summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorblaise <blaise@3ad0048d-3df7-0310-abae-a5850022a9f2>2012-01-20 16:59:47 +0000
committerblaise <blaise@3ad0048d-3df7-0310-abae-a5850022a9f2>2012-01-20 16:59:47 +0000
commit350adcb4b28481f4ae121a996c9f43dc019da18b (patch)
tree7706bc04e2d90f0667dc7131e8d510d7d6faea12
parent3b26cada0c5d0710b95d3603e9f59cea429f7b79 (diff)
downloadfpc-350adcb4b28481f4ae121a996c9f43dc019da18b.tar.gz
starting from r20123
git-svn-id: http://svn.freepascal.org/svn/fpc/branches/blaise@20126 3ad0048d-3df7-0310-abae-a5850022a9f2
-rw-r--r--closures/compiler/COPYING.txt340
-rw-r--r--closures/compiler/MPWMake1
-rw-r--r--closures/compiler/Makefile3596
-rw-r--r--closures/compiler/Makefile.fpc789
-rw-r--r--closures/compiler/README.txt63
-rw-r--r--closures/compiler/aasmbase.pas435
-rw-r--r--closures/compiler/aasmdata.pas525
-rw-r--r--closures/compiler/aasmsym.pas71
-rw-r--r--closures/compiler/aasmtai.pas2654
-rw-r--r--closures/compiler/aggas.pas1636
-rw-r--r--closures/compiler/alpha/aasmcpu.pas281
-rw-r--r--closures/compiler/alpha/agaxpgas.pas126
-rw-r--r--closures/compiler/alpha/aoptcpu.pas38
-rw-r--r--closures/compiler/alpha/aoptcpub.pas115
-rw-r--r--closures/compiler/alpha/aoptcpuc.pas38
-rw-r--r--closures/compiler/alpha/aoptcpud.pas39
-rw-r--r--closures/compiler/alpha/cgcpu.pas167
-rw-r--r--closures/compiler/alpha/cpubase.pas430
-rw-r--r--closures/compiler/alpha/cpuinfo.pas68
-rw-r--r--closures/compiler/alpha/cpunode.pas54
-rw-r--r--closures/compiler/alpha/cpupara.pas290
-rw-r--r--closures/compiler/alpha/cpupi.pas43
-rw-r--r--closures/compiler/alpha/cputarg.pas51
-rw-r--r--closures/compiler/alpha/radirect.pas0
-rw-r--r--closures/compiler/alpha/rasm.pas65
-rw-r--r--closures/compiler/alpha/rgcpu.pas69
-rw-r--r--closures/compiler/alpha/tgcpu.pas42
-rw-r--r--closures/compiler/aopt.pas277
-rw-r--r--closures/compiler/aoptbase.pas242
-rw-r--r--closures/compiler/aoptcs.pas848
-rw-r--r--closures/compiler/aoptda.pas165
-rw-r--r--closures/compiler/aoptobj.pas1156
-rw-r--r--closures/compiler/arm/aasmcpu.pas2807
-rw-r--r--closures/compiler/arm/agarmgas.pas326
-rw-r--r--closures/compiler/arm/aoptcpu.pas343
-rw-r--r--closures/compiler/arm/aoptcpub.pas120
-rw-r--r--closures/compiler/arm/aoptcpuc.pas38
-rw-r--r--closures/compiler/arm/aoptcpud.pas40
-rw-r--r--closures/compiler/arm/armatt.inc208
-rw-r--r--closures/compiler/arm/armatts.inc208
-rw-r--r--closures/compiler/arm/armins.dat628
-rw-r--r--closures/compiler/arm/armnop.inc2
-rw-r--r--closures/compiler/arm/armop.inc208
-rw-r--r--closures/compiler/arm/armreg.dat108
-rw-r--r--closures/compiler/arm/armtab.inc745
-rw-r--r--closures/compiler/arm/cgcpu.pas3709
-rw-r--r--closures/compiler/arm/cpubase.pas581
-rw-r--r--closures/compiler/arm/cpuinfo.pas1034
-rw-r--r--closures/compiler/arm/cpunode.pas47
-rw-r--r--closures/compiler/arm/cpupara.pas592
-rw-r--r--closures/compiler/arm/cpupi.pas128
-rw-r--r--closures/compiler/arm/cputarg.pas93
-rw-r--r--closures/compiler/arm/itcpugas.pas93
-rw-r--r--closures/compiler/arm/narmadd.pas434
-rw-r--r--closures/compiler/arm/narmcal.pas74
-rw-r--r--closures/compiler/arm/narmcnv.pas343
-rw-r--r--closures/compiler/arm/narmcon.pas140
-rw-r--r--closures/compiler/arm/narminl.pas337
-rw-r--r--closures/compiler/arm/narmmat.pas357
-rw-r--r--closures/compiler/arm/narmset.pas256
-rw-r--r--closures/compiler/arm/pp.lpi.template90
-rw-r--r--closures/compiler/arm/raarm.pas56
-rw-r--r--closures/compiler/arm/raarmgas.pas1176
-rw-r--r--closures/compiler/arm/rarmcon.inc92
-rw-r--r--closures/compiler/arm/rarmdwa.inc92
-rw-r--r--closures/compiler/arm/rarmnor.inc2
-rw-r--r--closures/compiler/arm/rarmnum.inc92
-rw-r--r--closures/compiler/arm/rarmrni.inc92
-rw-r--r--closures/compiler/arm/rarmsri.inc92
-rw-r--r--closures/compiler/arm/rarmsta.inc92
-rw-r--r--closures/compiler/arm/rarmstd.inc92
-rw-r--r--closures/compiler/arm/rarmsup.inc92
-rw-r--r--closures/compiler/arm/rgcpu.pas404
-rw-r--r--closures/compiler/asmutils.pas131
-rw-r--r--closures/compiler/assemble.pas1669
-rw-r--r--closures/compiler/avr/aasmcpu.pas456
-rw-r--r--closures/compiler/avr/agavrgas.pas216
-rw-r--r--closures/compiler/avr/aoptcpu.pas100
-rw-r--r--closures/compiler/avr/aoptcpub.pas120
-rw-r--r--closures/compiler/avr/aoptcpud.pas40
-rw-r--r--closures/compiler/avr/avrreg.dat41
-rw-r--r--closures/compiler/avr/cgcpu.pas1752
-rw-r--r--closures/compiler/avr/cpubase.pas474
-rw-r--r--closures/compiler/avr/cpuinfo.pas226
-rw-r--r--closures/compiler/avr/cpunode.pas43
-rw-r--r--closures/compiler/avr/cpupara.pas527
-rw-r--r--closures/compiler/avr/cpupi.pas73
-rw-r--r--closures/compiler/avr/cputarg.pas70
-rw-r--r--closures/compiler/avr/itcpugas.pas101
-rw-r--r--closures/compiler/avr/navradd.pas251
-rw-r--r--closures/compiler/avr/navrcnv.pas59
-rw-r--r--closures/compiler/avr/navrmat.pas265
-rw-r--r--closures/compiler/avr/raavr.pas52
-rw-r--r--closures/compiler/avr/raavrgas.pas693
-rw-r--r--closures/compiler/avr/ravrcon.inc34
-rw-r--r--closures/compiler/avr/ravrdwa.inc34
-rw-r--r--closures/compiler/avr/ravrnor.inc2
-rw-r--r--closures/compiler/avr/ravrnum.inc34
-rw-r--r--closures/compiler/avr/ravrrni.inc34
-rw-r--r--closures/compiler/avr/ravrsri.inc34
-rw-r--r--closures/compiler/avr/ravrsta.inc34
-rw-r--r--closures/compiler/avr/ravrstd.inc34
-rw-r--r--closures/compiler/avr/ravrsup.inc34
-rw-r--r--closures/compiler/avr/rgcpu.pas169
-rw-r--r--closures/compiler/browcol.pas2291
-rw-r--r--closures/compiler/bsdcompile3
-rw-r--r--closures/compiler/catch.pas87
-rw-r--r--closures/compiler/ccharset.pas294
-rw-r--r--closures/compiler/cclasses.pas3035
-rw-r--r--closures/compiler/cfidwarf.pas429
-rw-r--r--closures/compiler/cfileutl.pas1301
-rw-r--r--closures/compiler/cg64f32.pas971
-rw-r--r--closures/compiler/cgbase.pas693
-rw-r--r--closures/compiler/cgobj.pas4395
-rw-r--r--closures/compiler/cgutils.pas248
-rw-r--r--closures/compiler/cmsgs.pas475
-rw-r--r--closures/compiler/comphook.pas408
-rw-r--r--closures/compiler/compiler.pas372
-rw-r--r--closures/compiler/compinnr.inc128
-rw-r--r--closures/compiler/comprsrc.pas523
-rw-r--r--closures/compiler/constexp.pas585
-rw-r--r--closures/compiler/cp1251.pas282
-rw-r--r--closures/compiler/cp1252.pp282
-rw-r--r--closures/compiler/cp437.pas282
-rw-r--r--closures/compiler/cp850.pas282
-rw-r--r--closures/compiler/cp866.pas282
-rw-r--r--closures/compiler/cp8859_1.pas282
-rw-r--r--closures/compiler/cp8859_5.pas282
-rw-r--r--closures/compiler/cpid.pas191
-rw-r--r--closures/compiler/crefs.pas65
-rw-r--r--closures/compiler/cresstr.pas323
-rw-r--r--closures/compiler/cstreams.pas641
-rw-r--r--closures/compiler/cutils.pas1363
-rw-r--r--closures/compiler/cwindirs.pp123
-rw-r--r--closures/compiler/dbgbase.pas626
-rw-r--r--closures/compiler/dbgdwarf.pas4139
-rw-r--r--closures/compiler/dbgstabs.pas1732
-rw-r--r--closures/compiler/defcmp.pas1942
-rw-r--r--closures/compiler/defutil.pas1164
-rw-r--r--closures/compiler/export.pas269
-rw-r--r--closures/compiler/expunix.pas189
-rw-r--r--closures/compiler/finput.pas726
-rw-r--r--closures/compiler/fmodule.pas1017
-rw-r--r--closures/compiler/fpccrc.pas76
-rw-r--r--closures/compiler/fpcdefs.inc179
-rw-r--r--closures/compiler/fppu.pas1732
-rw-r--r--closures/compiler/gendef.pas163
-rw-r--r--closures/compiler/generic/cpuinfo.pas51
-rw-r--r--closures/compiler/globals.pas1549
-rw-r--r--closures/compiler/globtype.pas563
-rw-r--r--closures/compiler/html/i386/readme.txt5
-rw-r--r--closures/compiler/html/powerpc/readme.txt5
-rw-r--r--closures/compiler/htypechk.pas2968
-rw-r--r--closures/compiler/i386/aopt386.pas119
-rw-r--r--closures/compiler/i386/cgcpu.pas862
-rw-r--r--closures/compiler/i386/cpubase.inc147
-rw-r--r--closures/compiler/i386/cpuinfo.pas114
-rw-r--r--closures/compiler/i386/cpunode.pas60
-rw-r--r--closures/compiler/i386/cpupara.pas762
-rw-r--r--closures/compiler/i386/cpupi.pas103
-rw-r--r--closures/compiler/i386/cputarg.pas132
-rw-r--r--closures/compiler/i386/csopt386.pas2255
-rw-r--r--closures/compiler/i386/daopt386.pas2816
-rw-r--r--closures/compiler/i386/i386att.inc688
-rw-r--r--closures/compiler/i386/i386atts.inc688
-rw-r--r--closures/compiler/i386/i386int.inc688
-rw-r--r--closures/compiler/i386/i386nop.inc2
-rw-r--r--closures/compiler/i386/i386op.inc688
-rw-r--r--closures/compiler/i386/i386prop.inc688
-rw-r--r--closures/compiler/i386/i386tab.inc8438
-rw-r--r--closures/compiler/i386/n386add.pas448
-rw-r--r--closures/compiler/i386/n386cal.pas120
-rw-r--r--closures/compiler/i386/n386inl.pas42
-rw-r--r--closures/compiler/i386/n386mat.pas473
-rw-r--r--closures/compiler/i386/n386mem.pas98
-rw-r--r--closures/compiler/i386/n386set.pas73
-rw-r--r--closures/compiler/i386/popt386.pas2262
-rw-r--r--closures/compiler/i386/r386ari.inc73
-rw-r--r--closures/compiler/i386/r386att.inc73
-rw-r--r--closures/compiler/i386/r386con.inc73
-rw-r--r--closures/compiler/i386/r386dwrf.inc73
-rw-r--r--closures/compiler/i386/r386int.inc73
-rw-r--r--closures/compiler/i386/r386iri.inc73
-rw-r--r--closures/compiler/i386/r386nasm.inc73
-rw-r--r--closures/compiler/i386/r386nor.inc2
-rw-r--r--closures/compiler/i386/r386nri.inc73
-rw-r--r--closures/compiler/i386/r386num.inc73
-rw-r--r--closures/compiler/i386/r386op.inc73
-rw-r--r--closures/compiler/i386/r386ot.inc73
-rw-r--r--closures/compiler/i386/r386rni.inc73
-rw-r--r--closures/compiler/i386/r386sri.inc73
-rw-r--r--closures/compiler/i386/r386stab.inc73
-rw-r--r--closures/compiler/i386/r386std.inc73
-rw-r--r--closures/compiler/i386/ra386att.pas59
-rw-r--r--closures/compiler/i386/ra386int.pas74
-rw-r--r--closures/compiler/i386/rgcpu.pas71
-rw-r--r--closures/compiler/i386/rropt386.pas371
-rw-r--r--closures/compiler/ia64/aasmcpu.pas287
-rw-r--r--closures/compiler/ia64/cpubase.pas149
-rw-r--r--closures/compiler/ia64/cpuinfo.pas83
-rw-r--r--closures/compiler/ia64/ia64reg.dat268
-rw-r--r--closures/compiler/impdef.pas473
-rw-r--r--closures/compiler/import.pas130
-rw-r--r--closures/compiler/link.pas1398
-rw-r--r--closures/compiler/m68k/aasmcpu.pas579
-rw-r--r--closures/compiler/m68k/ag68kgas.pas385
-rw-r--r--closures/compiler/m68k/aoptcpu.pas41
-rw-r--r--closures/compiler/m68k/aoptcpub.pas120
-rw-r--r--closures/compiler/m68k/aoptcpud.pas36
-rw-r--r--closures/compiler/m68k/cgcpu.pas1751
-rw-r--r--closures/compiler/m68k/cpuasm.pas26
-rw-r--r--closures/compiler/m68k/cpubase.pas520
-rw-r--r--closures/compiler/m68k/cpuinfo.pas87
-rw-r--r--closures/compiler/m68k/cpunode.pas52
-rw-r--r--closures/compiler/m68k/cpupara.pas599
-rw-r--r--closures/compiler/m68k/cpupi.pas41
-rw-r--r--closures/compiler/m68k/cputarg.pas61
-rw-r--r--closures/compiler/m68k/itcpugas.pas138
-rw-r--r--closures/compiler/m68k/m68kreg.dat44
-rw-r--r--closures/compiler/m68k/n68kadd.pas546
-rw-r--r--closures/compiler/m68k/n68kcal.pas86
-rw-r--r--closures/compiler/m68k/n68kcnv.pas257
-rw-r--r--closures/compiler/m68k/n68kmat.pas361
-rw-r--r--closures/compiler/m68k/r68kcon.inc35
-rw-r--r--closures/compiler/m68k/r68kgas.inc35
-rw-r--r--closures/compiler/m68k/r68kgri.inc35
-rw-r--r--closures/compiler/m68k/r68knor.inc2
-rw-r--r--closures/compiler/m68k/r68knum.inc35
-rw-r--r--closures/compiler/m68k/r68krni.inc35
-rw-r--r--closures/compiler/m68k/r68ksri.inc35
-rw-r--r--closures/compiler/m68k/r68ksta.inc35
-rw-r--r--closures/compiler/m68k/r68kstd.inc35
-rw-r--r--closures/compiler/m68k/r68ksup.inc35
-rw-r--r--closures/compiler/m68k/ra68k.pas371
-rw-r--r--closures/compiler/m68k/ra68kmot.pas1835
-rw-r--r--closures/compiler/m68k/rgcpu.pas40
-rw-r--r--closures/compiler/macho.pas2103
-rw-r--r--closures/compiler/machoutils.pas1466
-rw-r--r--closures/compiler/mips/aasmcpu.pas449
-rw-r--r--closures/compiler/mips/aoptcpu.pas41
-rw-r--r--closures/compiler/mips/aoptcpub.pas119
-rw-r--r--closures/compiler/mips/aoptcpud.pas36
-rw-r--r--closures/compiler/mips/cgcpu.pas1980
-rw-r--r--closures/compiler/mips/cpubase.pas397
-rw-r--r--closures/compiler/mips/cpugas.pas265
-rw-r--r--closures/compiler/mips/cpuinfo.pas79
-rw-r--r--closures/compiler/mips/cpunode.pas41
-rw-r--r--closures/compiler/mips/cpupara.pas371
-rw-r--r--closures/compiler/mips/cpupi.pas76
-rw-r--r--closures/compiler/mips/cputarg.pas53
-rw-r--r--closures/compiler/mips/itcpugas.pas101
-rw-r--r--closures/compiler/mips/mipsreg.dat83
-rw-r--r--closures/compiler/mips/ncpuadd.pas598
-rw-r--r--closures/compiler/mips/ncpucall.pas62
-rw-r--r--closures/compiler/mips/ncpucnv.pas286
-rw-r--r--closures/compiler/mips/ncpuinln.pas138
-rw-r--r--closures/compiler/mips/ncpumat.pas302
-rw-r--r--closures/compiler/mips/ncpuset.pas130
-rw-r--r--closures/compiler/mips/opcode.inc241
-rw-r--r--closures/compiler/mips/rgcpu.pas165
-rw-r--r--closures/compiler/mips/rmipscon.inc75
-rw-r--r--closures/compiler/mips/rmipsdwf.inc75
-rw-r--r--closures/compiler/mips/rmipsgas.inc75
-rw-r--r--closures/compiler/mips/rmipsgri.inc75
-rw-r--r--closures/compiler/mips/rmipsgss.inc75
-rw-r--r--closures/compiler/mips/rmipsnor.inc2
-rw-r--r--closures/compiler/mips/rmipsnum.inc75
-rw-r--r--closures/compiler/mips/rmipsrni.inc75
-rw-r--r--closures/compiler/mips/rmipssri.inc75
-rw-r--r--closures/compiler/mips/rmipssta.inc75
-rw-r--r--closures/compiler/mips/rmipsstd.inc75
-rw-r--r--closures/compiler/mips/rmipssup.inc75
-rw-r--r--closures/compiler/mips/strinst.inc241
-rw-r--r--closures/compiler/msg/errorct.msg2357
-rw-r--r--closures/compiler/msg/errord.msg3417
-rw-r--r--closures/compiler/msg/errorda.msg2501
-rw-r--r--closures/compiler/msg/errordu.msg3418
-rw-r--r--closures/compiler/msg/errore.msg3445
-rw-r--r--closures/compiler/msg/errores.msg2375
-rw-r--r--closures/compiler/msg/errorf.msg1899
-rw-r--r--closures/compiler/msg/errorfi.msg2517
-rw-r--r--closures/compiler/msg/errorhe.msg2708
-rw-r--r--closures/compiler/msg/errorheu.msg2708
-rw-r--r--closures/compiler/msg/errorid.msg2715
-rw-r--r--closures/compiler/msg/erroriu.msg3048
-rw-r--r--closures/compiler/msg/errorn.msg2372
-rw-r--r--closures/compiler/msg/errorpl.msg2385
-rw-r--r--closures/compiler/msg/errorpli.msg2385
-rw-r--r--closures/compiler/msg/errorpt.msg3447
-rw-r--r--closures/compiler/msg/errorptu.msg3447
-rw-r--r--closures/compiler/msg/errorr.msg2832
-rw-r--r--closures/compiler/msg/errorru.msg2832
-rw-r--r--closures/compiler/msg/errorues.msg2369
-rw-r--r--closures/compiler/msgidx.inc926
-rw-r--r--closures/compiler/msgtxt.inc1453
-rw-r--r--closures/compiler/nadd.pas3070
-rw-r--r--closures/compiler/nbas.pas1130
-rw-r--r--closures/compiler/ncal.pas3888
-rw-r--r--closures/compiler/ncgadd.pas854
-rw-r--r--closures/compiler/ncgbas.pas558
-rw-r--r--closures/compiler/ncgcal.pas976
-rw-r--r--closures/compiler/ncgcnv.pas760
-rw-r--r--closures/compiler/ncgcon.pas493
-rw-r--r--closures/compiler/ncgflw.pas1662
-rw-r--r--closures/compiler/ncginl.pas835
-rw-r--r--closures/compiler/ncgld.pas1286
-rw-r--r--closures/compiler/ncgmat.pas519
-rw-r--r--closures/compiler/ncgmem.pas1005
-rw-r--r--closures/compiler/ncgobjc.pas102
-rw-r--r--closures/compiler/ncgopt.pas188
-rw-r--r--closures/compiler/ncgrtti.pas1244
-rw-r--r--closures/compiler/ncgset.pas879
-rw-r--r--closures/compiler/ncgutil.pas3252
-rw-r--r--closures/compiler/ncnv.pas3703
-rw-r--r--closures/compiler/ncon.pas1314
-rw-r--r--closures/compiler/nflw.pas2144
-rw-r--r--closures/compiler/ninl.pas3375
-rw-r--r--closures/compiler/nld.pas1269
-rw-r--r--closures/compiler/nmat.pas1131
-rw-r--r--closures/compiler/nmem.pas1099
-rw-r--r--closures/compiler/nobj.pas1593
-rw-r--r--closures/compiler/nobjc.pas169
-rw-r--r--closures/compiler/node.pas1301
-rw-r--r--closures/compiler/nopt.pas394
-rw-r--r--closures/compiler/nset.pas1015
-rw-r--r--closures/compiler/nstate.pas123
-rw-r--r--closures/compiler/nutils.pas1222
-rw-r--r--closures/compiler/objcdef.pas653
-rw-r--r--closures/compiler/objcgutl.pas1625
-rw-r--r--closures/compiler/objcutil.pas291
-rw-r--r--closures/compiler/ogbase.pas2862
-rw-r--r--closures/compiler/ogcoff.pas3158
-rw-r--r--closures/compiler/ogelf.pas1318
-rw-r--r--closures/compiler/oglx.pas394
-rw-r--r--closures/compiler/ogmacho.pas1223
-rw-r--r--closures/compiler/ogmap.pas162
-rw-r--r--closures/compiler/ognlm.pas1521
-rw-r--r--closures/compiler/optbase.pas216
-rw-r--r--closures/compiler/optcse.pas335
-rw-r--r--closures/compiler/optdead.pas424
-rw-r--r--closures/compiler/optdfa.pas616
-rw-r--r--closures/compiler/options.pas2958
-rw-r--r--closures/compiler/optloop.pas487
-rw-r--r--closures/compiler/opttail.pas212
-rw-r--r--closures/compiler/optutils.pas327
-rw-r--r--closures/compiler/optvirt.pas1181
-rw-r--r--closures/compiler/owar.pas522
-rw-r--r--closures/compiler/owbase.pas304
-rw-r--r--closures/compiler/parabase.pas372
-rw-r--r--closures/compiler/paramgr.pas484
-rw-r--r--closures/compiler/parser.pas529
-rw-r--r--closures/compiler/pass_1.pas253
-rw-r--r--closures/compiler/pass_2.pas234
-rw-r--r--closures/compiler/pbase.pas379
-rw-r--r--closures/compiler/pdecl.pas874
-rw-r--r--closures/compiler/pdecobj.pas1281
-rw-r--r--closures/compiler/pdecsub.pas3388
-rw-r--r--closures/compiler/pdecvar.pas1864
-rw-r--r--closures/compiler/pexports.pas249
-rw-r--r--closures/compiler/pexpr.pas3430
-rw-r--r--closures/compiler/pgenutil.pas558
-rw-r--r--closures/compiler/pinline.pas784
-rw-r--r--closures/compiler/pmodules.pas2523
-rw-r--r--closures/compiler/powerpc/agppcmpw.pas1248
-rw-r--r--closures/compiler/powerpc/agppcvasm.pas406
-rw-r--r--closures/compiler/powerpc/aoptcpu.pas535
-rw-r--r--closures/compiler/powerpc/aoptcpub.pas121
-rw-r--r--closures/compiler/powerpc/aoptcpuc.pas40
-rw-r--r--closures/compiler/powerpc/aoptcpud.pas40
-rw-r--r--closures/compiler/powerpc/cgcpu.pas1820
-rw-r--r--closures/compiler/powerpc/cpubase.pas575
-rw-r--r--closures/compiler/powerpc/cpuinfo.pas88
-rw-r--r--closures/compiler/powerpc/cpunode.pas51
-rw-r--r--closures/compiler/powerpc/cpupara.pas709
-rw-r--r--closures/compiler/powerpc/cpupi.pas207
-rw-r--r--closures/compiler/powerpc/cputarg.pas99
-rw-r--r--closures/compiler/powerpc/itcpugas.pas151
-rw-r--r--closures/compiler/powerpc/nppcadd.pas965
-rw-r--r--closures/compiler/powerpc/nppccal.pas147
-rw-r--r--closures/compiler/powerpc/nppccnv.pas231
-rw-r--r--closures/compiler/powerpc/nppcmat.pas721
-rw-r--r--closures/compiler/powerpc/ppcins.dat68
-rw-r--r--closures/compiler/powerpc/ppcreg.dat120
-rw-r--r--closures/compiler/powerpc/rappc.pas41
-rw-r--r--closures/compiler/powerpc/rappcgas.pas799
-rw-r--r--closures/compiler/powerpc/rppccon.inc111
-rw-r--r--closures/compiler/powerpc/rppcdwrf.inc111
-rw-r--r--closures/compiler/powerpc/rppcgas.inc111
-rw-r--r--closures/compiler/powerpc/rppcgri.inc111
-rw-r--r--closures/compiler/powerpc/rppcgss.inc111
-rw-r--r--closures/compiler/powerpc/rppcmot.inc111
-rw-r--r--closures/compiler/powerpc/rppcmri.inc111
-rw-r--r--closures/compiler/powerpc/rppcnor.inc2
-rw-r--r--closures/compiler/powerpc/rppcnum.inc111
-rw-r--r--closures/compiler/powerpc/rppcrni.inc111
-rw-r--r--closures/compiler/powerpc/rppcsri.inc111
-rw-r--r--closures/compiler/powerpc/rppcstab.inc111
-rw-r--r--closures/compiler/powerpc/rppcstd.inc111
-rw-r--r--closures/compiler/powerpc/rppcsup.inc111
-rw-r--r--closures/compiler/powerpc64/aoptcpu.pas41
-rw-r--r--closures/compiler/powerpc64/aoptcpub.pas123
-rw-r--r--closures/compiler/powerpc64/aoptcpuc.pas40
-rw-r--r--closures/compiler/powerpc64/aoptcpud.pas40
-rw-r--r--closures/compiler/powerpc64/cgcpu.pas2199
-rw-r--r--closures/compiler/powerpc64/cpubase.pas572
-rw-r--r--closures/compiler/powerpc64/cpuinfo.pas82
-rw-r--r--closures/compiler/powerpc64/cpunode.pas52
-rw-r--r--closures/compiler/powerpc64/cpupara.pas526
-rw-r--r--closures/compiler/powerpc64/cpupi.pas130
-rw-r--r--closures/compiler/powerpc64/cputarg.pas83
-rw-r--r--closures/compiler/powerpc64/itcpugas.pas160
-rw-r--r--closures/compiler/powerpc64/nppcadd.pas360
-rw-r--r--closures/compiler/powerpc64/nppccal.pas63
-rw-r--r--closures/compiler/powerpc64/nppccnv.pas235
-rw-r--r--closures/compiler/powerpc64/nppcld.pas62
-rw-r--r--closures/compiler/powerpc64/nppcmat.pas446
-rw-r--r--closures/compiler/powerpc64/ppcins.dat75
-rw-r--r--closures/compiler/powerpc64/ppcreg.dat143
-rw-r--r--closures/compiler/powerpc64/rappc.pas42
-rw-r--r--closures/compiler/powerpc64/rappcgas.pas799
-rw-r--r--closures/compiler/powerpc64/rppccon.inc111
-rw-r--r--closures/compiler/powerpc64/rppcdwrf.inc111
-rw-r--r--closures/compiler/powerpc64/rppcgas.inc111
-rw-r--r--closures/compiler/powerpc64/rppcgri.inc111
-rw-r--r--closures/compiler/powerpc64/rppcgss.inc111
-rw-r--r--closures/compiler/powerpc64/rppcmot.inc111
-rw-r--r--closures/compiler/powerpc64/rppcmri.inc111
-rw-r--r--closures/compiler/powerpc64/rppcnor.inc2
-rw-r--r--closures/compiler/powerpc64/rppcnum.inc111
-rw-r--r--closures/compiler/powerpc64/rppcrni.inc111
-rw-r--r--closures/compiler/powerpc64/rppcsri.inc111
-rw-r--r--closures/compiler/powerpc64/rppcstab.inc111
-rw-r--r--closures/compiler/powerpc64/rppcstd.inc111
-rw-r--r--closures/compiler/powerpc64/rppcsup.inc111
-rw-r--r--closures/compiler/pp.lpi86
-rw-r--r--closures/compiler/pp.pas229
-rw-r--r--closures/compiler/ppc.cfg40
-rw-r--r--closures/compiler/ppc.conf39
-rw-r--r--closures/compiler/ppc.dof95
-rw-r--r--closures/compiler/ppc68k.lpi79
-rw-r--r--closures/compiler/ppcarm.lpi93
-rw-r--r--closures/compiler/ppcavr.lpi84
-rw-r--r--closures/compiler/ppcgen/aasmcpu.pas602
-rw-r--r--closures/compiler/ppcgen/agppcgas.pas456
-rw-r--r--closures/compiler/ppcgen/cgppc.pas962
-rw-r--r--closures/compiler/ppcgen/ngppcadd.pas543
-rw-r--r--closures/compiler/ppcgen/ngppccnv.pas208
-rw-r--r--closures/compiler/ppcgen/ngppcinl.pas237
-rw-r--r--closures/compiler/ppcgen/ngppcset.pas243
-rw-r--r--closures/compiler/ppcgen/rgcpu.pas200
-rw-r--r--closures/compiler/ppcmipsel.lpi95
-rw-r--r--closures/compiler/ppcppc.lpi79
-rw-r--r--closures/compiler/ppcsparc.lpi79
-rw-r--r--closures/compiler/ppheap.pas147
-rw-r--r--closures/compiler/ppu.pas1373
-rw-r--r--closures/compiler/ppx86_64.lpi82
-rw-r--r--closures/compiler/procinfo.pas292
-rw-r--r--closures/compiler/pstatmnt.pas1397
-rw-r--r--closures/compiler/psub.pas2073
-rw-r--r--closures/compiler/psystem.pas625
-rw-r--r--closures/compiler/ptconst.pas1570
-rw-r--r--closures/compiler/ptype.pas1590
-rw-r--r--closures/compiler/raatt.pas1645
-rw-r--r--closures/compiler/rabase.pas107
-rw-r--r--closures/compiler/rasm.pas68
-rw-r--r--closures/compiler/rautils.pas1640
-rw-r--r--closures/compiler/regvars.pas666
-rw-r--r--closures/compiler/rescmn.pas59
-rw-r--r--closures/compiler/rgbase.pas80
-rw-r--r--closures/compiler/rgobj.pas2162
-rw-r--r--closures/compiler/scandir.pas1542
-rw-r--r--closures/compiler/scanner.pas4734
-rw-r--r--closures/compiler/script.pas526
-rw-r--r--closures/compiler/sparc/aasmcpu.pas318
-rw-r--r--closures/compiler/sparc/aoptcpu.pas41
-rw-r--r--closures/compiler/sparc/aoptcpub.pas120
-rw-r--r--closures/compiler/sparc/aoptcpud.pas36
-rw-r--r--closures/compiler/sparc/cgcpu.pas1598
-rw-r--r--closures/compiler/sparc/cpubase.pas455
-rw-r--r--closures/compiler/sparc/cpugas.pas237
-rw-r--r--closures/compiler/sparc/cpuinfo.pas89
-rw-r--r--closures/compiler/sparc/cpunode.pas38
-rw-r--r--closures/compiler/sparc/cpupara.pas357
-rw-r--r--closures/compiler/sparc/cpupi.pas76
-rw-r--r--closures/compiler/sparc/cputarg.pas76
-rw-r--r--closures/compiler/sparc/itcpugas.pas98
-rw-r--r--closures/compiler/sparc/ncpuadd.pas376
-rw-r--r--closures/compiler/sparc/ncpucall.pas56
-rw-r--r--closures/compiler/sparc/ncpucnv.pas336
-rw-r--r--closures/compiler/sparc/ncpuinln.pas143
-rw-r--r--closures/compiler/sparc/ncpumat.pas332
-rw-r--r--closures/compiler/sparc/ncpuset.pas126
-rw-r--r--closures/compiler/sparc/opcode.inc75
-rw-r--r--closures/compiler/sparc/racpu.pas54
-rw-r--r--closures/compiler/sparc/racpugas.pas688
-rw-r--r--closures/compiler/sparc/rgcpu.pas164
-rw-r--r--closures/compiler/sparc/rspcon.inc140
-rw-r--r--closures/compiler/sparc/rspdwrf.inc140
-rw-r--r--closures/compiler/sparc/rspnor.inc2
-rw-r--r--closures/compiler/sparc/rspnum.inc140
-rw-r--r--closures/compiler/sparc/rsprni.inc140
-rw-r--r--closures/compiler/sparc/rspsri.inc140
-rw-r--r--closures/compiler/sparc/rspstab.inc140
-rw-r--r--closures/compiler/sparc/rspstd.inc140
-rw-r--r--closures/compiler/sparc/rspsup.inc140
-rw-r--r--closures/compiler/sparc/spreg.dat173
-rw-r--r--closures/compiler/sparc/strinst.inc72
-rw-r--r--closures/compiler/switches.pas369
-rw-r--r--closures/compiler/symbase.pas441
-rw-r--r--closures/compiler/symconst.pas660
-rw-r--r--closures/compiler/symdef.pas5947
-rw-r--r--closures/compiler/symnot.pas63
-rw-r--r--closures/compiler/symsym.pas2109
-rw-r--r--closures/compiler/symtable.pas3217
-rw-r--r--closures/compiler/symtype.pas1034
-rw-r--r--closures/compiler/symutil.pas97
-rw-r--r--closures/compiler/systems.inc216
-rw-r--r--closures/compiler/systems.pas872
-rw-r--r--closures/compiler/systems/i_amiga.pas167
-rw-r--r--closures/compiler/systems/i_atari.pas91
-rw-r--r--closures/compiler/systems/i_beos.pas114
-rw-r--r--closures/compiler/systems/i_bsd.pas858
-rw-r--r--closures/compiler/systems/i_embed.pas235
-rw-r--r--closures/compiler/systems/i_emx.pas118
-rw-r--r--closures/compiler/systems/i_gba.pas102
-rw-r--r--closures/compiler/systems/i_go32v2.pas101
-rw-r--r--closures/compiler/systems/i_haiku.pas113
-rw-r--r--closures/compiler/systems/i_linux.pas909
-rw-r--r--closures/compiler/systems/i_macos.pas100
-rw-r--r--closures/compiler/systems/i_morph.pas101
-rw-r--r--closures/compiler/systems/i_nativent.pas106
-rw-r--r--closures/compiler/systems/i_nds.pas102
-rw-r--r--closures/compiler/systems/i_nwl.pas101
-rw-r--r--closures/compiler/systems/i_nwm.pas101
-rw-r--r--closures/compiler/systems/i_os2.pas118
-rw-r--r--closures/compiler/systems/i_palmos.pas189
-rw-r--r--closures/compiler/systems/i_sunos.pas245
-rw-r--r--closures/compiler/systems/i_symbian.pas174
-rw-r--r--closures/compiler/systems/i_watcom.pas101
-rw-r--r--closures/compiler/systems/i_wdosx.pas103
-rw-r--r--closures/compiler/systems/i_wii.pas101
-rw-r--r--closures/compiler/systems/i_win.pas320
-rw-r--r--closures/compiler/systems/mac_crea.txt71
-rw-r--r--closures/compiler/systems/t_amiga.pas273
-rw-r--r--closures/compiler/systems/t_atari.pas43
-rw-r--r--closures/compiler/systems/t_beos.pas500
-rw-r--r--closures/compiler/systems/t_bsd.pas855
-rw-r--r--closures/compiler/systems/t_embed.pas910
-rw-r--r--closures/compiler/systems/t_emx.pas531
-rw-r--r--closures/compiler/systems/t_gba.pas632
-rw-r--r--closures/compiler/systems/t_go32v2.pas407
-rw-r--r--closures/compiler/systems/t_haiku.pas500
-rw-r--r--closures/compiler/systems/t_linux.pas1188
-rw-r--r--closures/compiler/systems/t_macos.pas255
-rw-r--r--closures/compiler/systems/t_morph.pas260
-rw-r--r--closures/compiler/systems/t_nativent.pas94
-rw-r--r--closures/compiler/systems/t_nds.pas780
-rw-r--r--closures/compiler/systems/t_nwl.pas631
-rw-r--r--closures/compiler/systems/t_nwm.pas988
-rw-r--r--closures/compiler/systems/t_os2.pas556
-rw-r--r--closures/compiler/systems/t_palmos.pas218
-rw-r--r--closures/compiler/systems/t_sunos.pas666
-rw-r--r--closures/compiler/systems/t_symbian.pas199
-rw-r--r--closures/compiler/systems/t_watcom.pas179
-rw-r--r--closures/compiler/systems/t_wdosx.pas84
-rw-r--r--closures/compiler/systems/t_wii.pas597
-rw-r--r--closures/compiler/systems/t_win.pas1882
-rw-r--r--closures/compiler/tgobj.pas663
-rw-r--r--closures/compiler/tokens.pas651
-rw-r--r--closures/compiler/utils/Makefile2469
-rw-r--r--closures/compiler/utils/Makefile.fpc93
-rw-r--r--closures/compiler/utils/README.txt20
-rw-r--r--closures/compiler/utils/dummyas.pp112
-rw-r--r--closures/compiler/utils/fixlog.pp174
-rw-r--r--closures/compiler/utils/fixmsg.pp66
-rw-r--r--closures/compiler/utils/fixnasm.pp76
-rw-r--r--closures/compiler/utils/fixtab.pp367
-rw-r--r--closures/compiler/utils/fpc.mpw2
-rw-r--r--closures/compiler/utils/fpc.pp267
-rw-r--r--closures/compiler/utils/fpcsubst.pp243
-rw-r--r--closures/compiler/utils/fpimpdef.pp92
-rw-r--r--closures/compiler/utils/gia64reg.pp14
-rw-r--r--closures/compiler/utils/gppc386.pp195
-rw-r--r--closures/compiler/utils/mk68kreg.pp308
-rw-r--r--closures/compiler/utils/mkarmins.pp404
-rw-r--r--closures/compiler/utils/mkarmreg.pp276
-rw-r--r--closures/compiler/utils/mkavrreg.pp272
-rw-r--r--closures/compiler/utils/mkmpsreg.pp318
-rw-r--r--closures/compiler/utils/mkppcreg.pp370
-rw-r--r--closures/compiler/utils/mkspreg.pp275
-rw-r--r--closures/compiler/utils/mkx86ins.pp442
-rw-r--r--closures/compiler/utils/mkx86reg.pp443
-rw-r--r--closures/compiler/utils/msg2inc.pp823
-rw-r--r--closures/compiler/utils/msgdif.pp529
-rw-r--r--closures/compiler/utils/msgused.pl42
-rw-r--r--closures/compiler/utils/ppudump.pp3034
-rw-r--r--closures/compiler/utils/ppufiles.pp246
-rw-r--r--closures/compiler/utils/ppumove.pp651
-rw-r--r--closures/compiler/utils/samplecfg101
-rw-r--r--closures/compiler/utils/usubst.pp109
-rw-r--r--closures/compiler/verbose.pas987
-rw-r--r--closures/compiler/version.pas96
-rw-r--r--closures/compiler/vis/aasmcpu.pas248
-rw-r--r--closures/compiler/vis/cpubase.pas608
-rw-r--r--closures/compiler/vis/cpuinfo.pas56
-rw-r--r--closures/compiler/vis/cpunode.pas47
-rw-r--r--closures/compiler/vis/cpupara.pas74
-rw-r--r--closures/compiler/widestr.pas326
-rw-r--r--closures/compiler/wpo.pas79
-rw-r--r--closures/compiler/wpobase.pas829
-rw-r--r--closures/compiler/wpoinfo.pas329
-rw-r--r--closures/compiler/x86/aasmcpu.pas2626
-rw-r--r--closures/compiler/x86/agx86att.pas437
-rw-r--r--closures/compiler/x86/agx86int.pas1018
-rw-r--r--closures/compiler/x86/agx86nsm.pas1145
-rw-r--r--closures/compiler/x86/cga.pas132
-rw-r--r--closures/compiler/x86/cgx86.pas2299
-rw-r--r--closures/compiler/x86/cpubase.pas511
-rw-r--r--closures/compiler/x86/itcpugas.pas167
-rw-r--r--closures/compiler/x86/itx86int.pas97
-rw-r--r--closures/compiler/x86/nx86add.pas1080
-rw-r--r--closures/compiler/x86/nx86cnv.pas378
-rw-r--r--closures/compiler/x86/nx86con.pas90
-rw-r--r--closures/compiler/x86/nx86inl.pas534
-rw-r--r--closures/compiler/x86/nx86mat.pas309
-rw-r--r--closures/compiler/x86/nx86mem.pas108
-rw-r--r--closures/compiler/x86/nx86set.pas649
-rw-r--r--closures/compiler/x86/rax86.pas782
-rw-r--r--closures/compiler/x86/rax86att.pas920
-rw-r--r--closures/compiler/x86/rax86int.pas2238
-rw-r--r--closures/compiler/x86/rgx86.pas413
-rw-r--r--closures/compiler/x86/x86ins.dat3439
-rw-r--r--closures/compiler/x86/x86reg.dat140
-rw-r--r--closures/compiler/x86_64/aoptcpu.pas41
-rw-r--r--closures/compiler/x86_64/aoptcpub.pas120
-rw-r--r--closures/compiler/x86_64/aoptcpud.pas36
-rw-r--r--closures/compiler/x86_64/cgcpu.pas368
-rw-r--r--closures/compiler/x86_64/cpubase.inc134
-rw-r--r--closures/compiler/x86_64/cpuinfo.pas103
-rw-r--r--closures/compiler/x86_64/cpunode.pas63
-rw-r--r--closures/compiler/x86_64/cpupara.pas1251
-rw-r--r--closures/compiler/x86_64/cpupi.pas166
-rw-r--r--closures/compiler/x86_64/cputarg.pas94
-rw-r--r--closures/compiler/x86_64/nx64add.pas126
-rw-r--r--closures/compiler/x86_64/nx64cal.pas82
-rw-r--r--closures/compiler/x86_64/nx64cnv.pas175
-rw-r--r--closures/compiler/x86_64/nx64flw.pas559
-rw-r--r--closures/compiler/x86_64/nx64inl.pas42
-rw-r--r--closures/compiler/x86_64/nx64mat.pas213
-rw-r--r--closures/compiler/x86_64/r8664ari.inc126
-rw-r--r--closures/compiler/x86_64/r8664att.inc126
-rw-r--r--closures/compiler/x86_64/r8664con.inc126
-rw-r--r--closures/compiler/x86_64/r8664dwrf.inc126
-rw-r--r--closures/compiler/x86_64/r8664int.inc126
-rw-r--r--closures/compiler/x86_64/r8664iri.inc126
-rw-r--r--closures/compiler/x86_64/r8664nor.inc2
-rw-r--r--closures/compiler/x86_64/r8664num.inc126
-rw-r--r--closures/compiler/x86_64/r8664op.inc126
-rw-r--r--closures/compiler/x86_64/r8664ot.inc126
-rw-r--r--closures/compiler/x86_64/r8664rni.inc126
-rw-r--r--closures/compiler/x86_64/r8664sri.inc126
-rw-r--r--closures/compiler/x86_64/r8664stab.inc126
-rw-r--r--closures/compiler/x86_64/r8664std.inc126
-rw-r--r--closures/compiler/x86_64/rax64att.pas243
-rw-r--r--closures/compiler/x86_64/rax64int.pas70
-rw-r--r--closures/compiler/x86_64/rgcpu.pas53
-rw-r--r--closures/compiler/x86_64/win64unw.pas408
-rw-r--r--closures/compiler/x86_64/x8664ats.inc688
-rw-r--r--closures/compiler/x86_64/x8664att.inc688
-rw-r--r--closures/compiler/x86_64/x8664int.inc688
-rw-r--r--closures/compiler/x86_64/x8664nop.inc2
-rw-r--r--closures/compiler/x86_64/x8664op.inc688
-rw-r--r--closures/compiler/x86_64/x8664pro.inc688
-rw-r--r--closures/compiler/x86_64/x8664tab.inc8508
674 files changed, 404058 insertions, 0 deletions
diff --git a/closures/compiler/COPYING.txt b/closures/compiler/COPYING.txt
new file mode 100644
index 0000000000..5b6e7c66c2
--- /dev/null
+++ b/closures/compiler/COPYING.txt
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/closures/compiler/MPWMake b/closures/compiler/MPWMake
new file mode 100644
index 0000000000..8591f382fc
--- /dev/null
+++ b/closures/compiler/MPWMake
@@ -0,0 +1 @@
+# Make file for MPW make. # To run it, use: # Make <target> -f MPWMake > Makeout ; Makeout # where <target> should be replaced with actual make target. ############################################# # TIPS (TODO move to Wiki or something # # Defined variables: No quoting # Command lines: quote paths, dont quote option strings, since # they might contain several options, which must be separated. # Recursive call to Make: # - give options as -d XXX="{XXX}" # - in same dir, remember to ensure to have different Makeout files, # e g Makeout2. # # NOTE Currently cycle is stopped after three rounds, no diff is checked. FPC = {FPCDIR}bin:ppcppc # Default language for the compiler (english): FPCLANG = e MSGFILE = :msg:error{FPCLANG}.msg msg2inc Ä :utils:msg2inc.pp {FPC} -FE: -WT :utils:msg2inc.pp # The msgtxt.inc only depends on the error?.msg file, not on msg2inc, # because that one will be new almost everytime msgtxt.inc Ä {MSGFILE} Make msg2inc -f MPWMake > Makeout3 ; Makeout3 msg2inc {MSGFILE} msg msg msg Ä msgtxt.inc compiler Ä msg Set Exit 0 NewFolder :powerpc:units: ³ Dev:Null NewFolder :powerpc:units:powerpc-macos: ³ Dev:Null Set Exit 1 "{FPC}" {OPT} "-Fu{RTLDIR}" -Fu:systems: -Fu:powerpc: -Fu:ppcgen -dGDB -dBROWSERLOG -dNOOPT ¶ -dpowerpc -WT -FE: -FU:powerpc:units:powerpc-macos: pp.pas Rename -y pp ppcppc clean Ä utils_clean Set Exit 0 Delete -y :powerpc:units:powerpc-macos Delete -y ppcppc oldfpc msg2inc Delete -y Å.xcoff Set Exit 1 cycleclean Ä Set Exit 0 Delete -y :powerpc:units:powerpc-macos Set Exit 1 install Ä If {FPCDIR} == '' Set -e FPCDIR `GetFileName -wd -m 'Select where to install the FreePascal folder'`FreePascal: Set -e Commands "{Commands},{FPCDIR}bin:" Echo "Set -e FPCDIR ¶'{FPCDIR}¶'" > "{MPW}Startup Items:FPC Startup" Echo 'Set -e Commands "{Commands},{FPCDIR}bin:"' >> "{MPW}Startup Items:FPC Startup" End Set Exit 0 NewFolder "{FPCDIR}" ³ Dev:Null NewFolder "{FPCDIR}bin:" ³ Dev:Null Set Exit 1 Duplicate -y :ppcppc :utils:ppudump :utils:ppufiles :utils:ppumove ¶ :utils:fpc "{FPCDIR}bin:" Echo "# Configuration file for Free Pascal for MPW" > "{FPCDIR}bin:fpc.cfg" Echo "-Fu¶'{FPCDIR}units:rtl:¶'" >> "{FPCDIR}bin:fpc.cfg" Echo "-l" >> "{FPCDIR}bin:fpc.cfg" Echo "-vi" >> "{FPCDIR}bin:fpc.cfg" cycle Ä Directory ::rtl:macos Make clean -f MPWMake > Makeout ; Makeout Make all -d FPC="{FPC}" -d OPT="{OPT}" -f MPWMake > Makeout ; Makeout Directory :::compiler Make clean -f MPWMake > Makeout2 ; Makeout2 Make compiler -d FPC="{FPC}" -d OPT="{OPT}" -d RTLDIR=::rtl:units:powerpc-macos -f MPWMake > Makeout2 ; Makeout2 # Echo '******************** SECOND ROUND *********************' Rename -y ppcppc oldfpc Directory ::rtl:macos Make clean -f MPWMake > Makeout ; Makeout Make all -d FPC=:::compiler:oldfpc -d OPT="{OPT}" -f MPWMake > Makeout ; Makeout Directory :::compiler Make cycleclean -f MPWMake > Makeout2 ; Makeout2 Make compiler -d FPC=oldfpc -d OPT="{OPT}" -d RTLDIR=::rtl:units:powerpc-macos -f MPWMake > Makeout2 ; Makeout2 # Echo '********************* THIRD ROUND *********************' Rename -y ppcppc oldfpc Directory ::rtl:macos Make clean -f MPWMake > Makeout ; Makeout Make all -d FPC=:::compiler:oldfpc -d OPT="{OPT}" -f MPWMake > Makeout ; Makeout Directory :::compiler Make cycleclean -f MPWMake > Makeout2 ; Makeout2 Make compiler -d FPC=oldfpc -d OPT="{OPT}" -d RTLDIR=::rtl:units:powerpc-macos -f MPWMake > Makeout2 ; Makeout2 # Make utils_clean -f MPWMake > Makeout2 ; Makeout2 Make utils_all -d FPC=::oldfpc -d OPT="{OPT}" -d RTLDIR=:::rtl:units:powerpc-macos -f MPWMake > Makeout2 ; Makeout2 utils_all Ä Directory :utils Set Exit 0 NewFolder :units: ³ Dev:Null NewFolder :units:powerpc-macos: ³ Dev:Null Set Exit 1 "{FPC}" {OPT} "-Fu{RTLDIR}" -FE: -FU:units:powerpc-macos -Fu:: -WT ppudump.pp "{FPC}" {OPT} "-Fu{RTLDIR}" -FE: -FU:units:powerpc-macos -Fu:: -WT ppufiles.pp "{FPC}" {OPT} "-Fu{RTLDIR}" -FE: -FU:units:powerpc-macos -Fu:: -WT ppumove.pp Duplicate -y fpc.mpw fpc Directory :: utils_clean Ä Directory :utils Set Exit 0 Delete -y :units:powerpc-macos Delete -y fpc ppudump ppufiles ppumove msg2inc Delete -y Å.xcoff Set Exit 1 Directory :: \ No newline at end of file
diff --git a/closures/compiler/Makefile b/closures/compiler/Makefile
new file mode 100644
index 0000000000..0226d078e1
--- /dev/null
+++ b/closures/compiler/Makefile
@@ -0,0 +1,3596 @@
+#
+# Don't edit, this file is generated by FPCMake Version 2.0.0 [2012/01/14]
+#
+default: all
+MAKEFILETARGETS=i386-linux i386-go32v2 i386-win32 i386-os2 i386-freebsd i386-beos i386-haiku i386-netbsd i386-solaris i386-qnx i386-netware i386-openbsd i386-wdosx i386-darwin i386-emx i386-watcom i386-netwlibc i386-wince i386-embedded i386-symbian i386-nativent i386-iphonesim m68k-linux m68k-freebsd m68k-netbsd m68k-amiga m68k-atari m68k-openbsd m68k-palmos m68k-embedded powerpc-linux powerpc-netbsd powerpc-amiga powerpc-macos powerpc-darwin powerpc-morphos powerpc-embedded powerpc-wii sparc-linux sparc-netbsd sparc-solaris sparc-embedded x86_64-linux x86_64-freebsd x86_64-solaris x86_64-darwin x86_64-win64 x86_64-embedded arm-linux arm-palmos arm-darwin arm-wince arm-gba arm-nds arm-embedded arm-symbian powerpc64-linux powerpc64-darwin powerpc64-embedded avr-embedded armeb-linux armeb-embedded mipsel-linux
+BSDs = freebsd netbsd openbsd darwin
+UNIXs = linux $(BSDs) solaris qnx haiku
+LIMIT83fs = go32v2 os2 emx watcom
+OSNeedsComspecToRunBatch = go32v2 watcom
+FORCE:
+.PHONY: FORCE
+override PATH:=$(patsubst %/,%,$(subst \,/,$(PATH)))
+ifneq ($(findstring darwin,$(OSTYPE)),)
+inUnix=1 #darwin
+SEARCHPATH:=$(filter-out .,$(subst :, ,$(PATH)))
+else
+ifeq ($(findstring ;,$(PATH)),)
+inUnix=1
+SEARCHPATH:=$(filter-out .,$(subst :, ,$(PATH)))
+else
+SEARCHPATH:=$(subst ;, ,$(PATH))
+endif
+endif
+SEARCHPATH+=$(patsubst %/,%,$(subst \,/,$(dir $(MAKE))))
+PWD:=$(strip $(wildcard $(addsuffix /pwd.exe,$(SEARCHPATH))))
+ifeq ($(PWD),)
+PWD:=$(strip $(wildcard $(addsuffix /pwd,$(SEARCHPATH))))
+ifeq ($(PWD),)
+$(error You need the GNU utils package to use this Makefile)
+else
+PWD:=$(firstword $(PWD))
+SRCEXEEXT=
+endif
+else
+PWD:=$(firstword $(PWD))
+SRCEXEEXT=.exe
+endif
+ifndef inUnix
+ifeq ($(OS),Windows_NT)
+inWinNT=1
+else
+ifdef OS2_SHELL
+inOS2=1
+endif
+endif
+else
+ifneq ($(findstring cygdrive,$(PATH)),)
+inCygWin=1
+endif
+endif
+ifdef inUnix
+SRCBATCHEXT=.sh
+else
+ifdef inOS2
+SRCBATCHEXT=.cmd
+else
+SRCBATCHEXT=.bat
+endif
+endif
+ifdef COMSPEC
+ifneq ($(findstring $(OS_SOURCE),$(OSNeedsComspecToRunBatch)),)
+ifndef RUNBATCH
+RUNBATCH=$(COMSPEC) /C
+endif
+endif
+endif
+ifdef inUnix
+PATHSEP=/
+else
+PATHSEP:=$(subst /,\,/)
+ifdef inCygWin
+PATHSEP=/
+endif
+endif
+ifdef PWD
+BASEDIR:=$(subst \,/,$(shell $(PWD)))
+ifdef inCygWin
+ifneq ($(findstring /cygdrive/,$(BASEDIR)),)
+BASENODIR:=$(patsubst /cygdrive%,%,$(BASEDIR))
+BASEDRIVE:=$(firstword $(subst /, ,$(BASENODIR)))
+BASEDIR:=$(subst /cygdrive/$(BASEDRIVE)/,$(BASEDRIVE):/,$(BASEDIR))
+endif
+endif
+else
+BASEDIR=.
+endif
+ifdef inOS2
+ifndef ECHO
+ECHO:=$(strip $(wildcard $(addsuffix /gecho$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(ECHO),)
+ECHO:=$(strip $(wildcard $(addsuffix /echo$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(ECHO),)
+ECHO=echo
+else
+ECHO:=$(firstword $(ECHO))
+endif
+else
+ECHO:=$(firstword $(ECHO))
+endif
+endif
+export ECHO
+endif
+override DEFAULT_FPCDIR=..
+ifndef FPC
+ifdef PP
+FPC=$(PP)
+endif
+endif
+ifndef FPC
+FPCPROG:=$(strip $(wildcard $(addsuffix /fpc$(SRCEXEEXT),$(SEARCHPATH))))
+ifneq ($(FPCPROG),)
+FPCPROG:=$(firstword $(FPCPROG))
+ifneq ($(CPU_TARGET),)
+FPC:=$(shell $(FPCPROG) -P$(CPU_TARGET) -PB)
+else
+FPC:=$(shell $(FPCPROG) -PB)
+endif
+ifneq ($(findstring Error,$(FPC)),)
+override FPC=$(firstword $(strip $(wildcard $(addsuffix /ppc386$(SRCEXEEXT),$(SEARCHPATH)))))
+else
+ifeq ($(strip $(wildcard $(FPC))),)
+FPC:=$(firstword $(FPCPROG))
+endif
+endif
+else
+override FPC=$(firstword $(strip $(wildcard $(addsuffix /ppc386$(SRCEXEEXT),$(SEARCHPATH)))))
+endif
+endif
+override FPC:=$(subst $(SRCEXEEXT),,$(FPC))
+override FPC:=$(subst \,/,$(FPC))$(SRCEXEEXT)
+FOUNDFPC:=$(strip $(wildcard $(FPC)))
+ifeq ($(FOUNDFPC),)
+FOUNDFPC=$(strip $(wildcard $(addsuffix /$(FPC),$(SEARCHPATH))))
+ifeq ($(FOUNDFPC),)
+$(error Compiler $(FPC) not found)
+endif
+endif
+ifndef FPC_COMPILERINFO
+FPC_COMPILERINFO:=$(shell $(FPC) -iVSPTPSOTO)
+endif
+ifndef FPC_VERSION
+FPC_VERSION:=$(word 1,$(FPC_COMPILERINFO))
+endif
+export FPC FPC_VERSION FPC_COMPILERINFO
+unexport CHECKDEPEND ALLDEPENDENCIES
+ifndef CPU_TARGET
+ifdef CPU_TARGET_DEFAULT
+CPU_TARGET=$(CPU_TARGET_DEFAULT)
+endif
+endif
+ifndef OS_TARGET
+ifdef OS_TARGET_DEFAULT
+OS_TARGET=$(OS_TARGET_DEFAULT)
+endif
+endif
+ifndef CPU_SOURCE
+CPU_SOURCE:=$(word 2,$(FPC_COMPILERINFO))
+endif
+ifndef CPU_TARGET
+CPU_TARGET:=$(word 3,$(FPC_COMPILERINFO))
+endif
+ifndef OS_SOURCE
+OS_SOURCE:=$(word 4,$(FPC_COMPILERINFO))
+endif
+ifndef OS_TARGET
+OS_TARGET:=$(word 5,$(FPC_COMPILERINFO))
+endif
+FULL_TARGET=$(CPU_TARGET)-$(OS_TARGET)
+FULL_SOURCE=$(CPU_SOURCE)-$(OS_SOURCE)
+ifeq ($(CPU_TARGET),armeb)
+ARCH=arm
+override FPCOPT+=-Cb
+else
+ifeq ($(CPU_TARGET),armel)
+ARCH=arm
+override FPCOPT+=-CaEABI
+else
+ARCH=$(CPU_TARGET)
+endif
+endif
+ifeq ($(FULL_TARGET),arm-embedded)
+ifeq ($(SUBARCH),)
+$(error When compiling for arm-embedded, a sub-architecture (e.g. SUBARCH=armv4t or SUBARCH=armv7m) must be defined)
+endif
+override FPCOPT+=-Cp$(SUBARCH)
+endif
+ifneq ($(findstring $(OS_SOURCE),$(LIMIT83fs)),)
+TARGETSUFFIX=$(OS_TARGET)
+SOURCESUFFIX=$(OS_SOURCE)
+else
+ifneq ($(findstring $(OS_TARGET),$(LIMIT83fs)),)
+TARGETSUFFIX=$(OS_TARGET)
+else
+TARGETSUFFIX=$(FULL_TARGET)
+endif
+SOURCESUFFIX=$(FULL_SOURCE)
+endif
+ifneq ($(FULL_TARGET),$(FULL_SOURCE))
+CROSSCOMPILE=1
+endif
+ifeq ($(findstring makefile,$(MAKECMDGOALS)),)
+ifeq ($(findstring $(FULL_TARGET),$(MAKEFILETARGETS)),)
+$(error The Makefile doesn't support target $(FULL_TARGET), please run fpcmake first)
+endif
+endif
+ifneq ($(findstring $(OS_TARGET),$(BSDs)),)
+BSDhier=1
+endif
+ifeq ($(OS_TARGET),linux)
+linuxHier=1
+endif
+export OS_TARGET OS_SOURCE ARCH CPU_TARGET CPU_SOURCE FULL_TARGET FULL_SOURCE TARGETSUFFIX SOURCESUFFIX CROSSCOMPILE
+ifdef FPCDIR
+override FPCDIR:=$(subst \,/,$(FPCDIR))
+ifeq ($(wildcard $(addprefix $(FPCDIR)/,rtl units)),)
+override FPCDIR=wrong
+endif
+else
+override FPCDIR=wrong
+endif
+ifdef DEFAULT_FPCDIR
+ifeq ($(FPCDIR),wrong)
+override FPCDIR:=$(subst \,/,$(DEFAULT_FPCDIR))
+ifeq ($(wildcard $(addprefix $(FPCDIR)/,rtl units)),)
+override FPCDIR=wrong
+endif
+endif
+endif
+ifeq ($(FPCDIR),wrong)
+ifdef inUnix
+override FPCDIR=/usr/local/lib/fpc/$(FPC_VERSION)
+ifeq ($(wildcard $(FPCDIR)/units),)
+override FPCDIR=/usr/lib/fpc/$(FPC_VERSION)
+endif
+else
+override FPCDIR:=$(subst /$(FPC),,$(firstword $(strip $(wildcard $(addsuffix /$(FPC),$(SEARCHPATH))))))
+override FPCDIR:=$(FPCDIR)/..
+ifeq ($(wildcard $(addprefix $(FPCDIR)/,rtl units)),)
+override FPCDIR:=$(FPCDIR)/..
+ifeq ($(wildcard $(addprefix $(FPCDIR)/,rtl units)),)
+override FPCDIR:=$(BASEDIR)
+ifeq ($(wildcard $(addprefix $(FPCDIR)/,rtl units)),)
+override FPCDIR=c:/pp
+endif
+endif
+endif
+endif
+endif
+ifndef CROSSBINDIR
+CROSSBINDIR:=$(wildcard $(FPCDIR)/bin/$(TARGETSUFFIX))
+endif
+ifneq ($(findstring $(OS_TARGET),darwin iphonesim),)
+ifeq ($(OS_SOURCE),darwin)
+DARWIN2DARWIN=1
+endif
+endif
+ifndef BINUTILSPREFIX
+ifndef CROSSBINDIR
+ifdef CROSSCOMPILE
+ifndef DARWIN2DARWIN
+BINUTILSPREFIX=$(CPU_TARGET)-$(OS_TARGET)-
+endif
+endif
+endif
+endif
+UNITSDIR:=$(wildcard $(FPCDIR)/units/$(TARGETSUFFIX))
+ifeq ($(UNITSDIR),)
+UNITSDIR:=$(wildcard $(FPCDIR)/units/$(OS_TARGET))
+endif
+PACKAGESDIR:=$(wildcard $(FPCDIR) $(FPCDIR)/packages $(FPCDIR)/packages/base $(FPCDIR)/packages/extra)
+ifndef FPCFPMAKE
+ifdef CROSSCOMPILE
+ifeq ($(strip $(wildcard $(addsuffix /compiler/ppc$(SRCEXEEXT),$(FPCDIR)))),)
+FPCPROG:=$(strip $(wildcard $(addsuffix /fpc$(SRCEXEEXT),$(SEARCHPATH))))
+ifneq ($(FPCPROG),)
+FPCPROG:=$(firstword $(FPCPROG))
+FPCFPMAKE:=$(shell $(FPCPROG) -PB)
+ifeq ($(strip $(wildcard $(FPCFPMAKE))),)
+FPCFPMAKE:=$(firstword $(FPCPROG))
+endif
+else
+override FPCFPMAKE=$(firstword $(strip $(wildcard $(addsuffix /ppc386$(SRCEXEEXT),$(SEARCHPATH)))))
+endif
+else
+FPCFPMAKE=$(strip $(wildcard $(addsuffix /compiler/ppc$(SRCEXEEXT),$(FPCDIR))))
+FPMAKE_SKIP_CONFIG=-n
+export FPCFPMAKE
+export FPMAKE_SKIP_CONFIG
+endif
+else
+FPMAKE_SKIP_CONFIG=-n
+FPCFPMAKE=$(FPC)
+endif
+endif
+override PACKAGE_NAME=compiler
+override PACKAGE_VERSION=2.7.1
+unexport FPC_VERSION FPC_COMPILERINFO
+CYCLETARGETS=i386 powerpc sparc arm x86_64 powerpc64 m68k armeb mipsel mips avr
+ALLTARGETS=$(CYCLETARGETS)
+ifdef ALPHA
+PPC_TARGET=alpha
+endif
+ifdef POWERPC
+PPC_TARGET=powerpc
+endif
+ifdef POWERPC64
+PPC_TARGET=powerpc64
+endif
+ifdef SPARC
+PPC_TARGET=sparc
+endif
+ifdef M68K
+PPC_TARGET=m68k
+endif
+ifdef I386
+PPC_TARGET=i386
+endif
+ifdef X86_64
+PPC_TARGET=x86_64
+endif
+ifdef ARM
+PPC_TARGET=arm
+endif
+ifdef ARMEB
+PPC_TARGET=armeb
+endif
+ifdef MIPS
+PPC_TARGET=mips
+endif
+ifdef MIPSEL
+PPC_TARGET=mipsel
+endif
+ifdef AVR
+PPC_TARGET=avr
+endif
+ifndef PPC_TARGET
+PPC_TARGET=$(CPU_TARGET)
+endif
+ifeq ($(PPC_TARGET),armeb)
+CPC_TARGET=arm
+else
+CPC_TARGET=$(PPC_TARGET)
+endif
+ifndef PPC_OS
+PPC_OS=$(OS_TARGET)
+endif
+CPU_UNITDIR=$(CPC_TARGET)
+UTILSDIR=../utils
+COMPILERSOURCEDIR=$(CPC_TARGET) systems
+COMPILERUTILSDIR=utils
+ifndef FPCLANG
+FPCLANG=e
+endif
+ifndef LOCALOPT
+LOCALOPT:=$(OPT)
+endif
+ifndef RTLOPT
+RTLOPT:=$(OPT)
+endif
+override OPT=
+MSGFILES=$(wildcard msg/error*.msg)
+ifeq ($(CPC_TARGET),i386)
+CPUSUF=386
+endif
+ifeq ($(CPC_TARGET),alpha)
+CPUSUF=axp
+endif
+ifeq ($(CPC_TARGET),m68k)
+CPUSUF=68k
+endif
+ifeq ($(CPC_TARGET),powerpc)
+CPUSUF=ppc
+endif
+ifeq ($(CPC_TARGET),powerpc64)
+CPUSUF=ppc64
+endif
+ifeq ($(CPC_TARGET),sparc)
+CPUSUF=sparc
+endif
+ifeq ($(CPC_TARGET),x86_64)
+CPUSUF=x64
+endif
+ifeq ($(CPC_TARGET),arm)
+CPUSUF=arm
+endif
+ifeq ($(CPC_TARGET),mips)
+CPUSUF=mips
+endif
+ifeq ($(CPC_TARGET),mipsel)
+CPUSUF=mipsel
+endif
+ifeq ($(CPC_TARGET),avr)
+CPUSUF=avr
+endif
+NOCPUDEF=1
+MSGFILE=msg/error$(FPCLANG).msg
+SVNVERSION:=$(wildcard $(addsuffix /svnversion$(SRCEXEEXT),$(SEARCHPATH)))
+REVINC:=$(wildcard revision.inc)
+ifneq ($(REVINC),)
+override LOCALOPT+=-dREVINC
+ifeq ($(REVSTR),)
+ifneq ($(SVNVERSION),)
+REVSTR:=$(shell $(SVNVERSION) -c .)
+export REVSTR
+else
+ifeq ($(REVINC),force)
+REVSTR:=exported
+export REVSTR
+endif
+endif
+endif
+endif
+override LOCALOPT+=-d$(CPC_TARGET) -dGDB -dBROWSERLOG
+ifeq ($(PPC_TARGET),i386)
+override LOCALOPT+=-Fux86
+endif
+ifeq ($(PPC_TARGET),x86_64)
+override LOCALOPT+=-Fux86
+endif
+ifeq ($(PPC_TARGET),powerpc)
+override LOCALOPT+=-Fuppcgen
+endif
+ifeq ($(PPC_TARGET),powerpc64)
+override LOCALOPT+=-Fuppcgen
+endif
+ifeq ($(PPC_TARGET),m68k)
+override LOCALOPT+=-dNOOPT
+endif
+ifeq ($(PPC_TARGET),sparc)
+override LOCALOPT+=
+endif
+ifeq ($(PPC_TARGET),m68k)
+ifeq ($(OS_TARGET),amiga)
+override LOCALOPT+=-Ct
+endif
+endif
+ifeq ($(PPC_TARGET),arm)
+override LOCALOPT+=
+endif
+ifeq ($(PPC_TARGET),mipsel)
+override LOCALOPT+=-Fumips
+endif
+OPTWPOCOLLECT=-OWdevirtcalls,optvmts -FW$(BASEDIR)/pp1.wpo
+OPTWPOPERFORM=-Owdevirtcalls,optvmts -Fw$(BASEDIR)/pp1.wpo
+ifneq ($(findstring $(OS_TARGET),darwin linux freebsd solaris),)
+ifdef LINKSMART
+ifdef CREATESMART
+OPTWPOCOLLECT+=-OWsymbolliveness -Xs-
+OPTWPOPERFORM+=-Owsymbolliveness
+endif
+endif
+endif
+ifeq ($(FULL_TARGET),i386-linux)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),i386-go32v2)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),i386-win32)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),i386-os2)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),i386-freebsd)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),i386-beos)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),i386-haiku)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),i386-netbsd)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),i386-solaris)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),i386-qnx)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),i386-netware)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),i386-openbsd)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),i386-wdosx)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),i386-darwin)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),i386-emx)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),i386-watcom)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),i386-netwlibc)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),i386-wince)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),i386-embedded)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),i386-symbian)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),i386-nativent)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),i386-iphonesim)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),m68k-linux)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),m68k-freebsd)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),m68k-netbsd)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),m68k-amiga)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),m68k-atari)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),m68k-openbsd)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),m68k-palmos)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),m68k-embedded)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),powerpc-linux)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),powerpc-netbsd)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),powerpc-amiga)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),powerpc-macos)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),powerpc-darwin)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),powerpc-morphos)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),powerpc-embedded)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),powerpc-wii)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),sparc-linux)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),sparc-netbsd)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),sparc-solaris)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),sparc-embedded)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),x86_64-linux)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),x86_64-freebsd)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),x86_64-solaris)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),x86_64-darwin)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),x86_64-win64)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),x86_64-embedded)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),arm-linux)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),arm-palmos)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),arm-darwin)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),arm-wince)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),arm-gba)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),arm-nds)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),arm-embedded)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),arm-symbian)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),powerpc64-linux)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),powerpc64-darwin)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),powerpc64-embedded)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),avr-embedded)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),armeb-linux)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),armeb-embedded)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),mipsel-linux)
+override TARGET_DIRS+=utils
+endif
+ifeq ($(FULL_TARGET),i386-linux)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),i386-go32v2)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),i386-win32)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),i386-os2)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),i386-freebsd)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),i386-beos)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),i386-haiku)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),i386-netbsd)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),i386-solaris)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),i386-qnx)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),i386-netware)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),i386-openbsd)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),i386-wdosx)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),i386-darwin)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),i386-emx)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),i386-watcom)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),i386-netwlibc)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),i386-wince)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),i386-embedded)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),i386-symbian)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),i386-nativent)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),i386-iphonesim)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),m68k-linux)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),m68k-freebsd)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),m68k-netbsd)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),m68k-amiga)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),m68k-atari)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),m68k-openbsd)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),m68k-palmos)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),m68k-embedded)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),powerpc-linux)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),powerpc-netbsd)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),powerpc-amiga)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),powerpc-macos)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),powerpc-darwin)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),powerpc-morphos)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),powerpc-embedded)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),powerpc-wii)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),sparc-linux)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),sparc-netbsd)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),sparc-solaris)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),sparc-embedded)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),x86_64-linux)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),x86_64-freebsd)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),x86_64-solaris)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),x86_64-darwin)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),x86_64-win64)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),x86_64-embedded)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),arm-linux)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),arm-palmos)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),arm-darwin)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),arm-wince)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),arm-gba)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),arm-nds)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),arm-embedded)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),arm-symbian)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),powerpc64-linux)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),powerpc64-darwin)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),powerpc64-embedded)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),avr-embedded)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),armeb-linux)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),armeb-embedded)
+override TARGET_PROGRAMS+=pp
+endif
+ifeq ($(FULL_TARGET),mipsel-linux)
+override TARGET_PROGRAMS+=pp
+endif
+override INSTALL_FPCPACKAGE=y
+ifeq ($(FULL_TARGET),i386-linux)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-go32v2)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-win32)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-os2)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-freebsd)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-beos)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-haiku)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-netbsd)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-solaris)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-qnx)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-netware)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-openbsd)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-wdosx)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-darwin)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-emx)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-watcom)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-netwlibc)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-wince)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-embedded)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-symbian)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-nativent)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-iphonesim)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),m68k-linux)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),m68k-freebsd)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),m68k-netbsd)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),m68k-amiga)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),m68k-atari)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),m68k-openbsd)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),m68k-palmos)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),m68k-embedded)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),powerpc-linux)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),powerpc-netbsd)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),powerpc-amiga)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),powerpc-macos)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),powerpc-darwin)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),powerpc-morphos)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),powerpc-embedded)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),powerpc-wii)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),sparc-linux)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),sparc-netbsd)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),sparc-solaris)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),sparc-embedded)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),x86_64-linux)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),x86_64-freebsd)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),x86_64-solaris)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),x86_64-darwin)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),x86_64-win64)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),x86_64-embedded)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),arm-linux)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),arm-palmos)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),arm-darwin)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),arm-wince)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),arm-gba)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),arm-nds)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),arm-embedded)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),arm-symbian)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),powerpc64-linux)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),powerpc64-darwin)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),powerpc64-embedded)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),avr-embedded)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),armeb-linux)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),armeb-embedded)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),mipsel-linux)
+override COMPILER_INCLUDEDIR+=$(CPC_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-linux)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),i386-go32v2)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),i386-win32)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),i386-os2)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),i386-freebsd)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),i386-beos)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),i386-haiku)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),i386-netbsd)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),i386-solaris)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),i386-qnx)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),i386-netware)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),i386-openbsd)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),i386-wdosx)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),i386-darwin)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),i386-emx)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),i386-watcom)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),i386-netwlibc)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),i386-wince)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),i386-embedded)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),i386-symbian)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),i386-nativent)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),i386-iphonesim)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),m68k-linux)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),m68k-freebsd)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),m68k-netbsd)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),m68k-amiga)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),m68k-atari)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),m68k-openbsd)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),m68k-palmos)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),m68k-embedded)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),powerpc-linux)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),powerpc-netbsd)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),powerpc-amiga)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),powerpc-macos)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),powerpc-darwin)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),powerpc-morphos)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),powerpc-embedded)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),powerpc-wii)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),sparc-linux)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),sparc-netbsd)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),sparc-solaris)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),sparc-embedded)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),x86_64-linux)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),x86_64-freebsd)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),x86_64-solaris)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),x86_64-darwin)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),x86_64-win64)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),x86_64-embedded)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),arm-linux)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),arm-palmos)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),arm-darwin)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),arm-wince)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),arm-gba)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),arm-nds)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),arm-embedded)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),arm-symbian)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),powerpc64-linux)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),powerpc64-darwin)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),powerpc64-embedded)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),avr-embedded)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),armeb-linux)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),armeb-embedded)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),mipsel-linux)
+override COMPILER_UNITDIR+=$(COMPILERSOURCEDIR)
+endif
+ifeq ($(FULL_TARGET),i386-linux)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),i386-go32v2)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),i386-win32)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),i386-os2)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),i386-freebsd)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),i386-beos)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),i386-haiku)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),i386-netbsd)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),i386-solaris)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),i386-qnx)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),i386-netware)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),i386-openbsd)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),i386-wdosx)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),i386-darwin)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),i386-emx)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),i386-watcom)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),i386-netwlibc)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),i386-wince)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),i386-embedded)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),i386-symbian)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),i386-nativent)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),i386-iphonesim)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),m68k-linux)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),m68k-freebsd)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),m68k-netbsd)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),m68k-amiga)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),m68k-atari)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),m68k-openbsd)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),m68k-palmos)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),m68k-embedded)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),powerpc-linux)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),powerpc-netbsd)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),powerpc-amiga)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),powerpc-macos)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),powerpc-darwin)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),powerpc-morphos)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),powerpc-embedded)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),powerpc-wii)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),sparc-linux)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),sparc-netbsd)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),sparc-solaris)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),sparc-embedded)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),x86_64-linux)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),x86_64-freebsd)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),x86_64-solaris)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),x86_64-darwin)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),x86_64-win64)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),x86_64-embedded)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),arm-linux)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),arm-palmos)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),arm-darwin)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),arm-wince)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),arm-gba)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),arm-nds)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),arm-embedded)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),arm-symbian)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),powerpc64-linux)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),powerpc64-darwin)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),powerpc64-embedded)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),avr-embedded)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),armeb-linux)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),armeb-embedded)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),mipsel-linux)
+override COMPILER_TARGETDIR+=.
+endif
+ifeq ($(FULL_TARGET),i386-linux)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-go32v2)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-win32)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-os2)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-freebsd)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-beos)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-haiku)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-netbsd)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-solaris)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-qnx)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-netware)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-openbsd)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-wdosx)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-darwin)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-emx)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-watcom)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-netwlibc)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-wince)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-embedded)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-symbian)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-nativent)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),i386-iphonesim)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),m68k-linux)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),m68k-freebsd)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),m68k-netbsd)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),m68k-amiga)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),m68k-atari)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),m68k-openbsd)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),m68k-palmos)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),m68k-embedded)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),powerpc-linux)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),powerpc-netbsd)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),powerpc-amiga)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),powerpc-macos)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),powerpc-darwin)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),powerpc-morphos)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),powerpc-embedded)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),powerpc-wii)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),sparc-linux)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),sparc-netbsd)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),sparc-solaris)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),sparc-embedded)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),x86_64-linux)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),x86_64-freebsd)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),x86_64-solaris)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),x86_64-darwin)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),x86_64-win64)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),x86_64-embedded)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),arm-linux)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),arm-palmos)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),arm-darwin)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),arm-wince)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),arm-gba)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),arm-nds)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),arm-embedded)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),arm-symbian)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),powerpc64-linux)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),powerpc64-darwin)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),powerpc64-embedded)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),avr-embedded)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),armeb-linux)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),armeb-embedded)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifeq ($(FULL_TARGET),mipsel-linux)
+override COMPILER_UNITTARGETDIR+=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+endif
+ifdef REQUIRE_UNITSDIR
+override UNITSDIR+=$(REQUIRE_UNITSDIR)
+endif
+ifdef REQUIRE_PACKAGESDIR
+override PACKAGESDIR+=$(REQUIRE_PACKAGESDIR)
+endif
+ifdef ZIPINSTALL
+ifneq ($(findstring $(OS_TARGET),$(UNIXs)),)
+UNIXHier=1
+endif
+else
+ifneq ($(findstring $(OS_SOURCE),$(UNIXs)),)
+UNIXHier=1
+endif
+endif
+ifndef INSTALL_PREFIX
+ifdef PREFIX
+INSTALL_PREFIX=$(PREFIX)
+endif
+endif
+ifndef INSTALL_PREFIX
+ifdef UNIXHier
+INSTALL_PREFIX=/usr/local
+else
+ifdef INSTALL_FPCPACKAGE
+INSTALL_BASEDIR:=/pp
+else
+INSTALL_BASEDIR:=/$(PACKAGE_NAME)
+endif
+endif
+endif
+export INSTALL_PREFIX
+ifdef INSTALL_FPCSUBDIR
+export INSTALL_FPCSUBDIR
+endif
+ifndef DIST_DESTDIR
+DIST_DESTDIR:=$(BASEDIR)
+endif
+export DIST_DESTDIR
+ifndef COMPILER_UNITTARGETDIR
+ifdef PACKAGEDIR_MAIN
+COMPILER_UNITTARGETDIR=$(PACKAGEDIR_MAIN)/units/$(TARGETSUFFIX)
+else
+COMPILER_UNITTARGETDIR=units/$(TARGETSUFFIX)
+endif
+endif
+ifndef COMPILER_TARGETDIR
+COMPILER_TARGETDIR=.
+endif
+ifndef INSTALL_BASEDIR
+ifdef UNIXHier
+ifdef INSTALL_FPCPACKAGE
+INSTALL_BASEDIR:=$(INSTALL_PREFIX)/lib/fpc/$(FPC_VERSION)
+else
+INSTALL_BASEDIR:=$(INSTALL_PREFIX)/lib/$(PACKAGE_NAME)
+endif
+else
+INSTALL_BASEDIR:=$(INSTALL_PREFIX)
+endif
+endif
+ifndef INSTALL_BINDIR
+ifdef UNIXHier
+INSTALL_BINDIR:=$(INSTALL_PREFIX)/bin
+else
+INSTALL_BINDIR:=$(INSTALL_BASEDIR)/bin
+ifdef INSTALL_FPCPACKAGE
+ifdef CROSSCOMPILE
+ifdef CROSSINSTALL
+INSTALL_BINDIR:=$(INSTALL_BINDIR)/$(SOURCESUFFIX)
+else
+INSTALL_BINDIR:=$(INSTALL_BINDIR)/$(TARGETSUFFIX)
+endif
+else
+INSTALL_BINDIR:=$(INSTALL_BINDIR)/$(TARGETSUFFIX)
+endif
+endif
+endif
+endif
+ifndef INSTALL_UNITDIR
+INSTALL_UNITDIR:=$(INSTALL_BASEDIR)/units/$(TARGETSUFFIX)
+ifdef INSTALL_FPCPACKAGE
+ifdef PACKAGE_NAME
+INSTALL_UNITDIR:=$(INSTALL_UNITDIR)/$(PACKAGE_NAME)
+endif
+endif
+endif
+ifndef INSTALL_LIBDIR
+ifdef UNIXHier
+INSTALL_LIBDIR:=$(INSTALL_PREFIX)/lib
+else
+INSTALL_LIBDIR:=$(INSTALL_UNITDIR)
+endif
+endif
+ifndef INSTALL_SOURCEDIR
+ifdef UNIXHier
+ifdef BSDhier
+SRCPREFIXDIR=share/src
+else
+ifdef linuxHier
+SRCPREFIXDIR=share/src
+else
+SRCPREFIXDIR=src
+endif
+endif
+ifdef INSTALL_FPCPACKAGE
+ifdef INSTALL_FPCSUBDIR
+INSTALL_SOURCEDIR:=$(INSTALL_PREFIX)/$(SRCPREFIXDIR)/fpc-$(FPC_VERSION)/$(INSTALL_FPCSUBDIR)/$(PACKAGE_NAME)
+else
+INSTALL_SOURCEDIR:=$(INSTALL_PREFIX)/$(SRCPREFIXDIR)/fpc-$(FPC_VERSION)/$(PACKAGE_NAME)
+endif
+else
+INSTALL_SOURCEDIR:=$(INSTALL_PREFIX)/$(SRCPREFIXDIR)/$(PACKAGE_NAME)-$(PACKAGE_VERSION)
+endif
+else
+ifdef INSTALL_FPCPACKAGE
+ifdef INSTALL_FPCSUBDIR
+INSTALL_SOURCEDIR:=$(INSTALL_BASEDIR)/source/$(INSTALL_FPCSUBDIR)/$(PACKAGE_NAME)
+else
+INSTALL_SOURCEDIR:=$(INSTALL_BASEDIR)/source/$(PACKAGE_NAME)
+endif
+else
+INSTALL_SOURCEDIR:=$(INSTALL_BASEDIR)/source
+endif
+endif
+endif
+ifndef INSTALL_DOCDIR
+ifdef UNIXHier
+ifdef BSDhier
+DOCPREFIXDIR=share/doc
+else
+ifdef linuxHier
+DOCPREFIXDIR=share/doc
+else
+DOCPREFIXDIR=doc
+endif
+endif
+ifdef INSTALL_FPCPACKAGE
+INSTALL_DOCDIR:=$(INSTALL_PREFIX)/$(DOCPREFIXDIR)/fpc-$(FPC_VERSION)/$(PACKAGE_NAME)
+else
+INSTALL_DOCDIR:=$(INSTALL_PREFIX)/$(DOCPREFIXDIR)/$(PACKAGE_NAME)-$(PACKAGE_VERSION)
+endif
+else
+ifdef INSTALL_FPCPACKAGE
+INSTALL_DOCDIR:=$(INSTALL_BASEDIR)/doc/$(PACKAGE_NAME)
+else
+INSTALL_DOCDIR:=$(INSTALL_BASEDIR)/doc
+endif
+endif
+endif
+ifndef INSTALL_EXAMPLEDIR
+ifdef UNIXHier
+ifdef INSTALL_FPCPACKAGE
+ifdef BSDhier
+INSTALL_EXAMPLEDIR:=$(INSTALL_PREFIX)/share/examples/fpc-$(FPC_VERSION)/$(PACKAGE_NAME)
+else
+ifdef linuxHier
+INSTALL_EXAMPLEDIR:=$(INSTALL_DOCDIR)/examples
+else
+INSTALL_EXAMPLEDIR:=$(INSTALL_PREFIX)/doc/fpc-$(FPC_VERSION)/examples/$(PACKAGE_NAME)
+endif
+endif
+else
+ifdef BSDhier
+INSTALL_EXAMPLEDIR:=$(INSTALL_PREFIX)/share/examples/$(PACKAGE_NAME)-$(PACKAGE_VERSION)
+else
+ifdef linuxHier
+INSTALL_EXAMPLEDIR:=$(INSTALL_DOCDIR)/examples/$(PACKAGE_NAME)-$(PACKAGE_VERSION)
+else
+INSTALL_EXAMPLEDIR:=$(INSTALL_PREFIX)/doc/$(PACKAGE_NAME)-$(PACKAGE_VERSION)
+endif
+endif
+endif
+else
+ifdef INSTALL_FPCPACKAGE
+INSTALL_EXAMPLEDIR:=$(INSTALL_BASEDIR)/examples/$(PACKAGE_NAME)
+else
+INSTALL_EXAMPLEDIR:=$(INSTALL_BASEDIR)/examples
+endif
+endif
+endif
+ifndef INSTALL_DATADIR
+INSTALL_DATADIR=$(INSTALL_BASEDIR)
+endif
+ifndef INSTALL_SHAREDDIR
+INSTALL_SHAREDDIR=$(INSTALL_PREFIX)/lib
+endif
+ifdef CROSSCOMPILE
+ifndef CROSSBINDIR
+CROSSBINDIR:=$(wildcard $(CROSSTARGETDIR)/bin/$(SOURCESUFFIX))
+ifeq ($(CROSSBINDIR),)
+CROSSBINDIR:=$(wildcard $(INSTALL_BASEDIR)/cross/$(TARGETSUFFIX)/bin/$(FULL_SOURCE))
+endif
+endif
+else
+CROSSBINDIR=
+endif
+BATCHEXT=.bat
+LOADEREXT=.as
+EXEEXT=.exe
+PPLEXT=.ppl
+PPUEXT=.ppu
+OEXT=.o
+ASMEXT=.s
+SMARTEXT=.sl
+STATICLIBEXT=.a
+SHAREDLIBEXT=.so
+SHAREDLIBPREFIX=libfp
+STATICLIBPREFIX=libp
+IMPORTLIBPREFIX=libimp
+RSTEXT=.rst
+EXEDBGEXT=.dbg
+ifeq ($(OS_TARGET),go32v1)
+STATICLIBPREFIX=
+SHORTSUFFIX=v1
+endif
+ifeq ($(OS_TARGET),go32v2)
+STATICLIBPREFIX=
+SHORTSUFFIX=dos
+IMPORTLIBPREFIX=
+endif
+ifeq ($(OS_TARGET),watcom)
+STATICLIBPREFIX=
+OEXT=.obj
+ASMEXT=.asm
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=wat
+IMPORTLIBPREFIX=
+endif
+ifeq ($(OS_TARGET),linux)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=lnx
+endif
+ifeq ($(OS_TARGET),freebsd)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=fbs
+endif
+ifeq ($(OS_TARGET),netbsd)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=nbs
+endif
+ifeq ($(OS_TARGET),openbsd)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=obs
+endif
+ifeq ($(OS_TARGET),win32)
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=w32
+endif
+ifeq ($(OS_TARGET),os2)
+BATCHEXT=.cmd
+AOUTEXT=.out
+STATICLIBPREFIX=
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=os2
+ECHO=echo
+IMPORTLIBPREFIX=
+endif
+ifeq ($(OS_TARGET),emx)
+BATCHEXT=.cmd
+AOUTEXT=.out
+STATICLIBPREFIX=
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=emx
+ECHO=echo
+IMPORTLIBPREFIX=
+endif
+ifeq ($(OS_TARGET),amiga)
+EXEEXT=
+SHAREDLIBEXT=.library
+SHORTSUFFIX=amg
+endif
+ifeq ($(OS_TARGET),morphos)
+EXEEXT=
+SHAREDLIBEXT=.library
+SHORTSUFFIX=mos
+endif
+ifeq ($(OS_TARGET),atari)
+EXEEXT=.ttp
+SHORTSUFFIX=ata
+endif
+ifeq ($(OS_TARGET),beos)
+BATCHEXT=.sh
+EXEEXT=
+SHORTSUFFIX=be
+endif
+ifeq ($(OS_TARGET),haiku)
+BATCHEXT=.sh
+EXEEXT=
+SHORTSUFFIX=hai
+endif
+ifeq ($(OS_TARGET),solaris)
+BATCHEXT=.sh
+EXEEXT=
+SHORTSUFFIX=sun
+endif
+ifeq ($(OS_TARGET),qnx)
+BATCHEXT=.sh
+EXEEXT=
+SHORTSUFFIX=qnx
+endif
+ifeq ($(OS_TARGET),netware)
+EXEEXT=.nlm
+STATICLIBPREFIX=
+SHORTSUFFIX=nw
+IMPORTLIBPREFIX=imp
+endif
+ifeq ($(OS_TARGET),netwlibc)
+EXEEXT=.nlm
+STATICLIBPREFIX=
+SHORTSUFFIX=nwl
+IMPORTLIBPREFIX=imp
+endif
+ifeq ($(OS_TARGET),macos)
+BATCHEXT=
+EXEEXT=
+DEBUGSYMEXT=.xcoff
+SHORTSUFFIX=mac
+IMPORTLIBPREFIX=imp
+endif
+ifneq ($(findstring $(OS_TARGET),darwin iphonesim),)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=dwn
+EXEDBGEXT=.dSYM
+endif
+ifeq ($(OS_TARGET),gba)
+EXEEXT=.gba
+SHAREDLIBEXT=.so
+SHORTSUFFIX=gba
+endif
+ifeq ($(OS_TARGET),symbian)
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=symbian
+endif
+ifeq ($(OS_TARGET),NativeNT)
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=nativent
+endif
+ifeq ($(OS_TARGET),wii)
+EXEEXT=.dol
+SHAREDLIBEXT=.so
+SHORTSUFFIX=wii
+endif
+ifneq ($(findstring $(OS_SOURCE),$(LIMIT83fs)),)
+FPCMADE=fpcmade.$(SHORTSUFFIX)
+ZIPSUFFIX=$(SHORTSUFFIX)
+ZIPCROSSPREFIX=
+ZIPSOURCESUFFIX=src
+ZIPEXAMPLESUFFIX=exm
+else
+FPCMADE=fpcmade.$(TARGETSUFFIX)
+ZIPSOURCESUFFIX=.source
+ZIPEXAMPLESUFFIX=.examples
+ifdef CROSSCOMPILE
+ZIPSUFFIX=.$(SOURCESUFFIX)
+ZIPCROSSPREFIX=$(TARGETSUFFIX)-
+else
+ZIPSUFFIX=.$(TARGETSUFFIX)
+ZIPCROSSPREFIX=
+endif
+endif
+ifndef ECHO
+ECHO:=$(strip $(wildcard $(addsuffix /gecho$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(ECHO),)
+ECHO:=$(strip $(wildcard $(addsuffix /echo$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(ECHO),)
+ECHO= __missing_command_ECHO
+else
+ECHO:=$(firstword $(ECHO))
+endif
+else
+ECHO:=$(firstword $(ECHO))
+endif
+endif
+export ECHO
+ifndef DATE
+DATE:=$(strip $(wildcard $(addsuffix /gdate$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(DATE),)
+DATE:=$(strip $(wildcard $(addsuffix /date$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(DATE),)
+DATE= __missing_command_DATE
+else
+DATE:=$(firstword $(DATE))
+endif
+else
+DATE:=$(firstword $(DATE))
+endif
+endif
+export DATE
+ifndef GINSTALL
+GINSTALL:=$(strip $(wildcard $(addsuffix /ginstall$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(GINSTALL),)
+GINSTALL:=$(strip $(wildcard $(addsuffix /install$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(GINSTALL),)
+GINSTALL= __missing_command_GINSTALL
+else
+GINSTALL:=$(firstword $(GINSTALL))
+endif
+else
+GINSTALL:=$(firstword $(GINSTALL))
+endif
+endif
+export GINSTALL
+ifndef CPPROG
+CPPROG:=$(strip $(wildcard $(addsuffix /cp$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(CPPROG),)
+CPPROG= __missing_command_CPPROG
+else
+CPPROG:=$(firstword $(CPPROG))
+endif
+endif
+export CPPROG
+ifndef RMPROG
+RMPROG:=$(strip $(wildcard $(addsuffix /rm$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(RMPROG),)
+RMPROG= __missing_command_RMPROG
+else
+RMPROG:=$(firstword $(RMPROG))
+endif
+endif
+export RMPROG
+ifndef MVPROG
+MVPROG:=$(strip $(wildcard $(addsuffix /mv$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(MVPROG),)
+MVPROG= __missing_command_MVPROG
+else
+MVPROG:=$(firstword $(MVPROG))
+endif
+endif
+export MVPROG
+ifndef MKDIRPROG
+MKDIRPROG:=$(strip $(wildcard $(addsuffix /gmkdir$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(MKDIRPROG),)
+MKDIRPROG:=$(strip $(wildcard $(addsuffix /mkdir$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(MKDIRPROG),)
+MKDIRPROG= __missing_command_MKDIRPROG
+else
+MKDIRPROG:=$(firstword $(MKDIRPROG))
+endif
+else
+MKDIRPROG:=$(firstword $(MKDIRPROG))
+endif
+endif
+export MKDIRPROG
+ifndef ECHOREDIR
+ifndef inUnix
+ECHOREDIR=echo
+else
+ECHOREDIR=$(ECHO)
+endif
+endif
+ifndef COPY
+COPY:=$(CPPROG) -fp
+endif
+ifndef COPYTREE
+COPYTREE:=$(CPPROG) -Rfp
+endif
+ifndef MKDIRTREE
+MKDIRTREE:=$(MKDIRPROG) -p
+endif
+ifndef MOVE
+MOVE:=$(MVPROG) -f
+endif
+ifndef DEL
+DEL:=$(RMPROG) -f
+endif
+ifndef DELTREE
+DELTREE:=$(RMPROG) -rf
+endif
+ifndef INSTALL
+ifdef inUnix
+INSTALL:=$(GINSTALL) -c -m 644
+else
+INSTALL:=$(COPY)
+endif
+endif
+ifndef INSTALLEXE
+ifdef inUnix
+INSTALLEXE:=$(GINSTALL) -c -m 755
+else
+INSTALLEXE:=$(COPY)
+endif
+endif
+ifndef MKDIR
+MKDIR:=$(GINSTALL) -m 755 -d
+endif
+export ECHOREDIR COPY COPYTREE MOVE DEL DELTREE INSTALL INSTALLEXE MKDIR
+ifndef PPUMOVE
+PPUMOVE:=$(strip $(wildcard $(addsuffix /ppumove$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(PPUMOVE),)
+PPUMOVE= __missing_command_PPUMOVE
+else
+PPUMOVE:=$(firstword $(PPUMOVE))
+endif
+endif
+export PPUMOVE
+ifndef FPCMAKE
+FPCMAKE:=$(strip $(wildcard $(addsuffix /fpcmake$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(FPCMAKE),)
+FPCMAKE= __missing_command_FPCMAKE
+else
+FPCMAKE:=$(firstword $(FPCMAKE))
+endif
+endif
+export FPCMAKE
+ifndef ZIPPROG
+ZIPPROG:=$(strip $(wildcard $(addsuffix /zip$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(ZIPPROG),)
+ZIPPROG= __missing_command_ZIPPROG
+else
+ZIPPROG:=$(firstword $(ZIPPROG))
+endif
+endif
+export ZIPPROG
+ifndef TARPROG
+TARPROG:=$(strip $(wildcard $(addsuffix /gtar$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(TARPROG),)
+TARPROG:=$(strip $(wildcard $(addsuffix /tar$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(TARPROG),)
+TARPROG= __missing_command_TARPROG
+else
+TARPROG:=$(firstword $(TARPROG))
+endif
+else
+TARPROG:=$(firstword $(TARPROG))
+endif
+endif
+export TARPROG
+ASNAME=$(BINUTILSPREFIX)as
+LDNAME=$(BINUTILSPREFIX)ld
+ARNAME=$(BINUTILSPREFIX)ar
+RCNAME=$(BINUTILSPREFIX)rc
+ifndef ASPROG
+ifdef CROSSBINDIR
+ASPROG=$(CROSSBINDIR)/$(ASNAME)$(SRCEXEEXT)
+else
+ASPROG=$(ASNAME)
+endif
+endif
+ifndef LDPROG
+ifdef CROSSBINDIR
+LDPROG=$(CROSSBINDIR)/$(LDNAME)$(SRCEXEEXT)
+else
+LDPROG=$(LDNAME)
+endif
+endif
+ifndef RCPROG
+ifdef CROSSBINDIR
+RCPROG=$(CROSSBINDIR)/$(RCNAME)$(SRCEXEEXT)
+else
+RCPROG=$(RCNAME)
+endif
+endif
+ifndef ARPROG
+ifdef CROSSBINDIR
+ARPROG=$(CROSSBINDIR)/$(ARNAME)$(SRCEXEEXT)
+else
+ARPROG=$(ARNAME)
+endif
+endif
+AS=$(ASPROG)
+LD=$(LDPROG)
+RC=$(RCPROG)
+AR=$(ARPROG)
+PPAS=ppas$(SRCBATCHEXT)
+ifdef inUnix
+LDCONFIG=ldconfig
+else
+LDCONFIG=
+endif
+ifdef DATE
+DATESTR:=$(shell $(DATE) +%Y%m%d)
+else
+DATESTR=
+endif
+ZIPOPT=-9
+ZIPEXT=.zip
+ifeq ($(USETAR),bz2)
+TAROPT=vj
+TAREXT=.tar.bz2
+else
+TAROPT=vz
+TAREXT=.tar.gz
+endif
+override REQUIRE_PACKAGES=rtl rtl
+ifeq ($(FULL_TARGET),i386-linux)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-go32v2)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-win32)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-os2)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-freebsd)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-beos)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-haiku)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-netbsd)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-solaris)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-qnx)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-netware)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-openbsd)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-wdosx)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-darwin)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-emx)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-watcom)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-netwlibc)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-wince)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-embedded)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-symbian)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-nativent)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-iphonesim)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),m68k-linux)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),m68k-freebsd)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),m68k-netbsd)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),m68k-amiga)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),m68k-atari)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),m68k-openbsd)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),m68k-palmos)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),m68k-embedded)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),powerpc-linux)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),powerpc-netbsd)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),powerpc-amiga)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),powerpc-macos)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),powerpc-darwin)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),powerpc-morphos)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),powerpc-embedded)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),powerpc-wii)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),sparc-linux)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),sparc-netbsd)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),sparc-solaris)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),sparc-embedded)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),x86_64-linux)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),x86_64-freebsd)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),x86_64-solaris)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),x86_64-darwin)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),x86_64-win64)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),x86_64-embedded)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),arm-linux)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),arm-palmos)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),arm-darwin)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),arm-wince)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),arm-gba)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),arm-nds)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),arm-embedded)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),arm-symbian)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),powerpc64-linux)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),powerpc64-darwin)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),powerpc64-embedded)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),avr-embedded)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),armeb-linux)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),armeb-embedded)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),mipsel-linux)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifdef REQUIRE_PACKAGES_RTL
+PACKAGEDIR_RTL:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /rtl/Makefile.fpc,$(PACKAGESDIR))))))
+ifneq ($(PACKAGEDIR_RTL),)
+ifneq ($(wildcard $(PACKAGEDIR_RTL)/units/$(TARGETSUFFIX)),)
+UNITDIR_RTL=$(PACKAGEDIR_RTL)/units/$(TARGETSUFFIX)
+else
+UNITDIR_RTL=$(PACKAGEDIR_RTL)
+endif
+ifneq ($(wildcard $(PACKAGEDIR_RTL)/units/$(SOURCESUFFIX)),)
+UNITDIR_FPMAKE_RTL=$(PACKAGEDIR_RTL)/units/$(SOURCESUFFIX)
+else
+ifneq ($(wildcard $(PACKAGEDIR_RTL)/units_bs/$(SOURCESUFFIX)),)
+UNITDIR_FPMAKE_RTL=$(PACKAGEDIR_RTL)/units_bs/$(SOURCESUFFIX)
+else
+UNITDIR_FPMAKE_RTL=$(PACKAGEDIR_RTL)
+endif
+endif
+ifdef CHECKDEPEND
+$(PACKAGEDIR_RTL)/$(OS_TARGET)/$(FPCMADE):
+ $(MAKE) -C $(PACKAGEDIR_RTL)/$(OS_TARGET) $(FPCMADE)
+override ALLDEPENDENCIES+=$(PACKAGEDIR_RTL)/$(OS_TARGET)/$(FPCMADE)
+endif
+else
+PACKAGEDIR_RTL=
+UNITDIR_RTL:=$(subst /Package.fpc,,$(strip $(wildcard $(addsuffix /rtl/Package.fpc,$(UNITSDIR)))))
+ifneq ($(UNITDIR_RTL),)
+UNITDIR_RTL:=$(firstword $(UNITDIR_RTL))
+else
+UNITDIR_RTL=
+endif
+endif
+ifdef UNITDIR_RTL
+override COMPILER_UNITDIR+=$(UNITDIR_RTL)
+endif
+ifdef UNITDIR_FPMAKE_RTL
+override COMPILER_FPMAKE_UNITDIR+=$(UNITDIR_FPMAKE_RTL)
+endif
+endif
+ifndef NOCPUDEF
+override FPCOPTDEF=$(ARCH)
+endif
+ifneq ($(OS_TARGET),$(OS_SOURCE))
+override FPCOPT+=-T$(OS_TARGET)
+endif
+ifneq ($(CPU_TARGET),$(CPU_SOURCE))
+override FPCOPT+=-P$(ARCH)
+endif
+ifeq ($(OS_SOURCE),openbsd)
+override FPCOPT+=-FD$(NEW_BINUTILS_PATH)
+override FPCMAKEOPT+=-FD$(NEW_BINUTILS_PATH)
+endif
+ifndef CROSSBOOTSTRAP
+ifneq ($(BINUTILSPREFIX),)
+override FPCOPT+=-XP$(BINUTILSPREFIX)
+endif
+ifneq ($(BINUTILSPREFIX),)
+override FPCOPT+=-Xr$(RLINKPATH)
+endif
+endif
+ifndef CROSSCOMPILE
+ifneq ($(BINUTILSPREFIX),)
+override FPCMAKEOPT+=-XP$(BINUTILSPREFIX)
+endif
+endif
+ifdef UNITDIR
+override FPCOPT+=$(addprefix -Fu,$(UNITDIR))
+endif
+ifdef LIBDIR
+override FPCOPT+=$(addprefix -Fl,$(LIBDIR))
+endif
+ifdef OBJDIR
+override FPCOPT+=$(addprefix -Fo,$(OBJDIR))
+endif
+ifdef INCDIR
+override FPCOPT+=$(addprefix -Fi,$(INCDIR))
+endif
+ifdef LINKSMART
+override FPCOPT+=-XX
+endif
+ifdef CREATESMART
+override FPCOPT+=-CX
+endif
+ifdef DEBUG
+override FPCOPT+=-gl
+override FPCOPTDEF+=DEBUG
+endif
+ifdef RELEASE
+ifneq ($(findstring 2.0.,$(FPC_VERSION)),)
+ifeq ($(CPU_TARGET),i386)
+FPCCPUOPT:=-OG2p3
+endif
+ifeq ($(CPU_TARGET),powerpc)
+FPCCPUOPT:=-O1r
+endif
+else
+FPCCPUOPT:=-O2
+endif
+override FPCOPT+=-Ur -Xs $(FPCCPUOPT) -n
+override FPCOPTDEF+=RELEASE
+endif
+ifdef STRIP
+override FPCOPT+=-Xs
+endif
+ifdef OPTIMIZE
+override FPCOPT+=-O2
+endif
+ifdef VERBOSE
+override FPCOPT+=-vwni
+endif
+ifdef COMPILER_OPTIONS
+override FPCOPT+=$(COMPILER_OPTIONS)
+endif
+ifdef COMPILER_UNITDIR
+override FPCOPT+=$(addprefix -Fu,$(COMPILER_UNITDIR))
+endif
+ifdef COMPILER_LIBRARYDIR
+override FPCOPT+=$(addprefix -Fl,$(COMPILER_LIBRARYDIR))
+endif
+ifdef COMPILER_OBJECTDIR
+override FPCOPT+=$(addprefix -Fo,$(COMPILER_OBJECTDIR))
+endif
+ifdef COMPILER_INCLUDEDIR
+override FPCOPT+=$(addprefix -Fi,$(COMPILER_INCLUDEDIR))
+endif
+ifdef CROSSBINDIR
+override FPCOPT+=-FD$(CROSSBINDIR)
+endif
+ifdef COMPILER_TARGETDIR
+override FPCOPT+=-FE$(COMPILER_TARGETDIR)
+ifeq ($(COMPILER_TARGETDIR),.)
+override TARGETDIRPREFIX=
+else
+override TARGETDIRPREFIX=$(COMPILER_TARGETDIR)/
+endif
+endif
+ifdef COMPILER_UNITTARGETDIR
+override FPCOPT+=-FU$(COMPILER_UNITTARGETDIR)
+ifeq ($(COMPILER_UNITTARGETDIR),.)
+override UNITTARGETDIRPREFIX=
+else
+override UNITTARGETDIRPREFIX=$(COMPILER_UNITTARGETDIR)/
+endif
+else
+ifdef COMPILER_TARGETDIR
+override COMPILER_UNITTARGETDIR=$(COMPILER_TARGETDIR)
+override UNITTARGETDIRPREFIX=$(TARGETDIRPREFIX)
+endif
+endif
+ifdef CREATESHARED
+override FPCOPT+=-Cg
+ifeq ($(CPU_TARGET),i386)
+override FPCOPT+=-Aas
+endif
+endif
+ifeq ($(findstring 2.0.,$(FPC_VERSION)),)
+ifneq ($(findstring $(OS_TARGET),freebsd openbsd netbsd linux solaris),)
+ifeq ($(CPU_TARGET),x86_64)
+override FPCOPT+=-Cg
+endif
+endif
+endif
+ifdef LINKSHARED
+endif
+ifdef OPT
+override FPCOPT+=$(OPT)
+endif
+ifdef FPCOPTDEF
+override FPCOPT+=$(addprefix -d,$(FPCOPTDEF))
+endif
+ifdef CFGFILE
+override FPCOPT+=@$(CFGFILE)
+endif
+ifdef USEENV
+override FPCEXTCMD:=$(FPCOPT)
+override FPCOPT:=!FPCEXTCMD
+export FPCEXTCMD
+endif
+override AFULL_TARGET=$(CPU_TARGET)-$(OS_TARGET)
+override AFULL_SOURCE=$(CPU_SOURCE)-$(OS_SOURCE)
+ifneq ($(AFULL_TARGET),$(AFULL_SOURCE))
+override ACROSSCOMPILE=1
+endif
+ifdef ACROSSCOMPILE
+override FPCOPT+=$(CROSSOPT)
+endif
+override COMPILER:=$(FPC) $(FPCOPT)
+ifeq (,$(findstring -s ,$(COMPILER)))
+EXECPPAS=
+else
+ifeq ($(FULL_SOURCE),$(FULL_TARGET))
+ifdef RUNBATCH
+EXECPPAS:=@$(RUNBATCH) $(PPAS)
+else
+EXECPPAS:=@$(PPAS)
+endif
+endif
+endif
+.PHONY: fpc_exes
+ifndef CROSSINSTALL
+ifneq ($(TARGET_PROGRAMS),)
+override EXEFILES=$(addsuffix $(EXEEXT),$(TARGET_PROGRAMS))
+override EXEOFILES:=$(addsuffix $(OEXT),$(TARGET_PROGRAMS)) $(addprefix $(STATICLIBPREFIX),$(addsuffix $(STATICLIBEXT),$(TARGET_PROGRAMS))) $(addprefix $(IMPORTLIBPREFIX),$(addsuffix $(STATICLIBEXT),$(TARGET_PROGRAMS)))
+override EXEDBGFILES:=$(addsuffix $(EXEDBGEXT),$(TARGET_PROGRAMS))
+override ALLTARGET+=fpc_exes
+override INSTALLEXEFILES+=$(EXEFILES)
+override CLEANEXEFILES+=$(EXEFILES) $(EXEOFILES)
+override CLEANEXEDBGFILES+=$(EXEDBGFILES)
+ifeq ($(OS_TARGET),os2)
+override CLEANEXEFILES+=$(addsuffix $(AOUTEXT),$(TARGET_PROGRAMS))
+endif
+ifeq ($(OS_TARGET),emx)
+override CLEANEXEFILES+=$(addsuffix $(AOUTEXT),$(TARGET_PROGRAMS))
+endif
+endif
+endif
+fpc_exes: $(COMPILER_TARGETDIR) $(COMPILER_UNITTARGETDIR) $(EXEFILES)
+ifdef TARGET_RSTS
+override RSTFILES=$(addsuffix $(RSTEXT),$(TARGET_RSTS))
+override CLEANRSTFILES+=$(RSTFILES)
+endif
+.PHONY: fpc_all fpc_smart fpc_debug fpc_release fpc_shared
+$(FPCMADE): $(ALLDEPENDENCIES) $(ALLTARGET)
+ @$(ECHOREDIR) Compiled > $(FPCMADE)
+fpc_all: $(FPCMADE)
+fpc_smart:
+ $(MAKE) all LINKSMART=1 CREATESMART=1
+fpc_debug:
+ $(MAKE) all DEBUG=1
+fpc_release:
+ $(MAKE) all RELEASE=1
+.SUFFIXES: $(EXEEXT) $(PPUEXT) $(OEXT) .pas .lpr .dpr .pp .rc .res
+$(COMPILER_UNITTARGETDIR):
+ $(MKDIRTREE) $(COMPILER_UNITTARGETDIR)
+$(COMPILER_TARGETDIR):
+ $(MKDIRTREE) $(COMPILER_TARGETDIR)
+%$(PPUEXT): %.pp
+ $(COMPILER) $<
+ $(EXECPPAS)
+%$(PPUEXT): %.pas
+ $(COMPILER) $<
+ $(EXECPPAS)
+%$(EXEEXT): %.pp
+ $(COMPILER) $<
+ $(EXECPPAS)
+%$(EXEEXT): %.pas
+ $(COMPILER) $<
+ $(EXECPPAS)
+%$(EXEEXT): %.lpr
+ $(COMPILER) $<
+ $(EXECPPAS)
+%$(EXEEXT): %.dpr
+ $(COMPILER) $<
+ $(EXECPPAS)
+%.res: %.rc
+ windres -i $< -o $@
+vpath %.pp $(COMPILER_SOURCEDIR) $(COMPILER_INCLUDEDIR)
+vpath %.pas $(COMPILER_SOURCEDIR) $(COMPILER_INCLUDEDIR)
+vpath %.lpr $(COMPILER_SOURCEDIR) $(COMPILER_INCLUDEDIR)
+vpath %.dpr $(COMPILER_SOURCEDIR) $(COMPILER_INCLUDEDIR)
+vpath %.inc $(COMPILER_INCLUDEDIR)
+vpath %$(OEXT) $(COMPILER_UNITTARGETDIR)
+vpath %$(PPUEXT) $(COMPILER_UNITTARGETDIR)
+.PHONY: fpc_shared
+override INSTALLTARGET+=fpc_shared_install
+ifndef SHARED_LIBVERSION
+SHARED_LIBVERSION=$(FPC_VERSION)
+endif
+ifndef SHARED_LIBNAME
+SHARED_LIBNAME=$(PACKAGE_NAME)
+endif
+ifndef SHARED_FULLNAME
+SHARED_FULLNAME=$(SHAREDLIBPREFIX)$(SHARED_LIBNAME)-$(SHARED_LIBVERSION)$(SHAREDLIBEXT)
+endif
+ifndef SHARED_LIBUNITS
+SHARED_LIBUNITS:=$(TARGET_UNITS) $(TARGET_IMPLICITUNITS)
+override SHARED_LIBUNITS:=$(filter-out $(INSTALL_BUILDUNIT),$(SHARED_LIBUNITS))
+endif
+fpc_shared:
+ifdef HASSHAREDLIB
+ $(MAKE) all CREATESHARED=1 LINKSHARED=1 CREATESMART=1
+ifneq ($(SHARED_BUILD),n)
+ $(PPUMOVE) -q $(SHARED_LIBUNITS) -i$(COMPILER_UNITTARGETDIR) -o$(SHARED_FULLNAME) -d$(COMPILER_UNITTARGETDIR)
+endif
+else
+ @$(ECHO) Shared Libraries not supported
+endif
+fpc_shared_install:
+ifneq ($(SHARED_BUILD),n)
+ifneq ($(SHARED_LIBUNITS),)
+ifneq ($(wildcard $(COMPILER_UNITTARGETDIR)/$(SHARED_FULLNAME)),)
+ $(INSTALL) $(COMPILER_UNITTARGETDIR)/$(SHARED_FULLNAME) $(INSTALL_SHAREDDIR)
+endif
+endif
+endif
+.PHONY: fpc_install fpc_sourceinstall fpc_exampleinstall
+ifdef INSTALL_UNITS
+override INSTALLPPUFILES+=$(addsuffix $(PPUEXT),$(INSTALL_UNITS))
+endif
+ifdef INSTALL_BUILDUNIT
+override INSTALLPPUFILES:=$(filter-out $(INSTALL_BUILDUNIT)$(PPUEXT),$(INSTALLPPUFILES))
+endif
+ifdef INSTALLPPUFILES
+override INSTALLPPULINKFILES:=$(subst $(PPUEXT),$(OEXT),$(INSTALLPPUFILES)) $(addprefix $(STATICLIBPREFIX),$(subst $(PPUEXT),$(STATICLIBEXT),$(INSTALLPPUFILES))) $(addprefix $(IMPORTLIBPREFIX),$(subst $(PPUEXT),$(STATICLIBEXT),$(INSTALLPPUFILES)))
+ifneq ($(UNITTARGETDIRPREFIX),)
+override INSTALLPPUFILES:=$(addprefix $(UNITTARGETDIRPREFIX),$(notdir $(INSTALLPPUFILES)))
+override INSTALLPPULINKFILES:=$(wildcard $(addprefix $(UNITTARGETDIRPREFIX),$(notdir $(INSTALLPPULINKFILES))))
+endif
+override INSTALL_CREATEPACKAGEFPC=1
+endif
+ifdef INSTALLEXEFILES
+ifneq ($(TARGETDIRPREFIX),)
+override INSTALLEXEFILES:=$(addprefix $(TARGETDIRPREFIX),$(notdir $(INSTALLEXEFILES)))
+endif
+endif
+fpc_install: all $(INSTALLTARGET)
+ifdef INSTALLEXEFILES
+ $(MKDIR) $(INSTALL_BINDIR)
+ $(INSTALLEXE) $(INSTALLEXEFILES) $(INSTALL_BINDIR)
+endif
+ifdef INSTALL_CREATEPACKAGEFPC
+ifdef FPCMAKE
+ifdef PACKAGE_VERSION
+ifneq ($(wildcard Makefile.fpc),)
+ $(FPCMAKE) -p -T$(CPU_TARGET)-$(OS_TARGET) Makefile.fpc
+ $(MKDIR) $(INSTALL_UNITDIR)
+ $(INSTALL) Package.fpc $(INSTALL_UNITDIR)
+endif
+endif
+endif
+endif
+ifdef INSTALLPPUFILES
+ $(MKDIR) $(INSTALL_UNITDIR)
+ $(INSTALL) $(INSTALLPPUFILES) $(INSTALL_UNITDIR)
+ifneq ($(INSTALLPPULINKFILES),)
+ $(INSTALL) $(INSTALLPPULINKFILES) $(INSTALL_UNITDIR)
+endif
+ifneq ($(wildcard $(LIB_FULLNAME)),)
+ $(MKDIR) $(INSTALL_LIBDIR)
+ $(INSTALL) $(LIB_FULLNAME) $(INSTALL_LIBDIR)
+ifdef inUnix
+ ln -sf $(LIB_FULLNAME) $(INSTALL_LIBDIR)/$(LIB_NAME)
+endif
+endif
+endif
+ifdef INSTALL_FILES
+ $(MKDIR) $(INSTALL_DATADIR)
+ $(INSTALL) $(INSTALL_FILES) $(INSTALL_DATADIR)
+endif
+fpc_sourceinstall: distclean
+ $(MKDIR) $(INSTALL_SOURCEDIR)
+ $(COPYTREE) $(BASEDIR)/* $(INSTALL_SOURCEDIR)
+fpc_exampleinstall: $(addsuffix _distclean,$(TARGET_EXAMPLEDIRS))
+ifdef HASEXAMPLES
+ $(MKDIR) $(INSTALL_EXAMPLEDIR)
+endif
+ifdef EXAMPLESOURCEFILES
+ $(COPY) $(EXAMPLESOURCEFILES) $(INSTALL_EXAMPLEDIR)
+endif
+ifdef TARGET_EXAMPLEDIRS
+ $(COPYTREE) $(addsuffix /*,$(TARGET_EXAMPLEDIRS)) $(INSTALL_EXAMPLEDIR)
+endif
+.PHONY: fpc_distinstall
+fpc_distinstall: install exampleinstall
+.PHONY: fpc_zipinstall fpc_zipsourceinstall fpc_zipexampleinstall
+ifndef PACKDIR
+ifndef inUnix
+PACKDIR=$(BASEDIR)/../fpc-pack
+else
+PACKDIR=/tmp/fpc-pack
+endif
+endif
+ifndef ZIPNAME
+ifdef DIST_ZIPNAME
+ZIPNAME=$(DIST_ZIPNAME)
+else
+ZIPNAME=$(PACKAGE_NAME)
+endif
+endif
+ifndef FULLZIPNAME
+FULLZIPNAME=$(ZIPCROSSPREFIX)$(ZIPPREFIX)$(ZIPNAME)$(ZIPSUFFIX)
+endif
+ifndef ZIPTARGET
+ifdef DIST_ZIPTARGET
+ZIPTARGET=DIST_ZIPTARGET
+else
+ZIPTARGET=install
+endif
+endif
+ifndef USEZIP
+ifdef inUnix
+USETAR=1
+endif
+endif
+ifndef inUnix
+USEZIPWRAPPER=1
+endif
+ifdef USEZIPWRAPPER
+ZIPPATHSEP=$(PATHSEP)
+ZIPWRAPPER=$(subst /,$(PATHSEP),$(DIST_DESTDIR)/fpczip$(SRCBATCHEXT))
+else
+ZIPPATHSEP=/
+endif
+ZIPCMD_CDPACK:=cd $(subst /,$(ZIPPATHSEP),$(PACKDIR))
+ZIPCMD_CDBASE:=cd $(subst /,$(ZIPPATHSEP),$(BASEDIR))
+ifdef USETAR
+ZIPDESTFILE:=$(DIST_DESTDIR)/$(FULLZIPNAME)$(TAREXT)
+ZIPCMD_ZIP:=$(TARPROG) c$(TAROPT)f $(ZIPDESTFILE) *
+else
+ZIPDESTFILE:=$(DIST_DESTDIR)/$(FULLZIPNAME)$(ZIPEXT)
+ZIPCMD_ZIP:=$(subst /,$(ZIPPATHSEP),$(ZIPPROG)) -Dr $(ZIPOPT) $(ZIPDESTFILE) *
+endif
+fpc_zipinstall:
+ $(MAKE) $(ZIPTARGET) INSTALL_PREFIX=$(PACKDIR) ZIPINSTALL=1
+ $(MKDIR) $(DIST_DESTDIR)
+ $(DEL) $(ZIPDESTFILE)
+ifdef USEZIPWRAPPER
+ifneq ($(ECHOREDIR),echo)
+ $(ECHOREDIR) -e "$(subst \,\\,$(ZIPCMD_CDPACK))" > $(ZIPWRAPPER)
+ $(ECHOREDIR) -e "$(subst \,\\,$(ZIPCMD_ZIP))" >> $(ZIPWRAPPER)
+ $(ECHOREDIR) -e "$(subst \,\\,$(ZIPCMD_CDBASE))" >> $(ZIPWRAPPER)
+else
+ echo $(ZIPCMD_CDPACK) > $(ZIPWRAPPER)
+ echo $(ZIPCMD_ZIP) >> $(ZIPWRAPPER)
+ echo $(ZIPCMD_CDBASE) >> $(ZIPWRAPPER)
+endif
+ifdef inUnix
+ /bin/sh $(ZIPWRAPPER)
+else
+ifdef RUNBATCH
+ $(RUNBATCH) $(ZIPWRAPPER)
+else
+ $(ZIPWRAPPER)
+endif
+endif
+ $(DEL) $(ZIPWRAPPER)
+else
+ $(ZIPCMD_CDPACK) ; $(ZIPCMD_ZIP) ; $(ZIPCMD_CDBASE)
+endif
+ $(DELTREE) $(PACKDIR)
+fpc_zipsourceinstall:
+ $(MAKE) fpc_zipinstall ZIPTARGET=sourceinstall ZIPSUFFIX=$(ZIPSOURCESUFFIX)
+fpc_zipexampleinstall:
+ifdef HASEXAMPLES
+ $(MAKE) fpc_zipinstall ZIPTARGET=exampleinstall ZIPSUFFIX=$(ZIPEXAMPLESUFFIX)
+endif
+fpc_zipdistinstall:
+ $(MAKE) fpc_zipinstall ZIPTARGET=distinstall
+.PHONY: fpc_clean fpc_cleanall fpc_distclean
+ifdef EXEFILES
+override CLEANEXEFILES:=$(addprefix $(TARGETDIRPREFIX),$(CLEANEXEFILES))
+override CLEANEXEDBGFILES:=$(addprefix $(TARGETDIRPREFIX),$(CLEANEXEDBGFILES))
+endif
+ifdef CLEAN_PROGRAMS
+override CLEANEXEFILES+=$(addprefix $(TARGETDIRPREFIX),$(addsuffix $(EXEEXT), $(CLEAN_PROGRAMS)))
+override CLEANEXEDBGFILES+=$(addprefix $(TARGETDIRPREFIX),$(addsuffix $(EXEDBGEXT), $(CLEAN_PROGRAMS)))
+endif
+ifdef CLEAN_UNITS
+override CLEANPPUFILES+=$(addsuffix $(PPUEXT),$(CLEAN_UNITS))
+endif
+ifdef CLEANPPUFILES
+override CLEANPPULINKFILES:=$(subst $(PPUEXT),$(OEXT),$(CLEANPPUFILES)) $(addprefix $(STATICLIBPREFIX),$(subst $(PPUEXT),$(STATICLIBEXT),$(CLEANPPUFILES))) $(addprefix $(IMPORTLIBPREFIX),$(subst $(PPUEXT),$(STATICLIBEXT),$(CLEANPPUFILES)))
+ifdef DEBUGSYMEXT
+override CLEANPPULINKFILES+=$(subst $(PPUEXT),$(DEBUGSYMEXT),$(CLEANPPUFILES))
+endif
+override CLEANPPUFILES:=$(addprefix $(UNITTARGETDIRPREFIX),$(CLEANPPUFILES))
+override CLEANPPULINKFILES:=$(wildcard $(addprefix $(UNITTARGETDIRPREFIX),$(CLEANPPULINKFILES)))
+endif
+fpc_clean: $(CLEANTARGET)
+ifdef CLEANEXEFILES
+ -$(DEL) $(CLEANEXEFILES)
+endif
+ifdef CLEANEXEDBGFILES
+ -$(DELTREE) $(CLEANEXEDBGFILES)
+endif
+ifdef CLEANPPUFILES
+ -$(DEL) $(CLEANPPUFILES)
+endif
+ifneq ($(CLEANPPULINKFILES),)
+ -$(DEL) $(CLEANPPULINKFILES)
+endif
+ifdef CLEANRSTFILES
+ -$(DEL) $(addprefix $(UNITTARGETDIRPREFIX),$(CLEANRSTFILES))
+endif
+ifdef CLEAN_FILES
+ -$(DEL) $(CLEAN_FILES)
+endif
+ifdef LIB_NAME
+ -$(DEL) $(LIB_NAME) $(LIB_FULLNAME)
+endif
+ -$(DEL) $(FPCMADE) Package.fpc $(PPAS) script.res link.res $(FPCEXTFILE) $(REDIRFILE)
+ -$(DEL) *$(ASMEXT) *_ppas$(BATCHEXT)
+fpc_cleanall: $(CLEANTARGET)
+ifdef CLEANEXEFILES
+ -$(DEL) $(CLEANEXEFILES)
+endif
+ifdef COMPILER_UNITTARGETDIR
+ifdef CLEANPPUFILES
+ -$(DEL) $(CLEANPPUFILES)
+endif
+ifneq ($(CLEANPPULINKFILES),)
+ -$(DEL) $(CLEANPPULINKFILES)
+endif
+ifdef CLEANRSTFILES
+ -$(DEL) $(addprefix $(UNITTARGETDIRPREFIX),$(CLEANRSTFILES))
+endif
+endif
+ifdef CLEAN_FILES
+ -$(DEL) $(CLEAN_FILES)
+endif
+ -$(DELTREE) units
+ -$(DEL) *$(OEXT) *$(PPUEXT) *$(RSTEXT) *$(ASMEXT) *$(STATICLIBEXT) *$(SHAREDLIBEXT) *$(PPLEXT)
+ifneq ($(PPUEXT),.ppu)
+ -$(DEL) *.o *.ppu *.a
+endif
+ -$(DELTREE) *$(SMARTEXT)
+ -$(DEL) fpcmade.* Package.fpc $(PPAS) script.res link.res $(FPCEXTFILE) $(REDIRFILE)
+ -$(DEL) *_ppas$(BATCHEXT)
+ifdef AOUTEXT
+ -$(DEL) *$(AOUTEXT)
+endif
+ifdef DEBUGSYMEXT
+ -$(DEL) *$(DEBUGSYMEXT)
+endif
+fpc_distclean: cleanall
+.PHONY: fpc_baseinfo
+override INFORULES+=fpc_baseinfo
+fpc_baseinfo:
+ @$(ECHO)
+ @$(ECHO) == Package info ==
+ @$(ECHO) Package Name..... $(PACKAGE_NAME)
+ @$(ECHO) Package Version.. $(PACKAGE_VERSION)
+ @$(ECHO)
+ @$(ECHO) == Configuration info ==
+ @$(ECHO)
+ @$(ECHO) FPC.......... $(FPC)
+ @$(ECHO) FPC Version.. $(FPC_VERSION)
+ @$(ECHO) Source CPU... $(CPU_SOURCE)
+ @$(ECHO) Target CPU... $(CPU_TARGET)
+ @$(ECHO) Source OS.... $(OS_SOURCE)
+ @$(ECHO) Target OS.... $(OS_TARGET)
+ @$(ECHO) Full Source.. $(FULL_SOURCE)
+ @$(ECHO) Full Target.. $(FULL_TARGET)
+ @$(ECHO) SourceSuffix. $(SOURCESUFFIX)
+ @$(ECHO) TargetSuffix. $(TARGETSUFFIX)
+ @$(ECHO) FPC fpmake... $(FPCFPMAKE)
+ @$(ECHO)
+ @$(ECHO) == Directory info ==
+ @$(ECHO)
+ @$(ECHO) Required pkgs... $(REQUIRE_PACKAGES)
+ @$(ECHO)
+ @$(ECHO) Basedir......... $(BASEDIR)
+ @$(ECHO) FPCDir.......... $(FPCDIR)
+ @$(ECHO) CrossBinDir..... $(CROSSBINDIR)
+ @$(ECHO) UnitsDir........ $(UNITSDIR)
+ @$(ECHO) PackagesDir..... $(PACKAGESDIR)
+ @$(ECHO)
+ @$(ECHO) GCC library..... $(GCCLIBDIR)
+ @$(ECHO) Other library... $(OTHERLIBDIR)
+ @$(ECHO)
+ @$(ECHO) == Tools info ==
+ @$(ECHO)
+ @$(ECHO) As........ $(AS)
+ @$(ECHO) Ld........ $(LD)
+ @$(ECHO) Ar........ $(AR)
+ @$(ECHO) Rc........ $(RC)
+ @$(ECHO)
+ @$(ECHO) Mv........ $(MVPROG)
+ @$(ECHO) Cp........ $(CPPROG)
+ @$(ECHO) Rm........ $(RMPROG)
+ @$(ECHO) GInstall.. $(GINSTALL)
+ @$(ECHO) Echo...... $(ECHO)
+ @$(ECHO) Shell..... $(SHELL)
+ @$(ECHO) Date...... $(DATE)
+ @$(ECHO) FPCMake... $(FPCMAKE)
+ @$(ECHO) PPUMove... $(PPUMOVE)
+ @$(ECHO) Zip....... $(ZIPPROG)
+ @$(ECHO)
+ @$(ECHO) == Object info ==
+ @$(ECHO)
+ @$(ECHO) Target Loaders........ $(TARGET_LOADERS)
+ @$(ECHO) Target Units.......... $(TARGET_UNITS)
+ @$(ECHO) Target Implicit Units. $(TARGET_IMPLICITUNITS)
+ @$(ECHO) Target Programs....... $(TARGET_PROGRAMS)
+ @$(ECHO) Target Dirs........... $(TARGET_DIRS)
+ @$(ECHO) Target Examples....... $(TARGET_EXAMPLES)
+ @$(ECHO) Target ExampleDirs.... $(TARGET_EXAMPLEDIRS)
+ @$(ECHO)
+ @$(ECHO) Clean Units......... $(CLEAN_UNITS)
+ @$(ECHO) Clean Files......... $(CLEAN_FILES)
+ @$(ECHO)
+ @$(ECHO) Install Units....... $(INSTALL_UNITS)
+ @$(ECHO) Install Files....... $(INSTALL_FILES)
+ @$(ECHO)
+ @$(ECHO) == Install info ==
+ @$(ECHO)
+ @$(ECHO) DateStr.............. $(DATESTR)
+ @$(ECHO) ZipName.............. $(ZIPNAME)
+ @$(ECHO) ZipPrefix............ $(ZIPPREFIX)
+ @$(ECHO) ZipCrossPrefix....... $(ZIPCROSSPREFIX)
+ @$(ECHO) ZipSuffix............ $(ZIPSUFFIX)
+ @$(ECHO) FullZipName.......... $(FULLZIPNAME)
+ @$(ECHO) Install FPC Package.. $(INSTALL_FPCPACKAGE)
+ @$(ECHO)
+ @$(ECHO) Install base dir..... $(INSTALL_BASEDIR)
+ @$(ECHO) Install binary dir... $(INSTALL_BINDIR)
+ @$(ECHO) Install library dir.. $(INSTALL_LIBDIR)
+ @$(ECHO) Install units dir.... $(INSTALL_UNITDIR)
+ @$(ECHO) Install source dir... $(INSTALL_SOURCEDIR)
+ @$(ECHO) Install doc dir...... $(INSTALL_DOCDIR)
+ @$(ECHO) Install example dir.. $(INSTALL_EXAMPLEDIR)
+ @$(ECHO) Install data dir..... $(INSTALL_DATADIR)
+ @$(ECHO)
+ @$(ECHO) Dist destination dir. $(DIST_DESTDIR)
+ @$(ECHO) Dist zip name........ $(DIST_ZIPNAME)
+ @$(ECHO)
+.PHONY: fpc_info
+fpc_info: $(INFORULES)
+.PHONY: fpc_makefile fpc_makefiles fpc_makefile_sub1 fpc_makefile_sub2 \
+ fpc_makefile_dirs
+fpc_makefile:
+ $(FPCMAKE) -w -T$(OS_TARGET) Makefile.fpc
+fpc_makefile_sub1:
+ifdef TARGET_DIRS
+ $(FPCMAKE) -w -T$(OS_TARGET) $(addsuffix /Makefile.fpc,$(TARGET_DIRS))
+endif
+ifdef TARGET_EXAMPLEDIRS
+ $(FPCMAKE) -w -T$(OS_TARGET) $(addsuffix /Makefile.fpc,$(TARGET_EXAMPLEDIRS))
+endif
+fpc_makefile_sub2: $(addsuffix _makefile_dirs,$(TARGET_DIRS) $(TARGET_EXAMPLEDIRS))
+fpc_makefile_dirs: fpc_makefile_sub1 fpc_makefile_sub2
+fpc_makefiles: fpc_makefile fpc_makefile_dirs
+ifeq ($(FULL_TARGET),i386-linux)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),i386-go32v2)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),i386-win32)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),i386-os2)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),i386-freebsd)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),i386-beos)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),i386-haiku)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),i386-netbsd)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),i386-solaris)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),i386-qnx)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),i386-netware)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),i386-openbsd)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),i386-wdosx)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),i386-darwin)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),i386-emx)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),i386-watcom)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),i386-netwlibc)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),i386-wince)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),i386-embedded)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),i386-symbian)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),i386-nativent)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),i386-iphonesim)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),m68k-linux)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),m68k-freebsd)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),m68k-netbsd)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),m68k-amiga)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),m68k-atari)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),m68k-openbsd)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),m68k-palmos)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),m68k-embedded)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),powerpc-linux)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),powerpc-netbsd)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),powerpc-amiga)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),powerpc-macos)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),powerpc-darwin)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),powerpc-morphos)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),powerpc-embedded)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),powerpc-wii)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),sparc-linux)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),sparc-netbsd)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),sparc-solaris)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),sparc-embedded)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),x86_64-linux)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),x86_64-freebsd)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),x86_64-solaris)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),x86_64-darwin)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),x86_64-win64)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),x86_64-embedded)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),arm-linux)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),arm-palmos)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),arm-darwin)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),arm-wince)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),arm-gba)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),arm-nds)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),arm-embedded)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),arm-symbian)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),powerpc64-linux)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),powerpc64-darwin)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),powerpc64-embedded)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),avr-embedded)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),armeb-linux)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),armeb-embedded)
+TARGET_DIRS_UTILS=1
+endif
+ifeq ($(FULL_TARGET),mipsel-linux)
+TARGET_DIRS_UTILS=1
+endif
+ifdef TARGET_DIRS_UTILS
+utils_all:
+ $(MAKE) -C utils all
+utils_debug:
+ $(MAKE) -C utils debug
+utils_smart:
+ $(MAKE) -C utils smart
+utils_release:
+ $(MAKE) -C utils release
+utils_units:
+ $(MAKE) -C utils units
+utils_examples:
+ $(MAKE) -C utils examples
+utils_shared:
+ $(MAKE) -C utils shared
+utils_install:
+ $(MAKE) -C utils install
+utils_sourceinstall:
+ $(MAKE) -C utils sourceinstall
+utils_exampleinstall:
+ $(MAKE) -C utils exampleinstall
+utils_distinstall:
+ $(MAKE) -C utils distinstall
+utils_zipinstall:
+ $(MAKE) -C utils zipinstall
+utils_zipsourceinstall:
+ $(MAKE) -C utils zipsourceinstall
+utils_zipexampleinstall:
+ $(MAKE) -C utils zipexampleinstall
+utils_zipdistinstall:
+ $(MAKE) -C utils zipdistinstall
+utils_clean:
+ $(MAKE) -C utils clean
+utils_distclean:
+ $(MAKE) -C utils distclean
+utils_cleanall:
+ $(MAKE) -C utils cleanall
+utils_info:
+ $(MAKE) -C utils info
+utils_makefiles:
+ $(MAKE) -C utils makefiles
+utils:
+ $(MAKE) -C utils all
+.PHONY: utils_all utils_debug utils_smart utils_release utils_units utils_examples utils_shared utils_install utils_sourceinstall utils_exampleinstall utils_distinstall utils_zipinstall utils_zipsourceinstall utils_zipexampleinstall utils_zipdistinstall utils_clean utils_distclean utils_cleanall utils_info utils_makefiles utils
+endif
+ifndef DIFF
+DIFF:=$(strip $(wildcard $(addsuffix /diff$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(DIFF),)
+DIFF= __missing_command_DIFF
+else
+DIFF:=$(firstword $(DIFF))
+endif
+endif
+export DIFF
+ifndef CMP
+CMP:=$(strip $(wildcard $(addsuffix /cmp$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(CMP),)
+CMP= __missing_command_CMP
+else
+CMP:=$(firstword $(CMP))
+endif
+endif
+export CMP
+debug: fpc_debug
+smart: fpc_smart
+release: fpc_release
+units: fpc_units $(addsuffix _units,$(TARGET_DIRS))
+examples: $(addsuffix _examples,$(TARGET_DIRS))
+shared: fpc_shared
+sourceinstall: fpc_sourceinstall
+exampleinstall: fpc_exampleinstall $(addsuffix _exampleinstall,$(TARGET_DIRS))
+distinstall: fpc_distinstall
+zipinstall: fpc_zipinstall
+zipsourceinstall: fpc_zipsourceinstall
+zipexampleinstall: fpc_zipexampleinstall $(addsuffix _zipexampleinstall,$(TARGET_DIRS))
+zipdistinstall: fpc_zipdistinstall
+cleanall: fpc_cleanall $(addsuffix _cleanall,$(TARGET_DIRS))
+info: fpc_info
+makefiles: fpc_makefiles
+.PHONY: debug smart release units examples shared sourceinstall exampleinstall distinstall zipinstall zipsourceinstall zipexampleinstall zipdistinstall cleanall info makefiles
+ifneq ($(wildcard fpcmake.loc),)
+include fpcmake.loc
+endif
+ifeq ($(OS_TARGET),win32)
+USE_CMP_FOR_DIFF=1
+endif
+ifeq ($(OS_TARGET),win64)
+USE_CMP_FOR_DIFF=1
+endif
+ifdef USE_CMP_FOR_DIFF
+ifdef CMP
+override DIFF:=$(CMP) -i218
+endif
+endif
+ifeq ($(findstring 2.4.,$(FPC_VERSION)),)
+ifndef ALLOW_WARNINGS
+override LOCALOPT+=-Sew
+endif
+endif
+override COMPILER+=$(LOCALOPT)
+PASDOC:=$(strip $(wildcard $(addsuffix /pasdoc.exe,$(SEARCHPATH))))
+ifeq ($(PASDOC),)
+PASDOC:=$(strip $(wildcard $(addsuffix /pasdoc,$(SEARCHPATH))))
+endif
+ifeq ($(PASDOC),)
+PASDOC:=../projects/pasdoc/bin/pasdoc
+else
+PASDOC:=$(firstword $(PASDOC))
+endif
+ifndef EXENAME
+EXENAME=ppc$(CPUSUF)$(EXEEXT)
+endif
+PPEXENAME=pp$(EXEEXT)
+TEMPNAME=ppc$(SRCEXEEXT)
+PPCROSSNAME=ppcross$(CPUSUF)$(SRCEXEEXT)
+TEMPNAME1=ppc1$(EXEEXT)
+TEMPNAME2=ppc2$(EXEEXT)
+TEMPNAME3=ppc3$(EXEEXT)
+TEMPWPONAME1=ppcwpo1$(EXEEXT)
+TEMPWPONAME2=ppcwpo2$(EXEEXT)
+MAKEDEP=ppdep$(EXEEXT)
+MSG2INC=./msg2inc$(EXEEXT)
+ifdef CROSSINSTALL
+INSTALLEXEFILE=$(PPCROSSNAME)
+else
+INSTALLEXEFILE=$(EXENAME)
+endif
+PPC_TARGETS=i386 m68k powerpc sparc arm armeb x86_64 powerpc64 alpha vis ia64 mips mipsel avr
+INSTALL_TARGETS=$(addsuffix _exe_install,$(sort $(CYCLETARGETS) $(PPC_TARGETS)))
+.PHONY: $(PPC_TARGETS) $(INSTALL_TARGETS)
+$(PPC_TARGETS):
+ $(MAKE) PPC_TARGET=$@ CPU_UNITDIR=$@ all
+$(INSTALL_TARGETS):
+ $(MAKE) all exeinstall PPC_TARGET=$(subst _exe_install,,$@) CPU_UNITDIR=$(subst _exe_install,,$@)
+alltargets: $(ALLTARGETS)
+.NOTPARALLEL:
+.PHONY: all compiler echotime ppuclean execlean clean distclean
+all: compiler $(addsuffix _all,$(TARGET_DIRS))
+compiler: $(COMPILER_UNITTARGETDIR) $(COMPILER_TARGETDIR) $(EXENAME)
+ifeq ($(MAKELEVEL),0)
+ifndef STARTTIME
+ifdef DATE
+STARTTIME:=$(shell $(DATE) +%T)
+else
+STARTTIME:=unknown
+endif
+endif
+endif
+export STARTTIME
+ifdef DATE
+ENDTIME=$(shell $(DATE) +%T)
+else
+ENDTIME:=unknown
+endif
+echotime:
+ @echo Start $(STARTTIME) now $(ENDTIME)
+ppuclean:
+ -$(DEL) *$(OEXT) *$(PPUEXT) *$(RSTEXT) *$(ASMEXT) *$(STATICLIBEXT) *$(SHAREDLIBEXT) *$(PPLEXT)
+ -$(DEL) $(addsuffix /*$(PPUEXT),$(COMPILERSOURCEDIR))
+tempclean:
+ -$(DEL) $(PPCROSSNAME) $(TEMPNAME) $(TEMPNAME1) $(TEMPNAME2) $(TEMPNAME3) $(MSG2INC) pp1.wpo pp2.wpo
+execlean :
+ -$(DEL) ppc386$(EXEEXT) ppc68k$(EXEEXT) ppcx64$(EXEEXT) ppcppc$(EXEEXT) ppcsparc$(EXEEXT) ppcppc64$(EXEEXT) ppcarm$(EXEEXT) ppcmips$(EXEEXT) ppcmipsel$(EXEEXT) $(EXENAME) $(TEMPWPONAME1) $(TEMPWPONAME2)
+$(addsuffix _clean,$(ALLTARGETS)):
+ -$(DELTREE) $(addprefix $(subst _clean,,$@),/units)
+ -$(DEL) $(addprefix $(subst _clean,,$@)/,*$(OEXT) *$(PPUEXT) *$(RSTEXT) *$(ASMEXT) *$(STATICLIBEXT) *$(SHAREDLIBEXT) *$(PPLEXT))
+ -$(DEL) $(addprefix $(subst _clean,,$@)/,ppc386$(EXEEXT) ppc68k$(EXEEXT) ppcx64$(EXEEXT) ppcppc$(EXEEXT) ppcsparc$(EXEEXT) ppcppc64$(EXEEXT) ppcarm$(EXEEXT) ppcmips$(EXEEXT) ppcmipsel$(EXEEXT) $(EXENAME))
+cycleclean: cleanall $(addsuffix _clean,$(CPC_TARGET))
+ -$(DEL) $(EXENAME)
+clean: tempclean execlean cleanall $(addsuffix _clean,$(CPC_TARGET)) $(addsuffix _clean,$(TARGET_DIRS))
+distclean: tempclean execlean cleanall $(addsuffix _clean,$(ALLTARGETS)) $(addsuffix _distclean,$(TARGET_DIRS))
+$(MSG2INC): $(COMPILER_TARGETDIR) $(COMPILER_UNITTARGETDIR) $(COMPILERUTILSDIR)/msg2inc.pp
+ $(COMPILER) -FE. $(COMPILERUTILSDIR)/msg2inc.pp
+msgtxt.inc: $(MSGFILE)
+ $(MAKE) $(MSG2INC)
+ $(MSG2INC) $(MSGFILE) msg msg
+msg: msgtxt.inc
+insdatx86 : $(COMPILER_UNITTARGETDIR) x86/x86ins.dat
+ $(COMPILER) -FE$(COMPILERUTILSDIR) $(COMPILERUTILSDIR)/mkx86ins.pp
+ cd x86 && ..$(PATHSEP)utils$(PATHSEP)mkx86ins$(SRCEXEEXT) && mv -f *.inc ../i386
+ cd x86 && ..$(PATHSEP)utils$(PATHSEP)mkx86ins$(SRCEXEEXT) x86_64 && mv -f *.inc ../x86_64
+ $(COMPILER) -FE$(COMPILERUTILSDIR) $(COMPILERUTILSDIR)/mkx86reg.pp
+ cd x86 && ..$(PATHSEP)utils$(PATHSEP)mkx86reg$(SRCEXEEXT)
+ mv -f x86/r386*.inc i386
+ cd x86 && ..$(PATHSEP)utils$(PATHSEP)mkx86reg$(SRCEXEEXT) x86_64
+ mv -f x86/r8664*.inc x86_64
+insdatarm : arm/armins.dat
+ $(COMPILER) -FE$(COMPILERUTILSDIR) $(COMPILERUTILSDIR)/mkarmins.pp
+ cd arm && ..$(PATHSEP)utils$(PATHSEP)mkarmins$(SRCEXEEXT)
+insdat: insdatx86 insdatarm
+regdatarm : arm/armreg.dat
+ $(COMPILER) -FE$(COMPILERUTILSDIR) $(COMPILERUTILSDIR)/mkarmreg.pp
+ cd arm && ..$(PATHSEP)utils$PATHSEP)mkarmreg$(SRCEXEEXT)
+revision.inc :
+ifneq ($(REVSTR),)
+ifdef USEZIPWRAPPER
+ifneq ($(ECHOREDIR),echo)
+ $(ECHOREDIR) "'$(REVSTR)'" > revision.inc
+else
+ $(ECHOREDIR) '$(REVSTR)' > revision.inc
+endif
+else
+ $(ECHOREDIR) "'$(REVSTR)'" > revision.inc
+endif
+else
+ $(MAKE) revision.inc REVINC=force
+endif
+.PHONY : revision
+revision :
+ $(DEL) revision.inc
+ $(MAKE) revision.inc
+$(EXENAME) : $(wildcard *.pas) $(wildcard *.inc) msg \
+ $(wildcard systems/*.pas) $(wilcard systems/*.inc) \
+ $(wildcard $(CPC_TARGET)/*.pas) $(wildcard $(CPC_TARGET)/*.inc) \
+ $(COMPILER_UNITTARGETDIR) $(COMPILER_TARGETDIR)
+ifneq ($(REVSTR),)
+ifdef USEZIPWRAPPER
+ifneq ($(ECHOREDIR),echo)
+ $(ECHOREDIR) "'$(REVSTR)'" > revision.inc
+else
+ $(ECHOREDIR) '$(REVSTR)' > revision.inc
+endif
+else
+ $(ECHOREDIR) "'$(REVSTR)'" > revision.inc
+endif
+ $(COMPILER) version.pas
+endif
+ $(COMPILER) pp.pas
+ $(EXECPPAS)
+ $(MOVE) $(COMPILER_TARGETDIR)/$(PPEXENAME) $(EXENAME)
+ifeq ($(CPU_SOURCE),$(PPC_TARGET))
+ifeq ($(OS_SOURCE),$(OS_TARGET))
+ifndef NOWPOCYCLE
+ifdef RELEASE
+DOWPOCYCLE=1
+wpocycle:
+ $(RM) $(EXENAME)
+ $(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME3)' 'OPT=$(LOCALOPT) $(OPTWPOCOLLECT)' compiler
+ $(RM) $(EXENAME)
+ $(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME3)' 'OPT=$(RTLOPT) $(OPTWPOPERFORM)' rtlclean rtl
+ $(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME3)' 'OPT=$(LOCALOPT) $(OPTWPOPERFORM) $(subst pp1.wpo,pp2.wpo,$(OPTWPOCOLLECT))' $(addsuffix _clean,$(ALLTARGETS)) compiler
+ $(MOVE) $(EXENAME) $(TEMPWPONAME1)
+ $(MAKE) 'FPC=$(BASEDIR)/$(TEMPWPONAME1)' 'OPT=$(RTLOPT) $(subst pp1.wpo,pp2.wpo,$(OPTWPOPERFORM))' rtlclean rtl
+ $(MAKE) 'FPC=$(BASEDIR)/$(TEMPWPONAME1)' 'OPT=$(LOCALOPT) $(subst pp1.wpo,pp2.wpo,$(OPTWPOPERFORM))' $(addsuffix _clean,$(ALLTARGETS)) compiler
+ $(COPY) $(EXENAME) $(TEMPWPONAME2)
+endif
+endif
+ifndef DOWPOCYCLE
+wpocycle:
+endif
+ifdef DIFF
+ifdef OLDFPC
+ifneq ($(OS_TARGET),darwin)
+DIFFRESULT:=$(shell $(DIFF) $(OLDFPC) $(FPC))
+else
+DIFFRESULT:=$(shell cp $(OLDFPC) $(OLDFPC).tmp; cp $(FPC) $(FPC).tmp; strip -no_uuid $(OLDFPC).tmp; strip -no_uuid $(FPC).tmp; $(DIFF) $(OLDFPC).tmp $(FPC).tmp; rm $(OLDFPC).tmp $(FPC).tmp)
+endif
+else
+DIFFRESULT=Not equal
+endif
+else
+DIFFRESULT=No diff program
+endif
+ifndef DIFFRESULT
+next :
+ @echo $(OLDFPC) and $(FPC) are equal
+ $(COPY) $(FPC) $(EXENAME)
+else
+next :
+ $(MAKE) rtlclean rtl
+ $(MAKE) cycleclean compiler
+ $(MAKE) echotime
+endif
+$(TEMPNAME1) :
+ $(MAKE) 'OLDFPC=' next
+ -$(DEL) $(TEMPNAME1)
+ $(MOVE) $(EXENAME) $(TEMPNAME1)
+$(TEMPNAME2) : $(TEMPNAME1)
+ $(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME1)' 'OLDFPC=' next
+ -$(DEL) $(TEMPNAME2)
+ $(MOVE) $(EXENAME) $(TEMPNAME2)
+$(TEMPNAME3) : $(TEMPNAME2)
+ $(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME2)' 'OLDFPC=$(BASEDIR)/$(TEMPNAME1)' next
+ -$(DEL) $(TEMPNAME3)
+ $(MOVE) $(EXENAME) $(TEMPNAME3)
+cycle:
+ $(MAKE) tempclean $(TEMPNAME3)
+ $(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME3)' 'OLDFPC=$(BASEDIR)/$(TEMPNAME2)' next
+ $(DIFF) $(TEMPNAME3) $(EXENAME)
+ $(MAKE) $(addsuffix _all,$(TARGET_DIRS)) 'FPC=$(BASEDIR)/$(EXENAME)'
+ $(MAKE) wpocycle
+ $(MAKE) echotime
+else
+cycle:
+ $(MAKE) OS_TARGET=$(OS_SOURCE) CROSSBINDIR= BINUTILSPREFIX= CROSSCYCLEBOOTSTRAP=1 rtlclean rtl
+ $(MAKE) OS_TARGET=$(OS_SOURCE) EXENAME=$(TEMPNAME) CROSSBINDIR= BINUTILSPREFIX= CROSSCYCLEBOOTSTRAP=1 cycleclean compiler
+ $(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME)' OS_TARGET=$(OS_SOURCE) CROSSBINDIR= BINUTILSPREFIX= CROSSCYCLEBOOTSTRAP=1 rtlclean rtl
+ $(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME)' OS_TARGET=$(OS_SOURCE) EXENAME=$(PPCROSSNAME) CROSSBINDIR= BINUTILSPREFIX= CROSSCYCLEBOOTSTRAP=1 cycleclean compiler
+ifndef CROSSINSTALL
+ $(MAKE) 'FPC=$(BASEDIR)/$(PPCROSSNAME)' rtlclean rtl
+ifneq ($(OS_TARGET),embedded)
+ifneq ($(OS_TARGET),gba)
+ $(MAKE) 'FPC=$(BASEDIR)/$(PPCROSSNAME)' cycleclean compiler
+endif
+endif
+endif
+endif
+else
+cycle: override FPC=
+cycle:
+ $(MAKE) OS_TARGET=$(OS_SOURCE) CPU_TARGET=$(CPU_SOURCE) CROSSBINDIR= BINUTILSPREFIX= CROSSCYCLEBOOTSTRAP=1 rtlclean rtl
+ $(MAKE) OS_TARGET=$(OS_SOURCE) CPU_TARGET=$(CPU_SOURCE) EXENAME=$(TEMPNAME) CROSSBINDIR= BINUTILSPREFIX= CROSSCYCLEBOOTSTRAP=1 cycleclean compiler
+ $(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME)' OS_TARGET=$(OS_SOURCE) CPU_TARGET=$(CPU_SOURCE) CROSSBINDIR= BINUTILSPREFIX= CROSSCYCLEBOOTSTRAP=1 rtlclean rtl
+ $(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME)' OS_TARGET=$(OS_SOURCE) CPU_TARGET=$(CPU_SOURCE) PPC_TARGET=$(CPU_TARGET) EXENAME=$(PPCROSSNAME) CROSSBINDIR= BINUTILSPREFIX= CROSSCYCLEBOOTSTRAP=1 cycleclean compiler
+ifndef CROSSINSTALL
+ $(MAKE) 'FPC=$(BASEDIR)/$(PPCROSSNAME)' 'OPT=$(OPT) $(CROSSOPT)' rtlclean rtl
+ifneq ($(OS_TARGET),embedded)
+ifneq ($(OS_TARGET),gba)
+ $(MAKE) 'FPC=$(BASEDIR)/$(PPCROSSNAME)' 'OPT=$(OPT) $(CROSSOPT)' cycleclean compiler
+endif
+endif
+endif
+endif
+cycledep:
+ $(MAKE) cycle USEDEPEND=1
+extcycle:
+ $(MAKE) cycle OPT='-n -OG2p3 -glttt -CRriot -dEXTDEBUG'
+cvstest:
+ $(MAKE) cycle 'LOCALOPT=-n -Se' 'RTLOPT=-n -Se'
+full: fullcycle
+fullcycle:
+ $(MAKE) cycle
+ $(MAKE) ppuclean
+ $(MAKE) $(filter-out $(PPC_TARGET),$(CYCLETARGETS)) 'FPC=$(BASEDIR)/$(EXENAME)'
+htmldocs:
+ $(PASDOC) -p -h -o html$(PATHSEP)$(PPC_TARGET) -d fpc -d gdb -d $(PPC_TARGET) -u $(PPC_TARGET) $(PPC_TARGET)$(PATHSEP)*.pas systems$(PATHSEP)*.pas *.pas
+.PHONY: quickinstall exeinstall install installsym
+MSGINSTALLDIR=$(INSTALL_BASEDIR)/msg
+override PPEXEFILE:=$(wildcard $(EXENAME))
+ifdef UNIXHier
+PPCCPULOCATION=$(INSTALL_BASEDIR)
+else
+PPCCPULOCATION=$(INSTALL_BINDIR)
+endif
+quickinstall: $(addsuffix _install,$(TARGET_DIRS))
+ $(MAKE) exeinstall
+exeinstall:
+ifneq ($(INSTALLEXEFILE),)
+ifdef UPXPROG
+ -$(UPXPROG) $(INSTALLEXEFILE)
+endif
+ $(MKDIR) $(PPCCPULOCATION)
+ $(INSTALLEXE) $(INSTALLEXEFILE) $(PPCCPULOCATION)/$(INSTALLEXEFILE)
+endif
+fullinstall:
+ $(MAKE) $(addsuffix _exe_install,$(filter-out $(PPC_TARGET),$(CYCLETARGETS)))
+install: quickinstall
+ifndef CROSSINSTALL
+ifdef UNIXHier
+ $(MKDIR) $(INSTALL_BASEDIR)
+ $(INSTALLEXE) $(COMPILERUTILSDIR)/samplecfg $(INSTALL_BASEDIR)/samplecfg
+endif
+ $(MKDIR) $(MSGINSTALLDIR)
+ $(INSTALL) $(MSGFILES) $(MSGINSTALLDIR)
+endif
+installsymlink: install
+ifneq ($(PPCCPULOCATION),$(INSTALL_BINDIR))
+ $(MKDIR) $(INSTALL_BINDIR)
+ ln -sf $(INSTALL_BASEDIR)/$(EXENAME) $(INSTALL_BINDIR)/$(EXENAME)
+endif
+.PHONY: rtl rtlclean rtlinstall
+rtl:
+ $(MAKE) -C $(PACKAGEDIR_RTL) 'OPT=$(RTLOPT)' all
+rtlclean:
+ $(MAKE) -C $(PACKAGEDIR_RTL) clean
+rtlinstall:
+ $(MAKE) -C $(PACKAGEDIR_RTL) install
+PPUDIR=$(COMPILER_UNITTARGETDIR)
+ALLPPUDIR=$(CPU_TARGET)/units/*
+PPULIST=$(wildcard $(PPUDIR)/*.ppu)
+PPULOGLIST=$(subst .ppu,.log-ppu,$(PPULIST))
+RTLPPUDIR=../rtl/units/$(FULL_TARGET)
+RTLPPULIST=$(wildcard $(RTLPPUDIR)/*.ppu)
+RTLPPULOGLIST=$(subst .ppu,.log-ppu,$(RTLPPULIST))
+.PHONY : ppulogs cleanppulogs rtlppulogs cleanrtlppulogs testppudump
+ppulogs : $(PPULOGLIST)
+rtlppulogs : $(RTLPPULOGLIST)
+vpath %.ppu $(PPUDIR) $(RTLPPUDIR) $(ALLPPUDIR)
+vpath %.log-ppu $(PPUDIR) $(RTLPPUDIR) $(ALLPPUDIR)
+%.log-ppu : %.ppu ./utils/ppudump$(EXEEXT)
+ .$(PATHSEP)utils$(PATHSEP)ppudump -VA -M $< > $@
+./utils/ppudump$(EXEEXT):
+ $(MAKE) -C $(COMPILERUTILSDIR) ppudump$(EXEEXT)
+ppuinfo :
+ echo PPU list is "$(PPULIST)"
+ echo PPULOG list is "$(PPULOGLIST)"
+cleanppulogs :
+ -$(RMPROG) $(PPULOGLIST)
+cleanrtlppulogs :
+ -$(RMPROG) $(RTLPPULOGLIST)
+testppudump :
+ $(MAKE) cleanrtlppulogs cleanppulogs ppulogs rtlppulogs
+localmake:=$(strip $(wildcard makefile.loc))
+ifdef localmake
+include ./$(localmake)
+endif
diff --git a/closures/compiler/Makefile.fpc b/closures/compiler/Makefile.fpc
new file mode 100644
index 0000000000..b3d7719a16
--- /dev/null
+++ b/closures/compiler/Makefile.fpc
@@ -0,0 +1,789 @@
+#
+# Makefile.fpc for Free Pascal Compiler
+#
+
+[package]
+name=compiler
+version=2.7.1
+
+[target]
+programs=pp
+dirs=utils
+
+[compiler]
+targetdir=.
+unittargetdir=$(CPU_UNITDIR)/units/$(FULL_TARGET)
+unitdir=$(COMPILERSOURCEDIR)
+includedir=$(CPC_TARGET)
+
+[require]
+packages=rtl
+tools=diff cmp
+
+[install]
+fpcpackage=y
+
+[default]
+fpcdir=..
+
+
+[prerules]
+# Don't export version it can change after the first compile
+unexport FPC_VERSION FPC_COMPILERINFO
+
+# Which platforms are ready for inclusion in the cycle
+CYCLETARGETS=i386 powerpc sparc arm x86_64 powerpc64 m68k armeb mipsel mips avr
+
+# All supported targets used for clean
+ALLTARGETS=$(CYCLETARGETS)
+
+# Allow ALPHA, POWERPC, POWERPC64, M68K, I386 defines for target cpu
+ifdef ALPHA
+PPC_TARGET=alpha
+endif
+ifdef POWERPC
+PPC_TARGET=powerpc
+endif
+ifdef POWERPC64
+PPC_TARGET=powerpc64
+endif
+ifdef SPARC
+PPC_TARGET=sparc
+endif
+ifdef M68K
+PPC_TARGET=m68k
+endif
+ifdef I386
+PPC_TARGET=i386
+endif
+ifdef X86_64
+PPC_TARGET=x86_64
+endif
+ifdef ARM
+PPC_TARGET=arm
+endif
+ifdef ARMEB
+PPC_TARGET=armeb
+endif
+ifdef MIPS
+PPC_TARGET=mips
+endif
+ifdef MIPSEL
+PPC_TARGET=mipsel
+endif
+ifdef AVR
+PPC_TARGET=avr
+endif
+
+# Default is to generate a compiler for the same
+# platform as CPU_TARGET (a native compiler)
+ifndef PPC_TARGET
+PPC_TARGET=$(CPU_TARGET)
+endif
+
+ifeq ($(PPC_TARGET),armeb)
+CPC_TARGET=arm
+else
+CPC_TARGET=$(PPC_TARGET)
+endif
+
+# Default is to generate a compiler for the same
+# target as OS_TARGET (a native compiler)
+ifndef PPC_OS
+PPC_OS=$(OS_TARGET)
+endif
+
+# Where to place the unit files.
+CPU_UNITDIR=$(CPC_TARGET)
+
+# RTL
+UTILSDIR=../utils
+
+# Directories containing compiler sources
+COMPILERSOURCEDIR=$(CPC_TARGET) systems
+
+# Utils used by compiler development/installation
+COMPILERUTILSDIR=utils
+
+# Default language for the compiler
+ifndef FPCLANG
+FPCLANG=e
+endif
+
+# Local options for the compiler only
+ifndef LOCALOPT
+LOCALOPT:=$(OPT)
+endif
+
+# Options for the RTL only when cycling
+ifndef RTLOPT
+RTLOPT:=$(OPT)
+endif
+
+# Make OPT empty. It is copied to LOCALOPT and RTLOPT
+override OPT=
+
+# Message files
+MSGFILES=$(wildcard msg/error*.msg)
+
+# ppcSUFFIX
+ifeq ($(CPC_TARGET),i386)
+CPUSUF=386
+endif
+ifeq ($(CPC_TARGET),alpha)
+CPUSUF=axp
+endif
+ifeq ($(CPC_TARGET),m68k)
+CPUSUF=68k
+endif
+ifeq ($(CPC_TARGET),powerpc)
+CPUSUF=ppc
+endif
+ifeq ($(CPC_TARGET),powerpc64)
+CPUSUF=ppc64
+endif
+ifeq ($(CPC_TARGET),sparc)
+CPUSUF=sparc
+endif
+ifeq ($(CPC_TARGET),x86_64)
+CPUSUF=x64
+endif
+ifeq ($(CPC_TARGET),arm)
+CPUSUF=arm
+endif
+ifeq ($(CPC_TARGET),mips)
+CPUSUF=mips
+endif
+ifeq ($(CPC_TARGET),mipsel)
+CPUSUF=mipsel
+endif
+ifeq ($(CPC_TARGET),avr)
+CPUSUF=avr
+endif
+
+# Do not define the default -d$(CPU_TARGET) because that
+# will conflict with our -d$(CPC_TARGET)
+NOCPUDEF=1
+
+# Default message file
+MSGFILE=msg/error$(FPCLANG).msg
+
+
+SVNVERSION:=$(wildcard $(addsuffix /svnversion$(SRCEXEEXT),$(SEARCHPATH)))
+# Check if revision.inc is present
+REVINC:=$(wildcard revision.inc)
+ifneq ($(REVINC),)
+# File revision.inc is present
+#Use it to compile version.pas unit
+override LOCALOPT+=-dREVINC
+# Automatically update revision.inc if
+# svnversion executable is available
+ifeq ($(REVSTR),)
+ifneq ($(SVNVERSION),)
+REVSTR:=$(shell $(SVNVERSION) -c .)
+export REVSTR
+else
+ifeq ($(REVINC),force)
+REVSTR:=exported
+export REVSTR
+endif
+endif
+endif
+endif
+
+# set correct defines (-d$(CPU_TARGET) is automatically added in makefile.fpc)
+override LOCALOPT+=-d$(CPC_TARGET) -dGDB -dBROWSERLOG
+
+# i386 specific
+ifeq ($(PPC_TARGET),i386)
+override LOCALOPT+=-Fux86
+endif
+
+# x86_64 specific
+ifeq ($(PPC_TARGET),x86_64)
+override LOCALOPT+=-Fux86
+endif
+
+# PowerPC specific
+ifeq ($(PPC_TARGET),powerpc)
+override LOCALOPT+=-Fuppcgen
+endif
+
+# PowerPC64 specific
+ifeq ($(PPC_TARGET),powerpc64)
+override LOCALOPT+=-Fuppcgen
+endif
+
+# m68k specific
+ifeq ($(PPC_TARGET),m68k)
+override LOCALOPT+=-dNOOPT
+endif
+
+# Sparc specific
+ifeq ($(PPC_TARGET),sparc)
+override LOCALOPT+=
+endif
+
+# m68k specific with low stack
+ifeq ($(PPC_TARGET),m68k)
+ifeq ($(OS_TARGET),amiga)
+override LOCALOPT+=-Ct
+endif
+endif
+
+# ARM specific
+ifeq ($(PPC_TARGET),arm)
+override LOCALOPT+=
+endif
+
+# mipsel specific
+ifeq ($(PPC_TARGET),mipsel)
+override LOCALOPT+=-Fumips
+endif
+
+
+OPTWPOCOLLECT=-OWdevirtcalls,optvmts -FW$(BASEDIR)/pp1.wpo
+OPTWPOPERFORM=-Owdevirtcalls,optvmts -Fw$(BASEDIR)/pp1.wpo
+# symbol liveness WPO requires nm, smart linking and no stripping (the latter
+# is forced by the Makefile when necessary)
+ifneq ($(findstring $(OS_TARGET),darwin linux freebsd solaris),)
+ifdef LINKSMART
+ifdef CREATESMART
+OPTWPOCOLLECT+=-OWsymbolliveness -Xs-
+OPTWPOPERFORM+=-Owsymbolliveness
+endif
+endif
+endif
+
+
+[rules]
+#####################################################################
+# Setup Targets
+#####################################################################
+
+ifeq ($(OS_TARGET),win32)
+USE_CMP_FOR_DIFF=1
+endif
+ifeq ($(OS_TARGET),win64)
+USE_CMP_FOR_DIFF=1
+endif
+
+ifdef USE_CMP_FOR_DIFF
+ifdef CMP
+override DIFF:=$(CMP) -i218
+endif
+endif
+
+# Use -Sew option by default
+# Allow disabling by setting ALLOW_WARNINGS=1
+ifeq ($(findstring 2.4.,$(FPC_VERSION)),)
+ifndef ALLOW_WARNINGS
+override LOCALOPT+=-Sew
+endif
+endif
+
+# Add Local options
+override COMPILER+=$(LOCALOPT)
+
+
+#####################################################################
+# PASDoc
+#####################################################################
+
+PASDOC:=$(strip $(wildcard $(addsuffix /pasdoc.exe,$(SEARCHPATH))))
+ifeq ($(PASDOC),)
+PASDOC:=$(strip $(wildcard $(addsuffix /pasdoc,$(SEARCHPATH))))
+endif
+ifeq ($(PASDOC),)
+PASDOC:=../projects/pasdoc/bin/pasdoc
+else
+PASDOC:=$(firstword $(PASDOC))
+endif
+
+
+#####################################################################
+# Setup os-independent filenames
+#####################################################################
+
+ifndef EXENAME
+EXENAME=ppc$(CPUSUF)$(EXEEXT)
+endif
+PPEXENAME=pp$(EXEEXT)
+TEMPNAME=ppc$(SRCEXEEXT)
+PPCROSSNAME=ppcross$(CPUSUF)$(SRCEXEEXT)
+TEMPNAME1=ppc1$(EXEEXT)
+TEMPNAME2=ppc2$(EXEEXT)
+TEMPNAME3=ppc3$(EXEEXT)
+TEMPWPONAME1=ppcwpo1$(EXEEXT)
+TEMPWPONAME2=ppcwpo2$(EXEEXT)
+MAKEDEP=ppdep$(EXEEXT)
+MSG2INC=./msg2inc$(EXEEXT)
+ifdef CROSSINSTALL
+INSTALLEXEFILE=$(PPCROSSNAME)
+else
+INSTALLEXEFILE=$(EXENAME)
+endif
+
+#####################################################################
+# CPU targets
+#####################################################################
+
+PPC_TARGETS=i386 m68k powerpc sparc arm armeb x86_64 powerpc64 alpha vis ia64 mips mipsel avr
+INSTALL_TARGETS=$(addsuffix _exe_install,$(sort $(CYCLETARGETS) $(PPC_TARGETS)))
+
+.PHONY: $(PPC_TARGETS) $(INSTALL_TARGETS)
+
+$(PPC_TARGETS):
+ $(MAKE) PPC_TARGET=$@ CPU_UNITDIR=$@ all
+
+$(INSTALL_TARGETS):
+ $(MAKE) all exeinstall PPC_TARGET=$(subst _exe_install,,$@) CPU_UNITDIR=$(subst _exe_install,,$@)
+
+alltargets: $(ALLTARGETS)
+
+
+#####################################################################
+# Default makefile
+#####################################################################
+
+.NOTPARALLEL:
+
+.PHONY: all compiler echotime ppuclean execlean clean distclean
+
+all: compiler $(addsuffix _all,$(TARGET_DIRS))
+
+compiler: $(COMPILER_UNITTARGETDIR) $(COMPILER_TARGETDIR) $(EXENAME)
+
+ifeq ($(MAKELEVEL),0)
+ifndef STARTTIME
+ifdef DATE
+STARTTIME:=$(shell $(DATE) +%T)
+else
+STARTTIME:=unknown
+endif
+endif
+endif
+
+export STARTTIME
+
+ifdef DATE
+ENDTIME=$(shell $(DATE) +%T)
+else
+ENDTIME:=unknown
+endif
+
+echotime:
+ @echo Start $(STARTTIME) now $(ENDTIME)
+
+ppuclean:
+ -$(DEL) *$(OEXT) *$(PPUEXT) *$(RSTEXT) *$(ASMEXT) *$(STATICLIBEXT) *$(SHAREDLIBEXT) *$(PPLEXT)
+ -$(DEL) $(addsuffix /*$(PPUEXT),$(COMPILERSOURCEDIR))
+
+tempclean:
+ -$(DEL) $(PPCROSSNAME) $(TEMPNAME) $(TEMPNAME1) $(TEMPNAME2) $(TEMPNAME3) $(MSG2INC) pp1.wpo pp2.wpo
+
+execlean :
+ -$(DEL) ppc386$(EXEEXT) ppc68k$(EXEEXT) ppcx64$(EXEEXT) ppcppc$(EXEEXT) ppcsparc$(EXEEXT) ppcppc64$(EXEEXT) ppcarm$(EXEEXT) ppcmips$(EXEEXT) ppcmipsel$(EXEEXT) $(EXENAME) $(TEMPWPONAME1) $(TEMPWPONAME2)
+
+$(addsuffix _clean,$(ALLTARGETS)):
+ -$(DELTREE) $(addprefix $(subst _clean,,$@),/units)
+ -$(DEL) $(addprefix $(subst _clean,,$@)/,*$(OEXT) *$(PPUEXT) *$(RSTEXT) *$(ASMEXT) *$(STATICLIBEXT) *$(SHAREDLIBEXT) *$(PPLEXT))
+ -$(DEL) $(addprefix $(subst _clean,,$@)/,ppc386$(EXEEXT) ppc68k$(EXEEXT) ppcx64$(EXEEXT) ppcppc$(EXEEXT) ppcsparc$(EXEEXT) ppcppc64$(EXEEXT) ppcarm$(EXEEXT) ppcmips$(EXEEXT) ppcmipsel$(EXEEXT) $(EXENAME))
+
+cycleclean: cleanall $(addsuffix _clean,$(CPC_TARGET))
+ -$(DEL) $(EXENAME)
+
+clean: tempclean execlean cleanall $(addsuffix _clean,$(CPC_TARGET)) $(addsuffix _clean,$(TARGET_DIRS))
+
+distclean: tempclean execlean cleanall $(addsuffix _clean,$(ALLTARGETS)) $(addsuffix _distclean,$(TARGET_DIRS))
+
+
+#####################################################################
+# Make targets
+#####################################################################
+
+$(MSG2INC): $(COMPILER_TARGETDIR) $(COMPILER_UNITTARGETDIR) $(COMPILERUTILSDIR)/msg2inc.pp
+ $(COMPILER) -FE. $(COMPILERUTILSDIR)/msg2inc.pp
+
+# The msgtxt.inc only depends on the error?.msg file, not on msg2inc,
+# because that one will be new almost everytime
+msgtxt.inc: $(MSGFILE)
+ $(MAKE) $(MSG2INC)
+ $(MSG2INC) $(MSGFILE) msg msg
+
+msg: msgtxt.inc
+
+insdatx86 : $(COMPILER_UNITTARGETDIR) x86/x86ins.dat
+ $(COMPILER) -FE$(COMPILERUTILSDIR) $(COMPILERUTILSDIR)/mkx86ins.pp
+ cd x86 && ..$(PATHSEP)utils$(PATHSEP)mkx86ins$(SRCEXEEXT) && mv -f *.inc ../i386
+ cd x86 && ..$(PATHSEP)utils$(PATHSEP)mkx86ins$(SRCEXEEXT) x86_64 && mv -f *.inc ../x86_64
+ $(COMPILER) -FE$(COMPILERUTILSDIR) $(COMPILERUTILSDIR)/mkx86reg.pp
+ cd x86 && ..$(PATHSEP)utils$(PATHSEP)mkx86reg$(SRCEXEEXT)
+ mv -f x86/r386*.inc i386
+ cd x86 && ..$(PATHSEP)utils$(PATHSEP)mkx86reg$(SRCEXEEXT) x86_64
+ mv -f x86/r8664*.inc x86_64
+
+insdatarm : arm/armins.dat
+ $(COMPILER) -FE$(COMPILERUTILSDIR) $(COMPILERUTILSDIR)/mkarmins.pp
+ cd arm && ..$(PATHSEP)utils$(PATHSEP)mkarmins$(SRCEXEEXT)
+
+insdat: insdatx86 insdatarm
+
+regdatarm : arm/armreg.dat
+ $(COMPILER) -FE$(COMPILERUTILSDIR) $(COMPILERUTILSDIR)/mkarmreg.pp
+ cd arm && ..$(PATHSEP)utils$PATHSEP)mkarmreg$(SRCEXEEXT)
+
+# revision.inc rule
+revision.inc :
+ifneq ($(REVSTR),)
+ifdef USEZIPWRAPPER
+ifneq ($(ECHOREDIR),echo)
+ $(ECHOREDIR) "'$(REVSTR)'" > revision.inc
+else
+ $(ECHOREDIR) '$(REVSTR)' > revision.inc
+endif
+else
+ $(ECHOREDIR) "'$(REVSTR)'" > revision.inc
+endif
+else
+ $(MAKE) revision.inc REVINC=force
+endif
+
+.PHONY : revision
+
+revision :
+ $(DEL) revision.inc
+ $(MAKE) revision.inc
+
+# Make only the compiler
+# ECHOREDIR sometimes does not remove double quotes
+$(EXENAME) : $(wildcard *.pas) $(wildcard *.inc) msg \
+ $(wildcard systems/*.pas) $(wilcard systems/*.inc) \
+ $(wildcard $(CPC_TARGET)/*.pas) $(wildcard $(CPC_TARGET)/*.inc) \
+ $(COMPILER_UNITTARGETDIR) $(COMPILER_TARGETDIR)
+ifneq ($(REVSTR),)
+ifdef USEZIPWRAPPER
+ifneq ($(ECHOREDIR),echo)
+ $(ECHOREDIR) "'$(REVSTR)'" > revision.inc
+else
+ $(ECHOREDIR) '$(REVSTR)' > revision.inc
+endif
+else
+ $(ECHOREDIR) "'$(REVSTR)'" > revision.inc
+endif
+ $(COMPILER) version.pas
+endif
+ $(COMPILER) pp.pas
+ $(EXECPPAS)
+ $(MOVE) $(COMPILER_TARGETDIR)/$(PPEXENAME) $(EXENAME)
+
+
+#####################################################################
+# Cycle targets
+#
+# 1. Source CPU = Target CPU and Source OS = Target OS
+# Normal cycle
+#
+# 2. Source CPU = Target CPU and Source OS <> Target OS
+# First source native compiler
+# Second target native compiler (skipped for cross installation)
+#
+# 3. Source CPU <> Target CPU
+# First source native compiler
+# Second cross compiler
+# Third target native compiler (skipped for cross installation)
+#
+#####################################################################
+
+ifeq ($(CPU_SOURCE),$(PPC_TARGET))
+
+ifeq ($(OS_SOURCE),$(OS_TARGET))
+
+##########################
+# Normal cycle
+#
+
+ifndef NOWPOCYCLE
+ifdef RELEASE
+DOWPOCYCLE=1
+# Two WPO cycles in case of RELEASE=1
+wpocycle:
+# don't use cycle_clean, it will delete the compiler utilities again
+ $(RM) $(EXENAME)
+ $(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME3)' 'OPT=$(LOCALOPT) $(OPTWPOCOLLECT)' compiler
+ $(RM) $(EXENAME)
+ $(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME3)' 'OPT=$(RTLOPT) $(OPTWPOPERFORM)' rtlclean rtl
+ $(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME3)' 'OPT=$(LOCALOPT) $(OPTWPOPERFORM) $(subst pp1.wpo,pp2.wpo,$(OPTWPOCOLLECT))' $(addsuffix _clean,$(ALLTARGETS)) compiler
+ $(MOVE) $(EXENAME) $(TEMPWPONAME1)
+ $(MAKE) 'FPC=$(BASEDIR)/$(TEMPWPONAME1)' 'OPT=$(RTLOPT) $(subst pp1.wpo,pp2.wpo,$(OPTWPOPERFORM))' rtlclean rtl
+ $(MAKE) 'FPC=$(BASEDIR)/$(TEMPWPONAME1)' 'OPT=$(LOCALOPT) $(subst pp1.wpo,pp2.wpo,$(OPTWPOPERFORM))' $(addsuffix _clean,$(ALLTARGETS)) compiler
+ $(COPY) $(EXENAME) $(TEMPWPONAME2)
+endif
+endif
+
+ifndef DOWPOCYCLE
+wpocycle:
+endif
+
+# Used to avoid unnecessary steps
+ifdef DIFF
+ifdef OLDFPC
+ifneq ($(OS_TARGET),darwin)
+DIFFRESULT:=$(shell $(DIFF) $(OLDFPC) $(FPC))
+else
+DIFFRESULT:=$(shell cp $(OLDFPC) $(OLDFPC).tmp; cp $(FPC) $(FPC).tmp; strip -no_uuid $(OLDFPC).tmp; strip -no_uuid $(FPC).tmp; $(DIFF) $(OLDFPC).tmp $(FPC).tmp; rm $(OLDFPC).tmp $(FPC).tmp)
+endif
+else
+DIFFRESULT=Not equal
+endif
+else
+DIFFRESULT=No diff program
+endif
+
+ifndef DIFFRESULT
+next :
+ @echo $(OLDFPC) and $(FPC) are equal
+ $(COPY) $(FPC) $(EXENAME)
+else
+next :
+ $(MAKE) rtlclean rtl
+ $(MAKE) cycleclean compiler
+ $(MAKE) echotime
+endif
+
+$(TEMPNAME1) :
+ $(MAKE) 'OLDFPC=' next
+ -$(DEL) $(TEMPNAME1)
+ $(MOVE) $(EXENAME) $(TEMPNAME1)
+
+$(TEMPNAME2) : $(TEMPNAME1)
+ $(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME1)' 'OLDFPC=' next
+ -$(DEL) $(TEMPNAME2)
+ $(MOVE) $(EXENAME) $(TEMPNAME2)
+
+$(TEMPNAME3) : $(TEMPNAME2)
+ $(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME2)' 'OLDFPC=$(BASEDIR)/$(TEMPNAME1)' next
+ -$(DEL) $(TEMPNAME3)
+ $(MOVE) $(EXENAME) $(TEMPNAME3)
+
+cycle:
+ $(MAKE) tempclean $(TEMPNAME3)
+ $(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME3)' 'OLDFPC=$(BASEDIR)/$(TEMPNAME2)' next
+ $(DIFF) $(TEMPNAME3) $(EXENAME)
+ $(MAKE) $(addsuffix _all,$(TARGET_DIRS)) 'FPC=$(BASEDIR)/$(EXENAME)'
+ $(MAKE) wpocycle
+ $(MAKE) echotime
+
+else
+
+##########################
+# Cross Target cycle
+#
+
+cycle:
+# ppc (source native)
+ $(MAKE) OS_TARGET=$(OS_SOURCE) CROSSBINDIR= BINUTILSPREFIX= CROSSCYCLEBOOTSTRAP=1 rtlclean rtl
+ $(MAKE) OS_TARGET=$(OS_SOURCE) EXENAME=$(TEMPNAME) CROSSBINDIR= BINUTILSPREFIX= CROSSCYCLEBOOTSTRAP=1 cycleclean compiler
+# ppcross<ARCH> (source native)
+ $(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME)' OS_TARGET=$(OS_SOURCE) CROSSBINDIR= BINUTILSPREFIX= CROSSCYCLEBOOTSTRAP=1 rtlclean rtl
+ $(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME)' OS_TARGET=$(OS_SOURCE) EXENAME=$(PPCROSSNAME) CROSSBINDIR= BINUTILSPREFIX= CROSSCYCLEBOOTSTRAP=1 cycleclean compiler
+# ppc<ARCH> (target native)
+ifndef CROSSINSTALL
+ $(MAKE) 'FPC=$(BASEDIR)/$(PPCROSSNAME)' rtlclean rtl
+# building a native compiler for embedded targets is not possible
+ifneq ($(OS_TARGET),embedded)
+# building a native compiler for the arm-gba target is not possible
+ifneq ($(OS_TARGET),gba)
+ $(MAKE) 'FPC=$(BASEDIR)/$(PPCROSSNAME)' cycleclean compiler
+endif
+endif
+endif
+
+endif
+
+else
+
+##########################
+# Cross CPU cycle
+#
+# ppc1 = native
+# ppc2 = cross running on this platform
+# ppc3/ppcXXX = native (skipped for cross installation)
+#
+
+cycle: override FPC=
+cycle:
+# ppc (source native)
+# Clear detected compiler binary, because it can be existing crosscompiler binary, but we need native compiler here
+ $(MAKE) OS_TARGET=$(OS_SOURCE) CPU_TARGET=$(CPU_SOURCE) CROSSBINDIR= BINUTILSPREFIX= CROSSCYCLEBOOTSTRAP=1 rtlclean rtl
+ $(MAKE) OS_TARGET=$(OS_SOURCE) CPU_TARGET=$(CPU_SOURCE) EXENAME=$(TEMPNAME) CROSSBINDIR= BINUTILSPREFIX= CROSSCYCLEBOOTSTRAP=1 cycleclean compiler
+# ppcross<ARCH> (source native)
+ $(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME)' OS_TARGET=$(OS_SOURCE) CPU_TARGET=$(CPU_SOURCE) CROSSBINDIR= BINUTILSPREFIX= CROSSCYCLEBOOTSTRAP=1 rtlclean rtl
+ $(MAKE) 'FPC=$(BASEDIR)/$(TEMPNAME)' OS_TARGET=$(OS_SOURCE) CPU_TARGET=$(CPU_SOURCE) PPC_TARGET=$(CPU_TARGET) EXENAME=$(PPCROSSNAME) CROSSBINDIR= BINUTILSPREFIX= CROSSCYCLEBOOTSTRAP=1 cycleclean compiler
+# ppc<ARCH> (target native)
+ifndef CROSSINSTALL
+ $(MAKE) 'FPC=$(BASEDIR)/$(PPCROSSNAME)' 'OPT=$(OPT) $(CROSSOPT)' rtlclean rtl
+# building a native compiler for embedded targets is not possible
+ifneq ($(OS_TARGET),embedded)
+# building a native compiler for the arm-gba target is not possible
+ifneq ($(OS_TARGET),gba)
+ $(MAKE) 'FPC=$(BASEDIR)/$(PPCROSSNAME)' 'OPT=$(OPT) $(CROSSOPT)' cycleclean compiler
+endif
+endif
+endif
+
+endif
+
+cycledep:
+ $(MAKE) cycle USEDEPEND=1
+
+extcycle:
+ $(MAKE) cycle OPT='-n -OG2p3 -glttt -CRriot -dEXTDEBUG'
+
+cvstest:
+ $(MAKE) cycle 'LOCALOPT=-n -Se' 'RTLOPT=-n -Se'
+
+
+##########################
+# Full cycle
+#
+# 1. build a compiler using cycle
+# 2. remove all .ppufiles
+# 3. build all supported cross compilers except the
+# current PPC_TARGET which was already build
+#
+
+full: fullcycle
+
+fullcycle:
+ $(MAKE) cycle
+ $(MAKE) ppuclean
+ $(MAKE) $(filter-out $(PPC_TARGET),$(CYCLETARGETS)) 'FPC=$(BASEDIR)/$(EXENAME)'
+
+#####################################################################
+# Docs
+#####################################################################
+
+htmldocs:
+ $(PASDOC) -p -h -o html$(PATHSEP)$(PPC_TARGET) -d fpc -d gdb -d $(PPC_TARGET) -u $(PPC_TARGET) $(PPC_TARGET)$(PATHSEP)*.pas systems$(PATHSEP)*.pas *.pas
+
+#####################################################################
+# Installation
+#####################################################################
+
+.PHONY: quickinstall exeinstall install installsym
+
+MSGINSTALLDIR=$(INSTALL_BASEDIR)/msg
+override PPEXEFILE:=$(wildcard $(EXENAME))
+
+ifdef UNIXHier
+PPCCPULOCATION=$(INSTALL_BASEDIR)
+else
+PPCCPULOCATION=$(INSTALL_BINDIR)
+endif
+
+# This will only install the ppcXXX executable, not the message files etc.
+quickinstall: $(addsuffix _install,$(TARGET_DIRS))
+ $(MAKE) exeinstall
+
+# Install ppcXXX executable, for a cross installation we install
+# the ppcrossXXX as ppcXXX. The target native build ppcXXX is not used
+# for this installation type
+exeinstall:
+ifneq ($(INSTALLEXEFILE),)
+ifdef UPXPROG
+ -$(UPXPROG) $(INSTALLEXEFILE)
+endif
+ $(MKDIR) $(PPCCPULOCATION)
+ $(INSTALLEXE) $(INSTALLEXEFILE) $(PPCCPULOCATION)/$(INSTALLEXEFILE)
+endif
+
+fullinstall:
+ $(MAKE) $(addsuffix _exe_install,$(filter-out $(PPC_TARGET),$(CYCLETARGETS)))
+
+install: quickinstall
+ifndef CROSSINSTALL
+ifdef UNIXHier
+ $(MKDIR) $(INSTALL_BASEDIR)
+ $(INSTALLEXE) $(COMPILERUTILSDIR)/samplecfg $(INSTALL_BASEDIR)/samplecfg
+endif
+ $(MKDIR) $(MSGINSTALLDIR)
+ $(INSTALL) $(MSGFILES) $(MSGINSTALLDIR)
+endif
+
+# This also installs a link from bin to the actual executable.
+# The .deb does that later.
+installsymlink: install
+ifneq ($(PPCCPULOCATION),$(INSTALL_BINDIR))
+ $(MKDIR) $(INSTALL_BINDIR)
+ ln -sf $(INSTALL_BASEDIR)/$(EXENAME) $(INSTALL_BINDIR)/$(EXENAME)
+endif
+
+
+#####################################################################
+# RTL
+#####################################################################
+
+.PHONY: rtl rtlclean rtlinstall
+
+rtl:
+ $(MAKE) -C $(PACKAGEDIR_RTL) 'OPT=$(RTLOPT)' all
+
+rtlclean:
+ $(MAKE) -C $(PACKAGEDIR_RTL) clean
+
+rtlinstall:
+ $(MAKE) -C $(PACKAGEDIR_RTL) install
+
+#####################################################################
+# PPU testing targets
+#####################################################################
+
+PPUDIR=$(COMPILER_UNITTARGETDIR)
+ALLPPUDIR=$(CPU_TARGET)/units/*
+PPULIST=$(wildcard $(PPUDIR)/*.ppu)
+PPULOGLIST=$(subst .ppu,.log-ppu,$(PPULIST))
+
+RTLPPUDIR=../rtl/units/$(FULL_TARGET)
+RTLPPULIST=$(wildcard $(RTLPPUDIR)/*.ppu)
+RTLPPULOGLIST=$(subst .ppu,.log-ppu,$(RTLPPULIST))
+
+.PHONY : ppulogs cleanppulogs rtlppulogs cleanrtlppulogs testppudump
+
+ppulogs : $(PPULOGLIST)
+
+rtlppulogs : $(RTLPPULOGLIST)
+
+vpath %.ppu $(PPUDIR) $(RTLPPUDIR) $(ALLPPUDIR)
+vpath %.log-ppu $(PPUDIR) $(RTLPPUDIR) $(ALLPPUDIR)
+
+%.log-ppu : %.ppu ./utils/ppudump$(EXEEXT)
+ .$(PATHSEP)utils$(PATHSEP)ppudump -VA -M $< > $@
+
+
+./utils/ppudump$(EXEEXT):
+ $(MAKE) -C $(COMPILERUTILSDIR) ppudump$(EXEEXT)
+
+ppuinfo :
+ echo PPU list is "$(PPULIST)"
+ echo PPULOG list is "$(PPULOGLIST)"
+
+cleanppulogs :
+ -$(RMPROG) $(PPULOGLIST)
+
+cleanrtlppulogs :
+ -$(RMPROG) $(RTLPPULOGLIST)
+
+testppudump :
+ $(MAKE) cleanrtlppulogs cleanppulogs ppulogs rtlppulogs
+
+#####################################################################
+# local user configurable file
+# in makefile.loc you can add any desired target
+#####################################################################
+
+localmake:=$(strip $(wildcard makefile.loc))
+
+ifdef localmake
+include ./$(localmake)
+endif
diff --git a/closures/compiler/README.txt b/closures/compiler/README.txt
new file mode 100644
index 0000000000..745695cc1e
--- /dev/null
+++ b/closures/compiler/README.txt
@@ -0,0 +1,63 @@
+This directory contains the sources of the Free Pascal Compiler
+
+If you want to compile/modify the compiler, please read first the
+programmers manual.
+
+To recompile the compiler, you can use the batch files :
+ + mppc386.bat if you want to build a cross compiler from i386 to m68k
+ + mppcsparc if you want to build a cross compiler from i386 to SPARC
+
+ or
+Use the make utility as following
+
+ make OS_TARGET="compiler OS target" \
+ CPU_TARGET="compiler CPU target" \
+ FPCCPUOPT="Optimization level" \
+ PP="compiler used to compile FPC" \
+ COMPILER_OPTIONS="Options passed to compiler" \
+
+
+If an option is omitted, then target CPU/OS will be same as current CPU/OS
+
+Possibles targets are : linux go32v2 win32 os2 freebsd beos netbsd amiga haiku
+atari sunos qnx netware openbsd wdosx palmos macos macosx emx
+
+Possible compiler switches (* marks a currently required switch):
+ -----------------------------------------------------------------
+ GDB* support of the GNU Debugger
+ I386 generate a compiler for the Intel i386+
+ x86_64 generate a compiler for the AMD x86-64 architecture
+ M68K generate a compiler for the M68000
+ SPARC generate a compiler for SPARC
+ POWERPC generate a compiler for the PowerPC
+ VIS generate a compile for the VIS
+ DEBUG version with debug code is generated
+ EXTDEBUG some extra debug code is executed
+ SUPPORT_MMX only i386: releases the compiler switch
+ MMX which allows the compiler to generate
+ MMX instructions
+ EXTERN_MSG Don't compile the msgfiles in the compiler, always
+ use external messagefiles, default for TP
+ NOAG386INT no Intel Assembler output
+ NOAG386NSM no NASM output
+ NOAG386BIN leaves out the binary writer, default for TP
+ NORA386DIR No direct i386 assembler reader
+ TEST_GENERIC Test Generic version of code generator
+ (uses generic RTL calls)
+ -----------------------------------------------------------------
+ cpuflags The target processor has status flags (on by default)
+ cpufpemu The target compiler will also support emitting software
+ floating point operations
+ cpu64bitaddr The targets use a 64-bit address space (pointers and
+ the default integer type are 64 bit)
+ cpu64bitalu The target cpu has 64-bit registers available (unless
+ cpu64bitaddr is also defined, pointers and default
+ integer type remain 32 bit, but the cpu can perform
+ 64 bit calculations directly without needing helpers)
+ -----------------------------------------------------------------
+
+ Required switches for a i386 compiler be compiled by Free Pascal Compiler:
+ GDB;I386
+
+to build a compiler to SPARC target using a Win32/i386 you just use :
+ make CPU_TARGET=SPARC
diff --git a/closures/compiler/aasmbase.pas b/closures/compiler/aasmbase.pas
new file mode 100644
index 0000000000..7cc2e56c16
--- /dev/null
+++ b/closures/compiler/aasmbase.pas
@@ -0,0 +1,435 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit implements an abstract asmoutput class for all processor types
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+{ @abstract(This unit implements an abstract asm output class for all processor types)
+ This unit implements an abstract assembler output class for all processors, these
+ are then overridden for each assembler writer to actually write the data in these
+ classes to an assembler file.
+}
+
+unit aasmbase;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cutils,cclasses,
+ globtype,globals,systems
+ ;
+
+ type
+ TAsmsymbind=(
+ AB_NONE,AB_EXTERNAL,AB_COMMON,AB_LOCAL,AB_GLOBAL,AB_WEAK_EXTERNAL,
+ { global in the current program/library, but not visible outside it }
+ AB_PRIVATE_EXTERN,AB_LAZY,AB_IMPORT);
+
+ TAsmsymtype=(
+ AT_NONE,AT_FUNCTION,AT_DATA,AT_SECTION,AT_LABEL,
+ {
+ the address of this code label is taken somewhere in the code
+ so it must be taken care of it when creating pic
+ }
+ AT_ADDR
+ );
+
+ { is the label only there for getting an DataOffset (e.g. for i/o
+ checks -> alt_addr) or is it a jump target (alt_jump), for debug
+ info alt_dbgline and alt_dbgfile, etc. }
+ TAsmLabelType = (alt_jump,alt_addr,alt_data,alt_dbgline,alt_dbgfile,alt_dbgtype,alt_dbgframe);
+
+ const
+ asmlabeltypeprefix : array[TAsmLabeltype] of char = ('j','a','d','l','f','t','c');
+
+ type
+ TAsmSectiontype=(sec_none,
+ { this section type allows to define a user named section }
+ sec_user,
+ sec_code,
+ sec_data,
+ { read-only, but may contain relocations }
+ sec_rodata,
+ { read-only and cannot contain relocations }
+ sec_rodata_norel,
+ sec_bss,
+ sec_threadvar,
+ { used for wince exception handling }
+ sec_pdata,
+ { used for darwin import stubs }
+ sec_stub,
+ sec_data_nonlazy,
+ sec_data_lazy,
+ sec_init_func,
+ sec_term_func,
+ { stabs }
+ sec_stab,sec_stabstr,
+ { win32 }
+ sec_idata2,sec_idata4,sec_idata5,sec_idata6,sec_idata7,sec_edata,
+ { C++ exception handling unwinding (uses dwarf) }
+ sec_eh_frame,
+ { dwarf }
+ sec_debug_frame,
+ sec_debug_info,
+ sec_debug_line,
+ sec_debug_abbrev,
+ { Yury: "sec_fpc is intended for storing fpc specific data
+ which must be recognized and processed specially by linker.
+ Currently fpc version string, dummy links to stab sections
+ and elf resources are stored in .fpc sections."
+ "If special .fpc section cannot be used on some target,
+ .text can be used instead." }
+ sec_fpc,
+ { Table of contents section }
+ sec_toc,
+ sec_init,
+ sec_fini,
+ {Objective-C common and fragile ABI }
+ sec_objc_class,
+ sec_objc_meta_class,
+ sec_objc_cat_cls_meth,
+ sec_objc_cat_inst_meth,
+ sec_objc_protocol,
+ sec_objc_string_object,
+ sec_objc_cls_meth,
+ sec_objc_inst_meth,
+ sec_objc_cls_refs,
+ sec_objc_message_refs,
+ sec_objc_symbols,
+ sec_objc_category,
+ sec_objc_class_vars,
+ sec_objc_instance_vars,
+ sec_objc_module_info,
+ sec_objc_class_names,
+ sec_objc_meth_var_types,
+ sec_objc_meth_var_names,
+ sec_objc_selector_strs,
+ sec_objc_protocol_ext,
+ sec_objc_class_ext,
+ sec_objc_property,
+ sec_objc_image_info,
+ sec_objc_cstring_object,
+ sec_objc_sel_fixup,
+ { Objective-C non-fragile ABI }
+ sec_objc_data,
+ sec_objc_const,
+ sec_objc_sup_refs,
+ sec_data_coalesced,
+ sec_objc_classlist,
+ sec_objc_nlclasslist,
+ sec_objc_catlist,
+ sec_objc_nlcatlist,
+ sec_objc_protolist
+ );
+
+ TAsmSectionOrder = (secorder_begin,secorder_default,secorder_end);
+
+ TAsmSymbol = class(TFPHashObject)
+ private
+ { this need to be incremented with every symbol loading into the
+ TAsmList with loadsym/loadref/const_symbol (PFV) }
+ refs : longint;
+ public
+ { on avr the compiler needs to replace cond. jumps with too large offsets
+ so we have to store an offset somewhere to calculate jump distances }
+{$ifdef AVR}
+ offset : longint;
+{$endif AVR}
+ bind : TAsmsymbind;
+ typ : TAsmsymtype;
+ { Alternate symbol which can be used for 'renaming' needed for
+ asm inlining. Also used for external and common solving during linking }
+ altsymbol : TAsmSymbol;
+ { Cached objsymbol }
+ cachedobjsymbol : TObject;
+ constructor Create(AList:TFPHashObjectList;const s:string;_bind:TAsmsymbind;_typ:Tasmsymtype);
+ function getaltcopy(AList:TFPHashObjectList;altnr: longint): TAsmSymbol; virtual;
+ function is_used:boolean;
+ procedure increfs;
+ procedure decrefs;
+ function getrefs: longint;
+ end;
+ TAsmSymbolClass = class of TAsmSymbol;
+
+ TAsmLabel = class(TAsmSymbol)
+ protected
+ function getname:string;override;
+ public
+ labelnr : longint;
+ labeltype : TAsmLabelType;
+ is_set : boolean;
+ constructor Createlocal(AList:TFPHashObjectList;nr:longint;ltyp:TAsmLabelType);
+ constructor Createglobal(AList:TFPHashObjectList;const modulename:string;nr:longint;ltyp:TAsmLabelType);
+ function getaltcopy(AList:TFPHashObjectList;altnr: longint): TAsmSymbol; override;
+ end;
+
+ function create_smartlink_sections:boolean;inline;
+ function create_smartlink_library:boolean;inline;
+ function create_smartlink:boolean;inline;
+
+ function LengthUleb128(a: qword) : byte;
+ function LengthSleb128(a: int64) : byte;
+ function EncodeUleb128(a: qword;out buf) : byte;
+ function EncodeSleb128(a: int64;out buf) : byte;
+
+
+implementation
+
+ uses
+ SysUtils,
+ verbose;
+
+
+ function create_smartlink_sections:boolean;inline;
+ begin
+ result:=(af_smartlink_sections in target_asm.flags) and
+ (tf_smartlink_sections in target_info.flags);
+ end;
+
+
+ function create_smartlink_library:boolean;inline;
+ begin
+ result:=(cs_Create_smart in current_settings.moduleswitches) and
+ (tf_smartlink_library in target_info.flags) and
+ not create_smartlink_sections;
+ end;
+
+
+ function create_smartlink:boolean;inline;
+ begin
+ result:=(
+ (af_smartlink_sections in target_asm.flags) and
+ (tf_smartlink_sections in target_info.flags)
+ ) or
+ (
+ (cs_Create_smart in current_settings.moduleswitches) and
+ (tf_smartlink_library in target_info.flags)
+ );
+ end;
+
+
+ function LengthUleb128(a: qword) : byte;
+ begin
+ result:=0;
+ repeat
+ a := a shr 7;
+ inc(result);
+ if a=0 then
+ break;
+ until false;
+ end;
+
+
+ function LengthSleb128(a: int64) : byte;
+ var
+ b, size: byte;
+ asign : int64;
+ neg, more: boolean;
+ begin
+ more := true;
+ neg := a < 0;
+ size := sizeof(a)*8;
+ result:=0;
+ repeat
+ b := a and $7f;
+ a := a shr 7;
+ if neg then
+ begin
+ { Use a variable to be sure that the correct or mask is generated }
+ asign:=1;
+ asign:=asign shl (size - 7);
+ a := a or -asign;
+ end;
+ if (((a = 0) and
+ (b and $40 = 0)) or
+ ((a = -1) and
+ (b and $40 <> 0))) then
+ more := false;
+ inc(result);
+ if not(more) then
+ break;
+ until false;
+ end;
+
+
+ function EncodeUleb128(a: qword;out buf) : byte;
+ var
+ b: byte;
+ pbuf : pbyte;
+ begin
+ result:=0;
+ pbuf:=@buf;
+ repeat
+ b := a and $7f;
+ a := a shr 7;
+ if a<>0 then
+ b := b or $80;
+ pbuf^:=b;
+ inc(pbuf);
+ inc(result);
+ if a=0 then
+ break;
+ until false;
+ end;
+
+
+ function EncodeSleb128(a: int64;out buf) : byte;
+ var
+ b, size: byte;
+ asign : int64;
+ neg, more: boolean;
+ pbuf : pbyte;
+ begin
+ more := true;
+ neg := a < 0;
+ size := sizeof(a)*8;
+ result:=0;
+ pbuf:=@buf;
+ repeat
+ b := a and $7f;
+ a := a shr 7;
+ if neg then
+ begin
+ { Use a variable to be sure that the correct or mask is generated }
+ asign:=1;
+ asign:=asign shl (size - 7);
+ a := a or -asign;
+ end;
+ if (((a = 0) and
+ (b and $40 = 0)) or
+ ((a = -1) and
+ (b and $40 <> 0))) then
+ more := false
+ else
+ b := b or $80;
+ pbuf^:=b;
+ inc(pbuf);
+ inc(result);
+ if not(more) then
+ break;
+ until false;
+ end;
+
+
+{*****************************************************************************
+ TAsmSymbol
+*****************************************************************************}
+
+ constructor TAsmSymbol.Create(AList:TFPHashObjectList;const s:string;_bind:TAsmsymbind;_typ:Tasmsymtype);
+ begin;
+ inherited Create(AList,s);
+ bind:=_bind;
+ typ:=_typ;
+ { used to remove unused labels from the al_procedures }
+ refs:=0;
+ end;
+
+
+ function TAsmSymbol.getaltcopy(AList:TFPHashObjectList;altnr: longint): TAsmSymbol;
+ begin
+ result := TAsmSymbol(TAsmSymbolClass(classtype).Create(AList,name+'_'+tostr(altnr),bind,typ));
+ end;
+
+
+ function TAsmSymbol.is_used:boolean;
+ begin
+ is_used:=(refs>0);
+ end;
+
+
+ procedure TAsmSymbol.increfs;
+ begin
+ inc(refs);
+ end;
+
+
+ procedure TAsmSymbol.decrefs;
+ begin
+ dec(refs);
+ if refs<0 then
+ internalerror(200211121);
+ end;
+
+
+ function TAsmSymbol.getrefs: longint;
+ begin
+ getrefs := refs;
+ end;
+
+
+{*****************************************************************************
+ TAsmLabel
+*****************************************************************************}
+
+ constructor TAsmLabel.Createlocal(AList:TFPHashObjectList;nr:longint;ltyp:TAsmLabelType);
+ var
+ asmtyp: TAsmsymtype;
+ begin
+ case ltyp of
+ alt_addr:
+ asmtyp:=AT_ADDR;
+ alt_data:
+ asmtyp:=AT_DATA;
+ else
+ asmtyp:=AT_LABEL;
+ end;
+ inherited Create(AList,target_asm.labelprefix+asmlabeltypeprefix[ltyp]+tostr(nr),AB_LOCAL,asmtyp);
+ labelnr:=nr;
+ labeltype:=ltyp;
+ is_set:=false;
+ end;
+
+
+ constructor TAsmLabel.Createglobal(AList:TFPHashObjectList;const modulename:string;nr:longint;ltyp:TAsmLabelType);
+ begin
+ inherited Create(AList,'_$'+modulename+'$_L'+asmlabeltypeprefix[ltyp]+tostr(nr),AB_GLOBAL,AT_DATA);
+ labelnr:=nr;
+ labeltype:=ltyp;
+ is_set:=false;
+ { write it always }
+ increfs;
+ end;
+
+
+ function TAsmLabel.getaltcopy(AList:TFPHashObjectList;altnr: longint): TAsmSymbol;
+ begin;
+ result := inherited getaltcopy(AList,altnr);
+ TAsmLabel(result).labelnr:=labelnr;
+ TAsmLabel(result).labeltype:=labeltype;
+ TAsmLabel(result).is_set:=false;
+ case bind of
+ AB_GLOBAL,
+ AB_PRIVATE_EXTERN:
+ result.increfs;
+ AB_LOCAL:
+ ;
+ else
+ internalerror(2006053101);
+ end;
+ end;
+
+
+ function TAsmLabel.getname:string;
+ begin
+ getname:=inherited getname;
+ increfs;
+ end;
+
+end.
diff --git a/closures/compiler/aasmdata.pas b/closures/compiler/aasmdata.pas
new file mode 100644
index 0000000000..bc9065ca5d
--- /dev/null
+++ b/closures/compiler/aasmdata.pas
@@ -0,0 +1,525 @@
+{
+ Copyright (c) 1998-2006 by Florian Klaempfl
+
+ This unit implements an abstract asmoutput class for all processor types
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+{ @abstract(This unit implements an abstract asm output class for all processor types)
+ This unit implements an abstract assembler output class for all processors, these
+ are then overridden for each assembler writer to actually write the data in these
+ classes to an assembler file.
+}
+
+unit aasmdata;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cutils,cclasses,
+ globtype,globals,systems,
+ cpuinfo,cpubase,
+ cgbase,cgutils,
+ symtype,
+ aasmbase,ogbase;
+
+ type
+ { Type of AsmLists. The order is important for the layout of the
+ information in the .o file. The stabs for the types must be defined
+ before they can be referenced and therefor they need to be written
+ first (PFV) }
+ TAsmListType=(
+ al_start,
+ al_stabs,
+ al_procedures,
+ al_globals,
+ al_const,
+ al_typedconsts,
+ al_rotypedconsts,
+ al_threadvars,
+ al_imports,
+ al_exports,
+ al_resources,
+ al_rtti,
+ al_dwarf_frame,
+ al_dwarf_info,
+ al_dwarf_abbrev,
+ al_dwarf_line,
+ al_picdata,
+ al_resourcestrings,
+ { Objective-C related sections }
+ al_objc_data,
+ { keep pool data separate, so we can generate new pool entries
+ while emitting other data }
+ al_objc_pools,
+ al_end
+ );
+
+ { Type of constant 'pools'. Mostly for string types, but usable for
+ floating point and large set constants, too. }
+
+ TConstPoolType = (
+ sp_invalid,
+ sp_conststr,
+ sp_shortstr,
+ sp_longstr,
+ sp_ansistr,
+ sp_widestr,
+ sp_unicodestr,
+ sp_objcclassnamerefs,
+ sp_varnamerefs,
+ sp_objcclassnames,
+ sp_objcvarnames,
+ sp_objcvartypes,
+ sp_objcprotocolrefs,
+ sp_varsets,
+ sp_floats
+ );
+
+ const
+ AsmListTypeStr : array[TAsmListType] of string[24] =(
+ 'al_begin',
+ 'al_stabs',
+ 'al_procedures',
+ 'al_globals',
+ 'al_const',
+ 'al_typedconsts',
+ 'al_rotypedconsts',
+ 'al_threadvars',
+ 'al_imports',
+ 'al_exports',
+ 'al_resources',
+ 'al_rtti',
+ 'al_dwarf_frame',
+ 'al_dwarf_info',
+ 'al_dwarf_abbrev',
+ 'al_dwarf_line',
+ 'al_picdata',
+ 'al_resourcestrings',
+ 'al_objc_data',
+ 'al_objc_pools',
+ 'al_end'
+ );
+
+ type
+ TAsmList = class(tlinkedlist)
+ constructor create;
+ function empty : boolean;
+ function getlasttaifilepos : pfileposinfo;
+ end;
+
+ TAsmCFI=class
+ public
+ constructor create;virtual;
+ destructor destroy;override;
+ procedure generate_code(list:TAsmList);virtual;
+ procedure start_frame(list:TAsmList);virtual;
+ procedure end_frame(list:TAsmList);virtual;
+ procedure cfa_offset(list:TAsmList;reg:tregister;ofs:longint);virtual;
+ procedure cfa_restore(list:TAsmList;reg:tregister);virtual;
+ procedure cfa_def_cfa_register(list:TAsmList;reg:tregister);virtual;
+ procedure cfa_def_cfa_offset(list:TAsmList;ofs:longint);virtual;
+ end;
+ TAsmCFIClass=class of TAsmCFI;
+
+ { TAsmData }
+
+ TAsmData = class
+ private
+ { Symbols }
+ FAsmSymbolDict : TFPHashObjectList;
+ FAltSymbolList : TFPObjectList;
+ FNextAltNr : longint;
+ FNextLabelNr : array[TAsmLabeltype] of longint;
+ { Call Frame Information for stack unwinding}
+ FAsmCFI : TAsmCFI;
+ FConstPools : array[TConstPoolType] of THashSet;
+ function GetConstPools(APoolType: TConstPoolType): THashSet;
+ public
+ name,
+ realname : string[80];
+ NextVTEntryNr : longint;
+ { Assembler lists }
+ AsmLists : array[TAsmListType] of TAsmList;
+ CurrAsmList : TAsmList;
+ WideInits : TLinkedList;
+ ResStrInits : TLinkedList;
+ constructor create(const n:string);
+ destructor destroy;override;
+ { asmsymbol }
+ function DefineAsmSymbol(const s : string;_bind:TAsmSymBind;_typ:Tasmsymtype) : TAsmSymbol;
+ function WeakRefAsmSymbol(const s : string) : TAsmSymbol;
+ function RefAsmSymbol(const s : string) : TAsmSymbol;
+ function GetAsmSymbol(const s : string) : TAsmSymbol;
+ { create new assembler label }
+ procedure getlabel(out l : TAsmLabel;alt:TAsmLabeltype);
+ procedure getjumplabel(out l : TAsmLabel);
+ procedure getglobaljumplabel(out l : TAsmLabel);
+ procedure getaddrlabel(out l : TAsmLabel);
+ procedure getdatalabel(out l : TAsmLabel);
+ { generate an alternative (duplicate) symbol }
+ procedure GenerateAltSymbol(p:TAsmSymbol);
+ procedure ResetAltSymbols;
+ property AsmSymbolDict:TFPHashObjectList read FAsmSymbolDict;
+ property AsmCFI:TAsmCFI read FAsmCFI;
+ { hash tables for reusing constant storage }
+ property ConstPools[APoolType:TConstPoolType]: THashSet read GetConstPools;
+ end;
+
+ TTCInitItem = class(TLinkedListItem)
+ sym: tsym;
+ offset: aint;
+ datalabel: TAsmSymbol;
+ constructor Create(asym: tsym; aoffset: aint; alabel: TAsmSymbol);
+ end;
+
+ var
+ CAsmCFI : TAsmCFIClass;
+ current_asmdata : TAsmData;
+
+
+implementation
+
+ uses
+ verbose,
+ aasmtai;
+
+{$ifdef MEMDEBUG}
+ var
+ memasmsymbols,
+ memasmcfi,
+ memasmlists : TMemDebug;
+{$endif MEMDEBUG}
+
+
+{*****************************************************************************
+ TAsmCFI
+*****************************************************************************}
+
+ constructor TAsmCFI.create;
+ begin
+ end;
+
+
+ destructor TAsmCFI.destroy;
+ begin
+ end;
+
+
+ procedure TAsmCFI.generate_code(list:TAsmList);
+ begin
+ end;
+
+
+ procedure TAsmCFI.start_frame(list:TAsmList);
+ begin
+ end;
+
+
+ procedure TAsmCFI.end_frame(list:TAsmList);
+ begin
+ end;
+
+
+ procedure TAsmCFI.cfa_offset(list:TAsmList;reg:tregister;ofs:longint);
+ begin
+ end;
+
+
+ procedure TAsmCFI.cfa_restore(list:TAsmList;reg:tregister);
+ begin
+ end;
+
+
+ procedure TAsmCFI.cfa_def_cfa_register(list:TAsmList;reg:tregister);
+ begin
+ end;
+
+
+ procedure TAsmCFI.cfa_def_cfa_offset(list:TAsmList;ofs:longint);
+ begin
+ end;
+
+{*****************************************************************************
+ TTCInitItem
+*****************************************************************************}
+
+
+ constructor TTCInitItem.Create(asym: tsym; aoffset: aint; alabel: TAsmSymbol);
+ begin
+ inherited Create;
+ sym:=asym;
+ offset:=aoffset;
+ datalabel:=alabel;
+ end;
+
+{*****************************************************************************
+ TAsmList
+*****************************************************************************}
+
+ constructor TAsmList.create;
+ begin
+ inherited create;
+ { make sure the optimizer won't remove the first tai of this list}
+ insert(tai_marker.create(mark_BlockStart));
+ end;
+
+
+ function TAsmList.empty : boolean;
+ begin
+ { there is always a mark_BlockStart available,
+ see TAsmList.create }
+ result:=(count<=1);
+ end;
+
+
+ function TAsmList.getlasttaifilepos : pfileposinfo;
+ var
+ hp : tlinkedlistitem;
+ begin
+ getlasttaifilepos := nil;
+ if assigned(last) then
+ begin
+ { find the last file information record }
+ if not (tai(last).typ in SkipLineInfo) then
+ getlasttaifilepos:=@tailineinfo(last).fileinfo
+ else
+ { go through list backwards to find the first entry
+ with line information
+ }
+ begin
+ hp:=tai(last);
+ while assigned(hp) and (tai(hp).typ in SkipLineInfo) do
+ hp:=hp.Previous;
+ { found entry }
+ if assigned(hp) then
+ getlasttaifilepos:=@tailineinfo(hp).fileinfo
+ end;
+ end;
+ end;
+
+
+{****************************************************************************
+ TAsmData
+****************************************************************************}
+
+ function TAsmData.GetConstPools(APoolType: TConstPoolType): THashSet;
+ begin
+ if FConstPools[APoolType] = nil then
+ case APoolType of
+ sp_ansistr: FConstPools[APoolType] := TTagHashSet.Create(64, True, False);
+ else
+ FConstPools[APoolType] := THashSet.Create(64, True, False);
+ end;
+ Result := FConstPools[APoolType];
+ end;
+
+ constructor TAsmData.create(const n:string);
+ var
+ alt : TAsmLabelType;
+ hal : TAsmListType;
+ begin
+ inherited create;
+ realname:=n;
+ name:=upper(n);
+ { symbols }
+ FAsmSymbolDict:=TFPHashObjectList.create(true);
+ FAltSymbolList:=TFPObjectList.Create(false);
+ { labels }
+ FNextAltNr:=1;
+ for alt:=low(TAsmLabelType) to high(TAsmLabelType) do
+ FNextLabelNr[alt]:=1;
+ { AsmLists }
+ CurrAsmList:=TAsmList.create;
+ for hal:=low(TAsmListType) to high(TAsmListType) do
+ AsmLists[hal]:=TAsmList.create;
+ WideInits :=TLinkedList.create;
+ ResStrInits:=TLinkedList.create;
+ { CFI }
+ FAsmCFI:=CAsmCFI.Create;
+ end;
+
+
+ destructor TAsmData.destroy;
+ var
+ hal : TAsmListType;
+ hp : TConstPoolType;
+ begin
+ { Symbols }
+{$ifdef MEMDEBUG}
+ memasmsymbols.start;
+{$endif}
+ FAltSymbolList.free;
+ FAsmSymbolDict.free;
+{$ifdef MEMDEBUG}
+ memasmsymbols.stop;
+{$endif}
+ { CFI }
+{$ifdef MEMDEBUG}
+ memasmcfi.start;
+{$endif}
+ FAsmCFI.free;
+{$ifdef MEMDEBUG}
+ memasmcfi.stop;
+{$endif}
+ { Lists }
+{$ifdef MEMDEBUG}
+ memasmlists.start;
+{$endif}
+ ResStrInits.free;
+ WideInits.free;
+ for hal:=low(TAsmListType) to high(TAsmListType) do
+ AsmLists[hal].free;
+ CurrAsmList.free;
+{$ifdef MEMDEBUG}
+ memasmlists.stop;
+{$endif}
+ for hp := low(TConstPoolType) to high(TConstPoolType) do
+ FConstPools[hp].Free;
+ end;
+
+
+ function TAsmData.DefineAsmSymbol(const s : string;_bind:TAsmSymBind;_typ:Tasmsymtype) : TAsmSymbol;
+ var
+ hp : TAsmSymbol;
+ begin
+ hp:=TAsmSymbol(FAsmSymbolDict.Find(s));
+ if assigned(hp) then
+ begin
+ { Redefine is allowed, but the types must be the same. The redefine
+ is needed for Darwin where the labels are first allocated }
+ if (hp.bind<>AB_EXTERNAL) then
+ begin
+ if (hp.bind<>_bind) and
+ (hp.typ<>_typ) then
+ internalerror(200603261);
+ end;
+ hp.typ:=_typ;
+ hp.bind:=_bind;
+ end
+ else
+ begin
+ { Not found, insert it. }
+ hp:=TAsmSymbol.create(AsmSymbolDict,s,_bind,_typ);
+ end;
+ result:=hp;
+ end;
+
+
+ function TAsmData.RefAsmSymbol(const s : string) : TAsmSymbol;
+ begin
+ result:=TAsmSymbol(FAsmSymbolDict.Find(s));
+ if not assigned(result) then
+ result:=TAsmSymbol.create(AsmSymbolDict,s,AB_EXTERNAL,AT_NONE)
+ { one normal reference removes the "weak" character of a symbol }
+ else if (result.bind=AB_WEAK_EXTERNAL) then
+ result.bind:=AB_EXTERNAL;
+ end;
+
+
+ function TAsmData.WeakRefAsmSymbol(const s : string) : TAsmSymbol;
+ begin
+ result:=TAsmSymbol(FAsmSymbolDict.Find(s));
+ if not assigned(result) then
+ result:=TAsmSymbol.create(AsmSymbolDict,s,AB_WEAK_EXTERNAL,AT_NONE);
+ end;
+
+
+ function TAsmData.GetAsmSymbol(const s : string) : TAsmSymbol;
+ begin
+ result:=TAsmSymbol(FAsmSymbolDict.Find(s));
+ end;
+
+
+ procedure TAsmData.GenerateAltSymbol(p:TAsmSymbol);
+ begin
+ if not assigned(p.altsymbol) then
+ begin
+ p.altsymbol:=p.getaltcopy(AsmSymbolDict,FNextAltNr);
+ FAltSymbolList.Add(p);
+ end;
+ end;
+
+
+ procedure TAsmData.ResetAltSymbols;
+ var
+ i : longint;
+ begin
+ for i:=0 to FAltSymbolList.Count-1 do
+ TAsmSymbol(FAltSymbolList[i]).altsymbol:=nil;
+ FAltSymbolList.Clear;
+ end;
+
+
+ procedure TAsmData.getlabel(out l : TAsmLabel;alt:TAsmLabeltype);
+ begin
+ if (target_info.system in (systems_linux + systems_bsd)) and
+ (cs_create_smart in current_settings.moduleswitches) and
+ (alt = alt_dbgline) then
+ l:=TAsmLabel.createglobal(AsmSymbolDict,name,FNextLabelNr[alt],alt)
+ else
+ l:=TAsmLabel.createlocal(AsmSymbolDict,FNextLabelNr[alt],alt);
+ inc(FNextLabelNr[alt]);
+ end;
+
+
+ procedure TAsmData.getjumplabel(out l : TAsmLabel);
+ begin
+ l:=TAsmLabel.createlocal(AsmSymbolDict,FNextLabelNr[alt_jump],alt_jump);
+ inc(FNextLabelNr[alt_jump]);
+ end;
+
+ procedure TAsmData.getglobaljumplabel(out l : TAsmLabel);
+ begin
+ l:=TAsmLabel.createglobal(AsmSymbolDict,name,FNextLabelNr[alt_jump],alt_jump);
+ inc(FNextLabelNr[alt_jump]);
+ end;
+
+ procedure TAsmData.getdatalabel(out l : TAsmLabel);
+ begin
+ l:=TAsmLabel.createglobal(AsmSymbolDict,name,FNextLabelNr[alt_data],alt_data);
+ inc(FNextLabelNr[alt_data]);
+ end;
+
+
+ procedure TAsmData.getaddrlabel(out l : TAsmLabel);
+ begin
+ l:=TAsmLabel.createlocal(AsmSymbolDict,FNextLabelNr[alt_addr],alt_addr);
+ inc(FNextLabelNr[alt_addr]);
+ end;
+
+initialization
+{$ifdef MEMDEBUG}
+ memasmsymbols:=TMemDebug.create('AsmSymbols');
+ memasmsymbols.stop;
+ memasmcfi:=TMemDebug.create('AsmCFI');
+ memasmcfi.stop;
+ memasmlists:=TMemDebug.create('AsmLists');
+ memasmlists.stop;
+{$endif MEMDEBUG}
+ CAsmCFI:=TAsmCFI;
+
+finalization
+{$ifdef MEMDEBUG}
+ memasmsymbols.free;
+ memasmcfi.free;
+ memasmlists.free;
+{$endif MEMDEBUG}
+
+end.
diff --git a/closures/compiler/aasmsym.pas b/closures/compiler/aasmsym.pas
new file mode 100644
index 0000000000..f9287ce1f8
--- /dev/null
+++ b/closures/compiler/aasmsym.pas
@@ -0,0 +1,71 @@
+{
+ Copyright (c) 1998-2007 by Florian Klaempfl and Peter Vreman
+
+ Contains abstract assembler instructions for all processor
+ types, including routines which depend on the symbol table.
+ These cannot be in aasmtai, because the symbol table units
+ depend on that one.
+
+ * Portions of this code was inspired by the NASM sources
+ The Netwide Assembler is Copyright (c) 1996 Simon Tatham and
+ Julian Hall. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit aasmsym;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ aasmtai;
+
+ type
+ tai_cpu_abstract_sym = class(tai_cpu_abstract)
+ protected
+ procedure ppubuildderefimploper(var o:toper);override;
+ procedure ppuderefoper(var o:toper);override;
+ end;
+
+implementation
+
+ uses
+ symsym;
+
+
+ procedure tai_cpu_abstract_sym.ppubuildderefimploper(var o:toper);
+ begin
+ case o.typ of
+ top_local :
+ o.localoper^.localsymderef.build(tlocalvarsym(o.localoper^.localsym));
+ end;
+ end;
+
+
+ procedure tai_cpu_abstract_sym.ppuderefoper(var o:toper);
+ begin
+ case o.typ of
+ top_ref :
+ begin
+ end;
+ top_local :
+ o.localoper^.localsym:=tlocalvarsym(o.localoper^.localsymderef.resolve);
+ end;
+ end;
+
+end. \ No newline at end of file
diff --git a/closures/compiler/aasmtai.pas b/closures/compiler/aasmtai.pas
new file mode 100644
index 0000000000..7b511a8b2b
--- /dev/null
+++ b/closures/compiler/aasmtai.pas
@@ -0,0 +1,2654 @@
+{
+ Copyright (c) 1998-2006 by Florian Klaempfl
+
+ This unit implements an abstract asmoutput class for all processor types
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+{ @abstract(This unit implements an abstract asm output class for all processor types)
+ This unit implements an abstract assembler output class for all processors, these
+ are then overridden for each assembler writer to actually write the data in these
+ classes to an assembler file.
+}
+
+unit aasmtai;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cutils,cclasses,
+ globtype,systems,
+ cpuinfo,cpubase,
+ cgbase,cgutils,
+ symtype,
+ aasmbase,aasmdata,ogbase;
+
+ type
+ { keep the number of elements in this enumeration less or equal than 32 as long
+ as FPC knows only 4 byte and 32 byte sets (FK) }
+ taitype = (
+ ait_none,
+ ait_align,
+ ait_section,
+ ait_comment,
+ ait_string,
+ ait_instruction,
+ ait_datablock,
+ ait_symbol,
+ { needed to calc the size of a symbol }
+ ait_symbol_end,
+ ait_directive,
+ ait_label,
+ ait_const,
+ ait_real_32bit,
+ ait_real_64bit,
+ ait_real_80bit,
+ ait_comp_64bit,
+ ait_real_128bit,
+ ait_stab,
+ ait_force_line,
+ ait_function_name,
+{$ifdef alpha}
+ { the follow is for the DEC Alpha }
+ ait_frame,
+ ait_ent,
+{$endif alpha}
+{$ifdef ia64}
+ ait_bundle,
+ ait_stop,
+{$endif ia64}
+{$ifdef m68k}
+ ait_labeled_instruction,
+{$endif m68k}
+{$ifdef arm}
+ ait_thumb_func,
+{$endif arm}
+ { used to split into tiny assembler files }
+ ait_cutobject,
+ ait_regalloc,
+ ait_tempalloc,
+ { used to mark assembler blocks and inlined functions }
+ ait_marker,
+ { used to describe a new location of a variable }
+ ait_varloc,
+ { SEH directives used in ARM,MIPS and x86_64 COFF targets }
+ ait_seh_directive
+ );
+
+ taiconst_type = (
+ aitconst_128bit,
+ aitconst_64bit,
+ aitconst_32bit,
+ aitconst_16bit,
+ aitconst_8bit,
+ aitconst_sleb128bit,
+ aitconst_uleb128bit,
+ { win32 only }
+ aitconst_rva_symbol,
+ aitconst_secrel32_symbol,
+ { darwin only }
+ { From gcc/config/darwin.c (darwin_asm_output_dwarf_delta):
+ ***
+ Output a difference of two labels that will be an assembly time
+ constant if the two labels are local. (.long lab1-lab2 will be
+ very different if lab1 is at the boundary between two sections; it
+ will be relocated according to the second section, not the first,
+ so one ends up with a difference between labels in different
+ sections, which is bad in the dwarf2 eh context for instance.)
+ ***
+ We cannot use this everywhere, because older versions of the
+ darwin assembler don't support the construct used for these
+ relsyms (nor do they support dwarf, for that matter)
+ }
+ aitconst_darwin_dwarf_delta64,
+ aitconst_darwin_dwarf_delta32,
+ { ARM Thumb-2 only }
+ aitconst_half16bit { used for table jumps. The actual value is the 16bit value shifted left once }
+ );
+
+ const
+{$ifdef cpu64bitaddr}
+ aitconst_ptr = aitconst_64bit;
+{$else cpu64bitaddr}
+ aitconst_ptr = aitconst_32bit;
+{$endif cpu64bitaddr}
+
+{$ifdef cpu64bitalu}
+ aitconst_aint = aitconst_64bit;
+{$else cpu64bitaddr}
+ aitconst_aint = aitconst_32bit;
+{$endif cpu64bitaddr}
+
+ taitypestr : array[taitype] of string[24] = (
+ '<none>',
+ 'align',
+ 'section',
+ 'comment',
+ 'string',
+ 'instruction',
+ 'datablock',
+ 'symbol',
+ 'symbol_end',
+ 'symbol_directive',
+ 'label',
+ 'const',
+ 'real_32bit',
+ 'real_64bit',
+ 'real_80bit',
+ 'comp_64bit',
+ 'real_128bit',
+ 'stab',
+ 'force_line',
+ 'function_name',
+{$ifdef alpha}
+ { the follow is for the DEC Alpha }
+ 'frame',
+ 'ent',
+{$endif alpha}
+{$ifdef ia64}
+ 'bundle',
+ 'stop',
+{$endif ia64}
+{$ifdef m68k}
+ 'labeled_instr',
+{$endif m68k}
+{$ifdef arm}
+ 'thumb_func',
+{$endif arm}
+ 'cut',
+ 'regalloc',
+ 'tempalloc',
+ 'marker',
+ 'varloc',
+ 'seh_directive'
+ );
+
+ type
+ { Types of operand }
+ toptype=(top_none,top_reg,top_ref,top_const,top_bool,top_local
+{$ifdef arm}
+ { ARM only }
+ ,top_regset
+ ,top_shifterop
+ ,top_conditioncode
+ ,top_modeflags
+{$endif arm}
+{$ifdef m68k}
+ { m68k only }
+ ,top_regset
+{$endif m68k}
+ { i386 only});
+
+ { kinds of operations that an instruction can perform on an operand }
+ topertype = (operand_read,operand_write,operand_readwrite);
+
+ tlocaloper = record
+ localsym : pointer;
+ localsymderef : tderef;
+ localsymofs : longint;
+ localindexreg : tregister;
+ localscale : byte;
+ localgetoffset,
+ localforceref : boolean
+ end;
+ plocaloper = ^tlocaloper;
+
+ { please keep the size of this record <=12 bytes and keep it properly aligned }
+ toper = record
+ ot : longint;
+ case typ : toptype of
+ top_none : ();
+ top_reg : (reg:tregister);
+ top_ref : (ref:preference);
+ top_const : (val:tcgint);
+ top_bool : (b:boolean);
+ { local varsym that will be inserted in pass_generate_code }
+ top_local : (localoper:plocaloper);
+ {$ifdef arm}
+ top_regset : (regset:^tcpuregisterset; regtyp: tregistertype; subreg: tsubregister);
+ top_shifterop : (shifterop : pshifterop);
+ top_conditioncode : (cc : TAsmCond);
+ top_modeflags : (modeflags : tcpumodeflags);
+ {$endif arm}
+ {$ifdef m68k}
+ top_regset : (regset:^tcpuregisterset);
+ {$endif m68k}
+ end;
+ poper=^toper;
+
+ const
+ { ait_* types which don't result in executable code or which don't influence
+ the way the program runs/behaves, but which may be encountered by the
+ optimizer (= if it's sometimes added to the exprasm list). Update if you add
+ a new ait type! }
+ SkipInstr = [ait_comment, ait_symbol,ait_section
+ ,ait_stab, ait_function_name, ait_force_line
+ ,ait_regalloc, ait_tempalloc, ait_symbol_end, ait_directive
+ ,ait_varloc,ait_seh_directive];
+
+ { ait_* types which do not have line information (and hence which are of type
+ tai, otherwise, they are of type tailineinfo }
+ SkipLineInfo =[ait_label,
+ ait_regalloc,ait_tempalloc,
+ ait_stab,ait_function_name,
+ ait_cutobject,ait_marker,ait_varloc,ait_align,ait_section,ait_comment,
+ ait_const,
+{$ifdef arm}
+ ait_thumb_func,
+{$endif arm}
+ ait_real_32bit,ait_real_64bit,ait_real_80bit,ait_comp_64bit,ait_real_128bit,
+ ait_symbol,
+ ait_seh_directive
+ ];
+
+
+ type
+ { cut type, required for alphanumeric ordering of the assembler filenames }
+ TCutPlace=(cut_normal,cut_begin,cut_end);
+
+ TAsmMarker = (
+ mark_NoPropInfoStart,mark_NoPropInfoEnd,
+ mark_AsmBlockStart,mark_AsmBlockEnd,
+ mark_NoLineInfoStart,mark_NoLineInfoEnd,mark_BlockStart,
+ mark_Position
+ );
+
+ TRegAllocType = (ra_alloc,ra_dealloc,ra_sync,ra_resize);
+
+ TStabType = (stab_stabs,stab_stabn,stab_stabd);
+
+ TAsmDirective=(
+ asd_indirect_symbol,
+ asd_extern,asd_nasm_import, asd_toc_entry,
+ asd_reference,asd_no_dead_strip,asd_weak_reference,asd_lazy_reference,
+ asd_weak_definition
+ );
+
+ TAsmSehDirective=(
+ ash_proc,ash_endproc,
+ ash_endprologue,ash_handler,ash_handlerdata,
+ ash_eh,ash_32,ash_no32,
+ ash_setframe,ash_stackalloc,ash_pushreg,
+ ash_savereg,ash_savexmm,ash_pushframe
+ );
+
+
+ const
+ regallocstr : array[tregalloctype] of string[10]=('allocated','released','sync','resized');
+ tempallocstr : array[boolean] of string[10]=('released','allocated');
+ stabtypestr : array[TStabType] of string[5]=('stabs','stabn','stabd');
+ directivestr : array[TAsmDirective] of string[23]=(
+ 'indirect_symbol',
+ 'extern','nasm_import', 'tc', 'reference',
+ 'no_dead_strip','weak_reference','lazy_reference','weak_definition'
+ );
+ sehdirectivestr : array[TAsmSehDirective] of string[16]=(
+ '.seh_proc','.seh_endproc',
+ '.seh_endprologue','.seh_handler','.seh_handlerdata',
+ '.seh_eh','.seh_32','seh_no32',
+ '.seh_setframe','.seh_stackalloc','.seh_pushreg',
+ '.seh_savereg','.seh_savexmm','.seh_pushframe'
+ );
+
+ type
+ { abstract assembler item }
+ tai = class(TLinkedListItem)
+{$ifndef NOOPT}
+ { pointer to record with optimizer info about this tai object }
+ optinfo : pointer;
+{$endif NOOPT}
+ typ : taitype;
+ constructor Create;
+ constructor ppuload(t:taitype;ppufile:tcompilerppufile);virtual;
+ procedure ppuwrite(ppufile:tcompilerppufile);virtual;
+ procedure buildderefimpl;virtual;
+ procedure derefimpl;virtual;
+ end;
+
+ { abstract assembler item with line information }
+ tailineinfo = class(tai)
+ fileinfo : tfileposinfo;
+ constructor Create;
+ constructor ppuload(t:taitype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ end;
+
+ tai_simple = class(tai)
+ constructor create(_typ : taitype);
+ end;
+
+ taiclass = class of tai;
+
+ taiclassarray = array[taitype] of taiclass;
+
+ { Generates an assembler string }
+ tai_string = class(tailineinfo)
+ str : pchar;
+ { extra len so the string can contain an \0 }
+ len : longint;
+ constructor Create(const _str : string);
+ constructor Create_pchar(_str : pchar;length : longint);
+ destructor Destroy;override;
+ constructor ppuload(t:taitype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ function getcopy:tlinkedlistitem;override;
+ end;
+
+ { Generates a common label }
+ tai_symbol = class(tai)
+ sym : tasmsymbol;
+ value : puint;
+ size : longint;
+ is_global,
+ has_value : boolean;
+ constructor Create(_sym:tasmsymbol;siz:longint);
+ constructor Create_Global(_sym:tasmsymbol;siz:longint);
+ constructor Createname(const _name : string;_symtyp:Tasmsymtype;siz:longint);
+ constructor Createname_global(const _name : string;_symtyp:Tasmsymtype;siz:longint);
+ constructor Createname_global_value(const _name : string;_symtyp:Tasmsymtype;siz:longint;val:ptruint);
+ constructor ppuload(t:taitype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure derefimpl;override;
+ end;
+
+ tai_symbol_end = class(tailineinfo)
+ sym : tasmsymbol;
+ constructor Create(_sym:tasmsymbol);
+ constructor Createname(const _name : string);
+ constructor ppuload(t:taitype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure derefimpl;override;
+ end;
+
+ tai_directive = class(tailineinfo)
+ name : pshortstring;
+ directive : TAsmDirective;
+ constructor Create(_directive:TAsmDirective;const _name:string);
+ destructor Destroy;override;
+ constructor ppuload(t:taitype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ end;
+
+ { Generates an assembler label }
+ tai_label = class(tai)
+ is_global : boolean;
+ labsym : tasmlabel;
+ constructor Create(_labsym : tasmlabel);
+ constructor ppuload(t:taitype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure derefimpl;override;
+ end;
+
+ { Generates an assembler comment }
+ tai_comment = class(tai)
+ str : pchar;
+ constructor Create(_str : pchar);
+ destructor Destroy; override;
+ constructor ppuload(t:taitype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ function getcopy:tlinkedlistitem;override;
+ end;
+
+
+ { Generates a section / segment directive }
+ tai_section = class(tai)
+ sectype : TAsmSectiontype;
+ secorder : TasmSectionorder;
+ secalign : byte;
+ name : pshortstring;
+ sec : TObjSection; { used in binary writer }
+ destructor Destroy;override;
+ constructor ppuload(t:taitype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+{$push}{$warnings off}
+ private
+ { this constructor is made private on purpose }
+ { because sections should be created via new_section() }
+ constructor Create(Asectype:TAsmSectiontype;const Aname:string;Aalign:byte;Asecorder:TasmSectionorder=secorder_default);
+{$pop}
+ end;
+
+
+ { Generates an uninitializised data block }
+ tai_datablock = class(tailineinfo)
+ is_global : boolean;
+ sym : tasmsymbol;
+ size : asizeint;
+ constructor Create(const _name : string;_size : aint);
+ constructor Create_global(const _name : string;_size : asizeint);
+ constructor ppuload(t:taitype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure derefimpl;override;
+ end;
+
+
+ { Generates an integer const }
+ tai_const = class(tai)
+ sym,
+ endsym : tasmsymbol;
+ { if symbols and offset are provided the symofs is used,
+ the value is calculated during assembling }
+ symofs,
+ value : int64;
+ consttype : taiconst_type;
+ { we use for the 128bit int64/qword for now because I can't imagine a
+ case where we need 128 bit now (FK) }
+ constructor Create(_typ:taiconst_type;_value : int64);
+ constructor Create_128bit(_value : int64);
+ constructor Create_64bit(_value : int64);
+ constructor Create_32bit(_value : longint);
+ constructor Create_16bit(_value : word);
+ constructor Create_8bit(_value : byte);
+ constructor Create_char(size: integer; _value: dword);
+ constructor Create_sleb128bit(_value : int64);
+ constructor Create_uleb128bit(_value : qword);
+ constructor Create_aint(_value : aint);
+ constructor Create_pint(_value : pint);
+ constructor Create_sym(_sym:tasmsymbol);
+ constructor Create_type_sym(_typ:taiconst_type;_sym:tasmsymbol);
+ constructor Create_sym_offset(_sym:tasmsymbol;ofs:aint);
+ constructor Create_rel_sym(_typ:taiconst_type;_sym,_endsym:tasmsymbol);
+ constructor Create_rva_sym(_sym:tasmsymbol);
+ constructor Createname(const name:string;ofs:aint);
+ constructor ppuload(t:taitype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure derefimpl;override;
+ function getcopy:tlinkedlistitem;override;
+ function size:longint;
+ end;
+
+ { Generates a single float (32 bit real) }
+ tai_real_32bit = class(tai)
+ value : ts32real;
+ constructor Create(_value : ts32real);
+ constructor ppuload(t:taitype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ end;
+
+ tformatoptions = (fo_none,fo_hiloswapped);
+
+ { Generates a double float (64 bit real) }
+ tai_real_64bit = class(tai)
+ value : ts64real;
+{$ifdef ARM}
+ formatoptions : tformatoptions;
+ constructor Create_hiloswapped(_value : ts64real);
+{$endif ARM}
+ constructor Create(_value : ts64real);
+ constructor ppuload(t:taitype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ end;
+
+
+ { Generates an extended float (80 bit real) }
+ tai_real_80bit = class(tai)
+ value : ts80real;
+ savesize : byte;
+ constructor Create(_value : ts80real; _savesize: byte);
+ constructor ppuload(t:taitype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ end;
+
+
+ { Generates an float128 (128 bit real) }
+ tai_real_128bit = class(tai)
+ value : ts128real;
+ constructor Create(_value : ts128real);
+ constructor ppuload(t:taitype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ end;
+
+ { Generates a comp int (integer over 64 bits)
+
+ This is Intel 80x86 specific, and is not
+ really supported on other processors.
+ }
+ tai_comp_64bit = class(tai)
+ value : ts64comp;
+ constructor Create(_value : ts64comp);
+ constructor ppuload(t:taitype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ end;
+
+ { tai_stab }
+
+ tai_stab = class(tai)
+ str : pchar;
+ stabtype : TStabType;
+ constructor Create(_stabtype:TStabType;_str : pchar);
+ constructor Create_str(_stabtype:TStabType;const s:string);
+ constructor create_ansistr(_stabtype: TStabType; const s: ansistring);
+ destructor Destroy;override;
+ end;
+
+ tai_force_line = class(tailineinfo)
+ constructor Create;
+ end;
+
+ tai_function_name = class(tai)
+ funcname : pshortstring;
+ constructor create(const s:string);
+ destructor destroy;override;
+ end;
+
+ { Insert a cut to split assembler into several smaller files }
+ tai_cutobject = class(tai)
+ place : tcutplace;
+ constructor Create;
+ constructor Create_begin;
+ constructor Create_end;
+ constructor ppuload(t:taitype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ end;
+
+ { Insert a marker for assembler and inline blocks }
+ tai_marker = class(tai)
+ Kind: TAsmMarker;
+ Constructor Create(_Kind: TAsmMarker);
+ constructor ppuload(t:taitype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ end;
+
+ tai_tempalloc = class(tai)
+ allocation : boolean;
+{$ifdef EXTDEBUG}
+ problem : pshortstring;
+{$endif EXTDEBUG}
+ temppos,
+ tempsize : longint;
+ constructor alloc(pos,size:longint);
+ constructor dealloc(pos,size:longint);
+{$ifdef EXTDEBUG}
+ constructor allocinfo(pos,size:longint;const st:string);
+{$endif EXTDEBUG}
+ constructor ppuload(t:taitype;ppufile:tcompilerppufile);override;
+ destructor destroy;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ end;
+
+ tai_regalloc = class(tai)
+ reg : tregister;
+ ratype : TRegAllocType;
+ { reg(de)alloc belongs to this instruction, this
+ is only used for automatic inserted (de)alloc for
+ imaginary register and required for spilling code }
+ instr : tai;
+ constructor alloc(r : tregister;ainstr:tai);
+ constructor dealloc(r : tregister;ainstr:tai);
+ constructor sync(r : tregister);
+ constructor resize(r : tregister);
+ constructor ppuload(t:taitype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ end;
+
+ tadd_reg_instruction_proc=procedure(instr:Tai;r:tregister) of object;
+
+ { Class template for assembler instructions
+ }
+ tai_cpu_abstract = class(tailineinfo)
+ protected
+ procedure ppuloadoper(ppufile:tcompilerppufile;var o:toper);virtual;
+ procedure ppuwriteoper(ppufile:tcompilerppufile;const o:toper);virtual;
+ procedure ppubuildderefimploper(var o:toper);virtual;abstract;
+ procedure ppuderefoper(var o:toper);virtual;abstract;
+ public
+ { Condition flags for instruction }
+ condition : TAsmCond;
+ { Number of operands to instruction }
+ ops : byte;
+ { Number of allocate oper structures }
+ opercnt : byte;
+ { Operands of instruction }
+ oper : array[0..max_operands-1] of poper;
+ { Actual opcode of instruction }
+ opcode : tasmop;
+{$ifdef x86}
+ segprefix : tregister;
+{$endif x86}
+ { true if instruction is a jmp }
+ is_jmp : boolean; { is this instruction a jump? (needed for optimizer) }
+ Constructor Create(op : tasmop);virtual;
+ Destructor Destroy;override;
+ function getcopy:TLinkedListItem;override;
+ constructor ppuload(t:taitype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderefimpl;override;
+ procedure derefimpl;override;
+ procedure SetCondition(const c:TAsmCond);
+ procedure allocate_oper(opers:longint);
+ procedure loadconst(opidx:longint;l:aint);
+ procedure loadsymbol(opidx:longint;s:tasmsymbol;sofs:longint);
+ procedure loadlocal(opidx:longint;s:pointer;sofs:longint;indexreg:tregister;scale:byte;getoffset,forceref:boolean);
+ procedure loadref(opidx:longint;const r:treference);
+ procedure loadreg(opidx:longint;r:tregister);
+ procedure loadoper(opidx:longint;o:toper);
+ procedure clearop(opidx:longint);
+ procedure freeop(opidx:longint);
+ { register allocator }
+ function is_same_reg_move(regtype: Tregistertype):boolean;virtual;
+ function spilling_get_operation_type(opnr: longint): topertype;virtual;
+ function spilling_get_operation_type_ref(opnr: longint; reg: tregister): topertype;virtual;
+
+ function Pass1(objdata:TObjData):longint;virtual;
+ procedure Pass2(objdata:TObjData);virtual;
+
+ procedure resetpass1; virtual;
+ procedure resetpass2; virtual;
+ end;
+ tai_cpu_class = class of tai_cpu_abstract;
+
+ { Buffer type used for alignment }
+ tfillbuffer = array[0..63] of char;
+
+ { alignment for operator }
+ tai_align_abstract = class(tai)
+ aligntype : byte; { 1 = no align, 2 = word align, 4 = dword align }
+ fillsize : byte; { real size to fill }
+ fillop : byte; { value to fill with - optional }
+ use_op : boolean;
+ constructor Create(b:byte);virtual;
+ constructor Create_op(b: byte; _op: byte);virtual;
+ constructor Create_zeros(b:byte);
+ constructor ppuload(t:taitype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ function calculatefillbuf(var buf : tfillbuffer;executable : boolean):pchar;virtual;
+ end;
+ tai_align_class = class of tai_align_abstract;
+
+ tai_varloc = class(tai)
+ newlocation,
+ newlocationhi : tregister;
+ varsym : tsym;
+ constructor create(sym : tsym;loc : tregister);
+ constructor create64(sym : tsym;loc,lochi : tregister);
+ constructor ppuload(t:taitype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderefimpl;override;
+ procedure derefimpl;override;
+ end;
+
+ TSehDirectiveDatatype=(sd_none,sd_string,sd_reg,sd_offset,sd_regoffset);
+
+ TSehDirectiveData=record
+ case typ: TSehDirectiveDatatype of
+ sd_none: ();
+ sd_string: (name:pshortstring;flags:byte);
+ sd_reg,sd_offset,sd_regoffset: (reg:TRegister;offset:dword);
+ end;
+
+ tai_seh_directive = class(tai)
+ kind: TAsmSehDirective;
+ data: TSehDirectiveData;
+ constructor create(_kind:TAsmSehDirective);
+ constructor create_name(_kind:TAsmSehDirective;const _name: string);
+ constructor create_reg(_kind:TAsmSehDirective;r:TRegister);
+ constructor create_offset(_kind:TAsmSehDirective;ofs:dword);
+ constructor create_reg_offset(_kind:TAsmSehDirective;r:TRegister;ofs:dword);
+ constructor ppuload(t:taitype;ppufile:tcompilerppufile);override;
+ destructor destroy;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure generate_code(objdata:TObjData);virtual;
+ property datatype: TSehDirectiveDatatype read data.typ;
+ end;
+ tai_seh_directive_class=class of tai_seh_directive;
+
+ var
+ { array with all class types for tais }
+ aiclass : taiclassarray;
+
+ { target specific tais, possibly overwritten in target specific aasmcpu }
+ cai_align : tai_align_class = tai_align_abstract;
+ cai_cpu : tai_cpu_class = tai_cpu_abstract;
+ cai_seh_directive: tai_seh_directive_class = tai_seh_directive;
+
+ { hook to notify uses of registers }
+ add_reg_instruction_hook : tadd_reg_instruction_proc;
+
+ procedure maybe_new_object_file(list:TAsmList);
+ procedure new_section(list:TAsmList;Asectype:TAsmSectiontype;const Aname:string;Aalign:byte;Asecorder:TasmSectionorder=secorder_default);
+ procedure section_symbol_start(list:TAsmList;const Aname:string;Asymtyp:Tasmsymtype;
+ Aglobal:boolean;Asectype:TAsmSectiontype;Aalign:byte);
+ procedure section_symbol_end(list:TAsmList;const Aname:string);
+
+ function ppuloadai(ppufile:tcompilerppufile):tai;
+ procedure ppuwriteai(ppufile:tcompilerppufile;n:tai);
+
+
+implementation
+
+ uses
+ SysUtils,
+ verbose,
+ globals,
+ fmodule;
+
+ const
+ pputaimarker = 254;
+
+
+{****************************************************************************
+ Helpers
+ ****************************************************************************}
+
+ procedure maybe_new_object_file(list:TAsmList);
+ begin
+ if create_smartlink_library then
+ list.concat(tai_cutobject.create);
+ end;
+
+
+ procedure new_section(list:TAsmList;Asectype:TAsmSectiontype;const Aname:string;Aalign:byte;Asecorder:TasmSectionorder=secorder_default);
+ begin
+ list.concat(tai_section.create(Asectype,Aname,Aalign,Asecorder));
+ list.concat(cai_align.create(Aalign));
+ end;
+
+
+ procedure section_symbol_start(list:TAsmList;const Aname:string;Asymtyp:Tasmsymtype;
+ Aglobal:boolean;Asectype:TAsmSectiontype;Aalign:byte);
+ begin
+ maybe_new_object_file(list);
+ new_section(list,Asectype,Aname,Aalign);
+ if Aglobal or
+ create_smartlink then
+ list.concat(tai_symbol.createname_global(Aname,Asymtyp,0))
+ else
+ list.concat(tai_symbol.createname(Aname,Asymtyp,0));
+ end;
+
+
+ procedure section_symbol_end(list:TAsmList;const Aname:string);
+ begin
+ list.concat(tai_symbol_end.createname(Aname));
+ end;
+
+
+ function ppuloadai(ppufile:tcompilerppufile):tai;
+ var
+ b : byte;
+ t : taitype;
+ begin
+ { marker }
+ b:=ppufile.getbyte;
+ if b<>pputaimarker then
+ internalerror(200208181);
+ { load nodetype }
+ t:=taitype(ppufile.getbyte);
+ if t<>ait_none then
+ begin
+ if t>high(taitype) then
+ internalerror(200208182);
+ if not assigned(aiclass[t]) then
+ internalerror(200208183);
+ {writeln('taiload: ',taitypestr[t]);}
+ { generate tai of the correct class }
+ ppuloadai:=aiclass[t].ppuload(t,ppufile);
+ end
+ else
+ ppuloadai:=nil;
+ end;
+
+
+ procedure ppuwriteai(ppufile:tcompilerppufile;n:tai);
+ begin
+ { marker, read by ppuloadnode }
+ ppufile.putbyte(pputaimarker);
+ if assigned(n) then
+ begin
+ { type, read by ppuloadnode }
+ ppufile.putbyte(byte(n.typ));
+ {writeln('taiwrite: ',taitypestr[n.typ]);}
+ n.ppuwrite(ppufile);
+ end
+ else
+ ppufile.putbyte(byte(ait_none));
+ end;
+
+
+ constructor tai_varloc.create(sym: tsym; loc: tregister);
+ begin
+ inherited Create;
+ typ:=ait_varloc;
+ newlocation:=loc;
+ newlocationhi:=NR_NO;
+ varsym:=sym;
+ end;
+
+
+ constructor tai_varloc.create64(sym: tsym; loc: tregister;lochi : tregister);
+ begin
+ inherited Create;
+ typ:=ait_varloc;
+ newlocation:=loc;
+ newlocationhi:=lochi;
+ varsym:=sym;
+ end;
+
+
+ constructor tai_varloc.ppuload(t: taitype; ppufile: tcompilerppufile);
+ begin
+ inherited ppuload(t, ppufile);
+ end;
+
+
+ procedure tai_varloc.ppuwrite(ppufile: tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ end;
+
+
+ procedure tai_varloc.buildderefimpl;
+ begin
+ inherited buildderefimpl;
+ end;
+
+
+ procedure tai_varloc.derefimpl;
+ begin
+ inherited derefimpl;
+ end;
+
+
+{****************************************************************************
+ TAI
+ ****************************************************************************}
+
+ constructor tai.Create;
+ begin
+{$ifndef NOOPT}
+ optinfo:=nil;
+{$endif NOOPT}
+ end;
+
+
+ constructor tai.ppuload(t:taitype;ppufile:tcompilerppufile);
+ begin
+ typ:=t;
+{$ifndef NOOPT}
+ optinfo:=nil;
+{$endif}
+ end;
+
+
+ procedure tai.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ end;
+
+
+ procedure tai.buildderefimpl;
+ begin
+ end;
+
+
+ procedure tai.derefimpl;
+ begin
+ end;
+
+
+{****************************************************************************
+ TAILINEINFO
+ ****************************************************************************}
+
+ constructor tailineinfo.create;
+ begin
+ inherited create;
+ fileinfo:=current_filepos;
+ end;
+
+
+ constructor tailineinfo.ppuload(t:taitype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ ppufile.getposinfo(fileinfo);
+ end;
+
+
+ procedure tailineinfo.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putposinfo(fileinfo);
+ end;
+
+
+{****************************************************************************
+ TAI_SIMPLE
+ ****************************************************************************}
+
+ constructor tai_simple.create(_typ : taitype);
+ begin
+ inherited create;
+ typ:=_typ;
+ end;
+
+
+{****************************************************************************
+ TAI_SECTION
+ ****************************************************************************}
+
+ constructor tai_section.Create(Asectype:TAsmSectiontype;const Aname:string;Aalign:byte;Asecorder:TasmSectionorder=secorder_default);
+ begin
+ inherited Create;
+ typ:=ait_section;
+ sectype:=asectype;
+ secalign:=Aalign;
+ secorder:=Asecorder;
+ name:=stringdup(Aname);
+ sec:=nil;
+ end;
+
+
+ constructor tai_section.ppuload(t:taitype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ sectype:=TAsmSectiontype(ppufile.getbyte);
+ secalign:=ppufile.getbyte;
+ name:=stringdup(ppufile.getstring);
+ sec:=nil;
+ end;
+
+
+ destructor tai_section.Destroy;
+ begin
+ stringdispose(name);
+ end;
+
+
+ procedure tai_section.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putbyte(byte(sectype));
+ ppufile.putbyte(secalign);
+ ppufile.putstring(name^);
+ end;
+
+
+{****************************************************************************
+ TAI_DATABLOCK
+ ****************************************************************************}
+
+ constructor tai_datablock.Create(const _name : string;_size : aint);
+
+ begin
+ inherited Create;
+ typ:=ait_datablock;
+ sym:=current_asmdata.DefineAsmSymbol(_name,AB_LOCAL,AT_DATA);
+ { keep things aligned }
+ if _size<=0 then
+ _size:=sizeof(aint);
+ size:=_size;
+ is_global:=false;
+ end;
+
+
+ constructor tai_datablock.Create_global(const _name : string;_size : asizeint);
+ begin
+ inherited Create;
+ typ:=ait_datablock;
+ sym:=current_asmdata.DefineAsmSymbol(_name,AB_GLOBAL,AT_DATA);
+ { keep things aligned }
+ if _size<=0 then
+ _size:=sizeof(aint);
+ size:=_size;
+ is_global:=true;
+ end;
+
+
+ constructor tai_datablock.ppuload(t:taitype;ppufile:tcompilerppufile);
+ begin
+ inherited Create;
+ sym:=ppufile.getasmsymbol;
+ size:=ppufile.getaint;
+ is_global:=boolean(ppufile.getbyte);
+ end;
+
+
+ procedure tai_datablock.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putasmsymbol(sym);
+ ppufile.putaint(size);
+ ppufile.putbyte(byte(is_global));
+ end;
+
+
+ procedure tai_datablock.derefimpl;
+ begin
+ end;
+
+
+{****************************************************************************
+ TAI_SYMBOL
+ ****************************************************************************}
+
+ constructor tai_symbol.Create(_sym:tasmsymbol;siz:longint);
+ begin
+ inherited Create;
+ typ:=ait_symbol;
+ sym:=_sym;
+ size:=siz;
+ sym.bind:=AB_LOCAL;
+ is_global:=false;
+ end;
+
+
+ constructor tai_symbol.Create_global(_sym:tasmsymbol;siz:longint);
+ begin
+ inherited Create;
+ typ:=ait_symbol;
+ sym:=_sym;
+ size:=siz;
+ { don't override PRIVATE_EXTERN with GLOBAL }
+ if not(sym.bind in [AB_GLOBAL,AB_PRIVATE_EXTERN]) then
+ sym.bind:=AB_GLOBAL;
+ is_global:=true;
+ end;
+
+
+ constructor tai_symbol.Createname(const _name : string;_symtyp:Tasmsymtype;siz:longint);
+ begin
+ inherited Create;
+ typ:=ait_symbol;
+ sym:=current_asmdata.DefineAsmSymbol(_name,AB_LOCAL,_symtyp);
+ size:=siz;
+ is_global:=false;
+ end;
+
+
+ constructor tai_symbol.Createname_global(const _name : string;_symtyp:Tasmsymtype;siz:longint);
+ begin
+ inherited Create;
+ typ:=ait_symbol;
+ sym:=current_asmdata.DefineAsmSymbol(_name,AB_GLOBAL,_symtyp);
+ size:=siz;
+ is_global:=true;
+ end;
+
+
+ constructor tai_symbol.createname_global_value(const _name: string;_symtyp: tasmsymtype; siz: longint; val: ptruint);
+ begin
+ Createname_global(_name,_symtyp,siz);
+ value:=val;
+ has_value:=true;
+ end;
+
+
+ constructor tai_symbol.ppuload(t:taitype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ sym:=ppufile.getasmsymbol;
+ size:=ppufile.getlongint;
+ is_global:=boolean(ppufile.getbyte);
+ end;
+
+
+ procedure tai_symbol.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putasmsymbol(sym);
+ ppufile.putlongint(size);
+ ppufile.putbyte(byte(is_global));
+ end;
+
+
+ procedure tai_symbol.derefimpl;
+ begin
+ end;
+
+
+{****************************************************************************
+ TAI_SYMBOL_END
+ ****************************************************************************}
+
+ constructor tai_symbol_end.Create(_sym:tasmsymbol);
+ begin
+ inherited Create;
+ typ:=ait_symbol_end;
+ sym:=_sym;
+ end;
+
+
+ constructor tai_symbol_end.Createname(const _name : string);
+ begin
+ inherited Create;
+ typ:=ait_symbol_end;
+ sym:=current_asmdata.RefAsmSymbol(_name);
+ end;
+
+
+ constructor tai_symbol_end.ppuload(t:taitype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ sym:=ppufile.getasmsymbol;
+ end;
+
+
+ procedure tai_symbol_end.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putasmsymbol(sym);
+ end;
+
+
+ procedure tai_symbol_end.derefimpl;
+ begin
+ end;
+
+
+{****************************************************************************
+ TAI_SYMBOL_END
+ ****************************************************************************}
+
+ constructor tai_directive.Create(_directive:TAsmDirective;const _name:string);
+ begin
+ inherited Create;
+ typ:=ait_directive;
+ name:=stringdup(_name);
+ directive:=_directive;
+ end;
+
+
+ destructor tai_directive.Destroy;
+ begin
+ stringdispose(name);
+ end;
+
+
+ constructor tai_directive.ppuload(t:taitype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ name:=stringdup(ppufile.getstring);
+ directive:=TAsmDirective(ppufile.getbyte);
+ end;
+
+
+ procedure tai_directive.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putstring(name^);
+ ppufile.putbyte(byte(directive));
+ end;
+
+
+{****************************************************************************
+ TAI_CONST
+ ****************************************************************************}
+
+ constructor tai_const.Create(_typ:taiconst_type;_value : int64);
+ begin
+ inherited Create;
+ typ:=ait_const;
+ consttype:=_typ;
+ value:=_value;
+ sym:=nil;
+ endsym:=nil;
+ end;
+
+
+ constructor tai_const.Create_128bit(_value : int64);
+ begin
+ inherited Create;
+ typ:=ait_const;
+ consttype:=aitconst_128bit;
+ value:=_value;
+ sym:=nil;
+ endsym:=nil;
+ end;
+
+
+ constructor tai_const.Create_64bit(_value : int64);
+ begin
+ inherited Create;
+ typ:=ait_const;
+ consttype:=aitconst_64bit;
+ value:=_value;
+ sym:=nil;
+ endsym:=nil;
+ end;
+
+
+ constructor tai_const.Create_32bit(_value : longint);
+ begin
+ inherited Create;
+ typ:=ait_const;
+ consttype:=aitconst_32bit;
+ value:=_value;
+ sym:=nil;
+ endsym:=nil;
+ end;
+
+
+ constructor tai_const.Create_16bit(_value : word);
+ begin
+ inherited Create;
+ typ:=ait_const;
+ consttype:=aitconst_16bit;
+ value:=_value;
+ sym:=nil;
+ endsym:=nil;
+ end;
+
+
+ constructor tai_const.Create_8bit(_value : byte);
+ begin
+ inherited Create;
+ typ:=ait_const;
+ consttype:=aitconst_8bit;
+ value:=_value;
+ sym:=nil;
+ endsym:=nil;
+ end;
+
+
+ constructor tai_const.Create_char(size: integer; _value: dword);
+ begin
+ inherited Create;
+ typ:=ait_const;
+ case size of
+ 1:
+ begin
+ consttype:=aitconst_8bit;
+ value:=byte(_value)
+ end;
+ 2:
+ begin
+ consttype:=aitconst_16bit;
+ value:=word(_value)
+ end
+ else
+ InternalError(2010030701)
+ end
+ end;
+
+
+ constructor tai_const.Create_sleb128bit(_value : int64);
+ begin
+ inherited Create;
+ typ:=ait_const;
+ consttype:=aitconst_sleb128bit;
+ value:=_value;
+ sym:=nil;
+ endsym:=nil;
+ end;
+
+
+ constructor tai_const.Create_uleb128bit(_value : qword);
+ begin
+ inherited Create;
+ typ:=ait_const;
+ consttype:=aitconst_uleb128bit;
+ value:=int64(_value);
+ sym:=nil;
+ endsym:=nil;
+ end;
+
+
+ constructor tai_const.Create_aint(_value : aint);
+ begin
+ inherited Create;
+ typ:=ait_const;
+ consttype:=aitconst_aint;
+ value:=_value;
+ sym:=nil;
+ endsym:=nil;
+ end;
+
+
+ constructor tai_const.Create_pint(_value : pint);
+ begin
+ inherited Create;
+ typ:=ait_const;
+ consttype:=aitconst_ptr;
+ value:=_value;
+ sym:=nil;
+ endsym:=nil;
+ end;
+
+
+ constructor tai_const.Create_type_sym(_typ:taiconst_type;_sym:tasmsymbol);
+ begin
+ inherited Create;
+ typ:=ait_const;
+ consttype:=_typ;
+ sym:=_sym;
+ endsym:=nil;
+ value:=0;
+ { update sym info }
+ if assigned(sym) then
+ sym.increfs;
+ end;
+
+
+ constructor tai_const.Create_sym(_sym:tasmsymbol);
+ begin
+ self.create_sym_offset(_sym,0);
+ end;
+
+
+ constructor tai_const.Create_sym_offset(_sym:tasmsymbol;ofs:aint);
+ begin
+ inherited Create;
+ typ:=ait_const;
+ consttype:=aitconst_ptr;
+ { sym is allowed to be nil, this is used to write nil pointers }
+ sym:=_sym;
+ endsym:=nil;
+ { store the original offset in symofs so that we can recalculate the
+ value field in the assembler }
+ symofs:=ofs;
+ value:=ofs;
+ { update sym info }
+ if assigned(sym) then
+ sym.increfs;
+ end;
+
+
+ constructor tai_const.Create_rel_sym(_typ:taiconst_type;_sym,_endsym:tasmsymbol);
+ begin
+ self.create_sym_offset(_sym,0);
+ consttype:=_typ;
+ endsym:=_endsym;
+ endsym.increfs;
+ end;
+
+
+ constructor tai_const.Create_rva_sym(_sym:tasmsymbol);
+ begin
+ self.create_sym_offset(_sym,0);
+ consttype:=aitconst_rva_symbol;
+ end;
+
+
+ constructor tai_const.Createname(const name:string;ofs:aint);
+ begin
+ self.create_sym_offset(current_asmdata.RefAsmSymbol(name),ofs);
+ end;
+
+
+ constructor tai_const.ppuload(t:taitype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ consttype:=taiconst_type(ppufile.getbyte);
+ sym:=ppufile.getasmsymbol;
+ endsym:=ppufile.getasmsymbol;
+ value:=ppufile.getint64;
+ end;
+
+
+ procedure tai_const.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putbyte(byte(consttype));
+ ppufile.putasmsymbol(sym);
+ ppufile.putasmsymbol(endsym);
+ ppufile.putint64(value);
+ end;
+
+
+ procedure tai_const.derefimpl;
+ begin
+ end;
+
+
+ function tai_const.getcopy:tlinkedlistitem;
+ begin
+ getcopy:=inherited getcopy;
+ { we need to increase the reference number }
+ sym.increfs;
+ if assigned(endsym) then
+ endsym.increfs;
+ end;
+
+
+ function tai_const.size:longint;
+ begin
+ case consttype of
+ aitconst_8bit :
+ result:=1;
+ aitconst_16bit :
+ result:=2;
+ aitconst_32bit,aitconst_darwin_dwarf_delta32:
+ result:=4;
+ aitconst_64bit,aitconst_darwin_dwarf_delta64:
+ result:=8;
+ aitconst_secrel32_symbol,
+ aitconst_rva_symbol :
+ if target_info.system=system_x86_64_win64 then
+ result:=sizeof(longint)
+ else
+ result:=sizeof(pint);
+ aitconst_uleb128bit :
+ result:=LengthUleb128(qword(value));
+ aitconst_sleb128bit :
+ result:=LengthSleb128(value);
+ aitconst_half16bit:
+ result:=2;
+ else
+ internalerror(200603253);
+ end;
+ end;
+
+
+{****************************************************************************
+ TAI_real_32bit
+ ****************************************************************************}
+
+ constructor tai_real_32bit.Create(_value : ts32real);
+
+ begin
+ inherited Create;
+ typ:=ait_real_32bit;
+ value:=_value;
+ end;
+
+ constructor tai_real_32bit.ppuload(t:taitype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ value:=ppufile.getreal;
+ end;
+
+
+ procedure tai_real_32bit.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putreal(value);
+ end;
+
+
+{****************************************************************************
+ TAI_real_64bit
+ ****************************************************************************}
+
+ constructor tai_real_64bit.Create(_value : ts64real);
+
+ begin
+ inherited Create;
+ typ:=ait_real_64bit;
+ value:=_value;
+ end;
+
+
+{$ifdef ARM}
+ constructor tai_real_64bit.Create_hiloswapped(_value : ts64real);
+
+ begin
+ inherited Create;
+ typ:=ait_real_64bit;
+ value:=_value;
+ formatoptions:=fo_hiloswapped;
+ end;
+{$endif ARM}
+
+ constructor tai_real_64bit.ppuload(t:taitype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ value:=ppufile.getreal;
+{$ifdef ARM}
+ formatoptions:=tformatoptions(ppufile.getbyte);
+{$endif ARM}
+ end;
+
+
+ procedure tai_real_64bit.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putreal(value);
+{$ifdef ARM}
+ ppufile.putbyte(byte(formatoptions));
+{$endif ARM}
+ end;
+
+
+{****************************************************************************
+ TAI_real_80bit
+ ****************************************************************************}
+
+ constructor tai_real_80bit.Create(_value : ts80real; _savesize: byte);
+
+ begin
+ inherited Create;
+ typ:=ait_real_80bit;
+ value:=_value;
+ savesize:=_savesize;
+ end;
+
+
+ constructor tai_real_80bit.ppuload(t:taitype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ value:=ppufile.getreal;
+ savesize:=ppufile.getbyte;
+ end;
+
+
+ procedure tai_real_80bit.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putreal(value);
+ ppufile.putbyte(savesize);
+ end;
+
+
+{****************************************************************************
+ TAI_real_80bit
+ ****************************************************************************}
+
+ constructor tai_real_128bit.Create(_value : ts128real);
+
+ begin
+ inherited Create;
+ typ:=ait_real_128bit;
+ value:=_value;
+ end;
+
+
+ constructor tai_real_128bit.ppuload(t:taitype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ value:=ppufile.getreal;
+ end;
+
+
+ procedure tai_real_128bit.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putreal(value);
+ end;
+
+
+{****************************************************************************
+ Tai_comp_64bit
+ ****************************************************************************}
+
+ constructor tai_comp_64bit.Create(_value : ts64comp);
+
+ begin
+ inherited Create;
+ typ:=ait_comp_64bit;
+ value:=_value;
+ end;
+
+
+ constructor tai_comp_64bit.ppuload(t:taitype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ ppufile.putdata(value,sizeof(value));
+ end;
+
+
+ procedure tai_comp_64bit.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.getdata(value,sizeof(value));
+ end;
+
+
+{****************************************************************************
+ TAI_STRING
+ ****************************************************************************}
+
+ constructor tai_string.Create(const _str : string);
+ begin
+ inherited Create;
+ typ:=ait_string;
+ len:=length(_str);
+ getmem(str,len+1);
+ strpcopy(str,_str);
+ end;
+
+
+ constructor tai_string.Create_pchar(_str : pchar;length : longint);
+ begin
+ inherited Create;
+ typ:=ait_string;
+ str:=_str;
+ len:=length;
+ end;
+
+
+ destructor tai_string.destroy;
+ begin
+ if str<>nil then
+ freemem(str);
+ inherited Destroy;
+ end;
+
+
+ constructor tai_string.ppuload(t:taitype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ len:=ppufile.getlongint;
+ getmem(str,len);
+ ppufile.getdata(str^,len);
+ end;
+
+
+ procedure tai_string.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putlongint(len);
+ ppufile.putdata(str^,len);
+ end;
+
+
+ function tai_string.getcopy : tlinkedlistitem;
+ var
+ p : tlinkedlistitem;
+ begin
+ p:=inherited getcopy;
+ getmem(tai_string(p).str,len);
+ move(str^,tai_string(p).str^,len);
+ getcopy:=p;
+ end;
+
+
+{****************************************************************************
+ TAI_LABEL
+ ****************************************************************************}
+
+ constructor tai_label.create(_labsym : tasmlabel);
+ begin
+ inherited Create;
+ typ:=ait_label;
+ labsym:=_labsym;
+ labsym.is_set:=true;
+ is_global:=(labsym.bind in [AB_GLOBAL,AB_PRIVATE_EXTERN]);
+ end;
+
+
+ constructor tai_label.ppuload(t:taitype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ labsym:=tasmlabel(ppufile.getasmsymbol);
+ is_global:=boolean(ppufile.getbyte);
+ end;
+
+
+ procedure tai_label.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putasmsymbol(labsym);
+ ppufile.putbyte(byte(is_global));
+ end;
+
+
+ procedure tai_label.derefimpl;
+ begin
+ labsym.is_set:=true;
+ end;
+
+
+{****************************************************************************
+ tai_comment comment to be inserted in the assembler file
+ ****************************************************************************}
+
+ constructor tai_comment.Create(_str : pchar);
+
+ begin
+ inherited Create;
+ typ:=ait_comment;
+ str:=_str;
+ end;
+
+ destructor tai_comment.destroy;
+
+ begin
+ freemem(str);
+ inherited Destroy;
+ end;
+
+ constructor tai_comment.ppuload(t:taitype;ppufile:tcompilerppufile);
+ var
+ len : longint;
+ begin
+ inherited ppuload(t,ppufile);
+ len:=ppufile.getlongint;
+ getmem(str,len+1);
+ ppufile.getdata(str^,len);
+ str[len]:=#0;
+ end;
+
+
+ procedure tai_comment.ppuwrite(ppufile:tcompilerppufile);
+ var
+ len : longint;
+ begin
+ inherited ppuwrite(ppufile);
+ len:=strlen(str);
+ ppufile.putlongint(len);
+ ppufile.putdata(str^,len);
+ end;
+
+
+ function tai_comment.getcopy : tlinkedlistitem;
+ var
+ p : tlinkedlistitem;
+ begin
+ p:=inherited getcopy;
+ getmem(tai_comment(p).str,strlen(str)+1);
+ move(str^,tai_comment(p).str^,strlen(str)+1);
+ getcopy:=p;
+ end;
+
+
+{****************************************************************************
+ TAI_STABS
+ ****************************************************************************}
+
+ constructor tai_stab.create(_stabtype:TStabType;_str : pchar);
+ begin
+ inherited create;
+ typ:=ait_stab;
+ str:=_str;
+ stabtype:=_stabtype;
+ end;
+
+ constructor tai_stab.create_str(_stabtype:TStabType;const s:string);
+ begin
+ self.create(_stabtype,strpnew(s));
+ end;
+
+ constructor tai_stab.create_ansistr(_stabtype:TStabType;const s:ansistring);
+ begin
+ inherited create;
+ typ:=ait_stab;
+ stabtype:=_stabtype;
+ getmem(str,length(s)+1);
+ move(s[1],str^,length(s)+1);
+ end;
+
+ destructor tai_stab.destroy;
+ begin
+ freemem(str);
+ inherited destroy;
+ end;
+
+
+{****************************************************************************
+ TAI_FORCE_LINE
+ ****************************************************************************}
+
+ constructor tai_force_line.create;
+ begin
+ inherited create;
+ typ:=ait_force_line;
+ end;
+
+
+{****************************************************************************
+ TAI_FUNCTION_NAME
+ ****************************************************************************}
+
+ constructor tai_function_name.create(const s:string);
+ begin
+ inherited create;
+ typ:=ait_function_name;
+ funcname:=stringdup(s);
+ end;
+
+ destructor tai_function_name.destroy;
+ begin
+ stringdispose(funcname);
+ inherited destroy;
+ end;
+
+
+{****************************************************************************
+ TAI_CUTOBJECT
+ ****************************************************************************}
+
+ constructor tai_cutobject.Create;
+ begin
+ inherited Create;
+ typ:=ait_cutobject;
+ place:=cut_normal;
+ end;
+
+
+ constructor tai_cutobject.Create_begin;
+ begin
+ inherited Create;
+ typ:=ait_cutobject;
+ place:=cut_begin;
+ end;
+
+
+ constructor tai_cutobject.Create_end;
+ begin
+ inherited Create;
+ typ:=ait_cutobject;
+ place:=cut_end;
+ end;
+
+
+ constructor tai_cutobject.ppuload(t:taitype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ place:=TCutPlace(ppufile.getbyte);
+ end;
+
+
+ procedure tai_cutobject.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putbyte(byte(place));
+ end;
+
+
+{****************************************************************************
+ Tai_Marker
+ ****************************************************************************}
+
+ constructor Tai_Marker.Create(_Kind: TAsmMarker);
+ begin
+ Inherited Create;
+ typ := ait_marker;
+ Kind := _Kind;
+ end;
+
+
+ constructor Tai_Marker.ppuload(t:taitype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ kind:=TAsmMarker(ppufile.getbyte);
+ end;
+
+
+ procedure Tai_Marker.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putbyte(byte(kind));
+ end;
+
+
+{*****************************************************************************
+ tai_tempalloc
+*****************************************************************************}
+
+ constructor tai_tempalloc.alloc(pos,size:longint);
+ begin
+ inherited Create;
+ typ:=ait_tempalloc;
+ allocation:=true;
+ temppos:=pos;
+ tempsize:=size;
+{$ifdef EXTDEBUG}
+ problem:=nil;
+{$endif EXTDEBUG}
+ end;
+
+
+ destructor tai_tempalloc.destroy;
+ begin
+{$ifdef EXTDEBUG}
+ stringdispose(problem);
+{$endif EXTDEBUG}
+ inherited destroy;
+ end;
+
+
+ constructor tai_tempalloc.dealloc(pos,size:longint);
+ begin
+ inherited Create;
+ typ:=ait_tempalloc;
+ allocation:=false;
+ temppos:=pos;
+ tempsize:=size;
+{$ifdef EXTDEBUG}
+ problem:=nil;
+{$endif EXTDEBUG}
+ end;
+
+
+{$ifdef EXTDEBUG}
+ constructor tai_tempalloc.allocinfo(pos,size:longint;const st:string);
+ begin
+ inherited Create;
+ typ:=ait_tempalloc;
+ allocation:=false;
+ temppos:=pos;
+ tempsize:=size;
+ problem:=stringdup(st);
+ end;
+{$endif EXTDEBUG}
+
+
+ constructor tai_tempalloc.ppuload(t:taitype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ temppos:=ppufile.getlongint;
+ tempsize:=ppufile.getlongint;
+ allocation:=boolean(ppufile.getbyte);
+{$ifdef EXTDEBUG}
+ problem:=nil;
+{$endif EXTDEBUG}
+ end;
+
+
+ procedure tai_tempalloc.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putlongint(temppos);
+ ppufile.putlongint(tempsize);
+ ppufile.putbyte(byte(allocation));
+ end;
+
+
+{*****************************************************************************
+ tai_regalloc
+*****************************************************************************}
+
+ constructor tai_regalloc.alloc(r : tregister;ainstr:tai);
+ begin
+ inherited create;
+ typ:=ait_regalloc;
+ ratype:=ra_alloc;
+ reg:=r;
+ { ainstr must be an instruction }
+ if assigned(ainstr) and
+ (ainstr.typ<>ait_instruction) then
+ internalerror(200411011);
+ instr:=ainstr;
+ end;
+
+
+ constructor tai_regalloc.dealloc(r : tregister;ainstr:tai);
+ begin
+ inherited create;
+ typ:=ait_regalloc;
+ ratype:=ra_dealloc;
+ reg:=r;
+ { ainstr must be an instruction }
+ if assigned(ainstr) and
+ (ainstr.typ<>ait_instruction) then
+ internalerror(200411012);
+ instr:=ainstr;
+ end;
+
+
+ constructor tai_regalloc.sync(r : tregister);
+ begin
+ inherited create;
+ typ:=ait_regalloc;
+ ratype:=ra_sync;
+ reg:=r;
+ end;
+
+
+ constructor tai_regalloc.resize(r : tregister);
+ begin
+ inherited create;
+ typ:=ait_regalloc;
+ ratype:=ra_resize;
+ reg:=r;
+ end;
+
+
+ constructor tai_regalloc.ppuload(t:taitype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ ppufile.getdata(reg,sizeof(Tregister));
+ ratype:=tregalloctype(ppufile.getbyte);
+ end;
+
+
+ procedure tai_regalloc.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putdata(reg,sizeof(Tregister));
+ ppufile.putbyte(byte(ratype));
+ end;
+
+
+{*****************************************************************************
+ TaiInstruction
+*****************************************************************************}
+
+ constructor tai_cpu_abstract.Create(op : tasmop);
+
+ begin
+ inherited create;
+ typ:=ait_instruction;
+ is_jmp:=false;
+ opcode:=op;
+ ops:=0;
+ fillchar(condition,sizeof(condition),0);
+ fillchar(oper,sizeof(oper),0);
+ end;
+
+
+ destructor tai_cpu_abstract.Destroy;
+ var
+ i : integer;
+ begin
+ for i:=0 to opercnt-1 do
+ freeop(i);
+ inherited destroy;
+ end;
+
+
+{ ---------------------------------------------------------------------
+ Loading of operands.
+ ---------------------------------------------------------------------}
+
+ procedure tai_cpu_abstract.allocate_oper(opers:longint);
+ begin
+ while (opers>opercnt) do
+ begin
+ new(oper[opercnt]);
+ fillchar(oper[opercnt]^,sizeof(toper),0);
+ inc(opercnt);
+ end;
+ end;
+
+
+ procedure tai_cpu_abstract.loadconst(opidx:longint;l:aint);
+ begin
+ allocate_oper(opidx+1);
+ with oper[opidx]^ do
+ begin
+ if typ<>top_const then
+ clearop(opidx);
+ val:=l;
+ typ:=top_const;
+ end;
+ end;
+
+
+ procedure tai_cpu_abstract.loadsymbol(opidx:longint;s:tasmsymbol;sofs:longint);
+ var
+ r : treference;
+ begin
+ reference_reset_symbol(r,s,sofs,1);
+ r.refaddr:=addr_full;
+ loadref(opidx,r);
+ end;
+
+
+ procedure tai_cpu_abstract.loadlocal(opidx:longint;s:pointer;sofs:longint;indexreg:tregister;scale:byte;getoffset,forceref:boolean);
+ begin
+ if not assigned(s) then
+ internalerror(200204251);
+ allocate_oper(opidx+1);
+ with oper[opidx]^ do
+ begin
+ if typ<>top_local then
+ begin
+ clearop(opidx);
+ new(localoper);
+ end;
+ with oper[opidx]^.localoper^ do
+ begin
+ localsym:=s;
+ localsymofs:=sofs;
+ localindexreg:=indexreg;
+ localscale:=scale;
+ localgetoffset:=getoffset;
+ localforceref:=forceref;
+ end;
+ typ:=top_local;
+ end;
+ end;
+
+
+ procedure tai_cpu_abstract.loadref(opidx:longint;const r:treference);
+ begin
+ allocate_oper(opidx+1);
+ with oper[opidx]^ do
+ begin
+ if typ<>top_ref then
+ begin
+ clearop(opidx);
+ new(ref);
+ end;
+
+ ref^:=r;
+{$ifdef x86}
+ { We allow this exception for x86, since overloading this would be
+ too much of a a speed penalty}
+ if (ref^.segment<>NR_NO) and (ref^.segment<>NR_DS) then
+ segprefix:=ref^.segment;
+{$endif}
+ if (cs_create_pic in current_settings.moduleswitches) and
+ assigned(r.symbol) and
+ not assigned(r.relsymbol) and
+ (r.refaddr=addr_no)
+{$ifdef ARM}
+ and not(r.base=NR_R15)
+{$endif ARM}
+ then
+ internalerror(200502052);
+ typ:=top_ref;
+ if assigned(add_reg_instruction_hook) then
+ begin
+ add_reg_instruction_hook(self,ref^.base);
+ add_reg_instruction_hook(self,ref^.index);
+ end;
+ { mark symbol as used }
+ if assigned(ref^.symbol) then
+ ref^.symbol.increfs;
+ if assigned(ref^.relsymbol) then
+ ref^.relsymbol.increfs;
+ end;
+ end;
+
+
+ procedure tai_cpu_abstract.loadreg(opidx:longint;r:tregister);
+ begin
+ allocate_oper(opidx+1);
+ with oper[opidx]^ do
+ begin
+ if typ<>top_reg then
+ clearop(opidx);
+ reg:=r;
+ typ:=top_reg;
+ end;
+ if assigned(add_reg_instruction_hook) then
+ add_reg_instruction_hook(self,r);
+{$ifdef ARM}
+ { R15 is the PC on the ARM thus moves to R15 are jumps.
+ Due to speed considerations we don't use a virtual overridden method here.
+ Because the pc/r15 isn't handled by the reg. allocator this should never cause
+ problems with iregs getting r15.
+ }
+ is_jmp:=(opcode=A_MOV) and (opidx=0) and (r=NR_R15);
+{$endif ARM}
+ end;
+
+
+ procedure tai_cpu_abstract.loadoper(opidx:longint;o:toper);
+ begin
+ allocate_oper(opidx+1);
+ clearop(opidx);
+ oper[opidx]^:=o;
+ { copy also the reference }
+ with oper[opidx]^ do
+ begin
+ case typ of
+ top_reg:
+ begin
+ if assigned(add_reg_instruction_hook) then
+ add_reg_instruction_hook(self,reg);
+ end;
+ top_ref:
+ begin
+ new(ref);
+ ref^:=o.ref^;
+ if assigned(add_reg_instruction_hook) then
+ begin
+ add_reg_instruction_hook(self,ref^.base);
+ add_reg_instruction_hook(self,ref^.index);
+ end;
+ end;
+{$ifdef ARM}
+ top_shifterop:
+ begin
+ new(shifterop);
+ shifterop^:=o.shifterop^;
+ if assigned(add_reg_instruction_hook) then
+ add_reg_instruction_hook(self,shifterop^.rs);
+ end;
+{$endif ARM}
+ end;
+ end;
+ end;
+
+ procedure tai_cpu_abstract.clearop(opidx:longint);
+ begin
+ with oper[opidx]^ do
+ begin
+ case typ of
+ top_ref:
+ dispose(ref);
+ top_local:
+ dispose(localoper);
+{$ifdef ARM}
+ top_shifterop:
+ dispose(shifterop);
+ top_regset:
+ dispose(regset);
+{$endif ARM}
+ end;
+ typ:=top_none;
+ end;
+ end;
+
+
+ procedure tai_cpu_abstract.freeop(opidx:longint);
+ begin
+ clearop(opidx);
+ dispose(oper[opidx]);
+ end;
+
+
+{ ---------------------------------------------------------------------
+ Miscellaneous methods.
+ ---------------------------------------------------------------------}
+
+ procedure tai_cpu_abstract.SetCondition(const c:TAsmCond);
+ begin
+ condition:=c;
+ end;
+
+
+ Function tai_cpu_abstract.getcopy:TLinkedListItem;
+ var
+ i : longint;
+ p : tai_cpu_abstract;
+ begin
+ p:=tai_cpu_abstract(inherited getcopy);
+ { make a copy of the references }
+ p.opercnt:=0;
+ p.allocate_oper(ops);
+ for i:=0 to ops-1 do
+ begin
+ p.oper[i]^:=oper[i]^;
+ case oper[i]^.typ of
+ top_local :
+ begin
+ new(p.oper[i]^.localoper);
+ p.oper[i]^.localoper^:=oper[i]^.localoper^;
+ end;
+ top_ref :
+ begin
+ new(p.oper[i]^.ref);
+ p.oper[i]^.ref^:=oper[i]^.ref^;
+ end;
+{$ifdef ARM}
+ top_shifterop:
+ begin
+ new(p.oper[i]^.shifterop);
+ p.oper[i]^.shifterop^:=oper[i]^.shifterop^;
+ end;
+{$endif ARM}
+ end;
+ end;
+ getcopy:=p;
+ end;
+
+
+ function tai_cpu_abstract.is_same_reg_move(regtype: Tregistertype):boolean;
+ begin
+ { When the generic RA is used this needs to be overridden, we don't use
+ virtual;abstract; to prevent a lot of warnings of unimplemented abstract methods
+ when tai_cpu is created (PFV) }
+ internalerror(200404091);
+ result:=false;
+ end;
+
+
+ function tai_cpu_abstract.spilling_get_operation_type(opnr: longint): topertype;
+ begin
+ internalerror(200404091);
+ result:=operand_readwrite;
+ end;
+
+
+ function tai_cpu_abstract.spilling_get_operation_type_ref(opnr: longint; reg: tregister): topertype;
+ begin
+ result := operand_read;
+ end;
+
+
+ constructor tai_cpu_abstract.ppuload(t:taitype;ppufile:tcompilerppufile);
+ var
+ i : integer;
+ begin
+ inherited ppuload(t,ppufile);
+ { hopefully, we don't get problems with big/litte endian here when cross compiling :/ }
+ ppufile.getdata(condition,sizeof(tasmcond));
+ allocate_oper(ppufile.getbyte);
+ for i:=0 to ops-1 do
+ ppuloadoper(ppufile,oper[i]^);
+ opcode:=tasmop(ppufile.getword);
+{$ifdef x86}
+ ppufile.getdata(segprefix,sizeof(Tregister));
+{$endif x86}
+ is_jmp:=boolean(ppufile.getbyte);
+ end;
+
+
+ procedure tai_cpu_abstract.ppuwrite(ppufile:tcompilerppufile);
+ var
+ i : integer;
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putdata(condition,sizeof(tasmcond));
+ ppufile.putbyte(ops);
+ for i:=0 to ops-1 do
+ ppuwriteoper(ppufile,oper[i]^);
+ ppufile.putword(word(opcode));
+{$ifdef x86}
+ ppufile.putdata(segprefix,sizeof(Tregister));
+{$endif x86}
+ ppufile.putbyte(byte(is_jmp));
+ end;
+
+
+ procedure tai_cpu_abstract.buildderefimpl;
+ var
+ i : integer;
+ begin
+ for i:=0 to ops-1 do
+ ppubuildderefimploper(oper[i]^);
+ end;
+
+
+ procedure tai_cpu_abstract.derefimpl;
+ var
+ i : integer;
+ begin
+ for i:=0 to ops-1 do
+ ppuderefoper(oper[i]^);
+ end;
+
+
+ procedure tai_cpu_abstract.resetpass1;
+ begin
+ end;
+
+
+ procedure tai_cpu_abstract.resetpass2;
+ begin
+ end;
+
+
+ function tai_cpu_abstract.Pass1(objdata:TObjData):longint;
+ begin
+ result:=0;
+ end;
+
+
+ procedure tai_cpu_abstract.Pass2(objdata:TObjData);
+ begin
+ end;
+
+
+ procedure tai_cpu_abstract.ppuloadoper(ppufile:tcompilerppufile;var o:toper);
+ begin
+ o.typ:=toptype(ppufile.getbyte);
+ o.ot:=ppufile.getlongint;
+ case o.typ of
+ top_reg :
+ ppufile.getdata(o.reg,sizeof(Tregister));
+ top_ref :
+ begin
+ new(o.ref);
+{$ifdef x86}
+ ppufile.getdata(o.ref^.segment,sizeof(Tregister));
+{$endif x86}
+ ppufile.getdata(o.ref^.base,sizeof(Tregister));
+ ppufile.getdata(o.ref^.index,sizeof(Tregister));
+ ppufile.getdata(o.ref^.refaddr,sizeof(o.ref^.refaddr));
+ o.ref^.scalefactor:=ppufile.getbyte;
+ o.ref^.offset:=ppufile.getaint;
+ o.ref^.symbol:=ppufile.getasmsymbol;
+ o.ref^.relsymbol:=ppufile.getasmsymbol;
+ end;
+ top_const :
+ o.val:=ppufile.getaint;
+ top_local :
+ begin
+ new(o.localoper);
+ with o.localoper^ do
+ begin
+ ppufile.getderef(localsymderef);
+ localsymofs:=ppufile.getaint;
+ localindexreg:=tregister(ppufile.getlongint);
+ localscale:=ppufile.getbyte;
+ localgetoffset:=(ppufile.getbyte<>0);
+ end;
+ end;
+ else
+ internalerror(2007010210);
+ end;
+ end;
+
+
+ procedure tai_cpu_abstract.ppuwriteoper(ppufile:tcompilerppufile;const o:toper);
+ begin
+ ppufile.putbyte(byte(o.typ));
+ ppufile.putlongint(o.ot);
+ case o.typ of
+ top_reg :
+ ppufile.putdata(o.reg,sizeof(Tregister));
+ top_ref :
+ begin
+{$ifdef x86}
+ ppufile.putdata(o.ref^.segment,sizeof(Tregister));
+{$endif x86}
+ ppufile.putdata(o.ref^.base,sizeof(Tregister));
+ ppufile.putdata(o.ref^.index,sizeof(Tregister));
+ ppufile.putdata(o.ref^.refaddr,sizeof(o.ref^.refaddr));
+ ppufile.putbyte(o.ref^.scalefactor);
+ ppufile.putaint(o.ref^.offset);
+ ppufile.putasmsymbol(o.ref^.symbol);
+ ppufile.putasmsymbol(o.ref^.relsymbol);
+ end;
+ top_const :
+ ppufile.putaint(o.val);
+ top_local :
+ begin
+ with o.localoper^ do
+ begin
+ ppufile.putderef(localsymderef);
+ ppufile.putaint(localsymofs);
+ ppufile.putlongint(longint(localindexreg));
+ ppufile.putbyte(localscale);
+ ppufile.putbyte(byte(localgetoffset));
+ end;
+ end;
+ else
+ internalerror(2007010211);
+ end;
+ end;
+
+{****************************************************************************
+ tai_align_abstract
+ ****************************************************************************}
+
+ constructor tai_align_abstract.Create(b: byte);
+ begin
+ inherited Create;
+ typ:=ait_align;
+{$ifdef EXTDEBUG}
+ if upper(classname)='TAI_ALIGN_ABSTRACT' then
+ internalerror(200709191);
+{$endif EXTDEBUG}
+ if b in [1,2,4,8,16,32] then
+ aligntype := b
+ else
+ aligntype := 1;
+ fillsize:=0;
+ fillop:=0;
+ use_op:=false;
+ end;
+
+
+ constructor tai_align_abstract.Create_op(b: byte; _op: byte);
+ begin
+ inherited Create;
+ typ:=ait_align;
+ if b in [1,2,4,8,16,32] then
+ aligntype := b
+ else
+ aligntype := 1;
+ fillsize:=0;
+ fillop:=_op;
+ use_op:=true;
+ end;
+
+
+ constructor tai_align_abstract.Create_zeros(b: byte);
+ begin
+ inherited Create;
+ typ:=ait_align;
+ if b in [1,2,4,8,16,32] then
+ aligntype := b
+ else
+ aligntype := 1;
+ use_op:=true;
+ fillsize:=0;
+ fillop:=0;
+ end;
+
+
+ function tai_align_abstract.calculatefillbuf(var buf : tfillbuffer;executable : boolean):pchar;
+ begin
+ if fillsize>sizeof(buf) then
+ internalerror(200404293);
+ fillchar(buf,high(buf),fillop);
+ calculatefillbuf:=pchar(@buf);
+ end;
+
+
+ constructor tai_align_abstract.ppuload(t:taitype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ aligntype:=ppufile.getbyte;
+ fillsize:=0;
+ fillop:=ppufile.getbyte;
+ use_op:=boolean(ppufile.getbyte);
+ end;
+
+
+ procedure tai_align_abstract.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putbyte(aligntype);
+ ppufile.putbyte(fillop);
+ ppufile.putbyte(byte(use_op));
+ end;
+
+{****************************************************************************
+ tai_seh_directive
+ ****************************************************************************}
+
+ const
+ datatypemap: array[TAsmSehDirective] of TSehDirectiveDatatype=(
+ sd_string, { proc }
+ sd_none, { endproc }
+ sd_none, { endprologue }
+ sd_string, { handler }
+ sd_none, { handlerdata }
+ sd_none,sd_none,sd_none, { eh, 32, no32 }
+ sd_regoffset, { setframe }
+ sd_offset, { stackalloc }
+ sd_reg, { pushreg }
+ sd_regoffset, { savereg }
+ sd_regoffset, { savexmm }
+ sd_none { pushframe }
+ );
+
+ constructor tai_seh_directive.create(_kind:TAsmSehDirective);
+ begin
+ inherited Create;
+ typ:=ait_seh_directive;
+ kind:=_kind;
+ data.typ:=datatypemap[_kind];
+ end;
+
+ constructor tai_seh_directive.create_name(_kind:TAsmSehDirective;const _name:string);
+ begin
+ create(_kind);
+ data.name:=stringdup(_name);
+ end;
+
+ constructor tai_seh_directive.create_reg(_kind:TAsmSehDirective;r:TRegister);
+ begin
+ create(_kind);
+ data.reg:=r;
+ end;
+
+ constructor tai_seh_directive.create_offset(_kind:TAsmSehDirective;ofs:dword);
+ begin
+ create(_kind);
+ data.offset:=ofs;
+ end;
+
+ constructor tai_seh_directive.create_reg_offset(_kind:TAsmSehDirective;
+ r:TRegister;ofs:dword);
+ begin
+ create(_kind);
+ data.offset:=ofs;
+ data.reg:=r;
+ end;
+
+ constructor tai_seh_directive.ppuload(t:taitype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t, ppufile);
+ kind:=TAsmSehDirective(ppufile.getbyte);
+ data.typ:=datatypemap[kind];
+ case data.typ of
+ sd_none: ;
+ sd_string:
+ begin
+ data.name:=stringdup(ppufile.getstring);
+ data.flags:=ppufile.getbyte;
+ end;
+
+ sd_reg,sd_offset,sd_regoffset:
+ begin
+ ppufile.getdata(data.reg,sizeof(TRegister));
+ data.offset:=ppufile.getdword;
+ end;
+ else
+ InternalError(2011091201);
+ end;
+ end;
+
+ destructor tai_seh_directive.destroy;
+ begin
+ if data.typ=sd_string then
+ stringdispose(data.name);
+ inherited destroy;
+ end;
+
+ procedure tai_seh_directive.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putbyte(ord(kind));
+ case data.typ of
+ sd_none: ;
+ sd_string:
+ begin
+ ppufile.putstring(data.name^);
+ ppufile.putbyte(data.flags);
+ end;
+
+ sd_reg,sd_offset,sd_regoffset:
+ begin
+ ppufile.putdata(data.reg,sizeof(TRegister));
+ ppufile.putdword(data.offset);
+ end;
+ else
+ InternalError(2011091202);
+ end;
+ end;
+
+ procedure tai_seh_directive.generate_code(objdata:TObjData);
+ begin
+ end;
+
+begin
+{$push}{$warnings off}
+ { taitype should fit into a 4 byte set for speed reasons }
+ if ord(high(taitype))>31 then
+ internalerror(201108181);
+{$pop}
+end.
diff --git a/closures/compiler/aggas.pas b/closures/compiler/aggas.pas
new file mode 100644
index 0000000000..1fed1d0b79
--- /dev/null
+++ b/closures/compiler/aggas.pas
@@ -0,0 +1,1636 @@
+{
+ Copyright (c) 1998-2006 by the Free Pascal team
+
+ This unit implements the generic part of the GNU assembler
+ (v2.8 or later) writer
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+{ Base unit for writing GNU assembler output.
+}
+unit aggas;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cclasses,
+ globtype,globals,
+ aasmbase,aasmtai,aasmdata,aasmcpu,
+ assemble;
+
+ type
+ TCPUInstrWriter = class;
+ {# This is a derived class which is used to write
+ GAS styled assembler.
+ }
+
+ { TGNUAssembler }
+
+ TGNUAssembler=class(texternalassembler)
+ protected
+ function sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;virtual;
+ function sectionattrs_coff(atype:TAsmSectiontype):string;virtual;
+ procedure WriteSection(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder);
+ procedure WriteExtraHeader;virtual;
+ procedure WriteInstruction(hp: tai);
+ procedure WriteWeakSymbolDef(s: tasmsymbol); virtual;
+ public
+ function MakeCmdLine: TCmdStr; override;
+ procedure WriteTree(p:TAsmList);override;
+ procedure WriteAsmList;override;
+ destructor destroy; override;
+ private
+ setcount: longint;
+ procedure WriteDecodedSleb128(a: int64);
+ procedure WriteDecodedUleb128(a: qword);
+ function NextSetLabel: string;
+ protected
+ InstrWriter: TCPUInstrWriter;
+ end;
+
+
+ {# This is the base class for writing instructions.
+
+ The WriteInstruction() method must be overridden
+ to write a single instruction to the assembler
+ file.
+ }
+ TCPUInstrWriter = class
+ constructor create(_owner: TGNUAssembler);
+ procedure WriteInstruction(hp : tai); virtual; abstract;
+ protected
+ owner: TGNUAssembler;
+ end;
+
+
+ { TAppleGNUAssembler }
+
+ TAppleGNUAssembler=class(TGNUAssembler)
+ protected
+ function sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;override;
+ procedure WriteWeakSymbolDef(s: tasmsymbol); override;
+
+ end;
+
+
+ TAoutGNUAssembler=class(TGNUAssembler)
+ function sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;override;
+ end;
+
+
+implementation
+
+ uses
+ SysUtils,
+ cutils,cfileutl,systems,
+ fmodule,finput,verbose,
+ itcpugas,cpubase;
+
+ const
+ line_length = 70;
+
+ var
+ symendcount : longint;
+
+ type
+{$ifdef cpuextended}
+ t80bitarray = array[0..9] of byte;
+{$endif cpuextended}
+ t64bitarray = array[0..7] of byte;
+ t32bitarray = array[0..3] of byte;
+
+{****************************************************************************}
+{ Support routines }
+{****************************************************************************}
+
+ function single2str(d : single) : string;
+ var
+ hs : string;
+ begin
+ str(d,hs);
+ { replace space with + }
+ if hs[1]=' ' then
+ hs[1]:='+';
+ single2str:='0d'+hs
+ end;
+
+ function double2str(d : double) : string;
+ var
+ hs : string;
+ begin
+ str(d,hs);
+ { replace space with + }
+ if hs[1]=' ' then
+ hs[1]:='+';
+ double2str:='0d'+hs
+ end;
+
+ function extended2str(e : extended) : string;
+ var
+ hs : string;
+ begin
+ str(e,hs);
+ { replace space with + }
+ if hs[1]=' ' then
+ hs[1]:='+';
+ extended2str:='0d'+hs
+ end;
+
+
+ { convert floating point values }
+ { to correct endian }
+ procedure swap64bitarray(var t: t64bitarray);
+ var
+ b: byte;
+ begin
+ b:= t[7];
+ t[7] := t[0];
+ t[0] := b;
+
+ b := t[6];
+ t[6] := t[1];
+ t[1] := b;
+
+ b:= t[5];
+ t[5] := t[2];
+ t[2] := b;
+
+ b:= t[4];
+ t[4] := t[3];
+ t[3] := b;
+ end;
+
+
+ procedure swap32bitarray(var t: t32bitarray);
+ var
+ b: byte;
+ begin
+ b:= t[1];
+ t[1]:= t[2];
+ t[2]:= b;
+
+ b:= t[0];
+ t[0]:= t[3];
+ t[3]:= b;
+ end;
+
+
+ const
+ ait_const2str : array[aitconst_128bit..aitconst_half16bit] of string[20]=(
+ #9'.fixme128'#9,#9'.quad'#9,#9'.long'#9,#9'.short'#9,#9'.byte'#9,
+ #9'.sleb128'#9,#9'.uleb128'#9,
+ #9'.rva'#9,#9'.secrel32'#9,#9'.quad'#9,#9'.long'#9,#9'.short'#9
+ );
+
+{****************************************************************************}
+{ GNU Assembler writer }
+{****************************************************************************}
+
+ destructor TGNUAssembler.Destroy;
+ begin
+ InstrWriter.free;
+ inherited destroy;
+ end;
+
+
+ function TGNUAssembler.MakeCmdLine: TCmdStr;
+ begin
+ result := inherited MakeCmdLine;
+ // MWE: disabled again. It generates dwarf info for the generated .s
+ // files as well. This conflicts with the info we generate
+ // if target_dbg.id = dbg_dwarf then
+ // result := result + ' --gdwarf-2';
+ end;
+
+
+ function TGNUAssembler.NextSetLabel: string;
+ begin
+ inc(setcount);
+ result := target_asm.labelprefix+'$set$'+tostr(setcount);
+ end;
+
+ function is_smart_section(atype:TAsmSectiontype):boolean;
+ begin
+ { For bss we need to set some flags that are target dependent,
+ it is easier to disable it for smartlinking. It doesn't take up
+ filespace }
+ result:=not(target_info.system in systems_darwin) and
+ create_smartlink_sections and
+ (atype<>sec_toc) and
+ (atype<>sec_user) and
+ { on embedded systems every byte counts, so smartlink bss too }
+ ((atype<>sec_bss) or (target_info.system in systems_embedded));
+ end;
+
+ function TGNUAssembler.sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;
+ const
+ secnames : array[TAsmSectiontype] of string[length('__DATA, __datacoal_nt,coalesced')] = ('','',
+ '.text',
+ '.data',
+{ why doesn't .rodata work? (FK) }
+{ sometimes we have to create a data.rel.ro instead of .rodata, e.g. for }
+{ vtables (and anything else containing relocations), otherwise those are }
+{ not relocated properly on e.g. linux/ppc64. g++ generates there for a }
+{ vtable for a class called Window: }
+{ .section .data.rel.ro._ZTV6Window,"awG",@progbits,_ZTV6Window,comdat }
+{ TODO: .data.ro not yet working}
+{$if defined(arm) or defined(powerpc)}
+ '.rodata',
+{$else arm}
+ '.data',
+{$endif arm}
+{$if defined(m68k)} { Amiga/m68k GNU AS doesn't seem to like .rodata (KB) }
+ '.data',
+{$else}
+ '.rodata',
+{$endif}
+ '.bss',
+ '.threadvar',
+ '.pdata',
+ '', { stubs }
+ '__DATA,__nl_symbol_ptr',
+ '__DATA,__la_symbol_ptr',
+ '__DATA,__mod_init_func',
+ '__DATA,__mod_term_func',
+ '.stab',
+ '.stabstr',
+ '.idata$2','.idata$4','.idata$5','.idata$6','.idata$7','.edata',
+ '.eh_frame',
+ '.debug_frame','.debug_info','.debug_line','.debug_abbrev',
+ '.fpc',
+ '.toc',
+ '.init',
+ '.fini',
+ '.objc_class',
+ '.objc_meta_class',
+ '.objc_cat_cls_meth',
+ '.objc_cat_inst_meth',
+ '.objc_protocol',
+ '.objc_string_object',
+ '.objc_cls_meth',
+ '.objc_inst_meth',
+ '.objc_cls_refs',
+ '.objc_message_refs',
+ '.objc_symbols',
+ '.objc_category',
+ '.objc_class_vars',
+ '.objc_instance_vars',
+ '.objc_module_info',
+ '.objc_class_names',
+ '.objc_meth_var_types',
+ '.objc_meth_var_names',
+ '.objc_selector_strs',
+ '.objc_protocol_ext',
+ '.objc_class_ext',
+ '.objc_property',
+ '.objc_image_info',
+ '.objc_cstring_object',
+ '.objc_sel_fixup',
+ '__DATA,__objc_data',
+ '__DATA,__objc_const',
+ '.objc_superrefs',
+ '__DATA, __datacoal_nt,coalesced',
+ '.objc_classlist',
+ '.objc_nlclasslist',
+ '.objc_catlist',
+ '.obcj_nlcatlist',
+ '.objc_protolist'
+ );
+ secnames_pic : array[TAsmSectiontype] of string[length('__DATA, __datacoal_nt,coalesced')] = ('','',
+ '.text',
+ '.data.rel',
+ '.data.rel',
+ '.data.rel',
+ '.bss',
+ '.threadvar',
+ '.pdata',
+ '', { stubs }
+ '__DATA,__nl_symbol_ptr',
+ '__DATA,__la_symbol_ptr',
+ '__DATA,__mod_init_func',
+ '__DATA,__mod_term_func',
+ '.stab',
+ '.stabstr',
+ '.idata$2','.idata$4','.idata$5','.idata$6','.idata$7','.edata',
+ '.eh_frame',
+ '.debug_frame','.debug_info','.debug_line','.debug_abbrev',
+ '.fpc',
+ '.toc',
+ '.init',
+ '.fini',
+ '.objc_class',
+ '.objc_meta_class',
+ '.objc_cat_cls_meth',
+ '.objc_cat_inst_meth',
+ '.objc_protocol',
+ '.objc_string_object',
+ '.objc_cls_meth',
+ '.objc_inst_meth',
+ '.objc_cls_refs',
+ '.objc_message_refs',
+ '.objc_symbols',
+ '.objc_category',
+ '.objc_class_vars',
+ '.objc_instance_vars',
+ '.objc_module_info',
+ '.objc_class_names',
+ '.objc_meth_var_types',
+ '.objc_meth_var_names',
+ '.objc_selector_strs',
+ '.objc_protocol_ext',
+ '.objc_class_ext',
+ '.objc_property',
+ '.objc_image_info',
+ '.objc_cstring_object',
+ '.objc_sel_fixup',
+ '__DATA, __objc_data',
+ '__DATA, __objc_const',
+ '.objc_superrefs',
+ '__DATA, __datacoal_nt,coalesced',
+ '.objc_classlist',
+ '.objc_nlclasslist',
+ '.objc_catlist',
+ '.obcj_nlcatlist',
+ '.objc_protolist'
+ );
+ var
+ sep : string[3];
+ secname : string;
+ begin
+ if (cs_create_pic in current_settings.moduleswitches) and
+ not(target_info.system in systems_darwin) then
+ secname:=secnames_pic[atype]
+ else
+ secname:=secnames[atype];
+{$ifdef m68k}
+ { old Amiga GNU AS doesn't support .section .fpc }
+ if (atype=sec_fpc) and (target_info.system = system_m68k_amiga) then
+ secname:=secnames[sec_data];
+{$endif}
+ if (atype=sec_fpc) and (Copy(aname,1,3)='res') then
+ begin
+ result:=secname+'.'+aname;
+ exit;
+ end;
+
+ if (atype=sec_threadvar) and
+ (target_info.system in (systems_windows+systems_wince)) then
+ secname:='.tls';
+
+ { go32v2 stub only loads .text and .data sections, and allocates space for .bss.
+ Thus, data which normally goes into .rodata and .rodata_norel sections must
+ end up in .data section }
+ if (atype in [sec_rodata,sec_rodata_norel]) and
+ (target_info.system=system_i386_go32v2) then
+ secname:='.data';
+
+ { section type user gives the user full controll on the section name }
+ if atype=sec_user then
+ secname:=aname;
+
+ if is_smart_section(atype) and (aname<>'') then
+ begin
+ case aorder of
+ secorder_begin :
+ sep:='.b_';
+ secorder_end :
+ sep:='.z_';
+ else
+ sep:='.n_';
+ end;
+ result:=secname+sep+aname
+ end
+ else
+ result:=secname;
+ end;
+
+
+ function TGNUAssembler.sectionattrs_coff(atype:TAsmSectiontype):string;
+ begin
+ case atype of
+ sec_code, sec_init, sec_fini, sec_stub:
+ result:='x';
+
+ { TODO: must be individual for each section }
+ sec_user:
+ result:='d';
+
+ sec_data, sec_data_lazy, sec_data_nonlazy, sec_fpc,
+ sec_idata2, sec_idata4, sec_idata5, sec_idata6, sec_idata7:
+ result:='d';
+
+ { TODO: these need a fix to become read-only }
+ sec_rodata, sec_rodata_norel:
+ result:='d';
+
+ sec_bss:
+ result:='b';
+
+ { TODO: Somewhat questionable. FPC does not allow initialized threadvars,
+ so no sense to mark it as containing data. But Windows allows it to
+ contain data, and Linux even has .tdata and .tbss }
+ sec_threadvar:
+ result:='b';
+
+ sec_pdata, sec_edata, sec_eh_frame, sec_toc:
+ result:='r';
+
+ sec_stab,sec_stabstr,
+ sec_debug_frame,sec_debug_info,sec_debug_line,sec_debug_abbrev:
+ result:='n';
+ else
+ result:=''; { defaults to data+load }
+ end;
+ end;
+
+
+ procedure TGNUAssembler.WriteSection(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder);
+ var
+ s : string;
+ begin
+ AsmLn;
+ case target_info.system of
+ system_i386_OS2,
+ system_i386_EMX,
+ system_m68k_amiga, { amiga has old GNU AS (2.14), which blews up from .section (KB) }
+ system_m68k_linux: ;
+ system_powerpc_darwin,
+ system_i386_darwin,
+ system_i386_iphonesim,
+ system_powerpc64_darwin,
+ system_x86_64_darwin,
+ system_arm_darwin:
+ begin
+ if (atype in [sec_stub,sec_objc_data,sec_objc_const,sec_data_coalesced]) then
+ AsmWrite('.section ');
+ end
+ else
+ AsmWrite('.section ');
+ end;
+ s:=sectionname(atype,aname,aorder);
+ AsmWrite(s);
+ case atype of
+ sec_fpc :
+ if aname = 'resptrs' then
+ AsmWrite(', "a", @progbits');
+ sec_stub :
+ begin
+ case target_info.system of
+ { there are processor-independent shortcuts available }
+ { for this, namely .symbol_stub and .picsymbol_stub, but }
+ { they don't work and gcc doesn't use them either... }
+ system_powerpc_darwin,
+ system_powerpc64_darwin:
+ if (cs_create_pic in current_settings.moduleswitches) then
+ AsmWriteln('__TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32')
+ else
+ AsmWriteln('__TEXT,__symbol_stub1,symbol_stubs,pure_instructions,16');
+ system_i386_darwin,
+ system_i386_iphonesim:
+ AsmWriteln('__IMPORT,__jump_table,symbol_stubs,self_modifying_code+pure_instructions,5');
+ system_arm_darwin:
+ if (cs_create_pic in current_settings.moduleswitches) then
+ AsmWriteln('.section __TEXT,__picsymbolstub4,symbol_stubs,none,16')
+ else
+ AsmWriteln('.section __TEXT,__symbol_stub4,symbol_stubs,none,12')
+ { darwin/x86-64 uses RIP-based GOT addressing, no symbol stubs }
+ else
+ internalerror(2006031101);
+ end;
+ end;
+ else
+ { GNU AS won't recognize '.text.n_something' section name as belonging
+ to '.text' and assigns default attributes to it, which is not
+ always correct. We have to fix it.
+
+ TODO: This likely applies to all systems which smartlink without
+ creating libraries }
+ if (target_info.system in [system_i386_win32,system_x86_64_win64]) and
+ is_smart_section(atype) and (aname<>'') then
+ begin
+ s:=sectionattrs_coff(atype);
+ if (s<>'') then
+ AsmWrite(',"'+s+'"');
+ end;
+ end;
+ AsmLn;
+ LastSecType:=atype;
+ end;
+
+
+ procedure TGNUAssembler.WriteDecodedUleb128(a: qword);
+ var
+ i,len : longint;
+ buf : array[0..63] of byte;
+ begin
+ len:=EncodeUleb128(a,buf);
+ for i:=0 to len-1 do
+ begin
+ if (i > 0) then
+ AsmWrite(',');
+ AsmWrite(tostr(buf[i]));
+ end;
+ end;
+
+
+ procedure TGNUAssembler.WriteDecodedSleb128(a: int64);
+ var
+ i,len : longint;
+ buf : array[0..255] of byte;
+ begin
+ len:=EncodeSleb128(a,buf);
+ for i:=0 to len-1 do
+ begin
+ if (i > 0) then
+ AsmWrite(',');
+ AsmWrite(tostr(buf[i]));
+ end;
+ end;
+
+
+ procedure TGNUAssembler.WriteTree(p:TAsmList);
+
+ function needsObject(hp : tai_symbol) : boolean;
+ begin
+ needsObject :=
+ (
+ assigned(hp.next) and
+ (tai(hp.next).typ in [ait_const,ait_datablock,
+ ait_real_32bit,ait_real_64bit,ait_real_80bit,ait_comp_64bit])
+ ) or
+ (hp.sym.typ=AT_DATA);
+
+ end;
+
+
+ procedure doalign(alignment: byte; use_op: boolean; fillop: byte; out last_align: longint);
+ var
+ i: longint;
+ begin
+ last_align:=alignment;
+ if alignment>1 then
+ begin
+ if not(target_info.system in systems_darwin) then
+ begin
+ AsmWrite(#9'.balign '+tostr(alignment));
+ if use_op then
+ AsmWrite(','+tostr(fillop))
+{$ifdef x86}
+ { force NOP as alignment op code }
+ else if LastSecType=sec_code then
+ AsmWrite(',0x90');
+{$endif x86}
+ end
+ else
+ begin
+ { darwin as only supports .align }
+ if not ispowerof2(alignment,i) then
+ internalerror(2003010305);
+ AsmWrite(#9'.align '+tostr(i));
+ last_align:=i;
+ end;
+ AsmLn;
+ end;
+ end;
+
+ var
+ ch : char;
+ hp : tai;
+ constdef : taiconst_type;
+ s,t : string;
+ i,pos,l : longint;
+ InlineLevel : longint;
+ last_align : longint;
+ co : comp;
+ sin : single;
+ d : double;
+{$ifdef cpuextended}
+ e : extended;
+{$endif cpuextended}
+ do_line : boolean;
+
+ sepChar : char;
+ begin
+ if not assigned(p) then
+ exit;
+
+ last_align := 2;
+ InlineLevel:=0;
+ { lineinfo is only needed for al_procedures (PFV) }
+ do_line:=(cs_asm_source in current_settings.globalswitches) or
+ ((cs_lineinfo in current_settings.moduleswitches)
+ and (p=current_asmdata.asmlists[al_procedures]));
+ hp:=tai(p.first);
+ while assigned(hp) do
+ begin
+ prefetch(pointer(hp.next)^);
+ if not(hp.typ in SkipLineInfo) then
+ begin
+ current_filepos:=tailineinfo(hp).fileinfo;
+ { no line info for inlined code }
+ if do_line and (inlinelevel=0) then
+ WriteSourceLine(hp as tailineinfo);
+ end;
+
+ case hp.typ of
+
+ ait_comment :
+ Begin
+ AsmWrite(target_asm.comment);
+ AsmWritePChar(tai_comment(hp).str);
+ AsmLn;
+ End;
+
+ ait_regalloc :
+ begin
+ if (cs_asm_regalloc in current_settings.globalswitches) then
+ begin
+ AsmWrite(#9+target_asm.comment+'Register ');
+ repeat
+ AsmWrite(std_regname(Tai_regalloc(hp).reg));
+ if (hp.next=nil) or
+ (tai(hp.next).typ<>ait_regalloc) or
+ (tai_regalloc(hp.next).ratype<>tai_regalloc(hp).ratype) then
+ break;
+ hp:=tai(hp.next);
+ AsmWrite(',');
+ until false;
+ AsmWrite(' ');
+ AsmWriteLn(regallocstr[tai_regalloc(hp).ratype]);
+ end;
+ end;
+
+ ait_tempalloc :
+ begin
+ if (cs_asm_tempalloc in current_settings.globalswitches) then
+ WriteTempalloc(tai_tempalloc(hp));
+ end;
+
+ ait_align :
+ begin
+ doalign(tai_align_abstract(hp).aligntype,tai_align_abstract(hp).use_op,tai_align_abstract(hp).fillop,last_align);
+ end;
+
+ ait_section :
+ begin
+ if tai_section(hp).sectype<>sec_none then
+{$ifdef avr}
+ WriteSection(tai_section(hp).sectype,ReplaceForbiddenChars(tai_section(hp).name^),tai_section(hp).secorder)
+{$else avr}
+ WriteSection(tai_section(hp).sectype,tai_section(hp).name^,tai_section(hp).secorder)
+{$endif avr}
+ else
+ begin
+{$ifdef EXTDEBUG}
+ AsmWrite(target_asm.comment);
+ AsmWriteln(' sec_none');
+{$endif EXTDEBUG}
+ end;
+ end;
+
+ ait_datablock :
+ begin
+ if (target_info.system in systems_darwin) then
+ begin
+ { On Mac OS X you can't have common symbols in a shared library
+ since those are in the TEXT section and the text section is
+ read-only in shared libraries (so it can be shared among different
+ processes). The alternate code creates some kind of common symbols
+ in the data segment.
+ }
+ if tai_datablock(hp).is_global then
+ begin
+ asmwrite('.globl ');
+ asmwriteln(tai_datablock(hp).sym.name);
+ asmwriteln('.data');
+ asmwrite('.zerofill __DATA, __common, ');
+ asmwrite(tai_datablock(hp).sym.name);
+ asmwriteln(', '+tostr(tai_datablock(hp).size)+','+tostr(last_align));
+ if not(LastSecType in [sec_data,sec_none]) then
+ writesection(LastSecType,'',secorder_default);
+ end
+ else
+ begin
+ asmwrite(#9'.lcomm'#9);
+ asmwrite(tai_datablock(hp).sym.name);
+ asmwrite(','+tostr(tai_datablock(hp).size));
+ asmwrite(','+tostr(last_align));
+ asmln;
+ end;
+ end
+ else
+ begin
+{$ifdef USE_COMM_IN_BSS}
+ if writingpackages then
+ begin
+ { The .comm is required for COMMON symbols. These are used
+ in the shared library loading. All the symbols declared in
+ the .so file need to resolve to the data allocated in the main
+ program (PFV) }
+ if tai_datablock(hp).is_global then
+ begin
+ asmwrite(#9'.comm'#9);
+{$ifdef avr}
+ asmwrite(ReplaceForbiddenChars(tai_datablock(hp).sym.name));
+{$else avr}
+ asmwrite(tai_datablock(hp).sym.name);
+{$endif avr}
+ asmwrite(','+tostr(tai_datablock(hp).size));
+ asmwrite(','+tostr(last_align));
+ asmln;
+ end
+ else
+ begin
+ asmwrite(#9'.lcomm'#9);
+{$ifdef avr}
+ asmwrite(ReplaceForbiddenChars(tai_datablock(hp).sym.name));
+{$else avr}
+ asmwrite(tai_datablock(hp).sym.name);
+{$endif avr}
+ asmwrite(','+tostr(tai_datablock(hp).size));
+ asmwrite(','+tostr(last_align));
+ asmln;
+ end
+ end
+ else
+{$endif USE_COMM_IN_BSS}
+ begin
+ if Tai_datablock(hp).is_global then
+ begin
+ asmwrite(#9'.globl ');
+{$ifdef avr}
+ asmwriteln(ReplaceForbiddenChars(Tai_datablock(hp).sym.name));
+{$else avr}
+ asmwriteln(Tai_datablock(hp).sym.name);
+{$endif avr}
+ end;
+ if (target_info.system <> system_arm_linux) then
+ sepChar := '@'
+ else
+ sepChar := '%';
+{$ifdef avr}
+ if (tf_needs_symbol_type in target_info.flags) then
+ asmwriteln(#9'.type '+ReplaceForbiddenChars(Tai_datablock(hp).sym.name)+','+sepChar+'object');
+ if (tf_needs_symbol_size in target_info.flags) and (tai_datablock(hp).size > 0) then
+ asmwriteln(#9'.size '+ReplaceForbiddenChars(Tai_datablock(hp).sym.name)+','+tostr(Tai_datablock(hp).size));
+ asmwrite(ReplaceForbiddenChars(Tai_datablock(hp).sym.name));
+{$else avr}
+ if (tf_needs_symbol_type in target_info.flags) then
+ asmwriteln(#9'.type '+Tai_datablock(hp).sym.name+','+sepChar+'object');
+ if (tf_needs_symbol_size in target_info.flags) and (tai_datablock(hp).size > 0) then
+ asmwriteln(#9'.size '+Tai_datablock(hp).sym.name+','+tostr(Tai_datablock(hp).size));
+ asmwrite(Tai_datablock(hp).sym.name);
+{$endif avr}
+ asmwriteln(':');
+ asmwriteln(#9'.zero '+tostr(Tai_datablock(hp).size));
+ end;
+ end;
+ end;
+
+ ait_const:
+ begin
+ constdef:=tai_const(hp).consttype;
+ case constdef of
+{$ifndef cpu64bitaddr}
+ aitconst_128bit :
+ begin
+ internalerror(200404291);
+ end;
+
+ aitconst_64bit :
+ begin
+ if assigned(tai_const(hp).sym) then
+ internalerror(200404292);
+ AsmWrite(ait_const2str[aitconst_32bit]);
+ if target_info.endian = endian_little then
+ begin
+ AsmWrite(tostr(longint(lo(tai_const(hp).value))));
+ AsmWrite(',');
+ AsmWrite(tostr(longint(hi(tai_const(hp).value))));
+ end
+ else
+ begin
+ AsmWrite(tostr(longint(hi(tai_const(hp).value))));
+ AsmWrite(',');
+ AsmWrite(tostr(longint(lo(tai_const(hp).value))));
+ end;
+ AsmLn;
+ end;
+{$endif cpu64bitaddr}
+ aitconst_uleb128bit,
+ aitconst_sleb128bit,
+{$ifdef cpu64bitaddr}
+ aitconst_128bit,
+ aitconst_64bit,
+{$endif cpu64bitaddr}
+ aitconst_32bit,
+ aitconst_16bit,
+ aitconst_8bit,
+ aitconst_rva_symbol,
+ aitconst_secrel32_symbol,
+ aitconst_darwin_dwarf_delta32,
+ aitconst_darwin_dwarf_delta64,
+ aitconst_half16bit:
+ begin
+ if (target_info.system in systems_darwin) and
+ (constdef in [aitconst_uleb128bit,aitconst_sleb128bit]) then
+ begin
+ AsmWrite(ait_const2str[aitconst_8bit]);
+ case tai_const(hp).consttype of
+ aitconst_uleb128bit:
+ WriteDecodedUleb128(qword(tai_const(hp).value));
+ aitconst_sleb128bit:
+ WriteDecodedSleb128(int64(tai_const(hp).value));
+ end
+ end
+ else
+ begin
+ AsmWrite(ait_const2str[constdef]);
+ l:=0;
+ t := '';
+ repeat
+ if assigned(tai_const(hp).sym) then
+ begin
+ if assigned(tai_const(hp).endsym) then
+ begin
+ if (constdef in [aitconst_darwin_dwarf_delta32,aitconst_darwin_dwarf_delta64]) then
+ begin
+ s := NextSetLabel;
+ t := #9'.set '+s+','+tai_const(hp).endsym.name+'-'+tai_const(hp).sym.name;
+ end
+ else
+ s:=tai_const(hp).endsym.name+'-'+tai_const(hp).sym.name
+ end
+ else
+ s:=tai_const(hp).sym.name;
+{$ifdef avr}
+ s:=ReplaceForbiddenChars(s);
+{$endif avr}
+ if tai_const(hp).value<>0 then
+ s:=s+tostr_with_plus(tai_const(hp).value);
+ end
+ else
+{$ifdef cpu64bitaddr}
+ s:=tostr(tai_const(hp).value);
+{$else cpu64bitaddr}
+ { 64 bit constants are already handled above in this case }
+ s:=tostr(longint(tai_const(hp).value));
+{$endif cpu64bitaddr}
+ if constdef = aitconst_half16bit then
+ s:='('+s+')/2';
+
+ AsmWrite(s);
+ inc(l,length(s));
+ { Values with symbols are written on a single line to improve
+ reading of the .s file (PFV) }
+ if assigned(tai_const(hp).sym) or
+ not(LastSecType in [sec_data,sec_rodata,sec_rodata_norel]) or
+ (l>line_length) or
+ (hp.next=nil) or
+ (tai(hp.next).typ<>ait_const) or
+ (tai_const(hp.next).consttype<>constdef) or
+ assigned(tai_const(hp.next).sym) then
+ break;
+ hp:=tai(hp.next);
+ AsmWrite(',');
+ until false;
+ if (t <> '') then
+ begin
+ AsmLn;
+ AsmWrite(t);
+ end;
+ end;
+ AsmLn;
+ end;
+ else
+ internalerror(200704251);
+ end;
+ end;
+
+ { the "and defined(FPC_HAS_TYPE_EXTENDED)" isn't optimal but currently the only solution
+ it prevents proper cross compilation to i386 though
+ }
+{$if defined(cpuextended) and defined(FPC_HAS_TYPE_EXTENDED)}
+ ait_real_80bit :
+ begin
+ if do_line then
+ AsmWriteLn(target_asm.comment+'value: '+extended2str(tai_real_80bit(hp).value));
+ { Make sure e is a extended type, bestreal could be
+ a different type (bestreal) !! (PFV) }
+ e:=tai_real_80bit(hp).value;
+ AsmWrite(#9'.byte'#9);
+ for i:=0 to 9 do
+ begin
+ if i<>0 then
+ AsmWrite(',');
+ AsmWrite(tostr(t80bitarray(e)[i]));
+ end;
+ for i:=11 to tai_real_80bit(hp).savesize do
+ AsmWrite(',0');
+ AsmLn;
+ end;
+{$endif cpuextended}
+
+ ait_real_64bit :
+ begin
+ if do_line then
+ AsmWriteLn(target_asm.comment+'value: '+double2str(tai_real_64bit(hp).value));
+ d:=tai_real_64bit(hp).value;
+ { swap the values to correct endian if required }
+ if source_info.endian <> target_info.endian then
+ swap64bitarray(t64bitarray(d));
+ AsmWrite(#9'.byte'#9);
+{$ifdef arm}
+ if tai_real_64bit(hp).formatoptions=fo_hiloswapped then
+ begin
+ for i:=4 to 7 do
+ begin
+ if i<>4 then
+ AsmWrite(',');
+ AsmWrite(tostr(t64bitarray(d)[i]));
+ end;
+ for i:=0 to 3 do
+ begin
+ AsmWrite(',');
+ AsmWrite(tostr(t64bitarray(d)[i]));
+ end;
+ end
+ else
+{$endif arm}
+ begin
+ for i:=0 to 7 do
+ begin
+ if i<>0 then
+ AsmWrite(',');
+ AsmWrite(tostr(t64bitarray(d)[i]));
+ end;
+ end;
+ AsmLn;
+ end;
+
+ ait_real_32bit :
+ begin
+ if do_line then
+ AsmWriteLn(target_asm.comment+'value: '+single2str(tai_real_32bit(hp).value));
+ sin:=tai_real_32bit(hp).value;
+ { swap the values to correct endian if required }
+ if source_info.endian <> target_info.endian then
+ swap32bitarray(t32bitarray(sin));
+ AsmWrite(#9'.byte'#9);
+ for i:=0 to 3 do
+ begin
+ if i<>0 then
+ AsmWrite(',');
+ AsmWrite(tostr(t32bitarray(sin)[i]));
+ end;
+ AsmLn;
+ end;
+
+ ait_comp_64bit :
+ begin
+ if do_line then
+ AsmWriteLn(target_asm.comment+'value: '+extended2str(tai_comp_64bit(hp).value));
+ AsmWrite(#9'.byte'#9);
+ co:=comp(tai_comp_64bit(hp).value);
+ { swap the values to correct endian if required }
+ if source_info.endian <> target_info.endian then
+ swap64bitarray(t64bitarray(co));
+ for i:=0 to 7 do
+ begin
+ if i<>0 then
+ AsmWrite(',');
+ AsmWrite(tostr(t64bitarray(co)[i]));
+ end;
+ AsmLn;
+ end;
+
+ ait_string :
+ begin
+ pos:=0;
+ for i:=1 to tai_string(hp).len do
+ begin
+ if pos=0 then
+ begin
+ AsmWrite(#9'.ascii'#9'"');
+ pos:=20;
+ end;
+ ch:=tai_string(hp).str[i-1];
+ case ch of
+ #0, {This can't be done by range, because a bug in FPC}
+ #1..#31,
+ #128..#255 : s:='\'+tostr(ord(ch) shr 6)+tostr((ord(ch) and 63) shr 3)+tostr(ord(ch) and 7);
+ '"' : s:='\"';
+ '\' : s:='\\';
+ else
+ s:=ch;
+ end;
+ AsmWrite(s);
+ inc(pos,length(s));
+ if (pos>line_length) or (i=tai_string(hp).len) then
+ begin
+ AsmWriteLn('"');
+ pos:=0;
+ end;
+ end;
+ end;
+
+ ait_label :
+ begin
+ if (tai_label(hp).labsym.is_used) then
+ begin
+ if (tai_label(hp).labsym.bind=AB_PRIVATE_EXTERN) then
+ begin
+ AsmWrite(#9'.private_extern ');
+ AsmWriteln(tai_label(hp).labsym.name);
+ end;
+ if tai_label(hp).labsym.bind in [AB_GLOBAL,AB_PRIVATE_EXTERN] then
+ begin
+ AsmWrite('.globl'#9);
+{$ifdef avr}
+ AsmWriteLn(ReplaceForbiddenChars(tai_label(hp).labsym.name));
+{$else avr}
+ AsmWriteLn(tai_label(hp).labsym.name);
+{$endif avr}
+ end;
+{$ifdef avr}
+ AsmWrite(ReplaceForbiddenChars(tai_label(hp).labsym.name));
+{$else avr}
+ AsmWrite(tai_label(hp).labsym.name);
+{$endif avr}
+ AsmWriteLn(':');
+ end;
+ end;
+
+ ait_symbol :
+ begin
+ if (tai_symbol(hp).sym.bind=AB_PRIVATE_EXTERN) then
+ begin
+ AsmWrite(#9'.private_extern ');
+{$ifdef avr}
+ AsmWriteln(ReplaceForbiddenChars(tai_symbol(hp).sym.name));
+{$else avr}
+ AsmWriteln(tai_symbol(hp).sym.name);
+{$endif avr}
+ end;
+ if (target_info.system = system_powerpc64_linux) and
+ (tai_symbol(hp).sym.typ = AT_FUNCTION) and (cs_profile in current_settings.moduleswitches) then
+ AsmWriteLn('.globl _mcount');
+
+ if tai_symbol(hp).is_global then
+ begin
+ AsmWrite('.globl'#9);
+{$ifdef avr}
+ AsmWriteln(ReplaceForbiddenChars(tai_symbol(hp).sym.name));
+{$else avr}
+ AsmWriteln(tai_symbol(hp).sym.name);
+{$endif avr}
+ end;
+ if (target_info.system = system_powerpc64_linux) and
+ (tai_symbol(hp).sym.typ = AT_FUNCTION) then
+ begin
+ AsmWriteLn('.section ".opd", "aw"');
+ AsmWriteLn('.align 3');
+ AsmWriteLn(tai_symbol(hp).sym.name + ':');
+ AsmWriteLn('.quad .' + tai_symbol(hp).sym.name + ', .TOC.@tocbase, 0');
+ AsmWriteLn('.previous');
+ AsmWriteLn('.size ' + tai_symbol(hp).sym.name + ', 24');
+ if (tai_symbol(hp).is_global) then
+ AsmWriteLn('.globl .' + tai_symbol(hp).sym.name);
+ AsmWriteLn('.type .' + tai_symbol(hp).sym.name + ', @function');
+ { the dotted name is the name of the actual function entry }
+ AsmWrite('.');
+ end
+ else
+ begin
+ if (target_info.system <> system_arm_linux) then
+ sepChar := '@'
+ else
+ sepChar := '#';
+ if (tf_needs_symbol_type in target_info.flags) then
+ begin
+ AsmWrite(#9'.type'#9 + tai_symbol(hp).sym.name);
+ if (needsObject(tai_symbol(hp))) then
+ AsmWriteLn(',' + sepChar + 'object')
+ else
+ AsmWriteLn(',' + sepChar + 'function');
+ end;
+ end;
+{$ifdef avr}
+ if not(tai_symbol(hp).has_value) then
+ AsmWriteLn(ReplaceForbiddenChars(tai_symbol(hp).sym.name + ':'))
+ else
+ AsmWriteLn(ReplaceForbiddenChars(tai_symbol(hp).sym.name + '=' + tostr(tai_symbol(hp).value)));
+{$else avr}
+ if not(tai_symbol(hp).has_value) then
+ AsmWriteLn(tai_symbol(hp).sym.name + ':')
+ else
+ AsmWriteLn(tai_symbol(hp).sym.name + '=' + tostr(tai_symbol(hp).value));
+{$endif avr}
+ end;
+{$ifdef arm}
+ ait_thumb_func:
+ begin
+ AsmWriteLn(#9'.thumb_func');
+ end;
+{$endif arm}
+
+ ait_symbol_end :
+ begin
+ if tf_needs_symbol_size in target_info.flags then
+ begin
+ s:=target_asm.labelprefix+'e'+tostr(symendcount);
+ inc(symendcount);
+ AsmWriteLn(s+':');
+ AsmWrite(#9'.size'#9);
+ if (target_info.system = system_powerpc64_linux) and (tai_symbol_end(hp).sym.typ = AT_FUNCTION) then
+ AsmWrite('.');
+{$ifdef avr}
+ AsmWrite(ReplaceForbiddenChars(tai_symbol_end(hp).sym.name));
+{$else avr}
+ AsmWrite(tai_symbol_end(hp).sym.name);
+{$endif avr}
+ AsmWrite(', '+s+' - ');
+ if (target_info.system = system_powerpc64_linux) and (tai_symbol_end(hp).sym.typ = AT_FUNCTION) then
+ AsmWrite('.');
+{$ifdef avr}
+ AsmWriteLn(ReplaceForbiddenChars(tai_symbol_end(hp).sym.name));
+{$else avr}
+ AsmWriteLn(tai_symbol_end(hp).sym.name);
+{$endif avr}
+ end;
+ end;
+
+ ait_instruction :
+ begin
+ WriteInstruction(hp);
+ end;
+
+ ait_stab :
+ begin
+ if assigned(tai_stab(hp).str) then
+ begin
+ AsmWrite(#9'.'+stabtypestr[tai_stab(hp).stabtype]+' ');
+ AsmWritePChar(tai_stab(hp).str);
+ AsmLn;
+ end;
+ end;
+
+ ait_force_line,
+ ait_function_name :
+ ;
+
+ ait_cutobject :
+ begin
+ if SmartAsm then
+ begin
+ { only reset buffer if nothing has changed }
+ if AsmSize=AsmStartSize then
+ AsmClear
+ else
+ begin
+ AsmClose;
+ DoAssemble;
+ AsmCreate(tai_cutobject(hp).place);
+ end;
+ { avoid empty files }
+ while assigned(hp.next) and (tai(hp.next).typ in [ait_cutobject,ait_section,ait_comment]) do
+ begin
+ if tai(hp.next).typ=ait_section then
+ LastSecType:=tai_section(hp.next).sectype;
+ hp:=tai(hp.next);
+ end;
+ if LastSecType<>sec_none then
+ WriteSection(LastSecType,'',secorder_default);
+ AsmStartSize:=AsmSize;
+ end;
+ end;
+
+ ait_marker :
+ if tai_marker(hp).kind=mark_NoLineInfoStart then
+ inc(InlineLevel)
+ else if tai_marker(hp).kind=mark_NoLineInfoEnd then
+ dec(InlineLevel);
+
+ ait_directive :
+ begin
+ AsmWrite('.'+directivestr[tai_directive(hp).directive]+' ');
+ if assigned(tai_directive(hp).name) then
+ AsmWrite(tai_directive(hp).name^);
+ AsmLn;
+ end;
+
+ ait_seh_directive :
+ begin
+{$ifdef TEST_WIN64_SEH}
+ AsmWrite(sehdirectivestr[tai_seh_directive(hp).kind]);
+ case tai_seh_directive(hp).datatype of
+ sd_none:;
+ sd_string:
+ begin
+ AsmWrite(' '+tai_seh_directive(hp).data.name^);
+ if (tai_seh_directive(hp).data.flags and 1)<>0 then
+ AsmWrite(',@except');
+ if (tai_seh_directive(hp).data.flags and 2)<>0 then
+ AsmWrite(',@unwind');
+ end;
+ sd_reg:
+ AsmWrite(' '+gas_regname(tai_seh_directive(hp).data.reg));
+ sd_offset:
+ AsmWrite(' '+tostr(tai_seh_directive(hp).data.offset));
+ sd_regoffset:
+ AsmWrite(' '+gas_regname(tai_seh_directive(hp).data.reg)+', '+
+ tostr(tai_seh_directive(hp).data.offset));
+ end;
+ AsmLn;
+{$endif TEST_WIN64_SEH}
+ end;
+
+ else
+ internalerror(2006012201);
+ end;
+ hp:=tai(hp.next);
+ end;
+ end;
+
+
+ procedure TGNUAssembler.WriteExtraHeader;
+ begin
+ end;
+
+
+ procedure TGNUAssembler.WriteInstruction(hp: tai);
+ begin
+ InstrWriter.WriteInstruction(hp);
+ end;
+
+
+ procedure TGNUAssembler.WriteWeakSymbolDef(s: tasmsymbol);
+ begin
+ AsmWriteLn(#9'.weak '+s.name);
+ end;
+
+
+ procedure TGNUAssembler.WriteAsmList;
+ var
+ n : string;
+ hal : tasmlisttype;
+ i: longint;
+ begin
+{$ifdef EXTDEBUG}
+ if assigned(current_module.mainsource) then
+ Comment(V_Debug,'Start writing gas-styled assembler output for '+current_module.mainsource^);
+{$endif}
+
+ if assigned(current_module.mainsource) then
+ n:=ExtractFileName(current_module.mainsource^)
+ else
+ n:=InputFileName;
+
+ { gcc does not add it either for Darwin (and AIX). Grep for
+ TARGET_ASM_FILE_START_FILE_DIRECTIVE in gcc/config/*.h
+ }
+ if not(target_info.system in systems_darwin) then
+ AsmWriteLn(#9'.file "'+FixFileName(n)+'"');
+
+ WriteExtraHeader;
+ AsmStartSize:=AsmSize;
+ symendcount:=0;
+
+ for hal:=low(TasmlistType) to high(TasmlistType) do
+ begin
+ AsmWriteLn(target_asm.comment+'Begin asmlist '+AsmlistTypeStr[hal]);
+ writetree(current_asmdata.asmlists[hal]);
+ AsmWriteLn(target_asm.comment+'End asmlist '+AsmlistTypeStr[hal]);
+ end;
+
+ { add weak symbol markers }
+ for i:=0 to current_asmdata.asmsymboldict.count-1 do
+ if (tasmsymbol(current_asmdata.asmsymboldict[i]).bind=AB_WEAK_EXTERNAL) then
+ writeweaksymboldef(tasmsymbol(current_asmdata.asmsymboldict[i]));
+
+ if create_smartlink_sections and
+ (target_info.system in systems_darwin) then
+ AsmWriteLn(#9'.subsections_via_symbols');
+
+ { "no executable stack" marker for Linux }
+ if (target_info.system in systems_linux) and
+ not(cs_executable_stack in current_settings.moduleswitches) then
+ begin
+ AsmWriteLn('.section .note.GNU-stack,"",%progbits');
+ end;
+
+ AsmLn;
+{$ifdef EXTDEBUG}
+ if assigned(current_module.mainsource) then
+ Comment(V_Debug,'Done writing gas-styled assembler output for '+current_module.mainsource^);
+{$endif EXTDEBUG}
+ end;
+
+
+{****************************************************************************}
+{ Apple/GNU Assembler writer }
+{****************************************************************************}
+
+ function TAppleGNUAssembler.sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;
+ begin
+ if (target_info.system in systems_darwin) then
+ case atype of
+ sec_bss:
+ { all bss (lcomm) symbols are automatically put in the right }
+ { place by using the lcomm assembler directive }
+ atype := sec_none;
+ sec_debug_frame,
+ sec_eh_frame:
+ begin
+ result := '.section __DWARF,__debug_info,regular,debug';
+ exit;
+ end;
+ sec_debug_line:
+ begin
+ result := '.section __DWARF,__debug_line,regular,debug';
+ exit;
+ end;
+ sec_debug_info:
+ begin
+ result := '.section __DWARF,__debug_info,regular,debug';
+ exit;
+ end;
+ sec_debug_abbrev:
+ begin
+ result := '.section __DWARF,__debug_abbrev,regular,debug';
+ exit;
+ end;
+ sec_rodata:
+ begin
+ result := '.const_data';
+ exit;
+ end;
+ sec_rodata_norel:
+ begin
+ result := '.const';
+ exit;
+ end;
+ sec_fpc:
+ begin
+ result := '.section __TEXT, .fpc, regular, no_dead_strip';
+ exit;
+ end;
+ sec_code:
+ begin
+ if (aname='fpc_geteipasebx') or
+ (aname='fpc_geteipasecx') then
+ begin
+ result:='.section __TEXT,__textcoal_nt,coalesced,pure_instructions'#10'.weak_definition '+aname+
+ #10'.private_extern '+aname;
+ exit;
+ end;
+ end;
+ sec_data_nonlazy:
+ begin
+ result:='.section __DATA, __nl_symbol_ptr,non_lazy_symbol_pointers';
+ exit;
+ end;
+ sec_data_lazy:
+ begin
+ result:='.section __DATA, __la_symbol_ptr,lazy_symbol_pointers';
+ exit;
+ end;
+ sec_init_func:
+ begin
+ result:='.section __DATA, __mod_init_func, mod_init_funcs';
+ exit;
+ end;
+ sec_term_func:
+ begin
+ result:='.section __DATA, __mod_term_func, mod_term_funcs';
+ exit;
+ end;
+ sec_objc_protocol_ext:
+ begin
+ result:='.section __OBJC, __protocol_ext, regular, no_dead_strip';
+ exit;
+ end;
+ sec_objc_class_ext:
+ begin
+ result:='.section __OBJC, __class_ext, regular, no_dead_strip';
+ exit;
+ end;
+ sec_objc_property:
+ begin
+ result:='.section __OBJC, __property, regular, no_dead_strip';
+ exit;
+ end;
+ sec_objc_image_info:
+ begin
+ result:='.section __OBJC, __image_info, regular, no_dead_strip';
+ exit;
+ end;
+ sec_objc_cstring_object:
+ begin
+ result:='.section __OBJC, __cstring_object, regular, no_dead_strip';
+ exit;
+ end;
+ sec_objc_sel_fixup:
+ begin
+ result:='.section __OBJC, __sel_fixup, regular, no_dead_strip';
+ exit;
+ end;
+ sec_objc_message_refs:
+ begin
+ if (target_info.system in systems_objc_nfabi) then
+ begin
+ result:='.section __DATA, __objc_selrefs, literal_pointers, no_dead_strip';
+ exit;
+ end;
+ end;
+ sec_objc_cls_refs:
+ begin
+ if (target_info.system in systems_objc_nfabi) then
+ begin
+ result:='.section __DATA, __objc_clsrefs, regular, no_dead_strip';
+ exit;
+ end;
+ end;
+ sec_objc_meth_var_names,
+ sec_objc_class_names:
+ begin
+ if (target_info.system in systems_objc_nfabi) then
+ begin
+ result:='.cstring';
+ exit
+ end;
+ end;
+ sec_objc_inst_meth,
+ sec_objc_cls_meth,
+ sec_objc_cat_inst_meth,
+ sec_objc_cat_cls_meth:
+ begin
+ if (target_info.system in systems_objc_nfabi) then
+ begin
+ result:='.section __DATA, __objc_const';
+ exit;
+ end;
+ end;
+ sec_objc_meta_class,
+ sec_objc_class:
+ begin
+ if (target_info.system in systems_objc_nfabi) then
+ begin
+ result:='.section __DATA, __objc_data';
+ exit;
+ end;
+ end;
+ sec_objc_sup_refs:
+ begin
+ result:='.section __DATA, __objc_superrefs, regular, no_dead_strip';
+ exit
+ end;
+ sec_objc_classlist:
+ begin
+ result:='.section __DATA, __objc_classlist, regular, no_dead_strip';
+ exit
+ end;
+ sec_objc_nlclasslist:
+ begin
+ result:='.section __DATA, __objc_nlclasslist, regular, no_dead_strip';
+ exit
+ end;
+ sec_objc_catlist:
+ begin
+ result:='.section __DATA, __objc_catlist, regular, no_dead_strip';
+ exit
+ end;
+ sec_objc_nlcatlist:
+ begin
+ result:='.section __DATA, __objc_nlcatlist, regular, no_dead_strip';
+ exit
+ end;
+ sec_objc_protolist:
+ begin
+ result:='.section __DATA, __objc_protolist, coalesced, no_dead_strip';
+ exit;
+ end;
+ end;
+ result := inherited sectionname(atype,aname,aorder);
+ end;
+
+
+ procedure TAppleGNUAssembler.WriteWeakSymbolDef(s: tasmsymbol);
+ begin
+ AsmWriteLn(#9'.weak_reference '+s.name);
+ end;
+
+
+{****************************************************************************}
+{ a.out/GNU Assembler writer }
+{****************************************************************************}
+
+ function TAoutGNUAssembler.sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;
+ const
+(* Translation table - replace unsupported section types with basic ones. *)
+ SecXTable: array[TAsmSectionType] of TAsmSectionType = (
+ sec_none,
+ sec_none,
+ sec_code,
+ sec_data,
+ sec_data (* sec_rodata *),
+ sec_data (* sec_rodata_norel *),
+ sec_bss,
+ sec_data (* sec_threadvar *),
+ { used for wince exception handling }
+ sec_code (* sec_pdata *),
+ { used for darwin import stubs }
+ sec_code (* sec_stub *),
+ sec_data,(* sec_data_nonlazy *)
+ sec_data,(* sec_data_lazy *)
+ sec_data,(* sec_init_func *)
+ sec_data,(* sec_term_func *)
+ { stabs }
+ sec_stab,sec_stabstr,
+ { win32 }
+ sec_data (* sec_idata2 *),
+ sec_data (* sec_idata4 *),
+ sec_data (* sec_idata5 *),
+ sec_data (* sec_idata6 *),
+ sec_data (* sec_idata7 *),
+ sec_data (* sec_edata *),
+ { C++ exception handling unwinding (uses dwarf) }
+ sec_eh_frame,
+ { dwarf }
+ sec_debug_frame,
+ sec_debug_info,
+ sec_debug_line,
+ sec_debug_abbrev,
+ { ELF resources (+ references to stabs debug information sections) }
+ sec_code (* sec_fpc *),
+ { Table of contents section }
+ sec_code (* sec_toc *),
+ sec_code (* sec_init *),
+ sec_code (* sec_fini *),
+ sec_none (* sec_objc_class *),
+ sec_none (* sec_objc_meta_class *),
+ sec_none (* sec_objc_cat_cls_meth *),
+ sec_none (* sec_objc_cat_inst_meth *),
+ sec_none (* sec_objc_protocol *),
+ sec_none (* sec_objc_string_object *),
+ sec_none (* sec_objc_cls_meth *),
+ sec_none (* sec_objc_inst_meth *),
+ sec_none (* sec_objc_cls_refs *),
+ sec_none (* sec_objc_message_refs *),
+ sec_none (* sec_objc_symbols *),
+ sec_none (* sec_objc_category *),
+ sec_none (* sec_objc_class_vars *),
+ sec_none (* sec_objc_instance_vars *),
+ sec_none (* sec_objc_module_info *),
+ sec_none (* sec_objc_class_names *),
+ sec_none (* sec_objc_meth_var_types *),
+ sec_none (* sec_objc_meth_var_names *),
+ sec_none (* sec_objc_selector_strs *),
+ sec_none (* sec_objc_protocol_ext *),
+ sec_none (* sec_objc_class_ext *),
+ sec_none (* sec_objc_property *),
+ sec_none (* sec_objc_image_info *),
+ sec_none (* sec_objc_cstring_object *),
+ sec_none (* sec_objc_sel_fixup *),
+ sec_none (* sec_objc_data *),
+ sec_none (* sec_objc_const *),
+ sec_none (* sec_objc_sup_refs *),
+ sec_none (* sec_data_coalesced *),
+ sec_none (* sec_objc_classlist *),
+ sec_none (* sec_objc_nlclasslist *),
+ sec_none (* sec_objc_catlist *),
+ sec_none (* sec_objc_nlcatlist *),
+ sec_none (* sec_objc_protlist *)
+ );
+ begin
+ Result := inherited SectionName (SecXTable [AType], AName, AOrder);
+ end;
+
+
+{****************************************************************************}
+{ Abstract Instruction Writer }
+{****************************************************************************}
+
+ constructor TCPUInstrWriter.create(_owner: TGNUAssembler);
+ begin
+ inherited create;
+ owner := _owner;
+ end;
+
+end.
diff --git a/closures/compiler/alpha/aasmcpu.pas b/closures/compiler/alpha/aasmcpu.pas
new file mode 100644
index 0000000000..6e1ef8d02b
--- /dev/null
+++ b/closures/compiler/alpha/aasmcpu.pas
@@ -0,0 +1,281 @@
+{
+ Copyright (c) 1998-2000 by Florian Klaempfl
+
+ Implements the assembler classes specific for the Alpha
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+{
+ Implements the assembler classes specific for the Alpha.
+}
+unit aasmcpu;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ aasmbase,globals,verbose,
+ cpubase,aasmtai,aasmdata,aasmsym;
+
+ type
+ tai_frame = class(tai)
+ G,R : TRegister;
+ LS,LU : longint;
+ Constructor Create (GP : Tregister; Localsize : Longint; RA : TRegister; L : longint);
+ end;
+
+ tai_ent = class(tai)
+ Name : string;
+ Constructor Create (const ProcName : String);
+ end;
+
+
+ taicpu = class(tai_cpu_abstract_sym)
+ constructor op_none(op : tasmop);
+
+ constructor op_reg(op : tasmop;_op1 : tregister);
+ constructor op_const(op : tasmop;_op1 : longint);
+ constructor op_ref(op : tasmop;_op1 : preference);
+
+ constructor op_reg_reg(op : tasmop;_op1,_op2 : tregister);
+ constructor op_reg_ref(op : tasmop;_op1 : tregister;_op2 : preference);
+ constructor op_reg_const(op:tasmop; _op1: tregister; _op2: longint);
+
+ constructor op_const_reg(op : tasmop;_op1 : longint;_op2 : tregister);
+ constructor op_const_const(op : tasmop;_op1,_op2 : longint);
+ constructor op_const_ref(op : tasmop;_op1 : longint;_op2 : preference);
+
+ constructor op_ref_reg(op : tasmop;_op1 : preference;_op2 : tregister);
+ { this is only allowed if _op1 is an int value (_op1^.isintvalue=true) }
+ constructor op_ref_ref(op : tasmop;_op1,_op2 : preference);
+
+ constructor op_reg_reg_reg(op : tasmop;_op1,_op2,_op3 : tregister);
+ constructor op_reg_const_reg(op : tasmop;_op1 : tregister;_op2 : longint;_op3 : tregister);
+ constructor op_const_ref_reg(op : tasmop;_op1 : longint;_op2 : preference;_op3 : tregister);
+ constructor op_reg_reg_ref(op : tasmop;_op1,_op2 : tregister; _op3 : preference);
+ constructor op_const_reg_ref(op : tasmop;_op1 : longint;_op2 : tregister;_op3 : preference);
+ constructor op_reg_ref_const(op : tasmop;_op1 : tregister;_op2 : preference;_op3 : longint);
+
+ { this is for Jmp instructions }
+ constructor op_cond_sym(op : tasmop;cond:TAsmCond;_op1 : tasmsymbol);
+
+ constructor op_sym(op : tasmop;_op1 : tasmsymbol);
+ constructor op_sym_ofs(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint);
+ constructor op_sym_ofs_reg(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint;_op2 : tregister);
+ constructor op_sym_ofs_ref(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint;_op2 : preference);
+ end;
+
+ tai_align = class(tai_align_abstract)
+ { nothing to add }
+ end;
+
+ procedure InitAsm;
+ procedure DoneAsm;
+
+implementation
+
+
+{*****************************************************************************
+ taicpu Constructors
+*****************************************************************************}
+
+
+ constructor taicpu.op_none(op : tasmop);
+ begin
+ inherited create(op);
+ end;
+
+
+ constructor taicpu.op_reg(op : tasmop;_op1 : tregister);
+ begin
+ inherited create(op);
+ ops:=1;
+ end;
+
+
+ constructor taicpu.op_const(op : tasmop;_op1 : longint);
+ begin
+ inherited create(op);
+ ops:=1;
+ end;
+
+
+ constructor taicpu.op_ref(op : tasmop;_op1 : preference);
+ begin
+ inherited create(op);
+ ops:=1;
+ end;
+
+
+ constructor taicpu.op_reg_reg(op : tasmop;_op1,_op2 : tregister);
+ begin
+ inherited create(op);
+ ops:=2;
+ end;
+
+
+ constructor taicpu.op_reg_const(op:tasmop; _op1: tregister; _op2: longint);
+ begin
+ inherited create(op);
+ ops:=2;
+ end;
+
+
+ constructor taicpu.op_reg_ref(op : tasmop;_op1 : tregister;_op2 : preference);
+ begin
+ inherited create(op);
+ ops:=2;
+ end;
+
+
+ constructor taicpu.op_const_reg(op : tasmop;_op1 : longint;_op2 : tregister);
+ begin
+ inherited create(op);
+ ops:=2;
+ end;
+
+
+ constructor taicpu.op_const_const(op : tasmop;_op1,_op2 : longint);
+ begin
+ inherited create(op);
+ ops:=2;
+ end;
+
+
+ constructor taicpu.op_const_ref(op : tasmop;_op1 : longint;_op2 : preference);
+ begin
+ inherited create(op);
+ ops:=2;
+ end;
+
+ constructor taicpu.op_ref_reg(op : tasmop;_op1 : preference;_op2 : tregister);
+ begin
+ inherited create(op);
+ ops:=2;
+ end;
+
+
+ constructor taicpu.op_ref_ref(op : tasmop;_op1,_op2 : preference);
+ begin
+ inherited create(op);
+ ops:=2;
+ end;
+
+
+ constructor taicpu.op_reg_reg_reg(op : tasmop;_op1,_op2,_op3 : tregister);
+ begin
+ inherited create(op);
+ ops:=3;
+ end;
+
+ constructor taicpu.op_reg_const_reg(op : tasmop;_op1 : tregister;_op2 : longint;_op3 : tregister);
+ begin
+ inherited create(op);
+ ops:=3;
+ end;
+
+ constructor taicpu.op_reg_reg_ref(op : tasmop;_op1,_op2 : tregister;_op3 : preference);
+ begin
+ inherited create(op);
+ ops:=3;
+ end;
+
+ constructor taicpu.op_const_ref_reg(op : tasmop;_op1 : longint;_op2 : preference;_op3 : tregister);
+ begin
+ inherited create(op);
+ ops:=3;
+ end;
+
+ constructor taicpu.op_const_reg_ref(op : tasmop;_op1 : longint;_op2 : tregister;_op3 : preference);
+ begin
+ inherited create(op);
+ ops:=3;
+ end;
+
+ constructor taicpu.op_reg_ref_const(op : tasmop;_op1 : tregister;_op2 : preference;_op3 : longint);
+ begin
+ inherited create(op);
+ ops:=3;
+ end;
+
+
+ constructor taicpu.op_cond_sym(op : tasmop;cond:TAsmCond;_op1 : tasmsymbol);
+ begin
+ inherited create(op);
+ condition:=cond;
+ ops:=1;
+ end;
+
+
+ constructor taicpu.op_sym(op : tasmop;_op1 : tasmsymbol);
+ begin
+ inherited create(op);
+ ops:=1;
+ end;
+
+
+ constructor taicpu.op_sym_ofs(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint);
+ begin
+ inherited create(op);
+ ops:=1;
+ end;
+
+
+ constructor taicpu.op_sym_ofs_reg(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint;_op2 : tregister);
+ begin
+ inherited create(op);
+ ops:=2;
+ end;
+
+
+ constructor taicpu.op_sym_ofs_ref(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint;_op2 : preference);
+ begin
+ inherited create(op);
+ ops:=2;
+ end;
+
+ Constructor tai_frame.create (GP : Tregister; Localsize : Longint; RA : TRegister; L : longint);
+
+ begin
+ Inherited Create;
+ typ:=ait_frame;
+ G:=GP;
+ R:=RA;
+ LS:=LocalSize;
+ LU:=L;
+ end;
+
+ Constructor tai_ent.Create (const ProcName : String);
+
+ begin
+ Inherited Create;
+ typ:=ait_ent;
+ Name:=ProcName;
+ end;
+
+ procedure InitAsm;
+ begin
+ end;
+
+
+ procedure DoneAsm;
+ begin
+ end;
+
+
+ end.
diff --git a/closures/compiler/alpha/agaxpgas.pas b/closures/compiler/alpha/agaxpgas.pas
new file mode 100644
index 0000000000..eefa51a367
--- /dev/null
+++ b/closures/compiler/alpha/agaxpgas.pas
@@ -0,0 +1,126 @@
+{
+ Copyright (c) 1998-2000 by Florian Klaempfl
+
+ This unit implements an asm for the DEC Alpha
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit agaxpgas;
+
+ {$i fpcdefs.inc}
+
+ interface
+
+ uses
+ globals,systems,aasmbase,aasmtai,aasmdata,
+ aggas,cpubase;
+
+ type
+ TAXPGNUAssembler=class(TGNUAssembler)
+ procedure WriteInstruction(hp : tai);override;
+ end;
+
+ const
+ gas_reg2str : array[tregister] of string[4] = (
+ '',
+ '','','','','','','','','','',
+ '','','','','','','','','','',
+ '','','','','','','','','','',
+ '','',
+ '','','','','','','','','','',
+ '','','','','','','','','','',
+ '','','','','','','','','','',
+ '',''
+ );
+
+ implementation
+
+ const
+ op2str : array[tasmop] of string[14] = (
+ 'addf','addg','addl','addq',
+ 'adds','addt','amask','and','beq','bge',
+ 'bgt','bic','bis','blbc','blbs','ble',
+ 'blt','bne','br','bsr','call_pal','cmoveq',
+ 'cmovge','cmovgt','cmovlbc','cmovlbs','cmovle','cmovlt',
+ 'cmovne','cmpbge','cmpeq','cmpgeq','cmpgle','cmpglt',
+ 'cmple','cmplt','cmpteq','cmptle','cmptlt','cmptun',
+ 'cmpule','cmpult','cpys','cpyse','cpysn','ctlz',
+ 'ctpop','cttz','cvtdg','cvtgd','cvtgf','cvtgq',
+ 'cvtlq','cvtqf','cvtqg','cvtql','cvtqs','cvtqt',
+ 'cvtst','cvttq','cvtts','divf','divg','divs',
+ 'divt','ecb','eqv','excb','extbl','extlh',
+ 'extll','extqh','extql','extwh','extwl','fbeq',
+ 'fbge','fbgt','fble','fblt','fbne','fcmoveq',
+ 'fcmovge','fcmovgt','fcmovle','fcmovlt','fcmovne','fetch',
+ 'fetch_m','ftois','ftoit','implver','insbl','inslh',
+ 'insll','insqh','insql','inswh','inswl','itoff',
+ 'itofs','itoft','jmp','jsr','jsr_coroutine','lda',
+ 'ldah','ldbu','ldwu','ldf','ldg','ldl',
+ 'ldl_l','ldq','ldq_l','ldq_u','lds','ldt',
+ 'maxsb8','maxsw4','maxub8','maxuw4','mb','mf_fpcr',
+ 'minsb8','minsw4','minub8','minuw4','mskbl','msklh',
+ 'mskll','mskqh','mskql','mskwh','mskwl','mt_fpcr',
+ 'mulf','mulg','mull','mulq',
+ 'muls','mult','ornot','perr','pklb','pkwb',
+ 'rc','ret','rpcc','rs','s4addl','s4addq',
+ 's4subl','s4subq','s8addl','s8addq','s8subl','s8subq',
+ 'sextb','sextw','sll','sqrtf','sqrtg','sqrts',
+ 'sqrtt','sra','srl','stb','stf','stg',
+ 'sts','stl','stl_c','stq','stq_c','stq_u',
+ 'stt','stw','subf','subg','subl',
+ 'subq','subs','subt','trapb','umulh','unpkbl',
+ 'unpkbw','wh64','wmb','xor','zap','zapnot',
+ 'ldgp');
+
+ procedure TAXPGNUAssembler.WriteInstruction (hp : tai);
+ begin
+(*
+ op:=paicpu(hp)^.opcode;
+ calljmp:=is_calljmp(op);
+ { call maybe not translated to calll }
+ s:=#9+att_op2str[op]+cond2str[paicpu(hp)^.condition];
+ if (not calljmp) and
+ (not att_nosuffix[op]) and
+ not(
+ (paicpu(hp)^.oper[0].typ=top_reg) and
+ (paicpu(hp)^.oper[0].reg in [R_ST..R_ST7])
+ ) then
+ s:=s+att_opsize2str[paicpu(hp)^.opsize];
+ { process operands }
+ if paicpu(hp)^.ops<>0 then
+ begin
+ { call and jmp need an extra handling }
+ { this code is only called if jmp isn't a labeled instruction }
+ if calljmp then
+ s:=s+#9+getopstr_jmp(paicpu(hp)^.oper[0])
+ else
+ begin
+ for i:=0to paicpu(hp)^.ops-1 do
+ begin
+ if i=0 then
+ sep:=#9
+ else
+ sep:=',';
+ s:=s+sep+getopstr(paicpu(hp)^.oper[i])
+ end;
+ end;
+ end;
+ AsmWriteLn(s);
+*)
+ end;
+
+end.
diff --git a/closures/compiler/alpha/aoptcpu.pas b/closures/compiler/alpha/aoptcpu.pas
new file mode 100644
index 0000000000..494edf948c
--- /dev/null
+++ b/closures/compiler/alpha/aoptcpu.pas
@@ -0,0 +1,38 @@
+{
+ Copyright (c) 1998-2000 by Jonas Maebe, member of the Free Pascal
+ Development Team
+
+ This unit implements the Alpha optimizer object
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+
+
+Unit aoptcpu;
+
+Interface
+
+uses cpubase, aoptobj, aoptcpub;
+
+Type
+ TAOptCpu = Object(TAoptObj)
+ { uses the same constructor as TAopObj }
+ End;
+
+Implementation
+
+End.
diff --git a/closures/compiler/alpha/aoptcpub.pas b/closures/compiler/alpha/aoptcpub.pas
new file mode 100644
index 0000000000..aaad2910c3
--- /dev/null
+++ b/closures/compiler/alpha/aoptcpub.pas
@@ -0,0 +1,115 @@
+ {
+ Copyright (c) 1998-2000 by Jonas Maebe, member of the Free Pascal
+ Development Team
+
+ This unit contains several types and constants necessary for the
+ optimizer to work on the 80x86 architecture
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+Unit aoptcpub; { Assembler OPTimizer CPU specific Base }
+
+{ enable the following define if memory references can have both a base and }
+{ index register in 1 operand }
+
+{$define RefsHaveIndexReg}
+
+{ enable the following define if memory references can have a scaled index }
+
+{$define RefsHaveScale}
+
+{ enable the following define if memory references can have a segment }
+{ override }
+
+{ define RefsHaveSegment}
+
+Interface
+
+Uses
+ CPUAsm,AOptBase;
+
+Type
+
+{ type of a normal instruction }
+ TInstr = Taicpu;
+ PInstr = ^TInstr;
+
+{ ************************************************************************* }
+{ **************************** TCondRegs ********************************** }
+{ ************************************************************************* }
+{ Info about the conditional registers }
+ TCondRegs = Object
+ Constructor Init;
+ Destructor Done;
+ End;
+
+{ ************************************************************************* }
+{ **************************** TAoptBaseCpu ******************************* }
+{ ************************************************************************* }
+
+ TAoptBaseCpu = Object(TAoptBase)
+ End;
+
+
+{ ************************************************************************* }
+{ ******************************* Constants ******************************* }
+{ ************************************************************************* }
+Const
+
+{ the maximum number of things (registers, memory, ...) a single instruction }
+{ changes }
+
+ MaxCh = 3;
+
+{ the maximum number of operands an instruction has }
+
+ MaxOps = 3;
+
+{Oper index of operand that contains the source (reference) with a load }
+{instruction }
+
+ LoadSrc = 0;
+
+{Oper index of operand that contains the destination (register) with a load }
+{instruction }
+
+ LoadDst = 1;
+
+{Oper index of operand that contains the source (register) with a store }
+{instruction }
+
+ StoreSrc = 0;
+
+{Oper index of operand that contains the destination (reference) with a load }
+{instruction }
+
+ StoreDst = 1;
+
+Implementation
+
+{ ************************************************************************* }
+{ **************************** TCondRegs ********************************** }
+{ ************************************************************************* }
+Constructor TCondRegs.init;
+Begin
+End;
+
+Destructor TCondRegs.Done; {$ifdef inl} inline; {$endif inl}
+Begin
+End;
+
+End.
diff --git a/closures/compiler/alpha/aoptcpuc.pas b/closures/compiler/alpha/aoptcpuc.pas
new file mode 100644
index 0000000000..121a45370f
--- /dev/null
+++ b/closures/compiler/alpha/aoptcpuc.pas
@@ -0,0 +1,38 @@
+ {
+ Copyright (c) 1998-2000 by Jonas Maebe, member of the Free Pascal
+ Development Team
+
+ This unit contains the processor specific implementation of the
+ assembler optimizer common subexpression elimination object.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit aoptcpuc;
+
+Interface
+
+Uses
+ AOptCs;
+
+Type
+ TRegInfoCpu = Object(TRegInfo)
+ End;
+
+
+Implementation
+
+End.
diff --git a/closures/compiler/alpha/aoptcpud.pas b/closures/compiler/alpha/aoptcpud.pas
new file mode 100644
index 0000000000..c3ea9fe5f9
--- /dev/null
+++ b/closures/compiler/alpha/aoptcpud.pas
@@ -0,0 +1,39 @@
+{
+ Copyright (c) 1998-2000 by Jonas Maebe, member of the Free Pascal
+ Development Team
+
+ This unit contains the processor specific implementation of the
+ assembler optimizer data flow analyzer.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+Unit aoptcpud;
+
+Interface
+
+uses
+ AOptDA;
+
+Type
+ PAOptDFACpu = ^TAOptDFACpu;
+ TAOptDFACpu = Object(TAOptDFA)
+ End;
+
+Implementation
+
+
+End.
diff --git a/closures/compiler/alpha/cgcpu.pas b/closures/compiler/alpha/cgcpu.pas
new file mode 100644
index 0000000000..6706e90e48
--- /dev/null
+++ b/closures/compiler/alpha/cgcpu.pas
@@ -0,0 +1,167 @@
+{
+ Copyright (c) 1998-2000 by Florian Klaempfl
+
+ This unit implements the code generator for the Alpha
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+{
+ This unit implements the code generator for the Alpha.
+}
+unit cgcpu;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ cgbase,cgobj,aasmbase,aasmtai,aasmdata,aasmcpu,cginfo,cpubase,cpuinfo;
+
+type
+pcgalpha = ^tcgalpha;
+tcgalpha = class(tcg)
+ procedure a_call_name(list : TAsmList;const s : string);override;
+ procedure a_load_const_reg(list : TAsmList;size : tcgsize;a : aword;register : tregister);override;
+ procedure a_load_reg_ref(list : TAsmList;size : tcgsize;register : tregister;const ref : treference);override;
+ procedure a_load_ref_reg(list : TAsmList;size : tcgsize;const ref : treference;register : tregister);override;
+ procedure a_load_reg_reg(list : TAsmList;fromsize, tosize : tcgsize;reg1,reg2 : tregister);override;
+ procedure a_cmp_const_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;a : aword;
+ reg : tregister; l : tasmlabel);override;
+ procedure a_cmp_reg_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel);
+ procedure a_cmp_reg_ref_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;reg : tregister;l : tasmlabel);
+ procedure a_cmp_ref_const_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;a : aword;
+ reg : tregister; l : tasmlabel);
+ procedure a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);override;
+ procedure g_stackframe_entry(list : TAsmList;localsize : longint);override;
+ procedure g_maybe_loadself(list : TAsmList);override;
+ procedure g_restore_frame_pointer(list : TAsmList);override;
+end;
+
+procedure create_codegen;
+
+implementation
+
+uses
+ globtype,globals;
+
+procedure tcgalpha.g_stackframe_entry(list : TAsmList;localsize : longint);
+
+begin
+ list.concat(taicpu.op_reg_ref(A_LDGP,Global_pointer,new_reference(R_27,0)));
+ list.concat(taicpu.op_reg_ref(A_LDA,stack_pointer_reg,new_reference(stack_pointer_reg,-LocalSize)));
+ If LocalSize<>0 then
+ list.concat(tai_frame.create(Global_pointer,LocalSize,R_27,0));
+ { Always generate a frame pointer. }
+ list.concat(taicpu.op_reg_reg_reg(A_BIS,stack_pointer_reg,stack_pointer_reg,frame_pointer_reg));
+end;
+
+procedure g_exitcode(list : TAsmList;parasize : longint; nostackframe,inlined : boolean);
+
+begin
+ { Restore stack pointer from frame pointer }
+ list.Concat (taicpu.op_reg_reg_reg(A_BIS,frame_pointer_reg,frame_pointer_reg,stack_pointer_reg));
+ { Restore previous stack position}
+ list.Concat (taicpu.op_reg_const_reg(A_ADDQ,stack_pointer_reg,Parasize,stack_pointer_reg));
+ { return... }
+ list.Concat(taicpu.op_reg_ref_const(A_RET,stack_pointer_reg,new_reference(Return_pointer,0),1));
+ { end directive
+ Concat (paiend,init(''));
+ }
+end;
+
+procedure tcgalpha.a_call_name(list : TAsmList;const s : string);
+
+ begin
+ { list^.concat(taicpu,op_sym(A_CALL,S_NO,newasmsymbol(s,AB_EXTERNAL,AT_FUNCTION)))); }
+ {!!!!!!!!!1 offset is ignored }
+ abstract;
+ end;
+
+procedure tcgalpha.a_load_const_reg(list : TAsmList;size : tcgsize;a : aword;register : tregister);
+
+begin
+end;
+
+
+procedure tcgalpha.a_load_reg_ref(list : TAsmList;size : tcgsize;register : tregister;const ref : treference);
+
+begin
+end;
+
+
+procedure tcgalpha.a_load_ref_reg(list : TAsmList;size : tcgsize;const ref : treference;register : tregister);
+
+begin
+end;
+
+
+procedure tcgalpha.a_load_reg_reg(list : TAsmList;fromsize, tosize : tcgsize;reg1,reg2 : tregister);
+
+begin
+end;
+
+
+procedure tcgalpha.a_cmp_const_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;a : aword;reg : tregister;
+ l : tasmlabel);
+
+begin
+end;
+
+
+procedure tcgalpha.a_cmp_reg_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel);
+
+begin
+end;
+
+
+procedure tcgalpha.a_cmp_reg_ref_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;reg : tregister;l : tasmlabel);
+
+begin
+end;
+
+
+procedure tcgalpha.a_cmp_ref_const_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;a : aword;
+ reg : tregister; l : tasmlabel);
+
+begin
+end;
+
+
+procedure tcgalpha.a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);
+
+begin
+end;
+
+
+procedure tcgalpha.g_maybe_loadself(list : TAsmList);
+
+begin
+end;
+
+
+procedure tcgalpha.g_restore_frame_pointer(list : TAsmList);
+
+begin
+end;
+
+
+procedure create_codegen;
+ begin
+ cg:=tcgalpha.create;
+ end;
+
+end.
diff --git a/closures/compiler/alpha/cpubase.pas b/closures/compiler/alpha/cpubase.pas
new file mode 100644
index 0000000000..1136e1d7de
--- /dev/null
+++ b/closures/compiler/alpha/cpubase.pas
@@ -0,0 +1,430 @@
+{
+ Copyright (C) 1998-2000 by Florian Klaempfl
+
+ This unit implements an asmlistitem class for the Alpha architecture.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+{
+ This unit implements an asmlistitem class for the Alpha architecture.
+}
+unit cpubase;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ cutils,cclasses,globals,aasmbase,cpuinfo,cginfo;
+
+ type
+ { all registers }
+ TRegister = (R_NO, { R_NO is Mandatory, signifies no register }
+ R_0,R_1,R_2,R_3,R_4,R_5,R_6,R_7,R_8,R_9,
+ R_10,R_11,R_12,R_13,R_14,R_15,R_16,R_17,R_18,R_19,
+ R_20,R_21,R_22,R_23,R_24,R_25,R_26,R_27,R_28,R_29,
+ R_30,R_31,
+ R_F0,R_F1,R_F2,R_F3,R_F4,R_F5,R_F6,R_F7,R_F8,R_F9,
+ R_F10,R_F11,R_F12,R_F13,R_F14,R_F15,R_F16,R_F17,R_F18,R_F19,
+ R_F20,R_F21,R_F22,R_F23,R_F24,R_F25,R_F26,R_F27,R_F28,R_F29,
+ R_F30,R_F31);
+
+ tasmop = (A_ADDF,A_ADDG,A_ADDL,A_ADDQ,
+ A_ADDS,A_ADDT,A_AMASK,A_AND,A_BEQ,A_BGE,
+ A_BGT,A_BIC,A_BIS,A_BLBC,A_BLBS,A_BLE,
+ A_BLT,A_BNE,A_BR,A_BSR,A_CALL_PAL,A_CMOVEQ,
+ A_CMOVGE,A_CMOVGT,A_CMOVLBC,A_CMOVLBS,A_CMOVLE,A_CMOVLT,
+ A_CMOVNE,A_CMPBGE,A_CMPEQ,A_CMPGEQ,A_CMPGLE,A_CMPGLT,
+ A_CMPLE,A_CMPLT,A_CMPTEQ,A_CMPTLE,A_CMPTLT,A_CMPTUN,
+ A_CMPULE,A_CMPULT,A_CPYS,A_CPYSE,A_CPYSN,A_CTLZ,
+ A_CTPOP,A_CTTZ,A_CVTDG,A_CVTGD,A_CVTGF,A_CVTGQ,
+ A_CVTLQ,A_CVTQF,A_CVTQG,A_CVTQL,A_CVTQS,A_CVTQT,
+ A_CVTST,A_CVTTQ,A_CVTTS,A_DIVF,A_DIVG,A_DIVS,
+ A_DIVT,A_ECB,A_EQV,A_EXCB,A_EXTBL,A_EXTLH,
+ A_EXTLL,A_EXTQH,A_EXTQL,A_EXTWH,A_EXTWL,A_FBEQ,
+ A_FBGE,A_FBGT,A_FBLE,A_FBLT,A_FBNE,A_FCMOVEQ,
+ A_FCMOVGE,A_FCMOVGT,A_FCMOVLE,A_FCMOVLT,A_FCMOVNE,A_FETCH,
+ A_FETCH_M,A_FTOIS,A_FTOIT,A_IMPLVER,A_INSBL,A_INSLH,
+ A_INSLL,A_INSQH,A_INSQL,A_INSWH,A_INSWL,A_ITOFF,
+ A_ITOFS,A_ITOFT,A_JMP,A_JSR,A_JSR_COROUTINE,A_LDA,
+ A_LDAH,A_LDBU,A_LDWU,A_LDF,A_LDG,A_LDL,
+ A_LDL_L,A_LDQ,A_LDQ_L,A_LDQ_U,A_LDS,A_LDT,
+ A_MAXSB8,A_MAXSW4,A_MAXUB8,A_MAXUW4,A_MB,A_MF_FPCR,
+ A_MINSB8,A_MINSW4,A_MINUB8,A_MINUW4,A_MSKBL,A_MSKLH,
+ A_MSKLL,A_MSKQH,A_MSKQL,A_MSKWH,A_MSKWL,A_MT_FPCR,
+ A_MULF,A_MULG,A_MULL,A_MULQ,
+ A_MULS,A_MULT,A_ORNOT,A_PERR,A_PKLB,A_PKWB,
+ A_RC,A_RET,A_RPCC,A_RS,A_S4ADDL,A_S4ADDQ,
+ A_S4SUBL,A_S4SUBQ,A_S8ADDL,A_S8ADDQ,A_S8SUBL,A_S8SUBQ,
+ A_SEXTB,A_SEXTW,A_SLL,A_SQRTF,A_SQRTG,A_SQRTS,
+ A_SQRTT,A_SRA,A_SRL,A_STB,A_STF,A_STG,
+ A_STS,A_STL,A_STL_C,A_STQ,A_STQ_C,A_STQ_U,
+ A_STT,A_STW,A_SUBF,A_SUBG,A_SUBL,
+ A_SUBQ,A_SUBS,A_SUBT,A_TRAPB,A_UMULH,
+ A_UNPKBL,A_UNPKBW,A_WH64,A_WMB,A_XOR,A_ZAP,
+ A_ZAPNOT
+ { Psuedo code understood by the gnu assembler }
+ ,A_LDGP);
+
+ const
+ firstop = low(tasmop);
+ lastop = high(tasmop);
+
+ std_reg2str : array[tregister] of string[4] = (
+ '',
+ '','','','','','','','','','',
+ '','','','','','','','','','',
+ '','','','','','','','','','',
+ '','',
+ '','','','','','','','','','',
+ '','','','','','','','','','',
+ '','','','','','','','','','',
+ '',''
+ );
+
+
+ type
+ TAsmCond =
+ (
+ C_None,C_A,C_AE,C_B,C_BE,C_C,C_E,C_G,C_GE,C_L,C_LE,C_NA,C_NAE,
+ C_NB,C_NBE,C_NC,C_NE,C_NG,C_NGE,C_NL,C_NLE,C_NO,C_NP,C_NS,C_NZ,C_O,C_P,
+ C_PE,C_PO,C_S,C_Z
+ );
+
+ TRegisterset = Set of TRegister;
+
+ tregister64 = tregister;
+
+ Const
+ Firstreg = R_0;
+ LastReg = R_F31;
+
+
+{*****************************************************************************
+ Default generic sizes
+*****************************************************************************}
+
+ { Defines the default address size for a processor, }
+ OS_ADDR = OS_64;
+ { the natural int size for a processor, }
+ OS_INT = OS_64;
+ { the maximum float size for a processor, }
+ OS_FLOAT = OS_F80;
+ { the size of a vector register for a processor }
+ OS_VECTOR = OS_M64;
+
+ stack_pointer_reg = R_30;
+ frame_pointer_reg = R_15;
+ self_pointer_reg = R_16;
+ accumulator = R_0;
+ {the return_result_reg, is used inside the called function to store its return
+ value when that is a scalar value otherwise a pointer to the address of the
+ result is placed inside it}
+ return_result_reg = accumulator;
+
+ {the function_result_reg contains the function result after a call to a scalar
+ function othewise it contains a pointer to the returned result}
+ function_result_reg = accumulator;
+ fpu_result_reg = R_F0;
+ global_pointer = R_29;
+ return_pointer = R_26;
+ { it is used to pass the offset to the destructor helper routine }
+ vmt_offset_reg = R_1;
+
+ { low and high of the available maximum width integer general purpose }
+ { registers }
+ LoGPReg = R_0;
+ HiGPReg = R_31;
+
+ { low and high of every possible width general purpose register (same as
+ above on most architctures apart from the 80x86) }
+ LoReg = R_0;
+ HiReg = R_31;
+
+ maxfpuregs = 32;
+
+ max_operands = 4;
+
+ registers_saved_on_cdecl = [R_9..R_14,R_F2..R_F9];
+
+ maxvarregs = 6;
+ varregs : Array [1..maxvarregs] of Tregister =
+ (R_9,R_10,R_11,R_12,R_13,R_14);
+
+ maxfpuvarregs = 8;
+
+ { Registers which are defined as scratch and no need to save across
+ routine calls or in assembler blocks.
+ }
+ max_scratch_regs = 2;
+ scratch_regs : array[1..max_scratch_regs] of tregister = (R_1,R_2);
+
+{*****************************************************************************
+ GDB Information
+*****************************************************************************}
+
+ { Register indexes for stabs information, when some
+ parameters or variables are stored in registers.
+ }
+ stab_regindex : array[tregister] of shortint =
+ (0,
+ 0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,
+ 0,0,
+ 0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,
+ 0,0
+ );
+
+{*****************************************************************************
+ Flags
+*****************************************************************************}
+ type
+ { The Alpha doesn't have flags but some generic code depends on this type. }
+ TResFlags = (F_NO);
+
+
+ { reference record }
+ pparareference = ^tparareference;
+ tparareference = packed record
+ index : tregister;
+ offset : longint;
+ end;
+
+ trefoptions=(ref_none,ref_parafixup,ref_localfixup,ref_selffixup);
+
+ TReference = record
+ offset : aword;
+ symbol : tasmsymbol;
+ base : tregister;
+ { The index isn't used by the alpha port, but some generic code depends on it }
+ index : tregister;
+ is_immediate : boolean;
+ offsetfixup : word; {needed for inline}
+ options : trefoptions;
+ { the boundary to which the reference is surely aligned }
+ alignment : byte;
+ end;
+ PReference = ^TReference;
+
+ TLoc=(
+ LOC_INVALID, { added for tracking problems}
+ LOC_CONSTANT, { constant value }
+ LOC_JUMP, { boolean results only, jump to false or true label }
+ LOC_FLAGS, { boolean results only, flags are set }
+ LOC_CREFERENCE, { in memory constant value reference (cannot change) }
+ LOC_REFERENCE, { in memory value }
+ LOC_REGISTER, { in a processor register }
+ LOC_CREGISTER, { Constant register which shouldn't be modified }
+ LOC_FPUREGISTER, { FPU stack }
+ LOC_CFPUREGISTER, { if it is a FPU register variable on the fpu stack }
+ LOC_SSEREGISTER,
+ LOC_CSSEREGISTER,
+ LOC_CMMREGISTER,
+ LOC_MMREGISTER
+ );
+
+ { tparamlocation describes where a parameter for a procedure is stored.
+ References are given from the caller's point of view. The usual
+ TLocation isn't used, because contains a lot of unnessary fields.
+ }
+ tparalocation = packed record
+ size : TCGSize;
+ loc : TLoc;
+ sp_fixup : longint;
+ case TLoc of
+ LOC_REFERENCE : (reference : tparareference);
+ { segment in reference at the same place as in loc_register }
+ LOC_REGISTER,LOC_CREGISTER : (
+ case longint of
+ 1 : (register,register64.reghi : tregister);
+ { overlay a register64.reglo }
+ 2 : (register64.reglo : tregister);
+ { overlay a 64 Bit register type }
+ 3 : (reg64 : tregister64);
+ 4 : (register64 : tregister64);
+ );
+ end;
+
+ tlocation = packed record
+ loc : TLoc;
+ size : TCGSize;
+ case TLoc of
+ LOC_CONSTANT : (
+ case longint of
+ 1 : (value : AWord);
+ { can't do this, this layout depends on the host cpu. Use }
+ { lo(valueqword)/hi(valueqword) instead (JM) }
+ { 2 : (valuelow, valuehigh:AWord); }
+ { overlay a complete 64 Bit value }
+ 3 : (valueqword : qword);
+ );
+ LOC_CREFERENCE,
+ LOC_REFERENCE : (reference : treference);
+ { segment in reference at the same place as in loc_register }
+ LOC_REGISTER,LOC_CREGISTER : (
+ case longint of
+ 1 : (register,register64.reghi,segment : tregister);
+ { overlay a register64.reglo }
+ 2 : (register64.reglo : tregister);
+ { overlay a 64 Bit register type }
+ 3 : (reg64 : tregister64);
+ 4 : (register64 : tregister64);
+ );
+ end;
+
+{*****************************************************************************
+ Operands
+*****************************************************************************}
+
+
+ { Types of operand }
+ toptype=(top_none,top_reg,top_ref,top_const,top_symbol);
+
+ toper=record
+ ot : longint;
+ case typ : toptype of
+ top_none : ();
+ top_reg : (reg:tregister);
+ top_ref : (ref:preference);
+ top_const : (val:longint);
+ top_symbol : (sym:tasmsymbol;symofs:longint);
+ end;
+
+ const
+ { Registers which must be saved when calling a routine declared as
+ cppdecl, cdecl, stdcall, safecall, palmossyscall. The registers
+ saved should be the ones as defined in the target ABI and / or GCC.
+
+ This value can be deduced from the CALLED_USED_REGISTERS array in the
+ GCC source.
+ }
+ std_saved_registers = [];
+ { Required parameter alignment when calling a routine declared as
+ stdcall and cdecl. The alignment value should be the one defined
+ by GCC or the target ABI.
+
+ The value of this constant is equal to the constant
+ PARM_BOUNDARY / BITS_PER_UNIT in the GCC source.
+ }
+ std_param_align = 8;
+
+ { offsets for the integer and floating point registers }
+ INT_REG = 0;
+ FLOAT_REG = 32;
+
+ { operator qualifiers }
+ OQ_CHOPPED_ROUNDING = $01; { /C }
+ OQ_ROUNDING_MODE_DYNAMIC = $02; { /D }
+ OQ_ROUND_TOWARD_MINUS_INFINITY = $04; { /M }
+ OQ_INEXACT_RESULT_ENABLE = $08; { /I }
+ OQ_SOFTWARE_COMPLETION_ENABLE = $10; { /S }
+ OQ_FLOATING_UNDERFLOW_ENABLE = $20; { /U }
+ OQ_INTEGER_OVERFLOW_ENABLE = $40; { /V }
+
+
+{*****************************************************************************
+ Opcode propeties (needed for optimizer)
+*****************************************************************************}
+
+{$ifndef NOOPT}
+Type
+{What an instruction can change}
+ TInsChange = (Ch_None);
+{$endif}
+
+
+{ resets all values of ref to defaults }
+procedure reset_reference(var ref : treference);
+{ set mostly used values of a new reference }
+function new_reference(base : tregister;offset : longint) : preference;
+function newreference(const r : treference) : preference;
+procedure disposereference(var r : preference);
+
+function reg2str(r : tregister) : string;
+
+{*****************************************************************************
+ Init/Done
+*****************************************************************************}
+
+ procedure InitCpu;
+ procedure DoneCpu;
+
+implementation
+
+uses
+ verbose;
+
+function reg2str(r : tregister) : string;
+
+ begin
+ if r in [R_0..R_31] then
+ reg2str:='R'+tostr(longint(r)-longint(R_0))
+ else if r in [R_F0..R_F31] then
+ reg2str:='F'+tostr(longint(r)-longint(R_F0))
+ else internalerror(38991);
+ end;
+
+procedure reset_reference(var ref : treference);
+begin
+ FillChar(ref,sizeof(treference),0);
+end;
+
+
+function new_reference(base : tregister;offset : longint) : preference;
+var
+ r : preference;
+begin
+ new(r);
+ FillChar(r^,sizeof(treference),0);
+ r^.offset:=offset;
+ r^.alignment:=8;
+ new_reference:=r;
+end;
+
+function newreference(const r : treference) : preference;
+
+var
+ p : preference;
+begin
+ new(p);
+ p^:=r;
+ newreference:=p;
+end;
+
+procedure disposereference(var r : preference);
+
+begin
+ dispose(r);
+ r:=Nil;
+end;
+
+{*****************************************************************************
+ Init/Done
+*****************************************************************************}
+
+ procedure InitCpu;
+ begin
+ end;
+
+ procedure DoneCpu;
+ begin
+ end;
+
+end.
diff --git a/closures/compiler/alpha/cpuinfo.pas b/closures/compiler/alpha/cpuinfo.pas
new file mode 100644
index 0000000000..4779b4a73a
--- /dev/null
+++ b/closures/compiler/alpha/cpuinfo.pas
@@ -0,0 +1,68 @@
+{
+ This file is part of the Free Pascal run time library.
+ Copyright (c) 1998-2000 by the Free Pascal development team
+
+ Basic Processor information about the Alpha
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+{
+ Basic Processor information about the Alpha
+}
+Unit CPUInfo;
+
+{$i fpcdefs.inc}
+
+Interface
+
+Type
+ { Natural integer register type and size for the target machine }
+{$ifdef FPC}
+ AWord = Qword;
+{$else FPC}
+ AWord = Longint;
+{$endif FPC}
+ PAWord = ^AWord;
+
+ { This must be an ordinal type with the same size as a pointer
+ Note: Must be unsigned! Otherwise, ugly code like
+ pointer(-1) will result in a pointer with the value
+ $fffffffffffffff on a 32bit machine if the compiler uses
+ int64 constants internally (JM) }
+ TConstPtrUInt = qword;
+
+ bestreal = extended;
+ ts32real = single;
+ ts64real = double;
+ ts80real = extended;
+ ts64comp = extended;
+
+ pbestreal=^bestreal;
+
+ { possible supported processors for this target }
+ tcputype =
+ (cpu_none,
+ ClassEV7,
+ ClassEV8
+ );
+
+Const
+ { Size of native extended type }
+ extended_size = 16;
+ {# Size of a pointer }
+ aint_size = 8;
+ {# Size of a multimedia register }
+ mmreg_size = 8;
+
+ { target cpu string (used by compiler options) }
+ target_cpu_string = 'alpha';
+
+Implementation
+
+end.
diff --git a/closures/compiler/alpha/cpunode.pas b/closures/compiler/alpha/cpunode.pas
new file mode 100644
index 0000000000..c62bc9c303
--- /dev/null
+++ b/closures/compiler/alpha/cpunode.pas
@@ -0,0 +1,54 @@
+{
+ Copyright (c) 2000-2002 by Florian Klaempfl
+
+ Imports the Alpha code generator
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+{
+ This unit imports the Alpha code generator.
+}
+unit cpunode;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ implementation
+
+ uses
+ { generic nodes }
+ ncgbas,ncgld,ncgflw,ncgcnv,ncgmem,ncgcon,ncgcal,ncgset,ncginl
+ { to be able to only parts of the generic code,
+ the processor specific nodes must be included
+ after the generic one (FK)
+ }
+// naxpadd,
+// naxpcal,
+// naxpcon,
+// naxpflw,
+// naxpmem,
+// naxpset,
+// naxpinl,
+// nppcopt,
+ { this not really a node }
+// naxpobj,
+// naxpmat,
+// naxpcnv
+ ;
+
+end.
diff --git a/closures/compiler/alpha/cpupara.pas b/closures/compiler/alpha/cpupara.pas
new file mode 100644
index 0000000000..fe7de008a8
--- /dev/null
+++ b/closures/compiler/alpha/cpupara.pas
@@ -0,0 +1,290 @@
+{
+ Copyright (c) 2002 by Florian Klaempfl
+
+ Alpha specific calling conventions
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ ****************************************************************************
+}
+{ Alpha specific calling conventions are handled by this unit
+}
+unit cpupara;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ cpubase,
+ symconst,symbase,symtype,symdef,paramgr;
+
+ type
+ talphaparamanager = class(tparamanager)
+ function getintparaloc(nr : longint) : tparalocation;override;
+ procedure create_param_loc_info(p : tabstractprocdef);override;
+ function getfuncretparaloc(p : tabstractprocdef) : tparalocation;override;
+ end;
+
+ implementation
+
+ uses
+ verbose,
+ globtype,
+ cpuinfo,cginfo,cgbase,
+ defbase;
+
+ function talphaparamanager.getintparaloc(nr : longint) : tparalocation;
+
+ begin
+ fillchar(result,sizeof(tparalocation),0);
+ if nr<1 then
+ internalerror(2002070801)
+ else if nr<=8 then
+ begin
+ result.loc:=LOC_REGISTER;
+ result.register:=tregister(longint(R_2)+nr);
+ end
+ else
+ begin
+ result.loc:=LOC_REFERENCE;
+ result.reference.index:=stack_pointer_reg;
+ result.reference.offset:=(nr-8)*4;
+ end;
+ end;
+
+ function getparaloc(p : tdef) : tloc;
+
+ begin
+ { Later, the LOC_REFERENCE is in most cases changed into LOC_REGISTER
+ if push_addr_param for the def is true
+ }
+ case p.typ of
+ orddef:
+ getparaloc:=LOC_REGISTER;
+ floatdef:
+ getparaloc:=LOC_FPUREGISTER;
+ enumdef:
+ getparaloc:=LOC_REGISTER;
+ pointerdef:
+ getparaloc:=LOC_REGISTER;
+ formaldef:
+ getparaloc:=LOC_REGISTER;
+ classrefdef:
+ getparaloc:=LOC_REGISTER;
+ recorddef:
+ getparaloc:=LOC_REFERENCE;
+ objectdef:
+ if is_object(p) then
+ getparaloc:=LOC_REFERENCE
+ else
+ getparaloc:=LOC_REGISTER;
+ stringdef:
+ if is_shortstring(p) or is_longstring(p) then
+ getparaloc:=LOC_REFERENCE
+ else
+ getparaloc:=LOC_REGISTER;
+ procvardef:
+ if (po_methodpointer in tprocvardef(p).procoptions) then
+ getparaloc:=LOC_REFERENCE
+ else
+ getparaloc:=LOC_REGISTER;
+ filedef:
+ getparaloc:=LOC_REGISTER;
+ arraydef:
+ getparaloc:=LOC_REFERENCE;
+ setdef:
+ if is_smallset(p) then
+ getparaloc:=LOC_REGISTER
+ else
+ getparaloc:=LOC_REFERENCE;
+ variantdef:
+ getparaloc:=LOC_REFERENCE;
+ { avoid problems with errornous definitions }
+ errordef:
+ getparaloc:=LOC_REGISTER;
+ else
+ internalerror(2002071001);
+ end;
+ end;
+
+ procedure talphaparamanager.create_param_loc_info(p : tabstractprocdef);
+
+ var
+ nextintreg,nextfloatreg,nextmmreg : tregister;
+ stack_offset : aword;
+ hp : tparaitem;
+ loc : tloc;
+ is_64bit: boolean;
+
+ begin
+ nextintreg:=R_3;
+ nextfloatreg:=R_F1;
+ // nextmmreg:=R_M1;
+ stack_offset:=0;
+ { pointer for structured results ? }
+ if not is_void(p.returndef) then
+ begin
+ if not(ret_in_reg(p.returndef)) then
+ inc(nextintreg);
+ end;
+
+ { frame pointer for nested procedures? }
+ { inc(nextintreg); }
+ { constructor? }
+ { destructor? }
+ hp:=tparaitem(p.para.last);
+ while assigned(hp) do
+ begin
+ loc:=getparaloc(hp.paratype.def);
+ hp.paraloc.sp_fixup:=0;
+ case loc of
+ LOC_REGISTER:
+ begin
+ hp.paraloc.size := def_cgsize(hp.paratype.def);
+ { for things like formaldef }
+ if hp.paraloc.size = OS_NO then
+ hp.paraloc.size := OS_ADDR;
+ is_64bit := hp.paraloc.size in [OS_64,OS_S64];
+ if nextintreg<=tregister(ord(R_10)-ord(is_64bit)) then
+ begin
+ hp.paraloc.loc:=LOC_REGISTER;
+ hp.paraloc.register64.reglo:=nextintreg;
+ inc(nextintreg);
+ if is_64bit then
+ begin
+ hp.paraloc.register64.reghi:=nextintreg;
+ inc(nextintreg);
+ end;
+ end
+ else
+ begin
+ nextintreg := R_11;
+ hp.paraloc.loc:=LOC_REFERENCE;
+ hp.paraloc.reference.index:=stack_pointer_reg;
+ hp.paraloc.reference.offset:=stack_offset;
+ if not is_64bit then
+ inc(stack_offset,4)
+ else
+ inc(stack_offset,8);
+ end;
+ end;
+ LOC_FPUREGISTER:
+ begin
+ if hp.paratyp in [vs_var,vs_out] then
+ begin
+ if nextintreg<=R_10 then
+ begin
+ hp.paraloc.size:=OS_ADDR;
+ hp.paraloc.loc:=LOC_REGISTER;
+ hp.paraloc.register:=nextintreg;
+ inc(nextintreg);
+ end
+ else
+ begin
+ {!!!!!!!}
+ hp.paraloc.size:=def_cgsize(hp.paratype.def);
+ internalerror(2002071006);
+ end;
+ end
+ else if nextfloatreg<=R_F10 then
+ begin
+ hp.paraloc.size:=def_cgsize(hp.paratype.def);
+ hp.paraloc.loc:=LOC_FPUREGISTER;
+ hp.paraloc.register:=nextfloatreg;
+ inc(nextfloatreg);
+ end
+ else
+ begin
+ {!!!!!!!}
+ hp.paraloc.size:=def_cgsize(hp.paratype.def);
+ internalerror(2002071004);
+ end;
+ end;
+ LOC_REFERENCE:
+ begin
+ hp.paraloc.size:=OS_ADDR;
+ if push_addr_param(hp.paratype.def,p.proccalloption in [pocall_cdecl,pocall_cppdecl]) or (hp.paratyp in [vs_var,vs_out]) then
+ begin
+ if nextintreg<=R_10 then
+ begin
+ hp.paraloc.loc:=LOC_REGISTER;
+ hp.paraloc.register:=nextintreg;
+ inc(nextintreg);
+ end
+ else
+ begin
+ hp.paraloc.loc:=LOC_REFERENCE;
+ hp.paraloc.reference.index:=stack_pointer_reg;
+ hp.paraloc.reference.offset:=stack_offset;
+ inc(stack_offset,4);
+ end;
+ end
+ else
+ begin
+ hp.paraloc.loc:=LOC_REFERENCE;
+ hp.paraloc.reference.index:=stack_pointer_reg;
+ hp.paraloc.reference.offset:=stack_offset;
+ inc(stack_offset,hp.paratype.def.size);
+ end;
+ end;
+ else
+ internalerror(2002071002);
+ end;
+ hp:=tparaitem(hp.previous);
+ end;
+ end;
+
+ function talphaparamanager.getfuncretparaloc(p : tabstractprocdef) : tparalocation;
+ begin
+ case p.returndef.typ of
+ orddef,
+ enumdef:
+ begin
+ getfuncretparaloc.loc:=LOC_REGISTER;
+ getfuncretparaloc.register:=R_3;
+ getfuncretparaloc.size:=def_cgsize(p.returndef);
+ if getfuncretparaloc.size in [OS_S64,OS_64] then
+ getfuncretparaloc.register64.reghi:=R_4;
+ end;
+ floatdef:
+ begin
+ getfuncretparaloc.loc:=LOC_FPUREGISTER;
+ getfuncretparaloc.register:=R_F1;
+ getfuncretparaloc.size:=def_cgsize(p.returndef);
+ end;
+ pointerdef,
+ formaldef,
+ classrefdef,
+ recorddef,
+ objectdef,
+ stringdef,
+ procvardef,
+ filedef,
+ arraydef,
+ errordef:
+ begin
+ getfuncretparaloc.loc:=LOC_REGISTER;
+ getfuncretparaloc.register:=R_3;
+ getfuncretparaloc.size:=OS_ADDR;
+ end;
+ else
+ internalerror(2002090903);
+ end;
+ end;
+
+
+begin
+ paramanager:=talphaparamanager.create;
+end.
diff --git a/closures/compiler/alpha/cpupi.pas b/closures/compiler/alpha/cpupi.pas
new file mode 100644
index 0000000000..6b1470cde0
--- /dev/null
+++ b/closures/compiler/alpha/cpupi.pas
@@ -0,0 +1,43 @@
+{
+ Copyright (c) 2002 by Florian Klaempfl
+
+ This unit contains the CPU specific part of tprocinfo
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+{
+ This unit contains the CPU specific part of tprocinfo.
+}
+unit cpupi;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ cgbase;
+
+ type
+ talphaprocinfo = class(tprocinfo)
+ end;
+
+
+ implementation
+
+begin
+ cprocinfo:=talphaprocinfo;
+end.
diff --git a/closures/compiler/alpha/cputarg.pas b/closures/compiler/alpha/cputarg.pas
new file mode 100644
index 0000000000..f7e38332c7
--- /dev/null
+++ b/closures/compiler/alpha/cputarg.pas
@@ -0,0 +1,51 @@
+{
+ Copyright (c) 2001-2002 by Peter Vreman
+
+ Includes the powerpc dependent target units
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit cputarg;
+
+{$i fpcdefs.inc}
+
+interface
+
+
+implementation
+
+ uses
+ systems { prevent a syntax error when nothing is included }
+
+{**************************************
+ Targets
+**************************************}
+
+ {$ifndef NOTARGETLINUX}
+ ,t_linux
+ {$endif}
+
+{**************************************
+ Assemblers
+**************************************}
+
+ {$ifndef NOAGAXPGAS}
+ ,agaxpgas
+ {$endif}
+ ;
+
+end.
diff --git a/closures/compiler/alpha/radirect.pas b/closures/compiler/alpha/radirect.pas
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/closures/compiler/alpha/radirect.pas
diff --git a/closures/compiler/alpha/rasm.pas b/closures/compiler/alpha/rasm.pas
new file mode 100644
index 0000000000..b157752923
--- /dev/null
+++ b/closures/compiler/alpha/rasm.pas
@@ -0,0 +1,65 @@
+{
+ Copyright (c) 1998-2002 by The Free Pascal Team
+
+ This unit does the parsing process for the inline assembler
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+{
+ This unit does the parsing process for the inline assembler.
+}
+Unit Rasm;
+
+{$i fpcdefs.inc}
+
+Interface
+
+uses
+ node;
+
+ {
+ This routine is called to parse the instructions in assembler
+ blocks. It returns a complete list of directive and instructions
+ }
+ function assemble: tnode;
+
+
+Implementation
+
+ uses
+ { common }
+ cutils,cclasses,
+ { global }
+ globtype,globals,verbose,
+ systems,
+ { aasm }
+ cpubase,aasmbase,aasmtai,aasmdata,aasmcpu,
+ { symtable }
+ symconst,symbase,symtype,symsym,symtable,
+ { pass 1 }
+ nbas,
+ { parser }
+ scanner
+ // ,rautils
+ ;
+
+ function assemble : tnode;
+ begin
+ end;
+
+Begin
+end.
diff --git a/closures/compiler/alpha/rgcpu.pas b/closures/compiler/alpha/rgcpu.pas
new file mode 100644
index 0000000000..94bcc197a2
--- /dev/null
+++ b/closures/compiler/alpha/rgcpu.pas
@@ -0,0 +1,69 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit implements the powerpc specific class for the register
+ allocator
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+
+unit rgcpu;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ aasmbase,aasmtai,aasmdata,
+ cpubase,
+ rgobj;
+
+ type
+ trgcpu = class(trgobj)
+ function getcpuregisterint(list: TAsmList; reg: tregister): tregister; override;
+ procedure ungetregisterint(list: TAsmList; reg: tregister); override;
+ end;
+
+ implementation
+
+ uses
+ cgobj;
+
+ function trgcpu.getcpuregisterint(list: TAsmList; reg: tregister): tregister;
+
+ begin
+ if reg = R_0 then
+ begin
+ cg.a_reg_alloc(list,reg);
+ result := reg;
+ end
+ else result := inherited getcpuregisterint(list,reg);
+ end;
+
+
+ procedure trgcpu.ungetregisterint(list: TAsmList; reg: tregister);
+
+ begin
+ if reg = R_0 then
+ cg.a_reg_dealloc(list,reg)
+ else
+ inherited ungetregisterint(list,reg);
+ end;
+
+initialization
+ rg := trgcpu.create;
+end.
diff --git a/closures/compiler/alpha/tgcpu.pas b/closures/compiler/alpha/tgcpu.pas
new file mode 100644
index 0000000000..90c4ac5175
--- /dev/null
+++ b/closures/compiler/alpha/tgcpu.pas
@@ -0,0 +1,42 @@
+{
+ Copyright (C) 1998-2000 by Florian Klaempfl
+
+ This unit handles the temporary variables stuff for Alpha
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+{
+ This unit handles the temporary variables stuff for Alpha.
+}
+unit tgcpu;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ tgobj;
+
+ type
+ ttgalpha = class(ttgobj)
+ end;
+
+implementation
+
+begin
+ tg:=ttgalpha.create;
+end.
diff --git a/closures/compiler/aopt.pas b/closures/compiler/aopt.pas
new file mode 100644
index 0000000000..8f39aa2a25
--- /dev/null
+++ b/closures/compiler/aopt.pas
@@ -0,0 +1,277 @@
+{
+ Copyright (c) 1998-2004 by Jonas Maebe, member of the Free Pascal
+ Development Team
+
+ This unit contains the interface routines between the code generator
+ and the optimizer.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+Unit aopt;
+
+{$i fpcdefs.inc}
+
+ Interface
+
+ Uses
+ aasmbase,aasmtai,aasmdata,aasmcpu,
+ aoptobj;
+
+ Type
+ TAsmOptimizer = class(TAoptObj)
+
+ { _AsmL is the PAasmOutpout list that has to be optimized }
+ Constructor create(_AsmL: TAsmList); virtual; reintroduce;
+
+ { call the necessary optimizer procedures }
+ Procedure Optimize;
+ Destructor destroy;override;
+
+ private
+ procedure FindLoHiLabels;
+ Procedure BuildLabelTableAndFixRegAlloc;
+ procedure clear;
+ procedure pass_1;
+ End;
+ TAsmOptimizerClass = class of TAsmOptimizer;
+
+ var
+ casmoptimizer : TAsmOptimizerClass;
+
+ procedure Optimize(AsmL:TAsmList);
+
+ Implementation
+
+ uses
+ globtype, globals,
+ verbose,
+ aoptda,aoptcpu,aoptcpud;
+
+ Constructor TAsmOptimizer.create(_AsmL: TAsmList);
+ Begin
+ inherited create(_asml,nil,nil,nil);
+ {setup labeltable, always necessary}
+ New(LabelInfo);
+ End;
+
+ procedure TAsmOptimizer.FindLoHiLabels;
+ { Walks through the paasmlist to find the lowest and highest label number. }
+ { Returns the last Pai object of the current block }
+ Var LabelFound: Boolean;
+ p: tai;
+ Begin
+ LabelInfo^.LowLabel := High(longint);
+ LabelInfo^.HighLabel := 0;
+ LabelInfo^.LabelDif := 0;
+ LabelInfo^.LabelTable:=nil;
+ LabelFound := False;
+ P := BlockStart;
+ With LabelInfo^ Do
+ Begin
+ While Assigned(P) And
+ ((P.typ <> Ait_Marker) Or
+ (tai_Marker(P).Kind <> mark_AsmBlockStart)) Do
+ Begin
+ If (p.typ = ait_label) and
+ (tai_Label(p).labsym.labeltype=alt_jump) and
+ (tai_Label(p).labsym.is_used) Then
+ Begin
+ LabelFound := True;
+ If (tai_Label(p).labsym.labelnr < LowLabel) Then
+ LowLabel := tai_Label(p).labsym.labelnr;
+ If (tai_Label(p).labsym.labelnr > HighLabel) Then
+ HighLabel := tai_Label(p).labsym.labelnr
+ End;
+ GetNextInstruction(p, p)
+ End;
+ blockend:=p;
+ If LabelFound
+ Then LabelDif := HighLabel-LowLabel+1
+ Else LabelDif := 0
+ End
+ End;
+
+ Procedure TAsmOptimizer.BuildLabelTableAndFixRegAlloc;
+ { Builds a table with the locations of the labels in the TAsmList. }
+ { Also fixes some RegDeallocs like "# %eax released; push (%eax)" }
+ Var p{, hp1, hp2}: tai;
+ {UsedRegs: TRegSet;}
+ LabelIdx : longint;
+ Begin
+ {UsedRegs := [];}
+ With LabelInfo^ Do
+ If (LabelDif <> 0) Then
+ Begin
+ GetMem(LabelTable, LabelDif*SizeOf(TLabelTableItem));
+ FillChar(LabelTable^, LabelDif*SizeOf(TLabelTableItem), 0);
+ p := BlockStart;
+ While (P <> BlockEnd) Do
+ Begin
+ Case p.typ Of
+ ait_Label:
+ begin
+ If tai_label(p).labsym.is_used and
+ (tai_Label(p).labsym.labeltype=alt_jump) then
+ begin
+ LabelIdx:=tai_label(p).labsym.labelnr-LowLabel;
+ if LabelIdx>int64(LabelDif) then
+ internalerror(200604202);
+ LabelTable^[LabelIdx].PaiObj := p;
+ end;
+ end;
+ ait_regAlloc:
+ begin
+ {!!!!!!!!!
+ if tai_regalloc(p).ratype=ra_alloc then
+ Begin
+ If Not(tai_regalloc(p).Reg in UsedRegs) Then
+ UsedRegs := UsedRegs + [tai_regalloc(p).Reg]
+ Else
+ Begin
+ hp1 := p;
+ hp2 := nil;
+ While GetLastInstruction(hp1, hp1) And
+ Not(RegInInstruction(tai_regalloc(p).Reg, hp1)) Do
+ hp2:=hp1;
+ If hp2<>nil Then
+ Begin
+ hp1:=tai_regalloc.DeAlloc(tai_regalloc(p).Reg,hp2);
+ InsertLLItem(tai(hp2.previous), hp2, hp1);
+ End;
+ End;
+ End
+ else
+ Begin
+ UsedRegs := UsedRegs - [tai_regalloc(p).Reg];
+ hp1 := p;
+ hp2 := nil;
+ While Not(FindRegAlloc(tai_regalloc(p).Reg, tai(hp1.Next))) And
+ GetNextInstruction(hp1, hp1) And
+ RegInInstruction(tai_regalloc(p).Reg, hp1) Do
+ hp2 := hp1;
+ If hp2 <> nil Then
+ Begin
+ hp1 := tai(p.previous);
+ AsmL.Remove(p);
+ InsertLLItem(hp2, tai(hp2.Next), p);
+ p := hp1;
+ End
+ End
+ };
+ End
+ End;
+ P := tai(p.Next);
+ While Assigned(p) and
+ (p <> blockend) and
+ (p.typ in (SkipInstr - [ait_regalloc])) Do
+ P := tai(P.Next)
+ End;
+ End
+ End;
+
+ procedure tasmoptimizer.clear;
+ begin
+ if assigned(LabelInfo^.labeltable) then
+ begin
+ freemem(LabelInfo^.labeltable);
+ LabelInfo^.labeltable := nil;
+ end;
+ LabelInfo^.labeldif:=0;
+ LabelInfo^.lowlabel:=high(longint);
+ LabelInfo^.highlabel:=0;
+ end;
+
+ procedure tasmoptimizer.pass_1;
+ begin
+ findlohilabels;
+ BuildLabelTableAndFixRegAlloc;
+ end;
+
+
+ Procedure TAsmOptimizer.Optimize;
+ Var
+ HP: tai;
+ pass: longint;
+ Begin
+ pass:=0;
+ BlockStart := tai(AsmL.First);
+ pass_1;
+ While Assigned(BlockStart) Do
+ Begin
+ if pass = 0 then
+ PrePeepHoleOpts;
+ { Peephole optimizations }
+ PeepHoleOptPass1;
+ { Only perform them twice in the first pass }
+ if pass = 0 then
+ PeepHoleOptPass1;
+ If (cs_opt_asmcse in current_settings.optimizerswitches) Then
+ Begin
+// DFA:=TAOptDFACpu.Create(AsmL,BlockStart,BlockEnd,LabelInfo);
+ { data flow analyzer }
+// DFA.DoDFA;
+ { common subexpression elimination }
+ { CSE;}
+ End;
+ { more peephole optimizations }
+ PeepHoleOptPass2;
+ { if pass = last_pass then }
+ PostPeepHoleOpts;
+ { free memory }
+ clear;
+ { continue where we left off, BlockEnd is either the start of an }
+ { assembler block or nil}
+ BlockStart := BlockEnd;
+ While Assigned(BlockStart) And
+ (BlockStart.typ = ait_Marker) And
+ (tai_Marker(BlockStart).Kind = mark_AsmBlockStart) Do
+ Begin
+ { we stopped at an assembler block, so skip it }
+ While GetNextInstruction(BlockStart, BlockStart) And
+ ((BlockStart.Typ <> Ait_Marker) Or
+ (tai_Marker(Blockstart).Kind <> mark_AsmBlockEnd)) Do;
+ { blockstart now contains a tai_marker(mark_AsmBlockEnd) }
+ If GetNextInstruction(BlockStart, HP) And
+ ((HP.typ <> ait_Marker) Or
+ (Tai_Marker(HP).Kind <> mark_AsmBlockStart)) Then
+ { There is no assembler block anymore after the current one, so }
+ { optimize the next block of "normal" instructions }
+ pass_1
+ { Otherwise, skip the next assembler block }
+ else
+ blockStart := hp;
+ End
+ End;
+ End;
+
+ Destructor TAsmOptimizer.Destroy;
+ Begin
+ Dispose(LabelInfo)
+ End;
+
+
+ procedure Optimize(AsmL:TAsmList);
+ var
+ p : TAsmOptimizer;
+ begin
+ p:=casmoptimizer.Create(AsmL);
+ p.Optimize;
+ p.free
+ end;
+
+
+end.
diff --git a/closures/compiler/aoptbase.pas b/closures/compiler/aoptbase.pas
new file mode 100644
index 0000000000..9c461c76c9
--- /dev/null
+++ b/closures/compiler/aoptbase.pas
@@ -0,0 +1,242 @@
+{
+ Copyright (c) 1998-2002 by Jonas Maebe, member of the Free Pascal
+ Development Team
+
+ This unit contains the base of all optimizer related objects
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit aoptbase;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ aasmbase,aasmcpu,aasmtai,aasmdata,
+ cpubase,
+ cgbase,
+ cgutils;
+
+ Type
+ { the number of tai objects processed by an optimizer object since the last
+ time a register was modified }
+ { size at each dimension depends on the registers of this type }
+ TInstrSinceLastMod = Array[tregistertype] of pbyte;
+
+ { the TAopBase object implements the basic methods that most other }
+ { assembler optimizer objects require }
+ Type
+ TAoptBase = class
+ { processor independent methods }
+
+ constructor create; virtual;
+ destructor destroy;override;
+ { returns true if register Reg is used by instruction p1 }
+ Function RegInInstruction(Reg: TRegister; p1: tai): Boolean;
+ { returns true if register Reg occurs in operand op }
+ Function RegInOp(Reg: TRegister; const op: toper): Boolean;
+ { returns true if register Reg is used in the reference Ref }
+ Function RegInRef(Reg: TRegister; Const Ref: TReference): Boolean;
+
+ { returns true if the references are completely equal }
+ {Function RefsEqual(Const R1, R2: TReference): Boolean;}
+
+ { gets the next tai object after current that contains info relevant }
+ { to the optimizer in p1. If there is none, it returns false and }
+ { sets p1 to nil }
+ Function GetNextInstruction(Current: tai; Var Next: tai): Boolean;
+ { gets the previous tai object after current that contains info }
+ { relevant to the optimizer in last. If there is none, it retuns }
+ { false and sets last to nil }
+ Function GetLastInstruction(Current: tai; Var Last: tai): Boolean;
+
+
+ { processor dependent methods }
+
+ { returns the maximum width component of Reg. Only has to be }
+ { overridden for the 80x86 (afaik) }
+ Function RegMaxSize(Reg: TRegister): TRegister; Virtual;
+ { returns true if Reg1 and Reg2 are of the samae width. Only has to }
+ { overridden for the 80x86 (afaik) }
+ Function RegsSameSize(Reg1, Reg2: TRegister): Boolean; Virtual;
+ { returns whether P is a load instruction (load contents from a }
+ { memory location or (register) variable into a register) }
+ Function IsLoadMemReg(p: tai): Boolean; Virtual; Abstract;
+ { returns whether P is a load constant instruction (load a constant }
+ { into a register) }
+ Function IsLoadConstReg(p: tai): Boolean; Virtual; Abstract;
+ { returns whether P is a store instruction (store contents from a }
+ { register to a memory location or to a (register) variable) }
+ Function IsStoreRegMem(p: tai): Boolean; Virtual; Abstract;
+
+ { create a paicpu Object that loads the contents of reg1 into reg2 }
+ Function a_load_reg_reg(reg1, reg2: TRegister): taicpu; Virtual; Abstract;
+
+ end;
+
+
+ implementation
+
+ uses
+ globtype,globals, aoptcpub;
+
+ constructor taoptbase.create;
+ begin
+ inherited create;
+ end;
+
+
+ destructor taoptbase.destroy;
+ begin
+ inherited destroy;
+ end;
+
+
+ Function TAOptBase.RegInInstruction(Reg: TRegister; p1: tai): Boolean;
+ Var Count: AWord;
+ TmpResult: Boolean;
+ Begin
+ TmpResult := False;
+ Count := 0;
+ If (p1.typ = ait_instruction) Then
+ Repeat
+ TmpResult := RegInOp(Reg, PInstr(p1)^.oper[Count]^);
+ Inc(Count)
+ Until (Count = MaxOps) or TmpResult;
+ RegInInstruction := TmpResult
+ End;
+
+
+ Function TAOptBase.RegInOp(Reg: TRegister; const op: toper): Boolean;
+ Begin
+ Case op.typ Of
+ Top_Reg: RegInOp := Reg = op.reg;
+ Top_Ref: RegInOp := RegInRef(Reg, op.ref^)
+ Else RegInOp := False
+ End
+ End;
+
+
+ Function TAOptBase.RegInRef(Reg: TRegister; Const Ref: TReference): Boolean;
+ Begin
+ Reg := RegMaxSize(Reg);
+ RegInRef := (Ref.Base = Reg)
+ {$ifdef RefsHaveIndexReg}
+ Or (Ref.Index = Reg)
+ {$endif RefsHaveIndexReg}
+ End;
+
+ function labelCanBeSkipped(p: tai_label): boolean;
+ begin
+ labelCanBeSkipped := not(p.labsym.is_used) or (p.labsym.labeltype<>alt_jump);
+ end;
+
+ Function TAOptBase.GetNextInstruction(Current: tai; Var Next: tai): Boolean;
+ Begin
+ Repeat
+ Current := tai(Current.Next);
+ While Assigned(Current) And
+ ((Current.typ In SkipInstr) or
+{$ifdef SPARC}
+ ((Current.typ=ait_instruction) and
+ (taicpu(Current).opcode=A_NOP)
+ ) or
+{$endif SPARC}
+ ((Current.typ = ait_label) And
+ labelCanBeSkipped(Tai_Label(Current)))) Do
+ Current := tai(Current.Next);
+ If Assigned(Current) And
+ (Current.typ = ait_Marker) And
+ (Tai_Marker(Current).Kind = mark_NoPropInfoStart) Then
+ Begin
+ While Assigned(Current) And
+ ((Current.typ <> ait_Marker) Or
+ (Tai_Marker(Current).Kind <> mark_NoPropInfoEnd)) Do
+ Current := Tai(Current.Next);
+ End;
+ Until Not(Assigned(Current)) Or
+ (Current.typ <> ait_Marker) Or
+ (Tai_Marker(Current).Kind <> mark_NoPropInfoEnd);
+ Next := Current;
+ If Assigned(Current) And
+ Not((Current.typ In SkipInstr) or
+ ((Current.typ = ait_label) And
+ labelCanBeSkipped(Tai_Label(Current))))
+ Then GetNextInstruction := True
+ Else
+ Begin
+ Next := Nil;
+ GetNextInstruction := False;
+ End;
+ End;
+
+ Function TAOptBase.GetLastInstruction(Current: tai; Var Last: tai): Boolean;
+ Begin
+ Repeat
+ Current := Tai(Current.previous);
+ While Assigned(Current) And
+ (((Current.typ = ait_Marker) And
+ Not(Tai_Marker(Current).Kind in [mark_AsmBlockEnd,mark_NoPropInfoEnd])) or
+ (Current.typ In SkipInstr) or
+ ((Current.typ = ait_label) And
+ labelCanBeSkipped(Tai_Label(Current)))) Do
+ Current := Tai(Current.previous);
+ If Assigned(Current) And
+ (Current.typ = ait_Marker) And
+ (Tai_Marker(Current).Kind = mark_NoPropInfoEnd) Then
+ Begin
+ While Assigned(Current) And
+ ((Current.typ <> ait_Marker) Or
+ (Tai_Marker(Current).Kind <> mark_NoPropInfoStart)) Do
+ Current := Tai(Current.previous);
+ End;
+ Until Not(Assigned(Current)) Or
+ (Current.typ <> ait_Marker) Or
+ (Tai_Marker(Current).Kind <> mark_NoPropInfoStart);
+ If Not(Assigned(Current)) or
+ (Current.typ In SkipInstr) or
+ ((Current.typ = ait_label) And
+ labelCanBeSkipped(Tai_Label(Current))) or
+ ((Current.typ = ait_Marker) And
+ (Tai_Marker(Current).Kind = mark_AsmBlockEnd))
+ Then
+ Begin
+ Last := Nil;
+ GetLastInstruction := False
+ End
+ Else
+ Begin
+ Last := Current;
+ GetLastInstruction := True;
+ End;
+ End;
+
+
+ { ******************* Processor dependent stuff *************************** }
+
+ Function TAOptBase.RegMaxSize(Reg: TRegister): TRegister;
+ Begin
+ RegMaxSize := Reg
+ End;
+
+ Function TAOptBase.RegsSameSize(Reg1, Reg2: TRegister): Boolean;
+ Begin
+ RegsSameSize := True
+ End;
+
+end.
diff --git a/closures/compiler/aoptcs.pas b/closures/compiler/aoptcs.pas
new file mode 100644
index 0000000000..d50a57aaba
--- /dev/null
+++ b/closures/compiler/aoptcs.pas
@@ -0,0 +1,848 @@
+{
+ Copyright (c) 1998-2002 by Jonas Maebe, member of the Free Pascal
+ Development Team
+
+ This unit contains the common subexpression elimination object of the
+ assembler optimizer.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit aoptcs;
+
+interface
+
+uses aasm, aoptcpu, aoptobj;
+
+{ ************************************************************************* }
+{ info about the equivalence of registers when comparing two code sequences }
+{ ************************************************************************* }
+
+ TRegInfo = Object(TAoptBaseCpu)
+ { registers encountered in the new and old sequence }
+ NewRegsEncountered, OldRegsEncountered,
+ { registers which only have been loaded for use as base or index in a }
+ { reference later on }
+ RegsLoadedForRef: TRegSet;
+ { to which register in the old sequence corresponds every register in }
+ { the new sequence }
+ New2OldReg: TRegArray;
+
+ Constructor init;
+ { clear all information store in the object }
+ Procedure Clear;
+ { the contents of OldReg in the old sequence are now being loaded into }
+ { NewReg in the new sequence }
+ Procedure AddReg(OldReg, NewReg: TRegister); Virtual;
+ { the contents of OldOp in the old sequence are now being loaded into }
+ { NewOp in the new sequence. It is assumed that OldOp and NewOp are }
+ { equivalent }
+ Procedure AddOp(const OldOp, NewOp:Toper);
+ { check if a register in the old sequence (OldReg) can be equivalent to }
+ { a register in the new sequence (NewReg) if the operation OpAct is }
+ { performed on it. The RegInfo is updated (not necessary to call AddReg }
+ { afterwards) }
+ Function RegsEquivalent(OldReg, NewReg: TRegister; OpAct: TopAction):
+ Boolean;
+ { check if a reference in the old sequence (OldRef) can be equivalent }
+ { to a reference in the new sequence (NewRef) if the operation OpAct is }
+ { performed on it. The RegInfo is updated (not necessary to call AddOp }
+ { afterwards) }
+ Function RefsEquivalent(Const OldRef, NewRef: TReference; OpAct:
+ TOpAction): Boolean;
+ { check if an operand in the old sequence (OldOp) can be equivalent to }
+ { an operand in the new sequence (NewOp) if the operation OpAct is }
+ { performed on it. The RegInfo is updated (not necessary to call AddOp }
+ { afterwards) }
+ Function OpsEquivalent(const OldOp, NewOp: toper; OpAct: TopAction):
+ Boolean;
+ { check if an instruction in the old sequence (OldP) can be equivalent }
+ { to an instruction in the new sequence (Newp). The RegInfo is updated }
+ Function InstructionsEquivalent(OldP, NewP: Pai): Boolean;
+ End;
+
+
+{ ************************************************************************* }
+{ *************** The common subexpression elimination object ************* }
+{ ************************************************************************* }
+
+Type TAoptCSE = Object(TAoptObj)
+ { returns true if the instruction p1 modifies the register Reg }
+ Function RegModifiedByInstruction(Reg: TRegister; p1: Pai): Boolean;
+ End;
+
+Implementation
+
+{ ************************************************************************* }
+{ ******************************* TReginfo ******************************** }
+{ ************************************************************************* }
+
+Constructor TRegInfo.Init;
+Begin
+ Clear;
+End;
+
+Procedure TRegInfo.Clear;
+Begin
+ RegsLoadedForRef := [];
+ NewRegsEncountered := [FRAME_POINTER_REG, STACK_POINTER_REG];
+ OldRegsEncountered := [FRAME_POINTER_REG, STACK_POINTER_REG];
+ New2OldReg[FRAME_POINTER_REG] := FRAME_POINTER_REG;
+ New2OldReg[STACK_POINTER_REG] := STACK_POINTER_REG;
+End;
+
+Procedure TRegInfo.AddReg(OldReg, NewReg: TRegister);
+{ updates the ???RegsEncountered and ???2???Reg fields of RegInfo. Assumes }
+{ that OldReg and NewReg have the same size (has to be chcked in advance }
+{ with RegsSameSize) and that neither equals R_NO }
+{ has to be overridden for architectures like the 80x86 when not all GP }
+{ regs are of the same size }
+Begin
+ NewRegsEncountered := NewRegsEncountered + [NewReg];
+ OldRegsEncountered := OldRegsEncountered + [OldReg];
+ New2OldReg[NewReg] := OldReg;
+End;
+
+Procedure TRegInfo.AddOp(const OldOp, NewOp:Toper);
+Begin
+ Case OldOp.typ Of
+ Top_Reg:
+ If (OldOp.reg <> R_NO) Then
+ AddReg(OldOp.reg, NewOp.reg);
+ Top_Ref:
+ Begin
+ If OldOp.ref^.base <> R_NO Then
+ AddReg(OldOp.ref^.base, NewOp.ref^.base);
+{$ifdef RefsHaveIndexReg}
+ If OldOp.ref^.index <> R_NO Then
+ AddReg(OldOp.ref^.index, NewOp.ref^.index);
+{$endif RefsHaveIndexReg}
+ End;
+ End;
+End;
+
+Function TRegInfo.RegsEquivalent(OldReg, NewReg: TRegister;
+ OPAct: TOpAction): Boolean;
+Begin
+ If Not((OldReg = R_NO) Or (NewReg = R_NO)) Then
+ If RegsSameSize(OldReg, NewReg) Then
+{ here we always check for the 32 bit component, because it is possible }
+{ that the 8 bit component has not been set, event though NewReg already }
+{ has been processed. This happens if it has been compared with a register }
+{ that doesn't have an 8 bit component (such as EDI). In that case the 8 }
+{ bit component is still set to R_NO and the comparison in the Else-part }
+{ will fail }
+ If (RegMaxSize(OldReg) in OldRegsEncountered) Then
+ If (RegMaxSize(NewReg) in NewRegsEncountered) Then
+ RegsEquivalent := (OldReg = New2OldReg[NewReg])
+{ If we haven't encountered the new register yet, but we have encountered }
+{ the old one already, the new one can only be correct if it's being }
+{ written to (and consequently the old one is also being written to), }
+{ otherwise }
+{ }
+{ movl -8(%ebp), %eax and movl -8(%ebp), %eax }
+{ movl (%eax), %eax movl (%edx), %edx }
+{ }
+{ are considered equivalent }
+ Else
+ If (OpAct = OpAct_Write) Then
+ Begin
+ AddReg(OldReg, NewReg);
+ RegsEquivalent := True
+ End
+ Else Regsequivalent := False
+ Else
+ If Not(RegMaxSize(NewReg) in NewRegsEncountered) Then
+ Begin
+ AddReg(OldReg, NewReg);
+ RegsEquivalent := True
+ End
+ Else RegsEquivalent := False
+ Else RegsEquivalent := False
+ Else RegsEquivalent := OldReg = NewReg
+End;
+
+Function TRegInfo.RefsEquivalent(Const OldRef, NewRef: TReference;
+ OpAct: TOpAction): Boolean;
+Begin
+ If OldRef.is_immediate Then
+ RefsEquivalent := NewRef.is_immediate and (OldRef.Offset = NewRef.Offset)
+ Else
+ RefsEquivalent := (OldRef.Offset+OldRef.OffsetFixup =
+ NewRef.Offset+NewRef.OffsetFixup) And
+ RegsEquivalent(OldRef.Base, NewRef.Base, OpAct)
+{$ifdef RefsHaveindexReg}
+ And RegsEquivalent(OldRef.Index, NewRef.Index, OpAct)
+{$endif RefsHaveIndexReg}
+{$ifdef RefsHaveScale}
+ And (OldRef.ScaleFactor = NewRef.ScaleFactor)
+{$endif RefsHaveScale}
+ And (OldRef.Symbol = NewRef.Symbol)
+{$ifdef RefsHaveSegment}
+ And (OldRef.Segment = NewRef.Segment)
+{$endif RefsHaveSegment}
+ ;
+End;
+
+Function TRegInfo.OpsEquivalent(const OldOp, NewOp: toper; OpAct: TopAction):
+ Boolean;
+Begin
+ OpsEquivalent := False;
+ if OldOp.typ=NewOp.typ then
+ Case OldOp.typ Of
+ Top_Const: OpsEquivalent := OldOp.val = NewOp.val;
+ Top_Reg: OpsEquivalent := RegsEquivalent(OldOp.reg,NewOp.reg, OpAct);
+ Top_Ref: OpsEquivalent := RefsEquivalent(OldOp.ref^, NewOp.ref^, OpAct);
+ Top_None: OpsEquivalent := True
+ End;
+End;
+
+Function TRegInfo.InstructionsEquivalent(OldP, NewP: Pai): Boolean;
+
+ Function OperandTypesEqual: Boolean;
+ Var Count: AWord;
+ Begin
+ OperandTypesEqual := False;
+ For Count := 0 to max_operands-1 Do
+ If (PInstr(OldP)^.oper[Count].typ <> PInstr(NewP)^.oper[Count].typ) Then
+ Exit;
+ OperandTypesEqual := True
+ End;
+
+Var Count: AWord;
+ TmpResult: Boolean;
+Begin
+ If Assigned(OldP) And Assigned(NewP) And
+ (Pai(OldP)^.typ = ait_instruction) And
+ (Pai(NewP)^.typ = ait_instruction) And
+ (PInstr(OldP)^.opcode = PInstr(NewP)^.opcode) And
+ OperandTypesEqual
+ Then
+{ both instructions have the same structure: }
+{ "<operator> <operand of type1>, <operand of type 2>, ..." }
+ If IsLoadMemReg(OldP) Then
+{ then also NewP = loadmemreg because of the previous check }
+ If Not(RegInRef(PInstr(OldP)^.oper[LoadDst].reg,
+ PInstr(OldP)^.oper[LoadSrc].ref^)) Then
+{ the "old" instruction is a load of a register with a new value, not with }
+{ a value based on the contents of this register (so no "mov (reg), reg") }
+ If Not(RegInRef(PInstr(NewP)^.oper[LoadDst].reg,
+ PInstr(NewP)^.oper[LoadSrc].ref^)) And
+ RefsEqual(PInstr(OldP)^.oper[LoadSrc].ref^,
+ PInstr(NewP)^.oper[LoadSrc].ref^)
+ Then
+{ the "new" instruction is also a load of a register with a new value, and }
+{ this value is fetched from the same memory location }
+ Begin
+ With PInstr(NewP)^.oper[LoadSrc].ref^ Do
+ Begin
+ If Not(Base in [ProcInfo.FramePointer, R_NO, STACK_POINTER_REG])
+{ it won't do any harm if the register is already in RegsLoadedForRef }
+ Then RegsLoadedForRef := RegsLoadedForRef + [Base];
+{$ifdef RefsHaveIndexReg}
+ If Not(Index in [ProcInfo.FramePointer, R_NO, STACK_POINTER_REG])
+ Then RegsLoadedForRef := RegsLoadedForRef + [Index];
+{$endif RefsHaveIndexReg}
+ End;
+{ add the registers from the reference (.oper[Src]) to the RegInfo, all }
+{ registers from the reference are the same in the old and in the new }
+{ instruction sequence (refsequal returned true) }
+ AddOp(PInstr(OldP)^.oper[LoadSrc], PInstr(OldP)^.oper[LoadSrc]);
+{ the registers from .oper[Dest] have to be equivalent, but not necessarily }
+{ equal }
+ InstructionsEquivalent :=
+ RegsEquivalent(PInstr(OldP)^.oper[LoadDst].reg,
+ PInstr(NewP)^.oper[LoadDst].reg, OpAct_Write);
+ End
+{ the registers are loaded with values from different memory locations. If }
+{ this were allowed, the instructions "mov -4(%esi),%eax" and }
+{ "mov -4(%ebp),%eax" would be considered equivalent }
+ Else InstructionsEquivalent := False
+ Else
+{ load register with a value based on the current value of this register }
+ Begin
+ With PInstr(NewP)^.oper[0].ref^ Do
+{ Assume the registers occurring in the reference have only been loaded with }
+{ the value they contain now to calculate an address (so the value they have }
+{ now, won't be stored to memory later on) }
+ Begin
+ If Not(Base in [ProcInfo.FramePointer,
+ RegMaxSize(PInstr(NewP)^.oper[LoadDst].reg),
+ R_NO,STACK_POINTER_REG])
+{ It won't do any harm if the register is already in RegsLoadedForRef }
+ Then
+ Begin
+ RegsLoadedForRef := RegsLoadedForRef + [Base];
+{$ifdef csdebug}
+ Writeln(std_reg2str[base], ' added');
+{$endif csdebug}
+ end;
+{$Ifdef RefsHaveIndexReg}
+ If Not(Index in [ProcInfo.FramePointer,
+ RegMaxSize(PInstr(NewP)^.oper[LoadDst].reg),
+ R_NO,StackPtr])
+ Then
+ Begin
+ RegsLoadedForRef := RegsLoadedForRef + [Index];
+{$ifdef csdebug}
+ Writeln(std_reg2str[index], ' added');
+{$endif csdebug}
+ end;
+{$endif RefsHaveIndexReg}
+ End;
+
+{ now, remove the destination register of the load from the }
+{ RegsLoadedForReg, since if it's loaded with a new value, it certainly }
+{ will still be used later on }
+ If Not(RegMaxSize(PInstr(NewP)^.oper[LoadDst].reg) In
+ [ProcInfo.FramePointer,R_NO,STACK_POINTER_REG])
+ Then
+ Begin
+ RegsLoadedForRef := RegsLoadedForRef -
+ [RegMaxSize(PInstr(NewP)^.oper[LoadDst].reg)];
+{$ifdef csdebug}
+ Writeln(std_reg2str[RegMaxSize(PInstr(NewP)^.oper[1].reg)], ' removed');
+{$endif csdebug}
+ end;
+ InstructionsEquivalent :=
+ OpsEquivalent(PInstr(OldP)^.oper[LoadSrc],
+ PInstr(NewP)^.oper[LoadSrc], OpAct_Read) And
+ OpsEquivalent(PInstr(OldP)^.oper[LoadDst],
+ PInstr(NewP)^.oper[LoadDst], OpAct_Write)
+ End
+ Else
+{ OldP and NewP are not a load instruction, but have the same structure }
+{ (opcode, operand types), so they're equivalent if all operands are }
+{ equivalent }
+ Begin
+ Count := 0;
+ TmpResult := true;
+ Repeat
+ TmpResult :=
+ OpsEquivalent(PInstr(OldP)^.oper[Count], PInstr(NewP)^.oper[Count],
+ OpAct_Unknown);
+ Inc(Count)
+ Until (Count = MaxOps) or not(TmpResult);
+ InstructionsEquivalent := TmpResult
+ End
+{ the instructions haven't even got the same structure, so they're certainly }
+{ not equivalent }
+ Else InstructionsEquivalent := False;
+End;
+
+
+Function TRegInfo.CheckSequence(p: Pai; Reg: TRegister; Var Found: Longint):
+ Boolean;
+{checks whether the current instruction sequence (starting with p) and the
+ one between StartMod and EndMod of Reg are the same. If so, the number of
+ instructions that match is stored in Found and true is returned, otherwise
+ Found holds the number of instructions between StartMod and EndMod and false
+ is returned}
+
+{ note: the NrOfMods field can hold two deifferent values depending on }
+{ which instruction it belongs to: }
+{ * if it is the first instruction of a sequence that describes the }
+{ contents of a register, NrOfMods contains how many instructions are }
+{ in the sequence }
+{ * otherwise, NrOfMods contains how many instructions are in the }
+{ describing the contents of the register after the current instruction }
+{ has been executed }
+
+Var oldp, newp: Pai;
+ PrevNonRemovablePai: Pai;
+ OrgRegInfo, HighRegInfo: PRegInfo;
+ HighFound, OrgRegFound: Byte;
+ RegCounter: TRegister;
+ OrgRegResult: Boolean;
+ TmpResult: Boolean;
+ OldNrOfMods: Byte;
+Begin {CheckSequence}
+ Reg := RegMaxSize(Reg);
+{ have we found a sequence of instructions equivalent to the new one? }
+ TmpResult := False;
+{ HighRegInfo will contain the RegInfo for the longest sequence of matching }
+{ instructions found }
+ New(HighRegInfo, Init);
+{ how many instructions are in the sequence describing the content of Reg }
+{ (the parameter) in the old sequence }
+ OrgRegFound := 0;
+{ how many instructions are in the longest sequence of matching }
+{ instructions found until now? }
+ HighFound := 0;
+{ does the content of Reg in the old equence match the content of Reg in }
+{ the new sequence }
+ OrgRegResult := False;
+ RegCounter := LoGPReg;
+{ PrevNonRemovablePai's OptInfo contains the contents of the registers }
+{ before the current instruction is executed. It will be used to compare }
+{ the new contents with and to see whether the new instructions can be }
+{ removed }
+ GetLastInstruction(p, PrevNonRemovablePai);
+{ don't check registers that only contain a constant or something unknown }
+ While (RegCounter <= HiGPReg And
+ (PPaiProp(PrevNonRemovablePai^.OptInfo)^.Regs[RegCounter].Typ <> Con_Ref) Do
+ Inc(RegCounter);
+ While (RegCounter <= HiGPReg) Do
+ Begin
+ { reinitialize the reginfo fields }
+ Init;
+ { no matching instructions found yet }
+ Found := 0;
+ With PPaiProp(PrevNonRemovablePai^.OptInfo)^.Regs[RegCounter] Do
+ Begin
+ { get the first instruction that describes the content of the }
+ { the register we're going to check the way it was before the }
+ { current instruction got executed }
+ oldp := StartMod;
+ { how many instructions describe the content of the register }
+ { before the current instructions got executed? }
+ OldNrOfMods := NrOfMods
+ End;
+ { p is the first instruction that describes the content of Reg }
+ { after p (= the current instruction) got executed }
+ newp := p;
+ { it's possible that the old contents of the current register are }
+ { described by a sequence of instructions that also contains the }
+ { one in parameter p. In that case, we have to compare until we }
+ { encounter p. Otherwise, compare as much instructions as there are }
+ { in the old sequence or until there's a mismatch }
+ While (p <> oldp) And
+ (Found < OldNrOfMods) And
+ { old new }
+ InstructionsEquivalent(oldp, newp, RegInfo) Do
+ Begin
+ GetNextInstruction(oldp, oldp);
+ GetNextInstruction(newp, newp);
+ Inc(Found)
+ End;
+ If (Found < OldNrOfMods) Then
+ Begin
+ { the old sequence was longer than than the new one, so no match }
+ TmpResult := False;
+ { If there is no match, we have to set the CanBeRemoved flag of }
+ { all pai objects part of the new sequence to false, because it's }
+ { possible that some of them have already been scheduled for }
+ { removal after checking another sequence (an instruction can be }
+ { of more than one sequence). If we return false, the number }
+ { returned in found denotes how many instructions have to have }
+ { their CanBeRemoved flag set to false }
+ { We only have to set those flags to false if their was a partial }
+ { match of instructions (found > 0), because otherwise they can't }
+ { have been set to true in a previous comparison }
+ If (found > 0) Then
+ Found := PPaiProp(Pai(p)^.OptInfo)^.Regs[Reg].NrOfMods
+ End
+ Else TmpResult := True;
+ If (RegCounter = Reg) Then
+ Begin
+ OrgRegFound := Found;
+ OrgRegResult := TmpResult;
+ New(OrgRegInfo, InitWithValue(RegInfo));
+ End
+ Else
+ If TmpResult And
+ (Found > HighFound) Then
+ Begin
+ HighFound := Found;
+ HighRegInfo^.InitWithValue(RegInfo);
+ End;
+ RegInfo.Done;
+ Repeat
+ Inc(RegCounter);
+ Until (RegCounter > HiGPReg) or
+ (PPaiProp(PrevNonRemovablePai^.OptInfo)^.Regs[RegCounter].Typ =
+ Con_Ref);
+ End;
+ If (HighFound > 0) And
+ (Not(OrgRegResult) Or
+ (HighFound > OrgRegFound)) Then
+ Begin
+ CheckSequence := True;
+ Found := HighFound
+ InitWithValue(HighRegInfo);
+ End
+ Else
+ Begin
+ CheckSequence := OrgRegResult;
+ Found := OrgRegFound;
+ InitWithValue(OrgRegInfo);
+ End;
+ Dispose(HighRegInfo, Done);
+ Dispose(OrgRegInfo, Done)
+End; {CheckSequence}
+
+
+{ ************************************************************************* }
+{ ******************************* TAOptCSE ******************************** }
+{ ************************************************************************* }
+
+
+Function TAOptCSE.RegModifiedByInstruction(Reg: TRegister; p1: Pai): Boolean;
+Var hp: Pai;
+Begin
+ If GetLastInstruction(p1, hp)
+ Then
+ RegModifiedByInstruction :=
+ PPAiProp(p1^.OptInfo)^.GetWState <>
+ PPAiProp(hp^.OptInfo)^.GetWState
+ Else RegModifiedByInstruction := True;
+End;
+
+Procedure TAoptCSE.RestoreContents(Current: Pai; Reg: TRegister);
+Var Prev, hp3, hp5: Pai;
+ TmpState: TStateInt;
+ Cnt, Cnt2: Byte;
+Begin
+{ load Cnt2 with the total number of instructions of this sequence }
+ Cnt2 := PPaiProp(Prev^.OptInfo)^.Regs[RegInfo.New2OldReg[reg]].
+ NrOfMods;
+{ sometimes, a register can not be removed from a sequence, because it's }
+{ still used afterwards: }
+{ }
+{ movl -8(%ebp), %eax movl -8(%ebp), %eax }
+{ movl 70(%eax), %eax movl 70(%eax), %eax }
+{ cmpl 74(%eax), %eax cmpl 74(%eax), %eax }
+{ jne l1 can't be changed to jne l1 }
+{ movl -8(%ebp), %eax }
+{ movl 70(%eax), %edi movl %eax, %edi }
+{ boundl R_282, %edi boundl R_282, %edi }
+{ pushl 70(%eax) pushl 70(%eax) }
+{ }
+{ because eax now contains the wrong value when 70(%eax) is pushed }
+
+{ start at the first instruction of the sequence }
+ hp3 := Current;
+ For Cnt := 1 to Pred(Cnt2) Do
+ GetNextInstruction(hp3, hp3);
+{ hp3 now containts the last instruction of the sequence }
+{ get the writestate at this point of the register in TmpState }
+ TmpState := PPaiProp(hp3^.OptInfo)^.GetWState(reg);
+{ hp3 := first instruction after the sequence }
+ GetNextInstruction(hp3, hp3);
+
+{ now, even though reg is in RegsLoadedForRef, sometimes it's still used }
+{ afterwards. It is not if either it is not in usedregs anymore after the }
+{ sequence, or if it is loaded with a new value right after the sequence }
+ If (TmpState <> PPaiProp(hp3^.OptInfo)^.Regs[reg].WState) Or
+ Not(reg in PPaiProp(hp3^.OptInfo)^.UsedRegs) Then
+{ the register is not used anymore after the sequence! }
+ Begin
+{$ifdef csdebug}
+ Writeln('Cnt2: ',Cnt2);
+ hp5 := new(pai_asm_comment,init(strpnew('starting here...')));
+ InsertLLItem(Pai(Current^.previous), Current, hp5);
+{$endif csdebug}
+ hp3 := Current;
+{ first change the contents of the register inside the sequence }
+ For Cnt := 1 to Cnt2 Do
+ Begin
+ {save the WState of the last pai object of the sequence for later use}
+ TmpState := PPaiProp(hp3^.OptInfo)^.Regs[reg].WState;
+{$ifdef csdebug}
+ hp5 := new(pai_asm_comment,init(strpnew('WState for '+
+ std_reg2str[reg]+': '+tostr(tmpstate))));
+ InsertLLItem(hp3, pai(hp3^.next), hp5);
+{$endif csdebug}
+ PPaiProp(hp3^.OptInfo)^.Regs[reg] :=
+ PPaiProp(Prev^.OptInfo)^.Regs[reg];
+ GetNextInstruction(hp3, hp3);
+ End;
+{ here, hp3 = p = Pai object right after the sequence, TmpState = WState of }
+{ reg at the last Pai object of the sequence }
+ GetLastInstruction(hp3, hp3);
+{ now, as long as the register isn't modified after the sequence, set its }
+{ contents to what they were before the sequence }
+ While GetNextInstruction(hp3, hp3) And
+ (PPaiProp(hp3^.OptInfo)^.GetWState(Reg) = TmpState) Do
+{$ifdef csdebug}
+ begin
+ hp5 := new(pai_asm_comment,init(strpnew('WState for '+std_reg2str[reg]+': '+
+ tostr(PPaiProp(hp3^.OptInfo)^.GetWState(reg)))));
+ InsertLLItem(hp3, pai(hp3^.next), hp5);
+{$endif csdebug}
+ PPaiProp(hp3^.OptInfo)^.Regs[reg] :=
+ PPaiProp(Prev^.OptInfo)^.Regs[reg];
+{$ifdef csdebug}
+ end;
+{$endif csdebug}
+ End
+ Else
+{ the register is still used after the sequence, so undelete all }
+{ instructions in the sequence that modify reg }
+ Begin
+{$ifdef csdebug}
+ Writeln('Got there for ',std_reg2str[reg]);
+{$endif csdebug}
+ hp3 := Current;
+ For Cnt := 1 to Cnt2 Do
+ Begin
+ If RegModifiedByInstruction(reg, hp3) Then
+ PPaiProp(hp3^.OptInfo)^.CanBeRemoved := False;
+ GetNextInstruction(hp3, hp3);
+ End;
+ End;
+{$ifdef csdebug}
+ hp5 := new(pai_asm_comment,init(strpnew('stopping here...')));
+ InsertLLItem(AsmL, hp3, pai(hp3^.next), hp5);
+{$endif csdebug}
+End;
+
+Procedure TAoptCSE.DoCSE;
+{marks the instructions that can be removed by RemoveInstructs. They're not
+ removed immediately because sometimes an instruction needs to be checked in
+ two different sequences}
+Var Cnt, Cnt2: Longint;
+ p, hp1, Current: Pai;
+ hp3, Prev: Pai;
+{$ifdef csdebug}
+ hp5: pai;
+{$endif csdebug}
+ RegInfo: TRegInfo;
+ RegCounter: TRegister;
+ TmpState: Byte;
+Begin
+ p := SkipHead(BlockStart);
+ While (p <> BlockEnd) Do
+ Begin
+ Case p^.typ Of
+ ait_instruction:
+ Begin
+{ Case PInstr(p)^.opcode Of
+ A_CLD: If GetLastInstruction(p, hp1) And
+ (PPaiProp(hp1^.OptInfo)^.DirFlag = F_NotSet) Then
+ PPaiProp(Pai(p)^.OptInfo)^.CanBeRemoved := True;}
+ If IsLoadMemReg(p) Then
+ Begin
+ If (p = PPaiProp(p^.OptInfo)^.Regs[RegMaxSize(
+ PInstr(p)^.oper[LoadDst].reg)].StartMod) And
+ GetLastInstruction (p, hp1) And
+ (hp1^.typ <> ait_marker) Then
+{so we don't try to check a sequence when p is the first instruction of the block}
+ If CheckSequence(p, PInstr(p)^.oper[LoadDst].reg, Cnt) And
+ (Cnt > 0) Then
+ Begin
+ hp1 := nil;
+{ although it's perfectly ok to remove an instruction which doesn't contain }
+{ the register that we've just checked (CheckSequence takes care of that), }
+{ the sequence containing this other register should also be completely }
+{ checked (and either removed or marked as non-removable), otherwise we }
+{ may get situations like this: }
+{ }
+{ movl 12(%ebp), %edx movl 12(%ebp), %edx }
+{ movl 16(%ebp), %eax movl 16(%ebp), %eax }
+{ movl 8(%edx), %edx movl 8(%edx), %edx }
+{ movl (%eax), eax movl (%eax), eax }
+{ cmpl %eax, %edx cmpl %eax, %edx }
+{ jnz l123 getting converted to jnz l123 }
+{ movl 12(%ebp), %edx movl 4(%eax), eax }
+{ movl 16(%ebp), %eax }
+{ movl 8(%edx), %edx }
+{ movl 4(%eax), eax }
+ Current := p;
+ Cnt2 := 1;
+{ after this while loop, if hp1 <> nil it will contain the pai object }
+{ that's the start of a sequence that's not completely checked yet }
+ While Cnt2 <= Cnt Do
+ Begin
+ If (hp1 = nil) And
+ Not(RegInInstruction(
+ PInstr(Current)^.oper[LoadDst].reg,p) Or
+ RegInInstruction(RegMaxSize(PInstr(
+ Current)^.oper[LoadDst].reg), p)) And
+{ do not recheck a sequence if it's completely part of the one we just }
+{ checked }
+ Not(IsLoadMemReg(p) And
+ (PPaiProp(p^.OptInfo)^.Regs[RegMaxSize(
+ PInstr(p)^.Oper[LoadDst].reg)]
+ .NrOfMods <= (Cnt - Cnt2 + 1))) Then
+ hp1 := p;
+{$ifndef noremove}
+ PPaiProp(p^.OptInfo)^.CanBeRemoved := True;
+{$endif noremove}
+ Inc(Cnt2);
+ GetNextInstruction(p, p);
+ End;
+{ insert a marker noting that for the following instructions no PPaiProp's }
+{ (containing optimizer info) have been generated, so GetNext/ }
+{ LastInstruction will ignore them (it will use the original instructions) }
+ hp3 := New(Pai_Marker,Init(mark_NoPropInfoStart));
+ InsertLLItem(Pai(Current^.Previous), Current, hp3);
+{ Prev is used to get the contents of the registers before the sequence }
+ GetLastInstruction(Current, Prev);
+{ If some registers were different in the old and the new sequence, move }
+{ the contents of those old registers to the new ones, e.g. }
+{ }
+{ mov mem1, reg1 mov mem1, reg1 }
+{ ... can be changed to ... }
+{ mov mem1, reg2 mov reg1, reg2 }
+
+{$IfDef CSDebug}
+ For RegCounter := LoGPReg To HiGPReg Do
+ If (RegCounter in RegInfo.RegsLoadedForRef) Then
+ Begin
+ hp5 := new(pai_asm_comment,init(strpnew(
+ 'New: '+std_reg2str[RegCounter]+', Old: '+
+ std_reg2str[RegInfo.New2OldReg[RegCounter]])));
+ InsertLLItem(AsmL, Pai(Current^.previous), Current, hp5);
+ End;
+{$EndIf CSDebug}
+ For RegCounter := LoGPReg to HiGPReg Do
+ Begin
+{ if New2OldReg[RegCounter] = R_NO, it means this register doesn't appear }
+{ the new nor the old sequence }
+ If (RegInfo.New2OldReg[RegCounter] <> R_NO) Then
+{ if a register is in RegsLoadedForRef, it means this register was loaded }
+{ with a value only to function as a base or index in a reference. The }
+{ practical upshot of this is that this value won't be used anymore later }
+{ on, so even if another register was used in the new sequence for this, }
+{ we don't have to load it. E.g. }
+{ }
+{ movl 8(%ebp), %eax " }
+{ movl 4(%eax), %eax " }
+{ movl (%eax), %edi " }
+{ movl %edi, 12(%ebp) " }
+{ ... can be changed to " }
+{ movl 8(%ebp), %edx }
+{ movl 4(%edx), %edx }
+{ movl (%edx), %ebx movl %edi, %ebx }
+{ }
+{ There is no need to also add a "movl %eax, %edx" }
+ If Not(RegCounter In RegInfo.RegsLoadedForRef) And
+ {old reg new reg}
+{ no need to reload the register if it's the same in the old and new }
+{ sequence }
+ (RegInfo.New2OldReg[RegCounter] <> RegCounter) Then
+
+ Begin
+ hp3 := a_load_reg_reg(
+ {old reg new reg}
+ RegInfo.New2OldReg[RegCounter], RegCounter));
+ InsertLLItem(Pai(Current^.previous), Current, hp3);
+ End
+ Else
+{ As noted before, if a register is in RegsLoadedForRef, it doesn't have }
+{ to be loaded. However, when data flow analyzer processed this code, the }
+{ was loaded, so we need to change that. This is done by setting the }
+{ contents of the register to its contents before the new sequence, for }
+{ every instruction until the first load of the register with a new value }
+ If (RegCounter In RegInfo.RegsLoadedForRef) Then
+ RestoreOrigContents(Current, RegCounter);
+
+ End;
+{ the end of the area where instructions without optimizer info can occur }
+ hp3 := New(Pai_Marker,Init(mark_NoPropInfoEnd));
+ InsertLLItem(AsmL, Pai(Current^.Previous), Current, hp3);
+{ if we found an instruction sequence that needs complete re-evaluation, }
+{ process it }
+ If hp1 <> nil Then p := hp1;
+ Continue;
+ End
+ Else
+{ checksequence returned false. In that case, if the current instruction }
+{ was already deleted (as part of another sequence), we have to undelete }
+{ all instructions pertaining to the register whose sequence we just }
+{ checked }
+ If (Cnt > 0) And
+ (PPaiProp(p^.OptInfo)^. Regs[RegMaxSize(PInstr(p)^.
+ oper[LoadDst].reg)].Typ = Con_Ref) And
+ (PPaiProp(p^.OptInfo)^.CanBeRemoved) Then
+ Begin
+ Current := p;
+ Cnt2 := 1;
+ While Cnt2 <= Cnt Do
+ Begin
+ If RegInInstruction(PInstr(Current)^.
+ oper[LoadDst].reg, p) Or
+ RegInInstruction(RegMaxSize(PInstr(Current)^.
+ oper[LoadDst].reg), p) Then
+ PPaiProp(p^.OptInfo)^.CanBeRemoved := False;
+ Inc(Cnt2);
+ GetNextInstruction(p, p);
+ End;
+ Continue;
+ End;
+ End
+ Else if IsLoadConstReg(p) Then
+ Begin
+ If GetLastInstruction(p, hp1) Then
+ With PPaiProp(hp1^.OptInfo)^.Regs[
+ RegMaxSize(PInstr(p)^.oper[LoadDst].reg)] Do
+ If (Typ = Con_Const) And
+ (StartMod = p) Then
+ PPaiProp(p^.OptInfo)^.CanBeRemoved := True;
+ End
+ Else
+ CpuCSE(p);
+{ A_STD: If GetLastInstruction(p, hp1) And
+ (PPaiProp(hp1^.OptInfo)^.DirFlag = F_Set) Then
+ PPaiProp(Pai(p)^.OptInfo)^.CanBeRemoved := True;
+ A_XOR:
+ Begin
+ If (Paicpu(p)^.oper[0].typ = top_reg) And
+ (Paicpu(p)^.oper[0].typ = top_reg) And
+ (Paicpu(p)^.oper[1].reg = Paicpu(p)^.oper[1].reg) And
+ GetLastInstruction(p, hp1) And
+ (PPaiProp(hp1^.OptInfo)^.Regs[Reg32(Paicpu(p)^.oper[1].reg)].typ = con_const) And
+ (PPaiProp(hp1^.OptInfo)^.Regs[Reg32(Paicpu(p)^.oper[1].reg)].StartMod = nil)
+ Then PPaiProp(p^.OptInfo)^.CanBeRemoved := True
+ End
+ End;
+ End;
+ GetNextInstruction(p, p);
+ End;
+End;
+
+Procedure RemoveInstructs;
+{Removes the marked instructions and disposes the PPaiProps of the other
+ instructions, restoring their line number}
+Var p, hp1: Pai;
+ InstrCnt: Longint;
+Begin
+ p := SkipHead(BlockStart);
+ InstrCnt := 1;
+ While (p <> BlockEnd) Do
+ Begin
+{$ifndef noinstremove}
+ If PPaiProp(p^.OptInfo)^.CanBeRemoved
+ Then
+ Begin
+ Dispose(PPaiProp(p^.OptInfo));
+ GetNextInstruction(p, hp1);
+ AsmL^.Remove(p);
+ Dispose(p, Done);
+ p := hp1;
+ Inc(InstrCnt);
+ End
+ Else
+{$endif noinstremove}
+ Begin
+ Dispose(PPaiProp(p^.OptInfo));
+ p^.OptInfo := nil;
+ GetNextInstruction(p, p);
+ Inc(InstrCnt);
+ End;
+ End;
+End;
+
+Procedure TAoptCSE.CSE;
+Begin
+ DoCSE;
+ RemoveInstructs;
+End;
+
+
+
+End.
diff --git a/closures/compiler/aoptda.pas b/closures/compiler/aoptda.pas
new file mode 100644
index 0000000000..e7e0030ae2
--- /dev/null
+++ b/closures/compiler/aoptda.pas
@@ -0,0 +1,165 @@
+{
+ Copyright (c) 1998-2002 by Jonas Maebe, member of the Free Pascal
+ Development Team
+
+ This unit contains the data flow analyzer object of the assembler
+ optimizer.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+Unit aoptda;
+
+{$i fpcdefs.inc}
+
+ Interface
+
+ uses
+ cpubase,cgbase,
+ aasmbase,aasmtai,aasmdata,aasmcpu,
+ aoptcpub, aoptbase;
+
+ Type
+ TAOptDFA = class
+ { uses the same constructor as TAoptCpu = constructor from TAoptObj }
+
+ { How many instructions are between the current instruction and the }
+ { last one that modified the register }
+ InstrSinceLastMod: TInstrSinceLastMod;
+
+ { gathers the information regarding the contents of every register }
+ { at the end of every instruction }
+ Procedure DoDFA;
+
+ { handles the processor dependent dataflow analizing }
+ Procedure CpuDFA(p: PInstr); Virtual; Abstract;
+
+ { convert a TInsChange value into the corresponding register }
+ //!!!!!!!!!! Function TCh2Reg(Ch: TInsChange): TRegister; Virtual;
+ { returns whether the instruction P reads from register Reg }
+ Function RegReadByInstr(Reg: TRegister; p: tai): Boolean; Virtual; Abstract;
+ End;
+
+ Implementation
+
+ uses
+ globals, aoptobj;
+
+ Procedure TAOptDFA.DoDFA;
+ { Analyzes the Data Flow of an assembler list. Analyses the reg contents }
+ { for the instructions between blockstart and blockend. Returns the last pai }
+ { which has been processed }
+ {
+ Var
+ CurProp: TPaiProp;
+ UsedRegs: TUsedRegs;
+ p, hp, NewBlockStart : tai;
+ TmpReg: TRegister;
+ }
+ Begin
+ (*!!!!!!!!!!
+ p := BlockStart;
+ UsedRegs.Create;
+ UsedRegs.Update(p);
+ NewBlockStart := SkipHead(p);
+ { done implicitely by the constructor
+ FillChar(InstrSinceLastMod, SizeOf(InstrSinceLastMod), 0); }
+ While (P <> BlockEnd) Do
+ Begin
+ CurProp:=TPaiProp.Create;
+ If (p <> NewBlockStart) Then
+ Begin
+ GetLastInstruction(p, hp);
+ CurProp.Regs := TPaiProp(hp.OptInfo).Regs;
+ { !!!!!!!!!!!! }
+ {$ifdef x86}
+ CurProp.CondRegs.Flags :=
+ TPaiProp(hp.OptInfo).CondRegs.Flags;
+ {$endif}
+ End;
+ CurProp.UsedRegs.InitWithValue(UsedRegs.GetUsedRegs);
+ UsedRegs.Update(tai(p.Next));
+ TPaiProp(p.OptInfo) := CurProp;
+ For TmpReg := LoGPReg To HiGPReg Do
+ Inc(InstrSinceLastMod[TmpReg]);
+ Case p^.typ Of
+ ait_label:
+ If (Pai_label(p)^.l^.is_used) Then
+ CurProp^.DestroyAllRegs(InstrSinceLastMod);
+ ait_stab, ait_force_line, ait_function_name:;
+ ait_instruction:
+ if not(PInstr(p)^.is_jmp) then
+ begin
+ If IsLoadMemReg(p) Then
+ Begin
+ CurProp^.ReadRef(PInstr(p)^.oper[LoadSrc].ref);
+ TmpReg := RegMaxSize(PInstr(p)^.oper[LoadDst].reg);
+ If RegInRef(TmpReg, PInstr(p)^.oper[LoadSrc].ref^) And
+ (CurProp^.GetRegContentType(TmpReg) = Con_Ref) Then
+ Begin
+ { a load based on the value this register already }
+ { contained }
+ With CurProp^.Regs[TmpReg] Do
+ Begin
+ CurProp^.IncWState(TmpReg);
+ {also store how many instructions are part of the }
+ { sequence in the first instruction's PPaiProp, so }
+ { it can be easily accessed from within }
+ { CheckSequence }
+ Inc(NrOfMods, InstrSinceLastMod[TmpReg]);
+ PPaiProp(Pai(StartMod)^.OptInfo)^.Regs[TmpReg].NrOfMods := NrOfMods;
+ InstrSinceLastMod[TmpReg] := 0
+ End
+ End
+ Else
+ Begin
+ { load of a register with a completely new value }
+ CurProp^.DestroyReg(TmpReg, InstrSinceLastMod);
+ If Not(RegInRef(TmpReg, PInstr(p)^.oper[LoadSrc].ref^)) Then
+ With CurProp^.Regs[TmpReg] Do
+ Begin
+ Typ := Con_Ref;
+ StartMod := p;
+ NrOfMods := 1;
+ End
+ End;
+ {$ifdef StateDebug}
+ hp := new(pai_asm_comment,init(strpnew(std_reg2str[TmpReg]+': '+tostr(CurProp^.Regs[TmpReg].WState))));
+ InsertLLItem(AsmL, p, p^.next, hp);
+ {$endif StateDebug}
+
+ End
+ Else if IsLoadConstReg(p) Then
+ Begin
+ TmpReg := RegMaxSize(PInstr(p)^.oper[LoadDst].reg);
+ With CurProp^.Regs[TmpReg] Do
+ Begin
+ CurProp^.DestroyReg(TmpReg, InstrSinceLastMod);
+ typ := Con_Const;
+ StartMod := Pointer(PInstr(p)^.oper[LoadSrc].val);
+ End
+ End
+ Else CpuDFA(Pinstr(p));
+ End;
+ Else CurProp^.DestroyAllRegs(InstrSinceLastMod);
+ End;
+ { Inc(InstrCnt);}
+ GetNextInstruction(p, p);
+ End;
+ *)
+ End;
+
+End.
diff --git a/closures/compiler/aoptobj.pas b/closures/compiler/aoptobj.pas
new file mode 100644
index 0000000000..b9c53e76be
--- /dev/null
+++ b/closures/compiler/aoptobj.pas
@@ -0,0 +1,1156 @@
+{
+ Copyright (c) 1998-2004 by Jonas Maebe, member of the Free Pascal
+ Development Team
+
+ This unit contains the processor independent assembler optimizer
+ object, base for the dataflow analyzer, peepholeoptimizer and
+ common subexpression elimination objects.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+Unit AoptObj;
+
+ {$i fpcdefs.inc}
+
+ { general, processor independent objects for use by the assembler optimizer }
+
+ Interface
+
+ uses
+ globtype,
+ aasmbase,aasmcpu,aasmtai,aasmdata,
+ cclasses,
+ cgbase,cgutils,
+ cpubase,
+ aoptbase,aoptcpub,aoptda;
+
+ { ************************************************************************* }
+ { ********************************* Constants ***************************** }
+ { ************************************************************************* }
+
+ Const
+
+ {Possible register content types}
+ con_Unknown = 0;
+ con_ref = 1;
+ con_const = 2;
+
+ {***************** Types ****************}
+
+ Type
+
+ { ************************************************************************* }
+ { ************************* Some general type definitions ***************** }
+ { ************************************************************************* }
+ TRefCompare = Function(const r1, r2: TReference): Boolean;
+ //!!! FIXME
+ TRegArray = Array[byte] of tsuperregister;
+ TRegSet = Set of byte;
+ { possible actions on an operand: read, write or modify (= read & write) }
+ TOpAction = (OpAct_Read, OpAct_Write, OpAct_Modify, OpAct_Unknown);
+
+ { ************************************************************************* }
+ { * Object to hold information on which regiters are in use and which not * }
+ { ************************************************************************* }
+ TUsedRegs = class
+ Constructor create;
+ Constructor create_regset(Const _RegSet: TRegSet);
+
+ Destructor Destroy;override;
+ { update the info with the pairegalloc objects coming after }
+ { p }
+ Procedure Update(p: Tai);
+ { is Reg currently in use }
+ Function IsUsed(Reg: TRegister): Boolean;
+ { get all the currently used registers }
+ Function GetUsedRegs: TRegSet;
+
+ Private
+
+ UsedRegs: TRegSet;
+ End;
+
+ { ************************************************************************* }
+ { ******************* Contents of the integer registers ******************* }
+ { ************************************************************************* }
+
+ { size of the integer that holds the state number of a register. Can be any }
+ { integer type, so it can be changed to reduce the size of the TContent }
+ { structure or to improve alignment }
+ TStateInt = Byte;
+
+ TContent = Record
+ { start and end of block instructions that defines the }
+ { content of this register. If Typ = con_const, then }
+ { Longint(StartMod) = value of the constant) }
+ StartMod: Tai;
+ { starts at 0, gets increased everytime the register is }
+ { written to }
+ WState: TStateInt;
+ { starts at 0, gets increased everytime the register is read }
+ { from }
+ RState: TStateInt;
+ { how many instructions starting with StarMod does the block }
+ { consist of }
+ NrOfMods: Byte;
+ { the type of the content of the register: unknown, memory }
+ { (variable) or constant }
+ Typ: Byte;
+ End;
+
+ //!!! FIXME
+ TRegContent = Array[byte] Of TContent;
+
+ { ************************************************************************** }
+ { information object with the contents of every register. Every Tai object }
+ { gets one of these assigned: a pointer to it is stored in the OptInfo field }
+ { ************************************************************************** }
+
+ TPaiProp = class(TAoptBaseCpu)
+ Regs: TRegContent;
+ { info about allocation of general purpose integer registers }
+ UsedRegs: TUsedRegs;
+ { can this instruction be removed? }
+ CanBeRemoved: Boolean;
+
+ Constructor create; reintroduce;
+
+ { checks the whole sequence of which (so regs[which].StartMod and and }
+ { the next NrOfMods Tai objects) to see whether Reg is used somewhere, }
+ { without it being loaded with something else first }
+ Function RegInSequence(Reg, which: TRegister): Boolean;
+ { destroy the contents of a register, as well as those whose contents }
+ { are based on those of that register }
+ Procedure DestroyReg(Reg: TRegister; var InstrSinceLastMod:
+ TInstrSinceLastMod);
+ { if the contents of WhichReg (can be R_NO in case of a constant) are }
+ { written to memory at the location Ref, the contents of the registers }
+ { that depend on Ref have to be destroyed }
+ Procedure DestroyRefs(Const Ref: TReference; WhichReg: TRegister; var
+ InstrSinceLastMod: TInstrSinceLastMod);
+
+ { an instruction reads from operand o }
+ Procedure ReadOp(const o:toper);
+ { an instruction reads from reference Ref }
+ Procedure ReadRef(Ref: PReference);
+ { an instruction reads from register Reg }
+ Procedure ReadReg(Reg: TRegister);
+
+ { an instruction writes/modifies operand o and this has special }
+ { side-effects or modifies the contents in such a way that we can't }
+ { simply add this instruction to the sequence of instructions that }
+ { describe the contents of the operand, so destroy it }
+ Procedure DestroyOp(const o:Toper; var InstrSinceLastMod:
+ TInstrSinceLastMod);
+ { destroy the contents of all registers }
+ Procedure DestroyAllRegs(var InstrSinceLastMod: TInstrSinceLastMod);
+ { a register's contents are modified, but not destroyed (the new value }
+ { depends on the old one) }
+ Procedure ModifyReg(reg: TRegister; var InstrSinceLastMod:
+ TInstrSinceLastMod);
+ { an operand's contents are modified, but not destroyed (the new value }
+ { depends on the old one) }
+ Procedure ModifyOp(const oper: TOper; var InstrSinceLastMod:
+ TInstrSinceLastMod);
+
+ { increase the write state of a register (call every time a register is }
+ { written to) }
+ Procedure IncWState(Reg: TRegister);
+ { increase the read state of a register (call every time a register is }
+ { read from) }
+ Procedure IncRState(Reg: TRegister);
+ { get the write state of a register }
+ Function GetWState(Reg: TRegister): TStateInt;
+ { get the read state of a register }
+ Function GetRState(Reg: TRegister): TStateInt;
+
+ { get the type of contents of a register }
+ Function GetRegContentType(Reg: TRegister): Byte;
+
+ Destructor Done;
+
+ Private
+
+ Procedure IncState(var s: TStateInt);
+
+ { returns whether the reference Ref is used somewhere in the loading }
+ { sequence Content }
+ Function RefInSequence(Const Ref: TReference; Content: TContent;
+ RefsEq: TRefCompare): Boolean;
+
+ { returns whether the instruction P reads from and/or writes }
+ { to Reg }
+ Function RefInInstruction(Const Ref: TReference; p: Tai;
+ RefsEq: TRefCompare): Boolean;
+
+ { returns whether two references with at least one pointing to an array }
+ { may point to the same memory location }
+
+ End;
+
+
+ { ************************************************************************* }
+ { ************************ Label information ****************************** }
+ { ************************************************************************* }
+ TLabelTableItem = Record
+ PaiObj: Tai;
+ End;
+
+ TLabelTable = Array[0..2500000] Of TLabelTableItem;
+ PLabelTable = ^TLabelTable;
+ PLabelInfo = ^TLabelInfo;
+ TLabelInfo = Record
+ { the highest and lowest label number occurring in the current code }
+ { fragment }
+ LowLabel, HighLabel: longint;
+ LabelDif: cardinal;
+ { table that contains the addresses of the Pai_Label objects associated
+ with each label number }
+ LabelTable: PLabelTable;
+ End;
+
+ { ************************************************************************* }
+ { ********** General optimizer object, used to derive others from ********* }
+ { ************************************************************************* }
+
+ TAOptObj = class(TAoptBaseCpu)
+ { the PAasmOutput list this optimizer instance works on }
+ AsmL: TAsmList;
+
+ { The labelinfo record contains the addresses of the Tai objects }
+ { that are labels, how many labels there are and the min and max }
+ { label numbers }
+ LabelInfo: PLabelInfo;
+
+ { Start and end of the block that is currently being optimized }
+ BlockStart, BlockEnd: Tai;
+
+ DFA: TAOptDFA;
+ { _AsmL is the PAasmOutpout list that has to be optimized, }
+ { _BlockStart and _BlockEnd the start and the end of the block }
+ { that has to be optimized and _LabelInfo a pointer to a }
+ { TLabelInfo record }
+ Constructor create(_AsmL: TAsmList; _BlockStart, _BlockEnd: Tai;
+ _LabelInfo: PLabelInfo); virtual; reintroduce;
+
+ { processor independent methods }
+
+ { returns true if the label L is found between hp and the next }
+ { instruction }
+ Function FindLabel(L: TasmLabel; Var hp: Tai): Boolean;
+
+ { inserts new_one between prev and foll in AsmL }
+ Procedure InsertLLItem(prev, foll, new_one: TLinkedListItem);
+
+
+ { If P is a Tai object releveant to the optimizer, P is returned
+ If it is not relevant tot he optimizer, the first object after P
+ that is relevant is returned }
+ Function SkipHead(P: Tai): Tai;
+
+ { returns true if the operands o1 and o2 are completely equal }
+ Function OpsEqual(const o1,o2:toper): Boolean;
+
+ { Returns true if a ait_alloc object for Reg is found in the block
+ of Tai's starting with StartPai and ending with the next "real"
+ instruction }
+ Function FindRegAlloc(Reg: TRegister; StartPai: Tai): Boolean;
+
+ { traces sucessive jumps to their final destination and sets it, e.g.
+ je l1 je l3
+ <code> <code>
+ l1: becomes l1:
+ je l2 je l3
+ <code> <code>
+ l2: l2:
+ jmp l3 jmp l3
+
+ the level parameter denotes how deeep we have already followed the jump,
+ to avoid endless loops with constructs such as "l5: ; jmp l5" }
+ function GetFinalDestination(hp: taicpu; level: longint): boolean;
+
+ function getlabelwithsym(sym: tasmlabel): tai;
+
+ { peephole optimizer }
+ procedure PrePeepHoleOpts;
+ procedure PeepHoleOptPass1;
+ procedure PeepHoleOptPass2; virtual;
+ procedure PostPeepHoleOpts;
+
+ { processor dependent methods }
+ // if it returns true, perform a "continue"
+ function PeepHoleOptPass1Cpu(var p: tai): boolean; virtual;
+ function PostPeepHoleOptsCpu(var p: tai): boolean; virtual;
+ End;
+
+ Function ArrayRefsEq(const r1, r2: TReference): Boolean;
+
+ { ***************************** Implementation **************************** }
+
+ Implementation
+
+ uses
+ globals,
+ verbose,
+ procinfo;
+
+ { ************************************************************************* }
+ { ******************************** TUsedRegs ****************************** }
+ { ************************************************************************* }
+
+ Constructor TUsedRegs.create;
+ Begin
+ UsedRegs := [];
+ End;
+
+ Constructor TUsedRegs.create_regset(Const _RegSet: TRegSet);
+ Begin
+ UsedRegs := _RegSet;
+ End;
+
+ Procedure TUsedRegs.Update(p: Tai);
+ {updates UsedRegs with the RegAlloc Information coming after P}
+ Begin
+ Repeat
+ While Assigned(p) And
+ ((p.typ in (SkipInstr - [ait_RegAlloc])) or
+ ((p.typ = ait_label) And
+ Not(Tai_Label(p).labsym.is_used))) Do
+ p := Tai(p.next);
+ While Assigned(p) And
+ (p.typ=ait_RegAlloc) Do
+ Begin
+ {!!!!!!!! FIXME
+ if tai_regalloc(p).ratype=ra_alloc then
+ UsedRegs := UsedRegs + [tai_regalloc(p).Reg]
+ else
+ UsedRegs := UsedRegs - [tai_regalloc(p).Reg];
+ p := Tai(p.next);
+ }
+ End;
+ Until Not(Assigned(p)) Or
+ (Not(p.typ in SkipInstr) And
+ Not((p.typ = ait_label) And
+ Not(Tai_Label(p).labsym.is_used)));
+ End;
+
+ Function TUsedRegs.IsUsed(Reg: TRegister): Boolean;
+ Begin
+ //!!!!!!!!!!! IsUsed := Reg in UsedRegs
+ Result:=False; { unimplemented }
+ End;
+
+ Function TUsedRegs.GetUsedRegs: TRegSet;
+ Begin
+ GetUsedRegs := UsedRegs;
+ End;
+
+ Destructor TUsedRegs.Destroy;
+ Begin
+ inherited destroy;
+ end;
+
+ { ************************************************************************* }
+ { **************************** TPaiProp *********************************** }
+ { ************************************************************************* }
+
+ Constructor TPaiProp.Create;
+ Begin
+ {!!!!!!
+ UsedRegs.Init;
+ CondRegs.init;
+ }
+ { DirFlag: TFlagContents; I386 specific}
+ End;
+
+ Function TPaiProp.RegInSequence(Reg, which: TRegister): Boolean;
+ {
+ Var p: Tai;
+ RegsChecked: TRegSet;
+ content: TContent;
+ Counter: Byte;
+ TmpResult: Boolean;
+ }
+ begin
+ Result:=False; { unimplemented }
+ (*!!!!!!!!!!1
+ RegsChecked := [];
+ content := regs[which];
+ p := content.StartMod;
+ TmpResult := False;
+ Counter := 1;
+ While Not(TmpResult) And
+ (Counter <= Content.NrOfMods) Do
+ Begin
+ If IsLoadMemReg(p) Then
+ With PInstr(p)^.oper[LoadSrc]^.ref^ Do
+ If (Base = ProcInfo.FramePointer)
+ {$ifdef RefsHaveIndexReg}
+ And (Index = R_NO)
+ {$endif RefsHaveIndexReg} Then
+ Begin
+ RegsChecked := RegsChecked +
+ [RegMaxSize(PInstr(p)^.oper[LoadDst]^.reg)];
+ If Reg = RegMaxSize(PInstr(p)^.oper[LoadDst]^.reg) Then
+ Break;
+ End
+ Else
+ Begin
+ If (Base = Reg) And
+ Not(Base In RegsChecked)
+ Then TmpResult := True;
+ {$ifdef RefsHaveIndexReg}
+ If Not(TmpResult) And
+ (Index = Reg) And
+ Not(Index In RegsChecked)
+ Then TmpResult := True;
+ {$Endif RefsHaveIndexReg}
+ End
+ Else TmpResult := RegInInstruction(Reg, p);
+ Inc(Counter);
+ GetNextInstruction(p,p)
+ End;
+ RegInSequence := TmpResult
+ *)
+ End;
+
+
+ Procedure TPaiProp.DestroyReg(Reg: TRegister; var InstrSinceLastMod:
+ TInstrSinceLastMod);
+ { Destroys the contents of the register Reg in the PPaiProp p1, as well as }
+ { the contents of registers are loaded with a memory location based on Reg }
+ {
+ Var TmpWState, TmpRState: Byte;
+ Counter: TRegister;
+ }
+ Begin
+ {!!!!!!!
+ Reg := RegMaxSize(Reg);
+ If (Reg in [LoGPReg..HiGPReg]) Then
+ For Counter := LoGPReg to HiGPReg Do
+ With Regs[Counter] Do
+ If (Counter = reg) Or
+ ((Typ = Con_Ref) And
+ RegInSequence(Reg, Counter)) Then
+ Begin
+ InstrSinceLastMod[Counter] := 0;
+ IncWState(Counter);
+ TmpWState := GetWState(Counter);
+ TmpRState := GetRState(Counter);
+ FillChar(Regs[Counter], SizeOf(TContent), 0);
+ WState := TmpWState;
+ RState := TmpRState
+ End
+ }
+ End;
+
+ Function ArrayRefsEq(const r1, r2: TReference): Boolean;
+ Begin
+ Result:=False; { unimplemented }
+ (*!!!!!!!!!!
+ ArrayRefsEq := (R1.Offset+R1.OffsetFixup = R2.Offset+R2.OffsetFixup) And
+ {$ifdef refsHaveSegmentReg}
+ (R1.Segment = R2.Segment) And
+ {$endif}
+ (R1.Base = R2.Base) And
+ (R1.Symbol=R2.Symbol);
+ *)
+ End;
+
+ Procedure TPaiProp.DestroyRefs(Const Ref: TReference; WhichReg: TRegister;
+ var InstrSinceLastMod: TInstrSinceLastMod);
+ { destroys all registers which possibly contain a reference to Ref, WhichReg }
+ { is the register whose contents are being written to memory (if this proc }
+ { is called because of a "mov?? %reg, (mem)" instruction) }
+ {
+ Var RefsEq: TRefCompare;
+ Counter: TRegister;
+ }
+ Begin
+ (*!!!!!!!!!!!
+ WhichReg := RegMaxSize(WhichReg);
+ If (Ref.base = procinfo.FramePointer) or
+ Assigned(Ref.Symbol) Then
+ Begin
+ If
+ {$ifdef refsHaveIndexReg}
+ (Ref.Index = R_NO) And
+ {$endif refsHaveIndexReg}
+ (Not(Assigned(Ref.Symbol)) or
+ (Ref.base = R_NO)) Then
+ { local variable which is not an array }
+ RefsEq := @RefsEqual
+ Else
+ { local variable which is an array }
+ RefsEq := @ArrayRefsEq;
+ {write something to a parameter, a local or global variable, so
+ * with uncertain optimizations on:
+ - destroy the contents of registers whose contents have somewhere a
+ "mov?? (Ref), %reg". WhichReg (this is the register whose contents
+ are being written to memory) is not destroyed if it's StartMod is
+ of that form and NrOfMods = 1 (so if it holds ref, but is not a
+ pointer or value based on Ref)
+ * with uncertain optimizations off:
+ - also destroy registers that contain any pointer}
+ For Counter := LoGPReg to HiGPReg Do
+ With Regs[Counter] Do
+ Begin
+ If (typ = Con_Ref) And
+ ((Not(cs_opt_size in current_settings.optimizerswitches) And
+ (NrOfMods <> 1)
+ ) Or
+ (RefInSequence(Ref,Regs[Counter], RefsEq) And
+ ((Counter <> WhichReg) Or
+ ((NrOfMods <> 1) And
+ {StarMod is always of the type ait_instruction}
+ (PInstr(StartMod)^.oper[0].typ = top_ref) And
+ RefsEq(PInstr(StartMod)^.oper[0].ref^, Ref)
+ )
+ )
+ )
+ )
+ Then
+ DestroyReg(Counter, InstrSinceLastMod)
+ End
+ End
+ Else
+ {write something to a pointer location, so
+ * with uncertain optimzations on:
+ - do not destroy registers which contain a local/global variable or a
+ parameter, except if DestroyRefs is called because of a "movsl"
+ * with uncertain optimzations off:
+ - destroy every register which contains a memory location
+ }
+ For Counter := LoGPReg to HiGPReg Do
+ With Regs[Counter] Do
+ If (typ = Con_Ref) And
+ (Not(cs_opt_size in current_settings.optimizerswitches) Or
+ {$ifdef x86}
+ {for movsl}
+ (Ref.Base = R_EDI) Or
+ {$endif}
+ {don't destroy if reg contains a parameter, local or global variable}
+ Not((NrOfMods = 1) And
+ (PInstr(StartMod)^.oper[0].typ = top_ref) And
+ ((PInstr(StartMod)^.oper[0].ref^.base = ProcInfo.FramePointer) Or
+ Assigned(PInstr(StartMod)^.oper[0].ref^.Symbol)
+ )
+ )
+ )
+ Then DestroyReg(Counter, InstrSinceLastMod)
+ *)
+ End;
+
+ Procedure TPaiProp.DestroyAllRegs(var InstrSinceLastMod: TInstrSinceLastMod);
+ {Var Counter: TRegister;}
+ Begin {initializes/desrtoys all registers}
+ (*!!!!!!!!!
+ For Counter := LoGPReg To HiGPReg Do
+ Begin
+ ReadReg(Counter);
+ DestroyReg(Counter, InstrSinceLastMod);
+ End;
+ CondRegs.Init;
+ { FPURegs.Init; }
+ *)
+ End;
+
+ Procedure TPaiProp.DestroyOp(const o:Toper; var InstrSinceLastMod:
+ TInstrSinceLastMod);
+ Begin
+ {!!!!!!!
+ Case o.typ Of
+ top_reg: DestroyReg(o.reg, InstrSinceLastMod);
+ top_ref:
+ Begin
+ ReadRef(o.ref);
+ DestroyRefs(o.ref^, R_NO, InstrSinceLastMod);
+ End;
+ top_symbol:;
+ End;
+ }
+ End;
+
+ Procedure TPaiProp.ReadReg(Reg: TRegister);
+ Begin
+ {!!!!!!!
+ Reg := RegMaxSize(Reg);
+ If Reg in General_Registers Then
+ IncRState(RegMaxSize(Reg))
+ }
+ End;
+
+ Procedure TPaiProp.ReadRef(Ref: PReference);
+ Begin
+ (*!!!!!!
+ If Ref^.Base <> R_NO Then
+ ReadReg(Ref^.Base);
+ {$ifdef refsHaveIndexReg}
+ If Ref^.Index <> R_NO Then
+ ReadReg(Ref^.Index);
+ {$endif}
+ *)
+ End;
+
+ Procedure TPaiProp.ReadOp(const o:toper);
+ Begin
+ Case o.typ Of
+ top_reg: ReadReg(o.reg);
+ top_ref: ReadRef(o.ref);
+ else
+ internalerror(200410241);
+ End;
+ End;
+
+ Procedure TPaiProp.ModifyReg(reg: TRegister; Var InstrSinceLastMod:
+ TInstrSinceLastMod);
+ Begin
+ (*!!!!!!!
+ With Regs[reg] Do
+ If (Typ = Con_Ref)
+ Then
+ Begin
+ IncState(WState);
+ {also store how many instructions are part of the sequence in the first
+ instructions PPaiProp, so it can be easily accessed from within
+ CheckSequence}
+ Inc(NrOfMods, InstrSinceLastMod[Reg]);
+ PPaiProp(StartMod.OptInfo)^.Regs[Reg].NrOfMods := NrOfMods;
+ InstrSinceLastMod[Reg] := 0;
+ End
+ Else
+ DestroyReg(Reg, InstrSinceLastMod);
+ *)
+ End;
+
+ Procedure TPaiProp.ModifyOp(const oper: TOper; var InstrSinceLastMod:
+ TInstrSinceLastMod);
+ Begin
+ If oper.typ = top_reg Then
+ ModifyReg(RegMaxSize(oper.reg),InstrSinceLastMod)
+ Else
+ Begin
+ ReadOp(oper);
+ DestroyOp(oper, InstrSinceLastMod);
+ End
+ End;
+
+ Procedure TPaiProp.IncWState(Reg: TRegister);{$ifdef inl} inline;{$endif inl}
+ Begin
+ //!!!! IncState(Regs[Reg].WState);
+ End;
+
+ Procedure TPaiProp.IncRState(Reg: TRegister);{$ifdef inl} inline;{$endif inl}
+ Begin
+ //!!!! IncState(Regs[Reg].RState);
+ End;
+
+ Function TPaiProp.GetWState(Reg: TRegister): TStateInt; {$ifdef inl} inline;{$endif inl}
+ Begin
+ Result:=0; { unimplemented }
+ //!!!! GetWState := Regs[Reg].WState
+ End;
+
+ Function TPaiProp.GetRState(Reg: TRegister): TStateInt; {$ifdef inl} inline;{$endif inl}
+ Begin
+ Result:=0; { unimplemented }
+ //!!!! GetRState := Regs[Reg].RState
+ End;
+
+ Function TPaiProp.GetRegContentType(Reg: TRegister): Byte; {$ifdef inl} inline;{$endif inl}
+ Begin
+ Result:=0; { unimplemented }
+ //!!!! GetRegContentType := Regs[Reg].typ
+ End;
+
+ Destructor TPaiProp.Done;
+ Begin
+ //!!!! UsedRegs.Done;
+ //!!!! CondRegs.Done;
+ { DirFlag: TFlagContents; I386 specific}
+ End;
+ { ************************ private TPaiProp stuff ************************* }
+
+ Procedure TPaiProp.IncState(Var s: TStateInt); {$ifdef inl} inline;{$endif inl}
+ Begin
+ If s <> High(TStateInt) Then Inc(s)
+ Else s := 0
+ End;
+
+ Function TPaiProp.RefInInstruction(Const Ref: TReference; p: Tai;
+ RefsEq: TRefCompare): Boolean;
+ Var Count: AWord;
+ TmpResult: Boolean;
+ Begin
+ TmpResult := False;
+ If (p.typ = ait_instruction) Then
+ Begin
+ Count := 0;
+ Repeat
+ If (TInstr(p).oper[Count]^.typ = Top_Ref) Then
+ TmpResult := RefsEq(Ref, PInstr(p)^.oper[Count]^.ref^);
+ Inc(Count);
+ Until (Count = MaxOps) or TmpResult;
+ End;
+ RefInInstruction := TmpResult;
+ End;
+
+ Function TPaiProp.RefInSequence(Const Ref: TReference; Content: TContent;
+ RefsEq: TRefCompare): Boolean;
+ Var p: Tai;
+ Counter: Byte;
+ TmpResult: Boolean;
+ Begin
+ p := Content.StartMod;
+ TmpResult := False;
+ Counter := 1;
+ While Not(TmpResult) And
+ (Counter <= Content.NrOfMods) Do
+ Begin
+ If (p.typ = ait_instruction) And
+ RefInInstruction(Ref, p, @references_equal)
+ Then TmpResult := True;
+ Inc(Counter);
+ GetNextInstruction(p,p)
+ End;
+ RefInSequence := TmpResult
+ End;
+
+ { ************************************************************************* }
+ { ***************************** TAoptObj ********************************** }
+ { ************************************************************************* }
+
+ Constructor TAoptObj.create(_AsmL: TAsmList; _BlockStart, _BlockEnd: Tai;
+ _LabelInfo: PLabelInfo);
+ Begin
+ AsmL := _AsmL;
+ BlockStart := _BlockStart;
+ BlockEnd := _BlockEnd;
+ LabelInfo := _LabelInfo
+ End;
+
+ Function TAOptObj.FindLabel(L: TasmLabel; Var hp: Tai): Boolean;
+ Var TempP: Tai;
+ Begin
+ TempP := hp;
+ While Assigned(TempP) and
+ (TempP.typ In SkipInstr + [ait_label]) Do
+ If (TempP.typ <> ait_Label) Or
+ (Tai_label(TempP).labsym <> L)
+ Then GetNextInstruction(TempP, TempP)
+ Else
+ Begin
+ hp := TempP;
+ FindLabel := True;
+ exit
+ End;
+ FindLabel := False;
+ End;
+
+ Procedure TAOptObj.InsertLLItem(prev, foll, new_one : TLinkedListItem);
+ Begin
+ If Assigned(prev) Then
+ If Assigned(foll) Then
+ Begin
+ If Assigned(new_one) Then
+ Begin
+ new_one.previous := prev;
+ new_one.next := foll;
+ prev.next := new_one;
+ foll.previous := new_one;
+ { should we update line information? }
+ if (not (tai(new_one).typ in SkipLineInfo)) and
+ (not (tai(foll).typ in SkipLineInfo)) then
+ Tailineinfo(new_one).fileinfo := Tailineinfo(foll).fileinfo
+ End
+ End
+ Else AsmL.Concat(new_one)
+ Else If Assigned(Foll) Then AsmL.Insert(new_one)
+ End;
+
+
+ Function TAOptObj.SkipHead(P: Tai): Tai;
+ Var OldP: Tai;
+ Begin
+ Repeat
+ OldP := P;
+ If (P.typ in SkipInstr) Or
+ ((P.typ = ait_marker) And
+ (Tai_Marker(P).Kind = mark_AsmBlockEnd)) Then
+ GetNextInstruction(P, P)
+ Else If ((P.Typ = Ait_Marker) And
+ (Tai_Marker(P).Kind = mark_NoPropInfoStart)) Then
+ { a marker of the type mark_NoPropInfoStart can't be the first instruction of a }
+ { paasmoutput list }
+ GetNextInstruction(Tai(P.Previous),P);
+ If (P.Typ = Ait_Marker) And
+ (Tai_Marker(P).Kind = mark_AsmBlockStart) Then
+ Begin
+ P := Tai(P.Next);
+ While (P.typ <> Ait_Marker) Or
+ (Tai_Marker(P).Kind <> mark_AsmBlockEnd) Do
+ P := Tai(P.Next)
+ End;
+ Until P = OldP;
+ SkipHead := P;
+ End;
+
+ Function TAOptObj.OpsEqual(const o1,o2:toper): Boolean;
+ Begin
+ if o1.typ=o2.typ then
+ Case o1.typ Of
+ Top_Reg :
+ OpsEqual:=o1.reg=o2.reg;
+ Top_Ref :
+ OpsEqual := references_equal(o1.ref^, o2.ref^);
+ Top_Const :
+ OpsEqual:=o1.val=o2.val;
+ Top_None :
+ OpsEqual := True
+ else OpsEqual := False
+ End;
+ End;
+
+ Function TAOptObj.FindRegAlloc(Reg: TRegister; StartPai: Tai): Boolean;
+ Begin
+ FindRegAlloc:=False;
+ Repeat
+ While Assigned(StartPai) And
+ ((StartPai.typ in (SkipInstr - [ait_regAlloc])) Or
+ ((StartPai.typ = ait_label) and
+ Not(Tai_Label(StartPai).labsym.Is_Used))) Do
+ StartPai := Tai(StartPai.Next);
+ If Assigned(StartPai) And
+ (StartPai.typ = ait_regAlloc) and (tai_regalloc(StartPai).ratype=ra_alloc) Then
+ Begin
+ if tai_regalloc(StartPai).Reg = Reg then
+ begin
+ FindRegAlloc:=true;
+ exit;
+ end;
+ StartPai := Tai(StartPai.Next);
+ End
+ else
+ exit;
+ Until false;
+ End;
+
+
+ function SkipLabels(hp: tai; var hp2: tai): boolean;
+ {skips all labels and returns the next "real" instruction}
+ begin
+ while assigned(hp.next) and
+ (tai(hp.next).typ in SkipInstr + [ait_label,ait_align]) Do
+ hp := tai(hp.next);
+ if assigned(hp.next) then
+ begin
+ SkipLabels := True;
+ hp2 := tai(hp.next)
+ end
+ else
+ begin
+ hp2 := hp;
+ SkipLabels := False
+ end;
+ end;
+
+
+ function FindAnyLabel(hp: tai; var l: tasmlabel): Boolean;
+ begin
+ FindAnyLabel := false;
+ while assigned(hp.next) and
+ (tai(hp.next).typ in (SkipInstr+[ait_align])) Do
+ hp := tai(hp.next);
+ if assigned(hp.next) and
+ (tai(hp.next).typ = ait_label) then
+ begin
+ FindAnyLabel := true;
+ l := tai_label(hp.next).labsym;
+ end
+ end;
+
+
+{$push}
+{$r-}
+ function tAOptObj.getlabelwithsym(sym: tasmlabel): tai;
+ begin
+ if (int64(sym.labelnr) >= int64(labelinfo^.lowlabel)) and
+ (int64(sym.labelnr) <= int64(labelinfo^.highlabel)) then { range check, a jump can go past an assembler block! }
+ getlabelwithsym := labelinfo^.labeltable^[sym.labelnr-labelinfo^.lowlabel].paiobj
+ else
+ getlabelwithsym := nil;
+ end;
+{$pop}
+
+ function TAOptObj.GetFinalDestination(hp: taicpu; level: longint): boolean;
+ {traces sucessive jumps to their final destination and sets it, e.g.
+ je l1 je l3
+ <code> <code>
+ l1: becomes l1:
+ je l2 je l3
+ <code> <code>
+ l2: l2:
+ jmp l3 jmp l3
+
+ the level parameter denotes how deeep we have already followed the jump,
+ to avoid endless loops with constructs such as "l5: ; jmp l5" }
+
+ var p1, p2: tai;
+ l: tasmlabel;
+
+ begin
+ GetfinalDestination := false;
+ if level > 20 then
+ exit;
+ p1 := getlabelwithsym(tasmlabel(hp.oper[0]^.ref^.symbol));
+ if assigned(p1) then
+ begin
+ SkipLabels(p1,p1);
+ if (tai(p1).typ = ait_instruction) and
+ (taicpu(p1).is_jmp) then
+ if { the next instruction after the label where the jump hp arrives}
+ { is unconditional or of the same type as hp, so continue }
+ (((taicpu(p1).opcode = aopt_uncondjmp) and
+{$ifdef arm}
+ (taicpu(p1).condition = C_None) and
+{$endif arm}
+ (taicpu(p1).oper[0]^.typ = top_ref) and
+ (assigned(taicpu(p1).oper[0]^.ref^.symbol)) and
+ (taicpu(p1).oper[0]^.ref^.symbol is TAsmLabel)) or
+ conditions_equal(taicpu(p1).condition,hp.condition)) or
+ { the next instruction after the label where the jump hp arrives}
+ { is the opposite of hp (so this one is never taken), but after }
+ { that one there is a branch that will be taken, so perform a }
+ { little hack: set p1 equal to this instruction (that's what the}
+ { last SkipLabels is for, only works with short bool evaluation)}
+ (conditions_equal(taicpu(p1).condition,inverse_cond(hp.condition)) and
+ SkipLabels(p1,p2) and
+ (p2.typ = ait_instruction) and
+ (taicpu(p2).is_jmp) and
+ (((taicpu(p2).opcode = aopt_uncondjmp) and
+{$ifdef arm}
+ (taicpu(p1).condition = C_None) and
+{$endif arm}
+ (taicpu(p2).oper[0]^.typ = top_ref) and
+ (assigned(taicpu(p2).oper[0]^.ref^.symbol)) and
+ (taicpu(p2).oper[0]^.ref^.symbol is TAsmLabel)) or
+ (conditions_equal(taicpu(p2).condition,hp.condition))) and
+ SkipLabels(p1,p1)) then
+ begin
+ { quick check for loops of the form "l5: ; jmp l5 }
+ if (tasmlabel(taicpu(p1).oper[0]^.ref^.symbol).labelnr =
+ tasmlabel(hp.oper[0]^.ref^.symbol).labelnr) then
+ exit;
+ if not GetFinalDestination(taicpu(p1),succ(level)) then
+ exit;
+ tasmlabel(hp.oper[0]^.ref^.symbol).decrefs;
+ hp.oper[0]^.ref^.symbol:=taicpu(p1).oper[0]^.ref^.symbol;
+ tasmlabel(hp.oper[0]^.ref^.symbol).increfs;
+ end
+ else
+ if conditions_equal(taicpu(p1).condition,inverse_cond(hp.condition)) then
+ if not FindAnyLabel(p1,l) then
+ begin
+ {$ifdef finaldestdebug}
+ insertllitem(asml,p1,p1.next,tai_comment.Create(
+ strpnew('previous label inserted'))));
+ {$endif finaldestdebug}
+ current_asmdata.getjumplabel(l);
+ insertllitem(p1,p1.next,tai_label.Create(l));
+ tasmlabel(taicpu(hp).oper[0]^.ref^.symbol).decrefs;
+ hp.oper[0]^.ref^.symbol := l;
+ l.increfs;
+ { this won't work, since the new label isn't in the labeltable }
+ { so it will fail the rangecheck. Labeltable should become a }
+ { hashtable to support this: }
+ { GetFinalDestination(asml, hp); }
+ end
+ else
+ begin
+ {$ifdef finaldestdebug}
+ insertllitem(asml,p1,p1.next,tai_comment.Create(
+ strpnew('next label reused'))));
+ {$endif finaldestdebug}
+ l.increfs;
+ tasmlabel(hp.oper[0]^.ref^.symbol).decrefs;
+ hp.oper[0]^.ref^.symbol := l;
+ if not GetFinalDestination(hp,succ(level)) then
+ exit;
+ end;
+ end;
+ GetFinalDestination := true;
+ end;
+
+
+ procedure TAOptObj.PrePeepHoleOpts;
+ begin
+ end;
+
+
+ procedure TAOptObj.PeepHoleOptPass1;
+ var
+ p,hp1,hp2 : tai;
+ begin
+ p := BlockStart;
+ //!!!! UsedRegs := [];
+ while (p <> BlockEnd) Do
+ begin
+ //!!!! UpDateUsedRegs(UsedRegs, tai(p.next));
+ if PeepHoleOptPass1Cpu(p) then
+ continue;
+ case p.Typ Of
+ ait_instruction:
+ begin
+ { Handle Jmp Optimizations }
+ if taicpu(p).is_jmp then
+ begin
+ { the following if-block removes all code between a jmp and the next label,
+ because it can never be executed
+ }
+ if (taicpu(p).opcode = aopt_uncondjmp) and
+{$ifdef arm}
+ (taicpu(p).condition = C_None) and
+{$endif arm}
+ (taicpu(p).oper[0]^.typ = top_ref) and
+ (assigned(taicpu(p).oper[0]^.ref^.symbol)) and
+ (taicpu(p).oper[0]^.ref^.symbol is TAsmLabel) then
+ begin
+ while GetNextInstruction(p, hp1) and
+ (hp1.typ <> ait_label) do
+ if not(hp1.typ in ([ait_label,ait_align]+skipinstr)) then
+ begin
+ if (hp1.typ = ait_instruction) and
+ taicpu(hp1).is_jmp and
+ (taicpu(hp1).oper[0]^.typ = top_ref) and
+ assigned(taicpu(hp1).oper[0]^.ref^.symbol) and
+ (taicpu(hp1).oper[0]^.ref^.symbol is TAsmLabel) then
+ TAsmLabel(taicpu(hp1).oper[0]^.ref^.symbol).decrefs;
+ asml.remove(hp1);
+ hp1.free;
+ end
+ else break;
+ end;
+ { remove jumps to a label coming right after them }
+ if GetNextInstruction(p, hp1) then
+ begin
+ if FindLabel(tasmlabel(taicpu(p).oper[0]^.ref^.symbol), hp1) and
+ { TODO: FIXME removing the first instruction fails}
+ (p<>blockstart) then
+ begin
+ hp2:=tai(hp1.next);
+ asml.remove(p);
+ tasmlabel(taicpu(p).oper[0]^.ref^.symbol).decrefs;
+ p.free;
+ p:=hp2;
+ continue;
+ end
+ else
+ begin
+ if hp1.typ = ait_label then
+ SkipLabels(hp1,hp1);
+ if (tai(hp1).typ=ait_instruction) and
+ (taicpu(hp1).opcode=aopt_uncondjmp) and
+{$ifdef arm}
+ (taicpu(hp1).condition=C_None) and
+{$endif arm}
+ (taicpu(hp1).oper[0]^.typ = top_ref) and
+ (assigned(taicpu(hp1).oper[0]^.ref^.symbol)) and
+ (taicpu(hp1).oper[0]^.ref^.symbol is TAsmLabel) and
+ GetNextInstruction(hp1, hp2) and
+ FindLabel(tasmlabel(taicpu(p).oper[0]^.ref^.symbol), hp2) then
+ begin
+ if (taicpu(p).opcode=aopt_condjmp)
+{$ifdef arm}
+ and (taicpu(p).condition<>C_None)
+{$endif arm}
+ then
+ begin
+ taicpu(p).condition:=inverse_cond(taicpu(p).condition);
+ tai_label(hp2).labsym.decrefs;
+ taicpu(p).oper[0]^.ref^.symbol:=taicpu(hp1).oper[0]^.ref^.symbol;
+ { when freeing hp1, the reference count
+ isn't decreased, so don't increase
+
+ taicpu(p).oper[0]^.ref^.symbol.increfs;
+ }
+{$ifdef SPARC}
+ hp2:=tai(hp1.next);
+ asml.remove(hp2);
+ hp2.free;
+{$endif SPARC}
+ asml.remove(hp1);
+ hp1.free;
+ GetFinalDestination(taicpu(p),0);
+ end
+ else
+ begin
+ GetFinalDestination(taicpu(p),0);
+ p:=tai(p.next);
+ continue;
+ end;
+ end
+ else
+ GetFinalDestination(taicpu(p),0);
+ end;
+ end;
+ end
+ else
+ { All other optimizes }
+ begin
+ end; { if is_jmp }
+ end;
+ end;
+ //!!!!!!!! updateUsedRegs(UsedRegs,p);
+ p:=tai(p.next);
+ end;
+ end;
+
+
+ procedure TAOptObj.PeepHoleOptPass2;
+ begin
+ end;
+
+
+ procedure TAOptObj.PostPeepHoleOpts;
+ var
+ p: tai;
+ begin
+ p := BlockStart;
+ //!!!! UsedRegs := [];
+ while (p <> BlockEnd) Do
+ begin
+ //!!!! UpDateUsedRegs(UsedRegs, tai(p.next));
+ if PostPeepHoleOptsCpu(p) then
+ continue;
+ //!!!!!!!! updateUsedRegs(UsedRegs,p);
+ p:=tai(p.next);
+ end;
+ end;
+
+
+ function TAOptObj.PeepHoleOptPass1Cpu(var p: tai): boolean;
+ begin
+ result := false;
+ end;
+
+
+ function TAOptObj.PostPeepHoleOptsCpu(var p: tai): boolean;
+ begin
+ result := false;
+ end;
+
+End.
diff --git a/closures/compiler/arm/aasmcpu.pas b/closures/compiler/arm/aasmcpu.pas
new file mode 100644
index 0000000000..5ced8fc361
--- /dev/null
+++ b/closures/compiler/arm/aasmcpu.pas
@@ -0,0 +1,2807 @@
+{
+ Copyright (c) 2003 by Florian Klaempfl
+
+ Contains the assembler object for the ARM
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit aasmcpu;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ cclasses,globtype,globals,verbose,
+ aasmbase,aasmtai,aasmdata,aasmsym,
+ ogbase,
+ symtype,
+ cpubase,cpuinfo,cgbase,cgutils;
+
+ const
+ { "mov reg,reg" source operand number }
+ O_MOV_SOURCE = 1;
+ { "mov reg,reg" source operand number }
+ O_MOV_DEST = 0;
+
+ { Operand types }
+ OT_NONE = $00000000;
+
+ OT_BITS8 = $00000001; { size, and other attributes, of the operand }
+ OT_BITS16 = $00000002;
+ OT_BITS32 = $00000004;
+ OT_BITS64 = $00000008; { FPU only }
+ OT_BITS80 = $00000010;
+ OT_FAR = $00000020; { this means 16:16 or 16:32, like in CALL/JMP }
+ OT_NEAR = $00000040;
+ OT_SHORT = $00000080;
+ OT_BITSTINY = $00000100; { fpu constant }
+ OT_BITSSHIFTER =
+ $00000200;
+
+ OT_SIZE_MASK = $000003FF; { all the size attributes }
+ OT_NON_SIZE = longint(not OT_SIZE_MASK);
+
+ OT_SIGNED = $00000100; { the operand need to be signed -128-127 }
+
+ OT_TO = $00000200; { operand is followed by a colon }
+ { reverse effect in FADD, FSUB &c }
+ OT_COLON = $00000400;
+
+ OT_SHIFTEROP = $00000800;
+ OT_REGISTER = $00001000;
+ OT_IMMEDIATE = $00002000;
+ OT_REGLIST = $00008000;
+ OT_IMM8 = $00002001;
+ OT_IMM24 = $00002002;
+ OT_IMM32 = $00002004;
+ OT_IMM64 = $00002008;
+ OT_IMM80 = $00002010;
+ OT_IMMTINY = $00002100;
+ OT_IMMSHIFTER= $00002200;
+ OT_IMMEDIATE24 = OT_IMM24;
+ OT_SHIFTIMM = OT_SHIFTEROP or OT_IMMSHIFTER;
+ OT_SHIFTIMMEDIATE = OT_SHIFTIMM;
+ OT_IMMEDIATESHIFTER = OT_IMMSHIFTER;
+
+ OT_IMMEDIATEFPU = OT_IMMTINY;
+
+ OT_REGMEM = $00200000; { for r/m, ie EA, operands }
+ OT_REGNORM = $00201000; { 'normal' reg, qualifies as EA }
+ OT_REG8 = $00201001;
+ OT_REG16 = $00201002;
+ OT_REG32 = $00201004;
+ OT_REG64 = $00201008;
+ OT_VREG = $00201010; { vector register }
+ OT_REGF = $00201020; { coproc register }
+ OT_MEMORY = $00204000; { register number in 'basereg' }
+ OT_MEM8 = $00204001;
+ OT_MEM16 = $00204002;
+ OT_MEM32 = $00204004;
+ OT_MEM64 = $00204008;
+ OT_MEM80 = $00204010;
+ { word/byte load/store }
+ OT_AM2 = $00010000;
+ { misc ld/st operations }
+ OT_AM3 = $00020000;
+ { multiple ld/st operations }
+ OT_AM4 = $00040000;
+ { co proc. ld/st operations }
+ OT_AM5 = $00080000;
+ OT_AMMASK = $000f0000;
+ { IT instruction }
+ OT_CONDITION = $00100000;
+
+ OT_MEMORYAM2 = OT_MEMORY or OT_AM2;
+ OT_MEMORYAM3 = OT_MEMORY or OT_AM3;
+ OT_MEMORYAM4 = OT_MEMORY or OT_AM4;
+ OT_MEMORYAM5 = OT_MEMORY or OT_AM5;
+
+ OT_FPUREG = $01000000; { floating point stack registers }
+ OT_REG_SMASK = $00070000; { special register operands: these may be treated differently }
+ { a mask for the following }
+
+ OT_MEM_OFFS = $00604000; { special type of EA }
+ { simple [address] offset }
+ OT_ONENESS = $00800000; { special type of immediate operand }
+ { so UNITY == IMMEDIATE | ONENESS }
+ OT_UNITY = $00802000; { for shift/rotate instructions }
+
+ instabentries = {$i armnop.inc}
+
+ maxinfolen = 5;
+
+ IF_NONE = $00000000;
+
+ IF_ARMMASK = $000F0000;
+ IF_ARM7 = $00070000;
+ IF_FPMASK = $00F00000;
+ IF_FPA = $00100000;
+
+ { if the instruction can change in a second pass }
+ IF_PASS2 = longint($80000000);
+
+ type
+ TInsTabCache=array[TasmOp] of longint;
+ PInsTabCache=^TInsTabCache;
+
+ tinsentry = record
+ opcode : tasmop;
+ ops : byte;
+ optypes : array[0..3] of longint;
+ code : array[0..maxinfolen] of char;
+ flags : longint;
+ end;
+
+ pinsentry=^tinsentry;
+
+ const
+ InsTab : array[0..instabentries-1] of TInsEntry={$i armtab.inc}
+
+ var
+ InsTabCache : PInsTabCache;
+
+ type
+ taicpu = class(tai_cpu_abstract_sym)
+ oppostfix : TOpPostfix;
+ wideformat : boolean;
+ roundingmode : troundingmode;
+ procedure loadshifterop(opidx:longint;const so:tshifterop);
+ procedure loadregset(opidx:longint; regsetregtype: tregistertype; regsetsubregtype: tsubregister; const s:tcpuregisterset);
+ procedure loadconditioncode(opidx:longint;const cond:tasmcond);
+ procedure loadmodeflags(opidx:longint;const flags:tcpumodeflags);
+ constructor op_none(op : tasmop);
+
+ constructor op_reg(op : tasmop;_op1 : tregister);
+ constructor op_ref(op : tasmop;const _op1 : treference);
+ constructor op_const(op : tasmop;_op1 : longint);
+
+ constructor op_reg_reg(op : tasmop;_op1,_op2 : tregister);
+ constructor op_reg_ref(op : tasmop;_op1 : tregister;const _op2 : treference);
+ constructor op_reg_const(op:tasmop; _op1: tregister; _op2: aint);
+
+ constructor op_ref_regset(op:tasmop; _op1: treference; regtype: tregistertype; subreg: tsubregister; _op2: tcpuregisterset);
+
+ constructor op_reg_reg_reg(op : tasmop;_op1,_op2,_op3 : tregister);
+ constructor op_reg_reg_const(op : tasmop;_op1,_op2 : tregister; _op3: aint);
+ constructor op_reg_reg_sym_ofs(op : tasmop;_op1,_op2 : tregister; _op3: tasmsymbol;_op3ofs: longint);
+ constructor op_reg_reg_ref(op : tasmop;_op1,_op2 : tregister; const _op3: treference);
+ constructor op_reg_reg_shifterop(op : tasmop;_op1,_op2 : tregister;_op3 : tshifterop);
+ constructor op_reg_reg_reg_shifterop(op : tasmop;_op1,_op2,_op3 : tregister;_op4 : tshifterop);
+ { SFM/LFM }
+ constructor op_reg_const_ref(op : tasmop;_op1 : tregister;_op2 : aint;_op3 : treference);
+
+ { ITxxx }
+ constructor op_cond(op: tasmop; cond: tasmcond);
+
+ { CPSxx }
+ constructor op_modeflags(op: tasmop; flags: tcpumodeflags);
+ constructor op_modeflags_const(op: tasmop; flags: tcpumodeflags; a: aint);
+
+ { *M*LL }
+ constructor op_reg_reg_reg_reg(op : tasmop;_op1,_op2,_op3,_op4 : tregister);
+
+ { this is for Jmp instructions }
+ constructor op_cond_sym(op : tasmop;cond:TAsmCond;_op1 : tasmsymbol);
+
+ constructor op_sym(op : tasmop;_op1 : tasmsymbol);
+ constructor op_sym_ofs(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint);
+ constructor op_reg_sym_ofs(op : tasmop;_op1 : tregister;_op2:tasmsymbol;_op2ofs : longint);
+ constructor op_sym_ofs_ref(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint;const _op2 : treference);
+
+ function is_same_reg_move(regtype: Tregistertype):boolean; override;
+
+ function spilling_get_operation_type(opnr: longint): topertype;override;
+
+ { assembler }
+ public
+ { the next will reset all instructions that can change in pass 2 }
+ procedure ResetPass1;override;
+ procedure ResetPass2;override;
+ function CheckIfValid:boolean;
+ function GetString:string;
+ function Pass1(objdata:TObjData):longint;override;
+ procedure Pass2(objdata:TObjData);override;
+ protected
+ procedure ppuloadoper(ppufile:tcompilerppufile;var o:toper);override;
+ procedure ppuwriteoper(ppufile:tcompilerppufile;const o:toper);override;
+ procedure ppubuildderefimploper(var o:toper);override;
+ procedure ppuderefoper(var o:toper);override;
+ private
+ { next fields are filled in pass1, so pass2 is faster }
+ inssize : shortint;
+ insoffset : longint;
+ LastInsOffset : longint; { need to be public to be reset }
+ insentry : PInsEntry;
+ function InsEnd:longint;
+ procedure create_ot(objdata:TObjData);
+ function Matches(p:PInsEntry):longint;
+ function calcsize(p:PInsEntry):shortint;
+ procedure gencode(objdata:TObjData);
+ function NeedAddrPrefix(opidx:byte):boolean;
+ procedure Swapoperands;
+ function FindInsentry(objdata:TObjData):boolean;
+ end;
+
+ tai_align = class(tai_align_abstract)
+ { nothing to add }
+ end;
+
+ tai_thumb_func = class(tai)
+ constructor create;
+ end;
+
+ function spilling_create_load(const ref:treference;r:tregister):Taicpu;
+ function spilling_create_store(r:tregister; const ref:treference):Taicpu;
+
+ function setoppostfix(i : taicpu;pf : toppostfix) : taicpu;
+ function setroundingmode(i : taicpu;rm : troundingmode) : taicpu;
+ function setcondition(i : taicpu;c : tasmcond) : taicpu;
+
+ { inserts pc relative symbols at places where they are reachable
+ and transforms special instructions to valid instruction encodings }
+ procedure finalizearmcode(list,listtoinsert : TAsmList);
+ { inserts .pdata section and dummy function prolog needed for arm-wince exception handling }
+ procedure InsertPData;
+
+ procedure InitAsm;
+ procedure DoneAsm;
+
+
+implementation
+
+ uses
+ cutils,rgobj,itcpugas;
+
+
+ procedure taicpu.loadshifterop(opidx:longint;const so:tshifterop);
+ begin
+ allocate_oper(opidx+1);
+ with oper[opidx]^ do
+ begin
+ if typ<>top_shifterop then
+ begin
+ clearop(opidx);
+ new(shifterop);
+ end;
+ shifterop^:=so;
+ typ:=top_shifterop;
+ if assigned(add_reg_instruction_hook) then
+ add_reg_instruction_hook(self,shifterop^.rs);
+ end;
+ end;
+
+
+ procedure taicpu.loadregset(opidx:longint; regsetregtype: tregistertype; regsetsubregtype: tsubregister; const s:tcpuregisterset);
+ var
+ i : byte;
+ begin
+ allocate_oper(opidx+1);
+ with oper[opidx]^ do
+ begin
+ if typ<>top_regset then
+ begin
+ clearop(opidx);
+ new(regset);
+ end;
+ regset^:=s;
+ regtyp:=regsetregtype;
+ subreg:=regsetsubregtype;
+ typ:=top_regset;
+ case regsetregtype of
+ R_INTREGISTER:
+ for i:=RS_R0 to RS_R15 do
+ begin
+ if assigned(add_reg_instruction_hook) and (i in regset^) then
+ add_reg_instruction_hook(self,newreg(R_INTREGISTER,i,regsetsubregtype));
+ end;
+ R_MMREGISTER:
+ { both RS_S0 and RS_D0 range from 0 to 31 }
+ for i:=RS_D0 to RS_D31 do
+ begin
+ if assigned(add_reg_instruction_hook) and (i in regset^) then
+ add_reg_instruction_hook(self,newreg(R_MMREGISTER,i,regsetsubregtype));
+ end;
+ end;
+ end;
+ end;
+
+
+ procedure taicpu.loadconditioncode(opidx:longint;const cond:tasmcond);
+ begin
+ allocate_oper(opidx+1);
+ with oper[opidx]^ do
+ begin
+ if typ<>top_conditioncode then
+ clearop(opidx);
+ cc:=cond;
+ typ:=top_conditioncode;
+ end;
+ end;
+
+ procedure taicpu.loadmodeflags(opidx: longint; const flags: tcpumodeflags);
+ begin
+ allocate_oper(opidx+1);
+ with oper[opidx]^ do
+ begin
+ if typ<>top_modeflags then
+ clearop(opidx);
+ modeflags:=flags;
+ typ:=top_modeflags;
+ end;
+ end;
+
+{*****************************************************************************
+ taicpu Constructors
+*****************************************************************************}
+
+ constructor taicpu.op_none(op : tasmop);
+ begin
+ inherited create(op);
+ end;
+
+
+ { for pld }
+ constructor taicpu.op_ref(op : tasmop;const _op1 : treference);
+ begin
+ inherited create(op);
+ ops:=1;
+ loadref(0,_op1);
+ end;
+
+
+ constructor taicpu.op_reg(op : tasmop;_op1 : tregister);
+ begin
+ inherited create(op);
+ ops:=1;
+ loadreg(0,_op1);
+ end;
+
+
+ constructor taicpu.op_const(op : tasmop;_op1 : longint);
+ begin
+ inherited create(op);
+ ops:=1;
+ loadconst(0,aint(_op1));
+ end;
+
+
+ constructor taicpu.op_reg_reg(op : tasmop;_op1,_op2 : tregister);
+ begin
+ inherited create(op);
+ ops:=2;
+ loadreg(0,_op1);
+ loadreg(1,_op2);
+ end;
+
+
+ constructor taicpu.op_reg_const(op:tasmop; _op1: tregister; _op2: aint);
+ begin
+ inherited create(op);
+ ops:=2;
+ loadreg(0,_op1);
+ loadconst(1,aint(_op2));
+ end;
+
+
+ constructor taicpu.op_ref_regset(op:tasmop; _op1: treference; regtype: tregistertype; subreg: tsubregister; _op2: tcpuregisterset);
+ begin
+ inherited create(op);
+ ops:=2;
+ loadref(0,_op1);
+ loadregset(1,regtype,subreg,_op2);
+ end;
+
+
+ constructor taicpu.op_reg_ref(op : tasmop;_op1 : tregister;const _op2 : treference);
+ begin
+ inherited create(op);
+ ops:=2;
+ loadreg(0,_op1);
+ loadref(1,_op2);
+ end;
+
+
+ constructor taicpu.op_reg_reg_reg(op : tasmop;_op1,_op2,_op3 : tregister);
+ begin
+ inherited create(op);
+ ops:=3;
+ loadreg(0,_op1);
+ loadreg(1,_op2);
+ loadreg(2,_op3);
+ end;
+
+
+ constructor taicpu.op_reg_reg_reg_reg(op : tasmop;_op1,_op2,_op3,_op4 : tregister);
+ begin
+ inherited create(op);
+ ops:=4;
+ loadreg(0,_op1);
+ loadreg(1,_op2);
+ loadreg(2,_op3);
+ loadreg(3,_op4);
+ end;
+
+
+ constructor taicpu.op_reg_reg_const(op : tasmop;_op1,_op2 : tregister; _op3: aint);
+ begin
+ inherited create(op);
+ ops:=3;
+ loadreg(0,_op1);
+ loadreg(1,_op2);
+ loadconst(2,aint(_op3));
+ end;
+
+
+ constructor taicpu.op_reg_const_ref(op : tasmop;_op1 : tregister;_op2 : aint;_op3 : treference);
+ begin
+ inherited create(op);
+ ops:=3;
+ loadreg(0,_op1);
+ loadconst(1,_op2);
+ loadref(2,_op3);
+ end;
+
+
+ constructor taicpu.op_cond(op: tasmop; cond: tasmcond);
+ begin
+ inherited create(op);
+ ops:=0;
+ condition := cond;
+ end;
+
+ constructor taicpu.op_modeflags(op: tasmop; flags: tcpumodeflags);
+ begin
+ inherited create(op);
+ ops := 1;
+ loadmodeflags(0,flags);
+ end;
+
+ constructor taicpu.op_modeflags_const(op: tasmop; flags: tcpumodeflags; a: aint);
+ begin
+ inherited create(op);
+ ops := 2;
+ loadmodeflags(0,flags);
+ loadconst(1,a);
+ end;
+
+
+ constructor taicpu.op_reg_reg_sym_ofs(op : tasmop;_op1,_op2 : tregister; _op3: tasmsymbol;_op3ofs: longint);
+ begin
+ inherited create(op);
+ ops:=3;
+ loadreg(0,_op1);
+ loadreg(1,_op2);
+ loadsymbol(0,_op3,_op3ofs);
+ end;
+
+
+ constructor taicpu.op_reg_reg_ref(op : tasmop;_op1,_op2 : tregister; const _op3: treference);
+ begin
+ inherited create(op);
+ ops:=3;
+ loadreg(0,_op1);
+ loadreg(1,_op2);
+ loadref(2,_op3);
+ end;
+
+
+ constructor taicpu.op_reg_reg_shifterop(op : tasmop;_op1,_op2 : tregister;_op3 : tshifterop);
+ begin
+ inherited create(op);
+ ops:=3;
+ loadreg(0,_op1);
+ loadreg(1,_op2);
+ loadshifterop(2,_op3);
+ end;
+
+
+ constructor taicpu.op_reg_reg_reg_shifterop(op : tasmop;_op1,_op2,_op3 : tregister;_op4 : tshifterop);
+ begin
+ inherited create(op);
+ ops:=4;
+ loadreg(0,_op1);
+ loadreg(1,_op2);
+ loadreg(2,_op3);
+ loadshifterop(3,_op4);
+ end;
+
+
+ constructor taicpu.op_cond_sym(op : tasmop;cond:TAsmCond;_op1 : tasmsymbol);
+ begin
+ inherited create(op);
+ condition:=cond;
+ ops:=1;
+ loadsymbol(0,_op1,0);
+ end;
+
+
+ constructor taicpu.op_sym(op : tasmop;_op1 : tasmsymbol);
+ begin
+ inherited create(op);
+ ops:=1;
+ loadsymbol(0,_op1,0);
+ end;
+
+
+ constructor taicpu.op_sym_ofs(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint);
+ begin
+ inherited create(op);
+ ops:=1;
+ loadsymbol(0,_op1,_op1ofs);
+ end;
+
+
+ constructor taicpu.op_reg_sym_ofs(op : tasmop;_op1 : tregister;_op2:tasmsymbol;_op2ofs : longint);
+ begin
+ inherited create(op);
+ ops:=2;
+ loadreg(0,_op1);
+ loadsymbol(1,_op2,_op2ofs);
+ end;
+
+
+ constructor taicpu.op_sym_ofs_ref(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint;const _op2 : treference);
+ begin
+ inherited create(op);
+ ops:=2;
+ loadsymbol(0,_op1,_op1ofs);
+ loadref(1,_op2);
+ end;
+
+
+ function taicpu.is_same_reg_move(regtype: Tregistertype):boolean;
+ begin
+ { allow the register allocator to remove unnecessary moves }
+ result:=(((opcode=A_MOV) and (regtype = R_INTREGISTER)) or
+ ((opcode=A_MVF) and (regtype = R_FPUREGISTER) and (oppostfix in [PF_None,PF_D])) or
+ (((opcode=A_FCPYS) or (opcode=A_FCPYD)) and (regtype = R_MMREGISTER))
+ ) and
+ (condition=C_None) and
+ (ops=2) and
+ (oper[0]^.typ=top_reg) and
+ (oper[1]^.typ=top_reg) and
+ (oper[0]^.reg=oper[1]^.reg);
+ end;
+
+
+ function spilling_create_load(const ref:treference;r:tregister):Taicpu;
+ var
+ op: tasmop;
+ begin
+ case getregtype(r) of
+ R_INTREGISTER :
+ result:=taicpu.op_reg_ref(A_LDR,r,ref);
+ R_FPUREGISTER :
+ { use lfm because we don't know the current internal format
+ and avoid exceptions
+ }
+ result:=taicpu.op_reg_const_ref(A_LFM,r,1,ref);
+ R_MMREGISTER :
+ begin
+ case getsubreg(r) of
+ R_SUBFD:
+ op:=A_FLDD;
+ R_SUBFS:
+ op:=A_FLDS;
+ else
+ internalerror(2009112905);
+ end;
+ result:=taicpu.op_reg_ref(op,r,ref);
+ end;
+ else
+ internalerror(200401041);
+ end;
+ end;
+
+
+ function spilling_create_store(r:tregister; const ref:treference):Taicpu;
+ var
+ op: tasmop;
+ begin
+ case getregtype(r) of
+ R_INTREGISTER :
+ result:=taicpu.op_reg_ref(A_STR,r,ref);
+ R_FPUREGISTER :
+ { use sfm because we don't know the current internal format
+ and avoid exceptions
+ }
+ result:=taicpu.op_reg_const_ref(A_SFM,r,1,ref);
+ R_MMREGISTER :
+ begin
+ case getsubreg(r) of
+ R_SUBFD:
+ op:=A_FSTD;
+ R_SUBFS:
+ op:=A_FSTS;
+ else
+ internalerror(2009112904);
+ end;
+ result:=taicpu.op_reg_ref(op,r,ref);
+ end;
+ else
+ internalerror(200401041);
+ end;
+ end;
+
+
+ function taicpu.spilling_get_operation_type(opnr: longint): topertype;
+ begin
+ case opcode of
+ A_ADC,A_ADD,A_AND,
+ A_EOR,A_CLZ,
+ A_LDR,A_LDRB,A_LDRBT,A_LDRH,A_LDRSB,
+ A_LDRSH,A_LDRT,
+ A_MOV,A_MVN,A_MLA,A_MUL,
+ A_ORR,A_RSB,A_RSC,A_SBC,A_SUB,
+ A_SWP,A_SWPB,
+ A_LDF,A_FLT,A_FIX,
+ A_ADF,A_DVF,A_FDV,A_FML,
+ A_RFS,A_RFC,A_RDF,
+ A_RMF,A_RPW,A_RSF,A_SUF,A_ABS,A_ACS,A_ASN,A_ATN,A_COS,
+ A_EXP,A_LOG,A_LGN,A_MVF,A_MNF,A_FRD,A_MUF,A_POL,A_RND,A_SIN,A_SQT,A_TAN,
+ A_LFM,
+ A_FLDS,A_FLDD,
+ A_FMRX,A_FMXR,A_FMSTAT,
+ A_FMSR,A_FMRS,A_FMDRR,
+ A_FCPYS,A_FCPYD,A_FCVTSD,A_FCVTDS,
+ A_FABSS,A_FABSD,A_FSQRTS,A_FSQRTD,A_FMULS,A_FMULD,
+ A_FADDS,A_FADDD,A_FSUBS,A_FSUBD,A_FDIVS,A_FDIVD,
+ A_FMACS,A_FMACD,A_FMSCS,A_FMSCD,A_FNMACS,A_FNMACD,
+ A_FNMSCS,A_FNMSCD,A_FNMULS,A_FNMULD,
+ A_FMDHR,A_FMRDH,A_FMDLR,A_FMRDL,
+ A_FNEGS,A_FNEGD,
+ A_FSITOS,A_FSITOD,A_FTOSIS,A_FTOSID,
+ A_FTOUIS,A_FTOUID,A_FUITOS,A_FUITOD:
+ if opnr=0 then
+ result:=operand_write
+ else
+ result:=operand_read;
+ A_BIC,A_BKPT,A_B,A_BL,A_BLX,A_BX,
+ A_CMN,A_CMP,A_TEQ,A_TST,
+ A_CMF,A_CMFE,A_WFS,A_CNF,
+ A_FCMPS,A_FCMPD,A_FCMPES,A_FCMPED,A_FCMPEZS,A_FCMPEZD,
+ A_FCMPZS,A_FCMPZD:
+ result:=operand_read;
+ A_SMLAL,A_UMLAL:
+ if opnr in [0,1] then
+ result:=operand_readwrite
+ else
+ result:=operand_read;
+ A_SMULL,A_UMULL,
+ A_FMRRD:
+ if opnr in [0,1] then
+ result:=operand_write
+ else
+ result:=operand_read;
+ A_STR,A_STRB,A_STRBT,
+ A_STRH,A_STRT,A_STF,A_SFM,
+ A_FSTS,A_FSTD:
+ { important is what happens with the involved registers }
+ if opnr=0 then
+ result := operand_read
+ else
+ { check for pre/post indexed }
+ result := operand_read;
+ //Thumb2
+ A_LSL, A_LSR, A_ROR, A_ASR, A_SDIV, A_UDIV,A_MOVT:
+ if opnr in [0] then
+ result:=operand_write
+ else
+ result:=operand_read;
+ A_LDREX:
+ if opnr in [0] then
+ result:=operand_write
+ else
+ result:=operand_read;
+ A_STREX:
+ if opnr in [0,1,2] then
+ result:=operand_write;
+ else
+ internalerror(200403151);
+ end;
+ end;
+
+
+ procedure BuildInsTabCache;
+ var
+ i : longint;
+ begin
+ new(instabcache);
+ FillChar(instabcache^,sizeof(tinstabcache),$ff);
+ i:=0;
+ while (i<InsTabEntries) do
+ begin
+ if InsTabCache^[InsTab[i].Opcode]=-1 then
+ InsTabCache^[InsTab[i].Opcode]:=i;
+ inc(i);
+ end;
+ end;
+
+
+ procedure InitAsm;
+ begin
+ if not assigned(instabcache) then
+ BuildInsTabCache;
+ end;
+
+
+ procedure DoneAsm;
+ begin
+ if assigned(instabcache) then
+ begin
+ dispose(instabcache);
+ instabcache:=nil;
+ end;
+ end;
+
+
+ function setoppostfix(i : taicpu;pf : toppostfix) : taicpu;
+ begin
+ i.oppostfix:=pf;
+ result:=i;
+ end;
+
+
+ function setroundingmode(i : taicpu;rm : troundingmode) : taicpu;
+ begin
+ i.roundingmode:=rm;
+ result:=i;
+ end;
+
+
+ function setcondition(i : taicpu;c : tasmcond) : taicpu;
+ begin
+ i.condition:=c;
+ result:=i;
+ end;
+
+
+ Function SimpleGetNextInstruction(Current: tai; Var Next: tai): Boolean;
+ Begin
+ Current:=tai(Current.Next);
+ While Assigned(Current) And (Current.typ In SkipInstr) Do
+ Current:=tai(Current.Next);
+ Next:=Current;
+ If Assigned(Next) And Not(Next.typ In SkipInstr) Then
+ Result:=True
+ Else
+ Begin
+ Next:=Nil;
+ Result:=False;
+ End;
+ End;
+
+
+(*
+ function armconstequal(hp1,hp2: tai): boolean;
+ begin
+ result:=false;
+ if hp1.typ<>hp2.typ then
+ exit;
+ case hp1.typ of
+ tai_const:
+ result:=
+ (tai_const(hp2).sym=tai_const(hp).sym) and
+ (tai_const(hp2).value=tai_const(hp).value) and
+ (tai(hp2.previous).typ=ait_label);
+ tai_const:
+ result:=
+ (tai_const(hp2).sym=tai_const(hp).sym) and
+ (tai_const(hp2).value=tai_const(hp).value) and
+ (tai(hp2.previous).typ=ait_label);
+ end;
+ end;
+*)
+
+ procedure insertpcrelativedata(list,listtoinsert : TAsmList);
+ var
+ curinspos,
+ penalty,
+ lastinspos,
+ { increased for every data element > 4 bytes inserted }
+ extradataoffset,
+ limit: longint;
+ curop : longint;
+ curtai : tai;
+ curdatatai,hp,hp2 : tai;
+ curdata : TAsmList;
+ l : tasmlabel;
+ doinsert,
+ removeref : boolean;
+ begin
+ curdata:=TAsmList.create;
+ lastinspos:=-1;
+ curinspos:=0;
+ extradataoffset:=0;
+ limit:=1016;
+ curtai:=tai(list.first);
+ doinsert:=false;
+ while assigned(curtai) do
+ begin
+ { instruction? }
+ case curtai.typ of
+ ait_instruction:
+ begin
+ { walk through all operand of the instruction }
+ for curop:=0 to taicpu(curtai).ops-1 do
+ begin
+ { reference? }
+ if (taicpu(curtai).oper[curop]^.typ=top_ref) then
+ begin
+ { pc relative symbol? }
+ curdatatai:=tai(taicpu(curtai).oper[curop]^.ref^.symboldata);
+ if assigned(curdatatai) and
+ { move only if we're at the first reference of a label }
+ (taicpu(curtai).oper[curop]^.ref^.offset=0) then
+ begin
+ { check if symbol already used. }
+ { if yes, reuse the symbol }
+ hp:=tai(curdatatai.next);
+ removeref:=false;
+ if assigned(hp) then
+ begin
+ case hp.typ of
+ ait_const:
+ begin
+ if (tai_const(hp).consttype=aitconst_64bit) then
+ inc(extradataoffset);
+ end;
+ ait_comp_64bit,
+ ait_real_64bit:
+ begin
+ inc(extradataoffset);
+ end;
+ ait_real_80bit:
+ begin
+ inc(extradataoffset,2);
+ end;
+ end;
+ if (hp.typ=ait_const) then
+ begin
+ hp2:=tai(curdata.first);
+ while assigned(hp2) do
+ begin
+ { if armconstequal(hp2,hp) then }
+ if (hp2.typ=ait_const) and (tai_const(hp2).sym=tai_const(hp).sym)
+ and (tai_const(hp2).value=tai_const(hp).value) and (tai(hp2.previous).typ=ait_label)
+ then
+ begin
+ with taicpu(curtai).oper[curop]^.ref^ do
+ begin
+ symboldata:=hp2.previous;
+ symbol:=tai_label(hp2.previous).labsym;
+ end;
+ removeref:=true;
+ break;
+ end;
+ hp2:=tai(hp2.next);
+ end;
+ end;
+ end;
+ { move or remove symbol reference }
+ repeat
+ hp:=tai(curdatatai.next);
+ listtoinsert.remove(curdatatai);
+ if removeref then
+ curdatatai.free
+ else
+ curdata.concat(curdatatai);
+ curdatatai:=hp;
+ until (curdatatai=nil) or (curdatatai.typ=ait_label);
+ if lastinspos=-1 then
+ lastinspos:=curinspos;
+ end;
+ end;
+ end;
+ inc(curinspos);
+ end;
+ ait_const:
+ begin
+ inc(curinspos);
+ if (tai_const(curtai).consttype=aitconst_64bit) then
+ inc(curinspos);
+ end;
+ ait_real_32bit:
+ begin
+ inc(curinspos);
+ end;
+ ait_comp_64bit,
+ ait_real_64bit:
+ begin
+ inc(curinspos,2);
+ end;
+ ait_real_80bit:
+ begin
+ inc(curinspos,3);
+ end;
+ end;
+ { special case for case jump tables }
+ if SimpleGetNextInstruction(curtai,hp) and
+ (tai(hp).typ=ait_instruction) and
+ (taicpu(hp).opcode=A_LDR) and
+ (taicpu(hp).oper[0]^.typ=top_reg) and
+ (taicpu(hp).oper[0]^.reg=NR_PC) then
+ begin
+ penalty:=1;
+ hp:=tai(hp.next);
+ while assigned(hp) and (hp.typ=ait_const) do
+ begin
+ inc(penalty);
+ hp:=tai(hp.next);
+ end;
+ end
+ else
+ penalty:=0;
+
+ { FLD/FST VFP instructions have a limit of +/- 1024, not 4096 }
+ if SimpleGetNextInstruction(curtai,hp) and
+ (tai(hp).typ=ait_instruction) and
+ ((taicpu(hp).opcode=A_FLDS) or
+ (taicpu(hp).opcode=A_FLDD)) then
+ limit:=254;
+
+ { don't miss an insert }
+ doinsert:=doinsert or
+ (not(curdata.empty) and
+ (curinspos-lastinspos+penalty+extradataoffset>limit));
+
+ { split only at real instructions else the test below fails }
+ if doinsert and (curtai.typ=ait_instruction) and
+ (
+ { don't split loads of pc to lr and the following move }
+ not(
+ (taicpu(curtai).opcode=A_MOV) and
+ (taicpu(curtai).oper[0]^.typ=top_reg) and
+ (taicpu(curtai).oper[0]^.reg=NR_R14) and
+ (taicpu(curtai).oper[1]^.typ=top_reg) and
+ (taicpu(curtai).oper[1]^.reg=NR_PC)
+ )
+ ) then
+ begin
+ lastinspos:=-1;
+ extradataoffset:=0;
+ limit:=1016;
+ doinsert:=false;
+ hp:=tai(curtai.next);
+ current_asmdata.getjumplabel(l);
+ curdata.insert(taicpu.op_sym(A_B,l));
+ curdata.concat(tai_label.create(l));
+ list.insertlistafter(curtai,curdata);
+ curtai:=hp;
+ end
+ else
+ curtai:=tai(curtai.next);
+ end;
+ list.concatlist(curdata);
+ curdata.free;
+ end;
+
+
+ procedure ensurethumb2encodings(list: TAsmList);
+ var
+ curtai: tai;
+ op2reg: TRegister;
+ begin
+ { Do Thumb-2 16bit -> 32bit transformations }
+ curtai:=tai(list.first);
+ while assigned(curtai) do
+ begin
+ case curtai.typ of
+ ait_instruction:
+ begin
+ case taicpu(curtai).opcode of
+ A_ADD:
+ begin
+ { Set wide flag for ADD Rd,Rn,Rm where registers are over R7(high register set) }
+ if taicpu(curtai).ops = 3 then
+ begin
+ if taicpu(curtai).oper[2]^.typ in [top_reg,top_shifterop] then
+ begin
+ if taicpu(curtai).oper[2]^.typ = top_reg then
+ op2reg := taicpu(curtai).oper[2]^.reg
+ else if taicpu(curtai).oper[2]^.shifterop^.rs <> NR_NO then
+ op2reg := taicpu(curtai).oper[2]^.shifterop^.rs
+ else
+ op2reg := NR_NO;
+
+ if op2reg <> NR_NO then
+ begin
+ if (taicpu(curtai).oper[0]^.reg >= NR_R8) or
+ (taicpu(curtai).oper[1]^.reg >= NR_R8) or
+ (op2reg >= NR_R8) then
+ begin
+ taicpu(curtai).wideformat:=true;
+
+ { Handle special cases where register rules are violated by optimizer/user }
+ { if d == 13 || (d == 15 && S == ‘0’) || n == 15 || m IN [13,15] then UNPREDICTABLE; }
+
+ { Transform ADD.W Rx, Ry, R13 into ADD.W Rx, R13, Ry }
+ if (op2reg = NR_R13) and (taicpu(curtai).oper[2]^.typ = top_reg) then
+ begin
+ taicpu(curtai).oper[2]^.reg := taicpu(curtai).oper[1]^.reg;
+ taicpu(curtai).oper[1]^.reg := op2reg;
+ end;
+ end;
+ end;
+ end;
+ end;
+ end;
+ end;
+ end;
+ end;
+
+
+ curtai:=tai(curtai.Next);
+ end;
+ end;
+
+ procedure finalizearmcode(list, listtoinsert: TAsmList);
+ begin
+ insertpcrelativedata(list, listtoinsert);
+
+ { Do Thumb-2 16bit -> 32bit transformations }
+ if current_settings.cputype in cpu_thumb2 then
+ ensurethumb2encodings(list);
+ end;
+
+ procedure InsertPData;
+ var
+ prolog: TAsmList;
+ begin
+ prolog:=TAsmList.create;
+ new_section(prolog,sec_code,'FPC_EH_PROLOG',sizeof(pint),secorder_begin);
+ prolog.concat(Tai_const.Createname('_ARM_ExceptionHandler', 0));
+ prolog.concat(Tai_const.Create_32bit(0));
+ prolog.concat(Tai_symbol.Createname_global('FPC_EH_CODE_START',AT_DATA,0));
+ { dummy function }
+ prolog.concat(taicpu.op_reg_reg(A_MOV,NR_R15,NR_R14));
+ current_asmdata.asmlists[al_start].insertList(prolog);
+ prolog.Free;
+ new_section(current_asmdata.asmlists[al_end],sec_pdata,'',sizeof(pint));
+ current_asmdata.asmlists[al_end].concat(Tai_const.Createname('FPC_EH_CODE_START', 0));
+ current_asmdata.asmlists[al_end].concat(Tai_const.Create_32bit(longint($ffffff01)));
+ end;
+
+(*
+ Floating point instruction format information, taken from the linux kernel
+ ARM Floating Point Instruction Classes
+ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+ |c o n d|1 1 0 P|U|u|W|L| Rn |v| Fd |0|0|0|1| o f f s e t | CPDT
+ |c o n d|1 1 0 P|U|w|W|L| Rn |x| Fd |0|0|1|0| o f f s e t | CPDT (copro 2)
+ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+ |c o n d|1 1 1 0|a|b|c|d|e| Fn |j| Fd |0|0|0|1|f|g|h|0|i| Fm | CPDO
+ |c o n d|1 1 1 0|a|b|c|L|e| Fn | Rd |0|0|0|1|f|g|h|1|i| Fm | CPRT
+ |c o n d|1 1 1 0|a|b|c|1|e| Fn |1|1|1|1|0|0|0|1|f|g|h|1|i| Fm | comparisons
+ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+
+ CPDT data transfer instructions
+ LDF, STF, LFM (copro 2), SFM (copro 2)
+
+ CPDO dyadic arithmetic instructions
+ ADF, MUF, SUF, RSF, DVF, RDF,
+ POW, RPW, RMF, FML, FDV, FRD, POL
+
+ CPDO monadic arithmetic instructions
+ MVF, MNF, ABS, RND, SQT, LOG, LGN, EXP,
+ SIN, COS, TAN, ASN, ACS, ATN, URD, NRM
+
+ CPRT joint arithmetic/data transfer instructions
+ FIX (arithmetic followed by load/store)
+ FLT (load/store followed by arithmetic)
+ CMF, CNF CMFE, CNFE (comparisons)
+ WFS, RFS (write/read floating point status register)
+ WFC, RFC (write/read floating point control register)
+
+ cond condition codes
+ P pre/post index bit: 0 = postindex, 1 = preindex
+ U up/down bit: 0 = stack grows down, 1 = stack grows up
+ W write back bit: 1 = update base register (Rn)
+ L load/store bit: 0 = store, 1 = load
+ Rn base register
+ Rd destination/source register
+ Fd floating point destination register
+ Fn floating point source register
+ Fm floating point source register or floating point constant
+
+ uv transfer length (TABLE 1)
+ wx register count (TABLE 2)
+ abcd arithmetic opcode (TABLES 3 & 4)
+ ef destination size (rounding precision) (TABLE 5)
+ gh rounding mode (TABLE 6)
+ j dyadic/monadic bit: 0 = dyadic, 1 = monadic
+ i constant bit: 1 = constant (TABLE 6)
+ */
+
+ /*
+ TABLE 1
+ +-------------------------+---+---+---------+---------+
+ | Precision | u | v | FPSR.EP | length |
+ +-------------------------+---+---+---------+---------+
+ | Single | 0 | 0 | x | 1 words |
+ | Double | 1 | 1 | x | 2 words |
+ | Extended | 1 | 1 | x | 3 words |
+ | Packed decimal | 1 | 1 | 0 | 3 words |
+ | Expanded packed decimal | 1 | 1 | 1 | 4 words |
+ +-------------------------+---+---+---------+---------+
+ Note: x = don't care
+ */
+
+ /*
+ TABLE 2
+ +---+---+---------------------------------+
+ | w | x | Number of registers to transfer |
+ +---+---+---------------------------------+
+ | 0 | 1 | 1 |
+ | 1 | 0 | 2 |
+ | 1 | 1 | 3 |
+ | 0 | 0 | 4 |
+ +---+---+---------------------------------+
+ */
+
+ /*
+ TABLE 3: Dyadic Floating Point Opcodes
+ +---+---+---+---+----------+-----------------------+-----------------------+
+ | a | b | c | d | Mnemonic | Description | Operation |
+ +---+---+---+---+----------+-----------------------+-----------------------+
+ | 0 | 0 | 0 | 0 | ADF | Add | Fd := Fn + Fm |
+ | 0 | 0 | 0 | 1 | MUF | Multiply | Fd := Fn * Fm |
+ | 0 | 0 | 1 | 0 | SUF | Subtract | Fd := Fn - Fm |
+ | 0 | 0 | 1 | 1 | RSF | Reverse subtract | Fd := Fm - Fn |
+ | 0 | 1 | 0 | 0 | DVF | Divide | Fd := Fn / Fm |
+ | 0 | 1 | 0 | 1 | RDF | Reverse divide | Fd := Fm / Fn |
+ | 0 | 1 | 1 | 0 | POW | Power | Fd := Fn ^ Fm |
+ | 0 | 1 | 1 | 1 | RPW | Reverse power | Fd := Fm ^ Fn |
+ | 1 | 0 | 0 | 0 | RMF | Remainder | Fd := IEEE rem(Fn/Fm) |
+ | 1 | 0 | 0 | 1 | FML | Fast Multiply | Fd := Fn * Fm |
+ | 1 | 0 | 1 | 0 | FDV | Fast Divide | Fd := Fn / Fm |
+ | 1 | 0 | 1 | 1 | FRD | Fast reverse divide | Fd := Fm / Fn |
+ | 1 | 1 | 0 | 0 | POL | Polar angle (ArcTan2) | Fd := arctan2(Fn,Fm) |
+ | 1 | 1 | 0 | 1 | | undefined instruction | trap |
+ | 1 | 1 | 1 | 0 | | undefined instruction | trap |
+ | 1 | 1 | 1 | 1 | | undefined instruction | trap |
+ +---+---+---+---+----------+-----------------------+-----------------------+
+ Note: POW, RPW, POL are deprecated, and are available for backwards
+ compatibility only.
+ */
+
+ /*
+ TABLE 4: Monadic Floating Point Opcodes
+ +---+---+---+---+----------+-----------------------+-----------------------+
+ | a | b | c | d | Mnemonic | Description | Operation |
+ +---+---+---+---+----------+-----------------------+-----------------------+
+ | 0 | 0 | 0 | 0 | MVF | Move | Fd := Fm |
+ | 0 | 0 | 0 | 1 | MNF | Move negated | Fd := - Fm |
+ | 0 | 0 | 1 | 0 | ABS | Absolute value | Fd := abs(Fm) |
+ | 0 | 0 | 1 | 1 | RND | Round to integer | Fd := int(Fm) |
+ | 0 | 1 | 0 | 0 | SQT | Square root | Fd := sqrt(Fm) |
+ | 0 | 1 | 0 | 1 | LOG | Log base 10 | Fd := log10(Fm) |
+ | 0 | 1 | 1 | 0 | LGN | Log base e | Fd := ln(Fm) |
+ | 0 | 1 | 1 | 1 | EXP | Exponent | Fd := e ^ Fm |
+ | 1 | 0 | 0 | 0 | SIN | Sine | Fd := sin(Fm) |
+ | 1 | 0 | 0 | 1 | COS | Cosine | Fd := cos(Fm) |
+ | 1 | 0 | 1 | 0 | TAN | Tangent | Fd := tan(Fm) |
+ | 1 | 0 | 1 | 1 | ASN | Arc Sine | Fd := arcsin(Fm) |
+ | 1 | 1 | 0 | 0 | ACS | Arc Cosine | Fd := arccos(Fm) |
+ | 1 | 1 | 0 | 1 | ATN | Arc Tangent | Fd := arctan(Fm) |
+ | 1 | 1 | 1 | 0 | URD | Unnormalized round | Fd := int(Fm) |
+ | 1 | 1 | 1 | 1 | NRM | Normalize | Fd := norm(Fm) |
+ +---+---+---+---+----------+-----------------------+-----------------------+
+ Note: LOG, LGN, EXP, SIN, COS, TAN, ASN, ACS, ATN are deprecated, and are
+ available for backwards compatibility only.
+ */
+
+ /*
+ TABLE 5
+ +-------------------------+---+---+
+ | Rounding Precision | e | f |
+ +-------------------------+---+---+
+ | IEEE Single precision | 0 | 0 |
+ | IEEE Double precision | 0 | 1 |
+ | IEEE Extended precision | 1 | 0 |
+ | undefined (trap) | 1 | 1 |
+ +-------------------------+---+---+
+ */
+
+ /*
+ TABLE 5
+ +---------------------------------+---+---+
+ | Rounding Mode | g | h |
+ +---------------------------------+---+---+
+ | Round to nearest (default) | 0 | 0 |
+ | Round toward plus infinity | 0 | 1 |
+ | Round toward negative infinity | 1 | 0 |
+ | Round toward zero | 1 | 1 |
+ +---------------------------------+---+---+
+*)
+ function taicpu.GetString:string;
+ var
+ i : longint;
+ s : string;
+ addsize : boolean;
+ begin
+ s:='['+gas_op2str[opcode];
+ for i:=0 to ops-1 do
+ begin
+ with oper[i]^ do
+ begin
+ if i=0 then
+ s:=s+' '
+ else
+ s:=s+',';
+ { type }
+ addsize:=false;
+ if (ot and OT_VREG)=OT_VREG then
+ s:=s+'vreg'
+ else
+ if (ot and OT_FPUREG)=OT_FPUREG then
+ s:=s+'fpureg'
+ else
+ if (ot and OT_REGISTER)=OT_REGISTER then
+ begin
+ s:=s+'reg';
+ addsize:=true;
+ end
+ else
+ if (ot and OT_REGLIST)=OT_REGLIST then
+ begin
+ s:=s+'reglist';
+ addsize:=false;
+ end
+ else
+ if (ot and OT_IMMEDIATE)=OT_IMMEDIATE then
+ begin
+ s:=s+'imm';
+ addsize:=true;
+ end
+ else
+ if (ot and OT_MEMORY)=OT_MEMORY then
+ begin
+ s:=s+'mem';
+ addsize:=true;
+ if (ot and OT_AM2)<>0 then
+ s:=s+' am2 ';
+ end
+ else
+ s:=s+'???';
+ { size }
+ if addsize then
+ begin
+ if (ot and OT_BITS8)<>0 then
+ s:=s+'8'
+ else
+ if (ot and OT_BITS16)<>0 then
+ s:=s+'24'
+ else
+ if (ot and OT_BITS32)<>0 then
+ s:=s+'32'
+ else
+ if (ot and OT_BITSSHIFTER)<>0 then
+ s:=s+'shifter'
+ else
+ s:=s+'??';
+ { signed }
+ if (ot and OT_SIGNED)<>0 then
+ s:=s+'s';
+ end;
+ end;
+ end;
+ GetString:=s+']';
+ end;
+
+
+ procedure taicpu.ResetPass1;
+ begin
+ { we need to reset everything here, because the choosen insentry
+ can be invalid for a new situation where the previously optimized
+ insentry is not correct }
+ InsEntry:=nil;
+ InsSize:=0;
+ LastInsOffset:=-1;
+ end;
+
+
+ procedure taicpu.ResetPass2;
+ begin
+ { we are here in a second pass, check if the instruction can be optimized }
+ if assigned(InsEntry) and
+ ((InsEntry^.flags and IF_PASS2)<>0) then
+ begin
+ InsEntry:=nil;
+ InsSize:=0;
+ end;
+ LastInsOffset:=-1;
+ end;
+
+
+ function taicpu.CheckIfValid:boolean;
+ begin
+ Result:=False; { unimplemented }
+ end;
+
+
+ function taicpu.Pass1(objdata:TObjData):longint;
+ var
+ ldr2op : array[PF_B..PF_T] of tasmop = (
+ A_LDRB,A_LDRSB,A_LDRBT,A_LDRH,A_LDRSH,A_LDRT);
+ str2op : array[PF_B..PF_T] of tasmop = (
+ A_STRB,A_None,A_STRBT,A_STRH,A_None,A_STRT);
+ begin
+ Pass1:=0;
+ { Save the old offset and set the new offset }
+ InsOffset:=ObjData.CurrObjSec.Size;
+ { Error? }
+ if (Insentry=nil) and (InsSize=-1) then
+ exit;
+ { set the file postion }
+ current_filepos:=fileinfo;
+
+ { tranlate LDR+postfix to complete opcode }
+ if (opcode=A_LDR) and (oppostfix<>PF_None) then
+ begin
+ if (oppostfix in [low(ldr2op)..high(ldr2op)]) then
+ opcode:=ldr2op[oppostfix]
+ else
+ internalerror(2005091001);
+ if opcode=A_None then
+ internalerror(2005091004);
+ { postfix has been added to opcode }
+ oppostfix:=PF_None;
+ end
+ else if (opcode=A_STR) and (oppostfix<>PF_None) then
+ begin
+ if (oppostfix in [low(str2op)..high(str2op)]) then
+ opcode:=str2op[oppostfix]
+ else
+ internalerror(2005091002);
+ if opcode=A_None then
+ internalerror(2005091003);
+ { postfix has been added to opcode }
+ oppostfix:=PF_None;
+ end;
+
+ { Get InsEntry }
+ if FindInsEntry(objdata) then
+ begin
+ InsSize:=4;
+ LastInsOffset:=InsOffset;
+ Pass1:=InsSize;
+ exit;
+ end;
+ LastInsOffset:=-1;
+ end;
+
+
+ procedure taicpu.Pass2(objdata:TObjData);
+ begin
+ { error in pass1 ? }
+ if insentry=nil then
+ exit;
+ current_filepos:=fileinfo;
+ { Generate the instruction }
+ GenCode(objdata);
+ end;
+
+
+ procedure taicpu.ppuloadoper(ppufile:tcompilerppufile;var o:toper);
+ begin
+ end;
+
+
+ procedure taicpu.ppuwriteoper(ppufile:tcompilerppufile;const o:toper);
+ begin
+ end;
+
+
+ procedure taicpu.ppubuildderefimploper(var o:toper);
+ begin
+ end;
+
+
+ procedure taicpu.ppuderefoper(var o:toper);
+ begin
+ end;
+
+
+ function taicpu.InsEnd:longint;
+ begin
+ Result:=0; { unimplemented }
+ end;
+
+
+ procedure taicpu.create_ot(objdata:TObjData);
+ var
+ i,l,relsize : longint;
+ dummy : byte;
+ currsym : TObjSymbol;
+ begin
+ if ops=0 then
+ exit;
+ { update oper[].ot field }
+ for i:=0 to ops-1 do
+ with oper[i]^ do
+ begin
+ case typ of
+ top_regset:
+ begin
+ ot:=OT_REGLIST;
+ end;
+ top_reg :
+ begin
+ case getregtype(reg) of
+ R_INTREGISTER:
+ ot:=OT_REG32 or OT_SHIFTEROP;
+ R_FPUREGISTER:
+ ot:=OT_FPUREG;
+ else
+ internalerror(2005090901);
+ end;
+ end;
+ top_ref :
+ begin
+ if ref^.refaddr=addr_no then
+ begin
+ { create ot field }
+ { we should get the size here dependend on the
+ instruction }
+ if (ot and OT_SIZE_MASK)=0 then
+ ot:=OT_MEMORY or OT_BITS32
+ else
+ ot:=OT_MEMORY or (ot and OT_SIZE_MASK);
+ if (ref^.base=NR_NO) and (ref^.index=NR_NO) then
+ ot:=ot or OT_MEM_OFFS;
+ { if we need to fix a reference, we do it here }
+
+ { pc relative addressing }
+ if (ref^.base=NR_NO) and
+ (ref^.index=NR_NO) and
+ (ref^.shiftmode=SM_None)
+ { at least we should check if the destination symbol
+ is in a text section }
+ { and
+ (ref^.symbol^.owner="text") } then
+ ref^.base:=NR_PC;
+
+ { determine possible address modes }
+ if (ref^.base<>NR_NO) and
+ (
+ (
+ (ref^.index=NR_NO) and
+ (ref^.shiftmode=SM_None) and
+ (ref^.offset>=-4097) and
+ (ref^.offset<=4097)
+ ) or
+ (
+ (ref^.shiftmode=SM_None) and
+ (ref^.offset=0)
+ ) or
+ (
+ (ref^.index<>NR_NO) and
+ (ref^.shiftmode<>SM_None) and
+ (ref^.shiftimm<=31) and
+ (ref^.offset=0)
+ )
+ ) then
+ ot:=ot or OT_AM2;
+
+ if (ref^.index<>NR_NO) and
+ (oppostfix in [PF_IA,PF_IB,PF_DA,PF_DB,PF_FD,PF_FA,PF_ED,PF_EA]) and
+ (
+ (ref^.base=NR_NO) and
+ (ref^.shiftmode=SM_None) and
+ (ref^.offset=0)
+ ) then
+ ot:=ot or OT_AM4;
+
+ end
+ else
+ begin
+ l:=ref^.offset;
+ currsym:=ObjData.symbolref(ref^.symbol);
+ if assigned(currsym) then
+ inc(l,currsym.address);
+ relsize:=(InsOffset+2)-l;
+ if (relsize<-33554428) or (relsize>33554428) then
+ ot:=OT_IMM32
+ else
+ ot:=OT_IMM24;
+ end;
+ end;
+ top_local :
+ begin
+ { we should get the size here dependend on the
+ instruction }
+ if (ot and OT_SIZE_MASK)=0 then
+ ot:=OT_MEMORY or OT_BITS32
+ else
+ ot:=OT_MEMORY or (ot and OT_SIZE_MASK);
+ end;
+ top_const :
+ begin
+ ot:=OT_IMMEDIATE;
+ if is_shifter_const(val,dummy) then
+ ot:=OT_IMMSHIFTER
+ else
+ ot:=OT_IMM32
+ end;
+ top_none :
+ begin
+ { generated when there was an error in the
+ assembler reader. It never happends when generating
+ assembler }
+ end;
+ top_shifterop:
+ begin
+ ot:=OT_SHIFTEROP;
+ end;
+ else
+ internalerror(200402261);
+ end;
+ end;
+ end;
+
+
+ function taicpu.Matches(p:PInsEntry):longint;
+ { * IF_SM stands for Size Match: any operand whose size is not
+ * explicitly specified by the template is `really' intended to be
+ * the same size as the first size-specified operand.
+ * Non-specification is tolerated in the input instruction, but
+ * _wrong_ specification is not.
+ *
+ * IF_SM2 invokes Size Match on only the first _two_ operands, for
+ * three-operand instructions such as SHLD: it implies that the
+ * first two operands must match in size, but that the third is
+ * required to be _unspecified_.
+ *
+ * IF_SB invokes Size Byte: operands with unspecified size in the
+ * template are really bytes, and so no non-byte specification in
+ * the input instruction will be tolerated. IF_SW similarly invokes
+ * Size Word, and IF_SD invokes Size Doubleword.
+ *
+ * (The default state if neither IF_SM nor IF_SM2 is specified is
+ * that any operand with unspecified size in the template is
+ * required to have unspecified size in the instruction too...)
+ }
+ var
+ i{,j,asize,oprs} : longint;
+ {siz : array[0..3] of longint;}
+ begin
+ Matches:=100;
+ writeln(getstring,'---');
+
+ { Check the opcode and operands }
+ if (p^.opcode<>opcode) or (p^.ops<>ops) then
+ begin
+ Matches:=0;
+ exit;
+ end;
+
+ { Check that no spurious colons or TOs are present }
+ for i:=0 to p^.ops-1 do
+ if (oper[i]^.ot and (not p^.optypes[i]) and (OT_COLON or OT_TO))<>0 then
+ begin
+ Matches:=0;
+ exit;
+ end;
+
+ { Check that the operand flags all match up }
+ for i:=0 to p^.ops-1 do
+ begin
+ if ((p^.optypes[i] and (not oper[i]^.ot)) or
+ ((p^.optypes[i] and OT_SIZE_MASK) and
+ ((p^.optypes[i] xor oper[i]^.ot) and OT_SIZE_MASK)))<>0 then
+ begin
+ if ((p^.optypes[i] and (not oper[i]^.ot) and OT_NON_SIZE) or
+ (oper[i]^.ot and OT_SIZE_MASK))<>0 then
+ begin
+ Matches:=0;
+ exit;
+ end
+ else
+ Matches:=1;
+ end;
+ end;
+
+ { check postfixes:
+ the existance of a certain postfix requires a
+ particular code }
+
+ { update condition flags
+ or floating point single }
+ if (oppostfix=PF_S) and
+ not(p^.code[0] in [#$04]) then
+ begin
+ Matches:=0;
+ exit;
+ end;
+
+ { floating point size }
+ if (oppostfix in [PF_D,PF_E,PF_P,PF_EP]) and
+ not(p^.code[0] in []) then
+ begin
+ Matches:=0;
+ exit;
+ end;
+
+ { multiple load/store address modes }
+ if (oppostfix in [PF_IA,PF_IB,PF_DA,PF_DB,PF_FD,PF_FA,PF_ED,PF_EA]) and
+ not(p^.code[0] in [
+ // ldr,str,ldrb,strb
+ #$17,
+ // stm,ldm
+ #$26
+ ]) then
+ begin
+ Matches:=0;
+ exit;
+ end;
+
+ { we shouldn't see any opsize prefixes here }
+ if (oppostfix in [PF_B,PF_SB,PF_BT,PF_H,PF_SH,PF_T]) then
+ begin
+ Matches:=0;
+ exit;
+ end;
+
+ if (roundingmode<>RM_None) and not(p^.code[0] in []) then
+ begin
+ Matches:=0;
+ exit;
+ end;
+
+ { Check operand sizes }
+ { as default an untyped size can get all the sizes, this is different
+ from nasm, but else we need to do a lot checking which opcodes want
+ size or not with the automatic size generation }
+ (*
+ asize:=longint($ffffffff);
+ if (p^.flags and IF_SB)<>0 then
+ asize:=OT_BITS8
+ else if (p^.flags and IF_SW)<>0 then
+ asize:=OT_BITS16
+ else if (p^.flags and IF_SD)<>0 then
+ asize:=OT_BITS32;
+ if (p^.flags and IF_ARMASK)<>0 then
+ begin
+ siz[0]:=0;
+ siz[1]:=0;
+ siz[2]:=0;
+ if (p^.flags and IF_AR0)<>0 then
+ siz[0]:=asize
+ else if (p^.flags and IF_AR1)<>0 then
+ siz[1]:=asize
+ else if (p^.flags and IF_AR2)<>0 then
+ siz[2]:=asize;
+ end
+ else
+ begin
+ { we can leave because the size for all operands is forced to be
+ the same
+ but not if IF_SB IF_SW or IF_SD is set PM }
+ if asize=-1 then
+ exit;
+ siz[0]:=asize;
+ siz[1]:=asize;
+ siz[2]:=asize;
+ end;
+
+ if (p^.flags and (IF_SM or IF_SM2))<>0 then
+ begin
+ if (p^.flags and IF_SM2)<>0 then
+ oprs:=2
+ else
+ oprs:=p^.ops;
+ for i:=0 to oprs-1 do
+ if ((p^.optypes[i] and OT_SIZE_MASK) <> 0) then
+ begin
+ for j:=0 to oprs-1 do
+ siz[j]:=p^.optypes[i] and OT_SIZE_MASK;
+ break;
+ end;
+ end
+ else
+ oprs:=2;
+
+ { Check operand sizes }
+ for i:=0 to p^.ops-1 do
+ begin
+ if ((p^.optypes[i] and OT_SIZE_MASK)=0) and
+ ((oper[i]^.ot and OT_SIZE_MASK and (not siz[i]))<>0) and
+ { Immediates can always include smaller size }
+ ((oper[i]^.ot and OT_IMMEDIATE)=0) and
+ (((p^.optypes[i] and OT_SIZE_MASK) or siz[i])<(oper[i]^.ot and OT_SIZE_MASK)) then
+ Matches:=2;
+ end;
+ *)
+ end;
+
+
+ function taicpu.calcsize(p:PInsEntry):shortint;
+ begin
+ result:=4;
+ end;
+
+
+ function taicpu.NeedAddrPrefix(opidx:byte):boolean;
+ begin
+ Result:=False; { unimplemented }
+ end;
+
+
+ procedure taicpu.Swapoperands;
+ begin
+ end;
+
+
+ function taicpu.FindInsentry(objdata:TObjData):boolean;
+ var
+ i : longint;
+ begin
+ result:=false;
+ { Things which may only be done once, not when a second pass is done to
+ optimize }
+ if (Insentry=nil) or ((InsEntry^.flags and IF_PASS2)<>0) then
+ begin
+ { create the .ot fields }
+ create_ot(objdata);
+ { set the file postion }
+ current_filepos:=fileinfo;
+ end
+ else
+ begin
+ { we've already an insentry so it's valid }
+ result:=true;
+ exit;
+ end;
+ { Lookup opcode in the table }
+ InsSize:=-1;
+ i:=instabcache^[opcode];
+ if i=-1 then
+ begin
+ Message1(asmw_e_opcode_not_in_table,gas_op2str[opcode]);
+ exit;
+ end;
+ insentry:=@instab[i];
+ while (insentry^.opcode=opcode) do
+ begin
+ if matches(insentry)=100 then
+ begin
+ result:=true;
+ exit;
+ end;
+ inc(i);
+ insentry:=@instab[i];
+ end;
+ Message1(asmw_e_invalid_opcode_and_operands,GetString);
+ { No instruction found, set insentry to nil and inssize to -1 }
+ insentry:=nil;
+ inssize:=-1;
+ end;
+
+
+ procedure taicpu.gencode(objdata:TObjData);
+ var
+ bytes : dword;
+ i_field : byte;
+
+ procedure setshifterop(op : byte);
+ begin
+ case oper[op]^.typ of
+ top_const:
+ begin
+ i_field:=1;
+ bytes:=bytes or dword(oper[op]^.val and $fff);
+ end;
+ top_reg:
+ begin
+ i_field:=0;
+ bytes:=bytes or (getsupreg(oper[op]^.reg) shl 16);
+
+ { does a real shifter op follow? }
+ if (op+1<=op) and (oper[op+1]^.typ=top_shifterop) then
+ begin
+ end;
+ end;
+ else
+ internalerror(2005091103);
+ end;
+ end;
+
+ begin
+ bytes:=$0;
+ { evaluate and set condition code }
+
+ { condition code allowed? }
+
+ { setup rest of the instruction }
+ case insentry^.code[0] of
+ #$08:
+ begin
+ { set instruction code }
+ bytes:=bytes or (ord(insentry^.code[1]) shl 26);
+ bytes:=bytes or (ord(insentry^.code[2]) shl 21);
+
+ { set destination }
+ bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
+
+ { create shifter op }
+ setshifterop(1);
+
+ { set i field }
+ bytes:=bytes or (i_field shl 25);
+
+ { set s if necessary }
+ if oppostfix=PF_S then
+ bytes:=bytes or (1 shl 20);
+ end;
+ #$ff:
+ internalerror(2005091101);
+ else
+ internalerror(2005091102);
+ end;
+ { we're finished, write code }
+ objdata.writebytes(bytes,sizeof(bytes));
+ end;
+
+
+{$ifdef dummy}
+(*
+static void gencode (long segment, long offset, int bits,
+ insn *ins, char *codes, long insn_end)
+{
+ int has_S_code; /* S - setflag */
+ int has_B_code; /* B - setflag */
+ int has_T_code; /* T - setflag */
+ int has_W_code; /* ! => W flag */
+ int has_F_code; /* ^ => S flag */
+ int keep;
+ unsigned char c;
+ unsigned char bytes[4];
+ long data, size;
+ static int cc_code[] = /* bit pattern of cc */
+ { /* order as enum in */
+ 0x0E, 0x03, 0x02, 0x00, /* nasm.h */
+ 0x0A, 0x0C, 0x08, 0x0D,
+ 0x09, 0x0B, 0x04, 0x01,
+ 0x05, 0x07, 0x06,
+ };
+
+
+#ifdef DEBUG
+static char *CC[] =
+ { /* condition code names */
+ "AL", "CC", "CS", "EQ",
+ "GE", "GT", "HI", "LE",
+ "LS", "LT", "MI", "NE",
+ "PL", "VC", "VS", "",
+ "S"
+};
+
+
+ has_S_code = (ins->condition & C_SSETFLAG);
+ has_B_code = (ins->condition & C_BSETFLAG);
+ has_T_code = (ins->condition & C_TSETFLAG);
+ has_W_code = (ins->condition & C_EXSETFLAG);
+ has_F_code = (ins->condition & C_FSETFLAG);
+ ins->condition = (ins->condition & 0x0F);
+
+
+ if (rt_debug)
+ {
+ printf ("gencode: instruction: %s%s", insn_names[ins->opcode],
+ CC[ins->condition & 0x0F]);
+ if (has_S_code)
+ printf ("S");
+ if (has_B_code)
+ printf ("B");
+ if (has_T_code)
+ printf ("T");
+ if (has_W_code)
+ printf ("!");
+ if (has_F_code)
+ printf ("^");
+
+ printf ("\n");
+
+ c = *codes;
+
+ printf (" (%d) decode - '0x%02X'\n", ins->operands, c);
+
+
+ bytes[0] = 0xB;
+ bytes[1] = 0xE;
+ bytes[2] = 0xE;
+ bytes[3] = 0xF;
+ }
+
+ // First condition code in upper nibble
+ if (ins->condition < C_NONE)
+ {
+ c = cc_code[ins->condition] << 4;
+ }
+ else
+ {
+ c = cc_code[C_AL] << 4; // is often ALWAYS but not always
+ }
+
+
+ switch (keep = *codes)
+ {
+ case 1:
+ // B, BL
+ ++codes;
+ c |= *codes++;
+ bytes[0] = c;
+
+ if (ins->oprs[0].segment != segment)
+ {
+ // fais une relocation
+ c = 1;
+ data = 0; // Let the linker locate ??
+ }
+ else
+ {
+ c = 0;
+ data = ins->oprs[0].offset - (offset + 8);
+
+ if (data % 4)
+ {
+ errfunc (ERR_NONFATAL, "offset not aligned on 4 bytes");
+ }
+ }
+
+ if (data >= 0x1000)
+ {
+ errfunc (ERR_NONFATAL, "too long offset");
+ }
+
+ data = data >> 2;
+ bytes[1] = (data >> 16) & 0xFF;
+ bytes[2] = (data >> 8) & 0xFF;
+ bytes[3] = (data ) & 0xFF;
+
+ if (c == 1)
+ {
+// out (offset, segment, &bytes[0], OUT_RAWDATA+1, NO_SEG, NO_SEG);
+ out (offset, segment, &bytes[0], OUT_REL3ADR+4, ins->oprs[0].segment, NO_SEG);
+ }
+ else
+ {
+ out (offset, segment, &bytes[0], OUT_RAWDATA+4, NO_SEG, NO_SEG);
+ }
+ return;
+
+ case 2:
+ // SWI
+ ++codes;
+ c |= *codes++;
+ bytes[0] = c;
+ data = ins->oprs[0].offset;
+ bytes[1] = (data >> 16) & 0xFF;
+ bytes[2] = (data >> 8) & 0xFF;
+ bytes[3] = (data) & 0xFF;
+ out (offset, segment, &bytes, OUT_RAWDATA+4, NO_SEG, NO_SEG);
+ return;
+ case 3:
+ // BX
+ ++codes;
+ c |= *codes++;
+ bytes[0] = c;
+ bytes[1] = *codes++;
+ bytes[2] = *codes++;
+ bytes[3] = *codes++;
+ c = regval (&ins->oprs[0],1);
+ if (c == 15) // PC
+ {
+ errfunc (ERR_WARNING, "'BX' with R15 has undefined behaviour");
+ }
+ else if (c > 15)
+ {
+ errfunc (ERR_NONFATAL, "Illegal register specified for 'BX'");
+ }
+
+ bytes[3] |= (c & 0x0F);
+ out (offset, segment, bytes, OUT_RAWDATA+4, NO_SEG, NO_SEG);
+ return;
+
+ case 4: // AND Rd,Rn,Rm
+ case 5: // AND Rd,Rn,Rm,<shift>Rs
+ case 6: // AND Rd,Rn,Rm,<shift>imm
+ case 7: // AND Rd,Rn,<shift>imm
+ ++codes;
+#ifdef DEBUG
+ if (rt_debug)
+ {
+ printf (" decode - '0x%02X'\n", keep);
+ printf (" code - '0x%02X'\n", (unsigned char) ( *codes));
+ }
+#endif
+ bytes[0] = c | *codes;
+ ++codes;
+
+ bytes[1] = *codes;
+ if (has_S_code)
+ bytes[1] |= 0x10;
+ c = regval (&ins->oprs[1],1);
+ // Rn in low nibble
+ bytes[1] |= c;
+
+ // Rd in high nibble
+ bytes[2] = regval (&ins->oprs[0],1) << 4;
+
+ if (keep != 7)
+ {
+ // Rm in low nibble
+ bytes[3] = regval (&ins->oprs[2],1);
+ }
+
+ // Shifts if any
+ if (keep == 5 || keep == 6)
+ {
+ // Shift in bytes 2 and 3
+ if (keep == 5)
+ {
+ // Rs
+ c = regval (&ins->oprs[3],1);
+ bytes[2] |= c;
+
+ c = 0x10; // Set bit 4 in byte[3]
+ }
+ if (keep == 6)
+ {
+ c = (ins->oprs[3].offset) & 0x1F;
+
+ // #imm
+ bytes[2] |= c >> 1;
+ if (c & 0x01)
+ {
+ bytes[3] |= 0x80;
+ }
+ c = 0; // Clr bit 4 in byte[3]
+ }
+ // <shift>
+ c |= shiftval (&ins->oprs[3]) << 5;
+
+ bytes[3] |= c;
+ }
+
+ // reg,reg,imm
+ if (keep == 7)
+ {
+ int shimm;
+
+ shimm = imm_shift (ins->oprs[2].offset);
+
+ if (shimm == -1)
+ {
+ errfunc (ERR_NONFATAL, "cannot create that constant");
+ }
+ bytes[3] = shimm & 0xFF;
+ bytes[2] |= (shimm & 0xF00) >> 8;
+ }
+
+ out (offset, segment, bytes, OUT_RAWDATA+4, NO_SEG, NO_SEG);
+ return;
+
+ case 8: // MOV Rd,Rm
+ case 9: // MOV Rd,Rm,<shift>Rs
+ case 0xA: // MOV Rd,Rm,<shift>imm
+ case 0xB: // MOV Rd,<shift>imm
+ ++codes;
+#ifdef DEBUG
+ if (rt_debug)
+ {
+ printf (" decode - '0x%02X'\n", keep);
+ printf (" code - '0x%02X'\n", (unsigned char) ( *codes));
+ }
+#endif
+ bytes[0] = c | *codes;
+ ++codes;
+
+ bytes[1] = *codes;
+ if (has_S_code)
+ bytes[1] |= 0x10;
+
+ // Rd in high nibble
+ bytes[2] = regval (&ins->oprs[0],1) << 4;
+
+ if (keep != 0x0B)
+ {
+ // Rm in low nibble
+ bytes[3] = regval (&ins->oprs[1],1);
+ }
+
+ // Shifts if any
+ if (keep == 0x09 || keep == 0x0A)
+ {
+ // Shift in bytes 2 and 3
+ if (keep == 0x09)
+ {
+ // Rs
+ c = regval (&ins->oprs[2],1);
+ bytes[2] |= c;
+
+ c = 0x10; // Set bit 4 in byte[3]
+ }
+ if (keep == 0x0A)
+ {
+ c = (ins->oprs[2].offset) & 0x1F;
+
+ // #imm
+ bytes[2] |= c >> 1;
+ if (c & 0x01)
+ {
+ bytes[3] |= 0x80;
+ }
+ c = 0; // Clr bit 4 in byte[3]
+ }
+ // <shift>
+ c |= shiftval (&ins->oprs[2]) << 5;
+
+ bytes[3] |= c;
+ }
+
+ // reg,imm
+ if (keep == 0x0B)
+ {
+ int shimm;
+
+ shimm = imm_shift (ins->oprs[1].offset);
+
+ if (shimm == -1)
+ {
+ errfunc (ERR_NONFATAL, "cannot create that constant");
+ }
+ bytes[3] = shimm & 0xFF;
+ bytes[2] |= (shimm & 0xF00) >> 8;
+ }
+
+ out (offset, segment, bytes, OUT_RAWDATA+4, NO_SEG, NO_SEG);
+ return;
+
+
+ case 0xC: // CMP Rn,Rm
+ case 0xD: // CMP Rn,Rm,<shift>Rs
+ case 0xE: // CMP Rn,Rm,<shift>imm
+ case 0xF: // CMP Rn,<shift>imm
+ ++codes;
+
+ bytes[0] = c | *codes++;
+
+ bytes[1] = *codes;
+
+ // Implicit S code
+ bytes[1] |= 0x10;
+
+ c = regval (&ins->oprs[0],1);
+ // Rn in low nibble
+ bytes[1] |= c;
+
+ // No destination
+ bytes[2] = 0;
+
+ if (keep != 0x0B)
+ {
+ // Rm in low nibble
+ bytes[3] = regval (&ins->oprs[1],1);
+ }
+
+ // Shifts if any
+ if (keep == 0x0D || keep == 0x0E)
+ {
+ // Shift in bytes 2 and 3
+ if (keep == 0x0D)
+ {
+ // Rs
+ c = regval (&ins->oprs[2],1);
+ bytes[2] |= c;
+
+ c = 0x10; // Set bit 4 in byte[3]
+ }
+ if (keep == 0x0E)
+ {
+ c = (ins->oprs[2].offset) & 0x1F;
+
+ // #imm
+ bytes[2] |= c >> 1;
+ if (c & 0x01)
+ {
+ bytes[3] |= 0x80;
+ }
+ c = 0; // Clr bit 4 in byte[3]
+ }
+ // <shift>
+ c |= shiftval (&ins->oprs[2]) << 5;
+
+ bytes[3] |= c;
+ }
+
+ // reg,imm
+ if (keep == 0x0F)
+ {
+ int shimm;
+
+ shimm = imm_shift (ins->oprs[1].offset);
+
+ if (shimm == -1)
+ {
+ errfunc (ERR_NONFATAL, "cannot create that constant");
+ }
+ bytes[3] = shimm & 0xFF;
+ bytes[2] |= (shimm & 0xF00) >> 8;
+ }
+
+ out (offset, segment, bytes, OUT_RAWDATA+4, NO_SEG, NO_SEG);
+ return;
+
+ case 0x10: // MRS Rd,<psr>
+ ++codes;
+
+ bytes[0] = c | *codes++;
+
+ bytes[1] = *codes++;
+
+ // Rd
+ c = regval (&ins->oprs[0],1);
+
+ bytes[2] = c << 4;
+
+ bytes[3] = 0;
+
+ c = ins->oprs[1].basereg;
+
+ if (c == R_CPSR || c == R_SPSR)
+ {
+ if (c == R_SPSR)
+ {
+ bytes[1] |= 0x40;
+ }
+ }
+ else
+ {
+ errfunc (ERR_NONFATAL, "CPSR or SPSR expected");
+ }
+
+ out (offset, segment, bytes, OUT_RAWDATA+4, NO_SEG, NO_SEG);
+
+ return;
+
+ case 0x11: // MSR <psr>,Rm
+ case 0x12: // MSR <psrf>,Rm
+ case 0x13: // MSR <psrf>,#expression
+ ++codes;
+
+ bytes[0] = c | *codes++;
+
+ bytes[1] = *codes++;
+
+ bytes[2] = *codes;
+
+
+ if (keep == 0x11 || keep == 0x12)
+ {
+ // Rm
+ c = regval (&ins->oprs[1],1);
+
+ bytes[3] = c;
+ }
+ else
+ {
+ int shimm;
+
+ shimm = imm_shift (ins->oprs[1].offset);
+
+ if (shimm == -1)
+ {
+ errfunc (ERR_NONFATAL, "cannot create that constant");
+ }
+ bytes[3] = shimm & 0xFF;
+ bytes[2] |= (shimm & 0xF00) >> 8;
+ }
+
+ c = ins->oprs[0].basereg;
+
+ if ( keep == 0x11)
+ {
+ if ( c == R_CPSR || c == R_SPSR)
+ {
+ if ( c== R_SPSR)
+ {
+ bytes[1] |= 0x40;
+ }
+ }
+ else
+ {
+ errfunc (ERR_NONFATAL, "CPSR or SPSR expected");
+ }
+ }
+ else
+ {
+ if ( c == R_CPSR_FLG || c == R_SPSR_FLG)
+ {
+ if ( c== R_SPSR_FLG)
+ {
+ bytes[1] |= 0x40;
+ }
+ }
+ else
+ {
+ errfunc (ERR_NONFATAL, "CPSR_flg or SPSR_flg expected");
+ }
+ }
+ break;
+
+ case 0x14: // MUL Rd,Rm,Rs
+ case 0x15: // MULA Rd,Rm,Rs,Rn
+ ++codes;
+
+ bytes[0] = c | *codes++;
+
+ bytes[1] = *codes++;
+
+ bytes[3] = *codes;
+
+ // Rd
+ bytes[1] |= regval (&ins->oprs[0],1);
+ if (has_S_code)
+ bytes[1] |= 0x10;
+
+ // Rm
+ bytes[3] |= regval (&ins->oprs[1],1);
+
+ // Rs
+ bytes[2] = regval (&ins->oprs[2],1);
+
+ if (keep == 0x15)
+ {
+ bytes[2] |= regval (&ins->oprs[3],1) << 4;
+ }
+ break;
+
+ case 0x16: // SMLAL RdHi,RdLo,Rm,Rs
+ ++codes;
+
+ bytes[0] = c | *codes++;
+
+ bytes[1] = *codes++;
+
+ bytes[3] = *codes;
+
+ // RdHi
+ bytes[1] |= regval (&ins->oprs[1],1);
+ if (has_S_code)
+ bytes[1] |= 0x10;
+
+ // RdLo
+ bytes[2] = regval (&ins->oprs[0],1) << 4;
+ // Rm
+ bytes[3] |= regval (&ins->oprs[2],1);
+
+ // Rs
+ bytes[2] |= regval (&ins->oprs[3],1);
+
+ break;
+
+ case 0x17: // LDR Rd, expression
+ ++codes;
+
+ bytes[0] = c | *codes++;
+
+ bytes[1] = *codes++;
+
+ // Rd
+ bytes[2] = regval (&ins->oprs[0],1) << 4;
+ if (has_B_code)
+ bytes[1] |= 0x40;
+ if (has_T_code)
+ {
+ errfunc (ERR_NONFATAL, "'T' not allowed in pre-index mode");
+ }
+ if (has_W_code)
+ {
+ errfunc (ERR_NONFATAL, "'!' not allowed");
+ }
+
+ // Rn - implicit R15
+ bytes[1] |= 0xF;
+
+ if (ins->oprs[1].segment != segment)
+ {
+ errfunc (ERR_NONFATAL, "label not in same segment");
+ }
+
+ data = ins->oprs[1].offset - (offset + 8);
+
+ if (data < 0)
+ {
+ data = -data;
+ }
+ else
+ {
+ bytes[1] |= 0x80;
+ }
+
+ if (data >= 0x1000)
+ {
+ errfunc (ERR_NONFATAL, "too long offset");
+ }
+
+ bytes[2] |= ((data & 0xF00) >> 8);
+ bytes[3] = data & 0xFF;
+ break;
+
+ case 0x18: // LDR Rd, [Rn]
+ ++codes;
+
+ bytes[0] = c | *codes++;
+
+ bytes[1] = *codes++;
+
+ // Rd
+ bytes[2] = regval (&ins->oprs[0],1) << 4;
+ if (has_B_code)
+ bytes[1] |= 0x40;
+ if (has_T_code)
+ {
+ bytes[1] |= 0x20; // write-back
+ }
+ else
+ {
+ bytes[0] |= 0x01; // implicit pre-index mode
+ }
+
+ if (has_W_code)
+ {
+ bytes[1] |= 0x20; // write-back
+ }
+
+ // Rn
+ c = regval (&ins->oprs[1],1);
+ bytes[1] |= c;
+
+ if (c == 0x15) // R15
+ data = -8;
+ else
+ data = 0;
+
+ if (data < 0)
+ {
+ data = -data;
+ }
+ else
+ {
+ bytes[1] |= 0x80;
+ }
+
+ bytes[2] |= ((data & 0xF00) >> 8);
+ bytes[3] = data & 0xFF;
+ break;
+
+ case 0x19: // LDR Rd, [Rn,#expression]
+ case 0x20: // LDR Rd, [Rn,Rm]
+ case 0x21: // LDR Rd, [Rn,Rm,shift]
+ ++codes;
+
+ bytes[0] = c | *codes++;
+
+ bytes[1] = *codes++;
+
+ // Rd
+ bytes[2] = regval (&ins->oprs[0],1) << 4;
+ if (has_B_code)
+ bytes[1] |= 0x40;
+
+ // Rn
+ c = regval (&ins->oprs[1],1);
+ bytes[1] |= c;
+
+ if (ins->oprs[ins->operands-1].bracket) // FIXME: Bracket on last operand -> pre-index <--
+ {
+ bytes[0] |= 0x01; // pre-index mode
+ if (has_W_code)
+ {
+ bytes[1] |= 0x20;
+ }
+ if (has_T_code)
+ {
+ errfunc (ERR_NONFATAL, "'T' not allowed in pre-index mode");
+ }
+ }
+ else
+ {
+ if (has_T_code) // Forced write-back in post-index mode
+ {
+ bytes[1] |= 0x20;
+ }
+ if (has_W_code)
+ {
+ errfunc (ERR_NONFATAL, "'!' not allowed in post-index mode");
+ }
+ }
+
+ if (keep == 0x19)
+ {
+ data = ins->oprs[2].offset;
+
+ if (data < 0)
+ {
+ data = -data;
+ }
+ else
+ {
+ bytes[1] |= 0x80;
+ }
+
+ if (data >= 0x1000)
+ {
+ errfunc (ERR_NONFATAL, "too long offset");
+ }
+
+ bytes[2] |= ((data & 0xF00) >> 8);
+ bytes[3] = data & 0xFF;
+ }
+ else
+ {
+ if (ins->oprs[2].minus == 0)
+ {
+ bytes[1] |= 0x80;
+ }
+ c = regval (&ins->oprs[2],1);
+ bytes[3] = c;
+
+ if (keep == 0x21)
+ {
+ c = ins->oprs[3].offset;
+ if (c > 0x1F)
+ {
+ errfunc (ERR_NONFATAL, "too large shiftvalue");
+ c = c & 0x1F;
+ }
+
+ bytes[2] |= c >> 1;
+ if (c & 0x01)
+ {
+ bytes[3] |= 0x80;
+ }
+ bytes[3] |= shiftval (&ins->oprs[3]) << 5;
+ }
+ }
+
+ break;
+
+ case 0x22: // LDRH Rd, expression
+ ++codes;
+
+ bytes[0] = c | 0x01; // Implicit pre-index
+
+ bytes[1] = *codes++;
+
+ // Rd
+ bytes[2] = regval (&ins->oprs[0],1) << 4;
+
+ // Rn - implicit R15
+ bytes[1] |= 0xF;
+
+ if (ins->oprs[1].segment != segment)
+ {
+ errfunc (ERR_NONFATAL, "label not in same segment");
+ }
+
+ data = ins->oprs[1].offset - (offset + 8);
+
+ if (data < 0)
+ {
+ data = -data;
+ }
+ else
+ {
+ bytes[1] |= 0x80;
+ }
+
+ if (data >= 0x100)
+ {
+ errfunc (ERR_NONFATAL, "too long offset");
+ }
+ bytes[3] = *codes++;
+
+ bytes[2] |= ((data & 0xF0) >> 4);
+ bytes[3] |= data & 0xF;
+ break;
+
+ case 0x23: // LDRH Rd, Rn
+ ++codes;
+
+ bytes[0] = c | 0x01; // Implicit pre-index
+
+ bytes[1] = *codes++;
+
+ // Rd
+ bytes[2] = regval (&ins->oprs[0],1) << 4;
+
+ // Rn
+ c = regval (&ins->oprs[1],1);
+ bytes[1] |= c;
+
+ if (c == 0x15) // R15
+ data = -8;
+ else
+ data = 0;
+
+ if (data < 0)
+ {
+ data = -data;
+ }
+ else
+ {
+ bytes[1] |= 0x80;
+ }
+
+ if (data >= 0x100)
+ {
+ errfunc (ERR_NONFATAL, "too long offset");
+ }
+ bytes[3] = *codes++;
+
+ bytes[2] |= ((data & 0xF0) >> 4);
+ bytes[3] |= data & 0xF;
+ break;
+
+ case 0x24: // LDRH Rd, Rn, expression
+ case 0x25: // LDRH Rd, Rn, Rm
+ ++codes;
+
+ bytes[0] = c;
+
+ bytes[1] = *codes++;
+
+ // Rd
+ bytes[2] = regval (&ins->oprs[0],1) << 4;
+
+ // Rn
+ c = regval (&ins->oprs[1],1);
+ bytes[1] |= c;
+
+ if (ins->oprs[ins->operands-1].bracket) // FIXME: Bracket on last operand -> pre-index <--
+ {
+ bytes[0] |= 0x01; // pre-index mode
+ if (has_W_code)
+ {
+ bytes[1] |= 0x20;
+ }
+ }
+ else
+ {
+ if (has_W_code)
+ {
+ errfunc (ERR_NONFATAL, "'!' not allowed in post-index mode");
+ }
+ }
+
+ bytes[3] = *codes++;
+
+ if (keep == 0x24)
+ {
+ data = ins->oprs[2].offset;
+
+ if (data < 0)
+ {
+ data = -data;
+ }
+ else
+ {
+ bytes[1] |= 0x80;
+ }
+
+ if (data >= 0x100)
+ {
+ errfunc (ERR_NONFATAL, "too long offset");
+ }
+
+ bytes[2] |= ((data & 0xF0) >> 4);
+ bytes[3] |= data & 0xF;
+ }
+ else
+ {
+ if (ins->oprs[2].minus == 0)
+ {
+ bytes[1] |= 0x80;
+ }
+ c = regval (&ins->oprs[2],1);
+ bytes[3] |= c;
+
+ }
+ break;
+
+ case 0x26: // LDM/STM Rn, {reg-list}
+ ++codes;
+
+ bytes[0] = c;
+
+ bytes[0] |= ( *codes >> 4) & 0xF;
+ bytes[1] = ( *codes << 4) & 0xF0;
+ ++codes;
+
+ if (has_W_code)
+ {
+ bytes[1] |= 0x20;
+ }
+ if (has_F_code)
+ {
+ bytes[1] |= 0x40;
+ }
+
+ // Rn
+ bytes[1] |= regval (&ins->oprs[0],1);
+
+ data = ins->oprs[1].basereg;
+
+ bytes[2] = ((data >> 8) & 0xFF);
+ bytes[3] = (data & 0xFF);
+
+ break;
+
+ case 0x27: // SWP Rd, Rm, [Rn]
+ ++codes;
+
+ bytes[0] = c;
+
+ bytes[0] |= *codes++;
+
+ bytes[1] = regval (&ins->oprs[2],1);
+ if (has_B_code)
+ {
+ bytes[1] |= 0x40;
+ }
+ bytes[2] = regval (&ins->oprs[0],1) << 4;
+ bytes[3] = *codes++;
+ bytes[3] |= regval (&ins->oprs[1],1);
+ break;
+
+ default:
+ errfunc (ERR_FATAL, "unknown decoding of instruction");
+
+ bytes[0] = c;
+ // And a fix nibble
+ ++codes;
+ bytes[0] |= *codes++;
+
+ if ( *codes == 0x01) // An I bit
+ {
+
+ }
+ if ( *codes == 0x02) // An I bit
+ {
+
+ }
+ ++codes;
+ }
+ out (offset, segment, bytes, OUT_RAWDATA+4, NO_SEG, NO_SEG);
+}
+
+*)
+{$endif dummy}
+
+ constructor tai_thumb_func.create;
+ begin
+ inherited create;
+ typ:=ait_thumb_func;
+ end;
+
+begin
+ cai_align:=tai_align;
+end.
+
diff --git a/closures/compiler/arm/agarmgas.pas b/closures/compiler/arm/agarmgas.pas
new file mode 100644
index 0000000000..af037b2ab8
--- /dev/null
+++ b/closures/compiler/arm/agarmgas.pas
@@ -0,0 +1,326 @@
+{
+ Copyright (c) 2003 by Florian Klaempfl
+
+ This unit implements an asm for the ARM
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+{ This unit implements the GNU Assembler writer for the ARM
+}
+
+unit agarmgas;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ globtype,
+ aasmtai,aasmdata,
+ aggas,
+ cpubase;
+
+ type
+ TARMGNUAssembler=class(TGNUassembler)
+ constructor create(smart: boolean); override;
+ function MakeCmdLine: TCmdStr; override;
+ procedure WriteExtraHeader; override;
+ end;
+
+ TArmInstrWriter=class(TCPUInstrWriter)
+ procedure WriteInstruction(hp : tai);override;
+ end;
+
+ TArmAppleGNUAssembler=class(TAppleGNUassembler)
+ constructor create(smart: boolean); override;
+ end;
+
+
+ const
+ gas_shiftmode2str : array[tshiftmode] of string[3] = (
+ '','lsl','lsr','asr','ror','rrx');
+
+ implementation
+
+ uses
+ cutils,globals,verbose,
+ systems,
+ assemble,
+ cpuinfo,aasmcpu,
+ itcpugas,
+ cgbase,cgutils;
+
+{****************************************************************************}
+{ GNU Arm Assembler writer }
+{****************************************************************************}
+
+ constructor TArmGNUAssembler.create(smart: boolean);
+ begin
+ inherited create(smart);
+ InstrWriter := TArmInstrWriter.create(self);
+ end;
+
+
+ function TArmGNUAssembler.MakeCmdLine: TCmdStr;
+ begin
+ result:=inherited MakeCmdLine;
+ if (current_settings.fputype = fpu_soft) then
+ result:='-mfpu=softvfp '+result;
+
+ if current_settings.cputype = cpu_armv7m then
+ result:='-march=armv7m -mthumb -mthumb-interwork '+result;
+ end;
+
+ procedure TArmGNUAssembler.WriteExtraHeader;
+ begin
+ inherited WriteExtraHeader;
+ if current_settings.cputype in cpu_thumb2 then
+ AsmWriteLn(#9'.syntax unified');
+ end;
+
+{****************************************************************************}
+{ GNU/Apple ARM Assembler writer }
+{****************************************************************************}
+
+ constructor TArmAppleGNUAssembler.create(smart: boolean);
+ begin
+ inherited create(smart);
+ InstrWriter := TArmInstrWriter.create(self);
+ end;
+
+
+{****************************************************************************}
+{ Helper routines for Instruction Writer }
+{****************************************************************************}
+
+ function getreferencestring(var ref : treference) : string;
+ var
+ s : string;
+ begin
+ with ref do
+ begin
+{$ifdef extdebug}
+ // if base=NR_NO then
+ // internalerror(200308292);
+
+ // if ((index<>NR_NO) or (shiftmode<>SM_None)) and ((offset<>0) or (symbol<>nil)) then
+ // internalerror(200308293);
+{$endif extdebug}
+
+ if assigned(symbol) then
+ begin
+ if (base<>NR_NO) and not(is_pc(base)) then
+ internalerror(200309011);
+ s:=symbol.name;
+ if offset<0 then
+ s:=s+tostr(offset)
+ else if offset>0 then
+ s:=s+'+'+tostr(offset);
+ end
+ else
+ begin
+ s:='['+gas_regname(base);
+ if addressmode=AM_POSTINDEXED then
+ s:=s+']';
+ if index<>NR_NO then
+ begin
+ if signindex<0 then
+ s:=s+', -'
+ else
+ s:=s+', ';
+
+ s:=s+gas_regname(index);
+
+ if shiftmode<>SM_None then
+ s:=s+', '+gas_shiftmode2str[shiftmode]+' #'+tostr(shiftimm);
+ end
+ else if offset<>0 then
+ s:=s+', #'+tostr(offset);
+
+ case addressmode of
+ AM_OFFSET:
+ s:=s+']';
+ AM_PREINDEXED:
+ s:=s+']!';
+ end;
+ end;
+
+ end;
+ getreferencestring:=s;
+ end;
+
+
+ const
+ shiftmode2str: array[tshiftmode] of string[3] = ('','lsl','lsr','asr','ror','rrx');
+
+ function getopstr(const o:toper) : string;
+ var
+ hs : string;
+ first : boolean;
+ r : tsuperregister;
+ begin
+ case o.typ of
+ top_reg:
+ getopstr:=gas_regname(o.reg);
+ top_shifterop:
+ begin
+ if (o.shifterop^.rs<>NR_NO) and (o.shifterop^.shiftimm=0) then
+ getopstr:=shiftmode2str[o.shifterop^.shiftmode]+' '+gas_regname(o.shifterop^.rs)
+ else if (o.shifterop^.rs=NR_NO) then
+ getopstr:=shiftmode2str[o.shifterop^.shiftmode]+' #'+tostr(o.shifterop^.shiftimm)
+ else internalerror(200308282);
+ end;
+ top_const:
+ getopstr:='#'+tostr(longint(o.val));
+ top_regset:
+ begin
+ getopstr:='{';
+ first:=true;
+ for r:=RS_R0 to RS_R15 do
+ if r in o.regset^ then
+ begin
+ if not(first) then
+ getopstr:=getopstr+',';
+ getopstr:=getopstr+gas_regname(newreg(o.regtyp,r,o.subreg));
+ first:=false;
+ end;
+ getopstr:=getopstr+'}';
+ end;
+ top_conditioncode:
+ getopstr:=cond2str[o.cc];
+ top_modeflags:
+ begin
+ getopstr:='';
+ if mfA in o.modeflags then getopstr:=getopstr+'a';
+ if mfI in o.modeflags then getopstr:=getopstr+'i';
+ if mfF in o.modeflags then getopstr:=getopstr+'f';
+ end;
+ top_ref:
+ if o.ref^.refaddr=addr_full then
+ begin
+ hs:=o.ref^.symbol.name;
+ if o.ref^.offset>0 then
+ hs:=hs+'+'+tostr(o.ref^.offset)
+ else
+ if o.ref^.offset<0 then
+ hs:=hs+tostr(o.ref^.offset);
+ getopstr:=hs;
+ end
+ else
+ getopstr:=getreferencestring(o.ref^);
+ else
+ internalerror(2002070604);
+ end;
+ end;
+
+
+ Procedure TArmInstrWriter.WriteInstruction(hp : tai);
+ var op: TAsmOp;
+ postfix,s: string;
+ i: byte;
+ sep: string[3];
+ begin
+ op:=taicpu(hp).opcode;
+ if current_settings.cputype in cpu_thumb2 then
+ begin
+ postfix:='';
+ if taicpu(hp).wideformat then
+ postfix:='.w';
+
+ if taicpu(hp).ops = 0 then
+ s:=#9+gas_op2str[op]+' '+cond2str[taicpu(hp).condition]+oppostfix2str[taicpu(hp).oppostfix]
+ else
+ s:=#9+gas_op2str[op]+oppostfix2str[taicpu(hp).oppostfix]+postfix+cond2str[taicpu(hp).condition]; // Conditional infixes are deprecated in unified syntax
+ end
+ else
+ s:=#9+gas_op2str[op]+cond2str[taicpu(hp).condition]+oppostfix2str[taicpu(hp).oppostfix];
+ if taicpu(hp).ops<>0 then
+ begin
+ sep:=#9;
+ for i:=0 to taicpu(hp).ops-1 do
+ begin
+ // debug code
+ // writeln(s);
+ // writeln(taicpu(hp).fileinfo.line);
+
+ { LDM and STM use references as first operand but they are written like a register }
+ if (i=0) and (op in [A_LDM,A_STM,A_FSTM,A_FLDM]) then
+ begin
+ case taicpu(hp).oper[0]^.typ of
+ top_ref:
+ begin
+ s:=s+sep+gas_regname(taicpu(hp).oper[0]^.ref^.index);
+ if taicpu(hp).oper[0]^.ref^.addressmode=AM_PREINDEXED then
+ s:=s+'!';
+ end;
+ top_reg:
+ s:=s+sep+gas_regname(taicpu(hp).oper[0]^.reg);
+ else
+ internalerror(200311292);
+ end;
+ end
+ { register count of SFM and LFM is written without # }
+ else if (i=1) and (op in [A_SFM,A_LFM]) then
+ begin
+ case taicpu(hp).oper[1]^.typ of
+ top_const:
+ s:=s+sep+tostr(taicpu(hp).oper[1]^.val);
+ else
+ internalerror(200311292);
+ end;
+ end
+ else
+ s:=s+sep+getopstr(taicpu(hp).oper[i]^);
+
+ sep:=',';
+ end;
+ end;
+ owner.AsmWriteLn(s);
+ end;
+
+
+ const
+ as_arm_gas_info : tasminfo =
+ (
+ id : as_gas;
+
+ idtxt : 'AS';
+ asmbin : 'as';
+ asmcmd : '-o $OBJ $ASM';
+ supported_targets : [system_arm_linux,system_arm_wince,system_arm_gba,system_arm_palmos,system_arm_nds,system_arm_embedded,system_arm_symbian];
+ flags : [af_allowdirect,af_needar,af_smartlink_sections];
+ labelprefix : '.L';
+ comment : '# ';
+ );
+
+ as_arm_gas_darwin_info : tasminfo =
+ (
+ id : as_darwin;
+ idtxt : 'AS-Darwin';
+ asmbin : 'as';
+ asmcmd : '-o $OBJ $ASM -arch $ARCH';
+ supported_targets : [system_arm_darwin];
+ flags : [af_allowdirect,af_needar,af_smartlink_sections,af_supports_dwarf,af_stabs_use_function_absolute_addresses];
+ labelprefix : 'L';
+ comment : '# ';
+ );
+
+
+begin
+ RegisterAssembler(as_arm_gas_info,TARMGNUAssembler);
+ RegisterAssembler(as_arm_gas_darwin_info,TArmAppleGNUAssembler);
+end.
diff --git a/closures/compiler/arm/aoptcpu.pas b/closures/compiler/arm/aoptcpu.pas
new file mode 100644
index 0000000000..3f116a5dfd
--- /dev/null
+++ b/closures/compiler/arm/aoptcpu.pas
@@ -0,0 +1,343 @@
+{
+ Copyright (c) 1998-2002 by Jonas Maebe, member of the Free Pascal
+ Development Team
+
+ This unit implements the ARM optimizer object
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+
+
+Unit aoptcpu;
+
+{$i fpcdefs.inc}
+
+Interface
+
+uses cpubase, aasmtai, aopt, aoptcpub;
+
+Type
+ TCpuAsmOptimizer = class(TAsmOptimizer)
+ { uses the same constructor as TAopObj }
+ function PeepHoleOptPass1Cpu(var p: tai): boolean; override;
+ procedure PeepHoleOptPass2;override;
+ End;
+
+
+ TCpuThumb2AsmOptimizer = class(TCpuAsmOptimizer)
+ { uses the same constructor as TAopObj }
+ procedure PeepHoleOptPass2;override;
+ End;
+
+Implementation
+
+ uses
+ verbose,
+ aasmbase,aasmcpu;
+
+ function CanBeCond(p : tai) : boolean;
+ begin
+ result:=
+ (p.typ=ait_instruction) and
+ (taicpu(p).condition=C_None) and
+ ((taicpu(p).opcode<>A_BLX) or
+ (taicpu(p).oper[0]^.typ=top_reg));
+ end;
+
+
+ function TCpuAsmOptimizer.PeepHoleOptPass1Cpu(var p: tai): boolean;
+ var
+ next1: tai;
+ hp1: tai;
+ begin
+ result := false;
+ case p.typ of
+ ait_instruction:
+ begin
+ case taicpu(p).opcode of
+ A_MOV:
+ begin
+ { fold
+ mov reg1,reg0, shift imm1
+ mov reg1,reg1, shift imm2
+ to
+ mov reg1,reg0, shift imm1+imm2
+ }
+ if (taicpu(p).ops=3) and
+ (taicpu(p).oper[0]^.typ = top_reg) and
+ (taicpu(p).oper[2]^.typ = top_shifterop) and
+ (taicpu(p).oper[2]^.shifterop^.rs = NR_NO) and
+ getnextinstruction(p,next1) and
+ (next1.typ = ait_instruction) and
+ (taicpu(next1).opcode = A_MOV) and
+ (taicpu(p).condition=taicpu(next1).condition) and
+ (taicpu(next1).ops=3) and
+ (taicpu(next1).oper[0]^.typ = top_reg) and
+ (taicpu(p).oper[0]^.reg=taicpu(next1).oper[0]^.reg) and
+ (taicpu(next1).oper[1]^.typ = top_reg) and
+ (taicpu(p).oper[0]^.reg=taicpu(next1).oper[1]^.reg) and
+ (taicpu(next1).oper[2]^.typ = top_shifterop) and
+ (taicpu(next1).oper[2]^.shifterop^.rs = NR_NO) and
+ (taicpu(p).oper[2]^.shifterop^.shiftmode=taicpu(next1).oper[2]^.shifterop^.shiftmode) then
+ begin
+ inc(taicpu(p).oper[2]^.shifterop^.shiftimm,taicpu(next1).oper[2]^.shifterop^.shiftimm);
+ { avoid overflows }
+ if taicpu(p).oper[2]^.shifterop^.shiftimm>31 then
+ case taicpu(p).oper[2]^.shifterop^.shiftmode of
+ SM_ROR:
+ taicpu(p).oper[2]^.shifterop^.shiftimm:=taicpu(p).oper[2]^.shifterop^.shiftimm and 31;
+ SM_ASR:
+ taicpu(p).oper[2]^.shifterop^.shiftimm:=31;
+ SM_LSR,
+ SM_LSL:
+ begin
+ hp1:=taicpu.op_reg_const(A_MOV,taicpu(p).oper[0]^.reg,0);
+ InsertLLItem(p.previous, p.next, hp1);
+ p.free;
+ p:=hp1;
+ end;
+ else
+ internalerror(2008072803);
+ end;
+ asml.remove(next1);
+ next1.free;
+ result := true;
+ end;
+ end;
+ A_AND:
+ begin
+ {
+ change
+ and reg2,reg1,const1
+ and reg2,reg2,const2
+ to
+ and reg2,reg1,(const1 and const2)
+ }
+ if (taicpu(p).oper[0]^.typ = top_reg) and
+ (taicpu(p).oper[1]^.typ = top_reg) and
+ (taicpu(p).oper[2]^.typ = top_const) and
+ GetNextInstruction(p, hp1) and
+ (tai(hp1).typ = ait_instruction) and
+ (taicpu(hp1).opcode = A_AND) and
+ (taicpu(p).condition=taicpu(hp1).condition) and
+ (taicpu(p).oppostfix=PF_None) and
+ (taicpu(hp1).oper[0]^.typ = top_reg) and
+ (taicpu(hp1).oper[1]^.typ = top_reg) and
+ (taicpu(hp1).oper[2]^.typ = top_const) and
+ (taicpu(p).oper[0]^.reg = taicpu(hp1).oper[0]^.reg) and
+ (taicpu(hp1).oper[0]^.reg = taicpu(hp1).oper[1]^.reg) then
+ begin
+ taicpu(p).loadConst(2,taicpu(p).oper[2]^.val and taicpu(hp1).oper[2]^.val);
+ taicpu(p).oppostfix:=taicpu(hp1).oppostfix;
+ asml.remove(hp1);
+ hp1.free;
+ end;
+ end;
+ end;
+ end;
+ end;
+ end;
+
+
+ { instructions modifying the CPSR can be only the last instruction }
+ function MustBeLast(p : tai) : boolean;
+ begin
+ Result:=(p.typ=ait_instruction) and
+ ((taicpu(p).opcode in [A_BL,A_BLX,A_CMP,A_CMN,A_SWI,A_TEQ,A_TST,A_CMF,A_CMFE {,A_MSR}]) or
+ ((taicpu(p).ops>=1) and (taicpu(p).oper[0]^.typ=top_reg) and (taicpu(p).oper[0]^.reg=NR_PC)) or
+ (taicpu(p).oppostfix=PF_S));
+ end;
+
+
+ procedure TCpuAsmOptimizer.PeepHoleOptPass2;
+ var
+ p,hp1,hp2: tai;
+ l : longint;
+ condition : tasmcond;
+ hp3: tai;
+ WasLast: boolean;
+ { UsedRegs, TmpUsedRegs: TRegSet; }
+
+ begin
+ p := BlockStart;
+ { UsedRegs := []; }
+ while (p <> BlockEnd) Do
+ begin
+ { UpdateUsedRegs(UsedRegs, tai(p.next)); }
+ case p.Typ Of
+ Ait_Instruction:
+ begin
+ case taicpu(p).opcode Of
+ A_B:
+ if taicpu(p).condition<>C_None then
+ begin
+ { check for
+ Bxx xxx
+ <several instructions>
+ xxx:
+ }
+ l:=0;
+ WasLast:=False;
+ GetNextInstruction(p, hp1);
+ while assigned(hp1) and
+ (l<=4) and
+ CanBeCond(hp1) and
+ { stop on labels }
+ not(hp1.typ=ait_label) do
+ begin
+ inc(l);
+ if MustBeLast(hp1) then
+ begin
+ WasLast:=True;
+ GetNextInstruction(hp1,hp1);
+ break;
+ end
+ else
+ GetNextInstruction(hp1,hp1);
+ end;
+ if assigned(hp1) then
+ begin
+ if FindLabel(tasmlabel(taicpu(p).oper[0]^.ref^.symbol),hp1) then
+ begin
+ if (l<=4) and (l>0) then
+ begin
+ condition:=inverse_cond(taicpu(p).condition);
+ hp2:=p;
+ GetNextInstruction(p,hp1);
+ p:=hp1;
+ repeat
+ if hp1.typ=ait_instruction then
+ taicpu(hp1).condition:=condition;
+ if MustBeLast(hp1) then
+ begin
+ GetNextInstruction(hp1,hp1);
+ break;
+ end
+ else
+ GetNextInstruction(hp1,hp1);
+ until not(assigned(hp1)) or
+ not(CanBeCond(hp1)) or
+ (hp1.typ=ait_label);
+ { wait with removing else GetNextInstruction could
+ ignore the label if it was the only usage in the
+ jump moved away }
+ tasmlabel(taicpu(hp2).oper[0]^.ref^.symbol).decrefs;
+ asml.remove(hp2);
+ hp2.free;
+ continue;
+ end;
+ end
+ else
+ { do not perform further optimizations if there is inctructon
+ in block #1 which can not be optimized.
+ }
+ if not WasLast then
+ begin
+ { check further for
+ Bcc xxx
+ <several instructions 1>
+ B yyy
+ xxx:
+ <several instructions 2>
+ yyy:
+ }
+ { hp2 points to jmp yyy }
+ hp2:=hp1;
+ { skip hp1 to xxx }
+ GetNextInstruction(hp1, hp1);
+ if assigned(hp2) and
+ assigned(hp1) and
+ (l<=3) and
+ (hp2.typ=ait_instruction) and
+ (taicpu(hp2).is_jmp) and
+ (taicpu(hp2).condition=C_None) and
+ { real label and jump, no further references to the
+ label are allowed }
+ (tasmlabel(taicpu(p).oper[0]^.ref^.symbol).getrefs=2) and
+ FindLabel(tasmlabel(taicpu(p).oper[0]^.ref^.symbol),hp1) then
+ begin
+ l:=0;
+ { skip hp1 to <several moves 2> }
+ GetNextInstruction(hp1, hp1);
+ while assigned(hp1) and
+ CanBeCond(hp1) do
+ begin
+ inc(l);
+ GetNextInstruction(hp1, hp1);
+ end;
+ { hp1 points to yyy: }
+ if assigned(hp1) and
+ FindLabel(tasmlabel(taicpu(hp2).oper[0]^.ref^.symbol),hp1) then
+ begin
+ condition:=inverse_cond(taicpu(p).condition);
+ GetNextInstruction(p,hp1);
+ hp3:=p;
+ p:=hp1;
+ repeat
+ if hp1.typ=ait_instruction then
+ taicpu(hp1).condition:=condition;
+ GetNextInstruction(hp1,hp1);
+ until not(assigned(hp1)) or
+ not(CanBeCond(hp1));
+ { hp2 is still at jmp yyy }
+ GetNextInstruction(hp2,hp1);
+ { hp2 is now at xxx: }
+ condition:=inverse_cond(condition);
+ GetNextInstruction(hp1,hp1);
+ { hp1 is now at <several movs 2> }
+ repeat
+ taicpu(hp1).condition:=condition;
+ GetNextInstruction(hp1,hp1);
+ until not(assigned(hp1)) or
+ not(CanBeCond(hp1)) or
+ (hp1.typ=ait_label);
+ {
+ asml.remove(hp1.next)
+ hp1.next.free;
+ asml.remove(hp1);
+ hp1.free;
+ }
+ { remove Bcc }
+ tasmlabel(taicpu(hp3).oper[0]^.ref^.symbol).decrefs;
+ asml.remove(hp3);
+ hp3.free;
+ { remove jmp }
+ tasmlabel(taicpu(hp2).oper[0]^.ref^.symbol).decrefs;
+ asml.remove(hp2);
+ hp2.free;
+ continue;
+ end;
+ end;
+ end;
+ end;
+ end;
+ end;
+ end;
+ end;
+ p := tai(p.next)
+ end;
+ end;
+
+
+ procedure TCpuThumb2AsmOptimizer.PeepHoleOptPass2;
+ begin
+ { TODO: Add optimizer code }
+ end;
+
+begin
+ casmoptimizer:=TCpuAsmOptimizer;
+End.
diff --git a/closures/compiler/arm/aoptcpub.pas b/closures/compiler/arm/aoptcpub.pas
new file mode 100644
index 0000000000..e85f7bea7d
--- /dev/null
+++ b/closures/compiler/arm/aoptcpub.pas
@@ -0,0 +1,120 @@
+ {
+ Copyright (c) 1998-2002 by Jonas Maebe, member of the Free Pascal
+ Development Team
+
+ This unit contains several types and constants necessary for the
+ optimizer to work on the ARM architecture
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+Unit aoptcpub; { Assembler OPTimizer CPU specific Base }
+
+{$i fpcdefs.inc}
+
+{ enable the following define if memory references can have both a base and }
+{ index register in 1 operand }
+
+{$define RefsHaveIndexReg}
+
+{ enable the following define if memory references can have a scaled index }
+
+{ define RefsHaveScale}
+
+{ enable the following define if memory references can have a segment }
+{ override }
+
+{ define RefsHaveSegment}
+
+Interface
+
+Uses
+ cpubase,aasmcpu,AOptBase;
+
+Type
+
+{ type of a normal instruction }
+ TInstr = Taicpu;
+ PInstr = ^TInstr;
+
+{ ************************************************************************* }
+{ **************************** TCondRegs ********************************** }
+{ ************************************************************************* }
+{ Info about the conditional registers }
+ TCondRegs = Object
+ Constructor Init;
+ Destructor Done;
+ End;
+
+{ ************************************************************************* }
+{ **************************** TAoptBaseCpu ******************************* }
+{ ************************************************************************* }
+
+ TAoptBaseCpu = class(TAoptBase)
+ End;
+
+
+{ ************************************************************************* }
+{ ******************************* Constants ******************************* }
+{ ************************************************************************* }
+Const
+
+{ the maximum number of things (registers, memory, ...) a single instruction }
+{ changes }
+
+ MaxCh = 3;
+
+{ the maximum number of operands an instruction has }
+
+ MaxOps = 3;
+
+{Oper index of operand that contains the source (reference) with a load }
+{instruction }
+
+ LoadSrc = 0;
+
+{Oper index of operand that contains the destination (register) with a load }
+{instruction }
+
+ LoadDst = 1;
+
+{Oper index of operand that contains the source (register) with a store }
+{instruction }
+
+ StoreSrc = 0;
+
+{Oper index of operand that contains the destination (reference) with a load }
+{instruction }
+
+ StoreDst = 1;
+
+ aopt_uncondjmp = A_B;
+ aopt_condjmp = A_B;
+
+Implementation
+
+{ ************************************************************************* }
+{ **************************** TCondRegs ********************************** }
+{ ************************************************************************* }
+Constructor TCondRegs.init;
+Begin
+End;
+
+Destructor TCondRegs.Done; {$ifdef inl} inline; {$endif inl}
+Begin
+End;
+
+End.
diff --git a/closures/compiler/arm/aoptcpuc.pas b/closures/compiler/arm/aoptcpuc.pas
new file mode 100644
index 0000000000..7532a77fa3
--- /dev/null
+++ b/closures/compiler/arm/aoptcpuc.pas
@@ -0,0 +1,38 @@
+ {
+ Copyright (c) 1998-2002 by Jonas Maebe, member of the Free Pascal
+ Development Team
+
+ This unit contains the processor specific implementation of the
+ assembler optimizer common subexpression elimination object.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit aoptcpuc;
+
+Interface
+
+Uses
+ AOptCs;
+
+Type
+ TRegInfoCpu = Object(TRegInfo)
+ End;
+
+
+Implementation
+
+End.
diff --git a/closures/compiler/arm/aoptcpud.pas b/closures/compiler/arm/aoptcpud.pas
new file mode 100644
index 0000000000..2df7e2e49e
--- /dev/null
+++ b/closures/compiler/arm/aoptcpud.pas
@@ -0,0 +1,40 @@
+{
+ Copyright (c) 1998-2002 by Jonas Maebe, member of the Free Pascal
+ Development Team
+
+ This unit contains the processor specific implementation of the
+ assembler optimizer data flow analyzer.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+Unit aoptcpud;
+
+{$i fpcdefs.inc}
+
+Interface
+
+uses
+ AOptDA;
+
+Type
+ TAOptDFACpu = class(TAOptDFA)
+ End;
+
+Implementation
+
+
+End.
diff --git a/closures/compiler/arm/armatt.inc b/closures/compiler/arm/armatt.inc
new file mode 100644
index 0000000000..efc974dd25
--- /dev/null
+++ b/closures/compiler/arm/armatt.inc
@@ -0,0 +1,208 @@
+{ don't edit, this file is generated from armins.dat }
+(
+'none',
+'abs',
+'acs',
+'asn',
+'atn',
+'adc',
+'add',
+'adf',
+'and',
+'b',
+'bic',
+'bl',
+'blx',
+'bkpt',
+'bx',
+'cdp',
+'cmf',
+'cmfe',
+'cmn',
+'cmp',
+'clz',
+'cnf',
+'cos',
+'cps',
+'cpsid',
+'cpsie',
+'dvf',
+'eor',
+'exp',
+'fdv',
+'flt',
+'fix',
+'fml',
+'frd',
+'ldc',
+'ldm',
+'ldrbt',
+'ldrb',
+'ldr',
+'ldrh',
+'ldrsb',
+'ldrsh',
+'ldrt',
+'ldf',
+'lfm',
+'lgn',
+'log',
+'mcr',
+'mla',
+'mov',
+'mrs',
+'msr',
+'mnf',
+'muf',
+'mul',
+'mvf',
+'mvn',
+'nop',
+'orr',
+'rdf',
+'rfs',
+'rfc',
+'rmf',
+'rpw',
+'rsb',
+'rsc',
+'rsf',
+'rnd',
+'pol',
+'sbc',
+'sfm',
+'sin',
+'smlal',
+'smull',
+'sqt',
+'suf',
+'stf',
+'stm',
+'str',
+'strb',
+'strbt',
+'strh',
+'strt',
+'sub',
+'swi',
+'swp',
+'swpb',
+'tan',
+'teq',
+'tst',
+'umlal',
+'umull',
+'wfs',
+'ldrd',
+'mcrr',
+'mrrc',
+'pld',
+'qadd',
+'qdadd',
+'qdsub',
+'qsub',
+'smlabb',
+'smlabt',
+'smlatb',
+'smlatt',
+'smlalbb',
+'smlalbt',
+'smlaltb',
+'smlaltt',
+'smlawb',
+'smlawt',
+'smulbb',
+'smulbt',
+'smultb',
+'smultt',
+'smulwb',
+'smulwt',
+'strd',
+'fabsd',
+'fabss',
+'faddd',
+'fadds',
+'fcmpd',
+'fcmped',
+'fcmpes',
+'fcmpezd',
+'fcmpezs',
+'fcmps',
+'fcmpzd',
+'fcmpzs',
+'fcpyd',
+'fcpys',
+'fcvtds',
+'fcvtsd',
+'fdivd',
+'fdivs',
+'fldd',
+'fldm',
+'flds',
+'fmacd',
+'fmacs',
+'fmdhr',
+'fmdlr',
+'fmrdh',
+'fmrdl',
+'fmrs',
+'fmrx',
+'fmscd',
+'fmscs',
+'fmsr',
+'fmstat',
+'fmuld',
+'fmuls',
+'fmxr',
+'fnegd',
+'fnegs',
+'fnmacd',
+'fnmacs',
+'fnmscd',
+'fnmscs',
+'fnmuld',
+'fnmuls',
+'fsitod',
+'fsitos',
+'fsqrtd',
+'fsqrts',
+'fstd',
+'fstm',
+'fsts',
+'fsubd',
+'fsubs',
+'ftosid',
+'ftosis',
+'ftouid',
+'ftouis',
+'fuitod',
+'fuitos',
+'fmdrr',
+'fmrrd',
+'asr',
+'lsr',
+'lsl',
+'ror',
+'sdiv',
+'udiv',
+'movt',
+'ldrex',
+'strex',
+'it',
+'ite',
+'itt',
+'itee',
+'itte',
+'itet',
+'ittt',
+'iteee',
+'ittee',
+'itete',
+'ittte',
+'iteet',
+'ittet',
+'itett',
+'itttt',
+'tbb',
+'tbh'
+);
diff --git a/closures/compiler/arm/armatts.inc b/closures/compiler/arm/armatts.inc
new file mode 100644
index 0000000000..b11094b987
--- /dev/null
+++ b/closures/compiler/arm/armatts.inc
@@ -0,0 +1,208 @@
+{ don't edit, this file is generated from armins.dat }
+(
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE
+);
diff --git a/closures/compiler/arm/armins.dat b/closures/compiler/arm/armins.dat
new file mode 100644
index 0000000000..39a3b15d56
--- /dev/null
+++ b/closures/compiler/arm/armins.dat
@@ -0,0 +1,628 @@
+;
+; Table of assembler instructions for Free Pascal
+; adapted from Netwide Assembler by Florian Klaempfl
+;
+;
+; The Netwide Assembler is copyright (C) 1996 Simon Tatham and
+; Julian Hall. All rights reserved. The software is
+; redistributable under the licence given in the file "Licence"
+; distributed in the NASM archive.
+;
+; Format of file: all four fields must be present on every functional
+; line. Hence `void' for no-operand instructions, and `\0' for such
+; as EQU. If the last three fields are all `ignore', no action is
+; taken except to register the opcode as being present.
+;
+;
+; 'ignore' means no instruc
+; 'void' means instruc with zero operands
+;
+; Third field has a first byte indicating how to
+; put together the bits, and then some codes
+; that may be used at will (see assemble.c)
+;
+; \1 - 24 bit pc-rel offset [B, BL]
+; \2 - 24 bit imm value [SWI]
+; \3 - 3 byte code [BX]
+;
+; \4 - reg,reg,reg [AND,EOR,SUB,RSB,ADD,ADC,SBC,RSC,ORR,BIC]
+; \5 - reg,reg,reg,<shift>reg [-"-]
+; \6 - reg,reg,reg,<shift>#imm [-"-]
+; \7 - reg,reg,#imm [-"-]
+;
+; \x8 - reg,reg [MOV,MVN]
+; \x9 - reg,reg,<shift>reg [-"-]
+; \xA - reg,reg,<shift>#imm [-"-]
+; \xB - reg,#imm [-"-]
+;
+; \xC - reg,reg [CMP,CMN,TEQ,TST]
+; \xD - reg,reg,<shift>reg [-"-]
+; \xE - reg,reg,<shift>#imm [-"-]
+; \xF - reg,#imm [-"-]
+;
+; \xFx - floating point instructions
+; Floating point instruction format information, taken from the linux kernel,
+; for detailed tables, see aasmcpu.pas
+;
+; ARM Floating Point Instruction Classes
+; | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+; |c o n d|1 1 0 P|U|u|W|L| Rn |v| Fd |0|0|0|1| o f f s e t | CPDT
+; |c o n d|1 1 0 P|U|w|W|L| Rn |x| Fd |0|0|1|0| o f f s e t | CPDT (copro 2)
+; | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+; |c o n d|1 1 1 0|a|b|c|d|e| Fn |j| Fd |0|0|0|1|f|g|h|0|i| Fm | CPDO
+; |c o n d|1 1 1 0|a|b|c|L|e| Fn | Rd |0|0|0|1|f|g|h|1|i| Fm | CPRT
+; |c o n d|1 1 1 0|a|b|c|1|e| Fn |1|1|1|1|0|0|0|1|f|g|h|1|i| Fm | comparisons
+; | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+;
+; CPDT data transfer instructions
+; LDF, STF, LFM (copro 2), SFM (copro 2)
+;
+; CPDO dyadic arithmetic instructions
+; ADF, MUF, SUF, RSF, DVF, RDF,
+; POW, RPW, RMF, FML, FDV, FRD, POL
+;
+; CPDO monadic arithmetic instructions
+; MVF, MNF, ABS, RND, SQT, LOG, LGN, EXP,
+; SIN, COS, TAN, ASN, ACS, ATN, URD, NRM
+;
+; CPRT joint arithmetic/data transfer instructions
+; FIX (arithmetic followed by load/store)
+; FLT (load/store followed by arithmetic)
+; CMF, CNF CMFE, CNFE (comparisons)
+; WFS, RFS (write/read floating point status register)
+; WFC, RFC (write/read floating point control register)
+; \xF0 - CPDT
+; code 1: copro (1/2)
+; code 2: load/store bit
+; \xF1 - CPDO
+; \xF2 - CPDO monadic
+; \xF3 - CPRT
+; \xF4 - CPRT comparison
+;
+; \xFF - fix me
+;
+
+[NONE]
+void void none
+
+[ABScc]
+
+[ACScc]
+
+[ASNcc]
+
+[ATNcc]
+
+[ADCcc]
+reg32,reg32,reg32 \4\x0\xA0 ARM7
+reg32,reg32,reg32,reg32 \5\x0\xA0 ARM7
+reg32,reg32,reg32,imm \6\x0\xA0 ARM7
+reg32,reg32,imm \7\x2\xA0 ARM7
+
+[ADDcc]
+reg32,reg32,reg32 \4\x0\x80 ARM7
+reg32,reg32,reg32,reg32 \5\x0\x80 ARM7
+reg32,reg32,reg32,imm \6\x0\x80 ARM7
+reg32,reg32,imm \7\x2\x80 ARM7
+
+[ADFcc]
+
+[ANDcc]
+reg32,reg32,reg32 \4\x0\x00 ARM7
+reg32,reg32,reg32,reg32 \5\x0\x00 ARM7
+reg32,reg32,reg32,imm \6\x0\x00 ARM7
+reg32,reg32,imm \7\x2\x00 ARM7
+
+[Bcc]
+mem32 \1\x0A ARM7
+imm24 \1\x0A ARM7
+
+[BICcc]
+reg32,reg32,reg32 \4\x1\xC0 ARM7
+reg32,reg32,reg32,reg32 \5\x1\xC0 ARM7
+reg32,reg32,reg32,imm \6\x1\xC0 ARM7
+reg32,reg32,imm \7\x3\xC0 ARM7
+
+[BLcc]
+mem32 \1\x0B ARM7
+imm24 \1\x0B ARM7
+
+[BLX]
+mem32 \xff ARM7
+imm24 \xff ARM7
+
+[BKPTcc]
+
+[BXcc]
+reg32 \3\x01\x2F\xFF\x10 ARM7
+
+[CDP]
+reg8,reg8 \300\1\x10\101 ARM7
+
+[CMFcc]
+
+[CMFEcc]
+
+[CMNcc]
+reg32,reg32 \xC\x1\x60 ARM7
+reg32,reg32,reg32 \xD\x1\x60 ARM7
+reg32,reg32,imm \xE\x1\x60 ARM7
+reg32,imm \xF\x3\x60 ARM7
+
+[CMPcc]
+reg32,reg32 \xC\x1\x40 ARM7
+reg32,reg32,reg32 \xD\x1\x40 ARM7
+reg32,reg32,imm \xE\x1\x40 ARM7
+reg32,imm \xF\x3\x40 ARM7
+
+[CLZcc]
+reg32,reg32 \x27\x01\x01 ARM7
+
+[CNFcc]
+
+[COScc]
+
+[CPS]
+[CPSID]
+[CPSIE]
+
+[DVFcc]
+
+[EORcc]
+reg32,reg32,reg32 \4\x0\x20 ARM7
+reg32,reg32,reg32,reg32 \5\x0\x20 ARM7
+reg32,reg32,reg32,imm \6\x0\x20 ARM7
+reg32,reg32,imm \7\x2\x20 ARM7
+
+[EXPcc]
+
+[FDVcc]
+
+[FLTcc]
+
+[FIXcc]
+
+[FMLcc]
+
+[FRDcc]
+
+[LDC]
+reg32,reg32 \321\300\1\x11\101 ARM7
+
+[LDMcc]
+memam4,reglist \x26\x81 ARM7
+
+[LDRBTcc]
+
+[LDRBcc]
+reg32,memam2 \x17\x07\x10 ARM7
+
+[LDRcc]
+reg32,memam2 \x17\x05\x10 ARM7
+; reg32,imm32 \x17\x05\x10 ARM7
+; reg32,reg32 \x18\x04\x10 ARM7
+; reg32,reg32,imm32 \x19\x04\x10 ARM7
+; reg32,reg32,reg32 \x20\x06\x10 ARM7
+; reg32,reg32,reg32,imm32 \x21\x06\x10 ARM7
+
+[LDRHcc]
+reg32,imm32 \x22\x50\xB0 ARM7
+reg32,reg32 \x23\x50\xB0 ARM7
+reg32,reg32,imm32 \x24\x50\xB0 ARM7
+reg32,reg32,reg32 \x25\x10\xB0 ARM7
+
+[LDRSBcc]
+reg32,imm32 \x22\x50\xD0 ARM7
+reg32,reg32 \x23\x50\xD0 ARM7
+reg32,reg32,imm32 \x24\x50\xD0 ARM7
+reg32,reg32,reg32 \x25\x10\xD0 ARM7
+
+[LDRSHcc]
+reg32,imm32 \x22\x50\xF0 ARM7
+reg32,reg32 \x23\x50\xF0 ARM7
+reg32,reg32,imm32 \x24\x50\xF0 ARM7
+reg32,reg32,reg32 \x25\x10\xF0 ARM7
+
+[LDRTcc]
+
+[LDFcc]
+
+[LFMcc]
+reg32,imm8,fpureg \xF0\x02\x01 FPA
+
+[LGNcc]
+
+[LOGcc]
+
+[MCR]
+reg32,mem32 \320\301\1\x13\110 ARM7
+
+[MLAcc]
+reg32,reg32,reg32,reg32 \x15\x00\x20\x90 ARM7
+
+[MOVcc]
+; reg32,shifterop \x8\x0\0xd ARM7
+; reg32,immshifter \x8\x0\0xd ARM7
+; reg32,reg32,reg32 \x9\x1\xA0 ARM7
+; reg32,reg32,imm \xA\x1\xA0 ARM7
+; reg32,imm \xB\x3\xA0 ARM7
+
+; [MRC]
+; reg32,reg32 \321\301\1\x13\110 ARM7
+
+[MRScc]
+reg32,reg32 \x10\x01\x0F ARM7
+
+[MSRcc]
+reg32,reg32 \x11\x01\x29\xF0 ARM7
+regf,reg32 \x12\x01\x28\xF0 ARM7
+regf,imm \x13\x03\x28\xF0 ARM7
+
+[MNFcc]
+
+[MUFcc]
+
+[MULcc]
+reg32,reg32,reg32 \x14\x00\x00\x90 ARM7
+
+[MVFcc]
+fpureg,fpureg \xF2 FPA
+fpureg,immfpu \xF2 FPA
+
+[MVNcc]
+; reg32,reg32 \x8\x0\0xf ARM7
+; reg32,reg32,reg32 \x9\x1\xE0 ARM7
+; reg32,reg32,imm \xA\x1\xE0 ARM7
+; reg32,imm \xB\x3\xE0 ARM7
+
+[NOP]
+
+[ORRcc]
+reg32,reg32,reg32 \4\x1\x80 ARM7
+reg32,reg32,reg32,reg32 \5\x1\x80 ARM7
+reg32,reg32,reg32,imm \6\x1\x80 ARM7
+reg32,reg32,imm \7\x3\x80 ARM7
+
+[RDFcc]
+
+[RFScc]
+
+[RFCcc]
+
+[RMFcc]
+
+[RPWcc]
+
+[RSBcc]
+reg32,reg32,reg32 \4\x0\x60 ARM7
+reg32,reg32,reg32,reg32 \5\x0\x60 ARM7
+reg32,reg32,reg32,imm \6\x0\x60 ARM7
+reg32,reg32,imm \7\x2\x60 ARM7
+
+[RSCcc]
+reg32,reg32,reg32 \4\x0\xE0 ARM7
+reg32,reg32,reg32,reg32 \5\x0\xE0 ARM7
+reg32,reg32,reg32,imm \6\x0\xE0 ARM7
+reg32,reg32,imm \7\x2\xE0 ARM7
+
+[RSFcc]
+
+[RNDcc]
+
+[POLcc]
+
+[SBCcc]
+reg32,reg32,reg32 \4\x0\xC0 ARM7
+reg32,reg32,reg32,reg32 \5\x0\xC0 ARM7
+reg32,reg32,reg32,imm \6\x0\xC0 ARM7
+reg32,reg32,imm \7\x2\xC0 ARM7
+
+[SFMcc]
+reg32,imm8,fpureg \xF0\x02\x00 FPA
+
+[SINcc]
+
+[SMLALcc]
+reg32,reg32,reg32,reg32 \x16\x00\xE0\x90 ARM7
+
+[SMULLcc]
+reg32,reg32,reg32,reg32 \x16\x00\xC0\x90 ARM7
+
+[SQTcc]
+
+[SUFcc]
+
+[STFcc]
+
+[STMcc]
+memam4,reglist \x26\x80 ARM7
+
+[STRcc]
+reg32,memam2 \x17\x04\x00 ARM7
+; reg32,imm32 \x17\x05\x00 ARM7
+; reg32,reg32 \x18\x04\x00 ARM7
+; reg32,reg32,imm32 \x19\x04\x00 ARM7
+; reg32,reg32,reg32 \x20\x06\x00 ARM7
+; reg32,reg32,reg32,imm32 \x21\x06\x00 ARM7
+
+[STRBcc]
+reg32,memam2 \x17\x06\x00 ARM7
+
+[STRBTcc]
+
+; A dummy since it is parsed as STR{cond}H
+[STRHcc]
+reg32,imm32 \x22\x40\xB0 ARM7
+reg32,reg32 \x23\x40\xB0 ARM7
+reg32,reg32,imm32 \x24\x40\xB0 ARM7
+reg32,reg32,reg32 \x25\x00\xB0 ARM7
+
+[STRTcc]
+
+[SUBcc]
+reg32,reg32,shifterop \4\x0\x40 ARM7
+reg32,reg32,immshifter \4\x0\x40 ARM7
+reg32,reg32,reg32 \4\x0\x40 ARM7
+; reg32,reg32,reg32,reg32 \5\x0\x40 ARM7
+; reg32,reg32,reg32,imm \6\x0\x40 ARM7
+; reg32,reg32,imm \7\x2\x40 ARM7
+
+[SWIcc]
+imm \2\x0F ARM7
+
+[SWPcc]
+reg32,reg32,reg32 \x27\x01\x90 ARM7
+
+[SWPBcc]
+reg32,reg32,reg32 \x27\x01\x90 ARM7
+
+[TANcc]
+
+[TEQcc]
+reg32,reg32 \xC\x1\x20 ARM7
+reg32,reg32,reg32 \xD\x1\x20 ARM7
+reg32,reg32,imm \xE\x1\x20 ARM7
+reg32,imm \xF\x3\x20 ARM7
+
+[TSTcc]
+reg32,reg32 \xC\x1\x00 ARM7
+reg32,reg32,reg32 \xD\x1\x00 ARM7
+reg32,reg32,imm \xE\x1\x00 ARM7
+reg32,imm \xF\x3\x00 ARM7
+
+[UMLALcc]
+reg32,reg32,reg32,reg32 \x16\x00\xA0\x90 ARM7
+
+[UMULLcc]
+reg32,reg32,reg32,reg32 \x16\x00\x80\x90 ARM7
+
+[WFScc]
+
+; EDSP instructions
+[LDRDcc]
+
+[MCRRcc]
+
+[MRRCcc]
+
+[PLD]
+
+[QADDcc]
+
+[QDADDcc]
+
+[QDSUBcc]
+
+[QSUBcc]
+
+[SMLABBcc]
+
+[SMLABTcc]
+
+[SMLATBcc]
+
+[SMLATTcc]
+
+[SMLALBBcc]
+
+[SMLALBTcc]
+
+[SMLALTBcc]
+
+[SMLALTTcc]
+
+[SMLAWBcc]
+
+[SMLAWTcc]
+
+[SMULBBcc]
+
+[SMULBTcc]
+
+[SMULTBcc]
+
+[SMULTTcc]
+
+[SMULWBcc]
+
+[SMULWTcc]
+
+[STRDcc]
+
+;
+; vfp instructions
+;
+[FABSDcc]
+
+[FABSScc]
+
+[FADDDcc]
+
+[FADDScc]
+
+[FCMPDcc]
+
+[FCMPEDcc]
+
+[FCMPEScc]
+
+[FCMPEZDcc]
+
+[FCMPEZScc]
+
+[FCMPScc]
+
+[FCMPZDcc]
+
+[FCMPZScc]
+
+[FCPYDcc]
+
+[FCPYScc]
+
+[FCVTDScc]
+
+[FCVTSDcc]
+
+[FDIVDcc]
+
+[FDIVScc]
+
+[FLDDcc]
+
+[FLDMcc]
+
+[FLDScc]
+
+[FMACDcc]
+
+[FMACScc]
+
+[FMDHRcc]
+
+[FMDLRcc]
+
+[FMRDHcc]
+
+[FMRDLcc]
+
+[FMRScc]
+
+[FMRXcc]
+
+[FMSCDcc]
+
+[FMSCScc]
+
+[FMSRcc]
+
+[FMSTATcc]
+
+[FMULDcc]
+
+[FMULScc]
+
+[FMXRcc]
+
+[FNEGDcc]
+
+[FNEGScc]
+
+[FNMACDcc]
+
+[FNMACScc]
+
+[FNMSCDcc]
+
+[FNMSCScc]
+
+[FNMULDcc]
+
+[FNMULScc]
+
+[FSITODcc]
+
+[FSITOScc]
+
+[FSQRTDcc]
+
+[FSQRTScc]
+
+[FSTDcc]
+
+[FSTMcc]
+
+[FSTScc]
+
+[FSUBDcc]
+
+[FSUBScc]
+
+[FTOSIDcc]
+
+[FTOSIScc]
+
+[FTOUIDcc]
+
+[FTOUIScc]
+
+[FUITODcc]
+
+[FUITOScc]
+
+[FMDRRcc]
+
+[FMRRDcc]
+
+; Thumb-2
+
+[ASRcc]
+
+[LSRcc]
+
+[LSLcc]
+
+[RORcc]
+
+[SDIVcc]
+
+[UDIVcc]
+
+[MOVTcc]
+
+[LDREXcc]
+
+[STREXcc]
+
+[IT]
+
+[ITE]
+
+[ITT]
+
+[ITEE]
+
+[ITTE]
+
+[ITET]
+
+[ITTT]
+
+[ITEEE]
+
+[ITTEE]
+
+[ITETE]
+
+[ITTTE]
+
+[ITEET]
+
+[ITTET]
+
+[ITETT]
+
+[ITTTT]
+
+[TBB]
+[TBH]
diff --git a/closures/compiler/arm/armnop.inc b/closures/compiler/arm/armnop.inc
new file mode 100644
index 0000000000..60560b933e
--- /dev/null
+++ b/closures/compiler/arm/armnop.inc
@@ -0,0 +1,2 @@
+{ don't edit, this file is generated from armins.dat }
+106;
diff --git a/closures/compiler/arm/armop.inc b/closures/compiler/arm/armop.inc
new file mode 100644
index 0000000000..ec5d50029e
--- /dev/null
+++ b/closures/compiler/arm/armop.inc
@@ -0,0 +1,208 @@
+{ don't edit, this file is generated from armins.dat }
+(
+A_NONE,
+A_ABS,
+A_ACS,
+A_ASN,
+A_ATN,
+A_ADC,
+A_ADD,
+A_ADF,
+A_AND,
+A_B,
+A_BIC,
+A_BL,
+A_BLX,
+A_BKPT,
+A_BX,
+A_CDP,
+A_CMF,
+A_CMFE,
+A_CMN,
+A_CMP,
+A_CLZ,
+A_CNF,
+A_COS,
+A_CPS,
+A_CPSID,
+A_CPSIE,
+A_DVF,
+A_EOR,
+A_EXP,
+A_FDV,
+A_FLT,
+A_FIX,
+A_FML,
+A_FRD,
+A_LDC,
+A_LDM,
+A_LDRBT,
+A_LDRB,
+A_LDR,
+A_LDRH,
+A_LDRSB,
+A_LDRSH,
+A_LDRT,
+A_LDF,
+A_LFM,
+A_LGN,
+A_LOG,
+A_MCR,
+A_MLA,
+A_MOV,
+A_MRS,
+A_MSR,
+A_MNF,
+A_MUF,
+A_MUL,
+A_MVF,
+A_MVN,
+A_NOP,
+A_ORR,
+A_RDF,
+A_RFS,
+A_RFC,
+A_RMF,
+A_RPW,
+A_RSB,
+A_RSC,
+A_RSF,
+A_RND,
+A_POL,
+A_SBC,
+A_SFM,
+A_SIN,
+A_SMLAL,
+A_SMULL,
+A_SQT,
+A_SUF,
+A_STF,
+A_STM,
+A_STR,
+A_STRB,
+A_STRBT,
+A_STRH,
+A_STRT,
+A_SUB,
+A_SWI,
+A_SWP,
+A_SWPB,
+A_TAN,
+A_TEQ,
+A_TST,
+A_UMLAL,
+A_UMULL,
+A_WFS,
+A_LDRD,
+A_MCRR,
+A_MRRC,
+A_PLD,
+A_QADD,
+A_QDADD,
+A_QDSUB,
+A_QSUB,
+A_SMLABB,
+A_SMLABT,
+A_SMLATB,
+A_SMLATT,
+A_SMLALBB,
+A_SMLALBT,
+A_SMLALTB,
+A_SMLALTT,
+A_SMLAWB,
+A_SMLAWT,
+A_SMULBB,
+A_SMULBT,
+A_SMULTB,
+A_SMULTT,
+A_SMULWB,
+A_SMULWT,
+A_STRD,
+A_FABSD,
+A_FABSS,
+A_FADDD,
+A_FADDS,
+A_FCMPD,
+A_FCMPED,
+A_FCMPES,
+A_FCMPEZD,
+A_FCMPEZS,
+A_FCMPS,
+A_FCMPZD,
+A_FCMPZS,
+A_FCPYD,
+A_FCPYS,
+A_FCVTDS,
+A_FCVTSD,
+A_FDIVD,
+A_FDIVS,
+A_FLDD,
+A_FLDM,
+A_FLDS,
+A_FMACD,
+A_FMACS,
+A_FMDHR,
+A_FMDLR,
+A_FMRDH,
+A_FMRDL,
+A_FMRS,
+A_FMRX,
+A_FMSCD,
+A_FMSCS,
+A_FMSR,
+A_FMSTAT,
+A_FMULD,
+A_FMULS,
+A_FMXR,
+A_FNEGD,
+A_FNEGS,
+A_FNMACD,
+A_FNMACS,
+A_FNMSCD,
+A_FNMSCS,
+A_FNMULD,
+A_FNMULS,
+A_FSITOD,
+A_FSITOS,
+A_FSQRTD,
+A_FSQRTS,
+A_FSTD,
+A_FSTM,
+A_FSTS,
+A_FSUBD,
+A_FSUBS,
+A_FTOSID,
+A_FTOSIS,
+A_FTOUID,
+A_FTOUIS,
+A_FUITOD,
+A_FUITOS,
+A_FMDRR,
+A_FMRRD,
+A_ASR,
+A_LSR,
+A_LSL,
+A_ROR,
+A_SDIV,
+A_UDIV,
+A_MOVT,
+A_LDREX,
+A_STREX,
+A_IT,
+A_ITE,
+A_ITT,
+A_ITEE,
+A_ITTE,
+A_ITET,
+A_ITTT,
+A_ITEEE,
+A_ITTEE,
+A_ITETE,
+A_ITTTE,
+A_ITEET,
+A_ITTET,
+A_ITETT,
+A_ITTTT,
+A_TBB,
+A_TBH
+);
diff --git a/closures/compiler/arm/armreg.dat b/closures/compiler/arm/armreg.dat
new file mode 100644
index 0000000000..0874db8ebb
--- /dev/null
+++ b/closures/compiler/arm/armreg.dat
@@ -0,0 +1,108 @@
+;
+; ARM registers
+;
+; layout
+; <name>,<type>,<subtype>,<value>,<stdname>,<stab idx>,<dwarf idx>
+;
+NO,$00,$00,$00,INVALID,-1,-1
+; Integer registers
+R0,$01,$00,$00,r0,0,0
+R1,$01,$00,$01,r1,1,1
+R2,$01,$00,$02,r2,2,2
+R3,$01,$00,$03,r3,3,3
+R4,$01,$00,$04,r4,4,4
+R5,$01,$00,$05,r5,5,5
+R6,$01,$00,$06,r6,6,6
+R7,$01,$00,$07,r7,7,7
+R8,$01,$00,$08,r8,8,8
+R9,$01,$00,$09,r9,9,9
+R10,$01,$00,$0a,r10,10,10
+R11,$01,$00,$0b,r11,11,11
+R12,$01,$00,$0c,r12,12,12
+R13,$01,$00,$0d,r13,13,13
+R14,$01,$00,$0e,r14,14,14
+R15,$01,$00,$0f,r15,15,15
+
+; Float registers
+F0,$02,$00,$00,f0,32,16
+F1,$02,$00,$01,f1,32,17
+F2,$02,$00,$02,f2,32,18
+F3,$02,$00,$03,f3,32,19
+F4,$02,$00,$04,f4,32,20
+F5,$02,$00,$05,f5,32,21
+F6,$02,$00,$06,f6,32,22
+F7,$02,$00,$07,f7,32,23
+
+; MM registers
+; S0/S1/D0 etc have the same register number because the register allocated
+; cannot deal with D0 conflicting with both S0 and S1. This unfortunately
+; means that we can only use 16 single precision registers instead of 32,
+; even if no double precision ones are used...
+S0,$04,$06,$00,s0,0,0
+S1,$04,$06,$00,s1,0,0
+D0,$04,$07,$00,d0,0,0
+S2,$04,$06,$01,s2,0,0
+S3,$04,$06,$01,s3,0,0
+D1,$04,$07,$01,d1,0,0
+S4,$04,$06,$02,s4,0,0
+S5,$04,$06,$02,s5,0,0
+D2,$04,$07,$02,d2,0,0
+S6,$04,$06,$03,s6,0,0
+S7,$04,$06,$03,s7,0,0
+D3,$04,$07,$03,d3,0,0
+S8,$04,$06,$04,s8,0,0
+S9,$04,$06,$04,s9,0,0
+D4,$04,$07,$04,d4,0,0
+S10,$04,$06,$05,s10,0,0
+S11,$04,$06,$05,s11,0,0
+D5,$04,$07,$05,d5,0,0
+S12,$04,$06,$06,s12,0,0
+S13,$04,$06,$06,s13,0,0
+D6,$04,$07,$06,d6,0,0
+S14,$04,$06,$07,s14,0,0
+S15,$04,$06,$07,s15,0,0
+D7,$04,$07,$07,d7,0,0
+S16,$04,$06,$08,s16,0,0
+S17,$04,$06,$08,s17,0,0
+D8,$04,$07,$08,d8,0,0
+S18,$04,$06,$09,s18,0,0
+S19,$04,$06,$09,s19,0,0
+D9,$04,$07,$09,d9,0,0
+S20,$04,$06,$0A,s20,0,0
+S21,$04,$06,$0A,s21,0,0
+D10,$04,$07,$0A,d10,0,0
+S22,$04,$06,$0B,s22,0,0
+S23,$04,$06,$0B,s23,0,0
+D11,$04,$07,$0B,d11,0,0
+S24,$04,$06,$0C,s24,0,0
+S25,$04,$06,$0C,s25,0,0
+D12,$04,$07,$0C,d12,0,0
+S26,$04,$06,$0D,s26,0,0
+S27,$04,$06,$0D,s27,0,0
+D13,$04,$07,$0D,d13,0,0
+S28,$04,$06,$0E,s28,0,0
+S29,$04,$06,$0E,s29,0,0
+D14,$04,$07,$0E,d14,0,0
+S30,$04,$06,$0F,s20,0,0
+S31,$04,$06,$0F,s21,0,0
+D15,$04,$07,$0F,d15,0,0
+D16,$04,$07,$10,d16,0,0
+D17,$04,$07,$11,d17,0,0
+D18,$04,$07,$12,d18,0,0
+D19,$04,$07,$13,d19,0,0
+D20,$04,$07,$14,d20,0,0
+D21,$04,$07,$15,d21,0,0
+D22,$04,$07,$16,d22,0,0
+D23,$04,$07,$17,d23,0,0
+D24,$04,$07,$18,d24,0,0
+D25,$04,$07,$19,d25,0,0
+D26,$04,$07,$1A,d26,0,0
+D27,$04,$07,$1B,d27,0,0
+D28,$04,$07,$1C,d28,0,0
+D29,$04,$07,$1D,d29,0,0
+D30,$04,$07,$1E,d30,0,0
+D31,$04,$07,$1F,d31,0,0
+
+; special registers
+CPSR_C,$05,$00,$00,cpsr_c,0,0
+FPSCR,$05,$00,$01,fpscr,0,0
diff --git a/closures/compiler/arm/armtab.inc b/closures/compiler/arm/armtab.inc
new file mode 100644
index 0000000000..d1543befa2
--- /dev/null
+++ b/closures/compiler/arm/armtab.inc
@@ -0,0 +1,745 @@
+{ don't edit, this file is generated from armins.dat }
+(
+ (
+ opcode : A_NONE;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #0;
+ flags : if_none
+ ),
+ (
+ opcode : A_ADC;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
+ code : #4#0#160;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_ADC;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
+ code : #5#0#160;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_ADC;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_immediate);
+ code : #6#0#160;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_ADC;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
+ code : #7#2#160;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_ADD;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
+ code : #4#0#128;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_ADD;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
+ code : #5#0#128;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_ADD;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_immediate);
+ code : #6#0#128;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_ADD;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
+ code : #7#2#128;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_AND;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
+ code : #4#0#0;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_AND;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
+ code : #5#0#0;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_AND;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_immediate);
+ code : #6#0#0;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_AND;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
+ code : #7#2#0;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_B;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+ code : #1#10;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_B;
+ ops : 1;
+ optypes : (ot_immediate24,ot_none,ot_none,ot_none);
+ code : #1#10;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_BIC;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
+ code : #4#1#192;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_BIC;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
+ code : #5#1#192;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_BIC;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_immediate);
+ code : #6#1#192;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_BIC;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
+ code : #7#3#192;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_BL;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+ code : #1#11;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_BL;
+ ops : 1;
+ optypes : (ot_immediate24,ot_none,ot_none,ot_none);
+ code : #1#11;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_BLX;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+ code : #15#15;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_BLX;
+ ops : 1;
+ optypes : (ot_immediate24,ot_none,ot_none,ot_none);
+ code : #15#15;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_BX;
+ ops : 1;
+ optypes : (ot_reg32,ot_none,ot_none,ot_none);
+ code : #3#1#47#255#16;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_CDP;
+ ops : 2;
+ optypes : (ot_reg8,ot_reg8,ot_none,ot_none);
+ code : #192#1#16#65;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_CMN;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #12#1#96;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_CMN;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
+ code : #13#1#96;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_CMN;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
+ code : #14#1#96;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_CMN;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediate,ot_none,ot_none);
+ code : #15#3#96;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #12#1#64;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_CMP;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
+ code : #13#1#64;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_CMP;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
+ code : #14#1#64;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediate,ot_none,ot_none);
+ code : #15#3#64;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_CLZ;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #39#1#1;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_EOR;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
+ code : #4#0#32;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_EOR;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
+ code : #5#0#32;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_EOR;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_immediate);
+ code : #6#0#32;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_EOR;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
+ code : #7#2#32;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_LDC;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #209#192#1#17#65;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_LDM;
+ ops : 2;
+ optypes : (ot_memoryam4,ot_reglist,ot_none,ot_none);
+ code : #38#129;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_LDRB;
+ ops : 2;
+ optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none);
+ code : #23#7#16;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_LDR;
+ ops : 2;
+ optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none);
+ code : #23#5#16;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_LDRH;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediate or ot_bits32,ot_none,ot_none);
+ code : #34#80#176;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_LDRH;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #35#80#176;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_LDRH;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediate or ot_bits32,ot_none);
+ code : #36#80#176;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_LDRH;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
+ code : #37#16#176;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_LDRSB;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediate or ot_bits32,ot_none,ot_none);
+ code : #34#80#208;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_LDRSB;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #35#80#208;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_LDRSB;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediate or ot_bits32,ot_none);
+ code : #36#80#208;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_LDRSB;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
+ code : #37#16#208;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_LDRSH;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediate or ot_bits32,ot_none,ot_none);
+ code : #34#80#240;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_LDRSH;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #35#80#240;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_LDRSH;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediate or ot_bits32,ot_none);
+ code : #36#80#240;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_LDRSH;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
+ code : #37#16#240;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_LFM;
+ ops : 3;
+ optypes : (ot_reg32,ot_immediate or ot_bits8,ot_fpureg,ot_none);
+ code : #240#2#1;
+ flags : if_fpa
+ ),
+ (
+ opcode : A_MCR;
+ ops : 2;
+ optypes : (ot_reg32,ot_memory or ot_bits32,ot_none,ot_none);
+ code : #208#193#1#19#72;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_MLA;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
+ code : #21#0#32#144;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_MRS;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #16#1#15;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_MSR;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #17#1#41#240;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_MSR;
+ ops : 2;
+ optypes : (ot_regf,ot_reg32,ot_none,ot_none);
+ code : #18#1#40#240;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_MSR;
+ ops : 2;
+ optypes : (ot_regf,ot_immediate,ot_none,ot_none);
+ code : #19#3#40#240;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_MUL;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
+ code : #20#0#0#144;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_MVF;
+ ops : 2;
+ optypes : (ot_fpureg,ot_fpureg,ot_none,ot_none);
+ code : #242;
+ flags : if_fpa
+ ),
+ (
+ opcode : A_MVF;
+ ops : 2;
+ optypes : (ot_fpureg,ot_immediatefpu,ot_none,ot_none);
+ code : #242;
+ flags : if_fpa
+ ),
+ (
+ opcode : A_ORR;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
+ code : #4#1#128;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_ORR;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
+ code : #5#1#128;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_ORR;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_immediate);
+ code : #6#1#128;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_ORR;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
+ code : #7#3#128;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_RSB;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
+ code : #4#0#96;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_RSB;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
+ code : #5#0#96;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_RSB;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_immediate);
+ code : #6#0#96;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_RSB;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
+ code : #7#2#96;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_RSC;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
+ code : #4#0#224;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_RSC;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
+ code : #5#0#224;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_RSC;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_immediate);
+ code : #6#0#224;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_RSC;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
+ code : #7#2#224;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_SBC;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
+ code : #4#0#192;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_SBC;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
+ code : #5#0#192;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_SBC;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_immediate);
+ code : #6#0#192;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_SBC;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
+ code : #7#2#192;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_SFM;
+ ops : 3;
+ optypes : (ot_reg32,ot_immediate or ot_bits8,ot_fpureg,ot_none);
+ code : #240#2#0;
+ flags : if_fpa
+ ),
+ (
+ opcode : A_SMLAL;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
+ code : #22#0#224#144;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_SMULL;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
+ code : #22#0#192#144;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_STM;
+ ops : 2;
+ optypes : (ot_memoryam4,ot_reglist,ot_none,ot_none);
+ code : #38#128;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_STR;
+ ops : 2;
+ optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none);
+ code : #23#4#0;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_STRB;
+ ops : 2;
+ optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none);
+ code : #23#6#0;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_STRH;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediate or ot_bits32,ot_none,ot_none);
+ code : #34#64#176;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_STRH;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #35#64#176;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_STRH;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediate or ot_bits32,ot_none);
+ code : #36#64#176;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_STRH;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
+ code : #37#0#176;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_SUB;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none);
+ code : #4#0#64;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_SUB;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none);
+ code : #4#0#64;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_SUB;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
+ code : #4#0#64;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_SWI;
+ ops : 1;
+ optypes : (ot_immediate,ot_none,ot_none,ot_none);
+ code : #2#15;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_SWP;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
+ code : #39#1#144;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_SWPB;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
+ code : #39#1#144;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_TEQ;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #12#1#32;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_TEQ;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
+ code : #13#1#32;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_TEQ;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
+ code : #14#1#32;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_TEQ;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediate,ot_none,ot_none);
+ code : #15#3#32;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_TST;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #12#1#0;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_TST;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
+ code : #13#1#0;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_TST;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
+ code : #14#1#0;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_TST;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediate,ot_none,ot_none);
+ code : #15#3#0;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_UMLAL;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
+ code : #22#0#160#144;
+ flags : if_arm7
+ ),
+ (
+ opcode : A_UMULL;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
+ code : #22#0#128#144;
+ flags : if_arm7
+ )
+);
diff --git a/closures/compiler/arm/cgcpu.pas b/closures/compiler/arm/cgcpu.pas
new file mode 100644
index 0000000000..595dde2126
--- /dev/null
+++ b/closures/compiler/arm/cgcpu.pas
@@ -0,0 +1,3709 @@
+{
+
+ Copyright (c) 2003 by Florian Klaempfl
+ Member of the Free Pascal development team
+
+ This unit implements the code generator for the ARM
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit cgcpu;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ globtype,symtype,symdef,
+ cgbase,cgutils,cgobj,
+ aasmbase,aasmcpu,aasmtai,aasmdata,
+ parabase,
+ cpubase,cpuinfo,node,cg64f32,rgcpu;
+
+
+ type
+ tcgarm = class(tcg)
+ { true, if the next arithmetic operation should modify the flags }
+ cgsetflags : boolean;
+
+ procedure a_load_const_cgpara(list : TAsmList;size : tcgsize;a : tcgint;const paraloc : TCGPara);override;
+ procedure a_load_ref_cgpara(list : TAsmList;size : tcgsize;const r : treference;const paraloc : TCGPara);override;
+ procedure a_loadaddr_ref_cgpara(list : TAsmList;const r : treference;const paraloc : TCGPara);override;
+
+ procedure a_call_name(list : TAsmList;const s : string; weak: boolean);override;
+ procedure a_call_reg(list : TAsmList;reg: tregister);override;
+ procedure a_call_ref(list : TAsmList;ref: treference);override;
+
+ procedure a_op_const_reg(list : TAsmList; Op: TOpCG; size: TCGSize; a: tcgint; reg: TRegister); override;
+ procedure a_op_reg_reg(list : TAsmList; Op: TOpCG; size: TCGSize; src, dst: TRegister); override;
+
+ procedure a_op_const_reg_reg(list: TAsmList; op: TOpCg;
+ size: tcgsize; a: tcgint; src, dst: tregister); override;
+ procedure a_op_reg_reg_reg(list: TAsmList; op: TOpCg;
+ size: tcgsize; src1, src2, dst: tregister); override;
+ procedure a_op_const_reg_reg_checkoverflow(list: TAsmList; op: TOpCg; size: tcgsize; a: tcgint; src, dst: tregister;setflags : boolean;var ovloc : tlocation);override;
+ procedure a_op_reg_reg_reg_checkoverflow(list: TAsmList; op: TOpCg; size: tcgsize; src1, src2, dst: tregister;setflags : boolean;var ovloc : tlocation);override;
+
+ { move instructions }
+ procedure a_load_reg_ref(list : TAsmList; fromsize, tosize: tcgsize; reg : tregister;const ref : treference);override;
+ procedure a_load_reg_reg(list : TAsmList; fromsize, tosize : tcgsize;reg1,reg2 : tregister);override;
+ function a_internal_load_reg_ref(list : TAsmList; fromsize, tosize: tcgsize; reg : tregister;const ref : treference):treference;
+ function a_internal_load_ref_reg(list : TAsmList; fromsize, tosize : tcgsize;const Ref : treference;reg : tregister):treference;
+
+ { fpu move instructions }
+ procedure a_loadfpu_reg_reg(list: TAsmList; fromsize, tosize: tcgsize; reg1, reg2: tregister); override;
+ procedure a_loadfpu_ref_reg(list: TAsmList; fromsize, tosize: tcgsize; const ref: treference; reg: tregister); override;
+ procedure a_loadfpu_reg_ref(list: TAsmList; fromsize, tosize: tcgsize; reg: tregister; const ref: treference); override;
+
+ procedure a_loadfpu_ref_cgpara(list : TAsmList;size : tcgsize;const ref : treference;const paraloc : TCGPara);override;
+ { comparison operations }
+ procedure a_cmp_const_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;a : tcgint;reg : tregister;
+ l : tasmlabel);override;
+ procedure a_cmp_reg_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel); override;
+
+ procedure a_jmp_name(list : TAsmList;const s : string); override;
+ procedure a_jmp_always(list : TAsmList;l: tasmlabel); override;
+ procedure a_jmp_flags(list : TAsmList;const f : TResFlags;l: tasmlabel); override;
+
+ procedure g_flags2reg(list: TAsmList; size: TCgSize; const f: TResFlags; reg: TRegister); override;
+
+ procedure g_proc_entry(list : TAsmList;localsize : longint;nostackframe:boolean);override;
+ procedure g_proc_exit(list : TAsmList;parasize : longint;nostackframe:boolean); override;
+
+ procedure a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);override;
+
+ procedure g_concatcopy(list : TAsmList;const source,dest : treference;len : tcgint);override;
+ procedure g_concatcopy_unaligned(list : TAsmList;const source,dest : treference;len : tcgint);override;
+ procedure g_concatcopy_move(list : TAsmList;const source,dest : treference;len : tcgint);
+ procedure g_concatcopy_internal(list : TAsmList;const source,dest : treference;len : tcgint;aligned : boolean);
+
+ procedure g_overflowcheck(list: TAsmList; const l: tlocation; def: tdef); override;
+ procedure g_overflowCheck_loc(List:TAsmList;const Loc:TLocation;def:TDef;ovloc : tlocation);override;
+
+ procedure g_save_registers(list : TAsmList);override;
+ procedure g_restore_registers(list : TAsmList);override;
+
+ procedure a_jmp_cond(list : TAsmList;cond : TOpCmp;l: tasmlabel);
+ procedure fixref(list : TAsmList;var ref : treference);
+ function handle_load_store(list:TAsmList;op: tasmop;oppostfix : toppostfix;reg:tregister;ref: treference):treference; virtual;
+
+ procedure g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);override;
+ procedure g_adjust_self_value(list:TAsmList;procdef: tprocdef;ioffset: tcgint); override;
+ procedure g_stackpointer_alloc(list : TAsmList;size : longint);override;
+
+ procedure a_loadmm_reg_reg(list: TAsmList; fromsize, tosize : tcgsize;reg1, reg2: tregister;shuffle : pmmshuffle); override;
+ procedure a_loadmm_ref_reg(list: TAsmList; fromsize, tosize : tcgsize;const ref: treference; reg: tregister;shuffle : pmmshuffle); override;
+ procedure a_loadmm_reg_ref(list: TAsmList; fromsize, tosize : tcgsize;reg: tregister; const ref: treference;shuffle : pmmshuffle); override;
+ procedure a_loadmm_intreg_reg(list: TAsmList; fromsize, tosize : tcgsize;intreg, mmreg: tregister; shuffle: pmmshuffle); override;
+ procedure a_loadmm_reg_intreg(list: TAsmList; fromsize, tosize : tcgsize;mmreg, intreg: tregister; shuffle : pmmshuffle); override;
+
+ procedure a_opmm_reg_reg(list: TAsmList; Op: TOpCG; size : tcgsize;src,dst: tregister;shuffle : pmmshuffle); override;
+ { Transform unsupported methods into Internal errors }
+ procedure a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; size: TCGSize; src, dst: TRegister); override;
+ private
+ { clear out potential overflow bits from 8 or 16 bit operations }
+ { the upper 24/16 bits of a register after an operation }
+ procedure maybeadjustresult(list: TAsmList; op: TOpCg; size: tcgsize; dst: tregister);
+ function get_darwin_call_stub(const s: string; weak: boolean): tasmsymbol;
+ end;
+
+ tarmcgarm = class(tcgarm)
+ procedure init_register_allocators;override;
+ procedure done_register_allocators;override;
+
+ procedure a_load_const_reg(list : TAsmList; size: tcgsize; a : tcgint;reg : tregister);override;
+ procedure a_load_ref_reg(list : TAsmList; fromsize, tosize : tcgsize;const Ref : treference;reg : tregister);override;
+ end;
+
+ tcg64farm = class(tcg64f32)
+ procedure a_op64_reg_reg(list : TAsmList;op:TOpCG;size : tcgsize;regsrc,regdst : tregister64);override;
+ procedure a_op64_const_reg(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;reg : tregister64);override;
+ procedure a_op64_const_reg_reg(list: TAsmList;op:TOpCG;size : tcgsize;value : int64;regsrc,regdst : tregister64);override;
+ procedure a_op64_reg_reg_reg(list: TAsmList;op:TOpCG;size : tcgsize;regsrc1,regsrc2,regdst : tregister64);override;
+ procedure a_op64_const_reg_reg_checkoverflow(list: TAsmList;op:TOpCG;size : tcgsize;value : int64;regsrc,regdst : tregister64;setflags : boolean;var ovloc : tlocation);override;
+ procedure a_op64_reg_reg_reg_checkoverflow(list: TAsmList;op:TOpCG;size : tcgsize;regsrc1,regsrc2,regdst : tregister64;setflags : boolean;var ovloc : tlocation);override;
+ procedure a_loadmm_intreg64_reg(list: TAsmList; mmsize: tcgsize; intreg: tregister64; mmreg: tregister);override;
+ procedure a_loadmm_reg_intreg64(list: TAsmList; mmsize: tcgsize; mmreg: tregister; intreg: tregister64);override;
+ end;
+
+ Tthumb2cgarm = class(tcgarm)
+ procedure init_register_allocators;override;
+ procedure done_register_allocators;override;
+
+ procedure a_call_reg(list : TAsmList;reg: tregister);override;
+
+ procedure a_load_const_reg(list : TAsmList; size: tcgsize; a : tcgint;reg : tregister);override;
+ procedure a_load_ref_reg(list : TAsmList; fromsize, tosize : tcgsize;const Ref : treference;reg : tregister);override;
+
+ procedure a_op_const_reg_reg_checkoverflow(list: TAsmList; op: TOpCg; size: tcgsize; a: tcgint; src, dst: tregister;setflags : boolean;var ovloc : tlocation);override;
+ procedure a_op_reg_reg_reg_checkoverflow(list: TAsmList; op: TOpCg; size: tcgsize; src1, src2, dst: tregister;setflags : boolean;var ovloc : tlocation);override;
+
+ procedure g_flags2reg(list: TAsmList; size: TCgSize; const f: TResFlags; reg: TRegister); override;
+
+ procedure g_proc_entry(list : TAsmList;localsize : longint;nostackframe:boolean);override;
+ procedure g_proc_exit(list : TAsmList;parasize : longint;nostackframe:boolean); override;
+
+ function handle_load_store(list:TAsmList;op: tasmop;oppostfix : toppostfix;reg:tregister;ref: treference):treference; override;
+ end;
+
+ tthumb2cg64farm = class(tcg64farm)
+ procedure a_op64_reg_reg(list : TAsmList;op:TOpCG;size : tcgsize;regsrc,regdst : tregister64);override;
+ end;
+
+ const
+ OpCmp2AsmCond : Array[topcmp] of TAsmCond = (C_NONE,C_EQ,C_GT,
+ C_LT,C_GE,C_LE,C_NE,C_LS,C_CC,C_CS,C_HI);
+
+ winstackpagesize = 4096;
+
+ function get_fpu_postfix(def : tdef) : toppostfix;
+ procedure create_codegen;
+
+ implementation
+
+
+ uses
+ globals,verbose,systems,cutils,
+ aopt,aoptcpu,
+ fmodule,
+ symconst,symsym,
+ tgobj,
+ procinfo,cpupi,
+ paramgr;
+
+
+ function get_fpu_postfix(def : tdef) : toppostfix;
+ begin
+ if def.typ=floatdef then
+ begin
+ case tfloatdef(def).floattype of
+ s32real:
+ result:=PF_S;
+ s64real:
+ result:=PF_D;
+ s80real:
+ result:=PF_E;
+ else
+ internalerror(200401272);
+ end;
+ end
+ else
+ internalerror(200401271);
+ end;
+
+
+ procedure tarmcgarm.init_register_allocators;
+ begin
+ inherited init_register_allocators;
+ { currently, we save R14 always, so we can use it }
+ if (target_info.system<>system_arm_darwin) then
+ rg[R_INTREGISTER]:=trgintcpu.create(R_INTREGISTER,R_SUBWHOLE,
+ [RS_R0,RS_R1,RS_R2,RS_R3,RS_R4,RS_R5,RS_R6,RS_R7,RS_R8,
+ RS_R9,RS_R10,RS_R12,RS_R14],first_int_imreg,[])
+ else
+ { r9 is not (always) available on Darwin according to the llvm code
+ generator. }
+ rg[R_INTREGISTER]:=trgintcpu.create(R_INTREGISTER,R_SUBWHOLE,
+ [RS_R0,RS_R1,RS_R2,RS_R3,RS_R4,RS_R5,RS_R6,RS_R7,RS_R8,
+ RS_R10,RS_R12,RS_R14],first_int_imreg,[]);
+ rg[R_FPUREGISTER]:=trgcpu.create(R_FPUREGISTER,R_SUBNONE,
+ [RS_F0,RS_F1,RS_F2,RS_F3,RS_F4,RS_F5,RS_F6,RS_F7],first_fpu_imreg,[]);
+ { The register allocator currently cannot deal with multiple
+ non-overlapping subregs per register, so we can only use
+ half the single precision registers for now (as sub registers of the
+ double precision ones). }
+ if current_settings.fputype=fpu_vfpv3 then
+ rg[R_MMREGISTER]:=trgcpu.create(R_MMREGISTER,R_SUBFD,
+ [RS_D0,RS_D1,RS_D2,RS_D3,RS_D4,RS_D5,RS_D6,RS_D7,
+ RS_D16,RS_D17,RS_D18,RS_D19,RS_D20,RS_D21,RS_D22,RS_D23,RS_D24,RS_D25,RS_D26,RS_D27,RS_D28,RS_D29,RS_D30,RS_D31,
+ RS_D8,RS_D9,RS_D10,RS_D11,RS_D12,RS_D13,RS_D14,RS_D15
+ ],first_mm_imreg,[])
+ else
+ rg[R_MMREGISTER]:=trgcpu.create(R_MMREGISTER,R_SUBFD,
+ [RS_D0,RS_D1,RS_D2,RS_D3,RS_D4,RS_D5,RS_D6,RS_D7,RS_D8,RS_D9,RS_D10,RS_D11,RS_D12,RS_D13,RS_D14,RS_D15],first_mm_imreg,[]);
+ end;
+
+
+ procedure tarmcgarm.done_register_allocators;
+ begin
+ rg[R_INTREGISTER].free;
+ rg[R_FPUREGISTER].free;
+ rg[R_MMREGISTER].free;
+ inherited done_register_allocators;
+ end;
+
+
+ procedure tarmcgarm.a_load_const_reg(list : TAsmList; size: tcgsize; a : tcgint;reg : tregister);
+ var
+ imm_shift : byte;
+ l : tasmlabel;
+ hr : treference;
+ begin
+ if not(size in [OS_8,OS_S8,OS_16,OS_S16,OS_32,OS_S32]) then
+ internalerror(2002090902);
+ if is_shifter_const(a,imm_shift) then
+ list.concat(taicpu.op_reg_const(A_MOV,reg,a))
+ else if is_shifter_const(not(a),imm_shift) then
+ list.concat(taicpu.op_reg_const(A_MVN,reg,not(a)))
+ { loading of constants with mov and orr }
+ else if (is_shifter_const(a-byte(a),imm_shift)) then
+ begin
+ list.concat(taicpu.op_reg_const(A_MOV,reg,a-byte(a)));
+ list.concat(taicpu.op_reg_reg_const(A_ORR,reg,reg,byte(a)));
+ end
+ else if (is_shifter_const(a-word(a),imm_shift)) and (is_shifter_const(word(a),imm_shift)) then
+ begin
+ list.concat(taicpu.op_reg_const(A_MOV,reg,a-word(a)));
+ list.concat(taicpu.op_reg_reg_const(A_ORR,reg,reg,word(a)));
+ end
+ else if (is_shifter_const(a-(dword(a) shl 8) shr 8,imm_shift)) and (is_shifter_const((dword(a) shl 8) shr 8,imm_shift)) then
+ begin
+ list.concat(taicpu.op_reg_const(A_MOV,reg,a-(dword(a) shl 8) shr 8));
+ list.concat(taicpu.op_reg_reg_const(A_ORR,reg,reg,(dword(a) shl 8) shr 8));
+ end
+ else
+ begin
+ reference_reset(hr,4);
+
+ current_asmdata.getjumplabel(l);
+ cg.a_label(current_procinfo.aktlocaldata,l);
+ hr.symboldata:=current_procinfo.aktlocaldata.last;
+ current_procinfo.aktlocaldata.concat(tai_const.Create_32bit(longint(a)));
+
+ hr.symbol:=l;
+ hr.base:=NR_PC;
+ list.concat(taicpu.op_reg_ref(A_LDR,reg,hr));
+ end;
+ end;
+
+
+ procedure tarmcgarm.a_load_ref_reg(list : TAsmList; fromsize, tosize : tcgsize;const Ref : treference;reg : tregister);
+ var
+ oppostfix:toppostfix;
+ usedtmpref: treference;
+ tmpreg,tmpreg2 : tregister;
+ so : tshifterop;
+ dir : integer;
+ begin
+ if (TCGSize2Size[FromSize] >= TCGSize2Size[ToSize]) then
+ FromSize := ToSize;
+ case FromSize of
+ { signed integer registers }
+ OS_8:
+ oppostfix:=PF_B;
+ OS_S8:
+ oppostfix:=PF_SB;
+ OS_16:
+ oppostfix:=PF_H;
+ OS_S16:
+ oppostfix:=PF_SH;
+ OS_32,
+ OS_S32:
+ oppostfix:=PF_None;
+ else
+ InternalError(200308297);
+ end;
+ if (ref.alignment in [1,2]) and (ref.alignment<tcgsize2size[fromsize]) then
+ begin
+ if target_info.endian=endian_big then
+ dir:=-1
+ else
+ dir:=1;
+ case FromSize of
+ OS_16,OS_S16:
+ begin
+ { only complicated references need an extra loadaddr }
+ if assigned(ref.symbol) or
+ (ref.index<>NR_NO) or
+ (ref.offset<-4095) or
+ (ref.offset>4094) or
+ { sometimes the compiler reused registers }
+ (reg=ref.index) or
+ (reg=ref.base) then
+ begin
+ tmpreg2:=getintregister(list,OS_INT);
+ a_loadaddr_ref_reg(list,ref,tmpreg2);
+ reference_reset_base(usedtmpref,tmpreg2,0,ref.alignment);
+ end
+ else
+ usedtmpref:=ref;
+
+ if target_info.endian=endian_big then
+ inc(usedtmpref.offset,1);
+ shifterop_reset(so);so.shiftmode:=SM_LSL;so.shiftimm:=8;
+ tmpreg:=getintregister(list,OS_INT);
+ a_internal_load_ref_reg(list,OS_8,OS_8,usedtmpref,reg);
+ inc(usedtmpref.offset,dir);
+ if FromSize=OS_16 then
+ a_internal_load_ref_reg(list,OS_8,OS_8,usedtmpref,tmpreg)
+ else
+ a_internal_load_ref_reg(list,OS_S8,OS_S8,usedtmpref,tmpreg);
+ list.concat(taicpu.op_reg_reg_reg_shifterop(A_ORR,reg,reg,tmpreg,so));
+ end;
+ OS_32,OS_S32:
+ begin
+ tmpreg:=getintregister(list,OS_INT);
+
+ { only complicated references need an extra loadaddr }
+ if assigned(ref.symbol) or
+ (ref.index<>NR_NO) or
+ (ref.offset<-4095) or
+ (ref.offset>4092) or
+ { sometimes the compiler reused registers }
+ (reg=ref.index) or
+ (reg=ref.base) then
+ begin
+ tmpreg2:=getintregister(list,OS_INT);
+ a_loadaddr_ref_reg(list,ref,tmpreg2);
+ reference_reset_base(usedtmpref,tmpreg2,0,ref.alignment);
+ end
+ else
+ usedtmpref:=ref;
+
+ shifterop_reset(so);so.shiftmode:=SM_LSL;
+ if ref.alignment=2 then
+ begin
+ if target_info.endian=endian_big then
+ inc(usedtmpref.offset,2);
+ a_internal_load_ref_reg(list,OS_16,OS_16,usedtmpref,reg);
+ inc(usedtmpref.offset,dir*2);
+ a_internal_load_ref_reg(list,OS_16,OS_16,usedtmpref,tmpreg);
+ so.shiftimm:=16;
+ list.concat(taicpu.op_reg_reg_reg_shifterop(A_ORR,reg,reg,tmpreg,so));
+ end
+ else
+ begin
+ if target_info.endian=endian_big then
+ inc(usedtmpref.offset,3);
+ a_internal_load_ref_reg(list,OS_8,OS_8,usedtmpref,reg);
+ inc(usedtmpref.offset,dir);
+ a_internal_load_ref_reg(list,OS_8,OS_8,usedtmpref,tmpreg);
+ so.shiftimm:=8;
+ list.concat(taicpu.op_reg_reg_reg_shifterop(A_ORR,reg,reg,tmpreg,so));
+ inc(usedtmpref.offset,dir);
+ a_internal_load_ref_reg(list,OS_8,OS_8,usedtmpref,tmpreg);
+ so.shiftimm:=16;
+ list.concat(taicpu.op_reg_reg_reg_shifterop(A_ORR,reg,reg,tmpreg,so));
+ inc(usedtmpref.offset,dir);
+ a_internal_load_ref_reg(list,OS_8,OS_8,usedtmpref,tmpreg);
+ so.shiftimm:=24;
+ list.concat(taicpu.op_reg_reg_reg_shifterop(A_ORR,reg,reg,tmpreg,so));
+ end;
+ end
+ else
+ handle_load_store(list,A_LDR,oppostfix,reg,ref);
+ end;
+ end
+ else
+ handle_load_store(list,A_LDR,oppostfix,reg,ref);
+
+ if (fromsize=OS_S8) and (tosize = OS_16) then
+ a_load_reg_reg(list,OS_16,OS_32,reg,reg);
+ end;
+
+
+ procedure tcgarm.a_load_const_cgpara(list : TAsmList;size : tcgsize;a : tcgint;const paraloc : TCGPara);
+ var
+ ref: treference;
+ begin
+ paraloc.check_simple_location;
+ paramanager.allocparaloc(list,paraloc.location);
+ case paraloc.location^.loc of
+ LOC_REGISTER,LOC_CREGISTER:
+ a_load_const_reg(list,size,a,paraloc.location^.register);
+ LOC_REFERENCE:
+ begin
+ reference_reset(ref,paraloc.alignment);
+ ref.base:=paraloc.location^.reference.index;
+ ref.offset:=paraloc.location^.reference.offset;
+ a_load_const_ref(list,size,a,ref);
+ end;
+ else
+ internalerror(2002081101);
+ end;
+ end;
+
+
+ procedure tcgarm.a_load_ref_cgpara(list : TAsmList;size : tcgsize;const r : treference;const paraloc : TCGPara);
+ var
+ tmpref, ref: treference;
+ location: pcgparalocation;
+ sizeleft: aint;
+ begin
+ location := paraloc.location;
+ tmpref := r;
+ sizeleft := paraloc.intsize;
+ while assigned(location) do
+ begin
+ paramanager.allocparaloc(list,location);
+ case location^.loc of
+ LOC_REGISTER,LOC_CREGISTER:
+ a_load_ref_reg(list,location^.size,location^.size,tmpref,location^.register);
+ LOC_REFERENCE:
+ begin
+ reference_reset_base(ref,location^.reference.index,location^.reference.offset,paraloc.alignment);
+ { doubles in softemu mode have a strange order of registers and references }
+ if location^.size=OS_32 then
+ g_concatcopy(list,tmpref,ref,4)
+ else
+ begin
+ g_concatcopy(list,tmpref,ref,sizeleft);
+ if assigned(location^.next) then
+ internalerror(2005010710);
+ end;
+ end;
+ LOC_FPUREGISTER,LOC_CFPUREGISTER:
+ case location^.size of
+ OS_F32, OS_F64:
+ a_loadfpu_ref_reg(list,location^.size,location^.size,tmpref,location^.register);
+ else
+ internalerror(2002072801);
+ end;
+ LOC_VOID:
+ begin
+ // nothing to do
+ end;
+ else
+ internalerror(2002081103);
+ end;
+ inc(tmpref.offset,tcgsize2size[location^.size]);
+ dec(sizeleft,tcgsize2size[location^.size]);
+ location := location^.next;
+ end;
+ end;
+
+
+ procedure tcgarm.a_loadaddr_ref_cgpara(list : TAsmList;const r : treference;const paraloc : TCGPara);
+ var
+ ref: treference;
+ tmpreg: tregister;
+ begin
+ paraloc.check_simple_location;
+ paramanager.allocparaloc(list,paraloc.location);
+ case paraloc.location^.loc of
+ LOC_REGISTER,LOC_CREGISTER:
+ a_loadaddr_ref_reg(list,r,paraloc.location^.register);
+ LOC_REFERENCE:
+ begin
+ reference_reset(ref,paraloc.alignment);
+ ref.base := paraloc.location^.reference.index;
+ ref.offset := paraloc.location^.reference.offset;
+ tmpreg := getintregister(list,OS_ADDR);
+ a_loadaddr_ref_reg(list,r,tmpreg);
+ a_load_reg_ref(list,OS_ADDR,OS_ADDR,tmpreg,ref);
+ end;
+ else
+ internalerror(2002080701);
+ end;
+ end;
+
+
+ procedure tcgarm.a_call_name(list : TAsmList;const s : string; weak: boolean);
+ var
+ branchopcode: tasmop;
+ begin
+ { check not really correct: should only be used for non-Thumb cpus }
+ if (current_settings.cputype<cpu_armv5) or
+ (current_settings.cputype in cpu_thumb2) then
+ branchopcode:=A_BL
+ else
+ branchopcode:=A_BLX;
+ if target_info.system<>system_arm_darwin then
+ if not weak then
+ list.concat(taicpu.op_sym(branchopcode,current_asmdata.RefAsmSymbol(s)))
+ else
+ list.concat(taicpu.op_sym(branchopcode,current_asmdata.WeakRefAsmSymbol(s)))
+ else
+ list.concat(taicpu.op_sym(branchopcode,get_darwin_call_stub(s,weak)));
+{
+ the compiler does not properly set this flag anymore in pass 1, and
+ for now we only need it after pass 2 (I hope) (JM)
+ if not(pi_do_call in current_procinfo.flags) then
+ internalerror(2003060703);
+}
+ include(current_procinfo.flags,pi_do_call);
+ end;
+
+
+ procedure tcgarm.a_call_reg(list : TAsmList;reg: tregister);
+ begin
+ { check not really correct: should only be used for non-Thumb cpus }
+ if (current_settings.cputype<cpu_armv5) then
+ begin
+ list.concat(taicpu.op_reg_reg(A_MOV,NR_R14,NR_PC));
+ list.concat(taicpu.op_reg_reg(A_MOV,NR_PC,reg));
+ end
+ else
+ list.concat(taicpu.op_reg(A_BLX, reg));
+{
+ the compiler does not properly set this flag anymore in pass 1, and
+ for now we only need it after pass 2 (I hope) (JM)
+ if not(pi_do_call in current_procinfo.flags) then
+ internalerror(2003060703);
+}
+ include(current_procinfo.flags,pi_do_call);
+ end;
+
+
+ procedure tcgarm.a_call_ref(list : TAsmList;ref: treference);
+ begin
+ a_reg_alloc(list,NR_R12);
+ a_load_ref_reg(list,OS_ADDR,OS_ADDR,ref,NR_R12);
+ a_call_reg(list,NR_R12);
+ a_reg_dealloc(list,NR_R12);
+ include(current_procinfo.flags,pi_do_call);
+ end;
+
+
+ procedure tcgarm.a_op_const_reg(list : TAsmList; Op: TOpCG; size: TCGSize; a: tcgint; reg: TRegister);
+ begin
+ a_op_const_reg_reg(list,op,size,a,reg,reg);
+ end;
+
+
+ procedure tcgarm.a_op_reg_reg(list : TAsmList; Op: TOpCG; size: TCGSize; src, dst: TRegister);
+ begin
+ case op of
+ OP_NEG:
+ list.concat(taicpu.op_reg_reg_const(A_RSB,dst,src,0));
+ OP_NOT:
+ begin
+ list.concat(taicpu.op_reg_reg(A_MVN,dst,src));
+ case size of
+ OS_8 :
+ a_op_const_reg_reg(list,OP_AND,OS_INT,$ff,dst,dst);
+ OS_16 :
+ a_op_const_reg_reg(list,OP_AND,OS_INT,$ffff,dst,dst);
+ end;
+ end
+ else
+ a_op_reg_reg_reg(list,op,OS_32,src,dst,dst);
+ end;
+ end;
+
+
+ const
+ op_reg_reg_opcg2asmop: array[TOpCG] of tasmop =
+ (A_NONE,A_MOV,A_ADD,A_AND,A_NONE,A_NONE,A_MUL,A_MUL,A_NONE,A_NONE,A_ORR,
+ A_NONE,A_NONE,A_NONE,A_SUB,A_EOR,A_NONE,A_NONE);
+
+
+ procedure tcgarm.a_op_const_reg_reg(list: TAsmList; op: TOpCg;
+ size: tcgsize; a: tcgint; src, dst: tregister);
+ var
+ ovloc : tlocation;
+ begin
+ a_op_const_reg_reg_checkoverflow(list,op,size,a,src,dst,false,ovloc);
+ end;
+
+
+ procedure tcgarm.a_op_reg_reg_reg(list: TAsmList; op: TOpCg;
+ size: tcgsize; src1, src2, dst: tregister);
+ var
+ ovloc : tlocation;
+ begin
+ a_op_reg_reg_reg_checkoverflow(list,op,size,src1,src2,dst,false,ovloc);
+ end;
+
+
+ procedure tcgarm.a_op_const_reg_reg_checkoverflow(list: TAsmList; op: TOpCg; size: tcgsize; a: tcgint; src, dst: tregister;setflags : boolean;var ovloc : tlocation);
+ var
+ shift : byte;
+ tmpreg : tregister;
+ so : tshifterop;
+ l1 : longint;
+ begin
+ ovloc.loc:=LOC_VOID;
+ if {$ifopt R+}(a<>-2147483648) and{$endif} is_shifter_const(-a,shift) then
+ case op of
+ OP_ADD:
+ begin
+ op:=OP_SUB;
+ a:=aint(dword(-a));
+ end;
+ OP_SUB:
+ begin
+ op:=OP_ADD;
+ a:=aint(dword(-a));
+ end
+ end;
+
+ if is_shifter_const(a,shift) and not(op in [OP_IMUL,OP_MUL]) then
+ case op of
+ OP_NEG,OP_NOT:
+ internalerror(200308281);
+ OP_SHL:
+ begin
+ if a>32 then
+ internalerror(200308294);
+ if a<>0 then
+ begin
+ shifterop_reset(so);
+ so.shiftmode:=SM_LSL;
+ so.shiftimm:=a;
+ list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src,so));
+ end
+ else
+ list.concat(taicpu.op_reg_reg(A_MOV,dst,src));
+ end;
+ OP_ROL:
+ begin
+ if a>32 then
+ internalerror(200308294);
+ if a<>0 then
+ begin
+ shifterop_reset(so);
+ so.shiftmode:=SM_ROR;
+ so.shiftimm:=32-a;
+ list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src,so));
+ end
+ else
+ list.concat(taicpu.op_reg_reg(A_MOV,dst,src));
+ end;
+ OP_ROR:
+ begin
+ if a>32 then
+ internalerror(200308294);
+ if a<>0 then
+ begin
+ shifterop_reset(so);
+ so.shiftmode:=SM_ROR;
+ so.shiftimm:=a;
+ list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src,so));
+ end
+ else
+ list.concat(taicpu.op_reg_reg(A_MOV,dst,src));
+ end;
+ OP_SHR:
+ begin
+ if a>32 then
+ internalerror(200308292);
+ shifterop_reset(so);
+ if a<>0 then
+ begin
+ so.shiftmode:=SM_LSR;
+ so.shiftimm:=a;
+ list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src,so));
+ end
+ else
+ list.concat(taicpu.op_reg_reg(A_MOV,dst,src));
+ end;
+ OP_SAR:
+ begin
+ if a>32 then
+ internalerror(200308295);
+ if a<>0 then
+ begin
+ shifterop_reset(so);
+ so.shiftmode:=SM_ASR;
+ so.shiftimm:=a;
+ list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src,so));
+ end
+ else
+ list.concat(taicpu.op_reg_reg(A_MOV,dst,src));
+ end;
+ else
+ {if (op in [OP_SUB, OP_ADD]) and
+ ((a < 0) or
+ (a > 4095)) then
+ begin
+ tmpreg:=getintregister(list,size);
+ list.concat(taicpu.op_reg_const(A_MOVT, tmpreg, (a shr 16) and $FFFF));
+ list.concat(taicpu.op_reg_const(A_MOV, tmpreg, a and $FFFF));
+ list.concat(setoppostfix(taicpu.op_reg_reg_reg(op_reg_reg_opcg2asmop[op],dst,src,tmpreg),toppostfix(ord(cgsetflags or setflags)*ord(PF_S))
+ ));
+ end
+ else}
+ list.concat(setoppostfix(
+ taicpu.op_reg_reg_const(op_reg_reg_opcg2asmop[op],dst,src,a),toppostfix(ord(cgsetflags or setflags)*ord(PF_S))
+ ));
+ if (cgsetflags or setflags) and (size in [OS_8,OS_16,OS_32]) then
+ begin
+ ovloc.loc:=LOC_FLAGS;
+ case op of
+ OP_ADD:
+ ovloc.resflags:=F_CS;
+ OP_SUB:
+ ovloc.resflags:=F_CC;
+ end;
+ end;
+ end
+ else
+ begin
+ { there could be added some more sophisticated optimizations }
+ if (op in [OP_MUL,OP_IMUL,OP_DIV,OP_IDIV]) and (a=1) then
+ a_load_reg_reg(list,size,size,src,dst)
+ else if (op in [OP_MUL,OP_IMUL]) and (a=0) then
+ a_load_const_reg(list,size,0,dst)
+ else if (op in [OP_IMUL,OP_IDIV]) and (a=-1) then
+ a_op_reg_reg(list,OP_NEG,size,src,dst)
+ { we do this here instead in the peephole optimizer because
+ it saves us a register }
+ else if (op in [OP_MUL,OP_IMUL]) and ispowerof2(a,l1) and not(cgsetflags or setflags) then
+ a_op_const_reg_reg(list,OP_SHL,size,l1,src,dst)
+ { for example : b=a*5 -> b=a*4+a with add instruction and shl }
+ else if (op in [OP_MUL,OP_IMUL]) and ispowerof2(a-1,l1) and not(cgsetflags or setflags) then
+ begin
+ if l1>32 then{roozbeh does this ever happen?}
+ internalerror(200308296);
+ shifterop_reset(so);
+ so.shiftmode:=SM_LSL;
+ so.shiftimm:=l1;
+ list.concat(taicpu.op_reg_reg_reg_shifterop(A_ADD,dst,src,src,so));
+ end
+ else
+ begin
+ tmpreg:=getintregister(list,size);
+ a_load_const_reg(list,size,a,tmpreg);
+ a_op_reg_reg_reg_checkoverflow(list,op,size,tmpreg,src,dst,setflags,ovloc);
+ end;
+ end;
+ maybeadjustresult(list,op,size,dst);
+ end;
+
+
+ procedure tcgarm.a_op_reg_reg_reg_checkoverflow(list: TAsmList; op: TOpCg; size: tcgsize; src1, src2, dst: tregister;setflags : boolean;var ovloc : tlocation);
+ var
+ so : tshifterop;
+ tmpreg,overflowreg : tregister;
+ asmop : tasmop;
+ begin
+ ovloc.loc:=LOC_VOID;
+ case op of
+ OP_NEG,OP_NOT,
+ OP_DIV,OP_IDIV:
+ internalerror(200308281);
+ OP_SHL:
+ begin
+ shifterop_reset(so);
+ so.rs:=src1;
+ so.shiftmode:=SM_LSL;
+ list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src2,so));
+ end;
+ OP_SHR:
+ begin
+ shifterop_reset(so);
+ so.rs:=src1;
+ so.shiftmode:=SM_LSR;
+ list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src2,so));
+ end;
+ OP_SAR:
+ begin
+ shifterop_reset(so);
+ so.rs:=src1;
+ so.shiftmode:=SM_ASR;
+ list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src2,so));
+ end;
+ OP_ROL:
+ begin
+ if not(size in [OS_32,OS_S32]) then
+ internalerror(2008072801);
+ { simulate ROL by ror'ing 32-value }
+ tmpreg:=getintregister(list,OS_32);
+ list.concat(taicpu.op_reg_const(A_MOV,tmpreg,32));
+ list.concat(taicpu.op_reg_reg_reg(A_SUB,src1,tmpreg,src1));
+ shifterop_reset(so);
+ so.rs:=src1;
+ so.shiftmode:=SM_ROR;
+ list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src2,so));
+ end;
+ OP_ROR:
+ begin
+ if not(size in [OS_32,OS_S32]) then
+ internalerror(2008072802);
+ shifterop_reset(so);
+ so.rs:=src1;
+ so.shiftmode:=SM_ROR;
+ list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src2,so));
+ end;
+ OP_IMUL,
+ OP_MUL:
+ begin
+ if cgsetflags or setflags then
+ begin
+ overflowreg:=getintregister(list,size);
+ if op=OP_IMUL then
+ asmop:=A_SMULL
+ else
+ asmop:=A_UMULL;
+ { the arm doesn't allow that rd and rm are the same }
+ if dst=src2 then
+ begin
+ if dst<>src1 then
+ list.concat(taicpu.op_reg_reg_reg_reg(asmop,dst,overflowreg,src1,src2))
+ else
+ begin
+ tmpreg:=getintregister(list,size);
+ a_load_reg_reg(list,size,size,src2,dst);
+ list.concat(taicpu.op_reg_reg_reg_reg(asmop,dst,overflowreg,tmpreg,src1));
+ end;
+ end
+ else
+ list.concat(taicpu.op_reg_reg_reg_reg(asmop,dst,overflowreg,src2,src1));
+ if op=OP_IMUL then
+ begin
+ shifterop_reset(so);
+ so.shiftmode:=SM_ASR;
+ so.shiftimm:=31;
+ list.concat(taicpu.op_reg_reg_shifterop(A_CMP,overflowreg,dst,so));
+ end
+ else
+ list.concat(taicpu.op_reg_const(A_CMP,overflowreg,0));
+
+ ovloc.loc:=LOC_FLAGS;
+ ovloc.resflags:=F_NE;
+ end
+ else
+ begin
+ { the arm doesn't allow that rd and rm are the same }
+ if dst=src2 then
+ begin
+ if dst<>src1 then
+ list.concat(taicpu.op_reg_reg_reg(A_MUL,dst,src1,src2))
+ else
+ begin
+ tmpreg:=getintregister(list,size);
+ a_load_reg_reg(list,size,size,src2,dst);
+ list.concat(taicpu.op_reg_reg_reg(A_MUL,dst,tmpreg,src1));
+ end;
+ end
+ else
+ list.concat(taicpu.op_reg_reg_reg(A_MUL,dst,src2,src1));
+ end;
+ end;
+ else
+ list.concat(setoppostfix(
+ taicpu.op_reg_reg_reg(op_reg_reg_opcg2asmop[op],dst,src2,src1),toppostfix(ord(cgsetflags or setflags)*ord(PF_S))
+ ));
+ end;
+ maybeadjustresult(list,op,size,dst);
+ end;
+
+
+ function tcgarm.handle_load_store(list:TAsmList;op: tasmop;oppostfix : toppostfix;reg:tregister;ref: treference):treference;
+ var
+ tmpreg : tregister;
+ tmpref : treference;
+ l : tasmlabel;
+ begin
+ tmpreg:=NR_NO;
+
+ { Be sure to have a base register }
+ if (ref.base=NR_NO) then
+ begin
+ if ref.shiftmode<>SM_None then
+ internalerror(200308294);
+ ref.base:=ref.index;
+ ref.index:=NR_NO;
+ end;
+
+ { absolute symbols can't be handled directly, we've to store the symbol reference
+ in the text segment and access it pc relative
+
+ For now, we assume that references where base or index equals to PC are already
+ relative, all other references are assumed to be absolute and thus they need
+ to be handled extra.
+
+ A proper solution would be to change refoptions to a set and store the information
+ if the symbol is absolute or relative there.
+ }
+
+ if (assigned(ref.symbol) and
+ not(is_pc(ref.base)) and
+ not(is_pc(ref.index))
+ ) or
+ { [#xxx] isn't a valid address operand }
+ ((ref.base=NR_NO) and (ref.index=NR_NO)) or
+ (ref.offset<-4095) or
+ (ref.offset>4095) or
+ ((oppostfix in [PF_SB,PF_H,PF_SH]) and
+ ((ref.offset<-255) or
+ (ref.offset>255)
+ )
+ ) or
+ ((op in [A_LDF,A_STF,A_FLDS,A_FLDD,A_FSTS,A_FSTD]) and
+ ((ref.offset<-1020) or
+ (ref.offset>1020) or
+ ((abs(ref.offset) mod 4)<>0) or
+ { the usual pc relative symbol handling assumes possible offsets of +/- 4095 }
+ assigned(ref.symbol)
+ )
+ ) then
+ begin
+ reference_reset(tmpref,4);
+
+ { load symbol }
+ tmpreg:=getintregister(list,OS_INT);
+ if assigned(ref.symbol) then
+ begin
+ current_asmdata.getjumplabel(l);
+ cg.a_label(current_procinfo.aktlocaldata,l);
+ tmpref.symboldata:=current_procinfo.aktlocaldata.last;
+
+ current_procinfo.aktlocaldata.concat(tai_const.create_sym_offset(ref.symbol,ref.offset));
+
+ { load consts entry }
+ tmpref.symbol:=l;
+ tmpref.base:=NR_R15;
+ list.concat(taicpu.op_reg_ref(A_LDR,tmpreg,tmpref));
+
+ { in case of LDF/STF, we got rid of the NR_R15 }
+ if is_pc(ref.base) then
+ ref.base:=NR_NO;
+ if is_pc(ref.index) then
+ ref.index:=NR_NO;
+ end
+ else
+ a_load_const_reg(list,OS_ADDR,ref.offset,tmpreg);
+
+ if (ref.base<>NR_NO) then
+ begin
+ if ref.index<>NR_NO then
+ begin
+ list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.base,tmpreg));
+ ref.base:=tmpreg;
+ end
+ else
+ begin
+ ref.index:=tmpreg;
+ ref.shiftimm:=0;
+ ref.signindex:=1;
+ ref.shiftmode:=SM_None;
+ end;
+ end
+ else
+ ref.base:=tmpreg;
+ ref.offset:=0;
+ ref.symbol:=nil;
+ end;
+
+ if (ref.base<>NR_NO) and (ref.index<>NR_NO) and (ref.offset<>0) then
+ begin
+ if tmpreg<>NR_NO then
+ a_op_const_reg_reg(list,OP_ADD,OS_ADDR,ref.offset,tmpreg,tmpreg)
+ else
+ begin
+ tmpreg:=getintregister(list,OS_ADDR);
+ a_op_const_reg_reg(list,OP_ADD,OS_ADDR,ref.offset,ref.base,tmpreg);
+ ref.base:=tmpreg;
+ end;
+ ref.offset:=0;
+ end;
+
+ { floating point operations have only limited references
+ we expect here, that a base is already set }
+ if (op in [A_LDF,A_STF,A_FLDS,A_FLDD,A_FSTS,A_FSTD]) and (ref.index<>NR_NO) then
+ begin
+ if ref.shiftmode<>SM_none then
+ internalerror(200309121);
+ if tmpreg<>NR_NO then
+ begin
+ if ref.base=tmpreg then
+ begin
+ if ref.signindex<0 then
+ list.concat(taicpu.op_reg_reg_reg(A_SUB,tmpreg,tmpreg,ref.index))
+ else
+ list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,tmpreg,ref.index));
+ ref.index:=NR_NO;
+ end
+ else
+ begin
+ if ref.index<>tmpreg then
+ internalerror(200403161);
+ if ref.signindex<0 then
+ list.concat(taicpu.op_reg_reg_reg(A_SUB,tmpreg,ref.base,tmpreg))
+ else
+ list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.base,tmpreg));
+ ref.base:=tmpreg;
+ ref.index:=NR_NO;
+ end;
+ end
+ else
+ begin
+ tmpreg:=getintregister(list,OS_ADDR);
+ list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.base,ref.index));
+ ref.base:=tmpreg;
+ ref.index:=NR_NO;
+ end;
+ end;
+ list.concat(setoppostfix(taicpu.op_reg_ref(op,reg,ref),oppostfix));
+ Result := ref;
+ end;
+
+
+ procedure tcgarm.a_load_reg_ref(list : TAsmList; fromsize, tosize: tcgsize; reg : tregister;const ref : treference);
+ var
+ oppostfix:toppostfix;
+ usedtmpref: treference;
+ tmpreg : tregister;
+ so : tshifterop;
+ dir : integer;
+ begin
+ if (TCGSize2Size[FromSize] >= TCGSize2Size[ToSize]) then
+ FromSize := ToSize;
+ case ToSize of
+ { signed integer registers }
+ OS_8,
+ OS_S8:
+ oppostfix:=PF_B;
+ OS_16,
+ OS_S16:
+ oppostfix:=PF_H;
+ OS_32,
+ OS_S32,
+ { for vfp value stored in integer register }
+ OS_F32:
+ oppostfix:=PF_None;
+ else
+ InternalError(200308295);
+ end;
+ if (ref.alignment in [1,2]) and (ref.alignment<tcgsize2size[tosize]) then
+ begin
+ if target_info.endian=endian_big then
+ dir:=-1
+ else
+ dir:=1;
+ case FromSize of
+ OS_16,OS_S16:
+ begin
+ shifterop_reset(so);so.shiftmode:=SM_LSR;so.shiftimm:=8;
+ tmpreg:=getintregister(list,OS_INT);
+ usedtmpref:=ref;
+ if target_info.endian=endian_big then
+ inc(usedtmpref.offset,1);
+ usedtmpref:=a_internal_load_reg_ref(list,OS_8,OS_8,reg,usedtmpref);
+ inc(usedtmpref.offset,dir);
+ list.concat(taicpu.op_reg_reg_shifterop(A_MOV,tmpreg,reg,so));
+ a_internal_load_reg_ref(list,OS_8,OS_8,tmpreg,usedtmpref);
+ end;
+ OS_32,OS_S32:
+ begin
+ tmpreg:=getintregister(list,OS_INT);
+ usedtmpref:=ref;
+ shifterop_reset(so);so.shiftmode:=SM_LSR;
+ if ref.alignment=2 then
+ begin
+ so.shiftimm:=16;
+ if target_info.endian=endian_big then
+ inc(usedtmpref.offset,2);
+ usedtmpref:=a_internal_load_reg_ref(list,OS_16,OS_16,reg,usedtmpref);
+ list.concat(taicpu.op_reg_reg_shifterop(A_MOV,tmpreg,reg,so));
+ inc(usedtmpref.offset,dir*2);
+ a_internal_load_reg_ref(list,OS_16,OS_16,tmpreg,usedtmpref);
+ end
+ else
+ begin
+ so.shiftimm:=8;
+ if target_info.endian=endian_big then
+ inc(usedtmpref.offset,3);
+ usedtmpref:=a_internal_load_reg_ref(list,OS_8,OS_8,reg,usedtmpref);
+ list.concat(taicpu.op_reg_reg_shifterop(A_MOV,tmpreg,reg,so));
+ inc(usedtmpref.offset,dir);
+ a_internal_load_reg_ref(list,OS_8,OS_8,tmpreg,usedtmpref);
+ list.concat(taicpu.op_reg_reg_shifterop(A_MOV,tmpreg,tmpreg,so));
+ inc(usedtmpref.offset,dir);
+ a_internal_load_reg_ref(list,OS_8,OS_8,tmpreg,usedtmpref);
+ list.concat(taicpu.op_reg_reg_shifterop(A_MOV,tmpreg,tmpreg,so));
+ inc(usedtmpref.offset,dir);
+ a_internal_load_reg_ref(list,OS_8,OS_8,tmpreg,usedtmpref);
+ end;
+ end
+ else
+ handle_load_store(list,A_STR,oppostfix,reg,ref);
+ end;
+ end
+ else
+ handle_load_store(list,A_STR,oppostfix,reg,ref);
+ end;
+
+
+ function tcgarm.a_internal_load_reg_ref(list : TAsmList; fromsize, tosize: tcgsize; reg : tregister;const ref : treference):treference;
+ var
+ oppostfix:toppostfix;
+ begin
+ case ToSize of
+ { signed integer registers }
+ OS_8,
+ OS_S8:
+ oppostfix:=PF_B;
+ OS_16,
+ OS_S16:
+ oppostfix:=PF_H;
+ OS_32,
+ OS_S32:
+ oppostfix:=PF_None;
+ else
+ InternalError(2003082910);
+ end;
+ result:=handle_load_store(list,A_STR,oppostfix,reg,ref);
+ end;
+
+
+ function tcgarm.a_internal_load_ref_reg(list : TAsmList; fromsize, tosize : tcgsize;const Ref : treference;reg : tregister):treference;
+ var
+ oppostfix:toppostfix;
+ begin
+ case FromSize of
+ { signed integer registers }
+ OS_8:
+ oppostfix:=PF_B;
+ OS_S8:
+ oppostfix:=PF_SB;
+ OS_16:
+ oppostfix:=PF_H;
+ OS_S16:
+ oppostfix:=PF_SH;
+ OS_32,
+ OS_S32:
+ oppostfix:=PF_None;
+ else
+ InternalError(200308291);
+ end;
+ result:=handle_load_store(list,A_LDR,oppostfix,reg,ref);
+ end;
+
+ procedure tcgarm.a_load_reg_reg(list : TAsmList; fromsize, tosize : tcgsize;reg1,reg2 : tregister);
+ var
+ so : tshifterop;
+
+ procedure do_shift(shiftmode : tshiftmode; shiftimm : byte; reg : tregister);
+ begin
+ so.shiftmode:=shiftmode;
+ so.shiftimm:=shiftimm;
+ list.concat(taicpu.op_reg_reg_shifterop(A_MOV,reg2,reg,so));
+ end;
+
+ var
+ instr: taicpu;
+ conv_done: boolean;
+ begin
+ if (tcgsize2size[fromsize]>32) or (tcgsize2size[tosize]>32) or (fromsize=OS_NO) or (tosize=OS_NO) then
+ internalerror(2002090901);
+
+ conv_done:=false;
+ if tosize<>fromsize then
+ begin
+ shifterop_reset(so);
+ conv_done:=true;
+ if tcgsize2size[tosize]<=tcgsize2size[fromsize] then
+ fromsize:=tosize;
+ case fromsize of
+ OS_8:
+ list.concat(taicpu.op_reg_reg_const(A_AND,reg2,reg1,$ff));
+ OS_S8:
+ begin
+ do_shift(SM_LSL,24,reg1);
+ if tosize=OS_16 then
+ begin
+ do_shift(SM_ASR,8,reg2);
+ do_shift(SM_LSR,16,reg2);
+ end
+ else
+ do_shift(SM_ASR,24,reg2);
+ end;
+ OS_16:
+ begin
+ do_shift(SM_LSL,16,reg1);
+ do_shift(SM_LSR,16,reg2);
+ end;
+ OS_S16:
+ begin
+ do_shift(SM_LSL,16,reg1);
+ do_shift(SM_ASR,16,reg2)
+ end;
+ else
+ conv_done:=false;
+ end;
+ end;
+ if not conv_done and (reg1<>reg2) then
+ begin
+ { same size, only a register mov required }
+ instr:=taicpu.op_reg_reg(A_MOV,reg2,reg1);
+ list.Concat(instr);
+ { Notify the register allocator that we have written a move instruction so
+ it can try to eliminate it. }
+ add_move_instruction(instr);
+ end;
+ end;
+
+
+ procedure tcgarm.a_loadfpu_ref_cgpara(list : TAsmList;size : tcgsize;const ref : treference;const paraloc : TCGPara);
+ var
+ href,href2 : treference;
+ hloc : pcgparalocation;
+ begin
+ href:=ref;
+ hloc:=paraloc.location;
+ while assigned(hloc) do
+ begin
+ case hloc^.loc of
+ LOC_FPUREGISTER,LOC_CFPUREGISTER:
+ begin
+ paramanager.allocparaloc(list,paraloc.location);
+ a_loadfpu_ref_reg(list,size,size,ref,hloc^.register);
+ end;
+ LOC_REGISTER :
+ case hloc^.size of
+ OS_32,
+ OS_F32:
+ begin
+ paramanager.allocparaloc(list,paraloc.location);
+ a_load_ref_reg(list,OS_32,OS_32,href,hloc^.register);
+ end;
+ OS_64,
+ OS_F64:
+ cg64.a_load64_ref_cgpara(list,href,paraloc);
+ else
+ a_load_ref_reg(list,hloc^.size,hloc^.size,href,hloc^.register);
+ end;
+ LOC_REFERENCE :
+ begin
+ reference_reset_base(href2,hloc^.reference.index,hloc^.reference.offset,paraloc.alignment);
+ { concatcopy should choose the best way to copy the data }
+ g_concatcopy(list,href,href2,tcgsize2size[hloc^.size]);
+ end;
+ else
+ internalerror(200408241);
+ end;
+ inc(href.offset,tcgsize2size[hloc^.size]);
+ hloc:=hloc^.next;
+ end;
+ end;
+
+
+ procedure tcgarm.a_loadfpu_reg_reg(list: TAsmList; fromsize,tosize: tcgsize; reg1, reg2: tregister);
+ begin
+ list.concat(setoppostfix(taicpu.op_reg_reg(A_MVF,reg2,reg1),cgsize2fpuoppostfix[tosize]));
+ end;
+
+
+ procedure tcgarm.a_loadfpu_ref_reg(list: TAsmList; fromsize,tosize: tcgsize; const ref: treference; reg: tregister);
+ var
+ oppostfix:toppostfix;
+ begin
+ case fromsize of
+ OS_32,
+ OS_F32:
+ oppostfix:=PF_S;
+ OS_64,
+ OS_F64:
+ oppostfix:=PF_D;
+ OS_F80:
+ oppostfix:=PF_E;
+ else
+ InternalError(200309021);
+ end;
+ handle_load_store(list,A_LDF,oppostfix,reg,ref);
+ if fromsize<>tosize then
+ a_loadfpu_reg_reg(list,fromsize,tosize,reg,reg);
+ end;
+
+
+ procedure tcgarm.a_loadfpu_reg_ref(list: TAsmList; fromsize, tosize: tcgsize; reg: tregister; const ref: treference);
+ var
+ oppostfix:toppostfix;
+ begin
+ case tosize of
+ OS_F32:
+ oppostfix:=PF_S;
+ OS_F64:
+ oppostfix:=PF_D;
+ OS_F80:
+ oppostfix:=PF_E;
+ else
+ InternalError(200309022);
+ end;
+ handle_load_store(list,A_STF,oppostfix,reg,ref);
+ end;
+
+
+ { comparison operations }
+ procedure tcgarm.a_cmp_const_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;a : tcgint;reg : tregister;
+ l : tasmlabel);
+ var
+ tmpreg : tregister;
+ b : byte;
+ begin
+ if is_shifter_const(a,b) then
+ list.concat(taicpu.op_reg_const(A_CMP,reg,a))
+ { CMN reg,0 and CMN reg,$80000000 are different from CMP reg,$ffffffff
+ and CMP reg,$7fffffff regarding the flags according to the ARM manual }
+ else if (a<>$7fffffff) and (a<>-1) and is_shifter_const(-a,b) then
+ list.concat(taicpu.op_reg_const(A_CMN,reg,-a))
+ else
+ begin
+ tmpreg:=getintregister(list,size);
+ a_load_const_reg(list,size,a,tmpreg);
+ list.concat(taicpu.op_reg_reg(A_CMP,reg,tmpreg));
+ end;
+ a_jmp_cond(list,cmp_op,l);
+ end;
+
+
+ procedure tcgarm.a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; size: TCGSize; src, dst: TRegister);
+ begin
+ Comment(V_Error,'tcgarm.a_bit_scan_reg_reg method not implemented');
+ end;
+
+ procedure tcgarm.a_cmp_reg_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel);
+ begin
+ list.concat(taicpu.op_reg_reg(A_CMP,reg2,reg1));
+ a_jmp_cond(list,cmp_op,l);
+ end;
+
+
+ procedure tcgarm.a_jmp_name(list : TAsmList;const s : string);
+ var
+ ai : taicpu;
+ begin
+ ai:=taicpu.op_sym(A_B,current_asmdata.RefAsmSymbol(s));
+ ai.is_jmp:=true;
+ list.concat(ai);
+ end;
+
+
+ procedure tcgarm.a_jmp_always(list : TAsmList;l: tasmlabel);
+ var
+ ai : taicpu;
+ begin
+ ai:=taicpu.op_sym(A_B,l);
+ ai.is_jmp:=true;
+ list.concat(ai);
+ end;
+
+
+ procedure tcgarm.a_jmp_flags(list : TAsmList;const f : TResFlags;l: tasmlabel);
+ var
+ ai : taicpu;
+ begin
+ ai:=setcondition(taicpu.op_sym(A_B,l),flags_to_cond(f));
+ ai.is_jmp:=true;
+ list.concat(ai);
+ end;
+
+
+ procedure tcgarm.g_flags2reg(list: TAsmList; size: TCgSize; const f: TResFlags; reg: TRegister);
+ begin
+ list.concat(setcondition(taicpu.op_reg_const(A_MOV,reg,1),flags_to_cond(f)));
+ list.concat(setcondition(taicpu.op_reg_const(A_MOV,reg,0),inverse_cond(flags_to_cond(f))));
+ end;
+
+
+ procedure tcgarm.g_proc_entry(list : TAsmList;localsize : longint;nostackframe:boolean);
+ var
+ ref : treference;
+ shift : byte;
+ firstfloatreg,lastfloatreg,
+ r : byte;
+ mmregs,
+ regs : tcpuregisterset;
+ stackmisalignment : pint;
+ postfix: toppostfix;
+ begin
+ LocalSize:=align(LocalSize,4);
+ { call instruction does not put anything on the stack }
+ stackmisalignment:=0;
+ if not(nostackframe) then
+ begin
+ firstfloatreg:=RS_NO;
+ mmregs:=[];
+ case current_settings.fputype of
+ fpu_fpa,
+ fpu_fpa10,
+ fpu_fpa11:
+ begin
+ { save floating point registers? }
+ regs:=rg[R_FPUREGISTER].used_in_proc-paramanager.get_volatile_registers_fpu(pocall_stdcall);
+ for r:=RS_F0 to RS_F7 do
+ if r in regs then
+ begin
+ if firstfloatreg=RS_NO then
+ firstfloatreg:=r;
+ lastfloatreg:=r;
+ inc(stackmisalignment,12);
+ end;
+ end;
+ fpu_vfpv2,
+ fpu_vfpv3:
+ begin;
+ mmregs:=rg[R_MMREGISTER].used_in_proc-paramanager.get_volatile_registers_mm(pocall_stdcall);
+ end;
+ end;
+ a_reg_alloc(list,NR_STACK_POINTER_REG);
+ if current_procinfo.framepointer<>NR_STACK_POINTER_REG then
+ begin
+ a_reg_alloc(list,NR_FRAME_POINTER_REG);
+ a_reg_alloc(list,NR_R12);
+
+ list.concat(taicpu.op_reg_reg(A_MOV,NR_R12,NR_STACK_POINTER_REG));
+ end;
+ { save int registers }
+ reference_reset(ref,4);
+ ref.index:=NR_STACK_POINTER_REG;
+ ref.addressmode:=AM_PREINDEXED;
+ regs:=rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall);
+ { the (old) ARM APCS requires saving both the stack pointer (to
+ crawl the stack) and the PC (to identify the function this
+ stack frame belongs to) -> also save R12 (= copy of R13 on entry)
+ and R15 -- still needs updating for EABI and Darwin, they don't
+ need that }
+ if current_procinfo.framepointer<>NR_STACK_POINTER_REG then
+ regs:=regs+[RS_FRAME_POINTER_REG,RS_R12,RS_R14,RS_R15]
+ else
+ if (regs<>[]) or (pi_do_call in current_procinfo.flags) then
+ include(regs,RS_R14);
+ if regs<>[] then
+ begin
+ for r:=RS_R0 to RS_R15 do
+ if (r in regs) then
+ inc(stackmisalignment,4);
+ list.concat(setoppostfix(taicpu.op_ref_regset(A_STM,ref,R_INTREGISTER,R_SUBWHOLE,regs),PF_FD));
+ end;
+
+ if current_procinfo.framepointer<>NR_STACK_POINTER_REG then
+ begin
+ { the framepointer now points to the saved R15, so the saved
+ framepointer is at R11-12 (for get_caller_frame) }
+ list.concat(taicpu.op_reg_reg_const(A_SUB,NR_FRAME_POINTER_REG,NR_R12,4));
+ a_reg_dealloc(list,NR_R12);
+ end;
+
+ stackmisalignment:=stackmisalignment mod current_settings.alignment.localalignmax;
+ if (LocalSize<>0) or
+ ((stackmisalignment<>0) and
+ ((pi_do_call in current_procinfo.flags) or
+ (po_assembler in current_procinfo.procdef.procoptions))) then
+ begin
+ localsize:=align(localsize+stackmisalignment,current_settings.alignment.localalignmax)-stackmisalignment;
+ if not(is_shifter_const(localsize,shift)) then
+ begin
+ if current_procinfo.framepointer=NR_STACK_POINTER_REG then
+ a_reg_alloc(list,NR_R12);
+ a_load_const_reg(list,OS_ADDR,LocalSize,NR_R12);
+ list.concat(taicpu.op_reg_reg_reg(A_SUB,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,NR_R12));
+ a_reg_dealloc(list,NR_R12);
+ end
+ else
+ begin
+ a_reg_dealloc(list,NR_R12);
+ list.concat(taicpu.op_reg_reg_const(A_SUB,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,LocalSize));
+ end;
+ end;
+
+ if (mmregs<>[]) or
+ (firstfloatreg<>RS_NO) then
+ begin
+ reference_reset(ref,4);
+ if (tg.direction*tarmprocinfo(current_procinfo).floatregstart>=1023) or
+ (current_settings.fputype in [fpu_vfpv2,fpu_vfpv3]) then
+ begin
+ if not is_shifter_const(tarmprocinfo(current_procinfo).floatregstart,shift) then
+ begin
+ a_reg_alloc(list,NR_R12);
+ a_load_const_reg(list,OS_ADDR,-tarmprocinfo(current_procinfo).floatregstart,NR_R12);
+ list.concat(taicpu.op_reg_reg_reg(A_SUB,NR_R12,current_procinfo.framepointer,NR_R12));
+ a_reg_dealloc(list,NR_R12);
+ end
+ else
+ list.concat(taicpu.op_reg_reg_const(A_SUB,NR_R12,current_procinfo.framepointer,-tarmprocinfo(current_procinfo).floatregstart));
+ ref.base:=NR_R12;
+ end
+ else
+ begin
+ ref.base:=current_procinfo.framepointer;
+ ref.offset:=tarmprocinfo(current_procinfo).floatregstart;
+ end;
+
+ case current_settings.fputype of
+ fpu_fpa,
+ fpu_fpa10,
+ fpu_fpa11:
+ begin
+ list.concat(taicpu.op_reg_const_ref(A_SFM,newreg(R_FPUREGISTER,firstfloatreg,R_SUBWHOLE),
+ lastfloatreg-firstfloatreg+1,ref));
+ end;
+ fpu_vfpv2,
+ fpu_vfpv3:
+ begin
+ ref.index:=ref.base;
+ ref.base:=NR_NO;
+ { FSTMX is deprecated on ARMv6 and later }
+ if (current_settings.cputype<cpu_armv6) then
+ postfix:=PF_IAX
+ else
+ postfix:=PF_IAD;
+ list.concat(setoppostfix(taicpu.op_ref_regset(A_FSTM,ref,R_MMREGISTER,R_SUBFD,mmregs),postfix));
+ end;
+ end;
+ end;
+ end;
+ end;
+
+
+ procedure tcgarm.g_proc_exit(list : TAsmList;parasize : longint;nostackframe:boolean);
+ var
+ ref : treference;
+ LocalSize : longint;
+ firstfloatreg,lastfloatreg,
+ r,
+ shift : byte;
+ mmregs,
+ regs : tcpuregisterset;
+ stackmisalignment: pint;
+ mmpostfix: toppostfix;
+ begin
+ if not(nostackframe) then
+ begin
+ stackmisalignment:=0;
+ firstfloatreg:=RS_NO;
+ mmregs:=[];
+ case current_settings.fputype of
+ fpu_fpa,
+ fpu_fpa10,
+ fpu_fpa11:
+ begin
+ { restore floating point registers? }
+ regs:=rg[R_FPUREGISTER].used_in_proc-paramanager.get_volatile_registers_fpu(pocall_stdcall);
+ for r:=RS_F0 to RS_F7 do
+ if r in regs then
+ begin
+ if firstfloatreg=RS_NO then
+ firstfloatreg:=r;
+ lastfloatreg:=r;
+ { floating point register space is already included in
+ localsize below by calc_stackframe_size
+ inc(stackmisalignment,12);
+ }
+ end;
+ end;
+ fpu_vfpv2,
+ fpu_vfpv3:
+ begin;
+ { restore vfp registers? }
+ mmregs:=rg[R_MMREGISTER].used_in_proc-paramanager.get_volatile_registers_mm(pocall_stdcall);
+ end;
+ end;
+
+ if (firstfloatreg<>RS_NO) or
+ (mmregs<>[]) then
+ begin
+ reference_reset(ref,4);
+ if (tg.direction*tarmprocinfo(current_procinfo).floatregstart>=1023) or
+ (current_settings.fputype in [fpu_vfpv2,fpu_vfpv3]) then
+ begin
+ if not is_shifter_const(tarmprocinfo(current_procinfo).floatregstart,shift) then
+ begin
+ a_reg_alloc(list,NR_R12);
+ a_load_const_reg(list,OS_ADDR,-tarmprocinfo(current_procinfo).floatregstart,NR_R12);
+ list.concat(taicpu.op_reg_reg_reg(A_SUB,NR_R12,current_procinfo.framepointer,NR_R12));
+ a_reg_dealloc(list,NR_R12);
+ end
+ else
+ list.concat(taicpu.op_reg_reg_const(A_SUB,NR_R12,current_procinfo.framepointer,-tarmprocinfo(current_procinfo).floatregstart));
+ ref.base:=NR_R12;
+ end
+ else
+ begin
+ ref.base:=current_procinfo.framepointer;
+ ref.offset:=tarmprocinfo(current_procinfo).floatregstart;
+ end;
+ case current_settings.fputype of
+ fpu_fpa,
+ fpu_fpa10,
+ fpu_fpa11:
+ begin
+ list.concat(taicpu.op_reg_const_ref(A_LFM,newreg(R_FPUREGISTER,firstfloatreg,R_SUBWHOLE),
+ lastfloatreg-firstfloatreg+1,ref));
+ end;
+ fpu_vfpv2,
+ fpu_vfpv3:
+ begin
+ ref.index:=ref.base;
+ ref.base:=NR_NO;
+ { FLDMX is deprecated on ARMv6 and later }
+ if (current_settings.cputype<cpu_armv6) then
+ mmpostfix:=PF_IAX
+ else
+ mmpostfix:=PF_IAD;
+ list.concat(setoppostfix(taicpu.op_ref_regset(A_FLDM,ref,R_MMREGISTER,R_SUBFD,mmregs),mmpostfix));
+ end;
+ end;
+ end;
+
+ regs:=rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall) ;
+ if (pi_do_call in current_procinfo.flags) or (regs<>[]) then
+ begin
+ exclude(regs,RS_R14);
+ include(regs,RS_R15);
+ end;
+ { restore saved stack pointer to SP (R13) and saved lr to PC (R15).
+ The saved PC came after that but is discarded, since we restore
+ the stack pointer }
+ if (current_procinfo.framepointer<>NR_STACK_POINTER_REG) then
+ regs:=regs+[RS_FRAME_POINTER_REG,RS_R13,RS_R15];
+
+ for r:=RS_R0 to RS_R15 do
+ if (r in regs) then
+ inc(stackmisalignment,4);
+ stackmisalignment:=stackmisalignment mod current_settings.alignment.localalignmax;
+ if (current_procinfo.framepointer=NR_STACK_POINTER_REG) then
+ begin
+ LocalSize:=current_procinfo.calc_stackframe_size;
+ if (LocalSize<>0) or
+ ((stackmisalignment<>0) and
+ ((pi_do_call in current_procinfo.flags) or
+ (po_assembler in current_procinfo.procdef.procoptions))) then
+ begin
+ localsize:=align(localsize+stackmisalignment,current_settings.alignment.localalignmax)-stackmisalignment;
+ if not(is_shifter_const(LocalSize,shift)) then
+ begin
+ a_reg_alloc(list,NR_R12);
+ a_load_const_reg(list,OS_ADDR,LocalSize,NR_R12);
+ list.concat(taicpu.op_reg_reg_reg(A_ADD,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,NR_R12));
+ a_reg_dealloc(list,NR_R12);
+ end
+ else
+ begin
+ list.concat(taicpu.op_reg_reg_const(A_ADD,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,LocalSize));
+ end;
+ end;
+
+ if regs=[] then
+ begin
+ if (current_settings.cputype<cpu_armv6) then
+ list.concat(taicpu.op_reg_reg(A_MOV,NR_PC,NR_R14))
+ else
+ list.concat(taicpu.op_reg(A_BX,NR_R14))
+ end
+ else
+ begin
+ reference_reset(ref,4);
+ ref.index:=NR_STACK_POINTER_REG;
+ ref.addressmode:=AM_PREINDEXED;
+ list.concat(setoppostfix(taicpu.op_ref_regset(A_LDM,ref,R_INTREGISTER,R_SUBWHOLE,regs),PF_FD));
+ end;
+ end
+ else
+ begin
+ { restore int registers and return }
+ reference_reset(ref,4);
+ ref.index:=NR_FRAME_POINTER_REG;
+ list.concat(setoppostfix(taicpu.op_ref_regset(A_LDM,ref,R_INTREGISTER,R_SUBWHOLE,regs),PF_EA));
+ end;
+ end
+ else if (current_settings.cputype<cpu_armv6) then
+ list.concat(taicpu.op_reg_reg(A_MOV,NR_PC,NR_R14))
+ else
+ list.concat(taicpu.op_reg(A_BX,NR_R14))
+ end;
+
+
+ procedure tcgarm.a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);
+ var
+ b : byte;
+ tmpref : treference;
+ instr : taicpu;
+ begin
+ if ref.addressmode<>AM_OFFSET then
+ internalerror(200309071);
+ tmpref:=ref;
+ { Be sure to have a base register }
+ if (tmpref.base=NR_NO) then
+ begin
+ if tmpref.shiftmode<>SM_None then
+ internalerror(200308294);
+ if tmpref.signindex<0 then
+ internalerror(200312023);
+ tmpref.base:=tmpref.index;
+ tmpref.index:=NR_NO;
+ end;
+
+ if assigned(tmpref.symbol) or
+ not((is_shifter_const(tmpref.offset,b)) or
+ (is_shifter_const(-tmpref.offset,b))
+ ) then
+ fixref(list,tmpref);
+
+ { expect a base here if there is an index }
+ if (tmpref.base=NR_NO) and (tmpref.index<>NR_NO) then
+ internalerror(200312022);
+
+ if tmpref.index<>NR_NO then
+ begin
+ if tmpref.shiftmode<>SM_None then
+ internalerror(200312021);
+ if tmpref.signindex<0 then
+ a_op_reg_reg_reg(list,OP_SUB,OS_ADDR,tmpref.base,tmpref.index,r)
+ else
+ a_op_reg_reg_reg(list,OP_ADD,OS_ADDR,tmpref.base,tmpref.index,r);
+ if tmpref.offset<>0 then
+ a_op_const_reg_reg(list,OP_ADD,OS_ADDR,tmpref.offset,r,r);
+ end
+ else
+ begin
+ if tmpref.base=NR_NO then
+ a_load_const_reg(list,OS_ADDR,tmpref.offset,r)
+ else
+ if tmpref.offset<>0 then
+ a_op_const_reg_reg(list,OP_ADD,OS_ADDR,tmpref.offset,tmpref.base,r)
+ else
+ begin
+ instr:=taicpu.op_reg_reg(A_MOV,r,tmpref.base);
+ list.concat(instr);
+ add_move_instruction(instr);
+ end;
+ end;
+ end;
+
+
+ procedure tcgarm.fixref(list : TAsmList;var ref : treference);
+ var
+ tmpreg : tregister;
+ tmpref : treference;
+ l : tasmlabel;
+ begin
+ { absolute symbols can't be handled directly, we've to store the symbol reference
+ in the text segment and access it pc relative
+
+ For now, we assume that references where base or index equals to PC are already
+ relative, all other references are assumed to be absolute and thus they need
+ to be handled extra.
+
+ A proper solution would be to change refoptions to a set and store the information
+ if the symbol is absolute or relative there.
+ }
+ { create consts entry }
+ reference_reset(tmpref,4);
+ current_asmdata.getjumplabel(l);
+ cg.a_label(current_procinfo.aktlocaldata,l);
+ tmpref.symboldata:=current_procinfo.aktlocaldata.last;
+
+ if assigned(ref.symbol) then
+ current_procinfo.aktlocaldata.concat(tai_const.create_sym_offset(ref.symbol,ref.offset))
+ else
+ current_procinfo.aktlocaldata.concat(tai_const.Create_32bit(ref.offset));
+
+ { load consts entry }
+ tmpreg:=getintregister(list,OS_INT);
+ tmpref.symbol:=l;
+ tmpref.base:=NR_PC;
+ list.concat(taicpu.op_reg_ref(A_LDR,tmpreg,tmpref));
+
+ if (ref.base<>NR_NO) then
+ begin
+ if ref.index<>NR_NO then
+ begin
+ list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.base,tmpreg));
+ ref.base:=tmpreg;
+ end
+ else
+ if ref.base<>NR_PC then
+ begin
+ ref.index:=tmpreg;
+ ref.shiftimm:=0;
+ ref.signindex:=1;
+ ref.shiftmode:=SM_None;
+ end
+ else
+ ref.base:=tmpreg;
+ end
+ else
+ ref.base:=tmpreg;
+ ref.offset:=0;
+ ref.symbol:=nil;
+ end;
+
+
+ procedure tcgarm.g_concatcopy_move(list : TAsmList;const source,dest : treference;len : tcgint);
+ var
+ paraloc1,paraloc2,paraloc3 : TCGPara;
+ begin
+ paraloc1.init;
+ paraloc2.init;
+ paraloc3.init;
+ paramanager.getintparaloc(pocall_default,1,paraloc1);
+ paramanager.getintparaloc(pocall_default,2,paraloc2);
+ paramanager.getintparaloc(pocall_default,3,paraloc3);
+ a_load_const_cgpara(list,OS_INT,len,paraloc3);
+ a_loadaddr_ref_cgpara(list,dest,paraloc2);
+ a_loadaddr_ref_cgpara(list,source,paraloc1);
+ paramanager.freecgpara(list,paraloc3);
+ paramanager.freecgpara(list,paraloc2);
+ paramanager.freecgpara(list,paraloc1);
+ alloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
+ alloccpuregisters(list,R_FPUREGISTER,paramanager.get_volatile_registers_fpu(pocall_default));
+ a_call_name(list,'FPC_MOVE',false);
+ dealloccpuregisters(list,R_FPUREGISTER,paramanager.get_volatile_registers_fpu(pocall_default));
+ dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
+ paraloc3.done;
+ paraloc2.done;
+ paraloc1.done;
+ end;
+
+
+ procedure tcgarm.g_concatcopy_internal(list : TAsmList;const source,dest : treference;len : tcgint;aligned : boolean);
+ const
+ maxtmpreg=10;{roozbeh: can be reduced to 8 or lower if might conflick with reserved ones,also +2 is used becouse of regs required for referencing}
+
+ var
+ srcref,dstref,usedtmpref,usedtmpref2:treference;
+ srcreg,destreg,countreg,r,tmpreg:tregister;
+ helpsize:aint;
+ copysize:byte;
+ cgsize:Tcgsize;
+ tmpregisters:array[1..maxtmpreg] of tregister;
+ tmpregi,tmpregi2:byte;
+
+ { will never be called with count<=4 }
+ procedure genloop(count : aword;size : byte);
+ const
+ size2opsize : array[1..4] of tcgsize = (OS_8,OS_16,OS_NO,OS_32);
+ var
+ l : tasmlabel;
+ begin
+ current_asmdata.getjumplabel(l);
+ if count<size then size:=1;
+ a_load_const_reg(list,OS_INT,count div size,countreg);
+ cg.a_label(list,l);
+ srcref.addressmode:=AM_POSTINDEXED;
+ dstref.addressmode:=AM_POSTINDEXED;
+ srcref.offset:=size;
+ dstref.offset:=size;
+ r:=getintregister(list,size2opsize[size]);
+ a_load_ref_reg(list,size2opsize[size],size2opsize[size],srcref,r);
+ list.concat(setoppostfix(taicpu.op_reg_reg_const(A_SUB,countreg,countreg,1),PF_S));
+ a_load_reg_ref(list,size2opsize[size],size2opsize[size],r,dstref);
+ a_jmp_flags(list,F_NE,l);
+ srcref.offset:=1;
+ dstref.offset:=1;
+ case count mod size of
+ 1:
+ begin
+ a_load_ref_reg(list,OS_8,OS_8,srcref,r);
+ a_load_reg_ref(list,OS_8,OS_8,r,dstref);
+ end;
+ 2:
+ if aligned then
+ begin
+ a_load_ref_reg(list,OS_16,OS_16,srcref,r);
+ a_load_reg_ref(list,OS_16,OS_16,r,dstref);
+ end
+ else
+ begin
+ a_load_ref_reg(list,OS_8,OS_8,srcref,r);
+ a_load_reg_ref(list,OS_8,OS_8,r,dstref);
+ a_load_ref_reg(list,OS_8,OS_8,srcref,r);
+ a_load_reg_ref(list,OS_8,OS_8,r,dstref);
+ end;
+ 3:
+ if aligned then
+ begin
+ srcref.offset:=2;
+ dstref.offset:=2;
+ a_load_ref_reg(list,OS_16,OS_16,srcref,r);
+ a_load_reg_ref(list,OS_16,OS_16,r,dstref);
+ a_load_ref_reg(list,OS_8,OS_8,srcref,r);
+ a_load_reg_ref(list,OS_8,OS_8,r,dstref);
+ end
+ else
+ begin
+ a_load_ref_reg(list,OS_8,OS_8,srcref,r);
+ a_load_reg_ref(list,OS_8,OS_8,r,dstref);
+ a_load_ref_reg(list,OS_8,OS_8,srcref,r);
+ a_load_reg_ref(list,OS_8,OS_8,r,dstref);
+ a_load_ref_reg(list,OS_8,OS_8,srcref,r);
+ a_load_reg_ref(list,OS_8,OS_8,r,dstref);
+ end;
+ end;
+ { keep the registers alive }
+ list.concat(taicpu.op_reg_reg(A_MOV,countreg,countreg));
+ list.concat(taicpu.op_reg_reg(A_MOV,srcreg,srcreg));
+ list.concat(taicpu.op_reg_reg(A_MOV,destreg,destreg));
+ end;
+
+ begin
+ if len=0 then
+ exit;
+ helpsize:=12+maxtmpreg*4;//52 with maxtmpreg=10
+ dstref:=dest;
+ srcref:=source;
+ if cs_opt_size in current_settings.optimizerswitches then
+ helpsize:=8;
+ if (len<=helpsize) and aligned then
+ begin
+ tmpregi:=0;
+ srcreg:=getintregister(list,OS_ADDR);
+
+ { explicit pc relative addressing, could be
+ e.g. a floating point constant }
+ if source.base=NR_PC then
+ begin
+ { ... then we don't need a loadaddr }
+ srcref:=source;
+ end
+ else
+ begin
+ a_loadaddr_ref_reg(list,source,srcreg);
+ reference_reset_base(srcref,srcreg,0,source.alignment);
+ end;
+
+ while (len div 4 <> 0) and (tmpregi<maxtmpreg) do
+ begin
+ inc(tmpregi);
+ tmpregisters[tmpregi]:=getintregister(list,OS_32);
+ a_load_ref_reg(list,OS_32,OS_32,srcref,tmpregisters[tmpregi]);
+ inc(srcref.offset,4);
+ dec(len,4);
+ end;
+
+ destreg:=getintregister(list,OS_ADDR);
+ a_loadaddr_ref_reg(list,dest,destreg);
+ reference_reset_base(dstref,destreg,0,dest.alignment);
+ tmpregi2:=1;
+ while (tmpregi2<=tmpregi) do
+ begin
+ a_load_reg_ref(list,OS_32,OS_32,tmpregisters[tmpregi2],dstref);
+ inc(dstref.offset,4);
+ inc(tmpregi2);
+ end;
+
+ copysize:=4;
+ cgsize:=OS_32;
+ while len<>0 do
+ begin
+ if len<2 then
+ begin
+ copysize:=1;
+ cgsize:=OS_8;
+ end
+ else if len<4 then
+ begin
+ copysize:=2;
+ cgsize:=OS_16;
+ end;
+ dec(len,copysize);
+ r:=getintregister(list,cgsize);
+ a_load_ref_reg(list,cgsize,cgsize,srcref,r);
+ a_load_reg_ref(list,cgsize,cgsize,r,dstref);
+ inc(srcref.offset,copysize);
+ inc(dstref.offset,copysize);
+ end;{end of while}
+ end
+ else
+ begin
+ cgsize:=OS_32;
+ if (len<=4) then{len<=4 and not aligned}
+ begin
+ r:=getintregister(list,cgsize);
+ usedtmpref:=a_internal_load_ref_reg(list,OS_8,OS_8,srcref,r);
+ if Len=1 then
+ a_load_reg_ref(list,OS_8,OS_8,r,dstref)
+ else
+ begin
+ tmpreg:=getintregister(list,cgsize);
+ usedtmpref2:=a_internal_load_reg_ref(list,OS_8,OS_8,r,dstref);
+ inc(usedtmpref.offset,1);
+ a_load_ref_reg(list,OS_8,OS_8,usedtmpref,tmpreg);
+ inc(usedtmpref2.offset,1);
+ a_load_reg_ref(list,OS_8,OS_8,tmpreg,usedtmpref2);
+ if len>2 then
+ begin
+ inc(usedtmpref.offset,1);
+ a_load_ref_reg(list,OS_8,OS_8,usedtmpref,tmpreg);
+ inc(usedtmpref2.offset,1);
+ a_load_reg_ref(list,OS_8,OS_8,tmpreg,usedtmpref2);
+ if len>3 then
+ begin
+ inc(usedtmpref.offset,1);
+ a_load_ref_reg(list,OS_8,OS_8,usedtmpref,tmpreg);
+ inc(usedtmpref2.offset,1);
+ a_load_reg_ref(list,OS_8,OS_8,tmpreg,usedtmpref2);
+ end;
+ end;
+ end;
+ end{end of if len<=4}
+ else
+ begin{unaligned & 4<len<helpsize **or** aligned/unaligned & len>helpsize}
+ destreg:=getintregister(list,OS_ADDR);
+ a_loadaddr_ref_reg(list,dest,destreg);
+ reference_reset_base(dstref,destreg,0,dest.alignment);
+
+ srcreg:=getintregister(list,OS_ADDR);
+ a_loadaddr_ref_reg(list,source,srcreg);
+ reference_reset_base(srcref,srcreg,0,source.alignment);
+
+ countreg:=getintregister(list,OS_32);
+
+// if cs_opt_size in current_settings.optimizerswitches then
+ { roozbeh : it seems loading 1 byte is faster becouse of caching/fetching(?) }
+ {if aligned then
+ genloop(len,4)
+ else}
+ genloop(len,1);
+ end;
+ end;
+ end;
+
+ procedure tcgarm.g_concatcopy_unaligned(list : TAsmList;const source,dest : treference;len : tcgint);
+ begin
+ g_concatcopy_internal(list,source,dest,len,false);
+ end;
+
+
+ procedure tcgarm.g_concatcopy(list : TAsmList;const source,dest : treference;len : tcgint);
+ begin
+ if (source.alignment in [1..3]) or
+ (dest.alignment in [1..3]) then
+ g_concatcopy_internal(list,source,dest,len,false)
+ else
+ g_concatcopy_internal(list,source,dest,len,true);
+ end;
+
+
+ procedure tcgarm.g_overflowCheck(list : TAsmList;const l : tlocation;def : tdef);
+ var
+ ovloc : tlocation;
+ begin
+ ovloc.loc:=LOC_VOID;
+ g_overflowCheck_loc(list,l,def,ovloc);
+ end;
+
+
+ procedure tcgarm.g_overflowCheck_loc(List:TAsmList;const Loc:TLocation;def:TDef;ovloc : tlocation);
+ var
+ hl : tasmlabel;
+ ai:TAiCpu;
+ hflags : tresflags;
+ begin
+ if not(cs_check_overflow in current_settings.localswitches) then
+ exit;
+ current_asmdata.getjumplabel(hl);
+ case ovloc.loc of
+ LOC_VOID:
+ begin
+ ai:=taicpu.op_sym(A_B,hl);
+ ai.is_jmp:=true;
+
+ if not((def.typ=pointerdef) or
+ ((def.typ=orddef) and
+ (torddef(def).ordtype in [u64bit,u16bit,u32bit,u8bit,uchar,
+ pasbool8,pasbool16,pasbool32,pasbool64]))) then
+ ai.SetCondition(C_VC)
+ else
+ if TAiCpu(List.Last).opcode in [A_RSB,A_RSC,A_SBC,A_SUB] then
+ ai.SetCondition(C_CS)
+ else
+ ai.SetCondition(C_CC);
+
+ list.concat(ai);
+ end;
+ LOC_FLAGS:
+ begin
+ hflags:=ovloc.resflags;
+ inverse_flags(hflags);
+ cg.a_jmp_flags(list,hflags,hl);
+ end;
+ else
+ internalerror(200409281);
+ end;
+
+ a_call_name(list,'FPC_OVERFLOW',false);
+ a_label(list,hl);
+ end;
+
+
+ procedure tcgarm.g_save_registers(list : TAsmList);
+ begin
+ { this work is done in g_proc_entry }
+ end;
+
+
+ procedure tcgarm.g_restore_registers(list : TAsmList);
+ begin
+ { this work is done in g_proc_exit }
+ end;
+
+
+ procedure tcgarm.a_jmp_cond(list : TAsmList;cond : TOpCmp;l: tasmlabel);
+ var
+ ai : taicpu;
+ begin
+ ai:=Taicpu.Op_sym(A_B,l);
+ ai.SetCondition(OpCmp2AsmCond[cond]);
+ ai.is_jmp:=true;
+ list.concat(ai);
+ end;
+
+
+ procedure tcgarm.g_adjust_self_value(list:TAsmList;procdef: tprocdef;ioffset: tcgint);
+ var
+ hsym : tsym;
+ href : treference;
+ paraloc : Pcgparalocation;
+ shift : byte;
+ begin
+ { calculate the parameter info for the procdef }
+ procdef.init_paraloc_info(callerside);
+ hsym:=tsym(procdef.parast.Find('self'));
+ if not(assigned(hsym) and
+ (hsym.typ=paravarsym)) then
+ internalerror(200305251);
+ paraloc:=tparavarsym(hsym).paraloc[callerside].location;
+ while paraloc<>nil do
+ with paraloc^ do
+ begin
+ case loc of
+ LOC_REGISTER:
+ begin
+ if is_shifter_const(ioffset,shift) then
+ a_op_const_reg(list,OP_SUB,size,ioffset,register)
+ else
+ begin
+ a_load_const_reg(list,OS_ADDR,ioffset,NR_R12);
+ a_op_reg_reg(list,OP_SUB,size,NR_R12,register);
+ end;
+ end;
+ LOC_REFERENCE:
+ begin
+ { offset in the wrapper needs to be adjusted for the stored
+ return address }
+ reference_reset_base(href,reference.index,reference.offset+sizeof(aint),sizeof(pint));
+ if is_shifter_const(ioffset,shift) then
+ a_op_const_ref(list,OP_SUB,size,ioffset,href)
+ else
+ begin
+ a_load_const_reg(list,OS_ADDR,ioffset,NR_R12);
+ a_op_reg_ref(list,OP_SUB,size,NR_R12,href);
+ end;
+ end
+ else
+ internalerror(200309189);
+ end;
+ paraloc:=next;
+ end;
+ end;
+
+ procedure tcgarm.g_stackpointer_alloc(list: TAsmList; size: longint);
+ begin
+ internalerror(200807237);
+ end;
+
+
+ function get_scalar_mm_op(fromsize,tosize : tcgsize) : tasmop;
+ const
+ convertop : array[OS_F32..OS_F128,OS_F32..OS_F128] of tasmop = (
+ (A_FCPYS,A_FCVTSD,A_NONE,A_NONE,A_NONE),
+ (A_FCVTDS,A_FCPYD,A_NONE,A_NONE,A_NONE),
+ (A_NONE,A_NONE,A_NONE,A_NONE,A_NONE),
+ (A_NONE,A_NONE,A_NONE,A_NONE,A_NONE),
+ (A_NONE,A_NONE,A_NONE,A_NONE,A_NONE));
+ begin
+ result:=convertop[fromsize,tosize];
+ if result=A_NONE then
+ internalerror(200312205);
+ end;
+
+
+ procedure tcgarm.a_loadmm_reg_reg(list: tasmlist; fromsize,tosize: tcgsize; reg1,reg2: tregister; shuffle: pmmshuffle);
+ var
+ instr: taicpu;
+ begin
+ if shuffle=nil then
+ begin
+ if fromsize=tosize then
+ { needs correct size in case of spilling }
+ case fromsize of
+ OS_F32:
+ instr:=taicpu.op_reg_reg(A_FCPYS,reg2,reg1);
+ OS_F64:
+ instr:=taicpu.op_reg_reg(A_FCPYD,reg2,reg1);
+ else
+ internalerror(2009112405);
+ end
+ else
+ internalerror(2009112406);
+ end
+ else if shufflescalar(shuffle) then
+ instr:=taicpu.op_reg_reg(get_scalar_mm_op(tosize,fromsize),reg2,reg1)
+ else
+ internalerror(2009112407);
+ list.concat(instr);
+ case instr.opcode of
+ A_FCPYS,
+ A_FCPYD:
+ add_move_instruction(instr);
+ end;
+ end;
+
+
+ procedure tcgarm.a_loadmm_ref_reg(list: tasmlist; fromsize,tosize: tcgsize; const ref: treference; reg: tregister; shuffle: pmmshuffle);
+ var
+ intreg,
+ tmpmmreg : tregister;
+ reg64 : tregister64;
+ op : tasmop;
+ begin
+ if assigned(shuffle) and
+ not(shufflescalar(shuffle)) then
+ internalerror(2009112413);
+
+ case fromsize of
+ OS_32,OS_S32:
+ begin
+ fromsize:=OS_F32;
+ { since we are loading an integer, no conversion may be required }
+ if (fromsize<>tosize) then
+ internalerror(2009112801);
+ end;
+ OS_64,OS_S64:
+ begin
+ fromsize:=OS_F64;
+ { since we are loading an integer, no conversion may be required }
+ if (fromsize<>tosize) then
+ internalerror(2009112901);
+ end;
+ end;
+
+ if (fromsize<>tosize) then
+ tmpmmreg:=getmmregister(list,fromsize)
+ else
+ tmpmmreg:=reg;
+ if (ref.alignment in [1,2]) then
+ begin
+ case fromsize of
+ OS_F32:
+ begin
+ intreg:=getintregister(list,OS_32);
+ a_load_ref_reg(list,OS_32,OS_32,ref,intreg);
+ a_loadmm_intreg_reg(list,OS_32,OS_F32,intreg,tmpmmreg,mms_movescalar);
+ end;
+ OS_F64:
+ begin
+ reg64.reglo:=getintregister(list,OS_32);
+ reg64.reghi:=getintregister(list,OS_32);
+ cg64.a_load64_ref_reg(list,ref,reg64);
+ cg64.a_loadmm_intreg64_reg(list,OS_F64,reg64,tmpmmreg);
+ end;
+ else
+ internalerror(2009112412);
+ end;
+ end
+ else
+ begin
+ case fromsize of
+ OS_F32:
+ op:=A_FLDS;
+ OS_F64:
+ op:=A_FLDD;
+ else
+ internalerror(2009112415);
+ end;
+ handle_load_store(list,op,PF_None,tmpmmreg,ref);
+ end;
+
+ if (tmpmmreg<>reg) then
+ a_loadmm_reg_reg(list,fromsize,tosize,tmpmmreg,reg,shuffle);
+ end;
+
+
+ procedure tcgarm.a_loadmm_reg_ref(list: tasmlist; fromsize,tosize: tcgsize; reg: tregister; const ref: treference; shuffle: pmmshuffle);
+ var
+ intreg,
+ tmpmmreg : tregister;
+ reg64 : tregister64;
+ op : tasmop;
+ begin
+ if assigned(shuffle) and
+ not(shufflescalar(shuffle)) then
+ internalerror(2009112416);
+
+ case tosize of
+ OS_32,OS_S32:
+ begin
+ tosize:=OS_F32;
+ { since we are loading an integer, no conversion may be required }
+ if (fromsize<>tosize) then
+ internalerror(2009112801);
+ end;
+ OS_64,OS_S64:
+ begin
+ tosize:=OS_F64;
+ { since we are loading an integer, no conversion may be required }
+ if (fromsize<>tosize) then
+ internalerror(2009112901);
+ end;
+ end;
+
+ if (fromsize<>tosize) then
+ begin
+ tmpmmreg:=getmmregister(list,tosize);
+ a_loadmm_reg_reg(list,fromsize,tosize,reg,tmpmmreg,shuffle);
+ end
+ else
+ tmpmmreg:=reg;
+ if (ref.alignment in [1,2]) then
+ begin
+ case tosize of
+ OS_F32:
+ begin
+ intreg:=getintregister(list,OS_32);
+ a_loadmm_reg_intreg(list,OS_F32,OS_32,tmpmmreg,intreg,shuffle);
+ a_load_reg_ref(list,OS_32,OS_32,intreg,ref);
+ end;
+ OS_F64:
+ begin
+ reg64.reglo:=getintregister(list,OS_32);
+ reg64.reghi:=getintregister(list,OS_32);
+ cg64.a_loadmm_reg_intreg64(list,OS_F64,tmpmmreg,reg64);
+ cg64.a_load64_reg_ref(list,reg64,ref);
+ end;
+ else
+ internalerror(2009112417);
+ end;
+ end
+ else
+ begin
+ case fromsize of
+ OS_F32:
+ op:=A_FSTS;
+ OS_F64:
+ op:=A_FSTD;
+ else
+ internalerror(2009112418);
+ end;
+ handle_load_store(list,op,PF_None,tmpmmreg,ref);
+ end;
+ end;
+
+
+ procedure tcgarm.a_loadmm_intreg_reg(list: TAsmList; fromsize, tosize : tcgsize; intreg, mmreg: tregister; shuffle: pmmshuffle);
+ begin
+ { this code can only be used to transfer raw data, not to perform
+ conversions }
+ if (tosize<>OS_F32) then
+ internalerror(2009112419);
+ if not(fromsize in [OS_32,OS_S32]) then
+ internalerror(2009112420);
+ if assigned(shuffle) and
+ not shufflescalar(shuffle) then
+ internalerror(2009112516);
+ list.concat(taicpu.op_reg_reg(A_FMSR,mmreg,intreg));
+ end;
+
+
+ procedure tcgarm.a_loadmm_reg_intreg(list: TAsmList; fromsize, tosize : tcgsize; mmreg, intreg: tregister;shuffle : pmmshuffle);
+ begin
+ { this code can only be used to transfer raw data, not to perform
+ conversions }
+ if (fromsize<>OS_F32) then
+ internalerror(2009112430);
+ if not(tosize in [OS_32,OS_S32]) then
+ internalerror(2009112420);
+ if assigned(shuffle) and
+ not shufflescalar(shuffle) then
+ internalerror(2009112514);
+ list.concat(taicpu.op_reg_reg(A_FMRS,intreg,mmreg));
+ end;
+
+
+ procedure tcgarm.a_opmm_reg_reg(list: tasmlist; op: topcg; size: tcgsize; src, dst: tregister; shuffle: pmmshuffle);
+ var
+ tmpreg: tregister;
+ begin
+ { the vfp doesn't support xor nor any other logical operation, but
+ this routine is used to initialise global mm regvars. We can
+ easily initialise an mm reg with 0 though. }
+ case op of
+ OP_XOR:
+ begin
+ if (src<>dst) or
+ (reg_cgsize(src)<>size) or
+ assigned(shuffle) then
+ internalerror(2009112907);
+ tmpreg:=getintregister(list,OS_32);
+ a_load_const_reg(list,OS_32,0,tmpreg);
+ case size of
+ OS_F32:
+ list.concat(taicpu.op_reg_reg(A_FMSR,dst,tmpreg));
+ OS_F64:
+ list.concat(taicpu.op_reg_reg_reg(A_FMDRR,dst,tmpreg,tmpreg));
+ else
+ internalerror(2009112908);
+ end;
+ end
+ else
+ internalerror(2009112906);
+ end;
+ end;
+
+
+ procedure tcgarm.g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);
+
+ procedure loadvmttor12;
+ var
+ href : treference;
+ begin
+ reference_reset_base(href,NR_R0,0,sizeof(pint));
+ cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_R12);
+ end;
+
+
+ procedure op_onr12methodaddr;
+ var
+ href : treference;
+ begin
+ if (procdef.extnumber=$ffff) then
+ Internalerror(200006139);
+ { call/jmp vmtoffs(%eax) ; method offs }
+ reference_reset_base(href,NR_R12,tobjectdef(procdef.struct).vmtmethodoffset(procdef.extnumber),sizeof(pint));
+ cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_R12);
+ list.concat(taicpu.op_reg_reg(A_MOV,NR_PC,NR_R12));
+ end;
+
+ var
+ make_global : boolean;
+ begin
+ if not(procdef.proctypeoption in [potype_function,potype_procedure]) then
+ Internalerror(200006137);
+ if not assigned(procdef.struct) or
+ (procdef.procoptions*[po_classmethod, po_staticmethod,
+ po_methodpointer, po_interrupt, po_iocheck]<>[]) then
+ Internalerror(200006138);
+ if procdef.owner.symtabletype<>ObjectSymtable then
+ Internalerror(200109191);
+
+ make_global:=false;
+ if (not current_module.is_unit) or
+ create_smartlink or
+ (procdef.owner.defowner.owner.symtabletype=globalsymtable) then
+ make_global:=true;
+
+ if make_global then
+ list.concat(Tai_symbol.Createname_global(labelname,AT_FUNCTION,0))
+ else
+ list.concat(Tai_symbol.Createname(labelname,AT_FUNCTION,0));
+
+ { the wrapper might need aktlocaldata for the additional data to
+ load the constant }
+ current_procinfo:=cprocinfo.create(nil);
+
+ { set param1 interface to self }
+ g_adjust_self_value(list,procdef,ioffset);
+
+ { case 4 }
+ if (po_virtualmethod in procdef.procoptions) and
+ not is_objectpascal_helper(procdef.struct) then
+ begin
+ loadvmttor12;
+ op_onr12methodaddr;
+ end
+ { case 0 }
+ else
+ list.concat(taicpu.op_sym(A_B,current_asmdata.RefAsmSymbol(procdef.mangledname)));
+ list.concatlist(current_procinfo.aktlocaldata);
+
+ current_procinfo.Free;
+ current_procinfo:=nil;
+
+ list.concat(Tai_symbol_end.Createname(labelname));
+ end;
+
+
+ procedure tcgarm.maybeadjustresult(list: TAsmList; op: TOpCg; size: tcgsize; dst: tregister);
+ const
+ overflowops = [OP_MUL,OP_SHL,OP_ADD,OP_SUB,OP_NOT,OP_NEG];
+ begin
+ if (op in overflowops) and
+ (size in [OS_8,OS_S8,OS_16,OS_S16]) then
+ a_load_reg_reg(list,OS_32,size,dst,dst);
+ end;
+
+
+ function tcgarm.get_darwin_call_stub(const s: string; weak: boolean): tasmsymbol;
+ var
+ stubname: string;
+ l1: tasmsymbol;
+ href: treference;
+ begin
+ stubname := 'L'+s+'$stub';
+ result := current_asmdata.getasmsymbol(stubname);
+ if assigned(result) then
+ exit;
+
+ if current_asmdata.asmlists[al_imports]=nil then
+ current_asmdata.asmlists[al_imports]:=TAsmList.create;
+
+ new_section(current_asmdata.asmlists[al_imports],sec_stub,'',4);
+ result := current_asmdata.RefAsmSymbol(stubname);
+ current_asmdata.asmlists[al_imports].concat(Tai_symbol.Create(result,0));
+ { register as a weak symbol if necessary }
+ if weak then
+ current_asmdata.weakrefasmsymbol(s);
+ current_asmdata.asmlists[al_imports].concat(tai_directive.create(asd_indirect_symbol,s));
+
+ if not(cs_create_pic in current_settings.moduleswitches) then
+ begin
+ l1 := current_asmdata.RefAsmSymbol('L'+s+'$slp');
+ reference_reset_symbol(href,l1,0,sizeof(pint));
+ href.refaddr:=addr_full;
+ current_asmdata.asmlists[al_imports].concat(taicpu.op_reg_ref(A_LDR,NR_R12,href));
+ reference_reset_base(href,NR_R12,0,sizeof(pint));
+ current_asmdata.asmlists[al_imports].concat(taicpu.op_reg_ref(A_LDR,NR_R15,href));
+ current_asmdata.asmlists[al_imports].concat(Tai_symbol.Create(l1,0));
+ l1 := current_asmdata.RefAsmSymbol('L'+s+'$lazy_ptr');
+ current_asmdata.asmlists[al_imports].concat(tai_const.create_sym(l1));
+ end
+ else
+ internalerror(2008100401);
+
+ new_section(current_asmdata.asmlists[al_imports],sec_data_lazy,'',sizeof(pint));
+ current_asmdata.asmlists[al_imports].concat(Tai_symbol.Create(l1,0));
+ current_asmdata.asmlists[al_imports].concat(tai_directive.create(asd_indirect_symbol,s));
+ current_asmdata.asmlists[al_imports].concat(tai_const.createname('dyld_stub_binding_helper',0));
+ end;
+
+
+ procedure tcg64farm.a_op64_reg_reg(list : TAsmList;op:TOpCG;size : tcgsize;regsrc,regdst : tregister64);
+ begin
+ case op of
+ OP_NEG:
+ begin
+ list.concat(setoppostfix(taicpu.op_reg_reg_const(A_RSB,regdst.reglo,regsrc.reglo,0),PF_S));
+ list.concat(taicpu.op_reg_reg_const(A_RSC,regdst.reghi,regsrc.reghi,0));
+ end;
+ OP_NOT:
+ begin
+ cg.a_op_reg_reg(list,OP_NOT,OS_INT,regsrc.reglo,regdst.reglo);
+ cg.a_op_reg_reg(list,OP_NOT,OS_INT,regsrc.reghi,regdst.reghi);
+ end;
+ else
+ a_op64_reg_reg_reg(list,op,size,regsrc,regdst,regdst);
+ end;
+ end;
+
+
+ procedure tcg64farm.a_op64_const_reg(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;reg : tregister64);
+ begin
+ a_op64_const_reg_reg(list,op,size,value,reg,reg);
+ end;
+
+
+ procedure tcg64farm.a_op64_const_reg_reg(list: TAsmList;op:TOpCG;size : tcgsize;value : int64;regsrc,regdst : tregister64);
+ var
+ ovloc : tlocation;
+ begin
+ a_op64_const_reg_reg_checkoverflow(list,op,size,value,regsrc,regdst,false,ovloc);
+ end;
+
+
+ procedure tcg64farm.a_op64_reg_reg_reg(list: TAsmList;op:TOpCG;size : tcgsize;regsrc1,regsrc2,regdst : tregister64);
+ var
+ ovloc : tlocation;
+ begin
+ a_op64_reg_reg_reg_checkoverflow(list,op,size,regsrc1,regsrc2,regdst,false,ovloc);
+ end;
+
+
+ procedure tcg64farm.a_loadmm_intreg64_reg(list: TAsmList; mmsize: tcgsize; intreg: tregister64; mmreg: tregister);
+ begin
+ { this code can only be used to transfer raw data, not to perform
+ conversions }
+ if (mmsize<>OS_F64) then
+ internalerror(2009112405);
+ list.concat(taicpu.op_reg_reg_reg(A_FMDRR,mmreg,intreg.reglo,intreg.reghi));
+ end;
+
+
+ procedure tcg64farm.a_loadmm_reg_intreg64(list: TAsmList; mmsize: tcgsize; mmreg: tregister; intreg: tregister64);
+ begin
+ { this code can only be used to transfer raw data, not to perform
+ conversions }
+ if (mmsize<>OS_F64) then
+ internalerror(2009112406);
+ list.concat(taicpu.op_reg_reg_reg(A_FMRRD,intreg.reglo,intreg.reghi,mmreg));
+ end;
+
+
+ procedure tcg64farm.a_op64_const_reg_reg_checkoverflow(list: TAsmList;op:TOpCG;size : tcgsize;value : int64;regsrc,regdst : tregister64;setflags : boolean;var ovloc : tlocation);
+ var
+ tmpreg : tregister;
+ b : byte;
+ begin
+ ovloc.loc:=LOC_VOID;
+ case op of
+ OP_NEG,
+ OP_NOT :
+ internalerror(200306017);
+ end;
+ if (setflags or tcgarm(cg).cgsetflags) and (op in [OP_ADD,OP_SUB]) then
+ begin
+ case op of
+ OP_ADD:
+ begin
+ if is_shifter_const(lo(value),b) then
+ list.concat(setoppostfix(taicpu.op_reg_reg_const(A_ADD,regdst.reglo,regsrc.reglo,lo(value)),PF_S))
+ else
+ begin
+ tmpreg:=cg.getintregister(list,OS_32);
+ cg.a_load_const_reg(list,OS_32,lo(value),tmpreg);
+ list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_ADD,regdst.reglo,regsrc.reglo,tmpreg),PF_S));
+ end;
+
+ if is_shifter_const(hi(value),b) then
+ list.concat(setoppostfix(taicpu.op_reg_reg_const(A_ADC,regdst.reghi,regsrc.reghi,hi(value)),PF_S))
+ else
+ begin
+ tmpreg:=cg.getintregister(list,OS_32);
+ cg.a_load_const_reg(list,OS_32,hi(value),tmpreg);
+ list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_ADC,regdst.reghi,regsrc.reghi,tmpreg),PF_S));
+ end;
+ end;
+ OP_SUB:
+ begin
+ if is_shifter_const(lo(value),b) then
+ list.concat(setoppostfix(taicpu.op_reg_reg_const(A_SUB,regdst.reglo,regsrc.reglo,lo(value)),PF_S))
+ else
+ begin
+ tmpreg:=cg.getintregister(list,OS_32);
+ cg.a_load_const_reg(list,OS_32,lo(value),tmpreg);
+ list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_SUB,regdst.reglo,regsrc.reglo,tmpreg),PF_S));
+ end;
+
+ if is_shifter_const(hi(value),b) then
+ list.concat(setoppostfix(taicpu.op_reg_reg_const(A_SBC,regdst.reghi,regsrc.reghi,aint(hi(value))),PF_S))
+ else
+ begin
+ tmpreg:=cg.getintregister(list,OS_32);
+ cg.a_load_const_reg(list,OS_32,hi(value),tmpreg);
+ list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_SBC,regdst.reghi,regsrc.reghi,tmpreg),PF_S));
+ end;
+ end;
+ else
+ internalerror(200502131);
+ end;
+ if size=OS_64 then
+ begin
+ { the arm has an weired opinion how flags for SUB/ADD are handled }
+ ovloc.loc:=LOC_FLAGS;
+ case op of
+ OP_ADD:
+ ovloc.resflags:=F_CS;
+ OP_SUB:
+ ovloc.resflags:=F_CC;
+ end;
+ end;
+ end
+ else
+ begin
+ case op of
+ OP_AND,OP_OR,OP_XOR:
+ begin
+ cg.a_op_const_reg_reg(list,op,OS_32,aint(lo(value)),regsrc.reglo,regdst.reglo);
+ cg.a_op_const_reg_reg(list,op,OS_32,aint(hi(value)),regsrc.reghi,regdst.reghi);
+ end;
+ OP_ADD:
+ begin
+ if is_shifter_const(aint(lo(value)),b) then
+ list.concat(setoppostfix(taicpu.op_reg_reg_const(A_ADD,regdst.reglo,regsrc.reglo,aint(lo(value))),PF_S))
+ else
+ begin
+ tmpreg:=cg.getintregister(list,OS_32);
+ cg.a_load_const_reg(list,OS_32,aint(lo(value)),tmpreg);
+ list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_ADD,regdst.reglo,regsrc.reglo,tmpreg),PF_S));
+ end;
+
+ if is_shifter_const(aint(hi(value)),b) then
+ list.concat(taicpu.op_reg_reg_const(A_ADC,regdst.reghi,regsrc.reghi,aint(hi(value))))
+ else
+ begin
+ tmpreg:=cg.getintregister(list,OS_32);
+ cg.a_load_const_reg(list,OS_32,aint(hi(value)),tmpreg);
+ list.concat(taicpu.op_reg_reg_reg(A_ADC,regdst.reghi,regsrc.reghi,tmpreg));
+ end;
+ end;
+ OP_SUB:
+ begin
+ if is_shifter_const(aint(lo(value)),b) then
+ list.concat(setoppostfix(taicpu.op_reg_reg_const(A_SUB,regdst.reglo,regsrc.reglo,aint(lo(value))),PF_S))
+ else
+ begin
+ tmpreg:=cg.getintregister(list,OS_32);
+ cg.a_load_const_reg(list,OS_32,aint(lo(value)),tmpreg);
+ list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_SUB,regdst.reglo,regsrc.reglo,tmpreg),PF_S));
+ end;
+
+ if is_shifter_const(aint(hi(value)),b) then
+ list.concat(taicpu.op_reg_reg_const(A_SBC,regdst.reghi,regsrc.reghi,aint(hi(value))))
+ else
+ begin
+ tmpreg:=cg.getintregister(list,OS_32);
+ cg.a_load_const_reg(list,OS_32,hi(value),tmpreg);
+ list.concat(taicpu.op_reg_reg_reg(A_SBC,regdst.reghi,regsrc.reghi,tmpreg));
+ end;
+ end;
+ else
+ internalerror(2003083101);
+ end;
+ end;
+ end;
+
+
+ procedure tcg64farm.a_op64_reg_reg_reg_checkoverflow(list: TAsmList;op:TOpCG;size : tcgsize;regsrc1,regsrc2,regdst : tregister64;setflags : boolean;var ovloc : tlocation);
+ begin
+ ovloc.loc:=LOC_VOID;
+ case op of
+ OP_NEG,
+ OP_NOT :
+ internalerror(200306017);
+ end;
+ if (setflags or tcgarm(cg).cgsetflags) and (op in [OP_ADD,OP_SUB]) then
+ begin
+ case op of
+ OP_ADD:
+ begin
+ list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_ADD,regdst.reglo,regsrc1.reglo,regsrc2.reglo),PF_S));
+ list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_ADC,regdst.reghi,regsrc1.reghi,regsrc2.reghi),PF_S));
+ end;
+ OP_SUB:
+ begin
+ list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_SUB,regdst.reglo,regsrc2.reglo,regsrc1.reglo),PF_S));
+ list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_SBC,regdst.reghi,regsrc2.reghi,regsrc1.reghi),PF_S));
+ end;
+ else
+ internalerror(2003083101);
+ end;
+ if size=OS_64 then
+ begin
+ { the arm has an weired opinion how flags for SUB/ADD are handled }
+ ovloc.loc:=LOC_FLAGS;
+ case op of
+ OP_ADD:
+ ovloc.resflags:=F_CS;
+ OP_SUB:
+ ovloc.resflags:=F_CC;
+ end;
+ end;
+ end
+ else
+ begin
+ case op of
+ OP_AND,OP_OR,OP_XOR:
+ begin
+ cg.a_op_reg_reg_reg(list,op,OS_32,regsrc1.reglo,regsrc2.reglo,regdst.reglo);
+ cg.a_op_reg_reg_reg(list,op,OS_32,regsrc1.reghi,regsrc2.reghi,regdst.reghi);
+ end;
+ OP_ADD:
+ begin
+ list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_ADD,regdst.reglo,regsrc1.reglo,regsrc2.reglo),PF_S));
+ list.concat(taicpu.op_reg_reg_reg(A_ADC,regdst.reghi,regsrc1.reghi,regsrc2.reghi));
+ end;
+ OP_SUB:
+ begin
+ list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_SUB,regdst.reglo,regsrc2.reglo,regsrc1.reglo),PF_S));
+ list.concat(taicpu.op_reg_reg_reg(A_SBC,regdst.reghi,regsrc2.reghi,regsrc1.reghi));
+ end;
+ else
+ internalerror(2003083101);
+ end;
+ end;
+ end;
+
+
+ procedure Tthumb2cgarm.init_register_allocators;
+ begin
+ inherited init_register_allocators;
+ { currently, we save R14 always, so we can use it }
+ if (target_info.system<>system_arm_darwin) then
+ rg[R_INTREGISTER]:=trgintcputhumb2.create(R_INTREGISTER,R_SUBWHOLE,
+ [RS_R0,RS_R1,RS_R2,RS_R3,RS_R4,RS_R5,RS_R6,RS_R7,RS_R8,
+ RS_R9,RS_R10,RS_R12,RS_R14],first_int_imreg,[])
+ else
+ { r9 is not available on Darwin according to the llvm code generator }
+ rg[R_INTREGISTER]:=trgintcputhumb2.create(R_INTREGISTER,R_SUBWHOLE,
+ [RS_R0,RS_R1,RS_R2,RS_R3,RS_R4,RS_R5,RS_R6,RS_R7,RS_R8,
+ RS_R10,RS_R12,RS_R14],first_int_imreg,[]);
+ rg[R_FPUREGISTER]:=trgcputhumb2.create(R_FPUREGISTER,R_SUBNONE,
+ [RS_F0,RS_F1,RS_F2,RS_F3,RS_F4,RS_F5,RS_F6,RS_F7],first_fpu_imreg,[]);
+ rg[R_MMREGISTER]:=trgcputhumb2.create(R_MMREGISTER,R_SUBNONE,
+ [RS_S0,RS_S1,RS_R2,RS_R3,RS_R4,RS_S31],first_mm_imreg,[]);
+ end;
+
+
+ procedure Tthumb2cgarm.done_register_allocators;
+ begin
+ rg[R_INTREGISTER].free;
+ rg[R_FPUREGISTER].free;
+ rg[R_MMREGISTER].free;
+ inherited done_register_allocators;
+ end;
+
+
+ procedure Tthumb2cgarm.a_call_reg(list : TAsmList;reg: tregister);
+ begin
+ list.concat(taicpu.op_reg(A_BLX, reg));
+{
+ the compiler does not properly set this flag anymore in pass 1, and
+ for now we only need it after pass 2 (I hope) (JM)
+ if not(pi_do_call in current_procinfo.flags) then
+ internalerror(2003060703);
+}
+ include(current_procinfo.flags,pi_do_call);
+ end;
+
+
+ procedure Tthumb2cgarm.a_load_const_reg(list : TAsmList; size: tcgsize; a : tcgint;reg : tregister);
+ var
+ imm_shift : byte;
+ l : tasmlabel;
+ hr : treference;
+ begin
+ if not(size in [OS_8,OS_S8,OS_16,OS_S16,OS_32,OS_S32]) then
+ internalerror(2002090902);
+ if is_shifter_const(a,imm_shift) then
+ list.concat(taicpu.op_reg_const(A_MOV,reg,a))
+ { loading of constants with mov and orr }
+ else if (is_shifter_const(a-byte(a),imm_shift)) then
+ begin
+ list.concat(taicpu.op_reg_const(A_MOV,reg,a-byte(a)));
+ list.concat(taicpu.op_reg_reg_const(A_ORR,reg,reg,byte(a)));
+ end
+ else if (is_shifter_const(a-word(a),imm_shift)) and (is_shifter_const(word(a),imm_shift)) then
+ begin
+ list.concat(taicpu.op_reg_const(A_MOV,reg,a-word(a)));
+ list.concat(taicpu.op_reg_reg_const(A_ORR,reg,reg,word(a)));
+ end
+ else if (is_shifter_const(a-(dword(a) shl 8) shr 8,imm_shift)) and (is_shifter_const((dword(a) shl 8) shr 8,imm_shift)) then
+ begin
+ list.concat(taicpu.op_reg_const(A_MOV,reg,a-(dword(a) shl 8) shr 8));
+ list.concat(taicpu.op_reg_reg_const(A_ORR,reg,reg,(dword(a) shl 8) shr 8));
+ end
+ else
+ begin
+ reference_reset(hr,4);
+
+ current_asmdata.getjumplabel(l);
+ cg.a_label(current_procinfo.aktlocaldata,l);
+ hr.symboldata:=current_procinfo.aktlocaldata.last;
+ current_procinfo.aktlocaldata.concat(tai_const.Create_32bit(longint(a)));
+
+ hr.symbol:=l;
+ list.concat(taicpu.op_reg_ref(A_LDR,reg,hr));
+ end;
+ end;
+
+
+ procedure Tthumb2cgarm.a_load_ref_reg(list : TAsmList; fromsize, tosize : tcgsize;const Ref : treference;reg : tregister);
+ var
+ oppostfix:toppostfix;
+ usedtmpref: treference;
+ tmpreg,tmpreg2 : tregister;
+ so : tshifterop;
+ dir : integer;
+ begin
+ if (TCGSize2Size[FromSize] >= TCGSize2Size[ToSize]) then
+ FromSize := ToSize;
+ case FromSize of
+ { signed integer registers }
+ OS_8:
+ oppostfix:=PF_B;
+ OS_S8:
+ oppostfix:=PF_SB;
+ OS_16:
+ oppostfix:=PF_H;
+ OS_S16:
+ oppostfix:=PF_SH;
+ OS_32,
+ OS_S32:
+ oppostfix:=PF_None;
+ else
+ InternalError(200308297);
+ end;
+ if (ref.alignment in [1,2]) and (ref.alignment<tcgsize2size[fromsize]) then
+ begin
+ if target_info.endian=endian_big then
+ dir:=-1
+ else
+ dir:=1;
+ case FromSize of
+ OS_16,OS_S16:
+ begin
+ { only complicated references need an extra loadaddr }
+ if assigned(ref.symbol) or
+ (ref.index<>NR_NO) or
+ (ref.offset<-255) or
+ (ref.offset>4094) or
+ { sometimes the compiler reused registers }
+ (reg=ref.index) or
+ (reg=ref.base) then
+ begin
+ tmpreg2:=getintregister(list,OS_INT);
+ a_loadaddr_ref_reg(list,ref,tmpreg2);
+ reference_reset_base(usedtmpref,tmpreg2,0,ref.alignment);
+ end
+ else
+ usedtmpref:=ref;
+
+ if target_info.endian=endian_big then
+ inc(usedtmpref.offset,1);
+ shifterop_reset(so);so.shiftmode:=SM_LSL;so.shiftimm:=8;
+ tmpreg:=getintregister(list,OS_INT);
+ a_internal_load_ref_reg(list,OS_8,OS_8,usedtmpref,reg);
+ inc(usedtmpref.offset,dir);
+ if FromSize=OS_16 then
+ a_internal_load_ref_reg(list,OS_8,OS_8,usedtmpref,tmpreg)
+ else
+ a_internal_load_ref_reg(list,OS_S8,OS_S8,usedtmpref,tmpreg);
+ list.concat(taicpu.op_reg_reg_reg_shifterop(A_ORR,reg,reg,tmpreg,so));
+ end;
+ OS_32,OS_S32:
+ begin
+ tmpreg:=getintregister(list,OS_INT);
+
+ { only complicated references need an extra loadaddr }
+ if assigned(ref.symbol) or
+ (ref.index<>NR_NO) or
+ (ref.offset<-255) or
+ (ref.offset>4092) or
+ { sometimes the compiler reused registers }
+ (reg=ref.index) or
+ (reg=ref.base) then
+ begin
+ tmpreg2:=getintregister(list,OS_INT);
+ a_loadaddr_ref_reg(list,ref,tmpreg2);
+ reference_reset_base(usedtmpref,tmpreg2,0,ref.alignment);
+ end
+ else
+ usedtmpref:=ref;
+
+ shifterop_reset(so);so.shiftmode:=SM_LSL;
+ if ref.alignment=2 then
+ begin
+ if target_info.endian=endian_big then
+ inc(usedtmpref.offset,2);
+ a_internal_load_ref_reg(list,OS_16,OS_16,usedtmpref,reg);
+ inc(usedtmpref.offset,dir*2);
+ a_internal_load_ref_reg(list,OS_16,OS_16,usedtmpref,tmpreg);
+ so.shiftimm:=16;
+ list.concat(taicpu.op_reg_reg_reg_shifterop(A_ORR,reg,reg,tmpreg,so));
+ end
+ else
+ begin
+ if target_info.endian=endian_big then
+ inc(usedtmpref.offset,3);
+ a_internal_load_ref_reg(list,OS_8,OS_8,usedtmpref,reg);
+ inc(usedtmpref.offset,dir);
+ a_internal_load_ref_reg(list,OS_8,OS_8,usedtmpref,tmpreg);
+ so.shiftimm:=8;
+ list.concat(taicpu.op_reg_reg_reg_shifterop(A_ORR,reg,reg,tmpreg,so));
+ inc(usedtmpref.offset,dir);
+ a_internal_load_ref_reg(list,OS_8,OS_8,usedtmpref,tmpreg);
+ so.shiftimm:=16;
+ list.concat(taicpu.op_reg_reg_reg_shifterop(A_ORR,reg,reg,tmpreg,so));
+ inc(usedtmpref.offset,dir);
+ a_internal_load_ref_reg(list,OS_8,OS_8,usedtmpref,tmpreg);
+ so.shiftimm:=24;
+ list.concat(taicpu.op_reg_reg_reg_shifterop(A_ORR,reg,reg,tmpreg,so));
+ end;
+ end
+ else
+ handle_load_store(list,A_LDR,oppostfix,reg,ref);
+ end;
+ end
+ else
+ handle_load_store(list,A_LDR,oppostfix,reg,ref);
+
+ if (fromsize=OS_S8) and (tosize = OS_16) then
+ a_load_reg_reg(list,OS_16,OS_32,reg,reg);
+ end;
+
+
+ procedure Tthumb2cgarm.a_op_const_reg_reg_checkoverflow(list: TAsmList; op: TOpCg; size: tcgsize; a: tcgint; src, dst: tregister;setflags : boolean;var ovloc : tlocation);
+ var
+ shift : byte;
+ tmpreg : tregister;
+ so : tshifterop;
+ l1 : longint;
+ begin
+ ovloc.loc:=LOC_VOID;
+ if {$ifopt R+}(a<>-2147483648) and{$endif} is_shifter_const(-a,shift) then
+ case op of
+ OP_ADD:
+ begin
+ op:=OP_SUB;
+ a:=aint(dword(-a));
+ end;
+ OP_SUB:
+ begin
+ op:=OP_ADD;
+ a:=aint(dword(-a));
+ end
+ end;
+
+ if is_shifter_const(a,shift) and not(op in [OP_IMUL,OP_MUL]) then
+ case op of
+ OP_NEG,OP_NOT,
+ OP_DIV,OP_IDIV:
+ internalerror(200308281);
+ OP_SHL:
+ begin
+ if a>32 then
+ internalerror(200308294);
+ if a<>0 then
+ begin
+ shifterop_reset(so);
+ so.shiftmode:=SM_LSL;
+ so.shiftimm:=a;
+ list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src,so));
+ end
+ else
+ list.concat(taicpu.op_reg_reg(A_MOV,dst,src));
+ end;
+ OP_ROL:
+ begin
+ if a>32 then
+ internalerror(200308294);
+ if a<>0 then
+ begin
+ shifterop_reset(so);
+ so.shiftmode:=SM_ROR;
+ so.shiftimm:=32-a;
+ list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src,so));
+ end
+ else
+ list.concat(taicpu.op_reg_reg(A_MOV,dst,src));
+ end;
+ OP_ROR:
+ begin
+ if a>32 then
+ internalerror(200308294);
+ if a<>0 then
+ begin
+ shifterop_reset(so);
+ so.shiftmode:=SM_ROR;
+ so.shiftimm:=a;
+ list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src,so));
+ end
+ else
+ list.concat(taicpu.op_reg_reg(A_MOV,dst,src));
+ end;
+ OP_SHR:
+ begin
+ if a>32 then
+ internalerror(200308292);
+ shifterop_reset(so);
+ if a<>0 then
+ begin
+ so.shiftmode:=SM_LSR;
+ so.shiftimm:=a;
+ list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src,so));
+ end
+ else
+ list.concat(taicpu.op_reg_reg(A_MOV,dst,src));
+ end;
+ OP_SAR:
+ begin
+ if a>32 then
+ internalerror(200308295);
+ if a<>0 then
+ begin
+ shifterop_reset(so);
+ so.shiftmode:=SM_ASR;
+ so.shiftimm:=a;
+ list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src,so));
+ end
+ else
+ list.concat(taicpu.op_reg_reg(A_MOV,dst,src));
+ end;
+ else
+ if (op in [OP_SUB, OP_ADD]) and
+ ((a < 0) or
+ (a > 4095)) then
+ begin
+ tmpreg:=getintregister(list,size);
+ a_load_const_reg(list, size, a, tmpreg);
+ list.concat(setoppostfix(taicpu.op_reg_reg_reg(op_reg_reg_opcg2asmop[op],dst,src,tmpreg),toppostfix(ord(cgsetflags or setflags)*ord(PF_S))
+ ));
+ end
+ else
+ list.concat(setoppostfix(
+ taicpu.op_reg_reg_const(op_reg_reg_opcg2asmop[op],dst,src,a),toppostfix(ord(cgsetflags or setflags)*ord(PF_S))
+ ));
+ if (cgsetflags or setflags) and (size in [OS_8,OS_16,OS_32]) then
+ begin
+ ovloc.loc:=LOC_FLAGS;
+ case op of
+ OP_ADD:
+ ovloc.resflags:=F_CS;
+ OP_SUB:
+ ovloc.resflags:=F_CC;
+ end;
+ end;
+ end
+ else
+ begin
+ { there could be added some more sophisticated optimizations }
+ if (op in [OP_MUL,OP_IMUL]) and (a=1) then
+ a_load_reg_reg(list,size,size,src,dst)
+ else if (op in [OP_MUL,OP_IMUL]) and (a=0) then
+ a_load_const_reg(list,size,0,dst)
+ else if (op in [OP_IMUL]) and (a=-1) then
+ a_op_reg_reg(list,OP_NEG,size,src,dst)
+ { we do this here instead in the peephole optimizer because
+ it saves us a register }
+ else if (op in [OP_MUL,OP_IMUL]) and ispowerof2(a,l1) and not(cgsetflags or setflags) then
+ a_op_const_reg_reg(list,OP_SHL,size,l1,src,dst)
+ { for example : b=a*5 -> b=a*4+a with add instruction and shl }
+ else if (op in [OP_MUL,OP_IMUL]) and ispowerof2(a-1,l1) and not(cgsetflags or setflags) then
+ begin
+ if l1>32 then{roozbeh does this ever happen?}
+ internalerror(200308296);
+ shifterop_reset(so);
+ so.shiftmode:=SM_LSL;
+ so.shiftimm:=l1;
+ list.concat(taicpu.op_reg_reg_reg_shifterop(A_ADD,dst,src,src,so));
+ end
+ else
+ begin
+ tmpreg:=getintregister(list,size);
+ a_load_const_reg(list,size,a,tmpreg);
+ a_op_reg_reg_reg_checkoverflow(list,op,size,tmpreg,src,dst,setflags,ovloc);
+ end;
+ end;
+ maybeadjustresult(list,op,size,dst);
+ end;
+
+
+ const
+ op_reg_reg_opcg2asmopThumb2: array[TOpCG] of tasmop =
+ (A_NONE,A_MOV,A_ADD,A_AND,A_UDIV,A_SDIV,A_MUL,A_MUL,A_NONE,A_MVN,A_ORR,
+ A_ASR,A_LSL,A_LSR,A_SUB,A_EOR,A_NONE,A_ROR);
+
+
+ procedure Tthumb2cgarm.a_op_reg_reg_reg_checkoverflow(list: TAsmList; op: TOpCg; size: tcgsize; src1, src2, dst: tregister;setflags : boolean;var ovloc : tlocation);
+ var
+ so : tshifterop;
+ tmpreg,overflowreg : tregister;
+ asmop : tasmop;
+ begin
+ ovloc.loc:=LOC_VOID;
+ case op of
+ OP_NEG,OP_NOT:
+ internalerror(200308281);
+ OP_ROL:
+ begin
+ if not(size in [OS_32,OS_S32]) then
+ internalerror(2008072801);
+ { simulate ROL by ror'ing 32-value }
+ tmpreg:=getintregister(list,OS_32);
+ list.concat(taicpu.op_reg_const(A_MOV,tmpreg,32));
+ list.concat(taicpu.op_reg_reg_reg(A_SUB,src1,tmpreg,src1));
+ list.concat(taicpu.op_reg_reg_reg(A_ROR, dst, src2, src1));
+ end;
+ OP_ROR:
+ begin
+ if not(size in [OS_32,OS_S32]) then
+ internalerror(2008072802);
+ list.concat(taicpu.op_reg_reg_reg(A_ROR, dst, src2, src1));
+ end;
+ OP_IMUL,
+ OP_MUL:
+ begin
+ if cgsetflags or setflags then
+ begin
+ overflowreg:=getintregister(list,size);
+ if op=OP_IMUL then
+ asmop:=A_SMULL
+ else
+ asmop:=A_UMULL;
+ { the arm doesn't allow that rd and rm are the same }
+ if dst=src2 then
+ begin
+ if dst<>src1 then
+ list.concat(taicpu.op_reg_reg_reg_reg(asmop,dst,overflowreg,src1,src2))
+ else
+ begin
+ tmpreg:=getintregister(list,size);
+ a_load_reg_reg(list,size,size,src2,dst);
+ list.concat(taicpu.op_reg_reg_reg_reg(asmop,dst,overflowreg,tmpreg,src1));
+ end;
+ end
+ else
+ list.concat(taicpu.op_reg_reg_reg_reg(asmop,dst,overflowreg,src2,src1));
+ if op=OP_IMUL then
+ begin
+ shifterop_reset(so);
+ so.shiftmode:=SM_ASR;
+ so.shiftimm:=31;
+ list.concat(taicpu.op_reg_reg_shifterop(A_CMP,overflowreg,dst,so));
+ end
+ else
+ list.concat(taicpu.op_reg_const(A_CMP,overflowreg,0));
+
+ ovloc.loc:=LOC_FLAGS;
+ ovloc.resflags:=F_NE;
+ end
+ else
+ begin
+ { the arm doesn't allow that rd and rm are the same }
+ if dst=src2 then
+ begin
+ if dst<>src1 then
+ list.concat(taicpu.op_reg_reg_reg(A_MUL,dst,src1,src2))
+ else
+ begin
+ tmpreg:=getintregister(list,size);
+ a_load_reg_reg(list,size,size,src2,dst);
+ list.concat(taicpu.op_reg_reg_reg(A_MUL,dst,tmpreg,src1));
+ end;
+ end
+ else
+ list.concat(taicpu.op_reg_reg_reg(A_MUL,dst,src2,src1));
+ end;
+ end;
+ else
+ list.concat(setoppostfix(
+ taicpu.op_reg_reg_reg(op_reg_reg_opcg2asmopThumb2[op],dst,src2,src1),toppostfix(ord(cgsetflags or setflags)*ord(PF_S))
+ ));
+ end;
+ maybeadjustresult(list,op,size,dst);
+ end;
+
+
+ procedure Tthumb2cgarm.g_flags2reg(list: TAsmList; size: TCgSize; const f: TResFlags; reg: TRegister);
+ var item: taicpu;
+ begin
+ item := setcondition(taicpu.op_reg_const(A_MOV,reg,1),flags_to_cond(f));
+ list.concat(item);
+ list.insertbefore(taicpu.op_cond(A_IT, flags_to_cond(f)), item);
+
+ item := setcondition(taicpu.op_reg_const(A_MOV,reg,0),inverse_cond(flags_to_cond(f)));
+ list.concat(item);
+ list.insertbefore(taicpu.op_cond(A_IT, inverse_cond(flags_to_cond(f))), item);
+ end;
+
+
+ procedure Tthumb2cgarm.g_proc_entry(list : TAsmList;localsize : longint;nostackframe:boolean);
+ var
+ ref : treference;
+ shift : byte;
+ firstfloatreg,lastfloatreg,
+ r : byte;
+ regs : tcpuregisterset;
+ stackmisalignment: pint;
+ begin
+ LocalSize:=align(LocalSize,4);
+ { call instruction does not put anything on the stack }
+ stackmisalignment:=0;
+ if not(nostackframe) then
+ begin
+ firstfloatreg:=RS_NO;
+ { save floating point registers? }
+ for r:=RS_F0 to RS_F7 do
+ if r in rg[R_FPUREGISTER].used_in_proc-paramanager.get_volatile_registers_fpu(pocall_stdcall) then
+ begin
+ if firstfloatreg=RS_NO then
+ firstfloatreg:=r;
+ lastfloatreg:=r;
+ inc(stackmisalignment,12);
+ end;
+
+ a_reg_alloc(list,NR_STACK_POINTER_REG);
+ if current_procinfo.framepointer<>NR_STACK_POINTER_REG then
+ begin
+ a_reg_alloc(list,NR_FRAME_POINTER_REG);
+ a_reg_alloc(list,NR_R12);
+
+ list.concat(taicpu.op_reg_reg(A_MOV,NR_R12,NR_STACK_POINTER_REG));
+ end;
+ { save int registers }
+ reference_reset(ref,4);
+ ref.index:=NR_STACK_POINTER_REG;
+ ref.addressmode:=AM_PREINDEXED;
+
+ regs:=rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall);
+
+ if current_procinfo.framepointer<>NR_STACK_POINTER_REG then
+ regs:=regs+[RS_FRAME_POINTER_REG,RS_R14]
+ else if (regs<>[]) or (pi_do_call in current_procinfo.flags) then
+ include(regs,RS_R14);
+
+ if regs<>[] then
+ begin
+ for r:=RS_R0 to RS_R15 do
+ if (r in regs) then
+ inc(stackmisalignment,4);
+ list.concat(setoppostfix(taicpu.op_ref_regset(A_STM,ref,R_INTREGISTER,R_SUBWHOLE,regs),PF_FD));
+ end;
+
+ if current_procinfo.framepointer<>NR_STACK_POINTER_REG then
+ begin
+ { the framepointer now points to the saved R15, so the saved
+ framepointer is at R11-12 (for get_caller_frame) }
+ list.concat(taicpu.op_reg_reg_const(A_SUB,NR_FRAME_POINTER_REG,NR_R12,4));
+ a_reg_dealloc(list,NR_R12);
+ end;
+
+ stackmisalignment:=stackmisalignment mod current_settings.alignment.localalignmax;
+ if (LocalSize<>0) or
+ ((stackmisalignment<>0) and
+ ((pi_do_call in current_procinfo.flags) or
+ (po_assembler in current_procinfo.procdef.procoptions))) then
+ begin
+ localsize:=align(localsize+stackmisalignment,current_settings.alignment.localalignmax)-stackmisalignment;
+ if not(is_shifter_const(localsize,shift)) then
+ begin
+ if current_procinfo.framepointer=NR_STACK_POINTER_REG then
+ a_reg_alloc(list,NR_R12);
+ a_load_const_reg(list,OS_ADDR,LocalSize,NR_R12);
+ list.concat(taicpu.op_reg_reg_reg(A_SUB,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,NR_R12));
+ a_reg_dealloc(list,NR_R12);
+ end
+ else
+ begin
+ a_reg_dealloc(list,NR_R12);
+ list.concat(taicpu.op_reg_reg_const(A_SUB,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,LocalSize));
+ end;
+ end;
+
+ if firstfloatreg<>RS_NO then
+ begin
+ reference_reset(ref,4);
+ if tg.direction*tarmprocinfo(current_procinfo).floatregstart>=1023 then
+ begin
+ a_load_const_reg(list,OS_ADDR,-tarmprocinfo(current_procinfo).floatregstart,NR_R12);
+ list.concat(taicpu.op_reg_reg_reg(A_SUB,NR_R12,current_procinfo.framepointer,NR_R12));
+ ref.base:=NR_R12;
+ end
+ else
+ begin
+ ref.base:=current_procinfo.framepointer;
+ ref.offset:=tarmprocinfo(current_procinfo).floatregstart;
+ end;
+ list.concat(taicpu.op_reg_const_ref(A_SFM,newreg(R_FPUREGISTER,firstfloatreg,R_SUBWHOLE),
+ lastfloatreg-firstfloatreg+1,ref));
+ end;
+ end;
+ end;
+
+
+ procedure Tthumb2cgarm.g_proc_exit(list : TAsmList;parasize : longint;nostackframe:boolean);
+ var
+ ref : treference;
+ firstfloatreg,lastfloatreg,
+ r : byte;
+ shift : byte;
+ regs : tcpuregisterset;
+ LocalSize : longint;
+ stackmisalignment: pint;
+ begin
+ if not(nostackframe) then
+ begin
+ stackmisalignment:=0;
+ { restore floating point register }
+ firstfloatreg:=RS_NO;
+ { save floating point registers? }
+ for r:=RS_F0 to RS_F7 do
+ if r in rg[R_FPUREGISTER].used_in_proc-paramanager.get_volatile_registers_fpu(pocall_stdcall) then
+ begin
+ if firstfloatreg=RS_NO then
+ firstfloatreg:=r;
+ lastfloatreg:=r;
+ { floating point register space is already included in
+ localsize below by calc_stackframe_size
+ inc(stackmisalignment,12);
+ }
+ end;
+
+ if firstfloatreg<>RS_NO then
+ begin
+ reference_reset(ref,4);
+ if tg.direction*tarmprocinfo(current_procinfo).floatregstart>=1023 then
+ begin
+ a_load_const_reg(list,OS_ADDR,-tarmprocinfo(current_procinfo).floatregstart,NR_R12);
+ list.concat(taicpu.op_reg_reg_reg(A_SUB,NR_R12,current_procinfo.framepointer,NR_R12));
+ ref.base:=NR_R12;
+ end
+ else
+ begin
+ ref.base:=current_procinfo.framepointer;
+ ref.offset:=tarmprocinfo(current_procinfo).floatregstart;
+ end;
+ list.concat(taicpu.op_reg_const_ref(A_LFM,newreg(R_FPUREGISTER,firstfloatreg,R_SUBWHOLE),
+ lastfloatreg-firstfloatreg+1,ref));
+ end;
+
+ regs:=rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall);
+ if (pi_do_call in current_procinfo.flags) or (regs<>[]) then
+ begin
+ exclude(regs,RS_R14);
+ include(regs,RS_R15);
+ end;
+ if (current_procinfo.framepointer<>NR_STACK_POINTER_REG) then
+ regs:=regs+[RS_FRAME_POINTER_REG,RS_R15];
+
+ for r:=RS_R0 to RS_R15 do
+ if (r in regs) then
+ inc(stackmisalignment,4);
+
+ stackmisalignment:=stackmisalignment mod current_settings.alignment.localalignmax;
+ if (current_procinfo.framepointer=NR_STACK_POINTER_REG) then
+ begin
+ LocalSize:=current_procinfo.calc_stackframe_size;
+ if (LocalSize<>0) or
+ ((stackmisalignment<>0) and
+ ((pi_do_call in current_procinfo.flags) or
+ (po_assembler in current_procinfo.procdef.procoptions))) then
+ begin
+ localsize:=align(localsize+stackmisalignment,current_settings.alignment.localalignmax)-stackmisalignment;
+ if not(is_shifter_const(LocalSize,shift)) then
+ begin
+ a_reg_alloc(list,NR_R12);
+ a_load_const_reg(list,OS_ADDR,LocalSize,NR_R12);
+ list.concat(taicpu.op_reg_reg_reg(A_ADD,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,NR_R12));
+ a_reg_dealloc(list,NR_R12);
+ end
+ else
+ begin
+ list.concat(taicpu.op_reg_reg_const(A_ADD,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,LocalSize));
+ end;
+ end;
+
+ if regs=[] then
+ list.concat(taicpu.op_reg_reg(A_MOV,NR_R15,NR_R14))
+ else
+ begin
+ reference_reset(ref,4);
+ ref.index:=NR_STACK_POINTER_REG;
+ ref.addressmode:=AM_PREINDEXED;
+ list.concat(setoppostfix(taicpu.op_ref_regset(A_LDM,ref,R_INTREGISTER,R_SUBWHOLE,regs),PF_FD));
+ end;
+ end
+ else
+ begin
+ { restore int registers and return }
+ list.concat(taicpu.op_reg_reg(A_MOV, NR_STACK_POINTER_REG, NR_FRAME_POINTER_REG));
+ { Add 4 to SP to make it point to an "imaginary PC" which the paramanager assumes is there(for normal ARM) }
+ list.concat(taicpu.op_reg_const(A_ADD, NR_STACK_POINTER_REG, 4));
+
+ reference_reset(ref,4);
+ ref.index:=NR_STACK_POINTER_REG;
+ list.concat(setoppostfix(taicpu.op_ref_regset(A_LDM,ref,R_INTREGISTER,R_SUBWHOLE,regs),PF_DB));
+ end;
+ end
+ else
+ list.concat(taicpu.op_reg_reg(A_MOV,NR_PC,NR_R14));
+ end;
+
+
+ function Tthumb2cgarm.handle_load_store(list:TAsmList;op: tasmop;oppostfix : toppostfix;reg:tregister;ref: treference):treference;
+ var
+ tmpreg : tregister;
+ tmpref : treference;
+ l : tasmlabel;
+ so: tshifterop;
+ begin
+ tmpreg:=NR_NO;
+
+ { Be sure to have a base register }
+ if (ref.base=NR_NO) then
+ begin
+ if ref.shiftmode<>SM_None then
+ internalerror(200308294);
+ ref.base:=ref.index;
+ ref.index:=NR_NO;
+ end;
+
+ { absolute symbols can't be handled directly, we've to store the symbol reference
+ in the text segment and access it pc relative
+
+ For now, we assume that references where base or index equals to PC are already
+ relative, all other references are assumed to be absolute and thus they need
+ to be handled extra.
+
+ A proper solution would be to change refoptions to a set and store the information
+ if the symbol is absolute or relative there.
+ }
+
+ if (assigned(ref.symbol) and
+ not(is_pc(ref.base)) and
+ not(is_pc(ref.index))
+ ) or
+ { [#xxx] isn't a valid address operand }
+ ((ref.base=NR_NO) and (ref.index=NR_NO)) or
+ //(ref.offset<-4095) or
+ (ref.offset<-255) or
+ (ref.offset>4095) or
+ ((oppostfix in [PF_SB,PF_H,PF_SH]) and
+ ((ref.offset<-255) or
+ (ref.offset>255)
+ )
+ ) or
+ ((op in [A_LDF,A_STF,A_FLDS,A_FLDD,A_FSTS,A_FSTD]) and
+ ((ref.offset<-1020) or
+ (ref.offset>1020) or
+ { the usual pc relative symbol handling assumes possible offsets of +/- 4095 }
+ assigned(ref.symbol)
+ )
+ ) then
+ begin
+ reference_reset(tmpref,4);
+
+ { load symbol }
+ tmpreg:=getintregister(list,OS_INT);
+ if assigned(ref.symbol) then
+ begin
+ current_asmdata.getjumplabel(l);
+ cg.a_label(current_procinfo.aktlocaldata,l);
+ tmpref.symboldata:=current_procinfo.aktlocaldata.last;
+
+ current_procinfo.aktlocaldata.concat(tai_const.create_sym_offset(ref.symbol,ref.offset));
+
+ { load consts entry }
+ tmpref.symbol:=l;
+ tmpref.base:=NR_R15;
+ list.concat(taicpu.op_reg_ref(A_LDR,tmpreg,tmpref));
+
+ { in case of LDF/STF, we got rid of the NR_R15 }
+ if is_pc(ref.base) then
+ ref.base:=NR_NO;
+ if is_pc(ref.index) then
+ ref.index:=NR_NO;
+ end
+ else
+ a_load_const_reg(list,OS_ADDR,ref.offset,tmpreg);
+
+ if (ref.base<>NR_NO) then
+ begin
+ if ref.index<>NR_NO then
+ begin
+ list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.base,tmpreg));
+ ref.base:=tmpreg;
+ end
+ else
+ begin
+ ref.index:=tmpreg;
+ ref.shiftimm:=0;
+ ref.signindex:=1;
+ ref.shiftmode:=SM_None;
+ end;
+ end
+ else
+ ref.base:=tmpreg;
+ ref.offset:=0;
+ ref.symbol:=nil;
+ end;
+
+ if (ref.base<>NR_NO) and (ref.index<>NR_NO) and (ref.offset<>0) then
+ begin
+ if tmpreg<>NR_NO then
+ a_op_const_reg_reg(list,OP_ADD,OS_ADDR,ref.offset,tmpreg,tmpreg)
+ else
+ begin
+ tmpreg:=getintregister(list,OS_ADDR);
+ a_op_const_reg_reg(list,OP_ADD,OS_ADDR,ref.offset,ref.base,tmpreg);
+ ref.base:=tmpreg;
+ end;
+ ref.offset:=0;
+ end;
+
+ { Hack? Thumb2 doesn't allow PC indexed addressing modes(although it does in the specification) }
+ if (ref.base=NR_R15) and (ref.index<>NR_NO) and (ref.shiftmode <> sm_none) then
+ begin
+ tmpreg:=getintregister(list,OS_ADDR);
+
+ list.concat(taicpu.op_reg_reg(A_MOV, tmpreg, NR_R15));
+
+ ref.base := tmpreg;
+ end;
+
+ { floating point operations have only limited references
+ we expect here, that a base is already set }
+ if (op in [A_LDF,A_STF,A_FLDS,A_FLDD,A_FSTS,A_FSTD]) and (ref.index<>NR_NO) then
+ begin
+ if ref.shiftmode<>SM_none then
+ internalerror(200309121);
+ if tmpreg<>NR_NO then
+ begin
+ if ref.base=tmpreg then
+ begin
+ if ref.signindex<0 then
+ list.concat(taicpu.op_reg_reg_reg(A_SUB,tmpreg,tmpreg,ref.index))
+ else
+ list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,tmpreg,ref.index));
+ ref.index:=NR_NO;
+ end
+ else
+ begin
+ if ref.index<>tmpreg then
+ internalerror(200403161);
+ if ref.signindex<0 then
+ list.concat(taicpu.op_reg_reg_reg(A_SUB,tmpreg,ref.base,tmpreg))
+ else
+ list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.base,tmpreg));
+ ref.base:=tmpreg;
+ ref.index:=NR_NO;
+ end;
+ end
+ else
+ begin
+ tmpreg:=getintregister(list,OS_ADDR);
+ list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.base,ref.index));
+ ref.base:=tmpreg;
+ ref.index:=NR_NO;
+ end;
+ end;
+ list.concat(setoppostfix(taicpu.op_reg_ref(op,reg,ref),oppostfix));
+ Result := ref;
+ end;
+
+
+ procedure tthumb2cg64farm.a_op64_reg_reg(list : TAsmList;op:TOpCG;size : tcgsize;regsrc,regdst : tregister64);
+ var tmpreg: tregister;
+ begin
+ case op of
+ OP_NEG:
+ begin
+ list.concat(setoppostfix(taicpu.op_reg_reg_const(A_RSB,regdst.reglo,regsrc.reglo,0),PF_S));
+ tmpreg:=cg.getintregister(list,OS_32);
+ list.concat(taicpu.op_reg_const(A_MOV,tmpreg,0));
+ list.concat(taicpu.op_reg_reg_reg(A_SBC,regdst.reghi,tmpreg,regsrc.reghi));
+ end;
+ else
+ inherited a_op64_reg_reg(list, op, size, regsrc, regdst);
+ end;
+ end;
+
+
+ procedure create_codegen;
+ begin
+ if current_settings.cputype in cpu_thumb2 then
+ begin
+ cg:=tthumb2cgarm.create;
+ cg64:=tthumb2cg64farm.create;
+
+ casmoptimizer:=TCpuThumb2AsmOptimizer;
+ end
+ else
+ begin
+ cg:=tarmcgarm.create;
+ cg64:=tcg64farm.create;
+
+ casmoptimizer:=TCpuAsmOptimizer;
+ end;
+ end;
+
+end.
diff --git a/closures/compiler/arm/cpubase.pas b/closures/compiler/arm/cpubase.pas
new file mode 100644
index 0000000000..351ea20789
--- /dev/null
+++ b/closures/compiler/arm/cpubase.pas
@@ -0,0 +1,581 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl and Peter Vreman
+
+ Contains the base types for the ARM
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+{# Base unit for processor information. This unit contains
+ enumerations of registers, opcodes, sizes, and other
+ such things which are processor specific.
+}
+unit cpubase;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ cutils,cclasses,
+ globtype,globals,
+ cpuinfo,
+ aasmbase,
+ cgbase
+ ;
+
+
+{*****************************************************************************
+ Assembler Opcodes
+*****************************************************************************}
+
+ type
+ TAsmOp= {$i armop.inc}
+
+ { This should define the array of instructions as string }
+ op2strtable=array[tasmop] of string[11];
+
+ const
+ { First value of opcode enumeration }
+ firstop = low(tasmop);
+ { Last value of opcode enumeration }
+ lastop = high(tasmop);
+
+{*****************************************************************************
+ Registers
+*****************************************************************************}
+
+ type
+ { Number of registers used for indexing in tables }
+ tregisterindex=0..{$i rarmnor.inc}-1;
+
+ const
+ { Available Superregisters }
+ {$i rarmsup.inc}
+
+ RS_PC = RS_R15;
+
+ { No Subregisters }
+ R_SUBWHOLE = R_SUBNONE;
+
+ { Available Registers }
+ {$i rarmcon.inc}
+
+ { aliases }
+ NR_PC = NR_R15;
+
+ { Integer Super registers first and last }
+ first_int_supreg = RS_R0;
+ first_int_imreg = $10;
+
+ { Float Super register first and last }
+ first_fpu_supreg = RS_F0;
+ first_fpu_imreg = $08;
+
+ { MM Super register first and last }
+ first_mm_supreg = RS_S0;
+ first_mm_imreg = $20;
+
+{ TODO: Calculate bsstart}
+ regnumber_count_bsstart = 64;
+
+ regnumber_table : array[tregisterindex] of tregister = (
+ {$i rarmnum.inc}
+ );
+
+ regstabs_table : array[tregisterindex] of shortint = (
+ {$i rarmsta.inc}
+ );
+
+ regdwarf_table : array[tregisterindex] of shortint = (
+ {$i rarmdwa.inc}
+ );
+ { registers which may be destroyed by calls }
+ VOLATILE_INTREGISTERS = [RS_R0..RS_R3,RS_R12..RS_R14];
+ VOLATILE_FPUREGISTERS = [RS_F0..RS_F3];
+ VOLATILE_MMREGISTERS = [RS_D0..RS_D7,RS_D16..RS_D31];
+
+ VOLATILE_INTREGISTERS_DARWIN = [RS_R0..RS_R3,RS_R9,RS_R12..RS_R14];
+
+ type
+ totherregisterset = set of tregisterindex;
+
+{*****************************************************************************
+ Instruction post fixes
+*****************************************************************************}
+ type
+ { ARM instructions load/store and arithmetic instructions
+ can have several instruction post fixes which are collected
+ in this enumeration
+ }
+ TOpPostfix = (PF_None,
+ { update condition flags
+ or floating point single }
+ PF_S,
+ { floating point size }
+ PF_D,PF_E,PF_P,PF_EP,
+ { load/store }
+ PF_B,PF_SB,PF_BT,PF_H,PF_SH,PF_T,
+ { multiple load/store address modes }
+ PF_IA,PF_IB,PF_DA,PF_DB,PF_FD,PF_FA,PF_ED,PF_EA,
+ { multiple load/store vfp address modes }
+ PF_IAD,PF_DBD,PF_FDD,PF_EAD,
+ PF_IAS,PF_DBS,PF_FDS,PF_EAS,
+ PF_IAX,PF_DBX,PF_FDX,PF_EAX
+ );
+
+ TRoundingMode = (RM_None,RM_P,RM_M,RM_Z);
+
+ const
+ cgsize2fpuoppostfix : array[OS_NO..OS_F128] of toppostfix = (
+ PF_None,
+ PF_None,PF_None,PF_None,PF_None,PF_None,PF_None,PF_None,PF_None,PF_None,PF_None,
+ PF_S,PF_D,PF_E,PF_None,PF_None);
+
+ oppostfix2str : array[TOpPostfix] of string[3] = ('',
+ 's',
+ 'd','e','p','ep',
+ 'b','sb','bt','h','sh','t',
+ 'ia','ib','da','db','fd','fa','ed','ea',
+ 'iad','dbd','fdd','ead',
+ 'ias','dbs','fds','eas',
+ 'iax','dbx','fdx','eax');
+
+ roundingmode2str : array[TRoundingMode] of string[1] = ('',
+ 'p','m','z');
+
+{*****************************************************************************
+ Conditions
+*****************************************************************************}
+
+ type
+ TAsmCond=(C_None,
+ C_EQ,C_NE,C_CS,C_CC,C_MI,C_PL,C_VS,C_VC,C_HI,C_LS,
+ C_GE,C_LT,C_GT,C_LE,C_AL,C_NV
+ );
+
+ const
+ cond2str : array[TAsmCond] of string[2]=('',
+ 'eq','ne','cs','cc','mi','pl','vs','vc','hi','ls',
+ 'ge','lt','gt','le','al','nv'
+ );
+
+ uppercond2str : array[TAsmCond] of string[2]=('',
+ 'EQ','NE','CS','CC','MI','PL','VS','VC','HI','LS',
+ 'GE','LT','GT','LE','AL','NV'
+ );
+
+{*****************************************************************************
+ Flags
+*****************************************************************************}
+
+ type
+ TResFlags = (F_EQ,F_NE,F_CS,F_CC,F_MI,F_PL,F_VS,F_VC,F_HI,F_LS,
+ F_GE,F_LT,F_GT,F_LE);
+
+{*****************************************************************************
+ Operands
+*****************************************************************************}
+
+ taddressmode = (AM_OFFSET,AM_PREINDEXED,AM_POSTINDEXED);
+ tshiftmode = (SM_None,SM_LSL,SM_LSR,SM_ASR,SM_ROR,SM_RRX);
+
+ tupdatereg = (UR_None,UR_Update);
+
+ pshifterop = ^tshifterop;
+
+ tshifterop = record
+ shiftmode : tshiftmode;
+ rs : tregister;
+ shiftimm : byte;
+ end;
+
+ tcpumodeflag = (mfA, mfI, mfF);
+ tcpumodeflags = set of tcpumodeflag;
+
+{*****************************************************************************
+ Constants
+*****************************************************************************}
+
+ const
+ max_operands = 4;
+
+ maxintregs = 15;
+ maxfpuregs = 8;
+ maxaddrregs = 0;
+
+{*****************************************************************************
+ Operand Sizes
+*****************************************************************************}
+
+ type
+ topsize = (S_NO,
+ S_B,S_W,S_L,S_BW,S_BL,S_WL,
+ S_IS,S_IL,S_IQ,
+ S_FS,S_FL,S_FX,S_D,S_Q,S_FV,S_FXX
+ );
+
+{*****************************************************************************
+ Constants
+*****************************************************************************}
+
+ const
+ firstsaveintreg = RS_R4;
+ lastsaveintreg = RS_R10;
+ firstsavefpureg = RS_F4;
+ lastsavefpureg = RS_F7;
+ firstsavemmreg = RS_D8;
+ lastsavemmreg = RS_D15;
+
+ maxvarregs = 7;
+ varregs : Array [1..maxvarregs] of tsuperregister =
+ (RS_R4,RS_R5,RS_R6,RS_R7,RS_R8,RS_R9,RS_R10);
+
+ maxfpuvarregs = 4;
+ fpuvarregs : Array [1..maxfpuvarregs] of tsuperregister =
+ (RS_F4,RS_F5,RS_F6,RS_F7);
+
+{*****************************************************************************
+ Default generic sizes
+*****************************************************************************}
+
+ { Defines the default address size for a processor, }
+ OS_ADDR = OS_32;
+ { the natural int size for a processor, }
+ OS_INT = OS_32;
+ OS_SINT = OS_S32;
+ { the maximum float size for a processor, }
+ OS_FLOAT = OS_F64;
+ { the size of a vector register for a processor }
+ OS_VECTOR = OS_M32;
+
+{*****************************************************************************
+ Generic Register names
+*****************************************************************************}
+
+ { Stack pointer register }
+ NR_STACK_POINTER_REG = NR_R13;
+ RS_STACK_POINTER_REG = RS_R13;
+ { Frame pointer register }
+ RS_FRAME_POINTER_REG = RS_R11;
+ NR_FRAME_POINTER_REG = NR_R11;
+ { Register for addressing absolute data in a position independant way,
+ such as in PIC code. The exact meaning is ABI specific. For
+ further information look at GCC source : PIC_OFFSET_TABLE_REGNUM
+ }
+ NR_PIC_OFFSET_REG = NR_R9;
+ { Results are returned in this register (32-bit values) }
+ NR_FUNCTION_RETURN_REG = NR_R0;
+ RS_FUNCTION_RETURN_REG = RS_R0;
+ { The value returned from a function is available in this register }
+ NR_FUNCTION_RESULT_REG = NR_FUNCTION_RETURN_REG;
+ RS_FUNCTION_RESULT_REG = RS_FUNCTION_RETURN_REG;
+
+ NR_FPU_RESULT_REG = NR_F0;
+
+ NR_MM_RESULT_REG = NR_NO;
+
+ NR_RETURN_ADDRESS_REG = NR_FUNCTION_RETURN_REG;
+
+ { Offset where the parent framepointer is pushed }
+ PARENT_FRAMEPOINTER_OFFSET = 0;
+
+ { Low part of 64bit return value }
+ function NR_FUNCTION_RESULT64_LOW_REG: tregister;
+ function RS_FUNCTION_RESULT64_LOW_REG: shortint;
+ { High part of 64bit return value }
+ function NR_FUNCTION_RESULT64_HIGH_REG: tregister;
+ function RS_FUNCTION_RESULT64_HIGH_REG: shortint;
+
+{*****************************************************************************
+ GCC /ABI linking information
+*****************************************************************************}
+
+ const
+ { Registers which must be saved when calling a routine declared as
+ cppdecl, cdecl, stdcall, safecall, palmossyscall. The registers
+ saved should be the ones as defined in the target ABI and / or GCC.
+
+ This value can be deduced from the CALLED_USED_REGISTERS array in the
+ GCC source.
+ }
+ saved_standard_registers : array[0..6] of tsuperregister =
+ (RS_R4,RS_R5,RS_R6,RS_R7,RS_R8,RS_R9,RS_R10);
+
+ { this is only for the generic code which is not used for this architecture }
+ saved_mm_registers : array[0..0] of tsuperregister = (RS_NO);
+
+ { Required parameter alignment when calling a routine declared as
+ stdcall and cdecl. The alignment value should be the one defined
+ by GCC or the target ABI.
+
+ The value of this constant is equal to the constant
+ PARM_BOUNDARY / BITS_PER_UNIT in the GCC source.
+ }
+ std_param_align = 4;
+
+
+{*****************************************************************************
+ Helpers
+*****************************************************************************}
+
+ { Returns the tcgsize corresponding with the size of reg.}
+ function reg_cgsize(const reg: tregister) : tcgsize;
+ function cgsize2subreg(regtype: tregistertype; s:Tcgsize):Tsubregister;
+ function is_calljmp(o:tasmop):boolean;
+ procedure inverse_flags(var f: TResFlags);
+ function flags_to_cond(const f: TResFlags) : TAsmCond;
+ function findreg_by_number(r:Tregister):tregisterindex;
+ function std_regnum_search(const s:string):Tregister;
+ function std_regname(r:Tregister):string;
+
+ function inverse_cond(const c: TAsmCond): TAsmCond; {$ifdef USEINLINE}inline;{$endif USEINLINE}
+ function conditions_equal(const c1, c2: TAsmCond): boolean; {$ifdef USEINLINE}inline;{$endif USEINLINE}
+
+ procedure shifterop_reset(var so : tshifterop);
+ function is_pc(const r : tregister) : boolean;
+
+ function is_shifter_const(d : aint;var imm_shift : byte) : boolean;
+ function dwarf_reg(r:tregister):shortint;
+
+ implementation
+
+ uses
+ systems,rgBase,verbose;
+
+
+ const
+ std_regname_table : array[tregisterindex] of string[7] = (
+ {$i rarmstd.inc}
+ );
+
+ regnumber_index : array[tregisterindex] of tregisterindex = (
+ {$i rarmrni.inc}
+ );
+
+ std_regname_index : array[tregisterindex] of tregisterindex = (
+ {$i rarmsri.inc}
+ );
+
+
+ function cgsize2subreg(regtype: tregistertype; s:Tcgsize):Tsubregister;
+ begin
+ case regtype of
+ R_MMREGISTER:
+ begin
+ case s of
+ OS_F32:
+ cgsize2subreg:=R_SUBFS;
+ OS_F64:
+ cgsize2subreg:=R_SUBFD;
+ else
+ internalerror(2009112701);
+ end;
+ end;
+ else
+ cgsize2subreg:=R_SUBWHOLE;
+ end;
+ end;
+
+
+ function reg_cgsize(const reg: tregister): tcgsize;
+ begin
+ case getregtype(reg) of
+ R_INTREGISTER :
+ reg_cgsize:=OS_32;
+ R_FPUREGISTER :
+ reg_cgsize:=OS_F80;
+ R_MMREGISTER :
+ begin
+ case getsubreg(reg) of
+ R_SUBFD,
+ R_SUBWHOLE:
+ result:=OS_F64;
+ R_SUBFS:
+ result:=OS_F32;
+ else
+ internalerror(2009112903);
+ end;
+ end;
+ else
+ internalerror(200303181);
+ end;
+ end;
+
+
+ function is_calljmp(o:tasmop):boolean;
+ begin
+ { This isn't 100% perfect because the arm allows jumps also by writing to PC=R15.
+ To overcome this problem we simply forbid that FPC generates jumps by loading R15 }
+ is_calljmp:= o in [A_B,A_BL,A_BX,A_BLX];
+ end;
+
+
+ procedure inverse_flags(var f: TResFlags);
+ const
+ inv_flags: array[TResFlags] of TResFlags =
+ (F_NE,F_EQ,F_CC,F_CS,F_PL,F_MI,F_VC,F_VS,F_LS,F_HI,
+ F_LT,F_GE,F_LE,F_GT);
+ begin
+ f:=inv_flags[f];
+ end;
+
+
+ function flags_to_cond(const f: TResFlags) : TAsmCond;
+ const
+ flag_2_cond: array[F_EQ..F_LE] of TAsmCond =
+ (C_EQ,C_NE,C_CS,C_CC,C_MI,C_PL,C_VS,C_VC,C_HI,C_LS,
+ C_GE,C_LT,C_GT,C_LE);
+ begin
+ if f>high(flag_2_cond) then
+ internalerror(200112301);
+ result:=flag_2_cond[f];
+ end;
+
+
+ function findreg_by_number(r:Tregister):tregisterindex;
+ begin
+ result:=rgBase.findreg_by_number_table(r,regnumber_index);
+ end;
+
+
+ function std_regnum_search(const s:string):Tregister;
+ begin
+ result:=regnumber_table[findreg_by_name_table(s,std_regname_table,std_regname_index)];
+ end;
+
+
+ function std_regname(r:Tregister):string;
+ var
+ p : tregisterindex;
+ begin
+ p:=findreg_by_number_table(r,regnumber_index);
+ if p<>0 then
+ result:=std_regname_table[p]
+ else
+ result:=generic_regname(r);
+ end;
+
+
+ procedure shifterop_reset(var so : tshifterop);
+ begin
+ FillChar(so,sizeof(so),0);
+ end;
+
+
+ function is_pc(const r : tregister) : boolean;
+ begin
+ is_pc:=(r=NR_R15);
+ end;
+
+
+ function inverse_cond(const c: TAsmCond): TAsmCond; {$ifdef USEINLINE}inline;{$endif USEINLINE}
+ const
+ inverse: array[TAsmCond] of TAsmCond=(C_None,
+ C_NE,C_EQ,C_CC,C_CS,C_PL,C_MI,C_VC,C_VS,C_LS,C_HI,
+ C_LT,C_GE,C_LE,C_GT,C_None,C_None
+ );
+ begin
+ result := inverse[c];
+ end;
+
+
+ function conditions_equal(const c1, c2: TAsmCond): boolean; {$ifdef USEINLINE}inline;{$endif USEINLINE}
+ begin
+ result := c1 = c2;
+ end;
+
+
+ function rotl(d : dword;b : byte) : dword;
+ begin
+ result:=(d shr (32-b)) or (d shl b);
+ end;
+
+
+ function is_shifter_const(d : aint;var imm_shift : byte) : boolean;
+ var
+ i : longint;
+ begin
+ if current_settings.cputype in cpu_thumb2 then
+ begin
+ for i:=0 to 24 do
+ begin
+ if (dword(d) and not($ff shl i))=0 then
+ begin
+ imm_shift:=i;
+ result:=true;
+ exit;
+ end;
+ end;
+ end
+ else
+ begin
+ for i:=0 to 15 do
+ begin
+ if (dword(d) and not(rotl($ff,i*2)))=0 then
+ begin
+ imm_shift:=i*2;
+ result:=true;
+ exit;
+ end;
+ end;
+ end;
+ result:=false;
+ end;
+
+
+ function dwarf_reg(r:tregister):shortint;
+ begin
+ result:=regdwarf_table[findreg_by_number(r)];
+ if result=-1 then
+ internalerror(200603251);
+ end;
+
+ { Low part of 64bit return value }
+ function NR_FUNCTION_RESULT64_LOW_REG: tregister;
+ begin
+ if target_info.endian=endian_little then
+ result:=NR_R0
+ else
+ result:=NR_R1;
+ end;
+
+ function RS_FUNCTION_RESULT64_LOW_REG: shortint;
+ begin
+ if target_info.endian=endian_little then
+ result:=RS_R0
+ else
+ result:=RS_R1;
+ end;
+
+ { High part of 64bit return value }
+ function NR_FUNCTION_RESULT64_HIGH_REG: tregister;
+ begin
+ if target_info.endian=endian_little then
+ result:=NR_R1
+ else
+ result:=NR_R0;
+ end;
+
+ function RS_FUNCTION_RESULT64_HIGH_REG: shortint;
+ begin
+ if target_info.endian=endian_little then
+ result:=RS_R1
+ else
+ result:=RS_R0;
+ end;
+
+end.
diff --git a/closures/compiler/arm/cpuinfo.pas b/closures/compiler/arm/cpuinfo.pas
new file mode 100644
index 0000000000..1b2accfa1c
--- /dev/null
+++ b/closures/compiler/arm/cpuinfo.pas
@@ -0,0 +1,1034 @@
+{
+ Copyright (c) 1998-2002 by the Free Pascal development team
+
+ Basic Processor information for the ARM
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+Unit CPUInfo;
+
+Interface
+
+ uses
+ globtype;
+
+Type
+ bestreal = double;
+ ts32real = single;
+ ts64real = double;
+ ts80real = type extended;
+ ts128real = type extended;
+ ts64comp = comp;
+
+ pbestreal=^bestreal;
+
+ { possible supported processors for this target }
+ tcputype =
+ (cpu_none,
+ cpu_armv3,
+ cpu_armv4,
+ cpu_armv4t,
+ cpu_armv5,
+ cpu_armv6,
+ cpu_armv7,
+ cpu_armv7m
+ );
+
+Const
+ cpu_arm = [cpu_none,cpu_armv3,cpu_armv4,cpu_armv4t,cpu_armv5];
+ cpu_thumb = [];
+ cpu_thumb2 = [cpu_armv7m];
+
+Type
+ tfputype =
+ (fpu_none,
+ fpu_soft,
+ fpu_libgcc,
+ fpu_fpa,
+ fpu_fpa10,
+ fpu_fpa11,
+ fpu_vfpv2,
+ fpu_vfpv3
+ );
+
+ tcontrollertype =
+ (ct_none,
+
+ { Phillips }
+ ct_lpc2114,
+ ct_lpc2124,
+ ct_lpc2194,
+ ct_lpc1768,
+
+ { ATMEL }
+ ct_at91sam7s256,
+ ct_at91sam7se256,
+ ct_at91sam7x256,
+ ct_at91sam7xc256,
+
+ { STMicroelectronics }
+ ct_stm32f103rb,
+ ct_stm32f103re,
+ ct_stm32f103c4t,
+
+ { TI - Fury Class - 64 K Flash, 16 K SRAM Devices }
+ ct_lm3s1110,
+ ct_lm3s1133,
+ ct_lm3s1138,
+ ct_lm3s1150,
+ ct_lm3s1162,
+ ct_lm3s1165,
+ ct_lm3s1166,
+ ct_lm3s2110,
+ ct_lm3s2139,
+ ct_lm3s6100,
+ ct_lm3s6110,
+
+ { TI - Fury Class - 128K Flash, 32K SRAM devices }
+ ct_lm3s1601,
+ ct_lm3s1608,
+ ct_lm3s1620,
+ ct_lm3s1635,
+ ct_lm3s1636,
+ ct_lm3s1637,
+ ct_lm3s1651,
+ ct_lm3s2601,
+ ct_lm3s2608,
+ ct_lm3s2620,
+ ct_lm3s2637,
+ ct_lm3s2651,
+ ct_lm3s6610,
+ ct_lm3s6611,
+ ct_lm3s6618,
+ ct_lm3s6633,
+ ct_lm3s6637,
+ ct_lm3s8630,
+
+ { TI - Fury Class - 256K Flash, 64K SRAM devices }
+ ct_lm3s1911,
+ ct_lm3s1918,
+ ct_lm3s1937,
+ ct_lm3s1958,
+ ct_lm3s1960,
+ ct_lm3s1968,
+ ct_lm3s1969,
+ ct_lm3s2911,
+ ct_lm3s2918,
+ ct_lm3s2919,
+ ct_lm3s2939,
+ ct_lm3s2948,
+ ct_lm3s2950,
+ ct_lm3s2965,
+ ct_lm3s6911,
+ ct_lm3s6918,
+ ct_lm3s6938,
+ ct_lm3s6950,
+ ct_lm3s6952,
+ ct_lm3s6965,
+ ct_lm3s8930,
+ ct_lm3s8933,
+ ct_lm3s8938,
+ ct_lm3s8962,
+ ct_lm3s8970,
+ ct_lm3s8971,
+
+ { TI - Tempest Tempest - 256 K Flash, 64 K SRAM }
+ ct_lm3s5951,
+ ct_lm3s5956,
+ ct_lm3s1b21,
+ ct_lm3s2b93,
+ ct_lm3s5b91,
+ ct_lm3s9b81,
+ ct_lm3s9b90,
+ ct_lm3s9b92,
+ ct_lm3s9b95,
+ ct_lm3s9b96,
+
+ { SAMSUNG }
+ ct_sc32442b,
+
+ // generic Thumb2 target
+ ct_thumb2bare
+ );
+
+
+Const
+ {# Size of native extended floating point type }
+ extended_size = 12;
+ {# Size of a multimedia register }
+ mmreg_size = 16;
+ { target cpu string (used by compiler options) }
+ target_cpu_string = 'arm';
+
+ { calling conventions supported by the code generator }
+ supported_calling_conventions : tproccalloptions = [
+ pocall_internproc,
+ pocall_safecall,
+ pocall_stdcall,
+ { same as stdcall only different name mangling }
+ pocall_cdecl,
+ { same as stdcall only different name mangling }
+ pocall_cppdecl,
+ { same as stdcall but floating point numbers are handled like equal sized integers }
+ pocall_softfloat,
+ { same as stdcall (requires that all const records are passed by
+ reference, but that's already done for stdcall) }
+ pocall_mwpascal,
+ { used for interrupt handling }
+ pocall_interrupt
+ ];
+
+ cputypestr : array[tcputype] of string[8] = ('',
+ 'ARMV3',
+ 'ARMV4',
+ 'ARMV4T',
+ 'ARMV5',
+ 'ARMV6',
+ 'ARMV7',
+ 'ARMV7M'
+ );
+
+ fputypestr : array[tfputype] of string[6] = ('',
+ 'SOFT',
+ 'LIBGCC',
+ 'FPA',
+ 'FPA10',
+ 'FPA11',
+ 'VFPV2',
+ 'VFPV3'
+ );
+
+
+ { We know that there are fields after sramsize
+ but we don't care about this warning }
+ {$WARN 3177 OFF}
+
+ embedded_controllers : array [tcontrollertype] of tcontrollerdatatype =
+ ((
+ controllertypestr:'';
+ controllerunitstr:'';
+ interruptvectors:0;
+ flashbase:0;
+ flashsize:0;
+ srambase:0;
+ sramsize:0
+ ),
+
+ (
+ controllertypestr:'LPC2114';
+ controllerunitstr:'LPC21x4';
+ interruptvectors:8;
+ flashbase:$00000000;
+ flashsize:$00040000;
+ srambase:$40000000;
+ sramsize:$00004000
+ ),
+
+ (
+ controllertypestr:'LPC2124';
+ controllerunitstr:'LPC21x4';
+ interruptvectors:8;
+ flashbase:$00000000;
+ flashsize:$00040000;
+ srambase:$40000000;
+ sramsize:$00004000
+ ),
+
+ (
+ controllertypestr:'LPC2194';
+ controllerunitstr:'LPC21x4';
+ interruptvectors:8;
+ flashbase:$00000000;
+ flashsize:$00040000;
+ srambase:$40000000;
+ sramsize:$00004000
+ ),
+
+ (
+ controllertypestr:'LPC1768';
+ controllerunitstr:'LPC1768';
+ interruptvectors:12;
+ flashbase:$00000000;
+ flashsize:$00040000;
+ srambase:$10000000;
+ sramsize:$00008000
+ ),
+
+ (
+ controllertypestr:'AT91SAM7S256';
+ controllerunitstr:'AT91SAM7x256';
+ interruptvectors:8;
+ flashbase:$00000000;
+ flashsize:$00040000;
+ srambase:$00200000;
+ sramsize:$00010000
+ ),
+
+ (
+ controllertypestr:'AT91SAM7SE256';
+ controllerunitstr:'AT91SAM7x256';
+ interruptvectors:8;
+ flashbase:$00000000;
+ flashsize:$00040000;
+ srambase:$00200000;
+ sramsize:$00010000
+ ),
+
+ (
+ controllertypestr:'AT91SAM7X256';
+ controllerunitstr:'AT91SAM7x256';
+ interruptvectors:8;
+ flashbase:$00000000;
+ flashsize:$00040000;
+ srambase:$00200000;
+ sramsize:$00010000
+ ),
+
+ (
+ controllertypestr:'AT91SAM7XC256';
+ controllerunitstr:'AT91SAM7x256';
+ interruptvectors:8;
+ flashbase:$00000000;
+ flashsize:$00040000;
+ srambase:$00200000;
+ sramsize:$00010000
+ ),
+
+ // ct_stm32f103rb,
+ (
+ controllertypestr:'STM32F103RB';
+ controllerunitstr:'STM32F103';
+ interruptvectors:12;
+ flashbase:$08000000;
+ flashsize:$00020000;
+ srambase:$20000000;
+ sramsize:$00005000
+ ),
+ // ct_stm32f103re,
+ (
+ controllertypestr:'STM32F103RE';
+ controllerunitstr:'STM32F103';
+ interruptvectors:12;
+ flashbase:$08000000;
+ flashsize:$00080000;
+ srambase:$20000000;
+ sramsize:$00010000
+ ),
+ // ct_stm32f103re,
+ (
+ controllertypestr:'STM32F103C4T';
+ controllerunitstr:'STM32F103';
+ interruptvectors:12;
+ flashbase:$08000000;
+ flashsize:$00004000;
+ srambase:$20000000;
+ sramsize:$00001800
+ ),
+
+ { TI - 64 K Flash, 16 K SRAM Devices }
+ // ct_lm3s1110,
+ (
+ controllertypestr:'LM3S1110';
+ controllerunitstr:'LM3FURY';
+ interruptvectors:72;
+ flashbase:$00000000;
+ flashsize:$00010000;
+ srambase:$20000000;
+ sramsize:$00004000
+ ),
+ // ct_lm3s1133,
+ (
+ controllertypestr:'LM3S1133';
+ controllerunitstr:'LM3FURY';
+ interruptvectors:72;
+ flashbase:$00000000;
+ flashsize:$00010000;
+ srambase:$20000000;
+ sramsize:$00004000
+ ),
+ // ct_lm3s1138,
+ (
+ controllertypestr:'LM3S1138';
+ controllerunitstr:'LM3FURY';
+ interruptvectors:72;
+ flashbase:$00000000;
+ flashsize:$00010000;
+ srambase:$20000000;
+ sramsize:$00004000
+ ),
+ // ct_lm3s1150,
+ (
+ controllertypestr:'LM3S1150';
+ controllerunitstr:'LM3FURY';
+ interruptvectors:72;
+ flashbase:$00000000;
+ flashsize:$00010000;
+ srambase:$20000000;
+ sramsize:$00004000
+ ),
+ // ct_lm3s1162,
+ (
+ controllertypestr:'LM3S1162';
+ controllerunitstr:'LM3FURY';
+ interruptvectors:72;
+ flashbase:$00000000;
+ flashsize:$00010000;
+ srambase:$20000000;
+ sramsize:$00004000
+ ),
+ // ct_lm3s1165,
+ (
+ controllertypestr:'LM3S1165';
+ controllerunitstr:'LM3FURY';
+ interruptvectors:72;
+ flashbase:$00000000;
+ flashsize:$00010000;
+ srambase:$20000000;
+ sramsize:$00004000
+ ),
+ // ct_lm3s1166,
+ (
+ controllertypestr:'LM3S1166';
+ controllerunitstr:'LM3FURY';
+ interruptvectors:72;
+ flashbase:$00000000;
+ flashsize:$00010000;
+ srambase:$20000000;
+ sramsize:$00004000
+ ),
+ // ct_lm3s2110,
+ (
+ controllertypestr:'LM3S2110';
+ controllerunitstr:'LM3FURY';
+ interruptvectors:72;
+ flashbase:$00000000;
+ flashsize:$00010000;
+ srambase:$20000000;
+ sramsize:$00004000
+ ),
+ // ct_lm3s2139,
+ (
+ controllertypestr:'LM3S2139';
+ controllerunitstr:'LM3FURY';
+ interruptvectors:72;
+ flashbase:$00000000;
+ flashsize:$00010000;
+ srambase:$20000000;
+ sramsize:$00004000
+ ),
+ // ct_lm3s6100,
+ (
+ controllertypestr:'LM3S6100';
+ controllerunitstr:'LM3FURY';
+ interruptvectors:72;
+ flashbase:$00000000;
+ flashsize:$00010000;
+ srambase:$20000000;
+ sramsize:$00004000
+ ),
+ // ct_lm3s6110,
+ (
+ controllertypestr:'LM3S6110';
+ controllerunitstr:'LM3FURY';
+ interruptvectors:72;
+ flashbase:$00000000;
+ flashsize:$00010000;
+ srambase:$20000000;
+ sramsize:$00004000
+ ),
+
+ { TI - 128K Flash, 32K SRAM devices }
+ // ct_lm3s1601,
+ (
+ controllertypestr:'LM3S1601';
+ controllerunitstr:'LM3FURY';
+ interruptvectors:72;
+ flashbase:$00000000;
+ flashsize:$00020000;
+ srambase:$20000000;
+ sramsize:$00008000
+ ),
+ // ct_lm3s1608,
+ (
+ controllertypestr:'LM3S1608';
+ controllerunitstr:'LM3FURY';
+ interruptvectors:72;
+ flashbase:$00000000;
+ flashsize:$00020000;
+ srambase:$20000000;
+ sramsize:$00008000
+ ),
+ // ct_lm3s1620,
+ (
+ controllertypestr:'LM3S1620';
+ controllerunitstr:'LM3FURY';
+ interruptvectors:72;
+ flashbase:$00000000;
+ flashsize:$00020000;
+ srambase:$20000000;
+ sramsize:$00008000
+ ),
+ // ct_lm3s1635,
+ (
+ controllertypestr:'LM3S1635';
+ controllerunitstr:'LM3FURY';
+ interruptvectors:72;
+ flashbase:$00000000;
+ flashsize:$00020000;
+ srambase:$20000000;
+ sramsize:$00008000
+ ),
+ // ct_lm3s1636,
+ (
+ controllertypestr:'LM3S1636';
+ controllerunitstr:'LM3FURY';
+ interruptvectors:72;
+ flashbase:$00000000;
+ flashsize:$00020000;
+ srambase:$20000000;
+ sramsize:$00008000
+ ),
+ // ct_lm3s1637,
+ (
+ controllertypestr:'LM3S1637';
+ controllerunitstr:'LM3FURY';
+ interruptvectors:72;
+ flashbase:$00000000;
+ flashsize:$00020000;
+ srambase:$20000000;
+ sramsize:$00008000
+ ),
+ // ct_lm3s1651,
+ (
+ controllertypestr:'LM3S1651';
+ controllerunitstr:'LM3FURY';
+ interruptvectors:72;
+ flashbase:$00000000;
+ flashsize:$00020000;
+ srambase:$20000000;
+ sramsize:$00008000
+ ),
+ // ct_lm3s2601,
+ (
+ controllertypestr:'LM3S2601';
+ controllerunitstr:'LM3FURY';
+ interruptvectors:72;
+ flashbase:$00000000;
+ flashsize:$00020000;
+ srambase:$20000000;
+ sramsize:$00008000
+ ),
+ // ct_lm3s2608,
+ (
+ controllertypestr:'LM3S2608';
+ controllerunitstr:'LM3FURY';
+ interruptvectors:72;
+ flashbase:$00000000;
+ flashsize:$00020000;
+ srambase:$20000000;
+ sramsize:$00008000
+ ),
+ // ct_lm3s2620,
+ (
+ controllertypestr:'LM3S2620';
+ controllerunitstr:'LM3FURY';
+ interruptvectors:72;
+ flashbase:$00000000;
+ flashsize:$00020000;
+ srambase:$20000000;
+ sramsize:$00008000
+ ),
+ // ct_lm3s2637,
+ (
+ controllertypestr:'LM3S2637';
+ controllerunitstr:'LM3FURY';
+ interruptvectors:72;
+ flashbase:$00000000;
+ flashsize:$00020000;
+ srambase:$20000000;
+ sramsize:$00008000
+ ),
+ // ct_lm3s2651,
+ (
+ controllertypestr:'LM3S2651';
+ controllerunitstr:'LM3FURY';
+ interruptvectors:72;
+ flashbase:$00000000;
+ flashsize:$00020000;
+ srambase:$20000000;
+ sramsize:$00008000
+ ),
+ // ct_lm3s6610,
+ (
+ controllertypestr:'LM3S6610';
+ controllerunitstr:'LM3FURY';
+ interruptvectors:72;
+ flashbase:$00000000;
+ flashsize:$00020000;
+ srambase:$20000000;
+ sramsize:$00008000
+ ),
+ // ct_lm3s6611,
+ (
+ controllertypestr:'LM3S6611';
+ controllerunitstr:'LM3FURY';
+ interruptvectors:72;
+ flashbase:$00000000;
+ flashsize:$00020000;
+ srambase:$20000000;
+ sramsize:$00008000
+ ),
+ // ct_lm3s6618,
+ (
+ controllertypestr:'LM3S6618';
+ controllerunitstr:'LM3FURY';
+ interruptvectors:72;
+ flashbase:$00000000;
+ flashsize:$00020000;
+ srambase:$20000000;
+ sramsize:$00008000
+ ),
+ // ct_lm3s6633,
+ (
+ controllertypestr:'LM3S6633';
+ controllerunitstr:'LM3FURY';
+ interruptvectors:72;
+ flashbase:$00000000;
+ flashsize:$00020000;
+ srambase:$20000000;
+ sramsize:$00008000
+ ),
+ // ct_lm3s6637,
+ (
+ controllertypestr:'LM3S6637';
+ controllerunitstr:'LM3FURY';
+ interruptvectors:72;
+ flashbase:$00000000;
+ flashsize:$00020000;
+ srambase:$20000000;
+ sramsize:$00008000
+ ),
+ // ct_lm3s8630,
+ (
+ controllertypestr:'LM3S8630';
+ controllerunitstr:'LM3FURY';
+ interruptvectors:72;
+ flashbase:$00000000;
+ flashsize:$00020000;
+ srambase:$20000000;
+ sramsize:$00008000
+ ),
+
+ { TI - 256K Flash, 64K SRAM devices }
+ // ct_lm3s1911,
+ (
+ controllertypestr:'LM3S1911';
+ controllerunitstr:'LM3FURY';
+ interruptvectors:72;
+ flashbase:$00000000;
+ flashsize:$00040000;
+ srambase:$20000000;
+ sramsize:$00010000
+ ),
+ // ct_lm3s1918,
+ (
+ controllertypestr:'LM3S1918';
+ controllerunitstr:'LM3FURY';
+ interruptvectors:72;
+ flashbase:$00000000;
+ flashsize:$00040000;
+ srambase:$20000000;
+ sramsize:$00010000
+ ),
+ // ct_lm3s1937,
+ (
+ controllertypestr:'LM3S1937';
+ controllerunitstr:'LM3FURY';
+ interruptvectors:72;
+ flashbase:$00000000;
+ flashsize:$00040000;
+ srambase:$20000000;
+ sramsize:$00010000
+ ),
+ // ct_lm3s1958,
+ (
+ controllertypestr:'LM3S1958';
+ controllerunitstr:'LM3FURY';
+ interruptvectors:72;
+ flashbase:$00000000;
+ flashsize:$00040000;
+ srambase:$20000000;
+ sramsize:$00010000
+ ),
+ // ct_lm3s1960,
+ (
+ controllertypestr:'LM3S1960';
+ controllerunitstr:'LM3FURY';
+ interruptvectors:72;
+ flashbase:$00000000;
+ flashsize:$00040000;
+ srambase:$20000000;
+ sramsize:$00010000
+ ),
+ // ct_lm3s1968,
+ (
+ controllertypestr:'LM3S1968';
+ controllerunitstr:'LM3FURY';
+ interruptvectors:72;
+ flashbase:$00000000;
+ flashsize:$00040000;
+ srambase:$20000000;
+ sramsize:$00010000
+ ),
+ // ct_lm3s1969,
+ (
+ controllertypestr:'LM3S1969';
+ controllerunitstr:'LM3FURY';
+ interruptvectors:72;
+ flashbase:$00000000;
+ flashsize:$00040000;
+ srambase:$20000000;
+ sramsize:$00010000
+ ),
+ // ct_lm3s2911,
+ (
+ controllertypestr:'LM3S2911';
+ controllerunitstr:'LM3FURY';
+ interruptvectors:72;
+ flashbase:$00000000;
+ flashsize:$00040000;
+ srambase:$20000000;
+ sramsize:$00010000
+ ),
+ // ct_lm3s2918,
+ (
+ controllertypestr:'LM3S2918';
+ controllerunitstr:'LM3FURY';
+ interruptvectors:72;
+ flashbase:$00000000;
+ flashsize:$00040000;
+ srambase:$20000000;
+ sramsize:$00010000
+ ),
+ // ct_lm3s2919,
+ (
+ controllertypestr:'LM3S2919';
+ controllerunitstr:'LM3FURY';
+ interruptvectors:72;
+ flashbase:$00000000;
+ flashsize:$00040000;
+ srambase:$20000000;
+ sramsize:$00010000
+ ),
+ // ct_lm3s2939,
+ (
+ controllertypestr:'LM3S2939';
+ controllerunitstr:'LM3FURY';
+ interruptvectors:72;
+ flashbase:$00000000;
+ flashsize:$00040000;
+ srambase:$20000000;
+ sramsize:$00010000
+ ),
+ // ct_lm3s2948,
+ (
+ controllertypestr:'LM3S2948';
+ controllerunitstr:'LM3FURY';
+ interruptvectors:72;
+ flashbase:$00000000;
+ flashsize:$00040000;
+ srambase:$20000000;
+ sramsize:$00010000
+ ),
+ // ct_lm3s2950,
+ (
+ controllertypestr:'LM3S2950';
+ controllerunitstr:'LM3FURY';
+ interruptvectors:72;
+ flashbase:$00000000;
+ flashsize:$00040000;
+ srambase:$20000000;
+ sramsize:$00010000
+ ),
+ // ct_lm3s2965,
+ (
+ controllertypestr:'LM3S2965';
+ controllerunitstr:'LM3FURY';
+ interruptvectors:72;
+ flashbase:$00000000;
+ flashsize:$00040000;
+ srambase:$20000000;
+ sramsize:$00010000
+ ),
+ // ct_lm3s6911,
+ (
+ controllertypestr:'LM3S6911';
+ controllerunitstr:'LM3FURY';
+ interruptvectors:72;
+ flashbase:$00000000;
+ flashsize:$00040000;
+ srambase:$20000000;
+ sramsize:$00010000
+ ),
+ // ct_lm3s6918,
+ (
+ controllertypestr:'LM3S6918';
+ controllerunitstr:'LM3FURY';
+ interruptvectors:72;
+ flashbase:$00000000;
+ flashsize:$00040000;
+ srambase:$20000000;
+ sramsize:$00010000
+ ),
+ // ct_lm3s6938,
+ (
+ controllertypestr:'LM3S6938';
+ controllerunitstr:'LM3FURY';
+ interruptvectors:72;
+ flashbase:$00000000;
+ flashsize:$00040000;
+ srambase:$20000000;
+ sramsize:$00010000
+ ),
+ // ct_lm3s6950,
+ (
+ controllertypestr:'LM3S6950';
+ controllerunitstr:'LM3FURY';
+ interruptvectors:72;
+ flashbase:$00000000;
+ flashsize:$00040000;
+ srambase:$20000000;
+ sramsize:$00010000
+ ),
+ // ct_lm3s6952,
+ (
+ controllertypestr:'LM3S6952';
+ controllerunitstr:'LM3FURY';
+ interruptvectors:72;
+ flashbase:$00000000;
+ flashsize:$00040000;
+ srambase:$20000000;
+ sramsize:$00010000
+ ),
+ // ct_lm3s6965,
+ (
+ controllertypestr:'LM3S6965';
+ controllerunitstr:'LM3FURY';
+ interruptvectors:72;
+ flashbase:$00000000;
+ flashsize:$00040000;
+ srambase:$20000000;
+ sramsize:$00010000
+ ),
+ // ct_lm3s8930,
+ (
+ controllertypestr:'LM3S8930';
+ controllerunitstr:'LM3FURY';
+ interruptvectors:72;
+ flashbase:$00000000;
+ flashsize:$00040000;
+ srambase:$20000000;
+ sramsize:$00010000
+ ),
+ // ct_lm3s8933,
+ (
+ controllertypestr:'LM3S8933';
+ controllerunitstr:'LM3FURY';
+ interruptvectors:72;
+ flashbase:$00000000;
+ flashsize:$00040000;
+ srambase:$20000000;
+ sramsize:$00010000
+ ),
+ // ct_lm3s8938,
+ (
+ controllertypestr:'LM3S8938';
+ controllerunitstr:'LM3FURY';
+ interruptvectors:72;
+ flashbase:$00000000;
+ flashsize:$00040000;
+ srambase:$20000000;
+ sramsize:$00010000
+ ),
+ // ct_lm3s8962,
+ (
+ controllertypestr:'LM3S8962';
+ controllerunitstr:'LM3FURY';
+ interruptvectors:72;
+ flashbase:$00000000;
+ flashsize:$00040000;
+ srambase:$20000000;
+ sramsize:$00010000
+ ),
+ // ct_lm3s8970,
+ (
+ controllertypestr:'LM3S8970';
+ controllerunitstr:'LM3FURY';
+ interruptvectors:72;
+ flashbase:$00000000;
+ flashsize:$00040000;
+ srambase:$20000000;
+ sramsize:$00010000
+ ),
+ // ct_lm3s8971,
+ (
+ controllertypestr:'LM3S8971';
+ controllerunitstr:'LM3FURY';
+ interruptvectors:72;
+ flashbase:$00000000;
+ flashsize:$00040000;
+ srambase:$20000000;
+ sramsize:$00010000
+ ),
+
+ { TI - Tempest parts - 256 K Flash, 64 K SRAM }
+ // ct_lm3s5951,
+ (
+ controllertypestr:'LM3S5951';
+ controllerunitstr:'LM3TEMPEST';
+ interruptvectors:72;
+ flashbase:$00000000;
+ flashsize:$00040000;
+ srambase:$20000000;
+ sramsize:$00010000
+ ),
+ // ct_lm3s5956,
+ (
+ controllertypestr:'LM3S5956';
+ controllerunitstr:'LM3TEMPEST';
+ interruptvectors:72;
+ flashbase:$00000000;
+ flashsize:$00040000;
+ srambase:$20000000;
+ sramsize:$00010000
+ ),
+ // ct_lm3s1b21,
+ (
+ controllertypestr:'LM3S1B21';
+ controllerunitstr:'LM3TEMPEST';
+ interruptvectors:72;
+ flashbase:$00000000;
+ flashsize:$00040000;
+ srambase:$20000000;
+ sramsize:$00010000
+ ),
+ // ct_lm3s2b93,
+ (
+ controllertypestr:'LM3S2B93';
+ controllerunitstr:'LM3TEMPEST';
+ interruptvectors:72;
+ flashbase:$00000000;
+ flashsize:$00040000;
+ srambase:$20000000;
+ sramsize:$00010000
+ ),
+ // ct_lm3s5b91,
+ (
+ controllertypestr:'LM3S5B91';
+ controllerunitstr:'LM3TEMPEST';
+ interruptvectors:72;
+ flashbase:$00000000;
+ flashsize:$00040000;
+ srambase:$20000000;
+ sramsize:$00010000
+ ),
+ // ct_lm3s9b81,
+ (
+ controllertypestr:'LM3S9B81';
+ controllerunitstr:'LM3TEMPEST';
+ interruptvectors:72;
+ flashbase:$00000000;
+ flashsize:$00040000;
+ srambase:$20000000;
+ sramsize:$00010000
+ ),
+ // ct_lm3s9b90,
+ (
+ controllertypestr:'LM3S9B90';
+ controllerunitstr:'LM3TEMPEST';
+ interruptvectors:72;
+ flashbase:$00000000;
+ flashsize:$00040000;
+ srambase:$20000000;
+ sramsize:$00010000
+ ),
+ // ct_lm3s9b92,
+ (
+ controllertypestr:'LM3S9B92';
+ controllerunitstr:'LM3TEMPEST';
+ interruptvectors:72;
+ flashbase:$00000000;
+ flashsize:$00040000;
+ srambase:$20000000;
+ sramsize:$00010000
+ ),
+ // ct_lm3s9b95,
+ (
+ controllertypestr:'LM3S9B95';
+ controllerunitstr:'LM3TEMPEST';
+ interruptvectors:72;
+ flashbase:$00000000;
+ flashsize:$00040000;
+ srambase:$20000000;
+ sramsize:$00010000
+ ),
+ // ct_lm3s9b96,
+ (
+ controllertypestr:'LM3S9B96';
+ controllerunitstr:'LM3TEMPEST';
+ interruptvectors:72;
+ flashbase:$00000000;
+ flashsize:$00040000;
+ srambase:$20000000;
+ sramsize:$00010000
+ ),
+
+ //ct_SC32442b,
+ (
+ controllertypestr:'SC32442B';
+ controllerunitstr:'sc32442b';
+ interruptvectors:7;
+ flashbase:$00000000;
+ flashsize:$00000000;
+ srambase:$00000000;
+ sramsize:$08000000
+ ),
+
+ // bare bones Thumb2
+ (
+ controllertypestr:'THUMB2_BARE';
+ controllerunitstr:'THUMB2_BARE';
+ interruptvectors:128;
+ flashbase:$00000000;
+ flashsize:$00100000;
+ srambase:$20000000;
+ sramsize:$00100000
+ )
+ );
+
+ vfp_scalar = [fpu_vfpv2,fpu_vfpv3];
+
+ { Supported optimizations, only used for information }
+ supported_optimizerswitches = genericlevel1optimizerswitches+
+ genericlevel2optimizerswitches+
+ genericlevel3optimizerswitches-
+ { no need to write info about those }
+ [cs_opt_level1,cs_opt_level2,cs_opt_level3]+
+ [cs_opt_regvar,cs_opt_loopunroll,cs_opt_tailrecursion,
+ cs_opt_stackframe,cs_opt_nodecse];
+
+ level1optimizerswitches = genericlevel1optimizerswitches;
+ level2optimizerswitches = genericlevel2optimizerswitches + level1optimizerswitches +
+ [cs_opt_regvar,cs_opt_stackframe,cs_opt_tailrecursion,cs_opt_nodecse];
+ level3optimizerswitches = genericlevel3optimizerswitches + level2optimizerswitches + [{,cs_opt_loopunroll}];
+
+Implementation
+
+end.
diff --git a/closures/compiler/arm/cpunode.pas b/closures/compiler/arm/cpunode.pas
new file mode 100644
index 0000000000..d015d46163
--- /dev/null
+++ b/closures/compiler/arm/cpunode.pas
@@ -0,0 +1,47 @@
+{
+ Copyright (c) 2000-2003 by Florian Klaempfl
+
+ This unit includes the ARM code generator into the compiler
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit cpunode;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ implementation
+
+ uses
+ { generic nodes }
+ ncgbas,ncgld,ncgflw,ncgcnv,ncgmem,ncgcon,ncgcal,ncgset,ncginl,ncgopt,ncgmat,ncgobjc,
+ { to be able to only parts of the generic code,
+ the processor specific nodes must be included
+ after the generic one (FK)
+ }
+ narmadd,
+ narmcal,
+ narmmat,
+ narminl,
+ narmcnv,
+ narmcon,
+ narmset
+ ;
+
+
+end.
diff --git a/closures/compiler/arm/cpupara.pas b/closures/compiler/arm/cpupara.pas
new file mode 100644
index 0000000000..338e2d5216
--- /dev/null
+++ b/closures/compiler/arm/cpupara.pas
@@ -0,0 +1,592 @@
+{
+ Copyright (c) 2003 by Florian Klaempfl
+
+ ARM specific calling conventions
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ ****************************************************************************
+}
+{ ARM specific calling conventions are handled by this unit
+}
+unit cpupara;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ globtype,globals,
+ aasmtai,aasmdata,
+ cpuinfo,cpubase,cgbase,cgutils,
+ symconst,symbase,symtype,symdef,parabase,paramgr;
+
+ type
+ tarmparamanager = class(tparamanager)
+ function get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;override;
+ function get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;override;
+ function get_volatile_registers_mm(calloption : tproccalloption):tcpuregisterset;override;
+ function push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override;
+ function ret_in_param(def : tdef;calloption : tproccalloption) : boolean;override;
+ procedure getintparaloc(calloption : tproccalloption; nr : longint;var cgpara:TCGPara);override;
+ function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override;
+ function create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;override;
+ function get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tcgpara;override;
+ private
+ procedure init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword);
+ function create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras: tparalist;
+ var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword):longint;
+ procedure create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
+ end;
+
+ implementation
+
+ uses
+ verbose,systems,cutils,
+ rgobj,
+ defutil,symsym;
+
+
+ function tarmparamanager.get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;
+ begin
+ if (target_info.system<>system_arm_darwin) then
+ result:=VOLATILE_INTREGISTERS
+ else
+ result:=VOLATILE_INTREGISTERS_DARWIN;
+ end;
+
+
+ function tarmparamanager.get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;
+ begin
+ result:=VOLATILE_FPUREGISTERS;
+ end;
+
+
+ function tarmparamanager.get_volatile_registers_mm(calloption: tproccalloption): tcpuregisterset;
+ begin
+ result:=VOLATILE_MMREGISTERS;
+ end;
+
+
+ procedure tarmparamanager.getintparaloc(calloption : tproccalloption; nr : longint;var cgpara:TCGPara);
+ var
+ paraloc : pcgparalocation;
+ begin
+ if nr<1 then
+ internalerror(2002070801);
+ cgpara.reset;
+ cgpara.size:=OS_ADDR;
+ cgpara.intsize:=sizeof(pint);
+ cgpara.alignment:=std_param_align;
+ paraloc:=cgpara.add_location;
+ with paraloc^ do
+ begin
+ size:=OS_INT;
+ { the four first parameters are passed into registers }
+ if nr<=4 then
+ begin
+ loc:=LOC_REGISTER;
+ register:=newreg(R_INTREGISTER,RS_R0+nr-1,R_SUBWHOLE);
+ end
+ else
+ begin
+ { the other parameters are passed on the stack }
+ loc:=LOC_REFERENCE;
+ reference.index:=NR_STACK_POINTER_REG;
+ reference.offset:=(nr-5)*4;
+ end;
+ end;
+ end;
+
+
+ function getparaloc(calloption : tproccalloption; p : tdef) : tcgloc;
+ begin
+ { Later, the LOC_REFERENCE is in most cases changed into LOC_REGISTER
+ if push_addr_param for the def is true
+ }
+ case p.typ of
+ orddef:
+ getparaloc:=LOC_REGISTER;
+ floatdef:
+ if (calloption in [pocall_cdecl,pocall_cppdecl,pocall_softfloat]) or
+ (cs_fp_emulation in current_settings.moduleswitches) or
+ (current_settings.fputype in [fpu_vfpv2,fpu_vfpv3]) then
+ { the ARM eabi also allows passing VFP values via VFP registers,
+ but at least neither Mac OS X nor Linux seems to do that }
+ getparaloc:=LOC_REGISTER
+ else
+ getparaloc:=LOC_FPUREGISTER;
+ enumdef:
+ getparaloc:=LOC_REGISTER;
+ pointerdef:
+ getparaloc:=LOC_REGISTER;
+ formaldef:
+ getparaloc:=LOC_REGISTER;
+ classrefdef:
+ getparaloc:=LOC_REGISTER;
+ recorddef:
+ getparaloc:=LOC_REGISTER;
+ objectdef:
+ getparaloc:=LOC_REGISTER;
+ stringdef:
+ if is_shortstring(p) or is_longstring(p) then
+ getparaloc:=LOC_REFERENCE
+ else
+ getparaloc:=LOC_REGISTER;
+ procvardef:
+ getparaloc:=LOC_REGISTER;
+ filedef:
+ getparaloc:=LOC_REGISTER;
+ arraydef:
+ getparaloc:=LOC_REFERENCE;
+ setdef:
+ if is_smallset(p) then
+ getparaloc:=LOC_REGISTER
+ else
+ getparaloc:=LOC_REFERENCE;
+ variantdef:
+ getparaloc:=LOC_REGISTER;
+ { avoid problems with errornous definitions }
+ errordef:
+ getparaloc:=LOC_REGISTER;
+ else
+ internalerror(2002071001);
+ end;
+ end;
+
+
+ function tarmparamanager.push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;
+ begin
+ result:=false;
+ if varspez in [vs_var,vs_out,vs_constref] then
+ begin
+ result:=true;
+ exit;
+ end;
+ case def.typ of
+ objectdef:
+ result:=is_object(def) and ((varspez=vs_const) or (def.size=0));
+ recorddef:
+ { note: should this ever be changed, make sure that const records
+ are always passed by reference for calloption=pocall_mwpascal }
+ result:=(varspez=vs_const) or (def.size=0);
+ variantdef,
+ formaldef:
+ result:=true;
+ arraydef:
+ result:=(tarraydef(def).highrange>=tarraydef(def).lowrange) or
+ is_open_array(def) or
+ is_array_of_const(def) or
+ is_array_constructor(def);
+ setdef :
+ result:=not is_smallset(def);
+ stringdef :
+ result:=tstringdef(def).stringtype in [st_shortstring,st_longstring];
+ end;
+ end;
+
+
+ function tarmparamanager.ret_in_param(def : tdef;calloption : tproccalloption) : boolean;
+ begin
+ case def.typ of
+ recorddef:
+ result:=def.size>4;
+ procvardef:
+ if not tprocvardef(def).is_addressonly then
+ result:=true
+ else
+ result:=false
+ else
+ result:=inherited ret_in_param(def,calloption);
+ end;
+ end;
+
+
+ procedure tarmparamanager.init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword);
+ begin
+ curintreg:=RS_R0;
+ curfloatreg:=RS_F0;
+ curmmreg:=RS_D0;
+ cur_stack_offset:=0;
+ end;
+
+
+ function tarmparamanager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras: tparalist;
+ var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword):longint;
+
+ var
+ nextintreg,nextfloatreg,nextmmreg : tsuperregister;
+ paradef : tdef;
+ paraloc : pcgparalocation;
+ stack_offset : aword;
+ hp : tparavarsym;
+ loc : tcgloc;
+ paracgsize : tcgsize;
+ paralen : longint;
+ i : integer;
+ firstparaloc: boolean;
+
+ procedure assignintreg;
+ begin
+ { In case of po_delphi_nested_cc, the parent frame pointer
+ is always passed on the stack. }
+ if (nextintreg<=RS_R3) and
+ (not(vo_is_parentfp in hp.varoptions) or
+ not(po_delphi_nested_cc in p.procoptions)) then
+ begin
+ paraloc^.loc:=LOC_REGISTER;
+ paraloc^.register:=newreg(R_INTREGISTER,nextintreg,R_SUBWHOLE);
+ inc(nextintreg);
+ end
+ else
+ begin
+ paraloc^.loc:=LOC_REFERENCE;
+ paraloc^.reference.index:=NR_STACK_POINTER_REG;
+ paraloc^.reference.offset:=stack_offset;
+ inc(stack_offset,4);
+ end;
+ end;
+
+
+ begin
+ result:=0;
+ nextintreg:=curintreg;
+ nextfloatreg:=curfloatreg;
+ nextmmreg:=curmmreg;
+ stack_offset:=cur_stack_offset;
+
+ for i:=0 to paras.count-1 do
+ begin
+ hp:=tparavarsym(paras[i]);
+ paradef:=hp.vardef;
+
+ hp.paraloc[side].reset;
+
+ { currently only support C-style array of const,
+ there should be no location assigned to the vararg array itself }
+ if (p.proccalloption in [pocall_cdecl,pocall_cppdecl]) and
+ is_array_of_const(paradef) then
+ begin
+ paraloc:=hp.paraloc[side].add_location;
+ { hack: the paraloc must be valid, but is not actually used }
+ paraloc^.loc:=LOC_REGISTER;
+ paraloc^.register:=NR_R0;
+ paraloc^.size:=OS_ADDR;
+ break;
+ end;
+
+ if (hp.varspez in [vs_var,vs_out]) or
+ push_addr_param(hp.varspez,paradef,p.proccalloption) or
+ is_open_array(paradef) or
+ is_array_of_const(paradef) then
+ begin
+ paradef:=voidpointertype;
+ loc:=LOC_REGISTER;
+ paracgsize := OS_ADDR;
+ paralen := tcgsize2size[OS_ADDR];
+ end
+ else
+ begin
+ if not is_special_array(paradef) then
+ paralen := paradef.size
+ else
+ paralen := tcgsize2size[def_cgsize(paradef)];
+ loc := getparaloc(p.proccalloption,paradef);
+ if (paradef.typ in [objectdef,arraydef,recorddef]) and
+ not is_special_array(paradef) and
+ (hp.varspez in [vs_value,vs_const]) then
+ paracgsize := int_cgsize(paralen)
+ else
+ begin
+ paracgsize:=def_cgsize(paradef);
+ { for things like formaldef }
+ if (paracgsize=OS_NO) then
+ begin
+ paracgsize:=OS_ADDR;
+ paralen := tcgsize2size[OS_ADDR];
+ end;
+ end
+ end;
+
+ hp.paraloc[side].size:=paracgsize;
+ hp.paraloc[side].Alignment:=std_param_align;
+ hp.paraloc[side].intsize:=paralen;
+ firstparaloc:=true;
+
+{$ifdef EXTDEBUG}
+ if paralen=0 then
+ internalerror(200410311);
+{$endif EXTDEBUG}
+ while paralen>0 do
+ begin
+ paraloc:=hp.paraloc[side].add_location;
+
+ if (loc=LOC_REGISTER) and (paracgsize in [OS_F32,OS_F64,OS_F80]) then
+ case paracgsize of
+ OS_F32:
+ paraloc^.size:=OS_32;
+ OS_F64:
+ paraloc^.size:=OS_32;
+ else
+ internalerror(2005082901);
+ end
+ else if (paracgsize in [OS_NO,OS_64,OS_S64]) then
+ paraloc^.size := OS_32
+ else
+ paraloc^.size:=paracgsize;
+ case loc of
+ LOC_REGISTER:
+ begin
+ { align registers for eabi }
+ if (target_info.abi=abi_eabi) and
+ firstparaloc and
+ (paradef.alignment=8) then
+ begin
+ if (nextintreg in [RS_R1,RS_R3]) then
+ inc(nextintreg)
+ else if nextintreg>RS_R3 then
+ stack_offset:=align(stack_offset,8);
+ end;
+ { this is not abi compliant
+ why? (FK) }
+ if nextintreg<=RS_R3 then
+ begin
+ paraloc^.loc:=LOC_REGISTER;
+ paraloc^.register:=newreg(R_INTREGISTER,nextintreg,R_SUBWHOLE);
+ inc(nextintreg);
+ end
+ else
+ begin
+ { LOC_REFERENCE always contains everything that's left }
+ paraloc^.loc:=LOC_REFERENCE;
+ paraloc^.size:=int_cgsize(paralen);
+ if (side=callerside) then
+ paraloc^.reference.index:=NR_STACK_POINTER_REG;
+ paraloc^.reference.offset:=stack_offset;
+ inc(stack_offset,align(paralen,4));
+ paralen:=0;
+ end;
+ end;
+ LOC_FPUREGISTER:
+ begin
+ if nextfloatreg<=RS_F3 then
+ begin
+ paraloc^.loc:=LOC_FPUREGISTER;
+ paraloc^.register:=newreg(R_FPUREGISTER,nextfloatreg,R_SUBWHOLE);
+ inc(nextfloatreg);
+ end
+ else
+ begin
+ paraloc^.loc:=LOC_REFERENCE;
+ paraloc^.reference.index:=NR_STACK_POINTER_REG;
+ paraloc^.reference.offset:=stack_offset;
+ case paraloc^.size of
+ OS_F32:
+ inc(stack_offset,4);
+ OS_F64:
+ inc(stack_offset,8);
+ OS_F80:
+ inc(stack_offset,10);
+ OS_F128:
+ inc(stack_offset,16);
+ else
+ internalerror(200403201);
+ end;
+ end;
+ end;
+ LOC_REFERENCE:
+ begin
+ if push_addr_param(hp.varspez,paradef,p.proccalloption) then
+ begin
+ paraloc^.size:=OS_ADDR;
+ assignintreg
+ end
+ else
+ begin
+ { align stack for eabi }
+ if (target_info.abi=abi_eabi) and
+ firstparaloc and
+ (paradef.alignment=8) then
+ stack_offset:=align(stack_offset,8);
+
+ paraloc^.size:=paracgsize;
+ paraloc^.loc:=LOC_REFERENCE;
+ paraloc^.reference.index:=NR_STACK_POINTER_REG;
+ paraloc^.reference.offset:=stack_offset;
+ inc(stack_offset,align(paralen,4));
+ paralen:=0
+ end;
+ end;
+ else
+ internalerror(2002071002);
+ end;
+ if side=calleeside then
+ begin
+ if paraloc^.loc=LOC_REFERENCE then
+ begin
+ paraloc^.reference.index:=NR_FRAME_POINTER_REG;
+ inc(paraloc^.reference.offset,4);
+ end;
+ end;
+ dec(paralen,tcgsize2size[paraloc^.size]);
+ firstparaloc:=false
+ end;
+ end;
+ curintreg:=nextintreg;
+ curfloatreg:=nextfloatreg;
+ curmmreg:=nextmmreg;
+ cur_stack_offset:=stack_offset;
+ result:=cur_stack_offset;
+ end;
+
+
+ procedure tarmparamanager.create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
+ begin
+ p.funcretloc[side]:=get_funcretloc(p,side,p.returndef);
+ end;
+
+
+ function tarmparamanager.get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tcgpara;
+ var
+ paraloc : pcgparalocation;
+ retcgsize : tcgsize;
+ begin
+ result.init;
+ result.alignment:=get_para_align(p.proccalloption);
+ { void has no location }
+ if is_void(def) then
+ begin
+ paraloc:=result.add_location;
+ result.size:=OS_NO;
+ result.intsize:=0;
+ paraloc^.size:=OS_NO;
+ paraloc^.loc:=LOC_VOID;
+ exit;
+ end;
+ { Constructors return self instead of a boolean }
+ if (p.proctypeoption=potype_constructor) then
+ begin
+ retcgsize:=OS_ADDR;
+ result.intsize:=sizeof(pint);
+ end
+ else
+ begin
+ retcgsize:=def_cgsize(def);
+ result.intsize:=def.size;
+ end;
+ result.size:=retcgsize;
+ { Return is passed as var parameter }
+ if ret_in_param(def,p.proccalloption) then
+ begin
+ paraloc:=result.add_location;
+ paraloc^.loc:=LOC_REFERENCE;
+ paraloc^.size:=retcgsize;
+ exit;
+ end;
+
+ paraloc:=result.add_location;
+ { Return in FPU register? }
+ if def.typ=floatdef then
+ begin
+ if (p.proccalloption in [pocall_softfloat]) or
+ (cs_fp_emulation in current_settings.moduleswitches) or
+ (current_settings.fputype in [fpu_vfpv2,fpu_vfpv3]) then
+ begin
+ case retcgsize of
+ OS_64,
+ OS_F64:
+ begin
+ paraloc^.loc:=LOC_REGISTER;
+ paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG;
+ paraloc^.size:=OS_32;
+ paraloc:=result.add_location;
+ paraloc^.loc:=LOC_REGISTER;
+ paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG;
+ paraloc^.size:=OS_32;
+ end;
+ OS_32,
+ OS_F32:
+ begin
+ paraloc^.loc:=LOC_REGISTER;
+ paraloc^.register:=NR_FUNCTION_RETURN_REG;
+ paraloc^.size:=OS_32;
+ end;
+ else
+ internalerror(2005082603);
+ end;
+ end
+ else
+ begin
+ paraloc^.loc:=LOC_FPUREGISTER;
+ paraloc^.register:=NR_FPU_RESULT_REG;
+ paraloc^.size:=retcgsize;
+ end;
+ end
+ { Return in register }
+ else
+ begin
+ if retcgsize in [OS_64,OS_S64] then
+ begin
+ paraloc^.loc:=LOC_REGISTER;
+ paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG;
+ paraloc^.size:=OS_32;
+ paraloc:=result.add_location;
+ paraloc^.loc:=LOC_REGISTER;
+ paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG;
+ paraloc^.size:=OS_32;
+ end
+ else
+ begin
+ paraloc^.loc:=LOC_REGISTER;
+ paraloc^.register:=NR_FUNCTION_RETURN_REG;
+ if (result.intsize<>3) then
+ paraloc^.size:=retcgsize
+ else
+ paraloc^.size:=OS_32;
+ end;
+ end;
+ end;
+
+
+ function tarmparamanager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;
+ var
+ cur_stack_offset: aword;
+ curintreg, curfloatreg, curmmreg: tsuperregister;
+ begin
+ init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset);
+
+ result:=create_paraloc_info_intern(p,side,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset);
+
+ create_funcretloc_info(p,side);
+ end;
+
+
+ function tarmparamanager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;
+ var
+ cur_stack_offset: aword;
+ curintreg, curfloatreg, curmmreg: tsuperregister;
+ begin
+ init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset);
+
+ result:=create_paraloc_info_intern(p,callerside,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset);
+ if (p.proccalloption in [pocall_cdecl,pocall_cppdecl]) then
+ { just continue loading the parameters in the registers }
+ result:=create_paraloc_info_intern(p,callerside,varargspara,curintreg,curfloatreg,curmmreg,cur_stack_offset)
+ else
+ internalerror(200410231);
+ end;
+
+begin
+ paramanager:=tarmparamanager.create;
+end.
diff --git a/closures/compiler/arm/cpupi.pas b/closures/compiler/arm/cpupi.pas
new file mode 100644
index 0000000000..2b67bb9e40
--- /dev/null
+++ b/closures/compiler/arm/cpupi.pas
@@ -0,0 +1,128 @@
+{
+ Copyright (c) 2002 by Florian Klaempfl
+
+ This unit contains the CPU specific part of tprocinfo
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+
+{ This unit contains the CPU specific part of tprocinfo. }
+unit cpupi;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ globtype,cutils,
+ procinfo,cpuinfo,psub;
+
+ type
+ tarmprocinfo = class(tcgprocinfo)
+ floatregstart : aint;
+ // procedure handle_body_start;override;
+ // procedure after_pass1;override;
+ procedure set_first_temp_offset;override;
+ function calc_stackframe_size:longint;override;
+ end;
+
+
+ implementation
+
+ uses
+ globals,systems,
+ cpubase,
+ aasmtai,aasmdata,
+ tgobj,
+ symconst,symsym,paramgr,
+ cgbase,
+ cgobj;
+
+ procedure tarmprocinfo.set_first_temp_offset;
+ begin
+ { We allocate enough space to save all registers because we can't determine
+ the necessary space because the used registers aren't known before
+ secondpass is run. Even worse, patching
+ the local offsets after generating the code could cause trouble because
+ "shifter" constants could change to non-"shifter" constants. This
+ is especially a problem when taking the address of a local. For now,
+ this extra memory should hurt less than generating all local contants with offsets
+ >256 as non shifter constants }
+ if tg.direction = -1 then
+ begin
+ if (target_info.system<>system_arm_darwin) then
+ { Non-Darwin, worst case: r4-r10,r11,r13,r14,r15 is saved -> -28-16, but we
+ always adjust the frame pointer to point to the first stored
+ register (= last register in list above) -> + 4 }
+ tg.setfirsttemp(-28-16+4)
+ else
+ { on Darwin r9 is not usable -> one less register to save }
+ tg.setfirsttemp(-24-16+4)
+ end
+ else
+ tg.setfirsttemp(maxpushedparasize);
+ end;
+
+
+ function tarmprocinfo.calc_stackframe_size:longint;
+ var
+ firstfloatreg,lastfloatreg,
+ r : byte;
+ floatsavesize : aword;
+ regs: tcpuregisterset;
+ begin
+ maxpushedparasize:=align(maxpushedparasize,max(current_settings.alignment.localalignmin,4));
+ floatsavesize:=0;
+ case current_settings.fputype of
+ fpu_fpa,
+ fpu_fpa10,
+ fpu_fpa11:
+ begin
+ { save floating point registers? }
+ firstfloatreg:=RS_NO;
+ regs:=cg.rg[R_FPUREGISTER].used_in_proc-paramanager.get_volatile_registers_fpu(pocall_stdcall);
+ for r:=RS_F0 to RS_F7 do
+ if r in regs then
+ begin
+ if firstfloatreg=RS_NO then
+ firstfloatreg:=r;
+ lastfloatreg:=r;
+ end;
+ if firstfloatreg<>RS_NO then
+ floatsavesize:=(lastfloatreg-firstfloatreg+1)*12;
+ end;
+ fpu_vfpv2,
+ fpu_vfpv3:
+ begin
+ floatsavesize:=0;
+ regs:=cg.rg[R_MMREGISTER].used_in_proc-paramanager.get_volatile_registers_mm(pocall_stdcall);
+ for r:=RS_D0 to RS_D31 do
+ if r in regs then
+ inc(floatsavesize,8);
+ end;
+ end;
+ floatsavesize:=align(floatsavesize,max(current_settings.alignment.localalignmin,4));
+ result:=Align(tg.direction*tg.lasttemp,max(current_settings.alignment.localalignmin,4))+maxpushedparasize+aint(floatsavesize);
+ floatregstart:=tg.direction*result+maxpushedparasize;
+ if tg.direction=1 then
+ dec(floatregstart,floatsavesize);
+ end;
+
+
+begin
+ cprocinfo:=tarmprocinfo;
+end.
diff --git a/closures/compiler/arm/cputarg.pas b/closures/compiler/arm/cputarg.pas
new file mode 100644
index 0000000000..fa005ff686
--- /dev/null
+++ b/closures/compiler/arm/cputarg.pas
@@ -0,0 +1,93 @@
+{
+ Copyright (c) 2001-2002 by Peter Vreman
+
+ Includes the arm dependent target units
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit cputarg;
+
+{$i fpcdefs.inc}
+
+interface
+
+
+implementation
+
+ uses
+ systems { prevent a syntax error when nothing is included }
+
+{**************************************
+ Targets
+**************************************}
+
+ {$ifndef NOTARGETLINUX}
+ ,t_linux
+ {$endif}
+ {$ifndef NOTARGETWINCE}
+ ,t_win
+ {$endif}
+ {$ifndef NOTARGETGBA}
+ ,t_gba
+ {$endif}
+ {$ifndef NOTARGETPALMOS}
+ ,t_palmos
+ {$endif}
+ {$ifndef NOTARGETNDS}
+ ,t_nds
+ {$endif}
+ {$ifndef NOTARGETEMBEDDED}
+ ,t_embed
+ {$endif}
+ {$ifndef NOTARGETSYMBIAN}
+ ,t_symbian
+ {$endif}
+ {$ifndef NOTARGETBSD}
+ ,t_bsd
+ {$endif}
+
+{**************************************
+ Assemblers
+**************************************}
+
+ {$ifndef NOAGARMGAS}
+ ,agarmgas
+ {$endif}
+
+ ,ogcoff
+
+{**************************************
+ Assembler Readers
+**************************************}
+
+ {$ifndef NoRaarmgas}
+ ,raarmgas
+ {$endif NoRaarmgas}
+
+{**************************************
+ Debuginfo
+**************************************}
+
+ {$ifndef NoDbgStabs}
+ ,dbgstabs
+ {$endif NoDbgStabs}
+ {$ifndef NoDbgDwarf}
+ ,dbgdwarf
+ {$endif NoDbgDwarf}
+ ;
+
+end.
diff --git a/closures/compiler/arm/itcpugas.pas b/closures/compiler/arm/itcpugas.pas
new file mode 100644
index 0000000000..74a186a20e
--- /dev/null
+++ b/closures/compiler/arm/itcpugas.pas
@@ -0,0 +1,93 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit contains the ARM GAS instruction tables
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit itcpugas;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cpubase,cgbase;
+
+
+ const
+ { Standard opcode string table (for each tasmop enumeration). The
+ opcode strings should conform to the names as defined by the
+ processor manufacturer.
+ }
+ gas_op2str : op2strtable = {$i armatt.inc}
+
+ function gas_regnum_search(const s:string):Tregister;
+ function gas_regname(r:Tregister):string;
+
+
+implementation
+
+ uses
+ cutils,verbose;
+
+ const
+ gas_regname_table : array[tregisterindex] of string[7] = (
+ {$i rarmstd.inc}
+ );
+
+ gas_regname_index : array[tregisterindex] of tregisterindex = (
+ {$i rarmsri.inc}
+ );
+
+ function findreg_by_gasname(const s:string):tregisterindex;
+ var
+ i,p : tregisterindex;
+ begin
+ {Binary search.}
+ p:=0;
+ i:=regnumber_count_bsstart;
+ repeat
+ if (p+i<=high(tregisterindex)) and (gas_regname_table[gas_regname_index[p+i]]<=s) then
+ p:=p+i;
+ i:=i shr 1;
+ until i=0;
+ if gas_regname_table[gas_regname_index[p]]=s then
+ findreg_by_gasname:=gas_regname_index[p]
+ else
+ findreg_by_gasname:=0;
+ end;
+
+
+ function gas_regnum_search(const s:string):Tregister;
+ begin
+ result:=regnumber_table[findreg_by_gasname(s)];
+ end;
+
+
+ function gas_regname(r:Tregister):string;
+ var
+ p : tregisterindex;
+ begin
+ p:=findreg_by_number(r);
+ if p<>0 then
+ result:=gas_regname_table[p]
+ else
+ result:=generic_regname(r);
+ end;
+
+end.
diff --git a/closures/compiler/arm/narmadd.pas b/closures/compiler/arm/narmadd.pas
new file mode 100644
index 0000000000..5aea26a11d
--- /dev/null
+++ b/closures/compiler/arm/narmadd.pas
@@ -0,0 +1,434 @@
+{
+ Copyright (c) 2000-2002 by Florian Klaempfl
+
+ Code generation for add nodes on the ARM
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit narmadd;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,ncgadd,cpubase;
+
+ type
+ tarmaddnode = class(tcgaddnode)
+ private
+ function GetResFlags(unsigned:Boolean):TResFlags;
+ public
+ function pass_1 : tnode;override;
+ protected
+ procedure second_addfloat;override;
+ procedure second_cmpfloat;override;
+ procedure second_cmpordinal;override;
+ procedure second_cmpsmallset;override;
+ procedure second_cmp64bit;override;
+ end;
+
+ implementation
+
+ uses
+ globtype,systems,
+ cutils,verbose,globals,
+ symconst,symdef,paramgr,
+ aasmbase,aasmtai,aasmdata,aasmcpu,defutil,htypechk,
+ cgbase,cgutils,cgcpu,
+ cpuinfo,pass_1,pass_2,regvars,procinfo,
+ cpupara,
+ ncon,nset,nadd,
+ ncgutil,tgobj,rgobj,rgcpu,cgobj,cg64f32;
+
+{*****************************************************************************
+ TSparcAddNode
+*****************************************************************************}
+
+ function tarmaddnode.GetResFlags(unsigned:Boolean):TResFlags;
+ begin
+ case NodeType of
+ equaln:
+ GetResFlags:=F_EQ;
+ unequaln:
+ GetResFlags:=F_NE;
+ else
+ if not(unsigned) then
+ begin
+ if nf_swapped in flags then
+ case NodeType of
+ ltn:
+ GetResFlags:=F_GT;
+ lten:
+ GetResFlags:=F_GE;
+ gtn:
+ GetResFlags:=F_LT;
+ gten:
+ GetResFlags:=F_LE;
+ end
+ else
+ case NodeType of
+ ltn:
+ GetResFlags:=F_LT;
+ lten:
+ GetResFlags:=F_LE;
+ gtn:
+ GetResFlags:=F_GT;
+ gten:
+ GetResFlags:=F_GE;
+ end;
+ end
+ else
+ begin
+ if nf_swapped in Flags then
+ case NodeType of
+ ltn:
+ GetResFlags:=F_HI;
+ lten:
+ GetResFlags:=F_CS;
+ gtn:
+ GetResFlags:=F_CC;
+ gten:
+ GetResFlags:=F_LS;
+ end
+ else
+ case NodeType of
+ ltn:
+ GetResFlags:=F_CC;
+ lten:
+ GetResFlags:=F_LS;
+ gtn:
+ GetResFlags:=F_HI;
+ gten:
+ GetResFlags:=F_CS;
+ end;
+ end;
+ end;
+ end;
+
+
+ procedure tarmaddnode.second_addfloat;
+ var
+ op : TAsmOp;
+ singleprec: boolean;
+ begin
+ pass_left_right;
+ if (nf_swapped in flags) then
+ swapleftright;
+
+ case current_settings.fputype of
+ fpu_fpa,
+ fpu_fpa10,
+ fpu_fpa11:
+ begin
+ { force fpureg as location, left right doesn't matter
+ as both will be in a fpureg }
+ location_force_fpureg(current_asmdata.CurrAsmList,left.location,true);
+ location_force_fpureg(current_asmdata.CurrAsmList,right.location,(left.location.loc<>LOC_CFPUREGISTER));
+
+ location_reset(location,LOC_FPUREGISTER,def_cgsize(resultdef));
+ if left.location.loc<>LOC_CFPUREGISTER then
+ location.register:=left.location.register
+ else
+ location.register:=right.location.register;
+
+ case nodetype of
+ addn :
+ op:=A_ADF;
+ muln :
+ op:=A_MUF;
+ subn :
+ op:=A_SUF;
+ slashn :
+ op:=A_DVF;
+ else
+ internalerror(200308313);
+ end;
+
+ current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg_reg(op,
+ location.register,left.location.register,right.location.register),
+ cgsize2fpuoppostfix[def_cgsize(resultdef)]));
+ end;
+ fpu_vfpv2,
+ fpu_vfpv3:
+ begin
+ { force mmreg as location, left right doesn't matter
+ as both will be in a fpureg }
+ location_force_mmregscalar(current_asmdata.CurrAsmList,left.location,true);
+ location_force_mmregscalar(current_asmdata.CurrAsmList,right.location,true);
+
+ location_reset(location,LOC_MMREGISTER,def_cgsize(resultdef));
+ if left.location.loc<>LOC_CMMREGISTER then
+ location.register:=left.location.register
+ else if right.location.loc<>LOC_CMMREGISTER then
+ location.register:=right.location.register
+ else
+ location.register:=cg.getmmregister(current_asmdata.CurrAsmList,location.size);
+
+ singleprec:=tfloatdef(left.resultdef).floattype=s32real;
+ case nodetype of
+ addn :
+ if singleprec then
+ op:=A_FADDS
+ else
+ op:=A_FADDD;
+ muln :
+ if singleprec then
+ op:=A_FMULS
+ else
+ op:=A_FMULD;
+ subn :
+ if singleprec then
+ op:=A_FSUBS
+ else
+ op:=A_FSUBD;
+ slashn :
+ if singleprec then
+ op:=A_FDIVS
+ else
+ op:=A_FDIVD;
+ else
+ internalerror(2009111401);
+ end;
+
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(op,
+ location.register,left.location.register,right.location.register));
+ end;
+ fpu_soft:
+ { this case should be handled already by pass1 }
+ internalerror(200308252);
+ else
+ internalerror(200308251);
+ end;
+ end;
+
+
+ procedure tarmaddnode.second_cmpfloat;
+ var
+ op: TAsmOp;
+ begin
+ pass_left_right;
+ if (nf_swapped in flags) then
+ swapleftright;
+
+ location_reset(location,LOC_FLAGS,OS_NO);
+ location.resflags:=getresflags(true);
+
+ case current_settings.fputype of
+ fpu_fpa,
+ fpu_fpa10,
+ fpu_fpa11:
+ begin
+ { force fpureg as location, left right doesn't matter
+ as both will be in a fpureg }
+ location_force_fpureg(current_asmdata.CurrAsmList,left.location,true);
+ location_force_fpureg(current_asmdata.CurrAsmList,right.location,true);
+
+ if nodetype in [equaln,unequaln] then
+ current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_CMF,
+ left.location.register,right.location.register),
+ cgsize2fpuoppostfix[def_cgsize(resultdef)]))
+ else
+ current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_CMFE,
+ left.location.register,right.location.register),
+ cgsize2fpuoppostfix[def_cgsize(resultdef)]));
+ end;
+ fpu_vfpv2,
+ fpu_vfpv3:
+ begin
+ location_force_mmregscalar(current_asmdata.CurrAsmList,left.location,true);
+ location_force_mmregscalar(current_asmdata.CurrAsmList,right.location,true);
+
+ if (tfloatdef(left.resultdef).floattype=s32real) then
+ if nodetype in [equaln,unequaln] then
+ op:=A_FCMPS
+ else
+ op:=A_FCMPES
+ else if nodetype in [equaln,unequaln] then
+ op:=A_FCMPD
+ else
+ op:=A_FCMPED;
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op,
+ left.location.register,right.location.register));
+ current_asmdata.CurrAsmList.concat(taicpu.op_none(A_FMSTAT));
+ end;
+ fpu_soft:
+ { this case should be handled already by pass1 }
+ internalerror(2009112404);
+ end;
+
+ location_reset(location,LOC_FLAGS,OS_NO);
+ location.resflags:=getresflags(false);
+ end;
+
+
+ procedure tarmaddnode.second_cmpsmallset;
+ var
+ tmpreg : tregister;
+ begin
+ pass_left_right;
+
+ location_reset(location,LOC_FLAGS,OS_NO);
+
+ force_reg_left_right(false,false);
+
+ case nodetype of
+ equaln:
+ begin
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CMP,left.location.register,right.location.register));
+ location.resflags:=F_EQ;
+ end;
+ unequaln:
+ begin
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CMP,left.location.register,right.location.register));
+ location.resflags:=F_NE;
+ end;
+ lten,
+ gten:
+ begin
+ if (not(nf_swapped in flags) and
+ (nodetype = lten)) or
+ ((nf_swapped in flags) and
+ (nodetype = gten)) then
+ swapleftright;
+ tmpreg:=cg.getintregister(current_asmdata.CurrAsmList,location.size);
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_AND,tmpreg,left.location.register,right.location.register));
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CMP,tmpreg,right.location.register));
+ location.resflags:=F_EQ;
+ end;
+ else
+ internalerror(2004012401);
+ end;
+ end;
+
+
+ procedure tarmaddnode.second_cmp64bit;
+ var
+ unsigned : boolean;
+ oldnodetype : tnodetype;
+ begin
+ pass_left_right;
+ force_reg_left_right(false,false);
+
+ unsigned:=not(is_signed(left.resultdef)) or
+ not(is_signed(right.resultdef));
+
+ { operation requiring proper N, Z and C flags ? }
+ if unsigned or (nodetype in [equaln,unequaln]) then
+ begin
+ location_reset(location,LOC_FLAGS,OS_NO);
+ location.resflags:=getresflags(unsigned);
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CMP,left.location.register64.reghi,right.location.register64.reghi));
+ if current_settings.cputype in cpu_thumb2 then
+ current_asmdata.CurrAsmList.concat(taicpu.op_cond(A_IT, C_EQ));
+ current_asmdata.CurrAsmList.concat(setcondition(taicpu.op_reg_reg(A_CMP,left.location.register64.reglo,right.location.register64.reglo),C_EQ));
+ end
+ else
+ { operation requiring proper N, Z and V flags ? }
+ begin
+ location_reset(location,LOC_JUMP,OS_NO);
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CMP,left.location.register64.reghi,right.location.register64.reghi));
+ { the jump the sequence is a little bit hairy }
+ case nodetype of
+ ltn,gtn:
+ begin
+ cg.a_jmp_flags(current_asmdata.CurrAsmList,getresflags(false),current_procinfo.CurrTrueLabel);
+ { cheat a little bit for the negative test }
+ toggleflag(nf_swapped);
+ cg.a_jmp_flags(current_asmdata.CurrAsmList,getresflags(false),current_procinfo.CurrFalseLabel);
+ toggleflag(nf_swapped);
+ end;
+ lten,gten:
+ begin
+ oldnodetype:=nodetype;
+ if nodetype=lten then
+ nodetype:=ltn
+ else
+ nodetype:=gtn;
+ cg.a_jmp_flags(current_asmdata.CurrAsmList,getresflags(unsigned),current_procinfo.CurrTrueLabel);
+ { cheat for the negative test }
+ if nodetype=ltn then
+ nodetype:=gtn
+ else
+ nodetype:=ltn;
+ cg.a_jmp_flags(current_asmdata.CurrAsmList,getresflags(unsigned),current_procinfo.CurrFalseLabel);
+ nodetype:=oldnodetype;
+ end;
+ end;
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CMP,left.location.register64.reglo,right.location.register64.reglo));
+ { the comparisaion of the low dword have to be
+ always unsigned! }
+ cg.a_jmp_flags(current_asmdata.CurrAsmList,getresflags(true),current_procinfo.CurrTrueLabel);
+ cg.a_jmp_always(current_asmdata.CurrAsmList,current_procinfo.CurrFalseLabel);
+ end;
+ end;
+
+
+ function tarmaddnode.pass_1 : tnode;
+ var
+ unsigned : boolean;
+ begin
+ result:=inherited pass_1;
+
+ if not(assigned(result)) then
+ begin
+ unsigned:=not(is_signed(left.resultdef)) or
+ not(is_signed(right.resultdef));
+
+ if is_64bit(left.resultdef) and
+ ((nodetype in [equaln,unequaln]) or
+ (unsigned and (nodetype in [ltn,lten,gtn,gten]))
+ ) then
+ expectloc:=LOC_FLAGS;
+ end;
+ end;
+
+
+ procedure tarmaddnode.second_cmpordinal;
+ var
+ unsigned : boolean;
+ tmpreg : tregister;
+ b : byte;
+ begin
+ pass_left_right;
+ force_reg_left_right(true,true);
+
+ unsigned:=not(is_signed(left.resultdef)) or
+ not(is_signed(right.resultdef));
+
+ if right.location.loc = LOC_CONSTANT then
+ begin
+ if is_shifter_const(right.location.value,b) then
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_CMP,left.location.register,right.location.value))
+ else
+ begin
+ tmpreg:=cg.getintregister(current_asmdata.CurrAsmList,location.size);
+ cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_INT,
+ right.location.value,tmpreg);
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CMP,left.location.register,tmpreg));
+ end;
+ end
+ else
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CMP,left.location.register,right.location.register));
+
+ location_reset(location,LOC_FLAGS,OS_NO);
+ location.resflags:=getresflags(unsigned);
+ end;
+
+begin
+ caddnode:=tarmaddnode;
+end.
diff --git a/closures/compiler/arm/narmcal.pas b/closures/compiler/arm/narmcal.pas
new file mode 100644
index 0000000000..da2b510187
--- /dev/null
+++ b/closures/compiler/arm/narmcal.pas
@@ -0,0 +1,74 @@
+{
+ Copyright (c) 2002 by Florian Klaempfl
+
+ Implements the ARM specific part of call nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit narmcal;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ symdef,node,ncal,ncgcal;
+
+ type
+ tarmcallnode = class(tcgcallnode)
+ procedure set_result_location(realresdef: tstoreddef);override;
+ end;
+
+implementation
+
+ uses
+ verbose,globtype,globals,aasmdata,
+ symconst,
+ cgbase,
+ cpubase,cpuinfo,
+ ncgutil,
+ paramgr;
+
+ procedure tarmcallnode.set_result_location(realresdef: tstoreddef);
+ begin
+ if (realresdef.typ=floatdef) and
+ ((cs_fp_emulation in current_settings.moduleswitches) or
+ (current_settings.fputype in [fpu_vfpv2,fpu_vfpv3])) then
+ begin
+ { keep the fpu values in integer registers for now, the code
+ generator will move them to memory or an mmregister when necessary
+ (avoids double moves in case a function result is assigned to
+ another function result, or passed as a parameter) }
+ case retloc.size of
+ OS_32,
+ OS_F32:
+ location_allocate_register(current_asmdata.CurrAsmList,location,s32inttype,false);
+ OS_64,
+ OS_F64:
+ location_allocate_register(current_asmdata.CurrAsmList,location,s64inttype,false);
+ else
+ internalerror(2010053008);
+ end
+ end
+ else
+ inherited;
+ end;
+
+
+begin
+ ccallnode:=tarmcallnode;
+end.
diff --git a/closures/compiler/arm/narmcnv.pas b/closures/compiler/arm/narmcnv.pas
new file mode 100644
index 0000000000..9dcfe1b48f
--- /dev/null
+++ b/closures/compiler/arm/narmcnv.pas
@@ -0,0 +1,343 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate ARM assembler for type converting nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit narmcnv;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,ncnv,ncgcnv,defcmp;
+
+ type
+ tarmtypeconvnode = class(tcgtypeconvnode)
+ protected
+ function first_int_to_real: tnode;override;
+ { procedure second_int_to_int;override; }
+ { procedure second_string_to_string;override; }
+ { procedure second_cstring_to_pchar;override; }
+ { procedure second_string_to_chararray;override; }
+ { procedure second_array_to_pointer;override; }
+ // function first_int_to_real: tnode; override;
+ { procedure second_pointer_to_array;override; }
+ { procedure second_chararray_to_string;override; }
+ { procedure second_char_to_string;override; }
+ procedure second_int_to_real;override;
+ // procedure second_real_to_real;override;
+ { procedure second_cord_to_pointer;override; }
+ { procedure second_proc_to_procvar;override; }
+ { procedure second_bool_to_int;override; }
+ procedure second_int_to_bool;override;
+ { procedure second_load_smallset;override; }
+ { procedure second_ansistring_to_pchar;override; }
+ { procedure second_pchar_to_string;override; }
+ { procedure second_class_to_intf;override; }
+ { procedure second_char_to_char;override; }
+ end;
+
+implementation
+
+ uses
+ verbose,globtype,globals,systems,
+ symconst,symdef,aasmbase,aasmtai,aasmdata,
+ defutil,
+ cgbase,cgutils,
+ pass_1,pass_2,procinfo,
+ ncon,ncal,
+ ncgutil,
+ cpubase,cpuinfo,aasmcpu,
+ rgobj,tgobj,cgobj,cgcpu;
+
+
+{*****************************************************************************
+ FirstTypeConv
+*****************************************************************************}
+
+ function tarmtypeconvnode.first_int_to_real: tnode;
+ var
+ fname: string[19];
+ begin
+ if cs_fp_emulation in current_settings.moduleswitches then
+ result:=inherited first_int_to_real
+ else
+ begin
+ { converting a 64bit integer to a float requires a helper }
+ if is_64bitint(left.resultdef) or
+ is_currency(left.resultdef) then
+ begin
+ { hack to avoid double division by 10000, as it's
+ already done by typecheckpass.resultdef_int_to_real }
+ if is_currency(left.resultdef) then
+ left.resultdef := s64inttype;
+ if is_signed(left.resultdef) then
+ fname := 'fpc_int64_to_double'
+ else
+ fname := 'fpc_qword_to_double';
+ result := ccallnode.createintern(fname,ccallparanode.create(
+ left,nil));
+ left:=nil;
+ if (tfloatdef(resultdef).floattype=s32real) then
+ inserttypeconv(result,s32floattype);
+ firstpass(result);
+ exit;
+ end
+ else
+ { other integers are supposed to be 32 bit }
+ begin
+ if is_signed(left.resultdef) then
+ inserttypeconv(left,s32inttype)
+ else
+ inserttypeconv(left,u32inttype);
+ firstpass(left);
+ end;
+ result := nil;
+ case current_settings.fputype of
+ fpu_fpa,
+ fpu_fpa10,
+ fpu_fpa11:
+ expectloc:=LOC_FPUREGISTER;
+ fpu_vfpv2,
+ fpu_vfpv3:
+ expectloc:=LOC_MMREGISTER;
+ else
+ internalerror(2009112702);
+ end;
+ end;
+ end;
+
+
+ procedure tarmtypeconvnode.second_int_to_real;
+ const
+ signedprec2vfpop: array[boolean,OS_F32..OS_F64] of tasmop =
+ ((A_FUITOS,A_FUITOD),
+ (A_FSITOS,A_FSITOD));
+ var
+ instr : taicpu;
+ href : treference;
+ l1,l2 : tasmlabel;
+ hregister : tregister;
+ signed : boolean;
+ begin
+ case current_settings.fputype of
+ fpu_fpa,
+ fpu_fpa10,
+ fpu_fpa11:
+ begin
+ { convert first to double to avoid precision loss }
+ location_reset(location,LOC_FPUREGISTER,def_cgsize(resultdef));
+ location_force_reg(current_asmdata.CurrAsmList,left.location,OS_32,true);
+ location.register:=cg.getfpuregister(current_asmdata.CurrAsmList,location.size);
+ instr:=taicpu.op_reg_reg(A_FLT,location.register,left.location.register);
+ if is_signed(left.resultdef) then
+ begin
+ instr.oppostfix:=cgsize2fpuoppostfix[def_cgsize(resultdef)];
+ current_asmdata.CurrAsmList.concat(instr);
+ end
+ else
+ begin
+ { flt does a signed load, fix this }
+ case tfloatdef(resultdef).floattype of
+ s32real,
+ s64real:
+ begin
+ { converting dword to s64real first and cut off at the end avoids precision loss }
+ instr.oppostfix:=PF_D;
+ current_asmdata.CurrAsmList.concat(instr);
+
+ current_asmdata.getdatalabel(l1);
+ current_asmdata.getjumplabel(l2);
+ reference_reset_symbol(href,l1,0,const_align(8));
+
+ current_asmdata.CurrAsmList.concat(Taicpu.op_reg_const(A_CMP,left.location.register,0));
+ cg.a_jmp_flags(current_asmdata.CurrAsmList,F_GE,l2);
+
+ hregister:=cg.getfpuregister(current_asmdata.CurrAsmList,OS_F64);
+ new_section(current_asmdata.asmlists[al_typedconsts],sec_rodata_norel,l1.name,const_align(8));
+ current_asmdata.asmlists[al_typedconsts].concat(Tai_label.Create(l1));
+ { I got this constant from a test program (FK) }
+ current_asmdata.asmlists[al_typedconsts].concat(Tai_const.Create_32bit($41f00000));
+ current_asmdata.asmlists[al_typedconsts].concat(Tai_const.Create_32bit(0));
+
+ cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,OS_F64,OS_F64,href,hregister);
+ current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg_reg(A_ADF,location.register,hregister,location.register),PF_D));
+ cg.a_label(current_asmdata.CurrAsmList,l2);
+
+ { cut off if we should convert to single }
+ if tfloatdef(resultdef).floattype=s32real then
+ begin
+ hregister:=location.register;
+ location.register:=cg.getfpuregister(current_asmdata.CurrAsmList,location.size);
+ current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_MVF,location.register,hregister),PF_S));
+ end;
+ end;
+ else
+ internalerror(200410031);
+ end;
+ end;
+ end;
+ fpu_vfpv2,
+ fpu_vfpv3:
+ begin
+ location_reset(location,LOC_MMREGISTER,def_cgsize(resultdef));
+ signed:=left.location.size=OS_S32;
+ location_force_mmregscalar(current_asmdata.CurrAsmList,left.location,false);
+ if (left.location.size<>OS_F32) then
+ internalerror(2009112703);
+ if left.location.size<>location.size then
+ location.register:=cg.getmmregister(current_asmdata.CurrAsmList,location.size)
+ else
+ location.register:=left.location.register;
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(
+ signedprec2vfpop[signed,location.size],location.register,left.location.register));
+ end;
+ end;
+ end;
+
+
+ procedure tarmtypeconvnode.second_int_to_bool;
+ var
+ hreg1,
+ hregister : tregister;
+ href : treference;
+ resflags : tresflags;
+ hlabel,oldTrueLabel,oldFalseLabel : tasmlabel;
+ newsize : tcgsize;
+ begin
+ oldTrueLabel:=current_procinfo.CurrTrueLabel;
+ oldFalseLabel:=current_procinfo.CurrFalseLabel;
+ current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
+ current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel);
+ secondpass(left);
+ if codegenerror then
+ exit;
+
+ { Explicit typecasts from any ordinal type to a boolean type }
+ { must not change the ordinal value }
+ if (nf_explicit in flags) and
+ not(left.location.loc in [LOC_FLAGS,LOC_JUMP]) then
+ begin
+ location_copy(location,left.location);
+ newsize:=def_cgsize(resultdef);
+ { change of size? change sign only if location is LOC_(C)REGISTER? Then we have to sign/zero-extend }
+ if (tcgsize2size[newsize]<>tcgsize2size[left.location.size]) or
+ ((newsize<>left.location.size) and (location.loc in [LOC_REGISTER,LOC_CREGISTER])) then
+ location_force_reg(current_asmdata.CurrAsmList,location,newsize,true)
+ else
+ location.size:=newsize;
+ current_procinfo.CurrTrueLabel:=oldTrueLabel;
+ current_procinfo.CurrFalseLabel:=oldFalseLabel;
+ exit;
+ end;
+
+ { Load left node into flag F_NE/F_E }
+ resflags:=F_NE;
+ case left.location.loc of
+ LOC_CREFERENCE,
+ LOC_REFERENCE :
+ begin
+ if left.location.size in [OS_64,OS_S64] then
+ begin
+ hregister:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+ cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_32,OS_32,left.location.reference,hregister);
+ href:=left.location.reference;
+ inc(href.offset,4);
+ tcgarm(cg).cgsetflags:=true;
+ cg.a_op_ref_reg(current_asmdata.CurrAsmList,OP_OR,OS_32,href,hregister);
+ tcgarm(cg).cgsetflags:=false;
+ end
+ else
+ begin
+ location_force_reg(current_asmdata.CurrAsmList,left.location,left.location.size,true);
+ tcgarm(cg).cgsetflags:=true;
+ cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_OR,left.location.size,left.location.register,left.location.register);
+ tcgarm(cg).cgsetflags:=false;
+ end;
+ end;
+ LOC_FLAGS :
+ begin
+ resflags:=left.location.resflags;
+ end;
+ LOC_REGISTER,LOC_CREGISTER :
+ begin
+ if left.location.size in [OS_64,OS_S64] then
+ begin
+ hregister:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
+ cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_32,OS_32,left.location.register64.reglo,hregister);
+ tcgarm(cg).cgsetflags:=true;
+ cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_OR,OS_32,left.location.register64.reghi,hregister);
+ tcgarm(cg).cgsetflags:=false;
+ end
+ else
+ begin
+ tcgarm(cg).cgsetflags:=true;
+ cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_OR,left.location.size,left.location.register,left.location.register);
+ tcgarm(cg).cgsetflags:=false;
+ end;
+ end;
+ LOC_JUMP :
+ begin
+ hregister:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+ current_asmdata.getjumplabel(hlabel);
+ cg.a_label(current_asmdata.CurrAsmList,current_procinfo.CurrTrueLabel);
+ cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_INT,1,hregister);
+ cg.a_jmp_always(current_asmdata.CurrAsmList,hlabel);
+ cg.a_label(current_asmdata.CurrAsmList,current_procinfo.CurrFalseLabel);
+ cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_INT,0,hregister);
+ cg.a_label(current_asmdata.CurrAsmList,hlabel);
+ tcgarm(cg).cgsetflags:=true;
+ cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_OR,OS_INT,hregister,hregister);
+ tcgarm(cg).cgsetflags:=false;
+ end;
+ else
+ internalerror(200311301);
+ end;
+ { load flags to register }
+ location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
+ hreg1:=cg.getintregister(current_asmdata.CurrAsmList,location.size);
+ cg.g_flags2reg(current_asmdata.CurrAsmList,location.size,resflags,hreg1);
+ if (is_cbool(resultdef)) then
+ cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_NEG,location.size,hreg1,hreg1);
+
+{$ifndef cpu64bitalu}
+ if (location.size in [OS_64,OS_S64]) then
+ begin
+ location.register64.reglo:=hreg1;
+ location.register64.reghi:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
+ if (is_cbool(resultdef)) then
+ { reglo is either 0 or -1 -> reghi has to become the same }
+ cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_32,OS_32,location.register64.reglo,location.register64.reghi)
+ else
+ { unsigned }
+ cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_32,0,location.register64.reghi);
+ end
+ else
+{$endif cpu64bitalu}
+ location.register:=hreg1;
+
+ current_procinfo.CurrTrueLabel:=oldTrueLabel;
+ current_procinfo.CurrFalseLabel:=oldFalseLabel;
+ end;
+
+
+begin
+ ctypeconvnode:=tarmtypeconvnode;
+end.
diff --git a/closures/compiler/arm/narmcon.pas b/closures/compiler/arm/narmcon.pas
new file mode 100644
index 0000000000..edfeedc529
--- /dev/null
+++ b/closures/compiler/arm/narmcon.pas
@@ -0,0 +1,140 @@
+{
+ Copyright (c) 2005 by Florian Klaempfl
+
+ Code generation for const nodes on the ARM
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit narmcon;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,ncgcon,cpubase;
+
+ type
+ tarmrealconstnode = class(tcgrealconstnode)
+ procedure pass_generate_code;override;
+ end;
+
+ implementation
+
+ uses
+ verbose,
+ globtype,globals,
+ cpuinfo,
+ aasmbase,aasmtai,aasmdata,
+ symconst,symdef,
+ defutil,
+ cgbase,cgutils,
+ procinfo,
+ ncon;
+
+{*****************************************************************************
+ TARMREALCONSTNODE
+*****************************************************************************}
+
+ procedure tarmrealconstnode.pass_generate_code;
+ { I suppose the parser/pass_1 must make sure the generated real }
+ { constants are actually supported by the target processor? (JM) }
+ const
+ floattype2ait:array[tfloattype] of taitype=
+ (ait_real_32bit,ait_real_64bit,ait_real_80bit,ait_real_80bit,ait_comp_64bit,ait_comp_64bit,ait_real_128bit);
+ var
+ lastlabel : tasmlabel;
+ realait : taitype;
+ hiloswapped : boolean;
+
+ begin
+ location_reset_ref(location,LOC_CREFERENCE,def_cgsize(resultdef),4);
+ lastlabel:=nil;
+ realait:=floattype2ait[tfloatdef(resultdef).floattype];
+ hiloswapped:=is_double_hilo_swapped;
+ { const already used ? }
+ if not assigned(lab_real) then
+ begin
+ current_asmdata.getjumplabel(lastlabel);
+ lab_real:=lastlabel;
+ current_procinfo.aktlocaldata.concat(Tai_label.Create(lastlabel));
+ location.reference.symboldata:=current_procinfo.aktlocaldata.last;
+ case realait of
+ ait_real_32bit :
+ begin
+ current_procinfo.aktlocaldata.concat(Tai_real_32bit.Create(ts32real(value_real)));
+ { range checking? }
+ if ((cs_check_range in current_settings.localswitches) or
+ (cs_check_overflow in current_settings.localswitches)) and
+ (tai_real_32bit(current_procinfo.aktlocaldata.last).value=MathInf.Value) then
+ Message(parser_e_range_check_error);
+ end;
+
+ ait_real_64bit :
+ begin
+ if hiloswapped then
+ current_procinfo.aktlocaldata.concat(Tai_real_64bit.Create_hiloswapped(ts64real(value_real)))
+ else
+ current_procinfo.aktlocaldata.concat(Tai_real_64bit.Create(ts64real(value_real)));
+
+ { range checking? }
+ if ((cs_check_range in current_settings.localswitches) or
+ (cs_check_overflow in current_settings.localswitches)) and
+ (tai_real_64bit(current_procinfo.aktlocaldata.last).value=MathInf.Value) then
+ Message(parser_e_range_check_error);
+ end;
+
+ ait_real_80bit :
+ begin
+ current_procinfo.aktlocaldata.concat(Tai_real_80bit.Create(value_real,tfloatdef(resultdef).size));
+
+ { range checking? }
+ if ((cs_check_range in current_settings.localswitches) or
+ (cs_check_overflow in current_settings.localswitches)) and
+ (tai_real_80bit(current_procinfo.aktlocaldata.last).value=MathInf.Value) then
+ Message(parser_e_range_check_error);
+ end;
+{$ifdef cpufloat128}
+ ait_real_128bit :
+ begin
+ current_procinfo.aktlocaldata.concat(Tai_real_128bit.Create(value_real));
+
+ { range checking? }
+ if ((cs_check_range in current_settings.localswitches) or
+ (cs_check_overflow in current_settings.localswitches)) and
+ (tai_real_128bit(current_procinfo.aktlocaldata.last).value=MathInf.Value) then
+ Message(parser_e_range_check_error);
+ end;
+{$endif cpufloat128}
+
+ { the round is necessary for native compilers where comp isn't a float }
+ ait_comp_64bit :
+ if (value_real>9223372036854775807.0) or (value_real<-9223372036854775808.0) then
+ message(parser_e_range_check_error)
+ else
+ current_procinfo.aktlocaldata.concat(Tai_comp_64bit.Create(round(value_real)));
+ else
+ internalerror(2005092401);
+ end;
+ end;
+ location.reference.symbol:=lab_real;
+ location.reference.base:=NR_R15;
+ end;
+
+begin
+ crealconstnode:=tarmrealconstnode;
+end.
diff --git a/closures/compiler/arm/narminl.pas b/closures/compiler/arm/narminl.pas
new file mode 100644
index 0000000000..28fce33de9
--- /dev/null
+++ b/closures/compiler/arm/narminl.pas
@@ -0,0 +1,337 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generates ARM inline nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit narminl;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,ninl,ncginl;
+
+ type
+ tarminlinenode = class(tcgInlineNode)
+ function first_abs_real: tnode; override;
+ function first_sqr_real: tnode; override;
+ function first_sqrt_real: tnode; override;
+ { atn,sin,cos,lgn isn't supported by the linux fpe
+ function first_arctan_real: tnode; override;
+ function first_ln_real: tnode; override;
+ function first_cos_real: tnode; override;
+ function first_sin_real: tnode; override;
+ }
+ procedure second_abs_real; override;
+ procedure second_sqr_real; override;
+ procedure second_sqrt_real; override;
+ { atn,sin,cos,lgn isn't supported by the linux fpe
+ procedure second_arctan_real; override;
+ procedure second_ln_real; override;
+ procedure second_cos_real; override;
+ procedure second_sin_real; override;
+ }
+ procedure second_prefetch; override;
+ private
+ procedure load_fpu_location(out singleprec: boolean);
+ end;
+
+
+implementation
+
+ uses
+ globtype,systems,
+ cutils,verbose,globals,fmodule,
+ cpuinfo,
+ symconst,symdef,
+ aasmbase,aasmtai,aasmdata,aasmcpu,
+ cgbase,cgutils,
+ pass_1,pass_2,
+ cpubase,paramgr,
+ nbas,ncon,ncal,ncnv,nld,
+ tgobj,ncgutil,cgobj,cg64f32,rgobj,rgcpu,cgcpu;
+
+{*****************************************************************************
+ tarminlinenode
+*****************************************************************************}
+
+ procedure tarminlinenode.load_fpu_location(out singleprec: boolean);
+ begin
+ secondpass(left);
+ case current_settings.fputype of
+ fpu_fpa,
+ fpu_fpa10,
+ fpu_fpa11:
+ begin
+ location_force_fpureg(current_asmdata.CurrAsmList,left.location,true);
+ location_copy(location,left.location);
+ if left.location.loc=LOC_CFPUREGISTER then
+ begin
+ location.register:=cg.getfpuregister(current_asmdata.CurrAsmList,location.size);
+ location.loc := LOC_FPUREGISTER;
+ end;
+ end;
+ fpu_vfpv2,
+ fpu_vfpv3:
+ begin
+ location_force_mmregscalar(current_asmdata.CurrAsmList,left.location,true);
+ location_copy(location,left.location);
+ if left.location.loc=LOC_CMMREGISTER then
+ begin
+ location.register:=cg.getmmregister(current_asmdata.CurrAsmList,location.size);
+ location.loc := LOC_MMREGISTER;
+ end;
+ end;
+ else
+ internalerror(2009111801);
+ end;
+ singleprec:=tfloatdef(left.resultdef).floattype=s32real;
+ end;
+
+
+ function tarminlinenode.first_abs_real : tnode;
+ begin
+ if (cs_fp_emulation in current_settings.moduleswitches) then
+ result:=inherited first_abs_real
+ else
+ begin
+ case current_settings.fputype of
+ fpu_fpa,
+ fpu_fpa10,
+ fpu_fpa11:
+ expectloc:=LOC_FPUREGISTER;
+ fpu_vfpv2,
+ fpu_vfpv3:
+ expectloc:=LOC_MMREGISTER;
+ else
+ internalerror(2009112401);
+ end;
+ first_abs_real:=nil;
+ end;
+ end;
+
+
+ function tarminlinenode.first_sqr_real : tnode;
+ begin
+ if (cs_fp_emulation in current_settings.moduleswitches) then
+ result:=inherited first_sqr_real
+ else
+ begin
+ case current_settings.fputype of
+ fpu_fpa,
+ fpu_fpa10,
+ fpu_fpa11:
+ expectloc:=LOC_FPUREGISTER;
+ fpu_vfpv2,
+ fpu_vfpv3:
+ expectloc:=LOC_MMREGISTER;
+ else
+ internalerror(2009112402);
+ end;
+ first_sqr_real:=nil;
+ end;
+ end;
+
+
+ function tarminlinenode.first_sqrt_real : tnode;
+ begin
+ if cs_fp_emulation in current_settings.moduleswitches then
+ result:=inherited first_sqrt_real
+ else
+ begin
+ case current_settings.fputype of
+ fpu_fpa,
+ fpu_fpa10,
+ fpu_fpa11:
+ expectloc:=LOC_FPUREGISTER;
+ fpu_vfpv2,
+ fpu_vfpv3:
+ expectloc:=LOC_MMREGISTER;
+ else
+ internalerror(2009112403);
+ end;
+ first_sqrt_real := nil;
+ end;
+ end;
+
+
+ { atn,sin,cos,lgn isn't supported by the linux fpe
+ function tarminlinenode.first_arctan_real: tnode;
+ begin
+ expectloc:=LOC_FPUREGISTER;
+ result:=nil;
+ end;
+
+
+ function tarminlinenode.first_ln_real: tnode;
+ begin
+ expectloc:=LOC_FPUREGISTER;
+ result:=nil;
+ end;
+
+ function tarminlinenode.first_cos_real: tnode;
+ begin
+ expectloc:=LOC_FPUREGISTER;
+ result:=nil;
+ end;
+
+
+ function tarminlinenode.first_sin_real: tnode;
+ begin
+ expectloc:=LOC_FPUREGISTER;
+ result:=nil;
+ end;
+ }
+
+
+ procedure tarminlinenode.second_abs_real;
+ var
+ singleprec: boolean;
+ op: TAsmOp;
+ begin
+ load_fpu_location(singleprec);
+ case current_settings.fputype of
+ fpu_fpa,
+ fpu_fpa10,
+ fpu_fpa11:
+ current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_ABS,location.register,left.location.register),get_fpu_postfix(resultdef)));
+ fpu_vfpv2,
+ fpu_vfpv3:
+ begin
+ if singleprec then
+ op:=A_FABSS
+ else
+ op:=A_FABSD;
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op,location.register,left.location.register));
+ end;
+ else
+ internalerror(2009111402);
+ end;
+ end;
+
+
+ procedure tarminlinenode.second_sqr_real;
+ var
+ singleprec: boolean;
+ op: TAsmOp;
+ begin
+ load_fpu_location(singleprec);
+ case current_settings.fputype of
+ fpu_fpa,
+ fpu_fpa10,
+ fpu_fpa11:
+ current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg_reg(A_MUF,location.register,left.location.register,left.location.register),get_fpu_postfix(resultdef)));
+ fpu_vfpv2,
+ fpu_vfpv3:
+ begin
+ if singleprec then
+ op:=A_FMULS
+ else
+ op:=A_FMULD;
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(op,location.register,left.location.register,left.location.register));
+ end;
+ else
+ internalerror(2009111403);
+ end;
+ end;
+
+
+ procedure tarminlinenode.second_sqrt_real;
+ var
+ singleprec: boolean;
+ op: TAsmOp;
+ begin
+ load_fpu_location(singleprec);
+ case current_settings.fputype of
+ fpu_fpa,
+ fpu_fpa10,
+ fpu_fpa11:
+ current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_SQT,location.register,left.location.register),get_fpu_postfix(resultdef)));
+ fpu_vfpv2,
+ fpu_vfpv3:
+ begin
+ if singleprec then
+ op:=A_FSQRTS
+ else
+ op:=A_FSQRTD;
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op,location.register,left.location.register));
+ end;
+ else
+ internalerror(2009111402);
+ end;
+ end;
+
+
+ { atn, sin, cos, lgn isn't supported by the linux fpe
+ procedure tarminlinenode.second_arctan_real;
+ begin
+ load_fpu_location;
+ current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_ATN,location.register,left.location.register),get_fpu_postfix(resultdef)));
+ end;
+
+
+ procedure tarminlinenode.second_ln_real;
+ begin
+ load_fpu_location;
+ current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_LGN,location.register,left.location.register),get_fpu_postfix(resultdef)));
+ end;
+
+ procedure tarminlinenode.second_cos_real;
+ begin
+ load_fpu_location;
+ current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_COS,location.register,left.location.register),get_fpu_postfix(resultdef)));
+ end;
+
+
+ procedure tarminlinenode.second_sin_real;
+ begin
+ load_fpu_location;
+ current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_SIN,location.register,left.location.register),get_fpu_postfix(resultdef)));
+ end;
+ }
+
+ procedure tarminlinenode.second_prefetch;
+ var
+ ref : treference;
+ r : tregister;
+ begin
+ if current_settings.cputype>=cpu_armv5 then
+ begin
+ secondpass(left);
+ case left.location.loc of
+ LOC_CREFERENCE,
+ LOC_REFERENCE:
+ begin
+ r:=cg.getintregister(current_asmdata.CurrAsmList,OS_ADDR);
+ cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,left.location.reference,r);
+ reference_reset_base(ref,r,0,left.location.reference.alignment);
+ { since the address might be nil we can't use ldr for older cpus }
+ current_asmdata.CurrAsmList.concat(taicpu.op_ref(A_PLD,ref));
+ end;
+ else
+ internalerror(200402021);
+ end;
+ end;
+ end;
+
+
+begin
+ cinlinenode:=tarminlinenode;
+end.
diff --git a/closures/compiler/arm/narmmat.pas b/closures/compiler/arm/narmmat.pas
new file mode 100644
index 0000000000..90e7abc2f0
--- /dev/null
+++ b/closures/compiler/arm/narmmat.pas
@@ -0,0 +1,357 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate ARM assembler for math nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit narmmat;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,nmat,ncgmat;
+
+ type
+ tarmmoddivnode = class(tmoddivnode)
+ function first_moddivint: tnode;override;
+ procedure pass_generate_code;override;
+ end;
+
+ tarmnotnode = class(tcgnotnode)
+ procedure second_boolean;override;
+ end;
+
+ tarmunaryminusnode = class(tcgunaryminusnode)
+ procedure second_float;override;
+ end;
+
+
+implementation
+
+ uses
+ globtype,systems,
+ cutils,verbose,globals,constexp,
+ aasmbase,aasmcpu,aasmtai,aasmdata,
+ defutil,
+ cgbase,cgobj,cgutils,
+ pass_2,procinfo,
+ ncon,
+ cpubase,cpuinfo,
+ ncgutil,cgcpu,
+ nadd,pass_1,symdef;
+
+{*****************************************************************************
+ TARMMODDIVNODE
+*****************************************************************************}
+
+ function tarmmoddivnode.first_moddivint: tnode;
+ var
+ power : longint;
+ begin
+ if (right.nodetype=ordconstn) and
+ (nodetype=divn) and
+ (ispowerof2(tordconstnode(right).value,power) or
+ (tordconstnode(right).value=1) or
+ (tordconstnode(right).value=int64(-1))
+ ) and
+ not(is_64bitint(resultdef)) then
+ result:=nil
+ else if (current_settings.cputype in [cpu_armv7m]) and
+ (nodetype=divn) and
+ not(is_64bitint(resultdef)) then
+ result:=nil
+ else if (current_settings.cputype in [cpu_armv7m]) and
+ (nodetype=modn) and
+ not(is_64bitint(resultdef)) then
+ begin
+ if (right.nodetype=ordconstn) and
+ ispowerof2(tordconstnode(right).value,power) and
+ (tordconstnode(right).value<=256) and
+ (tordconstnode(right).value>0) then
+ result:=caddnode.create(andn,left,cordconstnode.create(tordconstnode(right).value-1,sinttype,false))
+ else
+ begin
+ result:=caddnode.create(subn,left,caddnode.create(muln,right.getcopy, cmoddivnode.Create(divn,left.getcopy,right.getcopy)));
+ right:=nil;
+ end;
+ left:=nil;
+ end
+ else
+ result:=inherited first_moddivint;
+ end;
+
+
+ procedure tarmmoddivnode.pass_generate_code;
+ var
+ power : longint;
+ numerator,
+ helper1,
+ helper2,
+ resultreg : tregister;
+ size : Tcgsize;
+ so : tshifterop;
+
+ procedure genOrdConstNodeDiv;
+ begin
+ if tordconstnode(right).value=0 then
+ internalerror(2005061701)
+ else if tordconstnode(right).value=1 then
+ cg.a_load_reg_reg(current_asmdata.CurrAsmList, OS_INT, OS_INT, numerator, resultreg)
+ else if (tordconstnode(right).value = int64(-1)) then
+ begin
+ // note: only in the signed case possible..., may overflow
+ current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_MVN,
+ resultreg,numerator),toppostfix(ord(cs_check_overflow in current_settings.localswitches)*ord(PF_S))));
+ end
+ else if ispowerof2(tordconstnode(right).value,power) then
+ begin
+ if (is_signed(right.resultdef)) then
+ begin
+ helper1:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+ helper2:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+ shifterop_reset(so);
+ so.shiftmode:=SM_ASR;
+ so.shiftimm:=31;
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_shifterop(A_MOV,helper1,numerator,so));
+ shifterop_reset(so);
+ so.shiftmode:=SM_LSR;
+ so.shiftimm:=32-power;
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg_shifterop(A_ADD,helper2,numerator,helper1,so));
+ shifterop_reset(so);
+ so.shiftmode:=SM_ASR;
+ so.shiftimm:=power;
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_shifterop(A_MOV,resultreg,helper2,so));
+ end
+ else
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SHR,OS_INT,power,numerator,resultreg)
+ end;
+ end;
+
+{
+ procedure genOrdConstNodeMod;
+ var
+ modreg, maskreg, tempreg : tregister;
+ begin
+ if (tordconstnode(right).value = 0) then begin
+ internalerror(2005061702);
+ end
+ else if (abs(tordconstnode(right).value.svalue) = 1) then
+ begin
+ // x mod +/-1 is always zero
+ cg.a_load_const_reg(current_asmdata.CurrAsmList, OS_INT, 0, resultreg);
+ end
+ else if (ispowerof2(tordconstnode(right).value, power)) then
+ begin
+ if (is_signed(right.resultdef)) then begin
+
+ tempreg := cg.getintregister(current_asmdata.CurrAsmList, OS_INT);
+ maskreg := cg.getintregister(current_asmdata.CurrAsmList, OS_INT);
+ modreg := cg.getintregister(current_asmdata.CurrAsmList, OS_INT);
+
+ cg.a_load_const_reg(current_asmdata.CurrAsmList, OS_INT, abs(tordconstnode(right).value.svalue)-1, modreg);
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_SAR, OS_INT, 31, numerator, maskreg);
+ cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList, OP_AND, OS_INT, numerator, modreg, tempreg);
+
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_ANDC, maskreg, maskreg, modreg));
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_const(A_SUBFIC, modreg, tempreg, 0));
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SUBFE, modreg, modreg, modreg));
+ cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList, OP_AND, OS_INT, modreg, maskreg, maskreg);
+ cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList, OP_OR, OS_INT, maskreg, tempreg, resultreg);
+ end else begin
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_AND, OS_INT, tordconstnode(right).value.svalue-1, numerator, resultreg);
+ end;
+ end else begin
+ genOrdConstNodeDiv();
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_MUL, OS_INT, tordconstnode(right).value.svalue, resultreg, resultreg);
+ cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList, OP_SUB, OS_INT, resultreg, numerator, resultreg);
+ end;
+ end;
+}
+
+ begin
+ secondpass(left);
+ secondpass(right);
+
+ if (current_settings.cputype in [cpu_armv7m]) and
+ (nodetype=divn) and
+ not(is_64bitint(resultdef)) then
+ begin
+ size:=def_cgsize(left.resultdef);
+ location_force_reg(current_asmdata.CurrAsmList,left.location,size,true);
+
+ location_copy(location,left.location);
+ location.loc := LOC_REGISTER;
+ location.register := cg.getintregister(current_asmdata.CurrAsmList,size);
+ resultreg:=location.register;
+
+ if (right.nodetype=ordconstn) and
+ ((tordconstnode(right).value=1) or
+ (tordconstnode(right).value=int64(-1)) or
+ (tordconstnode(right).value=0) or
+ ispowerof2(tordconstnode(right).value,power)) then
+ begin
+ numerator:=left.location.register;
+
+ genOrdConstNodeDiv;
+ end
+ else
+ begin
+ location_force_reg(current_asmdata.CurrAsmList,right.location,size,true);
+
+ if is_signed(left.resultdef) or
+ is_signed(right.resultdef) then
+ cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,OP_IDIV,OS_INT,right.location.register,left.location.register,location.register)
+ else
+ cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,OP_DIV,OS_INT,right.location.register,left.location.register,location.register);
+ end;
+ end
+ else
+ begin
+ location_copy(location,left.location);
+
+ { put numerator in register }
+ size:=def_cgsize(left.resultdef);
+ location_force_reg(current_asmdata.CurrAsmList,left.location,
+ size,true);
+ location_copy(location,left.location);
+ numerator:=location.register;
+ resultreg:=location.register;
+ if location.loc=LOC_CREGISTER then
+ begin
+ location.loc := LOC_REGISTER;
+ location.register := cg.getintregister(current_asmdata.CurrAsmList,size);
+ resultreg:=location.register;
+ end
+ else if (nodetype=modn) or (right.nodetype=ordconstn) then
+ begin
+ // for a modulus op, and for const nodes we need the result register
+ // to be an extra register
+ resultreg:=cg.getintregister(current_asmdata.CurrAsmList,size);
+ end;
+
+ if right.nodetype=ordconstn then
+ begin
+ if nodetype=divn then
+ genOrdConstNodeDiv
+ else
+ // genOrdConstNodeMod;
+ end;
+
+ location.register:=resultreg;
+ end;
+
+ { unsigned division/module can only overflow in case of division by zero }
+ { (but checking this overflow flag is more convoluted than performing a }
+ { simple comparison with 0) }
+ if is_signed(right.resultdef) then
+ cg.g_overflowcheck(current_asmdata.CurrAsmList,location,resultdef);
+ end;
+
+{*****************************************************************************
+ TARMNOTNODE
+*****************************************************************************}
+
+ procedure tarmnotnode.second_boolean;
+ var
+ hl : tasmlabel;
+ begin
+ { if the location is LOC_JUMP, we do the secondpass after the
+ labels are allocated
+ }
+ if left.expectloc=LOC_JUMP then
+ begin
+ hl:=current_procinfo.CurrTrueLabel;
+ current_procinfo.CurrTrueLabel:=current_procinfo.CurrFalseLabel;
+ current_procinfo.CurrFalseLabel:=hl;
+ secondpass(left);
+ maketojumpbool(current_asmdata.CurrAsmList,left,lr_load_regvars);
+ hl:=current_procinfo.CurrTrueLabel;
+ current_procinfo.CurrTrueLabel:=current_procinfo.CurrFalseLabel;
+ current_procinfo.CurrFalseLabel:=hl;
+ location.loc:=LOC_JUMP;
+ end
+ else
+ begin
+ secondpass(left);
+ case left.location.loc of
+ LOC_FLAGS :
+ begin
+ location_copy(location,left.location);
+ inverse_flags(location.resflags);
+ end;
+ LOC_REGISTER,LOC_CREGISTER,LOC_REFERENCE,LOC_CREFERENCE,
+ LOC_SUBSETREG,LOC_CSUBSETREG,LOC_SUBSETREF,LOC_CSUBSETREF :
+ begin
+ location_force_reg(current_asmdata.CurrAsmList,left.location,def_cgsize(left.resultdef),true);
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_CMP,left.location.register,0));
+ location_reset(location,LOC_FLAGS,OS_NO);
+ location.resflags:=F_EQ;
+ end;
+ else
+ internalerror(2003042401);
+ end;
+ end;
+ end;
+
+{*****************************************************************************
+ TARMUNARYMINUSNODE
+*****************************************************************************}
+
+ procedure tarmunaryminusnode.second_float;
+ var
+ op: tasmop;
+ begin
+ secondpass(left);
+ case current_settings.fputype of
+ fpu_fpa,
+ fpu_fpa10,
+ fpu_fpa11:
+ begin
+ location_force_fpureg(current_asmdata.CurrAsmList,left.location,false);
+ location:=left.location;
+ current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg_const(A_RSF,
+ location.register,left.location.register,0),
+ cgsize2fpuoppostfix[def_cgsize(resultdef)]));
+ end;
+ fpu_vfpv2,
+ fpu_vfpv3:
+ begin
+ location_force_mmregscalar(current_asmdata.CurrAsmList,left.location,true);
+ location:=left.location;
+ if (left.location.loc=LOC_CMMREGISTER) then
+ location.register:=cg.getmmregister(current_asmdata.CurrAsmList,location.size);
+ if (location.size=OS_F32) then
+ op:=A_FNEGS
+ else
+ op:=A_FNEGD;
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op,
+ location.register,left.location.register));
+ end;
+ else
+ internalerror(2009112602);
+ end;
+ end;
+
+
+begin
+ cmoddivnode:=tarmmoddivnode;
+ cnotnode:=tarmnotnode;
+ cunaryminusnode:=tarmunaryminusnode;
+end.
diff --git a/closures/compiler/arm/narmset.pas b/closures/compiler/arm/narmset.pas
new file mode 100644
index 0000000000..7dd3fec264
--- /dev/null
+++ b/closures/compiler/arm/narmset.pas
@@ -0,0 +1,256 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate arm assembler for in set/case nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit narmset;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ globtype,
+ node,nset,pass_1,ncgset;
+
+ type
+ tarmcasenode = class(tcgcasenode)
+ procedure optimizevalues(var max_linear_list:aint;var max_dist:aword);override;
+ function has_jumptable : boolean;override;
+ procedure genjumptable(hp : pcaselabel;min_,max_ : aint);override;
+ procedure genlinearlist(hp : pcaselabel);override;
+ end;
+
+
+implementation
+
+ uses
+ systems,
+ verbose,globals,constexp,
+ symconst,symdef,defutil,
+ aasmbase,aasmtai,aasmdata,aasmcpu,
+ cgbase,pass_2,
+ ncon,
+ cpubase,cpuinfo,procinfo,
+ cgutils,cgobj,ncgutil,
+ cgcpu;
+
+
+{*****************************************************************************
+ TARMCASENODE
+*****************************************************************************}
+
+ procedure tarmcasenode.optimizevalues(var max_linear_list:aint;var max_dist:aword);
+ begin
+ inc(max_linear_list,2)
+ end;
+
+
+ function tarmcasenode.has_jumptable : boolean;
+ begin
+ has_jumptable:=true;
+ end;
+
+
+ procedure tarmcasenode.genjumptable(hp : pcaselabel;min_,max_ : aint);
+ var
+ last : TConstExprInt;
+ indexreg : tregister;
+ href : treference;
+ tablelabel: TAsmLabel;
+
+ procedure genitem(list:TAsmList;t : pcaselabel);
+ var
+ i : aint;
+ begin
+ if assigned(t^.less) then
+ genitem(list,t^.less);
+ { fill possible hole }
+ for i:=last.svalue+1 to t^._low.svalue-1 do
+ list.concat(Tai_const.Create_sym(elselabel));
+ for i:=t^._low.svalue to t^._high.svalue do
+ list.concat(Tai_const.Create_sym(blocklabel(t^.blockid)));
+ last:=t^._high.svalue;
+ if assigned(t^.greater) then
+ genitem(list,t^.greater);
+ end;
+
+ procedure genitem_thumb2(list:TAsmList;t : pcaselabel);
+ var
+ i : aint;
+ begin
+ if assigned(t^.less) then
+ genitem_thumb2(list,t^.less);
+ { fill possible hole }
+ for i:=last.svalue+1 to t^._low.svalue-1 do
+ list.concat(Tai_const.Create_rel_sym(aitconst_half16bit,tablelabel,elselabel));
+ for i:=t^._low.svalue to t^._high.svalue do
+ list.concat(Tai_const.Create_rel_sym(aitconst_half16bit,tablelabel,blocklabel(t^.blockid)));
+ last:=t^._high.svalue;
+ if assigned(t^.greater) then
+ genitem_thumb2(list,t^.greater);
+ end;
+
+ begin
+ if not(jumptable_no_range) then
+ begin
+ { case expr less than min_ => goto elselabel }
+ cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,opsize,jmp_lt,aint(min_),hregister,elselabel);
+ { case expr greater than max_ => goto elselabel }
+ cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,opsize,jmp_gt,aint(max_),hregister,elselabel);
+ end;
+ { make it a 32bit register }
+ indexreg:=cg.makeregsize(current_asmdata.CurrAsmList,hregister,OS_INT);
+ cg.a_load_reg_reg(current_asmdata.CurrAsmList,opsize,OS_INT,hregister,indexreg);
+
+ if current_settings.cputype in cpu_thumb2 then
+ begin
+ { adjust index }
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SUB,OS_ADDR,min_,indexreg,indexreg);
+ { create reference and generate jump table }
+ reference_reset(href,4);
+ href.base:=NR_PC;
+ href.index:=indexreg;
+ href.shiftmode:=SM_LSL;
+ href.shiftimm:=1;
+ current_asmdata.CurrAsmList.Concat(taicpu.op_ref(A_TBH,href));
+ { generate jump table }
+ current_asmdata.getjumplabel(tablelabel);
+ cg.a_label(current_asmdata.CurrAsmList,tablelabel);
+ last:=min_;
+ genitem_thumb2(current_asmdata.CurrAsmList,hp);
+ end
+ else
+ begin
+ { adjust index }
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SUB,OS_ADDR,min_+1,indexreg,indexreg);
+ { create reference and generate jump table }
+ reference_reset(href,4);
+ href.base:=NR_PC;
+ href.index:=indexreg;
+ href.shiftmode:=SM_LSL;
+ href.shiftimm:=2;
+ cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,href,NR_PC);
+ { generate jump table }
+ last:=min_;
+ genitem(current_asmdata.CurrAsmList,hp);
+ end;
+ end;
+
+
+ procedure tarmcasenode.genlinearlist(hp : pcaselabel);
+ var
+ first : boolean;
+ lastrange : boolean;
+ last : TConstExprInt;
+ cond_lt,cond_le : tresflags;
+
+ procedure genitem(t : pcaselabel);
+ begin
+ if assigned(t^.less) then
+ genitem(t^.less);
+ { need we to test the first value }
+ if first and (t^._low>get_min_value(left.resultdef)) then
+ begin
+ cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,opsize,jmp_lt,aint(t^._low.svalue),hregister,elselabel);
+ end;
+ if t^._low=t^._high then
+ begin
+ if t^._low-last=0 then
+ cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList, opsize, OC_EQ,0,hregister,blocklabel(t^.blockid))
+ else
+ begin
+ tcgarm(cg).cgsetflags:=true;
+ cg.a_op_const_reg(current_asmdata.CurrAsmList, OP_SUB, opsize, aint(int64(t^._low-last)), hregister);
+ tcgarm(cg).cgsetflags:=false;
+ cg.a_jmp_flags(current_asmdata.CurrAsmList,F_EQ,blocklabel(t^.blockid));
+ end;
+ last:=t^._low;
+ lastrange:=false;
+ end
+ else
+ begin
+ { it begins with the smallest label, if the value }
+ { is even smaller then jump immediately to the }
+ { ELSE-label }
+ if first then
+ begin
+ { have we to ajust the first value ? }
+ if (t^._low>get_min_value(left.resultdef)) or (get_min_value(left.resultdef)<>0) then
+ begin
+ tcgarm(cg).cgsetflags:=true;
+ cg.a_op_const_reg(current_asmdata.CurrAsmList, OP_SUB, opsize, aint(int64(t^._low)), hregister);
+ tcgarm(cg).cgsetflags:=false;
+ end;
+ end
+ else
+ begin
+ { if there is no unused label between the last and the }
+ { present label then the lower limit can be checked }
+ { immediately. else check the range in between: }
+
+ tcgarm(cg).cgsetflags:=true;
+ cg.a_op_const_reg(current_asmdata.CurrAsmList, OP_SUB, opsize, aint(int64(t^._low-last)), hregister);
+ tcgarm(cg).cgsetflags:=false;
+ { no jump necessary here if the new range starts at }
+ { at the value following the previous one }
+ if ((t^._low-last) <> 1) or
+ (not lastrange) then
+ cg.a_jmp_flags(current_asmdata.CurrAsmList,cond_lt,elselabel);
+ end;
+ tcgarm(cg).cgsetflags:=true;
+ cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_SUB,opsize,aint(int64(t^._high-t^._low)),hregister);
+ tcgarm(cg).cgsetflags:=false;
+ cg.a_jmp_flags(current_asmdata.CurrAsmList,cond_le,blocklabel(t^.blockid));
+
+ last:=t^._high;
+ lastrange:=true;
+ end;
+ first:=false;
+ if assigned(t^.greater) then
+ genitem(t^.greater);
+ end;
+
+ begin
+ if with_sign then
+ begin
+ cond_lt:=F_LT;
+ cond_le:=F_LE;
+ end
+ else
+ begin
+ cond_lt:=F_CC;
+ cond_le:=F_LS;
+ end;
+ { do we need to generate cmps? }
+ if (with_sign and (min_label<0)) then
+ genlinearcmplist(hp)
+ else
+ begin
+ last:=0;
+ lastrange:=false;
+ first:=true;
+ genitem(hp);
+ cg.a_jmp_always(current_asmdata.CurrAsmList,elselabel);
+ end;
+ end;
+
+begin
+ ccasenode:=tarmcasenode;
+end.
diff --git a/closures/compiler/arm/pp.lpi.template b/closures/compiler/arm/pp.lpi.template
new file mode 100644
index 0000000000..11b4a97b66
--- /dev/null
+++ b/closures/compiler/arm/pp.lpi.template
@@ -0,0 +1,90 @@
+<?xml version="1.0"?>
+<CONFIG>
+ <ProjectOptions>
+ <PathDelim Value="/"/>
+ <Version Value="5"/>
+ <General>
+ <Flags>
+ <MainUnitHasUsesSectionForAllUnits Value="False"/>
+ <MainUnitHasCreateFormStatements Value="False"/>
+ <MainUnitHasTitleStatement Value="False"/>
+ </Flags>
+ <MainUnit Value="0"/>
+ <IconPath Value="./"/>
+ <TargetFileExt Value=".exe"/>
+ <Title Value="pp"/>
+ <ActiveEditorIndexAtStart Value="1"/>
+ </General>
+ <PublishOptions>
+ <Version Value="2"/>
+ <DestinationDirectory Value="c:/temp/publishedproject/"/>
+ <IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
+ <ExcludeFileFilter Value="*.(bak|ppu|ppw|o|so);*~;backup"/>
+ </PublishOptions>
+ <RunParams>
+ <local>
+ <FormatVersion Value="1"/>
+ <CommandLineParams Value="-?"/>
+ <LaunchingApplication PathPlusParams="/usr/X11R6/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/>
+ </local>
+ </RunParams>
+ <Units Count="1">
+ <Unit0>
+ <Filename Value="../pp.pas"/>
+ <IsPartOfProject Value="True"/>
+ <UnitName Value="pp"/>
+ <EditorIndex Value="0"/>
+ <Loaded Value="True"/>
+ </Unit0>
+ </Units>
+ </ProjectOptions>
+ <CompilerOptions>
+ <Version Value="5"/>
+ <Target>
+ <Filename Value="arm/pp"/>
+ </Target>
+ <SearchPaths>
+ <IncludeFiles Value="../"/>
+ <OtherUnitFiles Value="../;../systems/"/>
+ <UnitOutputDirectory Value="lazbuild"/>
+ </SearchPaths>
+ <Parsing>
+ <SyntaxOptions>
+ <D2Extensions Value="False"/>
+ <CStyleOperator Value="False"/>
+ <AllowLabel Value="False"/>
+ <CPPInline Value="False"/>
+ </SyntaxOptions>
+ </Parsing>
+ <CodeGeneration>
+ <Generate Value="Faster"/>
+ <TargetProcessor Value="3"/>
+ </CodeGeneration>
+ <Linking>
+ <Debugging>
+ <GenerateDebugInfo Value="True"/>
+ </Debugging>
+ </Linking>
+ <Other>
+ <Verbosity>
+ <ShowWarn Value="False"/>
+ <ShowNotes Value="False"/>
+ <ShowHints Value="False"/>
+ </Verbosity>
+ <ConfigFile>
+ <StopAfterErrCount Value="50"/>
+ </ConfigFile>
+ <CustomOptions Value="-dGDB
+-darm
+"/>
+ <CompilerPath Value="$(CompPath)"/>
+ </Other>
+ </CompilerOptions>
+ <Debugging>
+ <Exceptions Count="1">
+ <Item1>
+ <Name Value="ECompilerAbortSilent"/>
+ </Item1>
+ </Exceptions>
+ </Debugging>
+</CONFIG>
diff --git a/closures/compiler/arm/raarm.pas b/closures/compiler/arm/raarm.pas
new file mode 100644
index 0000000000..f696f2dd6b
--- /dev/null
+++ b/closures/compiler/arm/raarm.pas
@@ -0,0 +1,56 @@
+{
+ Copyright (c) 1998-2003 by Carl Eric Codere and Peter Vreman
+
+ Handles the common arm assembler reader routines
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit raarm;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ cpubase,
+ aasmtai,aasmdata,
+ rautils;
+
+ type
+ TARMOperand=class(TOperand)
+ end;
+
+ TARMInstruction=class(TInstruction)
+ oppostfix : toppostfix;
+ wideformat : boolean; // For wide(32bit) instructions of the thumb-2 instruction set
+ function ConcatInstruction(p:TAsmList) : tai;override;
+ end;
+
+ implementation
+
+ uses
+ aasmcpu;
+
+ function TARMInstruction.ConcatInstruction(p:TAsmList) : tai;
+ begin
+ result:=inherited ConcatInstruction(p);
+ (result as taicpu).oppostfix:=oppostfix;
+ (result as taicpu).wideformat:=wideformat;
+ end;
+
+
+end.
diff --git a/closures/compiler/arm/raarmgas.pas b/closures/compiler/arm/raarmgas.pas
new file mode 100644
index 0000000000..9c52022a02
--- /dev/null
+++ b/closures/compiler/arm/raarmgas.pas
@@ -0,0 +1,1176 @@
+{
+ Copyright (c) 1998-2002 by Carl Eric Codere and Peter Vreman
+
+ Does the parsing for the ARM GNU AS styled inline assembler.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+Unit raarmgas;
+
+{$i fpcdefs.inc}
+
+ Interface
+
+ uses
+ raatt,raarm,
+ cpubase;
+
+ type
+ tarmattreader = class(tattreader)
+ actoppostfix : TOpPostfix;
+ actwideformat : boolean;
+ function is_asmopcode(const s: string):boolean;override;
+ function is_register(const s:string):boolean;override;
+ procedure handleopcode;override;
+ procedure BuildReference(oper : tarmoperand);
+ procedure BuildOperand(oper : tarmoperand);
+ function TryBuildShifterOp(oper : tarmoperand) : boolean;
+ procedure BuildOpCode(instr : tarminstruction);
+ procedure ReadSym(oper : tarmoperand);
+ procedure ConvertCalljmp(instr : tarminstruction);
+ end;
+
+
+ Implementation
+
+ uses
+ { helpers }
+ cutils,
+ { global }
+ globtype,globals,verbose,
+ systems,
+ { aasm }
+ cpuinfo,aasmbase,aasmtai,aasmdata,aasmcpu,
+ { symtable }
+ symconst,symbase,symtype,symsym,symtable,
+ { parser }
+ scanner,
+ procinfo,
+ itcpugas,
+ rabase,rautils,
+ cgbase,cgobj
+ ;
+
+
+ function tarmattreader.is_register(const s:string):boolean;
+ type
+ treg2str = record
+ name : string[2];
+ reg : tregister;
+ end;
+
+ const
+ extraregs : array[0..19] of treg2str = (
+ (name: 'A1'; reg : NR_R0),
+ (name: 'A2'; reg : NR_R1),
+ (name: 'A3'; reg : NR_R2),
+ (name: 'A4'; reg : NR_R3),
+ (name: 'V1'; reg : NR_R4),
+ (name: 'V2'; reg : NR_R5),
+ (name: 'V3'; reg : NR_R6),
+ (name: 'V4'; reg : NR_R7),
+ (name: 'V5'; reg : NR_R8),
+ (name: 'V6'; reg : NR_R9),
+ (name: 'V7'; reg : NR_R10),
+ (name: 'V8'; reg : NR_R11),
+ (name: 'WR'; reg : NR_R7),
+ (name: 'SB'; reg : NR_R9),
+ (name: 'SL'; reg : NR_R10),
+ (name: 'FP'; reg : NR_R11),
+ (name: 'IP'; reg : NR_R12),
+ (name: 'SP'; reg : NR_R13),
+ (name: 'LR'; reg : NR_R14),
+ (name: 'PC'; reg : NR_R15));
+
+ var
+ i : longint;
+
+ begin
+ result:=inherited is_register(s);
+ { reg found?
+ possible aliases are always 2 char
+ }
+ if result or (length(s)<>2) then
+ exit;
+ for i:=low(extraregs) to high(extraregs) do
+ begin
+ if s=extraregs[i].name then
+ begin
+ actasmregister:=extraregs[i].reg;
+ result:=true;
+ actasmtoken:=AS_REGISTER;
+ exit;
+ end;
+ end;
+ end;
+
+
+ procedure tarmattreader.ReadSym(oper : tarmoperand);
+ var
+ tempstr, mangledname : string;
+ typesize,l,k : longint;
+ begin
+ tempstr:=actasmpattern;
+ Consume(AS_ID);
+ { typecasting? }
+ if (actasmtoken=AS_LPAREN) and
+ SearchType(tempstr,typesize) then
+ begin
+ oper.hastype:=true;
+ Consume(AS_LPAREN);
+ BuildOperand(oper);
+ Consume(AS_RPAREN);
+ if oper.opr.typ in [OPR_REFERENCE,OPR_LOCAL] then
+ oper.SetSize(typesize,true);
+ end
+ else
+ if not oper.SetupVar(tempstr,false) then
+ Message1(sym_e_unknown_id,tempstr);
+ { record.field ? }
+ if actasmtoken=AS_DOT then
+ begin
+ BuildRecordOffsetSize(tempstr,l,k,mangledname,false);
+ if (mangledname<>'') then
+ Message(asmr_e_invalid_reference_syntax);
+ inc(oper.opr.ref.offset,l);
+ end;
+ end;
+
+
+ Procedure tarmattreader.BuildReference(oper : tarmoperand);
+
+ procedure do_error;
+ begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(false);
+ end;
+
+
+ procedure test_end(require_rbracket : boolean);
+ begin
+ if require_rbracket then begin
+ if not(actasmtoken=AS_RBRACKET) then
+ begin
+ do_error;
+ exit;
+ end
+ else
+ Consume(AS_RBRACKET);
+ if (actasmtoken=AS_NOT) then
+ begin
+ oper.opr.ref.addressmode:=AM_PREINDEXED;
+ Consume(AS_NOT);
+ end;
+ end;
+ if not(actasmtoken in [AS_SEPARATOR,AS_end]) then
+ do_error
+ else
+ begin
+{$IFDEF debugasmreader}
+ writeln('TEST_end_FINAL_OK. Created the following ref:');
+ writeln('oper.opr.ref.shiftimm=',oper.opr.ref.shiftimm);
+ writeln('oper.opr.ref.shiftmode=',ord(oper.opr.ref.shiftmode));
+ writeln('oper.opr.ref.index=',ord(oper.opr.ref.index));
+ writeln('oper.opr.ref.base=',ord(oper.opr.ref.base));
+ writeln('oper.opr.ref.signindex=',ord(oper.opr.ref.signindex));
+ writeln('oper.opr.ref.addressmode=',ord(oper.opr.ref.addressmode));
+ writeln;
+{$endIF debugasmreader}
+ end;
+ end;
+
+
+ function is_shifter_ref_operation(var a : tshiftmode) : boolean;
+ begin
+ a := SM_NONE;
+ if (actasmpattern='LSL') then
+ a := SM_LSL
+ else if (actasmpattern='LSR') then
+ a := SM_LSR
+ else if (actasmpattern='ASR') then
+ a := SM_ASR
+ else if (actasmpattern='ROR') then
+ a := SM_ROR
+ else if (actasmpattern='RRX') then
+ a := SM_RRX;
+ is_shifter_ref_operation := not(a=SM_NONE);
+ end;
+
+
+ procedure read_index_shift(require_rbracket : boolean);
+ var
+ shift : aint;
+ begin
+ case actasmtoken of
+ AS_COMMA :
+ begin
+ Consume(AS_COMMA);
+ if not(actasmtoken=AS_ID) then
+ do_error;
+ if is_shifter_ref_operation(oper.opr.ref.shiftmode) then
+ begin
+ Consume(AS_ID);
+ if not(oper.opr.ref.shiftmode=SM_RRX) then
+ begin
+ if not(actasmtoken=AS_HASH) then
+ do_error;
+ Consume(AS_HASH);
+ shift := BuildConstExpression(false,true);
+ if (shift<0) or (shift>32) then
+ do_error;
+ oper.opr.ref.shiftimm := shift;
+ test_end(require_rbracket);
+ end;
+ end
+ else
+ begin
+ do_error;
+ exit;
+ end;
+ end;
+ AS_RBRACKET :
+ if require_rbracket then
+ test_end(require_rbracket)
+ else
+ begin
+ do_error;
+ exit;
+ end;
+ AS_SEPARATOR,AS_END :
+ if not require_rbracket then
+ test_end(false)
+ else
+ do_error;
+ else
+ begin
+ do_error;
+ exit;
+ end;
+ end;
+ end;
+
+
+ procedure read_index(require_rbracket : boolean);
+ var
+ recname : string;
+ o_int,s_int : aint;
+ begin
+ case actasmtoken of
+ AS_REGISTER :
+ begin
+ oper.opr.ref.index:=actasmregister;
+ Consume(AS_REGISTER);
+ read_index_shift(require_rbracket);
+ exit;
+ end;
+ AS_PLUS,AS_MINUS :
+ begin
+ if actasmtoken=AS_PLUS then
+ begin
+ Consume(AS_PLUS);
+ end
+ else
+ begin
+ oper.opr.ref.signindex := -1;
+ Consume(AS_MINUS);
+ end;
+ if actasmtoken=AS_REGISTER then
+ begin
+ oper.opr.ref.index:=actasmregister;
+ Consume(AS_REGISTER);
+ read_index_shift(require_rbracket);
+ exit;
+ end
+ else
+ begin
+ do_error;
+ exit;
+ end;
+ test_end(require_rbracket);
+ exit;
+ end;
+ AS_HASH : // constant
+ begin
+ Consume(AS_HASH);
+ o_int := BuildConstExpression(false,true);
+ if (o_int>4095) or (o_int<-4095) then
+ begin
+ Message(asmr_e_constant_out_of_bounds);
+ RecoverConsume(false);
+ exit;
+ end
+ else
+ begin
+ inc(oper.opr.ref.offset,o_int);
+ test_end(require_rbracket);
+ exit;
+ end;
+ end;
+ AS_ID :
+ begin
+ recname := actasmpattern;
+ Consume(AS_ID);
+ BuildRecordOffsetSize(recname,o_int,s_int,recname,false);
+ if (o_int>4095)or(o_int<-4095) then
+ begin
+ Message(asmr_e_constant_out_of_bounds);
+ RecoverConsume(false);
+ exit;
+ end
+ else
+ begin
+ inc(oper.opr.ref.offset,o_int);
+ test_end(require_rbracket);
+ exit;
+ end;
+ end;
+ AS_AT:
+ begin
+ do_error;
+ exit;
+ end;
+ AS_DOT : // local label
+ begin
+ oper.opr.ref.signindex := BuildConstExpression(true,false);
+ test_end(require_rbracket);
+ exit;
+ end;
+ AS_RBRACKET :
+ begin
+ if require_rbracket then
+ begin
+ test_end(require_rbracket);
+ exit;
+ end
+ else
+ begin
+ do_error; // unexpected rbracket
+ exit;
+ end;
+ end;
+ AS_SEPARATOR,AS_end :
+ begin
+ if not require_rbracket then
+ begin
+ test_end(false);
+ exit;
+ end
+ else
+ begin
+ do_error;
+ exit;
+ end;
+ end;
+ else
+ begin
+ // unexpected token
+ do_error;
+ exit;
+ end;
+ end; // case
+ end;
+
+
+ procedure try_prepostindexed;
+ begin
+ Consume(AS_RBRACKET);
+ case actasmtoken of
+ AS_COMMA :
+ begin // post-indexed
+ Consume(AS_COMMA);
+ oper.opr.ref.addressmode:=AM_POSTINDEXED;
+ read_index(false);
+ exit;
+ end;
+ AS_NOT :
+ begin // pre-indexed
+ Consume(AS_NOT);
+ oper.opr.ref.addressmode:=AM_PREINDEXED;
+ test_end(false);
+ exit;
+ end;
+ else
+ begin
+ test_end(false);
+ exit;
+ end;
+ end; // case
+ end;
+
+ var
+ lab : TASMLABEL;
+ begin
+ Consume(AS_LBRACKET);
+ oper.opr.ref.addressmode:=AM_OFFSET; // assume "neither PRE nor POST inc"
+ if actasmtoken=AS_REGISTER then
+ begin
+ oper.opr.ref.base:=actasmregister;
+ Consume(AS_REGISTER);
+ case actasmtoken of
+ AS_RBRACKET :
+ begin
+ try_prepostindexed;
+ exit;
+ end;
+ AS_COMMA :
+ begin
+ Consume(AS_COMMA);
+ read_index(true);
+ exit;
+ end;
+ else
+ begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(false);
+ end;
+ end;
+ end
+ else
+{
+ if base isn't a register, r15=PC is implied base, so it must be a local label.
+ pascal constants don't make sense, because implied r15
+ record offsets probably don't make sense, too (a record offset of code?)
+
+ TODO: However, we could make the Stackpointer implied.
+
+}
+
+ Begin
+ case actasmtoken of
+ AS_ID :
+ begin
+ if is_locallabel(actasmpattern) then
+ begin
+ CreateLocalLabel(actasmpattern,lab,false);
+ oper.opr.ref.symbol := lab;
+ oper.opr.ref.base := NR_PC;
+ Consume(AS_ID);
+ test_end(true);
+ exit;
+ end
+ else
+ begin
+ // TODO: Stackpointer implied,
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(false);
+ exit;
+ end;
+ end;
+ else
+ begin // elsecase
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(false);
+ exit;
+ end;
+ end;
+ end;
+ end;
+
+
+ function tarmattreader.TryBuildShifterOp(oper : tarmoperand) : boolean;
+
+ procedure handlepara(sm : tshiftmode);
+ begin
+ consume(AS_ID);
+ fillchar(oper.opr,sizeof(oper.opr),0);
+ oper.opr.typ:=OPR_SHIFTEROP;
+ oper.opr.shifterop.shiftmode:=sm;
+ if sm<>SM_RRX then
+ begin
+ case actasmtoken of
+ AS_REGISTER:
+ begin
+ oper.opr.shifterop.rs:=actasmregister;
+ consume(AS_REGISTER);
+ end;
+ AS_HASH:
+ begin
+ consume(AS_HASH);
+ oper.opr.shifterop.shiftimm:=BuildConstExpression(false,false);
+ end;
+ else
+ Message(asmr_e_illegal_shifterop_syntax);
+ end;
+ end;
+ end;
+
+ begin
+ result:=true;
+ if (actasmtoken=AS_ID) then
+ begin
+ if (actasmpattern='LSL') then
+ handlepara(SM_LSL)
+ else if (actasmpattern='LSR') then
+ handlepara(SM_LSR)
+ else if (actasmpattern='ASR') then
+ handlepara(SM_ASR)
+ else if (actasmpattern='ROR') then
+ handlepara(SM_ROR)
+ else if (actasmpattern='RRX') then
+ handlepara(SM_ROR)
+ else
+ result:=false;
+ end
+ else
+ result:=false;
+ end;
+
+
+ Procedure tarmattreader.BuildOperand(oper : tarmoperand);
+ var
+ expr : string;
+ typesize,l : longint;
+
+
+ procedure AddLabelOperand(hl:tasmlabel);
+ begin
+ if not(actasmtoken in [AS_PLUS,AS_MINUS,AS_LPAREN]) and
+ is_calljmp(actopcode) then
+ begin
+ oper.opr.typ:=OPR_SYMBOL;
+ oper.opr.symbol:=hl;
+ end
+ else
+ begin
+ oper.InitRef;
+ oper.opr.ref.symbol:=hl;
+ oper.opr.ref.base:=NR_PC;
+ end;
+ end;
+
+
+ procedure MaybeRecordOffset;
+ var
+ mangledname: string;
+ hasdot : boolean;
+ l,
+ toffset,
+ tsize : longint;
+ begin
+ if not(actasmtoken in [AS_DOT,AS_PLUS,AS_MINUS]) then
+ exit;
+ l:=0;
+ hasdot:=(actasmtoken=AS_DOT);
+ if hasdot then
+ begin
+ if expr<>'' then
+ begin
+ BuildRecordOffsetSize(expr,toffset,tsize,mangledname,false);
+ if (oper.opr.typ<>OPR_CONSTANT) and
+ (mangledname<>'') then
+ Message(asmr_e_wrong_sym_type);
+ inc(l,toffset);
+ oper.SetSize(tsize,true);
+ end;
+ end;
+ if actasmtoken in [AS_PLUS,AS_MINUS] then
+ inc(l,BuildConstExpression(true,false));
+ case oper.opr.typ of
+ OPR_LOCAL :
+ begin
+ { don't allow direct access to fields of parameters, because that
+ will generate buggy code. Allow it only for explicit typecasting }
+ if hasdot and
+ (not oper.hastype) and
+ (tabstractnormalvarsym(oper.opr.localsym).owner.symtabletype=parasymtable) and
+ (current_procinfo.procdef.proccalloption<>pocall_register) then
+ Message(asmr_e_cannot_access_field_directly_for_parameters);
+ inc(oper.opr.localsymofs,l)
+ end;
+ OPR_CONSTANT :
+ inc(oper.opr.val,l);
+ OPR_REFERENCE :
+ if (mangledname<>'') then
+ begin
+ if (oper.opr.val<>0) then
+ Message(asmr_e_wrong_sym_type);
+ oper.opr.typ:=OPR_SYMBOL;
+ oper.opr.symbol:=current_asmdata.RefAsmSymbol(mangledname);
+ end
+ else
+ inc(oper.opr.val,l);
+ OPR_SYMBOL:
+ Message(asmr_e_invalid_symbol_ref);
+ else
+ internalerror(200309221);
+ end;
+ end;
+
+
+ function MaybeBuildReference:boolean;
+ { Try to create a reference, if not a reference is found then false
+ is returned }
+ begin
+ MaybeBuildReference:=true;
+ case actasmtoken of
+ AS_INTNUM,
+ AS_MINUS,
+ AS_PLUS:
+ Begin
+ oper.opr.ref.offset:=BuildConstExpression(True,False);
+ if actasmtoken<>AS_LPAREN then
+ Message(asmr_e_invalid_reference_syntax)
+ else
+ BuildReference(oper);
+ end;
+ AS_LPAREN:
+ BuildReference(oper);
+ AS_ID: { only a variable is allowed ... }
+ Begin
+ ReadSym(oper);
+ case actasmtoken of
+ AS_end,
+ AS_SEPARATOR,
+ AS_COMMA: ;
+ AS_LPAREN:
+ BuildReference(oper);
+ else
+ Begin
+ Message(asmr_e_invalid_reference_syntax);
+ Consume(actasmtoken);
+ end;
+ end; {end case }
+ end;
+ else
+ MaybeBuildReference:=false;
+ end; { end case }
+ end;
+
+
+ function is_ConditionCode(hs: string): boolean;
+ var icond: tasmcond;
+ begin
+ is_ConditionCode := false;
+
+ if actopcode in [A_IT,A_ITE,A_ITT,
+ A_ITEE,A_ITTE,A_ITET,A_ITTT,
+ A_ITEEE,A_ITTEE,A_ITETE,A_ITTTE,A_ITEET,A_ITTET,A_ITETT,A_ITTTT] then
+ begin
+ { search for condition, conditions are always 2 chars }
+ if length(hs)>1 then
+ begin
+ for icond:=low(tasmcond) to high(tasmcond) do
+ begin
+ if copy(hs,1,2)=uppercond2str[icond] then
+ begin
+ //actcondition:=icond;
+ oper.opr.typ := OPR_COND;
+ oper.opr.cc := icond;
+ exit(true);
+ end;
+ end;
+ end;
+ end;
+ end;
+
+
+ function is_modeflag(hs : string): boolean;
+ var
+ i: longint;
+ flags: tcpumodeflags;
+ begin
+ is_modeflag := false;
+
+ flags:=[];
+ hs:=lower(hs);
+
+ if (actopcode in [A_CPSID,A_CPSIE]) and (length(hs) >= 1) then
+ begin
+ for i:=1 to length(hs) do
+ begin
+ case hs[i] of
+ 'a':
+ Include(flags,mfA);
+ 'f':
+ Include(flags,mfF);
+ 'i':
+ Include(flags,mfI);
+ else
+ exit;
+ end;
+ end;
+ oper.opr.typ := OPR_MODEFLAGS;
+ oper.opr.flags := flags;
+ exit(true);
+ end;
+ end;
+
+ var
+ tempreg : tregister;
+ ireg : tsuperregister;
+ regtype: tregistertype;
+ subreg: tsubregister;
+ hl : tasmlabel;
+ {ofs : longint;}
+ registerset : tcpuregisterset;
+ Begin
+ expr:='';
+ case actasmtoken of
+ AS_LBRACKET: { Memory reference or constant expression }
+ Begin
+ oper.InitRef;
+ BuildReference(oper);
+ end;
+
+ AS_HASH: { Constant expression }
+ Begin
+ Consume(AS_HASH);
+ BuildConstantOperand(oper);
+ end;
+
+ (*
+ AS_INTNUM,
+ AS_MINUS,
+ AS_PLUS:
+ Begin
+ { Constant memory offset }
+ { This must absolutely be followed by ( }
+ oper.InitRef;
+ oper.opr.ref.offset:=BuildConstExpression(True,False);
+ if actasmtoken<>AS_LPAREN then
+ begin
+ ofs:=oper.opr.ref.offset;
+ BuildConstantOperand(oper);
+ inc(oper.opr.val,ofs);
+ end
+ else
+ BuildReference(oper);
+ end;
+ *)
+ AS_ID: { A constant expression, or a Variable ref. }
+ Begin
+ if is_modeflag(actasmpattern) then
+ begin
+ consume(AS_ID);
+ end
+ else
+ { Condition code? }
+ if is_conditioncode(actasmpattern) then
+ begin
+ consume(AS_ID);
+ end
+ else
+ { Local Label ? }
+ if is_locallabel(actasmpattern) then
+ begin
+ CreateLocalLabel(actasmpattern,hl,false);
+ Consume(AS_ID);
+ AddLabelOperand(hl);
+ end
+ else
+ { Check for label }
+ if SearchLabel(actasmpattern,hl,false) then
+ begin
+ Consume(AS_ID);
+ AddLabelOperand(hl);
+ end
+ else
+ { probably a variable or normal expression }
+ { or a procedure (such as in CALL ID) }
+ Begin
+ { is it a constant ? }
+ if SearchIConstant(actasmpattern,l) then
+ Begin
+ if not (oper.opr.typ in [OPR_NONE,OPR_CONSTANT]) then
+ Message(asmr_e_invalid_operand_type);
+ BuildConstantOperand(oper);
+ end
+ else
+ begin
+ expr:=actasmpattern;
+ Consume(AS_ID);
+ { typecasting? }
+ if (actasmtoken=AS_LPAREN) and
+ SearchType(expr,typesize) then
+ begin
+ oper.hastype:=true;
+ Consume(AS_LPAREN);
+ BuildOperand(oper);
+ Consume(AS_RPAREN);
+ if oper.opr.typ in [OPR_REFERENCE,OPR_LOCAL] then
+ oper.SetSize(typesize,true);
+ end
+ else
+ begin
+ if not(oper.SetupVar(expr,false)) then
+ Begin
+ { look for special symbols ... }
+ if expr= '__HIGH' then
+ begin
+ consume(AS_LPAREN);
+ if not oper.setupvar('high'+actasmpattern,false) then
+ Message1(sym_e_unknown_id,'high'+actasmpattern);
+ consume(AS_ID);
+ consume(AS_RPAREN);
+ end
+ else
+ if expr = '__RESULT' then
+ oper.SetUpResult
+ else
+ if expr = '__SELF' then
+ oper.SetupSelf
+ else
+ if expr = '__OLDEBP' then
+ oper.SetupOldEBP
+ else
+ Message1(sym_e_unknown_id,expr);
+ end;
+ end;
+ end;
+ if actasmtoken=AS_DOT then
+ MaybeRecordOffset;
+ { add a constant expression? }
+ if (actasmtoken=AS_PLUS) then
+ begin
+ l:=BuildConstExpression(true,false);
+ case oper.opr.typ of
+ OPR_CONSTANT :
+ inc(oper.opr.val,l);
+ OPR_LOCAL :
+ inc(oper.opr.localsymofs,l);
+ OPR_REFERENCE :
+ inc(oper.opr.ref.offset,l);
+ else
+ internalerror(200309202);
+ end;
+ end
+ end;
+ { Do we have a indexing reference, then parse it also }
+ if actasmtoken=AS_LPAREN then
+ BuildReference(oper);
+ end;
+
+ { Register, a variable reference or a constant reference }
+ AS_REGISTER:
+ Begin
+ { save the type of register used. }
+ tempreg:=actasmregister;
+ Consume(AS_REGISTER);
+ if (actasmtoken in [AS_end,AS_SEPARATOR,AS_COMMA]) then
+ Begin
+ if not (oper.opr.typ in [OPR_NONE,OPR_REGISTER]) then
+ Message(asmr_e_invalid_operand_type);
+ oper.opr.typ:=OPR_REGISTER;
+ oper.opr.reg:=tempreg;
+ end
+ else if (actasmtoken=AS_NOT) and (actopcode in [A_LDM,A_STM,A_FLDM,A_FSTM]) then
+ begin
+ consume(AS_NOT);
+ oper.opr.typ:=OPR_REFERENCE;
+ oper.opr.ref.addressmode:=AM_PREINDEXED;
+ oper.opr.ref.index:=tempreg;
+ end
+ else
+ Message(asmr_e_syn_operand);
+ end;
+
+ { Registerset }
+ AS_LSBRACKET:
+ begin
+ consume(AS_LSBRACKET);
+ registerset:=[];
+ regtype:=R_INVALIDREGISTER;
+ subreg:=R_SUBNONE;
+ while true do
+ begin
+ if actasmtoken=AS_REGISTER then
+ begin
+ include(registerset,getsupreg(actasmregister));
+ if regtype<>R_INVALIDREGISTER then
+ begin
+ if (getregtype(actasmregister)<>regtype) or
+ (getsubreg(actasmregister)<>subreg) then
+ Message(asmr_e_mixing_regtypes);
+ end
+ else
+ begin
+ regtype:=getregtype(actasmregister);
+ subreg:=getsubreg(actasmregister);
+ end;
+ tempreg:=actasmregister;
+ consume(AS_REGISTER);
+ if actasmtoken=AS_MINUS then
+ begin
+ consume(AS_MINUS);
+ for ireg:=getsupreg(tempreg) to getsupreg(actasmregister) do
+ include(registerset,ireg);
+ consume(AS_REGISTER);
+ end;
+ end
+ else
+ consume(AS_REGISTER);
+ if actasmtoken=AS_COMMA then
+ consume(AS_COMMA)
+ else
+ break;
+ end;
+ consume(AS_RSBRACKET);
+ oper.opr.typ:=OPR_REGSET;
+ oper.opr.regtype:=regtype;
+ oper.opr.subreg:=subreg;
+ oper.opr.regset:=registerset;
+ if (registerset=[]) then
+ Message(asmr_e_empty_regset);
+ end;
+ AS_end,
+ AS_SEPARATOR,
+ AS_COMMA: ;
+ else
+ Begin
+ Message(asmr_e_syn_operand);
+ Consume(actasmtoken);
+ end;
+ end; { end case }
+ end;
+
+
+{*****************************************************************************
+ tarmattreader
+*****************************************************************************}
+
+ procedure tarmattreader.BuildOpCode(instr : tarminstruction);
+ var
+ operandnum : longint;
+ Begin
+ { opcode }
+ if (actasmtoken<>AS_OPCODE) then
+ Begin
+ Message(asmr_e_invalid_or_missing_opcode);
+ RecoverConsume(true);
+ exit;
+ end;
+ { Fill the instr object with the current state }
+ with instr do
+ begin
+ Opcode:=ActOpcode;
+ condition:=ActCondition;
+ oppostfix:=actoppostfix;
+ wideformat:=actwideformat;
+ end;
+
+ { We are reading operands, so opcode will be an AS_ID }
+ operandnum:=1;
+ Consume(AS_OPCODE);
+ { Zero operand opcode ? }
+ if actasmtoken in [AS_SEPARATOR,AS_end] then
+ begin
+ operandnum:=0;
+ exit;
+ end;
+ { Read the operands }
+ repeat
+ case actasmtoken of
+ AS_COMMA: { Operand delimiter }
+ Begin
+ if ((instr.opcode=A_MOV) and (operandnum=2)) or
+ ((operandnum=3) and not(instr.opcode in [A_UMLAL,A_UMULL,A_SMLAL,A_SMULL,A_MLA])) then
+ begin
+ Consume(AS_COMMA);
+ if not(TryBuildShifterOp(instr.Operands[operandnum+1] as tarmoperand)) then
+ Message(asmr_e_illegal_shifterop_syntax);
+ Inc(operandnum);
+ end
+ else
+ begin
+ if operandnum>Max_Operands then
+ Message(asmr_e_too_many_operands)
+ else
+ Inc(operandnum);
+ Consume(AS_COMMA);
+ end;
+ end;
+ AS_SEPARATOR,
+ AS_end : { End of asm operands for this opcode }
+ begin
+ break;
+ end;
+ else
+ BuildOperand(instr.Operands[operandnum] as tarmoperand);
+ end; { end case }
+ until false;
+ instr.Ops:=operandnum;
+ end;
+
+
+ function tarmattreader.is_asmopcode(const s: string):boolean;
+
+ const
+ { sorted by length so longer postfixes will match first }
+ postfix2strsorted : array[1..31] of string[3] = (
+ 'IAD','DBD','FDD','EAD',
+ 'IAS','DBS','FDS','EAS',
+ 'IAX','DBX','FDX','EAX',
+ 'EP','SB','BT','SH',
+ 'IA','IB','DA','DB','FD','FA','ED','EA',
+ 'B','D','E','P','T','H','S');
+
+ postfixsorted : array[1..31] of TOpPostfix = (
+ PF_IAD,PF_DBD,PF_FDD,PF_EAD,
+ PF_IAS,PF_DBS,PF_FDS,PF_EAS,
+ PF_IAX,PF_DBX,PF_FDX,PF_EAX,
+ PF_EP,PF_SB,PF_BT,PF_SH,
+ PF_IA,PF_IB,PF_DA,PF_DB,PF_FD,PF_FA,PF_ED,PF_EA,
+ PF_B,PF_D,PF_E,PF_P,PF_T,PF_H,PF_S);
+
+ var
+ j : longint;
+ hs : string;
+ maxlen : longint;
+ icond : tasmcond;
+ Begin
+ { making s a value parameter would break other assembler readers }
+ hs:=s;
+ is_asmopcode:=false;
+
+ { clear op code }
+ actopcode:=A_None;
+
+ actcondition:=C_None;
+
+ { first, handle B else BLS is read wrong }
+ if ((hs[1]='B') and (length(hs)=3)) then
+ begin
+ for icond:=low(tasmcond) to high(tasmcond) do
+ begin
+ if copy(hs,2,3)=uppercond2str[icond] then
+ begin
+ actopcode:=A_B;
+ actasmtoken:=AS_OPCODE;
+ actcondition:=icond;
+ is_asmopcode:=true;
+ exit;
+ end;
+ end;
+ end;
+ maxlen:=max(length(hs),5);
+ actopcode:=A_NONE;
+ for j:=maxlen downto 1 do
+ begin
+ actopcode:=tasmop(PtrUInt(iasmops.Find(copy(hs,1,j))));
+ if actopcode<>A_NONE then
+ begin
+ actasmtoken:=AS_OPCODE;
+ { strip op code }
+ delete(hs,1,j);
+ break;
+ end;
+ end;
+ if actopcode=A_NONE then
+ exit;
+
+ { search for condition, conditions are always 2 chars }
+ if length(hs)>1 then
+ begin
+ for icond:=low(tasmcond) to high(tasmcond) do
+ begin
+ if copy(hs,1,2)=uppercond2str[icond] then
+ begin
+ actcondition:=icond;
+ { strip condition }
+ delete(hs,1,2);
+ break;
+ end;
+ end;
+ end;
+ { check for postfix }
+ if length(hs)>0 then
+ begin
+ for j:=low(postfixsorted) to high(postfixsorted) do
+ begin
+ if copy(hs,1,length(postfix2strsorted[j]))=postfix2strsorted[j] then
+ begin
+ actoppostfix:=postfixsorted[j];
+ { strip postfix }
+ delete(hs,1,length(postfix2strsorted[j]));
+ break;
+ end;
+ end;
+ end;
+ { check for format postfix }
+ if length(hs)>0 then
+ begin
+ if upcase(copy(hs,1,2)) = '.W' then
+ begin
+ actwideformat:=true;
+ delete(hs,1,2);
+ end;
+ end;
+ { if we stripped all postfixes, it's a valid opcode }
+ is_asmopcode:=length(hs)=0;
+ end;
+
+
+ procedure tarmattreader.ConvertCalljmp(instr : tarminstruction);
+ var
+ newopr : toprrec;
+ begin
+ if instr.Operands[1].opr.typ=OPR_REFERENCE then
+ begin
+ newopr.typ:=OPR_SYMBOL;
+ newopr.symbol:=instr.Operands[1].opr.ref.symbol;
+ newopr.symofs:=instr.Operands[1].opr.ref.offset;
+ if (instr.Operands[1].opr.ref.base<>NR_NO) or
+ (instr.Operands[1].opr.ref.index<>NR_NO) then
+ Message(asmr_e_syn_operand);
+ instr.Operands[1].opr:=newopr;
+ end;
+ end;
+
+
+ procedure tarmattreader.handleopcode;
+ var
+ instr : tarminstruction;
+ begin
+ instr:=TarmInstruction.Create(TarmOperand);
+ BuildOpcode(instr);
+ if is_calljmp(instr.opcode) then
+ ConvertCalljmp(instr);
+ {
+ instr.AddReferenceSizes;
+ instr.SetInstructionOpsize;
+ instr.CheckOperandSizes;
+ }
+ instr.ConcatInstruction(curlist);
+ instr.Free;
+ actoppostfix:=PF_None;
+ actwideformat:=false;
+ end;
+
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+const
+ asmmode_arm_att_info : tasmmodeinfo =
+ (
+ id : asmmode_arm_gas;
+ idtxt : 'GAS';
+ casmreader : tarmattreader;
+ );
+
+ asmmode_arm_standard_info : tasmmodeinfo =
+ (
+ id : asmmode_standard;
+ idtxt : 'STANDARD';
+ casmreader : tarmattreader;
+ );
+
+initialization
+ RegisterAsmMode(asmmode_arm_att_info);
+ RegisterAsmMode(asmmode_arm_standard_info);
+end.
diff --git a/closures/compiler/arm/rarmcon.inc b/closures/compiler/arm/rarmcon.inc
new file mode 100644
index 0000000000..fc820f5dcb
--- /dev/null
+++ b/closures/compiler/arm/rarmcon.inc
@@ -0,0 +1,92 @@
+{ don't edit, this file is generated from armreg.dat }
+NR_NO = tregister($00000000);
+NR_R0 = tregister($01000000);
+NR_R1 = tregister($01000001);
+NR_R2 = tregister($01000002);
+NR_R3 = tregister($01000003);
+NR_R4 = tregister($01000004);
+NR_R5 = tregister($01000005);
+NR_R6 = tregister($01000006);
+NR_R7 = tregister($01000007);
+NR_R8 = tregister($01000008);
+NR_R9 = tregister($01000009);
+NR_R10 = tregister($0100000a);
+NR_R11 = tregister($0100000b);
+NR_R12 = tregister($0100000c);
+NR_R13 = tregister($0100000d);
+NR_R14 = tregister($0100000e);
+NR_R15 = tregister($0100000f);
+NR_F0 = tregister($02000000);
+NR_F1 = tregister($02000001);
+NR_F2 = tregister($02000002);
+NR_F3 = tregister($02000003);
+NR_F4 = tregister($02000004);
+NR_F5 = tregister($02000005);
+NR_F6 = tregister($02000006);
+NR_F7 = tregister($02000007);
+NR_S0 = tregister($04060000);
+NR_S1 = tregister($04060000);
+NR_D0 = tregister($04070000);
+NR_S2 = tregister($04060001);
+NR_S3 = tregister($04060001);
+NR_D1 = tregister($04070001);
+NR_S4 = tregister($04060002);
+NR_S5 = tregister($04060002);
+NR_D2 = tregister($04070002);
+NR_S6 = tregister($04060003);
+NR_S7 = tregister($04060003);
+NR_D3 = tregister($04070003);
+NR_S8 = tregister($04060004);
+NR_S9 = tregister($04060004);
+NR_D4 = tregister($04070004);
+NR_S10 = tregister($04060005);
+NR_S11 = tregister($04060005);
+NR_D5 = tregister($04070005);
+NR_S12 = tregister($04060006);
+NR_S13 = tregister($04060006);
+NR_D6 = tregister($04070006);
+NR_S14 = tregister($04060007);
+NR_S15 = tregister($04060007);
+NR_D7 = tregister($04070007);
+NR_S16 = tregister($04060008);
+NR_S17 = tregister($04060008);
+NR_D8 = tregister($04070008);
+NR_S18 = tregister($04060009);
+NR_S19 = tregister($04060009);
+NR_D9 = tregister($04070009);
+NR_S20 = tregister($0406000A);
+NR_S21 = tregister($0406000A);
+NR_D10 = tregister($0407000A);
+NR_S22 = tregister($0406000B);
+NR_S23 = tregister($0406000B);
+NR_D11 = tregister($0407000B);
+NR_S24 = tregister($0406000C);
+NR_S25 = tregister($0406000C);
+NR_D12 = tregister($0407000C);
+NR_S26 = tregister($0406000D);
+NR_S27 = tregister($0406000D);
+NR_D13 = tregister($0407000D);
+NR_S28 = tregister($0406000E);
+NR_S29 = tregister($0406000E);
+NR_D14 = tregister($0407000E);
+NR_S30 = tregister($0406000F);
+NR_S31 = tregister($0406000F);
+NR_D15 = tregister($0407000F);
+NR_D16 = tregister($04070010);
+NR_D17 = tregister($04070011);
+NR_D18 = tregister($04070012);
+NR_D19 = tregister($04070013);
+NR_D20 = tregister($04070014);
+NR_D21 = tregister($04070015);
+NR_D22 = tregister($04070016);
+NR_D23 = tregister($04070017);
+NR_D24 = tregister($04070018);
+NR_D25 = tregister($04070019);
+NR_D26 = tregister($0407001A);
+NR_D27 = tregister($0407001B);
+NR_D28 = tregister($0407001C);
+NR_D29 = tregister($0407001D);
+NR_D30 = tregister($0407001E);
+NR_D31 = tregister($0407001F);
+NR_CPSR_C = tregister($05000000);
+NR_FPSCR = tregister($05000001);
diff --git a/closures/compiler/arm/rarmdwa.inc b/closures/compiler/arm/rarmdwa.inc
new file mode 100644
index 0000000000..42a6432848
--- /dev/null
+++ b/closures/compiler/arm/rarmdwa.inc
@@ -0,0 +1,92 @@
+{ don't edit, this file is generated from armreg.dat }
+-1,
+0,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+8,
+9,
+10,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+20,
+21,
+22,
+23,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0
diff --git a/closures/compiler/arm/rarmnor.inc b/closures/compiler/arm/rarmnor.inc
new file mode 100644
index 0000000000..00c1301ae9
--- /dev/null
+++ b/closures/compiler/arm/rarmnor.inc
@@ -0,0 +1,2 @@
+{ don't edit, this file is generated from armreg.dat }
+91
diff --git a/closures/compiler/arm/rarmnum.inc b/closures/compiler/arm/rarmnum.inc
new file mode 100644
index 0000000000..ceb5304995
--- /dev/null
+++ b/closures/compiler/arm/rarmnum.inc
@@ -0,0 +1,92 @@
+{ don't edit, this file is generated from armreg.dat }
+tregister($00000000),
+tregister($01000000),
+tregister($01000001),
+tregister($01000002),
+tregister($01000003),
+tregister($01000004),
+tregister($01000005),
+tregister($01000006),
+tregister($01000007),
+tregister($01000008),
+tregister($01000009),
+tregister($0100000a),
+tregister($0100000b),
+tregister($0100000c),
+tregister($0100000d),
+tregister($0100000e),
+tregister($0100000f),
+tregister($02000000),
+tregister($02000001),
+tregister($02000002),
+tregister($02000003),
+tregister($02000004),
+tregister($02000005),
+tregister($02000006),
+tregister($02000007),
+tregister($04060000),
+tregister($04060000),
+tregister($04070000),
+tregister($04060001),
+tregister($04060001),
+tregister($04070001),
+tregister($04060002),
+tregister($04060002),
+tregister($04070002),
+tregister($04060003),
+tregister($04060003),
+tregister($04070003),
+tregister($04060004),
+tregister($04060004),
+tregister($04070004),
+tregister($04060005),
+tregister($04060005),
+tregister($04070005),
+tregister($04060006),
+tregister($04060006),
+tregister($04070006),
+tregister($04060007),
+tregister($04060007),
+tregister($04070007),
+tregister($04060008),
+tregister($04060008),
+tregister($04070008),
+tregister($04060009),
+tregister($04060009),
+tregister($04070009),
+tregister($0406000A),
+tregister($0406000A),
+tregister($0407000A),
+tregister($0406000B),
+tregister($0406000B),
+tregister($0407000B),
+tregister($0406000C),
+tregister($0406000C),
+tregister($0407000C),
+tregister($0406000D),
+tregister($0406000D),
+tregister($0407000D),
+tregister($0406000E),
+tregister($0406000E),
+tregister($0407000E),
+tregister($0406000F),
+tregister($0406000F),
+tregister($0407000F),
+tregister($04070010),
+tregister($04070011),
+tregister($04070012),
+tregister($04070013),
+tregister($04070014),
+tregister($04070015),
+tregister($04070016),
+tregister($04070017),
+tregister($04070018),
+tregister($04070019),
+tregister($0407001A),
+tregister($0407001B),
+tregister($0407001C),
+tregister($0407001D),
+tregister($0407001E),
+tregister($0407001F),
+tregister($05000000),
+tregister($05000001)
diff --git a/closures/compiler/arm/rarmrni.inc b/closures/compiler/arm/rarmrni.inc
new file mode 100644
index 0000000000..a8a9d0fd7e
--- /dev/null
+++ b/closures/compiler/arm/rarmrni.inc
@@ -0,0 +1,92 @@
+{ don't edit, this file is generated from armreg.dat }
+0,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+8,
+9,
+10,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+20,
+21,
+22,
+23,
+24,
+25,
+26,
+29,
+28,
+31,
+32,
+35,
+34,
+37,
+38,
+41,
+40,
+43,
+44,
+47,
+46,
+49,
+50,
+53,
+52,
+55,
+56,
+59,
+58,
+61,
+62,
+65,
+64,
+67,
+68,
+71,
+70,
+27,
+30,
+33,
+36,
+39,
+42,
+45,
+48,
+51,
+54,
+57,
+60,
+63,
+66,
+69,
+72,
+73,
+74,
+75,
+76,
+77,
+78,
+79,
+80,
+81,
+82,
+83,
+84,
+85,
+86,
+87,
+88,
+89,
+90
diff --git a/closures/compiler/arm/rarmsri.inc b/closures/compiler/arm/rarmsri.inc
new file mode 100644
index 0000000000..b3e6f5d76f
--- /dev/null
+++ b/closures/compiler/arm/rarmsri.inc
@@ -0,0 +1,92 @@
+{ don't edit, this file is generated from armreg.dat }
+0,
+89,
+27,
+30,
+57,
+60,
+63,
+66,
+69,
+72,
+73,
+74,
+75,
+76,
+33,
+77,
+78,
+79,
+80,
+81,
+82,
+83,
+84,
+85,
+86,
+36,
+87,
+88,
+39,
+42,
+45,
+48,
+51,
+54,
+17,
+18,
+19,
+20,
+21,
+22,
+23,
+24,
+90,
+1,
+2,
+11,
+12,
+13,
+14,
+15,
+16,
+3,
+4,
+5,
+6,
+7,
+8,
+9,
+10,
+25,
+26,
+40,
+41,
+43,
+44,
+46,
+47,
+49,
+50,
+52,
+53,
+28,
+55,
+70,
+71,
+56,
+58,
+59,
+61,
+62,
+64,
+65,
+67,
+68,
+29,
+31,
+32,
+34,
+35,
+37,
+38
diff --git a/closures/compiler/arm/rarmsta.inc b/closures/compiler/arm/rarmsta.inc
new file mode 100644
index 0000000000..4180c8a244
--- /dev/null
+++ b/closures/compiler/arm/rarmsta.inc
@@ -0,0 +1,92 @@
+{ don't edit, this file is generated from armreg.dat }
+-1,
+0,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+8,
+9,
+10,
+11,
+12,
+13,
+14,
+15,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0
diff --git a/closures/compiler/arm/rarmstd.inc b/closures/compiler/arm/rarmstd.inc
new file mode 100644
index 0000000000..f6f071afca
--- /dev/null
+++ b/closures/compiler/arm/rarmstd.inc
@@ -0,0 +1,92 @@
+{ don't edit, this file is generated from armreg.dat }
+'INVALID',
+'r0',
+'r1',
+'r2',
+'r3',
+'r4',
+'r5',
+'r6',
+'r7',
+'r8',
+'r9',
+'r10',
+'r11',
+'r12',
+'r13',
+'r14',
+'r15',
+'f0',
+'f1',
+'f2',
+'f3',
+'f4',
+'f5',
+'f6',
+'f7',
+'s0',
+'s1',
+'d0',
+'s2',
+'s3',
+'d1',
+'s4',
+'s5',
+'d2',
+'s6',
+'s7',
+'d3',
+'s8',
+'s9',
+'d4',
+'s10',
+'s11',
+'d5',
+'s12',
+'s13',
+'d6',
+'s14',
+'s15',
+'d7',
+'s16',
+'s17',
+'d8',
+'s18',
+'s19',
+'d9',
+'s20',
+'s21',
+'d10',
+'s22',
+'s23',
+'d11',
+'s24',
+'s25',
+'d12',
+'s26',
+'s27',
+'d13',
+'s28',
+'s29',
+'d14',
+'s20',
+'s21',
+'d15',
+'d16',
+'d17',
+'d18',
+'d19',
+'d20',
+'d21',
+'d22',
+'d23',
+'d24',
+'d25',
+'d26',
+'d27',
+'d28',
+'d29',
+'d30',
+'d31',
+'cpsr_c',
+'fpscr'
diff --git a/closures/compiler/arm/rarmsup.inc b/closures/compiler/arm/rarmsup.inc
new file mode 100644
index 0000000000..cfcf09bbaa
--- /dev/null
+++ b/closures/compiler/arm/rarmsup.inc
@@ -0,0 +1,92 @@
+{ don't edit, this file is generated from armreg.dat }
+RS_NO = $00;
+RS_R0 = $00;
+RS_R1 = $01;
+RS_R2 = $02;
+RS_R3 = $03;
+RS_R4 = $04;
+RS_R5 = $05;
+RS_R6 = $06;
+RS_R7 = $07;
+RS_R8 = $08;
+RS_R9 = $09;
+RS_R10 = $0a;
+RS_R11 = $0b;
+RS_R12 = $0c;
+RS_R13 = $0d;
+RS_R14 = $0e;
+RS_R15 = $0f;
+RS_F0 = $00;
+RS_F1 = $01;
+RS_F2 = $02;
+RS_F3 = $03;
+RS_F4 = $04;
+RS_F5 = $05;
+RS_F6 = $06;
+RS_F7 = $07;
+RS_S0 = $00;
+RS_S1 = $00;
+RS_D0 = $00;
+RS_S2 = $01;
+RS_S3 = $01;
+RS_D1 = $01;
+RS_S4 = $02;
+RS_S5 = $02;
+RS_D2 = $02;
+RS_S6 = $03;
+RS_S7 = $03;
+RS_D3 = $03;
+RS_S8 = $04;
+RS_S9 = $04;
+RS_D4 = $04;
+RS_S10 = $05;
+RS_S11 = $05;
+RS_D5 = $05;
+RS_S12 = $06;
+RS_S13 = $06;
+RS_D6 = $06;
+RS_S14 = $07;
+RS_S15 = $07;
+RS_D7 = $07;
+RS_S16 = $08;
+RS_S17 = $08;
+RS_D8 = $08;
+RS_S18 = $09;
+RS_S19 = $09;
+RS_D9 = $09;
+RS_S20 = $0A;
+RS_S21 = $0A;
+RS_D10 = $0A;
+RS_S22 = $0B;
+RS_S23 = $0B;
+RS_D11 = $0B;
+RS_S24 = $0C;
+RS_S25 = $0C;
+RS_D12 = $0C;
+RS_S26 = $0D;
+RS_S27 = $0D;
+RS_D13 = $0D;
+RS_S28 = $0E;
+RS_S29 = $0E;
+RS_D14 = $0E;
+RS_S30 = $0F;
+RS_S31 = $0F;
+RS_D15 = $0F;
+RS_D16 = $10;
+RS_D17 = $11;
+RS_D18 = $12;
+RS_D19 = $13;
+RS_D20 = $14;
+RS_D21 = $15;
+RS_D22 = $16;
+RS_D23 = $17;
+RS_D24 = $18;
+RS_D25 = $19;
+RS_D26 = $1A;
+RS_D27 = $1B;
+RS_D28 = $1C;
+RS_D29 = $1D;
+RS_D30 = $1E;
+RS_D31 = $1F;
+RS_CPSR_C = $00;
+RS_FPSCR = $01;
diff --git a/closures/compiler/arm/rgcpu.pas b/closures/compiler/arm/rgcpu.pas
new file mode 100644
index 0000000000..bad81c5e7f
--- /dev/null
+++ b/closures/compiler/arm/rgcpu.pas
@@ -0,0 +1,404 @@
+{
+ Copyright (c) 1998-2003 by Florian Klaempfl
+
+ This unit implements the arm specific class for the register
+ allocator
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+
+unit rgcpu;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ aasmbase,aasmtai,aasmdata,aasmcpu,
+ cgbase,cgutils,
+ cpubase,
+ rgobj;
+
+ type
+ trgcpu = class(trgobj)
+ procedure do_spill_read(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister);override;
+ procedure do_spill_written(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister);override;
+ procedure add_constraints(reg:tregister);override;
+ function get_spill_subreg(r:tregister) : tsubregister;override;
+ end;
+
+ trgcputhumb2 = class(trgobj)
+ procedure do_spill_read(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister);override;
+ procedure do_spill_written(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister);override;
+ end;
+
+ trgintcputhumb2 = class(trgcputhumb2)
+ procedure add_cpu_interferences(p : tai);override;
+ end;
+
+ trgintcpu = class(trgcpu)
+ procedure add_cpu_interferences(p : tai);override;
+ end;
+
+ implementation
+
+ uses
+ verbose, cutils,globtype,
+ cgobj,
+ procinfo;
+
+ procedure trgintcputhumb2.add_cpu_interferences(p: tai);
+ var
+ r : tregister;
+ begin
+ if p.typ=ait_instruction then
+ begin
+ case taicpu(p).opcode of
+ A_ADD:
+ begin
+ if taicpu(p).ops = 3 then
+ begin
+ if (taicpu(p).oper[0]^.typ = top_reg) and
+ (taicpu(p).oper[1]^.typ = top_reg) and
+ (taicpu(p).oper[2]^.typ in [top_reg, top_shifterop]) then
+ begin
+ { if d == 13 || (d == 15 && S == ‘0’) || n == 15 || m IN [13,15] then UNPREDICTABLE; }
+ add_edge(getsupreg(taicpu(p).oper[0]^.reg), RS_R13);
+ if taicpu(p).oppostfix <> PF_S then
+ add_edge(getsupreg(taicpu(p).oper[0]^.reg), RS_R15);
+
+ add_edge(getsupreg(taicpu(p).oper[1]^.reg), RS_R15);
+
+ if (taicpu(p).oper[2]^.typ = top_shifterop) and
+ (taicpu(p).oper[2]^.shifterop^.rs <> NR_NO) then
+ begin
+ add_edge(getsupreg(taicpu(p).oper[2]^.shifterop^.rs), RS_R13);
+ add_edge(getsupreg(taicpu(p).oper[2]^.shifterop^.rs), RS_R15);
+ end
+ else if (taicpu(p).oper[2]^.typ = top_reg) then
+ begin
+ add_edge(getsupreg(taicpu(p).oper[2]^.reg), RS_R13);
+ add_edge(getsupreg(taicpu(p).oper[2]^.reg), RS_R15);
+ end;
+ end;
+ end;
+ end;
+ A_LDRB,
+ A_STRB,
+ A_STR,
+ A_LDR,
+ A_LDRH,
+ A_STRH,
+ A_LDRSB,
+ A_LDRSH,
+ A_LDRD,
+ A_STRD:
+ { don't mix up the framepointer and stackpointer with pre/post indexed operations }
+ if (taicpu(p).oper[1]^.typ=top_ref) and
+ (taicpu(p).oper[1]^.ref^.addressmode in [AM_PREINDEXED,AM_POSTINDEXED]) then
+ begin
+ add_edge(getsupreg(taicpu(p).oper[1]^.ref^.base),getsupreg(current_procinfo.framepointer));
+ { FIXME: temp variable r is needed here to avoid Internal error 20060521 }
+ { while compiling the compiler. }
+ r:=NR_STACK_POINTER_REG;
+ if current_procinfo.framepointer<>r then
+ add_edge(getsupreg(taicpu(p).oper[1]^.ref^.base),getsupreg(r));
+ end;
+ end;
+ end;
+ end;
+
+
+ procedure trgcpu.do_spill_read(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister);
+ var
+ tmpref : treference;
+ helplist : TAsmList;
+ l : tasmlabel;
+ hreg : tregister;
+ begin
+ { don't load spilled register between
+ mov lr,pc
+ mov pc,r4
+ but befure the mov lr,pc
+ }
+ if assigned(pos.previous) and
+ (pos.typ=ait_instruction) and
+ (taicpu(pos).opcode=A_MOV) and
+ (taicpu(pos).oper[0]^.typ=top_reg) and
+ (taicpu(pos).oper[0]^.reg=NR_R14) and
+ (taicpu(pos).oper[1]^.typ=top_reg) and
+ (taicpu(pos).oper[1]^.reg=NR_PC) then
+ pos:=tai(pos.previous);
+
+ if abs(spilltemp.offset)>4095 then
+ begin
+ helplist:=TAsmList.create;
+ reference_reset(tmpref,sizeof(aint));
+ { create consts entry }
+ current_asmdata.getjumplabel(l);
+ cg.a_label(current_procinfo.aktlocaldata,l);
+ tmpref.symboldata:=current_procinfo.aktlocaldata.last;
+
+ current_procinfo.aktlocaldata.concat(tai_const.Create_32bit(spilltemp.offset));
+
+ { load consts entry }
+ if getregtype(tempreg)=R_INTREGISTER then
+ hreg:=getregisterinline(helplist,[R_SUBWHOLE])
+ else
+ hreg:=cg.getintregister(helplist,OS_ADDR);
+
+ tmpref.symbol:=l;
+ tmpref.base:=NR_R15;
+ helplist.concat(taicpu.op_reg_ref(A_LDR,hreg,tmpref));
+
+ reference_reset_base(tmpref,current_procinfo.framepointer,0,sizeof(aint));
+ tmpref.index:=hreg;
+
+ if spilltemp.index<>NR_NO then
+ internalerror(200401263);
+
+ helplist.concat(spilling_create_load(tmpref,tempreg));
+ if getregtype(tempreg)=R_INTREGISTER then
+ ungetregisterinline(helplist,hreg);
+
+ list.insertlistafter(pos,helplist);
+ helplist.free;
+ end
+ else
+ inherited do_spill_read(list,pos,spilltemp,tempreg);
+ end;
+
+
+ procedure trgcpu.do_spill_written(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister);
+ var
+ tmpref : treference;
+ helplist : TAsmList;
+ l : tasmlabel;
+ hreg : tregister;
+ begin
+ if abs(spilltemp.offset)>4095 then
+ begin
+ helplist:=TAsmList.create;
+ reference_reset(tmpref,sizeof(aint));
+ { create consts entry }
+ current_asmdata.getjumplabel(l);
+ cg.a_label(current_procinfo.aktlocaldata,l);
+ tmpref.symboldata:=current_procinfo.aktlocaldata.last;
+
+ current_procinfo.aktlocaldata.concat(tai_const.Create_32bit(spilltemp.offset));
+
+ { load consts entry }
+ if getregtype(tempreg)=R_INTREGISTER then
+ hreg:=getregisterinline(helplist,[R_SUBWHOLE])
+ else
+ hreg:=cg.getintregister(helplist,OS_ADDR);
+ tmpref.symbol:=l;
+ tmpref.base:=NR_R15;
+ helplist.concat(taicpu.op_reg_ref(A_LDR,hreg,tmpref));
+
+ if spilltemp.index<>NR_NO then
+ internalerror(200401263);
+
+ reference_reset_base(tmpref,current_procinfo.framepointer,0,sizeof(pint));
+ tmpref.index:=hreg;
+
+ helplist.concat(spilling_create_store(tempreg,tmpref));
+
+ if getregtype(tempreg)=R_INTREGISTER then
+ ungetregisterinline(helplist,hreg);
+
+ list.insertlistafter(pos,helplist);
+ helplist.free;
+ end
+ else
+ inherited do_spill_written(list,pos,spilltemp,tempreg);
+ end;
+
+
+ procedure trgcpu.add_constraints(reg:tregister);
+ var
+ supreg,i : Tsuperregister;
+ begin
+ case getsubreg(reg) of
+ { Let 32bit floats conflict with all double precision regs > 15
+ (since these don't have 32 bit equivalents) }
+ R_SUBFS:
+ begin
+ supreg:=getsupreg(reg);
+ for i:=RS_D16 to RS_D31 do
+ add_edge(supreg,i);
+ end;
+ end;
+ end;
+
+
+ function trgcpu.get_spill_subreg(r:tregister) : tsubregister;
+ begin
+ if (getregtype(r)<>R_MMREGISTER) then
+ result:=defaultsub
+ else
+ result:=getsubreg(r);
+ end;
+
+
+ procedure trgcputhumb2.do_spill_read(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister);
+ var
+ tmpref : treference;
+ helplist : TAsmList;
+ l : tasmlabel;
+ hreg : tregister;
+ begin
+ { don't load spilled register between
+ mov lr,pc
+ mov pc,r4
+ but befure the mov lr,pc
+ }
+ if assigned(pos.previous) and
+ (pos.typ=ait_instruction) and
+ (taicpu(pos).opcode=A_MOV) and
+ (taicpu(pos).oper[0]^.typ=top_reg) and
+ (taicpu(pos).oper[0]^.reg=NR_R14) and
+ (taicpu(pos).oper[1]^.typ=top_reg) and
+ (taicpu(pos).oper[1]^.reg=NR_PC) then
+ pos:=tai(pos.previous);
+
+ if (spilltemp.offset>4095) or (spilltemp.offset<-255) then
+ begin
+ helplist:=TAsmList.create;
+ reference_reset(tmpref,sizeof(aint));
+ { create consts entry }
+ current_asmdata.getjumplabel(l);
+ cg.a_label(current_procinfo.aktlocaldata,l);
+ tmpref.symboldata:=current_procinfo.aktlocaldata.last;
+
+ current_procinfo.aktlocaldata.concat(tai_const.Create_32bit(spilltemp.offset));
+
+ { load consts entry }
+ if getregtype(tempreg)=R_INTREGISTER then
+ hreg:=getregisterinline(helplist,[R_SUBWHOLE])
+ else
+ hreg:=cg.getintregister(helplist,OS_ADDR);
+
+ tmpref.symbol:=l;
+ tmpref.base:=NR_R15;
+ helplist.concat(taicpu.op_reg_ref(A_LDR,hreg,tmpref));
+
+ reference_reset_base(tmpref,current_procinfo.framepointer,0,sizeof(aint));
+ tmpref.index:=hreg;
+
+ if spilltemp.index<>NR_NO then
+ internalerror(200401263);
+
+ helplist.concat(spilling_create_load(tmpref,tempreg));
+ if getregtype(tempreg)=R_INTREGISTER then
+ ungetregisterinline(helplist,hreg);
+
+ list.insertlistafter(pos,helplist);
+ helplist.free;
+ end
+ else
+ inherited do_spill_read(list,pos,spilltemp,tempreg);
+ end;
+
+
+ procedure trgcputhumb2.do_spill_written(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister);
+ var
+ tmpref : treference;
+ helplist : TAsmList;
+ l : tasmlabel;
+ hreg : tregister;
+ begin
+ if (spilltemp.offset>4095) or (spilltemp.offset<-255) then
+ begin
+ helplist:=TAsmList.create;
+ reference_reset(tmpref,sizeof(aint));
+ { create consts entry }
+ current_asmdata.getjumplabel(l);
+ cg.a_label(current_procinfo.aktlocaldata,l);
+ tmpref.symboldata:=current_procinfo.aktlocaldata.last;
+
+ current_procinfo.aktlocaldata.concat(tai_const.Create_32bit(spilltemp.offset));
+
+ { load consts entry }
+ if getregtype(tempreg)=R_INTREGISTER then
+ hreg:=getregisterinline(helplist,[R_SUBWHOLE])
+ else
+ hreg:=cg.getintregister(helplist,OS_ADDR);
+ tmpref.symbol:=l;
+ tmpref.base:=NR_R15;
+ helplist.concat(taicpu.op_reg_ref(A_LDR,hreg,tmpref));
+
+ if spilltemp.index<>NR_NO then
+ internalerror(200401263);
+
+ reference_reset_base(tmpref,current_procinfo.framepointer,0,sizeof(pint));
+ tmpref.index:=hreg;
+
+ helplist.concat(spilling_create_store(tempreg,tmpref));
+
+ if getregtype(tempreg)=R_INTREGISTER then
+ ungetregisterinline(helplist,hreg);
+
+ list.insertlistafter(pos,helplist);
+ helplist.free;
+ end
+ else
+ inherited do_spill_written(list,pos,spilltemp,tempreg);
+ end;
+
+
+ procedure trgintcpu.add_cpu_interferences(p : tai);
+ var
+ r : tregister;
+ begin
+ if p.typ=ait_instruction then
+ begin
+ case taicpu(p).opcode of
+ A_MUL:
+ add_edge(getsupreg(taicpu(p).oper[0]^.reg),getsupreg(taicpu(p).oper[1]^.reg));
+ A_UMULL,
+ A_UMLAL,
+ A_SMULL,
+ A_SMLAL:
+ begin
+ add_edge(getsupreg(taicpu(p).oper[0]^.reg),getsupreg(taicpu(p).oper[1]^.reg));
+ add_edge(getsupreg(taicpu(p).oper[1]^.reg),getsupreg(taicpu(p).oper[2]^.reg));
+ add_edge(getsupreg(taicpu(p).oper[0]^.reg),getsupreg(taicpu(p).oper[2]^.reg));
+ end;
+ A_LDRB,
+ A_STRB,
+ A_STR,
+ A_LDR,
+ A_LDRH,
+ A_STRH:
+ { don't mix up the framepointer and stackpointer with pre/post indexed operations }
+ if (taicpu(p).oper[1]^.typ=top_ref) and
+ (taicpu(p).oper[1]^.ref^.addressmode in [AM_PREINDEXED,AM_POSTINDEXED]) then
+ begin
+ add_edge(getsupreg(taicpu(p).oper[1]^.ref^.base),getsupreg(current_procinfo.framepointer));
+ { FIXME: temp variable r is needed here to avoid Internal error 20060521 }
+ { while compiling the compiler. }
+ r:=NR_STACK_POINTER_REG;
+ if current_procinfo.framepointer<>r then
+ add_edge(getsupreg(taicpu(p).oper[1]^.ref^.base),getsupreg(r));
+ end;
+ end;
+ end;
+ end;
+
+
+end.
diff --git a/closures/compiler/asmutils.pas b/closures/compiler/asmutils.pas
new file mode 100644
index 0000000000..570f598016
--- /dev/null
+++ b/closures/compiler/asmutils.pas
@@ -0,0 +1,131 @@
+{
+ Copyright (c) 1998-2006 by Florian Klaempfl
+
+ This unit contains utility functions for assembler output
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit asmutils;
+
+interface
+
+{$i fpcdefs.inc}
+
+uses
+ globtype,
+ aasmbase,
+ aasmdata;
+
+
+ function emit_ansistring_const(list:TAsmList;data:PChar;len:LongInt;encoding:tstringencoding;NewSection:Boolean=True):TAsmLabel;
+ function emit_unicodestring_const(list:TAsmList;data:Pointer;encoding:tstringencoding;Winlike:Boolean):TAsmLabel;
+
+
+implementation
+
+uses
+ globals,
+ systems,
+ verbose,
+ aasmtai,
+ widestr,
+ symdef;
+
+ function emit_ansistring_const(list:TAsmList;data:PChar;len:LongInt;encoding:tstringencoding;NewSection:Boolean): TAsmLabel;
+ var
+ referencelab: TAsmLabel;
+ s: PChar;
+ begin
+ current_asmdata.getdatalabel(result);
+ if NewSection then
+ new_section(list,sec_rodata,result.name,const_align(sizeof(pint)));
+ referencelab := nil;
+ if target_info.system in systems_darwin then
+ begin
+ current_asmdata.getdatalabel(referencelab);
+ list.concat(tai_label.create(referencelab));
+ end;
+ list.concat(tai_const.create_16bit(encoding));
+ list.concat(tai_const.create_16bit(1));
+{$ifdef cpu64bitaddr}
+ { dummy for alignment }
+ list.concat(tai_const.create_32bit(0));
+{$endif cpu64bitaddr}
+ list.concat(tai_const.create_pint(-1));
+ list.concat(tai_const.create_pint(len));
+ { make sure the string doesn't get dead stripped if the header is referenced }
+ if target_info.system in systems_darwin then
+ list.concat(tai_directive.create(asd_reference,result.name));
+ list.concat(tai_label.create(result));
+ { and vice versa }
+ if target_info.system in systems_darwin then
+ list.concat(tai_directive.create(asd_reference,referencelab.name));
+
+ getmem(s,len+1);
+ move(data^,s^,len);
+ s[len]:=#0;
+ list.concat(tai_string.create_pchar(s,len+1)); { terminating zero included }
+ end;
+
+
+ function emit_unicodestring_const(list:TAsmList;data:Pointer;encoding:tstringencoding;Winlike:Boolean):TAsmLabel;
+ var
+ referencelab: TAsmLabel;
+ i, strlength: SizeInt;
+ begin
+ current_asmdata.getdatalabel(result);
+ new_section(list,sec_rodata,result.name,const_align(sizeof(pint)));
+ referencelab := nil;
+ if target_info.system in systems_darwin then
+ begin
+ current_asmdata.getdatalabel(referencelab);
+ list.concat(tai_label.create(referencelab));
+ end;
+ strlength := getlengthwidestring(pcompilerwidestring(data));
+ if Winlike then
+ list.concat(Tai_const.Create_32bit(strlength*cwidechartype.size))
+ else
+ begin
+ list.concat(tai_const.create_16bit(encoding));
+ list.concat(tai_const.create_16bit(2));
+ {$ifdef cpu64bitaddr}
+ { dummy for alignment }
+ list.concat(Tai_const.Create_32bit(0));
+ {$endif cpu64bitaddr}
+ list.concat(Tai_const.Create_pint(-1));
+ list.concat(Tai_const.Create_pint(strlength));
+ end;
+ { make sure the string doesn't get dead stripped if the header is referenced }
+ if (target_info.system in systems_darwin) then
+ list.concat(tai_directive.create(asd_reference,result.name));
+ list.concat(Tai_label.Create(result));
+ { ... and vice versa }
+ if (target_info.system in systems_darwin) then
+ list.concat(tai_directive.create(asd_reference,referencelab.name));
+ if cwidechartype.size = 2 then
+ begin
+ for i:=0 to strlength-1 do
+ list.concat(Tai_const.Create_16bit(pcompilerwidestring(data)^.data[i]));
+ { ending #0 }
+ list.concat(Tai_const.Create_16bit(0));
+ end
+ else
+ InternalError(200904271); { codegeneration for other sizes must be written }
+ end;
+
+
+end.
diff --git a/closures/compiler/assemble.pas b/closures/compiler/assemble.pas
new file mode 100644
index 0000000000..5bf009404a
--- /dev/null
+++ b/closures/compiler/assemble.pas
@@ -0,0 +1,1669 @@
+{
+ Copyright (c) 1998-2004 by Peter Vreman
+
+ This unit handles the assemblerfile write and assembler calls of FPC
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+{# @abstract(This unit handles the assembler file write and assembler calls of FPC)
+ Handles the calls to the actual external assemblers, as well as the generation
+ of object files for smart linking. Also contains the base class for writing
+ the assembler statements to file.
+}
+unit assemble;
+
+{$i fpcdefs.inc}
+
+interface
+
+
+ uses
+ SysUtils,
+ systems,globtype,globals,aasmbase,aasmtai,aasmdata,ogbase,finput;
+
+ const
+ { maximum of aasmoutput lists there will be }
+ maxoutputlists = ord(high(tasmlisttype))+1;
+ { buffer size for writing the .s file }
+ AsmOutSize=32768*4;
+
+ type
+ TAssembler=class(TAbstractAssembler)
+ public
+ {filenames}
+ path : string;
+ name : string;
+ AsmFileName, { current .s and .o file }
+ ObjFileName,
+ ppufilename : string;
+ asmprefix : string;
+ SmartAsm : boolean;
+ SmartFilesCount,
+ SmartHeaderCount : longint;
+ Constructor Create(smart:boolean);virtual;
+ Destructor Destroy;override;
+ procedure NextSmartName(place:tcutplace);
+ procedure MakeObject;virtual;abstract;
+ end;
+
+ {# This is the base class which should be overridden for each each
+ assembler writer. It is used to actually assembler a file,
+ and write the output to the assembler file.
+ }
+ TExternalAssembler=class(TAssembler)
+ private
+ procedure CreateSmartLinkPath(const s:string);
+ protected
+ {outfile}
+ AsmSize,
+ AsmStartSize,
+ outcnt : longint;
+ outbuf : array[0..AsmOutSize-1] of char;
+ outfile : file;
+ ioerror : boolean;
+ {input source info}
+ lastfileinfo : tfileposinfo;
+ infile,
+ lastinfile : tinputfile;
+ {last section type written}
+ lastsectype : TAsmSectionType;
+ procedure WriteSourceLine(hp: tailineinfo);
+ procedure WriteTempalloc(hp: tai_tempalloc);
+ public
+ {# Returns the complete path and executable name of the assembler
+ program.
+
+ It first tries looking in the UTIL directory if specified,
+ otherwise it searches in the free pascal binary directory, in
+ the current working directory and then in the directories
+ in the $PATH environment.}
+ Function FindAssembler:string;
+
+ {# Actually does the call to the assembler file. Returns false
+ if the assembling of the file failed.}
+ Function CallAssembler(const command:string; const para:TCmdStr):Boolean;
+
+ Function DoAssemble:boolean;virtual;
+ Procedure RemoveAsm;
+ Procedure AsmFlush;
+ Procedure AsmClear;
+
+ {# Write a string to the assembler file }
+ Procedure AsmWrite(const s:string);
+
+ {# Write a string to the assembler file }
+ Procedure AsmWritePChar(p:pchar);
+
+ {# Write a string to the assembler file followed by a new line }
+ Procedure AsmWriteLn(const s:string);
+
+ {# Write a new line to the assembler file }
+ Procedure AsmLn;
+
+ procedure AsmCreate(Aplace:tcutplace);
+ procedure AsmClose;
+
+ {# This routine should be overridden for each assembler, it is used
+ to actually write the abstract assembler stream to file.}
+ procedure WriteTree(p:TAsmList);virtual;
+
+ {# This routine should be overridden for each assembler, it is used
+ to actually write all the different abstract assembler streams
+ by calling for each stream type, the @var(WriteTree) method.}
+ procedure WriteAsmList;virtual;
+
+ {# Constructs the command line for calling the assembler }
+ function MakeCmdLine: TCmdStr; virtual;
+ public
+ Constructor Create(smart:boolean);override;
+ procedure MakeObject;override;
+ end;
+
+ { TInternalAssembler }
+
+ TInternalAssembler=class(TAssembler)
+ private
+ FCObjOutput : TObjOutputclass;
+ { the aasmoutput lists that need to be processed }
+ lists : byte;
+ list : array[1..maxoutputlists] of TAsmList;
+ { current processing }
+ currlistidx : byte;
+ currlist : TAsmList;
+ procedure WriteStab(p:pchar);
+ function MaybeNextList(var hp:Tai):boolean;
+ function SetIndirectToSymbol(hp: Tai; const indirectname: string): Boolean;
+ function TreePass0(hp:Tai):Tai;
+ function TreePass1(hp:Tai):Tai;
+ function TreePass2(hp:Tai):Tai;
+ procedure writetree;
+ procedure writetreesmart;
+ protected
+ ObjData : TObjData;
+ ObjOutput : tObjOutput;
+ property CObjOutput:TObjOutputclass read FCObjOutput write FCObjOutput;
+ public
+ constructor create(smart:boolean);override;
+ destructor destroy;override;
+ procedure MakeObject;override;
+ end;
+
+ TAssemblerClass = class of TAssembler;
+
+ Procedure GenerateAsm(smart:boolean);
+ Procedure OnlyAsm;
+
+ procedure RegisterAssembler(const r:tasminfo;c:TAssemblerClass);
+
+
+Implementation
+
+ uses
+{$ifdef hasunix}
+ unix,
+{$endif}
+ cutils,cfileutl,
+{$ifdef memdebug}
+ cclasses,
+{$endif memdebug}
+ script,fmodule,verbose,
+{$if defined(m68k) or defined(arm)}
+ cpuinfo,
+{$endif m68k or arm}
+ aasmcpu,
+ owbase,owar
+ ;
+
+ var
+ CAssembler : array[tasm] of TAssemblerClass;
+
+ function fixline(s:string):string;
+ {
+ return s with all leading and ending spaces and tabs removed
+ }
+ var
+ i,j,k : integer;
+ begin
+ i:=length(s);
+ while (i>0) and (s[i] in [#9,' ']) do
+ dec(i);
+ j:=1;
+ while (j<i) and (s[j] in [#9,' ']) do
+ inc(j);
+ for k:=j to i do
+ if s[k] in [#0..#31,#127..#255] then
+ s[k]:='.';
+ fixline:=Copy(s,j,i-j+1);
+ end;
+
+{*****************************************************************************
+ TAssembler
+*****************************************************************************}
+
+ Constructor TAssembler.Create(smart:boolean);
+ begin
+ { load start values }
+ AsmFileName:=current_module.AsmFilename^;
+ ObjFileName:=current_module.ObjFileName^;
+ name:=Lower(current_module.modulename^);
+ path:=current_module.outputpath^;
+ asmprefix := current_module.asmprefix^;
+ if not assigned(current_module.outputpath) then
+ ppufilename := ''
+ else
+ ppufilename := current_module.ppufilename^;
+ SmartAsm:=smart;
+ SmartFilesCount:=0;
+ SmartHeaderCount:=0;
+ SmartLinkOFiles.Clear;
+ end;
+
+
+ Destructor TAssembler.Destroy;
+ begin
+ end;
+
+
+ procedure TAssembler.NextSmartName(place:tcutplace);
+ var
+ s : string;
+ begin
+ inc(SmartFilesCount);
+ if SmartFilesCount>999999 then
+ Message(asmw_f_too_many_asm_files);
+ case place of
+ cut_begin :
+ begin
+ inc(SmartHeaderCount);
+ s:=asmprefix+tostr(SmartHeaderCount)+'h';
+ end;
+ cut_normal :
+ s:=asmprefix+tostr(SmartHeaderCount)+'s';
+ cut_end :
+ s:=asmprefix+tostr(SmartHeaderCount)+'t';
+ end;
+ AsmFileName:=Path+FixFileName(s+tostr(SmartFilesCount)+target_info.asmext);
+ ObjFileName:=Path+FixFileName(s+tostr(SmartFilesCount)+target_info.objext);
+ { insert in container so it can be cleared after the linking }
+ SmartLinkOFiles.Insert(ObjFileName);
+ end;
+
+
+{*****************************************************************************
+ TExternalAssembler
+*****************************************************************************}
+
+ Function DoPipe:boolean;
+ begin
+ DoPipe:=(cs_asm_pipe in current_settings.globalswitches) and
+ (([cs_asm_extern,cs_asm_leave,cs_link_on_target] * current_settings.globalswitches) = []) and
+ ((target_asm.id in [as_gas,as_ggas,as_darwin]));
+ end;
+
+
+ Constructor TExternalAssembler.Create(smart:boolean);
+ begin
+ inherited Create(smart);
+ if SmartAsm then
+ begin
+ path:=FixPath(ChangeFileExt(AsmFileName,target_info.smartext),false);
+ CreateSmartLinkPath(path);
+ end;
+ Outcnt:=0;
+ end;
+
+
+ procedure TExternalAssembler.CreateSmartLinkPath(const s:string);
+
+ procedure DeleteFilesWithExt(const AExt:string);
+ var
+ dir : TSearchRec;
+ begin
+ if findfirst(s+source_info.dirsep+'*'+AExt,faAnyFile,dir) = 0 then
+ begin
+ repeat
+ DeleteFile(s+source_info.dirsep+dir.name);
+ until findnext(dir) <> 0;
+ end;
+ findclose(dir);
+ end;
+
+ var
+ hs : string;
+ begin
+ if PathExists(s,false) then
+ begin
+ { the path exists, now we clean only all the .o and .s files }
+ DeleteFilesWithExt(target_info.objext);
+ DeleteFilesWithExt(target_info.asmext);
+ end
+ else
+ begin
+ hs:=s;
+ if hs[length(hs)] in ['/','\'] then
+ delete(hs,length(hs),1);
+ {$push} {$I-}
+ mkdir(hs);
+ {$pop}
+ if ioresult<>0 then;
+ end;
+ end;
+
+
+ const
+ lastas : byte=255;
+ var
+ LastASBin : TCmdStr;
+ Function TExternalAssembler.FindAssembler:string;
+ var
+ asfound : boolean;
+ UtilExe : string;
+ begin
+ asfound:=false;
+ if cs_link_on_target in current_settings.globalswitches then
+ begin
+ { If linking on target, don't add any path PM }
+ FindAssembler:=utilsprefix+ChangeFileExt(target_asm.asmbin,target_info.exeext);
+ exit;
+ end
+ else
+ UtilExe:=utilsprefix+ChangeFileExt(target_asm.asmbin,source_info.exeext);
+ if lastas<>ord(target_asm.id) then
+ begin
+ lastas:=ord(target_asm.id);
+ { is an assembler passed ? }
+ if utilsdirectory<>'' then
+ asfound:=FindFile(UtilExe,utilsdirectory,false,LastASBin);
+ if not AsFound then
+ asfound:=FindExe(UtilExe,false,LastASBin);
+ if (not asfound) and not(cs_asm_extern in current_settings.globalswitches) then
+ begin
+ Message1(exec_e_assembler_not_found,LastASBin);
+ current_settings.globalswitches:=current_settings.globalswitches+[cs_asm_extern];
+ end;
+ if asfound then
+ Message1(exec_t_using_assembler,LastASBin);
+ end;
+ FindAssembler:=LastASBin;
+ end;
+
+
+ Function TExternalAssembler.CallAssembler(const command:string; const para:TCmdStr):Boolean;
+ var
+ DosExitCode : Integer;
+ begin
+ result:=true;
+ if (cs_asm_extern in current_settings.globalswitches) then
+ begin
+ AsmRes.AddAsmCommand(command,para,name);
+ exit;
+ end;
+ try
+ FlushOutput;
+ DosExitCode := ExecuteProcess(command,para);
+ if DosExitCode <>0
+ then begin
+ Message1(exec_e_error_while_assembling,tostr(dosexitcode));
+ result:=false;
+ end;
+ except on E:EOSError do
+ begin
+ Message1(exec_e_cant_call_assembler,tostr(E.ErrorCode));
+ current_settings.globalswitches:=current_settings.globalswitches+[cs_asm_extern];
+ result:=false;
+ end;
+ end;
+ end;
+
+
+ procedure TExternalAssembler.RemoveAsm;
+ var
+ g : file;
+ begin
+ if cs_asm_leave in current_settings.globalswitches then
+ exit;
+ if cs_asm_extern in current_settings.globalswitches then
+ AsmRes.AddDeleteCommand(AsmFileName)
+ else
+ begin
+ assign(g,AsmFileName);
+ {$push} {$I-}
+ erase(g);
+ {$pop}
+ if ioresult<>0 then;
+ end;
+ end;
+
+
+ Function TExternalAssembler.DoAssemble:boolean;
+ begin
+ DoAssemble:=true;
+ if DoPipe then
+ exit;
+ if not(cs_asm_extern in current_settings.globalswitches) then
+ begin
+ if SmartAsm then
+ begin
+ if (SmartFilesCount<=1) then
+ Message1(exec_i_assembling_smart,name);
+ end
+ else
+ Message1(exec_i_assembling,name);
+ end;
+
+ if CallAssembler(FindAssembler,MakeCmdLine) then
+ RemoveAsm
+ else
+ begin
+ DoAssemble:=false;
+ GenerateError;
+ end;
+ end;
+
+
+ Procedure TExternalAssembler.AsmFlush;
+ begin
+ if outcnt>0 then
+ begin
+ { suppress i/o error }
+ {$push} {$I-}
+ BlockWrite(outfile,outbuf,outcnt);
+ {$pop}
+ ioerror:=ioerror or (ioresult<>0);
+ outcnt:=0;
+ end;
+ end;
+
+
+ Procedure TExternalAssembler.AsmClear;
+ begin
+ outcnt:=0;
+ end;
+
+
+ Procedure TExternalAssembler.AsmWrite(const s:string);
+ begin
+ if OutCnt+length(s)>=AsmOutSize then
+ AsmFlush;
+ Move(s[1],OutBuf[OutCnt],length(s));
+ inc(OutCnt,length(s));
+ inc(AsmSize,length(s));
+ end;
+
+
+ Procedure TExternalAssembler.AsmWriteLn(const s:string);
+ begin
+ AsmWrite(s);
+ AsmLn;
+ end;
+
+
+ Procedure TExternalAssembler.AsmWritePChar(p:pchar);
+ var
+ i,j : longint;
+ begin
+ i:=StrLen(p);
+ j:=i;
+ while j>0 do
+ begin
+ i:=min(j,AsmOutSize);
+ if OutCnt+i>=AsmOutSize then
+ AsmFlush;
+ Move(p[0],OutBuf[OutCnt],i);
+ inc(OutCnt,i);
+ inc(AsmSize,i);
+ dec(j,i);
+ p:=pchar(@p[i]);
+ end;
+ end;
+
+
+ Procedure TExternalAssembler.AsmLn;
+ begin
+ if OutCnt>=AsmOutSize-2 then
+ AsmFlush;
+ if (cs_link_on_target in current_settings.globalswitches) then
+ begin
+ OutBuf[OutCnt]:=target_info.newline[1];
+ inc(OutCnt);
+ inc(AsmSize);
+ if length(target_info.newline)>1 then
+ begin
+ OutBuf[OutCnt]:=target_info.newline[2];
+ inc(OutCnt);
+ inc(AsmSize);
+ end;
+ end
+ else
+ begin
+ OutBuf[OutCnt]:=source_info.newline[1];
+ inc(OutCnt);
+ inc(AsmSize);
+ if length(source_info.newline)>1 then
+ begin
+ OutBuf[OutCnt]:=source_info.newline[2];
+ inc(OutCnt);
+ inc(AsmSize);
+ end;
+ end;
+ end;
+
+
+ function TExternalAssembler.MakeCmdLine: TCmdStr;
+ begin
+ result:=target_asm.asmcmd;
+{$ifdef m68k}
+ if current_settings.cputype = cpu_MC68020 then
+ result:='-m68020 '+result
+ else
+ result:='-m68000 '+result;
+{$endif}
+{$ifdef arm}
+ if (target_info.system=system_arm_darwin) then
+ Replace(result,'$ARCH',lower(cputypestr[current_settings.cputype]));
+{$endif arm}
+ if (cs_link_on_target in current_settings.globalswitches) then
+ begin
+ Replace(result,'$ASM',maybequoted(ScriptFixFileName(AsmFileName)));
+ Replace(result,'$OBJ',maybequoted(ScriptFixFileName(ObjFileName)));
+ end
+ else
+ begin
+{$ifdef hasunix}
+ if DoPipe then
+ Replace(result,'$ASM','')
+ else
+{$endif}
+ Replace(result,'$ASM',maybequoted(AsmFileName));
+ Replace(result,'$OBJ',maybequoted(ObjFileName));
+ end;
+ end;
+
+
+ procedure TExternalAssembler.AsmCreate(Aplace:tcutplace);
+ begin
+ if SmartAsm then
+ NextSmartName(Aplace);
+{$ifdef hasunix}
+ if DoPipe then
+ begin
+ if SmartAsm then
+ begin
+ if (SmartFilesCount<=1) then
+ Message1(exec_i_assembling_smart,name);
+ end
+ else
+ Message1(exec_i_assembling_pipe,AsmFileName);
+ POpen(outfile,maybequoted(FindAssembler)+' '+MakeCmdLine,'W');
+ end
+ else
+{$endif}
+ begin
+ Assign(outfile,AsmFileName);
+ {$push} {$I-}
+ Rewrite(outfile,1);
+ {$pop}
+ if ioresult<>0 then
+ begin
+ ioerror:=true;
+ Message1(exec_d_cant_create_asmfile,AsmFileName);
+ end;
+ end;
+ outcnt:=0;
+ AsmSize:=0;
+ AsmStartSize:=0;
+ end;
+
+
+ procedure TExternalAssembler.AsmClose;
+ var
+ f : file;
+ FileAge : longint;
+ begin
+ AsmFlush;
+{$ifdef hasunix}
+ if DoPipe then
+ begin
+ if PClose(outfile) <> 0 then
+ GenerateError;
+ end
+ else
+{$endif}
+ begin
+ {Touch Assembler time to ppu time is there is a ppufilename}
+ if ppufilename<>'' then
+ begin
+ Assign(f,ppufilename);
+ {$push} {$I-}
+ reset(f,1);
+ {$pop}
+ if ioresult=0 then
+ begin
+ FileAge := FileGetDate(GetFileHandle(f));
+ close(f);
+ reset(outfile,1);
+ FileSetDate(GetFileHandle(outFile),FileAge);
+ end;
+ end;
+ close(outfile);
+ end;
+ end;
+
+ procedure TExternalAssembler.WriteSourceLine(hp: tailineinfo);
+ begin
+ { load infile }
+ if lastfileinfo.fileindex<>hp.fileinfo.fileindex then
+ begin
+ infile:=current_module.sourcefiles.get_file(hp.fileinfo.fileindex);
+ if assigned(infile) then
+ begin
+ { open only if needed !! }
+ if (cs_asm_source in current_settings.globalswitches) then
+ infile.open;
+ end;
+ { avoid unnecessary reopens of the same file !! }
+ lastfileinfo.fileindex:=hp.fileinfo.fileindex;
+ { be sure to change line !! }
+ lastfileinfo.line:=-1;
+ end;
+ { write source }
+ if (cs_asm_source in current_settings.globalswitches) and
+ assigned(infile) then
+ begin
+ if (infile<>lastinfile) then
+ begin
+ AsmWriteLn(target_asm.comment+'['+infile.name^+']');
+ if assigned(lastinfile) then
+ lastinfile.close;
+ end;
+ if (hp.fileinfo.line<>lastfileinfo.line) and
+ (hp.fileinfo.line<infile.maxlinebuf) then
+ begin
+ if (hp.fileinfo.line<>0) and
+ (infile.linebuf^[hp.fileinfo.line]>=0) then
+ AsmWriteLn(target_asm.comment+'['+tostr(hp.fileinfo.line)+'] '+
+ fixline(infile.GetLineStr(hp.fileinfo.line)));
+ { set it to a negative value !
+ to make that is has been read already !! PM }
+ if (infile.linebuf^[hp.fileinfo.line]>=0) then
+ infile.linebuf^[hp.fileinfo.line]:=-infile.linebuf^[hp.fileinfo.line]-1;
+ end;
+ end;
+ lastfileinfo:=hp.fileinfo;
+ lastinfile:=infile;
+ end;
+
+ procedure TExternalAssembler.WriteTempalloc(hp: tai_tempalloc);
+ begin
+{$ifdef EXTDEBUG}
+ if assigned(hp.problem) then
+ AsmWriteLn(target_asm.comment+'Temp '+tostr(hp.temppos)+','+
+ tostr(hp.tempsize)+' '+hp.problem^)
+ else
+{$endif EXTDEBUG}
+ AsmWriteLn(target_asm.comment+'Temp '+tostr(hp.temppos)+','+
+ tostr(hp.tempsize)+' '+tempallocstr[hp.allocation]);
+ end;
+
+ procedure TExternalAssembler.WriteTree(p:TAsmList);
+ begin
+ end;
+
+
+ procedure TExternalAssembler.WriteAsmList;
+ begin
+ end;
+
+
+ procedure TExternalAssembler.MakeObject;
+ begin
+ AsmCreate(cut_normal);
+ FillChar(lastfileinfo, sizeof(lastfileinfo), 0);
+ lastfileinfo.line := -1;
+ lastinfile := nil;
+ lastsectype := sec_none;
+ WriteAsmList;
+ AsmClose;
+ if not(ioerror) then
+ DoAssemble;
+ end;
+
+
+{*****************************************************************************
+ TInternalAssembler
+*****************************************************************************}
+
+ constructor TInternalAssembler.create(smart:boolean);
+ begin
+ inherited create(smart);
+ ObjOutput:=nil;
+ ObjData:=nil;
+ SmartAsm:=smart;
+ end;
+
+
+ destructor TInternalAssembler.destroy;
+ begin
+ if assigned(ObjData) then
+ ObjData.free;
+ if assigned(ObjOutput) then
+ ObjOutput.free;
+ end;
+
+
+ procedure TInternalAssembler.WriteStab(p:pchar);
+
+ function consumecomma(var p:pchar):boolean;
+ begin
+ while (p^=' ') do
+ inc(p);
+ result:=(p^=',');
+ inc(p);
+ end;
+
+ function consumenumber(var p:pchar;out value:longint):boolean;
+ var
+ hs : string;
+ len,
+ code : integer;
+ begin
+ value:=0;
+ while (p^=' ') do
+ inc(p);
+ len:=0;
+ while (p^ in ['0'..'9']) do
+ begin
+ inc(len);
+ hs[len]:=p^;
+ inc(p);
+ end;
+ if len>0 then
+ begin
+ hs[0]:=chr(len);
+ val(hs,value,code);
+ end
+ else
+ code:=-1;
+ result:=(code=0);
+ end;
+
+ function consumeoffset(var p:pchar;out relocsym:tobjsymbol;out value:longint):boolean;
+ var
+ hs : string;
+ len,
+ code : integer;
+ pstart : pchar;
+ sym : tobjsymbol;
+ exprvalue : longint;
+ gotmin,
+ have_first_symbol,
+ have_second_symbol,
+ dosub : boolean;
+ begin
+ result:=false;
+ value:=0;
+ relocsym:=nil;
+ gotmin:=false;
+ have_first_symbol:=false;
+ have_second_symbol:=false;
+ repeat
+ dosub:=false;
+ exprvalue:=0;
+ if gotmin then
+ begin
+ dosub:=true;
+ gotmin:=false;
+ end;
+ while (p^=' ') do
+ inc(p);
+ case p^ of
+ #0 :
+ break;
+ ' ' :
+ inc(p);
+ '0'..'9' :
+ begin
+ len:=0;
+ while (p^ in ['0'..'9']) do
+ begin
+ inc(len);
+ hs[len]:=p^;
+ inc(p);
+ end;
+ hs[0]:=chr(len);
+ val(hs,exprvalue,code);
+ if code<>0 then
+ internalerror(200702251);
+ end;
+ '.','_',
+ 'A'..'Z',
+ 'a'..'z' :
+ begin
+ pstart:=p;
+ while not(p^ in [#0,' ','-','+']) do
+ inc(p);
+ len:=p-pstart;
+ if len>255 then
+ internalerror(200509187);
+ move(pstart^,hs[1],len);
+ hs[0]:=chr(len);
+ sym:=objdata.symbolref(hs);
+ have_first_symbol:=true;
+ { Second symbol? }
+ if assigned(relocsym) then
+ begin
+ if have_second_symbol then
+ internalerror(2007032201);
+ have_second_symbol:=true;
+ if not have_first_symbol then
+ internalerror(2007032202);
+ { second symbol should substracted to first }
+ if not dosub then
+ internalerror(2007032203);
+ if (relocsym.objsection<>sym.objsection) then
+ internalerror(2005091810);
+ exprvalue:=relocsym.address-sym.address;
+ relocsym:=nil;
+ dosub:=false;
+ end
+ else
+ begin
+ relocsym:=sym;
+ if assigned(sym.objsection) then
+ begin
+ { first symbol should be + }
+ if not have_first_symbol and dosub then
+ internalerror(2007032204);
+ have_first_symbol:=true;
+ end;
+ end;
+ end;
+ '+' :
+ begin
+ { nothing, by default addition is done }
+ inc(p);
+ end;
+ '-' :
+ begin
+ gotmin:=true;
+ inc(p);
+ end;
+ else
+ internalerror(200509189);
+ end;
+ if dosub then
+ dec(value,exprvalue)
+ else
+ inc(value,exprvalue);
+ until false;
+ result:=true;
+ end;
+
+ var
+ stabstrlen,
+ ofs,
+ nline,
+ nidx,
+ nother,
+ i : longint;
+ stab : TObjStabEntry;
+ relocsym : TObjSymbol;
+ pstr,
+ pcurr,
+ pendquote : pchar;
+ oldsec : TObjSection;
+ begin
+ pcurr:=nil;
+ pstr:=nil;
+ pendquote:=nil;
+ relocsym:=nil;
+ ofs:=0;
+
+ { Parse string part }
+ if (p[0]='"') then
+ begin
+ pstr:=@p[1];
+ { Ignore \" inside the string }
+ i:=1;
+ while not((p[i]='"') and (p[i-1]<>'\')) and
+ (p[i]<>#0) do
+ inc(i);
+ pendquote:=@p[i];
+ pendquote^:=#0;
+ pcurr:=@p[i+1];
+ if not consumecomma(pcurr) then
+ internalerror(200509181);
+ end
+ else
+ pcurr:=p;
+
+ { When in pass 1 then only alloc and leave }
+ if ObjData.currpass=1 then
+ begin
+ ObjData.StabsSec.Alloc(sizeof(TObjStabEntry));
+ if assigned(pstr) and (pstr[0]<>#0) then
+ ObjData.StabStrSec.Alloc(strlen(pstr)+1);
+ end
+ else
+ begin
+ { Stabs format: nidx,nother,nline[,offset] }
+ if not consumenumber(pcurr,nidx) then
+ internalerror(200509182);
+ if not consumecomma(pcurr) then
+ internalerror(200509183);
+ if not consumenumber(pcurr,nother) then
+ internalerror(200509184);
+ if not consumecomma(pcurr) then
+ internalerror(200509185);
+ if not consumenumber(pcurr,nline) then
+ internalerror(200509186);
+ if consumecomma(pcurr) then
+ consumeoffset(pcurr,relocsym,ofs);
+
+ { Generate stab entry }
+ if assigned(pstr) and (pstr[0]<>#0) then
+ begin
+ stabstrlen:=strlen(pstr);
+{$ifdef optimizestabs}
+ StabStrEntry:=nil;
+ if (nidx=N_SourceFile) or (nidx=N_IncludeFile) then
+ begin
+ hs:=strpas(pstr);
+ StabstrEntry:=StabStrDict.Find(hs);
+ if not assigned(StabstrEntry) then
+ begin
+ StabstrEntry:=TStabStrEntry.Create(hs);
+ StabstrEntry:=StabStrSec.Size;
+ StabStrDict.Insert(StabstrEntry);
+ { generate new stab }
+ StabstrEntry:=nil;
+ end;
+ end;
+ if assigned(StabstrEntry) then
+ stab.strpos:=StabstrEntry.strpos
+ else
+{$endif optimizestabs}
+ begin
+ stab.strpos:=ObjData.StabStrSec.Size;
+ ObjData.StabStrSec.write(pstr^,stabstrlen+1);
+ end;
+ end
+ else
+ stab.strpos:=0;
+ stab.ntype:=byte(nidx);
+ stab.ndesc:=word(nline);
+ stab.nother:=byte(nother);
+ stab.nvalue:=ofs;
+
+ { Write the stab first without the value field. Then
+ write a the value field with relocation }
+ oldsec:=ObjData.CurrObjSec;
+ ObjData.SetSection(ObjData.StabsSec);
+ ObjData.Writebytes(stab,sizeof(TObjStabEntry)-4);
+ ObjData.Writereloc(stab.nvalue,4,relocsym,RELOC_ABSOLUTE32);
+ ObjData.setsection(oldsec);
+ end;
+ if assigned(pendquote) then
+ pendquote^:='"';
+ end;
+
+
+ function TInternalAssembler.MaybeNextList(var hp:Tai):boolean;
+ begin
+ { maybe end of list }
+ while not assigned(hp) do
+ begin
+ if currlistidx<lists then
+ begin
+ inc(currlistidx);
+ currlist:=list[currlistidx];
+ hp:=Tai(currList.first);
+ end
+ else
+ begin
+ MaybeNextList:=false;
+ exit;
+ end;
+ end;
+ MaybeNextList:=true;
+ end;
+
+
+ function TInternalAssembler.SetIndirectToSymbol(hp: Tai; const indirectname: string): Boolean;
+ var
+ objsym : TObjSymbol;
+ indsym : TObjSymbol;
+ begin
+ Result:=
+ Assigned(hp) and
+ (hp.typ=ait_symbol);
+ if not Result then
+ Exit;
+ objsym:=Objdata.SymbolRef(tai_symbol(hp).sym);
+ objsym.size:=0;
+
+ indsym := TObjSymbol(ObjData.ObjSymbolList.Find(indirectname));
+ if not Assigned(indsym) then
+ begin
+ { it's possible that indirect symbol is not present in the list,
+ so we must create it as undefined }
+ indsym:=TObjSymbol.Create(ObjData.ObjSymbolList, indirectname);
+ indsym.typ:=AT_NONE;
+ indsym.bind:=AB_NONE;
+ end;
+ objsym.indsymbol:=indsym;
+ Result:=true;
+ end;
+
+
+ function TInternalAssembler.TreePass0(hp:Tai):Tai;
+ var
+ objsym,
+ objsymend : TObjSymbol;
+ begin
+ while assigned(hp) do
+ begin
+ case hp.typ of
+ ait_align :
+ begin
+ if tai_align_abstract(hp).aligntype>1 then
+ begin
+ { always use the maximum fillsize in this pass to avoid possible
+ short jumps to become out of range }
+ Tai_align_abstract(hp).fillsize:=Tai_align_abstract(hp).aligntype;
+ ObjData.alloc(Tai_align_abstract(hp).fillsize);
+ end
+ else
+ Tai_align_abstract(hp).fillsize:=0;
+ end;
+ ait_datablock :
+ begin
+{$ifdef USE_COMM_IN_BSS}
+ if writingpackages and
+ Tai_datablock(hp).is_global then
+ ObjData.SymbolDefine(Tai_datablock(hp).sym)
+ else
+{$endif USE_COMM_IN_BSS}
+ begin
+ ObjData.allocalign(used_align(size_2_align(Tai_datablock(hp).size),0,ObjData.CurrObjSec.secalign));
+ ObjData.SymbolDefine(Tai_datablock(hp).sym);
+ ObjData.alloc(Tai_datablock(hp).size);
+ end;
+ end;
+ ait_real_80bit :
+ ObjData.alloc(tai_real_80bit(hp).savesize);
+ ait_real_64bit :
+ ObjData.alloc(8);
+ ait_real_32bit :
+ ObjData.alloc(4);
+ ait_comp_64bit :
+ ObjData.alloc(8);
+ ait_const:
+ begin
+ { if symbols are provided we can calculate the value for relative symbols.
+ This is required for length calculation of leb128 constants }
+ if assigned(tai_const(hp).sym) then
+ begin
+ objsym:=Objdata.SymbolRef(tai_const(hp).sym);
+ { objsym already defined and there is endsym? }
+ if assigned(objsym.objsection) and assigned(tai_const(hp).endsym) then
+ begin
+ objsymend:=Objdata.SymbolRef(tai_const(hp).endsym);
+ { objsymend already defined? }
+ if assigned(objsymend.objsection) then
+ begin
+ if objsymend.objsection<>objsym.objsection then
+ internalerror(200404124);
+ Tai_const(hp).value:=objsymend.address-objsym.address+Tai_const(hp).symofs;
+ end;
+ end;
+ end;
+ ObjData.alloc(tai_const(hp).size);
+ end;
+ ait_directive:
+ begin
+ case tai_directive(hp).directive of
+ asd_indirect_symbol:
+ { handled in TreePass1 }
+ ;
+ asd_lazy_reference:
+ begin
+ if tai_directive(hp).name = nil then
+ Internalerror(2009112101);
+ objsym:=ObjData.symbolref(tai_directive(hp).name^);
+ objsym.bind:=AB_LAZY;
+ end;
+ asd_reference:
+ { ignore for now, but should be added}
+ ;
+ else
+ internalerror(2010011101);
+ end;
+ end;
+ ait_section:
+ begin
+ ObjData.CreateSection(Tai_section(hp).sectype,Tai_section(hp).name^,Tai_section(hp).secorder);
+ Tai_section(hp).sec:=ObjData.CurrObjSec;
+ end;
+ ait_symbol :
+ begin
+ { needs extra support in the internal assembler }
+ { the value is just ignored }
+ {if tai_symbol(hp).has_value then
+ internalerror(2009090804); ;}
+ ObjData.SymbolDefine(Tai_symbol(hp).sym);
+ end;
+ ait_label :
+ ObjData.SymbolDefine(Tai_label(hp).labsym);
+ ait_string :
+ ObjData.alloc(Tai_string(hp).len);
+ ait_instruction :
+ begin
+ { reset instructions which could change in pass 2 }
+ Taicpu(hp).resetpass2;
+ ObjData.alloc(Taicpu(hp).Pass1(ObjData));
+ end;
+ ait_cutobject :
+ if SmartAsm then
+ break;
+ end;
+ hp:=Tai(hp.next);
+ end;
+ TreePass0:=hp;
+ end;
+
+
+ function TInternalAssembler.TreePass1(hp:Tai):Tai;
+ var
+ objsym,
+ objsymend : TObjSymbol;
+ begin
+ while assigned(hp) do
+ begin
+ case hp.typ of
+ ait_align :
+ begin
+ if tai_align_abstract(hp).aligntype>1 then
+ begin
+ { here we must determine the fillsize which is used in pass2 }
+ Tai_align_abstract(hp).fillsize:=align(ObjData.CurrObjSec.Size,Tai_align_abstract(hp).aligntype)-
+ ObjData.CurrObjSec.Size;
+ ObjData.alloc(Tai_align_abstract(hp).fillsize);
+ end;
+ end;
+ ait_datablock :
+ begin
+ if (oso_data in ObjData.CurrObjSec.secoptions) then
+ Message(asmw_e_alloc_data_only_in_bss);
+{$ifdef USE_COMM_IN_BSS}
+ if writingpackages and
+ Tai_datablock(hp).is_global then
+ begin
+ objsym:=ObjData.SymbolDefine(Tai_datablock(hp).sym);
+ objsym.size:=Tai_datablock(hp).size;
+ objsym.bind:=AB_COMMON;
+ objsym.alignment:=needtowritealignmentalsoforELF;
+ end
+ else
+{$endif USE_COMM_IN_BSS}
+ begin
+ ObjData.allocalign(used_align(size_2_align(Tai_datablock(hp).size),0,ObjData.CurrObjSec.secalign));
+ objsym:=ObjData.SymbolDefine(Tai_datablock(hp).sym);
+ objsym.size:=Tai_datablock(hp).size;
+ ObjData.alloc(Tai_datablock(hp).size);
+ end;
+ end;
+ ait_real_80bit :
+ ObjData.alloc(tai_real_80bit(hp).savesize);
+ ait_real_64bit :
+ ObjData.alloc(8);
+ ait_real_32bit :
+ ObjData.alloc(4);
+ ait_comp_64bit :
+ ObjData.alloc(8);
+ ait_const:
+ begin
+ { Recalculate relative symbols }
+ if assigned(tai_const(hp).sym) and
+ assigned(tai_const(hp).endsym) then
+ begin
+ objsym:=Objdata.SymbolRef(tai_const(hp).sym);
+ objsymend:=Objdata.SymbolRef(tai_const(hp).endsym);
+ if objsymend.objsection<>objsym.objsection then
+ internalerror(200905042);
+ Tai_const(hp).value:=objsymend.address-objsym.address+Tai_const(hp).symofs;
+ end;
+ ObjData.alloc(tai_const(hp).size);
+ end;
+ ait_section:
+ begin
+ { use cached value }
+ ObjData.setsection(Tai_section(hp).sec);
+ end;
+ ait_stab :
+ begin
+ if assigned(Tai_stab(hp).str) then
+ WriteStab(Tai_stab(hp).str);
+ end;
+ ait_symbol :
+ ObjData.SymbolDefine(Tai_symbol(hp).sym);
+ ait_symbol_end :
+ begin
+ objsym:=ObjData.SymbolRef(Tai_symbol_end(hp).sym);
+ objsym.size:=ObjData.CurrObjSec.Size-objsym.offset;
+ end;
+ ait_label :
+ ObjData.SymbolDefine(Tai_label(hp).labsym);
+ ait_string :
+ ObjData.alloc(Tai_string(hp).len);
+ ait_instruction :
+ ObjData.alloc(Taicpu(hp).Pass1(ObjData));
+ ait_cutobject :
+ if SmartAsm then
+ break;
+ ait_directive :
+ begin
+ case tai_directive(hp).directive of
+ asd_indirect_symbol:
+ if tai_directive(hp).name = nil then
+ Internalerror(2009101103)
+ else if not SetIndirectToSymbol(Tai(hp.Previous), tai_directive(hp).name^) then
+ Internalerror(2009101102);
+ asd_lazy_reference:
+ { handled in TreePass0 }
+ ;
+ asd_reference:
+ { ignore for now, but should be added}
+ ;
+ else
+ internalerror(2010011102);
+ end;
+ end;
+ end;
+ hp:=Tai(hp.next);
+ end;
+ TreePass1:=hp;
+ end;
+
+
+ function TInternalAssembler.TreePass2(hp:Tai):Tai;
+ var
+ fillbuffer : tfillbuffer;
+{$ifdef x86}
+ co : comp;
+{$endif x86}
+ leblen : byte;
+ lebbuf : array[0..63] of byte;
+ objsym,
+ objsymend : TObjSymbol;
+ zerobuf : array[0..63] of byte;
+ begin
+ fillchar(zerobuf,sizeof(zerobuf),0);
+ { main loop }
+ while assigned(hp) do
+ begin
+ case hp.typ of
+ ait_align :
+ begin
+ if oso_data in ObjData.CurrObjSec.secoptions then
+ ObjData.writebytes(Tai_align_abstract(hp).calculatefillbuf(fillbuffer,oso_executable in ObjData.CurrObjSec.secoptions)^,
+ Tai_align_abstract(hp).fillsize)
+ else
+ ObjData.alloc(Tai_align_abstract(hp).fillsize);
+ end;
+ ait_section :
+ begin
+ { use cached value }
+ ObjData.setsection(Tai_section(hp).sec);
+ end;
+ ait_symbol :
+ begin
+ ObjOutput.exportsymbol(ObjData.SymbolRef(Tai_symbol(hp).sym));
+ end;
+ ait_symbol_end :
+ begin
+ { recalculate size, as some preceding instructions
+ could have been changed to smaller size }
+ objsym:=ObjData.SymbolRef(Tai_symbol_end(hp).sym);
+ objsym.size:=ObjData.CurrObjSec.Size-objsym.offset;
+ end;
+ ait_datablock :
+ begin
+ ObjOutput.exportsymbol(ObjData.SymbolRef(Tai_datablock(hp).sym));
+{$ifdef USE_COMM_IN_BSS}
+ if not(writingpackages and
+ Tai_datablock(hp).is_global) then
+{$endif USE_COMM_IN_BSS}
+ begin
+ ObjData.allocalign(used_align(size_2_align(Tai_datablock(hp).size),0,ObjData.CurrObjSec.secalign));
+ ObjData.alloc(Tai_datablock(hp).size);
+ end;
+ end;
+ ait_real_80bit :
+ begin
+ ObjData.writebytes(Tai_real_80bit(hp).value,10);
+ ObjData.writebytes(zerobuf,Tai_real_80bit(hp).savesize-10);
+ end;
+ ait_real_64bit :
+ ObjData.writebytes(Tai_real_64bit(hp).value,8);
+ ait_real_32bit :
+ ObjData.writebytes(Tai_real_32bit(hp).value,4);
+ ait_comp_64bit :
+ begin
+{$ifdef x86}
+ co:=comp(Tai_comp_64bit(hp).value);
+ ObjData.writebytes(co,8);
+{$endif x86}
+ end;
+ ait_string :
+ ObjData.writebytes(Tai_string(hp).str^,Tai_string(hp).len);
+ ait_const :
+ begin
+ { Recalculate relative symbols, addresses of forward references
+ can be changed in treepass1 }
+ if assigned(tai_const(hp).sym) and
+ assigned(tai_const(hp).endsym) then
+ begin
+ objsym:=Objdata.SymbolRef(tai_const(hp).sym);
+ objsymend:=Objdata.SymbolRef(tai_const(hp).endsym);
+ Tai_const(hp).value:=objsymend.address-objsym.address+Tai_const(hp).symofs;
+ end;
+ case tai_const(hp).consttype of
+ aitconst_64bit,
+ aitconst_32bit,
+ aitconst_16bit,
+ aitconst_8bit :
+ begin
+ if assigned(tai_const(hp).sym) and
+ not assigned(tai_const(hp).endsym) then
+ ObjData.writereloc(Tai_const(hp).symofs,tai_const(hp).size,Objdata.SymbolRef(tai_const(hp).sym),RELOC_ABSOLUTE)
+ else
+ ObjData.writebytes(Tai_const(hp).value,tai_const(hp).size);
+ end;
+ aitconst_rva_symbol :
+ begin
+ { PE32+? }
+ if target_info.system=system_x86_64_win64 then
+ ObjData.writereloc(Tai_const(hp).symofs,sizeof(longint),Objdata.SymbolRef(tai_const(hp).sym),RELOC_RVA)
+ else
+ ObjData.writereloc(Tai_const(hp).symofs,sizeof(pint),Objdata.SymbolRef(tai_const(hp).sym),RELOC_RVA);
+ end;
+ aitconst_secrel32_symbol :
+ begin
+ { Required for DWARF2 support under Windows }
+ ObjData.writereloc(Tai_const(hp).symofs,sizeof(longint),Objdata.SymbolRef(tai_const(hp).sym),RELOC_SECREL32);
+ end;
+ aitconst_uleb128bit,
+ aitconst_sleb128bit :
+ begin
+ if tai_const(hp).consttype=aitconst_uleb128bit then
+ leblen:=EncodeUleb128(qword(Tai_const(hp).value),lebbuf)
+ else
+ leblen:=EncodeSleb128(Tai_const(hp).value,lebbuf);
+ if leblen<>tai_const(hp).size then
+ internalerror(200709271);
+ ObjData.writebytes(lebbuf,leblen);
+ end;
+ aitconst_darwin_dwarf_delta32,
+ aitconst_darwin_dwarf_delta64:
+ ObjData.writebytes(Tai_const(hp).value,tai_const(hp).size);
+ else
+ internalerror(200603254);
+ end;
+ end;
+ ait_label :
+ begin
+ { exporting shouldn't be necessary as labels are local,
+ but it's better to be on the safe side (PFV) }
+ ObjOutput.exportsymbol(ObjData.SymbolRef(Tai_label(hp).labsym));
+ end;
+ ait_instruction :
+ Taicpu(hp).Pass2(ObjData);
+ ait_stab :
+ WriteStab(Tai_stab(hp).str);
+ ait_function_name,
+ ait_force_line : ;
+ ait_cutobject :
+ if SmartAsm then
+ break;
+{$ifdef TEST_WIN64_SEH}
+ ait_seh_directive :
+ tai_seh_directive(hp).generate_code(objdata);
+{$endif TEST_WIN64_SEH}
+ end;
+ hp:=Tai(hp.next);
+ end;
+ TreePass2:=hp;
+ end;
+
+
+ procedure TInternalAssembler.writetree;
+ label
+ doexit;
+ var
+ hp : Tai;
+ ObjWriter : TObjectWriter;
+ begin
+ ObjWriter:=TObjectwriter.create;
+ ObjOutput:=CObjOutput.Create(ObjWriter);
+ ObjData:=ObjOutput.newObjData(ObjFileName);
+
+ { Pass 0 }
+ ObjData.currpass:=0;
+ ObjData.createsection(sec_code);
+ ObjData.beforealloc;
+ { start with list 1 }
+ currlistidx:=1;
+ currlist:=list[currlistidx];
+ hp:=Tai(currList.first);
+ while assigned(hp) do
+ begin
+ hp:=TreePass0(hp);
+ MaybeNextList(hp);
+ end;
+ ObjData.afteralloc;
+ { leave if errors have occured }
+ if errorcount>0 then
+ goto doexit;
+
+ { Pass 1 }
+ ObjData.currpass:=1;
+ ObjData.resetsections;
+ ObjData.beforealloc;
+ ObjData.createsection(sec_code);
+ { start with list 1 }
+ currlistidx:=1;
+ currlist:=list[currlistidx];
+ hp:=Tai(currList.first);
+ while assigned(hp) do
+ begin
+ hp:=TreePass1(hp);
+ MaybeNextList(hp);
+ end;
+ ObjData.createsection(sec_code);
+ ObjData.afteralloc;
+
+ { leave if errors have occured }
+ if errorcount>0 then
+ goto doexit;
+
+ { Pass 2 }
+ ObjData.currpass:=2;
+ ObjData.resetsections;
+ ObjData.beforewrite;
+ ObjData.createsection(sec_code);
+ { start with list 1 }
+ currlistidx:=1;
+ currlist:=list[currlistidx];
+ hp:=Tai(currList.first);
+ while assigned(hp) do
+ begin
+ hp:=TreePass2(hp);
+ MaybeNextList(hp);
+ end;
+ ObjData.createsection(sec_code);
+ ObjData.afterwrite;
+
+ { don't write the .o file if errors have occured }
+ if errorcount=0 then
+ begin
+ { write objectfile }
+ ObjOutput.startobjectfile(ObjFileName);
+ ObjOutput.writeobjectfile(ObjData);
+ end;
+
+ doexit:
+ { Cleanup }
+ ObjData.free;
+ ObjData:=nil;
+ ObjWriter.free;
+ end;
+
+
+ procedure TInternalAssembler.writetreesmart;
+ var
+ hp : Tai;
+ startsectype : TAsmSectiontype;
+ place: tcutplace;
+ ObjWriter : TObjectWriter;
+ begin
+ if not(cs_asm_leave in current_settings.globalswitches) then
+ ObjWriter:=TARObjectWriter.create(current_module.staticlibfilename^)
+ else
+ ObjWriter:=TObjectwriter.create;
+
+ NextSmartName(cut_normal);
+ ObjOutput:=CObjOutput.Create(ObjWriter);
+ startsectype:=sec_code;
+
+ { start with list 1 }
+ currlistidx:=1;
+ currlist:=list[currlistidx];
+ hp:=Tai(currList.first);
+ while assigned(hp) do
+ begin
+ ObjData:=ObjOutput.newObjData(ObjFileName);
+
+ { Pass 0 }
+ ObjData.currpass:=0;
+ ObjData.resetsections;
+ ObjData.beforealloc;
+ ObjData.createsection(startsectype);
+ TreePass0(hp);
+ ObjData.afteralloc;
+ { leave if errors have occured }
+ if errorcount>0 then
+ break;
+
+ { Pass 1 }
+ ObjData.currpass:=1;
+ ObjData.resetsections;
+ ObjData.beforealloc;
+ ObjData.createsection(startsectype);
+ TreePass1(hp);
+ ObjData.afteralloc;
+
+ { leave if errors have occured }
+ if errorcount>0 then
+ break;
+
+ { Pass 2 }
+ ObjData.currpass:=2;
+ ObjOutput.startobjectfile(ObjFileName);
+ ObjData.resetsections;
+ ObjData.beforewrite;
+ ObjData.createsection(startsectype);
+ hp:=TreePass2(hp);
+ ObjData.afterwrite;
+
+ { leave if errors have occured }
+ if errorcount>0 then
+ break;
+
+ { write the current objectfile }
+ ObjOutput.writeobjectfile(ObjData);
+ ObjData.free;
+ ObjData:=nil;
+
+ { end of lists? }
+ if not MaybeNextList(hp) then
+ break;
+
+ { we will start a new objectfile so reset everything }
+ { The place can still change in the next while loop, so don't init }
+ { the writer yet (JM) }
+ if (hp.typ=ait_cutobject) then
+ place := Tai_cutobject(hp).place
+ else
+ place := cut_normal;
+
+ { avoid empty files }
+ startsectype:=sec_code;
+ while assigned(hp) and
+ (Tai(hp).typ in [ait_marker,ait_comment,ait_section,ait_cutobject]) do
+ begin
+ if Tai(hp).typ=ait_section then
+ startsectype:=Tai_section(hp).sectype;
+ if (Tai(hp).typ=ait_cutobject) then
+ place:=Tai_cutobject(hp).place;
+ hp:=Tai(hp.next);
+ end;
+
+ if not MaybeNextList(hp) then
+ break;
+
+ { start next objectfile }
+ NextSmartName(place);
+ end;
+ ObjData.free;
+ ObjData:=nil;
+ ObjWriter.free;
+ end;
+
+
+ procedure TInternalAssembler.MakeObject;
+
+ var to_do:set of TasmlistType;
+ i:TasmlistType;
+
+ procedure addlist(p:TAsmList);
+ begin
+ inc(lists);
+ list[lists]:=p;
+ end;
+
+ begin
+ to_do:=[low(Tasmlisttype)..high(Tasmlisttype)];
+ if usedeffileforexports then
+ exclude(to_do,al_exports);
+ if not(tf_section_threadvars in target_info.flags) then
+ exclude(to_do,al_threadvars);
+ for i:=low(TasmlistType) to high(TasmlistType) do
+ if (i in to_do) and (current_asmdata.asmlists[i]<>nil) then
+ addlist(current_asmdata.asmlists[i]);
+
+ if SmartAsm then
+ writetreesmart
+ else
+ writetree;
+ end;
+
+
+{*****************************************************************************
+ Generate Assembler Files Main Procedure
+*****************************************************************************}
+
+ Procedure GenerateAsm(smart:boolean);
+ var
+ a : TAssembler;
+ begin
+ if not assigned(CAssembler[target_asm.id]) then
+ Message(asmw_f_assembler_output_not_supported);
+ a:=CAssembler[target_asm.id].Create(smart);
+ a.MakeObject;
+ a.Free;
+ end;
+
+
+ Procedure OnlyAsm;
+ var
+ a : TExternalAssembler;
+ begin
+ a:=TExternalAssembler.Create(false);
+ a.DoAssemble;
+ a.Free;
+ end;
+
+
+{*****************************************************************************
+ Init/Done
+*****************************************************************************}
+
+ procedure RegisterAssembler(const r:tasminfo;c:TAssemblerClass);
+ var
+ t : tasm;
+ begin
+ t:=r.id;
+ if assigned(asminfos[t]) then
+ writeln('Warning: Assembler is already registered!')
+ else
+ Getmem(asminfos[t],sizeof(tasminfo));
+ asminfos[t]^:=r;
+ CAssembler[t]:=c;
+ end;
+
+end.
diff --git a/closures/compiler/avr/aasmcpu.pas b/closures/compiler/avr/aasmcpu.pas
new file mode 100644
index 0000000000..7d4f77e9c1
--- /dev/null
+++ b/closures/compiler/avr/aasmcpu.pas
@@ -0,0 +1,456 @@
+{
+ Copyright (c) 1999-2008 by Mazen Neifer and Florian Klaempfl
+
+ Contains the assembler object for the AVR
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit aasmcpu;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ cclasses,
+ globtype,globals,verbose,
+ aasmbase,aasmtai,aasmdata,aasmsym,
+ cgbase,cgutils,cpubase,cpuinfo,
+ ogbase;
+
+ const
+ { "mov reg,reg" source operand number }
+ O_MOV_SOURCE = 1;
+ { "mov reg,reg" source operand number }
+ O_MOV_DEST = 0;
+
+ maxinfolen = 5;
+
+ type
+ tinsentry = record
+ opcode : tasmop;
+ ops : byte;
+ optypes : array[0..3] of longint;
+ code : array[0..maxinfolen] of char;
+ flags : longint;
+ end;
+
+ pinsentry=^tinsentry;
+
+ taicpu = class(tai_cpu_abstract_sym)
+ constructor op_none(op : tasmop);
+
+ constructor op_reg(op : tasmop;_op1 : tregister);
+ constructor op_const(op : tasmop;_op1 : LongInt);
+ constructor op_ref(op : tasmop;const _op1 : treference);
+
+ constructor op_reg_reg(op : tasmop;_op1,_op2 : tregister);
+ constructor op_reg_ref(op : tasmop;_op1 : tregister;const _op2 : treference);
+ constructor op_reg_const(op:tasmop; _op1: tregister; _op2: LongInt);
+ constructor op_const_reg(op:tasmop; _op1: LongInt; _op2: tregister);
+ constructor op_ref_reg(op : tasmop;const _op1 : treference;_op2 : tregister);
+
+ { this is for Jmp instructions }
+ constructor op_cond_sym(op : tasmop;cond:TAsmCond;_op1 : tasmsymbol);
+ constructor op_sym(op : tasmop;_op1 : tasmsymbol);
+ constructor op_sym_ofs(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint);
+ procedure loadbool(opidx:longint;_b:boolean);
+ { register allocation }
+ function is_same_reg_move(regtype: Tregistertype):boolean; override;
+
+ { register spilling code }
+ function spilling_get_operation_type(opnr: longint): topertype;override;
+
+ { assembler }
+ public
+ { the next will reset all instructions that can change in pass 2 }
+ procedure ResetPass1;override;
+ procedure ResetPass2;override;
+{ function CheckIfValid:boolean;
+ function GetString:string; }
+ function Pass1(objdata:TObjData):longint;override;
+// procedure Pass2(objdata:TObjData);override;
+ function calcsize(p:PInsEntry):shortint;
+ private
+ { next fields are filled in pass1, so pass2 is faster }
+ inssize : shortint;
+ insoffset : longint;
+ insentry : PInsEntry;
+ LastInsOffset : longint; { need to be public to be reset }
+ function FindInsentry(objdata:TObjData):boolean;
+ end;
+
+ tai_align = class(tai_align_abstract)
+ { nothing to add }
+ end;
+
+ procedure InitAsm;
+ procedure DoneAsm;
+
+ function spilling_create_load(const ref:treference;r:tregister):Taicpu;
+ function spilling_create_store(r:tregister; const ref:treference):Taicpu;
+
+ function setcondition(i : taicpu;c : tasmcond) : taicpu;
+
+ { replaces cond. branches by rjmp/jmp and the inverse cond. branch if needed
+ and transforms special instructions to valid instruction encodings }
+ procedure finalizeavrcode(list : TAsmList);
+
+implementation
+
+{*****************************************************************************
+ taicpu Constructors
+*****************************************************************************}
+
+ procedure taicpu.loadbool(opidx:longint;_b:boolean);
+ begin
+ if opidx>=ops then
+ ops:=opidx+1;
+ with oper[opidx]^ do
+ begin
+ if typ=top_ref then
+ dispose(ref);
+ b:=_b;
+ typ:=top_bool;
+ end;
+ end;
+
+
+ constructor taicpu.op_none(op : tasmop);
+ begin
+ inherited create(op);
+ end;
+
+
+ constructor taicpu.op_reg(op : tasmop;_op1 : tregister);
+ begin
+ inherited create(op);
+ ops:=1;
+ loadreg(0,_op1);
+ end;
+
+
+ constructor taicpu.op_ref(op : tasmop;const _op1 : treference);
+ begin
+ inherited create(op);
+ ops:=1;
+ loadref(0,_op1);
+ end;
+
+
+ constructor taicpu.op_const(op : tasmop;_op1 : LongInt);
+ begin
+ inherited create(op);
+ ops:=1;
+ loadconst(0,_op1);
+ end;
+
+
+ constructor taicpu.op_reg_reg(op : tasmop;_op1,_op2 : tregister);
+ begin
+ inherited create(op);
+ ops:=2;
+ loadreg(0,_op1);
+ loadreg(1,_op2);
+ end;
+
+ constructor taicpu.op_reg_const(op:tasmop; _op1: tregister; _op2: LongInt);
+ begin
+ inherited create(op);
+ ops:=2;
+ loadreg(0,_op1);
+ loadconst(1,aint(_op2));
+ end;
+
+ constructor taicpu.op_const_reg(op:tasmop; _op1: LongInt; _op2: tregister);
+ begin
+ inherited create(op);
+ ops:=2;
+ loadconst(0,_op1);
+ loadreg(1,_op2);
+ end;
+
+
+ constructor taicpu.op_reg_ref(op : tasmop;_op1 : tregister;const _op2 : treference);
+ begin
+ inherited create(op);
+ ops:=2;
+ loadreg(0,_op1);
+ loadref(1,_op2);
+ end;
+
+
+ constructor taicpu.op_ref_reg(op : tasmop;const _op1 : treference;_op2 : tregister);
+ begin
+ inherited create(op);
+ ops:=2;
+ loadref(0,_op1);
+ loadreg(1,_op2);
+ end;
+
+
+ constructor taicpu.op_cond_sym(op : tasmop;cond:TAsmCond;_op1 : tasmsymbol);
+ begin
+ inherited create(op);
+ is_jmp:=op in jmp_instructions;
+ condition:=cond;
+ ops:=1;
+ loadsymbol(0,_op1,0);
+ end;
+
+
+ constructor taicpu.op_sym(op : tasmop;_op1 : tasmsymbol);
+ begin
+ inherited create(op);
+ is_jmp:=op in jmp_instructions;
+ ops:=1;
+ loadsymbol(0,_op1,0);
+ end;
+
+
+ constructor taicpu.op_sym_ofs(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint);
+ begin
+ inherited create(op);
+ ops:=1;
+ loadsymbol(0,_op1,_op1ofs);
+ end;
+
+
+ function taicpu.is_same_reg_move(regtype: Tregistertype):boolean;
+ begin
+ result:=(
+ ((opcode in [A_MOV,A_MOVW]) and (regtype = R_INTREGISTER))
+ ) and
+ (ops=2) and
+ (oper[0]^.typ=top_reg) and
+ (oper[1]^.typ=top_reg) and
+ (oper[0]^.reg=oper[1]^.reg);
+ end;
+
+
+ function taicpu.spilling_get_operation_type(opnr: longint): topertype;
+ begin
+ result:=operand_read;
+ case opcode of
+ A_CP,A_CPC,A_CPI,A_PUSH :
+ ;
+ else
+ begin
+ if opnr=0 then
+ result:=operand_write;
+ end;
+ end;
+ end;
+
+
+ function taicpu.calcsize(p:PInsEntry):shortint;
+ begin
+ case opcode of
+ A_CALL,
+ A_JMP:
+ result:=4;
+ A_LDS:
+ if (getsupreg(oper[0]^.reg)>=RS_R16) and (getsupreg(oper[0]^.reg)<=RS_R31) and
+ (oper[1]^.val>=0) and (oper[1]^.val<=127) then
+ result:=2
+ else
+ result:=4;
+ A_STS:
+ if (getsupreg(oper[1]^.reg)>=RS_R16) and (getsupreg(oper[1]^.reg)<=RS_R31) and
+ (oper[0]^.val>=0) and (oper[0]^.val<=127) then
+ result:=2
+ else
+ result:=4;
+ else
+ result:=2;
+ end;
+ end;
+
+
+ procedure taicpu.ResetPass1;
+ begin
+ { we need to reset everything here, because the choosen insentry
+ can be invalid for a new situation where the previously optimized
+ insentry is not correct }
+ InsEntry:=nil;
+ InsSize:=0;
+ LastInsOffset:=-1;
+ end;
+
+
+ procedure taicpu.ResetPass2;
+ begin
+ { we are here in a second pass, check if the instruction can be optimized }
+{
+ if assigned(InsEntry) and
+ ((InsEntry^.flags and IF_PASS2)<>0) then
+ begin
+ InsEntry:=nil;
+ InsSize:=0;
+ end;
+}
+ LastInsOffset:=-1;
+ end;
+
+
+ function taicpu.FindInsentry(objdata:TObjData):boolean;
+ begin
+ result:=false;
+ end;
+
+
+ function taicpu.Pass1(objdata:TObjData):longint;
+ begin
+ Pass1:=0;
+ { Save the old offset and set the new offset }
+ InsOffset:=ObjData.CurrObjSec.Size;
+ InsSize:=calcsize(InsEntry);
+ { Error? }
+ if (Insentry=nil) and (InsSize=-1) then
+ exit;
+ { set the file postion }
+ current_filepos:=fileinfo;
+
+ { Get InsEntry }
+ if FindInsEntry(objdata) then
+ begin
+ LastInsOffset:=InsOffset;
+ Pass1:=InsSize;
+ exit;
+ end;
+ LastInsOffset:=-1;
+ end;
+
+
+ function spilling_create_load(const ref:treference;r:tregister):Taicpu;
+ begin
+ case getregtype(r) of
+ R_INTREGISTER :
+ if ref.offset<>0 then
+ result:=taicpu.op_reg_ref(A_LDD,r,ref)
+ else
+ result:=taicpu.op_reg_ref(A_LD,r,ref);
+ R_ADDRESSREGISTER :
+ if ref.offset<>0 then
+ result:=taicpu.op_reg_ref(A_LDD,r,ref)
+ else
+ result:=taicpu.op_reg_ref(A_LD,r,ref);
+ else
+ internalerror(200401041);
+ end;
+ end;
+
+
+ function spilling_create_store(r:tregister; const ref:treference):Taicpu;
+ begin
+ case getregtype(r) of
+ R_INTREGISTER :
+ if ref.offset<>0 then
+ result:=taicpu.op_ref_reg(A_STD,ref,r)
+ else
+ result:=taicpu.op_ref_reg(A_ST,ref,r);
+ R_ADDRESSREGISTER :
+ if ref.offset<>0 then
+ result:=taicpu.op_ref_reg(A_STD,ref,r)
+ else
+ result:=taicpu.op_ref_reg(A_ST,ref,r);
+ else
+ internalerror(200401041);
+ end;
+ end;
+
+
+ procedure InitAsm;
+ begin
+ end;
+
+
+ procedure DoneAsm;
+ begin
+ end;
+
+
+ function setcondition(i : taicpu;c : tasmcond) : taicpu;
+ begin
+ i.condition:=c;
+ result:=i;
+ end;
+
+
+ procedure finalizeavrcode(list : TAsmList);
+ var
+ CurrOffset : longint;
+ curtai : tai;
+ again : boolean;
+ l : tasmlabel;
+ begin
+ again:=true;
+ while again do
+ begin
+ again:=false;
+ CurrOffset:=0;
+ curtai:=tai(list.first);
+ while assigned(curtai) do
+ begin
+ { instruction? }
+ if not(curtai.typ in SkipInstr) then
+ case curtai.typ of
+ ait_instruction:
+ begin
+ taicpu(curtai).InsOffset:=CurrOffset;
+ inc(CurrOffset,taicpu(curtai).calcsize(nil));
+ end;
+ ait_align:
+ inc(CurrOffset,tai_align(curtai).aligntype);
+ ait_marker:
+ ;
+ ait_label:
+ begin
+ tai_label(curtai).labsym.offset:=CurrOffset;
+ end;
+ else
+ internalerror(2011082401);
+ end;
+ curtai:=tai(curtai.next);
+ end;
+
+ curtai:=tai(list.first);
+ while assigned(curtai) do
+ begin
+ if (curtai.typ=ait_instruction) and
+ (taicpu(curtai).opcode in [A_BRxx]) and
+ ((taicpu(curtai).InsOffset-taicpu(curtai).oper[0]^.ref^.symbol.offset>64) or
+ (taicpu(curtai).InsOffset-taicpu(curtai).oper[0]^.ref^.symbol.offset<-63)
+ ) then
+ begin
+ current_asmdata.getjumplabel(l);
+ list.insertafter(tai_label.create(l),curtai);
+ list.insertafter(taicpu.op_sym(A_JMP,taicpu(curtai).oper[0]^.ref^.symbol),curtai);
+ taicpu(curtai).oper[0]^.ref^.symbol:=l;
+ taicpu(curtai).condition:=inverse_cond(taicpu(curtai).condition);
+ again:=true;
+ end;
+ curtai:=tai(curtai.next);
+ end;
+ end;
+ end;
+
+
+begin
+ cai_cpu:=taicpu;
+ cai_align:=tai_align;
+end.
diff --git a/closures/compiler/avr/agavrgas.pas b/closures/compiler/avr/agavrgas.pas
new file mode 100644
index 0000000000..74b95429de
--- /dev/null
+++ b/closures/compiler/avr/agavrgas.pas
@@ -0,0 +1,216 @@
+{
+ Copyright (c) 2003 by Florian Klaempfl
+
+ This unit implements an asm for the ARM
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+{ This unit implements the GNU Assembler writer for the ARM
+}
+
+unit agavrgas;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ globtype,
+ aasmtai,aasmdata,
+ aggas,
+ cpubase;
+
+ type
+
+ { TAVRGNUAssembler }
+
+ TAVRGNUAssembler=class(TGNUassembler)
+ constructor create(smart: boolean); override;
+ function MakeCmdLine: TCmdStr; override;
+ end;
+
+ TAVRInstrWriter=class(TCPUInstrWriter)
+ procedure WriteInstruction(hp : tai);override;
+ end;
+
+
+ implementation
+
+ uses
+ cutils,globals,verbose,
+ systems,
+ assemble,
+ aasmcpu,
+ itcpugas,
+ cpuinfo,
+ cgbase,cgutils;
+
+{****************************************************************************}
+{ GNU Arm Assembler writer }
+{****************************************************************************}
+
+ constructor TAVRGNUAssembler.create(smart: boolean);
+ begin
+ inherited create(smart);
+ InstrWriter := TAVRInstrWriter.create(self);
+ end;
+
+
+{****************************************************************************}
+{ Helper routines for Instruction Writer }
+{****************************************************************************}
+
+
+ Procedure TAVRInstrWriter.WriteInstruction(hp : tai);
+
+ function getreferencestring(var ref : treference) : string;
+ var
+ s : string;
+ begin
+ with ref do
+ begin
+ {$ifdef extdebug}
+ // if base=NR_NO then
+ // internalerror(200308292);
+
+ // if ((index<>NR_NO) or (shiftmode<>SM_None)) and ((offset<>0) or (symbol<>nil)) then
+ // internalerror(200308293);
+ {$endif extdebug}
+ if index<>NR_NO then
+ internalerror(2011021701)
+ else if base<>NR_NO then
+ begin
+ if addressmode=AM_PREDRECEMENT then
+ s:='-'
+ else
+ s:='';
+ case base of
+ NR_R26:
+ s:=s+'X';
+ NR_R28:
+ s:=s+'Y';
+ NR_R30:
+ s:=s+'Z';
+ else
+ s:=gas_regname(base);
+ end;
+ if addressmode=AM_POSTINCREMENT then
+ s:=s+'+';
+
+ if offset>0 then
+ s:=s+'+'+tostr(offset)
+ else if offset<0 then
+ s:=s+tostr(offset)
+ end
+ else if assigned(symbol) or (offset<>0) then
+ begin
+ if assigned(symbol) then
+ s:=ReplaceForbiddenChars(symbol.name)
+ else
+ s:='';
+
+ if offset<0 then
+ s:=s+tostr(offset)
+ else if offset>0 then
+ s:=s+'+'+tostr(offset);
+ case refaddr of
+ addr_hi8:
+ s:='hi8('+s+')';
+ addr_lo8:
+ s:='lo8('+s+')';
+ else
+ s:='('+s+')';
+ end;
+ end;
+ end;
+ getreferencestring:=s;
+ end;
+
+
+ function getopstr(const o:toper) : string;
+ var
+ hs : string;
+ first : boolean;
+ r : tsuperregister;
+ begin
+ case o.typ of
+ top_reg:
+ getopstr:=gas_regname(o.reg);
+ top_const:
+ getopstr:=tostr(longint(o.val));
+ top_ref:
+ if o.ref^.refaddr=addr_full then
+ begin
+ hs:=ReplaceForbiddenChars(o.ref^.symbol.name);
+ if o.ref^.offset>0 then
+ hs:=hs+'+'+tostr(o.ref^.offset)
+ else
+ if o.ref^.offset<0 then
+ hs:=hs+tostr(o.ref^.offset);
+ getopstr:=hs;
+ end
+ else
+ getopstr:=getreferencestring(o.ref^);
+ else
+ internalerror(2002070604);
+ end;
+ end;
+
+ var op: TAsmOp;
+ s: string;
+ i: byte;
+ sep: string[3];
+ begin
+ op:=taicpu(hp).opcode;
+ s:=#9+gas_op2str[op]+cond2str[taicpu(hp).condition];
+ if taicpu(hp).ops<>0 then
+ begin
+ sep:=#9;
+ for i:=0 to taicpu(hp).ops-1 do
+ begin
+ s:=s+sep+getopstr(taicpu(hp).oper[i]^);
+ sep:=',';
+ end;
+ end;
+ owner.AsmWriteLn(s);
+ end;
+
+
+ function TAVRGNUAssembler.MakeCmdLine: TCmdStr;
+ begin
+ result := '-mmcu='+lower(cputypestr[current_settings.cputype])+' '+inherited MakeCmdLine;
+ end;
+
+
+ const
+ as_arm_gas_info : tasminfo =
+ (
+ id : as_gas;
+
+ idtxt : 'AS';
+ asmbin : 'as';
+ asmcmd : '-o $OBJ $ASM';
+ supported_targets : [system_avr_embedded];
+ flags : [af_allowdirect,af_needar,af_smartlink_sections];
+ labelprefix : '.L';
+ comment : '# ';
+ );
+
+
+begin
+ RegisterAssembler(as_arm_gas_info,TAVRGNUAssembler);
+end.
diff --git a/closures/compiler/avr/aoptcpu.pas b/closures/compiler/avr/aoptcpu.pas
new file mode 100644
index 0000000000..90611a1e78
--- /dev/null
+++ b/closures/compiler/avr/aoptcpu.pas
@@ -0,0 +1,100 @@
+{
+ Copyright (c) 1998-2002 by Jonas Maebe, member of the Free Pascal
+ Development Team
+
+ This unit implements the ARM optimizer object
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+
+
+Unit aoptcpu;
+
+{$i fpcdefs.inc}
+
+Interface
+
+uses cpubase, aasmtai, aopt, aoptcpub;
+
+Type
+ TCpuAsmOptimizer = class(TAsmOptimizer)
+ { uses the same constructor as TAopObj }
+ function PeepHoleOptPass1Cpu(var p: tai): boolean; override;
+ procedure PeepHoleOptPass2;override;
+ End;
+
+Implementation
+
+ uses
+ aasmbase,aasmcpu,cgbase;
+
+ function CanBeCond(p : tai) : boolean;
+ begin
+ result:=(p.typ=ait_instruction) and (taicpu(p).condition=C_None);
+ end;
+
+
+ function TCpuAsmOptimizer.PeepHoleOptPass1Cpu(var p: tai): boolean;
+ var
+ next1: tai;
+ begin
+ result := false;
+ case p.typ of
+ ait_instruction:
+ begin
+ case taicpu(p).opcode of
+ A_MOV:
+ begin
+ { fold
+ mov reg2,reg0
+ mov reg3,reg1
+ to
+ movw reg2,reg0
+ }
+ if (taicpu(p).ops=2) and
+ (taicpu(p).oper[0]^.typ = top_reg) and
+ (taicpu(p).oper[1]^.typ = top_reg) and
+ getnextinstruction(p,next1) and
+ (next1.typ = ait_instruction) and
+ (taicpu(next1).opcode = A_MOV) and
+ (taicpu(next1).ops=2) and
+ (taicpu(next1).oper[0]^.typ = top_reg) and
+ (taicpu(next1).oper[1]^.typ = top_reg) and
+ (getsupreg(taicpu(next1).oper[0]^.reg)=getsupreg(taicpu(p).oper[0]^.reg)+1) and
+ ((getsupreg(taicpu(p).oper[0]^.reg) mod 2)=0) and
+ ((getsupreg(taicpu(p).oper[1]^.reg) mod 2)=0) and
+ (getsupreg(taicpu(next1).oper[1]^.reg)=getsupreg(taicpu(p).oper[1]^.reg)+1) then
+ begin
+ taicpu(p).opcode:=A_MOVW;
+ asml.remove(next1);
+ next1.free;
+ result := true;
+ end;
+ end;
+ end;
+ end;
+ end;
+ end;
+
+
+ procedure TCpuAsmOptimizer.PeepHoleOptPass2;
+ begin
+ end;
+
+begin
+ casmoptimizer:=TCpuAsmOptimizer;
+End.
diff --git a/closures/compiler/avr/aoptcpub.pas b/closures/compiler/avr/aoptcpub.pas
new file mode 100644
index 0000000000..c56bd8b31f
--- /dev/null
+++ b/closures/compiler/avr/aoptcpub.pas
@@ -0,0 +1,120 @@
+ {
+ Copyright (c) 1998-2002 by Jonas Maebe, member of the Free Pascal
+ Development Team
+
+ This unit contains several types and constants necessary for the
+ optimizer to work on the ARM architecture
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+Unit aoptcpub; { Assembler OPTimizer CPU specific Base }
+
+{$i fpcdefs.inc}
+
+{ enable the following define if memory references can have both a base and }
+{ index register in 1 operand }
+
+{$define RefsHaveIndexReg}
+
+{ enable the following define if memory references can have a scaled index }
+
+{ define RefsHaveScale}
+
+{ enable the following define if memory references can have a segment }
+{ override }
+
+{ define RefsHaveSegment}
+
+Interface
+
+Uses
+ cpubase,aasmcpu,AOptBase;
+
+Type
+
+{ type of a normal instruction }
+ TInstr = Taicpu;
+ PInstr = ^TInstr;
+
+{ ************************************************************************* }
+{ **************************** TCondRegs ********************************** }
+{ ************************************************************************* }
+{ Info about the conditional registers }
+ TCondRegs = Object
+ Constructor Init;
+ Destructor Done;
+ End;
+
+{ ************************************************************************* }
+{ **************************** TAoptBaseCpu ******************************* }
+{ ************************************************************************* }
+
+ TAoptBaseCpu = class(TAoptBase)
+ End;
+
+
+{ ************************************************************************* }
+{ ******************************* Constants ******************************* }
+{ ************************************************************************* }
+Const
+
+{ the maximum number of things (registers, memory, ...) a single instruction }
+{ changes }
+
+ MaxCh = 2;
+
+{ the maximum number of operands an instruction has }
+
+ MaxOps = 2;
+
+{Oper index of operand that contains the source (reference) with a load }
+{instruction }
+
+ LoadSrc = 1;
+
+{Oper index of operand that contains the destination (register) with a load }
+{instruction }
+
+ LoadDst = 0;
+
+{Oper index of operand that contains the source (register) with a store }
+{instruction }
+
+ StoreSrc = 1;
+
+{Oper index of operand that contains the destination (reference) with a load }
+{instruction }
+
+ StoreDst = 0;
+
+ aopt_uncondjmp = A_JMP;
+ aopt_condjmp = A_BRxx;
+
+Implementation
+
+{ ************************************************************************* }
+{ **************************** TCondRegs ********************************** }
+{ ************************************************************************* }
+Constructor TCondRegs.init;
+Begin
+End;
+
+Destructor TCondRegs.Done; {$ifdef inl} inline; {$endif inl}
+Begin
+End;
+
+End.
diff --git a/closures/compiler/avr/aoptcpud.pas b/closures/compiler/avr/aoptcpud.pas
new file mode 100644
index 0000000000..2df7e2e49e
--- /dev/null
+++ b/closures/compiler/avr/aoptcpud.pas
@@ -0,0 +1,40 @@
+{
+ Copyright (c) 1998-2002 by Jonas Maebe, member of the Free Pascal
+ Development Team
+
+ This unit contains the processor specific implementation of the
+ assembler optimizer data flow analyzer.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+Unit aoptcpud;
+
+{$i fpcdefs.inc}
+
+Interface
+
+uses
+ AOptDA;
+
+Type
+ TAOptDFACpu = class(TAOptDFA)
+ End;
+
+Implementation
+
+
+End.
diff --git a/closures/compiler/avr/avrreg.dat b/closures/compiler/avr/avrreg.dat
new file mode 100644
index 0000000000..83c71dec1d
--- /dev/null
+++ b/closures/compiler/avr/avrreg.dat
@@ -0,0 +1,41 @@
+;
+; AVR registers
+;
+; layout
+; <name>,<type>,<value>,<stdname>,<stab idx>,<dwarf idx>
+;
+NO,$00,$00,INVALID,-1,-1
+
+R0,$01,$00,r0,0,0
+R1,$01,$01,r1,1,1
+R2,$01,$02,r2,2,2
+R3,$01,$03,r3,3,3
+R4,$01,$04,r4,4,4
+R5,$01,$05,r5,5,5
+R6,$01,$06,r6,6,6
+R7,$01,$07,r7,7,7
+R8,$01,$08,r8,8,8
+R9,$01,$09,r9,9,9
+R10,$01,$0a,r10,10,10
+R11,$01,$0b,r11,11,11
+R12,$01,$0c,r12,12,12
+R13,$01,$0d,r13,13,13
+R14,$01,$0e,r14,14,14
+R15,$01,$0f,r15,15,15
+R16,$01,$10,r16,16,16
+R17,$01,$11,r17,17,17
+R18,$01,$12,r18,18,18
+R19,$01,$13,r19,19,19
+R20,$01,$14,r20,20,20
+R21,$01,$15,r21,21,21
+R22,$01,$16,r22,22,22
+R23,$01,$17,r23,23,23
+R24,$01,$18,r24,24,24
+R25,$01,$19,r25,25,25
+R26,$01,$1a,r26,26,26
+R27,$01,$1b,r27,27,27
+R28,$01,$1c,r28,28,28
+R29,$01,$1d,r29,29,29
+R30,$01,$1e,r30,30,30
+R31,$01,$1f,r31,31,31
+
diff --git a/closures/compiler/avr/cgcpu.pas b/closures/compiler/avr/cgcpu.pas
new file mode 100644
index 0000000000..21d0d8a5b5
--- /dev/null
+++ b/closures/compiler/avr/cgcpu.pas
@@ -0,0 +1,1752 @@
+{
+
+ Copyright (c) 2008 by Florian Klaempfl
+ Member of the Free Pascal development team
+
+ This unit implements the code generator for the AVR
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit cgcpu;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ globtype,symtype,symdef,
+ cgbase,cgutils,cgobj,
+ aasmbase,aasmcpu,aasmtai,aasmdata,
+ parabase,
+ cpubase,cpuinfo,node,cg64f32,rgcpu;
+
+ type
+
+ { tcgavr }
+
+ tcgavr = class(tcg)
+ { true, if the next arithmetic operation should modify the flags }
+ cgsetflags : boolean;
+ procedure init_register_allocators;override;
+ procedure done_register_allocators;override;
+
+ function getintregister(list:TAsmList;size:Tcgsize):Tregister;override;
+ function getaddressregister(list:TAsmList):TRegister;override;
+
+ procedure a_load_const_cgpara(list : TAsmList;size : tcgsize;a : tcgint;const paraloc : TCGPara);override;
+ procedure a_load_ref_cgpara(list : TAsmList;size : tcgsize;const r : treference;const paraloc : TCGPara);override;
+ procedure a_loadaddr_ref_cgpara(list : TAsmList;const r : treference;const paraloc : TCGPara);override;
+
+ procedure a_call_name(list : TAsmList;const s : string; weak: boolean);override;
+ procedure a_call_reg(list : TAsmList;reg: tregister);override;
+ procedure a_call_ref(list : TAsmList;ref: treference);override;
+
+ procedure a_op_const_reg(list : TAsmList; Op: TOpCG; size: TCGSize; a: tcgint; reg: TRegister); override;
+ procedure a_op_reg_reg(list : TAsmList; Op: TOpCG; size: TCGSize; src, dst: TRegister); override;
+
+ { move instructions }
+ procedure a_load_const_reg(list : TAsmList; size: tcgsize; a : tcgint;reg : tregister);override;
+ procedure a_load_reg_ref(list : TAsmList; fromsize, tosize: tcgsize; reg : tregister;const ref : treference);override;
+ procedure a_load_ref_reg(list : TAsmList; fromsize, tosize : tcgsize;const Ref : treference;reg : tregister);override;
+ procedure a_load_reg_reg(list : TAsmList; fromsize, tosize : tcgsize;reg1,reg2 : tregister);override;
+
+ { fpu move instructions }
+ procedure a_loadfpu_reg_reg(list: TAsmList; fromsize, tosize: tcgsize; reg1, reg2: tregister); override;
+ procedure a_loadfpu_ref_reg(list: TAsmList; fromsize, tosize: tcgsize; const ref: treference; reg: tregister); override;
+ procedure a_loadfpu_reg_ref(list: TAsmList; fromsize, tosize: tcgsize; reg: tregister; const ref: treference); override;
+
+ { comparison operations }
+ procedure a_cmp_const_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;a : tcgint;reg : tregister;
+ l : tasmlabel);override;
+ procedure a_cmp_reg_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel); override;
+
+ procedure a_jmp_name(list : TAsmList;const s : string); override;
+ procedure a_jmp_always(list : TAsmList;l: tasmlabel); override;
+ procedure a_jmp_flags(list : TAsmList;const f : TResFlags;l: tasmlabel); override;
+
+ procedure g_flags2reg(list: TAsmList; size: TCgSize; const f: TResFlags; reg: TRegister); override;
+
+ procedure g_proc_entry(list : TAsmList;localsize : longint;nostackframe:boolean);override;
+ procedure g_proc_exit(list : TAsmList;parasize : longint;nostackframe:boolean); override;
+
+ procedure a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);override;
+
+ procedure g_concatcopy(list : TAsmList;const source,dest : treference;len : tcgint);override;
+ procedure g_concatcopy_move(list : TAsmList;const source,dest : treference;len : tcgint);
+
+ procedure g_overflowcheck(list: TAsmList; const l: tlocation; def: tdef); override;
+
+ procedure g_save_registers(list : TAsmList);override;
+ procedure g_restore_registers(list : TAsmList);override;
+
+ procedure a_jmp_cond(list : TAsmList;cond : TOpCmp;l: tasmlabel);
+ procedure fixref(list : TAsmList;var ref : treference);
+ function normalize_ref(list : TAsmList;ref : treference;
+ tmpreg : tregister) : treference;
+
+ procedure g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);override;
+ procedure g_stackpointer_alloc(list : TAsmList;size : longint);override;
+ procedure emit_mov(list: TAsmList;reg2: tregister; reg1: tregister);
+
+ procedure a_adjust_sp(list: TAsmList; value: longint);
+ function GetLoad(const ref : treference) : tasmop;
+ function GetStore(const ref: treference): tasmop;
+
+ procedure a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; size: TCGSize; src, dst: TRegister); override;
+ end;
+
+ tcg64favr = class(tcg64f32)
+ procedure a_op64_reg_reg(list : TAsmList;op:TOpCG;size : tcgsize;regsrc,regdst : tregister64);override;
+ procedure a_op64_const_reg(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;reg : tregister64);override;
+ end;
+
+ procedure create_codegen;
+
+ const
+ TOpCG2AsmOp: Array[topcg] of TAsmOp = (A_NONE,A_MOV,A_ADD,A_AND,A_NONE,
+ A_NONE,A_MUL,A_MULS,A_NEG,A_COM,A_OR,
+ A_ASR,A_LSL,A_LSR,A_SUB,A_EOR,A_ROL,A_ROR);
+ implementation
+
+ uses
+ globals,verbose,systems,cutils,
+ fmodule,
+ symconst,symsym,
+ tgobj,rgobj,
+ procinfo,cpupi,
+ paramgr;
+
+
+ procedure tcgavr.init_register_allocators;
+ begin
+ inherited init_register_allocators;
+ rg[R_INTREGISTER]:=trgintcpu.create(R_INTREGISTER,R_SUBWHOLE,
+ [RS_R8,RS_R9,
+ RS_R10,RS_R11,RS_R12,RS_R13,RS_R14,RS_R15,RS_R16,RS_R17,RS_R18,RS_R19,
+ RS_R20,RS_R21,RS_R22,RS_R23,RS_R24,RS_R25,
+ RS_R2,RS_R3,RS_R4,RS_R5,RS_R6,RS_R7],first_int_imreg,[]);
+ { rg[R_ADDRESSREGISTER]:=trgintcpu.create(R_ADDRESSREGISTER,R_SUBWHOLE,
+ [RS_R26,RS_R30],first_int_imreg,[]); }
+ end;
+
+
+ procedure tcgavr.done_register_allocators;
+ begin
+ rg[R_INTREGISTER].free;
+ // rg[R_ADDRESSREGISTER].free;
+ inherited done_register_allocators;
+ end;
+
+
+ function tcgavr.getintregister(list: TAsmList; size: Tcgsize): Tregister;
+ var
+ tmp1,tmp2,tmp3 : TRegister;
+ begin
+ case size of
+ OS_8,OS_S8:
+ Result:=inherited getintregister(list, size);
+ OS_16,OS_S16:
+ begin
+ Result:=inherited getintregister(list, OS_8);
+ { ensure that the high register can be retrieved by
+ GetNextReg
+ }
+ if inherited getintregister(list, OS_8)<>GetNextReg(Result) then
+ internalerror(2011021331);
+ end;
+ OS_32,OS_S32:
+ begin
+ Result:=inherited getintregister(list, OS_8);
+ tmp1:=inherited getintregister(list, OS_8);
+ { ensure that the high register can be retrieved by
+ GetNextReg
+ }
+ if tmp1<>GetNextReg(Result) then
+ internalerror(2011021332);
+ tmp2:=inherited getintregister(list, OS_8);
+ { ensure that the upper register can be retrieved by
+ GetNextReg
+ }
+ if tmp2<>GetNextReg(tmp1) then
+ internalerror(2011021333);
+ tmp3:=inherited getintregister(list, OS_8);
+ { ensure that the upper register can be retrieved by
+ GetNextReg
+ }
+ if tmp3<>GetNextReg(tmp2) then
+ internalerror(2011021334);
+ end;
+ else
+ internalerror(2011021330);
+ end;
+ end;
+
+
+ function tcgavr.getaddressregister(list: TAsmList): TRegister;
+ begin
+ Result:=getintregister(list,OS_ADDR);
+ end;
+
+
+ procedure tcgavr.a_load_const_cgpara(list : TAsmList;size : tcgsize;a : tcgint;const paraloc : TCGPara);
+ var
+ ref: treference;
+ begin
+ paraloc.check_simple_location;
+ paramanager.allocparaloc(list,paraloc.location);
+ case paraloc.location^.loc of
+ LOC_REGISTER,LOC_CREGISTER:
+ a_load_const_reg(list,size,a,paraloc.location^.register);
+ LOC_REFERENCE:
+ begin
+ reference_reset(ref,paraloc.alignment);
+ ref.base:=paraloc.location^.reference.index;
+ ref.offset:=paraloc.location^.reference.offset;
+ a_load_const_ref(list,size,a,ref);
+ end;
+ else
+ internalerror(2002081101);
+ end;
+ end;
+
+
+ procedure tcgavr.a_load_ref_cgpara(list : TAsmList;size : tcgsize;const r : treference;const paraloc : TCGPara);
+ var
+ tmpref, ref: treference;
+ location: pcgparalocation;
+ sizeleft: tcgint;
+ begin
+ location := paraloc.location;
+ tmpref := r;
+ sizeleft := paraloc.intsize;
+ while assigned(location) do
+ begin
+ paramanager.allocparaloc(list,location);
+ case location^.loc of
+ LOC_REGISTER,LOC_CREGISTER:
+ a_load_ref_reg(list,location^.size,location^.size,tmpref,location^.register);
+ LOC_REFERENCE:
+ begin
+ reference_reset_base(ref,location^.reference.index,location^.reference.offset,paraloc.alignment);
+ { doubles in softemu mode have a strange order of registers and references }
+ if location^.size=OS_32 then
+ g_concatcopy(list,tmpref,ref,4)
+ else
+ begin
+ g_concatcopy(list,tmpref,ref,sizeleft);
+ if assigned(location^.next) then
+ internalerror(2005010710);
+ end;
+ end;
+ LOC_VOID:
+ begin
+ // nothing to do
+ end;
+ else
+ internalerror(2002081103);
+ end;
+ inc(tmpref.offset,tcgsize2size[location^.size]);
+ dec(sizeleft,tcgsize2size[location^.size]);
+ location := location^.next;
+ end;
+ end;
+
+
+ procedure tcgavr.a_loadaddr_ref_cgpara(list : TAsmList;const r : treference;const paraloc : TCGPara);
+ var
+ ref: treference;
+ tmpreg: tregister;
+ begin
+ paraloc.check_simple_location;
+ paramanager.allocparaloc(list,paraloc.location);
+ case paraloc.location^.loc of
+ LOC_REGISTER,LOC_CREGISTER:
+ a_loadaddr_ref_reg(list,r,paraloc.location^.register);
+ LOC_REFERENCE:
+ begin
+ reference_reset(ref,paraloc.alignment);
+ ref.base := paraloc.location^.reference.index;
+ ref.offset := paraloc.location^.reference.offset;
+ tmpreg := getintregister(list,OS_ADDR);
+ a_loadaddr_ref_reg(list,r,tmpreg);
+ a_load_reg_ref(list,OS_ADDR,OS_ADDR,tmpreg,ref);
+ end;
+ else
+ internalerror(2002080701);
+ end;
+ end;
+
+
+ procedure tcgavr.a_call_name(list : TAsmList;const s : string; weak: boolean);
+ begin
+ list.concat(taicpu.op_sym(A_RCALL,current_asmdata.RefAsmSymbol(s)));
+{
+ the compiler does not properly set this flag anymore in pass 1, and
+ for now we only need it after pass 2 (I hope) (JM)
+ if not(pi_do_call in current_procinfo.flags) then
+ internalerror(2003060703);
+}
+ include(current_procinfo.flags,pi_do_call);
+ end;
+
+
+ procedure tcgavr.a_call_reg(list : TAsmList;reg: tregister);
+ begin
+ a_reg_alloc(list,NR_ZLO);
+ a_reg_alloc(list,NR_ZHI);
+ list.concat(taicpu.op_reg_reg(A_MOV,NR_ZLO,reg));
+ list.concat(taicpu.op_reg_reg(A_MOV,NR_ZHI,GetHigh(reg)));
+ list.concat(taicpu.op_none(A_ICALL));
+ a_reg_dealloc(list,NR_ZLO);
+ a_reg_dealloc(list,NR_ZHI);
+
+ include(current_procinfo.flags,pi_do_call);
+ end;
+
+
+ procedure tcgavr.a_call_ref(list : TAsmList;ref: treference);
+ begin
+ a_reg_alloc(list,NR_ZLO);
+ a_reg_alloc(list,NR_ZHI);
+ a_load_ref_reg(list,OS_ADDR,OS_ADDR,ref,NR_ZLO);
+ list.concat(taicpu.op_none(A_ICALL));
+ a_reg_dealloc(list,NR_ZLO);
+ a_reg_dealloc(list,NR_ZHI);
+
+ include(current_procinfo.flags,pi_do_call);
+ end;
+
+
+ procedure tcgavr.a_op_const_reg(list : TAsmList; Op: TOpCG; size: TCGSize; a: tcgint; reg: TRegister);
+ var
+ mask : qword;
+ shift : byte;
+ i : byte;
+ tmpreg : tregister;
+ begin
+ mask:=$ff;
+ shift:=0;
+ case op of
+ OP_OR:
+ begin
+ for i:=1 to tcgsize2size[size] do
+ begin
+ list.concat(taicpu.op_reg_const(A_ORI,reg,(a and mask) shr shift));
+ reg:=GetNextReg(reg);
+ mask:=mask shl 8;
+ inc(shift,8);
+ end;
+ end;
+ OP_AND:
+ begin
+ for i:=1 to tcgsize2size[size] do
+ begin
+ list.concat(taicpu.op_reg_const(A_ANDI,reg,(a and mask) shr shift));
+ reg:=GetNextReg(reg);
+ mask:=mask shl 8;
+ inc(shift,8);
+ end;
+ end;
+ OP_SUB:
+ begin
+ list.concat(taicpu.op_reg_const(A_SUBI,reg,a));
+ if size in [OS_S16,OS_16,OS_S32,OS_32,OS_S64,OS_64] then
+ begin
+ for i:=2 to tcgsize2size[size] do
+ begin
+ reg:=GetNextReg(reg);
+ mask:=mask shl 8;
+ inc(shift,8);
+ list.concat(taicpu.op_reg_const(A_SBCI,reg,(a and mask) shr shift));
+ end;
+ end;
+ end;
+ else
+ begin
+ tmpreg:=getintregister(list,size);
+ a_load_const_reg(list,size,a,tmpreg);
+ a_op_reg_reg(list,op,size,tmpreg,reg);
+ end;
+ end;
+ end;
+
+
+ procedure tcgavr.a_op_reg_reg(list : TAsmList; Op: TOpCG; size: TCGSize; src, dst: TRegister);
+ var
+ countreg,
+ tmpreg: tregister;
+ i : integer;
+ instr : taicpu;
+ paraloc1,paraloc2,paraloc3 : TCGPara;
+ l1,l2 : tasmlabel;
+ begin
+ case op of
+ OP_ADD:
+ begin
+ list.concat(taicpu.op_reg_reg(A_ADD,dst,src));
+ if size in [OS_S16,OS_16,OS_S32,OS_32,OS_S64,OS_64] then
+ begin
+ for i:=2 to tcgsize2size[size] do
+ begin
+ dst:=GetNextReg(dst);
+ src:=GetNextReg(src);
+ list.concat(taicpu.op_reg_reg(A_ADC,dst,src));
+ end;
+ end
+ else
+ end;
+
+ OP_SUB:
+ begin
+ list.concat(taicpu.op_reg_reg(A_SUB,dst,src));
+ if size in [OS_S16,OS_16,OS_S32,OS_32,OS_S64,OS_64] then
+ begin
+ for i:=2 to tcgsize2size[size] do
+ begin
+ dst:=GetNextReg(dst);
+ src:=GetNextReg(src);
+ list.concat(taicpu.op_reg_reg(A_SBC,dst,src));
+ end;
+ end;
+ end;
+
+ OP_NEG:
+ begin
+ if src<>dst then
+ a_load_reg_reg(list,size,size,src,dst);
+
+ if size in [OS_S16,OS_16,OS_S32,OS_32,OS_S64,OS_64] then
+ begin
+ tmpreg:=GetNextReg(dst);
+ for i:=2 to tcgsize2size[size] do
+ begin
+ list.concat(taicpu.op_reg(A_COM,tmpreg));
+ tmpreg:=GetNextReg(tmpreg);
+ end;
+ list.concat(taicpu.op_reg(A_NEG,dst));
+ tmpreg:=GetNextReg(dst);
+ for i:=2 to tcgsize2size[size] do
+ begin
+ list.concat(taicpu.op_reg_const(A_SBCI,dst,-1));
+ tmpreg:=GetNextReg(tmpreg);
+ end;
+ end
+ else
+ list.concat(taicpu.op_reg(A_NEG,dst));
+ end;
+
+ OP_NOT:
+ begin
+ for i:=1 to tcgsize2size[size] do
+ begin
+ if src<>dst then
+ a_load_reg_reg(list,OS_8,OS_8,src,dst);
+ list.concat(taicpu.op_reg(A_COM,dst));
+ src:=GetNextReg(src);
+ dst:=GetNextReg(dst);
+ end;
+ end;
+
+ OP_MUL,OP_IMUL:
+ begin
+ if size in [OS_8,OS_S8] then
+ list.concat(taicpu.op_reg_reg(topcg2asmop[op],dst,src))
+ else if size=OS_16 then
+ begin
+ paraloc1.init;
+ paraloc2.init;
+ paraloc3.init;
+ paramanager.getintparaloc(pocall_default,1,paraloc1);
+ paramanager.getintparaloc(pocall_default,2,paraloc2);
+ paramanager.getintparaloc(pocall_default,3,paraloc3);
+ a_load_const_cgpara(list,OS_8,0,paraloc3);
+ a_load_reg_cgpara(list,OS_16,src,paraloc2);
+ a_load_reg_cgpara(list,OS_16,dst,paraloc1);
+ paramanager.freecgpara(list,paraloc3);
+ paramanager.freecgpara(list,paraloc2);
+ paramanager.freecgpara(list,paraloc1);
+ alloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
+ a_call_name(list,'FPC_MUL_WORD',false);
+ dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
+ cg.a_reg_alloc(list,NR_FUNCTION_RESULT_REG);
+ cg.a_load_reg_reg(list,OS_16,OS_16,NR_FUNCTION_RESULT_REG,dst);
+ paraloc3.done;
+ paraloc2.done;
+ paraloc1.done;
+ end
+ else
+ internalerror(2011022002);
+ end;
+
+ OP_DIV,OP_IDIV:
+ { special stuff, needs separate handling inside code }
+ { generator }
+ internalerror(2011022001);
+
+ OP_SHR,OP_SHL,OP_SAR,OP_ROL,OP_ROR:
+ begin
+ current_asmdata.getjumplabel(l1);
+ current_asmdata.getjumplabel(l2);
+ countreg:=getintregister(list,OS_8);
+ a_load_reg_reg(list,size,OS_8,src,countreg);
+ list.concat(taicpu.op_reg_const(A_CP,countreg,0));
+ a_jmp_flags(list,F_EQ,l2);
+ cg.a_label(list,l1);
+ case op of
+ OP_SHR:
+ list.concat(taicpu.op_reg(A_LSR,GetOffsetReg(dst,tcgsize2size[size]-1)));
+ OP_SHL:
+ list.concat(taicpu.op_reg(A_LSL,dst));
+ OP_SAR:
+ list.concat(taicpu.op_reg(A_ASR,GetOffsetReg(dst,tcgsize2size[size]-1)));
+ OP_ROR:
+ begin
+ { load carry? }
+ if not(size in [OS_8,OS_S8]) then
+ begin
+ list.concat(taicpu.op_none(A_CLC));
+ list.concat(taicpu.op_reg_const(A_SBRC,src,0));
+ list.concat(taicpu.op_none(A_SEC));
+ end;
+ list.concat(taicpu.op_reg(A_ROR,GetOffsetReg(dst,tcgsize2size[size]-1)));
+ end;
+ OP_ROL:
+ begin
+ { load carry? }
+ if not(size in [OS_8,OS_S8]) then
+ begin
+ list.concat(taicpu.op_none(A_CLC));
+ list.concat(taicpu.op_reg_const(A_SBRC,GetOffsetReg(dst,tcgsize2size[size]-1),7));
+ list.concat(taicpu.op_none(A_SEC));
+ end;
+ list.concat(taicpu.op_reg(A_ROL,dst))
+ end;
+ else
+ internalerror(2011030901);
+ end;
+ if size in [OS_S16,OS_16,OS_S32,OS_32,OS_S64,OS_64] then
+ begin
+ for i:=2 to tcgsize2size[size] do
+ begin
+ case op of
+ OP_ROR,
+ OP_SHR:
+ list.concat(taicpu.op_reg(A_ROR,GetOffsetReg(dst,tcgsize2size[size]-i)));
+ OP_ROL,
+ OP_SHL:
+ list.concat(taicpu.op_reg(A_ROL,GetOffsetReg(dst,i-1)));
+ OP_SAR:
+ list.concat(taicpu.op_reg(A_ROR,GetOffsetReg(dst,tcgsize2size[size]-i)));
+ else
+ internalerror(2011030902);
+ end;
+ end;
+ end;
+
+ a_op_const_reg(list,OP_SUB,OS_8,1,countreg);
+ a_jmp_flags(list,F_NE,l1);
+ // keep registers alive
+ list.concat(taicpu.op_reg_reg(A_MOV,countreg,countreg));
+ cg.a_label(list,l2);
+ end;
+
+ OP_AND,OP_OR,OP_XOR:
+ begin
+ for i:=1 to tcgsize2size[size] do
+ begin
+ list.concat(taicpu.op_reg_reg(topcg2asmop[op],dst,src));
+ dst:=GetNextReg(dst);
+ src:=GetNextReg(src);
+ end;
+ end;
+ else
+ internalerror(2011022004);
+ end;
+ end;
+
+
+ procedure tcgavr.a_load_const_reg(list : TAsmList; size: tcgsize; a : tcgint;reg : tregister);
+ var
+ mask : qword;
+ shift : byte;
+ i : byte;
+ begin
+ mask:=$ff;
+ shift:=0;
+ for i:=1 to tcgsize2size[size] do
+ begin
+ if ((qword(a) and mask) shr shift)=0 then
+ emit_mov(list,reg,NR_R1)
+ else
+ list.concat(taicpu.op_reg_const(A_LDI,reg,(qword(a) and mask) shr shift));
+
+ mask:=mask shl 8;
+ inc(shift,8);
+ reg:=GetNextReg(reg);
+ end;
+ end;
+
+
+ function tcgavr.normalize_ref(list:TAsmList;ref: treference;tmpreg : tregister) : treference;
+
+ procedure maybegetcpuregister(list:tasmlist;reg : tregister);
+ begin
+ { allocate the register only, if a cpu register is passed }
+ if getsupreg(reg)<first_int_imreg then
+ getcpuregister(list,reg);
+ end;
+
+ var
+ tmpref : treference;
+ l : tasmlabel;
+ begin
+ Result:=ref;
+
+ if ref.addressmode<>AM_UNCHANGED then
+ internalerror(2011021701);
+
+ { Be sure to have a base register }
+ if (ref.base=NR_NO) then
+ begin
+ { only symbol+offset? }
+ if ref.index=NR_NO then
+ exit;
+ ref.base:=ref.index;
+ ref.index:=NR_NO;
+ end;
+ if assigned(ref.symbol) or (ref.offset<>0) then
+ begin
+ reference_reset(tmpref,0);
+ tmpref.symbol:=ref.symbol;
+ tmpref.offset:=ref.offset;
+ tmpref.refaddr:=addr_lo8;
+ maybegetcpuregister(list,tmpreg);
+ list.concat(taicpu.op_reg_ref(A_LDI,tmpreg,tmpref));
+ tmpref.refaddr:=addr_hi8;
+ maybegetcpuregister(list,GetNextReg(tmpreg));
+ list.concat(taicpu.op_reg_ref(A_LDI,GetNextReg(tmpreg),tmpref));
+ if (ref.base<>NR_NO) then
+ begin
+ list.concat(taicpu.op_reg_reg(A_ADD,tmpreg,ref.base));
+ list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(tmpreg),GetNextReg(ref.base)));
+ end;
+ if (ref.index<>NR_NO) then
+ begin
+ list.concat(taicpu.op_reg_reg(A_ADD,tmpreg,ref.index));
+ list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(tmpreg),GetNextReg(ref.index)));
+ end;
+ ref.symbol:=nil;
+ ref.offset:=0;
+ ref.base:=tmpreg;
+ ref.index:=NR_NO;
+ end
+ else if (ref.base<>NR_NO) and (ref.index<>NR_NO) then
+ begin
+ maybegetcpuregister(list,tmpreg);
+ emit_mov(list,tmpreg,ref.index);
+ maybegetcpuregister(list,GetNextReg(tmpreg));
+ emit_mov(list,GetNextReg(tmpreg),GetNextReg(ref.index));
+ list.concat(taicpu.op_reg_reg(A_ADD,tmpreg,ref.base));
+ list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(tmpreg),GetNextReg(ref.base)));
+ ref.base:=tmpreg;
+ ref.index:=NR_NO;
+ end
+ else if (ref.base<>NR_NO) then
+ begin
+ maybegetcpuregister(list,tmpreg);
+ emit_mov(list,tmpreg,ref.base);
+ maybegetcpuregister(list,GetNextReg(tmpreg));
+ emit_mov(list,GetNextReg(tmpreg),GetNextReg(ref.base));
+ ref.base:=tmpreg;
+ ref.index:=NR_NO;
+ end
+ else if (ref.index<>NR_NO) then
+ begin
+ maybegetcpuregister(list,tmpreg);
+ emit_mov(list,tmpreg,ref.index);
+ maybegetcpuregister(list,GetNextReg(tmpreg));
+ emit_mov(list,GetNextReg(tmpreg),GetNextReg(ref.index));
+ ref.base:=tmpreg;
+ ref.index:=NR_NO;
+ end;
+ Result:=ref;
+ end;
+
+
+ procedure tcgavr.a_load_reg_ref(list : TAsmList; fromsize, tosize: tcgsize; reg : tregister;const ref : treference);
+ var
+ href : treference;
+ conv_done: boolean;
+ tmpreg : tregister;
+ i : integer;
+ QuickRef : Boolean;
+ begin
+ QuickRef:=false;
+ if not((Ref.addressmode=AM_UNCHANGED) and
+ (Ref.symbol=nil) and
+ ((Ref.base=NR_R28) or
+ (Ref.base=NR_R29)) and
+ (Ref.Index=NR_No) and
+ (Ref.Offset in [0..64-tcgsize2size[tosize]])) and
+ not((Ref.Base=NR_NO) and (Ref.Index=NR_NO)) then
+ href:=normalize_ref(list,Ref,NR_R30)
+ else
+ begin
+ QuickRef:=true;
+ href:=Ref;
+ end;
+
+ if (tcgsize2size[fromsize]>32) or (tcgsize2size[tosize]>32) or (fromsize=OS_NO) or (tosize=OS_NO) then
+ internalerror(2011021307);
+
+ conv_done:=false;
+ if tosize<>fromsize then
+ begin
+ conv_done:=true;
+ if tcgsize2size[tosize]<=tcgsize2size[fromsize] then
+ fromsize:=tosize;
+ case fromsize of
+ OS_8:
+ begin
+ if not(QuickRef) and (tcgsize2size[tosize]>1) then
+ href.addressmode:=AM_POSTINCREMENT;
+
+ list.concat(taicpu.op_ref_reg(GetStore(href),href,reg));
+ for i:=2 to tcgsize2size[tosize] do
+ begin
+ if QuickRef then
+ inc(href.offset);
+
+ if not(QuickRef) and (i<tcgsize2size[fromsize]) then
+ href.addressmode:=AM_POSTINCREMENT
+ else
+ href.addressmode:=AM_UNCHANGED;
+
+ list.concat(taicpu.op_ref_reg(GetStore(href),href,NR_R1));
+ end;
+ end;
+ OS_S8:
+ begin
+ if not(QuickRef) and (tcgsize2size[tosize]>1) then
+ href.addressmode:=AM_POSTINCREMENT;
+ list.concat(taicpu.op_ref_reg(GetStore(href),href,reg));
+
+ if tcgsize2size[tosize]>1 then
+ begin
+ tmpreg:=getintregister(list,OS_8);
+ list.concat(taicpu.op_reg(A_CLR,tmpreg));
+ list.concat(taicpu.op_reg_const(A_SBRC,reg,7));
+ list.concat(taicpu.op_reg(A_COM,tmpreg));
+ for i:=2 to tcgsize2size[tosize] do
+ begin
+ if QuickRef then
+ inc(href.offset);
+
+ if not(QuickRef) and (i<tcgsize2size[fromsize]) then
+ href.addressmode:=AM_POSTINCREMENT
+ else
+ href.addressmode:=AM_UNCHANGED;
+ list.concat(taicpu.op_ref_reg(GetStore(href),href,tmpreg));
+ end;
+ end;
+ end;
+ OS_16:
+ begin
+ if not(QuickRef) and (tcgsize2size[tosize]>1) then
+ href.addressmode:=AM_POSTINCREMENT;
+
+ list.concat(taicpu.op_ref_reg(GetStore(href),href,reg));
+ if QuickRef then
+ inc(href.offset)
+ else if not(QuickRef) and (tcgsize2size[fromsize]>2) then
+ href.addressmode:=AM_POSTINCREMENT
+ else
+ href.addressmode:=AM_UNCHANGED;
+
+ reg:=GetNextReg(reg);
+ list.concat(taicpu.op_ref_reg(GetStore(href),href,reg));
+
+ for i:=3 to tcgsize2size[tosize] do
+ begin
+ if QuickRef then
+ inc(href.offset);
+
+ if not(QuickRef) and (i<tcgsize2size[fromsize]) then
+ href.addressmode:=AM_POSTINCREMENT
+ else
+ href.addressmode:=AM_UNCHANGED;
+
+ list.concat(taicpu.op_ref_reg(GetStore(href),href,NR_R1));
+ end;
+ end;
+ OS_S16:
+ begin
+ if not(QuickRef) and (tcgsize2size[tosize]>1) then
+ href.addressmode:=AM_POSTINCREMENT;
+
+ list.concat(taicpu.op_ref_reg(GetStore(href),href,reg));
+ if QuickRef then
+ inc(href.offset)
+ else if not(QuickRef) and (tcgsize2size[fromsize]>2) then
+ href.addressmode:=AM_POSTINCREMENT
+ else
+ href.addressmode:=AM_UNCHANGED;
+
+ reg:=GetNextReg(reg);
+ list.concat(taicpu.op_ref_reg(GetStore(href),href,reg));
+
+ if tcgsize2size[tosize]>2 then
+ begin
+ tmpreg:=getintregister(list,OS_8);
+ list.concat(taicpu.op_reg(A_CLR,tmpreg));
+ list.concat(taicpu.op_reg_const(A_SBRC,reg,7));
+ list.concat(taicpu.op_reg(A_COM,tmpreg));
+ for i:=3 to tcgsize2size[tosize] do
+ begin
+ if QuickRef then
+ inc(href.offset);
+
+ if not(QuickRef) and (i<tcgsize2size[fromsize]) then
+ href.addressmode:=AM_POSTINCREMENT
+ else
+ href.addressmode:=AM_UNCHANGED;
+ list.concat(taicpu.op_ref_reg(GetStore(href),href,tmpreg));
+ end;
+ end;
+ end;
+ else
+ conv_done:=false;
+ end;
+ end;
+ if not conv_done then
+ begin
+ for i:=1 to tcgsize2size[fromsize] do
+ begin
+ if not(QuickRef) and (i<tcgsize2size[fromsize]) then
+ href.addressmode:=AM_POSTINCREMENT
+ else
+ href.addressmode:=AM_UNCHANGED;
+
+ list.concat(taicpu.op_ref_reg(GetStore(href),href,reg));
+
+ if QuickRef then
+ inc(href.offset);
+
+ reg:=GetNextReg(reg);
+ end;
+ end;
+
+ if not(QuickRef) then
+ begin
+ ungetcpuregister(list,href.base);
+ ungetcpuregister(list,GetNextReg(href.base));
+ end;
+ end;
+
+
+ procedure tcgavr.a_load_ref_reg(list : TAsmList; fromsize, tosize : tcgsize;
+ const Ref : treference;reg : tregister);
+ var
+ href : treference;
+ conv_done: boolean;
+ tmpreg : tregister;
+ i : integer;
+ QuickRef : boolean;
+ begin
+ QuickRef:=false;
+ if not((Ref.addressmode=AM_UNCHANGED) and
+ (Ref.symbol=nil) and
+ ((Ref.base=NR_R28) or
+ (Ref.base=NR_R29)) and
+ (Ref.Index=NR_No) and
+ (Ref.Offset in [0..64-tcgsize2size[fromsize]])) and
+ not((Ref.Base=NR_NO) and (Ref.Index=NR_NO)) then
+ href:=normalize_ref(list,Ref,NR_R30)
+ else
+ begin
+ QuickRef:=true;
+ href:=Ref;
+ end;
+
+ if (tcgsize2size[fromsize]>32) or (tcgsize2size[tosize]>32) or (fromsize=OS_NO) or (tosize=OS_NO) then
+ internalerror(2011021307);
+
+ conv_done:=false;
+ if tosize<>fromsize then
+ begin
+ conv_done:=true;
+ if tcgsize2size[tosize]<=tcgsize2size[fromsize] then
+ fromsize:=tosize;
+ case fromsize of
+ OS_8:
+ begin
+ list.concat(taicpu.op_reg_ref(GetLoad(href),reg,href));
+ for i:=2 to tcgsize2size[tosize] do
+ begin
+ reg:=GetNextReg(reg);
+ list.concat(taicpu.op_reg(A_CLR,reg));
+ end;
+ end;
+ OS_S8:
+ begin
+ list.concat(taicpu.op_reg_ref(GetLoad(href),reg,href));
+ tmpreg:=reg;
+
+ if tcgsize2size[tosize]>1 then
+ begin
+ reg:=GetNextReg(reg);
+ list.concat(taicpu.op_reg(A_CLR,reg));
+ list.concat(taicpu.op_reg_const(A_SBRC,tmpreg,7));
+ list.concat(taicpu.op_reg(A_COM,reg));
+ tmpreg:=reg;
+ for i:=3 to tcgsize2size[tosize] do
+ begin
+ reg:=GetNextReg(reg);
+ emit_mov(list,reg,tmpreg);
+ end;
+ end;
+ end;
+ OS_16:
+ begin
+ if not(QuickRef) then
+ href.addressmode:=AM_POSTINCREMENT;
+ list.concat(taicpu.op_reg_ref(GetLoad(href),reg,href));
+
+ if QuickRef then
+ inc(href.offset);
+ href.addressmode:=AM_UNCHANGED;
+
+ reg:=GetNextReg(reg);
+ list.concat(taicpu.op_reg_ref(GetLoad(href),reg,href));
+
+ for i:=3 to tcgsize2size[tosize] do
+ begin
+ reg:=GetNextReg(reg);
+ list.concat(taicpu.op_reg(A_CLR,reg));
+ end;
+ end;
+ OS_S16:
+ begin
+ if not(QuickRef) then
+ href.addressmode:=AM_POSTINCREMENT;
+ list.concat(taicpu.op_reg_ref(GetLoad(href),reg,href));
+ if QuickRef then
+ inc(href.offset);
+ href.addressmode:=AM_UNCHANGED;
+
+ reg:=GetNextReg(reg);
+ list.concat(taicpu.op_reg_ref(GetLoad(href),reg,href));
+ tmpreg:=reg;
+
+ reg:=GetNextReg(reg);
+ list.concat(taicpu.op_reg(A_CLR,reg));
+ list.concat(taicpu.op_reg_const(A_SBRC,tmpreg,7));
+ list.concat(taicpu.op_reg(A_COM,reg));
+ tmpreg:=reg;
+ for i:=4 to tcgsize2size[tosize] do
+ begin
+ reg:=GetNextReg(reg);
+ emit_mov(list,reg,tmpreg);
+ end;
+ end;
+ else
+ conv_done:=false;
+ end;
+ end;
+ if not conv_done then
+ begin
+ for i:=1 to tcgsize2size[fromsize] do
+ begin
+ if not(QuickRef) and (i<tcgsize2size[fromsize]) then
+ href.addressmode:=AM_POSTINCREMENT
+ else
+ href.addressmode:=AM_UNCHANGED;
+
+ list.concat(taicpu.op_reg_ref(GetLoad(href),reg,href));
+
+ if QuickRef then
+ inc(href.offset);
+
+ reg:=GetNextReg(reg);
+ end;
+ end;
+
+ if not(QuickRef) then
+ begin
+ ungetcpuregister(list,href.base);
+ ungetcpuregister(list,GetNextReg(href.base));
+ end;
+ end;
+
+
+ procedure tcgavr.a_load_reg_reg(list : TAsmList; fromsize, tosize : tcgsize;reg1,reg2 : tregister);
+ var
+ conv_done: boolean;
+ tmpreg : tregister;
+ i : integer;
+ begin
+ if (tcgsize2size[fromsize]>32) or (tcgsize2size[tosize]>32) or (fromsize=OS_NO) or (tosize=OS_NO) then
+ internalerror(2011021310);
+
+ conv_done:=false;
+ if tosize<>fromsize then
+ begin
+ conv_done:=true;
+ if tcgsize2size[tosize]<=tcgsize2size[fromsize] then
+ fromsize:=tosize;
+ case fromsize of
+ OS_8:
+ begin
+ emit_mov(list,reg2,reg1);
+ for i:=2 to tcgsize2size[tosize] do
+ begin
+ reg2:=GetNextReg(reg2);
+ list.concat(taicpu.op_reg(A_CLR,reg2));
+ end;
+ end;
+ OS_S8:
+ begin
+ { dest is always at least 16 bit at this point }
+ emit_mov(list,reg2,reg1);
+
+ reg2:=GetNextReg(reg2);
+ list.concat(taicpu.op_reg(A_CLR,reg2));
+ list.concat(taicpu.op_reg_const(A_SBRC,reg1,7));
+ list.concat(taicpu.op_reg(A_COM,reg2));
+ tmpreg:=reg2;
+ for i:=3 to tcgsize2size[tosize] do
+ begin
+ reg2:=GetNextReg(reg2);
+ emit_mov(list,reg2,tmpreg);
+ end;
+ end;
+ OS_16:
+ begin
+ emit_mov(list,reg2,reg1);
+
+ reg1:=GetNextReg(reg1);
+ reg2:=GetNextReg(reg2);
+ emit_mov(list,reg2,reg1);
+
+ for i:=3 to tcgsize2size[tosize] do
+ begin
+ reg2:=GetNextReg(reg2);
+ list.concat(taicpu.op_reg(A_CLR,reg2));
+ end;
+ end;
+ OS_S16:
+ begin
+ { dest is always at least 32 bit at this point }
+ emit_mov(list,reg2,reg1);
+
+ reg1:=GetNextReg(reg1);
+ reg2:=GetNextReg(reg2);
+ emit_mov(list,reg2,reg1);
+
+ reg2:=GetNextReg(reg2);
+ list.concat(taicpu.op_reg(A_CLR,reg2));
+ list.concat(taicpu.op_reg_const(A_SBRC,reg1,7));
+ list.concat(taicpu.op_reg(A_COM,reg2));
+ tmpreg:=reg2;
+ for i:=4 to tcgsize2size[tosize] do
+ begin
+ reg2:=GetNextReg(reg2);
+ emit_mov(list,reg2,tmpreg);
+ end;
+ end;
+ else
+ conv_done:=false;
+ end;
+ end;
+ if not conv_done and (reg1<>reg2) then
+ begin
+ for i:=1 to tcgsize2size[fromsize] do
+ begin
+ emit_mov(list,reg2,reg1);
+ reg1:=GetNextReg(reg1);
+ reg2:=GetNextReg(reg2);
+ end;
+ end;
+ end;
+
+
+ procedure tcgavr.a_loadfpu_reg_reg(list: TAsmList; fromsize,tosize: tcgsize; reg1, reg2: tregister);
+ begin
+ internalerror(2012010702);
+ end;
+
+
+ procedure tcgavr.a_loadfpu_ref_reg(list: TAsmList; fromsize,tosize: tcgsize; const ref: treference; reg: tregister);
+ begin
+ internalerror(2012010703);
+ end;
+
+
+ procedure tcgavr.a_loadfpu_reg_ref(list: TAsmList; fromsize, tosize: tcgsize; reg: tregister; const ref: treference);
+ begin
+ internalerror(2012010704);
+ end;
+
+
+ { comparison operations }
+ procedure tcgavr.a_cmp_const_reg_label(list : TAsmList;size : tcgsize;
+ cmp_op : topcmp;a : tcgint;reg : tregister;l : tasmlabel);
+ var
+ swapped : boolean;
+ tmpreg : tregister;
+ i : byte;
+ begin
+ if a=0 then
+ begin
+ { swap parameters? }
+ case cmp_op of
+ OC_GT:
+ begin
+ swapped:=true;
+ cmp_op:=OC_LT;
+ end;
+ OC_LTE:
+ begin
+ swapped:=true;
+ cmp_op:=OC_GTE;
+ end;
+ OC_BE:
+ begin
+ swapped:=true;
+ cmp_op:=OC_AE;
+ end;
+ OC_A:
+ begin
+ swapped:=true;
+ cmp_op:=OC_A;
+ end;
+ end;
+
+ if swapped then
+ list.concat(taicpu.op_reg_reg(A_CP,reg,NR_R1))
+ else
+ list.concat(taicpu.op_reg_reg(A_CP,NR_R1,reg));
+
+ for i:=2 to tcgsize2size[size] do
+ begin
+ reg:=GetNextReg(reg);
+ if swapped then
+ list.concat(taicpu.op_reg_reg(A_CPC,reg,NR_R1))
+ else
+ list.concat(taicpu.op_reg_reg(A_CPC,NR_R1,reg));
+ end;
+
+ a_jmp_cond(list,cmp_op,l);
+ end
+ else
+ inherited a_cmp_const_reg_label(list,size,cmp_op,a,reg,l);
+ end;
+
+
+ procedure tcgavr.a_cmp_reg_reg_label(list : TAsmList;size : tcgsize;
+ cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel);
+ var
+ swapped : boolean;
+ tmpreg : tregister;
+ i : byte;
+ begin
+ { swap parameters? }
+ case cmp_op of
+ OC_GT:
+ begin
+ swapped:=true;
+ cmp_op:=OC_LT;
+ end;
+ OC_LTE:
+ begin
+ swapped:=true;
+ cmp_op:=OC_GTE;
+ end;
+ OC_BE:
+ begin
+ swapped:=true;
+ cmp_op:=OC_AE;
+ end;
+ OC_A:
+ begin
+ swapped:=true;
+ cmp_op:=OC_A;
+ end;
+ end;
+ if swapped then
+ begin
+ tmpreg:=reg1;
+ reg1:=reg2;
+ reg2:=tmpreg;
+ end;
+ list.concat(taicpu.op_reg_reg(A_CP,reg1,reg2));
+
+ for i:=2 to tcgsize2size[size] do
+ begin
+ reg1:=GetNextReg(reg1);
+ reg2:=GetNextReg(reg2);
+ list.concat(taicpu.op_reg_reg(A_CPC,reg1,reg2));
+ end;
+
+ a_jmp_cond(list,cmp_op,l);
+ end;
+
+
+ procedure tcgavr.a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; size: TCGSize; src, dst: TRegister);
+ begin
+ Comment(V_Error,'tcgarm.a_bit_scan_reg_reg method not implemented');
+ end;
+
+
+ procedure tcgavr.a_jmp_name(list : TAsmList;const s : string);
+ var
+ ai : taicpu;
+ begin
+ ai:=taicpu.op_sym(A_JMP,current_asmdata.RefAsmSymbol(s));
+ ai.is_jmp:=true;
+ list.concat(ai);
+ end;
+
+
+ procedure tcgavr.a_jmp_always(list : TAsmList;l: tasmlabel);
+ var
+ ai : taicpu;
+ begin
+ ai:=taicpu.op_sym(A_JMP,l);
+ ai.is_jmp:=true;
+ list.concat(ai);
+ end;
+
+
+ procedure tcgavr.a_jmp_flags(list : TAsmList;const f : TResFlags;l: tasmlabel);
+ var
+ ai : taicpu;
+ begin
+ ai:=setcondition(taicpu.op_sym(A_BRxx,l),flags_to_cond(f));
+ ai.is_jmp:=true;
+ list.concat(ai);
+ end;
+
+
+ procedure tcgavr.g_flags2reg(list: TAsmList; size: TCgSize; const f: TResFlags; reg: TRegister);
+ var
+ l : TAsmLabel;
+ tmpflags : TResFlags;
+ begin
+ current_asmdata.getjumplabel(l);
+ {
+ if flags_to_cond(f) then
+ begin
+ tmpflags:=f;
+ inverse_flags(tmpflags);
+ list.concat(taicpu.op_reg(A_CLR,reg));
+ a_jmp_flags(list,tmpflags,l);
+ list.concat(taicpu.op_reg_const(A_LDI,reg,1));
+ end
+ else
+ }
+ begin
+ list.concat(taicpu.op_reg_const(A_LDI,reg,1));
+ a_jmp_flags(list,f,l);
+ list.concat(taicpu.op_reg(A_CLR,reg));
+ end;
+ cg.a_label(list,l);
+ end;
+
+
+ procedure tcgavr.a_adjust_sp(list : TAsmList; value : longint);
+ var
+ i : integer;
+ begin
+ case value of
+ 0:
+ ;
+ -14..-1:
+ begin
+ if ((-value) mod 2)<>0 then
+ list.concat(taicpu.op_reg(A_PUSH,NR_R0));
+ for i:=1 to (-value) div 2 do
+ list.concat(taicpu.op_const(A_RCALL,0));
+ end;
+ 1..7:
+ begin
+ for i:=1 to value do
+ list.concat(taicpu.op_reg(A_POP,NR_R0));
+ end;
+ else
+ begin
+ list.concat(taicpu.op_reg_const(A_SUBI,NR_R28,lo(word(-value))));
+ list.concat(taicpu.op_reg_const(A_SBCI,NR_R29,hi(word(-value))));
+ // get SREG
+ list.concat(taicpu.op_reg_const(A_IN,NR_R0,NIO_SREG));
+
+ // block interrupts
+ list.concat(taicpu.op_none(A_CLI));
+
+ // write high SP
+ list.concat(taicpu.op_const_reg(A_OUT,NIO_SP_HI,NR_R29));
+
+ // release interrupts
+ list.concat(taicpu.op_const_reg(A_OUT,NIO_SREG,NR_R0));
+
+ // write low SP
+ list.concat(taicpu.op_const_reg(A_OUT,NIO_SP_LO,NR_R28));
+ end;
+ end;
+ end;
+
+
+ function tcgavr.GetLoad(const ref: treference) : tasmop;
+ begin
+ if (ref.base=NR_NO) and (ref.index=NR_NO) then
+ result:=A_LDS
+ else if (ref.base<>NR_NO) and (ref.offset<>0) then
+ result:=A_LDD
+ else
+ result:=A_LD;
+ end;
+
+
+ function tcgavr.GetStore(const ref: treference) : tasmop;
+ begin
+ if (ref.base=NR_NO) and (ref.index=NR_NO) then
+ result:=A_STS
+ else if (ref.base<>NR_NO) and (ref.offset<>0) then
+ result:=A_STD
+ else
+ result:=A_ST;
+ end;
+
+
+ procedure tcgavr.g_proc_entry(list : TAsmList;localsize : longint;nostackframe:boolean);
+ var
+ regs : tcpuregisterset;
+ reg : tsuperregister;
+ begin
+ if not(nostackframe) then
+ begin
+ { save int registers }
+ regs:=rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall);
+ if current_procinfo.framepointer<>NR_STACK_POINTER_REG then
+ regs:=regs+[RS_R28,RS_R29];
+
+ for reg:=RS_R31 downto RS_R0 do
+ if reg in regs then
+ list.concat(taicpu.op_reg(A_PUSH,newreg(R_INTREGISTER,reg,R_SUBWHOLE)));
+
+ if current_procinfo.framepointer<>NR_STACK_POINTER_REG then
+ begin
+ list.concat(taicpu.op_reg_const(A_IN,NR_R28,NIO_SP_LO));
+ list.concat(taicpu.op_reg_const(A_IN,NR_R29,NIO_SP_HI));
+ end
+ else
+ { the framepointer cannot be omitted on avr because sp
+ is not a register but part of the i/o map
+ }
+ internalerror(2011021901);
+
+ a_adjust_sp(list,-localsize);
+ end;
+ end;
+
+
+ procedure tcgavr.g_proc_exit(list : TAsmList;parasize : longint;nostackframe:boolean);
+ var
+ regs : tcpuregisterset;
+ reg : TSuperRegister;
+ LocalSize : longint;
+ begin
+ if not(nostackframe) then
+ begin
+ if current_procinfo.framepointer<>NR_STACK_POINTER_REG then
+ begin
+ LocalSize:=current_procinfo.calc_stackframe_size;
+ a_adjust_sp(list,LocalSize);
+ regs:=rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall);
+
+ for reg:=RS_R0 to RS_R31 do
+ if reg in regs then
+ list.concat(taicpu.op_reg(A_POP,newreg(R_INTREGISTER,reg,R_SUBWHOLE)));
+
+ end
+ else
+ { the framepointer cannot be omitted on avr because sp
+ is not a register but part of the i/o map
+ }
+ internalerror(2011021902);
+ end;
+ list.concat(taicpu.op_none(A_RET));
+ end;
+
+
+ procedure tcgavr.a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);
+ var
+ tmpref : treference;
+ begin
+ if ref.addressmode<>AM_UNCHANGED then
+ internalerror(2011021701);
+
+ if assigned(ref.symbol) or (ref.offset<>0) then
+ begin
+ reference_reset(tmpref,0);
+ tmpref.symbol:=ref.symbol;
+ tmpref.offset:=ref.offset;
+ tmpref.refaddr:=addr_lo8;
+ list.concat(taicpu.op_reg_ref(A_LDI,r,tmpref));
+ tmpref.refaddr:=addr_hi8;
+ list.concat(taicpu.op_reg_ref(A_LDI,GetNextReg(r),tmpref));
+ if (ref.base<>NR_NO) then
+ begin
+ list.concat(taicpu.op_reg_reg(A_ADD,r,ref.base));
+ list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(r),GetNextReg(ref.base)));
+ end;
+ if (ref.index<>NR_NO) then
+ begin
+ list.concat(taicpu.op_reg_reg(A_ADD,r,ref.index));
+ list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(r),GetNextReg(ref.index)));
+ end;
+ end
+ else if (ref.base<>NR_NO)then
+ begin
+ emit_mov(list,r,ref.base);
+ emit_mov(list,GetNextReg(r),GetNextReg(ref.base));
+ if (ref.index<>NR_NO) then
+ begin
+ list.concat(taicpu.op_reg_reg(A_ADD,r,ref.index));
+ list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(r),GetNextReg(ref.index)));
+ end;
+ end
+ else if (ref.index<>NR_NO) then
+ begin
+ emit_mov(list,r,ref.index);
+ emit_mov(list,GetNextReg(r),GetNextReg(ref.index));
+ end;
+ end;
+
+
+ procedure tcgavr.fixref(list : TAsmList;var ref : treference);
+ begin
+ internalerror(2011021320);
+ end;
+
+
+ procedure tcgavr.g_concatcopy_move(list : TAsmList;const source,dest : treference;len : tcgint);
+ var
+ paraloc1,paraloc2,paraloc3 : TCGPara;
+ begin
+ paraloc1.init;
+ paraloc2.init;
+ paraloc3.init;
+ paramanager.getintparaloc(pocall_default,1,paraloc1);
+ paramanager.getintparaloc(pocall_default,2,paraloc2);
+ paramanager.getintparaloc(pocall_default,3,paraloc3);
+ a_load_const_cgpara(list,OS_INT,len,paraloc3);
+ a_loadaddr_ref_cgpara(list,dest,paraloc2);
+ a_loadaddr_ref_cgpara(list,source,paraloc1);
+ paramanager.freecgpara(list,paraloc3);
+ paramanager.freecgpara(list,paraloc2);
+ paramanager.freecgpara(list,paraloc1);
+ alloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
+ a_call_name_static(list,'FPC_MOVE');
+ dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
+ paraloc3.done;
+ paraloc2.done;
+ paraloc1.done;
+ end;
+
+
+ procedure tcgavr.g_concatcopy(list : TAsmList;const source,dest : treference;len : tcgint);
+ var
+ countreg,tmpreg : tregister;
+ srcref,dstref : treference;
+ copysize,countregsize : tcgsize;
+ l : TAsmLabel;
+ i : longint;
+ SrcQuickRef, DestQuickRef : Boolean;
+ begin
+ if len>16 then
+ begin
+ current_asmdata.getjumplabel(l);
+
+ reference_reset(srcref,0);
+ reference_reset(dstref,0);
+ srcref.base:=NR_R30;
+ srcref.addressmode:=AM_POSTINCREMENT;
+ dstref.base:=NR_R26;
+ dstref.addressmode:=AM_POSTINCREMENT;
+
+ copysize:=OS_8;
+ if len<256 then
+ countregsize:=OS_8
+ else if len<65536 then
+ countregsize:=OS_16
+ else
+ internalerror(2011022007);
+ countreg:=getintregister(list,countregsize);
+ a_load_const_reg(list,countregsize,len,countreg);
+ a_loadaddr_ref_reg(list,source,NR_R30);
+ tmpreg:=getaddressregister(list);
+ a_loadaddr_ref_reg(list,dest,tmpreg);
+
+ { X is used for spilling code so we can load it
+ only by a push/pop sequence, this can be
+ optimized later on by the peephole optimizer
+ }
+ list.concat(taicpu.op_reg(A_PUSH,tmpreg));
+ list.concat(taicpu.op_reg(A_PUSH,GetNextReg(tmpreg)));
+ list.concat(taicpu.op_reg(A_POP,NR_R27));
+ list.concat(taicpu.op_reg(A_POP,NR_R26));
+ cg.a_label(list,l);
+ list.concat(taicpu.op_reg_ref(GetLoad(srcref),NR_R0,srcref));
+ list.concat(taicpu.op_ref_reg(GetStore(dstref),dstref,NR_R0));
+ a_op_const_reg(list,OP_SUB,countregsize,1,countreg);
+ a_jmp_flags(list,F_NE,l);
+ // keep registers alive
+ list.concat(taicpu.op_reg_reg(A_MOV,countreg,countreg));
+ end
+ else
+ begin
+ SrcQuickRef:=false;
+ DestQuickRef:=false;
+ if not((source.addressmode=AM_UNCHANGED) and
+ (source.symbol=nil) and
+ ((source.base=NR_R28) or
+ (source.base=NR_R29)) and
+ (source.Index=NR_NO) and
+ (source.Offset in [0..64-len])) and
+ not((source.Base=NR_NO) and (source.Index=NR_NO)) then
+ srcref:=normalize_ref(list,source,NR_R30)
+ else
+ begin
+ SrcQuickRef:=true;
+ srcref:=source;
+ end;
+
+ if not((dest.addressmode=AM_UNCHANGED) and
+ (dest.symbol=nil) and
+ ((dest.base=NR_R28) or
+ (dest.base=NR_R29)) and
+ (dest.Index=NR_No) and
+ (dest.Offset in [0..64-len])) and
+ not((dest.Base=NR_NO) and (dest.Index=NR_NO)) then
+ begin
+ if not(SrcQuickRef) then
+ begin
+ tmpreg:=getaddressregister(list);
+ dstref:=normalize_ref(list,dest,tmpreg);
+
+ { X is used for spilling code so we can load it
+ only by a push/pop sequence, this can be
+ optimized later on by the peephole optimizer
+ }
+ list.concat(taicpu.op_reg(A_PUSH,tmpreg));
+ list.concat(taicpu.op_reg(A_PUSH,GetNextReg(tmpreg)));
+ list.concat(taicpu.op_reg(A_POP,NR_R27));
+ list.concat(taicpu.op_reg(A_POP,NR_R26));
+ dstref.base:=NR_R26;
+ end
+ else
+ dstref:=normalize_ref(list,dest,NR_R30);
+ end
+ else
+ begin
+ DestQuickRef:=true;
+ dstref:=dest;
+ end;
+
+ for i:=1 to len do
+ begin
+ if not(SrcQuickRef) and (i<len) then
+ srcref.addressmode:=AM_POSTINCREMENT
+ else
+ srcref.addressmode:=AM_UNCHANGED;
+
+ if not(DestQuickRef) and (i<len) then
+ dstref.addressmode:=AM_POSTINCREMENT
+ else
+ dstref.addressmode:=AM_UNCHANGED;
+
+ list.concat(taicpu.op_reg_ref(GetLoad(srcref),NR_R0,srcref));
+ list.concat(taicpu.op_ref_reg(GetStore(dstref),dstref,NR_R0));
+
+ if SrcQuickRef then
+ inc(srcref.offset);
+ if DestQuickRef then
+ inc(dstref.offset);
+ end;
+ if not(SrcQuickRef) then
+ begin
+ ungetcpuregister(list,srcref.base);
+ ungetcpuregister(list,GetNextReg(srcref.base));
+ end;
+ end;
+ end;
+
+
+ procedure tcgavr.g_overflowCheck(list : TAsmList;const l : tlocation;def : tdef);
+ var
+ hl : tasmlabel;
+ ai : taicpu;
+ cond : TAsmCond;
+ begin
+ if not(cs_check_overflow in current_settings.localswitches) then
+ exit;
+ current_asmdata.getjumplabel(hl);
+ if not ((def.typ=pointerdef) or
+ ((def.typ=orddef) and
+ (torddef(def).ordtype in [u64bit,u16bit,u32bit,u8bit,uchar,
+ pasbool8,pasbool16,pasbool32,pasbool64]))) then
+ cond:=C_VC
+ else
+ cond:=C_CC;
+ ai:=Taicpu.Op_Sym(A_BRxx,hl);
+ ai.SetCondition(cond);
+ ai.is_jmp:=true;
+ list.concat(ai);
+
+ a_call_name(list,'FPC_OVERFLOW',false);
+ a_label(list,hl);
+ end;
+
+
+ procedure tcgavr.g_save_registers(list: TAsmList);
+ begin
+ { this is done by the entry code }
+ end;
+
+
+ procedure tcgavr.g_restore_registers(list: TAsmList);
+ begin
+ { this is done by the exit code }
+ end;
+
+
+ procedure tcgavr.a_jmp_cond(list : TAsmList;cond : TOpCmp;l: tasmlabel);
+ var
+ ai1,ai2 : taicpu;
+ hl : TAsmLabel;
+ begin
+ ai1:=Taicpu.Op_sym(A_BRxx,l);
+ ai1.is_jmp:=true;
+ hl:=nil;
+ case cond of
+ OC_EQ:
+ ai1.SetCondition(C_EQ);
+ OC_GT:
+ begin
+ { emulate GT }
+ current_asmdata.getjumplabel(hl);
+ ai2:=Taicpu.Op_Sym(A_BRxx,hl);
+ ai2.SetCondition(C_EQ);
+ ai2.is_jmp:=true;
+ list.concat(ai2);
+
+ ai1.SetCondition(C_GE);
+ end;
+ OC_LT:
+ ai1.SetCondition(C_LT);
+ OC_GTE:
+ ai1.SetCondition(C_GE);
+ OC_LTE:
+ begin
+ { emulate LTE }
+ ai2:=Taicpu.Op_Sym(A_BRxx,l);
+ ai2.SetCondition(C_EQ);
+ ai2.is_jmp:=true;
+ list.concat(ai2);
+
+ ai1.SetCondition(C_LT);
+ end;
+ OC_NE:
+ ai1.SetCondition(C_NE);
+ OC_BE:
+ begin
+ { emulate BE }
+ ai2:=Taicpu.Op_Sym(A_BRxx,l);
+ ai2.SetCondition(C_EQ);
+ ai2.is_jmp:=true;
+ list.concat(ai2);
+
+ ai1.SetCondition(C_LO);
+ end;
+ OC_B:
+ ai1.SetCondition(C_LO);
+ OC_AE:
+ ai1.SetCondition(C_SH);
+ OC_A:
+ begin
+ { emulate A (unsigned GT) }
+ current_asmdata.getjumplabel(hl);
+ ai2:=Taicpu.Op_Sym(A_BRxx,hl);
+ ai2.SetCondition(C_EQ);
+ ai2.is_jmp:=true;
+ list.concat(ai2);
+
+ ai1.SetCondition(C_SH);
+ end;
+ else
+ internalerror(2011082501);
+ end;
+ list.concat(ai1);
+ if assigned(hl) then
+ a_label(list,hl);
+ end;
+
+
+ procedure tcgavr.g_stackpointer_alloc(list: TAsmList; size: longint);
+ begin
+ internalerror(201201071);
+ end;
+
+
+ procedure tcgavr.g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);
+ begin
+ internalerror(2011021324);
+ end;
+
+
+ procedure tcgavr.emit_mov(list: TAsmList;reg2: tregister; reg1: tregister);
+ var
+ instr: taicpu;
+ begin
+ instr:=taicpu.op_reg_reg(A_MOV,reg2,reg1);
+ list.Concat(instr);
+ { Notify the register allocator that we have written a move instruction so
+ it can try to eliminate it. }
+ add_move_instruction(instr);
+ end;
+
+
+ procedure tcg64favr.a_op64_reg_reg(list : TAsmList;op:TOpCG;size : tcgsize;regsrc,regdst : tregister64);
+ begin
+ { TODO : a_op64_reg_reg }
+ end;
+
+
+ procedure tcg64favr.a_op64_const_reg(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;reg : tregister64);
+ begin
+ { TODO : a_op64_const_reg }
+ end;
+
+
+ procedure create_codegen;
+ begin
+ cg:=tcgavr.create;
+ cg64:=tcg64favr.create;
+ end;
+
+end.
diff --git a/closures/compiler/avr/cpubase.pas b/closures/compiler/avr/cpubase.pas
new file mode 100644
index 0000000000..6e04d858ce
--- /dev/null
+++ b/closures/compiler/avr/cpubase.pas
@@ -0,0 +1,474 @@
+{
+ Copyright (c) 2006 by Florian Klaempfl
+
+ Contains the base types for the AVR
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+{# Base unit for processor information. This unit contains
+ enumerations of registers, opcodes, sizes, and other
+ such things which are processor specific.
+}
+unit cpubase;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ cutils,cclasses,
+ globtype,globals,
+ cpuinfo,
+ aasmbase,
+ cgbase
+ ;
+
+
+{*****************************************************************************
+ Assembler Opcodes
+*****************************************************************************}
+
+ type
+ TAsmOp=(A_None,
+ A_ADD,A_ADC,A_ADIW,A_SUB,A_SUBI,A_SBC,A_SBCI,A_SBRC,A_SBRS,A_CLC,A_SEC,A_SBIW,A_AND,A_ANDI,
+ A_OR,A_ORI,A_EOR,A_COM,A_NEG,A_SBR,A_CBR,A_INC,A_DEC,A_TST,A_CLR,
+ A_SER,A_MUL,A_MULS,A_FMUL,A_FMULS,A_FMULSU,A_RJMP,A_IJMP,
+ A_EIJMP,A_JMP,A_RCALL,A_ICALL,R_EICALL,A_CALL,A_RET,A_RETI,A_CPSE,
+ A_CP,A_CPC,A_CPI,A_SBIC,A_SBIS,A_BRxx,A_MOV,A_MOVW,A_LDI,A_LDS,A_LD,A_LDD,
+ A_STS,A_ST,A_STD,A_LPM,A_ELPM,A_SPM,A_IN,A_OUT,A_PUSH,A_POP,
+ A_LSL,A_LSR,A_ROL,A_ROR,A_ASR,A_SWAP,A_BSET,A_BCLR,A_SBI,A_CBI,
+ A_BST,A_BLD,A_Sxx,A_CLI,A_BRAK,A_NOP,A_SLEEP,A_WDR);
+
+
+ { This should define the array of instructions as string }
+ op2strtable=array[tasmop] of string[11];
+
+ const
+ { First value of opcode enumeration }
+ firstop = low(tasmop);
+ { Last value of opcode enumeration }
+ lastop = high(tasmop);
+
+ jmp_instructions = [A_BRxx,A_SBIC,A_SBIS,A_JMP,A_RCALL,A_ICALL,A_EIJMP,
+ A_RJMP,A_CALL,A_RET,A_RETI,A_CPSE,A_IJMP];
+
+{*****************************************************************************
+ Registers
+*****************************************************************************}
+
+ type
+ { Number of registers used for indexing in tables }
+ tregisterindex=0..{$i ravrnor.inc}-1;
+
+ const
+ { Available Superregisters }
+ {$i ravrsup.inc}
+
+ { No Subregisters }
+ R_SUBWHOLE = R_SUBNONE;
+
+ { Available Registers }
+ {$i ravrcon.inc}
+
+ NR_XLO = NR_R26;
+ NR_XHI = NR_R27;
+ NR_YLO = NR_R28;
+ NR_YHI = NR_R29;
+ NR_ZLO = NR_R30;
+ NR_ZHI = NR_R31;
+
+ NIO_SREG = $3f;
+ NIO_SP_LO = $3d;
+ NIO_SP_HI = $3e;
+
+ { Integer Super registers first and last }
+ first_int_supreg = RS_R0;
+ first_int_imreg = $20;
+
+ { Float Super register first and last }
+ first_fpu_supreg = RS_INVALID;
+ first_fpu_imreg = RS_INVALID;
+
+ { MM Super register first and last }
+ first_mm_supreg = RS_INVALID;
+ first_mm_imreg = RS_INVALID;
+
+ regnumber_count_bsstart = 32;
+
+ regnumber_table : array[tregisterindex] of tregister = (
+ {$i ravrnum.inc}
+ );
+
+ regstabs_table : array[tregisterindex] of shortint = (
+ {$i ravrsta.inc}
+ );
+
+ regdwarf_table : array[tregisterindex] of shortint = (
+ {$i ravrdwa.inc}
+ );
+ { registers which may be destroyed by calls }
+ VOLATILE_INTREGISTERS = [RS_R0,RS_R1,RS_R8..RS_R27,RS_R30,RS_R31];
+ VOLATILE_FPUREGISTERS = [];
+
+ type
+ totherregisterset = set of tregisterindex;
+
+{*****************************************************************************
+ Conditions
+*****************************************************************************}
+
+ type
+ TAsmCond=(C_None,
+ C_CC,C_CS,C_EQ,C_GE,C_HC,C_HS,C_ID,C_IE,C_LO,C_LT,
+ C_MI,C_NE,C_PL,C_SH,C_TC,C_TS,C_VC,C_VS
+ );
+
+ const
+ cond2str : array[TAsmCond] of string[2]=('',
+ 'cc','cs','eq','ge','hc','hs','id','ie','lo','lt',
+ 'mi','ne','pl','sh','tc','ts','vc','vs'
+ );
+
+ uppercond2str : array[TAsmCond] of string[2]=('',
+ 'CC','CS','EQ','GE','HC','HS','ID','IE','LO','LT',
+ 'MI','NE','PL','SH','TC','TS','VC','VS'
+ );
+
+{*****************************************************************************
+ Flags
+*****************************************************************************}
+
+ type
+ TResFlags = (F_NotPossible,F_CC,F_CS,F_EQ,F_GE,F_LO,F_LT,
+ F_NE,F_SH,F_VC,F_VS);
+
+{*****************************************************************************
+ Operands
+*****************************************************************************}
+
+ taddressmode = (AM_UNCHANGED,AM_POSTINCREMENT,AM_PREDRECEMENT);
+
+{*****************************************************************************
+ Constants
+*****************************************************************************}
+
+ const
+ max_operands = 4;
+
+ maxintregs = 15;
+ maxfpuregs = 0;
+ maxaddrregs = 0;
+
+{*****************************************************************************
+ Operand Sizes
+*****************************************************************************}
+
+ type
+ topsize = (S_NO,
+ S_B,S_W,S_L,S_BW,S_BL,S_WL,
+ S_IS,S_IL,S_IQ,
+ S_FS,S_FL,S_FX,S_D,S_Q,S_FV,S_FXX
+ );
+
+{*****************************************************************************
+ Constants
+*****************************************************************************}
+
+ const
+ firstsaveintreg = RS_R4;
+ lastsaveintreg = RS_R10;
+ firstsavefpureg = RS_INVALID;
+ lastsavefpureg = RS_INVALID;
+ firstsavemmreg = RS_INVALID;
+ lastsavemmreg = RS_INVALID;
+
+ maxvarregs = 7;
+ varregs : Array [1..maxvarregs] of tsuperregister =
+ (RS_R4,RS_R5,RS_R6,RS_R7,RS_R8,RS_R9,RS_R10);
+
+ maxfpuvarregs = 1;
+ fpuvarregs : Array [1..maxfpuvarregs] of tsuperregister =
+ (RS_INVALID);
+
+{*****************************************************************************
+ Default generic sizes
+*****************************************************************************}
+
+ { Defines the default address size for a processor, }
+ OS_ADDR = OS_16;
+ { the natural int size for a processor, }
+ OS_INT = OS_16;
+ OS_SINT = OS_S16;
+ { the maximum float size for a processor, }
+ OS_FLOAT = OS_F64;
+ { the size of a vector register for a processor }
+ OS_VECTOR = OS_M32;
+
+{*****************************************************************************
+ Generic Register names
+*****************************************************************************}
+
+ { Stack pointer register }
+ NR_STACK_POINTER_REG = NR_R13;
+ RS_STACK_POINTER_REG = RS_R13;
+ { Frame pointer register }
+ RS_FRAME_POINTER_REG = RS_R28;
+ NR_FRAME_POINTER_REG = NR_R28;
+ { Register for addressing absolute data in a position independant way,
+ such as in PIC code. The exact meaning is ABI specific. For
+ further information look at GCC source : PIC_OFFSET_TABLE_REGNUM
+ }
+ NR_PIC_OFFSET_REG = NR_R9;
+ { Results are returned in this register (32-bit values) }
+ NR_FUNCTION_RETURN_REG = NR_R0;
+ RS_FUNCTION_RETURN_REG = RS_R0;
+ { Low part of 64bit return value }
+ NR_FUNCTION_RETURN64_LOW_REG = NR_R0;
+ RS_FUNCTION_RETURN64_LOW_REG = RS_R0;
+ { High part of 64bit return value }
+ NR_FUNCTION_RETURN64_HIGH_REG = NR_R1;
+ RS_FUNCTION_RETURN64_HIGH_REG = RS_R1;
+ { The value returned from a function is available in this register }
+ NR_FUNCTION_RESULT_REG = NR_FUNCTION_RETURN_REG;
+ RS_FUNCTION_RESULT_REG = RS_FUNCTION_RETURN_REG;
+ { The lowh part of 64bit value returned from a function }
+ NR_FUNCTION_RESULT64_LOW_REG = NR_FUNCTION_RETURN64_LOW_REG;
+ RS_FUNCTION_RESULT64_LOW_REG = RS_FUNCTION_RETURN64_LOW_REG;
+ { The high part of 64bit value returned from a function }
+ NR_FUNCTION_RESULT64_HIGH_REG = NR_FUNCTION_RETURN64_HIGH_REG;
+ RS_FUNCTION_RESULT64_HIGH_REG = RS_FUNCTION_RETURN64_HIGH_REG;
+
+ NR_FPU_RESULT_REG = NR_NO;
+
+ NR_MM_RESULT_REG = NR_NO;
+
+ NR_RETURN_ADDRESS_REG = NR_FUNCTION_RETURN_REG;
+
+ { Offset where the parent framepointer is pushed }
+ PARENT_FRAMEPOINTER_OFFSET = 0;
+
+{*****************************************************************************
+ GCC /ABI linking information
+*****************************************************************************}
+
+ const
+ { Registers which must be saved when calling a routine declared as
+ cppdecl, cdecl, stdcall, safecall, palmossyscall. The registers
+ saved should be the ones as defined in the target ABI and / or GCC.
+
+ This value can be deduced from the CALLED_USED_REGISTERS array in the
+ GCC source.
+ }
+ { on avr, gen_entry/gen_exit code saves/restores registers, so
+ we don't need this array }
+ saved_standard_registers : array[0..0] of tsuperregister =
+ (RS_INVALID);
+ { Required parameter alignment when calling a routine declared as
+ stdcall and cdecl. The alignment value should be the one defined
+ by GCC or the target ABI.
+
+ The value of this constant is equal to the constant
+ PARM_BOUNDARY / BITS_PER_UNIT in the GCC source.
+ }
+ std_param_align = 4;
+
+ saved_mm_registers : array[0..0] of tsuperregister = (RS_INVALID);
+
+{*****************************************************************************
+ Helpers
+*****************************************************************************}
+
+ { Returns the tcgsize corresponding with the size of reg.}
+ function reg_cgsize(const reg: tregister) : tcgsize;
+ function cgsize2subreg(regtype: tregistertype; s:Tcgsize):Tsubregister;
+ procedure inverse_flags(var f: TResFlags);
+ function flags_to_cond(const f: TResFlags) : TAsmCond;
+ function findreg_by_number(r:Tregister):tregisterindex;
+ function std_regnum_search(const s:string):Tregister;
+ function std_regname(r:Tregister):string;
+
+ function inverse_cond(const c: TAsmCond): TAsmCond; {$ifdef USEINLINE}inline;{$endif USEINLINE}
+ function conditions_equal(const c1, c2: TAsmCond): boolean; {$ifdef USEINLINE}inline;{$endif USEINLINE}
+
+ function dwarf_reg(r:tregister):byte;
+ function GetHigh(const r : TRegister) : TRegister;
+
+ { returns the next virtual register }
+ function GetNextReg(const r : TRegister) : TRegister;
+
+ { returns the last virtual register }
+ function GetLastReg(const r : TRegister) : TRegister;
+
+ function GetOffsetReg(const r : TRegister;ofs : shortint) : TRegister;
+
+ function ReplaceForbiddenChars(const s: string): string;
+
+ implementation
+
+ uses
+ rgBase,verbose;
+
+
+ const
+ std_regname_table : array[tregisterindex] of string[7] = (
+ {$i ravrstd.inc}
+ );
+
+ regnumber_index : array[tregisterindex] of tregisterindex = (
+ {$i ravrrni.inc}
+ );
+
+ std_regname_index : array[tregisterindex] of tregisterindex = (
+ {$i ravrsri.inc}
+ );
+
+
+ function cgsize2subreg(regtype: tregistertype; s:Tcgsize):Tsubregister;
+ begin
+ cgsize2subreg:=R_SUBWHOLE;
+ end;
+
+
+ function reg_cgsize(const reg: tregister): tcgsize;
+ begin
+ case getregtype(reg) of
+ R_INTREGISTER :
+ reg_cgsize:=OS_8;
+ R_ADDRESSREGISTER :
+ reg_cgsize:=OS_16;
+ else
+ internalerror(2011021905);
+ end;
+ end;
+
+
+ procedure inverse_flags(var f: TResFlags);
+ const
+ inv_flags: array[TResFlags] of TResFlags =
+ (F_NotPossible,F_CS,F_CC,F_NE,F_LT,F_SH,F_GE,
+ F_NE,F_LO,F_VS,F_VC);
+ begin
+ f:=inv_flags[f];
+ end;
+
+
+ function flags_to_cond(const f: TResFlags) : TAsmCond;
+ const
+ flag_2_cond: array[F_CC..F_VS] of TAsmCond =
+ (C_CC,C_CS,C_EQ,C_GE,C_LO,C_LT,
+ C_NE,C_SH,C_VC,C_VS);
+ begin
+ if f=F_NotPossible then
+ internalerror(2011022101);
+ if f>high(flag_2_cond) then
+ internalerror(200112301);
+ result:=flag_2_cond[f];
+ end;
+
+
+ function findreg_by_number(r:Tregister):tregisterindex;
+ begin
+ result:=rgBase.findreg_by_number_table(r,regnumber_index);
+ end;
+
+
+ function std_regnum_search(const s:string):Tregister;
+ begin
+ result:=regnumber_table[findreg_by_name_table(s,std_regname_table,std_regname_index)];
+ end;
+
+
+ function std_regname(r:Tregister):string;
+ var
+ p : tregisterindex;
+ begin
+ p:=findreg_by_number_table(r,regnumber_index);
+ if p<>0 then
+ result:=std_regname_table[p]
+ else
+ result:=generic_regname(r);
+ end;
+
+
+ function inverse_cond(const c: TAsmCond): TAsmCond; {$ifdef USEINLINE}inline;{$endif USEINLINE}
+ const
+ inverse: array[TAsmCond] of TAsmCond=(C_None,
+ C_CS,C_CC,C_NE,C_LT,C_HS,C_HC,C_IE,C_ID,C_SH,C_GE,
+ C_PL,C_EQ,C_MI,C_LO,C_TS,C_TC,C_VS,C_VC);
+ begin
+ result := inverse[c];
+ end;
+
+
+ function conditions_equal(const c1, c2: TAsmCond): boolean; {$ifdef USEINLINE}inline;{$endif USEINLINE}
+ begin
+ result := c1 = c2;
+ end;
+
+
+ function rotl(d : dword;b : byte) : dword;
+ begin
+ result:=(d shr (32-b)) or (d shl b);
+ end;
+
+
+ function dwarf_reg(r:tregister):byte;
+ var
+ reg : shortint;
+ begin
+ reg:=regdwarf_table[findreg_by_number(r)];
+ if reg=-1 then
+ internalerror(200603251);
+ result:=reg;
+ end;
+
+
+ function GetHigh(const r : TRegister) : TRegister;
+ begin
+ result:=TRegister(longint(r)+1)
+ end;
+
+
+ function GetNextReg(const r: TRegister): TRegister;
+ begin
+ result:=TRegister(longint(r)+1);
+ end;
+
+
+ function GetLastReg(const r: TRegister): TRegister;
+ begin
+ result:=TRegister(longint(r)-1);
+ end;
+
+
+ function GetOffsetReg(const r: TRegister;ofs : shortint): TRegister;
+ begin
+ result:=TRegister(longint(r)+ofs);
+ end;
+
+
+ function ReplaceForbiddenChars(const s: string): string;
+ var
+ i : longint;
+ begin
+ Result:=s;
+ for i:=1 to Length(Result) do
+ if Result[i]='$' then
+ Result[i]:='s';
+ end;
+
+end.
diff --git a/closures/compiler/avr/cpuinfo.pas b/closures/compiler/avr/cpuinfo.pas
new file mode 100644
index 0000000000..70c4e70886
--- /dev/null
+++ b/closures/compiler/avr/cpuinfo.pas
@@ -0,0 +1,226 @@
+{
+ Copyright (c) 2008 by the Free Pascal development team
+
+ Basic Processor information for the AVR
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+Unit CPUInfo;
+
+Interface
+
+ uses
+ globtype;
+
+Type
+ bestreal = double;
+ ts32real = single;
+ ts64real = double;
+ ts80real = type extended;
+ ts128real = type extended;
+ ts64comp = comp;
+
+ pbestreal=^bestreal;
+
+ { possible supported processors for this target }
+ tcputype =
+ (cpu_none,
+ cpu_avr1,
+ cpu_avr2,
+ cpu_avr25,
+ cpu_avr3,
+ cpu_avr31,
+ cpu_avr35,
+ cpu_avr4,
+ cpu_avr5,
+ cpu_avr51,
+ cpu_avr6
+ );
+
+ tcpuflags =
+ (AVR_HAS_JMP_CALL,
+ AVR_HAS_MOVW,
+ AVR_HAS_LPMX,
+ AVR_HAS_MUL,
+ AVR_HAS_RAMPZ,
+ AVR_HAS_ELPM,
+ AVR_HAS_ELPMX,
+ AVR_2_BYTE_PC,
+ AVR_3_BYTE_PC
+ );
+
+ tfputype =
+ (fpu_none,
+ fpu_soft,
+ fp_libgcc
+ );
+
+ tcontrollertype =
+ (ct_none,
+
+ ct_atmega16,
+ ct_atmega32,
+ ct_atmega48,
+ ct_atmega64,
+ ct_atmega128
+ );
+
+Const
+ {# Size of native extended floating point type }
+ extended_size = 12;
+ {# Size of a multimedia register }
+ mmreg_size = 16;
+ { target cpu string (used by compiler options) }
+ target_cpu_string = 'avr';
+
+ { calling conventions supported by the code generator }
+ supported_calling_conventions : tproccalloptions = [
+ pocall_internproc,
+ pocall_safecall,
+ pocall_stdcall,
+ { same as stdcall only different name mangling }
+ pocall_cdecl,
+ { same as stdcall only different name mangling }
+ pocall_cppdecl,
+ { same as stdcall but floating point numbers are handled like equal sized integers }
+ pocall_softfloat
+ ];
+
+ cputypestr : array[tcputype] of string[5] = ('',
+ 'AVR1',
+ 'AVR2',
+ 'AVR25',
+ 'AVR3',
+ 'AVR31',
+ 'AVR35',
+ 'AVR4',
+ 'AVR5',
+ 'AVR51',
+ 'AVR6'
+ );
+
+ fputypestr : array[tfputype] of string[6] = (
+ 'NONE',
+ 'SOFT',
+ 'LIBGCC'
+ );
+
+ embedded_controllers : array [tcontrollertype] of tcontrollerdatatype =
+ ((
+ controllertypestr:'';
+ controllerunitstr:'';
+ interruptvectors:0;
+ flashbase:0;
+ flashsize:0;
+ srambase:0;
+ sramsize:0;
+ eeprombase:0;
+ eepromsize:0
+ ),
+ (
+ controllertypestr:'ATMEGA16';
+ controllerunitstr:'ATMEGA16';
+ interruptvectors:0;
+ flashbase:0;
+ flashsize:$4000;
+ srambase:0;
+ sramsize:1024;
+ eeprombase:0;
+ eepromsize:512
+ ),
+ (
+ controllertypestr:'ATMEGA32';
+ controllerunitstr:'ATMEGA32';
+ interruptvectors:0;
+ flashbase:0;
+ flashsize:$8000;
+ srambase:0;
+ sramsize:1024;
+ eeprombase:0;
+ eepromsize:512
+ ),
+ (
+ controllertypestr:'ATMEGA48';
+ controllerunitstr:'ATMEGA48';
+ interruptvectors:0;
+ flashbase:0;
+ flashsize:$1000;
+ srambase:0;
+ sramsize:512;
+ eeprombase:0;
+ eepromsize:256;
+ ),
+ (
+ controllertypestr:'ATMEGA64';
+ controllerunitstr:'ATMEGA64';
+ interruptvectors:0;
+ flashbase:0;
+ flashsize:$10000;
+ srambase:0;
+ sramsize:4096;
+ eeprombase:0;
+ eepromsize:2048;
+ ),
+ (
+ controllertypestr:'ATMEGA128';
+ controllerunitstr:'ATMEGA128';
+ interruptvectors:0;
+ flashbase:0;
+ flashsize:$20000;
+ srambase:0;
+ sramsize:4096;
+ eeprombase:0;
+ eepromsize:4096;
+ )
+ );
+
+ { Supported optimizations, only used for information }
+ supported_optimizerswitches = genericlevel1optimizerswitches+
+ genericlevel2optimizerswitches+
+ genericlevel3optimizerswitches-
+ { no need to write info about those }
+ [cs_opt_level1,cs_opt_level2,cs_opt_level3]+
+ [cs_opt_regvar,cs_opt_loopunroll,cs_opt_tailrecursion,
+ cs_opt_stackframe,cs_opt_nodecse];
+ cpuflagsstr : array[tcpuflags] of string[20] =
+ ('AVR_HAS_JMP_CALL',
+ 'AVR_HAS_MOVW',
+ 'AVR_HAS_LPMX',
+ 'AVR_HAS_MUL',
+ 'AVR_HAS_RAMPZ',
+ 'AVR_HAS_ELPM',
+ 'AVR_HAS_ELPMX',
+ 'AVR_2_BYTE_PC',
+ 'AVR_3_BYTE_PC'
+ );
+
+
+ level1optimizerswitches = genericlevel1optimizerswitches;
+ level2optimizerswitches = genericlevel2optimizerswitches + level1optimizerswitches +
+ [cs_opt_regvar,cs_opt_stackframe,cs_opt_tailrecursion];
+ level3optimizerswitches = genericlevel3optimizerswitches + level2optimizerswitches + [{,cs_opt_loopunroll}];
+
+ cpu_capabilities : array[tcputype] of set of tcpuflags =
+ ( { cpu_none } [],
+ { cpu_avr1 } [],
+ { cpu_avr2 } [],
+ { cpu_avr25 } [],
+ { cpu_avr3 } [],
+ { cpu_avr31 } [],
+ { cpu_avr35 } [],
+ { cpu_avr4 } [],
+ { cpu_avr5 } [],
+ { cpu_avr51 } [],
+ { cpu_avr6 } []
+ );
+
+Implementation
+
+end.
diff --git a/closures/compiler/avr/cpunode.pas b/closures/compiler/avr/cpunode.pas
new file mode 100644
index 0000000000..64090a192b
--- /dev/null
+++ b/closures/compiler/avr/cpunode.pas
@@ -0,0 +1,43 @@
+{
+ Copyright (c) 2000-2008 by Florian Klaempfl
+
+ This unit includes the AVR code generator into the compiler
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit cpunode;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ implementation
+
+ uses
+ { generic nodes }
+ ncgbas,ncgld,ncgflw,ncgcnv,ncgmem,ncgcon,ncgcal,ncgset,ncginl,ncgopt,ncgmat,ncgadd
+ { to be able to only parts of the generic code,
+ the processor specific nodes must be included
+ after the generic one (FK)
+ }
+ ,navradd
+ ,navrmat
+ ,navrcnv
+ ;
+
+
+end.
diff --git a/closures/compiler/avr/cpupara.pas b/closures/compiler/avr/cpupara.pas
new file mode 100644
index 0000000000..d313d24896
--- /dev/null
+++ b/closures/compiler/avr/cpupara.pas
@@ -0,0 +1,527 @@
+{
+ Copyright (c) 2008 by Florian Klaempfl
+
+ AVR specific calling conventions, it follows the GCC AVR calling conventions
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ ****************************************************************************
+}
+{ ARM specific calling conventions are handled by this unit
+}
+unit cpupara;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ globtype,globals,
+ aasmtai,aasmdata,
+ cpuinfo,cpubase,cgbase,cgutils,
+ symconst,symbase,symtype,symdef,parabase,paramgr;
+
+ type
+ tavrparamanager = class(tparamanager)
+ function get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;override;
+ function get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;override;
+ function push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override;
+ function ret_in_param(def : tdef;calloption : tproccalloption) : boolean;override;
+ procedure getintparaloc(calloption : tproccalloption; nr : longint;var cgpara:TCGPara);override;
+ function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override;
+ function create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;override;
+ function get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tcgpara;override;
+ private
+ procedure init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword);
+ function create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras: tparalist;
+ var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword):longint;
+ procedure create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
+ end;
+
+ implementation
+
+ uses
+ verbose,systems,
+ rgobj,
+ defutil,symsym;
+
+
+ function tavrparamanager.get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;
+ begin
+ result:=VOLATILE_INTREGISTERS;
+ end;
+
+
+ function tavrparamanager.get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;
+ begin
+ result:=VOLATILE_FPUREGISTERS;
+ end;
+
+
+ procedure tavrparamanager.getintparaloc(calloption : tproccalloption; nr : longint;var cgpara:TCGPara);
+ var
+ paraloc : pcgparalocation;
+ begin
+ if nr<1 then
+ internalerror(2002070801);
+ cgpara.reset;
+ cgpara.size:=OS_INT;
+ cgpara.intsize:=tcgsize2size[OS_INT];
+ cgpara.alignment:=std_param_align;
+ paraloc:=cgpara.add_location;
+ with paraloc^ do
+ begin
+ size:=OS_INT;
+ { the four first parameters are passed into registers }
+ if nr<=9 then
+ begin
+ loc:=LOC_REGISTER;
+ register:=newreg(R_INTREGISTER,RS_R25-(nr-1)*2,R_SUBWHOLE);
+ end
+ else
+ begin
+ { the other parameters are passed on the stack }
+ loc:=LOC_REFERENCE;
+ reference.index:=NR_STACK_POINTER_REG;
+ reference.offset:=(nr-10)*2;
+ end;
+ end;
+ end;
+
+
+ function getparaloc(calloption : tproccalloption; p : tdef) : tcgloc;
+ begin
+ { Later, the LOC_REFERENCE is in most cases changed into LOC_REGISTER
+ if push_addr_param for the def is true
+ }
+ case p.typ of
+ orddef:
+ getparaloc:=LOC_REGISTER;
+ floatdef:
+ getparaloc:=LOC_REGISTER;
+ enumdef:
+ getparaloc:=LOC_REGISTER;
+ pointerdef:
+ getparaloc:=LOC_REGISTER;
+ formaldef:
+ getparaloc:=LOC_REGISTER;
+ classrefdef:
+ getparaloc:=LOC_REGISTER;
+ recorddef:
+ getparaloc:=LOC_REGISTER;
+ objectdef:
+ getparaloc:=LOC_REGISTER;
+ stringdef:
+ if is_shortstring(p) or is_longstring(p) then
+ getparaloc:=LOC_REFERENCE
+ else
+ getparaloc:=LOC_REGISTER;
+ procvardef:
+ getparaloc:=LOC_REGISTER;
+ filedef:
+ getparaloc:=LOC_REGISTER;
+ arraydef:
+ getparaloc:=LOC_REFERENCE;
+ setdef:
+ if is_smallset(p) then
+ getparaloc:=LOC_REGISTER
+ else
+ getparaloc:=LOC_REFERENCE;
+ variantdef:
+ getparaloc:=LOC_REGISTER;
+ { avoid problems with errornous definitions }
+ errordef:
+ getparaloc:=LOC_REGISTER;
+ else
+ internalerror(2002071001);
+ end;
+ end;
+
+
+ function tavrparamanager.push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;
+ begin
+ result:=false;
+ if varspez in [vs_var,vs_out,vs_constref] then
+ begin
+ result:=true;
+ exit;
+ end;
+ case def.typ of
+ objectdef:
+ result:=is_object(def) and ((varspez=vs_const) or (def.size=0));
+ recorddef:
+ result:=(varspez=vs_const) or (def.size=0);
+ variantdef,
+ formaldef:
+ result:=true;
+ arraydef:
+ result:=(tarraydef(def).highrange>=tarraydef(def).lowrange) or
+ is_open_array(def) or
+ is_array_of_const(def) or
+ is_array_constructor(def);
+ setdef :
+ result:=not is_smallset(def);
+ stringdef :
+ result:=tstringdef(def).stringtype in [st_shortstring,st_longstring];
+ end;
+ end;
+
+
+ function tavrparamanager.ret_in_param(def : tdef;calloption : tproccalloption) : boolean;
+ begin
+ case def.typ of
+ recorddef:
+ { this is how gcc 4.0.4 on linux seems to do it, it doesn't look like being
+ ARM ABI standard compliant
+ }
+ result:=not((trecorddef(def).symtable.SymList.count=1) and
+ not(ret_in_param(tabstractvarsym(trecorddef(def).symtable.SymList[0]).vardef,calloption)));
+ {
+ objectdef
+ arraydef:
+ result:=not(def.size in [1,2,4]);
+ }
+ else
+ result:=inherited ret_in_param(def,calloption);
+ end;
+ end;
+
+
+ procedure tavrparamanager.init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword);
+ begin
+ curintreg:=RS_R25;
+ curfloatreg:=RS_INVALID;
+ curmmreg:=RS_INVALID;
+ cur_stack_offset:=0;
+ end;
+
+
+ { TODO : fix tavrparamanager.create_paraloc_info_intern }
+ function tavrparamanager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras: tparalist;
+ var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword):longint;
+
+ var
+ nextintreg,nextfloatreg,nextmmreg : tsuperregister;
+ paradef : tdef;
+ paraloc : pcgparalocation;
+ stack_offset : aword;
+ hp : tparavarsym;
+ loc : tcgloc;
+ paracgsize : tcgsize;
+ paralen : longint;
+ i : integer;
+
+ procedure assignintreg;
+ begin
+ { In case of po_delphi_nested_cc, the parent frame pointer
+ is always passed on the stack. }
+ if (nextintreg>RS_R8) and
+ (not(vo_is_parentfp in hp.varoptions) or
+ not(po_delphi_nested_cc in p.procoptions)) then
+ begin
+ paraloc^.loc:=LOC_REGISTER;
+ paraloc^.register:=newreg(R_INTREGISTER,nextintreg,R_SUBWHOLE);
+ inc(nextintreg);
+ end
+ else
+ begin
+ paraloc^.loc:=LOC_REFERENCE;
+ paraloc^.reference.index:=NR_STACK_POINTER_REG;
+ paraloc^.reference.offset:=stack_offset;
+ dec(stack_offset,2);
+ end;
+ end;
+
+
+ begin
+ result:=0;
+ nextintreg:=curintreg;
+ nextfloatreg:=curfloatreg;
+ nextmmreg:=curmmreg;
+ stack_offset:=cur_stack_offset;
+
+ for i:=0 to paras.count-1 do
+ begin
+ hp:=tparavarsym(paras[i]);
+ paradef:=hp.vardef;
+
+ hp.paraloc[side].reset;
+
+ { currently only support C-style array of const,
+ there should be no location assigned to the vararg array itself }
+ if (p.proccalloption in [pocall_cdecl,pocall_cppdecl]) and
+ is_array_of_const(paradef) then
+ begin
+ paraloc:=hp.paraloc[side].add_location;
+ { hack: the paraloc must be valid, but is not actually used }
+ paraloc^.loc:=LOC_REGISTER;
+ paraloc^.register:=NR_R25;
+ paraloc^.size:=OS_ADDR;
+ break;
+ end;
+
+ if (hp.varspez in [vs_var,vs_out]) or
+ push_addr_param(hp.varspez,paradef,p.proccalloption) or
+ is_open_array(paradef) or
+ is_array_of_const(paradef) then
+ begin
+ paradef:=voidpointertype;
+ loc:=LOC_REGISTER;
+ paracgsize := OS_ADDR;
+ paralen := tcgsize2size[OS_ADDR];
+ end
+ else
+ begin
+ if not is_special_array(paradef) then
+ paralen := paradef.size
+ else
+ paralen := tcgsize2size[def_cgsize(paradef)];
+ loc := getparaloc(p.proccalloption,paradef);
+ if (paradef.typ in [objectdef,arraydef,recorddef]) and
+ not is_special_array(paradef) and
+ (hp.varspez in [vs_value,vs_const]) then
+ paracgsize := int_cgsize(paralen)
+ else
+ begin
+ paracgsize:=def_cgsize(paradef);
+ { for things like formaldef }
+ if (paracgsize=OS_NO) then
+ begin
+ paracgsize:=OS_ADDR;
+ paralen := tcgsize2size[OS_ADDR];
+ end;
+ end
+ end;
+
+ hp.paraloc[side].size:=paracgsize;
+ hp.paraloc[side].Alignment:=std_param_align;
+ hp.paraloc[side].intsize:=paralen;
+
+{$ifdef EXTDEBUG}
+ if paralen=0 then
+ internalerror(200410311);
+{$endif EXTDEBUG}
+ while paralen>0 do
+ begin
+ paraloc:=hp.paraloc[side].add_location;
+
+ if (loc=LOC_REGISTER) and (paracgsize in [OS_F32,OS_F64,OS_F80]) then
+ case paracgsize of
+ OS_F32:
+ paraloc^.size:=OS_32;
+ OS_F64:
+ paraloc^.size:=OS_32;
+ else
+ internalerror(2005082901);
+ end
+ else if (paracgsize in [OS_NO,OS_64,OS_S64]) then
+ paraloc^.size := OS_32
+ else
+ paraloc^.size:=paracgsize;
+ case loc of
+ LOC_REGISTER:
+ begin
+ { this is not abi compliant
+ why? (FK) }
+ if nextintreg>=RS_R8 then
+ begin
+ paraloc^.loc:=LOC_REGISTER;
+ paraloc^.register:=newreg(R_INTREGISTER,nextintreg,R_SUBWHOLE);
+ dec(nextintreg);
+ end
+ else
+ begin
+ { LOC_REFERENCE covers always the overleft }
+ paraloc^.loc:=LOC_REFERENCE;
+ paraloc^.size:=int_cgsize(paralen);
+ if (side=callerside) then
+ paraloc^.reference.index:=NR_STACK_POINTER_REG;
+ paraloc^.reference.offset:=stack_offset;
+ inc(stack_offset,align(paralen,4));
+ paralen:=0;
+ end;
+ end;
+ LOC_REFERENCE:
+ begin
+ paraloc^.size:=OS_ADDR;
+ if push_addr_param(hp.varspez,paradef,p.proccalloption) or
+ is_open_array(paradef) or
+ is_array_of_const(paradef) then
+ assignintreg
+ else
+ begin
+ paraloc^.loc:=LOC_REFERENCE;
+ paraloc^.reference.index:=NR_STACK_POINTER_REG;
+ paraloc^.reference.offset:=stack_offset;
+ inc(stack_offset,hp.vardef.size);
+ end;
+ end;
+ else
+ internalerror(2002071002);
+ end;
+ if side=calleeside then
+ begin
+ if paraloc^.loc=LOC_REFERENCE then
+ begin
+ paraloc^.reference.index:=NR_FRAME_POINTER_REG;
+ inc(paraloc^.reference.offset,2);
+ end;
+ end;
+ dec(paralen,tcgsize2size[paraloc^.size]);
+ end;
+ end;
+ curintreg:=nextintreg;
+ curfloatreg:=nextfloatreg;
+ curmmreg:=nextmmreg;
+ cur_stack_offset:=stack_offset;
+ result:=cur_stack_offset;
+ end;
+
+
+ function tavrparamanager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;
+ var
+ cur_stack_offset: aword;
+ curintreg, curfloatreg, curmmreg: tsuperregister;
+ retcgsize : tcgsize;
+ begin
+ init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset);
+
+ result:=create_paraloc_info_intern(p,side,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset);
+
+ create_funcretloc_info(p,side);
+ end;
+
+
+ procedure tavrparamanager.create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
+ begin
+ p.funcretloc[side]:=get_funcretloc(p,side,p.returndef);
+ end;
+
+
+ { TODO : fix tavrparamanager.get_funcretloc }
+ function tavrparamanager.get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tcgpara;
+ var
+ retcgsize : tcgsize;
+ paraloc : pcgparalocation;
+ begin
+ result.init;
+ result.alignment:=get_para_align(p.proccalloption);
+ { void has no location }
+ if is_void(def) then
+ begin
+ paraloc:=result.add_location;
+ result.size:=OS_NO;
+ result.intsize:=0;
+ paraloc^.size:=OS_NO;
+ paraloc^.loc:=LOC_VOID;
+ exit;
+ end;
+ { Constructors return self instead of a boolean }
+ if (p.proctypeoption=potype_constructor) then
+ begin
+ retcgsize:=OS_ADDR;
+ result.intsize:=sizeof(pint);
+ end
+ else
+ begin
+ retcgsize:=def_cgsize(def);
+ result.intsize:=def.size;
+ end;
+ result.size:=retcgsize;
+ { Return is passed as var parameter }
+ if ret_in_param(def,p.proccalloption) then
+ begin
+ paraloc:=result.add_location;
+ paraloc^.loc:=LOC_REFERENCE;
+ paraloc^.size:=retcgsize;
+ exit;
+ end;
+
+ paraloc:=result.add_location;
+ { Return in FPU register? }
+ if def.typ=floatdef then
+ begin
+ if (p.proccalloption in [pocall_softfloat]) or (cs_fp_emulation in current_settings.moduleswitches) then
+ begin
+ case retcgsize of
+ OS_64,
+ OS_F64:
+ begin
+ paraloc^.loc:=LOC_REGISTER;
+ paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG;
+ paraloc^.size:=OS_32;
+ paraloc:=result.add_location;
+ paraloc^.loc:=LOC_REGISTER;
+ paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG;
+ paraloc^.size:=OS_32;
+ end;
+ OS_32,
+ OS_F32:
+ begin
+ paraloc^.loc:=LOC_REGISTER;
+ paraloc^.register:=NR_FUNCTION_RETURN_REG;
+ paraloc^.size:=OS_32;
+ end;
+ else
+ internalerror(2005082603);
+ end;
+ end
+ else
+ begin
+ paraloc^.loc:=LOC_FPUREGISTER;
+ paraloc^.register:=NR_FPU_RESULT_REG;
+ paraloc^.size:=retcgsize;
+ end;
+ end
+ { Return in register }
+ else
+ begin
+ if retcgsize in [OS_64,OS_S64] then
+ begin
+ paraloc^.loc:=LOC_REGISTER;
+ paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG;
+ paraloc^.size:=OS_32;
+ paraloc:=result.add_location;
+ paraloc^.loc:=LOC_REGISTER;
+ paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG;
+ paraloc^.size:=OS_32;
+ end
+ else
+ begin
+ paraloc^.loc:=LOC_REGISTER;
+ paraloc^.register:=NR_FUNCTION_RETURN_REG;
+ paraloc^.size:=OS_32;
+ end;
+ end;
+ end;
+
+
+ function tavrparamanager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;
+ var
+ cur_stack_offset: aword;
+ curintreg, curfloatreg, curmmreg: tsuperregister;
+ begin
+ init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset);
+
+ result:=create_paraloc_info_intern(p,callerside,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset);
+ if (p.proccalloption in [pocall_cdecl,pocall_cppdecl]) then
+ { just continue loading the parameters in the registers }
+ result:=create_paraloc_info_intern(p,callerside,varargspara,curintreg,curfloatreg,curmmreg,cur_stack_offset)
+ else
+ internalerror(200410231);
+ end;
+
+begin
+ paramanager:=tavrparamanager.create;
+end.
diff --git a/closures/compiler/avr/cpupi.pas b/closures/compiler/avr/cpupi.pas
new file mode 100644
index 0000000000..676fb27541
--- /dev/null
+++ b/closures/compiler/avr/cpupi.pas
@@ -0,0 +1,73 @@
+{
+ Copyright (c) 2008 by Florian Klaempfl
+
+ This unit contains the CPU specific part of tprocinfo
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+
+{ This unit contains the CPU specific part of tprocinfo. }
+unit cpupi;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ globtype,cutils,
+ procinfo,cpuinfo,psub;
+
+ type
+ tavrprocinfo = class(tcgprocinfo)
+ // procedure handle_body_start;override;
+ // procedure after_pass1;override;
+ procedure set_first_temp_offset;override;
+ function calc_stackframe_size:longint;override;
+ end;
+
+
+ implementation
+
+ uses
+ globals,systems,
+ cpubase,
+ aasmtai,aasmdata,
+ tgobj,
+ symconst,symsym,paramgr,
+ cgbase,
+ cgobj;
+
+ procedure tavrprocinfo.set_first_temp_offset;
+ begin
+ if tg.direction = -1 then
+ tg.setfirsttemp(0)
+ else
+ tg.setfirsttemp(maxpushedparasize);
+ end;
+
+
+ function tavrprocinfo.calc_stackframe_size:longint;
+ begin
+ maxpushedparasize:=align(maxpushedparasize,max(current_settings.alignment.localalignmin,4));
+ result:=0;
+ end;
+
+
+begin
+ cprocinfo:=tavrprocinfo;
+end.
+
diff --git a/closures/compiler/avr/cputarg.pas b/closures/compiler/avr/cputarg.pas
new file mode 100644
index 0000000000..db2b0e6726
--- /dev/null
+++ b/closures/compiler/avr/cputarg.pas
@@ -0,0 +1,70 @@
+{
+ Copyright (c) 2001-2008 by Peter Vreman
+
+ Includes the AVR dependent target units
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit cputarg;
+
+{$i fpcdefs.inc}
+
+interface
+
+
+implementation
+
+ uses
+ systems { prevent a syntax error when nothing is included }
+
+{**************************************
+ Targets
+**************************************}
+
+ {$ifndef NOTARGETEMBEDDED}
+ ,t_embed
+ {$endif}
+
+{**************************************
+ Assemblers
+**************************************}
+
+ {$ifndef NOAGARMGAS}
+ ,agavrgas
+ {$endif}
+
+{**************************************
+ Assembler Readers
+**************************************}
+
+ {$ifndef NoRaarmgas}
+ ,raavrgas
+ {$endif NoRaarmgas}
+
+{**************************************
+ Debuginfo
+**************************************}
+
+ {$ifndef NoDbgStabs}
+ ,dbgstabs
+ {$endif NoDbgStabs}
+ {$ifndef NoDbgDwarf}
+ ,dbgdwarf
+ {$endif NoDbgDwarf}
+ ;
+
+end.
diff --git a/closures/compiler/avr/itcpugas.pas b/closures/compiler/avr/itcpugas.pas
new file mode 100644
index 0000000000..6af73515c7
--- /dev/null
+++ b/closures/compiler/avr/itcpugas.pas
@@ -0,0 +1,101 @@
+{
+ Copyright (c) 2008 by Florian Klaempfl
+
+ This unit contains the AVR GAS instruction tables
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit itcpugas;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cpubase,cgbase;
+
+
+ const
+ { Standard opcode string table (for each tasmop enumeration). The
+ opcode strings should conform to the names as defined by the
+ processor manufacturer.
+ }
+ gas_op2str : op2strtable = ('',
+ 'add','adc','adiw','sub','subi','sbc','sbci','sbrc','sbrs','clc','sec','sbiw','and','andi',
+ 'or','ori','eor','com','neg','sbr','cbr','inc','dec','tst','clr',
+ 'ser','mul','muls','fmul','fmuls','fmulsu','rjmp','ijmp',
+ 'eijmp','jmp','rcall','icall','eicall','call','ret','reti','cpse',
+ 'cp','cpc','cpi','sbic','sbis','br','mov','movw','ldi','lds','ld','ldd',
+ 'sts','st','std','lpm','elpm','spm','in','out','push','pop',
+ 'lsl','lsr','rol','ror','asr','swap','bset','bclr','sbi','cbi',
+ 'bst','bld','s','cli','brak','nop','sleep','wdr');
+
+ function gas_regnum_search(const s:string):Tregister;
+ function gas_regname(r:Tregister):string;
+
+
+implementation
+
+ uses
+ cutils,verbose;
+
+ const
+ gas_regname_table : array[tregisterindex] of string[7] = (
+ {$i ravrstd.inc}
+ );
+
+ gas_regname_index : array[tregisterindex] of tregisterindex = (
+ {$i ravrsri.inc}
+ );
+
+ function findreg_by_gasname(const s:string):tregisterindex;
+ var
+ i,p : tregisterindex;
+ begin
+ {Binary search.}
+ p:=0;
+ i:=regnumber_count_bsstart;
+ repeat
+ if (p+i<=high(tregisterindex)) and (gas_regname_table[gas_regname_index[p+i]]<=s) then
+ p:=p+i;
+ i:=i shr 1;
+ until i=0;
+ if gas_regname_table[gas_regname_index[p]]=s then
+ findreg_by_gasname:=gas_regname_index[p]
+ else
+ findreg_by_gasname:=0;
+ end;
+
+
+ function gas_regnum_search(const s:string):Tregister;
+ begin
+ result:=regnumber_table[findreg_by_gasname(s)];
+ end;
+
+
+ function gas_regname(r:Tregister):string;
+ var
+ p : tregisterindex;
+ begin
+ p:=findreg_by_number(r);
+ if p<>0 then
+ result:=gas_regname_table[p]
+ else
+ result:=generic_regname(r);
+ end;
+
+end.
diff --git a/closures/compiler/avr/navradd.pas b/closures/compiler/avr/navradd.pas
new file mode 100644
index 0000000000..aefa78955b
--- /dev/null
+++ b/closures/compiler/avr/navradd.pas
@@ -0,0 +1,251 @@
+{
+ Copyright (c) 2008 by Florian Klaempfl
+
+ Code generation for add nodes on the AVR
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit navradd;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,ncgadd,cpubase;
+
+ type
+ tavraddnode = class(tcgaddnode)
+ private
+ function GetResFlags(unsigned:Boolean):TResFlags;
+ protected
+ function pass_1 : tnode;override;
+ procedure second_cmpordinal;override;
+ procedure second_cmpsmallset;override;
+ procedure second_cmp64bit;override;
+ procedure second_cmp;
+ end;
+
+ implementation
+
+ uses
+ globtype,systems,
+ cutils,verbose,globals,
+ symconst,symdef,paramgr,
+ aasmbase,aasmtai,aasmdata,aasmcpu,defutil,htypechk,
+ cgbase,cgutils,cgcpu,
+ cpuinfo,pass_1,pass_2,regvars,procinfo,
+ cpupara,
+ ncon,nset,nadd,
+ ncgutil,tgobj,rgobj,rgcpu,cgobj,cg64f32;
+
+{*****************************************************************************
+ TSparcAddNode
+*****************************************************************************}
+
+ function tavraddnode.GetResFlags(unsigned:Boolean):TResFlags;
+ begin
+ case NodeType of
+ equaln:
+ GetResFlags:=F_EQ;
+ unequaln:
+ GetResFlags:=F_NE;
+ else
+ if not(unsigned) then
+ begin
+ if nf_swapped in flags then
+ case NodeType of
+ ltn:
+ GetResFlags:=F_NotPossible;
+ lten:
+ GetResFlags:=F_GE;
+ gtn:
+ GetResFlags:=F_LT;
+ gten:
+ GetResFlags:=F_NotPossible;
+ end
+ else
+ case NodeType of
+ ltn:
+ GetResFlags:=F_LT;
+ lten:
+ GetResFlags:=F_NotPossible;
+ gtn:
+ GetResFlags:=F_NotPossible;
+ gten:
+ GetResFlags:=F_GE;
+ end;
+ end
+ else
+ begin
+ if nf_swapped in Flags then
+ case NodeType of
+ ltn:
+ GetResFlags:=F_NotPossible;
+ lten:
+ GetResFlags:=F_CS;
+ gtn:
+ GetResFlags:=F_CC;
+ gten:
+ GetResFlags:=F_NotPossible;
+ end
+ else
+ case NodeType of
+ ltn:
+ GetResFlags:=F_CC;
+ lten:
+ GetResFlags:=F_NotPossible;
+ gtn:
+ GetResFlags:=F_NotPossible;
+ gten:
+ GetResFlags:=F_CS;
+ end;
+ end;
+ end;
+ end;
+
+
+ procedure tavraddnode.second_cmpsmallset;
+
+ procedure gencmp(tmpreg1,tmpreg2 : tregister);
+ var
+ i : byte;
+ begin
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CP,tmpreg1,tmpreg2));
+ for i:=2 to tcgsize2size[left.location.size] do
+ begin
+ tmpreg1:=GetNextReg(tmpreg1);
+ tmpreg2:=GetNextReg(tmpreg2);
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CPC,tmpreg1,tmpreg2));
+ end;
+ end;
+
+ var
+ tmpreg : tregister;
+ begin
+ pass_left_right;
+ location_reset(location,LOC_FLAGS,OS_NO);
+ force_reg_left_right(false,false);
+
+ case nodetype of
+ equaln:
+ begin
+ gencmp(left.location.register,right.location.register);
+ location.resflags:=F_EQ;
+ end;
+ unequaln:
+ begin
+ gencmp(left.location.register,right.location.register);
+ location.resflags:=F_NE;
+ end;
+ lten,
+ gten:
+ begin
+ if (not(nf_swapped in flags) and
+ (nodetype = lten)) or
+ ((nf_swapped in flags) and
+ (nodetype = gten)) then
+ swapleftright;
+ tmpreg:=cg.getintregister(current_asmdata.CurrAsmList,location.size);
+ cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,OP_AND,location.size,
+ left.location.register,right.location.register,tmpreg);
+ gencmp(tmpreg,right.location.register);
+ location.resflags:=F_EQ;
+ end;
+ else
+ internalerror(2004012401);
+ end;
+ end;
+
+
+ procedure tavraddnode.second_cmp;
+ var
+ unsigned : boolean;
+ tmpreg1,tmpreg2 : tregister;
+ i : longint;
+ begin
+ pass_left_right;
+ force_reg_left_right(true,false);
+
+ unsigned:=not(is_signed(left.resultdef)) or
+ not(is_signed(right.resultdef));
+
+ if getresflags(unsigned)=F_NotPossible then
+ swapleftright;
+
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CP,left.location.register,right.location.register));
+ tmpreg1:=left.location.register;
+ tmpreg2:=right.location.register;
+
+ for i:=2 to tcgsize2size[left.location.size] do
+ begin
+ tmpreg1:=GetNextReg(tmpreg1);
+ tmpreg2:=GetNextReg(tmpreg2);
+ if i=5 then
+ begin
+ tmpreg1:=left.location.registerhi;
+ tmpreg2:=right.location.registerhi;
+ end;
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CPC,tmpreg1,tmpreg2));
+ end;
+
+ location_reset(location,LOC_FLAGS,OS_NO);
+ location.resflags:=getresflags(unsigned);
+ end;
+
+
+ procedure tavraddnode.second_cmp64bit;
+ begin
+ second_cmp;
+ end;
+
+
+ function tavraddnode.pass_1 : tnode;
+ begin
+ result:=inherited pass_1;
+{
+ if not(assigned(result)) then
+ begin
+ unsigned:=not(is_signed(left.resultdef)) or
+ not(is_signed(right.resultdef));
+
+ if is_64bit(left.resultdef) and
+ ((nodetype in [equaln,unequaln]) or
+ (unsigned and (nodetype in [ltn,lten,gtn,gten]))
+ ) then
+ expectloc:=LOC_FLAGS;
+ end;
+ { handling boolean expressions }
+ if not(assigned(result)) and
+ (
+ not(is_boolean(left.resultdef)) or
+ not(is_boolean(right.resultdef)) or
+ is_dynamic_array(left.resultdef)
+ ) then
+ expectloc:=LOC_FLAGS;
+}
+ end;
+
+
+ procedure tavraddnode.second_cmpordinal;
+ begin
+ second_cmp;
+ end;
+
+begin
+ caddnode:=tavraddnode;
+end.
diff --git a/closures/compiler/avr/navrcnv.pas b/closures/compiler/avr/navrcnv.pas
new file mode 100644
index 0000000000..4afaf6bc95
--- /dev/null
+++ b/closures/compiler/avr/navrcnv.pas
@@ -0,0 +1,59 @@
+{
+ Copyright (c) 1998-2009 by Florian Klaempfl
+
+ Generate AVR assembler for type converting nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit navrcnv;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,ncnv,ncgcnv,defcmp;
+
+ type
+ tarmtypeconvnode = class(tcgtypeconvnode)
+ protected
+ { procedure second_int_to_int;override; }
+ { procedure second_string_to_string;override; }
+ { procedure second_cstring_to_pchar;override; }
+ { procedure second_string_to_chararray;override; }
+ { procedure second_array_to_pointer;override; }
+ { procedure second_pointer_to_array;override; }
+ { procedure second_chararray_to_string;override; }
+ { procedure second_char_to_string;override; }
+ { procedure second_int_to_real;override; }
+ { procedure second_real_to_real;override; }
+ { procedure second_cord_to_pointer;override; }
+ { procedure second_proc_to_procvar;override; }
+ { procedure second_bool_to_int;override; }
+ { procedure second_int_to_bool;override; }
+ { procedure second_load_smallset;override; }
+ { procedure second_ansistring_to_pchar;override; }
+ { procedure second_pchar_to_string;override; }
+ { procedure second_class_to_intf;override; }
+ { procedure second_char_to_char;override; }
+ end;
+
+implementation
+
+begin
+ ctypeconvnode:=tarmtypeconvnode;
+end.
diff --git a/closures/compiler/avr/navrmat.pas b/closures/compiler/avr/navrmat.pas
new file mode 100644
index 0000000000..d4482a62e4
--- /dev/null
+++ b/closures/compiler/avr/navrmat.pas
@@ -0,0 +1,265 @@
+{
+ Copyright (c) 1998-2008 by Florian Klaempfl
+
+ Generates AVR assembler for math nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit navrmat;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,nmat,ncgmat;
+
+ type
+ tavrmoddivnode = class(tmoddivnode)
+ function first_moddivint: tnode;override;
+ procedure pass_generate_code;override;
+ end;
+
+ tavrnotnode = class(tcgnotnode)
+ procedure second_boolean;override;
+ end;
+
+implementation
+
+ uses
+ globtype,systems,
+ cutils,verbose,globals,constexp,
+ aasmbase,aasmcpu,aasmtai,aasmdata,
+ defutil,
+ cgbase,cgobj,cgutils,
+ pass_2,procinfo,
+ ncon,
+ cpubase,
+ ncgutil,cgcpu;
+
+{*****************************************************************************
+ TAVRMODDIVNODE
+*****************************************************************************}
+
+ function tavrmoddivnode.first_moddivint: tnode;
+ var
+ power : longint;
+ begin
+ if (right.nodetype=ordconstn) and
+ (nodetype=divn) and
+ (ispowerof2(tordconstnode(right).value,power) or
+ (tordconstnode(right).value=1) or
+ (tordconstnode(right).value=int64(-1))
+ ) and
+ not(is_64bitint(resultdef)) then
+ result:=nil
+ else
+ result:=inherited first_moddivint;
+ end;
+
+
+ procedure tavrmoddivnode.pass_generate_code;
+ var
+ power : longint;
+ numerator,
+ helper1,
+ helper2,
+ resultreg : tregister;
+ size : Tcgsize;
+ procedure genOrdConstNodeDiv;
+ begin
+{
+ if tordconstnode(right).value=0 then
+ internalerror(2005061701)
+ else if tordconstnode(right).value=1 then
+ cg.a_load_reg_reg(current_asmdata.CurrAsmList, OS_INT, OS_INT, numerator, resultreg)
+ else if (tordconstnode(right).value = int64(-1)) then
+ begin
+ // note: only in the signed case possible..., may overflow
+ current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_MVN,
+ resultreg,numerator),toppostfix(ord(cs_check_overflow in current_settings.localswitches)*ord(PF_S))));
+ end
+ else if ispowerof2(tordconstnode(right).value,power) then
+ begin
+ if (is_signed(right.resultdef)) then
+ begin
+ helper1:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+ helper2:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+ shifterop_reset(so);
+ so.shiftmode:=SM_ASR;
+ so.shiftimm:=31;
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_shifterop(A_MOV,helper1,numerator,so));
+ shifterop_reset(so);
+ so.shiftmode:=SM_LSR;
+ so.shiftimm:=32-power;
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg_shifterop(A_ADD,helper2,numerator,helper1,so));
+ shifterop_reset(so);
+ so.shiftmode:=SM_ASR;
+ so.shiftimm:=power;
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_shifterop(A_MOV,resultreg,helper2,so));
+ end
+ else
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SHR,OS_INT,power,numerator,resultreg)
+ end;
+}
+ end;
+
+
+ procedure genOrdConstNodeMod;
+ var
+ modreg, maskreg, tempreg : tregister;
+ begin
+{
+ if (tordconstnode(right).value = 0) then begin
+ internalerror(2005061702);
+ end
+ else if (abs(tordconstnode(right).value.svalue) = 1) then
+ begin
+ // x mod +/-1 is always zero
+ cg.a_load_const_reg(current_asmdata.CurrAsmList, OS_INT, 0, resultreg);
+ end
+ else if (ispowerof2(tordconstnode(right).value, power)) then
+ begin
+ if (is_signed(right.resultdef)) then begin
+
+ tempreg := cg.getintregister(current_asmdata.CurrAsmList, OS_INT);
+ maskreg := cg.getintregister(current_asmdata.CurrAsmList, OS_INT);
+ modreg := cg.getintregister(current_asmdata.CurrAsmList, OS_INT);
+
+ cg.a_load_const_reg(current_asmdata.CurrAsmList, OS_INT, abs(tordconstnode(right).value.svalue)-1, modreg);
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_SAR, OS_INT, 31, numerator, maskreg);
+ cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList, OP_AND, OS_INT, numerator, modreg, tempreg);
+
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_ANDC, maskreg, maskreg, modreg));
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_const(A_SUBFIC, modreg, tempreg, 0));
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SUBFE, modreg, modreg, modreg));
+ cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList, OP_AND, OS_INT, modreg, maskreg, maskreg);
+ cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList, OP_OR, OS_INT, maskreg, tempreg, resultreg);
+ end else begin
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_AND, OS_INT, tordconstnode(right).value.svalue-1, numerator, resultreg);
+ end;
+ end else begin
+ genOrdConstNodeDiv();
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_MUL, OS_INT, tordconstnode(right).value.svalue, resultreg, resultreg);
+ cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList, OP_SUB, OS_INT, resultreg, numerator, resultreg);
+ end;
+}
+ end;
+
+ begin
+ secondpass(left);
+ secondpass(right);
+ location_copy(location,left.location);
+
+{
+ { put numerator in register }
+ size:=def_cgsize(left.resultdef);
+ location_force_reg(current_asmdata.CurrAsmList,left.location,
+ size,true);
+ location_copy(location,left.location);
+ numerator:=location.register;
+ resultreg:=location.register;
+ if location.loc=LOC_CREGISTER then
+ begin
+ location.loc := LOC_REGISTER;
+ location.register := cg.getintregister(current_asmdata.CurrAsmList,size);
+ resultreg:=location.register;
+ end
+ else if (nodetype=modn) or (right.nodetype=ordconstn) then
+ begin
+ // for a modulus op, and for const nodes we need the result register
+ // to be an extra register
+ resultreg:=cg.getintregister(current_asmdata.CurrAsmList,size);
+ end;
+
+ if right.nodetype=ordconstn then
+ begin
+ if nodetype=divn then
+ genOrdConstNodeDiv
+ else
+ genOrdConstNodeMod;
+ end;
+
+ location.register:=resultreg;
+
+ { unsigned division/module can only overflow in case of division by zero }
+ { (but checking this overflow flag is more convoluted than performing a }
+ { simple comparison with 0) }
+ if is_signed(right.resultdef) then
+ cg.g_overflowcheck(current_asmdata.CurrAsmList,location,resultdef);
+}
+ end;
+
+{*****************************************************************************
+ TAVRNOTNODE
+*****************************************************************************}
+
+ procedure tavrnotnode.second_boolean;
+ var
+ hl : tasmlabel;
+ tmpreg : tregister;
+ i : longint;
+ begin
+ { if the location is LOC_JUMP, we do the secondpass after the
+ labels are allocated
+ }
+ if left.expectloc=LOC_JUMP then
+ begin
+ hl:=current_procinfo.CurrTrueLabel;
+ current_procinfo.CurrTrueLabel:=current_procinfo.CurrFalseLabel;
+ current_procinfo.CurrFalseLabel:=hl;
+ secondpass(left);
+ maketojumpbool(current_asmdata.CurrAsmList,left,lr_load_regvars);
+ hl:=current_procinfo.CurrTrueLabel;
+ current_procinfo.CurrTrueLabel:=current_procinfo.CurrFalseLabel;
+ current_procinfo.CurrFalseLabel:=hl;
+ location.loc:=LOC_JUMP;
+ end
+ else
+ begin
+ secondpass(left);
+ case left.location.loc of
+ LOC_FLAGS :
+ begin
+ location_copy(location,left.location);
+ inverse_flags(location.resflags);
+ end;
+ LOC_REGISTER,LOC_CREGISTER,LOC_REFERENCE,LOC_CREFERENCE,
+ LOC_SUBSETREG,LOC_CSUBSETREG,LOC_SUBSETREF,LOC_CSUBSETREF :
+ begin
+ location_force_reg(current_asmdata.CurrAsmList,left.location,def_cgsize(left.resultdef),true);
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_CPI,left.location.register,0));
+ tmpreg:=left.location.register;
+
+ { avr has no cpci, so we use the first register as "zero" register }
+ for i:=2 to tcgsize2size[left.location.size] do
+ begin
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CPC,tmpreg,left.location.register));
+ end;
+ location_reset(location,LOC_FLAGS,OS_NO);
+ location.resflags:=F_EQ;
+ end;
+ else
+ internalerror(2003042401);
+ end;
+ end;
+ end;
+
+begin
+ cmoddivnode:=tavrmoddivnode;
+ cnotnode:=tavrnotnode;
+end.
diff --git a/closures/compiler/avr/raavr.pas b/closures/compiler/avr/raavr.pas
new file mode 100644
index 0000000000..b837b02bef
--- /dev/null
+++ b/closures/compiler/avr/raavr.pas
@@ -0,0 +1,52 @@
+{
+ Copyright (c) 1998-2003 by Carl Eric Codere and Peter Vreman
+
+ Handles the common arm assembler reader routines
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit raavr;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ cpubase,
+ aasmtai,aasmdata,
+ rautils;
+
+ type
+ TAVROperand=class(TOperand)
+ end;
+
+ TAVRInstruction=class(TInstruction)
+ function ConcatInstruction(p:TAsmList) : tai;override;
+ end;
+
+ implementation
+
+ uses
+ aasmcpu;
+
+ function TAVRInstruction.ConcatInstruction(p:TAsmList) : tai;
+ begin
+ result:=inherited ConcatInstruction(p);
+ end;
+
+
+end.
diff --git a/closures/compiler/avr/raavrgas.pas b/closures/compiler/avr/raavrgas.pas
new file mode 100644
index 0000000000..3cefacaedf
--- /dev/null
+++ b/closures/compiler/avr/raavrgas.pas
@@ -0,0 +1,693 @@
+{
+ Copyright (c) 1998-2008 by Carl Eric Codere and Peter Vreman
+
+ Does the parsing for the ARM GNU AS styled inline assembler.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+Unit raavrgas;
+
+{$i fpcdefs.inc}
+
+ Interface
+
+ uses
+ raatt,raavr,
+ cpubase;
+
+ type
+ tavrattreader = class(tattreader)
+ function is_asmopcode(const s: string):boolean;override;
+ function is_register(const s:string):boolean;override;
+ procedure handleopcode;override;
+ procedure BuildReference(oper : tavroperand);
+ procedure BuildOperand(oper : tavroperand);
+ procedure BuildOpCode(instr : tavrinstruction);
+ procedure ReadSym(oper : tavroperand);
+ procedure ConvertCalljmp(instr : tavrinstruction);
+ end;
+
+
+ Implementation
+
+ uses
+ { helpers }
+ cutils,
+ { global }
+ globtype,globals,verbose,
+ systems,
+ { aasm }
+ cpuinfo,aasmbase,aasmtai,aasmdata,aasmcpu,
+ { symtable }
+ symconst,symbase,symtype,symsym,symtable,
+ { parser }
+ scanner,
+ procinfo,
+ itcpugas,
+ rabase,rautils,
+ cgbase,cgobj
+ ;
+
+
+ function tavrattreader.is_register(const s:string):boolean;
+ type
+ treg2str = record
+ name : string[2];
+ reg : tregister;
+ end;
+{
+ const
+ extraregs : array[0..19] of treg2str = (
+ (name: 'X'; reg : NR_Z),
+ (name: 'Y'; reg : NR_R1),
+ (name: 'Z'; reg : NR_R2),
+ );
+}
+ var
+ i : longint;
+
+ begin
+ result:=inherited is_register(s);
+ { reg found?
+ possible aliases are always 2 char
+ }
+ if result or (length(s)<>2) then
+ exit;
+{
+ for i:=low(extraregs) to high(extraregs) do
+ begin
+ if s=extraregs[i].name then
+ begin
+ actasmregister:=extraregs[i].reg;
+ result:=true;
+ actasmtoken:=AS_REGISTER;
+ exit;
+ end;
+ end;
+}
+ end;
+
+
+ procedure tavrattreader.ReadSym(oper : tavroperand);
+ var
+ tempstr, mangledname : string;
+ typesize,l,k : aint;
+ begin
+ tempstr:=actasmpattern;
+ Consume(AS_ID);
+ { typecasting? }
+ if (actasmtoken=AS_LPAREN) and
+ SearchType(tempstr,typesize) then
+ begin
+ oper.hastype:=true;
+ Consume(AS_LPAREN);
+ BuildOperand(oper);
+ Consume(AS_RPAREN);
+ if oper.opr.typ in [OPR_REFERENCE,OPR_LOCAL] then
+ oper.SetSize(typesize,true);
+ end
+ else
+ if not oper.SetupVar(tempstr,false) then
+ Message1(sym_e_unknown_id,tempstr);
+ { record.field ? }
+ if actasmtoken=AS_DOT then
+ begin
+ BuildRecordOffsetSize(tempstr,l,k,mangledname,false);
+ if (mangledname<>'') then
+ Message(asmr_e_invalid_reference_syntax);
+ inc(oper.opr.ref.offset,l);
+ end;
+ end;
+
+
+ Procedure tavrattreader.BuildReference(oper : tavroperand);
+
+ procedure Consume_RParen;
+ begin
+ if actasmtoken<>AS_RPAREN then
+ Begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(true);
+ end
+ else
+ begin
+ Consume(AS_RPAREN);
+ if not (actasmtoken in [AS_COMMA,AS_SEPARATOR,AS_END]) then
+ Begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(true);
+ end;
+ end;
+ end;
+
+
+ procedure read_index;
+ begin
+ Consume(AS_COMMA);
+ if actasmtoken=AS_REGISTER then
+ Begin
+ oper.opr.ref.index:=actasmregister;
+ Consume(AS_REGISTER);
+ end
+ else if actasmtoken=AS_HASH then
+ begin
+ Consume(AS_HASH);
+ inc(oper.opr.ref.offset,BuildConstExpression(false,true));
+ end;
+ end;
+
+
+ begin
+ Consume(AS_LPAREN);
+ if actasmtoken=AS_REGISTER then
+ begin
+ oper.opr.ref.base:=actasmregister;
+ Consume(AS_REGISTER);
+ { can either be a register or a right parenthesis }
+ { (reg) }
+ if actasmtoken=AS_LPAREN then
+ Begin
+ Consume_RParen;
+ exit;
+ end;
+ if actasmtoken=AS_PLUS then
+ begin
+ consume(AS_PLUS);
+ oper.opr.ref.addressmode:=AM_POSTINCREMENT;
+ end;
+ end {end case }
+ else
+ Begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(false);
+ end;
+ end;
+
+
+ Procedure tavrattreader.BuildOperand(oper : tavroperand);
+ var
+ expr : string;
+ typesize,l : aint;
+
+
+ procedure AddLabelOperand(hl:tasmlabel);
+ begin
+ if not(actasmtoken in [AS_PLUS,AS_MINUS,AS_LPAREN]) { and
+ is_calljmp(actopcode) } then
+ begin
+ oper.opr.typ:=OPR_SYMBOL;
+ oper.opr.symbol:=hl;
+ end
+ else
+ begin
+ oper.InitRef;
+ oper.opr.ref.symbol:=hl;
+ end;
+ end;
+
+
+ procedure MaybeRecordOffset;
+ var
+ mangledname: string;
+ hasdot : boolean;
+ l,
+ toffset,
+ tsize : aint;
+ begin
+ if not(actasmtoken in [AS_DOT,AS_PLUS,AS_MINUS]) then
+ exit;
+ l:=0;
+ hasdot:=(actasmtoken=AS_DOT);
+ if hasdot then
+ begin
+ if expr<>'' then
+ begin
+ BuildRecordOffsetSize(expr,toffset,tsize,mangledname,false);
+ if (oper.opr.typ<>OPR_CONSTANT) and
+ (mangledname<>'') then
+ Message(asmr_e_wrong_sym_type);
+ inc(l,toffset);
+ oper.SetSize(tsize,true);
+ end;
+ end;
+ if actasmtoken in [AS_PLUS,AS_MINUS] then
+ inc(l,BuildConstExpression(true,false));
+ case oper.opr.typ of
+ OPR_LOCAL :
+ begin
+ { don't allow direct access to fields of parameters, because that
+ will generate buggy code. Allow it only for explicit typecasting }
+ if hasdot and
+ (not oper.hastype) and
+ (tabstractnormalvarsym(oper.opr.localsym).owner.symtabletype=parasymtable) and
+ (current_procinfo.procdef.proccalloption<>pocall_register) then
+ Message(asmr_e_cannot_access_field_directly_for_parameters);
+ inc(oper.opr.localsymofs,l)
+ end;
+ OPR_CONSTANT :
+ inc(oper.opr.val,l);
+ OPR_REFERENCE :
+ if (mangledname<>'') then
+ begin
+ if (oper.opr.val<>0) then
+ Message(asmr_e_wrong_sym_type);
+ oper.opr.typ:=OPR_SYMBOL;
+ oper.opr.symbol:=current_asmdata.RefAsmSymbol(mangledname);
+ end
+ else
+ inc(oper.opr.val,l);
+ OPR_SYMBOL:
+ Message(asmr_e_invalid_symbol_ref);
+ else
+ internalerror(200309221);
+ end;
+ end;
+
+
+ function MaybeBuildReference:boolean;
+ { Try to create a reference, if not a reference is found then false
+ is returned }
+ begin
+ MaybeBuildReference:=true;
+ case actasmtoken of
+ AS_INTNUM,
+ AS_MINUS,
+ AS_PLUS:
+ Begin
+ oper.opr.ref.offset:=BuildConstExpression(True,False);
+ if actasmtoken<>AS_LPAREN then
+ Message(asmr_e_invalid_reference_syntax)
+ else
+ BuildReference(oper);
+ end;
+ AS_LPAREN:
+ BuildReference(oper);
+ AS_ID: { only a variable is allowed ... }
+ Begin
+ ReadSym(oper);
+ case actasmtoken of
+ AS_END,
+ AS_SEPARATOR,
+ AS_COMMA: ;
+ AS_LPAREN:
+ BuildReference(oper);
+ else
+ Begin
+ Message(asmr_e_invalid_reference_syntax);
+ Consume(actasmtoken);
+ end;
+ end; {end case }
+ end;
+ else
+ MaybeBuildReference:=false;
+ end; { end case }
+ end;
+
+
+ var
+ tempreg : tregister;
+ ireg : tsuperregister;
+ hl : tasmlabel;
+ ofs : longint;
+ registerset : tcpuregisterset;
+ tempstr : string;
+ tempsymtyp : tasmsymtype;
+ Begin
+ expr:='';
+ case actasmtoken of
+ AS_LBRACKET: { Memory reference or constant expression }
+ Begin
+ oper.InitRef;
+ BuildReference(oper);
+ end;
+
+ AS_INTNUM,
+ AS_MINUS,
+ AS_PLUS:
+ Begin
+ { Constant memory offset }
+ { This must absolutely be followed by ( }
+ oper.InitRef;
+ oper.opr.ref.offset:=BuildConstExpression(True,False);
+
+ { absolute memory addresss? }
+ if actopcode in [A_LDS,A_STS] then
+ BuildReference(oper)
+ else
+ begin
+ ofs:=oper.opr.ref.offset;
+ BuildConstantOperand(oper);
+ inc(oper.opr.val,ofs);
+ end;
+ end;
+
+ AS_ID: { A constant expression, or a Variable ref. }
+ Begin
+ if (actasmpattern='LO8') or (actasmpattern='HI8') then
+ begin
+ { Low or High part of a constant (or constant
+ memory location) }
+ oper.InitRef;
+ if actasmpattern='LO8' then
+ oper.opr.ref.refaddr:=addr_lo8
+ else
+ oper.opr.ref.refaddr:=addr_hi8;
+ Consume(actasmtoken);
+ Consume(AS_LPAREN);
+ BuildConstSymbolExpression(false, true,false,l,tempstr,tempsymtyp);
+ if not assigned(oper.opr.ref.symbol) then
+ oper.opr.ref.symbol:=current_asmdata.RefAsmSymbol(tempstr)
+ else
+ Message(asmr_e_cant_have_multiple_relocatable_symbols);
+ case oper.opr.typ of
+ OPR_CONSTANT :
+ inc(oper.opr.val,l);
+ OPR_LOCAL :
+ inc(oper.opr.localsymofs,l);
+ OPR_REFERENCE :
+ inc(oper.opr.ref.offset,l);
+ else
+ internalerror(200309202);
+ end;
+ Consume(AS_RPAREN);
+ end
+ { Local Label ? }
+ else if is_locallabel(actasmpattern) then
+ begin
+ CreateLocalLabel(actasmpattern,hl,false);
+ Consume(AS_ID);
+ AddLabelOperand(hl);
+ end
+ { Check for label }
+ else if SearchLabel(actasmpattern,hl,false) then
+ begin
+ Consume(AS_ID);
+ AddLabelOperand(hl);
+ end
+ else
+ { probably a variable or normal expression }
+ { or a procedure (such as in CALL ID) }
+ Begin
+ { is it a constant ? }
+ if SearchIConstant(actasmpattern,l) then
+ Begin
+ if not (oper.opr.typ in [OPR_NONE,OPR_CONSTANT]) then
+ Message(asmr_e_invalid_operand_type);
+ BuildConstantOperand(oper);
+ end
+ else
+ begin
+ expr:=actasmpattern;
+ Consume(AS_ID);
+ { typecasting? }
+ if (actasmtoken=AS_LPAREN) and
+ SearchType(expr,typesize) then
+ begin
+ oper.hastype:=true;
+ Consume(AS_LPAREN);
+ BuildOperand(oper);
+ Consume(AS_RPAREN);
+ if oper.opr.typ in [OPR_REFERENCE,OPR_LOCAL] then
+ oper.SetSize(typesize,true);
+ end
+ else
+ begin
+ if not(oper.SetupVar(expr,false)) then
+ Begin
+ { look for special symbols ... }
+ if expr= '__HIGH' then
+ begin
+ consume(AS_LPAREN);
+ if not oper.setupvar('high'+actasmpattern,false) then
+ Message1(sym_e_unknown_id,'high'+actasmpattern);
+ consume(AS_ID);
+ consume(AS_RPAREN);
+ end
+ else
+ if expr = '__RESULT' then
+ oper.SetUpResult
+ else
+ if expr = '__SELF' then
+ oper.SetupSelf
+ else
+ if expr = '__OLDEBP' then
+ oper.SetupOldEBP
+ else
+ Message1(sym_e_unknown_id,expr);
+ end;
+ end;
+ end;
+ if actasmtoken=AS_DOT then
+ MaybeRecordOffset;
+ { add a constant expression? }
+ if (actasmtoken=AS_PLUS) then
+ begin
+ l:=BuildConstExpression(true,false);
+ case oper.opr.typ of
+ OPR_CONSTANT :
+ inc(oper.opr.val,l);
+ OPR_LOCAL :
+ inc(oper.opr.localsymofs,l);
+ OPR_REFERENCE :
+ inc(oper.opr.ref.offset,l);
+ else
+ internalerror(200309202);
+ end;
+ end
+ end;
+ { Do we have a indexing reference, then parse it also }
+ if actasmtoken=AS_LPAREN then
+ BuildReference(oper);
+ end;
+
+ { Register, a variable reference or a constant reference }
+ AS_REGISTER:
+ Begin
+ { save the type of register used. }
+ tempreg:=actasmregister;
+ Consume(AS_REGISTER);
+ if (actasmtoken in [AS_END,AS_SEPARATOR,AS_COMMA]) then
+ Begin
+ if not (oper.opr.typ in [OPR_NONE,OPR_REGISTER]) then
+ Message(asmr_e_invalid_operand_type);
+ oper.opr.typ:=OPR_REGISTER;
+ oper.opr.reg:=tempreg;
+ end
+ else
+ Message(asmr_e_syn_operand);
+ end;
+
+ AS_END,
+ AS_SEPARATOR,
+ AS_COMMA: ;
+ else
+ Begin
+ Message(asmr_e_syn_operand);
+ Consume(actasmtoken);
+ end;
+ end; { end case }
+ end;
+
+
+{*****************************************************************************
+ tavrattreader
+*****************************************************************************}
+
+ procedure tavrattreader.BuildOpCode(instr : tavrinstruction);
+ var
+ operandnum : longint;
+ Begin
+ { opcode }
+ if (actasmtoken<>AS_OPCODE) then
+ Begin
+ Message(asmr_e_invalid_or_missing_opcode);
+ RecoverConsume(true);
+ exit;
+ end;
+ { Fill the instr object with the current state }
+ with instr do
+ begin
+ Opcode:=ActOpcode;
+ condition:=ActCondition;
+ end;
+
+ { We are reading operands, so opcode will be an AS_ID }
+ operandnum:=1;
+ Consume(AS_OPCODE);
+ { Zero operand opcode ? }
+ if actasmtoken in [AS_SEPARATOR,AS_END] then
+ begin
+ operandnum:=0;
+ exit;
+ end;
+ { Read the operands }
+ repeat
+ case actasmtoken of
+ AS_COMMA: { Operand delimiter }
+ Begin
+ if operandnum>Max_Operands then
+ Message(asmr_e_too_many_operands)
+ else
+ Inc(operandnum);
+ Consume(AS_COMMA);
+ end;
+ AS_SEPARATOR,
+ AS_END : { End of asm operands for this opcode }
+ begin
+ break;
+ end;
+ else
+ BuildOperand(instr.Operands[operandnum] as tavroperand);
+ end; { end case }
+ until false;
+ instr.Ops:=operandnum;
+ end;
+
+
+ function tavrattreader.is_asmopcode(const s: string):boolean;
+
+ const
+ { sorted by length so longer postfixes will match first }
+ postfix2strsorted : array[1..19] of string[2] = (
+ 'EP','SB','BT','SH',
+ 'IA','IB','DA','DB','FD','FA','ED','EA',
+ 'B','D','E','P','T','H','S');
+
+ var
+ len,
+ j,
+ sufidx : longint;
+ hs : string;
+ maxlen : longint;
+ icond : tasmcond;
+ Begin
+ { making s a value parameter would break other assembler readers }
+ hs:=s;
+ is_asmopcode:=false;
+
+ { clear op code }
+ actopcode:=A_None;
+
+ actcondition:=C_None;
+
+ { first, handle B else BLS is read wrong }
+ if ((copy(hs,1,2)='BR') and (length(hs)=4)) then
+ begin
+ for icond:=low(tasmcond) to high(tasmcond) do
+ begin
+ if copy(hs,2,3)=uppercond2str[icond] then
+ begin
+ actopcode:=A_BRxx;
+ actasmtoken:=AS_OPCODE;
+ actcondition:=icond;
+ is_asmopcode:=true;
+ exit;
+ end;
+ end;
+ end;
+ maxlen:=max(length(hs),5);
+ actopcode:=A_NONE;
+ for j:=maxlen downto 1 do
+ begin
+ actopcode:=tasmop(PtrInt(iasmops.Find(copy(hs,1,j))));
+ if actopcode<>A_NONE then
+ begin
+ actasmtoken:=AS_OPCODE;
+ { strip op code }
+ delete(hs,1,j);
+ break;
+ end;
+ end;
+ if actopcode=A_NONE then
+ exit;
+ { search for condition, conditions are always 2 chars }
+ if length(hs)>1 then
+ begin
+ for icond:=low(tasmcond) to high(tasmcond) do
+ begin
+ if copy(hs,1,2)=uppercond2str[icond] then
+ begin
+ actcondition:=icond;
+ { strip condition }
+ delete(hs,1,2);
+ break;
+ end;
+ end;
+ end;
+ { if we stripped all postfixes, it's a valid opcode }
+ is_asmopcode:=length(hs)=0;
+ end;
+
+
+ procedure tavrattreader.ConvertCalljmp(instr : tavrinstruction);
+ var
+ newopr : toprrec;
+ begin
+ if instr.Operands[1].opr.typ=OPR_REFERENCE then
+ begin
+ newopr.typ:=OPR_SYMBOL;
+ newopr.symbol:=instr.Operands[1].opr.ref.symbol;
+ newopr.symofs:=instr.Operands[1].opr.ref.offset;
+ if (instr.Operands[1].opr.ref.base<>NR_NO) or
+ (instr.Operands[1].opr.ref.index<>NR_NO) then
+ Message(asmr_e_syn_operand);
+ instr.Operands[1].opr:=newopr;
+ end;
+ end;
+
+
+ procedure tavrattreader.handleopcode;
+ var
+ instr : tavrinstruction;
+ begin
+ instr:=tavrinstruction.Create(tavroperand);
+ BuildOpcode(instr);
+{ if is_calljmp(instr.opcode) then
+ ConvertCalljmp(instr); }
+ {
+ instr.AddReferenceSizes;
+ instr.SetInstructionOpsize;
+ instr.CheckOperandSizes;
+ }
+ instr.ConcatInstruction(curlist);
+ instr.Free;
+ end;
+
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+const
+ asmmode_avr_att_info : tasmmodeinfo =
+ (
+ id : asmmode_avr_gas;
+ idtxt : 'GAS';
+ casmreader : tavrattreader;
+ );
+
+ asmmode_avr_standard_info : tasmmodeinfo =
+ (
+ id : asmmode_standard;
+ idtxt : 'STANDARD';
+ casmreader : tavrattreader;
+ );
+
+initialization
+ RegisterAsmMode(asmmode_avr_att_info);
+ RegisterAsmMode(asmmode_avr_standard_info);
+end.
diff --git a/closures/compiler/avr/ravrcon.inc b/closures/compiler/avr/ravrcon.inc
new file mode 100644
index 0000000000..b5f01d44a4
--- /dev/null
+++ b/closures/compiler/avr/ravrcon.inc
@@ -0,0 +1,34 @@
+{ don't edit, this file is generated from avrreg.dat }
+NR_NO = tregister($00000000);
+NR_R0 = tregister($01000000);
+NR_R1 = tregister($01000001);
+NR_R2 = tregister($01000002);
+NR_R3 = tregister($01000003);
+NR_R4 = tregister($01000004);
+NR_R5 = tregister($01000005);
+NR_R6 = tregister($01000006);
+NR_R7 = tregister($01000007);
+NR_R8 = tregister($01000008);
+NR_R9 = tregister($01000009);
+NR_R10 = tregister($0100000a);
+NR_R11 = tregister($0100000b);
+NR_R12 = tregister($0100000c);
+NR_R13 = tregister($0100000d);
+NR_R14 = tregister($0100000e);
+NR_R15 = tregister($0100000f);
+NR_R16 = tregister($01000010);
+NR_R17 = tregister($01000011);
+NR_R18 = tregister($01000012);
+NR_R19 = tregister($01000013);
+NR_R20 = tregister($01000014);
+NR_R21 = tregister($01000015);
+NR_R22 = tregister($01000016);
+NR_R23 = tregister($01000017);
+NR_R24 = tregister($01000018);
+NR_R25 = tregister($01000019);
+NR_R26 = tregister($0100001a);
+NR_R27 = tregister($0100001b);
+NR_R28 = tregister($0100001c);
+NR_R29 = tregister($0100001d);
+NR_R30 = tregister($0100001e);
+NR_R31 = tregister($0100001f);
diff --git a/closures/compiler/avr/ravrdwa.inc b/closures/compiler/avr/ravrdwa.inc
new file mode 100644
index 0000000000..4231ab6f18
--- /dev/null
+++ b/closures/compiler/avr/ravrdwa.inc
@@ -0,0 +1,34 @@
+{ don't edit, this file is generated from avrreg.dat }
+-1,
+0,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+8,
+9,
+10,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+20,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+31
diff --git a/closures/compiler/avr/ravrnor.inc b/closures/compiler/avr/ravrnor.inc
new file mode 100644
index 0000000000..6640bf866a
--- /dev/null
+++ b/closures/compiler/avr/ravrnor.inc
@@ -0,0 +1,2 @@
+{ don't edit, this file is generated from avrreg.dat }
+33
diff --git a/closures/compiler/avr/ravrnum.inc b/closures/compiler/avr/ravrnum.inc
new file mode 100644
index 0000000000..92e62c897f
--- /dev/null
+++ b/closures/compiler/avr/ravrnum.inc
@@ -0,0 +1,34 @@
+{ don't edit, this file is generated from avrreg.dat }
+tregister($00000000),
+tregister($01000000),
+tregister($01000001),
+tregister($01000002),
+tregister($01000003),
+tregister($01000004),
+tregister($01000005),
+tregister($01000006),
+tregister($01000007),
+tregister($01000008),
+tregister($01000009),
+tregister($0100000a),
+tregister($0100000b),
+tregister($0100000c),
+tregister($0100000d),
+tregister($0100000e),
+tregister($0100000f),
+tregister($01000010),
+tregister($01000011),
+tregister($01000012),
+tregister($01000013),
+tregister($01000014),
+tregister($01000015),
+tregister($01000016),
+tregister($01000017),
+tregister($01000018),
+tregister($01000019),
+tregister($0100001a),
+tregister($0100001b),
+tregister($0100001c),
+tregister($0100001d),
+tregister($0100001e),
+tregister($0100001f)
diff --git a/closures/compiler/avr/ravrrni.inc b/closures/compiler/avr/ravrrni.inc
new file mode 100644
index 0000000000..9f5aa02027
--- /dev/null
+++ b/closures/compiler/avr/ravrrni.inc
@@ -0,0 +1,34 @@
+{ don't edit, this file is generated from avrreg.dat }
+0,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+8,
+9,
+10,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+20,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+31,
+32
diff --git a/closures/compiler/avr/ravrsri.inc b/closures/compiler/avr/ravrsri.inc
new file mode 100644
index 0000000000..771be07f06
--- /dev/null
+++ b/closures/compiler/avr/ravrsri.inc
@@ -0,0 +1,34 @@
+{ don't edit, this file is generated from avrreg.dat }
+0,
+1,
+2,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+20,
+3,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+4,
+31,
+32,
+5,
+6,
+7,
+8,
+9,
+10
diff --git a/closures/compiler/avr/ravrsta.inc b/closures/compiler/avr/ravrsta.inc
new file mode 100644
index 0000000000..4231ab6f18
--- /dev/null
+++ b/closures/compiler/avr/ravrsta.inc
@@ -0,0 +1,34 @@
+{ don't edit, this file is generated from avrreg.dat }
+-1,
+0,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+8,
+9,
+10,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+20,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+31
diff --git a/closures/compiler/avr/ravrstd.inc b/closures/compiler/avr/ravrstd.inc
new file mode 100644
index 0000000000..a29e9cf2a9
--- /dev/null
+++ b/closures/compiler/avr/ravrstd.inc
@@ -0,0 +1,34 @@
+{ don't edit, this file is generated from avrreg.dat }
+'INVALID',
+'r0',
+'r1',
+'r2',
+'r3',
+'r4',
+'r5',
+'r6',
+'r7',
+'r8',
+'r9',
+'r10',
+'r11',
+'r12',
+'r13',
+'r14',
+'r15',
+'r16',
+'r17',
+'r18',
+'r19',
+'r20',
+'r21',
+'r22',
+'r23',
+'r24',
+'r25',
+'r26',
+'r27',
+'r28',
+'r29',
+'r30',
+'r31'
diff --git a/closures/compiler/avr/ravrsup.inc b/closures/compiler/avr/ravrsup.inc
new file mode 100644
index 0000000000..da781e0718
--- /dev/null
+++ b/closures/compiler/avr/ravrsup.inc
@@ -0,0 +1,34 @@
+{ don't edit, this file is generated from avrreg.dat }
+RS_NO = $00;
+RS_R0 = $00;
+RS_R1 = $01;
+RS_R2 = $02;
+RS_R3 = $03;
+RS_R4 = $04;
+RS_R5 = $05;
+RS_R6 = $06;
+RS_R7 = $07;
+RS_R8 = $08;
+RS_R9 = $09;
+RS_R10 = $0a;
+RS_R11 = $0b;
+RS_R12 = $0c;
+RS_R13 = $0d;
+RS_R14 = $0e;
+RS_R15 = $0f;
+RS_R16 = $10;
+RS_R17 = $11;
+RS_R18 = $12;
+RS_R19 = $13;
+RS_R20 = $14;
+RS_R21 = $15;
+RS_R22 = $16;
+RS_R23 = $17;
+RS_R24 = $18;
+RS_R25 = $19;
+RS_R26 = $1a;
+RS_R27 = $1b;
+RS_R28 = $1c;
+RS_R29 = $1d;
+RS_R30 = $1e;
+RS_R31 = $1f;
diff --git a/closures/compiler/avr/rgcpu.pas b/closures/compiler/avr/rgcpu.pas
new file mode 100644
index 0000000000..602ec1c2ff
--- /dev/null
+++ b/closures/compiler/avr/rgcpu.pas
@@ -0,0 +1,169 @@
+{
+ Copyright (c) 1998-2008 by Florian Klaempfl
+
+ This unit implements the avr specific class for the register
+ allocator
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+
+unit rgcpu;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ aasmbase,aasmtai,aasmdata,aasmcpu,
+ cgbase,cgutils,
+ cpubase,
+ rgobj;
+
+ type
+ trgcpu = class(trgobj)
+ procedure add_constraints(reg:tregister);override;
+ procedure do_spill_read(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister);override;
+ procedure do_spill_written(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister);override;
+ end;
+
+ trgintcpu = class(trgcpu)
+ procedure add_cpu_interferences(p : tai);override;
+ end;
+
+ implementation
+
+ uses
+ verbose, cutils,
+ cgobj,
+ procinfo;
+
+
+ procedure trgcpu.add_constraints(reg:tregister);
+ var
+ supreg,i : Tsuperregister;
+ begin
+ case getsubreg(reg) of
+ { Let 64bit floats conflict with all odd float regs }
+ R_SUBFD:
+ begin
+ {
+ supreg:=getsupreg(reg);
+ i:=RS_F1;
+ while (i<=RS_F31) do
+ begin
+ add_edge(supreg,i);
+ inc(i,2);
+ end;
+ }
+ end;
+ { Let 64bit ints conflict with all odd int regs }
+ R_SUBQ:
+ begin
+ supreg:=getsupreg(reg);
+ {
+ i:=RS_G1;
+ while (i<=RS_I7) do
+ begin
+ add_edge(supreg,i);
+ inc(i,2);
+ end;
+ }
+ end;
+ end;
+ end;
+
+
+ procedure trgcpu.do_spill_read(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister);
+ var
+ helpins : tai;
+ tmpref : treference;
+ helplist : TAsmList;
+ hreg : tregister;
+ begin
+ if abs(spilltemp.offset)>63 then
+ begin
+ helplist:=TAsmList.create;
+
+ helplist.concat(taicpu.op_reg_const(A_LDI,NR_R26,lo(word(spilltemp.offset))));
+ helplist.concat(taicpu.op_reg_const(A_LDI,NR_R27,hi(word(spilltemp.offset))));
+ helplist.concat(taicpu.op_reg_reg(A_ADD,NR_R26,spilltemp.base));
+ helplist.concat(taicpu.op_reg_reg(A_ADC,NR_R27,GetNextReg(spilltemp.base)));
+
+ reference_reset_base(tmpref,NR_R26,0,1);
+ helpins:=spilling_create_load(tmpref,tempreg);
+ helplist.concat(helpins);
+ list.insertlistafter(pos,helplist);
+ helplist.free;
+ end
+ else
+ inherited do_spill_read(list,pos,spilltemp,tempreg);
+ end;
+
+
+ procedure trgcpu.do_spill_written(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister);
+ var
+ tmpref : treference;
+ helplist : TAsmList;
+ hreg : tregister;
+ begin
+ if abs(spilltemp.offset)>63 then
+ begin
+ helplist:=TAsmList.create;
+
+ helplist.concat(taicpu.op_reg_const(A_LDI,NR_R26,lo(word(spilltemp.offset))));
+ helplist.concat(taicpu.op_reg_const(A_LDI,NR_R27,hi(word(spilltemp.offset))));
+ helplist.concat(taicpu.op_reg_reg(A_ADD,NR_R26,spilltemp.base));
+ helplist.concat(taicpu.op_reg_reg(A_ADC,NR_R27,GetNextReg(spilltemp.base)));
+
+ reference_reset_base(tmpref,NR_R26,0,1);
+ helplist.concat(spilling_create_store(tempreg,tmpref));
+ list.insertlistafter(pos,helplist);
+ helplist.free;
+ end
+ else
+ inherited do_spill_written(list,pos,spilltemp,tempreg);
+ end;
+
+
+ procedure trgintcpu.add_cpu_interferences(p : tai);
+ var
+ r : tsuperregister;
+ begin
+ if p.typ=ait_instruction then
+ begin
+ case taicpu(p).opcode of
+ A_CPI,
+ A_ANDI,
+ A_ORI,
+ A_SUBI,
+ A_SBCI,
+ A_LDI:
+ for r:=RS_R0 to RS_R15 do
+ add_edge(r,GetSupReg(taicpu(p).oper[0]^.reg));
+ A_MULS:
+ begin
+ for r:=RS_R0 to RS_R15 do
+ add_edge(r,GetSupReg(taicpu(p).oper[0]^.reg));
+ for r:=RS_R0 to RS_R15 do
+ add_edge(r,GetSupReg(taicpu(p).oper[1]^.reg));
+ end;
+ end;
+ end;
+ end;
+
+
+end.
diff --git a/closures/compiler/browcol.pas b/closures/compiler/browcol.pas
new file mode 100644
index 0000000000..183063be35
--- /dev/null
+++ b/closures/compiler/browcol.pas
@@ -0,0 +1,2291 @@
+{
+ Copyright (c) 1998-2002 by Berczi Gabor
+ Modifications Copyright (c) 1999-2002 Florian Klaempfl and Pierre Muller
+
+ Support routines for getting browser info in collections
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+{$ifdef TP}
+ {$N+,E+}
+{$endif}
+unit browcol;
+
+{$i fpcdefs.inc}
+{ $define use_refs}
+{$H-}
+
+interface
+
+uses
+ SysUtils,
+ CUtils,
+ objects,
+ cclasses,
+ symconst,symtable;
+
+const
+ SymbolTypLen : integer = 6;
+
+ RecordTypes : set of tsymtyp =
+ ([typesym,unitsym]);
+
+ sfRecord = $00000001;
+ sfObject = $00000002;
+ sfClass = $00000004;
+ sfPointer = $00000008;
+ sfHasMemInfo = $80000000;
+
+type
+ TStoreCollection = object(TStringCollection)
+ function Add(const S: string): PString;
+ end;
+
+ PModuleNameCollection = ^TModuleNameCollection;
+ TModuleNameCollection = object(TStoreCollection)
+ end;
+
+ PTypeNameCollection = ^TTypeNameCollection;
+ TTypeNameCollection = object(TStoreCollection)
+ end;
+
+ PSymbolCollection = ^TSymbolCollection;
+ PSortedSymbolCollection = ^TSortedSymbolCollection;
+ PReferenceCollection = ^TReferenceCollection;
+
+ PReference = ^TReference;
+ TReference = object(TObject)
+ FileName : PString;
+ Position : TPoint;
+ constructor Init(AFileName: PString; ALine, AColumn: Sw_integer);
+ function GetFileName: string;
+ destructor Done; virtual;
+ constructor Load(var S: TStream);
+ procedure Store(var S: TStream);
+ end;
+
+ PSymbolMemInfo = ^TSymbolMemInfo;
+ TSymbolMemInfo = record
+ Addr : longint;
+ Size : longint;
+ PushSize : longint;
+ end;
+
+ PSymbol = ^TSymbol;
+ TSymbol = object(TObject)
+ Name : PString;
+ Typ : tsymtyp;
+ varoptions : tvaroptions;
+ varspez : tvarspez; { sets the type of access }
+ Params : PString;
+ References : PReferenceCollection;
+ Items : PSymbolCollection;
+ DType : PString;
+ VType : PString;
+ TypeID : Ptrint;
+ RelatedTypeID : Ptrint;
+ DebuggerCount : longint;
+ Ancestor : PSymbol;
+ Flags : longint;
+ MemInfo : PSymbolMemInfo;
+ constructor Init(const AName: string; ATyp: tsymtyp; AParams: string; AMemInfo: PSymbolMemInfo);
+ procedure SetMemInfo(const AMemInfo: TSymbolMemInfo);
+ function GetReferenceCount: Sw_integer;
+ function GetReference(Index: Sw_integer): PReference;
+ function GetItemCount: Sw_integer;
+ function GetItem(Index: Sw_integer): PSymbol;
+ function GetName: string;
+ function GetText: string;
+ function GetTypeName: string;
+ destructor Done; virtual;
+ procedure SetVarSpez(const AVarSpez : TVarSpez);
+ procedure SetVarOptions(const AVarOptions : TVarOptions);
+ constructor Load(var S: TStream);
+ procedure Store(var S: TStream);
+ end;
+
+ PExport = ^TExport;
+ TExport = object(TObject)
+ constructor Init(const AName: string; AIndex: longint; ASymbol: PSymbol);
+ function GetDisplayText: string;
+ destructor Done; virtual;
+ private
+ Name: PString;
+ Index: longint;
+ Symbol: PSymbol;
+ end;
+
+ PExportCollection = ^TExportCollection;
+ TExportCollection = object(TSortedCollection)
+ function At(Index: sw_Integer): PExport;
+ function Compare(Key1, Key2: Pointer): sw_Integer; virtual;
+ end;
+
+ PImport = ^TImport;
+ TImport = object(TObject)
+ constructor Init(const ALibName, AFuncName,ARealName: string; AIndex: longint);
+ function GetDisplayText: string;
+ destructor Done; virtual;
+ private
+ LibName: PString;
+ FuncName: PString;
+ RealName: PString;
+ Index: longint;
+ end;
+
+ PImportCollection = ^TImportCollection;
+ TImportCollection = object(TSortedCollection)
+ function At(Index: sw_Integer): PImport;
+ function Compare(Key1, Key2: Pointer): sw_Integer; virtual;
+ end;
+
+ PObjectSymbolCollection = ^TObjectSymbolCollection;
+
+ PObjectSymbol = ^TObjectSymbol;
+ TObjectSymbol = object(TObject)
+ Parent : PObjectSymbol;
+ Symbol : PSymbol;
+ Expanded : boolean;
+ constructor Init(AParent: PObjectSymbol; ASymbol: PSymbol);
+ constructor InitName(const AName: string);
+ function GetName: string;
+ function GetDescendantCount: sw_integer;
+ function GetDescendant(Index: sw_integer): PObjectSymbol;
+ procedure AddDescendant(P: PObjectSymbol);
+ destructor Done; virtual;
+ constructor Load(var S: TStream);
+ procedure Store(S: TStream);
+ private
+ Name: PString;
+ Descendants: PObjectSymbolCollection;
+ end;
+
+ TSymbolCollection = object(TSortedCollection)
+ constructor Init(ALimit, ADelta: Integer);
+ function At(Index: Sw_Integer): PSymbol;
+ procedure Insert(Item: Pointer); virtual;
+ function LookUp(const S: string; var Idx: sw_integer): string; virtual;
+ end;
+
+ TSortedSymbolCollection = object(TSymbolCollection)
+ function Compare(Key1, Key2: Pointer): Sw_Integer; virtual;
+ procedure Insert(Item: Pointer); virtual;
+ function LookUp(const S: string; var Idx: sw_integer): string; virtual;
+ end;
+
+ PIDSortedSymbolCollection = ^TIDSortedSymbolCollection;
+ TIDSortedSymbolCollection = object(TSymbolCollection)
+ function Compare(Key1, Key2: Pointer): Sw_Integer; virtual;
+ procedure Insert(Item: Pointer); virtual;
+ function SearchSymbolByID(AID: longint): PSymbol;
+ end;
+
+ TObjectSymbolCollection = object(TSortedCollection)
+ constructor Init(ALimit, ADelta: Integer);
+ function Compare(Key1, Key2: Pointer): Sw_Integer; virtual;
+ function LookUp(const S: string; var Idx: sw_integer): string; virtual;
+ function At(Index: Sw_Integer): PObjectSymbol;
+ end;
+
+ TReferenceCollection = object(TCollection)
+ function At(Index: Sw_Integer): PReference;
+ end;
+
+ PSourceFile = ^TSourceFile;
+ TSourceFile = object(TObject)
+ SourceFileName: PString;
+ ObjFileName: PString;
+ PPUFileName: PString;
+ constructor Init(ASourceFileName, AObjFileName, APPUFileName: string);
+ destructor Done; virtual;
+ function GetSourceFilename: string;
+ function GetObjFileName: string;
+ function GetPPUFileName: string;
+ end;
+
+ PSourceFileCollection = ^TSourceFileCollection;
+ TSourceFileCollection = object(TCollection)
+ function At(Index: sw_Integer): PSourceFile;
+ end;
+
+ PModuleSymbol = ^TModuleSymbol;
+ TModuleSymbol = object(TSymbol)
+ Exports_ : PExportCollection;
+ Imports : PImportCollection;
+ LoadedFrom : PString;
+ UsedUnits : PSymbolCollection;
+ DependentUnits: PSymbolCollection;
+ MainSource: PString;
+ SourceFiles: pstringCollection;
+ constructor Init(const AName, AMainSource: string);
+ procedure SetLoadedFrom(const AModuleName: string);
+ procedure AddUsedUnit(P: PSymbol);
+ procedure AddDependentUnit(P: PSymbol);
+ procedure AddSourceFile(const Path: string);
+ destructor Done; virtual;
+ end;
+
+const
+ Modules : PSymbolCollection = nil;
+ ModuleNames : PModuleNameCollection = nil;
+ TypeNames : PTypeNameCollection = nil;
+ ObjectTree : PObjectSymbol = nil;
+ SourceFiles : PSourceFileCollection = nil;
+
+procedure DisposeBrowserCol;
+procedure NewBrowserCol;
+procedure CreateBrowserCol;
+procedure InitBrowserCol;
+procedure DoneBrowserCol;
+
+function LoadBrowserCol(S: PStream): boolean;
+function StoreBrowserCol(S: PStream) : boolean;
+
+procedure BuildObjectInfo;
+
+procedure BuildSourceList;
+
+function SearchObjectForSymbol(O: PSymbol): PObjectSymbol;
+
+procedure RegisterSymbols;
+
+implementation
+
+uses
+ globtype,globals,comphook,constexp,
+{$ifdef DEBUG}
+ verbose,
+{$endif DEBUG}
+ finput,fmodule,
+ crefs,cpuinfo,cgbase,
+ aasmbase,aasmtai,aasmdata,paramgr,
+ symsym,symdef,symtype,symbase,defutil;
+
+const
+ RModuleNameCollection: TStreamRec = (
+ ObjType: 3001;
+ VmtLink: Ofs(TypeOf(TModuleNameCollection)^);
+ Load: @TModuleNameCollection.Load;
+ Store: @TModuleNameCollection.Store;
+ Next: nil
+ );
+ RTypeNameCollection: TStreamRec = (
+ ObjType: 3002;
+ VmtLink: Ofs(TypeOf(TTypeNameCollection)^);
+ Load: @TTypeNameCollection.Load;
+ Store: @TTypeNameCollection.Store;
+ Next: nil
+ );
+ RReference: TStreamRec = (
+ ObjType: 3003;
+ VmtLink: Ofs(TypeOf(TReference)^);
+ Load: @TReference.Load;
+ Store: @TReference.Store;
+ Next: nil
+ );
+ RSymbol: TStreamRec = (
+ ObjType: 3004;
+ VmtLink: Ofs(TypeOf(TSymbol)^);
+ Load: @TSymbol.Load;
+ Store: @TSymbol.Store;
+ Next: nil
+ );
+ RObjectSymbol: TStreamRec = (
+ ObjType: 3005;
+ VmtLink: Ofs(TypeOf(TObjectSymbol)^);
+ Load: @TObjectSymbol.Load;
+ Store: @TObjectSymbol.Store;
+ Next: nil
+ );
+ RSymbolCollection: TStreamRec = (
+ ObjType: 3006;
+ VmtLink: Ofs(TypeOf(TSymbolCollection)^);
+ Load: @TSymbolCollection.Load;
+ Store: @TSymbolCollection.Store;
+ Next: nil
+ );
+ RSortedSymbolCollection: TStreamRec = (
+ ObjType: 3007;
+ VmtLink: Ofs(TypeOf(TSortedSymbolCollection)^);
+ Load: @TSortedSymbolCollection.Load;
+ Store: @TSortedSymbolCollection.Store;
+ Next: nil
+ );
+ RIDSortedSymbolCollection: TStreamRec = (
+ ObjType: 3008;
+ VmtLink: Ofs(TypeOf(TIDSortedSymbolCollection)^);
+ Load: @TIDSortedSymbolCollection.Load;
+ Store: @TIDSortedSymbolCollection.Store;
+ Next: nil
+ );
+ RObjectSymbolCollection: TStreamRec = (
+ ObjType: 3009;
+ VmtLink: Ofs(TypeOf(TObjectSymbolCollection)^);
+ Load: @TObjectSymbolCollection.Load;
+ Store: @TObjectSymbolCollection.Store;
+ Next: nil
+ );
+ RReferenceCollection: TStreamRec = (
+ ObjType: 3010;
+ VmtLink: Ofs(TypeOf(TReferenceCollection)^);
+ Load: @TReferenceCollection.Load;
+ Store: @TReferenceCollection.Store;
+ Next: nil
+ );
+ RModuleSymbol: TStreamRec = (
+ ObjType: 3011;
+ VmtLink: Ofs(TypeOf(TModuleSymbol)^);
+ Load: @TModuleSymbol.Load;
+ Store: @TModuleSymbol.Store;
+ Next: nil
+ );
+
+ SymbolCount : longint = 0;
+
+{****************************************************************************
+ Helpers
+****************************************************************************}
+
+function GetStr(P: PString): string;
+begin
+ if P=nil then
+ GetStr:=''
+ else
+ GetStr:=P^;
+end;
+
+function IntToStr(L: longint): string;
+var S: string;
+begin
+ Str(L,S);
+ IntToStr:=S;
+end;
+
+function UpcaseStr(S: string): string;
+var I: integer;
+begin
+ for I:=1 to length(S) do
+ S[I]:=Upcase(S[I]);
+ UpcaseStr:=S;
+end;
+
+function FloatToStr(E: extended): string;
+var S: string;
+begin
+ Str(E:0:24,S);
+ if Pos('.',S)>0 then
+ begin
+ while (length(S)>0) and (S[length(S)]='0') do
+ Delete(S,length(S),1);
+ if (length(S)>0) and (S[length(S)]='.') then
+ Delete(S,length(S),1);
+ end;
+ if S='' then S:='0';
+ FloatToStr:=S;
+end;
+
+{****************************************************************************
+ TStoreCollection
+****************************************************************************}
+
+function TStoreCollection.Add(const S: string): PString;
+var P: PString;
+ Index: Sw_integer;
+begin
+ if S='' then P:=nil else
+ if Search(@S,Index) then P:=At(Index) else
+ begin
+ P:=NewStr(S);
+ Insert(P);
+ end;
+ Add:=P;
+end;
+
+
+{****************************************************************************
+ TSymbolCollection
+****************************************************************************}
+
+constructor TSymbolCollection.Init(ALimit, ADelta: Integer);
+begin
+ inherited Init(ALimit,ADelta);
+ Duplicates:=true;
+end;
+
+function TSymbolCollection.At(Index: Sw_Integer): PSymbol;
+begin
+ At:=inherited At(Index);
+end;
+
+procedure TSymbolCollection.Insert(Item: Pointer);
+begin
+
+ TCollection.Insert(Item);
+end;
+
+function TSymbolCollection.LookUp(const S: string; var Idx: sw_integer): string;
+begin
+ Idx:=-1;
+ LookUp:='';
+end;
+
+{****************************************************************************
+ TReferenceCollection
+****************************************************************************}
+
+function TReferenceCollection.At(Index: Sw_Integer): PReference;
+begin
+ At:=inherited At(Index);
+end;
+
+
+{****************************************************************************
+ TSortedSymbolCollection
+****************************************************************************}
+
+function TSortedSymbolCollection.Compare(Key1, Key2: Pointer): Sw_Integer;
+var K1: PSymbol absolute Key1;
+ K2: PSymbol absolute Key2;
+ R: Sw_integer;
+ S1,S2: string;
+begin
+ S1:=Upper(K1^.GetName);
+ S2:=Upper(K2^.GetName);
+ if S1<S2 then R:=-1 else
+ if S1>S2 then R:=1 else
+ if K1^.TypeID=K2^.TypeID then
+ R:=0
+ else
+ begin
+ S1:=K1^.GetName;
+ S2:=K2^.GetName;
+ if S1<S2 then R:=-1 else
+ if S1>S2 then R:=1 else
+ if K1^.TypeID<K2^.TypeID then R:=-1 else
+ if K1^.TypeID>K2^.TypeID then R:= 1 else
+ begin
+ { Handle overloaded functions }
+ if (K1^.Typ=procsym) then
+ begin
+ S1:=K1^.GetText;
+ S2:=K2^.GetText;
+ if S1<S2 then R:=-1 else
+ if S1>S2 then R:=1 else
+ R:=0;
+ end
+ else
+ R:=0;
+ end
+ end;
+ Compare:=R;
+end;
+
+procedure TSortedSymbolCollection.Insert(Item: Pointer);
+begin
+ TSortedCollection.Insert(Item);
+end;
+
+function TSortedSymbolCollection.LookUp(const S: string; var Idx: sw_integer): string;
+var OLI,ORI,Left,Right,Mid: integer;
+ LeftP,RightP,MidP: PSymbol;
+ LeftS,MidS,RightS: string;
+ FoundS: string;
+ UpS : string;
+begin
+ Idx:=-1; FoundS:='';
+ Left:=0; Right:=Count-1;
+ UpS:=Upper(S);
+ if Left<Right then
+ begin
+ while (Left<Right) do
+ begin
+ OLI:=Left; ORI:=Right;
+ Mid:=Left+(Right-Left) div 2;
+ MidP:=At(Mid);
+{$ifdef DEBUG}
+ LeftP:=At(Left); RightP:=At(Right);
+ LeftS:=Upper(LeftP^.GetName);
+ RightS:=Upper(RightP^.GetName);
+{$endif DEBUG}
+ MidS:=Upper(MidP^.GetName);
+ if copy(MidS,1,length(UpS))=UpS then
+ begin
+ Idx:=Mid;
+ FoundS:=MidS;
+ end;
+{ else}
+ if UpS<MidS then
+ Right:=Mid
+ else
+ Left:=Mid;
+ if (OLI=Left) and (ORI=Right) then
+ begin
+ if idX<>-1 then
+ break;
+ if Mid=Left then
+ begin
+ RightP:=At(Right);
+ RightS:=Upper(RightP^.GetName);
+ if copy(RightS,1,length(UpS))=UpS then
+ begin
+ Idx:=Right;
+ FoundS:=RightS;
+ end;
+ end;
+ if Mid=Right then
+ begin
+ LeftP:=At(Left);
+ LeftS:=Upper(LeftP^.GetName);
+ if copy(LeftS,1,length(UpS))=UpS then
+ begin
+ Idx:=Left;
+ FoundS:=LeftS;
+ end;
+ end;
+ Break;
+ end;
+ end;
+ end;
+ LookUp:=FoundS;
+end;
+
+{****************************************************************************
+ TIDSortedSymbolCollection
+****************************************************************************}
+
+function TIDSortedSymbolCollection.Compare(Key1, Key2: Pointer): Sw_Integer;
+var K1: PSymbol absolute Key1;
+ K2: PSymbol absolute Key2;
+ R: Sw_integer;
+begin
+ if K1^.TypeID<K2^.TypeID then R:=-1 else
+ if K1^.TypeID>K2^.TypeID then R:= 1 else
+ R:=0;
+ Compare:=R;
+end;
+
+procedure TIDSortedSymbolCollection.Insert(Item: Pointer);
+begin
+ TSortedCollection.Insert(Item);
+end;
+
+function TIDSortedSymbolCollection.SearchSymbolByID(AID: longint): PSymbol;
+var S: TSymbol;
+ Index: sw_integer;
+ P: PSymbol;
+begin
+ S.TypeID:=AID;
+ if Search(@S,Index)=false then P:=nil else
+ P:=At(Index);
+ SearchSymbolByID:=P;
+end;
+
+{****************************************************************************
+ TObjectSymbolCollection
+****************************************************************************}
+
+function TObjectSymbolCollection.At(Index: Sw_Integer): PObjectSymbol;
+begin
+ At:=inherited At(Index);
+end;
+
+constructor TObjectSymbolCollection.Init(ALimit, ADelta: Integer);
+begin
+ inherited Init(ALimit,ADelta);
+end;
+
+function TObjectSymbolCollection.Compare(Key1, Key2: Pointer): Sw_Integer;
+var K1: PObjectSymbol absolute Key1;
+ K2: PObjectSymbol absolute Key2;
+ R: Sw_integer;
+ S1,S2: string;
+begin
+ S1:=Upper(K1^.GetName);
+ S2:=Upper(K2^.GetName);
+ if S1<S2 then R:=-1 else
+ if S1>S2 then R:=1 else
+ { make sure that we distinguish between different objects with the same name }
+ if PtrUInt(K1^.Symbol)<PtrUInt(K2^.Symbol) then R:=-1 else
+ if PtrUInt(K1^.Symbol)>PtrUInt(K2^.Symbol) then R:= 1 else
+ R:=0;
+ Compare:=R;
+end;
+
+function TObjectSymbolCollection.LookUp(const S: string; var Idx: sw_integer): string;
+var OLI,ORI,Left,Right,Mid: integer;
+ {LeftP,RightP,}MidP: PObjectSymbol;
+ {LeftS,RightS,}MidS: string;
+ FoundS: string;
+ UpS : string;
+begin
+ Idx:=-1; FoundS:='';
+ Left:=0; Right:=Count-1;
+ UpS:=Upper(S);
+ if Left<Right then
+ begin
+ while (Left<Right) do
+ begin
+ OLI:=Left; ORI:=Right;
+ Mid:=Left+(Right-Left) div 2;
+ {LeftP:=At(Left);
+ LeftS:=Upper(LeftP^.GetName);}
+ MidP:=At(Mid);
+ MidS:=Upper(MidP^.GetName);
+ {RightP:=At(Right);
+ RightS:=Upper(RightP^.GetName);}
+ if copy(MidS,1,length(UpS))=UpS then
+ begin
+ Idx:=Mid;
+ FoundS:=MidS;
+ end;
+{ else}
+ if UpS<MidS then
+ Right:=Mid
+ else
+ Left:=Mid;
+ if (OLI=Left) and (ORI=Right) then
+ Break;
+ end;
+ end;
+ LookUp:=FoundS;
+end;
+
+{****************************************************************************
+ TReference
+****************************************************************************}
+
+constructor TReference.Init(AFileName: PString; ALine, AColumn: Sw_integer);
+begin
+ inherited Init;
+ FileName:=AFileName;
+ Position.X:=AColumn;
+ Position.Y:=ALine;
+end;
+
+function TReference.GetFileName: string;
+begin
+ GetFileName:=GetStr(FileName);
+end;
+
+destructor TReference.Done;
+begin
+ inherited Done;
+end;
+
+constructor TReference.Load(var S: TStream);
+begin
+ S.Read(Position, SizeOf(Position));
+
+ { --- items needing fixup --- }
+ S.Read(FileName, SizeOf(FileName)); { ->ModulesNames^.Item }
+end;
+
+procedure TReference.Store(var S: TStream);
+begin
+ S.Write(Position, SizeOf(Position));
+
+ { --- items needing fixup --- }
+ S.Write(FileName, SizeOf(FileName));
+end;
+
+{****************************************************************************
+ TSymbol
+****************************************************************************}
+
+constructor TSymbol.Init(const AName: string; ATyp: tsymtyp; AParams: string; AMemInfo: PSymbolMemInfo);
+begin
+ inherited Init;
+ inc(SymbolCount);
+ VarSpez:=vs_value;
+ VarOptions:=[];
+ Name:=NewStr(AName); Typ:=ATyp;
+ if AMemInfo<>nil then
+ SetMemInfo(AMemInfo^);
+ New(References, Init(20,50));
+ if ATyp in RecordTypes then
+ begin
+ Items:=New(PSortedSymbolCollection, Init(50,100));
+ end;
+end;
+
+procedure TSymbol.SetVarSpez(const AVarSpez : TVarSpez);
+begin
+ VarSpez:=AVarSpez;
+end;
+
+procedure TSymbol.SetVarOptions(const AVarOptions : TVarOptions);
+begin
+ VarOptions:=AVarOptions;
+end;
+
+procedure TSymbol.SetMemInfo(const AMemInfo: TSymbolMemInfo);
+begin
+ if MemInfo=nil then New(MemInfo);
+ Move(AMemInfo,MemInfo^,SizeOf(MemInfo^));
+ Flags:=Flags or sfHasMemInfo;
+end;
+
+function TSymbol.GetReferenceCount: Sw_integer;
+var Count: Sw_integer;
+begin
+ if References=nil then Count:=0 else
+ Count:=References^.Count;
+ GetReferenceCount:=Count;
+end;
+
+function TSymbol.GetReference(Index: Sw_integer): PReference;
+begin
+ GetReference:=References^.At(Index);
+end;
+
+function TSymbol.GetItemCount: Sw_integer;
+var Count: Sw_integer;
+begin
+ if Items=nil then Count:=0 else
+ Count:=Items^.Count;
+ GetItemCount:=Count;
+end;
+
+function TSymbol.GetItem(Index: Sw_integer): PSymbol;
+begin
+ GetItem:=Items^.At(Index);
+end;
+
+function TSymbol.GetName: string;
+begin
+ GetName:=GetStr(Name);
+end;
+
+function TSymbol.GetText: string;
+var S: string;
+begin
+ S:=GetTypeName;
+ if length(S)>SymbolTypLen then
+ S:=Copy(S,1,SymbolTypLen)
+ else
+ begin
+ while length(S)<SymbolTypLen do
+ S:=S+' ';
+ end;
+ S:=S+' '+GetName;
+ if (Flags and sfRecord)<>0 then
+ S:=S+' = record'
+ else
+ if (Flags and sfObject)<>0 then
+ begin
+ S:=S+' = ';
+ if (Flags and sfClass)<>0 then
+ S:=S+'class'
+ else
+ S:=S+'object';
+ if Ancestor<>nil then
+ S:=S+'('+Ancestor^.GetName+')';
+ end
+ else
+ begin
+ if Assigned(DType) then
+ S:=S+' = '+DType^;
+ if Assigned(Params) then
+ S:=S+'('+Params^+')';
+ if Assigned(VType) then
+ S:=S+': '+VType^;
+ end;
+ if Typ=ProcSym then
+ S:=S+';';
+ GetText:=S;
+end;
+
+function TSymbol.GetTypeName: string;
+var S: string;
+begin
+ case Typ of
+ abstractsym : S:='abst';
+ fieldvarsym : S:='member';
+ staticvarsym,
+ localvarsym,
+ paravarsym :
+ begin
+ if (vo_is_hidden_para in varoptions) then
+ S:='hidden'
+ else
+ S:='var';
+ end;
+ typesym : S:='type';
+ procsym : if VType=nil then
+ S:='proc'
+ else
+ S:='func';
+ unitsym : S:='unit';
+ constsym : S:='const';
+ enumsym : S:='enum';
+ errorsym : S:='error';
+ syssym : S:='sys';
+ labelsym : S:='label';
+ absolutevarsym :
+ if (vo_is_funcret in varoptions) then
+ S:='ret'
+ else
+ S:='abs';
+ propertysym : S:='prop';
+ macrosym : S:='macro';
+ else S:='';
+ end;
+ GetTypeName:=S;
+end;
+
+destructor TSymbol.Done;
+begin
+ if assigned(MemInfo) then
+ Dispose(MemInfo);
+ if assigned(References) then
+ Dispose(References, Done);
+ if assigned(Items) then
+ Dispose(Items, Done);
+ if assigned(Name) then
+ DisposeStr(Name);
+{ if assigned(Params) then
+ DisposeStr(Params); in TypeNames
+ if assigned(VType) then
+ DisposeStr(VType);
+ if assigned(DType) then
+ DisposeStr(DType);
+ if assigned(Ancestor) then
+ DisposeStr(Ancestor);}
+ dec(SymbolCount);
+ inherited Done;
+end;
+
+constructor TSymbol.Load(var S: TStream);
+var MI: TSymbolMemInfo;
+ W: word;
+begin
+ TObject.Init;
+ inc(SymbolCount);
+
+ S.Read(Typ,SizeOf(Typ));
+ case Typ of
+ abstractsym,
+ absolutevarsym,
+ staticvarsym,
+ localvarsym,
+ paravarsym :
+ begin
+ S.Read(VarSpez,SizeOf(VarSpez));
+ S.Read(VarOptions,SizeOf(VarOptions));
+ end;
+ else
+ begin
+ VarSpez:=vs_value;
+ VarOptions:=[];
+ end;
+ end;
+ S.Read(TypeID, SizeOf(TypeID));
+ S.Read(RelatedTypeID, SizeOf(RelatedTypeID));
+ S.Read(Flags, SizeOf(Flags));
+ Name:=S.ReadStr;
+ if (Flags and sfHasMemInfo)<>0 then
+ begin
+ S.Read(MI,SizeOf(MI));
+ SetMemInfo(MI);
+ end;
+
+ W:=0;
+ S.Read(W,SizeOf(W));
+ if (W and 1)<>0 then
+ New(References, Load(S));
+ if (W and 2)<>0 then
+ New(Items, Load(S));
+
+ { --- items needing fixup --- }
+ S.Read(DType, SizeOf(DType));
+ S.Read(VType, SizeOf(VType));
+ S.Read(Params, SizeOf(Params));
+end;
+
+procedure TSymbol.Store(var S: TStream);
+var W: word;
+begin
+ S.Write(Typ,SizeOf(Typ));
+ case Typ of
+ abstractsym,
+ absolutevarsym,
+ staticvarsym,
+ localvarsym,
+ paravarsym :
+ begin
+ S.Write(VarSpez,SizeOf(VarSpez));
+ S.Write(VarOptions,SizeOf(VarOptions));
+ end;
+ end;
+ S.Write(TypeID, SizeOf(TypeID));
+ S.Write(RelatedTypeID, SizeOf(RelatedTypeID));
+ S.Write(Flags, SizeOf(Flags));
+ S.WriteStr(Name);
+
+ if (Flags and sfHasMemInfo)<>0 then
+ S.Write(MemInfo^,SizeOf(MemInfo^));
+
+ W:=0;
+ if Assigned(References) then W:=W or 1;
+ if Assigned(Items) then W:=W or 2;
+ S.Write(W,SizeOf(W));
+ if Assigned(References) then References^.Store(S);
+ if Assigned(Items) then Items^.Store(S);
+
+ { --- items needing fixup --- }
+ S.Write(DType, SizeOf(DType));
+ S.Write(VType, SizeOf(VType));
+ S.Write(Params, SizeOf(Params));
+end;
+
+constructor TExport.Init(const AName: string; AIndex: longint; ASymbol: PSymbol);
+begin
+ inherited Init;
+ Name:=NewStr(AName); Index:=AIndex;
+ Symbol:=ASymbol;
+end;
+
+function TExport.GetDisplayText: string;
+var S: string;
+begin
+ S:=GetStr(Name)+' '+IntToStr(Index);
+ if Assigned(Symbol) and (UpcaseStr(Symbol^.GetName)<>UpcaseStr(GetStr(Name))) then
+ S:=S+' ('+Symbol^.GetName+')';
+ GetDisplayText:=S;
+end;
+
+destructor TExport.Done;
+begin
+ if Assigned(Name) then DisposeStr(Name);
+ inherited Done;
+end;
+
+constructor TImport.Init(const ALibName, AFuncName,ARealName: string; AIndex: longint);
+begin
+ inherited Init;
+ LibName:=NewStr(ALibName);
+ FuncName:=NewStr(AFuncName); RealName:=NewStr(ARealName);
+ Index:=AIndex;
+end;
+
+function TImport.GetDisplayText: string;
+var S: string;
+begin
+ S:=GetStr(RealName);
+ if Assigned(FuncName) then S:=GetStr(FuncName)+' ('+S+')';
+ if S='' then S:=IntToStr(Index);
+ S:=GetStr(LibName)+' '+S;
+ GetDisplayText:=S;
+end;
+
+destructor TImport.Done;
+begin
+ if Assigned(LibName) then DisposeStr(LibName);
+ if Assigned(FuncName) then DisposeStr(FuncName);
+ if Assigned(RealName) then DisposeStr(RealName);
+ inherited Done;
+end;
+
+function TImportCollection.At(Index: sw_Integer): PImport;
+begin
+ At:=inherited At(Index);
+end;
+
+function TImportCollection.Compare(Key1, Key2: Pointer): sw_Integer;
+var K1: PImport absolute Key1;
+ K2: PImport absolute Key2;
+ S1: string;
+ S2: string;
+ R: sw_integer;
+begin
+ if (K1^.RealName=nil) and (K2^.RealName<>nil) then R:= 1 else
+ if (K1^.RealName<>nil) and (K2^.RealName=nil) then R:=-1 else
+ if (K1^.RealName=nil) and (K2^.RealName=nil) then
+ begin
+ if K1^.Index<K2^.Index then R:=-1 else
+ if K1^.Index>K2^.Index then R:= 1 else
+ R:=0;
+ end
+ else
+ begin
+ if K1^.FuncName=nil then S1:=GetStr(K1^.RealName) else S1:=GetStr(K1^.FuncName);
+ if K2^.FuncName=nil then S2:=GetStr(K2^.RealName) else S2:=GetStr(K2^.FuncName);
+ S1:=UpcaseStr(S1); S2:=UpcaseStr(S2);
+ if S1<S2 then R:=-1 else
+ if S1>S2 then R:= 1 else
+ R:=0;
+ end;
+ Compare:=R;
+end;
+
+function TExportCollection.At(Index: sw_Integer): PExport;
+begin
+ At:=inherited At(Index);
+end;
+
+function TExportCollection.Compare(Key1, Key2: Pointer): sw_Integer;
+var K1: PExport absolute Key1;
+ K2: PExport absolute Key2;
+ S1: string;
+ S2: string;
+ R: sw_integer;
+begin
+ S1:=UpcaseStr(GetStr(K1^.Name)); S2:=UpcaseStr(GetStr(K2^.Name));
+ if S1<S2 then R:=-1 else
+ if S1>S2 then R:= 1 else
+ R:=0;
+ Compare:=R;
+end;
+
+constructor TModuleSymbol.Init(const AName, AMainSource: string);
+begin
+ inherited Init(AName,unitsym,'',nil);
+ MainSource:=NewStr(AMainSource);
+end;
+
+procedure TModuleSymbol.SetLoadedFrom(const AModuleName: string);
+begin
+ SetStr(LoadedFrom,AModuleName);
+end;
+
+procedure TModuleSymbol.AddUsedUnit(P: PSymbol);
+begin
+ if Assigned(UsedUnits)=false then
+ New(UsedUnits, Init(10,10));
+ UsedUnits^.Insert(P);
+end;
+
+procedure TModuleSymbol.AddDependentUnit(P: PSymbol);
+begin
+ if Assigned(DependentUnits)=false then
+ New(DependentUnits, Init(10,10));
+ DependentUnits^.Insert(P);
+end;
+
+procedure TModuleSymbol.AddSourceFile(const Path: string);
+begin
+ if Assigned(SourceFiles)=false then
+ New(SourceFiles, Init(10,10));
+ sourcefiles^.Insert(NewStr(Path));
+end;
+
+destructor TModuleSymbol.Done;
+begin
+ if Assigned(MainSource) then DisposeStr(MainSource);
+ if assigned(Exports_) then
+ Dispose(Exports_, Done);
+ if Assigned(Imports) then
+ Dispose(Imports, Done);
+ if Assigned(LoadedFrom) then
+ DisposeStr(LoadedFrom);
+ if Assigned(UsedUnits) then
+ begin
+ UsedUnits^.DeleteAll;
+ Dispose(UsedUnits, Done);
+ end;
+ if Assigned(DependentUnits) then
+ begin
+ DependentUnits^.DeleteAll;
+ Dispose(DependentUnits, Done);
+ end;
+ if Assigned(SourceFiles) then Dispose(SourceFiles, Done);
+ inherited Done;
+end;
+
+
+constructor TObjectSymbol.Init(AParent: PObjectSymbol; ASymbol: PSymbol);
+begin
+ inherited Init;
+ Parent:=AParent;
+ Symbol:=ASymbol;
+end;
+
+constructor TObjectSymbol.InitName(const AName: string);
+begin
+ inherited Init;
+ Name:=NewStr(AName);
+end;
+
+function TObjectSymbol.GetName: string;
+begin
+ if Name<>nil then
+ GetName:=Name^
+ else
+ GetName:=Symbol^.GetName;
+end;
+
+function TObjectSymbol.GetDescendantCount: sw_integer;
+var Count: sw_integer;
+begin
+ if Descendants=nil then Count:=0 else
+ Count:=Descendants^.Count;
+ GetDescendantCount:=Count;
+end;
+
+function TObjectSymbol.GetDescendant(Index: sw_integer): PObjectSymbol;
+begin
+ GetDescendant:=Descendants^.At(Index);
+end;
+
+procedure TObjectSymbol.AddDescendant(P: PObjectSymbol);
+begin
+ if Descendants=nil then
+ New(Descendants, Init(50,10));
+ Descendants^.Insert(P);
+end;
+
+destructor TObjectSymbol.Done;
+begin
+ if Assigned(Name) then DisposeStr(Name); Name:=nil;
+ if Assigned(Descendants) then Dispose(Descendants, Done); Descendants:=nil;
+ inherited Done;
+end;
+
+constructor TObjectSymbol.Load(var S: TStream);
+begin
+end;
+
+procedure TObjectSymbol.Store(S: TStream);
+begin
+end;
+
+{****************************************************************************
+ TSourceFile
+****************************************************************************}
+
+constructor TSourceFile.Init(ASourceFileName, AObjFileName, APPUFileName: string);
+begin
+ inherited Init;
+ SourceFileName:=NewStr(ASourceFileName);
+ ObjFileName:=NewStr(AObjFileName);
+ PPUFileName:=NewStr(APPUFileName);
+end;
+
+destructor TSourceFile.Done;
+begin
+ if assigned(SourceFileName) then DisposeStr(SourceFileName);
+ if assigned(ObjFileName) then DisposeStr(ObjFileName);
+ if assigned(PPUFileName) then DisposeStr(PPUFileName);
+ inherited Done;
+end;
+
+function TSourceFile.GetSourceFilename: string;
+begin
+ GetSourceFilename:=GetStr(SourceFileName);
+end;
+
+function TSourceFile.GetObjFileName: string;
+begin
+ GetObjFilename:=GetStr(ObjFileName);
+end;
+
+function TSourceFile.GetPPUFileName: string;
+begin
+ GetPPUFilename:=GetStr(PPUFileName);
+end;
+
+function TSourceFileCollection.At(Index: sw_Integer): PSourceFile;
+begin
+ At:=inherited At(Index);
+end;
+
+{*****************************************************************************
+ Main Routines
+*****************************************************************************}
+
+procedure DisposeBrowserCol;
+begin
+ if assigned(Modules) then
+ begin
+ dispose(Modules,Done);
+ Modules:=nil;
+ end;
+ if assigned(ModuleNames) then
+ begin
+ dispose(ModuleNames,Done);
+ ModuleNames:=nil;
+ end;
+ if assigned(TypeNames) then
+ begin
+ dispose(TypeNames,Done);
+ TypeNames:=nil;
+ end;
+ if assigned(ObjectTree) then
+ begin
+ Dispose(ObjectTree, Done);
+ ObjectTree:=nil;
+ end;
+end;
+
+
+procedure NewBrowserCol;
+begin
+ New(Modules, Init(50,50));
+ New(ModuleNames, Init(50,50));
+ New(TypeNames, Init(1000,5000));
+end;
+
+
+ procedure ProcessSymTable(OwnerSym: PSymbol; var Owner: PSymbolCollection; Table: TSymTable);
+ var I: longint;
+ Sym: TSym;
+ pd : TProcDef;
+ Symbol: PSymbol;
+ Reference: PReference;
+ inputfile : Tinputfile;
+ Ref : TRefItem;
+ DefPos : TFilePosInfo;
+ procedure SetVType(Symbol: PSymbol; VType: string);
+ begin
+ Symbol^.VType:=TypeNames^.Add(VType);
+ end;
+ procedure SetDType(Symbol: PSymbol; DType: string);
+ begin
+ Symbol^.DType:=TypeNames^.Add(DType);
+ end;
+ function GetDefinitionStr(def: tdef): string; forward;
+ function GetEnumDefStr(def: tenumdef): string;
+ var
+ Name: string;
+ esym: tenumsym;
+ i: integer;
+ begin
+ Name:='(';
+ for i := 0 to def.symtable.SymList.Count - 1 do
+ begin
+ if i>0 then
+ Name:=Name+', ';
+ Name:=Name+tenumsym(def.symtable.SymList[i]).name;
+ end;
+ Name:=Name+')';
+ GetEnumDefStr:=Name;
+ end;
+ function GetArrayDefStr(def: tarraydef): string;
+ var Name: string;
+ begin
+ Name:='array ['+IntToStr(def.lowrange)+'..'+IntToStr(def.highrange)+'] of ';
+ if assigned(def.elementdef) then
+ Name:=Name+GetDefinitionStr(def.elementdef);
+ GetArrayDefStr:=Name;
+ end;
+ function GetFileDefStr(def: tfiledef): string;
+ var Name: string;
+ begin
+ Name:='';
+ case def.filetyp of
+ ft_text : Name:='text';
+ ft_untyped : Name:='file';
+ ft_typed : Name:='file of '+GetDefinitionStr(def.typedfiledef);
+ end;
+ GetFileDefStr:=Name;
+ end;
+ function GetStringDefStr(def: tstringdef): string;
+ var Name: string;
+ begin
+ Name:='';
+ case def.stringtype of
+ st_shortstring :
+ if def.len=255 then
+ Name:='shortstring'
+ else
+ Name:='string['+IntToStr(def.len)+']';
+ st_longstring :
+ Name:='longstring';
+ st_ansistring :
+ Name:='ansistring';
+ st_widestring :
+ Name:='widestring';
+ st_unicodestring :
+ Name:='unicodestring';
+ else ;
+ end;
+ GetStringDefStr:=Name;
+ end;
+ function retdefassigned(def: tabstractprocdef): boolean;
+ var OK: boolean;
+ begin
+ OK:=false;
+ if assigned(def.returndef) then
+ if UpcaseStr(GetDefinitionStr(def.returndef))<>'VOID' then
+ OK:=true;
+ retdefassigned:=OK;
+ end;
+ function GetAbsProcParmDefStr(def: tabstractprocdef): string;
+ var Name: string;
+ dc: tabstractvarsym;
+ i,
+ Count: integer;
+ CurName: string;
+ begin
+ Name:='';
+ Count:=0;
+ for i:=0 to def.paras.count-1 do
+ begin
+ dc:=tabstractvarsym(def.paras[i]);
+ if not (vo_is_hidden_para in dc.VarOptions) then
+ begin
+ CurName:='';
+ if assigned(dc.vardef) then
+ CurName:=': '+GetDefinitionStr(dc.vardef);
+ CurName:=dc.RealName+CurName;
+ case dc.varspez of
+ vs_Value : ;
+ vs_Const : CurName:='const '+CurName;
+ vs_Var : CurName:='var '+CurName;
+ vs_Out : CurName:='out '+CurName;
+ vs_Constref : CurName:='constref '+CurName;
+ end;
+ if Count>0 then
+ CurName:='; '+CurName;
+ Name:=Name+CurName;
+ Inc(Count);
+ end;
+ end;
+ GetAbsProcParmDefStr:=Name;
+ end;
+ function GetAbsProcDefStr(def: tabstractprocdef): string;
+ var Name: string;
+ begin
+ Name:=GetAbsProcParmDefStr(def);
+ if Name<>'' then Name:='('+Name+')';
+ if retdefassigned(def) then
+ Name:='function'+Name+': '+GetDefinitionStr(def.returndef)+';'
+ else
+ Name:='procedure'+Name+';';
+ GetAbsProcDefStr:=Name;
+ end;
+ function GetProcDefStr(def: tprocdef): string;
+ var DName: string;
+ {J: integer;}
+ begin
+{ DName:='';
+ if assigned(def) then
+ begin
+ if assigned(def.parast) then
+ begin
+ with def.parast^ do
+ for J:=1 to number_symbols do
+ begin
+ if J<>1 then DName:=DName+', ';
+ ParSym:=GetsymNr(J);
+ if ParSym=nil then Break;
+ DName:=DName+ParSym^.Name;
+ end;
+ end
+ end;}
+ DName:=GetAbsProcDefStr(def);
+ GetProcDefStr:=DName;
+ end;
+ function GetProcVarDefStr(def: tprocvardef): string;
+ begin
+ GetProcVarDefStr:=GetAbsProcDefStr(def);
+ end;
+ function GetSetDefStr(def: tsetdef): string;
+ var Name: string;
+ begin
+ Name:='set of '+GetDefinitionStr(def.elementdef);
+ GetSetDefStr:=Name;
+ end;
+ function GetPointerDefStr(def: tpointerdef): string;
+ begin
+ GetPointerDefStr:='^'+GetDefinitionStr(def.pointeddef);
+ end;
+ function GetDefinitionStr(def: tdef): string;
+ var Name: string;
+ begin
+ Name:='';
+ if def<>nil then
+ begin
+ if assigned(def.typesym) then
+ Name:=def.typesym.name;
+ if Name='' then
+ case def.typ of
+ arraydef :
+ Name:=GetArrayDefStr(tarraydef(def));
+ stringdef :
+ Name:=GetStringDefStr(tstringdef(def));
+ enumdef :
+ Name:=GetEnumDefStr(tenumdef(def));
+ procdef :
+ Name:=GetProcDefStr(tprocdef(def));
+ procvardef :
+ Name:=GetProcVarDefStr(tprocvardef(def));
+ filedef :
+ Name:=GetFileDefStr(tfiledef(def));
+ setdef :
+ Name:=GetSetDefStr(tsetdef(def));
+ end;
+ end;
+ GetDefinitionStr:=Name;
+ end;
+ function GetEnumItemName(Sym: tenumsym): string;
+ var Name: string;
+ {ES: tenumsym;}
+ begin
+ Name:='';
+ if assigned(sym) and assigned(sym.definition) then
+ if assigned(sym.definition.typesym) then
+ begin
+{ ES:=sym.definition.First;
+ while (ES<>nil) and (ES^.Value<>sym.value) do
+ ES:=ES^.next;
+ if assigned(es) and (es^.value=sym.value) then
+ Name:=}
+ Name:=sym.definition.typesym.name;
+ if Name<>'' then
+ Name:=Name+'('+IntToStr(sym.value)+')';
+ end;
+ GetEnumItemName:=Name;
+ end;
+ function GetConstValueName(sym: tconstsym): string;
+ var Name: string;
+ begin
+ Name:='';
+ if Name='' then
+ case sym.consttyp of
+ constord :
+ begin
+ if sym.constdef.typ=enumdef then
+ Name:=sym.constdef.typesym.name+'('+tostr(sym.value.valueord)+')'
+ else
+ if is_boolean(sym.constdef) then
+ Name:='Longbool('+tostr(sym.value.valueord)+')'
+ else
+ if is_char(sym.constdef) or
+ is_widechar(sym.constdef) then
+ Name:=''''+chr(sym.value.valueord.svalue)+''''
+ else
+ Name:=tostr(sym.value.valueord);
+ end;
+ constresourcestring,
+ conststring :
+ Name:=''''+StrPas(pchar(sym.value.valueptr))+'''';
+ constreal:
+ Name:=FloatToStr(PBestReal(sym.value.valueptr)^);
+ constset:
+{ Name:=SetToStr(pnormalset(sym.value.valueptr)) };
+ constnil: ;
+ end;
+ GetConstValueName:=Name;
+ end;
+ procedure ProcessDefIfStruct(definition: tdef);
+ begin
+ { still led to infinite recursions
+ only useful for unamed types PM }
+ if assigned(definition) and not assigned(definition.typesym) then
+ begin
+ case definition.typ of
+ recorddef :
+ if trecorddef(definition).symtable<>Table then
+ ProcessSymTable(Symbol,Symbol^.Items,trecorddef(definition).symtable);
+ objectdef :
+ if tobjectdef(definition).symtable<>Table then
+ ProcessSymTable(Symbol,Symbol^.Items,tobjectdef(definition).symtable);
+ { leads to infinite loops !!
+ pointerdef :
+ with tpointerdef(definition)^ do
+ if assigned(definition) then
+ if assigned(definition.sym) then
+ ProcessDefIfStruct(definition.sym.definition);}
+ end;
+ end;
+ end;
+ var MemInfo: TSymbolMemInfo;
+ ObjDef: tobjectdef;
+ symidx : longint;
+ begin
+ if not Assigned(Table) then
+ Exit;
+ Symbol:=nil;
+ if Owner=nil then
+ Owner:=New(PSortedSymbolCollection, Init(10,50));
+ for symidx:=0 to Table.SymList.Count-1 do
+ begin
+ sym:=tsym(Table.SymList[symidx]);
+ New(Symbol, Init(Sym.Name,Sym.Typ,'',nil));
+ case Sym.Typ of
+ staticvarsym,
+ localvarsym,
+ absolutevarsym,
+ paravarsym :
+ begin
+ Symbol^.SetVarOptions(tabstractvarsym(sym).VarOptions);
+ Symbol^.SetVarSpez(tabstractvarsym(sym).VarSpez);
+ end;
+ end;
+ case Sym.Typ of
+ staticvarsym,
+ localvarsym,
+ paravarsym :
+ with tabstractvarsym(sym) do
+ begin
+ if (vo_is_funcret in varoptions) then
+ begin
+ if Assigned(OwnerSym) then
+ if assigned(vardef) then
+ if assigned(vardef.typesym) then
+ SetVType(OwnerSym,vardef.typesym.name)
+ else
+ SetVType(OwnerSym,GetDefinitionStr(vardef));
+ end;
+ if assigned(vardef) then
+ if assigned(vardef.typesym) then
+ SetVType(Symbol,vardef.typesym.name)
+ else
+ SetVType(Symbol,GetDefinitionStr(vardef));
+ ProcessDefIfStruct(vardef);
+ if assigned(vardef) then
+ if (vardef.typ=pointerdef) and
+ assigned(tpointerdef(vardef).pointeddef) then
+ begin
+ Symbol^.Flags:=(Symbol^.Flags or sfPointer);
+ Symbol^.RelatedTypeID:=Ptrint(tpointerdef(vardef).pointeddef);
+ end;
+ if typ=fieldvarsym then
+ MemInfo.Addr:=tfieldvarsym(sym).fieldoffset
+ else
+ begin
+ if tabstractnormalvarsym(sym).localloc.loc=LOC_REFERENCE then
+ MemInfo.Addr:=tabstractnormalvarsym(sym).localloc.reference.offset
+ else
+ MemInfo.Addr:=0;
+ end;
+ if assigned(vardef) and (vardef.typ=arraydef) then
+ begin
+ if tarraydef(vardef).highrange<tarraydef(vardef).lowrange then
+ MemInfo.Size:=-1
+ else
+ MemInfo.Size:=getsize;
+ end
+ else
+ MemInfo.Size:=getsize;
+ { this is not completely correct... }
+ if assigned(vardef) then
+ MemInfo.PushSize:=paramanager.push_size(varspez,vardef,pocall_default)
+ else
+ begin
+ { This can happen, why? }
+ MemInfo.PushSize:=0;
+ end;
+ Symbol^.SetMemInfo(MemInfo);
+ end;
+ fieldvarsym :
+ with tfieldvarsym(sym) do
+ begin
+ if assigned(vardef) and (vardef.typ=arraydef) then
+ begin
+ if tarraydef(vardef).highrange<tarraydef(vardef).lowrange then
+ MemInfo.Size:=-1
+ else
+ MemInfo.Size:=getsize;
+ end
+ else
+ MemInfo.Size:=getsize;
+ Symbol^.SetMemInfo(MemInfo);
+ end;
+ constsym :
+ SetDType(Symbol,GetConstValueName(tconstsym(sym)));
+ enumsym :
+ if assigned(tenumsym(sym).definition) then
+ SetDType(Symbol,GetEnumItemName(tenumsym(sym)));
+ unitsym :
+ begin
+ { ProcessSymTable(Symbol^.Items,tunitsym(sym).unitsymtable);}
+ end;
+ syssym :
+{ if assigned(Table.Name) then
+ if Table.Name^='SYSTEM' then}
+ begin
+ Symbol^.Params:=TypeNames^.Add('...');
+ end;
+ procsym :
+ begin
+ for i:=0 to tprocsym(sym).ProcdefList.Count-1 do
+ begin
+ if i>0 then
+ begin
+ if Assigned(Symbol) then
+ Owner^.Insert(Symbol);
+ New(Symbol, Init(Sym.Name,Sym.Typ,'',nil));
+ end;
+ with tprocsym(sym) do
+ begin
+ pd:=tprocdef(procdeflist[i]);
+ if assigned(pd) then
+ begin
+ ProcessSymTable(Symbol,Symbol^.Items,pd.parast);
+ if assigned(pd.parast) then
+ begin
+ Symbol^.Params:=TypeNames^.Add(
+ GetAbsProcParmDefStr(pd));
+ end
+ else { param-definition is NOT assigned }
+ if assigned(Table.Name) and
+ (Table.Name^='SYSTEM') then
+ begin
+ Symbol^.Params:=TypeNames^.Add('...');
+ end;
+ if cs_local_browser in current_settings.moduleswitches then
+ begin
+ if assigned(pd.localst) and
+ (pd.localst.symtabletype<>staticsymtable) then
+ ProcessSymTable(Symbol,Symbol^.Items,pd.localst);
+ end;
+ end;
+ end;
+ end;
+ end;
+ typesym :
+ begin
+ with ttypesym(sym) do
+ if assigned(typedef) then
+ begin
+ Symbol^.TypeID:=Ptrint(typedef);
+ case typedef.typ of
+ arraydef :
+ SetDType(Symbol,GetArrayDefStr(tarraydef(typedef)));
+ enumdef :
+ SetDType(Symbol,GetEnumDefStr(tenumdef(typedef)));
+ procdef :
+ SetDType(Symbol,GetProcDefStr(tprocdef(typedef)));
+ procvardef :
+ SetDType(Symbol,GetProcVarDefStr(tprocvardef(typedef)));
+ objectdef :
+ with tobjectdef(typedef) do
+ begin
+ ObjDef:=childof;
+ if ObjDef<>nil then
+ Symbol^.RelatedTypeID:=Ptrint(ObjDef);{TypeNames^.Add(S);}
+ Symbol^.Flags:=(Symbol^.Flags or sfObject);
+ if tobjectdef(typedef).objecttype=odt_class then
+ Symbol^.Flags:=(Symbol^.Flags or sfClass);
+ ProcessSymTable(Symbol,Symbol^.Items,tobjectdef(typedef).symtable);
+ end;
+ recorddef :
+ begin
+ Symbol^.Flags:=(Symbol^.Flags or sfRecord);
+ ProcessSymTable(Symbol,Symbol^.Items,trecorddef(typedef).symtable);
+ end;
+ pointerdef :
+ begin
+ Symbol^.Flags:=(Symbol^.Flags or sfPointer);
+ Symbol^.RelatedTypeID:=Ptrint(tpointerdef(typedef).pointeddef);{TypeNames^.Add(S);}
+ SetDType(Symbol,GetPointerDefStr(tpointerdef(typedef)));
+ end;
+
+ filedef :
+ SetDType(Symbol,GetFileDefStr(tfiledef(typedef)));
+ setdef :
+ SetDType(Symbol,GetSetDefStr(tsetdef(typedef)));
+ end;
+ end;
+ end;
+ end;
+ if assigned(sym) then
+ begin
+ DefPos:=tstoredsym(sym).FileInfo;
+ inputfile:=get_source_file(defpos.moduleindex,defpos.fileindex);
+ if Assigned(inputfile) and Assigned(inputfile.name) then
+ begin
+ New(Reference, Init(ModuleNames^.Add(inputfile.name^),
+ DefPos.line,DefPos.column));
+ Symbol^.References^.Insert(Reference);
+ end;
+ end;
+ if assigned(Symbol) and assigned(sym.RefList) then
+ begin
+ Ref:=TRefItem(tstoredsym(sym).RefList.First);
+ while assigned(Ref) do
+ begin
+ inputfile:=get_source_file(ref.refinfo.moduleindex,ref.refinfo.fileindex);
+ if Assigned(inputfile) and Assigned(inputfile.name) then
+ begin
+ New(Reference, Init(ModuleNames^.Add(inputfile.name^),
+ ref.refinfo.line,ref.refinfo.column));
+ Symbol^.References^.Insert(Reference);
+ end;
+ Ref:=TRefItem(Ref.next);
+ end;
+ end;
+ if Assigned(Symbol) then
+ begin
+ (* if not Owner^.Search(Symbol,J) then *)
+ Owner^.Insert(Symbol)
+ (*else
+ begin
+ Dispose(Symbol,done);
+ Symbol:=nil;
+ end;*)
+ end;
+ end;
+ end;
+
+function SearchModule(const Name: string): PModuleSymbol;
+function Match(P: PModuleSymbol): boolean;
+begin
+ Match:=CompareText(P^.GetName,Name)=0;
+end;
+var P: PModuleSymbol;
+begin
+ P:=nil;
+ if Assigned(Modules) then
+ P:=Modules^.FirstThat(@Match);
+ SearchModule:=P;
+end;
+
+procedure CreateBrowserCol;
+var
+ path,module,
+ name,msource : string;
+
+ T: TSymTable;
+ UnitS,PM: PModuleSymbol;
+ hp : tmodule;
+ puu: tused_unit;
+ pdu: tdependent_unit;
+ pif: tinputfile;
+begin
+ DisposeBrowserCol;
+ if (cs_browser in current_settings.moduleswitches) then
+ NewBrowserCol;
+ hp:=tmodule(loaded_units.first);
+ if (cs_browser in current_settings.moduleswitches) then
+ while assigned(hp) do
+ begin
+ if hp.is_unit then
+ t:=tsymtable(hp.globalsymtable)
+ else
+ t:=tsymtable(hp.localsymtable);
+ if assigned(t) then
+ begin
+ name:=GetStr(T.Name);
+ msource:=GetStr(hp.mainsource);
+ New(UnitS, Init(Name,msource));
+ if Assigned(hp.loaded_from) then
+ if assigned(hp.loaded_from.globalsymtable) then
+ UnitS^.SetLoadedFrom(tsymtable(hp.loaded_from.globalsymtable).name^);
+{ pimportlist(current_module^.imports^.first);}
+
+ if assigned(hp.sourcefiles) then
+ begin
+ pif:=hp.sourcefiles.files;
+ while (pif<>nil) do
+ begin
+ path:=GetStr(pif.path);
+ name:=GetStr(pif.name);
+ UnitS^.AddSourceFile(path+name);
+ pif:=pif.next;
+ end;
+ end;
+
+ Modules^.Insert(UnitS);
+ ProcessSymTable(UnitS,UnitS^.Items,T);
+ if hp.is_unit then
+ if cs_local_browser in current_settings.moduleswitches then
+ begin
+ t:=tsymtable(hp.localsymtable);
+ if assigned(t) then
+ ProcessSymTable(UnitS,UnitS^.Items,T);
+ end;
+ end;
+ hp:=tmodule(hp.next);
+ end;
+
+ hp:=tmodule(loaded_units.first);
+ if (cs_browser in current_settings.moduleswitches) then
+ while assigned(hp) do
+ begin
+ t:=tsymtable(hp.globalsymtable);
+ if assigned(t) then
+ begin
+ name:=GetStr(T.Name);
+ UnitS:=SearchModule(Name);
+ puu:=tused_unit(hp.used_units.first);
+ while (puu<>nil) do
+ begin
+ module:=GetStr(puu.u.modulename);
+ PM:=SearchModule(module);
+ if Assigned(PM) then
+ UnitS^.AddUsedUnit(PM);
+ puu:=tused_unit(puu.next);
+ end;
+ pdu:=tdependent_unit(hp.dependent_units.first);
+ while (pdu<>nil) do
+ begin
+ name:=GetStr(tsymtable(pdu.u.globalsymtable).name);
+ PM:=SearchModule(Name);
+ if Assigned(PM) then
+ UnitS^.AddDependentUnit(PM);
+ pdu:=tdependent_unit(pdu.next);
+ end;
+ end;
+ hp:=tmodule(hp.next);
+ end;
+
+ if (cs_browser in current_settings.moduleswitches) then
+ BuildObjectInfo;
+ { can allways be done
+ needed to know when recompilation of sources is necessary }
+ BuildSourceList;
+end;
+
+procedure BuildObjectInfo;
+var C,D: PIDSortedSymbolCollection;
+ E : PCollection;
+ ObjectC: PObjectSymbolCollection;
+ ObjectsSymbol: PObjectSymbol;
+procedure InsertSymbolCollection(Symbols: PSymbolCollection);
+var I: sw_integer;
+ P: PSymbol;
+begin
+ for I:=0 to Symbols^.Count-1 do
+ begin
+ P:=Symbols^.At(I);
+ if (P^.Flags and (sfObject or sfClass))<>0 then
+ C^.Insert(P);
+ if (P^.typ=typesym) then
+ D^.Insert(P);
+ if (P^.typ in [staticvarsym,localvarsym,paravarsym]) and ((P^.flags and sfPointer)<>0) then
+ E^.Insert(P);
+ if P^.Items<>nil then
+ InsertSymbolCollection(P^.Items);
+ end;
+end;
+function SearchObjectForSym(O: PSymbol): PObjectSymbol;
+var I: sw_integer;
+ OS,P: PObjectSymbol;
+begin
+ P:=nil;
+ for I:=0 to ObjectC^.Count-1 do
+ begin
+ OS:=ObjectC^.At(I);
+ if OS^.Symbol=O then
+ begin P:=OS; Break; end;
+ end;
+ SearchObjectForSym:=P;
+end;
+procedure BuildTree;
+var I: sw_integer;
+ Symbol: PSymbol;
+ Parent,OS: PObjectSymbol;
+begin
+ I:=0;
+ while (I<C^.Count) do
+ begin
+ Symbol:=C^.At(I);
+ if Symbol^.Ancestor=nil then
+ Parent:=ObjectsSymbol
+ else
+ Parent:=SearchObjectForSym(Symbol^.Ancestor);
+ if Parent<>nil then
+ begin
+ New(OS, Init(Parent, Symbol));
+ Parent^.AddDescendant(OS);
+ ObjectC^.Insert(OS);
+ C^.AtDelete(I);
+ end
+ else
+ Inc(I);
+ end;
+end;
+var Pass: integer;
+ I: sw_integer;
+ P: PSymbol;
+begin
+ New(C, Init(1000,5000));
+ New(D, Init(1000,5000));
+ New(E, Init(1000,5000));
+ InsertSymbolCollection(Modules);
+
+ { --- Resolve ancestor<->descendant references --- }
+ for I:=0 to C^.Count-1 do
+ begin
+ P:=C^.At(I);
+ if P^.RelatedTypeID<>0 then
+ P^.Ancestor:=C^.SearchSymbolByID(P^.RelatedTypeID);
+ end;
+
+ { --- Resolve pointer definition references --- }
+ for I:=0 to D^.Count-1 do
+ begin
+ P:=D^.At(I);
+ if P^.RelatedTypeID<>0 then
+ P^.Ancestor:=D^.SearchSymbolByID(P^.RelatedTypeID);
+ end;
+
+ { --- Resolve pointer var definition references --- }
+ for I:=0 to E^.Count-1 do
+ begin
+ P:=PSymbol(E^.At(I));
+ if P^.RelatedTypeID<>0 then
+ P^.Ancestor:=D^.SearchSymbolByID(P^.RelatedTypeID);
+ end;
+
+ { E is not needed anymore }
+ E^.DeleteAll;
+ Dispose(E,Done);
+
+ { D is not needed anymore }
+ D^.DeleteAll;
+ Dispose(D,Done);
+
+ { --- Build object tree --- }
+ if assigned(ObjectTree) then
+ Dispose(ObjectTree, Done);
+ New(ObjectsSymbol, InitName('Objects'));
+ ObjectTree:=ObjectsSymbol;
+
+ New(ObjectC, Init(C^.Count,100));
+
+ Pass:=0;
+ if C^.Count>0 then
+ repeat
+ BuildTree;
+ Inc(Pass);
+ until (C^.Count=0) or (Pass>20); { more than 20 levels ? - then there must be a bug }
+
+ ObjectC^.DeleteAll; Dispose(ObjectC, Done);
+ C^.DeleteAll; Dispose(C, Done);
+end;
+
+function SearchObjectForSymbol(O: PSymbol): PObjectSymbol;
+function ScanObjectCollection(Parent: PObjectSymbol): PObjectSymbol;
+var I: sw_integer;
+ OS,P: PObjectSymbol;
+ ObjectC: PObjectSymbolCollection;
+begin
+ P:=nil;
+ if Parent<>nil then
+ if Parent^.Descendants<>nil then
+ begin
+ ObjectC:=Parent^.Descendants;
+ for I:=0 to ObjectC^.Count-1 do
+ begin
+ OS:=ObjectC^.At(I);
+ if OS^.Symbol=O then
+ begin P:=OS; Break; end;
+ if OS^.Descendants<>nil then
+ begin
+ P:=ScanObjectCollection(OS);
+ if P<>nil then Break;
+ end;
+ end;
+ end;
+ ScanObjectCollection:=P;
+end;
+begin
+ SearchObjectForSymbol:=ScanObjectCollection(ObjectTree);
+end;
+
+procedure BuildSourceList;
+var m: tmodule;
+ s: tinputfile;
+ p: pstring;
+ ppu,obj: string;
+ source: string;
+begin
+ if Assigned(SourceFiles) then
+ begin
+ Dispose(SourceFiles, Done);
+ SourceFiles:=nil;
+ end;
+ if assigned(loaded_units.first) then
+ begin
+ New(SourceFiles, Init(50,10));
+ m:=tmodule(loaded_units.first);
+ while assigned(m) do
+ begin
+ obj:=ExpandFileName(m.objfilename^);
+ ppu:=''; source:='';
+ if m.is_unit then
+ ppu:=ExpandFileName(m.ppufilename^);
+ if (m.is_unit=false) and (m.islibrary=false) then
+ ppu:=ExpandFileName(m.exefilename^);
+ if assigned(m.sourcefiles) then
+ begin
+ s:=m.sourcefiles.files;
+ while assigned(s) do
+ begin
+ source:='';
+ p:=s.path;
+ if assigned(p) then
+ source:=source+p^;
+ p:=s.name;
+ if assigned(p) then
+ source:=source+p^;
+ source:=ExpandFileName(source);
+
+ sourcefiles^.Insert(New(PSourceFile, Init(source,obj,ppu)));
+ s:=s.ref_next;
+ end;
+ end;
+ m:=tmodule(m.next);
+ end;
+ end;
+end;
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+
+
+var
+ oldexit : pointer;
+
+procedure browcol_exit;
+begin
+ exitproc:=oldexit;
+ DisposeBrowserCol;
+ if Assigned(SourceFiles) then
+ begin
+ Dispose(SourceFiles, Done);
+ SourceFiles:=nil;
+ end;
+ if assigned(ObjectTree) then
+ begin
+ Dispose(ObjectTree, Done);
+ ObjectTree:=nil;
+ end;
+end;
+
+
+procedure InitBrowserCol;
+begin
+end;
+
+
+procedure DoneBrowserCol;
+begin
+ { nothing, the collections are freed in the exitproc - ??? }
+ { nothing? then why do we've this routine for ? IMHO, either we should
+ remove this, or it should destroy the browser info when it's called. - BG }
+end;
+
+type
+ PPointerXRef = ^TPointerXRef;
+ TPointerXRef = record
+ PtrValue : pointer;
+ DataPtr : pointer;
+ end;
+
+ PPointerDictionary = ^TPointerDictionary;
+ TPointerDictionary = object(TSortedCollection)
+ function At(Index: sw_Integer): PPointerXRef;
+ function Compare(Key1, Key2: Pointer): sw_Integer; virtual;
+ procedure FreeItem(Item: Pointer); virtual;
+ function SearchXRef(PtrValue: pointer): PPointerXRef;
+ function AddPtr(PtrValue, DataPtr: pointer): PPointerXRef;
+ procedure Resolve(var P);
+ end;
+
+function NewPointerXRef(APtrValue, ADataPtr: pointer): PPointerXRef;
+var P: PPointerXRef;
+begin
+ New(P); FillChar(P^,SizeOf(P^),0);
+ with P^ do begin PtrValue:=APtrValue; DataPtr:=ADataPtr; end;
+ NewPointerXRef:=P;
+end;
+
+procedure DisposePointerXRef(P: PPointerXRef);
+begin
+ if Assigned(P) then Dispose(P);
+end;
+
+function TPointerDictionary.At(Index: sw_Integer): PPointerXRef;
+begin
+ At:=inherited At(Index);
+end;
+
+function TPointerDictionary.Compare(Key1, Key2: Pointer): sw_Integer;
+var K1: PPointerXRef absolute Key1;
+ K2: PPointerXRef absolute Key2;
+ R: integer;
+begin
+ if PtrUInt(K1^.PtrValue)<PtrUInt(K2^.PtrValue) then R:=-1 else
+ if PtrUInt(K1^.PtrValue)>PtrUInt(K2^.PtrValue) then R:= 1 else
+ R:=0;
+ Compare:=R;
+end;
+
+procedure TPointerDictionary.FreeItem(Item: Pointer);
+begin
+ if Assigned(Item) then DisposePointerXRef(Item);
+end;
+
+function TPointerDictionary.SearchXRef(PtrValue: pointer): PPointerXRef;
+var P: PPointerXRef;
+ T: TPointerXRef;
+ Index: sw_integer;
+begin
+ T.PtrValue:=PtrValue;
+ if Search(@T,Index)=false then P:=nil else
+ P:=At(Index);
+ SearchXRef:=P;
+end;
+
+function TPointerDictionary.AddPtr(PtrValue, DataPtr: pointer): PPointerXRef;
+var P: PPointerXRef;
+begin
+ P:=SearchXRef(PtrValue);
+ if P=nil then
+ begin
+ P:=NewPointerXRef(PtrValue,DataPtr);
+ Insert(P);
+{$ifdef DEBUG}
+ end
+ else
+ begin
+ if P^.DataPtr<>DataPtr then
+ InternalError(987654);
+{$endif DEBUG}
+ end;
+ AddPtr:=P;
+end;
+
+procedure TPointerDictionary.Resolve(var P);
+var X: PPointerXRef;
+ V: pointer;
+begin
+ Move(P,V,SizeOf(V));
+ X:=SearchXRef(V);
+ if X=nil then V:=nil else
+ V:=X^.DataPtr;
+ Move(V,P,SizeOf(V));
+end;
+
+procedure ReadPointers(S: PStream; C: PCollection; D: PPointerDictionary);
+var W,I: sw_integer;
+ P: pointer;
+begin
+ S^.Read(W,SizeOf(W));
+ for I:=0 to W-1 do
+ begin
+ S^.Read(P,SizeOf(P));
+ D^.AddPtr(P,C^.At(I));
+ end;
+end;
+
+function LoadBrowserCol(S: PStream): boolean;
+var PD: PPointerDictionary;
+procedure FixupPointers;
+procedure FixupReference(P: PReference);
+begin
+ PD^.Resolve(P^.FileName);
+end;
+procedure FixupSymbol(P: PSymbol);
+var I: sw_integer;
+begin
+ PD^.Resolve(P^.DType);
+ PD^.Resolve(P^.VType);
+ PD^.Resolve(P^.Params);
+ if Assigned(P^.References) then
+ with P^.References^ do
+ for I:=0 to Count-1 do
+ FixupReference(At(I));
+ if Assigned(P^.Items) then
+ with P^.Items^ do
+ for I:=0 to Count-1 do
+ FixupSymbol(At(I));
+end;
+begin
+ Modules^.ForEach(@FixupSymbol);
+end;
+procedure ReadSymbolPointers(P: PSymbol);
+var I: sw_integer;
+ PV: pointer;
+begin
+ S^.Read(PV, SizeOf(PV));
+ PD^.AddPtr(PV,P);
+ if Assigned(P^.Items) then
+ with P^.Items^ do
+ for I:=0 to Count-1 do
+ ReadSymbolPointers(At(I));
+end;
+begin
+ DisposeBrowserCol;
+
+ New(ModuleNames, Load(S^));
+ New(TypeNames, Load(S^));
+ New(Modules, Load(S^));
+
+ New(PD, Init(4000,1000));
+ ReadPointers(S,ModuleNames,PD);
+ ReadPointers(S,TypeNames,PD);
+ ReadPointers(S,Modules,PD);
+ Modules^.ForEach(@ReadSymbolPointers);
+ FixupPointers;
+ Dispose(PD, Done);
+
+ BuildObjectInfo;
+ LoadBrowserCol:=(S^.Status=stOK);
+end;
+
+procedure StorePointers(S: PStream; C: PCollection);
+var W,I: sw_integer;
+ P: pointer;
+begin
+ W:=C^.Count;
+ S^.Write(W,SizeOf(W));
+ for I:=0 to W-1 do
+ begin
+ P:=C^.At(I);
+ S^.Write(P,SizeOf(P));
+ end;
+end;
+
+function StoreBrowserCol(S: PStream) : boolean;
+procedure WriteSymbolPointers(P: PSymbol);
+var I: sw_integer;
+begin
+ S^.Write(P, SizeOf(P));
+ if Assigned(P^.Items) then
+ with P^.Items^ do
+ for I:=0 to Count-1 do
+ WriteSymbolPointers(At(I));
+end;
+begin
+ ModuleNames^.Store(S^);
+ TypeNames^.Store(S^);
+ Modules^.Store(S^);
+
+ StorePointers(S,ModuleNames);
+ StorePointers(S,TypeNames);
+ StorePointers(S,Modules);
+ Modules^.ForEach(@WriteSymbolPointers);
+ StoreBrowserCol:=(S^.Status=stOK);
+end;
+
+procedure RegisterSymbols;
+begin
+ RegisterType(RModuleNameCollection);
+ RegisterType(RTypeNameCollection);
+ RegisterType(RReference);
+ RegisterType(RSymbol);
+ RegisterType(RObjectSymbol);
+ RegisterType(RSymbolCollection);
+ RegisterType(RSortedSymbolCollection);
+ RegisterType(RIDSortedSymbolCollection);
+ RegisterType(RObjectSymbolCollection);
+ RegisterType(RReferenceCollection);
+ RegisterType(RModuleSymbol);
+end;
+
+begin
+ oldexit:=exitproc;
+ exitproc:=@browcol_exit;
+end.
diff --git a/closures/compiler/bsdcompile b/closures/compiler/bsdcompile
new file mode 100644
index 0000000000..1260d53da6
--- /dev/null
+++ b/closures/compiler/bsdcompile
@@ -0,0 +1,3 @@
+#!/bin/sh
+ppc386 -OG3p3 -Ch8000000 -dI386 -dGDB -dBROWSERLOG -Sg pp.pas -a -s -g %1 %2 %3 %4 %5 %6 %7 %8 %9
+
diff --git a/closures/compiler/catch.pas b/closures/compiler/catch.pas
new file mode 100644
index 0000000000..002d559280
--- /dev/null
+++ b/closures/compiler/catch.pas
@@ -0,0 +1,87 @@
+{
+ Copyright (c) 1998-2002 by Michael Van Canneyt
+
+ Unit to catch segmentation faults and Ctrl-C and exit gracefully
+ under linux and go32v2
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ *********************************************************************
+}
+Unit catch;
+
+{$i fpcdefs.inc}
+
+{$ifdef DEBUG}
+ {$define NOCATCH}
+{$endif DEBUG}
+
+interface
+uses
+{ you cannot safely raise an exception inside a signal handler on any OS,
+ and on darwin this even often crashes
+}
+{$if defined(unix) and not defined(darwin) }
+ {$ifndef darwin}
+ {$define has_signal}
+ BaseUnix,Unix,
+ {$endif}
+{$endif}
+{$ifdef go32v2}
+{$define has_signal}
+ dpmiexcp,
+{$endif}
+{$ifdef watcom}
+ {$define has_signal}
+ dpmiexcp,
+{$endif}
+ verbose;
+
+{$ifdef has_signal}
+Var
+ NewSignal,
+ OldSigInt : SignalHandler;
+{$endif}
+
+Implementation
+
+uses
+ comphook;
+
+{$ifdef has_signal}
+{$ifdef unix}
+Procedure CatchSignal(Sig : Longint);cdecl;
+{$else}
+Function CatchSignal(Sig : longint):longint; cdecl;
+{$endif}
+begin
+ case Sig of
+ SIGINT :
+ raise EControlCAbort.Create;
+ end;
+{$ifndef unix}
+ CatchSignal:=0;
+{$endif}
+end;
+{$endif def has_signal}
+
+begin
+{$ifndef nocatch}
+ {$ifdef has_signal}
+ NewSignal:=SignalHandler(@CatchSignal);
+ OldSigInt:={$ifdef Unix}fpSignal{$else}Signal{$endif}(SIGINT,NewSignal);
+ {$endif}
+{$endif nocatch}
+end.
diff --git a/closures/compiler/ccharset.pas b/closures/compiler/ccharset.pas
new file mode 100644
index 0000000000..bb6073c8a6
--- /dev/null
+++ b/closures/compiler/ccharset.pas
@@ -0,0 +1,294 @@
+{
+ This file is part of the Free Pascal run time library.
+ Copyright (c) 2000 by Florian Klaempfl
+ member of the Free Pascal development team.
+
+ This unit implements several classes for charset conversions
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+{$mode objfpc}
+unit ccharset;
+
+ interface
+
+ type
+ tunicodechar = word;
+ tunicodestring = ^tunicodechar;
+
+ tcsconvert = class
+ // !!!!!!1constructor create;
+ end;
+
+ tunicodecharmappingflag = (umf_noinfo,umf_leadbyte,umf_undefined,
+ umf_unused);
+
+ punicodecharmapping = ^tunicodecharmapping;
+ tunicodecharmapping = record
+ unicode : tunicodechar;
+ flag : tunicodecharmappingflag;
+ reserved : byte;
+ end;
+
+ punicodemap = ^tunicodemap;
+ tunicodemap = record
+ cpname : string[20];
+ cp : word;
+ map : punicodecharmapping;
+ lastchar : longint;
+ next : punicodemap;
+ internalmap : boolean;
+ end;
+
+ tcp2unicode = class(tcsconvert)
+ end;
+
+ const
+ DefaultSystemCodePage = 437;
+
+ function loadunicodemapping(const cpname,f : string; cp :word) : punicodemap;
+ procedure registermapping(p : punicodemap);
+ function getmap(const s : string) : punicodemap;
+ function getmap(cp : word) : punicodemap;
+ function mappingavailable(const s : string) : boolean;
+ function mappingavailable(cp :word) : boolean;
+ function getunicode(c : char;p : punicodemap) : tunicodechar;
+ function getascii(c : tunicodechar;p : punicodemap) : string;
+
+ implementation
+
+ var
+ mappings : punicodemap;
+
+ function loadunicodemapping(const cpname,f : string; cp :word) : punicodemap;
+
+ var
+ data : punicodecharmapping;
+ datasize : longint;
+ t : text;
+ s,hs : string;
+ scanpos,charpos,unicodevalue : longint;
+ code : word;
+ flag : tunicodecharmappingflag;
+ p : punicodemap;
+ lastchar : longint;
+
+ begin
+ lastchar:=-1;
+ loadunicodemapping:=nil;
+ datasize:=256;
+ getmem(data,sizeof(tunicodecharmapping)*datasize);
+ assign(t,f);
+ {$I-}
+ reset(t);
+ {$I+}
+ if ioresult<>0 then
+ begin
+ freemem(data,sizeof(tunicodecharmapping)*datasize);
+ exit;
+ end;
+ while not(eof(t)) do
+ begin
+ readln(t,s);
+ if (s[1]='0') and (s[2]='x') then
+ begin
+ flag:=umf_unused;
+ scanpos:=3;
+ hs:='$';
+ while s[scanpos] in ['0'..'9','A'..'F','a'..'f'] do
+ begin
+ hs:=hs+s[scanpos];
+ inc(scanpos);
+ end;
+ val(hs,charpos,code);
+ if code<>0 then
+ begin
+ freemem(data,sizeof(tunicodecharmapping)*datasize);
+ close(t);
+ exit;
+ end;
+ while not(s[scanpos] in ['0','#']) do
+ inc(scanpos);
+ if s[scanpos]='#' then
+ begin
+ { special char }
+ unicodevalue:=$ffff;
+ hs:=copy(s,scanpos,length(s)-scanpos+1);
+ if hs='#DBCS LEAD BYTE' then
+ flag:=umf_leadbyte;
+ end
+ else
+ begin
+ { C hex prefix }
+ inc(scanpos,2);
+ hs:='$';
+ while s[scanpos] in ['0'..'9','A'..'F','a'..'f'] do
+ begin
+ hs:=hs+s[scanpos];
+ inc(scanpos);
+ end;
+ val(hs,unicodevalue,code);
+ if code<>0 then
+ begin
+ freemem(data,sizeof(tunicodecharmapping)*datasize);
+ close(t);
+ exit;
+ end;
+ if charpos>datasize then
+ begin
+ { allocate 1024 bytes more because }
+ { if we need more than 256 entries it's }
+ { probably a mbcs with a lot of }
+ { entries }
+ datasize:=charpos+1024;
+ reallocmem(data,sizeof(tunicodecharmapping)*datasize);
+ end;
+ flag:=umf_noinfo;
+ end;
+ data[charpos].flag:=flag;
+ data[charpos].unicode:=unicodevalue;
+ if charpos>lastchar then
+ lastchar:=charpos;
+ end;
+ end;
+ close(t);
+ new(p);
+ p^.lastchar:=lastchar;
+ p^.cpname:=cpname;
+ p^.cp:=cp;
+ p^.internalmap:=false;
+ p^.next:=nil;
+ p^.map:=data;
+ loadunicodemapping:=p;
+ end;
+
+ procedure registermapping(p : punicodemap);
+
+ begin
+ p^.next:=mappings;
+ mappings:=p;
+ end;
+
+ function getmap(const s : string) : punicodemap;
+
+ var
+ hp : punicodemap;
+
+ const
+ mapcache : string = '';
+ mapcachep : punicodemap = nil;
+
+ begin
+ if (mapcache=s) and assigned(mapcachep) and (mapcachep^.cpname=s) then
+ begin
+ getmap:=mapcachep;
+ exit;
+ end;
+ hp:=mappings;
+ while assigned(hp) do
+ begin
+ if hp^.cpname=s then
+ begin
+ getmap:=hp;
+ mapcache:=s;
+ mapcachep:=hp;
+ exit;
+ end;
+ hp:=hp^.next;
+ end;
+ getmap:=nil;
+ end;////////
+
+ function getmap(cp : word) : punicodemap;
+
+ var
+ hp : punicodemap;
+
+ const
+ mapcache : word = 0;
+ mapcachep : punicodemap = nil;
+
+ begin
+ if (mapcache=cp) and assigned(mapcachep) and (mapcachep^.cp=cp) then
+ begin
+ getmap:=mapcachep;
+ exit;
+ end;
+ hp:=mappings;
+ while assigned(hp) do
+ begin
+ if hp^.cp=cp then
+ begin
+ getmap:=hp;
+ mapcache:=cp;
+ mapcachep:=hp;
+ exit;
+ end;
+ hp:=hp^.next;
+ end;
+ getmap:=nil;
+ end;
+
+ function mappingavailable(const s : string) : boolean;
+
+ begin
+ mappingavailable:=getmap(s)<>nil;
+ end;
+
+ function mappingavailable(cp : word) : boolean;
+
+ begin
+ mappingavailable:=getmap(cp)<>nil;
+ end;
+
+ function getunicode(c : char;p : punicodemap) : tunicodechar;
+
+ begin
+ if ord(c)<=p^.lastchar then
+ getunicode:=p^.map[ord(c)].unicode
+ else
+ getunicode:=0;
+ end;
+
+ function getascii(c : tunicodechar;p : punicodemap) : string;
+
+ var
+ i : longint;
+
+ begin
+ { at least map to '?' }
+ getascii:=#63;
+ for i:=0 to p^.lastchar do
+ if p^.map[i].unicode=c then
+ begin
+ if i<256 then
+ getascii:=chr(i)
+ else
+ getascii:=chr(i div 256)+chr(i mod 256);
+ exit;
+ end;
+ end;
+
+ var
+ hp : punicodemap;
+
+initialization
+ mappings:=nil;
+finalization
+ while assigned(mappings) do
+ begin
+ hp:=mappings^.next;
+ if not(mappings^.internalmap) then
+ begin
+ freemem(mappings^.map);
+ dispose(mappings);
+ end;
+ mappings:=hp;
+ end;
+end.
diff --git a/closures/compiler/cclasses.pas b/closures/compiler/cclasses.pas
new file mode 100644
index 0000000000..7df8bc326c
--- /dev/null
+++ b/closures/compiler/cclasses.pas
@@ -0,0 +1,3035 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl and Peter Vreman
+
+ This module provides some basic classes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit cclasses;
+
+{$i fpcdefs.inc}
+
+{$ifndef VER2_0}
+ {$define CCLASSESINLINE}
+{$endif}
+
+interface
+
+ uses
+{$IFNDEF USE_FAKE_SYSUTILS}
+ SysUtils,
+{$ELSE}
+ fksysutl,
+{$ENDIF}
+ globtype,
+ CUtils,CStreams;
+
+{********************************************
+ TMemDebug
+********************************************}
+
+ type
+ tmemdebug = class
+ private
+ totalmem,
+ startmem : int64;
+ infostr : string[40];
+ public
+ constructor Create(const s:string);
+ destructor Destroy;override;
+ procedure show;
+ procedure start;
+ procedure stop;
+ end;
+
+{*******************************************************
+ TFPList (From rtl/objpas/classes/classesh.inc)
+********************************************************}
+
+const
+ SListIndexError = 'List index exceeds bounds (%d)';
+ SListCapacityError = 'The maximum list capacity is reached (%d)';
+ SListCapacityPower2Error = 'The capacity has to be a power of 2, but is set to %d';
+ SListCountError = 'List count too large (%d)';
+type
+ EListError = class(Exception);
+
+const
+ MaxListSize = Maxint div 16;
+type
+ PPointerList = ^TPointerList;
+ TPointerList = array[0..MaxListSize - 1] of Pointer;
+ TListSortCompare = function (Item1, Item2: Pointer): Integer;
+ TListCallback = procedure(data,arg:pointer) of object;
+ TListStaticCallback = procedure(data,arg:pointer);
+
+ TFPList = class(TObject)
+ private
+ FList: PPointerList;
+ FCount: Integer;
+ FCapacity: Integer;
+ protected
+ function Get(Index: Integer): Pointer;
+ procedure Put(Index: Integer; Item: Pointer);
+ procedure SetCapacity(NewCapacity: Integer);
+ procedure SetCount(NewCount: Integer);
+ Procedure RaiseIndexError(Index : Integer);
+ public
+ destructor Destroy; override;
+ function Add(Item: Pointer): Integer;
+ procedure Clear;
+ procedure Delete(Index: Integer);
+ class procedure Error(const Msg: string; Data: PtrInt);
+ procedure Exchange(Index1, Index2: Integer);
+ function Expand: TFPList;
+ function Extract(item: Pointer): Pointer;
+ function First: Pointer;
+ function IndexOf(Item: Pointer): Integer;
+ procedure Insert(Index: Integer; Item: Pointer);
+ function Last: Pointer;
+ procedure Move(CurIndex, NewIndex: Integer);
+ procedure Assign(Obj:TFPList);
+ function Remove(Item: Pointer): Integer;
+ procedure Pack;
+ procedure Sort(Compare: TListSortCompare);
+ procedure ForEachCall(proc2call:TListCallback;arg:pointer);
+ procedure ForEachCall(proc2call:TListStaticCallback;arg:pointer);
+ property Capacity: Integer read FCapacity write SetCapacity;
+ property Count: Integer read FCount write SetCount;
+ property Items[Index: Integer]: Pointer read Get write Put; default;
+ property List: PPointerList read FList;
+ end;
+
+
+{*******************************************************
+ TFPObjectList (From fcl/inc/contnrs.pp)
+********************************************************}
+
+ TObjectListCallback = procedure(data:TObject;arg:pointer) of object;
+ TObjectListStaticCallback = procedure(data:TObject;arg:pointer);
+
+ TFPObjectList = class(TObject)
+ private
+ FFreeObjects : Boolean;
+ FList: TFPList;
+ function GetCount: integer; {$ifdef CCLASSESINLINE}inline;{$endif}
+ procedure SetCount(const AValue: integer);
+ protected
+ function GetItem(Index: Integer): TObject; {$ifdef CCLASSESINLINE}inline;{$endif}
+ procedure SetItem(Index: Integer; AObject: TObject);
+ procedure SetCapacity(NewCapacity: Integer); {$ifdef CCLASSESINLINE}inline;{$endif}
+ function GetCapacity: integer; {$ifdef CCLASSESINLINE}inline;{$endif}
+ public
+ constructor Create;
+ constructor Create(FreeObjects : Boolean);
+ destructor Destroy; override;
+ procedure Clear;
+ function Add(AObject: TObject): Integer; {$ifdef CCLASSESINLINE}inline;{$endif}
+ procedure Delete(Index: Integer);
+ procedure Exchange(Index1, Index2: Integer); {$ifdef CCLASSESINLINE}inline;{$endif}
+ function Expand: TFPObjectList;{$ifdef CCLASSESINLINE}inline;{$endif}
+ function Extract(Item: TObject): TObject; {$ifdef CCLASSESINLINE}inline;{$endif}
+ function Remove(AObject: TObject): Integer;
+ function IndexOf(AObject: TObject): Integer; {$ifdef CCLASSESINLINE}inline;{$endif}
+ function FindInstanceOf(AClass: TClass; AExact: Boolean; AStartAt: Integer): Integer;
+ procedure Insert(Index: Integer; AObject: TObject); {$ifdef CCLASSESINLINE}inline;{$endif}
+ function First: TObject; {$ifdef CCLASSESINLINE}inline;{$endif}
+ function Last: TObject; {$ifdef CCLASSESINLINE}inline;{$endif}
+ procedure Move(CurIndex, NewIndex: Integer); {$ifdef CCLASSESINLINE}inline;{$endif}
+ procedure Assign(Obj:TFPObjectList);
+ procedure Pack; {$ifdef CCLASSESINLINE}inline;{$endif}
+ procedure Sort(Compare: TListSortCompare); {$ifdef CCLASSESINLINE}inline;{$endif}
+ procedure ForEachCall(proc2call:TObjectListCallback;arg:pointer); {$ifdef CCLASSESINLINE}inline;{$endif}
+ procedure ForEachCall(proc2call:TObjectListStaticCallback;arg:pointer); {$ifdef CCLASSESINLINE}inline;{$endif}
+ property Capacity: Integer read GetCapacity write SetCapacity;
+ property Count: Integer read GetCount write SetCount;
+ property OwnsObjects: Boolean read FFreeObjects write FFreeObjects;
+ property Items[Index: Integer]: TObject read GetItem write SetItem; default;
+ property List: TFPList read FList;
+ end;
+
+type
+ THashItem=record
+ HashValue : LongWord;
+ StrIndex : Integer;
+ NextIndex : Integer;
+ Data : Pointer;
+ end;
+ PHashItem=^THashItem;
+
+const
+ MaxHashListSize = Maxint div 16;
+ MaxHashStrSize = Maxint;
+ MaxHashTableSize = Maxint div 4;
+ MaxItemsPerHash = 3;
+
+type
+ PHashItemList = ^THashItemList;
+ THashItemList = array[0..MaxHashListSize - 1] of THashItem;
+ PHashTable = ^THashTable;
+ THashTable = array[0..MaxHashTableSize - 1] of Integer;
+
+ TFPHashList = class(TObject)
+ private
+ { ItemList }
+ FHashList : PHashItemList;
+ FCount,
+ FCapacity : Integer;
+ FCapacityMask: LongWord;
+ { Hash }
+ FHashTable : PHashTable;
+ FHashCapacity : Integer;
+ { Strings }
+ FStrs : PChar;
+ FStrCount,
+ FStrCapacity : Integer;
+ function InternalFind(AHash:LongWord;const AName:shortstring;out PrevIndex:Integer):Integer;
+ protected
+ function Get(Index: Integer): Pointer;
+ procedure Put(Index: Integer; Item: Pointer);
+ procedure SetCapacity(NewCapacity: Integer);
+ procedure SetCount(NewCount: Integer);
+ Procedure RaiseIndexError(Index : Integer);
+ function AddStr(const s:shortstring): Integer;
+ procedure AddToHashTable(Index: Integer);
+ procedure StrExpand(MinIncSize:Integer);
+ procedure SetStrCapacity(NewCapacity: Integer);
+ procedure SetHashCapacity(NewCapacity: Integer);
+ procedure ReHash;
+ public
+ constructor Create;
+ destructor Destroy; override;
+ function Add(const AName:shortstring;Item: Pointer): Integer;
+ procedure Clear;
+ function NameOfIndex(Index: Integer): ShortString;
+ function HashOfIndex(Index: Integer): LongWord;
+ function GetNextCollision(Index: Integer): Integer;
+ procedure Delete(Index: Integer);
+ class procedure Error(const Msg: string; Data: PtrInt);
+ function Expand: TFPHashList;
+ function Extract(item: Pointer): Pointer;
+ function IndexOf(Item: Pointer): Integer;
+ function Find(const AName:shortstring): Pointer;
+ function FindIndexOf(const AName:shortstring): Integer;
+ function FindWithHash(const AName:shortstring;AHash:LongWord): Pointer;
+ function Rename(const AOldName,ANewName:shortstring): Integer;
+ function Remove(Item: Pointer): Integer;
+ procedure Pack;
+ procedure ShowStatistics;
+ procedure ForEachCall(proc2call:TListCallback;arg:pointer);
+ procedure ForEachCall(proc2call:TListStaticCallback;arg:pointer);
+ property Capacity: Integer read FCapacity write SetCapacity;
+ property Count: Integer read FCount write SetCount;
+ property Items[Index: Integer]: Pointer read Get write Put; default;
+ property List: PHashItemList read FHashList;
+ property Strs: PChar read FStrs;
+ end;
+
+
+{*******************************************************
+ TFPHashObjectList (From fcl/inc/contnrs.pp)
+********************************************************}
+
+ TFPHashObjectList = class;
+
+ { TFPHashObject }
+
+ TFPHashObject = class
+ private
+ FOwner : TFPHashObjectList;
+ FCachedStr : pshortstring;
+ FStrIndex : Integer;
+ procedure InternalChangeOwner(HashObjectList:TFPHashObjectList;const s:shortstring);
+ protected
+ function GetName:shortstring;virtual;
+ function GetHash:Longword;virtual;
+ public
+ constructor CreateNotOwned;
+ constructor Create(HashObjectList:TFPHashObjectList;const s:shortstring);
+ procedure ChangeOwner(HashObjectList:TFPHashObjectList);
+ procedure ChangeOwnerAndName(HashObjectList:TFPHashObjectList;const s:shortstring); {$ifdef CCLASSESINLINE}inline;{$endif}
+ procedure Rename(const ANewName:shortstring);
+ property Name:shortstring read GetName;
+ property Hash:Longword read GetHash;
+ end;
+
+ TFPHashObjectList = class(TObject)
+ private
+ FFreeObjects : Boolean;
+ FHashList: TFPHashList;
+ function GetCount: integer; {$ifdef CCLASSESINLINE}inline;{$endif}
+ procedure SetCount(const AValue: integer);
+ protected
+ function GetItem(Index: Integer): TObject; {$ifdef CCLASSESINLINE}inline;{$endif}
+ procedure SetItem(Index: Integer; AObject: TObject);
+ procedure SetCapacity(NewCapacity: Integer); {$ifdef CCLASSESINLINE}inline;{$endif}
+ function GetCapacity: integer; {$ifdef CCLASSESINLINE}inline;{$endif}
+ public
+ constructor Create(FreeObjects : boolean = True);
+ destructor Destroy; override;
+ procedure Clear;
+ function Add(const AName:shortstring;AObject: TObject): Integer; {$ifdef CCLASSESINLINE}inline;{$endif}
+ function NameOfIndex(Index: Integer): ShortString; {$ifdef CCLASSESINLINE}inline;{$endif}
+ function HashOfIndex(Index: Integer): LongWord; {$ifdef CCLASSESINLINE}inline;{$endif}
+ function GetNextCollision(Index: Integer): Integer; {$ifdef CCLASSESINLINE}inline;{$endif}
+ procedure Delete(Index: Integer);
+ function Expand: TFPHashObjectList; {$ifdef CCLASSESINLINE}inline;{$endif}
+ function Extract(Item: TObject): TObject; {$ifdef CCLASSESINLINE}inline;{$endif}
+ function Remove(AObject: TObject): Integer;
+ function IndexOf(AObject: TObject): Integer; {$ifdef CCLASSESINLINE}inline;{$endif}
+ function Find(const s:shortstring): TObject; {$ifdef CCLASSESINLINE}inline;{$endif}
+ function FindIndexOf(const s:shortstring): Integer; {$ifdef CCLASSESINLINE}inline;{$endif}
+ function FindWithHash(const AName:shortstring;AHash:LongWord): Pointer;
+ function Rename(const AOldName,ANewName:shortstring): Integer; {$ifdef CCLASSESINLINE}inline;{$endif}
+ function FindInstanceOf(AClass: TClass; AExact: Boolean; AStartAt: Integer): Integer;
+ procedure Pack; {$ifdef CCLASSESINLINE}inline;{$endif}
+ procedure ShowStatistics; {$ifdef CCLASSESINLINE}inline;{$endif}
+ procedure ForEachCall(proc2call:TObjectListCallback;arg:pointer); {$ifdef CCLASSESINLINE}inline;{$endif}
+ procedure ForEachCall(proc2call:TObjectListStaticCallback;arg:pointer); {$ifdef CCLASSESINLINE}inline;{$endif}
+ property Capacity: Integer read GetCapacity write SetCapacity;
+ property Count: Integer read GetCount write SetCount;
+ property OwnsObjects: Boolean read FFreeObjects write FFreeObjects;
+ property Items[Index: Integer]: TObject read GetItem write SetItem; default;
+ property List: TFPHashList read FHashList;
+ end;
+
+
+{********************************************
+ TLinkedList
+********************************************}
+
+ type
+ TLinkedListItem = class
+ public
+ Previous,
+ Next : TLinkedListItem;
+ Constructor Create;
+ Destructor Destroy;override;
+ Function GetCopy:TLinkedListItem;virtual;
+ end;
+
+ TLinkedListItemClass = class of TLinkedListItem;
+
+ TLinkedList = class
+ private
+ FCount : integer;
+ FFirst,
+ FLast : TLinkedListItem;
+ FNoClear : boolean;
+ public
+ constructor Create;
+ destructor Destroy;override;
+ { true when the List is empty }
+ function Empty:boolean; {$ifdef CCLASSESINLINE}inline;{$endif}
+ { deletes all Items }
+ procedure Clear;
+ { inserts an Item }
+ procedure Insert(Item:TLinkedListItem);
+ { inserts an Item before Loc }
+ procedure InsertBefore(Item,Loc : TLinkedListItem);
+ { inserts an Item after Loc }
+ procedure InsertAfter(Item,Loc : TLinkedListItem);virtual;
+ { concats an Item }
+ procedure Concat(Item:TLinkedListItem);
+ { deletes an Item }
+ procedure Remove(Item:TLinkedListItem);
+ { Gets First Item }
+ function GetFirst:TLinkedListItem;
+ { Gets last Item }
+ function GetLast:TLinkedListItem;
+ { inserts another List at the begin and make this List empty }
+ procedure insertList(p : TLinkedList);
+ { inserts another List before the provided item and make this List empty }
+ procedure insertListBefore(Item:TLinkedListItem;p : TLinkedList);
+ { inserts another List after the provided item and make this List empty }
+ procedure insertListAfter(Item:TLinkedListItem;p : TLinkedList);
+ { concats another List at the end and make this List empty }
+ procedure concatList(p : TLinkedList);
+ { concats another List at the start and makes a copy
+ the list is ordered in reverse.
+ }
+ procedure insertListcopy(p : TLinkedList);
+ { concats another List at the end and makes a copy }
+ procedure concatListcopy(p : TLinkedList);
+ property First:TLinkedListItem read FFirst;
+ property Last:TLinkedListItem read FLast;
+ property Count:Integer read FCount;
+ property NoClear:boolean write FNoClear;
+ end;
+
+{********************************************
+ TCmdStrList
+********************************************}
+
+ { string containerItem }
+ TCmdStrListItem = class(TLinkedListItem)
+ FPStr : TCmdStr;
+ public
+ constructor Create(const s:TCmdStr);
+ destructor Destroy;override;
+ function GetCopy:TLinkedListItem;override;
+ function Str:TCmdStr; {$ifdef CCLASSESINLINE}inline;{$endif}
+ end;
+
+ { string container }
+ TCmdStrList = class(TLinkedList)
+ private
+ FDoubles : boolean; { if this is set to true, doubles are allowed }
+ public
+ constructor Create;
+ constructor Create_No_Double;
+ { inserts an Item }
+ procedure Insert(const s:TCmdStr);
+ { concats an Item }
+ procedure Concat(const s:TCmdStr);
+ { deletes an Item }
+ procedure Remove(const s:TCmdStr);
+ { Gets First Item }
+ function GetFirst:TCmdStr;
+ { Gets last Item }
+ function GetLast:TCmdStr;
+ { true if string is in the container, compare case sensitive }
+ function FindCase(const s:TCmdStr):TCmdStrListItem;
+ { true if string is in the container }
+ function Find(const s:TCmdStr):TCmdStrListItem;
+ { inserts an item }
+ procedure InsertItem(item:TCmdStrListItem); {$ifdef CCLASSESINLINE}inline;{$endif}
+ { concats an item }
+ procedure ConcatItem(item:TCmdStrListItem); {$ifdef CCLASSESINLINE}inline;{$endif}
+ property Doubles:boolean read FDoubles write FDoubles;
+ end;
+
+
+{********************************************
+ DynamicArray
+********************************************}
+
+ type
+ { can't use sizeof(integer) because it crashes gdb }
+ tdynamicblockdata=array[0..1024*1024-1] of byte;
+
+ pdynamicblock = ^tdynamicblock;
+ tdynamicblock = record
+ pos,
+ size,
+ used : longword;
+ Next : pdynamicblock;
+ data : tdynamicblockdata;
+ end;
+
+ const
+ dynamicblockbasesize = sizeof(tdynamicblock)-sizeof(tdynamicblockdata);
+ mindynamicblocksize = 8*sizeof(pointer);
+
+ type
+ tdynamicarray = class
+ private
+ FPosn : longword;
+ FPosnblock : pdynamicblock;
+ FCurrBlocksize,
+ FMaxBlocksize : longword;
+ FFirstblock,
+ FLastblock : pdynamicblock;
+ procedure grow;
+ public
+ constructor Create(Ablocksize:longword);
+ destructor Destroy;override;
+ procedure reset;
+ function size:longword;
+ procedure align(i:longword);
+ procedure seek(i:longword);
+ function read(var d;len:longword):longword;
+ procedure write(const d;len:longword);
+ procedure writestr(const s:string); {$ifdef CCLASSESINLINE}inline;{$endif}
+ procedure readstream(f:TCStream;maxlen:longword);
+ procedure writestream(f:TCStream);
+ property CurrBlockSize : longword read FCurrBlocksize;
+ property FirstBlock : PDynamicBlock read FFirstBlock;
+ property Pos : longword read FPosn;
+ end;
+
+
+{******************************************************************
+ THashSet (keys not limited to ShortString, no indexed access)
+*******************************************************************}
+
+ PPHashSetItem = ^PHashSetItem;
+ PHashSetItem = ^THashSetItem;
+ THashSetItem = record
+ Next: PHashSetItem;
+ Key: Pointer;
+ KeyLength: Integer;
+ HashValue: LongWord;
+ Data: TObject;
+ end;
+
+ THashSet = class(TObject)
+ private
+ FCount: LongWord;
+ FOwnsObjects: Boolean;
+ FOwnsKeys: Boolean;
+ function Lookup(Key: Pointer; KeyLen: Integer; var Found: Boolean;
+ CanCreate: Boolean): PHashSetItem;
+ procedure Resize(NewCapacity: LongWord);
+ protected
+ FBucket: PPHashSetItem;
+ FBucketCount: LongWord;
+ class procedure FreeItem(item:PHashSetItem); virtual;
+ class function SizeOfItem: Integer; virtual;
+ public
+ constructor Create(InitSize: Integer; OwnKeys, OwnObjects: Boolean);
+ destructor Destroy; override;
+ procedure Clear;
+ { finds an entry by key }
+ function Find(Key: Pointer; KeyLen: Integer): PHashSetItem;
+ { finds an entry, creates one if not exists }
+ function FindOrAdd(Key: Pointer; KeyLen: Integer;
+ var Found: Boolean): PHashSetItem;
+ { finds an entry, creates one if not exists }
+ function FindOrAdd(Key: Pointer; KeyLen: Integer): PHashSetItem;
+ { returns Data by given Key }
+ function Get(Key: Pointer; KeyLen: Integer): TObject;
+ { removes an entry, returns False if entry wasn't there }
+ function Remove(Entry: PHashSetItem): Boolean;
+ property Count: LongWord read FCount;
+ end;
+
+{******************************************************************
+ TTagHasSet
+*******************************************************************}
+ PPTagHashSetItem = ^PTagHashSetItem;
+ PTagHashSetItem = ^TTagHashSetItem;
+ TTagHashSetItem = record
+ Next: PTagHashSetItem;
+ Key: Pointer;
+ KeyLength: Integer;
+ HashValue: LongWord;
+ Data: TObject;
+ Tag: LongWord;
+ end;
+
+ TTagHashSet = class(THashSet)
+ private
+ function Lookup(Key: Pointer; KeyLen: Integer; Tag: LongWord; var Found: Boolean;
+ CanCreate: Boolean): PTagHashSetItem;
+ protected
+ class procedure FreeItem(item:PHashSetItem); override;
+ class function SizeOfItem: Integer; override;
+ public
+ { finds an entry by key }
+ function Find(Key: Pointer; KeyLen: Integer; Tag: LongWord): PTagHashSetItem; reintroduce;
+ { finds an entry, creates one if not exists }
+ function FindOrAdd(Key: Pointer; KeyLen: Integer; Tag: LongWord;
+ var Found: Boolean): PTagHashSetItem; reintroduce;
+ { finds an entry, creates one if not exists }
+ function FindOrAdd(Key: Pointer; KeyLen: Integer; Tag: LongWord): PTagHashSetItem; reintroduce;
+ { returns Data by given Key }
+ function Get(Key: Pointer; KeyLen: Integer; Tag: LongWord): TObject; reintroduce;
+ end;
+
+
+{******************************************************************
+ tbitset
+*******************************************************************}
+
+ tbitset = class
+ private
+ fdata: pbyte;
+ fdatasize: longint;
+ public
+ constructor create(initsize: longint);
+ constructor create_bytesize(bytesize: longint);
+ destructor destroy; override;
+ procedure clear;
+ procedure grow(nsize: longint);
+ { sets a bit }
+ procedure include(index: longint);
+ { clears a bit }
+ procedure exclude(index: longint);
+ { finds an entry, creates one if not exists }
+ function isset(index: longint): boolean;
+
+ procedure addset(aset: tbitset);
+ procedure subset(aset: tbitset);
+
+ property data: pbyte read fdata;
+ property datasize: longint read fdatasize;
+ end;
+
+
+ function FPHash(const s:shortstring):LongWord;
+ function FPHash(P: PChar; Len: Integer): LongWord;
+ function FPHash(P: PChar; Len: Integer; Tag: LongWord): LongWord;
+
+
+implementation
+
+{*****************************************************************************
+ Memory debug
+*****************************************************************************}
+
+ constructor tmemdebug.create(const s:string);
+ begin
+ infostr:=s;
+ totalmem:=0;
+ Start;
+ end;
+
+
+ procedure tmemdebug.start;
+
+ var
+ status : TFPCHeapStatus;
+
+ begin
+ status:=GetFPCHeapStatus;
+ startmem:=status.CurrHeapUsed;
+ end;
+
+
+ procedure tmemdebug.stop;
+ var
+ status : TFPCHeapStatus;
+ begin
+ if startmem<>0 then
+ begin
+ status:=GetFPCHeapStatus;
+ inc(TotalMem,startmem-status.CurrHeapUsed);
+ startmem:=0;
+ end;
+ end;
+
+
+ destructor tmemdebug.destroy;
+ begin
+ Stop;
+ show;
+ end;
+
+
+ procedure tmemdebug.show;
+ begin
+ write('memory [',infostr,'] ');
+ if TotalMem>0 then
+ writeln(DStr(TotalMem shr 10),' Kb released')
+ else
+ writeln(DStr((-TotalMem) shr 10),' Kb allocated');
+ end;
+
+
+{*****************************************************************************
+ TFPObjectList (Copied from rtl/objpas/classes/lists.inc)
+*****************************************************************************}
+
+procedure TFPList.RaiseIndexError(Index : Integer);
+begin
+ Error(SListIndexError, Index);
+end;
+
+function TFPList.Get(Index: Integer): Pointer;
+begin
+ If (Index < 0) or (Index >= FCount) then
+ RaiseIndexError(Index);
+ Result:=FList^[Index];
+end;
+
+procedure TFPList.Put(Index: Integer; Item: Pointer);
+begin
+ if (Index < 0) or (Index >= FCount) then
+ RaiseIndexError(Index);
+ Flist^[Index] := Item;
+end;
+
+function TFPList.Extract(item: Pointer): Pointer;
+var
+ i : Integer;
+begin
+ result := nil;
+ i := IndexOf(item);
+ if i >= 0 then
+ begin
+ Result := item;
+ FList^[i] := nil;
+ Delete(i);
+ end;
+end;
+
+procedure TFPList.SetCapacity(NewCapacity: Integer);
+begin
+ If (NewCapacity < FCount) or (NewCapacity > MaxListSize) then
+ Error (SListCapacityError, NewCapacity);
+ if NewCapacity = FCapacity then
+ exit;
+ ReallocMem(FList, SizeOf(Pointer)*NewCapacity);
+ FCapacity := NewCapacity;
+end;
+
+procedure TFPList.SetCount(NewCount: Integer);
+begin
+ if (NewCount < 0) or (NewCount > MaxListSize)then
+ Error(SListCountError, NewCount);
+ If NewCount > FCount then
+ begin
+ If NewCount > FCapacity then
+ SetCapacity(NewCount);
+ If FCount < NewCount then
+ FillChar(Flist^[FCount], (NewCount-FCount) * sizeof(Pointer), 0);
+ end;
+ FCount := Newcount;
+end;
+
+destructor TFPList.Destroy;
+begin
+ Self.Clear;
+ inherited Destroy;
+end;
+
+function TFPList.Add(Item: Pointer): Integer;
+begin
+ if FCount = FCapacity then
+ Self.Expand;
+ FList^[FCount] := Item;
+ Result := FCount;
+ inc(FCount);
+end;
+
+procedure TFPList.Clear;
+begin
+ if Assigned(FList) then
+ begin
+ SetCount(0);
+ SetCapacity(0);
+ FList := nil;
+ end;
+end;
+
+procedure TFPList.Delete(Index: Integer);
+begin
+ If (Index<0) or (Index>=FCount) then
+ Error (SListIndexError, Index);
+ dec(FCount);
+ System.Move (FList^[Index+1], FList^[Index], (FCount - Index) * SizeOf(Pointer));
+ { Shrink the list if appropriate }
+ if (FCapacity > 256) and (FCount < FCapacity shr 2) then
+ begin
+ FCapacity := FCapacity shr 1;
+ ReallocMem(FList, SizeOf(Pointer) * FCapacity);
+ end;
+end;
+
+class procedure TFPList.Error(const Msg: string; Data: PtrInt);
+begin
+ Raise EListError.CreateFmt(Msg,[Data]) at get_caller_addr(get_frame);
+end;
+
+procedure TFPList.Exchange(Index1, Index2: Integer);
+var
+ Temp : Pointer;
+begin
+ If ((Index1 >= FCount) or (Index1 < 0)) then
+ Error(SListIndexError, Index1);
+ If ((Index2 >= FCount) or (Index2 < 0)) then
+ Error(SListIndexError, Index2);
+ Temp := FList^[Index1];
+ FList^[Index1] := FList^[Index2];
+ FList^[Index2] := Temp;
+end;
+
+function TFPList.Expand: TFPList;
+var
+ IncSize : Longint;
+begin
+ Result := Self;
+ if FCount < FCapacity then
+ exit;
+ IncSize := sizeof(ptrint)*2;
+ if FCapacity > 127 then
+ Inc(IncSize, FCapacity shr 2)
+ else if FCapacity > sizeof(ptrint)*4 then
+ Inc(IncSize, FCapacity shr 1)
+ else if FCapacity >= sizeof(ptrint) then
+ inc(IncSize,sizeof(ptrint));
+ SetCapacity(FCapacity + IncSize);
+end;
+
+function TFPList.First: Pointer;
+begin
+ If FCount<>0 then
+ Result := Items[0]
+ else
+ Result := Nil;
+end;
+
+function TFPList.IndexOf(Item: Pointer): Integer;
+var
+ psrc : PPointer;
+ Index : Integer;
+begin
+ Result:=-1;
+ psrc:=@FList^[0];
+ For Index:=0 To FCount-1 Do
+ begin
+ if psrc^=Item then
+ begin
+ Result:=Index;
+ exit;
+ end;
+ inc(psrc);
+ end;
+end;
+
+procedure TFPList.Insert(Index: Integer; Item: Pointer);
+begin
+ if (Index < 0) or (Index > FCount )then
+ Error(SlistIndexError, Index);
+ iF FCount = FCapacity then Self.Expand;
+ if Index<FCount then
+ System.Move(Flist^[Index], Flist^[Index+1], (FCount - Index) * SizeOf(Pointer));
+ FList^[Index] := Item;
+ FCount := FCount + 1;
+end;
+
+function TFPList.Last: Pointer;
+begin
+ If FCount<>0 then
+ Result := Items[FCount - 1]
+ else
+ Result := nil
+end;
+
+procedure TFPList.Move(CurIndex, NewIndex: Integer);
+var
+ Temp : Pointer;
+begin
+ if ((CurIndex < 0) or (CurIndex > Count - 1)) then
+ Error(SListIndexError, CurIndex);
+ if (NewINdex < 0) then
+ Error(SlistIndexError, NewIndex);
+ Temp := FList^[CurIndex];
+ FList^[CurIndex] := nil;
+ Self.Delete(CurIndex);
+ Self.Insert(NewIndex, nil);
+ FList^[NewIndex] := Temp;
+end;
+
+function TFPList.Remove(Item: Pointer): Integer;
+begin
+ Result := IndexOf(Item);
+ If Result <> -1 then
+ Self.Delete(Result);
+end;
+
+procedure TFPList.Pack;
+var
+ NewCount,
+ i : integer;
+ pdest,
+ psrc : PPointer;
+begin
+ NewCount:=0;
+ psrc:=@FList^[0];
+ pdest:=psrc;
+ For I:=0 To FCount-1 Do
+ begin
+ if assigned(psrc^) then
+ begin
+ pdest^:=psrc^;
+ inc(pdest);
+ inc(NewCount);
+ end;
+ inc(psrc);
+ end;
+ FCount:=NewCount;
+end;
+
+
+Procedure QuickSort(FList: PPointerList; L, R : Longint;Compare: TListSortCompare);
+var
+ I, J, P: Longint;
+ PItem, Q : Pointer;
+begin
+ repeat
+ I := L;
+ J := R;
+ P := (L + R) div 2;
+ repeat
+ PItem := FList^[P];
+ while Compare(PItem, FList^[i]) > 0 do
+ I := I + 1;
+ while Compare(PItem, FList^[J]) < 0 do
+ J := J - 1;
+ If I <= J then
+ begin
+ Q := FList^[I];
+ Flist^[I] := FList^[J];
+ FList^[J] := Q;
+ if P = I then
+ P := J
+ else if P = J then
+ P := I;
+ I := I + 1;
+ J := J - 1;
+ end;
+ until I > J;
+ if L < J then
+ QuickSort(FList, L, J, Compare);
+ L := I;
+ until I >= R;
+end;
+
+procedure TFPList.Sort(Compare: TListSortCompare);
+begin
+ if Not Assigned(FList) or (FCount < 2) then exit;
+ QuickSort(Flist, 0, FCount-1, Compare);
+end;
+
+procedure TFPList.Assign(Obj: TFPList);
+var
+ i: Integer;
+begin
+ Clear;
+ for I := 0 to Obj.Count - 1 do
+ Add(Obj[i]);
+end;
+
+
+procedure TFPList.ForEachCall(proc2call:TListCallback;arg:pointer);
+var
+ i : integer;
+ p : pointer;
+begin
+ For I:=0 To Count-1 Do
+ begin
+ p:=FList^[i];
+ if assigned(p) then
+ proc2call(p,arg);
+ end;
+end;
+
+
+procedure TFPList.ForEachCall(proc2call:TListStaticCallback;arg:pointer);
+var
+ i : integer;
+ p : pointer;
+begin
+ For I:=0 To Count-1 Do
+ begin
+ p:=FList^[i];
+ if assigned(p) then
+ proc2call(p,arg);
+ end;
+end;
+
+
+{*****************************************************************************
+ TFPObjectList (Copied from rtl/objpas/classes/lists.inc)
+*****************************************************************************}
+
+constructor TFPObjectList.Create(FreeObjects : boolean);
+begin
+ Create;
+ FFreeObjects := Freeobjects;
+end;
+
+destructor TFPObjectList.Destroy;
+begin
+ if (FList <> nil) then
+ begin
+ Clear;
+ FList.Destroy;
+ end;
+ inherited Destroy;
+end;
+
+procedure TFPObjectList.Clear;
+var
+ i: integer;
+begin
+ if FFreeObjects then
+ for i := 0 to FList.Count - 1 do
+ TObject(FList[i]).Free;
+ FList.Clear;
+end;
+
+constructor TFPObjectList.Create;
+begin
+ inherited Create;
+ FList := TFPList.Create;
+ FFreeObjects := True;
+end;
+
+function TFPObjectList.GetCount: integer;
+begin
+ Result := FList.Count;
+end;
+
+procedure TFPObjectList.SetCount(const AValue: integer);
+begin
+ if FList.Count <> AValue then
+ FList.Count := AValue;
+end;
+
+function TFPObjectList.GetItem(Index: Integer): TObject;
+begin
+ Result := TObject(FList[Index]);
+end;
+
+procedure TFPObjectList.SetItem(Index: Integer; AObject: TObject);
+begin
+ if OwnsObjects then
+ TObject(FList[Index]).Free;
+ FList[index] := AObject;
+end;
+
+procedure TFPObjectList.SetCapacity(NewCapacity: Integer);
+begin
+ FList.Capacity := NewCapacity;
+end;
+
+function TFPObjectList.GetCapacity: integer;
+begin
+ Result := FList.Capacity;
+end;
+
+function TFPObjectList.Add(AObject: TObject): Integer;
+begin
+ Result := FList.Add(AObject);
+end;
+
+procedure TFPObjectList.Delete(Index: Integer);
+begin
+ if OwnsObjects then
+ TObject(FList[Index]).Free;
+ FList.Delete(Index);
+end;
+
+procedure TFPObjectList.Exchange(Index1, Index2: Integer);
+begin
+ FList.Exchange(Index1, Index2);
+end;
+
+function TFPObjectList.Expand: TFPObjectList;
+begin
+ FList.Expand;
+ Result := Self;
+end;
+
+function TFPObjectList.Extract(Item: TObject): TObject;
+begin
+ Result := TObject(FList.Extract(Item));
+end;
+
+function TFPObjectList.Remove(AObject: TObject): Integer;
+begin
+ Result := IndexOf(AObject);
+ if (Result <> -1) then
+ begin
+ if OwnsObjects then
+ TObject(FList[Result]).Free;
+ FList.Delete(Result);
+ end;
+end;
+
+function TFPObjectList.IndexOf(AObject: TObject): Integer;
+begin
+ Result := FList.IndexOf(Pointer(AObject));
+end;
+
+function TFPObjectList.FindInstanceOf(AClass: TClass; AExact: Boolean; AStartAt : Integer): Integer;
+var
+ I : Integer;
+begin
+ I:=AStartAt;
+ Result:=-1;
+ If AExact then
+ while (I<Count) and (Result=-1) do
+ If Items[i].ClassType=AClass then
+ Result:=I
+ else
+ Inc(I)
+ else
+ while (I<Count) and (Result=-1) do
+ If Items[i].InheritsFrom(AClass) then
+ Result:=I
+ else
+ Inc(I);
+end;
+
+procedure TFPObjectList.Insert(Index: Integer; AObject: TObject);
+begin
+ FList.Insert(Index, Pointer(AObject));
+end;
+
+procedure TFPObjectList.Move(CurIndex, NewIndex: Integer);
+begin
+ FList.Move(CurIndex, NewIndex);
+end;
+
+procedure TFPObjectList.Assign(Obj: TFPObjectList);
+var
+ i: Integer;
+begin
+ Clear;
+ for I := 0 to Obj.Count - 1 do
+ Add(Obj[i]);
+end;
+
+procedure TFPObjectList.Pack;
+begin
+ FList.Pack;
+end;
+
+procedure TFPObjectList.Sort(Compare: TListSortCompare);
+begin
+ FList.Sort(Compare);
+end;
+
+function TFPObjectList.First: TObject;
+begin
+ Result := TObject(FList.First);
+end;
+
+function TFPObjectList.Last: TObject;
+begin
+ Result := TObject(FList.Last);
+end;
+
+procedure TFPObjectList.ForEachCall(proc2call:TObjectListCallback;arg:pointer);
+begin
+ FList.ForEachCall(TListCallBack(proc2call),arg);
+end;
+
+procedure TFPObjectList.ForEachCall(proc2call:TObjectListStaticCallback;arg:pointer);
+begin
+ FList.ForEachCall(TListStaticCallBack(proc2call),arg);
+end;
+
+
+{*****************************************************************************
+ TFPHashList
+*****************************************************************************}
+
+ function FPHash(const s:shortstring):LongWord;
+ Var
+ p,pmax : pchar;
+ begin
+{$push}
+{$q-,r-}
+ result:=0;
+ p:=@s[1];
+ pmax:=@s[length(s)+1];
+ while (p<pmax) do
+ begin
+ result:=LongWord(LongInt(result shl 5) - LongInt(result)) xor LongWord(P^);
+ inc(p);
+ end;
+{$pop}
+ end;
+
+ function FPHash(P: PChar; Len: Integer): LongWord;
+ Var
+ pmax : pchar;
+ begin
+{$push}
+{$q-,r-}
+ result:=0;
+ pmax:=p+len;
+ while (p<pmax) do
+ begin
+ result:=LongWord(LongInt(result shl 5) - LongInt(result)) xor LongWord(P^);
+ inc(p);
+ end;
+{$pop}
+ end;
+
+ function FPHash(P: PChar; Len: Integer; Tag: LongWord): LongWord;
+ Var
+ pmax : pchar;
+ begin
+{$push}
+{$q-,r-}
+ result:=Tag;
+ pmax:=p+len;
+ while (p<pmax) do
+ begin
+ result:=LongWord(LongInt(result shl 5) - LongInt(result)) xor LongWord(P^);
+ inc(p);
+ end;
+{$pop}
+ end;
+
+procedure TFPHashList.RaiseIndexError(Index : Integer);
+begin
+ Error(SListIndexError, Index);
+end;
+
+
+function TFPHashList.Get(Index: Integer): Pointer;
+begin
+ If (Index < 0) or (Index >= FCount) then
+ RaiseIndexError(Index);
+ Result:=FHashList^[Index].Data;
+end;
+
+
+procedure TFPHashList.Put(Index: Integer; Item: Pointer);
+begin
+ if (Index < 0) or (Index >= FCount) then
+ RaiseIndexError(Index);
+ FHashList^[Index].Data:=Item;
+end;
+
+
+function TFPHashList.NameOfIndex(Index: Integer): shortstring;
+begin
+ If (Index < 0) or (Index >= FCount) then
+ RaiseIndexError(Index);
+ with FHashList^[Index] do
+ begin
+ if StrIndex>=0 then
+ Result:=PShortString(@FStrs[StrIndex])^
+ else
+ Result:='';
+ end;
+end;
+
+
+function TFPHashList.HashOfIndex(Index: Integer): LongWord;
+begin
+ If (Index < 0) or (Index >= FCount) then
+ RaiseIndexError(Index);
+ Result:=FHashList^[Index].HashValue;
+end;
+
+
+function TFPHashList.GetNextCollision(Index: Integer): Integer;
+begin
+ Result:=-1;
+ if ((Index > -1) and (Index < FCount)) then
+ Result:=FHashList^[Index].NextIndex;
+end;
+
+
+function TFPHashList.Extract(item: Pointer): Pointer;
+var
+ i : Integer;
+begin
+ result := nil;
+ i := IndexOf(item);
+ if i >= 0 then
+ begin
+ Result := item;
+ Delete(i);
+ end;
+end;
+
+
+procedure TFPHashList.SetCapacity(NewCapacity: Integer);
+var
+ power: longint;
+begin
+ { use a power of two to be able to quickly calculate the hash table index }
+ if NewCapacity <> 0 then
+ NewCapacity := nextpowerof2((NewCapacity+(MaxItemsPerHash-1)) div MaxItemsPerHash, power) * MaxItemsPerHash;
+ if (NewCapacity < FCount) or (NewCapacity > MaxHashListSize) then
+ Error (SListCapacityError, NewCapacity);
+ if NewCapacity = FCapacity then
+ exit;
+ ReallocMem(FHashList, NewCapacity*SizeOf(THashItem));
+ FCapacity := NewCapacity;
+ { Maybe expand hash also }
+ if FCapacity>FHashCapacity*MaxItemsPerHash then
+ SetHashCapacity(FCapacity div MaxItemsPerHash);
+end;
+
+
+procedure TFPHashList.SetCount(NewCount: Integer);
+begin
+ if (NewCount < 0) or (NewCount > MaxHashListSize)then
+ Error(SListCountError, NewCount);
+ If NewCount > FCount then
+ begin
+ If NewCount > FCapacity then
+ SetCapacity(NewCount);
+ If FCount < NewCount then
+ { FCapacity is NewCount rounded up to the next power of 2 }
+ FillChar(FHashList^[FCount], (FCapacity-FCount) div Sizeof(THashItem), 0);
+ end;
+ FCount := Newcount;
+end;
+
+
+procedure TFPHashList.SetStrCapacity(NewCapacity: Integer);
+begin
+{$push}{$warnings off}
+ If (NewCapacity < FStrCount) or (NewCapacity > MaxHashStrSize) then
+ Error (SListCapacityError, NewCapacity);
+{$pop}
+ if NewCapacity = FStrCapacity then
+ exit;
+ ReallocMem(FStrs, NewCapacity);
+ FStrCapacity := NewCapacity;
+end;
+
+
+procedure TFPHashList.SetHashCapacity(NewCapacity: Integer);
+var
+ power: longint;
+begin
+ If (NewCapacity < 1) then
+ Error (SListCapacityError, NewCapacity);
+ if FHashCapacity=NewCapacity then
+ exit;
+ if (NewCapacity<>0) and
+ not ispowerof2(NewCapacity,power) then
+ Error(SListCapacityPower2Error, NewCapacity);
+ FHashCapacity:=NewCapacity;
+ ReallocMem(FHashTable, FHashCapacity*sizeof(Integer));
+ FCapacityMask:=(1 shl power)-1;
+ ReHash;
+end;
+
+
+procedure TFPHashList.ReHash;
+var
+ i : Integer;
+begin
+ FillDword(FHashTable^,FHashCapacity,LongWord(-1));
+ For i:=0 To FCount-1 Do
+ AddToHashTable(i);
+end;
+
+
+constructor TFPHashList.Create;
+begin
+ SetHashCapacity(1);
+end;
+
+
+destructor TFPHashList.Destroy;
+begin
+ Clear;
+ if assigned(FHashTable) then
+ FreeMem(FHashTable);
+ inherited Destroy;
+end;
+
+
+function TFPHashList.AddStr(const s:shortstring): Integer;
+var
+ Len : Integer;
+begin
+ len:=length(s)+1;
+ if FStrCount+Len >= FStrCapacity then
+ StrExpand(Len);
+ System.Move(s[0],FStrs[FStrCount],Len);
+ result:=FStrCount;
+ inc(FStrCount,Len);
+end;
+
+
+procedure TFPHashList.AddToHashTable(Index: Integer);
+var
+ HashIndex : Integer;
+begin
+ with FHashList^[Index] do
+ begin
+ if not assigned(Data) then
+ exit;
+ HashIndex:=HashValue and FCapacityMask;
+ NextIndex:=FHashTable^[HashIndex];
+ FHashTable^[HashIndex]:=Index;
+ end;
+end;
+
+
+function TFPHashList.Add(const AName:shortstring;Item: Pointer): Integer;
+begin
+ if FCount = FCapacity then
+ Expand;
+ with FHashList^[FCount] do
+ begin
+ HashValue:=FPHash(AName);
+ Data:=Item;
+ StrIndex:=AddStr(AName);
+ end;
+ AddToHashTable(FCount);
+ Result := FCount;
+ inc(FCount);
+end;
+
+procedure TFPHashList.Clear;
+begin
+ if Assigned(FHashList) then
+ begin
+ FCount:=0;
+ SetCapacity(0);
+ FHashList := nil;
+ end;
+ SetHashCapacity(1);
+ FHashTable^[0]:=-1; // sethashcapacity does not always call rehash
+ if Assigned(FStrs) then
+ begin
+ FStrCount:=0;
+ SetStrCapacity(0);
+ FStrs := nil;
+ end;
+end;
+
+procedure TFPHashList.Delete(Index: Integer);
+begin
+ If (Index<0) or (Index>=FCount) then
+ Error (SListIndexError, Index);
+ { Remove from HashList }
+ dec(FCount);
+ System.Move (FHashList^[Index+1], FHashList^[Index], (FCount - Index) * Sizeof(THashItem));
+ { All indexes are updated, we need to build the hashtable again }
+ Rehash;
+ { Shrink the list if appropriate }
+ if (FCapacity > 256) and (FCount < FCapacity shr 2) then
+ begin
+ FCapacity := FCapacity shr 1;
+ ReallocMem(FHashList, Sizeof(THashItem) * FCapacity);
+ end;
+end;
+
+function TFPHashList.Remove(Item: Pointer): Integer;
+begin
+ Result := IndexOf(Item);
+ If Result <> -1 then
+ Self.Delete(Result);
+end;
+
+class procedure TFPHashList.Error(const Msg: string; Data: PtrInt);
+begin
+ Raise EListError.CreateFmt(Msg,[Data]) at get_caller_addr(get_frame);
+end;
+
+function TFPHashList.Expand: TFPHashList;
+var
+ IncSize : Longint;
+begin
+ Result := Self;
+ if FCount < FCapacity then
+ exit;
+ IncSize := sizeof(ptrint)*2;
+ SetCapacity(FCapacity + IncSize);
+end;
+
+procedure TFPHashList.StrExpand(MinIncSize:Integer);
+var
+ IncSize : Longint;
+begin
+ if FStrCount+MinIncSize < FStrCapacity then
+ exit;
+ IncSize := 64;
+ if FStrCapacity > 255 then
+ Inc(IncSize, FStrCapacity shr 2);
+ SetStrCapacity(FStrCapacity + IncSize + MinIncSize);
+end;
+
+function TFPHashList.IndexOf(Item: Pointer): Integer;
+var
+ psrc : PHashItem;
+ Index : integer;
+begin
+ Result:=-1;
+ psrc:=@FHashList^[0];
+ For Index:=0 To FCount-1 Do
+ begin
+ if psrc^.Data=Item then
+ begin
+ Result:=Index;
+ exit;
+ end;
+ inc(psrc);
+ end;
+end;
+
+function TFPHashList.InternalFind(AHash:LongWord;const AName:shortstring;out PrevIndex:Integer):Integer;
+begin
+ prefetch(AName);
+ Result:=FHashTable^[AHash and FCapacityMask];
+ PrevIndex:=-1;
+ while Result<>-1 do
+ begin
+ with FHashList^[Result] do
+ begin
+ if assigned(Data) and
+ (HashValue=AHash) and
+ (AName=PShortString(@FStrs[StrIndex])^) then
+ exit;
+ PrevIndex:=Result;
+ Result:=NextIndex;
+ end;
+ end;
+end;
+
+
+function TFPHashList.Find(const AName:shortstring): Pointer;
+var
+ Index,
+ PrevIndex : Integer;
+begin
+ Result:=nil;
+ Index:=InternalFind(FPHash(AName),AName,PrevIndex);
+ if Index=-1 then
+ exit;
+ Result:=FHashList^[Index].Data;
+end;
+
+
+function TFPHashList.FindIndexOf(const AName:shortstring): Integer;
+var
+ PrevIndex : Integer;
+begin
+ Result:=InternalFind(FPHash(AName),AName,PrevIndex);
+end;
+
+
+function TFPHashList.FindWithHash(const AName:shortstring;AHash:LongWord): Pointer;
+var
+ Index,
+ PrevIndex : Integer;
+begin
+ Result:=nil;
+ Index:=InternalFind(AHash,AName,PrevIndex);
+ if Index=-1 then
+ exit;
+ Result:=FHashList^[Index].Data;
+end;
+
+
+function TFPHashList.Rename(const AOldName,ANewName:shortstring): Integer;
+var
+ PrevIndex,
+ Index : Integer;
+ OldHash : LongWord;
+begin
+ Result:=-1;
+ OldHash:=FPHash(AOldName);
+ Index:=InternalFind(OldHash,AOldName,PrevIndex);
+ if Index=-1 then
+ exit;
+ { Remove from current Hash }
+ if PrevIndex<>-1 then
+ FHashList^[PrevIndex].NextIndex:=FHashList^[Index].NextIndex
+ else
+ FHashTable^[OldHash and FCapacityMask]:=FHashList^[Index].NextIndex;
+ { Set new name and hash }
+ with FHashList^[Index] do
+ begin
+ HashValue:=FPHash(ANewName);
+ StrIndex:=AddStr(ANewName);
+ end;
+ { Insert back in Hash }
+ AddToHashTable(Index);
+ { Return Index }
+ Result:=Index;
+end;
+
+procedure TFPHashList.Pack;
+var
+ NewCount,
+ i : integer;
+ pdest,
+ psrc : PHashItem;
+begin
+ NewCount:=0;
+ psrc:=@FHashList^[0];
+ pdest:=psrc;
+ For I:=0 To FCount-1 Do
+ begin
+ if assigned(psrc^.Data) then
+ begin
+ pdest^:=psrc^;
+ inc(pdest);
+ inc(NewCount);
+ end;
+ inc(psrc);
+ end;
+ FCount:=NewCount;
+ { We need to ReHash to update the IndexNext }
+ ReHash;
+ { Release over-capacity }
+ SetCapacity(FCount);
+ SetStrCapacity(FStrCount);
+end;
+
+
+procedure TFPHashList.ShowStatistics;
+var
+ HashMean,
+ HashStdDev : Double;
+ Index,
+ i,j : Integer;
+begin
+ { Calculate Mean and StdDev }
+ HashMean:=0;
+ HashStdDev:=0;
+ for i:=0 to FHashCapacity-1 do
+ begin
+ j:=0;
+ Index:=FHashTable^[i];
+ while (Index<>-1) do
+ begin
+ inc(j);
+ Index:=FHashList^[Index].NextIndex;
+ end;
+ HashMean:=HashMean+j;
+ HashStdDev:=HashStdDev+Sqr(j);
+ end;
+ HashMean:=HashMean/FHashCapacity;
+ HashStdDev:=(HashStdDev-FHashCapacity*Sqr(HashMean));
+ If FHashCapacity>1 then
+ HashStdDev:=Sqrt(HashStdDev/(FHashCapacity-1))
+ else
+ HashStdDev:=0;
+ { Print info to stdout }
+ Writeln('HashSize : ',FHashCapacity);
+ Writeln('HashMean : ',HashMean:1:4);
+ Writeln('HashStdDev : ',HashStdDev:1:4);
+ Writeln('ListSize : ',FCount,'/',FCapacity);
+ Writeln('StringSize : ',FStrCount,'/',FStrCapacity);
+end;
+
+
+procedure TFPHashList.ForEachCall(proc2call:TListCallback;arg:pointer);
+var
+ i : integer;
+ p : pointer;
+begin
+ For I:=0 To Count-1 Do
+ begin
+ p:=FHashList^[i].Data;
+ if assigned(p) then
+ proc2call(p,arg);
+ end;
+end;
+
+
+procedure TFPHashList.ForEachCall(proc2call:TListStaticCallback;arg:pointer);
+var
+ i : integer;
+ p : pointer;
+begin
+ For I:=0 To Count-1 Do
+ begin
+ p:=FHashList^[i].Data;
+ if assigned(p) then
+ proc2call(p,arg);
+ end;
+end;
+
+
+{*****************************************************************************
+ TFPHashObject
+*****************************************************************************}
+
+procedure TFPHashObject.InternalChangeOwner(HashObjectList:TFPHashObjectList;const s:shortstring);
+var
+ Index : integer;
+begin
+ FOwner:=HashObjectList;
+ Index:=HashObjectList.Add(s,Self);
+ FStrIndex:=HashObjectList.List.List^[Index].StrIndex;
+ FCachedStr:=PShortString(@FOwner.List.Strs[FStrIndex]);
+end;
+
+
+constructor TFPHashObject.CreateNotOwned;
+begin
+ FStrIndex:=-1;
+end;
+
+
+constructor TFPHashObject.Create(HashObjectList:TFPHashObjectList;const s:shortstring);
+begin
+ InternalChangeOwner(HashObjectList,s);
+end;
+
+
+procedure TFPHashObject.ChangeOwner(HashObjectList:TFPHashObjectList);
+begin
+ InternalChangeOwner(HashObjectList,PShortString(@FOwner.List.Strs[FStrIndex])^);
+end;
+
+
+procedure TFPHashObject.ChangeOwnerAndName(HashObjectList:TFPHashObjectList;const s:shortstring);
+begin
+ InternalChangeOwner(HashObjectList,s);
+end;
+
+
+procedure TFPHashObject.Rename(const ANewName:shortstring);
+var
+ Index : integer;
+begin
+ Index:=FOwner.Rename(PShortString(@FOwner.List.Strs[FStrIndex])^,ANewName);
+ if Index<>-1 then
+ begin
+ FStrIndex:=FOwner.List.List^[Index].StrIndex;
+ FCachedStr:=PShortString(@FOwner.List.Strs[FStrIndex]);
+ end;
+end;
+
+
+function TFPHashObject.GetName:shortstring;
+begin
+ if FOwner<>nil then
+ begin
+ FCachedStr:=PShortString(@FOwner.List.Strs[FStrIndex]);
+ Result:=FCachedStr^;
+ end
+ else
+ Result:='';
+end;
+
+
+function TFPHashObject.GetHash:Longword;
+begin
+ if FOwner<>nil then
+ Result:=FPHash(PShortString(@FOwner.List.Strs[FStrIndex])^)
+ else
+ Result:=$ffffffff;
+end;
+
+
+{*****************************************************************************
+ TFPHashObjectList (Copied from rtl/objpas/classes/lists.inc)
+*****************************************************************************}
+
+constructor TFPHashObjectList.Create(FreeObjects : boolean = True);
+begin
+ inherited Create;
+ FHashList := TFPHashList.Create;
+ FFreeObjects := Freeobjects;
+end;
+
+destructor TFPHashObjectList.Destroy;
+begin
+ if (FHashList <> nil) then
+ begin
+ Clear;
+ FHashList.Destroy;
+ end;
+ inherited Destroy;
+end;
+
+procedure TFPHashObjectList.Clear;
+var
+ i: integer;
+begin
+ if FFreeObjects then
+ for i := 0 to FHashList.Count - 1 do
+ TObject(FHashList[i]).Free;
+ FHashList.Clear;
+end;
+
+function TFPHashObjectList.GetCount: integer;
+begin
+ Result := FHashList.Count;
+end;
+
+procedure TFPHashObjectList.SetCount(const AValue: integer);
+begin
+ if FHashList.Count <> AValue then
+ FHashList.Count := AValue;
+end;
+
+function TFPHashObjectList.GetItem(Index: Integer): TObject;
+begin
+ Result := TObject(FHashList[Index]);
+end;
+
+procedure TFPHashObjectList.SetItem(Index: Integer; AObject: TObject);
+begin
+ if OwnsObjects then
+ TObject(FHashList[Index]).Free;
+ FHashList[index] := AObject;
+end;
+
+procedure TFPHashObjectList.SetCapacity(NewCapacity: Integer);
+begin
+ FHashList.Capacity := NewCapacity;
+end;
+
+function TFPHashObjectList.GetCapacity: integer;
+begin
+ Result := FHashList.Capacity;
+end;
+
+function TFPHashObjectList.Add(const AName:shortstring;AObject: TObject): Integer;
+begin
+ Result := FHashList.Add(AName,AObject);
+end;
+
+function TFPHashObjectList.NameOfIndex(Index: Integer): shortstring;
+begin
+ Result := FHashList.NameOfIndex(Index);
+end;
+
+function TFPHashObjectList.HashOfIndex(Index: Integer): LongWord;
+begin
+ Result := FHashList.HashOfIndex(Index);
+end;
+
+function TFPHashObjectList.GetNextCollision(Index: Integer): Integer;
+begin
+ Result := FHashList.GetNextCollision(Index);
+end;
+
+procedure TFPHashObjectList.Delete(Index: Integer);
+begin
+ if OwnsObjects then
+ TObject(FHashList[Index]).Free;
+ FHashList.Delete(Index);
+end;
+
+function TFPHashObjectList.Expand: TFPHashObjectList;
+begin
+ FHashList.Expand;
+ Result := Self;
+end;
+
+function TFPHashObjectList.Extract(Item: TObject): TObject;
+begin
+ Result := TObject(FHashList.Extract(Item));
+end;
+
+function TFPHashObjectList.Remove(AObject: TObject): Integer;
+begin
+ Result := IndexOf(AObject);
+ if (Result <> -1) then
+ begin
+ if OwnsObjects then
+ TObject(FHashList[Result]).Free;
+ FHashList.Delete(Result);
+ end;
+end;
+
+function TFPHashObjectList.IndexOf(AObject: TObject): Integer;
+begin
+ Result := FHashList.IndexOf(Pointer(AObject));
+end;
+
+
+function TFPHashObjectList.Find(const s:shortstring): TObject;
+begin
+ result:=TObject(FHashList.Find(s));
+end;
+
+
+function TFPHashObjectList.FindIndexOf(const s:shortstring): Integer;
+begin
+ result:=FHashList.FindIndexOf(s);
+end;
+
+
+function TFPHashObjectList.FindWithHash(const AName:shortstring;AHash:LongWord): Pointer;
+begin
+ Result:=TObject(FHashList.FindWithHash(AName,AHash));
+end;
+
+
+function TFPHashObjectList.Rename(const AOldName,ANewName:shortstring): Integer;
+begin
+ Result:=FHashList.Rename(AOldName,ANewName);
+end;
+
+
+function TFPHashObjectList.FindInstanceOf(AClass: TClass; AExact: Boolean; AStartAt : Integer): Integer;
+var
+ I : Integer;
+begin
+ I:=AStartAt;
+ Result:=-1;
+ If AExact then
+ while (I<Count) and (Result=-1) do
+ If Items[i].ClassType=AClass then
+ Result:=I
+ else
+ Inc(I)
+ else
+ while (I<Count) and (Result=-1) do
+ If Items[i].InheritsFrom(AClass) then
+ Result:=I
+ else
+ Inc(I);
+end;
+
+
+procedure TFPHashObjectList.Pack;
+begin
+ FHashList.Pack;
+end;
+
+
+procedure TFPHashObjectList.ShowStatistics;
+begin
+ FHashList.ShowStatistics;
+end;
+
+
+procedure TFPHashObjectList.ForEachCall(proc2call:TObjectListCallback;arg:pointer);
+begin
+ FHashList.ForEachCall(TListCallBack(proc2call),arg);
+end;
+
+
+procedure TFPHashObjectList.ForEachCall(proc2call:TObjectListStaticCallback;arg:pointer);
+begin
+ FHashList.ForEachCall(TListStaticCallBack(proc2call),arg);
+end;
+
+
+{****************************************************************************
+ TLinkedListItem
+ ****************************************************************************}
+
+ constructor TLinkedListItem.Create;
+ begin
+ Previous:=nil;
+ Next:=nil;
+ end;
+
+
+ destructor TLinkedListItem.Destroy;
+ begin
+ end;
+
+
+ function TLinkedListItem.GetCopy:TLinkedListItem;
+ var
+ p : TLinkedListItem;
+ l : integer;
+ begin
+ p:=TLinkedListItemClass(ClassType).Create;
+ l:=InstanceSize;
+ Move(pointer(self)^,pointer(p)^,l);
+ Result:=p;
+ end;
+
+
+{****************************************************************************
+ TLinkedList
+ ****************************************************************************}
+
+ constructor TLinkedList.Create;
+ begin
+ FFirst:=nil;
+ Flast:=nil;
+ FCount:=0;
+ FNoClear:=False;
+ end;
+
+
+ destructor TLinkedList.destroy;
+ begin
+ if not FNoClear then
+ Clear;
+ end;
+
+
+ function TLinkedList.empty:boolean;
+ begin
+ Empty:=(FFirst=nil);
+ end;
+
+
+ procedure TLinkedList.Insert(Item:TLinkedListItem);
+ begin
+ if FFirst=nil then
+ begin
+ FLast:=Item;
+ Item.Previous:=nil;
+ Item.Next:=nil;
+ end
+ else
+ begin
+ FFirst.Previous:=Item;
+ Item.Previous:=nil;
+ Item.Next:=FFirst;
+ end;
+ FFirst:=Item;
+ inc(FCount);
+ end;
+
+
+ procedure TLinkedList.InsertBefore(Item,Loc : TLinkedListItem);
+ begin
+ Item.Previous:=Loc.Previous;
+ Item.Next:=Loc;
+ Loc.Previous:=Item;
+ if assigned(Item.Previous) then
+ Item.Previous.Next:=Item
+ else
+ { if we've no next item, we've to adjust FFist }
+ FFirst:=Item;
+ inc(FCount);
+ end;
+
+
+ procedure TLinkedList.InsertAfter(Item,Loc : TLinkedListItem);
+ begin
+ Item.Next:=Loc.Next;
+ Loc.Next:=Item;
+ Item.Previous:=Loc;
+ if assigned(Item.Next) then
+ Item.Next.Previous:=Item
+ else
+ { if we've no next item, we've to adjust FLast }
+ FLast:=Item;
+ inc(FCount);
+ end;
+
+
+ procedure TLinkedList.Concat(Item:TLinkedListItem);
+ begin
+ if FFirst=nil then
+ begin
+ FFirst:=Item;
+ Item.Previous:=nil;
+ Item.Next:=nil;
+ end
+ else
+ begin
+ Flast.Next:=Item;
+ Item.Previous:=Flast;
+ Item.Next:=nil;
+ end;
+ Flast:=Item;
+ inc(FCount);
+ end;
+
+
+ procedure TLinkedList.remove(Item:TLinkedListItem);
+ begin
+ if Item=nil then
+ exit;
+ if (FFirst=Item) and (Flast=Item) then
+ begin
+ FFirst:=nil;
+ Flast:=nil;
+ end
+ else if FFirst=Item then
+ begin
+ FFirst:=Item.Next;
+ if assigned(FFirst) then
+ FFirst.Previous:=nil;
+ end
+ else if Flast=Item then
+ begin
+ Flast:=Flast.Previous;
+ if assigned(Flast) then
+ Flast.Next:=nil;
+ end
+ else
+ begin
+ Item.Previous.Next:=Item.Next;
+ Item.Next.Previous:=Item.Previous;
+ end;
+ Item.Next:=nil;
+ Item.Previous:=nil;
+ dec(FCount);
+ end;
+
+
+ procedure TLinkedList.clear;
+ var
+ NewNode, Next : TLinkedListItem;
+ begin
+ NewNode:=FFirst;
+ while assigned(NewNode) do
+ begin
+ Next:=NewNode.Next;
+ prefetch(next.next);
+ NewNode.Free;
+ NewNode:=Next;
+ end;
+ FLast:=nil;
+ FFirst:=nil;
+ FCount:=0;
+ end;
+
+
+ function TLinkedList.GetFirst:TLinkedListItem;
+ begin
+ if FFirst=nil then
+ GetFirst:=nil
+ else
+ begin
+ GetFirst:=FFirst;
+ if FFirst=FLast then
+ FLast:=nil;
+ FFirst:=FFirst.Next;
+ dec(FCount);
+ end;
+ end;
+
+
+ function TLinkedList.GetLast:TLinkedListItem;
+ begin
+ if FLast=nil then
+ Getlast:=nil
+ else
+ begin
+ Getlast:=FLast;
+ if FLast=FFirst then
+ FFirst:=nil;
+ FLast:=FLast.Previous;
+ dec(FCount);
+ end;
+ end;
+
+
+ procedure TLinkedList.insertList(p : TLinkedList);
+ begin
+ { empty List ? }
+ if (p.FFirst=nil) then
+ exit;
+ p.Flast.Next:=FFirst;
+ { we have a double Linked List }
+ if assigned(FFirst) then
+ FFirst.Previous:=p.Flast;
+ FFirst:=p.FFirst;
+ if (FLast=nil) then
+ Flast:=p.Flast;
+ inc(FCount,p.FCount);
+ { p becomes empty }
+ p.FFirst:=nil;
+ p.Flast:=nil;
+ p.FCount:=0;
+ end;
+
+
+ procedure TLinkedList.insertListBefore(Item:TLinkedListItem;p : TLinkedList);
+ begin
+ { empty List ? }
+ if (p.FFirst=nil) then
+ exit;
+ if (Item=nil) then
+ begin
+ { Insert at begin }
+ InsertList(p);
+ exit;
+ end
+ else
+ begin
+ p.FLast.Next:=Item;
+ p.FFirst.Previous:=Item.Previous;
+ if assigned(Item.Previous) then
+ Item.Previous.Next:=p.FFirst
+ else
+ FFirst:=p.FFirst;
+ Item.Previous:=p.FLast;
+ inc(FCount,p.FCount);
+ end;
+ { p becomes empty }
+ p.FFirst:=nil;
+ p.Flast:=nil;
+ p.FCount:=0;
+ end;
+
+
+ procedure TLinkedList.insertListAfter(Item:TLinkedListItem;p : TLinkedList);
+ begin
+ { empty List ? }
+ if (p.FFirst=nil) then
+ exit;
+ if (Item=nil) then
+ begin
+ { Insert at begin }
+ InsertList(p);
+ exit;
+ end
+ else
+ begin
+ p.FFirst.Previous:=Item;
+ p.FLast.Next:=Item.Next;
+ if assigned(Item.Next) then
+ Item.Next.Previous:=p.FLast
+ else
+ FLast:=p.FLast;
+ Item.Next:=p.FFirst;
+ inc(FCount,p.FCount);
+ end;
+ { p becomes empty }
+ p.FFirst:=nil;
+ p.Flast:=nil;
+ p.FCount:=0;
+ end;
+
+
+ procedure TLinkedList.concatList(p : TLinkedList);
+ begin
+ if (p.FFirst=nil) then
+ exit;
+ if FFirst=nil then
+ FFirst:=p.FFirst
+ else
+ begin
+ FLast.Next:=p.FFirst;
+ p.FFirst.Previous:=Flast;
+ end;
+ Flast:=p.Flast;
+ inc(FCount,p.FCount);
+ { make p empty }
+ p.Flast:=nil;
+ p.FFirst:=nil;
+ p.FCount:=0;
+ end;
+
+
+ procedure TLinkedList.insertListcopy(p : TLinkedList);
+ var
+ NewNode,NewNode2 : TLinkedListItem;
+ begin
+ NewNode:=p.Last;
+ while assigned(NewNode) do
+ begin
+ NewNode2:=NewNode.Getcopy;
+ if assigned(NewNode2) then
+ Insert(NewNode2);
+ NewNode:=NewNode.Previous;
+ end;
+ end;
+
+
+ procedure TLinkedList.concatListcopy(p : TLinkedList);
+ var
+ NewNode,NewNode2 : TLinkedListItem;
+ begin
+ NewNode:=p.First;
+ while assigned(NewNode) do
+ begin
+ NewNode2:=NewNode.Getcopy;
+ if assigned(NewNode2) then
+ Concat(NewNode2);
+ NewNode:=NewNode.Next;
+ end;
+ end;
+
+
+{****************************************************************************
+ TCmdStrListItem
+ ****************************************************************************}
+
+ constructor TCmdStrListItem.Create(const s:TCmdStr);
+ begin
+ inherited Create;
+ FPStr:=s;
+ end;
+
+
+ destructor TCmdStrListItem.Destroy;
+ begin
+ FPStr:='';
+ end;
+
+
+ function TCmdStrListItem.Str:TCmdStr;
+ begin
+ Str:=FPStr;
+ end;
+
+
+ function TCmdStrListItem.GetCopy:TLinkedListItem;
+ begin
+ Result:=(inherited GetCopy);
+ { TLinkedListItem.GetCopy performs a "move" to copy all data -> reinit
+ the ansistring, so the refcount is properly increased }
+ Initialize(TCmdStrListItem(Result).FPStr);
+ TCmdStrListItem(Result).FPStr:=FPstr;
+ end;
+
+
+{****************************************************************************
+ TCmdStrList
+ ****************************************************************************}
+
+ constructor TCmdStrList.Create;
+ begin
+ inherited Create;
+ FDoubles:=true;
+ end;
+
+
+ constructor TCmdStrList.Create_no_double;
+ begin
+ inherited Create;
+ FDoubles:=false;
+ end;
+
+
+ procedure TCmdStrList.insert(const s : TCmdStr);
+ begin
+ if (s='') or
+ ((not FDoubles) and (find(s)<>nil)) then
+ exit;
+ inherited insert(TCmdStrListItem.create(s));
+ end;
+
+
+ procedure TCmdStrList.concat(const s : TCmdStr);
+ begin
+ if (s='') or
+ ((not FDoubles) and (find(s)<>nil)) then
+ exit;
+ inherited concat(TCmdStrListItem.create(s));
+ end;
+
+
+ procedure TCmdStrList.remove(const s : TCmdStr);
+ var
+ p : TCmdStrListItem;
+ begin
+ if s='' then
+ exit;
+ p:=find(s);
+ if assigned(p) then
+ begin
+ inherited Remove(p);
+ p.Free;
+ end;
+ end;
+
+
+ function TCmdStrList.GetFirst : TCmdStr;
+ var
+ p : TCmdStrListItem;
+ begin
+ p:=TCmdStrListItem(inherited GetFirst);
+ if p=nil then
+ GetFirst:=''
+ else
+ begin
+ GetFirst:=p.FPStr;
+ p.free;
+ end;
+ end;
+
+
+ function TCmdStrList.Getlast : TCmdStr;
+ var
+ p : TCmdStrListItem;
+ begin
+ p:=TCmdStrListItem(inherited Getlast);
+ if p=nil then
+ Getlast:=''
+ else
+ begin
+ Getlast:=p.FPStr;
+ p.free;
+ end;
+ end;
+
+
+ function TCmdStrList.FindCase(const s:TCmdStr):TCmdStrListItem;
+ var
+ NewNode : TCmdStrListItem;
+ begin
+ result:=nil;
+ if s='' then
+ exit;
+ NewNode:=TCmdStrListItem(FFirst);
+ while assigned(NewNode) do
+ begin
+ if NewNode.FPStr=s then
+ begin
+ result:=NewNode;
+ exit;
+ end;
+ NewNode:=TCmdStrListItem(NewNode.Next);
+ end;
+ end;
+
+
+ function TCmdStrList.Find(const s:TCmdStr):TCmdStrListItem;
+ var
+ NewNode : TCmdStrListItem;
+ begin
+ result:=nil;
+ if s='' then
+ exit;
+ NewNode:=TCmdStrListItem(FFirst);
+ while assigned(NewNode) do
+ begin
+ if SysUtils.CompareText(s, NewNode.FPStr)=0 then
+ begin
+ result:=NewNode;
+ exit;
+ end;
+ NewNode:=TCmdStrListItem(NewNode.Next);
+ end;
+ end;
+
+
+ procedure TCmdStrList.InsertItem(item:TCmdStrListItem);
+ begin
+ inherited Insert(item);
+ end;
+
+
+ procedure TCmdStrList.ConcatItem(item:TCmdStrListItem);
+ begin
+ inherited Concat(item);
+ end;
+
+
+{****************************************************************************
+ tdynamicarray
+****************************************************************************}
+
+ constructor tdynamicarray.create(Ablocksize:longword);
+ begin
+ FPosn:=0;
+ FPosnblock:=nil;
+ FFirstblock:=nil;
+ FLastblock:=nil;
+ FCurrBlockSize:=0;
+ { Every block needs at least a header and alignment slack,
+ therefore its size cannot be arbitrarily small. However,
+ the blocksize argument is often confused with data size.
+ See e.g. Mantis #20929. }
+ if Ablocksize<mindynamicblocksize then
+ Ablocksize:=mindynamicblocksize;
+ FMaxBlockSize:=Ablocksize;
+ grow;
+ end;
+
+
+ destructor tdynamicarray.destroy;
+ var
+ hp : pdynamicblock;
+ begin
+ while assigned(FFirstblock) do
+ begin
+ hp:=FFirstblock;
+ FFirstblock:=FFirstblock^.Next;
+ Freemem(hp);
+ end;
+ end;
+
+
+ function tdynamicarray.size:longword;
+ begin
+ if assigned(FLastblock) then
+ size:=FLastblock^.pos+FLastblock^.used
+ else
+ size:=0;
+ end;
+
+
+ procedure tdynamicarray.reset;
+ var
+ hp : pdynamicblock;
+ begin
+ while assigned(FFirstblock) do
+ begin
+ hp:=FFirstblock;
+ FFirstblock:=FFirstblock^.Next;
+ Freemem(hp);
+ end;
+ FPosn:=0;
+ FPosnblock:=nil;
+ FFirstblock:=nil;
+ FLastblock:=nil;
+ grow;
+ end;
+
+
+ procedure tdynamicarray.grow;
+ var
+ nblock : pdynamicblock;
+ OptBlockSize,
+ IncSize : integer;
+ begin
+ if CurrBlockSize<FMaxBlocksize then
+ begin
+ IncSize := mindynamicblocksize;
+ if FCurrBlockSize > 255 then
+ Inc(IncSize, FCurrBlockSize shr 2);
+ inc(FCurrBlockSize,IncSize);
+ end;
+ if CurrBlockSize>FMaxBlocksize then
+ FCurrBlockSize:=FMaxBlocksize;
+ { Calculate the most optimal size so there is no alignment overhead
+ lost in the heap manager }
+ OptBlockSize:=cutils.Align(CurrBlockSize+dynamicblockbasesize,16)-dynamicblockbasesize-sizeof(ptrint);
+ Getmem(nblock,OptBlockSize+dynamicblockbasesize);
+ if not assigned(FFirstblock) then
+ begin
+ FFirstblock:=nblock;
+ FPosnblock:=nblock;
+ nblock^.pos:=0;
+ end
+ else
+ begin
+ FLastblock^.Next:=nblock;
+ nblock^.pos:=FLastblock^.pos+FLastblock^.size;
+ end;
+ nblock^.used:=0;
+ nblock^.size:=OptBlockSize;
+ nblock^.Next:=nil;
+ fillchar(nblock^.data,nblock^.size,0);
+ FLastblock:=nblock;
+ end;
+
+
+ procedure tdynamicarray.align(i:longword);
+ var
+ j : longword;
+ begin
+ j:=(FPosn mod i);
+ if j<>0 then
+ begin
+ j:=i-j;
+ if FPosnblock^.used+j>FPosnblock^.size then
+ begin
+ dec(j,FPosnblock^.size-FPosnblock^.used);
+ FPosnblock^.used:=FPosnblock^.size;
+ grow;
+ FPosnblock:=FLastblock;
+ end;
+ inc(FPosnblock^.used,j);
+ inc(FPosn,j);
+ end;
+ end;
+
+
+ procedure tdynamicarray.seek(i:longword);
+ begin
+ if (i<FPosnblock^.pos) or (i>=FPosnblock^.pos+FPosnblock^.size) then
+ begin
+ { set FPosnblock correct if the size is bigger then
+ the current block }
+ if FPosnblock^.pos>i then
+ FPosnblock:=FFirstblock;
+ while assigned(FPosnblock) do
+ begin
+ if FPosnblock^.pos+FPosnblock^.size>i then
+ break;
+ FPosnblock:=FPosnblock^.Next;
+ end;
+ { not found ? then increase blocks }
+ if not assigned(FPosnblock) then
+ begin
+ repeat
+ { the current FLastblock is now also fully used }
+ FLastblock^.used:=FLastblock^.size;
+ grow;
+ FPosnblock:=FLastblock;
+ until FPosnblock^.pos+FPosnblock^.size>=i;
+ end;
+ end;
+ FPosn:=i;
+ if FPosn-FPosnblock^.pos>FPosnblock^.used then
+ FPosnblock^.used:=FPosn-FPosnblock^.pos;
+ end;
+
+
+ procedure tdynamicarray.write(const d;len:longword);
+ var
+ p : pchar;
+ i,j : longword;
+ begin
+ p:=pchar(@d);
+ while (len>0) do
+ begin
+ i:=FPosn-FPosnblock^.pos;
+ if i+len>=FPosnblock^.size then
+ begin
+ j:=FPosnblock^.size-i;
+ move(p^,FPosnblock^.data[i],j);
+ inc(p,j);
+ inc(FPosn,j);
+ dec(len,j);
+ FPosnblock^.used:=FPosnblock^.size;
+ if assigned(FPosnblock^.Next) then
+ FPosnblock:=FPosnblock^.Next
+ else
+ begin
+ grow;
+ FPosnblock:=FLastblock;
+ end;
+ end
+ else
+ begin
+ move(p^,FPosnblock^.data[i],len);
+ inc(p,len);
+ inc(FPosn,len);
+ i:=FPosn-FPosnblock^.pos;
+ if i>FPosnblock^.used then
+ FPosnblock^.used:=i;
+ len:=0;
+ end;
+ end;
+ end;
+
+
+ procedure tdynamicarray.writestr(const s:string);
+ begin
+ write(s[1],length(s));
+ end;
+
+
+ function tdynamicarray.read(var d;len:longword):longword;
+ var
+ p : pchar;
+ i,j,res : longword;
+ begin
+ res:=0;
+ p:=pchar(@d);
+ while (len>0) do
+ begin
+ i:=FPosn-FPosnblock^.pos;
+ if i+len>=FPosnblock^.used then
+ begin
+ j:=FPosnblock^.used-i;
+ move(FPosnblock^.data[i],p^,j);
+ inc(p,j);
+ inc(FPosn,j);
+ inc(res,j);
+ dec(len,j);
+ if assigned(FPosnblock^.Next) then
+ FPosnblock:=FPosnblock^.Next
+ else
+ break;
+ end
+ else
+ begin
+ move(FPosnblock^.data[i],p^,len);
+ inc(p,len);
+ inc(FPosn,len);
+ inc(res,len);
+ len:=0;
+ end;
+ end;
+ read:=res;
+ end;
+
+
+ procedure tdynamicarray.readstream(f:TCStream;maxlen:longword);
+ var
+ i,left : longword;
+ begin
+ repeat
+ left:=FPosnblock^.size-FPosnblock^.used;
+ if left>maxlen then
+ left:=maxlen;
+ i:=f.Read(FPosnblock^.data[FPosnblock^.used],left);
+ dec(maxlen,i);
+ inc(FPosnblock^.used,i);
+ if FPosnblock^.used=FPosnblock^.size then
+ begin
+ if assigned(FPosnblock^.Next) then
+ FPosnblock:=FPosnblock^.Next
+ else
+ begin
+ grow;
+ FPosnblock:=FLastblock;
+ end;
+ end;
+ until (i<left) or (maxlen=0);
+ end;
+
+
+ procedure tdynamicarray.writestream(f:TCStream);
+ var
+ hp : pdynamicblock;
+ begin
+ hp:=FFirstblock;
+ while assigned(hp) do
+ begin
+ f.Write(hp^.data,hp^.used);
+ hp:=hp^.Next;
+ end;
+ end;
+
+{****************************************************************************
+ thashset
+****************************************************************************}
+
+ constructor THashSet.Create(InitSize: Integer; OwnKeys, OwnObjects: Boolean);
+ var
+ I: Integer;
+ begin
+ inherited Create;
+ FOwnsObjects := OwnObjects;
+ FOwnsKeys := OwnKeys;
+ I := 64;
+ while I < InitSize do I := I shl 1;
+ FBucketCount := I;
+ FBucket := AllocMem(I * sizeof(PHashSetItem));
+ end;
+
+
+ destructor THashSet.Destroy;
+ begin
+ Clear;
+ FreeMem(FBucket);
+ inherited Destroy;
+ end;
+
+
+ procedure THashSet.Clear;
+ var
+ I: Integer;
+ item, next: PHashSetItem;
+ begin
+ for I := 0 to FBucketCount-1 do
+ begin
+ item := FBucket[I];
+ while Assigned(item) do
+ begin
+ next := item^.Next;
+ if FOwnsObjects then
+ item^.Data.Free;
+ if FOwnsKeys then
+ FreeMem(item^.Key);
+ FreeItem(item);
+ item := next;
+ end;
+ end;
+ FillChar(FBucket^, FBucketCount * sizeof(PHashSetItem), 0);
+ end;
+
+
+ function THashSet.Find(Key: Pointer; KeyLen: Integer): PHashSetItem;
+ var
+ Dummy: Boolean;
+ begin
+ Result := Lookup(Key, KeyLen, Dummy, False);
+ end;
+
+
+ function THashSet.FindOrAdd(Key: Pointer; KeyLen: Integer;
+ var Found: Boolean): PHashSetItem;
+ begin
+ Result := Lookup(Key, KeyLen, Found, True);
+ end;
+
+
+ function THashSet.FindOrAdd(Key: Pointer; KeyLen: Integer): PHashSetItem;
+ var
+ Dummy: Boolean;
+ begin
+ Result := Lookup(Key, KeyLen, Dummy, True);
+ end;
+
+
+ function THashSet.Get(Key: Pointer; KeyLen: Integer): TObject;
+ var
+ e: PHashSetItem;
+ Dummy: Boolean;
+ begin
+ e := Lookup(Key, KeyLen, Dummy, False);
+ if Assigned(e) then
+ Result := e^.Data
+ else
+ Result := nil;
+ end;
+
+
+ function THashSet.Lookup(Key: Pointer; KeyLen: Integer;
+ var Found: Boolean; CanCreate: Boolean): PHashSetItem;
+ var
+ Entry: PPHashSetItem;
+ h: LongWord;
+ begin
+ h := FPHash(Key, KeyLen);
+ Entry := @FBucket[h mod FBucketCount];
+ while Assigned(Entry^) and
+ not ((Entry^^.HashValue = h) and (Entry^^.KeyLength = KeyLen) and
+ (CompareByte(Entry^^.Key^, Key^, KeyLen) = 0)) do
+ Entry := @Entry^^.Next;
+ Found := Assigned(Entry^);
+ if Found or (not CanCreate) then
+ begin
+ Result := Entry^;
+ Exit;
+ end;
+ if FCount > FBucketCount then { arbitrary limit, probably too high }
+ begin
+ { rehash and repeat search }
+ Resize(FBucketCount * 2);
+ Result := Lookup(Key, KeyLen, Found, CanCreate);
+ end
+ else
+ begin
+ New(Result);
+ if FOwnsKeys then
+ begin
+ GetMem(Result^.Key, KeyLen);
+ Move(Key^, Result^.Key^, KeyLen);
+ end
+ else
+ Result^.Key := Key;
+ Result^.KeyLength := KeyLen;
+ Result^.HashValue := h;
+ Result^.Data := nil;
+ Result^.Next := nil;
+ Inc(FCount);
+ Entry^ := Result;
+ end;
+ end;
+
+
+ procedure THashSet.Resize(NewCapacity: LongWord);
+ var
+ p, chain: PPHashSetItem;
+ i: Integer;
+ e, n: PHashSetItem;
+ begin
+ p := AllocMem(NewCapacity * SizeOfItem);
+ for i := 0 to FBucketCount-1 do
+ begin
+ e := FBucket[i];
+ while Assigned(e) do
+ begin
+ chain := @p[e^.HashValue mod NewCapacity];
+ n := e^.Next;
+ e^.Next := chain^;
+ chain^ := e;
+ e := n;
+ end;
+ end;
+ FBucketCount := NewCapacity;
+ FreeMem(FBucket);
+ FBucket := p;
+ end;
+
+ class procedure THashSet.FreeItem(item: PHashSetItem);
+ begin
+ Dispose(item);
+ end;
+
+ class function THashSet.SizeOfItem: Integer;
+ begin
+ Result := SizeOf(THashSetItem);
+ end;
+
+ function THashSet.Remove(Entry: PHashSetItem): Boolean;
+ var
+ chain: PPHashSetItem;
+ begin
+ chain := @FBucket[Entry^.HashValue mod FBucketCount];
+ while Assigned(chain^) do
+ begin
+ if chain^ = Entry then
+ begin
+ chain^ := Entry^.Next;
+ if FOwnsObjects then
+ Entry^.Data.Free;
+ if FOwnsKeys then
+ FreeMem(Entry^.Key);
+ FreeItem(Entry);
+ Dec(FCount);
+ Result := True;
+ Exit;
+ end;
+ chain := @chain^^.Next;
+ end;
+ Result := False;
+ end;
+
+
+{****************************************************************************
+ ttaghashset
+****************************************************************************}
+
+ function TTagHashSet.Lookup(Key: Pointer; KeyLen: Integer;
+ Tag: LongWord; var Found: Boolean; CanCreate: Boolean): PTagHashSetItem;
+ var
+ Entry: PPTagHashSetItem;
+ h: LongWord;
+ begin
+ h := FPHash(Key, KeyLen, Tag);
+ Entry := @PPTagHashSetItem(FBucket)[h mod FBucketCount];
+ while Assigned(Entry^) and
+ not ((Entry^^.HashValue = h) and (Entry^^.KeyLength = KeyLen) and
+ (Entry^^.Tag = Tag) and (CompareByte(Entry^^.Key^, Key^, KeyLen) = 0)) do
+ Entry := @Entry^^.Next;
+ Found := Assigned(Entry^);
+ if Found or (not CanCreate) then
+ begin
+ Result := Entry^;
+ Exit;
+ end;
+ if FCount > FBucketCount then { arbitrary limit, probably too high }
+ begin
+ { rehash and repeat search }
+ Resize(FBucketCount * 2);
+ Result := Lookup(Key, KeyLen, Tag, Found, CanCreate);
+ end
+ else
+ begin
+ New(Result);
+ if FOwnsKeys then
+ begin
+ GetMem(Result^.Key, KeyLen);
+ Move(Key^, Result^.Key^, KeyLen);
+ end
+ else
+ Result^.Key := Key;
+ Result^.KeyLength := KeyLen;
+ Result^.HashValue := h;
+ Result^.Tag := Tag;
+ Result^.Data := nil;
+ Result^.Next := nil;
+ Inc(FCount);
+ Entry^ := Result;
+ end;
+ end;
+
+ class procedure TTagHashSet.FreeItem(item: PHashSetItem);
+ begin
+ Dispose(PTagHashSetItem(item));
+ end;
+
+ class function TTagHashSet.SizeOfItem: Integer;
+ begin
+ Result := SizeOf(TTagHashSetItem);
+ end;
+
+ function TTagHashSet.Find(Key: Pointer; KeyLen: Integer; Tag: LongWord): PTagHashSetItem;
+ var
+ Dummy: Boolean;
+ begin
+ Result := Lookup(Key, KeyLen, Tag, Dummy, False);
+ end;
+
+ function TTagHashSet.FindOrAdd(Key: Pointer; KeyLen: Integer; Tag: LongWord;
+ var Found: Boolean): PTagHashSetItem;
+ begin
+ Result := Lookup(Key, KeyLen, Tag, Found, True);
+ end;
+
+ function TTagHashSet.FindOrAdd(Key: Pointer; KeyLen: Integer; Tag: LongWord): PTagHashSetItem;
+ var
+ Dummy: Boolean;
+ begin
+ Result := Lookup(Key, KeyLen, Tag, Dummy, True);
+ end;
+
+ function TTagHashSet.Get(Key: Pointer; KeyLen: Integer; Tag: LongWord): TObject;
+ var
+ e: PTagHashSetItem;
+ Dummy: Boolean;
+ begin
+ e := Lookup(Key, KeyLen, Tag, Dummy, False);
+ if Assigned(e) then
+ Result := e^.Data
+ else
+ Result := nil;
+ end;
+
+{****************************************************************************
+ tbitset
+****************************************************************************}
+
+ constructor tbitset.create(initsize: longint);
+ begin
+ create_bytesize((initsize+7) div 8);
+ end;
+
+
+ constructor tbitset.create_bytesize(bytesize: longint);
+ begin
+ fdatasize:=bytesize;
+ getmem(fdata,fdataSize);
+ clear;
+ end;
+
+
+ destructor tbitset.destroy;
+ begin
+ freemem(fdata,fdatasize);
+ inherited destroy;
+ end;
+
+
+ procedure tbitset.clear;
+ begin
+ fillchar(fdata^,fdatasize,0);
+ end;
+
+
+ procedure tbitset.grow(nsize: longint);
+ begin
+ reallocmem(fdata,nsize);
+ fillchar(fdata[fdatasize],nsize-fdatasize,0);
+ fdatasize:=nsize;
+ end;
+
+
+ procedure tbitset.include(index: longint);
+ var
+ dataindex: longint;
+ begin
+ { don't use bitpacked array, not endian-safe }
+ dataindex:=index shr 3;
+ if (dataindex>=datasize) then
+ grow(dataindex+16);
+ fdata[dataindex]:=fdata[dataindex] or (1 shl (index and 7));
+ end;
+
+
+ procedure tbitset.exclude(index: longint);
+ var
+ dataindex: longint;
+ begin
+ dataindex:=index shr 3;
+ if (dataindex>=datasize) then
+ exit;
+ fdata[dataindex]:=fdata[dataindex] and not(1 shl (index and 7));
+ end;
+
+
+ function tbitset.isset(index: longint): boolean;
+ var
+ dataindex: longint;
+ begin
+ dataindex:=index shr 3;
+ result:=
+ (dataindex<datasize) and
+ (((fdata[dataindex] shr (index and 7)) and 1)<>0);
+ end;
+
+
+ procedure tbitset.addset(aset: tbitset);
+ var
+ i: longint;
+ begin
+ if (aset.datasize>datasize) then
+ grow(aset.datasize);
+ for i:=0 to aset.datasize-1 do
+ fdata[i]:=fdata[i] or aset.data[i];
+ end;
+
+
+ procedure tbitset.subset(aset: tbitset);
+ var
+ i: longint;
+ begin
+ for i:=0 to min(datasize,aset.datasize)-1 do
+ fdata[i]:=fdata[i] and not(aset.data[i]);
+ end;
+
+
+end.
diff --git a/closures/compiler/cfidwarf.pas b/closures/compiler/cfidwarf.pas
new file mode 100644
index 0000000000..5a1bfc3b62
--- /dev/null
+++ b/closures/compiler/cfidwarf.pas
@@ -0,0 +1,429 @@
+{
+ Copyright (c) 2003-2004 by Peter Vreman and Florian Klaempfl
+
+ This units contains special support for DWARF debug info
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit cfidwarf;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cclasses,
+ globtype,
+ cgbase,cpubase,
+ aasmbase,aasmtai,aasmdata;
+
+ const
+ maxdwarfops = 2;
+
+ type
+ tdwarfoperenc=(doe_uleb,doe_sleb,doe_ptr,doe_32bit,doe_16bit,doe_8bit);
+ tdwarfopertype=(dop_reg,dop_const,dop_sym,dop_reloffset);
+
+ tdwarfoper=record
+ enc : tdwarfoperenc;
+ case typ:tdwarfopertype of
+ dop_reg : (register:tregister);
+ dop_const : (value:int64);
+ dop_sym : (sym:tasmsymbol);
+ dop_reloffset : (beginsym,endsym:tasmsymbol);
+ end;
+
+ tdwarfitem=class(TLinkedListItem)
+ op : byte;
+ ops : byte;
+ oper : array[0..maxdwarfops-1] of tdwarfoper;
+ constructor create(aop:byte);
+ constructor create_reg(aop:byte;enc1:tdwarfoperenc;reg:tregister);
+ constructor create_const(aop:byte;enc1:tdwarfoperenc;val:int64);
+ constructor create_reloffset(aop:byte;enc1:tdwarfoperenc;beginlab,endlab:tasmsymbol);
+ constructor create_reg_const(aop:byte;enc1:tdwarfoperenc;reg:tregister;enc2:tdwarfoperenc;val:longint);
+ procedure generate_code(list:TAsmList);
+ end;
+
+ TDwarfAsmCFI=class(TAsmCFI)
+ private
+ FDwarfList : TLinkedList;
+ FFrameStartLabel,
+ FFrameEndLabel,
+ FLastloclabel : tasmlabel;
+ procedure cfa_advance_loc(list:TAsmList);
+ procedure generate_initial_instructions(list:TAsmList);virtual;
+ protected
+ code_alignment_factor,
+ data_alignment_factor : shortint;
+ property DwarfList:TlinkedList read FDwarfList;
+ public
+ constructor create;override;
+ destructor destroy;override;
+ procedure generate_code(list:TAsmList);override;
+ { operations }
+ procedure start_frame(list:TAsmList);override;
+ procedure end_frame(list:TAsmList);override;
+ procedure cfa_offset(list:TAsmList;reg:tregister;ofs:longint);override;
+ procedure cfa_restore(list:TAsmList;reg:tregister);override;
+ procedure cfa_def_cfa_register(list:TAsmList;reg:tregister);override;
+ procedure cfa_def_cfa_offset(list:TAsmList;ofs:longint);override;
+ end;
+
+
+implementation
+
+ uses
+ systems,
+ verbose;
+
+ const
+ { Call frame information }
+ DW_CFA_set_loc = $01;
+ DW_CFA_advance_loc1 = $02;
+ DW_CFA_advance_loc2 = $03;
+ DW_CFA_advance_loc4 = $04;
+ DW_CFA_offset_extended = $05;
+ DW_CFA_restore_extended = $06;
+ DW_CFA_def_cfa = $0c;
+ DW_CFA_def_cfa_register = $0d;
+ DW_CFA_def_cfa_offset = $0e;
+ { Own additions }
+ DW_CFA_start_frame = $f0;
+ DW_CFA_end_frame = $f1;
+
+ DW_LNS_copy = $01;
+ DW_LNS_advance_pc = $02;
+ DW_LNS_advance_line = $03;
+ DW_LNS_set_file = $04;
+ DW_LNS_set_column = $05;
+ DW_LNS_negate_stmt = $06;
+ DW_LNS_set_basic_block = $07;
+ DW_LNS_const_add_pc = $08;
+
+ DW_LNS_fixed_advance_pc = $09;
+ DW_LNS_set_prologue_end = $0a;
+ DW_LNS_set_epilogue_begin = $0b;
+ DW_LNS_set_isa = $0c;
+
+ DW_LNE_end_sequence = $01;
+ DW_LNE_set_address = $02;
+ DW_LNE_define_file = $03;
+ DW_LNE_lo_user = $80;
+ DW_LNE_hi_user = $ff;
+
+
+{****************************************************************************
+ TDWARFITEM
+****************************************************************************}
+
+ constructor tdwarfitem.create(aop:byte);
+ begin
+ inherited create;
+ op:=aop;
+ ops:=0;
+ end;
+
+
+ constructor tdwarfitem.create_reg(aop:byte;enc1:tdwarfoperenc;reg:tregister);
+ begin
+ inherited create;
+ op:=aop;
+ ops:=1;
+ oper[0].typ:=dop_reg;
+ oper[0].enc:=enc1;
+ oper[0].register:=reg;
+ end;
+
+
+ constructor tdwarfitem.create_const(aop:byte;enc1:tdwarfoperenc;val:int64);
+ begin
+ inherited create;
+ op:=aop;
+ ops:=1;
+ oper[0].typ:=dop_const;
+ oper[0].enc:=enc1;
+ oper[0].value:=val;
+ end;
+
+
+ constructor tdwarfitem.create_reloffset(aop:byte;enc1:tdwarfoperenc;beginlab,endlab:tasmsymbol);
+ begin
+ inherited create;
+ op:=aop;
+ ops:=1;
+ { relative offsets are passed }
+ oper[0].typ:=dop_reloffset;
+ oper[0].enc:=enc1;
+ oper[0].beginsym:=beginlab;
+ oper[0].endsym:=endlab;
+ end;
+
+
+ constructor tdwarfitem.create_reg_const(aop:byte;enc1:tdwarfoperenc;reg:tregister;enc2:tdwarfoperenc;val:longint);
+ begin
+ inherited create;
+ op:=aop;
+ ops:=2;
+ oper[0].typ:=dop_reg;
+ oper[0].enc:=enc1;
+ oper[0].register:=reg;
+ oper[1].typ:=dop_const;
+ oper[1].enc:=enc2;
+ oper[1].value:=val;
+ end;
+
+
+ procedure tdwarfitem.generate_code(list:TAsmList);
+ const
+ enc2ait_const : array[tdwarfoperenc] of taiconst_type = (
+ aitconst_uleb128bit,aitconst_sleb128bit,aitconst_ptr,
+ aitconst_32bit,aitconst_16bit,aitconst_8bit
+ );
+ var
+ i : integer;
+ begin
+ list.concat(tai_const.create_8bit(op));
+ for i:=0 to ops-1 do
+ begin
+ case oper[i].typ of
+ dop_const :
+ list.concat(tai_const.create(enc2ait_const[oper[i].enc],oper[i].value));
+ dop_sym :
+ begin
+ if oper[i].enc<>doe_ptr then
+ internalerror(200404127);
+ list.concat(tai_const.create_sym(oper[i].sym));
+ end;
+ dop_reloffset :
+ list.concat(tai_const.create_rel_sym(enc2ait_const[oper[i].enc],oper[i].beginsym,oper[i].endsym));
+ dop_reg :
+ list.concat(tai_const.create(enc2ait_const[oper[i].enc],dwarf_reg(oper[i].register)));
+ else
+ internalerror(200404128);
+ end;
+ end;
+ end;
+
+
+{****************************************************************************
+ TDwarfAsmCFI
+****************************************************************************}
+
+ constructor TDwarfAsmCFI.create;
+ begin
+ inherited create;
+ FFrameStartLabel:=nil;
+ FFrameEndLabel:=nil;
+ FLastLocLabel:=nil;
+ code_alignment_factor:=1;
+ data_alignment_factor:=-4;
+ FDwarfList:=TLinkedList.Create;
+ end;
+
+
+ destructor TDwarfAsmCFI.destroy;
+ begin
+ FDwarfList.Free;
+ end;
+
+
+{$ifdef i386}
+ { if more cpu dependend stuff is implemented, this needs more refactoring }
+ procedure TDwarfAsmCFI.generate_initial_instructions(list:TAsmList);
+ begin
+ list.concat(tai_const.create_8bit(DW_CFA_def_cfa));
+ list.concat(tai_const.create_uleb128bit(dwarf_reg(NR_STACK_POINTER_REG)));
+ list.concat(tai_const.create_uleb128bit(sizeof(aint)));
+ list.concat(tai_const.create_8bit(DW_CFA_offset_extended));
+ list.concat(tai_const.create_uleb128bit(dwarf_reg(NR_RETURN_ADDRESS_REG)));
+ list.concat(tai_const.create_uleb128bit((-sizeof(aint)) div data_alignment_factor));
+ end;
+{$else i386}
+ { if more cpu dependend stuff is implemented, this needs more refactoring }
+ procedure TDwarfAsmCFI.generate_initial_instructions(list:TAsmList);
+ begin
+ list.concat(tai_const.create_8bit(DW_CFA_def_cfa));
+ list.concat(tai_const.create_uleb128bit(dwarf_reg(NR_STACK_POINTER_REG)));
+ list.concat(tai_const.create_uleb128bit(sizeof(aint)));
+ list.concat(tai_const.create_8bit(DW_CFA_offset_extended));
+ list.concat(tai_const.create_uleb128bit(dwarf_reg(NR_RETURN_ADDRESS_REG)));
+ list.concat(tai_const.create_uleb128bit((-sizeof(aint)) div data_alignment_factor));
+ end;
+{$endif i386}
+
+ procedure TDwarfAsmCFI.generate_code(list:TAsmList);
+ var
+ hp : tdwarfitem;
+ cielabel,
+ lenstartlabel,
+ lenendlabel : tasmlabel;
+ tc : tai_const;
+ begin
+ new_section(list,sec_debug_frame,'',0);
+ { CIE
+ DWORD length
+ DWORD CIE_Id = 0xffffffff
+ BYTE version = 1
+ STRING augmentation = "" = BYTE 0
+ ULEB128 code alignment factor = 1
+ ULEB128 data alignment factor = -1
+ BYTE return address register
+ <...> start sequence
+ }
+ current_asmdata.getlabel(cielabel,alt_dbgframe);
+ list.concat(tai_label.create(cielabel));
+ current_asmdata.getlabel(lenstartlabel,alt_dbgframe);
+ current_asmdata.getlabel(lenendlabel,alt_dbgframe);
+ list.concat(tai_const.create_rel_sym(aitconst_32bit,lenstartlabel,lenendlabel));
+ list.concat(tai_label.create(lenstartlabel));
+ list.concat(tai_const.create_32bit(longint($ffffffff)));
+ list.concat(tai_const.create_8bit(1));
+ list.concat(tai_const.create_8bit(0)); { empty string }
+ list.concat(tai_const.create_uleb128bit(code_alignment_factor));
+ list.concat(tai_const.create_sleb128bit(data_alignment_factor));
+ list.concat(tai_const.create_8bit(dwarf_reg(NR_RETURN_ADDRESS_REG)));
+ { Generate standard code
+ def_cfa(stackpointer,sizeof(aint))
+ cfa_offset_extended(returnaddres,-sizeof(aint))
+ }
+ generate_initial_instructions(list);
+
+ list.concat(cai_align.create_zeros(4));
+ list.concat(tai_label.create(lenendlabel));
+ lenstartlabel:=nil;
+ lenendlabel:=nil;
+
+ hp:=TDwarfItem(DwarfList.first);
+ while assigned(hp) do
+ begin
+ case hp.op of
+ DW_CFA_Start_Frame :
+ begin
+ if assigned(lenstartlabel) then
+ internalerror(200404125);
+ if (hp.ops<>1) or
+ (hp.oper[0].typ<>dop_reloffset) then
+ internalerror(200404126);
+ current_asmdata.getlabel(lenstartlabel,alt_dbgframe);
+ current_asmdata.getlabel(lenendlabel,alt_dbgframe);
+ { FDE
+ DWORD length
+ DWORD CIE-pointer = cielabel relative to section start
+ PTRSIZE initial location = oper[0]
+ PTRSIZE function size = oper[1]
+ }
+ list.concat(tai_const.create_rel_sym(aitconst_32bit,lenstartlabel,lenendlabel));
+ list.concat(tai_label.create(lenstartlabel));
+ tc:=tai_const.create_sym(cielabel);
+ { force label offset to secrel32 for windows systems }
+ if (target_info.system in systems_windows+systems_wince) then
+ tc.consttype:=aitconst_secrel32_symbol;
+ list.concat(tc);
+ list.concat(tai_const.create_sym(hp.oper[0].beginsym));
+ list.concat(tai_const.create_rel_sym(aitconst_ptr,hp.oper[0].beginsym,hp.oper[0].endsym));
+ end;
+ DW_CFA_End_Frame :
+ begin
+ list.concat(cai_align.create_zeros(4));
+ list.concat(tai_label.create(lenendlabel));
+ lenstartlabel:=nil;
+ lenendlabel:=nil;
+ end;
+ else
+ hp.generate_code(list);
+ end;
+ hp:=TDwarfItem(hp.next);
+ end;
+ { Check for open frames }
+ if assigned(lenstartlabel) then
+ internalerror(2004041210);
+ { DwarfList is processed, remove items }
+ DwarfList.Clear;
+ end;
+
+
+ procedure TDwarfAsmCFI.start_frame(list:TAsmList);
+ begin
+ if assigned(FFrameStartLabel) then
+ internalerror(200404129);
+ current_asmdata.getlabel(FFrameStartLabel,alt_dbgframe);
+ current_asmdata.getlabel(FFrameEndLabel,alt_dbgframe);
+ FLastloclabel:=FFrameStartLabel;
+ list.concat(tai_label.create(FFrameStartLabel));
+ DwarfList.concat(tdwarfitem.create_reloffset(DW_CFA_start_frame,doe_32bit,FFrameStartLabel,FFrameEndLabel));
+ end;
+
+
+ procedure TDwarfAsmCFI.end_frame(list:TAsmList);
+ begin
+ if not assigned(FFrameStartLabel) then
+ internalerror(2004041213);
+ DwarfList.concat(tdwarfitem.create(DW_CFA_end_frame));
+ list.concat(tai_label.create(FFrameEndLabel));
+ FFrameStartLabel:=nil;
+ FFrameEndLabel:=nil;
+ FLastLocLabel:=nil;
+ end;
+
+
+ procedure TDwarfAsmCFI.cfa_advance_loc(list:TAsmList);
+ var
+ currloclabel : tasmlabel;
+ begin
+ if FLastloclabel=nil then
+ internalerror(200404082);
+ current_asmdata.getlabel(currloclabel,alt_dbgframe);
+ list.concat(tai_label.create(currloclabel));
+ DwarfList.concat(tdwarfitem.create_reloffset(DW_CFA_advance_loc4,doe_32bit,FLastloclabel,currloclabel));
+ FLastloclabel:=currloclabel;
+ end;
+
+
+ procedure TDwarfAsmCFI.cfa_offset(list:TAsmList;reg:tregister;ofs:longint);
+ begin
+ cfa_advance_loc(list);
+{ TODO: check if ref is a temp}
+ { offset must be positive }
+ DwarfList.concat(tdwarfitem.create_reg_const(DW_CFA_offset_extended,doe_uleb,reg,doe_uleb,ofs div data_alignment_factor));
+ end;
+
+
+ procedure TDwarfAsmCFI.cfa_restore(list:TAsmList;reg:tregister);
+ begin
+ cfa_advance_loc(list);
+ DwarfList.concat(tdwarfitem.create_reg(DW_CFA_restore_extended,doe_uleb,reg));
+ end;
+
+
+ procedure TDwarfAsmCFI.cfa_def_cfa_register(list:TAsmList;reg:tregister);
+ begin
+ cfa_advance_loc(list);
+ DwarfList.concat(tdwarfitem.create_reg(DW_CFA_def_cfa_register,doe_uleb,reg));
+ end;
+
+
+ procedure TDwarfAsmCFI.cfa_def_cfa_offset(list:TAsmList;ofs:longint);
+ begin
+ cfa_advance_loc(list);
+ DwarfList.concat(tdwarfitem.create_const(DW_CFA_def_cfa_offset,doe_uleb,ofs));
+ end;
+
+
+begin
+ CAsmCFI:=TDwarfAsmCFI;
+end.
diff --git a/closures/compiler/cfileutl.pas b/closures/compiler/cfileutl.pas
new file mode 100644
index 0000000000..f15b8e588e
--- /dev/null
+++ b/closures/compiler/cfileutl.pas
@@ -0,0 +1,1301 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl and Peter Vreman
+
+ This module provides some basic file/dir handling utils and classes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit cfileutl;
+
+{$i fpcdefs.inc}
+
+{$define usedircache}
+
+interface
+
+ uses
+{$ifdef hasunix}
+ Baseunix,unix,
+{$endif hasunix}
+{$ifdef win32}
+ Windows,
+{$endif win32}
+{$if defined(go32v2) or defined(watcom)}
+ Dos,
+{$endif}
+{$IFNDEF USE_FAKE_SYSUTILS}
+ SysUtils,
+{$ELSE}
+ fksysutl,
+{$ENDIF}
+ GlobType,
+ CUtils,CClasses,
+ Systems;
+
+ type
+ TCachedDirectory = class(TFPHashObject)
+ private
+ FDirectoryEntries : TFPHashList;
+ FCached : Boolean;
+ procedure FreeDirectoryEntries;
+ function GetItemAttr(const AName: TCmdStr): longint;
+ function TryUseCache: boolean;
+ procedure ForceUseCache;
+ procedure Reload;
+ public
+ constructor Create(AList:TFPHashObjectList;const AName:TCmdStr);
+ destructor destroy;override;
+ function FileExists(const AName:TCmdStr):boolean;
+ function FileExistsCaseAware(const path, fn: TCmdStr; out FoundName: TCmdStr):boolean;
+ function DirectoryExists(const AName:TCmdStr):boolean;
+ property DirectoryEntries:TFPHashList read FDirectoryEntries;
+ end;
+
+ TCachedSearchRec = record
+ Name : TCmdStr;
+ Attr : byte;
+ Pattern : TCmdStr;
+ CachedDir : TCachedDirectory;
+ EntryIndex : longint;
+ end;
+
+ PCachedDirectoryEntry = ^TCachedDirectoryEntry;
+ TCachedDirectoryEntry = record
+ RealName: TCmdStr;
+ Attr : longint;
+ end;
+
+ TDirectoryCache = class
+ private
+ FDirectories : TFPHashObjectList;
+ function GetDirectory(const ADir:TCmdStr):TCachedDirectory;
+ public
+ constructor Create;
+ destructor destroy;override;
+ function FileExists(const AName:TCmdStr):boolean;
+ function FileExistsCaseAware(const path, fn: TCmdStr; out FoundName: TCmdStr):boolean;
+ function DirectoryExists(const AName:TCmdStr):boolean;
+ function FindFirst(const APattern:TCmdStr;var Res:TCachedSearchRec):boolean;
+ function FindNext(var Res:TCachedSearchRec):boolean;
+ function FindClose(var Res:TCachedSearchRec):boolean;
+ end;
+
+ TSearchPathList = class(TCmdStrList)
+ procedure AddPath(s:TCmdStr;addfirst:boolean);overload;
+ procedure AddPath(SrcPath,s:TCmdStr;addfirst:boolean);overload;
+ procedure AddList(list:TSearchPathList;addfirst:boolean);
+ function FindFile(const f : TCmdStr;allowcache:boolean;var foundfile:TCmdStr):boolean;
+ end;
+
+ function bstoslash(const s : TCmdStr) : TCmdStr;
+ {Gives the absolute path to the current directory}
+ function GetCurrentDir:TCmdStr;
+ {Gives the relative path to the current directory,
+ with a trailing dir separator. E. g. on unix ./ }
+ function CurDirRelPath(systeminfo: tsysteminfo): TCmdStr;
+ function path_absolute(const s : TCmdStr) : boolean;
+ Function PathExists (const F : TCmdStr;allowcache:boolean) : Boolean;
+ Function FileExists (const F : TCmdStr;allowcache:boolean) : Boolean;
+ function FileExistsNonCase(const path,fn:TCmdStr;allowcache:boolean;var foundfile:TCmdStr):boolean;
+ Function RemoveDir(d:TCmdStr):boolean;
+ Function FixPath(const s:TCmdStr;allowdot:boolean):TCmdStr;
+ function FixFileName(const s:TCmdStr):TCmdStr;
+ function TargetFixPath(s:TCmdStr;allowdot:boolean):TCmdStr;
+ function TargetFixFileName(const s:TCmdStr):TCmdStr;
+ procedure SplitBinCmd(const s:TCmdStr;var bstr: TCmdStr;var cstr:TCmdStr);
+ function FindFile(const f : TCmdStr; const path : TCmdStr;allowcache:boolean;var foundfile:TCmdStr):boolean;
+{ function FindFilePchar(const f : TCmdStr;path : pchar;allowcache:boolean;var foundfile:TCmdStr):boolean;}
+ function FindExe(const bin:TCmdStr;allowcache:boolean;var foundfile:TCmdStr):boolean;
+ function GetShortName(const n:TCmdStr):TCmdStr;
+
+ procedure InitFileUtils;
+ procedure DoneFileUtils;
+
+
+{ * Since native Amiga commands can't handle Unix-style relative paths used by the compiler,
+ and some GNU tools, Unix2AmigaPath is needed to handle such situations (KB) * }
+
+{$IF DEFINED(MORPHOS) OR DEFINED(AMIGA)}
+{ * PATHCONV is implemented in the Amiga/MorphOS system unit * }
+{$WARNING TODO Amiga: implement PathConv() in System unit, which works with AnsiString}
+function Unix2AmigaPath(path: ShortString): ShortString; external name 'PATHCONV';
+{$ELSE}
+function Unix2AmigaPath(path: String): String;{$IFDEF USEINLINE}inline;{$ENDIF}
+{$ENDIF}
+
+
+
+implementation
+
+ uses
+ Comphook,
+ Globals;
+
+{$undef AllFilesMaskIsInRTL}
+
+{$if (FPC_VERSION > 2)}
+ {$define AllFilesMaskIsInRTL}
+{$endif FPC_VERSION}
+
+{$if (FPC_VERSION = 2) and (FPC_RELEASE > 2)}
+ {$define AllFilesMaskIsInRTL}
+{$endif}
+
+{$if (FPC_VERSION = 2) and (FPC_RELEASE = 2) and (FPC_PATCH > 0)}
+ {$define AllFilesMaskIsInRTL}
+{$endif}
+
+{$ifndef AllFilesMaskIsInRTL}
+ {$if defined(go32v2) or defined(watcom)}
+ const
+ AllFilesMask = '*.*';
+ {$else}
+ const
+ AllFilesMask = '*';
+ {$endif not (go32v2 or watcom)}
+{$endif not AllFilesMaskIsInRTL}
+ var
+ DirCache : TDirectoryCache;
+
+
+{$IF NOT (DEFINED(MORPHOS) OR DEFINED(AMIGA))}
+{ Stub function for Unix2Amiga Path conversion functionality, only available in
+ Amiga/MorphOS RTL. I'm open for better solutions. (KB) }
+function Unix2AmigaPath(path: String): String;{$IFDEF USEINLINE}inline;{$ENDIF}
+begin
+ Unix2AmigaPath:=path;
+end;
+{$ENDIF}
+
+
+
+{****************************************************************************
+ TCachedDirectory
+****************************************************************************}
+
+ constructor TCachedDirectory.create(AList:TFPHashObjectList;const AName:TCmdStr);
+ begin
+ inherited create(AList,AName);
+ FDirectoryEntries:=TFPHashList.Create;
+ FCached:=False;
+ end;
+
+
+ destructor TCachedDirectory.destroy;
+ begin
+ FreeDirectoryEntries;
+ FDirectoryEntries.Free;
+ inherited destroy;
+ end;
+
+
+ function TCachedDirectory.TryUseCache:boolean;
+ begin
+ Result:=True;
+ if FCached then
+ exit;
+ if not current_settings.disabledircache then
+ ForceUseCache
+ else
+ Result:=False;
+ end;
+
+
+ procedure TCachedDirectory.ForceUseCache;
+ begin
+ if not FCached then
+ begin
+ FCached:=True;
+ Reload;
+ end;
+ end;
+
+
+ procedure TCachedDirectory.FreeDirectoryEntries;
+ var
+ i: Integer;
+ begin
+ if not(tf_files_case_aware in source_info.flags) then
+ exit;
+ for i := 0 to DirectoryEntries.Count-1 do
+ dispose(PCachedDirectoryEntry(DirectoryEntries[i]));
+ end;
+
+
+ function TCachedDirectory.GetItemAttr(const AName: TCmdStr): longint;
+ var
+ entry: PCachedDirectoryEntry;
+ begin
+ if not(tf_files_case_sensitive in source_info.flags) then
+ if (tf_files_case_aware in source_info.flags) then
+ begin
+ entry:=PCachedDirectoryEntry(DirectoryEntries.Find(Lower(AName)));
+ if assigned(entry) then
+ Result:=entry^.Attr
+ else
+ Result:=0;
+ end
+ else
+ Result:=PtrUInt(DirectoryEntries.Find(Lower(AName)))
+ else
+ Result:=PtrUInt(DirectoryEntries.Find(AName));
+ end;
+
+
+ procedure TCachedDirectory.Reload;
+ var
+ dir : TSearchRec;
+ entry : PCachedDirectoryEntry;
+ begin
+ FreeDirectoryEntries;
+ DirectoryEntries.Clear;
+ if findfirst(IncludeTrailingPathDelimiter(Name)+AllFilesMask,faAnyFile or faDirectory,dir) = 0 then
+ begin
+ repeat
+ if ((dir.attr and faDirectory)<>faDirectory) or
+ ((dir.Name<>'.') and
+ (dir.Name<>'..')) then
+ begin
+ { Force Archive bit so the attribute always has a value. This is needed
+ to be able to see the difference in the directoryentries lookup if a file
+ exists or not }
+ Dir.Attr:=Dir.Attr or faArchive;
+ if not(tf_files_case_sensitive in source_info.flags) then
+ if (tf_files_case_aware in source_info.flags) then
+ begin
+ new(entry);
+ entry^.RealName:=Dir.Name;
+ entry^.Attr:=Dir.Attr;
+ DirectoryEntries.Add(Lower(Dir.Name),entry)
+ end
+ else
+ DirectoryEntries.Add(Lower(Dir.Name),Pointer(Ptrint(Dir.Attr)))
+ else
+ DirectoryEntries.Add(Dir.Name,Pointer(Ptrint(Dir.Attr)));
+ end;
+ until findnext(dir) <> 0;
+ end;
+ findclose(dir);
+ end;
+
+
+ function TCachedDirectory.FileExists(const AName:TCmdStr):boolean;
+ var
+ Attr : Longint;
+ begin
+ if not TryUseCache then
+ begin
+ { prepend directory name again }
+ result:=cfileutl.FileExists(Name+AName,false);
+ exit;
+ end;
+ Attr:=GetItemAttr(AName);
+ if Attr<>0 then
+ Result:=((Attr and faDirectory)=0)
+ else
+ Result:=false;
+ end;
+
+
+ function TCachedDirectory.FileExistsCaseAware(const path, fn: TCmdStr; out FoundName: TCmdStr):boolean;
+ var
+ entry : PCachedDirectoryEntry;
+ begin
+ if (tf_files_case_aware in source_info.flags) then
+ begin
+ if not TryUseCache then
+ begin
+ Result:=FileExistsNonCase(path,fn,false,FoundName);
+ exit;
+ end;
+ entry:=PCachedDirectoryEntry(DirectoryEntries.Find(Lower(ExtractFileName(fn))));
+ if assigned(entry) and
+ (entry^.Attr<>0) and
+ ((entry^.Attr and faDirectory) = 0) then
+ begin
+ FoundName:=ExtractFilePath(path+fn)+entry^.RealName;
+ Result:=true
+ end
+ else
+ Result:=false;
+ end
+ else
+ { should not be called in this case, use plain FileExists }
+ Result:=False;
+ end;
+
+
+ function TCachedDirectory.DirectoryExists(const AName:TCmdStr):boolean;
+ var
+ Attr : Longint;
+ begin
+ if not TryUseCache then
+ begin
+ Result:=PathExists(Name+AName,false);
+ exit;
+ end;
+ Attr:=GetItemAttr(AName);
+ if Attr<>0 then
+ Result:=((Attr and faDirectory)=faDirectory)
+ else
+ Result:=false;
+ end;
+
+
+{****************************************************************************
+ TDirectoryCache
+****************************************************************************}
+
+ constructor TDirectoryCache.create;
+ begin
+ inherited create;
+ FDirectories:=TFPHashObjectList.Create(true);
+ end;
+
+
+ destructor TDirectoryCache.destroy;
+ begin
+ FDirectories.Free;
+ inherited destroy;
+ end;
+
+
+ function TDirectoryCache.GetDirectory(const ADir:TCmdStr):TCachedDirectory;
+ var
+ CachedDir : TCachedDirectory;
+ DirName : TCmdStr;
+ begin
+ if ADir='' then
+ DirName:='.'+source_info.DirSep
+ else
+ DirName:=ADir;
+ CachedDir:=TCachedDirectory(FDirectories.Find(DirName));
+ if not assigned(CachedDir) then
+ CachedDir:=TCachedDirectory.Create(FDirectories,DirName);
+ Result:=CachedDir;
+ end;
+
+
+ function TDirectoryCache.FileExists(const AName:TCmdStr):boolean;
+ var
+ CachedDir : TCachedDirectory;
+ begin
+ Result:=false;
+ CachedDir:=GetDirectory(ExtractFilePath(AName));
+ if assigned(CachedDir) then
+ Result:=CachedDir.FileExists(ExtractFileName(AName));
+ end;
+
+
+ function TDirectoryCache.FileExistsCaseAware(const path, fn: TCmdStr; out FoundName: TCmdStr):boolean;
+ var
+ CachedDir : TCachedDirectory;
+ begin
+ Result:=false;
+ CachedDir:=GetDirectory(ExtractFilePath(path+fn));
+ if assigned(CachedDir) then
+ Result:=CachedDir.FileExistsCaseAware(path,fn,FoundName);
+ end;
+
+
+ function TDirectoryCache.DirectoryExists(const AName:TCmdStr):boolean;
+ var
+ CachedDir : TCachedDirectory;
+ begin
+ Result:=false;
+ CachedDir:=GetDirectory(ExtractFilePath(AName));
+ if assigned(CachedDir) then
+ Result:=CachedDir.DirectoryExists(ExtractFileName(AName));
+ end;
+
+
+ function TDirectoryCache.FindFirst(const APattern:TCmdStr;var Res:TCachedSearchRec):boolean;
+ begin
+ Res.Pattern:=ExtractFileName(APattern);
+ Res.CachedDir:=GetDirectory(ExtractFilePath(APattern));
+ Res.CachedDir.ForceUseCache;
+ Res.EntryIndex:=0;
+ if assigned(Res.CachedDir) then
+ Result:=FindNext(Res)
+ else
+ Result:=false;
+ end;
+
+
+ function TDirectoryCache.FindNext(var Res:TCachedSearchRec):boolean;
+ var
+ entry: PCachedDirectoryEntry;
+ begin
+ if Res.EntryIndex<Res.CachedDir.DirectoryEntries.Count then
+ begin
+ if (tf_files_case_aware in source_info.flags) then
+ begin
+ entry:=Res.CachedDir.DirectoryEntries[Res.EntryIndex];
+ Res.Name:=entry^.RealName;
+ Res.Attr:=entry^.Attr;
+ end
+ else
+ begin
+ Res.Name:=Res.CachedDir.DirectoryEntries.NameOfIndex(Res.EntryIndex);
+ Res.Attr:=PtrUInt(Res.CachedDir.DirectoryEntries[Res.EntryIndex]);
+ end;
+ inc(Res.EntryIndex);
+ Result:=true;
+ end
+ else
+ Result:=false;
+ end;
+
+
+ function TDirectoryCache.FindClose(var Res:TCachedSearchRec):boolean;
+ begin
+ { nothing todo }
+ result:=true;
+ end;
+
+
+{****************************************************************************
+ Utils
+****************************************************************************}
+
+ function bstoslash(const s : TCmdStr) : TCmdStr;
+ {
+ return TCmdStr s with all \ changed into /
+ }
+ var
+ i : longint;
+ begin
+ setlength(bstoslash,length(s));
+ for i:=1to length(s) do
+ if s[i]='\' then
+ bstoslash[i]:='/'
+ else
+ bstoslash[i]:=s[i];
+ end;
+
+
+ {Gives the absolute path to the current directory}
+ var
+ CachedCurrentDir : TCmdStr;
+ function GetCurrentDir:TCmdStr;
+ begin
+ if CachedCurrentDir='' then
+ begin
+ GetDir(0,CachedCurrentDir);
+ CachedCurrentDir:=FixPath(CachedCurrentDir,false);
+ end;
+ result:=CachedCurrentDir;
+ end;
+
+ {Gives the relative path to the current directory,
+ with a trailing dir separator. E. g. on unix ./ }
+ function CurDirRelPath(systeminfo: tsysteminfo): TCmdStr;
+
+ begin
+ if systeminfo.system <> system_powerpc_macos then
+ CurDirRelPath:= '.'+systeminfo.DirSep
+ else
+ CurDirRelPath:= ':'
+ end;
+
+
+ function path_absolute(const s : TCmdStr) : boolean;
+ {
+ is path s an absolute path?
+ }
+ begin
+ result:=false;
+{$if defined(unix)}
+ if (length(s)>0) and (s[1] in AllowDirectorySeparators) then
+ result:=true;
+{$elseif defined(amiga) or defined(morphos)}
+ (* An Amiga path is absolute, if it has a volume/device name in it (contains ":"),
+ otherwise it's always a relative path, no matter if it starts with a directory
+ separator or not. (KB) *)
+ if (length(s)>0) and (Pos(':',s) <> 0) then
+ result:=true;
+{$elseif defined(macos)}
+ if IsMacFullPath(s) then
+ result:=true;
+{$elseif defined(netware)}
+ if (Pos (DriveSeparator, S) <> 0) or
+ ((Length (S) > 0) and (S [1] in AllowDirectorySeparators)) then
+ result:=true;
+{$elseif defined(win32) or defined(win64) or defined(go32v2) or defined(os2) or defined(watcom)}
+ if ((length(s)>0) and (s[1] in AllowDirectorySeparators)) or
+(* The following check for non-empty AllowDriveSeparators assumes that all
+ other platforms supporting drives and not handled as exceptions above
+ should work with DOS-like paths, i.e. use absolute paths with one letter
+ for drive followed by path separator *)
+ ((length(s)>2) and (s[2] in AllowDriveSeparators) and (s[3] in AllowDirectorySeparators)) then
+ result:=true;
+{$else}
+ if ((length(s)>0) and (s[1] in AllowDirectorySeparators)) or
+(* The following check for non-empty AllowDriveSeparators assumes that all
+ other platforms supporting drives and not handled as exceptions above
+ should work with DOS-like paths, i.e. use absolute paths with one letter
+ for drive followed by path separator *)
+ ((AllowDriveSeparators <> []) and (length(s)>2) and (s[2] in AllowDriveSeparators) and (s[3] in AllowDirectorySeparators)) then
+ result:=true;
+{$endif unix}
+ end;
+
+ Function FileExists ( Const F : TCmdStr;allowcache:boolean) : Boolean;
+ begin
+{$ifdef usedircache}
+ if allowcache then
+ Result:=DirCache.FileExists(F)
+ else
+{$endif usedircache}
+ Result:=SysUtils.FileExists(F);
+ if do_checkverbosity(V_Tried) then
+ begin
+ if Result then
+ do_comment(V_Tried,'Searching file '+F+'... found')
+ else
+ do_comment(V_Tried,'Searching file '+F+'... not found');
+ end;
+ end;
+
+
+ function FileExistsNonCase(const path,fn:TCmdStr;allowcache:boolean;var foundfile:TCmdStr):boolean;
+ var
+ fn2 : TCmdStr;
+ begin
+ result:=false;
+ if tf_files_case_sensitive in source_info.flags then
+ begin
+ {
+ Search order for case sensitive systems:
+ 1. NormalCase
+ 2. lowercase
+ 3. UPPERCASE
+ }
+ FoundFile:=path+fn;
+ If FileExists(FoundFile,allowcache) then
+ begin
+ result:=true;
+ exit;
+ end;
+ fn2:=Lower(fn);
+ if fn2<>fn then
+ begin
+ FoundFile:=path+fn2;
+ If FileExists(FoundFile,allowcache) then
+ begin
+ result:=true;
+ exit;
+ end;
+ end;
+ fn2:=Upper(fn);
+ if fn2<>fn then
+ begin
+ FoundFile:=path+fn2;
+ If FileExists(FoundFile,allowcache) then
+ begin
+ result:=true;
+ exit;
+ end;
+ end;
+ end
+ else
+ if tf_files_case_aware in source_info.flags then
+ begin
+ {
+ Search order for case aware systems:
+ 1. NormalCase
+ }
+{$ifdef usedircache}
+ if allowcache then
+ begin
+ result:=DirCache.FileExistsCaseAware(path,fn,fn2);
+ if result then
+ begin
+ FoundFile:=fn2;
+ exit;
+ end;
+ end
+ else
+{$endif usedircache}
+ begin
+ FoundFile:=path+fn;
+ If FileExists(FoundFile,allowcache) then
+ begin
+ { don't know the real name in this case }
+ result:=true;
+ exit;
+ end;
+ end;
+ end
+ else
+ begin
+ { None case sensitive only lowercase }
+ FoundFile:=path+Lower(fn);
+ If FileExists(FoundFile,allowcache) then
+ begin
+ result:=true;
+ exit;
+ end;
+ end;
+ { Set foundfile to something useful }
+ FoundFile:=fn;
+ end;
+
+
+ Function PathExists (const F : TCmdStr;allowcache:boolean) : Boolean;
+ Var
+ i: longint;
+ hs : TCmdStr;
+ begin
+ if F = '' then
+ begin
+ result := true;
+ exit;
+ end;
+ hs := ExpandFileName(F);
+ I := Pos (DriveSeparator, hs);
+ if (hs [Length (hs)] = DirectorySeparator) and
+ (((I = 0) and (Length (hs) > 1)) or (I <> Length (hs) - 1)) then
+ Delete (hs, Length (hs), 1);
+{$ifdef usedircache}
+ if allowcache then
+ Result:=DirCache.DirectoryExists(hs)
+ else
+{$endif usedircache}
+ Result:=SysUtils.DirectoryExists(hs);
+ end;
+
+
+ Function RemoveDir(d:TCmdStr):boolean;
+ begin
+ if d[length(d)]=source_info.DirSep then
+ Delete(d,length(d),1);
+ {$push}{$I-}
+ rmdir(d);
+ {$pop}
+ RemoveDir:=(ioresult=0);
+ end;
+
+
+ Function FixPath(const s:TCmdStr;allowdot:boolean):TCmdStr;
+ var
+ i, L : longint;
+ P: PChar;
+ begin
+ Result := s;
+ L := Length(Result);
+ if L=0 then
+ exit;
+ { Fix separator }
+ P := @Result[1];
+ for i:=0 to L-1 do
+ begin
+ if p^ in ['/','\'] then
+ p^:=source_info.DirSep;
+ inc(p);
+ end;
+ { Fix ending / }
+ if (L>0) and (Result[L]<>source_info.DirSep) and
+ (Result[L]<>DriveSeparator) then
+ Result:=Result+source_info.DirSep; { !still results in temp AnsiString }
+ { Remove ./ }
+ if (not allowdot) and ((Length(Result)=2) and (Result[1]='.') and (Result[2] = source_info.DirSep)) then
+ begin
+ Result:='';
+ Exit;
+ end;
+ { return }
+ if not ((tf_files_case_aware in source_info.flags) or
+ (tf_files_case_sensitive in source_info.flags)) then
+ Result := lower(Result);
+ end;
+
+ {Actually the version in macutils.pp could be used,
+ but that would not work for crosscompiling, so this is a slightly modified
+ version of it.}
+ function TranslatePathToMac (const path: TCmdStr; mpw: Boolean): TCmdStr;
+
+ function GetVolumeIdentifier: TCmdStr;
+
+ begin
+ GetVolumeIdentifier := '{Boot}'
+ (*
+ if mpw then
+ GetVolumeIdentifier := '{Boot}'
+ else
+ GetVolumeIdentifier := macosBootVolumeName;
+ *)
+ end;
+
+ var
+ slashPos, oldpos, newpos, oldlen, maxpos: Longint;
+
+ begin
+ oldpos := 1;
+ slashPos := Pos('/', path);
+ if (slashPos <> 0) then {its a unix path}
+ begin
+ if slashPos = 1 then
+ begin {its a full path}
+ oldpos := 2;
+ TranslatePathToMac := GetVolumeIdentifier;
+ end
+ else {its a partial path}
+ TranslatePathToMac := ':';
+ end
+ else
+ begin
+ slashPos := Pos('\', path);
+ if (slashPos <> 0) then {its a dos path}
+ begin
+ if slashPos = 1 then
+ begin {its a full path, without drive letter}
+ oldpos := 2;
+ TranslatePathToMac := GetVolumeIdentifier;
+ end
+ else if (Length(path) >= 2) and (path[2] = ':') then {its a full path, with drive letter}
+ begin
+ oldpos := 4;
+ TranslatePathToMac := GetVolumeIdentifier;
+ end
+ else {its a partial path}
+ TranslatePathToMac := ':';
+ end;
+ end;
+
+ if (slashPos <> 0) then {its a unix or dos path}
+ begin
+ {Translate "/../" to "::" , "/./" to ":" and "/" to ":" }
+ newpos := Length(TranslatePathToMac);
+ oldlen := Length(path);
+ SetLength(TranslatePathToMac, newpos + oldlen); {It will be no longer than what is already}
+ {prepended plus length of path.}
+ maxpos := Length(TranslatePathToMac); {Get real maxpos, can be short if String is ShortString}
+
+ {There is never a slash in the beginning, because either it was an absolute path, and then the}
+ {drive and slash was removed, or it was a relative path without a preceding slash.}
+ while oldpos <= oldlen do
+ begin
+ {Check if special dirs, ./ or ../ }
+ if path[oldPos] = '.' then
+ if (oldpos + 1 <= oldlen) and (path[oldPos + 1] = '.') then
+ begin
+ if (oldpos + 2 > oldlen) or (path[oldPos + 2] in ['/', '\']) then
+ begin
+ {It is "../" or ".." translates to ":" }
+ if newPos = maxPos then
+ begin {Shouldn't actually happen, but..}
+ Exit('');
+ end;
+ newPos := newPos + 1;
+ TranslatePathToMac[newPos] := ':';
+ oldPos := oldPos + 3;
+ continue; {Start over again}
+ end;
+ end
+ else if (oldpos + 1 > oldlen) or (path[oldPos + 1] in ['/', '\']) then
+ begin
+ {It is "./" or "." ignor it }
+ oldPos := oldPos + 2;
+ continue; {Start over again}
+ end;
+
+ {Collect file or dir name}
+ while (oldpos <= oldlen) and not (path[oldPos] in ['/', '\']) do
+ begin
+ if newPos = maxPos then
+ begin {Shouldn't actually happen, but..}
+ Exit('');
+ end;
+ newPos := newPos + 1;
+ TranslatePathToMac[newPos] := path[oldPos];
+ oldPos := oldPos + 1;
+ end;
+
+ {When we come here there is either a slash or we are at the end.}
+ if (oldpos <= oldlen) then
+ begin
+ if newPos = maxPos then
+ begin {Shouldn't actually happen, but..}
+ Exit('');
+ end;
+ newPos := newPos + 1;
+ TranslatePathToMac[newPos] := ':';
+ oldPos := oldPos + 1;
+ end;
+ end;
+
+ SetLength(TranslatePathToMac, newpos);
+ end
+ else if (path = '.') then
+ TranslatePathToMac := ':'
+ else if (path = '..') then
+ TranslatePathToMac := '::'
+ else
+ TranslatePathToMac := path; {its a mac path}
+ end;
+
+
+ function FixFileName(const s:TCmdStr):TCmdStr;
+ var
+ i : longint;
+ begin
+ if source_info.system = system_powerpc_MACOS then
+ FixFileName:= TranslatePathToMac(s, true)
+ else
+ if (tf_files_case_aware in source_info.flags) or
+ (tf_files_case_sensitive in source_info.flags) then
+ begin
+ setlength(FixFileName,length(s));
+ for i:=1 to length(s) do
+ begin
+ case s[i] of
+ '/','\' :
+ FixFileName[i]:=source_info.dirsep;
+ else
+ FixFileName[i]:=s[i];
+ end;
+ end;
+ end
+ else
+ begin
+ setlength(FixFileName,length(s));
+ for i:=1 to length(s) do
+ begin
+ case s[i] of
+ '/','\' :
+ FixFileName[i]:=source_info.dirsep;
+ 'A'..'Z' :
+ FixFileName[i]:=char(byte(s[i])+32);
+ else
+ FixFileName[i]:=s[i];
+ end;
+ end;
+ end;
+ end;
+
+
+ Function TargetFixPath(s:TCmdStr;allowdot:boolean):TCmdStr;
+ var
+ i : longint;
+ begin
+ { Fix separator }
+ for i:=1 to length(s) do
+ if s[i] in ['/','\'] then
+ s[i]:=target_info.DirSep;
+ { Fix ending / }
+ if (length(s)>0) and (s[length(s)]<>target_info.DirSep) and
+ (s[length(s)]<>':') then
+ s:=s+target_info.DirSep;
+ { Remove ./ }
+ if (not allowdot) and (s='.'+target_info.DirSep) then
+ s:='';
+ { return }
+ if (tf_files_case_aware in target_info.flags) or
+ (tf_files_case_sensitive in target_info.flags) then
+ TargetFixPath:=s
+ else
+ TargetFixPath:=Lower(s);
+ end;
+
+
+ function TargetFixFileName(const s:TCmdStr):TCmdStr;
+ var
+ i : longint;
+ begin
+ if target_info.system = system_powerpc_MACOS then
+ TargetFixFileName:= TranslatePathToMac(s, true)
+ else
+ if (tf_files_case_aware in target_info.flags) or
+ (tf_files_case_sensitive in target_info.flags) then
+ begin
+ setlength(TargetFixFileName,length(s));
+ for i:=1 to length(s) do
+ begin
+ case s[i] of
+ '/','\' :
+ TargetFixFileName[i]:=target_info.dirsep;
+ else
+ TargetFixFileName[i]:=s[i];
+ end;
+ end;
+ end
+ else
+ begin
+ setlength(TargetFixFileName,length(s));
+ for i:=1 to length(s) do
+ begin
+ case s[i] of
+ '/','\' :
+ TargetFixFileName[i]:=target_info.dirsep;
+ 'A'..'Z' :
+ TargetFixFileName[i]:=char(byte(s[i])+32);
+ else
+ TargetFixFileName[i]:=s[i];
+ end;
+ end;
+ end;
+ end;
+
+
+ procedure SplitBinCmd(const s:TCmdStr;var bstr:TCmdStr;var cstr:TCmdStr);
+ var
+ i : longint;
+ begin
+ i:=pos(' ',s);
+ if i>0 then
+ begin
+ bstr:=Copy(s,1,i-1);
+ cstr:=Copy(s,i+1,length(s)-i);
+ end
+ else
+ begin
+ bstr:=s;
+ cstr:='';
+ end;
+ end;
+
+
+ procedure TSearchPathList.AddPath(s:TCmdStr;addfirst:boolean);
+ begin
+ AddPath('',s,AddFirst);
+ end;
+
+
+ procedure TSearchPathList.AddPath(SrcPath,s:TCmdStr;addfirst:boolean);
+ var
+ staridx,
+ i,j : longint;
+ prefix,
+ suffix,
+ CurrentDir,
+ currPath : TCmdStr;
+ subdirfound : boolean;
+{$ifdef usedircache}
+ dir : TCachedSearchRec;
+{$else usedircache}
+ dir : TSearchRec;
+{$endif usedircache}
+ hp : TCmdStrListItem;
+
+ procedure WarnNonExistingPath(const path : TCmdStr);
+ begin
+ if do_checkverbosity(V_Tried) then
+ do_comment(V_Tried,'Path "'+path+'" not found');
+ end;
+
+ procedure AddCurrPath;
+ begin
+ if addfirst then
+ begin
+ Remove(currPath);
+ Insert(currPath);
+ end
+ else
+ begin
+ { Check if already in path, then we don't add it }
+ hp:=Find(currPath);
+ if not assigned(hp) then
+ Concat(currPath);
+ end;
+ end;
+
+ begin
+ if s='' then
+ exit;
+ { Support default macro's }
+ DefaultReplacements(s);
+{$warnings off}
+ if PathSeparator <> ';' then
+ for i:=1 to length(s) do
+ if s[i]=PathSeparator then
+ s[i]:=';';
+{$warnings on}
+ { get current dir }
+ CurrentDir:=GetCurrentDir;
+ repeat
+ { get currpath }
+ if addfirst then
+ begin
+ j:=length(s);
+ while (j>0) and (s[j]<>';') do
+ dec(j);
+ currPath:= TrimSpace(Copy(s,j+1,length(s)-j));
+ if j=0 then
+ s:=''
+ else
+ System.Delete(s,j,length(s)-j+1);
+ end
+ else
+ begin
+ j:=Pos(';',s);
+ if j=0 then
+ j:=length(s)+1;
+ currPath:= TrimSpace(Copy(s,1,j-1));
+ System.Delete(s,1,j);
+ end;
+
+ { fix pathname }
+ DePascalQuote(currPath);
+ currPath:=SrcPath+FixPath(currPath,false);
+ if currPath='' then
+ currPath:= CurDirRelPath(source_info)
+ else
+ begin
+ currPath:=FixPath(ExpandFileName(currpath),false);
+ if (CurrentDir<>'') and (Copy(currPath,1,length(CurrentDir))=CurrentDir) then
+ begin
+{$if defined(amiga) and defined(morphos)}
+ currPath:= CurrentDir+Copy(currPath,length(CurrentDir)+1,length(currPath));
+{$else}
+ currPath:= CurDirRelPath(source_info)+Copy(currPath,length(CurrentDir)+1,length(currPath));
+{$endif}
+ end;
+ end;
+ { wildcard adding ? }
+ staridx:=pos('*',currpath);
+ if staridx>0 then
+ begin
+ prefix:=ExtractFilePath(Copy(currpath,1,staridx));
+ suffix:=Copy(currpath,staridx+1,length(currpath));
+ subdirfound:=false;
+{$ifdef usedircache}
+ if DirCache.FindFirst(Prefix+AllFilesMask,dir) then
+ begin
+ repeat
+ if (dir.attr and faDirectory)<>0 then
+ begin
+ subdirfound:=true;
+ currpath:=prefix+dir.name+suffix;
+ if (suffix='') or PathExists(currpath,true) then
+ begin
+ hp:=Find(currPath);
+ if not assigned(hp) then
+ AddCurrPath;
+ end;
+ end;
+ until not DirCache.FindNext(dir);
+ end;
+ DirCache.FindClose(dir);
+{$else usedircache}
+ if findfirst(prefix+AllFilesMask,faDirectory,dir) = 0 then
+ begin
+ repeat
+ if (dir.name<>'.') and
+ (dir.name<>'..') and
+ ((dir.attr and faDirectory)<>0) then
+ begin
+ subdirfound:=true;
+ currpath:=prefix+dir.name+suffix;
+ if (suffix='') or PathExists(currpath,false) then
+ begin
+ hp:=Find(currPath);
+ if not assigned(hp) then
+ AddCurrPath;
+ end;
+ end;
+ until findnext(dir) <> 0;
+ end;
+ FindClose(dir);
+{$endif usedircache}
+ if not subdirfound then
+ WarnNonExistingPath(currpath);
+ end
+ else
+ begin
+ if PathExists(currpath,true) then
+ AddCurrPath
+ else
+ WarnNonExistingPath(currpath);
+ end;
+ until (s='');
+ end;
+
+
+ procedure TSearchPathList.AddList(list:TSearchPathList;addfirst:boolean);
+ var
+ s : TCmdStr;
+ hl : TSearchPathList;
+ hp,hp2 : TCmdStrListItem;
+ begin
+ if list.empty then
+ exit;
+ { create temp and reverse the list }
+ if addfirst then
+ begin
+ hl:=TSearchPathList.Create;
+ hp:=TCmdStrListItem(list.first);
+ while assigned(hp) do
+ begin
+ hl.insert(hp.Str);
+ hp:=TCmdStrListItem(hp.next);
+ end;
+ while not hl.empty do
+ begin
+ s:=hl.GetFirst;
+ Remove(s);
+ Insert(s);
+ end;
+ hl.Free;
+ end
+ else
+ begin
+ hp:=TCmdStrListItem(list.first);
+ while assigned(hp) do
+ begin
+ hp2:=Find(hp.Str);
+ { Check if already in path, then we don't add it }
+ if not assigned(hp2) then
+ Concat(hp.Str);
+ hp:=TCmdStrListItem(hp.next);
+ end;
+ end;
+ end;
+
+
+ function TSearchPathList.FindFile(const f :TCmdStr;allowcache:boolean;var foundfile:TCmdStr):boolean;
+ Var
+ p : TCmdStrListItem;
+ begin
+ FindFile:=false;
+ p:=TCmdStrListItem(first);
+ while assigned(p) do
+ begin
+ result:=FileExistsNonCase(p.Str,f,allowcache,FoundFile);
+ if result then
+ exit;
+ p:=TCmdStrListItem(p.next);
+ end;
+ { Return original filename if not found }
+ FoundFile:=f;
+ end;
+
+
+ function FindFile(const f : TCmdStr; const path : TCmdStr;allowcache:boolean;var foundfile:TCmdStr):boolean;
+ Var
+ StartPos, EndPos, L: LongInt;
+ begin
+ Result:=False;
+ StartPos := 1;
+ L := Length(Path);
+ repeat
+ EndPos := StartPos;
+ while (EndPos <= L) and ((Path[EndPos] <> PathSeparator) and (Path[EndPos] <> ';')) do
+ Inc(EndPos);
+ Result := FileExistsNonCase(FixPath(Copy(Path, StartPos, EndPos-StartPos), False), f, allowcache, FoundFile);
+ if Result then
+ Exit;
+ StartPos := EndPos + 1;
+ until StartPos > L;
+ FoundFile:=f;
+ end;
+
+{
+ function FindFilePchar(const f : TCmdStr;path : pchar;allowcache:boolean;var foundfile:TCmdStr):boolean;
+ Var
+ singlepathstring : TCmdStr;
+ startpc,pc : pchar;
+ begin
+ FindFilePchar:=false;
+ if Assigned (Path) then
+ begin
+ pc:=path;
+ repeat
+ startpc:=pc;
+ while (pc^<>PathSeparator) and (pc^<>';') and (pc^<>#0) do
+ inc(pc);
+ SetLength(singlepathstring, pc-startpc);
+ move(startpc^,singlepathstring[1],pc-startpc);
+ singlepathstring:=FixPath(ExpandFileName(singlepathstring),false);
+ result:=FileExistsNonCase(singlepathstring,f,allowcache,FoundFile);
+ if result then
+ exit;
+ if (pc^=#0) then
+ break;
+ inc(pc);
+ until false;
+ end;
+ foundfile:=f;
+ end;
+}
+
+ function FindExe(const bin:TCmdStr;allowcache:boolean;var foundfile:TCmdStr):boolean;
+ var
+ Path : TCmdStr;
+ found : boolean;
+ begin
+ found:=FindFile(FixFileName(ChangeFileExt(bin,source_info.exeext)),exepath,allowcache,foundfile);
+ if not found then
+ begin
+{$ifdef macos}
+ Path:=GetEnvironmentVariable('Commands');
+{$else}
+ Path:=GetEnvironmentVariable('PATH');
+{$endif}
+ found:=FindFile(FixFileName(ChangeFileExt(bin,source_info.exeext)),Path,allowcache,foundfile);
+ end;
+ FindExe:=found;
+ end;
+
+
+ function GetShortName(const n:TCmdStr):TCmdStr;
+{$ifdef win32}
+ var
+ hs,hs2 : TCmdStr;
+ i : longint;
+{$endif}
+{$if defined(go32v2) or defined(watcom)}
+ var
+ hs : shortstring;
+{$endif}
+ begin
+ GetShortName:=n;
+{$ifdef win32}
+ hs:=n+#0;
+ { may become longer in case of e.g. ".a" -> "a~1" or so }
+ setlength(hs2,length(hs)*2);
+ i:=Windows.GetShortPathName(@hs[1],@hs2[1],length(hs)*2);
+ if (i>0) and (i<=length(hs)*2) then
+ begin
+ setlength(hs2,strlen(@hs2[1]));
+ GetShortName:=hs2;
+ end;
+{$endif}
+{$if defined(go32v2) or defined(watcom)}
+ hs:=n;
+ if Dos.GetShortName(hs) then
+ GetShortName:=hs;
+{$endif}
+ end;
+
+
+{****************************************************************************
+ Init / Done
+****************************************************************************}
+
+ procedure InitFileUtils;
+ begin
+ DirCache:=TDirectoryCache.Create;
+ end;
+
+
+ procedure DoneFileUtils;
+ begin
+ DirCache.Free;
+ end;
+
+end.
diff --git a/closures/compiler/cg64f32.pas b/closures/compiler/cg64f32.pas
new file mode 100644
index 0000000000..2da012c2e9
--- /dev/null
+++ b/closures/compiler/cg64f32.pas
@@ -0,0 +1,971 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+ Member of the Free Pascal development team
+
+ This unit implements the code generation for 64 bit int
+ arithmethics on 32 bit processors
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+{# This unit implements the code generation for 64 bit int arithmethics on
+ 32 bit processors.
+}
+unit cg64f32;
+
+ {$i fpcdefs.inc}
+
+ interface
+
+ uses
+ aasmbase,aasmtai,aasmdata,aasmcpu,
+ cpubase,cpupara,
+ cgbase,cgobj,parabase,cgutils,
+ symtype
+ ;
+
+ type
+ {# Defines all the methods required on 32-bit processors
+ to handle 64-bit integers.
+ }
+ tcg64f32 = class(tcg64)
+ procedure a_load64_const_ref(list : TAsmList;value : int64;const ref : treference);override;
+ procedure a_load64_reg_ref(list : TAsmList;reg : tregister64;const ref : treference);override;
+ procedure a_load64_ref_reg(list : TAsmList;const ref : treference;reg : tregister64);override;
+ procedure a_load64_reg_reg(list : TAsmList;regsrc,regdst : tregister64);override;
+ procedure a_load64_const_reg(list : TAsmList;value: int64;reg : tregister64);override;
+
+ procedure a_load64_subsetref_reg(list : TAsmList; const sref: tsubsetreference; destreg: tregister64);override;
+ procedure a_load64_reg_subsetref(list : TAsmList; fromreg: tregister64; const sref: tsubsetreference);override;
+ procedure a_load64_const_subsetref(list: TAsmlist; a: int64; const sref: tsubsetreference);override;
+ procedure a_load64_ref_subsetref(list : TAsmList; const fromref: treference; const sref: tsubsetreference);override;
+ procedure a_load64_subsetref_subsetref(list: TAsmlist; const fromsref, tosref: tsubsetreference);override;
+ procedure a_load64_subsetref_ref(list : TAsmList; const sref: tsubsetreference; const destref: treference);override;
+
+ procedure a_load64_loc_reg(list : TAsmList;const l : tlocation;reg : tregister64);override;
+ procedure a_load64_loc_ref(list : TAsmList;const l : tlocation;const ref : treference);override;
+ procedure a_load64_const_loc(list : TAsmList;value : int64;const l : tlocation);override;
+ procedure a_load64_reg_loc(list : TAsmList;reg : tregister64;const l : tlocation);override;
+
+
+
+ procedure a_load64high_reg_ref(list : TAsmList;reg : tregister;const ref : treference);override;
+ procedure a_load64low_reg_ref(list : TAsmList;reg : tregister;const ref : treference);override;
+ procedure a_load64high_ref_reg(list : TAsmList;const ref : treference;reg : tregister);override;
+ procedure a_load64low_ref_reg(list : TAsmList;const ref : treference;reg : tregister);override;
+ procedure a_load64high_loc_reg(list : TAsmList;const l : tlocation;reg : tregister);override;
+ procedure a_load64low_loc_reg(list : TAsmList;const l : tlocation;reg : tregister);override;
+
+ procedure a_op64_ref_reg(list : TAsmList;op:TOpCG;size : tcgsize;const ref : treference;reg : tregister64);override;
+ procedure a_op64_reg_ref(list : TAsmList;op:TOpCG;size : tcgsize;reg : tregister64; const ref: treference);override;
+ procedure a_op64_const_loc(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;const l: tlocation);override;
+ procedure a_op64_reg_loc(list : TAsmList;op:TOpCG;size : tcgsize;reg : tregister64;const l : tlocation);override;
+ procedure a_op64_loc_reg(list : TAsmList;op:TOpCG;size : tcgsize;const l : tlocation;reg : tregister64);override;
+ procedure a_op64_const_ref(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;const ref : treference);override;
+
+ procedure a_load64_reg_cgpara(list : TAsmList;reg : tregister64;const paraloc : tcgpara);override;
+ procedure a_load64_const_cgpara(list : TAsmList;value : int64;const paraloc : tcgpara);override;
+ procedure a_load64_ref_cgpara(list : TAsmList;const r : treference;const paraloc : tcgpara);override;
+ procedure a_load64_loc_cgpara(list : TAsmList;const l : tlocation;const paraloc : tcgpara);override;
+
+ procedure a_loadmm_intreg64_reg(list: TAsmList; mmsize: tcgsize; intreg: tregister64; mmreg: tregister);override;
+ procedure a_loadmm_reg_intreg64(list: TAsmList; mmsize: tcgsize; mmreg: tregister; intreg: tregister64);override;
+ {# This routine tries to optimize the a_op64_const_reg operation, by
+ removing superfluous opcodes. Returns TRUE if normal processing
+ must continue in op64_const_reg, otherwise, everything is processed
+ entirely in this routine, by emitting the appropriate 32-bit opcodes.
+ }
+ function optimize64_op_const_reg(list: TAsmList; var op: topcg; var a : int64; var reg: tregister64): boolean;override;
+
+ procedure g_rangecheck64(list: TAsmList; const l:tlocation;fromdef,todef: tdef); override;
+ end;
+
+ {# Creates a tregister64 record from 2 32 Bit registers. }
+ function joinreg64(reglo,reghi : tregister) : tregister64;
+
+ implementation
+
+ uses
+ globtype,systems,constexp,
+ verbose,cutils,
+ symbase,symconst,symdef,symtable,defutil,paramgr,
+ tgobj;
+
+{****************************************************************************
+ Helpers
+****************************************************************************}
+
+ function joinreg64(reglo,reghi : tregister) : tregister64;
+ begin
+ result.reglo:=reglo;
+ result.reghi:=reghi;
+ end;
+
+
+ procedure swap64(var q : int64);
+ begin
+ q:=(int64(lo(q)) shl 32) or hi(q);
+ end;
+
+
+ procedure splitparaloc64(const cgpara:tcgpara;var cgparalo,cgparahi:tcgpara);
+ var
+ paraloclo,
+ paralochi : pcgparalocation;
+ begin
+ if not(cgpara.size in [OS_64,OS_S64]) then
+ internalerror(200408231);
+ if not assigned(cgpara.location) then
+ internalerror(200408201);
+ { init lo/hi para }
+ cgparahi.reset;
+ if cgpara.size=OS_S64 then
+ cgparahi.size:=OS_S32
+ else
+ cgparahi.size:=OS_32;
+ cgparahi.intsize:=4;
+ cgparahi.alignment:=cgpara.alignment;
+ paralochi:=cgparahi.add_location;
+ cgparalo.reset;
+ cgparalo.size:=OS_32;
+ cgparalo.intsize:=4;
+ cgparalo.alignment:=cgpara.alignment;
+ paraloclo:=cgparalo.add_location;
+ { 2 parameter fields? }
+ if assigned(cgpara.location^.next) then
+ begin
+ { Order for multiple locations is always
+ paraloc^ -> high
+ paraloc^.next -> low }
+ if (target_info.endian=ENDIAN_BIG) then
+ begin
+ { paraloc^ -> high
+ paraloc^.next -> low }
+ move(cgpara.location^,paralochi^,sizeof(paralochi^));
+ move(cgpara.location^.next^,paraloclo^,sizeof(paraloclo^));
+ end
+ else
+ begin
+ { paraloc^ -> low
+ paraloc^.next -> high }
+ move(cgpara.location^,paraloclo^,sizeof(paraloclo^));
+ move(cgpara.location^.next^,paralochi^,sizeof(paralochi^));
+ end;
+ end
+ else
+ begin
+ { single parameter, this can only be in memory }
+ if cgpara.location^.loc<>LOC_REFERENCE then
+ internalerror(200408282);
+ move(cgpara.location^,paraloclo^,sizeof(paraloclo^));
+ move(cgpara.location^,paralochi^,sizeof(paralochi^));
+ { for big endian low is at +4, for little endian high }
+ if target_info.endian = endian_big then
+ begin
+ inc(cgparalo.location^.reference.offset,4);
+ cgparalo.alignment:=newalignment(cgparalo.alignment,4);
+ end
+ else
+ begin
+ inc(cgparahi.location^.reference.offset,4);
+ cgparahi.alignment:=newalignment(cgparahi.alignment,4);
+ end;
+ end;
+ { fix size }
+ paraloclo^.size:=cgparalo.size;
+ paraloclo^.next:=nil;
+ paralochi^.size:=cgparahi.size;
+ paralochi^.next:=nil;
+ end;
+
+
+{****************************************************************************
+ TCG64F32
+****************************************************************************}
+
+ procedure tcg64f32.a_load64_reg_ref(list : TAsmList;reg : tregister64;const ref : treference);
+ var
+ tmpreg: tregister;
+ tmpref: treference;
+ begin
+ if target_info.endian = endian_big then
+ begin
+ tmpreg:=reg.reglo;
+ reg.reglo:=reg.reghi;
+ reg.reghi:=tmpreg;
+ end;
+ cg.a_load_reg_ref(list,OS_32,OS_32,reg.reglo,ref);
+ tmpref := ref;
+ inc(tmpref.offset,4);
+ cg.a_load_reg_ref(list,OS_32,OS_32,reg.reghi,tmpref);
+ end;
+
+
+ procedure tcg64f32.a_load64_const_ref(list : TAsmList;value : int64;const ref : treference);
+ var
+ tmpref: treference;
+ begin
+ if target_info.endian = endian_big then
+ swap64(value);
+ cg.a_load_const_ref(list,OS_32,aint(lo(value)),ref);
+ tmpref := ref;
+ inc(tmpref.offset,4);
+ cg.a_load_const_ref(list,OS_32,aint(hi(value)),tmpref);
+ end;
+
+
+ procedure tcg64f32.a_load64_ref_reg(list : TAsmList;const ref : treference;reg : tregister64);
+ var
+ tmpreg: tregister;
+ tmpref: treference;
+ begin
+ if target_info.endian = endian_big then
+ begin
+ tmpreg := reg.reglo;
+ reg.reglo := reg.reghi;
+ reg.reghi := tmpreg;
+ end;
+ tmpref := ref;
+ if (tmpref.base=reg.reglo) then
+ begin
+ tmpreg:=cg.getaddressregister(list);
+ cg.a_load_reg_reg(list,OS_ADDR,OS_ADDR,tmpref.base,tmpreg);
+ tmpref.base:=tmpreg;
+ end
+ else
+ { this works only for the i386, thus the i386 needs to override }
+ { this method and this method must be replaced by a more generic }
+ { implementation FK }
+ if (tmpref.index=reg.reglo) then
+ begin
+ tmpreg:=cg.getaddressregister(list);
+ cg.a_load_reg_reg(list,OS_ADDR,OS_ADDR,tmpref.index,tmpreg);
+ tmpref.index:=tmpreg;
+ end;
+ cg.a_load_ref_reg(list,OS_32,OS_32,tmpref,reg.reglo);
+ inc(tmpref.offset,4);
+ cg.a_load_ref_reg(list,OS_32,OS_32,tmpref,reg.reghi);
+ end;
+
+
+ procedure tcg64f32.a_load64_reg_reg(list : TAsmList;regsrc,regdst : tregister64);
+
+ begin
+ cg.a_load_reg_reg(list,OS_32,OS_32,regsrc.reglo,regdst.reglo);
+ cg.a_load_reg_reg(list,OS_32,OS_32,regsrc.reghi,regdst.reghi);
+ end;
+
+
+ procedure tcg64f32.a_load64_const_reg(list : TAsmList;value : int64;reg : tregister64);
+
+ begin
+ cg.a_load_const_reg(list,OS_32,aint(lo(value)),reg.reglo);
+ cg.a_load_const_reg(list,OS_32,aint(hi(value)),reg.reghi);
+ end;
+
+
+ procedure tcg64f32.a_load64_subsetref_reg(list : TAsmList; const sref: tsubsetreference; destreg: tregister64);
+
+ var
+ tmpreg: tregister;
+ tmpsref: tsubsetreference;
+ begin
+ if (sref.bitindexreg <> NR_NO) or
+ (sref.bitlen <> 64) then
+ internalerror(2006082310);
+ if (sref.startbit = 0) then
+ begin
+ a_load64_ref_reg(list,sref.ref,destreg);
+ exit;
+ end;
+
+ if target_info.endian = endian_big then
+ begin
+ tmpreg := destreg.reglo;
+ destreg.reglo := destreg.reghi;
+ destreg.reghi := tmpreg;
+ end;
+ tmpsref:=sref;
+ if (tmpsref.ref.base=destreg.reglo) then
+ begin
+ tmpreg:=cg.getaddressregister(list);
+ cg.a_load_reg_reg(list,OS_ADDR,OS_ADDR,tmpsref.ref.base,tmpreg);
+ tmpsref.ref.base:=tmpreg;
+ end
+ else
+ if (tmpsref.ref.index=destreg.reglo) then
+ begin
+ tmpreg:=cg.getaddressregister(list);
+ cg.a_load_reg_reg(list,OS_ADDR,OS_ADDR,tmpsref.ref.index,tmpreg);
+ tmpsref.ref.index:=tmpreg;
+ end;
+ tmpsref.bitlen:=32;
+ cg.a_load_subsetref_reg(list,OS_32,OS_32,tmpsref,destreg.reglo);
+ inc(tmpsref.ref.offset,4);
+ cg.a_load_subsetref_reg(list,OS_32,OS_32,tmpsref,destreg.reghi);
+ end;
+
+
+ procedure tcg64f32.a_load64_reg_subsetref(list : TAsmList; fromreg: tregister64; const sref: tsubsetreference);
+
+ var
+ tmpreg: tregister;
+ tmpsref: tsubsetreference;
+ begin
+ if (sref.bitindexreg <> NR_NO) or
+ (sref.bitlen <> 64) then
+ internalerror(2006082311);
+ if (sref.startbit = 0) then
+ begin
+ a_load64_reg_ref(list,fromreg,sref.ref);
+ exit;
+ end;
+
+ if target_info.endian = endian_big then
+ begin
+ tmpreg:=fromreg.reglo;
+ fromreg.reglo:=fromreg.reghi;
+ fromreg.reghi:=tmpreg;
+ end;
+ tmpsref:=sref;
+ tmpsref.bitlen:=32;
+ cg.a_load_reg_subsetref(list,OS_32,OS_32,fromreg.reglo,tmpsref);
+ inc(tmpsref.ref.offset,4);
+ cg.a_load_reg_subsetref(list,OS_32,OS_32,fromreg.reghi,tmpsref);
+ end;
+
+
+ procedure tcg64f32.a_load64_const_subsetref(list: TAsmlist; a: int64; const sref: tsubsetreference);
+
+ var
+ tmpsref: tsubsetreference;
+ begin
+ if (sref.bitindexreg <> NR_NO) or
+ (sref.bitlen <> 64) then
+ internalerror(2006082312);
+ if target_info.endian = endian_big then
+ swap64(a);
+ tmpsref := sref;
+ tmpsref.bitlen := 32;
+ cg.a_load_const_subsetref(list,OS_32,aint(lo(a)),tmpsref);
+ inc(tmpsref.ref.offset,4);
+ cg.a_load_const_subsetref(list,OS_32,aint(hi(a)),tmpsref);
+ end;
+
+
+
+
+ procedure tcg64f32.a_load64_subsetref_subsetref(list: TAsmlist; const fromsref, tosref: tsubsetreference);
+
+ var
+ tmpreg64 : tregister64;
+ begin
+ tmpreg64.reglo:=cg.getintregister(list,OS_32);
+ tmpreg64.reghi:=cg.getintregister(list,OS_32);
+ a_load64_subsetref_reg(list,fromsref,tmpreg64);
+ a_load64_reg_subsetref(list,tmpreg64,tosref);
+ end;
+
+
+ procedure tcg64f32.a_load64_subsetref_ref(list : TAsmList; const sref: tsubsetreference; const destref: treference);
+
+ var
+ tmpreg64 : tregister64;
+ begin
+ tmpreg64.reglo:=cg.getintregister(list,OS_32);
+ tmpreg64.reghi:=cg.getintregister(list,OS_32);
+ a_load64_subsetref_reg(list,sref,tmpreg64);
+ a_load64_reg_ref(list,tmpreg64,destref);
+ end;
+
+
+ procedure tcg64f32.a_load64_ref_subsetref(list : TAsmList; const fromref: treference; const sref: tsubsetreference);
+
+ var
+ tmpreg64 : tregister64;
+ begin
+ tmpreg64.reglo:=cg.getintregister(list,OS_32);
+ tmpreg64.reghi:=cg.getintregister(list,OS_32);
+ a_load64_ref_reg(list,fromref,tmpreg64);
+ a_load64_reg_subsetref(list,tmpreg64,sref);
+ end;
+
+
+ procedure tcg64f32.a_load64_loc_reg(list : TAsmList;const l : tlocation;reg : tregister64);
+
+ begin
+ case l.loc of
+ LOC_REFERENCE, LOC_CREFERENCE:
+ a_load64_ref_reg(list,l.reference,reg);
+ LOC_REGISTER,LOC_CREGISTER:
+ a_load64_reg_reg(list,l.register64,reg);
+ LOC_CONSTANT :
+ a_load64_const_reg(list,l.value64,reg);
+ LOC_SUBSETREF, LOC_CSUBSETREF:
+ a_load64_subsetref_reg(list,l.sref,reg);
+ else
+ internalerror(200112292);
+ end;
+ end;
+
+
+ procedure tcg64f32.a_load64_loc_ref(list : TAsmList;const l : tlocation;const ref : treference);
+ begin
+ case l.loc of
+ LOC_REGISTER,LOC_CREGISTER:
+ a_load64_reg_ref(list,l.register64,ref);
+ LOC_CONSTANT :
+ a_load64_const_ref(list,l.value64,ref);
+ LOC_SUBSETREF, LOC_CSUBSETREF:
+ a_load64_subsetref_ref(list,l.sref,ref);
+ else
+ internalerror(200203288);
+ end;
+ end;
+
+
+ procedure tcg64f32.a_load64_const_loc(list : TAsmList;value : int64;const l : tlocation);
+
+ begin
+ case l.loc of
+ LOC_REFERENCE, LOC_CREFERENCE:
+ a_load64_const_ref(list,value,l.reference);
+ LOC_REGISTER,LOC_CREGISTER:
+ a_load64_const_reg(list,value,l.register64);
+ LOC_SUBSETREF, LOC_CSUBSETREF:
+ a_load64_const_subsetref(list,value,l.sref);
+ else
+ internalerror(200112293);
+ end;
+ end;
+
+
+ procedure tcg64f32.a_load64_reg_loc(list : TAsmList;reg : tregister64;const l : tlocation);
+
+ begin
+ case l.loc of
+ LOC_REFERENCE, LOC_CREFERENCE:
+ a_load64_reg_ref(list,reg,l.reference);
+ LOC_REGISTER,LOC_CREGISTER:
+ a_load64_reg_reg(list,reg,l.register64);
+ LOC_SUBSETREF, LOC_CSUBSETREF:
+ a_load64_reg_subsetref(list,reg,l.sref);
+ LOC_MMREGISTER, LOC_CMMREGISTER:
+ a_loadmm_intreg64_reg(list,l.size,reg,l.register);
+ else
+ internalerror(200112293);
+ end;
+ end;
+
+
+ procedure tcg64f32.a_load64high_reg_ref(list : TAsmList;reg : tregister;const ref : treference);
+ var
+ tmpref: treference;
+ begin
+ if target_info.endian = endian_big then
+ cg.a_load_reg_ref(list,OS_32,OS_32,reg,ref)
+ else
+ begin
+ tmpref := ref;
+ inc(tmpref.offset,4);
+ cg.a_load_reg_ref(list,OS_32,OS_32,reg,tmpref)
+ end;
+ end;
+
+ procedure tcg64f32.a_load64low_reg_ref(list : TAsmList;reg : tregister;const ref : treference);
+ var
+ tmpref: treference;
+ begin
+ if target_info.endian = endian_little then
+ cg.a_load_reg_ref(list,OS_32,OS_32,reg,ref)
+ else
+ begin
+ tmpref := ref;
+ inc(tmpref.offset,4);
+ cg.a_load_reg_ref(list,OS_32,OS_32,reg,tmpref)
+ end;
+ end;
+
+
+ procedure tcg64f32.a_load64high_ref_reg(list : TAsmList;const ref : treference;reg : tregister);
+ var
+ tmpref: treference;
+ begin
+ if target_info.endian = endian_big then
+ cg.a_load_ref_reg(list,OS_32,OS_32,ref,reg)
+ else
+ begin
+ tmpref := ref;
+ inc(tmpref.offset,4);
+ cg.a_load_ref_reg(list,OS_32,OS_32,tmpref,reg)
+ end;
+ end;
+
+
+ procedure tcg64f32.a_load64low_ref_reg(list : TAsmList;const ref : treference;reg : tregister);
+ var
+ tmpref: treference;
+ begin
+ if target_info.endian = endian_little then
+ cg.a_load_ref_reg(list,OS_32,OS_32,ref,reg)
+ else
+ begin
+ tmpref := ref;
+ inc(tmpref.offset,4);
+ cg.a_load_ref_reg(list,OS_32,OS_32,tmpref,reg)
+ end;
+ end;
+
+
+ procedure tcg64f32.a_load64low_loc_reg(list : TAsmList;const l : tlocation;reg : tregister);
+ begin
+ case l.loc of
+ LOC_REFERENCE,
+ LOC_CREFERENCE :
+ a_load64low_ref_reg(list,l.reference,reg);
+ LOC_REGISTER,
+ LOC_CREGISTER :
+ cg.a_load_reg_reg(list,OS_32,OS_32,l.register64.reglo,reg);
+ LOC_CONSTANT :
+ cg.a_load_const_reg(list,OS_32,aint(lo(l.value64)),reg);
+ else
+ internalerror(200203244);
+ end;
+ end;
+
+
+ procedure tcg64f32.a_load64high_loc_reg(list : TAsmList;const l : tlocation;reg : tregister);
+ begin
+ case l.loc of
+ LOC_REFERENCE,
+ LOC_CREFERENCE :
+ a_load64high_ref_reg(list,l.reference,reg);
+ LOC_REGISTER,
+ LOC_CREGISTER :
+ cg.a_load_reg_reg(list,OS_32,OS_32,l.register64.reghi,reg);
+ LOC_CONSTANT :
+ cg.a_load_const_reg(list,OS_32,aint(hi(l.value64)),reg);
+ else
+ internalerror(200203244);
+ end;
+ end;
+
+
+ procedure tcg64f32.a_op64_const_loc(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;const l: tlocation);
+ begin
+ case l.loc of
+ LOC_REFERENCE, LOC_CREFERENCE:
+ a_op64_const_ref(list,op,size,value,l.reference);
+ LOC_REGISTER,LOC_CREGISTER:
+ a_op64_const_reg(list,op,size,value,l.register64);
+ else
+ internalerror(200203292);
+ end;
+ end;
+
+
+ procedure tcg64f32.a_op64_reg_loc(list : TAsmList;op:TOpCG;size : tcgsize;reg : tregister64;const l : tlocation);
+ begin
+ case l.loc of
+ LOC_REFERENCE, LOC_CREFERENCE:
+ a_op64_reg_ref(list,op,size,reg,l.reference);
+ LOC_REGISTER,LOC_CREGISTER:
+ a_op64_reg_reg(list,op,size,reg,l.register64);
+ else
+ internalerror(2002032422);
+ end;
+ end;
+
+
+
+ procedure tcg64f32.a_op64_loc_reg(list : TAsmList;op:TOpCG;size : tcgsize;const l : tlocation;reg : tregister64);
+ begin
+ case l.loc of
+ LOC_REFERENCE, LOC_CREFERENCE:
+ a_op64_ref_reg(list,op,size,l.reference,reg);
+ LOC_REGISTER,LOC_CREGISTER:
+ a_op64_reg_reg(list,op,size,l.register64,reg);
+ LOC_CONSTANT :
+ a_op64_const_reg(list,op,size,l.value64,reg);
+ else
+ internalerror(200203242);
+ end;
+ end;
+
+
+ procedure tcg64f32.a_op64_ref_reg(list : TAsmList;op:TOpCG;size : tcgsize;const ref : treference;reg : tregister64);
+ var
+ tempreg: tregister64;
+ begin
+ tempreg.reghi:=cg.getintregister(list,OS_32);
+ tempreg.reglo:=cg.getintregister(list,OS_32);
+ a_load64_ref_reg(list,ref,tempreg);
+ a_op64_reg_reg(list,op,size,tempreg,reg);
+ end;
+
+
+ procedure tcg64f32.a_op64_reg_ref(list : TAsmList;op:TOpCG;size : tcgsize;reg : tregister64; const ref: treference);
+ var
+ tempreg: tregister64;
+ begin
+ tempreg.reghi:=cg.getintregister(list,OS_32);
+ tempreg.reglo:=cg.getintregister(list,OS_32);
+ a_load64_ref_reg(list,ref,tempreg);
+ a_op64_reg_reg(list,op,size,reg,tempreg);
+ a_load64_reg_ref(list,tempreg,ref);
+ end;
+
+
+ procedure tcg64f32.a_op64_const_ref(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;const ref : treference);
+ var
+ tempreg: tregister64;
+ begin
+ tempreg.reghi:=cg.getintregister(list,OS_32);
+ tempreg.reglo:=cg.getintregister(list,OS_32);
+ a_load64_ref_reg(list,ref,tempreg);
+ a_op64_const_reg(list,op,size,value,tempreg);
+ a_load64_reg_ref(list,tempreg,ref);
+ end;
+
+
+ procedure tcg64f32.a_load64_reg_cgpara(list : TAsmList;reg : tregister64;const paraloc : tcgpara);
+ var
+ tmplochi,tmploclo: tcgpara;
+ begin
+ tmploclo.init;
+ tmplochi.init;
+ splitparaloc64(paraloc,tmploclo,tmplochi);
+ { Keep this order of first hi before lo to have
+ the correct push order for i386 }
+ cg.a_load_reg_cgpara(list,OS_32,reg.reghi,tmplochi);
+ cg.a_load_reg_cgpara(list,OS_32,reg.reglo,tmploclo);
+ tmploclo.done;
+ tmplochi.done;
+ end;
+
+
+ procedure tcg64f32.a_load64_const_cgpara(list : TAsmList;value : int64;const paraloc : tcgpara);
+ var
+ tmplochi,tmploclo: tcgpara;
+ begin
+ tmploclo.init;
+ tmplochi.init;
+ splitparaloc64(paraloc,tmploclo,tmplochi);
+ { Keep this order of first hi before lo to have
+ the correct push order for i386 }
+ cg.a_load_const_cgpara(list,OS_32,aint(hi(value)),tmplochi);
+ cg.a_load_const_cgpara(list,OS_32,aint(lo(value)),tmploclo);
+ tmploclo.done;
+ tmplochi.done;
+ end;
+
+
+ procedure tcg64f32.a_load64_ref_cgpara(list : TAsmList;const r : treference;const paraloc : tcgpara);
+ var
+ tmprefhi,tmpreflo : treference;
+ tmploclo,tmplochi : tcgpara;
+ begin
+ tmploclo.init;
+ tmplochi.init;
+ splitparaloc64(paraloc,tmploclo,tmplochi);
+ tmprefhi:=r;
+ tmpreflo:=r;
+ if target_info.endian=endian_big then
+ inc(tmpreflo.offset,4)
+ else
+ inc(tmprefhi.offset,4);
+ { Keep this order of first hi before lo to have
+ the correct push order for i386 }
+ cg.a_load_ref_cgpara(list,OS_32,tmprefhi,tmplochi);
+ cg.a_load_ref_cgpara(list,OS_32,tmpreflo,tmploclo);
+ tmploclo.done;
+ tmplochi.done;
+ end;
+
+
+ procedure tcg64f32.a_load64_loc_cgpara(list : TAsmList;const l:tlocation;const paraloc : tcgpara);
+ begin
+ case l.loc of
+ LOC_REGISTER,
+ LOC_CREGISTER :
+ a_load64_reg_cgpara(list,l.register64,paraloc);
+ LOC_CONSTANT :
+ a_load64_const_cgpara(list,l.value64,paraloc);
+ LOC_CREFERENCE,
+ LOC_REFERENCE :
+ a_load64_ref_cgpara(list,l.reference,paraloc);
+ else
+ internalerror(200203287);
+ end;
+ end;
+
+
+ procedure tcg64f32.a_loadmm_intreg64_reg(list: TAsmList; mmsize: tcgsize; intreg: tregister64; mmreg: tregister);
+ var
+ tmpref: treference;
+ begin
+ if (tcgsize2size[mmsize]<>8) then
+ internalerror(2009112501);
+ tg.gettemp(list,8,8,tt_normal,tmpref);
+ a_load64_reg_ref(list,intreg,tmpref);
+ cg.a_loadmm_ref_reg(list,mmsize,mmsize,tmpref,mmreg,mms_movescalar);
+ tg.ungettemp(list,tmpref);
+ end;
+
+
+ procedure tcg64f32.a_loadmm_reg_intreg64(list: TAsmList; mmsize: tcgsize; mmreg: tregister; intreg: tregister64);
+ var
+ tmpref: treference;
+ begin
+ if (tcgsize2size[mmsize]<>8) then
+ internalerror(2009112502);
+ tg.gettemp(list,8,8,tt_normal,tmpref);
+ cg.a_loadmm_reg_ref(list,mmsize,mmsize,mmreg,tmpref,mms_movescalar);
+ a_load64_ref_reg(list,tmpref,intreg);
+ tg.ungettemp(list,tmpref);
+ end;
+
+
+ procedure tcg64f32.g_rangecheck64(list : TAsmList;const l:tlocation;fromdef,todef:tdef);
+
+ var
+ neglabel,
+ poslabel,
+ endlabel: tasmlabel;
+ hreg : tregister;
+ hdef : torddef;
+ opsize : tcgsize;
+ from_signed,to_signed: boolean;
+ temploc : tlocation;
+
+ begin
+ from_signed := is_signed(fromdef);
+ to_signed := is_signed(todef);
+
+ if not is_64bit(todef) then
+ begin
+ { get the high dword in a register }
+ if l.loc in [LOC_REGISTER,LOC_CREGISTER] then
+ begin
+ hreg := l.register64.reghi;
+ end
+ else
+ begin
+ hreg:=cg.getintregister(list,OS_32);
+ a_load64high_ref_reg(list,l.reference,hreg);
+ end;
+ current_asmdata.getjumplabel(poslabel);
+
+ { check high dword, must be 0 (for positive numbers) }
+ cg.a_cmp_const_reg_label(list,OS_32,OC_EQ,0,hreg,poslabel);
+
+ { It can also be $ffffffff, but only for negative numbers }
+ if from_signed and to_signed then
+ begin
+ current_asmdata.getjumplabel(neglabel);
+ cg.a_cmp_const_reg_label(list,OS_32,OC_EQ,-1,hreg,neglabel);
+ end;
+ { For all other values we have a range check error }
+ cg.a_call_name(list,'FPC_RANGEERROR',false);
+
+ { if the high dword = 0, the low dword can be considered a }
+ { simple cardinal }
+ cg.a_label(list,poslabel);
+ hdef:=torddef.create(u32bit,0,$ffffffff);
+
+ location_copy(temploc,l);
+ temploc.size:=OS_32;
+
+ if (temploc.loc in [LOC_REFERENCE,LOC_CREFERENCE]) and
+ (target_info.endian = endian_big) then
+ begin
+ inc(temploc.reference.offset,4);
+ temploc.reference.alignment:=newalignment(temploc.reference.alignment,4);
+ end;
+
+ cg.g_rangecheck(list,temploc,hdef,todef);
+ hdef.owner.deletedef(hdef);
+
+ if from_signed and to_signed then
+ begin
+ current_asmdata.getjumplabel(endlabel);
+ cg.a_jmp_always(list,endlabel);
+ { if the high dword = $ffffffff, then the low dword (when }
+ { considered as a longint) must be < 0 }
+ cg.a_label(list,neglabel);
+ if l.loc in [LOC_REGISTER,LOC_CREGISTER] then
+ begin
+ hreg := l.register64.reglo;
+ end
+ else
+ begin
+ hreg:=cg.getintregister(list,OS_32);
+ a_load64low_ref_reg(list,l.reference,hreg);
+ end;
+ { get a new neglabel (JM) }
+ current_asmdata.getjumplabel(neglabel);
+ cg.a_cmp_const_reg_label(list,OS_32,OC_LT,0,hreg,neglabel);
+
+ cg.a_call_name(list,'FPC_RANGEERROR',false);
+
+ { if we get here, the 64bit value lies between }
+ { longint($80000000) and -1 (JM) }
+ cg.a_label(list,neglabel);
+ hdef:=torddef.create(s32bit,int64(longint($80000000)),int64(-1));
+ location_copy(temploc,l);
+ temploc.size:=OS_32;
+ cg.g_rangecheck(list,temploc,hdef,todef);
+ hdef.owner.deletedef(hdef);
+ cg.a_label(list,endlabel);
+ end;
+ end
+ else
+ { todef = 64bit int }
+ { no 64bit subranges supported, so only a small check is necessary }
+
+ { if both are signed or both are unsigned, no problem! }
+ if (from_signed xor to_signed) and
+ { also not if the fromdef is unsigned and < 64bit, since that will }
+ { always fit in a 64bit int (todef is 64bit) }
+ (from_signed or
+ (torddef(fromdef).ordtype = u64bit)) then
+ begin
+ { in all cases, there is only a problem if the higest bit is set }
+ if l.loc in [LOC_REGISTER,LOC_CREGISTER] then
+ begin
+ if is_64bit(fromdef) then
+ begin
+ hreg := l.register64.reghi;
+ opsize := OS_32;
+ end
+ else
+ begin
+ hreg := l.register;
+ opsize := def_cgsize(fromdef);
+ end;
+ end
+ else
+ begin
+ hreg:=cg.getintregister(list,OS_32);
+ opsize:=OS_32;
+
+ if l.size in [OS_64,OS_S64] then
+ a_load64high_ref_reg(list,l.reference,hreg)
+ else
+ cg.a_load_ref_reg(list,l.size,OS_32,l.reference,hreg);
+ end;
+ current_asmdata.getjumplabel(poslabel);
+ cg.a_cmp_const_reg_label(list,opsize,OC_GTE,0,hreg,poslabel);
+
+ cg.a_call_name(list,'FPC_RANGEERROR',false);
+ cg.a_label(list,poslabel);
+ end;
+ end;
+
+
+ function tcg64f32.optimize64_op_const_reg(list: TAsmList; var op: topcg; var a : int64; var reg: tregister64): boolean;
+ var
+ lowvalue, highvalue : longint;
+ hreg: tregister;
+ begin
+ lowvalue := longint(a);
+ highvalue:= longint(a shr 32);
+ { assume it will be optimized out }
+ optimize64_op_const_reg := true;
+ case op of
+ OP_ADD:
+ begin
+ if a = 0 then
+ exit;
+ end;
+ OP_AND:
+ begin
+ if lowvalue <> -1 then
+ cg.a_op_const_reg(list,op,OS_32,lowvalue,reg.reglo);
+ if highvalue <> -1 then
+ cg.a_op_const_reg(list,op,OS_32,highvalue,reg.reghi);
+ { already emitted correctly }
+ exit;
+ end;
+ OP_OR:
+ begin
+ if lowvalue <> 0 then
+ cg.a_op_const_reg(list,op,OS_32,lowvalue,reg.reglo);
+ if highvalue <> 0 then
+ cg.a_op_const_reg(list,op,OS_32,highvalue,reg.reghi);
+ { already emitted correctly }
+ exit;
+ end;
+ OP_SUB:
+ begin
+ if a = 0 then
+ exit;
+ end;
+ OP_XOR:
+ begin
+ end;
+ OP_SHL:
+ begin
+ if a = 0 then
+ exit;
+ { simply clear low-register
+ and shift the rest and swap
+ registers.
+ }
+ if (a > 31) then
+ begin
+ cg.a_load_const_reg(list,OS_32,0,reg.reglo);
+ cg.a_op_const_reg(list,OP_SHL,OS_32,a mod 32,reg.reghi);
+ { swap the registers }
+ hreg := reg.reghi;
+ reg.reghi := reg.reglo;
+ reg.reglo := hreg;
+ exit;
+ end;
+ end;
+ OP_SHR:
+ begin
+ if a = 0 then exit;
+ { simply clear high-register
+ and shift the rest and swap
+ registers.
+ }
+ if (a > 31) then
+ begin
+ cg.a_load_const_reg(list,OS_32,0,reg.reghi);
+ cg.a_op_const_reg(list,OP_SHL,OS_32,a mod 32,reg.reglo);
+ { swap the registers }
+ hreg := reg.reghi;
+ reg.reghi := reg.reglo;
+ reg.reglo := hreg;
+ exit;
+ end;
+ end;
+ OP_IMUL,OP_MUL:
+ begin
+ if a = 1 then exit;
+ end;
+ OP_IDIV,OP_DIV:
+ begin
+ if a = 1 then exit;
+ end;
+ else
+ internalerror(20020817);
+ end;
+ optimize64_op_const_reg := false;
+ end;
+
+end.
diff --git a/closures/compiler/cgbase.pas b/closures/compiler/cgbase.pas
new file mode 100644
index 0000000000..08f130bad8
--- /dev/null
+++ b/closures/compiler/cgbase.pas
@@ -0,0 +1,693 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Some basic types and constants for the code generation
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+{# This unit exports some types which are used across the code generator }
+unit cgbase;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ globtype,
+ symconst;
+
+ type
+ { Location types where value can be stored }
+ TCGLoc=(
+ LOC_INVALID, { added for tracking problems}
+ LOC_VOID, { no value is available }
+ LOC_CONSTANT, { constant value }
+ LOC_JUMP, { boolean results only, jump to false or true label }
+ LOC_FLAGS, { boolean results only, flags are set }
+ LOC_REGISTER, { in a processor register }
+ LOC_CREGISTER, { Constant register which shouldn't be modified }
+ LOC_FPUREGISTER, { FPU stack }
+ LOC_CFPUREGISTER, { if it is a FPU register variable on the fpu stack }
+ LOC_MMXREGISTER, { MMX register }
+ { MMX register variable }
+ LOC_CMMXREGISTER,
+ { multimedia register }
+ LOC_MMREGISTER,
+ { Constant multimedia reg which shouldn't be modified }
+ LOC_CMMREGISTER,
+ { contiguous subset of bits of an integer register }
+ LOC_SUBSETREG,
+ LOC_CSUBSETREG,
+ { contiguous subset of bits in memory }
+ LOC_SUBSETREF,
+ LOC_CSUBSETREF,
+ { keep these last for range checking purposes }
+ LOC_CREFERENCE, { in memory constant value reference (cannot change) }
+ LOC_REFERENCE { in memory value }
+ );
+
+ TCGNonRefLoc=low(TCGLoc)..pred(LOC_CREFERENCE);
+ TCGRefLoc=LOC_CREFERENCE..LOC_REFERENCE;
+
+ { since we have only 16bit offsets, we need to be able to specify the high
+ and lower 16 bits of the address of a symbol of up to 64 bit }
+ trefaddr = (
+ addr_no,
+ addr_full,
+ addr_pic,
+ addr_pic_no_got
+ {$IF defined(POWERPC) or defined(POWERPC64) or defined(SPARC) or defined(MIPS)}
+ ,
+ addr_low, // bits 48-63
+ addr_high, // bits 32-47
+ {$IF defined(POWERPC64)}
+ addr_higher, // bits 16-31
+ addr_highest, // bits 00-15
+ {$ENDIF}
+ addr_higha // bits 16-31, adjusted
+ {$IF defined(POWERPC64)}
+ ,
+ addr_highera, // bits 32-47, adjusted
+ addr_highesta // bits 48-63, adjusted
+ {$ENDIF}
+ {$ENDIF}
+ {$IFDEF AVR}
+ ,addr_lo8
+ ,addr_hi8
+ {$ENDIF}
+ );
+
+
+ {# Generic opcodes, which must be supported by all processors
+ }
+ topcg =
+ (
+ OP_NONE,
+ OP_MOVE, { replaced operation with direct load }
+ OP_ADD, { simple addition }
+ OP_AND, { simple logical and }
+ OP_DIV, { simple unsigned division }
+ OP_IDIV, { simple signed division }
+ OP_IMUL, { simple signed multiply }
+ OP_MUL, { simple unsigned multiply }
+ OP_NEG, { simple negate }
+ OP_NOT, { simple logical not }
+ OP_OR, { simple logical or }
+ OP_SAR, { arithmetic shift-right }
+ OP_SHL, { logical shift left }
+ OP_SHR, { logical shift right }
+ OP_SUB, { simple subtraction }
+ OP_XOR, { simple exclusive or }
+ OP_ROL, { rotate left }
+ OP_ROR { rotate right }
+ );
+
+ {# Generic flag values - used for jump locations }
+ TOpCmp =
+ (
+ OC_NONE,
+ OC_EQ, { equality comparison }
+ OC_GT, { greater than (signed) }
+ OC_LT, { less than (signed) }
+ OC_GTE, { greater or equal than (signed) }
+ OC_LTE, { less or equal than (signed) }
+ OC_NE, { not equal }
+ OC_BE, { less or equal than (unsigned) }
+ OC_B, { less than (unsigned) }
+ OC_AE, { greater or equal than (unsigned) }
+ OC_A { greater than (unsigned) }
+ );
+
+ { OS_NO is also used memory references with large data that can
+ not be loaded in a register directly }
+ TCgSize = (OS_NO,
+ { integer registers }
+ OS_8,OS_16,OS_32,OS_64,OS_128,OS_S8,OS_S16,OS_S32,OS_S64,OS_S128,
+ { single,double,extended,comp,float128 }
+ OS_F32,OS_F64,OS_F80,OS_C64,OS_F128,
+ { multi-media sizes: split in byte, word, dword, ... }
+ { entities, then the signed counterparts }
+ OS_M8,OS_M16,OS_M32,OS_M64,OS_M128,
+ OS_MS8,OS_MS16,OS_MS32,OS_MS64,OS_MS128);
+
+ { Register types }
+ TRegisterType = (
+ R_INVALIDREGISTER, { = 0 }
+ R_INTREGISTER, { = 1 }
+ R_FPUREGISTER, { = 2 }
+ { used by Intel only }
+ R_MMXREGISTER, { = 3 }
+ R_MMREGISTER, { = 4 }
+ R_SPECIALREGISTER, { = 5 }
+ R_ADDRESSREGISTER { = 6 }
+ );
+
+ { Sub registers }
+ TSubRegister = (
+ R_SUBNONE, { = 0; no sub register possible }
+ R_SUBL, { = 1; 8 bits, Like AL }
+ R_SUBH, { = 2; 8 bits, Like AH }
+ R_SUBW, { = 3; 16 bits, Like AX }
+ R_SUBD, { = 4; 32 bits, Like EAX }
+ R_SUBQ, { = 5; 64 bits, Like RAX }
+ { For Sparc floats that use F0:F1 to store doubles }
+ R_SUBFS, { = 6; Float that allocates 1 FPU register }
+ R_SUBFD, { = 7; Float that allocates 2 FPU registers }
+ R_SUBFQ, { = 8; Float that allocates 4 FPU registers }
+ R_SUBMMS, { = 9; single scalar in multi media register }
+ R_SUBMMD, { = 10; double scalar in multi media register }
+ R_SUBMMWHOLE { = 11; complete MM register, size depends on CPU }
+ );
+ TSubRegisterSet = set of TSubRegister;
+
+ TSuperRegister = type word;
+
+ {
+ The new register coding:
+
+ SuperRegister (bits 0..15)
+ Subregister (bits 16..23)
+ Register type (bits 24..31)
+
+ TRegister is defined as an enum to make it incompatible
+ with TSuperRegister to avoid mixing them
+ }
+ TRegister = (
+ TRegisterLowEnum := Low(longint),
+ TRegisterHighEnum := High(longint)
+ );
+ TRegisterRec=packed record
+{$ifdef FPC_BIG_ENDIAN}
+ regtype : Tregistertype;
+ subreg : Tsubregister;
+ supreg : Tsuperregister;
+{$else FPC_BIG_ENDIAN}
+ supreg : Tsuperregister;
+ subreg : Tsubregister;
+ regtype : Tregistertype;
+{$endif FPC_BIG_ENDIAN}
+ end;
+
+ { A type to store register locations for 64 Bit values. }
+{$ifdef cpu64bitalu}
+ tregister64 = tregister;
+{$else cpu64bitalu}
+ tregister64 = record
+ reglo,reghi : tregister;
+ end;
+{$endif cpu64bitalu}
+
+ Tregistermmxset = record
+ reg0,reg1,reg2,reg3:Tregister
+ end;
+
+ { Set type definition for registers }
+ tcpuregisterset = set of byte;
+ tsuperregisterset = array[byte] of set of byte;
+
+ pmmshuffle = ^tmmshuffle;
+
+ { this record describes shuffle operations for mm operations; if a pointer a shuffle record
+ passed to an mm operation is nil, it means that the whole location is moved }
+ tmmshuffle = record
+ { describes how many shuffles are actually described, if len=0 then
+ moving the scalar with index 0 to the scalar with index 0 is meant }
+ len : byte;
+ { lower nibble of each entry of this array describes index of the source data index while
+ the upper nibble describes the destination index }
+ shuffles : array[1..1] of byte;
+ end;
+
+ Tsuperregisterarray=array[0..$ffff] of Tsuperregister;
+ Psuperregisterarray=^Tsuperregisterarray;
+
+ Tsuperregisterworklist=object
+ buflength,
+ buflengthinc,
+ length:word;
+ buf:Psuperregisterarray;
+ constructor init;
+ constructor copyfrom(const x:Tsuperregisterworklist);
+ destructor done;
+ procedure clear;
+ procedure add(s:tsuperregister);
+ function addnodup(s:tsuperregister): boolean;
+ function get:tsuperregister;
+ function readidx(i:word):tsuperregister;
+ procedure deleteidx(i:word);
+ function delete(s:tsuperregister):boolean;
+ end;
+ psuperregisterworklist=^tsuperregisterworklist;
+
+ const
+ { alias for easier understanding }
+ R_SSEREGISTER = R_MMREGISTER;
+
+ { Invalid register number }
+ RS_INVALID = high(tsuperregister);
+
+ { Maximum number of cpu registers per register type,
+ this must fit in tcpuregisterset }
+ maxcpuregister = 32;
+
+ tcgsize2size : Array[tcgsize] of integer =
+ { integer values }
+ (0,1,2,4,8,16,1,2,4,8,16,
+ { floating point values }
+ 4,8,10,8,16,
+ { multimedia values }
+ 1,2,4,8,16,1,2,4,8,16);
+
+ tfloat2tcgsize: array[tfloattype] of tcgsize =
+ (OS_F32,OS_F64,OS_F80,OS_F80,OS_C64,OS_C64,OS_F128);
+
+ tcgsize2tfloat: array[OS_F32..OS_C64] of tfloattype =
+ (s32real,s64real,s80real,s64comp);
+
+ tvarregable2tcgloc : array[tvarregable] of tcgloc = (LOC_VOID,
+ LOC_CREGISTER,LOC_CFPUREGISTER,LOC_CMMREGISTER,LOC_CREGISTER);
+
+ { Table to convert tcgsize variables to the correspondending
+ unsigned types }
+ tcgsize2unsigned : array[tcgsize] of tcgsize = (OS_NO,
+ OS_8,OS_16,OS_32,OS_64,OS_128,OS_8,OS_16,OS_32,OS_64,OS_128,
+ OS_F32,OS_F64,OS_F80,OS_C64,OS_F128,
+ OS_M8,OS_M16,OS_M32,OS_M64,OS_M128,OS_M8,OS_M16,OS_M32,
+ OS_M64,OS_M128);
+
+ tcgloc2str : array[TCGLoc] of string[12] = (
+ 'LOC_INVALID',
+ 'LOC_VOID',
+ 'LOC_CONST',
+ 'LOC_JUMP',
+ 'LOC_FLAGS',
+ 'LOC_REG',
+ 'LOC_CREG',
+ 'LOC_FPUREG',
+ 'LOC_CFPUREG',
+ 'LOC_MMXREG',
+ 'LOC_CMMXREG',
+ 'LOC_MMREG',
+ 'LOC_CMMREG',
+ 'LOC_SSETREG',
+ 'LOC_CSSETREG',
+ 'LOC_SSETREF',
+ 'LOC_CSSETREF',
+ 'LOC_CREF',
+ 'LOC_REF'
+ );
+
+ var
+ mms_movescalar : pmmshuffle;
+
+ procedure supregset_reset(var regs:tsuperregisterset;setall:boolean;
+ maxreg:Tsuperregister);{$ifdef USEINLINE}inline;{$endif}
+ procedure supregset_include(var regs:tsuperregisterset;s:tsuperregister);{$ifdef USEINLINE}inline;{$endif}
+ procedure supregset_exclude(var regs:tsuperregisterset;s:tsuperregister);{$ifdef USEINLINE}inline;{$endif}
+ function supregset_in(const regs:tsuperregisterset;s:tsuperregister):boolean;{$ifdef USEINLINE}inline;{$endif}
+
+ function newreg(rt:tregistertype;sr:tsuperregister;sb:tsubregister):tregister;{$ifdef USEINLINE}inline;{$endif}
+ function getsubreg(r:tregister):tsubregister;{$ifdef USEINLINE}inline;{$endif}
+ function getsupreg(r:tregister):tsuperregister;{$ifdef USEINLINE}inline;{$endif}
+ function getregtype(r:tregister):tregistertype;{$ifdef USEINLINE}inline;{$endif}
+ procedure setsubreg(var r:tregister;sr:tsubregister);{$ifdef USEINLINE}inline;{$endif}
+ procedure setsupreg(var r:tregister;sr:tsuperregister);{$ifdef USEINLINE}inline;{$endif}
+ function generic_regname(r:tregister):string;
+
+ {# From a constant numeric value, return the abstract code generator
+ size.
+ }
+ function int_cgsize(const a: tcgint): tcgsize;{$ifdef USEINLINE}inline;{$endif}
+ function int_float_cgsize(const a: tcgint): tcgsize;
+
+ { return the inverse condition of opcmp }
+ function inverse_opcmp(opcmp: topcmp): topcmp;{$ifdef USEINLINE}inline;{$endif}
+
+ { return the opcmp needed when swapping the operands }
+ function swap_opcmp(opcmp: topcmp): topcmp;{$ifdef USEINLINE}inline;{$endif}
+
+ { return whether op is commutative }
+ function commutativeop(op: topcg): boolean;{$ifdef USEINLINE}inline;{$endif}
+
+ { returns true, if shuffle describes a real shuffle operation and not only a move }
+ function realshuffle(shuffle : pmmshuffle) : boolean;
+
+ { returns true, if the shuffle describes only a move of the scalar at index 0 }
+ function shufflescalar(shuffle : pmmshuffle) : boolean;
+
+ { removes shuffling from shuffle, this means that the destenation index of each shuffle is copied to
+ the source }
+ procedure removeshuffles(var shuffle : tmmshuffle);
+
+implementation
+
+ uses
+ verbose;
+
+{******************************************************************************
+ tsuperregisterworklist
+******************************************************************************}
+
+ constructor tsuperregisterworklist.init;
+
+ begin
+ length:=0;
+ buflength:=0;
+ buflengthinc:=16;
+ buf:=nil;
+ end;
+
+ constructor Tsuperregisterworklist.copyfrom(const x:Tsuperregisterworklist);
+
+ begin
+ self:=x;
+ if x.buf<>nil then
+ begin
+ getmem(buf,buflength*sizeof(Tsuperregister));
+ move(x.buf^,buf^,length*sizeof(Tsuperregister));
+ end;
+ end;
+
+ destructor tsuperregisterworklist.done;
+
+ begin
+ if assigned(buf) then
+ freemem(buf);
+ end;
+
+
+ procedure tsuperregisterworklist.add(s:tsuperregister);
+
+ begin
+ inc(length);
+ { Need to increase buffer length? }
+ if length>=buflength then
+ begin
+ inc(buflength,buflengthinc);
+ buflengthinc:=buflengthinc*2;
+ if buflengthinc>256 then
+ buflengthinc:=256;
+ reallocmem(buf,buflength*sizeof(Tsuperregister));
+ end;
+ buf^[length-1]:=s;
+ end;
+
+
+ function tsuperregisterworklist.addnodup(s:tsuperregister): boolean;
+
+ begin
+ addnodup := false;
+ if indexword(buf^,length,s) = -1 then
+ begin
+ add(s);
+ addnodup := true;
+ end;
+ end;
+
+
+ procedure tsuperregisterworklist.clear;
+
+ begin
+ length:=0;
+ end;
+
+
+ procedure tsuperregisterworklist.deleteidx(i:word);
+
+ begin
+ if i>=length then
+ internalerror(200310144);
+ buf^[i]:=buf^[length-1];
+ dec(length);
+ end;
+
+
+ function tsuperregisterworklist.readidx(i:word):tsuperregister;
+ begin
+ if (i >= length) then
+ internalerror(2005010601);
+ result := buf^[i];
+ end;
+
+
+ function tsuperregisterworklist.get:tsuperregister;
+
+ begin
+ if length=0 then
+ internalerror(200310142);
+ get:=buf^[0];
+ buf^[0]:=buf^[length-1];
+ dec(length);
+ end;
+
+
+ function tsuperregisterworklist.delete(s:tsuperregister):boolean;
+
+ var
+ i:longint;
+
+ begin
+ delete:=false;
+ { indexword in 1.0.x and 1.9.4 is broken }
+ i:=indexword(buf^,length,s);
+ if i<>-1 then
+ begin
+ deleteidx(i);
+ delete := true;
+ end;
+ end;
+
+
+ procedure supregset_reset(var regs:tsuperregisterset;setall:boolean;
+ maxreg:Tsuperregister);{$ifdef USEINLINE}inline;{$endif}
+
+ begin
+ fillchar(regs,(maxreg+7) shr 3,-byte(setall));
+ end;
+
+
+ procedure supregset_include(var regs:tsuperregisterset;s:tsuperregister);{$ifdef USEINLINE}inline;{$endif}
+ begin
+ include(regs[s shr 8],(s and $ff));
+ end;
+
+
+ procedure supregset_exclude(var regs:tsuperregisterset;s:tsuperregister);{$ifdef USEINLINE}inline;{$endif}
+ begin
+ exclude(regs[s shr 8],(s and $ff));
+ end;
+
+
+ function supregset_in(const regs:tsuperregisterset;s:tsuperregister):boolean;{$ifdef USEINLINE}inline;{$endif}
+ begin
+ result:=(s and $ff) in regs[s shr 8];
+ end;
+
+
+ function newreg(rt:tregistertype;sr:tsuperregister;sb:tsubregister):tregister;{$ifdef USEINLINE}inline;{$endif}
+ begin
+ tregisterrec(result).regtype:=rt;
+ tregisterrec(result).supreg:=sr;
+ tregisterrec(result).subreg:=sb;
+ end;
+
+
+ function getsubreg(r:tregister):tsubregister;{$ifdef USEINLINE}inline;{$endif}
+ begin
+ result:=tregisterrec(r).subreg;
+ end;
+
+
+ function getsupreg(r:tregister):tsuperregister;{$ifdef USEINLINE}inline;{$endif}
+ begin
+ result:=tregisterrec(r).supreg;
+ end;
+
+
+ function getregtype(r:tregister):tregistertype;{$ifdef USEINLINE}inline;{$endif}
+ begin
+ result:=tregisterrec(r).regtype;
+ end;
+
+
+ procedure setsubreg(var r:tregister;sr:tsubregister);{$ifdef USEINLINE}inline;{$endif}
+ begin
+ tregisterrec(r).subreg:=sr;
+ end;
+
+
+ procedure setsupreg(var r:tregister;sr:tsuperregister);{$ifdef USEINLINE}inline;{$endif}
+ begin
+ tregisterrec(r).supreg:=sr;
+ end;
+
+
+ function generic_regname(r:tregister):string;
+ var
+ nr : string[12];
+ begin
+ str(getsupreg(r),nr);
+ case getregtype(r) of
+ R_INTREGISTER:
+ result:='ireg'+nr;
+ R_FPUREGISTER:
+ result:='freg'+nr;
+ R_MMREGISTER:
+ result:='mreg'+nr;
+ R_MMXREGISTER:
+ result:='xreg'+nr;
+ R_ADDRESSREGISTER:
+ result:='areg'+nr;
+ R_SPECIALREGISTER:
+ result:='sreg'+nr;
+ else
+ begin
+ result:='INVALID';
+ exit;
+ end;
+ end;
+ case getsubreg(r) of
+ R_SUBNONE:
+ ;
+ R_SUBL:
+ result:=result+'l';
+ R_SUBH:
+ result:=result+'h';
+ R_SUBW:
+ result:=result+'w';
+ R_SUBD:
+ result:=result+'d';
+ R_SUBQ:
+ result:=result+'q';
+ R_SUBFS:
+ result:=result+'fs';
+ R_SUBFD:
+ result:=result+'fd';
+ R_SUBMMD:
+ result:=result+'md';
+ R_SUBMMS:
+ result:=result+'ms';
+ R_SUBMMWHOLE:
+ result:=result+'ma';
+ else
+ internalerror(200308252);
+ end;
+ end;
+
+
+ function int_cgsize(const a: tcgint): tcgsize;{$ifdef USEINLINE}inline;{$endif}
+ const
+ size2cgsize : array[0..8] of tcgsize = (
+ OS_NO,OS_8,OS_16,OS_NO,OS_32,OS_NO,OS_NO,OS_NO,OS_64
+ );
+ begin
+ if a>8 then
+ result:=OS_NO
+ else
+ result:=size2cgsize[a];
+ end;
+
+
+ function int_float_cgsize(const a: tcgint): tcgsize;
+ begin
+ case a of
+ 4 :
+ result:=OS_F32;
+ 8 :
+ result:=OS_F64;
+ 10 :
+ result:=OS_F80;
+ 16 :
+ result:=OS_F128;
+ else
+ internalerror(200603211);
+ end;
+ end;
+
+
+ function inverse_opcmp(opcmp: topcmp): topcmp;{$ifdef USEINLINE}inline;{$endif}
+ const
+ list: array[TOpCmp] of TOpCmp =
+ (OC_NONE,OC_NE,OC_LTE,OC_GTE,OC_LT,OC_GT,OC_EQ,OC_A,OC_AE,
+ OC_B,OC_BE);
+ begin
+ inverse_opcmp := list[opcmp];
+ end;
+
+
+ function swap_opcmp(opcmp: topcmp): topcmp;{$ifdef USEINLINE}inline;{$endif}
+ const
+ list: array[TOpCmp] of TOpCmp =
+ (OC_NONE,OC_EQ,OC_LT,OC_GT,OC_LTE,OC_GTE,OC_NE,OC_AE,OC_A,
+ OC_BE,OC_B);
+ begin
+ swap_opcmp := list[opcmp];
+ end;
+
+
+ function commutativeop(op: topcg): boolean;{$ifdef USEINLINE}inline;{$endif}
+ const
+ list: array[topcg] of boolean =
+ (true,false,true,true,false,false,true,true,false,false,
+ true,false,false,false,false,true,false,false);
+ begin
+ commutativeop := list[op];
+ end;
+
+
+ function realshuffle(shuffle : pmmshuffle) : boolean;
+ var
+ i : longint;
+ begin
+ realshuffle:=true;
+ if (shuffle=nil) or (shuffle^.len=0) then
+ realshuffle:=false
+ else
+ begin
+ for i:=1 to shuffle^.len do
+ begin
+ if (shuffle^.shuffles[i] and $f)<>((shuffle^.shuffles[i] and $f0) shr 4) then
+ exit;
+ end;
+ realshuffle:=false;
+ end;
+ end;
+
+
+ function shufflescalar(shuffle : pmmshuffle) : boolean;
+ begin
+ result:=shuffle^.len=0;
+ end;
+
+
+ procedure removeshuffles(var shuffle : tmmshuffle);
+ var
+ i : longint;
+ begin
+ if shuffle.len=0 then
+ exit;
+ for i:=1 to shuffle.len do
+ shuffle.shuffles[i]:=(shuffle.shuffles[i] and $f) or ((shuffle.shuffles[i] and $f0) shr 4);
+ end;
+
+
+initialization
+ new(mms_movescalar);
+ mms_movescalar^.len:=0;
+finalization
+ dispose(mms_movescalar);
+end.
diff --git a/closures/compiler/cgobj.pas b/closures/compiler/cgobj.pas
new file mode 100644
index 0000000000..7f78586aff
--- /dev/null
+++ b/closures/compiler/cgobj.pas
@@ -0,0 +1,4395 @@
+{
+ Copyright (c) 1998-2005 by Florian Klaempfl
+ Member of the Free Pascal development team
+
+ This unit implements the basic code generator object
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+{# @abstract(Abstract code generator unit)
+ Abstreact code generator unit. This contains the base class
+ to implement for all new supported processors.
+
+ WARNING: None of the routines implemented in these modules,
+ or their descendants, should use the temp. allocator, as
+ these routines may be called inside genentrycode, and the
+ stack frame is already setup!
+}
+unit cgobj;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ cclasses,globtype,constexp,
+ cpubase,cgbase,cgutils,parabase,
+ aasmbase,aasmtai,aasmdata,aasmcpu,
+ symconst,symtype,symdef,rgobj
+ ;
+
+ type
+ talignment = (AM_NATURAL,AM_NONE,AM_2BYTE,AM_4BYTE,AM_8BYTE);
+ tsubsetloadopt = (SL_REG,SL_REGNOSRCMASK,SL_SETZERO,SL_SETMAX);
+
+ {# @abstract(Abstract code generator)
+ This class implements an abstract instruction generator. Some of
+ the methods of this class are generic, while others must
+ be overridden for all new processors which will be supported
+ by Free Pascal. For 32-bit processors, the base class
+ should be @link(tcg64f32) and not @var(tcg).
+ }
+ tcg = class
+ public
+ { how many times is this current code executed }
+ executionweight : longint;
+ alignment : talignment;
+ rg : array[tregistertype] of trgobj;
+ {$ifdef flowgraph}
+ aktflownode:word;
+ {$endif}
+ {************************************************}
+ { basic routines }
+ constructor create;
+
+ {# Initialize the register allocators needed for the codegenerator.}
+ procedure init_register_allocators;virtual;
+ {# Clean up the register allocators needed for the codegenerator.}
+ procedure done_register_allocators;virtual;
+ {# Set whether live_start or live_end should be updated when allocating registers, needed when e.g. generating initcode after the rest of the code. }
+ procedure set_regalloc_live_range_direction(dir: TRADirection);
+
+ {$ifdef flowgraph}
+ procedure init_flowgraph;
+ procedure done_flowgraph;
+ {$endif}
+ {# Gets a register suitable to do integer operations on.}
+ function getintregister(list:TAsmList;size:Tcgsize):Tregister;virtual;
+ {# Gets a register suitable to do integer operations on.}
+ function getaddressregister(list:TAsmList):Tregister;virtual;
+ function getfpuregister(list:TAsmList;size:Tcgsize):Tregister;virtual;
+ function getmmregister(list:TAsmList;size:Tcgsize):Tregister;virtual;
+ function getflagregister(list:TAsmList;size:Tcgsize):Tregister;virtual;
+ {Does the generic cg need SIMD registers, like getmmxregister? Or should
+ the cpu specific child cg object have such a method?}
+
+ procedure add_reg_instruction(instr:Tai;r:tregister);virtual;
+ procedure add_move_instruction(instr:Taicpu);virtual;
+
+ function uses_registers(rt:Tregistertype):boolean;virtual;
+ {# Get a specific register.}
+ procedure getcpuregister(list:TAsmList;r:Tregister);virtual;
+ procedure ungetcpuregister(list:TAsmList;r:Tregister);virtual;
+ {# Get multiple registers specified.}
+ procedure alloccpuregisters(list:TAsmList;rt:Tregistertype;const r:Tcpuregisterset);virtual;
+ {# Free multiple registers specified.}
+ procedure dealloccpuregisters(list:TAsmList;rt:Tregistertype;const r:Tcpuregisterset);virtual;
+
+ procedure allocallcpuregisters(list:TAsmList);virtual;
+ procedure deallocallcpuregisters(list:TAsmList);virtual;
+ procedure do_register_allocation(list:TAsmList;headertai:tai);virtual;
+ procedure translate_register(var reg : tregister);
+
+ function makeregsize(list:TAsmList;reg:Tregister;size:Tcgsize):Tregister;
+
+ {# Emit a label to the instruction stream. }
+ procedure a_label(list : TAsmList;l : tasmlabel);virtual;
+
+ {# Allocates register r by inserting a pai_realloc record }
+ procedure a_reg_alloc(list : TAsmList;r : tregister);
+ {# Deallocates register r by inserting a pa_regdealloc record}
+ procedure a_reg_dealloc(list : TAsmList;r : tregister);
+ { Synchronize register, make sure it is still valid }
+ procedure a_reg_sync(list : TAsmList;r : tregister);
+
+ {# Pass a parameter, which is located in a register, to a routine.
+
+ This routine should push/send the parameter to the routine, as
+ required by the specific processor ABI and routine modifiers.
+ It must generate register allocation information for the cgpara in
+ case it consists of cpuregisters.
+
+ @param(size size of the operand in the register)
+ @param(r register source of the operand)
+ @param(cgpara where the parameter will be stored)
+ }
+ procedure a_load_reg_cgpara(list : TAsmList;size : tcgsize;r : tregister;const cgpara : TCGPara);virtual;
+ {# Pass a parameter, which is a constant, to a routine.
+
+ A generic version is provided. This routine should
+ be overridden for optimization purposes if the cpu
+ permits directly sending this type of parameter.
+ It must generate register allocation information for the cgpara in
+ case it consists of cpuregisters.
+
+ @param(size size of the operand in constant)
+ @param(a value of constant to send)
+ @param(cgpara where the parameter will be stored)
+ }
+ procedure a_load_const_cgpara(list : TAsmList;size : tcgsize;a : tcgint;const cgpara : TCGPara);virtual;
+ {# Pass the value of a parameter, which is located in memory, to a routine.
+
+ A generic version is provided. This routine should
+ be overridden for optimization purposes if the cpu
+ permits directly sending this type of parameter.
+ It must generate register allocation information for the cgpara in
+ case it consists of cpuregisters.
+
+ @param(size size of the operand in constant)
+ @param(r Memory reference of value to send)
+ @param(cgpara where the parameter will be stored)
+ }
+ procedure a_load_ref_cgpara(list : TAsmList;size : tcgsize;const r : treference;const cgpara : TCGPara);virtual;
+ {# Pass the value of a parameter, which can be located either in a register or memory location,
+ to a routine.
+
+ A generic version is provided.
+
+ @param(l location of the operand to send)
+ @param(nr parameter number (starting from one) of routine (from left to right))
+ @param(cgpara where the parameter will be stored)
+ }
+ procedure a_load_loc_cgpara(list : TAsmList;const l : tlocation;const cgpara : TCGPara);
+ {# Pass the address of a reference to a routine. This routine
+ will calculate the address of the reference, and pass this
+ calculated address as a parameter.
+ It must generate register allocation information for the cgpara in
+ case it consists of cpuregisters.
+
+ A generic version is provided. This routine should
+ be overridden for optimization purposes if the cpu
+ permits directly sending this type of parameter.
+
+ @param(r reference to get address from)
+ @param(nr parameter number (starting from one) of routine (from left to right))
+ }
+ procedure a_loadaddr_ref_cgpara(list : TAsmList;const r : treference;const cgpara : TCGPara);virtual;
+
+ {# Load a cgparaloc into a memory reference.
+ It must generate register allocation information for the cgpara in
+ case it consists of cpuregisters.
+
+ @param(paraloc the source parameter sublocation)
+ @param(ref the destination reference)
+ @param(sizeleft indicates the total number of bytes left in all of
+ the remaining sublocations of this parameter (the current
+ sublocation and all of the sublocations coming after it).
+ In case this location is also a reference, it is assumed
+ to be the final part sublocation of the parameter and that it
+ contains all of the "sizeleft" bytes).)
+ @param(align the alignment of the paraloc in case it's a reference)
+ }
+ procedure a_load_cgparaloc_ref(list : TAsmList;const paraloc : TCGParaLocation;const ref : treference;sizeleft : tcgint;align : longint);
+
+ {# Load a cgparaloc into any kind of register (int, fp, mm).
+
+ @param(regsize the size of the destination register)
+ @param(paraloc the source parameter sublocation)
+ @param(reg the destination register)
+ @param(align the alignment of the paraloc in case it's a reference)
+ }
+ procedure a_load_cgparaloc_anyreg(list : TAsmList;regsize : tcgsize;const paraloc : TCGParaLocation;reg : tregister;align : longint);
+
+ { Remarks:
+ * If a method specifies a size you have only to take care
+ of that number of bits, i.e. load_const_reg with OP_8 must
+ only load the lower 8 bit of the specified register
+ the rest of the register can be undefined
+ if necessary the compiler will call a method
+ to zero or sign extend the register
+ * The a_load_XX_XX with OP_64 needn't to be
+ implemented for 32 bit
+ processors, the code generator takes care of that
+ * the addr size is for work with the natural pointer
+ size
+ * the procedures without fpu/mm are only for integer usage
+ * normally the first location is the source and the
+ second the destination
+ }
+
+ {# Emits instruction to call the method specified by symbol name.
+ This routine must be overridden for each new target cpu.
+ }
+ procedure a_call_name(list : TAsmList;const s : string; weak: boolean);virtual; abstract;
+ procedure a_call_reg(list : TAsmList;reg : tregister);virtual; abstract;
+ procedure a_call_ref(list : TAsmList;ref : treference);virtual;
+ { same as a_call_name, might be overridden on certain architectures to emit
+ static calls without usage of a got trampoline }
+ procedure a_call_name_static(list : TAsmList;const s : string);virtual;
+
+ { move instructions }
+ procedure a_load_const_reg(list : TAsmList;size : tcgsize;a : tcgint;register : tregister);virtual; abstract;
+ procedure a_load_const_ref(list : TAsmList;size : tcgsize;a : tcgint;const ref : treference);virtual;
+ procedure a_load_const_loc(list : TAsmList;a : tcgint;const loc : tlocation);
+ procedure a_load_reg_ref(list : TAsmList;fromsize,tosize : tcgsize;register : tregister;const ref : treference);virtual; abstract;
+ procedure a_load_reg_ref_unaligned(list : TAsmList;fromsize,tosize : tcgsize;register : tregister;const ref : treference);virtual;
+ procedure a_load_reg_reg(list : TAsmList;fromsize,tosize : tcgsize;reg1,reg2 : tregister);virtual; abstract;
+ procedure a_load_reg_loc(list : TAsmList;fromsize : tcgsize;reg : tregister;const loc: tlocation);
+ procedure a_load_ref_reg(list : TAsmList;fromsize,tosize : tcgsize;const ref : treference;register : tregister);virtual; abstract;
+ procedure a_load_ref_reg_unaligned(list : TAsmList;fromsize,tosize : tcgsize;const ref : treference;register : tregister);virtual;
+ procedure a_load_ref_ref(list : TAsmList;fromsize,tosize : tcgsize;const sref : treference;const dref : treference);virtual;
+ procedure a_load_loc_reg(list : TAsmList;tosize: tcgsize; const loc: tlocation; reg : tregister);
+ procedure a_load_loc_ref(list : TAsmList;tosize: tcgsize; const loc: tlocation; const ref : treference);
+ procedure a_load_loc_subsetreg(list : TAsmList;subsetsize: tcgsize; const loc: tlocation; const sreg : tsubsetregister);
+ procedure a_load_loc_subsetref(list : TAsmList;subsetsize: tcgsize; const loc: tlocation; const sref : tsubsetreference);
+ procedure a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);virtual; abstract;
+
+ procedure a_load_subsetreg_reg(list : TAsmList; subsetsize, tosize: tcgsize; const sreg: tsubsetregister; destreg: tregister); virtual;
+ procedure a_load_reg_subsetreg(list : TAsmList; fromsize, subsetsize: tcgsize; fromreg: tregister; const sreg: tsubsetregister); virtual;
+ procedure a_load_subsetreg_subsetreg(list: TAsmlist; fromsubsetsize, tosubsetsize : tcgsize; const fromsreg, tosreg: tsubsetregister); virtual;
+ procedure a_load_subsetreg_ref(list : TAsmList; subsetsize, tosize: tcgsize; const sreg: tsubsetregister; const destref: treference); virtual;
+ procedure a_load_ref_subsetreg(list : TAsmList; fromsize, subsetsize: tcgsize; const fromref: treference; const sreg: tsubsetregister); virtual;
+ procedure a_load_const_subsetreg(list: TAsmlist; subsetsize: tcgsize; a: tcgint; const sreg: tsubsetregister); virtual;
+ procedure a_load_subsetreg_loc(list: TAsmlist; subsetsize: tcgsize; const sreg: tsubsetregister; const loc: tlocation); virtual;
+
+ procedure a_load_subsetref_reg(list : TAsmList; subsetsize, tosize: tcgsize; const sref: tsubsetreference; destreg: tregister); virtual;
+ procedure a_load_reg_subsetref(list : TAsmList; fromsize, subsetsize: tcgsize; fromreg: tregister; const sref: tsubsetreference);
+ procedure a_load_subsetref_subsetref(list: TAsmlist; fromsubsetsize, tosubsetsize : tcgsize; const fromsref, tosref: tsubsetreference); virtual;
+ procedure a_load_subsetref_ref(list : TAsmList; subsetsize, tosize: tcgsize; const sref: tsubsetreference; const destref: treference); virtual;
+ procedure a_load_ref_subsetref(list : TAsmList; fromsize, subsetsize: tcgsize; const fromref: treference; const sref: tsubsetreference); virtual;
+ procedure a_load_const_subsetref(list: TAsmlist; subsetsize: tcgsize; a: tcgint; const sref: tsubsetreference); virtual;
+ procedure a_load_subsetref_loc(list: TAsmlist; subsetsize: tcgsize; const sref: tsubsetreference; const loc: tlocation); virtual;
+ procedure a_load_subsetref_subsetreg(list: TAsmlist; fromsubsetsize, tosubsetsize : tcgsize; const fromsref: tsubsetreference; const tosreg: tsubsetregister); virtual;
+ procedure a_load_subsetreg_subsetref(list: TAsmlist; fromsubsetsize, tosubsetsize : tcgsize; const fromsreg: tsubsetregister; const tosref: tsubsetreference); virtual;
+
+ { bit test instructions }
+ procedure a_bit_test_reg_reg_reg(list : TAsmList; bitnumbersize,valuesize,destsize: tcgsize;bitnumber,value,destreg: tregister); virtual;
+ procedure a_bit_test_const_ref_reg(list: TAsmList; destsize: tcgsize; bitnumber: tcgint; const ref: treference; destreg: tregister); virtual;
+ procedure a_bit_test_const_reg_reg(list: TAsmList; setregsize, destsize: tcgsize; bitnumber: tcgint; setreg, destreg: tregister); virtual;
+ procedure a_bit_test_const_subsetreg_reg(list: TAsmList; setregsize, destsize: tcgsize; bitnumber: tcgint; const setreg: tsubsetregister; destreg: tregister); virtual;
+ procedure a_bit_test_reg_ref_reg(list: TAsmList; bitnumbersize, destsize: tcgsize; bitnumber: tregister; const ref: treference; destreg: tregister); virtual;
+ procedure a_bit_test_reg_loc_reg(list: TAsmList; bitnumbersize, destsize: tcgsize; bitnumber: tregister; const loc: tlocation; destreg: tregister);
+ procedure a_bit_test_const_loc_reg(list: TAsmList; destsize: tcgsize; bitnumber: tcgint; const loc: tlocation; destreg: tregister);
+
+ { bit set/clear instructions }
+ procedure a_bit_set_reg_reg(list : TAsmList; doset: boolean; bitnumbersize, destsize: tcgsize; bitnumber,dest: tregister); virtual;
+ procedure a_bit_set_const_ref(list: TAsmList; doset: boolean;destsize: tcgsize; bitnumber: tcgint; const ref: treference); virtual;
+ procedure a_bit_set_const_reg(list: TAsmList; doset: boolean; destsize: tcgsize; bitnumber: tcgint; destreg: tregister); virtual;
+ procedure a_bit_set_const_subsetreg(list: TAsmList; doset: boolean; destsize: tcgsize; bitnumber: tcgint; const destreg: tsubsetregister); virtual;
+ procedure a_bit_set_reg_ref(list: TAsmList; doset: boolean; bitnumbersize: tcgsize; bitnumber: tregister; const ref: treference); virtual;
+ procedure a_bit_set_reg_loc(list: TAsmList; doset: boolean; bitnumbersize: tcgsize; bitnumber: tregister; const loc: tlocation);
+ procedure a_bit_set_const_loc(list: TAsmList; doset: boolean; bitnumber: tcgint; const loc: tlocation);
+
+ { bit scan instructions }
+ procedure a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; size: tcgsize; src, dst: TRegister); virtual; abstract;
+
+ { fpu move instructions }
+ procedure a_loadfpu_reg_reg(list: TAsmList; fromsize, tosize:tcgsize; reg1, reg2: tregister); virtual; abstract;
+ procedure a_loadfpu_ref_reg(list: TAsmList; fromsize, tosize: tcgsize; const ref: treference; reg: tregister); virtual; abstract;
+ procedure a_loadfpu_reg_ref(list: TAsmList; fromsize, tosize: tcgsize; reg: tregister; const ref: treference); virtual; abstract;
+ procedure a_loadfpu_ref_ref(list: TAsmList; fromsize, tosize: tcgsize; const ref1,ref2: treference);
+ procedure a_loadfpu_loc_reg(list: TAsmList; tosize: tcgsize; const loc: tlocation; const reg: tregister);
+ procedure a_loadfpu_reg_loc(list: TAsmList; fromsize: tcgsize; const reg: tregister; const loc: tlocation);
+ procedure a_loadfpu_reg_cgpara(list : TAsmList;size : tcgsize;const r : tregister;const cgpara : TCGPara);virtual;
+ procedure a_loadfpu_ref_cgpara(list : TAsmList;size : tcgsize;const ref : treference;const cgpara : TCGPara);virtual;
+
+ { vector register move instructions }
+ procedure a_loadmm_reg_reg(list: TAsmList; fromsize, tosize : tcgsize;reg1, reg2: tregister;shuffle : pmmshuffle); virtual;
+ procedure a_loadmm_ref_reg(list: TAsmList; fromsize, tosize : tcgsize;const ref: treference; reg: tregister;shuffle : pmmshuffle); virtual;
+ procedure a_loadmm_reg_ref(list: TAsmList; fromsize, tosize : tcgsize;reg: tregister; const ref: treference;shuffle : pmmshuffle); virtual;
+ procedure a_loadmm_loc_reg(list: TAsmList; size: tcgsize; const loc: tlocation; const reg: tregister;shuffle : pmmshuffle);
+ procedure a_loadmm_reg_loc(list: TAsmList; size: tcgsize; const reg: tregister; const loc: tlocation;shuffle : pmmshuffle);
+ procedure a_loadmm_reg_cgpara(list: TAsmList; size: tcgsize; reg: tregister;const cgpara : TCGPara;shuffle : pmmshuffle); virtual;
+ procedure a_loadmm_ref_cgpara(list: TAsmList; size: tcgsize; const ref: treference;const cgpara : TCGPara;shuffle : pmmshuffle); virtual;
+ procedure a_loadmm_loc_cgpara(list: TAsmList; const loc: tlocation; const cgpara : TCGPara;shuffle : pmmshuffle); virtual;
+ procedure a_opmm_reg_reg(list: TAsmList; Op: TOpCG; size : tcgsize;src,dst: tregister;shuffle : pmmshuffle); virtual;
+ procedure a_opmm_ref_reg(list: TAsmList; Op: TOpCG; size : tcgsize;const ref: treference; reg: tregister;shuffle : pmmshuffle); virtual;
+ procedure a_opmm_loc_reg(list: TAsmList; Op: TOpCG; size : tcgsize;const loc: tlocation; reg: tregister;shuffle : pmmshuffle); virtual;
+ procedure a_opmm_reg_ref(list: TAsmList; Op: TOpCG; size : tcgsize;reg: tregister;const ref: treference; shuffle : pmmshuffle); virtual;
+
+ procedure a_loadmm_intreg_reg(list: TAsmList; fromsize, tosize : tcgsize; intreg, mmreg: tregister; shuffle: pmmshuffle); virtual;
+ procedure a_loadmm_reg_intreg(list: TAsmList; fromsize, tosize : tcgsize; mmreg, intreg: tregister; shuffle : pmmshuffle); virtual;
+
+ { basic arithmetic operations }
+ { note: for operators which require only one argument (not, neg), use }
+ { the op_reg_reg, op_reg_ref or op_reg_loc methods and keep in mind }
+ { that in this case the *second* operand is used as both source and }
+ { destination (JM) }
+ procedure a_op_const_reg(list : TAsmList; Op: TOpCG; size: TCGSize; a: tcgint; reg: TRegister); virtual; abstract;
+ procedure a_op_const_ref(list : TAsmList; Op: TOpCG; size: TCGSize; a: tcgint; const ref: TReference); virtual;
+ procedure a_op_const_subsetreg(list : TAsmList; Op : TOpCG; size, subsetsize : TCGSize; a : tcgint; const sreg: tsubsetregister); virtual;
+ procedure a_op_const_subsetref(list : TAsmList; Op : TOpCG; size, subsetsize : TCGSize; a : tcgint; const sref: tsubsetreference); virtual;
+ procedure a_op_const_loc(list : TAsmList; Op: TOpCG; a: tcgint; const loc: tlocation);
+ procedure a_op_reg_reg(list : TAsmList; Op: TOpCG; size: TCGSize; reg1, reg2: TRegister); virtual; abstract;
+ procedure a_op_reg_ref(list : TAsmList; Op: TOpCG; size: TCGSize; reg: TRegister; const ref: TReference); virtual;
+ procedure a_op_ref_reg(list : TAsmList; Op: TOpCG; size: TCGSize; const ref: TReference; reg: TRegister); virtual;
+ procedure a_op_reg_subsetreg(list : TAsmList; Op : TOpCG; opsize, subsetsize : TCGSize; reg: TRegister; const sreg: tsubsetregister); virtual;
+ procedure a_op_reg_subsetref(list : TAsmList; Op : TOpCG; opsize, subsetsize : TCGSize; reg: TRegister; const sref: tsubsetreference); virtual;
+ procedure a_op_reg_loc(list : TAsmList; Op: TOpCG; reg: tregister; const loc: tlocation);
+ procedure a_op_ref_loc(list : TAsmList; Op: TOpCG; const ref: TReference; const loc: tlocation);
+
+ { trinary operations for processors that support them, 'emulated' }
+ { on others. None with "ref" arguments since I don't think there }
+ { are any processors that support it (JM) }
+ procedure a_op_const_reg_reg(list: TAsmList; op: TOpCg; size: tcgsize; a: tcgint; src, dst: tregister); virtual;
+ procedure a_op_reg_reg_reg(list: TAsmList; op: TOpCg; size: tcgsize; src1, src2, dst: tregister); virtual;
+ procedure a_op_const_reg_reg_checkoverflow(list: TAsmList; op: TOpCg; size: tcgsize; a: tcgint; src, dst: tregister;setflags : boolean;var ovloc : tlocation); virtual;
+ procedure a_op_reg_reg_reg_checkoverflow(list: TAsmList; op: TOpCg; size: tcgsize; src1, src2, dst: tregister;setflags : boolean;var ovloc : tlocation); virtual;
+
+ { comparison operations }
+ procedure a_cmp_const_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;a : tcgint;reg : tregister;
+ l : tasmlabel); virtual;
+ procedure a_cmp_const_ref_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;a : tcgint;const ref : treference;
+ l : tasmlabel); virtual;
+ procedure a_cmp_const_loc_label(list: TAsmList; size: tcgsize;cmp_op: topcmp; a: tcgint; const loc: tlocation;
+ l : tasmlabel);
+ procedure a_cmp_reg_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel); virtual; abstract;
+ procedure a_cmp_ref_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp; const ref: treference; reg : tregister; l : tasmlabel); virtual;
+ procedure a_cmp_reg_ref_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;reg : tregister; const ref: treference; l : tasmlabel); virtual;
+ procedure a_cmp_subsetreg_reg_label(list : TAsmList; subsetsize, cmpsize : tcgsize; cmp_op : topcmp; const sreg: tsubsetregister; reg : tregister; l : tasmlabel); virtual;
+ procedure a_cmp_subsetref_reg_label(list : TAsmList; subsetsize, cmpsize : tcgsize; cmp_op : topcmp; const sref: tsubsetreference; reg : tregister; l : tasmlabel); virtual;
+
+ procedure a_cmp_loc_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp; const loc: tlocation; reg : tregister; l : tasmlabel);
+ procedure a_cmp_reg_loc_label(list : TAsmList;size : tcgsize;cmp_op : topcmp; reg: tregister; const loc: tlocation; l : tasmlabel);
+ procedure a_cmp_ref_loc_label(list: TAsmList; size: tcgsize;cmp_op: topcmp; const ref: treference; const loc: tlocation;
+ l : tasmlabel);
+
+ procedure a_jmp_name(list : TAsmList;const s : string); virtual; abstract;
+ procedure a_jmp_always(list : TAsmList;l: tasmlabel); virtual; abstract;
+{$ifdef cpuflags}
+ procedure a_jmp_flags(list : TAsmList;const f : TResFlags;l: tasmlabel); virtual; abstract;
+
+ {# Depending on the value to check in the flags, either sets the register reg to one (if the flag is set)
+ or zero (if the flag is cleared). The size parameter indicates the destination size register.
+ }
+ procedure g_flags2reg(list: TAsmList; size: TCgSize; const f: tresflags; reg: TRegister); virtual; abstract;
+ procedure g_flags2ref(list: TAsmList; size: TCgSize; const f: tresflags; const ref:TReference); virtual;
+{$endif cpuflags}
+
+ {
+ This routine tries to optimize the op_const_reg/ref opcode, and should be
+ called at the start of a_op_const_reg/ref. It returns the actual opcode
+ to emit, and the constant value to emit. This function can opcode OP_NONE to
+ remove the opcode and OP_MOVE to replace it with a simple load
+
+ @param(op The opcode to emit, returns the opcode which must be emitted)
+ @param(a The constant which should be emitted, returns the constant which must
+ be emitted)
+ }
+ procedure optimize_op_const(var op: topcg; var a : tcgint);virtual;
+
+ {#
+ This routine is used in exception management nodes. It should
+ save the exception reason currently in the FUNCTION_RETURN_REG. The
+ save should be done either to a temp (pointed to by href).
+ or on the stack (pushing the value on the stack).
+
+ The size of the value to save is OS_S32. The default version
+ saves the exception reason to a temp. memory area.
+ }
+ procedure g_exception_reason_save(list : TAsmList; const href : treference);virtual;
+ {#
+ This routine is used in exception management nodes. It should
+ save the exception reason constant. The
+ save should be done either to a temp (pointed to by href).
+ or on the stack (pushing the value on the stack).
+
+ The size of the value to save is OS_S32. The default version
+ saves the exception reason to a temp. memory area.
+ }
+ procedure g_exception_reason_save_const(list : TAsmList; const href : treference; a: tcgint);virtual;
+ {#
+ This routine is used in exception management nodes. It should
+ load the exception reason to the FUNCTION_RETURN_REG. The saved value
+ should either be in the temp. area (pointed to by href , href should
+ *NOT* be freed) or on the stack (the value should be popped).
+
+ The size of the value to save is OS_S32. The default version
+ saves the exception reason to a temp. memory area.
+ }
+ procedure g_exception_reason_load(list : TAsmList; const href : treference);virtual;
+
+ procedure g_maybe_testself(list : TAsmList;reg:tregister);
+ procedure g_maybe_testvmt(list : TAsmList;reg:tregister;objdef:tobjectdef);
+ {# This should emit the opcode to copy len bytes from the source
+ to destination.
+
+ It must be overridden for each new target processor.
+
+ @param(source Source reference of copy)
+ @param(dest Destination reference of copy)
+
+ }
+ procedure g_concatcopy(list : TAsmList;const source,dest : treference;len : tcgint);virtual; abstract;
+ {# This should emit the opcode to copy len bytes from the an unaligned source
+ to destination.
+
+ It must be overridden for each new target processor.
+
+ @param(source Source reference of copy)
+ @param(dest Destination reference of copy)
+
+ }
+ procedure g_concatcopy_unaligned(list : TAsmList;const source,dest : treference;len : tcgint);virtual;
+ {# This should emit the opcode to a shortrstring from the source
+ to destination.
+
+ @param(source Source reference of copy)
+ @param(dest Destination reference of copy)
+
+ }
+ procedure g_copyshortstring(list : TAsmList;const source,dest : treference;len:byte);
+ procedure g_copyvariant(list : TAsmList;const source,dest : treference);
+
+ procedure g_incrrefcount(list : TAsmList;t: tdef; const ref: treference);
+ procedure g_array_rtti_helper(list: TAsmList; t: tdef; const ref: treference; const highloc: tlocation;
+ const name: string);
+ procedure g_initialize(list : TAsmList;t : tdef;const ref : treference);
+ procedure g_finalize(list : TAsmList;t : tdef;const ref : treference);
+
+ {# Generates range checking code. It is to note
+ that this routine does not need to be overridden,
+ as it takes care of everything.
+
+ @param(p Node which contains the value to check)
+ @param(todef Type definition of node to range check)
+ }
+ procedure g_rangecheck(list: TAsmList; const l:tlocation; fromdef,todef: tdef); virtual;
+
+ {# Generates overflow checking code for a node }
+ procedure g_overflowcheck(list: TAsmList; const Loc:tlocation; def:tdef); virtual;abstract;
+ procedure g_overflowCheck_loc(List:TAsmList;const Loc:TLocation;def:TDef;ovloc : tlocation);virtual;
+
+ procedure g_copyvaluepara_openarray(list : TAsmList;const ref:treference;const lenloc:tlocation;elesize:tcgint;destreg:tregister);virtual;
+ procedure g_releasevaluepara_openarray(list : TAsmList;const l:tlocation);virtual;
+
+ {# Emits instructions when compilation is done in profile
+ mode (this is set as a command line option). The default
+ behavior does nothing, should be overridden as required.
+ }
+ procedure g_profilecode(list : TAsmList);virtual;
+ {# Emits instruction for allocating @var(size) bytes at the stackpointer
+
+ @param(size Number of bytes to allocate)
+ }
+ procedure g_stackpointer_alloc(list : TAsmList;size : longint);virtual; abstract;
+ {# Emits instruction for allocating the locals in entry
+ code of a routine. This is one of the first
+ routine called in @var(genentrycode).
+
+ @param(localsize Number of bytes to allocate as locals)
+ }
+ procedure g_proc_entry(list : TAsmList;localsize : longint;nostackframe:boolean);virtual; abstract;
+ {# Emits instructions for returning from a subroutine.
+ Should also restore the framepointer and stack.
+
+ @param(parasize Number of bytes of parameters to deallocate from stack)
+ }
+ procedure g_proc_exit(list : TAsmList;parasize:longint;nostackframe:boolean);virtual;abstract;
+ {# This routine is called when generating the code for the entry point
+ of a routine. It should save all registers which are not used in this
+ routine, and which should be declared as saved in the std_saved_registers
+ set.
+
+ This routine is mainly used when linking to code which is generated
+ by ABI-compliant compilers (like GCC), to make sure that the reserved
+ registers of that ABI are not clobbered.
+
+ @param(usedinproc Registers which are used in the code of this routine)
+ }
+ procedure g_save_registers(list:TAsmList);virtual;
+ {# This routine is called when generating the code for the exit point
+ of a routine. It should restore all registers which were previously
+ saved in @var(g_save_standard_registers).
+
+ @param(usedinproc Registers which are used in the code of this routine)
+ }
+ procedure g_restore_registers(list:TAsmList);virtual;
+
+ procedure g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);virtual;abstract;
+ procedure g_adjust_self_value(list:TAsmList;procdef: tprocdef;ioffset: tcgint);virtual;
+
+ function g_indirect_sym_load(list:TAsmList;const symname: string; weak: boolean): tregister;virtual;
+ { generate a stub which only purpose is to pass control the given external method,
+ setting up any additional environment before doing so (if required).
+
+ The default implementation issues a jump instruction to the external name. }
+ procedure g_external_wrapper(list : TAsmList; procdef: tprocdef; const externalname: string); virtual;
+
+ { initialize the pic/got register }
+ procedure g_maybe_got_init(list: TAsmList); virtual;
+ { allocallcpuregisters, a_call_name, deallocallcpuregisters sequence }
+ procedure g_call(list: TAsmList; const s: string);
+ { Generate code to exit an unwind-protected region. The default implementation
+ produces a simple jump to destination label. }
+ procedure g_local_unwind(list: TAsmList; l: TAsmLabel);virtual;
+ protected
+ procedure get_subsetref_load_info(const sref: tsubsetreference; out loadsize: tcgsize; out extra_load: boolean);
+ procedure a_load_subsetref_regs_noindex(list: TAsmList; subsetsize: tcgsize; loadbitsize: byte; const sref: tsubsetreference; valuereg, extra_value_reg: tregister); virtual;
+ procedure a_load_subsetref_regs_index(list: TAsmList; subsetsize: tcgsize; loadbitsize: byte; const sref: tsubsetreference; valuereg: tregister); virtual;
+
+ procedure a_load_regconst_subsetref_intern(list : TAsmList; fromsize, subsetsize: tcgsize; fromreg: tregister; const sref: tsubsetreference; slopt: tsubsetloadopt); virtual;
+ procedure a_load_regconst_subsetreg_intern(list : TAsmList; fromsize, subsetsize: tcgsize; fromreg: tregister; const sreg: tsubsetregister; slopt: tsubsetloadopt); virtual;
+
+ function get_bit_const_ref_sref(bitnumber: tcgint; const ref: treference): tsubsetreference;
+ function get_bit_const_reg_sreg(setregsize: tcgsize; bitnumber: tcgint; setreg: tregister): tsubsetregister;
+ function get_bit_reg_ref_sref(list: TAsmList; bitnumbersize: tcgsize; bitnumber: tregister; const ref: treference): tsubsetreference;
+ end;
+
+{$ifndef cpu64bitalu}
+ {# @abstract(Abstract code generator for 64 Bit operations)
+ This class implements an abstract code generator class
+ for 64 Bit operations.
+ }
+ tcg64 = class
+ procedure a_load64_const_ref(list : TAsmList;value : int64;const ref : treference);virtual;abstract;
+ procedure a_load64_reg_ref(list : TAsmList;reg : tregister64;const ref : treference);virtual;abstract;
+ procedure a_load64_ref_reg(list : TAsmList;const ref : treference;reg : tregister64);virtual;abstract;
+ procedure a_load64_reg_reg(list : TAsmList;regsrc,regdst : tregister64);virtual;abstract;
+ procedure a_load64_const_reg(list : TAsmList;value : int64;reg : tregister64);virtual;abstract;
+ procedure a_load64_loc_reg(list : TAsmList;const l : tlocation;reg : tregister64);virtual;abstract;
+ procedure a_load64_loc_ref(list : TAsmList;const l : tlocation;const ref : treference);virtual;abstract;
+ procedure a_load64_const_loc(list : TAsmList;value : int64;const l : tlocation);virtual;abstract;
+ procedure a_load64_reg_loc(list : TAsmList;reg : tregister64;const l : tlocation);virtual;abstract;
+
+
+ procedure a_load64_subsetref_reg(list : TAsmList; const sref: tsubsetreference; destreg: tregister64);virtual;abstract;
+ procedure a_load64_reg_subsetref(list : TAsmList; fromreg: tregister64; const sref: tsubsetreference);virtual;abstract;
+ procedure a_load64_const_subsetref(list: TAsmlist; a: int64; const sref: tsubsetreference);virtual;abstract;
+ procedure a_load64_ref_subsetref(list : TAsmList; const fromref: treference; const sref: tsubsetreference);virtual;abstract;
+ procedure a_load64_subsetref_subsetref(list: TAsmlist; const fromsref, tosref: tsubsetreference); virtual;abstract;
+ procedure a_load64_subsetref_ref(list : TAsmList; const sref: tsubsetreference; const destref: treference); virtual;abstract;
+ procedure a_load64_loc_subsetref(list : TAsmList; const l: tlocation; const sref : tsubsetreference);
+ procedure a_load64_subsetref_loc(list: TAsmlist; const sref: tsubsetreference; const l: tlocation);
+
+ procedure a_load64high_reg_ref(list : TAsmList;reg : tregister;const ref : treference);virtual;abstract;
+ procedure a_load64low_reg_ref(list : TAsmList;reg : tregister;const ref : treference);virtual;abstract;
+ procedure a_load64high_ref_reg(list : TAsmList;const ref : treference;reg : tregister);virtual;abstract;
+ procedure a_load64low_ref_reg(list : TAsmList;const ref : treference;reg : tregister);virtual;abstract;
+ procedure a_load64high_loc_reg(list : TAsmList;const l : tlocation;reg : tregister);virtual;abstract;
+ procedure a_load64low_loc_reg(list : TAsmList;const l : tlocation;reg : tregister);virtual;abstract;
+
+ procedure a_op64_ref_reg(list : TAsmList;op:TOpCG;size : tcgsize;const ref : treference;reg : tregister64);virtual;abstract;
+ procedure a_op64_reg_reg(list : TAsmList;op:TOpCG;size : tcgsize;regsrc,regdst : tregister64);virtual;abstract;
+ procedure a_op64_reg_ref(list : TAsmList;op:TOpCG;size : tcgsize;regsrc : tregister64;const ref : treference);virtual;abstract;
+ procedure a_op64_const_reg(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;regdst : tregister64);virtual;abstract;
+ procedure a_op64_const_ref(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;const ref : treference);virtual;abstract;
+ procedure a_op64_const_loc(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;const l: tlocation);virtual;abstract;
+ procedure a_op64_reg_loc(list : TAsmList;op:TOpCG;size : tcgsize;reg : tregister64;const l : tlocation);virtual;abstract;
+ procedure a_op64_loc_reg(list : TAsmList;op:TOpCG;size : tcgsize;const l : tlocation;reg64 : tregister64);virtual;abstract;
+ procedure a_op64_const_reg_reg(list: TAsmList;op:TOpCG;size : tcgsize;value : int64;regsrc,regdst : tregister64);virtual;
+ procedure a_op64_reg_reg_reg(list: TAsmList;op:TOpCG;size : tcgsize;regsrc1,regsrc2,regdst : tregister64);virtual;
+ procedure a_op64_const_reg_reg_checkoverflow(list: TAsmList;op:TOpCG;size : tcgsize;value : int64;regsrc,regdst : tregister64;setflags : boolean;var ovloc : tlocation);virtual;
+ procedure a_op64_reg_reg_reg_checkoverflow(list: TAsmList;op:TOpCG;size : tcgsize;regsrc1,regsrc2,regdst : tregister64;setflags : boolean;var ovloc : tlocation);virtual;
+
+ procedure a_op64_const_subsetref(list : TAsmList; Op : TOpCG; size : TCGSize; a : int64; const sref: tsubsetreference);
+ procedure a_op64_reg_subsetref(list : TAsmList; Op : TOpCG; size : TCGSize; reg: tregister64; const sref: tsubsetreference);
+ procedure a_op64_ref_subsetref(list : TAsmList; Op : TOpCG; size : TCGSize; const ref: treference; const sref: tsubsetreference);
+ procedure a_op64_subsetref_subsetref(list : TAsmList; Op : TOpCG; size : TCGSize; const ssref,dsref: tsubsetreference);
+
+ procedure a_load64_reg_cgpara(list : TAsmList;reg64 : tregister64;const loc : TCGPara);virtual;abstract;
+ procedure a_load64_const_cgpara(list : TAsmList;value : int64;const loc : TCGPara);virtual;abstract;
+ procedure a_load64_ref_cgpara(list : TAsmList;const r : treference;const loc : TCGPara);virtual;abstract;
+ procedure a_load64_loc_cgpara(list : TAsmList;const l : tlocation;const loc : TCGPara);virtual;abstract;
+
+ procedure a_loadmm_intreg64_reg(list: TAsmList; mmsize: tcgsize; intreg: tregister64; mmreg: tregister); virtual;abstract;
+ procedure a_loadmm_reg_intreg64(list: TAsmList; mmsize: tcgsize; mmreg: tregister; intreg: tregister64); virtual;abstract;
+ {
+ This routine tries to optimize the const_reg opcode, and should be
+ called at the start of a_op64_const_reg. It returns the actual opcode
+ to emit, and the constant value to emit. If this routine returns
+ TRUE, @var(no) instruction should be emitted (.eg : imul reg by 1 )
+
+ @param(op The opcode to emit, returns the opcode which must be emitted)
+ @param(a The constant which should be emitted, returns the constant which must
+ be emitted)
+ @param(reg The register to emit the opcode with, returns the register with
+ which the opcode will be emitted)
+ }
+ function optimize64_op_const_reg(list: TAsmList; var op: topcg; var a : int64; var reg: tregister64): boolean;virtual;abstract;
+
+
+ { override to catch 64bit rangechecks }
+ procedure g_rangecheck64(list: TAsmList; const l:tlocation; fromdef,todef: tdef);virtual;abstract;
+ end;
+{$endif cpu64bitalu}
+
+ var
+ {# Main code generator class }
+ cg : tcg;
+{$ifndef cpu64bitalu}
+ {# Code generator class for all operations working with 64-Bit operands }
+ cg64 : tcg64;
+{$endif cpu64bitalu}
+
+ procedure destroy_codegen;
+
+implementation
+
+ uses
+ globals,options,systems,
+ verbose,defutil,paramgr,symsym,
+ tgobj,cutils,procinfo,
+ ncgrtti;
+
+
+{*****************************************************************************
+ basic functionallity
+******************************************************************************}
+
+ constructor tcg.create;
+ begin
+ end;
+
+
+{*****************************************************************************
+ register allocation
+******************************************************************************}
+
+
+ procedure tcg.init_register_allocators;
+ begin
+ fillchar(rg,sizeof(rg),0);
+ add_reg_instruction_hook:=@add_reg_instruction;
+ executionweight:=1;
+ end;
+
+
+ procedure tcg.done_register_allocators;
+ begin
+ { Safety }
+ fillchar(rg,sizeof(rg),0);
+ add_reg_instruction_hook:=nil;
+ end;
+
+ {$ifdef flowgraph}
+ procedure Tcg.init_flowgraph;
+
+ begin
+ aktflownode:=0;
+ end;
+
+ procedure Tcg.done_flowgraph;
+
+ begin
+ end;
+ {$endif}
+
+ function tcg.getintregister(list:TAsmList;size:Tcgsize):Tregister;
+ begin
+ if not assigned(rg[R_INTREGISTER]) then
+ internalerror(200312122);
+ result:=rg[R_INTREGISTER].getregister(list,cgsize2subreg(R_INTREGISTER,size));
+ end;
+
+
+ function tcg.getfpuregister(list:TAsmList;size:Tcgsize):Tregister;
+ begin
+ if not assigned(rg[R_FPUREGISTER]) then
+ internalerror(200312123);
+ result:=rg[R_FPUREGISTER].getregister(list,cgsize2subreg(R_FPUREGISTER,size));
+ end;
+
+
+ function tcg.getmmregister(list:TAsmList;size:Tcgsize):Tregister;
+ begin
+ if not assigned(rg[R_MMREGISTER]) then
+ internalerror(2003121214);
+ result:=rg[R_MMREGISTER].getregister(list,cgsize2subreg(R_MMREGISTER,size));
+ end;
+
+
+ function tcg.getaddressregister(list:TAsmList):Tregister;
+ begin
+ if assigned(rg[R_ADDRESSREGISTER]) then
+ result:=rg[R_ADDRESSREGISTER].getregister(list,R_SUBWHOLE)
+ else
+ begin
+ if not assigned(rg[R_INTREGISTER]) then
+ internalerror(200312121);
+ result:=rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
+ end;
+ end;
+
+
+ function Tcg.makeregsize(list:TAsmList;reg:Tregister;size:Tcgsize):Tregister;
+ var
+ subreg:Tsubregister;
+ begin
+ subreg:=cgsize2subreg(getregtype(reg),size);
+ result:=reg;
+ setsubreg(result,subreg);
+ { notify RA }
+ if result<>reg then
+ list.concat(tai_regalloc.resize(result));
+ end;
+
+
+ procedure tcg.getcpuregister(list:TAsmList;r:Tregister);
+ begin
+ if not assigned(rg[getregtype(r)]) then
+ internalerror(200312125);
+ rg[getregtype(r)].getcpuregister(list,r);
+ end;
+
+
+ procedure tcg.ungetcpuregister(list:TAsmList;r:Tregister);
+ begin
+ if not assigned(rg[getregtype(r)]) then
+ internalerror(200312126);
+ rg[getregtype(r)].ungetcpuregister(list,r);
+ end;
+
+
+ procedure tcg.alloccpuregisters(list:TAsmList;rt:Tregistertype;const r:Tcpuregisterset);
+ begin
+ if assigned(rg[rt]) then
+ rg[rt].alloccpuregisters(list,r)
+ else
+ internalerror(200310092);
+ end;
+
+
+ procedure tcg.allocallcpuregisters(list:TAsmList);
+ begin
+ alloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
+{$if not(defined(i386)) and not(defined(avr))}
+ alloccpuregisters(list,R_FPUREGISTER,paramanager.get_volatile_registers_fpu(pocall_default));
+{$ifdef cpumm}
+ alloccpuregisters(list,R_MMREGISTER,paramanager.get_volatile_registers_mm(pocall_default));
+{$endif cpumm}
+{$endif not(defined(i386)) and not(defined(avr))}
+ end;
+
+
+ procedure tcg.dealloccpuregisters(list:TAsmList;rt:Tregistertype;const r:Tcpuregisterset);
+ begin
+ if assigned(rg[rt]) then
+ rg[rt].dealloccpuregisters(list,r)
+ else
+ internalerror(200310093);
+ end;
+
+
+ procedure tcg.deallocallcpuregisters(list:TAsmList);
+ begin
+ dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
+{$if not(defined(i386)) and not(defined(avr))}
+ dealloccpuregisters(list,R_FPUREGISTER,paramanager.get_volatile_registers_fpu(pocall_default));
+{$ifdef cpumm}
+ dealloccpuregisters(list,R_MMREGISTER,paramanager.get_volatile_registers_mm(pocall_default));
+{$endif cpumm}
+{$endif not(defined(i386)) and not(defined(avr))}
+ end;
+
+
+ function tcg.uses_registers(rt:Tregistertype):boolean;
+ begin
+ if assigned(rg[rt]) then
+ result:=rg[rt].uses_registers
+ else
+ result:=false;
+ end;
+
+
+ procedure tcg.add_reg_instruction(instr:Tai;r:tregister);
+ var
+ rt : tregistertype;
+ begin
+ rt:=getregtype(r);
+ { Only add it when a register allocator is configured.
+ No IE can be generated, because the VMT is written
+ without a valid rg[] }
+ if assigned(rg[rt]) then
+ rg[rt].add_reg_instruction(instr,r,cg.executionweight);
+ end;
+
+
+ procedure tcg.add_move_instruction(instr:Taicpu);
+ var
+ rt : tregistertype;
+ begin
+ rt:=getregtype(instr.oper[O_MOV_SOURCE]^.reg);
+ if assigned(rg[rt]) then
+ rg[rt].add_move_instruction(instr)
+ else
+ internalerror(200310095);
+ end;
+
+
+ procedure tcg.set_regalloc_live_range_direction(dir: TRADirection);
+ var
+ rt : tregistertype;
+ begin
+ for rt:=low(rg) to high(rg) do
+ begin
+ if assigned(rg[rt]) then
+ rg[rt].live_range_direction:=dir;
+ end;
+ end;
+
+
+ procedure tcg.do_register_allocation(list:TAsmList;headertai:tai);
+ var
+ rt : tregistertype;
+ begin
+ for rt:=R_FPUREGISTER to R_SPECIALREGISTER do
+ begin
+ if assigned(rg[rt]) then
+ rg[rt].do_register_allocation(list,headertai);
+ end;
+ { running the other register allocator passes could require addition int/addr. registers
+ when spilling so run int/addr register allocation at the end }
+ if assigned(rg[R_INTREGISTER]) then
+ rg[R_INTREGISTER].do_register_allocation(list,headertai);
+ if assigned(rg[R_ADDRESSREGISTER]) then
+ rg[R_ADDRESSREGISTER].do_register_allocation(list,headertai);
+ end;
+
+
+ procedure tcg.translate_register(var reg : tregister);
+ begin
+ rg[getregtype(reg)].translate_register(reg);
+ end;
+
+
+ procedure tcg.a_reg_alloc(list : TAsmList;r : tregister);
+ begin
+ list.concat(tai_regalloc.alloc(r,nil));
+ end;
+
+
+ procedure tcg.a_reg_dealloc(list : TAsmList;r : tregister);
+ begin
+ list.concat(tai_regalloc.dealloc(r,nil));
+ end;
+
+
+ procedure tcg.a_reg_sync(list : TAsmList;r : tregister);
+ var
+ instr : tai;
+ begin
+ instr:=tai_regalloc.sync(r);
+ list.concat(instr);
+ add_reg_instruction(instr,r);
+ end;
+
+
+ procedure tcg.a_label(list : TAsmList;l : tasmlabel);
+ begin
+ list.concat(tai_label.create(l));
+ end;
+
+
+{*****************************************************************************
+ for better code generation these methods should be overridden
+******************************************************************************}
+
+ procedure tcg.a_load_reg_cgpara(list : TAsmList;size : tcgsize;r : tregister;const cgpara : TCGPara);
+ var
+ ref : treference;
+ begin
+ cgpara.check_simple_location;
+ paramanager.alloccgpara(list,cgpara);
+ case cgpara.location^.loc of
+ LOC_REGISTER,LOC_CREGISTER:
+ a_load_reg_reg(list,size,cgpara.location^.size,r,cgpara.location^.register);
+ LOC_REFERENCE,LOC_CREFERENCE:
+ begin
+ reference_reset_base(ref,cgpara.location^.reference.index,cgpara.location^.reference.offset,cgpara.alignment);
+ a_load_reg_ref(list,size,cgpara.location^.size,r,ref);
+ end;
+ LOC_MMREGISTER,LOC_CMMREGISTER:
+ a_loadmm_intreg_reg(list,size,cgpara.location^.size,r,cgpara.location^.register,mms_movescalar);
+ LOC_FPUREGISTER,LOC_CFPUREGISTER:
+ begin
+ tg.GetTemp(list,TCGSize2Size[size],TCGSize2Size[size],tt_normal,ref);
+ a_load_reg_ref(list,size,size,r,ref);
+ a_loadfpu_ref_cgpara(list,cgpara.location^.size,ref,cgpara);
+ tg.Ungettemp(list,ref);
+ end
+ else
+ internalerror(2002071004);
+ end;
+ end;
+
+
+ procedure tcg.a_load_const_cgpara(list : TAsmList;size : tcgsize;a : tcgint;const cgpara : TCGPara);
+ var
+ ref : treference;
+ begin
+ cgpara.check_simple_location;
+ paramanager.alloccgpara(list,cgpara);
+ case cgpara.location^.loc of
+ LOC_REGISTER,LOC_CREGISTER:
+ a_load_const_reg(list,cgpara.location^.size,a,cgpara.location^.register);
+ LOC_REFERENCE,LOC_CREFERENCE:
+ begin
+ reference_reset_base(ref,cgpara.location^.reference.index,cgpara.location^.reference.offset,cgpara.alignment);
+ a_load_const_ref(list,cgpara.location^.size,a,ref);
+ end
+ else
+ internalerror(2010053109);
+ end;
+ end;
+
+
+ procedure tcg.a_load_ref_cgpara(list : TAsmList;size : tcgsize;const r : treference;const cgpara : TCGPara);
+ var
+ tmpref, ref: treference;
+ tmpreg: tregister;
+ location: pcgparalocation;
+ orgsizeleft,
+ sizeleft: tcgint;
+ reghasvalue: boolean;
+ begin
+ location:=cgpara.location;
+ tmpref:=r;
+ sizeleft:=cgpara.intsize;
+ while assigned(location) do
+ begin
+ paramanager.allocparaloc(list,location);
+ case location^.loc of
+ LOC_REGISTER,LOC_CREGISTER:
+ begin
+ { Parameter locations are often allocated in multiples of
+ entire registers. If a parameter only occupies a part of
+ such a register (e.g. a 16 bit int on a 32 bit
+ architecture), the size of this parameter can only be
+ determined by looking at the "size" parameter of this
+ method -> if the size parameter is <= sizeof(aint), then
+ we check that there is only one parameter location and
+ then use this "size" to load the value into the parameter
+ location }
+ if (size<>OS_NO) and
+ (tcgsize2size[size]<=sizeof(aint)) then
+ begin
+ cgpara.check_simple_location;
+ a_load_ref_reg(list,size,location^.size,tmpref,location^.register);
+ end
+ { there's a lot more data left, and the current paraloc's
+ register is entirely filled with part of that data }
+ else if (sizeleft>sizeof(aint)) then
+ begin
+ a_load_ref_reg(list,location^.size,location^.size,tmpref,location^.register);
+ end
+ { we're at the end of the data, and it can be loaded into
+ the current location's register with a single regular
+ load }
+ else if (sizeleft in [1,2{$ifndef cpu16bitalu},4{$endif}{$ifdef cpu64bitalu},8{$endif}]) then
+ begin
+ a_load_ref_reg(list,int_cgsize(sizeleft),location^.size,tmpref,location^.register);
+ end
+ { we're at the end of the data, and we need multiple loads
+ to get it in the register because it's an irregular size }
+ else
+ begin
+ { should be the last part }
+ if assigned(location^.next) then
+ internalerror(2010052907);
+ { load the value piecewise to get it into the register }
+ orgsizeleft:=sizeleft;
+ reghasvalue:=false;
+{$ifdef cpu64bitalu}
+ if sizeleft>=4 then
+ begin
+ a_load_ref_reg(list,OS_32,location^.size,tmpref,location^.register);
+ dec(sizeleft,4);
+ if target_info.endian=endian_big then
+ a_op_const_reg(list,OP_SHL,location^.size,sizeleft*8,location^.register);
+ inc(tmpref.offset,4);
+ reghasvalue:=true;
+ end;
+{$endif cpu64bitalu}
+ if sizeleft>=2 then
+ begin
+ tmpreg:=getintregister(list,location^.size);
+ a_load_ref_reg(list,OS_16,location^.size,tmpref,tmpreg);
+ dec(sizeleft,2);
+ if reghasvalue then
+ begin
+ if target_info.endian=endian_big then
+ a_op_const_reg(list,OP_SHL,location^.size,sizeleft*8,tmpreg)
+ else
+ a_op_const_reg(list,OP_SHL,location^.size,(orgsizeleft-(sizeleft+2))*8,tmpreg);
+ a_op_reg_reg(list,OP_OR,location^.size,tmpreg,location^.register);
+ end
+ else
+ begin
+ if target_info.endian=endian_big then
+ a_op_const_reg_reg(list,OP_SHL,location^.size,sizeleft*8,tmpreg,location^.register)
+ else
+ a_load_reg_reg(list,location^.size,location^.size,tmpreg,location^.register);
+ end;
+ inc(tmpref.offset,2);
+ reghasvalue:=true;
+ end;
+ if sizeleft=1 then
+ begin
+ tmpreg:=getintregister(list,location^.size);
+ a_load_ref_reg(list,OS_8,location^.size,tmpref,tmpreg);
+ dec(sizeleft,1);
+ if reghasvalue then
+ begin
+ if target_info.endian=endian_little then
+ a_op_const_reg(list,OP_SHL,location^.size,(orgsizeleft-(sizeleft+1))*8,tmpreg);
+ a_op_reg_reg(list,OP_OR,location^.size,tmpreg,location^.register)
+ end
+ else
+ a_load_reg_reg(list,location^.size,location^.size,tmpreg,location^.register);
+ inc(tmpref.offset);
+ end;
+ { the loop will already adjust the offset and sizeleft }
+ dec(tmpref.offset,orgsizeleft);
+ sizeleft:=orgsizeleft;
+ end;
+ end;
+ LOC_REFERENCE,LOC_CREFERENCE:
+ begin
+ if assigned(location^.next) then
+ internalerror(2010052906);
+ reference_reset_base(ref,location^.reference.index,location^.reference.offset,newalignment(cgpara.alignment,cgpara.intsize-sizeleft));
+ if (size <> OS_NO) and
+ (tcgsize2size[size] <= sizeof(aint)) then
+ a_load_ref_ref(list,size,location^.size,tmpref,ref)
+ else
+ { use concatcopy, because the parameter can be larger than }
+ { what the OS_* constants can handle }
+ g_concatcopy(list,tmpref,ref,sizeleft);
+ end;
+ LOC_MMREGISTER,LOC_CMMREGISTER:
+ begin
+ case location^.size of
+ OS_F32,
+ OS_F64,
+ OS_F128:
+ a_loadmm_ref_reg(list,location^.size,location^.size,tmpref,location^.register,mms_movescalar);
+ OS_M8..OS_M128,
+ OS_MS8..OS_MS128:
+ a_loadmm_ref_reg(list,location^.size,location^.size,tmpref,location^.register,nil);
+ else
+ internalerror(2010053101);
+ end;
+ end
+ else
+ internalerror(2010053111);
+ end;
+ inc(tmpref.offset,tcgsize2size[location^.size]);
+ dec(sizeleft,tcgsize2size[location^.size]);
+ location:=location^.next;
+ end;
+ end;
+
+
+ procedure tcg.a_load_loc_cgpara(list : TAsmList;const l:tlocation;const cgpara : TCGPara);
+ begin
+ case l.loc of
+ LOC_REGISTER,
+ LOC_CREGISTER :
+ a_load_reg_cgpara(list,l.size,l.register,cgpara);
+ LOC_CONSTANT :
+ a_load_const_cgpara(list,l.size,l.value,cgpara);
+ LOC_CREFERENCE,
+ LOC_REFERENCE :
+ a_load_ref_cgpara(list,l.size,l.reference,cgpara);
+ else
+ internalerror(2002032211);
+ end;
+ end;
+
+
+ procedure tcg.a_loadaddr_ref_cgpara(list : TAsmList;const r : treference;const cgpara : TCGPara);
+ var
+ hr : tregister;
+ begin
+ cgpara.check_simple_location;
+ if cgpara.location^.loc in [LOC_CREGISTER,LOC_REGISTER] then
+ begin
+ paramanager.allocparaloc(list,cgpara.location);
+ a_loadaddr_ref_reg(list,r,cgpara.location^.register)
+ end
+ else
+ begin
+ hr:=getaddressregister(list);
+ a_loadaddr_ref_reg(list,r,hr);
+ a_load_reg_cgpara(list,OS_ADDR,hr,cgpara);
+ end;
+ end;
+
+
+ procedure tcg.a_load_cgparaloc_ref(list : TAsmList;const paraloc : TCGParaLocation;const ref : treference;sizeleft : tcgint;align : longint);
+ var
+ href : treference;
+ begin
+ case paraloc.loc of
+ LOC_REGISTER :
+ begin
+{$IFDEF POWERPC64}
+ if (paraloc.shiftval <> 0) then
+ a_op_const_reg_reg(list, OP_SHL, OS_INT, paraloc.shiftval, paraloc.register, paraloc.register);
+{$ENDIF POWERPC64}
+ a_load_reg_ref(list,paraloc.size,paraloc.size,paraloc.register,ref);
+ end;
+ LOC_MMREGISTER :
+ begin
+ case paraloc.size of
+ OS_F32,
+ OS_F64,
+ OS_F128:
+ a_loadmm_reg_ref(list,paraloc.size,paraloc.size,paraloc.register,ref,mms_movescalar);
+ OS_M8..OS_M128,
+ OS_MS8..OS_MS128:
+ a_loadmm_reg_ref(list,paraloc.size,paraloc.size,paraloc.register,ref,nil);
+ else
+ internalerror(2010053102);
+ end;
+ end;
+ LOC_FPUREGISTER :
+ cg.a_loadfpu_reg_ref(list,paraloc.size,paraloc.size,paraloc.register,ref);
+ LOC_REFERENCE :
+ begin
+ reference_reset_base(href,paraloc.reference.index,paraloc.reference.offset,align);
+ { use concatcopy, because it can also be a float which fails when
+ load_ref_ref is used. Don't copy data when the references are equal }
+ if not((href.base=ref.base) and (href.offset=ref.offset)) then
+ g_concatcopy(list,href,ref,sizeleft);
+ end;
+ else
+ internalerror(2002081302);
+ end;
+ end;
+
+
+ procedure tcg.a_load_cgparaloc_anyreg(list: TAsmList;regsize: tcgsize;const paraloc: TCGParaLocation;reg: tregister;align: longint);
+ var
+ href : treference;
+ begin
+ case paraloc.loc of
+ LOC_REGISTER :
+ begin
+ case getregtype(reg) of
+ R_INTREGISTER:
+ a_load_reg_reg(list,paraloc.size,regsize,paraloc.register,reg);
+ R_MMREGISTER:
+ a_loadmm_intreg_reg(list,paraloc.size,regsize,paraloc.register,reg,mms_movescalar);
+ else
+ internalerror(2009112422);
+ end;
+ end;
+ LOC_MMREGISTER :
+ begin
+ case getregtype(reg) of
+ R_INTREGISTER:
+ a_loadmm_reg_intreg(list,paraloc.size,regsize,paraloc.register,reg,mms_movescalar);
+ R_MMREGISTER:
+ begin
+ case paraloc.size of
+ OS_F32,
+ OS_F64,
+ OS_F128:
+ a_loadmm_reg_reg(list,paraloc.size,regsize,paraloc.register,reg,mms_movescalar);
+ OS_M8..OS_M128,
+ OS_MS8..OS_MS128:
+ a_loadmm_reg_reg(list,paraloc.size,paraloc.size,paraloc.register,reg,nil);
+ else
+ internalerror(2010053102);
+ end;
+ end;
+ else
+ internalerror(2010053104);
+ end;
+ end;
+ LOC_FPUREGISTER :
+ a_loadfpu_reg_reg(list,paraloc.size,regsize,paraloc.register,reg);
+ LOC_REFERENCE :
+ begin
+ reference_reset_base(href,paraloc.reference.index,paraloc.reference.offset,align);
+ case getregtype(reg) of
+ R_INTREGISTER :
+ a_load_ref_reg(list,paraloc.size,regsize,href,reg);
+ R_FPUREGISTER :
+ a_loadfpu_ref_reg(list,paraloc.size,regsize,href,reg);
+ R_MMREGISTER :
+ { not paraloc.size, because it may be OS_64 instead of
+ OS_F64 in case the parameter is passed using integer
+ conventions (e.g., on ARM) }
+ a_loadmm_ref_reg(list,regsize,regsize,href,reg,mms_movescalar);
+ else
+ internalerror(2004101012);
+ end;
+ end;
+ else
+ internalerror(2002081302);
+ end;
+ end;
+
+
+{****************************************************************************
+ some generic implementations
+****************************************************************************}
+
+{$push}
+{$r-}
+{$q-}
+
+ procedure tcg.a_load_subsetreg_reg(list : TAsmList; subsetsize, tosize: tcgsize; const sreg: tsubsetregister; destreg: tregister);
+ var
+ bitmask: aword;
+ tmpreg: tregister;
+ stopbit: byte;
+ begin
+ tmpreg:=getintregister(list,sreg.subsetregsize);
+ if (subsetsize in [OS_S8..OS_S128]) then
+ begin
+ { sign extend in case the value has a bitsize mod 8 <> 0 }
+ { both instructions will be optimized away if not }
+ a_op_const_reg_reg(list,OP_SHL,sreg.subsetregsize,(tcgsize2size[sreg.subsetregsize]*8)-sreg.startbit-sreg.bitlen,sreg.subsetreg,tmpreg);
+ a_op_const_reg(list,OP_SAR,sreg.subsetregsize,(tcgsize2size[sreg.subsetregsize]*8)-sreg.bitlen,tmpreg);
+ end
+ else
+ begin
+ a_op_const_reg_reg(list,OP_SHR,sreg.subsetregsize,sreg.startbit,sreg.subsetreg,tmpreg);
+ stopbit := sreg.startbit + sreg.bitlen;
+ // on x86(64), 1 shl 32(64) = 1 instead of 0
+ // use aword to prevent overflow with 1 shl 31
+ if (stopbit - sreg.startbit <> AIntBits) then
+ bitmask := (aword(1) shl (stopbit - sreg.startbit)) - 1
+ else
+ bitmask := high(aword);
+ a_op_const_reg(list,OP_AND,sreg.subsetregsize,tcgint(bitmask),tmpreg);
+ end;
+ tmpreg := makeregsize(list,tmpreg,subsetsize);
+ a_load_reg_reg(list,tcgsize2unsigned[subsetsize],subsetsize,tmpreg,tmpreg);
+ a_load_reg_reg(list,subsetsize,tosize,tmpreg,destreg);
+ end;
+
+
+ procedure tcg.a_load_reg_subsetreg(list : TAsmList; fromsize, subsetsize: tcgsize; fromreg: tregister; const sreg: tsubsetregister);
+ begin
+ a_load_regconst_subsetreg_intern(list,fromsize,subsetsize,fromreg,sreg,SL_REG);
+ end;
+
+
+ procedure tcg.a_load_regconst_subsetreg_intern(list : TAsmList; fromsize, subsetsize: tcgsize; fromreg: tregister; const sreg: tsubsetregister; slopt: tsubsetloadopt);
+ var
+ bitmask: aword;
+ tmpreg: tregister;
+ stopbit: byte;
+ begin
+ stopbit := sreg.startbit + sreg.bitlen;
+ // on x86(64), 1 shl 32(64) = 1 instead of 0
+ if (stopbit <> AIntBits) then
+ bitmask := not(((aword(1) shl stopbit)-1) xor ((aword(1) shl sreg.startbit)-1))
+ else
+ bitmask := not(high(aword) xor ((aword(1) shl sreg.startbit)-1));
+ if not(slopt in [SL_SETZERO,SL_SETMAX]) then
+ begin
+ tmpreg:=getintregister(list,sreg.subsetregsize);
+ a_load_reg_reg(list,fromsize,sreg.subsetregsize,fromreg,tmpreg);
+ a_op_const_reg(list,OP_SHL,sreg.subsetregsize,sreg.startbit,tmpreg);
+ if (slopt <> SL_REGNOSRCMASK) then
+ a_op_const_reg(list,OP_AND,sreg.subsetregsize,tcgint(not(bitmask)),tmpreg);
+ end;
+ if (slopt <> SL_SETMAX) then
+ a_op_const_reg(list,OP_AND,sreg.subsetregsize,tcgint(bitmask),sreg.subsetreg);
+
+ case slopt of
+ SL_SETZERO : ;
+ SL_SETMAX :
+ if (sreg.bitlen <> AIntBits) then
+ a_op_const_reg(list,OP_OR,sreg.subsetregsize,
+ tcgint(((aword(1) shl sreg.bitlen)-1) shl sreg.startbit),
+ sreg.subsetreg)
+ else
+ a_load_const_reg(list,sreg.subsetregsize,-1,sreg.subsetreg);
+ else
+ a_op_reg_reg(list,OP_OR,sreg.subsetregsize,tmpreg,sreg.subsetreg);
+ end;
+ end;
+
+
+ procedure tcg.a_load_subsetreg_subsetreg(list: TAsmlist; fromsubsetsize, tosubsetsize : tcgsize; const fromsreg, tosreg: tsubsetregister);
+ var
+ tmpreg: tregister;
+ bitmask: aword;
+ stopbit: byte;
+ begin
+ if (fromsreg.bitlen >= tosreg.bitlen) then
+ begin
+ tmpreg := getintregister(list,tosreg.subsetregsize);
+ a_load_reg_reg(list,fromsreg.subsetregsize,tosreg.subsetregsize,fromsreg.subsetreg,tmpreg);
+ if (fromsreg.startbit <= tosreg.startbit) then
+ a_op_const_reg(list,OP_SHL,tosreg.subsetregsize,tosreg.startbit-fromsreg.startbit,tmpreg)
+ else
+ a_op_const_reg(list,OP_SHR,tosreg.subsetregsize,fromsreg.startbit-tosreg.startbit,tmpreg);
+ stopbit := tosreg.startbit + tosreg.bitlen;
+ // on x86(64), 1 shl 32(64) = 1 instead of 0
+ if (stopbit <> AIntBits) then
+ bitmask := not(((aword(1) shl stopbit)-1) xor ((aword(1) shl tosreg.startbit)-1))
+ else
+ bitmask := (aword(1) shl tosreg.startbit) - 1;
+ a_op_const_reg(list,OP_AND,tosreg.subsetregsize,tcgint(bitmask),tosreg.subsetreg);
+ a_op_const_reg(list,OP_AND,tosreg.subsetregsize,tcgint(not(bitmask)),tmpreg);
+ a_op_reg_reg(list,OP_OR,tosreg.subsetregsize,tmpreg,tosreg.subsetreg);
+ end
+ else
+ begin
+ tmpreg := getintregister(list,tosubsetsize);
+ a_load_subsetreg_reg(list,fromsubsetsize,tosubsetsize,fromsreg,tmpreg);
+ a_load_reg_subsetreg(list,tosubsetsize,tosubsetsize,tmpreg,tosreg);
+ end;
+ end;
+
+
+ procedure tcg.a_load_subsetreg_ref(list : TAsmList; subsetsize, tosize: tcgsize; const sreg: tsubsetregister; const destref: treference);
+ var
+ tmpreg: tregister;
+ begin
+ tmpreg := getintregister(list,tosize);
+ a_load_subsetreg_reg(list,subsetsize,tosize,sreg,tmpreg);
+ a_load_reg_ref(list,tosize,tosize,tmpreg,destref);
+ end;
+
+
+ procedure tcg.a_load_ref_subsetreg(list : TAsmList; fromsize, subsetsize: tcgsize; const fromref: treference; const sreg: tsubsetregister);
+ var
+ tmpreg: tregister;
+ begin
+ tmpreg := getintregister(list,subsetsize);
+ a_load_ref_reg(list,fromsize,subsetsize,fromref,tmpreg);
+ a_load_reg_subsetreg(list,subsetsize,subsetsize,tmpreg,sreg);
+ end;
+
+
+ procedure tcg.a_load_const_subsetreg(list: TAsmlist; subsetsize: tcgsize; a: tcgint; const sreg: tsubsetregister);
+ var
+ bitmask: aword;
+ stopbit: byte;
+ begin
+ stopbit := sreg.startbit + sreg.bitlen;
+ // on x86(64), 1 shl 32(64) = 1 instead of 0
+ if (stopbit <> AIntBits) then
+ bitmask := not(((aword(1) shl stopbit)-1) xor ((aword(1) shl sreg.startbit)-1))
+ else
+ bitmask := (aword(1) shl sreg.startbit) - 1;
+ if (((aword(a) shl sreg.startbit) and not bitmask) <> not bitmask) then
+ a_op_const_reg(list,OP_AND,sreg.subsetregsize,tcgint(bitmask),sreg.subsetreg);
+ a_op_const_reg(list,OP_OR,sreg.subsetregsize,tcgint((aword(a) shl sreg.startbit) and not(bitmask)),sreg.subsetreg);
+ end;
+
+
+ procedure tcg.a_load_loc_subsetref(list : TAsmList;subsetsize: tcgsize; const loc: tlocation; const sref : tsubsetreference);
+ begin
+ case loc.loc of
+ LOC_REFERENCE,LOC_CREFERENCE:
+ a_load_ref_subsetref(list,loc.size,subsetsize,loc.reference,sref);
+ LOC_REGISTER,LOC_CREGISTER:
+ a_load_reg_subsetref(list,loc.size,subsetsize,loc.register,sref);
+ LOC_CONSTANT:
+ a_load_const_subsetref(list,subsetsize,loc.value,sref);
+ LOC_SUBSETREG,LOC_CSUBSETREG:
+ a_load_subsetreg_subsetref(list,loc.size,subsetsize,loc.sreg,sref);
+ LOC_SUBSETREF,LOC_CSUBSETREF:
+ a_load_subsetref_subsetref(list,loc.size,subsetsize,loc.sref,sref);
+ else
+ internalerror(200608053);
+ end;
+ end;
+
+
+(*
+ Subsetrefs are used for (bit)packed arrays and (bit)packed records stored
+ in memory. They are like a regular reference, but contain an extra bit
+ offset (either constant -startbit- or variable -bitindexreg-, always OS_INT)
+ and a bit length (always constant).
+
+ Bit packed values are stored differently in memory depending on whether we
+ are on a big or a little endian system (compatible with at least GPC). The
+ size of the basic working unit is always the smallest power-of-2 byte size
+ which can contain the bit value (so 1..8 bits -> 1 byte, 9..16 bits -> 2
+ bytes, 17..32 bits -> 4 bytes etc).
+
+ On a big endian, 5-bit: values are stored like this:
+ 11111222 22333334 44445555 56666677 77788888
+ The leftmost bit of each 5-bit value corresponds to the most significant
+ bit.
+
+ On little endian, it goes like this:
+ 22211111 43333322 55554444 77666665 88888777
+ In this case, per byte the left-most bit is more significant than those on
+ the right, but the bits in the next byte are all more significant than
+ those in the previous byte (e.g., the 222 in the first byte are the low
+ three bits of that value, while the 22 in the second byte are the upper
+ two bits.
+
+ Big endian, 9 bit values:
+ 11111111 12222222 22333333 33344444 ...
+
+ Little endian, 9 bit values:
+ 11111111 22222221 33333322 44444333 ...
+ This is memory representation and the 16 bit values are byteswapped.
+ Similarly as in the previous case, the 2222222 string contains the lower
+ bits of value 2 and the 22 string contains the upper bits. Once loaded into
+ registers (two 16 bit registers in the current implementation, although a
+ single 32 bit register would be possible too, in particular if 32 bit
+ alignment can be guaranteed), this becomes:
+ 22222221 11111111 44444333 33333322 ...
+ (l)ow u l l u l u
+
+ The startbit/bitindex in a subsetreference always refers to
+ a) on big endian: the most significant bit of the value
+ (bits counted from left to right, both memory an registers)
+ b) on little endian: the least significant bit when the value
+ is loaded in a register (bit counted from right to left)
+
+ Although a) results in more complex code for big endian systems, it's
+ needed for compatibility both with GPC and with e.g. bitpacked arrays in
+ Apple's universal interfaces which depend on these layout differences).
+
+ Note: when changing the loadsize calculated in get_subsetref_load_info,
+ make sure the appropriate alignment is guaranteed, at least in case of
+ {$defined cpurequiresproperalignment}.
+*)
+
+ procedure tcg.get_subsetref_load_info(const sref: tsubsetreference; out loadsize: tcgsize; out extra_load: boolean);
+ var
+ intloadsize: tcgint;
+ begin
+ intloadsize := packedbitsloadsize(sref.bitlen);
+
+ if (intloadsize = 0) then
+ internalerror(2006081310);
+
+ if (intloadsize > sizeof(aint)) then
+ intloadsize := sizeof(aint);
+ loadsize := int_cgsize(intloadsize);
+
+ if (loadsize = OS_NO) then
+ internalerror(2006081311);
+ if (sref.bitlen > sizeof(aint)*8) then
+ internalerror(2006081312);
+
+ extra_load :=
+ (sref.bitlen <> 1) and
+ ((sref.bitindexreg <> NR_NO) or
+ (byte(sref.startbit+sref.bitlen) > byte(intloadsize*8)));
+ end;
+
+
+ procedure tcg.a_load_subsetref_regs_noindex(list: TAsmList; subsetsize: tcgsize; loadbitsize: byte; const sref: tsubsetreference; valuereg, extra_value_reg: tregister);
+ var
+ restbits: byte;
+ begin
+ if (target_info.endian = endian_big) then
+ begin
+ { valuereg contains the upper bits, extra_value_reg the lower }
+ restbits := (sref.bitlen - (loadbitsize - sref.startbit));
+ if (subsetsize in [OS_S8..OS_S128]) then
+ begin
+ { sign extend }
+ a_op_const_reg(list,OP_SHL,OS_INT,AIntBits-loadbitsize+sref.startbit,valuereg);
+ a_op_const_reg(list,OP_SAR,OS_INT,AIntBits-sref.bitlen,valuereg);
+ end
+ else
+ begin
+ a_op_const_reg(list,OP_SHL,OS_INT,restbits,valuereg);
+ { mask other bits }
+ if (sref.bitlen <> AIntBits) then
+ a_op_const_reg(list,OP_AND,OS_INT,tcgint((aword(1) shl sref.bitlen)-1),valuereg);
+ end;
+ a_op_const_reg(list,OP_SHR,OS_INT,loadbitsize-restbits,extra_value_reg)
+ end
+ else
+ begin
+ { valuereg contains the lower bits, extra_value_reg the upper }
+ a_op_const_reg(list,OP_SHR,OS_INT,sref.startbit,valuereg);
+ if (subsetsize in [OS_S8..OS_S128]) then
+ begin
+ a_op_const_reg(list,OP_SHL,OS_INT,AIntBits-sref.bitlen+loadbitsize-sref.startbit,extra_value_reg);
+ a_op_const_reg(list,OP_SAR,OS_INT,AIntBits-sref.bitlen,extra_value_reg);
+ end
+ else
+ begin
+ a_op_const_reg(list,OP_SHL,OS_INT,loadbitsize-sref.startbit,extra_value_reg);
+ { mask other bits }
+ if (sref.bitlen <> AIntBits) then
+ a_op_const_reg(list,OP_AND,OS_INT,tcgint((aword(1) shl sref.bitlen)-1),extra_value_reg);
+ end;
+ end;
+ { merge }
+ a_op_reg_reg(list,OP_OR,OS_INT,extra_value_reg,valuereg);
+ end;
+
+
+ procedure tcg.a_load_subsetref_regs_index(list: TAsmList; subsetsize: tcgsize; loadbitsize: byte; const sref: tsubsetreference; valuereg: tregister);
+ var
+ hl: tasmlabel;
+ tmpref: treference;
+ extra_value_reg,
+ tmpreg: tregister;
+ begin
+ tmpreg := getintregister(list,OS_INT);
+ tmpref := sref.ref;
+ inc(tmpref.offset,loadbitsize div 8);
+ extra_value_reg := getintregister(list,OS_INT);
+
+ if (target_info.endian = endian_big) then
+ begin
+ { since this is a dynamic index, it's possible that the value }
+ { is entirely in valuereg. }
+
+ { get the data in valuereg in the right place }
+ a_op_reg_reg(list,OP_SHL,OS_INT,sref.bitindexreg,valuereg);
+ if (subsetsize in [OS_S8..OS_S128]) then
+ begin
+ a_op_const_reg(list,OP_SHL,OS_INT,AIntBits-loadbitsize,valuereg);
+ a_op_const_reg(list,OP_SAR,OS_INT,AIntBits-sref.bitlen,valuereg)
+ end
+ else
+ begin
+ a_op_const_reg(list,OP_SHR,OS_INT,loadbitsize-sref.bitlen,valuereg);
+ if (loadbitsize <> AIntBits) then
+ { mask left over bits }
+ a_op_const_reg(list,OP_AND,OS_INT,tcgint((aword(1) shl sref.bitlen)-1),valuereg);
+ end;
+ tmpreg := getintregister(list,OS_INT);
+
+ { ensure we don't load anything past the end of the array }
+ current_asmdata.getjumplabel(hl);
+ a_cmp_const_reg_label(list,OS_INT,OC_BE,loadbitsize-sref.bitlen,sref.bitindexreg,hl);
+
+ { the bits in extra_value_reg (if any) start at the most significant bit => }
+ { extra_value_reg must be shr by (loadbitsize-sref.bitlen)+(loadsize-sref.bitindex) }
+ { => = -(sref.bitindex+(sref.bitlen-2*loadbitsize)) }
+ a_op_const_reg_reg(list,OP_ADD,OS_INT,sref.bitlen-2*loadbitsize,sref.bitindexreg,tmpreg);
+ a_op_reg_reg(list,OP_NEG,OS_INT,tmpreg,tmpreg);
+
+ { load next "loadbitsize" bits of the array }
+ a_load_ref_reg(list,int_cgsize(loadbitsize div 8),OS_INT,tmpref,extra_value_reg);
+
+ a_op_reg_reg(list,OP_SHR,OS_INT,tmpreg,extra_value_reg);
+ { if there are no bits in extra_value_reg, then sref.bitindex was }
+ { < loadsize-sref.bitlen, and therefore tmpreg will now be >= loadsize }
+ { => extra_value_reg is now 0 }
+ { merge }
+ a_op_reg_reg(list,OP_OR,OS_INT,extra_value_reg,valuereg);
+ { no need to mask, necessary masking happened earlier on }
+ a_label(list,hl);
+ end
+ else
+ begin
+ a_op_reg_reg(list,OP_SHR,OS_INT,sref.bitindexreg,valuereg);
+
+ { ensure we don't load anything past the end of the array }
+ current_asmdata.getjumplabel(hl);
+ a_cmp_const_reg_label(list,OS_INT,OC_BE,loadbitsize-sref.bitlen,sref.bitindexreg,hl);
+
+ { Y-x = -(Y-x) }
+ a_op_const_reg_reg(list,OP_SUB,OS_INT,loadbitsize,sref.bitindexreg,tmpreg);
+ a_op_reg_reg(list,OP_NEG,OS_INT,tmpreg,tmpreg);
+
+ { load next "loadbitsize" bits of the array }
+ a_load_ref_reg(list,int_cgsize(loadbitsize div 8),OS_INT,tmpref,extra_value_reg);
+
+ { tmpreg is in the range 1..<cpu_bitsize>-1 -> always ok }
+ a_op_reg_reg(list,OP_SHL,OS_INT,tmpreg,extra_value_reg);
+ { merge }
+ a_op_reg_reg(list,OP_OR,OS_INT,extra_value_reg,valuereg);
+ a_label(list,hl);
+ { sign extend or mask other bits }
+ if (subsetsize in [OS_S8..OS_S128]) then
+ begin
+ a_op_const_reg(list,OP_SHL,OS_INT,AIntBits-sref.bitlen,valuereg);
+ a_op_const_reg(list,OP_SAR,OS_INT,AIntBits-sref.bitlen,valuereg);
+ end
+ else
+ a_op_const_reg(list,OP_AND,OS_INT,tcgint((aword(1) shl sref.bitlen)-1),valuereg);
+ end;
+ end;
+
+
+ procedure tcg.a_load_subsetref_reg(list : TAsmList; subsetsize, tosize: tcgsize; const sref: tsubsetreference; destreg: tregister);
+ var
+ tmpref: treference;
+ valuereg,extra_value_reg: tregister;
+ tosreg: tsubsetregister;
+ loadsize: tcgsize;
+ loadbitsize: byte;
+ extra_load: boolean;
+ begin
+
+ get_subsetref_load_info(sref,loadsize,extra_load);
+ loadbitsize := tcgsize2size[loadsize]*8;
+
+ { load the (first part) of the bit sequence }
+ valuereg := getintregister(list,OS_INT);
+ a_load_ref_reg(list,loadsize,OS_INT,sref.ref,valuereg);
+
+ if not extra_load then
+ begin
+ { everything is guaranteed to be in a single register of loadsize }
+ if (sref.bitindexreg = NR_NO) then
+ begin
+ { use subsetreg routine, it may have been overridden with an optimized version }
+ tosreg.subsetreg := valuereg;
+ tosreg.subsetregsize := OS_INT;
+ { subsetregs always count bits from right to left }
+ if (target_info.endian = endian_big) then
+ tosreg.startbit := loadbitsize - (sref.startbit+sref.bitlen)
+ else
+ tosreg.startbit := sref.startbit;
+ tosreg.bitlen := sref.bitlen;
+ a_load_subsetreg_reg(list,subsetsize,tosize,tosreg,destreg);
+ exit;
+ end
+ else
+ begin
+ if (sref.startbit <> 0) then
+ internalerror(2006081510);
+ if (target_info.endian = endian_big) then
+ begin
+ a_op_reg_reg(list,OP_SHL,OS_INT,sref.bitindexreg,valuereg);
+ if (subsetsize in [OS_S8..OS_S128]) then
+ begin
+ { sign extend to entire register }
+ a_op_const_reg(list,OP_SHL,OS_INT,AIntBits-loadbitsize,valuereg);
+ a_op_const_reg(list,OP_SAR,OS_INT,AIntBits-sref.bitlen,valuereg);
+ end
+ else
+ a_op_const_reg(list,OP_SHR,OS_INT,loadbitsize-sref.bitlen,valuereg);
+ end
+ else
+ begin
+ a_op_reg_reg(list,OP_SHR,OS_INT,sref.bitindexreg,valuereg);
+ if (subsetsize in [OS_S8..OS_S128]) then
+ begin
+ a_op_const_reg(list,OP_SHL,OS_INT,AIntBits-sref.bitlen,valuereg);
+ a_op_const_reg(list,OP_SAR,OS_INT,AIntBits-sref.bitlen,valuereg);
+ end
+ end;
+ { mask other bits/sign extend }
+ if not(subsetsize in [OS_S8..OS_S128]) then
+ a_op_const_reg(list,OP_AND,OS_INT,tcgint((aword(1) shl sref.bitlen)-1),valuereg);
+ end
+ end
+ else
+ begin
+ { load next value as well }
+ extra_value_reg := getintregister(list,OS_INT);
+
+ if (sref.bitindexreg = NR_NO) then
+ begin
+ tmpref := sref.ref;
+ inc(tmpref.offset,loadbitsize div 8);
+ a_load_ref_reg(list,loadsize,OS_INT,tmpref,extra_value_reg);
+ { can be overridden to optimize }
+ a_load_subsetref_regs_noindex(list,subsetsize,loadbitsize,sref,valuereg,extra_value_reg)
+ end
+ else
+ begin
+ if (sref.startbit <> 0) then
+ internalerror(2006080610);
+ a_load_subsetref_regs_index(list,subsetsize,loadbitsize,sref,valuereg);
+ end;
+ end;
+
+ { store in destination }
+ { avoid unnecessary sign extension and zeroing }
+ valuereg := makeregsize(list,valuereg,OS_INT);
+ destreg := makeregsize(list,destreg,OS_INT);
+ a_load_reg_reg(list,OS_INT,OS_INT,valuereg,destreg);
+ destreg := makeregsize(list,destreg,tosize);
+ end;
+
+
+ procedure tcg.a_load_reg_subsetref(list : TAsmList; fromsize, subsetsize: tcgsize; fromreg: tregister; const sref: tsubsetreference);
+ begin
+ a_load_regconst_subsetref_intern(list,fromsize,subsetsize,fromreg,sref,SL_REG);
+ end;
+
+
+ procedure tcg.a_load_regconst_subsetref_intern(list : TAsmList; fromsize, subsetsize: tcgsize; fromreg: tregister; const sref: tsubsetreference; slopt: tsubsetloadopt);
+ var
+ hl: tasmlabel;
+ tmpreg, tmpindexreg, valuereg, extra_value_reg, maskreg: tregister;
+ tosreg, fromsreg: tsubsetregister;
+ tmpref: treference;
+ bitmask: aword;
+ loadsize: tcgsize;
+ loadbitsize: byte;
+ extra_load: boolean;
+ begin
+ { the register must be able to contain the requested value }
+ if (tcgsize2size[fromsize]*8 < sref.bitlen) then
+ internalerror(2006081613);
+
+ get_subsetref_load_info(sref,loadsize,extra_load);
+ loadbitsize := tcgsize2size[loadsize]*8;
+
+ { load the (first part) of the bit sequence }
+ valuereg := getintregister(list,OS_INT);
+ a_load_ref_reg(list,loadsize,OS_INT,sref.ref,valuereg);
+
+ { constant offset of bit sequence? }
+ if not extra_load then
+ begin
+ if (sref.bitindexreg = NR_NO) then
+ begin
+ { use subsetreg routine, it may have been overridden with an optimized version }
+ tosreg.subsetreg := valuereg;
+ tosreg.subsetregsize := OS_INT;
+ { subsetregs always count bits from right to left }
+ if (target_info.endian = endian_big) then
+ tosreg.startbit := loadbitsize - (sref.startbit+sref.bitlen)
+ else
+ tosreg.startbit := sref.startbit;
+ tosreg.bitlen := sref.bitlen;
+ a_load_regconst_subsetreg_intern(list,fromsize,subsetsize,fromreg,tosreg,slopt);
+ end
+ else
+ begin
+ if (sref.startbit <> 0) then
+ internalerror(2006081710);
+ { should be handled by normal code and will give wrong result }
+ { on x86 for the '1 shl bitlen' below }
+ if (sref.bitlen = AIntBits) then
+ internalerror(2006081711);
+
+ { zero the bits we have to insert }
+ if (slopt <> SL_SETMAX) then
+ begin
+ maskreg := getintregister(list,OS_INT);
+ if (target_info.endian = endian_big) then
+ begin
+ a_load_const_reg(list,OS_INT,tcgint((aword(1) shl sref.bitlen)-1) shl (loadbitsize-sref.bitlen),maskreg);
+ a_op_reg_reg(list,OP_SHR,OS_INT,sref.bitindexreg,maskreg);
+ end
+ else
+ begin
+ a_load_const_reg(list,OS_INT,tcgint((aword(1) shl sref.bitlen)-1),maskreg);
+ a_op_reg_reg(list,OP_SHL,OS_INT,sref.bitindexreg,maskreg);
+ end;
+ a_op_reg_reg(list,OP_NOT,OS_INT,maskreg,maskreg);
+ a_op_reg_reg(list,OP_AND,OS_INT,maskreg,valuereg);
+ end;
+
+ { insert the value }
+ if (slopt <> SL_SETZERO) then
+ begin
+ tmpreg := getintregister(list,OS_INT);
+ if (slopt <> SL_SETMAX) then
+ a_load_reg_reg(list,fromsize,OS_INT,fromreg,tmpreg)
+ else if (sref.bitlen <> AIntBits) then
+ a_load_const_reg(list,OS_INT,tcgint((aword(1) shl sref.bitlen) - 1), tmpreg)
+ else
+ a_load_const_reg(list,OS_INT,-1,tmpreg);
+ if (target_info.endian = endian_big) then
+ begin
+ a_op_const_reg(list,OP_SHL,OS_INT,loadbitsize-sref.bitlen,tmpreg);
+ if not(slopt in [SL_REGNOSRCMASK,SL_SETMAX]) then
+ begin
+ if (loadbitsize <> AIntBits) then
+ bitmask := (((aword(1) shl loadbitsize)-1) xor ((aword(1) shl (loadbitsize-sref.bitlen))-1))
+ else
+ bitmask := (high(aword) xor ((aword(1) shl (loadbitsize-sref.bitlen))-1));
+ a_op_const_reg(list,OP_AND,OS_INT,bitmask,tmpreg);
+ end;
+ a_op_reg_reg(list,OP_SHR,OS_INT,sref.bitindexreg,tmpreg);
+ end
+ else
+ begin
+ if not(slopt in [SL_REGNOSRCMASK,SL_SETMAX]) then
+ a_op_const_reg(list,OP_AND,OS_INT,tcgint((aword(1) shl sref.bitlen)-1),tmpreg);
+ a_op_reg_reg(list,OP_SHL,OS_INT,sref.bitindexreg,tmpreg);
+ end;
+ a_op_reg_reg(list,OP_OR,OS_INT,tmpreg,valuereg);
+ end;
+ end;
+ { store back to memory }
+ valuereg := makeregsize(list,valuereg,loadsize);
+ a_load_reg_ref(list,loadsize,loadsize,valuereg,sref.ref);
+ exit;
+ end
+ else
+ begin
+ { load next value }
+ extra_value_reg := getintregister(list,OS_INT);
+ tmpref := sref.ref;
+ inc(tmpref.offset,loadbitsize div 8);
+
+ { should maybe be taken out too, can be done more efficiently }
+ { on e.g. i386 with shld/shrd }
+ if (sref.bitindexreg = NR_NO) then
+ begin
+ a_load_ref_reg(list,loadsize,OS_INT,tmpref,extra_value_reg);
+
+ fromsreg.subsetreg := fromreg;
+ fromsreg.subsetregsize := fromsize;
+ tosreg.subsetreg := valuereg;
+ tosreg.subsetregsize := OS_INT;
+
+ { transfer first part }
+ fromsreg.bitlen := loadbitsize-sref.startbit;
+ tosreg.bitlen := fromsreg.bitlen;
+ if (target_info.endian = endian_big) then
+ begin
+ { valuereg must contain the upper bits of the value at bits [0..loadbitsize-startbit] }
+
+ { upper bits of the value ... }
+ fromsreg.startbit := sref.bitlen-(loadbitsize-sref.startbit);
+ { ... to bit 0 }
+ tosreg.startbit := 0
+ end
+ else
+ begin
+ { valuereg must contain the lower bits of the value at bits [startbit..loadbitsize] }
+
+ { lower bits of the value ... }
+ fromsreg.startbit := 0;
+ { ... to startbit }
+ tosreg.startbit := sref.startbit;
+ end;
+ case slopt of
+ SL_SETZERO,
+ SL_SETMAX:
+ a_load_regconst_subsetreg_intern(list,fromsize,subsetsize,fromreg,tosreg,slopt);
+ else
+ a_load_subsetreg_subsetreg(list,subsetsize,subsetsize,fromsreg,tosreg);
+ end;
+ valuereg := makeregsize(list,valuereg,loadsize);
+ a_load_reg_ref(list,loadsize,loadsize,valuereg,sref.ref);
+
+ { transfer second part }
+ if (target_info.endian = endian_big) then
+ begin
+ { extra_value_reg must contain the lower bits of the value at bits }
+ { [(loadbitsize-(bitlen-(loadbitsize-startbit)))..loadbitsize] }
+ { (loadbitsize-(bitlen-(loadbitsize-startbit))) = 2*loadbitsize }
+ { - bitlen - startbit }
+
+ fromsreg.startbit := 0;
+ tosreg.startbit := 2*loadbitsize - sref.bitlen - sref.startbit
+ end
+ else
+ begin
+ { extra_value_reg must contain the upper bits of the value at bits [0..bitlen-(loadbitsize-startbit)] }
+
+ fromsreg.startbit := fromsreg.bitlen;
+ tosreg.startbit := 0;
+ end;
+ tosreg.subsetreg := extra_value_reg;
+ fromsreg.bitlen := sref.bitlen-fromsreg.bitlen;
+ tosreg.bitlen := fromsreg.bitlen;
+
+ case slopt of
+ SL_SETZERO,
+ SL_SETMAX:
+ a_load_regconst_subsetreg_intern(list,fromsize,subsetsize,fromreg,tosreg,slopt);
+ else
+ a_load_subsetreg_subsetreg(list,subsetsize,subsetsize,fromsreg,tosreg);
+ end;
+ extra_value_reg := makeregsize(list,extra_value_reg,loadsize);
+ a_load_reg_ref(list,loadsize,loadsize,extra_value_reg,tmpref);
+ exit;
+ end
+ else
+ begin
+ if (sref.startbit <> 0) then
+ internalerror(2006081812);
+ { should be handled by normal code and will give wrong result }
+ { on x86 for the '1 shl bitlen' below }
+ if (sref.bitlen = AIntBits) then
+ internalerror(2006081713);
+
+ { generate mask to zero the bits we have to insert }
+ if (slopt <> SL_SETMAX) then
+ begin
+ maskreg := getintregister(list,OS_INT);
+ if (target_info.endian = endian_big) then
+ begin
+ a_load_const_reg(list,OS_INT,tcgint(((aword(1) shl sref.bitlen)-1) shl (loadbitsize-sref.bitlen)),maskreg);
+ a_op_reg_reg(list,OP_SHR,OS_INT,sref.bitindexreg,maskreg);
+ end
+ else
+ begin
+ a_load_const_reg(list,OS_INT,tcgint((aword(1) shl sref.bitlen)-1),maskreg);
+ a_op_reg_reg(list,OP_SHL,OS_INT,sref.bitindexreg,maskreg);
+ end;
+
+ a_op_reg_reg(list,OP_NOT,OS_INT,maskreg,maskreg);
+ a_op_reg_reg(list,OP_AND,OS_INT,maskreg,valuereg);
+ end;
+
+ { insert the value }
+ if (slopt <> SL_SETZERO) then
+ begin
+ tmpreg := getintregister(list,OS_INT);
+ if (slopt <> SL_SETMAX) then
+ a_load_reg_reg(list,fromsize,OS_INT,fromreg,tmpreg)
+ else if (sref.bitlen <> AIntBits) then
+ a_load_const_reg(list,OS_INT,tcgint((aword(1) shl sref.bitlen) - 1), tmpreg)
+ else
+ a_load_const_reg(list,OS_INT,-1,tmpreg);
+ if (target_info.endian = endian_big) then
+ begin
+ a_op_const_reg(list,OP_SHL,OS_INT,loadbitsize-sref.bitlen,tmpreg);
+ if not(slopt in [SL_REGNOSRCMASK,SL_SETMAX]) then
+ { mask left over bits }
+ a_op_const_reg(list,OP_AND,OS_INT,tcgint(((aword(1) shl sref.bitlen)-1) shl (loadbitsize-sref.bitlen)),tmpreg);
+ a_op_reg_reg(list,OP_SHR,OS_INT,sref.bitindexreg,tmpreg);
+ end
+ else
+ begin
+ if not(slopt in [SL_REGNOSRCMASK,SL_SETMAX]) then
+ { mask left over bits }
+ a_op_const_reg(list,OP_AND,OS_INT,tcgint((aword(1) shl sref.bitlen)-1),tmpreg);
+ a_op_reg_reg(list,OP_SHL,OS_INT,sref.bitindexreg,tmpreg);
+ end;
+ a_op_reg_reg(list,OP_OR,OS_INT,tmpreg,valuereg);
+ end;
+ valuereg := makeregsize(list,valuereg,loadsize);
+ a_load_reg_ref(list,loadsize,loadsize,valuereg,sref.ref);
+
+ { make sure we do not read/write past the end of the array }
+ current_asmdata.getjumplabel(hl);
+ a_cmp_const_reg_label(list,OS_INT,OC_BE,loadbitsize-sref.bitlen,sref.bitindexreg,hl);
+
+ a_load_ref_reg(list,loadsize,OS_INT,tmpref,extra_value_reg);
+ tmpindexreg := getintregister(list,OS_INT);
+
+ { load current array value }
+ if (slopt <> SL_SETZERO) then
+ begin
+ tmpreg := getintregister(list,OS_INT);
+ if (slopt <> SL_SETMAX) then
+ a_load_reg_reg(list,fromsize,OS_INT,fromreg,tmpreg)
+ else if (sref.bitlen <> AIntBits) then
+ a_load_const_reg(list,OS_INT,tcgint((aword(1) shl sref.bitlen) - 1), tmpreg)
+ else
+ a_load_const_reg(list,OS_INT,-1,tmpreg);
+ end;
+
+ { generate mask to zero the bits we have to insert }
+ if (slopt <> SL_SETMAX) then
+ begin
+ maskreg := getintregister(list,OS_INT);
+ if (target_info.endian = endian_big) then
+ begin
+ a_op_const_reg_reg(list,OP_ADD,OS_INT,sref.bitlen-2*loadbitsize,sref.bitindexreg,tmpindexreg);
+ a_op_reg_reg(list,OP_NEG,OS_INT,tmpindexreg,tmpindexreg);
+ a_load_const_reg(list,OS_INT,tcgint((aword(1) shl sref.bitlen)-1),maskreg);
+ a_op_reg_reg(list,OP_SHL,OS_INT,tmpindexreg,maskreg);
+ end
+ else
+ begin
+ { Y-x = -(x-Y) }
+ a_op_const_reg_reg(list,OP_SUB,OS_INT,loadbitsize,sref.bitindexreg,tmpindexreg);
+ a_op_reg_reg(list,OP_NEG,OS_INT,tmpindexreg,tmpindexreg);
+ a_load_const_reg(list,OS_INT,tcgint((aword(1) shl sref.bitlen)-1),maskreg);
+ a_op_reg_reg(list,OP_SHR,OS_INT,tmpindexreg,maskreg);
+ end;
+
+ a_op_reg_reg(list,OP_NOT,OS_INT,maskreg,maskreg);
+ a_op_reg_reg(list,OP_AND,OS_INT,maskreg,extra_value_reg);
+ end;
+
+ if (slopt <> SL_SETZERO) then
+ begin
+ if (target_info.endian = endian_big) then
+ a_op_reg_reg(list,OP_SHL,OS_INT,tmpindexreg,tmpreg)
+ else
+ begin
+ if not(slopt in [SL_REGNOSRCMASK,SL_SETMAX]) then
+ a_op_const_reg(list,OP_AND,OS_INT,tcgint((aword(1) shl sref.bitlen)-1),tmpreg);
+ a_op_reg_reg(list,OP_SHR,OS_INT,tmpindexreg,tmpreg);
+ end;
+ a_op_reg_reg(list,OP_OR,OS_INT,tmpreg,extra_value_reg);
+ end;
+ extra_value_reg := makeregsize(list,extra_value_reg,loadsize);
+ a_load_reg_ref(list,loadsize,loadsize,extra_value_reg,tmpref);
+
+ a_label(list,hl);
+ end;
+ end;
+ end;
+
+
+ procedure tcg.a_load_subsetref_subsetref(list: TAsmlist; fromsubsetsize, tosubsetsize : tcgsize; const fromsref, tosref: tsubsetreference);
+ var
+ tmpreg: tregister;
+ begin
+ tmpreg := getintregister(list,tosubsetsize);
+ a_load_subsetref_reg(list,fromsubsetsize,tosubsetsize,fromsref,tmpreg);
+ a_load_reg_subsetref(list,tosubsetsize,tosubsetsize,tmpreg,tosref);
+ end;
+
+
+ procedure tcg.a_load_subsetref_ref(list : TAsmList; subsetsize, tosize: tcgsize; const sref: tsubsetreference; const destref: treference);
+ var
+ tmpreg: tregister;
+ begin
+ tmpreg := getintregister(list,tosize);
+ a_load_subsetref_reg(list,subsetsize,tosize,sref,tmpreg);
+ a_load_reg_ref(list,tosize,tosize,tmpreg,destref);
+ end;
+
+
+ procedure tcg.a_load_ref_subsetref(list : TAsmList; fromsize, subsetsize: tcgsize; const fromref: treference; const sref: tsubsetreference);
+ var
+ tmpreg: tregister;
+ begin
+ tmpreg := getintregister(list,subsetsize);
+ a_load_ref_reg(list,fromsize,subsetsize,fromref,tmpreg);
+ a_load_reg_subsetref(list,subsetsize,subsetsize,tmpreg,sref);
+ end;
+
+
+ procedure tcg.a_load_const_subsetref(list: TAsmlist; subsetsize: tcgsize; a: tcgint; const sref: tsubsetreference);
+ var
+ tmpreg: tregister;
+ slopt: tsubsetloadopt;
+ begin
+ { perform masking of the source value in advance }
+ slopt := SL_REGNOSRCMASK;
+ if (sref.bitlen <> AIntBits) then
+ a := tcgint(aword(a) and ((aword(1) shl sref.bitlen) -1));
+ if (
+ { broken x86 "x shl regbitsize = x" }
+ ((sref.bitlen <> AIntBits) and
+ ((aword(a) and ((aword(1) shl sref.bitlen) -1)) = (aword(1) shl sref.bitlen) -1)) or
+ ((sref.bitlen = AIntBits) and
+ (a = -1))
+ ) then
+ slopt := SL_SETMAX
+ else if (a = 0) then
+ slopt := SL_SETZERO;
+ tmpreg := getintregister(list,subsetsize);
+ if not(slopt in [SL_SETZERO,SL_SETMAX]) then
+ a_load_const_reg(list,subsetsize,a,tmpreg);
+ a_load_regconst_subsetref_intern(list,subsetsize,subsetsize,tmpreg,sref,slopt);
+ end;
+
+
+ procedure tcg.a_load_subsetref_loc(list: TAsmlist; subsetsize: tcgsize; const sref: tsubsetreference; const loc: tlocation);
+ begin
+ case loc.loc of
+ LOC_REFERENCE,LOC_CREFERENCE:
+ a_load_subsetref_ref(list,subsetsize,loc.size,sref,loc.reference);
+ LOC_REGISTER,LOC_CREGISTER:
+ a_load_subsetref_reg(list,subsetsize,loc.size,sref,loc.register);
+ LOC_SUBSETREG,LOC_CSUBSETREG:
+ a_load_subsetref_subsetreg(list,subsetsize,loc.size,sref,loc.sreg);
+ LOC_SUBSETREF,LOC_CSUBSETREF:
+ a_load_subsetref_subsetref(list,subsetsize,loc.size,sref,loc.sref);
+ else
+ internalerror(200608054);
+ end;
+ end;
+
+
+ procedure tcg.a_load_subsetref_subsetreg(list: TAsmlist; fromsubsetsize, tosubsetsize : tcgsize; const fromsref: tsubsetreference; const tosreg: tsubsetregister);
+ var
+ tmpreg: tregister;
+ begin
+ tmpreg := getintregister(list,tosubsetsize);
+ a_load_subsetref_reg(list,fromsubsetsize,tosubsetsize,fromsref,tmpreg);
+ a_load_reg_subsetreg(list,tosubsetsize,tosubsetsize,tmpreg,tosreg);
+ end;
+
+
+ procedure tcg.a_load_subsetreg_subsetref(list: TAsmlist; fromsubsetsize, tosubsetsize : tcgsize; const fromsreg: tsubsetregister; const tosref: tsubsetreference);
+ var
+ tmpreg: tregister;
+ begin
+ tmpreg := getintregister(list,tosubsetsize);
+ a_load_subsetreg_reg(list,fromsubsetsize,tosubsetsize,fromsreg,tmpreg);
+ a_load_reg_subsetref(list,tosubsetsize,tosubsetsize,tmpreg,tosref);
+ end;
+
+
+{$pop}
+
+ { generic bit address calculation routines }
+
+ function tcg.get_bit_const_ref_sref(bitnumber: tcgint; const ref: treference): tsubsetreference;
+ begin
+ result.ref:=ref;
+ inc(result.ref.offset,bitnumber div 8);
+ result.bitindexreg:=NR_NO;
+ result.startbit:=bitnumber mod 8;
+ result.bitlen:=1;
+ end;
+
+
+ function tcg.get_bit_const_reg_sreg(setregsize: tcgsize; bitnumber: tcgint; setreg: tregister): tsubsetregister;
+ begin
+ result.subsetreg:=setreg;
+ result.subsetregsize:=setregsize;
+ { subsetregs always count from the least significant to the most significant bit }
+ if (target_info.endian=endian_big) then
+ result.startbit:=(tcgsize2size[setregsize]*8)-bitnumber-1
+ else
+ result.startbit:=bitnumber;
+ result.bitlen:=1;
+ end;
+
+
+ function tcg.get_bit_reg_ref_sref(list: TAsmList; bitnumbersize: tcgsize; bitnumber: tregister; const ref: treference): tsubsetreference;
+ var
+ tmpreg,
+ tmpaddrreg: tregister;
+ begin
+ result.ref:=ref;
+ result.startbit:=0;
+ result.bitlen:=1;
+
+ tmpreg:=getintregister(list,bitnumbersize);
+ a_op_const_reg_reg(list,OP_SHR,bitnumbersize,3,bitnumber,tmpreg);
+ tmpaddrreg:=getaddressregister(list);
+ a_load_reg_reg(list,bitnumbersize,OS_ADDR,tmpreg,tmpaddrreg);
+ if (result.ref.base=NR_NO) then
+ result.ref.base:=tmpaddrreg
+ else if (result.ref.index=NR_NO) then
+ result.ref.index:=tmpaddrreg
+ else
+ begin
+ a_op_reg_reg(list,OP_ADD,OS_ADDR,result.ref.index,tmpaddrreg);
+ result.ref.index:=tmpaddrreg;
+ end;
+ tmpreg:=getintregister(list,OS_INT);
+ a_op_const_reg_reg(list,OP_AND,OS_INT,7,bitnumber,tmpreg);
+ result.bitindexreg:=tmpreg;
+ end;
+
+
+ { bit testing routines }
+
+ procedure tcg.a_bit_test_reg_reg_reg(list : TAsmList; bitnumbersize,valuesize,destsize: tcgsize;bitnumber,value,destreg: tregister);
+ var
+ tmpvalue: tregister;
+ begin
+ tmpvalue:=getintregister(list,valuesize);
+
+ if (target_info.endian=endian_little) then
+ begin
+ { rotate value register "bitnumber" bits to the right }
+ a_op_reg_reg_reg(list,OP_SHR,valuesize,bitnumber,value,tmpvalue);
+ { extract the bit we want }
+ a_op_const_reg(list,OP_AND,valuesize,1,tmpvalue);
+ end
+ else
+ begin
+ { highest (leftmost) bit = bit 0 -> shl bitnumber results in wanted }
+ { bit in uppermost position, then move it to the lowest position }
+ { "and" is not necessary since combination of shl/shr will clear }
+ { all other bits }
+ a_op_reg_reg_reg(list,OP_SHL,valuesize,bitnumber,value,tmpvalue);
+ a_op_const_reg(list,OP_SHR,valuesize,tcgsize2size[valuesize]*8-1,tmpvalue);
+ end;
+ a_load_reg_reg(list,valuesize,destsize,tmpvalue,destreg);
+ end;
+
+
+ procedure tcg.a_bit_test_const_ref_reg(list: TAsmList; destsize: tcgsize; bitnumber: tcgint; const ref: treference; destreg: tregister);
+ begin
+ a_load_subsetref_reg(list,OS_8,destsize,get_bit_const_ref_sref(bitnumber,ref),destreg);
+ end;
+
+
+ procedure tcg.a_bit_test_const_reg_reg(list: TAsmList; setregsize, destsize: tcgsize; bitnumber: tcgint; setreg, destreg: tregister);
+ begin
+ a_load_subsetreg_reg(list,setregsize,destsize,get_bit_const_reg_sreg(setregsize,bitnumber,setreg),destreg);
+ end;
+
+
+ procedure tcg.a_bit_test_const_subsetreg_reg(list: TAsmList; setregsize, destsize: tcgsize; bitnumber: tcgint; const setreg: tsubsetregister; destreg: tregister);
+ var
+ tmpsreg: tsubsetregister;
+ begin
+ { the first parameter is used to calculate the bit offset in }
+ { case of big endian, and therefore must be the size of the }
+ { set and not of the whole subsetreg }
+ tmpsreg:=get_bit_const_reg_sreg(setregsize,bitnumber,setreg.subsetreg);
+ { now fix the size of the subsetreg }
+ tmpsreg.subsetregsize:=setreg.subsetregsize;
+ { correct offset of the set in the subsetreg }
+ inc(tmpsreg.startbit,setreg.startbit);
+ a_load_subsetreg_reg(list,setregsize,destsize,tmpsreg,destreg);
+ end;
+
+
+ procedure tcg.a_bit_test_reg_ref_reg(list: TAsmList; bitnumbersize, destsize: tcgsize; bitnumber: tregister; const ref: treference; destreg: tregister);
+ begin
+ a_load_subsetref_reg(list,OS_8,destsize,get_bit_reg_ref_sref(list,bitnumbersize,bitnumber,ref),destreg);
+ end;
+
+
+ procedure tcg.a_bit_test_reg_loc_reg(list: TAsmList; bitnumbersize, destsize: tcgsize; bitnumber: tregister; const loc: tlocation; destreg: tregister);
+ var
+ tmpreg: tregister;
+ begin
+ case loc.loc of
+ LOC_REFERENCE,LOC_CREFERENCE:
+ a_bit_test_reg_ref_reg(list,bitnumbersize,destsize,bitnumber,loc.reference,destreg);
+ LOC_REGISTER,LOC_CREGISTER,
+ LOC_SUBSETREG,LOC_CSUBSETREG,
+ LOC_CONSTANT:
+ begin
+ case loc.loc of
+ LOC_REGISTER,LOC_CREGISTER:
+ tmpreg:=loc.register;
+ LOC_SUBSETREG,LOC_CSUBSETREG:
+ begin
+ tmpreg:=getintregister(list,loc.size);
+ a_load_subsetreg_reg(list,loc.size,loc.size,loc.sreg,tmpreg);
+ end;
+ LOC_CONSTANT:
+ begin
+ tmpreg:=getintregister(list,loc.size);
+ a_load_const_reg(list,loc.size,loc.value,tmpreg);
+ end;
+ end;
+ a_bit_test_reg_reg_reg(list,bitnumbersize,loc.size,destsize,bitnumber,tmpreg,destreg);
+ end;
+ { LOC_SUBSETREF is not possible, because sets are not (yet) bitpacked }
+ else
+ internalerror(2007051701);
+ end;
+ end;
+
+
+ procedure tcg.a_bit_test_const_loc_reg(list: TAsmList; destsize: tcgsize; bitnumber: tcgint; const loc: tlocation; destreg: tregister);
+ begin
+ case loc.loc of
+ LOC_REFERENCE,LOC_CREFERENCE:
+ a_bit_test_const_ref_reg(list,destsize,bitnumber,loc.reference,destreg);
+ LOC_REGISTER,LOC_CREGISTER:
+ a_bit_test_const_reg_reg(list,loc.size,destsize,bitnumber,loc.register,destreg);
+ LOC_SUBSETREG,LOC_CSUBSETREG:
+ a_bit_test_const_subsetreg_reg(list,loc.size,destsize,bitnumber,loc.sreg,destreg);
+ { LOC_SUBSETREF is not possible, because sets are not (yet) bitpacked }
+ else
+ internalerror(2007051702);
+ end;
+ end;
+
+ { bit setting/clearing routines }
+
+ procedure tcg.a_bit_set_reg_reg(list : TAsmList; doset: boolean; bitnumbersize, destsize: tcgsize; bitnumber,dest: tregister);
+ var
+ tmpvalue: tregister;
+ begin
+ tmpvalue:=getintregister(list,destsize);
+
+ if (target_info.endian=endian_little) then
+ begin
+ a_load_const_reg(list,destsize,1,tmpvalue);
+ { rotate bit "bitnumber" bits to the left }
+ a_op_reg_reg(list,OP_SHL,destsize,bitnumber,tmpvalue);
+ end
+ else
+ begin
+ { highest (leftmost) bit = bit 0 -> "$80/$8000/$80000000/ ... }
+ { shr bitnumber" results in correct mask }
+ a_load_const_reg(list,destsize,1 shl (tcgsize2size[destsize]*8-1),tmpvalue);
+ a_op_reg_reg(list,OP_SHR,destsize,bitnumber,tmpvalue);
+ end;
+ { set/clear the bit we want }
+ if (doset) then
+ a_op_reg_reg(list,OP_OR,destsize,tmpvalue,dest)
+ else
+ begin
+ a_op_reg_reg(list,OP_NOT,destsize,tmpvalue,tmpvalue);
+ a_op_reg_reg(list,OP_AND,destsize,tmpvalue,dest)
+ end;
+ end;
+
+
+ procedure tcg.a_bit_set_const_ref(list: TAsmList; doset: boolean;destsize: tcgsize; bitnumber: tcgint; const ref: treference);
+ begin
+ a_load_const_subsetref(list,OS_8,ord(doset),get_bit_const_ref_sref(bitnumber,ref));
+ end;
+
+
+ procedure tcg.a_bit_set_const_reg(list: TAsmList; doset: boolean; destsize: tcgsize; bitnumber: tcgint; destreg: tregister);
+ begin
+ a_load_const_subsetreg(list,OS_8,ord(doset),get_bit_const_reg_sreg(destsize,bitnumber,destreg));
+ end;
+
+
+ procedure tcg.a_bit_set_const_subsetreg(list: TAsmList; doset: boolean; destsize: tcgsize; bitnumber: tcgint; const destreg: tsubsetregister);
+ var
+ tmpsreg: tsubsetregister;
+ begin
+ { the first parameter is used to calculate the bit offset in }
+ { case of big endian, and therefore must be the size of the }
+ { set and not of the whole subsetreg }
+ tmpsreg:=get_bit_const_reg_sreg(destsize,bitnumber,destreg.subsetreg);
+ { now fix the size of the subsetreg }
+ tmpsreg.subsetregsize:=destreg.subsetregsize;
+ { correct offset of the set in the subsetreg }
+ inc(tmpsreg.startbit,destreg.startbit);
+ a_load_const_subsetreg(list,OS_8,ord(doset),tmpsreg);
+ end;
+
+
+ procedure tcg.a_bit_set_reg_ref(list: TAsmList; doset: boolean; bitnumbersize: tcgsize; bitnumber: tregister; const ref: treference);
+ begin
+ a_load_const_subsetref(list,OS_8,ord(doset),get_bit_reg_ref_sref(list,bitnumbersize,bitnumber,ref));
+ end;
+
+
+ procedure tcg.a_bit_set_reg_loc(list: TAsmList; doset: boolean; bitnumbersize: tcgsize; bitnumber: tregister; const loc: tlocation);
+ var
+ tmpreg: tregister;
+ begin
+ case loc.loc of
+ LOC_REFERENCE:
+ a_bit_set_reg_ref(list,doset,bitnumbersize,bitnumber,loc.reference);
+ LOC_CREGISTER:
+ a_bit_set_reg_reg(list,doset,bitnumbersize,loc.size,bitnumber,loc.register);
+ { e.g. a 2-byte set in a record regvar }
+ LOC_CSUBSETREG:
+ begin
+ { hard to do in-place in a generic way, so operate on a copy }
+ tmpreg:=getintregister(list,loc.size);
+ a_load_subsetreg_reg(list,loc.size,loc.size,loc.sreg,tmpreg);
+ a_bit_set_reg_reg(list,doset,bitnumbersize,loc.size,bitnumber,tmpreg);
+ a_load_reg_subsetreg(list,loc.size,loc.size,tmpreg,loc.sreg);
+ end;
+ { LOC_SUBSETREF is not possible, because sets are not (yet) bitpacked }
+ else
+ internalerror(2007051703)
+ end;
+ end;
+
+
+ procedure tcg.a_bit_set_const_loc(list: TAsmList; doset: boolean; bitnumber: tcgint; const loc: tlocation);
+ begin
+ case loc.loc of
+ LOC_REFERENCE:
+ a_bit_set_const_ref(list,doset,loc.size,bitnumber,loc.reference);
+ LOC_CREGISTER:
+ a_bit_set_const_reg(list,doset,loc.size,bitnumber,loc.register);
+ LOC_CSUBSETREG:
+ a_bit_set_const_subsetreg(list,doset,loc.size,bitnumber,loc.sreg);
+ { LOC_SUBSETREF is not possible, because sets are not (yet) bitpacked }
+ else
+ internalerror(2007051704)
+ end;
+ end;
+
+
+ { memory/register loading }
+
+ procedure tcg.a_load_reg_ref_unaligned(list : TAsmList;fromsize,tosize : tcgsize;register : tregister;const ref : treference);
+ var
+ tmpref : treference;
+ tmpreg : tregister;
+ i : longint;
+ begin
+ if ref.alignment<tcgsize2size[fromsize] then
+ begin
+ tmpref:=ref;
+ { we take care of the alignment now }
+ tmpref.alignment:=0;
+ case FromSize of
+ OS_16,OS_S16:
+ begin
+ tmpreg:=getintregister(list,OS_16);
+ a_load_reg_reg(list,fromsize,OS_16,register,tmpreg);
+ if target_info.endian=endian_big then
+ inc(tmpref.offset);
+ tmpreg:=makeregsize(list,tmpreg,OS_8);
+ a_load_reg_ref(list,OS_8,OS_8,tmpreg,tmpref);
+ tmpreg:=makeregsize(list,tmpreg,OS_16);
+ a_op_const_reg(list,OP_SHR,OS_16,8,tmpreg);
+ if target_info.endian=endian_big then
+ dec(tmpref.offset)
+ else
+ inc(tmpref.offset);
+ tmpreg:=makeregsize(list,tmpreg,OS_8);
+ a_load_reg_ref(list,OS_8,OS_8,tmpreg,tmpref);
+ end;
+ OS_32,OS_S32:
+ begin
+ { could add an optimised case for ref.alignment=2 }
+ tmpreg:=getintregister(list,OS_32);
+ a_load_reg_reg(list,fromsize,OS_32,register,tmpreg);
+ if target_info.endian=endian_big then
+ inc(tmpref.offset,3);
+ tmpreg:=makeregsize(list,tmpreg,OS_8);
+ a_load_reg_ref(list,OS_8,OS_8,tmpreg,tmpref);
+ tmpreg:=makeregsize(list,tmpreg,OS_32);
+ for i:=1 to 3 do
+ begin
+ a_op_const_reg(list,OP_SHR,OS_32,8,tmpreg);
+ if target_info.endian=endian_big then
+ dec(tmpref.offset)
+ else
+ inc(tmpref.offset);
+ tmpreg:=makeregsize(list,tmpreg,OS_8);
+ a_load_reg_ref(list,OS_8,OS_8,tmpreg,tmpref);
+ tmpreg:=makeregsize(list,tmpreg,OS_32);
+ end;
+ end
+ else
+ a_load_reg_ref(list,fromsize,tosize,register,tmpref);
+ end;
+ end
+ else
+ a_load_reg_ref(list,fromsize,tosize,register,ref);
+ end;
+
+
+ procedure tcg.a_load_ref_reg_unaligned(list : TAsmList;fromsize,tosize : tcgsize;const ref : treference;register : tregister);
+ var
+ tmpref : treference;
+ tmpreg,
+ tmpreg2 : tregister;
+ i : longint;
+ begin
+ if ref.alignment in [1,2] then
+ begin
+ tmpref:=ref;
+ { we take care of the alignment now }
+ tmpref.alignment:=0;
+ case FromSize of
+ OS_16,OS_S16:
+ if ref.alignment=2 then
+ a_load_ref_reg(list,fromsize,tosize,tmpref,register)
+ else
+ begin
+ { first load in tmpreg, because the target register }
+ { may be used in ref as well }
+ if target_info.endian=endian_little then
+ inc(tmpref.offset);
+ tmpreg:=getintregister(list,OS_8);
+ a_load_ref_reg(list,OS_8,OS_8,tmpref,tmpreg);
+ tmpreg:=makeregsize(list,tmpreg,OS_16);
+ a_op_const_reg(list,OP_SHL,OS_16,8,tmpreg);
+ if target_info.endian=endian_little then
+ dec(tmpref.offset)
+ else
+ inc(tmpref.offset);
+ a_load_ref_reg(list,OS_8,OS_16,tmpref,register);
+ a_op_reg_reg(list,OP_OR,OS_16,tmpreg,register);
+ end;
+ OS_32,OS_S32:
+ if ref.alignment=2 then
+ begin
+ if target_info.endian=endian_little then
+ inc(tmpref.offset,2);
+ tmpreg:=getintregister(list,OS_32);
+ a_load_ref_reg(list,OS_16,OS_32,tmpref,tmpreg);
+ a_op_const_reg(list,OP_SHL,OS_32,16,tmpreg);
+ if target_info.endian=endian_little then
+ dec(tmpref.offset,2)
+ else
+ inc(tmpref.offset,2);
+ a_load_ref_reg(list,OS_16,OS_32,tmpref,register);
+ a_op_reg_reg(list,OP_OR,OS_32,tmpreg,register);
+ end
+ else
+ begin
+ if target_info.endian=endian_little then
+ inc(tmpref.offset,3);
+ tmpreg:=getintregister(list,OS_32);
+ a_load_ref_reg(list,OS_8,OS_32,tmpref,tmpreg);
+ tmpreg2:=getintregister(list,OS_32);
+ for i:=1 to 3 do
+ begin
+ a_op_const_reg(list,OP_SHL,OS_32,8,tmpreg);
+ if target_info.endian=endian_little then
+ dec(tmpref.offset)
+ else
+ inc(tmpref.offset);
+ a_load_ref_reg(list,OS_8,OS_32,tmpref,tmpreg2);
+ a_op_reg_reg(list,OP_OR,OS_32,tmpreg2,tmpreg);
+ end;
+ a_load_reg_reg(list,OS_32,OS_32,tmpreg,register);
+ end
+ else
+ a_load_ref_reg(list,fromsize,tosize,tmpref,register);
+ end;
+ end
+ else
+ a_load_ref_reg(list,fromsize,tosize,ref,register);
+ end;
+
+
+ procedure tcg.a_load_ref_ref(list : TAsmList;fromsize,tosize : tcgsize;const sref : treference;const dref : treference);
+ var
+ tmpreg: tregister;
+ begin
+ { verify if we have the same reference }
+ if references_equal(sref,dref) then
+ exit;
+ tmpreg:=getintregister(list,tosize);
+ a_load_ref_reg(list,fromsize,tosize,sref,tmpreg);
+ a_load_reg_ref(list,tosize,tosize,tmpreg,dref);
+ end;
+
+
+ procedure tcg.a_load_const_ref(list : TAsmList;size : tcgsize;a : tcgint;const ref : treference);
+ var
+ tmpreg: tregister;
+ begin
+ tmpreg:=getintregister(list,size);
+ a_load_const_reg(list,size,a,tmpreg);
+ a_load_reg_ref(list,size,size,tmpreg,ref);
+ end;
+
+
+ procedure tcg.a_load_const_loc(list : TAsmList;a : tcgint;const loc: tlocation);
+ begin
+ case loc.loc of
+ LOC_REFERENCE,LOC_CREFERENCE:
+ a_load_const_ref(list,loc.size,a,loc.reference);
+ LOC_REGISTER,LOC_CREGISTER:
+ a_load_const_reg(list,loc.size,a,loc.register);
+ LOC_SUBSETREG,LOC_CSUBSETREG:
+ a_load_const_subsetreg(list,loc.size,a,loc.sreg);
+ LOC_SUBSETREF,LOC_CSUBSETREF:
+ a_load_const_subsetref(list,loc.size,a,loc.sref);
+ else
+ internalerror(200203272);
+ end;
+ end;
+
+
+ procedure tcg.a_load_reg_loc(list : TAsmList;fromsize : tcgsize;reg : tregister;const loc: tlocation);
+ begin
+ case loc.loc of
+ LOC_REFERENCE,LOC_CREFERENCE:
+ a_load_reg_ref(list,fromsize,loc.size,reg,loc.reference);
+ LOC_REGISTER,LOC_CREGISTER:
+ a_load_reg_reg(list,fromsize,loc.size,reg,loc.register);
+ LOC_SUBSETREG,LOC_CSUBSETREG:
+ a_load_reg_subsetreg(list,fromsize,loc.size,reg,loc.sreg);
+ LOC_SUBSETREF,LOC_CSUBSETREF:
+ a_load_reg_subsetref(list,fromsize,loc.size,reg,loc.sref);
+ LOC_MMREGISTER,LOC_CMMREGISTER:
+ a_loadmm_intreg_reg(list,fromsize,loc.size,reg,loc.register,mms_movescalar);
+ else
+ internalerror(200203271);
+ end;
+ end;
+
+
+ procedure tcg.a_load_loc_reg(list : TAsmList; tosize: tcgsize; const loc: tlocation; reg : tregister);
+ begin
+ case loc.loc of
+ LOC_REFERENCE,LOC_CREFERENCE:
+ a_load_ref_reg(list,loc.size,tosize,loc.reference,reg);
+ LOC_REGISTER,LOC_CREGISTER:
+ a_load_reg_reg(list,loc.size,tosize,loc.register,reg);
+ LOC_CONSTANT:
+ a_load_const_reg(list,tosize,loc.value,reg);
+ LOC_SUBSETREG,LOC_CSUBSETREG:
+ a_load_subsetreg_reg(list,loc.size,tosize,loc.sreg,reg);
+ LOC_SUBSETREF,LOC_CSUBSETREF:
+ a_load_subsetref_reg(list,loc.size,tosize,loc.sref,reg);
+ else
+ internalerror(200109092);
+ end;
+ end;
+
+
+ procedure tcg.a_load_loc_ref(list : TAsmList;tosize: tcgsize; const loc: tlocation; const ref : treference);
+ begin
+ case loc.loc of
+ LOC_REFERENCE,LOC_CREFERENCE:
+ a_load_ref_ref(list,loc.size,tosize,loc.reference,ref);
+ LOC_REGISTER,LOC_CREGISTER:
+ a_load_reg_ref(list,loc.size,tosize,loc.register,ref);
+ LOC_CONSTANT:
+ a_load_const_ref(list,tosize,loc.value,ref);
+ LOC_SUBSETREG,LOC_CSUBSETREG:
+ a_load_subsetreg_ref(list,loc.size,tosize,loc.sreg,ref);
+ LOC_SUBSETREF,LOC_CSUBSETREF:
+ a_load_subsetref_ref(list,loc.size,tosize,loc.sref,ref);
+ else
+ internalerror(200109302);
+ end;
+ end;
+
+
+ procedure tcg.a_load_loc_subsetreg(list : TAsmList; subsetsize: tcgsize; const loc: tlocation; const sreg : tsubsetregister);
+ begin
+ case loc.loc of
+ LOC_REFERENCE,LOC_CREFERENCE:
+ a_load_ref_subsetreg(list,loc.size,subsetsize,loc.reference,sreg);
+ LOC_REGISTER,LOC_CREGISTER:
+ a_load_reg_subsetreg(list,loc.size,subsetsize,loc.register,sreg);
+ LOC_CONSTANT:
+ a_load_const_subsetreg(list,subsetsize,loc.value,sreg);
+ LOC_SUBSETREG,LOC_CSUBSETREG:
+ a_load_subsetreg_subsetreg(list,loc.size,subsetsize,loc.sreg,sreg);
+ LOC_SUBSETREF,LOC_CSUBSETREF:
+ a_load_subsetref_subsetreg(list,loc.size,subsetsize,loc.sref,sreg);
+ else
+ internalerror(2006052310);
+ end;
+ end;
+
+
+ procedure tcg.a_load_subsetreg_loc(list: TAsmlist; subsetsize: tcgsize; const sreg: tsubsetregister; const loc: tlocation);
+ begin
+ case loc.loc of
+ LOC_REFERENCE,LOC_CREFERENCE:
+ a_load_subsetreg_ref(list,subsetsize,loc.size,sreg,loc.reference);
+ LOC_REGISTER,LOC_CREGISTER:
+ a_load_subsetreg_reg(list,subsetsize,loc.size,sreg,loc.register);
+ LOC_SUBSETREG,LOC_CSUBSETREG:
+ a_load_subsetreg_subsetreg(list,subsetsize,loc.size,sreg,loc.sreg);
+ LOC_SUBSETREF,LOC_CSUBSETREF:
+ a_load_subsetreg_subsetref(list,subsetsize,loc.size,sreg,loc.sref);
+ else
+ internalerror(2006051510);
+ end;
+ end;
+
+
+ procedure tcg.optimize_op_const(var op: topcg; var a : tcgint);
+ var
+ powerval : longint;
+ begin
+ case op of
+ OP_OR :
+ begin
+ { or with zero returns same result }
+ if a = 0 then
+ op:=OP_NONE
+ else
+ { or with max returns max }
+ if a = -1 then
+ op:=OP_MOVE;
+ end;
+ OP_AND :
+ begin
+ { and with max returns same result }
+ if (a = -1) then
+ op:=OP_NONE
+ else
+ { and with 0 returns 0 }
+ if a=0 then
+ op:=OP_MOVE;
+ end;
+ OP_DIV :
+ begin
+ { division by 1 returns result }
+ if a = 1 then
+ op:=OP_NONE
+ else if ispowerof2(int64(a), powerval) and not(cs_check_overflow in current_settings.localswitches) then
+ begin
+ a := powerval;
+ op:= OP_SHR;
+ end;
+ end;
+ OP_IDIV:
+ begin
+ if a = 1 then
+ op:=OP_NONE;
+ end;
+ OP_MUL,OP_IMUL:
+ begin
+ if a = 1 then
+ op:=OP_NONE
+ else
+ if a=0 then
+ op:=OP_MOVE
+ else if ispowerof2(int64(a), powerval) and not(cs_check_overflow in current_settings.localswitches) then
+ begin
+ a := powerval;
+ op:= OP_SHL;
+ end;
+ end;
+ OP_ADD,OP_SUB:
+ begin
+ if a = 0 then
+ op:=OP_NONE;
+ end;
+ OP_SAR,OP_SHL,OP_SHR,OP_ROL,OP_ROR:
+ begin
+ if a = 0 then
+ op:=OP_NONE;
+ end;
+ end;
+ end;
+
+
+ procedure tcg.a_loadfpu_loc_reg(list: TAsmList; tosize: tcgsize; const loc: tlocation; const reg: tregister);
+ begin
+ case loc.loc of
+ LOC_REFERENCE, LOC_CREFERENCE:
+ a_loadfpu_ref_reg(list,loc.size,tosize,loc.reference,reg);
+ LOC_FPUREGISTER, LOC_CFPUREGISTER:
+ a_loadfpu_reg_reg(list,loc.size,tosize,loc.register,reg);
+ else
+ internalerror(200203301);
+ end;
+ end;
+
+
+ procedure tcg.a_loadfpu_reg_loc(list: TAsmList; fromsize: tcgsize; const reg: tregister; const loc: tlocation);
+ begin
+ case loc.loc of
+ LOC_REFERENCE, LOC_CREFERENCE:
+ a_loadfpu_reg_ref(list,fromsize,loc.size,reg,loc.reference);
+ LOC_FPUREGISTER, LOC_CFPUREGISTER:
+ a_loadfpu_reg_reg(list,fromsize,loc.size,reg,loc.register);
+ else
+ internalerror(48991);
+ end;
+ end;
+
+
+ procedure tcg.a_loadfpu_ref_ref(list: TAsmList; fromsize, tosize: tcgsize; const ref1,ref2: treference);
+ var
+ reg: tregister;
+ regsize: tcgsize;
+ begin
+ if (fromsize>=tosize) then
+ regsize:=fromsize
+ else
+ regsize:=tosize;
+ reg:=getfpuregister(list,regsize);
+ a_loadfpu_ref_reg(list,fromsize,regsize,ref1,reg);
+ a_loadfpu_reg_ref(list,regsize,tosize,reg,ref2);
+ end;
+
+
+ procedure tcg.a_loadfpu_reg_cgpara(list : TAsmList;size : tcgsize;const r : tregister;const cgpara : TCGPara);
+ var
+ ref : treference;
+ begin
+ paramanager.alloccgpara(list,cgpara);
+ case cgpara.location^.loc of
+ LOC_FPUREGISTER,LOC_CFPUREGISTER:
+ begin
+ cgpara.check_simple_location;
+ a_loadfpu_reg_reg(list,size,size,r,cgpara.location^.register);
+ end;
+ LOC_REFERENCE,LOC_CREFERENCE:
+ begin
+ cgpara.check_simple_location;
+ reference_reset_base(ref,cgpara.location^.reference.index,cgpara.location^.reference.offset,cgpara.alignment);
+ a_loadfpu_reg_ref(list,size,size,r,ref);
+ end;
+ LOC_REGISTER,LOC_CREGISTER:
+ begin
+ { paramfpu_ref does the check_simpe_location check here if necessary }
+ tg.GetTemp(list,TCGSize2Size[size],TCGSize2Size[size],tt_normal,ref);
+ a_loadfpu_reg_ref(list,size,size,r,ref);
+ a_loadfpu_ref_cgpara(list,size,ref,cgpara);
+ tg.Ungettemp(list,ref);
+ end;
+ else
+ internalerror(2010053112);
+ end;
+ end;
+
+
+ procedure tcg.a_loadfpu_ref_cgpara(list : TAsmList;size : tcgsize;const ref : treference;const cgpara : TCGPara);
+ var
+ href : treference;
+ hsize: tcgsize;
+ begin
+ case cgpara.location^.loc of
+ LOC_FPUREGISTER,LOC_CFPUREGISTER:
+ begin
+ cgpara.check_simple_location;
+ paramanager.alloccgpara(list,cgpara);
+ a_loadfpu_ref_reg(list,size,size,ref,cgpara.location^.register);
+ end;
+ LOC_REFERENCE,LOC_CREFERENCE:
+ begin
+ cgpara.check_simple_location;
+ reference_reset_base(href,cgpara.location^.reference.index,cgpara.location^.reference.offset,cgpara.alignment);
+ { concatcopy should choose the best way to copy the data }
+ g_concatcopy(list,ref,href,tcgsize2size[size]);
+ end;
+ LOC_REGISTER,LOC_CREGISTER:
+ begin
+ { force integer size }
+ hsize:=int_cgsize(tcgsize2size[size]);
+{$ifndef cpu64bitalu}
+ if (hsize in [OS_S64,OS_64]) then
+ cg64.a_load64_ref_cgpara(list,ref,cgpara)
+ else
+{$endif not cpu64bitalu}
+ begin
+ cgpara.check_simple_location;
+ a_load_ref_cgpara(list,hsize,ref,cgpara)
+ end;
+ end
+ else
+ internalerror(200402201);
+ end;
+ end;
+
+
+ procedure tcg.a_op_const_ref(list : TAsmList; Op: TOpCG; size: TCGSize; a: tcgint; const ref: TReference);
+ var
+ tmpreg : tregister;
+ begin
+ tmpreg:=getintregister(list,size);
+ a_load_ref_reg(list,size,size,ref,tmpreg);
+ a_op_const_reg(list,op,size,a,tmpreg);
+ a_load_reg_ref(list,size,size,tmpreg,ref);
+ end;
+
+
+ procedure tcg.a_op_const_subsetreg(list : TAsmList; Op : TOpCG; size, subsetsize : TCGSize; a : tcgint; const sreg: tsubsetregister);
+ var
+ tmpreg: tregister;
+ begin
+ tmpreg := getintregister(list, size);
+ a_load_subsetreg_reg(list,subsetsize,size,sreg,tmpreg);
+ a_op_const_reg(list,op,size,a,tmpreg);
+ a_load_reg_subsetreg(list,size,subsetsize,tmpreg,sreg);
+ end;
+
+
+ procedure tcg.a_op_const_subsetref(list : TAsmList; Op : TOpCG; size, subsetsize : TCGSize; a : tcgint; const sref: tsubsetreference);
+ var
+ tmpreg: tregister;
+ begin
+ tmpreg := getintregister(list, size);
+ a_load_subsetref_reg(list,subsetsize,size,sref,tmpreg);
+ a_op_const_reg(list,op,size,a,tmpreg);
+ a_load_reg_subsetref(list,size,subsetsize,tmpreg,sref);
+ end;
+
+
+ procedure tcg.a_op_const_loc(list : TAsmList; Op: TOpCG; a: tcgint; const loc: tlocation);
+ begin
+ case loc.loc of
+ LOC_REGISTER, LOC_CREGISTER:
+ a_op_const_reg(list,op,loc.size,a,loc.register);
+ LOC_REFERENCE, LOC_CREFERENCE:
+ a_op_const_ref(list,op,loc.size,a,loc.reference);
+ LOC_SUBSETREG, LOC_CSUBSETREG:
+ a_op_const_subsetreg(list,op,loc.size,loc.size,a,loc.sreg);
+ LOC_SUBSETREF, LOC_CSUBSETREF:
+ a_op_const_subsetref(list,op,loc.size,loc.size,a,loc.sref);
+ else
+ internalerror(200109061);
+ end;
+ end;
+
+
+ procedure tcg.a_op_reg_ref(list : TAsmList; Op: TOpCG; size: TCGSize;reg: TRegister; const ref: TReference);
+ var
+ tmpreg : tregister;
+ begin
+ tmpreg:=getintregister(list,size);
+ a_load_ref_reg(list,size,size,ref,tmpreg);
+ a_op_reg_reg(list,op,size,reg,tmpreg);
+ a_load_reg_ref(list,size,size,tmpreg,ref);
+ end;
+
+
+ procedure tcg.a_op_ref_reg(list : TAsmList; Op: TOpCG; size: TCGSize; const ref: TReference; reg: TRegister);
+
+ var
+ tmpreg: tregister;
+
+ begin
+ case op of
+ OP_NOT,OP_NEG:
+ { handle it as "load ref,reg; op reg" }
+ begin
+ a_load_ref_reg(list,size,size,ref,reg);
+ a_op_reg_reg(list,op,size,reg,reg);
+ end;
+ else
+ begin
+ tmpreg:=getintregister(list,size);
+ a_load_ref_reg(list,size,size,ref,tmpreg);
+ a_op_reg_reg(list,op,size,tmpreg,reg);
+ end;
+ end;
+ end;
+
+
+ procedure tcg.a_op_reg_subsetreg(list : TAsmList; Op : TOpCG; opsize, subsetsize : TCGSize; reg: TRegister; const sreg: tsubsetregister);
+ var
+ tmpreg: tregister;
+ begin
+ tmpreg := getintregister(list, opsize);
+ a_load_subsetreg_reg(list,subsetsize,opsize,sreg,tmpreg);
+ a_op_reg_reg(list,op,opsize,reg,tmpreg);
+ a_load_reg_subsetreg(list,opsize,subsetsize,tmpreg,sreg);
+ end;
+
+
+ procedure tcg.a_op_reg_subsetref(list : TAsmList; Op : TOpCG; opsize, subsetsize : TCGSize; reg: TRegister; const sref: tsubsetreference);
+ var
+ tmpreg: tregister;
+ begin
+ tmpreg := getintregister(list, opsize);
+ a_load_subsetref_reg(list,subsetsize,opsize,sref,tmpreg);
+ a_op_reg_reg(list,op,opsize,reg,tmpreg);
+ a_load_reg_subsetref(list,opsize,subsetsize,tmpreg,sref);
+ end;
+
+
+ procedure tcg.a_op_reg_loc(list : TAsmList; Op: TOpCG; reg: tregister; const loc: tlocation);
+
+ begin
+ case loc.loc of
+ LOC_REGISTER, LOC_CREGISTER:
+ a_op_reg_reg(list,op,loc.size,reg,loc.register);
+ LOC_REFERENCE, LOC_CREFERENCE:
+ a_op_reg_ref(list,op,loc.size,reg,loc.reference);
+ LOC_SUBSETREG, LOC_CSUBSETREG:
+ a_op_reg_subsetreg(list,op,loc.size,loc.size,reg,loc.sreg);
+ LOC_SUBSETREF, LOC_CSUBSETREF:
+ a_op_reg_subsetref(list,op,loc.size,loc.size,reg,loc.sref);
+ else
+ internalerror(200109061);
+ end;
+ end;
+
+
+ procedure tcg.a_op_ref_loc(list : TAsmList; Op: TOpCG; const ref: TReference; const loc: tlocation);
+
+ var
+ tmpreg: tregister;
+
+ begin
+ case loc.loc of
+ LOC_REGISTER,LOC_CREGISTER:
+ a_op_ref_reg(list,op,loc.size,ref,loc.register);
+ LOC_REFERENCE,LOC_CREFERENCE:
+ begin
+ tmpreg:=getintregister(list,loc.size);
+ a_load_ref_reg(list,loc.size,loc.size,ref,tmpreg);
+ a_op_reg_ref(list,op,loc.size,tmpreg,loc.reference);
+ end;
+ LOC_SUBSETREG, LOC_CSUBSETREG:
+ begin
+ tmpreg:=getintregister(list,loc.size);
+ a_load_subsetreg_reg(list,loc.size,loc.size,loc.sreg,tmpreg);
+ a_op_ref_reg(list,op,loc.size,ref,tmpreg);
+ a_load_reg_subsetreg(list,loc.size,loc.size,tmpreg,loc.sreg);
+ end;
+ LOC_SUBSETREF, LOC_CSUBSETREF:
+ begin
+ tmpreg:=getintregister(list,loc.size);
+ a_load_subsetreF_reg(list,loc.size,loc.size,loc.sref,tmpreg);
+ a_op_ref_reg(list,op,loc.size,ref,tmpreg);
+ a_load_reg_subsetref(list,loc.size,loc.size,tmpreg,loc.sref);
+ end;
+ else
+ internalerror(200109061);
+ end;
+ end;
+
+
+ procedure Tcg.a_op_const_reg_reg(list:TAsmList;op:Topcg;size:Tcgsize;
+ a:tcgint;src,dst:Tregister);
+
+ begin
+ a_load_reg_reg(list,size,size,src,dst);
+ a_op_const_reg(list,op,size,a,dst);
+ end;
+
+ procedure tcg.a_op_reg_reg_reg(list: TAsmList; op: TOpCg;
+ size: tcgsize; src1, src2, dst: tregister);
+ var
+ tmpreg: tregister;
+ begin
+ if (dst<>src1) then
+ begin
+ a_load_reg_reg(list,size,size,src2,dst);
+ a_op_reg_reg(list,op,size,src1,dst);
+ end
+ else
+ begin
+ { can we do a direct operation on the target register ? }
+ if op in [OP_ADD,OP_MUL,OP_AND,OP_MOVE,OP_XOR,OP_IMUL,OP_OR] then
+ a_op_reg_reg(list,op,size,src2,dst)
+ else
+ begin
+ tmpreg:=getintregister(list,size);
+ a_load_reg_reg(list,size,size,src2,tmpreg);
+ a_op_reg_reg(list,op,size,src1,tmpreg);
+ a_load_reg_reg(list,size,size,tmpreg,dst);
+ end;
+ end;
+ end;
+
+
+ procedure tcg.a_op_const_reg_reg_checkoverflow(list: TAsmList; op: TOpCg; size: tcgsize; a: tcgint; src, dst: tregister;setflags : boolean;var ovloc : tlocation);
+ begin
+ a_op_const_reg_reg(list,op,size,a,src,dst);
+ ovloc.loc:=LOC_VOID;
+ end;
+
+
+ procedure tcg.a_op_reg_reg_reg_checkoverflow(list: TAsmList; op: TOpCg; size: tcgsize; src1, src2, dst: tregister;setflags : boolean;var ovloc : tlocation);
+ begin
+ a_op_reg_reg_reg(list,op,size,src1,src2,dst);
+ ovloc.loc:=LOC_VOID;
+ end;
+
+
+ procedure tcg.a_cmp_const_reg_label(list: TAsmList; size: tcgsize;
+ cmp_op: topcmp; a: tcgint; reg: tregister; l: tasmlabel);
+ var
+ tmpreg: tregister;
+ begin
+ tmpreg:=getintregister(list,size);
+ a_load_const_reg(list,size,a,tmpreg);
+ a_cmp_reg_reg_label(list,size,cmp_op,tmpreg,reg,l);
+ end;
+
+
+ procedure tcg.a_cmp_const_ref_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;a : tcgint;const ref : treference;
+ l : tasmlabel);
+ var
+ tmpreg: tregister;
+ begin
+ tmpreg:=getintregister(list,size);
+ a_load_ref_reg(list,size,size,ref,tmpreg);
+ a_cmp_const_reg_label(list,size,cmp_op,a,tmpreg,l);
+ end;
+
+
+ procedure tcg.a_cmp_const_loc_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;a : tcgint;const loc : tlocation;
+ l : tasmlabel);
+ var
+ tmpreg : tregister;
+ begin
+ case loc.loc of
+ LOC_REGISTER,LOC_CREGISTER:
+ a_cmp_const_reg_label(list,size,cmp_op,a,loc.register,l);
+ LOC_REFERENCE,LOC_CREFERENCE:
+ a_cmp_const_ref_label(list,size,cmp_op,a,loc.reference,l);
+ LOC_SUBSETREG, LOC_CSUBSETREG:
+ begin
+ tmpreg:=getintregister(list,size);
+ a_load_subsetreg_reg(list,loc.size,size,loc.sreg,tmpreg);
+ a_cmp_const_reg_label(list,size,cmp_op,a,tmpreg,l);
+ end;
+ LOC_SUBSETREF, LOC_CSUBSETREF:
+ begin
+ tmpreg:=getintregister(list,size);
+ a_load_subsetref_reg(list,loc.size,size,loc.sref,tmpreg);
+ a_cmp_const_reg_label(list,size,cmp_op,a,tmpreg,l);
+ end;
+ else
+ internalerror(200109061);
+ end;
+ end;
+
+
+ procedure tcg.a_cmp_ref_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp; const ref: treference; reg : tregister; l : tasmlabel);
+ var
+ tmpreg: tregister;
+ begin
+ tmpreg:=getintregister(list,size);
+ a_load_ref_reg(list,size,size,ref,tmpreg);
+ a_cmp_reg_reg_label(list,size,cmp_op,tmpreg,reg,l);
+ end;
+
+
+ procedure tcg.a_cmp_reg_ref_label(list : TAsmList;size : tcgsize;cmp_op : topcmp; reg : tregister; const ref: treference; l : tasmlabel);
+ var
+ tmpreg: tregister;
+ begin
+ tmpreg:=getintregister(list,size);
+ a_load_ref_reg(list,size,size,ref,tmpreg);
+ a_cmp_reg_reg_label(list,size,cmp_op,reg,tmpreg,l);
+ end;
+
+
+ procedure tcg.a_cmp_reg_loc_label(list : TAsmList;size : tcgsize;cmp_op : topcmp; reg: tregister; const loc: tlocation; l : tasmlabel);
+ begin
+ a_cmp_loc_reg_label(list,size,swap_opcmp(cmp_op),loc,reg,l);
+ end;
+
+
+ procedure tcg.a_cmp_loc_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp; const loc: tlocation; reg : tregister; l : tasmlabel);
+ begin
+ case loc.loc of
+ LOC_REGISTER,
+ LOC_CREGISTER:
+ a_cmp_reg_reg_label(list,size,cmp_op,loc.register,reg,l);
+ LOC_REFERENCE,
+ LOC_CREFERENCE :
+ a_cmp_ref_reg_label(list,size,cmp_op,loc.reference,reg,l);
+ LOC_CONSTANT:
+ a_cmp_const_reg_label(list,size,cmp_op,loc.value,reg,l);
+ LOC_SUBSETREG,
+ LOC_CSUBSETREG:
+ a_cmp_subsetreg_reg_label(list,loc.size,size,cmp_op,loc.sreg,reg,l);
+ LOC_SUBSETREF,
+ LOC_CSUBSETREF:
+ a_cmp_subsetref_reg_label(list,loc.size,size,cmp_op,loc.sref,reg,l);
+ else
+ internalerror(200203231);
+ end;
+ end;
+
+
+ procedure tcg.a_cmp_subsetreg_reg_label(list : TAsmList; subsetsize : tcgsize; cmpsize : tcgsize; cmp_op : topcmp; const sreg: tsubsetregister; reg : tregister; l : tasmlabel);
+ var
+ tmpreg: tregister;
+ begin
+ tmpreg:=getintregister(list, cmpsize);
+ a_load_subsetreg_reg(list,subsetsize,cmpsize,sreg,tmpreg);
+ a_cmp_reg_reg_label(list,cmpsize,cmp_op,tmpreg,reg,l);
+ end;
+
+
+ procedure tcg.a_cmp_subsetref_reg_label(list : TAsmList; subsetsize, cmpsize : tcgsize; cmp_op : topcmp; const sref: tsubsetreference; reg : tregister; l : tasmlabel);
+ var
+ tmpreg: tregister;
+ begin
+ tmpreg:=getintregister(list, cmpsize);
+ a_load_subsetref_reg(list,subsetsize,cmpsize,sref,tmpreg);
+ a_cmp_reg_reg_label(list,cmpsize,cmp_op,tmpreg,reg,l);
+ end;
+
+
+ procedure tcg.a_cmp_ref_loc_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;const ref: treference;const loc : tlocation;
+ l : tasmlabel);
+ var
+ tmpreg: tregister;
+ begin
+ case loc.loc of
+ LOC_REGISTER,LOC_CREGISTER:
+ a_cmp_ref_reg_label(list,size,cmp_op,ref,loc.register,l);
+ LOC_REFERENCE,LOC_CREFERENCE:
+ begin
+ tmpreg:=getintregister(list,size);
+ a_load_ref_reg(list,size,size,loc.reference,tmpreg);
+ a_cmp_ref_reg_label(list,size,cmp_op,ref,tmpreg,l);
+ end;
+ LOC_SUBSETREG, LOC_CSUBSETREG:
+ begin
+ tmpreg:=getintregister(list, size);
+ a_load_ref_reg(list,size,size,loc.reference,tmpreg);
+ a_cmp_subsetreg_reg_label(list,loc.size,size,swap_opcmp(cmp_op),loc.sreg,tmpreg,l);
+ end;
+ LOC_SUBSETREF, LOC_CSUBSETREF:
+ begin
+ tmpreg:=getintregister(list, size);
+ a_load_ref_reg(list,size,size,loc.reference,tmpreg);
+ a_cmp_subsetref_reg_label(list,loc.size,size,swap_opcmp(cmp_op),loc.sref,tmpreg,l);
+ end;
+ else
+ internalerror(200109061);
+ end;
+ end;
+
+
+ procedure tcg.a_loadmm_loc_reg(list: TAsmList; size: tcgsize; const loc: tlocation; const reg: tregister;shuffle : pmmshuffle);
+ begin
+ case loc.loc of
+ LOC_MMREGISTER,LOC_CMMREGISTER:
+ a_loadmm_reg_reg(list,loc.size,size,loc.register,reg,shuffle);
+ LOC_REFERENCE,LOC_CREFERENCE:
+ a_loadmm_ref_reg(list,loc.size,size,loc.reference,reg,shuffle);
+ LOC_REGISTER,LOC_CREGISTER:
+ a_loadmm_intreg_reg(list,loc.size,size,loc.register,reg,shuffle);
+ else
+ internalerror(200310121);
+ end;
+ end;
+
+
+ procedure tcg.a_loadmm_reg_loc(list: TAsmList; size: tcgsize; const reg: tregister; const loc: tlocation;shuffle : pmmshuffle);
+ begin
+ case loc.loc of
+ LOC_MMREGISTER,LOC_CMMREGISTER:
+ a_loadmm_reg_reg(list,size,loc.size,reg,loc.register,shuffle);
+ LOC_REFERENCE,LOC_CREFERENCE:
+ a_loadmm_reg_ref(list,size,loc.size,reg,loc.reference,shuffle);
+ else
+ internalerror(200310122);
+ end;
+ end;
+
+
+ procedure tcg.a_loadmm_reg_cgpara(list: TAsmList; size: tcgsize; reg: tregister;const cgpara : TCGPara;shuffle : pmmshuffle);
+ var
+ href : treference;
+{$ifndef cpu64bitalu}
+ tmpreg : tregister;
+ reg64 : tregister64;
+{$endif not cpu64bitalu}
+ begin
+{$ifndef cpu64bitalu}
+ if not(cgpara.location^.loc in [LOC_REGISTER,LOC_CREGISTER]) or
+ (size<>OS_F64) then
+{$endif not cpu64bitalu}
+ cgpara.check_simple_location;
+ paramanager.alloccgpara(list,cgpara);
+ case cgpara.location^.loc of
+ LOC_MMREGISTER,LOC_CMMREGISTER:
+ a_loadmm_reg_reg(list,size,cgpara.location^.size,reg,cgpara.location^.register,shuffle);
+ LOC_REFERENCE,LOC_CREFERENCE:
+ begin
+ reference_reset_base(href,cgpara.location^.reference.index,cgpara.location^.reference.offset,cgpara.alignment);
+ a_loadmm_reg_ref(list,size,cgpara.location^.size,reg,href,shuffle);
+ end;
+ LOC_REGISTER,LOC_CREGISTER:
+ begin
+ if assigned(shuffle) and
+ not shufflescalar(shuffle) then
+ internalerror(2009112510);
+{$ifndef cpu64bitalu}
+ if (size=OS_F64) then
+ begin
+ if not assigned(cgpara.location^.next) or
+ assigned(cgpara.location^.next^.next) then
+ internalerror(2009112512);
+ case cgpara.location^.next^.loc of
+ LOC_REGISTER,LOC_CREGISTER:
+ tmpreg:=cgpara.location^.next^.register;
+ LOC_REFERENCE,LOC_CREFERENCE:
+ tmpreg:=getintregister(list,OS_32);
+ else
+ internalerror(2009112910);
+ end;
+ if (target_info.endian=ENDIAN_BIG) then
+ begin
+ { paraloc^ -> high
+ paraloc^.next -> low }
+ reg64.reghi:=cgpara.location^.register;
+ reg64.reglo:=tmpreg;
+ end
+ else
+ begin
+ { paraloc^ -> low
+ paraloc^.next -> high }
+ reg64.reglo:=cgpara.location^.register;
+ reg64.reghi:=tmpreg;
+ end;
+ cg64.a_loadmm_reg_intreg64(list,size,reg,reg64);
+ if (cgpara.location^.next^.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
+ begin
+ if not(cgpara.location^.next^.size in [OS_32,OS_S32]) then
+ internalerror(2009112911);
+ reference_reset_base(href,cgpara.location^.next^.reference.index,cgpara.location^.next^.reference.offset,cgpara.alignment);
+ a_load_reg_ref(list,OS_32,cgpara.location^.next^.size,tmpreg,href);
+ end;
+ end
+ else
+{$endif not cpu64bitalu}
+ a_loadmm_reg_intreg(list,size,cgpara.location^.size,reg,cgpara.location^.register,mms_movescalar);
+ end
+ else
+ internalerror(200310123);
+ end;
+ end;
+
+
+ procedure tcg.a_loadmm_ref_cgpara(list: TAsmList; size: tcgsize;const ref: treference;const cgpara : TCGPara;shuffle : pmmshuffle);
+ var
+ hr : tregister;
+ hs : tmmshuffle;
+ begin
+ cgpara.check_simple_location;
+ hr:=getmmregister(list,cgpara.location^.size);
+ a_loadmm_ref_reg(list,size,cgpara.location^.size,ref,hr,shuffle);
+ if realshuffle(shuffle) then
+ begin
+ hs:=shuffle^;
+ removeshuffles(hs);
+ a_loadmm_reg_cgpara(list,cgpara.location^.size,hr,cgpara,@hs);
+ end
+ else
+ a_loadmm_reg_cgpara(list,cgpara.location^.size,hr,cgpara,shuffle);
+ end;
+
+
+ procedure tcg.a_loadmm_loc_cgpara(list: TAsmList;const loc: tlocation; const cgpara : TCGPara;shuffle : pmmshuffle);
+ begin
+ case loc.loc of
+ LOC_MMREGISTER,LOC_CMMREGISTER:
+ a_loadmm_reg_cgpara(list,loc.size,loc.register,cgpara,shuffle);
+ LOC_REFERENCE,LOC_CREFERENCE:
+ a_loadmm_ref_cgpara(list,loc.size,loc.reference,cgpara,shuffle);
+ else
+ internalerror(200310123);
+ end;
+ end;
+
+
+ procedure tcg.a_opmm_ref_reg(list: TAsmList; Op: TOpCG; size : tcgsize;const ref: treference; reg: tregister;shuffle : pmmshuffle);
+ var
+ hr : tregister;
+ hs : tmmshuffle;
+ begin
+ hr:=getmmregister(list,size);
+ a_loadmm_ref_reg(list,size,size,ref,hr,shuffle);
+ if realshuffle(shuffle) then
+ begin
+ hs:=shuffle^;
+ removeshuffles(hs);
+ a_opmm_reg_reg(list,op,size,hr,reg,@hs);
+ end
+ else
+ a_opmm_reg_reg(list,op,size,hr,reg,shuffle);
+ end;
+
+
+ procedure tcg.a_opmm_reg_ref(list: TAsmList; Op: TOpCG; size : tcgsize;reg: tregister; const ref: treference; shuffle : pmmshuffle);
+ var
+ hr : tregister;
+ hs : tmmshuffle;
+ begin
+ hr:=getmmregister(list,size);
+ a_loadmm_ref_reg(list,size,size,ref,hr,shuffle);
+ if realshuffle(shuffle) then
+ begin
+ hs:=shuffle^;
+ removeshuffles(hs);
+ a_opmm_reg_reg(list,op,size,reg,hr,@hs);
+ a_loadmm_reg_ref(list,size,size,hr,ref,@hs);
+ end
+ else
+ begin
+ a_opmm_reg_reg(list,op,size,reg,hr,shuffle);
+ a_loadmm_reg_ref(list,size,size,hr,ref,shuffle);
+ end;
+ end;
+
+
+ procedure tcg.a_loadmm_intreg_reg(list: tasmlist; fromsize,tosize: tcgsize; intreg,mmreg: tregister; shuffle: pmmshuffle);
+ var
+ tmpref: treference;
+ begin
+ if (tcgsize2size[fromsize]<>4) or
+ (tcgsize2size[tosize]<>4) then
+ internalerror(2009112503);
+ tg.gettemp(list,4,4,tt_normal,tmpref);
+ a_load_reg_ref(list,fromsize,fromsize,intreg,tmpref);
+ a_loadmm_ref_reg(list,tosize,tosize,tmpref,mmreg,shuffle);
+ tg.ungettemp(list,tmpref);
+ end;
+
+
+ procedure tcg.a_loadmm_reg_intreg(list: tasmlist; fromsize,tosize: tcgsize; mmreg,intreg: tregister; shuffle: pmmshuffle);
+ var
+ tmpref: treference;
+ begin
+ if (tcgsize2size[fromsize]<>4) or
+ (tcgsize2size[tosize]<>4) then
+ internalerror(2009112504);
+ tg.gettemp(list,8,8,tt_normal,tmpref);
+ cg.a_loadmm_reg_ref(list,fromsize,fromsize,mmreg,tmpref,shuffle);
+ a_load_ref_reg(list,tosize,tosize,tmpref,intreg);
+ tg.ungettemp(list,tmpref);
+ end;
+
+
+ procedure tcg.a_opmm_loc_reg(list: TAsmList; Op: TOpCG; size : tcgsize;const loc: tlocation; reg: tregister;shuffle : pmmshuffle);
+ begin
+ case loc.loc of
+ LOC_CMMREGISTER,LOC_MMREGISTER:
+ a_opmm_reg_reg(list,op,size,loc.register,reg,shuffle);
+ LOC_CREFERENCE,LOC_REFERENCE:
+ a_opmm_ref_reg(list,op,size,loc.reference,reg,shuffle);
+ else
+ internalerror(200312232);
+ end;
+ end;
+
+
+ procedure tcg.g_concatcopy_unaligned(list : TAsmList;const source,dest : treference;len : tcgint);
+ begin
+ g_concatcopy(list,source,dest,len);
+ end;
+
+
+ procedure tcg.g_copyshortstring(list : TAsmList;const source,dest : treference;len:byte);
+ var
+ cgpara1,cgpara2,cgpara3 : TCGPara;
+ begin
+ cgpara1.init;
+ cgpara2.init;
+ cgpara3.init;
+ paramanager.getintparaloc(pocall_default,1,cgpara1);
+ paramanager.getintparaloc(pocall_default,2,cgpara2);
+ paramanager.getintparaloc(pocall_default,3,cgpara3);
+ a_loadaddr_ref_cgpara(list,dest,cgpara3);
+ a_loadaddr_ref_cgpara(list,source,cgpara2);
+ a_load_const_cgpara(list,OS_INT,len,cgpara1);
+ paramanager.freecgpara(list,cgpara3);
+ paramanager.freecgpara(list,cgpara2);
+ paramanager.freecgpara(list,cgpara1);
+ allocallcpuregisters(list);
+ a_call_name(list,'FPC_SHORTSTR_ASSIGN',false);
+ deallocallcpuregisters(list);
+ cgpara3.done;
+ cgpara2.done;
+ cgpara1.done;
+ end;
+
+
+ procedure tcg.g_copyvariant(list : TAsmList;const source,dest : treference);
+ var
+ cgpara1,cgpara2 : TCGPara;
+ begin
+ cgpara1.init;
+ cgpara2.init;
+ paramanager.getintparaloc(pocall_default,1,cgpara1);
+ paramanager.getintparaloc(pocall_default,2,cgpara2);
+ a_loadaddr_ref_cgpara(list,dest,cgpara2);
+ a_loadaddr_ref_cgpara(list,source,cgpara1);
+ paramanager.freecgpara(list,cgpara2);
+ paramanager.freecgpara(list,cgpara1);
+ allocallcpuregisters(list);
+ a_call_name(list,'FPC_VARIANT_COPY_OVERWRITE',false);
+ deallocallcpuregisters(list);
+ cgpara2.done;
+ cgpara1.done;
+ end;
+
+
+ procedure tcg.g_incrrefcount(list : TAsmList;t: tdef; const ref: treference);
+ var
+ href : treference;
+ incrfunc : string;
+ cgpara1,cgpara2 : TCGPara;
+ begin
+ cgpara1.init;
+ cgpara2.init;
+ paramanager.getintparaloc(pocall_default,1,cgpara1);
+ paramanager.getintparaloc(pocall_default,2,cgpara2);
+ if is_interfacecom_or_dispinterface(t) then
+ incrfunc:='FPC_INTF_INCR_REF'
+ else if is_ansistring(t) then
+ incrfunc:='FPC_ANSISTR_INCR_REF'
+ else if is_widestring(t) then
+ incrfunc:='FPC_WIDESTR_INCR_REF'
+ else if is_unicodestring(t) then
+ incrfunc:='FPC_UNICODESTR_INCR_REF'
+ else if is_dynamic_array(t) then
+ incrfunc:='FPC_DYNARRAY_INCR_REF'
+ else
+ incrfunc:='';
+ { call the special incr function or the generic addref }
+ if incrfunc<>'' then
+ begin
+ { widestrings aren't ref. counted on all platforms so we need the address
+ to create a real copy }
+ if is_widestring(t) then
+ a_loadaddr_ref_cgpara(list,ref,cgpara1)
+ else
+ { these functions get the pointer by value }
+ a_load_ref_cgpara(list,OS_ADDR,ref,cgpara1);
+ paramanager.freecgpara(list,cgpara1);
+ allocallcpuregisters(list);
+ a_call_name(list,incrfunc,false);
+ deallocallcpuregisters(list);
+ end
+ else
+ begin
+ if is_open_array(t) then
+ InternalError(201103054);
+ reference_reset_symbol(href,RTTIWriter.get_rtti_label(t,initrtti),0,sizeof(pint));
+ a_loadaddr_ref_cgpara(list,href,cgpara2);
+ a_loadaddr_ref_cgpara(list,ref,cgpara1);
+ paramanager.freecgpara(list,cgpara1);
+ paramanager.freecgpara(list,cgpara2);
+ allocallcpuregisters(list);
+ a_call_name(list,'FPC_ADDREF',false);
+ deallocallcpuregisters(list);
+ end;
+ cgpara2.done;
+ cgpara1.done;
+ end;
+
+
+ procedure tcg.g_array_rtti_helper(list: TAsmList; t: tdef; const ref: treference; const highloc: tlocation; const name: string);
+ var
+ cgpara1,cgpara2,cgpara3: TCGPara;
+ href: TReference;
+ hreg, lenreg: TRegister;
+ begin
+ cgpara1.init;
+ cgpara2.init;
+ cgpara3.init;
+ paramanager.getintparaloc(pocall_default,1,cgpara1);
+ paramanager.getintparaloc(pocall_default,2,cgpara2);
+ paramanager.getintparaloc(pocall_default,3,cgpara3);
+
+ reference_reset_symbol(href,RTTIWriter.get_rtti_label(t,initrtti),0,sizeof(pint));
+ if highloc.loc=LOC_CONSTANT then
+ a_load_const_cgpara(list,OS_INT,highloc.value+1,cgpara3)
+ else
+ begin
+ if highloc.loc in [LOC_REGISTER,LOC_CREGISTER] then
+ hreg:=highloc.register
+ else
+ begin
+ hreg:=getintregister(list,OS_INT);
+ a_load_loc_reg(list,OS_INT,highloc,hreg);
+ end;
+ { increment, converts high(x) to length(x) }
+ lenreg:=getintregister(list,OS_INT);
+ a_op_const_reg_reg(list,OP_ADD,OS_INT,1,hreg,lenreg);
+ a_load_reg_cgpara(list,OS_INT,lenreg,cgpara3);
+ end;
+
+ a_loadaddr_ref_cgpara(list,href,cgpara2);
+ a_loadaddr_ref_cgpara(list,ref,cgpara1);
+ paramanager.freecgpara(list,cgpara1);
+ paramanager.freecgpara(list,cgpara2);
+ paramanager.freecgpara(list,cgpara3);
+ allocallcpuregisters(list);
+ a_call_name(list,name,false);
+ deallocallcpuregisters(list);
+
+ cgpara3.done;
+ cgpara2.done;
+ cgpara1.done;
+ end;
+
+ procedure tcg.g_initialize(list : TAsmList;t : tdef;const ref : treference);
+ var
+ href : treference;
+ cgpara1,cgpara2 : TCGPara;
+ begin
+ cgpara1.init;
+ cgpara2.init;
+ if is_ansistring(t) or
+ is_widestring(t) or
+ is_unicodestring(t) or
+ is_interfacecom_or_dispinterface(t) or
+ is_dynamic_array(t) then
+ a_load_const_ref(list,OS_ADDR,0,ref)
+ else if t.typ=variantdef then
+ begin
+ paramanager.getintparaloc(pocall_default,1,cgpara1);
+ a_loadaddr_ref_cgpara(list,ref,cgpara1);
+ paramanager.freecgpara(list,cgpara1);
+ allocallcpuregisters(list);
+ a_call_name(list,'FPC_VARIANT_INIT',false);
+ deallocallcpuregisters(list);
+ end
+ else
+ begin
+ if is_open_array(t) then
+ InternalError(201103052);
+ paramanager.getintparaloc(pocall_default,1,cgpara1);
+ paramanager.getintparaloc(pocall_default,2,cgpara2);
+ reference_reset_symbol(href,RTTIWriter.get_rtti_label(t,initrtti),0,sizeof(pint));
+ a_loadaddr_ref_cgpara(list,href,cgpara2);
+ a_loadaddr_ref_cgpara(list,ref,cgpara1);
+ paramanager.freecgpara(list,cgpara1);
+ paramanager.freecgpara(list,cgpara2);
+ allocallcpuregisters(list);
+ a_call_name(list,'FPC_INITIALIZE',false);
+ deallocallcpuregisters(list);
+ end;
+ cgpara1.done;
+ cgpara2.done;
+ end;
+
+
+ procedure tcg.g_finalize(list : TAsmList;t : tdef;const ref : treference);
+ var
+ href : treference;
+ cgpara1,cgpara2 : TCGPara;
+ decrfunc : string;
+ begin
+ if is_interfacecom_or_dispinterface(t) then
+ decrfunc:='FPC_INTF_DECR_REF'
+ else if is_ansistring(t) then
+ decrfunc:='FPC_ANSISTR_DECR_REF'
+ else if is_widestring(t) then
+ decrfunc:='FPC_WIDESTR_DECR_REF'
+ else if is_unicodestring(t) then
+ decrfunc:='FPC_UNICODESTR_DECR_REF'
+ else if t.typ=variantdef then
+ decrfunc:='FPC_VARIANT_CLEAR'
+ else
+ begin
+ cgpara1.init;
+ cgpara2.init;
+ if is_open_array(t) then
+ InternalError(201103051);
+ paramanager.getintparaloc(pocall_default,1,cgpara1);
+ paramanager.getintparaloc(pocall_default,2,cgpara2);
+ reference_reset_symbol(href,RTTIWriter.get_rtti_label(t,initrtti),0,sizeof(pint));
+ a_loadaddr_ref_cgpara(list,href,cgpara2);
+ a_loadaddr_ref_cgpara(list,ref,cgpara1);
+ paramanager.freecgpara(list,cgpara1);
+ paramanager.freecgpara(list,cgpara2);
+ if is_dynamic_array(t) then
+ g_call(list,'FPC_DYNARRAY_CLEAR')
+ else
+ g_call(list,'FPC_FINALIZE');
+ cgpara1.done;
+ cgpara2.done;
+ exit;
+ end;
+ cgpara1.init;
+ paramanager.getintparaloc(pocall_default,1,cgpara1);
+ a_loadaddr_ref_cgpara(list,ref,cgpara1);
+ paramanager.freecgpara(list,cgpara1);
+ g_call(list,decrfunc);
+ cgpara1.done;
+ end;
+
+
+ procedure tcg.g_rangecheck(list: TAsmList; const l:tlocation;fromdef,todef: tdef);
+ { generate range checking code for the value at location p. The type }
+ { type used is checked against todefs ranges. fromdef (p.resultdef) }
+ { is the original type used at that location. When both defs are equal }
+ { the check is also insert (needed for succ,pref,inc,dec) }
+ const
+ aintmax=high(aint);
+ var
+ neglabel : tasmlabel;
+ hreg : tregister;
+ lto,hto,
+ lfrom,hfrom : TConstExprInt;
+ fromsize, tosize: cardinal;
+ from_signed, to_signed: boolean;
+ begin
+ { range checking on and range checkable value? }
+ if not(cs_check_range in current_settings.localswitches) or
+ not(fromdef.typ in [orddef,enumdef]) or
+ { C-style booleans can't really fail range checks, }
+ { all values are always valid }
+ is_cbool(todef) then
+ exit;
+{$ifndef cpu64bitalu}
+ { handle 64bit rangechecks separate for 32bit processors }
+ if is_64bit(fromdef) or is_64bit(todef) then
+ begin
+ cg64.g_rangecheck64(list,l,fromdef,todef);
+ exit;
+ end;
+{$endif cpu64bitalu}
+ { only check when assigning to scalar, subranges are different, }
+ { when todef=fromdef then the check is always generated }
+ getrange(fromdef,lfrom,hfrom);
+ getrange(todef,lto,hto);
+ from_signed := is_signed(fromdef);
+ to_signed := is_signed(todef);
+ { check the rangedef of the array, not the array itself }
+ { (only change now, since getrange needs the arraydef) }
+ if (todef.typ = arraydef) then
+ todef := tarraydef(todef).rangedef;
+ { no range check if from and to are equal and are both longint/dword }
+ { (if we have a 32bit processor) or int64/qword, since such }
+ { operations can at most cause overflows (JM) }
+ { Note that these checks are mostly processor independent, they only }
+ { have to be changed once we introduce 64bit subrange types }
+{$ifdef cpu64bitalu}
+ if (fromdef = todef) and
+ (fromdef.typ=orddef) and
+ (((((torddef(fromdef).ordtype = s64bit) and
+ (lfrom = low(int64)) and
+ (hfrom = high(int64))) or
+ ((torddef(fromdef).ordtype = u64bit) and
+ (lfrom = low(qword)) and
+ (hfrom = high(qword))) or
+ ((torddef(fromdef).ordtype = scurrency) and
+ (lfrom = low(int64)) and
+ (hfrom = high(int64)))))) then
+ exit;
+{$else cpu64bitalu}
+ if (fromdef = todef) and
+ (fromdef.typ=orddef) and
+ (((((torddef(fromdef).ordtype = s32bit) and
+ (lfrom = int64(low(longint))) and
+ (hfrom = int64(high(longint)))) or
+ ((torddef(fromdef).ordtype = u32bit) and
+ (lfrom = low(cardinal)) and
+ (hfrom = high(cardinal)))))) then
+ exit;
+{$endif cpu64bitalu}
+
+ { optimize some range checks away in safe cases }
+ fromsize := fromdef.size;
+ tosize := todef.size;
+ if ((from_signed = to_signed) or
+ (not from_signed)) and
+ (lto<=lfrom) and (hto>=hfrom) and
+ (fromsize <= tosize) then
+ begin
+ { if fromsize < tosize, and both have the same signed-ness or }
+ { fromdef is unsigned, then all bit patterns from fromdef are }
+ { valid for todef as well }
+ if (fromsize < tosize) then
+ exit;
+ if (fromsize = tosize) and
+ (from_signed = to_signed) then
+ { only optimize away if all bit patterns which fit in fromsize }
+ { are valid for the todef }
+ begin
+{$push}
+{$Q-}
+{$R-}
+ if to_signed then
+ begin
+ { calculation of the low/high ranges must not overflow 64 bit
+ otherwise we end up comparing with zero for 64 bit data types on
+ 64 bit processors }
+ if (lto = (int64(-1) << (tosize * 8 - 1))) and
+ (hto = (-((int64(-1) << (tosize * 8 - 1))+1))) then
+ exit
+ end
+ else
+ begin
+ { calculation of the low/high ranges must not overflow 64 bit
+ otherwise we end up having all zeros for 64 bit data types on
+ 64 bit processors }
+ if (lto = 0) and
+ (qword(hto) = (qword(-1) >> (64-(tosize * 8))) ) then
+ exit
+ end;
+{$pop}
+ end
+ end;
+
+ { generate the rangecheck code for the def where we are going to }
+ { store the result }
+
+ { use the trick that }
+ { a <= x <= b <=> 0 <= x-a <= b-a <=> unsigned(x-a) <= unsigned(b-a) }
+
+ { To be able to do that, we have to make sure however that either }
+ { fromdef and todef are both signed or unsigned, or that we leave }
+ { the parts < 0 and > maxlongint out }
+
+ if from_signed xor to_signed then
+ begin
+ if from_signed then
+ { from is signed, to is unsigned }
+ begin
+ { if high(from) < 0 -> always range error }
+ if (hfrom < 0) or
+ { if low(to) > maxlongint also range error }
+ (lto > aintmax) then
+ begin
+ a_call_name(list,'FPC_RANGEERROR',false);
+ exit
+ end;
+ { from is signed and to is unsigned -> when looking at to }
+ { as an signed value, it must be < maxaint (otherwise }
+ { it will become negative, which is invalid since "to" is unsigned) }
+ if hto > aintmax then
+ hto := aintmax;
+ end
+ else
+ { from is unsigned, to is signed }
+ begin
+ if (lfrom > aintmax) or
+ (hto < 0) then
+ begin
+ a_call_name(list,'FPC_RANGEERROR',false);
+ exit
+ end;
+ { from is unsigned and to is signed -> when looking at to }
+ { as an unsigned value, it must be >= 0 (since negative }
+ { values are the same as values > maxlongint) }
+ if lto < 0 then
+ lto := 0;
+ end;
+ end;
+ hreg:=getintregister(list,OS_INT);
+ a_load_loc_reg(list,OS_INT,l,hreg);
+ a_op_const_reg(list,OP_SUB,OS_INT,tcgint(int64(lto)),hreg);
+ current_asmdata.getjumplabel(neglabel);
+ {
+ if from_signed then
+ a_cmp_const_reg_label(list,OS_INT,OC_GTE,aint(hto-lto),hreg,neglabel)
+ else
+ }
+{$ifdef cpu64bitalu}
+ if qword(hto-lto)>qword(aintmax) then
+ a_cmp_const_reg_label(list,OS_INT,OC_BE,aintmax,hreg,neglabel)
+ else
+{$endif cpu64bitalu}
+ a_cmp_const_reg_label(list,OS_INT,OC_BE,tcgint(int64(hto-lto)),hreg,neglabel);
+ a_call_name(list,'FPC_RANGEERROR',false);
+ a_label(list,neglabel);
+ end;
+
+
+ procedure tcg.g_overflowCheck_loc(List:TAsmList;const Loc:TLocation;def:TDef;ovloc : tlocation);
+ begin
+ g_overflowCheck(list,loc,def);
+ end;
+
+
+{$ifdef cpuflags}
+ procedure tcg.g_flags2ref(list: TAsmList; size: TCgSize; const f: tresflags; const ref:TReference);
+
+ var
+ tmpreg : tregister;
+ begin
+ tmpreg:=getintregister(list,size);
+ g_flags2reg(list,size,f,tmpreg);
+ a_load_reg_ref(list,size,size,tmpreg,ref);
+ end;
+{$endif cpuflags}
+
+
+ procedure tcg.g_maybe_testself(list : TAsmList;reg:tregister);
+ var
+ OKLabel : tasmlabel;
+ cgpara1 : TCGPara;
+ begin
+ if (cs_check_object in current_settings.localswitches) or
+ (cs_check_range in current_settings.localswitches) then
+ begin
+ current_asmdata.getjumplabel(oklabel);
+ a_cmp_const_reg_label(list,OS_ADDR,OC_NE,0,reg,oklabel);
+ cgpara1.init;
+ paramanager.getintparaloc(pocall_default,1,cgpara1);
+ a_load_const_cgpara(list,OS_INT,tcgint(210),cgpara1);
+ paramanager.freecgpara(list,cgpara1);
+ a_call_name(list,'FPC_HANDLEERROR',false);
+ a_label(list,oklabel);
+ cgpara1.done;
+ end;
+ end;
+
+
+ procedure tcg.g_maybe_testvmt(list : TAsmList;reg:tregister;objdef:tobjectdef);
+ var
+ hrefvmt : treference;
+ cgpara1,cgpara2 : TCGPara;
+ begin
+ cgpara1.init;
+ cgpara2.init;
+ paramanager.getintparaloc(pocall_default,1,cgpara1);
+ paramanager.getintparaloc(pocall_default,2,cgpara2);
+ if (cs_check_object in current_settings.localswitches) then
+ begin
+ reference_reset_symbol(hrefvmt,current_asmdata.RefAsmSymbol(objdef.vmt_mangledname),0,sizeof(pint));
+ a_loadaddr_ref_cgpara(list,hrefvmt,cgpara2);
+ a_load_reg_cgpara(list,OS_ADDR,reg,cgpara1);
+ paramanager.freecgpara(list,cgpara1);
+ paramanager.freecgpara(list,cgpara2);
+ allocallcpuregisters(list);
+ a_call_name(list,'FPC_CHECK_OBJECT_EXT',false);
+ deallocallcpuregisters(list);
+ end
+ else
+ if (cs_check_range in current_settings.localswitches) then
+ begin
+ a_load_reg_cgpara(list,OS_ADDR,reg,cgpara1);
+ paramanager.freecgpara(list,cgpara1);
+ allocallcpuregisters(list);
+ a_call_name(list,'FPC_CHECK_OBJECT',false);
+ deallocallcpuregisters(list);
+ end;
+ cgpara1.done;
+ cgpara2.done;
+ end;
+
+
+{*****************************************************************************
+ Entry/Exit Code Functions
+*****************************************************************************}
+
+ procedure tcg.g_copyvaluepara_openarray(list : TAsmList;const ref:treference;const lenloc:tlocation;elesize:tcgint;destreg:tregister);
+ var
+ sizereg,sourcereg,lenreg : tregister;
+ cgpara1,cgpara2,cgpara3 : TCGPara;
+ begin
+ { because some abis don't support dynamic stack allocation properly
+ open array value parameters are copied onto the heap
+ }
+
+ { calculate necessary memory }
+
+ { read/write operations on one register make the life of the register allocator hard }
+ if not(lenloc.loc in [LOC_REGISTER,LOC_CREGISTER]) then
+ begin
+ lenreg:=getintregister(list,OS_INT);
+ a_load_loc_reg(list,OS_INT,lenloc,lenreg);
+ end
+ else
+ lenreg:=lenloc.register;
+
+ sizereg:=getintregister(list,OS_INT);
+ a_op_const_reg_reg(list,OP_ADD,OS_INT,1,lenreg,sizereg);
+ a_op_const_reg(list,OP_IMUL,OS_INT,elesize,sizereg);
+ { load source }
+ sourcereg:=getaddressregister(list);
+ a_loadaddr_ref_reg(list,ref,sourcereg);
+
+ { do getmem call }
+ cgpara1.init;
+ paramanager.getintparaloc(pocall_default,1,cgpara1);
+ a_load_reg_cgpara(list,OS_INT,sizereg,cgpara1);
+ paramanager.freecgpara(list,cgpara1);
+ allocallcpuregisters(list);
+ a_call_name(list,'FPC_GETMEM',false);
+ deallocallcpuregisters(list);
+ cgpara1.done;
+ { return the new address }
+ a_load_reg_reg(list,OS_ADDR,OS_ADDR,NR_FUNCTION_RESULT_REG,destreg);
+
+ { do move call }
+ cgpara1.init;
+ cgpara2.init;
+ cgpara3.init;
+ paramanager.getintparaloc(pocall_default,1,cgpara1);
+ paramanager.getintparaloc(pocall_default,2,cgpara2);
+ paramanager.getintparaloc(pocall_default,3,cgpara3);
+ { load size }
+ a_load_reg_cgpara(list,OS_INT,sizereg,cgpara3);
+ { load destination }
+ a_load_reg_cgpara(list,OS_ADDR,destreg,cgpara2);
+ { load source }
+ a_load_reg_cgpara(list,OS_ADDR,sourcereg,cgpara1);
+ paramanager.freecgpara(list,cgpara3);
+ paramanager.freecgpara(list,cgpara2);
+ paramanager.freecgpara(list,cgpara1);
+ allocallcpuregisters(list);
+ a_call_name(list,'FPC_MOVE',false);
+ deallocallcpuregisters(list);
+ cgpara3.done;
+ cgpara2.done;
+ cgpara1.done;
+ end;
+
+
+ procedure tcg.g_releasevaluepara_openarray(list : TAsmList;const l:tlocation);
+ var
+ cgpara1 : TCGPara;
+ begin
+ { do move call }
+ cgpara1.init;
+ paramanager.getintparaloc(pocall_default,1,cgpara1);
+ { load source }
+ a_load_loc_cgpara(list,l,cgpara1);
+ paramanager.freecgpara(list,cgpara1);
+ allocallcpuregisters(list);
+ a_call_name(list,'FPC_FREEMEM',false);
+ deallocallcpuregisters(list);
+ cgpara1.done;
+ end;
+
+
+ procedure tcg.g_save_registers(list:TAsmList);
+ var
+ href : treference;
+ size : longint;
+ r : integer;
+ begin
+ { calculate temp. size }
+ size:=0;
+ for r:=low(saved_standard_registers) to high(saved_standard_registers) do
+ if saved_standard_registers[r] in rg[R_INTREGISTER].used_in_proc then
+ inc(size,sizeof(aint));
+
+ { mm registers }
+ if uses_registers(R_MMREGISTER) then
+ begin
+ { Make sure we reserve enough space to do the alignment based on the offset
+ later on. We can't use the size for this, because the alignment of the start
+ of the temp is smaller than needed for an OS_VECTOR }
+ inc(size,tcgsize2size[OS_VECTOR]);
+
+ for r:=low(saved_mm_registers) to high(saved_mm_registers) do
+ if saved_mm_registers[r] in rg[R_MMREGISTER].used_in_proc then
+ inc(size,tcgsize2size[OS_VECTOR]);
+ end;
+
+ if size>0 then
+ begin
+ tg.GetTemp(list,size,sizeof(aint),tt_noreuse,current_procinfo.save_regs_ref);
+ include(current_procinfo.flags,pi_has_saved_regs);
+
+ { Copy registers to temp }
+ href:=current_procinfo.save_regs_ref;
+ for r:=low(saved_standard_registers) to high(saved_standard_registers) do
+ begin
+ if saved_standard_registers[r] in rg[R_INTREGISTER].used_in_proc then
+ begin
+ a_load_reg_ref(list,OS_ADDR,OS_ADDR,newreg(R_INTREGISTER,saved_standard_registers[r],R_SUBWHOLE),href);
+ inc(href.offset,sizeof(aint));
+ end;
+ include(rg[R_INTREGISTER].preserved_by_proc,saved_standard_registers[r]);
+ end;
+
+ if uses_registers(R_MMREGISTER) then
+ begin
+ if (href.offset mod tcgsize2size[OS_VECTOR])<>0 then
+ inc(href.offset,tcgsize2size[OS_VECTOR]-(href.offset mod tcgsize2size[OS_VECTOR]));
+
+ for r:=low(saved_mm_registers) to high(saved_mm_registers) do
+ begin
+ if saved_mm_registers[r] in rg[R_MMREGISTER].used_in_proc then
+ begin
+ a_loadmm_reg_ref(list,OS_VECTOR,OS_VECTOR,newreg(R_MMREGISTER,saved_mm_registers[r],R_SUBNONE),href,nil);
+ inc(href.offset,tcgsize2size[OS_VECTOR]);
+ end;
+ include(rg[R_MMREGISTER].preserved_by_proc,saved_mm_registers[r]);
+ end;
+ end;
+ end;
+ end;
+
+
+ procedure tcg.g_restore_registers(list:TAsmList);
+ var
+ href : treference;
+ r : integer;
+ hreg : tregister;
+ begin
+ if not(pi_has_saved_regs in current_procinfo.flags) then
+ exit;
+ { Copy registers from temp }
+ href:=current_procinfo.save_regs_ref;
+ for r:=low(saved_standard_registers) to high(saved_standard_registers) do
+ if saved_standard_registers[r] in rg[R_INTREGISTER].used_in_proc then
+ begin
+ hreg:=newreg(R_INTREGISTER,saved_standard_registers[r],R_SUBWHOLE);
+ { Allocate register so the optimizer does not remove the load }
+ a_reg_alloc(list,hreg);
+ a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,hreg);
+ inc(href.offset,sizeof(aint));
+ end;
+
+ if uses_registers(R_MMREGISTER) then
+ begin
+ if (href.offset mod tcgsize2size[OS_VECTOR])<>0 then
+ inc(href.offset,tcgsize2size[OS_VECTOR]-(href.offset mod tcgsize2size[OS_VECTOR]));
+
+ for r:=low(saved_mm_registers) to high(saved_mm_registers) do
+ begin
+ if saved_mm_registers[r] in rg[R_MMREGISTER].used_in_proc then
+ begin
+ hreg:=newreg(R_MMREGISTER,saved_mm_registers[r],R_SUBNONE);
+ { Allocate register so the optimizer does not remove the load }
+ a_reg_alloc(list,hreg);
+ a_loadmm_ref_reg(list,OS_VECTOR,OS_VECTOR,href,hreg,nil);
+ inc(href.offset,tcgsize2size[OS_VECTOR]);
+ end;
+ end;
+ end;
+ tg.UnGetTemp(list,current_procinfo.save_regs_ref);
+ end;
+
+
+ procedure tcg.g_profilecode(list : TAsmList);
+ begin
+ end;
+
+
+ procedure tcg.g_exception_reason_save(list : TAsmList; const href : treference);
+ begin
+ a_load_reg_ref(list, OS_INT, OS_INT, NR_FUNCTION_RESULT_REG, href);
+ end;
+
+
+ procedure tcg.g_exception_reason_save_const(list : TAsmList; const href : treference; a: tcgint);
+ begin
+ a_load_const_ref(list, OS_INT, a, href);
+ end;
+
+
+ procedure tcg.g_exception_reason_load(list : TAsmList; const href : treference);
+ begin
+ cg.a_reg_alloc(list,NR_FUNCTION_RESULT_REG);
+ a_load_ref_reg(list, OS_INT, OS_INT, href, NR_FUNCTION_RESULT_REG);
+ end;
+
+
+ procedure tcg.g_adjust_self_value(list:TAsmList;procdef: tprocdef;ioffset: tcgint);
+ var
+ hsym : tsym;
+ href : treference;
+ paraloc : Pcgparalocation;
+ begin
+ { calculate the parameter info for the procdef }
+ procdef.init_paraloc_info(callerside);
+ hsym:=tsym(procdef.parast.Find('self'));
+ if not(assigned(hsym) and
+ (hsym.typ=paravarsym)) then
+ internalerror(200305251);
+ paraloc:=tparavarsym(hsym).paraloc[callerside].location;
+ while paraloc<>nil do
+ with paraloc^ do
+ begin
+ case loc of
+ LOC_REGISTER:
+ a_op_const_reg(list,OP_SUB,size,ioffset,register);
+ LOC_REFERENCE:
+ begin
+ { offset in the wrapper needs to be adjusted for the stored
+ return address }
+ reference_reset_base(href,reference.index,reference.offset+sizeof(pint),sizeof(pint));
+ a_op_const_ref(list,OP_SUB,size,ioffset,href);
+ end
+ else
+ internalerror(200309189);
+ end;
+ paraloc:=next;
+ end;
+ end;
+
+
+ procedure tcg.g_external_wrapper(list : TAsmList; procdef: tprocdef; const externalname: string);
+ begin
+ a_jmp_name(list,externalname);
+ end;
+
+
+ procedure tcg.a_call_name_static(list : TAsmList;const s : string);
+ begin
+ a_call_name(list,s,false);
+ end;
+
+
+ procedure tcg.a_call_ref(list : TAsmList;ref: treference);
+ var
+ tempreg : TRegister;
+ begin
+ tempreg := getintregister(list, OS_ADDR);
+ a_load_ref_reg(list,OS_ADDR,OS_ADDR,ref,tempreg);
+ a_call_reg(list,tempreg);
+ end;
+
+
+ function tcg.g_indirect_sym_load(list:TAsmList;const symname: string; weak: boolean): tregister;
+ var
+ l: tasmsymbol;
+ ref: treference;
+ nlsymname: string;
+ begin
+ result := NR_NO;
+ case target_info.system of
+ system_powerpc_darwin,
+ system_i386_darwin,
+ system_i386_iphonesim,
+ system_powerpc64_darwin,
+ system_arm_darwin:
+ begin
+ nlsymname:='L'+symname+'$non_lazy_ptr';
+ l:=current_asmdata.getasmsymbol(nlsymname);
+ if not(assigned(l)) then
+ begin
+ new_section(current_asmdata.asmlists[al_picdata],sec_data_nonlazy,'',sizeof(pint));
+ l:=current_asmdata.DefineAsmSymbol(nlsymname,AB_LOCAL,AT_DATA);
+ current_asmdata.asmlists[al_picdata].concat(tai_symbol.create(l,0));
+ if not(weak) then
+ current_asmdata.asmlists[al_picdata].concat(tai_directive.Create(asd_indirect_symbol,current_asmdata.RefAsmSymbol(symname).Name))
+ else
+ current_asmdata.asmlists[al_picdata].concat(tai_directive.Create(asd_indirect_symbol,current_asmdata.WeakRefAsmSymbol(symname).Name));
+{$ifdef cpu64bitaddr}
+ current_asmdata.asmlists[al_picdata].concat(tai_const.create_64bit(0));
+{$else cpu64bitaddr}
+ current_asmdata.asmlists[al_picdata].concat(tai_const.create_32bit(0));
+{$endif cpu64bitaddr}
+ end;
+ result := getaddressregister(list);
+ reference_reset_symbol(ref,l,0,sizeof(pint));
+ { a_load_ref_reg will turn this into a pic-load if needed }
+ a_load_ref_reg(list,OS_ADDR,OS_ADDR,ref,result);
+ end;
+ end;
+ end;
+
+
+ procedure tcg.g_maybe_got_init(list: TAsmList);
+ begin
+ end;
+
+ procedure tcg.g_call(list: TAsmList;const s: string);
+ begin
+ allocallcpuregisters(list);
+ a_call_name(list,s,false);
+ deallocallcpuregisters(list);
+ end;
+
+ procedure tcg.g_local_unwind(list: TAsmList; l: TAsmLabel);
+ begin
+ a_jmp_always(list,l);
+ end;
+
+ procedure tcg.a_loadmm_reg_reg(list: TAsmList; fromsize, tosize: tcgsize; reg1, reg2: tregister; shuffle: pmmshuffle);
+ begin
+ internalerror(200807231);
+ end;
+
+
+ procedure tcg.a_loadmm_ref_reg(list: TAsmList; fromsize, tosize: tcgsize; const ref: treference; reg: tregister; shuffle: pmmshuffle);
+ begin
+ internalerror(200807232);
+ end;
+
+
+ procedure tcg.a_loadmm_reg_ref(list: TAsmList; fromsize, tosize: tcgsize; reg: tregister; const ref: treference; shuffle: pmmshuffle);
+ begin
+ internalerror(200807233);
+ end;
+
+
+ procedure tcg.a_opmm_reg_reg(list: TAsmList; Op: TOpCG; size: tcgsize; src, dst: tregister; shuffle: pmmshuffle);
+ begin
+ internalerror(200807234);
+ end;
+
+
+ function tcg.getflagregister(list: TAsmList; size: Tcgsize): Tregister;
+ begin
+ Result:=TRegister(0);
+ internalerror(200807238);
+ end;
+
+{*****************************************************************************
+ TCG64
+*****************************************************************************}
+
+{$ifndef cpu64bitalu}
+ procedure tcg64.a_op64_const_reg_reg(list: TAsmList;op:TOpCG;size : tcgsize;value : int64; regsrc,regdst : tregister64);
+ begin
+ a_load64_reg_reg(list,regsrc,regdst);
+ a_op64_const_reg(list,op,size,value,regdst);
+ end;
+
+
+ procedure tcg64.a_op64_reg_reg_reg(list: TAsmList;op:TOpCG;size : tcgsize;regsrc1,regsrc2,regdst : tregister64);
+ var
+ tmpreg64 : tregister64;
+ begin
+ { when src1=dst then we need to first create a temp to prevent
+ overwriting src1 with src2 }
+ if (regsrc1.reghi=regdst.reghi) or
+ (regsrc1.reglo=regdst.reghi) or
+ (regsrc1.reghi=regdst.reglo) or
+ (regsrc1.reglo=regdst.reglo) then
+ begin
+ tmpreg64.reglo:=cg.getintregister(list,OS_32);
+ tmpreg64.reghi:=cg.getintregister(list,OS_32);
+ a_load64_reg_reg(list,regsrc2,tmpreg64);
+ a_op64_reg_reg(list,op,size,regsrc1,tmpreg64);
+ a_load64_reg_reg(list,tmpreg64,regdst);
+ end
+ else
+ begin
+ a_load64_reg_reg(list,regsrc2,regdst);
+ a_op64_reg_reg(list,op,size,regsrc1,regdst);
+ end;
+ end;
+
+
+ procedure tcg64.a_op64_const_subsetref(list : TAsmList; Op : TOpCG; size : TCGSize; a : int64; const sref: tsubsetreference);
+ var
+ tmpreg64 : tregister64;
+ begin
+ tmpreg64.reglo:=cg.getintregister(list,OS_32);
+ tmpreg64.reghi:=cg.getintregister(list,OS_32);
+ a_load64_subsetref_reg(list,sref,tmpreg64);
+ a_op64_const_reg(list,op,size,a,tmpreg64);
+ a_load64_reg_subsetref(list,tmpreg64,sref);
+ end;
+
+
+ procedure tcg64.a_op64_reg_subsetref(list : TAsmList; Op : TOpCG; size : TCGSize; reg: tregister64; const sref: tsubsetreference);
+ var
+ tmpreg64 : tregister64;
+ begin
+ tmpreg64.reglo:=cg.getintregister(list,OS_32);
+ tmpreg64.reghi:=cg.getintregister(list,OS_32);
+ a_load64_subsetref_reg(list,sref,tmpreg64);
+ a_op64_reg_reg(list,op,size,reg,tmpreg64);
+ a_load64_reg_subsetref(list,tmpreg64,sref);
+ end;
+
+
+ procedure tcg64.a_op64_ref_subsetref(list : TAsmList; Op : TOpCG; size : TCGSize; const ref: treference; const sref: tsubsetreference);
+ var
+ tmpreg64 : tregister64;
+ begin
+ tmpreg64.reglo:=cg.getintregister(list,OS_32);
+ tmpreg64.reghi:=cg.getintregister(list,OS_32);
+ a_load64_subsetref_reg(list,sref,tmpreg64);
+ a_op64_ref_reg(list,op,size,ref,tmpreg64);
+ a_load64_reg_subsetref(list,tmpreg64,sref);
+ end;
+
+
+ procedure tcg64.a_op64_subsetref_subsetref(list : TAsmList; Op : TOpCG; size : TCGSize; const ssref,dsref: tsubsetreference);
+ var
+ tmpreg64 : tregister64;
+ begin
+ tmpreg64.reglo:=cg.getintregister(list,OS_32);
+ tmpreg64.reghi:=cg.getintregister(list,OS_32);
+ a_load64_subsetref_reg(list,ssref,tmpreg64);
+ a_op64_reg_subsetref(list,op,size,tmpreg64,dsref);
+ end;
+
+
+ procedure tcg64.a_op64_const_reg_reg_checkoverflow(list: TAsmList;op:TOpCG;size : tcgsize;value : int64;regsrc,regdst : tregister64;setflags : boolean;var ovloc : tlocation);
+ begin
+ a_op64_const_reg_reg(list,op,size,value,regsrc,regdst);
+ ovloc.loc:=LOC_VOID;
+ end;
+
+
+ procedure tcg64.a_op64_reg_reg_reg_checkoverflow(list: TAsmList;op:TOpCG;size : tcgsize;regsrc1,regsrc2,regdst : tregister64;setflags : boolean;var ovloc : tlocation);
+ begin
+ a_op64_reg_reg_reg(list,op,size,regsrc1,regsrc2,regdst);
+ ovloc.loc:=LOC_VOID;
+ end;
+
+
+ procedure tcg64.a_load64_loc_subsetref(list : TAsmList;const l: tlocation; const sref : tsubsetreference);
+ begin
+ case l.loc of
+ LOC_REFERENCE, LOC_CREFERENCE:
+ a_load64_ref_subsetref(list,l.reference,sref);
+ LOC_REGISTER,LOC_CREGISTER:
+ a_load64_reg_subsetref(list,l.register64,sref);
+ LOC_CONSTANT :
+ a_load64_const_subsetref(list,l.value64,sref);
+ LOC_SUBSETREF,LOC_CSUBSETREF:
+ a_load64_subsetref_subsetref(list,l.sref,sref);
+ else
+ internalerror(2006082210);
+ end;
+ end;
+
+
+ procedure tcg64.a_load64_subsetref_loc(list: TAsmlist; const sref: tsubsetreference; const l: tlocation);
+ begin
+ case l.loc of
+ LOC_REFERENCE, LOC_CREFERENCE:
+ a_load64_subsetref_ref(list,sref,l.reference);
+ LOC_REGISTER,LOC_CREGISTER:
+ a_load64_subsetref_reg(list,sref,l.register64);
+ LOC_SUBSETREF,LOC_CSUBSETREF:
+ a_load64_subsetref_subsetref(list,sref,l.sref);
+ else
+ internalerror(2006082211);
+ end;
+ end;
+{$endif cpu64bitalu}
+
+
+ procedure destroy_codegen;
+ begin
+ cg.free;
+ cg:=nil;
+{$ifndef cpu64bitalu}
+ cg64.free;
+ cg64:=nil;
+{$endif cpu64bitalu}
+ end;
+
+end.
diff --git a/closures/compiler/cgutils.pas b/closures/compiler/cgutils.pas
new file mode 100644
index 0000000000..5426f7b3c6
--- /dev/null
+++ b/closures/compiler/cgutils.pas
@@ -0,0 +1,248 @@
+{
+ Copyright (c) 1998-2004 by Florian Klaempfl
+
+ Some basic types and constants for the code generation
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+{ This unit exports some helper routines which are used across the code generator }
+unit cgutils;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ globtype,
+ cclasses,
+ aasmbase,
+ cpubase,cgbase;
+
+ type
+ { reference record, reordered for best alignment }
+ preference = ^treference;
+ treference = record
+ offset : asizeint;
+ symbol,
+ relsymbol : tasmsymbol;
+{$if defined(x86) or defined(m68k)}
+ segment,
+{$endif defined(x86) or defined(m68k)}
+ base,
+ index : tregister;
+ refaddr : trefaddr;
+ scalefactor : byte;
+{$ifdef arm}
+ symboldata : tlinkedlistitem;
+ signindex : shortint;
+ shiftimm : byte;
+ addressmode : taddressmode;
+ shiftmode : tshiftmode;
+{$endif arm}
+{$ifdef avr}
+ addressmode : taddressmode;
+{$endif avr}
+{$ifdef m68k}
+ { indexed increment and decrement mode }
+ { (An)+ and -(An) }
+ direction : tdirection;
+{$endif m68k}
+ alignment : byte;
+ end;
+
+ tsubsetregister = record
+ subsetreg : tregister;
+ startbit, bitlen: byte;
+ subsetregsize: tcgsize;
+ end;
+
+ tsubsetreference = record
+ ref: treference;
+ bitindexreg: tregister;
+ startbit, bitlen: byte;
+ end;
+
+ tlocation = record
+ loc : TCGLoc;
+ size : TCGSize;
+ case TCGLoc of
+{$ifdef cpuflags}
+ LOC_FLAGS : (resflags : tresflags);
+{$endif cpuflags}
+ LOC_CONSTANT : (
+ case longint of
+{$ifdef FPC_BIG_ENDIAN}
+ 1 : (_valuedummy,value : aint);
+{$else FPC_BIG_ENDIAN}
+ 1 : (value : aint);
+{$endif FPC_BIG_ENDIAN}
+ 2 : (value64 : Int64);
+ );
+ LOC_CREFERENCE,
+ LOC_REFERENCE : (reference : treference);
+ { segment in reference at the same place as in loc_register }
+ LOC_REGISTER,
+ LOC_CREGISTER : (
+ case longint of
+ 1 : (register : tregister;
+ { some x86_64 targets require two function result registers }
+ registerhi : tregister;
+{$ifdef m68k}
+ { some m68k OSes require that the result is returned in d0 and a0
+ the second location must be stored here }
+ registeralias : tregister;
+{$endif m68k}
+ );
+{$ifndef cpu64bitalu}
+ { overlay a 64 Bit register type }
+ 2 : (register64 : tregister64);
+{$endif cpu64bitalu}
+{$ifdef avr}
+ 3 : (registers : array[0..3] of tregister);
+{$endif avr}
+ );
+ LOC_SUBSETREG,
+ LOC_CSUBSETREG : (
+ sreg: tsubsetregister;
+ );
+ LOC_SUBSETREF : (
+ sref: tsubsetreference;
+ )
+ end;
+
+
+ { trerefence handling }
+
+ {# Clear to zero a treference }
+ procedure reference_reset(var ref : treference; alignment: longint);
+ {# Clear to zero a treference, and set is base address
+ to base register.
+ }
+ procedure reference_reset_base(var ref : treference;base : tregister;offset, alignment : longint);
+ procedure reference_reset_symbol(var ref : treference;sym : tasmsymbol;offset, alignment : longint);
+ { This routine verifies if two references are the same, and
+ if so, returns TRUE, otherwise returns false.
+ }
+ function references_equal(const sref,dref : treference) : boolean;
+
+ { tlocation handling }
+
+ { cannot be used for loc_(c)reference, because that one requires an alignment }
+ procedure location_reset(var l : tlocation;lt:TCGNonRefLoc;lsize:TCGSize);
+ { for loc_(c)reference }
+ procedure location_reset_ref(var l : tlocation;lt:TCGRefLoc;lsize:TCGSize; alignment: longint);
+ procedure location_copy(var destloc:tlocation; const sourceloc : tlocation);
+ procedure location_swap(var destloc,sourceloc : tlocation);
+
+ { returns r with the given alignment }
+ function setalignment(const r : treference;b : byte) : treference;
+
+
+implementation
+
+uses
+ systems,
+ verbose;
+
+{****************************************************************************
+ TReference
+****************************************************************************}
+
+ procedure reference_reset(var ref : treference; alignment: longint);
+ begin
+ FillChar(ref,sizeof(treference),0);
+{$ifdef arm}
+ ref.signindex:=1;
+{$endif arm}
+ ref.alignment:=alignment;
+ end;
+
+
+ procedure reference_reset_base(var ref : treference;base : tregister;offset, alignment : longint);
+ begin
+ reference_reset(ref,alignment);
+ ref.base:=base;
+ ref.offset:=offset;
+ end;
+
+
+ procedure reference_reset_symbol(var ref : treference;sym : tasmsymbol;offset, alignment : longint);
+ begin
+ reference_reset(ref,alignment);
+ ref.symbol:=sym;
+ ref.offset:=offset;
+ end;
+
+
+ function references_equal(const sref,dref : treference):boolean;
+ begin
+ references_equal:=CompareByte(sref,dref,sizeof(treference))=0;
+ end;
+
+
+ { returns r with the given alignment }
+ function setalignment(const r : treference;b : byte) : treference;
+ begin
+ result:=r;
+ result.alignment:=b;
+ end;
+
+{****************************************************************************
+ TLocation
+****************************************************************************}
+
+ procedure location_reset(var l : tlocation;lt:TCGNonRefLoc;lsize:TCGSize);
+ begin
+ FillChar(l,sizeof(tlocation),0);
+ l.loc:=lt;
+ l.size:=lsize;
+ if l.loc in [LOC_REFERENCE,LOC_CREFERENCE] then
+ { call location_reset_ref instead }
+ internalerror(2009020705);
+ end;
+
+ procedure location_reset_ref(var l: tlocation; lt: tcgrefloc; lsize: tcgsize;
+ alignment: longint);
+ begin
+ FillChar(l,sizeof(tlocation),0);
+ l.loc:=lt;
+ l.size:=lsize;
+{$ifdef arm}
+ l.reference.signindex:=1;
+{$endif arm}
+ l.reference.alignment:=alignment;
+ end;
+
+
+ procedure location_copy(var destloc:tlocation; const sourceloc : tlocation);
+ begin
+ destloc:=sourceloc;
+ end;
+
+
+ procedure location_swap(var destloc,sourceloc : tlocation);
+ var
+ swapl : tlocation;
+ begin
+ swapl := destloc;
+ destloc := sourceloc;
+ sourceloc := swapl;
+ end;
+
+
+end.
+
diff --git a/closures/compiler/cmsgs.pas b/closures/compiler/cmsgs.pas
new file mode 100644
index 0000000000..eb550f5a94
--- /dev/null
+++ b/closures/compiler/cmsgs.pas
@@ -0,0 +1,475 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ This unit implements the message object
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit cmsgs;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ globtype;
+
+const
+ maxmsgidxparts = 20;
+
+type
+ ppchar=^pchar;
+ TMsgStr = AnsiString;
+
+ TArrayOfPChar = array[0..1000] of pchar;
+ PArrayOfPChar = ^TArrayOfPChar;
+
+ TArrayOfState = array[0..1000] of tmsgstate;
+ PArrayOfState = ^TArrayOfState;
+
+ PMessage=^TMessage;
+ TMessage=object
+ msgfilename : string;
+ msgintern : boolean;
+ msgallocsize,
+ msgsize,
+ msgparts,
+ msgs : longint;
+ msgtxt : pchar;
+ msgidx : array[1..maxmsgidxparts] of PArrayOfPChar;
+ msgidxmax : array[1..maxmsgidxparts] of longint;
+ msgstates : array[1..maxmsgidxparts] of PArrayOfState;
+ { set if changes with $WARN need to be cleared at next module change }
+ has_local_changes : boolean;
+ constructor Init(n:longint;const idxmax:array of longint);
+ destructor Done;
+ function LoadIntern(p:pointer;n:longint):boolean;
+ function LoadExtern(const fn:string):boolean;
+ procedure ClearIdx;
+ procedure ResetStates;
+ procedure CreateIdx;
+ function GetPChar(nr:longint):pchar;
+ { function ClearVerbosity(nr:longint):boolean; not used anymore }
+ function SetVerbosity(nr:longint;newstate:tmsgstate):boolean;
+ function Get(nr:longint;const args:array of TMsgStr):ansistring;
+ end;
+
+{ this will read a line until #10 or #0 and also increase p }
+function GetMsgLine(var p:pchar):string;
+
+
+implementation
+
+uses
+ SysUtils,
+ cutils;
+
+
+function MsgReplace(const s:TMsgStr;const args:array of TMsgStr):ansistring;
+var
+ last,
+ i : longint;
+ hs : TMsgStr;
+
+begin
+ if s='' then
+ begin
+ MsgReplace:='';
+ exit;
+ end;
+ hs:='';
+ i:=0;
+ last:=0;
+ while (i<length(s)-1) do
+ begin
+ inc(i);
+ if (s[i]='$') and (s[i+1] in ['1'..'9']) then
+ begin
+ hs:=hs+copy(s,last+1,i-last-1)+args[byte(s[i+1])-byte('1')];
+ inc(i);
+ last:=i;
+ end;
+ end;
+ MsgReplace:=hs+copy(s,last+1,length(s)-last);
+end;
+
+
+
+constructor TMessage.Init(n:longint;const idxmax:array of longint);
+var
+ i,j : longint;
+begin
+ msgtxt:=nil;
+ has_local_changes:=false;
+ msgsize:=0;
+ msgparts:=n;
+ if n<>high(idxmax)+1 then
+ fail;
+ for i:=1 to n do
+ begin
+ msgidxmax[i]:=idxmax[i-1];
+ { create array of msgidx }
+ getmem(msgidx[i],msgidxmax[i]*sizeof(pointer));
+ fillchar(msgidx[i]^,msgidxmax[i]*sizeof(pointer),0);
+ { create array of states }
+ getmem(msgstates[i],msgidxmax[i]*sizeof(tmsgstate));
+ { default value for msgstate is ms_on_global }
+ for j:=0 to msgidxmax[i]-1 do
+ msgstates[i]^[j]:=ms_on_global;
+ end;
+end;
+
+
+destructor TMessage.Done;
+var
+ i : longint;
+begin
+ for i:=1 to msgparts do
+ begin
+ freemem(msgidx[i],msgidxmax[i]*sizeof(pointer));
+ freemem(msgstates[i],msgidxmax[i]*sizeof(tmsgstate));
+ end;
+ if msgallocsize>0 then
+ begin
+ freemem(msgtxt,msgsize);
+ msgallocsize:=0;
+ end;
+ msgtxt:=nil;
+ msgsize:=0;
+ msgparts:=0;
+end;
+
+
+function TMessage.LoadIntern(p:pointer;n:longint):boolean;
+begin
+ msgtxt:=pchar(p);
+ msgsize:=n;
+ msgallocsize:=0;
+ msgintern:=true;
+ ClearIdx;
+ CreateIdx;
+ LoadIntern:=true;
+end;
+
+
+function TMessage.LoadExtern(const fn:string):boolean;
+const
+ bufsize=8192;
+var
+ f : text;
+ error,multiline : boolean;
+ line,i,j : longint;
+ ptxt : pchar;
+ s,s1 : string;
+ buf : pointer;
+
+ procedure err(const msgstr:TMsgStr);
+ begin
+ writeln('*** PPC, file ',fn,', error in line ',line,': ',msgstr);
+ error:=true;
+ end;
+
+begin
+ LoadExtern:=false;
+ getmem(buf,bufsize);
+ { Read the message file }
+ assign(f,fn);
+ {$push}{$I-}
+ reset(f);
+ {$pop}
+ if ioresult<>0 then
+ begin
+ WriteLn('*** PPC, can not open message file ',fn);
+ exit;
+ end;
+ settextbuf(f,buf^,bufsize);
+ { First parse the file and count bytes needed }
+ error:=false;
+ line:=0;
+ multiline:=false;
+ msgsize:=0;
+ while not eof(f) do
+ begin
+ readln(f,s);
+ inc(line);
+ if multiline then
+ begin
+ if s=']' then
+ multiline:=false
+ else
+ inc(msgsize,length(s)+1); { +1 for linebreak }
+ end
+ else
+ begin
+ if (s<>'') and not(s[1] in ['#',';','%']) then
+ begin
+ i:=pos('=',s);
+ if i>0 then
+ begin
+ j:=i+1;
+ if not(s[j] in ['0'..'9']) then
+ err('no number found')
+ else
+ begin
+ while (s[j] in ['0'..'9']) do
+ inc(j);
+ end;
+ if j-i-1<>5 then
+ err('number length is not 5');
+ if s[j+1]='[' then
+ begin
+ inc(msgsize,j-i);
+ multiline:=true
+ end
+ else
+ inc(msgsize,length(s)-i+1);
+ end
+ else
+ err('no = found');
+ end;
+ end;
+ end;
+ if multiline then
+ err('still in multiline mode');
+ if error then
+ begin
+ freemem(buf,bufsize);
+ close(f);
+ exit;
+ end;
+ { now read the buffer in mem }
+ msgallocsize:=msgsize;
+ getmem(msgtxt,msgallocsize);
+ ptxt:=msgtxt;
+ reset(f);
+ while not eof(f) do
+ begin
+ readln(f,s);
+ if multiline then
+ begin
+ if s=']' then
+ begin
+ multiline:=false;
+ { overwrite last eol }
+ dec(ptxt);
+ ptxt^:=#0;
+ inc(ptxt);
+ end
+ else
+ begin
+ move(s[1],ptxt^,length(s));
+ inc(ptxt,length(s));
+ ptxt^:=#10;
+ inc(ptxt);
+ end;
+ end
+ else
+ begin
+ if (s<>'') and not(s[1] in ['#',';','%']) then
+ begin
+ i:=pos('=',s);
+ if i>0 then
+ begin
+ j:=i+1;
+ while (s[j] in ['0'..'9']) do
+ inc(j);
+ { multiline start then no txt }
+ if s[j+1]='[' then
+ begin
+ s1:=Copy(s,i+1,j-i);
+ move(s1[1],ptxt^,length(s1));
+ inc(ptxt,length(s1));
+ multiline:=true;
+ end
+ else
+ begin
+ { txt including number }
+ s1:=Copy(s,i+1,255);
+ move(s1[1],ptxt^,length(s1));
+ inc(ptxt,length(s1));
+ ptxt^:=#0;
+ inc(ptxt);
+ end;
+ end;
+ end;
+ end;
+ end;
+ close(f);
+ freemem(buf,bufsize);
+{ now we can create the index, clear if the previous load was also
+ an external file, because those can't be reused }
+ if not msgintern then
+ ClearIdx;
+ CreateIdx;
+{ set that we've loaded an external file }
+ msgintern:=false;
+ LoadExtern:=true;
+end;
+
+
+procedure TMessage.ClearIdx;
+var
+ i : longint;
+begin
+ { clear }
+ for i:=1 to msgparts do
+ fillchar(msgidx[i]^,msgidxmax[i]*sizeof(pointer),0);
+end;
+
+
+procedure TMessage.CreateIdx;
+var
+ hp1,
+ hp,hpend : pchar;
+ code : integer;
+ num : longint;
+ number : string[5];
+ i : longint;
+ numpart,numidx : longint;
+begin
+ { process msgtxt buffer }
+ number:='00000';
+ hp:=msgtxt;
+ hpend:=@msgtxt[msgsize];
+ while (hp<hpend) do
+ begin
+ hp1:=hp;
+ for i:=1 to 5 do
+ begin
+ number[i]:=hp1^;
+ inc(hp1);
+ end;
+ val(number,num,code);
+ numpart:=num div 1000;
+ numidx:=num mod 1000;
+ { check range }
+ if (numpart <= msgparts) and (numidx < msgidxmax[numpart]) then
+ begin
+ { skip _ }
+ inc(hp1);
+ { set default verbosity to off is '-' is found just after the '_' }
+ if hp1^='-' then
+ begin
+ msgstates[numpart]^[numidx]:=ms_off_global;
+ inc(hp1);
+ end;
+ { put the address in the idx, the numbers are already checked }
+ msgidx[numpart]^[numidx]:=hp1;
+ end;
+ { next string }
+ hp:=pchar(@hp[strlen(hp)+1]);
+ end;
+end;
+
+
+function GetMsgLine(var p:pchar):string;
+var
+ i : longint;
+begin
+ i:=0;
+ while not(p^ in [#0,#10]) and (i<256) do
+ begin
+ inc(i);
+ GetMsgLine[i]:=p^;
+ inc(p);
+ end;
+ { skip #10 }
+ if p^=#10 then
+ inc(p);
+ { if #0 then set p to nil }
+ if p^=#0 then
+ p:=nil;
+ { return string }
+ GetMsgLine[0]:=chr(i);
+end;
+
+
+function TMessage.GetPChar(nr:longint):pchar;
+begin
+ if (nr div 1000 < msgparts) and
+ (nr mod 1000 < msgidxmax[nr div 1000]) then
+ GetPChar:=msgidx[nr div 1000]^[nr mod 1000]
+ else
+ GetPChar:='';
+end;
+
+function TMessage.SetVerbosity(nr:longint;newstate:tmsgstate):boolean;
+var
+ i: longint;
+ oldstate : tmsgstate;
+ is_global : boolean;
+begin
+ result:=false;
+ i:=nr div 1000;
+ if (i < low(msgstates)) or
+ (i > msgparts) then
+ exit;
+ if (nr mod 1000 < msgidxmax[i]) then
+ begin
+ is_global:=(ord(newstate) and ms_global_mask) <> 0;
+ oldstate:=msgstates[i]^[nr mod 1000];
+ if not is_global then
+ newstate:= tmsgstate((ord(newstate) and ms_local_mask) or (ord(oldstate) and ms_global_mask));
+ if newstate<>oldstate then
+ has_local_changes:=true;
+ msgstates[i]^[nr mod 1000]:=newstate;
+ result:=true;
+ end;
+end;
+
+{
+function TMessage.ClearVerbosity(nr:longint):boolean;
+begin
+ ClearVerbosity:=SetVerbosity(nr,ms_off);
+end;
+}
+
+function TMessage.Get(nr:longint;const args:array of TMsgStr):ansistring;
+var
+ hp : pchar;
+begin
+ if (nr div 1000 < msgparts) and
+ (nr mod 1000 < msgidxmax[nr div 1000]) then
+ hp:=msgidx[nr div 1000]^[nr mod 1000]
+ else
+ hp:=nil;
+ if hp=nil then
+ Get:='msg nr '+tostr(nr)
+ else
+ Get:=MsgReplace(system.strpas(hp),args);
+end;
+
+procedure TMessage.ResetStates;
+var
+ i,j,glob : longint;
+ state : tmsgstate;
+begin
+ if not has_local_changes then
+ exit;
+ for i:=1 to msgparts do
+ for j:=0 to msgidxmax[i] - 1 do
+ begin
+ state:=msgstates[i]^[j];
+ glob:=(ord(state) and ms_global_mask) shr ms_shift;
+ state:=tmsgstate((glob shl ms_shift) or glob);
+ msgstates[i]^[j]:=state;
+ end;
+ has_local_changes:=false;
+end;
+
+
+end.
diff --git a/closures/compiler/comphook.pas b/closures/compiler/comphook.pas
new file mode 100644
index 0000000000..f6d7323f98
--- /dev/null
+++ b/closures/compiler/comphook.pas
@@ -0,0 +1,408 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ This unit handles the compilerhooks for output to external programs
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit comphook;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+{$IFNDEF USE_FAKE_SYSUTILS}
+ sysutils,
+{$ELSE}
+ fksysutl,
+{$ENDIF}
+ globtype,
+ finput;
+
+Const
+ { Levels }
+ V_None = $0;
+ V_Fatal = $1;
+ V_Error = $2;
+ V_Normal = $4; { doesn't show a text like Error: }
+ V_Warning = $8;
+ V_Note = $10;
+ V_Hint = $20;
+ V_LineInfoMask = $fff;
+ { From here by default no line info }
+ V_Info = $1000;
+ V_Status = $2000;
+ V_Used = $4000;
+ V_Tried = $8000;
+ V_Conditional = $10000;
+ V_Debug = $20000;
+ V_Executable = $40000;
+ V_TimeStamps = $80000;
+ V_LevelMask = $fffffff;
+ V_All = V_LevelMask;
+ V_Default = V_Fatal + V_Error + V_Normal;
+ { Flags }
+ V_LineInfo = $10000000;
+
+const
+ { RHIDE expect gcc like error output }
+ fatalstr : string[20] = 'Fatal:';
+ errorstr : string[20] = 'Error:';
+ warningstr : string[20] = 'Warning:';
+ notestr : string[20] = 'Note:';
+ hintstr : string[20] = 'Hint:';
+
+type
+ PCompilerStatus = ^TCompilerStatus;
+ TCompilerStatus = record
+ { Current status }
+ currentmodule,
+ currentsourcepath,
+ currentsource : string; { filename }
+ currentline,
+ currentcolumn : longint; { current line and column }
+ currentmodulestate : string[20];
+ { Total Status }
+ compiledlines : longint; { the number of lines which are compiled }
+ errorcount,
+ countWarnings,
+ countNotes,
+ countHints : longint; { number of found errors/warnings/notes/hints }
+ codesize,
+ datasize : qword;
+ { program info }
+ isexe,
+ ispackage,
+ islibrary : boolean;
+ { Settings for the output }
+ showmsgnrs : boolean;
+ verbosity : longint;
+ maxerrorcount : longint;
+ errorwarning,
+ errornote,
+ errorhint,
+ skip_error,
+ use_stderr,
+ use_redir,
+ use_bugreport,
+ use_gccoutput,
+ print_source_path : boolean;
+ { Redirection support }
+ redirfile : text;
+ { Special file for bug report }
+ reportbugfile : text;
+ end;
+
+type
+ EControlCAbort=class(Exception)
+ constructor Create;
+ end;
+ ECompilerAbort=class(Exception)
+ constructor Create;
+ end;
+ ECompilerAbortSilent=class(Exception)
+ constructor Create;
+ end;
+
+var
+ status : tcompilerstatus;
+
+{ Default Functions }
+Function def_status:boolean;
+Function def_comment(Level:Longint;const s:ansistring):boolean;
+function def_internalerror(i:longint):boolean;
+function def_CheckVerbosity(v:longint):boolean;
+procedure def_initsymbolinfo;
+procedure def_donesymbolinfo;
+procedure def_extractsymbolinfo;
+function def_openinputfile(const filename: string): tinputfile;
+Function def_getnamedfiletime(Const F : String) : Longint;
+{ Function redirecting for IDE support }
+type
+ tstopprocedure = procedure(err:longint);
+ tstatusfunction = function:boolean;
+ tcommentfunction = function(Level:Longint;const s:ansistring):boolean;
+ tinternalerrorfunction = function(i:longint):boolean;
+ tcheckverbosityfunction = function(i:longint):boolean;
+
+ tinitsymbolinfoproc = procedure;
+ tdonesymbolinfoproc = procedure;
+ textractsymbolinfoproc = procedure;
+ topeninputfilefunc = function(const filename: string): tinputfile;
+ tgetnamedfiletimefunc = function(const filename: string): longint;
+
+const
+ do_status : tstatusfunction = @def_status;
+ do_comment : tcommentfunction = @def_comment;
+ do_internalerror : tinternalerrorfunction = @def_internalerror;
+ do_checkverbosity : tcheckverbosityfunction = @def_checkverbosity;
+
+ do_initsymbolinfo : tinitsymbolinfoproc = @def_initsymbolinfo;
+ do_donesymbolinfo : tdonesymbolinfoproc = @def_donesymbolinfo;
+ do_extractsymbolinfo : textractsymbolinfoproc = @def_extractsymbolinfo;
+ needsymbolinfo : boolean =false;
+
+ do_openinputfile : topeninputfilefunc = @def_openinputfile;
+ do_getnamedfiletime : tgetnamedfiletimefunc = @def_getnamedfiletime;
+
+implementation
+
+ uses
+ cutils, systems, globals
+ ;
+
+{****************************************************************************
+ Helper Routines
+****************************************************************************}
+
+function gccfilename(const s : string) : string;
+var
+ i : longint;
+begin
+ for i:=1to length(s) do
+ begin
+ case s[i] of
+ '\' : gccfilename[i]:='/';
+ 'A'..'Z' : if not (tf_files_case_aware in source_info.flags) and
+ not (tf_files_case_sensitive in source_info.flags) then
+ gccfilename[i]:=chr(ord(s[i])+32)
+ else
+ gccfilename[i]:=s[i];
+ else
+ gccfilename[i]:=s[i];
+ end;
+ end;
+ gccfilename[0]:=s[0];
+end;
+
+
+function tostr(i : longint) : string;
+var
+ hs : string;
+begin
+ str(i,hs);
+ tostr:=hs;
+end;
+
+
+{****************************************************************************
+ Stopping the compiler
+****************************************************************************}
+
+constructor EControlCAbort.Create;
+ begin
+ inherited Create('Ctrl-C Signaled!');
+ end;
+
+
+constructor ECompilerAbort.Create;
+ begin
+ inherited Create('Compilation Aborted');
+ end;
+
+
+constructor ECompilerAbortSilent.Create;
+ begin
+ inherited Create('Compilation Aborted');
+ end;
+
+
+{****************************************************************************
+ Predefined default Handlers
+****************************************************************************}
+
+function def_status:boolean;
+var
+ hstatus : TFPCHeapStatus;
+begin
+ def_status:=false; { never stop }
+{ Status info?, Called every line }
+ if ((status.verbosity and V_Status)<>0) then
+ begin
+ if (status.compiledlines=1) or
+ (status.currentline mod 100=0) then
+ begin
+ if status.currentline>0 then
+ Write(status.currentline,' ');
+ hstatus:=GetFPCHeapStatus;
+ WriteLn(DStr(hstatus.CurrHeapUsed shr 10),'/',DStr(hstatus.CurrHeapSize shr 10),' Kb Used');
+ end;
+ end;
+{$ifdef macos}
+ Yield;
+{$endif}
+end;
+
+
+Function def_comment(Level:Longint;const s:ansistring):boolean;
+const
+ rh_errorstr = 'error:';
+ rh_warningstr = 'warning:';
+var
+ hs : ansistring;
+ hs2 : ansistring;
+begin
+ def_comment:=false; { never stop }
+ hs:='';
+ if not(status.use_gccoutput) then
+ begin
+ if (status.verbosity and Level)=V_Hint then
+ hs:=hintstr;
+ if (status.verbosity and Level)=V_Note then
+ hs:=notestr;
+ if (status.verbosity and Level)=V_Warning then
+ hs:=warningstr;
+ if (status.verbosity and Level)=V_Error then
+ hs:=errorstr;
+ if (status.verbosity and Level)=V_Fatal then
+ hs:=fatalstr;
+ if (status.verbosity and Level)=V_Used then
+ hs:=PadSpace('('+status.currentmodule+')',10);
+ end
+ else
+ begin
+ if (status.verbosity and Level)=V_Hint then
+ hs:=rh_warningstr;
+ if (status.verbosity and Level)=V_Note then
+ hs:=rh_warningstr;
+ if (status.verbosity and Level)=V_Warning then
+ hs:=rh_warningstr;
+ if (status.verbosity and Level)=V_Error then
+ hs:=rh_errorstr;
+ if (status.verbosity and Level)=V_Fatal then
+ hs:=rh_errorstr;
+ end;
+ { Generate line prefix }
+ if ((Level and V_LineInfo)=V_LineInfo) and
+ (status.currentsource<>'') and
+ (status.currentline>0) then
+ begin
+ {$ifndef macos}
+ { Adding the column should not confuse RHIDE,
+ even if it does not yet use it PM
+ but only if it is after error or warning !! PM }
+ if status.currentcolumn>0 then
+ begin
+ if status.use_gccoutput then
+ hs:=gccfilename(status.currentsource)+':'+tostr(status.currentline)+': '+hs+' '+
+ tostr(status.currentcolumn)+': '+s
+ else
+ begin
+ hs:=status.currentsource+'('+tostr(status.currentline)+
+ ','+tostr(status.currentcolumn)+') '+hs+' '+s;
+ end;
+ if status.print_source_path then
+ hs:=status.currentsourcepath+hs;
+ end
+ else
+ begin
+ if status.use_gccoutput then
+ hs:=gccfilename(status.currentsource)+': '+hs+' '+tostr(status.currentline)+': '+s
+ else
+ hs:=status.currentsource+'('+tostr(status.currentline)+') '+hs+' '+s;
+ end;
+ {$else}
+ {MPW style error}
+ if status.currentcolumn>0 then
+ hs:='File "'+status.currentsourcepath+status.currentsource+'"; Line '+tostr(status.currentline)+
+ ' #[' + tostr(status.currentcolumn) + '] ' +hs+' '+s
+ else
+ hs:='File "'+status.currentsourcepath+status.currentsource+'"; Line '+tostr(status.currentline)+' # '+hs+' '+s;
+ {$endif}
+ end
+ else
+ begin
+ if hs<>'' then
+ hs:=hs+' '+s
+ else
+ hs:=s;
+ end;
+ if (status.verbosity and V_TimeStamps)<>0 then
+ begin
+ system.str(getrealtime-starttime:0:3,hs2);
+ hs:='['+hs2+'] '+s;
+ end;
+
+ { Display line }
+ if (Level<>V_None) and
+ ((status.verbosity and (Level and V_LevelMask))=(Level and V_LevelMask)) then
+ begin
+ if status.use_stderr then
+ begin
+ writeln(stderr,hs);
+ flush(stderr);
+ end
+ else
+ begin
+ if status.use_redir then
+ writeln(status.redirfile,hs)
+ else
+ writeln(hs);
+ end;
+ end;
+ { include everything in the bugreport file }
+ if status.use_bugreport then
+ begin
+ Write(status.reportbugfile,hexstr(level,8)+':');
+ Writeln(status.reportbugfile,hs);
+ end;
+end;
+
+
+function def_internalerror(i : longint) : boolean;
+begin
+ do_comment(V_Fatal+V_LineInfo,'Internal error '+tostr(i));
+{$ifdef EXTDEBUG}
+ { Internalerror() and def_internalerror() do not
+ have a stackframe }
+ dump_stack(stdout,get_caller_frame(get_frame));
+{$endif EXTDEBUG}
+ def_internalerror:=true;
+end;
+
+function def_CheckVerbosity(v:longint):boolean;
+begin
+ result:=status.use_bugreport or
+ ((v<>V_None) and
+ ((status.verbosity and (v and V_LevelMask))=(v and V_LevelMask)));
+end;
+
+procedure def_initsymbolinfo;
+begin
+end;
+
+procedure def_donesymbolinfo;
+begin
+end;
+
+procedure def_extractsymbolinfo;
+begin
+end;
+
+function def_openinputfile(const filename: string): tinputfile;
+begin
+ def_openinputfile:=tdosinputfile.create(filename);
+end;
+
+
+Function def_GetNamedFileTime (Const F : String) : Longint;
+begin
+ Result:=FileAge(F);
+end;
+
+end.
diff --git a/closures/compiler/compiler.pas b/closures/compiler/compiler.pas
new file mode 100644
index 0000000000..f30fbc172b
--- /dev/null
+++ b/closures/compiler/compiler.pas
@@ -0,0 +1,372 @@
+{
+ This unit is the interface of the compiler which can be used by
+ external programs to link in the compiler
+
+ Copyright (c) 1998-2005 by Florian Klaempfl
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************}
+
+unit compiler;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+{$ifdef GO32V2}
+ emu387,
+{$endif GO32V2}
+{$ifdef WATCOM}
+ emu387,
+{$endif WATCOM}
+{$IFNDEF USE_FAKE_SYSUTILS}
+ sysutils,math,
+{$ELSE}
+ fksysutl,
+{$ENDIF}
+ verbose,comphook,systems,
+ cutils,cfileutl,cclasses,globals,options,fmodule,parser,symtable,
+ assemble,link,dbgbase,import,export,tokens,pass_1,wpobase,wpo
+ { cpu parameter handling }
+ ,cpupara
+ { procinfo stuff }
+ ,cpupi
+ { cpu codegenerator }
+ ,cgcpu
+{$ifndef NOPASS2}
+ ,cpunode
+{$endif}
+ { cpu targets }
+ ,cputarg
+ { system information for source system }
+ { the information about the target os }
+ { are pulled in by the t_* units }
+{$ifdef amiga}
+ ,i_amiga
+{$endif amiga}
+{$ifdef atari}
+ ,i_atari
+{$endif atari}
+{$ifdef beos}
+ ,i_beos
+{$endif beos}
+{$ifdef fbsd}
+ ,i_fbsd
+{$endif fbsd}
+{$ifdef gba}
+ ,i_gba
+{$endif gba}
+{$ifdef go32v2}
+ ,i_go32v2
+{$endif go32v2}
+{$ifdef linux}
+ ,i_linux
+{$endif linux}
+{$ifdef macos}
+ ,i_macos
+{$endif macos}
+{$ifdef nds}
+ ,i_nds
+{$endif nds}
+{$ifdef nwm}
+ ,i_nwm
+{$endif nwm}
+{$ifdef nwl}
+ ,i_nwl
+{$endif nwm}
+{$ifdef os2}
+ {$ifdef emx}
+ ,i_emx
+ {$else emx}
+ ,i_os2
+ {$endif emx}
+{$endif os2}
+{$ifdef palmos}
+ ,i_palmos
+{$endif palmos}
+{$ifdef solaris}
+ ,i_sunos
+{$endif solaris}
+{$ifdef wdosx}
+ ,i_wdosx
+{$endif wdosx}
+{$ifdef wii}
+ ,i_wii
+{$endif wii}
+{$ifdef win32}
+ ,i_win
+{$endif win32}
+{$ifdef symbian}
+ ,i_symbian
+{$endif symbian}
+{$ifdef nativent}
+ ,i_nativent
+{$endif nativent}
+ ,globtype;
+
+function Compile(const cmd:TCmdStr):longint;
+
+implementation
+
+uses
+ aasmcpu;
+
+{$if defined(EXTDEBUG) or defined(MEMDEBUG)}
+ {$define SHOWUSEDMEM}
+{$endif}
+
+var
+ CompilerInitedAfterArgs,
+ CompilerInited : boolean;
+
+
+{****************************************************************************
+ Compiler
+****************************************************************************}
+
+procedure DoneCompiler;
+begin
+ if not CompilerInited then
+ exit;
+{ Free compiler if args are read }
+ if CompilerInitedAfterArgs then
+ begin
+ CompilerInitedAfterArgs:=false;
+ DoneParser;
+ DoneImport;
+ DoneExport;
+ DoneLinker;
+ DoneAsm;
+ DoneWpo;
+ end;
+{ Free memory for the others }
+ CompilerInited:=false;
+ do_doneSymbolInfo;
+ DoneSymtable;
+ DoneGlobals;
+ DoneFileUtils;
+ donetokens;
+end;
+
+
+procedure InitCompiler(const cmd:TCmdStr);
+begin
+ if CompilerInited then
+ DoneCompiler;
+{ inits which need to be done before the arguments are parsed }
+ InitSystems;
+ { fileutils depends on source_info so it must be after systems }
+ InitFileUtils;
+ { globals depends on source_info so it must be after systems }
+ InitGlobals;
+ { verbose depends on exe_path and must be after globals }
+ InitVerbose;
+ inittokens;
+ IniTSymtable; {Must come before read_arguments, to enable macrosymstack}
+ do_initSymbolInfo;
+ CompilerInited:=true;
+{ this is needed here for the IDE
+ in case of compilation failure
+ at the previous compile }
+ set_current_module(nil);
+{ read the arguments }
+ read_arguments(cmd);
+{ inits which depend on arguments }
+ InitParser;
+ InitImport;
+ InitExport;
+ InitLinker;
+ InitAsm;
+ InitWpo;
+
+ CompilerInitedAfterArgs:=true;
+end;
+
+
+function Compile(const cmd:TCmdStr):longint;
+
+{$maxfpuregisters 0}
+
+ procedure writepathlist(w:longint;l:TSearchPathList);
+ var
+ hp : TCmdStrListItem;
+ begin
+ hp:=TCmdStrListItem(l.first);
+ while assigned(hp) do
+ begin
+ Message1(w,hp.str);
+ hp:=TCmdStrListItem(hp.next);
+ end;
+ end;
+
+var
+ timestr : string[20];
+ linkstr : string[64];
+{$ifdef SHOWUSEDMEM}
+ hstatus : TFPCHeapStatus;
+{$endif SHOWUSEDMEM}
+ ExceptionMask : TFPUExceptionMask;
+ totaltime : real;
+begin
+ try
+ try
+ ExceptionMask:=GetExceptionMask;
+ SetExceptionMask([exInvalidOp, exDenormalized, exZeroDivide,
+ exOverflow, exUnderflow, exPrecision]);
+
+ starttime:=getrealtime;
+
+ { Initialize the compiler }
+ InitCompiler(cmd);
+
+ { show some info }
+ Message1(general_t_compilername,FixFileName(system.paramstr(0)));
+ Message1(general_d_sourceos,source_info.name);
+ Message1(general_i_targetos,target_info.name);
+ Message1(general_t_exepath,exepath);
+ WritePathList(general_t_unitpath,unitsearchpath);
+ WritePathList(general_t_includepath,includesearchpath);
+ WritePathList(general_t_librarypath,librarysearchpath);
+ WritePathList(general_t_objectpath,objectsearchpath);
+
+ { Compile the program }
+ {$ifdef PREPROCWRITE}
+ if parapreprocess then
+ parser.preprocess(inputfilepath+inputfilename)
+ else
+ {$endif PREPROCWRITE}
+ parser.compile(inputfilepath+inputfilename);
+
+ { Show statistics }
+ if status.errorcount=0 then
+ begin
+ totaltime:=getrealtime-starttime;
+ if totaltime<0 then
+ totaltime:=totaltime+3600.0*24.0;
+ timestr:=tostr(trunc(totaltime))+'.'+tostr(round(frac(totaltime)*10));
+ if status.codesize<>aword(-1) then
+ linkstr:=', '+tostr(status.codesize)+' ' +strpas(MessagePChar(general_text_bytes_code))+', '+tostr(status.datasize)+' '+strpas(MessagePChar(general_text_bytes_data))
+ else
+ linkstr:='';
+ Message3(general_i_abslines_compiled,tostr(status.compiledlines),timestr,linkstr);
+ if (Status.Verbosity and V_Warning = V_Warning) and
+ (Status.CountWarnings <> 0) then
+ Message1 (general_i_number_of_warnings, tostr (Status.CountWarnings));
+ if (Status.Verbosity and V_Hint = V_Hint) and
+ (Status.CountHints <> 0) then
+ Message1 (general_i_number_of_hints, tostr (Status.CountHints));
+ if (Status.Verbosity and V_Note = V_Note) and
+ (Status.CountNotes <> 0) then
+ Message1 (general_i_number_of_notes, tostr (Status.CountNotes));
+ end;
+ finally
+ { no message possible after this !! }
+ DoneCompiler;
+
+ SetExceptionMask(ExceptionMask);
+ end;
+ DoneVerbose;
+ except
+ on EControlCAbort do
+ begin
+ try
+ { in case of 50 errors, this could cause another exception,
+ suppress this exception
+ }
+ Message(general_f_compilation_aborted);
+ except
+ on ECompilerAbort do
+ ;
+ end;
+ DoneVerbose;
+ end;
+ on ECompilerAbort do
+ begin
+ try
+ { in case of 50 errors, this could cause another exception,
+ suppress this exception
+ }
+ Message(general_f_compilation_aborted);
+ except
+ on ECompilerAbort do
+ ;
+ end;
+ DoneVerbose;
+ end;
+ on ECompilerAbortSilent do
+ begin
+ DoneVerbose;
+ end;
+ on EOutOfMemory do
+ begin
+ try
+ Message(general_f_no_memory_left);
+ except
+ on ECompilerAbort do
+ ;
+ end;
+ DoneVerbose;
+ end;
+ on e : EInOutError do
+ begin
+ try
+ Message1(general_f_ioerror,e.message);
+ except
+ on ECompilerAbort do
+ ;
+ end;
+ DoneVerbose;
+ end;
+ on e : EOSError do
+ begin
+ try
+ Message1(general_f_oserror,e.message);
+ except
+ on ECompilerAbort do
+ ;
+ end;
+ DoneVerbose;
+ end;
+ on Exception do
+ begin
+ { General catchall, normally not used }
+ try
+ { in case of 50 errors, this could cause another exception,
+ suppress this exception
+ }
+ Message(general_f_compilation_aborted);
+ except
+ on ECompilerAbort do
+ ;
+ end;
+ DoneVerbose;
+ Raise;
+ end;
+ end;
+{$ifdef SHOWUSEDMEM}
+ hstatus:=GetFPCHeapStatus;
+ Writeln('Max Memory used/heapsize: ',DStr(hstatus.MaxHeapUsed shr 10),'/',DStr(hstatus.MaxHeapSize shr 10),' Kb');
+{$endif SHOWUSEDMEM}
+
+ { Set the return value if an error has occurred }
+ if status.errorcount=0 then
+ result:=0
+ else
+ result:=1;
+end;
+
+end.
diff --git a/closures/compiler/compinnr.inc b/closures/compiler/compinnr.inc
new file mode 100644
index 0000000000..ae13aea213
--- /dev/null
+++ b/closures/compiler/compinnr.inc
@@ -0,0 +1,128 @@
+{
+ This file is part of the Free Pascal run time library and compiler.
+ Copyright (c) 1998-2002 by the Free Pascal development team
+
+ Internal Function/Constant Evaluator numbers
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+const
+{ Internal functions }
+ in_lo_word = 1;
+ in_hi_word = 2;
+ in_lo_long = 3;
+ in_hi_long = 4;
+ in_ord_x = 5;
+ in_length_x = 6;
+ in_chr_byte = 7;
+ in_write_x = 14;
+ in_writeln_x = 15;
+ in_read_x = 16;
+ in_readln_x = 17;
+ in_concat_x = 18;
+ in_assigned_x = 19;
+ in_str_x_string = 20;
+ in_ofs_x = 21;
+ in_sizeof_x = 22;
+ in_typeof_x = 23;
+ in_val_x = 24;
+ in_reset_x = 25;
+ in_rewrite_x = 26;
+ in_low_x = 27;
+ in_high_x = 28;
+ in_seg_x = 29;
+ in_pred_x = 30;
+ in_succ_x = 31;
+ in_reset_typedfile = 32;
+ in_rewrite_typedfile = 33;
+ in_settextbuf_file_x = 34;
+ in_inc_x = 35;
+ in_dec_x = 36;
+ in_include_x_y = 37;
+ in_exclude_x_y = 38;
+ in_break = 39;
+ in_continue = 40;
+ in_assert_x_y = 41;
+ in_addr_x = 42;
+ in_typeinfo_x = 43;
+ in_setlength_x = 44;
+ in_finalize_x = 45;
+ in_new_x = 46;
+ in_dispose_x = 47;
+ in_exit = 48;
+ in_copy_x = 49;
+ in_initialize_x = 50;
+ in_leave = 51; {macpas}
+ in_cycle = 52; {macpas}
+ in_slice_x = 53;
+ in_unaligned_x = 54;
+ in_get_frame = 56;
+ in_get_caller_addr = 57;
+ in_get_caller_frame = 58;
+ in_pack_x_y_z = 59;
+ in_unpack_x_y_z = 60;
+ in_bitsizeof_x = 61;
+ in_writestr_x = 62;
+ in_readstr_x = 63;
+ in_abs_long = 64;
+ in_ror_x = 65;
+ in_ror_x_y = 66;
+ in_rol_x = 67;
+ in_rol_x_y = 68;
+ in_objc_selector_x = 69;
+ in_objc_protocol_x = 70;
+ in_objc_encode_x = 71;
+ in_sar_x_y = 72;
+ in_sar_x = 73;
+ in_bsf_x = 74;
+ in_bsr_x = 75;
+
+{ Internal constant functions }
+ in_const_sqr = 100;
+ in_const_abs = 101;
+ in_const_odd = 102;
+ in_const_ptr = 103;
+ in_const_swap_word = 104;
+ in_const_swap_long = 105;
+ in_lo_qword = 106;
+ in_hi_qword = 107;
+ in_const_swap_qword = 108;
+ in_prefetch_var = 109;
+
+{ FPU functions }
+ in_trunc_real = 120;
+ in_round_real = 121;
+ in_frac_real = 122;
+ in_int_real = 123;
+ in_exp_real = 124;
+ in_cos_real = 125;
+ in_pi_real = 126;
+ in_abs_real = 127;
+ in_sqr_real = 128;
+ in_sqrt_real = 129;
+ in_arctan_real = 130;
+ in_ln_real = 131;
+ in_sin_real = 132;
+
+{ MMX functions }
+ { these contants are used by the mmx unit }
+
+ { MMX }
+ in_mmx_pcmpeqb = 200;
+ in_mmx_pcmpeqw = 201;
+ in_mmx_pcmpeqd = 202;
+ in_mmx_pcmpgtb = 203;
+ in_mmx_pcmpgtw = 204;
+ in_mmx_pcmpgtd = 205;
+
+ { 3DNow }
+
+ { SSE }
+
diff --git a/closures/compiler/comprsrc.pas b/closures/compiler/comprsrc.pas
new file mode 100644
index 0000000000..8988263bf0
--- /dev/null
+++ b/closures/compiler/comprsrc.pas
@@ -0,0 +1,523 @@
+{
+ Copyright (c) 1998-2008 by Florian Klaempfl
+
+ Handles the resource files handling
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit comprsrc;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ Systems, cstreams, Script;
+
+type
+ tresoutput = (roRES, roOBJ);
+
+ tresourcefile = class(TAbstractResourceFile)
+ private
+ fname : ansistring;
+ protected
+ function SetupCompilerArguments(output: tresoutput; const OutName :
+ ansistring; respath: ansistring; out ObjUsed : boolean) : ansistring; virtual;
+ public
+ constructor Create(const fn : ansistring);override;
+ function Compile(output: tresoutput; const OutName: ansistring) : boolean; virtual;
+ procedure PostProcessResourcefile(const s : ansistring);virtual;
+ function IsCompiled(const fn : ansistring) : boolean;virtual;
+ procedure Collect(const fn : ansistring);virtual;
+ procedure EndCollect; virtual;
+ end;
+
+ TWinLikeResourceFile = class(tresourcefile)
+ private
+ fResScript : TScript;
+ fScriptName : ansistring;
+ fCollectCount : integer;
+ protected
+ function SetupCompilerArguments(output: tresoutput; const OutName :
+ ansistring; respath: ansistring; out ObjUsed : boolean) : ansistring; override;
+ public
+ constructor Create(const fn : ansistring);override;
+ destructor Destroy; override;
+ function Compile(output: tresoutput; const OutName: ansistring) : boolean; override;
+ function IsCompiled(const fn : ansistring) : boolean;override;
+ procedure Collect(const fn : ansistring);override;
+ procedure EndCollect; override;
+ end;
+
+procedure CompileResourceFiles;
+procedure CollectResourceFiles;
+
+Var
+ ResCompiler : String;
+ RCCompiler : String;
+
+implementation
+
+uses
+ SysUtils,
+ cutils,cfileutl,cclasses,
+ Globtype,Globals,Verbose,Fmodule, comphook,cpuinfo;
+
+{****************************************************************************
+ TRESOURCEFILE
+****************************************************************************}
+
+constructor tresourcefile.create(const fn : ansistring);
+begin
+ fname:=fn;
+end;
+
+
+procedure tresourcefile.PostProcessResourcefile(const s : ansistring);
+begin
+end;
+
+
+function tresourcefile.IsCompiled(const fn: ansistring): boolean;
+begin
+ Result:=CompareText(ExtractFileExt(fn), target_info.resobjext) = 0;
+end;
+
+procedure tresourcefile.Collect(const fn: ansistring);
+begin
+ if fn='' then
+ exit;
+ fname:=fn;
+ Compile(roOBJ, ChangeFileExt(fn, target_info.resobjext));
+end;
+
+procedure tresourcefile.EndCollect;
+begin
+
+end;
+
+function tresourcefile.SetupCompilerArguments(output: tresoutput; const OutName
+ : ansistring; respath: ansistring; out ObjUsed : boolean) : ansistring;
+var
+ s : TCmdStr;
+begin
+ if output=roRES then
+ begin
+ s:=target_res.rccmd;
+ Replace(s,'$RES',maybequoted(OutName));
+ Replace(s,'$RC',maybequoted(fname));
+ ObjUsed:=False;
+ end
+ else
+ begin
+ s:=target_res.rescmd;
+ ObjUsed:=(pos('$OBJ',s)>0);
+ Replace(s,'$OBJ',maybequoted(OutName));
+ Replace(s,'$RES',maybequoted(fname));
+ end;
+ Result:=s;
+end;
+
+function tresourcefile.compile(output: tresoutput; const OutName: ansistring)
+ : boolean;
+
+ Function SelectBin(Const Bin1,Bin2 : String) : String;
+ begin
+ If (Bin1<>'') then
+ SelectBin:=Bin1
+ else
+ SelectBin:=Bin2;
+ end;
+
+var
+ respath,
+ s,
+ bin,
+ resbin : TCmdStr;
+ resfound,
+ objused : boolean;
+begin
+ Result:=true;
+ if output=roRES then
+ Bin:=SelectBin(RCCompiler,target_res.rcbin)
+ else
+ Bin:=SelectBin(ResCompiler,target_res.resbin);
+ if bin='' then
+ begin
+ Result:=false;
+ exit;
+ end;
+ resfound:=false;
+ if utilsdirectory<>'' then
+ resfound:=FindFile(utilsprefix+bin+source_info.exeext,utilsdirectory,false,resbin);
+ if not resfound then
+ begin
+ resfound:=FindExe(utilsprefix+bin,false,resbin);
+ if not resfound and (utilsprefix<>'') and ( (output=roRES) or (Pos('$ARCH', target_res.rescmd)<>0) ) then
+ { Search for resource compiler without utilsprefix, if RC->RES compiler is called }
+ { or RES->OBJ compiler supports different architectures. }
+ resfound:=FindExe(bin,false,resbin);
+ end;
+ { get also the path to be searched for the windres.h }
+ respath:=ExtractFilePath(resbin);
+ if (not resfound) and not(cs_link_nolink in current_settings.globalswitches) then
+ begin
+ Message1(exec_e_res_not_found, utilsprefix+bin+source_info.exeext);
+ current_settings.globalswitches:=current_settings.globalswitches+[cs_link_nolink];
+ Result:=false;
+ end;
+ s:=SetupCompilerArguments(output,OutName,respath,objused);
+{ Execute the command }
+{ Always try to compile resources. but don't complain if cs_link_nolink }
+ if resfound then
+ begin
+ Message1(exec_i_compilingresource,fname);
+ Message2(exec_d_resbin_params,resbin,s);
+ FlushOutput;
+ try
+ if ExecuteProcess(resbin,s) <> 0 then
+ begin
+ if not (cs_link_nolink in current_settings.globalswitches) then
+ Message(exec_e_error_while_compiling_resources);
+ current_settings.globalswitches:=current_settings.globalswitches+[cs_link_nolink];
+ Result:=false;
+ end;
+ except
+ on E:EOSError do
+ begin
+ if not (cs_link_nolink in current_settings.globalswitches) then
+ Message1(exec_e_cant_call_resource_compiler, resbin);
+ current_settings.globalswitches:=current_settings.globalswitches+[cs_link_nolink];
+ Result:=false;
+ end
+ end;
+ end;
+ { Update asmres when externmode is set and resource compiling failed }
+ if (not Result) and (cs_link_nolink in current_settings.globalswitches) then
+ AsmRes.AddLinkCommand(resbin,s,OutName);
+ if Result and (output=roOBJ) and ObjUsed then
+ current_module.linkunitofiles.add(OutName,link_always);
+end;
+
+constructor TWinLikeResourceFile.Create(const fn : ansistring);
+begin
+ inherited Create(fn);
+ fResScript:=nil;
+ fCollectCount:=0;
+ if (tf_use_8_3 in target_info.flags) then
+ fScriptName:=ChangeFileExt(fn,'.rls')
+ else
+ fScriptName:=ChangeFileExt(fn,'.reslst');
+end;
+
+destructor TWinLikeResourceFile.Destroy;
+begin
+ if fResScript<>nil then
+ fResScript.Free;
+ inherited;
+end;
+
+function TWinLikeResourceFile.SetupCompilerArguments(output: tresoutput; const
+ OutName : ansistring; respath : ansistring; out ObjUsed : boolean) : ansistring;
+var
+ srcfilepath,
+ preprocessorbin,
+ s : TCmdStr;
+ arch,
+ subarch: ansistring;
+
+ function WindresFileName(filename: TCmdStr): TCmdStr;
+ // to be on the safe side, for files that are passed to the preprocessor,
+ // only give short file names with forward slashes to windres
+ var
+ i: longint;
+ begin
+ Result := GetShortName(filename);
+ for I:=1 to Length(Result) do
+ if Result[I] in AllowDirectorySeparators then
+ Result[i]:='/';
+ end;
+
+begin
+ srcfilepath:=ExtractFilePath(current_module.mainsource^);
+ if output=roRES then
+ begin
+ s:=target_res.rccmd;
+ if target_res.rcbin = 'windres' then
+ Replace(s,'$RC',WindresFileName(fname))
+ else
+ Replace(s,'$RC',maybequoted(fname));
+ Replace(s,'$RES',maybequoted(OutName));
+ ObjUsed:=False;
+ end
+ else
+ begin
+ s:=target_res.rescmd;
+ if (res_external_file in target_res.resflags) then
+ ObjUsed:=false
+ else
+ ObjUsed:=(pos('$OBJ',s)>0);
+ Replace(s,'$OBJ',maybequoted(OutName));
+ subarch:='all';
+ arch:=cpu2str[target_cpu];
+ if (source_info.cpu=systems.cpu_arm) then
+ begin
+ //Differentiate between arm and armeb
+ if (source_info.endian=endian_big) then
+ arch:=arch+'eb';
+ end;
+ Replace(s,'$ARCH',arch);
+ if target_info.system=system_arm_darwin then
+ subarch:=lower(cputypestr[current_settings.cputype]);
+ Replace(s,'$SUBARCH',subarch);
+ case target_info.endian of
+ endian_little : Replace(s,'$ENDIAN','littleendian');
+ endian_big : Replace(s,'$ENDIAN','bigendian');
+ end;
+ //call resource compiler with debug switch
+ if (status.verbosity and V_Debug)<>0 then
+ Replace(s,'$DBG','-v')
+ else
+ Replace(s,'$DBG','');
+ if fCollectCount=0 then
+ s:=s+' '+maybequoted(fname)
+ else
+ s:=s+' '+maybequoted('@'+fScriptName);
+ end;
+ { windres doesn't like empty include paths }
+ if respath='' then
+ respath:='.';
+ Replace(s,'$INC',maybequoted(respath));
+ if (output=roRes) and (target_res.rcbin='windres') then
+ begin
+ { try to find a preprocessor }
+ preprocessorbin := respath+'cpp'+source_info.exeext;
+ if FileExists(preprocessorbin,true) then
+ s:='--preprocessor='+preprocessorbin+' '+s;
+ if (srcfilepath<>'') then
+ s:='--include '+WindresFileName(srcfilepath)+' '+s;
+ end;
+ Result:=s;
+end;
+
+function TWinLikeResourceFile.compile(output: tresoutput;
+ const OutName: ansistring) : boolean;
+begin
+ Result:=inherited compile(output,OutName);
+ //delete fpc-res.lst file if things went well
+ if Result and (output=roOBJ) then
+ DeleteFile(fScriptName);
+end;
+
+function TWinLikeResourceFile.IsCompiled(const fn: ansistring): boolean;
+const
+ ResSignature : array [1..32] of byte =
+ ($00,$00,$00,$00,$20,$00,$00,$00,$FF,$FF,$00,$00,$FF,$FF,$00,$00,
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00);
+ knownexts : array[1..4] of string[4] = ('.lfm', '.dfm', '.xfm', '.tlb');
+var
+ f : file;
+ oldfmode : byte;
+ buf: array[1..32] of byte;
+ i: longint;
+ ext : shortstring;
+begin
+ ext:=lower(ExtractFileExt(fn));
+ Result:=CompareText(ext, target_info.resext) = 0;
+ if not Result then
+ for i:=1 to high(knownexts) do
+ begin
+ Result:=CompareText(ext, knownexts[i]) = 0;
+ if Result then break;
+ end;
+
+ if Result or not FileExists(fn, False) then exit;
+ oldfmode:=Filemode;
+ Filemode:=0;
+ assign(f,fn);
+ reset(f,1);
+ BlockRead(f, buf, SizeOf(buf), i);
+ close(f);
+ Filemode:=oldfmode;
+
+ if i<>SizeOf(buf) then
+ exit;
+
+ for i:=1 to 32 do
+ if buf[i]<>ResSignature[i] then
+ exit;
+
+ Result:=True;
+end;
+
+procedure TWinLikeResourceFile.Collect(const fn: ansistring);
+begin
+ if fResScript=nil then
+ fResScript:=TScript.Create(fScriptName);
+ fResScript.Add(MaybeQuoted(fn));
+ inc(fCollectCount);
+end;
+
+procedure TWinLikeResourceFile.EndCollect;
+begin
+ if fResScript<>nil then
+ begin
+ fResScript.WriteToDisk;
+ FreeAndNil(fResScript);
+ Compile(roOBJ,ChangeFileExt(fname,target_info.resobjext));
+ end;
+end;
+
+
+function CopyResFile(inf,outf : TCmdStr) : boolean;
+var
+ src,dst : TCCustomFileStream;
+begin
+ { Copy .res file to units output dir. }
+ Result:=false;
+ src:=CFileStreamClass.Create(inf,fmOpenRead or fmShareDenyNone);
+ if CStreamError<>0 then
+ begin
+ Message1(exec_e_cant_open_resource_file, src.FileName);
+ Include(current_settings.globalswitches, cs_link_nolink);
+ exit;
+ end;
+ dst:=CFileStreamClass.Create(current_module.outputpath^+outf,fmCreate);
+ if CStreamError<>0 then
+ begin
+ Message1(exec_e_cant_write_resource_file, dst.FileName);
+ Include(current_settings.globalswitches, cs_link_nolink);
+ exit;
+ end;
+ dst.CopyFrom(src,src.Size);
+ dst.Free;
+ src.Free;
+ Result:=true;
+end;
+
+procedure CompileResourceFiles;
+var
+ resourcefile : tresourcefile;
+ res: TCmdStrListItem;
+ p,s : TCmdStr;
+ outfmt : tresoutput;
+begin
+ { Don't do anything for systems supporting resources without using resource
+ file classes (e.g. Mac OS). They process resources elsewhere. }
+ if (target_info.res<>res_none) and (target_res.resourcefileclass=nil) then
+ exit;
+
+ p:=ExtractFilePath(ExpandFileName(current_module.mainsource^));
+ res:=TCmdStrListItem(current_module.ResourceFiles.First);
+ while res<>nil do
+ begin
+ if target_info.res=res_none then
+ Message(scan_e_resourcefiles_not_supported);
+ s:=res.FPStr;
+ if not path_absolute(s) then
+ s:=p+s;
+ if not FileExists(s, True) then
+ begin
+ Message1(exec_e_cant_open_resource_file, s);
+ Include(current_settings.globalswitches, cs_link_nolink);
+ exit;
+ end;
+ resourcefile:=TResourceFile(resinfos[target_info.res]^.resourcefileclass.create(s));
+ if resourcefile.IsCompiled(s) then
+ begin
+ resourcefile.free;
+ if AnsiCompareFileName(IncludeTrailingPathDelimiter(ExpandFileName(current_module.outputpath^)), p) <> 0 then
+ begin
+ { Copy .res file to units output dir. Otherwise .res file will not be found
+ when only compiled units path is available }
+ res.FPStr:=ExtractFileName(res.FPStr); //store file name only in PPU.
+ if not CopyResFile(s,res.FPStr) then exit;
+ end;
+ end
+ else
+ begin
+ res.FPStr:=ExtractFileName(res.FPStr);
+ if (target_res.rcbin='') and (RCCompiler='') then
+ begin
+ { if target does not have .rc to .res compiler, create obj }
+ outfmt:=roOBJ;
+ res.FPStr:=ChangeFileExt(res.FPStr,target_info.resobjext);
+ end
+ else
+ begin
+ outfmt:=roRES;
+ res.FPStr:=ChangeFileExt(res.FPStr,target_info.resext);
+ end;
+ resourcefile.compile(outfmt, current_module.outputpath^+res.FPStr);
+ resourcefile.free;
+ end;
+ res:=TCmdStrListItem(res.Next);
+ end;
+end;
+
+
+procedure CollectResourceFiles;
+var
+ resourcefile : tresourcefile;
+
+ procedure ProcessModule(u : tmodule);
+ var
+ res : TCmdStrListItem;
+ s : TCmdStr;
+ begin
+ res:=TCmdStrListItem(u.ResourceFiles.First);
+ while assigned(res) do
+ begin
+ if path_absolute(res.FPStr) then
+ s:=res.FPStr
+ else
+ begin
+ s:=u.path^+res.FPStr;
+ if not FileExists(s,True) then
+ s:=u.outputpath^+res.FPStr;
+ end;
+ resourcefile.Collect(s);
+ res:=TCmdStrListItem(res.Next);
+ end;
+ end;
+
+var
+ hp : tused_unit;
+ s : TCmdStr;
+begin
+ if (target_info.res=res_none) or ((target_res.resbin='')
+ and (ResCompiler='')) then
+ exit;
+// if cs_link_nolink in current_settings.globalswitches then
+// exit;
+ s:=ChangeFileExt(current_module.ppufilename^,target_info.resobjext);
+ if (res_arch_in_file_name in target_res.resflags) then
+ s:=ChangeFileExt(s,'.'+cpu2str[target_cpu]+target_info.resobjext);
+ resourcefile:=TResourceFile(resinfos[target_info.res]^.resourcefileclass.create(s));
+ hp:=tused_unit(usedunits.first);
+ while assigned(hp) do
+ begin
+ ProcessModule(hp.u);
+ hp:=tused_unit(hp.next);
+ end;
+ ProcessModule(current_module);
+ { Finish collection }
+ resourcefile.EndCollect;
+ resourcefile.free;
+end;
+
+end.
diff --git a/closures/compiler/constexp.pas b/closures/compiler/constexp.pas
new file mode 100644
index 0000000000..95ddd7a28a
--- /dev/null
+++ b/closures/compiler/constexp.pas
@@ -0,0 +1,585 @@
+{
+ Copyright (c) 2007 by Daniel Mantione
+
+ This unit implements a Tconstexprint type. This type simulates an integer
+ type that can handle numbers from low(int64) to high(qword) calculations.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit constexp;
+
+{$i fpcdefs.inc}
+
+interface
+
+{ bootstrapping with 2.0.x }
+{$ifdef VER2_0}
+ {$Q-}
+ {$R-}
+{$endif}
+
+
+type Tconstexprint=record
+ overflow:boolean;
+ case signed:boolean of
+ false:
+ (uvalue:qword);
+ true:
+ (svalue:int64);
+ end;
+
+ Tconststring = type pchar;
+
+ errorproc=procedure (i:longint);
+
+{"Uses verbose" gives a dependency on cpuinfo through globals. This leads
+ build trouble when compiling the directory utils, since the cpu directory
+ isn't searched there. Therefore we use a procvar and make verbose install
+ the errorhandler. A dependency from verbose on this unit is no problem.}
+var internalerror:errorproc;
+
+{Same issue, avoid dependency on cpuinfo because the cpu directory isn't
+ searched during utils building.}
+{$ifdef GENERIC_CPU}
+type bestreal=extended;
+{$else}
+{$ifdef x86}
+type bestreal=extended;
+{$else}
+type bestreal=double;
+{$endif}
+{$endif}
+
+operator := (const u:qword):Tconstexprint;inline;
+operator := (const s:int64):Tconstexprint;inline;
+operator := (const c:Tconstexprint):qword;
+operator := (const c:Tconstexprint):int64;
+operator := (const c:Tconstexprint):bestreal;
+
+operator + (const a,b:Tconstexprint):Tconstexprint;
+operator - (const a,b:Tconstexprint):Tconstexprint;
+operator - (const a:Tconstexprint):Tconstexprint;
+operator * (const a,b:Tconstexprint):Tconstexprint;
+operator div (const a,b:Tconstexprint):Tconstexprint;
+operator mod (const a,b:Tconstexprint):Tconstexprint;
+operator / (const a,b:Tconstexprint):bestreal;
+
+operator = (const a,b:Tconstexprint):boolean;
+operator > (const a,b:Tconstexprint):boolean;
+operator >= (const a,b:Tconstexprint):boolean;
+operator < (const a,b:Tconstexprint):boolean;
+operator <= (const a,b:Tconstexprint):boolean;
+
+operator and (const a,b:Tconstexprint):Tconstexprint;
+operator or (const a,b:Tconstexprint):Tconstexprint;
+operator xor (const a,b:Tconstexprint):Tconstexprint;
+operator shl (const a,b:Tconstexprint):Tconstexprint;
+operator shr (const a,b:Tconstexprint):Tconstexprint;
+
+function tostr(const i:Tconstexprint):shortstring;overload;
+
+{****************************************************************************}
+implementation
+{****************************************************************************}
+
+
+
+operator := (const u:qword):Tconstexprint;
+
+begin
+ result.overflow:=false;
+ result.signed:=false;
+ result.uvalue:=u;
+end;
+
+operator := (const s:int64):Tconstexprint;
+
+begin
+ result.overflow:=false;
+ result.signed:=true;
+ result.svalue:=s;
+end;
+
+operator := (const c:Tconstexprint):qword;
+
+begin
+ if c.overflow then
+ internalerror(200706091)
+ else if not c.signed then
+ result:=c.uvalue
+ else if c.svalue<0 then
+ internalerror(200706092)
+ else
+ result:=qword(c.svalue);
+end;
+
+operator := (const c:Tconstexprint):int64;
+
+begin
+ if c.overflow then
+ internalerror(200706093)
+ else if c.signed then
+ result:=c.svalue
+ else if c.uvalue>qword(high(int64)) then
+ internalerror(200706094)
+ else
+ result:=int64(c.uvalue);
+end;
+
+operator := (const c:Tconstexprint):bestreal;
+
+begin
+ if c.overflow then
+ internalerror(200706095)
+ else if c.signed then
+ result:=c.svalue
+ else
+ result:=c.uvalue;
+end;
+
+function add_to(const a:Tconstexprint;b:qword):Tconstexprint;
+
+var sspace,uspace:qword;
+
+label try_qword;
+
+begin
+ result.overflow:=false;
+
+ {Try if the result fits in an int64.}
+ if (a.signed) and (a.svalue<0) then
+ {$push}{$Q-}
+ sspace:=qword(high(int64))+qword(-a.svalue)
+ {$pop}
+ else if not a.signed and (a.uvalue>qword(high(int64))) then
+ goto try_qword
+ else
+ sspace:=qword(high(int64))-a.svalue;
+
+ if sspace>=b then
+ begin
+ result.signed:=true;
+ {$push} {$Q-}
+ result.svalue:=a.svalue+int64(b);
+ {$pop}
+ exit;
+ end;
+
+ {Try if the result fits in a qword.}
+try_qword:
+ if (a.signed) and (a.svalue<0) then
+ uspace:=high(qword)-qword(-a.svalue)
+{ else if not a.signed and (a.uvalue>qword(high(int64))) then
+ uspace:=high(qword)-a.uvalue}
+ else
+ uspace:=high(qword)-a.uvalue;
+ if uspace>=b then
+ begin
+ result.signed:=false;
+ {$push} {$Q-}
+ result.uvalue:=a.uvalue+b;
+ {$pop}
+ exit;
+ end;
+ result.overflow:=true;
+end;
+
+function sub_from(const a:Tconstexprint;b:qword):Tconstexprint;
+
+const abs_low_int64=qword(9223372036854775808); {abs(low(int64)) -> overflow error}
+
+var sspace:qword;
+
+label try_qword,ov;
+
+begin
+ result.overflow:=false;
+
+ {Try if the result fits in an int64.}
+ if (a.signed) and (a.svalue<0) then
+ {$push} {$Q-}
+ sspace:=qword(a.svalue)+abs_low_int64
+ {$pop}
+ else if not a.signed and (a.uvalue>qword(high(int64))) then
+ goto try_qword
+ else
+ sspace:=a.uvalue+qword(abs(low(int64)));
+ if sspace>=b then
+ begin
+ result.signed:=true;
+ {$push} {$Q-}
+ result.svalue:=a.svalue-int64(b);
+ {$pop}
+ exit;
+ end;
+
+ {Try if the result fits in a qword.}
+try_qword:
+ if not(a.signed and (a.svalue<0)) and (a.uvalue>=b) then
+ begin
+ result.signed:=false;
+ {$push} {$Q-}
+ result.uvalue:=a.uvalue-b;
+ {$pop}
+ exit;
+ end;
+ov:
+ result.overflow:=true;
+end;
+
+operator + (const a,b:Tconstexprint):Tconstexprint;
+
+begin
+ if a.overflow or b.overflow then
+ begin
+ result.overflow:=true;
+ exit;
+ end;
+ if b.signed and (b.svalue<0) then
+ {$push} {$Q-}
+ result:=sub_from(a,qword(-b.svalue))
+ {$pop}
+ else
+ result:=add_to(a,b.uvalue);
+end;
+
+operator - (const a,b:Tconstexprint):Tconstexprint;
+
+begin
+ if a.overflow or b.overflow then
+ begin
+ result.overflow:=true;
+ exit;
+ end;
+ if b.signed and (b.svalue<0) then
+ {$push} {$Q-}
+ result:=add_to(a,qword(-b.svalue))
+ {$pop}
+ else
+ result:=sub_from(a,b.uvalue);
+end;
+
+operator - (const a:Tconstexprint):Tconstexprint;
+
+begin
+ if not a.signed and (a.uvalue>qword(high(int64))) then
+ result.overflow:=true
+ else
+ begin
+ result.overflow:=false;
+ result.signed:=true;
+ result.svalue:=-a.svalue;
+ end;
+end;
+
+
+operator * (const a,b:Tconstexprint):Tconstexprint;
+
+var aa,bb,r:qword;
+ sa,sb:boolean;
+
+begin
+ if a.overflow or b.overflow then
+ begin
+ result.overflow:=true;
+ exit;
+ end;
+ result.overflow:=false;
+ sa:=a.signed and (a.svalue<0);
+ if sa then
+ aa:=qword(-a.svalue)
+ else
+ aa:=a.uvalue;
+ sb:=b.signed and (b.svalue<0);
+ if sb then
+ bb:=qword(-b.svalue)
+ else
+ bb:=b.uvalue;
+
+ if (bb<>0) and (high(qword) div bb<aa) then
+ result.overflow:=true
+ else
+ begin
+ r:=aa*bb;
+ if sa xor sb then
+ begin
+ result.signed:=true;
+ if r>qword(high(int64)) then
+ result.overflow:=true
+ else
+ result.svalue:=-int64(r);
+ end
+ else
+ begin
+ result.signed:=false;
+ result.uvalue:=r;
+ end;
+ end;
+end;
+
+operator div (const a,b:Tconstexprint):Tconstexprint;
+
+var aa,bb,r:qword;
+ sa,sb:boolean;
+
+begin
+ if a.overflow or b.overflow then
+ begin
+ result.overflow:=true;
+ exit;
+ end;
+ result.overflow:=false;
+ sa:=a.signed and (a.svalue<0);
+ if sa then
+ {$push} {$Q-}
+ aa:=qword(-a.svalue)
+ {$pop}
+ else
+ aa:=a.uvalue;
+ sb:=b.signed and (b.svalue<0);
+ if sb then
+ {$push} {$Q-}
+ bb:=qword(-b.svalue)
+ {$pop}
+ else
+ bb:=b.uvalue;
+
+ if bb=0 then
+ result.overflow:=true
+ else
+ begin
+ r:=aa div bb;
+ if sa xor sb then
+ begin
+ result.signed:=true;
+ if r>qword(high(int64)) then
+ result.overflow:=true
+ else
+ result.svalue:=-int64(r);
+ end
+ else
+ begin
+ result.signed:=false;
+ result.uvalue:=r;
+ end;
+ end;
+end;
+
+operator mod (const a,b:Tconstexprint):Tconstexprint;
+
+var aa,bb,r:qword;
+ sa,sb:boolean;
+
+begin
+ if a.overflow or b.overflow then
+ begin
+ result.overflow:=true;
+ exit;
+ end;
+ result.overflow:=false;
+ sa:=a.signed and (a.svalue<0);
+ if sa then
+ {$push} {$Q-}
+ aa:=qword(-a.svalue)
+ {$pop}
+ else
+ aa:=a.uvalue;
+ sb:=b.signed and (b.svalue<0);
+ if sb then
+ {$push} {$Q-}
+ bb:=qword(-b.svalue)
+ {$pop}
+ else
+ bb:=b.uvalue;
+ if bb=0 then
+ result.overflow:=true
+ else
+ begin
+ { the sign of a modulo operation only depends on the sign of the
+ dividend }
+ r:=aa mod bb;
+ result.signed:=sa;
+ if not sa then
+ result.uvalue:=r
+ else
+ result.svalue:=-int64(r);
+ end;
+end;
+
+operator / (const a,b:Tconstexprint):bestreal;
+
+var aa,bb:bestreal;
+
+begin
+ if a.overflow or b.overflow then
+ internalerror(200706096);
+ if a.signed then
+ aa:=a.svalue
+ else
+ aa:=a.uvalue;
+ if b.signed then
+ bb:=b.svalue
+ else
+ bb:=b.uvalue;
+ result:=aa/bb;
+end;
+
+operator = (const a,b:Tconstexprint):boolean;
+
+begin
+ if a.signed and (a.svalue<0) then
+ if b.signed and (b.svalue<0) then
+ result:=a.svalue=b.svalue
+ else if b.uvalue>qword(high(int64)) then
+ result:=false
+ else
+ result:=a.svalue=b.svalue
+ else
+ if not (b.signed and (b.svalue<0)) then
+ result:=a.uvalue=b.uvalue
+ else if a.uvalue>qword(high(int64)) then
+ result:=false
+ else
+ result:=a.svalue=b.svalue
+end;
+
+operator > (const a,b:Tconstexprint):boolean;
+
+begin
+ if a.signed and (a.svalue<0) then
+ if b.signed and (b.svalue<0) then
+ result:=a.svalue>b.svalue
+ else if b.uvalue>qword(high(int64)) then
+ result:=false
+ else
+ result:=a.svalue>b.svalue
+ else
+ if not (b.signed and (b.svalue<0)) then
+ result:=a.uvalue>b.uvalue
+ else if a.uvalue>qword(high(int64)) then
+ result:=true
+ else
+ result:=a.svalue>b.svalue
+end;
+
+operator >= (const a,b:Tconstexprint):boolean;
+
+begin
+ if a.signed and (a.svalue<0) then
+ if b.signed and (b.svalue<0) then
+ result:=a.svalue>=b.svalue
+ else if b.uvalue>qword(high(int64)) then
+ result:=false
+ else
+ result:=a.svalue>=b.svalue
+ else
+ if not (b.signed and (b.svalue<0)) then
+ result:=a.uvalue>=b.uvalue
+ else if a.uvalue>qword(high(int64)) then
+ result:=true
+ else
+ result:=a.svalue>=b.svalue
+end;
+
+operator < (const a,b:Tconstexprint):boolean;
+
+begin
+ if a.signed and (a.svalue<0) then
+ if b.signed and (b.svalue<0) then
+ result:=a.svalue<b.svalue
+ else if b.uvalue>qword(high(int64)) then
+ result:=true
+ else
+ result:=a.svalue<b.svalue
+ else
+ if not (b.signed and (b.svalue<0)) then
+ result:=a.uvalue<b.uvalue
+ else if a.uvalue>qword(high(int64)) then
+ result:=false
+ else
+ result:=a.svalue<b.svalue
+end;
+
+operator <= (const a,b:Tconstexprint):boolean;
+
+begin
+ if a.signed and (a.svalue<0) then
+ if b.signed and (b.svalue<0) then
+ result:=a.svalue<=b.svalue
+ else if b.uvalue>qword(high(int64)) then
+ result:=true
+ else
+ result:=a.svalue<=b.svalue
+ else
+ if not (b.signed and (b.svalue<0)) then
+ result:=a.uvalue<=b.uvalue
+ else if a.uvalue>qword(high(int64)) then
+ result:=false
+ else
+ result:=a.svalue<=b.svalue
+end;
+
+operator and (const a,b:Tconstexprint):Tconstexprint;
+
+begin
+ result.overflow:=false;
+ result.signed:=a.signed or b.signed;
+ result.uvalue:=a.uvalue and b.uvalue;
+end;
+
+operator or (const a,b:Tconstexprint):Tconstexprint;
+
+begin
+ result.overflow:=false;
+ result.signed:=a.signed or b.signed;
+ result.uvalue:=a.uvalue or b.uvalue;
+end;
+
+operator xor (const a,b:Tconstexprint):Tconstexprint;
+
+begin
+ result.overflow:=false;
+ result.signed:=a.signed or b.signed;
+ result.uvalue:=a.uvalue xor b.uvalue;
+end;
+
+operator shl (const a,b:Tconstexprint):Tconstexprint;
+
+begin
+ result.overflow:=false;
+ result.signed:=a.signed;
+ result.uvalue:=a.uvalue shl b.uvalue;
+end;
+
+operator shr (const a,b:Tconstexprint):Tconstexprint;
+
+begin
+ result.overflow:=false;
+ result.signed:=a.signed;
+ result.uvalue:=a.uvalue shr b.uvalue;
+end;
+
+function tostr(const i:Tconstexprint):shortstring;overload;
+
+begin
+ if i.signed then
+ str(i.svalue,result)
+ else
+ str(i.uvalue,result);
+end;
+
+end.
diff --git a/closures/compiler/cp1251.pas b/closures/compiler/cp1251.pas
new file mode 100644
index 0000000000..c13a667956
--- /dev/null
+++ b/closures/compiler/cp1251.pas
@@ -0,0 +1,282 @@
+{ This is an automatically created file, so don't edit it }
+unit cp1251;
+
+ interface
+
+ implementation
+
+ uses
+ {$if FPC_FULLVERSION<20700}ccharset{$else}charset{$endif};
+
+ const
+ map : array[0..255] of tunicodecharmapping = (
+ (unicode : 0; flag : umf_noinfo; reserved : 0),
+ (unicode : 1; flag : umf_noinfo; reserved : 0),
+ (unicode : 2; flag : umf_noinfo; reserved : 0),
+ (unicode : 3; flag : umf_noinfo; reserved : 0),
+ (unicode : 4; flag : umf_noinfo; reserved : 0),
+ (unicode : 5; flag : umf_noinfo; reserved : 0),
+ (unicode : 6; flag : umf_noinfo; reserved : 0),
+ (unicode : 7; flag : umf_noinfo; reserved : 0),
+ (unicode : 8; flag : umf_noinfo; reserved : 0),
+ (unicode : 9; flag : umf_noinfo; reserved : 0),
+ (unicode : 10; flag : umf_noinfo; reserved : 0),
+ (unicode : 11; flag : umf_noinfo; reserved : 0),
+ (unicode : 12; flag : umf_noinfo; reserved : 0),
+ (unicode : 13; flag : umf_noinfo; reserved : 0),
+ (unicode : 14; flag : umf_noinfo; reserved : 0),
+ (unicode : 15; flag : umf_noinfo; reserved : 0),
+ (unicode : 16; flag : umf_noinfo; reserved : 0),
+ (unicode : 17; flag : umf_noinfo; reserved : 0),
+ (unicode : 18; flag : umf_noinfo; reserved : 0),
+ (unicode : 19; flag : umf_noinfo; reserved : 0),
+ (unicode : 20; flag : umf_noinfo; reserved : 0),
+ (unicode : 21; flag : umf_noinfo; reserved : 0),
+ (unicode : 22; flag : umf_noinfo; reserved : 0),
+ (unicode : 23; flag : umf_noinfo; reserved : 0),
+ (unicode : 24; flag : umf_noinfo; reserved : 0),
+ (unicode : 25; flag : umf_noinfo; reserved : 0),
+ (unicode : 26; flag : umf_noinfo; reserved : 0),
+ (unicode : 27; flag : umf_noinfo; reserved : 0),
+ (unicode : 28; flag : umf_noinfo; reserved : 0),
+ (unicode : 29; flag : umf_noinfo; reserved : 0),
+ (unicode : 30; flag : umf_noinfo; reserved : 0),
+ (unicode : 31; flag : umf_noinfo; reserved : 0),
+ (unicode : 32; flag : umf_noinfo; reserved : 0),
+ (unicode : 33; flag : umf_noinfo; reserved : 0),
+ (unicode : 34; flag : umf_noinfo; reserved : 0),
+ (unicode : 35; flag : umf_noinfo; reserved : 0),
+ (unicode : 36; flag : umf_noinfo; reserved : 0),
+ (unicode : 37; flag : umf_noinfo; reserved : 0),
+ (unicode : 38; flag : umf_noinfo; reserved : 0),
+ (unicode : 39; flag : umf_noinfo; reserved : 0),
+ (unicode : 40; flag : umf_noinfo; reserved : 0),
+ (unicode : 41; flag : umf_noinfo; reserved : 0),
+ (unicode : 42; flag : umf_noinfo; reserved : 0),
+ (unicode : 43; flag : umf_noinfo; reserved : 0),
+ (unicode : 44; flag : umf_noinfo; reserved : 0),
+ (unicode : 45; flag : umf_noinfo; reserved : 0),
+ (unicode : 46; flag : umf_noinfo; reserved : 0),
+ (unicode : 47; flag : umf_noinfo; reserved : 0),
+ (unicode : 48; flag : umf_noinfo; reserved : 0),
+ (unicode : 49; flag : umf_noinfo; reserved : 0),
+ (unicode : 50; flag : umf_noinfo; reserved : 0),
+ (unicode : 51; flag : umf_noinfo; reserved : 0),
+ (unicode : 52; flag : umf_noinfo; reserved : 0),
+ (unicode : 53; flag : umf_noinfo; reserved : 0),
+ (unicode : 54; flag : umf_noinfo; reserved : 0),
+ (unicode : 55; flag : umf_noinfo; reserved : 0),
+ (unicode : 56; flag : umf_noinfo; reserved : 0),
+ (unicode : 57; flag : umf_noinfo; reserved : 0),
+ (unicode : 58; flag : umf_noinfo; reserved : 0),
+ (unicode : 59; flag : umf_noinfo; reserved : 0),
+ (unicode : 60; flag : umf_noinfo; reserved : 0),
+ (unicode : 61; flag : umf_noinfo; reserved : 0),
+ (unicode : 62; flag : umf_noinfo; reserved : 0),
+ (unicode : 63; flag : umf_noinfo; reserved : 0),
+ (unicode : 64; flag : umf_noinfo; reserved : 0),
+ (unicode : 65; flag : umf_noinfo; reserved : 0),
+ (unicode : 66; flag : umf_noinfo; reserved : 0),
+ (unicode : 67; flag : umf_noinfo; reserved : 0),
+ (unicode : 68; flag : umf_noinfo; reserved : 0),
+ (unicode : 69; flag : umf_noinfo; reserved : 0),
+ (unicode : 70; flag : umf_noinfo; reserved : 0),
+ (unicode : 71; flag : umf_noinfo; reserved : 0),
+ (unicode : 72; flag : umf_noinfo; reserved : 0),
+ (unicode : 73; flag : umf_noinfo; reserved : 0),
+ (unicode : 74; flag : umf_noinfo; reserved : 0),
+ (unicode : 75; flag : umf_noinfo; reserved : 0),
+ (unicode : 76; flag : umf_noinfo; reserved : 0),
+ (unicode : 77; flag : umf_noinfo; reserved : 0),
+ (unicode : 78; flag : umf_noinfo; reserved : 0),
+ (unicode : 79; flag : umf_noinfo; reserved : 0),
+ (unicode : 80; flag : umf_noinfo; reserved : 0),
+ (unicode : 81; flag : umf_noinfo; reserved : 0),
+ (unicode : 82; flag : umf_noinfo; reserved : 0),
+ (unicode : 83; flag : umf_noinfo; reserved : 0),
+ (unicode : 84; flag : umf_noinfo; reserved : 0),
+ (unicode : 85; flag : umf_noinfo; reserved : 0),
+ (unicode : 86; flag : umf_noinfo; reserved : 0),
+ (unicode : 87; flag : umf_noinfo; reserved : 0),
+ (unicode : 88; flag : umf_noinfo; reserved : 0),
+ (unicode : 89; flag : umf_noinfo; reserved : 0),
+ (unicode : 90; flag : umf_noinfo; reserved : 0),
+ (unicode : 91; flag : umf_noinfo; reserved : 0),
+ (unicode : 92; flag : umf_noinfo; reserved : 0),
+ (unicode : 93; flag : umf_noinfo; reserved : 0),
+ (unicode : 94; flag : umf_noinfo; reserved : 0),
+ (unicode : 95; flag : umf_noinfo; reserved : 0),
+ (unicode : 96; flag : umf_noinfo; reserved : 0),
+ (unicode : 97; flag : umf_noinfo; reserved : 0),
+ (unicode : 98; flag : umf_noinfo; reserved : 0),
+ (unicode : 99; flag : umf_noinfo; reserved : 0),
+ (unicode : 100; flag : umf_noinfo; reserved : 0),
+ (unicode : 101; flag : umf_noinfo; reserved : 0),
+ (unicode : 102; flag : umf_noinfo; reserved : 0),
+ (unicode : 103; flag : umf_noinfo; reserved : 0),
+ (unicode : 104; flag : umf_noinfo; reserved : 0),
+ (unicode : 105; flag : umf_noinfo; reserved : 0),
+ (unicode : 106; flag : umf_noinfo; reserved : 0),
+ (unicode : 107; flag : umf_noinfo; reserved : 0),
+ (unicode : 108; flag : umf_noinfo; reserved : 0),
+ (unicode : 109; flag : umf_noinfo; reserved : 0),
+ (unicode : 110; flag : umf_noinfo; reserved : 0),
+ (unicode : 111; flag : umf_noinfo; reserved : 0),
+ (unicode : 112; flag : umf_noinfo; reserved : 0),
+ (unicode : 113; flag : umf_noinfo; reserved : 0),
+ (unicode : 114; flag : umf_noinfo; reserved : 0),
+ (unicode : 115; flag : umf_noinfo; reserved : 0),
+ (unicode : 116; flag : umf_noinfo; reserved : 0),
+ (unicode : 117; flag : umf_noinfo; reserved : 0),
+ (unicode : 118; flag : umf_noinfo; reserved : 0),
+ (unicode : 119; flag : umf_noinfo; reserved : 0),
+ (unicode : 120; flag : umf_noinfo; reserved : 0),
+ (unicode : 121; flag : umf_noinfo; reserved : 0),
+ (unicode : 122; flag : umf_noinfo; reserved : 0),
+ (unicode : 123; flag : umf_noinfo; reserved : 0),
+ (unicode : 124; flag : umf_noinfo; reserved : 0),
+ (unicode : 125; flag : umf_noinfo; reserved : 0),
+ (unicode : 126; flag : umf_noinfo; reserved : 0),
+ (unicode : 127; flag : umf_noinfo; reserved : 0),
+ (unicode : 1026; flag : umf_noinfo; reserved : 0),
+ (unicode : 1027; flag : umf_noinfo; reserved : 0),
+ (unicode : 8218; flag : umf_noinfo; reserved : 0),
+ (unicode : 1107; flag : umf_noinfo; reserved : 0),
+ (unicode : 8222; flag : umf_noinfo; reserved : 0),
+ (unicode : 8230; flag : umf_noinfo; reserved : 0),
+ (unicode : 8224; flag : umf_noinfo; reserved : 0),
+ (unicode : 8225; flag : umf_noinfo; reserved : 0),
+ (unicode : 8364; flag : umf_noinfo; reserved : 0),
+ (unicode : 8240; flag : umf_noinfo; reserved : 0),
+ (unicode : 1033; flag : umf_noinfo; reserved : 0),
+ (unicode : 8249; flag : umf_noinfo; reserved : 0),
+ (unicode : 1034; flag : umf_noinfo; reserved : 0),
+ (unicode : 1036; flag : umf_noinfo; reserved : 0),
+ (unicode : 1035; flag : umf_noinfo; reserved : 0),
+ (unicode : 1039; flag : umf_noinfo; reserved : 0),
+ (unicode : 1106; flag : umf_noinfo; reserved : 0),
+ (unicode : 8216; flag : umf_noinfo; reserved : 0),
+ (unicode : 8217; flag : umf_noinfo; reserved : 0),
+ (unicode : 8220; flag : umf_noinfo; reserved : 0),
+ (unicode : 8221; flag : umf_noinfo; reserved : 0),
+ (unicode : 8226; flag : umf_noinfo; reserved : 0),
+ (unicode : 8211; flag : umf_noinfo; reserved : 0),
+ (unicode : 8212; flag : umf_noinfo; reserved : 0),
+ (unicode : 65535; flag : umf_unused; reserved : 0),
+ (unicode : 8482; flag : umf_noinfo; reserved : 0),
+ (unicode : 1113; flag : umf_noinfo; reserved : 0),
+ (unicode : 8250; flag : umf_noinfo; reserved : 0),
+ (unicode : 1114; flag : umf_noinfo; reserved : 0),
+ (unicode : 1116; flag : umf_noinfo; reserved : 0),
+ (unicode : 1115; flag : umf_noinfo; reserved : 0),
+ (unicode : 1119; flag : umf_noinfo; reserved : 0),
+ (unicode : 160; flag : umf_noinfo; reserved : 0),
+ (unicode : 1038; flag : umf_noinfo; reserved : 0),
+ (unicode : 1118; flag : umf_noinfo; reserved : 0),
+ (unicode : 1032; flag : umf_noinfo; reserved : 0),
+ (unicode : 164; flag : umf_noinfo; reserved : 0),
+ (unicode : 1168; flag : umf_noinfo; reserved : 0),
+ (unicode : 166; flag : umf_noinfo; reserved : 0),
+ (unicode : 167; flag : umf_noinfo; reserved : 0),
+ (unicode : 1025; flag : umf_noinfo; reserved : 0),
+ (unicode : 169; flag : umf_noinfo; reserved : 0),
+ (unicode : 1028; flag : umf_noinfo; reserved : 0),
+ (unicode : 171; flag : umf_noinfo; reserved : 0),
+ (unicode : 172; flag : umf_noinfo; reserved : 0),
+ (unicode : 173; flag : umf_noinfo; reserved : 0),
+ (unicode : 174; flag : umf_noinfo; reserved : 0),
+ (unicode : 1031; flag : umf_noinfo; reserved : 0),
+ (unicode : 176; flag : umf_noinfo; reserved : 0),
+ (unicode : 177; flag : umf_noinfo; reserved : 0),
+ (unicode : 1030; flag : umf_noinfo; reserved : 0),
+ (unicode : 1110; flag : umf_noinfo; reserved : 0),
+ (unicode : 1169; flag : umf_noinfo; reserved : 0),
+ (unicode : 181; flag : umf_noinfo; reserved : 0),
+ (unicode : 182; flag : umf_noinfo; reserved : 0),
+ (unicode : 183; flag : umf_noinfo; reserved : 0),
+ (unicode : 1105; flag : umf_noinfo; reserved : 0),
+ (unicode : 8470; flag : umf_noinfo; reserved : 0),
+ (unicode : 1108; flag : umf_noinfo; reserved : 0),
+ (unicode : 187; flag : umf_noinfo; reserved : 0),
+ (unicode : 1112; flag : umf_noinfo; reserved : 0),
+ (unicode : 1029; flag : umf_noinfo; reserved : 0),
+ (unicode : 1109; flag : umf_noinfo; reserved : 0),
+ (unicode : 1111; flag : umf_noinfo; reserved : 0),
+ (unicode : 1040; flag : umf_noinfo; reserved : 0),
+ (unicode : 1041; flag : umf_noinfo; reserved : 0),
+ (unicode : 1042; flag : umf_noinfo; reserved : 0),
+ (unicode : 1043; flag : umf_noinfo; reserved : 0),
+ (unicode : 1044; flag : umf_noinfo; reserved : 0),
+ (unicode : 1045; flag : umf_noinfo; reserved : 0),
+ (unicode : 1046; flag : umf_noinfo; reserved : 0),
+ (unicode : 1047; flag : umf_noinfo; reserved : 0),
+ (unicode : 1048; flag : umf_noinfo; reserved : 0),
+ (unicode : 1049; flag : umf_noinfo; reserved : 0),
+ (unicode : 1050; flag : umf_noinfo; reserved : 0),
+ (unicode : 1051; flag : umf_noinfo; reserved : 0),
+ (unicode : 1052; flag : umf_noinfo; reserved : 0),
+ (unicode : 1053; flag : umf_noinfo; reserved : 0),
+ (unicode : 1054; flag : umf_noinfo; reserved : 0),
+ (unicode : 1055; flag : umf_noinfo; reserved : 0),
+ (unicode : 1056; flag : umf_noinfo; reserved : 0),
+ (unicode : 1057; flag : umf_noinfo; reserved : 0),
+ (unicode : 1058; flag : umf_noinfo; reserved : 0),
+ (unicode : 1059; flag : umf_noinfo; reserved : 0),
+ (unicode : 1060; flag : umf_noinfo; reserved : 0),
+ (unicode : 1061; flag : umf_noinfo; reserved : 0),
+ (unicode : 1062; flag : umf_noinfo; reserved : 0),
+ (unicode : 1063; flag : umf_noinfo; reserved : 0),
+ (unicode : 1064; flag : umf_noinfo; reserved : 0),
+ (unicode : 1065; flag : umf_noinfo; reserved : 0),
+ (unicode : 1066; flag : umf_noinfo; reserved : 0),
+ (unicode : 1067; flag : umf_noinfo; reserved : 0),
+ (unicode : 1068; flag : umf_noinfo; reserved : 0),
+ (unicode : 1069; flag : umf_noinfo; reserved : 0),
+ (unicode : 1070; flag : umf_noinfo; reserved : 0),
+ (unicode : 1071; flag : umf_noinfo; reserved : 0),
+ (unicode : 1072; flag : umf_noinfo; reserved : 0),
+ (unicode : 1073; flag : umf_noinfo; reserved : 0),
+ (unicode : 1074; flag : umf_noinfo; reserved : 0),
+ (unicode : 1075; flag : umf_noinfo; reserved : 0),
+ (unicode : 1076; flag : umf_noinfo; reserved : 0),
+ (unicode : 1077; flag : umf_noinfo; reserved : 0),
+ (unicode : 1078; flag : umf_noinfo; reserved : 0),
+ (unicode : 1079; flag : umf_noinfo; reserved : 0),
+ (unicode : 1080; flag : umf_noinfo; reserved : 0),
+ (unicode : 1081; flag : umf_noinfo; reserved : 0),
+ (unicode : 1082; flag : umf_noinfo; reserved : 0),
+ (unicode : 1083; flag : umf_noinfo; reserved : 0),
+ (unicode : 1084; flag : umf_noinfo; reserved : 0),
+ (unicode : 1085; flag : umf_noinfo; reserved : 0),
+ (unicode : 1086; flag : umf_noinfo; reserved : 0),
+ (unicode : 1087; flag : umf_noinfo; reserved : 0),
+ (unicode : 1088; flag : umf_noinfo; reserved : 0),
+ (unicode : 1089; flag : umf_noinfo; reserved : 0),
+ (unicode : 1090; flag : umf_noinfo; reserved : 0),
+ (unicode : 1091; flag : umf_noinfo; reserved : 0),
+ (unicode : 1092; flag : umf_noinfo; reserved : 0),
+ (unicode : 1093; flag : umf_noinfo; reserved : 0),
+ (unicode : 1094; flag : umf_noinfo; reserved : 0),
+ (unicode : 1095; flag : umf_noinfo; reserved : 0),
+ (unicode : 1096; flag : umf_noinfo; reserved : 0),
+ (unicode : 1097; flag : umf_noinfo; reserved : 0),
+ (unicode : 1098; flag : umf_noinfo; reserved : 0),
+ (unicode : 1099; flag : umf_noinfo; reserved : 0),
+ (unicode : 1100; flag : umf_noinfo; reserved : 0),
+ (unicode : 1101; flag : umf_noinfo; reserved : 0),
+ (unicode : 1102; flag : umf_noinfo; reserved : 0),
+ (unicode : 1103; flag : umf_noinfo; reserved : 0)
+ );
+
+ unicodemap : tunicodemap = (
+ cpname : 'cp1251';
+ cp : 1251;
+ map : @map;
+ lastchar : 255;
+ next : nil;
+ internalmap : true
+ );
+
+ begin
+ registermapping(@unicodemap)
+ end.
diff --git a/closures/compiler/cp1252.pp b/closures/compiler/cp1252.pp
new file mode 100644
index 0000000000..dc538efc83
--- /dev/null
+++ b/closures/compiler/cp1252.pp
@@ -0,0 +1,282 @@
+{ This is an automatically created file, so don't edit it }
+unit CP1252;
+
+ interface
+
+ implementation
+
+ uses
+ {$if FPC_FULLVERSION<20700}ccharset{$else}charset{$endif};
+
+ const
+ map : array[0..255] of tunicodecharmapping = (
+ (unicode : 0; flag : umf_noinfo; reserved: 0),
+ (unicode : 1; flag : umf_noinfo; reserved: 0),
+ (unicode : 2; flag : umf_noinfo; reserved: 0),
+ (unicode : 3; flag : umf_noinfo; reserved: 0),
+ (unicode : 4; flag : umf_noinfo; reserved: 0),
+ (unicode : 5; flag : umf_noinfo; reserved: 0),
+ (unicode : 6; flag : umf_noinfo; reserved: 0),
+ (unicode : 7; flag : umf_noinfo; reserved: 0),
+ (unicode : 8; flag : umf_noinfo; reserved: 0),
+ (unicode : 9; flag : umf_noinfo; reserved: 0),
+ (unicode : 10; flag : umf_noinfo; reserved: 0),
+ (unicode : 11; flag : umf_noinfo; reserved: 0),
+ (unicode : 12; flag : umf_noinfo; reserved: 0),
+ (unicode : 13; flag : umf_noinfo; reserved: 0),
+ (unicode : 14; flag : umf_noinfo; reserved: 0),
+ (unicode : 15; flag : umf_noinfo; reserved: 0),
+ (unicode : 16; flag : umf_noinfo; reserved: 0),
+ (unicode : 17; flag : umf_noinfo; reserved: 0),
+ (unicode : 18; flag : umf_noinfo; reserved: 0),
+ (unicode : 19; flag : umf_noinfo; reserved: 0),
+ (unicode : 20; flag : umf_noinfo; reserved: 0),
+ (unicode : 21; flag : umf_noinfo; reserved: 0),
+ (unicode : 22; flag : umf_noinfo; reserved: 0),
+ (unicode : 23; flag : umf_noinfo; reserved: 0),
+ (unicode : 24; flag : umf_noinfo; reserved: 0),
+ (unicode : 25; flag : umf_noinfo; reserved: 0),
+ (unicode : 26; flag : umf_noinfo; reserved: 0),
+ (unicode : 27; flag : umf_noinfo; reserved: 0),
+ (unicode : 28; flag : umf_noinfo; reserved: 0),
+ (unicode : 29; flag : umf_noinfo; reserved: 0),
+ (unicode : 30; flag : umf_noinfo; reserved: 0),
+ (unicode : 31; flag : umf_noinfo; reserved: 0),
+ (unicode : 32; flag : umf_noinfo; reserved: 0),
+ (unicode : 33; flag : umf_noinfo; reserved: 0),
+ (unicode : 34; flag : umf_noinfo; reserved: 0),
+ (unicode : 35; flag : umf_noinfo; reserved: 0),
+ (unicode : 36; flag : umf_noinfo; reserved: 0),
+ (unicode : 37; flag : umf_noinfo; reserved: 0),
+ (unicode : 38; flag : umf_noinfo; reserved: 0),
+ (unicode : 39; flag : umf_noinfo; reserved: 0),
+ (unicode : 40; flag : umf_noinfo; reserved: 0),
+ (unicode : 41; flag : umf_noinfo; reserved: 0),
+ (unicode : 42; flag : umf_noinfo; reserved: 0),
+ (unicode : 43; flag : umf_noinfo; reserved: 0),
+ (unicode : 44; flag : umf_noinfo; reserved: 0),
+ (unicode : 45; flag : umf_noinfo; reserved: 0),
+ (unicode : 46; flag : umf_noinfo; reserved: 0),
+ (unicode : 47; flag : umf_noinfo; reserved: 0),
+ (unicode : 48; flag : umf_noinfo; reserved: 0),
+ (unicode : 49; flag : umf_noinfo; reserved: 0),
+ (unicode : 50; flag : umf_noinfo; reserved: 0),
+ (unicode : 51; flag : umf_noinfo; reserved: 0),
+ (unicode : 52; flag : umf_noinfo; reserved: 0),
+ (unicode : 53; flag : umf_noinfo; reserved: 0),
+ (unicode : 54; flag : umf_noinfo; reserved: 0),
+ (unicode : 55; flag : umf_noinfo; reserved: 0),
+ (unicode : 56; flag : umf_noinfo; reserved: 0),
+ (unicode : 57; flag : umf_noinfo; reserved: 0),
+ (unicode : 58; flag : umf_noinfo; reserved: 0),
+ (unicode : 59; flag : umf_noinfo; reserved: 0),
+ (unicode : 60; flag : umf_noinfo; reserved: 0),
+ (unicode : 61; flag : umf_noinfo; reserved: 0),
+ (unicode : 62; flag : umf_noinfo; reserved: 0),
+ (unicode : 63; flag : umf_noinfo; reserved: 0),
+ (unicode : 64; flag : umf_noinfo; reserved: 0),
+ (unicode : 65; flag : umf_noinfo; reserved: 0),
+ (unicode : 66; flag : umf_noinfo; reserved: 0),
+ (unicode : 67; flag : umf_noinfo; reserved: 0),
+ (unicode : 68; flag : umf_noinfo; reserved: 0),
+ (unicode : 69; flag : umf_noinfo; reserved: 0),
+ (unicode : 70; flag : umf_noinfo; reserved: 0),
+ (unicode : 71; flag : umf_noinfo; reserved: 0),
+ (unicode : 72; flag : umf_noinfo; reserved: 0),
+ (unicode : 73; flag : umf_noinfo; reserved: 0),
+ (unicode : 74; flag : umf_noinfo; reserved: 0),
+ (unicode : 75; flag : umf_noinfo; reserved: 0),
+ (unicode : 76; flag : umf_noinfo; reserved: 0),
+ (unicode : 77; flag : umf_noinfo; reserved: 0),
+ (unicode : 78; flag : umf_noinfo; reserved: 0),
+ (unicode : 79; flag : umf_noinfo; reserved: 0),
+ (unicode : 80; flag : umf_noinfo; reserved: 0),
+ (unicode : 81; flag : umf_noinfo; reserved: 0),
+ (unicode : 82; flag : umf_noinfo; reserved: 0),
+ (unicode : 83; flag : umf_noinfo; reserved: 0),
+ (unicode : 84; flag : umf_noinfo; reserved: 0),
+ (unicode : 85; flag : umf_noinfo; reserved: 0),
+ (unicode : 86; flag : umf_noinfo; reserved: 0),
+ (unicode : 87; flag : umf_noinfo; reserved: 0),
+ (unicode : 88; flag : umf_noinfo; reserved: 0),
+ (unicode : 89; flag : umf_noinfo; reserved: 0),
+ (unicode : 90; flag : umf_noinfo; reserved: 0),
+ (unicode : 91; flag : umf_noinfo; reserved: 0),
+ (unicode : 92; flag : umf_noinfo; reserved: 0),
+ (unicode : 93; flag : umf_noinfo; reserved: 0),
+ (unicode : 94; flag : umf_noinfo; reserved: 0),
+ (unicode : 95; flag : umf_noinfo; reserved: 0),
+ (unicode : 96; flag : umf_noinfo; reserved: 0),
+ (unicode : 97; flag : umf_noinfo; reserved: 0),
+ (unicode : 98; flag : umf_noinfo; reserved: 0),
+ (unicode : 99; flag : umf_noinfo; reserved: 0),
+ (unicode : 100; flag : umf_noinfo; reserved: 0),
+ (unicode : 101; flag : umf_noinfo; reserved: 0),
+ (unicode : 102; flag : umf_noinfo; reserved: 0),
+ (unicode : 103; flag : umf_noinfo; reserved: 0),
+ (unicode : 104; flag : umf_noinfo; reserved: 0),
+ (unicode : 105; flag : umf_noinfo; reserved: 0),
+ (unicode : 106; flag : umf_noinfo; reserved: 0),
+ (unicode : 107; flag : umf_noinfo; reserved: 0),
+ (unicode : 108; flag : umf_noinfo; reserved: 0),
+ (unicode : 109; flag : umf_noinfo; reserved: 0),
+ (unicode : 110; flag : umf_noinfo; reserved: 0),
+ (unicode : 111; flag : umf_noinfo; reserved: 0),
+ (unicode : 112; flag : umf_noinfo; reserved: 0),
+ (unicode : 113; flag : umf_noinfo; reserved: 0),
+ (unicode : 114; flag : umf_noinfo; reserved: 0),
+ (unicode : 115; flag : umf_noinfo; reserved: 0),
+ (unicode : 116; flag : umf_noinfo; reserved: 0),
+ (unicode : 117; flag : umf_noinfo; reserved: 0),
+ (unicode : 118; flag : umf_noinfo; reserved: 0),
+ (unicode : 119; flag : umf_noinfo; reserved: 0),
+ (unicode : 120; flag : umf_noinfo; reserved: 0),
+ (unicode : 121; flag : umf_noinfo; reserved: 0),
+ (unicode : 122; flag : umf_noinfo; reserved: 0),
+ (unicode : 123; flag : umf_noinfo; reserved: 0),
+ (unicode : 124; flag : umf_noinfo; reserved: 0),
+ (unicode : 125; flag : umf_noinfo; reserved: 0),
+ (unicode : 126; flag : umf_noinfo; reserved: 0),
+ (unicode : 127; flag : umf_noinfo; reserved: 0),
+ (unicode : 8364; flag : umf_noinfo; reserved: 0),
+ (unicode : 65535; flag : umf_unused; reserved: 0),
+ (unicode : 8218; flag : umf_noinfo; reserved: 0),
+ (unicode : 402; flag : umf_noinfo; reserved: 0),
+ (unicode : 8222; flag : umf_noinfo; reserved: 0),
+ (unicode : 8230; flag : umf_noinfo; reserved: 0),
+ (unicode : 8224; flag : umf_noinfo; reserved: 0),
+ (unicode : 8225; flag : umf_noinfo; reserved: 0),
+ (unicode : 710; flag : umf_noinfo; reserved: 0),
+ (unicode : 8240; flag : umf_noinfo; reserved: 0),
+ (unicode : 352; flag : umf_noinfo; reserved: 0),
+ (unicode : 8249; flag : umf_noinfo; reserved: 0),
+ (unicode : 338; flag : umf_noinfo; reserved: 0),
+ (unicode : 65535; flag : umf_unused; reserved: 0),
+ (unicode : 381; flag : umf_noinfo; reserved: 0),
+ (unicode : 65535; flag : umf_unused; reserved: 0),
+ (unicode : 65535; flag : umf_unused; reserved: 0),
+ (unicode : 8216; flag : umf_noinfo; reserved: 0),
+ (unicode : 8217; flag : umf_noinfo; reserved: 0),
+ (unicode : 8220; flag : umf_noinfo; reserved: 0),
+ (unicode : 8221; flag : umf_noinfo; reserved: 0),
+ (unicode : 8226; flag : umf_noinfo; reserved: 0),
+ (unicode : 8211; flag : umf_noinfo; reserved: 0),
+ (unicode : 8212; flag : umf_noinfo; reserved: 0),
+ (unicode : 732; flag : umf_noinfo; reserved: 0),
+ (unicode : 8482; flag : umf_noinfo; reserved: 0),
+ (unicode : 353; flag : umf_noinfo; reserved: 0),
+ (unicode : 8250; flag : umf_noinfo; reserved: 0),
+ (unicode : 339; flag : umf_noinfo; reserved: 0),
+ (unicode : 65535; flag : umf_unused; reserved: 0),
+ (unicode : 382; flag : umf_noinfo; reserved: 0),
+ (unicode : 376; flag : umf_noinfo; reserved: 0),
+ (unicode : 160; flag : umf_noinfo; reserved: 0),
+ (unicode : 161; flag : umf_noinfo; reserved: 0),
+ (unicode : 162; flag : umf_noinfo; reserved: 0),
+ (unicode : 163; flag : umf_noinfo; reserved: 0),
+ (unicode : 164; flag : umf_noinfo; reserved: 0),
+ (unicode : 165; flag : umf_noinfo; reserved: 0),
+ (unicode : 166; flag : umf_noinfo; reserved: 0),
+ (unicode : 167; flag : umf_noinfo; reserved: 0),
+ (unicode : 168; flag : umf_noinfo; reserved: 0),
+ (unicode : 169; flag : umf_noinfo; reserved: 0),
+ (unicode : 170; flag : umf_noinfo; reserved: 0),
+ (unicode : 171; flag : umf_noinfo; reserved: 0),
+ (unicode : 172; flag : umf_noinfo; reserved: 0),
+ (unicode : 173; flag : umf_noinfo; reserved: 0),
+ (unicode : 174; flag : umf_noinfo; reserved: 0),
+ (unicode : 175; flag : umf_noinfo; reserved: 0),
+ (unicode : 176; flag : umf_noinfo; reserved: 0),
+ (unicode : 177; flag : umf_noinfo; reserved: 0),
+ (unicode : 178; flag : umf_noinfo; reserved: 0),
+ (unicode : 179; flag : umf_noinfo; reserved: 0),
+ (unicode : 180; flag : umf_noinfo; reserved: 0),
+ (unicode : 181; flag : umf_noinfo; reserved: 0),
+ (unicode : 182; flag : umf_noinfo; reserved: 0),
+ (unicode : 183; flag : umf_noinfo; reserved: 0),
+ (unicode : 184; flag : umf_noinfo; reserved: 0),
+ (unicode : 185; flag : umf_noinfo; reserved: 0),
+ (unicode : 186; flag : umf_noinfo; reserved: 0),
+ (unicode : 187; flag : umf_noinfo; reserved: 0),
+ (unicode : 188; flag : umf_noinfo; reserved: 0),
+ (unicode : 189; flag : umf_noinfo; reserved: 0),
+ (unicode : 190; flag : umf_noinfo; reserved: 0),
+ (unicode : 191; flag : umf_noinfo; reserved: 0),
+ (unicode : 192; flag : umf_noinfo; reserved: 0),
+ (unicode : 193; flag : umf_noinfo; reserved: 0),
+ (unicode : 194; flag : umf_noinfo; reserved: 0),
+ (unicode : 195; flag : umf_noinfo; reserved: 0),
+ (unicode : 196; flag : umf_noinfo; reserved: 0),
+ (unicode : 197; flag : umf_noinfo; reserved: 0),
+ (unicode : 198; flag : umf_noinfo; reserved: 0),
+ (unicode : 199; flag : umf_noinfo; reserved: 0),
+ (unicode : 200; flag : umf_noinfo; reserved: 0),
+ (unicode : 201; flag : umf_noinfo; reserved: 0),
+ (unicode : 202; flag : umf_noinfo; reserved: 0),
+ (unicode : 203; flag : umf_noinfo; reserved: 0),
+ (unicode : 204; flag : umf_noinfo; reserved: 0),
+ (unicode : 205; flag : umf_noinfo; reserved: 0),
+ (unicode : 206; flag : umf_noinfo; reserved: 0),
+ (unicode : 207; flag : umf_noinfo; reserved: 0),
+ (unicode : 208; flag : umf_noinfo; reserved: 0),
+ (unicode : 209; flag : umf_noinfo; reserved: 0),
+ (unicode : 210; flag : umf_noinfo; reserved: 0),
+ (unicode : 211; flag : umf_noinfo; reserved: 0),
+ (unicode : 212; flag : umf_noinfo; reserved: 0),
+ (unicode : 213; flag : umf_noinfo; reserved: 0),
+ (unicode : 214; flag : umf_noinfo; reserved: 0),
+ (unicode : 215; flag : umf_noinfo; reserved: 0),
+ (unicode : 216; flag : umf_noinfo; reserved: 0),
+ (unicode : 217; flag : umf_noinfo; reserved: 0),
+ (unicode : 218; flag : umf_noinfo; reserved: 0),
+ (unicode : 219; flag : umf_noinfo; reserved: 0),
+ (unicode : 220; flag : umf_noinfo; reserved: 0),
+ (unicode : 221; flag : umf_noinfo; reserved: 0),
+ (unicode : 222; flag : umf_noinfo; reserved: 0),
+ (unicode : 223; flag : umf_noinfo; reserved: 0),
+ (unicode : 224; flag : umf_noinfo; reserved: 0),
+ (unicode : 225; flag : umf_noinfo; reserved: 0),
+ (unicode : 226; flag : umf_noinfo; reserved: 0),
+ (unicode : 227; flag : umf_noinfo; reserved: 0),
+ (unicode : 228; flag : umf_noinfo; reserved: 0),
+ (unicode : 229; flag : umf_noinfo; reserved: 0),
+ (unicode : 230; flag : umf_noinfo; reserved: 0),
+ (unicode : 231; flag : umf_noinfo; reserved: 0),
+ (unicode : 232; flag : umf_noinfo; reserved: 0),
+ (unicode : 233; flag : umf_noinfo; reserved: 0),
+ (unicode : 234; flag : umf_noinfo; reserved: 0),
+ (unicode : 235; flag : umf_noinfo; reserved: 0),
+ (unicode : 236; flag : umf_noinfo; reserved: 0),
+ (unicode : 237; flag : umf_noinfo; reserved: 0),
+ (unicode : 238; flag : umf_noinfo; reserved: 0),
+ (unicode : 239; flag : umf_noinfo; reserved: 0),
+ (unicode : 240; flag : umf_noinfo; reserved: 0),
+ (unicode : 241; flag : umf_noinfo; reserved: 0),
+ (unicode : 242; flag : umf_noinfo; reserved: 0),
+ (unicode : 243; flag : umf_noinfo; reserved: 0),
+ (unicode : 244; flag : umf_noinfo; reserved: 0),
+ (unicode : 245; flag : umf_noinfo; reserved: 0),
+ (unicode : 246; flag : umf_noinfo; reserved: 0),
+ (unicode : 247; flag : umf_noinfo; reserved: 0),
+ (unicode : 248; flag : umf_noinfo; reserved: 0),
+ (unicode : 249; flag : umf_noinfo; reserved: 0),
+ (unicode : 250; flag : umf_noinfo; reserved: 0),
+ (unicode : 251; flag : umf_noinfo; reserved: 0),
+ (unicode : 252; flag : umf_noinfo; reserved: 0),
+ (unicode : 253; flag : umf_noinfo; reserved: 0),
+ (unicode : 254; flag : umf_noinfo; reserved: 0),
+ (unicode : 255; flag : umf_noinfo; reserved: 0)
+ );
+
+ unicodemap : tunicodemap = (
+ cpname : 'CP1252';
+ cp : 1252;
+ map : @map;
+ lastchar : 255;
+ next : nil;
+ internalmap : true
+ );
+
+ begin
+ registermapping(@unicodemap)
+ end.
diff --git a/closures/compiler/cp437.pas b/closures/compiler/cp437.pas
new file mode 100644
index 0000000000..4776c5ef0e
--- /dev/null
+++ b/closures/compiler/cp437.pas
@@ -0,0 +1,282 @@
+{ This is an automatically created file, so don't edit it }
+unit cp437;
+
+ interface
+
+ implementation
+
+ uses
+ {$if FPC_FULLVERSION<20700}ccharset{$else}charset{$endif};
+
+ const
+ map : array[0..255] of tunicodecharmapping = (
+ (unicode : 0; flag : umf_noinfo; reserved : 0),
+ (unicode : 1; flag : umf_noinfo; reserved : 0),
+ (unicode : 2; flag : umf_noinfo; reserved : 0),
+ (unicode : 3; flag : umf_noinfo; reserved : 0),
+ (unicode : 4; flag : umf_noinfo; reserved : 0),
+ (unicode : 5; flag : umf_noinfo; reserved : 0),
+ (unicode : 6; flag : umf_noinfo; reserved : 0),
+ (unicode : 7; flag : umf_noinfo; reserved : 0),
+ (unicode : 8; flag : umf_noinfo; reserved : 0),
+ (unicode : 9; flag : umf_noinfo; reserved : 0),
+ (unicode : 10; flag : umf_noinfo; reserved : 0),
+ (unicode : 11; flag : umf_noinfo; reserved : 0),
+ (unicode : 12; flag : umf_noinfo; reserved : 0),
+ (unicode : 13; flag : umf_noinfo; reserved : 0),
+ (unicode : 14; flag : umf_noinfo; reserved : 0),
+ (unicode : 15; flag : umf_noinfo; reserved : 0),
+ (unicode : 16; flag : umf_noinfo; reserved : 0),
+ (unicode : 17; flag : umf_noinfo; reserved : 0),
+ (unicode : 18; flag : umf_noinfo; reserved : 0),
+ (unicode : 19; flag : umf_noinfo; reserved : 0),
+ (unicode : 20; flag : umf_noinfo; reserved : 0),
+ (unicode : 21; flag : umf_noinfo; reserved : 0),
+ (unicode : 22; flag : umf_noinfo; reserved : 0),
+ (unicode : 23; flag : umf_noinfo; reserved : 0),
+ (unicode : 24; flag : umf_noinfo; reserved : 0),
+ (unicode : 25; flag : umf_noinfo; reserved : 0),
+ (unicode : 26; flag : umf_noinfo; reserved : 0),
+ (unicode : 27; flag : umf_noinfo; reserved : 0),
+ (unicode : 28; flag : umf_noinfo; reserved : 0),
+ (unicode : 29; flag : umf_noinfo; reserved : 0),
+ (unicode : 30; flag : umf_noinfo; reserved : 0),
+ (unicode : 31; flag : umf_noinfo; reserved : 0),
+ (unicode : 32; flag : umf_noinfo; reserved : 0),
+ (unicode : 33; flag : umf_noinfo; reserved : 0),
+ (unicode : 34; flag : umf_noinfo; reserved : 0),
+ (unicode : 35; flag : umf_noinfo; reserved : 0),
+ (unicode : 36; flag : umf_noinfo; reserved : 0),
+ (unicode : 37; flag : umf_noinfo; reserved : 0),
+ (unicode : 38; flag : umf_noinfo; reserved : 0),
+ (unicode : 39; flag : umf_noinfo; reserved : 0),
+ (unicode : 40; flag : umf_noinfo; reserved : 0),
+ (unicode : 41; flag : umf_noinfo; reserved : 0),
+ (unicode : 42; flag : umf_noinfo; reserved : 0),
+ (unicode : 43; flag : umf_noinfo; reserved : 0),
+ (unicode : 44; flag : umf_noinfo; reserved : 0),
+ (unicode : 45; flag : umf_noinfo; reserved : 0),
+ (unicode : 46; flag : umf_noinfo; reserved : 0),
+ (unicode : 47; flag : umf_noinfo; reserved : 0),
+ (unicode : 48; flag : umf_noinfo; reserved : 0),
+ (unicode : 49; flag : umf_noinfo; reserved : 0),
+ (unicode : 50; flag : umf_noinfo; reserved : 0),
+ (unicode : 51; flag : umf_noinfo; reserved : 0),
+ (unicode : 52; flag : umf_noinfo; reserved : 0),
+ (unicode : 53; flag : umf_noinfo; reserved : 0),
+ (unicode : 54; flag : umf_noinfo; reserved : 0),
+ (unicode : 55; flag : umf_noinfo; reserved : 0),
+ (unicode : 56; flag : umf_noinfo; reserved : 0),
+ (unicode : 57; flag : umf_noinfo; reserved : 0),
+ (unicode : 58; flag : umf_noinfo; reserved : 0),
+ (unicode : 59; flag : umf_noinfo; reserved : 0),
+ (unicode : 60; flag : umf_noinfo; reserved : 0),
+ (unicode : 61; flag : umf_noinfo; reserved : 0),
+ (unicode : 62; flag : umf_noinfo; reserved : 0),
+ (unicode : 63; flag : umf_noinfo; reserved : 0),
+ (unicode : 64; flag : umf_noinfo; reserved : 0),
+ (unicode : 65; flag : umf_noinfo; reserved : 0),
+ (unicode : 66; flag : umf_noinfo; reserved : 0),
+ (unicode : 67; flag : umf_noinfo; reserved : 0),
+ (unicode : 68; flag : umf_noinfo; reserved : 0),
+ (unicode : 69; flag : umf_noinfo; reserved : 0),
+ (unicode : 70; flag : umf_noinfo; reserved : 0),
+ (unicode : 71; flag : umf_noinfo; reserved : 0),
+ (unicode : 72; flag : umf_noinfo; reserved : 0),
+ (unicode : 73; flag : umf_noinfo; reserved : 0),
+ (unicode : 74; flag : umf_noinfo; reserved : 0),
+ (unicode : 75; flag : umf_noinfo; reserved : 0),
+ (unicode : 76; flag : umf_noinfo; reserved : 0),
+ (unicode : 77; flag : umf_noinfo; reserved : 0),
+ (unicode : 78; flag : umf_noinfo; reserved : 0),
+ (unicode : 79; flag : umf_noinfo; reserved : 0),
+ (unicode : 80; flag : umf_noinfo; reserved : 0),
+ (unicode : 81; flag : umf_noinfo; reserved : 0),
+ (unicode : 82; flag : umf_noinfo; reserved : 0),
+ (unicode : 83; flag : umf_noinfo; reserved : 0),
+ (unicode : 84; flag : umf_noinfo; reserved : 0),
+ (unicode : 85; flag : umf_noinfo; reserved : 0),
+ (unicode : 86; flag : umf_noinfo; reserved : 0),
+ (unicode : 87; flag : umf_noinfo; reserved : 0),
+ (unicode : 88; flag : umf_noinfo; reserved : 0),
+ (unicode : 89; flag : umf_noinfo; reserved : 0),
+ (unicode : 90; flag : umf_noinfo; reserved : 0),
+ (unicode : 91; flag : umf_noinfo; reserved : 0),
+ (unicode : 92; flag : umf_noinfo; reserved : 0),
+ (unicode : 93; flag : umf_noinfo; reserved : 0),
+ (unicode : 94; flag : umf_noinfo; reserved : 0),
+ (unicode : 95; flag : umf_noinfo; reserved : 0),
+ (unicode : 96; flag : umf_noinfo; reserved : 0),
+ (unicode : 97; flag : umf_noinfo; reserved : 0),
+ (unicode : 98; flag : umf_noinfo; reserved : 0),
+ (unicode : 99; flag : umf_noinfo; reserved : 0),
+ (unicode : 100; flag : umf_noinfo; reserved : 0),
+ (unicode : 101; flag : umf_noinfo; reserved : 0),
+ (unicode : 102; flag : umf_noinfo; reserved : 0),
+ (unicode : 103; flag : umf_noinfo; reserved : 0),
+ (unicode : 104; flag : umf_noinfo; reserved : 0),
+ (unicode : 105; flag : umf_noinfo; reserved : 0),
+ (unicode : 106; flag : umf_noinfo; reserved : 0),
+ (unicode : 107; flag : umf_noinfo; reserved : 0),
+ (unicode : 108; flag : umf_noinfo; reserved : 0),
+ (unicode : 109; flag : umf_noinfo; reserved : 0),
+ (unicode : 110; flag : umf_noinfo; reserved : 0),
+ (unicode : 111; flag : umf_noinfo; reserved : 0),
+ (unicode : 112; flag : umf_noinfo; reserved : 0),
+ (unicode : 113; flag : umf_noinfo; reserved : 0),
+ (unicode : 114; flag : umf_noinfo; reserved : 0),
+ (unicode : 115; flag : umf_noinfo; reserved : 0),
+ (unicode : 116; flag : umf_noinfo; reserved : 0),
+ (unicode : 117; flag : umf_noinfo; reserved : 0),
+ (unicode : 118; flag : umf_noinfo; reserved : 0),
+ (unicode : 119; flag : umf_noinfo; reserved : 0),
+ (unicode : 120; flag : umf_noinfo; reserved : 0),
+ (unicode : 121; flag : umf_noinfo; reserved : 0),
+ (unicode : 122; flag : umf_noinfo; reserved : 0),
+ (unicode : 123; flag : umf_noinfo; reserved : 0),
+ (unicode : 124; flag : umf_noinfo; reserved : 0),
+ (unicode : 125; flag : umf_noinfo; reserved : 0),
+ (unicode : 126; flag : umf_noinfo; reserved : 0),
+ (unicode : 127; flag : umf_noinfo; reserved : 0),
+ (unicode : 199; flag : umf_noinfo; reserved : 0),
+ (unicode : 252; flag : umf_noinfo; reserved : 0),
+ (unicode : 233; flag : umf_noinfo; reserved : 0),
+ (unicode : 226; flag : umf_noinfo; reserved : 0),
+ (unicode : 228; flag : umf_noinfo; reserved : 0),
+ (unicode : 224; flag : umf_noinfo; reserved : 0),
+ (unicode : 229; flag : umf_noinfo; reserved : 0),
+ (unicode : 231; flag : umf_noinfo; reserved : 0),
+ (unicode : 234; flag : umf_noinfo; reserved : 0),
+ (unicode : 235; flag : umf_noinfo; reserved : 0),
+ (unicode : 232; flag : umf_noinfo; reserved : 0),
+ (unicode : 239; flag : umf_noinfo; reserved : 0),
+ (unicode : 238; flag : umf_noinfo; reserved : 0),
+ (unicode : 236; flag : umf_noinfo; reserved : 0),
+ (unicode : 196; flag : umf_noinfo; reserved : 0),
+ (unicode : 197; flag : umf_noinfo; reserved : 0),
+ (unicode : 201; flag : umf_noinfo; reserved : 0),
+ (unicode : 230; flag : umf_noinfo; reserved : 0),
+ (unicode : 198; flag : umf_noinfo; reserved : 0),
+ (unicode : 244; flag : umf_noinfo; reserved : 0),
+ (unicode : 246; flag : umf_noinfo; reserved : 0),
+ (unicode : 242; flag : umf_noinfo; reserved : 0),
+ (unicode : 251; flag : umf_noinfo; reserved : 0),
+ (unicode : 249; flag : umf_noinfo; reserved : 0),
+ (unicode : 255; flag : umf_noinfo; reserved : 0),
+ (unicode : 214; flag : umf_noinfo; reserved : 0),
+ (unicode : 220; flag : umf_noinfo; reserved : 0),
+ (unicode : 162; flag : umf_noinfo; reserved : 0),
+ (unicode : 163; flag : umf_noinfo; reserved : 0),
+ (unicode : 165; flag : umf_noinfo; reserved : 0),
+ (unicode : 8359; flag : umf_noinfo; reserved : 0),
+ (unicode : 402; flag : umf_noinfo; reserved : 0),
+ (unicode : 225; flag : umf_noinfo; reserved : 0),
+ (unicode : 237; flag : umf_noinfo; reserved : 0),
+ (unicode : 243; flag : umf_noinfo; reserved : 0),
+ (unicode : 250; flag : umf_noinfo; reserved : 0),
+ (unicode : 241; flag : umf_noinfo; reserved : 0),
+ (unicode : 209; flag : umf_noinfo; reserved : 0),
+ (unicode : 170; flag : umf_noinfo; reserved : 0),
+ (unicode : 186; flag : umf_noinfo; reserved : 0),
+ (unicode : 191; flag : umf_noinfo; reserved : 0),
+ (unicode : 8976; flag : umf_noinfo; reserved : 0),
+ (unicode : 172; flag : umf_noinfo; reserved : 0),
+ (unicode : 189; flag : umf_noinfo; reserved : 0),
+ (unicode : 188; flag : umf_noinfo; reserved : 0),
+ (unicode : 161; flag : umf_noinfo; reserved : 0),
+ (unicode : 171; flag : umf_noinfo; reserved : 0),
+ (unicode : 187; flag : umf_noinfo; reserved : 0),
+ (unicode : 9617; flag : umf_noinfo; reserved : 0),
+ (unicode : 9618; flag : umf_noinfo; reserved : 0),
+ (unicode : 9619; flag : umf_noinfo; reserved : 0),
+ (unicode : 9474; flag : umf_noinfo; reserved : 0),
+ (unicode : 9508; flag : umf_noinfo; reserved : 0),
+ (unicode : 9569; flag : umf_noinfo; reserved : 0),
+ (unicode : 9570; flag : umf_noinfo; reserved : 0),
+ (unicode : 9558; flag : umf_noinfo; reserved : 0),
+ (unicode : 9557; flag : umf_noinfo; reserved : 0),
+ (unicode : 9571; flag : umf_noinfo; reserved : 0),
+ (unicode : 9553; flag : umf_noinfo; reserved : 0),
+ (unicode : 9559; flag : umf_noinfo; reserved : 0),
+ (unicode : 9565; flag : umf_noinfo; reserved : 0),
+ (unicode : 9564; flag : umf_noinfo; reserved : 0),
+ (unicode : 9563; flag : umf_noinfo; reserved : 0),
+ (unicode : 9488; flag : umf_noinfo; reserved : 0),
+ (unicode : 9492; flag : umf_noinfo; reserved : 0),
+ (unicode : 9524; flag : umf_noinfo; reserved : 0),
+ (unicode : 9516; flag : umf_noinfo; reserved : 0),
+ (unicode : 9500; flag : umf_noinfo; reserved : 0),
+ (unicode : 9472; flag : umf_noinfo; reserved : 0),
+ (unicode : 9532; flag : umf_noinfo; reserved : 0),
+ (unicode : 9566; flag : umf_noinfo; reserved : 0),
+ (unicode : 9567; flag : umf_noinfo; reserved : 0),
+ (unicode : 9562; flag : umf_noinfo; reserved : 0),
+ (unicode : 9556; flag : umf_noinfo; reserved : 0),
+ (unicode : 9577; flag : umf_noinfo; reserved : 0),
+ (unicode : 9574; flag : umf_noinfo; reserved : 0),
+ (unicode : 9568; flag : umf_noinfo; reserved : 0),
+ (unicode : 9552; flag : umf_noinfo; reserved : 0),
+ (unicode : 9580; flag : umf_noinfo; reserved : 0),
+ (unicode : 9575; flag : umf_noinfo; reserved : 0),
+ (unicode : 9576; flag : umf_noinfo; reserved : 0),
+ (unicode : 9572; flag : umf_noinfo; reserved : 0),
+ (unicode : 9573; flag : umf_noinfo; reserved : 0),
+ (unicode : 9561; flag : umf_noinfo; reserved : 0),
+ (unicode : 9560; flag : umf_noinfo; reserved : 0),
+ (unicode : 9554; flag : umf_noinfo; reserved : 0),
+ (unicode : 9555; flag : umf_noinfo; reserved : 0),
+ (unicode : 9579; flag : umf_noinfo; reserved : 0),
+ (unicode : 9578; flag : umf_noinfo; reserved : 0),
+ (unicode : 9496; flag : umf_noinfo; reserved : 0),
+ (unicode : 9484; flag : umf_noinfo; reserved : 0),
+ (unicode : 9608; flag : umf_noinfo; reserved : 0),
+ (unicode : 9604; flag : umf_noinfo; reserved : 0),
+ (unicode : 9612; flag : umf_noinfo; reserved : 0),
+ (unicode : 9616; flag : umf_noinfo; reserved : 0),
+ (unicode : 9600; flag : umf_noinfo; reserved : 0),
+ (unicode : 945; flag : umf_noinfo; reserved : 0),
+ (unicode : 223; flag : umf_noinfo; reserved : 0),
+ (unicode : 915; flag : umf_noinfo; reserved : 0),
+ (unicode : 960; flag : umf_noinfo; reserved : 0),
+ (unicode : 931; flag : umf_noinfo; reserved : 0),
+ (unicode : 963; flag : umf_noinfo; reserved : 0),
+ (unicode : 181; flag : umf_noinfo; reserved : 0),
+ (unicode : 964; flag : umf_noinfo; reserved : 0),
+ (unicode : 934; flag : umf_noinfo; reserved : 0),
+ (unicode : 920; flag : umf_noinfo; reserved : 0),
+ (unicode : 937; flag : umf_noinfo; reserved : 0),
+ (unicode : 948; flag : umf_noinfo; reserved : 0),
+ (unicode : 8734; flag : umf_noinfo; reserved : 0),
+ (unicode : 966; flag : umf_noinfo; reserved : 0),
+ (unicode : 949; flag : umf_noinfo; reserved : 0),
+ (unicode : 8745; flag : umf_noinfo; reserved : 0),
+ (unicode : 8801; flag : umf_noinfo; reserved : 0),
+ (unicode : 177; flag : umf_noinfo; reserved : 0),
+ (unicode : 8805; flag : umf_noinfo; reserved : 0),
+ (unicode : 8804; flag : umf_noinfo; reserved : 0),
+ (unicode : 8992; flag : umf_noinfo; reserved : 0),
+ (unicode : 8993; flag : umf_noinfo; reserved : 0),
+ (unicode : 247; flag : umf_noinfo; reserved : 0),
+ (unicode : 8776; flag : umf_noinfo; reserved : 0),
+ (unicode : 176; flag : umf_noinfo; reserved : 0),
+ (unicode : 8729; flag : umf_noinfo; reserved : 0),
+ (unicode : 183; flag : umf_noinfo; reserved : 0),
+ (unicode : 8730; flag : umf_noinfo; reserved : 0),
+ (unicode : 8319; flag : umf_noinfo; reserved : 0),
+ (unicode : 178; flag : umf_noinfo; reserved : 0),
+ (unicode : 9632; flag : umf_noinfo; reserved : 0),
+ (unicode : 160; flag : umf_noinfo; reserved : 0)
+ );
+
+ unicodemap : tunicodemap = (
+ cpname : 'cp437';
+ cp : 437;
+ map : @map[0];
+ lastchar : 255;
+ next : nil;
+ internalmap : true
+ );
+
+ begin
+ registermapping(@unicodemap)
+ end.
diff --git a/closures/compiler/cp850.pas b/closures/compiler/cp850.pas
new file mode 100644
index 0000000000..c624590d5f
--- /dev/null
+++ b/closures/compiler/cp850.pas
@@ -0,0 +1,282 @@
+{ This is an automatically created file, so don't edit it }
+unit cp850;
+
+ interface
+
+ implementation
+
+ uses
+ {$if FPC_FULLVERSION<20700}ccharset{$else}charset{$endif};
+
+ const
+ map : array[0..255] of tunicodecharmapping = (
+ (unicode : 0; flag : umf_noinfo; reserved : 0),
+ (unicode : 1; flag : umf_noinfo; reserved : 0),
+ (unicode : 2; flag : umf_noinfo; reserved : 0),
+ (unicode : 3; flag : umf_noinfo; reserved : 0),
+ (unicode : 4; flag : umf_noinfo; reserved : 0),
+ (unicode : 5; flag : umf_noinfo; reserved : 0),
+ (unicode : 6; flag : umf_noinfo; reserved : 0),
+ (unicode : 7; flag : umf_noinfo; reserved : 0),
+ (unicode : 8; flag : umf_noinfo; reserved : 0),
+ (unicode : 9; flag : umf_noinfo; reserved : 0),
+ (unicode : 10; flag : umf_noinfo; reserved : 0),
+ (unicode : 11; flag : umf_noinfo; reserved : 0),
+ (unicode : 12; flag : umf_noinfo; reserved : 0),
+ (unicode : 13; flag : umf_noinfo; reserved : 0),
+ (unicode : 14; flag : umf_noinfo; reserved : 0),
+ (unicode : 15; flag : umf_noinfo; reserved : 0),
+ (unicode : 16; flag : umf_noinfo; reserved : 0),
+ (unicode : 17; flag : umf_noinfo; reserved : 0),
+ (unicode : 18; flag : umf_noinfo; reserved : 0),
+ (unicode : 19; flag : umf_noinfo; reserved : 0),
+ (unicode : 20; flag : umf_noinfo; reserved : 0),
+ (unicode : 21; flag : umf_noinfo; reserved : 0),
+ (unicode : 22; flag : umf_noinfo; reserved : 0),
+ (unicode : 23; flag : umf_noinfo; reserved : 0),
+ (unicode : 24; flag : umf_noinfo; reserved : 0),
+ (unicode : 25; flag : umf_noinfo; reserved : 0),
+ (unicode : 26; flag : umf_noinfo; reserved : 0),
+ (unicode : 27; flag : umf_noinfo; reserved : 0),
+ (unicode : 28; flag : umf_noinfo; reserved : 0),
+ (unicode : 29; flag : umf_noinfo; reserved : 0),
+ (unicode : 30; flag : umf_noinfo; reserved : 0),
+ (unicode : 31; flag : umf_noinfo; reserved : 0),
+ (unicode : 32; flag : umf_noinfo; reserved : 0),
+ (unicode : 33; flag : umf_noinfo; reserved : 0),
+ (unicode : 34; flag : umf_noinfo; reserved : 0),
+ (unicode : 35; flag : umf_noinfo; reserved : 0),
+ (unicode : 36; flag : umf_noinfo; reserved : 0),
+ (unicode : 37; flag : umf_noinfo; reserved : 0),
+ (unicode : 38; flag : umf_noinfo; reserved : 0),
+ (unicode : 39; flag : umf_noinfo; reserved : 0),
+ (unicode : 40; flag : umf_noinfo; reserved : 0),
+ (unicode : 41; flag : umf_noinfo; reserved : 0),
+ (unicode : 42; flag : umf_noinfo; reserved : 0),
+ (unicode : 43; flag : umf_noinfo; reserved : 0),
+ (unicode : 44; flag : umf_noinfo; reserved : 0),
+ (unicode : 45; flag : umf_noinfo; reserved : 0),
+ (unicode : 46; flag : umf_noinfo; reserved : 0),
+ (unicode : 47; flag : umf_noinfo; reserved : 0),
+ (unicode : 48; flag : umf_noinfo; reserved : 0),
+ (unicode : 49; flag : umf_noinfo; reserved : 0),
+ (unicode : 50; flag : umf_noinfo; reserved : 0),
+ (unicode : 51; flag : umf_noinfo; reserved : 0),
+ (unicode : 52; flag : umf_noinfo; reserved : 0),
+ (unicode : 53; flag : umf_noinfo; reserved : 0),
+ (unicode : 54; flag : umf_noinfo; reserved : 0),
+ (unicode : 55; flag : umf_noinfo; reserved : 0),
+ (unicode : 56; flag : umf_noinfo; reserved : 0),
+ (unicode : 57; flag : umf_noinfo; reserved : 0),
+ (unicode : 58; flag : umf_noinfo; reserved : 0),
+ (unicode : 59; flag : umf_noinfo; reserved : 0),
+ (unicode : 60; flag : umf_noinfo; reserved : 0),
+ (unicode : 61; flag : umf_noinfo; reserved : 0),
+ (unicode : 62; flag : umf_noinfo; reserved : 0),
+ (unicode : 63; flag : umf_noinfo; reserved : 0),
+ (unicode : 64; flag : umf_noinfo; reserved : 0),
+ (unicode : 65; flag : umf_noinfo; reserved : 0),
+ (unicode : 66; flag : umf_noinfo; reserved : 0),
+ (unicode : 67; flag : umf_noinfo; reserved : 0),
+ (unicode : 68; flag : umf_noinfo; reserved : 0),
+ (unicode : 69; flag : umf_noinfo; reserved : 0),
+ (unicode : 70; flag : umf_noinfo; reserved : 0),
+ (unicode : 71; flag : umf_noinfo; reserved : 0),
+ (unicode : 72; flag : umf_noinfo; reserved : 0),
+ (unicode : 73; flag : umf_noinfo; reserved : 0),
+ (unicode : 74; flag : umf_noinfo; reserved : 0),
+ (unicode : 75; flag : umf_noinfo; reserved : 0),
+ (unicode : 76; flag : umf_noinfo; reserved : 0),
+ (unicode : 77; flag : umf_noinfo; reserved : 0),
+ (unicode : 78; flag : umf_noinfo; reserved : 0),
+ (unicode : 79; flag : umf_noinfo; reserved : 0),
+ (unicode : 80; flag : umf_noinfo; reserved : 0),
+ (unicode : 81; flag : umf_noinfo; reserved : 0),
+ (unicode : 82; flag : umf_noinfo; reserved : 0),
+ (unicode : 83; flag : umf_noinfo; reserved : 0),
+ (unicode : 84; flag : umf_noinfo; reserved : 0),
+ (unicode : 85; flag : umf_noinfo; reserved : 0),
+ (unicode : 86; flag : umf_noinfo; reserved : 0),
+ (unicode : 87; flag : umf_noinfo; reserved : 0),
+ (unicode : 88; flag : umf_noinfo; reserved : 0),
+ (unicode : 89; flag : umf_noinfo; reserved : 0),
+ (unicode : 90; flag : umf_noinfo; reserved : 0),
+ (unicode : 91; flag : umf_noinfo; reserved : 0),
+ (unicode : 92; flag : umf_noinfo; reserved : 0),
+ (unicode : 93; flag : umf_noinfo; reserved : 0),
+ (unicode : 94; flag : umf_noinfo; reserved : 0),
+ (unicode : 95; flag : umf_noinfo; reserved : 0),
+ (unicode : 96; flag : umf_noinfo; reserved : 0),
+ (unicode : 97; flag : umf_noinfo; reserved : 0),
+ (unicode : 98; flag : umf_noinfo; reserved : 0),
+ (unicode : 99; flag : umf_noinfo; reserved : 0),
+ (unicode : 100; flag : umf_noinfo; reserved : 0),
+ (unicode : 101; flag : umf_noinfo; reserved : 0),
+ (unicode : 102; flag : umf_noinfo; reserved : 0),
+ (unicode : 103; flag : umf_noinfo; reserved : 0),
+ (unicode : 104; flag : umf_noinfo; reserved : 0),
+ (unicode : 105; flag : umf_noinfo; reserved : 0),
+ (unicode : 106; flag : umf_noinfo; reserved : 0),
+ (unicode : 107; flag : umf_noinfo; reserved : 0),
+ (unicode : 108; flag : umf_noinfo; reserved : 0),
+ (unicode : 109; flag : umf_noinfo; reserved : 0),
+ (unicode : 110; flag : umf_noinfo; reserved : 0),
+ (unicode : 111; flag : umf_noinfo; reserved : 0),
+ (unicode : 112; flag : umf_noinfo; reserved : 0),
+ (unicode : 113; flag : umf_noinfo; reserved : 0),
+ (unicode : 114; flag : umf_noinfo; reserved : 0),
+ (unicode : 115; flag : umf_noinfo; reserved : 0),
+ (unicode : 116; flag : umf_noinfo; reserved : 0),
+ (unicode : 117; flag : umf_noinfo; reserved : 0),
+ (unicode : 118; flag : umf_noinfo; reserved : 0),
+ (unicode : 119; flag : umf_noinfo; reserved : 0),
+ (unicode : 120; flag : umf_noinfo; reserved : 0),
+ (unicode : 121; flag : umf_noinfo; reserved : 0),
+ (unicode : 122; flag : umf_noinfo; reserved : 0),
+ (unicode : 123; flag : umf_noinfo; reserved : 0),
+ (unicode : 124; flag : umf_noinfo; reserved : 0),
+ (unicode : 125; flag : umf_noinfo; reserved : 0),
+ (unicode : 126; flag : umf_noinfo; reserved : 0),
+ (unicode : 127; flag : umf_noinfo; reserved : 0),
+ (unicode : 199; flag : umf_noinfo; reserved : 0),
+ (unicode : 252; flag : umf_noinfo; reserved : 0),
+ (unicode : 233; flag : umf_noinfo; reserved : 0),
+ (unicode : 226; flag : umf_noinfo; reserved : 0),
+ (unicode : 228; flag : umf_noinfo; reserved : 0),
+ (unicode : 224; flag : umf_noinfo; reserved : 0),
+ (unicode : 229; flag : umf_noinfo; reserved : 0),
+ (unicode : 231; flag : umf_noinfo; reserved : 0),
+ (unicode : 234; flag : umf_noinfo; reserved : 0),
+ (unicode : 235; flag : umf_noinfo; reserved : 0),
+ (unicode : 232; flag : umf_noinfo; reserved : 0),
+ (unicode : 239; flag : umf_noinfo; reserved : 0),
+ (unicode : 238; flag : umf_noinfo; reserved : 0),
+ (unicode : 236; flag : umf_noinfo; reserved : 0),
+ (unicode : 196; flag : umf_noinfo; reserved : 0),
+ (unicode : 197; flag : umf_noinfo; reserved : 0),
+ (unicode : 201; flag : umf_noinfo; reserved : 0),
+ (unicode : 230; flag : umf_noinfo; reserved : 0),
+ (unicode : 198; flag : umf_noinfo; reserved : 0),
+ (unicode : 244; flag : umf_noinfo; reserved : 0),
+ (unicode : 246; flag : umf_noinfo; reserved : 0),
+ (unicode : 242; flag : umf_noinfo; reserved : 0),
+ (unicode : 251; flag : umf_noinfo; reserved : 0),
+ (unicode : 249; flag : umf_noinfo; reserved : 0),
+ (unicode : 255; flag : umf_noinfo; reserved : 0),
+ (unicode : 214; flag : umf_noinfo; reserved : 0),
+ (unicode : 220; flag : umf_noinfo; reserved : 0),
+ (unicode : 248; flag : umf_noinfo; reserved : 0),
+ (unicode : 163; flag : umf_noinfo; reserved : 0),
+ (unicode : 216; flag : umf_noinfo; reserved : 0),
+ (unicode : 215; flag : umf_noinfo; reserved : 0),
+ (unicode : 402; flag : umf_noinfo; reserved : 0),
+ (unicode : 225; flag : umf_noinfo; reserved : 0),
+ (unicode : 237; flag : umf_noinfo; reserved : 0),
+ (unicode : 243; flag : umf_noinfo; reserved : 0),
+ (unicode : 250; flag : umf_noinfo; reserved : 0),
+ (unicode : 241; flag : umf_noinfo; reserved : 0),
+ (unicode : 209; flag : umf_noinfo; reserved : 0),
+ (unicode : 170; flag : umf_noinfo; reserved : 0),
+ (unicode : 186; flag : umf_noinfo; reserved : 0),
+ (unicode : 191; flag : umf_noinfo; reserved : 0),
+ (unicode : 174; flag : umf_noinfo; reserved : 0),
+ (unicode : 172; flag : umf_noinfo; reserved : 0),
+ (unicode : 189; flag : umf_noinfo; reserved : 0),
+ (unicode : 188; flag : umf_noinfo; reserved : 0),
+ (unicode : 161; flag : umf_noinfo; reserved : 0),
+ (unicode : 171; flag : umf_noinfo; reserved : 0),
+ (unicode : 187; flag : umf_noinfo; reserved : 0),
+ (unicode : 9617; flag : umf_noinfo; reserved : 0),
+ (unicode : 9618; flag : umf_noinfo; reserved : 0),
+ (unicode : 9619; flag : umf_noinfo; reserved : 0),
+ (unicode : 9474; flag : umf_noinfo; reserved : 0),
+ (unicode : 9508; flag : umf_noinfo; reserved : 0),
+ (unicode : 193; flag : umf_noinfo; reserved : 0),
+ (unicode : 194; flag : umf_noinfo; reserved : 0),
+ (unicode : 192; flag : umf_noinfo; reserved : 0),
+ (unicode : 169; flag : umf_noinfo; reserved : 0),
+ (unicode : 9571; flag : umf_noinfo; reserved : 0),
+ (unicode : 9553; flag : umf_noinfo; reserved : 0),
+ (unicode : 9559; flag : umf_noinfo; reserved : 0),
+ (unicode : 9565; flag : umf_noinfo; reserved : 0),
+ (unicode : 162; flag : umf_noinfo; reserved : 0),
+ (unicode : 165; flag : umf_noinfo; reserved : 0),
+ (unicode : 9488; flag : umf_noinfo; reserved : 0),
+ (unicode : 9492; flag : umf_noinfo; reserved : 0),
+ (unicode : 9524; flag : umf_noinfo; reserved : 0),
+ (unicode : 9516; flag : umf_noinfo; reserved : 0),
+ (unicode : 9500; flag : umf_noinfo; reserved : 0),
+ (unicode : 9472; flag : umf_noinfo; reserved : 0),
+ (unicode : 9532; flag : umf_noinfo; reserved : 0),
+ (unicode : 227; flag : umf_noinfo; reserved : 0),
+ (unicode : 195; flag : umf_noinfo; reserved : 0),
+ (unicode : 9562; flag : umf_noinfo; reserved : 0),
+ (unicode : 9556; flag : umf_noinfo; reserved : 0),
+ (unicode : 9577; flag : umf_noinfo; reserved : 0),
+ (unicode : 9574; flag : umf_noinfo; reserved : 0),
+ (unicode : 9568; flag : umf_noinfo; reserved : 0),
+ (unicode : 9552; flag : umf_noinfo; reserved : 0),
+ (unicode : 9580; flag : umf_noinfo; reserved : 0),
+ (unicode : 164; flag : umf_noinfo; reserved : 0),
+ (unicode : 240; flag : umf_noinfo; reserved : 0),
+ (unicode : 208; flag : umf_noinfo; reserved : 0),
+ (unicode : 202; flag : umf_noinfo; reserved : 0),
+ (unicode : 203; flag : umf_noinfo; reserved : 0),
+ (unicode : 200; flag : umf_noinfo; reserved : 0),
+ (unicode : 305; flag : umf_noinfo; reserved : 0),
+ (unicode : 205; flag : umf_noinfo; reserved : 0),
+ (unicode : 206; flag : umf_noinfo; reserved : 0),
+ (unicode : 207; flag : umf_noinfo; reserved : 0),
+ (unicode : 9496; flag : umf_noinfo; reserved : 0),
+ (unicode : 9484; flag : umf_noinfo; reserved : 0),
+ (unicode : 9608; flag : umf_noinfo; reserved : 0),
+ (unicode : 9604; flag : umf_noinfo; reserved : 0),
+ (unicode : 166; flag : umf_noinfo; reserved : 0),
+ (unicode : 204; flag : umf_noinfo; reserved : 0),
+ (unicode : 9600; flag : umf_noinfo; reserved : 0),
+ (unicode : 211; flag : umf_noinfo; reserved : 0),
+ (unicode : 223; flag : umf_noinfo; reserved : 0),
+ (unicode : 212; flag : umf_noinfo; reserved : 0),
+ (unicode : 210; flag : umf_noinfo; reserved : 0),
+ (unicode : 245; flag : umf_noinfo; reserved : 0),
+ (unicode : 213; flag : umf_noinfo; reserved : 0),
+ (unicode : 181; flag : umf_noinfo; reserved : 0),
+ (unicode : 254; flag : umf_noinfo; reserved : 0),
+ (unicode : 222; flag : umf_noinfo; reserved : 0),
+ (unicode : 218; flag : umf_noinfo; reserved : 0),
+ (unicode : 219; flag : umf_noinfo; reserved : 0),
+ (unicode : 217; flag : umf_noinfo; reserved : 0),
+ (unicode : 253; flag : umf_noinfo; reserved : 0),
+ (unicode : 221; flag : umf_noinfo; reserved : 0),
+ (unicode : 175; flag : umf_noinfo; reserved : 0),
+ (unicode : 180; flag : umf_noinfo; reserved : 0),
+ (unicode : 173; flag : umf_noinfo; reserved : 0),
+ (unicode : 177; flag : umf_noinfo; reserved : 0),
+ (unicode : 8215; flag : umf_noinfo; reserved : 0),
+ (unicode : 190; flag : umf_noinfo; reserved : 0),
+ (unicode : 182; flag : umf_noinfo; reserved : 0),
+ (unicode : 167; flag : umf_noinfo; reserved : 0),
+ (unicode : 247; flag : umf_noinfo; reserved : 0),
+ (unicode : 184; flag : umf_noinfo; reserved : 0),
+ (unicode : 176; flag : umf_noinfo; reserved : 0),
+ (unicode : 168; flag : umf_noinfo; reserved : 0),
+ (unicode : 183; flag : umf_noinfo; reserved : 0),
+ (unicode : 185; flag : umf_noinfo; reserved : 0),
+ (unicode : 179; flag : umf_noinfo; reserved : 0),
+ (unicode : 178; flag : umf_noinfo; reserved : 0),
+ (unicode : 9632; flag : umf_noinfo; reserved : 0),
+ (unicode : 160; flag : umf_noinfo; reserved : 0)
+ );
+
+ unicodemap : tunicodemap = (
+ cpname : 'cp850';
+ cp : 850;
+ map : @map[0];
+ lastchar : 255;
+ next : nil;
+ internalmap : true
+ );
+
+ begin
+ registermapping(@unicodemap)
+ end.
diff --git a/closures/compiler/cp866.pas b/closures/compiler/cp866.pas
new file mode 100644
index 0000000000..d36527aee7
--- /dev/null
+++ b/closures/compiler/cp866.pas
@@ -0,0 +1,282 @@
+{ This is an automatically created file, so don't edit it }
+unit cp866;
+
+ interface
+
+ implementation
+
+ uses
+ {$if FPC_FULLVERSION<20700}ccharset{$else}charset{$endif};
+
+ const
+ map : array[0..255] of tunicodecharmapping = (
+ (unicode : 0; flag : umf_noinfo; reserved : 0),
+ (unicode : 1; flag : umf_noinfo; reserved : 0),
+ (unicode : 2; flag : umf_noinfo; reserved : 0),
+ (unicode : 3; flag : umf_noinfo; reserved : 0),
+ (unicode : 4; flag : umf_noinfo; reserved : 0),
+ (unicode : 5; flag : umf_noinfo; reserved : 0),
+ (unicode : 6; flag : umf_noinfo; reserved : 0),
+ (unicode : 7; flag : umf_noinfo; reserved : 0),
+ (unicode : 8; flag : umf_noinfo; reserved : 0),
+ (unicode : 9; flag : umf_noinfo; reserved : 0),
+ (unicode : 10; flag : umf_noinfo; reserved : 0),
+ (unicode : 11; flag : umf_noinfo; reserved : 0),
+ (unicode : 12; flag : umf_noinfo; reserved : 0),
+ (unicode : 13; flag : umf_noinfo; reserved : 0),
+ (unicode : 14; flag : umf_noinfo; reserved : 0),
+ (unicode : 15; flag : umf_noinfo; reserved : 0),
+ (unicode : 16; flag : umf_noinfo; reserved : 0),
+ (unicode : 17; flag : umf_noinfo; reserved : 0),
+ (unicode : 18; flag : umf_noinfo; reserved : 0),
+ (unicode : 19; flag : umf_noinfo; reserved : 0),
+ (unicode : 20; flag : umf_noinfo; reserved : 0),
+ (unicode : 21; flag : umf_noinfo; reserved : 0),
+ (unicode : 22; flag : umf_noinfo; reserved : 0),
+ (unicode : 23; flag : umf_noinfo; reserved : 0),
+ (unicode : 24; flag : umf_noinfo; reserved : 0),
+ (unicode : 25; flag : umf_noinfo; reserved : 0),
+ (unicode : 26; flag : umf_noinfo; reserved : 0),
+ (unicode : 27; flag : umf_noinfo; reserved : 0),
+ (unicode : 28; flag : umf_noinfo; reserved : 0),
+ (unicode : 29; flag : umf_noinfo; reserved : 0),
+ (unicode : 30; flag : umf_noinfo; reserved : 0),
+ (unicode : 31; flag : umf_noinfo; reserved : 0),
+ (unicode : 32; flag : umf_noinfo; reserved : 0),
+ (unicode : 33; flag : umf_noinfo; reserved : 0),
+ (unicode : 34; flag : umf_noinfo; reserved : 0),
+ (unicode : 35; flag : umf_noinfo; reserved : 0),
+ (unicode : 36; flag : umf_noinfo; reserved : 0),
+ (unicode : 37; flag : umf_noinfo; reserved : 0),
+ (unicode : 38; flag : umf_noinfo; reserved : 0),
+ (unicode : 39; flag : umf_noinfo; reserved : 0),
+ (unicode : 40; flag : umf_noinfo; reserved : 0),
+ (unicode : 41; flag : umf_noinfo; reserved : 0),
+ (unicode : 42; flag : umf_noinfo; reserved : 0),
+ (unicode : 43; flag : umf_noinfo; reserved : 0),
+ (unicode : 44; flag : umf_noinfo; reserved : 0),
+ (unicode : 45; flag : umf_noinfo; reserved : 0),
+ (unicode : 46; flag : umf_noinfo; reserved : 0),
+ (unicode : 47; flag : umf_noinfo; reserved : 0),
+ (unicode : 48; flag : umf_noinfo; reserved : 0),
+ (unicode : 49; flag : umf_noinfo; reserved : 0),
+ (unicode : 50; flag : umf_noinfo; reserved : 0),
+ (unicode : 51; flag : umf_noinfo; reserved : 0),
+ (unicode : 52; flag : umf_noinfo; reserved : 0),
+ (unicode : 53; flag : umf_noinfo; reserved : 0),
+ (unicode : 54; flag : umf_noinfo; reserved : 0),
+ (unicode : 55; flag : umf_noinfo; reserved : 0),
+ (unicode : 56; flag : umf_noinfo; reserved : 0),
+ (unicode : 57; flag : umf_noinfo; reserved : 0),
+ (unicode : 58; flag : umf_noinfo; reserved : 0),
+ (unicode : 59; flag : umf_noinfo; reserved : 0),
+ (unicode : 60; flag : umf_noinfo; reserved : 0),
+ (unicode : 61; flag : umf_noinfo; reserved : 0),
+ (unicode : 62; flag : umf_noinfo; reserved : 0),
+ (unicode : 63; flag : umf_noinfo; reserved : 0),
+ (unicode : 64; flag : umf_noinfo; reserved : 0),
+ (unicode : 65; flag : umf_noinfo; reserved : 0),
+ (unicode : 66; flag : umf_noinfo; reserved : 0),
+ (unicode : 67; flag : umf_noinfo; reserved : 0),
+ (unicode : 68; flag : umf_noinfo; reserved : 0),
+ (unicode : 69; flag : umf_noinfo; reserved : 0),
+ (unicode : 70; flag : umf_noinfo; reserved : 0),
+ (unicode : 71; flag : umf_noinfo; reserved : 0),
+ (unicode : 72; flag : umf_noinfo; reserved : 0),
+ (unicode : 73; flag : umf_noinfo; reserved : 0),
+ (unicode : 74; flag : umf_noinfo; reserved : 0),
+ (unicode : 75; flag : umf_noinfo; reserved : 0),
+ (unicode : 76; flag : umf_noinfo; reserved : 0),
+ (unicode : 77; flag : umf_noinfo; reserved : 0),
+ (unicode : 78; flag : umf_noinfo; reserved : 0),
+ (unicode : 79; flag : umf_noinfo; reserved : 0),
+ (unicode : 80; flag : umf_noinfo; reserved : 0),
+ (unicode : 81; flag : umf_noinfo; reserved : 0),
+ (unicode : 82; flag : umf_noinfo; reserved : 0),
+ (unicode : 83; flag : umf_noinfo; reserved : 0),
+ (unicode : 84; flag : umf_noinfo; reserved : 0),
+ (unicode : 85; flag : umf_noinfo; reserved : 0),
+ (unicode : 86; flag : umf_noinfo; reserved : 0),
+ (unicode : 87; flag : umf_noinfo; reserved : 0),
+ (unicode : 88; flag : umf_noinfo; reserved : 0),
+ (unicode : 89; flag : umf_noinfo; reserved : 0),
+ (unicode : 90; flag : umf_noinfo; reserved : 0),
+ (unicode : 91; flag : umf_noinfo; reserved : 0),
+ (unicode : 92; flag : umf_noinfo; reserved : 0),
+ (unicode : 93; flag : umf_noinfo; reserved : 0),
+ (unicode : 94; flag : umf_noinfo; reserved : 0),
+ (unicode : 95; flag : umf_noinfo; reserved : 0),
+ (unicode : 96; flag : umf_noinfo; reserved : 0),
+ (unicode : 97; flag : umf_noinfo; reserved : 0),
+ (unicode : 98; flag : umf_noinfo; reserved : 0),
+ (unicode : 99; flag : umf_noinfo; reserved : 0),
+ (unicode : 100; flag : umf_noinfo; reserved : 0),
+ (unicode : 101; flag : umf_noinfo; reserved : 0),
+ (unicode : 102; flag : umf_noinfo; reserved : 0),
+ (unicode : 103; flag : umf_noinfo; reserved : 0),
+ (unicode : 104; flag : umf_noinfo; reserved : 0),
+ (unicode : 105; flag : umf_noinfo; reserved : 0),
+ (unicode : 106; flag : umf_noinfo; reserved : 0),
+ (unicode : 107; flag : umf_noinfo; reserved : 0),
+ (unicode : 108; flag : umf_noinfo; reserved : 0),
+ (unicode : 109; flag : umf_noinfo; reserved : 0),
+ (unicode : 110; flag : umf_noinfo; reserved : 0),
+ (unicode : 111; flag : umf_noinfo; reserved : 0),
+ (unicode : 112; flag : umf_noinfo; reserved : 0),
+ (unicode : 113; flag : umf_noinfo; reserved : 0),
+ (unicode : 114; flag : umf_noinfo; reserved : 0),
+ (unicode : 115; flag : umf_noinfo; reserved : 0),
+ (unicode : 116; flag : umf_noinfo; reserved : 0),
+ (unicode : 117; flag : umf_noinfo; reserved : 0),
+ (unicode : 118; flag : umf_noinfo; reserved : 0),
+ (unicode : 119; flag : umf_noinfo; reserved : 0),
+ (unicode : 120; flag : umf_noinfo; reserved : 0),
+ (unicode : 121; flag : umf_noinfo; reserved : 0),
+ (unicode : 122; flag : umf_noinfo; reserved : 0),
+ (unicode : 123; flag : umf_noinfo; reserved : 0),
+ (unicode : 124; flag : umf_noinfo; reserved : 0),
+ (unicode : 125; flag : umf_noinfo; reserved : 0),
+ (unicode : 126; flag : umf_noinfo; reserved : 0),
+ (unicode : 127; flag : umf_noinfo; reserved : 0),
+ (unicode : 1040; flag : umf_noinfo; reserved : 0),
+ (unicode : 1041; flag : umf_noinfo; reserved : 0),
+ (unicode : 1042; flag : umf_noinfo; reserved : 0),
+ (unicode : 1043; flag : umf_noinfo; reserved : 0),
+ (unicode : 1044; flag : umf_noinfo; reserved : 0),
+ (unicode : 1045; flag : umf_noinfo; reserved : 0),
+ (unicode : 1046; flag : umf_noinfo; reserved : 0),
+ (unicode : 1047; flag : umf_noinfo; reserved : 0),
+ (unicode : 1048; flag : umf_noinfo; reserved : 0),
+ (unicode : 1049; flag : umf_noinfo; reserved : 0),
+ (unicode : 1050; flag : umf_noinfo; reserved : 0),
+ (unicode : 1051; flag : umf_noinfo; reserved : 0),
+ (unicode : 1052; flag : umf_noinfo; reserved : 0),
+ (unicode : 1053; flag : umf_noinfo; reserved : 0),
+ (unicode : 1054; flag : umf_noinfo; reserved : 0),
+ (unicode : 1055; flag : umf_noinfo; reserved : 0),
+ (unicode : 1056; flag : umf_noinfo; reserved : 0),
+ (unicode : 1057; flag : umf_noinfo; reserved : 0),
+ (unicode : 1058; flag : umf_noinfo; reserved : 0),
+ (unicode : 1059; flag : umf_noinfo; reserved : 0),
+ (unicode : 1060; flag : umf_noinfo; reserved : 0),
+ (unicode : 1061; flag : umf_noinfo; reserved : 0),
+ (unicode : 1062; flag : umf_noinfo; reserved : 0),
+ (unicode : 1063; flag : umf_noinfo; reserved : 0),
+ (unicode : 1064; flag : umf_noinfo; reserved : 0),
+ (unicode : 1065; flag : umf_noinfo; reserved : 0),
+ (unicode : 1066; flag : umf_noinfo; reserved : 0),
+ (unicode : 1067; flag : umf_noinfo; reserved : 0),
+ (unicode : 1068; flag : umf_noinfo; reserved : 0),
+ (unicode : 1069; flag : umf_noinfo; reserved : 0),
+ (unicode : 1070; flag : umf_noinfo; reserved : 0),
+ (unicode : 1071; flag : umf_noinfo; reserved : 0),
+ (unicode : 1072; flag : umf_noinfo; reserved : 0),
+ (unicode : 1073; flag : umf_noinfo; reserved : 0),
+ (unicode : 1074; flag : umf_noinfo; reserved : 0),
+ (unicode : 1075; flag : umf_noinfo; reserved : 0),
+ (unicode : 1076; flag : umf_noinfo; reserved : 0),
+ (unicode : 1077; flag : umf_noinfo; reserved : 0),
+ (unicode : 1078; flag : umf_noinfo; reserved : 0),
+ (unicode : 1079; flag : umf_noinfo; reserved : 0),
+ (unicode : 1080; flag : umf_noinfo; reserved : 0),
+ (unicode : 1081; flag : umf_noinfo; reserved : 0),
+ (unicode : 1082; flag : umf_noinfo; reserved : 0),
+ (unicode : 1083; flag : umf_noinfo; reserved : 0),
+ (unicode : 1084; flag : umf_noinfo; reserved : 0),
+ (unicode : 1085; flag : umf_noinfo; reserved : 0),
+ (unicode : 1086; flag : umf_noinfo; reserved : 0),
+ (unicode : 1087; flag : umf_noinfo; reserved : 0),
+ (unicode : 9617; flag : umf_noinfo; reserved : 0),
+ (unicode : 9618; flag : umf_noinfo; reserved : 0),
+ (unicode : 9619; flag : umf_noinfo; reserved : 0),
+ (unicode : 9474; flag : umf_noinfo; reserved : 0),
+ (unicode : 9508; flag : umf_noinfo; reserved : 0),
+ (unicode : 9569; flag : umf_noinfo; reserved : 0),
+ (unicode : 9570; flag : umf_noinfo; reserved : 0),
+ (unicode : 9558; flag : umf_noinfo; reserved : 0),
+ (unicode : 9557; flag : umf_noinfo; reserved : 0),
+ (unicode : 9571; flag : umf_noinfo; reserved : 0),
+ (unicode : 9553; flag : umf_noinfo; reserved : 0),
+ (unicode : 9559; flag : umf_noinfo; reserved : 0),
+ (unicode : 9565; flag : umf_noinfo; reserved : 0),
+ (unicode : 9564; flag : umf_noinfo; reserved : 0),
+ (unicode : 9563; flag : umf_noinfo; reserved : 0),
+ (unicode : 9488; flag : umf_noinfo; reserved : 0),
+ (unicode : 9492; flag : umf_noinfo; reserved : 0),
+ (unicode : 9524; flag : umf_noinfo; reserved : 0),
+ (unicode : 9516; flag : umf_noinfo; reserved : 0),
+ (unicode : 9500; flag : umf_noinfo; reserved : 0),
+ (unicode : 9472; flag : umf_noinfo; reserved : 0),
+ (unicode : 9532; flag : umf_noinfo; reserved : 0),
+ (unicode : 9566; flag : umf_noinfo; reserved : 0),
+ (unicode : 9567; flag : umf_noinfo; reserved : 0),
+ (unicode : 9562; flag : umf_noinfo; reserved : 0),
+ (unicode : 9556; flag : umf_noinfo; reserved : 0),
+ (unicode : 9577; flag : umf_noinfo; reserved : 0),
+ (unicode : 9574; flag : umf_noinfo; reserved : 0),
+ (unicode : 9568; flag : umf_noinfo; reserved : 0),
+ (unicode : 9552; flag : umf_noinfo; reserved : 0),
+ (unicode : 9580; flag : umf_noinfo; reserved : 0),
+ (unicode : 9575; flag : umf_noinfo; reserved : 0),
+ (unicode : 9576; flag : umf_noinfo; reserved : 0),
+ (unicode : 9572; flag : umf_noinfo; reserved : 0),
+ (unicode : 9573; flag : umf_noinfo; reserved : 0),
+ (unicode : 9561; flag : umf_noinfo; reserved : 0),
+ (unicode : 9560; flag : umf_noinfo; reserved : 0),
+ (unicode : 9554; flag : umf_noinfo; reserved : 0),
+ (unicode : 9555; flag : umf_noinfo; reserved : 0),
+ (unicode : 9579; flag : umf_noinfo; reserved : 0),
+ (unicode : 9578; flag : umf_noinfo; reserved : 0),
+ (unicode : 9496; flag : umf_noinfo; reserved : 0),
+ (unicode : 9484; flag : umf_noinfo; reserved : 0),
+ (unicode : 9608; flag : umf_noinfo; reserved : 0),
+ (unicode : 9604; flag : umf_noinfo; reserved : 0),
+ (unicode : 9612; flag : umf_noinfo; reserved : 0),
+ (unicode : 9616; flag : umf_noinfo; reserved : 0),
+ (unicode : 9600; flag : umf_noinfo; reserved : 0),
+ (unicode : 1088; flag : umf_noinfo; reserved : 0),
+ (unicode : 1089; flag : umf_noinfo; reserved : 0),
+ (unicode : 1090; flag : umf_noinfo; reserved : 0),
+ (unicode : 1091; flag : umf_noinfo; reserved : 0),
+ (unicode : 1092; flag : umf_noinfo; reserved : 0),
+ (unicode : 1093; flag : umf_noinfo; reserved : 0),
+ (unicode : 1094; flag : umf_noinfo; reserved : 0),
+ (unicode : 1095; flag : umf_noinfo; reserved : 0),
+ (unicode : 1096; flag : umf_noinfo; reserved : 0),
+ (unicode : 1097; flag : umf_noinfo; reserved : 0),
+ (unicode : 1098; flag : umf_noinfo; reserved : 0),
+ (unicode : 1099; flag : umf_noinfo; reserved : 0),
+ (unicode : 1100; flag : umf_noinfo; reserved : 0),
+ (unicode : 1101; flag : umf_noinfo; reserved : 0),
+ (unicode : 1102; flag : umf_noinfo; reserved : 0),
+ (unicode : 1103; flag : umf_noinfo; reserved : 0),
+ (unicode : 1025; flag : umf_noinfo; reserved : 0),
+ (unicode : 1105; flag : umf_noinfo; reserved : 0),
+ (unicode : 1028; flag : umf_noinfo; reserved : 0),
+ (unicode : 1108; flag : umf_noinfo; reserved : 0),
+ (unicode : 1031; flag : umf_noinfo; reserved : 0),
+ (unicode : 1111; flag : umf_noinfo; reserved : 0),
+ (unicode : 1038; flag : umf_noinfo; reserved : 0),
+ (unicode : 1118; flag : umf_noinfo; reserved : 0),
+ (unicode : 176; flag : umf_noinfo; reserved : 0),
+ (unicode : 8729; flag : umf_noinfo; reserved : 0),
+ (unicode : 183; flag : umf_noinfo; reserved : 0),
+ (unicode : 8730; flag : umf_noinfo; reserved : 0),
+ (unicode : 8470; flag : umf_noinfo; reserved : 0),
+ (unicode : 164; flag : umf_noinfo; reserved : 0),
+ (unicode : 9632; flag : umf_noinfo; reserved : 0),
+ (unicode : 160; flag : umf_noinfo; reserved : 0)
+ );
+
+ unicodemap : tunicodemap = (
+ cpname : 'cp866';
+ cp : 866;
+ map : @map;
+ lastchar : 255;
+ next : nil;
+ internalmap : true
+ );
+
+ begin
+ registermapping(@unicodemap)
+ end.
diff --git a/closures/compiler/cp8859_1.pas b/closures/compiler/cp8859_1.pas
new file mode 100644
index 0000000000..ed4f04d3b6
--- /dev/null
+++ b/closures/compiler/cp8859_1.pas
@@ -0,0 +1,282 @@
+{ This is an automatically created file, so don't edit it }
+unit cp8859_1;
+
+ interface
+
+ implementation
+
+ uses
+ {$if FPC_FULLVERSION<20700}ccharset{$else}charset{$endif};
+
+ const
+ map : array[0..255] of tunicodecharmapping = (
+ (unicode : 0; flag : umf_noinfo; reserved : 0),
+ (unicode : 1; flag : umf_noinfo; reserved : 0),
+ (unicode : 2; flag : umf_noinfo; reserved : 0),
+ (unicode : 3; flag : umf_noinfo; reserved : 0),
+ (unicode : 4; flag : umf_noinfo; reserved : 0),
+ (unicode : 5; flag : umf_noinfo; reserved : 0),
+ (unicode : 6; flag : umf_noinfo; reserved : 0),
+ (unicode : 7; flag : umf_noinfo; reserved : 0),
+ (unicode : 8; flag : umf_noinfo; reserved : 0),
+ (unicode : 9; flag : umf_noinfo; reserved : 0),
+ (unicode : 10; flag : umf_noinfo; reserved : 0),
+ (unicode : 11; flag : umf_noinfo; reserved : 0),
+ (unicode : 12; flag : umf_noinfo; reserved : 0),
+ (unicode : 13; flag : umf_noinfo; reserved : 0),
+ (unicode : 14; flag : umf_noinfo; reserved : 0),
+ (unicode : 15; flag : umf_noinfo; reserved : 0),
+ (unicode : 16; flag : umf_noinfo; reserved : 0),
+ (unicode : 17; flag : umf_noinfo; reserved : 0),
+ (unicode : 18; flag : umf_noinfo; reserved : 0),
+ (unicode : 19; flag : umf_noinfo; reserved : 0),
+ (unicode : 20; flag : umf_noinfo; reserved : 0),
+ (unicode : 21; flag : umf_noinfo; reserved : 0),
+ (unicode : 22; flag : umf_noinfo; reserved : 0),
+ (unicode : 23; flag : umf_noinfo; reserved : 0),
+ (unicode : 24; flag : umf_noinfo; reserved : 0),
+ (unicode : 25; flag : umf_noinfo; reserved : 0),
+ (unicode : 26; flag : umf_noinfo; reserved : 0),
+ (unicode : 27; flag : umf_noinfo; reserved : 0),
+ (unicode : 28; flag : umf_noinfo; reserved : 0),
+ (unicode : 29; flag : umf_noinfo; reserved : 0),
+ (unicode : 30; flag : umf_noinfo; reserved : 0),
+ (unicode : 31; flag : umf_noinfo; reserved : 0),
+ (unicode : 32; flag : umf_noinfo; reserved : 0),
+ (unicode : 33; flag : umf_noinfo; reserved : 0),
+ (unicode : 34; flag : umf_noinfo; reserved : 0),
+ (unicode : 35; flag : umf_noinfo; reserved : 0),
+ (unicode : 36; flag : umf_noinfo; reserved : 0),
+ (unicode : 37; flag : umf_noinfo; reserved : 0),
+ (unicode : 38; flag : umf_noinfo; reserved : 0),
+ (unicode : 39; flag : umf_noinfo; reserved : 0),
+ (unicode : 40; flag : umf_noinfo; reserved : 0),
+ (unicode : 41; flag : umf_noinfo; reserved : 0),
+ (unicode : 42; flag : umf_noinfo; reserved : 0),
+ (unicode : 43; flag : umf_noinfo; reserved : 0),
+ (unicode : 44; flag : umf_noinfo; reserved : 0),
+ (unicode : 45; flag : umf_noinfo; reserved : 0),
+ (unicode : 46; flag : umf_noinfo; reserved : 0),
+ (unicode : 47; flag : umf_noinfo; reserved : 0),
+ (unicode : 48; flag : umf_noinfo; reserved : 0),
+ (unicode : 49; flag : umf_noinfo; reserved : 0),
+ (unicode : 50; flag : umf_noinfo; reserved : 0),
+ (unicode : 51; flag : umf_noinfo; reserved : 0),
+ (unicode : 52; flag : umf_noinfo; reserved : 0),
+ (unicode : 53; flag : umf_noinfo; reserved : 0),
+ (unicode : 54; flag : umf_noinfo; reserved : 0),
+ (unicode : 55; flag : umf_noinfo; reserved : 0),
+ (unicode : 56; flag : umf_noinfo; reserved : 0),
+ (unicode : 57; flag : umf_noinfo; reserved : 0),
+ (unicode : 58; flag : umf_noinfo; reserved : 0),
+ (unicode : 59; flag : umf_noinfo; reserved : 0),
+ (unicode : 60; flag : umf_noinfo; reserved : 0),
+ (unicode : 61; flag : umf_noinfo; reserved : 0),
+ (unicode : 62; flag : umf_noinfo; reserved : 0),
+ (unicode : 63; flag : umf_noinfo; reserved : 0),
+ (unicode : 64; flag : umf_noinfo; reserved : 0),
+ (unicode : 65; flag : umf_noinfo; reserved : 0),
+ (unicode : 66; flag : umf_noinfo; reserved : 0),
+ (unicode : 67; flag : umf_noinfo; reserved : 0),
+ (unicode : 68; flag : umf_noinfo; reserved : 0),
+ (unicode : 69; flag : umf_noinfo; reserved : 0),
+ (unicode : 70; flag : umf_noinfo; reserved : 0),
+ (unicode : 71; flag : umf_noinfo; reserved : 0),
+ (unicode : 72; flag : umf_noinfo; reserved : 0),
+ (unicode : 73; flag : umf_noinfo; reserved : 0),
+ (unicode : 74; flag : umf_noinfo; reserved : 0),
+ (unicode : 75; flag : umf_noinfo; reserved : 0),
+ (unicode : 76; flag : umf_noinfo; reserved : 0),
+ (unicode : 77; flag : umf_noinfo; reserved : 0),
+ (unicode : 78; flag : umf_noinfo; reserved : 0),
+ (unicode : 79; flag : umf_noinfo; reserved : 0),
+ (unicode : 80; flag : umf_noinfo; reserved : 0),
+ (unicode : 81; flag : umf_noinfo; reserved : 0),
+ (unicode : 82; flag : umf_noinfo; reserved : 0),
+ (unicode : 83; flag : umf_noinfo; reserved : 0),
+ (unicode : 84; flag : umf_noinfo; reserved : 0),
+ (unicode : 85; flag : umf_noinfo; reserved : 0),
+ (unicode : 86; flag : umf_noinfo; reserved : 0),
+ (unicode : 87; flag : umf_noinfo; reserved : 0),
+ (unicode : 88; flag : umf_noinfo; reserved : 0),
+ (unicode : 89; flag : umf_noinfo; reserved : 0),
+ (unicode : 90; flag : umf_noinfo; reserved : 0),
+ (unicode : 91; flag : umf_noinfo; reserved : 0),
+ (unicode : 92; flag : umf_noinfo; reserved : 0),
+ (unicode : 93; flag : umf_noinfo; reserved : 0),
+ (unicode : 94; flag : umf_noinfo; reserved : 0),
+ (unicode : 95; flag : umf_noinfo; reserved : 0),
+ (unicode : 96; flag : umf_noinfo; reserved : 0),
+ (unicode : 97; flag : umf_noinfo; reserved : 0),
+ (unicode : 98; flag : umf_noinfo; reserved : 0),
+ (unicode : 99; flag : umf_noinfo; reserved : 0),
+ (unicode : 100; flag : umf_noinfo; reserved : 0),
+ (unicode : 101; flag : umf_noinfo; reserved : 0),
+ (unicode : 102; flag : umf_noinfo; reserved : 0),
+ (unicode : 103; flag : umf_noinfo; reserved : 0),
+ (unicode : 104; flag : umf_noinfo; reserved : 0),
+ (unicode : 105; flag : umf_noinfo; reserved : 0),
+ (unicode : 106; flag : umf_noinfo; reserved : 0),
+ (unicode : 107; flag : umf_noinfo; reserved : 0),
+ (unicode : 108; flag : umf_noinfo; reserved : 0),
+ (unicode : 109; flag : umf_noinfo; reserved : 0),
+ (unicode : 110; flag : umf_noinfo; reserved : 0),
+ (unicode : 111; flag : umf_noinfo; reserved : 0),
+ (unicode : 112; flag : umf_noinfo; reserved : 0),
+ (unicode : 113; flag : umf_noinfo; reserved : 0),
+ (unicode : 114; flag : umf_noinfo; reserved : 0),
+ (unicode : 115; flag : umf_noinfo; reserved : 0),
+ (unicode : 116; flag : umf_noinfo; reserved : 0),
+ (unicode : 117; flag : umf_noinfo; reserved : 0),
+ (unicode : 118; flag : umf_noinfo; reserved : 0),
+ (unicode : 119; flag : umf_noinfo; reserved : 0),
+ (unicode : 120; flag : umf_noinfo; reserved : 0),
+ (unicode : 121; flag : umf_noinfo; reserved : 0),
+ (unicode : 122; flag : umf_noinfo; reserved : 0),
+ (unicode : 123; flag : umf_noinfo; reserved : 0),
+ (unicode : 124; flag : umf_noinfo; reserved : 0),
+ (unicode : 125; flag : umf_noinfo; reserved : 0),
+ (unicode : 126; flag : umf_noinfo; reserved : 0),
+ (unicode : 127; flag : umf_noinfo; reserved : 0),
+ (unicode : 128; flag : umf_noinfo; reserved : 0),
+ (unicode : 129; flag : umf_noinfo; reserved : 0),
+ (unicode : 130; flag : umf_noinfo; reserved : 0),
+ (unicode : 131; flag : umf_noinfo; reserved : 0),
+ (unicode : 132; flag : umf_noinfo; reserved : 0),
+ (unicode : 133; flag : umf_noinfo; reserved : 0),
+ (unicode : 134; flag : umf_noinfo; reserved : 0),
+ (unicode : 135; flag : umf_noinfo; reserved : 0),
+ (unicode : 136; flag : umf_noinfo; reserved : 0),
+ (unicode : 137; flag : umf_noinfo; reserved : 0),
+ (unicode : 138; flag : umf_noinfo; reserved : 0),
+ (unicode : 139; flag : umf_noinfo; reserved : 0),
+ (unicode : 140; flag : umf_noinfo; reserved : 0),
+ (unicode : 141; flag : umf_noinfo; reserved : 0),
+ (unicode : 142; flag : umf_noinfo; reserved : 0),
+ (unicode : 143; flag : umf_noinfo; reserved : 0),
+ (unicode : 144; flag : umf_noinfo; reserved : 0),
+ (unicode : 145; flag : umf_noinfo; reserved : 0),
+ (unicode : 146; flag : umf_noinfo; reserved : 0),
+ (unicode : 147; flag : umf_noinfo; reserved : 0),
+ (unicode : 148; flag : umf_noinfo; reserved : 0),
+ (unicode : 149; flag : umf_noinfo; reserved : 0),
+ (unicode : 150; flag : umf_noinfo; reserved : 0),
+ (unicode : 151; flag : umf_noinfo; reserved : 0),
+ (unicode : 152; flag : umf_noinfo; reserved : 0),
+ (unicode : 153; flag : umf_noinfo; reserved : 0),
+ (unicode : 154; flag : umf_noinfo; reserved : 0),
+ (unicode : 155; flag : umf_noinfo; reserved : 0),
+ (unicode : 156; flag : umf_noinfo; reserved : 0),
+ (unicode : 157; flag : umf_noinfo; reserved : 0),
+ (unicode : 158; flag : umf_noinfo; reserved : 0),
+ (unicode : 159; flag : umf_noinfo; reserved : 0),
+ (unicode : 160; flag : umf_noinfo; reserved : 0),
+ (unicode : 161; flag : umf_noinfo; reserved : 0),
+ (unicode : 162; flag : umf_noinfo; reserved : 0),
+ (unicode : 163; flag : umf_noinfo; reserved : 0),
+ (unicode : 164; flag : umf_noinfo; reserved : 0),
+ (unicode : 165; flag : umf_noinfo; reserved : 0),
+ (unicode : 166; flag : umf_noinfo; reserved : 0),
+ (unicode : 167; flag : umf_noinfo; reserved : 0),
+ (unicode : 168; flag : umf_noinfo; reserved : 0),
+ (unicode : 169; flag : umf_noinfo; reserved : 0),
+ (unicode : 170; flag : umf_noinfo; reserved : 0),
+ (unicode : 171; flag : umf_noinfo; reserved : 0),
+ (unicode : 172; flag : umf_noinfo; reserved : 0),
+ (unicode : 173; flag : umf_noinfo; reserved : 0),
+ (unicode : 174; flag : umf_noinfo; reserved : 0),
+ (unicode : 175; flag : umf_noinfo; reserved : 0),
+ (unicode : 176; flag : umf_noinfo; reserved : 0),
+ (unicode : 177; flag : umf_noinfo; reserved : 0),
+ (unicode : 178; flag : umf_noinfo; reserved : 0),
+ (unicode : 179; flag : umf_noinfo; reserved : 0),
+ (unicode : 180; flag : umf_noinfo; reserved : 0),
+ (unicode : 181; flag : umf_noinfo; reserved : 0),
+ (unicode : 182; flag : umf_noinfo; reserved : 0),
+ (unicode : 183; flag : umf_noinfo; reserved : 0),
+ (unicode : 184; flag : umf_noinfo; reserved : 0),
+ (unicode : 185; flag : umf_noinfo; reserved : 0),
+ (unicode : 186; flag : umf_noinfo; reserved : 0),
+ (unicode : 187; flag : umf_noinfo; reserved : 0),
+ (unicode : 188; flag : umf_noinfo; reserved : 0),
+ (unicode : 189; flag : umf_noinfo; reserved : 0),
+ (unicode : 190; flag : umf_noinfo; reserved : 0),
+ (unicode : 191; flag : umf_noinfo; reserved : 0),
+ (unicode : 192; flag : umf_noinfo; reserved : 0),
+ (unicode : 193; flag : umf_noinfo; reserved : 0),
+ (unicode : 194; flag : umf_noinfo; reserved : 0),
+ (unicode : 195; flag : umf_noinfo; reserved : 0),
+ (unicode : 196; flag : umf_noinfo; reserved : 0),
+ (unicode : 197; flag : umf_noinfo; reserved : 0),
+ (unicode : 198; flag : umf_noinfo; reserved : 0),
+ (unicode : 199; flag : umf_noinfo; reserved : 0),
+ (unicode : 200; flag : umf_noinfo; reserved : 0),
+ (unicode : 201; flag : umf_noinfo; reserved : 0),
+ (unicode : 202; flag : umf_noinfo; reserved : 0),
+ (unicode : 203; flag : umf_noinfo; reserved : 0),
+ (unicode : 204; flag : umf_noinfo; reserved : 0),
+ (unicode : 205; flag : umf_noinfo; reserved : 0),
+ (unicode : 206; flag : umf_noinfo; reserved : 0),
+ (unicode : 207; flag : umf_noinfo; reserved : 0),
+ (unicode : 208; flag : umf_noinfo; reserved : 0),
+ (unicode : 209; flag : umf_noinfo; reserved : 0),
+ (unicode : 210; flag : umf_noinfo; reserved : 0),
+ (unicode : 211; flag : umf_noinfo; reserved : 0),
+ (unicode : 212; flag : umf_noinfo; reserved : 0),
+ (unicode : 213; flag : umf_noinfo; reserved : 0),
+ (unicode : 214; flag : umf_noinfo; reserved : 0),
+ (unicode : 215; flag : umf_noinfo; reserved : 0),
+ (unicode : 216; flag : umf_noinfo; reserved : 0),
+ (unicode : 217; flag : umf_noinfo; reserved : 0),
+ (unicode : 218; flag : umf_noinfo; reserved : 0),
+ (unicode : 219; flag : umf_noinfo; reserved : 0),
+ (unicode : 220; flag : umf_noinfo; reserved : 0),
+ (unicode : 221; flag : umf_noinfo; reserved : 0),
+ (unicode : 222; flag : umf_noinfo; reserved : 0),
+ (unicode : 223; flag : umf_noinfo; reserved : 0),
+ (unicode : 224; flag : umf_noinfo; reserved : 0),
+ (unicode : 225; flag : umf_noinfo; reserved : 0),
+ (unicode : 226; flag : umf_noinfo; reserved : 0),
+ (unicode : 227; flag : umf_noinfo; reserved : 0),
+ (unicode : 228; flag : umf_noinfo; reserved : 0),
+ (unicode : 229; flag : umf_noinfo; reserved : 0),
+ (unicode : 230; flag : umf_noinfo; reserved : 0),
+ (unicode : 231; flag : umf_noinfo; reserved : 0),
+ (unicode : 232; flag : umf_noinfo; reserved : 0),
+ (unicode : 233; flag : umf_noinfo; reserved : 0),
+ (unicode : 234; flag : umf_noinfo; reserved : 0),
+ (unicode : 235; flag : umf_noinfo; reserved : 0),
+ (unicode : 236; flag : umf_noinfo; reserved : 0),
+ (unicode : 237; flag : umf_noinfo; reserved : 0),
+ (unicode : 238; flag : umf_noinfo; reserved : 0),
+ (unicode : 239; flag : umf_noinfo; reserved : 0),
+ (unicode : 240; flag : umf_noinfo; reserved : 0),
+ (unicode : 241; flag : umf_noinfo; reserved : 0),
+ (unicode : 242; flag : umf_noinfo; reserved : 0),
+ (unicode : 243; flag : umf_noinfo; reserved : 0),
+ (unicode : 244; flag : umf_noinfo; reserved : 0),
+ (unicode : 245; flag : umf_noinfo; reserved : 0),
+ (unicode : 246; flag : umf_noinfo; reserved : 0),
+ (unicode : 247; flag : umf_noinfo; reserved : 0),
+ (unicode : 248; flag : umf_noinfo; reserved : 0),
+ (unicode : 249; flag : umf_noinfo; reserved : 0),
+ (unicode : 250; flag : umf_noinfo; reserved : 0),
+ (unicode : 251; flag : umf_noinfo; reserved : 0),
+ (unicode : 252; flag : umf_noinfo; reserved : 0),
+ (unicode : 253; flag : umf_noinfo; reserved : 0),
+ (unicode : 254; flag : umf_noinfo; reserved : 0),
+ (unicode : 255; flag : umf_noinfo; reserved : 0)
+ );
+
+ unicodemap : tunicodemap = (
+ cpname : '8859-1';
+ cp : 28591;
+ map : @map[0];
+ lastchar : 255;
+ next : nil;
+ internalmap : true
+ );
+
+ begin
+ registermapping(@unicodemap)
+ end.
diff --git a/closures/compiler/cp8859_5.pas b/closures/compiler/cp8859_5.pas
new file mode 100644
index 0000000000..641c1c0582
--- /dev/null
+++ b/closures/compiler/cp8859_5.pas
@@ -0,0 +1,282 @@
+{ This is an automatically created file, so don't edit it }
+unit cp8859_5;
+
+ interface
+
+ implementation
+
+ uses
+ {$if FPC_FULLVERSION<20700}ccharset{$else}charset{$endif};
+
+ const
+ map : array[0..255] of tunicodecharmapping = (
+ (unicode : 0; flag : umf_noinfo; reserved : 0),
+ (unicode : 1; flag : umf_noinfo; reserved : 0),
+ (unicode : 2; flag : umf_noinfo; reserved : 0),
+ (unicode : 3; flag : umf_noinfo; reserved : 0),
+ (unicode : 4; flag : umf_noinfo; reserved : 0),
+ (unicode : 5; flag : umf_noinfo; reserved : 0),
+ (unicode : 6; flag : umf_noinfo; reserved : 0),
+ (unicode : 7; flag : umf_noinfo; reserved : 0),
+ (unicode : 8; flag : umf_noinfo; reserved : 0),
+ (unicode : 9; flag : umf_noinfo; reserved : 0),
+ (unicode : 10; flag : umf_noinfo; reserved : 0),
+ (unicode : 11; flag : umf_noinfo; reserved : 0),
+ (unicode : 12; flag : umf_noinfo; reserved : 0),
+ (unicode : 13; flag : umf_noinfo; reserved : 0),
+ (unicode : 14; flag : umf_noinfo; reserved : 0),
+ (unicode : 15; flag : umf_noinfo; reserved : 0),
+ (unicode : 16; flag : umf_noinfo; reserved : 0),
+ (unicode : 17; flag : umf_noinfo; reserved : 0),
+ (unicode : 18; flag : umf_noinfo; reserved : 0),
+ (unicode : 19; flag : umf_noinfo; reserved : 0),
+ (unicode : 20; flag : umf_noinfo; reserved : 0),
+ (unicode : 21; flag : umf_noinfo; reserved : 0),
+ (unicode : 22; flag : umf_noinfo; reserved : 0),
+ (unicode : 23; flag : umf_noinfo; reserved : 0),
+ (unicode : 24; flag : umf_noinfo; reserved : 0),
+ (unicode : 25; flag : umf_noinfo; reserved : 0),
+ (unicode : 26; flag : umf_noinfo; reserved : 0),
+ (unicode : 27; flag : umf_noinfo; reserved : 0),
+ (unicode : 28; flag : umf_noinfo; reserved : 0),
+ (unicode : 29; flag : umf_noinfo; reserved : 0),
+ (unicode : 30; flag : umf_noinfo; reserved : 0),
+ (unicode : 31; flag : umf_noinfo; reserved : 0),
+ (unicode : 32; flag : umf_noinfo; reserved : 0),
+ (unicode : 33; flag : umf_noinfo; reserved : 0),
+ (unicode : 34; flag : umf_noinfo; reserved : 0),
+ (unicode : 35; flag : umf_noinfo; reserved : 0),
+ (unicode : 36; flag : umf_noinfo; reserved : 0),
+ (unicode : 37; flag : umf_noinfo; reserved : 0),
+ (unicode : 38; flag : umf_noinfo; reserved : 0),
+ (unicode : 39; flag : umf_noinfo; reserved : 0),
+ (unicode : 40; flag : umf_noinfo; reserved : 0),
+ (unicode : 41; flag : umf_noinfo; reserved : 0),
+ (unicode : 42; flag : umf_noinfo; reserved : 0),
+ (unicode : 43; flag : umf_noinfo; reserved : 0),
+ (unicode : 44; flag : umf_noinfo; reserved : 0),
+ (unicode : 45; flag : umf_noinfo; reserved : 0),
+ (unicode : 46; flag : umf_noinfo; reserved : 0),
+ (unicode : 47; flag : umf_noinfo; reserved : 0),
+ (unicode : 48; flag : umf_noinfo; reserved : 0),
+ (unicode : 49; flag : umf_noinfo; reserved : 0),
+ (unicode : 50; flag : umf_noinfo; reserved : 0),
+ (unicode : 51; flag : umf_noinfo; reserved : 0),
+ (unicode : 52; flag : umf_noinfo; reserved : 0),
+ (unicode : 53; flag : umf_noinfo; reserved : 0),
+ (unicode : 54; flag : umf_noinfo; reserved : 0),
+ (unicode : 55; flag : umf_noinfo; reserved : 0),
+ (unicode : 56; flag : umf_noinfo; reserved : 0),
+ (unicode : 57; flag : umf_noinfo; reserved : 0),
+ (unicode : 58; flag : umf_noinfo; reserved : 0),
+ (unicode : 59; flag : umf_noinfo; reserved : 0),
+ (unicode : 60; flag : umf_noinfo; reserved : 0),
+ (unicode : 61; flag : umf_noinfo; reserved : 0),
+ (unicode : 62; flag : umf_noinfo; reserved : 0),
+ (unicode : 63; flag : umf_noinfo; reserved : 0),
+ (unicode : 64; flag : umf_noinfo; reserved : 0),
+ (unicode : 65; flag : umf_noinfo; reserved : 0),
+ (unicode : 66; flag : umf_noinfo; reserved : 0),
+ (unicode : 67; flag : umf_noinfo; reserved : 0),
+ (unicode : 68; flag : umf_noinfo; reserved : 0),
+ (unicode : 69; flag : umf_noinfo; reserved : 0),
+ (unicode : 70; flag : umf_noinfo; reserved : 0),
+ (unicode : 71; flag : umf_noinfo; reserved : 0),
+ (unicode : 72; flag : umf_noinfo; reserved : 0),
+ (unicode : 73; flag : umf_noinfo; reserved : 0),
+ (unicode : 74; flag : umf_noinfo; reserved : 0),
+ (unicode : 75; flag : umf_noinfo; reserved : 0),
+ (unicode : 76; flag : umf_noinfo; reserved : 0),
+ (unicode : 77; flag : umf_noinfo; reserved : 0),
+ (unicode : 78; flag : umf_noinfo; reserved : 0),
+ (unicode : 79; flag : umf_noinfo; reserved : 0),
+ (unicode : 80; flag : umf_noinfo; reserved : 0),
+ (unicode : 81; flag : umf_noinfo; reserved : 0),
+ (unicode : 82; flag : umf_noinfo; reserved : 0),
+ (unicode : 83; flag : umf_noinfo; reserved : 0),
+ (unicode : 84; flag : umf_noinfo; reserved : 0),
+ (unicode : 85; flag : umf_noinfo; reserved : 0),
+ (unicode : 86; flag : umf_noinfo; reserved : 0),
+ (unicode : 87; flag : umf_noinfo; reserved : 0),
+ (unicode : 88; flag : umf_noinfo; reserved : 0),
+ (unicode : 89; flag : umf_noinfo; reserved : 0),
+ (unicode : 90; flag : umf_noinfo; reserved : 0),
+ (unicode : 91; flag : umf_noinfo; reserved : 0),
+ (unicode : 92; flag : umf_noinfo; reserved : 0),
+ (unicode : 93; flag : umf_noinfo; reserved : 0),
+ (unicode : 94; flag : umf_noinfo; reserved : 0),
+ (unicode : 95; flag : umf_noinfo; reserved : 0),
+ (unicode : 96; flag : umf_noinfo; reserved : 0),
+ (unicode : 97; flag : umf_noinfo; reserved : 0),
+ (unicode : 98; flag : umf_noinfo; reserved : 0),
+ (unicode : 99; flag : umf_noinfo; reserved : 0),
+ (unicode : 100; flag : umf_noinfo; reserved : 0),
+ (unicode : 101; flag : umf_noinfo; reserved : 0),
+ (unicode : 102; flag : umf_noinfo; reserved : 0),
+ (unicode : 103; flag : umf_noinfo; reserved : 0),
+ (unicode : 104; flag : umf_noinfo; reserved : 0),
+ (unicode : 105; flag : umf_noinfo; reserved : 0),
+ (unicode : 106; flag : umf_noinfo; reserved : 0),
+ (unicode : 107; flag : umf_noinfo; reserved : 0),
+ (unicode : 108; flag : umf_noinfo; reserved : 0),
+ (unicode : 109; flag : umf_noinfo; reserved : 0),
+ (unicode : 110; flag : umf_noinfo; reserved : 0),
+ (unicode : 111; flag : umf_noinfo; reserved : 0),
+ (unicode : 112; flag : umf_noinfo; reserved : 0),
+ (unicode : 113; flag : umf_noinfo; reserved : 0),
+ (unicode : 114; flag : umf_noinfo; reserved : 0),
+ (unicode : 115; flag : umf_noinfo; reserved : 0),
+ (unicode : 116; flag : umf_noinfo; reserved : 0),
+ (unicode : 117; flag : umf_noinfo; reserved : 0),
+ (unicode : 118; flag : umf_noinfo; reserved : 0),
+ (unicode : 119; flag : umf_noinfo; reserved : 0),
+ (unicode : 120; flag : umf_noinfo; reserved : 0),
+ (unicode : 121; flag : umf_noinfo; reserved : 0),
+ (unicode : 122; flag : umf_noinfo; reserved : 0),
+ (unicode : 123; flag : umf_noinfo; reserved : 0),
+ (unicode : 124; flag : umf_noinfo; reserved : 0),
+ (unicode : 125; flag : umf_noinfo; reserved : 0),
+ (unicode : 126; flag : umf_noinfo; reserved : 0),
+ (unicode : 127; flag : umf_noinfo; reserved : 0),
+ (unicode : 128; flag : umf_noinfo; reserved : 0),
+ (unicode : 129; flag : umf_noinfo; reserved : 0),
+ (unicode : 130; flag : umf_noinfo; reserved : 0),
+ (unicode : 131; flag : umf_noinfo; reserved : 0),
+ (unicode : 132; flag : umf_noinfo; reserved : 0),
+ (unicode : 133; flag : umf_noinfo; reserved : 0),
+ (unicode : 134; flag : umf_noinfo; reserved : 0),
+ (unicode : 135; flag : umf_noinfo; reserved : 0),
+ (unicode : 136; flag : umf_noinfo; reserved : 0),
+ (unicode : 137; flag : umf_noinfo; reserved : 0),
+ (unicode : 138; flag : umf_noinfo; reserved : 0),
+ (unicode : 139; flag : umf_noinfo; reserved : 0),
+ (unicode : 140; flag : umf_noinfo; reserved : 0),
+ (unicode : 141; flag : umf_noinfo; reserved : 0),
+ (unicode : 142; flag : umf_noinfo; reserved : 0),
+ (unicode : 143; flag : umf_noinfo; reserved : 0),
+ (unicode : 144; flag : umf_noinfo; reserved : 0),
+ (unicode : 145; flag : umf_noinfo; reserved : 0),
+ (unicode : 146; flag : umf_noinfo; reserved : 0),
+ (unicode : 147; flag : umf_noinfo; reserved : 0),
+ (unicode : 148; flag : umf_noinfo; reserved : 0),
+ (unicode : 149; flag : umf_noinfo; reserved : 0),
+ (unicode : 150; flag : umf_noinfo; reserved : 0),
+ (unicode : 151; flag : umf_noinfo; reserved : 0),
+ (unicode : 152; flag : umf_noinfo; reserved : 0),
+ (unicode : 153; flag : umf_noinfo; reserved : 0),
+ (unicode : 154; flag : umf_noinfo; reserved : 0),
+ (unicode : 155; flag : umf_noinfo; reserved : 0),
+ (unicode : 156; flag : umf_noinfo; reserved : 0),
+ (unicode : 157; flag : umf_noinfo; reserved : 0),
+ (unicode : 158; flag : umf_noinfo; reserved : 0),
+ (unicode : 159; flag : umf_noinfo; reserved : 0),
+ (unicode : 160; flag : umf_noinfo; reserved : 0),
+ (unicode : 1025; flag : umf_noinfo; reserved : 0),
+ (unicode : 1026; flag : umf_noinfo; reserved : 0),
+ (unicode : 1027; flag : umf_noinfo; reserved : 0),
+ (unicode : 1028; flag : umf_noinfo; reserved : 0),
+ (unicode : 1029; flag : umf_noinfo; reserved : 0),
+ (unicode : 1030; flag : umf_noinfo; reserved : 0),
+ (unicode : 1031; flag : umf_noinfo; reserved : 0),
+ (unicode : 1032; flag : umf_noinfo; reserved : 0),
+ (unicode : 1033; flag : umf_noinfo; reserved : 0),
+ (unicode : 1034; flag : umf_noinfo; reserved : 0),
+ (unicode : 1035; flag : umf_noinfo; reserved : 0),
+ (unicode : 1036; flag : umf_noinfo; reserved : 0),
+ (unicode : 173; flag : umf_noinfo; reserved : 0),
+ (unicode : 1038; flag : umf_noinfo; reserved : 0),
+ (unicode : 1039; flag : umf_noinfo; reserved : 0),
+ (unicode : 1040; flag : umf_noinfo; reserved : 0),
+ (unicode : 1041; flag : umf_noinfo; reserved : 0),
+ (unicode : 1042; flag : umf_noinfo; reserved : 0),
+ (unicode : 1043; flag : umf_noinfo; reserved : 0),
+ (unicode : 1044; flag : umf_noinfo; reserved : 0),
+ (unicode : 1045; flag : umf_noinfo; reserved : 0),
+ (unicode : 1046; flag : umf_noinfo; reserved : 0),
+ (unicode : 1047; flag : umf_noinfo; reserved : 0),
+ (unicode : 1048; flag : umf_noinfo; reserved : 0),
+ (unicode : 1049; flag : umf_noinfo; reserved : 0),
+ (unicode : 1050; flag : umf_noinfo; reserved : 0),
+ (unicode : 1051; flag : umf_noinfo; reserved : 0),
+ (unicode : 1052; flag : umf_noinfo; reserved : 0),
+ (unicode : 1053; flag : umf_noinfo; reserved : 0),
+ (unicode : 1054; flag : umf_noinfo; reserved : 0),
+ (unicode : 1055; flag : umf_noinfo; reserved : 0),
+ (unicode : 1056; flag : umf_noinfo; reserved : 0),
+ (unicode : 1057; flag : umf_noinfo; reserved : 0),
+ (unicode : 1058; flag : umf_noinfo; reserved : 0),
+ (unicode : 1059; flag : umf_noinfo; reserved : 0),
+ (unicode : 1060; flag : umf_noinfo; reserved : 0),
+ (unicode : 1061; flag : umf_noinfo; reserved : 0),
+ (unicode : 1062; flag : umf_noinfo; reserved : 0),
+ (unicode : 1063; flag : umf_noinfo; reserved : 0),
+ (unicode : 1064; flag : umf_noinfo; reserved : 0),
+ (unicode : 1065; flag : umf_noinfo; reserved : 0),
+ (unicode : 1066; flag : umf_noinfo; reserved : 0),
+ (unicode : 1067; flag : umf_noinfo; reserved : 0),
+ (unicode : 1068; flag : umf_noinfo; reserved : 0),
+ (unicode : 1069; flag : umf_noinfo; reserved : 0),
+ (unicode : 1070; flag : umf_noinfo; reserved : 0),
+ (unicode : 1071; flag : umf_noinfo; reserved : 0),
+ (unicode : 1072; flag : umf_noinfo; reserved : 0),
+ (unicode : 1073; flag : umf_noinfo; reserved : 0),
+ (unicode : 1074; flag : umf_noinfo; reserved : 0),
+ (unicode : 1075; flag : umf_noinfo; reserved : 0),
+ (unicode : 1076; flag : umf_noinfo; reserved : 0),
+ (unicode : 1077; flag : umf_noinfo; reserved : 0),
+ (unicode : 1078; flag : umf_noinfo; reserved : 0),
+ (unicode : 1079; flag : umf_noinfo; reserved : 0),
+ (unicode : 1080; flag : umf_noinfo; reserved : 0),
+ (unicode : 1081; flag : umf_noinfo; reserved : 0),
+ (unicode : 1082; flag : umf_noinfo; reserved : 0),
+ (unicode : 1083; flag : umf_noinfo; reserved : 0),
+ (unicode : 1084; flag : umf_noinfo; reserved : 0),
+ (unicode : 1085; flag : umf_noinfo; reserved : 0),
+ (unicode : 1086; flag : umf_noinfo; reserved : 0),
+ (unicode : 1087; flag : umf_noinfo; reserved : 0),
+ (unicode : 1088; flag : umf_noinfo; reserved : 0),
+ (unicode : 1089; flag : umf_noinfo; reserved : 0),
+ (unicode : 1090; flag : umf_noinfo; reserved : 0),
+ (unicode : 1091; flag : umf_noinfo; reserved : 0),
+ (unicode : 1092; flag : umf_noinfo; reserved : 0),
+ (unicode : 1093; flag : umf_noinfo; reserved : 0),
+ (unicode : 1094; flag : umf_noinfo; reserved : 0),
+ (unicode : 1095; flag : umf_noinfo; reserved : 0),
+ (unicode : 1096; flag : umf_noinfo; reserved : 0),
+ (unicode : 1097; flag : umf_noinfo; reserved : 0),
+ (unicode : 1098; flag : umf_noinfo; reserved : 0),
+ (unicode : 1099; flag : umf_noinfo; reserved : 0),
+ (unicode : 1100; flag : umf_noinfo; reserved : 0),
+ (unicode : 1101; flag : umf_noinfo; reserved : 0),
+ (unicode : 1102; flag : umf_noinfo; reserved : 0),
+ (unicode : 1103; flag : umf_noinfo; reserved : 0),
+ (unicode : 8470; flag : umf_noinfo; reserved : 0),
+ (unicode : 1105; flag : umf_noinfo; reserved : 0),
+ (unicode : 1106; flag : umf_noinfo; reserved : 0),
+ (unicode : 1107; flag : umf_noinfo; reserved : 0),
+ (unicode : 1108; flag : umf_noinfo; reserved : 0),
+ (unicode : 1109; flag : umf_noinfo; reserved : 0),
+ (unicode : 1110; flag : umf_noinfo; reserved : 0),
+ (unicode : 1111; flag : umf_noinfo; reserved : 0),
+ (unicode : 1112; flag : umf_noinfo; reserved : 0),
+ (unicode : 1113; flag : umf_noinfo; reserved : 0),
+ (unicode : 1114; flag : umf_noinfo; reserved : 0),
+ (unicode : 1115; flag : umf_noinfo; reserved : 0),
+ (unicode : 1116; flag : umf_noinfo; reserved : 0),
+ (unicode : 167; flag : umf_noinfo; reserved : 0),
+ (unicode : 1118; flag : umf_noinfo; reserved : 0),
+ (unicode : 1119; flag : umf_noinfo; reserved : 0)
+ );
+
+ unicodemap : tunicodemap = (
+ cpname : '8859-5';
+ cp : 28595;
+ map : @map;
+ lastchar : 255;
+ next : nil;
+ internalmap : true
+ );
+
+ begin
+ registermapping(@unicodemap)
+ end.
diff --git a/closures/compiler/cpid.pas b/closures/compiler/cpid.pas
new file mode 100644
index 0000000000..0811a36570
--- /dev/null
+++ b/closures/compiler/cpid.pas
@@ -0,0 +1,191 @@
+{
+ Copyright (c) 2008 by Florian Klaempfl
+
+ Basic stuff for encoding sensitive strings
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ ****************************************************************************
+}
+unit cpid;
+
+
+{$i fpcdefs.inc}
+
+ interface
+
+ type
+ TEncodingEntry = record
+ id : TStringEncoding;
+ name : Ansistring;
+ end;
+
+ const Encodings : array[0..150] of TEncodingEntry = (
+ id : 037; name : 'IBM037';
+ id : 437; name : 'IBM437';
+ id : 500; name : 'IBM500';
+ id : 708; name : 'ASMO-708';
+ id : 709; name : 'ASMO-449+';
+ id : 710; name : 'Arabic';
+ id : 720; name : 'DOS-720';
+ id : 737; name : 'ibm737';
+ id : 775; name : 'ibm775';
+ id : 850; name : 'ibm850';
+ id : 852; name : 'ibm852';
+ id : 855; name : 'IBM855';
+ id : 857; name : 'ibm857';
+ id : 858; name : 'IBM00858';
+ id : 860; name : 'IBM860';
+ id : 861; name : 'ibm861';
+ id : 862; name : 'DOS-862';
+ id : 863; name : 'IBM863';
+ id : 864; name : 'IBM864';
+ id : 865; name : 'IBM865';
+ id : 866; name : 'cp866'';;
+ id : 869; name : 'ibm869';
+ id : 870; name : 'IBM870';
+ id : 874; name : 'windows-874';
+ id : 875; name : 'cp875';
+ id : 932; name : 'shift_jis';
+ id : 936; name : 'gb2312';
+ id : 949; name : 'ks_c_5601-1987';
+ id : 950; name : 'big5';
+ id : 1026; name : 'IBM1026';
+ id : 1047; name : 'IBM01047';
+ id : 1140; name : 'IBM01140';
+ id : 1141; name : 'IBM01141';
+ id : 1142; name : 'IBM01142';
+ id : 1143; name : 'IBM01143';
+ id : 1144; name : 'IBM01144';
+ id : 1145; name : 'IBM01145';
+ id : 1146; name : 'IBM01146';
+ id : 1147; name : 'IBM01147';
+ id : 1148; name : 'IBM01148';
+ id : 1149; name : 'IBM01149';
+ id : 1200; name : 'utf-16';
+ id : 1201; name : 'unicodeFFFE';
+ id : 1250; name : 'windows-1250';
+ id : 1251; name : 'windows-1251';
+ id : 1252; name : 'windows-1252';
+ id : 1253; name : 'windows-1253';
+ id : 1254; name : 'windows-1254';
+ id : 1255; name : 'windows-1255';
+ id : 1256; name : 'windows-1256';
+ id : 1257; name : 'windows-1257';
+ id : 1258; name : 'windows-1258';
+ id : 1361; name : 'Johab';
+ id : 10000; name : 'macintosh';
+ id : 10001; name : 'x-mac-japanese';
+ id : 10002; name : 'x-mac-chinesetrad';
+ id : 10003; name : 'x-mac-korean';
+ id : 10004; name : 'x-mac-arabic';
+ id : 10005; name : 'x-mac-hebrew';
+ id : 10006; name : 'x-mac-greek';
+ id : 10007; name : 'x-mac-cyrillic';
+ id : 10008; name : 'x-mac-chinesesimp';
+ id : 10010; name : 'x-mac-romanian';
+ id : 10017; name : 'x-mac-ukrainian';
+ id : 10021; name : 'x-mac-thai';
+ id : 10029; name : 'x-mac-ce';
+ id : 10079; name : 'x-mac-icelandic';
+ id : 10081; name : 'x-mac-turkish';
+ id : 10082; name : 'x-mac-croatian';
+ id : 12000; name : 'utf-32';
+ id : 12001; name : 'utf-32BE';
+ id : 20000; name : 'x-Chinese_CNS';
+ id : 20001; name : 'x-cp20001';
+ id : 20002; name : 'x_Chinese-Eten';
+ id : 20003; name : 'x-cp20003';
+ id : 20004; name : 'x-cp20004';
+ id : 20005; name : 'x-cp20005';
+ id : 20105; name : 'x-IA5';
+ id : 20106; name : 'x-IA5-German';
+ id : 20107; name : 'x-IA5-Swedish';
+ id : 20108; name : 'x-IA5-Norwegian';
+ id : 20127; name : 'us-ascii';
+ id : 20261; name : 'x-cp20261';
+ id : 20269; name : 'x-cp20269';
+ id : 20273; name : 'IBM273';
+ id : 20277; name : 'IBM277';
+ id : 20278; name : 'IBM278';
+ id : 20280; name : 'IBM280';
+ id : 20284; name : 'IBM284';
+ id : 20285; name : 'IBM285';
+ id : 20290; name : 'IBM290';
+ id : 20297; name : 'IBM297';
+ id : 20420; name : 'IBM420';
+ id : 20423; name : 'IBM423';
+ id : 20424; name : 'IBM424';
+ id : 20833; name : 'x-EBCDIC-KoreanExtended';
+ id : 20838; name : 'IBM-Thai';
+ id : 20866; name : 'koi8-r';
+ id : 20871; name : 'IBM871';
+ id : 20880; name : 'IBM880';
+ id : 20905; name : 'IBM905';
+ id : 20924; name : 'IBM00924';
+ id : 20932; name : 'EUC-JP';
+ id : 20936; name : 'x-cp20936';
+ id : 20949; name : 'x-cp20949';
+ id : 21025; name : 'cp1025';
+ id : 21866; name : 'koi8-u';
+ id : 28591; name : 'iso-8859-1';
+ id : 28592; name : 'iso-8859-2';
+ id : 28593; name : 'iso-8859-3';
+ id : 28594; name : 'iso-8859-4';
+ id : 28595; name : 'iso-8859-5';
+ id : 28596; name : 'iso-8859-6';
+ id : 28597; name : 'iso-8859-7';
+ id : 28598; name : 'iso-8859-8';
+ id : 28599; name : 'iso-8859-9';
+ id : 28603; name : 'iso-8859-13';
+ id : 28605; name : 'iso-8859-15';
+ id : 29001; name : 'x-Europa';
+ id : 38598; name : 'iso-8859-8-i';
+ id : 50220; name : 'iso-2022-jp';
+ id : 50221; name : 'csISO2022JP';
+ id : 50222; name : 'iso-2022-jp';
+ id : 50225; name : 'iso-2022-kr';
+ id : 50227; name : 'x-cp50227';
+ id : 50229; name : 'ISO 2022';
+ { not unique
+ id : 50930; name : 'EBCDIC
+ id : 50931; name : 'EBCDIC
+ id : 50933; name : 'EBCDIC
+ id : 50935; name : 'EBCDIC
+ id : 50936; name : 'EBCDIC
+ id : 50937; name : 'EBCDIC
+ id : 50939; name : 'EBCDIC
+ }
+ id : 51932; name : 'euc-jp';
+ id : 51936; name : 'EUC-CN';
+ id : 51949; name : 'euc-kr';
+ id : 51950; name : 'EUC';
+ id : 52936; name : 'hz-gb-2312';
+ id : 54936; name : 'GB18030';
+ id : 57002; name : 'x-iscii-de';
+ id : 57003; name : 'x-iscii-be';
+ id : 57004; name : 'x-iscii-ta';
+ id : 57005; name : 'x-iscii-te';
+ id : 57006; name : 'x-iscii-as';
+ id : 57007; name : 'x-iscii-or';
+ id : 57008; name : 'x-iscii-ka';
+ id : 57009; name : 'x-iscii-ma';
+ id : 57010; name : 'x-iscii-gu';
+ id : 57011; name : 'x-iscii-pa';
+ id : 65000; name : 'utf-7';
+ id : 65001; name : 'utf-8');
+
+ implementation
+
+end.
diff --git a/closures/compiler/crefs.pas b/closures/compiler/crefs.pas
new file mode 100644
index 0000000000..c3284eba60
--- /dev/null
+++ b/closures/compiler/crefs.pas
@@ -0,0 +1,65 @@
+{
+ Copyright (c) 2007 by Pierre Muller
+
+ Common reference types
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ ****************************************************************************
+}
+
+unit crefs;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ globtype,
+ cclasses;
+
+ type
+
+ TrefItem = class (TLinkedListItem)
+ refinfo : tfileposinfo;
+ constructor create(const ARefInfo : tfileposinfo);
+ Function GetCopy:TLinkedListItem;virtual;reintroduce;
+ end;
+
+ TRefLinkedList = class(TLinkedList)
+ procedure WriteToPPU;
+ end;
+
+implementation
+
+constructor TRefItem.Create(const ARefInfo : tfileposinfo);
+begin
+ Inherited Create;
+ RefInfo:=ARefInfo;
+end;
+
+Function TRefItem.GetCopy : TLinkedListItem;
+var
+ NR : TRefItem;
+begin
+ NR.Create(RefInfo);
+ GetCopy:=NR;
+end;
+
+procedure TRefLinkedList.WriteToPPU;
+begin
+end;
+
+begin
+end.
diff --git a/closures/compiler/cresstr.pas b/closures/compiler/cresstr.pas
new file mode 100644
index 0000000000..a4c4109265
--- /dev/null
+++ b/closures/compiler/cresstr.pas
@@ -0,0 +1,323 @@
+{
+ Copyright (c) 1998-2002 by Michael van Canneyt
+
+ Handles resourcestrings
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit cresstr;
+
+{$i fpcdefs.inc}
+
+interface
+
+ Procedure GenerateResourceStrings;
+
+
+implementation
+
+uses
+ SysUtils,
+ cclasses,
+ cutils,globtype,globals,systems,
+ symconst,symtype,symdef,symsym,
+ verbose,fmodule,ppu,
+ aasmbase,aasmtai,aasmdata,
+ aasmcpu,
+{$if FPC_FULLVERSION<20700}
+ ccharset,
+{$endif}
+ asmutils;
+
+ Type
+ { These are used to form a singly-linked list, ordered by hash value }
+ TResourceStringItem = class(TLinkedListItem)
+ Sym : TConstSym;
+ Name : String;
+ Value : Pchar;
+ Len : Longint;
+ hash : Cardinal;
+ constructor Create(asym:TConstsym);
+ destructor Destroy;override;
+ procedure CalcHash;
+ end;
+
+ Tresourcestrings=class
+ private
+ List : TLinkedList;
+ procedure ConstSym_Register(p:TObject;arg:pointer);
+ public
+ constructor Create;
+ destructor Destroy;override;
+ procedure CreateResourceStringData;
+ Procedure WriteResourceFile;
+ procedure RegisterResourceStrings;
+ end;
+
+
+
+{ ---------------------------------------------------------------------
+ TRESOURCESTRING_ITEM
+ ---------------------------------------------------------------------}
+
+ constructor TResourceStringItem.Create(asym:TConstsym);
+ begin
+ inherited Create;
+ Sym:=Asym;
+ Name:=lower(asym.owner.name^+'.'+asym.Name);
+ Len:=asym.value.len;
+ GetMem(Value,Len);
+ Move(asym.value.valueptr^,Value^,Len);
+ CalcHash;
+ end;
+
+
+ destructor TResourceStringItem.Destroy;
+ begin
+ FreeMem(Value);
+ end;
+
+
+ procedure TResourceStringItem.CalcHash;
+ Var
+ g : Cardinal;
+ I : longint;
+ begin
+ hash:=0;
+ For I:=0 to Len-1 do { 0 terminated }
+ begin
+ hash:=hash shl 4;
+ inc(Hash,Ord(Value[i]));
+ g:=hash and ($f shl 28);
+ if g<>0 then
+ begin
+ hash:=hash xor (g shr 24);
+ hash:=hash xor g;
+ end;
+ end;
+ If Hash=0 then
+ Hash:=$ffffffff;
+ end;
+
+
+{ ---------------------------------------------------------------------
+ Tresourcestrings
+ ---------------------------------------------------------------------}
+
+ Constructor Tresourcestrings.Create;
+ begin
+ List:=TLinkedList.Create;
+ end;
+
+
+ Destructor Tresourcestrings.Destroy;
+ begin
+ List.Free;
+ end;
+
+
+ procedure Tresourcestrings.CreateResourceStringData;
+ Var
+ namelab,
+ valuelab : tasmlabel;
+ resstrlab : tasmsymbol;
+ endsymlab : tasmsymbol;
+ R : TResourceStringItem;
+ begin
+ { Put resourcestrings in a new objectfile. Putting it in multiple files
+ makes the linking too dependent on the linker script requiring a SORT(*) for
+ the data sections }
+ maybe_new_object_file(current_asmdata.asmlists[al_const]);
+ new_section(current_asmdata.asmlists[al_const],sec_data,make_mangledname('RESSTRTABLE',current_module.localsymtable,''),sizeof(pint));
+
+ maybe_new_object_file(current_asmdata.asmlists[al_resourcestrings]);
+ new_section(current_asmdata.asmlists[al_resourcestrings],sec_data,make_mangledname('RESSTR',current_module.localsymtable,'1_START'),sizeof(pint));
+ current_asmdata.AsmLists[al_resourcestrings].concat(tai_symbol.createname_global(
+ make_mangledname('RESSTR',current_module.localsymtable,'START'),AT_DATA,0));
+
+ { Write unitname entry }
+ namelab:=emit_ansistring_const(current_asmdata.asmlists[al_const],@current_module.localsymtable.name^[1],length(current_module.localsymtable.name^),getansistringcodepage,False);
+ current_asmdata.asmlists[al_resourcestrings].concat(tai_const.create_sym(namelab));
+ current_asmdata.asmlists[al_resourcestrings].concat(tai_const.create_sym(nil));
+ current_asmdata.asmlists[al_resourcestrings].concat(tai_const.create_sym(nil));
+ current_asmdata.asmlists[al_resourcestrings].concat(tai_const.create_32bit(0));
+{$ifdef cpu64bitaddr}
+ current_asmdata.asmlists[al_resourcestrings].concat(tai_const.create_32bit(0));
+{$endif cpu64bitaddr}
+
+ { Add entries }
+ R:=TResourceStringItem(List.First);
+ while assigned(R) do
+ begin
+ new_section(current_asmdata.asmlists[al_const],sec_rodata,make_mangledname('RESSTR',current_module.localsymtable,'d_'+r.name),sizeof(pint));
+ { Write default value }
+ if assigned(R.value) and (R.len<>0) then
+ valuelab:=emit_ansistring_const(current_asmdata.asmlists[al_const],R.Value,R.Len,getansistringcodepage,False)
+ else
+ valuelab:=nil;
+ { Append the name as a ansistring. }
+ current_asmdata.asmlists[al_const].concat(cai_align.Create(const_align(sizeof(pint))));
+ namelab:=emit_ansistring_const(current_asmdata.asmlists[al_const],@R.Name[1],length(R.name),getansistringcodepage,False);
+
+ {
+ Resourcestring index:
+ TResourceStringRecord = Packed Record
+ Name,
+ CurrentValue,
+ DefaultValue : AnsiString;
+ HashValue : LongWord;
+ end;
+ }
+ new_section(current_asmdata.asmlists[al_resourcestrings],sec_data,make_mangledname('RESSTR',current_module.localsymtable,'2_'+r.name),sizeof(pint));
+ resstrlab:=current_asmdata.DefineAsmSymbol(make_mangledname('RESSTR',R.Sym.owner,R.Sym.name),AB_GLOBAL,AT_DATA);
+ current_asmdata.asmlists[al_resourcestrings].concat(tai_symbol.Create_global(resstrlab,0));
+ current_asmdata.asmlists[al_resourcestrings].concat(tai_const.create_sym(namelab));
+ current_asmdata.asmlists[al_resourcestrings].concat(tai_const.create_sym(valuelab));
+ current_asmdata.asmlists[al_resourcestrings].concat(tai_const.create_sym(valuelab));
+ current_asmdata.asmlists[al_resourcestrings].concat(tai_const.create_32bit(longint(R.Hash)));
+{$ifdef cpu64bitaddr}
+ current_asmdata.asmlists[al_resourcestrings].concat(tai_const.create_32bit(0));
+{$endif cpu64bitaddr}
+ current_asmdata.asmlists[al_resourcestrings].concat(tai_symbol_end.create(resstrlab));
+ R:=TResourceStringItem(R.Next);
+ end;
+ new_section(current_asmdata.asmlists[al_resourcestrings],sec_data,make_mangledname('RESSTR',current_module.localsymtable,'3_END'),sizeof(pint));
+ endsymlab:=current_asmdata.DefineAsmSymbol(make_mangledname('RESSTR',current_module.localsymtable,'END'),AB_GLOBAL,AT_DATA);
+ current_asmdata.AsmLists[al_resourcestrings].concat(tai_symbol.create_global(endsymlab,0));
+ { The darwin/ppc64 assembler or linker seems to have trouble }
+ { if a section ends with a global label without any data after it. }
+ { So for safety, just put a dummy value here. }
+ { Further, the regular linker also kills this symbol when turning }
+ { on smart linking in case no value appears after it, so put the }
+ { dummy byte there always }
+ { Update: the Mac OS X 10.6 linker orders data that needs to be }
+ { relocated before all other data, so make this data relocatable, }
+ { otherwise the end label won't be moved with the rest }
+ if (target_info.system in systems_darwin) then
+ current_asmdata.asmlists[al_resourcestrings].concat(Tai_const.create_sym(endsymlab));
+ end;
+
+
+ Procedure Tresourcestrings.WriteResourceFile;
+ Type
+ TMode = (quoted,unquoted);
+ Var
+ F : Text;
+ Mode : TMode;
+ R : TResourceStringItem;
+ C : char;
+ Col,i : longint;
+ ResFileName : string;
+
+ Procedure Add(Const S : String);
+ begin
+ Write(F,S);
+ inc(Col,length(s));
+ end;
+
+ begin
+ ResFileName:=ChangeFileExt(current_module.ppufilename^,'.rst');
+ message1 (general_i_writingresourcefile,ExtractFileName(ResFileName));
+ Assign(F,ResFileName);
+ {$push}{$i-}
+ Rewrite(f);
+ {$pop}
+ If IOresult<>0 then
+ begin
+ message1(general_e_errorwritingresourcefile,ResFileName);
+ exit;
+ end;
+ R:=TResourceStringItem(List.First);
+ while assigned(R) do
+ begin
+ writeln(f);
+ Writeln(f,'# hash value = ',R.Hash);
+ col:=0;
+ Add(R.Name+'=');
+ Mode:=unquoted;
+ For I:=0 to R.Len-1 do
+ begin
+ C:=R.Value[i];
+ If (ord(C)>31) and (Ord(c)<=128) and (c<>'''') then
+ begin
+ If mode=Quoted then
+ Add(c)
+ else
+ begin
+ Add(''''+c);
+ mode:=quoted
+ end;
+ end
+ else
+ begin
+ If Mode=quoted then
+ begin
+ Add('''');
+ mode:=unquoted;
+ end;
+ Add('#'+tostr(ord(c)));
+ end;
+ If Col>72 then
+ begin
+ if mode=quoted then
+ Write (F,'''');
+ Writeln(F,'+');
+ Col:=0;
+ Mode:=unQuoted;
+ end;
+ end;
+ if mode=quoted then
+ writeln (f,'''');
+ Writeln(f);
+ R:=TResourceStringItem(R.Next);
+ end;
+ close(f);
+ end;
+
+
+ procedure Tresourcestrings.ConstSym_Register(p:TObject;arg:pointer);
+ begin
+ if (tsym(p).typ=constsym) and
+ (tconstsym(p).consttyp=constresourcestring) then
+ List.Concat(tResourceStringItem.Create(TConstsym(p)));
+ end;
+
+
+ procedure Tresourcestrings.RegisterResourceStrings;
+ begin
+ if assigned(current_module.globalsymtable) then
+ current_module.globalsymtable.SymList.ForEachCall(@ConstSym_Register,nil);
+ current_module.localsymtable.SymList.ForEachCall(@ConstSym_Register,nil);
+ end;
+
+
+ Procedure GenerateResourceStrings;
+ var
+ resstrs : Tresourcestrings;
+ begin
+ resstrs:=Tresourcestrings.Create;
+ resstrs.RegisterResourceStrings;
+ if not resstrs.List.Empty then
+ begin
+ current_module.flags:=current_module.flags or uf_has_resourcestrings;
+ resstrs.CreateResourceStringData;
+ resstrs.WriteResourceFile;
+ end;
+ resstrs.Free;
+ end;
+
+end.
diff --git a/closures/compiler/cstreams.pas b/closures/compiler/cstreams.pas
new file mode 100644
index 0000000000..d0cd536051
--- /dev/null
+++ b/closures/compiler/cstreams.pas
@@ -0,0 +1,641 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl and Peter Vreman
+
+ This module provides stream classes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit cstreams;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cutils;
+
+
+{****************************************************************************
+ TCStream
+****************************************************************************}
+
+ {
+ TCStream is copied directly from classesh.inc from the FCL so
+ it's compatible with the normal Classes.TStream.
+
+ TCFileStream is a merge of THandleStream and TFileStream and updated
+ to have a 'file' type instead of Handle.
+
+ TCCustomMemoryStream and TCMemoryStream are direct copies.
+ }
+ const
+ { TCStream seek origins }
+ soFromBeginning = 0;
+ soFromCurrent = 1;
+ soFromEnd = 2;
+
+ { TCFileStream create mode }
+ fmCreate = $FFFF;
+ fmOpenRead = 0;
+ fmOpenWrite = 1;
+ fmOpenReadWrite = 2;
+
+var
+{ Used for Error reporting instead of exceptions }
+ CStreamError : longint;
+
+type
+{ Fake TComponent class, it isn't used any futher }
+ TCComponent = class(TObject)
+ end;
+
+{ TCStream abstract class }
+
+ TCStream = class(TObject)
+ private
+ function GetPosition: Longint;
+ procedure SetPosition(Pos: Longint);
+ function GetSize: Longint;
+ protected
+ procedure SetSize(NewSize: Longint); virtual;
+ public
+ function Read(var Buffer; Count: Longint): Longint; virtual; abstract;
+ function Write(const Buffer; Count: Longint): Longint; virtual; abstract;
+ function Seek(Offset: Longint; Origin: Word): Longint; virtual; abstract;
+ procedure ReadBuffer(var Buffer; Count: Longint);
+ procedure WriteBuffer(const Buffer; Count: Longint);
+ function CopyFrom(Source: TCStream; Count: Longint): Longint;
+ function ReadComponent(Instance: TCComponent): TCComponent;
+ function ReadComponentRes(Instance: TCComponent): TCComponent;
+ procedure WriteComponent(Instance: TCComponent);
+ procedure WriteComponentRes(const ResName: string; Instance: TCComponent);
+ procedure WriteDescendent(Instance, Ancestor: TCComponent);
+ procedure WriteDescendentRes(const ResName: string; Instance, Ancestor: TCComponent);
+ procedure WriteResourceHeader(const ResName: string; {!!!:out} var FixupInfo: Integer);
+ procedure FixupResourceHeader(FixupInfo: Integer);
+ procedure ReadResHeader;
+ function ReadByte : Byte;
+ function ReadWord : Word;
+ function ReadDWord : Cardinal;
+ function ReadAnsiString : AnsiString;
+ procedure WriteByte(b : Byte);
+ procedure WriteWord(w : Word);
+ procedure WriteDWord(d : Cardinal);
+ Procedure WriteAnsiString (S : AnsiString);
+ property Position: Longint read GetPosition write SetPosition;
+ property Size: Longint read GetSize write SetSize;
+ end;
+
+{ TCCustomFileStream class }
+
+ TCCustomFileStream = class(TCStream)
+ protected
+ FFileName : String;
+ public
+ constructor Create(const AFileName: string;{shortstring!} Mode: Word); virtual; abstract;
+ function EOF: boolean; virtual; abstract;
+ property FileName : String Read FFilename;
+ end;
+
+{ TFileStream class }
+
+ TCFileStream = class(TCCustomFileStream)
+ Private
+ FHandle: File;
+ protected
+ procedure SetSize(NewSize: Longint); override;
+ public
+ constructor Create(const AFileName: string; Mode: Word); override;
+ destructor Destroy; override;
+ function Read(var Buffer; Count: Longint): Longint; override;
+ function Write(const Buffer; Count: Longint): Longint; override;
+ function Seek(Offset: Longint; Origin: Word): Longint; override;
+ function EOF: boolean; override;
+ end;
+
+ TCFileStreamClass = class of TCCustomFileStream;
+var
+ CFileStreamClass: TCFileStreamClass = TCFileStream;
+
+type
+{ TCustomMemoryStream abstract class }
+
+ TCCustomMemoryStream = class(TCStream)
+ private
+ FMemory: Pointer;
+ FSize, FPosition: Longint;
+ protected
+ procedure SetPointer(Ptr: Pointer; ASize: Longint);
+ public
+ function Read(var Buffer; Count: Longint): Longint; override;
+ function Seek(Offset: Longint; Origin: Word): Longint; override;
+ procedure SaveToStream(Stream: TCStream);
+ procedure SaveToFile(const FileName: string);
+ property Memory: Pointer read FMemory;
+ end;
+
+{ TCMemoryStream }
+
+ TCMemoryStream = class(TCCustomMemoryStream)
+ private
+ FCapacity: Longint;
+ procedure SetCapacity(NewCapacity: Longint);
+ protected
+ function Realloc(var NewCapacity: Longint): Pointer; virtual;
+ property Capacity: Longint read FCapacity write SetCapacity;
+ public
+ destructor Destroy; override;
+ procedure Clear;
+ procedure LoadFromStream(Stream: TCStream);
+ procedure LoadFromFile(const FileName: string);
+ procedure SetSize(NewSize: Longint); override;
+ function Write(const Buffer; Count: Longint): Longint; override;
+ end;
+
+
+implementation
+
+ Type
+ PByte = ^Byte;
+
+{*****************************************************************************
+ TCStream
+*****************************************************************************}
+
+ function TCStream.GetPosition: Longint;
+
+ begin
+ Result:=Seek(0,soFromCurrent);
+ end;
+
+ procedure TCStream.SetPosition(Pos: Longint);
+
+ begin
+ Seek(pos,soFromBeginning);
+ end;
+
+ function TCStream.GetSize: Longint;
+
+ var
+ p : longint;
+
+ begin
+ p:=GetPosition;
+ GetSize:=Seek(0,soFromEnd);
+ Seek(p,soFromBeginning);
+ end;
+
+ procedure TCStream.SetSize(NewSize: Longint);
+
+ begin
+ // We do nothing. Pipe streams don't support this
+ // As well as possible read-ony streams !!
+ end;
+
+ procedure TCStream.ReadBuffer(var Buffer; Count: Longint);
+
+ begin
+ CStreamError:=0;
+ if Read(Buffer,Count)<Count then
+ CStreamError:=102;
+ end;
+
+ procedure TCStream.WriteBuffer(const Buffer; Count: Longint);
+
+ begin
+ CStreamError:=0;
+ if Write(Buffer,Count)<Count then
+ CStreamError:=103;
+ end;
+
+ function TCStream.CopyFrom(Source: TCStream; Count: Longint): Longint;
+
+ var
+ i : longint;
+ buffer : array[0..1023] of byte;
+
+ begin
+ CStreamError:=0;
+ Result:=0;
+ while Count>0 do
+ begin
+ if (Count>sizeof(buffer)) then
+ i:=sizeof(Buffer)
+ else
+ i:=Count;
+ i:=Source.Read(buffer,i);
+ i:=Write(buffer,i);
+ dec(count,i);
+ inc(Result,i);
+ if i=0 then
+ exit;
+ end;
+ end;
+
+ function TCStream.ReadComponent(Instance: TCComponent): TCComponent;
+ begin
+ Result:=nil;
+ end;
+
+ function TCStream.ReadComponentRes(Instance: TCComponent): TCComponent;
+ begin
+ Result:=nil;
+ end;
+
+ procedure TCStream.WriteComponent(Instance: TCComponent);
+ begin
+ end;
+
+ procedure TCStream.WriteComponentRes(const ResName: string; Instance: TCComponent);
+ begin
+ end;
+
+ procedure TCStream.WriteDescendent(Instance, Ancestor: TCComponent);
+ begin
+ end;
+
+ procedure TCStream.WriteDescendentRes(const ResName: string; Instance, Ancestor: TCComponent);
+ begin
+ end;
+
+ procedure TCStream.WriteResourceHeader(const ResName: string; {!!!: out} var FixupInfo: Integer);
+ begin
+ end;
+
+ procedure TCStream.FixupResourceHeader(FixupInfo: Integer);
+ begin
+ end;
+
+ procedure TCStream.ReadResHeader;
+ begin
+ end;
+
+ function TCStream.ReadByte : Byte;
+
+ var
+ b : Byte;
+
+ begin
+ ReadBuffer(b,1);
+ ReadByte:=b;
+ end;
+
+ function TCStream.ReadWord : Word;
+
+ var
+ w : Word;
+
+ begin
+ ReadBuffer(w,2);
+ ReadWord:=w;
+ end;
+
+ function TCStream.ReadDWord : Cardinal;
+
+ var
+ d : Cardinal;
+
+ begin
+ ReadBuffer(d,4);
+ ReadDWord:=d;
+ end;
+
+ Function TCStream.ReadAnsiString : AnsiString;
+ Var
+ TheSize : Longint;
+ P : PByte ;
+ begin
+ ReadBuffer (TheSize,SizeOf(TheSize));
+ SetLength(Result,TheSize);
+ // Illegal typecast if no AnsiStrings defined.
+ if TheSize>0 then
+ begin
+ ReadBuffer (Pointer(Result)^,TheSize);
+ P:=PByte(PtrInt(Result)+TheSize);
+ p^:=0;
+ end;
+ end;
+
+ Procedure TCStream.WriteAnsiString (S : AnsiString);
+
+ Var L : Longint;
+
+ begin
+ L:=Length(S);
+ WriteBuffer (L,SizeOf(L));
+ WriteBuffer (Pointer(S)^,L);
+ end;
+
+ procedure TCStream.WriteByte(b : Byte);
+
+ begin
+ WriteBuffer(b,1);
+ end;
+
+ procedure TCStream.WriteWord(w : Word);
+
+ begin
+ WriteBuffer(w,2);
+ end;
+
+ procedure TCStream.WriteDWord(d : Cardinal);
+
+ begin
+ WriteBuffer(d,4);
+ end;
+
+
+{****************************************************************************}
+{* TCFileStream *}
+{****************************************************************************}
+
+constructor TCFileStream.Create(const AFileName: string; Mode: Word);
+var
+ oldfilemode : byte;
+begin
+ FFileName:=AFileName;
+ If Mode=fmcreate then
+ begin
+ system.assign(FHandle,AFileName);
+ {$push} {$I-}
+ system.rewrite(FHandle,1);
+ {$pop}
+ CStreamError:=IOResult;
+ end
+ else
+ begin
+ oldfilemode:=filemode;
+ filemode:=$40 or Mode;
+ system.assign(FHandle,AFileName);
+ {$push} {$I-}
+ system.reset(FHandle,1);
+ {$pop}
+ CStreamError:=IOResult;
+ filemode:=oldfilemode;
+ end;
+end;
+
+
+destructor TCFileStream.Destroy;
+begin
+ {$push} {$I-}
+ System.Close(FHandle);
+ {$pop}
+ CStreamError:=IOResult;
+end;
+
+
+function TCFileStream.Read(var Buffer; Count: Longint): Longint;
+begin
+ CStreamError:=0;
+ BlockRead(FHandle,Buffer,Count,Result);
+ If Result=-1 then Result:=0;
+end;
+
+
+function TCFileStream.Write(const Buffer; Count: Longint): Longint;
+begin
+ CStreamError:=0;
+ BlockWrite (FHandle,(@Buffer)^,Count,Result);
+ If Result=-1 then Result:=0;
+end;
+
+
+Procedure TCFileStream.SetSize(NewSize: Longint);
+begin
+ {$push} {$I-}
+ System.Seek(FHandle,NewSize);
+ System.Truncate(FHandle);
+ {$pop}
+ CStreamError:=IOResult;
+end;
+
+
+function TCFileStream.Seek(Offset: Longint; Origin: Word): Longint;
+var
+ l : longint;
+begin
+ {$push} {$I-}
+ case Origin of
+ soFromBeginning :
+ begin
+ System.Seek(FHandle,Offset);
+ l:=Offset;
+ end;
+ soFromCurrent :
+ begin
+ l:=System.FilePos(FHandle);
+ inc(l,Offset);
+ System.Seek(FHandle,l);
+ end;
+ soFromEnd :
+ begin
+ l:=System.FileSize(FHandle);
+ dec(l,Offset);
+ if l<0 then
+ l:=0;
+ System.Seek(FHandle,l);
+ end;
+ end;
+ {$pop}
+ CStreamError:=IOResult;
+ Result:=l;
+end;
+
+function TCFileStream.EOF: boolean;
+begin
+ EOF:=system.eof(FHandle);
+end;
+
+
+{****************************************************************************}
+{* TCustomMemoryStream *}
+{****************************************************************************}
+
+procedure TCCustomMemoryStream.SetPointer(Ptr: Pointer; ASize: Longint);
+
+begin
+ FMemory:=Ptr;
+ FSize:=ASize;
+end;
+
+
+function TCCustomMemoryStream.Read(var Buffer; Count: Longint): Longint;
+
+begin
+ Result:=0;
+ If (FSize>0) and (FPosition<Fsize) then
+ begin
+ Result:=FSize-FPosition;
+ If Result>Count then Result:=Count;
+ Move (Pointer(PtrUInt(FMemory)+PtrUInt(FPosition))^,Buffer,Result);
+ FPosition:=Fposition+Result;
+ end;
+end;
+
+
+function TCCustomMemoryStream.Seek(Offset: Longint; Origin: Word): Longint;
+
+begin
+ Case Origin of
+ soFromBeginning : FPosition:=Offset;
+ soFromEnd : FPosition:=FSize+Offset;
+ soFromCurrent : FpoSition:=FPosition+Offset;
+ end;
+ Result:=FPosition;
+end;
+
+
+procedure TCCustomMemoryStream.SaveToStream(Stream: TCStream);
+
+begin
+ if FSize>0 then Stream.WriteBuffer (FMemory^,FSize);
+end;
+
+
+procedure TCCustomMemoryStream.SaveToFile(const FileName: string);
+
+Var S : TCCustomFileStream;
+
+begin
+ Try
+ S:=CFileStreamClass.Create (FileName,fmCreate);
+ SaveToStream(S);
+ finally
+ S.free;
+ end;
+end;
+
+
+{****************************************************************************}
+{* TCMemoryStream *}
+{****************************************************************************}
+
+
+Const TMSGrow = 4096; { Use 4k blocks. }
+
+procedure TCMemoryStream.SetCapacity(NewCapacity: Longint);
+
+begin
+ SetPointer (Realloc(NewCapacity),Fsize);
+ FCapacity:=NewCapacity;
+end;
+
+
+function TCMemoryStream.Realloc(var NewCapacity: Longint): Pointer;
+
+Var MoveSize : Longint;
+
+begin
+ CStreamError:=0;
+ If NewCapacity>0 Then // round off to block size.
+ NewCapacity := (NewCapacity + (TMSGrow-1)) and not (TMSGROW-1);
+ // Only now check !
+ If NewCapacity=FCapacity then
+ Result:=FMemory
+ else
+ If NewCapacity=0 then
+ FreeMem (FMemory,Fcapacity)
+ else
+ begin
+ GetMem (Result,NewCapacity);
+ If Result=Nil then
+ CStreamError:=204;
+ If FCapacity>0 then
+ begin
+ MoveSize:=FSize;
+ If MoveSize>NewCapacity then MoveSize:=NewCapacity;
+ Move (Fmemory^,Result^,MoveSize);
+ FreeMem (FMemory,FCapacity);
+ end;
+ end;
+end;
+
+
+destructor TCMemoryStream.Destroy;
+
+begin
+ Clear;
+ Inherited Destroy;
+end;
+
+
+procedure TCMemoryStream.Clear;
+
+begin
+ FSize:=0;
+ FPosition:=0;
+ SetCapacity (0);
+end;
+
+
+procedure TCMemoryStream.LoadFromStream(Stream: TCStream);
+
+begin
+ Stream.Position:=0;
+ SetSize(Stream.Size);
+ If FSize>0 then Stream.ReadBuffer(FMemory^,FSize);
+end;
+
+
+procedure TCMemoryStream.LoadFromFile(const FileName: string);
+
+Var S : TCCustomFileStream;
+
+begin
+ Try
+ S:=CFileStreamClass.Create (FileName,fmOpenRead);
+ LoadFromStream(S);
+ finally
+ S.free;
+ end;
+end;
+
+
+procedure TCMemoryStream.SetSize(NewSize: Longint);
+
+begin
+ SetCapacity (NewSize);
+ FSize:=NewSize;
+ IF FPosition>FSize then
+ FPosition:=FSize;
+end;
+
+
+function TCMemoryStream.Write(const Buffer; Count: Longint): Longint;
+
+Var NewPos : Longint;
+
+begin
+ If Count=0 then
+ begin
+ Result:=0;
+ exit;
+ end;
+ NewPos:=FPosition+Count;
+ If NewPos>Fsize then
+ begin
+ IF NewPos>FCapacity then
+ SetCapacity (NewPos);
+ FSize:=Newpos;
+ end;
+ System.Move (Buffer,Pointer(Ptruint(FMemory)+PtrUInt(FPosition))^,Count);
+ FPosition:=NewPos;
+ Result:=Count;
+end;
+
+end.
diff --git a/closures/compiler/cutils.pas b/closures/compiler/cutils.pas
new file mode 100644
index 0000000000..1f05c5cad5
--- /dev/null
+++ b/closures/compiler/cutils.pas
@@ -0,0 +1,1363 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit implements some support functions
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+****************************************************************************
+}
+{# This unit contains some generic support functions which are used
+ in the different parts of the compiler.
+}
+unit cutils;
+
+{$i fpcdefs.inc}
+
+interface
+
+ type
+ Tcharset=set of char;
+
+ var
+ internalerrorproc : procedure(i:longint);
+
+
+ {# Returns the minimal value between @var(a) and @var(b) }
+ function min(a,b : longint) : longint;{$ifdef USEINLINE}inline;{$endif}
+ function min(a,b : int64) : int64;{$ifdef USEINLINE}inline;{$endif}
+ {# Returns the maximum value between @var(a) and @var(b) }
+ function max(a,b : longint) : longint;{$ifdef USEINLINE}inline;{$endif}
+ function max(a,b : int64) : int64;{$ifdef USEINLINE}inline;{$endif}
+ {# Return value @var(i) aligned on @var(a) boundary }
+ function align(i,a:longint):longint;{$ifdef USEINLINE}inline;{$endif}
+ { if you have an address aligned using "oldalignment" and add an
+ offset of (a multiple of) offset to it, this function calculates
+ the new minimally guaranteed alignment
+ }
+ function newalignment(oldalignment: longint; offset: int64): longint;
+ {# Return @var(b) with the bit order reversed }
+ function reverse_byte(b: byte): byte;
+
+ function used_align(varalign,minalign,maxalign:shortint):shortint;
+ function isbetteralignedthan(new, org, limit: cardinal): boolean;
+ function size_2_align(len : longint) : shortint;
+ function packedbitsloadsize(bitlen: int64) : int64;
+ procedure Replace(var s:string;s1:string;const s2:string);
+ procedure Replace(var s:AnsiString;s1:string;const s2:AnsiString);
+ procedure ReplaceCase(var s:string;const s1,s2:string);
+ Function MatchPattern(const pattern,what:string):boolean;
+ function upper(const c : char) : char;
+ function upper(const s : string) : string;
+ function upper(const s : ansistring) : ansistring;
+ function lower(const c : char) : char;
+ function lower(const s : string) : string;
+ function lower(const s : ansistring) : ansistring;
+ function trimbspace(const s:string):string;
+ function trimspace(const s:string):string;
+ function space (b : longint): string;
+ function PadSpace(const s:string;len:longint):string;
+ function GetToken(var s:string;endchar:char):string;
+ procedure uppervar(var s : string);
+ function realtostr(e:extended):string;{$ifdef USEINLINE}inline;{$endif}
+ function tostr(i : qword) : string;{$ifdef USEINLINE}inline;{$endif}overload;
+ function tostr(i : int64) : string;{$ifdef USEINLINE}inline;{$endif}overload;
+ function tostr(i : longint) : string;{$ifdef USEINLINE}inline;{$endif}overload;
+ function tostr_with_plus(i : int64) : string;{$ifdef USEINLINE}inline;{$endif}
+ function DStr(l:longint):string;
+ {# Returns true if the string s is a number }
+ function is_number(const s : string) : boolean;{$ifdef USEINLINE}inline;{$endif}
+ {# Returns true if value is a power of 2, the actual
+ exponent value is returned in power.
+ }
+ function ispowerof2(value : int64;out power : longint) : boolean;
+ function nextpowerof2(value : int64; out power: longint) : int64;
+ function backspace_quote(const s:string;const qchars:Tcharset):string;
+ function octal_quote(const s:string;const qchars:Tcharset):string;
+ function maybequoted(const s:string):string;
+ function maybequoted(const s:ansistring):ansistring;
+
+ {# If the string is quoted, in accordance with pascal, it is
+ dequoted and returned in s, and the function returns true.
+ If it is not quoted, or if the quoting is bad, s is not touched,
+ and false is returned.
+ }
+ function DePascalQuote(var s: ansistring): Boolean;
+ function CompareStr(const S1, S2: string): Integer;
+ function CompareText(S1, S2: string): integer;
+
+ { releases the string p and assignes nil to p }
+ { if p=nil then freemem isn't called }
+ procedure stringdispose(var p : pshortstring);{$ifdef USEINLINE}inline;{$endif}
+
+
+ { allocates mem for a copy of s, copies s to this mem and returns }
+ { a pointer to this mem }
+ function stringdup(const s : string) : pshortstring;{$ifdef USEINLINE}inline;{$endif}
+
+ {# Allocates memory for the string @var(s) and copies s as zero
+ terminated string to that allocated memory and returns a pointer
+ to that mem
+ }
+ function strpnew(const s : string) : pchar;
+
+ {# makes the character @var(c) lowercase, with spanish, french and german
+ character set
+ }
+ function lowercase(c : char) : char;
+
+ { makes zero terminated string to a pascal string }
+ { the data in p is modified and p is returned }
+ function pchar2pshortstring(p : pchar) : pshortstring;
+
+ { inverse of pchar2pshortstring }
+ function pshortstring2pchar(p : pshortstring) : pchar;
+
+ { allocate a new pchar with the contents of a}
+ function ansistring2pchar(const a: ansistring) : pchar;
+
+ { Ansistring (pchar+length) support }
+ procedure ansistringdispose(var p : pchar;length : longint);
+ function compareansistrings(p1,p2 : pchar;length1,length2 : longint) : longint;
+ function concatansistrings(p1,p2 : pchar;length1,length2 : longint) : pchar;
+
+ {Lzw encode/decode to compress strings -> save memory.}
+ function minilzw_encode(const s:string):string;
+ function minilzw_decode(const s:string):string;
+
+ Function nextafter(x,y:double):double;
+
+implementation
+
+ uses
+ SysUtils;
+
+ var
+ uppertbl,
+ lowertbl : array[char] of char;
+
+
+ function min(a,b : longint) : longint;{$ifdef USEINLINE}inline;{$endif}
+ {
+ return the minimal of a and b
+ }
+ begin
+ if a<=b then
+ min:=a
+ else
+ min:=b;
+ end;
+
+
+ function min(a,b : int64) : int64;{$ifdef USEINLINE}inline;{$endif}
+ {
+ return the minimal of a and b
+ }
+ begin
+ if a<=b then
+ min:=a
+ else
+ min:=b;
+ end;
+
+
+ function max(a,b : longint) : longint;{$ifdef USEINLINE}inline;{$endif}
+ {
+ return the maximum of a and b
+ }
+ begin
+ if a>=b then
+ max:=a
+ else
+ max:=b;
+ end;
+
+
+ function max(a,b : int64) : int64;{$ifdef USEINLINE}inline;{$endif}
+ {
+ return the maximum of a and b
+ }
+ begin
+ if a>=b then
+ max:=a
+ else
+ max:=b;
+ end;
+
+
+ function newalignment(oldalignment: longint; offset: int64): longint;
+ var
+ localoffset: longint;
+ begin
+ localoffset:=longint(offset);
+ while (localoffset mod oldalignment)<>0 do
+ oldalignment:=oldalignment div 2;
+ newalignment:=oldalignment;
+ end;
+
+
+ function reverse_byte(b: byte): byte;
+ const
+ reverse_nible:array[0..15] of 0..15 =
+ (%0000,%1000,%0100,%1100,%0010,%1010,%0110,%1110,
+ %0001,%1001,%0101,%1101,%0011,%1011,%0111,%1111);
+ begin
+ reverse_byte:=(reverse_nible[b and $f] shl 4) or reverse_nible[b shr 4];
+ end;
+
+ function align(i,a:longint):longint;{$ifdef USEINLINE}inline;{$endif}
+ {
+ return value <i> aligned <a> boundary
+ }
+ begin
+ { for 0 and 1 no aligning is needed }
+ if a<=1 then
+ result:=i
+ else
+ begin
+ if i<0 then
+ result:=((i-a+1) div a) * a
+ else
+ result:=((i+a-1) div a) * a;
+ end;
+ end;
+
+
+ function size_2_align(len : longint) : shortint;
+ begin
+ if len>16 then
+ size_2_align:=32
+ else if len>8 then
+ size_2_align:=16
+ else if len>4 then
+ size_2_align:=8
+ else if len>2 then
+ size_2_align:=4
+ else if len>1 then
+ size_2_align:=2
+ else
+ size_2_align:=1;
+ end;
+
+
+ function packedbitsloadsize(bitlen: int64) : int64;
+ begin
+ case bitlen of
+ 1,2,4,8:
+ result := 1;
+ { 10 bits can never be split over 3 bytes via 1-8-1, because it }
+ { always starts at a multiple of 10 bits. Same for the others. }
+ 3,5,6,7,9,10,12,16:
+ result := 2;
+ {$ifdef cpu64bitalu}
+ { performance penalty for unaligned 8 byte access is much }
+ { higher than for unaligned 4 byte access, at least on ppc, }
+ { so use 4 bytes even in some cases where a value could }
+ { always loaded using a single 8 byte load (e.g. in case of }
+ { 28 bit values) }
+ 11,13,14,15,17..32:
+ result := 4;
+ else
+ result := 8;
+ {$else cpu64bitalu}
+ else
+ result := 4;
+ {$endif cpu64bitalu}
+ end;
+ end;
+
+
+ function isbetteralignedthan(new, org, limit: cardinal): boolean;
+ var
+ cnt: cardinal;
+ begin
+ cnt:=2;
+ while (cnt <= limit) do
+ begin
+ if (org and (cnt-1)) > (new and (cnt-1)) then
+ begin
+ result:=true;
+ exit;
+ end
+ else if (org and (cnt-1)) < (new and (cnt-1)) then
+ begin
+ result:=false;
+ exit;
+ end;
+ cnt:=cnt*2;
+ end;
+ result:=false;
+ end;
+
+
+ function used_align(varalign,minalign,maxalign:shortint):shortint;
+ begin
+ { varalign : minimum alignment required for the variable
+ minalign : Minimum alignment of this structure, 0 = undefined
+ maxalign : Maximum alignment of this structure, 0 = undefined }
+ if (minalign>0) and
+ (varalign<minalign) then
+ used_align:=minalign
+ else
+ begin
+ if (maxalign>0) and
+ (varalign>maxalign) then
+ used_align:=maxalign
+ else
+ used_align:=varalign;
+ end;
+ end;
+
+
+ procedure Replace(var s:string;s1:string;const s2:string);
+ var
+ last,
+ i : longint;
+ begin
+ s1:=upper(s1);
+ last:=0;
+ repeat
+ i:=pos(s1,upper(s));
+ if i=last then
+ i:=0;
+ if (i>0) then
+ begin
+ Delete(s,i,length(s1));
+ Insert(s2,s,i);
+ last:=i;
+ end;
+ until (i=0);
+ end;
+
+
+ procedure Replace(var s:AnsiString;s1:string;const s2:AnsiString);
+ var
+ last,
+ i : longint;
+ begin
+ s1:=upper(s1);
+ last:=0;
+ repeat
+ i:=pos(s1,upper(s));
+ if i=last then
+ i:=0;
+ if (i>0) then
+ begin
+ Delete(s,i,length(s1));
+ Insert(s2,s,i);
+ last:=i;
+ end;
+ until (i=0);
+ end;
+
+
+ procedure ReplaceCase(var s:string;const s1,s2:string);
+ var
+ last,
+ i : longint;
+ begin
+ last:=0;
+ repeat
+ i:=pos(s1,s);
+ if i=last then
+ i:=0;
+ if (i>0) then
+ begin
+ Delete(s,i,length(s1));
+ Insert(s2,s,i);
+ last:=i;
+ end;
+ until (i=0);
+ end;
+
+
+ Function MatchPattern(const pattern,what:string):boolean;
+ var
+ found : boolean;
+ i1,i2 : longint;
+ begin
+ i1:=0;
+ i2:=0;
+ if pattern='' then
+ begin
+ result:=(what='');
+ exit;
+ end;
+ found:=true;
+ repeat
+ inc(i1);
+ if (i1>length(pattern)) then
+ break;
+ inc(i2);
+ if (i2>length(what)) then
+ break;
+ case pattern[i1] of
+ '?' :
+ found:=true;
+ '*' :
+ begin
+ found:=true;
+ if (i1=length(pattern)) then
+ i2:=length(what)
+ else
+ if (i1<length(pattern)) and (pattern[i1+1]<>what[i2]) then
+ begin
+ if i2<length(what) then
+ dec(i1)
+ end
+ else
+ if i2>1 then
+ dec(i2);
+ end;
+ else
+ found:=(pattern[i1]=what[i2]) or (what[i2]='?');
+ end;
+ until not found;
+ if found then
+ begin
+ found:=(i2>=length(what)) and
+ (
+ (i1>length(pattern)) or
+ ((i1=length(pattern)) and
+ (pattern[i1]='*'))
+ );
+ end;
+ result:=found;
+ end;
+
+
+ function upper(const c : char) : char;
+ {
+ return uppercase of c
+ }
+ begin
+ upper:=uppertbl[c];
+ end;
+
+
+ function upper(const s : string) : string;
+ {
+ return uppercased string of s
+ }
+ var
+ i : longint;
+ begin
+ for i:=1 to length(s) do
+ upper[i]:=uppertbl[s[i]];
+ upper[0]:=s[0];
+ end;
+
+
+ function upper(const s : ansistring) : ansistring;
+ {
+ return uppercased string of s
+ }
+ var
+ i : longint;
+ begin
+ setlength(upper,length(s));
+ for i:=1 to length(s) do
+ upper[i]:=uppertbl[s[i]];
+ end;
+
+
+ function lower(const c : char) : char;
+ {
+ return lowercase of c
+ }
+ begin
+ lower:=lowertbl[c];
+ end;
+
+
+ function lower(const s : string) : string;
+ {
+ return lowercased string of s
+ }
+ var
+ i : longint;
+ begin
+ for i:=1 to length(s) do
+ lower[i]:=lowertbl[s[i]];
+ lower[0]:=s[0];
+ end;
+
+
+ function lower(const s : ansistring) : ansistring;
+ {
+ return lowercased string of s
+ }
+ var
+ i : longint;
+ begin
+ setlength(lower,length(s));
+ for i:=1 to length(s) do
+ lower[i]:=lowertbl[s[i]];
+ end;
+
+
+ procedure uppervar(var s : string);
+ {
+ uppercase string s
+ }
+ var
+ i : longint;
+ begin
+ for i:=1 to length(s) do
+ s[i]:=uppertbl[s[i]];
+ end;
+
+
+ procedure initupperlower;
+ var
+ c : char;
+ begin
+ for c:=#0 to #255 do
+ begin
+ lowertbl[c]:=c;
+ uppertbl[c]:=c;
+ case c of
+ 'A'..'Z' :
+ lowertbl[c]:=char(byte(c)+32);
+ 'a'..'z' :
+ uppertbl[c]:=char(byte(c)-32);
+ end;
+ end;
+ end;
+
+
+ function DStr(l:longint):string;
+ var
+ TmpStr : string[32];
+ i : longint;
+ begin
+ Str(l,TmpStr);
+ i:=Length(TmpStr);
+ while (i>3) do
+ begin
+ dec(i,3);
+ if TmpStr[i]<>'-' then
+ insert('.',TmpStr,i+1);
+ end;
+ DStr:=TmpStr;
+ end;
+
+
+ function trimbspace(const s:string):string;
+ {
+ return s with all leading spaces and tabs removed
+ }
+ var
+ i,j : longint;
+ begin
+ j:=1;
+ i:=length(s);
+ while (j<i) and (s[j] in [#9,' ']) do
+ inc(j);
+ trimbspace:=Copy(s,j,i-j+1);
+ end;
+
+
+
+ function trimspace(const s:string):string;
+ {
+ return s with all leading and ending spaces and tabs removed
+ }
+ var
+ i,j : longint;
+ begin
+ i:=length(s);
+ while (i>0) and (s[i] in [#9,' ']) do
+ dec(i);
+ j:=1;
+ while (j<i) and (s[j] in [#9,' ']) do
+ inc(j);
+ trimspace:=Copy(s,j,i-j+1);
+ end;
+
+
+ function space (b : longint): string;
+ var
+ s: string;
+ begin
+ space[0] := chr(b);
+ s[0] := chr(b);
+ FillChar (S[1],b,' ');
+ space:=s;
+ end;
+
+
+ function PadSpace(const s:string;len:longint):string;
+ {
+ return s with spaces add to the end
+ }
+ begin
+ if length(s)<len then
+ PadSpace:=s+Space(len-length(s))
+ else
+ PadSpace:=s;
+ end;
+
+
+ function GetToken(var s:string;endchar:char):string;
+ var
+ i : longint;
+ quote : char;
+ begin
+ GetToken:='';
+ s:=TrimSpace(s);
+ if (length(s)>0) and
+ (s[1] in ['''','"']) then
+ begin
+ quote:=s[1];
+ i:=1;
+ while (i<length(s)) do
+ begin
+ inc(i);
+ if s[i]=quote then
+ begin
+ { Remove double quote }
+ if (i<length(s)) and
+ (s[i+1]=quote) then
+ begin
+ Delete(s,i,1);
+ inc(i);
+ end
+ else
+ begin
+ GetToken:=Copy(s,2,i-2);
+ Delete(s,1,i);
+ exit;
+ end;
+ end;
+ end;
+ GetToken:=s;
+ s:='';
+ end
+ else
+ begin
+ i:=pos(EndChar,s);
+ if i=0 then
+ begin
+ GetToken:=s;
+ s:='';
+ exit;
+ end
+ else
+ begin
+ GetToken:=Copy(s,1,i-1);
+ Delete(s,1,i);
+ exit;
+ end;
+ end;
+ end;
+
+
+ function realtostr(e:extended):string;{$ifdef USEINLINE}inline;{$endif}
+ begin
+ str(e,result);
+ end;
+
+
+ function tostr(i : qword) : string;{$ifdef USEINLINE}inline;{$endif}overload;
+ {
+ return string of value i
+ }
+ begin
+ str(i,result);
+ end;
+
+
+ function tostr(i : int64) : string;{$ifdef USEINLINE}inline;{$endif}overload;
+ {
+ return string of value i
+ }
+ begin
+ str(i,result);
+ end;
+
+
+ function tostr(i : longint) : string;{$ifdef USEINLINE}inline;{$endif}overload;
+ {
+ return string of value i
+ }
+ begin
+ str(i,result);
+ end;
+
+
+ function tostr_with_plus(i : int64) : string;{$ifdef USEINLINE}inline;{$endif}
+ {
+ return string of value i, but always include a + when i>=0
+ }
+ begin
+ str(i,result);
+ if i>=0 then
+ result:='+'+result;
+ end;
+
+
+ function is_number(const s : string) : boolean;{$ifdef USEINLINE}inline;{$endif}
+ {
+ is string a correct number ?
+ }
+ var
+ w : integer;
+ l : longint;
+ begin
+ val(s,l,w);
+ // remove warning
+ l:=l;
+ is_number:=(w=0);
+ end;
+
+
+ function ispowerof2(value : int64;out power : longint) : boolean;
+ {
+ return if value is a power of 2. And if correct return the power
+ }
+ var
+ hl : int64;
+ i : longint;
+ begin
+ if value and (value - 1) <> 0 then
+ begin
+ ispowerof2 := false;
+ exit
+ end;
+ hl:=1;
+ ispowerof2:=true;
+ for i:=0 to 63 do
+ begin
+ if hl=value then
+ begin
+ power:=i;
+ exit;
+ end;
+ hl:=hl shl 1;
+ end;
+ ispowerof2:=false;
+ end;
+
+
+ function nextpowerof2(value : int64; out power: longint) : int64;
+ {
+ returns the power of 2 >= value
+ }
+ var
+ i : longint;
+ begin
+ result := 0;
+ power := -1;
+ if ((value <= 0) or
+ (value >= $4000000000000000)) then
+ exit;
+ result := 1;
+ for i:=0 to 63 do
+ begin
+ if result>=value then
+ begin
+ power := i;
+ exit;
+ end;
+ result:=result shl 1;
+ end;
+ end;
+
+
+ function backspace_quote(const s:string;const qchars:Tcharset):string;
+
+ var i:byte;
+
+ begin
+ backspace_quote:='';
+ for i:=1 to length(s) do
+ begin
+ if (s[i]=#10) and (#10 in qchars) then
+ backspace_quote:=backspace_quote+'\n'
+ else if (s[i]=#13) and (#13 in qchars) then
+ backspace_quote:=backspace_quote+'\r'
+ else
+ begin
+ if s[i] in qchars then
+ backspace_quote:=backspace_quote+'\';
+ backspace_quote:=backspace_quote+s[i];
+ end;
+ end;
+ end;
+
+ function octal_quote(const s:string;const qchars:Tcharset):string;
+
+ var i:byte;
+
+ begin
+ octal_quote:='';
+ for i:=1 to length(s) do
+ begin
+ if s[i] in qchars then
+ begin
+ if ord(s[i])<64 then
+ octal_quote:=octal_quote+'\'+octstr(ord(s[i]),3)
+ else
+ octal_quote:=octal_quote+'\'+octstr(ord(s[i]),4);
+ end
+ else
+ octal_quote:=octal_quote+s[i];
+ end;
+ end;
+
+ function maybequoted(const s:ansistring):ansistring;
+ const
+ {$IFDEF MSWINDOWS}
+ FORBIDDEN_CHARS = ['!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
+ '{', '}', '''', '`', '~'];
+ {$ELSE}
+ FORBIDDEN_CHARS = ['!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
+ '{', '}', '''', ':', '\', '`', '~'];
+ {$ENDIF}
+ var
+ s1 : ansistring;
+ i : integer;
+ quoted : boolean;
+ begin
+ quoted:=false;
+ s1:='"';
+ for i:=1 to length(s) do
+ begin
+ case s[i] of
+ '"' :
+ begin
+ quoted:=true;
+ s1:=s1+'\"';
+ end;
+ ' ',
+ #128..#255 :
+ begin
+ quoted:=true;
+ s1:=s1+s[i];
+ end;
+ else begin
+ if s[i] in FORBIDDEN_CHARS then
+ quoted:=True;
+ s1:=s1+s[i];
+ end;
+ end;
+ end;
+ if quoted then
+ maybequoted:=s1+'"'
+ else
+ maybequoted:=s;
+ end;
+
+
+ function maybequoted(const s:string):string;
+ const
+ {$IFDEF MSWINDOWS}
+ FORBIDDEN_CHARS = ['!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
+ '{', '}', '''', '`', '~'];
+ {$ELSE}
+ FORBIDDEN_CHARS = ['!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
+ '{', '}', '''', ':', '\', '`', '~'];
+ {$ENDIF}
+ var
+ s1 : string;
+ i : integer;
+ quoted : boolean;
+ begin
+ quoted:=false;
+ s1:='"';
+ for i:=1 to length(s) do
+ begin
+ case s[i] of
+ '"' :
+ begin
+ quoted:=true;
+ s1:=s1+'\"';
+ end;
+ ' ',
+ #128..#255 :
+ begin
+ quoted:=true;
+ s1:=s1+s[i];
+ end;
+ else begin
+ if s[i] in FORBIDDEN_CHARS then
+ quoted:=True;
+ s1:=s1+s[i];
+ end;
+ end;
+ end;
+ if quoted then
+ maybequoted:=s1+'"'
+ else
+ maybequoted:=s;
+ end;
+
+
+ function DePascalQuote(var s: ansistring): Boolean;
+ var
+ destPos, sourcePos, len: Integer;
+ t: string;
+ ch: Char;
+ begin
+ DePascalQuote:= false;
+ len:= length(s);
+ if (len >= 1) and (s[1] = '''') then
+ begin
+ {Remove quotes, exchange '' against ' }
+ destPos := 0;
+ sourcepos:=1;
+ while (sourcepos<len) do
+ begin
+ inc(sourcePos);
+ ch := s[sourcePos];
+ if ch = '''' then
+ begin
+ inc(sourcePos);
+ if (sourcePos <= len) and (s[sourcePos] = '''') then
+ {Add the quote as part of string}
+ else
+ begin
+ SetLength(t, destPos);
+ s:= t;
+ Exit(true);
+ end;
+ end;
+ inc(destPos);
+ t[destPos] := ch;
+ end;
+ end;
+ end;
+
+
+ function pchar2pshortstring(p : pchar) : pshortstring;
+ var
+ w,i : longint;
+ begin
+ w:=strlen(p);
+ for i:=w-1 downto 0 do
+ p[i+1]:=p[i];
+ p[0]:=chr(w);
+ pchar2pshortstring:=pshortstring(p);
+ end;
+
+
+ function pshortstring2pchar(p : pshortstring) : pchar;
+ var
+ w,i : longint;
+ begin
+ w:=length(p^);
+ for i:=1 to w do
+ p^[i-1]:=p^[i];
+ p^[w]:=#0;
+ pshortstring2pchar:=pchar(p);
+ end;
+
+
+ function ansistring2pchar(const a: ansistring) : pchar;
+ var
+ len: ptrint;
+ begin
+ len:=length(a);
+ getmem(result,len+1);
+ if (len<>0) then
+ move(a[1],result[0],len);
+ result[len]:=#0;
+ end;
+
+
+ function lowercase(c : char) : char;
+ begin
+ case c of
+ #65..#90 : c := chr(ord (c) + 32);
+ #154 : c:=#129; { german }
+ #142 : c:=#132; { german }
+ #153 : c:=#148; { german }
+ #144 : c:=#130; { french }
+ #128 : c:=#135; { french }
+ #143 : c:=#134; { swedish/norge (?) }
+ #165 : c:=#164; { spanish }
+ #228 : c:=#229; { greek }
+ #226 : c:=#231; { greek }
+ #232 : c:=#227; { greek }
+ end;
+ lowercase := c;
+ end;
+
+
+ function strpnew(const s : string) : pchar;
+ var
+ p : pchar;
+ begin
+ getmem(p,length(s)+1);
+ move(s[1],p^,length(s));
+ p[length(s)]:=#0;
+ result:=p;
+ end;
+
+
+ procedure stringdispose(var p : pshortstring);{$ifdef USEINLINE}inline;{$endif}
+ begin
+ if assigned(p) then
+ begin
+ freemem(p);
+ p:=nil;
+ end;
+ end;
+
+
+ function stringdup(const s : string) : pshortstring;{$ifdef USEINLINE}inline;{$endif}
+ begin
+ getmem(result,length(s)+1);
+ result^:=s;
+ end;
+
+
+ function CompareStr(const S1, S2: string): Integer;
+ var
+ count, count1, count2: integer;
+ begin
+ result := 0;
+ Count1 := Length(S1);
+ Count2 := Length(S2);
+ if Count1>Count2 then
+ Count:=Count2
+ else
+ Count:=Count1;
+ result := CompareChar(S1[1],S2[1], Count);
+ if result=0 then
+ result:=Count1-Count2;
+ end;
+
+
+ function CompareText(S1, S2: string): integer;
+ begin
+ UpperVar(S1);
+ UpperVar(S2);
+ Result:=CompareStr(S1,S2);
+ end;
+
+
+{*****************************************************************************
+ Ansistring (PChar+Length)
+*****************************************************************************}
+
+ procedure ansistringdispose(var p : pchar;length : longint);
+ begin
+ if assigned(p) then
+ begin
+ freemem(p);
+ p:=nil;
+ end;
+ end;
+
+
+ { enable ansistring comparison }
+ { 0 means equal }
+ { 1 means p1 > p2 }
+ { -1 means p1 < p2 }
+ function compareansistrings(p1,p2 : pchar;length1,length2 : longint) : longint;
+ var
+ i,j : longint;
+ begin
+ compareansistrings:=0;
+ j:=min(length1,length2);
+ i:=0;
+ while (i<j) do
+ begin
+ if p1[i]>p2[i] then
+ begin
+ compareansistrings:=1;
+ exit;
+ end
+ else
+ if p1[i]<p2[i] then
+ begin
+ compareansistrings:=-1;
+ exit;
+ end;
+ inc(i);
+ end;
+ if length1>length2 then
+ compareansistrings:=1
+ else
+ if length1<length2 then
+ compareansistrings:=-1;
+ end;
+
+
+ function concatansistrings(p1,p2 : pchar;length1,length2 : longint) : pchar;
+ var
+ p : pchar;
+ begin
+ getmem(p,length1+length2+1);
+ move(p1[0],p[0],length1);
+ move(p2[0],p[length1],length2+1);
+ concatansistrings:=p;
+ end;
+
+
+{*****************************************************************************
+ Ultra basic KISS Lzw (de)compressor
+*****************************************************************************}
+
+ {This is an extremely basic implementation of the Lzw algorithm. It
+ compresses 7-bit ASCII strings into 8-bit compressed strings.
+ The Lzw dictionary is preinitialized with 0..127, therefore this
+ part of the dictionary does not need to be stored in the arrays.
+ The Lzw code size is allways 8 bit, so we do not need complex code
+ that can write partial bytes.}
+
+ function minilzw_encode(const s:string):string;
+
+ var t,u,i:byte;
+ c:char;
+ data:array[128..255] of char;
+ previous:array[128..255] of byte;
+ lzwptr:byte;
+ next_avail:set of 0..255;
+
+ label l1;
+
+ begin
+ minilzw_encode:='';
+ fillchar(data,sizeof(data),#0);
+ fillchar(previous,sizeof(previous),#0);
+ if s<>'' then
+ begin
+ lzwptr:=127;
+ t:=byte(s[1]);
+ i:=2;
+ u:=128;
+ next_avail:=[];
+ while i<=length(s) do
+ begin
+ c:=s[i];
+ if not(t in next_avail) or (u>lzwptr) then goto l1;
+ while (previous[u]<>t) or (data[u]<>c) do
+ begin
+ inc(u);
+ if u>lzwptr then goto l1;
+ end;
+ t:=u;
+ inc(i);
+ continue;
+ l1:
+ {It's a pity that we still need those awfull tricks
+ with this modern compiler. Without this performance
+ of the entire procedure drops about 3 times.}
+ inc(minilzw_encode[0]);
+ minilzw_encode[length(minilzw_encode)]:=char(t);
+ if lzwptr=255 then
+ begin
+ lzwptr:=127;
+ next_avail:=[];
+ end
+ else
+ begin
+ inc(lzwptr);
+ data[lzwptr]:=c;
+ previous[lzwptr]:=t;
+ include(next_avail,t);
+ end;
+ t:=byte(c);
+ u:=128;
+ inc(i);
+ end;
+ inc(minilzw_encode[0]);
+ minilzw_encode[length(minilzw_encode)]:=char(t);
+ end;
+ end;
+
+ function minilzw_decode(const s:string):string;
+
+ var oldc,newc,c:char;
+ i,j:byte;
+ data:array[128..255] of char;
+ previous:array[128..255] of byte;
+ lzwptr:byte;
+ t:string;
+
+ begin
+ minilzw_decode:='';
+ fillchar(data,sizeof(data),#0);
+ fillchar(previous,sizeof(previous),#0);
+ if s<>'' then
+ begin
+ lzwptr:=127;
+ oldc:=s[1];
+ c:=oldc;
+ i:=2;
+ minilzw_decode:=oldc;
+ while i<=length(s) do
+ begin
+ newc:=s[i];
+ if byte(newc)>lzwptr then
+ begin
+ t:=c;
+ c:=oldc;
+ end
+ else
+ begin
+ c:=newc;
+ t:='';
+ end;
+ while c>=#128 do
+ begin
+ inc(t[0]);
+ t[length(t)]:=data[byte(c)];
+ byte(c):=previous[byte(c)];
+ end;
+ inc(minilzw_decode[0]);
+ minilzw_decode[length(minilzw_decode)]:=c;
+ for j:=length(t) downto 1 do
+ begin
+ inc(minilzw_decode[0]);
+ minilzw_decode[length(minilzw_decode)]:=t[j];
+ end;
+ if lzwptr=255 then
+ lzwptr:=127
+ else
+ begin
+ inc(lzwptr);
+ previous[lzwptr]:=byte(oldc);
+ data[lzwptr]:=c;
+ end;
+ oldc:=newc;
+ inc(i);
+ end;
+ end;
+ end;
+
+
+ procedure defaulterror(i:longint);
+ begin
+ writeln('Internal error ',i);
+ runerror(255);
+ end;
+
+ Function Nextafter(x,y:double):double;
+ // Returns the double precision number closest to x in
+ // the direction toward y.
+
+ // Initial direct translation by Soeren Haastrup from
+ // www.netlib.org/fdlibm/s_nextafter.c according to
+ // ====================================================
+ // Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ // Developed at SunSoft, a Sun Microsystems, Inc. business.
+ // Permission to use, copy, modify, and distribute this
+ // software is freely granted, provided that this notice
+ // is preserved.
+ // ====================================================
+ // and with all signaling policies preserved as is.
+
+ type
+ {$if defined(ENDIAN_LITTLE) and not defined(FPC_DOUBLE_HILO_SWAPPED)}
+ twoword=record
+ lo,hi:longword; // Little Endian split of a double.
+ end;
+ {$else}
+ twoword=record
+ hi,lo:longword; // Big Endian split of a double.
+ end;
+ {$endif}
+
+ var
+ hx,hy,ix,iy:longint;
+ lx,ly:longword;
+
+ Begin
+ hx:=twoword(x).hi; // high and low words of x and y
+ lx:=twoword(x).lo;
+ hy:=twoword(y).hi;
+ ly:=twoword(y).lo;
+ ix:=hx and $7fffffff; // absolute values
+ iy:=hy and $7fffffff;
+
+ // Case x=NAN or y=NAN
+
+ if ( (ix>=$7ff00000) and ((longword(ix-$7ff00000) or lx) <> 0) )
+ or ( (iy>=$7ff00000) and ((longword(iy-$7ff00000) OR ly) <> 0) )
+ then exit(x+y);
+
+ // Case x=y
+
+ if x=y then exit(x); // (implies Nextafter(0,-0) is 0 and not -0...)
+
+ // Case x=0
+
+ if (longword(ix) or lx)=0
+ then begin
+ twoword(x).hi:=hy and $80000000; // return +-minimalSubnormal
+ twoword(x).lo:=1;
+ y:=x*x; // set underflow flag (ignored in FPC as default)
+ if y=x
+ then exit(y)
+ else exit(x);
+ end;
+
+ // all other cases
+
+ if hx>=0 // x>0
+ then begin
+ if (hx>hy) or ( (hx=hy) and (lx>ly) ) // x>y , return x-ulp
+ then begin
+ if (lx=0) then hx:=hx-1;
+ lx:=lx-1;
+ end
+ else begin // x<y, return x+ulp
+ lx:=lx+1;
+ if lx=0 then hx:=hx+1;
+ end
+ end
+ else begin // x<0
+ if (hy>=0) or (hx>=hy) or ( (hx=hy) and (lx>ly)) // x<y, return x-ulp
+ then begin
+ if (lx=0) then hx:=hx-1;
+ lx:=lx-1;
+ end
+ else begin // x>y , return x+ulp
+ lx:=lx+1;
+ if lx=0 then hx:=hx+1;
+ end
+ end;
+
+ // finally check if overflow or underflow just happend
+
+ hy:=hx and $7ff00000;
+ if (hy>= $7ff00000) then exit(x+x); // overflow and signal
+ if (hy<$0010000) // underflow
+ then begin
+ y:=x*x; // raise underflow flag
+ if y<>x
+ then begin
+ twoword(y).hi:=hx;
+ twoword(y).lo:=lx;
+ exit(y);
+ end
+ end;
+
+ twoword(x).hi:=hx;
+ twoword(x).lo:=lx;
+ nextafter:=x;
+
+ end;
+
+
+initialization
+ internalerrorproc:=@defaulterror;
+ initupperlower;
+end.
diff --git a/closures/compiler/cwindirs.pp b/closures/compiler/cwindirs.pp
new file mode 100644
index 0000000000..077697d2a8
--- /dev/null
+++ b/closures/compiler/cwindirs.pp
@@ -0,0 +1,123 @@
+{ this unit is temporarily included in the compiler sources till stable releases with
+ windirs from the rtl are shipped
+}
+unit cwindirs;
+
+{$mode objfpc}
+{$H+}
+
+interface
+
+uses
+ windows,
+ strings;
+
+Const
+ CSIDL_PROGRAMS = $0002; { %SYSTEMDRIVE%\Program Files }
+ CSIDL_PERSONAL = $0005; { %USERPROFILE%\My Documents }
+ CSIDL_FAVORITES = $0006; { %USERPROFILE%\Favorites }
+ CSIDL_STARTUP = $0007; { %USERPROFILE%\Start menu\Programs\Startup }
+ CSIDL_RECENT = $0008; { %USERPROFILE%\Recent }
+ CSIDL_SENDTO = $0009; { %USERPROFILE%\Sendto }
+ CSIDL_STARTMENU = $000B; { %USERPROFILE%\Start menu }
+ CSIDL_MYMUSIC = $000D; { %USERPROFILE%\Documents\My Music }
+ CSIDL_MYVIDEO = $000E; { %USERPROFILE%\Documents\My Videos }
+ CSIDL_DESKTOPDIRECTORY = $0010; { %USERPROFILE%\Desktop }
+ CSIDL_NETHOOD = $0013; { %USERPROFILE%\NetHood }
+ CSIDL_TEMPLATES = $0015; { %USERPROFILE%\Templates }
+ CSIDL_COMMON_STARTMENU = $0016; { %PROFILEPATH%\All users\Start menu }
+ CSIDL_COMMON_PROGRAMS = $0017; { %PROFILEPATH%\All users\Start menu\Programs }
+ CSIDL_COMMON_STARTUP = $0018; { %PROFILEPATH%\All users\Start menu\Programs\Startup }
+ CSIDL_COMMON_DESKTOPDIRECTORY = $0019; { %PROFILEPATH%\All users\Desktop }
+ CSIDL_APPDATA = $001A; { %USERPROFILE%\Application Data (roaming) }
+ CSIDL_PRINTHOOD = $001B; { %USERPROFILE%\Printhood }
+ CSIDL_LOCAL_APPDATA = $001C; { %USERPROFILE%\Local Settings\Application Data (non roaming) }
+ CSIDL_COMMON_FAVORITES = $001F; { %PROFILEPATH%\All users\Favorites }
+ CSIDL_INTERNET_CACHE = $0020; { %USERPROFILE%\Local Settings\Temporary Internet Files }
+ CSIDL_COOKIES = $0021; { %USERPROFILE%\Cookies }
+ CSIDL_HISTORY = $0022; { %USERPROFILE%\Local settings\History }
+ CSIDL_COMMON_APPDATA = $0023; { %PROFILESPATH%\All Users\Application Data }
+ CSIDL_WINDOWS = $0024; { %SYSTEMROOT% }
+ CSIDL_SYSTEM = $0025; { %SYSTEMROOT%\SYSTEM32 (may be system on 95/98/ME) }
+ CSIDL_PROGRAM_FILES = $0026; { %SYSTEMDRIVE%\Program Files }
+ CSIDL_MYPICTURES = $0027; { %USERPROFILE%\My Documents\My Pictures }
+ CSIDL_PROFILE = $0028; { %USERPROFILE% }
+ CSIDL_PROGRAM_FILES_COMMON = $002B; { %SYSTEMDRIVE%\Program Files\Common }
+ CSIDL_COMMON_TEMPLATES = $002D; { %PROFILEPATH%\All Users\Templates }
+ CSIDL_COMMON_DOCUMENTS = $002E; { %PROFILEPATH%\All Users\Documents }
+ CSIDL_COMMON_ADMINTOOLS = $002F; { %PROFILEPATH%\All Users\Start Menu\Programs\Administrative Tools }
+ CSIDL_ADMINTOOLS = $0030; { %USERPROFILE%\Start Menu\Programs\Administrative Tools }
+ CSIDL_COMMON_MUSIC = $0035; { %PROFILEPATH%\All Users\Documents\my music }
+ CSIDL_COMMON_PICTURES = $0036; { %PROFILEPATH%\All Users\Documents\my pictures }
+ CSIDL_COMMON_VIDEO = $0037; { %PROFILEPATH%\All Users\Documents\my videos }
+ CSIDL_CDBURN_AREA = $003B; { %USERPROFILE%\Local Settings\Application Data\Microsoft\CD Burning }
+ CSIDL_PROFILES = $003E; { %PROFILEPATH% }
+
+ CSIDL_FLAG_CREATE = $8000; { (force creation of requested folder if it doesn't exist yet) }
+
+Function GetWindowsSpecialDir(ID : Integer) : String;
+
+implementation
+
+uses
+ sysutils;
+
+Type
+ PFNSHGetFolderPath = Function(Ahwnd: HWND; Csidl: Integer; Token: THandle; Flags: DWord; Path: PChar): HRESULT; stdcall;
+
+
+var
+ SHGetFolderPath : PFNSHGetFolderPath = Nil;
+ CFGDLLHandle : THandle = 0;
+
+Procedure InitDLL;
+
+Var
+ pathBuf: array[0..MAX_PATH-1] of char;
+ pathLength: Integer;
+begin
+ { Load shfolder.dll using a full path, in order to prevent spoofing (Mantis #18185)
+ Don't bother loading shell32.dll because shfolder.dll itself redirects SHGetFolderPath
+ to shell32.dll whenever possible. }
+ pathLength:=GetSystemDirectory(pathBuf, MAX_PATH);
+ if (pathLength>0) and (pathLength<MAX_PATH-14) then { 14=length('\shfolder.dll'#0) }
+ begin
+ StrLCopy(@pathBuf[pathLength],'\shfolder.dll',MAX_PATH-pathLength-1);
+ CFGDLLHandle:=LoadLibrary(pathBuf);
+
+ if (CFGDLLHandle<>0) then
+ begin
+ Pointer(ShGetFolderPath):=GetProcAddress(CFGDLLHandle,'SHGetFolderPathA');
+ If @ShGetFolderPath=nil then
+ begin
+ FreeLibrary(CFGDLLHandle);
+ CFGDllHandle:=0;
+ end;
+ end;
+ end;
+ If (@ShGetFolderPath=Nil) then
+ Raise Exception.Create('Could not determine SHGetFolderPath Function');
+end;
+
+Function GetWindowsSpecialDir(ID : Integer) : String;
+
+Var
+ APath : Array[0..MAX_PATH] of char;
+
+begin
+ Result:='';
+ if (CFGDLLHandle=0) then
+ InitDLL;
+ If (SHGetFolderPath<>Nil) then
+ begin
+ if SHGetFolderPath(0,ID or CSIDL_FLAG_CREATE,0,0,@APATH[0])=S_OK then
+ Result:=IncludeTrailingPathDelimiter(StrPas(@APath[0]));
+ end;
+end;
+
+Initialization
+Finalization
+ if CFGDLLHandle<>0 then
+ FreeLibrary(CFGDllHandle);
+end.
+
diff --git a/closures/compiler/dbgbase.pas b/closures/compiler/dbgbase.pas
new file mode 100644
index 0000000000..f6b7b15171
--- /dev/null
+++ b/closures/compiler/dbgbase.pas
@@ -0,0 +1,626 @@
+{
+ Copyright (c) 2003-2006 by Peter Vreman and Florian Klaempfl
+
+ This units contains the base class for debug info generation
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit dbgbase;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cclasses,
+ systems,
+ parabase,
+ symconst,symbase,symdef,symtype,symsym,symtable,
+ fmodule,
+ aasmtai,aasmdata;
+
+ type
+ TDebugInfo=class
+ protected
+ { definitions }
+ { collect all defs in one list so we can reset them easily }
+ defnumberlist : TFPObjectList;
+ deftowritelist : TFPObjectList;
+ procedure appenddef(list:TAsmList;def:tdef);
+ procedure beforeappenddef(list:TAsmList;def:tdef);virtual;
+ procedure afterappenddef(list:TAsmList;def:tdef);virtual;
+ procedure appenddef_ord(list:TAsmList;def:torddef);virtual;
+ procedure appenddef_float(list:TAsmList;def:tfloatdef);virtual;
+ procedure appenddef_file(list:TAsmList;def:tfiledef);virtual;
+ procedure appenddef_enum(list:TAsmList;def:tenumdef);virtual;
+ procedure appenddef_array(list:TAsmList;def:tarraydef);virtual;
+ procedure appenddef_record(list:TAsmList;def:trecorddef);virtual;
+ procedure appenddef_object(list:TAsmList;def:tobjectdef);virtual;
+ procedure appenddef_classref(list:TAsmList;def: tclassrefdef);virtual;
+ procedure appenddef_pointer(list:TAsmList;def:tpointerdef);virtual;
+ procedure appenddef_string(list:TAsmList;def:tstringdef);virtual;
+ procedure appenddef_procvar(list:TAsmList;def:tprocvardef);virtual;
+ procedure appenddef_variant(list:TAsmList;def:tvariantdef);virtual;
+ procedure appenddef_set(list:TAsmList;def:tsetdef);virtual;
+ procedure appenddef_formal(list:TAsmList;def:tformaldef);virtual;
+ procedure appenddef_undefined(list:TAsmList;def: tundefineddef);virtual;
+ procedure appendprocdef(list:TAsmList;def:tprocdef);virtual;
+ procedure write_remaining_defs_to_write(list:TAsmList);
+ { symbols }
+ procedure appendsym(list:TAsmList;sym:tsym);
+ procedure beforeappendsym(list:TAsmList;sym:tsym);virtual;
+ procedure afterappendsym(list:TAsmList;sym:tsym);virtual;
+ procedure appendsym_staticvar(list:TAsmList;sym:tstaticvarsym);virtual;
+ procedure appendsym_paravar(list:TAsmList;sym:tparavarsym);virtual;
+ procedure appendsym_localvar(list:TAsmList;sym:tlocalvarsym);virtual;
+ procedure appendsym_fieldvar(list:TAsmList;sym:tfieldvarsym);virtual;
+ procedure appendsym_unit(list:TAsmList;sym:tunitsym);virtual;
+ procedure appendsym_const(list:TAsmList;sym:tconstsym);virtual;
+ procedure appendsym_type(list:TAsmList;sym:ttypesym);virtual;
+ procedure appendsym_label(list:TAsmList;sym:tlabelsym);virtual;
+ procedure appendsym_absolute(list:TAsmList;sym:tabsolutevarsym);virtual;
+ procedure appendsym_property(list:TAsmList;sym:tpropertysym);virtual;
+ { symtable }
+ procedure write_symtable_parasyms(list:TAsmList;paras: tparalist);
+ procedure write_symtable_syms(list:TAsmList;st:TSymtable);
+ procedure write_symtable_defs(list:TAsmList;st:TSymtable);
+ procedure write_symtable_procdefs(list:TAsmList;st:TSymtable);
+ procedure reset_unit_type_info;
+ procedure write_used_unit_type_info(list:TAsmList;hp:tmodule);
+ public
+ constructor Create;virtual;
+ procedure inserttypeinfo;virtual;
+ procedure insertmoduleinfo;virtual;
+ procedure insertlineinfo(list:TAsmList);virtual;
+ procedure referencesections(list:TAsmList);virtual;
+ end;
+ TDebugInfoClass=class of TDebugInfo;
+
+ var
+ CDebugInfo : array[tdbg] of TDebugInfoClass;
+ current_debuginfo : tdebuginfo;
+
+ procedure InitDebugInfo(hp:tmodule);
+ procedure DoneDebugInfo(hp:tmodule);
+ procedure RegisterDebugInfo(const r:tdbginfo;c:TDebugInfoClass);
+
+
+implementation
+
+ uses
+ cutils,
+ verbose;
+
+
+ constructor TDebugInfo.Create;
+ begin
+ end;
+
+
+ procedure TDebugInfo.insertmoduleinfo;
+ begin
+ end;
+
+
+ procedure TDebugInfo.inserttypeinfo;
+ begin
+ end;
+
+
+ procedure TDebugInfo.insertlineinfo(list:TAsmList);
+ begin
+ end;
+
+
+ procedure TDebugInfo.referencesections(list:TAsmList);
+ begin
+ end;
+
+
+{**************************************
+ Definition
+**************************************}
+
+ procedure TDebugInfo.appendprocdef(list:TAsmList;def:tprocdef);
+ begin
+ end;
+
+
+ procedure TDebugInfo.beforeappenddef(list:TAsmList;def:tdef);
+ begin
+ end;
+
+
+ procedure TDebugInfo.afterappenddef(list:TAsmList;def:tdef);
+ begin
+ end;
+
+
+ procedure TDebugInfo.appenddef_ord(list:TAsmList;def:torddef);
+ begin
+ end;
+
+
+ procedure TDebugInfo.appenddef_float(list:TAsmList;def:tfloatdef);
+ begin
+ end;
+
+
+ procedure TDebugInfo.appenddef_formal(list:TAsmList;def: tformaldef);
+ begin
+ end;
+
+
+ procedure TDebugInfo.appenddef_undefined(list:TAsmList;def: tundefineddef);
+ begin
+ end;
+
+
+ procedure TDebugInfo.appenddef_set(list:TAsmList;def: tsetdef);
+ begin
+ end;
+
+
+ procedure TDebugInfo.appenddef_object(list:TAsmList;def: tobjectdef);
+ begin
+ end;
+
+
+ procedure TDebugInfo.appenddef_classref(list:TAsmList;def: tclassrefdef);
+ begin
+ appenddef_pointer(list,tpointerdef(pvmttype));
+ end;
+
+
+ procedure TDebugInfo.appenddef_variant(list:TAsmList;def: tvariantdef);
+ begin
+ end;
+
+
+ procedure TDebugInfo.appenddef_enum(list:TAsmList;def:tenumdef);
+ begin
+ end;
+
+
+ procedure TDebugInfo.appenddef_file(list:TAsmList;def: tfiledef);
+ begin
+ end;
+
+
+ procedure TDebugInfo.appenddef_array(list:TAsmList;def:tarraydef);
+ begin
+ end;
+
+
+ procedure TDebugInfo.appenddef_record(list:TAsmList;def:trecorddef);
+ begin
+ end;
+
+
+ procedure TDebugInfo.appenddef_pointer(list:TAsmList;def:tpointerdef);
+ begin
+ end;
+
+
+ procedure TDebugInfo.appenddef_string(list:TAsmList;def:tstringdef);
+ begin
+ end;
+
+
+ procedure TDebugInfo.appenddef_procvar(list:TAsmList;def:tprocvardef);
+ begin
+ end;
+
+
+ procedure TDebugInfo.appenddef(list:TAsmList;def:tdef);
+ begin
+ if (def.dbg_state in [dbg_state_writing,dbg_state_written]) then
+ exit;
+ { never write generic template defs }
+ if df_generic in def.defoptions then
+ begin
+ def.dbg_state:=dbg_state_written;
+ exit;
+ end;
+ { to avoid infinite loops }
+ def.dbg_state := dbg_state_writing;
+ beforeappenddef(list,def);
+ { queued defs have to be written later }
+ if (def.dbg_state=dbg_state_queued) then
+ exit;
+ case def.typ of
+ stringdef :
+ appenddef_string(list,tstringdef(def));
+ enumdef :
+ appenddef_enum(list,tenumdef(def));
+ orddef :
+ appenddef_ord(list,torddef(def));
+ pointerdef :
+ appenddef_pointer(list,tpointerdef(def));
+ floatdef :
+ appenddef_float(list,tfloatdef(def));
+ filedef :
+ appenddef_file(list,tfiledef(def));
+ recorddef :
+ appenddef_record(list,trecorddef(def));
+ variantdef :
+ appenddef_variant(list,tvariantdef(def));
+ classrefdef :
+ appenddef_classref(list,tclassrefdef(def));
+ setdef :
+ appenddef_set(list,tsetdef(def));
+ formaldef :
+ appenddef_formal(list,tformaldef(def));
+ arraydef :
+ appenddef_array(list,tarraydef(def));
+ procvardef :
+ appenddef_procvar(list,tprocvardef(def));
+ objectdef :
+ appenddef_object(list,tobjectdef(def));
+ undefineddef :
+ appenddef_undefined(list,tundefineddef(def));
+ procdef :
+ begin
+ { procdefs are already written in a separate step. procdef
+ support in appenddef is only needed for beforeappenddef to
+ write all local type defs }
+ end;
+ else
+ internalerror(200601281);
+ end;
+ afterappenddef(list,def);
+ def.dbg_state := dbg_state_written;
+ end;
+
+
+ procedure TDebugInfo.write_remaining_defs_to_write(list:TAsmList);
+ var
+ n : integer;
+ looplist,
+ templist: TFPObjectList;
+ def : tdef;
+ begin
+ templist := TFPObjectList.Create(False);
+ looplist := deftowritelist;
+ while looplist.count > 0 do
+ begin
+ deftowritelist := templist;
+ for n := 0 to looplist.count - 1 do
+ begin
+ def := tdef(looplist[n]);
+ case def.dbg_state of
+ dbg_state_written:
+ continue;
+ dbg_state_writing:
+ internalerror(200610052);
+ dbg_state_unused:
+ internalerror(200610053);
+ dbg_state_used:
+ appenddef(list,def);
+ else
+ internalerror(200610054);
+ end;
+ end;
+ looplist.clear;
+ templist := looplist;
+ looplist := deftowritelist;
+ end;
+ templist.free;
+ end;
+
+
+{**************************************
+ Symbols
+**************************************}
+
+ procedure TDebugInfo.beforeappendsym(list:TAsmList;sym:tsym);
+ begin
+ end;
+
+
+ procedure TDebugInfo.afterappendsym(list:TAsmList;sym:tsym);
+ begin
+ end;
+
+
+ procedure TDebugInfo.appendsym_staticvar(list:TAsmList;sym:tstaticvarsym);
+ begin
+ end;
+
+
+ procedure TDebugInfo.appendsym_paravar(list:TAsmList;sym: tparavarsym);
+ begin
+ end;
+
+
+ procedure TDebugInfo.appendsym_localvar(list:TAsmList;sym: tlocalvarsym);
+ begin
+ end;
+
+
+ procedure TDebugInfo.appendsym_fieldvar(list:TAsmList;sym: tfieldvarsym);
+ begin
+ end;
+
+
+ procedure TDebugInfo.appendsym_const(list:TAsmList;sym:tconstsym);
+ begin
+ end;
+
+
+ procedure TDebugInfo.appendsym_label(list:TAsmList;sym: tlabelsym);
+ begin
+ end;
+
+
+ procedure TDebugInfo.appendsym_property(list:TAsmList;sym: tpropertysym);
+ begin
+ end;
+
+
+ procedure TDebugInfo.appendsym_type(list:TAsmList;sym: ttypesym);
+ begin
+ end;
+
+
+ procedure TDebugInfo.appendsym_unit(list:TAsmList;sym: tunitsym);
+ begin
+ end;
+
+
+ procedure TDebugInfo.appendsym_absolute(list:TAsmList;sym:tabsolutevarsym);
+ begin
+ end;
+
+
+ procedure TDebugInfo.appendsym(list:TAsmList;sym:tsym);
+ begin
+ if sym.isdbgwritten then
+ exit;
+ beforeappendsym(list,sym);
+ case sym.typ of
+ staticvarsym :
+ appendsym_staticvar(list,tstaticvarsym(sym));
+ unitsym:
+ appendsym_unit(list,tunitsym(sym));
+ labelsym :
+ appendsym_label(list,tlabelsym(sym));
+ localvarsym :
+ appendsym_localvar(list,tlocalvarsym(sym));
+ paravarsym :
+ appendsym_paravar(list,tparavarsym(sym));
+ constsym :
+ appendsym_const(list,tconstsym(sym));
+ typesym :
+ appendsym_type(list,ttypesym(sym));
+ enumsym :
+ { ignore enum syms, they are written by the owner }
+ ;
+ syssym :
+ { ignore sys syms, they are only of internal use }
+ ;
+ procsym :
+ { ignore proc syms, they are written by procdefs }
+ ;
+ absolutevarsym :
+ appendsym_absolute(list,tabsolutevarsym(sym));
+ propertysym :
+ appendsym_property(list,tpropertysym(sym));
+ namespacesym :
+ { ignore namespace syms, they are only of internal use }
+ ;
+ else
+ internalerror(200601242);
+ end;
+ afterappendsym(list,sym);
+ sym.isdbgwritten:=true;
+ end;
+
+
+{**************************************
+ Symtables
+**************************************}
+
+ procedure TDebugInfo.write_symtable_defs(list:TAsmList;st:TSymtable);
+ var
+ def : tdef;
+ i : longint;
+ nonewadded : boolean;
+ begin
+ case st.symtabletype of
+ staticsymtable :
+ list.concat(tai_comment.Create(strpnew('Defs - Begin Staticsymtable')));
+ globalsymtable :
+ list.concat(tai_comment.Create(strpnew('Defs - Begin unit '+st.name^+' has index '+tostr(st.moduleid))));
+ end;
+ repeat
+ nonewadded:=true;
+ for i:=0 to st.DefList.Count-1 do
+ begin
+ def:=tdef(st.DefList[i]);
+ if (def.dbg_state in [dbg_state_used,dbg_state_queued]) then
+ begin
+ appenddef(list,def);
+ nonewadded:=false;
+ end;
+ end;
+ until nonewadded;
+ case st.symtabletype of
+ staticsymtable :
+ list.concat(tai_comment.Create(strpnew('Defs - End Staticsymtable')));
+ globalsymtable :
+ list.concat(tai_comment.Create(strpnew('Defs - End unit '+st.name^+' has index '+tostr(st.moduleid))));
+ end;
+ end;
+
+
+ procedure TDebugInfo.write_symtable_parasyms(list:TAsmList;paras: tparalist);
+ var
+ i : longint;
+ sym : tsym;
+ begin
+ for i:=0 to paras.Count-1 do
+ begin
+ sym:=tsym(paras[i]);
+ if (sym.visibility<>vis_hidden) then
+ begin
+ appendsym(list,sym);
+ { if we ever write this procdef again for some reason (this
+ can happen with DWARF), then we want to write all the
+ parasyms again as well. }
+ sym.isdbgwritten:=false;
+ end;
+ end;
+ end;
+
+
+ procedure TDebugInfo.write_symtable_syms(list:TAsmList;st:TSymtable);
+ var
+ i : longint;
+ sym : tsym;
+ begin
+ case st.symtabletype of
+ staticsymtable :
+ list.concat(tai_comment.Create(strpnew('Syms - Begin Staticsymtable')));
+ globalsymtable :
+ list.concat(tai_comment.Create(strpnew('Syms - Begin unit '+st.name^+' has index '+tostr(st.moduleid))));
+ end;
+ for i:=0 to st.SymList.Count-1 do
+ begin
+ sym:=tsym(st.SymList[i]);
+ if (sym.visibility<>vis_hidden) and
+ (not sym.isdbgwritten) then
+ appendsym(list,sym);
+ end;
+ case st.symtabletype of
+ staticsymtable :
+ list.concat(tai_comment.Create(strpnew('Syms - End Staticsymtable')));
+ globalsymtable :
+ list.concat(tai_comment.Create(strpnew('Syms - End unit '+st.name^+' has index '+tostr(st.moduleid))));
+ end;
+ end;
+
+
+ procedure TDebugInfo.write_symtable_procdefs(list:TAsmList;st:TSymtable);
+ var
+ i : longint;
+ def : tdef;
+ begin
+ for i:=0 to st.DefList.Count-1 do
+ begin
+ def:=tdef(st.DefList[i]);
+ case def.typ of
+ procdef :
+ begin
+ appendprocdef(list,tprocdef(def));
+ if assigned(tprocdef(def).localst) then
+ write_symtable_procdefs(list,tprocdef(def).localst);
+ end;
+ objectdef,recorddef :
+ begin
+ write_symtable_procdefs(list,tabstractrecorddef(def).symtable);
+ end;
+ end;
+ end;
+ end;
+
+
+ procedure TDebugInfo.reset_unit_type_info;
+ var
+ hp : tmodule;
+ begin
+ hp:=tmodule(loaded_units.first);
+ while assigned(hp) do
+ begin
+ hp.is_dbginfo_written:=false;
+ hp:=tmodule(hp.next);
+ end;
+ end;
+
+
+ procedure TDebugInfo.write_used_unit_type_info(list:TAsmList;hp:tmodule);
+ var
+ pu : tused_unit;
+ begin
+ pu:=tused_unit(hp.used_units.first);
+ while assigned(pu) do
+ begin
+ if not pu.u.is_dbginfo_written then
+ begin
+ { prevent infinte loop for circular dependencies }
+ pu.u.is_dbginfo_written:=true;
+ { write type info from used units, use a depth first
+ strategy to reduce the recursion in writing all
+ dependent stabs }
+ write_used_unit_type_info(list,pu.u);
+ if assigned(pu.u.globalsymtable) then
+ write_symtable_defs(list,pu.u.globalsymtable);
+ end;
+ pu:=tused_unit(pu.next);
+ end;
+ end;
+
+
+{****************************************************************************
+ Init / Done
+****************************************************************************}
+
+ procedure InitDebugInfo(hp:tmodule);
+ begin
+ if not assigned(CDebugInfo[target_dbg.id]) then
+ begin
+ Comment(V_Fatal,'cg_f_debuginfo_output_not_supported');
+ exit;
+ end;
+ hp.DebugInfo:=CDebugInfo[target_dbg.id].Create;
+ end;
+
+
+ procedure DoneDebugInfo(hp:tmodule);
+ begin
+ if assigned(hp.DebugInfo) then
+ begin
+ hp.DebugInfo.Free;
+ hp.DebugInfo:=nil;
+ end;
+ end;
+
+
+ procedure RegisterDebugInfo(const r:tdbginfo;c:TDebugInfoClass);
+ var
+ t : tdbg;
+ begin
+ t:=r.id;
+ if assigned(dbginfos[t]) then
+ writeln('Warning: DebugInfo is already registered!')
+ else
+ Getmem(dbginfos[t],sizeof(tdbginfo));
+ dbginfos[t]^:=r;
+ CDebugInfo[t]:=c;
+ end;
+
+
+ const
+ dbg_none_info : tdbginfo =
+ (
+ id : dbg_none;
+ idtxt : 'NONE';
+ );
+
+initialization
+ RegisterDebugInfo(dbg_none_info,TDebugInfo);
+end.
diff --git a/closures/compiler/dbgdwarf.pas b/closures/compiler/dbgdwarf.pas
new file mode 100644
index 0000000000..797a71db01
--- /dev/null
+++ b/closures/compiler/dbgdwarf.pas
@@ -0,0 +1,4139 @@
+{
+ Copyright (c) 2003-2006 by Peter Vreman and Florian Klaempfl
+
+ This units contains support for DWARF debug info generation
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+{
+ This units contains support for DWARF debug info generation.
+
+ Currently a lot of code looks like being mergable with dbgstabs. This might
+ change however when improved dwarf info is generated, so the stuff shouldn't be
+ merged yet. (FK)
+
+ The easiest way to debug dwarf debug info generation is the usage of
+ readelf --debug-dump <executable>
+ This works only with elf targets though.
+
+ There is a similar utility called dwarfdump which is not elf-specific and
+ which has been ported to most systems.
+}
+unit dbgdwarf;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cclasses,globtype,
+ aasmbase,aasmtai,aasmdata,
+ symbase,symconst,symtype,symdef,symsym,
+ finput,
+ DbgBase;
+
+ type
+ { Tag names and codes. }
+ tdwarf_tag = (DW_TAG_padding := $00,DW_TAG_array_type := $01,
+ DW_TAG_class_type := $02,DW_TAG_entry_point := $03,
+ DW_TAG_enumeration_type := $04,DW_TAG_formal_parameter := $05,
+ DW_TAG_imported_declaration := $08,DW_TAG_label := $0a,
+ DW_TAG_lexical_block := $0b,DW_TAG_member := $0d,
+ DW_TAG_pointer_type := $0f,DW_TAG_reference_type := $10,
+ DW_TAG_compile_unit := $11,DW_TAG_stringtypee := $12,
+ DW_TAG_structure_type := $13,DW_TAG_subroutine_type := $15,
+ DW_TAG_typedef := $16,DW_TAG_union_type := $17,
+ DW_TAG_unspecified_parameters := $18,
+ DW_TAG_variant := $19,DW_TAG_common_block := $1a,
+ DW_TAG_common_inclusion := $1b,DW_TAG_inheritance := $1c,
+ DW_TAG_inlined_subroutine := $1d,DW_TAG_module := $1e,
+ DW_TAG_ptr_to_member_type := $1f,DW_TAG_set_type := $20,
+ DW_TAG_subrange_type := $21,DW_TAG_with_stmt := $22,
+ DW_TAG_access_declaration := $23,DW_TAG_base_type := $24,
+ DW_TAG_catch_block := $25,DW_TAG_const_type := $26,
+ DW_TAG_constant := $27,DW_TAG_enumerator := $28,
+ DW_TAG_file_type := $29,DW_TAG_friend := $2a,
+ DW_TAG_namelist := $2b,DW_TAG_namelist_item := $2c,
+ DW_TAG_packed_type := $2d,DW_TAG_subprogram := $2e,
+ DW_TAG_template_type_param := $2f,DW_TAG_template_value_param := $30,
+ DW_TAG_thrown_type := $31,DW_TAG_try_block := $32,
+ DW_TAG_variant_part := $33,DW_TAG_variable := $34,
+ DW_TAG_volatile_type := $35,
+ { DWARF 3. }
+ DW_TAG_dwarf_procedure := $36,
+ DW_TAG_restrict_type := $37,DW_TAG_interface_type := $38,
+ DW_TAG_namespace := $39,DW_TAG_imported_module := $3a,
+ DW_TAG_unspecified_type := $3b,DW_TAG_partial_unit := $3c,
+ DW_TAG_imported_unit := $3d,
+ DW_TAG_condition := $3f,
+ DW_TAG_shared_type := $40,
+
+ { DWARF 4 }
+ DW_TAG_type_unit := $41,
+ DW_TAG_rvalue_reference_type := $42,
+ DW_TAG_template_alias := $43,
+
+
+ { SGI/MIPS Extensions. }
+ DW_TAG_MIPS_loop := $4081,
+
+ { HP extensions. See: ftp://ftp.hp.com/pub/lang/tools/WDB/wdb-4.0.tar.gz . }
+ DW_TAG_HP_array_descriptor := $4090,
+
+ { GNU extensions. }
+ { For FORTRAN 77 and Fortran 90. }
+ DW_TAG_format_label := $4101,
+ { For C++. }
+ DW_TAG_function_template := $4102,DW_TAG_class_template := $4103,
+
+ DW_TAG_GNU_BINCL := $4104,DW_TAG_GNU_EINCL := $4105,
+ { Extensions for UPC. See: http://upc.gwu.edu/~upc. }
+ DW_TAG_upc_shared_type := $8765,DW_TAG_upc_strict_type := $8766,
+ DW_TAG_upc_relaxed_type := $8767,
+
+ { PGI (STMicroelectronics) extensions. No documentation available. }
+ DW_TAG_PGI_kanji_type := $A000,
+ DW_TAG_PGI_interface_block := $A020
+ );
+
+{$notes off}
+ { Attribute names and codes. }
+ tdwarf_attribute = (DW_AT_sibling := $01,DW_AT_location := $02,
+ DW_AT_name := $03,DW_AT_ordering := $09,
+ DW_AT_subscr_data := $0a,DW_AT_byte_size := $0b,
+ DW_AT_bit_offset := $0c,DW_AT_bit_size := $0d,
+ DW_AT_element_list := $0f,DW_AT_stmt_list := $10,
+ DW_AT_low_pc := $11,DW_AT_high_pc := $12,
+ DW_AT_language := $13,DW_AT_member := $14,
+ DW_AT_discr := $15,DW_AT_discr_value := $16,
+ DW_AT_visibility := $17,DW_AT_import := $18,
+ DW_AT_string_length := $19,DW_AT_common_reference := $1a,
+ DW_AT_comp_dir := $1b,DW_AT_const_value := $1c,
+ DW_AT_containing_type := $1d,DW_AT_default_value := $1e,
+ DW_AT_inline := $20,DW_AT_is_optional := $21,
+ DW_AT_lower_bound := $22,DW_AT_producer := $25,
+ DW_AT_prototyped := $27,DW_AT_return_addr := $2a,
+ DW_AT_start_scope := $2c,DW_AT_stride_size := $2e,
+ DW_AT_upper_bound := $2f,DW_AT_abstract_origin := $31,
+ DW_AT_accessibility := $32,DW_AT_address_class := $33,
+ DW_AT_artificial := $34,DW_AT_base_types := $35,
+ DW_AT_calling_convention := $36,DW_AT_count := $37,
+ DW_AT_data_member_location := $38,DW_AT_decl_column := $39,
+ DW_AT_decl_file := $3a,DW_AT_decl_line := $3b,
+ DW_AT_declaration := $3c,DW_AT_discr_list := $3d,
+ DW_AT_encoding := $3e,DW_AT_external := $3f,
+ DW_AT_frame_base := $40,DW_AT_friend := $41,
+ DW_AT_identifier_case := $42,DW_AT_macro_info := $43,
+ DW_AT_namelist_items := $44,DW_AT_priority := $45,
+ DW_AT_segment := $46,DW_AT_specification := $47,
+ DW_AT_static_link := $48,DW_AT_type := $49,
+ DW_AT_use_location := $4a,DW_AT_variable_parameter := $4b,
+ DW_AT_virtuality := $4c,DW_AT_vtable_elem_location := $4d,
+
+ { DWARF 3 values. }
+ DW_AT_allocated := $4e,DW_AT_associated := $4f,
+ DW_AT_data_location := $50,DW_AT_byte_stride := $51,
+ DW_AT_entry_pc := $52,DW_AT_use_UTF8 := $53,
+ DW_AT_extension := $54,DW_AT_ranges := $55,
+ DW_AT_trampoline := $56,DW_AT_call_column := $57,
+ DW_AT_call_file := $58,DW_AT_call_line := $59,
+ DW_AT_description := $5a, { string }
+ DW_AT_binary_scale := $5b, { constant }
+ DW_AT_decimal_scale := $5c, { constant }
+ DW_AT_small := $5d, { reference }
+ DW_AT_decimal_sign := $5e, { constant }
+ DW_AT_digit_count := $5f, { constant }
+ DW_AT_picture_string := $60, { string }
+ DW_AT_mutable := $61, { flag }
+ DW_AT_threads_scaled := $62, { flag }
+ DW_AT_explicit := $63, { flag }
+ DW_AT_object_pointer := $64, { reference }
+ DW_AT_endianity := $65, { constant }
+ DW_AT_elemental := $66, { flag }
+ DW_AT_pure := $67, { flag }
+ DW_AT_recursive := $68, { flag }
+
+ { DWARF 4 values }
+ DW_AT_signature := $69, { reference }
+ DW_AT_main_subprogram := $6a, { flag }
+ DW_AT_data_bit_offset := $6b, { constant }
+ DW_AT_const_expr := $6c, { flag }
+ DW_AT_enum_class := $6d, { flag }
+ DW_AT_linkage_name := $6e, { string }
+
+
+ { SGI/MIPS extensions. }
+ DW_AT_MIPS_fde := $2001,DW_AT_MIPS_loop_begin := $2002,
+ DW_AT_MIPS_tail_loop_begin := $2003,DW_AT_MIPS_epilog_begin := $2004,
+ DW_AT_MIPS_loop_unroll_factor := $2005,
+ DW_AT_MIPS_software_pipeline_depth := $2006,
+ DW_AT_MIPS_linkage_name := $2007,DW_AT_MIPS_stride := $2008,
+ DW_AT_MIPS_abstract_name := $2009,DW_AT_MIPS_clone_origin := $200a,
+ DW_AT_MIPS_has_inlines := $200b,
+
+ { HP extensions. }
+ DW_AT_HP_block_index := $2000,
+ DW_AT_HP_unmodifiable := $2001,DW_AT_HP_actuals_stmt_list := $2010,
+ DW_AT_HP_proc_per_section := $2011,DW_AT_HP_raw_data_ptr := $2012,
+ DW_AT_HP_pass_by_reference := $2013,DW_AT_HP_opt_level := $2014,
+ DW_AT_HP_prof_version_id := $2015,DW_AT_HP_opt_flags := $2016,
+ DW_AT_HP_cold_region_low_pc := $2017,DW_AT_HP_cold_region_high_pc := $2018,
+ DW_AT_HP_all_variables_modifiable := $2019,
+ DW_AT_HP_linkage_name := $201a,DW_AT_HP_prof_flags := $201b,
+
+ { GNU extensions. }
+ DW_AT_sf_names := $2101,DW_AT_src_info := $2102,
+ DW_AT_mac_info := $2103,DW_AT_src_coords := $2104,
+ DW_AT_body_begin := $2105,DW_AT_body_end := $2106,
+ DW_AT_GNU_vector := $2107,
+
+ { VMS extensions. }
+ DW_AT_VMS_rtnbeg_pd_address := $2201,
+
+ { UPC extension. }
+ DW_AT_upc_threads_scaled := $3210,
+
+ { PGI (STMicroelectronics) extensions. }
+ DW_AT_PGI_lbase := $3a00,
+ DW_AT_PGI_soffset := $3a01,DW_AT_PGI_lstride := $3a02,
+
+ { Apple extensions }
+ DW_AT_APPLE_optimized := $3fe1,
+ DW_AT_APPLE_flags := $3fe2,
+ DW_AT_APPLE_major_runtime_vers := $3fe5,
+ DW_AT_APPLE_runtime_class := $3fe6
+ );
+{$notes on}
+
+ { Form names and codes. }
+ Tdwarf_form = (DW_FORM_addr := $01,DW_FORM_block2 := $03,
+ DW_FORM_block4 := $04,DW_FORM_data2 := $05,
+ DW_FORM_data4 := $06,DW_FORM_data8 := $07,
+ DW_FORM_string := $08,DW_FORM_block := $09,
+ DW_FORM_block1 := $0a,DW_FORM_data1 := $0b,
+ DW_FORM_flag := $0c,DW_FORM_sdata := $0d,
+ DW_FORM_strp := $0e,DW_FORM_udata := $0f,
+ DW_FORM_ref_addr := $10,DW_FORM_ref1 := $11,
+ DW_FORM_ref2 := $12,DW_FORM_ref4 := $13,
+ DW_FORM_ref8 := $14,DW_FORM_ref_udata := $15,
+ DW_FORM_indirect := $16,
+
+ { DWARF 4 }
+ DW_FORM_sec_offset := $17, { lineptr, loclistptr, macptr, rangelistptr }
+ DW_FORM_exprloc := $18, { exprloc }
+ DW_FORM_flag_present := $19, { flag }
+ DW_FORM_ref_sig8 := $20 { reference }
+ );
+
+ TDwarfFile = record
+ Index: integer;
+ Name: PChar;
+ end;
+
+ { flags for emitting variables/parameters }
+ tdwarfvarsymflag =
+ { force the sym to be emitted as a local variable regardless of its
+ type; used for "absolute" local variables referring to parameters.
+ }
+ (dvf_force_local_var
+ );
+ tdwarfvarsymflags = set of tdwarfvarsymflag;
+
+ pAbbrevSearchTreeItem = ^tAbbrevSearchTreeItem;
+ tAbbrevSearchTreeItem = record
+ value: QWord;
+ Abbrev: longint;
+ // When this item does not match the abbrev-value, look for it
+ // in the next SearchItem
+ SearchItem: pAbbrevSearchTreeItem;
+ // Next and prior item of the abbrev-section
+ NextItem: pAbbrevSearchTreeItem;
+ PriorItem: pAbbrevSearchTreeItem;
+ bit8: boolean;
+ end;
+
+ { TDebugInfoDwarf }
+
+ TDebugInfoDwarf = class(TDebugInfo)
+ private
+ currabbrevnumber : longint;
+
+ { use this defs to create info for variants and file handles }
+ { unused (MWE)
+ filerecdef,
+ textrecdef : tdef;
+ }
+
+ dirlist: TFPHashObjectList;
+ filesequence: Integer;
+ loclist: tdynamicarray;
+ asmline: TAsmList;
+
+ // The current entry in dwarf_info with the link to the abbrev-section
+ dwarf_info_abbref_tai: tai_const;
+ // Empty start-item of the abbrev-searchtree
+ AbbrevSearchTree: pAbbrevSearchTreeItem;
+ // The current abbrev-item
+ CurrentSearchTreeItem: pAbbrevSearchTreeItem;
+ // Is true when the abbrev-section is newly created
+ NewAbbrev: boolean;
+ procedure StartAbbrevSearch;
+ procedure AddConstToAbbrev(Value: QWord; bit8:boolean=false);
+ procedure StartAbbrevSectionFromSearchtree;
+ procedure WriteSearchItemToAbbrevSection(SI: pAbbrevSearchTreeItem);
+ function FinishAbbrevSearch: longint;
+
+ function def_dwarf_lab(def:tdef) : tasmsymbol;
+ function def_dwarf_ref_lab(def:tdef) : tasmsymbol;
+ function def_dwarf_class_struct_lab(def:tobjectdef) : tasmsymbol;
+ function get_file_index(afile: tinputfile): Integer;
+ function relative_dwarf_path(const s:tcmdstr):tcmdstr;
+ protected
+ // set if we should use 64bit headers (dwarf3 and up)
+ _use_64bit_headers: Boolean;
+ // set to ait_const32bit if use_64bit_headers is false, otherwise
+ // to ait_const64bit
+ offsetreltype,
+ offsetabstype : taiconst_type;
+ // set if we generated any lineinfo at all. If not, we have to terminate
+ // when insertmoduleinfo is called.
+ generated_lineinfo: boolean;
+
+ vardatadef: trecorddef;
+
+ procedure set_use_64bit_headers(state: boolean);
+ property use_64bit_headers: Boolean read _use_64bit_headers write set_use_64bit_headers;
+
+ procedure set_def_dwarf_labs(def:tdef);
+
+ { Convenience version of the method below, so the compiler creates the
+ tvarrec for us (must only pass one element in the last parameter). }
+ procedure append_attribute(attr: tdwarf_attribute; form: tdwarf_form; const values: array of const);
+ procedure append_attribute(attr: tdwarf_attribute; form: tdwarf_form; const value: tvarrec);
+ procedure append_entry(tag : tdwarf_tag;has_children : boolean;data : array of const);
+ procedure append_block1(attr: tdwarf_attribute; size: aint);
+ procedure append_labelentry(attr : tdwarf_attribute;sym : tasmsymbol);
+ procedure append_labelentry_addr_ref(attr : tdwarf_attribute;sym : tasmsymbol); virtual;
+ procedure append_labelentry_ref(attr : tdwarf_attribute;sym : tasmsymbol);
+ procedure append_labelentry_dataptr_abs(attr : tdwarf_attribute;sym : tasmsymbol);
+ procedure append_labelentry_dataptr_rel(attr : tdwarf_attribute;sym,endsym : tasmsymbol);
+ procedure append_labelentry_dataptr_common(attr : tdwarf_attribute);
+
+ procedure beforeappenddef(list:TAsmList;def:tdef);override;
+ procedure afterappenddef(list:TAsmList;def:tdef);override;
+ procedure appenddef_ord(list:TAsmList;def:torddef);override;
+ procedure appenddef_float(list:TAsmList;def:tfloatdef);override;
+ procedure appenddef_enum(list:TAsmList;def:tenumdef);override;
+ procedure appenddef_array(list:TAsmList;def:tarraydef);override;
+ procedure appenddef_record_named(list:TAsmList;def:trecorddef;const name: shortstring);
+ procedure appenddef_record(list:TAsmList;def:trecorddef);override;
+ procedure appenddef_pointer(list:TAsmList;def:tpointerdef);override;
+ procedure appenddef_string(list:TAsmList;def:tstringdef);override;
+ procedure appenddef_procvar(list:TAsmList;def:tprocvardef);override;
+ procedure appendprocdef(list:TAsmList;def:tprocdef);override;
+
+ function get_symlist_sym_offset(symlist: ppropaccesslistitem; out sym: tabstractvarsym; out offset: pint): boolean;
+ procedure appendsym_var(list:TAsmList;sym:tabstractnormalvarsym);
+ procedure appendsym_var_with_name_type_offset(list:TAsmList; sym:tabstractnormalvarsym; const name: string; def: tdef; offset: pint; const flags: tdwarfvarsymflags);
+ { used for fields and properties mapped to fields }
+ procedure appendsym_fieldvar_with_name_offset(list:TAsmList;sym: tfieldvarsym;const name: string; def: tdef; offset: pint);
+ procedure appendsym_const_member(list:TAsmList;sym:tconstsym;ismember:boolean);
+
+ procedure beforeappendsym(list:TAsmList;sym:tsym);override;
+ procedure appendsym_staticvar(list:TAsmList;sym:tstaticvarsym);override;
+ procedure appendsym_paravar(list:TAsmList;sym:tparavarsym);override;
+ procedure appendsym_localvar(list:TAsmList;sym:tlocalvarsym);override;
+ procedure appendsym_fieldvar(list:TAsmList;sym:tfieldvarsym);override;
+ procedure appendsym_const(list:TAsmList;sym:tconstsym);override;
+ procedure appendsym_type(list:TAsmList;sym:ttypesym);override;
+ procedure appendsym_label(list:TAsmList;sym:tlabelsym);override;
+ procedure appendsym_absolute(list:TAsmList;sym:tabsolutevarsym);override;
+ procedure appendsym_property(list:TAsmList;sym:tpropertysym);override;
+
+ function symdebugname(sym:tsym): String; virtual;
+ function symname(sym:tsym): String; virtual;
+ procedure append_visibility(vis: tvisibility);
+
+ procedure enum_membersyms_callback(p:TObject;arg:pointer);
+
+ procedure finish_children;
+ procedure finish_entry;
+ procedure finish_lineinfo;
+ public
+ constructor Create;override;
+ destructor Destroy;override;
+ procedure insertmoduleinfo;override;
+ procedure inserttypeinfo;override;
+ procedure referencesections(list:TAsmList);override;
+ procedure insertlineinfo(list:TAsmList);override;
+ function dwarf_version: Word; virtual; abstract;
+ end;
+
+ { TDebugInfoDwarf2 }
+
+ TDebugInfoDwarf2 = class(TDebugInfoDwarf)
+ private
+ protected
+ procedure appenddef_set_intern(list:TAsmList;def:tsetdef; force_tag_set: boolean);
+ procedure append_object_struct(def: tobjectdef; const createlabel: boolean; const objectname: PShortString);
+
+ procedure appenddef_file(list:TAsmList;def:tfiledef); override;
+ procedure appenddef_formal(list:TAsmList;def:tformaldef); override;
+ procedure appenddef_object(list:TAsmList;def:tobjectdef); override;
+ procedure appenddef_set(list:TAsmList;def:tsetdef); override;
+ procedure appenddef_undefined(list:TAsmList;def:tundefineddef); override;
+ procedure appenddef_variant(list:TAsmList;def:tvariantdef); override;
+ public
+ function dwarf_version: Word; override;
+ end;
+
+ { TDebugInfoDwarf3 }
+
+ TDebugInfoDwarf3 = class(TDebugInfoDwarf2)
+ private
+ protected
+ procedure append_labelentry_addr_ref(attr : tdwarf_attribute;sym : tasmsymbol); override;
+ procedure appenddef_array(list:TAsmList;def:tarraydef); override;
+ procedure appenddef_string(list:TAsmList;def:tstringdef);override;
+ procedure appenddef_file(list:TAsmList;def:tfiledef); override;
+ procedure appenddef_formal(list:TAsmList;def:tformaldef); override;
+ procedure appenddef_object(list:TAsmList;def:tobjectdef); override;
+ procedure appenddef_set(list:TAsmList;def: tsetdef); override;
+ procedure appenddef_undefined(list:TAsmList;def:tundefineddef); override;
+ procedure appenddef_variant(list:TAsmList;def:tvariantdef); override;
+
+ function symdebugname(sym:tsym): String; override;
+ public
+ function dwarf_version: Word; override;
+ end;
+
+
+ TDebugInfoDwarf4 = class(TDebugInfoDwarf3)
+ public
+ function dwarf_version: Word; override;
+ end;
+
+
+implementation
+
+ uses
+ sysutils,cutils,cfileutl,constexp,
+ version,globals,verbose,systems,
+ cpubase,cpuinfo,cgbase,paramgr,
+ fmodule,
+ defutil,symtable,ppu
+ ;
+
+ const
+ LINE_BASE = 1;
+ OPCODE_BASE = 13;
+
+ const
+ DW_TAG_lo_user = $4080;
+ DW_TAG_hi_user = $ffff;
+
+ { Flag that tells whether entry has a child or not. }
+ DW_children_no = 0;
+ DW_children_yes = 1;
+
+ const
+ { Implementation-defined range start. }
+ DW_AT_lo_user = $2000;
+ { Implementation-defined range end. }
+ DW_AT_hi_user = $3ff0;
+
+ type
+ { Source language names and codes. }
+ tdwarf_source_language = (DW_LANG_C89 := $0001,DW_LANG_C := $0002,DW_LANG_Ada83 := $0003,
+ DW_LANG_C_plus_plus := $0004,DW_LANG_Cobol74 := $0005,
+ DW_LANG_Cobol85 := $0006,DW_LANG_Fortran77 := $0007,
+ DW_LANG_Fortran90 := $0008,DW_LANG_Pascal83 := $0009,
+ DW_LANG_Modula2 := $000a,DW_LANG_Java := $000b,
+
+ { DWARF 3. }
+ DW_LANG_C99 := $000c,DW_LANG_Ada95 := $000d,
+ DW_LANG_Fortran95 := $000e,
+
+ { Objective-C }
+ DW_LANG_ObjC := $10,
+
+ { MIPS. }
+ DW_LANG_Mips_Assembler := $8001,
+
+ { UPC. }
+ DW_LANG_Upc := $8765
+ );
+
+ const
+ { Implementation-defined range start. }
+ DW_LANG_lo_user = $8000;
+
+ { Implementation-defined range start. }
+ DW_LANG_hi_user = $ffff;
+
+ type
+ { Names and codes for macro information. }
+ tdwarf_macinfo_record_type = (DW_MACINFO_define := 1,DW_MACINFO_undef := 2,
+ DW_MACINFO_start_file := 3,DW_MACINFO_end_file := 4,
+ DW_MACINFO_vendor_ext := 255);
+
+
+ type
+ { Type encodings. }
+ Tdwarf_type = (DW_ATE_void := $0,DW_ATE_address := $1,
+ DW_ATE_boolean := $2,DW_ATE_complex_float := $3,
+ DW_ATE_float := $4,DW_ATE_signed := $5,
+ DW_ATE_signed_char := $6,DW_ATE_unsigned := $7,
+ DW_ATE_unsigned_char := $8,DW_ATE_imaginary_float := $9,
+
+ { HP extensions. }
+ DW_ATE_HP_float80 := $80,DW_ATE_HP_complex_float80 := $81,
+ DW_ATE_HP_float128 := $82,DW_ATE_HP_complex_float128 := $83,
+ DW_ATE_HP_floathpintel := $84,DW_ATE_HP_imaginary_float80 := $85,
+ DW_ATE_HP_imaginary_float128 := $86
+ );
+
+
+ const
+ DW_ATE_lo_user = $80;
+ DW_ATE_hi_user = $ff;
+
+
+ type
+ Tdwarf_array_dim_ordering = (DW_ORD_row_major := 0,DW_ORD_col_major := 1
+ );
+
+ { Access attribute. }
+ Tdwarf_access_attribute = (DW_ACCESS_public := 1,DW_ACCESS_protected := 2,
+ DW_ACCESS_private := 3);
+
+ { Visibility. }
+ Tdwarf_visibility_attribute = (DW_VIS_local := 1,DW_VIS_exported := 2,
+ DW_VIS_qualified := 3);
+
+ { Virtuality. }
+ Tdwarf_virtuality_attribute = (DW_VIRTUALITY_none := 0,DW_VIRTUALITY_virtual := 1,
+ DW_VIRTUALITY_pure_virtual := 2);
+
+ { Case sensitivity. }
+ Tdwarf_id_case = (DW_ID_case_sensitive := 0,DW_ID_up_case := 1,
+ DW_ID_down_case := 2,DW_ID_case_insensitive := 3
+ );
+
+ { Calling convention. }
+ Tdwarf_calling_convention = (DW_CC_normal := $1,DW_CC_program := $2,
+ DW_CC_nocall := $3,DW_CC_GNU_renesas_sh := $40, DW_CC_GNU_borland_fastcall_i386 := $41
+ );
+{$notes off}
+ { Location atom names and codes. }
+ Tdwarf_location_atom = (DW_OP_addr := $03,DW_OP_deref := $06,DW_OP_const1u := $08,
+ DW_OP_const1s := $09,DW_OP_const2u := $0a,
+ DW_OP_const2s := $0b,DW_OP_const4u := $0c,
+ DW_OP_const4s := $0d,DW_OP_const8u := $0e,
+ DW_OP_const8s := $0f,DW_OP_constu := $10,
+ DW_OP_consts := $11,DW_OP_dup := $12,DW_OP_drop := $13,
+ DW_OP_over := $14,DW_OP_pick := $15,DW_OP_swap := $16,
+ DW_OP_rot := $17,DW_OP_xderef := $18,DW_OP_abs := $19,
+ DW_OP_and := $1a,DW_OP_div := $1b,DW_OP_minus := $1c,
+ DW_OP_mod := $1d,DW_OP_mul := $1e,DW_OP_neg := $1f,
+ DW_OP_not := $20,DW_OP_or := $21,DW_OP_plus := $22,
+ DW_OP_plus_uconst := $23,DW_OP_shl := $24,
+ DW_OP_shr := $25,DW_OP_shra := $26,DW_OP_xor := $27,
+ DW_OP_bra := $28,DW_OP_eq := $29,DW_OP_ge := $2a,
+ DW_OP_gt := $2b,DW_OP_le := $2c,DW_OP_lt := $2d,
+ DW_OP_ne := $2e,DW_OP_skip := $2f,DW_OP_lit0 := $30,
+ DW_OP_lit1 := $31,DW_OP_lit2 := $32,DW_OP_lit3 := $33,
+ DW_OP_lit4 := $34,DW_OP_lit5 := $35,DW_OP_lit6 := $36,
+ DW_OP_lit7 := $37,DW_OP_lit8 := $38,DW_OP_lit9 := $39,
+ DW_OP_lit10 := $3a,DW_OP_lit11 := $3b,
+ DW_OP_lit12 := $3c,DW_OP_lit13 := $3d,
+ DW_OP_lit14 := $3e,DW_OP_lit15 := $3f,
+ DW_OP_lit16 := $40,DW_OP_lit17 := $41,
+ DW_OP_lit18 := $42,DW_OP_lit19 := $43,
+ DW_OP_lit20 := $44,DW_OP_lit21 := $45,
+ DW_OP_lit22 := $46,DW_OP_lit23 := $47,
+ DW_OP_lit24 := $48,DW_OP_lit25 := $49,
+ DW_OP_lit26 := $4a,DW_OP_lit27 := $4b,
+ DW_OP_lit28 := $4c,DW_OP_lit29 := $4d,
+ DW_OP_lit30 := $4e,DW_OP_lit31 := $4f,
+ DW_OP_reg0 := $50,DW_OP_reg1 := $51,DW_OP_reg2 := $52,
+ DW_OP_reg3 := $53,DW_OP_reg4 := $54,DW_OP_reg5 := $55,
+ DW_OP_reg6 := $56,DW_OP_reg7 := $57,DW_OP_reg8 := $58,
+ DW_OP_reg9 := $59,DW_OP_reg10 := $5a,DW_OP_reg11 := $5b,
+ DW_OP_reg12 := $5c,DW_OP_reg13 := $5d,
+ DW_OP_reg14 := $5e,DW_OP_reg15 := $5f,
+ DW_OP_reg16 := $60,DW_OP_reg17 := $61,
+ DW_OP_reg18 := $62,DW_OP_reg19 := $63,
+ DW_OP_reg20 := $64,DW_OP_reg21 := $65,
+ DW_OP_reg22 := $66,DW_OP_reg23 := $67,
+ DW_OP_reg24 := $68,DW_OP_reg25 := $69,
+ DW_OP_reg26 := $6a,DW_OP_reg27 := $6b,
+ DW_OP_reg28 := $6c,DW_OP_reg29 := $6d,
+ DW_OP_reg30 := $6e,DW_OP_reg31 := $6f,
+ DW_OP_breg0 := $70,DW_OP_breg1 := $71,
+ DW_OP_breg2 := $72,DW_OP_breg3 := $73,
+ DW_OP_breg4 := $74,DW_OP_breg5 := $75,
+ DW_OP_breg6 := $76,DW_OP_breg7 := $77,
+ DW_OP_breg8 := $78,DW_OP_breg9 := $79,
+ DW_OP_breg10 := $7a,DW_OP_breg11 := $7b,
+ DW_OP_breg12 := $7c,DW_OP_breg13 := $7d,
+ DW_OP_breg14 := $7e,DW_OP_breg15 := $7f,
+ DW_OP_breg16 := $80,DW_OP_breg17 := $81,
+ DW_OP_breg18 := $82,DW_OP_breg19 := $83,
+ DW_OP_breg20 := $84,DW_OP_breg21 := $85,
+ DW_OP_breg22 := $86,DW_OP_breg23 := $87,
+ DW_OP_breg24 := $88,DW_OP_breg25 := $89,
+ DW_OP_breg26 := $8a,DW_OP_breg27 := $8b,
+ DW_OP_breg28 := $8c,DW_OP_breg29 := $8d,
+ DW_OP_breg30 := $8e,DW_OP_breg31 := $8f,
+ DW_OP_regx := $90,DW_OP_fbreg := $91,DW_OP_bregx := $92,
+ DW_OP_piece := $93,DW_OP_deref_size := $94,
+ DW_OP_xderef_size := $95,DW_OP_nop := $96,
+
+ { DWARF 3 extensions. }
+ DW_OP_push_object_address := $97,DW_OP_call2 := $98,
+ DW_OP_call4 := $99,DW_OP_call_ref := $9a,
+
+ { DWARF 4 extensions. }
+ DW_OP_implicit_value := $9e, DW_OP_stack_value := $9f,
+
+ { GNU extensions. }
+ DW_OP_GNU_push_tls_address := $e0,
+
+ { HP extensions. }
+ DW_OP_HP_unknown := $e0,
+ DW_OP_HP_is_value := $e1,DW_OP_HP_fltconst4 := $e2,
+ DW_OP_HP_fltconst8 := $e3,DW_OP_HP_mod_range := $e4,
+ DW_OP_HP_unmod_range := $e5,DW_OP_HP_tls := $e6
+ );
+{$notes on}
+
+ const
+ { Implementation-defined range start. }
+ DW_OP_lo_user = $e0;
+ { Implementation-defined range end. }
+ DW_OP_hi_user = $ff;
+
+
+ const
+ DW_LNS_extended_op = $00;
+
+ { next copied from cfidwarf, need to go to something shared }
+ DW_LNS_copy = $01;
+ DW_LNS_advance_pc = $02;
+ DW_LNS_advance_line = $03;
+ DW_LNS_set_file = $04;
+ DW_LNS_set_column = $05;
+ DW_LNS_negate_stmt = $06;
+ DW_LNS_set_basic_block = $07;
+ DW_LNS_const_add_pc = $08;
+
+ DW_LNS_fixed_advance_pc = $09;
+ DW_LNS_set_prologue_end = $0a;
+ DW_LNS_set_epilogue_begin = $0b;
+ DW_LNS_set_isa = $0c;
+
+ DW_LNE_end_sequence = $01;
+ DW_LNE_set_address = $02;
+ DW_LNE_define_file = $03;
+ DW_LNE_lo_user = $80;
+ DW_LNE_hi_user = $ff;
+
+ type
+ { TDirIndexItem }
+
+ TDirIndexItem = class(TFPHashObject)
+ private
+ FFiles: TFPHashObjectList;
+ public
+ IndexNr : Integer;
+ constructor Create(AList:TFPHashObjectList;const AName: String; AIndex: Integer);
+ destructor Destroy;override;
+ property Files: TFPHashObjectList read FFiles;
+ end;
+
+ { TFileIndexItem }
+
+ TFileIndexItem = class(TFPHashObject)
+ private
+ FDirIndex: Integer;
+ public
+ IndexNr : Integer;
+ constructor Create(AList:TFPHashObjectList;const AName: String; ADirIndex, AIndex: Integer);
+ property DirIndex: Integer read FDirIndex;
+ end;
+
+
+{****************************************************************************
+ procs
+****************************************************************************}
+
+ function DirListSortCompare(AItem1, AItem2: Pointer): Integer;
+ begin
+ Result := TDirIndexItem(AItem1).IndexNr - TDirIndexItem(AItem2).IndexNr;
+ end;
+
+
+ function FileListSortCompare(AItem1, AItem2: Pointer): Integer;
+ begin
+ Result := TFileIndexItem(AItem1).IndexNr - TFileIndexItem(AItem2).IndexNr;
+ end;
+
+
+ function AllocateNewAiSearchItem: pAbbrevSearchTreeItem;
+ begin
+ new(result);
+ FillChar(result^,sizeof(result^),#0);
+ end;
+
+ procedure FreeSearchItem(SI: pAbbrevSearchTreeItem);
+ begin
+ if assigned(SI^.NextItem) then
+ FreeSearchItem(SI^.NextItem);
+ if assigned(SI^.SearchItem) then
+ FreeSearchItem(SI^.SearchItem);
+ Dispose(SI);
+ end;
+
+{****************************************************************************
+ TDirIndexItem
+****************************************************************************}
+
+ constructor TDirIndexItem.Create(AList:TFPHashObjectList;const AName: String; AIndex: Integer);
+ begin
+ inherited Create(AList,AName);
+ FFiles := TFPHashObjectList.Create;
+ IndexNr := AIndex;
+ end;
+
+
+ destructor TDirIndexItem.Destroy;
+ begin
+ FFiles.Free;
+ inherited Destroy;
+ end;
+
+
+{****************************************************************************
+ TFileIndexItem
+****************************************************************************}
+
+ constructor TFileIndexItem.Create(AList:TFPHashObjectList;const AName: String; ADirIndex, AIndex: Integer);
+ begin
+ inherited Create(AList,Aname);
+ FDirIndex := ADirIndex;
+ IndexNr := AIndex;
+ end;
+
+
+{****************************************************************************
+ TDebugInfoDwarf
+****************************************************************************}
+
+ procedure TDebugInfoDwarf.StartAbbrevSearch;
+ begin
+ CurrentSearchTreeItem:=AbbrevSearchTree;
+ end;
+
+
+ procedure TDebugInfoDwarf.WriteSearchItemToAbbrevSection(SI: pAbbrevSearchTreeItem);
+ begin
+ if SI^.bit8 then
+ current_asmdata.asmlists[al_dwarf_abbrev].concat(tai_const.Create_8bit(SI^.value))
+ else
+ current_asmdata.asmlists[al_dwarf_abbrev].concat(tai_const.Create_uleb128bit(SI^.value));
+ end;
+
+
+ procedure TDebugInfoDwarf.StartAbbrevSectionFromSearchtree;
+
+ procedure AddCurrentAndPriorItemsToAbrev(SI: pAbbrevSearchTreeItem);
+ begin
+ if assigned(SI^.PriorItem) then
+ AddCurrentAndPriorItemsToAbrev(SI^.PriorItem);
+ WriteSearchItemToAbbrevSection(SI);
+ end;
+
+ begin
+ NewAbbrev:=true;
+ inc(currabbrevnumber);
+ current_asmdata.asmlists[al_dwarf_abbrev].concat(tai_comment.Create(strpnew('Abbrev '+tostr(currabbrevnumber))));
+ current_asmdata.asmlists[al_dwarf_abbrev].concat(tai_const.create_uleb128bit(currabbrevnumber));
+
+ if CurrentSearchTreeItem<>AbbrevSearchTree then
+ AddCurrentAndPriorItemsToAbrev(CurrentSearchTreeItem);
+ end;
+
+
+ function TDebugInfoDwarf.FinishAbbrevSearch: longint;
+
+ procedure FinalizeAbbrevSection;
+ begin
+ current_asmdata.asmlists[al_dwarf_abbrev].concat(tai_const.create_8bit(0));
+ current_asmdata.asmlists[al_dwarf_abbrev].concat(tai_const.create_8bit(0));
+ CurrentSearchTreeItem^.Abbrev:=currabbrevnumber;
+ NewAbbrev := false;
+ end;
+
+ begin
+ if NewAbbrev then
+ FinalizeAbbrevSection;
+ result := CurrentSearchTreeItem^.Abbrev;
+ if result=0 then
+ begin
+ // In this case the abbrev-section equals an existing longer abbrev section.
+ // So a new abbrev-section has to be made which ends on the current
+ // searchtree item
+ StartAbbrevSectionFromSearchtree;
+ FinalizeAbbrevSection;
+ result := CurrentSearchTreeItem^.Abbrev;
+ end;
+ end;
+
+
+ procedure TDebugInfoDwarf.AddConstToAbbrev(Value: QWord; bit8:boolean);
+
+ procedure AddCurrentItemToAbbrev;
+ begin
+ CurrentSearchTreeItem^.value:=value;
+ CurrentSearchTreeItem^.bit8:=bit8;
+ WriteSearchItemToAbbrevSection(CurrentSearchTreeItem);
+ end;
+
+ var si: pAbbrevSearchTreeItem;
+ begin
+ // Instead of adding this value directly to the ai-tree, search if an
+ // abbrev section with the same values already exist, and use the existing
+ // one or create one.
+ if NewAbbrev then
+ begin
+ // The current abbrev-section is new, so add the value to the abbrev-section
+ // and add it to the search-list.
+ CurrentSearchTreeItem^.NextItem:=AllocateNewAiSearchItem;
+ CurrentSearchTreeItem^.NextItem^.PriorItem:=CurrentSearchTreeItem;
+ CurrentSearchTreeItem := CurrentSearchTreeItem^.NextItem;
+ AddCurrentItemToAbbrev;
+ end
+ else
+ begin
+ // Search for the value which is added in the next sections of the
+ // searchtree for a match
+ si := CurrentSearchTreeItem^.NextItem;
+ while assigned(si) do
+ begin
+ if (SI^.value=Value) and (si^.bit8=bit8) then
+ begin
+ // If a match is found, set the current searchtree item to the next item
+ CurrentSearchTreeItem:=SI;
+ Exit;
+ end
+ else if si^.SearchItem=nil then
+ begin
+ // If no match is found, add a new item to the searchtree and write
+ // a new abbrev-section.
+ StartAbbrevSectionFromSearchtree;
+
+ si^.SearchItem:=AllocateNewAiSearchItem;
+ if currentsearchtreeitem<>AbbrevSearchTree then
+ si^.SearchItem^.PriorItem:=CurrentSearchTreeItem;
+ CurrentSearchTreeItem := si^.SearchItem;
+
+ AddCurrentItemToAbbrev;
+ Exit;
+ end;
+ Si := SI^.SearchItem;
+ end;
+ // The abbrev section we are looking for is longer than the one
+ // which is already in the search-tree. So expand the searchtree with
+ // the new value and write a new abbrev section
+ StartAbbrevSectionFromSearchtree;
+
+ CurrentSearchTreeItem^.NextItem:=AllocateNewAiSearchItem;
+ if currentsearchtreeitem^.PriorItem<>AbbrevSearchTree then
+ CurrentSearchTreeItem^.NextItem^.PriorItem:=CurrentSearchTreeItem;
+ CurrentSearchTreeItem := CurrentSearchTreeItem^.NextItem;
+
+ AddCurrentItemToAbbrev;
+ end;
+ end;
+
+
+ function TDebugInfoDwarf.relative_dwarf_path(const s:tcmdstr):tcmdstr;
+ begin
+ { Make a clean path for gdb. Remove trailing / and ./ prefixes and
+ use always a / }
+ result:=BsToSlash(ExcludeTrailingPathDelimiter(ExtractRelativePath(GetCurrentDir,FixFileName(ExpandFileName(s)))));
+ end;
+
+
+ procedure TDebugInfoDwarf.set_use_64bit_headers(state: boolean);
+ begin
+ _use_64bit_headers:=state;
+ if not(state) then
+ begin
+ if (target_info.system in systems_windows+systems_wince) then
+ offsetabstype:=aitconst_secrel32_symbol
+ else
+ offsetabstype:=aitconst_32bit;
+ if (target_info.system in systems_darwin) then
+ offsetreltype:=aitconst_darwin_dwarf_delta32
+ else
+ offsetreltype:=aitconst_32bit;
+ end
+ else
+ begin
+ if (target_info.system in systems_darwin) then
+ offsetreltype:=aitconst_darwin_dwarf_delta64
+ else
+ offsetreltype:=aitconst_64bit;
+ offsetabstype:=aitconst_64bit;
+ end;
+ end;
+
+
+ procedure TDebugInfoDwarf.set_def_dwarf_labs(def:tdef);
+ begin
+ { Keep track of used dwarf entries, this info is only useful for dwarf entries
+ referenced by the symbols. Definitions will always include all
+ required stabs }
+ if def.dbg_state=dbg_state_unused then
+ def.dbg_state:=dbg_state_used;
+ { Need a new label? }
+ if not assigned(def.dwarf_lab) then
+ begin
+ if not(tf_dwarf_only_local_labels in target_info.flags) then
+ begin
+ if (ds_dwarf_dbg_info_written in def.defstates) then
+ begin
+ if not assigned(def.typesym) then
+ internalerror(200610011);
+ def.dwarf_lab:=current_asmdata.RefAsmSymbol(make_mangledname('DBG',def.owner,symname(def.typesym)));
+ def.dwarf_ref_lab:=current_asmdata.RefAsmSymbol(make_mangledname('DBGREF',def.owner,symname(def.typesym)));
+ if is_class_or_interface_or_dispinterface(def) or is_objectpascal_helper(def) then
+ tobjectdef(def).dwarf_struct_lab:=current_asmdata.RefAsmSymbol(make_mangledname('DBG2',def.owner,symname(def.typesym)));
+ def.dbg_state:=dbg_state_written;
+ end
+ else
+ begin
+ { Create an exported DBG symbol if we are generating a def defined in the
+ globalsymtable of the current unit }
+ if assigned(def.typesym) and
+ (def.owner.symtabletype=globalsymtable) and
+ (def.owner.iscurrentunit) then
+ begin
+ def.dwarf_lab:=current_asmdata.DefineAsmSymbol(make_mangledname('DBG',def.owner,symname(def.typesym)),AB_GLOBAL,AT_DATA);
+ def.dwarf_ref_lab:=current_asmdata.DefineAsmSymbol(make_mangledname('DBGREF',def.owner,symname(def.typesym)),AB_GLOBAL,AT_DATA);
+ if is_class_or_interface_or_dispinterface(def) or is_objectpascal_helper(def) then
+ tobjectdef(def).dwarf_struct_lab:=current_asmdata.DefineAsmSymbol(make_mangledname('DBG2',def.owner,symname(def.typesym)),AB_GLOBAL,AT_DATA);
+ include(def.defstates,ds_dwarf_dbg_info_written);
+ end
+ else
+ begin
+ { The pointer typecast is needed to prevent a problem with range checking
+ on when the typecast is changed to 'as' }
+ current_asmdata.getdatalabel(TAsmLabel(pointer(def.dwarf_lab)));
+ current_asmdata.getdatalabel(TAsmLabel(pointer(def.dwarf_ref_lab)));
+ if is_implicit_pointer_object_type(def) then
+ current_asmdata.getdatalabel(TAsmLabel(pointer(tobjectdef(def).dwarf_struct_lab)));
+ end;
+ end;
+ end
+ else
+ begin
+ { The pointer typecast is needed to prevent a problem with range checking
+ on when the typecast is changed to 'as' }
+ { addrlabel instead of datalabel because it must be a local one }
+ current_asmdata.getaddrlabel(TAsmLabel(pointer(def.dwarf_lab)));
+ current_asmdata.getaddrlabel(TAsmLabel(pointer(def.dwarf_ref_lab)));
+ if is_implicit_pointer_object_type(def) then
+ current_asmdata.getaddrlabel(TAsmLabel(pointer(tobjectdef(def).dwarf_struct_lab)));
+ end;
+ if def.dbg_state=dbg_state_used then
+ deftowritelist.Add(def);
+ defnumberlist.Add(def);
+ end;
+ end;
+
+ function TDebugInfoDwarf.def_dwarf_lab(def: tdef): tasmsymbol;
+ begin
+ set_def_dwarf_labs(def);
+ result:=def.dwarf_lab;
+ end;
+
+ function TDebugInfoDwarf.def_dwarf_class_struct_lab(def: tobjectdef): tasmsymbol;
+ begin
+ set_def_dwarf_labs(def);
+ result:=def.dwarf_struct_lab;
+ end;
+
+ function TDebugInfoDwarf.def_dwarf_ref_lab(def: tdef): tasmsymbol;
+ begin
+ set_def_dwarf_labs(def);
+ result:=def.dwarf_ref_lab;
+ end;
+
+ constructor TDebugInfoDwarf.Create;
+ begin
+ inherited Create;
+ { 64bit headers are only supported for dwarf3 and up, so default off }
+ use_64bit_headers := false;
+ { we haven't generated any lineinfo yet }
+ generated_lineinfo := false;
+
+ dirlist := TFPHashObjectList.Create;
+ { add current dir as first item (index=0) }
+ TDirIndexItem.Create(dirlist,'.', 0);
+ asmline := TAsmList.create;
+ loclist := tdynamicarray.Create(4096);
+
+ AbbrevSearchTree:=AllocateNewAiSearchItem;
+
+ vardatadef := nil;
+ end;
+
+
+ destructor TDebugInfoDwarf.Destroy;
+ begin
+ dirlist.Free;
+ if assigned(AbbrevSearchTree) then
+ FreeSearchItem(AbbrevSearchTree);
+ dirlist := nil;
+ asmline.free;
+ asmline:=nil;
+ loclist.Free;
+ loclist := nil;
+ inherited Destroy;
+ end;
+
+
+ procedure TDebugInfoDwarf.enum_membersyms_callback(p:TObject; arg: pointer);
+ begin
+ case tsym(p).typ of
+ fieldvarsym:
+ appendsym_fieldvar(TAsmList(arg),tfieldvarsym(p));
+ propertysym:
+ appendsym_property(TAsmList(arg),tpropertysym(p));
+ constsym:
+ appendsym_const_member(TAsmList(arg),tconstsym(p),true);
+ end;
+ end;
+
+
+ function TDebugInfoDwarf.get_file_index(afile: tinputfile): Integer;
+ var
+ dirname: String;
+ diritem: TDirIndexItem;
+ diridx: Integer;
+ fileitem: TFileIndexItem;
+ begin
+ if afile.path^ = '' then
+ dirname := '.'
+ else
+ begin
+ { add the canonical form here already to avoid problems with }
+ { paths such as './' etc }
+ dirname := relative_dwarf_path(afile.path^);
+ if dirname = '' then
+ dirname := '.';
+ end;
+ diritem := TDirIndexItem(dirlist.Find(dirname));
+ if diritem = nil then
+ diritem := TDirIndexItem.Create(dirlist,dirname, dirlist.Count);
+ diridx := diritem.IndexNr;
+
+ fileitem := TFileIndexItem(diritem.files.Find(afile.name^));
+ if fileitem = nil then
+ begin
+ Inc(filesequence);
+ fileitem := TFileIndexItem.Create(diritem.files,afile.name^, diridx, filesequence);
+ end;
+ Result := fileitem.IndexNr;
+ end;
+
+
+ procedure TDebugInfoDwarf.append_attribute(attr: tdwarf_attribute; form: tdwarf_form; const values: array of const);
+ begin
+ if length(values)<>1 then
+ internalerror(2009040402);
+ append_attribute(attr,form,values[0]);
+ end;
+
+
+ procedure TDebugInfoDwarf.append_attribute(attr: tdwarf_attribute; form: tdwarf_form; const value: tvarrec);
+ begin
+ { attribute }
+ AddConstToAbbrev(cardinal(attr));
+
+ { form }
+ AddConstToAbbrev(cardinal(form));
+
+ { info itself }
+ case form of
+ DW_FORM_string:
+ case value.VType of
+ vtChar:
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_string.create(value.VChar));
+ vtString:
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_string.create(value.VString^));
+ vtAnsistring:
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_string.create(Ansistring(value.VAnsiString)));
+ else
+ internalerror(200601264);
+ end;
+
+ DW_FORM_flag:
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(byte(value.VBoolean)));
+
+ DW_FORM_data1:
+ case value.VType of
+ vtInteger:
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(value.VInteger));
+ vtInt64:
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(value.VInt64^));
+ vtQWord:
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(value.VQWord^));
+ else
+ internalerror(200602143);
+ end;
+
+ DW_FORM_data2:
+ case value.VType of
+ vtInteger:
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_16bit(value.VInteger));
+ vtInt64:
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_16bit(value.VInt64^));
+ vtQWord:
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_16bit(value.VQWord^));
+ else
+ internalerror(200602144);
+ end;
+
+ DW_FORM_data4:
+ case value.VType of
+ vtInteger:
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_32bit(value.VInteger));
+ vtInt64:
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_32bit(value.VInt64^));
+ vtQWord:
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_32bit(value.VQWord^));
+ else
+ internalerror(200602145);
+ end;
+
+ DW_FORM_data8:
+ case value.VType of
+ vtInteger:
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_64bit(value.VInteger));
+ vtInt64:
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_64bit(value.VInt64^));
+ vtQWord:
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_64bit(value.VQWord^));
+ else
+ internalerror(200602146);
+ end;
+
+ DW_FORM_sdata:
+ case value.VType of
+ vtInteger:
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_sleb128bit(value.VInteger));
+ vtInt64:
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_sleb128bit(value.VInt64^));
+ vtQWord:
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_sleb128bit(value.VQWord^));
+ else
+ internalerror(200601285);
+ end;
+
+ DW_FORM_udata:
+ case value.VType of
+ vtInteger:
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_uleb128bit(value.VInteger));
+ vtInt64:
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_uleb128bit(value.VInt64^));
+ vtQWord:
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_uleb128bit(value.VQWord^));
+ else
+ internalerror(200601284);
+ end;
+
+ { block gets only the size, the rest is appended manually by the caller }
+ DW_FORM_block1:
+ case value.VType of
+ vtInteger:
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(value.VInteger));
+ vtInt64:
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(value.VInt64^));
+ vtQWord:
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(value.VQWord^));
+ else
+ internalerror(200602141);
+ end;
+ else
+ internalerror(200601263);
+ end;
+ end;
+
+
+ { writing the data through a few simply procedures allows to create easily extra information
+ for debugging of debug info }
+ procedure TDebugInfoDwarf.append_entry(tag : tdwarf_tag;has_children : boolean;data : array of const);
+ var
+ i : longint;
+ begin
+ { abbrev number }
+ // Store the ai with the reference to the abbrev number and start a search
+ // to find the right abbrev-section. (Or create one)
+ dwarf_info_abbref_tai := tai_const.create_uleb128bit(currabbrevnumber);
+ current_asmdata.asmlists[al_dwarf_info].concat(dwarf_info_abbref_tai);
+ StartAbbrevSearch;
+
+ { tag }
+ AddConstToAbbrev(ord(tag));
+
+ { children? }
+ AddConstToAbbrev(ord(has_children),true);
+
+ i:=0;
+ while i<=high(data) do
+ begin
+ if (i+2 > high(data)) then
+ internalerror(2009040401);
+ if data[i].VType<>vtInteger then
+ internalerror(200601261);
+ if data[i+1].VType<>vtInteger then
+ internalerror(200601261);
+ append_attribute(tdwarf_attribute(data[i].VInteger),tdwarf_form(data[i+1].VInteger),data[i+2]);
+ inc(i,3);
+ end;
+ end;
+
+
+ procedure TDebugInfoDwarf.append_block1(attr: tdwarf_attribute; size: aint);
+ begin
+ AddConstToAbbrev(ord(attr));
+ AddConstToAbbrev(ord(DW_FORM_block1));
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(size));
+ end;
+
+
+ procedure TDebugInfoDwarf.append_labelentry(attr : tdwarf_attribute;sym : tasmsymbol);
+ begin
+ AddConstToAbbrev(ord(attr));
+ AddConstToAbbrev(ord(DW_FORM_addr));
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_sym(sym));
+ end;
+
+ procedure TDebugInfoDwarf.append_labelentry_addr_ref(attr : tdwarf_attribute;sym : tasmsymbol);
+ begin
+ AddConstToAbbrev(ord(DW_FORM_ref_addr));
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_sym(sym))
+ end;
+
+ procedure TDebugInfoDwarf.append_labelentry_ref(attr : tdwarf_attribute;sym : tasmsymbol);
+ begin
+ AddConstToAbbrev(ord(attr));
+ if not(tf_dwarf_only_local_labels in target_info.flags) then
+ append_labelentry_addr_ref(attr, sym)
+ else
+ begin
+ AddConstToAbbrev(ord(DW_FORM_ref4));
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_rel_sym(offsetreltype,current_asmdata.RefAsmSymbol(target_asm.labelprefix+'debug_info0'),sym));
+ end;
+ end;
+
+
+ procedure TDebugInfoDwarf.append_labelentry_dataptr_common(attr : tdwarf_attribute);
+ begin
+ AddConstToAbbrev(ord(attr));
+ if use_64bit_headers then
+ AddConstToAbbrev(ord(DW_FORM_data8))
+ else
+ AddConstToAbbrev(ord(DW_FORM_data4));
+ end;
+
+
+ procedure TDebugInfoDwarf.append_labelentry_dataptr_abs(attr : tdwarf_attribute;sym : tasmsymbol);
+ begin
+ {
+ used for writing dwarf lineptr, loclistptr, macptr and rangelistptr classes as FORM_dataN
+ The size of these depend on the header format
+ Must be relative to another symbol on tf_dwarf_relative_addresses
+ targets
+ }
+ if (tf_dwarf_relative_addresses in target_info.flags) then
+ { use append_labelentry_dataptr_rel instead }
+ internalerror(2007020210);
+ append_labelentry_dataptr_common(attr);
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_type_sym(offsetabstype,sym))
+ end;
+
+
+ procedure TDebugInfoDwarf.append_labelentry_dataptr_rel(attr : tdwarf_attribute;sym,endsym : tasmsymbol);
+ begin
+ {
+ used for writing dwarf lineptr, loclistptr, macptr and rangelistptr classes as FORM_dataN
+ The size of these depend on the header format
+ Must be relative to another symbol on tf_dwarf_relative_addresses
+ targets
+ }
+ append_labelentry_dataptr_common(attr);
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_rel_sym(offsetreltype,sym,endsym));
+ end;
+
+
+ procedure TDebugInfoDwarf.finish_entry;
+ begin
+ dwarf_info_abbref_tai.value:=FinishAbbrevSearch;
+ end;
+
+
+ procedure TDebugInfoDwarf.finish_children;
+ begin
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(0));
+ end;
+
+ procedure TDebugInfoDwarf.appenddef_ord(list:TAsmList;def:torddef);
+ var
+ basedef : tdef;
+ sign : tdwarf_type;
+ signform : tdwarf_form;
+ fullbytesize : byte;
+ begin
+ case def.ordtype of
+ s8bit,
+ s16bit,
+ s32bit,
+ u8bit,
+ u16bit,
+ u32bit :
+ begin
+ { generate proper signed/unsigned info for types like 0..3 }
+ { these are s8bit, but should be identified as unsigned }
+ { because otherwise they are interpreted wrongly when used }
+ { in a bitpacked record }
+ if (def.low<0) then
+ begin
+ sign:=DW_ATE_signed;
+ signform:=DW_FORM_sdata
+ end
+ else
+ begin
+ sign:=DW_ATE_unsigned;
+ signform:=DW_FORM_udata
+ end;
+ fullbytesize:=def.size;
+ case fullbytesize of
+ 1:
+ if (sign=DW_ATE_signed) then
+ basedef:=s8inttype
+ else
+ basedef:=u8inttype;
+ 2:
+ if (sign=DW_ATE_signed) then
+ basedef:=s16inttype
+ else
+ basedef:=u16inttype;
+ 4:
+ if (sign=DW_ATE_signed) then
+ basedef:=s32inttype
+ else
+ basedef:=u32inttype;
+ else
+ internalerror(2008032201);
+ end;
+
+ if (def.low=torddef(basedef).low) and
+ (def.high=torddef(basedef).high) then
+ { base type such as byte/shortint/word/... }
+ if assigned(def.typesym) then
+ append_entry(DW_TAG_base_type,false,[
+ DW_AT_name,DW_FORM_string,symname(def.typesym)+#0,
+ DW_AT_encoding,DW_FORM_data1,sign,
+ DW_AT_byte_size,DW_FORM_data1,fullbytesize])
+ else
+ append_entry(DW_TAG_base_type,false,[
+ DW_AT_encoding,DW_FORM_data1,sign,
+ DW_AT_byte_size,DW_FORM_data1,fullbytesize])
+ else
+ begin
+ { subrange type }
+ { note: don't do this 64 bit int types, they appear }
+ { to be always clipped to s32bit for some reason }
+ if assigned(def.typesym) then
+ append_entry(DW_TAG_subrange_type,false,[
+ DW_AT_name,DW_FORM_string,symname(def.typesym)+#0,
+ DW_AT_lower_bound,signform,int64(def.low),
+ DW_AT_upper_bound,signform,int64(def.high)
+ ])
+ else
+ append_entry(DW_TAG_subrange_type,false,[
+ DW_AT_lower_bound,signform,int64(def.low),
+ DW_AT_upper_bound,signform,int64(def.high)
+ ]);
+ append_labelentry_ref(DW_AT_type,def_dwarf_lab(basedef));
+ end;
+
+ finish_entry;
+ end;
+ uvoid :
+ begin
+ { gdb 6.4 doesn't support DW_TAG_unspecified_type so we
+ replace it with a unsigned type with size 0 (FK)
+ }
+ append_entry(DW_TAG_base_type,false,[
+ DW_AT_name,DW_FORM_string,'Void'#0,
+ DW_AT_encoding,DW_FORM_data1,DW_ATE_unsigned,
+ DW_AT_byte_size,DW_FORM_data1,0
+ ]);
+ finish_entry;
+ end;
+ uchar :
+ begin
+ append_entry(DW_TAG_base_type,false,[
+ DW_AT_name,DW_FORM_string,'Char'#0,
+ DW_AT_encoding,DW_FORM_data1,DW_ATE_unsigned_char,
+ DW_AT_byte_size,DW_FORM_data1,1
+ ]);
+ finish_entry;
+ end;
+ uwidechar :
+ begin
+ append_entry(DW_TAG_base_type,false,[
+ DW_AT_name,DW_FORM_string,'WideChar'#0,
+ DW_AT_encoding,DW_FORM_data1,DW_ATE_unsigned_char,
+ DW_AT_byte_size,DW_FORM_data1,2
+ ]);
+ finish_entry;
+ end;
+ pasbool8 :
+ begin
+ append_entry(DW_TAG_base_type,false,[
+ DW_AT_name,DW_FORM_string,'Boolean'#0,
+ DW_AT_encoding,DW_FORM_data1,DW_ATE_boolean,
+ DW_AT_byte_size,DW_FORM_data1,1
+ ]);
+ finish_entry;
+ end;
+ bool8bit :
+ begin
+ append_entry(DW_TAG_base_type,false,[
+ DW_AT_name,DW_FORM_string,'ByteBool'#0,
+ DW_AT_encoding,DW_FORM_data1,DW_ATE_boolean,
+ DW_AT_byte_size,DW_FORM_data1,1
+ ]);
+ finish_entry;
+ end;
+ pasbool16 :
+ begin
+ append_entry(DW_TAG_base_type,false,[
+ DW_AT_name,DW_FORM_string,'Boolean16'#0,
+ DW_AT_encoding,DW_FORM_data1,DW_ATE_boolean,
+ DW_AT_byte_size,DW_FORM_data1,2
+ ]);
+ finish_entry;
+ end;
+ bool16bit :
+ begin
+ append_entry(DW_TAG_base_type,false,[
+ DW_AT_name,DW_FORM_string,'WordBool'#0,
+ DW_AT_encoding,DW_FORM_data1,DW_ATE_boolean,
+ DW_AT_byte_size,DW_FORM_data1,2
+ ]);
+ finish_entry;
+ end;
+ pasbool32 :
+ begin
+ append_entry(DW_TAG_base_type,false,[
+ DW_AT_name,DW_FORM_string,'Boolean32'#0,
+ DW_AT_encoding,DW_FORM_data1,DW_ATE_boolean,
+ DW_AT_byte_size,DW_FORM_data1,4
+ ]);
+ finish_entry;
+ end;
+ bool32bit :
+ begin
+ append_entry(DW_TAG_base_type,false,[
+ DW_AT_name,DW_FORM_string,'LongBool'#0,
+ DW_AT_encoding,DW_FORM_data1,DW_ATE_boolean,
+ DW_AT_byte_size,DW_FORM_data1,4
+ ]);
+ finish_entry;
+ end;
+ pasbool64 :
+ begin
+ append_entry(DW_TAG_base_type,false,[
+ DW_AT_name,DW_FORM_string,'Boolean64'#0,
+ DW_AT_encoding,DW_FORM_data1,DW_ATE_boolean,
+ DW_AT_byte_size,DW_FORM_data1,8
+ ]);
+ finish_entry;
+ end;
+ bool64bit :
+ begin
+ append_entry(DW_TAG_base_type,false,[
+ DW_AT_name,DW_FORM_string,'QWordBool'#0,
+ DW_AT_encoding,DW_FORM_data1,DW_ATE_boolean,
+ DW_AT_byte_size,DW_FORM_data1,8
+ ]);
+ finish_entry;
+ end;
+ u64bit :
+ begin
+ append_entry(DW_TAG_base_type,false,[
+ DW_AT_name,DW_FORM_string,'QWord'#0,
+ DW_AT_encoding,DW_FORM_data1,DW_ATE_unsigned,
+ DW_AT_byte_size,DW_FORM_data1,8
+ ]);
+ finish_entry;
+ end;
+ scurrency :
+ begin
+ { we should use DW_ATE_signed_fixed, however it isn't supported yet by GDB (FK) }
+ append_entry(DW_TAG_base_type,false,[
+ DW_AT_name,DW_FORM_string,'Currency'#0,
+ DW_AT_encoding,DW_FORM_data1,DW_ATE_signed,
+ DW_AT_byte_size,DW_FORM_data1,8
+ ]);
+ finish_entry;
+ end;
+ s64bit :
+ begin
+ append_entry(DW_TAG_base_type,false,[
+ DW_AT_name,DW_FORM_string,'Int64'#0,
+ DW_AT_encoding,DW_FORM_data1,DW_ATE_signed,
+ DW_AT_byte_size,DW_FORM_data1,8
+ ]);
+ finish_entry;
+ end;
+ else
+ internalerror(200601287);
+ end;
+ end;
+
+ procedure TDebugInfoDwarf.appenddef_float(list:TAsmList;def:tfloatdef);
+ begin
+ case def.floattype of
+ s32real,
+ s64real,
+ s80real,
+ sc80real:
+ if assigned(def.typesym) then
+ begin
+ append_entry(DW_TAG_base_type,false,[
+ DW_AT_name,DW_FORM_string,symname(def.typesym)+#0,
+ DW_AT_encoding,DW_FORM_data1,DW_ATE_float,
+ DW_AT_byte_size,DW_FORM_data1,def.size
+ ]);
+ if (def.floattype in [s80real,sc80real]) and
+ (def.size<>10) then
+ begin
+ append_attribute(DW_AT_bit_size,DW_FORM_data1,[10*8]);
+ { "The bit offset attribute describes the offset in bits
+ of the high order bit of a value of the given type
+ from the high order bit of the storage unit used to
+ contain that value." }
+ if target_info.endian=endian_little then
+ append_attribute(DW_AT_bit_offset,DW_FORM_data1,[(def.size-10)*8]);
+ end;
+ end
+ else
+ append_entry(DW_TAG_base_type,false,[
+ DW_AT_encoding,DW_FORM_data1,DW_ATE_float,
+ DW_AT_byte_size,DW_FORM_data1,def.size
+ ]);
+ s64currency:
+ { we should use DW_ATE_signed_fixed, however it isn't supported yet by GDB (FK) }
+ if assigned(def.typesym) then
+ append_entry(DW_TAG_base_type,false,[
+ DW_AT_name,DW_FORM_string,symname(def.typesym)+#0,
+ DW_AT_encoding,DW_FORM_data1,DW_ATE_signed,
+ DW_AT_byte_size,DW_FORM_data1,8
+ ])
+ else
+ append_entry(DW_TAG_base_type,false,[
+ DW_AT_encoding,DW_FORM_data1,DW_ATE_signed,
+ DW_AT_byte_size,DW_FORM_data1,8
+ ]);
+ s64comp:
+ if assigned(def.typesym) then
+ append_entry(DW_TAG_base_type,false,[
+ DW_AT_name,DW_FORM_string,symname(def.typesym)+#0,
+ DW_AT_encoding,DW_FORM_data1,DW_ATE_signed,
+ DW_AT_byte_size,DW_FORM_data1,8
+ ])
+ else
+ append_entry(DW_TAG_base_type,false,[
+ DW_AT_encoding,DW_FORM_data1,DW_ATE_signed,
+ DW_AT_byte_size,DW_FORM_data1,8
+ ]);
+ else
+ internalerror(200601289);
+ end;
+ finish_entry;
+ end;
+
+
+ procedure TDebugInfoDwarf.appenddef_enum(list:TAsmList;def:tenumdef);
+ var
+ hp : tenumsym;
+ i : integer;
+ begin
+ if assigned(def.typesym) then
+ append_entry(DW_TAG_enumeration_type,true,[
+ DW_AT_name,DW_FORM_string,symname(def.typesym)+#0,
+ DW_AT_byte_size,DW_FORM_data1,def.size
+ ])
+ else
+ append_entry(DW_TAG_enumeration_type,true,[
+ DW_AT_byte_size,DW_FORM_data1,def.size
+ ]);
+ if assigned(def.basedef) then
+ append_labelentry_ref(DW_AT_type,def_dwarf_lab(def.basedef));
+ finish_entry;
+
+ { write enum symbols }
+ for i := 0 to def.symtable.SymList.Count - 1 do
+ begin
+ hp:=tenumsym(def.symtable.SymList[i]);
+ if hp.value<def.minval then
+ continue
+ else
+ if hp.value>def.maxval then
+ break;
+ append_entry(DW_TAG_enumerator,false,[
+ DW_AT_name,DW_FORM_string,symname(hp)+#0,
+ DW_AT_const_value,DW_FORM_data4,hp.value
+ ]);
+ finish_entry;
+ end;
+
+ finish_children;
+ end;
+
+
+ procedure TDebugInfoDwarf.appenddef_array(list:TAsmList;def:tarraydef);
+ var
+ size : aint;
+ elesize : aint;
+ elestrideattr : tdwarf_attribute;
+ labsym: tasmlabel;
+ begin
+ if is_dynamic_array(def) then
+ begin
+ { It's a pointer to the actual array }
+ current_asmdata.getaddrlabel(labsym);
+ append_entry(DW_TAG_pointer_type,false,[]);
+ append_labelentry_ref(DW_AT_type,labsym);
+ finish_entry;
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_symbol.create(labsym,0));
+ end;
+
+ if not is_packed_array(def) then
+ begin
+ elestrideattr := DW_AT_byte_stride;
+ elesize := def.elesize;
+ end
+ else
+ begin
+ elestrideattr := DW_AT_stride_size;
+ elesize := def.elepackedbitsize;
+ end;
+
+ if is_special_array(def) then
+ begin
+ { no known size, no known upper bound }
+ if assigned(def.typesym) then
+ append_entry(DW_TAG_array_type,true,[
+ DW_AT_name,DW_FORM_string,symname(def.typesym)+#0
+ ])
+ else
+ append_entry(DW_TAG_array_type,true,[]);
+ append_labelentry_ref(DW_AT_type,def_dwarf_lab(def.elementdef));
+ finish_entry;
+ { a missing upper bound means "unknown"/default }
+ append_entry(DW_TAG_subrange_type,false,[
+ DW_AT_lower_bound,DW_FORM_sdata,def.lowrange,
+ elestrideattr,DW_FORM_udata,elesize
+ ]);
+ end
+ else
+ begin
+ size:=def.size;
+ if assigned(def.typesym) then
+ append_entry(DW_TAG_array_type,true,[
+ DW_AT_name,DW_FORM_string,symname(def.typesym)+#0,
+ DW_AT_byte_size,DW_FORM_udata,size
+ ])
+ else
+ append_entry(DW_TAG_array_type,true,[
+ DW_AT_byte_size,DW_FORM_udata,size
+ ]);
+ append_labelentry_ref(DW_AT_type,def_dwarf_lab(def.elementdef));
+ finish_entry;
+ { to simplify things, we don't write a multidimensional array here }
+ append_entry(DW_TAG_subrange_type,false,[
+ DW_AT_lower_bound,DW_FORM_sdata,def.lowrange,
+ DW_AT_upper_bound,DW_FORM_sdata,def.highrange,
+ elestrideattr,DW_FORM_udata,elesize
+ ]);
+ end;
+ append_labelentry_ref(DW_AT_type,def_dwarf_lab(def.rangedef));
+ finish_entry;
+ finish_children;
+ end;
+
+
+ procedure TDebugInfoDwarf.appenddef_record(list:TAsmList;def:trecorddef);
+ begin
+ if assigned(def.objname) then
+ appenddef_record_named(list,def,def.objname^)
+ else
+ appenddef_record_named(list,def,'');
+ end;
+
+
+ procedure TDebugInfoDwarf.appenddef_record_named(list:TAsmList;def:trecorddef;const name: shortstring);
+ begin
+ if (name<>'') then
+ append_entry(DW_TAG_structure_type,true,[
+ DW_AT_name,DW_FORM_string,name+#0,
+ DW_AT_byte_size,DW_FORM_udata,def.size
+ ])
+ else
+ append_entry(DW_TAG_structure_type,true,[
+ DW_AT_byte_size,DW_FORM_udata,def.size
+ ]);
+ finish_entry;
+ def.symtable.symList.ForEachCall(@enum_membersyms_callback,nil);
+ { don't know whether external record declaration is allow but if it so then
+ do the same as we do for other object types - skip procdef info generation
+ for external defs (Paul Ishenin) }
+ if not(oo_is_external in def.objectoptions) then
+ write_symtable_procdefs(current_asmdata.asmlists[al_dwarf_info],def.symtable);
+ finish_children;
+ end;
+
+
+ procedure TDebugInfoDwarf.appenddef_pointer(list:TAsmList;def:tpointerdef);
+ begin
+ append_entry(DW_TAG_pointer_type,false,[]);
+ if not(is_voidpointer(def)) then
+ append_labelentry_ref(DW_AT_type,def_dwarf_lab(def.pointeddef));
+ finish_entry;
+ end;
+
+
+ procedure TDebugInfoDwarf.appenddef_string(list:TAsmList;def:tstringdef);
+
+ procedure addnormalstringdef(const name: shortstring; lendef: tdef; maxlen: asizeuint);
+ var
+ { maxlen can be > high(int64) }
+ slen : asizeuint;
+ arr : tasmlabel;
+ begin
+ { fix length of openshortstring }
+ slen:=aword(def.len);
+ if (slen=0) or
+ (slen>maxlen) then
+ slen:=maxlen;
+
+ { create a structure with two elements }
+ if not(tf_dwarf_only_local_labels in target_info.flags) then
+ current_asmdata.getdatalabel(arr)
+ else
+ current_asmdata.getaddrlabel(arr);
+ append_entry(DW_TAG_structure_type,true,[
+ DW_AT_name,DW_FORM_string,name+#0,
+ DW_AT_byte_size,DW_FORM_udata,qword(lendef.size)+slen
+ ]);
+ finish_entry;
+
+ { length entry }
+ append_entry(DW_TAG_member,false,[
+ DW_AT_name,DW_FORM_string,'length'#0,
+ DW_AT_data_member_location,DW_FORM_block1,1+lengthuleb128(0)
+ ]);
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(ord(DW_OP_plus_uconst)));
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_uleb128bit(0));
+ append_labelentry_ref(DW_AT_type,def_dwarf_lab(lendef));
+ finish_entry;
+
+ { string data entry }
+ append_entry(DW_TAG_member,false,[
+ DW_AT_name,DW_FORM_string,'st'#0,
+ DW_AT_data_member_location,DW_FORM_block1,1+lengthuleb128(1)
+ ]);
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(ord(DW_OP_plus_uconst)));
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_uleb128bit(lendef.size));
+ append_labelentry_ref(DW_AT_type,arr);
+ finish_entry;
+
+ finish_children;
+
+ { now the data array }
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_symbol.create(arr,0));
+ append_entry(DW_TAG_array_type,true,[
+ DW_AT_byte_size,DW_FORM_udata,def.size,
+ DW_AT_byte_stride,DW_FORM_udata,1
+ ]);
+ append_labelentry_ref(DW_AT_type,def_dwarf_lab(cchartype));
+ finish_entry;
+ append_entry(DW_TAG_subrange_type,false,[
+ DW_AT_lower_bound,DW_FORM_udata,0,
+ DW_AT_upper_bound,DW_FORM_udata,qword(slen)
+ ]);
+ append_labelentry_ref(DW_AT_type,def_dwarf_lab(lendef));
+ finish_entry;
+ finish_children;
+ end;
+
+ begin
+ case def.stringtype of
+ st_shortstring:
+ begin
+ addnormalstringdef('ShortString',u8inttype,255);
+ end;
+ st_longstring:
+ begin
+ { a) we don't actually support variables of this type currently
+ b) this type is only used as the type for constant strings
+ > 255 characters
+ c) in such a case, gdb will allocate and initialise enough
+ memory to hold the maximum size for such a string
+ -> don't use high(qword)/high(cardinal) as maximum, since that
+ will cause exhausting the VM space, but some "reasonably high"
+ number that should be enough for most constant strings
+ }
+{$ifdef cpu64bitaddr}
+ addnormalstringdef('LongString',u64inttype,qword(1024*1024));
+{$endif cpu64bitaddr}
+{$ifdef cpu32bitaddr}
+ addnormalstringdef('LongString',u32inttype,cardinal(1024*1024));
+{$endif cpu32bitaddr}
+{$ifdef cpu16bitaddr}
+ addnormalstringdef('LongString',u16inttype,cardinal(1024));
+{$endif cpu16bitaddr}
+ end;
+ st_ansistring:
+ begin
+ { looks like a pchar }
+ append_entry(DW_TAG_pointer_type,false,[]);
+ append_labelentry_ref(DW_AT_type,def_dwarf_lab(cchartype));
+ finish_entry;
+ end;
+ st_unicodestring,
+ st_widestring:
+ begin
+ { looks like a pwidechar }
+ append_entry(DW_TAG_pointer_type,false,[]);
+ append_labelentry_ref(DW_AT_type,def_dwarf_lab(cwidechartype));
+ finish_entry;
+ end;
+ end;
+ end;
+
+ procedure TDebugInfoDwarf.appenddef_procvar(list:TAsmList;def:tprocvardef);
+
+ procedure doappend;
+ var
+ i : longint;
+ begin
+ if assigned(def.typesym) then
+ append_entry(DW_TAG_subroutine_type,true,[
+ DW_AT_name,DW_FORM_string,symname(def.typesym)+#0,
+ DW_AT_prototyped,DW_FORM_flag,true
+ ])
+ else
+ append_entry(DW_TAG_subroutine_type,true,[
+ DW_AT_prototyped,DW_FORM_flag,true
+ ]);
+ if not(is_void(tprocvardef(def).returndef)) then
+ append_labelentry_ref(DW_AT_type,def_dwarf_lab(tprocvardef(def).returndef));
+ finish_entry;
+
+ { write parameters }
+ for i:=0 to def.paras.count-1 do
+ begin
+ append_entry(DW_TAG_formal_parameter,false,[
+ DW_AT_name,DW_FORM_string,symname(tsym(def.paras[i]))+#0
+ ]);
+ append_labelentry_ref(DW_AT_type,def_dwarf_lab(tparavarsym(def.paras[i]).vardef));
+ finish_entry;
+ end;
+
+ finish_children;
+ end;
+
+ var
+ proc : tasmlabel;
+
+ begin
+ if not def.is_addressonly then
+ begin
+ { create a structure with two elements }
+ if not(tf_dwarf_only_local_labels in target_info.flags) then
+ current_asmdata.getdatalabel(proc)
+ else
+ current_asmdata.getaddrlabel(proc);
+ append_entry(DW_TAG_structure_type,true,[
+ DW_AT_byte_size,DW_FORM_data1,2*sizeof(pint)
+ ]);
+ finish_entry;
+
+ { proc entry }
+ append_entry(DW_TAG_member,false,[
+ DW_AT_name,DW_FORM_string,'Proc'#0,
+ DW_AT_data_member_location,DW_FORM_block1,1+lengthuleb128(0)
+ ]);
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(ord(DW_OP_plus_uconst)));
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_uleb128bit(0));
+ append_labelentry_ref(DW_AT_type,proc);
+ finish_entry;
+
+ { self entry }
+ append_entry(DW_TAG_member,false,[
+ DW_AT_name,DW_FORM_string,'Self'#0,
+ DW_AT_data_member_location,DW_FORM_block1,1+lengthuleb128(sizeof(pint))
+ ]);
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(ord(DW_OP_plus_uconst)));
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_uleb128bit(sizeof(pint)));
+ append_labelentry_ref(DW_AT_type,def_dwarf_lab(class_tobject));
+ finish_entry;
+
+ finish_children;
+
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_symbol.create(proc,0));
+ doappend;
+ end
+ else
+ doappend;
+ end;
+
+
+ procedure TDebugInfoDwarf.beforeappenddef(list:TAsmList;def:tdef);
+ var
+ labsym : tasmsymbol;
+ begin
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_comment.Create(strpnew('Definition '+def.typename)));
+
+ labsym:=def_dwarf_lab(def);
+ if ds_dwarf_dbg_info_written in def.defstates then
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_symbol.create_global(labsym,0))
+ else
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_symbol.create(labsym,0));
+
+ { On Darwin, dwarf info is not linked in the final binary,
+ but kept in the individual object files. This allows for
+ faster linking, but means that you have to keep the object
+ files for debugging and also that gdb only loads in the
+ debug info of a particular object file once you step into
+ or over a procedure in it.
+
+ To solve this, there is a tool called dsymutil which can
+ extract all the dwarf info from a program's object files.
+ This utility however performs "smart linking" on the dwarf
+ info and throws away all unreferenced dwarf entries. Since
+ variables' types always point to the dwarfinfo for a tdef
+ and never to that for a typesym, this means all debug
+ entries generated for typesyms are thrown away.
+
+ The problem with that is that we translate typesyms into
+ DW_TAG_typedef, and gdb's dwarf-2 reader only makes types
+ globally visibly if they are defined using a DW_TAG_typedef.
+ So as a result, before running dsymutil types only become
+ available once you stepped into/over a function in the object
+ file where they are declared, and after running dsymutil they
+ are all gone (printing variables still works because the
+ tdef dwarf info is still available, but you cannot typecast
+ anything outside the declaring units because the type names
+ are not known there).
+
+ The solution: if a tdef has an associated typesym, let the
+ debug label for the tdef point to a DW_TAG_typedef instead
+ of directly to the tdef itself. And don't write anything
+ special for the typesym itself.
+
+ Update: we now also do this for other platforms, because
+ otherwise if you compile unit A without debug info and
+ use one of its types in unit B, then no typedef will be
+ generated and hence gdb will not be able to give a definition
+ of the type.
+ }
+
+ if is_objc_class_or_protocol(def) then
+ begin
+ { for Objective-C classes, the typedef must refer to the
+ struct itself, not to the pointer of the struct; Objective-C
+ classes are not implicit pointers in Objective-C itself, only
+ in FPC. So make the def label point to a pointer to the
+ typedef, which in turn refers to the actual struct (for Delphi-
+ style classes, the def points to the typedef, which refers to
+ a pointer to the actual struct) }
+
+ { implicit pointer }
+ current_asmdata.getaddrlabel(TAsmLabel(pointer(labsym)));
+ append_entry(DW_TAG_pointer_type,false,[]);
+ append_labelentry_ref(DW_AT_type,labsym);
+ finish_entry;
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_symbol.create(labsym,0));
+ end;
+
+ if assigned(def.typesym) and
+ not(df_generic in def.defoptions) then
+ begin
+ current_asmdata.getaddrlabel(TAsmLabel(pointer(labsym)));
+ append_entry(DW_TAG_typedef,false,[
+ DW_AT_name,DW_FORM_string,symname(def.typesym)+#0
+ ]);
+ append_labelentry_ref(DW_AT_type,labsym);
+ finish_entry;
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_symbol.create(labsym,0));
+ end
+ end;
+
+
+ procedure TDebugInfoDwarf.afterappenddef(list:TAsmList;def:tdef);
+ var
+ labsym : tasmsymbol;
+ begin
+ { create a derived reference type for pass-by-reference parameters }
+ { (gdb doesn't support DW_AT_variable_parameter yet) }
+ labsym:=def_dwarf_ref_lab(def);
+ if ds_dwarf_dbg_info_written in def.defstates then
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_symbol.create_global(labsym,0))
+ else
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_symbol.create(labsym,0));
+ append_entry(DW_TAG_reference_type,false,[]);
+ append_labelentry_ref(DW_AT_type,def_dwarf_lab(def));
+ finish_entry;
+ end;
+
+
+ procedure TDebugInfoDwarf.appendprocdef(list:TAsmList; def:tprocdef);
+
+ function dwarf_calling_convention(def: tprocdef): Tdwarf_calling_convention;
+ begin
+ case def.proccalloption of
+ pocall_register:
+ result:=DW_CC_GNU_borland_fastcall_i386;
+ pocall_cdecl,
+ pocall_stdcall,
+ pocall_cppdecl,
+ pocall_mwpascal:
+ result:=DW_CC_normal;
+ else
+ result:=DW_CC_nocall;
+ end
+ end;
+
+ var
+ procendlabel : tasmlabel;
+ procentry : string;
+ cc : Tdwarf_calling_convention;
+ st : tsymtable;
+ vmtoffset : pint;
+ in_currentunit : boolean;
+ begin
+ { only write debug info for procedures defined in the current module,
+ except in case of methods (gcc-compatible)
+ }
+ in_currentunit:=def.in_currentunit;
+
+ if not in_currentunit and
+ not (def.owner.symtabletype in [objectsymtable,recordsymtable]) then
+ exit;
+
+ { happens for init procdef of units without init section }
+ if in_currentunit and
+ not assigned(def.procstarttai) then
+ exit;
+
+ { Procdefs are not handled by the regular def writing code, so
+ dbg_state is not set/checked for them. Do it here. }
+ if (def.dbg_state in [dbg_state_writing,dbg_state_written]) then
+ exit;
+ defnumberlist.Add(def);
+
+ { Write methods and only in the scope of their parent objectdefs. }
+ if (def.owner.symtabletype in [objectsymtable,recordsymtable]) then
+ begin
+ { this code can also work for nested procdefs, but is not yet
+ activated for those because there is no clear advantage yet to
+ limiting the scope of nested procedures to that of their parent,
+ and it makes it impossible to set breakpoints in them by
+ referring to their name. }
+ st:=def.owner;
+ while assigned(st.defowner) and
+ (tdef(st.defowner).typ = procdef) do
+ st:=tprocdef(st.defowner).owner;
+ if assigned(st) and
+ (tdef(st.defowner).dbg_state<>dbg_state_writing) then
+ exit;
+ end;
+
+ def.dbg_state:=dbg_state_writing;
+
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_comment.Create(strpnew('Procdef '+def.fullprocname(true))));
+ if not is_objc_class_or_protocol(def.struct) then
+ append_entry(DW_TAG_subprogram,true,
+ [DW_AT_name,DW_FORM_string,symname(def.procsym)+#0
+ { data continues below }
+ { problem: base reg isn't known here
+ DW_AT_frame_base,DW_FORM_block1,1
+ }
+ ])
+ else
+ append_entry(DW_TAG_subprogram,true,
+ [DW_AT_name,DW_FORM_string,def.mangledname+#0
+ { data continues below }
+ { problem: base reg isn't known here
+ DW_AT_frame_base,DW_FORM_block1,1
+ }
+ ]);
+
+ { Append optional flags. }
+
+ { All Pascal procedures are prototyped }
+ append_attribute(DW_AT_prototyped,DW_FORM_flag,[true]);
+ { Calling convention. }
+ cc:=dwarf_calling_convention(def);
+ if (cc<>DW_CC_normal) then
+ append_attribute(DW_AT_calling_convention,DW_FORM_data1,[ord(cc)]);
+ { Externally visible. }
+ if (po_global in def.procoptions) and
+ (def.parast.symtablelevel<=normal_function_level) then
+ append_attribute(DW_AT_external,DW_FORM_flag,[true]);
+ { Abstract or virtual/overriding method. }
+ if (([po_abstractmethod, po_virtualmethod, po_overridingmethod] * def.procoptions) <> []) and
+ not is_objc_class_or_protocol(def.struct) and
+ not is_objectpascal_helper(def.struct) then
+ begin
+ if not(po_abstractmethod in def.procoptions) then
+ append_attribute(DW_AT_virtuality,DW_FORM_data1,[ord(DW_VIRTUALITY_virtual)])
+ else
+ append_attribute(DW_AT_virtuality,DW_FORM_data1,[ord(DW_VIRTUALITY_pure_virtual)]);
+ { Element number in the vmt (needs to skip stuff coming before the
+ actual method addresses in the vmt, so we use vmtmethodoffset()
+ and then divide by sizeof(pint)). }
+ vmtoffset:=tobjectdef(def.owner.defowner).vmtmethodoffset(def.extnumber);
+ append_attribute(DW_AT_vtable_elem_location,DW_FORM_block1,[3+LengthUleb128(vmtoffset)]);
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(ord(DW_OP_deref)));
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(ord(DW_OP_constu)));
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.Create_uleb128bit(vmtoffset));
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(ord(DW_OP_plus)));
+ end;
+
+ { accessibility: public/private/protected }
+ if (def.owner.symtabletype in [objectsymtable,recordsymtable]) then
+ append_visibility(def.visibility);
+
+ { Return type. }
+ if not(is_void(tprocdef(def).returndef)) then
+ append_labelentry_ref(DW_AT_type,def_dwarf_lab(tprocdef(def).returndef));
+
+ { we can only write the start/end if this procedure is implemented in
+ this module
+ }
+ if in_currentunit then
+ begin
+ { mark end of procedure }
+ current_asmdata.getlabel(procendlabel,alt_dbgtype);
+ current_asmdata.asmlists[al_procedures].insertbefore(tai_label.create(procendlabel),def.procendtai);
+
+ if (target_info.system = system_powerpc64_linux) then
+ procentry := '.' + def.mangledname
+ else
+ procentry := def.mangledname;
+
+ append_labelentry(DW_AT_low_pc,current_asmdata.RefAsmSymbol(procentry));
+ append_labelentry(DW_AT_high_pc,procendlabel);
+ end;
+
+ { Don't write the funcretsym explicitly, it's also in the
+ localsymtable and/or parasymtable.
+ }
+ finish_entry;
+
+ if assigned(def.parast) then
+ begin
+ { First insert self, because gdb uses the fact whether or not the
+ first parameter of a method is artificial to distinguish static
+ from regular methods. }
+
+ { fortunately, self is the always the first parameter in the
+ paralist, since it has the lowest paranr. Note that this is not
+ true for Objective-C, but those methods are detected in
+ another way (by reading the ObjC run time information) }
+ write_symtable_parasyms(current_asmdata.asmlists[al_dwarf_info],def.paras);
+ end;
+ { local type defs and vars should not be written
+ inside the main proc }
+ if in_currentunit and
+ assigned(def.localst) and
+ (def.localst.symtabletype=localsymtable) then
+ write_symtable_syms(current_asmdata.asmlists[al_dwarf_info],def.localst);
+
+ { last write the types from this procdef }
+ if assigned(def.parast) then
+ write_symtable_defs(current_asmdata.asmlists[al_dwarf_info],def.parast);
+ { only try to write the localst if the routine is implemented here }
+ if in_currentunit and
+ assigned(def.localst) and
+ (def.localst.symtabletype=localsymtable) then
+ begin
+ write_symtable_defs(current_asmdata.asmlists[al_dwarf_info],def.localst);
+ { Write nested procedures -- disabled, see scope check at the
+ beginning; currently, these are still written in the global
+ scope. }
+ // write_symtable_procdefs(current_asmdata.asmlists[al_dwarf_info],def.localst);
+ end;
+
+ finish_children;
+ end;
+
+
+ function TDebugInfoDwarf.get_symlist_sym_offset(symlist: ppropaccesslistitem; out sym: tabstractvarsym; out offset: pint): boolean;
+ var
+ elesize : pint;
+ currdef : tdef;
+ indirection: boolean;
+ begin
+ result:=false;
+ if not assigned(symlist) then
+ exit;
+ sym:=nil;
+ offset:=0;
+ currdef:=nil;
+ indirection:=false;
+ repeat
+ case symlist^.sltype of
+ sl_load:
+ begin
+ if assigned(sym) then
+ internalerror(2009031203);
+ if not(symlist^.sym.typ in [paravarsym,localvarsym,staticvarsym,fieldvarsym]) then
+ { can't handle... }
+ exit;
+ sym:=tabstractvarsym(symlist^.sym);
+ currdef:=tabstractvarsym(sym).vardef;
+ if ((sym.typ=paravarsym) and
+ paramanager.push_addr_param(tparavarsym(sym).varspez,sym.vardef,tprocdef(sym.owner.defowner).proccalloption)) then
+ indirection:=true;
+ end;
+ sl_subscript:
+ begin
+ if not assigned(currdef) then
+ internalerror(2009031301);
+ if (symlist^.sym.typ<>fieldvarsym) then
+ internalerror(2009031202);
+ { can't handle offsets with indirections yet }
+ if indirection then
+ exit;
+ if is_packed_record_or_object(currdef) then
+ begin
+ { can't calculate the address of a non-byte aligned field }
+ if (tfieldvarsym(symlist^.sym).fieldoffset mod 8) <> 0 then
+ exit;
+ inc(offset,tfieldvarsym(symlist^.sym).fieldoffset div 8)
+ end
+ else
+ inc(offset,tfieldvarsym(symlist^.sym).fieldoffset);
+ currdef:=tfieldvarsym(symlist^.sym).vardef;
+ end;
+ sl_absolutetype,
+ sl_typeconv:
+ begin
+ currdef:=tfieldvarsym(symlist^.sym).vardef;
+ { ignore, these don't change the address }
+ end;
+ sl_vec:
+ begin
+ if not assigned(currdef) or
+ (currdef.typ<>arraydef) then
+ internalerror(2009031201);
+ { can't handle offsets with indirections yet }
+ if indirection then
+ exit;
+ if not is_packed_array(currdef) then
+ elesize:=tarraydef(currdef).elesize
+ else
+ begin
+ elesize:=tarraydef(currdef).elepackedbitsize;
+ { can't calculate the address of a non-byte aligned element }
+ if (elesize mod 8)<>0 then
+ exit;
+ elesize:=elesize div 8;
+ end;
+ inc(offset,(symlist^.value.svalue-tarraydef(currdef).lowrange)*elesize);
+ currdef:=tarraydef(currdef).elementdef;
+ end;
+ else
+ internalerror(2009031401);
+ end;
+ symlist:=symlist^.next;
+ until not assigned(symlist);
+ if not assigned(sym) then
+ internalerror(2009031205);
+ result:=true;
+ end;
+
+
+ procedure TDebugInfoDwarf.appendsym_var(list:TAsmList;sym:tabstractnormalvarsym);
+ begin
+ appendsym_var_with_name_type_offset(list,sym,symname(sym),sym.vardef,0,[]);
+ end;
+
+
+ procedure TDebugInfoDwarf.appendsym_var_with_name_type_offset(list:TAsmList; sym:tabstractnormalvarsym; const name: string; def: tdef; offset: pint; const flags: tdwarfvarsymflags);
+ var
+ templist : TAsmList;
+ blocksize : longint;
+ tag : tdwarf_tag;
+ dreg : byte;
+ begin
+ { external symbols can't be resolved at link time, so we
+ can't generate stabs for them
+
+ not sure if this applies to dwarf as well (FK)
+ }
+ if vo_is_external in sym.varoptions then
+ exit;
+
+ { There is no space allocated for not referenced locals }
+ if (sym.owner.symtabletype=localsymtable) and (sym.refs=0) then
+ exit;
+
+ templist:=TAsmList.create;
+
+ case sym.localloc.loc of
+ LOC_REGISTER,
+ LOC_CREGISTER,
+ LOC_MMREGISTER,
+ LOC_CMMREGISTER,
+ LOC_FPUREGISTER,
+ LOC_CFPUREGISTER :
+ begin
+ templist.concat(tai_const.create_8bit(ord(DW_OP_regx)));
+ dreg:=dwarf_reg(sym.localloc.register);
+ templist.concat(tai_const.create_uleb128bit(dreg));
+ blocksize:=1+Lengthuleb128(dreg);
+ end;
+ else
+ begin
+ case sym.typ of
+ staticvarsym:
+ begin
+ if (vo_is_thread_var in sym.varoptions) then
+ begin
+{ TODO: !!! FIXME: dwarf for thread vars !!!}
+ blocksize:=0;
+ end
+ else
+ begin
+ templist.concat(tai_const.create_8bit(ord(DW_OP_addr)));
+ templist.concat(tai_const.createname(sym.mangledname,offset));
+ blocksize:=1+sizeof(puint);
+ end;
+ end;
+ paravarsym,
+ localvarsym:
+ begin
+ { Happens when writing debug info for paras of procdefs not
+ implemented in the current module. Can't add a general check
+ for LOC_INVALID above, because staticvarsyms may also have it.
+ }
+ if sym.localloc.loc<> LOC_INVALID then
+ begin
+ dreg:=dwarf_reg(sym.localloc.reference.base);
+ templist.concat(tai_const.create_8bit(ord(DW_OP_breg0)+dreg));
+ templist.concat(tai_const.create_sleb128bit(sym.localloc.reference.offset+offset));
+ blocksize:=1+Lengthsleb128(sym.localloc.reference.offset);
+{$ifndef gdb_supports_DW_AT_variable_parameter}
+ { Parameters which are passed by reference. (var and the like)
+ Hide the reference-pointer and dereference the pointer
+ in the DW_AT_location block.
+ }
+ if (sym.typ=paravarsym) and
+ paramanager.push_addr_param(sym.varspez,sym.vardef,tprocdef(sym.owner.defowner).proccalloption) and
+ not(vo_has_local_copy in sym.varoptions) and
+ not is_open_string(sym.vardef) then
+ begin
+ templist.concat(tai_const.create_8bit(ord(DW_OP_deref)));
+ inc(blocksize);
+ end
+{$endif not gdb_supports_DW_AT_variable_parameter}
+ end;
+ end
+ else
+ internalerror(200601288);
+ end;
+ end;
+ end;
+
+ { function results must not be added to the parameter list,
+ as they are not part of the signature of the function
+ (gdb automatically adds them according to the ABI specifications
+ when calling the function)
+ }
+ if (sym.typ=paravarsym) and
+ not(dvf_force_local_var in flags) and
+ not(vo_is_funcret in sym.varoptions) then
+ tag:=DW_TAG_formal_parameter
+ else
+ tag:=DW_TAG_variable;
+
+ { must be parasym of externally implemented procdef, but
+ the parasymtable can con also contain e.g. absolutevarsyms
+ -> check symtabletype}
+ if (sym.owner.symtabletype=parasymtable) and
+ (sym.localloc.loc=LOC_INVALID) then
+ begin
+ if (sym.owner.symtabletype<>parasymtable) then
+ internalerror(2009101001);
+ append_entry(tag,false,[
+ DW_AT_name,DW_FORM_string,name+#0
+ {
+ DW_AT_decl_file,DW_FORM_data1,0,
+ DW_AT_decl_line,DW_FORM_data1,
+ }
+ ])
+ end
+ else if not(sym.localloc.loc in [LOC_REGISTER,LOC_CREGISTER,LOC_MMREGISTER,
+ LOC_CMMREGISTER,LOC_FPUREGISTER,LOC_CFPUREGISTER]) and
+ ((sym.owner.symtabletype = globalsymtable) or
+ (sp_static in sym.symoptions) or
+ (vo_is_public in sym.varoptions)) then
+ append_entry(tag,false,[
+ DW_AT_name,DW_FORM_string,name+#0,
+ {
+ DW_AT_decl_file,DW_FORM_data1,0,
+ DW_AT_decl_line,DW_FORM_data1,
+ }
+ DW_AT_external,DW_FORM_flag,true,
+ { data continues below }
+ DW_AT_location,DW_FORM_block1,blocksize
+ ])
+{$ifdef gdb_supports_DW_AT_variable_parameter}
+ else if (sym.typ=paravarsym) and
+ paramanager.push_addr_param(sym.varspez,sym.vardef,tprocdef(sym.owner.defowner).proccalloption) and
+ not(vo_has_local_copy in sym.varoptions) and
+ not is_open_string(sym.vardef) then
+ append_entry(tag,false,[
+ DW_AT_name,DW_FORM_string,name+#0,
+ DW_AT_variable_parameter,DW_FORM_flag,true,
+ {
+ DW_AT_decl_file,DW_FORM_data1,0,
+ DW_AT_decl_line,DW_FORM_data1,
+ }
+ { data continues below }
+ DW_AT_location,DW_FORM_block1,blocksize
+ ])
+{$endif gdb_supports_DW_AT_variable_parameter}
+ else
+ append_entry(tag,false,[
+ DW_AT_name,DW_FORM_string,name+#0,
+ {
+ DW_AT_decl_file,DW_FORM_data1,0,
+ DW_AT_decl_line,DW_FORM_data1,
+ }
+ { data continues below }
+ DW_AT_location,DW_FORM_block1,blocksize
+ ]);
+ { append block data }
+ current_asmdata.asmlists[al_dwarf_info].concatlist(templist);
+ { Mark self as artificial for methods, because gdb uses the fact
+ whether or not the first parameter of a method is artificial to
+ distinguish regular from static methods (since there are no
+ no vo_is_self parameters for static methods, we don't have to check
+ that). }
+ if (vo_is_self in sym.varoptions) then
+ append_attribute(DW_AT_artificial,DW_FORM_flag,[true]);
+ append_labelentry_ref(DW_AT_type,def_dwarf_lab(def));
+
+ templist.free;
+
+ finish_entry;
+ end;
+
+
+ procedure TDebugInfoDwarf.appendsym_staticvar(list:TAsmList;sym:tstaticvarsym);
+ begin
+ appendsym_var(list,sym);
+ end;
+
+
+ procedure TDebugInfoDwarf.appendsym_localvar(list:TAsmList;sym:tlocalvarsym);
+ begin
+ appendsym_var(list,sym);
+ end;
+
+
+ procedure TDebugInfoDwarf.appendsym_paravar(list:TAsmList;sym:tparavarsym);
+ begin
+ appendsym_var(list,sym);
+ end;
+
+
+ procedure TDebugInfoDwarf.appendsym_fieldvar(list:TAsmList;sym: tfieldvarsym);
+ begin
+ appendsym_fieldvar_with_name_offset(list,sym,symname(sym),sym.vardef,0);
+ end;
+
+
+ procedure TDebugInfoDwarf.appendsym_fieldvar_with_name_offset(list:TAsmList;sym: tfieldvarsym;const name: string; def: tdef; offset: pint);
+ var
+ bitoffset,
+ fieldoffset,
+ fieldnatsize: asizeint;
+ begin
+ if (sp_static in sym.symoptions) or
+ (sym.visibility=vis_hidden) then
+ exit;
+
+ if (tabstractrecordsymtable(sym.owner).usefieldalignment<>bit_alignment) or
+ { only ordinals are bitpacked }
+ not is_ordinal(sym.vardef) then
+ begin
+ { other kinds of fields can however also appear in a bitpacked }
+ { record, and then their offset is also specified in bits rather }
+ { than in bytes }
+ if (tabstractrecordsymtable(sym.owner).usefieldalignment<>bit_alignment) then
+ fieldoffset:=sym.fieldoffset
+ else
+ fieldoffset:=sym.fieldoffset div 8;
+ inc(fieldoffset,offset);
+ append_entry(DW_TAG_member,false,[
+ DW_AT_name,DW_FORM_string,name+#0,
+ DW_AT_data_member_location,DW_FORM_block1,1+lengthuleb128(fieldoffset)
+ ]);
+ end
+ else
+ begin
+ if (sym.vardef.packedbitsize > 255) then
+ internalerror(2007061201);
+
+ { we don't bitpack according to the ABI, but as close as }
+ { possible, i.e., equivalent to gcc's }
+ { __attribute__((__packed__)), which is also what gpc }
+ { does. }
+ fieldnatsize:=max(sizeof(pint),sym.vardef.size);
+ fieldoffset:=(sym.fieldoffset div (fieldnatsize*8)) * fieldnatsize;
+ inc(fieldoffset,offset);
+ bitoffset:=sym.fieldoffset mod (fieldnatsize*8);
+ if (target_info.endian=endian_little) then
+ bitoffset:=(fieldnatsize*8)-bitoffset-sym.vardef.packedbitsize;
+ append_entry(DW_TAG_member,false,[
+ DW_AT_name,DW_FORM_string,symname(sym)+#0,
+ { gcc also generates both a bit and byte size attribute }
+ { we don't support ordinals >= 256 bits }
+ DW_AT_byte_size,DW_FORM_data1,fieldnatsize,
+ { nor >= 256 bits (not yet, anyway, see IE above) }
+ DW_AT_bit_size,DW_FORM_data1,sym.vardef.packedbitsize,
+ { data1 and data2 are unsigned, bitoffset can also be negative }
+ DW_AT_bit_offset,DW_FORM_data4,bitoffset,
+ DW_AT_data_member_location,DW_FORM_block1,1+lengthuleb128(fieldoffset)
+ ]);
+ end;
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(ord(DW_OP_plus_uconst)));
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_uleb128bit(fieldoffset));
+ if (sym.owner.symtabletype in [objectsymtable,recordsymtable]) then
+ append_visibility(sym.visibility);
+
+ append_labelentry_ref(DW_AT_type,def_dwarf_lab(def));
+ finish_entry;
+ end;
+
+ procedure TDebugInfoDwarf.appendsym_const(list:TAsmList;sym:tconstsym);
+ begin
+ appendsym_const_member(list,sym,false);
+ end;
+
+ procedure TDebugInfoDwarf.appendsym_const_member(list:TAsmList;sym:tconstsym;ismember:boolean);
+ var
+ i,
+ size: aint;
+ usedef: tdef;
+ begin
+ { These are default values of parameters. These should be encoded
+ via DW_AT_default_value, not as a separate sym. Moreover, their
+ type is not available when writing the debug info for external
+ procedures.
+ }
+ if (sym.owner.symtabletype=parasymtable) then
+ exit;
+
+ if ismember then
+ append_entry(DW_TAG_member,false,[
+ DW_AT_name,DW_FORM_string,symname(sym)+#0,
+ { The DW_AT_declaration tag is invalid according to the DWARF specifications.
+ But gcc adds this to static const members and gdb checks
+ for this flag. So we have to set it also.
+ }
+ DW_AT_declaration,DW_FORM_flag,true,
+ DW_AT_external,DW_FORM_flag,true
+ ])
+ else
+ append_entry(DW_TAG_variable,false,[
+ DW_AT_name,DW_FORM_string,symname(sym)+#0
+ ]);
+ { for string constants, constdef isn't set because they have no real type }
+ case sym.consttyp of
+ conststring:
+ begin
+ { if DW_FORM_string is used below one day, this usedef should
+ probably become nil }
+ { note: < 255 instead of <= 255 because we have to store the
+ entire length of the string as well, and 256 does not fit in
+ a byte }
+ if (sym.value.len<255) then
+ usedef:=cshortstringtype
+ else
+ usedef:=clongstringtype;
+ end;
+ constresourcestring,
+ constwstring:
+ usedef:=nil;
+ else
+ usedef:=sym.constdef;
+ end;
+ if assigned(usedef) then
+ append_labelentry_ref(DW_AT_type,def_dwarf_lab(usedef));
+ AddConstToAbbrev(ord(DW_AT_const_value));
+ case sym.consttyp of
+ conststring:
+ begin
+ { DW_FORM_string isn't supported yet by the Pascal value printer
+ -> create a string using raw bytes }
+ if (sym.value.len<255) then
+ begin
+ AddConstToAbbrev(ord(DW_FORM_block1));
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(sym.value.len+1));
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(sym.value.len));
+ end
+ else
+ begin
+ AddConstToAbbrev(ord(DW_FORM_block));
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_uleb128bit(sym.value.len+sizeof(pint)));
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_pint(sym.value.len));
+ end;
+ i:=0;
+ size:=sym.value.len;
+ while(i<size) do
+ begin
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit((pbyte(sym.value.valueptr+i)^)));
+ inc(i);
+ end;
+ end;
+ constguid,
+ constset:
+ begin
+ AddConstToAbbrev(ord(DW_FORM_block1));
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(usedef.size));
+ i:=0;
+ size:=sym.constdef.size;
+ while (i<size) do
+ begin
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit((pbyte(sym.value.valueptr+i)^)));
+ inc(i);
+ end;
+ end;
+ constwstring,
+ constresourcestring:
+ begin
+ { write dummy for now }
+ AddConstToAbbrev(ord(DW_FORM_string));
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_string.create(''));
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(0));
+ end;
+ constord:
+ begin
+ if (sym.value.valueord<0) then
+ begin
+ AddConstToAbbrev(ord(DW_FORM_sdata));
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_sleb128bit(sym.value.valueord.svalue));
+ end
+ else
+ begin
+ AddConstToAbbrev(ord(DW_FORM_udata));
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_uleb128bit(sym.value.valueord.uvalue));
+ end;
+ end;
+ constnil:
+ begin
+{$ifdef cpu64bitaddr}
+ AddConstToAbbrev(ord(DW_FORM_data8));
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_64bit(0));
+{$else cpu64bitaddr}
+ AddConstToAbbrev(ord(DW_FORM_data4));
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_32bit(0));
+{$endif cpu64bitaddr}
+ end;
+ constpointer:
+ begin
+{$ifdef cpu64bitaddr}
+ AddConstToAbbrev(ord(DW_FORM_data8));
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_64bit(int64(sym.value.valueordptr)));
+{$else cpu64bitaddr}
+ AddConstToAbbrev(ord(DW_FORM_data4));
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_32bit(longint(sym.value.valueordptr)));
+{$endif cpu64bitaddr}
+ end;
+ constreal:
+ begin
+ AddConstToAbbrev(ord(DW_FORM_block1));
+ case tfloatdef(sym.constdef).floattype of
+ s32real:
+ begin
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(4));
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_real_32bit.create(pbestreal(sym.value.valueptr)^));
+ end;
+ s64real:
+ begin
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(8));
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_real_64bit.create(pbestreal(sym.value.valueptr)^));
+ end;
+ s64comp,
+ s64currency:
+ begin
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(8));
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_64bit(trunc(pbestreal(sym.value.valueptr)^)));
+ end;
+ s80real,
+ sc80real:
+ begin
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(sym.constdef.size));
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_real_80bit.create(pextended(sym.value.valueptr)^,sym.constdef.size));
+ end;
+ else
+ internalerror(200601291);
+ end;
+ end;
+ else
+ internalerror(200601292);
+ end;
+ finish_entry;
+ end;
+
+
+ procedure TDebugInfoDwarf.appendsym_label(list:TAsmList;sym: tlabelsym);
+ begin
+ { ignore label syms for now, the problem is that a label sym
+ can have more than one label associated e.g. in case of
+ an inline procedure expansion }
+ end;
+
+
+ procedure TDebugInfoDwarf.appendsym_property(list:TAsmList;sym: tpropertysym);
+ var
+ symlist: ppropaccesslistitem;
+ tosym: tabstractvarsym;
+ offset: pint;
+ begin
+ if assigned(sym.propaccesslist[palt_read]) and
+ not assigned(sym.propaccesslist[palt_read].procdef) then
+ symlist:=sym.propaccesslist[palt_read].firstsym
+ else
+ { can't handle }
+ exit;
+
+ if not get_symlist_sym_offset(symlist,tosym,offset) then
+ exit;
+
+ if not (tosym.owner.symtabletype in [objectsymtable,recordsymtable]) then
+ begin
+ if (tosym.typ=fieldvarsym) then
+ internalerror(2009031404);
+ appendsym_var_with_name_type_offset(list,tabstractnormalvarsym(tosym),symname(sym),sym.propdef,offset,[])
+ end
+ else
+ appendsym_fieldvar_with_name_offset(list,tfieldvarsym(tosym),symname(sym),sym.propdef,offset)
+ end;
+
+
+ function TDebugInfoDwarf.symdebugname(sym: tsym): String;
+ begin
+ result := sym.name;
+ end;
+
+
+ procedure TDebugInfoDwarf.appendsym_type(list:TAsmList;sym: ttypesym);
+ begin
+ { just queue the def if needed, beforeappenddef will
+ emit the typedef if necessary }
+ def_dwarf_lab(sym.typedef);
+ end;
+
+
+ procedure TDebugInfoDwarf.appendsym_absolute(list:TAsmList;sym:tabsolutevarsym);
+ var
+ templist : TAsmList;
+ blocksize : longint;
+ symlist : ppropaccesslistitem;
+ tosym: tabstractvarsym;
+ offset: pint;
+ flags: tdwarfvarsymflags;
+ begin
+ templist:=TAsmList.create;
+ case tabsolutevarsym(sym).abstyp of
+ toaddr :
+ begin
+ { MWE: replaced ifdef i368 }
+ (*
+ if target_cpu = cpu_i386 then
+ begin
+ { in theory, we could write a DW_AT_segment entry here for sym.absseg,
+ however I doubt that gdb supports this (FK) }
+ end;
+ *)
+ templist.concat(tai_const.create_8bit(3));
+ templist.concat(tai_const.create_pint(sym.addroffset));
+ blocksize:=1+sizeof(puint);
+ end;
+ toasm :
+ begin
+ templist.concat(tai_const.create_8bit(3));
+ templist.concat(tai_const.createname(sym.mangledname,0));
+ blocksize:=1+sizeof(puint);
+ end;
+ tovar:
+ begin
+ symlist:=tabsolutevarsym(sym).ref.firstsym;
+ if get_symlist_sym_offset(symlist,tosym,offset) then
+ begin
+ if (tosym.typ=fieldvarsym) then
+ internalerror(2009031402);
+ flags:=[];
+ if (sym.owner.symtabletype=localsymtable) then
+ include(flags,dvf_force_local_var);
+ appendsym_var_with_name_type_offset(list,tabstractnormalvarsym(tosym),symname(sym),tabstractvarsym(sym).vardef,offset,flags);
+ end;
+ templist.free;
+ exit;
+ end;
+ end;
+
+ append_entry(DW_TAG_variable,false,[
+ DW_AT_name,DW_FORM_string,symname(sym)+#0,
+ {
+ DW_AT_decl_file,DW_FORM_data1,0,
+ DW_AT_decl_line,DW_FORM_data1,
+ }
+ DW_AT_external,DW_FORM_flag,true,
+ { data continues below }
+ DW_AT_location,DW_FORM_block1,blocksize
+ ]);
+ { append block data }
+ current_asmdata.asmlists[al_dwarf_info].concatlist(templist);
+ append_labelentry_ref(DW_AT_type,def_dwarf_lab(sym.vardef));
+
+ templist.free;
+
+ finish_entry;
+ end;
+
+
+ procedure TDebugInfoDwarf.beforeappendsym(list:TAsmList;sym:tsym);
+ begin
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_comment.Create(strpnew('Symbol '+symname(sym))));
+ end;
+
+
+ procedure TDebugInfoDwarf.insertmoduleinfo;
+ var
+ templist: TAsmList;
+ linelist: TAsmList;
+ lbl : tasmlabel;
+ n,m : Integer;
+ ditem : TDirIndexItem;
+ fitem : TFileIndexItem;
+ flist : TFPList;
+ dbgname : String;
+ begin
+ { insert DEBUGSTART and DEBUGEND labels }
+ dbgname:=make_mangledname('DEBUGSTART',current_module.localsymtable,'');
+ { Darwin's linker does not like two global labels both pointing to the
+ end of a section, which can happen in case of units without code ->
+ make them local; we don't need the debugtable stuff there either,
+ so it doesn't matter that they are not global.
+ }
+ if (target_info.system in systems_darwin) then
+ dbgname:='L'+dbgname;
+ new_section(current_asmdata.asmlists[al_start],sec_code,dbgname,0,secorder_begin);
+ if not(target_info.system in systems_darwin) then
+ current_asmdata.asmlists[al_start].concat(tai_symbol.Createname_global(dbgname,AT_DATA,0))
+ else
+ current_asmdata.asmlists[al_start].concat(tai_symbol.Createname(dbgname,AT_DATA,0));
+
+ dbgname:=make_mangledname('DEBUGEND',current_module.localsymtable,'');
+ { See above. }
+ if (target_info.system in systems_darwin) then
+ dbgname:='L'+dbgname;
+ new_section(current_asmdata.asmlists[al_end],sec_code,dbgname,0,secorder_end);
+ if not(target_info.system in systems_darwin) then
+ current_asmdata.asmlists[al_end].concat(tai_symbol.Createname_global(dbgname,AT_DATA,0))
+ else
+ current_asmdata.asmlists[al_end].concat(tai_symbol.Createname(dbgname,AT_DATA,0));
+
+ { insert .Ldebug_abbrev0 label }
+ templist:=TAsmList.create;
+ new_section(templist,sec_debug_abbrev,'',0);
+ templist.concat(tai_symbol.createname(target_asm.labelprefix+'debug_abbrevsection0',AT_DATA,0));
+ { add any extra stuff which needs to be in the abbrev section, but before }
+ { the actual abbreviations, in between the symbol above and below, i.e. here }
+ templist.concat(tai_symbol.createname(target_asm.labelprefix+'debug_abbrev0',AT_DATA,0));
+ current_asmdata.asmlists[al_start].insertlist(templist);
+ templist.free;
+
+ { insert .Ldebug_line0 label }
+ templist:=TAsmList.create;
+ new_section(templist,sec_debug_line,'',0);
+ templist.concat(tai_symbol.createname(target_asm.labelprefix+'debug_linesection0',AT_DATA,0));
+ { add any extra stuff which needs to be in the line section, but before }
+ { the actual line info, in between the symbol above and below, i.e. here }
+ templist.concat(tai_symbol.createname(target_asm.labelprefix+'debug_line0',AT_DATA,0));
+ current_asmdata.asmlists[al_start].insertlist(templist);
+ templist.free;
+
+ { finalize line info if the unit doesn't contain any function/ }
+ { procedure/init/final code }
+ finish_lineinfo;
+
+ { debug line header }
+ linelist := current_asmdata.asmlists[al_dwarf_line];
+ new_section(linelist,sec_debug_line,'',0);
+ linelist.concat(tai_comment.Create(strpnew('=== header start ===')));
+
+ { size }
+ current_asmdata.getlabel(lbl,alt_dbgfile);
+ if use_64bit_headers then
+ linelist.concat(tai_const.create_32bit(longint($FFFFFFFF)));
+ linelist.concat(tai_const.create_rel_sym(offsetreltype,
+ lbl,current_asmdata.RefAsmSymbol(target_asm.labelprefix+'edebug_line0')));
+ linelist.concat(tai_label.create(lbl));
+
+ { version }
+ linelist.concat(tai_const.create_16bit(dwarf_version));
+
+ { header length }
+ current_asmdata.getlabel(lbl,alt_dbgfile);
+ linelist.concat(tai_const.create_rel_sym(offsetreltype,
+ lbl,current_asmdata.RefAsmSymbol(target_asm.labelprefix+'ehdebug_line0')));
+ linelist.concat(tai_label.create(lbl));
+
+ { minimum_instruction_length }
+ linelist.concat(tai_const.create_8bit(1));
+
+ { default_is_stmt }
+ linelist.concat(tai_const.create_8bit(1));
+
+ { line_base }
+ linelist.concat(tai_const.create_8bit(LINE_BASE));
+
+ { line_range }
+ { only line increase, no adress }
+ linelist.concat(tai_const.create_8bit(255));
+
+ { opcode_base }
+ linelist.concat(tai_const.create_8bit(OPCODE_BASE));
+
+ { standard_opcode_lengths }
+ { MWE: sigh... why adding the default lengths (and make those sizes sense with LEB encoding) }
+ { DW_LNS_copy }
+ linelist.concat(tai_const.create_8bit(0));
+ { DW_LNS_advance_pc }
+ linelist.concat(tai_const.create_8bit(1));
+ { DW_LNS_advance_line }
+ linelist.concat(tai_const.create_8bit(1));
+ { DW_LNS_set_file }
+ linelist.concat(tai_const.create_8bit(1));
+ { DW_LNS_set_column }
+ linelist.concat(tai_const.create_8bit(1));
+ { DW_LNS_negate_stmt }
+ linelist.concat(tai_const.create_8bit(0));
+ { DW_LNS_set_basic_block }
+ linelist.concat(tai_const.create_8bit(0));
+ { DW_LNS_const_add_pc }
+ linelist.concat(tai_const.create_8bit(0));
+ { DW_LNS_fixed_advance_pc }
+ linelist.concat(tai_const.create_8bit(1));
+ { DW_LNS_set_prologue_end }
+ linelist.concat(tai_const.create_8bit(0));
+ { DW_LNS_set_epilogue_begin }
+ linelist.concat(tai_const.create_8bit(0));
+ { DW_LNS_set_isa }
+ linelist.concat(tai_const.create_8bit(1));
+
+ { Create single list of filenames sorted in IndexNr }
+ flist:=TFPList.Create;
+ for n := 0 to dirlist.Count - 1 do
+ begin
+ ditem := TDirIndexItem(dirlist[n]);
+ for m := 0 to ditem.Files.Count - 1 do
+ flist.Add(ditem.Files[m]);
+ end;
+ flist.Sort(@FileListSortCompare);
+
+ { include_directories }
+ linelist.concat(tai_comment.Create(strpnew('include_directories')));
+ for n := 0 to dirlist.Count - 1 do
+ begin
+ ditem := TDirIndexItem(dirlist[n]);
+ if ditem.Name = '.' then
+ Continue;
+ { Write without trailing path delimiter and also don't prefix with ./ for current dir (already done while adding to dirlist }
+
+ linelist.concat(tai_string.create(ditem.Name+#0));
+ end;
+ linelist.concat(tai_const.create_8bit(0));
+
+ { file_names }
+ linelist.concat(tai_comment.Create(strpnew('file_names')));
+ for n := 0 to flist.Count - 1 do
+ begin
+ fitem := TFileIndexItem(flist[n]);
+ { file name }
+ linelist.concat(tai_string.create(fitem.Name+#0));
+ { directory index }
+ linelist.concat(tai_const.create_uleb128bit(fitem.DirIndex));
+ { last modification }
+ linelist.concat(tai_const.create_uleb128bit(0));
+ { file length }
+ linelist.concat(tai_const.create_uleb128bit(0));
+ end;
+ linelist.concat(tai_const.create_8bit(0));
+
+ { end of debug line header }
+ linelist.concat(tai_symbol.createname(target_asm.labelprefix+'ehdebug_line0',AT_DATA,0));
+ linelist.concat(tai_comment.Create(strpnew('=== header end ===')));
+
+ { add line program }
+ linelist.concatList(asmline);
+
+ { end of debug line table }
+ linelist.concat(tai_symbol.createname(target_asm.labelprefix+'edebug_line0',AT_DATA,0));
+
+ flist.free;
+ end;
+
+
+ procedure TDebugInfoDwarf.inserttypeinfo;
+
+
+ var
+ storefilepos : tfileposinfo;
+ lenstartlabel : tasmlabel;
+ i : longint;
+ def: tdef;
+ dbgname: string;
+ vardatatype: ttypesym;
+ begin
+ current_module.flags:=current_module.flags or uf_has_dwarf_debuginfo;
+ storefilepos:=current_filepos;
+ current_filepos:=current_module.mainfilepos;
+
+ currabbrevnumber:=0;
+
+ defnumberlist:=TFPObjectList.create(false);
+ deftowritelist:=TFPObjectList.create(false);
+
+ { not exported (FK)
+ FILEREC
+ TEXTREC
+ }
+ vardatatype:=try_search_system_type('TVARDATA');
+ if assigned(vardatatype) then
+ vardatadef:=trecorddef(vardatatype.typedef);
+
+ { write start labels }
+ new_section(current_asmdata.asmlists[al_dwarf_info],sec_debug_info,'',0);
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_symbol.createname(target_asm.labelprefix+'debug_info0',AT_DATA,0));
+
+ { start abbrev section }
+ new_section(current_asmdata.asmlists[al_dwarf_abbrev],sec_debug_abbrev,'',0);
+
+ { debug info header }
+ current_asmdata.getlabel(lenstartlabel,alt_dbgfile);
+ { size }
+ if use_64bit_headers then
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_32bit(longint($FFFFFFFF)));
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_rel_sym(offsetreltype,
+ lenstartlabel,current_asmdata.RefAsmSymbol(target_asm.labelprefix+'edebug_info0')));
+
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_label.create(lenstartlabel));
+ { version }
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_16bit(dwarf_version));
+ { abbrev table (=relative from section start)}
+ if not(tf_dwarf_relative_addresses in target_info.flags) then
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_type_sym(offsetabstype,
+ current_asmdata.RefAsmSymbol(target_asm.labelprefix+'debug_abbrev0')))
+ else
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_rel_sym(offsetreltype,
+ current_asmdata.RefAsmSymbol(target_asm.labelprefix+'debug_abbrevsection0'),
+ current_asmdata.RefAsmSymbol(target_asm.labelprefix+'debug_abbrev0')));
+
+ { address size }
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(sizeof(pint)));
+
+ { first manadatory compilation unit TAG }
+ append_entry(DW_TAG_compile_unit,true,[
+ DW_AT_name,DW_FORM_string,relative_dwarf_path(current_module.sourcefiles.get_file(1).path^+current_module.sourcefiles.get_file(1).name^)+#0,
+ DW_AT_producer,DW_FORM_string,'Free Pascal '+full_version_string+' '+date_string+#0,
+ DW_AT_comp_dir,DW_FORM_string,BSToSlash(FixPath(GetCurrentDir,false))+#0,
+ DW_AT_language,DW_FORM_data1,DW_LANG_Pascal83,
+ DW_AT_identifier_case,DW_FORM_data1,DW_ID_case_insensitive]);
+
+ { reference to line info section }
+ if not(tf_dwarf_relative_addresses in target_info.flags) then
+ append_labelentry_dataptr_abs(DW_AT_stmt_list,current_asmdata.RefAsmSymbol(target_asm.labelprefix+'debug_line0'))
+ else
+ append_labelentry_dataptr_rel(DW_AT_stmt_list,
+ current_asmdata.RefAsmSymbol(target_asm.labelprefix+'debug_linesection0'),
+ current_asmdata.RefAsmSymbol(target_asm.labelprefix+'debug_line0'));
+
+ if (m_objectivec1 in current_settings.modeswitches) then
+ append_attribute(DW_AT_APPLE_major_runtime_vers,DW_FORM_data1,[1]);
+
+ dbgname:=make_mangledname('DEBUGSTART',current_module.localsymtable,'');
+ if (target_info.system in systems_darwin) then
+ dbgname:='L'+dbgname;
+ append_labelentry(DW_AT_low_pc,current_asmdata.RefAsmSymbol(dbgname));
+ dbgname:=make_mangledname('DEBUGEND',current_module.localsymtable,'');
+ if (target_info.system in systems_darwin) then
+ dbgname:='L'+dbgname;
+ append_labelentry(DW_AT_high_pc,current_asmdata.RefAsmSymbol(dbgname));
+
+ finish_entry;
+
+ { write all global/local variables. This will flag all required tdefs }
+ if assigned(current_module.globalsymtable) then
+ write_symtable_syms(current_asmdata.asmlists[al_dwarf_info],current_module.globalsymtable);
+ if assigned(current_module.localsymtable) then
+ write_symtable_syms(current_asmdata.asmlists[al_dwarf_info],current_module.localsymtable);
+
+ { write all procedures and methods. This will flag all required tdefs }
+ if assigned(current_module.globalsymtable) then
+ write_symtable_procdefs(current_asmdata.asmlists[al_dwarf_info],current_module.globalsymtable);
+ if assigned(current_module.localsymtable) then
+ write_symtable_procdefs(current_asmdata.asmlists[al_dwarf_info],current_module.localsymtable);
+
+ { reset unit type info flag }
+ reset_unit_type_info;
+
+ { write used types from the used units }
+ write_used_unit_type_info(current_asmdata.asmlists[al_dwarf_info],current_module);
+
+ { last write the types from this unit }
+ if assigned(current_module.globalsymtable) then
+ write_symtable_defs(current_asmdata.asmlists[al_dwarf_info],current_module.globalsymtable);
+ if assigned(current_module.localsymtable) then
+ write_symtable_defs(current_asmdata.asmlists[al_dwarf_info],current_module.localsymtable);
+
+ { write defs not written yet }
+ write_remaining_defs_to_write(current_asmdata.asmlists[al_dwarf_info]);
+
+ { close compilation unit entry }
+ finish_children;
+
+ { end of debug info table }
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_symbol.createname(target_asm.labelprefix+'edebug_info0',AT_DATA,0));
+
+ { end of abbrev table }
+ current_asmdata.asmlists[al_dwarf_abbrev].concat(tai_const.create_8bit(0));
+
+ { reset all def labels }
+ for i:=0 to defnumberlist.count-1 do
+ begin
+ def := tdef(defnumberlist[i]);
+ if assigned(def) then
+ begin
+ def.dwarf_lab:=nil;
+ def.dbg_state:=dbg_state_unused;
+ end;
+ end;
+
+ defnumberlist.free;
+ defnumberlist:=nil;
+ deftowritelist.free;
+ deftowritelist:=nil;
+
+ current_filepos:=storefilepos;
+ end;
+
+
+ procedure TDebugInfoDwarf.referencesections(list:TAsmList);
+ var
+ hp : tmodule;
+ begin
+ { Reference all DEBUGINFO sections from the main .fpc section }
+ { to prevent eliminating them by smartlinking }
+ if (target_info.system in ([system_powerpc_macos]+systems_darwin)) then
+ exit;
+ new_section(list,sec_fpc,'links',0);
+
+ { include reference to all debuginfo sections of used units }
+ hp:=tmodule(loaded_units.first);
+ while assigned(hp) do
+ begin
+ If (hp.flags and uf_has_dwarf_debuginfo)=uf_has_dwarf_debuginfo then
+ begin
+ list.concat(Tai_const.Createname(make_mangledname('DEBUGSTART',hp.localsymtable,''),0));
+ list.concat(Tai_const.Createname(make_mangledname('DEBUGEND',hp.localsymtable,''),0));
+ end;
+ hp:=tmodule(hp.next);
+ end;
+ end;
+
+
+ function TDebugInfoDwarf.symname(sym: tsym): String;
+ begin
+ if (sym.typ=paravarsym) and
+ (vo_is_self in tparavarsym(sym).varoptions) then
+ { We use 'this' for regular methods because that's what gdb triggers
+ on to automatically search fields. Don't do this for class methods,
+ because search class fields is not supported, and gdb 7.0+ fails
+ in this case because "this" is not a record in that case (it's a
+ pointer to a vmt) }
+ if not is_objc_class_or_protocol(tdef(sym.owner.defowner.owner.defowner)) and
+ not(po_classmethod in tabstractprocdef(sym.owner.defowner).procoptions) then
+ result:='this'
+ else
+ result:='self'
+ else if (sym.typ=typesym) and
+ is_objc_class_or_protocol(ttypesym(sym).typedef) then
+ result:=tobjectdef(ttypesym(sym).typedef).objextname^
+ else if (ds_dwarf_method_class_prefix in current_settings.debugswitches) and
+ (sym.typ=procsym) and
+ (tprocsym(sym).owner.symtabletype in [objectsymtable,recordsymtable]) then
+ result:=tprocsym(sym).owner.name^+'__'+symdebugname(sym)
+ else
+ result:=symdebugname(sym);
+ end;
+
+
+ procedure tdebuginfodwarf.append_visibility(vis: tvisibility);
+ begin
+ case vis of
+ vis_private,
+ vis_strictprivate:
+ append_attribute(DW_AT_accessibility,DW_FORM_data1,[ord(DW_ACCESS_private)]);
+ vis_protected,
+ vis_strictprotected:
+ append_attribute(DW_AT_accessibility,DW_FORM_data1,[ord(DW_ACCESS_protected)]);
+ vis_public:
+ { default };
+ end;
+ end;
+
+
+ procedure TDebugInfoDwarf.insertlineinfo(list:TAsmList);
+ var
+ currfileinfo,
+ lastfileinfo : tfileposinfo;
+ currfuncname : pshortstring;
+ currsectype : TAsmSectiontype;
+ hp, hpend : tai;
+ infile : tinputfile;
+ prevcolumn,
+ diffline,
+ prevline,
+ prevfileidx,
+ currfileidx,
+ nolineinfolevel : Integer;
+ prevlabel,
+ currlabel : tasmlabel;
+ begin
+ { this function will always terminate the lineinfo block }
+ generated_lineinfo := true;
+ FillChar(lastfileinfo,sizeof(lastfileinfo),0);
+ currfuncname:=nil;
+ currsectype:=sec_code;
+ hp:=Tai(list.first);
+ prevcolumn := 0;
+ prevline := 1;
+ prevfileidx := 1;
+ prevlabel := nil;
+ nolineinfolevel:=0;
+ while assigned(hp) do
+ begin
+ case hp.typ of
+ ait_section :
+ currsectype:=tai_section(hp).sectype;
+ ait_function_name :
+ begin
+ currfuncname:=tai_function_name(hp).funcname;
+ asmline.concat(tai_comment.Create(strpnew('function: '+currfuncname^)));
+ end;
+ ait_force_line :
+ begin
+ lastfileinfo.line:=-1;
+ end;
+ ait_marker :
+ begin
+ case tai_marker(hp).kind of
+ mark_NoLineInfoStart:
+ inc(nolineinfolevel);
+ mark_NoLineInfoEnd:
+ dec(nolineinfolevel);
+ end;
+ end;
+ end;
+
+ if (currsectype=sec_code) and
+ (hp.typ=ait_instruction) and
+ (nolineinfolevel=0) then
+ begin
+ currfileinfo:=tailineinfo(hp).fileinfo;
+ { file changed ? (must be before line info) }
+ if (currfileinfo.fileindex<>0) and
+ ((lastfileinfo.fileindex<>currfileinfo.fileindex) or
+ (lastfileinfo.moduleindex<>currfileinfo.moduleindex)) then
+ begin
+ infile:=get_module(currfileinfo.moduleindex).sourcefiles.get_file(currfileinfo.fileindex);
+ if assigned(infile) then
+ begin
+ currfileidx := get_file_index(infile);
+ if prevfileidx <> currfileidx then
+ begin
+ list.insertbefore(tai_comment.Create(strpnew('path: '+infile.path^)), hp);
+ list.insertbefore(tai_comment.Create(strpnew('file: '+infile.name^)), hp);
+ list.insertbefore(tai_comment.Create(strpnew('indx: '+tostr(currfileidx))), hp);
+
+ { set file }
+ asmline.concat(tai_comment.Create(strpnew('path: '+infile.path^)));
+ asmline.concat(tai_comment.Create(strpnew('file: '+infile.name^)));
+ asmline.concat(tai_const.create_8bit(DW_LNS_set_file));
+ asmline.concat(tai_const.create_uleb128bit(currfileidx));
+
+ prevfileidx := currfileidx;
+ end;
+ { force new line info }
+ lastfileinfo.line:=-1;
+ end;
+ end;
+
+ { line changed ? }
+ if (lastfileinfo.line<>currfileinfo.line) and (currfileinfo.line<>0) then
+ begin
+ { set address }
+ current_asmdata.getlabel(currlabel, alt_dbgline);
+ list.insertbefore(tai_label.create(currlabel), hp);
+
+ asmline.concat(tai_comment.Create(strpnew('['+tostr(currfileinfo.line)+':'+tostr(currfileinfo.column)+']')));
+
+ if (prevlabel = nil) or
+ { darwin's assembler cannot create an uleb128 of the difference }
+ { between to symbols }
+ (target_info.system in systems_darwin) then
+ begin
+ asmline.concat(tai_const.create_8bit(DW_LNS_extended_op));
+ asmline.concat(tai_const.create_uleb128bit(1+sizeof(pint)));
+ asmline.concat(tai_const.create_8bit(DW_LNE_set_address));
+ asmline.concat(tai_const.create_sym(currlabel));
+ end
+ else
+ begin
+ asmline.concat(tai_const.create_8bit(DW_LNS_advance_pc));
+ asmline.concat(tai_const.create_rel_sym(aitconst_uleb128bit, prevlabel, currlabel));
+ end;
+ prevlabel := currlabel;
+
+ { set column }
+ if prevcolumn <> currfileinfo.column then
+ begin
+ asmline.concat(tai_const.create_8bit(DW_LNS_set_column));
+ asmline.concat(tai_const.create_uleb128bit(currfileinfo.column));
+ prevcolumn := currfileinfo.column;
+ end;
+
+ { set line }
+ diffline := currfileinfo.line - prevline;
+ if (diffline >= LINE_BASE) and (OPCODE_BASE + diffline - LINE_BASE <= 255) then
+ begin
+ { use special opcode, this also adds a row }
+ asmline.concat(tai_const.create_8bit(OPCODE_BASE + diffline - LINE_BASE));
+ end
+ else
+ begin
+ if diffline <> 0 then
+ begin
+ asmline.concat(tai_const.create_8bit(DW_LNS_advance_line));
+ asmline.concat(tai_const.create_sleb128bit(diffline));
+ end;
+ { no row added yet, do it manually }
+ asmline.concat(tai_const.create_8bit(DW_LNS_copy));
+ end;
+ prevline := currfileinfo.line;
+ end;
+
+ lastfileinfo:=currfileinfo;
+ end;
+
+ hpend:=hp;
+ hp:=tai(hp.next);
+ end;
+
+ if assigned(hpend) then
+ begin
+ { set address for end (see appendix 3 of dwarf 2 specs) }
+ current_asmdata.getlabel(currlabel, alt_dbgline);
+ list.insertafter(tai_label.create(currlabel), hpend);
+ asmline.concat(tai_const.create_8bit(DW_LNS_extended_op));
+ asmline.concat(tai_const.create_uleb128bit(1+sizeof(pint)));
+ asmline.concat(tai_const.create_8bit(DW_LNE_set_address));
+ asmline.concat(tai_const.create_sym(currlabel));
+ end;
+
+ { end sequence }
+ asmline.concat(tai_const.Create_8bit(DW_LNS_extended_op));
+ asmline.concat(tai_const.Create_8bit(1));
+ asmline.concat(tai_const.Create_8bit(DW_LNE_end_sequence));
+ asmline.concat(tai_comment.Create(strpnew('###################')));
+ end;
+
+
+ procedure TDebugInfoDwarf.finish_lineinfo;
+ var
+ infile: tinputfile;
+ begin
+ { only needed if no line info at all has been generated }
+ if generated_lineinfo then
+ begin
+ { reset for next module compilation }
+ generated_lineinfo:=false;
+ exit;
+ end;
+ { at least the Darwin linker is annoyed if you do not }
+ { finish the lineinfo section, or if it doesn't }
+ { contain at least one file name and set_address }
+ infile:=current_module.sourcefiles.get_file(1);
+ if not assigned(infile) then
+ internalerror(2006020211);
+ asmline.concat(tai_const.create_8bit(DW_LNS_set_file));
+ asmline.concat(tai_const.create_uleb128bit(get_file_index(infile)));
+
+ asmline.concat(tai_const.create_8bit(DW_LNS_extended_op));
+ asmline.concat(tai_const.create_uleb128bit(1+sizeof(pint)));
+ asmline.concat(tai_const.create_8bit(DW_LNE_set_address));
+ asmline.concat(tai_const.create_sym(nil));
+ asmline.concat(tai_const.create_8bit(DW_LNS_extended_op));
+ asmline.concat(tai_const.Create_8bit(1));
+ asmline.concat(tai_const.Create_8bit(DW_LNE_end_sequence));
+ asmline.concat(tai_comment.Create(strpnew('###################')));
+ end;
+
+{****************************************************************************
+ TDebugInfoDwarf2
+****************************************************************************}
+
+ procedure TDebugInfoDwarf2.appenddef_file(list:TAsmList;def: tfiledef);
+ begin
+ { gdb 6.4 doesn't support files so far so we use some fake recorddef
+ file recs. are less than 1k so using data2 is enough }
+ if assigned(def.typesym) then
+ append_entry(DW_TAG_structure_type,false,[
+ DW_AT_name,DW_FORM_string,symname(def.typesym)+#0,
+ DW_AT_byte_size,DW_FORM_udata,def.size
+ ])
+ else
+ append_entry(DW_TAG_structure_type,false,[
+ DW_AT_byte_size,DW_FORM_udata,def.size
+ ]);
+ finish_entry;
+ end;
+
+ procedure TDebugInfoDwarf2.appenddef_formal(list:TAsmList;def: tformaldef);
+ begin
+ { gdb 6.4 doesn't support DW_TAG_unspecified_type so we
+ replace it with a unsigned type with size 0 (FK)
+ }
+ append_entry(DW_TAG_base_type,false,[
+ DW_AT_name,DW_FORM_string,'FormalDef'#0,
+ DW_AT_encoding,DW_FORM_data1,DW_ATE_unsigned,
+ DW_AT_byte_size,DW_FORM_data1,0
+ ]);
+ finish_entry;
+ end;
+
+ procedure TDebugInfoDwarf2.append_object_struct(def: tobjectdef; const createlabel: boolean; const objectname: PShortString);
+ begin
+ if createlabel then
+ begin
+ if not(tf_dwarf_only_local_labels in target_info.flags) then
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_symbol.create_global(def_dwarf_class_struct_lab(def),0))
+ else
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_symbol.create(def_dwarf_class_struct_lab(def),0));
+ end;
+ if assigned(objectname) then
+ append_entry(DW_TAG_class_type,true,[
+ DW_AT_name,DW_FORM_string,objectname^+#0,
+ DW_AT_byte_size,DW_FORM_udata,tobjectsymtable(def.symtable).datasize
+ ])
+ else
+ append_entry(DW_TAG_class_type,true,[
+ DW_AT_byte_size,DW_FORM_udata,tobjectsymtable(def.symtable).datasize
+ ]);
+ { Apple-specific tag that identifies it as an Objective-C class }
+ if (def.objecttype=odt_objcclass) then
+ append_attribute(DW_AT_APPLE_runtime_class,DW_FORM_data1,[DW_LANG_ObjC]);
+
+ finish_entry;
+ if assigned(def.childof) then
+ begin
+ append_entry(DW_TAG_inheritance,false,[
+ DW_AT_accessibility,DW_FORM_data1,DW_ACCESS_public,
+ DW_AT_data_member_location,DW_FORM_block1,1+lengthuleb128(0)
+ ]);
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(ord(DW_OP_plus_uconst)));
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_uleb128bit(0));
+ if (def.childof.dbg_state=dbg_state_unused) then
+ def.childof.dbg_state:=dbg_state_used;
+ if is_implicit_pointer_object_type(def) then
+ append_labelentry_ref(DW_AT_type,def_dwarf_class_struct_lab(def.childof))
+ else
+ append_labelentry_ref(DW_AT_type,def_dwarf_lab(def.childof));
+ finish_entry;
+ end;
+ if (oo_has_vmt in def.objectoptions) and
+ (not assigned(def.childof) or
+ not(oo_has_vmt in def.childof.objectoptions)) then
+ begin
+ { vmt field }
+ append_entry(DW_TAG_member,false,[
+ DW_AT_artificial,DW_FORM_flag,true,
+ DW_AT_name,DW_FORM_string,'_vptr$'+def.objname^+#0,
+ DW_AT_data_member_location,DW_FORM_block1,1+lengthuleb128(def.vmt_offset)
+ ]);
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(ord(DW_OP_plus_uconst)));
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_uleb128bit(def.vmt_offset));
+ { should be changed into a pointer to a function returning an }
+ { int and with TAG_unspecified_parameters }
+ if (voidpointertype.dbg_state=dbg_state_unused) then
+ voidpointertype.dbg_state:=dbg_state_used;
+ append_labelentry_ref(DW_AT_type,def_dwarf_lab(voidpointertype));
+ finish_entry;
+ end;
+
+ def.symtable.symList.ForEachCall(@enum_membersyms_callback,nil);
+ { Write the methods in the scope of the class/object, except for Objective-C. }
+ if is_objc_class_or_protocol(def) then
+ finish_children;
+ { don't write procdefs of externally defined classes, gcc doesn't
+ either (info is probably gotten from ObjC runtime) }
+ if not(oo_is_external in def.objectoptions) then
+ write_symtable_procdefs(current_asmdata.asmlists[al_dwarf_info],def.symtable);
+ if not is_objc_class_or_protocol(def) then
+ finish_children;
+ end;
+
+
+ procedure TDebugInfoDwarf2.appenddef_object(list:TAsmList;def: tobjectdef);
+
+ begin
+ case def.objecttype of
+ odt_cppclass,
+ odt_object:
+ append_object_struct(def,false,def.objname);
+ odt_interfacecom,
+ odt_interfacecorba,
+ odt_dispinterface,
+ odt_helper,
+ odt_class:
+ begin
+ { implicit pointer }
+ append_entry(DW_TAG_pointer_type,false,[]);
+ append_labelentry_ref(DW_AT_type,def_dwarf_class_struct_lab(def));
+ finish_entry;
+
+ append_object_struct(def,true,def.objname);
+ end;
+ odt_objcclass:
+ { Objective-C class: same as regular class, except for
+ a) Apple-specific tag that identifies it as an Objective-C class
+ b) use extname^ instead of objname
+ }
+ append_object_struct(def,true,def.objextname);
+ odt_objcprotocol:
+ begin
+ append_entry(DW_TAG_pointer_type,false,[]);
+ append_labelentry_ref(DW_AT_type,def_dwarf_lab(voidpointertype));
+ finish_entry;
+ end;
+ else
+ internalerror(200602041);
+ end;
+ end;
+
+ procedure TDebugInfoDwarf2.appenddef_set_intern(list:TAsmList;def: tsetdef; force_tag_set: boolean);
+ var
+ lab: tasmlabel;
+ begin
+ if force_tag_set or
+ (ds_dwarf_sets in current_settings.debugswitches) then
+ begin
+ { current (20070704 -- patch was committed on 20060513) gdb cvs supports set types }
+
+ if assigned(def.typesym) then
+ append_entry(DW_TAG_set_type,false,[
+ DW_AT_name,DW_FORM_string,symname(def.typesym)+#0,
+ DW_AT_byte_size,DW_FORM_data2,def.size
+ ])
+ else
+ append_entry(DW_TAG_set_type,false,[
+ DW_AT_byte_size,DW_FORM_data2,def.size
+ ]);
+ if assigned(def.elementdef) then
+ begin
+ if not(tf_dwarf_only_local_labels in target_info.flags) then
+ current_asmdata.getdatalabel(lab)
+ else
+ current_asmdata.getaddrlabel(lab);
+ append_labelentry_ref(DW_AT_type,lab);
+ finish_entry;
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_symbol.create(lab,0));
+ { Sets of e.g. [1..5] are actually stored as a set of [0..7],
+ so write the exact boundaries of the set here. Let's hope no
+ debugger ever rejects this because this "subrange" type can
+ actually have a larger range than the original one. }
+ append_entry(DW_TAG_subrange_type,false,[
+ DW_AT_lower_bound,DW_FORM_sdata,def.setbase,
+ DW_AT_upper_bound,DW_FORM_sdata,get_max_value(def.elementdef).svalue
+ ]);
+ append_labelentry_ref(DW_AT_type,def_dwarf_lab(def.elementdef))
+ end
+ end
+ else
+ begin
+ { gdb versions which don't support sets refuse to load the debug }
+ { info of modules that contain set tags }
+ if assigned(def.typesym) then
+ append_entry(DW_TAG_base_type,false,[
+ DW_AT_name,DW_FORM_string,symname(def.typesym)+#0,
+ DW_AT_encoding,DW_FORM_data1,DW_ATE_unsigned,
+ DW_AT_byte_size,DW_FORM_data2,def.size
+ ])
+ else
+ append_entry(DW_TAG_base_type,false,[
+ DW_AT_encoding,DW_FORM_data1,DW_ATE_unsigned,
+ DW_AT_byte_size,DW_FORM_data2,def.size
+ ]);
+ end;
+ finish_entry;
+ end;
+
+ procedure TDebugInfoDwarf2.appenddef_set(list:TAsmList;def: tsetdef);
+ begin
+ appenddef_set_intern(list,def,false);
+ end;
+
+ procedure TDebugInfoDwarf2.appenddef_undefined(list:TAsmList;def: tundefineddef);
+ begin
+ { gdb 6.4 doesn't support DW_TAG_unspecified_type so we
+ replace it with a unsigned type with size 0 (FK)
+ }
+ append_entry(DW_TAG_base_type,false,[
+ DW_AT_name,DW_FORM_string,'FormalDef'#0,
+ DW_AT_encoding,DW_FORM_data1,DW_ATE_unsigned,
+ DW_AT_byte_size,DW_FORM_data1,0
+ ]);
+ finish_entry;
+ end;
+
+ procedure TDebugInfoDwarf2.appenddef_variant(list:TAsmList;def: tvariantdef);
+ begin
+ { variants aren't known to dwarf2 but writting tvardata should be enough }
+ if assigned(vardatadef) then
+ appenddef_record_named(list,trecorddef(vardatadef),'Variant');
+ end;
+
+ function TDebugInfoDwarf2.dwarf_version: Word;
+ begin
+ Result:=2;
+ end;
+
+{****************************************************************************
+ TDebugInfoDwarf3
+****************************************************************************}
+
+ procedure TDebugInfoDwarf3.append_labelentry_addr_ref(attr : tdwarf_attribute;sym : tasmsymbol);
+ begin
+ AddConstToAbbrev(ord(DW_FORM_ref_addr));
+ { Since Dwarf 3 the length of a DW_FORM_ref_addr entry is not dependent on the pointer size of the
+ target platform, but on the used Dwarf-format (32 bit or 64 bit) for the current compilation section. }
+ if use_64bit_headers then
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.Create_type_sym(aitconst_64bit,sym))
+ else
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.Create_type_sym(aitconst_32bit,sym));
+ end;
+
+ procedure tdebuginfodwarf3.appenddef_array(list: tasmlist; def: tarraydef);
+ begin
+ if not is_dynamic_array(def) then
+ begin
+ inherited appenddef_array(list,def);
+ exit;
+ end;
+
+ if assigned(def.typesym) then
+ append_entry(DW_TAG_array_type,true,[
+ DW_AT_name,DW_FORM_string,symname(def.typesym)+#0,
+ DW_AT_data_location,DW_FORM_block1,2
+ ])
+ else
+ append_entry(DW_TAG_array_type,true,[
+ DW_AT_data_location,DW_FORM_block1,2
+ ]);
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(ord(DW_OP_push_object_address)));
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(ord(DW_OP_deref)));
+
+ append_labelentry_ref(DW_AT_type,def_dwarf_lab(def.elementdef));
+ finish_entry;
+ { to simplify things, we don't write a multidimensional array here }
+ append_entry(DW_TAG_subrange_type,false,[
+ DW_AT_byte_stride,DW_FORM_udata,def.elesize,
+ DW_AT_lower_bound,DW_FORM_udata,0,
+ DW_AT_upper_bound,DW_FORM_block1,14
+ ]);
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(ord(DW_OP_push_object_address)));
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(ord(DW_OP_deref)));
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(ord(DW_OP_dup)));
+ { pointer = nil? }
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(ord(DW_OP_bra)));
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_16bit(5));
+ { yes -> length = 0 }
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(ord(DW_OP_const1s)));
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(byte(-1)));
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(ord(DW_OP_skip)));
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_16bit(3));
+ { no -> load length }
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(ord(DW_OP_lit0)+sizeof(ptrint)));
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(ord(DW_OP_minus)));
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(ord(DW_OP_deref)));
+ append_labelentry_ref(DW_AT_type,def_dwarf_lab(def.rangedef));
+ finish_entry;
+
+ finish_children;
+ end;
+
+
+ procedure tdebuginfodwarf3.appenddef_string(list: tasmlist; def: tstringdef);
+
+ procedure addstringdef(const name: shortstring; chardef: tdef; deref: boolean; lensize: aint);
+ var
+ upperopcodes: longint;
+ begin
+ { deref=true -> ansi/unicde/widestring; deref = false -> short/longstring }
+ if assigned(def.typesym) then
+ append_entry(DW_TAG_array_type,true,[
+ DW_AT_name,DW_FORM_string,name+#0,
+ DW_AT_data_location,DW_FORM_block1,2+ord(not(deref))
+ ])
+ else
+ append_entry(DW_TAG_array_type,true,[
+ DW_AT_data_location,DW_FORM_block1,2+ord(not(deref))
+ ]);
+
+ { in all cases we start with the address of the string }
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(ord(DW_OP_push_object_address)));
+ if deref then
+ begin
+ { ansi/unicode/widestring -> dereference the address of the string, and then
+ we point to address of the string
+ }
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(ord(DW_OP_deref)));
+ end
+ else
+ begin
+ { shortstring characters begin at string[1], so add one to the string's address }
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(ord(DW_OP_lit0)+lensize));
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(ord(DW_OP_plus)))
+ end;
+
+ { reference to the element type of the string }
+ append_labelentry_ref(DW_AT_type,def_dwarf_lab(chardef));
+ finish_entry;
+
+ { now the information about the length of the string }
+ if deref then
+ begin
+ if (chardef.size=1) then
+ upperopcodes:=13
+ else
+ upperopcodes:=15;
+ { lower bound is always 1, upper bound (length) needs to be calculated }
+ append_entry(DW_TAG_subrange_type,false,[
+ DW_AT_lower_bound,DW_FORM_udata,1,
+ DW_AT_upper_bound,DW_FORM_block1,upperopcodes
+ ]);
+
+ { high(string) is stored sizeof(ptrint) bytes before the string data }
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(ord(DW_OP_push_object_address)));
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(ord(DW_OP_deref)));
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(ord(DW_OP_dup)));
+ { pointer = nil? }
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(ord(DW_OP_bra)));
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_16bit(4));
+ { yes -> length = 0 }
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(ord(DW_OP_lit0)));
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(ord(DW_OP_skip)));
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_16bit(3));
+ { no -> load length }
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(ord(DW_OP_lit0)+sizeof(ptrint)));
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(ord(DW_OP_minus)));
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(ord(DW_OP_deref)));
+
+ { for widestrings, the length is specified in bytes, so divide by two }
+ if (upperopcodes=15) then
+ begin
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(ord(DW_OP_lit1)));
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(ord(DW_OP_shr)));
+ end;
+ end
+ else
+ begin
+ append_entry(DW_TAG_subrange_type,false,[
+ DW_AT_lower_bound,DW_FORM_udata,1,
+ DW_AT_upper_bound,DW_FORM_block1,3
+ ]);
+ { for shortstrings, the length is the first byte of the string }
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(ord(DW_OP_push_object_address)));
+ { load 1 byte }
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(ord(DW_OP_deref_size)));
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(lensize));
+ end;
+ finish_entry;
+
+ finish_children;
+ end;
+
+ begin
+ case def.stringtype of
+ st_shortstring:
+ begin
+ addstringdef('ShortString',cchartype,false,1);
+ end;
+ st_longstring:
+ begin
+{$ifdef cpu64bitaddr}
+ addstringdef('LongString',cchartype,false,8);
+{$else cpu64bitaddr}
+ addstringdef('LongString',cchartype,false,4);
+{$endif cpu64bitaddr}
+ end;
+ st_ansistring:
+ begin
+ addstringdef('AnsiString',cchartype,true,-1);
+ end;
+ st_unicodestring:
+ begin
+ addstringdef('UnicodeString',cwidechartype,true,-1);
+ end;
+ st_widestring:
+ begin
+ if not(tf_winlikewidestring in target_info.flags) then
+ addstringdef('WideString',cwidechartype,true,-1)
+ else
+ begin
+ { looks like a pwidechar (no idea about length location) }
+ append_entry(DW_TAG_pointer_type,false,[]);
+ append_labelentry_ref(DW_AT_type,def_dwarf_lab(cwidechartype));
+ finish_entry;
+ end;
+ end;
+ end;
+ end;
+
+ procedure TDebugInfoDwarf3.appenddef_file(list:TAsmList;def: tfiledef);
+ begin
+ if assigned(def.typesym) then
+ append_entry(DW_TAG_file_type,false,[
+ DW_AT_name,DW_FORM_string,symname(def.typesym)+#0,
+ DW_AT_byte_size,DW_FORM_data2,def.size
+ ])
+ else
+ append_entry(DW_TAG_file_type,false,[
+ DW_AT_byte_size,DW_FORM_data2,def.size
+ ]);
+ if tfiledef(def).filetyp=ft_typed then
+ append_labelentry_ref(DW_AT_type,def_dwarf_lab(tfiledef(def).typedfiledef));
+ finish_entry;
+ end;
+
+ procedure TDebugInfoDwarf3.appenddef_formal(list:TAsmList;def: tformaldef);
+ begin
+ append_entry(DW_TAG_unspecified_type,false,[
+ ]);
+ finish_entry;
+ end;
+
+ procedure TDebugInfoDwarf3.appenddef_object(list:TAsmList;def: tobjectdef);
+
+ procedure dostruct(tag: tdwarf_tag);
+ begin
+ if assigned(def.objname) then
+ append_entry(tag,true,[
+ DW_AT_name,DW_FORM_string,def.objrealname^+#0
+ ])
+ else
+ append_entry(DW_TAG_structure_type,true,[]);
+ append_attribute(DW_AT_byte_size,DW_FORM_udata,[tobjectsymtable(def.symtable).datasize]);
+ // The pointer to the class-structure is hidden. The debug-information
+ // does not contain an implicit pointer, but the data-adress is dereferenced here.
+ // In case of a nil-pointer, report the class as being unallocated.
+ append_block1(DW_AT_allocated,2);
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(ord(DW_OP_push_object_address)));
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(ord(DW_OP_deref)));
+ append_block1(DW_AT_data_location,2);
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(ord(DW_OP_push_object_address)));
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(ord(DW_OP_deref)));
+ finish_entry;
+ end;
+
+ procedure doimplicitpointer;
+ var
+ obj : tasmlabel;
+ begin
+ if not(tf_dwarf_only_local_labels in target_info.flags) then
+ current_asmdata.getdatalabel(obj)
+ else
+ current_asmdata.getaddrlabel(obj);
+ { implicit pointer }
+ append_entry(DW_TAG_pointer_type,false,[]);
+ append_labelentry_ref(DW_AT_type,obj);
+ finish_entry;
+
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_symbol.create(obj,0));
+ end;
+
+ procedure doparent(isinterface: boolean);
+ begin
+ if not assigned(def.childof) then
+ exit;
+
+ if isinterface then
+ begin
+ append_entry(DW_TAG_inheritance,false,[]);
+ end
+ else
+ begin
+ append_entry(DW_TAG_inheritance,false,[
+ DW_AT_accessibility,DW_FORM_data1,DW_ACCESS_public,
+ DW_AT_data_member_location,DW_FORM_block1,1+lengthuleb128(0)
+ ]);
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(ord(DW_OP_plus_uconst)));
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_uleb128bit(0));
+ end;
+ append_labelentry_ref(DW_AT_type,def_dwarf_lab(def.childof));
+ finish_entry;
+ end;
+
+ var
+ n: integer;
+
+ begin
+ case def.objecttype of
+ odt_cppclass,
+ odt_object:
+ begin
+ dostruct(DW_TAG_structure_type);
+ doparent(false);
+ end;
+ odt_interfacecom,
+ odt_interfacecorba,
+ odt_dispinterface:
+ begin
+ dostruct(DW_TAG_interface_type);
+ doparent(true);
+ end;
+ odt_helper,
+ odt_class:
+ begin
+ //dostruct(DW_TAG_class_type);
+ //doparent(false);
+ append_entry(DW_TAG_pointer_type,false,[]);
+ append_labelentry_ref(DW_AT_type,def_dwarf_class_struct_lab(def));
+ finish_entry;
+
+ append_object_struct(def,true,def.objrealname);
+ Exit;
+ end;
+ else
+ internalerror(200609171);
+ end;
+
+ { add implemented interfaces }
+ if assigned(def.ImplementedInterfaces) then
+ for n := 0 to def.ImplementedInterfaces.count-1 do
+ begin
+ append_entry(DW_TAG_inheritance,false,[]);
+ append_labelentry_ref(DW_AT_type,def_dwarf_lab(TImplementedInterface(def.ImplementedInterfaces[n]).IntfDef));
+ finish_entry;
+ end;
+
+ { add members }
+ def.symtable.symList.ForEachCall(@enum_membersyms_callback,nil);
+ finish_children;
+ end;
+
+ procedure TDebugInfoDwarf3.appenddef_set(list:TAsmList;def: tsetdef);
+ begin
+ appenddef_set_intern(list,def,true);
+ end;
+
+ procedure TDebugInfoDwarf3.appenddef_undefined(list:TAsmList;def: tundefineddef);
+ begin
+ { ??? can a undefined def have a typename ? }
+ if assigned(def.typesym) then
+ append_entry(DW_TAG_unspecified_type,false,[
+ DW_AT_name,DW_FORM_string,symname(def.typesym)+#0
+ ])
+ else
+ append_entry(DW_TAG_unspecified_type,false,[
+ ]);
+ finish_entry;
+ end;
+
+ procedure TDebugInfoDwarf3.appenddef_variant(list:TAsmList;def: tvariantdef);
+ const
+ VARIANTS: array[1..27] of record Value: Word; Name: String end = (
+ (value:0; name:''),
+ (value:1; name:''),
+ (value:2; name:'VSMALLINT'),
+ (value:3; name:'VINTEGER'),
+ (value:4; name:'VSINGLE'),
+ (value:5; name:'VDOUBLE'),
+ (value:6; name:'VCURRENCY'),
+ (value:7; name:'VDATE'),
+ (value:8; name:'VOLESTR'),
+ (value:9; name:'VDISPATCH'),
+ (value:10; name:'VERROR'),
+ (value:11; name:'VBOOLEAN'),
+ (value:12; name:''),
+ (value:13; name:'VUNKNOWN'),
+ (value:14; name:''),
+ (value:16; name:'VSHORTINT'),
+ (value:17; name:'VBYTE'),
+ (value:18; name:'VWORD'),
+ (value:19; name:'VLONGWORD'),
+ (value:20; name:'VINT64'),
+ (value:21; name:'VQWORD'),
+ (value:36; name:'VRECORD'),
+ (value:$48; name:''),
+ (value:$100; name:'VSTRING'),
+ (value:$101; name:'VANY'),
+ (value:$2000; name:'VARRAY'),
+ (value:$4000; name:'VPOINTER')
+ );
+ var
+ fs: tfieldvarsym;
+ lbl: tasmlabel;
+ idx: integer;
+ begin
+ { it could be done with DW_TAG_variant for the union part (if that info was available)
+ now we do it manually for variants (MWE) }
+
+ { struct }
+ append_entry(DW_TAG_structure_type,true,[
+ DW_AT_name,DW_FORM_string,'Variant'#0,
+ DW_AT_byte_size,DW_FORM_udata,vardatadef.size
+ ]);
+ finish_entry;
+
+ append_entry(DW_TAG_variant_part,true,[
+ ]);
+ current_asmdata.getaddrlabel(lbl);
+ append_labelentry_ref(DW_AT_discr,lbl);
+ finish_entry;
+
+ { discriminant }
+ fs := tfieldvarsym(vardatadef.symtable.Find('VTYPE'));
+ if (fs = nil) or (fs.typ <> fieldvarsym) then
+ internalerror(200609271);
+ current_asmdata.asmlists[al_dwarf_info].concat(tai_symbol.create(lbl,0));
+ appendsym_fieldvar(list,fs);
+
+ { variants }
+ for idx := Low(VARIANTS) to High(VARIANTS) do
+ begin
+ append_entry(DW_TAG_variant,true,[
+ DW_AT_discr_value,DW_FORM_udata,VARIANTS[idx].value
+ ]);
+ finish_entry;
+
+ if VARIANTS[idx].name <> '' then
+ begin
+ fs := tfieldvarsym(vardatadef.symtable.Find(VARIANTS[idx].name));
+ if (fs = nil) or (fs.typ <> fieldvarsym) then
+ internalerror(20060927200+idx);
+ appendsym_fieldvar(list,fs);
+ end;
+
+ finish_children; { variant }
+ end;
+
+
+ finish_children; { variant part }
+
+ finish_children; { struct }
+ end;
+
+ function TDebugInfoDwarf3.dwarf_version: Word;
+ begin
+ Result:=3;
+ end;
+
+ function TDebugInfoDwarf3.symdebugname(sym: tsym): String;
+ begin
+ Result:=sym.realname;
+ end;
+
+
+ { TDebugInfoDwarf4 }
+
+ function TDebugInfoDwarf4.dwarf_version: Word;
+ begin
+ Result:=4;
+ end;
+
+
+{****************************************************************************
+****************************************************************************}
+ const
+ dbg_dwarf2_info : tdbginfo =
+ (
+ id : dbg_dwarf2;
+ idtxt : 'DWARF2';
+ );
+
+ dbg_dwarf3_info : tdbginfo =
+ (
+ id : dbg_dwarf3;
+ idtxt : 'DWARF3';
+ );
+
+ dbg_dwarf4_info : tdbginfo =
+ (
+ id : dbg_dwarf4;
+ idtxt : 'DWARF4';
+ );
+
+
+initialization
+ RegisterDebugInfo(dbg_dwarf2_info,TDebugInfoDwarf2);
+ RegisterDebugInfo(dbg_dwarf3_info,TDebugInfoDwarf3);
+ RegisterDebugInfo(dbg_dwarf4_info,TDebugInfoDwarf4);
+
+end.
diff --git a/closures/compiler/dbgstabs.pas b/closures/compiler/dbgstabs.pas
new file mode 100644
index 0000000000..625a58d6a8
--- /dev/null
+++ b/closures/compiler/dbgstabs.pas
@@ -0,0 +1,1732 @@
+{
+ Copyright (c) 2003-2004 by Peter Vreman and Florian Klaempfl
+
+ This units contains support for STABS debug info generation
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit dbgstabs;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cclasses,
+ dbgbase,cgbase,
+ symtype,symdef,symsym,symtable,symbase,
+ aasmtai,aasmdata;
+
+ const
+ { stab types }
+ N_GSYM = $20;
+ N_STSYM = 38; { initialized const }
+ N_LCSYM = 40; { non initialized variable}
+ N_Function = $24; { function or const }
+ N_TextLine = $44;
+ N_DataLine = $46;
+ N_BssLine = $48;
+ N_RSYM = $40; { register variable }
+ N_LSYM = $80;
+ N_tsym = 160;
+ N_SourceFile = $64;
+{ APPLE LOCAL N_OSO: This is the stab that associated the .o file with the
+ N_SO stab, in the case where debug info is mostly stored in the .o file. }
+ N_OSO = $66;
+ N_IncludeFile = $84;
+ N_BINCL = $82;
+ N_EINCL = $A2;
+ N_LBRAC = $C0;
+ N_EXCL = $C2;
+ N_RBRAC = $E0;
+
+ type
+ TDebugInfoStabs=class(TDebugInfo)
+ private
+ writing_def_stabs : boolean;
+ global_stab_number : word;
+ vardatadef: trecorddef;
+ { tsym writing }
+ function sym_var_value(const s:string;arg:pointer):string;
+ function sym_stabstr_evaluate(sym:tsym;const s:string;const vars:array of string):ansistring;
+ procedure write_sym_stabstr(list:TAsmList;sym:tsym;const ss:ansistring);
+ { tdef writing }
+ function def_stab_number(def:tdef):string;
+ function def_stab_classnumber(def:tabstractrecorddef):string;
+ function def_var_value(const s:string;arg:pointer):string;
+ function def_stabstr_evaluate(def:tdef;const s:string;const vars:array of string):ansistring;
+ procedure write_def_stabstr(list:TAsmList;def:tdef;const ss:ansistring);
+ procedure field_add_stabstr(p:TObject;arg:pointer);
+ procedure method_add_stabstr(p:TObject;arg:pointer);
+ procedure field_write_defs(p:TObject;arg:pointer);
+ function get_enum_defstr(def: tenumdef; lowerbound: longint): ansistring;
+ function get_appendsym_paravar_reg(sym:tparavarsym;const typ,stabstr:string;reg: tregister): ansistring;
+ protected
+ procedure appendsym_staticvar(list:TAsmList;sym:tstaticvarsym);override;
+ procedure appendsym_paravar(list:TAsmList;sym:tparavarsym);override;
+ procedure appendsym_localvar(list:TAsmList;sym:tlocalvarsym);override;
+ procedure appendsym_fieldvar(list:TAsmList;sym:tfieldvarsym);override;
+ procedure appendsym_const(list:TAsmList;sym:tconstsym);override;
+ procedure appendsym_type(list:TAsmList;sym:ttypesym);override;
+ procedure appendsym_label(list:TAsmList;sym:tlabelsym);override;
+ procedure beforeappenddef(list:TAsmList;def:tdef);override;
+ procedure appenddef_ord(list:TAsmList;def:torddef);override;
+ procedure appenddef_float(list:TAsmList;def:tfloatdef);override;
+ procedure appenddef_file(list:TAsmList;def:tfiledef);override;
+ procedure appenddef_enum(list:TAsmList;def:tenumdef);override;
+ procedure appenddef_array(list:TAsmList;def:tarraydef);override;
+ procedure appenddef_record(list:TAsmList;def:trecorddef);override;
+ procedure appenddef_object(list:TAsmList;def:tobjectdef);override;
+ procedure appenddef_pointer(list:TAsmList;def:tpointerdef);override;
+ procedure appenddef_string(list:TAsmList;def:tstringdef);override;
+ procedure appenddef_procvar(list:TAsmList;def:tprocvardef);override;
+ procedure appenddef_variant(list:TAsmList;def:tvariantdef);override;
+ procedure appenddef_set(list:TAsmList;def:tsetdef);override;
+ procedure appenddef_formal(list:TAsmList;def:tformaldef);override;
+ procedure appenddef_undefined(list:TAsmList;def: tundefineddef);override;
+ procedure appendprocdef(list:TAsmList;def:tprocdef);override;
+ public
+ procedure inserttypeinfo;override;
+ procedure insertmoduleinfo;override;
+ procedure insertlineinfo(list:TAsmList);override;
+ procedure referencesections(list:TAsmList);override;
+
+ constructor Create;override;
+ end;
+
+
+implementation
+
+ uses
+ SysUtils,cutils,cfileutl,
+ systems,globals,globtype,verbose,constexp,
+ symconst,defutil,
+ cpuinfo,cpubase,paramgr,
+ aasmbase,procinfo,
+ finput,fmodule,ppu;
+
+ function GetSymName(Sym : TSymEntry) : string;
+ begin
+ if Not (cs_stabs_preservecase in current_settings.globalswitches) then
+ result := Sym.Name
+ else
+ result := Sym.RealName;
+{$ifdef avr}
+ if target_asm.id=as_gas then
+ result:=ReplaceForbiddenChars(result);
+{$endif avr}
+ end;
+
+ function GetSymTableName(SymTable : TSymTable) : string;
+ begin
+ if Not (cs_stabs_preservecase in current_settings.globalswitches) then
+ result := SymTable.Name^
+ else
+ result := SymTable.RealName^;
+{$ifdef avr}
+ if target_asm.id=as_gas then
+ result:=ReplaceForbiddenChars(result);
+{$endif avr}
+ end;
+
+ const
+ memsizeinc = 512;
+
+ tagtypes = [
+ recorddef,
+ variantdef,
+ enumdef,
+ stringdef,
+ filedef,
+ objectdef
+ ];
+
+ type
+ get_var_value_proc=function(const s:string;arg:pointer):string of object;
+
+
+ function string_evaluate(s:string;get_var_value:get_var_value_proc;get_var_value_arg:pointer;const vars:array of string):ansistring;
+ (*
+ S contains a prototype of a result. Stabstr_evaluate will expand
+ variables and parameters.
+
+ Output is s in ASCIIZ format, with the following expanded:
+
+ ${varname} - The variable name is expanded.
+ $n - The parameter n is expanded.
+ $$ - Is expanded to $
+ *)
+
+ const maxvalue=9;
+ maxdata=1023;
+
+ var i,j:byte;
+ varname:string[63];
+ varno,varcounter:byte;
+ varvalues:array[0..9] of pshortstring;
+ {1 kb of parameters is the limit. 256 extra bytes are allocated to
+ ensure buffer integrity.}
+ varvaluedata:array[0..maxdata+256] of char;
+ varptr:Pchar;
+ varidx : byte;
+ len:longint;
+ r:Pchar;
+
+ begin
+ {Two pass approach, first, calculate the length and receive variables.}
+ i:=1;
+ len:=0;
+ varcounter:=0;
+ varptr:=@varvaluedata[0];
+ while i<=length(s) do
+ begin
+ if (s[i]='$') and (i<length(s)) then
+ begin
+ if s[i+1]='$' then
+ begin
+ inc(len);
+ inc(i);
+ end
+ else if (s[i+1]='{') and (length(s)>2) and (i<length(s)-2) then
+ begin
+ varname:='';
+ inc(i,2);
+ repeat
+ inc(varname[0]);
+ varname[length(varname)]:=s[i];
+ s[i]:=char(varcounter);
+ inc(i);
+ until s[i]='}';
+ varvalues[varcounter]:=pshortstring(varptr);
+ if varptr>@varvaluedata[maxdata] then
+ internalerrorproc(200411152);
+ pshortstring(varptr)^:=get_var_value(varname,get_var_value_arg);
+ inc(len,length(pshortstring(varptr)^));
+ inc(varptr,length(pshortstring(varptr)^)+1);
+ inc(varcounter);
+ end
+ else if s[i+1] in ['1'..'9'] then
+ begin
+ varidx:=byte(s[i+1])-byte('1');
+ if varidx>high(vars) then
+ internalerror(200509263);
+ inc(len,length(vars[varidx]));
+ inc(i);
+ end;
+ end
+ else
+ inc(len);
+ inc(i);
+ end;
+
+ {Second pass, writeout result.}
+ setlength(result,len);
+ r:=pchar(result);
+ i:=1;
+ while i<=length(s) do
+ begin
+ if (s[i]='$') and (i<length(s)) then
+ begin
+ if s[i+1]='$' then
+ begin
+ r^:='$';
+ inc(r);
+ inc(i);
+ end
+ else if (s[i+1]='{') and (length(s)>2) and (i<length(s)-2) then
+ begin
+ varname:='';
+ inc(i,2);
+ varno:=byte(s[i]);
+ repeat
+ inc(i);
+ until s[i]='}';
+ for j:=1 to length(varvalues[varno]^) do
+ begin
+ r^:=varvalues[varno]^[j];
+ inc(r);
+ end;
+ end
+ else if s[i+1] in ['0'..'9'] then
+ begin
+ for j:=1 to length(vars[byte(s[i+1])-byte('1')]) do
+ begin
+ r^:=vars[byte(s[i+1])-byte('1')][j];
+ inc(r);
+ end;
+ inc(i);
+ end
+ end
+ else
+ begin
+ r^:=s[i];
+ inc(r);
+ end;
+ inc(i);
+ end;
+ { verify that the length was correct }
+ if r^<>#0 then
+ internalerror(200802031);
+ end;
+
+
+{****************************************************************************
+ TDef support
+****************************************************************************}
+
+ function TDebugInfoStabs.def_stab_number(def:tdef):string;
+ begin
+ { procdefs only need a number, mark them as already written
+ so they won't be written implicitly }
+ if (def.typ=procdef) then
+ def.dbg_state:=dbg_state_written;
+
+ { Stab must already be written, or we must be busy writing it }
+ if writing_def_stabs and
+ not(def.dbg_state in [dbg_state_writing,dbg_state_written,dbg_state_queued]) then
+ internalerror(200403091);
+
+ { Keep track of used stabs, this info is only useful for stabs
+ referenced by the symbols. Definitions will always include all
+ required stabs }
+ if def.dbg_state=dbg_state_unused then
+ begin
+ def.dbg_state:=dbg_state_used;
+ deftowritelist.Add(def);
+ end;
+ { Need a new number? }
+ if def.stab_number=0 then
+ begin
+ inc(global_stab_number);
+ { classes require 2 numbers }
+ if is_class(def) then
+ inc(global_stab_number);
+ def.stab_number:=global_stab_number;
+ if global_stab_number>=defnumberlist.count then
+ defnumberlist.count:=global_stab_number+250;
+ defnumberlist[global_stab_number]:=def;
+ end;
+ result:=tostr(def.stab_number);
+ end;
+
+
+ function TDebugInfoStabs.def_stab_classnumber(def:tabstractrecorddef):string;
+ begin
+ if def.stab_number=0 then
+ def_stab_number(def);
+ if (def.typ=objectdef) and (tobjectdef(def).objecttype=odt_class) then
+ result:=tostr(def.stab_number-1)
+ else
+ result:=tostr(def.stab_number);
+ end;
+
+
+ function TDebugInfoStabs.def_var_value(const s:string;arg:pointer):string;
+ var
+ def : tdef;
+ begin
+ def:=tdef(arg);
+ result:='';
+ if s='numberstring' then
+ result:=def_stab_number(def)
+ else if s='sym_name' then
+ begin
+ if assigned(def.typesym) then
+ result:=GetSymName(Ttypesym(def.typesym));
+ end
+ else if s='N_LSYM' then
+ result:=tostr(N_LSYM)
+ else if s='savesize' then
+ result:=tostr(def.size);
+ end;
+
+
+ function TDebugInfoStabs.def_stabstr_evaluate(def:tdef;const s:string;const vars:array of string):ansistring;
+ begin
+ result:=string_evaluate(s,@def_var_value,def,vars);
+ end;
+
+
+ procedure TDebugInfoStabs.field_add_stabstr(p:TObject;arg:pointer);
+ var
+ spec : string[3];
+ varsize : asizeint;
+ newss : ansistring;
+ ss : pansistring absolute arg;
+ begin
+ if (tsym(p).visibility=vis_hidden) then
+ exit;
+ { static variables from objects are like global objects }
+ if (Tsym(p).typ=fieldvarsym) and
+ not(sp_static in Tsym(p).symoptions) then
+ begin
+ case tsym(p).visibility of
+ vis_private,
+ vis_strictprivate :
+ spec:='/0';
+ vis_protected,
+ vis_strictprotected :
+ spec:='/1';
+ else
+ spec:='';
+ end;
+ if (tabstractrecordsymtable(tsym(p).owner).usefieldalignment<>bit_alignment) then
+ begin
+ varsize:=tfieldvarsym(p).vardef.size;
+ { open arrays made overflows !! }
+ { how can a record/object/class contain an open array? (JM) }
+{$ifdef cpu16bitaddr}
+ if varsize>$fff then
+ varsize:=$fff;
+{$else cpu16bitaddr}
+ if varsize>$fffffff then
+ varsize:=$fffffff;
+{$endif cpu16bitaddr}
+ newss:=def_stabstr_evaluate(nil,'$1:$2,$3,$4;',[GetSymName(tfieldvarsym(p)),
+ spec+def_stab_number(tfieldvarsym(p).vardef),
+ tostr(TConstExprInt(tfieldvarsym(p).fieldoffset)*8),tostr(varsize*8)])
+ end
+ else
+ newss:=def_stabstr_evaluate(nil,'$1:$2,$3,$4;',[GetSymName(tfieldvarsym(p)),
+ spec+def_stab_number(tfieldvarsym(p).vardef),
+ tostr(TConstExprInt(tfieldvarsym(p).fieldoffset)),tostr(tfieldvarsym(p).vardef.packedbitsize)]);
+ ss^:=ss^+newss;
+ end;
+ end;
+
+
+ procedure TDebugInfoStabs.method_add_stabstr(p:TObject;arg:pointer);
+ var
+ virtualind,argnames : string;
+ pd : tprocdef;
+ lindex : longint;
+ arglength : byte;
+ sp : char;
+ i : integer;
+ parasym : tparavarsym;
+ newss : ansistring;
+ ss : pansistring absolute arg;
+ begin
+ if tsym(p).typ = procsym then
+ begin
+ pd :=tprocdef(tprocsym(p).ProcdefList[0]);
+ if (po_virtualmethod in pd.procoptions) and
+ not is_objectpascal_helper(pd.struct) then
+ begin
+ lindex := pd.extnumber;
+ {doesnt seem to be necessary
+ lindex := lindex or $80000000;}
+ virtualind := '*'+tostr(lindex)+';'+def_stab_classnumber(pd.struct)+';'
+ end
+ else
+ virtualind := '.';
+
+ { used by gdbpas to recognize constructor and destructors }
+ if (pd.proctypeoption=potype_constructor) then
+ argnames:='__ct__'
+ else if (pd.proctypeoption=potype_destructor) then
+ argnames:='__dt__'
+ else
+ argnames := '';
+
+ { arguments are not listed here }
+ {we don't need another definition}
+ for i:=0 to pd.paras.count-1 do
+ begin
+ parasym:=tparavarsym(pd.paras[i]);
+ if Parasym.vardef.typ = formaldef then
+ begin
+ case Parasym.varspez of
+ vs_var :
+ argnames := argnames+'3var';
+ vs_const :
+ argnames:=argnames+'5const';
+ vs_out :
+ argnames:=argnames+'3out';
+ vs_constref :
+ argnames:=argnames+'8constref';
+ end;
+ end
+ else
+ begin
+ { if the arg definition is like (v: ^byte;..
+ there is no sym attached to data !!! }
+ if assigned(Parasym.vardef.typesym) then
+ begin
+ arglength := length(GetSymName(Parasym.vardef.typesym));
+ argnames := argnames + tostr(arglength)+GetSymName(Parasym.vardef.typesym);
+ end
+ else
+ argnames:=argnames+'11unnamedtype';
+ end;
+ end;
+ { here 2A must be changed for private and protected }
+ { 0 is private 1 protected and 2 public }
+ case tsym(p).visibility of
+ vis_private,
+ vis_strictprivate :
+ sp:='0';
+ vis_protected,
+ vis_strictprotected :
+ sp:='1'
+ else
+ sp:='2';
+ end;
+ newss:=def_stabstr_evaluate(nil,'$1::$2=##$3;:$4;$5A$6;',[GetSymName(tsym(p)),def_stab_number(pd),
+ def_stab_number(pd.returndef),argnames,sp,
+ virtualind]);
+ ss^:=ss^+newss;
+ end;
+ end;
+
+
+ procedure TDebugInfoStabs.field_write_defs(p:TObject;arg:pointer);
+ begin
+ if (Tsym(p).typ=fieldvarsym) and
+ not(sp_static in Tsym(p).symoptions) then
+ appenddef(TAsmList(arg),tfieldvarsym(p).vardef);
+ end;
+
+
+ procedure TDebugInfoStabs.write_def_stabstr(list:TAsmList;def:tdef;const ss:ansistring);
+ var
+ stabchar : string[2];
+ symname : string[20];
+ st : ansistring;
+ begin
+ { type prefix }
+ if def.typ in tagtypes then
+ stabchar := 'Tt'
+ else
+ stabchar := 't';
+ { in case of writing the class record structure, we always have to
+ use the class name (so it refers both to the struct and the
+ pointer to the struct), otherwise gdb crashes (see tests/webtbs/tw9766.pp) }
+ if is_class(def) and
+ tobjectdef(def).writing_class_record_dbginfo then
+ st:=def_stabstr_evaluate(def,'"${sym_name}:$1$2=',[stabchar,def_stab_classnumber(tobjectdef(def))])
+ else
+ begin
+ { Type names for types defined in the current unit are already written in
+ the typesym }
+ if (def.owner.symtabletype=globalsymtable) and
+ not(def.owner.iscurrentunit) then
+ symname:='${sym_name}'
+ else
+ symname:='';
+ st:=def_stabstr_evaluate(def,'"'+symname+':$1$2=',[stabchar,def_stab_number(def)]);
+ end;
+ st:=st+ss;
+ { line info is set to 0 for all defs, because the def can be in another
+ unit and then the linenumber is invalid in the current sourcefile }
+ st:=st+def_stabstr_evaluate(def,'",${N_LSYM},0,0,0',[]);
+ { add to list }
+ list.concat(Tai_stab.create_ansistr(stab_stabs,st));
+ end;
+
+
+ procedure TDebugInfoStabs.appenddef_string(list:TAsmList;def:tstringdef);
+ var
+ bytest,charst,longst : string;
+ ss : ansistring;
+ slen : longint;
+ begin
+ ss:='';
+ case def.stringtype of
+ st_shortstring:
+ begin
+ { fix length of openshortstring }
+ slen:=def.len;
+ if slen=0 then
+ slen:=255;
+ charst:=def_stab_number(cchartype);
+ bytest:=def_stab_number(u8inttype);
+ ss:=def_stabstr_evaluate(def,'s$1length:$2,0,8;st:ar$2;1;$3;$4,8,$5;;',
+ [tostr(slen+1),bytest,tostr(slen),charst,tostr(slen*8)]);
+ end;
+ st_longstring:
+ begin
+ charst:=def_stab_number(cchartype);
+ bytest:=def_stab_number(u8inttype);
+ longst:=def_stab_number(u32inttype);
+ ss:=def_stabstr_evaluate(def,'s$1length:$2,0,32;dummy:$6,32,8;st:ar$2;1;$3;$4,40,$5;;',
+ [tostr(def.len+5),longst,tostr(def.len),charst,tostr(def.len*8),bytest]);
+ end;
+ st_ansistring:
+ begin
+ { looks like a pchar }
+ ss:='*'+def_stab_number(cchartype);
+ end;
+ st_unicodestring,
+ st_widestring:
+ begin
+ { looks like a pwidechar }
+ ss:='*'+def_stab_number(cwidechartype);
+ end;
+ end;
+ write_def_stabstr(list,def,ss);
+ end;
+
+
+ function TDebugInfoStabs.get_enum_defstr(def: tenumdef; lowerbound: longint): ansistring;
+ var
+ i: longint;
+ p: tenumsym;
+ begin
+ { we can specify the size with @s<size>; prefix PM }
+ if def.size <> std_param_align then
+ result:='@s'+tostr(def.size*8)+';e'
+ else
+ result:='e';
+ { the if-test is required because pred(def.minval) might overflow;
+ the longint() typecast should be safe because stabs is not
+ supported for 64 bit targets }
+ if (def.minval<>lowerbound) then
+ for i:=lowerbound to pred(longint(def.minval)) do
+ result:=result+'<invalid>:'+tostr(i)+',';
+
+ for i := 0 to def.symtable.SymList.Count - 1 do
+ begin
+ p := tenumsym(def.symtable.SymList[i]);
+ if p.value<def.minval then
+ continue
+ else
+ if p.value>def.maxval then
+ break;
+ result:=result+GetSymName(p)+':'+tostr(p.value)+',';
+ end;
+ { the final ',' is required to have a valid stabs }
+ result:=result+';';
+ end;
+
+ procedure TDebugInfoStabs.appenddef_enum(list:TAsmList;def:tenumdef);
+ begin
+ write_def_stabstr(list,def,get_enum_defstr(def,def.minval));
+ end;
+
+
+ procedure TDebugInfoStabs.appenddef_ord(list:TAsmList;def:torddef);
+ var
+ ss : ansistring;
+ begin
+ ss:='';
+ if cs_gdb_valgrind in current_settings.globalswitches then
+ begin
+ case def.ordtype of
+ uvoid :
+ ss:=def_stab_number(def);
+ pasbool8,
+ pasbool16,
+ pasbool32,
+ pasbool64,
+ bool8bit,
+ bool16bit,
+ bool32bit,
+ bool64bit :
+ ss:=def_stabstr_evaluate(def,'r${numberstring};0;255;',[]);
+ u32bit,
+ s64bit,
+ u64bit :
+ ss:=def_stabstr_evaluate(def,'r${numberstring};0;-1;',[]);
+ else
+ ss:=def_stabstr_evaluate(def,'r${numberstring};$1;$2;',[tostr(longint(def.low.svalue)),tostr(longint(def.high.svalue))]);
+ end;
+ end
+ else
+ begin
+ case def.ordtype of
+ uvoid :
+ ss:=def_stab_number(def);
+ uchar :
+ ss:='-20;';
+ uwidechar :
+ ss:='-30;';
+ pasbool8,
+ bool8bit :
+ ss:='-21;';
+ pasbool16,
+ bool16bit :
+ ss:='-22;';
+ pasbool32,
+ bool32bit :
+ ss:='-23;';
+ pasbool64,
+ bool64bit :
+ { no clue if this is correct (FK) }
+ ss:='-23;';
+ u64bit :
+ ss:='-32;';
+ s64bit :
+ ss:='-31;';
+ {u32bit : result:=def_stab_number(s32inttype)+';0;-1;'); }
+ else
+ ss:=def_stabstr_evaluate(def,'r${numberstring};$1;$2;',[tostr(longint(def.low.svalue)),tostr(longint(def.high.svalue))]);
+ end;
+ end;
+ write_def_stabstr(list,def,ss);
+ end;
+
+
+ procedure TDebugInfoStabs.appenddef_float(list:TAsmList;def:tfloatdef);
+ var
+ ss : ansistring;
+ begin
+ ss:='';
+ case def.floattype of
+ s32real,
+ s64real,
+ s80real,
+ sc80real:
+ ss:=def_stabstr_evaluate(def,'r$1;${savesize};0;',[def_stab_number(s32inttype)]);
+ s64currency,
+ s64comp:
+ ss:=def_stabstr_evaluate(def,'r$1;-${savesize};0;',[def_stab_number(s32inttype)]);
+ else
+ internalerror(200509261);
+ end;
+ write_def_stabstr(list,def,ss);
+ end;
+
+
+ procedure TDebugInfoStabs.appenddef_file(list:TAsmList;def:tfiledef);
+ var
+ ss : ansistring;
+ begin
+{$ifdef cpu64bitaddr}
+ ss:=def_stabstr_evaluate(def,'s${savesize}HANDLE:$1,0,32;MODE:$1,32,32;RECSIZE:$2,64,64;'+
+ '_PRIVATE:ar$1;1;64;$3,128,256;USERDATA:ar$1;1;16;$3,384,128;'+
+ 'NAME:ar$1;0;255;$4,512,2048;;',[def_stab_number(s32inttype),
+ def_stab_number(s64inttype),
+ def_stab_number(u8inttype),
+ def_stab_number(cchartype)]);
+{$else cpu64bitaddr}
+ ss:=def_stabstr_evaluate(def,'s${savesize}HANDLE:$1,0,32;MODE:$1,32,32;RECSIZE:$1,64,32;'+
+ '_PRIVATE:ar$1;1;32;$3,96,256;USERDATA:ar$1;1;16;$2,352,128;'+
+ 'NAME:ar$1;0;255;$3,480,2048;;',[def_stab_number(s32inttype),
+ def_stab_number(u8inttype),
+ def_stab_number(cchartype)]);
+{$endif cpu64bitaddr}
+ write_def_stabstr(list,def,ss);
+ end;
+
+
+ procedure TDebugInfoStabs.appenddef_record(list:TAsmList;def:trecorddef);
+ var
+ ss : ansistring;
+ begin
+ ss:='s'+tostr(def.size);
+ def.symtable.SymList.ForEachCall(@field_add_stabstr,@ss);
+ ss[length(ss)]:=';';
+ write_def_stabstr(list,def,ss);
+ end;
+
+
+ procedure TDebugInfoStabs.appenddef_object(list:TAsmList;def:tobjectdef);
+
+ procedure do_write_object(list:TAsmList;def:tobjectdef);
+ var
+ ss : ansistring;
+ anc : tobjectdef;
+ begin
+ ss:='';
+ { Write the invisible pointer for the class? }
+ if (def.objecttype=odt_class) and
+ (not def.writing_class_record_dbginfo) then
+ begin
+ ss:='*'+def_stab_classnumber(def);
+ write_def_stabstr(list,def,ss);
+ exit;
+ end;
+
+ ss:='s'+tostr(tobjecTSymtable(def.symtable).datasize);
+ if assigned(def.childof) then
+ begin
+ {only one ancestor not virtual, public, at base offset 0 }
+ { !1 , 0 2 0 , }
+ ss:=ss+'!1,020,'+def_stab_classnumber(def.childof)+';';
+ end;
+
+ {virtual table to implement yet}
+ def.symtable.symList.ForEachCall(@field_add_stabstr,@ss);
+
+ if (oo_has_vmt in def.objectoptions) and
+ (
+ not assigned(def.childof) or
+ not(oo_has_vmt in def.childof.objectoptions)
+ ) then
+ ss:=ss+'$vf'+def_stab_classnumber(def)+':'+def_stab_number(vmtarraytype)+','+tostr(def.vmt_offset*8)+';';
+ def.symtable.symList.ForEachCall(@method_add_stabstr,@ss);
+ if (oo_has_vmt in def.objectoptions) then
+ begin
+ anc := def;
+ while assigned(anc.childof) and (oo_has_vmt in anc.childof.objectoptions) do
+ anc := anc.childof;
+ { just in case anc = self }
+ ss:=ss+';~%'+def_stab_classnumber(anc)+';';
+ end
+ else
+ ss:=ss+';';
+ write_def_stabstr(list,def,ss);
+ end;
+
+ var
+ oldtypesym : tsym;
+ begin
+ { classes require special code to write the record and the invisible pointer }
+ if is_class(def) then
+ begin
+ { Write the record class itself }
+ tobjectdef(def).writing_class_record_dbginfo:=true;
+ do_write_object(list,def);
+ tobjectdef(def).writing_class_record_dbginfo:=false;
+ { Write the invisible pointer class }
+ oldtypesym:=def.typesym;
+ def.typesym:=nil;
+ do_write_object(list,def);
+ def.typesym:=oldtypesym;
+ end
+ else
+ do_write_object(list,def);
+ { VMT symbol }
+ if (oo_has_vmt in def.objectoptions) and
+ assigned(def.owner) and
+ assigned(def.owner.name) then
+ list.concat(Tai_stab.create_ansistr(stab_stabs,ansistring('"vmt_')+GetSymTableName(def.owner)+tobjectdef(def).objname^+':S'+
+ def_stab_number(vmttype)+'",'+tostr(N_STSYM)+',0,0,'+ansistring(tobjectdef(def).vmt_mangledname)));
+ end;
+
+
+ procedure TDebugInfoStabs.appenddef_variant(list:TAsmList;def:tvariantdef);
+ var
+ ss : ansistring;
+ begin
+ if not assigned(vardatadef) then
+ exit;
+
+ ss:='s'+tostr(vardatadef.size);
+ vardatadef.symtable.SymList.ForEachCall(@field_add_stabstr,@ss);
+ ss[length(ss)]:=';';
+ write_def_stabstr(list,def,ss);
+ end;
+
+
+ procedure TDebugInfoStabs.appenddef_pointer(list:TAsmList;def:tpointerdef);
+ var
+ ss : ansistring;
+ begin
+ ss:='*'+def_stab_number(tpointerdef(def).pointeddef);
+ write_def_stabstr(list,def,ss);
+ end;
+
+
+ procedure TDebugInfoStabs.appenddef_set(list:TAsmList;def:tsetdef);
+ var
+ st,
+ ss : ansistring;
+ elementdefstabnr: string;
+ begin
+ { ugly hack: create a temporary subrange type if the lower bound of
+ the set's element type is not a multiple of 8 (because we store them
+ as if the lower bound is a multiple of 8) }
+ if (def.setbase<>get_min_value(def.elementdef)) then
+ begin
+ { allocate a def number }
+ inc(global_stab_number);
+ elementdefstabnr:=tostr(global_stab_number);
+ { anonymous subrange def }
+ st:='":t'+elementdefstabnr+'=';
+ if (def.elementdef.typ = enumdef) then
+ st:=st+get_enum_defstr(tenumdef(def.elementdef),def.setbase)
+ else
+ st:=st+def_stabstr_evaluate(def.elementdef,'r'+elementdefstabnr+';$1;$2;',[tostr(longint(def.setbase)),tostr(longint(get_max_value(def.elementdef).svalue))]);
+ st:=st+'",'+tostr(N_LSYM)+',0,0,0';
+ { add to list }
+ list.concat(Tai_stab.create_ansistr(stab_stabs,st));
+ end
+ else
+ elementdefstabnr:=def_stab_number(def.elementdef);
+ ss:=def_stabstr_evaluate(def,'@s$1;S$2',[tostr(def.size*8),elementdefstabnr]);
+ write_def_stabstr(list,def,ss);
+ end;
+
+
+ procedure TDebugInfoStabs.appenddef_formal(list:TAsmList;def:tformaldef);
+ var
+ ss : ansistring;
+ begin
+ ss:=def_stabstr_evaluate(def,'${numberstring};',[]);
+ write_def_stabstr(list,def,ss);
+ end;
+
+
+ procedure TDebugInfoStabs.appenddef_array(list:TAsmList;def:tarraydef);
+ var
+ tempstr: shortstring;
+ ss : ansistring;
+ begin
+ if not is_packed_array(def) then
+ begin
+ tempstr:='ar$1;$2;$3;$4';
+ if is_dynamic_array(def) then
+ tempstr:='*'+tempstr;
+ ss:=def_stabstr_evaluate(def,tempstr,[def_stab_number(tarraydef(def).rangedef),
+ tostr(tarraydef(def).lowrange),tostr(tarraydef(def).highrange),def_stab_number(tarraydef(def).elementdef)])
+ end
+ else
+ begin
+ // the @P seems to be ignored by gdb
+ tempstr:=def_stabstr_evaluate(tarraydef(def).rangedef,'r${numberstring};$1;$2;',
+ [tostr(tarraydef(def).lowrange),tostr(tarraydef(def).highrange)]);
+ // will only show highrange-lowrange+1 bits in gdb
+ ss:=def_stabstr_evaluate(def,'@s$1;@S;S$2',
+ [tostr(TConstExprInt(tarraydef(def).elepackedbitsize) * tarraydef(def).elecount),tempstr]);
+ end;
+ write_def_stabstr(list,def,ss);
+ end;
+
+
+ procedure TDebugInfoStabs.appenddef_procvar(list:TAsmList;def:tprocvardef);
+ var
+ ss : ansistring;
+ begin
+ ss:='*f'+def_stab_number(tprocvardef(def).returndef);
+ write_def_stabstr(list,def,ss);
+ end;
+
+
+ procedure TDebugInfoStabs.appenddef_undefined(list:TAsmList;def:tundefineddef);
+ var
+ ss : ansistring;
+ begin
+ ss:=def_stabstr_evaluate(def,'${numberstring};',[]);
+ write_def_stabstr(list,def,ss);
+ end;
+
+
+ procedure TDebugInfoStabs.beforeappenddef(list:TAsmList;def:tdef);
+ var
+ anc : tobjectdef;
+ i : longint;
+ begin
+ { write dependencies first }
+ case def.typ of
+ stringdef :
+ begin
+ if tstringdef(def).stringtype in [st_widestring,st_unicodestring] then
+ appenddef(list,cwidechartype)
+ else
+ begin
+ appenddef(list,cchartype);
+ appenddef(list,u8inttype);
+ end;
+ end;
+ floatdef :
+ appenddef(list,s32inttype);
+ filedef :
+ begin
+ appenddef(list,s32inttype);
+{$ifdef cpu64bitaddr}
+ appenddef(list,s64inttype);
+{$endif cpu64bitaddr}
+ appenddef(list,u8inttype);
+ appenddef(list,cchartype);
+ end;
+ classrefdef :
+ appenddef(list,pvmttype);
+ pointerdef :
+ appenddef(list,tpointerdef(def).pointeddef);
+ setdef :
+ appenddef(list,tsetdef(def).elementdef);
+ procvardef :
+ begin
+ appenddef(list,tprocvardef(def).returndef);
+ if assigned(tprocvardef(def).parast) then
+ write_symtable_defs(list,tprocvardef(def).parast);
+ end;
+ procdef :
+ begin
+ appenddef(list,tprocdef(def).returndef);
+ if assigned(tprocdef(def).parast) then
+ write_symtable_defs(list,tprocdef(def).parast);
+ if assigned(tprocdef(def).localst) and
+ (tprocdef(def).localst.symtabletype=localsymtable) then
+ write_symtable_defs(list,tprocdef(def).localst);
+ end;
+ arraydef :
+ begin
+ appenddef(list,tarraydef(def).rangedef);
+ appenddef(list,tarraydef(def).elementdef);
+ end;
+ recorddef :
+ trecorddef(def).symtable.symList.ForEachCall(@field_write_defs,list);
+ enumdef :
+ if assigned(tenumdef(def).basedef) then
+ appenddef(list,tenumdef(def).basedef);
+ objectdef :
+ begin
+ { make sure we don't write child classdefs before their parent }
+ { classdefs, because this crashes gdb }
+ anc:=tobjectdef(def);
+ while assigned(anc.childof) do
+ begin
+ anc:=anc.childof;
+ if (anc.dbg_state=dbg_state_writing) then
+ { happens in case a field of a parent is of the (forward }
+ { defined) child type }
+ begin
+ { We don't explicitly requeue it, but the fact that }
+ { a child type was used in a parent before the child }
+ { type was fully defined means that it was forward }
+ { declared, and will still be encountered later (it }
+ { cannot have been declared in another unit, because }
+ { then this and that other unit would depend on }
+ { eachother's interface) }
+ { Setting the state to queued however allows us to }
+ { get the def number already without an IE }
+ def.dbg_state:=dbg_state_queued;
+ exit;
+ end;
+ end;
+ appenddef(list,vmtarraytype);
+ if assigned(tobjectdef(def).ImplementedInterfaces) then
+ for i:=0 to tobjectdef(def).ImplementedInterfaces.Count-1 do
+ appenddef(list,TImplementedInterface(tobjectdef(def).ImplementedInterfaces[i]).IntfDef);
+ { first the parents }
+ anc:=tobjectdef(def);
+ while assigned(anc.childof) do
+ begin
+ anc:=anc.childof;
+ appenddef(list,anc);
+ if assigned(anc.ImplementedInterfaces) then
+ for i:=0 to anc.ImplementedInterfaces.Count-1 do
+ appenddef(list,TImplementedInterface(anc.ImplementedInterfaces[i]).IntfDef);
+ end;
+ tobjectdef(def).symtable.symList.ForEachCall(@field_write_defs,list);
+ end;
+ end;
+ end;
+
+
+ procedure TDebugInfoStabs.appendprocdef(list:TAsmList;def:tprocdef);
+ var
+ templist : TAsmList;
+ stabsendlabel : tasmlabel;
+ RType : Char;
+ Obj,Info : String;
+ hs : string;
+ ss : ansistring;
+ begin
+ if not(def.in_currentunit) or
+ { happens for init procdef of units without init section }
+ not assigned(def.procstarttai) then
+ exit;
+
+ { mark as used so the local type defs also be written }
+ def.dbg_state:=dbg_state_used;
+
+ templist:=TAsmList.create;
+
+ { end of procedure }
+ current_asmdata.getlabel(stabsendlabel,alt_dbgtype);
+
+ if assigned(def.funcretsym) and
+ (tabstractnormalvarsym(def.funcretsym).refs>0) then
+ begin
+ if tabstractnormalvarsym(def.funcretsym).localloc.loc=LOC_REFERENCE then
+ begin
+{ TODO: Need to add gdb support for ret in param register calling}
+ if paramanager.ret_in_param(def.returndef,def.proccalloption) then
+ hs:='X*'
+ else
+ hs:='X';
+ templist.concat(Tai_stab.create(stab_stabs,strpnew(
+ '"'+GetSymName(def.procsym)+':'+hs+def_stab_number(def.returndef)+'",'+
+ tostr(N_tsym)+',0,0,'+tostr(tabstractnormalvarsym(def.funcretsym).localloc.reference.offset))));
+ if (m_result in current_settings.modeswitches) then
+ templist.concat(Tai_stab.create(stab_stabs,strpnew(
+ '"RESULT:'+hs+def_stab_number(def.returndef)+'",'+
+ tostr(N_tsym)+',0,0,'+tostr(tabstractnormalvarsym(def.funcretsym).localloc.reference.offset))));
+ end;
+ end;
+ // LBRAC
+ ss:=tostr(N_LBRAC)+',0,0,';
+ if target_info.cpu=cpu_powerpc64 then
+ ss:=ss+'.';
+ ss:=ss+def.mangledname;
+ if not(af_stabs_use_function_absolute_addresses in target_asm.flags) then
+ begin
+ ss:=ss+'-';
+ if target_info.cpu=cpu_powerpc64 then
+ ss:=ss+'.';
+ ss:=ss+def.mangledname;
+ end;
+ templist.concat(Tai_stab.Create_ansistr(stab_stabn,ss));
+ // RBRAC
+ ss:=tostr(N_RBRAC)+',0,0,'+stabsendlabel.name;
+ if not(af_stabs_use_function_absolute_addresses in target_asm.flags) then
+ begin
+ ss:=ss+'-';
+ if target_info.cpu=cpu_powerpc64 then
+ ss:=ss+'.';
+ ss:=ss+def.mangledname;
+ end;
+ templist.concat(Tai_stab.Create_ansistr(stab_stabn,ss));
+
+ { the stabsendlabel must come after all other stabs for this }
+ { function }
+ templist.concat(tai_label.create(stabsendlabel));
+
+ { Add a "size" stab as described in the last paragraph of 2.5 at }
+ { http://sourceware.org/gdb/current/onlinedocs/stabs_2.html#SEC12 }
+ { This works at least on Darwin (and is needed on Darwin to get }
+ { correct smartlinking of stabs), but I don't know which binutils }
+ { version is required on other platforms }
+ { This stab must come after all other stabs for the procedure, }
+ { including the LBRAC/RBRAC ones }
+ if (target_info.system in systems_darwin) then
+ templist.concat(Tai_stab.create(stab_stabs,
+ strpnew('"",'+tostr(N_FUNCTION)+',0,0,'+stabsendlabel.name+'-'+def.mangledname)));
+
+ current_asmdata.asmlists[al_procedures].insertlistafter(def.procendtai,templist);
+
+ { "The stab representing a procedure is located immediately
+ following the code of the procedure. This stab is in turn
+ directly followed by a group of other stabs describing
+ elements of the procedure. These other stabs describe the
+ procedure's parameters, its block local variables, and its
+ block structure." (stab docs) }
+ { this is however incorrect in case "include source" statements }
+ { appear in the block, in that case the procedure stab must }
+ { appear before this include stabs (and we generate such an }
+ { stabs for all functions) (JM) }
+
+ { FUNC stabs }
+ obj := GetSymName(def.procsym);
+ info := '';
+ if (po_global in def.procoptions) then
+ RType := 'F'
+ else
+ RType := 'f';
+ if assigned(def.owner) then
+ begin
+ if (def.owner.symtabletype in [ObjectSymtable,recordsymtable]) then
+ obj := GetSymTableName(def.owner)+'__'+GetSymName(def.procsym);
+ if not(cs_gdb_valgrind in current_settings.globalswitches) and
+ (def.owner.symtabletype=localsymtable) and
+ assigned(def.owner.defowner) and
+ assigned(tprocdef(def.owner.defowner).procsym) then
+ info := ','+GetSymName(def.procsym)+','+GetSymName(tprocdef(def.owner.defowner).procsym);
+ end;
+ templist.concat(Tai_stab.Create_ansistr(stab_stabs,'"'+ansistring(obj)+':'+RType+def_stab_number(def.returndef)+info+'",'+tostr(n_function)+',0,'+tostr(def.fileinfo.line)+','+ansistring(def.mangledname)));
+
+ current_asmdata.asmlists[al_procedures].insertlistbefore(def.procstarttai,templist);
+
+ { para types }
+ if assigned(def.parast) then
+ write_symtable_syms(templist,def.parast);
+ { local type defs and vars should not be written
+ inside the main proc stab }
+ if assigned(def.localst) and
+ (def.localst.symtabletype=localsymtable) then
+ write_symtable_syms(templist,def.localst);
+
+ current_asmdata.asmlists[al_procedures].insertlistbefore(def.procstarttai,templist);
+
+ templist.free;
+ end;
+
+
+{****************************************************************************
+ TSym support
+****************************************************************************}
+
+ function TDebugInfoStabs.sym_var_value(const s:string;arg:pointer):string;
+ var
+ sym : tsym absolute arg;
+ begin
+ result:='';
+ if s='name' then
+ result:=GetSymName(sym)
+ else if s='mangledname' then
+ result:=sym.mangledname
+ else if s='ownername' then
+ result:=GetSymTableName(sym.owner)
+ else if s='line' then
+ result:=tostr(sym.fileinfo.line)
+ else if s='N_LSYM' then
+ result:=tostr(N_LSYM)
+ else if s='N_LCSYM' then
+ result:=tostr(N_LCSYM)
+ else if s='N_RSYM' then
+ result:=tostr(N_RSYM)
+ else if s='N_TSYM' then
+ result:=tostr(N_TSYM)
+ else if s='N_STSYM' then
+ result:=tostr(N_STSYM)
+ else if s='N_FUNCTION' then
+ result:=tostr(N_FUNCTION)
+ else
+ internalerror(200401152);
+ end;
+
+
+ function TDebugInfoStabs.sym_stabstr_evaluate(sym:tsym;const s:string;const vars:array of string):ansistring;
+ begin
+ result:=string_evaluate(s,@sym_var_value,sym,vars);
+ end;
+
+
+ procedure TDebugInfoStabs.write_sym_stabstr(list:TAsmList;sym:tsym;const ss:ansistring);
+ begin
+ if ss='' then
+ exit;
+ { add to list }
+ list.concat(Tai_stab.create_ansistr(stab_stabs,ss));
+ end;
+
+
+ procedure TDebugInfoStabs.appendsym_fieldvar(list:TAsmList;sym:tfieldvarsym);
+ var
+ ss : ansistring;
+ begin
+ ss:='';
+ if (sym.owner.symtabletype in [ObjectSymtable,recordsymtable]) and
+ (sp_static in sym.symoptions) then
+ ss:=sym_stabstr_evaluate(sym,'"${ownername}__${name}:S$1",${N_LCSYM},0,${line},${mangledname}',
+ [def_stab_number(sym.vardef)]);
+ write_sym_stabstr(list,sym,ss);
+ end;
+
+
+ procedure TDebugInfoStabs.appendsym_staticvar(list:TAsmList;sym:tstaticvarsym);
+ var
+ ss : ansistring;
+ st : string;
+ threadvaroffset : string;
+ regidx : Tregisterindex;
+ nsym : string[7];
+ begin
+ { external symbols can't be resolved at link time, so we
+ can't generate stabs for them }
+ if vo_is_external in sym.varoptions then
+ exit;
+ ss:='';
+ st:=def_stab_number(sym.vardef);
+ case sym.localloc.loc of
+ LOC_REGISTER,
+ LOC_CREGISTER,
+ LOC_MMREGISTER,
+ LOC_CMMREGISTER,
+ LOC_FPUREGISTER,
+ LOC_CFPUREGISTER :
+ begin
+ regidx:=findreg_by_number(sym.localloc.register);
+ { "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi", "eip", "ps", "cs", "ss", "ds", "es", "fs", "gs", }
+ { this is the register order for GDB}
+ if regidx<>0 then
+ ss:=sym_stabstr_evaluate(sym,'"${name}:r$1",${N_RSYM},0,${line},$2',[st,tostr(regstabs_table[regidx])]);
+ end;
+ else
+ begin
+ if (vo_is_thread_var in sym.varoptions) then
+ threadvaroffset:='+'+tostr(sizeof(pint))
+ else
+ threadvaroffset:='';
+ if (vo_is_typed_const in sym.varoptions) then
+ nsym:='N_STSYM'
+ else
+ nsym:='N_LCSYM';
+ { Here we used S instead of
+ because with G GDB doesn't look at the address field
+ but searches the same name or with a leading underscore
+ but these names don't exist in pascal !}
+ st:='S'+st;
+ ss:=sym_stabstr_evaluate(sym,'"${name}:$1",${'+nsym+'},0,${line},${mangledname}$2',[st,threadvaroffset]);
+ end;
+ end;
+ write_sym_stabstr(list,sym,ss);
+ end;
+
+
+ procedure TDebugInfoStabs.appendsym_localvar(list:TAsmList;sym:tlocalvarsym);
+ var
+ ss : ansistring;
+ st : string;
+ regidx : Tregisterindex;
+ begin
+ { There is no space allocated for not referenced locals }
+ if (sym.owner.symtabletype=localsymtable) and (sym.refs=0) then
+ exit;
+
+ ss:='';
+ st:=def_stab_number(sym.vardef);
+ case sym.localloc.loc of
+ LOC_REGISTER,
+ LOC_CREGISTER,
+ LOC_MMREGISTER,
+ LOC_CMMREGISTER,
+ LOC_FPUREGISTER,
+ LOC_CFPUREGISTER :
+ begin
+ regidx:=findreg_by_number(sym.localloc.register);
+ { "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi", "eip", "ps", "cs", "ss", "ds", "es", "fs", "gs", }
+ { this is the register order for GDB}
+ if regidx<>0 then
+ ss:=sym_stabstr_evaluate(sym,'"${name}:r$1",${N_RSYM},0,${line},$2',[st,tostr(regstabs_table[regidx])]);
+ end;
+ LOC_REFERENCE :
+ { offset to ebp => will not work if the framepointer is esp
+ so some optimizing will make things harder to debug }
+ ss:=sym_stabstr_evaluate(sym,'"${name}:$1",${N_TSYM},0,${line},$2',[st,tostr(sym.localloc.reference.offset)])
+ else
+ internalerror(2003091814);
+ end;
+ write_sym_stabstr(list,sym,ss);
+ end;
+
+
+ function TDebugInfoStabs.get_appendsym_paravar_reg(sym:tparavarsym;const typ,stabstr:string;reg: tregister): ansistring;
+ var
+ ltyp: string[1];
+ regidx : Tregisterindex;
+ begin
+ result:='';
+ if typ='p' then
+ ltyp:='R'
+ else
+ ltyp:='a';
+ regidx:=findreg_by_number(reg);
+ { "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi", "eip", "ps", "cs", "ss", "ds", "es", "fs", "gs", }
+ { this is the register order for GDB}
+ if regidx<>0 then
+ result:=sym_stabstr_evaluate(sym,'"${name}:$1",${N_RSYM},0,${line},$2',[ltyp+stabstr,tostr(longint(regstabs_table[regidx]))]);
+ end;
+
+
+ procedure TDebugInfoStabs.appendsym_paravar(list:TAsmList;sym:tparavarsym);
+ var
+ ss : ansistring;
+ c : string[1];
+ st : string;
+ regidx : Tregisterindex;
+ begin
+ ss:='';
+ { set loc to LOC_REFERENCE to get somewhat usable debugging info for -Or }
+ { while stabs aren't adapted for regvars yet }
+ if (vo_is_self in sym.varoptions) then
+ begin
+ case sym.localloc.loc of
+ LOC_REGISTER,
+ LOC_CREGISTER:
+ regidx:=findreg_by_number(sym.localloc.register);
+ LOC_REFERENCE: ;
+ else
+ internalerror(2003091815);
+ end;
+ if (po_classmethod in tabstractprocdef(sym.owner.defowner).procoptions) or
+ (po_staticmethod in tabstractprocdef(sym.owner.defowner).procoptions) then
+ begin
+ if (sym.localloc.loc=LOC_REFERENCE) then
+ ss:=sym_stabstr_evaluate(sym,'"pvmt:p$1",${N_TSYM},0,0,$2',
+ [def_stab_number(pvmttype),tostr(sym.localloc.reference.offset)])
+ else
+ begin
+ regidx:=findreg_by_number(sym.localloc.register);
+ ss:=sym_stabstr_evaluate(sym,'"pvmt:r$1",${N_RSYM},0,0,$2',
+ [def_stab_number(pvmttype),tostr(regstabs_table[regidx])]);
+ end
+ end
+ else
+ begin
+ if not(is_class(tprocdef(sym.owner.defowner).struct)) then
+ c:='v'
+ else
+ c:='p';
+ if (sym.localloc.loc=LOC_REFERENCE) then
+ ss:=sym_stabstr_evaluate(sym,'"$$t:$1",${N_TSYM},0,0,$2',
+ [c+def_stab_number(tprocdef(sym.owner.defowner).struct),tostr(sym.localloc.reference.offset)])
+ else
+ begin
+ if (c='p') then
+ c:='R'
+ else
+ c:='a';
+ regidx:=findreg_by_number(sym.localloc.register);
+ ss:=sym_stabstr_evaluate(sym,'"$$t:$1",${N_RSYM},0,0,$2',
+ [c+def_stab_number(tprocdef(sym.owner.defowner).struct),tostr(regstabs_table[regidx])]);
+ end
+ end;
+ end
+ else
+ begin
+ st:=def_stab_number(sym.vardef);
+
+ if paramanager.push_addr_param(sym.varspez,sym.vardef,tprocdef(sym.owner.defowner).proccalloption) and
+ not(vo_has_local_copy in sym.varoptions) and
+ not is_open_string(sym.vardef) then
+ c:='v' { should be 'i' but 'i' doesn't work }
+ else
+ c:='p';
+ case sym.localloc.loc of
+ LOC_REGISTER,
+ LOC_CREGISTER,
+ LOC_MMREGISTER,
+ LOC_CMMREGISTER,
+ LOC_FPUREGISTER,
+ LOC_CFPUREGISTER :
+ begin
+ ss:=get_appendsym_paravar_reg(sym,c,st,sym.localloc.register);
+ end;
+ LOC_REFERENCE :
+ begin
+ { When the *value* of a parameter (so not its address!) is
+ copied into a local variable, you have to generate two
+ stabs: one for the parmeter, and one for the local copy.
+ Not doing this breaks debugging under e.g. SPARC. Doc:
+ http://sourceware.org/gdb/current/onlinedocs/stabs_4.html#SEC26
+ }
+ if (c='p') and
+ not is_open_string(sym.vardef) and
+ ((sym.paraloc[calleeside].location^.loc<>sym.localloc.loc) or
+ ((sym.localloc.loc in [LOC_REFERENCE,LOC_CREFERENCE]) and
+ ((sym.paraloc[calleeside].location^.reference.index<>sym.localloc.reference.base) or
+ (sym.paraloc[calleeside].location^.reference.offset<>sym.localloc.reference.offset))) or
+ ((sym.localloc.loc in [LOC_REGISTER,LOC_CREGISTER,LOC_MMREGISTER,LOC_CMMREGISTER,LOC_FPUREGISTER,LOC_CFPUREGISTER]) and
+ (sym.localloc.register<>sym.paraloc[calleeside].location^.register))) then
+ begin
+ if not(sym.paraloc[calleeside].location^.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
+ ss:=get_appendsym_paravar_reg(sym,c,st,sym.paraloc[calleeside].location^.register)
+ else
+ ss:=sym_stabstr_evaluate(sym,'"${name}:$1",${N_TSYM},0,${line},$2',[c+st,tostr(sym.paraloc[calleeside].location^.reference.offset)]);
+ write_sym_stabstr(list,sym,ss);
+ { second stab has no parameter specifier }
+ c:='';
+ end;
+ { offset to ebp => will not work if the framepointer is esp
+ so some optimizing will make things harder to debug }
+ ss:=sym_stabstr_evaluate(sym,'"${name}:$1",${N_TSYM},0,${line},$2',[c+st,tostr(sym.localloc.reference.offset)])
+ end;
+ else
+ internalerror(2003091814);
+ end;
+ end;
+ write_sym_stabstr(list,sym,ss);
+ end;
+
+
+ procedure TDebugInfoStabs.appendsym_const(list:TAsmList;sym:tconstsym);
+ var
+ st : string;
+ ss : ansistring;
+ begin
+ ss:='';
+ { Don't write info for default parameter values, the N_Func breaks
+ the N_Func for the function itself.
+ Valgrind does not support constants }
+ if (sym.owner.symtabletype=parasymtable) or
+ (cs_gdb_valgrind in current_settings.globalswitches) then
+ exit;
+ case sym.consttyp of
+ conststring:
+ begin
+ if sym.value.len<200 then
+ st:='s'''+backspace_quote(octal_quote(strpas(pchar(sym.value.valueptr)),[#0..#9,#11,#12,#14..#31,'''']),['"','\',#10,#13])+''''
+ else
+ st:='<constant string too long>';
+ end;
+ constord:
+ st:='i'+tostr(sym.value.valueord);
+ constpointer:
+ st:='i'+tostr(sym.value.valueordptr);
+ constreal:
+ begin
+ system.str(pbestreal(sym.value.valueptr)^,st);
+ st := 'r'+st;
+ end;
+ else
+ begin
+ { if we don't know just put zero !! }
+ st:='i0';
+ end;
+ end;
+ ss:=sym_stabstr_evaluate(sym,'"${name}:c=$1;",${N_FUNCTION},0,${line},0',[st]);
+ write_sym_stabstr(list,sym,ss);
+ end;
+
+
+ procedure TDebugInfoStabs.appendsym_type(list:TAsmList;sym:ttypesym);
+ var
+ ss : ansistring;
+ stabchar : string[2];
+ begin
+ ss:='';
+ if not assigned(sym.typedef) then
+ internalerror(200509262);
+ if sym.typedef.typ in tagtypes then
+ stabchar:='Tt'
+ else
+ stabchar:='t';
+ ss:=sym_stabstr_evaluate(sym,'"${name}:$1$2",${N_LSYM},0,${line},0',[stabchar,def_stab_number(sym.typedef)]);
+ write_sym_stabstr(list,sym,ss);
+ end;
+
+
+ procedure TDebugInfoStabs.appendsym_label(list:TAsmList;sym:tlabelsym);
+ var
+ ss : ansistring;
+ begin
+ ss:=sym_stabstr_evaluate(sym,'"${name}",${N_LSYM},0,${line},0',[]);
+ write_sym_stabstr(list,sym,ss);
+ end;
+
+
+{****************************************************************************
+ Proc/Module support
+****************************************************************************}
+
+ procedure tdebuginfostabs.inserttypeinfo;
+ var
+ stabsvarlist,
+ stabstypelist : TAsmList;
+ storefilepos : tfileposinfo;
+ i : longint;
+ vardatatype : ttypesym;
+ begin
+ storefilepos:=current_filepos;
+ current_filepos:=current_module.mainfilepos;
+
+ global_stab_number:=0;
+ defnumberlist:=TFPObjectlist.create(false);
+ deftowritelist:=TFPObjectlist.create(false);
+ stabsvarlist:=TAsmList.create;
+ stabstypelist:=TAsmList.create;
+
+ vardatatype:=try_search_system_type('TVARDATA');
+ if assigned(vardatatype) then
+ vardatadef:=trecorddef(vardatatype.typedef);
+
+ { include symbol that will be referenced from the main to be sure to
+ include this debuginfo .o file }
+ current_module.flags:=current_module.flags or uf_has_stabs_debuginfo;
+ if not(target_info.system in systems_darwin) then
+ begin
+ new_section(current_asmdata.asmlists[al_stabs],sec_data,GetSymTableName(current_module.localsymtable),0);
+ current_asmdata.asmlists[al_stabs].concat(tai_symbol.Createname_global(make_mangledname('DEBUGINFO',current_module.localsymtable,''),AT_DATA,0));
+ end
+ else
+ new_section(current_asmdata.asmlists[al_stabs],sec_code,GetSymTableName(current_module.localsymtable),0);
+
+ { write all global/local variables. This will flag all required tdefs }
+ if assigned(current_module.globalsymtable) then
+ write_symtable_syms(stabsvarlist,current_module.globalsymtable);
+ if assigned(current_module.localsymtable) then
+ write_symtable_syms(stabsvarlist,current_module.localsymtable);
+
+ { write all procedures and methods. This will flag all required tdefs }
+ if assigned(current_module.globalsymtable) then
+ write_symtable_procdefs(stabsvarlist,current_module.globalsymtable);
+ if assigned(current_module.localsymtable) then
+ write_symtable_procdefs(stabsvarlist,current_module.localsymtable);
+
+ { reset unit type info flag }
+ reset_unit_type_info;
+
+ { write used types from the used units }
+ write_used_unit_type_info(stabstypelist,current_module);
+ { last write the types from this unit }
+ if assigned(current_module.globalsymtable) then
+ write_symtable_defs(stabstypelist,current_module.globalsymtable);
+ if assigned(current_module.localsymtable) then
+ write_symtable_defs(stabstypelist,current_module.localsymtable);
+
+ write_remaining_defs_to_write(stabstypelist);
+
+ current_asmdata.asmlists[al_stabs].concatlist(stabstypelist);
+ current_asmdata.asmlists[al_stabs].concatlist(stabsvarlist);
+
+ { reset stab numbers }
+ for i:=0 to defnumberlist.count-1 do
+ begin
+ if assigned(defnumberlist[i]) then
+ begin
+ tdef(defnumberlist[i]).stab_number:=0;
+ tdef(defnumberlist[i]).dbg_state:=dbg_state_unused;
+ end;
+ end;
+
+ defnumberlist.free;
+ defnumberlist:=nil;
+ deftowritelist.free;
+ deftowritelist:=nil;
+
+ stabsvarlist.free;
+ stabstypelist.free;
+ current_filepos:=storefilepos;
+ end;
+
+
+ procedure tdebuginfostabs.insertlineinfo(list:TAsmList);
+ var
+ currfileinfo,
+ lastfileinfo : tfileposinfo;
+ currfuncname : pshortstring;
+ currsectype : TAsmSectiontype;
+ hlabel : tasmlabel;
+ hp : tai;
+ infile : tinputfile;
+ begin
+ FillChar(lastfileinfo,sizeof(lastfileinfo),0);
+ currfuncname:=nil;
+ currsectype:=sec_code;
+ hp:=Tai(list.first);
+ while assigned(hp) do
+ begin
+ case hp.typ of
+ ait_section :
+ currsectype:=tai_section(hp).sectype;
+ ait_function_name :
+ currfuncname:=tai_function_name(hp).funcname;
+ ait_force_line :
+ lastfileinfo.line:=-1;
+ end;
+
+ if (currsectype=sec_code) and
+ (hp.typ=ait_instruction) then
+ begin
+ currfileinfo:=tailineinfo(hp).fileinfo;
+ { file changed ? (must be before line info) }
+ if (currfileinfo.fileindex<>0) and
+ ((lastfileinfo.fileindex<>currfileinfo.fileindex) or
+ (lastfileinfo.moduleindex<>currfileinfo.moduleindex)) then
+ begin
+ infile:=get_module(currfileinfo.moduleindex).sourcefiles.get_file(currfileinfo.fileindex);
+ if assigned(infile) then
+ begin
+ current_asmdata.getlabel(hlabel,alt_dbgfile);
+ { emit stabs }
+ if not(ds_stabs_abs_include_files in current_settings.debugswitches) or
+ path_absolute(infile.path^) then
+ list.insertbefore(Tai_stab.Create_str(stab_stabs,'"'+BsToSlash(FixPath(infile.path^,false))+FixFileName(infile.name^)+'",'+tostr(n_includefile)+
+ ',0,0,'+hlabel.name),hp)
+ else
+ list.insertbefore(Tai_stab.Create_str(stab_stabs,'"'+BsToSlash(FixPath(getcurrentdir,false)+FixPath(infile.path^,false))+FixFileName(infile.name^)+'",'+tostr(n_includefile)+
+ ',0,0,'+hlabel.name),hp);
+ list.insertbefore(tai_label.create(hlabel),hp);
+ { force new line info }
+ lastfileinfo.line:=-1;
+ end;
+ end;
+
+ { line changed ? }
+ if (currfileinfo.line>lastfileinfo.line) and (currfileinfo.line<>0) then
+ begin
+ if assigned(currfuncname) and
+ not(af_stabs_use_function_absolute_addresses in target_asm.flags) then
+ begin
+ current_asmdata.getlabel(hlabel,alt_dbgline);
+ list.insertbefore(Tai_stab.Create_str(stab_stabn,tostr(n_textline)+',0,'+tostr(currfileinfo.line)+','+
+ hlabel.name+' - '+{$IFDEF POWERPC64}'.'+{$ENDIF POWERPC64}currfuncname^),hp);
+ list.insertbefore(tai_label.create(hlabel),hp);
+ end
+ else
+ list.insertbefore(Tai_stab.Create_str(stab_stabd,tostr(n_textline)+',0,'+tostr(currfileinfo.line)),hp);
+ end;
+ lastfileinfo:=currfileinfo;
+ end;
+
+ hp:=tai(hp.next);
+ end;
+ end;
+
+
+ procedure tdebuginfostabs.insertmoduleinfo;
+ var
+ hlabel : tasmlabel;
+ infile : tinputfile;
+ begin
+ { emit main source n_sourcefile for start of module }
+ current_asmdata.getlabel(hlabel,alt_dbgfile);
+ infile:=current_module.sourcefiles.get_file(1);
+ new_section(current_asmdata.asmlists[al_start],sec_code,make_mangledname('DEBUGSTART',current_module.localsymtable,''),0,secorder_begin);
+ if not(target_info.system in systems_darwin) then
+ current_asmdata.asmlists[al_start].concat(tai_symbol.Createname_global(make_mangledname('DEBUGSTART',current_module.localsymtable,''),AT_DATA,0));
+ current_asmdata.asmlists[al_start].concat(Tai_stab.Create_str(stab_stabs,'"'+BsToSlash(FixPath(getcurrentdir,false))+'",'+tostr(n_sourcefile)+
+ ',0,0,'+hlabel.name));
+ current_asmdata.asmlists[al_start].concat(Tai_stab.Create_str(stab_stabs,'"'+BsToSlash(FixPath(infile.path^,false))+FixFileName(infile.name^)+'",'+tostr(n_sourcefile)+
+ ',0,0,'+hlabel.name));
+ current_asmdata.asmlists[al_start].concat(tai_label.create(hlabel));
+ { for darwin, you need a "module marker" too to work around }
+ { either some assembler or gdb bug (radar 4386531 according to a }
+ { comment in dbxout.c of Apple's gcc) }
+ if (target_info.system in systems_darwin) then
+ current_asmdata.asmlists[al_end].concat(Tai_stab.Create_str(stab_stabs,'"",'+tostr(N_OSO)+',0,0,0'));
+ { emit empty n_sourcefile for end of module }
+ current_asmdata.getlabel(hlabel,alt_dbgfile);
+ new_section(current_asmdata.asmlists[al_end],sec_code,make_mangledname('DEBUGEND',current_module.localsymtable,''),0,secorder_end);
+ if not(target_info.system in systems_darwin) then
+ current_asmdata.asmlists[al_end].concat(tai_symbol.Createname_global(make_mangledname('DEBUGEND',current_module.localsymtable,''),AT_DATA,0));
+ current_asmdata.asmlists[al_end].concat(Tai_stab.Create_str(stab_stabs,'"",'+tostr(n_sourcefile)+',0,0,'+hlabel.name));
+ current_asmdata.asmlists[al_end].concat(tai_label.create(hlabel));
+ end;
+
+
+ procedure tdebuginfostabs.referencesections(list:TAsmList);
+ var
+ hp : tmodule;
+ dbgtable : tai_symbol;
+ begin
+ { Reference all DEBUGINFO sections from the main .fpc section }
+ if (target_info.system in ([system_powerpc_macos]+systems_darwin)) then
+ exit;
+ new_section(list,sec_fpc,'links',0);
+ { make sure the debuginfo doesn't get stripped out }
+ if (target_info.system in systems_darwin) then
+ begin
+ dbgtable:=tai_symbol.createname('DEBUGINFOTABLE',AT_DATA,0);
+ list.concat(tai_directive.create(asd_no_dead_strip,dbgtable.sym.name));
+ list.concat(dbgtable);
+ end;
+ { include reference to all debuginfo sections of used units }
+ hp:=tmodule(loaded_units.first);
+ while assigned(hp) do
+ begin
+ If (hp.flags and uf_has_stabs_debuginfo)=uf_has_stabs_debuginfo then
+ begin
+ list.concat(Tai_const.Createname(make_mangledname('DEBUGINFO',hp.localsymtable,''),0));
+ list.concat(Tai_const.Createname(make_mangledname('DEBUGSTART',hp.localsymtable,''),0));
+ list.concat(Tai_const.Createname(make_mangledname('DEBUGEND',hp.localsymtable,''),0));
+ end;
+ hp:=tmodule(hp.next);
+ end;
+ end;
+
+ constructor TDebugInfoStabs.Create;
+ begin
+ inherited Create;
+ vardatadef:=nil;
+ end;
+
+ const
+ dbg_stabs_info : tdbginfo =
+ (
+ id : dbg_stabs;
+ idtxt : 'STABS';
+ );
+
+initialization
+ RegisterDebugInfo(dbg_stabs_info,TDebugInfoStabs);
+end.
diff --git a/closures/compiler/defcmp.pas b/closures/compiler/defcmp.pas
new file mode 100644
index 0000000000..25c4ca4f11
--- /dev/null
+++ b/closures/compiler/defcmp.pas
@@ -0,0 +1,1942 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Compare definitions and parameter lists
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit defcmp;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cclasses,
+ globtype,globals,
+ node,
+ symconst,symtype,symdef;
+
+ type
+ { if acp is cp_all the var const or nothing are considered equal }
+ tcompare_paras_type = ( cp_none, cp_value_equal_const, cp_all,cp_procvar);
+ tcompare_paras_option = (
+ cpo_allowdefaults,
+ cpo_ignorehidden, // ignore hidden parameters
+ cpo_allowconvert,
+ cpo_comparedefaultvalue,
+ cpo_openequalisexact,
+ cpo_ignoreuniv,
+ cpo_warn_incompatible_univ,
+ cpo_ignorevarspez, // ignore parameter access type
+ cpo_ignoreframepointer, // ignore frame pointer parameter (for assignment-compatibility of global procedures to nested procvars)
+ cpo_compilerproc,
+ cpo_rtlproc
+ );
+
+ tcompare_paras_options = set of tcompare_paras_option;
+
+ tcompare_defs_option = (cdo_internal,cdo_explicit,cdo_check_operator,cdo_allow_variant,cdo_parameter,cdo_warn_incompatible_univ);
+ tcompare_defs_options = set of tcompare_defs_option;
+
+ tconverttype = (tc_none,
+ tc_equal,
+ tc_not_possible,
+ tc_string_2_string,
+ tc_char_2_string,
+ tc_char_2_chararray,
+ tc_pchar_2_string,
+ tc_cchar_2_pchar,
+ tc_cstring_2_pchar,
+ tc_cstring_2_int,
+ tc_ansistring_2_pchar,
+ tc_string_2_chararray,
+ tc_chararray_2_string,
+ tc_array_2_pointer,
+ tc_pointer_2_array,
+ tc_int_2_int,
+ tc_int_2_bool,
+ tc_bool_2_bool,
+ tc_bool_2_int,
+ tc_real_2_real,
+ tc_int_2_real,
+ tc_real_2_currency,
+ tc_proc_2_procvar,
+ tc_nil_2_methodprocvar,
+ tc_arrayconstructor_2_set,
+ tc_set_to_set,
+ tc_cord_2_pointer,
+ tc_intf_2_string,
+ tc_intf_2_guid,
+ tc_class_2_intf,
+ tc_char_2_char,
+ tc_dynarray_2_openarray,
+ tc_pwchar_2_string,
+ tc_variant_2_dynarray,
+ tc_dynarray_2_variant,
+ tc_variant_2_enum,
+ tc_enum_2_variant,
+ tc_interface_2_variant,
+ tc_variant_2_interface,
+ tc_array_2_dynarray
+ );
+
+ function compare_defs_ext(def_from,def_to : tdef;
+ fromtreetype : tnodetype;
+ var doconv : tconverttype;
+ var operatorpd : tprocdef;
+ cdoptions:tcompare_defs_options):tequaltype;
+
+ { Returns if the type def_from can be converted to def_to or if both types are equal }
+ function compare_defs(def_from,def_to:tdef;fromtreetype:tnodetype):tequaltype;
+
+ { Returns true, if def1 and def2 are semantically the same }
+ function equal_defs(def_from,def_to:tdef):boolean;
+
+ { Checks for type compatibility (subgroups of type)
+ used for case statements... probably missing stuff
+ to use on other types }
+ function is_subequal(def1, def2: tdef): boolean;
+
+ {# true, if two parameter lists are equal
+ if acp is cp_all, all have to match exactly
+ if acp is cp_value_equal_const call by value
+ and call by const parameter are assumed as
+ equal
+ if acp is cp_procvar then the varspez have to match,
+ and all parameter types must be at least te_equal
+ if acp is cp_none, then we don't check the varspez at all
+ allowdefaults indicates if default value parameters
+ are allowed (in this case, the search order will first
+ search for a routine with default parameters, before
+ searching for the same definition with no parameters)
+ }
+ function compare_paras(para1,para2 : TFPObjectList; acp : tcompare_paras_type; cpoptions: tcompare_paras_options):tequaltype;
+
+ { True if a function can be assigned to a procvar }
+ { changed first argument type to pabstractprocdef so that it can also be }
+ { used to test compatibility between two pprocvardefs (JM) }
+ function proc_to_procvar_equal(def1:tabstractprocdef;def2:tprocvardef;checkincompatibleuniv: boolean):tequaltype;
+
+ { Parentdef is the definition of a method defined in a parent class or interface }
+ { Childdef is the definition of a method defined in a child class, interface or }
+ { a class implementing an interface with parentdef. }
+ { Returns true if the resultdef of childdef can be used to implement/override }
+ { parentdef's resultdef }
+ function compatible_childmethod_resultdef(parentretdef, childretdef: tdef): boolean;
+
+
+implementation
+
+ uses
+ verbose,systems,constexp,
+ symtable,symsym,
+ defutil,symutil;
+
+
+ function compare_defs_ext(def_from,def_to : tdef;
+ fromtreetype : tnodetype;
+ var doconv : tconverttype;
+ var operatorpd : tprocdef;
+ cdoptions:tcompare_defs_options):tequaltype;
+
+ { tordtype:
+ uvoid,
+ u8bit,u16bit,u32bit,u64bit,
+ s8bit,s16bit,s32bit,s64bit,
+ pasbool, bool8bit,bool16bit,bool32bit,bool64bit,
+ uchar,uwidechar,scurrency }
+
+ type
+ tbasedef=(bvoid,bchar,bint,bbool);
+ const
+ basedeftbl:array[tordtype] of tbasedef =
+ (bvoid,
+ bint,bint,bint,bint,
+ bint,bint,bint,bint,
+ bbool,bbool,bbool,bbool,
+ bbool,bbool,bbool,bbool,
+ bchar,bchar,bint);
+
+ basedefconvertsimplicit : array[tbasedef,tbasedef] of tconverttype =
+ { void, char, int, bool }
+ ((tc_not_possible,tc_not_possible,tc_not_possible,tc_not_possible),
+ (tc_not_possible,tc_char_2_char,tc_not_possible,tc_not_possible),
+ (tc_not_possible,tc_not_possible,tc_int_2_int,tc_not_possible),
+ (tc_not_possible,tc_not_possible,tc_not_possible,tc_bool_2_bool));
+ basedefconvertsexplicit : array[tbasedef,tbasedef] of tconverttype =
+ { void, char, int, bool }
+ ((tc_not_possible,tc_not_possible,tc_not_possible,tc_not_possible),
+ (tc_not_possible,tc_char_2_char,tc_int_2_int,tc_int_2_bool),
+ (tc_not_possible,tc_int_2_int,tc_int_2_int,tc_int_2_bool),
+ (tc_not_possible,tc_bool_2_int,tc_bool_2_int,tc_bool_2_bool));
+
+ var
+ subeq,eq : tequaltype;
+ hd1,hd2 : tdef;
+ hct : tconverttype;
+ hobjdef : tobjectdef;
+ hpd : tprocdef;
+ begin
+ eq:=te_incompatible;
+ doconv:=tc_not_possible;
+
+ { safety check }
+ if not(assigned(def_from) and assigned(def_to)) then
+ begin
+ compare_defs_ext:=te_incompatible;
+ exit;
+ end;
+
+ { same def? then we've an exact match }
+ if def_from=def_to then
+ begin
+ doconv:=tc_equal;
+ compare_defs_ext:=te_exact;
+ exit;
+ end;
+
+ { undefined def? then mark it as equal }
+ if (def_from.typ=undefineddef) or
+ (def_to.typ=undefineddef) then
+ begin
+ doconv:=tc_equal;
+ compare_defs_ext:=te_exact;
+ exit;
+ end;
+
+ { we walk the wanted (def_to) types and check then the def_from
+ types if there is a conversion possible }
+ case def_to.typ of
+ orddef :
+ begin
+ case def_from.typ of
+ orddef :
+ begin
+ if (torddef(def_from).ordtype=torddef(def_to).ordtype) then
+ begin
+ case torddef(def_from).ordtype of
+ uchar,uwidechar,
+ u8bit,u16bit,u32bit,u64bit,
+ s8bit,s16bit,s32bit,s64bit:
+ begin
+ if (torddef(def_from).low>=torddef(def_to).low) and
+ (torddef(def_from).high<=torddef(def_to).high) then
+ eq:=te_equal
+ else
+ begin
+ doconv:=tc_int_2_int;
+ eq:=te_convert_l1;
+ end;
+ end;
+ uvoid,
+ pasbool8,pasbool16,pasbool32,pasbool64,
+ bool8bit,bool16bit,bool32bit,bool64bit:
+ eq:=te_equal;
+ else
+ internalerror(200210061);
+ end;
+ end
+ else
+ begin
+ if cdo_explicit in cdoptions then
+ doconv:=basedefconvertsexplicit[basedeftbl[torddef(def_from).ordtype],basedeftbl[torddef(def_to).ordtype]]
+ else
+ doconv:=basedefconvertsimplicit[basedeftbl[torddef(def_from).ordtype],basedeftbl[torddef(def_to).ordtype]];
+ if (doconv=tc_not_possible) then
+ eq:=te_incompatible
+ else if (not is_in_limit(def_from,def_to)) then
+ { "punish" bad type conversions :) (JM) }
+ eq:=te_convert_l3
+ else
+ eq:=te_convert_l1;
+ end;
+ end;
+ enumdef :
+ begin
+ { needed for char(enum) }
+ if cdo_explicit in cdoptions then
+ begin
+ doconv:=tc_int_2_int;
+ eq:=te_convert_l1;
+ end;
+ end;
+ floatdef :
+ begin
+ if is_currency(def_to) then
+ begin
+ doconv:=tc_real_2_currency;
+ eq:=te_convert_l2;
+ end;
+ end;
+ objectdef:
+ begin
+ if (m_delphi in current_settings.modeswitches) and
+ is_implicit_pointer_object_type(def_from) and
+ (cdo_explicit in cdoptions) then
+ begin
+ eq:=te_convert_l1;
+ if (fromtreetype=niln) then
+ begin
+ { will be handled by the constant folding }
+ doconv:=tc_equal;
+ end
+ else
+ doconv:=tc_int_2_int;
+ end;
+ end;
+ classrefdef,
+ procvardef,
+ pointerdef :
+ begin
+ if cdo_explicit in cdoptions then
+ begin
+ eq:=te_convert_l1;
+ if (fromtreetype=niln) then
+ begin
+ { will be handled by the constant folding }
+ doconv:=tc_equal;
+ end
+ else
+ doconv:=tc_int_2_int;
+ end;
+ end;
+ arraydef :
+ begin
+ if (m_mac in current_settings.modeswitches) and
+ (fromtreetype=stringconstn) then
+ begin
+ eq:=te_convert_l3;
+ doconv:=tc_cstring_2_int;
+ end;
+ end;
+ end;
+ end;
+
+ stringdef :
+ begin
+ case def_from.typ of
+ stringdef :
+ begin
+ { Constant string }
+ if (fromtreetype=stringconstn) then
+ begin
+ if (tstringdef(def_from).stringtype=tstringdef(def_to).stringtype) and
+ ((tstringdef(def_from).stringtype<>st_ansistring) or
+ (tstringdef(def_from).encoding=tstringdef(def_to).encoding)
+ ) then
+ eq:=te_equal
+ else
+ begin
+ doconv:=tc_string_2_string;
+ if (tstringdef(def_from).stringtype = st_ansistring) and
+ (tstringdef(def_to).stringtype = st_ansistring) then
+ if (tstringdef(def_to).encoding=globals.CP_UTF8) then
+ eq:=te_convert_l1
+ else
+ eq:=te_convert_l2
+ else
+ begin
+ { Don't prefer conversions from widestring to a
+ normal string as we can lose information }
+ if (tstringdef(def_from).stringtype in [st_widestring,st_unicodestring]) and
+ not (tstringdef(def_to).stringtype in [st_widestring,st_unicodestring]) then
+ eq:=te_convert_l3
+ else if tstringdef(def_to).stringtype in [st_widestring,st_unicodestring] then
+ eq:=te_convert_l2
+ else
+ eq:=te_convert_l1;
+ end;
+ end;
+ end
+ else if (tstringdef(def_from).stringtype=tstringdef(def_to).stringtype) and
+ (tstringdef(def_from).stringtype=st_ansistring) then
+ begin
+ { don't convert ansistrings if any conditions is true:
+ 1) same encoding
+ 2) from explicit codepage ansistring to ansistring and vice versa
+ 3) from any ansistring to rawbytestring }
+ if (tstringdef(def_from).encoding=tstringdef(def_to).encoding) or
+ ((tstringdef(def_to).encoding=0) and (tstringdef(def_from).encoding=getansistringcodepage)) or
+ ((tstringdef(def_to).encoding=getansistringcodepage) and (tstringdef(def_from).encoding=0)) or
+ (tstringdef(def_to).encoding=globals.CP_NONE) then
+ begin
+ eq:=te_equal;
+ end
+ else
+ begin
+ doconv := tc_string_2_string;
+ if (tstringdef(def_to).encoding=globals.CP_UTF8) then
+ eq:=te_convert_l1
+ else
+ eq:=te_convert_l2;
+ end
+ end
+ else
+ { same string type ? }
+ if (tstringdef(def_from).stringtype=tstringdef(def_to).stringtype) and
+ { for shortstrings also the length must match }
+ ((tstringdef(def_from).stringtype<>st_shortstring) or
+ (tstringdef(def_from).len=tstringdef(def_to).len)) and
+ { for ansi- and unicodestrings also the encoding must match }
+ (not(tstringdef(def_from).stringtype in [st_ansistring,st_unicodestring]) or
+ (tstringdef(def_from).encoding=tstringdef(def_to).encoding)) then
+ eq:=te_equal
+ else
+ begin
+ doconv:=tc_string_2_string;
+ case tstringdef(def_from).stringtype of
+ st_widestring :
+ begin
+ { Prefer conversions to unicodestring }
+ if tstringdef(def_to).stringtype=st_unicodestring then
+ eq:=te_convert_l1
+ { else prefer conversions to ansistring }
+ else if tstringdef(def_to).stringtype=st_ansistring then
+ eq:=te_convert_l2
+ else
+ eq:=te_convert_l3;
+ end;
+ st_unicodestring :
+ begin
+ { Prefer conversions to widestring }
+ if tstringdef(def_to).stringtype=st_widestring then
+ eq:=te_convert_l1
+ { else prefer conversions to ansistring }
+ else if tstringdef(def_to).stringtype=st_ansistring then
+ eq:=te_convert_l2
+ else
+ eq:=te_convert_l3;
+ end;
+ st_shortstring :
+ begin
+ { Prefer shortstrings of different length or conversions
+ from shortstring to ansistring }
+ if (tstringdef(def_to).stringtype=st_shortstring) then
+ eq:=te_convert_l1
+ else if tstringdef(def_to).stringtype=st_ansistring then
+ eq:=te_convert_l2
+ else
+ eq:=te_convert_l3;
+ end;
+ st_ansistring :
+ begin
+ { Prefer conversion to widestrings }
+ if (tstringdef(def_to).stringtype in [st_widestring,st_unicodestring]) then
+ eq:=te_convert_l2
+ else
+ eq:=te_convert_l3;
+ end;
+ end;
+ end;
+ end;
+ orddef :
+ begin
+ { char to string}
+ if is_char(def_from) or
+ is_widechar(def_from) then
+ begin
+ doconv:=tc_char_2_string;
+ eq:=te_convert_l1;
+ end;
+ end;
+ arraydef :
+ begin
+ { array of char to string, the length check is done by the firstpass of this node }
+ if is_chararray(def_from) or is_open_chararray(def_from) then
+ begin
+ { "Untyped" stringconstn is an array of char }
+ if fromtreetype=stringconstn then
+ begin
+ doconv:=tc_string_2_string;
+ { prefered string type depends on the $H switch }
+ if not(cs_ansistrings in current_settings.localswitches) and
+ (tstringdef(def_to).stringtype=st_shortstring) then
+ eq:=te_equal
+ else if (cs_ansistrings in current_settings.localswitches) and
+ (tstringdef(def_to).stringtype=st_ansistring) then
+ eq:=te_equal
+ else if tstringdef(def_to).stringtype in [st_widestring,st_unicodestring] then
+ eq:=te_convert_l3
+ else
+ eq:=te_convert_l1;
+ end
+ else
+ begin
+ doconv:=tc_chararray_2_string;
+ if is_open_array(def_from) then
+ begin
+ if is_ansistring(def_to) then
+ eq:=te_convert_l1
+ else if is_widestring(def_to) or is_unicodestring(def_to) then
+ eq:=te_convert_l3
+ else
+ eq:=te_convert_l2;
+ end
+ else
+ begin
+ if is_shortstring(def_to) then
+ begin
+ { Only compatible with arrays that fit
+ smaller than 255 chars }
+ if (def_from.size <= 255) then
+ eq:=te_convert_l1;
+ end
+ else if is_ansistring(def_to) then
+ begin
+ if (def_from.size > 255) then
+ eq:=te_convert_l1
+ else
+ eq:=te_convert_l2;
+ end
+ else if is_widestring(def_to) or is_unicodestring(def_to) then
+ eq:=te_convert_l3
+ else
+ eq:=te_convert_l2;
+ end;
+ end;
+ end
+ else
+ { array of widechar to string, the length check is done by the firstpass of this node }
+ if is_widechararray(def_from) or is_open_widechararray(def_from) then
+ begin
+ doconv:=tc_chararray_2_string;
+ if is_widestring(def_to) or is_unicodestring(def_to) then
+ eq:=te_convert_l1
+ else
+ { size of widechar array is double due the sizeof a widechar }
+ if not(is_shortstring(def_to) and (is_open_widechararray(def_from) or (def_from.size>255*sizeof(widechar)))) then
+ eq:=te_convert_l3
+ else
+ eq:=te_convert_l2;
+ end;
+ end;
+ pointerdef :
+ begin
+ { pchar can be assigned to short/ansistrings,
+ but not in tp7 compatible mode }
+ if not(m_tp7 in current_settings.modeswitches) then
+ begin
+ if is_pchar(def_from) then
+ begin
+ doconv:=tc_pchar_2_string;
+ { prefer ansistrings because pchars can overflow shortstrings, }
+ { but only if ansistrings are the default (JM) }
+ if (is_shortstring(def_to) and
+ not(cs_ansistrings in current_settings.localswitches)) or
+ (is_ansistring(def_to) and
+ (cs_ansistrings in current_settings.localswitches)) then
+ eq:=te_convert_l1
+ else
+ eq:=te_convert_l2;
+ end
+ else if is_pwidechar(def_from) then
+ begin
+ doconv:=tc_pwchar_2_string;
+ if is_widestring(def_to) or is_unicodestring(def_to) then
+ eq:=te_convert_l1
+ else
+ eq:=te_convert_l3;
+ end;
+ end;
+ end;
+ objectdef :
+ begin
+ { corba interface -> id string }
+ if is_interfacecorba(def_from) then
+ begin
+ doconv:=tc_intf_2_string;
+ eq:=te_convert_l1;
+ end;
+ end;
+ end;
+ end;
+
+ floatdef :
+ begin
+ case def_from.typ of
+ orddef :
+ begin { ordinal to real }
+ { only for implicit and internal typecasts in tp/delphi }
+ if (([cdo_explicit,cdo_internal] * cdoptions <> [cdo_explicit]) or
+ ([m_tp7,m_delphi] * current_settings.modeswitches = [])) and
+ (is_integer(def_from) or
+ (is_currency(def_from) and
+ (s64currencytype.typ = floatdef))) then
+ begin
+ doconv:=tc_int_2_real;
+
+ { prefer single over others }
+ if is_single(def_to) then
+ eq:=te_convert_l3
+ else
+ eq:=te_convert_l4;
+ end
+ else if is_currency(def_from)
+ { and (s64currencytype.typ = orddef)) } then
+ begin
+ { prefer conversion to orddef in this case, unless }
+ { the orddef < currency (then it will get convert l3, }
+ { and conversion to float is favoured) }
+ doconv:=tc_int_2_real;
+ eq:=te_convert_l2;
+ end;
+ end;
+ floatdef :
+ begin
+ if tfloatdef(def_from).floattype=tfloatdef(def_to).floattype then
+ eq:=te_equal
+ else
+ begin
+ { Delphi does not allow explicit type conversions for float types like:
+ single_var:=single(double_var);
+ But if such conversion is inserted by compiler (internal) for some purpose,
+ it should be allowed even in Delphi mode. }
+ if (fromtreetype=realconstn) or
+ not((cdoptions*[cdo_explicit,cdo_internal]=[cdo_explicit]) and
+ (m_delphi in current_settings.modeswitches)) then
+ begin
+ doconv:=tc_real_2_real;
+ { do we lose precision? }
+ if (def_to.size<def_from.size) or
+ (is_currency(def_from) and (tfloatdef(def_to).floattype in [s32real,s64real])) then
+ eq:=te_convert_l2
+ else
+ eq:=te_convert_l1;
+ end;
+ end;
+ end;
+ end;
+ end;
+
+ enumdef :
+ begin
+ case def_from.typ of
+ enumdef :
+ begin
+ if cdo_explicit in cdoptions then
+ begin
+ eq:=te_convert_l1;
+ doconv:=tc_int_2_int;
+ end
+ else
+ begin
+ hd1:=def_from;
+ while assigned(tenumdef(hd1).basedef) do
+ hd1:=tenumdef(hd1).basedef;
+ hd2:=def_to;
+ while assigned(tenumdef(hd2).basedef) do
+ hd2:=tenumdef(hd2).basedef;
+ if (hd1=hd2) then
+ begin
+ eq:=te_convert_l1;
+ { because of packenum they can have different sizes! (JM) }
+ doconv:=tc_int_2_int;
+ end
+ else
+ begin
+ { assignment of an enum symbol to an unique type? }
+ if (fromtreetype=ordconstn) and
+ (tenumsym(tenumdef(hd1).getfirstsym)=tenumsym(tenumdef(hd2).getfirstsym)) then
+ begin
+ { because of packenum they can have different sizes! (JM) }
+ eq:=te_convert_l1;
+ doconv:=tc_int_2_int;
+ end;
+ end;
+ end;
+ end;
+ orddef :
+ begin
+ if cdo_explicit in cdoptions then
+ begin
+ eq:=te_convert_l1;
+ doconv:=tc_int_2_int;
+ end;
+ end;
+ variantdef :
+ begin
+ eq:=te_convert_l1;
+ doconv:=tc_variant_2_enum;
+ end;
+ pointerdef :
+ begin
+ { ugly, but delphi allows it }
+ if (cdo_explicit in cdoptions) and
+ (m_delphi in current_settings.modeswitches) then
+ begin
+ doconv:=tc_int_2_int;
+ eq:=te_convert_l1;
+ end;
+ end;
+ objectdef:
+ begin
+ { ugly, but delphi allows it }
+ if (m_delphi in current_settings.modeswitches) and
+ is_class_or_interface_or_dispinterface(def_from) and
+ (cdo_explicit in cdoptions) then
+ begin
+ doconv:=tc_int_2_int;
+ eq:=te_convert_l1;
+ end;
+ end;
+ end;
+ end;
+
+ arraydef :
+ begin
+ { open array is also compatible with a single element of its base type.
+ the extra check for deftyp is needed because equal defs can also return
+ true if the def types are not the same, for example with dynarray to pointer. }
+ if is_open_array(def_to) and
+ (def_from.typ=tarraydef(def_to).elementdef.typ) and
+ equal_defs(def_from,tarraydef(def_to).elementdef) then
+ begin
+ doconv:=tc_equal;
+ { also update in htypechk.pas/var_para_allowed if changed
+ here }
+ eq:=te_convert_l3;
+ end
+ else
+ begin
+ case def_from.typ of
+ arraydef :
+ begin
+ { from/to packed array -- packed chararrays are }
+ { strings in ISO Pascal (at least if the lower bound }
+ { is 1, but GPC makes all equal-length chararrays }
+ { compatible), so treat those the same as regular }
+ { char arrays }
+ if (is_packed_array(def_from) and
+ not is_chararray(def_from) and
+ not is_widechararray(def_from)) xor
+ (is_packed_array(def_to) and
+ not is_chararray(def_to) and
+ not is_widechararray(def_to)) then
+ { both must be packed }
+ begin
+ compare_defs_ext:=te_incompatible;
+ exit;
+ end
+ { to dynamic array }
+ else if is_dynamic_array(def_to) then
+ begin
+ if equal_defs(tarraydef(def_from).elementdef,tarraydef(def_to).elementdef) then
+ begin
+ { dynamic array -> dynamic array }
+ if is_dynamic_array(def_from) then
+ eq:=te_equal
+ { fpc modes only: array -> dyn. array }
+ else if (current_settings.modeswitches*[m_objfpc,m_fpc]<>[]) and
+ not(is_special_array(def_from)) and
+ is_zero_based_array(def_from) then
+ begin
+ eq:=te_convert_l2;
+ doconv:=tc_array_2_dynarray;
+ end;
+ end
+ end
+ else
+ { to open array }
+ if is_open_array(def_to) then
+ begin
+ { array constructor -> open array }
+ if is_array_constructor(def_from) then
+ begin
+ if is_void(tarraydef(def_from).elementdef) then
+ begin
+ doconv:=tc_equal;
+ eq:=te_convert_l1;
+ end
+ else
+ begin
+ subeq:=compare_defs_ext(tarraydef(def_from).elementdef,
+ tarraydef(def_to).elementdef,
+ { reason for cdo_allow_variant: see webtbs/tw7070a and webtbs/tw7070b }
+ arrayconstructorn,hct,hpd,[cdo_check_operator,cdo_allow_variant]);
+ if (subeq>=te_equal) then
+ begin
+ doconv:=tc_equal;
+ eq:=te_convert_l1;
+ end
+ else
+ if (subeq>te_incompatible) then
+ begin
+ doconv:=hct;
+ eq:=te_convert_l2;
+ end;
+ end;
+ end
+ else
+ { dynamic array -> open array }
+ if is_dynamic_array(def_from) and
+ equal_defs(tarraydef(def_from).elementdef,tarraydef(def_to).elementdef) then
+ begin
+ doconv:=tc_dynarray_2_openarray;
+ eq:=te_convert_l2;
+ end
+ else
+ { open array -> open array }
+ if is_open_array(def_from) and
+ equal_defs(tarraydef(def_from).elementdef,tarraydef(def_to).elementdef) then
+ if tarraydef(def_from).elementdef=tarraydef(def_to).elementdef then
+ eq:=te_exact
+ else
+ eq:=te_equal
+ else
+ { array -> open array }
+ if not(cdo_parameter in cdoptions) and
+ equal_defs(tarraydef(def_from).elementdef,tarraydef(def_to).elementdef) then
+ begin
+ if fromtreetype=stringconstn then
+ eq:=te_convert_l1
+ else
+ eq:=te_equal;
+ end;
+ end
+ else
+ { to array of const }
+ if is_array_of_const(def_to) then
+ begin
+ if is_array_of_const(def_from) or
+ is_array_constructor(def_from) then
+ begin
+ eq:=te_equal;
+ end
+ else
+ { array of tvarrec -> array of const }
+ if equal_defs(tarraydef(def_to).elementdef,tarraydef(def_from).elementdef) then
+ begin
+ doconv:=tc_equal;
+ eq:=te_convert_l1;
+ end;
+ end
+ else
+ { to array of char, from "Untyped" stringconstn (array of char) }
+ if (fromtreetype=stringconstn) and
+ (is_chararray(def_to) or
+ is_widechararray(def_to)) then
+ begin
+ eq:=te_convert_l1;
+ doconv:=tc_string_2_chararray;
+ end
+ else
+ { other arrays }
+ begin
+ { open array -> array }
+ if not(cdo_parameter in cdoptions) and
+ is_open_array(def_from) and
+ equal_defs(tarraydef(def_from).elementdef,tarraydef(def_to).elementdef) then
+ begin
+ eq:=te_equal
+ end
+ else
+ { array -> array }
+ if not(m_tp7 in current_settings.modeswitches) and
+ not(m_delphi in current_settings.modeswitches) and
+ (tarraydef(def_from).lowrange=tarraydef(def_to).lowrange) and
+ (tarraydef(def_from).highrange=tarraydef(def_to).highrange) and
+ equal_defs(tarraydef(def_from).elementdef,tarraydef(def_to).elementdef) and
+ equal_defs(tarraydef(def_from).rangedef,tarraydef(def_to).rangedef) then
+ begin
+ eq:=te_equal
+ end;
+ end;
+ end;
+ pointerdef :
+ begin
+ { nil and voidpointers are compatible with dyn. arrays }
+ if is_dynamic_array(def_to) and
+ ((fromtreetype=niln) or
+ is_voidpointer(def_from)) then
+ begin
+ doconv:=tc_equal;
+ eq:=te_convert_l1;
+ end
+ else
+ if is_zero_based_array(def_to) and
+ equal_defs(tpointerdef(def_from).pointeddef,tarraydef(def_to).elementdef) then
+ begin
+ doconv:=tc_pointer_2_array;
+ eq:=te_convert_l1;
+ end;
+ end;
+ stringdef :
+ begin
+ { string to char array }
+ if (not is_special_array(def_to)) and
+ (is_char(tarraydef(def_to).elementdef)or
+ is_widechar(tarraydef(def_to).elementdef)) then
+ begin
+ doconv:=tc_string_2_chararray;
+ eq:=te_convert_l1;
+ end;
+ end;
+ orddef:
+ begin
+ if is_chararray(def_to) and
+ is_char(def_from) then
+ begin
+ doconv:=tc_char_2_chararray;
+ eq:=te_convert_l2;
+ end;
+ end;
+ recorddef :
+ begin
+ { tvarrec -> array of const }
+ if is_array_of_const(def_to) and
+ equal_defs(def_from,tarraydef(def_to).elementdef) then
+ begin
+ doconv:=tc_equal;
+ eq:=te_convert_l1;
+ end;
+ end;
+ variantdef :
+ begin
+ if is_dynamic_array(def_to) then
+ begin
+ doconv:=tc_variant_2_dynarray;
+ eq:=te_convert_l1;
+ end;
+ end;
+ end;
+ end;
+ end;
+
+ variantdef :
+ begin
+ if (cdo_allow_variant in cdoptions) then
+ begin
+ case def_from.typ of
+ enumdef :
+ begin
+ doconv:=tc_enum_2_variant;
+ eq:=te_convert_l1;
+ end;
+ arraydef :
+ begin
+ if is_dynamic_array(def_from) then
+ begin
+ doconv:=tc_dynarray_2_variant;
+ eq:=te_convert_l1;
+ end;
+ end;
+ objectdef :
+ begin
+ { corbainterfaces not accepted, until we have
+ runtime support for them in Variants (sergei) }
+ if is_interfacecom_or_dispinterface(def_from) then
+ begin
+ doconv:=tc_interface_2_variant;
+ eq:=te_convert_l1;
+ end;
+ end;
+ variantdef :
+ begin
+ { doing this in the compiler avoids a lot of unncessary
+ copying }
+ if (tvariantdef(def_from).varianttype=vt_olevariant) and
+ (tvariantdef(def_to).varianttype=vt_normalvariant) then
+ begin
+ doconv:=tc_equal;
+ eq:=te_convert_l1;
+ end;
+ end;
+ end;
+ end;
+ end;
+
+ pointerdef :
+ begin
+ case def_from.typ of
+ stringdef :
+ begin
+ { string constant (which can be part of array constructor)
+ to zero terminated string constant }
+ if (fromtreetype = stringconstn) and
+ (is_pchar(def_to) or is_pwidechar(def_to)) then
+ begin
+ doconv:=tc_cstring_2_pchar;
+ eq:=te_convert_l2;
+ end
+ else
+ if (cdo_explicit in cdoptions) or (fromtreetype = arrayconstructorn) then
+ begin
+ { pchar(ansistring) }
+ if is_pchar(def_to) and
+ is_ansistring(def_from) then
+ begin
+ doconv:=tc_ansistring_2_pchar;
+ eq:=te_convert_l1;
+ end
+ else
+ { pwidechar(widestring) }
+ if is_pwidechar(def_to) and
+ is_wide_or_unicode_string(def_from) then
+ begin
+ doconv:=tc_ansistring_2_pchar;
+ eq:=te_convert_l1;
+ end;
+ end;
+ end;
+ orddef :
+ begin
+ { char constant to zero terminated string constant }
+ if (fromtreetype in [ordconstn,arrayconstructorn]) then
+ begin
+ if (is_char(def_from) or is_widechar(def_from)) and
+ (is_pchar(def_to) or is_pwidechar(def_to)) then
+ begin
+ doconv:=tc_cchar_2_pchar;
+ eq:=te_convert_l1;
+ end
+ else
+ if (m_delphi in current_settings.modeswitches) and is_integer(def_from) then
+ begin
+ doconv:=tc_cord_2_pointer;
+ eq:=te_convert_l5;
+ end;
+ end;
+ { allow explicit typecasts from ordinals to pointer.
+ Support for delphi compatibility
+ Support constructs like pointer(cardinal-cardinal) or pointer(longint+cardinal) where
+ the result of the ordinal operation is int64 also on 32 bit platforms.
+ It is also used by the compiler internally for inc(pointer,ordinal) }
+ if (eq=te_incompatible) and
+ not is_void(def_from) and
+ (
+ (
+ (cdo_explicit in cdoptions) and
+ (
+ (m_delphi in current_settings.modeswitches) or
+ { Don't allow pchar(char) in fpc modes }
+ is_integer(def_from)
+ )
+ ) or
+ (cdo_internal in cdoptions)
+ ) then
+ begin
+ doconv:=tc_int_2_int;
+ eq:=te_convert_l1;
+ end;
+ end;
+ enumdef :
+ begin
+ { allow explicit typecasts from enums to pointer.
+ Support for delphi compatibility
+ }
+ if (((cdo_explicit in cdoptions) and
+ (m_delphi in current_settings.modeswitches)
+ ) or
+ (cdo_internal in cdoptions)
+ ) then
+ begin
+ doconv:=tc_int_2_int;
+ eq:=te_convert_l1;
+ end;
+ end;
+ arraydef :
+ begin
+ { string constant (which can be part of array constructor)
+ to zero terminated string constant }
+ if (((fromtreetype = arrayconstructorn) and
+ { can't use is_chararray, because returns false for }
+ { array constructors }
+ is_char(tarraydef(def_from).elementdef)) or
+ (fromtreetype = stringconstn)) and
+ (is_pchar(def_to) or is_pwidechar(def_to)) then
+ begin
+ doconv:=tc_cstring_2_pchar;
+ eq:=te_convert_l2;
+ end
+ else
+ { chararray to pointer }
+ if (is_zero_based_array(def_from) or
+ is_open_array(def_from)) and
+ equal_defs(tarraydef(def_from).elementdef,tpointerdef(def_to).pointeddef) then
+ begin
+ doconv:=tc_array_2_pointer;
+ { don't prefer the pchar overload when a constant
+ string was passed }
+ if fromtreetype=stringconstn then
+ eq:=te_convert_l2
+ else
+ eq:=te_convert_l1;
+ end
+ else
+ { dynamic array to pointer, delphi only }
+ if (m_delphi in current_settings.modeswitches) and
+ is_dynamic_array(def_from) and
+ is_voidpointer(def_to) then
+ begin
+ eq:=te_equal;
+ end;
+ end;
+ pointerdef :
+ begin
+ { check for far pointers }
+ if (tpointerdef(def_from).is_far<>tpointerdef(def_to).is_far) then
+ begin
+ eq:=te_incompatible;
+ end
+ else
+ { the types can be forward type, handle before normal type check !! }
+ if assigned(def_to.typesym) and
+ (tpointerdef(def_to).pointeddef.typ=forwarddef) then
+ begin
+ if (def_from.typesym=def_to.typesym) then
+ eq:=te_equal
+ end
+ else
+ { same types }
+ if equal_defs(tpointerdef(def_from).pointeddef,tpointerdef(def_to).pointeddef) then
+ begin
+ eq:=te_equal
+ end
+ else
+ { child class pointer can be assigned to anchestor pointers }
+ if (
+ (tpointerdef(def_from).pointeddef.typ=objectdef) and
+ (tpointerdef(def_to).pointeddef.typ=objectdef) and
+ tobjectdef(tpointerdef(def_from).pointeddef).is_related(
+ tobjectdef(tpointerdef(def_to).pointeddef))
+ ) then
+ begin
+ doconv:=tc_equal;
+ eq:=te_convert_l1;
+ end
+ else
+ { all pointers can be assigned to void-pointer }
+ if is_void(tpointerdef(def_to).pointeddef) then
+ begin
+ doconv:=tc_equal;
+ { give pwidechar,pchar a penalty so it prefers
+ conversion to ansistring }
+ if is_pchar(def_from) or
+ is_pwidechar(def_from) then
+ eq:=te_convert_l2
+ else
+ eq:=te_convert_l1;
+ end
+ else
+ { all pointers can be assigned from void-pointer }
+ if is_void(tpointerdef(def_from).pointeddef) or
+ { all pointers can be assigned from void-pointer or formaldef pointer, check
+ tw3777.pp if you change this }
+ (tpointerdef(def_from).pointeddef.typ=formaldef) then
+ begin
+ doconv:=tc_equal;
+ { give pwidechar a penalty so it prefers
+ conversion to pchar }
+ if is_pwidechar(def_to) then
+ eq:=te_convert_l2
+ else
+ eq:=te_convert_l1;
+ end
+ { id = generic class instance. metaclasses are also
+ class instances themselves. }
+ else if ((def_from=objc_idtype) and
+ (def_to=objc_metaclasstype)) or
+ ((def_to=objc_idtype) and
+ (def_from=objc_metaclasstype)) then
+ begin
+ doconv:=tc_equal;
+ eq:=te_convert_l2;
+ end;
+ end;
+ procvardef :
+ begin
+ { procedure variable can be assigned to an void pointer,
+ this is not allowed for complex procvars }
+ if (is_void(tpointerdef(def_to).pointeddef) or
+ (m_mac_procvar in current_settings.modeswitches)) and
+ tprocvardef(def_from).is_addressonly then
+ begin
+ doconv:=tc_equal;
+ eq:=te_convert_l1;
+ end;
+ end;
+ procdef :
+ begin
+ { procedure variable can be assigned to an void pointer,
+ this not allowed for methodpointers }
+ if (m_mac_procvar in current_settings.modeswitches) and
+ tprocdef(def_from).is_addressonly then
+ begin
+ doconv:=tc_proc_2_procvar;
+ eq:=te_convert_l2;
+ end;
+ end;
+ classrefdef,
+ objectdef :
+ begin
+ { implicit pointer object and class reference types
+ can be assigned to void pointers, but it is less
+ preferred than assigning to a related objectdef }
+ if (
+ is_implicit_pointer_object_type(def_from) or
+ (def_from.typ=classrefdef)
+ ) and
+ (tpointerdef(def_to).pointeddef.typ=orddef) and
+ (torddef(tpointerdef(def_to).pointeddef).ordtype=uvoid) then
+ begin
+ doconv:=tc_equal;
+ eq:=te_convert_l2;
+ end
+ else if (is_objc_class_or_protocol(def_from) and
+ (def_to=objc_idtype)) or
+ { classrefs are also instances in Objective-C,
+ hence they're also assignment-cpmpatible with
+ id }
+ (is_objcclassref(def_from) and
+ ((def_to=objc_metaclasstype) or
+ (def_to=objc_idtype))) then
+ begin
+ doconv:=tc_equal;
+ eq:=te_convert_l2;
+ end;
+ end;
+ end;
+ end;
+
+ setdef :
+ begin
+ case def_from.typ of
+ setdef :
+ begin
+ if assigned(tsetdef(def_from).elementdef) and
+ assigned(tsetdef(def_to).elementdef) then
+ begin
+ { sets with the same element base type and the same range are equal }
+ if equal_defs(tsetdef(def_from).elementdef,tsetdef(def_to).elementdef) and
+ (tsetdef(def_from).setbase=tsetdef(def_to).setbase) and
+ (tsetdef(def_from).setmax=tsetdef(def_to).setmax) then
+ eq:=te_equal
+ else if is_subequal(tsetdef(def_from).elementdef,tsetdef(def_to).elementdef) then
+ begin
+ eq:=te_convert_l1;
+ doconv:=tc_set_to_set;
+ end;
+ end
+ else
+ begin
+ { empty set is compatible with everything }
+ eq:=te_convert_l1;
+ doconv:=tc_set_to_set;
+ end;
+ end;
+ arraydef :
+ begin
+ { automatic arrayconstructor -> set conversion }
+ if is_array_constructor(def_from) then
+ begin
+ doconv:=tc_arrayconstructor_2_set;
+ eq:=te_convert_l1;
+ end;
+ end;
+ end;
+ end;
+
+ procvardef :
+ begin
+ case def_from.typ of
+ procdef :
+ begin
+ { proc -> procvar }
+ if (m_tp_procvar in current_settings.modeswitches) or
+ (m_mac_procvar in current_settings.modeswitches) then
+ begin
+ subeq:=proc_to_procvar_equal(tprocdef(def_from),tprocvardef(def_to),cdo_warn_incompatible_univ in cdoptions);
+ if subeq>te_incompatible then
+ begin
+ doconv:=tc_proc_2_procvar;
+ if subeq>te_convert_l5 then
+ eq:=pred(subeq)
+ else
+ eq:=subeq;
+ end;
+ end;
+ end;
+ procvardef :
+ begin
+ { procvar -> procvar }
+ eq:=proc_to_procvar_equal(tprocvardef(def_from),tprocvardef(def_to),cdo_warn_incompatible_univ in cdoptions);
+ end;
+ pointerdef :
+ begin
+ { nil is compatible with procvars }
+ if (fromtreetype=niln) then
+ begin
+ if not Tprocvardef(def_to).is_addressonly then
+ {Nil to method pointers requires to convert a single
+ pointer nil value to a two pointer procvardef.}
+ doconv:=tc_nil_2_methodprocvar
+ else
+ doconv:=tc_equal;
+ eq:=te_convert_l1;
+ end
+ else
+ { for example delphi allows the assignement from pointers }
+ { to procedure variables }
+ if (m_pointer_2_procedure in current_settings.modeswitches) and
+ is_void(tpointerdef(def_from).pointeddef) and
+ tprocvardef(def_to).is_addressonly then
+ begin
+ doconv:=tc_equal;
+ eq:=te_convert_l1;
+ end;
+ end;
+ end;
+ end;
+
+ objectdef :
+ begin
+ { Objective-C classes (handle anonymous externals) }
+ if (def_from.typ=objectdef) and
+ (find_real_objcclass_definition(tobjectdef(def_from),false) =
+ find_real_objcclass_definition(tobjectdef(def_to),false)) then
+ begin
+ doconv:=tc_equal;
+ { exact, not equal, because can change between interface
+ and implementation }
+ eq:=te_exact;
+ end
+ { object pascal objects }
+ else if (def_from.typ=objectdef) and
+ (tobjectdef(def_from).is_related(tobjectdef(def_to))) then
+ begin
+ doconv:=tc_equal;
+ eq:=te_convert_l1;
+ end
+ else
+ { specific to implicit pointer object types }
+ if is_implicit_pointer_object_type(def_to) then
+ begin
+ { void pointer also for delphi mode }
+ if (m_delphi in current_settings.modeswitches) and
+ is_voidpointer(def_from) then
+ begin
+ doconv:=tc_equal;
+ { prefer pointer-pointer assignments }
+ eq:=te_convert_l2;
+ end
+ else
+ { nil is compatible with class instances and interfaces }
+ if (fromtreetype=niln) then
+ begin
+ doconv:=tc_equal;
+ eq:=te_convert_l1;
+ end
+ { All Objective-C classes are compatible with ID }
+ else if is_objc_class_or_protocol(def_to) and
+ (def_from=objc_idtype) then
+ begin
+ doconv:=tc_equal;
+ eq:=te_convert_l2;
+ end
+ { classes can be assigned to interfaces
+ (same with objcclass and objcprotocol) }
+ else if ((is_interface(def_to) and
+ is_class(def_from)) or
+ (is_objcprotocol(def_to) and
+ is_objcclass(def_from))) and
+ assigned(tobjectdef(def_from).ImplementedInterfaces) then
+ begin
+ { we've to search in parent classes as well }
+ hobjdef:=tobjectdef(def_from);
+ while assigned(hobjdef) do
+ begin
+ if hobjdef.find_implemented_interface(tobjectdef(def_to))<>nil then
+ begin
+ if is_interface(def_to) then
+ doconv:=tc_class_2_intf
+ else
+ { for Objective-C, we don't have to do anything special }
+ doconv:=tc_equal;
+ { don't prefer this over objectdef->objectdef }
+ eq:=te_convert_l2;
+ break;
+ end;
+ hobjdef:=hobjdef.childof;
+ end;
+ end
+ { Interface 2 GUID handling }
+ else if (def_to=tdef(rec_tguid)) and
+ (fromtreetype=typen) and
+ is_interface(def_from) and
+ assigned(tobjectdef(def_from).iidguid) then
+ begin
+ eq:=te_convert_l1;
+ doconv:=tc_equal;
+ end
+ else if (def_from.typ=variantdef) and is_interfacecom_or_dispinterface(def_to) then
+ begin
+ { corbainterfaces not accepted, until we have
+ runtime support for them in Variants (sergei) }
+ doconv:=tc_variant_2_interface;
+ eq:=te_convert_l2;
+ end
+ { ugly, but delphi allows it }
+ else if (def_from.typ in [orddef,enumdef]) and
+ (m_delphi in current_settings.modeswitches) and
+ (cdo_explicit in cdoptions) then
+ begin
+ doconv:=tc_int_2_int;
+ eq:=te_convert_l1;
+ end;
+ end;
+ end;
+
+ classrefdef :
+ begin
+ { similar to pointerdef wrt forwards }
+ if assigned(def_to.typesym) and
+ (tclassrefdef(def_to).pointeddef.typ=forwarddef) then
+ begin
+ if (def_from.typesym=def_to.typesym) then
+ eq:=te_equal;
+ end
+ else
+ { class reference types }
+ if (def_from.typ=classrefdef) then
+ begin
+ if equal_defs(tclassrefdef(def_from).pointeddef,tclassrefdef(def_to).pointeddef) then
+ begin
+ eq:=te_equal;
+ end
+ else
+ begin
+ doconv:=tc_equal;
+ if (cdo_explicit in cdoptions) or
+ tobjectdef(tclassrefdef(def_from).pointeddef).is_related(
+ tobjectdef(tclassrefdef(def_to).pointeddef)) then
+ eq:=te_convert_l1;
+ end;
+ end
+ else
+ if (m_delphi in current_settings.modeswitches) and
+ is_voidpointer(def_from) then
+ begin
+ doconv:=tc_equal;
+ { prefer pointer-pointer assignments }
+ eq:=te_convert_l2;
+ end
+ else
+ { nil is compatible with class references }
+ if (fromtreetype=niln) then
+ begin
+ doconv:=tc_equal;
+ eq:=te_convert_l1;
+ end
+ else
+ { id is compatible with all classref types }
+ if (def_from=objc_idtype) then
+ begin
+ doconv:=tc_equal;
+ eq:=te_convert_l1;
+ end;
+ end;
+
+ filedef :
+ begin
+ { typed files are all equal to the abstract file type
+ name TYPEDFILE in system.pp in is_equal in types.pas
+ the problem is that it sholud be also compatible to FILE
+ but this would leed to a problem for ASSIGN RESET and REWRITE
+ when trying to find the good overloaded function !!
+ so all file function are doubled in system.pp
+ this is not very beautiful !!}
+ if (def_from.typ=filedef) then
+ begin
+ if (tfiledef(def_from).filetyp=tfiledef(def_to).filetyp) then
+ begin
+ if
+ (
+ (tfiledef(def_from).typedfiledef=nil) and
+ (tfiledef(def_to).typedfiledef=nil)
+ ) or
+ (
+ (tfiledef(def_from).typedfiledef<>nil) and
+ (tfiledef(def_to).typedfiledef<>nil) and
+ equal_defs(tfiledef(def_from).typedfiledef,tfiledef(def_to).typedfiledef)
+ ) or
+ (
+ (tfiledef(def_from).filetyp = ft_typed) and
+ (tfiledef(def_to).filetyp = ft_typed) and
+ (
+ (tfiledef(def_from).typedfiledef = tdef(voidtype)) or
+ (tfiledef(def_to).typedfiledef = tdef(voidtype))
+ )
+ ) then
+ begin
+ eq:=te_equal;
+ end;
+ end
+ else
+ if ((tfiledef(def_from).filetyp = ft_untyped) and
+ (tfiledef(def_to).filetyp = ft_typed)) or
+ ((tfiledef(def_from).filetyp = ft_typed) and
+ (tfiledef(def_to).filetyp = ft_untyped)) then
+ begin
+ doconv:=tc_equal;
+ eq:=te_convert_l1;
+ end;
+ end;
+ end;
+
+ recorddef :
+ begin
+ { interface -> guid }
+ if (def_to=rec_tguid) and
+ (is_interfacecom_or_dispinterface(def_from)) then
+ begin
+ doconv:=tc_intf_2_guid;
+ eq:=te_convert_l1;
+ end;
+ end;
+
+ formaldef :
+ begin
+ doconv:=tc_equal;
+ if (def_from.typ=formaldef) then
+ eq:=te_equal
+ else
+ { Just about everything can be converted to a formaldef...}
+ if not (def_from.typ in [abstractdef,errordef]) then
+ eq:=te_convert_l2;
+ end;
+ end;
+
+ { if we didn't find an appropriate type conversion yet
+ then we search also the := operator }
+ if (eq=te_incompatible) and
+ { make sure there is not a single variant if variants }
+ { are not allowed (otherwise if only cdo_check_operator }
+ { and e.g. fromdef=stringdef and todef=variantdef, then }
+ { the test will still succeed }
+ ((cdo_allow_variant in cdoptions) or
+ ((def_from.typ<>variantdef) and (def_to.typ<>variantdef))
+ ) and
+ (
+ { Check for variants? }
+ (
+ (cdo_allow_variant in cdoptions) and
+ ((def_from.typ=variantdef) or (def_to.typ=variantdef))
+ ) or
+ { Check for operators? }
+ (
+ (cdo_check_operator in cdoptions) and
+ ((def_from.typ<>variantdef) or (def_to.typ<>variantdef))
+ )
+ ) then
+ begin
+ operatorpd:=search_assignment_operator(def_from,def_to,cdo_explicit in cdoptions);
+ if assigned(operatorpd) then
+ eq:=te_convert_operator;
+ end;
+
+ { update convtype for te_equal when it is not yet set }
+ if (eq=te_equal) and
+ (doconv=tc_not_possible) then
+ doconv:=tc_equal;
+
+ compare_defs_ext:=eq;
+ end;
+
+
+ function equal_defs(def_from,def_to:tdef):boolean;
+ var
+ convtyp : tconverttype;
+ pd : tprocdef;
+ begin
+ { Compare defs with nothingn and no explicit typecasts and
+ searching for overloaded operators is not needed }
+ equal_defs:=(compare_defs_ext(def_from,def_to,nothingn,convtyp,pd,[])>=te_equal);
+ end;
+
+
+ function compare_defs(def_from,def_to:tdef;fromtreetype:tnodetype):tequaltype;
+ var
+ doconv : tconverttype;
+ pd : tprocdef;
+ begin
+ compare_defs:=compare_defs_ext(def_from,def_to,fromtreetype,doconv,pd,[cdo_check_operator,cdo_allow_variant]);
+ end;
+
+
+ function is_subequal(def1, def2: tdef): boolean;
+ var
+ basedef1,basedef2 : tenumdef;
+
+ Begin
+ is_subequal := false;
+ if assigned(def1) and assigned(def2) then
+ Begin
+ if (def1.typ = orddef) and (def2.typ = orddef) then
+ Begin
+ { see p.47 of Turbo Pascal 7.01 manual for the separation of types }
+ { range checking for case statements is done with testrange }
+ case torddef(def1).ordtype of
+ u8bit,u16bit,u32bit,u64bit,
+ s8bit,s16bit,s32bit,s64bit :
+ is_subequal:=(torddef(def2).ordtype in [s64bit,u64bit,s32bit,u32bit,u8bit,s8bit,s16bit,u16bit]);
+ pasbool8,pasbool16,pasbool32,pasbool64,
+ bool8bit,bool16bit,bool32bit,bool64bit :
+ is_subequal:=(torddef(def2).ordtype in [pasbool8,pasbool16,pasbool32,pasbool64,bool8bit,bool16bit,bool32bit,bool64bit]);
+ uchar :
+ is_subequal:=(torddef(def2).ordtype=uchar);
+ uwidechar :
+ is_subequal:=(torddef(def2).ordtype=uwidechar);
+ end;
+ end
+ else
+ Begin
+ { Check if both basedefs are equal }
+ if (def1.typ=enumdef) and (def2.typ=enumdef) then
+ Begin
+ { get both basedefs }
+ basedef1:=tenumdef(def1);
+ while assigned(basedef1.basedef) do
+ basedef1:=basedef1.basedef;
+ basedef2:=tenumdef(def2);
+ while assigned(basedef2.basedef) do
+ basedef2:=basedef2.basedef;
+ is_subequal:=(basedef1=basedef2);
+ end;
+ end;
+ end;
+ end;
+
+
+ function potentially_incompatible_univ_paras(def1, def2: tdef): boolean;
+ begin
+ result :=
+ { not entirely safe: different records can be passed differently
+ depending on the types of their fields, but they're hard to compare
+ (variant records, bitpacked vs non-bitpacked) }
+ ((def1.typ in [floatdef,recorddef,arraydef,filedef,variantdef]) and
+ (def1.typ<>def2.typ)) or
+ { pointers, ordinals and small sets are all passed the same}
+ (((def1.typ in [orddef,enumdef,pointerdef,procvardef,classrefdef]) or
+ (is_class_or_interface_or_objc(def1)) or
+ is_dynamic_array(def1) or
+ is_smallset(def1) or
+ is_ansistring(def1) or
+ is_unicodestring(def1)) <>
+ (def2.typ in [orddef,enumdef,pointerdef,procvardef,classrefdef]) or
+ (is_class_or_interface_or_objc(def2)) or
+ is_dynamic_array(def2) or
+ is_smallset(def2) or
+ is_ansistring(def2) or
+ is_unicodestring(def2)) or
+ { shortstrings }
+ (is_shortstring(def1)<>
+ is_shortstring(def2)) or
+ { winlike widestrings }
+ (is_widestring(def1)<>
+ is_widestring(def2)) or
+ { TP-style objects }
+ (is_object(def1) <>
+ is_object(def2));
+ end;
+
+
+ function compare_paras(para1,para2 : TFPObjectList; acp : tcompare_paras_type; cpoptions: tcompare_paras_options):tequaltype;
+ var
+ currpara1,
+ currpara2 : tparavarsym;
+ eq,lowesteq : tequaltype;
+ hpd : tprocdef;
+ convtype : tconverttype;
+ cdoptions : tcompare_defs_options;
+ i1,i2 : byte;
+ begin
+ compare_paras:=te_incompatible;
+ cdoptions:=[cdo_parameter,cdo_check_operator,cdo_allow_variant];
+ { we need to parse the list from left-right so the
+ not-default parameters are checked first }
+ lowesteq:=high(tequaltype);
+ i1:=0;
+ i2:=0;
+ if cpo_ignorehidden in cpoptions then
+ begin
+ while (i1<para1.count) and
+ (vo_is_hidden_para in tparavarsym(para1[i1]).varoptions) do
+ inc(i1);
+ while (i2<para2.count) and
+ (vo_is_hidden_para in tparavarsym(para2[i2]).varoptions) do
+ inc(i2);
+ end;
+ if cpo_ignoreframepointer in cpoptions then
+ begin
+ if (i1<para1.count) and
+ (vo_is_parentfp in tparavarsym(para1[i1]).varoptions) then
+ inc(i1);
+ if (i2<para2.count) and
+ (vo_is_parentfp in tparavarsym(para2[i2]).varoptions) then
+ inc(i2);
+ end;
+ while (i1<para1.count) and (i2<para2.count) do
+ begin
+ eq:=te_incompatible;
+
+ currpara1:=tparavarsym(para1[i1]);
+ currpara2:=tparavarsym(para2[i2]);
+
+ { Unique types must match exact }
+ if ((df_unique in currpara1.vardef.defoptions) or (df_unique in currpara2.vardef.defoptions)) and
+ (currpara1.vardef<>currpara2.vardef) then
+ exit;
+
+ { Handle hidden parameters separately, because self is
+ defined as voidpointer for methodpointers }
+ if (vo_is_hidden_para in currpara1.varoptions) or
+ (vo_is_hidden_para in currpara2.varoptions) then
+ begin
+ { both must be hidden }
+ if (vo_is_hidden_para in currpara1.varoptions)<>(vo_is_hidden_para in currpara2.varoptions) then
+ exit;
+ eq:=te_exact;
+ if not(vo_is_self in currpara1.varoptions) and
+ not(vo_is_self in currpara2.varoptions) then
+ begin
+ if not(cpo_ignorevarspez in cpoptions) and
+ (currpara1.varspez<>currpara2.varspez) then
+ exit;
+ eq:=compare_defs_ext(currpara1.vardef,currpara2.vardef,nothingn,
+ convtype,hpd,cdoptions);
+ end;
+ end
+ else
+ begin
+ case acp of
+ cp_value_equal_const :
+ begin
+ { this one is used for matching parameters from a call
+ statement to a procdef -> univ state can't be equal
+ in any case since the call statement does not contain
+ any information about that }
+ if (
+ not(cpo_ignorevarspez in cpoptions) and
+ (currpara1.varspez<>currpara2.varspez) and
+ ((currpara1.varspez in [vs_var,vs_out,vs_constref]) or
+ (currpara2.varspez in [vs_var,vs_out,vs_constref]))
+ ) then
+ exit;
+ eq:=compare_defs_ext(currpara1.vardef,currpara2.vardef,nothingn,
+ convtype,hpd,cdoptions);
+ end;
+ cp_all :
+ begin
+ { used to resolve forward definitions -> headers must
+ match exactly, including the "univ" specifier }
+ if (not(cpo_ignorevarspez in cpoptions) and
+ (currpara1.varspez<>currpara2.varspez)) or
+ (currpara1.univpara<>currpara2.univpara) then
+ exit;
+ eq:=compare_defs_ext(currpara1.vardef,currpara2.vardef,nothingn,
+ convtype,hpd,cdoptions);
+ end;
+ cp_procvar :
+ begin
+ if not(cpo_ignorevarspez in cpoptions) and
+ (currpara1.varspez<>currpara2.varspez) then
+ exit;
+ { "univ" state doesn't matter here: from univ to non-univ
+ matches if the types are compatible (i.e., as usual),
+ from from non-univ to univ also matches if the types
+ have the same size (checked below) }
+ eq:=compare_defs_ext(currpara1.vardef,currpara2.vardef,nothingn,
+ convtype,hpd,cdoptions);
+ { Parameters must be at least equal otherwise the are incompatible }
+ if (eq<te_equal) then
+ eq:=te_incompatible;
+ end;
+ else
+ eq:=compare_defs_ext(currpara1.vardef,currpara2.vardef,nothingn,
+ convtype,hpd,cdoptions);
+ end;
+ end;
+ { check type }
+ if eq=te_incompatible then
+ begin
+ { special case: "univ" parameters match if their size is equal }
+ if not(cpo_ignoreuniv in cpoptions) and
+ currpara2.univpara and
+ is_valid_univ_para_type(currpara1.vardef) and
+ (currpara1.vardef.size=currpara2.vardef.size) then
+ begin
+ { only pick as last choice }
+ eq:=te_convert_l5;
+ if (acp=cp_procvar) and
+ (cpo_warn_incompatible_univ in cpoptions) then
+ begin
+ { if the types may be passed in different ways by the
+ calling convention then this can lead to crashes
+ (note: not an exhaustive check, and failing this
+ this check does not mean things will crash on all
+ platforms) }
+ if potentially_incompatible_univ_paras(currpara1.vardef,currpara2.vardef) then
+ Message2(type_w_procvar_univ_conflicting_para,currpara1.vardef.typename,currpara2.vardef.typename)
+ end;
+ end
+ else
+ exit;
+ end;
+ { open strings can never match exactly, since you cannot define }
+ { a separate "open string" type -> we have to be able to }
+ { consider those as exact when resolving forward definitions. }
+ { The same goes for array of const. Open arrays are handled }
+ { already (if their element types match exactly, they are }
+ { considered to be an exact match) }
+ { And also for "inline defined" function parameter definitions }
+ { (i.e., function types directly declared in a parameter list) }
+ if (is_array_of_const(currpara1.vardef) or
+ is_open_string(currpara1.vardef) or
+ ((currpara1.vardef.typ = procvardef) and
+ not(assigned(currpara1.vardef.typesym)))) and
+ (eq=te_equal) and
+ (cpo_openequalisexact in cpoptions) then
+ eq:=te_exact;
+ if eq<lowesteq then
+ lowesteq:=eq;
+ { also check default value if both have it declared }
+ if (cpo_comparedefaultvalue in cpoptions) and
+ assigned(currpara1.defaultconstsym) and
+ assigned(currpara2.defaultconstsym) then
+ begin
+ if not equal_constsym(tconstsym(currpara1.defaultconstsym),tconstsym(currpara2.defaultconstsym)) then
+ exit;
+ end;
+ if not(cpo_compilerproc in cpoptions) and
+ not(cpo_rtlproc in cpoptions) and
+ is_ansistring(currpara1.vardef) and
+ is_ansistring(currpara2.vardef) and
+ (tstringdef(currpara1.vardef).encoding<>tstringdef(currpara2.vardef).encoding) and
+ ((tstringdef(currpara1.vardef).encoding=globals.CP_NONE) or
+ (tstringdef(currpara2.vardef).encoding=globals.CP_NONE)
+ ) then
+ eq:=te_convert_l1;
+ if eq<lowesteq then
+ lowesteq:=eq;
+ inc(i1);
+ inc(i2);
+ if cpo_ignorehidden in cpoptions then
+ begin
+ while (i1<para1.count) and
+ (vo_is_hidden_para in tparavarsym(para1[i1]).varoptions) do
+ inc(i1);
+ while (i2<para2.count) and
+ (vo_is_hidden_para in tparavarsym(para2[i2]).varoptions) do
+ inc(i2);
+ end;
+ if cpo_ignoreframepointer in cpoptions then
+ begin
+ if (i1<para1.count) and
+ (vo_is_parentfp in tparavarsym(para1[i1]).varoptions) then
+ inc(i1);
+ if (i2<para2.count) and
+ (vo_is_parentfp in tparavarsym(para2[i2]).varoptions) then
+ inc(i2);
+ end;
+ end;
+ { when both lists are empty then the parameters are equal. Also
+ when one list is empty and the other has a parameter with default
+ value assigned then the parameters are also equal }
+ if ((i1>=para1.count) and (i2>=para2.count)) or
+ ((cpo_allowdefaults in cpoptions) and
+ (((i1<para1.count) and assigned(tparavarsym(para1[i1]).defaultconstsym)) or
+ ((i2<para2.count) and assigned(tparavarsym(para2[i2]).defaultconstsym)))) then
+ compare_paras:=lowesteq;
+ end;
+
+
+ function proc_to_procvar_equal(def1:tabstractprocdef;def2:tprocvardef;checkincompatibleuniv: boolean):tequaltype;
+ var
+ eq : tequaltype;
+ po_comp : tprocoptions;
+ pa_comp: tcompare_paras_options;
+ begin
+ proc_to_procvar_equal:=te_incompatible;
+ if not(assigned(def1)) or not(assigned(def2)) then
+ exit;
+ { check for method pointer and local procedure pointer:
+ a) if one is a procedure of object, the other also has to be one
+ b) if one is a pure address, the other also has to be one
+ except if def1 is a global proc and def2 is a nested procdef
+ (global procedures can be converted into nested procvars)
+ c) if def1 is a nested procedure, then def2 has to be a nested
+ procvar and def1 has to have the po_delphi_nested_cc option
+ d) if def1 is a procvar, def1 and def2 both have to be nested or
+ non-nested (we don't allow assignments from non-nested to
+ nested procvars to make sure that we can still implement
+ nested procvars using trampolines -- e.g., this would be
+ necessary for LLVM or CIL as long as they do not have support
+ for Delphi-style frame pointer parameter passing) }
+ if (def1.is_methodpointer<>def2.is_methodpointer) or { a) }
+ ((def1.is_addressonly<>def2.is_addressonly) and { b) }
+ (is_nested_pd(def1) or
+ not is_nested_pd(def2))) or
+ ((def1.typ=procdef) and { c) }
+ is_nested_pd(def1) and
+ (not(po_delphi_nested_cc in def1.procoptions) or
+ not is_nested_pd(def2))) or
+ ((def1.typ=procvardef) and { d) }
+ (is_nested_pd(def1)<>is_nested_pd(def2))) then
+ exit;
+ pa_comp:=[cpo_ignoreframepointer];
+ if checkincompatibleuniv then
+ include(pa_comp,cpo_warn_incompatible_univ);
+ { check return value and options, methodpointer is already checked }
+ po_comp:=[po_staticmethod,po_interrupt,
+ po_iocheck,po_varargs];
+ if (m_delphi in current_settings.modeswitches) then
+ exclude(po_comp,po_varargs);
+ if (def1.proccalloption=def2.proccalloption) and
+ ((po_comp * def1.procoptions)= (po_comp * def2.procoptions)) and
+ equal_defs(def1.returndef,def2.returndef) then
+ begin
+ { return equal type based on the parameters, but a proc->procvar
+ is never exact, so map an exact match of the parameters to
+ te_equal }
+ eq:=compare_paras(def1.paras,def2.paras,cp_procvar,pa_comp);
+ if eq=te_exact then
+ eq:=te_equal;
+ if (eq=te_equal) then
+ begin
+ { prefer non-nested to non-nested over non-nested to nested }
+ if (is_nested_pd(def1)<>is_nested_pd(def2)) then
+ eq:=te_convert_l1;
+ end;
+ proc_to_procvar_equal:=eq;
+ end;
+ end;
+
+
+ function compatible_childmethod_resultdef(parentretdef, childretdef: tdef): boolean;
+ begin
+ compatible_childmethod_resultdef :=
+ (equal_defs(parentretdef,childretdef)) or
+ ((parentretdef.typ=objectdef) and
+ (childretdef.typ=objectdef) and
+ is_class_or_interface_or_objc(parentretdef) and
+ is_class_or_interface_or_objc(childretdef) and
+ (tobjectdef(childretdef).is_related(tobjectdef(parentretdef))))
+ end;
+
+
+end.
diff --git a/closures/compiler/defutil.pas b/closures/compiler/defutil.pas
new file mode 100644
index 0000000000..061044904e
--- /dev/null
+++ b/closures/compiler/defutil.pas
@@ -0,0 +1,1164 @@
+{
+ Copyright (c) 1998-2006 by Florian Klaempfl
+
+ This unit provides some help routines for type handling
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit defutil;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cclasses,
+ globtype,globals,constexp,node,
+ symconst,symbase,symtype,symdef,
+ cgbase,cpubase;
+
+ type
+ tmmxtype = (mmxno,mmxu8bit,mmxs8bit,mmxu16bit,mmxs16bit,
+ mmxu32bit,mmxs32bit,mmxfixed16,mmxsingle);
+
+
+{*****************************************************************************
+ Basic type functions
+ *****************************************************************************}
+
+ {# Returns true, if definition defines an ordinal type }
+ function is_ordinal(def : tdef) : boolean;
+
+ {# Returns true, if definition defines a string type }
+ function is_string(def : tdef): boolean;
+
+ {# Returns the minimal integer value of the type }
+ function get_min_value(def : tdef) : TConstExprInt;
+
+ {# Returns the maximal integer value of the type }
+ function get_max_value(def : tdef) : TConstExprInt;
+
+ {# Returns basetype of the specified integer range }
+ function range_to_basetype(l,h:TConstExprInt):tordtype;
+
+ procedure range_to_type(l,h:TConstExprInt;var def:tdef);
+
+ procedure int_to_type(v:TConstExprInt;var def:tdef);
+
+ {# Returns true, if definition defines an integer type }
+ function is_integer(def : tdef) : boolean;
+
+ {# Returns true if definition is a boolean }
+ function is_boolean(def : tdef) : boolean;
+
+ {# Returns true if definition is a Pascal-style boolean (1 = true, zero = false) }
+ function is_pasbool(def : tdef) : boolean;
+
+ {# Returns true if definition is a C-style boolean (non-zero value = true, zero = false) }
+ function is_cbool(def : tdef) : boolean;
+
+ {# Returns true if definition is a char
+
+ This excludes the unicode char.
+ }
+ function is_char(def : tdef) : boolean;
+
+ {# Returns true if definition is a widechar }
+ function is_widechar(def : tdef) : boolean;
+
+ {# Returns true if definition is either an AnsiChar or a WideChar }
+ function is_anychar(def : tdef) : boolean;
+
+ {# Returns true if definition is a void}
+ function is_void(def : tdef) : boolean;
+
+ {# Returns true if definition is a smallset}
+ function is_smallset(p : tdef) : boolean;
+
+ {# Returns true, if def defines a signed data type
+ (only for ordinal types)
+ }
+ function is_signed(def : tdef) : boolean;
+
+ {# Returns whether def_from's range is comprised in def_to's if both are
+ orddefs, false otherwise }
+ function is_in_limit(def_from,def_to : tdef) : boolean;
+
+ {# Returns whether def is reference counted }
+ function is_managed_type(def: tdef) : boolean;{$ifdef USEINLINE}inline;{$endif}
+
+
+{ function is_in_limit_value(val_from:TConstExprInt;def_from,def_to : tdef) : boolean;}
+
+{*****************************************************************************
+ Array helper functions
+ *****************************************************************************}
+
+ {# Returns true, if p points to a zero based (non special like open or
+ dynamic array def).
+
+ This is mainly used to see if the array
+ is convertable to a pointer
+ }
+ function is_zero_based_array(p : tdef) : boolean;
+
+ {# Returns true if p points to an open array definition }
+ function is_open_array(p : tdef) : boolean;
+
+ {# Returns true if p points to a dynamic array definition }
+ function is_dynamic_array(p : tdef) : boolean;
+
+ {# Returns true, if p points to an array of const definition }
+ function is_array_constructor(p : tdef) : boolean;
+
+ {# Returns true, if p points to a variant array }
+ function is_variant_array(p : tdef) : boolean;
+
+ {# Returns true, if p points to an array of const }
+ function is_array_of_const(p : tdef) : boolean;
+
+ {# Returns true, if p points any kind of special array
+
+ That is if the array is an open array, a variant
+ array, an array constants constructor, or an
+ array of const.
+
+ Bitpacked arrays aren't special in this regard though.
+ }
+ function is_special_array(p : tdef) : boolean;
+
+ {# Returns true if p is a bitpacked array }
+ function is_packed_array(p: tdef) : boolean;
+
+ {# Returns true if p is a bitpacked record }
+ function is_packed_record_or_object(p: tdef) : boolean;
+
+ {# Returns true if p is a char array def }
+ function is_chararray(p : tdef) : boolean;
+
+ {# Returns true if p is a wide char array def }
+ function is_widechararray(p : tdef) : boolean;
+
+ {# Returns true if p is a open char array def }
+ function is_open_chararray(p : tdef) : boolean;
+
+ {# Returns true if p is a open wide char array def }
+ function is_open_widechararray(p : tdef) : boolean;
+
+{*****************************************************************************
+ String helper functions
+ *****************************************************************************}
+
+ {# Returns true if p points to an open string type }
+ function is_open_string(p : tdef) : boolean;
+
+ {# Returns true if p is an ansi string type }
+ function is_ansistring(p : tdef) : boolean;
+
+ {# Returns true if p is an ansi string type with codepage 0 }
+ function is_rawbytestring(p : tdef) : boolean;
+
+ {# Returns true if p is a long string type }
+ function is_longstring(p : tdef) : boolean;
+
+ {# returns true if p is a wide string type }
+ function is_widestring(p : tdef) : boolean;
+
+ {# true if p is an unicode string def }
+ function is_unicodestring(p : tdef) : boolean;
+
+ {# returns true if p is a wide or unicode string type }
+ function is_wide_or_unicode_string(p : tdef) : boolean;
+
+ {# Returns true if p is a short string type }
+ function is_shortstring(p : tdef) : boolean;
+
+ {# Returns true if p is a pchar def }
+ function is_pchar(p : tdef) : boolean;
+
+ {# Returns true if p is a pwidechar def }
+ function is_pwidechar(p : tdef) : boolean;
+
+ {# Returns true if p is a voidpointer def }
+ function is_voidpointer(p : tdef) : boolean;
+
+ {# Returns true, if definition is a float }
+ function is_fpu(def : tdef) : boolean;
+
+ {# Returns true, if def is a currency type }
+ function is_currency(def : tdef) : boolean;
+
+ {# Returns true, if def is a single type }
+ function is_single(def : tdef) : boolean;
+
+ {# Returns true, if def is a double type }
+ function is_double(def : tdef) : boolean;
+
+ {# Returns true, if def is an extended type }
+ function is_extended(def : tdef) : boolean;
+
+ {# Returns true, if definition is a "real" real (i.e. single/double/extended) }
+ function is_real(def : tdef) : boolean;
+
+ {# Returns true, if def is a 32 bit integer type }
+ function is_32bitint(def : tdef) : boolean;
+
+ {# Returns true, if def is a 64 bit integer type }
+ function is_64bitint(def : tdef) : boolean;
+
+ {# Returns true, if def is a 64 bit type }
+ function is_64bit(def : tdef) : boolean;
+
+ {# If @var(l) isn't in the range of todef a range check error (if not explicit) is generated and
+ the value is placed within the range
+ }
+ procedure testrange(todef : tdef;var l : tconstexprint;explicit,forcerangecheck:boolean);
+
+ {# Returns the range of def, where @var(l) is the low-range and @var(h) is
+ the high-range.
+ }
+ procedure getrange(def : tdef;out l, h : TConstExprInt);
+
+ { type being a vector? }
+ function is_vector(p : tdef) : boolean;
+
+ { some type helper routines for MMX support }
+ function is_mmx_able_array(p : tdef) : boolean;
+
+ {# returns the mmx type }
+ function mmx_type(p : tdef) : tmmxtype;
+
+ { returns if the passed type (array) fits into an mm register }
+ function fits_in_mm_register(p : tdef) : boolean;
+
+ {# From a definition return the abstract code generator size enum. It is
+ to note that the value returned can be @var(OS_NO) }
+ function def_cgsize(def: tdef): tcgsize;
+
+ {# returns true, if the type passed is can be used with windows automation }
+ function is_automatable(p : tdef) : boolean;
+
+ { # returns true if the procdef has no parameters and no specified return type }
+ function is_bareprocdef(pd : tprocdef): boolean;
+
+ { # returns the smallest base integer type whose range encompasses that of
+ both ld and rd; if keep_sign_if_equal, then if ld and rd have the same
+ signdness, the result will also get that signdness }
+ function get_common_intdef(ld, rd: torddef; keep_sign_if_equal: boolean): torddef;
+
+ { # returns whether the type is potentially a valid type of/for an "univ" parameter
+ (basically: it must have a compile-time size) }
+ function is_valid_univ_para_type(def: tdef): boolean;
+
+ { # returns whether the procdef/procvardef represents a nested procedure
+ or not }
+ function is_nested_pd(def: tabstractprocdef): boolean;{$ifdef USEINLINE}inline;{$endif}
+
+ { # returns whether def is a type parameter of a generic }
+ function is_typeparam(def : tdef) : boolean;{$ifdef USEINLINE}inline;{$endif}
+
+implementation
+
+ uses
+ systems,verbose;
+
+ { returns true, if def uses FPU }
+ function is_fpu(def : tdef) : boolean;
+ begin
+ is_fpu:=(def.typ=floatdef);
+ end;
+
+
+ { returns true, if def is a currency type }
+ function is_currency(def : tdef) : boolean;
+ begin
+ case s64currencytype.typ of
+ orddef :
+ result:=(def.typ=orddef) and
+ (torddef(s64currencytype).ordtype=torddef(def).ordtype);
+ floatdef :
+ result:=(def.typ=floatdef) and
+ (tfloatdef(s64currencytype).floattype=tfloatdef(def).floattype);
+ else
+ internalerror(200304222);
+ end;
+ end;
+
+
+ { returns true, if def is a single type }
+ function is_single(def : tdef) : boolean;
+ begin
+ result:=(def.typ=floatdef) and
+ (tfloatdef(def).floattype=s32real);
+ end;
+
+
+ { returns true, if def is a double type }
+ function is_double(def : tdef) : boolean;
+ begin
+ result:=(def.typ=floatdef) and
+ (tfloatdef(def).floattype=s64real);
+ end;
+
+
+ function is_extended(def : tdef) : boolean;
+ begin
+ result:=(def.typ=floatdef) and
+ (tfloatdef(def).floattype in [s80real,sc80real]);
+ end;
+
+
+ { returns true, if definition is a "real" real (i.e. single/double/extended) }
+ function is_real(def : tdef) : boolean;
+ begin
+ result:=(def.typ=floatdef) and
+ (tfloatdef(def).floattype in [s32real,s64real,s80real]);
+ end;
+
+
+ function range_to_basetype(l,h:TConstExprInt):tordtype;
+ begin
+ { prefer signed over unsigned }
+ if (l>=int64(-128)) and (h<=127) then
+ range_to_basetype:=s8bit
+ else if (l>=0) and (h<=255) then
+ range_to_basetype:=u8bit
+ else if (l>=int64(-32768)) and (h<=32767) then
+ range_to_basetype:=s16bit
+ else if (l>=0) and (h<=65535) then
+ range_to_basetype:=u16bit
+ else if (l>=int64(low(longint))) and (h<=high(longint)) then
+ range_to_basetype:=s32bit
+ else if (l>=low(cardinal)) and (h<=high(cardinal)) then
+ range_to_basetype:=u32bit
+ else
+ range_to_basetype:=s64bit;
+ end;
+
+
+ procedure range_to_type(l,h:TConstExprInt;var def:tdef);
+ begin
+ { prefer signed over unsigned }
+ if (l>=int64(-128)) and (h<=127) then
+ def:=s8inttype
+ else if (l>=0) and (h<=255) then
+ def:=u8inttype
+ else if (l>=int64(-32768)) and (h<=32767) then
+ def:=s16inttype
+ else if (l>=0) and (h<=65535) then
+ def:=u16inttype
+ else if (l>=int64(low(longint))) and (h<=high(longint)) then
+ def:=s32inttype
+ else if (l>=low(cardinal)) and (h<=high(cardinal)) then
+ def:=u32inttype
+ else if (l>=low(int64)) and (h<=high(int64)) then
+ def:=s64inttype
+ else
+ def:=u64inttype;
+ end;
+
+
+ procedure int_to_type(v:TConstExprInt;var def:tdef);
+ begin
+ range_to_type(v,v,def);
+ end;
+
+
+ { true if p is an ordinal }
+ function is_ordinal(def : tdef) : boolean;
+ var
+ dt : tordtype;
+ begin
+ case def.typ of
+ orddef :
+ begin
+ dt:=torddef(def).ordtype;
+ is_ordinal:=dt in [uchar,uwidechar,
+ u8bit,u16bit,u32bit,u64bit,
+ s8bit,s16bit,s32bit,s64bit,
+ pasbool8,pasbool16,pasbool32,pasbool64,
+ bool8bit,bool16bit,bool32bit,bool64bit];
+ end;
+ enumdef :
+ is_ordinal:=true;
+ else
+ is_ordinal:=false;
+ end;
+ end;
+
+ { true if p is a string }
+ function is_string(def : tdef) : boolean;
+ begin
+ is_string := (assigned(def) and (def.typ = stringdef));
+ end;
+
+
+ { returns the min. value of the type }
+ function get_min_value(def : tdef) : TConstExprInt;
+ begin
+ case def.typ of
+ orddef:
+ result:=torddef(def).low;
+ enumdef:
+ result:=int64(tenumdef(def).min);
+ else
+ result:=0;
+ end;
+ end;
+
+
+ { returns the max. value of the type }
+ function get_max_value(def : tdef) : TConstExprInt;
+ begin
+ case def.typ of
+ orddef:
+ result:=torddef(def).high;
+ enumdef:
+ result:=tenumdef(def).max;
+ else
+ result:=0;
+ end;
+ end;
+
+
+ { true if p is an integer }
+ function is_integer(def : tdef) : boolean;
+ begin
+ result:=(def.typ=orddef) and
+ (torddef(def).ordtype in [u8bit,u16bit,u32bit,u64bit,
+ s8bit,s16bit,s32bit,s64bit]);
+ end;
+
+
+ { true if p is a boolean }
+ function is_boolean(def : tdef) : boolean;
+ begin
+ result:=(def.typ=orddef) and
+ (torddef(def).ordtype in [pasbool8,pasbool16,pasbool32,pasbool64,bool8bit,bool16bit,bool32bit,bool64bit]);
+ end;
+
+
+ function is_pasbool(def : tdef) : boolean;
+ begin
+ result:=(def.typ=orddef) and
+ (torddef(def).ordtype in [pasbool8,pasbool16,pasbool32,pasbool64]);
+ end;
+
+ { true if def is a C-style boolean (non-zero value = true, zero = false) }
+ function is_cbool(def : tdef) : boolean;
+ begin
+ result:=(def.typ=orddef) and
+ (torddef(def).ordtype in [bool8bit,bool16bit,bool32bit,bool64bit]);
+ end;
+
+
+ { true if p is a void }
+ function is_void(def : tdef) : boolean;
+ begin
+ result:=(def.typ=orddef) and
+ (torddef(def).ordtype=uvoid);
+ end;
+
+
+ { true if p is a char }
+ function is_char(def : tdef) : boolean;
+ begin
+ result:=(def.typ=orddef) and
+ (torddef(def).ordtype=uchar);
+ end;
+
+
+ { true if p is a wchar }
+ function is_widechar(def : tdef) : boolean;
+ begin
+ result:=(def.typ=orddef) and
+ (torddef(def).ordtype=uwidechar);
+ end;
+
+
+ { true if p is a char or wchar }
+ function is_anychar(def : tdef) : boolean;
+ begin
+ result:=(def.typ=orddef) and
+ (torddef(def).ordtype in [uchar,uwidechar])
+ end;
+
+
+ { true if p is signed (integer) }
+ function is_signed(def : tdef) : boolean;
+ begin
+ case def.typ of
+ orddef :
+ result:=torddef(def).low < 0;
+ enumdef :
+ result:=tenumdef(def).min < 0;
+ arraydef :
+ result:=is_signed(tarraydef(def).rangedef);
+ else
+ result:=false;
+ end;
+ end;
+
+
+ function is_in_limit(def_from,def_to : tdef) : boolean;
+
+ begin
+ if (def_from.typ<>def_to.typ) or
+ not(def_from.typ in [orddef,enumdef,setdef]) then
+ begin
+ is_in_limit := false;
+ exit;
+ end;
+ case def_from.typ of
+ orddef:
+ is_in_limit:=(torddef(def_from).low>=torddef(def_to).low) and
+ (torddef(def_from).high<=torddef(def_to).high);
+ enumdef:
+ is_in_limit:=(tenumdef(def_from).min>=tenumdef(def_to).min) and
+ (tenumdef(def_from).max<=tenumdef(def_to).max);
+ setdef:
+ is_in_limit:=(tsetdef(def_from).setbase>=tsetdef(def_to).setbase) and
+ (tsetdef(def_from).setmax<=tsetdef(def_to).setmax);
+ else
+ is_in_limit:=false;
+ end;
+ end;
+
+
+ function is_managed_type(def: tdef): boolean;{$ifdef USEINLINE}inline;{$endif}
+ begin
+ result:=def.needs_inittable;
+ end;
+
+
+ { true, if p points to an open array def }
+ function is_open_string(p : tdef) : boolean;
+ begin
+ is_open_string:=(p.typ=stringdef) and
+ (tstringdef(p).stringtype=st_shortstring) and
+ (tstringdef(p).len=0);
+ end;
+
+
+ { true, if p points to a zero based array def }
+ function is_zero_based_array(p : tdef) : boolean;
+ begin
+ result:=(p.typ=arraydef) and
+ (tarraydef(p).lowrange=0) and
+ not(is_special_array(p));
+ end;
+
+ { true if p points to a dynamic array def }
+ function is_dynamic_array(p : tdef) : boolean;
+ begin
+ result:=(p.typ=arraydef) and
+ (ado_IsDynamicArray in tarraydef(p).arrayoptions);
+ end;
+
+
+ { true, if p points to an open array def }
+ function is_open_array(p : tdef) : boolean;
+ begin
+ { check for s32inttype is needed, because for u32bit the high
+ range is also -1 ! (PFV) }
+ result:=(p.typ=arraydef) and
+ (tarraydef(p).rangedef=s32inttype) and
+ (tarraydef(p).lowrange=0) and
+ (tarraydef(p).highrange=-1) and
+ ((tarraydef(p).arrayoptions * [ado_IsVariant,ado_IsArrayOfConst,ado_IsConstructor,ado_IsDynamicArray])=[]);
+ end;
+
+ { true, if p points to an array of const def }
+ function is_array_constructor(p : tdef) : boolean;
+ begin
+ result:=(p.typ=arraydef) and
+ (ado_IsConstructor in tarraydef(p).arrayoptions);
+ end;
+
+ { true, if p points to a variant array }
+ function is_variant_array(p : tdef) : boolean;
+ begin
+ result:=(p.typ=arraydef) and
+ (ado_IsVariant in tarraydef(p).arrayoptions);
+ end;
+
+ { true, if p points to an array of const }
+ function is_array_of_const(p : tdef) : boolean;
+ begin
+ result:=(p.typ=arraydef) and
+ (ado_IsArrayOfConst in tarraydef(p).arrayoptions);
+ end;
+
+ { true, if p points to a special array, bitpacked arrays aren't special in this regard though }
+ function is_special_array(p : tdef) : boolean;
+ begin
+ result:=(p.typ=arraydef) and
+ (
+ ((tarraydef(p).arrayoptions * [ado_IsVariant,ado_IsArrayOfConst,ado_IsConstructor,ado_IsDynamicArray])<>[]) or
+ is_open_array(p)
+ );
+ end;
+
+ { true if p is an ansi string def }
+ function is_ansistring(p : tdef) : boolean;
+ begin
+ is_ansistring:=(p.typ=stringdef) and
+ (tstringdef(p).stringtype=st_ansistring);
+ end;
+
+ { true if p is an ansi string def with codepage CP_NONE }
+ function is_rawbytestring(p : tdef) : boolean;
+ begin
+ is_rawbytestring:=(p.typ=stringdef) and
+ (tstringdef(p).stringtype=st_ansistring) and
+ (tstringdef(p).encoding=globals.CP_NONE);
+ end;
+
+ { true if p is an long string def }
+ function is_longstring(p : tdef) : boolean;
+ begin
+ is_longstring:=(p.typ=stringdef) and
+ (tstringdef(p).stringtype=st_longstring);
+ end;
+
+
+ { true if p is an wide string def }
+ function is_widestring(p : tdef) : boolean;
+ begin
+ is_widestring:=(p.typ=stringdef) and
+ (tstringdef(p).stringtype=st_widestring);
+ end;
+
+
+ { true if p is an wide string def }
+ function is_wide_or_unicode_string(p : tdef) : boolean;
+ begin
+ is_wide_or_unicode_string:=(p.typ=stringdef) and
+ (tstringdef(p).stringtype in [st_widestring,st_unicodestring]);
+ end;
+
+
+ { true if p is an unicode string def }
+ function is_unicodestring(p : tdef) : boolean;
+ begin
+ is_unicodestring:=(p.typ=stringdef) and
+ (tstringdef(p).stringtype=st_unicodestring);
+ end;
+
+
+ { true if p is an short string def }
+ function is_shortstring(p : tdef) : boolean;
+ begin
+ is_shortstring:=(p.typ=stringdef) and
+ (tstringdef(p).stringtype=st_shortstring);
+ end;
+
+
+ { true if p is bit packed array def }
+ function is_packed_array(p: tdef) : boolean;
+ begin
+ is_packed_array :=
+ (p.typ = arraydef) and
+ (ado_IsBitPacked in tarraydef(p).arrayoptions);
+ end;
+
+
+ { true if p is bit packed record def }
+ function is_packed_record_or_object(p: tdef) : boolean;
+ begin
+ is_packed_record_or_object :=
+ (p.typ in [recorddef,objectdef]) and
+ (tabstractrecorddef(p).is_packed);
+ end;
+
+
+ { true if p is a char array def }
+ function is_chararray(p : tdef) : boolean;
+ begin
+ is_chararray:=(p.typ=arraydef) and
+ is_char(tarraydef(p).elementdef) and
+ not(is_special_array(p));
+ end;
+
+ { true if p is a widechar array def }
+ function is_widechararray(p : tdef) : boolean;
+ begin
+ is_widechararray:=(p.typ=arraydef) and
+ is_widechar(tarraydef(p).elementdef) and
+ not(is_special_array(p));
+ end;
+
+
+ { true if p is a open char array def }
+ function is_open_chararray(p : tdef) : boolean;
+ begin
+ is_open_chararray:= is_open_array(p) and
+ is_char(tarraydef(p).elementdef);
+ end;
+
+ { true if p is a open wide char array def }
+ function is_open_widechararray(p : tdef) : boolean;
+ begin
+ is_open_widechararray:= is_open_array(p) and
+ is_widechar(tarraydef(p).elementdef);
+ end;
+
+ { true if p is a pchar def }
+ function is_pchar(p : tdef) : boolean;
+ begin
+ is_pchar:=(p.typ=pointerdef) and
+ (is_char(tpointerdef(p).pointeddef) or
+ (is_zero_based_array(tpointerdef(p).pointeddef) and
+ is_chararray(tpointerdef(p).pointeddef)));
+ end;
+
+ { true if p is a pchar def }
+ function is_pwidechar(p : tdef) : boolean;
+ begin
+ is_pwidechar:=(p.typ=pointerdef) and
+ (is_widechar(tpointerdef(p).pointeddef) or
+ (is_zero_based_array(tpointerdef(p).pointeddef) and
+ is_widechararray(tpointerdef(p).pointeddef)));
+ end;
+
+
+ { true if p is a voidpointer def }
+ function is_voidpointer(p : tdef) : boolean;
+ begin
+ is_voidpointer:=(p.typ=pointerdef) and
+ (tpointerdef(p).pointeddef.typ=orddef) and
+ (torddef(tpointerdef(p).pointeddef).ordtype=uvoid);
+ end;
+
+
+ { true, if def is a 32 bit int type }
+ function is_32bitint(def : tdef) : boolean;
+ begin
+ result:=(def.typ=orddef) and (torddef(def).ordtype in [u32bit,s32bit])
+ end;
+
+
+ { true, if def is a 64 bit int type }
+ function is_64bitint(def : tdef) : boolean;
+ begin
+ is_64bitint:=(def.typ=orddef) and (torddef(def).ordtype in [u64bit,s64bit])
+ end;
+
+
+ { true, if def is a 64 bit type }
+ function is_64bit(def : tdef) : boolean;
+ begin
+ is_64bit:=(def.typ=orddef) and (torddef(def).ordtype in [u64bit,s64bit,scurrency,pasbool64,bool64bit])
+ end;
+
+
+ { if l isn't in the range of todef a range check error (if not explicit) is generated and
+ the value is placed within the range }
+ procedure testrange(todef : tdef;var l : tconstexprint;explicit,forcerangecheck:boolean);
+ var
+ lv,hv: TConstExprInt;
+ begin
+ { for 64 bit types we need only to check if it is less than }
+ { zero, if def is a qword node }
+ getrange(todef,lv,hv);
+ if (l<lv) or (l>hv) then
+ begin
+ if not explicit then
+ begin
+ if ((todef.typ=enumdef) and
+ { delphi allows range check errors in
+ enumeration type casts FK }
+ not(m_delphi in current_settings.modeswitches)) or
+ (cs_check_range in current_settings.localswitches) or
+ forcerangecheck then
+ Message(parser_e_range_check_error)
+ else
+ Message(parser_w_range_check_error);
+ end;
+ { Fix the value to fit in the allocated space for this type of variable }
+ case longint(todef.size) of
+ 1: l := l and $ff;
+ 2: l := l and $ffff;
+ 4: l := l and $ffffffff;
+ end;
+ {reset sign, i.e. converting -1 to qword changes the value to high(qword)}
+ l.signed:=false;
+ { do sign extension if necessary (JM) }
+ if is_signed(todef) then
+ begin
+ case longint(todef.size) of
+ 1: l.svalue := shortint(l.svalue);
+ 2: l.svalue := smallint(l.svalue);
+ 4: l.svalue := longint(l.svalue);
+ end;
+ l.signed:=true;
+ end;
+ end;
+ end;
+
+
+ { return the range from def in l and h }
+ procedure getrange(def : tdef;out l, h : TConstExprInt);
+ begin
+ case def.typ of
+ orddef :
+ begin
+ l:=torddef(def).low;
+ h:=torddef(def).high;
+ end;
+ enumdef :
+ begin
+ l:=int64(tenumdef(def).min);
+ h:=int64(tenumdef(def).max);
+ end;
+ arraydef :
+ begin
+ l:=int64(tarraydef(def).lowrange);
+ h:=int64(tarraydef(def).highrange);
+ end;
+ else
+ internalerror(200611054);
+ end;
+ end;
+
+
+ function mmx_type(p : tdef) : tmmxtype;
+ begin
+ mmx_type:=mmxno;
+ if is_mmx_able_array(p) then
+ begin
+ if tarraydef(p).elementdef.typ=floatdef then
+ case tfloatdef(tarraydef(p).elementdef).floattype of
+ s32real:
+ mmx_type:=mmxsingle;
+ end
+ else
+ case torddef(tarraydef(p).elementdef).ordtype of
+ u8bit:
+ mmx_type:=mmxu8bit;
+ s8bit:
+ mmx_type:=mmxs8bit;
+ u16bit:
+ mmx_type:=mmxu16bit;
+ s16bit:
+ mmx_type:=mmxs16bit;
+ u32bit:
+ mmx_type:=mmxu32bit;
+ s32bit:
+ mmx_type:=mmxs32bit;
+ end;
+ end;
+ end;
+
+
+ function is_vector(p : tdef) : boolean;
+ begin
+ result:=(p.typ=arraydef) and
+ not(is_special_array(p)) and
+ (tarraydef(p).elementdef.typ=floatdef) and
+ (tfloatdef(tarraydef(p).elementdef).floattype in [s32real,s64real]);
+ end;
+
+
+ { returns if the passed type (array) fits into an mm register }
+ function fits_in_mm_register(p : tdef) : boolean;
+ begin
+{$ifdef x86}
+ result:= is_vector(p) and
+ (
+ (tarraydef(p).elementdef.typ=floatdef) and
+ (
+ (tarraydef(p).lowrange=0) and
+ (tarraydef(p).highrange=3) and
+ (tfloatdef(tarraydef(p).elementdef).floattype=s32real)
+ )
+ ) or
+
+ (
+ (tarraydef(p).elementdef.typ=floatdef) and
+ (
+ (tarraydef(p).lowrange=0) and
+ (tarraydef(p).highrange=1) and
+ (tfloatdef(tarraydef(p).elementdef).floattype=s64real)
+ )
+ );
+{$else x86}
+ result:=false;
+{$endif x86}
+ end;
+
+
+ function is_mmx_able_array(p : tdef) : boolean;
+ begin
+{$ifdef SUPPORT_MMX}
+ if (cs_mmx_saturation in current_settings.localswitches) then
+ begin
+ is_mmx_able_array:=(p.typ=arraydef) and
+ not(is_special_array(p)) and
+ (
+ (
+ (tarraydef(p).elementdef.typ=orddef) and
+ (
+ (
+ (tarraydef(p).lowrange=0) and
+ (tarraydef(p).highrange=1) and
+ (torddef(tarraydef(p).elementdef).ordtype in [u32bit,s32bit])
+ )
+ or
+ (
+ (tarraydef(p).lowrange=0) and
+ (tarraydef(p).highrange=3) and
+ (torddef(tarraydef(p).elementdef).ordtype in [u16bit,s16bit])
+ )
+ )
+ )
+ or
+ (
+ (
+ (tarraydef(p).elementdef.typ=floatdef) and
+ (
+ (tarraydef(p).lowrange=0) and
+ (tarraydef(p).highrange=1) and
+ (tfloatdef(tarraydef(p).elementdef).floattype=s32real)
+ )
+ )
+ )
+ );
+ end
+ else
+ begin
+ is_mmx_able_array:=(p.typ=arraydef) and
+ (
+ (
+ (tarraydef(p).elementdef.typ=orddef) and
+ (
+ (
+ (tarraydef(p).lowrange=0) and
+ (tarraydef(p).highrange=1) and
+ (torddef(tarraydef(p).elementdef).ordtype in [u32bit,s32bit])
+ )
+ or
+ (
+ (tarraydef(p).lowrange=0) and
+ (tarraydef(p).highrange=3) and
+ (torddef(tarraydef(p).elementdef).ordtype in [u16bit,s16bit])
+ )
+ or
+ (
+ (tarraydef(p).lowrange=0) and
+ (tarraydef(p).highrange=7) and
+ (torddef(tarraydef(p).elementdef).ordtype in [u8bit,s8bit])
+ )
+ )
+ )
+ or
+ (
+ (tarraydef(p).elementdef.typ=floatdef) and
+ (
+ (tarraydef(p).lowrange=0) and
+ (tarraydef(p).highrange=1) and
+ (tfloatdef(tarraydef(p).elementdef).floattype=s32real)
+ )
+ )
+ );
+ end;
+{$else SUPPORT_MMX}
+ is_mmx_able_array:=false;
+{$endif SUPPORT_MMX}
+ end;
+
+
+ function def_cgsize(def: tdef): tcgsize;
+ begin
+ case def.typ of
+ orddef,
+ enumdef,
+ setdef:
+ begin
+ result:=int_cgsize(def.size);
+ if is_signed(def) then
+ result:=tcgsize(ord(result)+(ord(OS_S8)-ord(OS_8)));
+ end;
+ classrefdef,
+ pointerdef:
+ result := OS_ADDR;
+ procvardef:
+ begin
+ if not tprocvardef(def).is_addressonly then
+ {$if sizeof(pint) = 4}
+ result:=OS_64
+ {$else} {$if sizeof(pint) = 8}
+ result:=OS_128
+ {$else}
+ internalerror(200707141)
+ {$endif} {$endif}
+ else
+ result:=OS_ADDR;
+ end;
+ stringdef :
+ begin
+ if is_ansistring(def) or is_wide_or_unicode_string(def) then
+ result := OS_ADDR
+ else
+ result:=int_cgsize(def.size);
+ end;
+ objectdef :
+ begin
+ if is_implicit_pointer_object_type(def) then
+ result := OS_ADDR
+ else
+ result:=int_cgsize(def.size);
+ end;
+ floatdef:
+ if cs_fp_emulation in current_settings.moduleswitches then
+ result:=int_cgsize(def.size)
+ else
+ result:=tfloat2tcgsize[tfloatdef(def).floattype];
+ recorddef :
+ result:=int_cgsize(def.size);
+ arraydef :
+ begin
+ if not is_special_array(def) then
+ result := int_cgsize(def.size)
+ else
+ begin
+ if is_dynamic_array(def) then
+ result := OS_ADDR
+ else
+ result := OS_NO;
+ end;
+ end;
+ else
+ begin
+ { undefined size }
+ result:=OS_NO;
+ end;
+ end;
+ end;
+
+ { In Windows 95 era, ordinals were restricted to [u8bit,s32bit,s16bit,bool16bit]
+ As of today, both signed and unsigned types from 8 to 64 bits are supported. }
+ function is_automatable(p : tdef) : boolean;
+ begin
+ result:=false;
+ case p.typ of
+ orddef:
+ result:=torddef(p).ordtype in [u8bit,s8bit,u16bit,s16bit,u32bit,s32bit,
+ u64bit,s64bit,bool16bit,scurrency];
+ floatdef:
+ result:=tfloatdef(p).floattype in [s64currency,s64real,s32real];
+ stringdef:
+ result:=tstringdef(p).stringtype in [st_ansistring,st_widestring,st_unicodestring];
+ variantdef:
+ result:=true;
+ objectdef:
+ result:=tobjectdef(p).objecttype in [odt_interfacecom,odt_dispinterface,odt_interfacecorba];
+ end;
+ end;
+
+
+ {# returns true, if the type passed is a varset }
+ function is_smallset(p : tdef) : boolean;
+ begin
+ result:=(p.typ=setdef) and (p.size in [1,2,4])
+ end;
+
+
+ function is_bareprocdef(pd : tprocdef): boolean;
+ begin
+ result:=(pd.maxparacount=0) and
+ (is_void(pd.returndef) or
+ (pd.proctypeoption = potype_constructor));
+ end;
+
+
+ function get_common_intdef(ld, rd: torddef; keep_sign_if_equal: boolean): torddef;
+ var
+ llow, lhigh: tconstexprint;
+ begin
+ llow:=rd.low;
+ if llow<ld.low then
+ llow:=ld.low;
+ lhigh:=rd.high;
+ if lhigh<ld.high then
+ lhigh:=ld.high;
+ case range_to_basetype(llow,lhigh) of
+ s8bit:
+ result:=torddef(s8inttype);
+ u8bit:
+ result:=torddef(u8inttype);
+ s16bit:
+ result:=torddef(s16inttype);
+ u16bit:
+ result:=torddef(u16inttype);
+ s32bit:
+ result:=torddef(s32inttype);
+ u32bit:
+ result:=torddef(u32inttype);
+ s64bit:
+ result:=torddef(s64inttype);
+ u64bit:
+ result:=torddef(u64inttype);
+ else
+ begin
+ { avoid warning }
+ result:=nil;
+ internalerror(200802291);
+ end;
+ end;
+ if keep_sign_if_equal and
+ (is_signed(ld)=is_signed(rd)) and
+ (is_signed(result)<>is_signed(ld)) then
+ case result.ordtype of
+ s8bit:
+ result:=torddef(u8inttype);
+ u8bit:
+ result:=torddef(s16inttype);
+ s16bit:
+ result:=torddef(u16inttype);
+ u16bit:
+ result:=torddef(s32inttype);
+ s32bit:
+ result:=torddef(u32inttype);
+ u32bit:
+ result:=torddef(s64inttype);
+ s64bit:
+ result:=torddef(u64inttype);
+ end;
+ end;
+
+
+ function is_valid_univ_para_type(def: tdef): boolean;
+ begin
+ result:=
+ not is_open_array(def) and
+ not is_void(def) and
+ (def.typ<>formaldef);
+ end;
+
+
+ function is_nested_pd(def: tabstractprocdef): boolean;{$ifdef USEINLINE}inline;{$endif}
+ begin
+ result:=def.parast.symtablelevel>normal_function_level;
+ end;
+
+
+ function is_typeparam(def : tdef) : boolean;{$ifdef USEINLINE}inline;{$endif}
+ begin
+ result:=(def.typ=undefineddef);
+ end;
+end.
diff --git a/closures/compiler/export.pas b/closures/compiler/export.pas
new file mode 100644
index 0000000000..d363d7434a
--- /dev/null
+++ b/closures/compiler/export.pas
@@ -0,0 +1,269 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit implements an uniform export object
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit export;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ cutils,cclasses,
+ systems,
+ symtype,symdef,symsym,
+ aasmbase,aasmdata;
+
+const
+ { export options }
+ eo_resident = $1;
+ eo_index = $2;
+ eo_name = $4;
+
+type
+ texported_item = class(TLinkedListItem)
+ sym : tsym;
+ index : longint;
+ name : pshortstring;
+ options : word;
+ is_var : boolean;
+ constructor create;
+ destructor destroy;override;
+ end;
+
+ texportlib=class
+ private
+ notsupmsg : boolean;
+ finitname,
+ ffininame : string;
+ procedure NotSupported;
+ public
+ constructor Create;virtual;
+ destructor Destroy;override;
+ procedure preparelib(const s : string);virtual;
+ procedure exportprocedure(hp : texported_item);virtual;
+ procedure exportvar(hp : texported_item);virtual;
+ procedure generatelib;virtual;
+ procedure setinitname(list: TAsmList; const s: string); virtual;
+ procedure setfininame(list: TAsmList; const s: string); virtual;
+
+ property initname: string read finitname;
+ property fininame: string read ffininame;
+ end;
+
+ TExportLibClass=class of TExportLib;
+
+
+ procedure exportprocsym(sym: tsym; const s : string; index: longint; options: word);
+ procedure exportvarsym(sym: tsym; const s : string; index: longint; options: word);
+ { to export symbols not directly related to a tsym (e.g., the Objective-C
+ rtti) }
+ procedure exportname(const s : string; options: word);
+
+ procedure exportallprocdefnames(sym: tprocsym; pd: tprocdef; options: word);
+ procedure exportallprocsymnames(ps: tprocsym; options: word);
+
+
+var
+ CExportLib : array[tsystem] of TExportLibClass;
+ ExportLib : TExportLib;
+
+procedure RegisterExport(t:tsystem;c:TExportLibClass);
+procedure InitExport;
+procedure DoneExport;
+
+implementation
+
+uses
+ verbose,globals;
+
+{****************************************************************************
+ TExported_procedure
+****************************************************************************}
+
+procedure exportprocsym(sym: tsym; const s : string; index: longint; options: word);
+ var
+ hp : texported_item;
+ begin
+ hp:=texported_item.create;
+ hp.name:=stringdup(s);
+ hp.sym:=sym;
+ hp.options:=options or eo_name;
+ hp.index:=index;
+ exportlib.exportprocedure(hp);
+ end;
+
+
+procedure exportvarsym(sym: tsym; const s : string; index: longint; options: word);
+ var
+ hp : texported_item;
+ begin
+ hp:=texported_item.create;
+ hp.name:=stringdup(s);
+ hp.sym:=sym;
+ hp.is_var:=true;
+ hp.options:=options or eo_name;
+ hp.index:=index;
+ exportlib.exportvar(hp);
+ end;
+
+
+procedure exportname(const s : string; options: word);
+ begin
+ exportvarsym(nil,s,0,options);
+ end;
+
+
+ procedure exportallprocdefnames(sym: tprocsym; pd: tprocdef; options: word);
+ var
+ item: TCmdStrListItem;
+ begin
+ exportprocsym(sym,pd.mangledname,0,options);
+ { walk through all aliases }
+ item:=TCmdStrListItem(pd.aliasnames.first);
+ while assigned(item) do
+ begin
+ { avoid duplicate entries, sometimes aliasnames contains the mangledname }
+ if item.str<>pd.mangledname then
+ exportprocsym(sym,item.str,0,options);
+ item:=TCmdStrListItem(item.next);
+ end;
+ end;
+
+
+ procedure exportallprocsymnames(ps: tprocsym; options: word);
+ var
+ i: longint;
+ begin
+ for i:= 0 to ps.ProcdefList.Count-1 do
+ exportallprocdefnames(ps,tprocdef(ps.ProcdefList[i]),options);
+ end;
+
+
+{****************************************************************************
+ TExported_procedure
+****************************************************************************}
+
+constructor texported_item.Create;
+begin
+ inherited Create;
+ sym:=nil;
+ index:=-1;
+ name:=nil;
+ options:=0;
+ is_var:=false;
+end;
+
+
+destructor texported_item.destroy;
+begin
+ stringdispose(name);
+ inherited destroy;
+end;
+
+
+{****************************************************************************
+ TExportLib
+****************************************************************************}
+
+constructor texportlib.Create;
+begin
+ notsupmsg:=false;
+end;
+
+
+destructor texportlib.Destroy;
+begin
+end;
+
+
+procedure texportlib.NotSupported;
+begin
+ { show the message only once }
+ if not notsupmsg then
+ begin
+ Message(exec_e_dll_not_supported);
+ notsupmsg:=true;
+ end;
+end;
+
+
+procedure texportlib.preparelib(const s:string);
+begin
+ NotSupported;
+end;
+
+
+procedure texportlib.exportprocedure(hp : texported_item);
+begin
+ NotSupported;
+end;
+
+
+procedure texportlib.exportvar(hp : texported_item);
+begin
+ NotSupported;
+end;
+
+
+procedure texportlib.generatelib;
+begin
+ NotSupported;
+end;
+
+
+procedure texportlib.setinitname(list: TAsmList; const s: string);
+begin
+ finitname:=s;
+end;
+
+
+procedure texportlib.setfininame(list: TAsmList; const s: string);
+begin
+ ffininame:=s;
+end;
+
+{*****************************************************************************
+ Init/Done
+*****************************************************************************}
+
+procedure RegisterExport(t:tsystem;c:TExportLibClass);
+begin
+ CExportLib[t]:=c;
+end;
+
+
+procedure InitExport;
+begin
+ if assigned(CExportLib[target_info.system]) then
+ exportlib:=CExportLib[target_info.system].Create
+ else
+ exportlib:=TExportLib.Create;
+end;
+
+
+procedure DoneExport;
+begin
+ if assigned(Exportlib) then
+ Exportlib.free;
+end;
+
+
+end.
diff --git a/closures/compiler/expunix.pas b/closures/compiler/expunix.pas
new file mode 100644
index 0000000000..9bf7ae3919
--- /dev/null
+++ b/closures/compiler/expunix.pas
@@ -0,0 +1,189 @@
+{
+ Copyright (c) 2008 by the Free Pascal Compiler team
+
+ This unit implements common support for import,export,link routines
+ for unix target
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit expunix;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ cutils,cclasses,
+ systems,
+ export,
+ symtype,symdef,symsym,
+ aasmbase;
+
+type
+ texportlibunix=class(texportlib)
+ private
+ fexportedsymnames: TCmdStrList;
+ public
+ constructor Create; override;
+ destructor destroy; override;
+ procedure preparelib(const s : string);override;
+ procedure exportprocedure(hp : texported_item);override;
+ procedure exportvar(hp : texported_item);override;
+ procedure generatelib;override;
+ property exportedsymnames: TCmdStrList read fexportedsymnames;
+ end;
+
+implementation
+
+{****************************************************************************
+ TExportLibUnix
+****************************************************************************}
+
+uses
+ symconst,
+ globtype,globals,
+ aasmdata,aasmtai,aasmcpu,
+ fmodule,
+ cgbase,cgutils,cpubase,cgobj,
+ cgcpu,
+ ncgutil,
+ verbose;
+
+
+constructor texportlibunix.create;
+begin
+ inherited create;
+ fexportedsymnames:=tcmdstrlist.create_no_double;
+end;
+
+destructor texportlibunix.destroy;
+begin
+ fexportedsymnames.free;
+ inherited destroy;
+end;
+
+
+
+procedure texportlibunix.preparelib(const s:string);
+begin
+end;
+
+
+procedure texportlibunix.exportprocedure(hp : texported_item);
+var
+ hp2 : texported_item;
+begin
+ { first test the index value }
+ if (hp.options and eo_index)<>0 then
+ begin
+ Message1(parser_e_no_export_with_index_for_target,target_info.shortname);
+ exit;
+ end;
+ { now place in correct order }
+ hp2:=texported_item(current_module._exports.first);
+ while assigned(hp2) and
+ (hp.name^>hp2.name^) do
+ hp2:=texported_item(hp2.next);
+ { insert hp there !! }
+ if assigned(hp2) and (hp2.name^=hp.name^) then
+ begin
+ { this is not allowed !! }
+ Message1(parser_e_export_name_double,hp.name^);
+ exit;
+ end;
+ if hp2=texported_item(current_module._exports.first) then
+ current_module._exports.concat(hp)
+ else if assigned(hp2) then
+ begin
+ hp.next:=hp2;
+ hp.previous:=hp2.previous;
+ if assigned(hp2.previous) then
+ hp2.previous.next:=hp;
+ hp2.previous:=hp;
+ end
+ else
+ current_module._exports.concat(hp);
+end;
+
+
+procedure texportlibunix.exportvar(hp : texported_item);
+begin
+ hp.is_var:=true;
+ exportprocedure(hp);
+end;
+
+
+procedure texportlibunix.generatelib; // straight t_linux copy for now.
+var
+ hp2 : texported_item;
+ pd : tprocdef;
+{$ifdef x86}
+ sym : tasmsymbol;
+ r : treference;
+{$endif x86}
+begin
+ create_codegen;
+ new_section(current_asmdata.asmlists[al_procedures],sec_code,'',0);
+ hp2:=texported_item(current_module._exports.first);
+ while assigned(hp2) do
+ begin
+ if (not hp2.is_var) and
+ (hp2.sym.typ=procsym) then
+ begin
+ { the manglednames can already be the same when the procedure
+ is declared with cdecl }
+ pd:=tprocdef(tprocsym(hp2.sym).ProcdefList[0]);
+ if not has_alias_name(pd,hp2.name^) then
+ begin
+ { place jump in al_procedures }
+ current_asmdata.asmlists[al_procedures].concat(tai_align.create(target_info.alignment.procalign));
+ current_asmdata.asmlists[al_procedures].concat(Tai_symbol.Createname_global(hp2.name^,AT_FUNCTION,0));
+ if (cs_create_pic in current_settings.moduleswitches) and
+ { other targets need to be checked how it works }
+ (target_info.system in [system_i386_freebsd,system_x86_64_freebsd,system_x86_64_linux,system_i386_linux,system_x86_64_solaris,system_i386_solaris]) then
+ begin
+{$ifdef x86}
+ sym:=current_asmdata.RefAsmSymbol(pd.mangledname);
+ reference_reset_symbol(r,sym,0,sizeof(pint));
+ if cs_create_pic in current_settings.moduleswitches then
+ r.refaddr:=addr_pic
+ else
+ r.refaddr:=addr_full;
+ current_asmdata.asmlists[al_procedures].concat(taicpu.op_ref(A_JMP,S_NO,r));
+{$endif x86}
+ end
+ else
+ cg.a_jmp_name(current_asmdata.asmlists[al_procedures],pd.mangledname);
+ current_asmdata.asmlists[al_procedures].concat(Tai_symbol_end.Createname(hp2.name^));
+ end;
+ exportedsymnames.insert(hp2.name^);
+ end
+ else
+ begin
+ if assigned(hp2.sym) and
+ (hp2.name^<>hp2.sym.mangledname) then
+ Message2(parser_e_cant_export_var_different_name,hp2.sym.realname,hp2.sym.mangledname)
+ else
+ exportedsymnames.insert(hp2.name^);
+ end;
+ hp2:=texported_item(hp2.next);
+ end;
+ destroy_codegen;
+end;
+
+
+end.
diff --git a/closures/compiler/finput.pas b/closures/compiler/finput.pas
new file mode 100644
index 0000000000..1bfd39e18e
--- /dev/null
+++ b/closures/compiler/finput.pas
@@ -0,0 +1,726 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit implements an extended file management
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit finput;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cutils,cclasses,cstreams;
+
+ const
+ InputFileBufSize=32*1024+1;
+ linebufincrease=512;
+
+ type
+ tlongintarr = array[0..1000000] of longint;
+ plongintarr = ^tlongintarr;
+
+ tinputfile = class
+ path,name : pshortstring; { path and filename }
+ next : tinputfile; { next file for reading }
+
+ is_macro,
+ endoffile, { still bytes left to read }
+ closed : boolean; { is the file closed }
+
+ buf : pchar; { buffer }
+ bufstart, { buffer start position in the file }
+ bufsize, { amount of bytes in the buffer }
+ maxbufsize : longint; { size in memory for the buffer }
+
+ saveinputpointer : pchar; { save fields for scanner variables }
+ savelastlinepos,
+ saveline_no : longint;
+
+ linebuf : plongintarr; { line buffer to retrieve lines }
+ maxlinebuf : longint;
+
+ ref_index : longint;
+ ref_next : tinputfile;
+
+ constructor create(const fn:string);
+ destructor destroy;override;
+ procedure setpos(l:longint);
+ procedure seekbuf(fpos:longint);
+ procedure readbuf;
+ function open:boolean;
+ procedure close;
+ procedure tempclose;
+ function tempopen:boolean;
+ procedure setmacro(p:pchar;len:longint);
+ procedure setline(line,linepos:longint);
+ function getlinestr(l:longint):string;
+ function getfiletime:longint;
+ protected
+ filetime : longint;
+ function fileopen(const filename: string): boolean; virtual; abstract;
+ function fileseek(pos: longint): boolean; virtual; abstract;
+ function fileread(var databuf; maxsize: longint): longint; virtual; abstract;
+ function fileeof: boolean; virtual; abstract;
+ function fileclose: boolean; virtual; abstract;
+ procedure filegettime; virtual; abstract;
+ end;
+
+ tdosinputfile = class(tinputfile)
+ protected
+ function fileopen(const filename: string): boolean; override;
+ function fileseek(pos: longint): boolean; override;
+ function fileread(var databuf; maxsize: longint): longint; override;
+ function fileeof: boolean; override;
+ function fileclose: boolean; override;
+ procedure filegettime; override;
+ private
+ f : TCCustomFileStream; { current file handle }
+ end;
+
+ tinputfilemanager = class
+ files : tinputfile;
+ last_ref_index : longint;
+ cacheindex : longint;
+ cacheinputfile : tinputfile;
+ constructor create;
+ destructor destroy;override;
+ procedure register_file(f : tinputfile);
+ function get_file(l:longint) : tinputfile;
+ function get_file_name(l :longint):string;
+ function get_file_path(l :longint):string;
+ end;
+
+{****************************************************************************
+ TModuleBase
+ ****************************************************************************}
+
+ type
+ tmodulestate = (ms_unknown,
+ ms_registered,
+ ms_load,ms_compile,
+ ms_second_load,ms_second_compile,
+ ms_compiled
+ );
+ const
+ ModuleStateStr : array[TModuleState] of string[20] = (
+ 'Unknown',
+ 'Registered',
+ 'Load','Compile',
+ 'Second_Load','Second_Compile',
+ 'Compiled'
+ );
+
+ type
+ tmodulebase = class(TLinkedListItem)
+ { index }
+ unit_index : longint; { global counter for browser }
+ { status }
+ state : tmodulestate;
+ { sources }
+ sourcefiles : tinputfilemanager;
+ { paths and filenames }
+ paramallowoutput : boolean; { original allowoutput parameter }
+ paramfn, { original filename }
+ path, { path where the module is find/created }
+ outputpath, { path where the .s / .o / exe are created }
+ modulename, { name of the module in uppercase }
+ realmodulename, { name of the module in the orignal case }
+ objfilename, { fullname of the objectfile }
+ asmfilename, { fullname of the assemblerfile }
+ ppufilename, { fullname of the ppufile }
+ importlibfilename, { fullname of the import libraryfile }
+ staticlibfilename, { fullname of the static libraryfile }
+ sharedlibfilename, { fullname of the shared libraryfile }
+ mapfilename, { fullname of the mapfile }
+ exefilename, { fullname of the exefile }
+ dbgfilename, { fullname of the debug info file }
+ mainsource : pshortstring; { name of the main sourcefile }
+ constructor create(const s:string);
+ destructor destroy;override;
+ procedure setfilename(const fn:string;allowoutput:boolean);
+ end;
+
+
+ Function GetNamedFileTime (Const F : String) : Longint;
+
+
+implementation
+
+uses
+ SysUtils,
+ GlobType,Comphook,
+{$ifdef heaptrc}
+ fmodule,
+ ppheap,
+{$endif heaptrc}
+ cfileutl,
+ Globals,Systems
+ ;
+
+
+{****************************************************************************
+ Utils
+ ****************************************************************************}
+
+ Function GetNamedFileTime (Const F : String) : Longint;
+ begin
+ GetNamedFileTime:=do_getnamedfiletime(F);
+ end;
+
+
+{****************************************************************************
+ TINPUTFILE
+ ****************************************************************************}
+
+ constructor tinputfile.create(const fn:string);
+ begin
+ name:=stringdup(ExtractFileName(fn));
+ path:=stringdup(ExtractFilePath(fn));
+ next:=nil;
+ filetime:=-1;
+ { file info }
+ is_macro:=false;
+ endoffile:=false;
+ closed:=true;
+ buf:=nil;
+ bufstart:=0;
+ bufsize:=0;
+ maxbufsize:=InputFileBufSize;
+ { save fields }
+ saveinputpointer:=nil;
+ saveline_no:=0;
+ savelastlinepos:=0;
+ { indexing refs }
+ ref_next:=nil;
+ ref_index:=0;
+ { line buffer }
+ linebuf:=nil;
+ maxlinebuf:=0;
+ end;
+
+
+ destructor tinputfile.destroy;
+ begin
+ if not closed then
+ close;
+ stringdispose(path);
+ stringdispose(name);
+ { free memory }
+ if assigned(linebuf) then
+ freemem(linebuf,maxlinebuf shl 2);
+ end;
+
+
+ procedure tinputfile.setpos(l:longint);
+ begin
+ bufstart:=l;
+ end;
+
+
+ procedure tinputfile.seekbuf(fpos:longint);
+ begin
+ if closed then
+ exit;
+ fileseek(fpos);
+ bufstart:=fpos;
+ bufsize:=0;
+ end;
+
+
+ procedure tinputfile.readbuf;
+ begin
+ if is_macro then
+ endoffile:=true;
+ if closed then
+ exit;
+ inc(bufstart,bufsize);
+ bufsize:=fileread(buf^,maxbufsize-1);
+ buf[bufsize]:=#0;
+ endoffile:=fileeof;
+ end;
+
+
+ function tinputfile.open:boolean;
+ begin
+ open:=false;
+ if not closed then
+ Close;
+ if not fileopen(path^+name^) then
+ exit;
+ { file }
+ endoffile:=false;
+ closed:=false;
+ Getmem(buf,MaxBufsize);
+ buf[0]:=#0;
+ bufstart:=0;
+ bufsize:=0;
+ open:=true;
+ end;
+
+
+ procedure tinputfile.close;
+ begin
+ if is_macro then
+ begin
+ if assigned(buf) then
+ begin
+ Freemem(buf,maxbufsize);
+ buf:=nil;
+ end;
+ closed:=true;
+ exit;
+ end;
+ if not closed then
+ begin
+ fileclose;
+ closed:=true;
+ end;
+ if assigned(buf) then
+ begin
+ Freemem(buf,maxbufsize);
+ buf:=nil;
+ end;
+ bufstart:=0;
+ end;
+
+
+ procedure tinputfile.tempclose;
+ begin
+ if is_macro then
+ exit;
+ if not closed then
+ begin
+ fileclose;
+ if assigned(buf) then
+ begin
+ Freemem(buf,maxbufsize);
+ buf:=nil;
+ end;
+ closed:=true;
+ end;
+ end;
+
+
+ function tinputfile.tempopen:boolean;
+ begin
+ tempopen:=false;
+ if is_macro then
+ begin
+ { seek buffer postion to bufstart }
+ if bufstart>0 then
+ begin
+ move(buf[bufstart],buf[0],bufsize-bufstart+1);
+ bufstart:=0;
+ end;
+ tempopen:=true;
+ exit;
+ end;
+ if not closed then
+ exit;
+ if not fileopen(path^+name^) then
+ exit;
+ closed:=false;
+ { get new mem }
+ Getmem(buf,maxbufsize);
+ { restore state }
+ fileseek(BufStart);
+ bufsize:=0;
+ readbuf;
+ tempopen:=true;
+ end;
+
+
+ procedure tinputfile.setmacro(p:pchar;len:longint);
+ begin
+ { create new buffer }
+ getmem(buf,len+1);
+ move(p^,buf^,len);
+ buf[len]:=#0;
+ { reset }
+ bufstart:=0;
+ bufsize:=len;
+ maxbufsize:=len+1;
+ is_macro:=true;
+ endoffile:=true;
+ closed:=true;
+ end;
+
+
+ procedure tinputfile.setline(line,linepos:longint);
+ var
+ oldlinebuf : plongintarr;
+ begin
+ if line<1 then
+ exit;
+ while (line>=maxlinebuf) do
+ begin
+ oldlinebuf:=linebuf;
+ { create new linebuf and move old info }
+ getmem(linebuf,(maxlinebuf+linebufincrease) shl 2);
+ if assigned(oldlinebuf) then
+ begin
+ move(oldlinebuf^,linebuf^,maxlinebuf shl 2);
+ freemem(oldlinebuf,maxlinebuf shl 2);
+ end;
+ fillchar(linebuf^[maxlinebuf],linebufincrease shl 2,0);
+ inc(maxlinebuf,linebufincrease);
+ end;
+ linebuf^[line]:=linepos;
+ end;
+
+
+ function tinputfile.getlinestr(l:longint):string;
+ var
+ c : char;
+ i,
+ fpos : longint;
+ p : pchar;
+ begin
+ getlinestr:='';
+ if l<maxlinebuf then
+ begin
+ fpos:=linebuf^[l];
+ { fpos is set negativ if the line was already written }
+ { but we still know the correct value }
+ if fpos<0 then
+ fpos:=-fpos+1;
+ if closed then
+ open;
+ { in current buf ? }
+ if (fpos<bufstart) or (fpos>bufstart+bufsize) then
+ begin
+ seekbuf(fpos);
+ readbuf;
+ end;
+ { the begin is in the buf now simply read until #13,#10 }
+ i:=0;
+ p:=@buf[fpos-bufstart];
+ repeat
+ c:=p^;
+ if c=#0 then
+ begin
+ if endoffile then
+ break;
+ readbuf;
+ p:=buf;
+ c:=p^;
+ end;
+ if c in [#10,#13] then
+ break;
+ inc(i);
+ getlinestr[i]:=c;
+ inc(p);
+ until (i=255);
+ getlinestr[0]:=chr(i);
+ end;
+ end;
+
+
+ function tinputfile.getfiletime:longint;
+ begin
+ if filetime=-1 then
+ filegettime;
+ getfiletime:=filetime;
+ end;
+
+
+{****************************************************************************
+ TDOSINPUTFILE
+ ****************************************************************************}
+
+ function tdosinputfile.fileopen(const filename: string): boolean;
+ begin
+ { Check if file exists, this will also check if it is
+ a real file and not a directory }
+ if not fileexists(filename,false) then
+ begin
+ result:=false;
+ exit;
+ end;
+ { Open file }
+ fileopen:=false;
+ try
+ f:=CFileStreamClass.Create(filename,fmOpenRead);
+ fileopen:=true;
+ except
+ end;
+ end;
+
+
+ function tdosinputfile.fileseek(pos: longint): boolean;
+ begin
+ fileseek:=false;
+ try
+ f.position:=Pos;
+ fileseek:=true;
+ except
+ end;
+ end;
+
+
+ function tdosinputfile.fileread(var databuf; maxsize: longint): longint;
+ begin
+ fileread:=f.Read(databuf,maxsize);
+ end;
+
+
+ function tdosinputfile.fileeof: boolean;
+ begin
+ fileeof:=f.eof();
+ end;
+
+
+ function tdosinputfile.fileclose: boolean;
+ begin
+ fileclose:=false;
+ try
+ f.Free;
+ fileclose:=true;
+ except
+ end;
+ end;
+
+
+ procedure tdosinputfile.filegettime;
+ begin
+ filetime:=getnamedfiletime(path^+name^);
+ end;
+
+
+{****************************************************************************
+ Tinputfilemanager
+ ****************************************************************************}
+
+ constructor tinputfilemanager.create;
+ begin
+ files:=nil;
+ last_ref_index:=0;
+ cacheindex:=0;
+ cacheinputfile:=nil;
+ end;
+
+
+ destructor tinputfilemanager.destroy;
+ var
+ hp : tinputfile;
+ begin
+ hp:=files;
+ while assigned(hp) do
+ begin
+ files:=files.ref_next;
+ hp.free;
+ hp:=files;
+ end;
+ last_ref_index:=0;
+ end;
+
+
+ procedure tinputfilemanager.register_file(f : tinputfile);
+ begin
+ { don't register macro's }
+ if f.is_macro then
+ exit;
+ inc(last_ref_index);
+ f.ref_next:=files;
+ f.ref_index:=last_ref_index;
+ files:=f;
+ { update cache }
+ cacheindex:=last_ref_index;
+ cacheinputfile:=f;
+{$ifdef heaptrc}
+ ppheap_register_file(f.name^,current_module.unit_index*100000+f.ref_index);
+{$endif heaptrc}
+ end;
+
+
+ function tinputfilemanager.get_file(l :longint) : tinputfile;
+ var
+ ff : tinputfile;
+ begin
+ { check cache }
+ if (l=cacheindex) and assigned(cacheinputfile) then
+ begin
+ get_file:=cacheinputfile;
+ exit;
+ end;
+ ff:=files;
+ while assigned(ff) and (ff.ref_index<>l) do
+ ff:=ff.ref_next;
+ if assigned(ff) then
+ begin
+ cacheindex:=ff.ref_index;
+ cacheinputfile:=ff;
+ end;
+ get_file:=ff;
+ end;
+
+
+ function tinputfilemanager.get_file_name(l :longint):string;
+ var
+ hp : tinputfile;
+ begin
+ hp:=get_file(l);
+ if assigned(hp) then
+ get_file_name:=hp.name^
+ else
+ get_file_name:='';
+ end;
+
+
+ function tinputfilemanager.get_file_path(l :longint):string;
+ var
+ hp : tinputfile;
+ begin
+ hp:=get_file(l);
+ if assigned(hp) then
+ get_file_path:=hp.path^
+ else
+ get_file_path:='';
+ end;
+
+
+{****************************************************************************
+ TModuleBase
+ ****************************************************************************}
+
+ procedure tmodulebase.setfilename(const fn:string;allowoutput:boolean);
+ var
+ p,n,
+ prefix,
+ suffix : string;
+ begin
+ stringdispose(objfilename);
+ stringdispose(asmfilename);
+ stringdispose(ppufilename);
+ stringdispose(importlibfilename);
+ stringdispose(staticlibfilename);
+ stringdispose(sharedlibfilename);
+ stringdispose(mapfilename);
+ stringdispose(exefilename);
+ stringdispose(dbgfilename);
+ stringdispose(outputpath);
+ stringdispose(path);
+ stringdispose(paramfn);
+ { Create names }
+ paramfn := stringdup(fn);
+ paramallowoutput := allowoutput;
+ p := FixPath(ExtractFilePath(fn),false);
+ n := FixFileName(ChangeFileExt(ExtractFileName(fn),''));
+ { set path }
+ path:=stringdup(p);
+ { obj,asm,ppu names }
+ if AllowOutput then
+ begin
+ if (OutputUnitDir<>'') then
+ p:=OutputUnitDir
+ else
+ if (OutputExeDir<>'') then
+ p:=OutputExeDir;
+ end;
+ outputpath:=stringdup(p);
+ asmfilename:=stringdup(p+n+target_info.asmext);
+ objfilename:=stringdup(p+n+target_info.objext);
+ ppufilename:=stringdup(p+n+target_info.unitext);
+ importlibfilename:=stringdup(p+target_info.importlibprefix+n+target_info.importlibext);
+ staticlibfilename:=stringdup(p+target_info.staticlibprefix+n+target_info.staticlibext);
+
+ { output dir of exe can be specified separatly }
+ if AllowOutput and (OutputExeDir<>'') then
+ p:=OutputExeDir
+ else
+ p:=path^;
+
+ { lib and exe could be loaded with a file specified with -o }
+ if AllowOutput and
+ (compile_level=1) and
+ (OutputFileName<>'')then
+ begin
+ exefilename:=stringdup(p+OutputFileName);
+ sharedlibfilename:=stringdup(p+OutputFileName);
+ end
+ else
+ begin
+ exefilename:=stringdup(p+n+target_info.exeext);
+ if Assigned(OutputPrefix) then
+ prefix := OutputPrefix^
+ else
+ prefix := target_info.sharedlibprefix;
+ if Assigned(OutputSuffix) then
+ suffix := OutputSuffix^
+ else
+ suffix := '';
+ sharedlibfilename:=stringdup(p+prefix+n+suffix+target_info.sharedlibext);
+ end;
+ mapfilename:=stringdup(p+n+'.map');
+ dbgfilename:=stringdup(p+n+'.dbg');
+ end;
+
+
+ constructor tmodulebase.create(const s:string);
+ begin
+ modulename:=stringdup(Upper(s));
+ realmodulename:=stringdup(s);
+ mainsource:=nil;
+ ppufilename:=nil;
+ objfilename:=nil;
+ asmfilename:=nil;
+ importlibfilename:=nil;
+ staticlibfilename:=nil;
+ sharedlibfilename:=nil;
+ exefilename:=nil;
+ dbgfilename:=nil;
+ mapfilename:=nil;
+ outputpath:=nil;
+ paramfn:=nil;
+ path:=nil;
+ { status }
+ state:=ms_registered;
+ { unit index }
+ inc(global_unit_count);
+ unit_index:=global_unit_count;
+ { sources }
+ sourcefiles:=TInputFileManager.Create;
+ end;
+
+
+ destructor tmodulebase.destroy;
+ begin
+ if assigned(sourcefiles) then
+ sourcefiles.free;
+ sourcefiles:=nil;
+ stringdispose(objfilename);
+ stringdispose(asmfilename);
+ stringdispose(ppufilename);
+ stringdispose(importlibfilename);
+ stringdispose(staticlibfilename);
+ stringdispose(sharedlibfilename);
+ stringdispose(exefilename);
+ stringdispose(dbgfilename);
+ stringdispose(mapfilename);
+ stringdispose(outputpath);
+ stringdispose(path);
+ stringdispose(modulename);
+ stringdispose(realmodulename);
+ stringdispose(mainsource);
+ stringdispose(paramfn);
+ inherited destroy;
+ end;
+
+end.
diff --git a/closures/compiler/fmodule.pas b/closures/compiler/fmodule.pas
new file mode 100644
index 0000000000..7134218995
--- /dev/null
+++ b/closures/compiler/fmodule.pas
@@ -0,0 +1,1017 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit implements the first loading and searching of the modules
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit fmodule;
+
+{$i fpcdefs.inc}
+
+{$ifdef go32v2}
+ {$define shortasmprefix}
+{$endif}
+{$ifdef watcom}
+ {$define shortasmprefix}
+{$endif}
+{$ifdef tos}
+ {$define shortasmprefix}
+{$endif}
+{$ifdef OS2}
+ { Allthough OS/2 supports long filenames I play it safe and
+ use 8.3 filenames, because this allows the compiler to run
+ on a FAT partition. (DM) }
+ {$define shortasmprefix}
+{$endif}
+
+interface
+
+ uses
+ cutils,cclasses,cfileutl,
+ globtype,finput,ogbase,
+ symbase,symsym,
+ wpobase,
+ aasmbase,aasmtai,aasmdata;
+
+
+ const
+ UNSPECIFIED_LIBRARY_NAME = '<none>';
+
+ type
+ trecompile_reason = (rr_unknown,
+ rr_noppu,rr_sourcenewer,rr_build,rr_crcchanged
+ );
+
+ { unit options }
+ tmoduleoption = (mo_none,
+ mo_hint_deprecated,
+ mo_hint_platform,
+ mo_hint_library,
+ mo_hint_unimplemented,
+ mo_hint_experimental,
+ mo_has_deprecated_msg
+ );
+ tmoduleoptions = set of tmoduleoption;
+
+ tlinkcontaineritem=class(tlinkedlistitem)
+ public
+ data : pshortstring;
+ needlink : cardinal;
+ constructor Create(const s:string;m:cardinal);
+ destructor Destroy;override;
+ end;
+
+ tlinkcontainer=class(tlinkedlist)
+ procedure add(const s : string;m:cardinal);
+ function get(var m:cardinal) : string;
+ function getusemask(mask:cardinal) : string;
+ function find(const s:string):boolean;
+ end;
+
+ tmodule = class;
+ tused_unit = class;
+
+ tunitmaprec = record
+ u : tmodule;
+ { number of references }
+ refs : longint;
+ { index in the derefmap }
+ derefidx : longint;
+ end;
+ punitmap = ^tunitmaprec;
+
+ tderefmaprec = record
+ u : tmodule;
+ { modulename, used during ppu load }
+ modulename : pshortstring;
+ end;
+ pderefmap = ^tderefmaprec;
+
+ { tmodule }
+
+ tmodule = class(tmodulebase)
+ private
+ FImportLibraryList : TFPHashObjectList;
+ public
+ do_reload, { force reloading of the unit }
+ do_compile, { need to compile the sources }
+ sources_avail, { if all sources are reachable }
+ interface_compiled, { if the interface section has been parsed/compiled/loaded }
+ is_dbginfo_written,
+ is_unit,
+ in_interface, { processing the implementation part? }
+ { allow global settings }
+ in_global : boolean;
+ { Whether a mode switch is still allowed at this point in the parsing.}
+ mode_switch_allowed,
+ { generate pic helper which loads eip in ecx (for leave procedures) }
+ requires_ecx_pic_helper,
+ { generate pic helper which loads eip in ebx (for non leave procedures) }
+ requires_ebx_pic_helper : boolean;
+ interface_only: boolean; { interface-only macpas unit; flag does not need saving/restoring to ppu }
+ mainfilepos : tfileposinfo;
+ recompile_reason : trecompile_reason; { the reason why the unit should be recompiled }
+ crc,
+ interface_crc,
+ indirect_crc : cardinal;
+ flags : cardinal; { the PPU flags }
+ islibrary : boolean; { if it is a library (win32 dll) }
+ IsPackage : boolean;
+ moduleid : longint;
+ unitmap : punitmap; { mapping of all used units }
+ unitmapsize : longint; { number of units in the map }
+ derefmap : pderefmap; { mapping of all units needed for deref }
+ derefmapcnt : longint; { number of units in the map }
+ derefmapsize : longint; { number of units in the map }
+ derefdataintflen : longint;
+ derefdata : tdynamicarray;
+ checkforwarddefs,
+ deflist,
+ symlist : TFPObjectList;
+ ansistrdef : tobject; { an ansistring def redefined for the current module }
+ wpoinfo : tunitwpoinfobase; { whole program optimization-related information that is generated during the current run for this unit }
+ globalsymtable, { pointer to the global symtable of this unit }
+ localsymtable : TSymtable;{ pointer to the local symtable of this unit }
+ globalmacrosymtable, { pointer to the global macro symtable of this unit }
+ localmacrosymtable : TSymtable;{ pointer to the local macro symtable of this unit }
+ scanner : TObject; { scanner object used }
+ procinfo : TObject; { current procedure being compiled }
+ asmdata : TObject; { Assembler data }
+ asmprefix : pshortstring; { prefix for the smartlink asmfiles }
+ debuginfo : TObject;
+ loaded_from : tmodule;
+ _exports : tlinkedlist;
+ dllscannerinputlist : TFPHashList;
+ resourcefiles : TCmdStrList;
+ linkunitofiles,
+ linkunitstaticlibs,
+ linkunitsharedlibs,
+ linkotherofiles, { objects,libs loaded from the source }
+ linkothersharedlibs, { using $L or $LINKLIB or import lib (for linux) }
+ linkotherstaticlibs,
+ linkotherframeworks : tlinkcontainer;
+ mainname : pshortstring; { alternate name for "main" procedure }
+
+ used_units : tlinkedlist;
+ dependent_units : tlinkedlist;
+
+ localunitsearchpath, { local searchpaths }
+ localobjectsearchpath,
+ localincludesearchpath,
+ locallibrarysearchpath,
+ localframeworksearchpath : TSearchPathList;
+
+ moduleoptions: tmoduleoptions;
+ deprecatedmsg: pshortstring;
+
+ { contains a list of types that are extended by helper types; the key is
+ the full name of the type and the data is a TFPObjectList of
+ tobjectdef instances (the helper defs) }
+ extendeddefs: TFPHashObjectList;
+
+ {create creates a new module which name is stored in 's'. LoadedFrom
+ points to the module calling it. It is nil for the first compiled
+ module. This allow inheritence of all path lists. MUST pay attention
+ to that when creating link.res!!!!(mazen)}
+ constructor create(LoadedFrom:TModule;const amodulename,afilename:string;_is_unit:boolean);
+ destructor destroy;override;
+ procedure reset;virtual;
+ procedure adddependency(callermodule:tmodule);
+ procedure flagdependent(callermodule:tmodule);
+ function addusedunit(hp:tmodule;inuses:boolean;usym:tunitsym):tused_unit;
+ procedure updatemaps;
+ procedure check_hints;
+ function derefidx_unit(id:longint):longint;
+ function resolve_unit(id:longint):tmodule;
+ procedure allunitsused;
+ procedure setmodulename(const s:string);
+ procedure AddExternalImport(const libname,symname,symmangledname:string;OrdNr: longint;isvar:boolean;ImportByOrdinalOnly:boolean);
+ property ImportLibraryList : TFPHashObjectList read FImportLibraryList;
+ end;
+
+ tused_unit = class(tlinkedlistitem)
+ checksum,
+ interface_checksum,
+ indirect_checksum: cardinal;
+ in_uses,
+ in_interface : boolean;
+ u : tmodule;
+ unitsym : tunitsym;
+ constructor create(_u : tmodule;intface,inuses:boolean;usym:tunitsym);
+ end;
+
+ tdependent_unit = class(tlinkedlistitem)
+ u : tmodule;
+ constructor create(_u : tmodule);
+ end;
+
+ var
+ main_module : tmodule; { Main module of the program }
+ current_module : tmodule; { Current module which is compiled or loaded }
+ compiled_module : tmodule; { Current module which is compiled }
+ usedunits : tlinkedlist; { Used units for this program }
+ loaded_units : tlinkedlist; { All loaded units }
+ unloaded_units : tlinkedlist; { Units removed from loaded_units, to be freed }
+ SmartLinkOFiles : TCmdStrList; { List of .o files which are generated,
+ used to delete them after linking }
+
+
+ procedure set_current_module(p:tmodule);
+ function get_module(moduleindex : longint) : tmodule;
+ function get_source_file(moduleindex,fileindex : longint) : tinputfile;
+ procedure addloadedunit(hp:tmodule);
+ function find_module_from_symtable(st:tsymtable):tmodule;
+
+
+implementation
+
+ uses
+ SysUtils,globals,
+ verbose,systems,
+ scanner,ppu,dbgbase,
+ procinfo,symdef;
+
+{$ifdef MEMDEBUG}
+ var
+ memsymtable : TMemDebug;
+{$endif}
+
+{*****************************************************************************
+ Global Functions
+*****************************************************************************}
+
+ function find_module_from_symtable(st:tsymtable):tmodule;
+ var
+ hp : tmodule;
+ begin
+ result:=nil;
+ hp:=tmodule(loaded_units.first);
+ while assigned(hp) do
+ begin
+ if (hp.moduleid=st.moduleid) then
+ begin
+ result:=hp;
+ exit;
+ end;
+ hp:=tmodule(hp.next);
+ end;
+ end;
+
+ procedure set_current_module(p:tmodule);
+ begin
+ { save the state of the scanner }
+ if assigned(current_scanner) then
+ current_scanner.tempcloseinputfile;
+ { set new module }
+ current_module:=p;
+ { restore previous module settings }
+ Fillchar(current_filepos,0,sizeof(current_filepos));
+ if assigned(current_module) then
+ begin
+ current_asmdata:=tasmdata(current_module.asmdata);
+ current_debuginfo:=tdebuginfo(current_module.debuginfo);
+ { restore scanner and file positions }
+ current_scanner:=tscannerfile(current_module.scanner);
+ if assigned(current_scanner) then
+ begin
+ current_scanner.tempopeninputfile;
+ current_scanner.gettokenpos;
+ parser_current_file:=current_scanner.inputfile.name^;
+ end
+ else
+ begin
+ current_filepos.moduleindex:=current_module.unit_index;
+ parser_current_file:='';
+ end;
+ end
+ else
+ begin
+ current_asmdata:=nil;
+ current_scanner:=nil;
+ current_debuginfo:=nil;
+ end;
+ end;
+
+
+ function get_module(moduleindex : longint) : tmodule;
+ var
+ hp : tmodule;
+ begin
+ result:=nil;
+ if moduleindex=0 then
+ exit;
+ result:=current_module;
+ if not(assigned(loaded_units)) then
+ exit;
+ hp:=tmodule(loaded_units.first);
+ while assigned(hp) and (hp.unit_index<>moduleindex) do
+ hp:=tmodule(hp.next);
+ result:=hp;
+ end;
+
+
+ function get_source_file(moduleindex,fileindex : longint) : tinputfile;
+ var
+ hp : tmodule;
+ begin
+ hp:=get_module(moduleindex);
+ if assigned(hp) then
+ get_source_file:=hp.sourcefiles.get_file(fileindex)
+ else
+ get_source_file:=nil;
+ end;
+
+
+ procedure addloadedunit(hp:tmodule);
+ begin
+ hp.moduleid:=loaded_units.count;
+ loaded_units.concat(hp);
+ end;
+
+
+{****************************************************************************
+ TLinkContainerItem
+ ****************************************************************************}
+
+ constructor TLinkContainerItem.Create(const s:string;m:cardinal);
+ begin
+ inherited Create;
+ data:=stringdup(s);
+ needlink:=m;
+ end;
+
+
+ destructor TLinkContainerItem.Destroy;
+ begin
+ stringdispose(data);
+ end;
+
+
+{****************************************************************************
+ TLinkContainer
+ ****************************************************************************}
+
+ procedure TLinkContainer.add(const s : string;m:cardinal);
+ begin
+ inherited concat(TLinkContainerItem.Create(s,m));
+ end;
+
+
+ function TLinkContainer.get(var m:cardinal) : string;
+ var
+ p : tlinkcontaineritem;
+ begin
+ p:=tlinkcontaineritem(inherited getfirst);
+ if p=nil then
+ begin
+ get:='';
+ m:=0;
+ end
+ else
+ begin
+ get:=p.data^;
+ m:=p.needlink;
+ p.free;
+ end;
+ end;
+
+
+ function TLinkContainer.getusemask(mask:cardinal) : string;
+ var
+ p : tlinkcontaineritem;
+ found : boolean;
+ begin
+ found:=false;
+ repeat
+ p:=tlinkcontaineritem(inherited getfirst);
+ if p=nil then
+ begin
+ getusemask:='';
+ exit;
+ end;
+ getusemask:=p.data^;
+ found:=(p.needlink and mask)<>0;
+ p.free;
+ until found;
+ end;
+
+
+ function TLinkContainer.find(const s:string):boolean;
+ var
+ newnode : tlinkcontaineritem;
+ begin
+ find:=false;
+ newnode:=tlinkcontaineritem(First);
+ while assigned(newnode) do
+ begin
+ if newnode.data^=s then
+ begin
+ find:=true;
+ exit;
+ end;
+ newnode:=tlinkcontaineritem(newnode.next);
+ end;
+ end;
+
+
+{****************************************************************************
+ TUSED_UNIT
+ ****************************************************************************}
+
+ constructor tused_unit.create(_u : tmodule;intface,inuses:boolean;usym:tunitsym);
+ begin
+ u:=_u;
+ in_interface:=intface;
+ in_uses:=inuses;
+ unitsym:=usym;
+ if _u.state=ms_compiled then
+ begin
+ checksum:=u.crc;
+ interface_checksum:=u.interface_crc;
+ indirect_checksum:=u.indirect_crc;
+ end
+ else
+ begin
+ checksum:=0;
+ interface_checksum:=0;
+ indirect_checksum:=0;
+ end;
+ end;
+
+
+{****************************************************************************
+ TDENPENDENT_UNIT
+ ****************************************************************************}
+
+ constructor tdependent_unit.create(_u : tmodule);
+ begin
+ u:=_u;
+ end;
+
+
+{****************************************************************************
+ TMODULE
+ ****************************************************************************}
+
+ constructor tmodule.create(LoadedFrom:TModule;const amodulename,afilename:string;_is_unit:boolean);
+ var
+ n,fn:string;
+ begin
+ if amodulename='' then
+ n:=ChangeFileExt(ExtractFileName(afilename),'')
+ else
+ n:=amodulename;
+ if afilename='' then
+ fn:=amodulename
+ else
+ fn:=afilename;
+ { Programs have the name 'Program' to don't conflict with dup id's }
+ if _is_unit then
+ inherited create(amodulename)
+ else
+ inherited create('Program');
+ mainsource:=stringdup(fn);
+ { Dos has the famous 8.3 limit :( }
+{$ifdef shortasmprefix}
+ asmprefix:=stringdup(FixFileName('as'));
+{$else}
+ asmprefix:=stringdup(FixFileName(n));
+{$endif}
+ setfilename(fn,true);
+ localunitsearchpath:=TSearchPathList.Create;
+ localobjectsearchpath:=TSearchPathList.Create;
+ localincludesearchpath:=TSearchPathList.Create;
+ locallibrarysearchpath:=TSearchPathList.Create;
+ localframeworksearchpath:=TSearchPathList.Create;
+ used_units:=TLinkedList.Create;
+ dependent_units:=TLinkedList.Create;
+ resourcefiles:=TCmdStrList.Create;
+ linkunitofiles:=TLinkContainer.Create;
+ linkunitstaticlibs:=TLinkContainer.Create;
+ linkunitsharedlibs:=TLinkContainer.Create;
+ linkotherofiles:=TLinkContainer.Create;
+ linkotherstaticlibs:=TLinkContainer.Create;
+ linkothersharedlibs:=TLinkContainer.Create;
+ linkotherframeworks:=TLinkContainer.Create;
+ mainname:=nil;
+ FImportLibraryList:=TFPHashObjectList.Create(true);
+ crc:=0;
+ interface_crc:=0;
+ indirect_crc:=0;
+ flags:=0;
+ scanner:=nil;
+ unitmap:=nil;
+ unitmapsize:=0;
+ derefmap:=nil;
+ derefmapsize:=0;
+ derefmapcnt:=0;
+ derefdata:=TDynamicArray.Create(1024);
+ derefdataintflen:=0;
+ deflist:=TFPObjectList.Create(false);
+ symlist:=TFPObjectList.Create(false);
+ ansistrdef:=nil;
+ wpoinfo:=nil;
+ checkforwarddefs:=TFPObjectList.Create(false);
+ extendeddefs := TFPHashObjectList.Create(true);
+ globalsymtable:=nil;
+ localsymtable:=nil;
+ globalmacrosymtable:=nil;
+ localmacrosymtable:=nil;
+ loaded_from:=LoadedFrom;
+ do_reload:=false;
+ do_compile:=false;
+ sources_avail:=true;
+ mainfilepos.line:=0;
+ mainfilepos.column:=0;
+ mainfilepos.fileindex:=0;
+ recompile_reason:=rr_unknown;
+ in_interface:=true;
+ in_global:=true;
+ is_unit:=_is_unit;
+ islibrary:=false;
+ ispackage:=false;
+ is_dbginfo_written:=false;
+ mode_switch_allowed:= true;
+ moduleoptions:=[];
+ deprecatedmsg:=nil;
+ _exports:=TLinkedList.Create;
+ dllscannerinputlist:=TFPHashList.Create;
+ asmdata:=TAsmData.create(realmodulename^);
+ InitDebugInfo(self);
+ end;
+
+
+ destructor tmodule.Destroy;
+ var
+ i : longint;
+ begin
+ if assigned(unitmap) then
+ freemem(unitmap);
+ if assigned(derefmap) then
+ begin
+ for i:=0 to derefmapcnt-1 do
+ stringdispose(derefmap[i].modulename);
+ freemem(derefmap);
+ end;
+ if assigned(_exports) then
+ _exports.free;
+ if assigned(dllscannerinputlist) then
+ dllscannerinputlist.free;
+ if assigned(scanner) then
+ begin
+ { also update current_scanner if it was pointing
+ to this module }
+ if current_scanner=tscannerfile(scanner) then
+ current_scanner:=nil;
+ tscannerfile(scanner).free;
+ end;
+ if assigned(asmdata) then
+ begin
+ if current_asmdata=asmdata then
+ current_asmdata:=nil;
+ asmdata.free;
+ end;
+ if assigned(procinfo) then
+ begin
+ if current_procinfo=tprocinfo(procinfo) then
+ begin
+ current_procinfo:=nil;
+ current_structdef:=nil;
+ current_genericdef:=nil;
+ current_specializedef:=nil;
+ end;
+ { release procinfo tree }
+ tprocinfo(procinfo).destroy_tree;
+ end;
+ DoneDebugInfo(self);
+ used_units.free;
+ dependent_units.free;
+ resourcefiles.Free;
+ linkunitofiles.Free;
+ linkunitstaticlibs.Free;
+ linkunitsharedlibs.Free;
+ linkotherofiles.Free;
+ linkotherstaticlibs.Free;
+ linkothersharedlibs.Free;
+ linkotherframeworks.Free;
+ stringdispose(mainname);
+ FImportLibraryList.Free;
+ extendeddefs.Free;
+ stringdispose(objfilename);
+ stringdispose(asmfilename);
+ stringdispose(ppufilename);
+ stringdispose(importlibfilename);
+ stringdispose(staticlibfilename);
+ stringdispose(sharedlibfilename);
+ stringdispose(exefilename);
+ stringdispose(outputpath);
+ stringdispose(path);
+ stringdispose(realmodulename);
+ stringdispose(mainsource);
+ stringdispose(asmprefix);
+ stringdispose(deprecatedmsg);
+ localunitsearchpath.Free;
+ localobjectsearchpath.free;
+ localincludesearchpath.free;
+ locallibrarysearchpath.free;
+ localframeworksearchpath.free;
+{$ifdef MEMDEBUG}
+ memsymtable.start;
+{$endif}
+ derefdata.free;
+ deflist.free;
+ symlist.free;
+ ansistrdef:=nil;
+ wpoinfo.free;
+ checkforwarddefs.free;
+ globalsymtable.free;
+ localsymtable.free;
+ globalmacrosymtable.free;
+ localmacrosymtable.free;
+{$ifdef MEMDEBUG}
+ memsymtable.stop;
+{$endif}
+ stringdispose(modulename);
+ inherited Destroy;
+ end;
+
+
+ procedure tmodule.reset;
+ var
+ i : longint;
+ begin
+ if assigned(scanner) then
+ begin
+ { also update current_scanner if it was pointing
+ to this module }
+ if current_scanner=tscannerfile(scanner) then
+ current_scanner:=nil;
+ tscannerfile(scanner).free;
+ scanner:=nil;
+ end;
+ if assigned(procinfo) then
+ begin
+ if current_procinfo=tprocinfo(procinfo) then
+ begin
+ current_procinfo:=nil;
+ current_structdef:=nil;
+ current_genericdef:=nil;
+ current_specializedef:=nil;
+ end;
+ { release procinfo tree }
+ tprocinfo(procinfo).destroy_tree;
+ end;
+ if assigned(asmdata) then
+ begin
+ if current_asmdata=TAsmData(asmdata) then
+ current_asmdata:=nil;
+ asmdata.free;
+ asmdata:=nil;
+ end;
+ DoneDebugInfo(self);
+ globalsymtable.free;
+ globalsymtable:=nil;
+ localsymtable.free;
+ localsymtable:=nil;
+ globalmacrosymtable.free;
+ globalmacrosymtable:=nil;
+ localmacrosymtable.free;
+ localmacrosymtable:=nil;
+ deflist.free;
+ deflist:=TFPObjectList.Create(false);
+ symlist.free;
+ symlist:=TFPObjectList.Create(false);
+ wpoinfo.free;
+ wpoinfo:=nil;
+ checkforwarddefs.free;
+ checkforwarddefs:=TFPObjectList.Create(false);
+ derefdata.free;
+ derefdata:=TDynamicArray.Create(1024);
+ if assigned(unitmap) then
+ begin
+ freemem(unitmap);
+ unitmap:=nil;
+ end;
+ if assigned(derefmap) then
+ begin
+ for i:=0 to derefmapcnt-1 do
+ stringdispose(derefmap[i].modulename);
+ freemem(derefmap);
+ derefmap:=nil;
+ end;
+ unitmapsize:=0;
+ derefmapsize:=0;
+ derefmapcnt:=0;
+ derefdataintflen:=0;
+ sourcefiles.free;
+ sourcefiles:=tinputfilemanager.create;
+ asmdata:=TAsmData.create(realmodulename^);
+ InitDebugInfo(self);
+ _exports.free;
+ _exports:=tlinkedlist.create;
+ dllscannerinputlist.free;
+ dllscannerinputlist:=TFPHashList.create;
+ used_units.free;
+ used_units:=TLinkedList.Create;
+ dependent_units.free;
+ dependent_units:=TLinkedList.Create;
+ resourcefiles.Free;
+ resourcefiles:=TCmdStrList.Create;
+ linkunitofiles.Free;
+ linkunitofiles:=TLinkContainer.Create;
+ linkunitstaticlibs.Free;
+ linkunitstaticlibs:=TLinkContainer.Create;
+ linkunitsharedlibs.Free;
+ linkunitsharedlibs:=TLinkContainer.Create;
+ linkotherofiles.Free;
+ linkotherofiles:=TLinkContainer.Create;
+ linkotherstaticlibs.Free;
+ linkotherstaticlibs:=TLinkContainer.Create;
+ linkothersharedlibs.Free;
+ linkothersharedlibs:=TLinkContainer.Create;
+ linkotherframeworks.Free;
+ linkotherframeworks:=TLinkContainer.Create;
+ stringdispose(mainname);
+ FImportLibraryList.Free;
+ FImportLibraryList:=TFPHashObjectList.Create;
+ do_compile:=false;
+ do_reload:=false;
+ interface_compiled:=false;
+ in_interface:=true;
+ in_global:=true;
+ mode_switch_allowed:=true;
+ stringdispose(deprecatedmsg);
+ moduleoptions:=[];
+ is_dbginfo_written:=false;
+ crc:=0;
+ interface_crc:=0;
+ indirect_crc:=0;
+ flags:=0;
+ mainfilepos.line:=0;
+ mainfilepos.column:=0;
+ mainfilepos.fileindex:=0;
+ recompile_reason:=rr_unknown;
+ {
+ The following fields should not
+ be reset:
+ mainsource
+ state
+ loaded_from
+ sources_avail
+ }
+ end;
+
+
+ procedure tmodule.adddependency(callermodule:tmodule);
+ begin
+ { This is not needed for programs }
+ if not callermodule.is_unit then
+ exit;
+ Message2(unit_u_add_depend_to,callermodule.modulename^,modulename^);
+ dependent_units.concat(tdependent_unit.create(callermodule));
+ end;
+
+
+ procedure tmodule.flagdependent(callermodule:tmodule);
+ var
+ pm : tdependent_unit;
+ begin
+ { flag all units that depend on this unit for reloading }
+ pm:=tdependent_unit(current_module.dependent_units.first);
+ while assigned(pm) do
+ begin
+ { We do not have to reload the unit that wants to load
+ this unit, unless this unit is already compiled during
+ the loading }
+ if (pm.u=callermodule) and
+ (pm.u.state<>ms_compiled) then
+ Message1(unit_u_no_reload_is_caller,pm.u.modulename^)
+ else
+ if pm.u.state=ms_second_compile then
+ Message1(unit_u_no_reload_in_second_compile,pm.u.modulename^)
+ else
+ begin
+ pm.u.do_reload:=true;
+ Message1(unit_u_flag_for_reload,pm.u.modulename^);
+ end;
+ pm:=tdependent_unit(pm.next);
+ end;
+ end;
+
+
+ function tmodule.addusedunit(hp:tmodule;inuses:boolean;usym:tunitsym):tused_unit;
+ var
+ pu : tused_unit;
+ begin
+ pu:=tused_unit.create(hp,in_interface,inuses,usym);
+ used_units.concat(pu);
+ addusedunit:=pu;
+ end;
+
+
+ procedure tmodule.updatemaps;
+ var
+ oldmapsize : longint;
+ hp : tmodule;
+ i : longint;
+ begin
+ { Extend unitmap }
+ oldmapsize:=unitmapsize;
+ unitmapsize:=loaded_units.count;
+ reallocmem(unitmap,unitmapsize*sizeof(tunitmaprec));
+ fillchar(unitmap[oldmapsize],(unitmapsize-oldmapsize)*sizeof(tunitmaprec),0);
+
+ { Extend Derefmap }
+ oldmapsize:=derefmapsize;
+ derefmapsize:=loaded_units.count;
+ reallocmem(derefmap,derefmapsize*sizeof(tderefmaprec));
+ fillchar(derefmap[oldmapsize],(derefmapsize-oldmapsize)*sizeof(tderefmaprec),0);
+
+ { Add all units to unitmap }
+ hp:=tmodule(loaded_units.first);
+ i:=0;
+ while assigned(hp) do
+ begin
+ if hp.moduleid>=unitmapsize then
+ internalerror(200501151);
+ { Verify old entries }
+ if (i<oldmapsize) then
+ begin
+ if (hp.moduleid<>i) or
+ (unitmap[hp.moduleid].u<>hp) then
+ internalerror(200501156);
+ end
+ else
+ begin
+ unitmap[hp.moduleid].u:=hp;
+ unitmap[hp.moduleid].derefidx:=-1;
+ end;
+ inc(i);
+ hp:=tmodule(hp.next);
+ end;
+ end;
+
+ procedure tmodule.check_hints;
+ begin
+ if mo_hint_deprecated in moduleoptions then
+ if (mo_has_deprecated_msg in moduleoptions) and (deprecatedmsg <> nil) then
+ Message2(sym_w_deprecated_unit_with_msg,realmodulename^,deprecatedmsg^)
+ else
+ Message1(sym_w_deprecated_unit,realmodulename^);
+ if mo_hint_experimental in moduleoptions then
+ Message1(sym_w_experimental_unit,realmodulename^);
+ if mo_hint_platform in moduleoptions then
+ Message1(sym_w_non_portable_unit,realmodulename^);
+ if mo_hint_library in moduleoptions then
+ Message1(sym_w_library_unit,realmodulename^);
+ if mo_hint_unimplemented in moduleoptions then
+ Message1(sym_w_non_implemented_unit,realmodulename^);
+ end;
+
+
+ function tmodule.derefidx_unit(id:longint):longint;
+ begin
+ if id>=unitmapsize then
+ internalerror(2005011511);
+ if unitmap[id].derefidx=-1 then
+ begin
+ unitmap[id].derefidx:=derefmapcnt;
+ inc(derefmapcnt);
+ derefmap[unitmap[id].derefidx].u:=unitmap[id].u;
+ end;
+ if unitmap[id].derefidx>=derefmapsize then
+ internalerror(2005011514);
+ result:=unitmap[id].derefidx;
+ end;
+
+
+ function tmodule.resolve_unit(id:longint):tmodule;
+ var
+ hp : tmodule;
+ begin
+ if id>=derefmapsize then
+ internalerror(200306231);
+ result:=derefmap[id].u;
+ if not assigned(result) then
+ begin
+ if not assigned(derefmap[id].modulename) or
+ (derefmap[id].modulename^='') then
+ internalerror(200501159);
+ hp:=tmodule(loaded_units.first);
+ while assigned(hp) do
+ begin
+ { only check for units. The main program is also
+ as a unit in the loaded_units list. We simply need
+ to ignore this entry (PFV) }
+ if hp.is_unit and
+ (hp.modulename^=derefmap[id].modulename^) then
+ break;
+ hp:=tmodule(hp.next);
+ end;
+ if not assigned(hp) then
+ internalerror(2005011510);
+ derefmap[id].u:=hp;
+ result:=hp;
+ end;
+ end;
+
+
+ procedure tmodule.allunitsused;
+ var
+ pu : tused_unit;
+ begin
+ pu:=tused_unit(used_units.first);
+ while assigned(pu) do
+ begin
+ if assigned(pu.u.globalsymtable) then
+ begin
+ if unitmap[pu.u.moduleid].u<>pu.u then
+ internalerror(200501157);
+ { Give a note when the unit is not referenced, skip
+ this is for units with an initialization/finalization }
+ if (unitmap[pu.u.moduleid].refs=0) and
+ ((pu.u.flags and (uf_init or uf_finalize))=0) then
+ CGMessagePos2(pu.unitsym.fileinfo,sym_n_unit_not_used,pu.u.realmodulename^,realmodulename^);
+ end;
+ pu:=tused_unit(pu.next);
+ end;
+ end;
+
+
+ procedure tmodule.setmodulename(const s:string);
+ begin
+ stringdispose(modulename);
+ stringdispose(realmodulename);
+ modulename:=stringdup(upper(s));
+ realmodulename:=stringdup(s);
+ { also update asmlibrary names }
+ current_asmdata.name:=modulename^;
+ current_asmdata.realname:=realmodulename^;
+ end;
+
+
+ procedure TModule.AddExternalImport(const libname,symname,symmangledname:string;
+ OrdNr: longint;isvar:boolean;ImportByOrdinalOnly:boolean);
+ var
+ ImportLibrary,OtherIL : TImportLibrary;
+ ImportSymbol : TImportSymbol;
+ i : longint;
+ begin
+ ImportLibrary:=TImportLibrary(ImportLibraryList.Find(libname));
+ if not assigned(ImportLibrary) then
+ ImportLibrary:=TImportLibrary.Create(ImportLibraryList,libname);
+ ImportSymbol:=TImportSymbol(ImportLibrary.ImportSymbolList.Find(symname));
+ if not assigned(ImportSymbol) then
+ begin
+ { Check that the same name does not exist in another library }
+ { If it does and the same mangled name is used, issue a warning }
+ if ImportLibraryList.Count>1 then
+ for i:=0 To ImportLibraryList.Count-1 do
+ begin
+ OtherIL:=TImportLibrary(ImportLibraryList.Items[i]);
+ ImportSymbol:=TImportSymbol(OtherIL.ImportSymbolList.Find(symname));
+ if assigned(ImportSymbol) then
+ begin
+ if ImportSymbol.MangledName=symmangledname then
+ begin
+ CGMessage3(sym_w_library_overload,symname,libname,OtherIL.Name);
+ break;
+ end;
+ end;
+ end;
+ if not ImportByOrdinalOnly then
+ { negative ordinal number indicates import by name with ordinal number as hint }
+ OrdNr:=-OrdNr;
+ ImportSymbol:=TImportSymbol.Create(ImportLibrary.ImportSymbolList,
+ symname,symmangledname,OrdNr,isvar);
+ end;
+ end;
+
+
+initialization
+{$ifdef MEMDEBUG}
+ memsymtable:=TMemDebug.create('Symtables');
+ memsymtable.stop;
+{$endif MEMDEBUG}
+
+finalization
+{$ifdef MEMDEBUG}
+ memsymtable.free;
+{$endif MEMDEBUG}
+
+end.
diff --git a/closures/compiler/fpccrc.pas b/closures/compiler/fpccrc.pas
new file mode 100644
index 0000000000..a617b65dba
--- /dev/null
+++ b/closures/compiler/fpccrc.pas
@@ -0,0 +1,76 @@
+{
+ Copyright (c) 2000-2002 by Free Pascal Development Team
+
+ Routines to compute CRC values
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+Unit fpccrc;
+
+{$i fpcdefs.inc}
+
+Interface
+
+Function UpdateCrc32(InitCrc:cardinal;const InBuf;InLen:integer):cardinal;
+
+
+Implementation
+
+{*****************************************************************************
+ Crc 32
+*****************************************************************************}
+
+var
+ Crc32Tbl : array[0..255] of cardinal;
+
+procedure MakeCRC32Tbl;
+var
+ crc : cardinal;
+ i,n : integer;
+begin
+ for i:=0 to 255 do
+ begin
+ crc:=i;
+ for n:=1 to 8 do
+ if (crc and 1)<>0 then
+ crc:=(crc shr 1) xor cardinal($edb88320)
+ else
+ crc:=crc shr 1;
+ Crc32Tbl[i]:=crc;
+ end;
+end;
+
+
+Function UpdateCrc32(InitCrc:cardinal;const InBuf;InLen:Integer):cardinal;
+var
+ i : integer;
+ p : pchar;
+begin
+ if Crc32Tbl[1]=0 then
+ MakeCrc32Tbl;
+ p:=@InBuf;
+ result:=not InitCrc;
+ for i:=1 to InLen do
+ begin
+ result:=Crc32Tbl[byte(result) xor byte(p^)] xor (result shr 8);
+ inc(p);
+ end;
+ result:=not result;
+end;
+
+
+end.
diff --git a/closures/compiler/fpcdefs.inc b/closures/compiler/fpcdefs.inc
new file mode 100644
index 0000000000..fc41470b8c
--- /dev/null
+++ b/closures/compiler/fpcdefs.inc
@@ -0,0 +1,179 @@
+{$mode objfpc}
+{$asmmode default}
+{$H-}
+{$goto on}
+{$inline on}
+{$interfaces corba}
+
+{ This reduces the memory requirements a lot }
+{$PACKENUM 1}
+{$ifdef FPC_HAS_VARSETS}
+{$ifndef FPC_BIG_ENDIAN}
+{ $define USE_PACKSET1}
+{$endif}
+{$endif FPC_HAS_VARSETS}
+
+{$ifdef USE_PACKSET1}
+{$PACKSET 1}
+{$endif USE_PACKSET1}
+
+{ We don't use exceptions, so turn off the implicit
+ exceptions in the constructors }
+{$IMPLICITEXCEPTIONS OFF}
+
+{ Inline small functions, but not when EXTDEBUG is used }
+{$ifndef EXTDEBUG}
+ {$define USEINLINE}
+{$endif EXTDEBUG}
+
+{$define USEEXCEPT}
+
+{ If anyone wants to use interrupt for
+ a specific target, add a
+ $define FPC_HAS_SYSTEMS_INTERRUPT_TABLE
+ to fpcdefs.inc to reactivate
+ the corresponding code }
+{$undef FPC_HAS_SYSTEMS_INTERRUPT_TABLE}
+
+{ This fake CPU is used to allow incorporation of globtype unit
+ into utils/ppudump without any CPU specific code PM }
+{$ifdef generic_cpu}
+ {$define cpu32bit}
+ {$define cpu32bitaddr}
+ {$define cpu32bitalu}
+ {$define cpuflags}
+ {$define cpuextended}
+{$endif generic_cpu}
+
+{$ifdef cpuarm}
+ {$packrecords c}
+{$endif cpuarm}
+
+{$ifdef i386}
+ {$define cpu32bit}
+ {$define cpu32bitaddr}
+ {$define cpu32bitalu}
+ {$define x86}
+ {$define cpuflags}
+ {$define cpuextended}
+ {$define SUPPORT_MMX}
+ {$define cpumm}
+ {$define fewintregisters}
+ {$define cpurox}
+{$endif i386}
+
+{$ifdef x86_64}
+ {$define x86}
+ {$define cpuflags}
+ {$define cpu64bitalu}
+ {$define cpu64bitaddr}
+ {$define cpuextended}
+ {$define cpufloat128}
+ {$define cputargethasfixedstack}
+ {$define cpumm}
+ {$define cpurox}
+{$endif x86_64}
+
+{$ifdef ia64}
+ {$define cpuflags}
+ {$define cpu64bitalu}
+ {$define cpu64bitaddr}
+ {$define cpuextended}
+ {$define cpufloat128}
+{$endif ia64}
+
+{$ifdef alpha}
+ {$define cpu64bitalu}
+ {$define cpu64bitaddr}
+{$endif alpha}
+
+{$ifdef sparc}
+ {$define cpu32bit}
+ {$define cpu32bitaddr}
+ {$define cpu32bitalu}
+ {$define cpuflags}
+ {$define cputargethasfixedstack}
+{$endif sparc}
+
+{$ifdef powerpc}
+ {$define cpu32bit}
+ {$define cpu32bitaddr}
+ {$define cpu32bitalu}
+ {$define cpuflags}
+ {$define cputargethasfixedstack}
+ {$define cpumm}
+ {$define cpurox}
+{$endif powerpc}
+
+{$ifdef powerpc64}
+ {$define cpu64bitalu}
+ {$define cpu64bitaddr}
+ {$define cpuflags}
+ {$define cputargethasfixedstack}
+ {$define cpumm}
+ {$define cpurox}
+{$endif powerpc64}
+
+{$ifdef arm}
+ {$define cpu32bit}
+ {$define cpu32bitaddr}
+ {$define cpu32bitalu}
+ {$define cpuflags}
+ {$define cpufpemu}
+ {$define cpuneedsdiv32helper}
+ {$define cpurox}
+ {$define cputargethasfixedstack}
+ { default to armel }
+ {$if not(defined(CPUARM)) and not(defined(CPUARMEB)) and not(defined(FPC_OARM)) and not(defined(FPC_ARMEB))}
+ {$define FPC_ARMEL}
+ {$endif}
+ { inherit FPC_ARMEL? }
+ {$if defined(CPUARMEL) and not(defined(FPC_OARM)) and not(defined(FPC_ARMEB))}
+ {$define FPC_ARMEL}
+ {$endif}
+ { inherit FPC_ARMEB? }
+ {$if defined(CPUARMEB) and not(defined(FPC_OARM)) and not(defined(FPC_ARMEL))}
+ {$define FPC_ARMEB}
+ {$endif}
+{$endif arm}
+
+{$ifdef m68k}
+ {$define cpu32bit}
+ {$define cpu32bitaddr}
+ {$define cpu32bitalu}
+ {$define cpuflags}
+ {$define cpufpemu}
+{$endif m68k}
+
+{$ifdef avr}
+ {$define cpu8bit}
+ {$define cpu16bitaddr}
+ {$define cpu8bitalu}
+ {$define cpuflags}
+ {$define cpunofpu}
+ {$define cpunodefaultint}
+ {$define cpuneedsdiv32helper}
+ {$define cpuneedsmulhelper}
+{$endif avr}
+
+{$ifdef mipsel}
+ {$define mips}
+{$endif mipsel}
+
+{$ifdef mips}
+ {$define cpu32bit}
+ {$define cpu32bitalu}
+ {$define cpu32bitaddr}
+ { $define cpuflags}
+ {$define cputargethasfixedstack}
+ {$define cpurequiresproperalignment}
+ {$define cpumm}
+{$endif mips}
+
+{$IFDEF MACOS}
+{$DEFINE USE_FAKE_SYSUTILS}
+{$ENDIF MACOS}
+
+{$if not defined(FPC_HAS_TYPE_EXTENDED) and defined(i386)}
+{$error Cross-compiling from systems without support for an 80 bit extended floating point type to i386 is not yet supported at this time }
+{$endif}
diff --git a/closures/compiler/fppu.pas b/closures/compiler/fppu.pas
new file mode 100644
index 0000000000..d75bca19c9
--- /dev/null
+++ b/closures/compiler/fppu.pas
@@ -0,0 +1,1732 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit implements the first loading and searching of the modules
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit fppu;
+
+{$i fpcdefs.inc}
+
+{ close ppufiles on system that are
+ short on file handles like DOS system PM }
+{$ifdef GO32V2}
+ {$define SHORT_ON_FILE_HANDLES}
+{$endif GO32V2}
+{$ifdef WATCOM}
+ {$define SHORT_ON_FILE_HANDLES}
+{$endif WATCOM}
+
+interface
+
+ uses
+ cmsgs,verbose,
+ cutils,cclasses,
+ globtype,globals,finput,fmodule,
+ symbase,ppu,symtype;
+
+ type
+
+ { tppumodule }
+
+ tppumodule = class(tmodule)
+ ppufile : tcompilerppufile; { the PPU file }
+ sourcefn : pshortstring; { Source specified with "uses .. in '..'" }
+ comments : TCmdStrList;
+{$ifdef Test_Double_checksum}
+ crc_array : pointer;
+ crc_size : longint;
+ crc_array2 : pointer;
+ crc_size2 : longint;
+{$endif def Test_Double_checksum}
+ constructor create(LoadedFrom:TModule;const amodulename,afilename:string;_is_unit:boolean);
+ destructor destroy;override;
+ procedure reset;override;
+ function openppu:boolean;
+ procedure getppucrc;
+ procedure writeppu;
+ procedure loadppu;
+ function needrecompile:boolean;
+ procedure setdefgeneration;
+ procedure reload_flagged_units;
+ private
+ { Each time a unit's defs are (re)created, its defsgeneration is
+ set to the value of a global counter, and the global counter is
+ increased. We only reresolve its dependent units' defs in case
+ they have been resolved only for an older generation, in order to
+ avoid endless resolving loops in case of cyclic dependencies. }
+ defsgeneration : longint;
+
+ function search_unit_files(onlysource:boolean):boolean;
+ function search_unit(onlysource,shortname:boolean):boolean;
+ procedure load_interface;
+ procedure load_implementation;
+ procedure load_usedunits;
+ procedure printcomments;
+ procedure queuecomment(const s:TMsgStr;v,w:longint);
+ procedure writesourcefiles;
+ procedure writeusedunit(intf:boolean);
+ procedure writelinkcontainer(var p:tlinkcontainer;id:byte;strippath:boolean);
+ procedure writederefmap;
+ procedure writederefdata;
+ procedure writeImportSymbols;
+ procedure writeResources;
+ procedure readsourcefiles;
+ procedure readloadunit;
+ procedure readlinkcontainer(var p:tlinkcontainer);
+ procedure readderefmap;
+ procedure readderefdata;
+ procedure readImportSymbols;
+ procedure readResources;
+ procedure readwpofile;
+{$IFDEF MACRO_DIFF_HINT}
+ procedure writeusedmacro(p:TNamedIndexItem;arg:pointer);
+ procedure writeusedmacros;
+ procedure readusedmacros;
+{$ENDIF}
+ end;
+
+ function registerunit(callermodule:tmodule;const s : TIDString;const fn:string) : tppumodule;
+
+
+implementation
+
+uses
+ SysUtils,
+ cfileutl,
+ systems,version,
+ symtable, symsym,
+ wpoinfo,
+ scanner,
+ aasmbase,ogbase,
+ parser,
+ comphook;
+
+
+var
+ currentdefgeneration: longint;
+
+{****************************************************************************
+ TPPUMODULE
+ ****************************************************************************}
+
+ constructor tppumodule.create(LoadedFrom:TModule;const amodulename,afilename:string;_is_unit:boolean);
+ begin
+ inherited create(LoadedFrom,amodulename,afilename,_is_unit);
+ ppufile:=nil;
+ sourcefn:=stringdup(afilename);
+ end;
+
+
+ destructor tppumodule.Destroy;
+ begin
+ if assigned(ppufile) then
+ ppufile.free;
+ ppufile:=nil;
+ comments.free;
+ comments:=nil;
+ stringdispose(sourcefn);
+ inherited Destroy;
+ end;
+
+
+ procedure tppumodule.reset;
+ begin
+ inc(currentdefgeneration);
+ if assigned(ppufile) then
+ begin
+ ppufile.free;
+ ppufile:=nil;
+ end;
+ inherited reset;
+ end;
+
+ procedure tppumodule.queuecomment(const s:TMsgStr;v,w:longint);
+ begin
+ if comments = nil then
+ comments := TCmdStrList.create;
+ comments.insert(s);
+ end;
+
+ procedure tppumodule.printcomments;
+ var
+ comment: string;
+ begin
+ if comments = nil then
+ exit;
+ { comments are inserted in reverse order }
+ repeat
+ comment := comments.getlast;
+ if length(comment) = 0 then
+ exit;
+ do_comment(v_normal, comment);
+ until false;
+ end;
+
+ function tppumodule.openppu:boolean;
+ var
+ ppufiletime : longint;
+ begin
+ openppu:=false;
+ Message1(unit_t_ppu_loading,ppufilename^,@queuecomment);
+ { Get ppufile time (also check if the file exists) }
+ ppufiletime:=getnamedfiletime(ppufilename^);
+ if ppufiletime=-1 then
+ exit;
+ { Open the ppufile }
+ Message1(unit_u_ppu_name,ppufilename^);
+ ppufile:=tcompilerppufile.create(ppufilename^);
+ if not ppufile.openfile then
+ begin
+ ppufile.free;
+ ppufile:=nil;
+ Message(unit_u_ppu_file_too_short);
+ exit;
+ end;
+ { check for a valid PPU file }
+ if not ppufile.CheckPPUId then
+ begin
+ ppufile.free;
+ ppufile:=nil;
+ Message(unit_u_ppu_invalid_header);
+ exit;
+ end;
+ { check for allowed PPU versions }
+ if not (ppufile.GetPPUVersion = CurrentPPUVersion) then
+ begin
+ Message1(unit_u_ppu_invalid_version,tostr(ppufile.GetPPUVersion),@queuecomment);
+ ppufile.free;
+ ppufile:=nil;
+ exit;
+ end;
+ { check the target processor }
+ if tsystemcpu(ppufile.header.cpu)<>target_cpu then
+ begin
+ ppufile.free;
+ ppufile:=nil;
+ Message(unit_u_ppu_invalid_processor,@queuecomment);
+ exit;
+ end;
+ { check target }
+ if tsystem(ppufile.header.target)<>target_info.system then
+ begin
+ ppufile.free;
+ ppufile:=nil;
+ Message(unit_u_ppu_invalid_target,@queuecomment);
+ exit;
+ end;
+{$ifdef cpufpemu}
+ { check if floating point emulation is on?
+ fpu emulation isn't unit levelwise because it affects calling convention }
+ if ((ppufile.header.flags and uf_fpu_emulation)<>0) xor
+ (cs_fp_emulation in current_settings.moduleswitches) then
+ begin
+ ppufile.free;
+ ppufile:=nil;
+ Message(unit_u_ppu_invalid_fpumode,@queuecomment);
+ exit;
+ end;
+{$endif cpufpemu}
+
+ { Load values to be access easier }
+ flags:=ppufile.header.flags;
+ crc:=ppufile.header.checksum;
+ interface_crc:=ppufile.header.interface_checksum;
+ indirect_crc:=ppufile.header.indirect_checksum;
+ { Show Debug info }
+ Message1(unit_u_ppu_time,filetimestring(ppufiletime));
+ Message1(unit_u_ppu_flags,tostr(flags));
+ Message1(unit_u_ppu_crc,hexstr(ppufile.header.checksum,8));
+ Message1(unit_u_ppu_crc,hexstr(ppufile.header.interface_checksum,8)+' (intfc)');
+ Message1(unit_u_ppu_crc,hexstr(ppufile.header.indirect_checksum,8)+' (indc)');
+ Comment(V_used,'Number of definitions: '+tostr(ppufile.header.deflistsize));
+ Comment(V_used,'Number of symbols: '+tostr(ppufile.header.symlistsize));
+ do_compile:=false;
+ openppu:=true;
+ end;
+
+
+ function tppumodule.search_unit_files(onlysource:boolean):boolean;
+ var
+ found : boolean;
+ begin
+ found:=false;
+ if search_unit(onlysource,false) then
+ found:=true;
+ if (not found) and
+ (length(modulename^)>8) and
+ search_unit(onlysource,true) then
+ found:=true;
+ search_unit_files:=found;
+ end;
+
+
+ function tppumodule.search_unit(onlysource,shortname:boolean):boolean;
+ var
+ singlepathstring,
+ filename : TCmdStr;
+
+ Function UnitExists(const ext:string;var foundfile:TCmdStr):boolean;
+ begin
+ if CheckVerbosity(V_Tried) then
+ Message1(unit_t_unitsearch,Singlepathstring+filename+ext);
+ UnitExists:=FindFile(FileName+ext,Singlepathstring,true,foundfile);
+ end;
+
+ Function PPUSearchPath(const s:TCmdStr):boolean;
+ var
+ found : boolean;
+ hs : TCmdStr;
+ begin
+ Found:=false;
+ singlepathstring:=FixPath(s,false);
+ { Check for PPU file }
+ Found:=UnitExists(target_info.unitext,hs);
+ if Found then
+ Begin
+ SetFileName(hs,false);
+ Found:=OpenPPU;
+ End;
+ PPUSearchPath:=Found;
+ end;
+
+ Function SourceSearchPath(const s:TCmdStr):boolean;
+ var
+ found : boolean;
+ hs : TCmdStr;
+ begin
+ Found:=false;
+ singlepathstring:=FixPath(s,false);
+ { Check for Sources }
+ ppufile:=nil;
+ do_compile:=true;
+ recompile_reason:=rr_noppu;
+ {Check for .pp file}
+ Found:=UnitExists(sourceext,hs);
+ if not Found then
+ begin
+ { Check for .pas }
+ Found:=UnitExists(pasext,hs);
+ end;
+ if not Found and
+ ((m_mac in current_settings.modeswitches) or
+ (tf_p_ext_support in target_info.flags)) then
+ begin
+ { Check for .p, if mode is macpas}
+ Found:=UnitExists(pext,hs);
+ end;
+ stringdispose(mainsource);
+ if Found then
+ begin
+ sources_avail:=true;
+ { Load Filenames when found }
+ mainsource:=StringDup(hs);
+ SetFileName(hs,false);
+ end
+ else
+ sources_avail:=false;
+ SourceSearchPath:=Found;
+ end;
+
+ Function SearchPath(const s:TCmdStr):boolean;
+ var
+ found : boolean;
+ begin
+ { First check for a ppu, then for the source }
+ found:=false;
+ if not onlysource then
+ found:=PPUSearchPath(s);
+ if not found then
+ found:=SourceSearchPath(s);
+ SearchPath:=found;
+ end;
+
+ Function SearchPathList(list:TSearchPathList):boolean;
+ var
+ hp : TCmdStrListItem;
+ found : boolean;
+ begin
+ found:=false;
+ hp:=TCmdStrListItem(list.First);
+ while assigned(hp) do
+ begin
+ found:=SearchPath(hp.Str);
+ if found then
+ break;
+ hp:=TCmdStrListItem(hp.next);
+ end;
+ SearchPathList:=found;
+ end;
+
+ var
+ fnd : boolean;
+ hs : TCmdStr;
+ begin
+ if shortname then
+ filename:=FixFileName(Copy(realmodulename^,1,8))
+ else
+ filename:=FixFileName(realmodulename^);
+ { try to find unit
+ 1. look for ppu in cwd
+ 2. look for ppu in outputpath if set, this is tp7 compatible (PFV)
+ 3. look for ppu in maindir
+ 4. look for the specified source file (from the uses line)
+ 5. look for source in cwd
+ 6. look for source in maindir
+ 7. local unit pathlist
+ 8. global unit pathlist }
+ fnd:=false;
+ if not onlysource then
+ begin
+ fnd:=PPUSearchPath('.');
+ if (not fnd) and (outputpath^<>'') then
+ fnd:=PPUSearchPath(outputpath^);
+ if (not fnd) and Assigned(main_module) and (main_module.Path^<>'') then
+ fnd:=PPUSearchPath(main_module.Path^);
+ end;
+ if (not fnd) and (sourcefn^<>'') then
+ begin
+ { the full filename is specified so we can't use here the
+ searchpath (PFV) }
+ if CheckVerbosity(V_Tried) then
+ Message1(unit_t_unitsearch,ChangeFileExt(sourcefn^,sourceext));
+ fnd:=FindFile(ChangeFileExt(sourcefn^,sourceext),'',true,hs);
+ if not fnd then
+ begin
+ if CheckVerbosity(V_Tried) then
+ Message1(unit_t_unitsearch,ChangeFileExt(sourcefn^,pasext));
+ fnd:=FindFile(ChangeFileExt(sourcefn^,pasext),'',true,hs);
+ end;
+ if not fnd and
+ ((m_mac in current_settings.modeswitches) or
+ (tf_p_ext_support in target_info.flags)) then
+ begin
+ if CheckVerbosity(V_Tried) then
+ Message1(unit_t_unitsearch,ChangeFileExt(sourcefn^,pext));
+ fnd:=FindFile(ChangeFileExt(sourcefn^,pext),'',true,hs);
+ end;
+ if fnd then
+ begin
+ sources_avail:=true;
+ do_compile:=true;
+ recompile_reason:=rr_noppu;
+ stringdispose(mainsource);
+ mainsource:=StringDup(hs);
+ SetFileName(hs,false);
+ end;
+ end;
+ if not fnd then
+ fnd:=SourceSearchPath('.');
+ if (not fnd) and Assigned(main_module) and (main_module.Path^<>'') then
+ fnd:=SourceSearchPath(main_module.Path^);
+ if (not fnd) and Assigned(loaded_from) then
+ fnd:=SearchPathList(loaded_from.LocalUnitSearchPath);
+ if not fnd then
+ fnd:=SearchPathList(UnitSearchPath);
+ search_unit:=fnd;
+ end;
+
+
+{**********************************
+ PPU Reading/Writing Helpers
+***********************************}
+
+{$IFDEF MACRO_DIFF_HINT}
+ var
+ is_initial: Boolean;
+
+ procedure tppumodule.writeusedmacro(p:TNamedIndexItem;arg:pointer);
+ begin
+ if tmacro(p).is_used or is_initial then
+ begin
+ ppufile.putstring(p.name);
+ ppufile.putbyte(byte(is_initial));
+ ppufile.putbyte(byte(tmacro(p).is_used));
+ end;
+ end;
+
+ procedure tppumodule.writeusedmacros;
+ begin
+ ppufile.do_crc:=false;
+ is_initial:= true;
+ initialmacrosymtable.foreach(@writeusedmacro,nil);
+ is_initial:= false;
+ if assigned(globalmacrosymtable) then
+ globalmacrosymtable.foreach(@writeusedmacro,nil);
+ localmacrosymtable.foreach(@writeusedmacro,nil);
+ ppufile.writeentry(ibusedmacros);
+ ppufile.do_crc:=true;
+ end;
+{$ENDIF}
+
+ procedure tppumodule.writesourcefiles;
+ var
+ hp : tinputfile;
+ i,j : longint;
+ begin
+ { second write the used source files }
+ ppufile.do_crc:=false;
+ hp:=sourcefiles.files;
+ { write source files directly in good order }
+ j:=0;
+ while assigned(hp) do
+ begin
+ inc(j);
+ hp:=hp.ref_next;
+ end;
+ while j>0 do
+ begin
+ hp:=sourcefiles.files;
+ for i:=1 to j-1 do
+ hp:=hp.ref_next;
+ ppufile.putstring(hp.name^);
+ ppufile.putlongint(hp.getfiletime);
+ dec(j);
+ end;
+ ppufile.writeentry(ibsourcefiles);
+ ppufile.do_crc:=true;
+ end;
+
+
+ procedure tppumodule.writeusedunit(intf:boolean);
+ var
+ hp : tused_unit;
+ oldcrc : boolean;
+ begin
+ { write a reference for each used unit }
+ hp:=tused_unit(used_units.first);
+ while assigned(hp) do
+ begin
+ if hp.in_interface=intf then
+ begin
+ ppufile.putstring(hp.u.realmodulename^);
+ { the checksum should not affect the crc of this unit ! (PFV) }
+ oldcrc:=ppufile.do_crc;
+ ppufile.do_crc:=false;
+ ppufile.putlongint(longint(hp.checksum));
+ ppufile.putlongint(longint(hp.interface_checksum));
+ ppufile.putlongint(longint(hp.indirect_checksum));
+ ppufile.do_crc:=oldcrc;
+ { combine all indirect checksums from units used by this unit }
+ if intf then
+ ppufile.indirect_crc:=ppufile.indirect_crc xor hp.indirect_checksum;
+ end;
+ hp:=tused_unit(hp.next);
+ end;
+ ppufile.do_interface_crc:=true;
+ ppufile.writeentry(ibloadunit);
+ end;
+
+
+ procedure tppumodule.writelinkcontainer(var p:tlinkcontainer;id:byte;strippath:boolean);
+ var
+ hcontainer : tlinkcontainer;
+ s : string;
+ mask : cardinal;
+ begin
+ hcontainer:=TLinkContainer.Create;
+ while not p.empty do
+ begin
+ s:=p.get(mask);
+ if strippath then
+ ppufile.putstring(ExtractFileName(s))
+ else
+ ppufile.putstring(s);
+ ppufile.putlongint(mask);
+ hcontainer.add(s,mask);
+ end;
+ ppufile.writeentry(id);
+ p.Free;
+ p:=hcontainer;
+ end;
+
+
+ procedure tppumodule.writederefmap;
+ var
+ i : longint;
+ oldcrc : boolean;
+ begin
+ { This does not influence crc }
+ oldcrc:=ppufile.do_crc;
+ ppufile.do_crc:=false;
+ { The unit map used for resolving }
+ ppufile.putlongint(derefmapcnt);
+ for i:=0 to derefmapcnt-1 do
+ begin
+ if not assigned(derefmap[i].u) then
+ internalerror(2005011512);
+ ppufile.putstring(derefmap[i].u.modulename^)
+ end;
+ ppufile.writeentry(ibderefmap);
+ ppufile.do_crc:=oldcrc;
+ end;
+
+
+ procedure tppumodule.writederefdata;
+ var
+ oldcrc : boolean;
+ len,hlen : longint;
+ buf : array[0..1023] of byte;
+ begin
+ if longword(derefdataintflen)>derefdata.size then
+ internalerror(200310223);
+ derefdata.seek(0);
+ { Write interface data }
+ len:=derefdataintflen;
+ while (len>0) do
+ begin
+ if len>1024 then
+ hlen:=1024
+ else
+ hlen:=len;
+ derefdata.read(buf,hlen);
+ ppufile.putdata(buf,hlen);
+ dec(len,hlen);
+ end;
+ { Write implementation data, this does not influence crc }
+ oldcrc:=ppufile.do_crc;
+ ppufile.do_crc:=false;
+ len:=derefdata.size-derefdataintflen;
+ while (len>0) do
+ begin
+ if len>1024 then
+ hlen:=1024
+ else
+ hlen:=len;
+ derefdata.read(buf,hlen);
+ ppufile.putdata(buf,hlen);
+ dec(len,hlen);
+ end;
+ if derefdata.pos<>derefdata.size then
+ internalerror(200310224);
+ ppufile.do_crc:=oldcrc;
+ ppufile.writeentry(ibderefdata);
+ end;
+
+
+ procedure tppumodule.writeImportSymbols;
+ var
+ i,j : longint;
+ ImportLibrary : TImportLibrary;
+ ImportSymbol : TImportSymbol;
+ begin
+ for i:=0 to ImportLibraryList.Count-1 do
+ begin
+ ImportLibrary:=TImportLibrary(ImportLibraryList[i]);
+ ppufile.putstring(ImportLibrary.Name);
+ ppufile.putlongint(ImportLibrary.ImportSymbolList.Count);
+ for j:=0 to ImportLibrary.ImportSymbolList.Count-1 do
+ begin
+ ImportSymbol:=TImportSymbol(ImportLibrary.ImportSymbolList[j]);
+ ppufile.putstring(ImportSymbol.Name);
+ ppufile.putstring(ImportSymbol.MangledName);
+ ppufile.putlongint(ImportSymbol.OrdNr);
+ ppufile.putbyte(byte(ImportSymbol.IsVar));
+ end;
+ end;
+ ppufile.writeentry(ibImportSymbols);
+ end;
+
+
+ procedure tppumodule.writeResources;
+ var
+ res : TCmdStrListItem;
+ begin
+ res:=TCmdStrListItem(ResourceFiles.First);
+ while res<>nil do
+ begin
+ ppufile.putstring(res.FPStr);
+ res:=TCmdStrListItem(res.Next);
+ end;
+ ppufile.writeentry(ibresources);
+ end;
+
+
+{$IFDEF MACRO_DIFF_HINT}
+
+{
+ Define MACRO_DIFF_HINT for the whole compiler (and ppudump)
+ to turn this facility on. Also the hint messages defined
+ below must be commented in in the msg/errore.msg file.
+
+ There is some problems with this, thats why it is shut off:
+
+ At the first compilation, consider a macro which is not initially
+ defined, but it is used (e g the check that it is undefined is true).
+ Since it do not exist, there is no macro object where the is_used
+ flag can be set. Later on when the macro is defined, and the ppu
+ is opened, the check cannot detect this.
+
+ Also, in which macro object should this flag be set ? It cant be set
+ for macros in the initialmacrosymboltable since this table is shared
+ between different files.
+}
+
+ procedure tppumodule.readusedmacros;
+ var
+ hs : string;
+ mac : tmacro;
+ was_initial,
+ was_used : boolean;
+ {Reads macros which was defined or used when the module was compiled.
+ This is done when a ppu file is open, before it possibly is parsed.}
+ begin
+ while not ppufile.endofentry do
+ begin
+ hs:=ppufile.getstring;
+ was_initial:=boolean(ppufile.getbyte);
+ was_used:=boolean(ppufile.getbyte);
+ mac:=tmacro(initialmacrosymtable.Find(hs));
+ if assigned(mac) then
+ begin
+{$ifndef EXTDEBUG}
+ { if we don't have the sources why tell }
+ if sources_avail then
+{$endif ndef EXTDEBUG}
+ if (not was_initial) and was_used then
+ Message2(unit_h_cond_not_set_in_last_compile,hs,mainsource^);
+ end
+ else { not assigned }
+ if was_initial and
+ was_used then
+ Message2(unit_h_cond_set_in_last_compile,hs,mainsource^);
+ end;
+ end;
+{$ENDIF}
+
+ procedure tppumodule.readsourcefiles;
+ var
+ temp,hs : string;
+ temp_dir : TCmdStr;
+ main_dir : TCmdStr;
+ found,
+ is_main : boolean;
+ orgfiletime,
+ source_time : longint;
+ hp : tinputfile;
+ begin
+ sources_avail:=(flags and uf_release) = 0;
+ if not sources_avail then
+ exit;
+ is_main:=true;
+ main_dir:='';
+ while not ppufile.endofentry do
+ begin
+ hs:=ppufile.getstring;
+ orgfiletime:=ppufile.getlongint;
+ temp_dir:='';
+ if (flags and uf_in_library)<>0 then
+ begin
+ sources_avail:=false;
+ temp:=' library';
+ end
+ else if pos('Macro ',hs)=1 then
+ begin
+ { we don't want to find this file }
+ { but there is a problem with file indexing !! }
+ temp:='';
+ end
+ else
+ begin
+ { check the date of the source files:
+ 1 path of ppu
+ 2 path of main source
+ 3 current dir
+ 4 include/unit path }
+ Source_Time:=GetNamedFileTime(path^+hs);
+ found:=false;
+ if Source_Time<>-1 then
+ hs:=path^+hs
+ else
+ if not(is_main) then
+ begin
+ Source_Time:=GetNamedFileTime(main_dir+hs);
+ if Source_Time<>-1 then
+ hs:=main_dir+hs;
+ end;
+ if Source_Time=-1 then
+ Source_Time:=GetNamedFileTime(hs);
+ if (Source_Time=-1) then
+ begin
+ if is_main then
+ found:=unitsearchpath.FindFile(hs,true,temp_dir)
+ else
+ found:=includesearchpath.FindFile(hs,true,temp_dir);
+ if found then
+ begin
+ Source_Time:=GetNamedFileTime(temp_dir);
+ if Source_Time<>-1 then
+ hs:=temp_dir;
+ end;
+ end;
+ if Source_Time<>-1 then
+ begin
+ if is_main then
+ main_dir:=ExtractFilePath(hs);
+ temp:=' time '+filetimestring(source_time);
+ if (orgfiletime<>-1) and
+ (source_time<>orgfiletime) then
+ begin
+ do_compile:=true;
+ recompile_reason:=rr_sourcenewer;
+ Message2(unit_u_source_modified,hs,ppufilename^,@queuecomment);
+ temp:=temp+' *';
+ end;
+ end
+ else
+ begin
+ sources_avail:=false;
+ temp:=' not found';
+ end;
+ hp:=tdosinputfile.create(hs);
+ { the indexing is wrong here PM }
+ sourcefiles.register_file(hp);
+ end;
+ if is_main then
+ begin
+ stringdispose(mainsource);
+ mainsource:=stringdup(hs);
+ end;
+ Message1(unit_u_ppu_source,hs+temp,@queuecomment);
+ is_main:=false;
+ end;
+ { check if we want to rebuild every unit, only if the sources are
+ available }
+ if do_build and sources_avail then
+ begin
+ do_compile:=true;
+ recompile_reason:=rr_build;
+ end;
+ end;
+
+
+ procedure tppumodule.readloadunit;
+ var
+ hs : string;
+ pu : tused_unit;
+ hp : tppumodule;
+ indchecksum,
+ intfchecksum,
+ checksum : cardinal;
+ begin
+ while not ppufile.endofentry do
+ begin
+ hs:=ppufile.getstring;
+ checksum:=cardinal(ppufile.getlongint);
+ intfchecksum:=cardinal(ppufile.getlongint);
+ indchecksum:=cardinal(ppufile.getlongint);
+ { set the state of this unit before registering, this is
+ needed for a correct circular dependency check }
+ hp:=registerunit(self,hs,'');
+ pu:=addusedunit(hp,false,nil);
+ pu.checksum:=checksum;
+ pu.interface_checksum:=intfchecksum;
+ pu.indirect_checksum:=indchecksum;
+ end;
+ in_interface:=false;
+ end;
+
+
+ procedure tppumodule.readlinkcontainer(var p:tlinkcontainer);
+ var
+ s : string;
+ m : longint;
+ begin
+ while not ppufile.endofentry do
+ begin
+ s:=ppufile.getstring;
+ m:=ppufile.getlongint;
+ p.add(s,m);
+ end;
+ end;
+
+
+ procedure tppumodule.readderefmap;
+ var
+ i : longint;
+ begin
+ { Load unit map used for resolving }
+ derefmapsize:=ppufile.getlongint;
+ derefmapcnt:=derefmapsize;
+ getmem(derefmap,derefmapsize*sizeof(tderefmaprec));
+ fillchar(derefmap^,derefmapsize*sizeof(tderefmaprec),0);
+ for i:=0 to derefmapsize-1 do
+ derefmap[i].modulename:=stringdup(ppufile.getstring);
+ end;
+
+
+ procedure tppumodule.readderefdata;
+ var
+ len,hlen : longint;
+ buf : array[0..1023] of byte;
+ begin
+ len:=ppufile.entrysize;
+ while (len>0) do
+ begin
+ if len>1024 then
+ hlen:=1024
+ else
+ hlen:=len;
+ ppufile.getdata(buf,hlen);
+ derefdata.write(buf,hlen);
+ dec(len,hlen);
+ end;
+ end;
+
+
+ procedure tppumodule.readImportSymbols;
+ var
+ j,
+ extsymcnt : longint;
+ ImportLibrary : TImportLibrary;
+ extsymname : string;
+ extsymmangledname : string;
+ extsymordnr : longint;
+ extsymisvar : boolean;
+ begin
+ while not ppufile.endofentry do
+ begin
+ ImportLibrary:=TImportLibrary.Create(ImportLibraryList,ppufile.getstring);
+ extsymcnt:=ppufile.getlongint;
+ for j:=0 to extsymcnt-1 do
+ begin
+ extsymname:=ppufile.getstring;
+ extsymmangledname:=ppufile.getstring;
+ extsymordnr:=ppufile.getlongint;
+ extsymisvar:=(ppufile.getbyte<>0);
+ TImportSymbol.Create(ImportLibrary.ImportSymbolList,extsymname,
+ extsymmangledname,extsymordnr,extsymisvar);
+ end;
+ end;
+ end;
+
+
+ procedure tppumodule.readResources;
+ begin
+ while not ppufile.endofentry do
+ resourcefiles.Insert(ppufile.getstring);
+ end;
+
+
+ procedure tppumodule.readwpofile;
+ var
+ orgwpofilename: string;
+ orgwpofiletime: longint;
+ begin
+ { check whether we are using the same wpo feedback input file as when
+ this unit was compiled (same file name and file date)
+ }
+ orgwpofilename:=ppufile.getstring;
+ orgwpofiletime:=ppufile.getlongint;
+ if (extractfilename(orgwpofilename)<>extractfilename(wpofeedbackinput)) or
+ (orgwpofiletime<>GetNamedFileTime(orgwpofilename)) then
+ { make sure we don't throw away a precompiled unit if the user simply
+ forgot to specify the right wpo feedback file
+ }
+ message3(unit_e_different_wpo_file,ppufilename^,orgwpofilename,filetimestring(orgwpofiletime));
+ end;
+
+
+ procedure tppumodule.load_interface;
+ var
+ b : byte;
+ newmodulename : string;
+ begin
+ { read interface part }
+ repeat
+ b:=ppufile.readentry;
+ case b of
+ ibmodulename :
+ begin
+ newmodulename:=ppufile.getstring;
+ if (cs_check_unit_name in current_settings.globalswitches) and
+ (upper(newmodulename)<>modulename^) then
+ Message2(unit_f_unit_name_error,realmodulename^,newmodulename);
+ stringdispose(modulename);
+ stringdispose(realmodulename);
+ modulename:=stringdup(upper(newmodulename));
+ realmodulename:=stringdup(newmodulename);
+ end;
+ ibmoduleoptions:
+ begin
+ ppufile.getsmallset(moduleoptions);
+ if mo_has_deprecated_msg in moduleoptions then
+ begin
+ stringdispose(deprecatedmsg);
+ deprecatedmsg:=stringdup(ppufile.getstring);
+ end;
+ end;
+ ibsourcefiles :
+ readsourcefiles;
+{$IFDEF MACRO_DIFF_HINT}
+ ibusedmacros :
+ readusedmacros;
+{$ENDIF}
+ ibloadunit :
+ readloadunit;
+ iblinkunitofiles :
+ readlinkcontainer(LinkUnitOFiles);
+ iblinkunitstaticlibs :
+ readlinkcontainer(LinkUnitStaticLibs);
+ iblinkunitsharedlibs :
+ readlinkcontainer(LinkUnitSharedLibs);
+ iblinkotherofiles :
+ readlinkcontainer(LinkotherOFiles);
+ iblinkotherstaticlibs :
+ readlinkcontainer(LinkotherStaticLibs);
+ iblinkothersharedlibs :
+ readlinkcontainer(LinkotherSharedLibs);
+ iblinkotherframeworks :
+ readlinkcontainer(LinkOtherFrameworks);
+ ibmainname:
+ begin
+ mainname:=stringdup(ppufile.getstring);
+ if (mainaliasname<>defaultmainaliasname) then
+ Message1(scan_w_multiple_main_name_overrides,mainaliasname);
+ mainaliasname:=mainname^;
+ end;
+ ibImportSymbols :
+ readImportSymbols;
+ ibderefmap :
+ readderefmap;
+ ibderefdata :
+ readderefdata;
+ ibresources:
+ readResources;
+ ibwpofile:
+ readwpofile;
+ ibendinterface :
+ break;
+ else
+ Message1(unit_f_ppu_invalid_entry,tostr(b));
+ end;
+ { we can already stop when we know that we must recompile }
+ if do_compile then
+ exit;
+ until false;
+ end;
+
+
+ procedure tppumodule.load_implementation;
+ var
+ b : byte;
+ begin
+ { read implementation part }
+ repeat
+ b:=ppufile.readentry;
+ case b of
+ ibloadunit :
+ readloadunit;
+ ibasmsymbols :
+{ TODO: Remove ibasmsymbols}
+ ;
+ ibendimplementation :
+ break;
+ else
+ Message1(unit_f_ppu_invalid_entry,tostr(b));
+ end;
+ until false;
+ end;
+
+
+ procedure tppumodule.writeppu;
+ begin
+ Message1(unit_u_ppu_write,realmodulename^);
+
+ { create unit flags }
+ if do_release then
+ flags:=flags or uf_release;
+ if assigned(localsymtable) then
+ flags:=flags or uf_local_symtable;
+{$ifdef cpufpemu}
+ if (cs_fp_emulation in current_settings.moduleswitches) then
+ flags:=flags or uf_fpu_emulation;
+{$endif cpufpemu}
+{$ifdef Test_Double_checksum_write}
+ Assign(CRCFile,s+'.IMP');
+ Rewrite(CRCFile);
+{$endif def Test_Double_checksum_write}
+
+ { create new ppufile }
+ ppufile:=tcompilerppufile.create(ppufilename^);
+ if not ppufile.createfile then
+ Message(unit_f_ppu_cannot_write);
+
+ { first the unitname }
+ ppufile.putstring(realmodulename^);
+ ppufile.writeentry(ibmodulename);
+
+ ppufile.putsmallset(moduleoptions);
+ if mo_has_deprecated_msg in moduleoptions then
+ ppufile.putstring(deprecatedmsg^);
+ ppufile.writeentry(ibmoduleoptions);
+
+ { write the alternate main procedure name if any }
+ if assigned(mainname) then
+ begin
+ ppufile.putstring(mainname^);
+ ppufile.writeentry(ibmainname);
+ end;
+
+ writesourcefiles;
+{$IFDEF MACRO_DIFF_HINT}
+ writeusedmacros;
+{$ENDIF}
+
+ { write interface uses }
+ writeusedunit(true);
+
+ { write the objectfiles and libraries that come for this unit,
+ preserve the containers because they are still needed to load
+ the link.res.
+ All doesn't depend on the crc! It doesn't matter
+ if a unit is in a .o or .a file }
+ ppufile.do_crc:=false;
+ { write after source files, so that we know whether or not the compiler
+ will recompile the unit when checking whether the correct wpo file is
+ used (if it will recompile the unit anyway, it doesn't matter)
+ }
+ if (wpofeedbackinput<>'') then
+ begin
+ ppufile.putstring(wpofeedbackinput);
+ ppufile.putlongint(getnamedfiletime(wpofeedbackinput));
+ ppufile.writeentry(ibwpofile);
+ end;
+ writelinkcontainer(linkunitofiles,iblinkunitofiles,true);
+ writelinkcontainer(linkunitstaticlibs,iblinkunitstaticlibs,true);
+ writelinkcontainer(linkunitsharedlibs,iblinkunitsharedlibs,true);
+ writelinkcontainer(linkotherofiles,iblinkotherofiles,false);
+ writelinkcontainer(linkotherstaticlibs,iblinkotherstaticlibs,true);
+ writelinkcontainer(linkothersharedlibs,iblinkothersharedlibs,true);
+ writelinkcontainer(linkotherframeworks,iblinkotherframeworks,true);
+ writeImportSymbols;
+ writeResources;
+ ppufile.do_crc:=true;
+
+ { generate implementation deref data, the interface deref data is
+ already generated when calculating the interface crc }
+ if (cs_compilesystem in current_settings.moduleswitches) then
+ begin
+ tstoredsymtable(globalsymtable).buildderef;
+ derefdataintflen:=derefdata.size;
+ end
+ else
+ { the unit may have been re-resolved, in which case the current
+ position in derefdata is not necessarily at the end }
+ derefdata.seek(derefdata.size);
+ tstoredsymtable(globalsymtable).buildderefimpl;
+ if (flags and uf_local_symtable)<>0 then
+ begin
+ tstoredsymtable(localsymtable).buildderef;
+ tstoredsymtable(localsymtable).buildderefimpl;
+ end;
+ tunitwpoinfo(wpoinfo).buildderef;
+ tunitwpoinfo(wpoinfo).buildderefimpl;
+ writederefmap;
+ writederefdata;
+
+ ppufile.writeentry(ibendinterface);
+
+ { write the symtable entries }
+ tstoredsymtable(globalsymtable).ppuwrite(ppufile);
+
+ if assigned(globalmacrosymtable) and (globalmacrosymtable.SymList.count > 0) then
+ begin
+ ppufile.putbyte(byte(true));
+ ppufile.writeentry(ibexportedmacros);
+ tstoredsymtable(globalmacrosymtable).ppuwrite(ppufile);
+ end
+ else
+ begin
+ ppufile.putbyte(byte(false));
+ ppufile.writeentry(ibexportedmacros);
+ end;
+
+ { everything after this doesn't affect the crc }
+ ppufile.do_crc:=false;
+
+ { write implementation uses }
+ writeusedunit(false);
+
+ { end of implementation }
+ ppufile.writeentry(ibendimplementation);
+
+ { write static symtable
+ needed for local debugging of unit functions }
+ if (flags and uf_local_symtable)<>0 then
+ tstoredsymtable(localsymtable).ppuwrite(ppufile);
+
+ { write whole program optimisation-related information }
+ tunitwpoinfo(wpoinfo).ppuwrite(ppufile);
+
+ { the last entry ibend is written automatically }
+
+ { flush to be sure }
+ ppufile.flush;
+ { create and write header }
+ ppufile.header.size:=ppufile.size;
+ ppufile.header.checksum:=ppufile.crc;
+ ppufile.header.interface_checksum:=ppufile.interface_crc;
+ ppufile.header.indirect_checksum:=ppufile.indirect_crc;
+ ppufile.header.compiler:=wordversion;
+ ppufile.header.cpu:=word(target_cpu);
+ ppufile.header.target:=word(target_info.system);
+ ppufile.header.flags:=flags;
+ ppufile.header.deflistsize:=current_module.deflist.count;
+ ppufile.header.symlistsize:=current_module.symlist.count;
+ ppufile.writeheader;
+
+ { save crc in current module also }
+ crc:=ppufile.crc;
+ interface_crc:=ppufile.interface_crc;
+ indirect_crc:=ppufile.indirect_crc;
+
+{$ifdef Test_Double_checksum_write}
+ close(CRCFile);
+{$endif Test_Double_checksum_write}
+
+ ppufile.closefile;
+ ppufile.free;
+ ppufile:=nil;
+ end;
+
+
+ procedure tppumodule.getppucrc;
+ begin
+{$ifdef Test_Double_checksum_write}
+ Assign(CRCFile,s+'.INT')
+ Rewrite(CRCFile);
+{$endif def Test_Double_checksum_write}
+
+ { create new ppufile }
+ ppufile:=tcompilerppufile.create(ppufilename^);
+ ppufile.crc_only:=true;
+ if not ppufile.createfile then
+ Message(unit_f_ppu_cannot_write);
+
+ { first the unitname }
+ ppufile.putstring(realmodulename^);
+ ppufile.writeentry(ibmodulename);
+
+ ppufile.putsmallset(moduleoptions);
+ if mo_has_deprecated_msg in moduleoptions then
+ ppufile.putstring(deprecatedmsg^);
+ ppufile.writeentry(ibmoduleoptions);
+
+ { the interface units affect the crc }
+ writeusedunit(true);
+
+ { deref data of interface that affect the crc }
+ derefdata.reset;
+ tstoredsymtable(globalsymtable).buildderef;
+ derefdataintflen:=derefdata.size;
+ writederefmap;
+ writederefdata;
+
+ ppufile.writeentry(ibendinterface);
+
+ { write the symtable entries }
+ tstoredsymtable(globalsymtable).ppuwrite(ppufile);
+
+ if assigned(globalmacrosymtable) and (globalmacrosymtable.SymList.count > 0) then
+ begin
+ ppufile.putbyte(byte(true));
+ ppufile.writeentry(ibexportedmacros);
+ tstoredsymtable(globalmacrosymtable).ppuwrite(ppufile);
+ end
+ else
+ begin
+ ppufile.putbyte(byte(false));
+ ppufile.writeentry(ibexportedmacros);
+ end;
+
+ { save crc }
+ crc:=ppufile.crc;
+ interface_crc:=ppufile.interface_crc;
+ indirect_crc:=ppufile.indirect_crc;
+
+ { end of implementation, to generate a correct ppufile
+ for ppudump when using INTFPPU define }
+ ppufile.writeentry(ibendimplementation);
+
+{$ifdef Test_Double_checksum}
+ crc_array:=ppufile.crc_test;
+ ppufile.crc_test:=nil;
+ crc_size:=ppufile.crc_index2;
+ crc_array2:=ppufile.crc_test2;
+ ppufile.crc_test2:=nil;
+ crc_size2:=ppufile.crc_index2;
+{$endif Test_Double_checksum}
+
+{$ifdef Test_Double_checksum_write}
+ close(CRCFile);
+{$endif Test_Double_checksum_write}
+
+ { create and write header, this will only be used
+ for debugging purposes }
+ ppufile.header.size:=ppufile.size;
+ ppufile.header.checksum:=ppufile.crc;
+ ppufile.header.interface_checksum:=ppufile.interface_crc;
+ ppufile.header.indirect_checksum:=ppufile.indirect_crc;
+ ppufile.header.compiler:=wordversion;
+ ppufile.header.cpu:=word(target_cpu);
+ ppufile.header.target:=word(target_info.system);
+ ppufile.header.flags:=flags;
+ ppufile.writeheader;
+
+ ppufile.closefile;
+ ppufile.free;
+ ppufile:=nil;
+ end;
+
+
+ procedure tppumodule.load_usedunits;
+ var
+ pu : tused_unit;
+ begin
+ if current_module<>self then
+ internalerror(200212284);
+
+ { load the used units from interface }
+ in_interface:=true;
+ pu:=tused_unit(used_units.first);
+ while assigned(pu) do
+ begin
+ if pu.in_interface then
+ begin
+ tppumodule(pu.u).loadppu;
+ { if this unit is compiled we can stop }
+ if state=ms_compiled then
+ exit;
+ { add this unit to the dependencies }
+ pu.u.adddependency(self);
+ { need to recompile the current unit, check the interface
+ crc. And when not compiled with -Ur then check the complete
+ crc }
+ if (pu.u.interface_crc<>pu.interface_checksum) or
+ (pu.u.indirect_crc<>pu.indirect_checksum) or
+ (
+ ((ppufile.header.flags and uf_release)=0) and
+ (pu.u.crc<>pu.checksum)
+ ) then
+ begin
+ Message2(unit_u_recompile_crc_change,realmodulename^,pu.u.realmodulename^,@queuecomment);
+{$ifdef DEBUG_UNIT_CRC_CHANGES}
+ if (pu.u.interface_crc<>pu.interface_checksum) then
+ writeln(' intfcrc change: ',hexstr(pu.u.interface_crc,8),' <> ',hexstr(pu.interface_checksum,8))
+ else if (pu.u.indirect_crc<>pu.indirect_checksum) then
+ writeln(' indcrc change: ',hexstr(pu.u.indirect_crc,8),' <> ',hexstr(pu.indirect_checksum,8))
+ else
+ writeln(' implcrc change: ',hexstr(pu.u.crc,8),' <> ',hexstr(pu.checksum,8));
+{$endif DEBUG_UNIT_CRC_CHANGES}
+ recompile_reason:=rr_crcchanged;
+ do_compile:=true;
+ exit;
+ end;
+ end;
+ pu:=tused_unit(pu.next);
+ end;
+
+ { ok, now load the interface of this unit }
+ if current_module<>self then
+ internalerror(200208187);
+ deflist.count:=ppufile.header.deflistsize;
+ symlist.count:=ppufile.header.symlistsize;
+ globalsymtable:=tglobalsymtable.create(modulename^,moduleid);
+ tstoredsymtable(globalsymtable).ppuload(ppufile);
+
+ if ppufile.readentry<>ibexportedmacros then
+ Message(unit_f_ppu_read_error);
+ if boolean(ppufile.getbyte) then
+ begin
+ globalmacrosymtable:=tmacrosymtable.Create(true);
+ tstoredsymtable(globalmacrosymtable).ppuload(ppufile)
+ end;
+
+ interface_compiled:=true;
+
+ { read the implementation part, containing
+ the implementation uses and ObjData }
+ in_interface:=false;
+ load_implementation;
+
+ { now only read the implementation uses }
+ pu:=tused_unit(used_units.first);
+ while assigned(pu) do
+ begin
+ if (not pu.in_interface) then
+ begin
+ tppumodule(pu.u).loadppu;
+ { if this unit is compiled we can stop }
+ if state=ms_compiled then
+ exit;
+ { add this unit to the dependencies }
+ pu.u.adddependency(self);
+ { need to recompile the current unit ? }
+ if (pu.u.interface_crc<>pu.interface_checksum) or
+ (pu.u.indirect_crc<>pu.indirect_checksum) then
+ begin
+ Message2(unit_u_recompile_crc_change,realmodulename^,pu.u.realmodulename^+' {impl}',@queuecomment);
+{$ifdef DEBUG_UNIT_CRC_CHANGES}
+ if (pu.u.interface_crc<>pu.interface_checksum) then
+ writeln(' intfcrc change (2): ',hexstr(pu.u.interface_crc,8),' <> ',hexstr(pu.interface_checksum,8))
+ else if (pu.u.indirect_crc<>pu.indirect_checksum) then
+ writeln(' indcrc change (2): ',hexstr(pu.u.indirect_crc,8),' <> ',hexstr(pu.indirect_checksum,8));
+{$endif DEBUG_UNIT_CRC_CHANGES}
+ recompile_reason:=rr_crcchanged;
+ do_compile:=true;
+ exit;
+ end;
+ end;
+ pu:=tused_unit(pu.next);
+ end;
+
+ { load implementation symtable }
+ if (flags and uf_local_symtable)<>0 then
+ begin
+ localsymtable:=tstaticsymtable.create(modulename^,moduleid);
+ tstaticsymtable(localsymtable).ppuload(ppufile);
+ end;
+
+ { we can now derefence all pointers to the implementation parts }
+ tstoredsymtable(globalsymtable).derefimpl;
+ if assigned(localsymtable) then
+ tstoredsymtable(localsymtable).derefimpl;
+
+ { read whole program optimisation-related information }
+ wpoinfo:=tunitwpoinfo.ppuload(ppufile);
+ tunitwpoinfo(wpoinfo).deref;
+ tunitwpoinfo(wpoinfo).derefimpl;
+ end;
+
+
+ function tppumodule.needrecompile:boolean;
+ var
+ pu : tused_unit;
+ begin
+ result:=false;
+ pu:=tused_unit(used_units.first);
+ while assigned(pu) do
+ begin
+ { need to recompile the current unit, check the interface
+ crc. And when not compiled with -Ur then check the complete
+ crc }
+ if (pu.u.interface_crc<>pu.interface_checksum) or
+ (pu.u.indirect_crc<>pu.indirect_checksum) or
+ (
+ (pu.in_interface) and
+ (pu.u.crc<>pu.checksum)
+ ) then
+ begin
+{$ifdef DEBUG_UNIT_CRC_CHANGES}
+ if (pu.u.interface_crc<>pu.interface_checksum) then
+ writeln(' intfcrc change (3): ',hexstr(pu.u.interface_crc,8),' <> ',hexstr(pu.interface_checksum,8))
+ else if (pu.u.indirect_crc<>pu.indirect_checksum) then
+ writeln(' indcrc change (3): ',hexstr(pu.u.indirect_crc,8),' <> ',hexstr(pu.indirect_checksum,8))
+ else
+ writeln(' implcrc change (3): ',hexstr(pu.u.crc,8),' <> ',hexstr(pu.checksum,8));
+{$endif DEBUG_UNIT_CRC_CHANGES}
+ result:=true;
+ exit;
+ end;
+ pu:=tused_unit(pu.next);
+ end;
+ end;
+
+
+ procedure tppumodule.setdefgeneration;
+ begin
+ defsgeneration:=currentdefgeneration;
+ inc(currentdefgeneration);
+ end;
+
+
+ procedure tppumodule.reload_flagged_units;
+ var
+ hp : tppumodule;
+ begin
+ { now reload all dependent units with outdated defs }
+ hp:=tppumodule(loaded_units.first);
+ while assigned(hp) do
+ begin
+ if hp.do_reload and
+ (hp.defsgeneration<defsgeneration) then
+ begin
+ hp.defsgeneration:=defsgeneration;
+ hp.loadppu
+ end
+ else
+ hp.do_reload:=false;
+ hp:=tppumodule(hp.next);
+ end;
+ end;
+
+
+ procedure tppumodule.loadppu;
+ const
+ ImplIntf : array[boolean] of string[15]=('implementation','interface');
+ var
+ do_load,
+ second_time : boolean;
+ old_current_module : tmodule;
+ begin
+ old_current_module:=current_module;
+ Message3(unit_u_load_unit,old_current_module.modulename^,
+ ImplIntf[old_current_module.in_interface],
+ modulename^);
+
+ { Update loaded_from to detect cycles }
+ loaded_from:=old_current_module;
+
+ { check if the globalsymtable is already available, but
+ we must reload when the do_reload flag is set }
+ if (not do_reload) and
+ assigned(globalsymtable) then
+ exit;
+
+ { reset }
+ do_load:=true;
+ second_time:=false;
+ set_current_module(self);
+
+ { A force reload }
+ if do_reload then
+ begin
+ Message(unit_u_forced_reload);
+ do_reload:=false;
+ { When the unit is already loaded or being loaded
+ we can maybe skip a complete reload/recompile }
+ if assigned(globalsymtable) and
+ (not needrecompile) then
+ begin
+ { When we don't have any data stored yet there
+ is nothing to resolve }
+ if interface_compiled then
+ begin
+ Message1(unit_u_reresolving_unit,modulename^);
+ tstoredsymtable(globalsymtable).deref;
+ tstoredsymtable(globalsymtable).derefimpl;
+ if assigned(localsymtable) then
+ begin
+ tstoredsymtable(localsymtable).deref;
+ tstoredsymtable(localsymtable).derefimpl;
+ end;
+ if assigned(wpoinfo) then
+ begin
+ tunitwpoinfo(wpoinfo).deref;
+ tunitwpoinfo(wpoinfo).derefimpl;
+ end;
+
+ { We have to flag the units that depend on this unit even
+ though it didn't change, because they might also
+ indirectly depend on the unit that did change (e.g.,
+ in case rgobj, rgx86 and rgcpu have been compiled
+ already, and then rgobj is recompiled for some reason
+ -> rgx86 is re-reresolved, but the vmtentries of trgcpu
+ must also be re-resolved, because they will also contain
+ pointers to procdefs in the old trgobj (in case of a
+ recompile, all old defs are freed) }
+ flagdependent(old_current_module);
+ reload_flagged_units;
+ end
+ else
+ Message1(unit_u_skipping_reresolving_unit,modulename^);
+ do_load:=false;
+ end;
+ end;
+
+ if do_load then
+ begin
+ { loading the unit for a second time? }
+ if state=ms_registered then
+ state:=ms_load
+ else
+ begin
+ { try to load the unit a second time first }
+ Message1(unit_u_second_load_unit,modulename^);
+ Message2(unit_u_previous_state,modulename^,ModuleStateStr[state]);
+ { Flag modules to reload }
+ flagdependent(old_current_module);
+ { Reset the module }
+ reset;
+ if state in [ms_compile,ms_second_compile] then
+ begin
+ Message1(unit_u_second_compile_unit,modulename^);
+ state:=ms_second_compile;
+ do_compile:=true;
+ end
+ else
+ state:=ms_second_load;
+ second_time:=true;
+ end;
+
+ { close old_current_ppu on system that are
+ short on file handles like DOS PM }
+{$ifdef SHORT_ON_FILE_HANDLES}
+ if old_current_module.is_unit and
+ assigned(tppumodule(old_current_module).ppufile) then
+ tppumodule(old_current_module).ppufile.tempclose;
+{$endif SHORT_ON_FILE_HANDLES}
+
+ { try to opening ppu, skip this when we already
+ know that we need to compile the unit }
+ if not do_compile then
+ begin
+ Message1(unit_u_loading_unit,modulename^);
+ search_unit_files(false);
+ if not do_compile then
+ begin
+ load_interface;
+ setdefgeneration;
+ if not do_compile then
+ begin
+ load_usedunits;
+ if not do_compile then
+ Message1(unit_u_finished_loading_unit,modulename^);
+ end;
+ end;
+ { PPU is not needed anymore }
+ if assigned(ppufile) then
+ begin
+ ppufile.closefile;
+ ppufile.free;
+ ppufile:=nil;
+ end;
+ end;
+
+ { Do we need to recompile the unit }
+ if do_compile then
+ begin
+ { recompile the unit or give a fatal error if sources not available }
+ if not(sources_avail) then
+ begin
+ search_unit_files(true);
+ if not(sources_avail) then
+ begin
+ printcomments;
+ if recompile_reason=rr_noppu then
+ Message2(unit_f_cant_find_ppu,realmodulename^,loaded_from.realmodulename^)
+ else
+ Message1(unit_f_cant_compile_unit,realmodulename^);
+ end;
+ end;
+ { we found the sources, we do not need the verbose messages anymore }
+ if comments <> nil then
+ begin
+ comments.free;
+ comments:=nil;
+ end;
+ { Flag modules to reload }
+ flagdependent(old_current_module);
+ { Reset the module }
+ reset;
+ { compile this module }
+ if not(state in [ms_compile,ms_second_compile]) then
+ state:=ms_compile;
+ compile(mainsource^);
+ setdefgeneration;
+ end
+ else
+ state:=ms_compiled;
+
+ if current_module<>self then
+ internalerror(200212282);
+
+ if in_interface then
+ internalerror(200212283);
+
+ { for a second_time recompile reload all dependent units,
+ for a first time compile register the unit _once_ }
+ if second_time then
+ reload_flagged_units
+ else
+ usedunits.concat(tused_unit.create(self,true,false,nil));
+
+ { reopen the old module }
+{$ifdef SHORT_ON_FILE_HANDLES}
+ if old_current_module.is_unit and
+ assigned(tppumodule(old_current_module).ppufile) then
+ tppumodule(old_current_module).ppufile.tempopen;
+{$endif SHORT_ON_FILE_HANDLES}
+ end;
+
+ { we are back, restore current_module }
+ set_current_module(old_current_module);
+ end;
+
+
+{*****************************************************************************
+ RegisterUnit
+*****************************************************************************}
+
+
+ function registerunit(callermodule:tmodule;const s : TIDString;const fn:string) : tppumodule;
+ var
+ ups : TIDString;
+ hp : tppumodule;
+ hp2 : tmodule;
+ begin
+ { Info }
+ ups:=upper(s);
+ { search all loaded units }
+ hp:=tppumodule(loaded_units.first);
+ while assigned(hp) do
+ begin
+ if hp.modulename^=ups then
+ begin
+ { only check for units. The main program is also
+ as a unit in the loaded_units list. We simply need
+ to ignore this entry (PFV) }
+ if hp.is_unit then
+ begin
+ { both units in interface ? }
+ if callermodule.in_interface and
+ hp.in_interface then
+ begin
+ { check for a cycle }
+ hp2:=callermodule.loaded_from;
+ while assigned(hp2) and (hp2<>hp) do
+ begin
+ if hp2.in_interface then
+ hp2:=hp2.loaded_from
+ else
+ hp2:=nil;
+ end;
+ if assigned(hp2) then
+ Message2(unit_f_circular_unit_reference,callermodule.realmodulename^,hp.realmodulename^);
+ end;
+ break;
+ end;
+ end;
+ { the next unit }
+ hp:=tppumodule(hp.next);
+ end;
+ { the unit is not in the loaded units,
+ we create an entry and register the unit }
+ if not assigned(hp) then
+ begin
+ Message1(unit_u_registering_new_unit,Upper(s));
+ hp:=tppumodule.create(callermodule,s,fn,true);
+ hp.loaded_from:=callermodule;
+ addloadedunit(hp);
+ end;
+ { return }
+ registerunit:=hp;
+ end;
+
+end.
diff --git a/closures/compiler/gendef.pas b/closures/compiler/gendef.pas
new file mode 100644
index 0000000000..65e64c353e
--- /dev/null
+++ b/closures/compiler/gendef.pas
@@ -0,0 +1,163 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generation of a .def file for needed for Os2/Win32
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit gendef;
+
+{$i fpcdefs.inc}
+
+interface
+uses
+ cclasses;
+
+type
+ tdeffile=class
+ fname : string;
+ constructor create(const fn:string);
+ destructor destroy;override;
+ procedure addexport(const s:string);
+ procedure addimport(const s:string);
+ procedure writefile;
+ function empty : boolean;
+ private
+ is_empty : boolean;
+ WrittenOnDisk : boolean;
+ exportlist,
+ importlist : TCmdStrList;
+ end;
+
+var
+ deffile : tdeffile;
+
+
+implementation
+
+uses
+ SysUtils,
+ systems,cutils,globtype,globals;
+
+{******************************************************************************
+ TDefFile
+******************************************************************************}
+
+constructor tdeffile.create(const fn:string);
+begin
+ fname:=fn;
+ WrittenOnDisk:=false;
+ is_empty:=true;
+ importlist:=TCmdStrList.Create;
+ exportlist:=TCmdStrList.Create;
+end;
+
+
+destructor tdeffile.destroy;
+begin
+ if WrittenOnDisk and
+ not(cs_link_nolink in current_settings.globalswitches) then
+ DeleteFile(FName);
+ importlist.Free;
+ exportlist.Free;
+end;
+
+
+
+procedure tdeffile.addexport(const s:string);
+begin
+ exportlist.insert(s);
+ is_empty:=false;
+end;
+
+
+procedure tdeffile.addimport(const s:string);
+begin
+ importlist.insert(s);
+ is_empty:=false;
+end;
+
+
+function tdeffile.empty : boolean;
+begin
+ empty:=is_empty or DescriptionSetExplicity;
+end;
+
+
+procedure tdeffile.writefile;
+var
+ t : text;
+begin
+ If WrittenOnDisk then
+ Exit;
+{ open file }
+ assign(t,fname);
+ {$push}{$I-}
+ rewrite(t);
+ {$pop}
+ if ioresult<>0 then
+ exit;
+ case target_info.system of
+ system_i386_Os2, system_i386_emx:
+ begin
+ write(t,'NAME '+ChangeFileExt(inputfilename,''));
+ if usewindowapi then
+ write(t,' WINDOWAPI');
+ writeln(t,'');
+ writeln(t,'PROTMODE');
+ writeln(t,'DESCRIPTION '+''''+description+'''');
+ writeln(t,'DATA'#9'MULTIPLE');
+ writeln(t,'STACKSIZE'#9+tostr(stacksize));
+ writeln(t,'HEAPSIZE'#9+tostr(heapsize));
+ end;
+ system_i386_win32,
+ system_x86_64_win64,
+ system_ia64_win64,
+ system_arm_wince,
+ system_i386_wince,
+ system_i386_wdosx :
+ begin
+ if description<>'' then
+ writeln(t,'DESCRIPTION '+''''+description+'''');
+ if dllversion<>'' then
+ writeln(t,'VERSION '+dllversion);
+ end;
+ end;
+
+{write imports}
+ if not importlist.empty then
+ begin
+ writeln(t,'');
+ writeln(t,'IMPORTS');
+ while not importlist.empty do
+ writeln(t,#9+importlist.getfirst);
+ end;
+
+{write exports}
+ if not exportlist.empty then
+ begin
+ writeln(t,'');
+ writeln(t,'EXPORTS');
+ while not exportlist.empty do
+ writeln(t,#9+exportlist.getfirst);
+ end;
+
+ close(t);
+ WrittenOnDisk:=true;
+end;
+
+end.
diff --git a/closures/compiler/generic/cpuinfo.pas b/closures/compiler/generic/cpuinfo.pas
new file mode 100644
index 0000000000..28b762da7b
--- /dev/null
+++ b/closures/compiler/generic/cpuinfo.pas
@@ -0,0 +1,51 @@
+{
+ Copyright (c) 1998-2002 by the Free Pascal development team
+
+ Basic Processor information for the Generic CPU
+ This file is used by PPUDump program from utils subdirectory.
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+Unit CPUInfo;
+
+Interface
+
+ uses
+ globtype;
+
+Type
+ bestreal = extended;
+ ts32real = single;
+ ts64real = double;
+ ts80real = type extended;
+ ts128real = type extended;
+ ts64comp = comp;
+
+ pbestreal=^bestreal;
+
+ { possible supported processors for this target }
+ tcputype =
+ (cpu_none
+ );
+
+
+Type
+ tfputype =
+ (fpu_none,
+ fpu_soft
+ );
+
+Const
+ cputypestr : array[tcputype] of string[8] = ('none');
+ fputypestr : array[tfputype] of string[6] = ('none','soft');
+
+Implementation
+
+end.
diff --git a/closures/compiler/globals.pas b/closures/compiler/globals.pas
new file mode 100644
index 0000000000..8cff5fbdf4
--- /dev/null
+++ b/closures/compiler/globals.pas
@@ -0,0 +1,1549 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit implements some support functions and global variables
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit globals;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+{$ifdef windows}
+ windows,
+{$endif}
+{$ifdef os2}
+ dos,
+{$endif os2}
+{$ifdef hasunix}
+ Baseunix,unix,
+{$endif}
+
+{$IFNDEF USE_FAKE_SYSUTILS}
+ sysutils,
+{$ELSE}
+ fksysutl,
+{$ENDIF}
+
+ { comphook pulls in sysutils anyways }
+ cutils,cclasses,cfileutl,
+ cpuinfo,
+ globtype,version,systems;
+
+ const
+ delphimodeswitches =
+ [m_delphi,m_all,m_class,m_objpas,m_result,m_string_pchar,
+ m_pointer_2_procedure,m_autoderef,m_tp_procvar,m_initfinal,m_default_ansistring,
+ m_out,m_default_para,m_duplicate_names,m_hintdirective,
+ m_property,m_default_inline,m_except,m_advanced_records];
+ delphiunicodemodeswitches = delphimodeswitches + [m_systemcodepage];
+ fpcmodeswitches =
+ [m_fpc,m_all,m_string_pchar,m_nested_comment,m_repeat_forward,
+ m_cvar_support,m_initfinal,m_hintdirective,
+ m_property,m_default_inline];
+ objfpcmodeswitches =
+ [m_objfpc,m_fpc,m_all,m_class,m_objpas,m_result,m_string_pchar,m_nested_comment,
+ m_repeat_forward,m_cvar_support,m_initfinal,m_out,m_default_para,m_hintdirective,
+ m_property,m_default_inline,m_except];
+ tpmodeswitches =
+ [m_tp7,m_all,m_tp_procvar,m_duplicate_names];
+{$ifdef gpc_mode}
+ gpcmodeswitches =
+ [m_gpc,m_all,m_tp_procvar];
+{$endif}
+ macmodeswitches =
+ [m_mac,m_all,m_cvar_support,m_mac_procvar,m_nested_procvars,m_non_local_goto,m_isolike_unary_minus,m_default_inline];
+ isomodeswitches =
+ [m_iso,m_all,m_tp_procvar,m_duplicate_names,m_nested_procvars,m_non_local_goto,m_isolike_unary_minus];
+
+ { maximum nesting of routines }
+ maxnesting = 32;
+
+ { Filenames and extensions }
+ sourceext = '.pp';
+ pasext = '.pas';
+ pext = '.p';
+
+ treelogfilename = 'tree.log';
+
+{$if defined(CPUARM) and defined(FPUFPA)}
+ MathQNaN : tdoublerec = (bytes : (0,0,252,255,0,0,0,0));
+ MathInf : tdoublerec = (bytes : (0,0,240,127,0,0,0,0));
+ MathNegInf : tdoublerec = (bytes : (0,0,240,255,0,0,0,0));
+ MathPi : tdoublerec = (bytes : (251,33,9,64,24,45,68,84));
+{$else}
+{$ifdef FPC_LITTLE_ENDIAN}
+ MathQNaN : tdoublerec = (bytes : (0,0,0,0,0,0,252,255));
+ MathInf : tdoublerec = (bytes : (0,0,0,0,0,0,240,127));
+ MathNegInf : tdoublerec = (bytes : (0,0,0,0,0,0,240,255));
+ MathPi : tdoublerec = (bytes : (24,45,68,84,251,33,9,64));
+ MathPiExtended : textendedrec = (bytes : (53,194,104,33,162,218,15,201,0,64));
+{$else FPC_LITTLE_ENDIAN}
+ MathQNaN : tdoublerec = (bytes : (255,252,0,0,0,0,0,0));
+ MathInf : tdoublerec = (bytes : (127,240,0,0,0,0,0,0));
+ MathNegInf : tdoublerec = (bytes : (255,240,0,0,0,0,0,0));
+ MathPi : tdoublerec = (bytes : (64,9,33,251,84,68,45,24));
+ MathPiExtended : textendedrec = (bytes : (64,0,201,15,218,162,33,104,194,53));
+{$endif FPC_LITTLE_ENDIAN}
+{$endif}
+ CP_UTF8 = 65001;
+ CP_UTF16 = 1200;
+ CP_NONE = 65535;
+
+
+ type
+ { this is written to ppus during token recording for generics so it must be packed }
+ tsettings = packed record
+ alignment : talignmentinfo;
+ globalswitches : tglobalswitches;
+ moduleswitches : tmoduleswitches;
+ localswitches : tlocalswitches;
+ modeswitches : tmodeswitches;
+ optimizerswitches : toptimizerswitches;
+ { generate information necessary to perform these wpo's during a subsequent compilation }
+ genwpoptimizerswitches: twpoptimizerswitches;
+ { perform these wpo's using information generated during a previous compilation }
+ dowpoptimizerswitches: twpoptimizerswitches;
+ debugswitches : tdebugswitches;
+ { 0: old behaviour for sets <=256 elements
+ >0: round to this size }
+ setalloc,
+ packenum : shortint;
+
+ packrecords : shortint;
+ maxfpuregisters : shortint;
+
+ cputype,
+ optimizecputype : tcputype;
+ fputype : tfputype;
+ asmmode : tasmmode;
+ interfacetype : tinterfacetypes;
+ defproccall : tproccalloption;
+ sourcecodepage : tstringencoding;
+
+ minfpconstprec : tfloattype;
+
+ disabledircache : boolean;
+
+ { CPU targets with microcontroller support can add a controller specific unit }
+{$if defined(ARM) or defined(AVR)}
+ controllertype : tcontrollertype;
+{$endif defined(ARM) or defined(AVR)}
+ { WARNING: this pointer cannot be written as such in record token }
+ pmessage : pmessagestaterecord;
+ end;
+
+ const
+ LinkMapWeightDefault = 1000;
+
+ type
+ TLinkRec = record
+ Key : AnsiString;
+ Value : AnsiString; // key expands to valuelist "value"
+ Weight: longint;
+ end;
+
+ TLinkStrMap = class
+ private
+ itemcnt : longint;
+ fmap : Array Of TLinkRec;
+ function Lookup(key:Ansistring):longint;
+ function getlinkrec(i:longint):TLinkRec;
+ public
+ procedure Add(key:ansistring;value:AnsiString='';weight:longint=LinkMapWeightDefault);
+ procedure addseries(keys:AnsiString;weight:longint=LinkMapWeightDefault);
+ function AddDep(keyvalue:String):boolean;
+ function AddWeight(keyvalue:String):boolean;
+ procedure SetValue(key:AnsiString;Weight:Integer);
+ procedure SortonWeight;
+ function Find(key:AnsiString):AnsiString;
+ procedure Expand(src:TCmdStrList;dest: TLinkStrMap);
+ procedure UpdateWeights(Weightmap:TLinkStrMap);
+ constructor Create;
+ property count : longint read itemcnt;
+ property items[I:longint]:TLinkRec read getlinkrec; default;
+ end;
+
+
+ tpendingstate = record
+ nextverbositystr : shortstring;
+ nextlocalswitches : tlocalswitches;
+ nextverbosityfullswitch: longint;
+ nextcallingstr : shortstring;
+ nextmessagerecord : pmessagestaterecord;
+ verbosityfullswitched,
+ localswitcheschanged : boolean;
+ end;
+
+
+ var
+ { specified inputfile }
+ inputfilepath : string;
+ inputfilename : string;
+ { specified outputfile with -o parameter }
+ outputfilename : string;
+ outputprefix : pshortstring;
+ outputsuffix : pshortstring;
+ { specified with -FE or -FU }
+ outputexedir : TPathStr;
+ outputunitdir : TPathStr;
+ { specified with -FW and -Fw }
+ wpofeedbackinput,
+ wpofeedbackoutput : TPathStr;
+
+ { things specified with parameters }
+ paratarget : tsystem;
+ paratargetdbg : tdbg;
+ paratargetasm : tasm;
+ paralinkoptions : TCmdStr;
+ paradynamiclinker : string;
+ paraprintnodetree : byte;
+ parapreprocess : boolean;
+ printnodefile : text;
+
+ { typical cross compiling params}
+
+ { directory where the utils can be found (options -FD) }
+ utilsdirectory : TPathStr;
+ { targetname specific prefix used by these utils (options -XP<path>) }
+ utilsprefix : TCmdStr;
+ cshared : boolean; { pass --shared to ld to link C libs shared}
+ Dontlinkstdlibpath: Boolean; { Don't add std paths to linkpath}
+ rlinkpath : TCmdStr; { rpath-link linkdir override}
+ sysrootpath : TCmdStr; { target system root to search dyn linker }
+
+ { some flags for global compiler switches }
+ do_build,
+ do_release,
+ do_make : boolean;
+ { path for searching units, different paths can be seperated by ; }
+ exepath : TPathStr; { Path to ppc }
+ librarysearchpath,
+ unitsearchpath,
+ objectsearchpath,
+ includesearchpath,
+ frameworksearchpath : TSearchPathList;
+ autoloadunits : string;
+
+ { linking }
+ usegnubinutils : boolean;
+ forceforwardslash : boolean;
+ usewindowapi : boolean;
+ description : string;
+ SetPEFlagsSetExplicity,
+ ImageBaseSetExplicity,
+ MinStackSizeSetExplicity,
+ MaxStackSizeSetExplicity,
+ DescriptionSetExplicity : boolean;
+ dllversion : string;
+ dllmajor,
+ dllminor,
+ dllrevision : word; { revision only for netware }
+ { win pe }
+ peflags : longint;
+ minstacksize,
+ maxstacksize,
+ imagebase : puint;
+ UseDeffileForExports : boolean;
+ UseDeffileForExportsSetExplicitly : boolean;
+ GenerateImportSection,
+ GenerateImportSectionSetExplicitly,
+ RelocSection : boolean;
+ RelocSectionSetExplicitly : boolean;
+ LinkTypeSetExplicitly : boolean;
+
+ current_tokenpos, { position of the last token }
+ current_filepos : tfileposinfo; { current position }
+
+ nwscreenname : string;
+ nwthreadname : string;
+ nwcopyright : string;
+
+ codegenerror : boolean; { true if there is an error reported }
+
+ block_type : tblock_type; { type of currently parsed block }
+
+ compile_level : word;
+ exceptblockcounter : integer; { each except block gets a unique number check gotos }
+ current_exceptblock : integer; { the exceptblock number of the current block (0 if none) }
+ LinkLibraryAliases : TLinkStrMap;
+ LinkLibraryOrder : TLinkStrMap;
+
+ init_settings,
+ current_settings : tsettings;
+
+ pendingstate : tpendingstate;
+ { Memory sizes }
+ heapsize,
+ stacksize,
+ jmp_buf_size,
+ jmp_buf_align : longint;
+
+{$Ifdef EXTDEBUG}
+ { parameter switches }
+ debugstop : boolean;
+{$EndIf EXTDEBUG}
+ { windows / OS/2 application type }
+ apptype : tapptype;
+
+ features : tfeatures;
+
+ const
+ DLLsource : boolean = false;
+
+ { used to set all registers used for each global function
+ this should dramatically decrease the number of
+ recompilations needed PM }
+ simplify_ppu : boolean = true;
+
+ Inside_asm_statement : boolean = false;
+
+ global_unit_count : word = 0;
+
+ { for error info in pp.pas }
+ parser_current_file : string = '';
+
+{$if defined(m68k) or defined(arm)}
+ { PalmOS resources }
+ palmos_applicationname : string = 'FPC Application';
+ palmos_applicationid : string[4] = 'FPCA';
+{$endif defined(m68k) or defined(arm)}
+
+{$ifdef powerpc}
+ { default calling convention used on MorphOS }
+ syscall_convention : string = 'LEGACY';
+{$endif powerpc}
+
+ { default name of the C-style "main" procedure of the library/program }
+ { (this will be prefixed with the target_info.cprefix) }
+ defaultmainaliasname = 'main';
+ mainaliasname : string = defaultmainaliasname;
+
+ { by default no local variable trashing }
+ localvartrashing: longint = -1;
+ { actual values are defined in ncgutil.pas }
+ nroftrashvalues = 4;
+
+ const
+ default_settings : TSettings = (
+ alignment : (
+ procalign : 0;
+ loopalign : 0;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 0;
+ varalignmin : 0;
+ varalignmax : 0;
+ localalignmin : 0;
+ localalignmax : 0;
+ recordalignmin : 0;
+ recordalignmax : 0;
+ maxCrecordalign : 0;
+ );
+ globalswitches : [cs_check_unit_name,cs_link_static];
+ moduleswitches : [cs_extsyntax,cs_implicit_exceptions];
+ localswitches : [cs_check_io,cs_typed_const_writable,cs_pointermath];
+ modeswitches : fpcmodeswitches;
+ optimizerswitches : [];
+ genwpoptimizerswitches : [];
+ dowpoptimizerswitches : [];
+ debugswitches : [];
+
+ setalloc : 0;
+ packenum : 4;
+
+ packrecords : 0;
+ maxfpuregisters : 0;
+
+{ Note: GENERIC_CPU is sued together with generic subdirectory to
+ be able to compile some of the units without any real CPU.
+ This is used to generate a CPU independant PPUDUMP utility. PM }
+{$ifdef GENERIC_CPU}
+ cputype : cpu_none;
+ optimizecputype : cpu_none;
+ fputype : fpu_none;
+{$else not GENERIC_CPU}
+ {$ifdef i386}
+ cputype : cpu_Pentium;
+ optimizecputype : cpu_Pentium3;
+ fputype : fpu_x87;
+ {$endif i386}
+ {$ifdef m68k}
+ cputype : cpu_MC68020;
+ optimizecputype : cpu_MC68020;
+ fputype : fpu_soft;
+ {$endif m68k}
+ {$ifdef powerpc}
+ cputype : cpu_PPC604;
+ optimizecputype : cpu_ppc7400;
+ fputype : fpu_standard;
+ {$endif powerpc}
+ {$ifdef POWERPC64}
+ cputype : cpu_PPC970;
+ optimizecputype : cpu_ppc970;
+ fputype : fpu_standard;
+ {$endif POWERPC64}
+ {$ifdef sparc}
+ cputype : cpu_SPARC_V8;
+ optimizecputype : cpu_SPARC_V8;
+ fputype : fpu_hard;
+ {$endif sparc}
+ {$ifdef arm}
+ cputype : cpu_armv3;
+ optimizecputype : cpu_armv3;
+ fputype : fpu_fpa;
+ {$endif arm}
+ {$ifdef x86_64}
+ cputype : cpu_athlon64;
+ optimizecputype : cpu_athlon64;
+ fputype : fpu_sse64;
+ {$endif x86_64}
+ {$ifdef ia64}
+ cputype : cpu_itanium;
+ optimizecputype : cpu_itanium;
+ fputype : fpu_itanium;
+ {$endif ia64}
+ {$ifdef avr}
+ cputype : cpuinfo.cpu_avr5;
+ optimizecputype : cpuinfo.cpu_avr5;
+ fputype : fpu_none;
+ {$endif avr}
+ {$ifdef mips}
+ cputype : cpu_mips32;
+ optimizecputype : cpu_mips32;
+ fputype : fpu_mips2;
+ {$endif mips}
+{$endif not GENERIC_CPU}
+ asmmode : asmmode_standard;
+ interfacetype : it_interfacecom;
+ defproccall : pocall_default;
+ sourcecodepage : 28591;
+ minfpconstprec : s32real;
+
+ disabledircache : false;
+{$if defined(ARM) or defined(AVR)}
+ controllertype : ct_none;
+{$endif defined(ARM) or defined(AVR)}
+ pmessage : nil;
+ );
+
+ var
+ starttime : real;
+
+ function getdatestr:string;
+ function gettimestr:string;
+ function filetimestring( t : longint) : string;
+ function getrealtime : real;
+
+ procedure DefaultReplacements(var s:ansistring);
+
+ function Shell(const command:ansistring): longint;
+ function GetEnvPChar(const envname:string):pchar;
+ procedure FreeEnvPChar(p:pchar);
+
+ function is_number_float(d : double) : boolean;
+ { discern +0.0 and -0.0 }
+ function get_real_sign(r: bestreal): longint;
+
+ procedure InitGlobals;
+ procedure DoneGlobals;
+
+ function string2guid(const s: string; var GUID: TGUID): boolean;
+ function guid2string(const GUID: TGUID): string;
+
+ function SetAktProcCall(const s:string; var a:tproccalloption):boolean;
+ function Setabitype(const s:string;var a:tabi):boolean;
+ function Setcputype(const s:string;var a:tcputype):boolean;
+ function SetFpuType(const s:string;var a:tfputype):boolean;
+{$if defined(arm) or defined(avr)}
+ function SetControllerType(const s:string;var a:tcontrollertype):boolean;
+{$endif defined(arm) or defined(avr)}
+ function UpdateAlignmentStr(s:string;var a:talignmentinfo):boolean;
+ function UpdateOptimizerStr(s:string;var a:toptimizerswitches):boolean;
+ function UpdateWpoStr(s: string; var a: twpoptimizerswitches): boolean;
+ function UpdateDebugStr(s:string;var a:tdebugswitches):boolean;
+ function IncludeFeature(const s : string) : boolean;
+ function SetMinFPConstPrec(const s: string; var a: tfloattype) : boolean;
+
+ {# Routine to get the required alignment for size of data, which will
+ be placed in bss segment, according to the current alignment requirements }
+ function var_align(want_align: longint): shortint;
+ function var_align_size(siz: longint): shortint;
+ {# Routine to get the required alignment for size of data, which will
+ be placed in data/const segment, according to the current alignment requirements }
+ function const_align(want_align: longint): shortint;
+ function const_align_size(siz: longint): shortint;
+{$ifdef ARM}
+ function is_double_hilo_swapped: boolean;{$ifdef USEINLINE}inline;{$endif}
+{$endif ARM}
+ function floating_point_range_check_error : boolean;
+
+implementation
+
+ uses
+{$ifdef macos}
+ macutils,
+{$endif}
+{$ifdef mswindows}
+{$ifdef VER2_4}
+ cwindirs,
+{$else VER2_4}
+ windirs,
+{$endif VER2_4}
+{$endif}
+ comphook;
+
+{****************************************************************************
+ TLinkStrMap
+****************************************************************************}
+
+ Constructor TLinkStrMap.create;
+ begin
+ inherited;
+ itemcnt:=0;
+ end;
+
+
+ procedure TLinkStrMap.Add(key:ansistring;value:AnsiString='';weight:longint=LinkMapWeightDefault);
+ begin
+ if lookup(key)<>-1 Then
+ exit;
+ if itemcnt<=length(fmap) Then
+ setlength(fmap,itemcnt+10);
+ fmap[itemcnt].key:=key;
+ fmap[itemcnt].value:=value;
+ fmap[itemcnt].weight:=weight;
+ inc(itemcnt);
+ end;
+
+
+ function TLinkStrMap.AddDep(keyvalue:String):boolean;
+ var
+ i : Longint;
+ begin
+ AddDep:=false;
+ i:=pos('=',keyvalue);
+ if i=0 then
+ exit;
+ Add(Copy(KeyValue,1,i-1),Copy(KeyValue,i+1,length(KeyValue)-i));
+ AddDep:=True;
+ end;
+
+
+ function TLinkStrMap.AddWeight(keyvalue:String):boolean;
+ var
+ i,j : Longint;
+ Code : Word;
+ s : AnsiString;
+ begin
+ AddWeight:=false;
+ i:=pos('=',keyvalue);
+ if i=0 then
+ exit;
+ s:=Copy(KeyValue,i+1,length(KeyValue)-i);
+ val(s,j,code);
+ if code=0 Then
+ begin
+ Add(Copy(KeyValue,1,i-1),'',j);
+ AddWeight:=True;
+ end;
+ end;
+
+
+ procedure TLinkStrMap.addseries(keys:AnsiString;weight:longint);
+ var
+ i,j,k : longint;
+ begin
+ k:=length(keys);
+ i:=1;
+ while i<=k do
+ begin
+ j:=i;
+ while (i<=k) and (keys[i]<>',') do
+ inc(i);
+ add(copy(keys,j,i-j),'',weight);
+ inc(i);
+ end;
+ end;
+
+ procedure TLinkStrMap.SetValue(Key:Ansistring;weight:Integer);
+ var
+ j : longint;
+ begin
+ j:=lookup(key);
+ if j<>-1 then
+ fmap[j].weight:=weight;
+ end;
+
+
+ function TLinkStrMap.find(key:Ansistring):Ansistring;
+ var
+ j : longint;
+ begin
+ find:='';
+ j:=lookup(key);
+ if j<>-1 then
+ find:=fmap[j].value;
+ end;
+
+
+ function TLinkStrMap.lookup(key:Ansistring):longint;
+ var
+ i : longint;
+ begin
+ lookup:=-1;
+ i:=0;
+ while (i<itemcnt) and (fmap[i].key<>key) do
+ inc(i);
+ if i<>itemcnt then
+ lookup:=i;
+ end;
+
+
+ procedure TLinkStrMap.SortOnWeight;
+ var
+ i, j : longint;
+ m : TLinkRec;
+ begin
+ if itemcnt <2 then exit;
+ for i:=0 to itemcnt-1 do
+ for j:=i+1 to itemcnt-1 do
+ begin
+ if fmap[i].weight>fmap[j].weight Then
+ begin
+ m:=fmap[i];
+ fmap[i]:=fmap[j];
+ fmap[j]:=m;
+ end;
+ end;
+ end;
+
+
+ function TLinkStrMap.getlinkrec(i:longint):TLinkRec;
+ begin
+ result:=fmap[i];
+ end;
+
+
+ procedure TLinkStrMap.Expand(Src:TCmdStrList;Dest:TLinkStrMap);
+ // expands every thing in Src to Dest for linkorder purposes.
+ var
+ r : longint;
+ LibN : TCmdStr;
+ begin
+ while not src.empty do
+ begin
+ LibN:=src.getfirst;
+ r:=lookup (LibN);
+ if r=-1 then
+ dest.add(LibN)
+ else
+ dest.addseries(fmap[r].value);
+ end;
+ end;
+
+ procedure TLinkStrMap.UpdateWeights(Weightmap:TLinkStrMap);
+ var
+ l,r : longint;
+ begin
+ for l := 0 to itemcnt-1 do
+ begin
+ r:=weightmap.lookup (fmap[l].key);
+ if r<>-1 then
+ fmap[l].weight:=weightmap[r].weight;
+ end;
+ end;
+
+
+{****************************************************************************
+ Time Handling
+****************************************************************************}
+
+ Function L0(l:longint):string;
+ {
+ return the string of value l, if l<10 then insert a zero, so
+ the string is always at least 2 chars '01','02',etc
+ }
+ var
+ s : string;
+ begin
+ Str(l,s);
+ if l<10 then
+ s:='0'+s;
+ L0:=s;
+ end;
+
+
+ function gettimestr:string;
+ {
+ get the current time in a string HH:MM:SS
+ }
+ var
+ hour,min,sec,hsec : word;
+ begin
+ DecodeTime(Time,hour,min,sec,hsec);
+ gettimestr:=L0(Hour)+':'+L0(min)+':'+L0(sec);
+ end;
+
+
+ function getdatestr:string;
+ {
+ get the current date in a string YY/MM/DD
+ }
+ var
+ Year,Month,Day: Word;
+ begin
+ DecodeDate(Date,year,month,day);
+ getdatestr:=L0(Year)+'/'+L0(Month)+'/'+L0(Day);
+ end;
+
+
+ function filetimestring( t : longint) : string;
+ {
+ convert dos datetime t to a string YY/MM/DD HH:MM:SS
+ }
+ var
+ DT : TDateTime;
+ hsec : word;
+ Year,Month,Day: Word;
+ hour,min,sec : word;
+ begin
+ if t=-1 then
+ begin
+ Result := 'Not Found';
+ exit;
+ end;
+ DT := FileDateToDateTime(t);
+ DecodeTime(DT,hour,min,sec,hsec);
+ DecodeDate(DT,year,month,day);
+ Result := L0(Year)+'/'+L0(Month)+'/'+L0(Day)+' '+L0(Hour)+':'+L0(min)+':'+L0(sec);
+ end;
+
+
+ function getrealtime : real;
+ var
+ h,m,s,s1000 : word;
+ begin
+ DecodeTime(Time,h,m,s,s1000);
+ result:=h*3600.0+m*60.0+s+s1000/1000.0;
+ end;
+
+{****************************************************************************
+ Default Macro Handling
+****************************************************************************}
+
+
+ procedure DefaultReplacements(var s:ansistring);
+{$ifdef mswindows}
+ procedure ReplaceSpecialFolder(const MacroName: string; const ID: integer);
+ begin
+ // Only try to receive the special folders (and thus dynamically
+ // load shfolder.dll) when that's needed.
+ if pos(MacroName,s)>0 then
+ Replace(s,MacroName,GetWindowsSpecialDir(ID));
+ end;
+
+{$endif mswindows}
+ var
+ envstr: string;
+ envvalue: pchar;
+ i: integer;
+ begin
+ { Replace some macros }
+ Replace(s,'$FPCVERSION',version_string);
+ Replace(s,'$FPCFULLVERSION',full_version_string);
+ Replace(s,'$FPCDATE',date_string);
+ Replace(s,'$FPCCPU',target_cpu_string);
+ Replace(s,'$FPCOS',target_os_string);
+ if (tf_use_8_3 in Source_Info.Flags) or
+ (tf_use_8_3 in Target_Info.Flags) then
+ Replace(s,'$FPCTARGET',target_os_string)
+ else
+ Replace(s,'$FPCTARGET',target_full_string);
+{$ifdef mswindows}
+ ReplaceSpecialFolder('$LOCAL_APPDATA',CSIDL_LOCAL_APPDATA);
+ ReplaceSpecialFolder('$APPDATA',CSIDL_APPDATA);
+ ReplaceSpecialFolder('$COMMON_APPDATA',CSIDL_COMMON_APPDATA);
+ ReplaceSpecialFolder('$PERSONAL',CSIDL_PERSONAL);
+ ReplaceSpecialFolder('$PROGRAM_FILES',CSIDL_PROGRAM_FILES);
+ ReplaceSpecialFolder('$PROGRAM_FILES_COMMON',CSIDL_PROGRAM_FILES_COMMON);
+ ReplaceSpecialFolder('$PROFILE',CSIDL_PROFILE);
+{$endif mswindows}
+ { Replace environment variables between dollar signs }
+ i := pos('$',s);
+ while i>0 do
+ begin
+ envstr:=copy(s,i+1,length(s)-i);
+ i:=pos('$',envstr);
+ if i>0 then
+ begin
+ envstr := copy(envstr,1,i-1);
+ envvalue := GetEnvPChar(envstr);
+ if assigned(envvalue) then
+ begin
+ Replace(s,'$'+envstr+'$',envvalue);
+ // Look if there is another env.var in the string
+ i:=pos('$',s);
+ end
+ else
+ // if the env.var is not set, do not replace the env.variable
+ // and stop looking for more env.var within the string
+ i := 0;
+ FreeEnvPChar(envvalue);
+ end;
+ end;
+ end;
+
+
+ {****************************************************************************
+ OS Dependent things
+ ****************************************************************************}
+
+ function GetEnvPChar(const envname:string):pchar;
+ {$ifdef win32}
+ var
+ s : string;
+ i,len : longint;
+ hp,p,p2 : pchar;
+ {$endif}
+ begin
+ {$ifdef hasunix}
+ GetEnvPchar:=BaseUnix.fpGetEnv(envname);
+ {$define GETENVOK}
+ {$endif}
+ {$ifdef win32}
+ GetEnvPchar:=nil;
+ p:=GetEnvironmentStrings;
+ hp:=p;
+ while hp^<>#0 do
+ begin
+ s:=strpas(hp);
+ i:=pos('=',s);
+ len:=strlen(hp);
+ if upper(copy(s,1,i-1))=upper(envname) then
+ begin
+ GetMem(p2,len-length(envname));
+ Move(hp[i],p2^,len-length(envname));
+ GetEnvPchar:=p2;
+ break;
+ end;
+ { next string entry}
+ hp:=hp+len+1;
+ end;
+ FreeEnvironmentStrings(p);
+ {$define GETENVOK}
+ {$endif}
+ {$ifdef os2}
+ GetEnvPChar := Dos.GetEnvPChar (EnvName);
+ {$define GETENVOK}
+ {$endif}
+ {$ifdef GETENVOK}
+ {$undef GETENVOK}
+ {$else}
+ GetEnvPchar:=StrPNew(GetEnvironmentVariable(envname));
+ {$endif}
+ end;
+
+
+ procedure FreeEnvPChar(p:pchar);
+ begin
+ {$ifndef hasunix}
+ {$ifndef os2}
+ freemem(p);
+ {$endif}
+ {$endif}
+ end;
+
+{$if defined(MORPHOS) or defined(AMIGA)}
+ {$define AMIGASHELL}
+{$endif}
+
+ function Shell(const command:ansistring): longint;
+ { This is already defined in the linux.ppu for linux, need for the *
+ expansion under linux }
+{$ifdef hasunix}
+ begin
+ result := Unix.fpsystem(command);
+ end;
+{$else hasunix}
+ {$ifdef amigashell}
+ begin
+ result := ExecuteProcess('',command);
+ end;
+ {$else amigashell}
+ var
+ comspec : string;
+ begin
+ comspec:=GetEnvironmentVariable('COMSPEC');
+ result := ExecuteProcess(comspec,' /C '+command);
+ end;
+ {$endif amigashell}
+{$endif hasunix}
+
+{$UNDEF AMIGASHELL}
+ function is_number_float(d : double) : boolean;
+ var
+ bytearray : array[0..7] of byte;
+ begin
+ move(d,bytearray,8);
+ { only 1.1 save, 1.0.x will use always little endian }
+{$ifdef FPC_BIG_ENDIAN}
+ result:=((bytearray[0] and $7f)<>$7f) or ((bytearray[1] and $f0)<>$f0);
+{$else FPC_BIG_ENDIAN}
+ result:=((bytearray[7] and $7f)<>$7f) or ((bytearray[6] and $f0)<>$f0);
+{$endif FPC_BIG_ENDIAN}
+ end;
+
+ function get_real_sign(r: bestreal): longint;
+ var
+ p: pbyte;
+ begin
+ p := pbyte(@r);
+{$ifdef CPU_ARM}
+ inc(p,4);
+{$else}
+{$ifdef FPC_LITTLE_ENDIAN}
+ inc(p,sizeof(r)-1);
+{$endif}
+{$endif}
+ if (p^ and $80) = 0 then
+ result := 1
+ else
+ result := -1;
+ end;
+
+ function convertdoublerec(d : tdoublerec) : tdoublerec;{$ifdef USEINLINE}inline;{$endif}
+{$ifdef CPUARM}
+ var
+ i : longint;
+ begin
+ for i:=0 to 3 do
+ begin
+ result.bytes[i+4]:=d.bytes[i];
+ result.bytes[i]:=d.bytes[i+4];
+ end;
+{$else CPUARM}
+ begin
+ result:=d;
+{$endif CPUARM}
+ end;
+
+
+ { '('D1:'00000000-'D2:'0000-'D3:'0000-'D4:'0000-000000000000)' }
+ function string2guid(const s: string; var GUID: TGUID): boolean;
+ function ishexstr(const hs: string): boolean;
+ var
+ i: integer;
+ begin
+ ishexstr:=false;
+ for i:=1 to Length(hs) do begin
+ if not (hs[i] in ['0'..'9','A'..'F','a'..'f']) then
+ exit;
+ end;
+ ishexstr:=true;
+ end;
+ function hexstr2longint(const hexs: string): longint;
+ var
+ i: integer;
+ rl: longint;
+ begin
+ rl:=0;
+ for i:=1 to length(hexs) do begin
+ rl:=rl shl 4;
+ case hexs[i] of
+ '0'..'9' : inc(rl,ord(hexs[i])-ord('0'));
+ 'A'..'F' : inc(rl,ord(hexs[i])-ord('A')+10);
+ 'a'..'f' : inc(rl,ord(hexs[i])-ord('a')+10);
+ end
+ end;
+ hexstr2longint:=rl;
+ end;
+ var
+ i: integer;
+ begin
+ if (Length(s)=38) and (s[1]='{') and (s[38]='}') and
+ (s[10]='-') and (s[15]='-') and (s[20]='-') and (s[25]='-') and
+ ishexstr(copy(s,2,8)) and ishexstr(copy(s,11,4)) and
+ ishexstr(copy(s,16,4)) and ishexstr(copy(s,21,4)) and
+ ishexstr(copy(s,26,12)) then begin
+ GUID.D1:=dword(hexstr2longint(copy(s,2,8)));
+ { these values are arealdy in the correct range (4 chars = word) }
+ GUID.D2:=word(hexstr2longint(copy(s,11,4)));
+ GUID.D3:=word(hexstr2longint(copy(s,16,4)));
+ for i:=0 to 1 do
+ GUID.D4[i]:=byte(hexstr2longint(copy(s,21+i*2,2)));
+ for i:=2 to 7 do
+ GUID.D4[i]:=byte(hexstr2longint(copy(s,22+i*2,2)));
+ string2guid:=true;
+ end
+ else if (length(s)=0) then
+ begin
+ FillChar(GUID,SizeOf(GUID),0);
+ string2guid:=true;
+ end
+ else
+ string2guid:=false;
+ end;
+
+
+ function guid2string(const GUID: TGUID): string;
+
+ begin
+ guid2string:=
+ '{'+hexstr(GUID.D1,8)+
+ '-'+hexstr(GUID.D2,4)+
+ '-'+hexstr(GUID.D3,4)+
+ '-'+hexstr(GUID.D4[0],2)+hexstr(GUID.D4[1],2)+
+ '-'+hexstr(GUID.D4[2],2)+hexstr(GUID.D4[3],2)+
+ hexstr(GUID.D4[4],2)+hexstr(GUID.D4[5],2)+
+ hexstr(GUID.D4[6],2)+hexstr(GUID.D4[7],2)+
+ '}';
+ end;
+
+
+ function SetAktProcCall(const s:string; var a:tproccalloption):boolean;
+ const
+ DefProcCallName : array[tproccalloption] of string[12] = ('',
+ 'CDECL',
+ 'CPPDECL',
+ 'FAR16',
+ 'OLDFPCCALL',
+ '', { internproc }
+ '', { syscall }
+ 'PASCAL',
+ 'REGISTER',
+ 'SAFECALL',
+ 'STDCALL',
+ 'SOFTFLOAT',
+ 'MWPASCAL',
+ 'INTERRUPT'
+ );
+ var
+ t : tproccalloption;
+ hs : string;
+ begin
+ result:=false;
+ if (s = '') then
+ exit;
+ hs:=upper(s);
+ if (hs = 'DEFAULT') then
+ begin
+ a := pocall_default;
+ result := true;
+ exit;
+ end;
+ for t:=low(tproccalloption) to high(tproccalloption) do
+ if DefProcCallName[t]=hs then
+ begin
+ a:=t;
+ result:=true;
+ break;
+ end;
+ end;
+
+
+ function Setabitype(const s:string;var a:tabi):boolean;
+ var
+ t : tabi;
+ hs : string;
+ begin
+ result:=false;
+ hs:=Upper(s);
+ for t:=low(t) to high(t) do
+ if abi2str[t]=hs then
+ begin
+ a:=t;
+ result:=true;
+ break;
+ end;
+ end;
+
+
+ function Setcputype(const s:string;var a:tcputype):boolean;
+ var
+ t : tcputype;
+ hs : string;
+ begin
+ result:=false;
+ hs:=Upper(s);
+ for t:=low(tcputype) to high(tcputype) do
+ if cputypestr[t]=hs then
+ begin
+ a:=t;
+ result:=true;
+ break;
+ end;
+ end;
+
+
+ function SetFpuType(const s:string;var a:tfputype):boolean;
+ var
+ t : tfputype;
+ begin
+ result:=false;
+ for t:=low(tfputype) to high(tfputype) do
+ if fputypestr[t]=s then
+ begin
+ a:=t;
+ result:=true;
+ break;
+ end;
+ end;
+
+
+{$if defined(arm) or defined(avr)}
+ function SetControllerType(const s:string;var a:tcontrollertype):boolean;
+ var
+ t : tcontrollertype;
+ hs : string;
+ begin
+ result:=false;
+ hs:=Upper(s);
+ for t:=low(tcontrollertype) to high(tcontrollertype) do
+ if embedded_controllers[t].controllertypestr=hs then
+ begin
+ a:=t;
+ result:=true;
+ break;
+ end;
+ end;
+{$endif defined(arm) or defined(avr)}
+
+
+ function UpdateAlignmentStr(s:string;var a:talignmentinfo):boolean;
+ var
+ tok : string;
+ vstr : string;
+ l : longint;
+ code : integer;
+ b : talignmentinfo;
+ begin
+ UpdateAlignmentStr:=true;
+ uppervar(s);
+ fillchar(b,sizeof(b),0);
+ repeat
+ tok:=GetToken(s,'=');
+ if tok='' then
+ break;
+ vstr:=GetToken(s,',');
+ val(vstr,l,code);
+ if tok='PROC' then
+ b.procalign:=l
+ else if tok='JUMP' then
+ b.jumpalign:=l
+ else if tok='LOOP' then
+ b.loopalign:=l
+ else if tok='CONSTMIN' then
+ begin
+ b.constalignmin:=l;
+ if l>b.constalignmax then
+ b.constalignmax:=l;
+ end
+ else if tok='CONSTMAX' then
+ b.constalignmax:=l
+ else if tok='VARMIN' then
+ begin
+ b.varalignmin:=l;
+ if l>b.varalignmax then
+ b.varalignmax:=l;
+ end
+ else if tok='VARMAX' then
+ b.varalignmax:=l
+ else if tok='LOCALMIN' then
+ begin
+ b.localalignmin:=l;
+ if l>b.localalignmax then
+ b.localalignmax:=l;
+ end
+ else if tok='LOCALMAX' then
+ b.localalignmax:=l
+ else if tok='RECORDMIN' then
+ begin
+ b.recordalignmin:=l;
+ if l>b.recordalignmax then
+ b.recordalignmax:=l;
+ end
+ else if tok='RECORDMAX' then
+ b.recordalignmax:=l
+ else { Error }
+ UpdateAlignmentStr:=false;
+ until false;
+ Result:=Result and UpdateAlignment(a,b);
+ end;
+
+
+ function UpdateOptimizerStr(s:string;var a:toptimizerswitches):boolean;
+ var
+ tok : string;
+ doset,
+ found : boolean;
+ opt : toptimizerswitch;
+ begin
+ result:=true;
+ uppervar(s);
+ repeat
+ tok:=GetToken(s,',');
+ if tok='' then
+ break;
+ if Copy(tok,1,2)='NO' then
+ begin
+ delete(tok,1,2);
+ doset:=false;
+ end
+ else
+ doset:=true;
+ found:=false;
+ for opt:=low(toptimizerswitch) to high(toptimizerswitch) do
+ begin
+ if OptimizerSwitchStr[opt]=tok then
+ begin
+ found:=true;
+ break;
+ end;
+ end;
+ if found then
+ begin
+ if doset then
+ include(a,opt)
+ else
+ exclude(a,opt);
+ end
+ else
+ result:=false;
+ until false;
+ end;
+
+
+ function UpdateWpoStr(s: string; var a: twpoptimizerswitches): boolean;
+ var
+ tok : string;
+ doset,
+ found : boolean;
+ opt : twpoptimizerswitch;
+ begin
+ result:=true;
+ uppervar(s);
+ repeat
+ tok:=GetToken(s,',');
+ if tok='' then
+ break;
+ if Copy(tok,1,2)='NO' then
+ begin
+ delete(tok,1,2);
+ doset:=false;
+ end
+ else
+ doset:=true;
+ found:=false;
+ if (tok = 'ALL') then
+ begin
+ for opt:=low(twpoptimizerswitch) to high(twpoptimizerswitch) do
+ if doset then
+ include(a,opt)
+ else
+ exclude(a,opt);
+ end
+ else
+ begin
+ for opt:=low(twpoptimizerswitch) to high(twpoptimizerswitch) do
+ begin
+ if WPOptimizerSwitchStr[opt]=tok then
+ begin
+ found:=true;
+ break;
+ end;
+ end;
+ if found then
+ begin
+ if doset then
+ include(a,opt)
+ else
+ exclude(a,opt);
+ end
+ else
+ result:=false;
+ end;
+ until false;
+ end;
+
+
+ function UpdateDebugStr(s:string;var a:tdebugswitches):boolean;
+ var
+ tok : string;
+ doset,
+ found : boolean;
+ opt : tdebugswitch;
+ begin
+ result:=true;
+ uppervar(s);
+ repeat
+ tok:=GetToken(s,',');
+ if tok='' then
+ break;
+ if Copy(tok,1,2)='NO' then
+ begin
+ delete(tok,1,2);
+ doset:=false;
+ end
+ else
+ doset:=true;
+ found:=false;
+ for opt:=low(tdebugswitch) to high(tdebugswitch) do
+ begin
+ if DebugSwitchStr[opt]=tok then
+ begin
+ found:=true;
+ break;
+ end;
+ end;
+ if found then
+ begin
+ if doset then
+ include(a,opt)
+ else
+ exclude(a,opt);
+ end
+ else
+ result:=false;
+ until false;
+ end;
+
+
+ function IncludeFeature(const s : string) : boolean;
+ var
+ i : tfeature;
+ begin
+ result:=true;
+ for i:=low(tfeature) to high(tfeature) do
+ if s=featurestr[i] then
+ begin
+ include(features,i);
+ exit;
+ end;
+ result:=false;
+ end;
+
+
+ function SetMinFPConstPrec(const s: string; var a: tfloattype) : boolean;
+ var
+ value, error: longint;
+ begin
+ if (upper(s)='DEFAULT') then
+ begin
+ a:=s32real;
+ result:=true;
+ exit;
+ end;
+ result:=false;
+ val(s,value,error);
+ if (error<>0) then
+ exit;
+ case value of
+ 32: a:=s32real;
+ 64: a:=s64real;
+ { adding support for 80 bit here is tricky, since we can't really }
+ { check whether the target cpu+OS actually supports it }
+ else
+ exit;
+ end;
+ result:=true;
+ end;
+
+
+ function var_align(want_align: longint): shortint;
+ begin
+ var_align := used_align(want_align,current_settings.alignment.varalignmin,current_settings.alignment.varalignmax);
+ end;
+
+
+ function var_align_size(siz: longint): shortint;
+ begin
+ siz := size_2_align(siz);
+ var_align_size := var_align(siz);
+ end;
+
+
+ function const_align(want_align: longint): shortint;
+ begin
+ const_align := used_align(want_align,current_settings.alignment.constalignmin,current_settings.alignment.constalignmax);
+ end;
+
+
+ function const_align_size(siz: longint): shortint;
+ begin
+ siz := size_2_align(siz);
+ const_align_size := const_align(siz);
+ end;
+
+
+{$ifdef ARM}
+ function is_double_hilo_swapped: boolean;{$ifdef USEINLINE}inline;{$endif}
+ begin
+ result := (current_settings.fputype in [fpu_fpa,fpu_fpa10,fpu_fpa11]) and
+ not(cs_fp_emulation in current_settings.moduleswitches);
+{$ifdef FPC_DOUBLE_HILO_SWAPPED}
+ { inverse result if compiler was compiled with swapped hilo already }
+ result := not result;
+{$endif FPC_DOUBLE_HILO_SWAPPED}
+ end;
+{$endif ARM}
+
+
+ function floating_point_range_check_error : boolean;
+ begin
+ result:=cs_ieee_errors in current_settings.localswitches;
+ end;
+
+{****************************************************************************
+ Init
+****************************************************************************}
+
+{$ifdef unix}
+ {$define need_path_search}
+{$endif unix}
+{$ifdef os2}
+ {$define need_path_search}
+{$endif os2}
+{$ifdef macos}
+ {$define need_path_search}
+{$endif macos}
+
+ procedure get_exepath;
+ var
+ localExepath : TCmdStr;
+ exeName:TCmdStr;
+{$ifdef need_path_search}
+ hs1 : TPathStr;
+{$endif need_path_search}
+ begin
+ localexepath:=GetEnvironmentVariable('PPC_EXEC_PATH');
+ if localexepath='' then
+ begin
+ exeName := FixFileName(system.paramstr(0));
+ localexepath := ExtractFilePath(exeName);
+ end;
+{$ifdef need_path_search}
+ if localexepath='' then
+ begin
+ hs1 := ExtractFileName(exeName);
+ ChangeFileExt(hs1,source_info.exeext);
+{$ifdef macos}
+ FindFile(hs1,GetEnvironmentVariable('Commands'),false,localExepath);
+{$else macos}
+ FindFile(hs1,GetEnvironmentVariable('PATH'),false,localExepath);
+{$endif macos}
+ localExepath:=ExtractFilePath(localExepath);
+ end;
+{$endif need_path_search}
+ exepath:=FixPath(localExepath,false);
+ end;
+
+
+
+ procedure DoneGlobals;
+ begin
+ librarysearchpath.Free;
+ unitsearchpath.Free;
+ objectsearchpath.Free;
+ includesearchpath.Free;
+ frameworksearchpath.Free;
+ LinkLibraryAliases.Free;
+ LinkLibraryOrder.Free;
+ end;
+
+ procedure InitGlobals;
+ begin
+ get_exepath;
+
+ { reset globals }
+ do_build:=false;
+ do_release:=false;
+ do_make:=true;
+ compile_level:=0;
+ codegenerror:=false;
+ DLLsource:=false;
+ paratarget:=system_none;
+ paratargetasm:=as_none;
+ paratargetdbg:=dbg_none;
+
+ { Output }
+ OutputFileName:='';
+ OutputPrefix:=Nil;
+ OutputSuffix:=Nil;
+
+ OutputExeDir:='';
+ OutputUnitDir:='';
+
+ { Utils directory }
+ utilsdirectory:='';
+ utilsprefix:='';
+ cshared:=false;
+ rlinkpath:='';
+ sysrootpath:='';
+
+ { Search Paths }
+ librarysearchpath:=TSearchPathList.Create;
+ unitsearchpath:=TSearchPathList.Create;
+ includesearchpath:=TSearchPathList.Create;
+ objectsearchpath:=TSearchPathList.Create;
+ frameworksearchpath:=TSearchPathList.Create;
+
+ { Def file }
+ usewindowapi:=false;
+ description:='Compiled by FPC '+version_string+' - '+target_cpu_string;
+ DescriptionSetExplicity:=false;
+ SetPEFlagsSetExplicity:=false;
+ ImageBaseSetExplicity:=false;
+ MinStackSizeSetExplicity:=false;
+ MaxStackSizeSetExplicity:=false;
+
+ dllversion:='';
+ dllmajor:=1;
+ dllminor:=0;
+ dllrevision:=0;
+ nwscreenname := '';
+ nwthreadname := '';
+ nwcopyright := '';
+ UseDeffileForExports:=false;
+ UseDeffileForExportsSetExplicitly:=false;
+ GenerateImportSection:=false;
+ RelocSection:=false;
+ RelocSectionSetExplicitly:=false;
+ LinkTypeSetExplicitly:=false;
+ { memory sizes, will be overridden by parameter or default for target
+ in options or init_parser }
+ stacksize:=0;
+ { not initialized yet }
+ jmp_buf_size:=-1;
+ apptype:=app_cui;
+
+ { Init values }
+ init_settings:=default_settings;
+ if init_settings.optimizecputype=cpu_none then
+ init_settings.optimizecputype:=init_settings.cputype;
+
+ LinkLibraryAliases :=TLinkStrMap.Create;
+ LinkLibraryOrder :=TLinkStrMap.Create;
+
+ { enable all features by default }
+ features:=[low(Tfeature)..high(Tfeature)];
+ end;
+
+end.
diff --git a/closures/compiler/globtype.pas b/closures/compiler/globtype.pas
new file mode 100644
index 0000000000..ed6f69d564
--- /dev/null
+++ b/closures/compiler/globtype.pas
@@ -0,0 +1,563 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl, Pierre Muller
+
+ Global types
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ ****************************************************************************
+}
+unit globtype;
+
+{$i fpcdefs.inc}
+
+interface
+
+ const
+ maxidlen = 127;
+
+ type
+ { TCmdStr is used to pass command line parameters to an external program to be
+ executed from the FPC application. In some circomstances, this can be more
+ than 255 characters. That's why using Ansi Strings}
+ TCmdStr = AnsiString;
+ TPathStr = AnsiString;
+
+ { Integer type corresponding to pointer size }
+{$ifdef cpu64bitaddr}
+ PUint = qword;
+ PInt = int64;
+{$endif cpu64bitaddr}
+{$ifdef cpu32bitaddr}
+ PUint = cardinal;
+ PInt = longint;
+{$endif cpu32bitaddr}
+{$ifdef cpu16bitaddr}
+ PUint = word;
+ PInt = Smallint;
+{$endif cpu16bitaddr}
+
+ { Natural integer register type and size for the target machine }
+{$ifdef cpu64bitalu}
+ AWord = qword;
+ AInt = Int64;
+
+ Const
+ AIntBits = 64;
+{$endif cpu64bitalu}
+{$ifdef cpu32bitalu}
+ AWord = longword;
+ AInt = longint;
+
+ Const
+ AIntBits = 32;
+{$endif cpu32bitalu}
+{$ifdef cpu16bitalu}
+ AWord = Word;
+ AInt = Smallint;
+
+ Const
+ AIntBits = 16;
+{$endif cpu16bitalu}
+{$ifdef cpu8bitalu}
+ AWord = Byte;
+ AInt = Shortint;
+
+ Const
+ AIntBits = 8;
+{$endif cpu8bitalu}
+
+ Type
+ PAWord = ^AWord;
+ PAInt = ^AInt;
+
+ { target cpu specific type used to store data sizes }
+ ASizeInt = PInt;
+ ASizeUInt = PUInt;
+
+ { type used for handling constants etc. in the code generator }
+ TCGInt = Int64;
+
+ { This must be an ordinal type with the same size as a pointer
+ Note: Must be unsigned! Otherwise, ugly code like
+ pointer(-1) will result in a pointer with the value
+ $fffffffffffffff on a 32bit machine if the compiler uses
+ int64 constants internally (JM) }
+ TConstPtrUInt = AWord;
+
+ { Use a variant record to be sure that the array if aligned correctly }
+ tdoublerec=record
+ case byte of
+ 0 : (bytes:array[0..7] of byte);
+ 1 : (value:double);
+ end;
+ textendedrec=record
+ case byte of
+ 0 : (bytes:array[0..9] of byte);
+ 1 : (value:extended);
+ end;
+
+ pconstset = ^tconstset;
+ tconstset = set of 0..255;
+
+ { Switches which can be changed locally }
+ tlocalswitch = (cs_localnone,
+ { codegen }
+ cs_check_overflow,cs_check_range,cs_check_object,
+ cs_check_io,cs_check_stack,
+ cs_checkpointer,cs_check_ordinal_size,
+ cs_generate_stackframes,cs_do_assertion,cs_generate_rtti,
+ cs_full_boolean_eval,cs_typed_const_writable,cs_allow_enum_calc,
+ cs_do_inline,cs_fpu_fwait,cs_ieee_errors,
+ { mmx }
+ cs_mmx,cs_mmx_saturation,
+ { parser }
+ cs_typed_addresses,cs_strict_var_strings,cs_ansistrings,cs_bitpacking,
+ cs_varpropsetter,cs_scopedenums,cs_pointermath,
+ { macpas specific}
+ cs_external_var, cs_externally_visible
+ );
+ tlocalswitches = set of tlocalswitch;
+
+ { Switches which can be changed only at the beginning of a new module }
+ tmoduleswitch = (cs_modulenone,
+ { parser }
+ cs_fp_emulation,cs_extsyntax,cs_openstring,
+ { support }
+ cs_support_goto,cs_support_macro,
+ cs_support_c_operators,
+ { generation }
+ cs_profile,cs_debuginfo,cs_compilesystem,
+ cs_lineinfo,cs_implicit_exceptions,cs_explicit_codepage,
+ { linking }
+ cs_create_smart,cs_create_dynamic,cs_create_pic,
+ { browser switches are back }
+ cs_browser,cs_local_browser,
+ { target specific }
+ cs_executable_stack
+ );
+ tmoduleswitches = set of tmoduleswitch;
+
+ { Switches which can be changed only for a whole program/compilation,
+ mostly set with commandline }
+ tglobalswitch = (cs_globalnone,
+ { parameter switches }
+ cs_check_unit_name,cs_constructor_name,cs_support_exceptions,
+ cs_support_c_objectivepas,
+ { units }
+ cs_load_objpas_unit,
+ cs_load_gpc_unit,
+ cs_load_fpcylix_unit,
+ cs_support_vectors,
+ { debuginfo }
+ cs_use_heaptrc,cs_use_lineinfo,
+ cs_gdb_valgrind,cs_no_regalloc,cs_stabs_preservecase,
+ { assembling }
+ cs_asm_leave,cs_asm_extern,cs_asm_pipe,cs_asm_source,
+ cs_asm_regalloc,cs_asm_tempalloc,cs_asm_nodes,
+ { linking }
+ cs_link_nolink,cs_link_static,cs_link_smart,cs_link_shared,cs_link_deffile,
+ cs_link_strip,cs_link_staticflag,cs_link_on_target,cs_link_extern,cs_link_opt_vtable,
+ cs_link_opt_used_sections,cs_link_separate_dbg_file,
+ cs_link_map,cs_link_pthread,cs_link_no_default_lib_order,
+ cs_link_native
+ );
+ tglobalswitches = set of tglobalswitch;
+
+ { global switches specific to debug information }
+ tdebugswitch = (ds_none,
+ { enable set support in dwarf debug info, breaks gdb versions }
+ { without support for that tag (they refuse to parse the rest }
+ { of the debug information) }
+ ds_dwarf_sets,
+ { use absolute paths for include files in stabs. Pro: gdb }
+ { always knows full path to file. Con: doesn't work anymore }
+ { if the include file is moved (otherwise, things still work }
+ { if your source hierarchy is the same, but has a different }
+ { base path) }
+ ds_stabs_abs_include_files,
+ { prefix method names by "classname__" in DWARF (like is done }
+ { for Stabs); not enabled by default, because otherwise once }
+ { support for calling methods has been added to gdb, you'd }
+ { always have to type classinstance.classname__methodname() }
+ ds_dwarf_method_class_prefix
+ );
+ tdebugswitches = set of tdebugswitch;
+
+
+ { adding a new entry here requires also adding the appropriate define in
+ systemh.inc (FK)
+ }
+ tfeature = (
+ f_heap,f_init_final,f_rtti,f_classes,f_exceptions,f_exitcode,
+ f_ansistrings,f_widestrings,f_textio,f_consoleio,f_fileio,
+ f_random,f_variants,f_objects,f_dynarrays,f_threading,f_commandargs,
+ f_processes,f_stackcheck,f_dynlibs,f_softfpu,f_objectivec1,f_resources
+ );
+ tfeatures = set of tfeature;
+
+ type
+ { optimizer }
+ toptimizerswitch = (cs_opt_none,
+ cs_opt_level1,cs_opt_level2,cs_opt_level3,
+ cs_opt_regvar,cs_opt_uncertain,cs_opt_size,cs_opt_stackframe,
+ cs_opt_peephole,cs_opt_asmcse,cs_opt_loopunroll,cs_opt_tailrecursion,cs_opt_nodecse,
+ cs_opt_nodedfa,cs_opt_loopstrength
+ );
+ toptimizerswitches = set of toptimizerswitch;
+
+ { whole program optimizer }
+ twpoptimizerswitch = (
+ cs_wpo_devirtualize_calls,cs_wpo_optimize_vmts,
+ cs_wpo_symbol_liveness
+ );
+ twpoptimizerswitches = set of twpoptimizerswitch;
+
+ type
+ { Used by ARM / AVR to differentiate between specific microcontrollers }
+ tcontrollerdatatype = record
+ controllertypestr, controllerunitstr: string[20];
+ interruptvectors:integer;
+ flashbase, flashsize, srambase, sramsize, eeprombase, eepromsize: dword;
+ end;
+
+ const
+ OptimizerSwitchStr : array[toptimizerswitch] of string[10] = ('',
+ 'LEVEL1','LEVEL2','LEVEL3',
+ 'REGVAR','UNCERTAIN','SIZE','STACKFRAME',
+ 'PEEPHOLE','ASMCSE','LOOPUNROLL','TAILREC','CSE','DFA','STRENGTH'
+ );
+ WPOptimizerSwitchStr : array [twpoptimizerswitch] of string[14] = (
+ 'DEVIRTCALLS','OPTVMTS','SYMBOLLIVENESS'
+ );
+
+ DebugSwitchStr : array[tdebugswitch] of string[22] = ('',
+ 'DWARFSETS','STABSABSINCLUDES','DWARFMETHODCLASSPREFIX');
+
+ { switches being applied to all CPUs at the given level }
+ genericlevel1optimizerswitches = [cs_opt_level1];
+ genericlevel2optimizerswitches = [cs_opt_level2];
+ genericlevel3optimizerswitches = [cs_opt_level3];
+
+ { whole program optimizations whose information generation requires
+ information from all loaded units
+ }
+ WPOptimizationsNeedingAllUnitInfo = [cs_wpo_devirtualize_calls];
+
+ featurestr : array[tfeature] of string[12] = (
+ 'HEAP','INITFINAL','RTTI','CLASSES','EXCEPTIONS','EXITCODE',
+ 'ANSISTRINGS','WIDESTRINGS','TEXTIO','CONSOLEIO','FILEIO',
+ 'RANDOM','VARIANTS','OBJECTS','DYNARRAYS','THREADING','COMMANDARGS',
+ 'PROCESSES','STACKCHECK','DYNLIBS','SOFTFPU','OBJECTIVEC1','RESOURCES'
+ );
+
+ type
+ { Switches which can be changed by a mode (fpc,tp7,delphi) }
+ tmodeswitch = (m_none,m_all, { needed for keyword }
+ { generic }
+ m_fpc,m_objfpc,m_delphi,m_tp7,m_mac,m_iso,
+ {$ifdef fpc_mode}m_gpc,{$endif}
+ { more specific }
+ m_class, { delphi class model }
+ m_objpas, { load objpas unit }
+ m_result, { result in functions }
+ m_string_pchar, { pchar 2 string conversion }
+ m_cvar_support, { cvar variable directive }
+ m_nested_comment, { nested comments }
+ m_tp_procvar, { tp style procvars (no @ needed) }
+ m_mac_procvar, { macpas style procvars }
+ m_repeat_forward, { repeating forward declarations is needed }
+ m_pointer_2_procedure, { allows the assignement of pointers to
+ procedure variables }
+ m_autoderef, { does auto dereferencing of struct. vars }
+ m_initfinal, { initialization/finalization for units }
+ m_default_ansistring, { ansistring turned on by default }
+ m_out, { support the calling convention OUT }
+ m_default_para, { support default parameters }
+ m_hintdirective, { support hint directives }
+ m_duplicate_names, { allow locals/paras to have duplicate names of globals }
+ m_property, { allow properties }
+ m_default_inline, { allow inline proc directive }
+ m_except, { allow exception-related keywords }
+ m_objectivec1, { support interfacing with Objective-C (1.0) }
+ m_objectivec2, { support interfacing with Objective-C (2.0) }
+ m_nested_procvars, { support nested procedural variables }
+ m_non_local_goto, { support non local gotos (like iso pascal) }
+ m_advanced_records, { advanced record syntax with visibility sections, methods and properties }
+ m_isolike_unary_minus, { unary minus like in iso pascal: same precedence level as binary minus/plus }
+ m_systemcodepage { use system codepage as compiler codepage by default, emit ansistrings with system codepage }
+ );
+ tmodeswitches = set of tmodeswitch;
+
+ { Win32, OS/2 & MacOS application types }
+ tapptype = (
+ app_none,
+ app_native,
+ app_gui, { graphic user-interface application}
+ app_cui, { console application}
+ app_fs, { full-screen type application (OS/2 and EMX only) }
+ app_tool, { tool application, (MPW tool for MacOS, MacOS only)}
+ app_arm7,
+ app_arm9,
+ app_bundle { dynamically loadable bundle, Darwin only }
+ );
+
+ { interface types }
+ tinterfacetypes = (
+ it_interfacecom,
+ it_interfacecorba
+ );
+
+ { currently parsed block type }
+ tblock_type = (
+ bt_none, { not assigned }
+ bt_general, { default }
+ bt_type, { type section }
+ bt_const, { const section }
+ bt_const_type, { const part of type. e.g.: ": Integer = 1" }
+ bt_var, { variable declaration }
+ bt_var_type, { type of variable }
+ bt_except, { except section }
+ bt_body { procedure body }
+ );
+
+ { Temp types }
+ ttemptype = (tt_none,
+ tt_free,tt_normal,tt_persistent,
+ tt_noreuse,tt_freenoreuse);
+ ttemptypeset = set of ttemptype;
+
+ { calling convention for tprocdef and tprocvardef }
+ tproccalloption=(pocall_none,
+ { procedure uses C styled calling }
+ pocall_cdecl,
+ { C++ calling conventions }
+ pocall_cppdecl,
+ { Far16 for OS/2 }
+ pocall_far16,
+ { Old style FPC default calling }
+ pocall_oldfpccall,
+ { Procedure has compiler magic}
+ pocall_internproc,
+ { procedure is a system call, applies e.g. to MorphOS and PalmOS }
+ pocall_syscall,
+ { pascal standard left to right }
+ pocall_pascal,
+ { procedure uses register (fastcall) calling }
+ pocall_register,
+ { safe call calling conventions }
+ pocall_safecall,
+ { procedure uses stdcall call }
+ pocall_stdcall,
+ { Special calling convention for cpus without a floating point
+ unit. Floating point numbers are passed in integer registers
+ instead of floating point registers. Depending on the other
+ available calling conventions available for the cpu
+ this replaces either pocall_fastcall or pocall_stdcall.
+ }
+ pocall_softfloat,
+ { Metrowerks Pascal. Special case on Mac OS (X): passes all }
+ { constant records by reference. }
+ pocall_mwpascal,
+ { Special interrupt handler for embedded systems }
+ pocall_interrupt
+ );
+ tproccalloptions = set of tproccalloption;
+
+ const
+ proccalloptionStr : array[tproccalloption] of string[14]=('',
+ 'CDecl',
+ 'CPPDecl',
+ 'Far16',
+ 'OldFPCCall',
+ 'InternProc',
+ 'SysCall',
+ 'Pascal',
+ 'Register',
+ 'SafeCall',
+ 'StdCall',
+ 'SoftFloat',
+ 'MWPascal',
+ 'Interrupt'
+ );
+
+ { Default calling convention }
+{$ifdef x86}
+ pocall_default = pocall_register;
+{$else}
+ pocall_default = pocall_stdcall;
+{$endif}
+
+ modeswitchstr : array[tmodeswitch] of string[18] = ('','',
+ '','','','','','',
+ {$ifdef fpc_mode}'',{$endif}
+ { more specific }
+ 'CLASS',
+ 'OBJPAS',
+ 'RESULT',
+ 'PCHARTOSTRING',
+ 'CVAR',
+ 'NESTEDCOMMENTS',
+ 'CLASSICPROCVARS',
+ 'MACPROCVARS',
+ 'REPEATFORWARD',
+ 'POINTERTOPROCVAR',
+ 'AUTODEREF',
+ 'INITFINAL',
+ 'ANSISTRINGS',
+ 'OUT',
+ 'DEFAULTPARAMETERS',
+ 'HINTDIRECTIVE',
+ 'DUPLICATELOCALS',
+ 'PROPERTIES',
+ 'ALLOWINLINE',
+ 'EXCEPTIONS',
+ 'OBJECTIVEC1',
+ 'OBJECTIVEC2',
+ 'NESTEDPROCVARS',
+ 'NONLOCALGOTO',
+ 'ADVANCEDRECORDS',
+ 'ISOUNARYMINUS',
+ 'SYSTEMCODEPAGE');
+
+
+ type
+ tprocinfoflag=(
+ { procedure has at least one assembler block }
+ pi_has_assembler_block,
+ { procedure does a call }
+ pi_do_call,
+ { procedure has a try statement = no register optimization }
+ pi_uses_exceptions,
+ { procedure is declared as @var(assembler), don't optimize}
+ pi_is_assembler,
+ { procedure contains data which needs to be finalized }
+ pi_needs_implicit_finally,
+ { procedure has the implicit try..finally generated }
+ pi_has_implicit_finally,
+ { procedure uses fpu}
+ pi_uses_fpu,
+ { procedure uses GOT for PIC code }
+ pi_needs_got,
+ { references var/proc/type/const in static symtable,
+ i.e. not allowed for inlining from other units }
+ pi_uses_static_symtable,
+ { set if the procedure has to push parameters onto the stack }
+ pi_has_stackparameter,
+ { set if the procedure has at least one label }
+ pi_has_label,
+ { calls itself recursive }
+ pi_is_recursive,
+ { stack frame optimization not possible (only on x86 probably) }
+ pi_needs_stackframe,
+ { set if the procedure has at least one register saved on the stack }
+ pi_has_saved_regs,
+ { dfa was generated for this proc }
+ pi_dfaavailable,
+ { subroutine contains interprocedural used labels }
+ pi_has_interproclabel,
+ { subroutine has unwind info (win64) }
+ pi_has_unwind_info
+ );
+ tprocinfoflags=set of tprocinfoflag;
+
+ type
+ { float types -- warning, this enum/order is used internally by the RTL
+ as well in rtl/inc/real2str.inc }
+ tfloattype = (
+ s32real,s64real,s80real,sc80real { the C "long double" type on x86 },
+ s64comp,s64currency,s128real
+ );
+
+ type
+ { register allocator live range extension direction }
+ TRADirection = (rad_forward, rad_backwards, rad_backwards_reinit);
+
+ type
+ TIDString = string[maxidlen];
+
+ tnormalset = set of byte; { 256 elements set }
+ pnormalset = ^tnormalset;
+
+ pboolean = ^boolean;
+ pdouble = ^double;
+ pbyte = ^byte;
+ pword = ^word;
+ plongint = ^longint;
+ plongintarray = plongint;
+
+ pfileposinfo = ^tfileposinfo;
+ tfileposinfo = record
+ { if types of column or fileindex are changed, modify tcompilerppufile.putposinfo }
+ line : longint;
+ column : word;
+ fileindex : word;
+ moduleindex : word;
+ end;
+
+ {$ifndef xFPC}
+ type
+ pguid = ^tguid;
+ tguid = packed record
+ D1: LongWord;
+ D2: Word;
+ D3: Word;
+ D4: array[0..7] of Byte;
+ end;
+ {$endif}
+
+ tstringencoding = Word;
+ tcodepagestring = string[20];
+
+ const
+ { link options }
+ link_none = $0;
+ link_always = $1;
+ link_static = $2;
+ link_smart = $4;
+ link_shared = $8;
+
+ type
+ { a message state }
+ tmsgstate = (
+ ms_on := 1,
+ ms_off := 2,
+ ms_error := 3,
+
+ ms_on_global := $11, // turn on output
+ ms_off_global := $22, // turn off output
+ ms_error_global := $33 // cast to error
+ );
+ const
+ { Mask for current value of message state }
+ ms_local_mask = $0f;
+ { Mask for global value of message state
+ that needs to be restored when changing units }
+ ms_global_mask = $f0;
+ { Shift used to convert global to local message state }
+ ms_shift = 4;
+
+ type
+ pmessagestaterecord = ^tmessagestaterecord;
+ tmessagestaterecord = record
+ next : pmessagestaterecord;
+ value : longint;
+ state : tmsgstate;
+ end;
+
+
+
+implementation
+
+end.
diff --git a/closures/compiler/html/i386/readme.txt b/closures/compiler/html/i386/readme.txt
new file mode 100644
index 0000000000..b1f0f0ba45
--- /dev/null
+++ b/closures/compiler/html/i386/readme.txt
@@ -0,0 +1,5 @@
+This directory contains the documentation of the compiler with i386 as target.
+To get the documentation you've to run the pasdoc utility. You can get it from
+http://pasdoc.sourceforge.net. Do a make htmldocs in the compiler directory
+to create the documentation. The generated all*.html file provide access
+to the different documentation.
diff --git a/closures/compiler/html/powerpc/readme.txt b/closures/compiler/html/powerpc/readme.txt
new file mode 100644
index 0000000000..7a534cd114
--- /dev/null
+++ b/closures/compiler/html/powerpc/readme.txt
@@ -0,0 +1,5 @@
+This directory contains the documentation of the compiler with powerpc as target.
+To get the documentation you've to run the pasdoc utility. You can get it from
+http://pasdoc.sourceforge.net. Do a make htmldocs in the compiler directory
+to create the documentation. The generated all*.html file provide access
+to the different documentation.
diff --git a/closures/compiler/htypechk.pas b/closures/compiler/htypechk.pas
new file mode 100644
index 0000000000..ea460f0816
--- /dev/null
+++ b/closures/compiler/htypechk.pas
@@ -0,0 +1,2968 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit exports some help routines for the type checking
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit htypechk;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cclasses,tokens,cpuinfo,
+ node,globtype,
+ symconst,symtype,symdef,symsym,symbase;
+
+ type
+ Ttok2nodeRec=record
+ tok : ttoken;
+ nod : tnodetype;
+ inr : integer; // inline number
+ op_overloading_supported : boolean;
+ end;
+
+ pcandidate = ^tcandidate;
+ tcandidate = record
+ next : pcandidate;
+ data : tprocdef;
+ wrongparaidx,
+ firstparaidx : integer;
+ exact_count,
+ equal_count,
+ cl1_count,
+ cl2_count,
+ cl3_count,
+ cl4_count,
+ cl5_count,
+ coper_count : integer; { should be signed }
+ ordinal_distance : double;
+ invalid : boolean;
+ wrongparanr : byte;
+ end;
+
+ tcallcandidates = class
+ private
+ FProcsym : tprocsym;
+ FProcsymtable : tsymtable;
+ FOperator : ttoken;
+ FCandidateProcs : pcandidate;
+ FProcCnt : integer;
+ FParaNode : tnode;
+ FParaLength : smallint;
+ FAllowVariant : boolean;
+ procedure collect_overloads_in_struct(structdef:tabstractrecorddef;ProcdefOverloadList:TFPObjectList;searchhelpers,anoninherited:boolean);
+ procedure collect_overloads_in_units(ProcdefOverloadList:TFPObjectList; objcidcall,explicitunit: boolean);
+ procedure create_candidate_list(ignorevisibility,allowdefaultparas,objcidcall,explicitunit,searchhelpers,anoninherited:boolean);
+ function proc_add(st:tsymtable;pd:tprocdef;objcidcall: boolean):pcandidate;
+ public
+ constructor create(sym:tprocsym;st:TSymtable;ppn:tnode;ignorevisibility,allowdefaultparas,objcidcall,explicitunit,searchhelpers,anoninherited:boolean);
+ constructor create_operator(op:ttoken;ppn:tnode);
+ destructor destroy;override;
+ procedure list(all:boolean);
+{$ifdef EXTDEBUG}
+ procedure dump_info(lvl:longint);
+{$endif EXTDEBUG}
+ procedure get_information;
+ function choose_best(var bestpd:tabstractprocdef; singlevariant: boolean):integer;
+ procedure find_wrong_para;
+ property Count:integer read FProcCnt;
+ end;
+
+ type
+ tregableinfoflag = (
+ // can be put in a register if it's the address of a var/out/const parameter
+ ra_addr_regable,
+ // orthogonal to above flag: the address of the node is taken and may
+ // possibly escape the block in which this node is declared (e.g. a
+ // local variable is passed as var parameter to another procedure)
+ ra_addr_taken);
+ tregableinfoflags = set of tregableinfoflag;
+
+ {$i compinnr.inc}
+ const
+ tok2nodes=27;
+ tok2node:array[1..tok2nodes] of ttok2noderec=(
+ (tok:_PLUS ;nod:addn;inr:-1;op_overloading_supported:true), { binary overloading supported }
+ (tok:_MINUS ;nod:subn;inr:-1;op_overloading_supported:true), { binary and unary overloading supported }
+ (tok:_STAR ;nod:muln;inr:-1;op_overloading_supported:true), { binary overloading supported }
+ (tok:_SLASH ;nod:slashn;inr:-1;op_overloading_supported:true), { binary overloading supported }
+ (tok:_EQ ;nod:equaln;inr:-1;op_overloading_supported:true), { binary overloading supported }
+ (tok:_GT ;nod:gtn;inr:-1;op_overloading_supported:true), { binary overloading supported }
+ (tok:_LT ;nod:ltn;inr:-1;op_overloading_supported:true), { binary overloading supported }
+ (tok:_GTE ;nod:gten;inr:-1;op_overloading_supported:true), { binary overloading supported }
+ (tok:_LTE ;nod:lten;inr:-1;op_overloading_supported:true), { binary overloading supported }
+ (tok:_SYMDIF ;nod:symdifn;inr:-1;op_overloading_supported:true), { binary overloading supported }
+ (tok:_STARSTAR ;nod:starstarn;inr:-1;op_overloading_supported:true), { binary overloading supported }
+ (tok:_OP_AS ;nod:asn;inr:-1;op_overloading_supported:false), { binary overloading NOT supported }
+ (tok:_OP_IN ;nod:inn;inr:-1;op_overloading_supported:true), { binary overloading supported }
+ (tok:_OP_IS ;nod:isn;inr:-1;op_overloading_supported:false), { binary overloading NOT supported }
+ (tok:_OP_OR ;nod:orn;inr:-1;op_overloading_supported:true), { binary overloading supported }
+ (tok:_OP_AND ;nod:andn;inr:-1;op_overloading_supported:true), { binary overloading supported }
+ (tok:_OP_DIV ;nod:divn;inr:-1;op_overloading_supported:true), { binary overloading supported }
+ (tok:_OP_NOT ;nod:notn;inr:-1;op_overloading_supported:true), { unary overloading supported }
+ (tok:_OP_MOD ;nod:modn;inr:-1;op_overloading_supported:true), { binary overloading supported }
+ (tok:_OP_SHL ;nod:shln;inr:-1;op_overloading_supported:true), { binary overloading supported }
+ (tok:_OP_SHR ;nod:shrn;inr:-1;op_overloading_supported:true), { binary overloading supported }
+ (tok:_OP_XOR ;nod:xorn;inr:-1;op_overloading_supported:true), { binary overloading supported }
+ (tok:_ASSIGNMENT ;nod:assignn;inr:-1;op_overloading_supported:true), { unary overloading supported }
+ (tok:_OP_EXPLICIT;nod:assignn;inr:-1;op_overloading_supported:true), { unary overloading supported }
+ (tok:_NE ;nod:unequaln;inr:-1;op_overloading_supported:true), { binary overloading supported }
+ (tok:_OP_INC ;nod:inlinen;inr:in_inc_x;op_overloading_supported:true),{ unary overloading supported }
+ (tok:_OP_DEC ;nod:inlinen;inr:in_dec_x;op_overloading_supported:true) { unary overloading supported }
+ );
+
+ { true, if we are parsing stuff which allows array constructors }
+ allow_array_constructor : boolean = false;
+
+ function node2opstr(nt:tnodetype):string;
+
+ { check operator args and result type }
+ function isbinaryoperatoroverloadable(treetyp:tnodetype;ld:tdef;lt:tnodetype;rd:tdef;rt:tnodetype) : boolean;
+ function isoperatoracceptable(pf : tprocdef; optoken : ttoken) : boolean;
+ function isunaryoverloaded(var t : tnode) : boolean;
+ function isbinaryoverloaded(var t : tnode) : boolean;
+
+ { Register Allocation }
+ procedure make_not_regable(p : tnode; how: tregableinfoflags);
+
+ { procvar handling }
+ function is_proc2procvar_load(p:tnode;out realprocdef:tprocdef):boolean;
+ { returns whether a node represents a load of the function result node via
+ the function name (so it could also be a recursive call to the function
+ in case there or no parameters, or the function could be passed as
+ procvar }
+ function is_ambiguous_funcret_load(p: tnode; out owningprocdef: tprocdef): boolean;
+ procedure test_local_to_procvar(from_def:tprocvardef;to_def:tdef);
+
+ { sets varsym varstate field correctly }
+ type
+ tvarstateflag = (vsf_must_be_valid,vsf_use_hints);
+ tvarstateflags = set of tvarstateflag;
+ procedure set_varstate(p:tnode;newstate:tvarstate;varstateflags:tvarstateflags);
+
+ { sets the callunique flag, if the node is a vecn, }
+ { takes care of type casts etc. }
+ procedure set_unique(p : tnode);
+
+ function valid_for_formal_var(p : tnode; report_errors: boolean) : boolean;
+ function valid_for_formal_const(p : tnode; report_errors: boolean) : boolean;
+ function valid_for_var(p:tnode; report_errors: boolean):boolean;
+ function valid_for_assignment(p:tnode; report_errors: boolean):boolean;
+ function valid_for_loopvar(p:tnode; report_errors: boolean):boolean;
+ function valid_for_addr(p : tnode; report_errors: boolean) : boolean;
+
+ function allowenumop(nt:tnodetype):boolean;
+
+ procedure check_hints(const srsym: tsym; const symoptions: tsymoptions; const deprecatedmsg : pshortstring);
+
+ procedure check_ranges(const location: tfileposinfo; source: tnode; destdef: tdef);
+
+implementation
+
+ uses
+ sysutils,
+ systems,constexp,globals,
+ cutils,verbose,
+ symtable,
+ defutil,defcmp,
+ nbas,ncnv,nld,nmem,ncal,nmat,ninl,nutils,ncon,
+ cgbase,procinfo
+ ;
+
+ type
+ TValidAssign=(Valid_Property,Valid_Void,Valid_Const,Valid_Addr,Valid_Packed);
+ TValidAssigns=set of TValidAssign;
+
+
+ function node2opstr(nt:tnodetype):string;
+ var
+ i : integer;
+ begin
+ result:='<unknown>';
+ for i:=1 to tok2nodes do
+ if tok2node[i].nod=nt then
+ begin
+ result:=tokeninfo^[tok2node[i].tok].str;
+ break;
+ end;
+ end;
+
+
+ function isbinaryoperatoroverloadable(treetyp:tnodetype;ld:tdef;lt:tnodetype;rd:tdef;rt:tnodetype) : boolean;
+
+ function internal_check(treetyp:tnodetype;ld:tdef;lt:tnodetype;rd:tdef;rt:tnodetype;var allowed:boolean):boolean;
+ begin
+ internal_check:=true;
+ case ld.typ of
+ formaldef,
+ recorddef,
+ variantdef :
+ begin
+ allowed:=true;
+ end;
+ procvardef :
+ begin
+ if (rd.typ in [pointerdef,procdef,procvardef]) then
+ begin
+ allowed:=false;
+ exit;
+ end;
+ allowed:=true;
+ end;
+ pointerdef :
+ begin
+ if ((rd.typ in [orddef,enumdef,pointerdef,classrefdef,procvardef]) or
+ is_implicit_pointer_object_type(rd)) then
+ begin
+ allowed:=false;
+ exit;
+ end;
+
+ { don't allow pchar+string }
+ if (is_pchar(ld) or is_pwidechar(ld)) and
+ ((rd.typ=stringdef) or
+ is_pchar(rd) or
+ is_pwidechar(rd) or
+ is_chararray(rd) or
+ is_widechararray(rd)) then
+ begin
+ allowed:=false;
+ exit;
+ end;
+ allowed:=true;
+ end;
+ arraydef :
+ begin
+ { not vector/mmx }
+ if ((cs_mmx in current_settings.localswitches) and
+ is_mmx_able_array(ld)) or
+ ((cs_support_vectors in current_settings.globalswitches) and
+ is_vector(ld)) then
+ begin
+ allowed:=false;
+ exit;
+ end;
+ { not chararray+[(wide)char,(wide)string,(wide)chararray] }
+ if (is_chararray(ld) or is_widechararray(ld) or
+ is_open_chararray(ld) or is_open_widechararray(ld))
+ and
+ ((rd.typ in [stringdef,orddef,enumdef]) or
+ is_pchar(rd) or
+ is_pwidechar(rd) or
+ is_chararray(rd) or
+ is_widechararray(rd) or
+ is_open_chararray(rd) or
+ is_open_widechararray(rd) or
+ (rt=niln)) then
+ begin
+ allowed:=false;
+ exit;
+ end;
+ { dynamic array compare with niln }
+ if ((is_dynamic_array(ld) and
+ (rt=niln)) or
+ (is_dynamic_array(ld) and is_dynamic_array(rd)))
+ and
+ (treetyp in [equaln,unequaln]) then
+ begin
+ allowed:=false;
+ exit;
+ end;
+ allowed:=true;
+ end;
+ objectdef :
+ begin
+ { <> and = are defined for implicit pointer object types }
+ if (treetyp in [equaln,unequaln]) and
+ is_implicit_pointer_object_type(ld) then
+ begin
+ allowed:=false;
+ exit;
+ end;
+ allowed:=true;
+ end;
+ stringdef :
+ begin
+ if (rd.typ in [orddef,enumdef,stringdef]) or
+ is_pchar(rd) or
+ is_pwidechar(rd) or
+ is_chararray(rd) or
+ is_widechararray(rd) or
+ is_open_chararray(rd) or
+ is_open_widechararray(rd) then
+ begin
+ allowed:=false;
+ exit;
+ end;
+ allowed:=true;
+ end;
+ else
+ internal_check:=false;
+ end;
+ end;
+
+ var
+ allowed : boolean;
+ begin
+ { power ** is always possible }
+ if (treetyp=starstarn) then
+ begin
+ isbinaryoperatoroverloadable:=true;
+ exit;
+ end;
+ { order of arguments does not matter so we have to check also
+ the reversed order }
+ allowed:=false;
+ if not internal_check(treetyp,ld,lt,rd,rt,allowed) then
+ internal_check(treetyp,rd,rt,ld,lt,allowed);
+ isbinaryoperatoroverloadable:=allowed;
+ end;
+
+
+ function isunaryoperatoroverloadable(treetyp:tnodetype;inlinenumber:integer;ld:tdef) : boolean;
+ begin
+ result:=false;
+ case treetyp of
+ subn,
+ addn,
+ unaryminusn,
+ unaryplusn,
+ inlinen:
+ begin
+ { only Inc, Dec inline functions are supported for now, so skip check inlinenumber }
+
+ if (ld.typ in [orddef,enumdef,floatdef]) then
+ exit;
+
+{$ifdef SUPPORT_MMX}
+ if (cs_mmx in current_settings.localswitches) and
+ is_mmx_able_array(ld) then
+ exit;
+{$endif SUPPORT_MMX}
+
+ result:=true;
+ end;
+
+ notn :
+ begin
+ if (ld.typ in [orddef,enumdef,floatdef]) then
+ exit;
+
+{$ifdef SUPPORT_MMX}
+ if (cs_mmx in current_settings.localswitches) and
+ is_mmx_able_array(ld) then
+ exit;
+{$endif SUPPORT_MMX}
+
+ result:=true;
+ end;
+ end;
+ end;
+
+
+ function isoperatoracceptable(pf : tprocdef; optoken : ttoken) : boolean;
+ var
+ ld,rd : tdef;
+ i : longint;
+ eq : tequaltype;
+ conv : tconverttype;
+ pd : tprocdef;
+ oldcount,
+ count: longint;
+ parasym : tparavarsym;
+ begin
+ result:=false;
+ count := pf.parast.SymList.count;
+
+ oldcount:=count;
+ while count > 0 do
+ begin
+ parasym:=tparavarsym(pf.parast.SymList[count-1]);
+ if is_boolean(parasym.vardef) then
+ begin
+ if parasym.name='RANGECHECK' then
+ begin
+ Include(parasym.varoptions, vo_is_hidden_para);
+ Include(parasym.varoptions, vo_is_range_check);
+ Dec(count);
+ end
+ else if parasym.name='OVERFLOWCHECK' then
+ begin
+ Include(parasym.varoptions, vo_is_hidden_para);
+ Include(parasym.varoptions, vo_is_overflow_check);
+ Dec(count);
+ end
+ else
+ break;
+ end
+ else
+ break;
+ end;
+ if count<>oldcount then
+ pf.calcparas;
+
+ case count of
+ 1 : begin
+ ld:=tparavarsym(pf.parast.SymList[0]).vardef;
+ { assignment is a special case }
+ if optoken in [_ASSIGNMENT,_OP_EXPLICIT] then
+ begin
+ eq:=compare_defs_ext(ld,pf.returndef,nothingn,conv,pd,[cdo_explicit]);
+ result:=
+ (eq=te_exact) or
+ (
+ (eq=te_incompatible) and
+ { don't allow overloading assigning to custom shortstring
+ types, because we also don't want to differentiate based
+ on different shortstring types (e.g.,
+ "operator :=(const v: variant) res: shorstring" also
+ has to work for assigning a variant to a string[80])
+ }
+ (not is_shortstring(pf.returndef) or
+ (tstringdef(pf.returndef).len=255))
+ );
+ end
+ else
+ { enumerator is a special case too }
+ if optoken=_OP_ENUMERATOR then
+ begin
+ result:=
+ is_class_or_interface_or_object(pf.returndef) or
+ is_record(pf.returndef);
+ if result then
+ begin
+ if not assigned(tabstractrecorddef(pf.returndef).search_enumerator_move) then
+ begin
+ Message1(sym_e_no_enumerator_move, pf.returndef.typename);
+ result:=false;
+ end;
+ if not assigned(tabstractrecorddef(pf.returndef).search_enumerator_current) then
+ begin
+ Message1(sym_e_no_enumerator_current,pf.returndef.typename);
+ result:=false;
+ end;
+ end;
+ end
+ else
+ begin
+ for i:=1 to tok2nodes do
+ if tok2node[i].tok=optoken then
+ begin
+ result:=
+ tok2node[i].op_overloading_supported and
+ isunaryoperatoroverloadable(tok2node[i].nod,tok2node[i].inr,ld);
+ break;
+ end;
+ { Inc, Dec operators are valid if only result type is the same as argument type }
+ if result and (optoken in [_OP_INC,_OP_DEC]) then
+ result:=pf.returndef=ld;
+ end;
+ end;
+ 2 : begin
+ for i:=1 to tok2nodes do
+ if tok2node[i].tok=optoken then
+ begin
+ ld:=tparavarsym(pf.parast.SymList[0]).vardef;
+ rd:=tparavarsym(pf.parast.SymList[1]).vardef;
+ result:=
+ tok2node[i].op_overloading_supported and
+ isbinaryoperatoroverloadable(tok2node[i].nod,ld,nothingn,rd,nothingn);
+ break;
+ end;
+ end;
+ end;
+ end;
+
+
+ function isunaryoverloaded(var t : tnode) : boolean;
+ var
+ ld : tdef;
+ optoken : ttoken;
+ operpd : tprocdef;
+ ppn : tcallparanode;
+ candidates : tcallcandidates;
+ cand_cnt,
+ inlinenumber: integer;
+ begin
+ result:=false;
+ operpd:=nil;
+
+ { load easier access variables }
+ ld:=tunarynode(t).left.resultdef;
+
+ { if we are dealing with inline function then get the function }
+ if t.nodetype=inlinen then
+ inlinenumber:=tinlinenode(t).inlinenumber
+ else
+ inlinenumber:=-1;
+
+ if not isunaryoperatoroverloadable(t.nodetype,inlinenumber,ld) then
+ exit;
+
+ { operator overload is possible }
+ result:=true;
+
+ optoken:=NOTOKEN;
+ case t.nodetype of
+ notn:
+ optoken:=_OP_NOT;
+ unaryminusn:
+ optoken:=_MINUS;
+ unaryplusn:
+ optoken:=_PLUS;
+ inlinen:
+ case inlinenumber of
+ in_inc_x:
+ optoken:=_OP_INC;
+ in_dec_x:
+ optoken:=_OP_DEC;
+ end;
+ end;
+ if (optoken=NOTOKEN) then
+ begin
+ CGMessage(parser_e_operator_not_overloaded);
+ t:=cnothingnode.create;
+ exit;
+ end;
+
+ { generate parameter nodes }
+ { for inline nodes just copy existent callparanode }
+ if (t.nodetype=inlinen) and (tinlinenode(t).left.nodetype=callparan) then
+ ppn:=tcallparanode(tinlinenode(t).left.getcopy)
+ else
+ begin
+ ppn:=ccallparanode.create(tunarynode(t).left.getcopy,nil);
+ ppn.get_paratype;
+ end;
+ candidates:=tcallcandidates.create_operator(optoken,ppn);
+
+ { stop when there are no operators found }
+ if candidates.count=0 then
+ begin
+ CGMessage2(parser_e_operator_not_overloaded_2,ld.typename,arraytokeninfo[optoken].str);
+ candidates.free;
+ ppn.free;
+ t:=cnothingnode.create;
+ exit;
+ end;
+
+ { Retrieve information about the candidates }
+ candidates.get_information;
+{$ifdef EXTDEBUG}
+ { Display info when multiple candidates are found }
+ candidates.dump_info(V_Debug);
+{$endif EXTDEBUG}
+ cand_cnt:=candidates.choose_best(tabstractprocdef(operpd),false);
+
+ { exit when no overloads are found }
+ if cand_cnt=0 then
+ begin
+ CGMessage2(parser_e_operator_not_overloaded_2,ld.typename,arraytokeninfo[optoken].str);
+ candidates.free;
+ ppn.free;
+ t:=cnothingnode.create;
+ exit;
+ end;
+
+ { Multiple candidates left? }
+ if cand_cnt>1 then
+ begin
+ CGMessage(type_e_cant_choose_overload_function);
+{$ifdef EXTDEBUG}
+ candidates.dump_info(V_Hint);
+{$else EXTDEBUG}
+ candidates.list(false);
+{$endif EXTDEBUG}
+ { we'll just use the first candidate to make the
+ call }
+ end;
+ candidates.free;
+
+ addsymref(operpd.procsym);
+
+ { the nil as symtable signs firstcalln that this is
+ an overloaded operator }
+ t:=ccallnode.create(ppn,Tprocsym(operpd.procsym),nil,nil,[]);
+
+ { we already know the procdef to use, so it can
+ skip the overload choosing in callnode.pass_typecheck }
+ tcallnode(t).procdefinition:=operpd;
+ end;
+
+
+ function isbinaryoverloaded(var t : tnode) : boolean;
+ var
+ rd,ld : tdef;
+ optoken : ttoken;
+ operpd : tprocdef;
+ ht : tnode;
+ ppn : tcallparanode;
+ cand_cnt : integer;
+
+ function search_operator(optoken:ttoken;generror:boolean): integer;
+ var
+ candidates : tcallcandidates;
+ begin
+ { generate parameter nodes }
+ ppn:=ccallparanode.create(tbinarynode(t).right.getcopy,ccallparanode.create(tbinarynode(t).left.getcopy,nil));
+ ppn.get_paratype;
+ candidates:=tcallcandidates.create_operator(optoken,ppn);
+
+ { for commutative operators we can swap arguments and try again }
+ if (candidates.count=0) and
+ not(optoken in [_OP_SHL,_OP_SHR,_OP_DIV,_OP_MOD,_STARSTAR,_SLASH,_MINUS]) then
+ begin
+ candidates.free;
+ reverseparameters(ppn);
+ { reverse compare operators }
+ case optoken of
+ _LT:
+ optoken:=_GTE;
+ _GT:
+ optoken:=_LTE;
+ _LTE:
+ optoken:=_GT;
+ _GTE:
+ optoken:=_LT;
+ end;
+ candidates:=tcallcandidates.create_operator(optoken,ppn);
+ end;
+
+ { stop when there are no operators found }
+ result:=candidates.count;
+ if (result=0) and generror then
+ begin
+ CGMessage(parser_e_operator_not_overloaded);
+ candidates.free;
+ exit;
+ end;
+
+ if (result>0) then
+ begin
+ { Retrieve information about the candidates }
+ candidates.get_information;
+ {$ifdef EXTDEBUG}
+ { Display info when multiple candidates are found }
+ candidates.dump_info(V_Debug);
+ {$endif EXTDEBUG}
+ result:=candidates.choose_best(tabstractprocdef(operpd),false);
+ end;
+
+ { exit when no overloads are found }
+ if (result=0) and generror then
+ begin
+ CGMessage3(parser_e_operator_not_overloaded_3,ld.typename,arraytokeninfo[optoken].str,rd.typename);
+ candidates.free;
+ exit;
+ end;
+
+ { Multiple candidates left? }
+ if result>1 then
+ begin
+ CGMessage(type_e_cant_choose_overload_function);
+ {$ifdef EXTDEBUG}
+ candidates.dump_info(V_Hint);
+ {$else EXTDEBUG}
+ candidates.list(false);
+ {$endif EXTDEBUG}
+ { we'll just use the first candidate to make the
+ call }
+ end;
+ candidates.free;
+ end;
+
+ begin
+ isbinaryoverloaded:=false;
+ operpd:=nil;
+ { load easier access variables }
+ ld:=tbinarynode(t).left.resultdef;
+ rd:=tbinarynode(t).right.resultdef;
+ if not isbinaryoperatoroverloadable(t.nodetype,ld,tbinarynode(t).left.nodetype,rd,tbinarynode(t).right.nodetype) then
+ exit;
+
+ { operator overload is possible }
+ result:=true;
+
+ case t.nodetype of
+ equaln:
+ optoken:=_EQ;
+ unequaln:
+ optoken:=_NE;
+ addn:
+ optoken:=_PLUS;
+ subn:
+ optoken:=_MINUS;
+ muln:
+ optoken:=_STAR;
+ starstarn:
+ optoken:=_STARSTAR;
+ slashn:
+ optoken:=_SLASH;
+ ltn:
+ optoken:=_LT;
+ gtn:
+ optoken:=_GT;
+ lten:
+ optoken:=_LTE;
+ gten:
+ optoken:=_GTE;
+ symdifn :
+ optoken:=_SYMDIF;
+ modn :
+ optoken:=_OP_MOD;
+ orn :
+ optoken:=_OP_OR;
+ xorn :
+ optoken:=_OP_XOR;
+ andn :
+ optoken:=_OP_AND;
+ divn :
+ optoken:=_OP_DIV;
+ shln :
+ optoken:=_OP_SHL;
+ shrn :
+ optoken:=_OP_SHR;
+ inn :
+ optoken:=_OP_IN;
+ else
+ begin
+ CGMessage(parser_e_operator_not_overloaded);
+ t:=cnothingnode.create;
+ exit;
+ end;
+ end;
+
+ cand_cnt:=search_operator(optoken,optoken<>_NE);
+
+ { no operator found for "<>" then search for "=" operator }
+ if (cand_cnt=0) and (optoken=_NE) then
+ begin
+ ppn.free;
+ operpd:=nil;
+ optoken:=_EQ;
+ cand_cnt:=search_operator(optoken,true);
+ end;
+
+ if (cand_cnt=0) then
+ begin
+ ppn.free;
+ t:=cnothingnode.create;
+ exit;
+ end;
+
+ addsymref(operpd.procsym);
+
+ { the nil as symtable signs firstcalln that this is
+ an overloaded operator }
+ ht:=ccallnode.create(ppn,Tprocsym(operpd.procsym),nil,nil,[]);
+
+ { we already know the procdef to use, so it can
+ skip the overload choosing in callnode.pass_typecheck }
+ tcallnode(ht).procdefinition:=operpd;
+
+ { if we found "=" operator for "<>" expression then use it
+ together with "not" }
+ if (t.nodetype=unequaln) and (optoken=_EQ) then
+ ht:=cnotnode.create(ht);
+ t:=ht;
+ end;
+
+
+{****************************************************************************
+ Register Calculation
+****************************************************************************}
+
+ { marks an lvalue as "unregable" }
+ procedure make_not_regable_intern(p : tnode; how: tregableinfoflags; records_only: boolean);
+ begin
+ repeat
+ case p.nodetype of
+ subscriptn:
+ begin
+ records_only:=true;
+ p:=tsubscriptnode(p).left;
+ end;
+ vecn:
+ begin
+ { if there's an implicit dereference, we can stop (just like
+ when there is an actual derefn) }
+ if ((tvecnode(p).left.resultdef.typ=arraydef) and
+ not is_special_array(tvecnode(p).left.resultdef)) or
+ ((tvecnode(p).left.resultdef.typ=stringdef) and
+ (tstringdef(tvecnode(p).left.resultdef).stringtype in [st_shortstring,st_longstring])) then
+ p:=tvecnode(p).left
+ else
+ break;
+ end;
+ typeconvn :
+ begin
+ { implicit dereference -> stop }
+ if (ttypeconvnode(p).convtype=tc_pointer_2_array) then
+ break;
+ if (ttypeconvnode(p).resultdef.typ=recorddef) then
+ records_only:=false;
+ p:=ttypeconvnode(p).left;
+ end;
+ loadn :
+ begin
+ if (tloadnode(p).symtableentry.typ in [staticvarsym,localvarsym,paravarsym]) then
+ begin
+ if (ra_addr_taken in how) then
+ tabstractvarsym(tloadnode(p).symtableentry).addr_taken:=true;
+ if (tabstractvarsym(tloadnode(p).symtableentry).varregable <> vr_none) and
+ ((not records_only) or
+ (tabstractvarsym(tloadnode(p).symtableentry).vardef.typ = recorddef)) then
+ if (tloadnode(p).symtableentry.typ = paravarsym) and
+ (ra_addr_regable in how) then
+ tabstractvarsym(tloadnode(p).symtableentry).varregable:=vr_addr
+ else
+ tabstractvarsym(tloadnode(p).symtableentry).varregable:=vr_none;
+ end;
+ break;
+ end;
+ temprefn :
+ begin
+ if (ra_addr_taken in how) then
+ include(ttemprefnode(p).tempinfo^.flags,ti_addr_taken);
+ if (ti_may_be_in_reg in ttemprefnode(p).tempinfo^.flags) and
+ ((not records_only) or
+ (ttemprefnode(p).tempinfo^.typedef.typ = recorddef)) then
+ exclude(ttemprefnode(p).tempinfo^.flags,ti_may_be_in_reg);
+ break;
+ end;
+ else
+ break;
+ end;
+ until false;
+ end;
+
+ procedure make_not_regable(p : tnode; how: tregableinfoflags);
+ begin
+ make_not_regable_intern(p,how,false);
+ end;
+
+
+{****************************************************************************
+ Subroutine Handling
+****************************************************************************}
+
+ function is_proc2procvar_load(p:tnode;out realprocdef:tprocdef):boolean;
+ begin
+ result:=false;
+ { remove voidpointer typecast for tp procvars }
+ if ((m_tp_procvar in current_settings.modeswitches) or
+ (m_mac_procvar in current_settings.modeswitches)) and
+ (p.nodetype=typeconvn) and
+ is_voidpointer(p.resultdef) then
+ p:=tunarynode(p).left;
+ result:=(p.nodetype=typeconvn) and
+ (ttypeconvnode(p).convtype=tc_proc_2_procvar);
+ if result then
+ realprocdef:=tprocdef(ttypeconvnode(p).left.resultdef);
+ end;
+
+
+ function is_ambiguous_funcret_load(p: tnode; out owningprocdef: tprocdef): boolean;
+ begin
+ result:=false;
+ { the funcret is an absolutevarsym, which gets converted into a type
+ conversion node of the loadnode of the actual function result. Its
+ resulttype is obviously the same as that of the real function result }
+ if (p.nodetype=typeconvn) and
+ (p.resultdef=ttypeconvnode(p).left.resultdef) then
+ p:=ttypeconvnode(p).left;
+ if (p.nodetype=loadn) and
+ (tloadnode(p).symtableentry.typ in [absolutevarsym,localvarsym,paravarsym]) and
+ ([vo_is_funcret,vo_is_result] * tabstractvarsym(tloadnode(p).symtableentry).varoptions = [vo_is_funcret]) then
+ begin
+ owningprocdef:=tprocdef(tloadnode(p).symtableentry.owner.defowner);
+ result:=true;
+ end;
+ end;
+
+
+ { local routines can't be assigned to procvars }
+ procedure test_local_to_procvar(from_def:tprocvardef;to_def:tdef);
+ begin
+ if not(m_nested_procvars in current_settings.modeswitches) and
+ (from_def.parast.symtablelevel>normal_function_level) and
+ (to_def.typ=procvardef) then
+ CGMessage(type_e_cannot_local_proc_to_procvar);
+ end;
+
+
+ procedure set_varstate(p:tnode;newstate:tvarstate;varstateflags:tvarstateflags);
+ const
+ vstrans: array[tvarstate,tvarstate] of tvarstate = (
+ { vs_none -> ... }
+ (vs_none,vs_declared,vs_initialised,vs_read,vs_read_not_warned,vs_referred_not_inited,vs_written,vs_readwritten),
+ { vs_declared -> ... }
+ (vs_none,vs_declared,vs_initialised,vs_read,vs_read_not_warned,vs_referred_not_inited,vs_written,vs_readwritten),
+ { vs_initialised -> ... }
+ (vs_none,vs_initialised,vs_initialised,vs_read,vs_read,vs_read,vs_written,vs_readwritten),
+ { vs_read -> ... }
+ (vs_none,vs_read,vs_read,vs_read,vs_read,vs_read,vs_readwritten,vs_readwritten),
+ { vs_read_not_warned -> ... }
+ (vs_none,vs_read_not_warned,vs_read,vs_read,vs_read_not_warned,vs_read_not_warned,vs_readwritten,vs_readwritten),
+ { vs_referred_not_inited }
+ (vs_none,vs_referred_not_inited,vs_read,vs_read,vs_read_not_warned,vs_referred_not_inited,vs_written,vs_readwritten),
+ { vs_written -> ... }
+ (vs_none,vs_written,vs_written,vs_readwritten,vs_readwritten,vs_written,vs_written,vs_readwritten),
+ { vs_readwritten -> ... }
+ (vs_none,vs_readwritten,vs_readwritten,vs_readwritten,vs_readwritten,vs_readwritten,vs_readwritten,vs_readwritten));
+ var
+ hsym : tabstractvarsym;
+ begin
+ { make sure we can still warn about uninitialised use after high(v), @v etc }
+ if (newstate = vs_read) and
+ not(vsf_must_be_valid in varstateflags) then
+ newstate := vs_referred_not_inited;
+
+ while assigned(p) do
+ begin
+ case p.nodetype of
+ derefn:
+ begin
+ if (tderefnode(p).left.nodetype=temprefn) and
+ assigned(ttemprefnode(tderefnode(p).left).tempinfo^.withnode) then
+ p:=ttemprefnode(tderefnode(p).left).tempinfo^.withnode
+ else
+ break;
+ end;
+ typeconvn :
+ begin
+ case ttypeconvnode(p).convtype of
+ tc_cchar_2_pchar,
+ tc_cstring_2_pchar,
+ tc_array_2_pointer :
+ exclude(varstateflags,vsf_must_be_valid);
+ tc_pchar_2_string,
+ tc_pointer_2_array :
+ include(varstateflags,vsf_must_be_valid);
+ end;
+ p:=tunarynode(p).left;
+ end;
+ subscriptn :
+ begin
+ if is_implicit_pointer_object_type(tunarynode(p).left.resultdef) then
+ newstate := vs_read;
+ p:=tunarynode(p).left;
+ end;
+ vecn:
+ begin
+ set_varstate(tbinarynode(p).right,vs_read,[vsf_must_be_valid]);
+ if (newstate in [vs_read,vs_readwritten]) or
+ not(tunarynode(p).left.resultdef.typ in [stringdef,arraydef]) then
+ include(varstateflags,vsf_must_be_valid)
+ else if (newstate = vs_written) then
+ exclude(varstateflags,vsf_must_be_valid);
+ p:=tunarynode(p).left;
+ end;
+ { do not parse calln }
+ calln :
+ break;
+ loadn :
+ begin
+ if (tloadnode(p).symtableentry.typ in [localvarsym,paravarsym,staticvarsym]) then
+ begin
+ hsym:=tabstractvarsym(tloadnode(p).symtableentry);
+ if (vsf_must_be_valid in varstateflags) and
+ (hsym.varstate in [vs_declared,vs_read_not_warned,vs_referred_not_inited]) then
+ begin
+ { Give warning/note for uninitialized locals }
+ if assigned(hsym.owner) and
+ not(cs_opt_nodedfa in current_settings.optimizerswitches) and
+ not(vo_is_external in hsym.varoptions) and
+ (hsym.owner.symtabletype in [parasymtable,localsymtable,staticsymtable]) and
+ ((hsym.owner=current_procinfo.procdef.localst) or
+ (hsym.owner=current_procinfo.procdef.parast)) then
+ begin
+ if (vo_is_funcret in hsym.varoptions) then
+ begin
+ if (vsf_use_hints in varstateflags) then
+ CGMessagePos(p.fileinfo,sym_h_function_result_uninitialized)
+ else
+ CGMessagePos(p.fileinfo,sym_w_function_result_uninitialized)
+ end
+ else
+ begin
+ if tloadnode(p).symtable.symtabletype=localsymtable then
+ begin
+ if (vsf_use_hints in varstateflags) then
+ CGMessagePos1(p.fileinfo,sym_h_uninitialized_local_variable,hsym.realname)
+ else
+ CGMessagePos1(p.fileinfo,sym_w_uninitialized_local_variable,hsym.realname);
+ end
+ else
+ begin
+ if (vsf_use_hints in varstateflags) then
+ CGMessagePos1(p.fileinfo,sym_h_uninitialized_variable,hsym.realname)
+ else
+ CGMessagePos1(p.fileinfo,sym_w_uninitialized_variable,hsym.realname);
+ end;
+ end;
+ end
+ else if (newstate = vs_read) then
+ newstate := vs_read_not_warned;
+ end;
+ hsym.varstate := vstrans[hsym.varstate,newstate];
+ end;
+ case newstate of
+ vs_written:
+ include(tloadnode(p).flags,nf_write);
+ vs_readwritten:
+ if not(nf_write in tloadnode(p).flags) then
+ include(tloadnode(p).flags,nf_modify);
+ end;
+ break;
+ end;
+ callparan :
+ internalerror(200310081);
+ else
+ break;
+ end;{case }
+ end;
+ end;
+
+
+ procedure set_unique(p : tnode);
+ begin
+ while assigned(p) do
+ begin
+ case p.nodetype of
+ vecn:
+ begin
+ include(p.flags,nf_callunique);
+ break;
+ end;
+ typeconvn,
+ subscriptn,
+ derefn:
+ p:=tunarynode(p).left;
+ else
+ break;
+ end;
+ end;
+ end;
+
+
+ function valid_for_assign(p:tnode;opts:TValidAssigns; report_errors: boolean):boolean;
+ var
+ hp2,
+ hp : tnode;
+ gotstring,
+ gotsubscript,
+ gotrecord,
+ gotpointer,
+ gotvec,
+ gotclass,
+ gotdynarray,
+ gotderef,
+ gottypeconv : boolean;
+ fromdef,
+ todef : tdef;
+ errmsg,
+ temp : longint;
+ begin
+ if valid_const in opts then
+ errmsg:=type_e_variable_id_expected
+ else if valid_property in opts then
+ errmsg:=type_e_argument_cant_be_assigned
+ else
+ errmsg:=type_e_no_addr_of_constant;
+ result:=false;
+ gotsubscript:=false;
+ gotvec:=false;
+ gotderef:=false;
+ gotrecord:=false;
+ gotclass:=false;
+ gotpointer:=false;
+ gotdynarray:=false;
+ gotstring:=false;
+ gottypeconv:=false;
+ hp:=p;
+ if not(valid_void in opts) and
+ is_void(hp.resultdef) then
+ begin
+ if report_errors then
+ CGMessagePos(hp.fileinfo,errmsg);
+ exit;
+ end;
+ while assigned(hp) do
+ begin
+ { property allowed? calln has a property check itself }
+ if (nf_isproperty in hp.flags) then
+ begin
+ { check return type }
+ case hp.resultdef.typ of
+ pointerdef :
+ gotpointer:=true;
+ objectdef :
+ gotclass:=is_implicit_pointer_object_type(hp.resultdef);
+ recorddef :
+ gotrecord:=true;
+ classrefdef :
+ gotclass:=true;
+ stringdef :
+ gotstring:=true;
+ end;
+ if (valid_property in opts) then
+ begin
+ { don't allow writing to calls that will create
+ temps like calls that return a structure and we
+ are assigning to a member }
+ if (valid_const in opts) or
+ { if we got a deref, we won't modify the property itself }
+ (gotderef) or
+ { same when we got a class and subscript (= deref) }
+ (gotclass and gotsubscript) or
+ (
+ { allowing assignments to typecasted properties
+ a) is Delphi-incompatible
+ b) causes problems in case the getter is a function
+ (because then the result of the getter is
+ typecasted to this type, and then we "assign" to
+ this typecasted function result) -> always
+ disallow, since property accessors should be
+ transparantly changeable to functions at all
+ times
+ }
+ not(gottypeconv) and
+ not(gotsubscript and gotrecord) and
+ not(gotstring and gotvec)
+ ) then
+ result:=true
+ else
+ if report_errors then
+ CGMessagePos(hp.fileinfo,errmsg);
+ end
+ else
+ begin
+ { 1. if it returns a pointer and we've found a deref,
+ 2. if it returns a class and a subscription or with is found
+ 3. if the address is needed of a field (subscriptn, vecn) }
+ if (gotpointer and gotderef) or
+ (gotstring and gotvec) or
+ (gotclass and gotsubscript) or
+ (
+ (gotvec and gotdynarray)
+ ) or
+ (
+ (Valid_Addr in opts) and
+ (hp.nodetype in [subscriptn,vecn])
+ ) then
+ result:=true
+ else
+ if report_errors then
+ CGMessagePos(hp.fileinfo,errmsg);
+ end;
+ exit;
+ end;
+ case hp.nodetype of
+ temprefn :
+ begin
+ valid_for_assign := true;
+ exit;
+ end;
+ derefn :
+ begin
+ gotderef:=true;
+ hp:=tderefnode(hp).left;
+ end;
+ typeconvn :
+ begin
+ gottypeconv:=true;
+ { typecast sizes must match, exceptions:
+ - implicit typecast made by absolute
+ - from formaldef
+ - from void
+ - from/to open array
+ - typecast from pointer to array }
+ fromdef:=ttypeconvnode(hp).left.resultdef;
+ todef:=hp.resultdef;
+ if not((nf_absolute in ttypeconvnode(hp).flags) or
+ (fromdef.typ=formaldef) or
+ is_void(fromdef) or
+ is_open_array(fromdef) or
+ is_open_array(todef) or
+ ((fromdef.typ=pointerdef) and (todef.typ=arraydef)) or
+ ((fromdef.typ = objectdef) and (todef.typ = objectdef) and
+ (tobjectdef(fromdef).is_related(tobjectdef(todef))))) and
+ (fromdef.size<>todef.size) then
+ begin
+ { in TP it is allowed to typecast to smaller types. But the variable can't
+ be in a register }
+ if (m_tp7 in current_settings.modeswitches) or
+ (todef.size<fromdef.size) then
+ make_not_regable(hp,[ra_addr_regable])
+ else
+ if report_errors then
+ CGMessagePos2(hp.fileinfo,type_e_typecast_wrong_size_for_assignment,tostr(fromdef.size),tostr(todef.size));
+ end;
+
+ { don't allow assignments to typeconvs that need special code }
+ if not(gotsubscript or gotvec or gotderef) and
+ not(ttypeconvnode(hp).assign_allowed) then
+ begin
+ if report_errors then
+ CGMessagePos(hp.fileinfo,errmsg);
+ exit;
+ end;
+ case hp.resultdef.typ of
+ pointerdef :
+ gotpointer:=true;
+ objectdef :
+ gotclass:=is_implicit_pointer_object_type(hp.resultdef);
+ classrefdef :
+ gotclass:=true;
+ arraydef :
+ begin
+ { pointer -> array conversion is done then we need to see it
+ as a deref, because a ^ is then not required anymore }
+ if (ttypeconvnode(hp).left.resultdef.typ=pointerdef) then
+ gotderef:=true;
+ end;
+ end;
+ hp:=ttypeconvnode(hp).left;
+ end;
+ vecn :
+ begin
+ if { only check for first (= outermost) vec node }
+ not gotvec and
+ not(valid_packed in opts) and
+ (tvecnode(hp).left.resultdef.typ = arraydef) and
+ (ado_IsBitPacked in tarraydef(tvecnode(hp).left.resultdef).arrayoptions) and
+ ((tarraydef(tvecnode(hp).left.resultdef).elepackedbitsize mod 8 <> 0) or
+ (is_ordinal(tarraydef(tvecnode(hp).left.resultdef).elementdef) and
+ not ispowerof2(tarraydef(tvecnode(hp).left.resultdef).elepackedbitsize div 8,temp))) then
+ begin
+ if report_errors then
+ if (valid_property in opts) then
+ CGMessagePos(hp.fileinfo,parser_e_packed_element_no_loop)
+ else
+ CGMessagePos(hp.fileinfo,parser_e_packed_element_no_var_addr);
+ exit;
+ end;
+ gotvec:=true;
+ { accesses to dyn. arrays override read only access in delphi }
+ if (m_delphi in current_settings.modeswitches) and is_dynamic_array(tunarynode(hp).left.resultdef) then
+ gotdynarray:=true;
+ hp:=tunarynode(hp).left;
+ end;
+ blockn :
+ begin
+ hp2:=tblocknode(hp).statements;
+ if assigned(hp2) then
+ begin
+ if hp2.nodetype<>statementn then
+ internalerror(2006110801);
+ while assigned(tstatementnode(hp2).next) do
+ hp2:=tstatementnode(hp2).next;
+ hp:=tstatementnode(hp2).statement;
+ end
+ else
+ begin
+ if report_errors then
+ CGMessagePos(hp.fileinfo,type_e_variable_id_expected);
+ exit;
+ end;
+ end;
+ asn :
+ begin
+ { asn can't be assigned directly, it returns the value in a register instead
+ of reference. }
+ if not(gotsubscript or gotderef or gotvec) then
+ begin
+ if report_errors then
+ CGMessagePos(hp.fileinfo,errmsg);
+ exit;
+ end;
+ hp:=tunarynode(hp).left;
+ end;
+ subscriptn :
+ begin
+ { only check first (= outermost) subscriptn }
+ if not gotsubscript and
+ not(valid_packed in opts) and
+ is_packed_record_or_object(tsubscriptnode(hp).left.resultdef) and
+ ((tsubscriptnode(hp).vs.fieldoffset mod 8 <> 0) or
+ (is_ordinal(tsubscriptnode(hp).resultdef) and
+ not ispowerof2(tsubscriptnode(hp).resultdef.packedbitsize div 8,temp))) then
+ begin
+ if report_errors then
+ if (valid_property in opts) then
+ CGMessagePos(hp.fileinfo,parser_e_packed_element_no_loop)
+ else
+ CGMessagePos(hp.fileinfo,parser_e_packed_element_no_var_addr);
+ exit;
+ end;
+ gotsubscript:=true;
+ { loop counter? }
+ if not(Valid_Const in opts) and
+ (vo_is_loop_counter in tsubscriptnode(hp).vs.varoptions) then
+ begin
+ if report_errors then
+ CGMessage1(parser_e_illegal_assignment_to_count_var,tsubscriptnode(hp).vs.realname);
+ exit;
+ end;
+ { implicit pointer object types result in dereferencing }
+ hp:=tsubscriptnode(hp).left;
+ if is_implicit_pointer_object_type(hp.resultdef) then
+ gotderef:=true;
+ end;
+ muln,
+ divn,
+ andn,
+ xorn,
+ orn,
+ notn,
+ subn,
+ addn :
+ begin
+ { Allow operators on a pointer, or an integer
+ and a pointer typecast and deref has been found }
+ if ((hp.resultdef.typ=pointerdef) or
+ (is_integer(hp.resultdef) and gotpointer)) and
+ gotderef then
+ result:=true
+ else
+ { Temp strings are stored in memory, for compatibility with
+ delphi only }
+ if (m_delphi in current_settings.modeswitches) and
+ ((valid_addr in opts) or
+ (valid_const in opts)) and
+ (hp.resultdef.typ=stringdef) then
+ result:=true
+ else
+ if report_errors then
+ CGMessagePos(hp.fileinfo,type_e_variable_id_expected);
+ exit;
+ end;
+ niln,
+ pointerconstn :
+ begin
+ { to support e.g. @tmypointer(0)^.data; see tests/tbs/tb0481 }
+ if gotderef then
+ result:=true
+ else
+ if report_errors then
+ CGMessagePos(hp.fileinfo,type_e_no_assign_to_addr);
+ exit;
+ end;
+ ordconstn,
+ realconstn :
+ begin
+ { these constants will be passed by value }
+ if report_errors then
+ CGMessagePos(hp.fileinfo,type_e_variable_id_expected);
+ exit;
+ end;
+ setconstn,
+ stringconstn,
+ guidconstn :
+ begin
+ { these constants will be passed by reference }
+ if valid_const in opts then
+ result:=true
+ else
+ if report_errors then
+ CGMessagePos(hp.fileinfo,type_e_variable_id_expected);
+ exit;
+ end;
+ addrn :
+ begin
+ if gotderef then
+ result:=true
+ else
+ if report_errors then
+ CGMessagePos(hp.fileinfo,type_e_no_assign_to_addr);
+ exit;
+ end;
+ calln :
+ begin
+ { check return type }
+ case hp.resultdef.typ of
+ arraydef :
+ begin
+ { dynamic arrays are allowed when there is also a
+ vec node }
+ if is_dynamic_array(hp.resultdef) and
+ gotvec then
+ begin
+ gotderef:=true;
+ gotpointer:=true;
+ end;
+ end;
+ pointerdef :
+ gotpointer:=true;
+ objectdef :
+ gotclass:=is_implicit_pointer_object_type(hp.resultdef);
+ recorddef, { handle record like class it needs a subscription }
+ classrefdef :
+ gotclass:=true;
+ stringdef :
+ gotstring:=true;
+ end;
+ { 1. if it returns a pointer and we've found a deref,
+ 2. if it returns a class or record and a subscription or with is found
+ 3. string is returned }
+ if (gotstring and gotvec) or
+ (gotpointer and gotderef) or
+ (gotclass and gotsubscript) then
+ result:=true
+ else
+ { Temp strings are stored in memory, for compatibility with
+ delphi only }
+ if (m_delphi in current_settings.modeswitches) and
+ (valid_addr in opts) and
+ (hp.resultdef.typ=stringdef) then
+ result:=true
+ else
+ if ([valid_const,valid_addr] * opts = [valid_const]) then
+ result:=true
+ else
+ if report_errors then
+ CGMessagePos(hp.fileinfo,errmsg);
+ exit;
+ end;
+ inlinen :
+ begin
+ if ((valid_const in opts) and
+ (tinlinenode(hp).inlinenumber in [in_typeof_x])) or
+ (tinlinenode(hp).inlinenumber in [in_unaligned_x]) then
+ result:=true
+ else
+ if report_errors then
+ CGMessagePos(hp.fileinfo,type_e_variable_id_expected);
+ exit;
+ end;
+ dataconstn:
+ begin
+ { only created internally, so no additional checks necessary }
+ result:=true;
+ exit;
+ end;
+ loadn :
+ begin
+ case tloadnode(hp).symtableentry.typ of
+ absolutevarsym,
+ staticvarsym,
+ localvarsym,
+ paravarsym :
+ begin
+ { loop counter? }
+ if not(Valid_Const in opts) and
+ not gotderef and
+ (vo_is_loop_counter in tabstractvarsym(tloadnode(hp).symtableentry).varoptions) then
+ begin
+ if report_errors then
+ CGMessage1(parser_e_illegal_assignment_to_count_var,tloadnode(hp).symtableentry.realname);
+ exit;
+ end;
+ { read-only variable? }
+ if (tabstractvarsym(tloadnode(hp).symtableentry).varspez in [vs_const,vs_constref]) then
+ begin
+ { allow p^:= constructions with p is const parameter }
+ if gotderef or gotdynarray or (Valid_Const in opts) or
+ (loadnf_isinternal_ignoreconst in tloadnode(hp).loadnodeflags) then
+ result:=true
+ else
+ if report_errors then
+ CGMessagePos(tloadnode(hp).fileinfo,type_e_no_assign_to_const);
+ exit;
+ end;
+ result:=true;
+ exit;
+ end;
+ procsym :
+ begin
+ if (Valid_Const in opts) then
+ result:=true
+ else
+ if report_errors then
+ CGMessagePos(hp.fileinfo,type_e_variable_id_expected);
+ exit;
+ end;
+ labelsym :
+ begin
+ if (Valid_Addr in opts) then
+ result:=true
+ else
+ if report_errors then
+ CGMessagePos(hp.fileinfo,type_e_variable_id_expected);
+ exit;
+ end;
+ constsym:
+ begin
+ if (tconstsym(tloadnode(hp).symtableentry).consttyp=constresourcestring) and
+ (valid_addr in opts) then
+ result:=true
+ else
+ if report_errors then
+ CGMessagePos(hp.fileinfo,type_e_variable_id_expected);
+ exit;
+ end;
+ else
+ begin
+ if report_errors then
+ CGMessagePos(hp.fileinfo,type_e_variable_id_expected);
+ exit;
+ end;
+ end;
+ end;
+ else
+ begin
+ if report_errors then
+ CGMessagePos(hp.fileinfo,type_e_variable_id_expected);
+ exit;
+ end;
+ end;
+ end;
+ end;
+
+
+ function valid_for_var(p:tnode; report_errors: boolean):boolean;
+ begin
+ valid_for_var:=valid_for_assign(p,[],report_errors);
+ end;
+
+
+ function valid_for_formal_var(p : tnode; report_errors: boolean) : boolean;
+ begin
+ valid_for_formal_var:=valid_for_assign(p,[valid_void],report_errors);
+ end;
+
+
+ function valid_for_formal_const(p : tnode; report_errors: boolean) : boolean;
+ begin
+ valid_for_formal_const:=(p.resultdef.typ=formaldef) or
+ valid_for_assign(p,[valid_void,valid_const,valid_property],report_errors);
+ end;
+
+
+ function valid_for_assignment(p:tnode; report_errors: boolean):boolean;
+ begin
+ valid_for_assignment:=valid_for_assign(p,[valid_property,valid_packed],report_errors);
+ end;
+
+
+ function valid_for_loopvar(p:tnode; report_errors: boolean):boolean;
+ begin
+ valid_for_loopvar:=valid_for_assign(p,[valid_property],report_errors);
+ end;
+
+
+ function valid_for_addr(p : tnode; report_errors: boolean) : boolean;
+ begin
+ result:=valid_for_assign(p,[valid_const,valid_addr,valid_void],report_errors);
+ end;
+
+
+ procedure var_para_allowed(var eq:tequaltype;def_from,def_to:Tdef; fromnode: tnode);
+ begin
+ { Note: eq must be already valid, it will only be updated! }
+ case def_to.typ of
+ formaldef :
+ begin
+ { all types can be passed to a formaldef,
+ but it is not the prefered way }
+ if not is_constnode(fromnode) then
+ eq:=te_convert_l2
+ else
+ eq:=te_incompatible;
+ end;
+ orddef :
+ begin
+ { allows conversion from word to integer and
+ byte to shortint, but only for TP7 compatibility }
+ if (m_tp7 in current_settings.modeswitches) and
+ (def_from.typ=orddef) and
+ (def_from.size=def_to.size) then
+ eq:=te_convert_l1;
+ end;
+ arraydef :
+ begin
+ if is_open_array(def_to) then
+ begin
+ if is_dynamic_array(def_from) and
+ equal_defs(tarraydef(def_from).elementdef,tarraydef(def_to).elementdef) then
+ eq:=te_convert_l2
+ else
+ if equal_defs(def_from,tarraydef(def_to).elementdef) then
+ eq:=te_convert_l3;
+ end;
+ end;
+ pointerdef :
+ begin
+ { an implicit pointer conversion is allowed }
+ if (def_from.typ=pointerdef) then
+ eq:=te_convert_l1;
+ end;
+ stringdef :
+ begin
+ { all shortstrings are allowed, size is not important }
+ if is_shortstring(def_from) and
+ is_shortstring(def_to) then
+ eq:=te_equal;
+ end;
+ objectdef :
+ begin
+ { child objects can be also passed }
+ { in non-delphi mode, otherwise }
+ { they must match exactly, except }
+ { if they are objects }
+ if (def_from.typ=objectdef) and
+ (
+ (tobjectdef(def_from).objecttype=odt_object) and
+ (tobjectdef(def_to).objecttype=odt_object)
+ ) and
+ (tobjectdef(def_from).is_related(tobjectdef(def_to))) then
+ eq:=te_convert_l1;
+ end;
+ filedef :
+ begin
+ { an implicit file conversion is also allowed }
+ { from a typed file to an untyped one }
+ if (def_from.typ=filedef) and
+ (tfiledef(def_from).filetyp = ft_typed) and
+ (tfiledef(def_to).filetyp = ft_untyped) then
+ eq:=te_convert_l1;
+ end;
+ end;
+ end;
+
+
+ procedure para_allowed(var eq:tequaltype;p:tcallparanode;def_to:tdef);
+ var
+ acn: tarrayconstructornode;
+ realprocdef: tprocdef;
+ tmpeq: tequaltype;
+ begin
+ { Note: eq must be already valid, it will only be updated! }
+ case def_to.typ of
+ formaldef :
+ begin
+ { all types can be passed to a formaldef }
+ eq:=te_equal;
+ end;
+ stringdef :
+ begin
+ { to support ansi/long/wide strings in a proper way }
+ { string and string[10] are assumed as equal }
+ { when searching the correct overloaded procedure }
+ if (p.resultdef.typ=stringdef) and
+ (tstringdef(def_to).stringtype=tstringdef(p.resultdef).stringtype) then
+ eq:=te_equal
+ else
+ { Passing a constant char to ansistring or shortstring or
+ a widechar to widestring then handle it as equal. }
+ if (p.left.nodetype=ordconstn) and
+ (
+ is_char(p.resultdef) and
+ (is_shortstring(def_to) or is_ansistring(def_to))
+ ) or
+ (
+ is_widechar(p.resultdef) and
+ (is_widestring(def_to) or is_unicodestring(def_to))
+ ) then
+ eq:=te_equal
+ end;
+ setdef :
+ begin
+ { set can also be a not yet converted array constructor }
+ if (p.resultdef.typ=arraydef) and
+ is_array_constructor(p.resultdef) and
+ not is_variant_array(p.resultdef) then
+ eq:=te_equal;
+ end;
+ procvardef :
+ begin
+ tmpeq:=te_incompatible;
+ { in tp/macpas mode proc -> procvar is allowed }
+ if ((m_tp_procvar in current_settings.modeswitches) or
+ (m_mac_procvar in current_settings.modeswitches)) and
+ (p.left.nodetype=calln) then
+ tmpeq:=proc_to_procvar_equal(tprocdef(tcallnode(p.left).procdefinition),tprocvardef(def_to),false);
+ if (tmpeq=te_incompatible) and
+ (m_nested_procvars in current_settings.modeswitches) and
+ is_proc2procvar_load(p.left,realprocdef) then
+ tmpeq:=proc_to_procvar_equal(realprocdef,tprocvardef(def_to),false);
+ if (tmpeq=te_incompatible) and
+ (m_mac in current_settings.modeswitches) and
+ is_ambiguous_funcret_load(p.left,realprocdef) then
+ tmpeq:=proc_to_procvar_equal(realprocdef,tprocvardef(def_to),false);
+ if tmpeq<>te_incompatible then
+ eq:=tmpeq;
+ end;
+ arraydef :
+ begin
+ { an arrayconstructor of proccalls may have to be converted to
+ an array of procvars }
+ if ((m_tp_procvar in current_settings.modeswitches) or
+ (m_mac_procvar in current_settings.modeswitches)) and
+ (tarraydef(def_to).elementdef.typ=procvardef) and
+ is_array_constructor(p.resultdef) and
+ not is_variant_array(p.resultdef) then
+ begin
+ acn:=tarrayconstructornode(p.left);
+ if assigned(acn.left) then
+ begin
+ eq:=te_exact;
+ while assigned(acn) and
+ (eq<>te_incompatible) do
+ begin
+ if (acn.left.nodetype=calln) then
+ tmpeq:=proc_to_procvar_equal(tprocdef(tcallnode(acn.left).procdefinition),tprocvardef(tarraydef(def_to).elementdef),false)
+ else
+ tmpeq:=compare_defs(acn.left.resultdef,tarraydef(def_to).elementdef,acn.left.nodetype);
+ if tmpeq<eq then
+ eq:=tmpeq;
+ acn:=tarrayconstructornode(acn.right);
+ end;
+ end
+ end;
+ end;
+ end;
+ end;
+
+
+ function allowenumop(nt:tnodetype):boolean;
+ begin
+ result:=(nt in [equaln,unequaln,ltn,lten,gtn,gten]) or
+ ((cs_allow_enum_calc in current_settings.localswitches) and
+ (nt in [addn,subn]));
+ end;
+
+
+{****************************************************************************
+ TCallCandidates
+****************************************************************************}
+
+ constructor tcallcandidates.create(sym:tprocsym;st:TSymtable;ppn:tnode;ignorevisibility,allowdefaultparas,objcidcall,explicitunit,searchhelpers,anoninherited:boolean);
+ begin
+ if not assigned(sym) then
+ internalerror(200411015);
+ FOperator:=NOTOKEN;
+ FProcsym:=sym;
+ FProcsymtable:=st;
+ FParanode:=ppn;
+ create_candidate_list(ignorevisibility,allowdefaultparas,objcidcall,explicitunit,searchhelpers,anoninherited);
+ end;
+
+
+ constructor tcallcandidates.create_operator(op:ttoken;ppn:tnode);
+ begin
+ FOperator:=op;
+ FProcsym:=nil;
+ FProcsymtable:=nil;
+ FParanode:=ppn;
+ create_candidate_list(false,false,false,false,false,false);
+ end;
+
+
+ destructor tcallcandidates.destroy;
+ var
+ hpnext,
+ hp : pcandidate;
+ begin
+ hp:=FCandidateProcs;
+ while assigned(hp) do
+ begin
+ hpnext:=hp^.next;
+ dispose(hp);
+ hp:=hpnext;
+ end;
+ end;
+
+
+ procedure tcallcandidates.collect_overloads_in_struct(structdef:tabstractrecorddef;ProcdefOverloadList:TFPObjectList;searchhelpers,anoninherited:boolean);
+
+ function processprocsym(srsym:tprocsym; out foundanything: boolean):boolean;
+ var
+ j : integer;
+ pd : tprocdef;
+ begin
+ { add all definitions }
+ result:=false;
+ foundanything:=false;
+ for j:=0 to srsym.ProcdefList.Count-1 do
+ begin
+ pd:=tprocdef(srsym.ProcdefList[j]);
+ { in case of anonymous inherited, only match procdefs identical
+ to the current one (apart from hidden parameters), rather than
+ anything compatible to the parameters -- except in case of
+ the presence of a messagestr/int, in which case those have to
+ match exactly }
+ if anoninherited then
+ if po_msgint in current_procinfo.procdef.procoptions then
+ begin
+ if not(po_msgint in pd.procoptions) or
+ (pd.messageinf.i<>current_procinfo.procdef.messageinf.i) then
+ continue
+ end
+ else if po_msgstr in current_procinfo.procdef.procoptions then
+ begin
+ if not(po_msgstr in pd.procoptions) or
+ (pd.messageinf.str^<>current_procinfo.procdef.messageinf.str^) then
+ continue
+ end
+ else if (compare_paras(current_procinfo.procdef.paras,pd.paras,cp_all,[cpo_ignorehidden])<te_equal) then
+ continue;
+ foundanything:=true;
+ { Store first procsym found }
+ if not assigned(FProcsym) then
+ FProcsym:=tprocsym(srsym);
+ if po_overload in pd.procoptions then
+ result:=true;
+ ProcdefOverloadList.Add(srsym.ProcdefList[j]);
+ end;
+ end;
+
+ var
+ srsym : tsym;
+ hashedid : THashedIDString;
+ hasoverload,
+ foundanything : boolean;
+ helperdef : tobjectdef;
+ begin
+ if FOperator=NOTOKEN then
+ hashedid.id:=FProcsym.name
+ else
+ hashedid.id:=overloaded_names[FOperator];
+ hasoverload:=false;
+ while assigned(structdef) do
+ begin
+ { first search in helpers for this type }
+ if (is_class(structdef) or is_record(structdef))
+ and searchhelpers then
+ begin
+ if search_last_objectpascal_helper(structdef,nil,helperdef) then
+ begin
+ srsym:=nil;
+ while assigned(helperdef) do
+ begin
+ srsym:=tsym(helperdef.symtable.FindWithHash(hashedid));
+ if assigned(srsym) and
+ { Delphi allows hiding a property by a procedure with the same name }
+ (srsym.typ=procsym) then
+ begin
+ hasoverload:=processprocsym(tprocsym(srsym),foundanything);
+ { when there is no explicit overload we stop searching }
+ if foundanything and
+ not hasoverload then
+ break;
+ end;
+ helperdef:=helperdef.childof;
+ end;
+ if not hasoverload and assigned(srsym) then
+ exit;
+ end;
+ end;
+ { now search in the type itself }
+ srsym:=tprocsym(structdef.symtable.FindWithHash(hashedid));
+ if assigned(srsym) and
+ { Delphi allows hiding a property by a procedure with the same name }
+ (srsym.typ=procsym) then
+ begin
+ hasoverload:=processprocsym(tprocsym(srsym),foundanything);
+ { when there is no explicit overload we stop searching }
+ if foundanything and
+ not hasoverload then
+ break;
+ end;
+ if is_objectpascal_helper(structdef) and
+ (tobjectdef(structdef).typ in [recorddef,objectdef]) then
+ begin
+ { search methods in the extended type as well }
+ srsym:=tprocsym(tabstractrecorddef(tobjectdef(structdef).extendeddef).symtable.FindWithHash(hashedid));
+ if assigned(srsym) and
+ { Delphi allows hiding a property by a procedure with the same name }
+ (srsym.typ=procsym) then
+ begin
+ hasoverload:=processprocsym(tprocsym(srsym),foundanything);
+ { when there is no explicit overload we stop searching }
+ if foundanything and
+ not hasoverload then
+ break;
+ end;
+ end;
+ { next parent }
+ if (structdef.typ=objectdef) then
+ structdef:=tobjectdef(structdef).childof
+ else
+ structdef:=nil;
+ end;
+ end;
+
+
+ procedure tcallcandidates.collect_overloads_in_units(ProcdefOverloadList:TFPObjectList; objcidcall,explicitunit: boolean);
+ var
+ j : integer;
+ pd : tprocdef;
+ srsymtable : TSymtable;
+ srsym : tsym;
+ checkstack : psymtablestackitem;
+ hashedid : THashedIDString;
+ hasoverload : boolean;
+ begin
+ { we search all overloaded operator definitions in the symtablestack. The found
+ entries are only added to the procs list and not the procsym, because
+ the list can change in every situation }
+ if FOperator=NOTOKEN then
+ begin
+ if not objcidcall then
+ hashedid.id:=FProcsym.name
+ else
+ hashedid.id:=class_helper_prefix+FProcsym.name;
+ end
+ else
+ hashedid.id:=overloaded_names[FOperator];
+
+ checkstack:=symtablestack.stack;
+ if assigned(FProcsymtable) then
+ begin
+ while assigned(checkstack) and
+ (checkstack^.symtable<>FProcsymtable) do
+ checkstack:=checkstack^.next;
+ end;
+ while assigned(checkstack) do
+ begin
+ srsymtable:=checkstack^.symtable;
+ { if the unit in which the routine has to be searched has been
+ specified explicitly, stop searching after its symtable(s) have
+ been checked (can be both the static and the global symtable
+ in case it's the current unit itself) }
+ if explicitunit and
+ (FProcsymtable.symtabletype in [globalsymtable,staticsymtable]) and
+ (srsymtable.moduleid<>FProcsymtable.moduleid) then
+ break;
+ if srsymtable.symtabletype in [localsymtable,staticsymtable,globalsymtable] then
+ begin
+ srsym:=tsym(srsymtable.FindWithHash(hashedid));
+ if assigned(srsym) and
+ (srsym.typ=procsym) then
+ begin
+ { Store first procsym found }
+ if not assigned(FProcsym) then
+ FProcsym:=tprocsym(srsym);
+ { add all definitions }
+ hasoverload:=false;
+ for j:=0 to tprocsym(srsym).ProcdefList.Count-1 do
+ begin
+ pd:=tprocdef(tprocsym(srsym).ProcdefList[j]);
+ if po_overload in pd.procoptions then
+ hasoverload:=true;
+ ProcdefOverloadList.Add(tprocsym(srsym).ProcdefList[j]);
+ end;
+ { when there is no explicit overload we stop searching,
+ except for Objective-C methods called via id }
+ if not hasoverload and
+ not objcidcall then
+ break;
+ end;
+ end;
+ checkstack:=checkstack^.next
+ end;
+ end;
+
+
+ procedure tcallcandidates.create_candidate_list(ignorevisibility,allowdefaultparas,objcidcall,explicitunit,searchhelpers,anoninherited:boolean);
+ var
+ j : integer;
+ pd : tprocdef;
+ hp : pcandidate;
+ pt : tcallparanode;
+ found : boolean;
+ st : TSymtable;
+ contextstructdef : tabstractrecorddef;
+ ProcdefOverloadList : TFPObjectList;
+ cpoptions : tcompare_paras_options;
+ begin
+ FCandidateProcs:=nil;
+
+ { Find all available overloads for this procsym }
+ ProcdefOverloadList:=TFPObjectList.Create(false);
+ if not objcidcall and
+ (FOperator=NOTOKEN) and
+ (FProcsym.owner.symtabletype in [objectsymtable,recordsymtable]) then
+ collect_overloads_in_struct(tabstractrecorddef(FProcsym.owner.defowner),ProcdefOverloadList,searchhelpers,anoninherited)
+ else
+ if (FOperator<>NOTOKEN) then
+ begin
+ { check operands and if they contain records then search in records,
+ then search in unit }
+ pt:=tcallparanode(FParaNode);
+ while assigned(pt) do
+ begin
+ if (pt.resultdef.typ=recorddef) then
+ collect_overloads_in_struct(tabstractrecorddef(pt.resultdef),ProcdefOverloadList,searchhelpers,anoninherited);
+ pt:=tcallparanode(pt.right);
+ end;
+ collect_overloads_in_units(ProcdefOverloadList,objcidcall,explicitunit);
+ end
+ else
+ collect_overloads_in_units(ProcdefOverloadList,objcidcall,explicitunit);
+
+ { determine length of parameter list.
+ for operators also enable the variant-operators if
+ a variant parameter is passed }
+ FParalength:=0;
+ FAllowVariant:=(FOperator=NOTOKEN);
+ pt:=tcallparanode(FParaNode);
+ while assigned(pt) do
+ begin
+ if (pt.resultdef.typ=variantdef) then
+ FAllowVariant:=true;
+ inc(FParalength);
+ pt:=tcallparanode(pt.right);
+ end;
+
+ { when the class passed is defined in this unit we
+ need to use the scope of that class. This is a trick
+ that can be used to access protected members in other
+ units. At least kylix supports it this way (PFV) }
+ if assigned(FProcSymtable) and
+ (
+ (FProcSymtable.symtabletype in [ObjectSymtable,recordsymtable]) or
+ ((FProcSymtable.symtabletype=withsymtable) and
+ (FProcSymtable.defowner.typ in [objectdef,recorddef]))
+ ) and
+ (FProcSymtable.defowner.owner.symtabletype in [globalsymtable,staticsymtable,objectsymtable,recordsymtable]) and
+ FProcSymtable.defowner.owner.iscurrentunit then
+ contextstructdef:=tabstractrecorddef(FProcSymtable.defowner)
+ else
+ contextstructdef:=current_structdef;
+
+ { symtable is needed later to calculate the distance }
+ if assigned(FProcsym) then
+ st:=FProcsym.Owner
+ else
+ st:=nil;
+ { Process all found overloads }
+ for j:=0 to ProcdefOverloadList.Count-1 do
+ begin
+ pd:=tprocdef(ProcdefOverloadList[j]);
+
+ { only when the # of parameter are supported by the procedure and
+ it is visible }
+ if (FParalength>=pd.minparacount) and
+ (
+ (
+ allowdefaultparas and
+ (
+ (FParalength<=pd.maxparacount) or
+ (po_varargs in pd.procoptions)
+ )
+ ) or
+ (
+ not allowdefaultparas and
+ (FParalength=pd.maxparacount)
+ )
+ ) and
+ (
+ ignorevisibility or
+ not (pd.owner.symtabletype in [objectsymtable,recordsymtable]) or
+ is_visible_for_object(pd,contextstructdef)
+ ) then
+ begin
+ { don't add duplicates, only compare visible parameters for the user }
+ cpoptions:=[cpo_ignorehidden];
+ if (po_compilerproc in pd.procoptions) then
+ cpoptions:=cpoptions+[cpo_compilerproc];
+ if (po_rtlproc in pd.procoptions) then
+ cpoptions:=cpoptions+[cpo_rtlproc];
+ found:=false;
+ hp:=FCandidateProcs;
+ while assigned(hp) do
+ begin
+ if (compare_paras(hp^.data.paras,pd.paras,cp_value_equal_const,cpoptions)>=te_equal) and
+ (not(po_objc in pd.procoptions) or
+ (pd.messageinf.str^=hp^.data.messageinf.str^)) then
+ begin
+ found:=true;
+ break;
+ end;
+ hp:=hp^.next;
+ end;
+ if not found then
+ proc_add(st,pd,objcidcall);
+ end;
+ end;
+
+ ProcdefOverloadList.Free;
+ end;
+
+
+ function tcallcandidates.proc_add(st:tsymtable;pd:tprocdef;objcidcall: boolean):pcandidate;
+ var
+ defaultparacnt : integer;
+ begin
+ { generate new candidate entry }
+ new(result);
+ fillchar(result^,sizeof(tcandidate),0);
+ result^.data:=pd;
+ result^.next:=FCandidateProcs;
+ FCandidateProcs:=result;
+ inc(FProccnt);
+ { Find last parameter, skip all default parameters
+ that are not passed. Ignore this skipping for varargs }
+ result^.firstparaidx:=pd.paras.count-1;
+ if not(po_varargs in pd.procoptions) then
+ begin
+ { ignore hidden parameters }
+ while (result^.firstparaidx>=0) and (vo_is_hidden_para in tparavarsym(pd.paras[result^.firstparaidx]).varoptions) do
+ dec(result^.firstparaidx);
+ defaultparacnt:=pd.maxparacount-FParalength;
+ if defaultparacnt>0 then
+ begin
+ if defaultparacnt>result^.firstparaidx+1 then
+ internalerror(200401141);
+ dec(result^.firstparaidx,defaultparacnt);
+ end;
+ end;
+ { Give a small penalty for overloaded methods not in
+ defined the current class/unit }
+ { when calling Objective-C methods via id.method, then the found
+ procsym will be inside an arbitrary ObjectSymtable, and we don't
+ want togive the methods of that particular objcclass precedence over
+ other methods, so instead check against the symtable in which this
+ objcclass is defined }
+ if objcidcall then
+ st:=st.defowner.owner;
+ if (st<>pd.owner) then
+ result^.ordinal_distance:=result^.ordinal_distance+1.0;
+ end;
+
+
+ procedure tcallcandidates.list(all:boolean);
+ var
+ hp : pcandidate;
+ begin
+ hp:=FCandidateProcs;
+ while assigned(hp) do
+ begin
+ if all or
+ (not hp^.invalid) then
+ MessagePos1(hp^.data.fileinfo,sym_h_param_list,hp^.data.fullprocname(false));
+ hp:=hp^.next;
+ end;
+ end;
+
+
+{$ifdef EXTDEBUG}
+ procedure tcallcandidates.dump_info(lvl:longint);
+
+ function ParaTreeStr(p:tcallparanode):string;
+ begin
+ result:='';
+ while assigned(p) do
+ begin
+ if result<>'' then
+ result:=','+result;
+ result:=p.resultdef.typename+result;
+ p:=tcallparanode(p.right);
+ end;
+ end;
+
+ var
+ hp : pcandidate;
+ i : integer;
+ currpara : tparavarsym;
+ begin
+ if not CheckVerbosity(lvl) then
+ exit;
+ Comment(lvl+V_LineInfo,'Overloaded callnode: '+FProcsym.name+'('+ParaTreeStr(tcallparanode(FParaNode))+')');
+ hp:=FCandidateProcs;
+ while assigned(hp) do
+ begin
+ Comment(lvl,' '+hp^.data.fullprocname(false));
+ if (hp^.invalid) then
+ Comment(lvl,' invalid')
+ else
+ begin
+ Comment(lvl,' ex: '+tostr(hp^.exact_count)+
+ ' eq: '+tostr(hp^.equal_count)+
+ ' l1: '+tostr(hp^.cl1_count)+
+ ' l2: '+tostr(hp^.cl2_count)+
+ ' l3: '+tostr(hp^.cl3_count)+
+ ' l4: '+tostr(hp^.cl4_count)+
+ ' l5: '+tostr(hp^.cl5_count)+
+ ' oper: '+tostr(hp^.coper_count)+
+ ' ord: '+realtostr(hp^.ordinal_distance));
+ { Print parameters in left-right order }
+ for i:=0 to hp^.data.paras.count-1 do
+ begin
+ currpara:=tparavarsym(hp^.data.paras[i]);
+ if not(vo_is_hidden_para in currpara.varoptions) then
+ Comment(lvl,' - '+currpara.vardef.typename+' : '+EqualTypeName[currpara.eqval]);
+ end;
+ end;
+ hp:=hp^.next;
+ end;
+ end;
+{$endif EXTDEBUG}
+
+
+ procedure tcallcandidates.get_information;
+ var
+ hp : pcandidate;
+ currpara : tparavarsym;
+ paraidx : integer;
+ currparanr : byte;
+ rfh,rth : double;
+ objdef : tobjectdef;
+ def_from,
+ def_to : tdef;
+ currpt,
+ pt : tcallparanode;
+ eq : tequaltype;
+ convtype : tconverttype;
+ pdtemp,
+ pdoper : tprocdef;
+ releasecurrpt : boolean;
+ cdoptions : tcompare_defs_options;
+ n : tnode;
+
+ {$push}
+ {$r-}
+ {$q-}
+ const
+ inf=1.0/0.0;
+ {$pop}
+ begin
+ cdoptions:=[cdo_check_operator];
+ if FAllowVariant then
+ include(cdoptions,cdo_allow_variant);
+ { process all procs }
+ hp:=FCandidateProcs;
+ while assigned(hp) do
+ begin
+ { We compare parameters in reverse order (right to left),
+ the firstpara is already pointing to the last parameter
+ were we need to start comparing }
+ currparanr:=FParalength;
+ paraidx:=hp^.firstparaidx;
+ while (paraidx>=0) and (vo_is_hidden_para in tparavarsym(hp^.data.paras[paraidx]).varoptions) do
+ dec(paraidx);
+ pt:=tcallparanode(FParaNode);
+ while assigned(pt) and (paraidx>=0) do
+ begin
+ currpara:=tparavarsym(hp^.data.paras[paraidx]);
+ { currpt can be changed from loadn to calln when a procvar
+ is passed. This is to prevent that the change is permanent }
+ currpt:=pt;
+ releasecurrpt:=false;
+ { retrieve current parameter definitions to compares }
+ eq:=te_incompatible;
+ def_from:=currpt.resultdef;
+ def_to:=currpara.vardef;
+ if not(assigned(def_from)) then
+ internalerror(200212091);
+ if not(
+ assigned(def_to) or
+ ((po_varargs in hp^.data.procoptions) and
+ (currparanr>hp^.data.minparacount))
+ ) then
+ internalerror(200212092);
+
+ { Convert tp procvars when not expecting a procvar }
+ if (currpt.left.resultdef.typ=procvardef) and
+ not(def_to.typ in [procvardef,formaldef]) and
+ { Only convert to call when there is no overload or the return type
+ is equal to the expected type. }
+ (
+ (count=1) or
+ equal_defs(tprocvardef(currpt.left.resultdef).returndef,def_to)
+ ) then
+ begin
+ releasecurrpt:=true;
+ currpt:=tcallparanode(pt.getcopy);
+ if maybe_call_procvar(currpt.left,true) then
+ begin
+ currpt.resultdef:=currpt.left.resultdef;
+ def_from:=currpt.left.resultdef;
+ end;
+ end;
+
+ { If we expect a procvar and the left is loadnode that
+ returns a procdef we need to find the correct overloaded
+ procdef that matches the expected procvar. The loadnode
+ temporary returned the first procdef (PFV) }
+ if (def_to.typ=procvardef) and
+ (currpt.left.nodetype=loadn) and
+ (currpt.left.resultdef.typ=procdef) then
+ begin
+ pdtemp:=tprocsym(Tloadnode(currpt.left).symtableentry).Find_procdef_byprocvardef(Tprocvardef(def_to));
+ if assigned(pdtemp) then
+ begin
+ tloadnode(currpt.left).setprocdef(pdtemp);
+ currpt.resultdef:=currpt.left.resultdef;
+ def_from:=currpt.left.resultdef;
+ end;
+ end;
+
+ { varargs are always equal, but not exact }
+ if (po_varargs in hp^.data.procoptions) and
+ (currparanr>hp^.data.minparacount) and
+ not is_array_of_const(def_from) and
+ not is_array_constructor(def_from) then
+ eq:=te_equal
+ else
+ { same definition -> exact }
+ if (def_from=def_to) then
+ eq:=te_exact
+ else
+ { for value and const parameters check if a integer is constant or
+ included in other integer -> equal and calc ordinal_distance }
+ if not(currpara.varspez in [vs_var,vs_out]) and
+ is_integer(def_from) and
+ is_integer(def_to) and
+ is_in_limit(def_from,def_to) then
+ begin
+ eq:=te_equal;
+ hp^.ordinal_distance:=hp^.ordinal_distance+
+ abs(bestreal(torddef(def_from).low)-bestreal(torddef(def_to).low));
+ rth:=bestreal(torddef(def_to).high);
+ rfh:=bestreal(torddef(def_from).high);
+ hp^.ordinal_distance:=hp^.ordinal_distance+abs(rth-rfh);
+ { Give wrong sign a small penalty, this is need to get a diffrence
+ from word->[longword,longint] }
+ if is_signed(def_from)<>is_signed(def_to) then
+{$push}
+{$r-}
+{$q-}
+ hp^.ordinal_distance:=nextafter(hp^.ordinal_distance,inf);
+{$pop}
+ end
+ else
+ { for value and const parameters check precision of real, give
+ penalty for loosing of precision. var and out parameters must match exactly }
+ if not(currpara.varspez in [vs_var,vs_out]) and
+ is_real(def_from) and
+ is_real(def_to) then
+ begin
+ eq:=te_equal;
+ if is_extended(def_to) then
+ rth:=4
+ else
+ if is_double (def_to) then
+ rth:=2
+ else
+ rth:=1;
+ if is_extended(def_from) then
+ rfh:=4
+ else
+ if is_double (def_from) then
+ rfh:=2
+ else
+ rfh:=1;
+ { penalty for shrinking of precision }
+ if rth<rfh then
+ rfh:=(rfh-rth)*16
+ else
+ rfh:=rth-rfh;
+ hp^.ordinal_distance:=hp^.ordinal_distance+rfh;
+ end
+ else
+ { related object parameters also need to determine the distance between the current
+ object and the object we are comparing with. var and out parameters must match exactly }
+ if not(currpara.varspez in [vs_var,vs_out]) and
+ (def_from.typ=objectdef) and
+ (def_to.typ=objectdef) and
+ (tobjectdef(def_from).objecttype=tobjectdef(def_to).objecttype) and
+ tobjectdef(def_from).is_related(tobjectdef(def_to)) then
+ begin
+ eq:=te_convert_l1;
+ objdef:=tobjectdef(def_from);
+ while assigned(objdef) do
+ begin
+ if objdef=def_to then
+ break;
+ hp^.ordinal_distance:=hp^.ordinal_distance+1;
+ objdef:=objdef.childof;
+ end;
+ end
+ { compare_defs_ext compares sets and array constructors very poorly because
+ it has too little information. So we do explicitly a detailed comparisation,
+ see also bug #11288 (FK)
+ }
+ else if (def_to.typ=setdef) and is_array_constructor(currpt.left.resultdef) then
+ begin
+ n:=currpt.left.getcopy;
+ arrayconstructor_to_set(n);
+ eq:=compare_defs_ext(n.resultdef,def_to,n.nodetype,convtype,pdoper,cdoptions);
+ n.free;
+ end
+ else
+ { generic type comparision }
+ begin
+ if not(po_compilerproc in hp^.data.procoptions) and
+ not(po_rtlproc in hp^.data.procoptions) and
+ is_ansistring(currpara.vardef) and
+ is_ansistring(currpt.left.resultdef) and
+ (tstringdef(currpara.vardef).encoding<>tstringdef(currpt.left.resultdef).encoding) and
+ ((tstringdef(currpara.vardef).encoding=globals.CP_NONE) or
+ (tstringdef(currpt.left.resultdef).encoding=globals.CP_NONE)
+ ) then
+ eq:=te_convert_l1
+ else
+ eq:=compare_defs_ext(def_from,def_to,currpt.left.nodetype,convtype,pdoper,cdoptions);
+
+ { when the types are not equal we need to check
+ some special case for parameter passing }
+ if (eq<te_equal) then
+ begin
+ if currpara.varspez in [vs_var,vs_out] then
+ begin
+ { para requires an equal type so the previous found
+ match was not good enough, reset to incompatible }
+ eq:=te_incompatible;
+ { var_para_allowed will return te_equal and te_convert_l1 to
+ make a difference for best matching }
+ var_para_allowed(eq,currpt.resultdef,currpara.vardef,currpt.left)
+ end
+ else
+ para_allowed(eq,currpt,def_to);
+ end;
+ end;
+
+ { univ parameters match if the size matches (don't override the
+ comparison result if it was ok, since a match based on the
+ "univ" character is the lowest possible match) }
+ if (eq=te_incompatible) and
+ currpara.univpara and
+ is_valid_univ_para_type(def_from) and
+ (def_from.size=def_to.size) then
+ eq:=te_convert_l5;
+
+ { when a procvar was changed to a call an exact match is
+ downgraded to equal. This way an overload call with the
+ procvar is choosen. See tb0471 (PFV) }
+ if (pt<>currpt) and (eq=te_exact) then
+ eq:=te_equal;
+
+ { increase correct counter }
+ case eq of
+ te_exact :
+ inc(hp^.exact_count);
+ te_equal :
+ inc(hp^.equal_count);
+ te_convert_l1 :
+ inc(hp^.cl1_count);
+ te_convert_l2 :
+ inc(hp^.cl2_count);
+ te_convert_l3 :
+ inc(hp^.cl3_count);
+ te_convert_l4 :
+ inc(hp^.cl4_count);
+ te_convert_l5 :
+ inc(hp^.cl5_count);
+ te_convert_operator :
+ inc(hp^.coper_count);
+ te_incompatible :
+ hp^.invalid:=true;
+ else
+ internalerror(200212072);
+ end;
+
+ { stop checking when an incompatible parameter is found }
+ if hp^.invalid then
+ begin
+ { store the current parameter info for
+ a nice error message when no procedure is found }
+ hp^.wrongparaidx:=paraidx;
+ hp^.wrongparanr:=currparanr;
+ break;
+ end;
+
+{$ifdef EXTDEBUG}
+ { store equal in node tree for dump }
+ currpara.eqval:=eq;
+{$endif EXTDEBUG}
+
+ { maybe release temp currpt }
+ if releasecurrpt then
+ currpt.free;
+
+ { next parameter in the call tree }
+ pt:=tcallparanode(pt.right);
+
+ { next parameter for definition, only goto next para
+ if we're out of the varargs }
+ if not(po_varargs in hp^.data.procoptions) or
+ (currparanr<=hp^.data.maxparacount) then
+ begin
+ { Ignore vs_hidden parameters }
+ repeat
+ dec(paraidx);
+ until (paraidx<0) or not(vo_is_hidden_para in tparavarsym(hp^.data.paras[paraidx]).varoptions);
+ end;
+ dec(currparanr);
+ end;
+ if not(hp^.invalid) and
+ (assigned(pt) or (paraidx>=0) or (currparanr<>0)) then
+ internalerror(200212141);
+ { next candidate }
+ hp:=hp^.next;
+ end;
+ end;
+
+
+ function get_variantequaltype(def: tdef): tvariantequaltype;
+ const
+ variantorddef_cl: array[tordtype] of tvariantequaltype =
+ (tve_incompatible,tve_byte,tve_word,tve_cardinal,tve_chari64,
+ tve_shortint,tve_smallint,tve_longint,tve_chari64,
+ tve_boolformal,tve_boolformal,tve_boolformal,tve_boolformal,
+ tve_boolformal,tve_boolformal,tve_boolformal,tve_boolformal,
+ tve_chari64,tve_chari64,tve_dblcurrency);
+{ TODO: fixme for 128 bit floats }
+ variantfloatdef_cl: array[tfloattype] of tvariantequaltype =
+ (tve_single,tve_dblcurrency,tve_extended,tve_extended,
+ tve_dblcurrency,tve_dblcurrency,tve_extended);
+ variantstringdef_cl: array[tstringtype] of tvariantequaltype =
+ (tve_sstring,tve_astring,tve_astring,tve_wstring,tve_ustring);
+ begin
+ case def.typ of
+ orddef:
+ begin
+ result:=variantorddef_cl[torddef(def).ordtype];
+ end;
+ floatdef:
+ begin
+ result:=variantfloatdef_cl[tfloatdef(def).floattype];
+ end;
+ stringdef:
+ begin
+ result:=variantstringdef_cl[tstringdef(def).stringtype];
+ end;
+ formaldef:
+ begin
+ result:=tve_boolformal;
+ end;
+ else
+ begin
+ result:=tve_incompatible;
+ end;
+ end
+ end;
+
+
+ function is_better_candidate(currpd,bestpd:pcandidate):integer;
+ var
+ res : integer;
+ begin
+ {
+ Return values:
+ > 0 when currpd is better than bestpd
+ < 0 when bestpd is better than currpd
+ = 0 when both are equal
+
+ To choose the best candidate we use the following order:
+ - Incompatible flag
+ - (Smaller) Number of convert operator parameters.
+ - (Smaller) Number of convertlevel 2 parameters.
+ - (Smaller) Number of convertlevel 1 parameters.
+ - (Bigger) Number of exact parameters.
+ - (Smaller) Number of equal parameters.
+ - (Smaller) Total of ordinal distance. For example, the distance of a word
+ to a byte is 65535-255=65280.
+ }
+ if bestpd^.invalid then
+ begin
+ if currpd^.invalid then
+ res:=0
+ else
+ res:=1;
+ end
+ else
+ if currpd^.invalid then
+ res:=-1
+ else
+ begin
+ { less operator parameters? }
+ res:=(bestpd^.coper_count-currpd^.coper_count);
+ if (res=0) then
+ begin
+ { less cl5 parameters? }
+ res:=(bestpd^.cl5_count-currpd^.cl5_count);
+ if (res=0) then
+ begin
+ { less cl4 parameters? }
+ res:=(bestpd^.cl4_count-currpd^.cl4_count);
+ if (res=0) then
+ begin
+ { less cl3 parameters? }
+ res:=(bestpd^.cl3_count-currpd^.cl3_count);
+ if (res=0) then
+ begin
+ { less cl2 parameters? }
+ res:=(bestpd^.cl2_count-currpd^.cl2_count);
+ if (res=0) then
+ begin
+ { less cl1 parameters? }
+ res:=(bestpd^.cl1_count-currpd^.cl1_count);
+ if (res=0) then
+ begin
+ { more exact parameters? }
+ res:=(currpd^.exact_count-bestpd^.exact_count);
+ if (res=0) then
+ begin
+ { less equal parameters? }
+ res:=(bestpd^.equal_count-currpd^.equal_count);
+ if (res=0) then
+ begin
+ { smaller ordinal distance? }
+ if (currpd^.ordinal_distance<bestpd^.ordinal_distance) then
+ res:=1
+ else
+ if (currpd^.ordinal_distance>bestpd^.ordinal_distance) then
+ res:=-1
+ else
+ res:=0;
+ end;
+ end;
+ end;
+ end;
+ end;
+ end;
+ end;
+ end;
+ end;
+ is_better_candidate:=res;
+ end;
+
+
+{ Delphi precedence rules extracted from test programs. Only valid if passing
+ a variant parameter to overloaded procedures expecting exactly one parameter.
+
+ single > (char, currency, int64, shortstring, ansistring, widestring, extended, double)
+ double/currency > (char, int64, shortstring, ansistring, widestring, extended)
+ extended > (char, int64, shortstring, ansistring, widestring)
+ longint/cardinal > (int64, shortstring, ansistring, widestring, extended, double, single, char, currency)
+ smallint > (longint, int64, shortstring, ansistring, widestring, extended, double single, char, currency);
+ word > (longint, cardinal, int64, shortstring, ansistring, widestring, extended, double single, char, currency);
+ shortint > (longint, smallint, int64, shortstring, ansistring, widestring, extended, double, single, char, currency)
+ byte > (longint, cardinal, word, smallint, int64, shortstring, ansistring, widestring, extended, double, single, char, currency);
+ boolean/formal > (char, int64, shortstring, ansistring, widestring)
+ shortstring > (char, int64, ansistring, widestring)
+ ansistring > (char, int64, widestring)
+ widestring > (char, int64)
+
+ Relations not mentioned mean that they conflict: no decision possible }
+
+ function is_better_candidate_single_variant(currpd,bestpd:pcandidate):integer;
+
+ function calculate_relation(const currvcl, bestvcl, testvcl:
+ tvariantequaltype; const conflictvcls: tvariantequaltypes):integer;
+ begin
+ { if (bestvcl=conflictvcl) or
+ (currvcl=conflictvcl) then
+ result:=0
+ else if (bestvcl=testvcl) then
+ result:=-1
+ else result:=1 }
+ result:=1-2*ord(bestvcl=testvcl)+
+ ord(currvcl in conflictvcls)-ord(bestvcl in conflictvcls);
+ end;
+
+
+ function getfirstrealparaidx(pd: pcandidate): integer;
+ begin
+ { can be different for currpd and bestpd in case of overloaded }
+ { functions, e.g. lowercase():char and lowercase():shortstring }
+ { (depending on the calling convention and parameter order) }
+ result:=pd^.firstparaidx;
+ while (result>=0) and (vo_is_hidden_para in tparavarsym(pd^.data.paras[result]).varoptions) do
+ dec(result);
+ if (vo_is_hidden_para in tparavarsym(pd^.data.paras[result]).varoptions) then
+ internalerror(2006122803);
+ end;
+
+ var
+ currpara, bestpara: tparavarsym;
+ currvcl, bestvcl: tvariantequaltype;
+ begin
+ {
+ Return values:
+ > 0 when currpd is better than bestpd
+ < 0 when bestpd is better than currpd
+ = 0 when both are equal
+ }
+ currpara:=tparavarsym(currpd^.data.paras[getfirstrealparaidx(currpd)]);
+ bestpara:=tparavarsym(bestpd^.data.paras[getfirstrealparaidx(bestpd)]);
+
+ { if one of the parameters is a regular variant, fall back to the }
+ { default algorithm }
+ if (currpara.vardef.typ = variantdef) or
+ (bestpara.vardef.typ = variantdef) then
+ begin
+ result:=is_better_candidate(currpd,bestpd);
+ exit;
+ end;
+
+ currvcl:=get_variantequaltype(currpara.vardef);
+ bestvcl:=get_variantequaltype(bestpara.vardef);
+
+ { sanity check }
+ result:=-5;
+
+ { if both are the same, there is a conflict }
+ if (currvcl=bestvcl) then
+ result:=0
+ { if one of the two cannot be used as variant, the other is better }
+ else if (bestvcl=tve_incompatible) then
+ result:=1
+ else if (currvcl=tve_incompatible) then
+ result:=-1
+ { boolean and formal are better than chari64str, but conflict with }
+ { everything else }
+ else if (currvcl=tve_boolformal) or
+ (bestvcl=tve_boolformal) then
+ if (currvcl=tve_boolformal) then
+ result:=ord(bestvcl in [tve_chari64,tve_sstring,tve_astring,tve_wstring,tve_ustring])
+ else
+ result:=-ord(currvcl in [tve_chari64,tve_sstring,tve_astring,tve_wstring,tve_ustring])
+ { byte is better than everything else (we assume both aren't byte, }
+ { since there's only one parameter and that one can't be the same) }
+ else if (currvcl=tve_byte) or
+ (bestvcl=tve_byte) then
+ result:=calculate_relation(currvcl,bestvcl,tve_byte,[tve_shortint])
+ { shortint conflicts with word and cardinal, but is better than }
+ { everything else but byte (which has already been handled) }
+ else if (currvcl=tve_shortint) or
+ (bestvcl=tve_shortint) then
+ result:=calculate_relation(currvcl,bestvcl,tve_shortint,[tve_word, tve_cardinal])
+ { word conflicts with smallint, but is better than everything else }
+ { but shortint and byte (which has already been handled) }
+ else if (currvcl=tve_word) or
+ (bestvcl=tve_word) then
+ result:=calculate_relation(currvcl,bestvcl,tve_word,[tve_smallint])
+ { smallint conflicts with cardinal, but is better than everything }
+ { which has not yet been tested }
+ else if (currvcl=tve_smallint) or
+ (bestvcl=tve_smallint) then
+ result:=calculate_relation(currvcl,bestvcl,tve_smallint,[tve_cardinal])
+ { cardinal conflicts with each longint and is better than everything }
+ { which has not yet been tested }
+ else if (currvcl=tve_cardinal) or
+ (bestvcl=tve_cardinal) then
+ result:=calculate_relation(currvcl,bestvcl,tve_cardinal,[tve_longint])
+ { longint is better than everything which has not yet been tested }
+ else if (currvcl=tve_longint) or
+ (bestvcl=tve_longint) then
+ { if bestvcl=tve_longint then
+ result:=-1
+ else
+ result:=1 }
+ result:=1-2*ord(bestvcl=tve_longint)
+ { single is better than everything left }
+ else if (currvcl=tve_single) or
+ (bestvcl=tve_single) then
+ result:=1-2*ord(bestvcl=tve_single)
+ { double/comp/currency are better than everything left, and conflict }
+ { with each other (but that's already tested) }
+ else if (currvcl=tve_dblcurrency) or
+ (bestvcl=tve_dblcurrency) then
+ result:=1-2*ord(bestvcl=tve_dblcurrency)
+ { extended is better than everything left }
+ else if (currvcl=tve_extended) or
+ (bestvcl=tve_extended) then
+ result:=1-2*ord(bestvcl=tve_extended)
+ { shortstring is better than everything left }
+ else if (currvcl=tve_sstring) or
+ (bestvcl=tve_sstring) then
+ result:=1-2*ord(bestvcl=tve_sstring)
+ { ansistring is better than everything left }
+ else if (currvcl=tve_astring) or
+ (bestvcl=tve_astring) then
+ result:=1-2*ord(bestvcl=tve_astring)
+ { widestring is better than everything left }
+ else if (currvcl=tve_wstring) or
+ (bestvcl=tve_wstring) then
+ result:=1-2*ord(bestvcl=tve_wstring)
+ { unicodestring is better than everything left }
+ else if (currvcl=tve_ustring) or
+ (bestvcl=tve_ustring) then
+ result:=1-2*ord(bestvcl=tve_ustring);
+
+ { all possibilities should have been checked now }
+ if (result=-5) then
+ internalerror(2006122805);
+ end;
+
+
+ function tcallcandidates.choose_best(var bestpd:tabstractprocdef; singlevariant: boolean):integer;
+ var
+ besthpstart,
+ hp : pcandidate;
+ cntpd,
+ res : integer;
+ begin
+ {
+ Returns the number of candidates left and the
+ first candidate is returned in pdbest
+ }
+ { Setup the first procdef as best, only count it as a result
+ when it is valid }
+ bestpd:=FCandidateProcs^.data;
+ if FCandidateProcs^.invalid then
+ cntpd:=0
+ else
+ cntpd:=1;
+ if assigned(FCandidateProcs^.next) then
+ begin
+ besthpstart:=FCandidateProcs;
+ hp:=FCandidateProcs^.next;
+ while assigned(hp) do
+ begin
+ if not singlevariant then
+ res:=is_better_candidate(hp,besthpstart)
+ else
+ res:=is_better_candidate_single_variant(hp,besthpstart);
+ if (res>0) then
+ begin
+ { hp is better, flag all procs to be incompatible }
+ while (besthpstart<>hp) do
+ begin
+ besthpstart^.invalid:=true;
+ besthpstart:=besthpstart^.next;
+ end;
+ { besthpstart is already set to hp }
+ bestpd:=besthpstart^.data;
+ cntpd:=1;
+ end
+ else
+ if (res<0) then
+ begin
+ { besthpstart is better, flag current hp to be incompatible }
+ hp^.invalid:=true;
+ end
+ else
+ begin
+ { res=0, both are valid }
+ if not hp^.invalid then
+ inc(cntpd);
+ end;
+ hp:=hp^.next;
+ end;
+ end;
+
+ result:=cntpd;
+ end;
+
+
+ procedure tcallcandidates.find_wrong_para;
+ var
+ currparanr : smallint;
+ hp : pcandidate;
+ pt : tcallparanode;
+ wrongpara : tparavarsym;
+ begin
+ { Only process the first overloaded procdef }
+ hp:=FCandidateProcs;
+ { Find callparanode corresponding to the argument }
+ pt:=tcallparanode(FParanode);
+ currparanr:=FParalength;
+ while assigned(pt) and
+ (currparanr>hp^.wrongparanr) do
+ begin
+ pt:=tcallparanode(pt.right);
+ dec(currparanr);
+ end;
+ if (currparanr<>hp^.wrongparanr) or
+ not assigned(pt) then
+ internalerror(200212094);
+ { Show error message, when it was a var or out parameter
+ guess that it is a missing typeconv }
+ wrongpara:=tparavarsym(hp^.data.paras[hp^.wrongparaidx]);
+ if wrongpara.varspez in [vs_var,vs_out] then
+ begin
+ { Maybe passing the correct type but passing a const to var parameter }
+ if (compare_defs(pt.resultdef,wrongpara.vardef,pt.nodetype)<>te_incompatible) and
+ not valid_for_var(pt.left,true) then
+ CGMessagePos(pt.left.fileinfo,type_e_variable_id_expected)
+ else
+ CGMessagePos3(pt.left.fileinfo,parser_e_call_by_ref_without_typeconv,tostr(hp^.wrongparanr),
+ FullTypeName(pt.left.resultdef,wrongpara.vardef),
+ FullTypeName(wrongpara.vardef,pt.left.resultdef))
+ end
+ else
+ CGMessagePos3(pt.left.fileinfo,type_e_wrong_parameter_type,tostr(hp^.wrongparanr),
+ FullTypeName(pt.left.resultdef,wrongpara.vardef),
+ FullTypeName(wrongpara.vardef,pt.left.resultdef));
+ end;
+
+
+ procedure check_hints(const srsym: tsym; const symoptions: tsymoptions; const deprecatedmsg : pshortstring);
+ begin
+ if not assigned(srsym) then
+ internalerror(200602051);
+ if sp_hint_deprecated in symoptions then
+ if (sp_has_deprecated_msg in symoptions) and (deprecatedmsg <> nil) then
+ Message2(sym_w_deprecated_symbol_with_msg,srsym.realname,deprecatedmsg^)
+ else
+ Message1(sym_w_deprecated_symbol,srsym.realname);
+ if sp_hint_experimental in symoptions then
+ Message1(sym_w_experimental_symbol,srsym.realname);
+ if sp_hint_platform in symoptions then
+ Message1(sym_w_non_portable_symbol,srsym.realname);
+ if sp_hint_library in symoptions then
+ Message1(sym_w_library_symbol,srsym.realname);
+ if sp_hint_unimplemented in symoptions then
+ Message1(sym_w_non_implemented_symbol,srsym.realname);
+ end;
+
+
+ procedure check_ranges(const location: tfileposinfo; source: tnode; destdef: tdef);
+ begin
+ if not(cs_check_ordinal_size in current_settings.localswitches) then
+ exit;
+ { check if the assignment may cause a range check error }
+ { if its not explicit, and only if the values are }
+ { ordinals, enumdef and floatdef }
+ if assigned(destdef) and
+ (destdef.typ in [enumdef,orddef,floatdef]) and
+ not is_boolean(destdef) and
+ assigned(source.resultdef) and
+ (source.resultdef.typ in [enumdef,orddef,floatdef]) and
+ not is_boolean(source.resultdef) and
+ not is_constrealnode(source) then
+ begin
+ if ((destdef.size < source.resultdef.size) and
+ { s80real and sc80real have a different size but the same precision }
+ not((destdef.typ=floatdef) and
+ (source.resultdef.typ=floatdef) and
+ (tfloatdef(source.resultdef).floattype in [s80real,sc80real]) and
+ (tfloatdef(destdef).floattype in [s80real,sc80real]))) or
+ ((destdef.typ<>floatdef) and
+ (source.resultdef.typ<>floatdef) and
+ not is_in_limit(source.resultdef,destdef)) then
+ begin
+ if (cs_check_range in current_settings.localswitches) then
+ MessagePos(location,type_w_smaller_possible_range_check)
+ else
+ MessagePos(location,type_h_smaller_possible_range_check);
+ end;
+ end;
+ end;
+
+
+end.
diff --git a/closures/compiler/i386/aopt386.pas b/closures/compiler/i386/aopt386.pas
new file mode 100644
index 0000000000..0e82343ad2
--- /dev/null
+++ b/closures/compiler/i386/aopt386.pas
@@ -0,0 +1,119 @@
+{
+ Copyright (c) 1998-2002 by Jonas Maebe
+
+ This unit calls the optimization procedures to optimize the assembler
+ code for i386+
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+Unit aopt386;
+
+{$i fpcdefs.inc}
+
+Interface
+
+Uses
+ aasmbase,aasmtai,aasmdata,aasmcpu;
+
+Procedure Optimize(AsmL: TAsmList);
+
+
+Implementation
+
+Uses
+ globtype,
+ globals,
+ DAOpt386,POpt386,CSOpt386;
+
+
+Procedure Optimize(AsmL: TAsmList);
+Var
+ BlockStart, BlockEnd, HP: Tai;
+ pass: longint;
+ slowopt, changed, lastLoop: boolean;
+Begin
+ slowopt := (cs_opt_level3 in current_settings.optimizerswitches);
+ pass := 0;
+ changed := false;
+ dfa := TDFAObj.create(asml);
+ repeat
+ lastLoop :=
+ not(slowopt) or
+ (not changed and (pass > 2)) or
+ { prevent endless loops }
+ (pass = 4);
+ changed := false;
+ { Setup labeltable, always necessary }
+ blockstart := tai(asml.first);
+ blockend := dfa.pass_1(blockstart);
+ { Blockend now either contains an ait_marker with Kind = mark_AsmBlockStart, }
+ { or nil }
+ While Assigned(BlockStart) Do
+ Begin
+ if pass = 0 then
+ PrePeepHoleOpts(AsmL, BlockStart, BlockEnd);
+ { Peephole optimizations }
+ PeepHoleOptPass1(AsmL, BlockStart, BlockEnd);
+ { Only perform them twice in the first pass }
+ if pass = 0 then
+ PeepHoleOptPass1(AsmL, BlockStart, BlockEnd);
+ { Data flow analyzer }
+ If (cs_opt_asmcse in current_settings.optimizerswitches) Then
+ begin
+ if dfa.pass_generate_code then
+ { common subexpression elimination }
+ changed := CSE(asmL, blockStart, blockEnd, pass) or changed;
+ end;
+ { More peephole optimizations }
+ PeepHoleOptPass2(AsmL, BlockStart, BlockEnd);
+ if lastLoop then
+ PostPeepHoleOpts(AsmL, BlockStart, BlockEnd);
+
+ { Free memory }
+ dfa.clear;
+
+ { Continue where we left off, BlockEnd is either the start of an }
+ { assembler block or nil }
+ BlockStart := BlockEnd;
+ While Assigned(BlockStart) And
+ (BlockStart.typ = ait_Marker) And
+ (Tai_Marker(BlockStart).Kind = mark_AsmBlockStart) Do
+ Begin
+ { We stopped at an assembler block, so skip it }
+ Repeat
+ BlockStart := Tai(BlockStart.Next);
+ Until (BlockStart.Typ = Ait_Marker) And
+ (Tai_Marker(Blockstart).Kind = mark_AsmBlockEnd);
+ { Blockstart now contains a Tai_marker(mark_AsmBlockEnd) }
+ If GetNextInstruction(BlockStart, HP) And
+ ((HP.typ <> ait_Marker) Or
+ (Tai_Marker(HP).Kind <> mark_AsmBlockStart)) Then
+ { There is no assembler block anymore after the current one, so }
+ { optimize the next block of "normal" instructions }
+ BlockEnd := dfa.pass_1(blockstart)
+ { Otherwise, skip the next assembler block }
+ else
+ blockStart := hp;
+ End;
+ End;
+ inc(pass);
+ until lastLoop;
+ dfa.free;
+
+End;
+
+End.
diff --git a/closures/compiler/i386/cgcpu.pas b/closures/compiler/i386/cgcpu.pas
new file mode 100644
index 0000000000..863638d3e7
--- /dev/null
+++ b/closures/compiler/i386/cgcpu.pas
@@ -0,0 +1,862 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit implements the code generator for the i386
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit cgcpu;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ globtype,
+ cgbase,cgobj,cg64f32,cgx86,
+ aasmbase,aasmtai,aasmdata,aasmcpu,
+ cpubase,parabase,cgutils,
+ symconst,symdef
+ ;
+
+ type
+ tcg386 = class(tcgx86)
+ procedure init_register_allocators;override;
+ procedure do_register_allocation(list:TAsmList;headertai:tai);override;
+
+ { passing parameter using push instead of mov }
+ procedure a_load_reg_cgpara(list : TAsmList;size : tcgsize;r : tregister;const cgpara : tcgpara);override;
+ procedure a_load_const_cgpara(list : TAsmList;size : tcgsize;a : tcgint;const cgpara : tcgpara);override;
+ procedure a_load_ref_cgpara(list : TAsmList;size : tcgsize;const r : treference;const cgpara : tcgpara);override;
+ procedure a_loadaddr_ref_cgpara(list : TAsmList;const r : treference;const cgpara : tcgpara);override;
+
+ procedure g_proc_exit(list : TAsmList;parasize:longint;nostackframe:boolean);override;
+ procedure g_copyvaluepara_openarray(list : TAsmList;const ref:treference;const lenloc:tlocation;elesize:tcgint;destreg:tregister);override;
+ procedure g_releasevaluepara_openarray(list : TAsmList;const l:tlocation);override;
+
+ procedure g_exception_reason_save(list : TAsmList; const href : treference);override;
+ procedure g_exception_reason_save_const(list : TAsmList; const href : treference; a: tcgint);override;
+ procedure g_exception_reason_load(list : TAsmList; const href : treference);override;
+ procedure g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);override;
+ procedure g_maybe_got_init(list: TAsmList); override;
+ end;
+
+ tcg64f386 = class(tcg64f32)
+ procedure a_op64_ref_reg(list : TAsmList;op:TOpCG;size : tcgsize;const ref : treference;reg : tregister64);override;
+ procedure a_op64_reg_reg(list : TAsmList;op:TOpCG;size : tcgsize;regsrc,regdst : tregister64);override;
+ procedure a_op64_const_reg(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;reg : tregister64);override;
+ procedure a_op64_const_ref(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;const ref : treference);override;
+ private
+ procedure get_64bit_ops(op:TOpCG;var op1,op2:TAsmOp);
+ end;
+
+ procedure create_codegen;
+
+ implementation
+
+ uses
+ globals,verbose,systems,cutils,
+ paramgr,procinfo,fmodule,
+ rgcpu,rgx86,cpuinfo;
+
+ function use_push(const cgpara:tcgpara):boolean;
+ begin
+ result:=(not paramanager.use_fixed_stack) and
+ assigned(cgpara.location) and
+ (cgpara.location^.loc=LOC_REFERENCE) and
+ (cgpara.location^.reference.index=NR_STACK_POINTER_REG);
+ end;
+
+
+ procedure tcg386.init_register_allocators;
+ begin
+ inherited init_register_allocators;
+ if not(target_info.system in [system_i386_darwin,system_i386_iphonesim]) and
+ (cs_create_pic in current_settings.moduleswitches) then
+ rg[R_INTREGISTER]:=trgcpu.create(R_INTREGISTER,R_SUBWHOLE,[RS_EAX,RS_EDX,RS_ECX,RS_ESI,RS_EDI],first_int_imreg,[RS_EBP])
+ else
+ rg[R_INTREGISTER]:=trgcpu.create(R_INTREGISTER,R_SUBWHOLE,[RS_EAX,RS_EDX,RS_ECX,RS_EBX,RS_ESI,RS_EDI],first_int_imreg,[RS_EBP]);
+ rg[R_MMXREGISTER]:=trgcpu.create(R_MMXREGISTER,R_SUBNONE,[RS_XMM0,RS_XMM1,RS_XMM2,RS_XMM3,RS_XMM4,RS_XMM5,RS_XMM6,RS_XMM7],first_mm_imreg,[]);
+ rg[R_MMREGISTER]:=trgcpu.create(R_MMREGISTER,R_SUBWHOLE,[RS_XMM0,RS_XMM1,RS_XMM2,RS_XMM3,RS_XMM4,RS_XMM5,RS_XMM6,RS_XMM7],first_mm_imreg,[]);
+ rgfpu:=Trgx86fpu.create;
+ end;
+
+ procedure tcg386.do_register_allocation(list:TAsmList;headertai:tai);
+ begin
+ if (pi_needs_got in current_procinfo.flags) then
+ begin
+ if getsupreg(current_procinfo.got) < first_int_imreg then
+ include(rg[R_INTREGISTER].used_in_proc,getsupreg(current_procinfo.got));
+ end;
+ inherited do_register_allocation(list,headertai);
+ end;
+
+
+ procedure tcg386.a_load_reg_cgpara(list : TAsmList;size : tcgsize;r : tregister;const cgpara : tcgpara);
+ var
+ pushsize : tcgsize;
+ begin
+ check_register_size(size,r);
+ if use_push(cgpara) then
+ begin
+ cgpara.check_simple_location;
+ if tcgsize2size[cgpara.location^.size]>cgpara.alignment then
+ pushsize:=cgpara.location^.size
+ else
+ pushsize:=int_cgsize(cgpara.alignment);
+ list.concat(taicpu.op_reg(A_PUSH,tcgsize2opsize[pushsize],makeregsize(list,r,pushsize)));
+ end
+ else
+ inherited a_load_reg_cgpara(list,size,r,cgpara);
+ end;
+
+
+ procedure tcg386.a_load_const_cgpara(list : TAsmList;size : tcgsize;a : tcgint;const cgpara : tcgpara);
+ var
+ pushsize : tcgsize;
+ begin
+ if use_push(cgpara) then
+ begin
+ cgpara.check_simple_location;
+ if tcgsize2size[cgpara.location^.size]>cgpara.alignment then
+ pushsize:=cgpara.location^.size
+ else
+ pushsize:=int_cgsize(cgpara.alignment);
+ list.concat(taicpu.op_const(A_PUSH,tcgsize2opsize[pushsize],a));
+ end
+ else
+ inherited a_load_const_cgpara(list,size,a,cgpara);
+ end;
+
+
+ procedure tcg386.a_load_ref_cgpara(list : TAsmList;size : tcgsize;const r : treference;const cgpara : tcgpara);
+
+ procedure pushdata(paraloc:pcgparalocation;ofs:tcgint);
+ var
+ pushsize : tcgsize;
+ tmpreg : tregister;
+ href : treference;
+ begin
+ if not assigned(paraloc) then
+ exit;
+ if (paraloc^.loc<>LOC_REFERENCE) or
+ (paraloc^.reference.index<>NR_STACK_POINTER_REG) or
+ (tcgsize2size[paraloc^.size]>sizeof(aint)) then
+ internalerror(200501162);
+ { Pushes are needed in reverse order, add the size of the
+ current location to the offset where to load from. This
+ prevents wrong calculations for the last location when
+ the size is not a power of 2 }
+ if assigned(paraloc^.next) then
+ pushdata(paraloc^.next,ofs+tcgsize2size[paraloc^.size]);
+ { Push the data starting at ofs }
+ href:=r;
+ inc(href.offset,ofs);
+ if tcgsize2size[paraloc^.size]>cgpara.alignment then
+ pushsize:=paraloc^.size
+ else
+ pushsize:=int_cgsize(cgpara.alignment);
+ if tcgsize2size[paraloc^.size]<cgpara.alignment then
+ begin
+ tmpreg:=getintregister(list,pushsize);
+ a_load_ref_reg(list,paraloc^.size,pushsize,href,tmpreg);
+ list.concat(taicpu.op_reg(A_PUSH,TCgsize2opsize[pushsize],tmpreg));
+ end
+ else
+ begin
+ make_simple_ref(list,href);
+ list.concat(taicpu.op_ref(A_PUSH,TCgsize2opsize[pushsize],href));
+ end;
+ end;
+
+ var
+ len : tcgint;
+ href : treference;
+ begin
+ { cgpara.size=OS_NO requires a copy on the stack }
+ if use_push(cgpara) then
+ begin
+ { Record copy? }
+ if (cgpara.size in [OS_NO,OS_F64]) or (size=OS_NO) then
+ begin
+ cgpara.check_simple_location;
+ len:=align(cgpara.intsize,cgpara.alignment);
+ g_stackpointer_alloc(list,len);
+ reference_reset_base(href,NR_STACK_POINTER_REG,0,4);
+ g_concatcopy(list,r,href,len);
+ end
+ else
+ begin
+ if tcgsize2size[cgpara.size]<>tcgsize2size[size] then
+ internalerror(200501161);
+ { We need to push the data in reverse order,
+ therefor we use a recursive algorithm }
+ pushdata(cgpara.location,0);
+ end
+ end
+ else
+ inherited a_load_ref_cgpara(list,size,r,cgpara);
+ end;
+
+
+ procedure tcg386.a_loadaddr_ref_cgpara(list : TAsmList;const r : treference;const cgpara : tcgpara);
+ var
+ tmpreg : tregister;
+ opsize : topsize;
+ tmpref : treference;
+ begin
+ with r do
+ begin
+ if (segment<>NR_NO) then
+ cgmessage(cg_e_cant_use_far_pointer_there);
+ if use_push(cgpara) then
+ begin
+ cgpara.check_simple_location;
+ opsize:=tcgsize2opsize[OS_ADDR];
+ if (segment=NR_NO) and (base=NR_NO) and (index=NR_NO) then
+ begin
+ if assigned(symbol) then
+ begin
+ if (target_info.system in [system_i386_darwin,system_i386_iphonesim]) and
+ ((r.symbol.bind in [AB_EXTERNAL,AB_WEAK_EXTERNAL]) or
+ (cs_create_pic in current_settings.moduleswitches)) then
+ begin
+ tmpreg:=getaddressregister(list);
+ a_loadaddr_ref_reg(list,r,tmpreg);
+ list.concat(taicpu.op_reg(A_PUSH,opsize,tmpreg));
+ end
+ else if cs_create_pic in current_settings.moduleswitches then
+ begin
+ if offset<>0 then
+ begin
+ tmpreg:=getaddressregister(list);
+ a_loadaddr_ref_reg(list,r,tmpreg);
+ list.concat(taicpu.op_reg(A_PUSH,opsize,tmpreg));
+ end
+ else
+ begin
+ reference_reset_symbol(tmpref,r.symbol,0,r.alignment);
+ tmpref.refaddr:=addr_pic;
+ tmpref.base:=current_procinfo.got;
+ include(current_procinfo.flags,pi_needs_got);
+ list.concat(taicpu.op_ref(A_PUSH,S_L,tmpref));
+ end
+ end
+ else
+ list.concat(Taicpu.Op_sym_ofs(A_PUSH,opsize,symbol,offset));
+ end
+ else
+ list.concat(Taicpu.Op_const(A_PUSH,opsize,offset));
+ end
+ else if (segment=NR_NO) and (base=NR_NO) and (index<>NR_NO) and
+ (offset=0) and (scalefactor=0) and (symbol=nil) then
+ list.concat(Taicpu.Op_reg(A_PUSH,opsize,index))
+ else if (segment=NR_NO) and (base<>NR_NO) and (index=NR_NO) and
+ (offset=0) and (symbol=nil) then
+ list.concat(Taicpu.Op_reg(A_PUSH,opsize,base))
+ else
+ begin
+ tmpreg:=getaddressregister(list);
+ a_loadaddr_ref_reg(list,r,tmpreg);
+ list.concat(taicpu.op_reg(A_PUSH,opsize,tmpreg));
+ end;
+ end
+ else
+ inherited a_loadaddr_ref_cgpara(list,r,cgpara);
+ end;
+ end;
+
+
+ procedure tcg386.g_proc_exit(list : TAsmList;parasize:longint;nostackframe:boolean);
+ var
+ stacksize : longint;
+ begin
+ { MMX needs to call EMMS }
+ if assigned(rg[R_MMXREGISTER]) and
+ (rg[R_MMXREGISTER].uses_registers) then
+ list.concat(Taicpu.op_none(A_EMMS,S_NO));
+
+ { remove stackframe }
+ if not nostackframe then
+ begin
+ if (current_procinfo.framepointer=NR_STACK_POINTER_REG) then
+ begin
+ stacksize:=current_procinfo.calc_stackframe_size;
+ if (target_info.system in [system_i386_darwin,system_i386_iphonesim]) and
+ ((stacksize <> 0) or
+ (pi_do_call in current_procinfo.flags) or
+ { can't detect if a call in this case -> use nostackframe }
+ { if you (think you) know what you are doing }
+ (po_assembler in current_procinfo.procdef.procoptions)) then
+ stacksize := align(stacksize+sizeof(aint),16) - sizeof(aint);
+ if (stacksize<>0) then
+ cg.a_op_const_reg(list,OP_ADD,OS_ADDR,stacksize,current_procinfo.framepointer);
+ end
+ else
+ list.concat(Taicpu.op_none(A_LEAVE,S_NO));
+ list.concat(tai_regalloc.dealloc(current_procinfo.framepointer,nil));
+ end;
+
+ { return from proc }
+ if (po_interrupt in current_procinfo.procdef.procoptions) and
+ { this messes up stack alignment }
+ not(target_info.system in [system_i386_darwin,system_i386_iphonesim]) then
+ begin
+ if assigned(current_procinfo.procdef.funcretloc[calleeside].location) and
+ (current_procinfo.procdef.funcretloc[calleeside].location^.loc=LOC_REGISTER) then
+ begin
+ if (getsupreg(current_procinfo.procdef.funcretloc[calleeside].location^.register)=RS_EAX) then
+ list.concat(Taicpu.Op_const_reg(A_ADD,S_L,4,NR_ESP))
+ else
+ internalerror(2010053001);
+ end
+ else
+ list.concat(Taicpu.Op_reg(A_POP,S_L,NR_EAX));
+ list.concat(Taicpu.Op_reg(A_POP,S_L,NR_EBX));
+ list.concat(Taicpu.Op_reg(A_POP,S_L,NR_ECX));
+
+ if (current_procinfo.procdef.funcretloc[calleeside].size in [OS_64,OS_S64]) and
+ assigned(current_procinfo.procdef.funcretloc[calleeside].location) and
+ assigned(current_procinfo.procdef.funcretloc[calleeside].location^.next) and
+ (current_procinfo.procdef.funcretloc[calleeside].location^.next^.loc=LOC_REGISTER) then
+ begin
+ if (getsupreg(current_procinfo.procdef.funcretloc[calleeside].location^.next^.register)=RS_EDX) then
+ list.concat(Taicpu.Op_const_reg(A_ADD,S_L,4,NR_ESP))
+ else
+ internalerror(2010053002);
+ end
+ else
+ list.concat(Taicpu.Op_reg(A_POP,S_L,NR_EDX));
+
+ list.concat(Taicpu.Op_reg(A_POP,S_L,NR_ESI));
+ list.concat(Taicpu.Op_reg(A_POP,S_L,NR_EDI));
+ { .... also the segment registers }
+ list.concat(Taicpu.Op_reg(A_POP,S_W,NR_DS));
+ list.concat(Taicpu.Op_reg(A_POP,S_W,NR_ES));
+ list.concat(Taicpu.Op_reg(A_POP,S_W,NR_FS));
+ list.concat(Taicpu.Op_reg(A_POP,S_W,NR_GS));
+ { this restores the flags }
+ list.concat(Taicpu.Op_none(A_IRET,S_NO));
+ end
+ { Routines with the poclearstack flag set use only a ret }
+ else if (current_procinfo.procdef.proccalloption in clearstack_pocalls) and
+ (not paramanager.use_fixed_stack) then
+ begin
+ { complex return values are removed from stack in C code PM }
+ { but not on win32 }
+ { and not for safecall with hidden exceptions, because the result }
+ { wich contains the exception is passed in EAX }
+ if (target_info.system <> system_i386_win32) and
+ not ((current_procinfo.procdef.proccalloption = pocall_safecall) and
+ (tf_safecall_exceptions in target_info.flags)) and
+ paramanager.ret_in_param(current_procinfo.procdef.returndef,
+ current_procinfo.procdef.proccalloption) then
+ list.concat(Taicpu.Op_const(A_RET,S_W,sizeof(aint)))
+ else
+ list.concat(Taicpu.Op_none(A_RET,S_NO));
+ end
+ { ... also routines with parasize=0 }
+ else if (parasize=0) then
+ list.concat(Taicpu.Op_none(A_RET,S_NO))
+ else
+ begin
+ { parameters are limited to 65535 bytes because ret allows only imm16 }
+ if (parasize>65535) then
+ CGMessage(cg_e_parasize_too_big);
+ list.concat(Taicpu.Op_const(A_RET,S_W,parasize));
+ end;
+ end;
+
+
+ procedure tcg386.g_copyvaluepara_openarray(list : TAsmList;const ref:treference;const lenloc:tlocation;elesize:tcgint;destreg:tregister);
+ var
+ power,len : longint;
+ opsize : topsize;
+{$ifndef __NOWINPECOFF__}
+ again,ok : tasmlabel;
+{$endif}
+ begin
+ if paramanager.use_fixed_stack then
+ begin
+ inherited g_copyvaluepara_openarray(list,ref,lenloc,elesize,destreg);
+ exit;
+ end;
+
+ { get stack space }
+ getcpuregister(list,NR_EDI);
+ a_load_loc_reg(list,OS_INT,lenloc,NR_EDI);
+ list.concat(Taicpu.op_reg(A_INC,S_L,NR_EDI));
+ { Now EDI contains (high+1). Copy it to ECX for later use. }
+ getcpuregister(list,NR_ECX);
+ list.concat(Taicpu.op_reg_reg(A_MOV,S_L,NR_EDI,NR_ECX));
+ if (elesize<>1) then
+ begin
+ if ispowerof2(elesize, power) then
+ list.concat(Taicpu.op_const_reg(A_SHL,S_L,power,NR_EDI))
+ else
+ list.concat(Taicpu.op_const_reg(A_IMUL,S_L,elesize,NR_EDI));
+ end;
+{$ifndef __NOWINPECOFF__}
+ { windows guards only a few pages for stack growing, }
+ { so we have to access every page first }
+ if target_info.system=system_i386_win32 then
+ begin
+ current_asmdata.getjumplabel(again);
+ current_asmdata.getjumplabel(ok);
+ a_label(list,again);
+ list.concat(Taicpu.op_const_reg(A_CMP,S_L,winstackpagesize,NR_EDI));
+ a_jmp_cond(list,OC_B,ok);
+ list.concat(Taicpu.op_const_reg(A_SUB,S_L,winstackpagesize-4,NR_ESP));
+ list.concat(Taicpu.op_reg(A_PUSH,S_L,NR_EDI));
+ list.concat(Taicpu.op_const_reg(A_SUB,S_L,winstackpagesize,NR_EDI));
+ a_jmp_always(list,again);
+
+ a_label(list,ok);
+ end;
+{$endif __NOWINPECOFF__}
+ { If we were probing pages, EDI=(size mod pagesize) and ESP is decremented
+ by (size div pagesize)*pagesize, otherwise EDI=size.
+ Either way, subtracting EDI from ESP will set ESP to desired final value. }
+ list.concat(Taicpu.op_reg_reg(A_SUB,S_L,NR_EDI,NR_ESP));
+ { align stack on 4 bytes }
+ list.concat(Taicpu.op_const_reg(A_AND,S_L,aint($fffffff4),NR_ESP));
+ { load destination, don't use a_load_reg_reg, that will add a move instruction
+ that can confuse the reg allocator }
+ list.concat(Taicpu.Op_reg_reg(A_MOV,S_L,NR_ESP,NR_EDI));
+
+ { Allocate ESI and load it with source }
+ getcpuregister(list,NR_ESI);
+ a_loadaddr_ref_reg(list,ref,NR_ESI);
+
+ { calculate size }
+ len:=elesize;
+ opsize:=S_B;
+ if (len and 3)=0 then
+ begin
+ opsize:=S_L;
+ len:=len shr 2;
+ end
+ else
+ if (len and 1)=0 then
+ begin
+ opsize:=S_W;
+ len:=len shr 1;
+ end;
+
+ if len>1 then
+ begin
+ if ispowerof2(len, power) then
+ list.concat(Taicpu.op_const_reg(A_SHL,S_L,power,NR_ECX))
+ else
+ list.concat(Taicpu.op_const_reg(A_IMUL,S_L,len,NR_ECX));
+ end;
+ list.concat(Taicpu.op_none(A_REP,S_NO));
+ case opsize of
+ S_B : list.concat(Taicpu.Op_none(A_MOVSB,S_NO));
+ S_W : list.concat(Taicpu.Op_none(A_MOVSW,S_NO));
+ S_L : list.concat(Taicpu.Op_none(A_MOVSD,S_NO));
+ end;
+ ungetcpuregister(list,NR_EDI);
+ ungetcpuregister(list,NR_ECX);
+ ungetcpuregister(list,NR_ESI);
+
+ { patch the new address, but don't use a_load_reg_reg, that will add a move instruction
+ that can confuse the reg allocator }
+ list.concat(Taicpu.Op_reg_reg(A_MOV,S_L,NR_ESP,destreg));
+ end;
+
+
+ procedure tcg386.g_releasevaluepara_openarray(list : TAsmList;const l:tlocation);
+ begin
+ if paramanager.use_fixed_stack then
+ begin
+ inherited g_releasevaluepara_openarray(list,l);
+ exit;
+ end;
+ { Nothing to release }
+ end;
+
+
+ procedure tcg386.g_exception_reason_save(list : TAsmList; const href : treference);
+ begin
+ if not paramanager.use_fixed_stack then
+ list.concat(Taicpu.op_reg(A_PUSH,tcgsize2opsize[OS_INT],NR_FUNCTION_RESULT_REG))
+ else
+ inherited g_exception_reason_save(list,href);
+ end;
+
+
+ procedure tcg386.g_exception_reason_save_const(list : TAsmList;const href : treference; a: tcgint);
+ begin
+ if not paramanager.use_fixed_stack then
+ list.concat(Taicpu.op_const(A_PUSH,tcgsize2opsize[OS_INT],a))
+ else
+ inherited g_exception_reason_save_const(list,href,a);
+ end;
+
+
+ procedure tcg386.g_exception_reason_load(list : TAsmList; const href : treference);
+ begin
+ if not paramanager.use_fixed_stack then
+ begin
+ cg.a_reg_alloc(list,NR_FUNCTION_RESULT_REG);
+ list.concat(Taicpu.op_reg(A_POP,tcgsize2opsize[OS_INT],NR_FUNCTION_RESULT_REG))
+ end
+ else
+ inherited g_exception_reason_load(list,href);
+ end;
+
+
+ procedure tcg386.g_maybe_got_init(list: TAsmList);
+ var
+ notdarwin: boolean;
+ begin
+ { allocate PIC register }
+ if (cs_create_pic in current_settings.moduleswitches) and
+ (tf_pic_uses_got in target_info.flags) and
+ (pi_needs_got in current_procinfo.flags) then
+ begin
+ notdarwin:=not(target_info.system in [system_i386_darwin,system_i386_iphonesim]);
+ { on darwin, the got register is virtual (and allocated earlier
+ already) }
+ if notdarwin then
+ { ecx could be used in leaf procedures that don't use ecx to pass
+ aparameter }
+ current_procinfo.got:=NR_EBX;
+ if notdarwin { needs testing before it can be enabled for non-darwin platforms
+ and
+ (current_settings.optimizecputype in [cpu_Pentium2,cpu_Pentium3,cpu_Pentium4]) } then
+ begin
+ current_module.requires_ebx_pic_helper:=true;
+ cg.a_call_name_static(list,'fpc_geteipasebx');
+ end
+ else
+ begin
+ { call/pop is faster than call/ret/mov on Core Solo and later
+ according to Apple's benchmarking -- and all Intel Macs
+ have at least a Core Solo (furthermore, the i386 - Pentium 1
+ don't have a return stack buffer) }
+ a_call_name_static(list,current_procinfo.CurrGOTLabel.name);
+ a_label(list,current_procinfo.CurrGotLabel);
+ list.concat(taicpu.op_reg(A_POP,S_L,current_procinfo.got))
+ end;
+ if notdarwin then
+ begin
+ list.concat(taicpu.op_sym_ofs_reg(A_ADD,S_L,current_asmdata.RefAsmSymbol('_GLOBAL_OFFSET_TABLE_'),0,NR_PIC_OFFSET_REG));
+ list.concat(tai_regalloc.alloc(NR_PIC_OFFSET_REG,nil));
+ end;
+ end;
+ end;
+
+
+ procedure tcg386.g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);
+ {
+ possible calling conventions:
+ default stdcall cdecl pascal register
+ default(0): OK OK OK OK OK
+ virtual(1): OK OK OK OK OK(2)
+
+ (0):
+ set self parameter to correct value
+ jmp mangledname
+
+ (1): The wrapper code use %eax to reach the virtual method address
+ set self to correct value
+ move self,%eax
+ mov 0(%eax),%eax ; load vmt
+ jmp vmtoffs(%eax) ; method offs
+
+ (2): Virtual use values pushed on stack to reach the method address
+ so the following code be generated:
+ set self to correct value
+ push %ebx ; allocate space for function address
+ push %eax
+ mov self,%eax
+ mov 0(%eax),%eax ; load vmt
+ mov vmtoffs(%eax),eax ; method offs
+ mov %eax,4(%esp)
+ pop %eax
+ ret 0; jmp the address
+
+ }
+
+ procedure getselftoeax(offs: longint);
+ var
+ href : treference;
+ selfoffsetfromsp : longint;
+ begin
+ { mov offset(%esp),%eax }
+ if (procdef.proccalloption<>pocall_register) then
+ begin
+ { framepointer is pushed for nested procs }
+ if procdef.parast.symtablelevel>normal_function_level then
+ selfoffsetfromsp:=2*sizeof(aint)
+ else
+ selfoffsetfromsp:=sizeof(aint);
+ reference_reset_base(href,NR_ESP,selfoffsetfromsp+offs,4);
+ cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_EAX);
+ end;
+ end;
+
+ procedure loadvmttoeax;
+ var
+ href : treference;
+ begin
+ { mov 0(%eax),%eax ; load vmt}
+ reference_reset_base(href,NR_EAX,0,4);
+ cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_EAX);
+ end;
+
+ procedure op_oneaxmethodaddr(op: TAsmOp);
+ var
+ href : treference;
+ begin
+ if (procdef.extnumber=$ffff) then
+ Internalerror(200006139);
+ { call/jmp vmtoffs(%eax) ; method offs }
+ reference_reset_base(href,NR_EAX,tobjectdef(procdef.struct).vmtmethodoffset(procdef.extnumber),4);
+ list.concat(taicpu.op_ref(op,S_L,href));
+ end;
+
+
+ procedure loadmethodoffstoeax;
+ var
+ href : treference;
+ begin
+ if (procdef.extnumber=$ffff) then
+ Internalerror(200006139);
+ { mov vmtoffs(%eax),%eax ; method offs }
+ reference_reset_base(href,NR_EAX,tobjectdef(procdef.struct).vmtmethodoffset(procdef.extnumber),4);
+ cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_EAX);
+ end;
+
+
+ var
+ lab : tasmsymbol;
+ make_global : boolean;
+ href : treference;
+ begin
+ if not(procdef.proctypeoption in [potype_function,potype_procedure]) then
+ Internalerror(200006137);
+ if not assigned(procdef.struct) or
+ (procdef.procoptions*[po_classmethod, po_staticmethod,
+ po_methodpointer, po_interrupt, po_iocheck]<>[]) then
+ Internalerror(200006138);
+ if procdef.owner.symtabletype<>ObjectSymtable then
+ Internalerror(200109191);
+
+ make_global:=false;
+ if (not current_module.is_unit) or
+ create_smartlink or
+ (procdef.owner.defowner.owner.symtabletype=globalsymtable) then
+ make_global:=true;
+
+ if make_global then
+ List.concat(Tai_symbol.Createname_global(labelname,AT_FUNCTION,0))
+ else
+ List.concat(Tai_symbol.Createname(labelname,AT_FUNCTION,0));
+
+ { set param1 interface to self }
+ g_adjust_self_value(list,procdef,ioffset);
+
+ if (po_virtualmethod in procdef.procoptions) and
+ not is_objectpascal_helper(procdef.struct) then
+ begin
+ if (procdef.proccalloption=pocall_register) then
+ begin
+ { case 2 }
+ list.concat(taicpu.op_reg(A_PUSH,S_L,NR_EBX)); { allocate space for address}
+ list.concat(taicpu.op_reg(A_PUSH,S_L,NR_EAX));
+ getselftoeax(8);
+ loadvmttoeax;
+ loadmethodoffstoeax;
+ { mov %eax,4(%esp) }
+ reference_reset_base(href,NR_ESP,4,4);
+ list.concat(taicpu.op_reg_ref(A_MOV,S_L,NR_EAX,href));
+ { pop %eax }
+ list.concat(taicpu.op_reg(A_POP,S_L,NR_EAX));
+ { ret ; jump to the address }
+ list.concat(taicpu.op_none(A_RET,S_L));
+ end
+ else
+ begin
+ { case 1 }
+ getselftoeax(0);
+ loadvmttoeax;
+ op_oneaxmethodaddr(A_JMP);
+ end;
+ end
+ { case 0 }
+ else
+ begin
+ if (target_info.system <> system_i386_darwin) then
+ begin
+ lab:=current_asmdata.RefAsmSymbol(procdef.mangledname);
+ list.concat(taicpu.op_sym(A_JMP,S_NO,lab))
+ end
+ else
+ list.concat(taicpu.op_sym(A_JMP,S_NO,get_darwin_call_stub(procdef.mangledname,false)))
+ end;
+
+ List.concat(Tai_symbol_end.Createname(labelname));
+ end;
+
+
+{ ************* 64bit operations ************ }
+
+ procedure tcg64f386.get_64bit_ops(op:TOpCG;var op1,op2:TAsmOp);
+ begin
+ case op of
+ OP_ADD :
+ begin
+ op1:=A_ADD;
+ op2:=A_ADC;
+ end;
+ OP_SUB :
+ begin
+ op1:=A_SUB;
+ op2:=A_SBB;
+ end;
+ OP_XOR :
+ begin
+ op1:=A_XOR;
+ op2:=A_XOR;
+ end;
+ OP_OR :
+ begin
+ op1:=A_OR;
+ op2:=A_OR;
+ end;
+ OP_AND :
+ begin
+ op1:=A_AND;
+ op2:=A_AND;
+ end;
+ else
+ internalerror(200203241);
+ end;
+ end;
+
+
+ procedure tcg64f386.a_op64_ref_reg(list : TAsmList;op:TOpCG;size : tcgsize;const ref : treference;reg : tregister64);
+ var
+ op1,op2 : TAsmOp;
+ tempref : treference;
+ begin
+ if not(op in [OP_NEG,OP_NOT]) then
+ begin
+ get_64bit_ops(op,op1,op2);
+ tempref:=ref;
+ tcgx86(cg).make_simple_ref(list,tempref);
+ list.concat(taicpu.op_ref_reg(op1,S_L,tempref,reg.reglo));
+ inc(tempref.offset,4);
+ list.concat(taicpu.op_ref_reg(op2,S_L,tempref,reg.reghi));
+ end
+ else
+ begin
+ a_load64_ref_reg(list,ref,reg);
+ a_op64_reg_reg(list,op,size,reg,reg);
+ end;
+ end;
+
+
+ procedure tcg64f386.a_op64_reg_reg(list : TAsmList;op:TOpCG;size : tcgsize;regsrc,regdst : tregister64);
+ var
+ op1,op2 : TAsmOp;
+ begin
+ case op of
+ OP_NEG :
+ begin
+ if (regsrc.reglo<>regdst.reglo) then
+ a_load64_reg_reg(list,regsrc,regdst);
+ list.concat(taicpu.op_reg(A_NOT,S_L,regdst.reghi));
+ list.concat(taicpu.op_reg(A_NEG,S_L,regdst.reglo));
+ list.concat(taicpu.op_const_reg(A_SBB,S_L,-1,regdst.reghi));
+ exit;
+ end;
+ OP_NOT :
+ begin
+ if (regsrc.reglo<>regdst.reglo) then
+ a_load64_reg_reg(list,regsrc,regdst);
+ list.concat(taicpu.op_reg(A_NOT,S_L,regdst.reghi));
+ list.concat(taicpu.op_reg(A_NOT,S_L,regdst.reglo));
+ exit;
+ end;
+ end;
+ get_64bit_ops(op,op1,op2);
+ list.concat(taicpu.op_reg_reg(op1,S_L,regsrc.reglo,regdst.reglo));
+ list.concat(taicpu.op_reg_reg(op2,S_L,regsrc.reghi,regdst.reghi));
+ end;
+
+
+ procedure tcg64f386.a_op64_const_reg(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;reg : tregister64);
+ var
+ op1,op2 : TAsmOp;
+ begin
+ case op of
+ OP_AND,OP_OR,OP_XOR:
+ begin
+ cg.a_op_const_reg(list,op,OS_32,tcgint(lo(value)),reg.reglo);
+ cg.a_op_const_reg(list,op,OS_32,tcgint(hi(value)),reg.reghi);
+ end;
+ OP_ADD, OP_SUB:
+ begin
+ // can't use a_op_const_ref because this may use dec/inc
+ get_64bit_ops(op,op1,op2);
+ list.concat(taicpu.op_const_reg(op1,S_L,aint(lo(value)),reg.reglo));
+ list.concat(taicpu.op_const_reg(op2,S_L,aint(hi(value)),reg.reghi));
+ end;
+ else
+ internalerror(200204021);
+ end;
+ end;
+
+
+ procedure tcg64f386.a_op64_const_ref(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;const ref : treference);
+ var
+ op1,op2 : TAsmOp;
+ tempref : treference;
+ begin
+ tempref:=ref;
+ tcgx86(cg).make_simple_ref(list,tempref);
+ case op of
+ OP_AND,OP_OR,OP_XOR:
+ begin
+ cg.a_op_const_ref(list,op,OS_32,tcgint(lo(value)),tempref);
+ inc(tempref.offset,4);
+ cg.a_op_const_ref(list,op,OS_32,tcgint(hi(value)),tempref);
+ end;
+ OP_ADD, OP_SUB:
+ begin
+ get_64bit_ops(op,op1,op2);
+ // can't use a_op_const_ref because this may use dec/inc
+ list.concat(taicpu.op_const_ref(op1,S_L,aint(lo(value)),tempref));
+ inc(tempref.offset,4);
+ list.concat(taicpu.op_const_ref(op2,S_L,aint(hi(value)),tempref));
+ end;
+ else
+ internalerror(200204022);
+ end;
+ end;
+
+ procedure create_codegen;
+ begin
+ cg := tcg386.create;
+ cg64 := tcg64f386.create;
+ end;
+
+end.
diff --git a/closures/compiler/i386/cpubase.inc b/closures/compiler/i386/cpubase.inc
new file mode 100644
index 0000000000..cadf3e29e2
--- /dev/null
+++ b/closures/compiler/i386/cpubase.inc
@@ -0,0 +1,147 @@
+{
+ Copyright (c) 1998-2000 by Florian Klaempfl and Peter Vreman
+
+ Contains the basic declarations for the i386 architecture
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+{ This include file contains the basic declarations for the i386 architecture.
+}
+
+{*****************************************************************************
+ Operand Sizes
+*****************************************************************************}
+
+ type
+ topsize = (S_NO,
+ S_B,S_W,S_L,S_Q,S_BW,S_BL,S_WL,
+ S_IS,S_IL,S_IQ,
+ S_FS,S_FL,S_FX,S_FV,S_FXX,
+ S_MD,
+ S_NEAR,S_FAR,S_SHORT,
+ S_T,
+ S_XMM
+ );
+
+
+{*****************************************************************************
+ Registers
+*****************************************************************************}
+ const
+ {# Standard opcode string table (for each tasmop enumeration). The
+ opcode strings should conform to the names as defined by the
+ processor manufacturer.
+ }
+ std_op2str:op2strtable={$i i386int.inc}
+
+{*****************************************************************************
+ GDB Information
+*****************************************************************************}
+
+ {# Register indexes for stabs information, when some
+ parameters or variables are stored in registers.
+
+ Taken from i386.c (dbx_register_map) and i386.h
+ (FIXED_REGISTERS) from GCC 3.x source code
+
+ }
+ reg_stab_table : array[tregisterindex] of shortint = (
+ {$i r386stab.inc}
+ );
+
+
+{*****************************************************************************
+ Default generic sizes
+*****************************************************************************}
+
+ {# Defines the default address size for a processor, }
+ OS_ADDR = OS_32;
+ {# the natural int size for a processor, }
+ OS_INT = OS_32;
+ OS_SINT = OS_S32;
+ {# the maximum float size for a processor, }
+ OS_FLOAT = OS_F80;
+ {# the size of a vector register for a processor }
+ OS_VECTOR = OS_M128;
+
+{*****************************************************************************
+ Generic Register names
+*****************************************************************************}
+
+ {# Stack pointer register }
+ NR_STACK_POINTER_REG = NR_ESP;
+ RS_STACK_POINTER_REG = RS_ESP;
+ {# Frame pointer register }
+ RS_FRAME_POINTER_REG = RS_EBP;
+ NR_FRAME_POINTER_REG = NR_EBP;
+ { Return address for DWARF }
+ NR_RETURN_ADDRESS_REG = NR_EIP;
+ {# Register for addressing absolute data in a position independant way,
+ such as in PIC code. The exact meaning is ABI specific. For
+ further information look at GCC source : PIC_OFFSET_TABLE_REGNUM
+ }
+ NR_PIC_OFFSET_REG = NR_EBX;
+ { Results are returned in this register (32-bit values) }
+ NR_FUNCTION_RETURN_REG = NR_EAX;
+ RS_FUNCTION_RETURN_REG = RS_EAX;
+ { Low part of 64bit return value }
+ NR_FUNCTION_RETURN64_LOW_REG = NR_EAX;
+ RS_FUNCTION_RETURN64_LOW_REG = RS_EAX;
+ { High part of 64bit return value }
+ NR_FUNCTION_RETURN64_HIGH_REG = NR_EDX;
+ RS_FUNCTION_RETURN64_HIGH_REG = RS_EDX;
+ { The value returned from a function is available in this register }
+ NR_FUNCTION_RESULT_REG = NR_FUNCTION_RETURN_REG;
+ RS_FUNCTION_RESULT_REG = RS_FUNCTION_RETURN_REG;
+ { The lowh part of 64bit value returned from a function }
+ NR_FUNCTION_RESULT64_LOW_REG = NR_FUNCTION_RETURN64_LOW_REG;
+ RS_FUNCTION_RESULT64_LOW_REG = RS_FUNCTION_RETURN64_LOW_REG;
+ { The high part of 64bit value returned from a function }
+ NR_FUNCTION_RESULT64_HIGH_REG = NR_FUNCTION_RETURN64_HIGH_REG;
+ RS_FUNCTION_RESULT64_HIGH_REG = RS_FUNCTION_RETURN64_HIGH_REG;
+
+ { WARNING: don't change to R_ST0!! See comments above implementation of }
+ { a_loadfpu* methods in rgcpu (JM) }
+ NR_fpu_result_reg = NR_ST;
+ NR_mm_result_reg = NR_MM0;
+
+ { Offset where the parent framepointer is pushed }
+ PARENT_FRAMEPOINTER_OFFSET = 8;
+
+{*****************************************************************************
+ GCC /ABI linking information
+*****************************************************************************}
+
+ const
+ {# Registers which must be saved when calling a routine declared as
+ cppdecl, cdecl, stdcall, safecall, palmossyscall. The registers
+ saved should be the ones as defined in the target ABI and / or GCC.
+
+ This value can be deduced from the CALLED_USED_REGISTERS array in the
+ GCC source.
+ }
+ saved_standard_registers : array[0..2] of tsuperregister = (RS_EBX,RS_ESI,RS_EDI);
+
+ saved_mm_registers : array[0..0] of tsuperregister = (RS_INVALID);
+ {# Required parameter alignment when calling a routine declared as
+ stdcall and cdecl. The alignment value should be the one defined
+ by GCC or the target ABI.
+
+ The value of this constant is equal to the constant
+ PARM_BOUNDARY / BITS_PER_UNIT in the GCC source.
+ }
+ std_param_align = 4;
diff --git a/closures/compiler/i386/cpuinfo.pas b/closures/compiler/i386/cpuinfo.pas
new file mode 100644
index 0000000000..598c746625
--- /dev/null
+++ b/closures/compiler/i386/cpuinfo.pas
@@ -0,0 +1,114 @@
+{
+ Copyright (c) 1998-2004 by Florian Klaempfl
+
+ Basic Processor information
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+Unit cpuinfo;
+
+{$i fpcdefs.inc}
+
+Interface
+
+ uses
+ globtype;
+
+Type
+ bestreal = extended;
+ ts32real = single;
+ ts64real = double;
+ ts80real = extended;
+ ts128real = type extended;
+ ts64comp = type extended;
+
+ pbestreal=^bestreal;
+
+ { possible supported processors for this target }
+ tcputype =
+ (cpu_none,
+ cpu_386,
+ cpu_Pentium,
+ cpu_Pentium2,
+ cpu_Pentium3,
+ cpu_Pentium4,
+ cpu_PentiumM
+ );
+
+ tfputype =
+ (fpu_none,
+// fpu_soft,
+ fpu_x87,
+ fpu_sse,
+ fpu_sse2,
+ fpu_sse3
+ );
+
+
+Const
+ { calling conventions supported by the code generator }
+ supported_calling_conventions : tproccalloptions = [
+ pocall_internproc,
+ pocall_register,
+ pocall_safecall,
+ pocall_stdcall,
+ pocall_cdecl,
+ pocall_cppdecl,
+ pocall_far16,
+ pocall_pascal,
+ pocall_oldfpccall,
+ pocall_mwpascal
+ ];
+
+ cputypestr : array[tcputype] of string[10] = ('',
+ '80386',
+ 'PENTIUM',
+ 'PENTIUM2',
+ 'PENTIUM3',
+ 'PENTIUM4',
+ 'PENTIUMM'
+ );
+
+ fputypestr : array[tfputype] of string[6] = ('',
+// 'SOFT',
+ 'X87',
+ 'SSE',
+ 'SSE2',
+ 'SSE3'
+ );
+
+ sse_singlescalar : set of tfputype = [fpu_sse,fpu_sse2,fpu_sse3];
+ sse_doublescalar : set of tfputype = [fpu_sse2,fpu_sse3];
+
+ { Supported optimizations, only used for information }
+ supported_optimizerswitches = genericlevel1optimizerswitches+
+ genericlevel2optimizerswitches+
+ genericlevel3optimizerswitches-
+ { no need to write info about those }
+ [cs_opt_level1,cs_opt_level2,cs_opt_level3]+
+ [cs_opt_peephole,cs_opt_regvar,cs_opt_stackframe,
+ cs_opt_asmcse,cs_opt_loopunroll,cs_opt_uncertain,
+ cs_opt_tailrecursion,cs_opt_nodecse];
+
+ level1optimizerswitches = genericlevel1optimizerswitches + [cs_opt_peephole];
+ level2optimizerswitches = genericlevel2optimizerswitches + level1optimizerswitches +
+ [cs_opt_regvar,cs_opt_stackframe,cs_opt_tailrecursion,cs_opt_nodecse];
+ level3optimizerswitches = genericlevel3optimizerswitches + level2optimizerswitches + [{,cs_opt_loopunroll}];
+
+Implementation
+
+end.
diff --git a/closures/compiler/i386/cpunode.pas b/closures/compiler/i386/cpunode.pas
new file mode 100644
index 0000000000..09db4d1057
--- /dev/null
+++ b/closures/compiler/i386/cpunode.pas
@@ -0,0 +1,60 @@
+{
+ Copyright (c) 2000-2002 by Florian Klaempfl
+
+ Includes the i386 code generator
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit cpunode;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ implementation
+
+ uses
+ { generic nodes }
+ ncgbas,
+ ncgld,
+ ncgflw,
+ ncgcnv,
+ ncgmem,
+ ncgmat,
+ ncgcon,
+ ncgcal,
+ ncgset,
+ ncginl,
+ ncgopt,
+ ncgobjc,
+ { to be able to only parts of the generic code,
+ the processor specific nodes must be included
+ after the generic one (FK)
+ }
+ nx86set,
+ nx86con,
+ nx86cnv,
+
+ n386add,
+ n386cal,
+ n386mem,
+ n386set,
+ n386inl,
+ n386mat
+ ;
+
+end.
diff --git a/closures/compiler/i386/cpupara.pas b/closures/compiler/i386/cpupara.pas
new file mode 100644
index 0000000000..d208cc619d
--- /dev/null
+++ b/closures/compiler/i386/cpupara.pas
@@ -0,0 +1,762 @@
+{
+ Copyright (c) 2002 by Florian Klaempfl
+
+ Generates the argument location information for i386
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit cpupara;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ globtype,
+ aasmtai,aasmdata,cpubase,cgbase,cgutils,
+ symconst,symtype,symsym,symdef,
+ parabase,paramgr;
+
+ type
+ ti386paramanager = class(tparamanager)
+ function param_use_paraloc(const cgpara:tcgpara):boolean;override;
+ function ret_in_param(def : tdef;calloption : tproccalloption) : boolean;override;
+ function push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override;
+ function get_para_align(calloption : tproccalloption):byte;override;
+ function get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;override;
+ function get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;override;
+ function get_volatile_registers_mm(calloption : tproccalloption):tcpuregisterset;override;
+ { Returns the location for the nr-st 32 Bit int parameter
+ if every parameter before is an 32 Bit int parameter as well
+ and if the calling conventions for the helper routines of the
+ rtl are used.
+ }
+ procedure getintparaloc(calloption : tproccalloption; nr : longint;var cgpara:TCGPara);override;
+ function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override;
+ function create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;override;
+ procedure createtempparaloc(list: TAsmList;calloption : tproccalloption;parasym : tparavarsym;can_use_final_stack_loc : boolean;var cgpara:TCGPara);override;
+ function get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): TCGPara;override;
+ private
+ procedure create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
+ procedure create_stdcall_paraloc_info(p : tabstractprocdef; side: tcallercallee;paras:tparalist;var parasize:longint);
+ procedure create_register_paraloc_info(p : tabstractprocdef; side: tcallercallee;paras:tparalist;var parareg,parasize:longint);
+ end;
+
+
+ implementation
+
+ uses
+ cutils,
+ systems,verbose,
+ symtable,
+ defutil;
+
+ const
+ parasupregs : array[0..2] of tsuperregister = (RS_EAX,RS_EDX,RS_ECX);
+
+{****************************************************************************
+ TI386PARAMANAGER
+****************************************************************************}
+
+ function ti386paramanager.param_use_paraloc(const cgpara:tcgpara):boolean;
+ var
+ paraloc : pcgparalocation;
+ begin
+ if not assigned(cgpara.location) then
+ internalerror(200410102);
+ result:=true;
+ { All locations are LOC_REFERENCE }
+ paraloc:=cgpara.location;
+ while assigned(paraloc) do
+ begin
+ if (paraloc^.loc<>LOC_REFERENCE) then
+ begin
+ result:=false;
+ exit;
+ end;
+ paraloc:=paraloc^.next;
+ end;
+ end;
+
+
+ function ti386paramanager.ret_in_param(def : tdef;calloption : tproccalloption) : boolean;
+ var
+ size: longint;
+ begin
+ if (tf_safecall_exceptions in target_info.flags) and
+ (calloption=pocall_safecall) then
+ begin
+ result:=true;
+ exit;
+ end;
+ case target_info.system of
+ system_i386_win32 :
+ begin
+ case def.typ of
+ recorddef :
+ begin
+ { Win32 GCC returns small records in the FUNCTION_RETURN_REG.
+ For stdcall we follow delphi instead of GCC }
+ if (calloption in [pocall_cdecl,pocall_cppdecl]) and
+ (def.size>0) and
+ (def.size<=8) then
+ begin
+ result:=false;
+ exit;
+ end;
+ end;
+ end;
+ end;
+ system_i386_darwin,
+ system_i386_iphonesim :
+ begin
+ case def.typ of
+ recorddef :
+ begin
+ size := def.size;
+ if (size > 0) and
+ (size <= 8) and
+ { only if size is a power of 2 }
+ ((size and (size-1)) = 0) then
+ begin
+ result := false;
+ exit;
+ end;
+ end;
+ procvardef:
+ begin
+ result:=false;
+ exit;
+ end;
+ end;
+ end;
+ end;
+ result:=inherited ret_in_param(def,calloption);
+ end;
+
+
+ function ti386paramanager.push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;
+ begin
+ result:=false;
+ { var,out,constref always require address }
+ if varspez in [vs_var,vs_out,vs_constref] then
+ begin
+ result:=true;
+ exit;
+ end;
+ { Only vs_const, vs_value here }
+ case def.typ of
+ variantdef :
+ begin
+ { variants are small enough to be passed by value except if
+ required by the windows api
+
+ variants are somethings very delphi/windows specific so do it like
+ windows/delphi (FK)
+ }
+ if ((target_info.system=system_i386_win32) and
+ (calloption in [pocall_stdcall,pocall_safecall]) and
+ (varspez=vs_const)) or
+ (calloption=pocall_register) then
+ result:=true
+ else
+ result:=false;
+ end;
+ formaldef :
+ result:=true;
+ recorddef :
+ begin
+ { Delphi stdcall passes records on the stack for call by value }
+ if (target_info.system=system_i386_win32) and
+ (calloption=pocall_stdcall) and
+ (varspez=vs_value) then
+ result:=false
+ else
+ result:=
+ (not(calloption in (cdecl_pocalls+[pocall_mwpascal])) and
+ (def.size>sizeof(aint))) or
+ (((calloption = pocall_mwpascal) or (target_info.system=system_i386_wince)) and
+ (varspez=vs_const));
+ end;
+ arraydef :
+ begin
+ { array of const values are pushed on the stack as
+ well as dyn. arrays }
+ if (calloption in cdecl_pocalls) then
+ result:=not(is_array_of_const(def) or
+ is_dynamic_array(def))
+ else
+ begin
+ result:=(
+ (tarraydef(def).highrange>=tarraydef(def).lowrange) and
+ (def.size>sizeof(aint))
+ ) or
+ is_open_array(def) or
+ is_array_of_const(def) or
+ is_array_constructor(def);
+ end;
+ end;
+ objectdef :
+ result:=is_object(def);
+ stringdef :
+ result:= (tstringdef(def).stringtype in [st_shortstring,st_longstring]);
+ procvardef :
+ result:=not(calloption in cdecl_pocalls) and not tprocvardef(def).is_addressonly;
+ setdef :
+ result:=not(calloption in cdecl_pocalls) and (not is_smallset(def));
+ end;
+ end;
+
+
+ function ti386paramanager.get_para_align(calloption : tproccalloption):byte;
+ begin
+ if calloption=pocall_oldfpccall then
+ begin
+ if target_info.system in [system_i386_go32v2,system_i386_watcom] then
+ result:=2
+ else
+ result:=4;
+ end
+ else
+ result:=std_param_align;
+ end;
+
+
+ function ti386paramanager.get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;
+ begin
+ case calloption of
+ pocall_internproc :
+ result:=[];
+ pocall_register,
+ pocall_safecall,
+ pocall_stdcall,
+ pocall_cdecl,
+ pocall_cppdecl,
+ pocall_mwpascal :
+ result:=[RS_EAX,RS_EDX,RS_ECX];
+ pocall_far16,
+ pocall_pascal,
+ pocall_oldfpccall :
+ result:=[RS_EAX,RS_EDX,RS_ECX,RS_ESI,RS_EDI,RS_EBX];
+ else
+ internalerror(200309071);
+ end;
+ end;
+
+
+ function ti386paramanager.get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;
+ begin
+ result:=[0..first_fpu_imreg-1];
+ end;
+
+
+ function ti386paramanager.get_volatile_registers_mm(calloption : tproccalloption):tcpuregisterset;
+ begin
+ result:=[0..first_mm_imreg-1];
+ end;
+
+
+ procedure ti386paramanager.getintparaloc(calloption : tproccalloption; nr : longint;var cgpara:TCGPara);
+ var
+ paraloc : pcgparalocation;
+ begin
+ cgpara.reset;
+ cgpara.size:=OS_ADDR;
+ cgpara.intsize:=sizeof(pint);
+ cgpara.alignment:=get_para_align(calloption);
+ paraloc:=cgpara.add_location;
+ with paraloc^ do
+ begin
+ size:=OS_INT;
+ if calloption=pocall_register then
+ begin
+ if (nr<=high(parasupregs)+1) then
+ begin
+ if nr=0 then
+ internalerror(200309271);
+ loc:=LOC_REGISTER;
+ register:=newreg(R_INTREGISTER,parasupregs[nr-1],R_SUBWHOLE);
+ end
+ else
+ begin
+ loc:=LOC_REFERENCE;
+ reference.index:=NR_STACK_POINTER_REG;
+ reference.offset:=sizeof(aint)*nr;
+ end;
+ end
+ else
+ begin
+ loc:=LOC_REFERENCE;
+ reference.index:=NR_STACK_POINTER_REG;
+ reference.offset:=sizeof(aint)*nr;
+ end;
+ end;
+ end;
+
+
+ procedure ti386paramanager.create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
+ begin
+ p.funcretloc[side]:=get_funcretloc(p,side,p.returndef);
+ end;
+
+
+ function ti386paramanager.get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): TCGPara;
+ var
+ retcgsize : tcgsize;
+ paraloc : pcgparalocation;
+ sym: tfieldvarsym;
+ begin
+ result.init;
+ result.alignment:=get_para_align(p.proccalloption);
+ { void has no location }
+ if is_void(def) then
+ begin
+ paraloc:=result.add_location;
+ result.size:=OS_NO;
+ result.intsize:=0;
+ paraloc^.size:=OS_NO;
+ paraloc^.loc:=LOC_VOID;
+ exit;
+ end;
+ { on darwin/i386, if a record has only one field and that field is a
+ single or double, it has to be returned like a single/double }
+ if (target_info.system in [system_i386_darwin,system_i386_iphonesim]) and
+ ((def.typ=recorddef) or
+ is_object(def)) and
+ tabstractrecordsymtable(tabstractrecorddef(def).symtable).has_single_field(sym) and
+ (sym.vardef.typ=floatdef) and
+ (tfloatdef(sym.vardef).floattype in [s32real,s64real]) then
+ def:=sym.vardef;
+ { Constructors return self instead of a boolean }
+ if (p.proctypeoption=potype_constructor) then
+ begin
+ retcgsize:=OS_ADDR;
+ result.intsize:=sizeof(pint);
+ end
+ else
+ begin
+ retcgsize:=def_cgsize(def);
+ { darwin/x86 requires that results < sizeof(aint) are sign/ }
+ { zero extended to sizeof(aint) }
+ if (target_info.system in [system_i386_darwin,system_i386_iphonesim]) and
+ (side=calleeside) and
+ (result.intsize>0) and
+ (result.intsize<sizeof(aint)) then
+ begin
+ result.intsize:=sizeof(aint);
+ retcgsize:=OS_SINT;
+ end
+ else
+ result.intsize:=def.size;
+ end;
+ result.size:=retcgsize;
+ { Return is passed as var parameter }
+ if ret_in_param(def,p.proccalloption) then
+ begin
+ paraloc:=result.add_location;
+ paraloc^.loc:=LOC_REFERENCE;
+ paraloc^.size:=retcgsize;
+ exit;
+ end;
+ { Return in FPU register? }
+ if def.typ=floatdef then
+ begin
+ paraloc:=result.add_location;
+ paraloc^.loc:=LOC_FPUREGISTER;
+ paraloc^.register:=NR_FPU_RESULT_REG;
+ paraloc^.size:=retcgsize;
+ end
+ else
+ { Return in register }
+ begin
+ paraloc:=result.add_location;
+ paraloc^.loc:=LOC_REGISTER;
+ if retcgsize in [OS_64,OS_S64] then
+ begin
+ { low 32bits }
+ if side=callerside then
+ paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG
+ else
+ paraloc^.register:=NR_FUNCTION_RETURN64_LOW_REG;
+ paraloc^.size:=OS_32;
+
+ { high 32bits }
+ paraloc:=result.add_location;
+ paraloc^.loc:=LOC_REGISTER;
+ if side=callerside then
+ paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG
+ else
+ paraloc^.register:=NR_FUNCTION_RETURN64_HIGH_REG;
+ paraloc^.size:=OS_32;
+ end
+ else
+ begin
+ paraloc^.size:=retcgsize;
+ if side=callerside then
+ paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize))
+ else
+ paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(R_INTREGISTER,retcgsize));
+ end;
+ end;
+ end;
+
+
+ procedure ti386paramanager.create_stdcall_paraloc_info(p : tabstractprocdef; side: tcallercallee;paras:tparalist;var parasize:longint);
+ var
+ i : integer;
+ hp : tparavarsym;
+ paraloc : pcgparalocation;
+ l,
+ paralen,
+ varalign : longint;
+ paraalign : shortint;
+ pushaddr : boolean;
+ paracgsize : tcgsize;
+ begin
+ paraalign:=get_para_align(p.proccalloption);
+ { we push Flags and CS as long
+ to cope with the IRETD
+ and we save 6 register + 4 selectors }
+ if po_interrupt in p.procoptions then
+ inc(parasize,8+6*4+4*2);
+ { Offset is calculated like:
+ sub esp,12
+ mov [esp+8],para3
+ mov [esp+4],para2
+ mov [esp],para1
+ call function
+ That means for pushes the para with the
+ highest offset (see para3) needs to be pushed first
+ }
+ if p.proccalloption in pushleftright_pocalls then
+ i:=paras.count-1
+ else
+ i:=0;
+ while ((p.proccalloption in pushleftright_pocalls) and (i>=0)) or
+ (not(p.proccalloption in pushleftright_pocalls) and (i<=paras.count-1)) do
+ begin
+ hp:=tparavarsym(paras[i]);
+ pushaddr:=push_addr_param(hp.varspez,hp.vardef,p.proccalloption);
+ if pushaddr then
+ begin
+ paralen:=sizeof(aint);
+ paracgsize:=OS_ADDR;
+ end
+ else
+ begin
+ paralen:=push_size(hp.varspez,hp.vardef,p.proccalloption);
+ { darwin/x86 requires that parameters < sizeof(aint) are sign/ }
+ { zero extended to sizeof(aint) }
+ if (target_info.system in [system_i386_darwin,system_i386_iphonesim]) and
+ (side = callerside) and
+ (paralen > 0) and
+ (paralen < sizeof(aint)) then
+ begin
+ paralen := sizeof(aint);
+ paracgsize:=OS_SINT;
+ end
+ else
+ paracgsize:=def_cgsize(hp.vardef);
+ end;
+ hp.paraloc[side].reset;
+ hp.paraloc[side].size:=paracgsize;
+ hp.paraloc[side].intsize:=paralen;
+ hp.paraloc[side].Alignment:=paraalign;
+ { Copy to stack? }
+ if (paracgsize=OS_NO) or
+ (use_fixed_stack) then
+ begin
+ paraloc:=hp.paraloc[side].add_location;
+ paraloc^.loc:=LOC_REFERENCE;
+ paraloc^.size:=paracgsize;
+ if side=callerside then
+ paraloc^.reference.index:=NR_STACK_POINTER_REG
+ else
+ paraloc^.reference.index:=NR_FRAME_POINTER_REG;
+ varalign:=used_align(size_2_align(paralen),paraalign,paraalign);
+
+ { don't let push_size return 16, because then we can }
+ { read past the end of the heap since the value is only }
+ { 10 bytes long (JM) }
+ if (paracgsize = OS_F80) and
+ (target_info.system in [system_i386_darwin,system_i386_iphonesim]) then
+ paralen:=16;
+ paraloc^.reference.offset:=parasize;
+ if side=calleeside then
+ inc(paraloc^.reference.offset,target_info.first_parm_offset);
+ parasize:=align(parasize+paralen,varalign);
+ end
+ else
+ begin
+ if paralen=0 then
+ internalerror(200501163);
+ while (paralen>0) do
+ begin
+ paraloc:=hp.paraloc[side].add_location;
+ paraloc^.loc:=LOC_REFERENCE;
+ { single and double need a single location }
+ if (paracgsize in [OS_F64,OS_F32]) then
+ begin
+ paraloc^.size:=paracgsize;
+ l:=paralen;
+ end
+ else
+ begin
+ { We can allocate at maximum 32 bits per location }
+ if paralen>sizeof(aint) then
+ l:=sizeof(aint)
+ else
+ l:=paralen;
+ paraloc^.size:=int_cgsize(l);
+ end;
+ if (side=callerside) or
+ (po_nostackframe in p.procoptions) then
+ paraloc^.reference.index:=NR_STACK_POINTER_REG
+ else
+ paraloc^.reference.index:=NR_FRAME_POINTER_REG;
+ varalign:=used_align(size_2_align(l),paraalign,paraalign);
+ paraloc^.reference.offset:=parasize;
+ if side=calleeside then
+ if not(po_nostackframe in p.procoptions) then
+ inc(paraloc^.reference.offset,target_info.first_parm_offset)
+ else
+ { return addres }
+ inc(paraloc^.reference.offset,4);
+ parasize:=align(parasize+l,varalign);
+ dec(paralen,l);
+ end;
+ end;
+ if p.proccalloption in pushleftright_pocalls then
+ dec(i)
+ else
+ inc(i);
+ end;
+ end;
+
+
+ procedure ti386paramanager.create_register_paraloc_info(p : tabstractprocdef; side: tcallercallee;paras:tparalist;
+ var parareg,parasize:longint);
+ var
+ hp : tparavarsym;
+ paraloc : pcgparalocation;
+ paracgsize : tcgsize;
+ i : integer;
+ l,
+ paralen,
+ varalign : longint;
+ pushaddr : boolean;
+ paraalign : shortint;
+ pass : byte;
+ begin
+ if paras.count=0 then
+ exit;
+ paraalign:=get_para_align(p.proccalloption);
+
+ { clean up here so we can later detect properly if a parameter has been
+ assigned or not
+ }
+ for i:=0 to paras.count-1 do
+ tparavarsym(paras[i]).paraloc[side].reset;
+ { Register parameters are assigned from left to right,
+ stack parameters from right to left so assign first the
+ register parameters in a first pass, in the second
+ pass all unhandled parameters are done }
+ for pass:=1 to 2 do
+ begin
+ if pass=1 then
+ i:=0
+ else
+ i:=paras.count-1;
+ while true do
+ begin
+ hp:=tparavarsym(paras[i]);
+ if not(assigned(hp.paraloc[side].location)) then
+ begin
+
+ pushaddr:=push_addr_param(hp.varspez,hp.vardef,p.proccalloption);
+ if pushaddr then
+ begin
+ paralen:=sizeof(aint);
+ paracgsize:=OS_ADDR;
+ end
+ else
+ begin
+ paralen:=push_size(hp.varspez,hp.vardef,p.proccalloption);
+ paracgsize:=def_cgsize(hp.vardef);
+ end;
+ hp.paraloc[side].size:=paracgsize;
+ hp.paraloc[side].intsize:=paralen;
+ hp.paraloc[side].Alignment:=paraalign;
+ {
+ EAX
+ EDX
+ ECX
+ Stack
+ Stack
+
+ 64bit values,floats,arrays and records are always
+ on the stack.
+
+ In case of po_delphi_nested_cc, the parent frame pointer
+ is also always passed on the stack.
+ }
+ if (parareg<=high(parasupregs)) and
+ (paralen<=sizeof(aint)) and
+ (not(hp.vardef.typ in [floatdef,recorddef,arraydef]) or
+ pushaddr) and
+ (not(vo_is_parentfp in hp.varoptions) or
+ not(po_delphi_nested_cc in p.procoptions)) then
+ begin
+ if pass=1 then
+ begin
+ paraloc:=hp.paraloc[side].add_location;
+ paraloc^.size:=paracgsize;
+ paraloc^.loc:=LOC_REGISTER;
+ paraloc^.register:=newreg(R_INTREGISTER,parasupregs[parareg],cgsize2subreg(R_INTREGISTER,paracgsize));
+ inc(parareg);
+ end;
+ end
+ else
+ if pass=2 then
+ begin
+ { Copy to stack? }
+ if (use_fixed_stack) or
+ (paracgsize=OS_NO) then
+ begin
+ paraloc:=hp.paraloc[side].add_location;
+ paraloc^.loc:=LOC_REFERENCE;
+ paraloc^.size:=paracgsize;
+ if side=callerside then
+ paraloc^.reference.index:=NR_STACK_POINTER_REG
+ else
+ paraloc^.reference.index:=NR_FRAME_POINTER_REG;
+ varalign:=used_align(size_2_align(paralen),paraalign,paraalign);
+ paraloc^.reference.offset:=parasize;
+ if side=calleeside then
+ inc(paraloc^.reference.offset,target_info.first_parm_offset);
+ parasize:=align(parasize+paralen,varalign);
+ end
+ else
+ begin
+ if paralen=0 then
+ internalerror(200501163);
+ while (paralen>0) do
+ begin
+ paraloc:=hp.paraloc[side].add_location;
+ paraloc^.loc:=LOC_REFERENCE;
+ { Extended and double need a single location }
+ if (paracgsize in [OS_F64,OS_F32]) then
+ begin
+ paraloc^.size:=paracgsize;
+ l:=paralen;
+ end
+ else
+ begin
+ { We can allocate at maximum 32 bits per location }
+ if paralen>sizeof(aint) then
+ l:=sizeof(aint)
+ else
+ l:=paralen;
+ paraloc^.size:=int_cgsize(l);
+ end;
+ if side=callerside then
+ paraloc^.reference.index:=NR_STACK_POINTER_REG
+ else
+ paraloc^.reference.index:=NR_FRAME_POINTER_REG;
+ varalign:=used_align(size_2_align(l),paraalign,paraalign);
+ paraloc^.reference.offset:=parasize;
+ if side=calleeside then
+ inc(paraloc^.reference.offset,target_info.first_parm_offset);
+ parasize:=align(parasize+l,varalign);
+ dec(paralen,l);
+ end;
+ end;
+ end;
+ end;
+ case pass of
+ 1:
+ begin
+ if i=paras.count-1 then
+ break;
+ inc(i);
+ end;
+ 2:
+ begin
+ if i=0 then
+ break;
+ dec(i);
+ end;
+ end;
+ end;
+ end;
+ end;
+
+
+ function ti386paramanager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;
+ var
+ parasize,
+ parareg : longint;
+ begin
+ parasize:=0;
+ parareg:=0;
+ case p.proccalloption of
+ pocall_register :
+ create_register_paraloc_info(p,side,p.paras,parareg,parasize);
+ pocall_internproc :
+ begin
+ { Use default calling }
+{$warnings off}
+ if (pocall_default=pocall_register) then
+ create_register_paraloc_info(p,side,p.paras,parareg,parasize)
+ else
+ create_stdcall_paraloc_info(p,side,p.paras,parasize);
+{$warnings on}
+ end;
+ else
+ create_stdcall_paraloc_info(p,side,p.paras,parasize);
+ end;
+ create_funcretloc_info(p,side);
+ result:=parasize;
+ end;
+
+
+ function ti386paramanager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;
+ var
+ parasize : longint;
+ begin
+ parasize:=0;
+ { calculate the registers for the normal parameters }
+ create_stdcall_paraloc_info(p,callerside,p.paras,parasize);
+ { append the varargs }
+ create_stdcall_paraloc_info(p,callerside,varargspara,parasize);
+ result:=parasize;
+ end;
+
+
+ procedure ti386paramanager.createtempparaloc(list: TAsmList;calloption : tproccalloption;parasym : tparavarsym;can_use_final_stack_loc : boolean;var cgpara:TCGPara);
+ begin
+ { Never a need for temps when value is pushed (calls inside parameters
+ will simply allocate even more stack space for their parameters) }
+ if not(use_fixed_stack) then
+ can_use_final_stack_loc:=true;
+ inherited createtempparaloc(list,calloption,parasym,can_use_final_stack_loc,cgpara);
+ end;
+
+
+begin
+ paramanager:=ti386paramanager.create;
+end.
diff --git a/closures/compiler/i386/cpupi.pas b/closures/compiler/i386/cpupi.pas
new file mode 100644
index 0000000000..3d3b35ce26
--- /dev/null
+++ b/closures/compiler/i386/cpupi.pas
@@ -0,0 +1,103 @@
+{
+ Copyright (c) 2002 by Florian Klaempfl
+
+ This unit contains the CPU specific part of tprocinfo
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+
+{ This unit contains the CPU specific part of tprocinfo. }
+unit cpupi;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ psub,procinfo,aasmdata;
+
+ type
+ ti386procinfo = class(tcgprocinfo)
+ constructor create(aparent:tprocinfo);override;
+ procedure set_first_temp_offset;override;
+ function calc_stackframe_size:longint;override;
+ procedure generate_parameter_info;override;
+ procedure allocate_got_register(list: tasmlist);override;
+ end;
+
+
+ implementation
+
+ uses
+ cutils,
+ systems,globals,globtype,
+ cgobj,tgobj,paramgr,
+ cpubase,
+ cgutils,
+ symconst;
+
+ constructor ti386procinfo.create(aparent:tprocinfo);
+ begin
+ inherited create(aparent);
+ got:=NR_EBX;
+ end;
+
+
+ procedure ti386procinfo.set_first_temp_offset;
+ begin
+ if paramanager.use_fixed_stack then
+ begin
+ if not(po_assembler in procdef.procoptions) and
+ (tg.direction > 0) then
+ tg.setfirsttemp(tg.direction*maxpushedparasize);
+ end;
+ end;
+
+
+ function ti386procinfo.calc_stackframe_size:longint;
+ begin
+ { align to 4 bytes at least
+ otherwise all those subl $2,%esp are meaningless PM }
+ if not(target_info.system in [system_i386_darwin,system_i386_iphonesim]) then
+ result:=Align(tg.direction*tg.lasttemp,min(current_settings.alignment.localalignmin,4))
+ else
+ result:=tg.direction*tg.lasttemp+maxpushedparasize;
+ end;
+
+
+ procedure ti386procinfo.generate_parameter_info;
+ begin
+ inherited generate_parameter_info;
+ { Para_stack_size is only used to determine how many bytes to remove }
+ { from the stack at the end of the procedure (in the "ret $xx"). }
+ { If the stack is fixed, nothing has to be removed by the callee }
+ if paramanager.use_fixed_stack then
+ para_stack_size := 0;
+ end;
+
+ procedure ti386procinfo.allocate_got_register(list: tasmlist);
+ begin
+ if (target_info.system in [system_i386_darwin,system_i386_iphonesim]) and
+ (cs_create_pic in current_settings.moduleswitches) then
+ begin
+ got := cg.getaddressregister(list);
+ end;
+ end;
+
+begin
+ cprocinfo:=ti386procinfo;
+end.
diff --git a/closures/compiler/i386/cputarg.pas b/closures/compiler/i386/cputarg.pas
new file mode 100644
index 0000000000..3b02424cba
--- /dev/null
+++ b/closures/compiler/i386/cputarg.pas
@@ -0,0 +1,132 @@
+{
+ Copyright (c) 2001-2002 by Peter Vreman
+
+ Includes the i386 dependent target units
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit cputarg;
+
+{$i fpcdefs.inc}
+
+interface
+
+
+implementation
+
+ uses
+ systems { prevent a syntax error when nothing is included }
+
+{**************************************
+ Targets
+**************************************}
+
+ {$ifndef NOTARGETLINUX}
+ ,t_linux
+ {$endif}
+ {$ifndef NOTARGETBSD}
+ ,t_bsd
+ {$endif}
+ {$ifndef NOTARGETSUNOS}
+ ,t_sunos
+ {$endif}
+ {$ifndef NOTARGETEMX}
+ ,t_emx
+ {$endif}
+ {$ifndef NOTARGETOS2}
+ ,t_os2
+ {$endif}
+ {$ifndef NOTARGETWIN}
+ ,t_win
+ {$endif}
+ {$ifndef NOTARGETNETWARE}
+ ,t_nwm
+ {$endif}
+ {$ifndef NOTARGETNETWLIBC}
+ ,t_nwl
+ {$endif}
+ {$ifndef NOTARGETGO32V2}
+ ,t_go32v2
+ {$endif}
+ {$ifndef NOTARGETBEOS}
+ ,t_beos
+ {$endif}
+ {$ifndef NOTARGETHAIKU}
+ ,t_haiku
+ {$endif}
+ {$ifndef NOTARGETWDOSX}
+ ,t_wdosx
+ {$endif}
+ {$ifndef NOTARGETWATCOM}
+ ,t_watcom
+ {$endif}
+ {$ifndef NOTARGETSYMBIAN}
+ ,t_symbian
+ {$endif}
+ {$ifndef NOTARGETNATIVENT}
+ ,t_nativent
+ {$endif}
+ {$ifndef NOTARGETEMBEDDED}
+ ,t_embed
+ {$endif}
+
+{**************************************
+ Assemblers
+**************************************}
+
+ {$ifndef NOAG386ATT}
+ ,agx86att
+ {$endif}
+ {$ifndef NOAG386NSM}
+ ,agx86nsm
+ {$endif}
+ {$ifndef NOAG386INT}
+ ,agx86int
+ {$endif}
+
+ ,ogcoff
+ ,ogelf
+ ,ogmacho
+
+{**************************************
+ Assembler Readers
+**************************************}
+
+ {$ifndef NoRa386Int}
+ ,ra386int
+ {$endif NoRa386Int}
+ {$ifndef NoRa386Att}
+ ,ra386att
+ {$endif NoRa386Att}
+
+{**************************************
+ Debuginfo
+**************************************}
+
+ {$ifndef NoCFIDwarf}
+ ,cfidwarf
+ {$endif NoCFIDwarf}
+ {$ifndef NoDbgStabs}
+ ,dbgstabs
+ {$endif NoDbgStabs}
+ {$ifndef NoDbgDwarf}
+ ,dbgdwarf
+ {$endif NoDbgDwarf}
+
+ ;
+
+end.
diff --git a/closures/compiler/i386/csopt386.pas b/closures/compiler/i386/csopt386.pas
new file mode 100644
index 0000000000..f8eaf47cd0
--- /dev/null
+++ b/closures/compiler/i386/csopt386.pas
@@ -0,0 +1,2255 @@
+{
+ Copyright (c) 1998-2002 by Jonas Maebe, member of the Free Pascal
+ development team
+
+ This unit contains the common subexpression elimination procedure.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS for A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit CSOpt386;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses aasmbase,aasmtai,aasmdata,aasmcpu, cpuinfo, cpubase, cgbase;
+
+function CSE(asml: TAsmList; first, last: tai; pass: longint): boolean;
+
+function doReplaceReg(hp: taicpu; newReg, orgReg: tsuperregister): boolean;
+function changeOp(var o: toper; newReg, orgReg: tsuperregister): boolean;
+function storeBack(start, current: tai; orgReg, newReg: tsuperregister): boolean;
+function NoHardCodedRegs(p: taicpu; orgReg, newReg: tsuperregister): boolean;
+function RegSizesOK(oldReg,newReg: tsuperregister; p: taicpu): boolean;
+
+implementation
+
+uses
+{$ifdef csdebug}
+ cutils,
+{$else}
+ {$ifdef replaceregdebug}cutils,{$endif}
+{$endif}
+ globtype, verbose, procinfo, globals, daopt386, rgobj, rropt386,cgutils;
+
+{
+function TaiInSequence(P: tai; Const Seq: TContent): Boolean;
+var P1: tai;
+ Counter: Byte;
+ TmpResult: Boolean;
+begin
+ TmpResult := False;
+ P1 := Seq.StartMod;
+ Counter := 1;
+ while not(TmpResult) and
+ (Counter <= Seq.NrofMods) do
+ begin
+ if (P = P1) then TmpResult := True;
+ inc(Counter);
+ p1 := tai(p1.Next);
+ end;
+ TaiInSequence := TmpResult;
+end;
+}
+
+function modifiesConflictingMemLocation(p1: tai; supreg: tsuperregister; c: tregContent;
+ var regsStillValid: tregset; onlymem: boolean; var invalsmemwrite: boolean): boolean;
+var
+ p: taicpu;
+ tmpRef: treference;
+ regCounter: tsuperregister;
+ opCount: longint;
+ dummy: boolean;
+begin
+ modifiesConflictingMemLocation := false;
+ invalsmemwrite := false;
+ if p1.typ <> ait_instruction then
+ exit;
+ p := taicpu(p1);
+ case p.opcode of
+ A_MOV,A_MOVSX,A_MOVZX:
+ if p.oper[1]^.typ = top_ref then
+ for regCounter := RS_EAX to RS_EDI do
+ begin
+ if (p.oper[0]^.typ<>top_reg) or
+ (getregtype(p.oper[0]^.reg) <> R_INTREGISTER) then
+ break;
+ if writeToMemDestroysContents(getsupreg(p.oper[0]^.reg),p.oper[1]^.ref^,
+ regCounter,topsize2tcgsize[p.opsize],c[regCounter],dummy) then
+ begin
+ exclude(regsStillValid,regCounter);
+ modifiesConflictingMemLocation := not(supreg in regsStillValid);
+ end;
+ if (regcounter = supreg) then
+ invalsmemwrite := invalsmemwrite or dummy;
+ end
+ else
+{ if is_reg_var[getsupreg(p.oper[1]^.reg)] then }
+ if not onlymem then
+ for regCounter := RS_EAX to RS_EDI do
+ begin
+ if writeDestroysContents(p.oper[1]^,regCounter,topsize2tcgsize[p.opsize],c[regCounter],dummy) then
+ begin
+ exclude(regsStillValid,regCounter);
+ modifiesConflictingMemLocation := not(supreg in regsStillValid);
+ end
+ end;
+ A_DIV, A_IDIV, A_MUL, A_IMUL:
+ begin
+ if not onlymem then
+ if (p.ops = 1) then
+ begin
+ for regCounter := RS_EAX to RS_EDI do
+ begin
+ if writeToRegDestroysContents(RS_EDX,regCounter,c[regCounter]) then
+ begin
+ exclude(regsStillValid,RS_EDX);
+ modifiesConflictingMemLocation := not(supreg in regsStillValid);
+ end;
+ if writeToRegDestroysContents(RS_EAX,regCounter,c[regCounter]) then
+ begin
+ exclude(regsStillValid,RS_EAX);
+ modifiesConflictingMemLocation := not(supreg in regsStillValid);
+ end;
+ end
+ end
+ else
+ { only possible for imul }
+ { last operand is always destination }
+ for regCounter := RS_EAX to RS_EDI do
+ begin
+ if writeDestroysContents(p.oper[p.ops-1]^,regCounter,topsize2tcgsize[p.opsize],c[regCounter],dummy) then
+ begin
+ exclude(regsStillValid,regCounter);
+ modifiesConflictingMemLocation := not(supreg in regsStillValid);
+ end
+ end
+ end;
+ else
+ for opCount := 1 to maxinschanges do
+ case InsProp[p.opcode].Ch[opCount] of
+ Ch_MOp1,CH_WOp1,CH_RWOp1:
+ if not(onlymem) or
+ (p.oper[0]^.typ = top_ref) then
+{ or ((p.oper[0]^.typ = top_reg) and }
+{ is_reg_var[getsupreg(p.oper[0]^.reg)]) then }
+ for regCounter := RS_EAX to RS_EDI do
+ begin
+ if writeDestroysContents(p.oper[0]^,regCounter,topsize2tcgsize[p.opsize],c[regCounter],dummy) then
+ begin
+ exclude(regsStillValid,regCounter);
+ modifiesConflictingMemLocation := not(supreg in regsStillValid);
+ end;
+ if (regcounter = supreg) then
+ invalsmemwrite := invalsmemwrite or dummy;
+ end;
+ Ch_MOp2,CH_WOp2,CH_RWOp2:
+ if not(onlymem) or
+ (p.oper[1]^.typ = top_ref) then
+{ or ((p.oper[1]^.typ = top_reg) and }
+{ is_reg_var[getsupreg(p.oper[1]^.reg)]) then }
+ for regCounter := RS_EAX to RS_EDI do
+ begin
+ if writeDestroysContents(p.oper[1]^,regCounter,topsize2tcgsize[p.opsize],c[regCounter],dummy) then
+ begin
+ exclude(regsStillValid,regCounter);
+ modifiesConflictingMemLocation := not(supreg in regsStillValid);
+ end;
+ if (regcounter = supreg) then
+ invalsmemwrite := invalsmemwrite or dummy;
+ end;
+ Ch_MOp3,CH_WOp3,CH_RWOp3:
+ if not(onlymem) or
+ (p.oper[2]^.typ = top_ref) then
+{ or ((p.oper[2]^.typ = top_reg) and }
+{ is_reg_var[getsupreg(p.oper[2]^.reg)]) then }
+ for regCounter := RS_EAX to RS_EDI do
+ begin
+ if writeDestroysContents(p.oper[2]^,regCounter,topsize2tcgsize[p.opsize],c[regCounter],dummy) then
+ begin
+ exclude(regsStillValid,regCounter);
+ modifiesConflictingMemLocation := not(supreg in regsStillValid);
+ end;
+ if (regcounter = supreg) then
+ invalsmemwrite := invalsmemwrite or dummy;
+ end;
+ Ch_WMemEDI:
+ begin
+ fillchar(tmpref,sizeof(tmpref),0);
+ tmpRef.base := NR_EDI;
+ tmpRef.index := NR_EDI;
+ for regCounter := RS_EAX to RS_EDI do
+ begin
+ if writeToMemDestroysContents(RS_INVALID,tmpRef,regCounter,OS_32,c[regCounter],dummy) then
+ begin
+ exclude(regsStillValid,regCounter);
+ modifiesConflictingMemLocation := not(supreg in regsStillValid);
+ end;
+ if (regcounter = supreg) then
+ invalsmemwrite := invalsmemwrite or dummy;
+ end;
+ end;
+ end;
+ end;
+end;
+
+
+function isSimpleMemLoc(const ref: treference): boolean;
+begin
+{ isSimpleMemLoc :=
+ (ref.index = RS_NO) and
+ not(ref.base in (rg.usableregsint+[RS_EDI]));}
+ isSimpleMemLoc :=
+ (ref.index = NR_NO) and
+ ((ref.base = NR_NO) or
+ not(getsupreg(ref.base) in [RS_EAX,RS_EBX,RS_ECX,RS_EDX,RS_ESI,RS_EDI]));
+end;
+
+
+{checks whether the current instruction sequence (starting with p) and the
+ one between StartMod and EndMod of Reg are the same. if so, the number of
+ instructions that match is stored in Found and true is returned, otherwise
+ Found holds the number of instructions between StartMod and EndMod and false
+ is returned}
+function CheckSequence(p: tai; var prev: tai; supreg: tsuperregister; var Found: Longint;
+ var reginfo: toptreginfo; findPrevSeqs: boolean): Boolean;
+
+var
+ regsNotRead, regsStillValid : tregset;
+ checkingPrevSequences,
+ passedFlagsModifyingInstr : boolean;
+
+ function getPrevSequence(p: tai; supreg: tsuperregister; currentPrev: tai; var newPrev: tai): tsuperregister;
+
+ const
+ current_reg: tsuperregister = RS_INVALID;
+
+ function stillValid(p: tai): boolean;
+ var
+ hp: tai;
+ begin
+ { only regvars are still used at jump instructions }
+ if (cs_opt_regvar in current_settings.optimizerswitches) and
+ (p.typ = ait_instruction) and
+ taicpu(p).is_jmp then
+ regsstillvalid := regsstillvalid - ptaiprop(p.optinfo)^.usedregs;
+
+ stillValid :=
+ (p.typ = ait_instruction) and
+ (taicpu(p).opcode <> a_jmp) and
+ (ptaiprop(p.optinfo)^.regs[supreg].wstate =
+ ptaiprop(currentPrev.optinfo)^.regs[supreg].wstate) and
+ { in case destroyreg is called with doIncState = false }
+ (ptaiprop(p.optinfo)^.regs[supreg].typ =
+ ptaiprop(currentPrev.optinfo)^.regs[supreg].typ) and
+ (supreg in (regsNotRead * regsStillValid));
+ { stop if the register was still used right before a (conditional) }
+ { jump, since in that case its current contents could still be }
+ { used in the other path of the jump) }
+ if (p.typ = ait_instruction) and
+ (taicpu(p).is_jmp) and
+ getlastinstruction(p,hp) then
+ stillValid := stillValid and
+ not(supreg in ptaiprop(hp.optinfo)^.usedregs);
+ passedFlagsModifyingInstr := passedFlagsModifyingInstr or
+ instrWritesFlags(currentPrev);
+ end;
+
+
+ function findChangedRegister(p: tai): tsuperregister;
+ var
+ regCounter, loopstart: tsuperregister;
+ begin
+ if (current_reg <> RS_INVALID) then
+ loopstart := succ(current_reg)
+ else
+ loopstart := RS_EAX;
+ for regCounter := loopstart to RS_EDI do
+ with ptaiprop(p.optinfo)^.regs[regCounter] do
+ if ((startmod <>
+ ptaiprop(currentPrev.optinfo)^.regs[regCounter].startmod) or
+ (nrofMods <>
+ ptaiprop(currentPrev.optinfo)^.regs[regCounter].nrofMods)) and
+ (ptaiprop(p.optinfo)^.regs[regCounter].typ in [con_ref,con_noRemoveRef]) then
+ begin
+ findChangedRegister := regCounter;
+ current_reg := regCounter;
+ exit;
+ end;
+ current_reg := RS_INVALID;
+ findChangedRegister := RS_INVALID;
+ end;
+
+
+ var
+ hp, prevFound: tai;
+ tmpResult, regCounter: tsuperregister;
+ invalsmemwrite: boolean;
+ begin
+ if (current_reg <> RS_EDI) and
+ (current_reg <> RS_INVALID) then
+ begin
+ tmpResult := findChangedRegister(currentPrev);
+ if tmpResult <> RS_INVALID then
+ begin
+ getPrevSequence := tmpResult;
+ exit;
+ end;
+ end;
+
+ getPrevSequence := RS_INVALID;
+ passedFlagsModifyingInstr := passedFlagsModifyingInstr or
+ instrWritesFlags(currentPrev);
+ if (cs_opt_regvar in current_settings.optimizerswitches) and
+ (currentprev.typ = ait_instruction) and
+ taicpu(currentprev).is_jmp then
+ regsstillvalid := regsstillvalid - ptaiprop(currentprev.optinfo)^.usedregs;
+
+ if not getLastInstruction(currentPrev,hp) then
+ exit;
+
+ prevFound := currentPrev;
+ tmpResult := RS_INVALID;
+
+ while (tmpResult = RS_INVALID) and
+ stillValid(hp) and
+ (ptaiprop(prevFound.optinfo)^.canBeRemoved or
+ not(modifiesConflictingMemLocation(prevFound,supreg,
+ ptaiprop(p.optinfo)^.regs,regsStillValid,false, invalsmemwrite))) do
+ begin
+ { only update the regsread for the instructions we already passed }
+ if not(ptaiprop(prevFound.optinfo)^.canBeRemoved) then
+ for regCounter := RS_EAX to RS_EDI do
+ if regReadByInstruction(regCounter,prevFound) then
+ exclude(regsNotRead,regCounter);
+
+ { in case getPreviousInstruction fails and sets hp to nil in the }
+ { next iteration }
+ prevFound := hp;
+ if not(ptaiprop(hp.optinfo)^.canBeRemoved) then
+ tmpResult := findChangedRegister(hp);
+ if not getLastInstruction(hp,hp) then
+ break;
+ end;
+ getPrevSequence := tmpResult;
+ if tmpResult <> RS_INVALID then
+ newPrev := prevFound;
+ end;
+
+
+ function getNextRegToTest(var prev: tai; currentReg: tsuperregister): tsuperregister;
+ begin
+ if not checkingPrevSequences then
+ begin
+ if (currentreg = RS_INVALID) then
+ currentreg := RS_EAX
+ else
+ inc(currentreg);
+ while (currentReg <= RS_EDI) and
+ not(ptaiprop(prev.optinfo)^.regs[currentReg].typ in [con_ref,con_noRemoveRef]) do
+ inc(currentReg);
+ if currentReg > RS_EDI then
+ begin
+ if (taicpu(p).oper[0]^.typ <> top_ref) or
+ isSimpleMemLoc(taicpu(p).oper[0]^.ref^) then
+ begin
+ checkingPrevSequences := true;
+ end
+ else
+ getNextRegToTest := RS_INVALID;
+ end
+ else
+ getNextRegToTest := currentReg;
+ end;
+ if checkingPrevSequences then
+ if findPrevSeqs then
+ getNextRegToTest :=
+ getPrevSequence(p,supreg,prev,prev)
+ else
+ getNextRegToTest := RS_INVALID;
+ end;
+
+
+ function changedreginvalidatedbetween(const oldreginfo: toptreginfo; var newreginfo: toptreginfo; startp,endp,current: tai): boolean;
+ var
+ orgdiffregs,diffregs: tregset;
+ runner: tai;
+ invalsmemwrite: boolean;
+ begin
+ diffregs := newreginfo.newregsencountered - oldreginfo.newregsencountered;
+ orgdiffregs := diffregs;
+ if diffregs <> [] then
+ begin
+ runner := startp;
+ repeat
+ modifiesConflictingMemLocation(runner,RS_EAX { dummy },ptaiprop(current.optinfo)^.regs,diffregs,true,invalsmemwrite);
+ if orgdiffregs <> diffregs then
+ begin
+ changedreginvalidatedbetween := true;
+ newreginfo := oldreginfo;
+ exit;
+ end;
+ getnextinstruction(runner,runner);
+ until (runner = endp);
+ end;
+ changedreginvalidatedbetween := false;
+ end;
+
+var
+ prevreginfo: toptreginfo;
+ hp2, hp3{, EndMod}, prevhp3, highPrev, orgPrev, pprev: tai;
+ {Cnt,} OldNrofMods: Longint;
+ startRegInfo, OrgRegInfo, HighRegInfo: toptreginfo;
+ regModified, lastregloadremoved: array[RS_EAX..RS_ESP] of boolean;
+ HighFound, OrgRegFound: longint;
+ regcounter, regCounter2, tmpreg, base, index: tsuperregister;
+ OrgRegResult: Boolean;
+ TmpResult, flagResultsNeeded: Boolean;
+begin {CheckSequence}
+ TmpResult := False;
+ FillChar(OrgRegInfo, Sizeof(OrgRegInfo), 0);
+ FillChar(startRegInfo, sizeof(startRegInfo), 0);
+ OrgRegFound := 0;
+ HighFound := 0;
+ OrgRegResult := False;
+ with startRegInfo do
+ begin
+ newRegsEncountered := [RS_EBP, RS_ESP];
+ fillword(new2oldreg,sizeof(new2oldreg),RS_INVALID);
+ new2OldReg[RS_EBP] := RS_EBP;
+ new2OldReg[RS_ESP] := RS_ESP;
+ oldRegsEncountered := newRegsEncountered;
+ end;
+
+ checkingPrevSequences := false;
+ passedFlagsModifyingInstr := false;
+ flagResultsNeeded := false;
+ regsNotRead := [RS_EAX,RS_EBX,RS_ECX,RS_EDX,RS_ESP,RS_EBP,RS_EDI,RS_ESI];
+ regsStillValid := regsNotRead;
+ GetLastInstruction(p, prev);
+ pprev := prev;
+ tmpreg:=RS_INVALID;
+ regCounter := getNextRegToTest(prev,tmpreg);
+ while (regcounter <> RS_INVALID) do
+ begin
+ fillchar(regModified,sizeof(regModified),0);
+ fillchar(lastregloadremoved,sizeof(lastregloadremoved),0);
+ reginfo := startRegInfo;
+ Found := 0;
+ hp2 := ptaiprop(prev.optinfo)^.Regs[regcounter].StartMod;
+ if (prev <> ptaiprop(prev.optinfo)^.Regs[regcounter].StartMod) then
+ OldNrofMods := ptaiprop(prev.optinfo)^.Regs[regcounter].NrofMods
+ else
+ OldNrofMods := 1;
+ hp3 := p;
+ if checkingprevsequences then
+ prevreginfo := reginfo;
+ while (Found <> OldNrofMods) and
+ { old new }
+ InstructionsEquivalent(hp2, hp3, reginfo) and
+ (not(checkingprevsequences) or
+ not(changedreginvalidatedbetween(prevreginfo,reginfo,prev,p,hp3))) do
+ begin
+ if checkingprevsequences then
+ begin
+ prevreginfo := reginfo;
+ end;
+ if (hp3.typ = ait_instruction) and
+ ((taicpu(hp3).opcode = A_MOV) or
+ (taicpu(hp3).opcode = A_MOVZX) or
+ (taicpu(hp3).opcode = A_LEA) or
+ (taicpu(hp3).opcode = A_MOVSX)) and
+ (taicpu(hp3).oper[1]^.typ = top_reg) and
+ not(regInOp(getsupreg(taicpu(hp3).oper[1]^.reg),taicpu(hp3).oper[0]^)) then
+ begin
+ tmpreg := getsupreg(taicpu(hp3).oper[1]^.reg);
+ lastregloadremoved[tmpreg] := ptaiprop(hp2.optinfo)^.canberemoved;
+ reginfo.lastReload[tmpreg] := hp3;
+ case taicpu(hp3).oper[0]^.typ of
+ top_ref:
+ begin
+ base := getsupreg(taicpu(hp3).oper[0]^.ref^.base);
+ index := getsupreg(taicpu(hp3).oper[0]^.ref^.index);
+ if (found <> 0) and
+ ((taicpu(hp3).oper[0]^.ref^.base = NR_NO) or
+ regModified[base] or
+ (base = getsupreg(current_procinfo.framepointer))) and
+ ((taicpu(hp3).oper[0]^.ref^.index = NR_NO) or
+ regModified[index]) and
+ not(regInRef(tmpReg,taicpu(hp3).oper[0]^.ref^)) then
+ begin
+ with ptaiprop(hp3.optinfo)^.regs[tmpreg] do
+ if nrofMods > (oldNrofMods - found) then
+ oldNrofMods := found + nrofMods;
+ { next is safe because instructions are equivalent }
+ with ptaiprop(hp2.optinfo)^.regs[getsupreg(taicpu(hp2).oper[1]^.reg)] do
+ if nrofMods > (oldNrofMods - found) then
+ oldNrofMods := found + nrofMods;
+ end;
+ end;
+ top_reg:
+ if regModified[getsupreg(taicpu(hp3).oper[0]^.reg)] then
+ begin
+ with ptaiprop(hp3.optinfo)^.regs[tmpreg] do
+ if nrofMods > (oldNrofMods - found) then
+ oldNrofMods := found + nrofMods;
+ with ptaiprop(hp2.optinfo)^.regs[getsupreg(taicpu(hp2).oper[1]^.reg)] do
+ if nrofMods > (oldNrofMods - found) then
+ oldNrofMods := found + nrofMods;
+ end;
+ end;
+ end;
+ for regCounter2 := RS_EAX to RS_EDI do
+ regModified[regCounter2] := regModified[regCounter2] or
+ regModifiedByInstruction(regCounter2,hp3);
+ if flagResultsNeeded then
+ flagResultsNeeded := not instrReadsFlags(hp3);
+ if not flagResultsNeeded then
+ flagResultsNeeded := ptaiprop(hp3.optinfo)^.FlagsUsed;
+ inc(Found);
+ prevhp3 := hp3;
+ if (Found <> OldNrofMods) then
+ if not GetNextInstruction(hp2, hp2) or
+ not GetNextInstruction(hp3, hp3) then
+ break;
+ end;
+
+ if assigned(hp3) then
+ begin
+ prevhp3 := hp3;
+ getnextinstruction(hp3,hp3);
+ end;
+ if not assigned(hp3) or
+ { a marker has no optinfo, which is used below }
+ (hp3.typ = ait_marker) then
+ hp3 := prevhp3;
+{
+a) movl -4(%ebp),%edx
+ movl -12(%ebp),%ecx
+ ...
+ movl -8(%ebp),%eax
+ movl -12(%ebp),%edx (marked as removable)
+ movl (%eax,%edx),%eax (replaced by "movl (%eax,%ecx),%eax")
+ ...
+ movl -8(%ebp),%eax
+ movl -12(%ebp),%edx
+ movl (%eax,%edx),%eax
+ movl (%edx),%edx
+
+-> the "movl -12(ebp),%edx" can't be removed in the last sequence, because
+ edx has not been replaced with ecx there, and edx is still used after the
+ sequence
+
+b) tests/webtbs/tw4266.pp
+}
+
+ { hp2 = instruction after previous sequence, pprev = instruction before }
+ { current sequence, prev = instruction where the loads of the registers }
+ { will be inserted }
+ for regCounter2 := RS_EAX to RS_EDI do
+ if (reginfo.new2OldReg[regCounter2] <> RS_INVALID) and
+ { case a) above }
+ (((regCounter2 in ptaiprop(hp3.optinfo)^.usedRegs) and
+ (not regLoadedWithNewValue(regCounter2,false,hp3) and
+ lastregloadremoved[regcounter2])) or
+ { case b) above }
+ ((ptaiprop(hp2.optinfo)^.regs[regCounter2].wstate <>
+ ptaiprop(pprev.optinfo)^.regs[regcounter2].wstate)) or
+ ((ptaiprop(hp2.optinfo)^.regs[reginfo.new2OldReg[regCounter2]].wstate <>
+ ptaiprop(prev.optinfo)^.regs[reginfo.new2OldReg[regCounter2]].wstate))) then
+ begin
+ found := 0;
+ break;
+ end;
+
+ if checkingPrevSequences then
+ begin
+ for regCounter2 := RS_EAX to RS_EDI do
+ if (reginfo.new2OldReg[regCounter2] <> RS_INVALID) and
+ (reginfo.new2OldReg[regCounter2] <> regCounter2) and
+ (not(regCounter2 in (regsNotRead * regsStillValid)) or
+ not(reginfo.new2OldReg[regCounter2] in regsStillValid)) then
+ begin
+ found := 0;
+ break;
+ end;
+ if passedFlagsModifyingInstr and flagResultsNeeded then
+ found := 0;
+ end;
+
+ TmpResult := true;
+ if (found <> OldNrofMods) then
+ TmpResult := false
+ else if assigned(hp3) then
+ for regcounter2 := RS_EAX to RS_EDI do
+ if (regcounter2 in reginfo.regsLoadedforRef) and
+ regModified[regcounter2] and
+ (regcounter2 in ptaiprop(hp3.optinfo)^.usedRegs) and
+ not regLoadedWithNewValue(regcounter2,false,hp3) then
+ begin
+ TmpResult := False;
+ if (found > 0) then
+ {this is correct because we only need to turn off the CanBeRemoved flag
+ when an instruction has already been processed by CheckSequence
+ (otherwise CanBeRemoved can't be true and thus can't have to be turned off).
+ if it has already been processed by CheckSequence and flagged to be
+ removed, it means that it has been checked against a previous sequence
+ and that it was equal (otherwise CheckSequence would have returned false
+ and the instruction wouldn't have been removed). if this "if found > 0"
+ check is left out, incorrect optimizations are performed.}
+ Found := ptaiprop(tai(p).optinfo)^.Regs[supreg].NrofMods;
+ break;
+ end;
+
+ if TmpResult and
+ (Found > HighFound) then
+ begin
+ highPrev := prev;
+ HighFound := Found;
+ HighRegInfo := reginfo;
+ end;
+ if (regcounter = supreg) then
+ begin
+ orgPrev := prev;
+ OrgRegFound := Found;
+ OrgRegResult := TmpResult;
+ OrgRegInfo := reginfo
+ end;
+ regCounter := getNextRegToTest(prev,regCounter);
+ end;
+ if (HighFound > 0) and
+ (not(OrgRegResult) Or
+ (HighFound > OrgRegFound))
+ then
+ begin
+ CheckSequence := True;
+ prev := highPrev;
+ reginfo := HighRegInfo;
+ Found := HighFound
+ end
+ else
+ begin
+ CheckSequence := OrgRegResult;
+ prev := orgPrev;
+ Found := OrgRegFound;
+ reginfo := OrgRegInfo;
+ end;
+end; {CheckSequence}
+
+
+procedure SetAlignReg(p: tai);
+Const alignSearch = 12;
+var regsUsable: TRegSet;
+ prevInstrCount, nextInstrCount: Longint;
+ prevState, nextWState,nextRState: Array[RS_EAX..RS_EDI] of byte;
+ regCounter, lastRemoved: tsuperregister;
+ prev, next: tai;
+{$ifdef alignregdebug}
+ temp: tai;
+{$endif alignregdebug}
+begin
+ regsUsable := [RS_EAX,RS_ECX,RS_EDX,RS_EBX,{R_ESP,RS_EBP,}RS_ESI,RS_EDI];
+ for regCounter := RS_EAX to RS_EDI do
+ begin
+ prevState[regCounter] := ptaiprop(p.optinfo)^.Regs[regCounter].wState;
+ nextWState[regCounter] := ptaiprop(p.optinfo)^.Regs[regCounter].wState;
+ nextRState[regCounter] := ptaiprop(p.optinfo)^.Regs[regCounter].rState;
+ end;
+ getLastInstruction(p,prev);
+ getNextInstruction(p,next);
+ lastRemoved := getsupreg(tai_align(p).reg);
+ nextInstrCount := 0;
+ prevInstrCount := 0;
+ while ((assigned(prev) and
+ assigned(prev.optinfo) and
+ (prevInstrCount < alignSearch)) or
+ (assigned(next) and
+ assigned(next.optinfo) and
+ (nextInstrCount < alignSearch))) and
+ (regsUsable <> []) do
+ begin
+{$ifdef alignregdebug}
+ if assigned(prev) then
+ begin
+ temp := tai_comment.Create(strpnew('got here'));
+ temp.next := prev.next;
+ temp.previous := prev;
+ prev.next := temp;
+ if assigned(temp.next) then
+ temp.next.previous := temp;
+ end;
+{$endif alignregdebug}
+ if assigned(prev) and assigned(prev.optinfo) and
+ (prevInstrCount < alignSearch) then
+ begin
+ if (prev.typ = ait_instruction) and
+ (insProp[taicpu(prev).opcode].ch[1] <> Ch_ALL) and
+ (taicpu(prev).opcode <> A_JMP) then
+ begin
+ inc(prevInstrCount);
+ for regCounter := RS_EAX to RS_EDI do
+ begin
+ if (regCounter in regsUsable) and
+ (ptaiprop(prev.optinfo)^.Regs[regCounter].wState <>
+ prevState[regCounter]) then
+ begin
+ lastRemoved := regCounter;
+ exclude(regsUsable,regCounter);
+{$ifdef alignregdebug}
+ temp := tai_comment.Create(strpnew(
+ std_regname(newreg(R_INTREGISTER,regCounter,R_SUBWHOLE))+' removed')));
+ temp.next := prev.next;
+ temp.previous := prev;
+ prev.next := temp;
+ if assigned(temp.next) then
+ temp.next.previous := temp;
+ if regsUsable = [] then
+ begin
+ temp := tai_comment.Create(strpnew(
+ 'regsUsable empty here')));
+ temp.next := prev.next;
+ temp.previous := prev;
+ prev.next := temp;
+ if assigned(temp.next) then
+ temp.next.previous := temp;
+ end;
+{$endif alignregdebug}
+ end;
+ prevState[regCounter] :=
+ ptaiprop(prev.optinfo)^.Regs[regCounter].wState;
+ end;
+ getLastInstruction(prev,prev);
+ end
+ else
+ if GetLastInstruction(prev,prev) and
+ assigned(prev.optinfo) then
+ for regCounter := RS_EAX to RS_EDI do
+ prevState[regCounter] :=
+ ptaiprop(prev.optinfo)^.Regs[regCounter].wState
+ end;
+ if assigned(next) and assigned(next.optinfo) and
+ (nextInstrCount < alignSearch) then
+ begin
+ if (next.typ = ait_instruction) and
+ (insProp[taicpu(next).opcode].ch[1] <> Ch_ALL) and
+ (taicpu(next).opcode <> A_JMP) then
+ begin
+ inc(nextInstrCount);
+ for regCounter := RS_EAX to RS_EDI do
+ begin
+ if (regCounter in regsUsable) and
+ ((ptaiprop(next.optinfo)^.Regs[regCounter].wState <>
+ nextWState[regCounter]) or
+ (ptaiprop(next.optinfo)^.Regs[regCounter].rState <>
+ nextRState[regCounter])) then
+ begin
+ lastRemoved := regCounter;
+ exclude(regsUsable,regCounter);
+{$ifdef alignregdebug}
+ temp := tai_comment.Create(strpnew(
+ std_regname(newreg(R_INTREGISTER,regCounter,R_SUBWHOLE))+' removed')));
+ temp.next := next.next;
+ temp.previous := next;
+ next.next := temp;
+ if assigned(temp.next) then
+ temp.next.previous := temp;
+ if regsUsable = [] then
+ begin
+ temp := tai_comment.Create(strpnew(
+ 'regsUsable empty here')));
+ temp.next := next.next;
+ temp.previous := next;
+ next.next := temp;
+ if assigned(temp.next) then
+ temp.next.previous := temp;
+ end;
+{$endif alignregdebug}
+ end;
+ nextWState[regCounter] :=
+ ptaiprop(next.optinfo)^.Regs[regCounter].wState;
+ nextRState[regCounter] :=
+ ptaiprop(next.optinfo)^.Regs[regCounter].rState;
+ end
+ end
+ else
+ for regCounter := RS_EAX to RS_EDI do
+ begin
+ nextWState[regCounter] :=
+ ptaiprop(next.optinfo)^.Regs[regCounter].wState;
+ nextRState[regCounter] :=
+ ptaiprop(next.optinfo)^.Regs[regCounter].rState;
+ end;
+ getNextInstruction(next,next);
+ end;
+ end;
+ if regsUsable <> [] then
+ for regCounter := RS_EAX to RS_EDI do
+ if regCounter in regsUsable then
+ begin
+ lastRemoved := regCounter;
+ break
+ end;
+{$ifdef alignregdebug}
+ next := tai_comment.Create(strpnew(std_regname(newreg(R_INTREGISTER,lastremoved,R_SUBWHOLE))+
+ ' chosen as alignment register')));
+ next.next := p.next;
+ next.previous := p;
+ p.next := next;
+ if assigned(next.next) then
+ next.next.previous := next;
+{$endif alignregdebug}
+ tai_align(p).reg := newreg(R_INTREGISTER,lastRemoved,R_SUBWHOLE);
+end;
+
+
+procedure clearmemwrites(p: tai; supreg: tsuperregister);
+var
+ beginmemwrite: tai;
+begin
+ beginmemwrite := ptaiprop(p.optinfo)^.regs[supreg].memwrite;
+ repeat
+ ptaiprop(p.optinfo)^.regs[supreg].memwrite := nil;
+ until not getnextinstruction(p,p) or
+ (ptaiprop(p.optinfo)^.regs[supreg].memwrite <> beginmemwrite);
+end;
+
+
+procedure ClearRegContentsFrom(asml: TAsmList; supreg: tsuperregister; p, endP: tai);
+{ first clears the contents of reg from p till endP. then the contents are }
+{ cleared until the first instruction that changes reg }
+var
+{$ifdef replaceregdebug}
+ hp: tai;
+ l: longint;
+{$endif replaceregdebug}
+ regcounter: tsuperregister;
+ oldStartmod: tai;
+ regstoclear: tregset;
+begin
+{$ifdef replaceregdebug}
+ l := random(1000);
+ hp := tai_comment.Create(strpnew(
+ 'cleared '+std_regname(newreg(R_INTREGISTER,supreg,R_SUBWHOLE))+' from here... '+tostr(l)));
+ insertllitem(asml,p.previous,p,hp);
+{$endif replaceregdebug}
+ ptaiprop(p.optinfo)^.Regs[supreg].typ := con_unknown;
+ regstoclear := [supreg];
+ while (p <> endP) do
+ begin
+ for regcounter := RS_EAX to RS_EDI do
+ begin
+ if (regcounter <> supreg) and
+ assigned(ptaiprop(p.optinfo)^.regs[supreg].memwrite) and
+ reginref(regcounter,ptaiprop(p.optinfo)^.regs[supreg].memwrite.oper[1]^.ref^) then
+ clearmemwrites(p,regcounter);
+ { needs double loop to cheack for each dependency combination? }
+ if assigned(ptaiprop(p.optinfo)^.regs[regcounter].startmod) and
+ sequencedependsonreg(ptaiprop(p.optinfo)^.regs[regcounter],regcounter,supreg) then
+ include(regstoclear,regcounter);
+
+ if regcounter in regstoclear then
+ with ptaiprop(p.optinfo)^.Regs[regcounter] do
+ begin
+ typ := con_unknown;
+ memwrite := nil;
+ startmod := nil;
+ nrofmods := 0;
+ end;
+ end;
+ getNextInstruction(p,p);
+ end;
+ oldStartmod := ptaiprop(p.optinfo)^.Regs[supreg].startmod;
+ repeat
+ for regcounter := RS_EAX to RS_EDI do
+ begin
+ { needs double loop to cheack for each dependency combination? }
+ if assigned(ptaiprop(p.optinfo)^.regs[regcounter].startmod) and
+ sequencedependsonreg(ptaiprop(p.optinfo)^.regs[regcounter],regcounter,supreg) then
+ include(regstoclear,regcounter);
+ with ptaiprop(p.optinfo)^.Regs[supreg] do
+ if regcounter in regstoclear then
+ begin
+ typ := con_unknown;
+ memwrite := nil;
+ end;
+ end;
+ until not getNextInstruction(p,p) or
+ (ptaiprop(p.optinfo)^.Regs[supreg].startmod <> oldStartmod);
+{$ifdef replaceregdebug}
+ if assigned(p) then
+ begin
+ hp := tai_comment.Create(strpnew(
+ 'cleared '+std_regname(newreg(R_INTREGISTER,supreg,R_SUBWHOLE))+' till here... '+tostr(l)));
+ insertllitem(asml,p.previous,p,hp);
+ end;
+{$endif replaceregdebug}
+end;
+
+procedure RestoreRegContentsTo(asml: TAsmList; supreg: tsuperregister; const c: TContent; p, endP: tai);
+var
+{$ifdef replaceregdebug}
+ l: longint;
+{$endif replaceregdebug}
+ hp: tai;
+ validregs, prevvalidregs: tregset;
+ regcounter: tsuperregister;
+ tmpState, newrstate: byte;
+ prevcontenttyp: byte;
+ memconflict: boolean;
+ invalsmemwrite: boolean;
+begin
+{$ifdef replaceregdebug}
+ l := random(1000);
+ hp := tai_comment.Create(strpnew(
+ 'restored '+std_regname(newreg(R_INTREGISTER,supreg,R_SUBWHOLE))+' with data from here... '+tostr(l)));
+ insertllitem(asml,p.previous,p,hp);
+{$endif replaceregdebug}
+{ ptaiprop(p.optinfo)^.Regs[reg] := c;}
+ newrstate := c.rstate;
+ incstate(newrstate,$7f);
+ memconflict := false;
+ invalsmemwrite := false;
+ validregs := [RS_EAX..RS_EDI];
+ prevvalidregs := validregs;
+ while (p <> endP) and
+ not(memconflict) and
+ not(invalsmemwrite) do
+ begin
+ if not(ptaiprop(p.optinfo)^.canberemoved) and
+ regreadbyinstruction(supreg,p) then
+ incstate(newrstate,1);
+ // is this a write to memory that destroys the contents we are restoring?
+ memconflict := modifiesConflictingMemLocation(p,supreg,ptaiprop(p.optinfo)^.regs,validregs,false,invalsmemwrite);
+ if (validregs <> prevvalidregs) then
+ begin
+ prevvalidregs := validregs >< prevvalidregs;
+ for regcounter := RS_EAX to RS_EDI do
+ if regcounter in prevvalidregs then
+ clearRegContentsFrom(asml,regcounter,p,endP);
+ end;
+ prevvalidregs := validregs;
+ if (not memconflict and not invalsmemwrite) then
+ begin
+ ptaiprop(p.optinfo)^.Regs[supreg] := c;
+ ptaiprop(p.optinfo)^.Regs[supreg].rstate := newrstate;
+ end
+ else
+ begin
+ clearRegContentsFrom(asml,supreg,p,endP);
+{$ifdef replaceregdebug}
+ if assigned(p) then
+ begin
+ hp := tai_comment.Create(strpnew(
+ 'stopping restoring of '+std_regname(newreg(R_INTREGISTER,supreg,R_SUBWHOLE))+'because memory conflict... '+tostr(l)));
+ insertllitem(asml,p,p.next,hp);
+ end;
+{$endif replaceregdebug}
+ exit
+ end;
+
+ getNextInstruction(p,p);
+ end;
+
+ tmpState := ptaiprop(p.optinfo)^.Regs[supreg].wState;
+ if (newrstate = ptaiprop(p.optinfo)^.Regs[supreg].rState) then
+ begin
+ incstate(ptaiprop(p.optinfo)^.regs[supreg].rstate,63);
+ if not getnextinstruction(p,hp) then
+ exit;
+ if (ptaiprop(hp.optinfo)^.regs[supreg].rstate = ptaiprop(p.optinfo)^.regs[supreg].rstate) then
+ internalerror(2004122710);
+ end;
+ repeat
+ newrstate := ptaiprop(p.optinfo)^.Regs[supreg].rState;
+ prevcontenttyp := ptaiprop(p.optinfo)^.Regs[supreg].typ;
+ // is this a write to memory that destroys the contents we are restoring?
+ memconflict := modifiesConflictingMemLocation(p,supreg,ptaiprop(p.optinfo)^.regs,validregs,false,invalsmemwrite);
+ if (validregs <> prevvalidregs) then
+ begin
+ prevvalidregs := validregs >< prevvalidregs;
+ for regcounter := RS_EAX to RS_EDI do
+ if regcounter in prevvalidregs then
+ clearRegContentsFrom(asml,regcounter,p,p);
+ end;
+ prevvalidregs := validregs;
+ if (not memconflict and not invalsmemwrite) then
+ begin
+ ptaiprop(p.optinfo)^.Regs[supreg] := c;
+ ptaiprop(p.optinfo)^.Regs[supreg].rstate := newrstate;
+ end;
+ until invalsmemwrite or
+ memconflict or
+ not getNextInstruction(p,p) or
+ (ptaiprop(p.optinfo)^.Regs[supreg].wState <> tmpState) or
+ (p.typ = ait_label) or
+ ((prevcontenttyp <> con_invalid) and
+ (ptaiprop(p.optinfo)^.Regs[supreg].typ = con_invalid));
+ if assigned(p) and
+ (p.typ <> ait_marker) then
+ if ((p.typ = ait_label) or
+ memconflict or
+ invalsmemwrite) then
+ clearRegContentsFrom(asml,supreg,p,p)
+ else if (ptaiprop(p.optinfo)^.Regs[supreg].rstate = newrstate) then
+ incstate(ptaiprop(p.optinfo)^.Regs[supreg].rstate,20);
+{$ifdef replaceregdebug}
+ if assigned(p) then
+ begin
+ hp := tai_comment.Create(strpnew(
+ 'restored '+std_regname(newreg(R_INTREGISTER,supreg,R_SUBWHOLE))+' till here... '+tostr(l)));
+ insertllitem(asml,p,p.next,hp);
+ end;
+{$endif replaceregdebug}
+end;
+
+function NoHardCodedRegs(p: taicpu; orgReg, newReg: tsuperregister): boolean;
+var
+ chCount: byte;
+begin
+ case p.opcode of
+ A_IMUL: noHardCodedRegs := p.ops <> 1;
+ A_SHL,A_SHR,A_ROR,A_ROL,A_SAR,A_SHLD,A_SHRD: noHardCodedRegs :=
+ (p.oper[0]^.typ <> top_reg) or
+ ((orgReg <> RS_ECX) and (newReg <> RS_ECX));
+ else
+ begin
+ NoHardCodedRegs := true;
+ with InsProp[p.opcode] do
+ for chCount := 1 to maxinschanges do
+ if Ch[chCount] in ([Ch_REAX..Ch_MEDI,Ch_WMemEDI,Ch_All]-[Ch_RESP,Ch_WESP,Ch_RWESP]) then
+ begin
+ NoHardCodedRegs := false;
+ break
+ end;
+ end;
+ end;
+end;
+
+
+function ChangeReg(var Reg: TRegister; newReg, orgReg: tsuperregister): boolean;
+begin
+ changereg := false;
+ if (reg <> NR_NO) and
+ (getregtype(reg) = R_INTREGISTER) and
+ (getsupreg(reg) = newreg) then
+ begin
+ changereg := true;
+ setsupreg(reg,orgreg);
+ end;
+end;
+
+
+function changeOp(var o: toper; newReg, orgReg: tsuperregister): boolean;
+var
+ tmpresult: boolean;
+begin
+ changeOp := false;
+ case o.typ of
+ top_reg: changeOp := changeReg(o.reg,newReg,orgReg);
+ top_ref:
+ begin
+ tmpresult := changeReg(o.ref^.base,newReg,orgReg);
+ changeop := changeReg(o.ref^.index,newReg,orgReg) or tmpresult;
+ end;
+ end;
+end;
+
+
+procedure updateStates(orgReg,newReg: tsuperregister; hp: tai; writeStateToo: boolean);
+var
+ prev: tai;
+ newOrgRegRState, newOrgRegWState: byte;
+begin
+ if getLastInstruction(hp,prev) then
+ with ptaiprop(prev.optinfo)^ do
+ begin
+ newOrgRegRState := byte(longint(regs[orgReg].rState) +
+ longint(ptaiprop(hp.optinfo)^.regs[newReg].rState) - regs[newReg].rstate);
+ if writeStateToo then
+ newOrgRegWState := byte(longint(regs[orgReg].wState) +
+ longint(ptaiprop(hp.optinfo)^.regs[newReg].wState) - regs[newReg].wstate);
+ end
+ else
+ with ptaiprop(hp.optinfo)^.regs[newReg] do
+ begin
+ newOrgRegRState := rState;
+ if writeStateToo then
+ newOrgRegWState := wState;
+ end;
+ with ptaiprop(hp.optinfo)^.regs[orgReg] do
+ begin
+ rState := newOrgRegRState;
+ if writeStateToo then
+ wState := newOrgRegwState;
+ end;
+end;
+
+
+function doReplaceReg(hp: taicpu; newReg, orgReg: tsuperregister): boolean;
+var
+ opCount: longint;
+ tmpResult: boolean;
+begin
+ tmpresult := false;
+ for opCount := 0 to hp.ops-1 do
+ tmpResult :=
+ changeOp(hp.oper[opCount]^,newReg,orgReg) or tmpResult;
+ doReplaceReg := tmpResult;
+end;
+
+
+function RegSizesOK(oldReg,newReg: tsuperregister; p: taicpu): boolean;
+{ oldreg and newreg must be 32bit components }
+var
+ opCount: longint;
+ tmpreg: tsuperregister;
+begin
+ RegSizesOK := true;
+ { if only one of them is a general purpose register ... }
+ if (IsGP32reg(oldReg) xor IsGP32Reg(newReg)) then
+ begin
+ for opCount := 0 to p.ops-1 do
+ if (p.oper[opCount]^.typ = top_reg) and
+ (getsubreg(p.oper[opCount]^.reg) in [R_SUBL,R_SUBH]) then
+ begin
+ tmpreg := getsupreg(p.oper[opCount]^.reg);
+ if (tmpreg = oldreg) or
+ (tmpreg = newreg) then
+ begin
+ RegSizesOK := false;
+ break
+ end
+ end;
+ end;
+end;
+
+
+function doReplaceReadReg(p: taicpu; newReg,orgReg: tsuperregister): boolean;
+var
+ opCount: longint;
+begin
+ doReplaceReadReg := false;
+ { handle special case }
+ case p.opcode of
+ A_IMUL:
+ begin
+ case p.ops of
+ 1: internalerror(1301001);
+ 2,3:
+ begin
+ if changeOp(p.oper[0]^,newReg,orgReg) then
+ begin
+{ updateStates(orgReg,newReg,p,false);}
+ doReplaceReadReg := true;
+ end;
+ if p.ops = 3 then
+ if changeOp(p.oper[1]^,newReg,orgReg) then
+ begin
+{ updateStates(orgReg,newReg,p,false);}
+ doReplaceReadReg := true;
+ end;
+ end;
+ end;
+ end;
+ A_DIV,A_IDIV,A_MUL: internalerror(1301002);
+ else
+ begin
+ for opCount := 0 to p.ops-1 do
+ if p.oper[opCount]^.typ = top_ref then
+ if changeOp(p.oper[opCount]^,newReg,orgReg) then
+ begin
+{ updateStates(orgReg,newReg,p,false);}
+ doReplaceReadReg := true;
+ end;
+ for opCount := 1 to maxinschanges do
+ case InsProp[p.opcode].Ch[opCount] of
+ Ch_ROp1:
+ if p.oper[0]^.typ = top_reg then
+ if changeReg(p.oper[0]^.reg,newReg,orgReg) then
+ begin
+{ updateStates(orgReg,newReg,p,false);}
+ doReplaceReadReg := true;
+ end;
+ Ch_ROp2:
+ if p.oper[1]^.typ = top_reg then
+ if changeReg(p.oper[1]^.reg,newReg,orgReg) then
+ begin
+{ updateStates(orgReg,newReg,p,false);}
+ doReplaceReadReg := true;
+ end;
+ Ch_ROp3:
+ if p.oper[2]^.typ = top_reg then
+ if changeReg(p.oper[2]^.reg,newReg,orgReg) then
+ begin
+{ updateStates(orgReg,newReg,p,false);}
+ doReplaceReadReg := true;
+ end;
+ end;
+ end;
+ end;
+end;
+
+
+procedure updateState(supreg: tsuperregister; p: tai);
+{ this procedure updates the read and write states of the instructions }
+{ coming after p. It's called when the read/write state of p has been }
+{ changed and this change has to be propagated to the following }
+{ instructions as well }
+var
+ newRState, newWState: byte;
+ prevRState, prevWState: byte;
+ doRState, doWState: boolean;
+begin
+ { get the new read/write states from p }
+ with ptaiprop(p.optinfo)^.regs[supreg] do
+ begin
+ newRState := rState;
+ newWState := wState;
+ end;
+ if not GetNextInstruction(p,p) then
+ exit;
+ { get the old read/write states from the next instruction, to know }
+ { when we can stop updating }
+ with ptaiprop(p.optinfo)^.regs[supreg] do
+ begin
+ prevRState := rState;
+ prevWState := wState;
+ end;
+ { adjust the states if this next instruction reads/writes the register }
+ if regReadByInstruction(supreg,p) then
+ incState(newRState,1);
+ if regModifiedByInstruction(supreg,p) then
+ incState(newWState,1);
+ { do we still have to update the read and/or write states? }
+ doRState := true;
+ doWState := true;
+ repeat
+ { update the states }
+ with ptaiprop(p.optinfo)^.regs[supreg] do
+ begin
+ if doRState then
+ rState := newRState;
+ if doWState then
+ wState := newWState;
+ end;
+ if not getNextInstruction(p,p) then
+ break;
+ with ptaiprop(p.optinfo)^.regs[supreg] do
+ begin
+ { stop updating the read state if it changes }
+ doRState :=
+ doRState and (rState = prevRState);
+ { if, by accident, this changed state is the same as the one }
+ { we've been using, change it to a value that's definitely }
+ { different from the previous and next state }
+ if not doRState and
+ (rState = newRState) then
+ begin
+ incState(newRState,1);
+ prevRState := rState;
+ doRState := true;
+ end;
+ { ditto for the write state }
+ doWState :=
+ doWState and (WState = prevWState);
+ if not doWState and
+ (wState = newWState) then
+ begin
+ incState(newWState,1);
+ prevWState := wState;
+ doWState := true;
+ end;
+ end;
+ { stop when we don't have to update either state anymore }
+ until not(doRState or doWState);
+end;
+
+
+function storeBack(start, current: tai; orgReg, newReg: tsuperregister): boolean;
+{ returns true if p1 contains an instruction that stores the contents }
+{ of newReg back to orgReg }
+begin
+ storeback := false;
+ if (current.typ = ait_instruction) and
+ (taicpu(current).opcode = A_MOV) and
+ (taicpu(current).oper[0]^.typ = top_reg) and
+ (getsupreg(taicpu(current).oper[0]^.reg) = newReg) and
+ (taicpu(current).oper[1]^.typ = top_reg) and
+ (getsupreg(taicpu(current).oper[1]^.reg) = orgReg) then
+ case taicpu(current).opsize of
+ S_B:
+ storeback := true;
+ S_W:
+ storeback := taicpu(start).opsize <> S_B;
+ S_L:
+ storeback := taicpu(start).opsize = S_L;
+ else
+ internalerror(2003121501);
+ end;
+end;
+
+
+function canreplacereg(orgsupreg, newsupreg: tsuperregister; p: tai;
+ orgRegCanBeModified: boolean; var resnewregmodified, resorgregread, resremovelast: boolean; var returnendp: tai): boolean;
+var
+ endP, hp: tai;
+ removeLast, sequenceEnd, tmpResult, newRegModified, orgRegRead: boolean;
+begin
+ canreplacereg := false;
+ tmpResult := true;
+ sequenceEnd := false;
+ newRegModified := false;
+ orgRegRead := false;
+ removeLast := false;
+ endP := p;
+ while tmpResult and not sequenceEnd do
+ begin
+ tmpResult :=
+ getNextInstruction(endP,endP) and
+ (endp.typ = ait_instruction) and
+ not(taicpu(endp).is_jmp);
+ if tmpresult and not assigned(endp.optinfo) then
+ begin
+{ hp := tai_comment.Create(strpnew('next no optinfo'));
+ hp.next := endp;
+ hp.previous := endp.previous;
+ endp.previous := hp;
+ if assigned(hp.previous) then
+ hp.previous.next := hp;}
+ exit;
+ end;
+ if tmpResult and
+ { don't take into account instructions that will be removed }
+ not (ptaiprop(endp.optinfo)^.canBeRemoved) then
+ begin
+ { if the newsupreg gets stored back to the oldReg, we can change }
+ { "mov %oldReg,%newReg; <operations on %newReg>; mov %newReg, }
+ { %oldReg" to "<operations on %oldReg>" }
+ removeLast := storeBack(p,endP, orgsupreg, newsupreg);
+ sequenceEnd :=
+ { no support for (i)div, mul and imul with hardcoded operands }
+ noHardCodedRegs(taicpu(endP),orgsupreg,newsupreg) and
+ { if newsupreg gets loaded with a new value, we can stop }
+ { replacing newsupreg with oldReg here (possibly keeping }
+ { the original contents of oldReg so we still know them }
+ { afterwards) }
+ (RegLoadedWithNewValue(newsupreg,true,taicpu(endP)) or
+ { we can also stop if we reached the end of the use of }
+ { newReg's current contents }
+ (GetNextInstruction(endp,hp) and
+ FindRegDealloc(newsupreg,hp)));
+ { to be able to remove the first and last instruction of }
+ { movl %reg1, %reg2 }
+ { <operations on %reg2> (replacing reg2 with reg1 here) }
+ { movl %reg2, %reg1 }
+ { %reg2 must not be use afterwards (it can be as the }
+ { result of a peepholeoptimization) }
+ removeLast := removeLast and sequenceEnd;
+ newRegModified :=
+ newRegModified or
+ (not(regLoadedWithNewValue(newsupreg,true,taicpu(endP))) and
+ RegModifiedByInstruction(newsupreg,endP));
+ orgRegRead := newRegModified and RegReadByInstruction(orgsupreg,endP);
+ sequenceEnd := SequenceEnd and
+ (removeLast or
+ { since newsupreg will be replaced by orgsupreg, we can't allow that newsupreg }
+ { gets modified if orgsupreg is still read afterwards (since after }
+ { replacing, this would mean that orgsupreg first gets modified and then }
+ { gets read in the assumption it still contains the unmodified value) }
+ not(newRegModified and orgRegRead)) (* and
+ { since newsupreg will be replaced by orgsupreg, we can't allow that newsupreg }
+ { gets modified if orgRegCanBeModified = false }
+
+ { this now gets checked after the loop (JM) }
+ (orgRegCanBeModified or not(newRegModified)) *);
+ tmpResult :=
+ not(removeLast) and
+ not(newRegModified and orgRegRead) and
+(* (orgRegCanBeModified or not(newRegModified)) and *)
+(* already checked at the top
+ (endp.typ = ait_instruction) and *)
+ NoHardCodedRegs(taicpu(endP),orgsupreg,newsupreg) and
+ RegSizesOk(orgsupreg,newsupreg,taicpu(endP)) and
+ not RegModifiedByInstruction(orgsupreg,endP);
+ end;
+ end;
+ canreplacereg := sequenceEnd and
+ (removeLast or
+ (orgRegCanBeModified or not(newRegModified))) and
+ (not(assigned(endp)) or
+ not(endp.typ = ait_instruction) or
+ (noHardCodedRegs(taicpu(endP),orgsupreg,newsupreg) and
+ RegSizesOk(orgsupreg,newsupreg,taicpu(endP)) and
+ not(newRegModified and
+ (orgsupreg in ptaiprop(endp.optinfo)^.usedRegs) and
+ not(RegLoadedWithNewValue(orgsupreg,true,taicpu(endP))))));
+ if canreplacereg then
+ begin
+ resnewregmodified := newregmodified;
+ resorgregread := orgregread;
+ resremovelast := removelast;
+ end;
+ { needed for replaceregdebug code }
+ returnendp := endp;
+end;
+
+
+
+function ReplaceReg(asml: TAsmList; orgsupreg, newsupreg: tsuperregister; p,
+ seqstart: tai; const c: TContent; orgRegCanBeModified: Boolean;
+ var returnEndP: tai): Boolean;
+{ Tries to replace orgsupreg with newsupreg in all instructions coming after p }
+{ until orgsupreg gets loaded with a new value. Returns true if successful, }
+{ false otherwise. if successful, the contents of newsupreg are set to c, }
+{ which should hold the contents of newsupreg before the current sequence }
+{ started }
+{ if the function returns true, returnEndP holds the last instruction }
+{ where newsupreg was replaced by orgsupreg }
+var
+ endP, hp: tai;
+ removeLast, newRegModified, orgRegRead,
+ stateChanged, readStateChanged: Boolean;
+{$ifdef replaceregdebug}
+ l: longint;
+{$endif replaceregdebug}
+
+begin
+ replacereg := false;
+ if canreplacereg(orgsupreg,newsupreg,p,orgregcanbemodified,newregmodified, orgregread, removelast,endp) then
+ begin
+{$ifdef replaceregdebug}
+ l := random(1000);
+ hp := tai_comment.Create(strpnew(
+ 'replacing '+std_regname(newreg(R_INTREGISTER,newsupreg,R_SUBWHOLE))+' with '+std_regname(newreg(R_INTREGISTER,orgsupreg,R_SUBWHOLE))+
+ ' from here... '+tostr(l)));
+ insertllitem(asml,p.previous,p,hp);
+ hp := tai_comment.Create(strpnew(
+ 'replaced '+std_regname(newreg(R_INTREGISTER,newsupreg,R_SUBWHOLE))+' with '+std_regname(newreg(R_INTREGISTER,orgsupreg,R_SUBWHOLE))+
+ ' till here ' + tostr(l)));
+ insertllitem(asml,endp,endp.next,hp);
+{$endif replaceregdebug}
+ replaceReg := true;
+ returnEndP := endP;
+
+ if not getNextInstruction(p,hp) then
+ exit;
+ stateChanged := false;
+ while hp <> endP do
+ begin
+ if {not(ptaiprop(hp.optinfo)^.canBeRemoved) and }
+ (hp.typ = ait_instruction) then
+ stateChanged :=
+ doReplaceReg(taicpu(hp),newsupreg,orgsupreg) or stateChanged;
+ if stateChanged then
+ updateStates(orgsupreg,newsupreg,hp,true);
+ getNextInstruction(hp,hp)
+ end;
+ if assigned(endp) and (endp.typ = ait_instruction) then
+ readStateChanged :=
+ doReplaceReadReg(taicpu(endP),newsupreg,orgsupreg);
+ if stateChanged or readStateChanged then
+ updateStates(orgsupreg,newsupreg,endP,stateChanged);
+
+ if stateChanged or readStateChanged then
+ updateState(orgsupreg,endP);
+
+{ We replaced newreg with oldreg between p and endp, so restore the contents }
+{ of newreg there with its contents from before the sequence. }
+ if removeLast or
+ RegLoadedWithNewValue(newsupreg,true,endP) then
+ GetLastInstruction(endP,hp)
+ else hp := endP;
+ RestoreRegContentsTo(asml,newsupreg,c,seqstart,hp);
+
+{ Ot is possible that the new register was modified (e.g. an add/sub), so if }
+{ it was replaced by oldreg in that instruction, oldreg's contents have been }
+{ changed. To take this into account, we simply set the contents of orgsupreg }
+{ to "unknown" after this sequence }
+ if newRegModified then
+ ClearRegContentsFrom(asml,orgsupreg,p,hp);
+ if removeLast then
+ ptaiprop(endp.optinfo)^.canBeRemoved := true;
+ allocRegBetween(asml,newreg(R_INTREGISTER,orgsupreg,R_SUBWHOLE),p,endP,ptaiprop(p.optinfo)^.usedregs);
+
+ end
+{$ifdef replaceregdebug}
+ else
+ begin
+ l := random(1000);
+ hp := tai_comment.Create(strpnew(
+ 'replacing '+std_regname(newreg(R_INTREGISTER,newsupreg,R_SUBWHOLE))+' with '+std_regname(newreg(R_INTREGISTER,orgsupreg,R_SUBWHOLE))+
+ ' from here... '+ tostr(l)));
+ insertllitem(asml,p.previous,p,hp);
+ hp := tai_comment.Create(strpnew(
+ 'replacing '+std_regname(newreg(R_INTREGISTER,newsupreg,R_SUBWHOLE))+' with '+std_regname(newreg(R_INTREGISTER,orgsupreg,R_SUBWHOLE))+
+ ' failed here ' + tostr(l)));
+ insertllitem(asml,endp,endp.next,hp);
+ end;
+{$endif replaceregdebug}
+end;
+
+
+function FindRegWithConst(p: tai; size: topsize; l: aint; var Res: TRegister): Boolean;
+{Finds a register which contains the constant l}
+var
+ Counter: tsuperregister;
+{$ifdef testing}
+ hp: tai;
+{$endif testing}
+begin
+ Result:=false;
+ Counter := RS_EAX;
+ repeat
+{$ifdef testing}
+ if (ptaiprop(p.optinfo)^.regs[counter].typ in [con_const,con_noRemoveConst]) then
+ begin
+ hp := tai_comment.Create(strpnew(
+ 'checking const load of '+tostr(l)+' here...'));
+ hp.next := ptaiprop(p.optinfo)^.Regs[Counter].StartMod;
+ hp.previous := ptaiprop(p.optinfo)^.Regs[Counter].StartMod^.previous;
+ ptaiprop(p.optinfo)^.Regs[Counter].StartMod^.previous := hp;
+ if assigned(hp.previous) then
+ hp.previous.next := hp;
+ end;
+{$endif testing}
+ if (ptaiprop(p.optinfo)^.regs[counter].typ in [con_const,con_noRemoveConst]) and
+ (taicpu(ptaiprop(p.optinfo)^.Regs[Counter].StartMod).opsize = size) and
+ (taicpu(ptaiprop(p.optinfo)^.Regs[Counter].StartMod).oper[0]^.typ = top_const) and
+ (taicpu(ptaiprop(p.optinfo)^.Regs[Counter].StartMod).oper[0]^.val = l) then
+ begin
+ res:=taicpu(ptaiprop(p.optinfo)^.Regs[Counter].StartMod).oper[1]^.reg;
+ result:=true;
+ exit;
+ end;
+ inc(counter);
+ until (Counter > RS_EDI);
+end;
+
+
+procedure removePrevNotUsedLoad(asml: TAsmList; p: tai; supreg: tsuperregister; check: boolean);
+{ if check = true, it means the procedure has to check whether it isn't }
+{ possible that the contents are still used after p (used when removing }
+{ instructions because of a "call"), otherwise this is not necessary }
+{ (e.g. when you have a "mov 8(%ebp),%eax", you can be sure the previous }
+{ value of %eax isn't used anymore later on) }
+var
+ hp1, next, beforestartmod: tai;
+begin
+ if getLastInstruction(p,hp1) then
+ with ptaiprop(hp1.optinfo)^.regs[supreg] do
+ if (typ in [con_ref,con_invalid,con_const]) and
+ (nrofMods = 1) and
+ (rState = ptaiprop(startmod.optinfo)^.regs[supreg].rState) and
+ (not(check) or
+ (not(regInInstruction(supreg,p)) and
+ (not(supreg in ptaiprop(hp1.optinfo)^.usedRegs) or
+ findRegDealloc(supreg,p)))) then
+ begin
+ ptaiprop(startMod.optinfo)^.canBeRemoved := true;
+ getnextinstruction(p,next);
+ { give the register that was modified by this instruction again }
+ { the contents it had before this instruction }
+ if getlastinstruction(startmod,beforestartmod) then
+ RestoreRegContentsTo(asml,supreg,ptaiprop(beforestartmod.optinfo)^.regs[supreg],
+ startmod,hp1)
+ else
+ ClearRegContentsFrom(asml,supreg,startmod,hp1);
+ end;
+end;
+
+
+{$ifdef notused}
+function is_mov_for_div(p: taicpu): boolean;
+begin
+ is_mov_for_div :=
+ (p.opcode = A_MOV) and
+ (p.oper[0]^.typ = top_const) and
+ (p.oper[1]^.typ = top_reg) and
+ (p.oper[1]^.reg = RS_EDX) and
+ getNextInstruction(p,p) and
+ (p.typ = ait_instruction) and
+ ((p.opcode = A_DIV) or
+ (p.opcode = A_IDIV));
+end;
+{$endif notused}
+
+
+function memtoreg(t: taicpu; const ref: treference; var startp: tai): tregister;
+var
+ hp: tai;
+ p: ptaiprop;
+ regcounter: tsuperregister;
+ optimizable: boolean;
+begin
+ if not getlastinstruction(t,hp) or
+ not issimplememloc(ref) then
+ begin
+ memtoreg := NR_NO;
+ exit;
+ end;
+ p := ptaiprop(hp.optinfo);
+ optimizable := false;
+ for regcounter := RS_EAX to RS_EDI do
+ begin
+ if (assigned(p^.regs[regcounter].memwrite) and
+ refsequal(ref,p^.regs[regcounter].memwrite.oper[1]^.ref^)) then
+ begin
+ optimizable := true;
+ hp := p^.regs[regcounter].memwrite;
+ end
+ else if ((p^.regs[regcounter].typ in [CON_REF,CON_NOREMOVEREF]) and
+ (p^.regs[regcounter].nrofmods = 1) and
+ ((taicpu(p^.regs[regcounter].startmod).opcode = A_MOV) or
+ (taicpu(p^.regs[regcounter].startmod).opcode = A_MOVZX) or
+ (taicpu(p^.regs[regcounter].startmod).opcode = A_MOVSX)) and
+ (taicpu(p^.regs[regcounter].startmod).oper[0]^.typ = top_ref) and
+ refsequal(ref,taicpu(p^.regs[regcounter].startmod).oper[0]^.ref^)) then
+ begin
+ optimizable := true;
+ hp := p^.regs[regcounter].startmod;
+ end;
+ if optimizable then
+ if ((t.opsize <> S_B) or
+ not(regcounter in [RS_ESI,RS_EDI])) and
+ sizescompatible(taicpu(hp).opsize,t.opsize) then
+ begin
+ case t.opsize of
+ S_B:
+ begin
+ memtoreg := newreg(R_INTREGISTER,regcounter,R_SUBL)
+ end;
+ S_W,S_BW:
+ begin
+ memtoreg := newreg(R_INTREGISTER,regcounter,R_SUBW);
+ if (t.opsize = S_BW) then
+ begin
+ t.opcode := A_MOV;
+ t.opsize := S_W;
+ end;
+ end;
+ S_L,S_BL,S_WL:
+ begin
+ memtoreg := newreg(R_INTREGISTER,regcounter,R_SUBWHOLE);
+ if (t.opsize <> S_L) then
+ begin
+ t.opcode := A_MOV;
+ t.opsize := S_L;
+ end;
+ end;
+ end;
+ startp := hp;
+ exit;
+ end;
+ end;
+ memtoreg := NR_NO;
+end;
+
+
+procedure removeLocalStores(const t1: tai);
+{var
+ p: tai;
+ regcount: tregister; }
+begin
+{
+ for regcount := LoGPReg to HiGPReg do
+ if assigned(pTaiProp(t1.optinfo)^.regs[regcount].memwrite) and
+ (taicpu(pTaiProp(t1.optinfo)^.regs[regcount].memwrite).oper[1]^.ref^.base
+ = current_procinfo.framepointer) then
+ begin
+ pTaiProp(pTaiProp(t1.optinfo)^.regs[regcount].memwrite.optinfo)^.canberemoved := true;
+ clearmemwrites(pTaiProp(t1.optinfo)^.regs[regcount].memwrite,regcount);
+ end;
+}
+end;
+
+
+procedure loadcseregs(asml: TAsmList; const reginfo: toptreginfo; curseqend, prevseqstart, curseqstart, curprev: tai; cnt: longint);
+var
+ regsloaded: tregset;
+ regloads, reguses: array[RS_EAX..RS_EDI] of tai;
+ regcounter: tsuperregister;
+ hp, hp2: tai;
+ insertpos, insertoptinfo, prevseq_next: tai;
+ i: longint;
+ opc: tasmop;
+begin
+ regsloaded := [];
+ fillchar(regloads,sizeof(regloads),0);
+ fillchar(reguses,sizeof(reguses),0);
+ getnextinstruction(prevseqstart,prevseq_next);
+ for regcounter := RS_EAX To RS_EDI do
+ if (reginfo.new2oldreg[regcounter] <> RS_INVALID) Then
+ begin
+ include(regsloaded,regcounter);
+ if assigned(ptaiprop(prevseqstart.optinfo)^.Regs[reginfo.new2oldreg[regcounter]].StartMod) then
+ AllocRegBetween(asml,newreg(R_INTREGISTER,reginfo.new2oldreg[regcounter],R_SUBWHOLE),
+ ptaiprop(prevseqstart.optinfo)^.Regs[reginfo.new2oldreg[regcounter]].StartMod,curseqstart,
+ ptaiprop(ptaiprop(prevseqstart.optinfo)^.Regs[reginfo.new2oldreg[regcounter]].StartMod.optinfo)^.usedregs)
+ else
+ AllocRegBetween(asml,newreg(R_INTREGISTER,reginfo.new2oldreg[regcounter],R_SUBWHOLE),
+ prevseqstart,curseqstart,ptaiprop(prevseqstart.optinfo)^.usedregs);
+
+ if curprev <> prevseqstart then
+ begin
+ if assigned(reginfo.lastReload[regCounter]) then
+ getLastInstruction(reginfo.lastReload[regCounter],hp)
+ else if assigned(reginfo.lastReload[reginfo.new2oldreg[regCounter]]) then
+ getLastInstruction(reginfo.lastReload[reginfo.new2OldReg[regCounter]],hp)
+ else
+ hp := curprev;
+ clearRegContentsFrom(asml,regCounter,prevSeq_next,hp);
+ getnextInstruction(hp,hp);
+ allocRegBetween(asml,newreg(R_INTREGISTER,regCounter,R_SUBWHOLE),prevseqstart,hp,
+ ptaiprop(prevseqstart.optinfo)^.usedregs);
+ end;
+ if not(regcounter in reginfo.RegsLoadedforRef) and
+ {old reg new reg}
+ (reginfo.new2oldreg[regcounter] <> regcounter) then
+ begin
+ getLastInstruction(curseqend,hp);
+ opc := A_MOV;
+ insertpos := prevseq_next;
+ insertoptinfo := prevseqstart;
+ if assigned(reguses[regcounter]) then
+ if assigned(regloads[reginfo.new2oldreg[regcounter]]) then
+ opc := A_XCHG
+ else
+ begin
+ insertoptinfo := reguses[regcounter];
+ insertpos := tai(insertoptinfo.next)
+ end
+ else
+ if assigned(regloads[reginfo.new2oldreg[regcounter]]) then
+ begin
+ insertpos := regloads[reginfo.new2oldreg[regcounter]];
+ if not getlastinstruction(insertpos,insertoptinfo) then
+ internalerror(2006060701);
+ end;
+ hp := Tai_Marker.Create(mark_NoPropInfoStart);
+ InsertLLItem(asml, insertpos.previous,insertpos, hp);
+ hp2 := taicpu.Op_Reg_Reg(opc, S_L,
+ {old reg new reg}
+ newreg(R_INTREGISTER,reginfo.new2oldreg[regcounter],R_SUBWHOLE), newreg(R_INTREGISTER,regcounter,R_SUBWHOLE));
+ if (opc = A_XCHG) and
+ (taicpu(regloads[reginfo.new2oldreg[regcounter]]).opcode <> A_XCHG) then
+ begin
+ asml.remove(regloads[reginfo.new2oldreg[regcounter]]);
+ regloads[reginfo.new2oldreg[regcounter]].free;
+ regloads[reginfo.new2oldreg[regcounter]] := hp2;
+ reguses[regcounter] := hp2;
+ end;
+ regloads[regcounter] := hp2;
+ reguses[reginfo.new2oldreg[regcounter]] := hp2;
+ new(ptaiprop(hp2.optinfo));
+ ptaiprop(hp2.optinfo)^ := ptaiprop(insertoptinfo.optinfo)^;
+ ptaiprop(hp2.optinfo)^.canBeRemoved := false;
+ InsertLLItem(asml, insertpos.previous, insertpos, hp2);
+ hp := Tai_Marker.Create(mark_NoPropInfoEnd);
+ InsertLLItem(asml, insertpos.previous, insertpos, hp);
+ { adjusts states in previous instruction so that it will }
+ { definitely be different from the previous or next state }
+ incstate(ptaiprop(hp2.optinfo)^.
+ regs[reginfo.new2oldreg[regcounter]].rstate,20);
+ incstate(ptaiprop(hp2.optinfo)^.
+ regs[regCounter].wstate,20);
+ updateState(reginfo.new2oldreg[regcounter],hp2);
+ updateState(regcounter,hp2);
+ end
+ else
+ { imagine the following code: }
+ { normal wrong optimized }
+ { movl 8(%ebp), %eax movl 8(%ebp), %eax }
+ { movl (%eax), %eax movl (%eax), %eax }
+ { cmpl 8(%ebp), %eax cmpl 8(%ebp), %eax }
+ { jne l1 jne l1 }
+ { movl 8(%ebp), %eax }
+ { movl (%eax), %edi movl %eax, %edi }
+ { movl %edi, -4(%ebp) movl %edi, -4(%ebp) }
+ { movl 8(%ebp), %eax }
+ { pushl 70(%eax) pushl 70(%eax) }
+ { }
+ { The error is that at the moment that the last instruction is executed, }
+ { %eax doesn't contain 8(%ebp) anymore. Solution: the contents of }
+ { registers that are completely removed from a sequence (= registers in }
+ { RegLoadedforRef), have to be changed to their contents from before the }
+ { sequence. }
+ { if regcounter in reginfo.RegsLoadedforRef then }
+ begin
+ hp := curseqstart;
+ { cnt still holds the number of instructions }
+ { of the sequence, so go to the end of it }
+ for i := 1 to pred(cnt) do
+ getNextInstruction(hp,hp);
+ { curprev = instruction prior to start of sequence }
+ restoreRegContentsTo(asml,regCounter,
+ ptaiprop(curprev.optinfo)^.Regs[regcounter],
+ curseqstart,hp);
+ end;
+ end;
+end;
+
+
+procedure replaceoperandwithreg(asml: TAsmList; p: tai; opnr: byte; reg: tregister);
+var
+ hp: tai;
+begin
+ { new instruction -> it's info block is not in the big one allocated at the start }
+ hp := Tai_Marker.Create(mark_NoPropInfoStart);
+ InsertLLItem(asml, p.previous,p, hp);
+ { duplicate the original instruction and replace it's designated operant with the register }
+ hp := tai(p.getcopy);
+ taicpu(hp).loadreg(opnr,reg);
+ { add optimizer state info }
+ new(ptaiprop(hp.optinfo));
+ ptaiprop(hp.optinfo)^ := ptaiprop(p.optinfo)^;
+ { new instruction can not be removed }
+ ptaiprop(hp.optinfo)^.canBeRemoved := false;
+ { but the old one can }
+ ptaiprop(p.optinfo)^.canBeRemoved := true;
+ { insert end marker }
+ InsertLLItem(asml, p.previous, p, hp);
+ hp := Tai_Marker.Create(mark_NoPropInfoEnd);
+ InsertLLItem(asml, p.previous, p, hp);
+end;
+
+
+procedure doCSE(asml: TAsmList; First, Last: tai; findPrevSeqs, doSubOpts: boolean);
+{marks the instructions that can be removed by RemoveInstructs. They're not
+ removed immediately because sometimes an instruction needs to be checked in
+ two different sequences}
+var cnt, cnt2, {cnt3,} orgNrofMods: longint;
+ p, hp1, hp2, prevSeq: tai;
+ hp4: tai;
+ hp5 : tai;
+ reginfo: toptreginfo;
+ memreg: tregister;
+ regcounter: tsuperregister;
+begin
+ p := First;
+ SkipHead(p);
+ while (p <> Last) do
+ begin
+ case p.typ of
+ ait_align:
+ if not(tai_align(p).use_op) then
+ SetAlignReg(p);
+ ait_instruction:
+ begin
+ case taicpu(p).opcode of
+{
+ Does not work anymore with register calling because the registers are
+ released before the call
+ A_CALL:
+ for regCounter := RS_EAX to RS_EBX do
+ removePrevNotUsedLoad(asml,p,regCounter,true);
+}
+ A_CLD: if GetLastInstruction(p, hp1) and
+ (ptaiprop(hp1.optinfo)^.DirFlag = F_NotSet) then
+ ptaiprop(tai(p).optinfo)^.CanBeRemoved := True;
+ A_LEA, A_MOV, A_MOVZX, A_MOVSX:
+ begin
+ hp2 := p;
+ case taicpu(p).oper[0]^.typ of
+ top_ref, top_reg:
+ if (taicpu(p).oper[1]^.typ = top_reg) then
+ begin
+ With ptaiprop(p.optinfo)^.Regs[getsupreg(taicpu(p).oper[1]^.reg)] do
+ begin
+ if (startmod = p) then
+ orgNrofMods := nrofMods
+ else
+ orgNrofMods := 0;
+ if (p = StartMod) and
+ GetLastInstruction (p, hp1) and
+ not(hp1.typ in [ait_marker,ait_label]) then
+{so we don't try to check a sequence when p is the first instruction of the block}
+ begin
+{$ifdef csdebug}
+ hp5 := tai_comment.Create(strpnew(
+ 'cse checking '+std_regname(taicpu(p).oper[1]^.reg)));
+ insertLLItem(asml,p,p.next,hp5);
+{$endif csdebug}
+ if CheckSequence(p,prevSeq,getsupreg(taicpu(p).oper[1]^.reg), Cnt, reginfo, findPrevSeqs) and
+ (Cnt > 0) then
+ begin
+(*
+ hp1 := nil;
+{ although it's perfectly ok to remove an instruction which doesn't contain }
+{ the register that we've just checked (CheckSequence takes care of that), }
+{ the sequence containing this other register should also be completely }
+{ checked and removed, otherwise we may get situations like this: }
+{ }
+{ movl 12(%ebp), %edx movl 12(%ebp), %edx }
+{ movl 16(%ebp), %eax movl 16(%ebp), %eax }
+{ movl 8(%edx), %edx movl 8(%edx), %edx }
+{ movl (%eax), eax movl (%eax), eax }
+{ cmpl %eax, %edx cmpl %eax, %edx }
+{ jnz l123 getting converted to jnz l123 }
+{ movl 12(%ebp), %edx movl 4(%eax), eax }
+{ movl 16(%ebp), %eax }
+{ movl 8(%edx), %edx }
+{ movl 4(%eax), eax }
+*)
+
+{ not anymore: if the start of a new sequence is found while checking (e.g. }
+{ above that of eax while checking edx, this new sequence is automatically }
+{ also checked }
+ Cnt2 := 1;
+ while Cnt2 <= Cnt do
+ begin
+{$ifndef noremove}
+ ptaiprop(p.optinfo)^.CanBeRemoved := True
+{$endif noremove}
+ ; inc(Cnt2);
+ GetNextInstruction(p, p);
+ end;
+ {hp4 is used to get the contents of the registers before the sequence}
+ GetLastInstruction(hp2, hp4);
+
+{$IfDef CSDebug}
+ for regcounter := RS_EAX To RS_EDI do
+ if (regcounter in reginfo.RegsLoadedforRef) then
+ begin
+ hp5 := tai_comment.Create(strpnew('New: '+std_regname(newreg(R_INTREGISTER,regcounter,R_SUBNONE))+', Old: '+
+ std_regname(newreg(R_INTREGISTER,reginfo.new2oldreg[regcounter],R_SUBNONE))));
+ InsertLLItem(asml, tai(hp2.previous), hp2, hp5);
+ end;
+{$EndIf CSDebug}
+ { if some registers were different in the old and the new sequence, move }
+ { the contents of those old registers to the new ones }
+ loadcseregs(asml,reginfo,p,prevseq,hp2,hp4,cnt);
+ continue;
+ end
+ end;
+ end;
+ { try to replace the new reg with the old reg }
+ if not(ptaiprop(p.optinfo)^.canBeRemoved) then
+ if (taicpu(p).oper[0]^.typ = top_reg) and
+ (taicpu(p).oper[1]^.typ = top_reg) and
+ { only remove if we're not storing something in a regvar }
+ (getsupreg(taicpu(p).oper[1]^.reg) in [RS_EAX,RS_EBX,RS_ECX,RS_EDX,RS_ESI,RS_EDI]) and
+{ (taicpu(p).oper[1]^.reg in (rg.usableregsint+[RS_EDI])) and}
+ (taicpu(p).opcode = A_MOV) and
+ getLastInstruction(p,hp4) and
+ { we only have to start replacing from the instruction after the mov, }
+ { but replacereg only starts with getnextinstruction(p,p) }
+ replaceReg(asml,getsupreg(taicpu(p).oper[0]^.reg),
+ getsupreg(taicpu(p).oper[1]^.reg),p,p,
+ ptaiprop(hp4.optinfo)^.regs[getsupreg(taicpu(p).oper[1]^.reg)],false,hp1) then
+ begin
+ ptaiprop(p.optinfo)^.canBeRemoved := true;
+ { this is just a regular move that was here, so the source register should be }
+ { allocated already at this point -> only allocate from here onwards }
+ if not(getsupreg(taicpu(p).oper[0]^.reg) in pTaiProp(p.optinfo)^.usedregs) then
+ internalerror(2004101011);
+ allocRegBetween(asml,taicpu(p).oper[0]^.reg,
+ p,hp1,pTaiProp(p.optinfo)^.usedregs)
+ end
+ else
+ begin
+ if (taicpu(p).oper[1]^.typ = top_reg) and
+ not regInOp(getsupreg(taicpu(p).oper[1]^.reg),taicpu(p).oper[0]^) then
+ removePrevNotUsedLoad(asml,p,getsupreg(taicpu(p).oper[1]^.reg),false);
+ if doSubOpts and
+ (taicpu(p).opcode <> A_LEA) and
+ (taicpu(p).oper[0]^.typ = top_ref) then
+ begin
+ memreg :=
+ memtoreg(taicpu(p),
+ taicpu(p).oper[0]^.ref^,hp5);
+ if memreg <> NR_NO then
+ if (taicpu(p).opcode = A_MOV) and
+ (taicpu(p).oper[1]^.typ = top_reg) and
+ (taicpu(p).oper[1]^.reg = memreg) then
+ begin
+ pTaiProp(p.optinfo)^.canberemoved := true;
+ allocregbetween(asml,memreg,hp5,p,ptaiprop(hp5.optinfo)^.usedregs);
+ end
+ else
+ begin
+ replaceoperandwithreg(asml,p,0,memreg);
+ allocregbetween(asml,memreg,hp5,p,ptaiprop(hp5.optinfo)^.usedregs);
+ regcounter := getsupreg(memreg);
+ incstate(pTaiProp(p.optinfo)^.regs[regcounter].rstate,1);
+ updatestate(regcounter,p);
+ end;
+ end;
+ end;
+ { at first, only try optimizations of large blocks, because doing }
+ { doing smaller ones may prevent bigger ones from completing in }
+ { in the next pass }
+ if not doSubOpts and (orgNrofMods <> 0) then
+ begin
+ p := hp2;
+ for cnt := 1 to pred(orgNrofMods) do
+ getNextInstruction(p,p);
+ end;
+ end;
+ top_Const:
+ begin
+ case taicpu(p).oper[1]^.typ of
+ Top_Reg:
+ begin
+ regCounter := getsupreg(taicpu(p).oper[1]^.reg);
+ if GetLastInstruction(p, hp1) then
+ With ptaiprop(hp1.optinfo)^.Regs[regCounter] do
+ if (typ in [con_const,con_noRemoveConst]) and
+ (taicpu(startMod).opsize >= taicpu(p).opsize) and
+ opsequal(taicpu(StartMod).oper[0]^,taicpu(p).oper[0]^) then
+ begin
+ ptaiprop(p.optinfo)^.CanBeRemoved := True;
+ allocRegBetween(asml,taicpu(p).oper[1]^.reg,startmod,p,
+ ptaiprop(startmod.optinfo)^.usedregs);
+ end
+ else
+ removePrevNotUsedLoad(asml,p,getsupreg(taicpu(p).oper[1]^.reg),false);
+
+ end;
+ Top_Ref:
+ if (taicpu(p).oper[0]^.typ = top_const) and
+ getLastInstruction(p,hp1) and
+ findRegWithConst(hp1,taicpu(p).opsize,taicpu(p).oper[0]^.val,memreg) then
+ begin
+ taicpu(p).loadreg(0,memreg);
+ { mark the used register as read }
+ incstate(ptaiprop(p.optinfo)^.
+ regs[getsupreg(memreg)].rstate,20);
+ updateState(getsupreg(memreg),p);
+ allocRegBetween(asml,memreg,
+ ptaiprop(hp1.optinfo)^.regs[getsupreg(memreg)].startMod,p,
+ ptaiprop(ptaiprop(hp1.optinfo)^.regs[getsupreg(memreg)].startMod.optinfo)^.usedregs);
+ end;
+ end;
+ end;
+ end;
+
+ end;
+ A_LEAVE:
+ begin
+ if getlastinstruction(p,hp1) then
+ removeLocalStores(hp1);
+ end;
+ A_STD: if GetLastInstruction(p, hp1) and
+ (ptaiprop(hp1.optinfo)^.DirFlag = F_Set) then
+ ptaiprop(tai(p).optinfo)^.CanBeRemoved := True;
+ else
+ begin
+ for cnt := 1 to maxinschanges do
+ begin
+ case InsProp[taicpu(p).opcode].Ch[cnt] of
+ Ch_ROp1:
+ if (taicpu(p).oper[0]^.typ = top_ref) and
+ ((taicpu(p).opcode < A_F2XM1) or
+ ((taicpu(p).opcode > A_IN) and
+ (taicpu(p).opcode < A_OUT)) or
+ (taicpu(p).opcode = A_PUSH) or
+ ((taicpu(p).opcode >= A_RCL) and
+ (taicpu(p).opcode <= A_XOR))) then
+ begin
+ memreg :=
+ memtoreg(taicpu(p),
+ taicpu(p).oper[0]^.ref^,hp5);
+ if memreg <> NR_NO then
+ begin
+ replaceoperandwithreg(asml,p,0,memreg);
+ allocregbetween(asml,memreg,hp5,p,ptaiprop(hp5.optinfo)^.usedregs);
+ regcounter := getsupreg(memreg);
+ incstate(pTaiProp(p.optinfo)^.regs[regcounter].rstate,1);
+ updatestate(regcounter,p);
+ end;
+ end;
+ Ch_MOp1:
+ if not(cs_opt_size in current_settings.optimizerswitches) and
+ (taicpu(p).oper[0]^.typ = top_ref) then
+ begin
+ memreg :=
+ memtoreg(taicpu(p),
+ taicpu(p).oper[0]^.ref^,hp5);
+ if (memreg <> NR_NO) and
+ (not getNextInstruction(p,hp1) or
+ (RegLoadedWithNewValue(getsupreg(memreg),false,hp1) or
+ FindRegDealloc(getsupreg(memreg),hp1))) then
+ begin
+ hp1 := Tai_Marker.Create(mark_NoPropInfoEnd);
+ insertllitem(asml,p,p.next,hp1);
+ hp1 := taicpu.op_reg_ref(A_MOV,reg2opsize(memreg),
+ memreg,taicpu(p).oper[0]^.ref^);
+ new(ptaiprop(hp1.optinfo));
+ pTaiProp(hp1.optinfo)^ := pTaiProp(p.optinfo)^;
+ insertllitem(asml,p,p.next,hp1);
+ regcounter := getsupreg(memreg);
+ incstate(pTaiProp(hp1.optinfo)^.regs[regcounter].rstate,1);
+ updatestate(regcounter,hp1);
+ hp1 := Tai_Marker.Create(mark_NoPropInfoStart);
+ insertllitem(asml,p,p.next,hp1);
+ replaceoperandwithreg(asml,p,0,memreg);
+ allocregbetween(asml,memreg,hp5,
+ tai(p.next.next),ptaiprop(hp5.optinfo)^.usedregs);
+ ClearRegContentsFrom(asml,regcounter,hp5,p);
+ end;
+ end;
+ Ch_ROp2:
+ if ((taicpu(p).opcode = A_CMP) or
+ (taicpu(p).opcode = A_TEST)) and
+ (taicpu(p).oper[1]^.typ = top_ref) then
+ begin
+ memreg :=
+ memtoreg(taicpu(p),
+ taicpu(p).oper[1]^.ref^,hp5);
+ if memreg <> NR_NO then
+ begin
+ replaceoperandwithreg(asml,p,1,memreg);
+ allocregbetween(asml,memreg,hp5,p,ptaiprop(hp5.optinfo)^.usedregs);
+ regcounter := getsupreg(memreg);
+ incstate(pTaiProp(p.optinfo)^.regs[regcounter].rstate,1);
+ updatestate(regcounter,p);
+ end;
+ end;
+ Ch_MOp2:
+ if not(cs_opt_size in current_settings.optimizerswitches) and
+ (taicpu(p).oper[1]^.typ = top_ref) and
+ ((taicpu(p).opcode < A_BT) or
+ ((taicpu(p).opcode > A_IN) and
+ (taicpu(p).opcode < A_OUT)) or
+ (taicpu(p).opcode = A_PUSH) or
+ ((taicpu(p).opcode >= A_RCL) and
+ (taicpu(p).opcode <= A_XOR))) then
+ begin
+ memreg :=
+ memtoreg(taicpu(p),
+ taicpu(p).oper[1]^.ref^,hp5);
+ if (memreg <> NR_NO) and
+ (not getNextInstruction(p,hp1) or
+ (RegLoadedWithNewValue(getsupreg(memreg),false,hp1) or
+ FindRegDealloc(getsupreg(memreg),hp1))) then
+ begin
+ hp1 := Tai_Marker.Create(mark_NoPropInfoEnd);
+ insertllitem(asml,p,p.next,hp1);
+ hp1 := taicpu.op_reg_ref(A_MOV,reg2opsize(memreg),
+ memreg,taicpu(p).oper[1]^.ref^);
+ new(ptaiprop(hp1.optinfo));
+ pTaiProp(hp1.optinfo)^ := pTaiProp(p.optinfo)^;
+ insertllitem(asml,p,p.next,hp1);
+ regcounter := getsupreg(memreg);
+ incstate(pTaiProp(hp1.optinfo)^.regs[regcounter].rstate,1);
+ updatestate(regcounter,hp1);
+ hp1 := Tai_Marker.Create(mark_NoPropInfoStart);
+ insertllitem(asml,p,p.next,hp1);
+ replaceoperandwithreg(asml,p,1,memreg);
+ allocregbetween(asml,memreg,hp5,
+ tai(p.next.next),ptaiprop(hp5.optinfo)^.usedregs);
+ ClearRegContentsFrom(asml,regcounter,hp5,p);
+ end;
+ end;
+ end;
+ end;
+ end;
+ end
+ end;
+ end;
+ GetNextInstruction(p, p);
+ end;
+end;
+
+function removeInstructs(asml: TAsmList; first, last: tai): boolean;
+{ Removes the marked instructions and disposes the PTaiProps of the other }
+{ instructions }
+var
+ p, hp1: tai;
+ nopropinfolevel: longint;
+begin
+ removeInstructs := false;
+ p := First;
+ nopropinfolevel := 0;
+ while (p <> Last) do
+ begin
+ if (p.typ = ait_marker) and
+ (Tai_marker(p).kind = mark_NoPropInfoStart) then
+ begin
+ hp1 := tai(p.next);
+ asml.remove(p);
+ p.free;
+ nopropinfolevel := 1;
+ while (nopropinfolevel <> 0) do
+ begin
+ p := tai(hp1.next);
+{$ifndef noinstremove}
+ { allocregbetween can insert new ait_regalloc objects }
+ { without optinfo }
+ if (hp1.typ = ait_marker) then
+ begin
+ case Tai_marker(hp1).kind of
+ { they can be nested! }
+ mark_NoPropInfoStart: inc(nopropinfolevel);
+ mark_NoPropInfoEnd: dec(nopropinfolevel);
+ else
+ begin
+ hp1 := p;
+ continue;
+ end;
+ end;
+ asml.remove(hp1);
+ hp1.free;
+ end
+ else if assigned(hp1.optinfo) then
+ if ptaiprop(hp1.optinfo)^.canBeRemoved then
+ begin
+ dispose(ptaiprop(hp1.optinfo));
+ hp1.optinfo := nil;
+ asml.remove(hp1);
+ hp1.free;
+ end
+ else
+{$endif noinstremove}
+ begin
+ dispose(ptaiprop(hp1.optinfo));
+ hp1.optinfo := nil;
+ end;
+ hp1 := p;
+ end;
+ end
+ else
+{$ifndef noinstremove}
+ if assigned(p.optinfo) and
+ ptaiprop(p.optinfo)^.canBeRemoved then
+ begin
+ hp1 := tai(p.next);
+ asml.Remove(p);
+ p.free;
+ p := hp1;
+ removeInstructs := true;
+ end
+ else
+{$endif noinstremove}
+ begin
+ p.optinfo := nil;
+ p := tai(p.next);
+ end;
+ end;
+end;
+
+function CSE(asml: TAsmList; First, Last: tai; pass: longint): boolean;
+begin
+ doCSE(asml, First, Last, not(cs_opt_level3 in current_settings.optimizerswitches) or (pass >= 2),
+ not(cs_opt_level3 in current_settings.optimizerswitches) or (pass >= 1));
+ { register renaming }
+ if not(cs_opt_level3 in current_settings.optimizerswitches) or (pass > 0) then
+ doRenaming(asml, first, last);
+ cse := removeInstructs(asml, first, last);
+end;
+
+end.
diff --git a/closures/compiler/i386/daopt386.pas b/closures/compiler/i386/daopt386.pas
new file mode 100644
index 0000000000..bdcaea11a2
--- /dev/null
+++ b/closures/compiler/i386/daopt386.pas
@@ -0,0 +1,2816 @@
+{
+ Copyright (c) 1998-2002 by Jonas Maebe, member of the Freepascal
+ development team
+
+ This unit contains the data flow analyzer and several helper procedures
+ and functions.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit daopt386;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ globtype,
+ cclasses,aasmbase,aasmtai,aasmdata,aasmcpu,cgbase,cgutils,
+ cpubase;
+
+{******************************* Constants *******************************}
+
+const
+
+{ Possible register content types }
+ con_Unknown = 0;
+ con_ref = 1;
+ con_const = 2;
+ { The contents aren't usable anymore for CSE, but they may still be }
+ { useful for detecting whether the result of a load is actually used }
+ con_invalid = 3;
+ { the reverse of the above (in case a (conditional) jump is encountered): }
+ { CSE is still possible, but the original instruction can't be removed }
+ con_noRemoveRef = 4;
+ { same, but for constants }
+ con_noRemoveConst = 5;
+
+
+const
+ topsize2tcgsize: array[topsize] of tcgsize = (OS_NO,
+ OS_8,OS_16,OS_32,OS_64,OS_16,OS_32,OS_32,
+ OS_16,OS_32,OS_64,
+ OS_F32,OS_F64,OS_F80,OS_C64,OS_F128,
+ OS_M32,
+ OS_ADDR,OS_NO,OS_NO,
+ OS_NO,
+ OS_NO);
+
+
+
+{********************************* Types *********************************}
+
+type
+ TRegEnum = RS_EAX..RS_ESP;
+ TRegArray = Array[TRegEnum] of tsuperregister;
+ TRegSet = Set of TRegEnum;
+ toptreginfo = Record
+ NewRegsEncountered, OldRegsEncountered: TRegSet;
+ RegsLoadedForRef: TRegSet;
+ lastReload: array[RS_EAX..RS_ESP] of tai;
+ New2OldReg: TRegArray;
+ end;
+
+{possible actions on an operand: read, write or modify (= read & write)}
+ TOpAction = (OpAct_Read, OpAct_Write, OpAct_Modify, OpAct_Unknown);
+
+{the possible states of a flag}
+ TFlagContents = (F_Unknown, F_notSet, F_Set);
+
+ TContent = Packed Record
+ {start and end of block instructions that defines the
+ content of this register.}
+ StartMod: tai;
+ MemWrite: taicpu;
+ {how many instructions starting with StarMod does the block consist of}
+ NrOfMods: Word;
+ {the type of the content of the register: unknown, memory, constant}
+ Typ: Byte;
+ case byte of
+ {starts at 0, gets increased everytime the register is written to}
+ 1: (WState: Byte;
+ {starts at 0, gets increased everytime the register is read from}
+ RState: Byte);
+ { to compare both states in one operation }
+ 2: (state: word);
+ end;
+
+{Contents of the integer registers}
+ TRegContent = Array[RS_EAX..RS_ESP] Of TContent;
+
+{contents of the FPU registers}
+// TRegFPUContent = Array[RS_ST..RS_ST7] Of TContent;
+
+{$ifdef tempOpts}
+{ linked list which allows searching/deleting based on value, no extra frills}
+ PSearchLinkedListItem = ^TSearchLinkedListItem;
+ TSearchLinkedListItem = object(TLinkedList_Item)
+ constructor init;
+ function equals(p: PSearchLinkedListItem): boolean; virtual;
+ end;
+
+ PSearchDoubleIntItem = ^TSearchDoubleInttem;
+ TSearchDoubleIntItem = object(TLinkedList_Item)
+ constructor init(_int1,_int2: longint);
+ function equals(p: PSearchLinkedListItem): boolean; virtual;
+ private
+ int1, int2: longint;
+ end;
+
+ PSearchLinkedList = ^TSearchLinkedList;
+ TSearchLinkedList = object(TLinkedList)
+ function searchByValue(p: PSearchLinkedListItem): boolean;
+ procedure removeByValue(p: PSearchLinkedListItem);
+ end;
+{$endif tempOpts}
+
+{information record with the contents of every register. Every tai object
+ gets one of these assigned: a pointer to it is stored in the OptInfo field}
+ TtaiProp = Record
+ Regs: TRegContent;
+{ FPURegs: TRegFPUContent;} {currently not yet used}
+ { allocated Registers }
+ UsedRegs: TRegSet;
+ { status of the direction flag }
+ DirFlag: TFlagContents;
+{$ifdef tempOpts}
+ { currently used temps }
+ tempAllocs: PSearchLinkedList;
+{$endif tempOpts}
+ { can this instruction be removed? }
+ CanBeRemoved: Boolean;
+ { are the resultflags set by this instruction used? }
+ FlagsUsed: Boolean;
+ end;
+
+ ptaiprop = ^TtaiProp;
+
+ TtaiPropBlock = Array[1..250000] Of TtaiProp;
+ PtaiPropBlock = ^TtaiPropBlock;
+
+ TInstrSinceLastMod = Array[RS_EAX..RS_ESP] Of Word;
+
+ TLabelTableItem = Record
+ taiObj: tai;
+{$ifDef JumpAnal}
+ InstrNr: Longint;
+ RefsFound: Word;
+ JmpsProcessed: Word
+{$endif JumpAnal}
+ end;
+ TLabelTable = Array[0..2500000] Of TLabelTableItem;
+ PLabelTable = ^TLabelTable;
+
+
+{*********************** procedures and functions ************************}
+
+procedure InsertLLItem(AsmL: TAsmList; prev, foll, new_one: TLinkedListItem);
+
+
+function RefsEqual(const R1, R2: TReference): Boolean;
+function isgp32reg(supreg: tsuperregister): Boolean;
+function reginref(supreg: tsuperregister; const ref: treference): boolean;
+function RegReadByInstruction(supreg: tsuperregister; hp: tai): boolean;
+function RegModifiedByInstruction(supreg: tsuperregister; p1: tai): boolean;
+function RegInInstruction(supreg: tsuperregister; p1: tai): boolean;
+function reginop(supreg: tsuperregister; const o:toper): boolean;
+function instrWritesFlags(p: tai): boolean;
+function instrReadsFlags(p: tai): boolean;
+
+function writeToMemDestroysContents(regWritten: tsuperregister; const ref: treference;
+ supreg: tsuperregister; size: tcgsize; const c: tcontent; var invalsmemwrite: boolean): boolean;
+function writeToRegDestroysContents(destReg, supreg: tsuperregister;
+ const c: tcontent): boolean;
+function writeDestroysContents(const op: toper; supreg: tsuperregister; size: tcgsize;
+ const c: tcontent; var memwritedestroyed: boolean): boolean;
+
+function sequenceDependsonReg(const Content: TContent; seqreg: tsuperregister; supreg: tsuperregister): Boolean;
+
+function GetNextInstruction(Current: tai; var Next: tai): Boolean;
+function GetLastInstruction(Current: tai; var Last: tai): Boolean;
+procedure SkipHead(var p: tai);
+function labelCanBeSkipped(p: tai_label): boolean;
+
+procedure RemoveLastDeallocForFuncRes(asmL: TAsmList; p: tai);
+function regLoadedWithNewValue(supreg: tsuperregister; canDependOnPrevValue: boolean;
+ hp: tai): boolean;
+procedure UpdateUsedRegs(var UsedRegs: TRegSet; p: tai);
+procedure AllocRegBetween(asml: TAsmList; reg: tregister; p1, p2: tai; var initialusedregs: tregset);
+function FindRegDealloc(supreg: tsuperregister; p: tai): boolean;
+
+function InstructionsEquivalent(p1, p2: tai; var RegInfo: toptreginfo): Boolean;
+function sizescompatible(loadsize,newsize: topsize): boolean;
+function OpsEqual(const o1,o2:toper): Boolean;
+
+
+type
+ tdfaobj = class
+ constructor create(_list: TAsmList); virtual;
+
+ function pass_1(_blockstart: tai): tai;
+ function pass_generate_code: boolean;
+ procedure clear;
+
+ function getlabelwithsym(sym: tasmlabel): tai;
+
+ private
+ { asm list we're working on }
+ list: TAsmList;
+
+ { current part of the asm list }
+ blockstart, blockend: tai;
+
+ { the amount of taiObjects in the current part of the assembler list }
+ nroftaiobjs: longint;
+
+ { Array which holds all TtaiProps }
+ taipropblock: ptaipropblock;
+
+ { all labels in the current block: their value mapped to their location }
+ lolab, hilab, labdif: longint;
+ labeltable: plabeltable;
+
+ { Walks through the list to find the lowest and highest label number, inits the }
+ { labeltable and fixes/optimizes some regallocs }
+ procedure initlabeltable;
+
+ function initdfapass2: boolean;
+ procedure dodfapass2;
+ end;
+
+
+function FindLabel(L: tasmlabel; var hp: tai): Boolean;
+
+procedure incState(var S: Byte; amount: longint);
+
+{******************************* Variables *******************************}
+
+var
+ dfa: tdfaobj;
+
+{*********************** end of Interface section ************************}
+
+
+Implementation
+
+Uses
+{$ifdef csdebug}
+ cutils,
+{$else}
+ {$ifdef statedebug}
+ cutils,
+ {$else}
+ {$ifdef allocregdebug}
+ cutils,
+ {$endif}
+ {$endif}
+{$endif}
+ globals, systems, verbose, symconst, cgobj,procinfo;
+
+Type
+ TRefCompare = function(const r1, r2: treference; size1, size2: tcgsize): boolean;
+
+var
+ {How many instructions are between the current instruction and the last one
+ that modified the register}
+ NrOfInstrSinceLastMod: TInstrSinceLastMod;
+
+{$ifdef tempOpts}
+ constructor TSearchLinkedListItem.init;
+ begin
+ end;
+
+ function TSearchLinkedListItem.equals(p: PSearchLinkedListItem): boolean;
+ begin
+ equals := false;
+ end;
+
+ constructor TSearchDoubleIntItem.init(_int1,_int2: longint);
+ begin
+ int1 := _int1;
+ int2 := _int2;
+ end;
+
+ function TSearchDoubleIntItem.equals(p: PSearchLinkedListItem): boolean;
+ begin
+ equals := (TSearchDoubleIntItem(p).int1 = int1) and
+ (TSearchDoubleIntItem(p).int2 = int2);
+ end;
+
+ function TSearchLinkedList.FindByValue(p: PSearchLinkedListItem): boolean;
+ var temp: PSearchLinkedListItem;
+ begin
+ temp := first;
+ while (temp <> last.next) and
+ not(temp.equals(p)) do
+ temp := temp.next;
+ searchByValue := temp <> last.next;
+ end;
+
+ procedure TSearchLinkedList.removeByValue(p: PSearchLinkedListItem);
+ begin
+ temp := first;
+ while (temp <> last.next) and
+ not(temp.equals(p)) do
+ temp := temp.next;
+ if temp <> last.next then
+ begin
+ remove(temp);
+ dispose(temp,done);
+ end;
+ end;
+
+procedure updateTempAllocs(var UsedRegs: TRegSet; p: tai);
+{updates UsedRegs with the RegAlloc Information coming after p}
+begin
+ repeat
+ while assigned(p) and
+ ((p.typ in (SkipInstr - [ait_RegAlloc])) or
+ ((p.typ = ait_label) and
+ labelCanBeSkipped(tai_label(current)))) Do
+ p := tai(p.next);
+ while assigned(p) and
+ (p.typ=ait_RegAlloc) Do
+ begin
+ case tai_regalloc(p).ratype of
+ ra_alloc :
+ Include(UsedRegs, TRegEnum(getsupreg(tai_regalloc(p).reg)));
+ ra_dealloc :
+ Exclude(UsedRegs, TRegEnum(getsupreg(tai_regalloc(p).reg)));
+ end;
+ p := tai(p.next);
+ end;
+ until not(assigned(p)) or
+ (not(p.typ in SkipInstr) and
+ not((p.typ = ait_label) and
+ labelCanBeSkipped(tai_label(current))));
+end;
+
+{$endif tempOpts}
+
+{************************ Create the Label table ************************}
+
+function findregalloc(supreg: tsuperregister; starttai: tai; ratyp: tregalloctype): boolean;
+{ Returns true if a ait_alloc object for reg is found in the block of tai's }
+{ starting with Starttai and ending with the next "real" instruction }
+begin
+ findregalloc := false;
+ repeat
+ while assigned(starttai) and
+ ((starttai.typ in (skipinstr - [ait_regalloc])) or
+ ((starttai.typ = ait_label) and
+ labelcanbeskipped(tai_label(starttai)))) do
+ starttai := tai(starttai.next);
+ if assigned(starttai) and
+ (starttai.typ = ait_regalloc) then
+ begin
+ if (tai_regalloc(Starttai).ratype = ratyp) and
+ (getsupreg(tai_regalloc(Starttai).reg) = supreg) then
+ begin
+ findregalloc:=true;
+ break;
+ end;
+ starttai := tai(starttai.next);
+ end
+ else
+ break;
+ until false;
+end;
+
+procedure RemoveLastDeallocForFuncRes(asml: TAsmList; p: tai);
+
+ procedure DoRemoveLastDeallocForFuncRes(asml: TAsmList; supreg: tsuperregister);
+ var
+ hp2: tai;
+ begin
+ hp2 := p;
+ repeat
+ hp2 := tai(hp2.previous);
+ if assigned(hp2) and
+ (hp2.typ = ait_regalloc) and
+ (tai_regalloc(hp2).ratype=ra_dealloc) and
+ (getregtype(tai_regalloc(hp2).reg) = R_INTREGISTER) and
+ (getsupreg(tai_regalloc(hp2).reg) = supreg) then
+ begin
+ asml.remove(hp2);
+ hp2.free;
+ break;
+ end;
+ until not(assigned(hp2)) or regInInstruction(supreg,hp2);
+ end;
+
+begin
+ case current_procinfo.procdef.returndef.typ of
+ arraydef,recorddef,pointerdef,
+ stringdef,enumdef,procdef,objectdef,errordef,
+ filedef,setdef,procvardef,
+ classrefdef,forwarddef:
+ DoRemoveLastDeallocForFuncRes(asml,RS_EAX);
+ orddef:
+ if current_procinfo.procdef.returndef.size <> 0 then
+ begin
+ DoRemoveLastDeallocForFuncRes(asml,RS_EAX);
+ { for int64/qword }
+ if current_procinfo.procdef.returndef.size = 8 then
+ DoRemoveLastDeallocForFuncRes(asml,RS_EDX);
+ end;
+ end;
+end;
+
+procedure getNoDeallocRegs(var regs: tregset);
+var
+ regCounter: TSuperRegister;
+begin
+ regs := [];
+ case current_procinfo.procdef.returndef.typ of
+ arraydef,recorddef,pointerdef,
+ stringdef,enumdef,procdef,objectdef,errordef,
+ filedef,setdef,procvardef,
+ classrefdef,forwarddef:
+ regs := [RS_EAX];
+ orddef:
+ if current_procinfo.procdef.returndef.size <> 0 then
+ begin
+ regs := [RS_EAX];
+ { for int64/qword }
+ if current_procinfo.procdef.returndef.size = 8 then
+ regs := regs + [RS_EDX];
+ end;
+ end;
+ for regCounter := RS_EAX to RS_EBX do
+{ if not(regCounter in rg.usableregsint) then}
+ include(regs,regcounter);
+end;
+
+
+procedure AddRegDeallocFor(asml: TAsmList; reg: tregister; p: tai);
+var
+ hp1: tai;
+ funcResRegs: tregset;
+{ funcResReg: boolean;}
+begin
+{ if not(supreg in rg.usableregsint) then
+ exit;}
+{ if not(supreg in [RS_EDI]) then
+ exit;}
+ getNoDeallocRegs(funcresregs);
+{ funcResRegs := funcResRegs - rg.usableregsint;}
+{ funcResRegs := funcResRegs - [RS_EDI];}
+{ funcResRegs := funcResRegs - [RS_EAX,RS_EBX,RS_ECX,RS_EDX,RS_ESI]; }
+{ funcResReg := getsupreg(reg) in funcresregs;}
+
+ hp1 := p;
+{
+
+
+ while not(funcResReg and
+ (p.typ = ait_instruction) and
+ (taicpu(p).opcode = A_JMP) and
+ (tasmlabel(taicpu(p).oper[0]^.sym) = aktexit2label)) and
+ getLastInstruction(p, p) and
+ not(regInInstruction(supreg, p)) do
+ hp1 := p;
+}
+ { don't insert a dealloc for registers which contain the function result }
+ { if they are followed by a jump to the exit label (for exit(...)) }
+{ if not(funcResReg) or
+ not((hp1.typ = ait_instruction) and
+ (taicpu(hp1).opcode = A_JMP) and
+ (tasmlabel(taicpu(hp1).oper[0]^.sym) = aktexit2label)) then }
+ begin
+ p := tai_regalloc.deAlloc(reg,nil);
+ insertLLItem(AsmL, hp1.previous, hp1, p);
+ end;
+end;
+
+
+
+{************************ Search the Label table ************************}
+
+function findlabel(l: tasmlabel; var hp: tai): boolean;
+
+{searches for the specified label starting from hp as long as the
+ encountered instructions are labels, to be able to optimize constructs like
+
+ jne l2 jmp l2
+ jmp l3 and l1:
+ l1: l2:
+ l2:}
+
+var
+ p: tai;
+
+begin
+ p := hp;
+ while assigned(p) and
+ (p.typ in SkipInstr + [ait_label,ait_align]) Do
+ if (p.typ <> ait_Label) or
+ (tai_label(p).labsym <> l) then
+ GetNextInstruction(p, p)
+ else
+ begin
+ hp := p;
+ findlabel := true;
+ exit
+ end;
+ findlabel := false;
+end;
+
+{************************ Some general functions ************************}
+
+function tch2reg(ch: tinschange): tsuperregister;
+{converts a TChange variable to a TRegister}
+const
+ ch2reg: array[CH_REAX..CH_REDI] of tsuperregister = (RS_EAX,RS_ECX,RS_EDX,RS_EBX,RS_ESP,RS_EBP,RS_ESI,RS_EDI);
+begin
+ if (ch <= CH_REDI) then
+ tch2reg := ch2reg[ch]
+ else if (ch <= CH_WEDI) then
+ tch2reg := ch2reg[tinschange(ord(ch) - ord(CH_REDI))]
+ else if (ch <= CH_RWEDI) then
+ tch2reg := ch2reg[tinschange(ord(ch) - ord(CH_WEDI))]
+ else if (ch <= CH_MEDI) then
+ tch2reg := ch2reg[tinschange(ord(ch) - ord(CH_RWEDI))]
+ else
+ InternalError($db)
+end;
+
+
+{ inserts new_one between prev and foll }
+
+procedure InsertLLItem(AsmL: TAsmList; prev, foll, new_one: TLinkedListItem);
+begin
+ if assigned(prev) then
+ if assigned(foll) then
+ begin
+ if assigned(new_one) then
+ begin
+ new_one.previous := prev;
+ new_one.next := foll;
+ prev.next := new_one;
+ foll.previous := new_one;
+ { shgould we update line information }
+ if (not (tai(new_one).typ in SkipLineInfo)) and
+ (not (tai(foll).typ in SkipLineInfo)) then
+ tailineinfo(new_one).fileinfo := tailineinfo(foll).fileinfo;
+ end;
+ end
+ else
+ asml.Concat(new_one)
+ else
+ if assigned(foll) then
+ asml.Insert(new_one)
+end;
+
+{********************* Compare parts of tai objects *********************}
+
+function regssamesize(reg1, reg2: tregister): boolean;
+{returns true if Reg1 and Reg2 are of the same size (so if they're both
+ 8bit, 16bit or 32bit)}
+begin
+ if (reg1 = NR_NO) or (reg2 = NR_NO) then
+ internalerror(2003111602);
+ regssamesize := getsubreg(reg1) = getsubreg(reg2);
+end;
+
+
+procedure AddReg2RegInfo(OldReg, NewReg: TRegister; var RegInfo: toptreginfo);
+{updates the ???RegsEncountered and ???2???reg fields of RegInfo. Assumes that
+ OldReg and NewReg have the same size (has to be chcked in advance with
+ RegsSameSize) and that neither equals RS_INVALID}
+var
+ newsupreg, oldsupreg: tsuperregister;
+begin
+ if (newreg = NR_NO) or (oldreg = NR_NO) then
+ internalerror(2003111601);
+ newsupreg := getsupreg(newreg);
+ oldsupreg := getsupreg(oldreg);
+ with RegInfo Do
+ begin
+ NewRegsEncountered := NewRegsEncountered + [newsupreg];
+ OldRegsEncountered := OldRegsEncountered + [oldsupreg];
+ New2OldReg[newsupreg] := oldsupreg;
+ end;
+end;
+
+
+procedure AddOp2RegInfo(const o:toper; var reginfo: toptreginfo);
+begin
+ case o.typ Of
+ top_reg:
+ if (o.reg <> NR_NO) then
+ AddReg2RegInfo(o.reg, o.reg, RegInfo);
+ top_ref:
+ begin
+ if o.ref^.base <> NR_NO then
+ AddReg2RegInfo(o.ref^.base, o.ref^.base, RegInfo);
+ if o.ref^.index <> NR_NO then
+ AddReg2RegInfo(o.ref^.index, o.ref^.index, RegInfo);
+ end;
+ end;
+end;
+
+
+function RegsEquivalent(oldreg, newreg: tregister; const oldinst, newinst: taicpu; var reginfo: toptreginfo; opact: topaction): Boolean;
+begin
+ if not((oldreg = NR_NO) or (newreg = NR_NO)) then
+ if RegsSameSize(oldreg, newreg) then
+ with reginfo do
+{here we always check for the 32 bit component, because it is possible that
+ the 8 bit component has not been set, event though NewReg already has been
+ processed. This happens if it has been compared with a register that doesn't
+ have an 8 bit component (such as EDI). in that case the 8 bit component is
+ still set to RS_NO and the comparison in the else-part will fail}
+ if (getsupreg(oldReg) in OldRegsEncountered) then
+ if (getsupreg(NewReg) in NewRegsEncountered) then
+ RegsEquivalent := (getsupreg(oldreg) = New2OldReg[getsupreg(newreg)])
+
+ { if we haven't encountered the new register yet, but we have encountered the
+ old one already, the new one can only be correct if it's being written to
+ (and consequently the old one is also being written to), otherwise
+
+ movl -8(%ebp), %eax and movl -8(%ebp), %eax
+ movl (%eax), %eax movl (%edx), %edx
+
+ are considered equivalent}
+
+ else
+ if (opact = opact_write) then
+ begin
+ AddReg2RegInfo(oldreg, newreg, reginfo);
+ RegsEquivalent := true
+ end
+ else
+ Regsequivalent := false
+ else
+ if not(getsupreg(newreg) in NewRegsEncountered) and
+ ((opact = opact_write) or
+ ((newreg = oldreg) and
+ (ptaiprop(oldinst.optinfo)^.regs[getsupreg(oldreg)].wstate =
+ ptaiprop(newinst.optinfo)^.regs[getsupreg(oldreg)].wstate) and
+ not(regmodifiedbyinstruction(getsupreg(oldreg),oldinst)))) then
+ begin
+ AddReg2RegInfo(oldreg, newreg, reginfo);
+ RegsEquivalent := true
+ end
+ else
+ RegsEquivalent := false
+ else
+ RegsEquivalent := false
+ else
+ RegsEquivalent := oldreg = newreg
+end;
+
+
+function RefsEquivalent(const r1, r2: treference; const oldinst, newinst: taicpu; var regInfo: toptreginfo): boolean;
+begin
+ RefsEquivalent :=
+ (r1.offset = r2.offset) and
+ RegsEquivalent(r1.base, r2.base, oldinst, newinst, reginfo, OpAct_Read) and
+ RegsEquivalent(r1.index, r2.index, oldinst, newinst, reginfo, OpAct_Read) and
+ (r1.segment = r2.segment) and (r1.scalefactor = r2.scalefactor) and
+ (r1.symbol = r2.symbol) and (r1.refaddr = r2.refaddr) and
+ (r1.relsymbol = r2.relsymbol);
+end;
+
+
+function refsequal(const r1, r2: treference): boolean;
+begin
+ refsequal :=
+ (r1.offset = r2.offset) and
+ (r1.segment = r2.segment) and (r1.base = r2.base) and
+ (r1.index = r2.index) and (r1.scalefactor = r2.scalefactor) and
+ (r1.symbol=r2.symbol) and (r1.refaddr = r2.refaddr) and
+ (r1.relsymbol = r2.relsymbol);
+end;
+
+
+{$push}
+{$q-}
+
+// checks whether a write to r2 of size "size" contains address r1
+function refsoverlapping(const r1, r2: treference; size1, size2: tcgsize): boolean;
+var
+ realsize1, realsize2: aint;
+begin
+ realsize1 := tcgsize2size[size1];
+ realsize2 := tcgsize2size[size2];
+ refsoverlapping :=
+ (r2.offset <= r1.offset+realsize1) and
+ (r1.offset <= r2.offset+realsize2) and
+ (r1.segment = r2.segment) and (r1.base = r2.base) and
+ (r1.index = r2.index) and (r1.scalefactor = r2.scalefactor) and
+ (r1.symbol=r2.symbol) and (r1.refaddr = r2.refaddr) and
+ (r1.relsymbol = r2.relsymbol);
+end;
+
+{$pop}
+
+
+function isgp32reg(supreg: tsuperregister): boolean;
+{Checks if the register is a 32 bit general purpose register}
+begin
+ isgp32reg := false;
+{$push}{$warnings off}
+ if (supreg >= RS_EAX) and (supreg <= RS_EBX) then
+ isgp32reg := true
+{$pop}
+end;
+
+
+function reginref(supreg: tsuperregister; const ref: treference): boolean;
+begin {checks whether ref contains a reference to reg}
+ reginref :=
+ ((ref.base <> NR_NO) and
+ (getsupreg(ref.base) = supreg)) or
+ ((ref.index <> NR_NO) and
+ (getsupreg(ref.index) = supreg))
+end;
+
+
+function RegReadByInstruction(supreg: tsuperregister; hp: tai): boolean;
+var
+ p: taicpu;
+ opcount: longint;
+begin
+ RegReadByInstruction := false;
+ if hp.typ <> ait_instruction then
+ exit;
+ p := taicpu(hp);
+ case p.opcode of
+ A_CALL:
+ regreadbyinstruction := true;
+ A_IMUL:
+ case p.ops of
+ 1:
+ regReadByInstruction :=
+ (supreg = RS_EAX) or reginop(supreg,p.oper[0]^);
+ 2,3:
+ regReadByInstruction :=
+ reginop(supreg,p.oper[0]^) or
+ reginop(supreg,p.oper[1]^);
+ end;
+ A_IDIV,A_DIV,A_MUL:
+ begin
+ regReadByInstruction :=
+ reginop(supreg,p.oper[0]^) or (supreg in [RS_EAX,RS_EDX]);
+ end;
+ else
+ begin
+ for opcount := 0 to p.ops-1 do
+ if (p.oper[opCount]^.typ = top_ref) and
+ reginref(supreg,p.oper[opcount]^.ref^) then
+ begin
+ RegReadByInstruction := true;
+ exit
+ end;
+ for opcount := 1 to maxinschanges do
+ case insprop[p.opcode].ch[opcount] of
+ CH_REAX..CH_REDI,CH_RWEAX..CH_MEDI:
+ if supreg = tch2reg(insprop[p.opcode].ch[opcount]) then
+ begin
+ RegReadByInstruction := true;
+ exit
+ end;
+ CH_RWOP1,CH_ROP1,CH_MOP1:
+ if //(p.oper[0]^.typ = top_reg) and
+ reginop(supreg,p.oper[0]^) then
+ begin
+ RegReadByInstruction := true;
+ exit
+ end;
+ Ch_RWOP2,Ch_ROP2,Ch_MOP2:
+ if //(p.oper[1]^.typ = top_reg) and
+ reginop(supreg,p.oper[1]^) then
+ begin
+ RegReadByInstruction := true;
+ exit
+ end;
+ Ch_RWOP3,Ch_ROP3,Ch_MOP3:
+ if //(p.oper[2]^.typ = top_reg) and
+ reginop(supreg,p.oper[2]^) then
+ begin
+ RegReadByInstruction := true;
+ exit
+ end;
+ end;
+ end;
+ end;
+end;
+
+
+function regInInstruction(supreg: tsuperregister; p1: tai): boolean;
+{ Checks if reg is used by the instruction p1 }
+{ Difference with "regReadBysinstruction() or regModifiedByInstruction()": }
+{ this one ignores CH_ALL opcodes, while regModifiedByInstruction doesn't }
+var
+ p: taicpu;
+ opcount: longint;
+begin
+ regInInstruction := false;
+ if p1.typ <> ait_instruction then
+ exit;
+ p := taicpu(p1);
+ case p.opcode of
+ A_CALL:
+ regininstruction := true;
+ A_IMUL:
+ case p.ops of
+ 1:
+ regInInstruction :=
+ (supreg = RS_EAX) or reginop(supreg,p.oper[0]^);
+ 2,3:
+ regInInstruction :=
+ reginop(supreg,p.oper[0]^) or
+ reginop(supreg,p.oper[1]^) or
+ (assigned(p.oper[2]) and
+ reginop(supreg,p.oper[2]^));
+ end;
+ A_IDIV,A_DIV,A_MUL:
+ regInInstruction :=
+ reginop(supreg,p.oper[0]^) or
+ (supreg in [RS_EAX,RS_EDX])
+ else
+ begin
+ for opcount := 0 to p.ops-1 do
+ if (p.oper[opCount]^.typ = top_ref) and
+ reginref(supreg,p.oper[opcount]^.ref^) then
+ begin
+ regInInstruction := true;
+ exit
+ end;
+ for opcount := 1 to maxinschanges do
+ case insprop[p.opcode].Ch[opCount] of
+ CH_REAX..CH_MEDI:
+ if tch2reg(InsProp[p.opcode].Ch[opCount]) = supreg then
+ begin
+ regInInstruction := true;
+ exit;
+ end;
+ CH_ROp1..CH_MOp1:
+ if reginop(supreg,p.oper[0]^) then
+ begin
+ regInInstruction := true;
+ exit
+ end;
+ Ch_ROp2..Ch_MOp2:
+ if reginop(supreg,p.oper[1]^) then
+ begin
+ regInInstruction := true;
+ exit
+ end;
+ Ch_ROp3..Ch_MOp3:
+ if reginop(supreg,p.oper[2]^) then
+ begin
+ regInInstruction := true;
+ exit
+ end;
+ end;
+ end;
+ end;
+end;
+
+
+function reginop(supreg: tsuperregister; const o:toper): boolean;
+begin
+ reginop := false;
+ case o.typ Of
+ top_reg:
+ reginop :=
+ (getregtype(o.reg) = R_INTREGISTER) and
+ (supreg = getsupreg(o.reg));
+ top_ref:
+ reginop :=
+ ((o.ref^.base <> NR_NO) and
+ (supreg = getsupreg(o.ref^.base))) or
+ ((o.ref^.index <> NR_NO) and
+ (supreg = getsupreg(o.ref^.index)));
+ end;
+end;
+
+
+function RegModifiedByInstruction(supreg: tsuperregister; p1: tai): boolean;
+var
+ InstrProp: TInsProp;
+ TmpResult: Boolean;
+ Cnt: Word;
+begin
+ TmpResult := False;
+ if supreg = RS_INVALID then
+ exit;
+ if (p1.typ = ait_instruction) then
+ case taicpu(p1).opcode of
+ A_IMUL:
+ With taicpu(p1) Do
+ TmpResult :=
+ ((ops = 1) and (supreg in [RS_EAX,RS_EDX])) or
+ ((ops = 2) and (getsupreg(oper[1]^.reg) = supreg)) or
+ ((ops = 3) and (getsupreg(oper[2]^.reg) = supreg));
+ A_DIV, A_IDIV, A_MUL:
+ With taicpu(p1) Do
+ TmpResult :=
+ (supreg in [RS_EAX,RS_EDX]);
+ else
+ begin
+ Cnt := 1;
+ InstrProp := InsProp[taicpu(p1).OpCode];
+ while (Cnt <= maxinschanges) and
+ (InstrProp.Ch[Cnt] <> Ch_None) and
+ not(TmpResult) Do
+ begin
+ case InstrProp.Ch[Cnt] Of
+ Ch_WEAX..Ch_MEDI:
+ TmpResult := supreg = tch2reg(InstrProp.Ch[Cnt]);
+ Ch_RWOp1,Ch_WOp1,Ch_Mop1:
+ TmpResult := (taicpu(p1).oper[0]^.typ = top_reg) and
+ reginop(supreg,taicpu(p1).oper[0]^);
+ Ch_RWOp2,Ch_WOp2,Ch_Mop2:
+ TmpResult := (taicpu(p1).oper[1]^.typ = top_reg) and
+ reginop(supreg,taicpu(p1).oper[1]^);
+ Ch_RWOp3,Ch_WOp3,Ch_Mop3:
+ TmpResult := (taicpu(p1).oper[2]^.typ = top_reg) and
+ reginop(supreg,taicpu(p1).oper[2]^);
+ Ch_FPU: TmpResult := false; // supreg is supposed to be an intreg!! supreg in [RS_ST..RS_ST7,RS_MM0..RS_MM7];
+ Ch_ALL: TmpResult := true;
+ end;
+ inc(Cnt)
+ end
+ end
+ end;
+ RegModifiedByInstruction := TmpResult
+end;
+
+
+function instrWritesFlags(p: tai): boolean;
+var
+ l: longint;
+begin
+ instrWritesFlags := true;
+ case p.typ of
+ ait_instruction:
+ begin
+ for l := 1 to maxinschanges do
+ if InsProp[taicpu(p).opcode].Ch[l] in [Ch_WFlags,Ch_RWFlags,Ch_All] then
+ exit;
+ end;
+ ait_label:
+ exit;
+ end;
+ instrWritesFlags := false;
+end;
+
+
+function instrReadsFlags(p: tai): boolean;
+var
+ l: longint;
+begin
+ instrReadsFlags := true;
+ case p.typ of
+ ait_instruction:
+ begin
+ for l := 1 to maxinschanges do
+ if InsProp[taicpu(p).opcode].Ch[l] in [Ch_RFlags,Ch_RWFlags,Ch_All] then
+ exit;
+ end;
+ ait_label:
+ exit;
+ end;
+ instrReadsFlags := false;
+end;
+
+
+{********************* GetNext and GetLastInstruction *********************}
+function GetNextInstruction(Current: tai; var Next: tai): Boolean;
+{ skips ait_regalloc, ait_regdealloc and ait_stab* objects and puts the }
+{ next tai object in Next. Returns false if there isn't any }
+begin
+ repeat
+ if (Current.typ = ait_marker) and
+ (tai_Marker(current).Kind = mark_AsmBlockStart) then
+ begin
+ GetNextInstruction := False;
+ Next := Nil;
+ Exit
+ end;
+ Current := tai(current.Next);
+ while assigned(Current) and
+ ((current.typ in skipInstr) or
+ ((current.typ = ait_label) and
+ labelCanBeSkipped(tai_label(current)))) do
+ Current := tai(current.Next);
+{ if assigned(Current) and
+ (current.typ = ait_Marker) and
+ (tai_Marker(current).Kind = mark_NoPropInfoStart) then
+ begin
+ while assigned(Current) and
+ ((current.typ <> ait_Marker) or
+ (tai_Marker(current).Kind <> mark_NoPropInfoEnd)) Do
+ Current := tai(current.Next);
+ end;}
+ until not(assigned(Current)) or
+ (current.typ <> ait_Marker) or
+ not(tai_Marker(current).Kind in [mark_NoPropInfoStart,mark_NoPropInfoEnd]);
+ Next := Current;
+ if assigned(Current) and
+ not((current.typ in SkipInstr) or
+ ((current.typ = ait_label) and
+ labelCanBeSkipped(tai_label(current))))
+ then
+ GetNextInstruction :=
+ not((current.typ = ait_marker) and
+ (tai_marker(current).kind = mark_AsmBlockStart))
+ else
+ begin
+ GetNextInstruction := False;
+ Next := nil;
+ end;
+end;
+
+
+function GetLastInstruction(Current: tai; var Last: tai): boolean;
+{skips the ait-types in SkipInstr puts the previous tai object in
+ Last. Returns false if there isn't any}
+begin
+ repeat
+ Current := tai(current.previous);
+ while assigned(Current) and
+ (((current.typ = ait_Marker) and
+ not(tai_Marker(current).Kind in [mark_AsmBlockEnd{,mark_NoPropInfoEnd}])) or
+ (current.typ in SkipInstr) or
+ ((current.typ = ait_label) and
+ labelCanBeSkipped(tai_label(current)))) Do
+ Current := tai(current.previous);
+{ if assigned(Current) and
+ (current.typ = ait_Marker) and
+ (tai_Marker(current).Kind = mark_NoPropInfoEnd) then
+ begin
+ while assigned(Current) and
+ ((current.typ <> ait_Marker) or
+ (tai_Marker(current).Kind <> mark_NoPropInfoStart)) Do
+ Current := tai(current.previous);
+ end;}
+ until not(assigned(Current)) or
+ (current.typ <> ait_Marker) or
+ not(tai_Marker(current).Kind in [mark_NoPropInfoStart,mark_NoPropInfoEnd]);
+ if not(assigned(Current)) or
+ (current.typ in SkipInstr) or
+ ((current.typ = ait_label) and
+ labelCanBeSkipped(tai_label(current))) or
+ ((current.typ = ait_Marker) and
+ (tai_Marker(current).Kind = mark_AsmBlockEnd))
+ then
+ begin
+ Last := nil;
+ GetLastInstruction := False
+ end
+ else
+ begin
+ Last := Current;
+ GetLastInstruction := True;
+ end;
+end;
+
+
+procedure SkipHead(var p: tai);
+var
+ oldp: tai;
+begin
+ repeat
+ oldp := p;
+ if (p.typ in SkipInstr) or
+ ((p.typ = ait_marker) and
+ (tai_Marker(p).Kind in [mark_AsmBlockEnd,mark_NoLineInfoStart,mark_NoLineInfoEnd])) then
+ GetNextInstruction(p,p)
+ else if ((p.Typ = Ait_Marker) and
+ (tai_Marker(p).Kind = mark_NoPropInfoStart)) then
+ {a marker of the mark_NoPropInfoStart can't be the first instruction of a
+ TAsmList list}
+ GetNextInstruction(tai(p.previous),p);
+ until p = oldp
+end;
+
+
+function labelCanBeSkipped(p: tai_label): boolean;
+begin
+ labelCanBeSkipped := not(p.labsym.is_used) or (p.labsym.labeltype<>alt_jump);
+end;
+
+{******************* The Data Flow Analyzer functions ********************}
+
+function regLoadedWithNewValue(supreg: tsuperregister; canDependOnPrevValue: boolean;
+ hp: tai): boolean;
+{ assumes reg is a 32bit register }
+var
+ p: taicpu;
+begin
+ if not assigned(hp) or
+ (hp.typ <> ait_instruction) then
+ begin
+ regLoadedWithNewValue := false;
+ exit;
+ end;
+ p := taicpu(hp);
+ regLoadedWithNewValue :=
+ (((p.opcode = A_MOV) or
+ (p.opcode = A_MOVZX) or
+ (p.opcode = A_MOVSX) or
+ (p.opcode = A_LEA)) and
+ (p.oper[1]^.typ = top_reg) and
+ (getsupreg(p.oper[1]^.reg) = supreg) and
+ (canDependOnPrevValue or
+ (p.oper[0]^.typ = top_const) or
+ ((p.oper[0]^.typ = top_reg) and
+ (getsupreg(p.oper[0]^.reg) <> supreg)) or
+ ((p.oper[0]^.typ = top_ref) and
+ not regInRef(supreg,p.oper[0]^.ref^)))) or
+ ((p.opcode = A_POP) and
+ (getsupreg(p.oper[0]^.reg) = supreg));
+end;
+
+procedure UpdateUsedRegs(var UsedRegs: TRegSet; p: tai);
+{updates UsedRegs with the RegAlloc Information coming after p}
+begin
+ repeat
+ while assigned(p) and
+ ((p.typ in (SkipInstr - [ait_RegAlloc])) or
+ ((p.typ = ait_label) and
+ labelCanBeSkipped(tai_label(p))) or
+ ((p.typ = ait_marker) and
+ (tai_Marker(p).Kind in [mark_AsmBlockEnd,mark_NoLineInfoStart,mark_NoLineInfoEnd]))) do
+ p := tai(p.next);
+ while assigned(p) and
+ (p.typ=ait_RegAlloc) Do
+ begin
+ if (getregtype(tai_regalloc(p).reg) = R_INTREGISTER) then
+ begin
+ case tai_regalloc(p).ratype of
+ ra_alloc :
+ Include(UsedRegs, TRegEnum(getsupreg(tai_regalloc(p).reg)));
+ ra_dealloc :
+ Exclude(UsedRegs, TRegEnum(getsupreg(tai_regalloc(p).reg)));
+ end;
+ end;
+ p := tai(p.next);
+ end;
+ until not(assigned(p)) or
+ (not(p.typ in SkipInstr) and
+ not((p.typ = ait_label) and
+ labelCanBeSkipped(tai_label(p))));
+end;
+
+
+procedure AllocRegBetween(asml: TAsmList; reg: tregister; p1, p2: tai; var initialusedregs: tregset);
+{ allocates register reg between (and including) instructions p1 and p2 }
+{ the type of p1 and p2 must not be in SkipInstr }
+{ note that this routine is both called from the peephole optimizer }
+{ where optinfo is not yet initialised) and from the cse (where it is) }
+var
+ hp, start: tai;
+ removedsomething,
+ firstRemovedWasAlloc,
+ lastRemovedWasDealloc: boolean;
+ supreg: tsuperregister;
+begin
+{$ifdef EXTDEBUG}
+ if assigned(p1.optinfo) and
+ (ptaiprop(p1.optinfo)^.usedregs <> initialusedregs) then
+ internalerror(2004101010);
+{$endif EXTDEBUG}
+ start := p1;
+ if (reg = NR_ESP) or
+ (reg = current_procinfo.framepointer) or
+ not(assigned(p1)) then
+ { this happens with registers which are loaded implicitely, outside the }
+ { current block (e.g. esi with self) }
+ exit;
+ supreg := getsupreg(reg);
+ { make sure we allocate it for this instruction }
+ getnextinstruction(p2,p2);
+ lastRemovedWasDealloc := false;
+ removedSomething := false;
+ firstRemovedWasAlloc := false;
+{$ifdef allocregdebug}
+ hp := tai_comment.Create(strpnew('allocating '+std_regname(newreg(R_INTREGISTER,supreg,R_SUBWHOLE))+
+ ' from here...'));
+ insertllitem(asml,p1.previous,p1,hp);
+ hp := tai_comment.Create(strpnew('allocated '+std_regname(newreg(R_INTREGISTER,supreg,R_SUBWHOLE))+
+ ' till here...'));
+ insertllitem(asml,p2,p2.next,hp);
+{$endif allocregdebug}
+ if not(supreg in initialusedregs) then
+ begin
+ hp := tai_regalloc.alloc(reg,nil);
+ insertllItem(asmL,p1.previous,p1,hp);
+ include(initialusedregs,supreg);
+ end;
+ while assigned(p1) and
+ (p1 <> p2) do
+ begin
+ if assigned(p1.optinfo) then
+ include(ptaiprop(p1.optinfo)^.usedregs,supreg);
+ p1 := tai(p1.next);
+ repeat
+ while assigned(p1) and
+ (p1.typ in (SkipInstr-[ait_regalloc])) Do
+ p1 := tai(p1.next);
+{ remove all allocation/deallocation info about the register in between }
+ if assigned(p1) and
+ (p1.typ = ait_regalloc) then
+ if (getsupreg(tai_regalloc(p1).reg) = supreg) then
+ begin
+ if not removedSomething then
+ begin
+ firstRemovedWasAlloc := tai_regalloc(p1).ratype=ra_alloc;
+ removedSomething := true;
+ end;
+ lastRemovedWasDealloc := (tai_regalloc(p1).ratype=ra_dealloc);
+ hp := tai(p1.Next);
+ asml.Remove(p1);
+ p1.free;
+ p1 := hp;
+ end
+ else p1 := tai(p1.next);
+ until not(assigned(p1)) or
+ not(p1.typ in SkipInstr);
+ end;
+ if assigned(p1) then
+ begin
+ if firstRemovedWasAlloc then
+ begin
+ hp := tai_regalloc.Alloc(reg,nil);
+ insertLLItem(asmL,start.previous,start,hp);
+ end;
+ if lastRemovedWasDealloc then
+ begin
+ hp := tai_regalloc.DeAlloc(reg,nil);
+ insertLLItem(asmL,p1.previous,p1,hp);
+ end;
+ end;
+end;
+
+
+function FindRegDealloc(supreg: tsuperregister; p: tai): boolean;
+var
+ hp: tai;
+ first: boolean;
+begin
+ findregdealloc := false;
+ first := true;
+ while assigned(p.previous) and
+ ((tai(p.previous).typ in (skipinstr+[ait_align])) or
+ ((tai(p.previous).typ = ait_label) and
+ labelCanBeSkipped(tai_label(p.previous)))) do
+ begin
+ p := tai(p.previous);
+ if (p.typ = ait_regalloc) and
+ (getregtype(tai_regalloc(p).reg) = R_INTREGISTER) and
+ (getsupreg(tai_regalloc(p).reg) = supreg) then
+ if (tai_regalloc(p).ratype=ra_dealloc) then
+ if first then
+ begin
+ findregdealloc := true;
+ break;
+ end
+ else
+ begin
+ findRegDealloc :=
+ getNextInstruction(p,hp) and
+ regLoadedWithNewValue(supreg,false,hp);
+ break
+ end
+ else
+ first := false;
+ end
+end;
+
+
+
+procedure incState(var S: Byte; amount: longint);
+{increases S by 1, wraps around at $ffff to 0 (so we won't get overflow
+ errors}
+begin
+ if (s <= $ff - amount) then
+ inc(s, amount)
+ else s := longint(s) + amount - $ff;
+end;
+
+
+function sequenceDependsonReg(const Content: TContent; seqreg: tsuperregister; supreg: tsuperregister): Boolean;
+{ Content is the sequence of instructions that describes the contents of }
+{ seqReg. reg is being overwritten by the current instruction. if the }
+{ content of seqReg depends on reg (ie. because of a }
+{ "movl (seqreg,reg), seqReg" instruction), this function returns true }
+var
+ p: tai;
+ Counter: Word;
+ TmpResult: Boolean;
+ RegsChecked: TRegSet;
+begin
+ RegsChecked := [];
+ p := Content.StartMod;
+ TmpResult := False;
+ Counter := 1;
+ while not(TmpResult) and
+ (Counter <= Content.NrOfMods) Do
+ begin
+ if (p.typ = ait_instruction) and
+ ((taicpu(p).opcode = A_MOV) or
+ (taicpu(p).opcode = A_MOVZX) or
+ (taicpu(p).opcode = A_MOVSX) or
+ (taicpu(p).opcode = A_LEA)) and
+ (taicpu(p).oper[0]^.typ = top_ref) then
+ With taicpu(p).oper[0]^.ref^ Do
+ if ((base = current_procinfo.FramePointer) or
+ (assigned(symbol) and (base = NR_NO))) and
+ (index = NR_NO) then
+ begin
+ RegsChecked := RegsChecked + [getsupreg(taicpu(p).oper[1]^.reg)];
+ if supreg = getsupreg(taicpu(p).oper[1]^.reg) then
+ break;
+ end
+ else
+ tmpResult :=
+ regReadByInstruction(supreg,p) and
+ regModifiedByInstruction(seqReg,p)
+ else
+ tmpResult :=
+ regReadByInstruction(supreg,p) and
+ regModifiedByInstruction(seqReg,p);
+ inc(Counter);
+ GetNextInstruction(p,p)
+ end;
+ sequenceDependsonReg := TmpResult
+end;
+
+
+procedure invalidateDependingRegs(p1: ptaiprop; supreg: tsuperregister);
+var
+ counter: tsuperregister;
+begin
+ for counter := RS_EAX to RS_EDI do
+ if counter <> supreg then
+ with p1^.regs[counter] Do
+ begin
+ if (typ in [con_ref,con_noRemoveRef]) and
+ sequenceDependsOnReg(p1^.Regs[counter],counter,supreg) then
+ if typ in [con_ref, con_invalid] then
+ typ := con_invalid
+ { con_noRemoveRef = con_unknown }
+ else
+ typ := con_unknown;
+ if assigned(memwrite) and
+ regInRef(counter,memwrite.oper[1]^.ref^) then
+ memwrite := nil;
+ end;
+end;
+
+
+procedure DestroyReg(p1: ptaiprop; supreg: tsuperregister; doincState:Boolean);
+{Destroys the contents of the register reg in the ptaiprop p1, as well as the
+ contents of registers are loaded with a memory location based on reg.
+ doincState is false when this register has to be destroyed not because
+ it's contents are directly modified/overwritten, but because of an indirect
+ action (e.g. this register holds the contents of a variable and the value
+ of the variable in memory is changed) }
+begin
+{$push}{$warnings off}
+ { the following happens for fpu registers }
+ if (supreg < low(NrOfInstrSinceLastMod)) or
+ (supreg > high(NrOfInstrSinceLastMod)) then
+ exit;
+{$pop}
+ NrOfInstrSinceLastMod[supreg] := 0;
+ with p1^.regs[supreg] do
+ begin
+ if doincState then
+ begin
+ incState(wstate,1);
+ typ := con_unknown;
+ startmod := nil;
+ end
+ else
+ if typ in [con_ref,con_const,con_invalid] then
+ typ := con_invalid
+ { con_noRemoveRef = con_unknown }
+ else
+ typ := con_unknown;
+ memwrite := nil;
+ end;
+ invalidateDependingRegs(p1,supreg);
+end;
+
+{procedure AddRegsToSet(p: tai; var RegSet: TRegSet);
+begin
+ if (p.typ = ait_instruction) then
+ begin
+ case taicpu(p).oper[0]^.typ Of
+ top_reg:
+ if not(taicpu(p).oper[0]^.reg in [RS_NO,RS_ESP,current_procinfo.FramePointer]) then
+ RegSet := RegSet + [taicpu(p).oper[0]^.reg];
+ top_ref:
+ With TReference(taicpu(p).oper[0]^) Do
+ begin
+ if not(base in [current_procinfo.FramePointer,RS_NO,RS_ESP])
+ then RegSet := RegSet + [base];
+ if not(index in [current_procinfo.FramePointer,RS_NO,RS_ESP])
+ then RegSet := RegSet + [index];
+ end;
+ end;
+ case taicpu(p).oper[1]^.typ Of
+ top_reg:
+ if not(taicpu(p).oper[1]^.reg in [RS_NO,RS_ESP,current_procinfo.FramePointer]) then
+ if RegSet := RegSet + [TRegister(TwoWords(taicpu(p).oper[1]^).Word1];
+ top_ref:
+ With TReference(taicpu(p).oper[1]^) Do
+ begin
+ if not(base in [current_procinfo.FramePointer,RS_NO,RS_ESP])
+ then RegSet := RegSet + [base];
+ if not(index in [current_procinfo.FramePointer,RS_NO,RS_ESP])
+ then RegSet := RegSet + [index];
+ end;
+ end;
+ end;
+end;}
+
+function OpsEquivalent(const o1, o2: toper; const oldinst, newinst: taicpu; var RegInfo: toptreginfo; OpAct: TopAction): Boolean;
+begin {checks whether the two ops are equivalent}
+ OpsEquivalent := False;
+ if o1.typ=o2.typ then
+ case o1.typ Of
+ top_reg:
+ OpsEquivalent :=RegsEquivalent(o1.reg,o2.reg, oldinst, newinst, RegInfo, OpAct);
+ top_ref:
+ OpsEquivalent := RefsEquivalent(o1.ref^, o2.ref^, oldinst, newinst, RegInfo);
+ Top_Const:
+ OpsEquivalent := o1.val = o2.val;
+ Top_None:
+ OpsEquivalent := True
+ end;
+end;
+
+
+function OpsEqual(const o1,o2:toper): Boolean;
+begin {checks whether the two ops are equal}
+ OpsEqual := False;
+ if o1.typ=o2.typ then
+ case o1.typ Of
+ top_reg :
+ OpsEqual:=o1.reg=o2.reg;
+ top_ref :
+ OpsEqual := RefsEqual(o1.ref^, o2.ref^);
+ Top_Const :
+ OpsEqual:=o1.val=o2.val;
+ Top_None :
+ OpsEqual := True
+ end;
+end;
+
+
+function sizescompatible(loadsize,newsize: topsize): boolean;
+ begin
+ case loadsize of
+ S_B,S_BW,S_BL:
+ sizescompatible := (newsize = loadsize) or (newsize = S_B);
+ S_W,S_WL:
+ sizescompatible := (newsize = loadsize) or (newsize = S_W);
+ else
+ sizescompatible := newsize = S_L;
+ end;
+ end;
+
+
+function opscompatible(p1,p2: taicpu): boolean;
+begin
+ case p1.opcode of
+ A_MOVZX,A_MOVSX:
+ opscompatible :=
+ ((p2.opcode = p1.opcode) or (p2.opcode = A_MOV)) and
+ sizescompatible(p1.opsize,p2.opsize);
+ else
+ opscompatible :=
+ (p1.opcode = p2.opcode) and
+ (p1.ops = p2.ops) and
+ (p1.opsize = p2.opsize);
+ end;
+end;
+
+
+function InstructionsEquivalent(p1, p2: tai; var RegInfo: toptreginfo): Boolean;
+{$ifdef csdebug}
+var
+ hp: tai;
+{$endif csdebug}
+begin {checks whether two taicpu instructions are equal}
+ if assigned(p1) and assigned(p2) and
+ (tai(p1).typ = ait_instruction) and
+ (tai(p2).typ = ait_instruction) and
+ opscompatible(taicpu(p1),taicpu(p2)) and
+ (not(assigned(taicpu(p1).oper[0])) or
+ (taicpu(p1).oper[0]^.typ = taicpu(p2).oper[0]^.typ)) and
+ (not(assigned(taicpu(p1).oper[1])) or
+ (taicpu(p1).oper[1]^.typ = taicpu(p2).oper[1]^.typ)) and
+ (not(assigned(taicpu(p1).oper[2])) or
+ (taicpu(p1).oper[2]^.typ = taicpu(p2).oper[2]^.typ)) then
+ {both instructions have the same structure:
+ "<operator> <operand of type1>, <operand of type 2>"}
+ if ((taicpu(p1).opcode = A_MOV) or
+ (taicpu(p1).opcode = A_MOVZX) or
+ (taicpu(p1).opcode = A_MOVSX) or
+ (taicpu(p1).opcode = A_LEA)) and
+ (taicpu(p1).oper[0]^.typ = top_ref) {then .oper[1]^t = top_reg} then
+ if not(RegInRef(getsupreg(taicpu(p1).oper[1]^.reg), taicpu(p1).oper[0]^.ref^)) then
+ {the "old" instruction is a load of a register with a new value, not with
+ a value based on the contents of this register (so no "mov (reg), reg")}
+ if not(RegInRef(getsupreg(taicpu(p2).oper[1]^.reg), taicpu(p2).oper[0]^.ref^)) and
+ RefsEquivalent(taicpu(p1).oper[0]^.ref^, taicpu(p2).oper[0]^.ref^,taicpu(p1), taicpu(p2), reginfo) then
+ {the "new" instruction is also a load of a register with a new value, and
+ this value is fetched from the same memory location}
+ begin
+ With taicpu(p2).oper[0]^.ref^ Do
+ begin
+ if (base <> NR_NO) and
+ (not(getsupreg(base) in [getsupreg(current_procinfo.FramePointer), RS_ESP])) then
+ include(RegInfo.RegsLoadedForRef, getsupreg(base));
+ if (index <> NR_NO) and
+ (not(getsupreg(index) in [getsupreg(current_procinfo.FramePointer), RS_ESP])) then
+ include(RegInfo.RegsLoadedForRef, getsupreg(index));
+ end;
+ {add the registers from the reference (.oper[0]^) to the RegInfo, all registers
+ from the reference are the same in the old and in the new instruction
+ sequence}
+ AddOp2RegInfo(taicpu(p1).oper[0]^, RegInfo);
+ {the registers from .oper[1]^ have to be equivalent, but not necessarily equal}
+ InstructionsEquivalent :=
+ RegsEquivalent(taicpu(p1).oper[1]^.reg,
+ taicpu(p2).oper[1]^.reg, taicpu(p1), taicpu(p2), RegInfo, OpAct_Write);
+ end
+ {the registers are loaded with values from different memory locations. if
+ this was allowed, the instructions "mov -4(esi),eax" and "mov -4(ebp),eax"
+ would be considered equivalent}
+ else
+ InstructionsEquivalent := False
+ else
+ {load register with a value based on the current value of this register}
+ begin
+ With taicpu(p2).oper[0]^.ref^ Do
+ begin
+ if (base <> NR_NO) and
+ (not(getsupreg(base) in [getsupreg(current_procinfo.FramePointer),
+ getsupreg(taicpu(p2).oper[1]^.reg),RS_ESP])) then
+ {it won't do any harm if the register is already in RegsLoadedForRef}
+ begin
+ include(RegInfo.RegsLoadedForRef, getsupreg(base));
+{$ifdef csdebug}
+ Writeln(std_regname(base), ' added');
+{$endif csdebug}
+ end;
+ if (index <> NR_NO) and
+ (not(getsupreg(index) in [getsupreg(current_procinfo.FramePointer),
+ getsupreg(taicpu(p2).oper[1]^.reg),RS_ESP])) then
+ begin
+ include(RegInfo.RegsLoadedForRef, getsupreg(index));
+{$ifdef csdebug}
+ Writeln(std_regname(index), ' added');
+{$endif csdebug}
+ end;
+
+ end;
+ if (taicpu(p2).oper[1]^.reg <> NR_NO) and
+ (not(getsupreg(taicpu(p2).oper[1]^.reg) in [getsupreg(current_procinfo.FramePointer),RS_ESP])) then
+ begin
+ RegInfo.RegsLoadedForRef := RegInfo.RegsLoadedForRef -
+ [getsupreg(taicpu(p2).oper[1]^.reg)];
+{$ifdef csdebug}
+ Writeln(std_regname(newreg(R_INTREGISTER,getsupreg(taicpu(p2).oper[1]^.reg),R_SUBWHOLE)), ' removed');
+{$endif csdebug}
+ end;
+ InstructionsEquivalent :=
+ OpsEquivalent(taicpu(p1).oper[0]^, taicpu(p2).oper[0]^, taicpu(p1), taicpu(p2), RegInfo, OpAct_Read) and
+ OpsEquivalent(taicpu(p1).oper[1]^, taicpu(p2).oper[1]^, taicpu(p1), taicpu(p2), RegInfo, OpAct_Write)
+ end
+ else
+ {an instruction <> mov, movzx, movsx}
+ begin
+ {$ifdef csdebug}
+ hp := tai_comment.Create(strpnew('checking if equivalent'));
+ hp.previous := p2;
+ hp.next := p2.next;
+ p2.next.previous := hp;
+ p2.next := hp;
+ {$endif csdebug}
+ InstructionsEquivalent :=
+ (not(assigned(taicpu(p1).oper[0])) or
+ OpsEquivalent(taicpu(p1).oper[0]^, taicpu(p2).oper[0]^, taicpu(p1), taicpu(p2), RegInfo, OpAct_Unknown)) and
+ (not(assigned(taicpu(p1).oper[1])) or
+ OpsEquivalent(taicpu(p1).oper[1]^, taicpu(p2).oper[1]^, taicpu(p1), taicpu(p2), RegInfo, OpAct_Unknown)) and
+ (not(assigned(taicpu(p1).oper[2])) or
+ OpsEquivalent(taicpu(p1).oper[2]^, taicpu(p2).oper[2]^, taicpu(p1), taicpu(p2), RegInfo, OpAct_Unknown))
+ end
+ {the instructions haven't even got the same structure, so they're certainly
+ not equivalent}
+ else
+ begin
+ {$ifdef csdebug}
+ hp := tai_comment.Create(strpnew('different opcodes/format'));
+ hp.previous := p2;
+ hp.next := p2.next;
+ p2.next.previous := hp;
+ p2.next := hp;
+ {$endif csdebug}
+ InstructionsEquivalent := False;
+ end;
+ {$ifdef csdebug}
+ hp := tai_comment.Create(strpnew('instreq: '+tostr(byte(instructionsequivalent))));
+ hp.previous := p2;
+ hp.next := p2.next;
+ p2.next.previous := hp;
+ p2.next := hp;
+ {$endif csdebug}
+end;
+
+(*
+function InstructionsEqual(p1, p2: tai): Boolean;
+begin {checks whether two taicpu instructions are equal}
+ InstructionsEqual :=
+ assigned(p1) and assigned(p2) and
+ ((tai(p1).typ = ait_instruction) and
+ (tai(p1).typ = ait_instruction) and
+ (taicpu(p1).opcode = taicpu(p2).opcode) and
+ (taicpu(p1).oper[0]^.typ = taicpu(p2).oper[0]^.typ) and
+ (taicpu(p1).oper[1]^.typ = taicpu(p2).oper[1]^.typ) and
+ OpsEqual(taicpu(p1).oper[0]^.typ, taicpu(p1).oper[0]^, taicpu(p2).oper[0]^) and
+ OpsEqual(taicpu(p1).oper[1]^.typ, taicpu(p1).oper[1]^, taicpu(p2).oper[1]^))
+end;
+*)
+
+procedure readreg(p: ptaiprop; supreg: tsuperregister);
+begin
+ if supreg in [RS_EAX..RS_EDI] then
+ incState(p^.regs[supreg].rstate,1)
+end;
+
+
+procedure readref(p: ptaiprop; const ref: preference);
+begin
+ if ref^.base <> NR_NO then
+ readreg(p, getsupreg(ref^.base));
+ if ref^.index <> NR_NO then
+ readreg(p, getsupreg(ref^.index));
+end;
+
+
+procedure ReadOp(p: ptaiprop;const o:toper);
+begin
+ case o.typ Of
+ top_reg: readreg(p, getsupreg(o.reg));
+ top_ref: readref(p, o.ref);
+ end;
+end;
+
+
+function RefInInstruction(const ref: TReference; p: tai;
+ RefsEq: TRefCompare; size: tcgsize): Boolean;
+{checks whehter ref is used in p}
+var
+ mysize: tcgsize;
+ TmpResult: Boolean;
+begin
+ TmpResult := False;
+ if (p.typ = ait_instruction) then
+ begin
+ mysize := topsize2tcgsize[taicpu(p).opsize];
+ if (taicpu(p).ops >= 1) and
+ (taicpu(p).oper[0]^.typ = top_ref) then
+ TmpResult := RefsEq(taicpu(p).oper[0]^.ref^,ref,mysize,size);
+ if not(TmpResult) and
+ (taicpu(p).ops >= 2) and
+ (taicpu(p).oper[1]^.typ = top_ref) then
+ TmpResult := RefsEq(taicpu(p).oper[1]^.ref^,ref,mysize,size);
+ if not(TmpResult) and
+ (taicpu(p).ops >= 3) and
+ (taicpu(p).oper[2]^.typ = top_ref) then
+ TmpResult := RefsEq(taicpu(p).oper[2]^.ref^,ref,mysize,size);
+ end;
+ RefInInstruction := TmpResult;
+end;
+
+
+function RefInSequence(const ref: TReference; Content: TContent;
+ RefsEq: TRefCompare; size: tcgsize): Boolean;
+{checks the whole sequence of Content (so StartMod and and the next NrOfMods
+ tai objects) to see whether ref is used somewhere}
+var p: tai;
+ Counter: Word;
+ TmpResult: Boolean;
+begin
+ p := Content.StartMod;
+ TmpResult := False;
+ Counter := 1;
+ while not(TmpResult) and
+ (Counter <= Content.NrOfMods) Do
+ begin
+ if (p.typ = ait_instruction) and
+ RefInInstruction(ref, p, RefsEq, size)
+ then TmpResult := True;
+ inc(Counter);
+ GetNextInstruction(p,p)
+ end;
+ RefInSequence := TmpResult
+end;
+
+{$push}
+{$q-}
+// checks whether a write to r2 of size "size" contains address r1
+function arrayrefsoverlapping(const r1, r2: treference; size1, size2: tcgsize): Boolean;
+var
+ realsize1, realsize2: aint;
+begin
+ realsize1 := tcgsize2size[size1];
+ realsize2 := tcgsize2size[size2];
+ arrayrefsoverlapping :=
+ (r2.offset <= r1.offset+realsize1) and
+ (r1.offset <= r2.offset+realsize2) and
+ (r1.segment = r2.segment) and
+ (r1.symbol=r2.symbol) and
+ (r1.base = r2.base)
+end;
+{$pop}
+
+function isSimpleRef(const ref: treference): boolean;
+{ returns true if ref is reference to a local or global variable, to a }
+{ parameter or to an object field (this includes arrays). Returns false }
+{ otherwise. }
+begin
+ isSimpleRef :=
+ assigned(ref.symbol) or
+ (ref.base = current_procinfo.framepointer);
+end;
+
+
+function containsPointerRef(p: tai): boolean;
+{ checks if an instruction contains a reference which is a pointer location }
+var
+ hp: taicpu;
+ count: longint;
+begin
+ containsPointerRef := false;
+ if p.typ <> ait_instruction then
+ exit;
+ hp := taicpu(p);
+ for count := 0 to hp.ops-1 do
+ begin
+ case hp.oper[count]^.typ of
+ top_ref:
+ if not isSimpleRef(hp.oper[count]^.ref^) then
+ begin
+ containsPointerRef := true;
+ exit;
+ end;
+ top_none:
+ exit;
+ end;
+ end;
+end;
+
+
+function containsPointerLoad(c: tcontent): boolean;
+{ checks whether the contents of a register contain a pointer reference }
+var
+ p: tai;
+ count: longint;
+begin
+ containsPointerLoad := false;
+ p := c.startmod;
+ for count := c.nrOfMods downto 1 do
+ begin
+ if containsPointerRef(p) then
+ begin
+ containsPointerLoad := true;
+ exit;
+ end;
+ getnextinstruction(p,p);
+ end;
+end;
+
+
+function writeToMemDestroysContents(regWritten: tsuperregister; const ref: treference;
+ supreg: tsuperregister; size: tcgsize; const c: tcontent; var invalsmemwrite: boolean): boolean;
+{ returns whether the contents c of reg are invalid after regWritten is }
+{ is written to ref }
+var
+ refsEq: trefCompare;
+begin
+ if isSimpleRef(ref) then
+ begin
+ if (ref.index <> NR_NO) or
+ (assigned(ref.symbol) and
+ (ref.base <> NR_NO)) then
+ { local/global variable or parameter which is an array }
+ refsEq := @arrayRefsOverlapping
+ else
+ { local/global variable or parameter which is not an array }
+ refsEq := @refsOverlapping;
+ invalsmemwrite :=
+ assigned(c.memwrite) and
+ ((not(cs_opt_size in current_settings.optimizerswitches) and
+ containsPointerRef(c.memwrite)) or
+ refsEq(c.memwrite.oper[1]^.ref^,ref,topsize2tcgsize[c.memwrite.opsize],size));
+ if not(c.typ in [con_ref,con_noRemoveRef,con_invalid]) then
+ begin
+ writeToMemDestroysContents := false;
+ exit;
+ end;
+
+ { write something to a parameter, a local or global variable, so }
+ { * with uncertain optimizations on: }
+ { - destroy the contents of registers whose contents have somewhere a }
+ { "mov?? (ref), %reg". WhichReg (this is the register whose contents }
+ { are being written to memory) is not destroyed if it's StartMod is }
+ { of that form and NrOfMods = 1 (so if it holds ref, but is not a }
+ { expression based on ref) }
+ { * with uncertain optimizations off: }
+ { - also destroy registers that contain any pointer }
+ with c do
+ writeToMemDestroysContents :=
+ (typ in [con_ref,con_noRemoveRef]) and
+ ((not(cs_opt_size in current_settings.optimizerswitches) and
+ containsPointerLoad(c)
+ ) or
+ (refInSequence(ref,c,refsEq,size) and
+ ((supreg <> regWritten) or
+ not((nrOfMods = 1) and
+ {StarMod is always of the type ait_instruction}
+ (taicpu(StartMod).oper[0]^.typ = top_ref) and
+ refsEq(taicpu(StartMod).oper[0]^.ref^, ref, topsize2tcgsize[taicpu(StartMod).opsize],size)
+ )
+ )
+ )
+ );
+ end
+ else
+ { write something to a pointer location, so }
+ { * with uncertain optimzations on: }
+ { - do not destroy registers which contain a local/global variable or }
+ { a parameter, except if DestroyRefs is called because of a "movsl" }
+ { * with uncertain optimzations off: }
+ { - destroy every register which contains a memory location }
+ begin
+ invalsmemwrite :=
+ assigned(c.memwrite) and
+ (not(cs_opt_size in current_settings.optimizerswitches) or
+ containsPointerRef(c.memwrite));
+ if not(c.typ in [con_ref,con_noRemoveRef,con_invalid]) then
+ begin
+ writeToMemDestroysContents := false;
+ exit;
+ end;
+ with c do
+ writeToMemDestroysContents :=
+ (typ in [con_ref,con_noRemoveRef]) and
+ (not(cs_opt_size in current_settings.optimizerswitches) or
+ { for movsl }
+ ((ref.base = NR_EDI) and (ref.index = NR_EDI)) or
+ { don't destroy if reg contains a parameter, local or global variable }
+ containsPointerLoad(c)
+ );
+ end;
+end;
+
+
+function writeToRegDestroysContents(destReg, supreg: tsuperregister;
+ const c: tcontent): boolean;
+{ returns whether the contents c of reg are invalid after destReg is }
+{ modified }
+begin
+ writeToRegDestroysContents :=
+ (c.typ in [con_ref,con_noRemoveRef,con_invalid]) and
+ sequenceDependsOnReg(c,supreg,destReg);
+end;
+
+
+function writeDestroysContents(const op: toper; supreg: tsuperregister; size: tcgsize;
+ const c: tcontent; var memwritedestroyed: boolean): boolean;
+{ returns whether the contents c of reg are invalid after regWritten is }
+{ is written to op }
+begin
+ memwritedestroyed := false;
+ case op.typ of
+ top_reg:
+ writeDestroysContents :=
+ (getregtype(op.reg) = R_INTREGISTER) and
+ writeToRegDestroysContents(getsupreg(op.reg),supreg,c);
+ top_ref:
+ writeDestroysContents :=
+ writeToMemDestroysContents(RS_INVALID,op.ref^,supreg,size,c,memwritedestroyed);
+ else
+ writeDestroysContents := false;
+ end;
+end;
+
+
+procedure destroyRefs(p: tai; const ref: treference; regwritten: tsuperregister; size: tcgsize);
+{ destroys all registers which possibly contain a reference to ref, regWritten }
+{ is the register whose contents are being written to memory (if this proc }
+{ is called because of a "mov?? %reg, (mem)" instruction) }
+var
+ counter: tsuperregister;
+ destroymemwrite: boolean;
+begin
+ for counter := RS_EAX to RS_EDI Do
+ begin
+ if writeToMemDestroysContents(regwritten,ref,counter,size,
+ ptaiprop(p.optInfo)^.regs[counter],destroymemwrite) then
+ destroyReg(ptaiprop(p.optInfo), counter, false)
+ else if destroymemwrite then
+ ptaiprop(p.optinfo)^.regs[counter].MemWrite := nil;
+ end;
+end;
+
+
+procedure DestroyAllRegs(p: ptaiprop; read, written: boolean);
+var Counter: tsuperregister;
+begin {initializes/desrtoys all registers}
+ For Counter := RS_EAX To RS_EDI Do
+ begin
+ if read then
+ readreg(p, Counter);
+ DestroyReg(p, Counter, written);
+ p^.regs[counter].MemWrite := nil;
+ end;
+ p^.DirFlag := F_Unknown;
+end;
+
+
+procedure DestroyOp(taiObj: tai; const o:Toper);
+{$ifdef statedebug}
+var
+ hp: tai;
+{$endif statedebug}
+begin
+ case o.typ Of
+ top_reg:
+ begin
+{$ifdef statedebug}
+ hp := tai_comment.Create(strpnew('destroying '+std_regname(o.reg)));
+ hp.next := taiobj.next;
+ hp.previous := taiobj;
+ taiobj.next := hp;
+ if assigned(hp.next) then
+ hp.next.previous := hp;
+{$endif statedebug}
+ DestroyReg(ptaiprop(taiObj.OptInfo), getsupreg(o.reg), true);
+ end;
+ top_ref:
+ begin
+ readref(ptaiprop(taiObj.OptInfo), o.ref);
+ DestroyRefs(taiObj, o.ref^, RS_INVALID,topsize2tcgsize[(taiobj as taicpu).opsize]);
+ end;
+ end;
+end;
+
+
+procedure AddInstr2RegContents({$ifdef statedebug} asml: TAsmList; {$endif}
+p: taicpu; supreg: tsuperregister);
+{$ifdef statedebug}
+var
+ hp: tai;
+{$endif statedebug}
+begin
+ With ptaiprop(p.optinfo)^.regs[supreg] Do
+ if (typ in [con_ref,con_noRemoveRef]) then
+ begin
+ incState(wstate,1);
+ { also store how many instructions are part of the sequence in the first }
+ { instructions ptaiprop, so it can be easily accessed from within }
+ { CheckSequence}
+ inc(NrOfMods, NrOfInstrSinceLastMod[supreg]);
+ ptaiprop(tai(StartMod).OptInfo)^.Regs[supreg].NrOfMods := NrOfMods;
+ NrOfInstrSinceLastMod[supreg] := 0;
+ invalidateDependingRegs(p.optinfo,supreg);
+ ptaiprop(p.optinfo)^.regs[supreg].memwrite := nil;
+{$ifdef StateDebug}
+ hp := tai_comment.Create(strpnew(std_regname(newreg(R_INTREGISTER,supreg,R_SUBWHOLE))+': '+tostr(ptaiprop(p.optinfo)^.Regs[supreg].WState)
+ + ' -- ' + tostr(ptaiprop(p.optinfo)^.Regs[supreg].nrofmods)));
+ InsertLLItem(AsmL, p, p.next, hp);
+{$endif StateDebug}
+ end
+ else
+ begin
+{$ifdef statedebug}
+ hp := tai_comment.Create(strpnew('destroying '+std_regname(newreg(R_INTREGISTER,supreg,R_SUBWHOLE))));
+ insertllitem(asml,p,p.next,hp);
+{$endif statedebug}
+ DestroyReg(ptaiprop(p.optinfo), supreg, true);
+{$ifdef StateDebug}
+ hp := tai_comment.Create(strpnew(std_regname(newreg(R_INTREGISTER,supreg,R_SUBWHOLE))+': '+tostr(ptaiprop(p.optinfo)^.Regs[supreg].WState)));
+ InsertLLItem(AsmL, p, p.next, hp);
+{$endif StateDebug}
+ end
+end;
+
+
+procedure AddInstr2OpContents({$ifdef statedebug} asml: TAsmList; {$endif}
+p: taicpu; const oper: TOper);
+begin
+ if oper.typ = top_reg then
+ AddInstr2RegContents({$ifdef statedebug} asml, {$endif}p, getsupreg(oper.reg))
+ else
+ begin
+ ReadOp(ptaiprop(p.optinfo), oper);
+ DestroyOp(p, oper);
+ end
+end;
+
+
+{*************************************************************************************}
+{************************************** TDFAOBJ **************************************}
+{*************************************************************************************}
+
+constructor tdfaobj.create(_list: TAsmList);
+begin
+ list := _list;
+ blockstart := nil;
+ blockend := nil;
+ nroftaiobjs := 0;
+ taipropblock := nil;
+ lolab := 0;
+ hilab := 0;
+ labdif := 0;
+ labeltable := nil;
+end;
+
+
+procedure tdfaobj.initlabeltable;
+var
+ labelfound: boolean;
+ p, prev: tai;
+ hp1, hp2: tai;
+{$ifdef i386}
+ regcounter,
+ supreg : tsuperregister;
+{$endif i386}
+ usedregs, nodeallocregs: tregset;
+begin
+ labelfound := false;
+ lolab := maxlongint;
+ hilab := 0;
+ p := blockstart;
+ prev := p;
+ while assigned(p) do
+ begin
+ if (tai(p).typ = ait_label) then
+ if not labelcanbeskipped(tai_label(p)) then
+ begin
+ labelfound := true;
+ if (tai_Label(p).labsym.labelnr < lolab) then
+ lolab := tai_label(p).labsym.labelnr;
+ if (tai_Label(p).labsym.labelnr > hilab) then
+ hilab := tai_label(p).labsym.labelnr;
+ end;
+ prev := p;
+ getnextinstruction(p, p);
+ end;
+ if (prev.typ = ait_marker) and
+ (tai_marker(prev).kind = mark_AsmBlockStart) then
+ blockend := prev
+ else blockend := nil;
+ if labelfound then
+ labdif := hilab+1-lolab
+ else labdif := 0;
+
+ usedregs := [];
+ if (labdif <> 0) then
+ begin
+ getmem(labeltable, labdif*sizeof(tlabeltableitem));
+ fillchar(labeltable^, labdif*sizeof(tlabeltableitem), 0);
+ end;
+ p := blockstart;
+ prev := p;
+ while (p <> blockend) do
+ begin
+ case p.typ of
+ ait_label:
+ if not labelcanbeskipped(tai_label(p)) then
+ labeltable^[tai_label(p).labsym.labelnr-lolab].taiobj := p;
+{$ifdef i386}
+ ait_regalloc:
+ if (getregtype(tai_regalloc(p).reg) = R_INTREGISTER) then
+ begin
+ supreg:=getsupreg(tai_regalloc(p).reg);
+ case tai_regalloc(p).ratype of
+ ra_alloc :
+ begin
+ if not(supreg in usedregs) then
+ include(usedregs, supreg)
+ else
+ begin
+ //addregdeallocfor(list, tai_regalloc(p).reg, p);
+ hp1 := tai(p.previous);
+ list.remove(p);
+ p.free;
+ p := hp1;
+ end;
+ end;
+ ra_dealloc :
+ begin
+ exclude(usedregs, supreg);
+ hp1 := p;
+ hp2 := nil;
+ while not(findregalloc(supreg,tai(hp1.next),ra_alloc)) and
+ getnextinstruction(hp1, hp1) and
+ regininstruction(getsupreg(tai_regalloc(p).reg), hp1) Do
+ hp2 := hp1;
+ if hp2 <> nil then
+ begin
+ hp1 := tai(p.previous);
+ list.remove(p);
+ insertllitem(list, hp2, tai(hp2.next), p);
+ p := hp1;
+ end
+ else if findregalloc(getsupreg(tai_regalloc(p).reg), tai(p.next),ra_alloc)
+ and getnextinstruction(p,hp1) then
+ begin
+ hp1 := tai(p.previous);
+ list.remove(p);
+ p.free;
+ p := hp1;
+// don't include here, since then the allocation will be removed when it's processed
+// include(usedregs,supreg);
+ end;
+ end;
+ end;
+ end;
+{$endif i386}
+ end;
+ repeat
+ prev := p;
+ p := tai(p.next);
+ until not(assigned(p)) or
+ (p = blockend) or
+ not(p.typ in (skipinstr - [ait_regalloc]));
+ end;
+{$ifdef i386}
+ { don't add deallocation for function result variable or for regvars}
+ getNoDeallocRegs(noDeallocRegs);
+ usedRegs := usedRegs - noDeallocRegs;
+ for regCounter := RS_EAX to RS_EDI do
+ if regCounter in usedRegs then
+ addRegDeallocFor(list,newreg(R_INTREGISTER,regCounter,R_SUBWHOLE),prev);
+{$endif i386}
+end;
+
+
+function tdfaobj.pass_1(_blockstart: tai): tai;
+begin
+ blockstart := _blockstart;
+ initlabeltable;
+ pass_1 := blockend;
+end;
+
+
+
+function tdfaobj.initdfapass2: boolean;
+{reserves memory for the PtaiProps in one big memory block when not using
+ TP, returns False if not enough memory is available for the optimizer in all
+ cases}
+var
+ p: tai;
+ count: Longint;
+{ TmpStr: String; }
+begin
+ p := blockstart;
+ skiphead(p);
+ nroftaiobjs := 0;
+ while (p <> blockend) do
+ begin
+{$ifDef JumpAnal}
+ case p.typ of
+ ait_label:
+ begin
+ if not labelcanbeskipped(tai_label(p)) then
+ labeltable^[tai_label(p).labsym.labelnr-lolab].instrnr := nroftaiobjs
+ end;
+ ait_instruction:
+ begin
+ if taicpu(p).is_jmp then
+ begin
+ if (tasmlabel(taicpu(p).oper[0]^.sym).labsymabelnr >= lolab) and
+ (tasmlabel(taicpu(p).oper[0]^.sym).labsymabelnr <= hilab) then
+ inc(labeltable^[tasmlabel(taicpu(p).oper[0]^.sym).labsymabelnr-lolab].refsfound);
+ end;
+ end;
+{ ait_instruction:
+ begin
+ if (taicpu(p).opcode = A_PUSH) and
+ (taicpu(p).oper[0]^.typ = top_symbol) and
+ (PCSymbol(taicpu(p).oper[0]^)^.offset = 0) then
+ begin
+ TmpStr := StrPas(PCSymbol(taicpu(p).oper[0]^)^.symbol);
+ if}
+ end;
+{$endif JumpAnal}
+ inc(NrOftaiObjs);
+ getnextinstruction(p,p);
+ end;
+ if nroftaiobjs <> 0 then
+ begin
+ initdfapass2 := True;
+ getmem(taipropblock, nroftaiobjs*sizeof(ttaiprop));
+ fillchar(taiPropblock^,nroftaiobjs*sizeof(ttaiprop),0);
+ p := blockstart;
+ skiphead(p);
+ for count := 1 To nroftaiobjs do
+ begin
+ ptaiprop(p.optinfo) := @taipropblock^[count];
+ getnextinstruction(p, p);
+ end;
+ end
+ else
+ initdfapass2 := false;
+end;
+
+
+procedure tdfaobj.dodfapass2;
+{Analyzes the Data Flow of an assembler list. Starts creating the reg
+ contents for the instructions starting with p. Returns the last tai which has
+ been processed}
+var
+ curprop, LastFlagsChangeProp: ptaiprop;
+ Cnt, InstrCnt : Longint;
+ InstrProp: TInsProp;
+ UsedRegs: TRegSet;
+ prev,p : tai;
+ tmpref: TReference;
+ tmpsupreg: tsuperregister;
+{$ifdef statedebug}
+ hp : tai;
+{$endif}
+{$ifdef AnalyzeLoops}
+ hp : tai;
+ TmpState: Byte;
+{$endif AnalyzeLoops}
+begin
+ p := BlockStart;
+ LastFlagsChangeProp := nil;
+ prev := nil;
+ UsedRegs := [];
+ UpdateUsedregs(UsedRegs, p);
+ SkipHead(p);
+ BlockStart := p;
+ InstrCnt := 1;
+ fillchar(NrOfInstrSinceLastMod, SizeOf(NrOfInstrSinceLastMod), 0);
+ while (p <> Blockend) Do
+ begin
+ curprop := @taiPropBlock^[InstrCnt];
+ if assigned(prev)
+ then
+ begin
+{$ifdef JumpAnal}
+ if (p.Typ <> ait_label) then
+{$endif JumpAnal}
+ begin
+ curprop^.regs := ptaiprop(prev.OptInfo)^.Regs;
+ curprop^.DirFlag := ptaiprop(prev.OptInfo)^.DirFlag;
+ curprop^.FlagsUsed := false;
+ end
+ end
+ else
+ begin
+ fillchar(curprop^, SizeOf(curprop^), 0);
+{ For tmpreg := RS_EAX to RS_EDI Do
+ curprop^.regs[tmpreg].WState := 1;}
+ end;
+ curprop^.UsedRegs := UsedRegs;
+ curprop^.CanBeRemoved := False;
+ UpdateUsedRegs(UsedRegs, tai(p.Next));
+ For tmpsupreg := RS_EAX To RS_EDI Do
+ if NrOfInstrSinceLastMod[tmpsupreg] < 255 then
+ inc(NrOfInstrSinceLastMod[tmpsupreg])
+ else
+ begin
+ NrOfInstrSinceLastMod[tmpsupreg] := 0;
+ curprop^.regs[tmpsupreg].typ := con_unknown;
+ end;
+ case p.typ Of
+ ait_marker:;
+ ait_label:
+{$ifndef JumpAnal}
+ if not labelCanBeSkipped(tai_label(p)) then
+ DestroyAllRegs(curprop,false,false);
+{$else JumpAnal}
+ begin
+ if not labelCanBeSkipped(tai_label(p)) then
+ With LTable^[tai_Label(p).labsym^.labelnr-LoLab] Do
+{$ifDef AnalyzeLoops}
+ if (RefsFound = tai_Label(p).labsym^.RefCount)
+{$else AnalyzeLoops}
+ if (JmpsProcessed = tai_Label(p).labsym^.RefCount)
+{$endif AnalyzeLoops}
+ then
+{all jumps to this label have been found}
+{$ifDef AnalyzeLoops}
+ if (JmpsProcessed > 0)
+ then
+{$endif AnalyzeLoops}
+ {we've processed at least one jump to this label}
+ begin
+ if (GetLastInstruction(p, hp) and
+ not(((hp.typ = ait_instruction)) and
+ (taicpu_labeled(hp).is_jmp))
+ then
+ {previous instruction not a JMP -> the contents of the registers after the
+ previous intruction has been executed have to be taken into account as well}
+ For tmpsupreg := RS_EAX to RS_EDI Do
+ begin
+ if (curprop^.regs[tmpsupreg].WState <>
+ ptaiprop(hp.OptInfo)^.Regs[tmpsupreg].WState)
+ then DestroyReg(curprop, tmpsupreg, true)
+ end
+ end
+{$ifDef AnalyzeLoops}
+ else
+ {a label from a backward jump (e.g. a loop), no jump to this label has
+ already been processed}
+ if GetLastInstruction(p, hp) and
+ not(hp.typ = ait_instruction) and
+ (taicpu_labeled(hp).opcode = A_JMP))
+ then
+ {previous instruction not a jmp, so keep all the registers' contents from the
+ previous instruction}
+ begin
+ curprop^.regs := ptaiprop(hp.OptInfo)^.Regs;
+ curprop.DirFlag := ptaiprop(hp.OptInfo)^.DirFlag;
+ end
+ else
+ {previous instruction a jmp and no jump to this label processed yet}
+ begin
+ hp := p;
+ Cnt := InstrCnt;
+ {continue until we find a jump to the label or a label which has already
+ been processed}
+ while GetNextInstruction(hp, hp) and
+ not((hp.typ = ait_instruction) and
+ (taicpu(hp).is_jmp) and
+ (tasmlabel(taicpu(hp).oper[0]^.sym).labsymabelnr = tai_Label(p).labsym^.labelnr)) and
+ not((hp.typ = ait_label) and
+ (LTable^[tai_Label(hp).labsym^.labelnr-LoLab].RefsFound
+ = tai_Label(hp).labsym^.RefCount) and
+ (LTable^[tai_Label(hp).labsym^.labelnr-LoLab].JmpsProcessed > 0)) Do
+ inc(Cnt);
+ if (hp.typ = ait_label)
+ then
+ {there's a processed label after the current one}
+ begin
+ curprop^.regs := taiPropBlock^[Cnt].Regs;
+ curprop.DirFlag := taiPropBlock^[Cnt].DirFlag;
+ end
+ else
+ {there's no label anymore after the current one, or they haven't been
+ processed yet}
+ begin
+ GetLastInstruction(p, hp);
+ curprop^.regs := ptaiprop(hp.OptInfo)^.Regs;
+ curprop.DirFlag := ptaiprop(hp.OptInfo)^.DirFlag;
+ DestroyAllRegs(ptaiprop(hp.OptInfo),true,true)
+ end
+ end
+{$endif AnalyzeLoops}
+ else
+{not all references to this label have been found, so destroy all registers}
+ begin
+ GetLastInstruction(p, hp);
+ curprop^.regs := ptaiprop(hp.OptInfo)^.Regs;
+ curprop.DirFlag := ptaiprop(hp.OptInfo)^.DirFlag;
+ DestroyAllRegs(curprop,true,true)
+ end;
+ end;
+{$endif JumpAnal}
+
+ ait_stab, ait_force_line, ait_function_name:;
+ ait_align: ; { may destroy flags !!! }
+ ait_instruction:
+ begin
+ if taicpu(p).is_jmp or
+ (taicpu(p).opcode = A_JMP) then
+ begin
+{$ifNDef JumpAnal}
+ for tmpsupreg := RS_EAX to RS_EDI do
+ with curprop^.regs[tmpsupreg] do
+ case typ of
+ con_ref: typ := con_noRemoveRef;
+ con_const: typ := con_noRemoveConst;
+ con_invalid: typ := con_unknown;
+ end;
+{$else JumpAnal}
+ With LTable^[tasmlabel(taicpu(p).oper[0]^.sym).labsymabelnr-LoLab] Do
+ if (RefsFound = tasmlabel(taicpu(p).oper[0]^.sym).RefCount) then
+ begin
+ if (InstrCnt < InstrNr)
+ then
+ {forward jump}
+ if (JmpsProcessed = 0) then
+ {no jump to this label has been processed yet}
+ begin
+ taiPropBlock^[InstrNr].Regs := curprop^.regs;
+ taiPropBlock^[InstrNr].DirFlag := curprop.DirFlag;
+ inc(JmpsProcessed);
+ end
+ else
+ begin
+ For tmpreg := RS_EAX to RS_EDI Do
+ if (taiPropBlock^[InstrNr].Regs[tmpreg].WState <>
+ curprop^.regs[tmpreg].WState) then
+ DestroyReg(@taiPropBlock^[InstrNr], tmpreg, true);
+ inc(JmpsProcessed);
+ end
+{$ifdef AnalyzeLoops}
+ else
+{ backward jump, a loop for example}
+{ if (JmpsProcessed > 0) or
+ not(GetLastInstruction(taiObj, hp) and
+ (hp.typ = ait_labeled_instruction) and
+ (taicpu_labeled(hp).opcode = A_JMP))
+ then}
+{instruction prior to label is not a jmp, or at least one jump to the label
+ has yet been processed}
+ begin
+ inc(JmpsProcessed);
+ For tmpreg := RS_EAX to RS_EDI Do
+ if (taiPropBlock^[InstrNr].Regs[tmpreg].WState <>
+ curprop^.regs[tmpreg].WState)
+ then
+ begin
+ TmpState := taiPropBlock^[InstrNr].Regs[tmpreg].WState;
+ Cnt := InstrNr;
+ while (TmpState = taiPropBlock^[Cnt].Regs[tmpreg].WState) Do
+ begin
+ DestroyReg(@taiPropBlock^[Cnt], tmpreg, true);
+ inc(Cnt);
+ end;
+ while (Cnt <= InstrCnt) Do
+ begin
+ inc(taiPropBlock^[Cnt].Regs[tmpreg].WState);
+ inc(Cnt)
+ end
+ end;
+ end
+{ else }
+{instruction prior to label is a jmp and no jumps to the label have yet been
+ processed}
+{ begin
+ inc(JmpsProcessed);
+ For tmpreg := RS_EAX to RS_EDI Do
+ begin
+ TmpState := taiPropBlock^[InstrNr].Regs[tmpreg].WState;
+ Cnt := InstrNr;
+ while (TmpState = taiPropBlock^[Cnt].Regs[tmpreg].WState) Do
+ begin
+ taiPropBlock^[Cnt].Regs[tmpreg] := curprop^.regs[tmpreg];
+ inc(Cnt);
+ end;
+ TmpState := taiPropBlock^[InstrNr].Regs[tmpreg].WState;
+ while (TmpState = taiPropBlock^[Cnt].Regs[tmpreg].WState) Do
+ begin
+ DestroyReg(@taiPropBlock^[Cnt], tmpreg, true);
+ inc(Cnt);
+ end;
+ while (Cnt <= InstrCnt) Do
+ begin
+ inc(taiPropBlock^[Cnt].Regs[tmpreg].WState);
+ inc(Cnt)
+ end
+ end
+ end}
+{$endif AnalyzeLoops}
+ end;
+{$endif JumpAnal}
+ end
+ else
+ begin
+ InstrProp := InsProp[taicpu(p).opcode];
+ case taicpu(p).opcode Of
+ A_MOV, A_MOVZX, A_MOVSX:
+ begin
+ case taicpu(p).oper[0]^.typ Of
+ top_ref, top_reg:
+ case taicpu(p).oper[1]^.typ Of
+ top_reg:
+ begin
+{$ifdef statedebug}
+ hp := tai_comment.Create(strpnew('destroying '+std_regname(taicpu(p).oper[1]^.reg)));
+ insertllitem(list,p,p.next,hp);
+{$endif statedebug}
+
+ readOp(curprop, taicpu(p).oper[0]^);
+ tmpsupreg := getsupreg(taicpu(p).oper[1]^.reg);
+ if reginop(tmpsupreg, taicpu(p).oper[0]^) and
+ (curprop^.regs[tmpsupreg].typ in [con_ref,con_noRemoveRef]) then
+ begin
+ with curprop^.regs[tmpsupreg] Do
+ begin
+ incState(wstate,1);
+ { also store how many instructions are part of the sequence in the first }
+ { instruction's ptaiprop, so it can be easily accessed from within }
+ { CheckSequence }
+ inc(nrOfMods, nrOfInstrSinceLastMod[tmpsupreg]);
+ ptaiprop(startmod.optinfo)^.regs[tmpsupreg].nrOfMods := nrOfMods;
+ nrOfInstrSinceLastMod[tmpsupreg] := 0;
+ { Destroy the contents of the registers }
+ { that depended on the previous value of }
+ { this register }
+ invalidateDependingRegs(curprop,tmpsupreg);
+ curprop^.regs[tmpsupreg].memwrite := nil;
+ end;
+ end
+ else
+ begin
+{$ifdef statedebug}
+ hp := tai_comment.Create(strpnew('destroying & initing '+std_regname(newreg(R_INTREGISTER,tmpsupreg,R_SUBWHOLE))));
+ insertllitem(list,p,p.next,hp);
+{$endif statedebug}
+ destroyReg(curprop, tmpsupreg, true);
+ if not(reginop(tmpsupreg, taicpu(p).oper[0]^)) then
+ with curprop^.regs[tmpsupreg] Do
+ begin
+ typ := con_ref;
+ startmod := p;
+ nrOfMods := 1;
+ end
+ end;
+{$ifdef StateDebug}
+ hp := tai_comment.Create(strpnew(std_regname(newreg(R_INTREGISTER,tmpsupreg,R_SUBWHOLE))+': '+tostr(curprop^.regs[tmpsupreg].WState)));
+ insertllitem(list,p,p.next,hp);
+{$endif StateDebug}
+ end;
+ top_ref:
+ begin
+ readref(curprop, taicpu(p).oper[1]^.ref);
+ if taicpu(p).oper[0]^.typ = top_reg then
+ begin
+ readreg(curprop, getsupreg(taicpu(p).oper[0]^.reg));
+ DestroyRefs(p, taicpu(p).oper[1]^.ref^, getsupreg(taicpu(p).oper[0]^.reg),topsize2tcgsize[taicpu(p).opsize]);
+ ptaiprop(p.optinfo)^.regs[getsupreg(taicpu(p).oper[0]^.reg)].memwrite :=
+ taicpu(p);
+ end
+ else
+ DestroyRefs(p, taicpu(p).oper[1]^.ref^, RS_INVALID,topsize2tcgsize[taicpu(p).opsize]);
+ end;
+ end;
+ top_Const:
+ begin
+ case taicpu(p).oper[1]^.typ Of
+ top_reg:
+ begin
+ tmpsupreg := getsupreg(taicpu(p).oper[1]^.reg);
+{$ifdef statedebug}
+ hp := tai_comment.Create(strpnew('destroying '+std_regname(newreg(R_INTREGISTER,tmpsupreg,R_SUBWHOLE))));
+ insertllitem(list,p,p.next,hp);
+{$endif statedebug}
+ With curprop^.regs[tmpsupreg] Do
+ begin
+ DestroyReg(curprop, tmpsupreg, true);
+ typ := Con_Const;
+ StartMod := p;
+ nrOfMods := 1;
+ end
+ end;
+ top_ref:
+ begin
+ readref(curprop, taicpu(p).oper[1]^.ref);
+ DestroyRefs(p, taicpu(p).oper[1]^.ref^, RS_INVALID,topsize2tcgsize[taicpu(p).opsize]);
+ end;
+ end;
+ end;
+ end;
+ end;
+ A_DIV, A_IDIV, A_MUL:
+ begin
+ ReadOp(curprop, taicpu(p).oper[0]^);
+ readreg(curprop,RS_EAX);
+ if (taicpu(p).OpCode = A_IDIV) or
+ (taicpu(p).OpCode = A_DIV) then
+ begin
+ readreg(curprop,RS_EDX);
+ end;
+{$ifdef statedebug}
+ hp := tai_comment.Create(strpnew('destroying eax and edx'));
+ insertllitem(list,p,p.next,hp);
+{$endif statedebug}
+{ DestroyReg(curprop, RS_EAX, true);}
+ AddInstr2RegContents({$ifdef statedebug}list,{$endif}
+ taicpu(p), RS_EAX);
+ DestroyReg(curprop, RS_EDX, true);
+ LastFlagsChangeProp := curprop;
+ end;
+ A_IMUL:
+ begin
+ ReadOp(curprop,taicpu(p).oper[0]^);
+ if (taicpu(p).ops >= 2) then
+ ReadOp(curprop,taicpu(p).oper[1]^);
+ if (taicpu(p).ops <= 2) then
+ if (taicpu(p).ops=1) then
+ begin
+ readreg(curprop,RS_EAX);
+{$ifdef statedebug}
+ hp := tai_comment.Create(strpnew('destroying eax and edx'));
+ insertllitem(list,p,p.next,hp);
+{$endif statedebug}
+{ DestroyReg(curprop, RS_EAX, true); }
+ AddInstr2RegContents({$ifdef statedebug}list,{$endif}
+ taicpu(p), RS_EAX);
+ DestroyReg(curprop,RS_EDX, true)
+ end
+ else
+ AddInstr2OpContents(
+ {$ifdef statedebug}list,{$endif}
+ taicpu(p), taicpu(p).oper[1]^)
+ else
+ AddInstr2OpContents({$ifdef statedebug}list,{$endif}
+ taicpu(p), taicpu(p).oper[2]^);
+ LastFlagsChangeProp := curprop;
+ end;
+ A_LEA:
+ begin
+ readop(curprop,taicpu(p).oper[0]^);
+ if reginref(getsupreg(taicpu(p).oper[1]^.reg),taicpu(p).oper[0]^.ref^) then
+ AddInstr2RegContents({$ifdef statedebug}list,{$endif}
+ taicpu(p), getsupreg(taicpu(p).oper[1]^.reg))
+ else
+ begin
+{$ifdef statedebug}
+ hp := tai_comment.Create(strpnew('destroying & initing'+
+ std_regname(taicpu(p).oper[1]^.reg)));
+ insertllitem(list,p,p.next,hp);
+{$endif statedebug}
+ destroyreg(curprop,getsupreg(taicpu(p).oper[1]^.reg),true);
+ with curprop^.regs[getsupreg(taicpu(p).oper[1]^.reg)] Do
+ begin
+ typ := con_ref;
+ startmod := p;
+ nrOfMods := 1;
+ end
+ end;
+ end;
+ else
+ begin
+ Cnt := 1;
+ while (Cnt <= maxinschanges) and
+ (InstrProp.Ch[Cnt] <> Ch_None) Do
+ begin
+ case InstrProp.Ch[Cnt] Of
+ Ch_REAX..Ch_REDI:
+ begin
+ tmpsupreg:=tch2reg(InstrProp.Ch[Cnt]);
+ readreg(curprop,tmpsupreg);
+ end;
+ Ch_WEAX..Ch_RWEDI:
+ begin
+ if (InstrProp.Ch[Cnt] >= Ch_RWEAX) then
+ begin
+ tmpsupreg:=tch2reg(InstrProp.Ch[Cnt]);
+ readreg(curprop,tmpsupreg);
+ end;
+{$ifdef statedebug}
+ hp := tai_comment.Create(strpnew('destroying '+
+ std_regname(tch2reg(InstrProp.Ch[Cnt]))));
+ insertllitem(list,p,p.next,hp);
+{$endif statedebug}
+ tmpsupreg:=tch2reg(InstrProp.Ch[Cnt]);
+ DestroyReg(curprop,tmpsupreg, true);
+ end;
+ Ch_MEAX..Ch_MEDI:
+ begin
+ tmpsupreg:=tch2reg(InstrProp.Ch[Cnt]);
+ AddInstr2RegContents({$ifdef statedebug} list,{$endif}
+ taicpu(p),tmpsupreg);
+ end;
+ Ch_CDirFlag: curprop^.DirFlag := F_notSet;
+ Ch_SDirFlag: curprop^.DirFlag := F_Set;
+ Ch_Rop1: ReadOp(curprop, taicpu(p).oper[0]^);
+ Ch_Rop2: ReadOp(curprop, taicpu(p).oper[1]^);
+ Ch_ROp3: ReadOp(curprop, taicpu(p).oper[2]^);
+ Ch_Wop1..Ch_RWop1:
+ begin
+ if (InstrProp.Ch[Cnt] in [Ch_RWop1]) then
+ ReadOp(curprop, taicpu(p).oper[0]^);
+ DestroyOp(p, taicpu(p).oper[0]^);
+ end;
+ Ch_Mop1:
+ AddInstr2OpContents({$ifdef statedebug} list, {$endif}
+ taicpu(p), taicpu(p).oper[0]^);
+ Ch_Wop2..Ch_RWop2:
+ begin
+ if (InstrProp.Ch[Cnt] = Ch_RWop2) then
+ ReadOp(curprop, taicpu(p).oper[1]^);
+ DestroyOp(p, taicpu(p).oper[1]^);
+ end;
+ Ch_Mop2:
+ AddInstr2OpContents({$ifdef statedebug} list, {$endif}
+ taicpu(p), taicpu(p).oper[1]^);
+ Ch_WOp3..Ch_RWOp3:
+ begin
+ if (InstrProp.Ch[Cnt] = Ch_RWOp3) then
+ ReadOp(curprop, taicpu(p).oper[2]^);
+ DestroyOp(p, taicpu(p).oper[2]^);
+ end;
+ Ch_Mop3:
+ AddInstr2OpContents({$ifdef statedebug} list, {$endif}
+ taicpu(p), taicpu(p).oper[2]^);
+ Ch_WMemEDI:
+ begin
+ readreg(curprop, RS_EDI);
+ fillchar(tmpref, SizeOf(tmpref), 0);
+ tmpref.base := NR_EDI;
+ tmpref.index := NR_EDI;
+ DestroyRefs(p, tmpref,RS_INVALID,OS_32)
+ end;
+ Ch_RFlags:
+ if assigned(LastFlagsChangeProp) then
+ LastFlagsChangeProp^.FlagsUsed := true;
+ Ch_WFlags:
+ LastFlagsChangeProp := curprop;
+ Ch_RWFlags:
+ begin
+ if assigned(LastFlagsChangeProp) then
+ LastFlagsChangeProp^.FlagsUsed := true;
+ LastFlagsChangeProp := curprop;
+ end;
+ Ch_FPU:;
+ else
+ begin
+{$ifdef statedebug}
+ hp := tai_comment.Create(strpnew(
+ 'destroying all regs for prev instruction'));
+ insertllitem(list,p, p.next,hp);
+{$endif statedebug}
+ DestroyAllRegs(curprop,true,true);
+ LastFlagsChangeProp := curprop;
+ end;
+ end;
+ inc(Cnt);
+ end
+ end;
+ end;
+ end;
+ end
+ else
+ begin
+{$ifdef statedebug}
+ hp := tai_comment.Create(strpnew(
+ 'destroying all regs: unknown tai: '+tostr(ord(p.typ))));
+ insertllitem(list,p, p.next,hp);
+{$endif statedebug}
+ DestroyAllRegs(curprop,true,true);
+ end;
+ end;
+ inc(InstrCnt);
+ prev := p;
+ GetNextInstruction(p, p);
+ end;
+end;
+
+
+function tdfaobj.pass_generate_code: boolean;
+begin
+ if initdfapass2 then
+ begin
+ dodfapass2;
+ pass_generate_code := true
+ end
+ else
+ pass_generate_code := false;
+end;
+
+{$push}
+{$r-}
+function tdfaobj.getlabelwithsym(sym: tasmlabel): tai;
+begin
+ if (sym.labelnr >= lolab) and
+ (sym.labelnr <= hilab) then { range check, a jump can go past an assembler block! }
+ getlabelwithsym := labeltable^[sym.labelnr-lolab].taiobj
+ else
+ getlabelwithsym := nil;
+end;
+{$pop}
+
+
+procedure tdfaobj.clear;
+begin
+ if labdif <> 0 then
+ begin
+ freemem(labeltable);
+ labeltable := nil;
+ end;
+ if assigned(taipropblock) then
+ begin
+ freemem(taipropblock, nroftaiobjs*sizeof(ttaiprop));
+ taipropblock := nil;
+ end;
+end;
+
+
+end.
diff --git a/closures/compiler/i386/i386att.inc b/closures/compiler/i386/i386att.inc
new file mode 100644
index 0000000000..a591dad220
--- /dev/null
+++ b/closures/compiler/i386/i386att.inc
@@ -0,0 +1,688 @@
+{ don't edit, this file is generated from x86ins.dat }
+(
+'none',
+'aaa',
+'aad',
+'aam',
+'aas',
+'adc',
+'add',
+'and',
+'arpl',
+'bound',
+'bsf',
+'bsr',
+'bswap',
+'bt',
+'btc',
+'btr',
+'bts',
+'call',
+'cbtw',
+'cltd',
+'clc',
+'cld',
+'cli',
+'clts',
+'cmc',
+'cmp',
+'cmpsb',
+'cmpsl',
+'cmpsw',
+'cmpxchg',
+'cmpxchg486',
+'cmpxchg8b',
+'cpuid',
+'cwd',
+'cwtl',
+'daa',
+'das',
+'dec',
+'div',
+'emms',
+'enter',
+'f2xm1',
+'fabs',
+'fadd',
+'faddp',
+'fbld',
+'fbstp',
+'fchs',
+'fclex',
+'fcmovb',
+'fcmovbe',
+'fcmove',
+'fcmovnb',
+'fcmovnbe',
+'fcmovne',
+'fcmovnu',
+'fcmovu',
+'fcom',
+'fcomi',
+'fcomip',
+'fcomp',
+'fcompp',
+'fcos',
+'fdecstp',
+'fdisi',
+'fdiv',
+'fdivp',
+'fdivr',
+'fdivrp',
+'femms',
+'feni',
+'ffree',
+'fiadd',
+'ficom',
+'ficomp',
+'fidiv',
+'fidivr',
+'fild',
+'fimul',
+'fincstp',
+'finit',
+'fist',
+'fistp',
+'fisttp',
+'fisub',
+'fisubr',
+'fld',
+'fld1',
+'fldcw',
+'fldenv',
+'fldl2e',
+'fldl2t',
+'fldlg2',
+'fldln2',
+'fldpi',
+'fldz',
+'fmul',
+'fmulp',
+'fnclex',
+'fndisi',
+'fneni',
+'fninit',
+'fnop',
+'fnsave',
+'fnstcw',
+'fnstenv',
+'fnstsw',
+'fpatan',
+'fprem',
+'fprem1',
+'fptan',
+'frndint',
+'frstor',
+'fsave',
+'fscale',
+'fsetpm',
+'fsin',
+'fsincos',
+'fsqrt',
+'fst',
+'fstcw',
+'fstenv',
+'fstp',
+'fstsw',
+'fsub',
+'fsubp',
+'fsubr',
+'fsubrp',
+'ftst',
+'fucom',
+'fucomi',
+'fucomip',
+'fucomp',
+'fucompp',
+'fwait',
+'fxam',
+'fxch',
+'fxtract',
+'fyl2x',
+'fyl2xp1',
+'hlt',
+'ibts',
+'icebp',
+'idiv',
+'imul',
+'in',
+'inc',
+'insb',
+'insl',
+'insw',
+'int',
+'int01',
+'int1',
+'int03',
+'int3',
+'into',
+'invd',
+'invlpg',
+'iret',
+'iret',
+'iretw',
+'iretq',
+'jcxz',
+'jecxz',
+'jrcxz',
+'jmp',
+'lahf',
+'lar',
+'lcall',
+'lds',
+'lea',
+'leave',
+'les',
+'lfs',
+'lgdt',
+'lgs',
+'lidt',
+'ljmp',
+'lldt',
+'lmsw',
+'loadall',
+'loadall286',
+'lock',
+'lodsb',
+'lodsl',
+'lodsw',
+'loop',
+'loope',
+'loopne',
+'loopnz',
+'loopz',
+'lsl',
+'lss',
+'ltr',
+'monitor',
+'mov',
+'movd',
+'movq',
+'movsb',
+'movsl',
+'movsq',
+'movsw',
+'movs',
+'movz',
+'mul',
+'mwait',
+'neg',
+'nop',
+'not',
+'or',
+'out',
+'outsb',
+'outsl',
+'outsw',
+'packssdw',
+'packsswb',
+'packuswb',
+'paddb',
+'paddd',
+'paddsb',
+'paddsiw',
+'paddsw',
+'paddusb',
+'paddusw',
+'paddw',
+'pand',
+'pandn',
+'paveb',
+'pavgusb',
+'pcmpeqb',
+'pcmpeqd',
+'pcmpeqw',
+'pcmpgtb',
+'pcmpgtd',
+'pcmpgtw',
+'pdistib',
+'pf2id',
+'pfacc',
+'pfadd',
+'pfcmpeq',
+'pfcmpge',
+'pfcmpgt',
+'pfmax',
+'pfmin',
+'pfmul',
+'pfrcp',
+'pfrcpit1',
+'pfrcpit2',
+'pfrsqit1',
+'pfrsqrt',
+'pfsub',
+'pfsubr',
+'pi2fd',
+'pmachriw',
+'pmaddwd',
+'pmagw',
+'pmulhriw',
+'pmulhrwa',
+'pmulhrwc',
+'pmulhw',
+'pmullw',
+'pmvgezb',
+'pmvlzb',
+'pmvnzb',
+'pmvzb',
+'pop',
+'popa',
+'popal',
+'popaw',
+'popf',
+'popfl',
+'popfw',
+'popfq',
+'por',
+'prefetch',
+'prefetchw',
+'pslld',
+'pslldq',
+'psllq',
+'psllw',
+'psrad',
+'psraw',
+'psrld',
+'psrlq',
+'psrlw',
+'psubb',
+'psubd',
+'psubsb',
+'psubsiw',
+'psubsw',
+'psubusb',
+'psubusw',
+'psubw',
+'punpckhbw',
+'punpckhdq',
+'punpckhwd',
+'punpcklbw',
+'punpckldq',
+'punpcklwd',
+'push',
+'pusha',
+'pushal',
+'pushaw',
+'pushf',
+'pushfl',
+'pushfw',
+'pushfq',
+'pxor',
+'rcl',
+'rcr',
+'rdshr',
+'rdmsr',
+'rdpmc',
+'rdtsc',
+'rep',
+'repe',
+'repne',
+'repnz',
+'repz',
+'ret',
+'lret',
+'ret',
+'rol',
+'ror',
+'rsdc',
+'rsldt',
+'rsm',
+'sahf',
+'sal',
+'salc',
+'sar',
+'sbb',
+'scasb',
+'scasl',
+'scasq',
+'scasw',
+'cs',
+'ds',
+'es',
+'fs',
+'gs',
+'ss',
+'sgdt',
+'shl',
+'shld',
+'shr',
+'shrd',
+'sidt',
+'sldt',
+'smi',
+'smint',
+'smintold',
+'smsw',
+'stc',
+'std',
+'sti',
+'stosb',
+'stosl',
+'stosw',
+'str',
+'sub',
+'svdc',
+'svldt',
+'svts',
+'syscall',
+'sysenter',
+'sysexit',
+'sysret',
+'test',
+'ud1',
+'ud2',
+'umov',
+'verr',
+'verw',
+'wait',
+'wbinvd',
+'wrshr',
+'wrmsr',
+'xadd',
+'xbts',
+'xchg',
+'xlat',
+'xlatb',
+'xor',
+'xstore',
+'xcryptecb',
+'xcryptcbc',
+'xcryptcfb',
+'xcryptofb',
+'cmov',
+'j',
+'set',
+'addps',
+'addss',
+'andnps',
+'andps',
+'cmpeqps',
+'cmpeqss',
+'cmpleps',
+'cmpless',
+'cmpltps',
+'cmpltss',
+'cmpneqps',
+'cmpneqss',
+'cmpnleps',
+'cmpnless',
+'cmpnltps',
+'cmpnltss',
+'cmpordps',
+'cmpordss',
+'cmpunordps',
+'cmpunordss',
+'cmpps',
+'cmpss',
+'comiss',
+'cvtpi2ps',
+'cvtps2pi',
+'cvtsi2ss',
+'cvtss2si',
+'cvttps2pi',
+'cvttss2si',
+'divps',
+'divss',
+'ldmxcsr',
+'maxps',
+'maxss',
+'minps',
+'minss',
+'movaps',
+'movhps',
+'movlhps',
+'movlps',
+'movhlps',
+'movmskps',
+'movntps',
+'movss',
+'movups',
+'mulps',
+'mulss',
+'orps',
+'rcpps',
+'rcpss',
+'rsqrtps',
+'rsqrtss',
+'shufps',
+'sqrtps',
+'sqrtss',
+'stmxcsr',
+'subps',
+'subss',
+'ucomiss',
+'unpckhps',
+'unpcklps',
+'xorps',
+'fxrstor',
+'fxsave',
+'prefetchnta',
+'prefetcht0',
+'prefetcht1',
+'prefetcht2',
+'sfence',
+'maskmovq',
+'movntq',
+'pavgb',
+'pavgw',
+'pextrw',
+'pinsrw',
+'pmaxsw',
+'pmaxub',
+'pminsw',
+'pminub',
+'pmovmskb',
+'pmulhuw',
+'psadbw',
+'pshufw',
+'pfnacc',
+'pfpnacc',
+'pi2fw',
+'pf2iw',
+'pswapd',
+'ffreep',
+'maskmovdqu',
+'clflush',
+'movntdq',
+'movnti',
+'movntpd',
+'pause',
+'lfence',
+'mfence',
+'movdqa',
+'movdqu',
+'movdq2q',
+'movq2dq',
+'paddq',
+'pmuludq',
+'pshufd',
+'pshufhw',
+'pshuflw',
+'psrldq',
+'psubq',
+'punpckhqdq',
+'punpcklqdq',
+'addpd',
+'addsd',
+'andnpd',
+'andpd',
+'cmpeqpd',
+'cmpeqsd',
+'cmplepd',
+'cmplesd',
+'cmpltpd',
+'cmpltsd',
+'cmpneqpd',
+'cmpneqsd',
+'cmpnlepd',
+'cmpnlesd',
+'cmpnltpd',
+'cmpnltsd',
+'cmpordpd',
+'cmpordsd',
+'cmpunordpd',
+'cmpunordsd',
+'cmppd',
+'comisd',
+'cvtdq2pd',
+'cvtdq2ps',
+'cvtpd2dq',
+'cvtpd2pi',
+'cvtpd2ps',
+'cvtpi2pd',
+'cvtps2dq',
+'cvtps2pd',
+'cvtsd2si',
+'cvtsd2ss',
+'cvtsi2sd',
+'cvtss2sd',
+'cvttpd2pi',
+'cvttpd2dq',
+'cvttps2dq',
+'cvttsd2si',
+'divpd',
+'divsd',
+'maxpd',
+'maxsd',
+'minpd',
+'minsd',
+'movapd',
+'movhpd',
+'movlpd',
+'movmskpd',
+'movupd',
+'mulpd',
+'mulsd',
+'orpd',
+'shufpd',
+'sqrtpd',
+'sqrtsd',
+'subpd',
+'subsd',
+'ucomisd',
+'unpckhpd',
+'unpcklpd',
+'xorpd',
+'addsubpd',
+'addsubps',
+'haddpd',
+'haddps',
+'hsubpd',
+'hsubps',
+'lddqu',
+'movddup',
+'movshdup',
+'movsldup',
+'vmread',
+'vmwrite',
+'vmcall',
+'vmlaunch',
+'vmresume',
+'vmxoff',
+'vmxon',
+'vmclear',
+'vmptrld',
+'vmptrst',
+'vmrun',
+'vmmcall',
+'vmload',
+'vmsave',
+'stgi',
+'clgi',
+'skinit',
+'invlpga',
+'montmul',
+'xsha1',
+'xsha256',
+'dmint',
+'rdm',
+'movabs',
+'movslq',
+'cqto',
+'cmpxchg16b',
+'movntss',
+'movntsd',
+'insertq',
+'extrq',
+'lzcnt',
+'pabsb',
+'pabsw',
+'pabsd',
+'palignr',
+'phaddw',
+'phaddd',
+'phaddsw',
+'phsubw',
+'phsubd',
+'phsubsw',
+'pmaddubsw',
+'pmulhrsw',
+'pshufb',
+'psignb',
+'psignw',
+'psignd',
+'blendps',
+'blendpd',
+'blendvps',
+'blendvpd',
+'dpps',
+'dppd',
+'extractps',
+'insertps',
+'movntdqa',
+'mpsadbw',
+'packusdw',
+'pblendvb',
+'pblendw',
+'pcmpeqq',
+'pextrb',
+'pextrd',
+'pextrq',
+'phminposuw',
+'pinsrb',
+'pinsrd',
+'pinsrq',
+'pmaxsb',
+'pmaxsd',
+'pmaxud',
+'pmaxuw',
+'pminsb',
+'pminsd',
+'pminuw',
+'pminud',
+'pmovsxbw',
+'pmovsxbd',
+'pmovsxbq',
+'pmovsxwd',
+'pmovsxwq',
+'pmovsxdq',
+'pmovzxbw',
+'pmovzxbd',
+'pmovzxbq',
+'pmovzxwd',
+'pmovzxwq',
+'pmovzxdq',
+'pmuldq',
+'pmulld',
+'ptest',
+'roundps',
+'roundpd',
+'roundss',
+'roundsd',
+'crc32',
+'pcmpestri',
+'pcmpestrm',
+'pcmpistri',
+'pcmpistrm',
+'pcmpgtq',
+'popcnt',
+'aesenc',
+'aesenclast',
+'aesdec',
+'aesdeclast',
+'aesimc',
+'aeskeygenassist',
+'stosq',
+'lodsq',
+'cmpsq'
+);
diff --git a/closures/compiler/i386/i386atts.inc b/closures/compiler/i386/i386atts.inc
new file mode 100644
index 0000000000..31bc9cd421
--- /dev/null
+++ b/closures/compiler/i386/i386atts.inc
@@ -0,0 +1,688 @@
+{ don't edit, this file is generated from x86ins.dat }
+(
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufNONE,
+attsufNONE,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufFPUint,
+attsufFPUint,
+attsufFPUint,
+attsufFPUint,
+attsufFPUint,
+attsufFPUint,
+attsufFPUint,
+attsufNONE,
+attsufNONE,
+attsufFPUint,
+attsufFPUint,
+attsufFPUint,
+attsufFPUint,
+attsufFPUint,
+attsufFPU,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufFPU,
+attsufFPU,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufFPU,
+attsufINT,
+attsufNONE,
+attsufFPU,
+attsufINT,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufNONE,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufFPU,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINTdual,
+attsufINTdual,
+attsufINT,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE
+);
diff --git a/closures/compiler/i386/i386int.inc b/closures/compiler/i386/i386int.inc
new file mode 100644
index 0000000000..b6cc4caa78
--- /dev/null
+++ b/closures/compiler/i386/i386int.inc
@@ -0,0 +1,688 @@
+{ don't edit, this file is generated from x86ins.dat }
+(
+'none',
+'aaa',
+'aad',
+'aam',
+'aas',
+'adc',
+'add',
+'and',
+'arpl',
+'bound',
+'bsf',
+'bsr',
+'bswap',
+'bt',
+'btc',
+'btr',
+'bts',
+'call',
+'cbw',
+'cdq',
+'clc',
+'cld',
+'cli',
+'clts',
+'cmc',
+'cmp',
+'cmpsb',
+'cmpsd',
+'cmpsw',
+'cmpxchg',
+'cmpxchg486',
+'cmpxchg8b',
+'cpuid',
+'cwd',
+'cwde',
+'daa',
+'das',
+'dec',
+'div',
+'emms',
+'enter',
+'f2xm1',
+'fabs',
+'fadd',
+'faddp',
+'fbld',
+'fbstp',
+'fchs',
+'fclex',
+'fcmovb',
+'fcmovbe',
+'fcmove',
+'fcmovnb',
+'fcmovnbe',
+'fcmovne',
+'fcmovnu',
+'fcmovu',
+'fcom',
+'fcomi',
+'fcomip',
+'fcomp',
+'fcompp',
+'fcos',
+'fdecstp',
+'fdisi',
+'fdiv',
+'fdivp',
+'fdivr',
+'fdivrp',
+'femms',
+'feni',
+'ffree',
+'fiadd',
+'ficom',
+'ficomp',
+'fidiv',
+'fidivr',
+'fild',
+'fimul',
+'fincstp',
+'finit',
+'fist',
+'fistp',
+'fisttp',
+'fisub',
+'fisubr',
+'fld',
+'fld1',
+'fldcw',
+'fldenv',
+'fldl2e',
+'fldl2t',
+'fldlg2',
+'fldln2',
+'fldpi',
+'fldz',
+'fmul',
+'fmulp',
+'fnclex',
+'fndisi',
+'fneni',
+'fninit',
+'fnop',
+'fnsave',
+'fnstcw',
+'fnstenv',
+'fnstsw',
+'fpatan',
+'fprem',
+'fprem1',
+'fptan',
+'frndint',
+'frstor',
+'fsave',
+'fscale',
+'fsetpm',
+'fsin',
+'fsincos',
+'fsqrt',
+'fst',
+'fstcw',
+'fstenv',
+'fstp',
+'fstsw',
+'fsub',
+'fsubp',
+'fsubr',
+'fsubrp',
+'ftst',
+'fucom',
+'fucomi',
+'fucomip',
+'fucomp',
+'fucompp',
+'fwait',
+'fxam',
+'fxch',
+'fxtract',
+'fyl2x',
+'fyl2xp1',
+'hlt',
+'ibts',
+'icebp',
+'idiv',
+'imul',
+'in',
+'inc',
+'insb',
+'insd',
+'insw',
+'int',
+'int01',
+'int1',
+'int03',
+'int3',
+'into',
+'invd',
+'invlpg',
+'iret',
+'iretd',
+'iretw',
+'iretq',
+'jcxz',
+'jecxz',
+'jrcxz',
+'jmp',
+'lahf',
+'lar',
+'lcall',
+'lds',
+'lea',
+'leave',
+'les',
+'lfs',
+'lgdt',
+'lgs',
+'lidt',
+'ljmp',
+'lldt',
+'lmsw',
+'loadall',
+'loadall286',
+'lock',
+'lodsb',
+'lodsd',
+'lodsw',
+'loop',
+'loope',
+'loopne',
+'loopnz',
+'loopz',
+'lsl',
+'lss',
+'ltr',
+'monitor',
+'mov',
+'movd',
+'movq',
+'movsb',
+'movsd',
+'movsq',
+'movsw',
+'movsx',
+'movzx',
+'mul',
+'mwait',
+'neg',
+'nop',
+'not',
+'or',
+'out',
+'outsb',
+'outsd',
+'outsw',
+'packssdw',
+'packsswb',
+'packuswb',
+'paddb',
+'paddd',
+'paddsb',
+'paddsiw',
+'paddsw',
+'paddusb',
+'paddusw',
+'paddw',
+'pand',
+'pandn',
+'paveb',
+'pavgusb',
+'pcmpeqb',
+'pcmpeqd',
+'pcmpeqw',
+'pcmpgtb',
+'pcmpgtd',
+'pcmpgtw',
+'pdistib',
+'pf2id',
+'pfacc',
+'pfadd',
+'pfcmpeq',
+'pfcmpge',
+'pfcmpgt',
+'pfmax',
+'pfmin',
+'pfmul',
+'pfrcp',
+'pfrcpit1',
+'pfrcpit2',
+'pfrsqit1',
+'pfrsqrt',
+'pfsub',
+'pfsubr',
+'pi2fd',
+'pmachriw',
+'pmaddwd',
+'pmagw',
+'pmulhriw',
+'pmulhrwa',
+'pmulhrwc',
+'pmulhw',
+'pmullw',
+'pmvgezb',
+'pmvlzb',
+'pmvnzb',
+'pmvzb',
+'pop',
+'popa',
+'popad',
+'popaw',
+'popf',
+'popfd',
+'popfw',
+'popfq',
+'por',
+'prefetch',
+'prefetchw',
+'pslld',
+'pslldq',
+'psllq',
+'psllw',
+'psrad',
+'psraw',
+'psrld',
+'psrlq',
+'psrlw',
+'psubb',
+'psubd',
+'psubsb',
+'psubsiw',
+'psubsw',
+'psubusb',
+'psubusw',
+'psubw',
+'punpckhbw',
+'punpckhdq',
+'punpckhwd',
+'punpcklbw',
+'punpckldq',
+'punpcklwd',
+'push',
+'pusha',
+'pushad',
+'pushaw',
+'pushf',
+'pushfd',
+'pushfw',
+'pushfq',
+'pxor',
+'rcl',
+'rcr',
+'rdshr',
+'rdmsr',
+'rdpmc',
+'rdtsc',
+'rep',
+'repe',
+'repne',
+'repnz',
+'repz',
+'ret',
+'retf',
+'retn',
+'rol',
+'ror',
+'rsdc',
+'rsldt',
+'rsm',
+'sahf',
+'sal',
+'salc',
+'sar',
+'sbb',
+'scasb',
+'scasd',
+'scasq',
+'scasw',
+'segcs',
+'segds',
+'seges',
+'segfs',
+'seggs',
+'segss',
+'sgdt',
+'shl',
+'shld',
+'shr',
+'shrd',
+'sidt',
+'sldt',
+'smi',
+'smint',
+'smintold',
+'smsw',
+'stc',
+'std',
+'sti',
+'stosb',
+'stosd',
+'stosw',
+'str',
+'sub',
+'svdc',
+'svldt',
+'svts',
+'syscall',
+'sysenter',
+'sysexit',
+'sysret',
+'test',
+'ud1',
+'ud2',
+'umov',
+'verr',
+'verw',
+'wait',
+'wbinvd',
+'wrshr',
+'wrmsr',
+'xadd',
+'xbts',
+'xchg',
+'xlat',
+'xlatb',
+'xor',
+'xstore',
+'xcryptecb',
+'xcryptcbc',
+'xcryptcfb',
+'xcryptofb',
+'cmov',
+'j',
+'set',
+'addps',
+'addss',
+'andnps',
+'andps',
+'cmpeqps',
+'cmpeqss',
+'cmpleps',
+'cmpless',
+'cmpltps',
+'cmpltss',
+'cmpneqps',
+'cmpneqss',
+'cmpnleps',
+'cmpnless',
+'cmpnltps',
+'cmpnltss',
+'cmpordps',
+'cmpordss',
+'cmpunordps',
+'cmpunordss',
+'cmpps',
+'cmpss',
+'comiss',
+'cvtpi2ps',
+'cvtps2pi',
+'cvtsi2ss',
+'cvtss2si',
+'cvttps2pi',
+'cvttss2si',
+'divps',
+'divss',
+'ldmxcsr',
+'maxps',
+'maxss',
+'minps',
+'minss',
+'movaps',
+'movhps',
+'movlhps',
+'movlps',
+'movhlps',
+'movmskps',
+'movntps',
+'movss',
+'movups',
+'mulps',
+'mulss',
+'orps',
+'rcpps',
+'rcpss',
+'rsqrtps',
+'rsqrtss',
+'shufps',
+'sqrtps',
+'sqrtss',
+'stmxcsr',
+'subps',
+'subss',
+'ucomiss',
+'unpckhps',
+'unpcklps',
+'xorps',
+'fxrstor',
+'fxsave',
+'prefetchnta',
+'prefetcht0',
+'prefetcht1',
+'prefetcht2',
+'sfence',
+'maskmovq',
+'movntq',
+'pavgb',
+'pavgw',
+'pextrw',
+'pinsrw',
+'pmaxsw',
+'pmaxub',
+'pminsw',
+'pminub',
+'pmovmskb',
+'pmulhuw',
+'psadbw',
+'pshufw',
+'pfnacc',
+'pfpnacc',
+'pi2fw',
+'pf2iw',
+'pswapd',
+'ffreep',
+'maskmovdqu',
+'clflush',
+'movntdq',
+'movnti',
+'movntpd',
+'pause',
+'lfence',
+'mfence',
+'movdqa',
+'movdqu',
+'movdq2q',
+'movq2dq',
+'paddq',
+'pmuludq',
+'pshufd',
+'pshufhw',
+'pshuflw',
+'psrldq',
+'psubq',
+'punpckhqdq',
+'punpcklqdq',
+'addpd',
+'addsd',
+'andnpd',
+'andpd',
+'cmpeqpd',
+'cmpeqsd',
+'cmplepd',
+'cmplesd',
+'cmpltpd',
+'cmpltsd',
+'cmpneqpd',
+'cmpneqsd',
+'cmpnlepd',
+'cmpnlesd',
+'cmpnltpd',
+'cmpnltsd',
+'cmpordpd',
+'cmpordsd',
+'cmpunordpd',
+'cmpunordsd',
+'cmppd',
+'comisd',
+'cvtdq2pd',
+'cvtdq2ps',
+'cvtpd2dq',
+'cvtpd2pi',
+'cvtpd2ps',
+'cvtpi2pd',
+'cvtps2dq',
+'cvtps2pd',
+'cvtsd2si',
+'cvtsd2ss',
+'cvtsi2sd',
+'cvtss2sd',
+'cvttpd2pi',
+'cvttpd2dq',
+'cvttps2dq',
+'cvttsd2si',
+'divpd',
+'divsd',
+'maxpd',
+'maxsd',
+'minpd',
+'minsd',
+'movapd',
+'movhpd',
+'movlpd',
+'movmskpd',
+'movupd',
+'mulpd',
+'mulsd',
+'orpd',
+'shufpd',
+'sqrtpd',
+'sqrtsd',
+'subpd',
+'subsd',
+'ucomisd',
+'unpckhpd',
+'unpcklpd',
+'xorpd',
+'addsubpd',
+'addsubps',
+'haddpd',
+'haddps',
+'hsubpd',
+'hsubps',
+'lddqu',
+'movddup',
+'movshdup',
+'movsldup',
+'vmread',
+'vmwrite',
+'vmcall',
+'vmlaunch',
+'vmresume',
+'vmxoff',
+'vmxon',
+'vmclear',
+'vmptrld',
+'vmptrst',
+'vmrun',
+'vmmcall',
+'vmload',
+'vmsave',
+'stgi',
+'clgi',
+'skinit',
+'invlpga',
+'montmul',
+'xsha1',
+'xsha256',
+'dmint',
+'rdm',
+'movabs',
+'movsxd',
+'cqo',
+'cmpxchg16b',
+'movntss',
+'movntsd',
+'insertq',
+'extrq',
+'lzcnt',
+'pabsb',
+'pabsw',
+'pabsd',
+'palignr',
+'phaddw',
+'phaddd',
+'phaddsw',
+'phsubw',
+'phsubd',
+'phsubsw',
+'pmaddubsw',
+'pmulhrsw',
+'pshufb',
+'psignb',
+'psignw',
+'psignd',
+'blendps',
+'blendpd',
+'blendvps',
+'blendvpd',
+'dpps',
+'dppd',
+'extractps',
+'insertps',
+'movntdqa',
+'mpsadbw',
+'packusdw',
+'pblendvb',
+'pblendw',
+'pcmpeqq',
+'pextrb',
+'pextrd',
+'pextrq',
+'phminposuw',
+'pinsrb',
+'pinsrd',
+'pinsrq',
+'pmaxsb',
+'pmaxsd',
+'pmaxud',
+'pmaxuw',
+'pminsb',
+'pminsd',
+'pminuw',
+'pminud',
+'pmovsxbw',
+'pmovsxbd',
+'pmovsxbq',
+'pmovsxwd',
+'pmovsxwq',
+'pmovsxdq',
+'pmovzxbw',
+'pmovzxbd',
+'pmovzxbq',
+'pmovzxwd',
+'pmovzxwq',
+'pmovzxdq',
+'pmuldq',
+'pmulld',
+'ptest',
+'roundps',
+'roundpd',
+'roundss',
+'roundsd',
+'crc32',
+'pcmpestri',
+'pcmpestrm',
+'pcmpistri',
+'pcmpistrm',
+'pcmpgtq',
+'popcnt',
+'aesenc',
+'aesenclast',
+'aesdec',
+'aesdeclast',
+'aesimc',
+'aeskeygenassist',
+'stosq',
+'lodsq',
+'cmpsq'
+);
diff --git a/closures/compiler/i386/i386nop.inc b/closures/compiler/i386/i386nop.inc
new file mode 100644
index 0000000000..69f2343600
--- /dev/null
+++ b/closures/compiler/i386/i386nop.inc
@@ -0,0 +1,2 @@
+{ don't edit, this file is generated from x86ins.dat }
+1205;
diff --git a/closures/compiler/i386/i386op.inc b/closures/compiler/i386/i386op.inc
new file mode 100644
index 0000000000..4070734e54
--- /dev/null
+++ b/closures/compiler/i386/i386op.inc
@@ -0,0 +1,688 @@
+{ don't edit, this file is generated from x86ins.dat }
+(
+A_NONE,
+A_AAA,
+A_AAD,
+A_AAM,
+A_AAS,
+A_ADC,
+A_ADD,
+A_AND,
+A_ARPL,
+A_BOUND,
+A_BSF,
+A_BSR,
+A_BSWAP,
+A_BT,
+A_BTC,
+A_BTR,
+A_BTS,
+A_CALL,
+A_CBW,
+A_CDQ,
+A_CLC,
+A_CLD,
+A_CLI,
+A_CLTS,
+A_CMC,
+A_CMP,
+A_CMPSB,
+A_CMPSD,
+A_CMPSW,
+A_CMPXCHG,
+A_CMPXCHG486,
+A_CMPXCHG8B,
+A_CPUID,
+A_CWD,
+A_CWDE,
+A_DAA,
+A_DAS,
+A_DEC,
+A_DIV,
+A_EMMS,
+A_ENTER,
+A_F2XM1,
+A_FABS,
+A_FADD,
+A_FADDP,
+A_FBLD,
+A_FBSTP,
+A_FCHS,
+A_FCLEX,
+A_FCMOVB,
+A_FCMOVBE,
+A_FCMOVE,
+A_FCMOVNB,
+A_FCMOVNBE,
+A_FCMOVNE,
+A_FCMOVNU,
+A_FCMOVU,
+A_FCOM,
+A_FCOMI,
+A_FCOMIP,
+A_FCOMP,
+A_FCOMPP,
+A_FCOS,
+A_FDECSTP,
+A_FDISI,
+A_FDIV,
+A_FDIVP,
+A_FDIVR,
+A_FDIVRP,
+A_FEMMS,
+A_FENI,
+A_FFREE,
+A_FIADD,
+A_FICOM,
+A_FICOMP,
+A_FIDIV,
+A_FIDIVR,
+A_FILD,
+A_FIMUL,
+A_FINCSTP,
+A_FINIT,
+A_FIST,
+A_FISTP,
+A_FISTTP,
+A_FISUB,
+A_FISUBR,
+A_FLD,
+A_FLD1,
+A_FLDCW,
+A_FLDENV,
+A_FLDL2E,
+A_FLDL2T,
+A_FLDLG2,
+A_FLDLN2,
+A_FLDPI,
+A_FLDZ,
+A_FMUL,
+A_FMULP,
+A_FNCLEX,
+A_FNDISI,
+A_FNENI,
+A_FNINIT,
+A_FNOP,
+A_FNSAVE,
+A_FNSTCW,
+A_FNSTENV,
+A_FNSTSW,
+A_FPATAN,
+A_FPREM,
+A_FPREM1,
+A_FPTAN,
+A_FRNDINT,
+A_FRSTOR,
+A_FSAVE,
+A_FSCALE,
+A_FSETPM,
+A_FSIN,
+A_FSINCOS,
+A_FSQRT,
+A_FST,
+A_FSTCW,
+A_FSTENV,
+A_FSTP,
+A_FSTSW,
+A_FSUB,
+A_FSUBP,
+A_FSUBR,
+A_FSUBRP,
+A_FTST,
+A_FUCOM,
+A_FUCOMI,
+A_FUCOMIP,
+A_FUCOMP,
+A_FUCOMPP,
+A_FWAIT,
+A_FXAM,
+A_FXCH,
+A_FXTRACT,
+A_FYL2X,
+A_FYL2XP1,
+A_HLT,
+A_IBTS,
+A_ICEBP,
+A_IDIV,
+A_IMUL,
+A_IN,
+A_INC,
+A_INSB,
+A_INSD,
+A_INSW,
+A_INT,
+A_INT01,
+A_INT1,
+A_INT03,
+A_INT3,
+A_INTO,
+A_INVD,
+A_INVLPG,
+A_IRET,
+A_IRETD,
+A_IRETW,
+A_IRETQ,
+A_JCXZ,
+A_JECXZ,
+A_JRCXZ,
+A_JMP,
+A_LAHF,
+A_LAR,
+A_LCALL,
+A_LDS,
+A_LEA,
+A_LEAVE,
+A_LES,
+A_LFS,
+A_LGDT,
+A_LGS,
+A_LIDT,
+A_LJMP,
+A_LLDT,
+A_LMSW,
+A_LOADALL,
+A_LOADALL286,
+A_LOCK,
+A_LODSB,
+A_LODSD,
+A_LODSW,
+A_LOOP,
+A_LOOPE,
+A_LOOPNE,
+A_LOOPNZ,
+A_LOOPZ,
+A_LSL,
+A_LSS,
+A_LTR,
+A_MONITOR,
+A_MOV,
+A_MOVD,
+A_MOVQ,
+A_MOVSB,
+A_MOVSD,
+A_MOVSQ,
+A_MOVSW,
+A_MOVSX,
+A_MOVZX,
+A_MUL,
+A_MWAIT,
+A_NEG,
+A_NOP,
+A_NOT,
+A_OR,
+A_OUT,
+A_OUTSB,
+A_OUTSD,
+A_OUTSW,
+A_PACKSSDW,
+A_PACKSSWB,
+A_PACKUSWB,
+A_PADDB,
+A_PADDD,
+A_PADDSB,
+A_PADDSIW,
+A_PADDSW,
+A_PADDUSB,
+A_PADDUSW,
+A_PADDW,
+A_PAND,
+A_PANDN,
+A_PAVEB,
+A_PAVGUSB,
+A_PCMPEQB,
+A_PCMPEQD,
+A_PCMPEQW,
+A_PCMPGTB,
+A_PCMPGTD,
+A_PCMPGTW,
+A_PDISTIB,
+A_PF2ID,
+A_PFACC,
+A_PFADD,
+A_PFCMPEQ,
+A_PFCMPGE,
+A_PFCMPGT,
+A_PFMAX,
+A_PFMIN,
+A_PFMUL,
+A_PFRCP,
+A_PFRCPIT1,
+A_PFRCPIT2,
+A_PFRSQIT1,
+A_PFRSQRT,
+A_PFSUB,
+A_PFSUBR,
+A_PI2FD,
+A_PMACHRIW,
+A_PMADDWD,
+A_PMAGW,
+A_PMULHRIW,
+A_PMULHRWA,
+A_PMULHRWC,
+A_PMULHW,
+A_PMULLW,
+A_PMVGEZB,
+A_PMVLZB,
+A_PMVNZB,
+A_PMVZB,
+A_POP,
+A_POPA,
+A_POPAD,
+A_POPAW,
+A_POPF,
+A_POPFD,
+A_POPFW,
+A_POPFQ,
+A_POR,
+A_PREFETCH,
+A_PREFETCHW,
+A_PSLLD,
+A_PSLLDQ,
+A_PSLLQ,
+A_PSLLW,
+A_PSRAD,
+A_PSRAW,
+A_PSRLD,
+A_PSRLQ,
+A_PSRLW,
+A_PSUBB,
+A_PSUBD,
+A_PSUBSB,
+A_PSUBSIW,
+A_PSUBSW,
+A_PSUBUSB,
+A_PSUBUSW,
+A_PSUBW,
+A_PUNPCKHBW,
+A_PUNPCKHDQ,
+A_PUNPCKHWD,
+A_PUNPCKLBW,
+A_PUNPCKLDQ,
+A_PUNPCKLWD,
+A_PUSH,
+A_PUSHA,
+A_PUSHAD,
+A_PUSHAW,
+A_PUSHF,
+A_PUSHFD,
+A_PUSHFW,
+A_PUSHFQ,
+A_PXOR,
+A_RCL,
+A_RCR,
+A_RDSHR,
+A_RDMSR,
+A_RDPMC,
+A_RDTSC,
+A_REP,
+A_REPE,
+A_REPNE,
+A_REPNZ,
+A_REPZ,
+A_RET,
+A_RETF,
+A_RETN,
+A_ROL,
+A_ROR,
+A_RSDC,
+A_RSLDT,
+A_RSM,
+A_SAHF,
+A_SAL,
+A_SALC,
+A_SAR,
+A_SBB,
+A_SCASB,
+A_SCASD,
+A_SCASQ,
+A_SCASW,
+A_SEGCS,
+A_SEGDS,
+A_SEGES,
+A_SEGFS,
+A_SEGGS,
+A_SEGSS,
+A_SGDT,
+A_SHL,
+A_SHLD,
+A_SHR,
+A_SHRD,
+A_SIDT,
+A_SLDT,
+A_SMI,
+A_SMINT,
+A_SMINTOLD,
+A_SMSW,
+A_STC,
+A_STD,
+A_STI,
+A_STOSB,
+A_STOSD,
+A_STOSW,
+A_STR,
+A_SUB,
+A_SVDC,
+A_SVLDT,
+A_SVTS,
+A_SYSCALL,
+A_SYSENTER,
+A_SYSEXIT,
+A_SYSRET,
+A_TEST,
+A_UD1,
+A_UD2,
+A_UMOV,
+A_VERR,
+A_VERW,
+A_WAIT,
+A_WBINVD,
+A_WRSHR,
+A_WRMSR,
+A_XADD,
+A_XBTS,
+A_XCHG,
+A_XLAT,
+A_XLATB,
+A_XOR,
+A_XSTORE,
+A_XCRYPTECB,
+A_XCRYPTCBC,
+A_XCRYPTCFB,
+A_XCRYPTOFB,
+A_CMOVcc,
+A_Jcc,
+A_SETcc,
+A_ADDPS,
+A_ADDSS,
+A_ANDNPS,
+A_ANDPS,
+A_CMPEQPS,
+A_CMPEQSS,
+A_CMPLEPS,
+A_CMPLESS,
+A_CMPLTPS,
+A_CMPLTSS,
+A_CMPNEQPS,
+A_CMPNEQSS,
+A_CMPNLEPS,
+A_CMPNLESS,
+A_CMPNLTPS,
+A_CMPNLTSS,
+A_CMPORDPS,
+A_CMPORDSS,
+A_CMPUNORDPS,
+A_CMPUNORDSS,
+A_CMPPS,
+A_CMPSS,
+A_COMISS,
+A_CVTPI2PS,
+A_CVTPS2PI,
+A_CVTSI2SS,
+A_CVTSS2SI,
+A_CVTTPS2PI,
+A_CVTTSS2SI,
+A_DIVPS,
+A_DIVSS,
+A_LDMXCSR,
+A_MAXPS,
+A_MAXSS,
+A_MINPS,
+A_MINSS,
+A_MOVAPS,
+A_MOVHPS,
+A_MOVLHPS,
+A_MOVLPS,
+A_MOVHLPS,
+A_MOVMSKPS,
+A_MOVNTPS,
+A_MOVSS,
+A_MOVUPS,
+A_MULPS,
+A_MULSS,
+A_ORPS,
+A_RCPPS,
+A_RCPSS,
+A_RSQRTPS,
+A_RSQRTSS,
+A_SHUFPS,
+A_SQRTPS,
+A_SQRTSS,
+A_STMXCSR,
+A_SUBPS,
+A_SUBSS,
+A_UCOMISS,
+A_UNPCKHPS,
+A_UNPCKLPS,
+A_XORPS,
+A_FXRSTOR,
+A_FXSAVE,
+A_PREFETCHNTA,
+A_PREFETCHT0,
+A_PREFETCHT1,
+A_PREFETCHT2,
+A_SFENCE,
+A_MASKMOVQ,
+A_MOVNTQ,
+A_PAVGB,
+A_PAVGW,
+A_PEXTRW,
+A_PINSRW,
+A_PMAXSW,
+A_PMAXUB,
+A_PMINSW,
+A_PMINUB,
+A_PMOVMSKB,
+A_PMULHUW,
+A_PSADBW,
+A_PSHUFW,
+A_PFNACC,
+A_PFPNACC,
+A_PI2FW,
+A_PF2IW,
+A_PSWAPD,
+A_FFREEP,
+A_MASKMOVDQU,
+A_CLFLUSH,
+A_MOVNTDQ,
+A_MOVNTI,
+A_MOVNTPD,
+A_PAUSE,
+A_LFENCE,
+A_MFENCE,
+A_MOVDQA,
+A_MOVDQU,
+A_MOVDQ2Q,
+A_MOVQ2DQ,
+A_PADDQ,
+A_PMULUDQ,
+A_PSHUFD,
+A_PSHUFHW,
+A_PSHUFLW,
+A_PSRLDQ,
+A_PSUBQ,
+A_PUNPCKHQDQ,
+A_PUNPCKLQDQ,
+A_ADDPD,
+A_ADDSD,
+A_ANDNPD,
+A_ANDPD,
+A_CMPEQPD,
+A_CMPEQSD,
+A_CMPLEPD,
+A_CMPLESD,
+A_CMPLTPD,
+A_CMPLTSD,
+A_CMPNEQPD,
+A_CMPNEQSD,
+A_CMPNLEPD,
+A_CMPNLESD,
+A_CMPNLTPD,
+A_CMPNLTSD,
+A_CMPORDPD,
+A_CMPORDSD,
+A_CMPUNORDPD,
+A_CMPUNORDSD,
+A_CMPPD,
+A_COMISD,
+A_CVTDQ2PD,
+A_CVTDQ2PS,
+A_CVTPD2DQ,
+A_CVTPD2PI,
+A_CVTPD2PS,
+A_CVTPI2PD,
+A_CVTPS2DQ,
+A_CVTPS2PD,
+A_CVTSD2SI,
+A_CVTSD2SS,
+A_CVTSI2SD,
+A_CVTSS2SD,
+A_CVTTPD2PI,
+A_CVTTPD2DQ,
+A_CVTTPS2DQ,
+A_CVTTSD2SI,
+A_DIVPD,
+A_DIVSD,
+A_MAXPD,
+A_MAXSD,
+A_MINPD,
+A_MINSD,
+A_MOVAPD,
+A_MOVHPD,
+A_MOVLPD,
+A_MOVMSKPD,
+A_MOVUPD,
+A_MULPD,
+A_MULSD,
+A_ORPD,
+A_SHUFPD,
+A_SQRTPD,
+A_SQRTSD,
+A_SUBPD,
+A_SUBSD,
+A_UCOMISD,
+A_UNPCKHPD,
+A_UNPCKLPD,
+A_XORPD,
+A_ADDSUBPD,
+A_ADDSUBPS,
+A_HADDPD,
+A_HADDPS,
+A_HSUBPD,
+A_HSUBPS,
+A_LDDQU,
+A_MOVDDUP,
+A_MOVSHDUP,
+A_MOVSLDUP,
+A_VMREAD,
+A_VMWRITE,
+A_VMCALL,
+A_VMLAUNCH,
+A_VMRESUME,
+A_VMXOFF,
+A_VMXON,
+A_VMCLEAR,
+A_VMPTRLD,
+A_VMPTRST,
+A_VMRUN,
+A_VMMCALL,
+A_VMLOAD,
+A_VMSAVE,
+A_STGI,
+A_CLGI,
+A_SKINIT,
+A_INVLPGA,
+A_MONTMUL,
+A_XSHA1,
+A_XSHA256,
+A_DMINT,
+A_RDM,
+A_MOVABS,
+A_MOVSXD,
+A_CQO,
+A_CMPXCHG16B,
+A_MOVNTSS,
+A_MOVNTSD,
+A_INSERTQ,
+A_EXTRQ,
+A_LZCNT,
+A_PABSB,
+A_PABSW,
+A_PABSD,
+A_PALIGNR,
+A_PHADDW,
+A_PHADDD,
+A_PHADDSW,
+A_PHSUBW,
+A_PHSUBD,
+A_PHSUBSW,
+A_PMADDUBSW,
+A_PMULHRSW,
+A_PSHUFB,
+A_PSIGNB,
+A_PSIGNW,
+A_PSIGND,
+A_BLENDPS,
+A_BLENDPD,
+A_BLENDVPS,
+A_BLENDVPD,
+A_DPPS,
+A_DPPD,
+A_EXTRACTPS,
+A_INSERTPS,
+A_MOVNTDQA,
+A_MPSADBW,
+A_PACKUSDW,
+A_PBLENDVB,
+A_PBLENDW,
+A_PCMPEQQ,
+A_PEXTRB,
+A_PEXTRD,
+A_PEXTRQ,
+A_PHMINPOSUW,
+A_PINSRB,
+A_PINSRD,
+A_PINSRQ,
+A_PMAXSB,
+A_PMAXSD,
+A_PMAXUD,
+A_PMAXUW,
+A_PMINSB,
+A_PMINSD,
+A_PMINUW,
+A_PMINUD,
+A_PMOVSXBW,
+A_PMOVSXBD,
+A_PMOVSXBQ,
+A_PMOVSXWD,
+A_PMOVSXWQ,
+A_PMOVSXDQ,
+A_PMOVZXBW,
+A_PMOVZXBD,
+A_PMOVZXBQ,
+A_PMOVZXWD,
+A_PMOVZXWQ,
+A_PMOVZXDQ,
+A_PMULDQ,
+A_PMULLD,
+A_PTEST,
+A_ROUNDPS,
+A_ROUNDPD,
+A_ROUNDSS,
+A_ROUNDSD,
+A_CRC32,
+A_PCMPESTRI,
+A_PCMPESTRM,
+A_PCMPISTRI,
+A_PCMPISTRM,
+A_PCMPGTQ,
+A_POPCNT,
+A_AESENC,
+A_AESENCLAST,
+A_AESDEC,
+A_AESDECLAST,
+A_AESIMC,
+A_AESKEYGENASSIST,
+A_STOSQ,
+A_LODSQ,
+A_CMPSQ
+);
diff --git a/closures/compiler/i386/i386prop.inc b/closures/compiler/i386/i386prop.inc
new file mode 100644
index 0000000000..4a8f2f7fa4
--- /dev/null
+++ b/closures/compiler/i386/i386prop.inc
@@ -0,0 +1,688 @@
+{ don't edit, this file is generated from x86ins.dat }
+(
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_MEAX, Ch_WFlags, Ch_None)),
+(Ch: (Ch_MEAX, Ch_WFlags, Ch_None)),
+(Ch: (Ch_MEAX, Ch_WFlags, Ch_None)),
+(Ch: (Ch_MEAX, Ch_WFlags, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_RWFlags)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_WFlags)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_WFlags)),
+(Ch: (Ch_WFlags, Ch_None, Ch_None)),
+(Ch: (Ch_Rop1, Ch_None, Ch_None)),
+(Ch: (Ch_Wop2, Ch_WFlags, Ch_Rop1)),
+(Ch: (Ch_Wop2, Ch_WFlags, Ch_Rop1)),
+(Ch: (Ch_MOp1, Ch_None, Ch_None)),
+(Ch: (Ch_WFlags, Ch_Rop1, Ch_Rop2)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_WFlags)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_WFlags)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_WFlags)),
+(Ch: (Ch_ROp1, Ch_All, Ch_None)),
+(Ch: (Ch_MEAX, Ch_None, Ch_None)),
+(Ch: (Ch_MEAX, Ch_WEDX, Ch_None)),
+(Ch: (Ch_WFlags, Ch_None, Ch_None)),
+(Ch: (Ch_CDirFlag, Ch_None, Ch_None)),
+(Ch: (Ch_WFlags, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_WFlags, Ch_None, Ch_None)),
+(Ch: (Ch_ROp1, Ch_ROp2, Ch_WFlags)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_none)),
+(Ch: (Ch_MEAX, Ch_WEDX, Ch_None)),
+(Ch: (Ch_MEAX, Ch_None, Ch_None)),
+(Ch: (Ch_MEAX, Ch_None, Ch_None)),
+(Ch: (Ch_MEAX, Ch_None, Ch_None)),
+(Ch: (Ch_Mop1, Ch_WFlags, Ch_None)),
+(Ch: (Ch_RWEAX, Ch_WEDX, Ch_WFlags)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_RWESP, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_ROp1, Ch_None)),
+(Ch: (Ch_FPU, Ch_ROp1, Ch_None)),
+(Ch: (Ch_Rop1, Ch_FPU, Ch_None)),
+(Ch: (Ch_Wop1, Ch_FPU, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_RFLAGS, Ch_None)),
+(Ch: (Ch_FPU, Ch_RFLAGS, Ch_None)),
+(Ch: (Ch_FPU, Ch_RFLAGS, Ch_None)),
+(Ch: (Ch_FPU, Ch_RFLAGS, Ch_None)),
+(Ch: (Ch_FPU, Ch_RFLAGS, Ch_None)),
+(Ch: (Ch_FPU, Ch_RFLAGS, Ch_None)),
+(Ch: (Ch_FPU, Ch_RFLAGS, Ch_None)),
+(Ch: (Ch_FPU, Ch_RFLAGS, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_WFLAGS, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_WFLAGS, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_ROp1, Ch_None)),
+(Ch: (Ch_FPU, Ch_ROp1, Ch_None)),
+(Ch: (Ch_FPU, Ch_ROp1, Ch_None)),
+(Ch: (Ch_FPU, Ch_ROp1, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_ROp1, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_ROp1, Ch_None)),
+(Ch: (Ch_FPU, Ch_ROp1, Ch_None)),
+(Ch: (Ch_FPU, Ch_ROp1, Ch_None)),
+(Ch: (Ch_FPU, Ch_ROp1, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_Wop1, Ch_None, Ch_None)),
+(Ch: (Ch_Wop1, Ch_None, Ch_None)),
+(Ch: (Ch_Wop1, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_ROp1, Ch_None)),
+(Ch: (Ch_FPU, Ch_ROp1, Ch_None)),
+(Ch: (Ch_Rop1, Ch_FPU, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_ROp1, Ch_FPU, Ch_None)),
+(Ch: (Ch_ROp1, Ch_FPU, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_Wop1, Ch_None, Ch_None)),
+(Ch: (Ch_Wop1, Ch_None, Ch_None)),
+(Ch: (Ch_Wop1, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_Wop1, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_Wop1, Ch_None, Ch_None)),
+(Ch: (Ch_Wop1, Ch_None, Ch_None)),
+(Ch: (Ch_Wop1, Ch_None, Ch_None)),
+(Ch: (Ch_Wop1, Ch_FPU, Ch_None)),
+(Ch: (Ch_Wop1, Ch_None, Ch_None)),
+(Ch: (Ch_ROp1, Ch_FPU, Ch_None)),
+(Ch: (Ch_ROp1, Ch_FPU, Ch_None)),
+(Ch: (Ch_ROp1, Ch_FPU, Ch_None)),
+(Ch: (Ch_ROp1, Ch_FPU, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_WFLAGS, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_WFLAGS, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_RWEAX, Ch_WEDX, Ch_WFlags)),
+(Ch: (Ch_RWEAX, Ch_WEDX, Ch_WFlags)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop1, Ch_WFlags, Ch_None)),
+(Ch: (Ch_WMemEDI, Ch_RWEDI, Ch_REDX)),
+(Ch: (Ch_WMemEDI, Ch_RWEDI, Ch_REDX)),
+(Ch: (Ch_WMemEDI, Ch_RWEDI, Ch_REDX)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_RECX, Ch_None, Ch_None)),
+(Ch: (Ch_RECX, Ch_None, Ch_None)),
+(Ch: (Ch_RECX, Ch_None, Ch_None)),
+(Ch: (Ch_ROp1, Ch_None, Ch_None)),
+(Ch: (Ch_WEAX, Ch_RFlags, Ch_None)),
+(Ch: (Ch_Wop2, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_RWESP, Ch_WEBP, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_ROp1, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_WEAX, Ch_RWESI, Ch_None)),
+(Ch: (Ch_WEAX, Ch_RWESI, Ch_None)),
+(Ch: (Ch_WEAX, Ch_RWESI, Ch_None)),
+(Ch: (Ch_RWECX, Ch_None, Ch_None)),
+(Ch: (Ch_RWECX, Ch_RFlags, Ch_None)),
+(Ch: (Ch_RWECX, Ch_RFlags, Ch_None)),
+(Ch: (Ch_RWECX, Ch_RFlags, Ch_None)),
+(Ch: (Ch_RWECX, Ch_RFlags, Ch_None)),
+(Ch: (Ch_Wop2, Ch_WFlags, Ch_None)),
+(Ch: (Ch_Wop2, Ch_ROP1, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Rop1, Ch_Wop2, Ch_None)),
+(Ch: (Ch_Rop1, Ch_Wop2, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_RWEAX, Ch_WEDX, Ch_WFlags)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_Mop1, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_Mop1, Ch_WFlags, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_WFlags)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Wop1, Ch_RWESP, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_RWESP, Ch_WFlags, Ch_None)),
+(Ch: (Ch_RWESP, Ch_WFlags, Ch_None)),
+(Ch: (Ch_RWESP, Ch_WFLAGS, Ch_None)),
+(Ch: (Ch_RWESP, Ch_WFlags, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Rop1, Ch_RWESP, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_RWESP, Ch_RFlags, Ch_None)),
+(Ch: (Ch_RWESP, Ch_RFlags, Ch_None)),
+(Ch: (Ch_RWESP, Ch_RFLAGS, Ch_None)),
+(Ch: (Ch_RWESP, Ch_RFlags, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_RWFlags)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_RWFlags)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_WEAX, Ch_WEDX, Ch_None)),
+(Ch: (Ch_WEAX, Ch_WEDX, Ch_None)),
+(Ch: (Ch_WEAX, Ch_WEDX, Ch_None)),
+(Ch: (Ch_RWECX, Ch_RWFlags, Ch_None)),
+(Ch: (Ch_RWECX, Ch_RWFlags, Ch_None)),
+(Ch: (Ch_RWECX, Ch_RWFlags, Ch_None)),
+(Ch: (Ch_RWECX, Ch_RWFLAGS, Ch_None)),
+(Ch: (Ch_RWECX, Ch_RWFLAGS, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_RWFlags)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_RWFlags)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_WFlags, Ch_REAX, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_RWFlags)),
+(Ch: (Ch_WEAX, Ch_RFLAGS, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_WFlags)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_RWFlags)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_Wop1, Ch_None, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_WFlags)),
+(Ch: (Ch_MOp3, Ch_RWFlags, Ch_Rop2)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_WFlags)),
+(Ch: (Ch_MOp3, Ch_RWFlags, Ch_Rop2)),
+(Ch: (Ch_Wop1, Ch_None, Ch_None)),
+(Ch: (Ch_Wop1, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Wop1, Ch_None, Ch_None)),
+(Ch: (Ch_WFlags, Ch_None, Ch_None)),
+(Ch: (Ch_SDirFlag, Ch_None, Ch_None)),
+(Ch: (Ch_WFlags, Ch_None, Ch_None)),
+(Ch: (Ch_REAX, Ch_WMemEDI, Ch_RWEDI)),
+(Ch: (Ch_REAX, Ch_WMemEDI, Ch_RWEDI)),
+(Ch: (Ch_REAX, Ch_WMemEDI, Ch_RWEDI)),
+(Ch: (Ch_Wop1, Ch_None, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_WFlags)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_WFlags, Ch_Rop1, Ch_Rop2)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_WFlags, Ch_None, Ch_None)),
+(Ch: (Ch_WFlags, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_RWop1, Ch_RWop2, Ch_None)),
+(Ch: (Ch_WEAX, Ch_REBX, Ch_None)),
+(Ch: (Ch_WEAX, Ch_REBX, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_WFlags)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_ROp1, Ch_WOp2, Ch_RFLAGS)),
+(Ch: (Ch_RFLAGS, Ch_None, Ch_None)),
+(Ch: (Ch_RFLAGS, Ch_WOp1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_WFlags)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_ROp1, Ch_WOp2, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_WFlags)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_WFlags)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_ROp1, Ch_WOp2, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_WFlags)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_MRAX, Ch_WRDX, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Mop1, Ch_Rop2, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_RRAX, Ch_WMemEDI, Ch_RWRDI)),
+(Ch: (Ch_WRAX, Ch_RWRSI, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None))
+);
diff --git a/closures/compiler/i386/i386tab.inc b/closures/compiler/i386/i386tab.inc
new file mode 100644
index 0000000000..f3df187bdc
--- /dev/null
+++ b/closures/compiler/i386/i386tab.inc
@@ -0,0 +1,8438 @@
+{ don't edit, this file is generated from x86ins.dat }
+(
+ (
+ opcode : A_NONE;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #0;
+ flags : if_none
+ ),
+ (
+ opcode : A_AAA;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#55;
+ flags : if_8086 or if_nox86_64
+ ),
+ (
+ opcode : A_AAD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#213#10;
+ flags : if_8086 or if_nox86_64
+ ),
+ (
+ opcode : A_AAD;
+ ops : 1;
+ optypes : (ot_immediate,ot_none,ot_none,ot_none);
+ code : #1#213#20;
+ flags : if_8086 or if_sb or if_nox86_64
+ ),
+ (
+ opcode : A_AAM;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#212#10;
+ flags : if_8086 or if_nox86_64
+ ),
+ (
+ opcode : A_AAM;
+ ops : 1;
+ optypes : (ot_immediate,ot_none,ot_none,ot_none);
+ code : #1#212#20;
+ flags : if_8086 or if_sb or if_nox86_64
+ ),
+ (
+ opcode : A_AAS;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#63;
+ flags : if_8086 or if_nox86_64
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_rm_gpr,ot_reg16 or ot_bits32 or ot_bits64,ot_none,ot_none);
+ code : #208#1#17#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_reg16 or ot_bits32 or ot_bits64,ot_rm_gpr,ot_none,ot_none);
+ code : #208#1#19#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_reg8,ot_none,ot_none);
+ code : #1#16#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_reg8,ot_rm_gpr or ot_bits8,ot_none,ot_none);
+ code : #1#18#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_immediate or ot_bits8 or ot_signed,ot_none,ot_none);
+ code : #208#1#131#130#13;
+ flags : if_8086
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_reg_eax,ot_immediate,ot_none,ot_none);
+ code : #213#1#21#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits32,ot_immediate,ot_none,ot_none);
+ code : #213#1#129#130#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_reg_ax,ot_immediate,ot_none,ot_none);
+ code : #212#1#21#25;
+ flags : if_8086 or if_sw
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16,ot_immediate,ot_none,ot_none);
+ code : #212#1#129#130#25;
+ flags : if_8086 or if_sw
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_reg_al,ot_immediate,ot_none,ot_none);
+ code : #1#20#17;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_immediate,ot_none,ot_none);
+ code : #1#128#130#17;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_rm_gpr,ot_reg16 or ot_bits32 or ot_bits64,ot_none,ot_none);
+ code : #208#1#1#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_reg16 or ot_bits32 or ot_bits64,ot_rm_gpr,ot_none,ot_none);
+ code : #208#1#3#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_reg8,ot_none,ot_none);
+ code : #1#0#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_reg8,ot_rm_gpr or ot_bits8,ot_none,ot_none);
+ code : #1#2#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_immediate or ot_bits8 or ot_signed,ot_none,ot_none);
+ code : #208#1#131#128#13;
+ flags : if_8086
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_reg_eax,ot_immediate,ot_none,ot_none);
+ code : #208#1#5#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits32,ot_immediate,ot_none,ot_none);
+ code : #213#1#129#128#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_reg_ax,ot_immediate,ot_none,ot_none);
+ code : #212#1#5#25;
+ flags : if_8086 or if_sw
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16,ot_immediate,ot_none,ot_none);
+ code : #212#1#129#128#25;
+ flags : if_8086 or if_sw
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_reg_al,ot_immediate,ot_none,ot_none);
+ code : #1#4#17;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_immediate,ot_none,ot_none);
+ code : #1#128#128#17;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_rm_gpr,ot_reg16 or ot_bits32 or ot_bits64,ot_none,ot_none);
+ code : #208#1#33#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_reg16 or ot_bits32 or ot_bits64,ot_rm_gpr,ot_none,ot_none);
+ code : #208#1#35#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_reg8,ot_none,ot_none);
+ code : #1#32#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_reg8,ot_rm_gpr or ot_bits8,ot_none,ot_none);
+ code : #1#34#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_immediate or ot_bits8 or ot_signed,ot_none,ot_none);
+ code : #208#1#131#132#13;
+ flags : if_8086
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_reg_eax,ot_immediate,ot_none,ot_none);
+ code : #213#1#37#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits32,ot_immediate,ot_none,ot_none);
+ code : #213#1#129#132#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_reg_ax,ot_immediate,ot_none,ot_none);
+ code : #212#1#37#25;
+ flags : if_8086 or if_sw
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16,ot_immediate,ot_none,ot_none);
+ code : #212#1#129#132#25;
+ flags : if_8086 or if_sw
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_reg_al,ot_immediate,ot_none,ot_none);
+ code : #1#36#17;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_immediate,ot_none,ot_none);
+ code : #1#128#132#17;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_ARPL;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none,ot_none);
+ code : #1#99#65;
+ flags : if_286 or if_prot or if_nox86_64
+ ),
+ (
+ opcode : A_ARPL;
+ ops : 2;
+ optypes : (ot_memory,ot_reg16,ot_none,ot_none);
+ code : #1#99#65;
+ flags : if_286 or if_prot or if_sm or if_nox86_64
+ ),
+ (
+ opcode : A_BOUND;
+ ops : 2;
+ optypes : (ot_reg16 or ot_bits32,ot_memory,ot_none,ot_none);
+ code : #208#1#98#72;
+ flags : if_186 or if_nox86_64
+ ),
+ (
+ opcode : A_BSF;
+ ops : 2;
+ optypes : (ot_reg16 or ot_bits32 or ot_bits64,ot_rm_gpr,ot_none,ot_none);
+ code : #208#2#15#188#72;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_BSR;
+ ops : 2;
+ optypes : (ot_reg16 or ot_bits32 or ot_bits64,ot_rm_gpr,ot_none,ot_none);
+ code : #208#2#15#189#72;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_BSWAP;
+ ops : 1;
+ optypes : (ot_reg32 or ot_bits64,ot_none,ot_none,ot_none);
+ code : #208#1#15#8#200;
+ flags : if_486
+ ),
+ (
+ opcode : A_BT;
+ ops : 2;
+ optypes : (ot_rm_gpr,ot_reg16 or ot_bits32 or ot_bits64,ot_none,ot_none);
+ code : #208#2#15#163#65;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_BT;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_immediate,ot_none,ot_none);
+ code : #208#2#15#186#132#21;
+ flags : if_386 or if_sb
+ ),
+ (
+ opcode : A_BTC;
+ ops : 2;
+ optypes : (ot_rm_gpr,ot_reg16 or ot_bits32 or ot_bits64,ot_none,ot_none);
+ code : #208#2#15#187#65;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_BTC;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_immediate,ot_none,ot_none);
+ code : #208#2#15#186#135#21;
+ flags : if_386 or if_sb
+ ),
+ (
+ opcode : A_BTR;
+ ops : 2;
+ optypes : (ot_rm_gpr,ot_reg16 or ot_bits32 or ot_bits64,ot_none,ot_none);
+ code : #208#2#15#179#65;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_BTR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_immediate,ot_none,ot_none);
+ code : #208#2#15#186#134#21;
+ flags : if_386 or if_sb
+ ),
+ (
+ opcode : A_BTS;
+ ops : 2;
+ optypes : (ot_rm_gpr,ot_reg16 or ot_bits32 or ot_bits64,ot_none,ot_none);
+ code : #208#2#15#171#65;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_BTS;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_immediate,ot_none,ot_none);
+ code : #208#2#15#186#133#21;
+ flags : if_386 or if_sb
+ ),
+ (
+ opcode : A_CALL;
+ ops : 1;
+ optypes : (ot_rm_gpr or ot_bits32,ot_none,ot_none,ot_none);
+ code : #213#1#255#130;
+ flags : if_386 or if_nox86_64
+ ),
+ (
+ opcode : A_CALL;
+ ops : 1;
+ optypes : (ot_rm_gpr or ot_bits16,ot_none,ot_none,ot_none);
+ code : #212#1#255#130;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CALL;
+ ops : 1;
+ optypes : (ot_immediate,ot_none,ot_none,ot_none);
+ code : #208#1#232#52;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CALL;
+ ops : 1;
+ optypes : (ot_immediate or ot_near,ot_none,ot_none,ot_none);
+ code : #208#1#232#52;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CALL;
+ ops : 1;
+ optypes : (ot_immediate or ot_far,ot_none,ot_none,ot_none);
+ code : #208#1#154#28#31;
+ flags : if_8086 or if_nox86_64
+ ),
+ (
+ opcode : A_CALL;
+ ops : 1;
+ optypes : (ot_memory or ot_near,ot_none,ot_none,ot_none);
+ code : #208#1#255#130;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CALL;
+ ops : 1;
+ optypes : (ot_memory or ot_far,ot_none,ot_none,ot_none);
+ code : #208#1#255#131;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CALL;
+ ops : 2;
+ optypes : (ot_immediate,ot_immediate,ot_none,ot_none);
+ code : #215#1#154#29#24;
+ flags : if_8086 or if_nox86_64
+ ),
+ (
+ opcode : A_CALL;
+ ops : 2;
+ optypes : (ot_immediate or ot_bits16,ot_immediate,ot_none,ot_none);
+ code : #212#1#154#25#24;
+ flags : if_8086 or if_nox86_64
+ ),
+ (
+ opcode : A_CALL;
+ ops : 2;
+ optypes : (ot_immediate,ot_immediate or ot_bits16,ot_none,ot_none);
+ code : #212#1#154#25#24;
+ flags : if_8086 or if_nox86_64
+ ),
+ (
+ opcode : A_CALL;
+ ops : 2;
+ optypes : (ot_immediate or ot_bits32,ot_immediate,ot_none,ot_none);
+ code : #213#1#154#33#24;
+ flags : if_386 or if_nox86_64
+ ),
+ (
+ opcode : A_CALL;
+ ops : 2;
+ optypes : (ot_immediate,ot_immediate or ot_bits32,ot_none,ot_none);
+ code : #213#1#154#33#24;
+ flags : if_386 or if_nox86_64
+ ),
+ (
+ opcode : A_CBW;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #212#1#152;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CDQ;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #213#1#153;
+ flags : if_386
+ ),
+ (
+ opcode : A_CLC;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#248;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CLD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#252;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CLI;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#250;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CLTS;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#15#6;
+ flags : if_286 or if_priv
+ ),
+ (
+ opcode : A_CMC;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#245;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_rm_gpr,ot_reg16 or ot_bits32 or ot_bits64,ot_none,ot_none);
+ code : #208#1#57#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_reg16 or ot_bits32 or ot_bits64,ot_rm_gpr,ot_none,ot_none);
+ code : #208#1#59#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_reg8,ot_none,ot_none);
+ code : #1#56#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_reg8,ot_rm_gpr or ot_bits8,ot_none,ot_none);
+ code : #1#58#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_immediate or ot_bits8 or ot_signed,ot_none,ot_none);
+ code : #208#1#131#135#13;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_reg_eax,ot_immediate,ot_none,ot_none);
+ code : #213#1#61#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits32,ot_immediate,ot_none,ot_none);
+ code : #213#1#129#135#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_reg_ax,ot_immediate,ot_none,ot_none);
+ code : #212#1#61#25;
+ flags : if_8086 or if_sw
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16,ot_immediate,ot_none,ot_none);
+ code : #212#1#129#135#25;
+ flags : if_8086 or if_sw
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_reg_al,ot_immediate,ot_none,ot_none);
+ code : #1#60#17;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_immediate,ot_none,ot_none);
+ code : #1#128#135#17;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits32,ot_none,ot_none);
+ code : #213#1#129#135#33;
+ flags : if_386 or if_sd
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits16,ot_none,ot_none);
+ code : #212#1#129#135#25;
+ flags : if_8086 or if_sw
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits8,ot_none,ot_none);
+ code : #1#128#135#17;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_CMPSB;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #218#1#166;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CMPSD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #218#213#1#167;
+ flags : if_386
+ ),
+ (
+ opcode : A_CMPSD;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_immediate,ot_none);
+ code : #220#2#15#194#72#22;
+ flags : if_willamette or if_sse2 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_CMPSW;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #218#212#1#167;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CMPXCHG;
+ ops : 2;
+ optypes : (ot_rm_gpr,ot_reg16 or ot_bits32 or ot_bits64,ot_none,ot_none);
+ code : #208#2#15#177#65;
+ flags : if_pent or if_sm
+ ),
+ (
+ opcode : A_CMPXCHG;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_reg8,ot_none,ot_none);
+ code : #2#15#176#65;
+ flags : if_pent
+ ),
+ (
+ opcode : A_CMPXCHG486;
+ ops : 2;
+ optypes : (ot_rm_gpr,ot_reg16 or ot_bits32 or ot_bits64,ot_none,ot_none);
+ code : #208#2#15#167#65;
+ flags : if_486 or if_sm
+ ),
+ (
+ opcode : A_CMPXCHG486;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_reg8,ot_none,ot_none);
+ code : #2#15#166#65;
+ flags : if_486 or if_undoc
+ ),
+ (
+ opcode : A_CMPXCHG8B;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #2#15#199#129;
+ flags : if_pent
+ ),
+ (
+ opcode : A_CPUID;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#15#162;
+ flags : if_pent
+ ),
+ (
+ opcode : A_CWD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #212#1#153;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CWDE;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #213#1#152;
+ flags : if_386
+ ),
+ (
+ opcode : A_DAA;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#39;
+ flags : if_8086 or if_nox86_64
+ ),
+ (
+ opcode : A_DAS;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#47;
+ flags : if_8086 or if_nox86_64
+ ),
+ (
+ opcode : A_DEC;
+ ops : 1;
+ optypes : (ot_reg16 or ot_bits32,ot_none,ot_none,ot_none);
+ code : #208#8#72;
+ flags : if_8086 or if_nox86_64
+ ),
+ (
+ opcode : A_DEC;
+ ops : 1;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_none,ot_none,ot_none);
+ code : #208#1#255#129;
+ flags : if_8086
+ ),
+ (
+ opcode : A_DEC;
+ ops : 1;
+ optypes : (ot_rm_gpr or ot_bits8,ot_none,ot_none,ot_none);
+ code : #1#254#129;
+ flags : if_8086
+ ),
+ (
+ opcode : A_DIV;
+ ops : 1;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_none,ot_none,ot_none);
+ code : #208#1#247#134;
+ flags : if_8086
+ ),
+ (
+ opcode : A_DIV;
+ ops : 1;
+ optypes : (ot_rm_gpr or ot_bits8,ot_none,ot_none,ot_none);
+ code : #1#246#134;
+ flags : if_8086
+ ),
+ (
+ opcode : A_EMMS;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#15#119;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_ENTER;
+ ops : 2;
+ optypes : (ot_immediate,ot_immediate,ot_none,ot_none);
+ code : #1#200#24#21;
+ flags : if_186
+ ),
+ (
+ opcode : A_F2XM1;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#217#240;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FABS;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#217#225;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FADD;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+ code : #1#216#128;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FADD;
+ ops : 1;
+ optypes : (ot_memory or ot_bits64,ot_none,ot_none,ot_none);
+ code : #1#220#128;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FADD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#222#193;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FADD;
+ ops : 1;
+ optypes : (ot_fpureg or ot_to,ot_none,ot_none,ot_none);
+ code : #1#220#8#192;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FADD;
+ ops : 2;
+ optypes : (ot_fpureg,ot_fpu0,ot_none,ot_none);
+ code : #1#220#8#192;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FADD;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#216#8#192;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FADD;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none,ot_none);
+ code : #1#216#9#192;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FADDP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#222#193;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FADDP;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#222#8#192;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FADDP;
+ ops : 2;
+ optypes : (ot_fpureg,ot_fpu0,ot_none,ot_none);
+ code : #1#222#8#192;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FBLD;
+ ops : 1;
+ optypes : (ot_memory or ot_bits80,ot_none,ot_none,ot_none);
+ code : #1#223#132;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FBLD;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #1#223#132;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FBSTP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits80,ot_none,ot_none,ot_none);
+ code : #1#223#134;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FBSTP;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #1#223#134;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FCHS;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#217#224;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FCLEX;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #3#155#219#226;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVB;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#218#193;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVB;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#218#8#192;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVB;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none,ot_none);
+ code : #1#218#9#192;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVBE;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#218#209;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVBE;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#218#8#208;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVBE;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none,ot_none);
+ code : #1#218#9#208;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVE;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#218#201;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVE;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#218#8#200;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVE;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none,ot_none);
+ code : #1#218#9#200;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVNB;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#219#193;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVNB;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#219#8#192;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVNB;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none,ot_none);
+ code : #1#219#9#192;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVNBE;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#219#209;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVNBE;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#219#8#208;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVNBE;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none,ot_none);
+ code : #1#219#9#208;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVNE;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#219#201;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVNE;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#219#8#200;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVNE;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none,ot_none);
+ code : #1#219#9#200;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVNU;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#219#217;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVNU;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#219#8#216;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVNU;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none,ot_none);
+ code : #1#219#9#216;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVU;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#218#217;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVU;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#218#8#216;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVU;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none,ot_none);
+ code : #1#218#9#216;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCOM;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+ code : #1#216#130;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FCOM;
+ ops : 1;
+ optypes : (ot_memory or ot_bits64,ot_none,ot_none,ot_none);
+ code : #1#220#130;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FCOM;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#216#209;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FCOM;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#216#8#208;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FCOM;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none,ot_none);
+ code : #1#216#9#208;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FCOMI;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#219#241;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCOMI;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#219#8#240;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCOMI;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none,ot_none);
+ code : #1#219#9#240;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCOMIP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#223#241;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCOMIP;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#223#8#240;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCOMIP;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none,ot_none);
+ code : #1#223#9#240;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCOMP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+ code : #1#216#131;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FCOMP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits64,ot_none,ot_none,ot_none);
+ code : #1#220#131;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FCOMP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#216#217;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FCOMP;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#216#8#216;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FCOMP;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none,ot_none);
+ code : #1#216#9#216;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FCOMPP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#222#217;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FCOS;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#217#255;
+ flags : if_386 or if_fpu
+ ),
+ (
+ opcode : A_FDECSTP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#217#246;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDISI;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #3#155#219#225;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIV;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+ code : #1#216#134;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIV;
+ ops : 1;
+ optypes : (ot_memory or ot_bits64,ot_none,ot_none,ot_none);
+ code : #1#220#134;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIV;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#220#241;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIV;
+ ops : 1;
+ optypes : (ot_fpureg or ot_to,ot_none,ot_none,ot_none);
+ code : #1#220#8#240;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIV;
+ ops : 2;
+ optypes : (ot_fpureg,ot_fpu0,ot_none,ot_none);
+ code : #1#220#8#240;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIV;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#216#8#240;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIV;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none,ot_none);
+ code : #1#216#9#240;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIVP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#222#241;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIVP;
+ ops : 2;
+ optypes : (ot_fpureg,ot_fpu0,ot_none,ot_none);
+ code : #1#222#8#240;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIVP;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#222#8#240;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIVR;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+ code : #1#216#135;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIVR;
+ ops : 1;
+ optypes : (ot_memory or ot_bits64,ot_none,ot_none,ot_none);
+ code : #1#220#135;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIVR;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#220#249;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIVR;
+ ops : 1;
+ optypes : (ot_fpureg or ot_to,ot_none,ot_none,ot_none);
+ code : #1#220#8#248;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIVR;
+ ops : 2;
+ optypes : (ot_fpureg,ot_fpu0,ot_none,ot_none);
+ code : #1#220#8#248;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIVR;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#216#8#248;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIVR;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none,ot_none);
+ code : #1#216#9#248;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIVRP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#222#249;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIVRP;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#222#8#248;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIVRP;
+ ops : 2;
+ optypes : (ot_fpureg,ot_fpu0,ot_none,ot_none);
+ code : #1#222#8#248;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FEMMS;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#15#14;
+ flags : if_pent or if_3dnow
+ ),
+ (
+ opcode : A_FENI;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #3#155#219#224;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FFREE;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#221#8#192;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FIADD;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none,ot_none);
+ code : #1#222#128;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FIADD;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+ code : #1#218#128;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FICOM;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none,ot_none);
+ code : #1#222#130;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FICOM;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+ code : #1#218#130;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FICOMP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none,ot_none);
+ code : #1#222#131;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FICOMP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+ code : #1#218#131;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FIDIV;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none,ot_none);
+ code : #1#222#134;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FIDIV;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+ code : #1#218#134;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FIDIVR;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none,ot_none);
+ code : #1#222#135;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FIDIVR;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+ code : #1#218#135;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FILD;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+ code : #1#219#128;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FILD;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none,ot_none);
+ code : #1#223#128;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FILD;
+ ops : 1;
+ optypes : (ot_memory or ot_bits64,ot_none,ot_none,ot_none);
+ code : #1#223#133;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FIMUL;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none,ot_none);
+ code : #1#222#129;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FIMUL;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+ code : #1#218#129;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FINCSTP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#217#247;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FINIT;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #3#155#219#227;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FIST;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+ code : #1#219#130;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FIST;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none,ot_none);
+ code : #212#1#223#130;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FISTP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+ code : #1#219#131;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FISTP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none,ot_none);
+ code : #212#1#223#131;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FISTP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits64,ot_none,ot_none,ot_none);
+ code : #1#223#135;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FISTTP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+ code : #1#219#129;
+ flags : if_prescott or if_fpu
+ ),
+ (
+ opcode : A_FISTTP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none,ot_none);
+ code : #1#223#129;
+ flags : if_prescott or if_fpu
+ ),
+ (
+ opcode : A_FISTTP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits64,ot_none,ot_none,ot_none);
+ code : #1#221#129;
+ flags : if_prescott or if_fpu
+ ),
+ (
+ opcode : A_FISUB;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none,ot_none);
+ code : #1#222#132;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FISUB;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+ code : #1#218#132;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FISUBR;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none,ot_none);
+ code : #1#222#133;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FISUBR;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+ code : #1#218#133;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FLD;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+ code : #1#217#128;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FLD;
+ ops : 1;
+ optypes : (ot_memory or ot_bits64,ot_none,ot_none,ot_none);
+ code : #1#221#128;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FLD;
+ ops : 1;
+ optypes : (ot_memory or ot_bits80,ot_none,ot_none,ot_none);
+ code : #1#219#133;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FLD;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#217#8#192;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FLD1;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#217#232;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FLDCW;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #1#217#133;
+ flags : if_8086 or if_fpu or if_sw
+ ),
+ (
+ opcode : A_FLDENV;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #1#217#132;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FLDL2E;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#217#234;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FLDL2T;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#217#233;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FLDLG2;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#217#236;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FLDLN2;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#217#237;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FLDPI;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#217#235;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FLDZ;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#217#238;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FMUL;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+ code : #1#216#129;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FMUL;
+ ops : 1;
+ optypes : (ot_memory or ot_bits64,ot_none,ot_none,ot_none);
+ code : #1#220#129;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FMUL;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#220#201;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FMUL;
+ ops : 1;
+ optypes : (ot_fpureg or ot_to,ot_none,ot_none,ot_none);
+ code : #1#220#8#200;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FMUL;
+ ops : 2;
+ optypes : (ot_fpureg,ot_fpu0,ot_none,ot_none);
+ code : #1#220#8#200;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FMUL;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#216#8#200;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FMUL;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none,ot_none);
+ code : #1#216#9#200;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FMULP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#222#201;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FMULP;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#222#8#200;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FMULP;
+ ops : 2;
+ optypes : (ot_fpureg,ot_fpu0,ot_none,ot_none);
+ code : #1#222#8#200;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FNCLEX;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#219#226;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FNDISI;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#219#225;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FNENI;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#219#224;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FNINIT;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#219#227;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FNOP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#217#208;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FNSAVE;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #1#221#134;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FNSTCW;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #1#217#135;
+ flags : if_8086 or if_fpu or if_sw
+ ),
+ (
+ opcode : A_FNSTENV;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #1#217#134;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FNSTSW;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #1#221#135;
+ flags : if_8086 or if_fpu or if_sw
+ ),
+ (
+ opcode : A_FNSTSW;
+ ops : 1;
+ optypes : (ot_reg_ax,ot_none,ot_none,ot_none);
+ code : #2#223#224;
+ flags : if_286 or if_fpu
+ ),
+ (
+ opcode : A_FPATAN;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#217#243;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FPREM;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#217#248;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FPREM1;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#217#245;
+ flags : if_386 or if_fpu
+ ),
+ (
+ opcode : A_FPTAN;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#217#242;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FRNDINT;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#217#252;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FRSTOR;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #1#221#132;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSAVE;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #2#155#221#134;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSCALE;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#217#253;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSETPM;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#219#228;
+ flags : if_286 or if_fpu
+ ),
+ (
+ opcode : A_FSIN;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#217#254;
+ flags : if_386 or if_fpu
+ ),
+ (
+ opcode : A_FSINCOS;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#217#251;
+ flags : if_386 or if_fpu
+ ),
+ (
+ opcode : A_FSQRT;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#217#250;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FST;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+ code : #1#217#130;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FST;
+ ops : 1;
+ optypes : (ot_memory or ot_bits64,ot_none,ot_none,ot_none);
+ code : #1#221#130;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FST;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#221#8#208;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSTCW;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #2#155#217#135;
+ flags : if_8086 or if_fpu or if_sw
+ ),
+ (
+ opcode : A_FSTENV;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #2#155#217#134;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSTP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+ code : #1#217#131;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSTP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits64,ot_none,ot_none,ot_none);
+ code : #1#221#131;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSTP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits80,ot_none,ot_none,ot_none);
+ code : #1#219#135;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSTP;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#221#8#216;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSTSW;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #2#155#221#135;
+ flags : if_8086 or if_fpu or if_sw
+ ),
+ (
+ opcode : A_FSTSW;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #3#155#223#224;
+ flags : if_286 or if_fpu
+ ),
+ (
+ opcode : A_FSTSW;
+ ops : 1;
+ optypes : (ot_reg_ax,ot_none,ot_none,ot_none);
+ code : #3#155#223#224;
+ flags : if_286 or if_fpu
+ ),
+ (
+ opcode : A_FSUB;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+ code : #1#216#132;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUB;
+ ops : 1;
+ optypes : (ot_memory or ot_bits64,ot_none,ot_none,ot_none);
+ code : #1#220#132;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUB;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#220#225;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUB;
+ ops : 1;
+ optypes : (ot_fpureg or ot_to,ot_none,ot_none,ot_none);
+ code : #1#220#8#224;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUB;
+ ops : 2;
+ optypes : (ot_fpureg,ot_fpu0,ot_none,ot_none);
+ code : #1#220#8#224;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUB;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#216#8#224;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUB;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none,ot_none);
+ code : #1#216#9#224;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUBP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#222#225;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUBP;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#222#8#224;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUBP;
+ ops : 2;
+ optypes : (ot_fpureg,ot_fpu0,ot_none,ot_none);
+ code : #1#222#8#224;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUBR;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+ code : #1#216#133;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUBR;
+ ops : 1;
+ optypes : (ot_memory or ot_bits64,ot_none,ot_none,ot_none);
+ code : #1#220#133;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUBR;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#220#233;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUBR;
+ ops : 1;
+ optypes : (ot_fpureg or ot_to,ot_none,ot_none,ot_none);
+ code : #1#220#8#232;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUBR;
+ ops : 2;
+ optypes : (ot_fpureg,ot_fpu0,ot_none,ot_none);
+ code : #1#220#8#232;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUBR;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#216#8#232;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUBR;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none,ot_none);
+ code : #1#216#9#232;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUBRP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#222#233;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUBRP;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#222#8#232;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUBRP;
+ ops : 2;
+ optypes : (ot_fpureg,ot_fpu0,ot_none,ot_none);
+ code : #1#222#8#232;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FTST;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#217#228;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FUCOM;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#221#225;
+ flags : if_386 or if_fpu
+ ),
+ (
+ opcode : A_FUCOM;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#221#8#224;
+ flags : if_386 or if_fpu
+ ),
+ (
+ opcode : A_FUCOM;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none,ot_none);
+ code : #1#221#9#224;
+ flags : if_386 or if_fpu
+ ),
+ (
+ opcode : A_FUCOMI;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#219#233;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FUCOMI;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#219#8#232;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FUCOMI;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none,ot_none);
+ code : #1#219#9#232;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FUCOMIP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#223#233;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FUCOMIP;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#223#8#232;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FUCOMIP;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none,ot_none);
+ code : #1#223#9#232;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FUCOMP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#221#233;
+ flags : if_386 or if_fpu
+ ),
+ (
+ opcode : A_FUCOMP;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#221#8#232;
+ flags : if_386 or if_fpu
+ ),
+ (
+ opcode : A_FUCOMP;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none,ot_none);
+ code : #1#221#9#232;
+ flags : if_386 or if_fpu
+ ),
+ (
+ opcode : A_FUCOMPP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#218#233;
+ flags : if_386 or if_fpu
+ ),
+ (
+ opcode : A_FWAIT;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#155;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FXAM;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#217#229;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FXCH;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#217#201;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FXCH;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#217#8#200;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FXCH;
+ ops : 2;
+ optypes : (ot_fpureg,ot_fpu0,ot_none,ot_none);
+ code : #1#217#8#200;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FXCH;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none,ot_none);
+ code : #1#217#9#200;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FXTRACT;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#217#244;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FYL2X;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#217#241;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FYL2XP1;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#217#249;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_HLT;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#244;
+ flags : if_8086 or if_priv
+ ),
+ (
+ opcode : A_IBTS;
+ ops : 2;
+ optypes : (ot_rm_gpr,ot_reg16 or ot_bits32 or ot_bits64,ot_none,ot_none);
+ code : #208#2#15#167#65;
+ flags : if_386 or if_sm or if_undoc
+ ),
+ (
+ opcode : A_ICEBP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#241;
+ flags : if_386
+ ),
+ (
+ opcode : A_IDIV;
+ ops : 1;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_none,ot_none,ot_none);
+ code : #208#1#247#135;
+ flags : if_8086
+ ),
+ (
+ opcode : A_IDIV;
+ ops : 1;
+ optypes : (ot_rm_gpr or ot_bits8,ot_none,ot_none,ot_none);
+ code : #1#246#135;
+ flags : if_8086
+ ),
+ (
+ opcode : A_IMUL;
+ ops : 2;
+ optypes : (ot_reg16 or ot_bits32 or ot_bits64,ot_rm_gpr,ot_none,ot_none);
+ code : #208#2#15#175#72;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_IMUL;
+ ops : 1;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_none,ot_none,ot_none);
+ code : #208#1#247#133;
+ flags : if_8086
+ ),
+ (
+ opcode : A_IMUL;
+ ops : 3;
+ optypes : (ot_reg32 or ot_bits64,ot_rm_gpr,ot_immediate or ot_bits8 or ot_signed,ot_none);
+ code : #208#1#107#72#14;
+ flags : if_286 or if_sm
+ ),
+ (
+ opcode : A_IMUL;
+ ops : 3;
+ optypes : (ot_reg32 or ot_bits64,ot_rm_gpr,ot_immediate,ot_none);
+ code : #208#1#105#72#34;
+ flags : if_286 or if_sm or if_sd or if_ar2
+ ),
+ (
+ opcode : A_IMUL;
+ ops : 2;
+ optypes : (ot_reg32 or ot_bits64,ot_immediate or ot_bits8 or ot_signed,ot_none,ot_none);
+ code : #208#1#107#64#13;
+ flags : if_286
+ ),
+ (
+ opcode : A_IMUL;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediate,ot_none,ot_none);
+ code : #213#1#105#64#33;
+ flags : if_286 or if_sd
+ ),
+ (
+ opcode : A_IMUL;
+ ops : 3;
+ optypes : (ot_reg16,ot_rm_gpr,ot_immediate or ot_bits8 or ot_signed,ot_none);
+ code : #212#1#107#72#14;
+ flags : if_286 or if_sm
+ ),
+ (
+ opcode : A_IMUL;
+ ops : 3;
+ optypes : (ot_reg16,ot_rm_gpr,ot_immediate,ot_none);
+ code : #212#1#105#72#26;
+ flags : if_286 or if_sm or if_sw or if_ar2
+ ),
+ (
+ opcode : A_IMUL;
+ ops : 2;
+ optypes : (ot_reg16,ot_immediate or ot_bits8 or ot_signed,ot_none,ot_none);
+ code : #212#1#107#64#13;
+ flags : if_286
+ ),
+ (
+ opcode : A_IMUL;
+ ops : 2;
+ optypes : (ot_reg16,ot_immediate,ot_none,ot_none);
+ code : #212#1#105#64#25;
+ flags : if_286 or if_sw
+ ),
+ (
+ opcode : A_IMUL;
+ ops : 1;
+ optypes : (ot_rm_gpr or ot_bits8,ot_none,ot_none,ot_none);
+ code : #1#246#133;
+ flags : if_8086
+ ),
+ (
+ opcode : A_IN;
+ ops : 2;
+ optypes : (ot_reg_al,ot_immediate,ot_none,ot_none);
+ code : #1#228#21;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_IN;
+ ops : 2;
+ optypes : (ot_reg_ax or ot_bits32,ot_immediate,ot_none,ot_none);
+ code : #208#1#229#21;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_IN;
+ ops : 2;
+ optypes : (ot_reg_al,ot_reg_dx,ot_none,ot_none);
+ code : #1#236;
+ flags : if_8086
+ ),
+ (
+ opcode : A_IN;
+ ops : 2;
+ optypes : (ot_reg_ax or ot_bits32,ot_reg_dx,ot_none,ot_none);
+ code : #208#1#237;
+ flags : if_8086
+ ),
+ (
+ opcode : A_INC;
+ ops : 1;
+ optypes : (ot_reg16 or ot_bits32,ot_none,ot_none,ot_none);
+ code : #208#8#64;
+ flags : if_8086 or if_nox86_64
+ ),
+ (
+ opcode : A_INC;
+ ops : 1;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_none,ot_none,ot_none);
+ code : #208#1#255#128;
+ flags : if_8086
+ ),
+ (
+ opcode : A_INC;
+ ops : 1;
+ optypes : (ot_rm_gpr or ot_bits8,ot_none,ot_none,ot_none);
+ code : #1#254#128;
+ flags : if_8086
+ ),
+ (
+ opcode : A_INSB;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#108;
+ flags : if_186
+ ),
+ (
+ opcode : A_INSD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #213#1#109;
+ flags : if_386
+ ),
+ (
+ opcode : A_INSW;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #212#1#109;
+ flags : if_186
+ ),
+ (
+ opcode : A_INT;
+ ops : 1;
+ optypes : (ot_immediate,ot_none,ot_none,ot_none);
+ code : #1#205#20;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_INT01;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#241;
+ flags : if_386
+ ),
+ (
+ opcode : A_INT1;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#241;
+ flags : if_386
+ ),
+ (
+ opcode : A_INT03;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#204;
+ flags : if_8086
+ ),
+ (
+ opcode : A_INT3;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#204;
+ flags : if_8086
+ ),
+ (
+ opcode : A_INTO;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#206;
+ flags : if_8086 or if_nox86_64
+ ),
+ (
+ opcode : A_INVD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#15#8;
+ flags : if_486 or if_priv
+ ),
+ (
+ opcode : A_INVLPG;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #2#15#1#135;
+ flags : if_486 or if_priv
+ ),
+ (
+ opcode : A_IRET;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #215#1#207;
+ flags : if_8086
+ ),
+ (
+ opcode : A_IRETD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #213#1#207;
+ flags : if_386
+ ),
+ (
+ opcode : A_IRETW;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #212#1#207;
+ flags : if_8086
+ ),
+ (
+ opcode : A_JCXZ;
+ ops : 1;
+ optypes : (ot_immediate,ot_none,ot_none,ot_none);
+ code : #200#1#227#40;
+ flags : if_8086 or if_nox86_64
+ ),
+ (
+ opcode : A_JECXZ;
+ ops : 1;
+ optypes : (ot_immediate,ot_none,ot_none,ot_none);
+ code : #201#1#227#40;
+ flags : if_386
+ ),
+ (
+ opcode : A_JMP;
+ ops : 1;
+ optypes : (ot_immediate or ot_bits8,ot_none,ot_none,ot_none);
+ code : #1#235#40;
+ flags : if_8086 or if_pass2
+ ),
+ (
+ opcode : A_JMP;
+ ops : 1;
+ optypes : (ot_immediate or ot_bits16 or ot_bits32,ot_none,ot_none,ot_none);
+ code : #208#1#233#52;
+ flags : if_8086 or if_pass2
+ ),
+ (
+ opcode : A_JMP;
+ ops : 1;
+ optypes : (ot_rm_gpr or ot_bits32,ot_none,ot_none,ot_none);
+ code : #213#1#255#132;
+ flags : if_386 or if_nox86_64
+ ),
+ (
+ opcode : A_JMP;
+ ops : 1;
+ optypes : (ot_rm_gpr or ot_bits16,ot_none,ot_none,ot_none);
+ code : #212#1#255#132;
+ flags : if_8086
+ ),
+ (
+ opcode : A_JMP;
+ ops : 1;
+ optypes : (ot_immediate or ot_short,ot_none,ot_none,ot_none);
+ code : #1#235#40;
+ flags : if_8086 or if_pass2
+ ),
+ (
+ opcode : A_JMP;
+ ops : 1;
+ optypes : (ot_immediate or ot_near,ot_none,ot_none,ot_none);
+ code : #208#1#233#52;
+ flags : if_8086 or if_pass2
+ ),
+ (
+ opcode : A_JMP;
+ ops : 1;
+ optypes : (ot_immediate or ot_far,ot_none,ot_none,ot_none);
+ code : #208#1#234#28#31;
+ flags : if_8086 or if_pass2 or if_nox86_64
+ ),
+ (
+ opcode : A_JMP;
+ ops : 1;
+ optypes : (ot_memory or ot_near,ot_none,ot_none,ot_none);
+ code : #208#1#255#132;
+ flags : if_8086
+ ),
+ (
+ opcode : A_JMP;
+ ops : 1;
+ optypes : (ot_memory or ot_far,ot_none,ot_none,ot_none);
+ code : #208#1#255#133;
+ flags : if_8086
+ ),
+ (
+ opcode : A_JMP;
+ ops : 2;
+ optypes : (ot_immediate,ot_immediate,ot_none,ot_none);
+ code : #215#1#234#29#24;
+ flags : if_8086 or if_nox86_64
+ ),
+ (
+ opcode : A_JMP;
+ ops : 2;
+ optypes : (ot_immediate,ot_immediate or ot_bits16,ot_none,ot_none);
+ code : #212#1#234#25#24;
+ flags : if_8086 or if_nox86_64
+ ),
+ (
+ opcode : A_JMP;
+ ops : 2;
+ optypes : (ot_immediate,ot_immediate or ot_bits32,ot_none,ot_none);
+ code : #213#1#234#33#24;
+ flags : if_386 or if_nox86_64
+ ),
+ (
+ opcode : A_LAHF;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#159;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LAR;
+ ops : 2;
+ optypes : (ot_reg16 or ot_bits32 or ot_bits64,ot_rm_gpr,ot_none,ot_none);
+ code : #208#2#15#2#72;
+ flags : if_286 or if_prot or if_sm
+ ),
+ (
+ opcode : A_LCALL;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+ code : #213#1#255#131;
+ flags : if_386 or if_nox86_64
+ ),
+ (
+ opcode : A_LCALL;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none,ot_none);
+ code : #212#1#255#131;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LDS;
+ ops : 2;
+ optypes : (ot_reg16 or ot_bits32,ot_memory,ot_none,ot_none);
+ code : #208#1#197#72;
+ flags : if_8086 or if_nox86_64
+ ),
+ (
+ opcode : A_LEA;
+ ops : 2;
+ optypes : (ot_reg32 or ot_bits64,ot_memory,ot_none,ot_none);
+ code : #208#1#141#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LEA;
+ ops : 2;
+ optypes : (ot_reg32 or ot_bits64,ot_immediate,ot_none,ot_none);
+ code : #208#1#141#72;
+ flags : if_8086 or if_sd
+ ),
+ (
+ opcode : A_LEAVE;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#201;
+ flags : if_186
+ ),
+ (
+ opcode : A_LES;
+ ops : 2;
+ optypes : (ot_reg16 or ot_bits32,ot_memory,ot_none,ot_none);
+ code : #208#1#196#72;
+ flags : if_8086 or if_nox86_64
+ ),
+ (
+ opcode : A_LFS;
+ ops : 2;
+ optypes : (ot_reg16 or ot_bits32,ot_memory,ot_none,ot_none);
+ code : #208#2#15#180#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_LGDT;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #2#15#1#130;
+ flags : if_286 or if_priv
+ ),
+ (
+ opcode : A_LGS;
+ ops : 2;
+ optypes : (ot_reg16 or ot_bits32,ot_memory,ot_none,ot_none);
+ code : #208#2#15#181#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_LIDT;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #2#15#1#131;
+ flags : if_286 or if_priv
+ ),
+ (
+ opcode : A_LJMP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+ code : #213#1#255#133;
+ flags : if_386 or if_nox86_64
+ ),
+ (
+ opcode : A_LJMP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none,ot_none);
+ code : #212#1#255#133;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LLDT;
+ ops : 1;
+ optypes : (ot_rm_gpr or ot_bits16,ot_none,ot_none,ot_none);
+ code : #2#15#0#130;
+ flags : if_286 or if_prot or if_priv
+ ),
+ (
+ opcode : A_LMSW;
+ ops : 1;
+ optypes : (ot_rm_gpr or ot_bits16,ot_none,ot_none,ot_none);
+ code : #2#15#1#134;
+ flags : if_286 or if_priv
+ ),
+ (
+ opcode : A_LOADALL;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#15#7;
+ flags : if_386 or if_undoc
+ ),
+ (
+ opcode : A_LOADALL286;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#15#5;
+ flags : if_286 or if_undoc
+ ),
+ (
+ opcode : A_LOCK;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#240;
+ flags : if_8086 or if_pre
+ ),
+ (
+ opcode : A_LODSB;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#172;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LODSD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #213#1#173;
+ flags : if_386
+ ),
+ (
+ opcode : A_LODSW;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #212#1#173;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LOOP;
+ ops : 1;
+ optypes : (ot_immediate,ot_none,ot_none,ot_none);
+ code : #202#1#226#40;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LOOP;
+ ops : 2;
+ optypes : (ot_immediate,ot_reg_cx,ot_none,ot_none);
+ code : #200#1#226#40;
+ flags : if_8086 or if_nox86_64
+ ),
+ (
+ opcode : A_LOOP;
+ ops : 2;
+ optypes : (ot_immediate,ot_reg_ecx or ot_bits64,ot_none,ot_none);
+ code : #201#1#226#40;
+ flags : if_386
+ ),
+ (
+ opcode : A_LOOPE;
+ ops : 1;
+ optypes : (ot_immediate,ot_none,ot_none,ot_none);
+ code : #202#1#225#40;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LOOPE;
+ ops : 2;
+ optypes : (ot_immediate,ot_reg_cx,ot_none,ot_none);
+ code : #200#1#225#40;
+ flags : if_8086 or if_nox86_64
+ ),
+ (
+ opcode : A_LOOPE;
+ ops : 2;
+ optypes : (ot_immediate,ot_reg_ecx or ot_bits64,ot_none,ot_none);
+ code : #201#1#225#40;
+ flags : if_386
+ ),
+ (
+ opcode : A_LOOPNE;
+ ops : 1;
+ optypes : (ot_immediate,ot_none,ot_none,ot_none);
+ code : #202#1#224#40;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LOOPNE;
+ ops : 2;
+ optypes : (ot_immediate,ot_reg_cx,ot_none,ot_none);
+ code : #200#1#224#40;
+ flags : if_8086 or if_nox86_64
+ ),
+ (
+ opcode : A_LOOPNE;
+ ops : 2;
+ optypes : (ot_immediate,ot_reg_ecx or ot_bits64,ot_none,ot_none);
+ code : #201#1#224#40;
+ flags : if_386
+ ),
+ (
+ opcode : A_LOOPNZ;
+ ops : 1;
+ optypes : (ot_immediate,ot_none,ot_none,ot_none);
+ code : #202#1#224#40;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LOOPNZ;
+ ops : 2;
+ optypes : (ot_immediate,ot_reg_cx,ot_none,ot_none);
+ code : #200#1#224#40;
+ flags : if_8086 or if_nox86_64
+ ),
+ (
+ opcode : A_LOOPNZ;
+ ops : 2;
+ optypes : (ot_immediate,ot_reg_ecx or ot_bits64,ot_none,ot_none);
+ code : #201#1#224#40;
+ flags : if_386
+ ),
+ (
+ opcode : A_LOOPZ;
+ ops : 1;
+ optypes : (ot_immediate,ot_none,ot_none,ot_none);
+ code : #202#1#225#40;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LOOPZ;
+ ops : 2;
+ optypes : (ot_immediate,ot_reg_cx,ot_none,ot_none);
+ code : #200#1#225#40;
+ flags : if_8086 or if_nox86_64
+ ),
+ (
+ opcode : A_LOOPZ;
+ ops : 2;
+ optypes : (ot_immediate,ot_reg_ecx or ot_bits64,ot_none,ot_none);
+ code : #201#1#225#40;
+ flags : if_386
+ ),
+ (
+ opcode : A_LSL;
+ ops : 2;
+ optypes : (ot_reg16 or ot_bits32 or ot_bits64,ot_rm_gpr,ot_none,ot_none);
+ code : #208#2#15#3#72;
+ flags : if_286 or if_prot or if_sm
+ ),
+ (
+ opcode : A_LSS;
+ ops : 2;
+ optypes : (ot_reg16 or ot_bits32 or ot_bits64,ot_memory,ot_none,ot_none);
+ code : #208#2#15#178#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_LTR;
+ ops : 1;
+ optypes : (ot_rm_gpr or ot_bits16,ot_none,ot_none,ot_none);
+ code : #2#15#0#131;
+ flags : if_286 or if_prot or if_priv
+ ),
+ (
+ opcode : A_MONITOR;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #3#15#1#200;
+ flags : if_prescott
+ ),
+ (
+ opcode : A_MONITOR;
+ ops : 3;
+ optypes : (ot_reg_eax,ot_reg_ecx,ot_reg_edx,ot_none);
+ code : #3#15#1#200;
+ flags : if_prescott
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_mem_offs,ot_reg_ax,ot_none,ot_none);
+ code : #212#1#163#36;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_mem_offs,ot_reg_eax,ot_none,ot_none);
+ code : #213#1#163#36;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_rm_gpr,ot_reg16 or ot_bits32 or ot_bits64,ot_none,ot_none);
+ code : #208#1#137#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg_ax,ot_mem_offs,ot_none,ot_none);
+ code : #212#1#161#37;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg_eax,ot_mem_offs,ot_none,ot_none);
+ code : #213#1#161#37;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg16 or ot_bits32 or ot_bits64,ot_rm_gpr,ot_none,ot_none);
+ code : #208#1#139#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediate,ot_none,ot_none);
+ code : #213#8#184#33;
+ flags : if_386 or if_sd
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits32,ot_immediate,ot_none,ot_none);
+ code : #213#1#199#128#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg16,ot_immediate,ot_none,ot_none);
+ code : #212#8#184#25;
+ flags : if_8086 or if_sw
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16,ot_immediate,ot_none,ot_none);
+ code : #212#1#199#128#25;
+ flags : if_8086 or if_sw
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_mem_offs,ot_reg_al,ot_none,ot_none);
+ code : #1#162#36;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_reg8,ot_none,ot_none);
+ code : #1#136#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg_al,ot_mem_offs,ot_none,ot_none);
+ code : #1#160#37;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg8,ot_rm_gpr or ot_bits8,ot_none,ot_none);
+ code : #1#138#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg8,ot_immediate,ot_none,ot_none);
+ code : #8#176#17;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_immediate,ot_none,ot_none);
+ code : #1#198#128#17;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32,ot_reg_cs,ot_none,ot_none);
+ code : #208#1#140#129;
+ flags : if_8086
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32,ot_reg_dess,ot_none,ot_none);
+ code : #208#1#140#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32,ot_reg_fsgs,ot_none,ot_none);
+ code : #208#1#140#65;
+ flags : if_386
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg_dess,ot_rm_gpr or ot_bits16 or ot_bits32,ot_none,ot_none);
+ code : #209#1#142#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg_fsgs,ot_rm_gpr or ot_bits16 or ot_bits32,ot_none,ot_none);
+ code : #209#1#142#72;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg_cr4,ot_none,ot_none);
+ code : #2#15#32#132;
+ flags : if_pent or if_priv or if_nox86_64
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg_creg,ot_none,ot_none);
+ code : #2#15#32#65;
+ flags : if_386 or if_priv or if_nox86_64
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg_dreg,ot_none,ot_none);
+ code : #2#15#33#65;
+ flags : if_386 or if_priv or if_nox86_64
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg_treg,ot_none,ot_none);
+ code : #2#15#36#65;
+ flags : if_386 or if_priv or if_nox86_64
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg_cr4,ot_reg32,ot_none,ot_none);
+ code : #2#15#34#140;
+ flags : if_pent or if_priv or if_nox86_64
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg_creg,ot_reg32,ot_none,ot_none);
+ code : #2#15#34#72;
+ flags : if_386 or if_priv or if_nox86_64
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg_dreg,ot_reg32,ot_none,ot_none);
+ code : #2#15#35#72;
+ flags : if_386 or if_priv or if_nox86_64
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg_treg,ot_reg32,ot_none,ot_none);
+ code : #2#15#38#72;
+ flags : if_386 or if_priv or if_nox86_64
+ ),
+ (
+ opcode : A_MOVD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_rm_gpr or ot_bits32,ot_none,ot_none);
+ code : #2#15#110#72;
+ flags : if_pent or if_mmx or if_sd
+ ),
+ (
+ opcode : A_MOVD;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits32,ot_mmxreg,ot_none,ot_none);
+ code : #2#15#126#65;
+ flags : if_pent or if_mmx or if_sd
+ ),
+ (
+ opcode : A_MOVD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_rm_gpr or ot_bits32,ot_none,ot_none);
+ code : #241#2#15#110#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVD;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits32,ot_xmmreg,ot_none,ot_none);
+ code : #241#2#15#126#65;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#111#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_MOVQ;
+ ops : 2;
+ optypes : (ot_mmxrm,ot_mmxreg,ot_none,ot_none);
+ code : #2#15#127#65;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_MOVQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #219#2#15#126#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVQ;
+ ops : 2;
+ optypes : (ot_xmmrm,ot_xmmreg,ot_none,ot_none);
+ code : #241#2#15#214#65;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVSB;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#164;
+ flags : if_8086
+ ),
+ (
+ opcode : A_MOVSD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #213#1#165;
+ flags : if_386
+ ),
+ (
+ opcode : A_MOVSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #220#2#15#16#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVSD;
+ ops : 2;
+ optypes : (ot_xmmrm,ot_xmmreg,ot_none,ot_none);
+ code : #220#2#15#17#65;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVSW;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #212#1#165;
+ flags : if_8086
+ ),
+ (
+ opcode : A_MOVSX;
+ ops : 2;
+ optypes : (ot_reg32 or ot_bits64,ot_rm_gpr or ot_bits16,ot_none,ot_none);
+ code : #208#2#15#191#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_MOVSX;
+ ops : 2;
+ optypes : (ot_reg16 or ot_bits32 or ot_bits64,ot_rm_gpr or ot_bits8,ot_none,ot_none);
+ code : #208#2#15#190#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_MOVZX;
+ ops : 2;
+ optypes : (ot_reg32 or ot_bits64,ot_rm_gpr or ot_bits16,ot_none,ot_none);
+ code : #208#2#15#183#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_MOVZX;
+ ops : 2;
+ optypes : (ot_reg16 or ot_bits32 or ot_bits64,ot_rm_gpr or ot_bits8,ot_none,ot_none);
+ code : #208#2#15#182#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_MUL;
+ ops : 1;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_none,ot_none,ot_none);
+ code : #208#1#247#132;
+ flags : if_8086
+ ),
+ (
+ opcode : A_MUL;
+ ops : 1;
+ optypes : (ot_rm_gpr or ot_bits8,ot_none,ot_none,ot_none);
+ code : #1#246#132;
+ flags : if_8086
+ ),
+ (
+ opcode : A_MWAIT;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #3#15#1#201;
+ flags : if_prescott
+ ),
+ (
+ opcode : A_MWAIT;
+ ops : 2;
+ optypes : (ot_reg_eax,ot_reg_ecx,ot_none,ot_none);
+ code : #3#15#1#201;
+ flags : if_prescott
+ ),
+ (
+ opcode : A_NEG;
+ ops : 1;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_none,ot_none,ot_none);
+ code : #208#1#247#131;
+ flags : if_8086
+ ),
+ (
+ opcode : A_NEG;
+ ops : 1;
+ optypes : (ot_rm_gpr or ot_bits8,ot_none,ot_none,ot_none);
+ code : #1#246#131;
+ flags : if_8086
+ ),
+ (
+ opcode : A_NOP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#144;
+ flags : if_8086
+ ),
+ (
+ opcode : A_NOT;
+ ops : 1;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_none,ot_none,ot_none);
+ code : #208#1#247#130;
+ flags : if_8086
+ ),
+ (
+ opcode : A_NOT;
+ ops : 1;
+ optypes : (ot_rm_gpr or ot_bits8,ot_none,ot_none,ot_none);
+ code : #1#246#130;
+ flags : if_8086
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_rm_gpr,ot_reg16 or ot_bits32 or ot_bits64,ot_none,ot_none);
+ code : #208#1#9#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_reg16 or ot_bits32 or ot_bits64,ot_rm_gpr,ot_none,ot_none);
+ code : #208#1#11#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_reg8,ot_none,ot_none);
+ code : #1#8#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_reg8,ot_rm_gpr or ot_bits8,ot_none,ot_none);
+ code : #1#10#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_immediate or ot_bits8 or ot_signed,ot_none,ot_none);
+ code : #208#1#131#129#13;
+ flags : if_8086
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_reg_eax,ot_immediate,ot_none,ot_none);
+ code : #213#1#13#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits32,ot_immediate,ot_none,ot_none);
+ code : #213#1#129#129#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_reg_ax,ot_immediate,ot_none,ot_none);
+ code : #212#1#13#25;
+ flags : if_8086 or if_sw
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16,ot_immediate,ot_none,ot_none);
+ code : #212#1#129#129#25;
+ flags : if_8086 or if_sw
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_reg_al,ot_immediate,ot_none,ot_none);
+ code : #1#12#17;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_immediate,ot_none,ot_none);
+ code : #1#128#129#17;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_OUT;
+ ops : 2;
+ optypes : (ot_immediate,ot_reg_al,ot_none,ot_none);
+ code : #1#230#20;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_OUT;
+ ops : 2;
+ optypes : (ot_immediate,ot_reg_ax,ot_none,ot_none);
+ code : #212#1#231#20;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_OUT;
+ ops : 2;
+ optypes : (ot_immediate,ot_reg_eax,ot_none,ot_none);
+ code : #213#1#231#20;
+ flags : if_386 or if_sb
+ ),
+ (
+ opcode : A_OUT;
+ ops : 2;
+ optypes : (ot_reg_dx,ot_reg_al,ot_none,ot_none);
+ code : #1#238;
+ flags : if_8086
+ ),
+ (
+ opcode : A_OUT;
+ ops : 2;
+ optypes : (ot_reg_dx,ot_reg_ax,ot_none,ot_none);
+ code : #212#1#239;
+ flags : if_8086
+ ),
+ (
+ opcode : A_OUT;
+ ops : 2;
+ optypes : (ot_reg_dx,ot_reg_eax,ot_none,ot_none);
+ code : #213#1#239;
+ flags : if_386
+ ),
+ (
+ opcode : A_OUTSB;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#110;
+ flags : if_186
+ ),
+ (
+ opcode : A_OUTSD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #213#1#111;
+ flags : if_386
+ ),
+ (
+ opcode : A_OUTSW;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #212#1#111;
+ flags : if_186
+ ),
+ (
+ opcode : A_PACKSSDW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#107#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PACKSSDW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#107#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PACKSSWB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#99#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PACKSSWB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#99#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PACKUSWB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#103#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PACKUSWB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#103#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PADDB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#252#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PADDB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#252#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PADDD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#254#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PADDD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#254#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PADDSB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#236#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PADDSB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#236#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PADDSIW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#81#72;
+ flags : if_pent or if_mmx or if_sm or if_cyrix
+ ),
+ (
+ opcode : A_PADDSW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#237#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PADDSW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#237#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PADDUSB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#220#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PADDUSB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#220#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PADDUSW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#221#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PADDUSW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#221#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PADDW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#253#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PADDW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#253#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PAND;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#219#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PAND;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#219#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PANDN;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#223#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PANDN;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#223#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PAVEB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#80#72;
+ flags : if_pent or if_mmx or if_sm or if_cyrix
+ ),
+ (
+ opcode : A_PAVGUSB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#15#72#1#191;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PCMPEQB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#116#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PCMPEQB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#116#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PCMPEQD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#118#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PCMPEQD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#118#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PCMPEQW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#117#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PCMPEQW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#117#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PCMPGTB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#100#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PCMPGTB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#100#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PCMPGTD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#102#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PCMPGTD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#102#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PCMPGTW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#101#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PCMPGTW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#101#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PDISTIB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none,ot_none);
+ code : #2#15#84#72;
+ flags : if_pent or if_mmx or if_sm or if_cyrix
+ ),
+ (
+ opcode : A_PF2ID;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#15#72#1#29;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PFACC;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#15#72#1#174;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PFADD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#15#72#1#158;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PFCMPEQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#15#72#1#176;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PFCMPGE;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#15#72#1#144;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PFCMPGT;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#15#72#1#160;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PFMAX;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#15#72#1#164;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PFMIN;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#15#72#1#148;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PFMUL;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#15#72#1#180;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PFRCP;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#15#72#1#150;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PFRCPIT1;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#15#72#1#166;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PFRCPIT2;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#15#72#1#182;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PFRSQIT1;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#15#72#1#167;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PFRSQRT;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#15#72#1#151;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PFSUB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#15#72#1#154;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PFSUBR;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#15#72#1#170;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PI2FD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#15#72#1#13;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PMACHRIW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none,ot_none);
+ code : #2#15#94#72;
+ flags : if_pent or if_mmx or if_sm or if_cyrix
+ ),
+ (
+ opcode : A_PMADDWD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#245#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PMADDWD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#245#72;
+ flags : if_willamette or if_sm or if_sse2
+ ),
+ (
+ opcode : A_PMAGW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#82#72;
+ flags : if_pent or if_mmx or if_sm or if_cyrix
+ ),
+ (
+ opcode : A_PMULHRIW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#93#72;
+ flags : if_pent or if_mmx or if_sm or if_cyrix
+ ),
+ (
+ opcode : A_PMULHRWA;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#15#72#1#183;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PMULHRWC;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#89#72;
+ flags : if_pent or if_mmx or if_sm or if_cyrix
+ ),
+ (
+ opcode : A_PMULHW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#229#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PMULHW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#229#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PMULLW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#213#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PMULLW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#213#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PMVGEZB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none,ot_none);
+ code : #2#15#92#72;
+ flags : if_pent or if_mmx or if_sm or if_cyrix
+ ),
+ (
+ opcode : A_PMVLZB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none,ot_none);
+ code : #2#15#91#72;
+ flags : if_pent or if_mmx or if_sm or if_cyrix
+ ),
+ (
+ opcode : A_PMVNZB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none,ot_none);
+ code : #2#15#90#72;
+ flags : if_pent or if_mmx or if_sm or if_cyrix
+ ),
+ (
+ opcode : A_PMVZB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none,ot_none);
+ code : #2#15#88#72;
+ flags : if_pent or if_mmx or if_sm or if_cyrix
+ ),
+ (
+ opcode : A_POP;
+ ops : 1;
+ optypes : (ot_reg16,ot_none,ot_none,ot_none);
+ code : #212#8#88;
+ flags : if_8086
+ ),
+ (
+ opcode : A_POP;
+ ops : 1;
+ optypes : (ot_reg32,ot_none,ot_none,ot_none);
+ code : #213#8#88;
+ flags : if_386 or if_nox86_64
+ ),
+ (
+ opcode : A_POP;
+ ops : 1;
+ optypes : (ot_rm_gpr or ot_bits16,ot_none,ot_none,ot_none);
+ code : #212#1#143#128;
+ flags : if_8086
+ ),
+ (
+ opcode : A_POP;
+ ops : 1;
+ optypes : (ot_rm_gpr or ot_bits32,ot_none,ot_none,ot_none);
+ code : #213#1#143#128;
+ flags : if_386 or if_nox86_64
+ ),
+ (
+ opcode : A_POP;
+ ops : 1;
+ optypes : (ot_reg_cs,ot_none,ot_none,ot_none);
+ code : #1#15;
+ flags : if_8086 or if_undoc
+ ),
+ (
+ opcode : A_POP;
+ ops : 1;
+ optypes : (ot_reg_dess,ot_none,ot_none,ot_none);
+ code : #4;
+ flags : if_8086 or if_nox86_64
+ ),
+ (
+ opcode : A_POP;
+ ops : 1;
+ optypes : (ot_reg_fsgs,ot_none,ot_none,ot_none);
+ code : #1#15#5#221;
+ flags : if_386
+ ),
+ (
+ opcode : A_POPA;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #215#1#97;
+ flags : if_186 or if_nox86_64
+ ),
+ (
+ opcode : A_POPAD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #213#1#97;
+ flags : if_386 or if_nox86_64
+ ),
+ (
+ opcode : A_POPAW;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #212#1#97;
+ flags : if_186 or if_nox86_64
+ ),
+ (
+ opcode : A_POPF;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #215#1#157;
+ flags : if_186 or if_nox86_64
+ ),
+ (
+ opcode : A_POPFD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #213#1#157;
+ flags : if_386 or if_nox86_64
+ ),
+ (
+ opcode : A_POPFW;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #212#1#157;
+ flags : if_186 or if_nox86_64
+ ),
+ (
+ opcode : A_POR;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#235#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_POR;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none,ot_none);
+ code : #241#2#15#235#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PREFETCH;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #2#15#13#128;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PREFETCHW;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #2#15#13#129;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PSLLD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#242#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSLLD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_immediate,ot_none,ot_none);
+ code : #2#15#114#134#21;
+ flags : if_pent or if_mmx or if_sb or if_ar1
+ ),
+ (
+ opcode : A_PSLLD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#242#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSLLD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_immediate,ot_none,ot_none);
+ code : #241#2#15#114#134#21;
+ flags : if_willamette or if_sse2 or if_sb or if_ar1
+ ),
+ (
+ opcode : A_PSLLDQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_immediate,ot_none,ot_none);
+ code : #241#2#15#115#135#21;
+ flags : if_willamette or if_sse2 or if_sb or if_ar1
+ ),
+ (
+ opcode : A_PSLLQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#243#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSLLQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_immediate,ot_none,ot_none);
+ code : #2#15#115#134#21;
+ flags : if_pent or if_mmx or if_sb or if_ar1
+ ),
+ (
+ opcode : A_PSLLQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#243#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSLLQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_immediate,ot_none,ot_none);
+ code : #241#2#15#115#134#21;
+ flags : if_willamette or if_sse2 or if_sb or if_ar1
+ ),
+ (
+ opcode : A_PSLLW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#241#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSLLW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_immediate,ot_none,ot_none);
+ code : #2#15#113#134#21;
+ flags : if_pent or if_mmx or if_sb or if_ar1
+ ),
+ (
+ opcode : A_PSLLW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#241#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSLLW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_immediate,ot_none,ot_none);
+ code : #241#2#15#113#134#21;
+ flags : if_willamette or if_sse2 or if_sb or if_ar1
+ ),
+ (
+ opcode : A_PSRAD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#226#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSRAD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_immediate,ot_none,ot_none);
+ code : #2#15#114#132#21;
+ flags : if_pent or if_mmx or if_sb or if_ar1
+ ),
+ (
+ opcode : A_PSRAD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#226#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSRAD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_immediate,ot_none,ot_none);
+ code : #241#2#15#114#132#21;
+ flags : if_willamette or if_sse2 or if_sb or if_ar1
+ ),
+ (
+ opcode : A_PSRAW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#225#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSRAW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_immediate,ot_none,ot_none);
+ code : #2#15#113#132#21;
+ flags : if_pent or if_mmx or if_sb or if_ar1
+ ),
+ (
+ opcode : A_PSRAW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#225#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSRAW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_immediate,ot_none,ot_none);
+ code : #241#2#15#113#132#21;
+ flags : if_willamette or if_sse2 or if_sb or if_ar1
+ ),
+ (
+ opcode : A_PSRLD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#210#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSRLD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_immediate,ot_none,ot_none);
+ code : #2#15#114#130#21;
+ flags : if_pent or if_mmx or if_sb or if_ar1
+ ),
+ (
+ opcode : A_PSRLD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#210#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSRLD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_immediate,ot_none,ot_none);
+ code : #241#2#15#114#130#21;
+ flags : if_willamette or if_sse2 or if_sb or if_ar1
+ ),
+ (
+ opcode : A_PSRLQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#211#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSRLQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_immediate,ot_none,ot_none);
+ code : #2#15#115#130#21;
+ flags : if_pent or if_mmx or if_sb or if_ar1
+ ),
+ (
+ opcode : A_PSRLQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#211#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSRLQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_immediate,ot_none,ot_none);
+ code : #241#2#15#115#130#21;
+ flags : if_willamette or if_sse2 or if_sb or if_ar1
+ ),
+ (
+ opcode : A_PSRLW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#209#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSRLW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_immediate,ot_none,ot_none);
+ code : #2#15#113#130#21;
+ flags : if_pent or if_mmx or if_sb or if_ar1
+ ),
+ (
+ opcode : A_PSRLW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#209#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSRLW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_immediate,ot_none,ot_none);
+ code : #241#2#15#113#130#21;
+ flags : if_willamette or if_sse2 or if_sb or if_ar1
+ ),
+ (
+ opcode : A_PSUBB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#248#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSUBB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#248#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSUBD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#250#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSUBD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#250#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSUBSB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#232#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSUBSB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#232#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSUBSIW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none,ot_none);
+ code : #2#15#85#72;
+ flags : if_pent or if_mmx or if_sm or if_cyrix
+ ),
+ (
+ opcode : A_PSUBSIW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none,ot_none);
+ code : #2#15#85#72;
+ flags : if_pent or if_mmx or if_cyrix
+ ),
+ (
+ opcode : A_PSUBSW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#233#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSUBSW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#233#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSUBUSB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#216#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSUBUSB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#216#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSUBUSW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#217#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSUBUSW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#217#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSUBW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#249#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSUBW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#249#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PUNPCKHBW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#104#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PUNPCKHBW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#104#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PUNPCKHDQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#106#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PUNPCKHDQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#106#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PUNPCKHWD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#105#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PUNPCKHWD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#105#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PUNPCKLBW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#96#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PUNPCKLBW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#96#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PUNPCKLDQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#98#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PUNPCKLDQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#98#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PUNPCKLWD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#97#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PUNPCKLWD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#97#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PUSH;
+ ops : 1;
+ optypes : (ot_reg16,ot_none,ot_none,ot_none);
+ code : #212#8#80;
+ flags : if_8086
+ ),
+ (
+ opcode : A_PUSH;
+ ops : 1;
+ optypes : (ot_reg32,ot_none,ot_none,ot_none);
+ code : #213#8#80;
+ flags : if_386 or if_nox86_64
+ ),
+ (
+ opcode : A_PUSH;
+ ops : 1;
+ optypes : (ot_rm_gpr or ot_bits16,ot_none,ot_none,ot_none);
+ code : #212#1#255#134;
+ flags : if_8086
+ ),
+ (
+ opcode : A_PUSH;
+ ops : 1;
+ optypes : (ot_rm_gpr or ot_bits32,ot_none,ot_none,ot_none);
+ code : #213#1#255#134;
+ flags : if_386 or if_nox86_64
+ ),
+ (
+ opcode : A_PUSH;
+ ops : 1;
+ optypes : (ot_immediate or ot_bits32,ot_none,ot_none,ot_none);
+ code : #213#1#104#32#221;
+ flags : if_386
+ ),
+ (
+ opcode : A_PUSH;
+ ops : 1;
+ optypes : (ot_immediate or ot_bits16,ot_none,ot_none,ot_none);
+ code : #212#1#104#24#221;
+ flags : if_286
+ ),
+ (
+ opcode : A_PUSH;
+ ops : 1;
+ optypes : (ot_immediate or ot_bits8 or ot_signed,ot_none,ot_none,ot_none);
+ code : #1#106#12#221;
+ flags : if_286
+ ),
+ (
+ opcode : A_PUSH;
+ ops : 1;
+ optypes : (ot_reg_fsgs,ot_none,ot_none,ot_none);
+ code : #1#15#7#221;
+ flags : if_386 or if_nox86_64
+ ),
+ (
+ opcode : A_PUSH;
+ ops : 1;
+ optypes : (ot_reg_sreg,ot_none,ot_none,ot_none);
+ code : #6;
+ flags : if_8086 or if_nox86_64
+ ),
+ (
+ opcode : A_PUSHA;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #215#1#96;
+ flags : if_186 or if_nox86_64
+ ),
+ (
+ opcode : A_PUSHAD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #213#1#96;
+ flags : if_386 or if_nox86_64
+ ),
+ (
+ opcode : A_PUSHAW;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #212#1#96;
+ flags : if_186 or if_nox86_64
+ ),
+ (
+ opcode : A_PUSHF;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #215#1#156;
+ flags : if_186
+ ),
+ (
+ opcode : A_PUSHFD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #213#1#156;
+ flags : if_386 or if_nox86_64
+ ),
+ (
+ opcode : A_PUSHFW;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #212#1#156;
+ flags : if_186
+ ),
+ (
+ opcode : A_PXOR;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#239#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PXOR;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#239#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_RCL;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_unity,ot_none,ot_none);
+ code : #208#1#209#130;
+ flags : if_8086
+ ),
+ (
+ opcode : A_RCL;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_reg_cl,ot_none,ot_none);
+ code : #208#1#211#130;
+ flags : if_8086
+ ),
+ (
+ opcode : A_RCL;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_immediate,ot_none,ot_none);
+ code : #208#1#193#130#21;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_RCL;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_unity,ot_none,ot_none);
+ code : #1#208#130;
+ flags : if_8086
+ ),
+ (
+ opcode : A_RCL;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_reg_cl,ot_none,ot_none);
+ code : #1#210#130;
+ flags : if_8086
+ ),
+ (
+ opcode : A_RCL;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_immediate,ot_none,ot_none);
+ code : #1#192#130#21;
+ flags : if_186 or if_sb
+ ),
+ (
+ opcode : A_RCR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_unity,ot_none,ot_none);
+ code : #208#1#209#131;
+ flags : if_8086
+ ),
+ (
+ opcode : A_RCR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_reg_cl,ot_none,ot_none);
+ code : #208#1#211#131;
+ flags : if_8086
+ ),
+ (
+ opcode : A_RCR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_immediate,ot_none,ot_none);
+ code : #208#1#193#131#21;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_RCR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_unity,ot_none,ot_none);
+ code : #1#208#131;
+ flags : if_8086
+ ),
+ (
+ opcode : A_RCR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_reg_cl,ot_none,ot_none);
+ code : #1#210#131;
+ flags : if_8086
+ ),
+ (
+ opcode : A_RCR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_immediate,ot_none,ot_none);
+ code : #1#192#131#21;
+ flags : if_186 or if_sb
+ ),
+ (
+ opcode : A_RDSHR;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#15#54;
+ flags : if_p6 or if_cyrix or if_smm
+ ),
+ (
+ opcode : A_RDMSR;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#15#50;
+ flags : if_pent or if_priv
+ ),
+ (
+ opcode : A_RDPMC;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#15#51;
+ flags : if_p6
+ ),
+ (
+ opcode : A_RDTSC;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#15#49;
+ flags : if_pent
+ ),
+ (
+ opcode : A_REP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#243;
+ flags : if_8086 or if_pre
+ ),
+ (
+ opcode : A_REPE;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#243;
+ flags : if_8086 or if_pre
+ ),
+ (
+ opcode : A_REPNE;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#242;
+ flags : if_8086 or if_pre
+ ),
+ (
+ opcode : A_REPNZ;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#242;
+ flags : if_8086 or if_pre
+ ),
+ (
+ opcode : A_REPZ;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#243;
+ flags : if_8086 or if_pre
+ ),
+ (
+ opcode : A_RET;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#195;
+ flags : if_8086
+ ),
+ (
+ opcode : A_RET;
+ ops : 1;
+ optypes : (ot_immediate,ot_none,ot_none,ot_none);
+ code : #1#194#24;
+ flags : if_8086 or if_sw
+ ),
+ (
+ opcode : A_RETF;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#203;
+ flags : if_8086
+ ),
+ (
+ opcode : A_RETF;
+ ops : 1;
+ optypes : (ot_immediate,ot_none,ot_none,ot_none);
+ code : #1#202#24;
+ flags : if_8086 or if_sw
+ ),
+ (
+ opcode : A_RETN;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#195;
+ flags : if_8086
+ ),
+ (
+ opcode : A_RETN;
+ ops : 1;
+ optypes : (ot_immediate,ot_none,ot_none,ot_none);
+ code : #1#194#24;
+ flags : if_8086 or if_sw
+ ),
+ (
+ opcode : A_ROL;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_unity,ot_none,ot_none);
+ code : #208#1#209#128;
+ flags : if_8086
+ ),
+ (
+ opcode : A_ROL;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_reg_cl,ot_none,ot_none);
+ code : #208#1#211#128;
+ flags : if_8086
+ ),
+ (
+ opcode : A_ROL;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_immediate,ot_none,ot_none);
+ code : #208#1#193#128#21;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_ROL;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_unity,ot_none,ot_none);
+ code : #1#208#128;
+ flags : if_8086
+ ),
+ (
+ opcode : A_ROL;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_reg_cl,ot_none,ot_none);
+ code : #1#210#128;
+ flags : if_8086
+ ),
+ (
+ opcode : A_ROL;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_immediate,ot_none,ot_none);
+ code : #1#192#128#21;
+ flags : if_186 or if_sb
+ ),
+ (
+ opcode : A_ROR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_unity,ot_none,ot_none);
+ code : #208#1#209#129;
+ flags : if_8086
+ ),
+ (
+ opcode : A_ROR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_reg_cl,ot_none,ot_none);
+ code : #208#1#211#129;
+ flags : if_8086
+ ),
+ (
+ opcode : A_ROR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_immediate,ot_none,ot_none);
+ code : #208#1#193#129#21;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_ROR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_unity,ot_none,ot_none);
+ code : #1#208#129;
+ flags : if_8086
+ ),
+ (
+ opcode : A_ROR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_reg_cl,ot_none,ot_none);
+ code : #1#210#129;
+ flags : if_8086
+ ),
+ (
+ opcode : A_ROR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_immediate,ot_none,ot_none);
+ code : #1#192#129#21;
+ flags : if_186 or if_sb
+ ),
+ (
+ opcode : A_RSDC;
+ ops : 2;
+ optypes : (ot_reg_sreg,ot_memory or ot_bits80,ot_none,ot_none);
+ code : #2#15#121#65;
+ flags : if_486 or if_cyrix or if_smm
+ ),
+ (
+ opcode : A_RSLDT;
+ ops : 1;
+ optypes : (ot_memory or ot_bits80,ot_none,ot_none,ot_none);
+ code : #2#15#123#128;
+ flags : if_486 or if_cyrix or if_smm
+ ),
+ (
+ opcode : A_RSM;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#15#170;
+ flags : if_pent or if_smm
+ ),
+ (
+ opcode : A_SAHF;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#158;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SAL;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_unity,ot_none,ot_none);
+ code : #208#1#209#132;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SAL;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_reg_cl,ot_none,ot_none);
+ code : #208#1#211#132;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SAL;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_immediate,ot_none,ot_none);
+ code : #208#1#193#132#21;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_SAL;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_unity,ot_none,ot_none);
+ code : #1#208#132;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SAL;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_reg_cl,ot_none,ot_none);
+ code : #1#210#132;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SAL;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_immediate,ot_none,ot_none);
+ code : #1#192#132#21;
+ flags : if_186 or if_sb
+ ),
+ (
+ opcode : A_SALC;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#214;
+ flags : if_8086 or if_undoc or if_nox86_64
+ ),
+ (
+ opcode : A_SAR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_unity,ot_none,ot_none);
+ code : #208#1#209#135;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SAR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_reg_cl,ot_none,ot_none);
+ code : #208#1#211#135;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SAR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_immediate,ot_none,ot_none);
+ code : #208#1#193#135#21;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_SAR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_unity,ot_none,ot_none);
+ code : #1#208#135;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SAR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_reg_cl,ot_none,ot_none);
+ code : #1#210#135;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SAR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_immediate,ot_none,ot_none);
+ code : #1#192#135#21;
+ flags : if_186 or if_sb
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_rm_gpr,ot_reg16 or ot_bits32 or ot_bits64,ot_none,ot_none);
+ code : #208#1#25#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_reg16 or ot_bits32 or ot_bits64,ot_rm_gpr,ot_none,ot_none);
+ code : #208#1#27#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_immediate or ot_bits8 or ot_signed,ot_none,ot_none);
+ code : #208#1#131#131#13;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_reg8,ot_none,ot_none);
+ code : #1#24#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_reg8,ot_rm_gpr or ot_bits8,ot_none,ot_none);
+ code : #1#26#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_reg_eax,ot_immediate,ot_none,ot_none);
+ code : #213#1#29#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits32,ot_immediate,ot_none,ot_none);
+ code : #208#1#129#131#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_reg_ax,ot_immediate,ot_none,ot_none);
+ code : #212#1#29#25;
+ flags : if_8086 or if_sw
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16,ot_immediate,ot_none,ot_none);
+ code : #208#1#129#131#25;
+ flags : if_8086 or if_sw
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_reg_al,ot_immediate,ot_none,ot_none);
+ code : #1#28#17;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_immediate,ot_none,ot_none);
+ code : #1#128#131#17;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_SCASB;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #218#1#174;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SCASD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #218#213#1#175;
+ flags : if_386
+ ),
+ (
+ opcode : A_SCASW;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #218#212#1#175;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SEGCS;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#46;
+ flags : if_8086 or if_pre
+ ),
+ (
+ opcode : A_SEGDS;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#62;
+ flags : if_8086 or if_pre
+ ),
+ (
+ opcode : A_SEGES;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#38;
+ flags : if_8086 or if_pre
+ ),
+ (
+ opcode : A_SEGFS;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#100;
+ flags : if_8086 or if_pre
+ ),
+ (
+ opcode : A_SEGGS;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#101;
+ flags : if_8086 or if_pre
+ ),
+ (
+ opcode : A_SEGSS;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#54;
+ flags : if_8086 or if_pre
+ ),
+ (
+ opcode : A_SGDT;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #2#15#1#128;
+ flags : if_286
+ ),
+ (
+ opcode : A_SHL;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_unity,ot_none,ot_none);
+ code : #208#1#209#132;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SHL;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_reg_cl,ot_none,ot_none);
+ code : #208#1#211#132;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SHL;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_immediate,ot_none,ot_none);
+ code : #208#1#193#132#21;
+ flags : if_186 or if_sw
+ ),
+ (
+ opcode : A_SHL;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_unity,ot_none,ot_none);
+ code : #1#208#132;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SHL;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_reg_cl,ot_none,ot_none);
+ code : #1#210#132;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SHL;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_immediate,ot_none,ot_none);
+ code : #1#192#132#21;
+ flags : if_186 or if_sb
+ ),
+ (
+ opcode : A_SHLD;
+ ops : 3;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_reg16 or ot_bits32 or ot_bits64,ot_immediate,ot_none);
+ code : #209#2#15#164#65#22;
+ flags : if_386 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_SHLD;
+ ops : 3;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_reg16 or ot_bits32 or ot_bits64,ot_reg_cl,ot_none);
+ code : #209#2#15#165#65;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_SHR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_unity,ot_none,ot_none);
+ code : #208#1#209#133;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SHR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_reg_cl,ot_none,ot_none);
+ code : #208#1#211#133;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SHR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_immediate,ot_none,ot_none);
+ code : #208#1#193#133#21;
+ flags : if_186 or if_sw
+ ),
+ (
+ opcode : A_SHR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_unity,ot_none,ot_none);
+ code : #1#208#133;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SHR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_reg_cl,ot_none,ot_none);
+ code : #1#210#133;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SHR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_immediate,ot_none,ot_none);
+ code : #1#192#133#21;
+ flags : if_186 or if_sb
+ ),
+ (
+ opcode : A_SHRD;
+ ops : 3;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_reg16 or ot_bits32 or ot_bits64,ot_immediate,ot_none);
+ code : #209#2#15#172#65#22;
+ flags : if_386 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_SHRD;
+ ops : 3;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_reg16 or ot_bits32 or ot_bits64,ot_reg_cl,ot_none);
+ code : #209#2#15#173#65;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_SIDT;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #2#15#1#129;
+ flags : if_286
+ ),
+ (
+ opcode : A_SLDT;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #2#15#0#128;
+ flags : if_286
+ ),
+ (
+ opcode : A_SLDT;
+ ops : 1;
+ optypes : (ot_reg16 or ot_bits32 or ot_bits64,ot_none,ot_none,ot_none);
+ code : #208#2#15#0#128;
+ flags : if_286
+ ),
+ (
+ opcode : A_SMI;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#241;
+ flags : if_386 or if_undoc
+ ),
+ (
+ opcode : A_SMINT;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#15#56;
+ flags : if_p6 or if_cyrix
+ ),
+ (
+ opcode : A_SMINTOLD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#15#126;
+ flags : if_486 or if_cyrix
+ ),
+ (
+ opcode : A_SMSW;
+ ops : 1;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_none,ot_none,ot_none);
+ code : #208#2#15#1#132;
+ flags : if_286
+ ),
+ (
+ opcode : A_STC;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#249;
+ flags : if_8086
+ ),
+ (
+ opcode : A_STD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#253;
+ flags : if_8086
+ ),
+ (
+ opcode : A_STI;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#251;
+ flags : if_8086
+ ),
+ (
+ opcode : A_STOSB;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#170;
+ flags : if_8086
+ ),
+ (
+ opcode : A_STOSD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #213#1#171;
+ flags : if_386
+ ),
+ (
+ opcode : A_STOSW;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #212#1#171;
+ flags : if_8086
+ ),
+ (
+ opcode : A_STR;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #2#15#0#129;
+ flags : if_286 or if_prot
+ ),
+ (
+ opcode : A_STR;
+ ops : 1;
+ optypes : (ot_reg16 or ot_bits32 or ot_bits64,ot_none,ot_none,ot_none);
+ code : #208#2#15#0#129;
+ flags : if_286 or if_prot
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_rm_gpr,ot_reg16 or ot_bits32 or ot_bits64,ot_none,ot_none);
+ code : #208#1#41#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_reg16 or ot_bits32 or ot_bits64,ot_rm_gpr,ot_none,ot_none);
+ code : #208#1#43#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_reg8,ot_none,ot_none);
+ code : #1#40#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_reg8,ot_rm_gpr or ot_bits8,ot_none,ot_none);
+ code : #1#42#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_immediate or ot_bits8 or ot_signed,ot_none,ot_none);
+ code : #208#1#131#133#13;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_reg_eax,ot_immediate,ot_none,ot_none);
+ code : #213#1#45#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits32,ot_immediate,ot_none,ot_none);
+ code : #208#1#129#133#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_reg_ax,ot_immediate,ot_none,ot_none);
+ code : #212#1#45#25;
+ flags : if_8086 or if_sw
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16,ot_immediate,ot_none,ot_none);
+ code : #212#1#129#133#25;
+ flags : if_8086 or if_sw
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_reg_al,ot_immediate,ot_none,ot_none);
+ code : #1#44#17;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_immediate,ot_none,ot_none);
+ code : #1#128#133#17;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_SVDC;
+ ops : 2;
+ optypes : (ot_memory or ot_bits80,ot_reg_sreg,ot_none,ot_none);
+ code : #2#15#120#65;
+ flags : if_486 or if_cyrix or if_smm
+ ),
+ (
+ opcode : A_SVLDT;
+ ops : 1;
+ optypes : (ot_memory or ot_bits80,ot_none,ot_none,ot_none);
+ code : #2#15#122#128;
+ flags : if_486 or if_cyrix or if_smm
+ ),
+ (
+ opcode : A_SVTS;
+ ops : 1;
+ optypes : (ot_memory or ot_bits80,ot_none,ot_none,ot_none);
+ code : #2#15#124#128;
+ flags : if_486 or if_cyrix or if_smm
+ ),
+ (
+ opcode : A_SYSCALL;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#15#5;
+ flags : if_p6 or if_amd
+ ),
+ (
+ opcode : A_SYSENTER;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#15#52;
+ flags : if_p6
+ ),
+ (
+ opcode : A_SYSEXIT;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#15#53;
+ flags : if_p6 or if_priv
+ ),
+ (
+ opcode : A_SYSRET;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#15#7;
+ flags : if_p6 or if_priv or if_amd
+ ),
+ (
+ opcode : A_TEST;
+ ops : 2;
+ optypes : (ot_rm_gpr,ot_reg16 or ot_bits32 or ot_bits64,ot_none,ot_none);
+ code : #208#1#133#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_TEST;
+ ops : 2;
+ optypes : (ot_reg16 or ot_bits32 or ot_bits64,ot_memory,ot_none,ot_none);
+ code : #208#1#133#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_TEST;
+ ops : 2;
+ optypes : (ot_reg8,ot_reg8,ot_none,ot_none);
+ code : #1#132#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_TEST;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_reg8,ot_none,ot_none);
+ code : #1#132#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_TEST;
+ ops : 2;
+ optypes : (ot_reg_eax,ot_immediate,ot_none,ot_none);
+ code : #213#1#169#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_TEST;
+ ops : 2;
+ optypes : (ot_reg_ax,ot_immediate,ot_none,ot_none);
+ code : #212#1#169#25;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_TEST;
+ ops : 2;
+ optypes : (ot_reg_al,ot_immediate,ot_none,ot_none);
+ code : #1#168#17;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_TEST;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits32,ot_immediate,ot_none,ot_none);
+ code : #213#1#247#128#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_TEST;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16,ot_immediate,ot_none,ot_none);
+ code : #212#1#247#128#25;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_TEST;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_immediate,ot_none,ot_none);
+ code : #1#246#128#17;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_TEST;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits32,ot_none,ot_none);
+ code : #213#1#247#128#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_TEST;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits16,ot_none,ot_none);
+ code : #212#1#247#128#25;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_TEST;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits8,ot_none,ot_none);
+ code : #1#246#128#17;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_UD1;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#15#185;
+ flags : if_286 or if_undoc
+ ),
+ (
+ opcode : A_UD2;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#15#11;
+ flags : if_286
+ ),
+ (
+ opcode : A_UMOV;
+ ops : 2;
+ optypes : (ot_rm_gpr,ot_reg16 or ot_bits32 or ot_bits64,ot_none,ot_none);
+ code : #208#2#15#17#65;
+ flags : if_386 or if_undoc or if_sm
+ ),
+ (
+ opcode : A_UMOV;
+ ops : 2;
+ optypes : (ot_reg16 or ot_bits32 or ot_bits64,ot_memory,ot_none,ot_none);
+ code : #208#2#15#19#72;
+ flags : if_386 or if_undoc or if_sm
+ ),
+ (
+ opcode : A_UMOV;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_reg8,ot_none,ot_none);
+ code : #2#15#16#65;
+ flags : if_386 or if_undoc
+ ),
+ (
+ opcode : A_UMOV;
+ ops : 2;
+ optypes : (ot_reg8,ot_rm_gpr or ot_bits8,ot_none,ot_none);
+ code : #2#15#18#72;
+ flags : if_386 or if_undoc
+ ),
+ (
+ opcode : A_VERR;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #2#15#0#132;
+ flags : if_286 or if_prot
+ ),
+ (
+ opcode : A_VERR;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none,ot_none);
+ code : #2#15#0#132;
+ flags : if_286 or if_prot
+ ),
+ (
+ opcode : A_VERR;
+ ops : 1;
+ optypes : (ot_reg16,ot_none,ot_none,ot_none);
+ code : #2#15#0#132;
+ flags : if_286 or if_prot
+ ),
+ (
+ opcode : A_VERW;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #2#15#0#133;
+ flags : if_286 or if_prot
+ ),
+ (
+ opcode : A_VERW;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none,ot_none);
+ code : #2#15#0#133;
+ flags : if_286 or if_prot
+ ),
+ (
+ opcode : A_VERW;
+ ops : 1;
+ optypes : (ot_reg16,ot_none,ot_none,ot_none);
+ code : #2#15#0#133;
+ flags : if_286 or if_prot
+ ),
+ (
+ opcode : A_WAIT;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#155;
+ flags : if_8086
+ ),
+ (
+ opcode : A_WBINVD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#15#9;
+ flags : if_486 or if_priv
+ ),
+ (
+ opcode : A_WRSHR;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#15#55;
+ flags : if_p6 or if_cyrix or if_smm
+ ),
+ (
+ opcode : A_WRMSR;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#15#48;
+ flags : if_pent or if_priv
+ ),
+ (
+ opcode : A_XADD;
+ ops : 2;
+ optypes : (ot_memory,ot_reg16 or ot_bits32 or ot_bits64,ot_none,ot_none);
+ code : #208#2#15#193#65;
+ flags : if_486 or if_sm
+ ),
+ (
+ opcode : A_XADD;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_reg8,ot_none,ot_none);
+ code : #2#15#192#65;
+ flags : if_486
+ ),
+ (
+ opcode : A_XBTS;
+ ops : 2;
+ optypes : (ot_reg16,ot_memory,ot_none,ot_none);
+ code : #212#2#15#166#72;
+ flags : if_386 or if_sw or if_undoc
+ ),
+ (
+ opcode : A_XBTS;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none,ot_none);
+ code : #212#2#15#166#72;
+ flags : if_386 or if_undoc
+ ),
+ (
+ opcode : A_XBTS;
+ ops : 2;
+ optypes : (ot_reg32,ot_memory,ot_none,ot_none);
+ code : #213#2#15#166#72;
+ flags : if_386 or if_sd or if_undoc
+ ),
+ (
+ opcode : A_XBTS;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #213#2#15#166#72;
+ flags : if_386 or if_undoc
+ ),
+ (
+ opcode : A_XCHG;
+ ops : 2;
+ optypes : (ot_reg_ax,ot_reg16,ot_none,ot_none);
+ code : #212#9#144;
+ flags : if_8086
+ ),
+ (
+ opcode : A_XCHG;
+ ops : 2;
+ optypes : (ot_reg_eax,ot_reg32,ot_none,ot_none);
+ code : #213#9#144;
+ flags : if_386
+ ),
+ (
+ opcode : A_XCHG;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg_ax,ot_none,ot_none);
+ code : #212#8#144;
+ flags : if_8086
+ ),
+ (
+ opcode : A_XCHG;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg_eax,ot_none,ot_none);
+ code : #213#8#144;
+ flags : if_386
+ ),
+ (
+ opcode : A_XCHG;
+ ops : 2;
+ optypes : (ot_reg16 or ot_bits32 or ot_bits64,ot_rm_gpr,ot_none,ot_none);
+ code : #208#1#135#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_XCHG;
+ ops : 2;
+ optypes : (ot_memory,ot_reg16 or ot_bits32 or ot_bits64,ot_none,ot_none);
+ code : #208#1#135#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_XCHG;
+ ops : 2;
+ optypes : (ot_reg8,ot_rm_gpr or ot_bits8,ot_none,ot_none);
+ code : #1#134#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_XCHG;
+ ops : 2;
+ optypes : (ot_memory or ot_bits8,ot_reg8,ot_none,ot_none);
+ code : #1#134#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_XLAT;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#215;
+ flags : if_8086
+ ),
+ (
+ opcode : A_XLATB;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#215;
+ flags : if_8086
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_rm_gpr,ot_reg16 or ot_bits32 or ot_bits64,ot_none,ot_none);
+ code : #208#1#49#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_reg16 or ot_bits32 or ot_bits64,ot_rm_gpr,ot_none,ot_none);
+ code : #208#1#51#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_reg8,ot_none,ot_none);
+ code : #1#48#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_reg8,ot_rm_gpr or ot_bits8,ot_none,ot_none);
+ code : #1#50#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_immediate or ot_bits8 or ot_signed,ot_none,ot_none);
+ code : #208#1#131#134#13;
+ flags : if_8086
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_reg_eax,ot_immediate,ot_none,ot_none);
+ code : #213#1#53#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits32,ot_immediate,ot_none,ot_none);
+ code : #208#1#129#134#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_reg_ax,ot_immediate,ot_none,ot_none);
+ code : #212#1#53#25;
+ flags : if_8086 or if_sw
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16,ot_immediate,ot_none,ot_none);
+ code : #212#1#129#134#25;
+ flags : if_8086 or if_sw
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_reg_al,ot_immediate,ot_none,ot_none);
+ code : #1#52#17;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_immediate,ot_none,ot_none);
+ code : #1#128#134#17;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_XSTORE;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #3#15#167#192;
+ flags : if_p6 or if_cyrix
+ ),
+ (
+ opcode : A_XCRYPTECB;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #219#3#15#167#200;
+ flags : if_p6 or if_cyrix
+ ),
+ (
+ opcode : A_XCRYPTCBC;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #219#3#15#167#208;
+ flags : if_p6 or if_cyrix
+ ),
+ (
+ opcode : A_XCRYPTCFB;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #219#3#15#167#224;
+ flags : if_p6 or if_cyrix
+ ),
+ (
+ opcode : A_XCRYPTOFB;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #219#3#15#167#232;
+ flags : if_p6 or if_cyrix
+ ),
+ (
+ opcode : A_CMOVcc;
+ ops : 2;
+ optypes : (ot_reg16 or ot_bits32 or ot_bits64,ot_rm_gpr,ot_none,ot_none);
+ code : #208#1#15#11#64#72;
+ flags : if_p6 or if_sm
+ ),
+ (
+ opcode : A_Jcc;
+ ops : 1;
+ optypes : (ot_immediate or ot_bits8,ot_none,ot_none,ot_none);
+ code : #11#112#40;
+ flags : if_8086
+ ),
+ (
+ opcode : A_Jcc;
+ ops : 1;
+ optypes : (ot_immediate or ot_bits16 or ot_bits32,ot_none,ot_none,ot_none);
+ code : #208#1#15#11#128#52;
+ flags : if_386 or if_pass2
+ ),
+ (
+ opcode : A_Jcc;
+ ops : 1;
+ optypes : (ot_immediate or ot_short,ot_none,ot_none,ot_none);
+ code : #11#112#40;
+ flags : if_8086
+ ),
+ (
+ opcode : A_Jcc;
+ ops : 1;
+ optypes : (ot_immediate or ot_near,ot_none,ot_none,ot_none);
+ code : #208#1#15#11#128#52;
+ flags : if_386 or if_pass2
+ ),
+ (
+ opcode : A_SETcc;
+ ops : 1;
+ optypes : (ot_rm_gpr or ot_bits8,ot_none,ot_none,ot_none);
+ code : #1#15#11#144#128;
+ flags : if_386
+ ),
+ (
+ opcode : A_ADDPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #217#2#15#88#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_ADDSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #219#2#15#88#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_ANDNPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #2#15#85#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_ANDPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #2#15#84#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPEQPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #217#2#15#194#72#1#0;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPEQSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #219#2#15#194#72#1#0;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPLEPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #217#2#15#194#72#1#2;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPLESS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #219#2#15#194#72#1#2;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPLTPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #217#2#15#194#72#1#1;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPLTSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #219#2#15#194#72#1#1;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPNEQPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #217#2#15#194#72#1#4;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPNEQSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #219#2#15#194#72#1#4;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPNLEPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #217#2#15#194#72#1#6;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPNLESS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #219#2#15#194#72#1#6;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPNLTPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #217#2#15#194#72#1#5;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPNLTSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #219#2#15#194#72#1#5;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPORDPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #217#2#15#194#72#1#7;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPORDSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #219#2#15#194#72#1#7;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPUNORDPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #217#2#15#194#72#1#3;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPUNORDSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #219#2#15#194#72#1#3;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPPS;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_immediate,ot_none);
+ code : #217#2#15#194#72#18;
+ flags : if_katmai or if_sse or if_sb or if_ar2
+ ),
+ (
+ opcode : A_CMPSS;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_immediate,ot_none);
+ code : #219#2#15#194#72#18;
+ flags : if_katmai or if_sse or if_sb or if_ar2
+ ),
+ (
+ opcode : A_COMISS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #2#15#47#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CVTPI2PS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none,ot_none);
+ code : #217#2#15#42#72;
+ flags : if_katmai or if_sse or if_mmx
+ ),
+ (
+ opcode : A_CVTPI2PS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_mmxreg,ot_none,ot_none);
+ code : #217#2#15#42#72;
+ flags : if_katmai or if_sse or if_mmx
+ ),
+ (
+ opcode : A_CVTPS2PI;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none,ot_none);
+ code : #217#2#15#45#72;
+ flags : if_katmai or if_sse or if_mmx
+ ),
+ (
+ opcode : A_CVTPS2PI;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_xmmreg,ot_none,ot_none);
+ code : #217#2#15#45#72;
+ flags : if_katmai or if_sse or if_mmx
+ ),
+ (
+ opcode : A_CVTSI2SS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none,ot_none);
+ code : #219#209#2#15#42#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CVTSI2SS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_reg32 or ot_bits64,ot_none,ot_none);
+ code : #219#209#2#15#42#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CVTSS2SI;
+ ops : 2;
+ optypes : (ot_reg32 or ot_bits64,ot_memory,ot_none,ot_none);
+ code : #219#208#2#15#45#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CVTSS2SI;
+ ops : 2;
+ optypes : (ot_reg32 or ot_bits64,ot_xmmreg,ot_none,ot_none);
+ code : #219#208#2#15#45#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CVTTPS2PI;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none,ot_none);
+ code : #217#2#15#44#72;
+ flags : if_katmai or if_sse or if_mmx
+ ),
+ (
+ opcode : A_CVTTPS2PI;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_xmmreg,ot_none,ot_none);
+ code : #217#2#15#44#72;
+ flags : if_katmai or if_sse or if_mmx
+ ),
+ (
+ opcode : A_CVTTSS2SI;
+ ops : 2;
+ optypes : (ot_reg32 or ot_bits64,ot_memory,ot_none,ot_none);
+ code : #219#208#2#15#44#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CVTTSS2SI;
+ ops : 2;
+ optypes : (ot_reg32 or ot_bits64,ot_xmmreg,ot_none,ot_none);
+ code : #219#208#2#15#44#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_DIVPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #217#2#15#94#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_DIVSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #219#2#15#94#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_LDMXCSR;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #2#15#174#130;
+ flags : if_katmai or if_sse or if_sd
+ ),
+ (
+ opcode : A_MAXPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #217#2#15#95#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MAXSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #219#2#15#95#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MINPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #217#2#15#93#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MINSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #219#2#15#93#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVAPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #2#15#40#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVAPS;
+ ops : 2;
+ optypes : (ot_xmmrm,ot_xmmreg,ot_none,ot_none);
+ code : #2#15#41#65;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVHPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none,ot_none);
+ code : #2#15#22#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVHPS;
+ ops : 2;
+ optypes : (ot_memory,ot_xmmreg,ot_none,ot_none);
+ code : #2#15#23#65;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVLHPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none,ot_none);
+ code : #2#15#22#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVLPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none,ot_none);
+ code : #2#15#18#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVLPS;
+ ops : 2;
+ optypes : (ot_memory,ot_xmmreg,ot_none,ot_none);
+ code : #2#15#19#65;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVHLPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none,ot_none);
+ code : #2#15#18#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVMSKPS;
+ ops : 2;
+ optypes : (ot_reg32,ot_xmmreg,ot_none,ot_none);
+ code : #2#15#80#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVNTPS;
+ ops : 2;
+ optypes : (ot_memory,ot_xmmreg,ot_none,ot_none);
+ code : #2#15#43#65;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #219#2#15#16#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVSS;
+ ops : 2;
+ optypes : (ot_xmmrm,ot_xmmreg,ot_none,ot_none);
+ code : #219#2#15#17#65;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVUPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #217#2#15#16#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVUPS;
+ ops : 2;
+ optypes : (ot_xmmrm,ot_xmmreg,ot_none,ot_none);
+ code : #217#2#15#17#65;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MULPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #2#15#89#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MULSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #219#2#15#89#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_ORPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #2#15#86#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_RCPPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #217#2#15#83#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_RCPSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #219#2#15#83#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_RSQRTPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #217#2#15#82#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_RSQRTSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #219#2#15#82#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_SHUFPS;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_immediate,ot_none);
+ code : #2#15#198#72#18;
+ flags : if_katmai or if_sse or if_sb or if_ar2
+ ),
+ (
+ opcode : A_SQRTPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #217#2#15#81#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_SQRTSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #219#2#15#81#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_STMXCSR;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #2#15#174#131;
+ flags : if_katmai or if_sse or if_sd
+ ),
+ (
+ opcode : A_SUBPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #217#2#15#92#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_SUBSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #219#2#15#92#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_UCOMISS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #2#15#46#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_UNPCKHPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #2#15#21#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_UNPCKLPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #2#15#20#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_XORPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #2#15#87#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_FXRSTOR;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #2#15#174#129;
+ flags : if_p6 or if_sse or if_fpu
+ ),
+ (
+ opcode : A_FXSAVE;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #2#15#174#128;
+ flags : if_p6 or if_sse or if_fpu
+ ),
+ (
+ opcode : A_PREFETCHNTA;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #2#15#24#128;
+ flags : if_katmai
+ ),
+ (
+ opcode : A_PREFETCHT0;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #2#15#24#129;
+ flags : if_katmai
+ ),
+ (
+ opcode : A_PREFETCHT1;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #2#15#24#130;
+ flags : if_katmai
+ ),
+ (
+ opcode : A_PREFETCHT2;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #2#15#24#131;
+ flags : if_katmai
+ ),
+ (
+ opcode : A_SFENCE;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #3#15#174#248;
+ flags : if_katmai
+ ),
+ (
+ opcode : A_MASKMOVQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none,ot_none);
+ code : #2#15#247#72;
+ flags : if_katmai or if_mmx
+ ),
+ (
+ opcode : A_MOVNTQ;
+ ops : 2;
+ optypes : (ot_memory,ot_mmxreg,ot_none,ot_none);
+ code : #2#15#231#65;
+ flags : if_katmai or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PAVGB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#224#72;
+ flags : if_katmai or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PAVGB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#224#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PAVGW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#227#72;
+ flags : if_katmai or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PAVGW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#227#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PEXTRW;
+ ops : 3;
+ optypes : (ot_reg32,ot_mmxreg,ot_immediate,ot_none);
+ code : #2#15#197#72#18;
+ flags : if_katmai or if_mmx or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PEXTRW;
+ ops : 3;
+ optypes : (ot_reg32,ot_xmmreg,ot_immediate,ot_none);
+ code : #241#2#15#197#72#22;
+ flags : if_sse41
+ ),
+ (
+ opcode : A_PEXTRW;
+ ops : 3;
+ optypes : (ot_memory or ot_bits32,ot_xmmreg,ot_immediate,ot_none);
+ code : #241#3#15#58#21#65#22;
+ flags : if_sse41
+ ),
+ (
+ opcode : A_PINSRW;
+ ops : 3;
+ optypes : (ot_mmxreg,ot_reg16,ot_immediate,ot_none);
+ code : #2#15#196#72#18;
+ flags : if_katmai or if_mmx or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PINSRW;
+ ops : 3;
+ optypes : (ot_mmxreg,ot_reg32,ot_immediate,ot_none);
+ code : #2#15#196#72#18;
+ flags : if_katmai or if_mmx or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PINSRW;
+ ops : 3;
+ optypes : (ot_mmxreg,ot_memory,ot_immediate,ot_none);
+ code : #2#15#196#72#18;
+ flags : if_katmai or if_mmx or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PINSRW;
+ ops : 3;
+ optypes : (ot_mmxreg,ot_memory or ot_bits16,ot_immediate,ot_none);
+ code : #2#15#196#72#18;
+ flags : if_katmai or if_mmx or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PINSRW;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_reg16,ot_immediate,ot_none);
+ code : #241#2#15#196#72#22;
+ flags : if_willamette or if_sse2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PINSRW;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_reg32,ot_immediate,ot_none);
+ code : #241#2#15#196#72#22;
+ flags : if_willamette or if_sse2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PINSRW;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_memory,ot_immediate,ot_none);
+ code : #241#2#15#196#72#22;
+ flags : if_willamette or if_sse2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PINSRW;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_memory or ot_bits16,ot_immediate,ot_none);
+ code : #241#2#15#196#72#22;
+ flags : if_willamette or if_sse2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PMAXSW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#238#72;
+ flags : if_katmai or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PMAXSW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#238#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PMAXUB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#222#72;
+ flags : if_katmai or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PMAXUB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#222#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PMINSW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#234#72;
+ flags : if_katmai or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PMINSW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#234#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PMINUB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#218#72;
+ flags : if_katmai or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PMINUB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#218#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PMOVMSKB;
+ ops : 2;
+ optypes : (ot_reg32,ot_mmxreg,ot_none,ot_none);
+ code : #2#15#215#72;
+ flags : if_katmai or if_mmx
+ ),
+ (
+ opcode : A_PMOVMSKB;
+ ops : 2;
+ optypes : (ot_reg32,ot_xmmreg,ot_none,ot_none);
+ code : #241#2#15#215#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PMULHUW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#228#72;
+ flags : if_katmai or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PMULHUW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#228#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSADBW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#246#72;
+ flags : if_katmai or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSADBW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#246#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSHUFW;
+ ops : 3;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_immediate,ot_none);
+ code : #2#15#112#72#18;
+ flags : if_katmai or if_mmx or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PFNACC;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#15#72#1#138;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PFPNACC;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#15#72#1#142;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PI2FW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#15#72#1#12;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PF2IW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#15#72#1#28;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PSWAPD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#15#72#1#187;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_FFREEP;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#223#8#192;
+ flags : if_pent or if_3dnow or if_fpu
+ ),
+ (
+ opcode : A_MASKMOVDQU;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none,ot_none);
+ code : #241#2#15#247#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CLFLUSH;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #2#15#174#135;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVNTDQ;
+ ops : 2;
+ optypes : (ot_memory,ot_xmmreg,ot_none,ot_none);
+ code : #241#2#15#231#65;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_MOVNTI;
+ ops : 2;
+ optypes : (ot_memory,ot_reg32 or ot_bits64,ot_none,ot_none);
+ code : #208#2#15#195#65;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_MOVNTPD;
+ ops : 2;
+ optypes : (ot_memory,ot_xmmreg,ot_none,ot_none);
+ code : #241#2#15#43#65;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PAUSE;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #219#1#144;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_LFENCE;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #3#15#174#232;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MFENCE;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #3#15#174#240;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVDQA;
+ ops : 2;
+ optypes : (ot_xmmrm,ot_xmmreg,ot_none,ot_none);
+ code : #241#2#15#127#65;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_MOVDQA;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#111#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_MOVDQU;
+ ops : 2;
+ optypes : (ot_xmmrm,ot_xmmreg,ot_none,ot_none);
+ code : #219#2#15#127#65;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_MOVDQU;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #219#2#15#111#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_MOVDQ2Q;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_xmmreg,ot_none,ot_none);
+ code : #220#2#15#214#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVQ2DQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_mmxreg,ot_none,ot_none);
+ code : #219#2#15#214#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PADDQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#212#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PADDQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#212#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PMULUDQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#244#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PMULUDQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#244#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSHUFD;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_immediate,ot_none);
+ code : #241#2#15#112#72#18;
+ flags : if_willamette or if_sse2 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PSHUFHW;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_immediate,ot_none);
+ code : #219#2#15#112#72#18;
+ flags : if_willamette or if_sse2 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PSHUFLW;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_immediate,ot_none);
+ code : #220#2#15#112#72#18;
+ flags : if_willamette or if_sse2 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PSRLDQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_immediate,ot_none,ot_none);
+ code : #241#2#15#115#131#21;
+ flags : if_willamette or if_sse2 or if_sb or if_ar1
+ ),
+ (
+ opcode : A_PSUBQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#251#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSUBQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#251#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PUNPCKHQDQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#109#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PUNPCKLQDQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#108#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_ADDPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#88#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_ADDSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #220#2#15#88#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_ANDNPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#85#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_ANDPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#84#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_CMPEQPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#194#72#1#0;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_CMPEQSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #220#2#15#194#72#1#0;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CMPLEPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#194#72#1#2;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_CMPLESD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #220#2#15#194#72#1#2;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CMPLTPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#194#72#1#1;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_CMPLTSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #220#2#15#194#72#1#1;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CMPNEQPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#194#72#1#4;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_CMPNEQSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #220#2#15#194#72#1#4;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CMPNLEPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#194#72#1#6;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_CMPNLESD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #220#2#15#194#72#1#6;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CMPNLTPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#194#72#1#5;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_CMPNLTSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #220#2#15#194#72#1#5;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CMPORDPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#194#72#1#7;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_CMPORDSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #220#2#15#194#72#1#7;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CMPUNORDPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#194#72#1#3;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_CMPUNORDSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #220#2#15#194#72#1#3;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CMPPD;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_immediate,ot_none);
+ code : #241#2#15#194#72#22;
+ flags : if_willamette or if_sse2 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_COMISD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#47#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTDQ2PD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #219#2#15#230#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTDQ2PS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #2#15#91#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_CVTPD2DQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #220#2#15#230#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_CVTPD2PI;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#45#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTPD2PS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#90#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_CVTPI2PD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_mmxrm,ot_none,ot_none);
+ code : #241#2#15#42#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTPS2DQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#91#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_CVTPS2PD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #2#15#90#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTSD2SI;
+ ops : 2;
+ optypes : (ot_reg32 or ot_bits64,ot_xmmreg,ot_none,ot_none);
+ code : #220#208#2#15#45#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTSD2SI;
+ ops : 2;
+ optypes : (ot_reg32 or ot_bits64,ot_memory,ot_none,ot_none);
+ code : #220#208#2#15#45#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTSD2SS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #220#2#15#90#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTSI2SD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_reg32 or ot_bits64,ot_none,ot_none);
+ code : #220#209#2#15#42#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTSI2SD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none,ot_none);
+ code : #220#209#2#15#42#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTSS2SD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #219#2#15#90#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTTPD2PI;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_xmmreg,ot_none,ot_none);
+ code : #241#2#15#44#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTTPD2PI;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none,ot_none);
+ code : #241#2#15#44#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTTPD2DQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#230#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_CVTTPS2DQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #219#2#15#91#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_CVTTSD2SI;
+ ops : 2;
+ optypes : (ot_reg32 or ot_bits64,ot_xmmreg,ot_none,ot_none);
+ code : #220#208#2#15#44#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTTSD2SI;
+ ops : 2;
+ optypes : (ot_reg32 or ot_bits64,ot_memory,ot_none,ot_none);
+ code : #220#208#2#15#44#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_DIVPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#94#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_DIVSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #220#2#15#94#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MAXPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#95#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_MAXSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #220#2#15#95#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MINPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#93#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_MINSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #220#2#15#93#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVAPD;
+ ops : 2;
+ optypes : (ot_xmmrm,ot_xmmreg,ot_none,ot_none);
+ code : #241#2#15#41#65;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_MOVAPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#40#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_MOVHPD;
+ ops : 2;
+ optypes : (ot_memory,ot_xmmreg,ot_none,ot_none);
+ code : #241#2#15#23#65;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVHPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none,ot_none);
+ code : #241#2#15#22#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVLPD;
+ ops : 2;
+ optypes : (ot_memory,ot_xmmreg,ot_none,ot_none);
+ code : #241#2#15#19#65;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVLPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none,ot_none);
+ code : #241#2#15#18#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVMSKPD;
+ ops : 2;
+ optypes : (ot_reg32,ot_xmmreg,ot_none,ot_none);
+ code : #241#2#15#80#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVUPD;
+ ops : 2;
+ optypes : (ot_xmmrm,ot_xmmreg,ot_none,ot_none);
+ code : #241#2#15#17#65;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_MOVUPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#16#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_MULPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#89#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_MULSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #220#2#15#89#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_ORPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#86#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_SHUFPD;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_immediate,ot_none);
+ code : #241#2#15#198#72#22;
+ flags : if_willamette or if_sse2 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_SQRTPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#81#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_SQRTSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #220#2#15#81#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_SUBPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#92#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_SUBSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #220#2#15#92#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_UCOMISD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#46#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_UNPCKHPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#21#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_UNPCKLPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#20#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_XORPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#87#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_ADDSUBPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#208#72;
+ flags : if_prescott or if_sse3 or if_sm
+ ),
+ (
+ opcode : A_ADDSUBPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #220#2#15#208#72;
+ flags : if_prescott or if_sse3 or if_sm
+ ),
+ (
+ opcode : A_HADDPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#124#72;
+ flags : if_prescott or if_sse3 or if_sm
+ ),
+ (
+ opcode : A_HADDPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #220#2#15#124#72;
+ flags : if_prescott or if_sse3 or if_sm
+ ),
+ (
+ opcode : A_HSUBPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#125#72;
+ flags : if_prescott or if_sse3 or if_sm
+ ),
+ (
+ opcode : A_HSUBPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #220#2#15#125#72;
+ flags : if_prescott or if_sse3 or if_sm
+ ),
+ (
+ opcode : A_LDDQU;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none,ot_none);
+ code : #220#2#15#240#72;
+ flags : if_prescott or if_sse3
+ ),
+ (
+ opcode : A_MOVDDUP;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #220#2#15#18#72;
+ flags : if_prescott or if_sse3
+ ),
+ (
+ opcode : A_MOVSHDUP;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #219#2#15#22#72;
+ flags : if_prescott or if_sse3 or if_sm
+ ),
+ (
+ opcode : A_MOVSLDUP;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #219#2#15#18#72;
+ flags : if_prescott or if_sse3 or if_sm
+ ),
+ (
+ opcode : A_VMREAD;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #2#15#120#65;
+ flags : if_386 or if_priv or if_prot
+ ),
+ (
+ opcode : A_VMREAD;
+ ops : 2;
+ optypes : (ot_memory,ot_reg32,ot_none,ot_none);
+ code : #2#15#120#65;
+ flags : if_386 or if_priv or if_prot or if_sm
+ ),
+ (
+ opcode : A_VMWRITE;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #2#15#121#72;
+ flags : if_386 or if_priv or if_prot
+ ),
+ (
+ opcode : A_VMWRITE;
+ ops : 2;
+ optypes : (ot_reg32,ot_memory,ot_none,ot_none);
+ code : #2#15#121#72;
+ flags : if_386 or if_priv or if_prot or if_sm
+ ),
+ (
+ opcode : A_VMCALL;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #3#15#1#193;
+ flags : if_386 or if_priv or if_prot
+ ),
+ (
+ opcode : A_VMLAUNCH;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #3#15#1#194;
+ flags : if_386 or if_priv or if_prot
+ ),
+ (
+ opcode : A_VMRESUME;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #3#15#1#195;
+ flags : if_386 or if_priv or if_prot
+ ),
+ (
+ opcode : A_VMXOFF;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #3#15#1#196;
+ flags : if_386 or if_priv or if_prot
+ ),
+ (
+ opcode : A_VMXON;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #219#2#15#199#134;
+ flags : if_priv or if_prot
+ ),
+ (
+ opcode : A_VMCLEAR;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #241#2#15#199#134;
+ flags : if_priv or if_prot
+ ),
+ (
+ opcode : A_VMPTRLD;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #2#15#199#134;
+ flags : if_priv or if_prot
+ ),
+ (
+ opcode : A_VMPTRST;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #2#15#199#135;
+ flags : if_priv or if_prot
+ ),
+ (
+ opcode : A_VMRUN;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #3#15#1#216;
+ flags : if_386 or if_svm or if_priv or if_prot
+ ),
+ (
+ opcode : A_VMMCALL;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #3#15#1#217;
+ flags : if_386 or if_svm
+ ),
+ (
+ opcode : A_VMLOAD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #3#15#1#218;
+ flags : if_386 or if_svm or if_priv or if_prot
+ ),
+ (
+ opcode : A_VMSAVE;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #3#15#1#219;
+ flags : if_386 or if_svm or if_priv or if_prot
+ ),
+ (
+ opcode : A_STGI;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #3#15#1#220;
+ flags : if_386 or if_svm or if_priv or if_prot
+ ),
+ (
+ opcode : A_CLGI;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #3#15#1#221;
+ flags : if_386 or if_svm or if_priv or if_prot
+ ),
+ (
+ opcode : A_SKINIT;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #3#15#1#222;
+ flags : if_386 or if_svm or if_priv or if_prot
+ ),
+ (
+ opcode : A_INVLPGA;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #3#15#1#223;
+ flags : if_386 or if_svm or if_priv or if_prot
+ ),
+ (
+ opcode : A_MONTMUL;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #219#3#15#166#192;
+ flags : if_centaur
+ ),
+ (
+ opcode : A_XSHA1;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #219#3#15#166#200;
+ flags : if_centaur
+ ),
+ (
+ opcode : A_XSHA256;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #219#3#15#166#208;
+ flags : if_centaur
+ ),
+ (
+ opcode : A_DMINT;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#15#57;
+ flags : if_p6 or if_cyrix
+ ),
+ (
+ opcode : A_RDM;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#15#58;
+ flags : if_p6 or if_cyrix
+ ),
+ (
+ opcode : A_MOVNTSS;
+ ops : 2;
+ optypes : (ot_memory,ot_xmmreg,ot_none,ot_none);
+ code : #219#2#15#43#65;
+ flags : if_sse4 or if_sd
+ ),
+ (
+ opcode : A_MOVNTSD;
+ ops : 2;
+ optypes : (ot_memory,ot_xmmreg,ot_none,ot_none);
+ code : #220#213#2#15#43#65;
+ flags : if_sse4
+ ),
+ (
+ opcode : A_INSERTQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none,ot_none);
+ code : #220#2#15#121#72;
+ flags : if_sse4
+ ),
+ (
+ opcode : A_INSERTQ;
+ ops : 4;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_immediate,ot_immediate);
+ code : #220#2#15#120#72#22#23;
+ flags : if_sse4 or if_sb
+ ),
+ (
+ opcode : A_EXTRQ;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_immediate,ot_immediate,ot_none);
+ code : #241#2#15#120#128#21#22;
+ flags : if_sse4 or if_sb
+ ),
+ (
+ opcode : A_EXTRQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none,ot_none);
+ code : #241#2#15#121#72;
+ flags : if_sse4
+ ),
+ (
+ opcode : A_LZCNT;
+ ops : 2;
+ optypes : (ot_reg16,ot_rm_gpr,ot_none,ot_none);
+ code : #208#219#2#15#189#72;
+ flags : if_386 or if_sm or if_sse4
+ ),
+ (
+ opcode : A_LZCNT;
+ ops : 2;
+ optypes : (ot_reg32 or ot_bits64,ot_rm_gpr,ot_none,ot_none);
+ code : #209#219#2#15#189#72;
+ flags : if_386 or if_sm or if_sse4
+ ),
+ (
+ opcode : A_PABSB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #217#3#15#56#28#72;
+ flags : if_ssse3 or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PABSB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#28#72;
+ flags : if_ssse3 or if_sm
+ ),
+ (
+ opcode : A_PABSW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #217#3#15#56#29#72;
+ flags : if_ssse3 or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PABSW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#29#72;
+ flags : if_ssse3 or if_sm
+ ),
+ (
+ opcode : A_PABSD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #217#3#15#56#30#72;
+ flags : if_ssse3 or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PABSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#30#72;
+ flags : if_ssse3 or if_sm
+ ),
+ (
+ opcode : A_PALIGNR;
+ ops : 3;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_immediate,ot_none);
+ code : #217#3#15#58#15#72#22;
+ flags : if_ssse3 or if_mmx or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PALIGNR;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_immediate,ot_none);
+ code : #241#3#15#58#15#72#22;
+ flags : if_ssse3 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PHADDW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #217#3#15#56#1#72;
+ flags : if_ssse3 or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PHADDW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#1#72;
+ flags : if_ssse3 or if_sm
+ ),
+ (
+ opcode : A_PHADDD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #217#3#15#56#2#72;
+ flags : if_ssse3 or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PHADDD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#2#72;
+ flags : if_ssse3 or if_sm
+ ),
+ (
+ opcode : A_PHADDSW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #217#3#15#56#3#72;
+ flags : if_ssse3 or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PHADDSW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#3#72;
+ flags : if_ssse3 or if_sm
+ ),
+ (
+ opcode : A_PHSUBW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #217#3#15#56#5#72;
+ flags : if_ssse3 or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PHSUBW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#5#72;
+ flags : if_ssse3 or if_sm
+ ),
+ (
+ opcode : A_PHSUBD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #217#3#15#56#6#72;
+ flags : if_ssse3 or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PHSUBD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#6#72;
+ flags : if_ssse3 or if_sm
+ ),
+ (
+ opcode : A_PHSUBSW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #217#3#15#56#7#72;
+ flags : if_ssse3 or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PHSUBSW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#7#72;
+ flags : if_ssse3 or if_sm
+ ),
+ (
+ opcode : A_PMADDUBSW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #217#3#15#56#4#72;
+ flags : if_ssse3 or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PMADDUBSW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#4#72;
+ flags : if_ssse3 or if_sm
+ ),
+ (
+ opcode : A_PMULHRSW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #217#3#15#56#11#72;
+ flags : if_ssse3 or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PMULHRSW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#11#72;
+ flags : if_ssse3 or if_sm
+ ),
+ (
+ opcode : A_PSHUFB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #217#3#15#56#0#72;
+ flags : if_ssse3 or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSHUFB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#0#72;
+ flags : if_ssse3 or if_sm
+ ),
+ (
+ opcode : A_PSIGNB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #217#3#15#56#8#72;
+ flags : if_ssse3 or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSIGNB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#8#72;
+ flags : if_ssse3 or if_sm
+ ),
+ (
+ opcode : A_PSIGNW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #217#3#15#56#9#72;
+ flags : if_ssse3 or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSIGNW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#9#72;
+ flags : if_ssse3 or if_sm
+ ),
+ (
+ opcode : A_PSIGND;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #217#3#15#56#10#72;
+ flags : if_ssse3 or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSIGND;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#10#72;
+ flags : if_ssse3 or if_sm
+ ),
+ (
+ opcode : A_BLENDPS;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_immediate,ot_none);
+ code : #241#3#15#58#12#72#22;
+ flags : if_sse41 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_BLENDPD;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_immediate,ot_none);
+ code : #241#3#15#58#13#72#22;
+ flags : if_sse41 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_BLENDVPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#20#72;
+ flags : if_sse41 or if_sm
+ ),
+ (
+ opcode : A_BLENDVPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#21#72;
+ flags : if_sse41 or if_sm
+ ),
+ (
+ opcode : A_DPPS;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_immediate,ot_none);
+ code : #241#3#15#58#64#72#22;
+ flags : if_sse41 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_DPPD;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_immediate,ot_none);
+ code : #241#3#15#58#65#72#22;
+ flags : if_sse41 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_EXTRACTPS;
+ ops : 3;
+ optypes : (ot_memory,ot_xmmreg,ot_immediate,ot_none);
+ code : #241#213#3#15#58#23#65#22;
+ flags : if_sse41 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_EXTRACTPS;
+ ops : 3;
+ optypes : (ot_reg32 or ot_bits64,ot_xmmreg,ot_immediate,ot_none);
+ code : #241#3#15#58#23#65#22;
+ flags : if_sse41 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_INSERTPS;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_immediate,ot_none);
+ code : #241#3#15#58#33#72#22;
+ flags : if_sse41 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_MOVNTDQA;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none,ot_none);
+ code : #241#3#15#56#42#72;
+ flags : if_sse41 or if_sm
+ ),
+ (
+ opcode : A_MPSADBW;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_immediate,ot_none);
+ code : #241#3#15#58#66#72#22;
+ flags : if_sse41 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PACKUSDW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#43#72;
+ flags : if_sse41 or if_sm
+ ),
+ (
+ opcode : A_PBLENDVB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#16#72;
+ flags : if_sse41 or if_sm
+ ),
+ (
+ opcode : A_PBLENDW;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_immediate,ot_none);
+ code : #241#3#15#58#14#72#22;
+ flags : if_sse41 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PCMPEQQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#41#72;
+ flags : if_sse41 or if_sm
+ ),
+ (
+ opcode : A_PEXTRB;
+ ops : 3;
+ optypes : (ot_reg32 or ot_bits64,ot_xmmreg,ot_immediate,ot_none);
+ code : #241#3#15#58#20#65#22;
+ flags : if_sse41 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PEXTRB;
+ ops : 3;
+ optypes : (ot_memory or ot_bits8,ot_xmmreg,ot_immediate,ot_none);
+ code : #241#3#15#58#20#65#22;
+ flags : if_sse41 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PEXTRD;
+ ops : 3;
+ optypes : (ot_reg32,ot_xmmreg,ot_immediate,ot_none);
+ code : #241#3#15#58#22#65#22;
+ flags : if_sse41 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PEXTRD;
+ ops : 3;
+ optypes : (ot_memory or ot_bits32,ot_xmmreg,ot_immediate,ot_none);
+ code : #241#3#15#58#22#65#22;
+ flags : if_sse41 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PHMINPOSUW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#65#72;
+ flags : if_sse41 or if_sm
+ ),
+ (
+ opcode : A_PINSRB;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_reg32 or ot_bits64,ot_immediate,ot_none);
+ code : #241#3#15#58#32#72#22;
+ flags : if_sse41 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PINSRB;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_memory or ot_bits8,ot_immediate,ot_none);
+ code : #241#3#15#58#32#72#22;
+ flags : if_sse41 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PINSRD;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_reg32,ot_immediate,ot_none);
+ code : #241#3#15#58#34#72#22;
+ flags : if_sse41 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PINSRD;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_memory or ot_bits32,ot_immediate,ot_none);
+ code : #241#3#15#58#34#72#22;
+ flags : if_sse41 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PMAXSB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#60#72;
+ flags : if_sse41 or if_sm
+ ),
+ (
+ opcode : A_PMAXSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#61#72;
+ flags : if_sse41 or if_sm
+ ),
+ (
+ opcode : A_PMAXUD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#63#72;
+ flags : if_sse41 or if_sm
+ ),
+ (
+ opcode : A_PMAXUW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#62#72;
+ flags : if_sse41 or if_sm
+ ),
+ (
+ opcode : A_PMINSB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#56#72;
+ flags : if_sse41 or if_sm
+ ),
+ (
+ opcode : A_PMINSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#57#72;
+ flags : if_sse41 or if_sm
+ ),
+ (
+ opcode : A_PMINUW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#58#72;
+ flags : if_sse41 or if_sm
+ ),
+ (
+ opcode : A_PMINUD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#59#72;
+ flags : if_sse41 or if_sm
+ ),
+ (
+ opcode : A_PMOVSXBW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#32#72;
+ flags : if_sse41 or if_sm
+ ),
+ (
+ opcode : A_PMOVSXBD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#33#72;
+ flags : if_sse41 or if_sm
+ ),
+ (
+ opcode : A_PMOVSXBQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#34#72;
+ flags : if_sse41 or if_sm
+ ),
+ (
+ opcode : A_PMOVSXWD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#35#72;
+ flags : if_sse41 or if_sm
+ ),
+ (
+ opcode : A_PMOVSXWQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#36#72;
+ flags : if_sse41 or if_sm
+ ),
+ (
+ opcode : A_PMOVSXDQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#37#72;
+ flags : if_sse41 or if_sm
+ ),
+ (
+ opcode : A_PMOVZXBW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#48#72;
+ flags : if_sse41 or if_sm
+ ),
+ (
+ opcode : A_PMOVZXBD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#49#72;
+ flags : if_sse41 or if_sm
+ ),
+ (
+ opcode : A_PMOVZXBQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#50#72;
+ flags : if_sse41 or if_sm
+ ),
+ (
+ opcode : A_PMOVZXWD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#51#72;
+ flags : if_sse41 or if_sm
+ ),
+ (
+ opcode : A_PMOVZXWQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#52#72;
+ flags : if_sse41 or if_sm
+ ),
+ (
+ opcode : A_PMOVZXDQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#53#72;
+ flags : if_sse41 or if_sm
+ ),
+ (
+ opcode : A_PMULDQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#40#72;
+ flags : if_sse41 or if_sm
+ ),
+ (
+ opcode : A_PMULLD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#64#72;
+ flags : if_sse41 or if_sm
+ ),
+ (
+ opcode : A_PTEST;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#23#72;
+ flags : if_sse41 or if_sm
+ ),
+ (
+ opcode : A_ROUNDPS;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_immediate,ot_none);
+ code : #241#3#15#58#8#72#22;
+ flags : if_sse41 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_ROUNDPD;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_immediate,ot_none);
+ code : #241#3#15#58#9#72#22;
+ flags : if_sse41 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_ROUNDSS;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_immediate,ot_none);
+ code : #241#3#15#58#10#72#22;
+ flags : if_sse41 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_ROUNDSD;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_immediate,ot_none);
+ code : #241#3#15#58#11#72#22;
+ flags : if_sse41 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_CRC32;
+ ops : 2;
+ optypes : (ot_reg32,ot_rm_gpr or ot_bits8,ot_none,ot_none);
+ code : #220#3#15#56#240#72;
+ flags : if_sse42
+ ),
+ (
+ opcode : A_CRC32;
+ ops : 2;
+ optypes : (ot_reg32,ot_rm_gpr or ot_bits16 or ot_bits32,ot_none,ot_none);
+ code : #209#220#3#15#56#241#72;
+ flags : if_sse42
+ ),
+ (
+ opcode : A_PCMPESTRI;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_immediate,ot_none);
+ code : #241#3#15#58#97#72#22;
+ flags : if_sse42 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PCMPESTRM;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_immediate,ot_none);
+ code : #241#3#15#58#96#72#22;
+ flags : if_sse42 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PCMPISTRI;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_immediate,ot_none);
+ code : #241#3#15#58#99#72#22;
+ flags : if_sse42 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PCMPISTRM;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_immediate,ot_none);
+ code : #241#3#15#58#98#72#22;
+ flags : if_sse42 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PCMPGTQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#55#72;
+ flags : if_sse42 or if_sm
+ ),
+ (
+ opcode : A_POPCNT;
+ ops : 2;
+ optypes : (ot_reg16,ot_rm_gpr or ot_bits16,ot_none,ot_none);
+ code : #219#208#2#15#184#72;
+ flags : if_386 or if_sm or if_sse4
+ ),
+ (
+ opcode : A_POPCNT;
+ ops : 2;
+ optypes : (ot_reg32,ot_rm_gpr or ot_bits32,ot_none,ot_none);
+ code : #219#208#2#15#184#72;
+ flags : if_386 or if_sm or if_sse4
+ ),
+ (
+ opcode : A_AESENC;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#220#72;
+ flags : if_sse4 or if_sm
+ ),
+ (
+ opcode : A_AESENCLAST;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#221#72;
+ flags : if_sse4 or if_sm
+ ),
+ (
+ opcode : A_AESDEC;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#222#72;
+ flags : if_sse4 or if_sm
+ ),
+ (
+ opcode : A_AESDECLAST;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#223#72;
+ flags : if_sse4 or if_sm
+ ),
+ (
+ opcode : A_AESIMC;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#219#72;
+ flags : if_sse4 or if_sm
+ ),
+ (
+ opcode : A_AESKEYGENASSIST;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_immediate,ot_none);
+ code : #241#3#15#58#223#72#22;
+ flags : if_sse4 or if_sb or if_ar2
+ )
+);
diff --git a/closures/compiler/i386/n386add.pas b/closures/compiler/i386/n386add.pas
new file mode 100644
index 0000000000..9485af5e02
--- /dev/null
+++ b/closures/compiler/i386/n386add.pas
@@ -0,0 +1,448 @@
+{
+ Copyright (c) 2000-2002 by Florian Klaempfl
+
+ Code generation for add nodes on the i386
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit n386add;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,nadd,cpubase,nx86add;
+
+ type
+ ti386addnode = class(tx86addnode)
+ function use_generic_mul32to64: boolean; override;
+ procedure second_addordinal; override;
+ procedure second_add64bit;override;
+ procedure second_cmp64bit;override;
+ procedure second_mul(unsigned: boolean);
+ end;
+
+ implementation
+
+ uses
+ globtype,systems,
+ cutils,verbose,globals,
+ symconst,symdef,paramgr,defutil,
+ aasmbase,aasmtai,aasmdata,aasmcpu,
+ cgbase,procinfo,
+ ncon,nset,cgutils,tgobj,
+ cga,ncgutil,cgobj,cg64f32,cgx86;
+
+{*****************************************************************************
+ use_generic_mul32to64
+*****************************************************************************}
+
+ function ti386addnode.use_generic_mul32to64: boolean;
+ begin
+ result := False;
+ end;
+
+ { handles all unsigned multiplications, and 32->64 bit signed ones.
+ 32bit-only signed mul is handled by generic codegen }
+ procedure ti386addnode.second_addordinal;
+ var
+ unsigned: boolean;
+ begin
+ unsigned:=not(is_signed(left.resultdef)) or
+ not(is_signed(right.resultdef));
+ if (nodetype=muln) and (unsigned or is_64bit(resultdef)) then
+ second_mul(unsigned)
+ else
+ inherited second_addordinal;
+ end;
+
+{*****************************************************************************
+ Add64bit
+*****************************************************************************}
+
+ procedure ti386addnode.second_add64bit;
+ var
+ op : TOpCG;
+ op1,op2 : TAsmOp;
+ opsize : TOpSize;
+ hregister,
+ hregister2 : tregister;
+ hl4 : tasmlabel;
+ mboverflow,
+ unsigned:boolean;
+ r:Tregister;
+ begin
+ firstcomplex(self);
+ pass_left_right;
+
+ op1:=A_NONE;
+ op2:=A_NONE;
+ mboverflow:=false;
+ opsize:=S_L;
+ unsigned:=((left.resultdef.typ=orddef) and
+ (torddef(left.resultdef).ordtype=u64bit)) or
+ ((right.resultdef.typ=orddef) and
+ (torddef(right.resultdef).ordtype=u64bit));
+ case nodetype of
+ addn :
+ begin
+ op:=OP_ADD;
+ mboverflow:=true;
+ end;
+ subn :
+ begin
+ op:=OP_SUB;
+ op1:=A_SUB;
+ op2:=A_SBB;
+ mboverflow:=true;
+ end;
+ xorn:
+ op:=OP_XOR;
+ orn:
+ op:=OP_OR;
+ andn:
+ op:=OP_AND;
+ else
+ begin
+ { everything should be handled in pass_1 (JM) }
+ internalerror(200109051);
+ end;
+ end;
+
+ { left and right no register? }
+ { then one must be demanded }
+ if (left.location.loc<>LOC_REGISTER) then
+ begin
+ if (right.location.loc<>LOC_REGISTER) then
+ begin
+ hregister:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+ hregister2:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+ cg64.a_load64_loc_reg(current_asmdata.CurrAsmList,left.location,joinreg64(hregister,hregister2));
+ location_reset(left.location,LOC_REGISTER,left.location.size);
+ left.location.register64.reglo:=hregister;
+ left.location.register64.reghi:=hregister2;
+ end
+ else
+ begin
+ location_swap(left.location,right.location);
+ toggleflag(nf_swapped);
+ end;
+ end;
+
+ { at this point, left.location.loc should be LOC_REGISTER }
+ if right.location.loc=LOC_REGISTER then
+ begin
+ { when swapped another result register }
+ if (nodetype=subn) and (nf_swapped in flags) then
+ begin
+ cg64.a_op64_reg_reg(current_asmdata.CurrAsmList,op,location.size,
+ left.location.register64,
+ right.location.register64);
+ location_swap(left.location,right.location);
+ toggleflag(nf_swapped);
+ end
+ else
+ begin
+ cg64.a_op64_reg_reg(current_asmdata.CurrAsmList,op,location.size,
+ right.location.register64,
+ left.location.register64);
+ end;
+ end
+ else
+ begin
+ { right.location<>LOC_REGISTER }
+ if (nodetype=subn) and (nf_swapped in flags) then
+ begin
+ r:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+ cg64.a_load64low_loc_reg(current_asmdata.CurrAsmList,right.location,r);
+ emit_reg_reg(op1,opsize,left.location.register64.reglo,r);
+ emit_reg_reg(A_MOV,opsize,r,left.location.register64.reglo);
+ cg64.a_load64high_loc_reg(current_asmdata.CurrAsmList,right.location,r);
+ { the carry flag is still ok }
+ emit_reg_reg(op2,opsize,left.location.register64.reghi,r);
+ emit_reg_reg(A_MOV,opsize,r,left.location.register64.reghi);
+ end
+ else
+ begin
+ cg64.a_op64_loc_reg(current_asmdata.CurrAsmList,op,location.size,right.location,
+ left.location.register64);
+ end;
+ location_freetemp(current_asmdata.CurrAsmList,right.location);
+ end;
+
+ { only in case of overflow operations }
+ { produce overflow code }
+ { we must put it here directly, because sign of operation }
+ { is in unsigned VAR!! }
+ if mboverflow then
+ begin
+ if cs_check_overflow in current_settings.localswitches then
+ begin
+ current_asmdata.getjumplabel(hl4);
+ if unsigned then
+ cg.a_jmp_flags(current_asmdata.CurrAsmList,F_AE,hl4)
+ else
+ cg.a_jmp_flags(current_asmdata.CurrAsmList,F_NO,hl4);
+ cg.a_call_name(current_asmdata.CurrAsmList,'FPC_OVERFLOW',false);
+ cg.a_label(current_asmdata.CurrAsmList,hl4);
+ end;
+ end;
+
+ location_copy(location,left.location);
+ end;
+
+
+ procedure ti386addnode.second_cmp64bit;
+ var
+ hregister,
+ hregister2 : tregister;
+ href : treference;
+ unsigned : boolean;
+
+ procedure firstjmp64bitcmp;
+
+ var
+ oldnodetype : tnodetype;
+
+ begin
+{$ifdef OLDREGVARS}
+ load_all_regvars(current_asmdata.CurrAsmList);
+{$endif OLDREGVARS}
+ { the jump the sequence is a little bit hairy }
+ case nodetype of
+ ltn,gtn:
+ begin
+ cg.a_jmp_flags(current_asmdata.CurrAsmList,getresflags(unsigned),current_procinfo.CurrTrueLabel);
+ { cheat a little bit for the negative test }
+ toggleflag(nf_swapped);
+ cg.a_jmp_flags(current_asmdata.CurrAsmList,getresflags(unsigned),current_procinfo.CurrFalseLabel);
+ toggleflag(nf_swapped);
+ end;
+ lten,gten:
+ begin
+ oldnodetype:=nodetype;
+ if nodetype=lten then
+ nodetype:=ltn
+ else
+ nodetype:=gtn;
+ cg.a_jmp_flags(current_asmdata.CurrAsmList,getresflags(unsigned),current_procinfo.CurrTrueLabel);
+ { cheat for the negative test }
+ if nodetype=ltn then
+ nodetype:=gtn
+ else
+ nodetype:=ltn;
+ cg.a_jmp_flags(current_asmdata.CurrAsmList,getresflags(unsigned),current_procinfo.CurrFalseLabel);
+ nodetype:=oldnodetype;
+ end;
+ equaln:
+ cg.a_jmp_flags(current_asmdata.CurrAsmList,F_NE,current_procinfo.CurrFalseLabel);
+ unequaln:
+ cg.a_jmp_flags(current_asmdata.CurrAsmList,F_NE,current_procinfo.CurrTrueLabel);
+ end;
+ end;
+
+ procedure secondjmp64bitcmp;
+
+ begin
+ { the jump the sequence is a little bit hairy }
+ case nodetype of
+ ltn,gtn,lten,gten:
+ begin
+ { the comparisaion of the low dword have to be }
+ { always unsigned! }
+ cg.a_jmp_flags(current_asmdata.CurrAsmList,getresflags(true),current_procinfo.CurrTrueLabel);
+ cg.a_jmp_always(current_asmdata.CurrAsmList,current_procinfo.CurrFalseLabel);
+ end;
+ equaln:
+ begin
+ cg.a_jmp_flags(current_asmdata.CurrAsmList,F_NE,current_procinfo.CurrFalseLabel);
+ cg.a_jmp_always(current_asmdata.CurrAsmList,current_procinfo.CurrTrueLabel);
+ end;
+ unequaln:
+ begin
+ cg.a_jmp_flags(current_asmdata.CurrAsmList,F_NE,current_procinfo.CurrTrueLabel);
+ cg.a_jmp_always(current_asmdata.CurrAsmList,current_procinfo.CurrFalseLabel);
+ end;
+ end;
+ end;
+
+ begin
+ firstcomplex(self);
+
+ pass_left_right;
+
+ unsigned:=((left.resultdef.typ=orddef) and
+ (torddef(left.resultdef).ordtype=u64bit)) or
+ ((right.resultdef.typ=orddef) and
+ (torddef(right.resultdef).ordtype=u64bit));
+
+ { left and right no register? }
+ { then one must be demanded }
+ if (left.location.loc<>LOC_REGISTER) then
+ begin
+ if (right.location.loc<>LOC_REGISTER) then
+ begin
+ { we can reuse a CREGISTER for comparison }
+ if (left.location.loc<>LOC_CREGISTER) then
+ begin
+ hregister:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+ hregister2:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+ cg64.a_load64_loc_reg(current_asmdata.CurrAsmList,left.location,joinreg64(hregister,hregister2));
+ location_freetemp(current_asmdata.CurrAsmList,left.location);
+ location_reset(left.location,LOC_REGISTER,left.location.size);
+ left.location.register64.reglo:=hregister;
+ left.location.register64.reghi:=hregister2;
+ end;
+ end
+ else
+ begin
+ location_swap(left.location,right.location);
+ toggleflag(nf_swapped);
+ end;
+ end;
+
+ { at this point, left.location.loc should be LOC_REGISTER }
+ if right.location.loc=LOC_REGISTER then
+ begin
+ emit_reg_reg(A_CMP,S_L,right.location.register64.reghi,left.location.register64.reghi);
+ firstjmp64bitcmp;
+ emit_reg_reg(A_CMP,S_L,right.location.register64.reglo,left.location.register64.reglo);
+ secondjmp64bitcmp;
+ end
+ else
+ begin
+ case right.location.loc of
+ LOC_CREGISTER :
+ begin
+ emit_reg_reg(A_CMP,S_L,right.location.register64.reghi,left.location.register64.reghi);
+ firstjmp64bitcmp;
+ emit_reg_reg(A_CMP,S_L,right.location.register64.reglo,left.location.register64.reglo);
+ secondjmp64bitcmp;
+ end;
+ LOC_CREFERENCE,
+ LOC_REFERENCE :
+ begin
+ tcgx86(cg).make_simple_ref(current_asmdata.CurrAsmList,right.location.reference);
+ href:=right.location.reference;
+ inc(href.offset,4);
+ emit_ref_reg(A_CMP,S_L,href,left.location.register64.reghi);
+ firstjmp64bitcmp;
+ emit_ref_reg(A_CMP,S_L,right.location.reference,left.location.register64.reglo);
+ secondjmp64bitcmp;
+ cg.a_jmp_always(current_asmdata.CurrAsmList,current_procinfo.CurrFalseLabel);
+ location_freetemp(current_asmdata.CurrAsmList,right.location);
+ end;
+ LOC_CONSTANT :
+ begin
+ current_asmdata.CurrAsmList.concat(taicpu.op_const_reg(A_CMP,S_L,aint(hi(right.location.value64)),left.location.register64.reghi));
+ firstjmp64bitcmp;
+ current_asmdata.CurrAsmList.concat(taicpu.op_const_reg(A_CMP,S_L,aint(lo(right.location.value64)),left.location.register64.reglo));
+ secondjmp64bitcmp;
+ end;
+ else
+ internalerror(200203282);
+ end;
+ end;
+
+ { we have LOC_JUMP as result }
+ location_reset(location,LOC_JUMP,OS_NO)
+ end;
+
+
+{*****************************************************************************
+ x86 MUL
+*****************************************************************************}
+
+ procedure ti386addnode.second_mul(unsigned: boolean);
+
+ var reg:Tregister;
+ ref:Treference;
+ use_ref:boolean;
+ hl4 : tasmlabel;
+
+ const
+ asmops: array[boolean] of tasmop = (A_IMUL, A_MUL);
+
+ begin
+ pass_left_right;
+
+ {The location.register will be filled in later (JM)}
+ location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
+ { Mul supports registers and references, so if not register/reference,
+ load the location into a register.
+ The variant of IMUL which is capable of doing 32->64 bits has the same restrictions. }
+ use_ref:=false;
+ if left.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
+ reg:=left.location.register
+ else if left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE] then
+ begin
+ tcgx86(cg).make_simple_ref(current_asmdata.CurrAsmList,left.location.reference);
+ ref:=left.location.reference;
+ use_ref:=true;
+ end
+ else
+ begin
+ {LOC_CONSTANT for example.}
+ reg:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+ cg.a_load_loc_reg(current_asmdata.CurrAsmList,OS_INT,left.location,reg);
+ end;
+ {Allocate EAX.}
+ cg.getcpuregister(current_asmdata.CurrAsmList,NR_EAX);
+ {Load the right value.}
+ cg.a_load_loc_reg(current_asmdata.CurrAsmList,OS_INT,right.location,NR_EAX);
+ {Also allocate EDX, since it is also modified by a mul (JM).}
+ cg.getcpuregister(current_asmdata.CurrAsmList,NR_EDX);
+ if use_ref then
+ emit_ref(asmops[unsigned],S_L,ref)
+ else
+ emit_reg(asmops[unsigned],S_L,reg);
+ if (cs_check_overflow in current_settings.localswitches) and
+ { 32->64 bit cannot overflow }
+ (not is_64bit(resultdef)) then
+ begin
+ current_asmdata.getjumplabel(hl4);
+ cg.a_jmp_flags(current_asmdata.CurrAsmList,F_AE,hl4);
+ cg.a_call_name(current_asmdata.CurrAsmList,'FPC_OVERFLOW',false);
+ cg.a_label(current_asmdata.CurrAsmList,hl4);
+ end;
+ {Free EAX,EDX}
+ cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_EDX);
+ if is_64bit(resultdef) then
+ begin
+ {Allocate a couple of registers and store EDX:EAX into it}
+ location.register64.reghi := cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+ cg.a_load_reg_reg(current_asmdata.CurrAsmList, OS_INT, OS_INT, NR_EDX, location.register64.reghi);
+ cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_EAX);
+ location.register64.reglo := cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+ cg.a_load_reg_reg(current_asmdata.CurrAsmList, OS_INT, OS_INT, NR_EAX, location.register64.reglo);
+ end
+ else
+ begin
+ {Allocate a new register and store the result in EAX in it.}
+ location.register:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+ cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_EAX);
+ cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_INT,OS_INT,NR_EAX,location.register);
+ end;
+ location_freetemp(current_asmdata.CurrAsmList,left.location);
+ location_freetemp(current_asmdata.CurrAsmList,right.location);
+ end;
+
+
+begin
+ caddnode:=ti386addnode;
+end.
diff --git a/closures/compiler/i386/n386cal.pas b/closures/compiler/i386/n386cal.pas
new file mode 100644
index 0000000000..3751c0003c
--- /dev/null
+++ b/closures/compiler/i386/n386cal.pas
@@ -0,0 +1,120 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate i386 assembler for in call nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit n386cal;
+
+{$i fpcdefs.inc}
+
+interface
+
+{ $define AnsiStrRef}
+
+ uses
+ ncgcal;
+
+ type
+ ti386callnode = class(tcgcallnode)
+ protected
+ procedure pop_parasize(pop_size:longint);override;
+ procedure extra_interrupt_code;override;
+ end;
+
+
+implementation
+
+ uses
+ globtype,systems,
+ cutils,verbose,globals,
+ cgbase,cgutils,
+ cpubase,paramgr,
+ aasmtai,aasmdata,aasmcpu,
+ ncal,nbas,nmem,nld,ncnv,
+ cga,cgobj,cpuinfo;
+
+
+{*****************************************************************************
+ TI386CALLNODE
+*****************************************************************************}
+
+
+ procedure ti386callnode.extra_interrupt_code;
+ begin
+ if not(target_info.system in [system_i386_darwin,system_i386_iphonesim]) then
+ begin
+ emit_none(A_PUSHF,S_L);
+ emit_reg(A_PUSH,S_L,NR_CS);
+ end;
+ end;
+
+
+ procedure ti386callnode.pop_parasize(pop_size:longint);
+ var
+ hreg : tregister;
+ begin
+ if (paramanager.use_fixed_stack) then
+ begin
+ { very weird: in this case the callee does a "ret $4" and the }
+ { caller immediately a "subl $4,%esp". Possibly this is for }
+ { use_fixed_stack code to be able to transparently call }
+ { old-style code (JM) }
+ dec(pop_size,pushedparasize);
+ if (pop_size < 0) then
+ current_asmdata.CurrAsmList.concat(taicpu.op_const_reg(A_SUB,S_L,-pop_size,NR_ESP));
+ exit;
+ end;
+
+ { on win32, the caller is responsible for removing the funcret }
+ { pointer from the stack, unlike on Linux. Don't know about }
+ { elsewhere (except Darwin, handled above), but since the default }
+ { was "callee removes funcret pointer from stack" until now, we'll }
+ { keep that default for everyone else (ncgcal decreases popsize by }
+ { sizeof(aint) in case of ret_in_param()) }
+ if (target_info.system = system_i386_win32) and
+ paramanager.ret_in_param(procdefinition.returndef,procdefinition.proccalloption) then
+ inc(pop_size,sizeof(aint));
+
+ { better than an add on all processors }
+ if pop_size=4 then
+ begin
+ hreg:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg(A_POP,S_L,hreg));
+ end
+ { the pentium has two pipes and pop reg is pairable }
+ { but the registers must be different! }
+ else
+ if (pop_size=8) and
+ not(cs_opt_size in current_settings.optimizerswitches) and
+ (current_settings.optimizecputype=cpu_Pentium) then
+ begin
+ hreg:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg(A_POP,S_L,hreg));
+ hreg:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg(A_POP,S_L,hreg));
+ end
+ else
+ if pop_size<>0 then
+ current_asmdata.CurrAsmList.concat(taicpu.op_const_reg(A_ADD,S_L,pop_size,NR_ESP));
+ end;
+
+
+begin
+ ccallnode:=ti386callnode;
+end.
diff --git a/closures/compiler/i386/n386inl.pas b/closures/compiler/i386/n386inl.pas
new file mode 100644
index 0000000000..4c28d2bc8a
--- /dev/null
+++ b/closures/compiler/i386/n386inl.pas
@@ -0,0 +1,42 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate i386 inline nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit n386inl;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ nx86inl;
+
+ type
+ ti386inlinenode = class(tx86inlinenode)
+ end;
+
+implementation
+
+ uses
+ ninl;
+
+begin
+ cinlinenode:=ti386inlinenode;
+end.
diff --git a/closures/compiler/i386/n386mat.pas b/closures/compiler/i386/n386mat.pas
new file mode 100644
index 0000000000..313f7f328d
--- /dev/null
+++ b/closures/compiler/i386/n386mat.pas
@@ -0,0 +1,473 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate i386 assembler for math nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit n386mat;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,nmat,ncgmat,nx86mat;
+
+ type
+ ti386moddivnode = class(tmoddivnode)
+ procedure pass_generate_code;override;
+ end;
+
+ ti386shlshrnode = class(tcgshlshrnode)
+ procedure second_64bit;override;
+ function first_shlshr64bitint: tnode; override;
+ end;
+
+ ti386unaryminusnode = class(tx86unaryminusnode)
+ end;
+
+ ti386notnode = class(tx86notnode)
+ end;
+
+
+implementation
+
+ uses
+ globtype,systems,constexp,
+ cutils,verbose,globals,
+ symconst,symdef,aasmbase,aasmtai,aasmdata,defutil,
+ cgbase,pass_2,
+ ncon,
+ cpubase,cpuinfo,
+ cga,ncgutil,cgobj,cgutils;
+
+{*****************************************************************************
+ TI386MODDIVNODE
+*****************************************************************************}
+
+ function log2(i : dword) : dword;
+ begin
+ result:=0;
+ i:=i shr 1;
+ while i<>0 do
+ begin
+ i:=i shr 1;
+ inc(result);
+ end;
+ end;
+
+
+ procedure ti386moddivnode.pass_generate_code;
+ var
+ hreg1,hreg2:Tregister;
+ power:longint;
+ hl:Tasmlabel;
+ op:Tasmop;
+ e : longint;
+ d,l,r,s,m,a,n,t : dword;
+ m_low,m_high,j,k : qword;
+ begin
+ secondpass(left);
+ if codegenerror then
+ exit;
+ secondpass(right);
+ if codegenerror then
+ exit;
+
+ if is_64bitint(resultdef) then
+ { should be handled in pass_1 (JM) }
+ internalerror(200109052);
+ { put numerator in register }
+ location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
+ location_force_reg(current_asmdata.CurrAsmList,left.location,location.size,false);
+ hreg1:=left.location.register;
+
+ if (nodetype=divn) and (right.nodetype=ordconstn) then
+ begin
+ if ispowerof2(tordconstnode(right).value.svalue,power) then
+ begin
+ { for signed numbers, the numerator must be adjusted before the
+ shift instruction, but not wih unsigned numbers! Otherwise,
+ "Cardinal($ffffffff) div 16" overflows! (JM) }
+ if is_signed(left.resultdef) Then
+ begin
+ if (current_settings.optimizecputype <> cpu_386) and
+ not(cs_opt_size in current_settings.optimizerswitches) then
+ { use a sequence without jumps, saw this in
+ comp.compilers (JM) }
+ begin
+ { no jumps, but more operations }
+ hreg2:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+ emit_reg_reg(A_MOV,S_L,hreg1,hreg2);
+ {If the left value is signed, hreg2=$ffffffff, otherwise 0.}
+ emit_const_reg(A_SAR,S_L,31,hreg2);
+ {If signed, hreg2=right value-1, otherwise 0.}
+ emit_const_reg(A_AND,S_L,tordconstnode(right).value.svalue-1,hreg2);
+ { add to the left value }
+ emit_reg_reg(A_ADD,S_L,hreg2,hreg1);
+ { do the shift }
+ emit_const_reg(A_SAR,S_L,power,hreg1);
+ end
+ else
+ begin
+ { a jump, but less operations }
+ emit_reg_reg(A_TEST,S_L,hreg1,hreg1);
+ current_asmdata.getjumplabel(hl);
+ cg.a_jmp_flags(current_asmdata.CurrAsmList,F_NS,hl);
+ if power=1 then
+ emit_reg(A_INC,S_L,hreg1)
+ else
+ emit_const_reg(A_ADD,S_L,tordconstnode(right).value.svalue-1,hreg1);
+ cg.a_label(current_asmdata.CurrAsmList,hl);
+ emit_const_reg(A_SAR,S_L,power,hreg1);
+ end
+ end
+ else
+ emit_const_reg(A_SHR,S_L,power,hreg1);
+ location.register:=hreg1;
+ end
+ else
+ begin
+ if is_signed(left.resultdef) then
+ begin
+ e:=tordconstnode(right).value.svalue;
+ d:=abs(e);
+ { Determine algorithm (a), multiplier (m), and shift factor (s) for 32-bit
+ signed integer division. Based on: Granlund, T.; Montgomery, P.L.:
+ "Division by Invariant Integers using Multiplication". SIGPLAN Notices,
+ Vol. 29, June 1994, page 61.
+ }
+
+ l:=log2(d);
+ j:=qword($80000000) mod qword(d);
+ k:=(qword(1) shl (32+l)) div (qword($80000000-j));
+ m_low:=((qword(1)) shl (32+l)) div d;
+ m_high:=(((qword(1)) shl (32+l)) + k) div d;
+ while ((m_low shr 1) < (m_high shr 1)) and (l > 0) do
+ begin
+ m_low:=m_low shr 1;
+ m_high:=m_high shr 1;
+ dec(l);
+ end;
+ m:=dword(m_high);
+ s:=l;
+ if (m_high shr 31)<>0 then
+ a:=1
+ else
+ a:=0;
+ cg.getcpuregister(current_asmdata.CurrAsmList,NR_EAX);
+ emit_const_reg(A_MOV,S_L,aint(m),NR_EAX);
+ cg.getcpuregister(current_asmdata.CurrAsmList,NR_EDX);
+ emit_reg(A_IMUL,S_L,hreg1);
+ emit_reg_reg(A_MOV,S_L,hreg1,NR_EAX);
+ if a<>0 then
+ begin
+ emit_reg_reg(A_ADD,S_L,NR_EAX,NR_EDX);
+ {
+ printf ("; dividend: memory location or register other than EAX or EDX\n");
+ printf ("\n");
+ printf ("MOV EAX, 0%08LXh\n", m);
+ printf ("IMUL dividend\n");
+ printf ("MOV EAX, dividend\n");
+ printf ("ADD EDX, EAX\n");
+ if (s) printf ("SAR EDX, %d\n", s);
+ printf ("SHR EAX, 31\n");
+ printf ("ADD EDX, EAX\n");
+ if (e < 0) printf ("NEG EDX\n");
+ printf ("\n");
+ printf ("; quotient now in EDX\n");
+ }
+ end;
+ {
+ printf ("; dividend: memory location of register other than EAX or EDX\n");
+ printf ("\n");
+ printf ("MOV EAX, 0%08LXh\n", m);
+ printf ("IMUL dividend\n");
+ printf ("MOV EAX, dividend\n");
+ if (s) printf ("SAR EDX, %d\n", s);
+ printf ("SHR EAX, 31\n");
+ printf ("ADD EDX, EAX\n");
+ if (e < 0) printf ("NEG EDX\n");
+ printf ("\n");
+ printf ("; quotient now in EDX\n");
+ }
+ if s<>0 then
+ emit_const_reg(A_SAR,S_L,s,NR_EDX);
+ emit_const_reg(A_SHR,S_L,31,NR_EAX);
+ emit_reg_reg(A_ADD,S_L,NR_EAX,NR_EDX);
+ if e<0 then
+ emit_reg(A_NEG,S_L,NR_EDX);
+ cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_EDX);
+ cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_EAX);
+ location.register:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+ cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_INT,OS_INT,NR_EDX,location.register)
+ end
+ else
+ begin
+ d:=tordconstnode(right).value.svalue;
+ if d>=$80000000 then
+ begin
+ emit_const_reg(A_CMP,S_L,aint(d),hreg1);
+ location.register:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+ emit_const_reg(A_MOV,S_L,0,location.register);
+ emit_const_reg(A_SBB,S_L,-1,location.register);
+ end
+ else
+ begin
+ { Reduce divisor until it becomes odd }
+ n:=0;
+ t:=d;
+ while (t and 1)=0 do
+ begin
+ t:=t shr 1;
+ inc(n);
+ end;
+ { Generate m, s for algorithm 0. Based on: Granlund, T.; Montgomery,
+ P.L.: "Division by Invariant Integers using Multiplication".
+ SIGPLAN Notices, Vol. 29, June 1994, page 61.
+ }
+ l:=log2(t)+1;
+ j:=qword($ffffffff) mod qword(t);
+ k:=(qword(1) shl (32+l)) div (qword($ffffffff-j));
+ m_low:=((qword(1)) shl (32+l)) div t;
+ m_high:=(((qword(1)) shl (32+l)) + k) div t;
+ while ((m_low shr 1) < (m_high shr 1)) and (l>0) do
+ begin
+ m_low:=m_low shr 1;
+ m_high:=m_high shr 1;
+ l:=l-1;
+ end;
+ if (m_high shr 32)=0 then
+ begin
+ m:=dword(m_high);
+ s:=l;
+ a:=0;
+ end
+
+ { Generate m, s for algorithm 1. Based on: Magenheimer, D.J.; et al:
+ "Integer Multiplication and Division on the HP Precision Architecture".
+ IEEE Transactions on Computers, Vol 37, No. 8, August 1988, page 980.
+ }
+ else
+ begin
+ s:=log2(t);
+ m_low:=(qword(1) shl (32+s)) div qword(t);
+ r:=dword(((qword(1)) shl (32+s)) mod qword(t));
+ if (r < ((t>>1)+1)) then
+ m:=dword(m_low)
+ else
+ m:=dword(m_low)+1;
+ a:=1;
+ end;
+ { Reduce multiplier for either algorithm to smallest possible }
+ while (m and 1)=0 do
+ begin
+ m:=m shr 1;
+ dec(s);
+ end;
+ { Adjust multiplier for reduction of even divisors }
+ inc(s,n);
+ cg.getcpuregister(current_asmdata.CurrAsmList,NR_EAX);
+ emit_const_reg(A_MOV,S_L,aint(m),NR_EAX);
+ cg.getcpuregister(current_asmdata.CurrAsmList,NR_EDX);
+ emit_reg(A_MUL,S_L,hreg1);
+ if a<>0 then
+ begin
+ {
+ printf ("; dividend: register other than EAX or memory location\n");
+ printf ("\n");
+ printf ("MOV EAX, 0%08lXh\n", m);
+ printf ("MUL dividend\n");
+ printf ("ADD EAX, 0%08lXh\n", m);
+ printf ("ADC EDX, 0\n");
+ if (s) printf ("SHR EDX, %d\n", s);
+ printf ("\n");
+ printf ("; quotient now in EDX\n");
+ }
+ emit_const_reg(A_ADD,S_L,aint(m),NR_EAX);
+ emit_const_reg(A_ADC,S_L,0,NR_EDX);
+ end;
+ if s<>0 then
+ emit_const_reg(A_SHR,S_L,aint(s),NR_EDX);
+ cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_EDX);
+ cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_EAX);
+ location.register:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+ cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_INT,OS_INT,NR_EDX,location.register)
+ end;
+ end
+ end
+ end
+ else
+ begin
+ cg.getcpuregister(current_asmdata.CurrAsmList,NR_EAX);
+ emit_reg_reg(A_MOV,S_L,hreg1,NR_EAX);
+ cg.getcpuregister(current_asmdata.CurrAsmList,NR_EDX);
+ {Sign extension depends on the left type.}
+ if torddef(left.resultdef).ordtype=u32bit then
+ emit_reg_reg(A_XOR,S_L,NR_EDX,NR_EDX)
+ else
+ emit_none(A_CDQ,S_NO);
+
+ {Division depends on the right type.}
+ if Torddef(right.resultdef).ordtype=u32bit then
+ op:=A_DIV
+ else
+ op:=A_IDIV;
+
+ if right.location.loc in [LOC_REFERENCE,LOC_CREFERENCE] then
+ emit_ref(op,S_L,right.location.reference)
+ else if right.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
+ emit_reg(op,S_L,right.location.register)
+ else
+ begin
+ hreg1:=cg.getintregister(current_asmdata.CurrAsmList,right.location.size);
+ cg.a_load_loc_reg(current_asmdata.CurrAsmList,OS_32,right.location,hreg1);
+ emit_reg(op,S_L,hreg1);
+ end;
+
+ {Copy the result into a new register. Release EAX & EDX.}
+ cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_EDX);
+ cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_EAX);
+ location.register:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+ if nodetype=divn then
+ cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_INT,OS_INT,NR_EAX,location.register)
+ else
+ cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_INT,OS_INT,NR_EDX,location.register);
+ end;
+ end;
+
+
+{*****************************************************************************
+ TI386SHLRSHRNODE
+*****************************************************************************}
+
+
+ function ti386shlshrnode.first_shlshr64bitint: tnode;
+ begin
+ result := nil;
+ end;
+
+ procedure ti386shlshrnode.second_64bit;
+ var
+ hreg64hi,hreg64lo:Tregister;
+ v : TConstExprInt;
+ l1,l2,l3:Tasmlabel;
+ begin
+ location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
+
+ { load left operator in a register }
+ location_force_reg(current_asmdata.CurrAsmList,left.location,location.size,false);
+ hreg64hi:=left.location.register64.reghi;
+ hreg64lo:=left.location.register64.reglo;
+
+ { shifting by a constant directly coded: }
+ if (right.nodetype=ordconstn) then
+ begin
+ v:=Tordconstnode(right).value and 63;
+ if v>31 then
+ begin
+ if nodetype=shln then
+ begin
+ emit_reg_reg(A_XOR,S_L,hreg64hi,hreg64hi);
+ if ((v and 31) <> 0) then
+ emit_const_reg(A_SHL,S_L,v.svalue and 31,hreg64lo);
+ end
+ else
+ begin
+ emit_reg_reg(A_XOR,S_L,hreg64lo,hreg64lo);
+ if ((v and 31) <> 0) then
+ emit_const_reg(A_SHR,S_L,v.svalue and 31,hreg64hi);
+ end;
+ location.register64.reghi:=hreg64lo;
+ location.register64.reglo:=hreg64hi;
+ end
+ else
+ begin
+ if nodetype=shln then
+ begin
+ emit_const_reg_reg(A_SHLD,S_L,v.svalue and 31,hreg64lo,hreg64hi);
+ emit_const_reg(A_SHL,S_L,v.svalue and 31,hreg64lo);
+ end
+ else
+ begin
+ emit_const_reg_reg(A_SHRD,S_L,v.svalue and 31,hreg64hi,hreg64lo);
+ emit_const_reg(A_SHR,S_L,v.svalue and 31,hreg64hi);
+ end;
+ location.register64.reglo:=hreg64lo;
+ location.register64.reghi:=hreg64hi;
+ end;
+ end
+ else
+ begin
+ { load right operators in a register }
+ cg.getcpuregister(current_asmdata.CurrAsmList,NR_ECX);
+ cg.a_load_loc_reg(current_asmdata.CurrAsmList,OS_32,right.location,NR_ECX);
+
+ { left operator is already in a register }
+ { hence are both in a register }
+ { is it in the case ECX ? }
+
+ { the damned shift instructions work only til a count of 32 }
+ { so we've to do some tricks here }
+ current_asmdata.getjumplabel(l1);
+ current_asmdata.getjumplabel(l2);
+ current_asmdata.getjumplabel(l3);
+ emit_const_reg(A_CMP,S_L,64,NR_ECX);
+ cg.a_jmp_flags(current_asmdata.CurrAsmList,F_L,l1);
+ emit_reg_reg(A_XOR,S_L,hreg64lo,hreg64lo);
+ emit_reg_reg(A_XOR,S_L,hreg64hi,hreg64hi);
+ cg.a_jmp_always(current_asmdata.CurrAsmList,l3);
+ cg.a_label(current_asmdata.CurrAsmList,l1);
+ emit_const_reg(A_CMP,S_L,32,NR_ECX);
+ cg.a_jmp_flags(current_asmdata.CurrAsmList,F_L,l2);
+ emit_const_reg(A_SUB,S_L,32,NR_ECX);
+ if nodetype=shln then
+ begin
+ emit_reg_reg(A_SHL,S_L,NR_CL,hreg64lo);
+ emit_reg_reg(A_MOV,S_L,hreg64lo,hreg64hi);
+ emit_reg_reg(A_XOR,S_L,hreg64lo,hreg64lo);
+ cg.a_jmp_always(current_asmdata.CurrAsmList,l3);
+ cg.a_label(current_asmdata.CurrAsmList,l2);
+ emit_reg_reg_reg(A_SHLD,S_L,NR_CL,hreg64lo,hreg64hi);
+ emit_reg_reg(A_SHL,S_L,NR_CL,hreg64lo);
+ end
+ else
+ begin
+ emit_reg_reg(A_SHR,S_L,NR_CL,hreg64hi);
+ emit_reg_reg(A_MOV,S_L,hreg64hi,hreg64lo);
+ emit_reg_reg(A_XOR,S_L,hreg64hi,hreg64hi);
+ cg.a_jmp_always(current_asmdata.CurrAsmList,l3);
+ cg.a_label(current_asmdata.CurrAsmList,l2);
+ emit_reg_reg_reg(A_SHRD,S_L,NR_CL,hreg64hi,hreg64lo);
+ emit_reg_reg(A_SHR,S_L,NR_CL,hreg64hi);
+ end;
+ cg.a_label(current_asmdata.CurrAsmList,l3);
+
+ cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_ECX);
+ location.register64.reglo:=hreg64lo;
+ location.register64.reghi:=hreg64hi;
+ end;
+ end;
+
+
+begin
+ cunaryminusnode:=ti386unaryminusnode;
+ cmoddivnode:=ti386moddivnode;
+ cshlshrnode:=ti386shlshrnode;
+ cnotnode:=ti386notnode;
+end.
diff --git a/closures/compiler/i386/n386mem.pas b/closures/compiler/i386/n386mem.pas
new file mode 100644
index 0000000000..fc9fb07853
--- /dev/null
+++ b/closures/compiler/i386/n386mem.pas
@@ -0,0 +1,98 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate i386 assembler for in memory related nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit n386mem;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ globtype,
+ cgbase,cpuinfo,cpubase,
+ node,nmem,ncgmem,nx86mem;
+
+ type
+ ti386addrnode = class(tcgaddrnode)
+ procedure pass_generate_code;override;
+ end;
+
+ ti386derefnode = class(tcgderefnode)
+ procedure pass_generate_code;override;
+ end;
+
+ ti386vecnode = class(tx86vecnode)
+ procedure pass_generate_code;override;
+ end;
+
+implementation
+
+ uses
+ systems,
+ cutils,verbose,
+ symdef,paramgr,
+ aasmtai,aasmdata,
+ nld,ncon,nadd,
+ cgutils,cgobj;
+
+{*****************************************************************************
+ TI386ADDRNODE
+*****************************************************************************}
+
+ procedure ti386addrnode.pass_generate_code;
+
+ begin
+ inherited pass_generate_code;
+ { for use of other segments, not used }
+ {if left.location.reference.segment<>NR_NO then
+ location.segment:=left.location.reference.segment;}
+ end;
+
+
+{*****************************************************************************
+ TI386DEREFNODE
+*****************************************************************************}
+
+ procedure ti386derefnode.pass_generate_code;
+ begin
+ inherited pass_generate_code;
+ if tpointerdef(left.resultdef).is_far then
+ location.reference.segment:=NR_FS;
+ end;
+
+
+{*****************************************************************************
+ TI386VECNODE
+*****************************************************************************}
+
+ procedure ti386vecnode.pass_generate_code;
+ begin
+ inherited pass_generate_code;
+ if nf_memseg in flags then
+ location.reference.segment:=NR_FS;
+ end;
+
+
+begin
+ caddrnode:=ti386addrnode;
+ cderefnode:=ti386derefnode;
+ cvecnode:=ti386vecnode;
+end.
diff --git a/closures/compiler/i386/n386set.pas b/closures/compiler/i386/n386set.pas
new file mode 100644
index 0000000000..e5ee719752
--- /dev/null
+++ b/closures/compiler/i386/n386set.pas
@@ -0,0 +1,73 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate i386 assembler for in set/case nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit n386set;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ globtype,
+ node,nset,pass_1,nx86set;
+
+ type
+ ti386casenode = class(tx86casenode)
+ procedure optimizevalues(var max_linear_list:aint;var max_dist:aword);override;
+ end;
+
+
+implementation
+
+ uses
+ systems,
+ verbose,globals,constexp,
+ symconst,symdef,defutil,
+ aasmbase,aasmtai,aasmdata,aasmcpu,
+ cgbase,pass_2,
+ ncon,
+ cpubase,cpuinfo,procinfo,
+ cga,cgutils,cgobj,ncgutil,
+ cgx86;
+
+
+{*****************************************************************************
+ TI386CASENODE
+*****************************************************************************}
+
+ procedure ti386casenode.optimizevalues(var max_linear_list:aint;var max_dist:aword);
+ begin
+ { a jump table crashes the pipeline! }
+ if current_settings.optimizecputype=cpu_386 then
+ inc(max_linear_list,3)
+ else if current_settings.optimizecputype=cpu_Pentium then
+ inc(max_linear_list,6)
+ else if current_settings.optimizecputype in [cpu_Pentium2,cpu_Pentium3] then
+ inc(max_linear_list,9)
+ else if current_settings.optimizecputype=cpu_Pentium4 then
+ inc(max_linear_list,14);
+ end;
+
+
+
+begin
+ ccasenode:=ti386casenode;
+end.
diff --git a/closures/compiler/i386/popt386.pas b/closures/compiler/i386/popt386.pas
new file mode 100644
index 0000000000..a7bbfe0434
--- /dev/null
+++ b/closures/compiler/i386/popt386.pas
@@ -0,0 +1,2262 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl and Jonas Maebe
+
+ This unit contains the peephole optimizer.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit popt386;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses Aasmbase,aasmtai,aasmdata,aasmcpu,verbose;
+
+procedure PrePeepHoleOpts(asml: TAsmList; BlockStart, BlockEnd: tai);
+procedure PeepHoleOptPass1(asml: TAsmList; BlockStart, BlockEnd: tai);
+procedure PeepHoleOptPass2(asml: TAsmList; BlockStart, BlockEnd: tai);
+procedure PostPeepHoleOpts(asml: TAsmList; BlockStart, BlockEnd: tai);
+
+implementation
+
+uses
+ globtype,systems,
+ globals,cgbase,procinfo,
+ symsym,
+{$ifdef finaldestdebug}
+ cobjects,
+{$endif finaldestdebug}
+ cpuinfo,cpubase,cgutils,daopt386;
+
+
+function isFoldableArithOp(hp1: taicpu; reg: tregister): boolean;
+begin
+ isFoldableArithOp := False;
+ case hp1.opcode of
+ A_ADD,A_SUB,A_OR,A_XOR,A_AND,A_SHL,A_SHR,A_SAR:
+ isFoldableArithOp :=
+ ((taicpu(hp1).oper[0]^.typ = top_const) or
+ ((taicpu(hp1).oper[0]^.typ = top_reg) and
+ (taicpu(hp1).oper[0]^.reg <> reg))) and
+ (taicpu(hp1).oper[1]^.typ = top_reg) and
+ (taicpu(hp1).oper[1]^.reg = reg);
+ A_INC,A_DEC:
+ isFoldableArithOp :=
+ (taicpu(hp1).oper[0]^.typ = top_reg) and
+ (taicpu(hp1).oper[0]^.reg = reg);
+ end;
+end;
+
+
+function RegUsedAfterInstruction(reg: Tregister; p: tai; var UsedRegs: TRegSet): Boolean;
+var
+ supreg: tsuperregister;
+begin
+ supreg := getsupreg(reg);
+ UpdateUsedRegs(UsedRegs, tai(p.Next));
+ RegUsedAfterInstruction :=
+ (supreg in UsedRegs) and
+ (not(getNextInstruction(p,p)) or
+ not(regLoadedWithNewValue(supreg,false,p)));
+end;
+
+
+function doFpuLoadStoreOpt(asmL: TAsmList; var p: tai): boolean;
+{ returns true if a "continue" should be done after this optimization }
+var hp1, hp2: tai;
+begin
+ doFpuLoadStoreOpt := false;
+ if (taicpu(p).oper[0]^.typ = top_ref) and
+ getNextInstruction(p, hp1) and
+ (hp1.typ = ait_instruction) and
+ (((taicpu(hp1).opcode = A_FLD) and
+ (taicpu(p).opcode = A_FSTP)) or
+ ((taicpu(p).opcode = A_FISTP) and
+ (taicpu(hp1).opcode = A_FILD))) and
+ (taicpu(hp1).oper[0]^.typ = top_ref) and
+ (taicpu(hp1).opsize = taicpu(p).opsize) and
+ refsEqual(taicpu(p).oper[0]^.ref^, taicpu(hp1).oper[0]^.ref^) then
+ begin
+ { replacing fstp f;fld f by fst f is only valid for extended because of rounding }
+ if (taicpu(p).opsize=S_FX) and
+ getNextInstruction(hp1, hp2) and
+ (hp2.typ = ait_instruction) and
+ ((taicpu(hp2).opcode = A_LEAVE) or
+ (taicpu(hp2).opcode = A_RET)) and
+ (taicpu(p).oper[0]^.ref^.base = current_procinfo.FramePointer) and
+ not(assigned(current_procinfo.procdef.funcretsym) and
+ (taicpu(p).oper[0]^.ref^.offset < tabstractnormalvarsym(current_procinfo.procdef.funcretsym).localloc.reference.offset)) and
+ (taicpu(p).oper[0]^.ref^.index = NR_NO) then
+ begin
+ asml.remove(p);
+ asml.remove(hp1);
+ p.free;
+ hp1.free;
+ p := hp2;
+ removeLastDeallocForFuncRes(asmL, p);
+ doFPULoadStoreOpt := true;
+ end
+ (* can't be done because the store operation rounds
+ else
+ { fst can't store an extended value! }
+ if (taicpu(p).opsize <> S_FX) and
+ (taicpu(p).opsize <> S_IQ) then
+ begin
+ if (taicpu(p).opcode = A_FSTP) then
+ taicpu(p).opcode := A_FST
+ else taicpu(p).opcode := A_FIST;
+ asml.remove(hp1);
+ hp1.free;
+ end
+ *)
+ end;
+end;
+
+
+{ returns true if p contains a memory operand with a segment set }
+function InsContainsSegRef(p: taicpu): boolean;
+var
+ i: longint;
+begin
+ result:=true;
+ for i:=0 to p.opercnt-1 do
+ if (p.oper[i]^.typ=top_ref) and
+ (p.oper[i]^.ref^.segment<>NR_NO) then
+ exit;
+ result:=false;
+end;
+
+
+procedure PrePeepHoleOpts(asml: TAsmList; BlockStart, BlockEnd: tai);
+var
+ p,hp1: tai;
+ l: aint;
+ tmpRef: treference;
+begin
+ p := BlockStart;
+ while (p <> BlockEnd) Do
+ begin
+ case p.Typ Of
+ Ait_Instruction:
+ begin
+ if InsContainsSegRef(taicpu(p)) then
+ begin
+ p := tai(p.next);
+ continue;
+ end;
+ case taicpu(p).opcode Of
+ A_IMUL:
+ {changes certain "imul const, %reg"'s to lea sequences}
+ begin
+ if (taicpu(p).oper[0]^.typ = Top_Const) and
+ (taicpu(p).oper[1]^.typ = Top_Reg) and
+ (taicpu(p).opsize = S_L) then
+ if (taicpu(p).oper[0]^.val = 1) then
+ if (taicpu(p).ops = 2) then
+ {remove "imul $1, reg"}
+ begin
+ hp1 := tai(p.Next);
+ asml.remove(p);
+ p.free;
+ p := hp1;
+ continue;
+ end
+ else
+ {change "imul $1, reg1, reg2" to "mov reg1, reg2"}
+ begin
+ hp1 := taicpu.Op_Reg_Reg(A_MOV, S_L, taicpu(p).oper[1]^.reg,taicpu(p).oper[2]^.reg);
+ InsertLLItem(asml, p.previous, p.next, hp1);
+ p.free;
+ p := hp1;
+ end
+ else if
+ ((taicpu(p).ops <= 2) or
+ (taicpu(p).oper[2]^.typ = Top_Reg)) and
+ (taicpu(p).oper[0]^.val <= 12) and
+ not(cs_opt_size in current_settings.optimizerswitches) and
+ (not(GetNextInstruction(p, hp1)) or
+ {GetNextInstruction(p, hp1) and}
+ not((tai(hp1).typ = ait_instruction) and
+ ((taicpu(hp1).opcode=A_Jcc) and
+ (taicpu(hp1).condition in [C_O,C_NO])))) then
+ begin
+ reference_reset(tmpref,1);
+ case taicpu(p).oper[0]^.val Of
+ 3: begin
+ {imul 3, reg1, reg2 to
+ lea (reg1,reg1,2), reg2
+ imul 3, reg1 to
+ lea (reg1,reg1,2), reg1}
+ TmpRef.base := taicpu(p).oper[1]^.reg;
+ TmpRef.index := taicpu(p).oper[1]^.reg;
+ TmpRef.ScaleFactor := 2;
+ if (taicpu(p).ops = 2) then
+ hp1 := taicpu.op_ref_reg(A_LEA, S_L, TmpRef, taicpu(p).oper[1]^.reg)
+ else
+ hp1 := taicpu.op_ref_reg(A_LEA, S_L, TmpRef, taicpu(p).oper[2]^.reg);
+ InsertLLItem(asml,p.previous, p.next, hp1);
+ p.free;
+ p := hp1;
+ end;
+ 5: begin
+ {imul 5, reg1, reg2 to
+ lea (reg1,reg1,4), reg2
+ imul 5, reg1 to
+ lea (reg1,reg1,4), reg1}
+ TmpRef.base := taicpu(p).oper[1]^.reg;
+ TmpRef.index := taicpu(p).oper[1]^.reg;
+ TmpRef.ScaleFactor := 4;
+ if (taicpu(p).ops = 2) then
+ hp1 := taicpu.op_ref_reg(A_LEA, S_L, TmpRef, taicpu(p).oper[1]^.reg)
+ else
+ hp1 := taicpu.op_ref_reg(A_LEA, S_L, TmpRef, taicpu(p).oper[2]^.reg);
+ InsertLLItem(asml,p.previous, p.next, hp1);
+ p.free;
+ p := hp1;
+ end;
+ 6: begin
+ {imul 6, reg1, reg2 to
+ lea (,reg1,2), reg2
+ lea (reg2,reg1,4), reg2
+ imul 6, reg1 to
+ lea (reg1,reg1,2), reg1
+ add reg1, reg1}
+ if (current_settings.optimizecputype <= cpu_386) then
+ begin
+ TmpRef.index := taicpu(p).oper[1]^.reg;
+ if (taicpu(p).ops = 3) then
+ begin
+ TmpRef.base := taicpu(p).oper[2]^.reg;
+ TmpRef.ScaleFactor := 4;
+ hp1 := taicpu.op_ref_reg(A_LEA, S_L, TmpRef, taicpu(p).oper[1]^.reg);
+ end
+ else
+ begin
+ hp1 := taicpu.op_reg_reg(A_ADD, S_L,
+ taicpu(p).oper[1]^.reg,taicpu(p).oper[1]^.reg);
+ end;
+ InsertLLItem(asml,p, p.next, hp1);
+ reference_reset(tmpref,2);
+ TmpRef.index := taicpu(p).oper[1]^.reg;
+ TmpRef.ScaleFactor := 2;
+ if (taicpu(p).ops = 3) then
+ begin
+ TmpRef.base := NR_NO;
+ hp1 := taicpu.op_ref_reg(A_LEA, S_L, TmpRef,
+ taicpu(p).oper[2]^.reg);
+ end
+ else
+ begin
+ TmpRef.base := taicpu(p).oper[1]^.reg;
+ hp1 := taicpu.op_ref_reg(A_LEA, S_L, TmpRef, taicpu(p).oper[1]^.reg);
+ end;
+ InsertLLItem(asml,p.previous, p.next, hp1);
+ p.free;
+ p := tai(hp1.next);
+ end
+ end;
+ 9: begin
+ {imul 9, reg1, reg2 to
+ lea (reg1,reg1,8), reg2
+ imul 9, reg1 to
+ lea (reg1,reg1,8), reg1}
+ TmpRef.base := taicpu(p).oper[1]^.reg;
+ TmpRef.index := taicpu(p).oper[1]^.reg;
+ TmpRef.ScaleFactor := 8;
+ if (taicpu(p).ops = 2) then
+ hp1 := taicpu.op_ref_reg(A_LEA, S_L, TmpRef, taicpu(p).oper[1]^.reg)
+ else
+ hp1 := taicpu.op_ref_reg(A_LEA, S_L, TmpRef, taicpu(p).oper[2]^.reg);
+ InsertLLItem(asml,p.previous, p.next, hp1);
+ p.free;
+ p := hp1;
+ end;
+ 10: begin
+ {imul 10, reg1, reg2 to
+ lea (reg1,reg1,4), reg2
+ add reg2, reg2
+ imul 10, reg1 to
+ lea (reg1,reg1,4), reg1
+ add reg1, reg1}
+ if (current_settings.optimizecputype <= cpu_386) then
+ begin
+ if (taicpu(p).ops = 3) then
+ hp1 := taicpu.op_reg_reg(A_ADD, S_L,
+ taicpu(p).oper[2]^.reg,taicpu(p).oper[2]^.reg)
+ else
+ hp1 := taicpu.op_reg_reg(A_ADD, S_L,
+ taicpu(p).oper[1]^.reg,taicpu(p).oper[1]^.reg);
+ InsertLLItem(asml,p, p.next, hp1);
+ TmpRef.base := taicpu(p).oper[1]^.reg;
+ TmpRef.index := taicpu(p).oper[1]^.reg;
+ TmpRef.ScaleFactor := 4;
+ if (taicpu(p).ops = 3) then
+ hp1 := taicpu.op_ref_reg(A_LEA, S_L, TmpRef, taicpu(p).oper[2]^.reg)
+ else
+ hp1 := taicpu.op_ref_reg(A_LEA, S_L, TmpRef, taicpu(p).oper[1]^.reg);
+ InsertLLItem(asml,p.previous, p.next, hp1);
+ p.free;
+ p := tai(hp1.next);
+ end
+ end;
+ 12: begin
+ {imul 12, reg1, reg2 to
+ lea (,reg1,4), reg2
+ lea (,reg1,8) reg2
+ imul 12, reg1 to
+ lea (reg1,reg1,2), reg1
+ lea (,reg1,4), reg1}
+ if (current_settings.optimizecputype <= cpu_386)
+ then
+ begin
+ TmpRef.index := taicpu(p).oper[1]^.reg;
+ if (taicpu(p).ops = 3) then
+ begin
+ TmpRef.base := taicpu(p).oper[2]^.reg;
+ TmpRef.ScaleFactor := 8;
+ hp1 := taicpu.op_ref_reg(A_LEA, S_L, TmpRef, taicpu(p).oper[2]^.reg);
+ end
+ else
+ begin
+ TmpRef.base := NR_NO;
+ TmpRef.ScaleFactor := 4;
+ hp1 := taicpu.op_ref_reg(A_LEA, S_L, TmpRef, taicpu(p).oper[1]^.reg);
+ end;
+ InsertLLItem(asml,p, p.next, hp1);
+ reference_reset(tmpref,2);
+ TmpRef.index := taicpu(p).oper[1]^.reg;
+ if (taicpu(p).ops = 3) then
+ begin
+ TmpRef.base := NR_NO;
+ TmpRef.ScaleFactor := 4;
+ hp1 := taicpu.op_ref_reg(A_LEA, S_L, TmpRef, taicpu(p).oper[2]^.reg);
+ end
+ else
+ begin
+ TmpRef.base := taicpu(p).oper[1]^.reg;
+ TmpRef.ScaleFactor := 2;
+ hp1 := taicpu.op_ref_reg(A_LEA, S_L, TmpRef, taicpu(p).oper[1]^.reg);
+ end;
+ InsertLLItem(asml,p.previous, p.next, hp1);
+ p.free;
+ p := tai(hp1.next);
+ end
+ end
+ end;
+ end;
+ end;
+ A_SAR, A_SHR:
+ {changes the code sequence
+ shr/sar const1, x
+ shl const2, x
+ to either "sar/and", "shl/and" or just "and" depending on const1 and const2}
+ begin
+ if GetNextInstruction(p, hp1) and
+ (tai(hp1).typ = ait_instruction) and
+ (taicpu(hp1).opcode = A_SHL) and
+ (taicpu(p).oper[0]^.typ = top_const) and
+ (taicpu(hp1).oper[0]^.typ = top_const) and
+ (taicpu(hp1).opsize = taicpu(p).opsize) and
+ (taicpu(hp1).oper[1]^.typ = taicpu(p).oper[1]^.typ) and
+ OpsEqual(taicpu(hp1).oper[1]^, taicpu(p).oper[1]^) then
+ if (taicpu(p).oper[0]^.val > taicpu(hp1).oper[0]^.val) and
+ not(cs_opt_size in current_settings.optimizerswitches) then
+ { shr/sar const1, %reg
+ shl const2, %reg
+ with const1 > const2 }
+ begin
+ taicpu(p).loadConst(0,taicpu(p).oper[0]^.val-taicpu(hp1).oper[0]^.val);
+ taicpu(hp1).opcode := A_AND;
+ l := (1 shl (taicpu(hp1).oper[0]^.val)) - 1;
+ case taicpu(p).opsize Of
+ S_L: taicpu(hp1).loadConst(0,l Xor aint($ffffffff));
+ S_B: taicpu(hp1).loadConst(0,l Xor $ff);
+ S_W: taicpu(hp1).loadConst(0,l Xor $ffff);
+ end;
+ end
+ else if (taicpu(p).oper[0]^.val<taicpu(hp1).oper[0]^.val) and
+ not(cs_opt_size in current_settings.optimizerswitches) then
+ { shr/sar const1, %reg
+ shl const2, %reg
+ with const1 < const2 }
+ begin
+ taicpu(hp1).loadConst(0,taicpu(hp1).oper[0]^.val-taicpu(p).oper[0]^.val);
+ taicpu(p).opcode := A_AND;
+ l := (1 shl (taicpu(p).oper[0]^.val))-1;
+ case taicpu(p).opsize Of
+ S_L: taicpu(p).loadConst(0,l Xor aint($ffffffff));
+ S_B: taicpu(p).loadConst(0,l Xor $ff);
+ S_W: taicpu(p).loadConst(0,l Xor $ffff);
+ end;
+ end
+ else
+ { shr/sar const1, %reg
+ shl const2, %reg
+ with const1 = const2 }
+ if (taicpu(p).oper[0]^.val = taicpu(hp1).oper[0]^.val) then
+ begin
+ taicpu(p).opcode := A_AND;
+ l := (1 shl (taicpu(p).oper[0]^.val))-1;
+ case taicpu(p).opsize Of
+ S_B: taicpu(p).loadConst(0,l Xor $ff);
+ S_W: taicpu(p).loadConst(0,l Xor $ffff);
+ S_L: taicpu(p).loadConst(0,l Xor aint($ffffffff));
+ end;
+ asml.remove(hp1);
+ hp1.free;
+ end;
+ end;
+ A_XOR:
+ if (taicpu(p).oper[0]^.typ = top_reg) and
+ (taicpu(p).oper[1]^.typ = top_reg) and
+ (taicpu(p).oper[0]^.reg = taicpu(p).oper[1]^.reg) then
+ { temporarily change this to 'mov reg,0' to make it easier }
+ { for the CSE. Will be changed back in pass 2 }
+ begin
+ taicpu(p).opcode := A_MOV;
+ taicpu(p).loadConst(0,0);
+ end;
+ end;
+ end;
+ end;
+ p := tai(p.next)
+ end;
+end;
+
+
+
+procedure PeepHoleOptPass1(Asml: TAsmList; BlockStart, BlockEnd: tai);
+{First pass of peepholeoptimizations}
+
+var
+ l : longint;
+ p,hp1,hp2 : tai;
+ hp3,hp4: tai;
+ v:aint;
+
+ TmpRef: TReference;
+
+ UsedRegs, TmpUsedRegs: TRegSet;
+
+ TmpBool1, TmpBool2: Boolean;
+
+ function SkipLabels(hp: tai; var hp2: tai): boolean;
+ {skips all labels and returns the next "real" instruction}
+ begin
+ while assigned(hp.next) and
+ (tai(hp.next).typ in SkipInstr + [ait_label,ait_align]) Do
+ hp := tai(hp.next);
+ if assigned(hp.next) then
+ begin
+ SkipLabels := True;
+ hp2 := tai(hp.next)
+ end
+ else
+ begin
+ hp2 := hp;
+ SkipLabels := False
+ end;
+ end;
+
+ function GetFinalDestination(asml: TAsmList; hp: taicpu; level: longint): boolean;
+ {traces sucessive jumps to their final destination and sets it, e.g.
+ je l1 je l3
+ <code> <code>
+ l1: becomes l1:
+ je l2 je l3
+ <code> <code>
+ l2: l2:
+ jmp l3 jmp l3
+
+ the level parameter denotes how deeep we have already followed the jump,
+ to avoid endless loops with constructs such as "l5: ; jmp l5" }
+
+ var p1, p2: tai;
+ l: tasmlabel;
+
+ function FindAnyLabel(hp: tai; var l: tasmlabel): Boolean;
+ begin
+ FindAnyLabel := false;
+ while assigned(hp.next) and
+ (tai(hp.next).typ in (SkipInstr+[ait_align])) Do
+ hp := tai(hp.next);
+ if assigned(hp.next) and
+ (tai(hp.next).typ = ait_label) then
+ begin
+ FindAnyLabel := true;
+ l := tai_label(hp.next).labsym;
+ end
+ end;
+
+ begin
+ GetfinalDestination := false;
+ if level > 20 then
+ exit;
+ p1 := dfa.getlabelwithsym(tasmlabel(hp.oper[0]^.ref^.symbol));
+ if assigned(p1) then
+ begin
+ SkipLabels(p1,p1);
+ if (tai(p1).typ = ait_instruction) and
+ (taicpu(p1).is_jmp) then
+ if { the next instruction after the label where the jump hp arrives}
+ { is unconditional or of the same type as hp, so continue }
+ (taicpu(p1).condition in [C_None,hp.condition]) or
+ { the next instruction after the label where the jump hp arrives}
+ { is the opposite of hp (so this one is never taken), but after }
+ { that one there is a branch that will be taken, so perform a }
+ { little hack: set p1 equal to this instruction (that's what the}
+ { last SkipLabels is for, only works with short bool evaluation)}
+ ((taicpu(p1).condition = inverse_cond(hp.condition)) and
+ SkipLabels(p1,p2) and
+ (p2.typ = ait_instruction) and
+ (taicpu(p2).is_jmp) and
+ (taicpu(p2).condition in [C_None,hp.condition]) and
+ SkipLabels(p1,p1)) then
+ begin
+ { quick check for loops of the form "l5: ; jmp l5 }
+ if (tasmlabel(taicpu(p1).oper[0]^.ref^.symbol).labelnr =
+ tasmlabel(hp.oper[0]^.ref^.symbol).labelnr) then
+ exit;
+ if not GetFinalDestination(asml, taicpu(p1),succ(level)) then
+ exit;
+ tasmlabel(hp.oper[0]^.ref^.symbol).decrefs;
+ hp.oper[0]^.ref^.symbol:=taicpu(p1).oper[0]^.ref^.symbol;
+ tasmlabel(hp.oper[0]^.ref^.symbol).increfs;
+ end
+ else
+ if (taicpu(p1).condition = inverse_cond(hp.condition)) then
+ if not FindAnyLabel(p1,l) then
+ begin
+ {$ifdef finaldestdebug}
+ insertllitem(asml,p1,p1.next,tai_comment.Create(
+ strpnew('previous label inserted'))));
+ {$endif finaldestdebug}
+ current_asmdata.getjumplabel(l);
+ insertllitem(asml,p1,p1.next,tai_label.Create(l));
+ tasmlabel(taicpu(hp).oper[0]^.ref^.symbol).decrefs;
+ hp.oper[0]^.ref^.symbol := l;
+ l.increfs;
+ { this won't work, since the new label isn't in the labeltable }
+ { so it will fail the rangecheck. Labeltable should become a }
+ { hashtable to support this: }
+ { GetFinalDestination(asml, hp); }
+ end
+ else
+ begin
+ {$ifdef finaldestdebug}
+ insertllitem(asml,p1,p1.next,tai_comment.Create(
+ strpnew('next label reused'))));
+ {$endif finaldestdebug}
+ l.increfs;
+ hp.oper[0]^.ref^.symbol := l;
+ if not GetFinalDestination(asml, hp,succ(level)) then
+ exit;
+ end;
+ end;
+ GetFinalDestination := true;
+ end;
+
+ function DoSubAddOpt(var p: tai): Boolean;
+ begin
+ DoSubAddOpt := False;
+ if GetLastInstruction(p, hp1) and
+ (hp1.typ = ait_instruction) and
+ (taicpu(hp1).opsize = taicpu(p).opsize) then
+ case taicpu(hp1).opcode Of
+ A_DEC:
+ if (taicpu(hp1).oper[0]^.typ = top_reg) and
+ (taicpu(hp1).oper[0]^.reg = taicpu(p).oper[1]^.reg) then
+ begin
+ taicpu(p).loadConst(0,taicpu(p).oper[0]^.val+1);
+ asml.remove(hp1);
+ hp1.free;
+ end;
+ A_SUB:
+ if (taicpu(hp1).oper[0]^.typ = top_const) and
+ (taicpu(hp1).oper[1]^.typ = top_reg) and
+ (taicpu(hp1).oper[1]^.reg = taicpu(p).oper[1]^.reg) then
+ begin
+ taicpu(p).loadConst(0,taicpu(p).oper[0]^.val+taicpu(hp1).oper[0]^.val);
+ asml.remove(hp1);
+ hp1.free;
+ end;
+ A_ADD:
+ if (taicpu(hp1).oper[0]^.typ = top_const) and
+ (taicpu(hp1).oper[1]^.typ = top_reg) and
+ (taicpu(hp1).oper[1]^.reg = taicpu(p).oper[1]^.reg) then
+ begin
+ taicpu(p).loadConst(0,taicpu(p).oper[0]^.val-taicpu(hp1).oper[0]^.val);
+ asml.remove(hp1);
+ hp1.free;
+ if (taicpu(p).oper[0]^.val = 0) then
+ begin
+ hp1 := tai(p.next);
+ asml.remove(p);
+ p.free;
+ if not GetLastInstruction(hp1, p) then
+ p := hp1;
+ DoSubAddOpt := True;
+ end
+ end;
+ end;
+ end;
+
+begin
+ p := BlockStart;
+ UsedRegs := [];
+ while (p <> BlockEnd) Do
+ begin
+ UpDateUsedRegs(UsedRegs, tai(p.next));
+ case p.Typ Of
+ ait_instruction:
+ begin
+ if InsContainsSegRef(taicpu(p)) then
+ begin
+ p := tai(p.next);
+ continue;
+ end;
+ { Handle Jmp Optimizations }
+ if taicpu(p).is_jmp then
+ begin
+ {the following if-block removes all code between a jmp and the next label,
+ because it can never be executed}
+ if (taicpu(p).opcode = A_JMP) then
+ begin
+ while GetNextInstruction(p, hp1) and
+ (hp1.typ <> ait_label) do
+ if not(hp1.typ in ([ait_label,ait_align]+skipinstr)) then
+ begin
+ asml.remove(hp1);
+ hp1.free;
+ end
+ else break;
+ end;
+ { remove jumps to a label coming right after them }
+ if GetNextInstruction(p, hp1) then
+ begin
+ if FindLabel(tasmlabel(taicpu(p).oper[0]^.ref^.symbol), hp1) and
+ { TODO: FIXME removing the first instruction fails}
+ (p<>blockstart) then
+ begin
+ hp2:=tai(hp1.next);
+ asml.remove(p);
+ p.free;
+ p:=hp2;
+ continue;
+ end
+ else
+ begin
+ if hp1.typ = ait_label then
+ SkipLabels(hp1,hp1);
+ if (tai(hp1).typ=ait_instruction) and
+ (taicpu(hp1).opcode=A_JMP) and
+ GetNextInstruction(hp1, hp2) and
+ FindLabel(tasmlabel(taicpu(p).oper[0]^.ref^.symbol), hp2) then
+ begin
+ if taicpu(p).opcode=A_Jcc then
+ begin
+ taicpu(p).condition:=inverse_cond(taicpu(p).condition);
+ tai_label(hp2).labsym.decrefs;
+ taicpu(p).oper[0]^.ref^.symbol:=taicpu(hp1).oper[0]^.ref^.symbol;
+ { when free'ing hp1, the ref. isn't decresed, so we don't
+ increase it (FK)
+
+ taicpu(p).oper[0]^.ref^.symbol.increfs;
+ }
+ asml.remove(hp1);
+ hp1.free;
+ GetFinalDestination(asml, taicpu(p),0);
+ end
+ else
+ begin
+ GetFinalDestination(asml, taicpu(p),0);
+ p:=tai(p.next);
+ continue;
+ end;
+ end
+ else
+ GetFinalDestination(asml, taicpu(p),0);
+ end;
+ end;
+ end
+ else
+ { All other optimizes }
+ begin
+ for l := 0 to taicpu(p).ops-1 Do
+ if (taicpu(p).oper[l]^.typ = top_ref) then
+ With taicpu(p).oper[l]^.ref^ Do
+ begin
+ if (base = NR_NO) and
+ (index <> NR_NO) and
+ (scalefactor in [0,1]) then
+ begin
+ base := index;
+ index := NR_NO
+ end
+ end;
+ case taicpu(p).opcode Of
+ A_AND:
+ begin
+ if (taicpu(p).oper[0]^.typ = top_const) and
+ (taicpu(p).oper[1]^.typ = top_reg) and
+ GetNextInstruction(p, hp1) and
+ (tai(hp1).typ = ait_instruction) and
+ (taicpu(hp1).opcode = A_AND) and
+ (taicpu(hp1).oper[0]^.typ = top_const) and
+ (taicpu(hp1).oper[1]^.typ = top_reg) and
+ (getsupreg(taicpu(p).oper[1]^.reg)=getsupreg(taicpu(hp1).oper[1]^.reg)) and
+ (getsubreg(taicpu(p).oper[1]^.reg)<=getsubreg(taicpu(hp1).oper[1]^.reg)) then
+ {change "and const1, reg; and const2, reg" to "and (const1 and const2), reg"}
+ begin
+ taicpu(hp1).loadConst(0,taicpu(p).oper[0]^.val and taicpu(hp1).oper[0]^.val);
+ asml.remove(p);
+ p.free;
+ p:=hp1;
+ end
+ else
+ {change "and x, reg; jxx" to "test x, reg", if reg is deallocated before the
+ jump, but only if it's a conditional jump (PFV) }
+ if (taicpu(p).oper[1]^.typ = top_reg) and
+ GetNextInstruction(p, hp1) and
+ (hp1.typ = ait_instruction) and
+ (taicpu(hp1).is_jmp) and
+ (taicpu(hp1).opcode<>A_JMP) and
+ not(getsupreg(taicpu(p).oper[1]^.reg) in UsedRegs) then
+ taicpu(p).opcode := A_TEST;
+ end;
+ A_CMP:
+ begin
+ { cmp register,$8000 neg register
+ je target --> jo target
+
+ .... only if register is deallocated before jump.}
+ case Taicpu(p).opsize of
+ S_B: v:=$80;
+ S_W: v:=$8000;
+ S_L: v:=aint($80000000);
+ end;
+ if (taicpu(p).oper[0]^.typ=Top_const) and
+ (taicpu(p).oper[0]^.val=v) and
+ (Taicpu(p).oper[1]^.typ=top_reg) and
+ GetNextInstruction(p, hp1) and
+ (hp1.typ=ait_instruction) and
+ (taicpu(hp1).opcode=A_Jcc) and
+ (Taicpu(hp1).condition in [C_E,C_NE]) and
+ not(getsupreg(Taicpu(p).oper[1]^.reg) in usedregs) then
+ begin
+ Taicpu(p).opcode:=A_NEG;
+ Taicpu(p).loadoper(0,Taicpu(p).oper[1]^);
+ Taicpu(p).clearop(1);
+ Taicpu(p).ops:=1;
+ if Taicpu(hp1).condition=C_E then
+ Taicpu(hp1).condition:=C_O
+ else
+ Taicpu(hp1).condition:=C_NO;
+ continue;
+ end;
+ {
+ @@2: @@2:
+ .... ....
+ cmp operand1,0
+ jle/jbe @@1
+ dec operand1 --> sub operand1,1
+ jmp @@2 jge/jae @@2
+ @@1: @@1:
+ ... ....}
+ if (taicpu(p).oper[0]^.typ = top_const) and
+ (taicpu(p).oper[1]^.typ in [top_reg,top_ref]) and
+ (taicpu(p).oper[0]^.val = 0) and
+ GetNextInstruction(p, hp1) and
+ (hp1.typ = ait_instruction) and
+ (taicpu(hp1).is_jmp) and
+ (taicpu(hp1).opcode=A_Jcc) and
+ (taicpu(hp1).condition in [C_LE,C_BE]) and
+ GetNextInstruction(hp1,hp2) and
+ (hp2.typ = ait_instruction) and
+ (taicpu(hp2).opcode = A_DEC) and
+ OpsEqual(taicpu(hp2).oper[0]^,taicpu(p).oper[1]^) and
+ GetNextInstruction(hp2, hp3) and
+ (hp3.typ = ait_instruction) and
+ (taicpu(hp3).is_jmp) and
+ (taicpu(hp3).opcode = A_JMP) and
+ GetNextInstruction(hp3, hp4) and
+ FindLabel(tasmlabel(taicpu(hp1).oper[0]^.ref^.symbol),hp4) then
+ begin
+ taicpu(hp2).Opcode := A_SUB;
+ taicpu(hp2).loadoper(1,taicpu(hp2).oper[0]^);
+ taicpu(hp2).loadConst(0,1);
+ taicpu(hp2).ops:=2;
+ taicpu(hp3).Opcode := A_Jcc;
+ case taicpu(hp1).condition of
+ C_LE: taicpu(hp3).condition := C_GE;
+ C_BE: taicpu(hp3).condition := C_AE;
+ end;
+ asml.remove(p);
+ asml.remove(hp1);
+ p.free;
+ hp1.free;
+ p := hp2;
+ continue;
+ end
+ end;
+ A_FLD:
+ begin
+ if (taicpu(p).oper[0]^.typ = top_reg) and
+ GetNextInstruction(p, hp1) and
+ (hp1.typ = Ait_Instruction) and
+ (taicpu(hp1).oper[0]^.typ = top_reg) and
+ (taicpu(hp1).oper[1]^.typ = top_reg) and
+ (taicpu(hp1).oper[0]^.reg = NR_ST) and
+ (taicpu(hp1).oper[1]^.reg = NR_ST1) then
+ { change to
+ fld reg fxxx reg,st
+ fxxxp st, st1 (hp1)
+ Remark: non commutative operations must be reversed!
+ }
+ begin
+ case taicpu(hp1).opcode Of
+ A_FMULP,A_FADDP,
+ A_FSUBP,A_FDIVP,A_FSUBRP,A_FDIVRP:
+ begin
+ case taicpu(hp1).opcode Of
+ A_FADDP: taicpu(hp1).opcode := A_FADD;
+ A_FMULP: taicpu(hp1).opcode := A_FMUL;
+ A_FSUBP: taicpu(hp1).opcode := A_FSUBR;
+ A_FSUBRP: taicpu(hp1).opcode := A_FSUB;
+ A_FDIVP: taicpu(hp1).opcode := A_FDIVR;
+ A_FDIVRP: taicpu(hp1).opcode := A_FDIV;
+ end;
+ taicpu(hp1).oper[0]^.reg := taicpu(p).oper[0]^.reg;
+ taicpu(hp1).oper[1]^.reg := NR_ST;
+ asml.remove(p);
+ p.free;
+ p := hp1;
+ continue;
+ end;
+ end;
+ end
+ else
+ if (taicpu(p).oper[0]^.typ = top_ref) and
+ GetNextInstruction(p, hp2) and
+ (hp2.typ = Ait_Instruction) and
+ (taicpu(hp2).ops = 2) and
+ (taicpu(hp2).oper[0]^.typ = top_reg) and
+ (taicpu(hp2).oper[1]^.typ = top_reg) and
+ (taicpu(p).opsize in [S_FS, S_FL]) and
+ (taicpu(hp2).oper[0]^.reg = NR_ST) and
+ (taicpu(hp2).oper[1]^.reg = NR_ST1) then
+ if GetLastInstruction(p, hp1) and
+ (hp1.typ = Ait_Instruction) and
+ ((taicpu(hp1).opcode = A_FLD) or
+ (taicpu(hp1).opcode = A_FST)) and
+ (taicpu(hp1).opsize = taicpu(p).opsize) and
+ (taicpu(hp1).oper[0]^.typ = top_ref) and
+ RefsEqual(taicpu(p).oper[0]^.ref^, taicpu(hp1).oper[0]^.ref^) then
+ if ((taicpu(hp2).opcode = A_FMULP) or
+ (taicpu(hp2).opcode = A_FADDP)) then
+ { change to
+ fld/fst mem1 (hp1) fld/fst mem1
+ fld mem1 (p) fadd/
+ faddp/ fmul st, st
+ fmulp st, st1 (hp2) }
+ begin
+ asml.remove(p);
+ p.free;
+ p := hp1;
+ if (taicpu(hp2).opcode = A_FADDP) then
+ taicpu(hp2).opcode := A_FADD
+ else
+ taicpu(hp2).opcode := A_FMUL;
+ taicpu(hp2).oper[1]^.reg := NR_ST;
+ end
+ else
+ { change to
+ fld/fst mem1 (hp1) fld/fst mem1
+ fld mem1 (p) fld st}
+ begin
+ taicpu(p).changeopsize(S_FL);
+ taicpu(p).loadreg(0,NR_ST);
+ end
+ else
+ begin
+ case taicpu(hp2).opcode Of
+ A_FMULP,A_FADDP,A_FSUBP,A_FDIVP,A_FSUBRP,A_FDIVRP:
+ { change to
+ fld/fst mem1 (hp1) fld/fst mem1
+ fld mem2 (p) fxxx mem2
+ fxxxp st, st1 (hp2) }
+
+ begin
+ case taicpu(hp2).opcode Of
+ A_FADDP: taicpu(p).opcode := A_FADD;
+ A_FMULP: taicpu(p).opcode := A_FMUL;
+ A_FSUBP: taicpu(p).opcode := A_FSUBR;
+ A_FSUBRP: taicpu(p).opcode := A_FSUB;
+ A_FDIVP: taicpu(p).opcode := A_FDIVR;
+ A_FDIVRP: taicpu(p).opcode := A_FDIV;
+ end;
+ asml.remove(hp2);
+ hp2.free;
+ end
+ end
+ end
+ end;
+ A_FSTP,A_FISTP:
+ if doFpuLoadStoreOpt(asmL,p) then
+ continue;
+ A_LEA:
+ begin
+ {removes seg register prefixes from LEA operations, as they
+ don't do anything}
+ taicpu(p).oper[0]^.ref^.Segment := NR_NO;
+ {changes "lea (%reg1), %reg2" into "mov %reg1, %reg2"}
+ if (taicpu(p).oper[0]^.ref^.base <> NR_NO) and
+ (getsupreg(taicpu(p).oper[0]^.ref^.base) in [RS_EAX..RS_ESP]) and
+ (taicpu(p).oper[0]^.ref^.index = NR_NO) and
+ (not(Assigned(taicpu(p).oper[0]^.ref^.Symbol))) then
+ if (taicpu(p).oper[0]^.ref^.base <> taicpu(p).oper[1]^.reg) and
+ (taicpu(p).oper[0]^.ref^.offset = 0) then
+ begin
+ hp1 := taicpu.op_reg_reg(A_MOV, S_L,taicpu(p).oper[0]^.ref^.base,
+ taicpu(p).oper[1]^.reg);
+ InsertLLItem(asml,p.previous,p.next, hp1);
+ p.free;
+ p := hp1;
+ continue;
+ end
+ else if (taicpu(p).oper[0]^.ref^.offset = 0) then
+ begin
+ hp1 := tai(p.Next);
+ asml.remove(p);
+ p.free;
+ p := hp1;
+ continue;
+ end
+ else
+ with taicpu(p).oper[0]^.ref^ do
+ if (base = taicpu(p).oper[1]^.reg) then
+ begin
+ l := offset;
+ if (l=1) then
+ begin
+ taicpu(p).opcode := A_INC;
+ taicpu(p).loadreg(0,taicpu(p).oper[1]^.reg);
+ taicpu(p).ops := 1
+ end
+ else if (l=-1) then
+ begin
+ taicpu(p).opcode := A_DEC;
+ taicpu(p).loadreg(0,taicpu(p).oper[1]^.reg);
+ taicpu(p).ops := 1;
+ end
+ else
+ begin
+ taicpu(p).opcode := A_ADD;
+ taicpu(p).loadConst(0,l);
+ end;
+ end;
+ end;
+ A_MOV:
+ begin
+ TmpUsedRegs := UsedRegs;
+ if (taicpu(p).oper[1]^.typ = top_reg) and
+ (getsupreg(taicpu(p).oper[1]^.reg) in [RS_EAX, RS_EBX, RS_ECX, RS_EDX, RS_ESI, RS_EDI]) and
+ GetNextInstruction(p, hp1) and
+ (tai(hp1).typ = ait_instruction) and
+ (taicpu(hp1).opcode = A_MOV) and
+ (taicpu(hp1).oper[0]^.typ = top_reg) and
+ (taicpu(hp1).oper[0]^.reg = taicpu(p).oper[1]^.reg) then
+ begin
+ {we have "mov x, %treg; mov %treg, y}
+ if not(RegUsedAfterInstruction(taicpu(p).oper[1]^.reg, hp1, TmpUsedRegs)) then
+ {we've got "mov x, %treg; mov %treg, y; with %treg is not used after }
+ case taicpu(p).oper[0]^.typ Of
+ top_reg:
+ begin
+ { change "mov %reg, %treg; mov %treg, y"
+ to "mov %reg, y" }
+ taicpu(p).loadOper(1,taicpu(hp1).oper[1]^);
+ asml.remove(hp1);
+ hp1.free;
+ continue;
+ end;
+ top_ref:
+ if (taicpu(hp1).oper[1]^.typ = top_reg) then
+ begin
+ { change "mov mem, %treg; mov %treg, %reg"
+ to "mov mem, %reg" }
+ taicpu(p).loadoper(1,taicpu(hp1).oper[1]^);
+ asml.remove(hp1);
+ hp1.free;
+ continue;
+ end;
+ end
+ end
+ else
+ {Change "mov %reg1, %reg2; xxx %reg2, ???" to
+ "mov %reg1, %reg2; xxx %reg1, ???" to avoid a write/read
+ penalty}
+ if (taicpu(p).oper[0]^.typ = top_reg) and
+ (taicpu(p).oper[1]^.typ = top_reg) and
+ GetNextInstruction(p,hp1) and
+ (tai(hp1).typ = ait_instruction) and
+ (taicpu(hp1).ops >= 1) and
+ (taicpu(hp1).oper[0]^.typ = top_reg) and
+ (taicpu(hp1).oper[0]^.reg = taicpu(p).oper[1]^.reg) then
+ {we have "mov %reg1, %reg2; XXX %reg2, ???"}
+ begin
+ if ((taicpu(hp1).opcode = A_OR) or
+ (taicpu(hp1).opcode = A_TEST)) and
+ (taicpu(hp1).oper[1]^.typ = top_reg) and
+ (taicpu(hp1).oper[0]^.reg = taicpu(hp1).oper[1]^.reg) then
+ {we have "mov %reg1, %reg2; test/or %reg2, %reg2"}
+ begin
+ TmpUsedRegs := UsedRegs;
+ { reg1 will be used after the first instruction, }
+ { so update the allocation info }
+ allocRegBetween(asmL,taicpu(p).oper[0]^.reg,p,hp1,usedregs);
+ if GetNextInstruction(hp1, hp2) and
+ (hp2.typ = ait_instruction) and
+ taicpu(hp2).is_jmp and
+ not(RegUsedAfterInstruction(taicpu(hp1).oper[0]^.reg, hp1, TmpUsedRegs)) then
+ { change "mov %reg1, %reg2; test/or %reg2, %reg2; jxx" to
+ "test %reg1, %reg1; jxx" }
+ begin
+ taicpu(hp1).loadoper(0,taicpu(p).oper[0]^);
+ taicpu(hp1).loadoper(1,taicpu(p).oper[0]^);
+ asml.remove(p);
+ p.free;
+ p := hp1;
+ continue
+ end
+ else
+ {change "mov %reg1, %reg2; test/or %reg2, %reg2" to
+ "mov %reg1, %reg2; test/or %reg1, %reg1"}
+ begin
+ taicpu(hp1).loadoper(0,taicpu(p).oper[0]^);
+ taicpu(hp1).loadoper(1,taicpu(p).oper[0]^);
+ end;
+ end
+{ else
+ if (taicpu(p.next)^.opcode
+ in [A_PUSH, A_OR, A_XOR, A_AND, A_TEST])}
+ {change "mov %reg1, %reg2; push/or/xor/... %reg2, ???" to
+ "mov %reg1, %reg2; push/or/xor/... %reg1, ???"}
+ end
+ else
+ {leave out the mov from "mov reg, x(%frame_pointer); leave/ret" (with
+ x >= RetOffset) as it doesn't do anything (it writes either to a
+ parameter or to the temporary storage room for the function
+ result)}
+ if GetNextInstruction(p, hp1) and
+ (tai(hp1).typ = ait_instruction) then
+ if ((taicpu(hp1).opcode = A_LEAVE) or
+ (taicpu(hp1).opcode = A_RET)) and
+ (taicpu(p).oper[1]^.typ = top_ref) and
+ (taicpu(p).oper[1]^.ref^.base = current_procinfo.FramePointer) and
+ not(assigned(current_procinfo.procdef.funcretsym) and
+ (taicpu(p).oper[1]^.ref^.offset < tabstractnormalvarsym(current_procinfo.procdef.funcretsym).localloc.reference.offset)) and
+ (taicpu(p).oper[1]^.ref^.index = NR_NO) and
+ (taicpu(p).oper[0]^.typ = top_reg) then
+ begin
+ asml.remove(p);
+ p.free;
+ p := hp1;
+ RemoveLastDeallocForFuncRes(asmL,p);
+ end
+ else
+ if (taicpu(p).oper[0]^.typ = top_reg) and
+ (taicpu(p).oper[1]^.typ = top_ref) and
+ (taicpu(p).opsize = taicpu(hp1).opsize) and
+ (taicpu(hp1).opcode = A_CMP) and
+ (taicpu(hp1).oper[1]^.typ = top_ref) and
+ RefsEqual(taicpu(p).oper[1]^.ref^, taicpu(hp1).oper[1]^.ref^) then
+ {change "mov reg1, mem1; cmp x, mem1" to "mov reg, mem1; cmp x, reg1"}
+ begin
+ taicpu(hp1).loadreg(1,taicpu(p).oper[0]^.reg);
+ allocRegBetween(asmL,taicpu(p).oper[0]^.reg,p,hp1,usedregs);
+ end;
+ { Next instruction is also a MOV ? }
+ if GetNextInstruction(p, hp1) and
+ (tai(hp1).typ = ait_instruction) and
+ (taicpu(hp1).opcode = A_MOV) and
+ (taicpu(hp1).opsize = taicpu(p).opsize) then
+ begin
+ if (taicpu(hp1).oper[0]^.typ = taicpu(p).oper[1]^.typ) and
+ (taicpu(hp1).oper[1]^.typ = taicpu(p).oper[0]^.typ) then
+ {mov reg1, mem1 or mov mem1, reg1
+ mov mem2, reg2 mov reg2, mem2}
+ begin
+ if OpsEqual(taicpu(hp1).oper[1]^,taicpu(p).oper[0]^) then
+ {mov reg1, mem1 or mov mem1, reg1
+ mov mem2, reg1 mov reg2, mem1}
+ begin
+ if OpsEqual(taicpu(hp1).oper[0]^,taicpu(p).oper[1]^) then
+ { Removes the second statement from
+ mov reg1, mem1/reg2
+ mov mem1/reg2, reg1 }
+ begin
+ if (taicpu(p).oper[0]^.typ = top_reg) then
+ AllocRegBetween(asmL,taicpu(p).oper[0]^.reg,p,hp1,usedregs);
+ asml.remove(hp1);
+ hp1.free;
+ end
+ else
+ begin
+ TmpUsedRegs := UsedRegs;
+ UpdateUsedRegs(TmpUsedRegs, tai(hp1.next));
+ if (taicpu(p).oper[1]^.typ = top_ref) and
+ { mov reg1, mem1
+ mov mem2, reg1 }
+ (taicpu(hp1).oper[0]^.ref^.refaddr = addr_no) and
+ GetNextInstruction(hp1, hp2) and
+ (hp2.typ = ait_instruction) and
+ (taicpu(hp2).opcode = A_CMP) and
+ (taicpu(hp2).opsize = taicpu(p).opsize) and
+ (taicpu(hp2).oper[0]^.typ = TOp_Ref) and
+ (taicpu(hp2).oper[1]^.typ = TOp_Reg) and
+ RefsEqual(taicpu(hp2).oper[0]^.ref^, taicpu(p).oper[1]^.ref^) and
+ (taicpu(hp2).oper[1]^.reg= taicpu(p).oper[0]^.reg) and
+ not(RegUsedAfterInstruction(taicpu(p).oper[0]^.reg, hp2, TmpUsedRegs)) then
+ { change to
+ mov reg1, mem1 mov reg1, mem1
+ mov mem2, reg1 cmp reg1, mem2
+ cmp mem1, reg1 }
+ begin
+ asml.remove(hp2);
+ hp2.free;
+ taicpu(hp1).opcode := A_CMP;
+ taicpu(hp1).loadref(1,taicpu(hp1).oper[0]^.ref^);
+ taicpu(hp1).loadreg(0,taicpu(p).oper[0]^.reg);
+ end;
+ end;
+ end
+ else
+ begin
+ tmpUsedRegs := UsedRegs;
+ if GetNextInstruction(hp1, hp2) and
+ (taicpu(p).oper[0]^.typ = top_ref) and
+ (taicpu(p).oper[1]^.typ = top_reg) and
+ (taicpu(hp1).oper[0]^.typ = top_reg) and
+ (taicpu(hp1).oper[0]^.reg = taicpu(p).oper[1]^.reg) and
+ (taicpu(hp1).oper[1]^.typ = top_ref) and
+ (tai(hp2).typ = ait_instruction) and
+ (taicpu(hp2).opcode = A_MOV) and
+ (taicpu(hp2).opsize = taicpu(p).opsize) and
+ (taicpu(hp2).oper[1]^.typ = top_reg) and
+ (taicpu(hp2).oper[0]^.typ = top_ref) and
+ RefsEqual(taicpu(hp2).oper[0]^.ref^, taicpu(hp1).oper[1]^.ref^) then
+ if not regInRef(getsupreg(taicpu(hp2).oper[1]^.reg),taicpu(hp2).oper[0]^.ref^) and
+ not(RegUsedAfterInstruction(taicpu(p).oper[1]^.reg,hp1,tmpUsedRegs)) then
+ { mov mem1, %reg1
+ mov %reg1, mem2
+ mov mem2, reg2
+ to:
+ mov mem1, reg2
+ mov reg2, mem2}
+ begin
+ AllocRegBetween(asmL,taicpu(hp2).oper[1]^.reg,p,hp2,usedregs);
+ taicpu(p).loadoper(1,taicpu(hp2).oper[1]^);
+ taicpu(hp1).loadoper(0,taicpu(hp2).oper[1]^);
+ asml.remove(hp2);
+ hp2.free;
+ end
+ else
+ if (taicpu(p).oper[1]^.reg <> taicpu(hp2).oper[1]^.reg) and
+ not(RegInRef(getsupreg(taicpu(p).oper[1]^.reg),taicpu(p).oper[0]^.ref^)) and
+ not(RegInRef(getsupreg(taicpu(hp2).oper[1]^.reg),taicpu(hp2).oper[0]^.ref^)) then
+ { mov mem1, reg1 mov mem1, reg1
+ mov reg1, mem2 mov reg1, mem2
+ mov mem2, reg2 mov mem2, reg1
+ to: to:
+ mov mem1, reg1 mov mem1, reg1
+ mov mem1, reg2 mov reg1, mem2
+ mov reg1, mem2
+
+ or (if mem1 depends on reg1
+ and/or if mem2 depends on reg2)
+ to:
+ mov mem1, reg1
+ mov reg1, mem2
+ mov reg1, reg2
+ }
+ begin
+ taicpu(hp1).loadRef(0,taicpu(p).oper[0]^.ref^);
+ taicpu(hp1).loadReg(1,taicpu(hp2).oper[1]^.reg);
+ taicpu(hp2).loadRef(1,taicpu(hp2).oper[0]^.ref^);
+ taicpu(hp2).loadReg(0,taicpu(p).oper[1]^.reg);
+ allocRegBetween(asmL,taicpu(p).oper[1]^.reg,p,hp2,usedregs);
+ if (taicpu(p).oper[0]^.ref^.base <> NR_NO) and
+ (getsupreg(taicpu(p).oper[0]^.ref^.base) in [RS_EAX,RS_EBX,RS_ECX,RS_EDX,RS_ESI,RS_EDI]) then
+ allocRegBetween(asmL,taicpu(p).oper[0]^.ref^.base,p,hp2,usedregs);
+ if (taicpu(p).oper[0]^.ref^.index <> NR_NO) and
+ (getsupreg(taicpu(p).oper[0]^.ref^.index) in [RS_EAX,RS_EBX,RS_ECX,RS_EDX,RS_ESI,RS_EDI]) then
+ allocRegBetween(asmL,taicpu(p).oper[0]^.ref^.index,p,hp2,usedregs);
+ end
+ else
+ if (taicpu(hp1).Oper[0]^.reg <> taicpu(hp2).Oper[1]^.reg) then
+ begin
+ taicpu(hp2).loadReg(0,taicpu(hp1).Oper[0]^.reg);
+ allocRegBetween(asmL,taicpu(p).oper[1]^.reg,p,hp2,usedregs);
+ end
+ else
+ begin
+ asml.remove(hp2);
+ hp2.free;
+ end
+ end
+ end
+ else
+(* {movl [mem1],reg1
+ movl [mem1],reg2
+ to:
+ movl [mem1],reg1
+ movl reg1,reg2 }
+ if (taicpu(p).oper[0]^.typ = top_ref) and
+ (taicpu(p).oper[1]^.typ = top_reg) and
+ (taicpu(hp1).oper[0]^.typ = top_ref) and
+ (taicpu(hp1).oper[1]^.typ = top_reg) and
+ (taicpu(p).opsize = taicpu(hp1).opsize) and
+ RefsEqual(TReference(taicpu(p).oper[0]^^),taicpu(hp1).oper[0]^^.ref^) and
+ (taicpu(p).oper[1]^.reg<>taicpu(hp1).oper[0]^^.ref^.base) and
+ (taicpu(p).oper[1]^.reg<>taicpu(hp1).oper[0]^^.ref^.index) then
+ taicpu(hp1).loadReg(0,taicpu(p).oper[1]^.reg)
+ else*)
+ { movl const1,[mem1]
+ movl [mem1],reg1
+ to:
+ movl const1,reg1
+ movl reg1,[mem1] }
+ if (taicpu(p).oper[0]^.typ = top_const) and
+ (taicpu(p).oper[1]^.typ = top_ref) and
+ (taicpu(hp1).oper[0]^.typ = top_ref) and
+ (taicpu(hp1).oper[1]^.typ = top_reg) and
+ (taicpu(p).opsize = taicpu(hp1).opsize) and
+ RefsEqual(taicpu(hp1).oper[0]^.ref^,taicpu(p).oper[1]^.ref^) and
+ not(reginref(getsupreg(taicpu(hp1).oper[1]^.reg),taicpu(hp1).oper[0]^.ref^)) then
+ begin
+ allocregbetween(asml,taicpu(hp1).oper[1]^.reg,p,hp1,usedregs);
+ taicpu(hp1).loadReg(0,taicpu(hp1).oper[1]^.reg);
+ taicpu(hp1).loadRef(1,taicpu(p).oper[1]^.ref^);
+ taicpu(p).loadReg(1,taicpu(hp1).oper[0]^.reg);
+ end
+ end;
+ if GetNextInstruction(p, hp1) and
+ (Tai(hp1).typ = ait_instruction) and
+ ((Taicpu(hp1).opcode = A_BTS) or (Taicpu(hp1).opcode = A_BTR)) and
+ (Taicpu(hp1).opsize = Taicpu(p).opsize) and
+ GetNextInstruction(hp1, hp2) and
+ (Tai(hp2).typ = ait_instruction) and
+ (Taicpu(hp2).opcode = A_OR) and
+ (Taicpu(hp1).opsize = Taicpu(p).opsize) and
+ (Taicpu(hp2).opsize = Taicpu(p).opsize) and
+ (Taicpu(p).oper[0]^.typ = top_const) and (Taicpu(p).oper[0]^.val=0) and
+ (Taicpu(p).oper[1]^.typ = top_reg) and
+ (Taicpu(hp1).oper[1]^.typ = top_reg) and
+ (Taicpu(p).oper[1]^.reg=Taicpu(hp1).oper[1]^.reg) and
+ (Taicpu(hp2).oper[1]^.typ = top_reg) and
+ (Taicpu(p).oper[1]^.reg=Taicpu(hp2).oper[1]^.reg) then
+ {mov reg1,0
+ bts reg1,operand1 --> mov reg1,operand2
+ or reg1,operand2 bts reg1,operand1}
+ begin
+ Taicpu(hp2).opcode:=A_MOV;
+ asml.remove(hp1);
+ insertllitem(asml,hp2,hp2.next,hp1);
+ asml.remove(p);
+ p.free;
+ end;
+ end;
+
+ A_MOVSX,
+ A_MOVZX :
+ begin
+ if (taicpu(p).oper[1]^.typ = top_reg) and
+ GetNextInstruction(p,hp1) and
+ (hp1.typ = ait_instruction) and
+ IsFoldableArithOp(taicpu(hp1),taicpu(p).oper[1]^.reg) and
+ (getsupreg(taicpu(hp1).oper[0]^.reg) in [RS_EAX, RS_EBX, RS_ECX, RS_EDX]) and
+ GetNextInstruction(hp1,hp2) and
+ (hp2.typ = ait_instruction) and
+ (taicpu(hp2).opcode = A_MOV) and
+ (taicpu(hp2).oper[0]^.typ = top_reg) and
+ OpsEqual(taicpu(hp2).oper[1]^,taicpu(p).oper[0]^) then
+ { change movsX/movzX reg/ref, reg2 }
+ { add/sub/or/... reg3/$const, reg2 }
+ { mov reg2 reg/ref }
+ { to add/sub/or/... reg3/$const, reg/ref }
+ begin
+ { by example:
+ movswl %si,%eax movswl %si,%eax p
+ decl %eax addl %edx,%eax hp1
+ movw %ax,%si movw %ax,%si hp2
+ ->
+ movswl %si,%eax movswl %si,%eax p
+ decw %eax addw %edx,%eax hp1
+ movw %ax,%si movw %ax,%si hp2
+ }
+ taicpu(hp1).changeopsize(taicpu(hp2).opsize);
+ {
+ ->
+ movswl %si,%eax movswl %si,%eax p
+ decw %si addw %dx,%si hp1
+ movw %ax,%si movw %ax,%si hp2
+ }
+ case taicpu(hp1).ops of
+ 1:
+ taicpu(hp1).loadoper(0,taicpu(hp2).oper[1]^);
+ 2:
+ begin
+ taicpu(hp1).loadoper(1,taicpu(hp2).oper[1]^);
+ if (taicpu(hp1).oper[0]^.typ = top_reg) then
+ setsubreg(taicpu(hp1).oper[0]^.reg,getsubreg(taicpu(hp2).oper[0]^.reg));
+ end;
+ else
+ internalerror(2008042701);
+ end;
+ {
+ ->
+ decw %si addw %dx,%si p
+ }
+ asml.remove(p);
+ asml.remove(hp2);
+ p.free;
+ hp2.free;
+ p := hp1
+ end
+ { removes superfluous And's after movzx's }
+ else if taicpu(p).opcode=A_MOVZX then
+ begin
+ if (taicpu(p).oper[1]^.typ = top_reg) and
+ GetNextInstruction(p, hp1) and
+ (tai(hp1).typ = ait_instruction) and
+ (taicpu(hp1).opcode = A_AND) and
+ (taicpu(hp1).oper[0]^.typ = top_const) and
+ (taicpu(hp1).oper[1]^.typ = top_reg) and
+ (taicpu(hp1).oper[1]^.reg = taicpu(p).oper[1]^.reg) then
+ case taicpu(p).opsize Of
+ S_BL, S_BW:
+ if (taicpu(hp1).oper[0]^.val = $ff) then
+ begin
+ asml.remove(hp1);
+ hp1.free;
+ end;
+ S_WL:
+ if (taicpu(hp1).oper[0]^.val = $ffff) then
+ begin
+ asml.remove(hp1);
+ hp1.free;
+ end;
+ end;
+ {changes some movzx constructs to faster synonims (all examples
+ are given with eax/ax, but are also valid for other registers)}
+ if (taicpu(p).oper[1]^.typ = top_reg) then
+ if (taicpu(p).oper[0]^.typ = top_reg) then
+ case taicpu(p).opsize of
+ S_BW:
+ begin
+ if (getsupreg(taicpu(p).oper[0]^.reg)=getsupreg(taicpu(p).oper[1]^.reg)) and
+ not(cs_opt_size in current_settings.optimizerswitches) then
+ {Change "movzbw %al, %ax" to "andw $0x0ffh, %ax"}
+ begin
+ taicpu(p).opcode := A_AND;
+ taicpu(p).changeopsize(S_W);
+ taicpu(p).loadConst(0,$ff);
+ end
+ else if GetNextInstruction(p, hp1) and
+ (tai(hp1).typ = ait_instruction) and
+ (taicpu(hp1).opcode = A_AND) and
+ (taicpu(hp1).oper[0]^.typ = top_const) and
+ (taicpu(hp1).oper[1]^.typ = top_reg) and
+ (taicpu(hp1).oper[1]^.reg = taicpu(p).oper[1]^.reg) then
+ {Change "movzbw %reg1, %reg2; andw $const, %reg2"
+ to "movw %reg1, reg2; andw $(const1 and $ff), %reg2"}
+ begin
+ taicpu(p).opcode := A_MOV;
+ taicpu(p).changeopsize(S_W);
+ setsubreg(taicpu(p).oper[0]^.reg,R_SUBW);
+ taicpu(hp1).loadConst(0,taicpu(hp1).oper[0]^.val and $ff);
+ end;
+ end;
+ S_BL:
+ begin
+ if (getsupreg(taicpu(p).oper[0]^.reg)=getsupreg(taicpu(p).oper[1]^.reg)) and
+ not(cs_opt_size in current_settings.optimizerswitches) then
+ {Change "movzbl %al, %eax" to "andl $0x0ffh, %eax"}
+ begin
+ taicpu(p).opcode := A_AND;
+ taicpu(p).changeopsize(S_L);
+ taicpu(p).loadConst(0,$ff)
+ end
+ else if GetNextInstruction(p, hp1) and
+ (tai(hp1).typ = ait_instruction) and
+ (taicpu(hp1).opcode = A_AND) and
+ (taicpu(hp1).oper[0]^.typ = top_const) and
+ (taicpu(hp1).oper[1]^.typ = top_reg) and
+ (taicpu(hp1).oper[1]^.reg = taicpu(p).oper[1]^.reg) then
+ {Change "movzbl %reg1, %reg2; andl $const, %reg2"
+ to "movl %reg1, reg2; andl $(const1 and $ff), %reg2"}
+ begin
+ taicpu(p).opcode := A_MOV;
+ taicpu(p).changeopsize(S_L);
+ setsubreg(taicpu(p).oper[0]^.reg,R_SUBWHOLE);
+ taicpu(hp1).loadConst(0,taicpu(hp1).oper[0]^.val and $ff);
+ end
+ end;
+ S_WL:
+ begin
+ if (getsupreg(taicpu(p).oper[0]^.reg)=getsupreg(taicpu(p).oper[1]^.reg)) and
+ not(cs_opt_size in current_settings.optimizerswitches) then
+ {Change "movzwl %ax, %eax" to "andl $0x0ffffh, %eax"}
+ begin
+ taicpu(p).opcode := A_AND;
+ taicpu(p).changeopsize(S_L);
+ taicpu(p).loadConst(0,$ffff);
+ end
+ else if GetNextInstruction(p, hp1) and
+ (tai(hp1).typ = ait_instruction) and
+ (taicpu(hp1).opcode = A_AND) and
+ (taicpu(hp1).oper[0]^.typ = top_const) and
+ (taicpu(hp1).oper[1]^.typ = top_reg) and
+ (taicpu(hp1).oper[1]^.reg = taicpu(p).oper[1]^.reg) then
+ {Change "movzwl %reg1, %reg2; andl $const, %reg2"
+ to "movl %reg1, reg2; andl $(const1 and $ffff), %reg2"}
+ begin
+ taicpu(p).opcode := A_MOV;
+ taicpu(p).changeopsize(S_L);
+ setsubreg(taicpu(p).oper[0]^.reg,R_SUBWHOLE);
+ taicpu(hp1).loadConst(0,taicpu(hp1).oper[0]^.val and $ffff);
+ end;
+ end;
+ end
+ else if (taicpu(p).oper[0]^.typ = top_ref) then
+ begin
+ if GetNextInstruction(p, hp1) and
+ (tai(hp1).typ = ait_instruction) and
+ (taicpu(hp1).opcode = A_AND) and
+ (taicpu(hp1).oper[0]^.typ = Top_Const) and
+ (taicpu(hp1).oper[1]^.typ = Top_Reg) and
+ (taicpu(hp1).oper[1]^.reg = taicpu(p).oper[1]^.reg) then
+ begin
+ taicpu(p).opcode := A_MOV;
+ case taicpu(p).opsize Of
+ S_BL:
+ begin
+ taicpu(p).changeopsize(S_L);
+ taicpu(hp1).loadConst(0,taicpu(hp1).oper[0]^.val and $ff);
+ end;
+ S_WL:
+ begin
+ taicpu(p).changeopsize(S_L);
+ taicpu(hp1).loadConst(0,taicpu(hp1).oper[0]^.val and $ffff);
+ end;
+ S_BW:
+ begin
+ taicpu(p).changeopsize(S_W);
+ taicpu(hp1).loadConst(0,taicpu(hp1).oper[0]^.val and $ff);
+ end;
+ end;
+ end;
+ end;
+ end;
+ end;
+
+(* should not be generated anymore by the current code generator
+ A_POP:
+ begin
+ if target_info.system=system_i386_go32v2 then
+ begin
+ { Transform a series of pop/pop/pop/push/push/push to }
+ { 'movl x(%esp),%reg' for go32v2 (not for the rest, }
+ { because I'm not sure whether they can cope with }
+ { 'movl x(%esp),%reg' with x > 0, I believe we had }
+ { such a problem when using esp as frame pointer (JM) }
+ if (taicpu(p).oper[0]^.typ = top_reg) then
+ begin
+ hp1 := p;
+ hp2 := p;
+ l := 0;
+ while getNextInstruction(hp1,hp1) and
+ (hp1.typ = ait_instruction) and
+ (taicpu(hp1).opcode = A_POP) and
+ (taicpu(hp1).oper[0]^.typ = top_reg) do
+ begin
+ hp2 := hp1;
+ inc(l,4);
+ end;
+ getLastInstruction(p,hp3);
+ l1 := 0;
+ while (hp2 <> hp3) and
+ assigned(hp1) and
+ (hp1.typ = ait_instruction) and
+ (taicpu(hp1).opcode = A_PUSH) and
+ (taicpu(hp1).oper[0]^.typ = top_reg) and
+ (taicpu(hp1).oper[0]^.reg.enum = taicpu(hp2).oper[0]^.reg.enum) do
+ begin
+ { change it to a two op operation }
+ taicpu(hp2).oper[1]^.typ:=top_none;
+ taicpu(hp2).ops:=2;
+ taicpu(hp2).opcode := A_MOV;
+ taicpu(hp2).loadoper(1,taicpu(hp1).oper[0]^);
+ reference_reset(tmpref);
+ tmpRef.base.enum:=R_INTREGISTER;
+ tmpRef.base.number:=NR_STACK_POINTER_REG;
+ convert_register_to_enum(tmpref.base);
+ tmpRef.offset := l;
+ taicpu(hp2).loadRef(0,tmpRef);
+ hp4 := hp1;
+ getNextInstruction(hp1,hp1);
+ asml.remove(hp4);
+ hp4.free;
+ getLastInstruction(hp2,hp2);
+ dec(l,4);
+ inc(l1);
+ end;
+ if l <> -4 then
+ begin
+ inc(l,4);
+ for l1 := l1 downto 1 do
+ begin
+ getNextInstruction(hp2,hp2);
+ dec(taicpu(hp2).oper[0]^.ref^.offset,l);
+ end
+ end
+ end
+ end
+ else
+ begin
+ if (taicpu(p).oper[0]^.typ = top_reg) and
+ GetNextInstruction(p, hp1) and
+ (tai(hp1).typ=ait_instruction) and
+ (taicpu(hp1).opcode=A_PUSH) and
+ (taicpu(hp1).oper[0]^.typ = top_reg) and
+ (taicpu(hp1).oper[0]^.reg.enum=taicpu(p).oper[0]^.reg.enum) then
+ begin
+ { change it to a two op operation }
+ taicpu(p).oper[1]^.typ:=top_none;
+ taicpu(p).ops:=2;
+ taicpu(p).opcode := A_MOV;
+ taicpu(p).loadoper(1,taicpu(p).oper[0]^);
+ reference_reset(tmpref);
+ TmpRef.base.enum := R_ESP;
+ taicpu(p).loadRef(0,TmpRef);
+ asml.remove(hp1);
+ hp1.free;
+ end;
+ end;
+ end;
+*)
+ A_PUSH:
+ begin
+ if (taicpu(p).opsize = S_W) and
+ (taicpu(p).oper[0]^.typ = Top_Const) and
+ GetNextInstruction(p, hp1) and
+ (tai(hp1).typ = ait_instruction) and
+ (taicpu(hp1).opcode = A_PUSH) and
+ (taicpu(hp1).oper[0]^.typ = Top_Const) and
+ (taicpu(hp1).opsize = S_W) then
+ begin
+ taicpu(p).changeopsize(S_L);
+ taicpu(p).loadConst(0,taicpu(p).oper[0]^.val shl 16 + word(taicpu(hp1).oper[0]^.val));
+ asml.remove(hp1);
+ hp1.free;
+ end;
+ end;
+ A_SHL, A_SAL:
+ begin
+ if (taicpu(p).oper[0]^.typ = Top_Const) and
+ (taicpu(p).oper[1]^.typ = Top_Reg) and
+ (taicpu(p).opsize = S_L) and
+ (taicpu(p).oper[0]^.val <= 3) then
+ {Changes "shl const, %reg32; add const/reg, %reg32" to one lea statement}
+ begin
+ TmpBool1 := True; {should we check the next instruction?}
+ TmpBool2 := False; {have we found an add/sub which could be
+ integrated in the lea?}
+ reference_reset(tmpref,2);
+ TmpRef.index := taicpu(p).oper[1]^.reg;
+ TmpRef.scalefactor := 1 shl taicpu(p).oper[0]^.val;
+ while TmpBool1 and
+ GetNextInstruction(p, hp1) and
+ (tai(hp1).typ = ait_instruction) and
+ ((((taicpu(hp1).opcode = A_ADD) or
+ (taicpu(hp1).opcode = A_SUB)) and
+ (taicpu(hp1).oper[1]^.typ = Top_Reg) and
+ (taicpu(hp1).oper[1]^.reg = taicpu(p).oper[1]^.reg)) or
+ (((taicpu(hp1).opcode = A_INC) or
+ (taicpu(hp1).opcode = A_DEC)) and
+ (taicpu(hp1).oper[0]^.typ = Top_Reg) and
+ (taicpu(hp1).oper[0]^.reg = taicpu(p).oper[1]^.reg))) and
+ (not GetNextInstruction(hp1,hp2) or
+ not instrReadsFlags(hp2)) Do
+ begin
+ TmpBool1 := False;
+ if (taicpu(hp1).oper[0]^.typ = Top_Const) then
+ begin
+ TmpBool1 := True;
+ TmpBool2 := True;
+ case taicpu(hp1).opcode of
+ A_ADD:
+ inc(TmpRef.offset, longint(taicpu(hp1).oper[0]^.val));
+ A_SUB:
+ dec(TmpRef.offset, longint(taicpu(hp1).oper[0]^.val));
+ end;
+ asml.remove(hp1);
+ hp1.free;
+ end
+ else
+ if (taicpu(hp1).oper[0]^.typ = Top_Reg) and
+ (((taicpu(hp1).opcode = A_ADD) and
+ (TmpRef.base = NR_NO)) or
+ (taicpu(hp1).opcode = A_INC) or
+ (taicpu(hp1).opcode = A_DEC)) then
+ begin
+ TmpBool1 := True;
+ TmpBool2 := True;
+ case taicpu(hp1).opcode of
+ A_ADD:
+ TmpRef.base := taicpu(hp1).oper[0]^.reg;
+ A_INC:
+ inc(TmpRef.offset);
+ A_DEC:
+ dec(TmpRef.offset);
+ end;
+ asml.remove(hp1);
+ hp1.free;
+ end;
+ end;
+ if TmpBool2 or
+ ((current_settings.optimizecputype < cpu_Pentium2) and
+ (taicpu(p).oper[0]^.val <= 3) and
+ not(cs_opt_size in current_settings.optimizerswitches)) then
+ begin
+ if not(TmpBool2) and
+ (taicpu(p).oper[0]^.val = 1) then
+ begin
+ hp1 := taicpu.Op_reg_reg(A_ADD,taicpu(p).opsize,
+ taicpu(p).oper[1]^.reg, taicpu(p).oper[1]^.reg)
+ end
+ else
+ hp1 := taicpu.op_ref_reg(A_LEA, S_L, TmpRef,
+ taicpu(p).oper[1]^.reg);
+ InsertLLItem(asml,p.previous, p.next, hp1);
+ p.free;
+ p := hp1;
+ end;
+ end
+ else
+ if (current_settings.optimizecputype < cpu_Pentium2) and
+ (taicpu(p).oper[0]^.typ = top_const) and
+ (taicpu(p).oper[1]^.typ = top_reg) then
+ if (taicpu(p).oper[0]^.val = 1) then
+ {changes "shl $1, %reg" to "add %reg, %reg", which is the same on a 386,
+ but faster on a 486, and Tairable in both U and V pipes on the Pentium
+ (unlike shl, which is only Tairable in the U pipe)}
+ begin
+ hp1 := taicpu.Op_reg_reg(A_ADD,taicpu(p).opsize,
+ taicpu(p).oper[1]^.reg, taicpu(p).oper[1]^.reg);
+ InsertLLItem(asml,p.previous, p.next, hp1);
+ p.free;
+ p := hp1;
+ end
+ else if (taicpu(p).opsize = S_L) and
+ (taicpu(p).oper[0]^.val<= 3) then
+ {changes "shl $2, %reg" to "lea (,%reg,4), %reg"
+ "shl $3, %reg" to "lea (,%reg,8), %reg}
+ begin
+ reference_reset(tmpref,2);
+ TmpRef.index := taicpu(p).oper[1]^.reg;
+ TmpRef.scalefactor := 1 shl taicpu(p).oper[0]^.val;
+ hp1 := taicpu.Op_ref_reg(A_LEA,S_L,TmpRef, taicpu(p).oper[1]^.reg);
+ InsertLLItem(asml,p.previous, p.next, hp1);
+ p.free;
+ p := hp1;
+ end
+ end;
+ A_SETcc :
+ { changes
+ setcc (funcres) setcc reg
+ movb (funcres), reg to leave/ret
+ leave/ret }
+ begin
+ if (taicpu(p).oper[0]^.typ = top_ref) and
+ GetNextInstruction(p, hp1) and
+ GetNextInstruction(hp1, hp2) and
+ (hp2.typ = ait_instruction) and
+ ((taicpu(hp2).opcode = A_LEAVE) or
+ (taicpu(hp2).opcode = A_RET)) and
+ (taicpu(p).oper[0]^.ref^.base = current_procinfo.FramePointer) and
+ (taicpu(p).oper[0]^.ref^.index = NR_NO) and
+ not(assigned(current_procinfo.procdef.funcretsym) and
+ (taicpu(p).oper[0]^.ref^.offset < tabstractnormalvarsym(current_procinfo.procdef.funcretsym).localloc.reference.offset)) and
+ (hp1.typ = ait_instruction) and
+ (taicpu(hp1).opcode = A_MOV) and
+ (taicpu(hp1).opsize = S_B) and
+ (taicpu(hp1).oper[0]^.typ = top_ref) and
+ RefsEqual(taicpu(hp1).oper[0]^.ref^, taicpu(p).oper[0]^.ref^) then
+ begin
+ taicpu(p).loadReg(0,taicpu(hp1).oper[1]^.reg);
+ asml.remove(hp1);
+ hp1.free;
+ end
+ end;
+ A_SUB:
+ { * change "subl $2, %esp; pushw x" to "pushl x"}
+ { * change "sub/add const1, reg" or "dec reg" followed by
+ "sub const2, reg" to one "sub ..., reg" }
+ begin
+ if (taicpu(p).oper[0]^.typ = top_const) and
+ (taicpu(p).oper[1]^.typ = top_reg) then
+ if (taicpu(p).oper[0]^.val = 2) and
+ (taicpu(p).oper[1]^.reg = NR_ESP) and
+ { Don't do the sub/push optimization if the sub }
+ { comes from setting up the stack frame (JM) }
+ (not getLastInstruction(p,hp1) or
+ (hp1.typ <> ait_instruction) or
+ (taicpu(hp1).opcode <> A_MOV) or
+ (taicpu(hp1).oper[0]^.typ <> top_reg) or
+ (taicpu(hp1).oper[0]^.reg <> NR_ESP) or
+ (taicpu(hp1).oper[1]^.typ <> top_reg) or
+ (taicpu(hp1).oper[1]^.reg <> NR_EBP)) then
+ begin
+ hp1 := tai(p.next);
+ while Assigned(hp1) and
+ (tai(hp1).typ in [ait_instruction]+SkipInstr) and
+ not regReadByInstruction(RS_ESP,hp1) and
+ not regModifiedByInstruction(RS_ESP,hp1) do
+ hp1 := tai(hp1.next);
+ if Assigned(hp1) and
+ (tai(hp1).typ = ait_instruction) and
+ (taicpu(hp1).opcode = A_PUSH) and
+ (taicpu(hp1).opsize = S_W) then
+ begin
+ taicpu(hp1).changeopsize(S_L);
+ if taicpu(hp1).oper[0]^.typ=top_reg then
+ setsubreg(taicpu(hp1).oper[0]^.reg,R_SUBWHOLE);
+ hp1 := tai(p.next);
+ asml.remove(p);
+ p.free;
+ p := hp1;
+ continue
+ end;
+ if DoSubAddOpt(p) then
+ continue;
+ end
+ else if DoSubAddOpt(p) then
+ continue
+ end;
+ end;
+ end; { if is_jmp }
+ end;
+ end;
+ updateUsedRegs(UsedRegs,p);
+ p:=tai(p.next);
+ end;
+end;
+
+
+procedure PeepHoleOptPass2(asml: TAsmList; BlockStart, BlockEnd: tai);
+
+ function CanBeCMOV(p : tai) : boolean;
+ begin
+ CanBeCMOV:=assigned(p) and (p.typ=ait_instruction) and
+ (taicpu(p).opcode=A_MOV) and
+ (taicpu(p).opsize in [S_L,S_W]) and
+ ((taicpu(p).oper[0]^.typ = top_reg)
+ { we can't use cmov ref,reg because
+ ref could be nil and cmov still throws an exception
+ if ref=nil but the mov isn't done (FK)
+ or ((taicpu(p).oper[0]^.typ = top_ref) and
+ (taicpu(p).oper[0]^.ref^.refaddr = addr_no))
+ }
+ ) and
+ (taicpu(p).oper[1]^.typ in [top_reg]);
+ end;
+
+var
+ p,hp1,hp2: tai;
+ l : longint;
+ condition : tasmcond;
+ hp3: tai;
+ UsedRegs, TmpUsedRegs: TRegSet;
+ carryadd_opcode: Tasmop;
+
+begin
+ p := BlockStart;
+ UsedRegs := [];
+ while (p <> BlockEnd) Do
+ begin
+ UpdateUsedRegs(UsedRegs, tai(p.next));
+ case p.Typ Of
+ Ait_Instruction:
+ begin
+ if InsContainsSegRef(taicpu(p)) then
+ begin
+ p := tai(p.next);
+ continue;
+ end;
+ case taicpu(p).opcode Of
+ A_Jcc:
+ begin
+ { jb @@1 cmc
+ inc/dec operand --> adc/sbb operand,0
+ @@1:
+
+ ... and ...
+
+ jnb @@1
+ inc/dec operand --> adc/sbb operand,0
+ @@1: }
+ if GetNextInstruction(p,hp1) and (hp1.typ=ait_instruction) and
+ GetNextInstruction(hp1,hp2) and (hp2.typ=ait_label) and
+ (Tasmlabel(Taicpu(p).oper[0]^.ref^.symbol)=Tai_label(hp2).labsym) then
+ begin
+ carryadd_opcode:=A_NONE;
+ if Taicpu(p).condition in [C_NAE,C_B] then
+ begin
+ if Taicpu(hp1).opcode=A_INC then
+ carryadd_opcode:=A_ADC;
+ if Taicpu(hp1).opcode=A_DEC then
+ carryadd_opcode:=A_SBB;
+ if carryadd_opcode<>A_NONE then
+ begin
+ Taicpu(p).clearop(0);
+ Taicpu(p).ops:=0;
+ Taicpu(p).is_jmp:=false;
+ Taicpu(p).opcode:=A_CMC;
+ Taicpu(p).condition:=C_NONE;
+ Taicpu(hp1).ops:=2;
+ Taicpu(hp1).loadoper(1,Taicpu(hp1).oper[0]^);
+ Taicpu(hp1).loadconst(0,0);
+ Taicpu(hp1).opcode:=carryadd_opcode;
+ continue;
+ end;
+ end;
+ if Taicpu(p).condition in [C_AE,C_NB] then
+ begin
+ if Taicpu(hp1).opcode=A_INC then
+ carryadd_opcode:=A_ADC;
+ if Taicpu(hp1).opcode=A_DEC then
+ carryadd_opcode:=A_SBB;
+ if carryadd_opcode<>A_NONE then
+ begin
+ asml.remove(p);
+ p.free;
+ Taicpu(hp1).ops:=2;
+ Taicpu(hp1).loadoper(1,Taicpu(hp1).oper[0]^);
+ Taicpu(hp1).loadconst(0,0);
+ Taicpu(hp1).opcode:=carryadd_opcode;
+ p:=hp1;
+ continue;
+ end;
+ end;
+ end;
+ if (current_settings.cputype>=cpu_Pentium2) then
+ begin
+ { check for
+ jCC xxx
+ <several movs>
+ xxx:
+ }
+ l:=0;
+ GetNextInstruction(p, hp1);
+ while assigned(hp1) and
+ CanBeCMOV(hp1) and
+ { stop on labels }
+ not(hp1.typ=ait_label) do
+ begin
+ inc(l);
+ GetNextInstruction(hp1,hp1);
+ end;
+ if assigned(hp1) then
+ begin
+ if FindLabel(tasmlabel(taicpu(p).oper[0]^.ref^.symbol),hp1) then
+ begin
+ if (l<=4) and (l>0) then
+ begin
+ condition:=inverse_cond(taicpu(p).condition);
+ hp2:=p;
+ GetNextInstruction(p,hp1);
+ p:=hp1;
+ repeat
+ taicpu(hp1).opcode:=A_CMOVcc;
+ taicpu(hp1).condition:=condition;
+ GetNextInstruction(hp1,hp1);
+ until not(assigned(hp1)) or
+ not(CanBeCMOV(hp1));
+ { wait with removing else GetNextInstruction could
+ ignore the label if it was the only usage in the
+ jump moved away }
+ tasmlabel(taicpu(hp2).oper[0]^.ref^.symbol).decrefs;
+ asml.remove(hp2);
+ hp2.free;
+ continue;
+ end;
+ end
+ else
+ begin
+ { check further for
+ jCC xxx
+ <several movs 1>
+ jmp yyy
+ xxx:
+ <several movs 2>
+ yyy:
+ }
+ { hp2 points to jmp yyy }
+ hp2:=hp1;
+ { skip hp1 to xxx }
+ GetNextInstruction(hp1, hp1);
+ if assigned(hp2) and
+ assigned(hp1) and
+ (l<=3) and
+ (hp2.typ=ait_instruction) and
+ (taicpu(hp2).is_jmp) and
+ (taicpu(hp2).condition=C_None) and
+ { real label and jump, no further references to the
+ label are allowed }
+ (tasmlabel(taicpu(p).oper[0]^.ref^.symbol).getrefs=2) and
+ FindLabel(tasmlabel(taicpu(p).oper[0]^.ref^.symbol),hp1) then
+ begin
+ l:=0;
+ { skip hp1 to <several moves 2> }
+ GetNextInstruction(hp1, hp1);
+ while assigned(hp1) and
+ CanBeCMOV(hp1) do
+ begin
+ inc(l);
+ GetNextInstruction(hp1, hp1);
+ end;
+ { hp1 points to yyy: }
+ if assigned(hp1) and
+ FindLabel(tasmlabel(taicpu(hp2).oper[0]^.ref^.symbol),hp1) then
+ begin
+ condition:=inverse_cond(taicpu(p).condition);
+ GetNextInstruction(p,hp1);
+ hp3:=p;
+ p:=hp1;
+ repeat
+ taicpu(hp1).opcode:=A_CMOVcc;
+ taicpu(hp1).condition:=condition;
+ GetNextInstruction(hp1,hp1);
+ until not(assigned(hp1)) or
+ not(CanBeCMOV(hp1));
+ { hp2 is still at jmp yyy }
+ GetNextInstruction(hp2,hp1);
+ { hp2 is now at xxx: }
+ condition:=inverse_cond(condition);
+ GetNextInstruction(hp1,hp1);
+ { hp1 is now at <several movs 2> }
+ repeat
+ taicpu(hp1).opcode:=A_CMOVcc;
+ taicpu(hp1).condition:=condition;
+ GetNextInstruction(hp1,hp1);
+ until not(assigned(hp1)) or
+ not(CanBeCMOV(hp1));
+ {
+ asml.remove(hp1.next)
+ hp1.next.free;
+ asml.remove(hp1);
+ hp1.free;
+ }
+ { remove jCC }
+ tasmlabel(taicpu(hp3).oper[0]^.ref^.symbol).decrefs;
+ asml.remove(hp3);
+ hp3.free;
+ { remove jmp }
+ tasmlabel(taicpu(hp2).oper[0]^.ref^.symbol).decrefs;
+ asml.remove(hp2);
+ hp2.free;
+ continue;
+ end;
+ end;
+ end;
+ end;
+ end;
+ end;
+ A_FSTP,A_FISTP:
+ if doFpuLoadStoreOpt(asmL,p) then
+ continue;
+ A_IMUL:
+ begin
+ if (taicpu(p).ops >= 2) and
+ ((taicpu(p).oper[0]^.typ = top_const) or
+ ((taicpu(p).oper[0]^.typ = top_ref) and (taicpu(p).oper[0]^.ref^.refaddr=addr_full))) and
+ (taicpu(p).oper[1]^.typ = top_reg) and
+ ((taicpu(p).ops = 2) or
+ ((taicpu(p).oper[2]^.typ = top_reg) and
+ (taicpu(p).oper[2]^.reg = taicpu(p).oper[1]^.reg))) and
+ getLastInstruction(p,hp1) and
+ (hp1.typ = ait_instruction) and
+ (taicpu(hp1).opcode = A_MOV) and
+ (taicpu(hp1).oper[0]^.typ = top_reg) and
+ (taicpu(hp1).oper[1]^.typ = top_reg) and
+ (taicpu(hp1).oper[1]^.reg = taicpu(p).oper[1]^.reg) then
+ { change "mov reg1,reg2; imul y,reg2" to "imul y,reg1,reg2" }
+ begin
+ taicpu(p).ops := 3;
+ taicpu(p).loadreg(1,taicpu(hp1).oper[0]^.reg);
+ taicpu(p).loadreg(2,taicpu(hp1).oper[1]^.reg);
+ asml.remove(hp1);
+ hp1.free;
+ end;
+ end;
+ A_MOV:
+ begin
+ if (taicpu(p).oper[0]^.typ = top_reg) and
+ (taicpu(p).oper[1]^.typ = top_reg) and
+ GetNextInstruction(p, hp1) and
+ (hp1.typ = ait_Instruction) and
+ ((taicpu(hp1).opcode = A_MOV) or
+ (taicpu(hp1).opcode = A_MOVZX) or
+ (taicpu(hp1).opcode = A_MOVSX)) and
+ (taicpu(hp1).oper[0]^.typ = top_ref) and
+ (taicpu(hp1).oper[1]^.typ = top_reg) and
+ ((taicpu(hp1).oper[0]^.ref^.base = taicpu(p).oper[1]^.reg) or
+ (taicpu(hp1).oper[0]^.ref^.index = taicpu(p).oper[1]^.reg)) and
+ (getsupreg(taicpu(hp1).oper[1]^.reg) = getsupreg(taicpu(p).oper[1]^.reg)) then
+ {mov reg1, reg2
+ mov/zx/sx (reg2, ..), reg2 to mov/zx/sx (reg1, ..), reg2}
+ begin
+ if (taicpu(hp1).oper[0]^.ref^.base = taicpu(p).oper[1]^.reg) then
+ taicpu(hp1).oper[0]^.ref^.base := taicpu(p).oper[0]^.reg;
+ if (taicpu(hp1).oper[0]^.ref^.index = taicpu(p).oper[1]^.reg) then
+ taicpu(hp1).oper[0]^.ref^.index := taicpu(p).oper[0]^.reg;
+ asml.remove(p);
+ p.free;
+ p := hp1;
+ continue;
+ end
+ else if (taicpu(p).oper[0]^.typ = top_ref) and
+ GetNextInstruction(p,hp1) and
+ (hp1.typ = ait_instruction) and
+ IsFoldableArithOp(taicpu(hp1),taicpu(p).oper[1]^.reg) and
+ GetNextInstruction(hp1,hp2) and
+ (hp2.typ = ait_instruction) and
+ (taicpu(hp2).opcode = A_MOV) and
+ (taicpu(hp2).oper[0]^.typ = top_reg) and
+ (taicpu(hp2).oper[0]^.reg = taicpu(p).oper[1]^.reg) and
+ (taicpu(hp2).oper[1]^.typ = top_ref) then
+ begin
+ TmpUsedRegs := UsedRegs;
+ UpdateUsedRegs(TmpUsedRegs,tai(hp1.next));
+ if (RefsEqual(taicpu(hp2).oper[1]^.ref^, taicpu(p).oper[0]^.ref^) and
+ not(RegUsedAfterInstruction(taicpu(p).oper[1]^.reg,
+ hp2, TmpUsedRegs))) then
+ { change mov (ref), reg }
+ { add/sub/or/... reg2/$const, reg }
+ { mov reg, (ref) }
+ { # release reg }
+ { to add/sub/or/... reg2/$const, (ref) }
+ begin
+ case taicpu(hp1).opcode of
+ A_INC,A_DEC:
+ taicpu(hp1).loadRef(0,taicpu(p).oper[0]^.ref^)
+ else
+ taicpu(hp1).loadRef(1,taicpu(p).oper[0]^.ref^);
+ end;
+ asml.remove(p);
+ asml.remove(hp2);
+ p.free;
+ hp2.free;
+ p := hp1
+ end;
+ end
+ end;
+ end;
+ end;
+ end;
+ p := tai(p.next)
+ end;
+end;
+
+
+procedure PostPeepHoleOpts(asml: TAsmList; BlockStart, BlockEnd: tai);
+var
+ p,hp1,hp2: tai;
+begin
+ p := BlockStart;
+ while (p <> BlockEnd) Do
+ begin
+ case p.Typ Of
+ Ait_Instruction:
+ begin
+ if InsContainsSegRef(taicpu(p)) then
+ begin
+ p := tai(p.next);
+ continue;
+ end;
+ case taicpu(p).opcode Of
+ A_CALL:
+ if (current_settings.optimizecputype < cpu_Pentium2) and
+ not(cs_create_pic in current_settings.moduleswitches) and
+ GetNextInstruction(p, hp1) and
+ (hp1.typ = ait_instruction) and
+ (taicpu(hp1).opcode = A_JMP) and
+ ((taicpu(hp1).oper[0]^.typ=top_ref) and (taicpu(hp1).oper[0]^.ref^.refaddr=addr_full)) then
+ begin
+ hp2 := taicpu.Op_sym(A_PUSH,S_L,taicpu(hp1).oper[0]^.ref^.symbol);
+ InsertLLItem(asml, p.previous, p, hp2);
+ taicpu(p).opcode := A_JMP;
+ taicpu(p).is_jmp := true;
+ asml.remove(hp1);
+ hp1.free;
+ end;
+ A_CMP:
+ begin
+ if (taicpu(p).oper[0]^.typ = top_const) and
+ (taicpu(p).oper[0]^.val = 0) and
+ (taicpu(p).oper[1]^.typ = top_reg) then
+ {change "cmp $0, %reg" to "test %reg, %reg"}
+ begin
+ taicpu(p).opcode := A_TEST;
+ taicpu(p).loadreg(0,taicpu(p).oper[1]^.reg);
+ continue;
+ end;
+ end;
+(*
+Optimization is not safe; xor clears the carry flag.
+See test/tgadint64 in the test suite.
+ A_MOV:
+ if (taicpu(p).oper[0]^.typ = Top_Const) and
+ (taicpu(p).oper[0]^.val = 0) and
+ (taicpu(p).oper[1]^.typ = Top_Reg) then
+ { change "mov $0, %reg" into "xor %reg, %reg" }
+ begin
+ taicpu(p).opcode := A_XOR;
+ taicpu(p).loadReg(0,taicpu(p).oper[1]^.reg);
+ end;
+*)
+ A_MOVZX:
+ { if register vars are on, it's possible there is code like }
+ { "cmpl $3,%eax; movzbl 8(%ebp),%ebx; je .Lxxx" }
+ { so we can't safely replace the movzx then with xor/mov, }
+ { since that would change the flags (JM) }
+ if not(cs_opt_regvar in current_settings.optimizerswitches) then
+ begin
+ if (taicpu(p).oper[1]^.typ = top_reg) then
+ if (taicpu(p).oper[0]^.typ = top_reg)
+ then
+ case taicpu(p).opsize of
+ S_BL:
+ begin
+ if IsGP32Reg(getsupreg(taicpu(p).oper[1]^.reg)) and
+ not(cs_opt_size in current_settings.optimizerswitches) and
+ (current_settings.optimizecputype = cpu_Pentium) then
+ {Change "movzbl %reg1, %reg2" to
+ "xorl %reg2, %reg2; movb %reg1, %reg2" for Pentium and
+ PentiumMMX}
+ begin
+ hp1 := taicpu.op_reg_reg(A_XOR, S_L,
+ taicpu(p).oper[1]^.reg, taicpu(p).oper[1]^.reg);
+ InsertLLItem(asml,p.previous, p, hp1);
+ taicpu(p).opcode := A_MOV;
+ taicpu(p).changeopsize(S_B);
+ setsubreg(taicpu(p).oper[1]^.reg,R_SUBL);
+ end;
+ end;
+ end
+ else if (taicpu(p).oper[0]^.typ = top_ref) and
+ (taicpu(p).oper[0]^.ref^.base <> taicpu(p).oper[1]^.reg) and
+ (taicpu(p).oper[0]^.ref^.index <> taicpu(p).oper[1]^.reg) and
+ not(cs_opt_size in current_settings.optimizerswitches) and
+ IsGP32Reg(getsupreg(taicpu(p).oper[1]^.reg)) and
+ (current_settings.optimizecputype = cpu_Pentium) and
+ (taicpu(p).opsize = S_BL) then
+ {changes "movzbl mem, %reg" to "xorl %reg, %reg; movb mem, %reg8" for
+ Pentium and PentiumMMX}
+ begin
+ hp1 := taicpu.Op_reg_reg(A_XOR, S_L, taicpu(p).oper[1]^.reg,
+ taicpu(p).oper[1]^.reg);
+ taicpu(p).opcode := A_MOV;
+ taicpu(p).changeopsize(S_B);
+ setsubreg(taicpu(p).oper[1]^.reg,R_SUBL);
+ InsertLLItem(asml,p.previous, p, hp1);
+ end;
+ end;
+ A_TEST, A_OR:
+ {removes the line marked with (x) from the sequence
+ and/or/xor/add/sub/... $x, %y
+ test/or %y, %y (x)
+ j(n)z _Label
+ as the first instruction already adjusts the ZF}
+ begin
+ if OpsEqual(taicpu(p).oper[0]^,taicpu(p).oper[1]^) then
+ if GetLastInstruction(p, hp1) and
+ (tai(hp1).typ = ait_instruction) and
+ GetNextInstruction(p,hp2) and
+ (hp2.typ = ait_instruction) and
+ ((taicpu(hp2).opcode = A_SETcc) or
+ (taicpu(hp2).opcode = A_Jcc) or
+ (taicpu(hp2).opcode = A_CMOVcc)) then
+ case taicpu(hp1).opcode Of
+ A_ADD, A_SUB, A_OR, A_XOR, A_AND{, A_SHL, A_SHR}:
+ begin
+ if OpsEqual(taicpu(hp1).oper[1]^,taicpu(p).oper[0]^) and
+ { does not work in case of overflow for G(E)/L(E)/C_O/C_NO }
+ { and in case of carry for A(E)/B(E)/C/NC }
+ ((taicpu(hp2).condition in [C_Z,C_NZ,C_E,C_NE]) or
+ ((taicpu(hp1).opcode <> A_ADD) and
+ (taicpu(hp1).opcode <> A_SUB))) then
+ begin
+ hp1 := tai(p.next);
+ asml.remove(p);
+ p.free;
+ p := tai(hp1);
+ continue
+ end;
+ end;
+ A_DEC, A_INC, A_NEG:
+ begin
+ if OpsEqual(taicpu(hp1).oper[0]^,taicpu(p).oper[0]^) and
+ { does not work in case of overflow for G(E)/L(E)/C_O/C_NO }
+ { and in case of carry for A(E)/B(E)/C/NC }
+ (taicpu(hp2).condition in [C_Z,C_NZ,C_E,C_NE]) then
+ begin
+ case taicpu(hp1).opcode Of
+ A_DEC, A_INC:
+ {replace inc/dec with add/sub 1, because inc/dec doesn't set the carry flag}
+ begin
+ case taicpu(hp1).opcode Of
+ A_DEC: taicpu(hp1).opcode := A_SUB;
+ A_INC: taicpu(hp1).opcode := A_ADD;
+ end;
+ taicpu(hp1).loadoper(1,taicpu(hp1).oper[0]^);
+ taicpu(hp1).loadConst(0,1);
+ taicpu(hp1).ops:=2;
+ end
+ end;
+ hp1 := tai(p.next);
+ asml.remove(p);
+ p.free;
+ p := tai(hp1);
+ continue
+ end;
+ end
+ end
+ end;
+ end;
+ end;
+ end;
+ p := tai(p.next)
+ end;
+end;
+
+
+
+end.
diff --git a/closures/compiler/i386/r386ari.inc b/closures/compiler/i386/r386ari.inc
new file mode 100644
index 0000000000..485e9d94a4
--- /dev/null
+++ b/closures/compiler/i386/r386ari.inc
@@ -0,0 +1,73 @@
+{ don't edit, this file is generated from x86reg.dat }
+2,
+1,
+3,
+14,
+13,
+21,
+15,
+6,
+5,
+38,
+39,
+40,
+41,
+26,
+7,
+10,
+19,
+9,
+32,
+33,
+34,
+35,
+36,
+37,
+27,
+11,
+4,
+22,
+16,
+8,
+20,
+12,
+25,
+28,
+18,
+24,
+30,
+31,
+56,
+57,
+58,
+59,
+60,
+61,
+62,
+63,
+17,
+23,
+29,
+55,
+47,
+48,
+49,
+50,
+51,
+52,
+53,
+54,
+42,
+43,
+44,
+45,
+46,
+64,
+65,
+66,
+67,
+68,
+69,
+70,
+71,
+0
diff --git a/closures/compiler/i386/r386att.inc b/closures/compiler/i386/r386att.inc
new file mode 100644
index 0000000000..2efe472cd4
--- /dev/null
+++ b/closures/compiler/i386/r386att.inc
@@ -0,0 +1,73 @@
+{ don't edit, this file is generated from x86reg.dat }
+'INVALID',
+'%al',
+'%ah',
+'%ax',
+'%eax',
+'%cl',
+'%ch',
+'%cx',
+'%ecx',
+'%dl',
+'%dh',
+'%dx',
+'%edx',
+'%bl',
+'%bh',
+'%bx',
+'%ebx',
+'%si',
+'%esi',
+'%di',
+'%edi',
+'%bp',
+'%ebp',
+'%sp',
+'%esp',
+'%eip',
+'%cs',
+'%ds',
+'%es',
+'%ss',
+'%fs',
+'%gs',
+'%dr0',
+'%dr1',
+'%dr2',
+'%dr3',
+'%dr6',
+'%dr7',
+'%cr0',
+'%cr2',
+'%cr3',
+'%cr4',
+'%tr3',
+'%tr4',
+'%tr5',
+'%tr6',
+'%tr7',
+'%st(0)',
+'%st(1)',
+'%st(2)',
+'%st(3)',
+'%st(4)',
+'%st(5)',
+'%st(6)',
+'%st(7)',
+'%st',
+'%mm0',
+'%mm1',
+'%mm2',
+'%mm3',
+'%mm4',
+'%mm5',
+'%mm6',
+'%mm7',
+'%xmm0',
+'%xmm1',
+'%xmm2',
+'%xmm3',
+'%xmm4',
+'%xmm5',
+'%xmm6',
+'%xmm7'
diff --git a/closures/compiler/i386/r386con.inc b/closures/compiler/i386/r386con.inc
new file mode 100644
index 0000000000..eb1f3d0a78
--- /dev/null
+++ b/closures/compiler/i386/r386con.inc
@@ -0,0 +1,73 @@
+{ don't edit, this file is generated from x86reg.dat }
+NR_NO = tregister($00000000);
+NR_AL = tregister($01010000);
+NR_AH = tregister($01020000);
+NR_AX = tregister($01030000);
+NR_EAX = tregister($01040000);
+NR_CL = tregister($01010001);
+NR_CH = tregister($01020001);
+NR_CX = tregister($01030001);
+NR_ECX = tregister($01040001);
+NR_DL = tregister($01010002);
+NR_DH = tregister($01020002);
+NR_DX = tregister($01030002);
+NR_EDX = tregister($01040002);
+NR_BL = tregister($01010003);
+NR_BH = tregister($01020003);
+NR_BX = tregister($01030003);
+NR_EBX = tregister($01040003);
+NR_SI = tregister($01030004);
+NR_ESI = tregister($01040004);
+NR_DI = tregister($01030005);
+NR_EDI = tregister($01040005);
+NR_BP = tregister($01030006);
+NR_EBP = tregister($01040006);
+NR_SP = tregister($01030007);
+NR_ESP = tregister($01040007);
+NR_EIP = tregister($05000000);
+NR_CS = tregister($05000001);
+NR_DS = tregister($05000002);
+NR_ES = tregister($05000003);
+NR_SS = tregister($05000004);
+NR_FS = tregister($05000005);
+NR_GS = tregister($05000006);
+NR_DR0 = tregister($05000007);
+NR_DR1 = tregister($05000008);
+NR_DR2 = tregister($05000009);
+NR_DR3 = tregister($0500000a);
+NR_DR6 = tregister($0500000b);
+NR_DR7 = tregister($0500000c);
+NR_CR0 = tregister($0500000d);
+NR_CR2 = tregister($0500000e);
+NR_CR3 = tregister($0500000f);
+NR_CR4 = tregister($05000010);
+NR_TR3 = tregister($05000011);
+NR_TR4 = tregister($05000012);
+NR_TR5 = tregister($05000013);
+NR_TR6 = tregister($05000014);
+NR_TR7 = tregister($05000015);
+NR_ST0 = tregister($02000000);
+NR_ST1 = tregister($02000001);
+NR_ST2 = tregister($02000002);
+NR_ST3 = tregister($02000003);
+NR_ST4 = tregister($02000004);
+NR_ST5 = tregister($02000005);
+NR_ST6 = tregister($02000006);
+NR_ST7 = tregister($02000007);
+NR_ST = tregister($02000008);
+NR_MM0 = tregister($03000000);
+NR_MM1 = tregister($03000001);
+NR_MM2 = tregister($03000002);
+NR_MM3 = tregister($03000003);
+NR_MM4 = tregister($03000004);
+NR_MM5 = tregister($03000005);
+NR_MM6 = tregister($03000006);
+NR_MM7 = tregister($03000007);
+NR_XMM0 = tregister($04000000);
+NR_XMM1 = tregister($04000001);
+NR_XMM2 = tregister($04000002);
+NR_XMM3 = tregister($04000003);
+NR_XMM4 = tregister($04000004);
+NR_XMM5 = tregister($04000005);
+NR_XMM6 = tregister($04000006);
+NR_XMM7 = tregister($04000007);
diff --git a/closures/compiler/i386/r386dwrf.inc b/closures/compiler/i386/r386dwrf.inc
new file mode 100644
index 0000000000..79d6522842
--- /dev/null
+++ b/closures/compiler/i386/r386dwrf.inc
@@ -0,0 +1,73 @@
+{ don't edit, this file is generated from x86reg.dat }
+-1,
+0,
+0,
+0,
+0,
+1,
+1,
+1,
+1,
+2,
+2,
+2,
+2,
+3,
+3,
+3,
+3,
+6,
+6,
+7,
+7,
+5,
+5,
+4,
+4,
+8,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+11,
+29,
+30,
+31,
+32,
+33,
+34,
+35,
+36,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28
diff --git a/closures/compiler/i386/r386int.inc b/closures/compiler/i386/r386int.inc
new file mode 100644
index 0000000000..585a5b0285
--- /dev/null
+++ b/closures/compiler/i386/r386int.inc
@@ -0,0 +1,73 @@
+{ don't edit, this file is generated from x86reg.dat }
+'INVALID',
+'al',
+'ah',
+'ax',
+'eax',
+'cl',
+'ch',
+'cx',
+'ecx',
+'dl',
+'dh',
+'dx',
+'edx',
+'bl',
+'bh',
+'bx',
+'ebx',
+'si',
+'esi',
+'di',
+'edi',
+'bp',
+'ebp',
+'sp',
+'esp',
+'eip',
+'cs',
+'ds',
+'es',
+'ss',
+'fs',
+'gs',
+'dr0',
+'dr1',
+'dr2',
+'dr3',
+'dr6',
+'dr7',
+'cr0',
+'cr2',
+'cr3',
+'cr4',
+'tr3',
+'tr4',
+'tr5',
+'tr6',
+'tr7',
+'st(0)',
+'st(1)',
+'st(2)',
+'st(3)',
+'st(4)',
+'st(5)',
+'st(6)',
+'st(7)',
+'st',
+'mm0',
+'mm1',
+'mm2',
+'mm3',
+'mm4',
+'mm5',
+'mm6',
+'mm7',
+'xmm0',
+'xmm1',
+'xmm2',
+'xmm3',
+'xmm4',
+'xmm5',
+'xmm6',
+'xmm7'
diff --git a/closures/compiler/i386/r386iri.inc b/closures/compiler/i386/r386iri.inc
new file mode 100644
index 0000000000..33148cb940
--- /dev/null
+++ b/closures/compiler/i386/r386iri.inc
@@ -0,0 +1,73 @@
+{ don't edit, this file is generated from x86reg.dat }
+0,
+2,
+1,
+3,
+14,
+13,
+21,
+15,
+6,
+5,
+38,
+39,
+40,
+41,
+26,
+7,
+10,
+19,
+9,
+32,
+33,
+34,
+35,
+36,
+37,
+27,
+11,
+4,
+22,
+16,
+8,
+20,
+12,
+25,
+28,
+18,
+24,
+30,
+31,
+56,
+57,
+58,
+59,
+60,
+61,
+62,
+63,
+17,
+23,
+29,
+55,
+47,
+48,
+49,
+50,
+51,
+52,
+53,
+54,
+42,
+43,
+44,
+45,
+46,
+64,
+65,
+66,
+67,
+68,
+69,
+70,
+71
diff --git a/closures/compiler/i386/r386nasm.inc b/closures/compiler/i386/r386nasm.inc
new file mode 100644
index 0000000000..1e2bd036b0
--- /dev/null
+++ b/closures/compiler/i386/r386nasm.inc
@@ -0,0 +1,73 @@
+{ don't edit, this file is generated from x86reg.dat }
+'INVALID',
+'al',
+'ah',
+'ax',
+'eax',
+'cl',
+'ch',
+'cx',
+'ecx',
+'dl',
+'dh',
+'dx',
+'edx',
+'bl',
+'bh',
+'bx',
+'ebx',
+'si',
+'esi',
+'di',
+'edi',
+'bp',
+'ebp',
+'sp',
+'esp',
+'eip',
+'cs',
+'ds',
+'es',
+'ss',
+'fs',
+'gs',
+'dr0',
+'dr1',
+'dr2',
+'dr3',
+'dr6',
+'dr7',
+'cr0',
+'cr2',
+'cr3',
+'cr4',
+'tr3',
+'tr4',
+'tr5',
+'tr6',
+'tr7',
+'st0',
+'st1',
+'st2',
+'st3',
+'st4',
+'st5',
+'st6',
+'st7',
+'st0',
+'mm0',
+'mm1',
+'mm2',
+'mm3',
+'mm4',
+'mm5',
+'mm6',
+'mm7',
+'xmm0',
+'xmm1',
+'xmm2',
+'xmm3',
+'xmm4',
+'xmm5',
+'xmm6',
+'xmm7'
diff --git a/closures/compiler/i386/r386nor.inc b/closures/compiler/i386/r386nor.inc
new file mode 100644
index 0000000000..2e66b09488
--- /dev/null
+++ b/closures/compiler/i386/r386nor.inc
@@ -0,0 +1,2 @@
+{ don't edit, this file is generated from x86reg.dat }
+72
diff --git a/closures/compiler/i386/r386nri.inc b/closures/compiler/i386/r386nri.inc
new file mode 100644
index 0000000000..33148cb940
--- /dev/null
+++ b/closures/compiler/i386/r386nri.inc
@@ -0,0 +1,73 @@
+{ don't edit, this file is generated from x86reg.dat }
+0,
+2,
+1,
+3,
+14,
+13,
+21,
+15,
+6,
+5,
+38,
+39,
+40,
+41,
+26,
+7,
+10,
+19,
+9,
+32,
+33,
+34,
+35,
+36,
+37,
+27,
+11,
+4,
+22,
+16,
+8,
+20,
+12,
+25,
+28,
+18,
+24,
+30,
+31,
+56,
+57,
+58,
+59,
+60,
+61,
+62,
+63,
+17,
+23,
+29,
+55,
+47,
+48,
+49,
+50,
+51,
+52,
+53,
+54,
+42,
+43,
+44,
+45,
+46,
+64,
+65,
+66,
+67,
+68,
+69,
+70,
+71
diff --git a/closures/compiler/i386/r386num.inc b/closures/compiler/i386/r386num.inc
new file mode 100644
index 0000000000..5762785a18
--- /dev/null
+++ b/closures/compiler/i386/r386num.inc
@@ -0,0 +1,73 @@
+{ don't edit, this file is generated from x86reg.dat }
+tregister($00000000),
+tregister($01010000),
+tregister($01020000),
+tregister($01030000),
+tregister($01040000),
+tregister($01010001),
+tregister($01020001),
+tregister($01030001),
+tregister($01040001),
+tregister($01010002),
+tregister($01020002),
+tregister($01030002),
+tregister($01040002),
+tregister($01010003),
+tregister($01020003),
+tregister($01030003),
+tregister($01040003),
+tregister($01030004),
+tregister($01040004),
+tregister($01030005),
+tregister($01040005),
+tregister($01030006),
+tregister($01040006),
+tregister($01030007),
+tregister($01040007),
+tregister($05000000),
+tregister($05000001),
+tregister($05000002),
+tregister($05000003),
+tregister($05000004),
+tregister($05000005),
+tregister($05000006),
+tregister($05000007),
+tregister($05000008),
+tregister($05000009),
+tregister($0500000a),
+tregister($0500000b),
+tregister($0500000c),
+tregister($0500000d),
+tregister($0500000e),
+tregister($0500000f),
+tregister($05000010),
+tregister($05000011),
+tregister($05000012),
+tregister($05000013),
+tregister($05000014),
+tregister($05000015),
+tregister($02000000),
+tregister($02000001),
+tregister($02000002),
+tregister($02000003),
+tregister($02000004),
+tregister($02000005),
+tregister($02000006),
+tregister($02000007),
+tregister($02000008),
+tregister($03000000),
+tregister($03000001),
+tregister($03000002),
+tregister($03000003),
+tregister($03000004),
+tregister($03000005),
+tregister($03000006),
+tregister($03000007),
+tregister($04000000),
+tregister($04000001),
+tregister($04000002),
+tregister($04000003),
+tregister($04000004),
+tregister($04000005),
+tregister($04000006),
+tregister($04000007)
diff --git a/closures/compiler/i386/r386op.inc b/closures/compiler/i386/r386op.inc
new file mode 100644
index 0000000000..c9df7fabcb
--- /dev/null
+++ b/closures/compiler/i386/r386op.inc
@@ -0,0 +1,73 @@
+{ don't edit, this file is generated from x86reg.dat }
+0,
+0,
+4,
+0,
+0,
+1,
+5,
+1,
+1,
+2,
+6,
+2,
+2,
+3,
+7,
+3,
+3,
+6,
+6,
+7,
+7,
+5,
+5,
+4,
+4,
+0,
+1,
+3,
+0,
+2,
+4,
+5,
+0,
+1,
+2,
+3,
+6,
+7,
+0,
+2,
+3,
+4,
+3,
+4,
+5,
+6,
+7,
+0,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+0,
+0,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+0,
+1,
+2,
+3,
+4,
+5,
+6,
+7
diff --git a/closures/compiler/i386/r386ot.inc b/closures/compiler/i386/r386ot.inc
new file mode 100644
index 0000000000..d30c918dc7
--- /dev/null
+++ b/closures/compiler/i386/r386ot.inc
@@ -0,0 +1,73 @@
+{ don't edit, this file is generated from x86reg.dat }
+OT_NONE,
+OT_REG_AL,
+OT_REG8,
+OT_REG_AX,
+OT_REG_EAX,
+OT_REG_CL,
+OT_REG8,
+OT_REG_CX,
+OT_REG_ECX,
+OT_REG8,
+OT_REG8,
+OT_REG_DX,
+OT_REG32,
+OT_REG8,
+OT_REG8,
+OT_REG16,
+OT_REG32,
+OT_REG16,
+OT_REG32,
+OT_REG16,
+OT_REG32,
+OT_REG16,
+OT_REG32,
+OT_REG16,
+OT_REG32,
+OT_NONE,
+OT_REG_CS,
+OT_REG_DESS,
+OT_REG_DESS,
+OT_REG_DESS,
+OT_REG_FSGS,
+OT_REG_FSGS,
+OT_REG_DREG,
+OT_REG_DREG,
+OT_REG_DREG,
+OT_REG_DREG,
+OT_REG_DREG,
+OT_REG_DREG,
+OT_REG_CREG,
+OT_REG_CREG,
+OT_REG_CREG,
+OT_REG_CR4,
+OT_REG_TREG,
+OT_REG_TREG,
+OT_REG_TREG,
+OT_REG_TREG,
+OT_REG_TREG,
+OT_FPU0,
+OT_FPUREG,
+OT_FPUREG,
+OT_FPUREG,
+OT_FPUREG,
+OT_FPUREG,
+OT_FPUREG,
+OT_FPUREG,
+OT_FPU0,
+OT_MMXREG,
+OT_MMXREG,
+OT_MMXREG,
+OT_MMXREG,
+OT_MMXREG,
+OT_MMXREG,
+OT_MMXREG,
+OT_MMXREG,
+OT_XMMREG,
+OT_XMMREG,
+OT_XMMREG,
+OT_XMMREG,
+OT_XMMREG,
+OT_XMMREG,
+OT_XMMREG,
+OT_XMMREG
diff --git a/closures/compiler/i386/r386rni.inc b/closures/compiler/i386/r386rni.inc
new file mode 100644
index 0000000000..294022d5e2
--- /dev/null
+++ b/closures/compiler/i386/r386rni.inc
@@ -0,0 +1,73 @@
+{ don't edit, this file is generated from x86reg.dat }
+0,
+1,
+5,
+9,
+13,
+2,
+6,
+10,
+14,
+3,
+7,
+11,
+15,
+17,
+19,
+21,
+23,
+4,
+8,
+12,
+16,
+18,
+20,
+22,
+24,
+47,
+48,
+49,
+50,
+51,
+52,
+53,
+54,
+55,
+56,
+57,
+58,
+59,
+60,
+61,
+62,
+63,
+64,
+65,
+66,
+67,
+68,
+69,
+70,
+71,
+25,
+26,
+27,
+28,
+29,
+30,
+31,
+32,
+33,
+34,
+35,
+36,
+37,
+38,
+39,
+40,
+41,
+42,
+43,
+44,
+45,
+46
diff --git a/closures/compiler/i386/r386sri.inc b/closures/compiler/i386/r386sri.inc
new file mode 100644
index 0000000000..33148cb940
--- /dev/null
+++ b/closures/compiler/i386/r386sri.inc
@@ -0,0 +1,73 @@
+{ don't edit, this file is generated from x86reg.dat }
+0,
+2,
+1,
+3,
+14,
+13,
+21,
+15,
+6,
+5,
+38,
+39,
+40,
+41,
+26,
+7,
+10,
+19,
+9,
+32,
+33,
+34,
+35,
+36,
+37,
+27,
+11,
+4,
+22,
+16,
+8,
+20,
+12,
+25,
+28,
+18,
+24,
+30,
+31,
+56,
+57,
+58,
+59,
+60,
+61,
+62,
+63,
+17,
+23,
+29,
+55,
+47,
+48,
+49,
+50,
+51,
+52,
+53,
+54,
+42,
+43,
+44,
+45,
+46,
+64,
+65,
+66,
+67,
+68,
+69,
+70,
+71
diff --git a/closures/compiler/i386/r386stab.inc b/closures/compiler/i386/r386stab.inc
new file mode 100644
index 0000000000..d2fbf4d7e5
--- /dev/null
+++ b/closures/compiler/i386/r386stab.inc
@@ -0,0 +1,73 @@
+{ don't edit, this file is generated from x86reg.dat }
+-1,
+0,
+0,
+0,
+0,
+1,
+1,
+1,
+1,
+2,
+2,
+2,
+2,
+3,
+3,
+3,
+3,
+6,
+6,
+7,
+7,
+5,
+5,
+4,
+4,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+12,
+29,
+30,
+31,
+32,
+33,
+34,
+35,
+36,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28
diff --git a/closures/compiler/i386/r386std.inc b/closures/compiler/i386/r386std.inc
new file mode 100644
index 0000000000..585a5b0285
--- /dev/null
+++ b/closures/compiler/i386/r386std.inc
@@ -0,0 +1,73 @@
+{ don't edit, this file is generated from x86reg.dat }
+'INVALID',
+'al',
+'ah',
+'ax',
+'eax',
+'cl',
+'ch',
+'cx',
+'ecx',
+'dl',
+'dh',
+'dx',
+'edx',
+'bl',
+'bh',
+'bx',
+'ebx',
+'si',
+'esi',
+'di',
+'edi',
+'bp',
+'ebp',
+'sp',
+'esp',
+'eip',
+'cs',
+'ds',
+'es',
+'ss',
+'fs',
+'gs',
+'dr0',
+'dr1',
+'dr2',
+'dr3',
+'dr6',
+'dr7',
+'cr0',
+'cr2',
+'cr3',
+'cr4',
+'tr3',
+'tr4',
+'tr5',
+'tr6',
+'tr7',
+'st(0)',
+'st(1)',
+'st(2)',
+'st(3)',
+'st(4)',
+'st(5)',
+'st(6)',
+'st(7)',
+'st',
+'mm0',
+'mm1',
+'mm2',
+'mm3',
+'mm4',
+'mm5',
+'mm6',
+'mm7',
+'xmm0',
+'xmm1',
+'xmm2',
+'xmm3',
+'xmm4',
+'xmm5',
+'xmm6',
+'xmm7'
diff --git a/closures/compiler/i386/ra386att.pas b/closures/compiler/i386/ra386att.pas
new file mode 100644
index 0000000000..4e1185e905
--- /dev/null
+++ b/closures/compiler/i386/ra386att.pas
@@ -0,0 +1,59 @@
+{
+ Copyright (c) 1998-2002 by Carl Eric Codere and Peter Vreman
+
+ Does the parsing for the i386 GNU AS styled inline assembler.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+Unit ra386att;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ rax86att;
+
+ type
+ ti386attreader = class(tx86attreader)
+ end;
+
+
+ implementation
+
+ uses
+ rabase,systems;
+
+const
+ asmmode_i386_att_info : tasmmodeinfo =
+ (
+ id : asmmode_i386_att;
+ idtxt : 'ATT';
+ casmreader : ti386attreader;
+ );
+
+ asmmode_i386_standard_info : tasmmodeinfo =
+ (
+ id : asmmode_standard;
+ idtxt : 'STANDARD';
+ casmreader : ti386attreader;
+ );
+
+initialization
+ RegisterAsmMode(asmmode_i386_att_info);
+ RegisterAsmMode(asmmode_i386_standard_info);
+end.
diff --git a/closures/compiler/i386/ra386int.pas b/closures/compiler/i386/ra386int.pas
new file mode 100644
index 0000000000..366595bac1
--- /dev/null
+++ b/closures/compiler/i386/ra386int.pas
@@ -0,0 +1,74 @@
+{
+ Copyright (c) 1998-2006 by Carl Eric Codere and Peter Vreman
+
+ Does the parsing for the i386 intel styled inline assembler.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+Unit ra386int;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ rax86int;
+
+ type
+ ti386intreader = class(tx86intreader)
+ // procedure handleopcode;override;
+ end;
+
+
+ implementation
+
+ uses
+ rabase,systems,rax86,aasmcpu;
+
+(*
+ procedure ti386intreader.handleopcode;
+ var
+ instr : Tx86Instruction;
+ begin
+ instr:=Tx86Instruction.Create(Tx86Operand);
+ instr.OpOrder:=op_att;
+ BuildOpcode(instr);
+ instr.AddReferenceSizes;
+ instr.SetInstructionOpsize;
+ {
+ instr.CheckOperandSizes;
+ }
+ instr.ConcatInstruction(curlist);
+ instr.Free;
+ end;
+*)
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+const
+ asmmode_i386_intel_info : tasmmodeinfo =
+ (
+ id : asmmode_i386_intel;
+ idtxt : 'INTEL';
+ casmreader : ti386intreader;
+ );
+
+begin
+ RegisterAsmMode(asmmode_i386_intel_info);
+end.
diff --git a/closures/compiler/i386/rgcpu.pas b/closures/compiler/i386/rgcpu.pas
new file mode 100644
index 0000000000..1bdff50369
--- /dev/null
+++ b/closures/compiler/i386/rgcpu.pas
@@ -0,0 +1,71 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit implements the i386 specific class for the register
+ allocator
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+
+unit rgcpu;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ cpubase,
+ cpuinfo,
+ aasmbase,aasmtai,aasmdata,
+ cclasses,globtype,cgbase,rgobj,rgx86;
+
+ type
+ trgcpu = class(trgx86)
+ procedure add_constraints(reg:Tregister);override;
+ end;
+
+implementation
+
+ uses
+ systems,
+ verbose;
+
+ const
+ { This value is used in tsaved. If the array value is equal
+ to this, then this means that this register is not used.}
+ reg_not_saved = $7fffffff;
+
+{************************************************************************
+ trgcpu
+*************************************************************************}
+
+ procedure trgcpu.add_constraints(reg:Tregister);
+ var
+ supreg : tsuperregister;
+ begin
+ if getsubreg(reg) in [R_SUBL,R_SUBH] then
+ begin
+ { Some registers have no 8-bit subregister }
+ supreg:=getsupreg(reg);
+ add_edge(supreg,RS_ESI);
+ add_edge(supreg,RS_EDI);
+ add_edge(supreg,RS_EBP);
+ end;
+ end;
+
+
+end.
diff --git a/closures/compiler/i386/rropt386.pas b/closures/compiler/i386/rropt386.pas
new file mode 100644
index 0000000000..158ff204b2
--- /dev/null
+++ b/closures/compiler/i386/rropt386.pas
@@ -0,0 +1,371 @@
+{
+ Copyright (c) 1998-2002 by Jonas Maebe, member of the Free Pascal
+ development team
+
+ This unit contains register renaming functionality
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit rropt386;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses aasmbase,aasmtai,aasmdata,aasmcpu;
+
+procedure doRenaming(asml: TAsmList; first, last: tai);
+
+implementation
+
+uses
+ {$ifdef replaceregdebug}cutils,{$endif}
+ verbose,globals,cpubase,daopt386,csopt386,rgobj,
+ cgbase,cgutils,cgobj;
+
+function canBeFirstSwitch(p: taicpu; supreg: tsuperregister): boolean;
+{ checks whether an operation on reg can be switched to another reg without an }
+{ additional mov, e.g. "addl $4,%reg1" can be changed to "leal 4(%reg1),%reg2" }
+begin
+ canBeFirstSwitch := false;
+ case p.opcode of
+ A_MOV,A_MOVZX,A_MOVSX,A_LEA:
+ canBeFirstSwitch :=
+ (p.oper[1]^.typ = top_reg) and
+ (getsupreg(p.oper[1]^.reg) = supreg);
+ A_IMUL:
+ canBeFirstSwitch :=
+ (p.ops >= 2) and
+ (p.oper[0]^.typ = top_const) and
+ (getsupreg(p.oper[p.ops-1]^.reg) = supreg) and
+ (not pTaiprop(p.optinfo)^.FlagsUsed);
+ A_INC,A_DEC:
+ canBeFirstSwitch :=
+ (p.oper[0]^.typ = top_reg) and
+ (p.opsize = S_L) and
+ (not pTaiprop(p.optinfo)^.FlagsUsed);
+ A_SUB,A_ADD:
+ canBeFirstSwitch :=
+ (p.oper[1]^.typ = top_reg) and
+ (p.opsize = S_L) and
+ (getsupreg(p.oper[1]^.reg) = supreg) and
+ (p.oper[0]^.typ <> top_ref) and
+ ((p.opcode <> A_SUB) or
+ (p.oper[0]^.typ = top_const)) and
+ (not pTaiprop(p.optinfo)^.FlagsUsed);
+ A_SHL:
+ canBeFirstSwitch :=
+ (p.opsize = S_L) and
+ (p.oper[1]^.typ = top_reg) and
+ (getsupreg(p.oper[1]^.reg) = supreg) and
+ (p.oper[0]^.typ = top_const) and
+ (p.oper[0]^.val in [1,2,3]) and
+ (not pTaiprop(p.optinfo)^.FlagsUsed);
+ end;
+end;
+
+
+procedure switchReg(var reg: tregister; reg1, reg2: tsuperregister);
+var
+ supreg: tsuperregister;
+begin
+ if (reg = NR_NO) or
+ (getregtype(reg) <> R_INTREGISTER) then
+ exit;
+ supreg := getsupreg(reg);
+ if (supreg = reg1) then
+ setsupreg(reg,reg2)
+ else if (supreg = reg2) then
+ setsupreg(reg,reg1);
+end;
+
+
+procedure switchOp(var op: toper; reg1, reg2: tsuperregister);
+begin
+ case op.typ of
+ top_reg:
+ switchReg(op.reg,reg1,reg2);
+ top_ref:
+ begin
+ switchReg(op.ref^.base,reg1,reg2);
+ switchReg(op.ref^.index,reg1,reg2);
+ end;
+ end;
+end;
+
+
+procedure doSwitchReg(hp: taicpu; reg1,reg2: tsuperregister);
+var
+ opCount: longint;
+begin
+ for opCount := 0 to hp.ops-1 do
+ switchOp(hp.oper[opCount]^,reg1,reg2);
+end;
+
+
+procedure doFirstSwitch(p: taicpu; reg1, reg2: tsuperregister);
+var
+ tmpRef: treference;
+begin
+ case p.opcode of
+ A_MOV,A_MOVZX,A_MOVSX,A_LEA:
+ begin
+ changeOp(p.oper[1]^,reg1,reg2);
+ changeOp(p.oper[0]^,reg2,reg1);
+ end;
+ A_IMUL:
+ begin
+ p.ops := 3;
+ p.loadreg(2,newreg(R_INTREGISTER,reg2,R_SUBWHOLE));
+ changeOp(p.oper[1]^,reg2,reg1);
+ end;
+ A_INC,A_DEC:
+ begin
+ reference_reset(tmpref,1);
+ tmpref.base := newreg(R_INTREGISTER,reg1,R_SUBWHOLE);
+ case p.opcode of
+ A_INC:
+ tmpref.offset := 1;
+ A_DEC:
+ tmpref.offset := -1;
+ end;
+ p.ops := 2;
+ p.opcode := A_LEA;
+ p.loadreg(1,newreg(R_INTREGISTER,reg2,R_SUBWHOLE));
+ p.loadref(0,tmpref);
+ end;
+ A_SUB,A_ADD:
+ begin
+ reference_reset(tmpref,1);
+ tmpref.base := newreg(R_INTREGISTER,reg1,R_SUBWHOLE);
+ case p.oper[0]^.typ of
+ top_const:
+ begin
+ tmpref.offset := longint(p.oper[0]^.val);
+ if p.opcode = A_SUB then
+ tmpref.offset := - tmpRef.offset;
+ end;
+ top_ref:
+ if (p.oper[0]^.ref^.refaddr=addr_full) then
+ tmpref.symbol := p.oper[0]^.ref^.symbol
+ else
+ internalerror(200402263);
+ top_reg:
+ begin
+ { "addl %reg2,%reg1" must become "leal (%reg1,%reg1),%reg2" }
+ { since at this point reg1 holds the value that reg2 would }
+ { otherwise contain }
+ tmpref.index := p.oper[0]^.reg;
+ if (getsupreg(tmpref.index)=reg2) then
+ setsupreg(tmpref.index,reg1);
+ tmpref.scalefactor := 1;
+ end;
+ else internalerror(200010031);
+ end;
+ p.opcode := A_LEA;
+ p.loadref(0,tmpref);
+ p.loadreg(1,newreg(R_INTREGISTER,reg2,R_SUBWHOLE));
+ end;
+ A_SHL:
+ begin
+ reference_reset(tmpref,2);
+ tmpref.index := newreg(R_INTREGISTER,reg1,R_SUBWHOLE);
+ tmpref.scalefactor := 1 shl p.oper[0]^.val;
+ p.opcode := A_LEA;
+ p.loadref(0,tmpref);
+ p.loadreg(1,newreg(R_INTREGISTER,reg2,R_SUBWHOLE));
+ end;
+ else internalerror(200010032);
+ end;
+end;
+
+
+function switchRegs(asml: TAsmList; reg1, reg2: tsuperregister; start: tai): Boolean;
+{ change movl %reg1,%reg2 ... bla ... to ... bla with reg1 and reg2 switched }
+var
+ endP, hp, lastreg1,lastreg2: tai;
+ switchDone, switchLast, tmpResult, sequenceEnd, reg1Modified, reg2Modified: boolean;
+ reg1StillUsed, reg2StillUsed, isInstruction: boolean;
+begin
+ switchRegs := false;
+ tmpResult := true;
+ sequenceEnd := false;
+ reg1Modified := false;
+ reg2Modified := false;
+ endP := start;
+ while tmpResult and not sequenceEnd do
+ begin
+ tmpResult :=
+ getNextInstruction(endP,endP);
+ If tmpResult and
+ not pTaiprop(endp.optinfo)^.canBeRemoved then
+ begin
+ { if the newReg gets stored back to the oldReg, we can change }
+ { "mov %oldReg,%newReg; <operations on %newReg>; mov %newReg, }
+ { %oldReg" to "<operations on %oldReg>" }
+ switchLast := storeBack(start,endP,reg1,reg2);
+ reg1StillUsed := reg1 in pTaiprop(endp.optinfo)^.usedregs;
+ reg2StillUsed := reg2 in pTaiprop(endp.optinfo)^.usedregs;
+ isInstruction := endp.typ = ait_instruction;
+ sequenceEnd :=
+ switchLast or
+ { if both registers are released right before an instruction }
+ { that contains hardcoded regs, it's ok too }
+ (not reg1StillUsed and not reg2StillUsed) or
+ { no support for (i)div, mul and imul with hardcoded operands }
+ (((not isInstruction) or
+ noHardCodedRegs(taicpu(endP),reg1,reg2)) and
+ (not reg1StillUsed or
+ (isInstruction and findRegDealloc(reg1,endP) and
+ regLoadedWithNewValue(reg1,false,taicpu(endP)))) and
+ (not reg2StillUsed or
+ (isInstruction and findRegDealloc(reg2,endP) and
+ regLoadedWithNewValue(reg2,false,taicpu(endP)))));
+
+ { we can't switch reg1 and reg2 in something like }
+ { movl %reg1,%reg2 }
+ { movl (%reg2),%reg2 }
+ { movl 4(%reg1),%reg1 }
+ if reg2Modified and not(reg1Modified) and
+ regReadByInstruction(reg1,endP) then
+ begin
+ tmpResult := false;
+ break
+ end;
+
+ if not reg1Modified then
+ begin
+ reg1Modified := regModifiedByInstruction(reg1,endP);
+ if reg1Modified and not canBeFirstSwitch(taicpu(endP),reg1) then
+ begin
+ tmpResult := false;
+ break;
+ end;
+ end;
+ if not reg2Modified then
+ reg2Modified := regModifiedByInstruction(reg2,endP);
+
+ tmpResult :=
+ ((not isInstruction) or
+ (NoHardCodedRegs(taicpu(endP),reg1,reg2) and
+ RegSizesOk(reg1,reg2,taicpu(endP))));
+
+ if sequenceEnd then
+ break;
+
+ tmpResult :=
+ tmpresult and
+ (endp.typ <> ait_label) and
+ ((not isInstruction) or
+ (not taicpu(endp).is_jmp));
+ end;
+ end;
+
+ if tmpResult and sequenceEnd then
+ begin
+ switchRegs := true;
+ reg1Modified := false;
+ reg2Modified := false;
+ lastreg1 := start;
+ lastreg2 := start;
+ getNextInstruction(start,hp);
+ while hp <> endP do
+ begin
+ if (not pTaiprop(hp.optinfo)^.canberemoved) and
+ (hp.typ = ait_instruction) then
+ begin
+ switchDone := false;
+ if not reg1Modified then
+ begin
+ reg1Modified := regModifiedByInstruction(reg1,hp);
+ if reg1Modified then
+ begin
+ doFirstSwitch(taicpu(hp),reg1,reg2);
+ switchDone := true;
+ end;
+ end;
+ if not switchDone then
+ if reg1Modified then
+ doSwitchReg(taicpu(hp),reg1,reg2)
+ else
+ doReplaceReg(taicpu(hp),reg2,reg1);
+ end;
+ if regininstruction(reg1,hp) then
+ lastreg1 := hp;
+ if regininstruction(reg2,hp) then
+ lastreg2 := hp;
+ getNextInstruction(hp,hp);
+ end;
+ if switchLast then
+ begin
+ lastreg1 := hp;
+ lastreg2 := hp;
+ { this is in case of a storeback, make sure the same size of register }
+ { contents as the initial move is transfered }
+ doSwitchReg(taicpu(hp),reg1,reg2);
+ if taicpu(hp).opsize <> taicpu(start).opsize then
+ begin
+ taicpu(hp).opsize := taicpu(start).opsize;
+ taicpu(hp).oper[0]^.reg := taicpu(start).oper[0]^.reg;
+ taicpu(hp).oper[1]^.reg := taicpu(start).oper[1]^.reg;
+ end;
+ end
+ else
+ getLastInstruction(hp,hp);
+ allocRegBetween(asmL,newreg(R_INTREGISTER,reg1,R_SUBWHOLE),start,lastreg1,
+ ptaiprop(start.optinfo)^.usedregs);
+ allocRegBetween(asmL,newreg(R_INTREGISTER,reg2,R_SUBWHOLE),start,lastreg2,
+ ptaiprop(start.optinfo)^.usedregs);
+ end;
+end;
+
+
+procedure doRenaming(asml: TAsmList; first, last: tai);
+var
+ p: tai;
+begin
+ p := First;
+ SkipHead(p);
+ while p <> last do
+ begin
+ case p.typ of
+ ait_instruction:
+ begin
+ case taicpu(p).opcode of
+ A_MOV:
+ begin
+ if not(pTaiprop(p.optinfo)^.canBeRemoved) and
+ (taicpu(p).oper[0]^.typ = top_reg) and
+ (taicpu(p).oper[1]^.typ = top_reg) and
+ (taicpu(p).opsize = S_L) and
+ (getsupreg(taicpu(p).oper[0]^.reg) in ([RS_EAX,RS_EBX,RS_ECX,RS_EDX,RS_ESI,RS_EDI])) and
+ (getsupreg(taicpu(p).oper[1]^.reg) in ([RS_EAX,RS_EBX,RS_ECX,RS_EDX,RS_ESI,RS_EDI])) then
+ if switchRegs(asml,getsupreg(taicpu(p).oper[0]^.reg),
+ getsupreg(taicpu(p).oper[1]^.reg),p) then
+ begin
+ pTaiprop(p.optinfo)^.canBeRemoved := true;
+ end;
+ end;
+ end;
+ end;
+ end;
+ getNextInstruction(p,p);
+ end;
+end;
+
+
+End.
diff --git a/closures/compiler/ia64/aasmcpu.pas b/closures/compiler/ia64/aasmcpu.pas
new file mode 100644
index 0000000000..35da6c32a5
--- /dev/null
+++ b/closures/compiler/ia64/aasmcpu.pas
@@ -0,0 +1,287 @@
+{
+ Copyright (c) 2000-2006 by Florian Klaempfl
+
+ Contains the assembler object for the ia64
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit aasmcpu;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ globals,verbose,
+ aasmbase,aasmtai,
+ cpubase,
+ cgutils;
+
+
+type
+ pairegalloc = ^tairegalloc;
+ tairegalloc = class(tai)
+ allocation : boolean;
+ reg : tregister;
+ constructor alloc(r : tregister);
+ constructor dealloc(r : tregister);
+ end;
+
+ { Types of operand }
+ toptype=(top_none,top_reg,top_ref,top_const,top_symbol,top_qp);
+
+ paicpu = ^taicpu;
+ taicpu = class(tai)
+ is_jmp : boolean; { is this instruction a jump? (needed for optimizer) }
+ opcode : tasmop;
+ ops : array[0..4] of longint;
+ oper : longint;
+ qp : tqp;
+ ldsttype : tldsttype;
+ hint : thint;
+ { ALU instructions }
+ { A1,A9: integer ALU }
+ constructor op_reg_reg_reg(op : tasmop;const r1,r2,r3 : tregister);
+ { A2,A10: shift left and add }
+ constructor op_reg_reg_const_reg(_qp : tqp;op : tasmop;
+ const r1,r2 : tregister;i : byte;const r3 : tregister);
+ { A3,A4,A5: integer ALU - imm.,register }
+ constructor op_reg_const_reg(_qp : tqp;op : tasmop;
+ const r1 : tregister;i : longint;const r3 : tregister);
+ { A6,A7: integer compare - register,register }
+ constructor op_preg_preg_reg_reg(_qp : tqp;op : tasmop;
+ cond : tasmcond;p1,p2 : tqp;const r2,r3 : tregister);
+ { A8: integer compare - imm.,register }
+ constructor op_preg_preg_const_reg(_qp : tqp;op : tasmop;
+ cond : tasmcond;p1,p2 : tqp;i : longint;const r3 : tregister);
+(*!!!!!!!
+ { multimedia shift and multiply }
+ constructor op_reg_reg_reg_const(_qp : tqp;
+ { multimedia mux }
+ constructor op_reg_reg_mbtype(_qp : tqp;
+ { multimedia shift fixed }
+ constructor op_reg_reg_const(_qp : tqp;
+ { div. }
+ constructor op_reg_reg(_qp : tqp;
+ { mm extract }
+ constructor op_reg_reg_const_const(_qp : tqp;
+ { zero and deposit imm }
+ constructor op_reg_const_const_const(_qp : tqp;
+ { deposit imm }
+ constructor op_reg_const_reg_const_const(_qp : tqp;
+ { deposit }
+ constructor op_reg_reg_reg_const_const(_qp : tqp;
+ { test bit }
+ { !!!! here we need also to take care of the postfix }
+ constructor op_preg_preg_reg_const(_qp : tqp;
+ { test NaT }
+ { !!!! here we need also to take care of the postfix }
+ constructor op_preg_preg_reg(_qp : tqp;
+
+ { -------- here are some missed ----------- }
+ *)
+
+ { M1: integer load }
+ { M4: integer store }
+ { M6: floating-point load }
+ { M9: floating-point store }
+ constructor op_reg_ref(_qp : tqp;op : tasmop;postfix : tldsttype;
+ _hint : thint;const r1 : tregister;ref : treference);
+
+ { M2: integer load incremented by register }
+ { M7: floating-point load incremented by register }
+ constructor op_reg_ref_reg(_qp : tqp;op : tasmop;postfix : tldsttype;
+ _hint : thint;const r1 : tregister;const ref : treference;
+ const r2 : tregister);
+
+ { M3: integer load increment by imm. }
+ { M5: integer store increment by imm. }
+ { M8: floating-point load increment by imm. }
+ { M10: floating-point store increment by imm. }
+ constructor op_reg_ref_const(_qp : tqp;op : tasmop;postfix : tldsttype;
+ _hint : thint;const r1 : tregister;ref : treference;i : longint);
+
+ { M11: floating-point load pair}
+ constructor op_reg_ref(_qp : tqp;op : tasmop;postfix : tldsttype;
+ _hint : thint;const r1,r2 : tregister;ref : treference);
+
+ { M12: floating-point load pair increment by imm. }
+ constructor op_reg_ref(_qp : tqp;op : tasmop;postfix : tldsttype;
+ _hint : thint;const r1,r2 : tregister;ref : treference;i : longint);
+
+ { X1: break/nop }
+ constructor op_const62(_qp : tqp;op : tasmop;i : int64);
+ { X2: move imm64 }
+ constructor op_reg_const64(_qp : tqp;op : tasmop;const r1 : tregister;
+ i : int64);
+ end;
+
+ { the following objects are special for the ia64 }
+ { they decribe a stop and the bundles }
+ paistop = ^taistop;
+ taistop = class(tai)
+ constructor init;
+ end;
+
+ { a second underscro indicates a stop }
+ tbundletemplate = (but_none,but_mii,but_mii_,
+ but_mi_i,but_mi_i_,but_mlx,but_mlx_,
+ but_mmi,but_mmi_,but_m_mi,but_m_mi_,
+ but_mfi,but_mfi_,but_mmf,but_mmf_,
+ but_mif,but_mib_,but_mbb,but_mbb_,
+ but_bbb,but_bbb_,but_mmb,but_mmb_,
+ but_mfb,but_mfb_);
+
+ paibundle = ^taibundle;
+ taibundle = class(tai)
+ template : tbundletemplate;
+ instructions : array[0..1] of paicpu;
+ end;
+
+implementation
+
+
+{*****************************************************************************
+ TaiStop
+*****************************************************************************}
+
+ constructor taistop.init;
+
+ begin
+ inherited create;
+ typ:=ait_stop;
+ end;
+
+
+{*****************************************************************************
+ TaiRegAlloc
+*****************************************************************************}
+
+ constructor tairegalloc.alloc(r : tregister);
+ begin
+ inherited create;
+ typ:=ait_regalloc;
+ allocation:=true;
+ reg:=r;
+ end;
+
+
+ constructor tairegalloc.dealloc(r : tregister);
+ begin
+ inherited create;
+ typ:=ait_regalloc;
+ allocation:=false;
+ reg:=r;
+ end;
+
+
+{*****************************************************************************
+ Taicpu
+*****************************************************************************}
+
+ { ALU instructions }
+ { A1,A9: integer ALU }
+ constructor taicpu.op_reg_reg_reg(op : tasmop;const r1,r2,r3 : tregister);
+
+ begin
+ end;
+
+ { A2,A10: shift left and add }
+ constructor taicpu.op_reg_reg_const_reg(_qp : tqp;op : tasmop;
+ const r1,r2 : tregister;i : byte;const r3 : tregister);
+
+ begin
+ end;
+
+ { A3,A4,A5: integer ALU - imm.,register }
+ constructor taicpu.op_reg_const_reg(_qp : tqp;op : tasmop;
+ const r1 : tregister;i : longint;const r3 : tregister);
+
+ begin
+ end;
+
+ { A6,A7: integer compare - register,register }
+ constructor taicpu.op_preg_preg_reg_reg(_qp : tqp;op : tasmop;
+ cond : tasmcond;p1,p2 : tqp;const r2,r3 : tregister);
+
+ begin
+ end;
+
+ { A8: integer compare - imm.,register }
+ constructor taicpu.op_preg_preg_const_reg(_qp : tqp;op : tasmop;
+ cond : tasmcond;p1,p2 : tqp;i : longint;const r3 : tregister);
+
+ begin
+ end;
+
+ { M1: integer load }
+ { M4: integer store }
+ { M6: floating-point load }
+ { M9: floating-point store }
+ constructor taicpu.op_reg_ref(_qp : tqp;op : tasmop;postfix : tldsttype;
+ _hint : thint;const r1 : tregister;ref : treference);
+
+ begin
+ end;
+
+ { M2: integer load incremented by register }
+ { M7: floating-point load incremented by register }
+ constructor taicpu.op_reg_ref_reg(_qp : tqp;op : tasmop;postfix : tldsttype;
+ _hint : thint;const r1 : tregister;const ref : treference;
+ const r2 : tregister);
+
+ begin
+ end;
+
+ { M3: integer load increment by imm. }
+ { M5: integer store increment by imm. }
+ { M8: floating-point load increment by imm. }
+ { M10: floating-point store increment by imm. }
+ constructor taicpu.op_reg_ref_const(_qp : tqp;op : tasmop;postfix : tldsttype;
+ _hint : thint;const r1 : tregister;ref : treference;i : longint);
+
+ begin
+ end;
+
+ { M11: floating-point load pair}
+ constructor taicpu.op_reg_ref(_qp : tqp;op : tasmop;postfix : tldsttype;
+ _hint : thint;const r1,r2 : tregister;ref : treference);
+
+ begin
+ end;
+
+ { M12: floating-point load pair increment by imm. }
+ constructor taicpu.op_reg_ref(_qp : tqp;op : tasmop;postfix : tldsttype;
+ _hint : thint;const r1,r2 : tregister;ref : treference;i : longint);
+
+ begin
+ end;
+
+ { X1: break/nop }
+ constructor taicpu.op_const62(_qp : tqp;op : tasmop;i : int64);
+ { X2: move imm64 }
+
+ begin
+ end;
+
+ constructor taicpu.op_reg_const64(_qp : tqp;op : tasmop;const r1 : tregister;
+ i : int64);
+
+ begin
+ end;
+
+end.
diff --git a/closures/compiler/ia64/cpubase.pas b/closures/compiler/ia64/cpubase.pas
new file mode 100644
index 0000000000..0590be4ec5
--- /dev/null
+++ b/closures/compiler/ia64/cpubase.pas
@@ -0,0 +1,149 @@
+{
+ Copyright (C) 2000-2006 by Florian Klaempfl
+
+ this unit implements the base types for the iA-64 architecture
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit cpubase;
+
+ interface
+
+ uses
+ cutils,
+ globals,
+ systems,
+ cpuinfo,
+ cgbase;
+
+type
+ tasmop = (A_ADD,A_SUB,A_ADDP4,A_AND,A_ANDCM,A_OR,A_XOR,A_SHLADD,
+ A_SHLADDP4,A_ADDS,A_ADDL,A_CMP,A_CMP4,A_PADD1,A_PADD2,
+ A_PADD4,A_PSUB1,A_PSUB2,A_PSUB4,A_PAVG1,A_PAVG2,A_PAVGSUB1,
+ A_PAVGSUB2,A_PCMP1,A_PCMP2,A_PCMP4,A_PSHLADD2,A_PSHRADD2,
+ A_PMPY2,A_MIX1,A_MIX2,A_MIX4,A_PACK2,A_PACK4,A_UNPACK2,
+ A_UNPACK4,A_PMIN1,A_PMAX1,A_PMIN2,A_PMAX2,A_PSAD1,A_MUX1,
+ A_MUX2,A_PSHR2,A_PSHR4,A_SHR,A_PSHL2,A_SHL4,A_SHL,
+ A_POPCNT,A_SHRP,A_EXTR,A_DEP,A_TBIT,A_TNAT,A_BREAK,
+ A_NOP,A_CHK,A_MOV,A_ZX1,A_ZX2,A_ZXT4,A_SXT1,A_SXT2,A_SXT4,
+ A_CXZ1,A_CZX2,A_LD1,A_LD2,A_LD4,A_LD8,A_ST1,A_ST2,A_ST4,
+ A_ST8,A_LDFS,A_LDFD,A_LDF8,A_LDFE,A_LDF,A_STFS,A_STFD,A_STF8,
+ A_STFE,A_STF,A_LDFPS,A_LDFPD,A_LDFP8,A_LFETCH,A_CMPXCHG1,
+ A_CMPXCHG2,A_CMPXHG4,A_CMPXCHG8,A_XCHG1,A_XCHG2,A_XCHG4,
+ A_XCHG8,A_FETCHADD4,A_FETCHADD8,A_SETF,A_GETF,
+ A_INVALA,A_MF,A_SRLZ,A_SYNC,A_FLUSHRS,A_FC,A_ALLOC,A_SUM,
+ A_RUM,A_BR,A_CLRRRB,A_FMA,A_FPMA,A_FMS,A_FPMS,A_FNMA,A_FPNMA,
+ A_XMA,A_FSELECT,A_FCLASS,A_FRCPA,A_FPRCPA,A_FRSQRTA,
+ A_FPRSQRTA,A_FMIN,A_FMAX,A_FAMIN,A_FAMAX,A_FPMIN,A_FPMAX,
+ A_FPAMIN,A_FPAMAX,A_FPCMP,A_FMERGE,A_FMIX,A_FSXT,A_FPACK,
+ A_FSWAP,A_FAND,A_FANDCM,A_FOR,A_FXOR,A_FPMERGE,A_FCVT,
+ A_FPCVT,A_FSETC,A_FCLRT,A_FCHKF,A_MOVL);
+
+Const
+ firstop = low(tasmop);
+ lastop = high(tasmop);
+
+type
+ TAsmCond = (C_NONE,C_LT,C_LTU,C_EQ,C_LT_UNC,C_LTU_UNC,C_EQ_UNC,
+ C_EQ_AND,C_EQ_OR,C_EQ_OR_ANDCM,C_NE_AND,C_NE_OR);
+
+ THint = (H_NONE,H_NT1,H_NT2,H_NTA);
+ TLdStType = (LST_NONE,LST_S,LST_A,LSR_SA,LST_BIAS,LST_ACQ,LST_C_CLR,
+ LST_FILL,LST_C_NC,LST_C_CLR_ACQ,LST_REL,
+ LST_SPILL);
+
+{*****************************************************************************
+ Flags
+*****************************************************************************}
+
+ type
+ TResFlags = (F_NONE,F_LT,F_LTU,F_EQ,F_LT_UNC,F_LTU_UNC,F_EQ_UNC,
+ F_EQ_AND,F_EQ_OR,F_EQ_OR_ANDCM,F_NE_AND,F_NE_OR);
+
+Type
+ TRegister = (R_NO, { R_NO is Mandatory, signifies no register }
+ R_0,R_1,R_2,R_3,R_4,R_5,R_6,R_7,R_8,R_9,
+ R_10,R_11,R_12,R_13,R_14,R_15,R_16,R_17,R_18,R_19,
+ R_20,R_21,R_22,R_23,R_24,R_25,R_26,R_27,R_28,R_29,
+ R_30,R_31,
+ R_F0,R_F1,R_F2,R_F3,R_F4,R_F5,R_F6,R_F7,R_F8,R_F9,
+ R_F10,R_F11,R_F12,R_F13,R_F14,R_F15,R_F16,R_F17,R_F18,R_F19,
+ R_F20,R_F21,R_F22,R_F23,R_F24,R_F25,R_F26,R_F27,R_F28,R_F29,
+ R_F30,R_F31);
+
+ TRegisterset = Set of TRegister;
+
+ { -1 indicates no qualifying prediction }
+ tqp = -1..63;
+
+const
+ qp_none : tqp = -1;
+
+{ Constants describing the registers }
+
+Const
+ intregs = [R_0..R_31];
+ fpuregs = [R_F0..R_F31];
+ mmregs = [];
+
+ maxvarregs = 128;
+ maxfpuvarregs = 128;
+
+ max_operands = 4;
+
+{*****************************************************************************
+ Default generic sizes
+*****************************************************************************}
+
+ { Defines the default address size for a processor, }
+ OS_ADDR = OS_64;
+ { the natural int size for a processor, }
+ OS_INT = OS_64;
+ OS_SINT = OS_S64;
+ { the maximum float size for a processor, }
+ OS_FLOAT = OS_F80;
+ { the size of a vector register for a processor }
+ OS_VECTOR = OS_M128;
+
+{*****************************************************************************
+ GCC /ABI linking information
+*****************************************************************************}
+
+ {# Registers which must be saved when calling a routine declared as
+ cppdecl, cdecl, stdcall, safecall, palmossyscall. The registers
+ saved should be the ones as defined in the target ABI and / or GCC.
+
+ This value can be deduced from CALLED_USED_REGISTERS array in the
+ GCC source.
+ }
+ std_saved_registers = [R_9..R_14,R_F2..R_F9];
+ {# Required parameter alignment when calling a routine declared as
+ stdcall and cdecl. The alignment value should be the one defined
+ by GCC or the target ABI.
+
+ The value of this constant is equal to the constant
+ PARM_BOUNDARY / BITS_PER_UNIT in the GCC source.
+ }
+ std_param_align = 8;
+
+{*****************************************************************************
+ Opcode propeties (needed for optimizer)
+*****************************************************************************}
+
+implementation
+
+end.
diff --git a/closures/compiler/ia64/cpuinfo.pas b/closures/compiler/ia64/cpuinfo.pas
new file mode 100644
index 0000000000..51e6df6f23
--- /dev/null
+++ b/closures/compiler/ia64/cpuinfo.pas
@@ -0,0 +1,83 @@
+{
+ Copyright (c) 1998-2006 by Florian Klaempfl
+
+ Basic Processor information
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+Unit cpuinfo;
+
+{$i fpcdefs.inc}
+
+Interface
+
+uses
+ globtype;
+
+Type
+ bestreal = extended;
+ ts32real = single;
+ ts64real = double;
+ ts80real = extended;
+ ts128real = type extended;
+ ts64comp = type extended;
+
+ pbestreal=^bestreal;
+
+ { possible supported processors for this target }
+ tcputype =
+ (cpu_none,
+ cpu_itanium
+ );
+
+ tfputype =
+ (fpu_none,
+ fpu_itanium
+ );
+
+const
+ { calling conventions supported by the code generator }
+ supported_calling_conventions : tproccalloptions = [
+ pocall_internproc,
+ pocall_stdcall,
+ pocall_cdecl,
+ pocall_cppdecl
+ ];
+
+
+ cputypestr : array[tcputype] of string[10] = ('',
+ 'ITANIUM'
+ );
+
+ fputypestr : array[tfputype] of string[6] = ('',
+ 'ITANIUM'
+ );
+
+ { Supported optimizations, only used for information }
+ supported_optimizerswitches = [cs_opt_peephole,cs_opt_regvar,cs_opt_stackframe,
+ cs_opt_asmcse,cs_opt_loopunroll,cs_opt_uncertain,
+ cs_opt_nodecse];
+
+ level1optimizerswitches = [cs_opt_level1,cs_opt_peephole];
+ level2optimizerswitches = level1optimizerswitches +
+ [cs_opt_level2,cs_opt_regvar,cs_opt_stackframe,cs_opt_asmcse,cs_opt_nodecse];
+ level3optimizerswitches = level2optimizerswitches + [cs_opt_level3{,cs_opt_loopunroll}];
+
+Implementation
+
+end.
+
diff --git a/closures/compiler/ia64/ia64reg.dat b/closures/compiler/ia64/ia64reg.dat
new file mode 100644
index 0000000000..dd2dac4515
--- /dev/null
+++ b/closures/compiler/ia64/ia64reg.dat
@@ -0,0 +1,268 @@
+;
+; iA-64 registers
+; This file is generate with help of fpc/compiler/utils/gia64reg,
+; please try to use this generator before you do error prone and tedious
+; editing by hand
+;
+; layout
+; <name>,<type>,<value>,<stdname>,<gasname>
+;
+NO,$00,$00,INVALID,INVALID
+
+R0,$01,0,r0,r0
+R1,$01,1,r1,r1
+R2,$01,2,r2,r2
+R3,$01,3,r3,r3
+R4,$01,4,r4,r4
+R5,$01,5,r5,r5
+R6,$01,6,r6,r6
+R7,$01,7,r7,r7
+R8,$01,8,r8,r8
+R9,$01,9,r9,r9
+R10,$01,10,r10,r10
+R11,$01,11,r11,r11
+R12,$01,12,r12,r12
+R13,$01,13,r13,r13
+R14,$01,14,r14,r14
+R15,$01,15,r15,r15
+R16,$01,16,r16,r16
+R17,$01,17,r17,r17
+R18,$01,18,r18,r18
+R19,$01,19,r19,r19
+R20,$01,20,r20,r20
+R21,$01,21,r21,r21
+R22,$01,22,r22,r22
+R23,$01,23,r23,r23
+R24,$01,24,r24,r24
+R25,$01,25,r25,r25
+R26,$01,26,r26,r26
+R27,$01,27,r27,r27
+R28,$01,28,r28,r28
+R29,$01,29,r29,r29
+R30,$01,30,r30,r30
+R31,$01,31,r31,r31
+R32,$01,32,r32,r32
+R33,$01,33,r33,r33
+R34,$01,34,r34,r34
+R35,$01,35,r35,r35
+R36,$01,36,r36,r36
+R37,$01,37,r37,r37
+R38,$01,38,r38,r38
+R39,$01,39,r39,r39
+R40,$01,40,r40,r40
+R41,$01,41,r41,r41
+R42,$01,42,r42,r42
+R43,$01,43,r43,r43
+R44,$01,44,r44,r44
+R45,$01,45,r45,r45
+R46,$01,46,r46,r46
+R47,$01,47,r47,r47
+R48,$01,48,r48,r48
+R49,$01,49,r49,r49
+R50,$01,50,r50,r50
+R51,$01,51,r51,r51
+R52,$01,52,r52,r52
+R53,$01,53,r53,r53
+R54,$01,54,r54,r54
+R55,$01,55,r55,r55
+R56,$01,56,r56,r56
+R57,$01,57,r57,r57
+R58,$01,58,r58,r58
+R59,$01,59,r59,r59
+R60,$01,60,r60,r60
+R61,$01,61,r61,r61
+R62,$01,62,r62,r62
+R63,$01,63,r63,r63
+R64,$01,64,r64,r64
+R65,$01,65,r65,r65
+R66,$01,66,r66,r66
+R67,$01,67,r67,r67
+R68,$01,68,r68,r68
+R69,$01,69,r69,r69
+R70,$01,70,r70,r70
+R71,$01,71,r71,r71
+R72,$01,72,r72,r72
+R73,$01,73,r73,r73
+R74,$01,74,r74,r74
+R75,$01,75,r75,r75
+R76,$01,76,r76,r76
+R77,$01,77,r77,r77
+R78,$01,78,r78,r78
+R79,$01,79,r79,r79
+R80,$01,80,r80,r80
+R81,$01,81,r81,r81
+R82,$01,82,r82,r82
+R83,$01,83,r83,r83
+R84,$01,84,r84,r84
+R85,$01,85,r85,r85
+R86,$01,86,r86,r86
+R87,$01,87,r87,r87
+R88,$01,88,r88,r88
+R89,$01,89,r89,r89
+R90,$01,90,r90,r90
+R91,$01,91,r91,r91
+R92,$01,92,r92,r92
+R93,$01,93,r93,r93
+R94,$01,94,r94,r94
+R95,$01,95,r95,r95
+R96,$01,96,r96,r96
+R97,$01,97,r97,r97
+R98,$01,98,r98,r98
+R99,$01,99,r99,r99
+R100,$01,100,r100,r100
+R101,$01,101,r101,r101
+R102,$01,102,r102,r102
+R103,$01,103,r103,r103
+R104,$01,104,r104,r104
+R105,$01,105,r105,r105
+R106,$01,106,r106,r106
+R107,$01,107,r107,r107
+R108,$01,108,r108,r108
+R109,$01,109,r109,r109
+R110,$01,110,r110,r110
+R111,$01,111,r111,r111
+R112,$01,112,r112,r112
+R113,$01,113,r113,r113
+R114,$01,114,r114,r114
+R115,$01,115,r115,r115
+R116,$01,116,r116,r116
+R117,$01,117,r117,r117
+R118,$01,118,r118,r118
+R119,$01,119,r119,r119
+R120,$01,120,r120,r120
+R121,$01,121,r121,r121
+R122,$01,122,r122,r122
+R123,$01,123,r123,r123
+R124,$01,124,r124,r124
+R125,$01,125,r125,r125
+R126,$01,126,r126,r126
+R127,$01,127,r127,r127
+
+F0,$02,0,r0,r0
+F1,$02,1,r1,r1
+F2,$02,2,r2,r2
+F3,$02,3,r3,r3
+F4,$02,4,r4,r4
+F5,$02,5,r5,r5
+F6,$02,6,r6,r6
+F7,$02,7,r7,r7
+F8,$02,8,r8,r8
+F9,$02,9,r9,r9
+F10,$02,10,r10,r10
+F11,$02,11,r11,r11
+F12,$02,12,r12,r12
+F13,$02,13,r13,r13
+F14,$02,14,r14,r14
+F15,$02,15,r15,r15
+F16,$02,16,r16,r16
+F17,$02,17,r17,r17
+F18,$02,18,r18,r18
+F19,$02,19,r19,r19
+F20,$02,20,r20,r20
+F21,$02,21,r21,r21
+F22,$02,22,r22,r22
+F23,$02,23,r23,r23
+F24,$02,24,r24,r24
+F25,$02,25,r25,r25
+F26,$02,26,r26,r26
+F27,$02,27,r27,r27
+F28,$02,28,r28,r28
+F29,$02,29,r29,r29
+F30,$02,30,r30,r30
+F31,$02,31,r31,r31
+F32,$02,32,r32,r32
+F33,$02,33,r33,r33
+F34,$02,34,r34,r34
+F35,$02,35,r35,r35
+F36,$02,36,r36,r36
+F37,$02,37,r37,r37
+F38,$02,38,r38,r38
+F39,$02,39,r39,r39
+F40,$02,40,r40,r40
+F41,$02,41,r41,r41
+F42,$02,42,r42,r42
+F43,$02,43,r43,r43
+F44,$02,44,r44,r44
+F45,$02,45,r45,r45
+F46,$02,46,r46,r46
+F47,$02,47,r47,r47
+F48,$02,48,r48,r48
+F49,$02,49,r49,r49
+F50,$02,50,r50,r50
+F51,$02,51,r51,r51
+F52,$02,52,r52,r52
+F53,$02,53,r53,r53
+F54,$02,54,r54,r54
+F55,$02,55,r55,r55
+F56,$02,56,r56,r56
+F57,$02,57,r57,r57
+F58,$02,58,r58,r58
+F59,$02,59,r59,r59
+F60,$02,60,r60,r60
+F61,$02,61,r61,r61
+F62,$02,62,r62,r62
+F63,$02,63,r63,r63
+F64,$02,64,r64,r64
+F65,$02,65,r65,r65
+F66,$02,66,r66,r66
+F67,$02,67,r67,r67
+F68,$02,68,r68,r68
+F69,$02,69,r69,r69
+F70,$02,70,r70,r70
+F71,$02,71,r71,r71
+F72,$02,72,r72,r72
+F73,$02,73,r73,r73
+F74,$02,74,r74,r74
+F75,$02,75,r75,r75
+F76,$02,76,r76,r76
+F77,$02,77,r77,r77
+F78,$02,78,r78,r78
+F79,$02,79,r79,r79
+F80,$02,80,r80,r80
+F81,$02,81,r81,r81
+F82,$02,82,r82,r82
+F83,$02,83,r83,r83
+F84,$02,84,r84,r84
+F85,$02,85,r85,r85
+F86,$02,86,r86,r86
+F87,$02,87,r87,r87
+F88,$02,88,r88,r88
+F89,$02,89,r89,r89
+F90,$02,90,r90,r90
+F91,$02,91,r91,r91
+F92,$02,92,r92,r92
+F93,$02,93,r93,r93
+F94,$02,94,r94,r94
+F95,$02,95,r95,r95
+F96,$02,96,r96,r96
+F97,$02,97,r97,r97
+F98,$02,98,r98,r98
+F99,$02,99,r99,r99
+F100,$02,100,r100,r100
+F101,$02,101,r101,r101
+F102,$02,102,r102,r102
+F103,$02,103,r103,r103
+F104,$02,104,r104,r104
+F105,$02,105,r105,r105
+F106,$02,106,r106,r106
+F107,$02,107,r107,r107
+F108,$02,108,r108,r108
+F109,$02,109,r109,r109
+F110,$02,110,r110,r110
+F111,$02,111,r111,r111
+F112,$02,112,r112,r112
+F113,$02,113,r113,r113
+F114,$02,114,r114,r114
+F115,$02,115,r115,r115
+F116,$02,116,r116,r116
+F117,$02,117,r117,r117
+F118,$02,118,r118,r118
+F119,$02,119,r119,r119
+F120,$02,120,r120,r120
+F121,$02,121,r121,r121
+F122,$02,122,r122,r122
+F123,$02,123,r123,r123
+F124,$02,124,r124,r124
+F125,$02,125,r125,r125
+F126,$02,126,r126,r126
+F127,$02,127,r127,r127
diff --git a/closures/compiler/impdef.pas b/closures/compiler/impdef.pas
new file mode 100644
index 0000000000..7cb0b8fee0
--- /dev/null
+++ b/closures/compiler/impdef.pas
@@ -0,0 +1,473 @@
+{
+ Copyright (c) 1998-2002 by Pavel
+
+ This unit finds the export defs from PE files
+
+ C source code of DEWIN Windows disassembler (written by A. Milukov) was
+ partially used
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit impdef;
+
+{$ifndef STANDALONE}
+ {$i fpcdefs.inc}
+{$endif}
+
+interface
+
+ uses
+ SysUtils;
+
+ var
+ as_name,
+ ar_name : string;
+
+ function makedef(const binname,
+{$IFDEF STANDALONE}
+ textname,
+{$ENDIF}
+ libname:string):longbool;
+
+
+implementation
+
+{$IFDEF STANDALONE}
+var
+ __textname : string;
+const
+ kind : array[longbool] of pchar=('',' DATA');
+{$ENDIF}
+
+var
+ f:file;
+{$IFDEF STANDALONE}
+ t:text;
+ FileCreated:longbool;
+{$ENDIF}
+ lname:string;
+ impname:string;
+ TheWord:array[0..1]of char;
+ PEoffset:cardinal;
+ loaded:longint;
+
+function DOSstubOK(var x:cardinal):longbool;
+begin
+ blockread(f,TheWord,2,loaded);
+ if loaded<>2 then
+ DOSstubOK:=false
+ else
+ begin
+ DOSstubOK:=TheWord='MZ';
+ seek(f,$3C);
+ blockread(f,x,4,loaded);
+ if(loaded<>4)or(x>filesize(f))then
+ DOSstubOK:=false;
+ end;
+end;
+
+
+function isPE(x:longint):longbool;
+begin
+ seek(f,x);
+ blockread(f,TheWord,2,loaded);
+ isPE:=(loaded=2)and(TheWord='PE');
+end;
+
+
+var
+ cstring : array[0..127]of char;
+function GetEdata(PE:cardinal):longbool;
+type
+ TObjInfo=packed record
+ ObjName:array[0..7]of char;
+ VirtSize,
+ VirtAddr,
+ RawSize,
+ RawOffset,
+ Reloc,
+ LineNum:cardinal;
+ RelCount,
+ LineCount:word;
+ flags:cardinal;
+ end;
+var
+ i:cardinal;
+ ObjOfs:cardinal;
+ Obj:TObjInfo;
+ APE_obj,APE_Optsize:word;
+ ExportRVA:cardinal;
+ delta:cardinal;
+const
+ IMAGE_SCN_CNT_CODE=$00000020;
+ const
+{$ifdef unix}
+ DirSep = '/';
+{$else}
+ {$if defined(amiga) or defined(morphos)}
+ DirSep = '/';
+ {$else}
+ DirSep = '\';
+ {$endif}
+{$endif}
+var
+ path:string;
+ _d:dirstr;
+ _n:namestr;
+ _e:extstr;
+ common_created:longbool;
+procedure cleardir(const s,ext:string);
+ var
+ ff:file;
+ dir:searchrec;
+ attr:word;
+ begin
+ findfirst(s+dirsep+ext,anyfile,dir);
+ while (doserror=0) do
+ begin
+ assign(ff,s+dirsep+dir.name);
+ GetFattr(ff,attr);
+ if not((DOSError<>0)or(Attr and Directory<>0))then
+ Erase(ff);
+ findnext(dir);
+ end;
+ findclose(dir);
+ end;
+procedure CreateTempDir(const s:string);
+ var
+ attr:word;
+ ff:file;
+ begin
+ assign(ff,s);
+ GetFattr(ff,attr);
+ if DosError=0 then
+ begin
+ cleardir(s,'*.sw');
+ cleardir(s,'*.swo');
+ end
+ else
+ begin
+ {$push} {$I-}
+ mkdir(s);
+ {$pop}
+ if ioresult<>0 then;
+ end;
+ end;
+procedure call_as(const name:string);
+ begin
+ FlushOutput;
+ ExecuteProcess(as_name,'-o '+name+'o '+name);
+ end;
+procedure call_ar;
+ var
+ f:file;
+ attr:word;
+ begin
+{$IFDEF STANDALONE}
+ if impname='' then
+ exit;
+{$ENDIF}
+ assign(f,impname);
+ GetFAttr(f,attr);
+ If DOSError=0 then
+ erase(f);
+ FlushOutput;
+ ExecuteProcess(ar_name,'rs '+impname+' '+path+dirsep+'*.swo');
+ cleardir(path,'*.sw');
+ cleardir(path,'*.swo');
+ {$push} {$I-}
+ RmDir(path);
+ {$pop}
+ if ioresult<>0 then;
+ end;
+procedure makeasm(index:cardinal;name:pchar;isData:longbool);
+ type
+ tt=array[1..1]of pchar;
+ pt=^tt;
+ const
+ fn_template:array[1..24]of pchar=(
+ '.section .idata$2',
+ '.rva .L4',
+ '.long 0,0',
+ '.rva ',
+ '.rva .L5',
+ '.section .idata$4',
+ '.L4:',
+ '.rva .L6',
+ '.long 0',
+ '.section .idata$5',
+ '.L5:',
+ '.text',
+ '.globl ',
+ ':',
+ 'jmp *.L7',
+ '.balign 4,144',
+ '.section .idata$5',
+ '.L7:',
+ '.rva .L6',
+ '.long 0',
+ '.section .idata$6',
+ '.L6:',
+ '.short 0',
+ '.ascii "\000"'
+ );
+ var_template:array[1..19]of pchar=(
+ '.section .idata$2',
+ '.rva .L7',
+ '.long 0,0',
+ '.rva ',
+ '.rva .L8',
+ '.section .idata$4',
+ '.L7:',
+ '.rva .L9',
+ '.long 0',
+ '.section .idata$5',
+ '.L8:',
+ '.globl ',
+ ':',
+ '.rva .L9',
+ '.long 0',
+ '.section .idata$6',
+ '.L9:',
+ '.short 0',
+ '.ascii "\000"'
+ );
+ __template:array[longbool]of pointer=(@fn_template,@var_template);
+ common_part:array[1..5]of pchar=(
+ '.balign 2,0',
+ '.section .idata$7',
+ '.globl ',
+ ':',
+ '.ascii "\000"'
+ );
+ posit:array[longbool,1..4]of longint=((4,13,14,24),(4,12,13,19));
+ var
+ template:array[longbool]of pt absolute __template;
+ f:text;
+ s:string;
+ i:longint;
+ n:string;
+ common_name,asmout:string;
+ __d:dirstr;
+ __n:namestr;
+ __x:extstr;
+ begin
+ if not common_created then
+ begin
+ common_name:='_$'+_n+'@common';
+ asmout:=path+dirsep+'0.sw';
+ assign(f,asmout);
+ rewrite(f);
+ for i:=1 to 5 do
+ begin
+ s:=StrPas(Common_part[i]);
+ case i of
+ 3:
+ s:=s+common_name;
+ 4:
+ s:=common_name+s;
+ 5:
+ begin
+ fsplit(lname,__d,__n,__x);
+ insert(__n+__x,s,9);
+ end;
+ end;
+ writeln(f,s);
+ end;
+ close(f);
+ call_as(asmout);
+ common_created:=true;
+ end;
+ n:=strpas(name);
+ str(succ(index):0,s);
+ asmout:=path+dirsep+s+'.sw';
+ assign(f,asmout);
+ rewrite(f);
+ for i:=1 to posit[isData,4]do
+ begin
+ s:=StrPas(template[isData]^[i]);
+ if i=posit[isData,1]then
+ s:=s+common_name
+ else if i=posit[isData,2]then
+ s:=s+n
+ else if i=posit[isData,3]then
+ s:=n+s
+ else if i=posit[isData,4]then
+ insert(n,s,9);
+ writeln(f,s);
+ end;
+ close(f);
+ call_as(asmout);
+ end;
+procedure ProcessEdata;
+ type
+ a8=array[0..7]of char;
+ function GetSectionName(rva:cardinal;var Flags:cardinal):a8;
+ var
+ i:cardinal;
+ LocObjOfs:cardinal;
+ LocObj:TObjInfo;
+ begin
+ GetSectionName:='';
+ Flags:=0;
+ LocObjOfs:=APE_OptSize+PEoffset+24;
+ for i:=1 to APE_obj do
+ begin
+ seek(f,LocObjOfs);
+ blockread(f,LocObj,sizeof(LocObj));
+ if(rva>=LocObj.VirtAddr)and(rva<=LocObj.VirtAddr+LocObj.RawSize)then
+ begin
+ GetSectionName:=a8(LocObj.ObjName);
+ Flags:=LocObj.flags;
+ end;
+ end;
+ end;
+ var
+ j,Fl:cardinal;
+ ulongval,procEntry:cardinal;
+ Ordinal:word;
+ isData:longbool;
+ ExpDir:packed record
+ flag,
+ stamp:cardinal;
+ Major,
+ Minor:word;
+ Name,
+ Base,
+ NumFuncs,
+ NumNames,
+ AddrFuncs,
+ AddrNames,
+ AddrOrds:cardinal;
+ end;
+ begin
+ with Obj do
+ begin
+ seek(f,RawOffset+delta);
+ blockread(f,ExpDir,sizeof(ExpDir));
+ fsplit(impname,_d,_n,_e);
+ path:=_d+_n+'.ils';
+{$IFDEF STANDALONE}
+ if impname<>'' then
+{$ENDIF}
+ CreateTempDir(path);
+ Common_created:=false;
+ for j:=0 to pred(ExpDir.NumNames)do
+ begin
+ seek(f,RawOffset-VirtAddr+ExpDir.AddrOrds+j*2);
+ blockread(f,Ordinal,2);
+ seek(f,RawOffset-VirtAddr+ExpDir.AddrFuncs+Cardinal(Ordinal*4));
+ blockread(f,ProcEntry,4);
+ seek(f,RawOffset-VirtAddr+ExpDir.AddrNames+j*4);
+ blockread(f,ulongval,4);
+ seek(f,RawOffset-VirtAddr+ulongval);
+ blockread(f,cstring,sizeof(cstring));
+{$IFDEF STANDALONE}
+ if not FileCreated then
+ begin
+ FileCreated:=true;
+ if(__textname<>'')or(impname='')then
+ begin
+ rewrite(t);
+ writeln(t,'EXPORTS');
+ end;
+ end;
+{$ENDIF}
+ isData:=GetSectionName(procentry,Fl)='';
+ if not isData then
+ isData:=Fl and IMAGE_SCN_CNT_CODE<>IMAGE_SCN_CNT_CODE;
+{$IFDEF STANDALONE}
+ if(__textname<>'')or(impname='')then
+ writeln(t,cstring,' @',succ(ordinal):0,' ',kind[isData]);
+ if impname<>''then
+{$ENDIF}
+ makeasm(j,cstring,isData);
+ end;
+ call_ar;
+ end;
+ end;
+
+begin
+ GetEdata:=false;
+{$IFDEF STANDALONE}
+ FileCreated:=false;
+{$ENDIF}
+ seek(f,PE+120);
+ blockread(f,ExportRVA,4);
+ seek(f,PE+6);
+ blockread(f,APE_Obj,2);
+ seek(f,PE+20);
+ blockread(f,APE_OptSize,2);
+ ObjOfs:=APE_OptSize+PEoffset+24;
+ for i:=1 to APE_obj do
+ begin
+ seek(f,ObjOfs);
+ blockread(f,Obj,sizeof(Obj));
+ inc(ObjOfs,sizeof(Obj));
+ with Obj do
+ if(VirtAddr<=ExportRva)and(ExportRva<VirtAddr+VirtSize)then
+ begin
+ delta:=ExportRva-VirtAddr;
+ ProcessEdata;
+ GetEdata:=true;
+ end;
+ end;
+end;
+
+
+function makedef(const binname,
+{$IFDEF STANDALONE}
+ textname,
+{$ENDIF}
+ libname:string):longbool;
+var
+ OldFileMode:longint;
+begin
+ assign(f,binname);
+{$IFDEF STANDALONE}
+ FileCreated:=false;
+ assign(t,textname);
+ __textname:=textname;
+{$ENDIF}
+ impname:=libname;
+ lname:=binname;
+ OldFileMode:=filemode;
+ {$push} {$I-}
+ filemode:=0;
+ reset(f,1);
+ filemode:=OldFileMode;
+ {$pop}
+ if IOResult<>0 then
+ begin
+ makedef:=false;
+ exit;
+ end;
+ if not DOSstubOK(PEoffset)then
+ makedef:=false
+ else if not IsPE(PEoffset)then
+ makedef:=false
+ else
+ makedef:=GetEdata(PEoffset);
+ close(f);
+{$IFDEF STANDALONE}
+ if FileCreated then
+ if(textname<>'')or(impname='')then
+ close(t);
+{$ENDIF}
+end;
+
+end.
diff --git a/closures/compiler/import.pas b/closures/compiler/import.pas
new file mode 100644
index 0000000000..c8bc844c50
--- /dev/null
+++ b/closures/compiler/import.pas
@@ -0,0 +1,130 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ This unit implements an uniform import object
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************}
+unit import;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ cutils,cclasses,
+ systems,
+ aasmbase,
+ symdef,symsym;
+
+type
+ timportlib=class
+ private
+ notsupmsg : boolean;
+ procedure NotSupported;
+ public
+ constructor Create;virtual;
+ destructor Destroy;override;
+ procedure generatelib;virtual;
+ end;
+
+ TDLLScanner=class
+ function Scan(const binname:string):boolean;virtual;abstract;
+ end;
+
+ TImportLibClass=class of TImportLib;
+ TDLLScannerClass=class of TDLLScanner;
+
+var
+ CImportLib : array[tsystem] of TImportLibClass;
+ CDLLScanner : array[tsystem] of TDLLScannerClass;
+ ImportLib : TImportLib;
+
+procedure RegisterImport(t:tsystem;c:TImportLibClass);
+procedure RegisterDLLScanner(t:tsystem;c:TDLLScannerClass);
+procedure InitImport;
+procedure DoneImport;
+
+
+implementation
+
+uses
+ verbose,globals;
+
+{****************************************************************************
+ TImportLib
+****************************************************************************}
+
+constructor timportlib.Create;
+begin
+ notsupmsg:=false;
+end;
+
+
+destructor timportlib.Destroy;
+begin
+end;
+
+
+procedure timportlib.NotSupported;
+begin
+ { show the message only once }
+ if not notsupmsg then
+ begin
+ Message(exec_e_dll_not_supported);
+ notsupmsg:=true;
+ end;
+end;
+
+
+procedure timportlib.generatelib;
+begin
+ NotSupported;
+end;
+
+
+{*****************************************************************************
+ Init/Done
+*****************************************************************************}
+
+procedure RegisterImport(t:tsystem;c:TImportLibClass);
+begin
+ CImportLib[t]:=c;
+end;
+
+
+procedure RegisterDLLScanner(t:tsystem;c:TDLLScannerClass);
+begin
+ CDLLScanner[t]:=c;
+end;
+
+
+procedure InitImport;
+begin
+ if assigned(CImportLib[target_info.system]) then
+ importlib:=CImportLib[target_info.system].Create
+ else
+ importlib:=TImportLib.Create;
+end;
+
+
+procedure DoneImport;
+begin
+ if assigned(importlib) then
+ importlib.free;
+end;
+
+end.
diff --git a/closures/compiler/link.pas b/closures/compiler/link.pas
new file mode 100644
index 0000000000..0f130c7723
--- /dev/null
+++ b/closures/compiler/link.pas
@@ -0,0 +1,1398 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ This unit handles the linker and binder calls for programs and
+ libraries
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit link;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ sysutils,
+ cclasses,
+ systems,
+ fmodule,
+ globtype,
+ ogbase;
+
+ Type
+ TLinkerInfo=record
+ ExeCmd,
+ DllCmd,
+ ExtDbgCmd : array[1..3] of string;
+ ResName : string[100];
+ ScriptName : string[100];
+ ExtraOptions : TCmdStr;
+ DynamicLinker : string[100];
+ end;
+
+ TLinker = class(TAbstractLinker)
+ public
+ HasResources,
+ HasExports : boolean;
+ SysInitUnit : string[20];
+ ObjectFiles,
+ SharedLibFiles,
+ StaticLibFiles,
+ FrameworkFiles : TCmdStrList;
+ Constructor Create;virtual;
+ Destructor Destroy;override;
+ procedure AddModuleFiles(hp:tmodule);
+ Procedure AddObject(const S,unitpath : TCmdStr;isunit:boolean);
+ Procedure AddStaticLibrary(const S : TCmdStr);
+ Procedure AddSharedLibrary(S : TCmdStr);
+ Procedure AddStaticCLibrary(const S : TCmdStr);
+ Procedure AddSharedCLibrary(S : TCmdStr);
+ Procedure AddFramework(S : TCmdStr);
+ procedure AddImportSymbol(const libname,symname,symmangledname:TCmdStr;OrdNr: longint;isvar:boolean);virtual;
+ Procedure InitSysInitUnitName;virtual;
+ Function MakeExecutable:boolean;virtual;
+ Function MakeSharedLibrary:boolean;virtual;
+ Function MakeStaticLibrary:boolean;virtual;
+ procedure ExpandAndApplyOrder(var Src:TCmdStrList);
+ procedure LoadPredefinedLibraryOrder;virtual;
+ function ReOrderEntries : boolean;
+ end;
+
+ TExternalLinker = class(TLinker)
+ public
+ Info : TLinkerInfo;
+ Constructor Create;override;
+ Destructor Destroy;override;
+ Function FindUtil(const s:TCmdStr):TCmdStr;
+ Function CatFileContent(para:TCmdStr):TCmdStr;
+ Function DoExec(const command:TCmdStr; para:TCmdStr;showinfo,useshell:boolean):boolean;
+ procedure SetDefaultInfo;virtual;
+ Function MakeStaticLibrary:boolean;override;
+ end;
+
+ TBooleanArray = array [1..1024] of boolean;
+ PBooleanArray = ^TBooleanArray;
+
+ TInternalLinker = class(TLinker)
+ private
+ FCExeOutput : TExeOutputClass;
+ FCObjInput : TObjInputClass;
+ { Libraries }
+ FStaticLibraryList : TFPHashObjectList;
+ FImportLibraryList : TFPHashObjectList;
+ procedure Load_ReadObject(const para:TCmdStr);
+ procedure Load_ReadStaticLibrary(const para:TCmdStr);
+ procedure ParseScript_Handle;
+ procedure ParseScript_PostCheck;
+ procedure ParseScript_Load;
+ function ParsePara(const para : string) : string;
+ procedure ParseScript_Order;
+ procedure ParseScript_MemPos;
+ procedure ParseScript_DataPos;
+ procedure PrintLinkerScript;
+ function RunLinkScript(const outputname:TCmdStr):boolean;
+ protected
+ linkscript : TCmdStrList;
+ ScriptCount : longint;
+ IsHandled : PBooleanArray;
+ property CObjInput:TObjInputClass read FCObjInput write FCObjInput;
+ property CExeOutput:TExeOutputClass read FCExeOutput write FCExeOutput;
+ property StaticLibraryList:TFPHashObjectList read FStaticLibraryList;
+ property ImportLibraryList:TFPHashObjectList read FImportLibraryList;
+ procedure DefaultLinkScript;virtual;abstract;
+ public
+ IsSharedLibrary : boolean;
+ UseStabs : boolean;
+ Constructor Create;override;
+ Destructor Destroy;override;
+ Function MakeExecutable:boolean;override;
+ Function MakeSharedLibrary:boolean;override;
+ procedure AddImportSymbol(const libname,symname,symmangledname:TCmdStr;OrdNr: longint;isvar:boolean);override;
+ end;
+
+ var
+ Linker : TLinker;
+
+ function FindObjectFile(s : TCmdStr;const unitpath:TCmdStr;isunit:boolean) : TCmdStr;
+ function FindLibraryFile(s:TCmdStr;const prefix,ext:TCmdStr;var foundfile : TCmdStr) : boolean;
+ function FindDLL(const s:TCmdStr;var founddll:TCmdStr):boolean;
+
+ procedure InitLinker;
+ procedure DoneLinker;
+
+
+Implementation
+
+ uses
+ cutils,cfileutl,cstreams,
+ script,globals,verbose,comphook,ppu,fpccrc,
+ aasmbase,aasmtai,aasmdata,aasmcpu,
+ owbase,owar,ogmap;
+
+ type
+ TLinkerClass = class of Tlinker;
+
+{*****************************************************************************
+ Helpers
+*****************************************************************************}
+
+ function GetFileCRC(const fn:string):cardinal;
+ var
+ fs : TCStream;
+ bufcount,
+ bufsize : Integer;
+ buf : pbyte;
+ begin
+ result:=0;
+ bufsize:=64*1024;
+ fs:=CFileStreamClass.Create(fn,fmOpenRead or fmShareDenyNone);
+ if CStreamError<>0 then
+ begin
+ fs.Free;
+ Comment(V_Error,'Can''t open file: '+fn);
+ exit;
+ end;
+ getmem(buf,bufsize);
+ repeat
+ bufcount:=fs.Read(buf^,bufsize);
+ result:=UpdateCrc32(result,buf^,bufcount);
+ until bufcount<bufsize;
+ freemem(buf);
+ fs.Free;
+ end;
+
+
+ { searches an object file }
+ function FindObjectFile(s:TCmdStr;const unitpath:TCmdStr;isunit:boolean) : TCmdStr;
+ var
+ found : boolean;
+ foundfile : TCmdStr;
+ begin
+ findobjectfile:='';
+ if s='' then
+ exit;
+
+ {When linking on target, the units has not been assembled yet,
+ so there is no object files to look for at
+ the host. Look for the corresponding assembler file instead,
+ because it will be assembled to object file on the target.}
+ if isunit and (cs_link_on_target in current_settings.globalswitches) then
+ s:=ChangeFileExt(s,target_info.asmext);
+
+ { when it does not belong to the unit then check if
+ the specified file exists without searching any paths }
+ if not isunit then
+ begin
+ if FileExists(FixFileName(s),false) then
+ begin
+ foundfile:=ScriptFixFileName(s);
+ found:=true;
+ end;
+ end;
+ if pos('.',s)=0 then
+ s:=s+target_info.objext;
+ { find object file
+ 1. output unit path
+ 2. output exe path
+ 3. specified unit path (if specified)
+ 4. cwd
+ 5. unit search path
+ 6. local object path
+ 7. global object path
+ 8. exepath (not when linking on target)
+ for all finds don't use the directory caching }
+ found:=false;
+ if isunit and (OutputUnitDir<>'') then
+ found:=FindFile(s,OutPutUnitDir,false,foundfile)
+ else
+ if OutputExeDir<>'' then
+ found:=FindFile(s,OutPutExeDir,false,foundfile);
+ if (not found) and (unitpath<>'') then
+ found:=FindFile(s,unitpath,false,foundfile);
+ if (not found) then
+ found:=FindFile(s, CurDirRelPath(source_info),false,foundfile);
+ if (not found) then
+ found:=UnitSearchPath.FindFile(s,false,foundfile);
+ if (not found) then
+ found:=current_module.localobjectsearchpath.FindFile(s,false,foundfile);
+ if (not found) then
+ found:=objectsearchpath.FindFile(s,false,foundfile);
+ if not(cs_link_on_target in current_settings.globalswitches) and (not found) then
+ found:=FindFile(s,exepath,false,foundfile);
+ if not(cs_link_nolink in current_settings.globalswitches) and (not found) then
+ Message1(exec_w_objfile_not_found,s);
+
+ {Restore file extension}
+ if isunit and (cs_link_on_target in current_settings.globalswitches) then
+ foundfile:= ChangeFileExt(foundfile,target_info.objext);
+
+ findobjectfile:=ScriptFixFileName(foundfile);
+ end;
+
+
+ { searches a (windows) DLL file }
+ function FindDLL(const s:TCmdStr;var founddll:TCmdStr):boolean;
+ var
+ sysdir : TCmdStr;
+ Found : boolean;
+ begin
+ Found:=false;
+ { Look for DLL in:
+ 1. Current dir
+ 2. Library Path
+ 3. windir,windir/system,windir/system32 }
+ Found:=FindFile(s,'.'+source_info.DirSep,false,founddll);
+ if (not found) then
+ Found:=librarysearchpath.FindFile(s,false,founddll);
+
+ { when cross compiling, it is pretty useless to search windir etc. for dlls }
+ if (not found) and (source_info.system=target_info.system) then
+ begin
+ sysdir:=FixPath(GetEnvironmentVariable('windir'),false);
+ Found:=FindFile(s,sysdir+';'+sysdir+'system'+source_info.DirSep+';'+sysdir+'system32'+source_info.DirSep,false,founddll);
+ end;
+ if (not found) then
+ begin
+ message1(exec_w_libfile_not_found,s);
+ FoundDll:=s;
+ end;
+ FindDll:=Found;
+ end;
+
+
+ { searches an library file }
+ function FindLibraryFile(s:TCmdStr;const prefix,ext:TCmdStr;var foundfile : TCmdStr) : boolean;
+ var
+ found : boolean;
+ paths : TCmdStr;
+ begin
+ findlibraryfile:=false;
+ foundfile:=s;
+ if s='' then
+ exit;
+ { split path from filename }
+ paths:=ExtractFilePath(s);
+ s:=ExtractFileName(s);
+ { add prefix 'lib' }
+ if (prefix<>'') and (Copy(s,1,length(prefix))<>prefix) then
+ s:=prefix+s;
+ { add extension }
+ if (ext<>'') and (Copy(s,length(s)-length(ext)+1,length(ext))<>ext) then
+ s:=s+ext;
+ { readd the split path }
+ s:=paths+s;
+ if FileExists(s,false) then
+ begin
+ foundfile:=ScriptFixFileName(s);
+ FindLibraryFile:=true;
+ exit;
+ end;
+ { find libary
+ 1. cwd
+ 2. local libary dir
+ 3. global libary dir
+ 4. exe path of the compiler (not when linking on target)
+ for all searches don't use the directory cache }
+ found:=FindFile(s, CurDirRelPath(source_info), false,foundfile);
+ if (not found) and (current_module.outputpath^<>'') then
+ found:=FindFile(s,current_module.outputpath^,false,foundfile);
+ if (not found) then
+ found:=current_module.locallibrarysearchpath.FindFile(s,false,foundfile);
+ if (not found) then
+ found:=librarysearchpath.FindFile(s,false,foundfile);
+ if not(cs_link_on_target in current_settings.globalswitches) and (not found) then
+ found:=FindFile(s,exepath,false,foundfile);
+ foundfile:=ScriptFixFileName(foundfile);
+ findlibraryfile:=found;
+ end;
+
+
+{*****************************************************************************
+ TLINKER
+*****************************************************************************}
+
+ Constructor TLinker.Create;
+ begin
+ Inherited Create;
+ ObjectFiles:=TCmdStrList.Create_no_double;
+ SharedLibFiles:=TCmdStrList.Create_no_double;
+ StaticLibFiles:=TCmdStrList.Create_no_double;
+ FrameworkFiles:=TCmdStrList.Create_no_double;
+ end;
+
+
+ Destructor TLinker.Destroy;
+ begin
+ ObjectFiles.Free;
+ SharedLibFiles.Free;
+ StaticLibFiles.Free;
+ FrameworkFiles.Free;
+ end;
+
+
+ procedure TLinker.AddModuleFiles(hp:tmodule);
+ var
+ mask : longint;
+ i,j : longint;
+ ImportLibrary : TImportLibrary;
+ ImportSymbol : TImportSymbol;
+ begin
+ with hp do
+ begin
+ if (flags and uf_has_resourcefiles)<>0 then
+ HasResources:=true;
+ if (flags and uf_has_exports)<>0 then
+ HasExports:=true;
+ { link unit files }
+ if (flags and uf_no_link)=0 then
+ begin
+ { create mask which unit files need linking }
+ mask:=link_always;
+ { static linking ? }
+ if (cs_link_static in current_settings.globalswitches) then
+ begin
+ if (flags and uf_static_linked)=0 then
+ begin
+ { if smart not avail then try static linking }
+ if (flags and uf_smart_linked)<>0 then
+ begin
+ Message1(exec_t_unit_not_static_linkable_switch_to_smart,modulename^);
+ mask:=mask or link_smart;
+ end
+ else
+ Message1(exec_e_unit_not_smart_or_static_linkable,modulename^);
+ end
+ else
+ mask:=mask or link_static;
+ end;
+ { smart linking ? }
+
+ if (cs_link_smart in current_settings.globalswitches) then
+ begin
+ if (flags and uf_smart_linked)=0 then
+ begin
+ { if smart not avail then try static linking }
+ if (flags and uf_static_linked)<>0 then
+ begin
+ { if not create_smartlink_library, then smart linking happens using the
+ regular object files
+ }
+ if create_smartlink_library then
+ Message1(exec_t_unit_not_smart_linkable_switch_to_static,modulename^);
+ mask:=mask or link_static;
+ end
+ else
+ Message1(exec_e_unit_not_smart_or_static_linkable,modulename^);
+ end
+ else
+ mask:=mask or link_smart;
+ end;
+ { shared linking }
+ if (cs_link_shared in current_settings.globalswitches) then
+ begin
+ if (flags and uf_shared_linked)=0 then
+ begin
+ { if shared not avail then try static linking }
+ if (flags and uf_static_linked)<>0 then
+ begin
+ Message1(exec_t_unit_not_shared_linkable_switch_to_static,modulename^);
+ mask:=mask or link_static;
+ end
+ else
+ Message1(exec_e_unit_not_shared_or_static_linkable,modulename^);
+ end
+ else
+ mask:=mask or link_shared;
+ end;
+ { unit files }
+ while not linkunitofiles.empty do
+ AddObject(linkunitofiles.getusemask(mask),path^,true);
+ while not linkunitstaticlibs.empty do
+ AddStaticLibrary(linkunitstaticlibs.getusemask(mask));
+ while not linkunitsharedlibs.empty do
+ AddSharedLibrary(linkunitsharedlibs.getusemask(mask));
+ end;
+ { Other needed .o and libs, specified using $L,$LINKLIB,external }
+ mask:=link_always;
+ while not linkotherofiles.empty do
+ AddObject(linkotherofiles.Getusemask(mask),path^,false);
+ while not linkotherstaticlibs.empty do
+ AddStaticCLibrary(linkotherstaticlibs.Getusemask(mask));
+ while not linkothersharedlibs.empty do
+ AddSharedCLibrary(linkothersharedlibs.Getusemask(mask));
+ while not linkotherframeworks.empty do
+ AddFramework(linkotherframeworks.Getusemask(mask));
+ { Known Library/DLL Imports }
+ for i:=0 to ImportLibraryList.Count-1 do
+ begin
+ ImportLibrary:=TImportLibrary(ImportLibraryList[i]);
+ for j:=0 to ImportLibrary.ImportSymbolList.Count-1 do
+ begin
+ ImportSymbol:=TImportSymbol(ImportLibrary.ImportSymbolList[j]);
+ AddImportSymbol(ImportLibrary.Name,ImportSymbol.Name,
+ ImportSymbol.MangledName,ImportSymbol.OrdNr,ImportSymbol.IsVar);
+ end;
+ end;
+ end;
+ end;
+
+
+ procedure TLinker.AddImportSymbol(const libname,symname,symmangledname:TCmdStr;OrdNr: longint;isvar:boolean);
+ begin
+ end;
+
+
+ Procedure TLinker.AddObject(const S,unitpath : TCmdStr;isunit:boolean);
+ begin
+ ObjectFiles.Concat(FindObjectFile(s,unitpath,isunit));
+ end;
+
+
+ Procedure TLinker.AddSharedLibrary(S:TCmdStr);
+ begin
+ if s='' then
+ exit;
+ { remove prefix 'lib' }
+ if Copy(s,1,length(target_info.sharedlibprefix))=target_info.sharedlibprefix then
+ Delete(s,1,length(target_info.sharedlibprefix));
+ { remove extension if any }
+ if Copy(s,length(s)-length(target_info.sharedlibext)+1,length(target_info.sharedlibext))=target_info.sharedlibext then
+ Delete(s,length(s)-length(target_info.sharedlibext)+1,length(target_info.sharedlibext)+1);
+ { ready to be added }
+ SharedLibFiles.Concat(S);
+ end;
+
+
+ Procedure TLinker.AddStaticLibrary(const S:TCmdStr);
+ var
+ ns : TCmdStr;
+ found : boolean;
+ begin
+ if s='' then
+ exit;
+ found:=FindLibraryFile(s,target_info.staticlibprefix,target_info.staticlibext,ns);
+ if not(cs_link_nolink in current_settings.globalswitches) and (not found) then
+ Message1(exec_w_libfile_not_found,s);
+ StaticLibFiles.Concat(ns);
+ end;
+
+
+ Procedure TLinker.AddSharedCLibrary(S:TCmdStr);
+ begin
+ if s='' then
+ exit;
+ { remove prefix 'lib' }
+ if Copy(s,1,length(target_info.sharedclibprefix))=target_info.sharedclibprefix then
+ Delete(s,1,length(target_info.sharedclibprefix));
+ { remove extension if any }
+ if Copy(s,length(s)-length(target_info.sharedclibext)+1,length(target_info.sharedclibext))=target_info.sharedclibext then
+ Delete(s,length(s)-length(target_info.sharedclibext)+1,length(target_info.sharedclibext)+1);
+ { ready to be added }
+ SharedLibFiles.Concat(S);
+ end;
+
+
+ Procedure TLinker.AddFramework(S:TCmdStr);
+ begin
+ if s='' then
+ exit;
+ { ready to be added }
+ FrameworkFiles.Concat(S);
+ end;
+
+
+ Procedure TLinker.AddStaticCLibrary(const S:TCmdStr);
+ var
+ ns : TCmdStr;
+ found : boolean;
+ begin
+ if s='' then
+ exit;
+ found:=FindLibraryFile(s,target_info.staticclibprefix,target_info.staticclibext,ns);
+ if not(cs_link_nolink in current_settings.globalswitches) and (not found) then
+ Message1(exec_w_libfile_not_found,s);
+ StaticLibFiles.Concat(ns);
+ end;
+
+
+ procedure AddImportSymbol(const libname,symname,symmangledname:TCmdStr;OrdNr: longint;isvar:boolean);
+ begin
+ end;
+
+
+ procedure TLinker.InitSysInitUnitName;
+ begin
+ end;
+
+ function TLinker.MakeExecutable:boolean;
+ begin
+ MakeExecutable:=false;
+ Message(exec_e_exe_not_supported);
+ end;
+
+
+ Function TLinker.MakeSharedLibrary:boolean;
+ begin
+ MakeSharedLibrary:=false;
+ Message(exec_e_dll_not_supported);
+ end;
+
+
+ Function TLinker.MakeStaticLibrary:boolean;
+ begin
+ MakeStaticLibrary:=false;
+ Message(exec_e_dll_not_supported);
+ end;
+
+
+ Procedure TLinker.ExpandAndApplyOrder(var Src:TCmdStrList);
+ var
+ p : TLinkStrMap;
+ i : longint;
+ begin
+ // call Virtual TLinker method to initialize
+ LoadPredefinedLibraryOrder;
+
+ // something to do?
+ if (LinkLibraryAliases.count=0) and (LinkLibraryOrder.Count=0) Then
+ exit;
+ p:=TLinkStrMap.Create;
+
+ // expand libaliases, clears src
+ LinkLibraryAliases.expand(src,p);
+
+ // writeln(src.count,' ',p.count,' ',linklibraryorder.count,' ',linklibraryaliases.count);
+ // apply order
+ p.UpdateWeights(LinkLibraryOrder);
+ p.SortOnWeight;
+
+ // put back in src
+ for i:=0 to p.count-1 do
+ src.insert(p[i].Key);
+ p.free;
+ end;
+
+
+ procedure TLinker.LoadPredefinedLibraryOrder;
+ begin
+ end;
+
+
+ function TLinker.ReOrderEntries : boolean;
+ begin
+ result:=(LinkLibraryOrder.count>0) or (LinkLibraryAliases.count>0);
+ end;
+
+
+{*****************************************************************************
+ TEXTERNALLINKER
+*****************************************************************************}
+
+ Constructor TExternalLinker.Create;
+ begin
+ inherited Create;
+ { set generic defaults }
+ FillChar(Info,sizeof(Info),0);
+ if cs_link_on_target in current_settings.globalswitches then
+ begin
+ Info.ResName:=outputexedir+ChangeFileExt(inputfilename,'_link.res');
+ Info.ScriptName:=outputexedir+ChangeFileExt(inputfilename,'_script.res');
+ end
+ else
+ begin
+ Info.ResName:='link.res';
+ Info.ScriptName:='script.res';
+ end;
+ { set the linker specific defaults }
+ SetDefaultInfo;
+ { Allow Parameter overrides for linker info }
+ with Info do
+ begin
+ if ParaLinkOptions<>'' then
+ ExtraOptions:=ParaLinkOptions;
+ if ParaDynamicLinker<>'' then
+ DynamicLinker:=ParaDynamicLinker;
+ end;
+ end;
+
+
+ Destructor TExternalLinker.Destroy;
+ begin
+ inherited destroy;
+ end;
+
+
+ Procedure TExternalLinker.SetDefaultInfo;
+ begin
+ end;
+
+
+ Function TExternalLinker.FindUtil(const s:TCmdStr):TCmdStr;
+ var
+ Found : boolean;
+ FoundBin : TCmdStr;
+ UtilExe : TCmdStr;
+ begin
+ if cs_link_on_target in current_settings.globalswitches then
+ begin
+ { If linking on target, don't add any path PM }
+ FindUtil:=ChangeFileExt(s,target_info.exeext);
+ exit;
+ end;
+ UtilExe:=ChangeFileExt(s,source_info.exeext);
+ FoundBin:='';
+ Found:=false;
+ if utilsdirectory<>'' then
+ Found:=FindFile(utilexe,utilsdirectory,false,Foundbin);
+ if (not Found) then
+ Found:=FindExe(utilexe,false,Foundbin);
+ if (not Found) and not(cs_link_nolink in current_settings.globalswitches) then
+ begin
+ Message1(exec_e_util_not_found,utilexe);
+ current_settings.globalswitches:=current_settings.globalswitches+[cs_link_nolink];
+ end;
+ if (FoundBin<>'') then
+ Message1(exec_t_using_util,FoundBin);
+ FindUtil:=FoundBin;
+ end;
+
+
+ Function TExternalLinker.CatFileContent(para : TCmdStr) : TCmdStr;
+ var
+ filecontent : TCmdStr;
+ f : text;
+ st : string;
+ begin
+ if not (tf_no_backquote_support in source_info.flags) then
+ begin
+ CatFileContent:='`cat '+MaybeQuoted(para)+'`';
+ Exit;
+ end;
+ assign(f,para);
+ filecontent:='';
+ {$push}{$I-}
+ reset(f);
+ {$pop}
+ if IOResult<>0 then
+ begin
+ Message1(exec_n_backquote_cat_file_not_found,para);
+ end
+ else
+ begin
+ while not eof(f) do
+ begin
+ readln(f,st);
+ if st<>'' then
+ filecontent:=filecontent+' '+st;
+ end;
+ close(f);
+ end;
+ CatFileContent:=filecontent;
+ end;
+
+ Function TExternalLinker.DoExec(const command:TCmdStr; para:TCmdStr;showinfo,useshell:boolean):boolean;
+ var
+ exitcode: longint;
+ begin
+ DoExec:=true;
+ if not(cs_link_nolink in current_settings.globalswitches) then
+ begin
+ FlushOutput;
+ if useshell then
+ exitcode:=shell(maybequoted(command)+' '+para)
+ else
+ try
+ exitcode:=ExecuteProcess(command,para);
+ except on E:EOSError do
+ begin
+ Message(exec_e_cant_call_linker);
+ current_settings.globalswitches:=current_settings.globalswitches+[cs_link_nolink];
+ DoExec:=false;
+ end;
+ end;
+ if (exitcode<>0) then
+ begin
+ Message(exec_e_error_while_linking);
+ current_settings.globalswitches:=current_settings.globalswitches+[cs_link_nolink];
+ DoExec:=false;
+ end;
+ end;
+ { Update asmres when externmode is set }
+ if cs_link_nolink in current_settings.globalswitches then
+ begin
+ if showinfo then
+ begin
+ if DLLsource then
+ AsmRes.AddLinkCommand(Command,Para,current_module.sharedlibfilename^)
+ else
+ AsmRes.AddLinkCommand(Command,Para,current_module.exefilename^);
+ end
+ else
+ AsmRes.AddLinkCommand(Command,Para,'');
+ end;
+ end;
+
+
+ Function TExternalLinker.MakeStaticLibrary:boolean;
+
+ function GetNextFiles(const maxCmdLength : Longint; var item : TCmdStrListItem) : TCmdStr;
+ begin
+ result := '';
+ while (assigned(item) and ((length(result) + length(item.str) + 1) < maxCmdLength)) do begin
+ result := result + ' ' + item.str;
+ item := TCmdStrListItem(item.next);
+ end;
+ end;
+
+ var
+ binstr, scriptfile : TCmdStr;
+ cmdstr, nextcmd, smartpath : TCmdStr;
+ current : TCmdStrListItem;
+ script: Text;
+ scripted_ar : boolean;
+ success : boolean;
+ begin
+ MakeStaticLibrary:=false;
+ { remove the library, to be sure that it is rewritten }
+ DeleteFile(current_module.staticlibfilename^);
+ { Call AR }
+ smartpath:=FixPath(ChangeFileExt(current_module.asmfilename^,target_info.smartext),false);
+ SplitBinCmd(target_ar.arcmd,binstr,cmdstr);
+ binstr := FindUtil(utilsprefix + binstr);
+
+
+ scripted_ar:=target_ar.id=ar_gnu_ar_scripted;
+
+ if scripted_ar then
+ begin
+ scriptfile := FixFileName(smartpath+'arscript.txt');
+ Replace(cmdstr,'$SCRIPT',maybequoted(scriptfile));
+ Assign(script, scriptfile);
+ Rewrite(script);
+ try
+ writeln(script, 'CREATE ' + current_module.staticlibfilename^);
+ current := TCmdStrListItem(SmartLinkOFiles.First);
+ while current <> nil do
+ begin
+ writeln(script, 'ADDMOD ' + current.str);
+ current := TCmdStrListItem(current.next);
+ end;
+ writeln(script, 'SAVE');
+ writeln(script, 'END');
+ finally
+ Close(script);
+ end;
+ success:=DoExec(binstr,cmdstr,false,true);
+ end
+ else
+ begin
+ Replace(cmdstr,'$LIB',maybequoted(current_module.staticlibfilename^));
+ { create AR commands }
+ success := true;
+ current := TCmdStrListItem(SmartLinkOFiles.First);
+ repeat
+ nextcmd := cmdstr;
+ Replace(nextcmd,'$FILES',GetNextFiles(2047, current));
+ success:=DoExec(binstr,nextcmd,false,true);
+ until (not assigned(current)) or (not success);
+ end;
+
+ if (target_ar.arfinishcmd <> '') then
+ begin
+ SplitBinCmd(target_ar.arfinishcmd,binstr,cmdstr);
+ binstr := FindUtil(utilsprefix + binstr);
+ Replace(cmdstr,'$LIB',maybequoted(current_module.staticlibfilename^));
+ success:=DoExec(binstr,cmdstr,false,true);
+ end;
+
+ { Clean up }
+ if not(cs_asm_leave in current_settings.globalswitches) then
+ if not(cs_link_nolink in current_settings.globalswitches) then
+ begin
+ while not SmartLinkOFiles.Empty do
+ DeleteFile(SmartLinkOFiles.GetFirst);
+ if scripted_ar then
+ DeleteFile(scriptfile);
+ RemoveDir(smartpath);
+ end
+ else
+ begin
+ AsmRes.AddDeleteCommand(FixFileName(smartpath+current_module.asmprefix^+'*'+target_info.objext));
+ if scripted_ar then
+ AsmRes.AddDeleteCommand(scriptfile);
+ AsmRes.AddDeleteDirCommand(smartpath);
+ end;
+ MakeStaticLibrary:=success;
+ end;
+
+
+{*****************************************************************************
+ TINTERNALLINKER
+*****************************************************************************}
+
+ Constructor TInternalLinker.Create;
+ begin
+ inherited Create;
+ linkscript:=TCmdStrList.Create;
+ FStaticLibraryList:=TFPHashObjectList.Create(true);
+ FImportLibraryList:=TFPHashObjectList.Create(true);
+ exemap:=nil;
+ exeoutput:=nil;
+ UseStabs:=false;
+ CObjInput:=TObjInput;
+ ScriptCount:=0;
+ IsHandled:=nil;
+ end;
+
+
+ Destructor TInternalLinker.Destroy;
+ begin
+ linkscript.free;
+ StaticLibraryList.Free;
+ ImportLibraryList.Free;
+ if assigned(IsHandled) then
+ begin
+ FreeMem(IsHandled,sizeof(boolean)*ScriptCount);
+ IsHandled:=nil;
+ ScriptCount:=0;
+ end;
+ if assigned(exeoutput) then
+ begin
+ exeoutput.free;
+ exeoutput:=nil;
+ end;
+ if assigned(exemap) then
+ begin
+ exemap.free;
+ exemap:=nil;
+ end;
+ inherited destroy;
+ end;
+
+
+ procedure TInternalLinker.AddImportSymbol(const libname,symname,symmangledname:TCmdStr;OrdNr: longint;isvar:boolean);
+ var
+ ImportLibrary : TImportLibrary;
+ ImportSymbol : TFPHashObject;
+ begin
+ ImportLibrary:=TImportLibrary(ImportLibraryList.Find(libname));
+ if not assigned(ImportLibrary) then
+ ImportLibrary:=TImportLibrary.Create(ImportLibraryList,libname);
+ ImportSymbol:=TFPHashObject(ImportLibrary.ImportSymbolList.Find(symname));
+ if not assigned(ImportSymbol) then
+ ImportSymbol:=TImportSymbol.Create(ImportLibrary.ImportSymbolList,symname,symmangledname,OrdNr,isvar);
+ end;
+
+
+ procedure TInternalLinker.Load_ReadObject(const para:TCmdStr);
+ var
+ objdata : TObjData;
+ objinput : TObjinput;
+ objreader : TObjectReader;
+ fn : TCmdStr;
+ begin
+ fn:=FindObjectFile(para,'',false);
+ Comment(V_Tried,'Reading object '+fn);
+ objinput:=CObjInput.Create;
+ objdata:=objinput.newObjData(para);
+ objreader:=TObjectreader.create;
+ if objreader.openfile(fn) then
+ begin
+ if objinput.ReadObjData(objreader,objdata) then
+ exeoutput.addobjdata(objdata);
+ end;
+ { release input object }
+ objinput.free;
+ objreader.free;
+ end;
+
+
+ procedure TInternalLinker.Load_ReadStaticLibrary(const para:TCmdStr);
+ var
+ objreader : TObjectReader;
+ begin
+{ TODO: Cleanup ignoring of FPC generated libimp*.a files}
+ { Don't load import libraries }
+ if copy(ExtractFileName(para),1,6)='libimp' then
+ exit;
+ Comment(V_Tried,'Opening library '+para);
+ objreader:=TArObjectreader.create(para);
+ TStaticLibrary.Create(StaticLibraryList,para,objreader,CObjInput);
+ end;
+
+
+ procedure TInternalLinker.ParseScript_Handle;
+ var
+ s, para, keyword : String;
+ hp : TCmdStrListItem;
+ i : longint;
+ begin
+ hp:=TCmdStrListItem(linkscript.first);
+ i:=0;
+ while assigned(hp) do
+ begin
+ inc(i);
+ s:=hp.str;
+ if (s='') or (s[1]='#') then
+ continue;
+ keyword:=Upper(GetToken(s,' '));
+ para:=GetToken(s,' ');
+ if Trim(s)<>'' then
+ Comment(V_Warning,'Unknown part "'+s+'" in "'+hp.str+'" internal linker script');
+ if (keyword<>'SYMBOL') and
+ (keyword<>'SYMBOLS') and
+ (keyword<>'STABS') and
+ (keyword<>'PROVIDE') and
+ (keyword<>'ZEROS') and
+ (keyword<>'BYTE') and
+ (keyword<>'WORD') and
+ (keyword<>'LONG') and
+ (keyword<>'QUAD') and
+ (keyword<>'ENTRYNAME') and
+ (keyword<>'ISSHAREDLIBRARY') and
+ (keyword<>'IMAGEBASE') and
+ (keyword<>'READOBJECT') and
+ (keyword<>'READSTATICLIBRARY') and
+ (keyword<>'EXESECTION') and
+ (keyword<>'ENDEXESECTION') and
+ (keyword<>'OBJSECTION') and
+ (keyword<>'HEADER')
+ then
+ Comment(V_Warning,'Unknown keyword "'+keyword+'" in "'+hp.str
+ +'" internal linker script');
+ hp:=TCmdStrListItem(hp.next);
+ end;
+ ScriptCount:=i;
+ if ScriptCount>0 then
+ begin
+ GetMem(IsHandled,sizeof(boolean)*ScriptCount);
+ Fillchar(IsHandled^,sizeof(boolean)*ScriptCount,#0);
+ end;
+ end;
+
+ procedure TInternalLinker.ParseScript_PostCheck;
+ var
+ hp : TCmdStrListItem;
+ i : longint;
+ begin
+ hp:=TCmdStrListItem(linkscript.first);
+ i:=0;
+ while assigned(hp) do
+ begin
+ inc(i);
+ if not IsHandled^[i] then
+ begin
+ Comment(V_Warning,'"'+hp.str+
+ '" internal linker script not handled');
+ end;
+ hp:=TCmdStrListItem(hp.next);
+ end;
+ end;
+
+ function TInternalLinker.ParsePara(const para : string) : string;
+ var
+ res : string;
+ begin
+ res:=trim(para);
+ { Remove enclosing braces }
+ if (length(res)>0) and (res[1]='(') and
+ (res[length(res)]=')') then
+ res:=trim(copy(res,2,length(res)-2));
+ result:=res;
+ end;
+
+ procedure TInternalLinker.ParseScript_Load;
+ var
+ s,
+ para,
+ keyword : String;
+ hp : TCmdStrListItem;
+ i : longint;
+ handled : boolean;
+ begin
+ exeoutput.Load_Start;
+ hp:=TCmdStrListItem(linkscript.first);
+ i:=0;
+ while assigned(hp) do
+ begin
+ inc(i);
+ s:=hp.str;
+ if (s='') or (s[1]='#') then
+ begin
+ IsHandled^[i]:=true;
+ continue;
+ end;
+ handled:=true;
+ keyword:=Upper(GetToken(s,' '));
+ para:=ParsePara(GetToken(s,' '));
+ if keyword='SYMBOL' then
+ ExeOutput.Load_Symbol(para)
+ else if keyword='PROVIDE' then
+ ExeOutput.Load_ProvideSymbol(para)
+ else if keyword='ENTRYNAME' then
+ ExeOutput.Load_EntryName(para)
+ else if keyword='ISSHAREDLIBRARY' then
+ ExeOutput.Load_IsSharedLibrary
+ else if keyword='IMAGEBASE' then
+ ExeOutput.Load_ImageBase(para)
+ else if keyword='READOBJECT' then
+ Load_ReadObject(para)
+ else if keyword='STABS' then
+ UseStabs:=true
+ else if keyword='READSTATICLIBRARY' then
+ Load_ReadStaticLibrary(para)
+ else
+ handled:=false;
+ if handled then
+ IsHandled^[i]:=true;
+ hp:=TCmdStrListItem(hp.next);
+ end;
+ end;
+
+
+ procedure TInternalLinker.ParseScript_Order;
+ var
+ s,
+ para,
+ keyword : String;
+ hp : TCmdStrListItem;
+ i : longint;
+ handled : boolean;
+ begin
+ exeoutput.Order_Start;
+ hp:=TCmdStrListItem(linkscript.first);
+ i:=0;
+ while assigned(hp) do
+ begin
+ inc(i);
+ s:=hp.str;
+ if (s='') or (s[1]='#') then
+ continue;
+ handled:=true;
+ keyword:=Upper(GetToken(s,' '));
+ para:=ParsePara(GetToken(s,' '));
+
+ if keyword='EXESECTION' then
+ ExeOutput.Order_ExeSection(para)
+ else if keyword='ENDEXESECTION' then
+ ExeOutput.Order_EndExeSection
+ else if keyword='OBJSECTION' then
+ ExeOutput.Order_ObjSection(para)
+ else if keyword='ZEROS' then
+ ExeOutput.Order_Zeros(para)
+ else if keyword='BYTE' then
+ ExeOutput.Order_Values(1,para)
+ else if keyword='WORD' then
+ ExeOutput.Order_Values(2,para)
+ else if keyword='LONG' then
+ ExeOutput.Order_Values(4,para)
+ else if keyword='QUAD' then
+ ExeOutput.Order_Values(8,para)
+ else if keyword='SYMBOL' then
+ ExeOutput.Order_Symbol(para)
+ else if keyword='PROVIDE' then
+ ExeOutput.Order_ProvideSymbol(para)
+ else
+ handled:=false;
+ if handled then
+ IsHandled^[i]:=true;
+ hp:=TCmdStrListItem(hp.next);
+ end;
+ exeoutput.Order_End;
+ end;
+
+
+ procedure TInternalLinker.ParseScript_MemPos;
+ var
+ s,
+ para,
+ keyword : String;
+ hp : TCmdStrListItem;
+ i : longint;
+ handled : boolean;
+ begin
+ exeoutput.MemPos_Start;
+ hp:=TCmdStrListItem(linkscript.first);
+ i:=0;
+ while assigned(hp) do
+ begin
+ inc(i);
+ s:=hp.str;
+ if (s='') or (s[1]='#') then
+ continue;
+ handled:=true;
+ keyword:=Upper(GetToken(s,' '));
+ para:=ParsePara(GetToken(s,' '));
+ if keyword='EXESECTION' then
+ ExeOutput.MemPos_ExeSection(para)
+ else if keyword='ENDEXESECTION' then
+ ExeOutput.MemPos_EndExeSection
+ else if keyword='HEADER' then
+ ExeOutput.MemPos_Header
+ else
+ handled:=false;
+ if handled then
+ IsHandled^[i]:=true;
+ hp:=TCmdStrListItem(hp.next);
+ end;
+ end;
+
+
+ procedure TInternalLinker.ParseScript_DataPos;
+ var
+ s,
+ para,
+ keyword : String;
+ hp : TCmdStrListItem;
+ i : longint;
+ handled : boolean;
+ begin
+ exeoutput.DataPos_Start;
+ hp:=TCmdStrListItem(linkscript.first);
+ i:=0;
+ while assigned(hp) do
+ begin
+ inc(i);
+ s:=hp.str;
+ if (s='') or (s[1]='#') then
+ continue;
+ handled:=true;
+ keyword:=Upper(GetToken(s,' '));
+ para:=ParsePara(GetToken(s,' '));
+ if keyword='EXESECTION' then
+ ExeOutput.DataPos_ExeSection(para)
+ else if keyword='ENDEXESECTION' then
+ ExeOutput.DataPos_EndExeSection
+ else if keyword='HEADER' then
+ ExeOutput.DataPos_Header
+ else if keyword='SYMBOLS' then
+ ExeOutput.DataPos_Symbols
+ else
+ handled:=false;
+ if handled then
+ IsHandled^[i]:=true;
+ hp:=TCmdStrListItem(hp.next);
+ end;
+ end;
+
+
+ procedure TInternalLinker.PrintLinkerScript;
+ var
+ hp : TCmdStrListItem;
+ begin
+ if not assigned(exemap) then
+ exit;
+ exemap.Add('Used linker script');
+ exemap.Add('');
+ hp:=TCmdStrListItem(linkscript.first);
+ while assigned(hp) do
+ begin
+ exemap.Add(hp.str);
+ hp:=TCmdStrListItem(hp.next);
+ end;
+ end;
+
+
+ function TInternalLinker.RunLinkScript(const outputname:TCmdStr):boolean;
+ label
+ myexit;
+ var
+ bsssize : aword;
+ bsssec : TExeSection;
+ dbgname : TCmdStr;
+ begin
+ result:=false;
+
+ Message1(exec_i_linking,outputname);
+ FlushOutput;
+
+{ TODO: Load custom linker script}
+ DefaultLinkScript;
+
+ exeoutput:=CExeOutput.Create;
+
+ if (cs_link_map in current_settings.globalswitches) then
+ exemap:=texemap.create(current_module.mapfilename^);
+
+ PrintLinkerScript;
+
+ { Check that syntax is OK }
+ ParseScript_Handle;
+ { Load .o files and resolve symbols }
+ ParseScript_Load;
+ exeoutput.ResolveSymbols(StaticLibraryList);
+ { Generate symbols and code to do the importing }
+ exeoutput.GenerateLibraryImports(ImportLibraryList);
+ { Fill external symbols data }
+ exeoutput.FixupSymbols;
+ if ErrorCount>0 then
+ goto myexit;
+
+ { parse linker options specific for output format }
+ exeoutput.ParseScript (linkscript);
+
+ { Create .exe sections and add .o sections }
+ ParseScript_Order;
+ exeoutput.RemoveUnreferencedSections;
+ { if UseStabs then, this would remove
+ STABS for empty linker scripts }
+ exeoutput.MergeStabs;
+ exeoutput.RemoveEmptySections;
+ if ErrorCount>0 then
+ goto myexit;
+
+ { Calc positions in mem }
+ ParseScript_MemPos;
+ exeoutput.FixupRelocations;
+ exeoutput.PrintMemoryMap;
+ if ErrorCount>0 then
+ goto myexit;
+
+ if cs_link_separate_dbg_file in current_settings.globalswitches then
+ begin
+ { create debuginfo, which is an executable without data on disk }
+ dbgname:=ChangeFileExt(outputname,'.dbg');
+ exeoutput.ExeWriteMode:=ewm_dbgonly;
+ ParseScript_DataPos;
+ exeoutput.WriteExeFile(dbgname);
+ { create executable with link to just created debuginfo file }
+ exeoutput.ExeWriteMode:=ewm_exeonly;
+ exeoutput.RemoveDebugInfo;
+ exeoutput.GenerateDebugLink(ExtractFileName(dbgname),GetFileCRC(dbgname));
+ ParseScript_MemPos;
+ ParseScript_DataPos;
+ exeoutput.WriteExeFile(outputname);
+ end
+ else
+ begin
+ exeoutput.ExeWriteMode:=ewm_exefull;
+ ParseScript_DataPos;
+ exeoutput.WriteExeFile(outputname);
+ end;
+
+ { Post check that everything was handled }
+ ParseScript_PostCheck;
+
+{ TODO: fixed section names}
+ status.codesize:=exeoutput.findexesection('.text').size;
+ status.datasize:=exeoutput.findexesection('.data').size;
+ bsssec:=exeoutput.findexesection('.bss');
+ if assigned(bsssec) then
+ bsssize:=bsssec.size
+ else
+ bsssize:=0;
+
+ { Executable info }
+ Message1(execinfo_x_codesize,tostr(status.codesize));
+ Message1(execinfo_x_initdatasize,tostr(status.datasize));
+ Message1(execinfo_x_uninitdatasize,tostr(bsssize));
+ Message1(execinfo_x_stackreserve,tostr(stacksize));
+
+ myexit:
+ { close map }
+ if assigned(exemap) then
+ begin
+ exemap.free;
+ exemap:=nil;
+ end;
+
+ { close exe }
+ exeoutput.free;
+ exeoutput:=nil;
+
+ result:=true;
+ end;
+
+
+ function TInternalLinker.MakeExecutable:boolean;
+ begin
+ IsSharedLibrary:=false;
+ result:=RunLinkScript(current_module.exefilename^);
+ end;
+
+
+ function TInternalLinker.MakeSharedLibrary:boolean;
+ begin
+ IsSharedLibrary:=true;
+ result:=RunLinkScript(current_module.sharedlibfilename^);
+ end;
+
+
+{*****************************************************************************
+ Init/Done
+*****************************************************************************}
+
+ procedure InitLinker;
+ var
+ lk : TlinkerClass;
+ begin
+ if (cs_link_extern in current_settings.globalswitches) and
+ assigned(target_info.linkextern) then
+ begin
+ lk:=TlinkerClass(target_info.linkextern);
+ linker:=lk.Create;
+ end
+ else
+ if assigned(target_info.link) then
+ begin
+ lk:=TLinkerClass(target_info.link);
+ linker:=lk.Create;
+ end
+ else
+ linker:=Tlinker.Create;
+ end;
+
+
+ procedure DoneLinker;
+ begin
+ if assigned(linker) then
+ Linker.Free;
+ end;
+
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+ const
+ ar_gnu_ar_info : tarinfo =
+ (
+ id : ar_gnu_ar;
+ arcmd : 'ar qS $LIB $FILES';
+ arfinishcmd : 'ar s $LIB'
+ );
+
+ ar_gnu_ar_scripted_info : tarinfo =
+ (
+ id : ar_gnu_ar_scripted;
+ arcmd : 'ar -M < $SCRIPT';
+ arfinishcmd : ''
+ );
+
+ ar_gnu_gar_info : tarinfo =
+ ( id : ar_gnu_gar;
+ arcmd : 'gar qS $LIB $FILES';
+ arfinishcmd : 'gar s $LIB'
+ );
+
+
+initialization
+ RegisterAr(ar_gnu_ar_info);
+ RegisterAr(ar_gnu_ar_scripted_info);
+ RegisterAr(ar_gnu_gar_info);
+end.
diff --git a/closures/compiler/m68k/aasmcpu.pas b/closures/compiler/m68k/aasmcpu.pas
new file mode 100644
index 0000000000..f2a5e837bc
--- /dev/null
+++ b/closures/compiler/m68k/aasmcpu.pas
@@ -0,0 +1,579 @@
+{
+ Copyright (c) 1998-2001 by Florian Klaempfl and Pierre Muller
+
+ m68k family assembler instructions
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit aasmcpu;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ cclasses,aasmtai,aasmdata,aasmsym,
+ aasmbase,globals,verbose,symtype,
+ cpubase,cpuinfo,cgbase,cgutils;
+
+
+const
+ { "mov reg,reg" source operand number }
+ O_MOV_SOURCE = 0;
+ { "mov reg,reg" source operand number }
+ O_MOV_DEST = 1;
+type
+
+ taicpu = class(tai_cpu_abstract_sym)
+ opsize : topsize;
+ constructor op_none(op : tasmop);
+ constructor op_none(op : tasmop;_size : topsize);
+
+ constructor op_reg(op : tasmop;_size : topsize;_op1 : tregister);
+ constructor op_const(op : tasmop;_size : topsize;_op1 : longint);
+ constructor op_ref(op : tasmop;_size : topsize;_op1 : treference);
+
+ constructor op_reg_reg(op : tasmop;_size : topsize;_op1,_op2 : tregister);
+ constructor op_reg_ref(op : tasmop;_size : topsize;_op1 : tregister;_op2 : treference);
+ constructor op_reg_const(op:tasmop; _size: topsize; _op1: tregister; _op2: longint);
+
+ constructor op_const_reg(op : tasmop;_size : topsize;_op1 : longint;_op2 : tregister);
+ constructor op_const_const(op : tasmop;_size : topsize;_op1,_op2 : longint);
+ constructor op_const_ref(op : tasmop;_size : topsize;_op1 : longint;_op2 : treference);
+
+ constructor op_ref_reg(op : tasmop;_size : topsize;_op1 : treference;_op2 : tregister);
+ { this is only allowed if _op1 is an int value (_op1^.isintvalue=true) }
+ constructor op_ref_ref(op : tasmop;_size : topsize;_op1,_op2 : treference);
+
+ constructor op_reg_reg_reg(op : tasmop;_size : topsize;_op1,_op2,_op3 : tregister);
+ constructor op_const_reg_reg(op : tasmop;_size : topsize;_op1 : longint;_op2 : tregister;_op3 : tregister);
+ constructor op_const_ref_reg(op : tasmop;_size : topsize;_op1 : longint;_op2 : treference;_op3 : tregister);
+ constructor op_reg_reg_ref(op : tasmop;_size : topsize;_op1,_op2 : tregister; _op3 : treference);
+ constructor op_const_reg_ref(op : tasmop;_size : topsize;_op1 : longint;_op2 : tregister;_op3 : treference);
+
+ constructor op_reg_regset(op: tasmop; _size : topsize; _op1: tregister;const _op2: tcpuregisterset);
+ constructor op_regset_reg(op: tasmop; _size : topsize;const _op1: tcpuregisterset; _op2: tregister);
+
+ constructor op_ref_regset(op: tasmop; _size : topsize; _op1: treference;const _op2: tcpuregisterset);
+ constructor op_regset_ref(op: tasmop; _size : topsize;const _op1: tcpuregisterset; _op2: treference);
+
+ { this is for Jmp instructions }
+ constructor op_cond_sym(op : tasmop;cond:TAsmCond;_size : topsize;_op1 : tasmsymbol);
+
+ constructor op_sym(op : tasmop;_size : topsize;_op1 : tasmsymbol);
+ { for DBxx opcodes }
+ constructor op_reg_sym(op: tasmop; _size : topsize; _op1: tregister; _op2 :tasmsymbol);
+ constructor op_sym_ofs_reg(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint;_op2 : tregister);
+
+ constructor op_sym_ofs(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint);
+ constructor op_sym_ofs_ref(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint;const _op2 : treference);
+
+ function is_same_reg_move(regtype: Tregistertype):boolean;override;
+ function spilling_get_operation_type(opnr: longint): topertype;override;
+
+ private
+ procedure loadregset(opidx:longint;const s:tcpuregisterset);
+ procedure init(_size : topsize); { this need to be called by all constructor }
+ end;
+
+
+ tai_align = class(tai_align_abstract)
+ { nothing to add }
+ end;
+
+ procedure InitAsm;
+ procedure DoneAsm;
+
+ function spilling_create_load(const ref:treference;r:tregister):Taicpu;
+ function spilling_create_store(r:tregister; const ref:treference):Taicpu;
+
+ implementation
+
+ uses
+ globtype;
+
+
+{ TODO: FIX ME!! useful for debug, remove it, same table as in ag68kgas }
+ const
+ gas_op2str:op2strtable=
+ { warning: CPU32 opcodes are not fully compatible with the MC68020. }
+ { 68000 only opcodes }
+ ( '',
+ 'abcd','add','adda','addi','addq','addx','and','andi',
+ 'asl','asr','bcc','bcs','beq','bge','bgt','bhi',
+ 'ble','bls','blt','bmi','bne','bpl','bvc','bvs',
+ 'bchg','bclr','bra','bset','bsr','btst','chk',
+ 'clr','cmp','cmpa','cmpi','cmpm','dbcc','dbcs','dbeq','dbge',
+ 'dbgt','dbhi','dble','dbls','dblt','dbmi','dbne','dbra',
+ 'dbpl','dbt','dbvc','dbvs','dbf','divs','divu',
+ 'eor','eori','exg','illegal','ext','jmp','jsr',
+ 'lea','link','lsl','lsr','move','movea','movei','moveq',
+ 'movem','movep','muls','mulu','nbcd','neg','negx',
+ 'nop','not','or','ori','pea','rol','ror','roxl',
+ 'roxr','rtr','rts','sbcd','scc','scs','seq','sge',
+ 'sgt','shi','sle','sls','slt','smi','sne',
+ 'spl','st','svc','svs','sf','sub','suba','subi','subq',
+ 'subx','swap','tas','trap','trapv','tst','unlk',
+ 'rte','reset','stop',
+ { mc68010 instructions }
+ 'bkpt','movec','moves','rtd',
+ { mc68020 instructions }
+ 'bfchg','bfclr','bfexts','bfextu','bfffo',
+ 'bfins','bfset','bftst','callm','cas','cas2',
+ 'chk2','cmp2','divsl','divul','extb','pack','rtm',
+ 'trapcc','tracs','trapeq','trapf','trapge','trapgt',
+ 'traphi','traple','trapls','traplt','trapmi','trapne',
+ 'trappl','trapt','trapvc','trapvs','unpk',
+ { fpu processor instructions - directly supported only. }
+ { ieee aware and misc. condition codes not supported }
+ 'fabs','fadd',
+ 'fbeq','fbne','fbngt','fbgt','fbge','fbnge',
+ 'fblt','fbnlt','fble','fbgl','fbngl','fbgle','fbngle',
+ 'fdbeq','fdbne','fdbgt','fdbngt','fdbge','fdbnge',
+ 'fdblt','fdbnlt','fdble','fdbgl','fdbngl','fdbgle','fdbngle',
+ 'fseq','fsne','fsgt','fsngt','fsge','fsnge',
+ 'fslt','fsnlt','fsle','fsgl','fsngl','fsgle','fsngle',
+ 'fcmp','fdiv','fmove','fmovem',
+ 'fmul','fneg','fnop','fsqrt','fsub','fsgldiv',
+ 'fsflmul','ftst',
+ 'ftrapeq','ftrapne','ftrapgt','ftrapngt','ftrapge','ftrapnge',
+ 'ftraplt','ftrapnlt','ftraple','ftrapgl','ftrapngl','ftrapgle','ftrapngle',
+ { protected instructions }
+ 'cprestore','cpsave',
+ { fpu unit protected instructions }
+ { and 68030/68851 common mmu instructions }
+ { (this may include 68040 mmu instructions) }
+ 'frestore','fsave','pflush','pflusha','pload','pmove','ptest',
+ { useful for assembly language output }
+ 'label','db','s','b','fb');
+
+
+{*****************************************************************************
+ Taicpu Constructors
+*****************************************************************************}
+
+
+
+ procedure taicpu.loadregset(opidx:longint;const s:tcpuregisterset);
+ var
+ i : byte;
+ begin
+ allocate_oper(opidx+1);
+ with oper[opidx]^ do
+ begin
+ if typ<>top_regset then
+ clearop(opidx);
+ new(regset);
+ regset^:=s;
+ typ:=top_regset;
+ for i:=RS_D0 to RS_D7 do
+ begin
+ if assigned(add_reg_instruction_hook) and (i in regset^) then
+ add_reg_instruction_hook(self,newreg(R_INTREGISTER,i,R_SUBWHOLE));
+ end;
+ for i:=RS_A0 to RS_SP do
+ begin
+ if assigned(add_reg_instruction_hook) and (i in regset^) then
+ add_reg_instruction_hook(self,newreg(R_ADDRESSREGISTER,i,R_SUBWHOLE));
+ end;
+ end;
+ end;
+
+
+ procedure taicpu.init(_size : topsize);
+ begin
+ typ:=ait_instruction;
+ is_jmp:=false;
+ opsize:=_size;
+ ops:=0;
+ end;
+
+
+ constructor taicpu.op_none(op : tasmop);
+ begin
+ inherited create(op);
+ init(S_NO);
+ end;
+
+
+ constructor taicpu.op_none(op : tasmop;_size : topsize);
+ begin
+ inherited create(op);
+ init(_size);
+ end;
+
+
+ constructor taicpu.op_reg(op : tasmop;_size : topsize;_op1 : tregister);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=1;
+ loadreg(0,_op1);
+ end;
+
+
+ constructor taicpu.op_const(op : tasmop;_size : topsize;_op1 : longint);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=1;
+ loadconst(0,aword(_op1));
+ end;
+
+
+ constructor taicpu.op_ref(op : tasmop;_size : topsize;_op1 : treference);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=1;
+ loadref(0,_op1);
+ end;
+
+
+ constructor taicpu.op_reg_reg(op : tasmop;_size : topsize;_op1,_op2 : tregister);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=2;
+ loadreg(0,_op1);
+ loadreg(1,_op2);
+ end;
+
+
+ constructor taicpu.op_reg_const(op:tasmop; _size: topsize; _op1: tregister; _op2: longint);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=2;
+ loadreg(0,_op1);
+ loadconst(1,aword(_op2));
+ end;
+
+
+ constructor taicpu.op_reg_ref(op : tasmop;_size : topsize;_op1 : tregister;_op2 : treference);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=2;
+ loadreg(0,_op1);
+ loadref(1,_op2);
+ end;
+
+
+ constructor taicpu.op_const_reg(op : tasmop;_size : topsize;_op1 : longint;_op2 : tregister);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=2;
+ loadconst(0,aword(_op1));
+ loadreg(1,_op2);
+ end;
+
+
+ constructor taicpu.op_const_const(op : tasmop;_size : topsize;_op1,_op2 : longint);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=2;
+ loadconst(0,aword(_op1));
+ loadconst(1,aword(_op2));
+ end;
+
+
+ constructor taicpu.op_const_ref(op : tasmop;_size : topsize;_op1 : longint;_op2 : treference);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=2;
+ loadconst(0,aword(_op1));
+ loadref(1,_op2);
+ end;
+
+
+ constructor taicpu.op_ref_reg(op : tasmop;_size : topsize;_op1 : treference;_op2 : tregister);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=2;
+ loadref(0,_op1);
+ loadreg(1,_op2);
+ end;
+
+
+ constructor taicpu.op_ref_ref(op : tasmop;_size : topsize;_op1,_op2 : treference);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=2;
+ loadref(0,_op1);
+ loadref(1,_op2);
+ end;
+
+
+ constructor taicpu.op_reg_reg_reg(op : tasmop;_size : topsize;_op1,_op2,_op3 : tregister);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=3;
+ loadreg(0,_op1);
+ loadreg(1,_op2);
+ loadreg(2,_op3);
+ end;
+
+ constructor taicpu.op_const_reg_reg(op : tasmop;_size : topsize;_op1 : longint;_op2 : tregister;_op3 : tregister);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=3;
+ loadconst(0,aword(_op1));
+ loadreg(1,_op2);
+ loadreg(2,_op3);
+ end;
+
+ constructor taicpu.op_reg_reg_ref(op : tasmop;_size : topsize;_op1,_op2 : tregister;_op3 : treference);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=3;
+ loadreg(0,_op1);
+ loadreg(1,_op2);
+ loadref(2,_op3);
+ end;
+
+
+ constructor taicpu.op_const_ref_reg(op : tasmop;_size : topsize;_op1 : longint;_op2 : treference;_op3 : tregister);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=3;
+ loadconst(0,aword(_op1));
+ loadref(1,_op2);
+ loadreg(2,_op3);
+ end;
+
+
+ constructor taicpu.op_const_reg_ref(op : tasmop;_size : topsize;_op1 : longint;_op2 : tregister;_op3 : treference);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=3;
+ loadconst(0,aword(_op1));
+ loadreg(1,_op2);
+ loadref(2,_op3);
+ end;
+
+
+ constructor taicpu.op_ref_regset(op: tasmop; _size : topsize; _op1: treference;const _op2: tcpuregisterset);
+ Begin
+ inherited create(op);
+ init(_size);
+ ops:=2;
+ loadref(0,_op1);
+ loadregset(1,_op2);
+ end;
+
+ constructor taicpu.op_regset_ref(op: tasmop; _size : topsize;const _op1: tcpuregisterset; _op2: treference);
+ Begin
+ inherited create(op);
+ init(_size);
+ ops:=2;
+ loadregset(0,_op1);
+ loadref(1,_op2);
+ End;
+
+
+
+ constructor taicpu.op_reg_regset(op: tasmop; _size : topsize; _op1: tregister;const _op2: tcpuregisterset);
+ Begin
+ inherited create(op);
+ init(_size);
+ ops:=2;
+ loadreg(0,_op1);
+ loadregset(1,_op2);
+ end;
+
+
+ constructor taicpu.op_regset_reg(op: tasmop; _size : topsize;const _op1: tcpuregisterset; _op2: tregister);
+ Begin
+ inherited create(op);
+ init(_size);
+ ops:=2;
+ loadregset(0,_op1);
+ loadreg(1,_op2);
+ End;
+
+
+ constructor taicpu.op_sym(op : tasmop;_size : topsize;_op1 : tasmsymbol);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=1;
+ loadsymbol(0,_op1,0);
+ end;
+
+
+ constructor taicpu.op_reg_sym(op: tasmop; _size : topsize; _op1: tregister; _op2 :tasmsymbol);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=2;
+ loadreg(0,_op1);
+ loadsymbol(1,_op2,0);
+ end;
+
+
+ constructor taicpu.op_sym_ofs_ref(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint;const _op2 : treference);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=2;
+ loadsymbol(0,_op1,_op1ofs);
+ loadref(1,_op2);
+ end;
+
+
+ constructor taicpu.op_sym_ofs(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=1;
+ loadsymbol(0,_op1,_op1ofs);
+ end;
+
+ constructor taicpu.op_sym_ofs_reg(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint;_op2 : tregister);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=2;
+ if ((op >= A_DBCC) and (op <= A_DBF))
+ or ((op >= A_FDBEQ) and (op <= A_FDBNGLE)) then
+ begin
+ loadreg(0,_op2);
+ loadsymbol(1,_op1,_op1ofs);
+ end
+ else
+ begin
+ loadsymbol(0,_op1,_op1ofs);
+ loadreg(1,_op2);
+ end;
+ end;
+
+
+ constructor taicpu.op_cond_sym(op : tasmop;cond:TAsmCond;_size : topsize;_op1 : tasmsymbol);
+ begin
+ inherited create(op);
+ init(_size);
+ condition:=cond;
+ ops:=1;
+ loadsymbol(0,_op1,0);
+ end;
+
+
+ function taicpu.is_same_reg_move(regtype: Tregistertype):boolean;
+ begin
+ result:=(((opcode=A_MOVE) or (opcode=A_EXG)) and
+ (regtype = R_INTREGISTER) and
+ (ops=2) and
+ (oper[0]^.typ=top_reg) and
+ (oper[1]^.typ=top_reg) and
+ (oper[0]^.reg=oper[1]^.reg)
+ ) or
+ (((opcode=A_MOVE) or (opcode=A_EXG) or (opcode=A_MOVEA)) and
+ (regtype = R_ADDRESSREGISTER) and
+ (ops=2) and
+ (oper[0]^.typ=top_reg) and
+ (oper[1]^.typ=top_reg) and
+ (oper[0]^.reg=oper[1]^.reg)
+ ) or
+ ((opcode=A_FMOVE) and
+ (regtype = R_FPUREGISTER) and
+ (ops=2) and
+ (oper[0]^.typ=top_reg) and
+ (oper[1]^.typ=top_reg) and
+ (oper[0]^.reg=oper[1]^.reg)
+ );
+ end;
+
+
+ function taicpu.spilling_get_operation_type(opnr: longint): topertype;
+ begin
+ case opcode of
+ A_MOVE, A_MOVEQ, A_ADD, A_ADDQ, A_ADDX, A_SUB, A_SUBQ,
+ A_AND, A_LSR, A_LSL, A_ASR, A_ASL, A_EOR, A_EORI, A_OR:
+ if opnr=1 then begin
+ result:=operand_write;
+ end else begin
+ result:=operand_read;
+ end;
+ A_TST,A_CMP,A_CMPI:
+ result:=operand_read;
+ A_CLR, A_SXX:
+ result:=operand_write;
+ A_NEG, A_EXT, A_EXTB, A_NOT:
+ result:=operand_readwrite;
+ else begin
+{ TODO: FIX ME!!! remove ugly debug code ... }
+ writeln('M68K: unknown opcode when spilling: ',gas_op2str[opcode]);
+ internalerror(200404091);
+ end;
+ end;
+ end;
+
+
+ function spilling_create_load(const ref:treference;r:tregister):Taicpu;
+ begin
+ case getregtype(r) of
+ R_INTREGISTER :
+ result:=taicpu.op_ref_reg(A_MOVE,S_L,ref,r);
+ R_ADDRESSREGISTER :
+ result:=taicpu.op_ref_reg(A_MOVE,S_L,ref,r);
+ R_FPUREGISTER :
+ // no need to handle sizes here
+ result:=taicpu.op_ref_reg(A_FMOVE,S_FS,ref,r);
+ else
+ internalerror(200602011);
+ end;
+ end;
+
+
+ function spilling_create_store(r:tregister; const ref:treference):Taicpu;
+ begin
+ case getregtype(r) of
+ R_INTREGISTER :
+ result:=taicpu.op_reg_ref(A_MOVE,S_L,r,ref);
+ R_ADDRESSREGISTER :
+ result:=taicpu.op_reg_ref(A_MOVE,S_L,r,ref);
+ R_FPUREGISTER :
+ // no need to handle sizes here
+ result:=taicpu.op_reg_ref(A_FMOVE,S_FS,r,ref);
+ else
+ internalerror(200602012);
+ end;
+ end;
+
+
+ procedure InitAsm;
+ begin
+ end;
+
+
+ procedure DoneAsm;
+ begin
+ end;
+
+
+end.
diff --git a/closures/compiler/m68k/ag68kgas.pas b/closures/compiler/m68k/ag68kgas.pas
new file mode 100644
index 0000000000..e2e5bc28ba
--- /dev/null
+++ b/closures/compiler/m68k/ag68kgas.pas
@@ -0,0 +1,385 @@
+{
+ Copyright (c) 1998-2006 by the Free Pascal development team
+
+ This unit implements an asmoutput class for m68k GAS syntax
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit ag68kgas;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cclasses,cpubase,
+ globals,
+ aasmbase,aasmtai,aasmdata,aasmcpu,assemble,aggas;
+
+ type
+ Tm68kGNUAssembler=class(TGNUassembler)
+ constructor create(smart: boolean); override;
+ end;
+
+ type
+ Tm68kInstrWriter=class(TCPUInstrWriter)
+ procedure WriteInstruction(hp: tai);override;
+ end;
+
+ const
+ gas_op2str:op2strtable=
+ { warning: CPU32 opcodes are not fully compatible with the MC68020. }
+ { 68000 only opcodes }
+ ( '',
+ 'abcd','add','adda','addi','addq','addx','and','andi',
+ 'asl','asr','bcc','bcs','beq','bge','bgt','bhi',
+ 'ble','bls','blt','bmi','bne','bpl','bvc','bvs',
+ 'bchg','bclr','bra','bset','bsr','btst','chk',
+ 'clr','cmp','cmpa','cmpi','cmpm','dbcc','dbcs','dbeq','dbge',
+ 'dbgt','dbhi','dble','dbls','dblt','dbmi','dbne','dbra',
+ 'dbpl','dbt','dbvc','dbvs','dbf','divs','divu',
+ 'eor','eori','exg','illegal','ext','jmp','jsr',
+ 'lea','link','lsl','lsr','move','movea','movei','moveq',
+ 'movem','movep','muls','mulu','nbcd','neg','negx',
+ 'nop','not','or','ori','pea','rol','ror','roxl',
+ 'roxr','rtr','rts','sbcd','scc','scs','seq','sge',
+ 'sgt','shi','sle','sls','slt','smi','sne',
+ 'spl','st','svc','svs','sf','sub','suba','subi','subq',
+ 'subx','swap','tas','trap','trapv','tst','unlk',
+ 'rte','reset','stop',
+ { mc68010 instructions }
+ 'bkpt','movec','moves','rtd',
+ { mc68020 instructions }
+ 'bfchg','bfclr','bfexts','bfextu','bfffo',
+ 'bfins','bfset','bftst','callm','cas','cas2',
+ 'chk2','cmp2','divsl','divul','extb','pack','rtm',
+ 'trapcc','tracs','trapeq','trapf','trapge','trapgt',
+ 'traphi','traple','trapls','traplt','trapmi','trapne',
+ 'trappl','trapt','trapvc','trapvs','unpk',
+ { fpu processor instructions - directly supported only. }
+ { ieee aware and misc. condition codes not supported }
+ 'fabs','fadd',
+ 'fbeq','fbne','fbngt','fbgt','fbge','fbnge',
+ 'fblt','fbnlt','fble','fbgl','fbngl','fbgle','fbngle',
+ 'fdbeq','fdbne','fdbgt','fdbngt','fdbge','fdbnge',
+ 'fdblt','fdbnlt','fdble','fdbgl','fdbngl','fdbgle','fdbngle',
+ 'fseq','fsne','fsgt','fsngt','fsge','fsnge',
+ 'fslt','fsnlt','fsle','fsgl','fsngl','fsgle','fsngle',
+ 'fcmp','fdiv','fmove','fmovem',
+ 'fmul','fneg','fnop','fsqrt','fsub','fsgldiv',
+ 'fsflmul','ftst',
+ 'ftrapeq','ftrapne','ftrapgt','ftrapngt','ftrapge','ftrapnge',
+ 'ftraplt','ftrapnlt','ftraple','ftrapgl','ftrapngl','ftrapgle','ftrapngle',
+ { protected instructions }
+ 'cprestore','cpsave',
+ { fpu unit protected instructions }
+ { and 68030/68851 common mmu instructions }
+ { (this may include 68040 mmu instructions) }
+ 'frestore','fsave','pflush','pflusha','pload','pmove','ptest',
+ { useful for assembly language output }
+ 'label','db','s','b','fb');
+
+
+ gas_opsize2str : array[topsize] of string[2] =
+ ('','.b','.w','.l','.s','.d','.x',''
+ );
+{
+ gas_reg2str : treg2strtable =
+ ('', '%d0','%d1','%d2','%d3','%d4','%d5','%d6','%d7',
+ '%a0','%a1','%a2','%a3','%a4','%a5','%a6','%sp',
+ '-(%sp)','(%sp)+',
+ '%ccr','%fp0','%fp1','%fp2','%fp3','%fp4','%fp5',
+ '%fp6','%fp7','%fpcr','%sr','%ssp','%dfc',
+ '%sfc','%vbr','%fpsr');
+}
+
+ implementation
+
+ uses
+ cutils,systems,
+ cgbase,cgutils,
+ verbose,itcpugas;
+
+
+ {****************************************************************************}
+ { GNU m68k Assembler writer }
+ {****************************************************************************}
+
+ constructor Tm68kGNUAssembler.create(smart: boolean);
+ begin
+ inherited create(smart);
+ InstrWriter := Tm68kInstrWriter.create(self);
+ end;
+
+
+ function getreferencestring(var ref : treference) : string;
+ var
+ s,basestr,indexstr : string;
+
+ begin
+ s:='';
+ with ref do
+ begin
+ basestr:=gas_regname(base);
+ indexstr:=gas_regname(index);
+ if assigned(symbol) then
+ s:=s+symbol.name;
+
+ if offset<0 then s:=s+tostr(offset)
+ else if (offset>0) then
+ begin
+ if (symbol=nil) then s:=tostr(offset)
+ else s:=s+'+'+tostr(offset);
+ end
+ else if (index=NR_NO) and (base=NR_NO) and not assigned(symbol) then
+ s:=s+'0';
+
+ if (index<>NR_NO) and (base=NR_NO) and (direction=dir_none) then
+ begin
+ if (scalefactor = 1) or (scalefactor = 0) then
+ s:=s+'(,'+indexstr+'.l)'
+ else
+ s:=s+'(,'+indexstr+'.l*'+tostr(scalefactor)+')'
+ end
+ else if (index=NR_NO) and (base<>NR_NO) and (direction=dir_inc) then
+ begin
+ if (scalefactor = 1) or (scalefactor = 0) then
+ s:=s+'('+basestr+')+'
+ else
+ InternalError(10002);
+ end
+ else if (index=NR_NO) and (base<>NR_NO) and (direction=dir_dec) then
+ begin
+ if (scalefactor = 1) or (scalefactor = 0) then
+ s:=s+'-('+basestr+')'
+ else
+ InternalError(10003);
+ end
+ else if (index=NR_NO) and (base<>NR_NO) and (direction=dir_none) then
+ begin
+ s:=s+'('+basestr+')'
+ end
+ else if (index<>NR_NO) and (base<>NR_NO) and (direction=dir_none) then
+ begin
+ if (scalefactor = 1) or (scalefactor = 0) then
+ s:=s+'('+basestr+','+indexstr+'.l)'
+ else
+ s:=s+'('+basestr+','+indexstr+'.l*'+tostr(scalefactor)+')';
+ end;
+ end;
+ getreferencestring:=s;
+ end;
+
+
+ function getopstr(const o:toper) : string;
+ var
+ hs : string;
+ i : tsuperregister;
+ begin
+ case o.typ of
+ top_reg: begin
+ getopstr:=gas_regname(o.reg);
+// writeln('top_reg:',getopstr,'!');
+ end;
+ top_ref:
+ if o.ref^.refaddr=addr_full then
+ begin
+ if assigned(o.ref^.symbol) then
+ hs:=o.ref^.symbol.name
+ else
+ hs:='#';
+ if o.ref^.offset>0 then
+ hs:=hs+'+'+tostr(o.ref^.offset)
+ else
+ if o.ref^.offset<0 then
+ hs:=hs+tostr(o.ref^.offset)
+ else
+ if not(assigned(o.ref^.symbol)) then
+ hs:=hs+'0';
+ getopstr:=hs;
+ end
+ else
+ getopstr:=getreferencestring(o.ref^);
+ top_regset:
+ begin
+ hs:='';
+ for i:=RS_D0 to RS_D7 do
+ begin
+ if i in o.regset^ then
+ hs:=hs+gas_regname(newreg(R_INTREGISTER,i,R_SUBWHOLE))+'/';
+ end;
+ for i:=RS_A0 to RS_SP do
+ begin
+ if i in o.regset^ then
+ hs:=hs+gas_regname(newreg(R_INTREGISTER,i,R_SUBWHOLE))+'/';
+ end;
+ delete(hs,length(hs),1);
+ getopstr := hs;
+ end;
+ top_const:
+ getopstr:='#'+tostr(longint(o.val));
+ else internalerror(200405021);
+ end;
+ end;
+
+
+ function getopstr_jmp(const o:toper) : string;
+ var
+ hs : string;
+ begin
+ case o.typ of
+ top_reg:
+ getopstr_jmp:=gas_regname(o.reg);
+ top_ref:
+ if o.ref^.refaddr=addr_no then
+ getopstr_jmp:=getreferencestring(o.ref^)
+ else
+ begin
+ if assigned(o.ref^.symbol) then
+ hs:=o.ref^.symbol.name
+ else
+ hs:='';
+ if o.ref^.offset>0 then
+ hs:=hs+'+'+tostr(o.ref^.offset)
+ else
+ if o.ref^.offset<0 then
+ hs:=hs+tostr(o.ref^.offset)
+ else
+ if not(assigned(o.ref^.symbol)) then
+ hs:=hs+'0';
+ getopstr_jmp:=hs;
+ end;
+ top_const:
+ getopstr_jmp:=tostr(o.val);
+ else internalerror(200405022);
+ end;
+ end;
+
+{****************************************************************************
+ TM68kASMOUTPUT
+ ****************************************************************************}
+
+ { returns the opcode string }
+ function getopcodestring(hp : tai) : string;
+ var
+ op : tasmop;
+ s : string;
+ begin
+ op:=taicpu(hp).opcode;
+ { old versions of GAS don't like PEA.L and LEA.L }
+ if (op in [
+ A_LEA,A_PEA,A_ABCD,A_BCHG,A_BCLR,A_BSET,A_BTST,
+ A_EXG,A_NBCD,A_SBCD,A_SWAP,A_TAS,A_SCC,A_SCS,
+ A_SEQ,A_SGE,A_SGT,A_SHI,A_SLE,A_SLS,A_SLT,A_SMI,
+ A_SNE,A_SPL,A_ST,A_SVC,A_SVS,A_SF]) then
+ s:=gas_op2str[op]
+ else
+ if op = A_SXX then
+ s:=gas_op2str[op]+cond2str[taicpu(hp).condition]
+ else
+ { size of DBRA is always WORD, doesn't need opsize (KB) }
+ if op = A_DBRA then
+ s:=gas_op2str[op]+cond2str[taicpu(hp).condition]
+ else
+ if op in [a_dbxx,a_bxx,a_fbxx] then
+ s:=gas_op2str[op]+cond2str[taicpu(hp).condition]+gas_opsize2str[taicpu(hp).opsize]
+ else
+ s:=gas_op2str[op]+gas_opsize2str[taicpu(hp).opsize];
+ if op = A_FMOVE then
+ begin
+{$ifdef DEBUG_CHARLIE}
+ writeln('fmove! opsize:',dword(taicpu(hp).opsize));
+{$endif DEBUG_CHARLIE}
+ end;
+ getopcodestring:=s;
+ end;
+
+
+ procedure Tm68kInstrWriter.WriteInstruction(hp: tai);
+ var
+ op : tasmop;
+ s : string;
+ sep : char;
+ calljmp : boolean;
+ i : integer;
+ begin
+ if hp.typ <> ait_instruction then exit;
+ op:=taicpu(hp).opcode;
+ calljmp:=is_calljmp(op);
+ { call maybe not translated to call }
+ s:=#9+getopcodestring(hp);
+ { process operands }
+ if taicpu(hp).ops<>0 then
+ begin
+ { call and jmp need an extra handling }
+ { this code is only called if jmp isn't a labeled instruction }
+ { quick hack to overcome a problem with manglednames=255 chars }
+ if calljmp then
+ begin
+ owner.AsmWrite(s+#9);
+ s:=getopstr_jmp(taicpu(hp).oper[0]^);
+ { dbcc dx,<sym> has two operands! (KB) }
+ if (taicpu(hp).ops>1) then
+ s:=s+','+getopstr_jmp(taicpu(hp).oper[1]^);
+ if (taicpu(hp).ops>2) then
+ internalerror(2006120501);
+ end
+ else
+ begin
+ for i:=0 to taicpu(hp).ops-1 do
+ begin
+ if i=0 then
+ sep:=#9
+ else
+ if ((op = A_DIVSL) or
+ (op = A_DIVUL) or
+ (op = A_MULU) or
+ (op = A_MULS) or
+ (op = A_DIVS) or
+ (op = A_DIVU)) and (i=2) then
+ begin
+ sep:=':'
+ end else
+ sep:=',';
+ s:=s+sep+getopstr(taicpu(hp).oper[i]^)
+ end;
+ end;
+ end;
+ owner.AsmWriteLn(s);
+ end;
+
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+ const
+ as_m68k_as_info : tasminfo =
+ (
+ id : as_gas;
+ idtxt : 'AS';
+ asmbin : 'as';
+ asmcmd : '-o $OBJ $ASM';
+ supported_targets : [system_m68k_Amiga,system_m68k_Atari,system_m68k_Mac,system_m68k_linux,system_m68k_PalmOS,system_m68k_netbsd,system_m68k_openbsd,system_m68k_embedded];
+ flags : [af_allowdirect,af_needar,af_smartlink_sections];
+ labelprefix : '.L';
+ comment : '# ';
+ );
+
+initialization
+ RegisterAssembler(as_m68k_as_info,Tm68kGNUAssembler);
+end.
diff --git a/closures/compiler/m68k/aoptcpu.pas b/closures/compiler/m68k/aoptcpu.pas
new file mode 100644
index 0000000000..cb656af36e
--- /dev/null
+++ b/closures/compiler/m68k/aoptcpu.pas
@@ -0,0 +1,41 @@
+{
+ Copyright (c) 1998-2004 by Jonas Maebe
+
+ This unit calls the optimization procedures to optimize the assembler
+ code for sparc
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+
+unit aoptcpu;
+
+{$i fpcdefs.inc}
+
+ Interface
+
+ uses
+ cpubase, aoptobj, aoptcpub, aopt;
+
+ Type
+ TCpuAsmOptimizer = class(TAsmOptimizer)
+ End;
+
+ Implementation
+
+begin
+ casmoptimizer:=TCpuAsmOptimizer;
+end.
diff --git a/closures/compiler/m68k/aoptcpub.pas b/closures/compiler/m68k/aoptcpub.pas
new file mode 100644
index 0000000000..bf1ab48cb8
--- /dev/null
+++ b/closures/compiler/m68k/aoptcpub.pas
@@ -0,0 +1,120 @@
+ {
+ Copyright (c) 1998-2004 by Jonas Maebe, member of the Free Pascal
+ Development Team
+
+ This unit contains several types and constants necessary for the
+ optimizer to work on the sparc architecture
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+Unit aoptcpub; { Assembler OPTimizer CPU specific Base }
+
+{$i fpcdefs.inc}
+
+{ enable the following define if memory references can have both a base and }
+{ index register in 1 operand }
+
+{$define RefsHaveIndexReg}
+
+{ enable the following define if memory references can have a scaled index }
+
+{ define RefsHaveScale}
+
+{ enable the following define if memory references can have a segment }
+{ override }
+
+{ define RefsHaveSegment}
+
+Interface
+
+Uses
+ cpubase,aasmcpu,AOptBase;
+
+Type
+
+{ type of a normal instruction }
+ TInstr = Taicpu;
+ PInstr = ^TInstr;
+
+{ ************************************************************************* }
+{ **************************** TCondRegs ********************************** }
+{ ************************************************************************* }
+{ Info about the conditional registers }
+ TCondRegs = Object
+ Constructor Init;
+ Destructor Done;
+ End;
+
+{ ************************************************************************* }
+{ **************************** TAoptBaseCpu ******************************* }
+{ ************************************************************************* }
+
+ TAoptBaseCpu = class(TAoptBase)
+ End;
+
+
+{ ************************************************************************* }
+{ ******************************* Constants ******************************* }
+{ ************************************************************************* }
+Const
+
+{ the maximum number of things (registers, memory, ...) a single instruction }
+{ changes }
+
+ MaxCh = 3;
+
+{ the maximum number of operands an instruction has }
+
+ MaxOps = 3;
+
+{Oper index of operand that contains the source (reference) with a load }
+{instruction }
+
+ LoadSrc = 0;
+
+{Oper index of operand that contains the destination (register) with a load }
+{instruction }
+
+ LoadDst = 1;
+
+{Oper index of operand that contains the source (register) with a store }
+{instruction }
+
+ StoreSrc = 0;
+
+{Oper index of operand that contains the destination (reference) with a load }
+{instruction }
+
+ StoreDst = 1;
+
+ aopt_uncondjmp = A_JMP;
+ aopt_condjmp = A_Bxx;
+
+Implementation
+
+{ ************************************************************************* }
+{ **************************** TCondRegs ********************************** }
+{ ************************************************************************* }
+Constructor TCondRegs.init;
+Begin
+End;
+
+Destructor TCondRegs.Done; {$ifdef inl} inline; {$endif inl}
+Begin
+End;
+
+End.
diff --git a/closures/compiler/m68k/aoptcpud.pas b/closures/compiler/m68k/aoptcpud.pas
new file mode 100644
index 0000000000..cb8c5d319f
--- /dev/null
+++ b/closures/compiler/m68k/aoptcpud.pas
@@ -0,0 +1,36 @@
+{
+ Copyright (c) 1998-2004 by Jonas Maebe, member of the Free Pascal
+ Development Team
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+Unit aoptcpud;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ aoptda;
+
+ type
+ TAOptDFACpu = class(TAOptDFA)
+ end;
+
+ implementation
+
+end.
diff --git a/closures/compiler/m68k/cgcpu.pas b/closures/compiler/m68k/cgcpu.pas
new file mode 100644
index 0000000000..a98ffce61b
--- /dev/null
+++ b/closures/compiler/m68k/cgcpu.pas
@@ -0,0 +1,1751 @@
+{
+ Copyright (c) 1998-2002 by the FPC team
+
+ This unit implements the code generator for the 680x0
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+{DEFINE DEBUG_CHARLIE}
+
+{$IFNDEF DEBUG_CHARLIE}
+{$WARNINGS OFF}
+{$ENDIF}
+unit cgcpu;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ cgbase,cgobj,globtype,
+ aasmbase,aasmtai,aasmdata,aasmcpu,
+ cpubase,cpuinfo,
+ parabase,cpupara,
+ node,symconst,symtype,symdef,
+ cgutils,cg64f32;
+
+ type
+ tcg68k = class(tcg)
+ procedure init_register_allocators;override;
+ procedure done_register_allocators;override;
+
+ procedure a_load_reg_cgpara(list : TAsmList;size : tcgsize;r : tregister;const cgpara : tcgpara);override;
+ procedure a_load_const_cgpara(list : TAsmList;size : tcgsize;a : tcgint;const cgpara : tcgpara);override;
+ procedure a_load_ref_cgpara(list : TAsmList;size : tcgsize;const r : treference;const cgpara : tcgpara);override;
+ procedure a_loadaddr_ref_cgpara(list : TAsmList;const r : treference;const cgpara : tcgpara);override;
+
+ procedure a_call_name(list : TAsmList;const s : string; weak: boolean);override;
+ procedure a_call_reg(list : TAsmList;reg : tregister);override;
+
+ procedure a_load_const_reg(list : TAsmList;size : tcgsize;a : tcgint;register : tregister);override;
+ procedure a_load_const_ref(list : TAsmList; tosize: tcgsize; a : tcgint;const ref : treference);override;
+
+ procedure a_load_reg_ref(list : TAsmList;fromsize,tosize : tcgsize;register : tregister;const ref : treference);override;
+ procedure a_load_reg_reg(list : TAsmList;fromsize,tosize : tcgsize;reg1,reg2 : tregister);override;
+ procedure a_load_ref_reg(list : TAsmList;fromsize,tosize : tcgsize;const ref : treference;register : tregister);override;
+ procedure a_load_ref_ref(list : TAsmList;fromsize,tosize : tcgsize;const sref : treference;const dref : treference);override;
+
+ procedure a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);override;
+ procedure a_loadfpu_reg_reg(list: TAsmList; fromsize, tosize: tcgsize; reg1, reg2: tregister); override;
+ procedure a_loadfpu_ref_reg(list: TAsmList; fromsize, tosize: tcgsize; const ref: treference; reg: tregister); override;
+ procedure a_loadfpu_reg_ref(list: TAsmList; fromsize, tosize: tcgsize; reg: tregister; const ref: treference); override;
+
+ procedure a_loadmm_reg_reg(list: TAsmList;fromsize,tosize : tcgsize; reg1, reg2: tregister;shuffle : pmmshuffle); override;
+ procedure a_loadmm_ref_reg(list: TAsmList;fromsize,tosize : tcgsize; const ref: treference; reg: tregister;shuffle : pmmshuffle); override;
+ procedure a_loadmm_reg_ref(list: TAsmList;fromsize,tosize : tcgsize; reg: tregister; const ref: treference;shuffle : pmmshuffle); override;
+ procedure a_loadmm_reg_cgpara(list: TAsmList; size: tcgsize; reg: tregister;const locpara : TCGPara;shuffle : pmmshuffle); override;
+
+ procedure a_op_const_reg(list : TAsmList; Op: TOpCG; size: tcgsize; a: tcgint; reg: TRegister); override;
+// procedure a_op_const_ref(list : TAsmList; Op: TOpCG; size: TCGSize; a: tcgint; const ref: TReference); override;
+ procedure a_op_reg_reg(list : TAsmList; Op: TOpCG; size: TCGSize; reg1, reg2: TRegister); override;
+
+ procedure a_cmp_const_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;a : tcgint;reg : tregister;
+ l : tasmlabel);override;
+ procedure a_cmp_reg_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel); override;
+ procedure a_jmp_always(list : TAsmList;l: tasmlabel); override;
+ procedure a_jmp_flags(list : TAsmList;const f : TResFlags;l: tasmlabel); override;
+ procedure g_flags2reg(list: TAsmList; size: TCgSize; const f: tresflags; reg: TRegister); override;
+
+ procedure g_concatcopy(list : TAsmList;const source,dest : treference;len : tcgint);override;
+ { generates overflow checking code for a node }
+ procedure g_overflowcheck(list: TAsmList; const l:tlocation; def:tdef); override;
+ procedure g_copyvaluepara_openarray(list : TAsmList;const ref:treference;const lenloc:tlocation;elesize:tcgint;destreg:tregister);override;
+
+ procedure g_proc_entry(list : TAsmList;localsize : longint;nostackframe:boolean);override;
+ procedure g_proc_exit(list : TAsmList;parasize:longint;nostackframe:boolean);override;
+
+// procedure g_restore_frame_pointer(list : TAsmList);override;
+// procedure g_return_from_proc(list : TAsmList;parasize : tcgint);override;
+ procedure g_restore_registers(list:TAsmList);override;
+ procedure g_save_registers(list:TAsmList);override;
+
+// procedure g_save_all_registers(list : TAsmList);override;
+// procedure g_restore_all_registers(list : TAsmList;const funcretparaloc:TCGPara);override;
+
+ procedure g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);override;
+
+ protected
+ function fixref(list: TAsmList; var ref: treference): boolean;
+ private
+ { # Sign or zero extend the register to a full 32-bit value.
+ The new value is left in the same register.
+ }
+ procedure sign_extend(list: TAsmList;_oldsize : tcgsize; reg: tregister);
+ procedure a_jmp_cond(list : TAsmList;cond : TOpCmp;l: tasmlabel);
+
+ end;
+
+ tcg64f68k = class(tcg64f32)
+ procedure a_op64_reg_reg(list : TAsmList;op:TOpCG; size: tcgsize; regsrc,regdst : tregister64);override;
+ procedure a_op64_const_reg(list : TAsmList;op:TOpCG; size: tcgsize; value : int64;regdst : tregister64);override;
+ end;
+
+ { This function returns true if the reference+offset is valid.
+ Otherwise extra code must be generated to solve the reference.
+
+ On the m68k, this verifies that the reference is valid
+ (e.g : if index register is used, then the max displacement
+ is 256 bytes, if only base is used, then max displacement
+ is 32K
+ }
+ function isvalidrefoffset(const ref: treference): boolean;
+
+ const
+ TCGSize2OpSize: Array[tcgsize] of topsize =
+ (S_NO,S_B,S_W,S_L,S_L,S_NO,S_B,S_W,S_L,S_L,S_NO,
+ S_FS,S_FD,S_FX,S_NO,S_NO,
+ S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_NO);
+
+ procedure create_codegen;
+
+ implementation
+
+ uses
+ globals,verbose,systems,cutils,
+ symsym,defutil,paramgr,procinfo,
+ rgobj,tgobj,rgcpu,fmodule;
+
+
+ const
+ { opcode table lookup }
+ topcg2tasmop: Array[topcg] of tasmop =
+ (
+ A_NONE,
+ A_MOVE,
+ A_ADD,
+ A_AND,
+ A_DIVU,
+ A_DIVS,
+ A_MULS,
+ A_MULU,
+ A_NEG,
+ A_NOT,
+ A_OR,
+ A_ASR,
+ A_LSL,
+ A_LSR,
+ A_SUB,
+ A_EOR,
+ A_NONE,
+ A_NONE
+ );
+
+
+ TOpCmp2AsmCond: Array[topcmp] of TAsmCond =
+ (
+ C_NONE,
+ C_EQ,
+ C_GT,
+ C_LT,
+ C_GE,
+ C_LE,
+ C_NE,
+ C_LS,
+ C_CS,
+ C_CC,
+ C_HI
+ );
+
+
+ function isvalidrefoffset(const ref: treference): boolean;
+ begin
+ isvalidrefoffset := true;
+ if ref.index <> NR_NO then
+ begin
+ if ref.base <> NR_NO then
+ internalerror(20020814);
+ if (ref.offset < low(shortint)) or (ref.offset > high(shortint)) then
+ isvalidrefoffset := false
+ end
+ else
+ begin
+ if (ref.offset < low(smallint)) or (ref.offset > high(smallint)) then
+ isvalidrefoffset := false;
+ end;
+ end;
+
+
+{****************************************************************************}
+{ TCG68K }
+{****************************************************************************}
+
+
+ function use_push(const cgpara:tcgpara):boolean;
+ begin
+ result:=(not paramanager.use_fixed_stack) and
+ assigned(cgpara.location) and
+ (cgpara.location^.loc=LOC_REFERENCE) and
+ (cgpara.location^.reference.index=NR_STACK_POINTER_REG);
+ end;
+
+
+ procedure tcg68k.init_register_allocators;
+ begin
+ inherited init_register_allocators;
+ rg[R_INTREGISTER]:=trgcpu.create(R_INTREGISTER,R_SUBWHOLE,
+ [RS_D0,RS_D1,RS_D2,RS_D3,RS_D4,RS_D5,RS_D6,RS_D7],
+ first_int_imreg,[]);
+ rg[R_ADDRESSREGISTER]:=trgcpu.create(R_ADDRESSREGISTER,R_SUBWHOLE,
+ [RS_A0,RS_A1,RS_A2,RS_A3,RS_A4,RS_A5,RS_A6],
+ first_addr_imreg,[]);
+ rg[R_FPUREGISTER]:=trgcpu.create(R_FPUREGISTER,R_SUBNONE,
+ [RS_FP0,RS_FP1,RS_FP2,RS_FP3,RS_FP4,RS_FP5,RS_FP6,RS_FP7],
+ first_fpu_imreg,[]);
+ end;
+
+
+ procedure tcg68k.done_register_allocators;
+ begin
+ rg[R_INTREGISTER].free;
+ rg[R_FPUREGISTER].free;
+ rg[R_ADDRESSREGISTER].free;
+ inherited done_register_allocators;
+ end;
+
+
+ procedure tcg68k.a_load_reg_cgpara(list : TAsmList;size : tcgsize;r : tregister;const cgpara : tcgpara);
+ var
+ pushsize : tcgsize;
+ ref : treference;
+ begin
+{$ifdef DEBUG_CHARLIE}
+// writeln('a_load_reg');_cgpara
+{$endif DEBUG_CHARLIE}
+ { it's probably necessary to port this from x86 later, or provide an m68k solution (KB) }
+{ TODO: FIX ME! check_register_size()}
+ // check_register_size(size,r);
+ if use_push(cgpara) then
+ begin
+ cgpara.check_simple_location;
+ if tcgsize2size[cgpara.location^.size]>cgpara.alignment then
+ pushsize:=cgpara.location^.size
+ else
+ pushsize:=int_cgsize(cgpara.alignment);
+
+ reference_reset_base(ref, NR_STACK_POINTER_REG, 0, cgpara.alignment);
+ ref.direction := dir_dec;
+ list.concat(taicpu.op_reg_ref(A_MOVE,tcgsize2opsize[pushsize],makeregsize(list,r,pushsize),ref));
+ end
+ else
+ inherited a_load_reg_cgpara(list,size,r,cgpara);
+ end;
+
+
+ procedure tcg68k.a_load_const_cgpara(list : TAsmList;size : tcgsize;a : tcgint;const cgpara : tcgpara);
+ var
+ pushsize : tcgsize;
+ ref : treference;
+ begin
+{$ifdef DEBUG_CHARLIE}
+// writeln('a_load_const');_cgpara
+{$endif DEBUG_CHARLIE}
+ if use_push(cgpara) then
+ begin
+ cgpara.check_simple_location;
+ if tcgsize2size[cgpara.location^.size]>cgpara.alignment then
+ pushsize:=cgpara.location^.size
+ else
+ pushsize:=int_cgsize(cgpara.alignment);
+
+ reference_reset_base(ref, NR_STACK_POINTER_REG, 0, cgpara.alignment);
+ ref.direction := dir_dec;
+ list.concat(taicpu.op_const_ref(A_MOVE,tcgsize2opsize[pushsize],a,ref));
+ end
+ else
+ inherited a_load_const_cgpara(list,size,a,cgpara);
+ end;
+
+
+ procedure tcg68k.a_load_ref_cgpara(list : TAsmList;size : tcgsize;const r : treference;const cgpara : tcgpara);
+
+ procedure pushdata(paraloc:pcgparalocation;ofs:tcgint);
+ var
+ pushsize : tcgsize;
+ tmpreg : tregister;
+ href : treference;
+ ref : treference;
+ begin
+ if not assigned(paraloc) then
+ exit;
+{ TODO: FIX ME!!! this also triggers location bug }
+ {if (paraloc^.loc<>LOC_REFERENCE) or
+ (paraloc^.reference.index<>NR_STACK_POINTER_REG) or
+ (tcgsize2size[paraloc^.size]>sizeof(tcgint)) then
+ internalerror(200501162);}
+
+ { Pushes are needed in reverse order, add the size of the
+ current location to the offset where to load from. This
+ prevents wrong calculations for the last location when
+ the size is not a power of 2 }
+ if assigned(paraloc^.next) then
+ pushdata(paraloc^.next,ofs+tcgsize2size[paraloc^.size]);
+ { Push the data starting at ofs }
+ href:=r;
+ inc(href.offset,ofs);
+ if tcgsize2size[paraloc^.size]>cgpara.alignment then
+ pushsize:=paraloc^.size
+ else
+ pushsize:=int_cgsize(cgpara.alignment);
+
+ reference_reset_base(ref, NR_STACK_POINTER_REG, 0, tcgsize2size[paraloc^.size]);
+ ref.direction := dir_dec;
+
+ if tcgsize2size[paraloc^.size]<cgpara.alignment then
+ begin
+ tmpreg:=getintregister(list,pushsize);
+ a_load_ref_reg(list,paraloc^.size,pushsize,href,tmpreg);
+ list.concat(taicpu.op_reg_ref(A_MOVE,tcgsize2opsize[pushsize],tmpreg,ref));
+ end
+ else
+ list.concat(taicpu.op_ref_ref(A_MOVE,tcgsize2opsize[pushsize],href,ref));
+ end;
+
+ var
+ len : tcgint;
+ href : treference;
+ begin
+{$ifdef DEBUG_CHARLIE}
+// writeln('a_load_ref');_cgpara
+{$endif DEBUG_CHARLIE}
+
+ { cgpara.size=OS_NO requires a copy on the stack }
+ if use_push(cgpara) then
+ begin
+ { Record copy? }
+ if (cgpara.size in [OS_NO,OS_F64]) or (size=OS_NO) then
+ begin
+ cgpara.check_simple_location;
+ len:=align(cgpara.intsize,cgpara.alignment);
+ g_stackpointer_alloc(list,len);
+ reference_reset_base(href,NR_STACK_POINTER_REG,0,cgpara.alignment);
+ g_concatcopy(list,r,href,len);
+ end
+ else
+ begin
+ if tcgsize2size[cgpara.size]<>tcgsize2size[size] then
+ internalerror(200501161);
+ { We need to push the data in reverse order,
+ therefor we use a recursive algorithm }
+ pushdata(cgpara.location,0);
+ end
+ end
+ else
+ inherited a_load_ref_cgpara(list,size,r,cgpara);
+ end;
+
+
+ procedure tcg68k.a_loadaddr_ref_cgpara(list : TAsmList;const r : treference;const cgpara : tcgpara);
+ var
+ tmpreg : tregister;
+ opsize : topsize;
+ begin
+{$ifdef DEBUG_CHARLIE}
+// writeln('a_loadaddr_ref');_cgpara
+{$endif DEBUG_CHARLIE}
+ with r do
+ begin
+ { i suppose this is not required for m68k (KB) }
+// if (segment<>NR_NO) then
+// cgmessage(cg_e_cant_use_far_pointer_there);
+ if not use_push(cgpara) then
+ begin
+ cgpara.check_simple_location;
+ opsize:=tcgsize2opsize[OS_ADDR];
+ if (segment=NR_NO) and (base=NR_NO) and (index=NR_NO) then
+ begin
+ if assigned(symbol) then
+// list.concat(Taicpu.Op_sym_ofs(A_PUSH,opsize,symbol,offset))
+ else;
+// list.concat(Taicpu.Op_const(A_PUSH,opsize,offset));
+ end
+ else if (segment=NR_NO) and (base=NR_NO) and (index<>NR_NO) and
+ (offset=0) and (scalefactor=0) and (symbol=nil) then
+// list.concat(Taicpu.Op_reg(A_PUSH,opsize,index))
+ else if (segment=NR_NO) and (base<>NR_NO) and (index=NR_NO) and
+ (offset=0) and (symbol=nil) then
+// list.concat(Taicpu.Op_reg(A_PUSH,opsize,base))
+ else
+ begin
+ tmpreg:=getaddressregister(list);
+ a_loadaddr_ref_reg(list,r,tmpreg);
+// list.concat(taicpu.op_reg(A_PUSH,opsize,tmpreg));
+ end;
+ end
+ else
+ inherited a_loadaddr_ref_cgpara(list,r,cgpara);
+ end;
+ end;
+
+
+
+ function tcg68k.fixref(list: TAsmList; var ref: treference): boolean;
+
+ begin
+ result:=false;
+ { The Coldfire and MC68020+ have extended
+ addressing capabilities with a 32-bit
+ displacement.
+ }
+ if (current_settings.cputype<>cpu_MC68000) then
+ exit;
+ if (ref.base<>NR_NO) then
+ begin
+ if (ref.index <> NR_NO) and assigned(ref.symbol) then
+ internalerror(20020814);
+ { base + reg }
+ if ref.index <> NR_NO then
+ begin
+ { base + reg + offset }
+ if (ref.offset < low(shortint)) or (ref.offset > high(shortint)) then
+ begin
+ list.concat(taicpu.op_const_reg(A_ADD,S_L,ref.offset,ref.base));
+ fixref := true;
+ ref.offset := 0;
+ exit;
+ end;
+ end
+ else
+ { base + offset }
+ if (ref.offset < low(smallint)) or (ref.offset > high(smallint)) then
+ begin
+ list.concat(taicpu.op_const_reg(A_ADD,S_L,ref.offset,ref.base));
+ fixref := true;
+ ref.offset := 0;
+ exit;
+ end;
+ end;
+ end;
+
+
+
+ procedure tcg68k.a_call_name(list : TAsmList;const s : string; weak: boolean);
+ var
+ sym: tasmsymbol;
+ begin
+ if not(weak) then
+ sym:=current_asmdata.RefAsmSymbol(s)
+ else
+ sym:=current_asmdata.WeakRefAsmSymbol(s);
+
+ list.concat(taicpu.op_sym(A_JSR,S_NO,current_asmdata.RefAsmSymbol(s)));
+ end;
+
+
+ procedure tcg68k.a_call_reg(list : TAsmList;reg: tregister);
+ var
+ tmpref : treference;
+ tmpreg : tregister;
+ begin
+{$ifdef DEBUG_CHARLIE}
+ list.concat(tai_comment.create(strpnew('a_call_reg')));
+{$endif}
+ if isaddressregister(reg) then
+ begin
+ { if we have an address register, we can jump to the address directly }
+ reference_reset_base(tmpref,reg,0,4);
+ end
+ else
+ begin
+ { if we have a data register, we need to move it to an address register first }
+ tmpreg:=getaddressregister(list);
+ reference_reset_base(tmpref,tmpreg,0,4);
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg,tmpreg));
+ end;
+ list.concat(taicpu.op_ref(A_JSR,S_NO,tmpref));
+ end;
+
+
+
+ procedure tcg68k.a_load_const_reg(list : TAsmList;size : tcgsize;a : tcgint;register : tregister);
+ begin
+{$ifdef DEBUG_CHARLIE}
+// writeln('a_load_const_reg');
+{$endif DEBUG_CHARLIE}
+
+ if isaddressregister(register) then
+ begin
+ list.concat(taicpu.op_const_reg(A_MOVE,S_L,longint(a),register))
+ end
+ else
+ if a = 0 then
+ list.concat(taicpu.op_reg(A_CLR,S_L,register))
+ else
+ begin
+ if (longint(a) >= low(shortint)) and (longint(a) <= high(shortint)) then
+ list.concat(taicpu.op_const_reg(A_MOVEQ,S_L,longint(a),register))
+ else
+ list.concat(taicpu.op_const_reg(A_MOVE,S_L,longint(a),register))
+ end;
+ end;
+
+ procedure tcg68k.a_load_const_ref(list : TAsmList; tosize: tcgsize; a : tcgint;const ref : treference);
+ begin
+{$ifdef DEBUG_CHARLIE}
+ list.concat(tai_comment.create(strpnew('a_load_const_ref')));
+{$endif DEBUG_CHARLIE}
+
+ list.concat(taicpu.op_const_ref(A_MOVE,S_L,longint(a),ref));
+ end;
+
+
+ procedure tcg68k.a_load_reg_ref(list : TAsmList;fromsize,tosize : tcgsize;register : tregister;const ref : treference);
+ var
+ href : treference;
+ begin
+ href := ref;
+ fixref(list,href);
+{$ifdef DEBUG_CHARLIE}
+ list.concat(tai_comment.create(strpnew('a_load_reg_ref')));
+{$endif DEBUG_CHARLIE}
+ { move to destination reference }
+ list.concat(taicpu.op_reg_ref(A_MOVE,TCGSize2OpSize[fromsize],register,href));
+ end;
+
+
+ procedure tcg68k.a_load_ref_ref(list : TAsmList;fromsize,tosize : tcgsize;const sref : treference;const dref : treference);
+ var
+ aref: treference;
+ bref: treference;
+ begin
+ aref := sref;
+ bref := dref;
+ fixref(list,aref);
+ fixref(list,bref);
+{$ifdef DEBUG_CHARLIE}
+// writeln('a_load_ref_ref');
+{$endif DEBUG_CHARLIE}
+ list.concat(taicpu.op_ref_ref(A_MOVE,TCGSize2OpSize[fromsize],aref,bref));
+ end;
+
+
+ procedure tcg68k.a_load_reg_reg(list : TAsmList;fromsize,tosize : tcgsize;reg1,reg2 : tregister);
+ begin
+ { move to destination register }
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg1,reg2));
+ { zero/sign extend register to 32-bit }
+ sign_extend(list, fromsize, reg2);
+ end;
+
+
+ procedure tcg68k.a_load_ref_reg(list : TAsmList;fromsize,tosize : tcgsize;const ref : treference;register : tregister);
+ var
+ href : treference;
+ begin
+ href := ref;
+ fixref(list,href);
+ list.concat(taicpu.op_ref_reg(A_MOVE,TCGSize2OpSize[fromsize],href,register));
+ { extend the value in the register }
+ sign_extend(list, tosize, register);
+ end;
+
+
+ procedure tcg68k.a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);
+ var
+ href : treference;
+// p: pointer;
+ begin
+ { TODO: FIX ME!!! take a look on this mess again...}
+// if getregtype(r)=R_ADDRESSREGISTER then
+// begin
+// writeln('address reg?!?');
+// p:=nil; dword(p^):=0; {DEBUG CODE... :D )
+// internalerror(2002072901);
+// end;
+ href:=ref;
+ fixref(list, href);
+ list.concat(taicpu.op_ref_reg(A_LEA,S_L,href,r));
+ end;
+
+
+ procedure tcg68k.a_loadfpu_reg_reg(list: TAsmList; fromsize, tosize: tcgsize; reg1, reg2: tregister);
+ begin
+ { in emulation mode, only 32-bit single is supported }
+ if cs_fp_emulation in current_settings.moduleswitches then
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg1,reg2))
+ else
+ list.concat(taicpu.op_reg_reg(A_FMOVE,tcgsize2opsize[tosize],reg1,reg2));
+ end;
+
+
+ procedure tcg68k.a_loadfpu_ref_reg(list: TAsmList; fromsize, tosize: tcgsize; const ref: treference; reg: tregister);
+ var
+ opsize : topsize;
+ href : treference;
+ tmpreg : tregister;
+ begin
+ opsize := tcgsize2opsize[fromsize];
+ { extended is not supported, since it is not available on Coldfire }
+ if opsize = S_FX then
+ internalerror(20020729);
+ href := ref;
+ fixref(list,href);
+ { in emulation mode, only 32-bit single is supported }
+ if cs_fp_emulation in current_settings.moduleswitches then
+ list.concat(taicpu.op_ref_reg(A_MOVE,S_L,href,reg))
+ else
+ begin
+ list.concat(taicpu.op_ref_reg(A_FMOVE,opsize,href,reg));
+ if (tosize < fromsize) then
+ a_loadfpu_reg_reg(list,fromsize,tosize,reg,reg);
+ end;
+ end;
+
+ procedure tcg68k.a_loadfpu_reg_ref(list: TAsmList; fromsize,tosize: tcgsize; reg: tregister; const ref: treference);
+ var
+ opsize : topsize;
+ begin
+ opsize := tcgsize2opsize[tosize];
+ { extended is not supported, since it is not available on Coldfire }
+ if opsize = S_FX then
+ internalerror(20020729);
+ { in emulation mode, only 32-bit single is supported }
+ if cs_fp_emulation in current_settings.moduleswitches then
+ list.concat(taicpu.op_reg_ref(A_MOVE,S_L,reg, ref))
+ else
+ list.concat(taicpu.op_reg_ref(A_FMOVE,opsize,reg, ref));
+ end;
+
+
+ procedure tcg68k.a_loadmm_reg_reg(list: TAsmList;fromsize,tosize : tcgsize; reg1, reg2: tregister;shuffle : pmmshuffle);
+ begin
+ internalerror(20020729);
+ end;
+
+
+ procedure tcg68k.a_loadmm_ref_reg(list: TAsmList;fromsize,tosize : tcgsize; const ref: treference; reg: tregister;shuffle : pmmshuffle);
+ begin
+ internalerror(20020729);
+ end;
+
+
+ procedure tcg68k.a_loadmm_reg_ref(list: TAsmList;fromsize,tosize : tcgsize; reg: tregister; const ref: treference;shuffle : pmmshuffle);
+ begin
+ internalerror(20020729);
+ end;
+
+
+ procedure tcg68k.a_loadmm_reg_cgpara(list: TAsmList; size: tcgsize; reg: tregister;const locpara : TCGPara;shuffle : pmmshuffle);
+ begin
+ internalerror(20020729);
+ end;
+
+
+ procedure tcg68k.a_op_const_reg(list : TAsmList; Op: TOpCG; size: tcgsize; a: tcgint; reg: TRegister);
+ var
+ scratch_reg : tregister;
+ scratch_reg2: tregister;
+ opcode : tasmop;
+ r,r2 : Tregister;
+ begin
+ optimize_op_const(op, a);
+ opcode := topcg2tasmop[op];
+ case op of
+ OP_NONE :
+ begin
+ { Opcode is optimized away }
+ end;
+ OP_MOVE :
+ begin
+ { Optimized, replaced with a simple load }
+ a_load_const_reg(list,size,a,reg);
+ end;
+ OP_ADD :
+ begin
+ if (a >= 1) and (a <= 8) then
+ list.concat(taicpu.op_const_reg(A_ADDQ,S_L,a, reg))
+ else
+ begin
+ { all others, including coldfire }
+ list.concat(taicpu.op_const_reg(A_ADD,S_L,a, reg));
+ end;
+ end;
+ OP_AND,
+ OP_OR:
+ begin
+ list.concat(taicpu.op_const_reg(topcg2tasmop[op],S_L,longint(a), reg));
+ end;
+ OP_DIV :
+ begin
+ internalerror(20020816);
+ end;
+ OP_IDIV :
+ begin
+ internalerror(20020816);
+ end;
+ OP_IMUL :
+ begin
+ if current_settings.cputype = cpu_MC68000 then
+ begin
+ r:=NR_D0;
+ r2:=NR_D1;
+ cg.getcpuregister(list,NR_D0);
+ cg.getcpuregister(list,NR_D1);
+ list.concat(taicpu.op_const_reg(A_MOVE,S_L,a, r));
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg, r2));
+ cg.a_call_name(list,'FPC_MUL_LONGINT',false);
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,r, reg));
+ cg.ungetcpuregister(list,r);
+ cg.ungetcpuregister(list,r2);
+
+ end
+ else
+ begin
+ if (isaddressregister(reg)) then
+ begin
+ scratch_reg := getintregister(list,OS_INT);
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg, scratch_reg));
+ list.concat(taicpu.op_const_reg(A_MULS,S_L,a,scratch_reg));
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,scratch_reg,reg));
+ end
+ else
+ list.concat(taicpu.op_const_reg(A_MULS,S_L,a,reg));
+ end;
+ end;
+ OP_MUL :
+ begin
+ if current_settings.cputype = cpu_MC68000 then
+ begin
+ r:=NR_D0;
+ r2:=NR_D1;
+ cg.getcpuregister(list,NR_D0);
+ cg.getcpuregister(list,NR_D1);
+ list.concat(taicpu.op_const_reg(A_MOVE,S_L,a, r));
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg, r2));
+ cg.a_call_name(list,'FPC_MUL_LONGWORD',false);
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,r, reg));
+ cg.ungetcpuregister(list,r);
+ cg.ungetcpuregister(list,r2);
+ end
+ else
+ begin
+ if (isaddressregister(reg)) then
+ begin
+ scratch_reg := getintregister(list,OS_INT);
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg, scratch_reg));
+ list.concat(taicpu.op_const_reg(A_MULU,S_L,a,scratch_reg));
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,scratch_reg,reg));
+ end
+ else
+ list.concat(taicpu.op_const_reg(A_MULU,S_L,a,reg));
+ end;
+ end;
+ OP_SAR,
+ OP_SHL,
+ OP_SHR :
+ begin
+ if (a >= 1) and (a <= 8) then
+ begin
+ { now allowed to shift an address register }
+ if (isaddressregister(reg)) then
+ begin
+ scratch_reg := getintregister(list,OS_INT);
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg, scratch_reg));
+ list.concat(taicpu.op_const_reg(opcode,S_L,a, scratch_reg));
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,scratch_reg,reg));
+ end
+ else
+ list.concat(taicpu.op_const_reg(opcode,S_L,a, reg));
+ end
+ else
+ begin
+ { we must load the data into a register ... :() }
+ scratch_reg := cg.getintregister(list,OS_INT);
+ list.concat(taicpu.op_const_reg(A_MOVE,S_L,a, scratch_reg));
+ { again... since shifting with address register is not allowed }
+ if (isaddressregister(reg)) then
+ begin
+ scratch_reg2 := cg.getintregister(list,OS_INT);
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg, scratch_reg2));
+ list.concat(taicpu.op_reg_reg(opcode,S_L,scratch_reg, scratch_reg2));
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,scratch_reg2,reg));
+ end
+ else
+ list.concat(taicpu.op_reg_reg(opcode,S_L,scratch_reg, reg));
+ end;
+ end;
+ OP_SUB :
+ begin
+ if (a >= 1) and (a <= 8) then
+ list.concat(taicpu.op_const_reg(A_SUBQ,S_L,a,reg))
+ else
+ begin
+ { all others, including coldfire }
+ list.concat(taicpu.op_const_reg(A_SUB,S_L,a, reg));
+ end;
+ end;
+ OP_XOR :
+ begin
+ list.concat(taicpu.op_const_reg(A_EORI,S_L,a, reg));
+ end;
+ else
+ internalerror(20020729);
+ end;
+ end;
+
+{
+ procedure tcg68k.a_op_const_ref(list : TAsmList; Op: TOpCG; size: TCGSize; a: tcgint; const ref: TReference);
+ var
+ opcode: tasmop;
+ begin
+ writeln('a_op_const_ref');
+
+ optimize_op_const(op, a);
+ opcode := topcg2tasmop[op];
+ case op of
+ OP_NONE :
+ begin
+ { opcode was optimized away }
+ end;
+ OP_MOVE :
+ begin
+ { Optimized, replaced with a simple load }
+ a_load_const_ref(list,size,a,ref);
+ end;
+ else
+ begin
+ internalerror(2007010101);
+ end;
+ end;
+ end;
+}
+
+ procedure tcg68k.a_op_reg_reg(list : TAsmList; Op: TOpCG; size: TCGSize; reg1, reg2: TRegister);
+ var
+ hreg1,hreg2,r,r2: tregister;
+ begin
+ case op of
+ OP_ADD :
+ begin
+ if current_settings.cputype = cpu_ColdFire then
+ begin
+ { operation only allowed only a longword }
+ sign_extend(list, size, reg1);
+ sign_extend(list, size, reg2);
+ list.concat(taicpu.op_reg_reg(A_ADD,S_L,reg1, reg2));
+ end
+ else
+ begin
+ list.concat(taicpu.op_reg_reg(A_ADD,TCGSize2OpSize[size],reg1, reg2));
+ end;
+ end;
+ OP_AND,OP_OR,
+ OP_SAR,OP_SHL,
+ OP_SHR,OP_SUB,OP_XOR :
+ begin
+ { load to data registers }
+ if (isaddressregister(reg1)) then
+ begin
+ hreg1 := getintregister(list,OS_INT);
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg1,hreg1));
+ end
+ else
+ hreg1 := reg1;
+
+ if (isaddressregister(reg2)) then
+ begin
+ hreg2:= getintregister(list,OS_INT);
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg2,hreg2));
+ end
+ else
+ hreg2 := reg2;
+
+ if current_settings.cputype = cpu_ColdFire then
+ begin
+ { operation only allowed only a longword }
+ {!***************************************
+ in the case of shifts, the value to
+ shift by, should already be valid, so
+ no need to sign extend the value
+ !
+ }
+ if op in [OP_AND,OP_OR,OP_SUB,OP_XOR] then
+ sign_extend(list, size, hreg1);
+ sign_extend(list, size, hreg2);
+ list.concat(taicpu.op_reg_reg(topcg2tasmop[op],S_L,hreg1, hreg2));
+ end
+ else
+ begin
+ list.concat(taicpu.op_reg_reg(topcg2tasmop[op],TCGSize2OpSize[size],hreg1, hreg2));
+ end;
+
+ { move back result into destination register }
+ if reg2 <> hreg2 then
+ begin
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,hreg2,reg2));
+ end;
+ end;
+ OP_DIV :
+ begin
+ internalerror(20020816);
+ end;
+ OP_IDIV :
+ begin
+ internalerror(20020816);
+ end;
+ OP_IMUL :
+ begin
+ sign_extend(list, size,reg1);
+ sign_extend(list, size,reg2);
+ if current_settings.cputype = cpu_MC68000 then
+ begin
+ r:=NR_D0;
+ r2:=NR_D1;
+ cg.getcpuregister(list,NR_D0);
+ cg.getcpuregister(list,NR_D1);
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg1, r));
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg2, r2));
+ cg.a_call_name(list,'FPC_MUL_LONGINT',false);
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,r, reg2));
+ cg.ungetcpuregister(list,r);
+ cg.ungetcpuregister(list,r2);
+ end
+ else
+ begin
+// writeln('doing 68020');
+
+ if (isaddressregister(reg1)) then
+ hreg1 := getintregister(list,OS_INT)
+ else
+ hreg1 := reg1;
+ if (isaddressregister(reg2)) then
+ hreg2:= getintregister(list,OS_INT)
+ else
+ hreg2 := reg2;
+
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg1,hreg1));
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg2,hreg2));
+
+ list.concat(taicpu.op_reg_reg(A_MULS,S_L,reg1,reg2));
+
+ { move back result into destination register }
+
+ if reg2 <> hreg2 then
+ begin
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,hreg2,reg2));
+ end;
+ end;
+ end;
+ OP_MUL :
+ begin
+ sign_extend(list, size,reg1);
+ sign_extend(list, size,reg2);
+ if current_settings.cputype = cpu_MC68000 then
+ begin
+ r:=NR_D0;
+ r2:=NR_D1;
+ cg.getcpuregister(list,NR_D0);
+ cg.getcpuregister(list,NR_D1);
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg1, r));
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg2, r2));
+ cg.a_call_name(list,'FPC_MUL_LONGWORD',false);
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,r, reg2));
+ cg.ungetcpuregister(list,r);
+ cg.ungetcpuregister(list,r2);
+ end
+ else
+ begin
+ if (isaddressregister(reg1)) then
+ begin
+ hreg1 := cg.getintregister(list,OS_INT);
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg1,hreg1));
+ end
+ else
+ hreg1 := reg1;
+
+ if (isaddressregister(reg2)) then
+ begin
+ hreg2:= cg.getintregister(list,OS_INT);
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg2,hreg2));
+ end
+ else
+ hreg2 := reg2;
+
+ list.concat(taicpu.op_reg_reg(A_MULU,S_L,reg1,reg2));
+
+ { move back result into destination register }
+ if reg2<>hreg2 then
+ begin
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,hreg2,reg2));
+ end;
+ end;
+ end;
+ OP_NEG,
+ OP_NOT :
+ Begin
+ { if there are two operands, move the register,
+ since the operation will only be done on the result
+ register.
+ }
+ if reg1 <> NR_NO then
+ cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_INT,OS_INT,reg1,reg2);
+
+ if (isaddressregister(reg2)) then
+ begin
+ hreg2 := getintregister(list,OS_INT);
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg2,hreg2));
+ end
+ else
+ hreg2 := reg2;
+
+ { coldfire only supports long version }
+ if current_settings.cputype = cpu_ColdFire then
+ begin
+ sign_extend(list, size,hreg2);
+ list.concat(taicpu.op_reg(topcg2tasmop[op],S_L,hreg2));
+ end
+ else
+ begin
+ list.concat(taicpu.op_reg(topcg2tasmop[op],TCGSize2OpSize[size],hreg2));
+ end;
+
+ if reg2 <> hreg2 then
+ begin
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,hreg2,reg2));
+ end;
+
+ end;
+ else
+ internalerror(20020729);
+ end;
+ end;
+
+
+
+ procedure tcg68k.a_cmp_const_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;a : tcgint;reg : tregister;
+ l : tasmlabel);
+ var
+ hregister : tregister;
+ begin
+ if a = 0 then
+ begin
+ list.concat(taicpu.op_reg(A_TST,TCGSize2OpSize[size],reg));
+ end
+ else
+ begin
+ if (current_settings.cputype = cpu_ColdFire) then
+ begin
+ {
+ only longword comparison is supported,
+ and only on data registers.
+ }
+ hregister := getintregister(list,OS_INT);
+ { always move to a data register }
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg,hregister));
+ { sign/zero extend the register }
+ sign_extend(list, size,hregister);
+ list.concat(taicpu.op_const_reg(A_CMPI,S_L,a,hregister));
+ end
+ else
+ begin
+ list.concat(taicpu.op_const_reg(A_CMPI,TCGSize2OpSize[size],a,reg));
+ end;
+ end;
+ { emit the actual jump to the label }
+ a_jmp_cond(list,cmp_op,l);
+ end;
+
+ procedure tcg68k.a_cmp_reg_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel);
+ begin
+ list.concat(taicpu.op_reg_reg(A_CMP,tcgsize2opsize[size],reg1,reg2));
+ { emit the actual jump to the label }
+ a_jmp_cond(list,cmp_op,l);
+ end;
+
+ procedure tcg68k.a_jmp_always(list : TAsmList;l: tasmlabel);
+ var
+ ai: taicpu;
+ begin
+ ai := Taicpu.op_sym(A_JMP,S_NO,l);
+ ai.is_jmp := true;
+ list.concat(ai);
+ end;
+
+ procedure tcg68k.a_jmp_flags(list : TAsmList;const f : TResFlags;l: tasmlabel);
+ var
+ ai : taicpu;
+ begin
+ ai := Taicpu.op_sym(A_BXX,S_NO,l);
+ ai.SetCondition(flags_to_cond(f));
+ ai.is_jmp := true;
+ list.concat(ai);
+ end;
+
+ procedure tcg68k.g_flags2reg(list: TAsmList; size: TCgSize; const f: tresflags; reg: TRegister);
+ var
+ ai : taicpu;
+ hreg : tregister;
+ begin
+ { move to a Dx register? }
+ if (isaddressregister(reg)) then
+ begin
+ hreg := getintregister(list,OS_INT);
+ a_load_const_reg(list,size,0,hreg);
+ ai:=Taicpu.Op_reg(A_Sxx,S_B,hreg);
+ ai.SetCondition(flags_to_cond(f));
+ list.concat(ai);
+
+ if (current_settings.cputype = cpu_ColdFire) then
+ begin
+ { neg.b does not exist on the Coldfire
+ so we need to sign extend the value
+ before doing a neg.l
+ }
+ list.concat(taicpu.op_reg(A_EXTB,S_L,hreg));
+ list.concat(taicpu.op_reg(A_NEG,S_L,hreg));
+ end
+ else
+ begin
+ list.concat(taicpu.op_reg(A_NEG,S_B,hreg));
+ end;
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,hreg,reg));
+ end
+ else
+ begin
+ a_load_const_reg(list,size,0,reg);
+ ai:=Taicpu.Op_reg(A_Sxx,S_B,reg);
+ ai.SetCondition(flags_to_cond(f));
+ list.concat(ai);
+
+ if (current_settings.cputype = cpu_ColdFire) then
+ begin
+ { neg.b does not exist on the Coldfire
+ so we need to sign extend the value
+ before doing a neg.l
+ }
+ list.concat(taicpu.op_reg(A_EXTB,S_L,reg));
+ list.concat(taicpu.op_reg(A_NEG,S_L,reg));
+ end
+ else
+ begin
+ list.concat(taicpu.op_reg(A_NEG,S_B,reg));
+ end;
+ end;
+ end;
+
+
+
+ procedure tcg68k.g_concatcopy(list : TAsmList;const source,dest : treference;len : tcgint);
+
+ var
+ helpsize : longint;
+ i : byte;
+ reg8,reg32 : tregister;
+ swap : boolean;
+ hregister : tregister;
+ iregister : tregister;
+ jregister : tregister;
+ hp1 : treference;
+ hp2 : treference;
+ hl : tasmlabel;
+ hl2: tasmlabel;
+ popaddress : boolean;
+ srcref,dstref : treference;
+
+ begin
+ popaddress := false;
+
+// writeln('concatcopy:',len);
+
+ { this should never occur }
+ if len > 65535 then
+ internalerror(0);
+
+ hregister := getintregister(list,OS_INT);
+// if delsource then
+// reference_release(list,source);
+
+ { from 12 bytes movs is being used }
+ if {(not loadref) and} ((len<=8) or (not(cs_opt_size in current_settings.optimizerswitches) and (len<=12))) then
+ begin
+ srcref := source;
+ dstref := dest;
+ helpsize:=len div 4;
+ { move a dword x times }
+ for i:=1 to helpsize do
+ begin
+ a_load_ref_reg(list,OS_INT,OS_INT,srcref,hregister);
+ a_load_reg_ref(list,OS_INT,OS_INT,hregister,dstref);
+ inc(srcref.offset,4);
+ inc(dstref.offset,4);
+ dec(len,4);
+ end;
+ { move a word }
+ if len>1 then
+ begin
+ a_load_ref_reg(list,OS_16,OS_16,srcref,hregister);
+ a_load_reg_ref(list,OS_16,OS_16,hregister,dstref);
+ inc(srcref.offset,2);
+ inc(dstref.offset,2);
+ dec(len,2);
+ end;
+ { move a single byte }
+ if len>0 then
+ begin
+ a_load_ref_reg(list,OS_8,OS_8,srcref,hregister);
+ a_load_reg_ref(list,OS_8,OS_8,hregister,dstref);
+ end
+ end
+ else
+ begin
+ iregister:=getaddressregister(list);
+ jregister:=getaddressregister(list);
+ { reference for move (An)+,(An)+ }
+ reference_reset(hp1,source.alignment);
+ hp1.base := iregister; { source register }
+ hp1.direction := dir_inc;
+ reference_reset(hp2,dest.alignment);
+ hp2.base := jregister;
+ hp2.direction := dir_inc;
+ { iregister = source }
+ { jregister = destination }
+
+{ if loadref then
+ cg.a_load_ref_reg(list,OS_INT,OS_INT,source,iregister)
+ else}
+ a_loadaddr_ref_reg(list,source,iregister);
+
+ a_loadaddr_ref_reg(list,dest,jregister);
+
+ { double word move only on 68020+ machines }
+ { because of possible alignment problems }
+ { use fast loop mode }
+ if (current_settings.cputype=cpu_MC68020) then
+ begin
+ helpsize := len - len mod 4;
+ len := len mod 4;
+ list.concat(taicpu.op_const_reg(A_MOVE,S_L,helpsize div 4,hregister));
+ current_asmdata.getjumplabel(hl2);
+ a_jmp_always(list,hl2);
+ current_asmdata.getjumplabel(hl);
+ a_label(list,hl);
+ list.concat(taicpu.op_ref_ref(A_MOVE,S_L,hp1,hp2));
+ a_label(list,hl2);
+ list.concat(taicpu.op_reg_sym(A_DBRA,S_L,hregister,hl));
+ if len > 1 then
+ begin
+ dec(len,2);
+ list.concat(taicpu.op_ref_ref(A_MOVE,S_W,hp1,hp2));
+ end;
+ if len = 1 then
+ list.concat(taicpu.op_ref_ref(A_MOVE,S_B,hp1,hp2));
+ end
+ else
+ begin
+ { Fast 68010 loop mode with no possible alignment problems }
+ helpsize := len;
+ list.concat(taicpu.op_const_reg(A_MOVE,S_L,helpsize,hregister));
+ current_asmdata.getjumplabel(hl2);
+ a_jmp_always(list,hl2);
+ current_asmdata.getjumplabel(hl);
+ a_label(list,hl);
+ list.concat(taicpu.op_ref_ref(A_MOVE,S_B,hp1,hp2));
+ a_label(list,hl2);
+ list.concat(taicpu.op_reg_sym(A_DBRA,S_L,hregister,hl));
+ end;
+
+ { restore the registers that we have just used olny if they are used! }
+ if jregister = NR_A1 then
+ hp2.base := NR_NO;
+ if iregister = NR_A0 then
+ hp1.base := NR_NO;
+// reference_release(list,hp1);
+// reference_release(list,hp2);
+ end;
+
+// if delsource then
+// tg.ungetiftemp(list,source);
+ end;
+
+ procedure tcg68k.g_overflowcheck(list: TAsmList; const l:tlocation; def:tdef);
+ begin
+ end;
+
+ procedure tcg68k.g_copyvaluepara_openarray(list : TAsmList;const ref:treference;const lenloc:tlocation;elesize:tcgint;destreg:tregister);
+ begin
+ end;
+
+
+ procedure tcg68k.g_proc_entry(list: TAsmList; localsize: longint; nostackframe:boolean);
+ var
+ r,rsp: TRegister;
+ ref : TReference;
+ begin
+{$ifdef DEBUG_CHARLIE}
+// writeln('proc entry, localsize:',localsize);
+{$endif DEBUG_CHARLIE}
+
+ if not nostackframe then
+ begin
+ if localsize<>0 then
+ begin
+ { size can't be negative }
+ if (localsize < 0) then
+ internalerror(2006122601);
+
+ { Not to complicate the code generator too much, and since some }
+ { of the systems only support this format, the localsize cannot }
+ { exceed 32K in size. }
+ if (localsize > high(smallint)) then
+ CGMessage(cg_e_localsize_too_big);
+
+ list.concat(taicpu.op_reg_const(A_LINK,S_W,NR_FRAME_POINTER_REG,-localsize));
+ end
+ else
+ begin
+ list.concat(taicpu.op_reg_const(A_LINK,S_W,NR_FRAME_POINTER_REG,0));
+(*
+ { FIXME! - Carl's original code uses this method. However,
+ according to the 68060 users manual, a LINK is faster than
+ two moves. So, use a link in #0 case too, for now. I'm not
+ really sure tho', that LINK supports #0 disposition, but i
+ see no reason why it shouldn't support it. (KB) }
+
+ { when localsize = 0, use two moves, instead of link }
+ r:=NR_FRAME_POINTER_REG;
+ rsp:=NR_STACK_POINTER_REG;
+
+ reference_reset_base(ref,NR_STACK_POINTER_REG,0);
+ ref.direction:=dir_dec;
+ list.concat(taicpu.op_reg_ref(A_MOVE,S_L,r,ref));
+ list.concat(taicpu.op_reg_reg(A_MOVE,S_L,rsp,r));
+ *)
+ end;
+ end;
+ end;
+
+{ procedure tcg68k.g_restore_frame_pointer(list : TAsmList);
+ var
+ r:Tregister;
+ begin
+ r:=NR_FRAME_POINTER_REG;
+ list.concat(taicpu.op_reg(A_UNLK,S_NO,r));
+ end;
+}
+
+ procedure tcg68k.g_proc_exit(list : TAsmList; parasize: longint; nostackframe: boolean);
+ var
+// r,hregister : TRegister;
+ localsize: tcgint;
+ spr : TRegister;
+ fpr : TRegister;
+ ref : TReference;
+ begin
+ if not nostackframe then
+ begin
+ localsize := current_procinfo.calc_stackframe_size;
+{$ifdef DEBUG_CHARLIE}
+// writeln('proc exit with stackframe, size:',localsize,' parasize:',parasize);
+{$endif DEBUG_CHARLIE}
+ list.concat(taicpu.op_reg(A_UNLK,S_NO,NR_FRAME_POINTER_REG));
+ parasize := parasize - target_info.first_parm_offset; { i'm still not 100% confident that this is
+ correct here, but at least it looks less
+ hacky, and makes some sense (KB) }
+ if (parasize<>0) then
+ begin
+ { only 68020+ supports RTD, so this needs another code path
+ for 68000 and Coldfire (KB) }
+{ TODO: 68020+ only code generation, without fallback}
+ list.concat(taicpu.op_const(A_RTD,S_NO,parasize));
+ end
+ else
+ list.concat(taicpu.op_none(A_RTS,S_NO));
+ end
+ else
+ begin
+{$ifdef DEBUG_CHARLIE}
+// writeln('proc exit, no stackframe');
+{$endif DEBUG_CHARLIE}
+ list.concat(taicpu.op_none(A_RTS,S_NO));
+ end;
+
+// writeln('g_proc_exit');
+ { Routines with the poclearstack flag set use only a ret.
+ also routines with parasize=0 }
+ (*
+ if current_procinfo.procdef.proccalloption in clearstack_pocalls then
+ begin
+ { complex return values are removed from stack in C code PM }
+ if paramanager.ret_in_param(current_procinfo.procdef.returndef,current_procinfo.procdef.proccalloption) then
+ list.concat(taicpu.op_const(A_RTD,S_NO,4))
+ else
+ list.concat(taicpu.op_none(A_RTS,S_NO));
+ end
+ else if (parasize=0) then
+ begin
+ list.concat(taicpu.op_none(A_RTS,S_NO));
+ end
+ else
+ begin
+ { return with immediate size possible here
+ signed!
+ RTD is not supported on the coldfire }
+ if (current_settings.cputype=cpu_MC68020) and (parasize<$7FFF) then
+ list.concat(taicpu.op_const(A_RTD,S_NO,parasize))
+ { manually restore the stack }
+ else
+ begin
+ { We must pull the PC Counter from the stack, before }
+ { restoring the stack pointer, otherwise the PC would }
+ { point to nowhere! }
+
+ { save the PC counter (pop it from the stack) }
+ hregister:=NR_A3;
+ cg.a_reg_alloc(list,hregister);
+ reference_reset_base(ref,NR_STACK_POINTER_REG,0);
+ ref.direction:=dir_inc;
+ list.concat(taicpu.op_ref_reg(A_MOVE,S_L,ref,hregister));
+ { can we do a quick addition ... }
+ r:=NR_SP;
+ if (parasize > 0) and (parasize < 9) then
+ list.concat(taicpu.op_const_reg(A_ADDQ,S_L,parasize,r))
+ else { nope ... }
+ list.concat(taicpu.op_const_reg(A_ADD,S_L,parasize,r));
+
+ { restore the PC counter (push it on the stack) }
+ reference_reset_base(ref,NR_STACK_POINTER_REG,0);
+ ref.direction:=dir_dec;
+ cg.a_reg_alloc(list,hregister);
+ list.concat(taicpu.op_reg_ref(A_MOVE,S_L,hregister,ref));
+ list.concat(taicpu.op_none(A_RTS,S_NO));
+ end;
+ end;
+ *)
+ end;
+
+
+ procedure Tcg68k.g_save_registers(list:TAsmList);
+ var
+ tosave : tcpuregisterset;
+ ref : treference;
+ begin
+ {!!!!!
+ tosave:=std_saved_registers;
+ { only save the registers which are not used and must be saved }
+ tosave:=tosave*(rg[R_INTREGISTER].used_in_proc+rg[R_ADDRESSREGISTER].used_in_proc);
+ reference_reset_base(ref,NR_STACK_POINTER_REG,0);
+ ref.direction:=dir_dec;
+ if tosave<>[] then
+ list.concat(taicpu.op_regset_ref(A_MOVEM,S_L,tosave,ref));
+ }
+ end;
+
+
+ procedure Tcg68k.g_restore_registers(list:TAsmList);
+ var
+ torestore : tcpuregisterset;
+ r:Tregister;
+ ref : treference;
+ begin
+ {!!!!!!!!
+ torestore:=std_saved_registers;
+ { should be intersected with used regs, no ? }
+ torestore:=torestore*(rg[R_INTREGISTER].used_in_proc+rg[R_ADDRESSREGISTER].used_in_proc);
+ reference_reset_base(ref,NR_STACK_POINTER_REG,0);
+ ref.direction:=dir_inc;
+ if torestore<>[] then
+ list.concat(taicpu.op_ref_regset(A_MOVEM,S_L,ref,torestore));
+ }
+ end;
+
+{
+ procedure tcg68k.g_save_all_registers(list : TAsmList);
+ begin
+ end;
+
+ procedure tcg68k.g_restore_all_registers(list : TAsmList;const funcretparaloc:TCGPara);
+ begin
+ end;
+}
+ procedure tcg68k.sign_extend(list: TAsmList;_oldsize : tcgsize; reg: tregister);
+ begin
+ case _oldsize of
+ { sign extend }
+ OS_S8:
+ begin
+ if (isaddressregister(reg)) then
+ internalerror(20020729);
+ if (current_settings.cputype = cpu_MC68000) then
+ begin
+ list.concat(taicpu.op_reg(A_EXT,S_W,reg));
+ list.concat(taicpu.op_reg(A_EXT,S_L,reg));
+ end
+ else
+ begin
+// list.concat(tai_comment.create(strpnew('sign extend byte')));
+ list.concat(taicpu.op_reg(A_EXTB,S_L,reg));
+ end;
+ end;
+ OS_S16:
+ begin
+ if (isaddressregister(reg)) then
+ internalerror(20020729);
+// list.concat(tai_comment.create(strpnew('sign extend word')));
+ list.concat(taicpu.op_reg(A_EXT,S_L,reg));
+ end;
+ { zero extend }
+ OS_8:
+ begin
+// list.concat(tai_comment.create(strpnew('zero extend byte')));
+ list.concat(taicpu.op_const_reg(A_AND,S_L,$FF,reg));
+ end;
+ OS_16:
+ begin
+// list.concat(tai_comment.create(strpnew('zero extend word')));
+ list.concat(taicpu.op_const_reg(A_AND,S_L,$FFFF,reg));
+ end;
+ end; { otherwise the size is already correct }
+ end;
+
+ procedure tcg68k.a_jmp_cond(list : TAsmList;cond : TOpCmp;l: tasmlabel);
+
+ var
+ ai : taicpu;
+
+ begin
+ if cond=OC_None then
+ ai := Taicpu.Op_sym(A_JMP,S_NO,l)
+ else
+ begin
+ ai:=Taicpu.Op_sym(A_Bxx,S_NO,l);
+ ai.SetCondition(TOpCmp2AsmCond[cond]);
+ end;
+ ai.is_jmp:=true;
+ list.concat(ai);
+ end;
+
+
+ procedure tcg68k.g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);
+{
+ procedure loadvmttor11;
+ var
+ href : treference;
+ begin
+ reference_reset_base(href,NR_R3,0);
+ cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_R11);
+ end;
+
+ procedure op_onr11methodaddr;
+ var
+ href : treference;
+ begin
+ if (procdef.extnumber=$ffff) then
+ Internalerror(200006139);
+ { call/jmp vmtoffs(%eax) ; method offs }
+ reference_reset_base(href,NR_R11,tobjectdef(procdef.struct).vmtmethodoffset(procdef.extnumber));
+ if not((longint(href.offset) >= low(smallint)) and
+ (longint(href.offset) <= high(smallint))) then
+ begin
+ list.concat(taicpu.op_reg_reg_const(A_ADDIS,NR_R11,NR_R11,
+ smallint((href.offset shr 16)+ord(smallint(href.offset and $ffff) < 0))));
+ href.offset := smallint(href.offset and $ffff);
+ end;
+ list.concat(taicpu.op_reg_ref(A_LWZ,NR_R11,href));
+ list.concat(taicpu.op_reg(A_MTCTR,NR_R11));
+ list.concat(taicpu.op_none(A_BCTR));
+ end;
+}
+ var
+ make_global : boolean;
+ begin
+ if not(procdef.proctypeoption in [potype_function,potype_procedure]) then
+ Internalerror(200006137);
+ if not assigned(procdef.struct) or
+ (procdef.procoptions*[po_classmethod, po_staticmethod,
+ po_methodpointer, po_interrupt, po_iocheck]<>[]) then
+ Internalerror(200006138);
+ if procdef.owner.symtabletype<>ObjectSymtable then
+ Internalerror(200109191);
+
+ make_global:=false;
+ if (not current_module.is_unit) or
+ create_smartlink or
+ (procdef.owner.defowner.owner.symtabletype=globalsymtable) then
+ make_global:=true;
+
+ if make_global then
+ List.concat(Tai_symbol.Createname_global(labelname,AT_FUNCTION,0))
+ else
+ List.concat(Tai_symbol.Createname(labelname,AT_FUNCTION,0));
+
+ { set param1 interface to self }
+// g_adjust_self_value(list,procdef,ioffset);
+
+ { case 4 }
+ if (po_virtualmethod in procdef.procoptions) and
+ not is_objectpascal_helper(procdef.struct) then
+ begin
+// loadvmttor11;
+// op_onr11methodaddr;
+ end
+ { case 0 }
+ else
+// list.concat(taicpu.op_sym(A_B,current_asmdata.RefAsmSymbol(procdef.mangledname)));
+
+ List.concat(Tai_symbol_end.Createname(labelname));
+ end;
+
+
+{****************************************************************************}
+{ TCG64F68K }
+{****************************************************************************}
+ procedure tcg64f68k.a_op64_reg_reg(list : TAsmList;op:TOpCG;size: tcgsize; regsrc,regdst : tregister64);
+ var
+ hreg1, hreg2 : tregister;
+ opcode : tasmop;
+ begin
+// writeln('a_op64_reg_reg');
+ opcode := topcg2tasmop[op];
+ case op of
+ OP_ADD :
+ begin
+ { if one of these three registers is an address
+ register, we'll really get into problems!
+ }
+ if isaddressregister(regdst.reglo) or
+ isaddressregister(regdst.reghi) or
+ isaddressregister(regsrc.reghi) then
+ internalerror(20020817);
+ list.concat(taicpu.op_reg_reg(A_ADD,S_L,regsrc.reglo,regdst.reglo));
+ list.concat(taicpu.op_reg_reg(A_ADDX,S_L,regsrc.reghi,regdst.reghi));
+ end;
+ OP_AND,OP_OR :
+ begin
+ { at least one of the registers must be a data register }
+ if (isaddressregister(regdst.reglo) and
+ isaddressregister(regsrc.reglo)) or
+ (isaddressregister(regsrc.reghi) and
+ isaddressregister(regdst.reghi))
+ then
+ internalerror(20020817);
+ cg.a_op_reg_reg(list,op,OS_32,regsrc.reglo,regdst.reglo);
+ cg.a_op_reg_reg(list,op,OS_32,regsrc.reghi,regdst.reghi);
+ end;
+ { this is handled in 1st pass for 32-bit cpu's (helper call) }
+ OP_IDIV,OP_DIV,
+ OP_IMUL,OP_MUL: internalerror(2002081701);
+ { this is also handled in 1st pass for 32-bit cpu's (helper call) }
+ OP_SAR,OP_SHL,OP_SHR: internalerror(2002081702);
+ OP_SUB:
+ begin
+ { if one of these three registers is an address
+ register, we'll really get into problems!
+ }
+ if isaddressregister(regdst.reglo) or
+ isaddressregister(regdst.reghi) or
+ isaddressregister(regsrc.reghi) then
+ internalerror(20020817);
+ list.concat(taicpu.op_reg_reg(A_SUB,S_L,regsrc.reglo,regdst.reglo));
+ list.concat(taicpu.op_reg_reg(A_SUBX,S_L,regsrc.reghi,regdst.reghi));
+ end;
+ OP_XOR:
+ begin
+ if isaddressregister(regdst.reglo) or
+ isaddressregister(regsrc.reglo) or
+ isaddressregister(regsrc.reghi) or
+ isaddressregister(regdst.reghi) then
+ internalerror(20020817);
+ list.concat(taicpu.op_reg_reg(A_EOR,S_L,regsrc.reglo,regdst.reglo));
+ list.concat(taicpu.op_reg_reg(A_EOR,S_L,regsrc.reghi,regdst.reghi));
+ end;
+ end; { end case }
+ end;
+
+
+ procedure tcg64f68k.a_op64_const_reg(list : TAsmList;op:TOpCG;size: tcgsize; value : int64;regdst : tregister64);
+ var
+ lowvalue : cardinal;
+ highvalue : cardinal;
+ hreg : tregister;
+ begin
+// writeln('a_op64_const_reg');
+ { is it optimized out ? }
+// if cg.optimize64_op_const_reg(list,op,value,reg) then
+// exit;
+
+ lowvalue := cardinal(value);
+ highvalue:= value shr 32;
+
+ { the destination registers must be data registers }
+ if isaddressregister(regdst.reglo) or
+ isaddressregister(regdst.reghi) then
+ internalerror(20020817);
+ case op of
+ OP_ADD :
+ begin
+ hreg:=cg.getintregister(list,OS_INT);
+ list.concat(taicpu.op_const_reg(A_MOVE,S_L,highvalue,hreg));
+ list.concat(taicpu.op_const_reg(A_ADD,S_L,lowvalue,regdst.reglo));
+ list.concat(taicpu.op_reg_reg(A_ADDX,S_L,hreg,regdst.reglo));
+ end;
+ OP_AND :
+ begin
+ list.concat(taicpu.op_const_reg(A_AND,S_L,lowvalue,regdst.reglo));
+ list.concat(taicpu.op_const_reg(A_AND,S_L,highvalue,regdst.reglo));
+ end;
+ OP_OR :
+ begin
+ list.concat(taicpu.op_const_reg(A_OR,S_L,lowvalue,regdst.reglo));
+ list.concat(taicpu.op_const_reg(A_OR,S_L,highvalue,regdst.reglo));
+ end;
+ { this is handled in 1st pass for 32-bit cpus (helper call) }
+ OP_IDIV,OP_DIV,
+ OP_IMUL,OP_MUL: internalerror(2002081701);
+ { this is also handled in 1st pass for 32-bit cpus (helper call) }
+ OP_SAR,OP_SHL,OP_SHR: internalerror(2002081702);
+ OP_SUB:
+ begin
+ hreg:=cg.getintregister(list,OS_INT);
+ list.concat(taicpu.op_const_reg(A_MOVE,S_L,highvalue,hreg));
+ list.concat(taicpu.op_const_reg(A_SUB,S_L,lowvalue,regdst.reglo));
+ list.concat(taicpu.op_reg_reg(A_SUBX,S_L,hreg,regdst.reglo));
+ end;
+ OP_XOR:
+ begin
+ list.concat(taicpu.op_const_reg(A_EOR,S_L,lowvalue,regdst.reglo));
+ list.concat(taicpu.op_const_reg(A_EOR,S_L,highvalue,regdst.reglo));
+ end;
+ end; { end case }
+ end;
+
+
+procedure create_codegen;
+ begin
+ cg := tcg68k.create;
+ cg64 :=tcg64f68k.create;
+ end;
+
+end.
diff --git a/closures/compiler/m68k/cpuasm.pas b/closures/compiler/m68k/cpuasm.pas
new file mode 100644
index 0000000000..b19eb527df
--- /dev/null
+++ b/closures/compiler/m68k/cpuasm.pas
@@ -0,0 +1,26 @@
+{
+ Copyright (c) 1998-2000 by Florian Klaempfl
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit cpuasm;
+
+ interface
+
+ implementation
+
+end.
diff --git a/closures/compiler/m68k/cpubase.pas b/closures/compiler/m68k/cpubase.pas
new file mode 100644
index 0000000000..e7de4b692a
--- /dev/null
+++ b/closures/compiler/m68k/cpubase.pas
@@ -0,0 +1,520 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Contains the base types for the m68k
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+{ This Unit contains the base types for the m68k
+}
+unit cpubase;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ globtype,
+ strings,cutils,cclasses,aasmbase,cpuinfo,cgbase;
+
+{*****************************************************************************
+ Assembler Opcodes
+*****************************************************************************}
+
+ type
+ { warning: CPU32 opcodes are not fully compatible with the MC68020. }
+ { 68000 only opcodes }
+ tasmop = (a_none,
+ a_abcd,a_add,a_adda,a_addi,a_addq,a_addx,a_and,a_andi,
+ a_asl,a_asr,a_bcc,a_bcs,a_beq,a_bge,a_bgt,a_bhi,
+ a_ble,a_bls,a_blt,a_bmi,a_bne,a_bpl,a_bvc,a_bvs,
+ a_bchg,a_bclr,a_bra,a_bset,a_bsr,a_btst,a_chk,
+ a_clr,a_cmp,a_cmpa,a_cmpi,a_cmpm,a_dbcc,a_dbcs,a_dbeq,a_dbge,
+ a_dbgt,a_dbhi,a_dble,a_dbls,a_dblt,a_dbmi,a_dbne,a_dbra,
+ a_dbpl,a_dbt,a_dbvc,a_dbvs,a_dbf,a_divs,a_divu,
+ a_eor,a_eori,a_exg,a_illegal,a_ext,a_jmp,a_jsr,
+ a_lea,a_link,a_lsl,a_lsr,a_move,a_movea,a_movei,a_moveq,
+ a_movem,a_movep,a_muls,a_mulu,a_nbcd,a_neg,a_negx,
+ a_nop,a_not,a_or,a_ori,a_pea,a_rol,a_ror,a_roxl,
+ a_roxr,a_rtr,a_rts,a_sbcd,a_scc,a_scs,a_seq,a_sge,
+ a_sgt,a_shi,a_sle,a_sls,a_slt,a_smi,a_sne,
+ a_spl,a_st,a_svc,a_svs,a_sf,a_sub,a_suba,a_subi,a_subq,
+ a_subx,a_swap,a_tas,a_trap,a_trapv,a_tst,a_unlk,
+ a_rte,a_reset,a_stop,
+ { mc68010 instructions }
+ a_bkpt,a_movec,a_moves,a_rtd,
+ { mc68020 instructions }
+ a_bfchg,a_bfclr,a_bfexts,a_bfextu,a_bfffo,
+ a_bfins,a_bfset,a_bftst,a_callm,a_cas,a_cas2,
+ a_chk2,a_cmp2,a_divsl,a_divul,a_extb,a_pack,a_rtm,
+ a_trapcc,a_tracs,a_trapeq,a_trapf,a_trapge,a_trapgt,
+ a_traphi,a_traple,a_trapls,a_traplt,a_trapmi,a_trapne,
+ a_trappl,a_trapt,a_trapvc,a_trapvs,a_unpk,
+ { fpu processor instructions - directly supported only. }
+ { ieee aware and misc. condition codes not supported }
+ a_fabs,a_fadd,
+ a_fbeq,a_fbne,a_fbngt,a_fbgt,a_fbge,a_fbnge,
+ a_fblt,a_fbnlt,a_fble,a_fbgl,a_fbngl,a_fbgle,a_fbngle,
+ a_fdbeq,a_fdbne,a_fdbgt,a_fdbngt,a_fdbge,a_fdbnge,
+ a_fdblt,a_fdbnlt,a_fdble,a_fdbgl,a_fdbngl,a_fdbgle,a_fdbngle,
+ a_fseq,a_fsne,a_fsgt,a_fsngt,a_fsge,a_fsnge,
+ a_fslt,a_fsnlt,a_fsle,a_fsgl,a_fsngl,a_fsgle,a_fsngle,
+ a_fcmp,a_fdiv,a_fmove,a_fmovem,
+ a_fmul,a_fneg,a_fnop,a_fsqrt,a_fsub,a_fsgldiv,
+ a_fsflmul,a_ftst,
+ a_ftrapeq,a_ftrapne,a_ftrapgt,a_ftrapngt,a_ftrapge,a_ftrapnge,
+ a_ftraplt,a_ftrapnlt,a_ftraple,a_ftrapgl,a_ftrapngl,a_ftrapgle,a_ftrapngle,
+ { protected instructions }
+ a_cprestore,a_cpsave,
+ { fpu unit protected instructions }
+ { and 68030/68851 common mmu instructions }
+ { (this may include 68040 mmu instructions) }
+ a_frestore,a_fsave,a_pflush,a_pflusha,a_pload,a_pmove,a_ptest,
+ { useful for assembly language output }
+ a_label,a_dbxx,a_sxx,a_bxx,a_fbxx);
+
+ {# This should define the array of instructions as string }
+ op2strtable=array[tasmop] of string[11];
+
+ Const
+ {# First value of opcode enumeration }
+ firstop = low(tasmop);
+ {# Last value of opcode enumeration }
+ lastop = high(tasmop);
+
+{*****************************************************************************
+ Registers
+*****************************************************************************}
+
+ type
+ { Number of registers used for indexing in tables }
+ tregisterindex=0..{$i r68knor.inc}-1;
+
+ const
+ { Available Superregisters }
+ {$i r68ksup.inc}
+
+ { ? whatever... }
+ R_SUBWHOLE = R_SUBNONE;
+
+ { Available Registers }
+ {$i r68kcon.inc}
+
+ { Integer Super registers first and last }
+ first_int_imreg = RS_D7+1;
+
+ { Float Super register first and last }
+ first_fpu_imreg = RS_FP7+1;
+
+ { Integer Super registers first and last }
+ first_addr_imreg = RS_SP+1;
+
+ { MM Super register first and last }
+ first_mm_supreg = 0;
+ first_mm_imreg = 0;
+
+ maxfpuregs = 8;
+
+{ TODO: FIX BSSTART}
+ regnumber_count_bsstart = 16;
+
+ regnumber_table : array[tregisterindex] of tregister = (
+ {$i r68knum.inc}
+ );
+
+ regstabs_table : array[tregisterindex] of shortint = (
+ {$i r68ksta.inc}
+ );
+
+ regdwarf_table : array[tregisterindex] of shortint = (
+{ TODO: reused stabs values!}
+ {$i r68ksta.inc}
+ );
+
+ { registers which may be destroyed by calls }
+ VOLATILE_INTREGISTERS = [RS_D0,RS_D1];
+ VOLATILE_FPUREGISTERS = [];
+ VOLATILE_ADDRESSREGISTER = [RS_A0,RS_A1];
+
+ type
+ totherregisterset = set of tregisterindex;
+
+
+{*****************************************************************************
+ Conditions
+*****************************************************************************}
+
+ type
+ TAsmCond=(C_None,
+ C_CC,C_LS,C_CS,C_LT,C_EQ,C_MI,C_F,C_NE,
+ C_GE,C_PL,C_GT,C_T,C_HI,C_VC,C_LE,C_VS
+ );
+
+
+ const
+ cond2str:array[TAsmCond] of string[3]=('',
+ 'cc','ls','cs','lt','eq','mi','f','ne',
+ 'ge','pl','gt','t','hi','vc','le','vs'
+ );
+
+{*****************************************************************************
+ Flags
+*****************************************************************************}
+
+ type
+ TResFlags = (
+ F_E,F_NE,
+ F_G,F_L,F_GE,F_LE,F_C,F_NC,F_A,F_AE,F_B,F_BE);
+
+{*****************************************************************************
+ Reference
+*****************************************************************************}
+
+ type
+ { direction of address register : }
+ { (An) (An)+ -(An) }
+ tdirection = (dir_none,dir_inc,dir_dec);
+
+
+{*****************************************************************************
+ Operand Sizes
+*****************************************************************************}
+
+ { S_NO = No Size of operand }
+ { S_B = 8-bit size operand }
+ { S_W = 16-bit size operand }
+ { S_L = 32-bit size operand }
+ { Floating point types }
+ { S_FS = single type (32 bit) }
+ { S_FD = double/64bit integer }
+ { S_FX = Extended type }
+ topsize = (S_NO,S_B,S_W,S_L,S_FS,S_FD,S_FX,S_IQ);
+
+{*****************************************************************************
+ Constants
+*****************************************************************************}
+
+ const
+ {# maximum number of operands in assembler instruction }
+ max_operands = 4;
+
+{*****************************************************************************
+ Default generic sizes
+*****************************************************************************}
+
+ {# Defines the default address size for a processor, }
+ OS_ADDR = OS_32;
+ {# the natural int size for a processor, }
+ OS_INT = OS_32;
+ OS_SINT = OS_S32;
+ {# the maximum float size for a processor, }
+ OS_FLOAT = OS_F64;
+ {# the size of a vector register for a processor }
+ OS_VECTOR = OS_M128;
+
+
+{*****************************************************************************
+ GDB Information
+*****************************************************************************}
+
+ {# Register indexes for stabs information, when some
+ parameters or variables are stored in registers.
+
+ Taken from m68kelf.h (DBX_REGISTER_NUMBER)
+ from GCC 3.x source code.
+
+ This is not compatible with the m68k-sun
+ implementation.
+ }
+ stab_regindex : array[tregisterindex] of shortint =
+ (
+ {$i r68ksta.inc}
+ );
+
+{*****************************************************************************
+ Generic Register names
+*****************************************************************************}
+
+ {# Stack pointer register }
+ NR_STACK_POINTER_REG = NR_SP;
+ RS_STACK_POINTER_REG = RS_SP;
+ {# Frame pointer register }
+{ TODO: FIX ME!!! frame pointer is A5 on Amiga, but A6 on unixes?}
+ NR_FRAME_POINTER_REG = NR_A5;
+ RS_FRAME_POINTER_REG = RS_A5;
+
+ {# Register for addressing absolute data in a position independant way,
+ such as in PIC code. The exact meaning is ABI specific. For
+ further information look at GCC source : PIC_OFFSET_TABLE_REGNUM
+ }
+{ TODO: FIX ME!!! pic offset reg conflicts with frame pointer?}
+ NR_PIC_OFFSET_REG = NR_A5;
+ { Return address for DWARF }
+{ TODO: just a guess!}
+ NR_RETURN_ADDRESS_REG = NR_A0;
+ { Results are returned in this register (32-bit values) }
+ NR_FUNCTION_RETURN_REG = NR_D0;
+ RS_FUNCTION_RETURN_REG = RS_D0;
+ { Low part of 64bit return value }
+ NR_FUNCTION_RETURN64_LOW_REG = NR_D0;
+ RS_FUNCTION_RETURN64_LOW_REG = RS_D0;
+ { High part of 64bit return value }
+ NR_FUNCTION_RETURN64_HIGH_REG = NR_D1;
+ RS_FUNCTION_RETURN64_HIGH_REG = RS_D1;
+ { The value returned from a function is available in this register }
+ NR_FUNCTION_RESULT_REG = NR_FUNCTION_RETURN_REG;
+ RS_FUNCTION_RESULT_REG = RS_FUNCTION_RETURN_REG;
+ { The lowh part of 64bit value returned from a function }
+ NR_FUNCTION_RESULT64_LOW_REG = NR_FUNCTION_RETURN64_LOW_REG;
+ RS_FUNCTION_RESULT64_LOW_REG = RS_FUNCTION_RETURN64_LOW_REG;
+ { The high part of 64bit value returned from a function }
+ NR_FUNCTION_RESULT64_HIGH_REG = NR_FUNCTION_RETURN64_HIGH_REG;
+ RS_FUNCTION_RESULT64_HIGH_REG = RS_FUNCTION_RETURN64_HIGH_REG;
+
+ {# Floating point results will be placed into this register }
+ NR_FPU_RESULT_REG = NR_FP0;
+
+{*****************************************************************************
+ GCC /ABI linking information
+*****************************************************************************}
+
+ {# Registers which must be saved when calling a routine declared as
+ cppdecl, cdecl, stdcall, safecall, palmossyscall. The registers
+ saved should be the ones as defined in the target ABI and / or GCC.
+
+ This value can be deduced from CALLED_USED_REGISTERS array in the
+ GCC source.
+ }
+ saved_standard_registers : array[0..5] of tsuperregister = (RS_D2,RS_D3,RS_D4,RS_D5,RS_D6,RS_D7);
+ saved_standard_address_registers : array[0..3] of tsuperregister = (RS_A2,RS_A3,RS_A4,RS_A5);
+
+ { this is only for the generic code which is not used for this architecture }
+ saved_mm_registers : array[0..0] of tsuperregister = (RS_NO);
+
+ {# Required parameter alignment when calling a routine declared as
+ stdcall and cdecl. The alignment value should be the one defined
+ by GCC or the target ABI.
+
+ The value of this constant is equal to the constant
+ PARM_BOUNDARY / BITS_PER_UNIT in the GCC source.
+ }
+ std_param_align = 4; { for 32-bit version only }
+
+
+{*****************************************************************************
+ CPU Dependent Constants
+*****************************************************************************}
+
+
+{*****************************************************************************
+ Helpers
+*****************************************************************************}
+
+ function is_calljmp(o:tasmop):boolean;
+
+ procedure inverse_flags(var r : TResFlags);
+ function flags_to_cond(const f: TResFlags) : TAsmCond;
+ function cgsize2subreg(regtype: tregistertype; s:Tcgsize):Tsubregister;
+ function reg_cgsize(const reg: tregister): tcgsize;
+
+ function findreg_by_number(r:Tregister):tregisterindex;
+ function std_regnum_search(const s:string):Tregister;
+ function std_regname(r:Tregister):string;
+
+ function isaddressregister(reg : tregister) : boolean;
+
+ function inverse_cond(const c: TAsmCond): TAsmCond; {$ifdef USEINLINE}inline;{$endif USEINLINE}
+ function conditions_equal(const c1, c2: TAsmCond): boolean; {$ifdef USEINLINE}inline;{$endif USEINLINE}
+ function dwarf_reg(r:tregister):shortint;
+
+implementation
+
+ uses
+ verbose,
+ rgbase;
+
+
+ const
+ std_regname_table : array[tregisterindex] of string[7] = (
+ {$i r68kstd.inc}
+ );
+
+ regnumber_index : array[tregisterindex] of tregisterindex = (
+ {$i r68krni.inc}
+ );
+
+ std_regname_index : array[tregisterindex] of tregisterindex = (
+ {$i r68ksri.inc}
+ );
+
+
+{*****************************************************************************
+ Helpers
+*****************************************************************************}
+
+ function is_calljmp(o:tasmop):boolean;
+ begin
+ is_calljmp := false;
+ if o in [A_BXX,A_FBXX,A_DBXX,A_BCC..A_BVS,A_DBCC..A_DBVS,A_FBEQ..A_FSNGLE,
+ A_JSR,A_BSR,A_JMP] then
+ is_calljmp := true;
+ end;
+
+
+ procedure inverse_flags(var r: TResFlags);
+ const flagsinvers : array[F_E..F_BE] of tresflags =
+ (F_NE,F_E,
+ F_LE,F_GE,
+ F_L,F_G,
+ F_NC,F_C,
+ F_BE,F_B,
+ F_AE,F_A);
+ begin
+ r:=flagsinvers[r];
+ end;
+
+
+
+ function flags_to_cond(const f: TResFlags) : TAsmCond;
+ const flags2cond: array[tresflags] of tasmcond = (
+ C_EQ,{F_E equal}
+ C_NE,{F_NE not equal}
+ C_GT,{F_G gt signed}
+ C_LT,{F_L lt signed}
+ C_GE,{F_GE ge signed}
+ C_LE,{F_LE le signed}
+ C_CS,{F_C carry set}
+ C_CC,{F_NC carry clear}
+ C_HI,{F_A gt unsigned}
+ C_CC,{F_AE ge unsigned}
+ C_CS,{F_B lt unsigned}
+ C_LS);{F_BE le unsigned}
+ begin
+ flags_to_cond := flags2cond[f];
+ end;
+
+ function cgsize2subreg(regtype: tregistertype; s:Tcgsize):Tsubregister;
+ var p: pointer;
+ begin
+ case s of
+ OS_NO: begin
+{ TODO: FIX ME!!! results in bad code generation}
+ cgsize2subreg:=R_SUBWHOLE;
+ end;
+
+ OS_8,OS_S8:
+ cgsize2subreg:=R_SUBWHOLE;
+ OS_16,OS_S16:
+ cgsize2subreg:=R_SUBWHOLE;
+ OS_32,OS_S32:
+ cgsize2subreg:=R_SUBWHOLE;
+ OS_64,OS_S64:
+ begin
+// writeln('64bit regsize?');
+ cgsize2subreg:=R_SUBWHOLE;
+ end;
+ OS_F32 :
+ cgsize2subreg:=R_SUBFS;
+ OS_F64 :
+ cgsize2subreg:=R_SUBFD;
+{
+ begin
+ // is this correct? (KB)
+ cgsize2subreg:=R_SUBNONE;
+ end;
+}
+ else begin
+ writeln('M68K: invalid register size');
+ // this supposed to be debug
+ // p:=nil; dword(p^):=0;
+ // internalerror(200301231);
+ cgsize2subreg:=R_SUBWHOLE;
+ end;
+ end;
+ end;
+
+
+ function reg_cgsize(const reg: tregister): tcgsize;
+ begin
+ case getregtype(reg) of
+ R_ADDRESSREGISTER,
+ R_INTREGISTER :
+ result:=OS_32;
+ R_FPUREGISTER :
+ result:=OS_F64;
+ else
+ internalerror(200303181);
+ end;
+ end;
+
+
+ function findreg_by_number(r:Tregister):tregisterindex;
+ begin
+ result:=findreg_by_number_table(r,regnumber_index);
+ end;
+
+
+ function std_regnum_search(const s:string):Tregister;
+ begin
+ result:=regnumber_table[findreg_by_name_table(s,std_regname_table,std_regname_index)];
+ end;
+
+
+ function std_regname(r:Tregister):string;
+ var
+ p : tregisterindex;
+ begin
+ p:=findreg_by_number_table(r,regnumber_index);
+ if p<>0 then
+ result:=std_regname_table[p]
+ else
+ result:=generic_regname(r);
+ end;
+
+
+ function isaddressregister(reg : tregister) : boolean;
+ begin
+ result:=getregtype(reg)=R_ADDRESSREGISTER;
+ end;
+
+
+ function inverse_cond(const c: TAsmCond): TAsmCond; {$ifdef USEINLINE}inline;{$endif USEINLINE}
+ const
+ inverse:array[TAsmCond] of TAsmCond=(C_None,
+{ TODO: TODO, this is just a copy!}
+ C_CC,C_LS,C_CS,C_LT,C_EQ,C_MI,C_F,C_NE,
+ C_GE,C_PL,C_GT,C_T,C_HI,C_VC,C_LE,C_VS
+ );
+ begin
+ result := inverse[c];
+ end;
+
+
+ function conditions_equal(const c1, c2: TAsmCond): boolean; {$ifdef USEINLINE}inline;{$endif USEINLINE}
+ begin
+ result := c1 = c2;
+ end;
+
+
+ function dwarf_reg(r:tregister):shortint;
+ begin
+ result:=regdwarf_table[findreg_by_number(r)];
+ if result=-1 then
+ internalerror(200603251);
+ end;
+
+end.
diff --git a/closures/compiler/m68k/cpuinfo.pas b/closures/compiler/m68k/cpuinfo.pas
new file mode 100644
index 0000000000..0006c73243
--- /dev/null
+++ b/closures/compiler/m68k/cpuinfo.pas
@@ -0,0 +1,87 @@
+{
+ Copyright (c) 1998-2002 by the Free Pascal development team
+
+ Basic Processor information for the m68k
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+Unit CPUInfo;
+
+Interface
+
+ uses
+ globtype;
+
+Type
+ bestreal = double;
+ ts32real = single;
+ ts64real = double;
+ ts80real = extended;
+ ts128real = type extended;
+ ts64comp = extended;
+
+ pbestreal=^bestreal;
+
+ { possible supported processors for this target }
+ tcputype =
+ (cpu_none,
+ cpu_MC68000,
+ cpu_MC68020,
+ cpu_Coldfire
+ );
+
+ tfputype =
+ (fpu_none,
+ fpu_soft,
+ fpu_libgcc,
+ fpu_68881
+ );
+
+Const
+ { calling conventions supported by the code generator }
+ supported_calling_conventions : tproccalloptions = [
+ pocall_internproc,
+ pocall_stdcall,
+ { the difference to stdcall is only the name mangling }
+ pocall_cdecl,
+ { the difference to stdcall is only the name mangling }
+ pocall_cppdecl,
+ { this used by the PalmOS port only }
+ pocall_syscall
+ ];
+
+ cputypestr : array[tcputype] of string[8] = ('',
+ '68000',
+ '68020',
+ 'COLDFIRE'
+ );
+
+ fputypestr : array[tfputype] of string[6] = ('',
+ 'SOFT',
+ 'LIBGCC',
+ '68881'
+ );
+
+ { Supported optimizations, only used for information }
+ supported_optimizerswitches = genericlevel1optimizerswitches+
+ genericlevel2optimizerswitches+
+ genericlevel3optimizerswitches-
+ { no need to write info about those }
+ [cs_opt_level1,cs_opt_level2,cs_opt_level3]+
+ [cs_opt_regvar,cs_opt_loopunroll,cs_opt_nodecse];
+
+ level1optimizerswitches = genericlevel1optimizerswitches;
+ level2optimizerswitches = genericlevel2optimizerswitches + level1optimizerswitches +
+ [cs_opt_regvar,cs_opt_stackframe,cs_opt_nodecse];
+ level3optimizerswitches = genericlevel3optimizerswitches + level2optimizerswitches + [{,cs_opt_loopunroll}];
+
+Implementation
+
+end.
diff --git a/closures/compiler/m68k/cpunode.pas b/closures/compiler/m68k/cpunode.pas
new file mode 100644
index 0000000000..79f38ae861
--- /dev/null
+++ b/closures/compiler/m68k/cpunode.pas
@@ -0,0 +1,52 @@
+{
+ Copyright (c) 2000-2002 by Florian Klaempfl
+
+ Includes the 680x0/Coldfire code generator
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit cpunode;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ implementation
+
+ uses
+ { generic nodes }
+ ncgbas,ncgld,ncgflw,ncgcnv,ncgmem,ncgcon,ncgcal,ncgset,ncginl,ncgmat,ncgadd,
+ { to be able to only parts of the generic code,
+ the processor specific nodes must be included
+ after the generic one (FK)
+ }
+ n68kadd,
+ n68kcal,
+// nppccon,
+// nppcflw,
+// nppcmem,
+// nppcset,
+// nppcinl,
+// nppcopt,
+ { this not really a node }
+// nppcobj,
+// nppcmat,
+ n68kmat,
+ n68kcnv
+ ;
+
+end.
diff --git a/closures/compiler/m68k/cpupara.pas b/closures/compiler/m68k/cpupara.pas
new file mode 100644
index 0000000000..bf23642a98
--- /dev/null
+++ b/closures/compiler/m68k/cpupara.pas
@@ -0,0 +1,599 @@
+{
+ Copyright (c) 2002 by Florian Klaempfl
+
+ Generates the argument location information for 680x0
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+{ Generates the argument location information for 680x0.
+}
+unit cpupara;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ globtype,
+ cpubase,
+ aasmdata,
+ symconst,symtype,symdef,symsym,
+ parabase,paramgr,cgbase;
+
+ type
+ { Returns the location for the nr-st 32 Bit int parameter
+ if every parameter before is an 32 Bit int parameter as well
+ and if the calling conventions for the helper routines of the
+ rtl are used.
+ }
+ tm68kparamanager = class(tparamanager)
+ procedure getintparaloc(calloption : tproccalloption; nr : longint;var cgpara : TCGPara);override;
+ function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override;
+ function push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override;
+ function get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tcgpara;override;
+ procedure createtempparaloc(list: TAsmList;calloption : tproccalloption;parasym : tparavarsym;can_use_final_stack_loc : boolean;var cgpara:TCGPara);override;
+ procedure create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
+ function create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;override;
+ function parseparaloc(p : tparavarsym;const s : string) : boolean;override;
+ function parsefuncretloc(p : tabstractprocdef; const s : string) : boolean;override;
+ private
+ procedure init_values(var curintreg, curfloatreg: tsuperregister; var cur_stack_offset: aword);
+ function create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras: tparalist;
+ var curintreg, curfloatreg: tsuperregister; var cur_stack_offset: aword):longint;
+ end;
+
+ implementation
+
+ uses
+ verbose,
+ globals,
+ systems,
+ cpuinfo,cgutils,
+ defutil;
+
+ procedure tm68kparamanager.getintparaloc(calloption : tproccalloption; nr : longint;var cgpara : TCGPara);
+ var
+ paraloc : pcgparalocation;
+ begin
+ if nr<1 then
+ internalerror(2002070801);
+ cgpara.reset;
+ cgpara.size:=OS_INT;
+ cgpara.alignment:=std_param_align;
+ paraloc:=cgpara.add_location;
+ with paraloc^ do
+ begin
+ { warning : THIS ONLY WORKS WITH INTERNAL ROUTINES,
+ WHICH MUST ALWAYS PASS 4-BYTE PARAMETERS!!
+ }
+ loc:=LOC_REFERENCE;
+ reference.index:=NR_STACK_POINTER_REG;
+ reference.offset:=target_info.first_parm_offset+nr*4;
+ end;
+ end;
+
+ function getparaloc(p : tdef) : tcgloc;
+
+ begin
+ result:=LOC_REFERENCE;
+ (* Later, the LOC_REFERENCE is in most cases changed into LOC_REGISTER
+ if push_addr_param for the def is true
+ case p.typ of
+ orddef:
+ result:=LOC_REGISTER;
+ floatdef:
+ result:=LOC_FPUREGISTER;
+ enumdef:
+ result:=LOC_REGISTER;
+ pointerdef:
+ result:=LOC_REGISTER;
+ formaldef:
+ result:=LOC_REGISTER;
+ classrefdef:
+ result:=LOC_REGISTER;
+ recorddef:
+ if (target_info.abi<>abi_powerpc_aix) then
+ result:=LOC_REFERENCE
+ else
+ result:=LOC_REGISTER;
+ objectdef:
+ if is_object(p) then
+ result:=LOC_REFERENCE
+ else
+ result:=LOC_REGISTER;
+ stringdef:
+ if is_shortstring(p) or is_longstring(p) then
+ result:=LOC_REFERENCE
+ else
+ result:=LOC_REGISTER;
+ procvardef:
+ if (po_methodpointer in tprocvardef(p).procoptions) then
+ result:=LOC_REFERENCE
+ else
+ result:=LOC_REGISTER;
+ filedef:
+ result:=LOC_REGISTER;
+ arraydef:
+ result:=LOC_REFERENCE;
+ setdef:
+ if is_smallset(p) then
+ result:=LOC_REGISTER
+ else
+ result:=LOC_REFERENCE;
+ variantdef:
+ result:=LOC_REFERENCE;
+ { avoid problems with errornous definitions }
+ errordef:
+ result:=LOC_REGISTER;
+ else
+ internalerror(2002071001);
+ end;
+ *)
+ end;
+
+
+{ TODO: copied from ppc cg, needs work}
+ function tm68kparamanager.push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;
+ begin
+ result:=false;
+ { var,out,constref always require address }
+ if varspez in [vs_var,vs_out,vs_constref] then
+ begin
+ result:=true;
+ exit;
+ end;
+ case def.typ of
+ variantdef,
+ formaldef :
+ result:=true;
+ recorddef:
+ result:=true;
+ arraydef:
+ result:=(tarraydef(def).highrange>=tarraydef(def).lowrange) or
+ is_open_array(def) or
+ is_array_of_const(def) or
+ is_array_constructor(def);
+ objectdef :
+ result:=is_object(def);
+ setdef :
+ result:=not is_smallset(def);
+ stringdef :
+ result:=tstringdef(def).stringtype in [st_shortstring,st_longstring];
+ procvardef :
+ result:=po_methodpointer in tprocvardef(def).procoptions;
+ end;
+ end;
+
+ procedure tm68kparamanager.init_values(var curintreg, curfloatreg: tsuperregister; var cur_stack_offset: aword);
+ begin
+ cur_stack_offset:=8;
+ curintreg:=RS_D0;
+ curfloatreg:=RS_FP0;
+ end;
+
+ procedure tm68kparamanager.create_funcretloc_info(p: tabstractprocdef; side: tcallercallee);
+ begin
+ p.funcretloc[side]:=get_funcretloc(p,side,p.returndef);
+ end;
+
+
+ function tm68kparamanager.get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tcgpara;
+ var
+ paraloc : pcgparalocation;
+ retcgsize : tcgsize;
+ begin
+ result.init;
+ result.alignment:=get_para_align(p.proccalloption);
+ { void has no location }
+ if is_void(def) then
+ begin
+ paraloc:=result.add_location;
+ result.size:=OS_NO;
+ result.intsize:=0;
+ paraloc^.size:=OS_NO;
+ paraloc^.loc:=LOC_VOID;
+ exit;
+ end;
+ { Constructors return self instead of a boolean }
+ if (p.proctypeoption=potype_constructor) then
+ begin
+ retcgsize:=OS_ADDR;
+ result.intsize:=sizeof(pint);
+ end
+ else
+ begin
+ retcgsize:=def_cgsize(def);
+ result.intsize:=def.size;
+ end;
+ result.size:=retcgsize;
+ { Return is passed as var parameter }
+ if ret_in_param(def,p.proccalloption) then
+ begin
+ paraloc:=result.add_location;
+ paraloc^.loc:=LOC_REFERENCE;
+ paraloc^.size:=retcgsize;
+ exit;
+ end;
+
+ paraloc:=result.add_location;
+ { Return in FPU register? }
+ if not(cs_fp_emulation in current_settings.moduleswitches) and (p.returndef.typ=floatdef) then
+ begin
+ paraloc^.loc:=LOC_FPUREGISTER;
+ paraloc^.register:=NR_FPU_RESULT_REG;
+ paraloc^.size:=retcgsize;
+ end
+ else
+ { Return in register }
+ begin
+ if retcgsize in [OS_64,OS_S64] then
+ begin
+ { low 32bits }
+ paraloc^.loc:=LOC_REGISTER;
+ paraloc^.size:=OS_32;
+ if side=callerside then
+ paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG
+ else
+ paraloc^.register:=NR_FUNCTION_RETURN64_LOW_REG;
+ { high 32bits }
+ paraloc:=result.add_location;
+ paraloc^.loc:=LOC_REGISTER;
+ paraloc^.size:=OS_32;
+ if side=calleeside then
+ paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG
+ else
+ paraloc^.register:=NR_FUNCTION_RETURN64_HIGH_REG;
+ end
+ else
+ begin
+ paraloc^.loc:=LOC_REGISTER;
+ paraloc^.size:=retcgsize;
+ if side=callerside then
+ paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize))
+ else
+ paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(R_INTREGISTER,retcgsize));
+ end;
+ end;
+ end;
+
+ function tm68kparamanager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;
+ var
+ cur_stack_offset: aword;
+ curintreg, curfloatreg: tsuperregister;
+ begin
+ init_values(curintreg,curfloatreg,cur_stack_offset);
+
+ result:=create_paraloc_info_intern(p,side,p.paras,curintreg,curfloatreg,cur_stack_offset);
+
+ create_funcretloc_info(p,side);
+ end;
+
+ function tm68kparamanager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras: tparalist;
+ var curintreg, curfloatreg: tsuperregister; var cur_stack_offset: aword):longint;
+ var
+ paraloc : pcgparalocation;
+ hp : tparavarsym;
+ paracgsize : tcgsize;
+ paralen : aint;
+ parasize : longint;
+ paradef : tdef;
+ i : longint;
+ loc : tcgloc;
+ nextintreg,
+ nextfloatreg : tsuperregister;
+ stack_offset : longint;
+
+ begin
+ result:=0;
+ nextintreg:=curintreg;
+ nextfloatreg:=curfloatreg;
+ stack_offset:=cur_stack_offset;
+
+ parasize:=0;
+
+ for i:=0 to p.paras.count-1 do
+ begin
+ hp:=tparavarsym(paras[i]);
+ paradef:=hp.vardef;
+
+ { syscall for AmigaOS can have already a paraloc set }
+ if (vo_has_explicit_paraloc in hp.varoptions) then
+ begin
+ if not(vo_is_syscall_lib in hp.varoptions) then
+ internalerror(200506051);
+ continue;
+ end;
+ hp.paraloc[side].reset;
+
+ { currently only support C-style array of const }
+ if (p.proccalloption in [pocall_cdecl,pocall_cppdecl]) and
+ is_array_of_const(paradef) then
+ begin
+{$ifdef DEBUG_CHARLIE}
+ writeln('loc register');
+{$endif DEBUG_CHARLIE}
+ paraloc:=hp.paraloc[side].add_location;
+ { hack: the paraloc must be valid, but is not actually used }
+ paraloc^.loc:=LOC_REGISTER;
+ paraloc^.register:=NR_D0;
+ paraloc^.size:=OS_ADDR;
+ break;
+ end;
+
+ if (hp.varspez in [vs_var,vs_out]) or
+ push_addr_param(hp.varspez,paradef,p.proccalloption) or
+ is_open_array(paradef) or
+ is_array_of_const(paradef) then
+ begin
+{$ifdef DEBUG_CHARLIE}
+ writeln('loc register');
+{$endif DEBUG_CHARLIE}
+ paradef:=voidpointertype;
+ loc:=LOC_REGISTER;
+ paracgsize := OS_ADDR;
+ paralen := tcgsize2size[OS_ADDR];
+ end
+ else
+ begin
+ if not is_special_array(paradef) then
+ paralen:=paradef.size
+ else
+ paralen:=tcgsize2size[def_cgsize(paradef)];
+
+ loc:=getparaloc(paradef);
+ paracgsize:=def_cgsize(paradef);
+ { for things like formaldef }
+ if (paracgsize=OS_NO) then
+ begin
+ paracgsize:=OS_ADDR;
+ paralen := tcgsize2size[OS_ADDR];
+ end;
+ end;
+
+ hp.paraloc[side].alignment:=std_param_align;
+ hp.paraloc[side].size:=paracgsize;
+ hp.paraloc[side].intsize:=paralen;
+
+ if (paralen = 0) then
+ if (paradef.typ = recorddef) then
+ begin
+ paraloc:=hp.paraloc[side].add_location;
+ paraloc^.loc := LOC_VOID;
+ end
+ else
+ internalerror(200506052);
+ { can become < 0 for e.g. 3-byte records }
+ while (paralen > 0) do
+ begin
+ paraloc:=hp.paraloc[side].add_location;
+ (*
+ by default, the m68k doesn't know any register parameters (FK)
+ if (loc = LOC_REGISTER) and
+ (nextintreg <= RS_D2) then
+ begin
+ //writeln('loc register');
+ paraloc^.loc := loc;
+ { make sure we don't lose whether or not the type is signed }
+ if (paradef.typ <> orddef) then
+ paracgsize := int_cgsize(paralen);
+ if (paracgsize in [OS_NO,OS_64,OS_S64]) then
+ paraloc^.size := OS_INT
+ else
+ paraloc^.size := paracgsize;
+ paraloc^.register:=newreg(R_INTREGISTER,nextintreg,R_SUBNONE);
+ inc(nextintreg);
+ dec(paralen,tcgsize2size[paraloc^.size]);
+ end
+ else if (loc = LOC_FPUREGISTER) and
+ (nextfloatreg <= RS_FP2) then
+ begin
+// writeln('loc fpuregister');
+ paraloc^.loc:=loc;
+ paraloc^.size := paracgsize;
+ paraloc^.register:=newreg(R_FPUREGISTER,nextfloatreg,R_SUBWHOLE);
+ inc(nextfloatreg);
+ dec(paralen,tcgsize2size[paraloc^.size]);
+ end
+ else { LOC_REFERENCE }
+ *)
+ begin
+{$ifdef DEBUG_CHARLIE}
+ writeln('loc reference');
+{$endif DEBUG_CHARLIE}
+ paraloc^.loc:=LOC_REFERENCE;
+ paraloc^.size:=int_cgsize(paralen);
+ if (side = callerside) then
+ paraloc^.reference.index:=NR_STACK_POINTER_REG
+ else
+ paraloc^.reference.index:=NR_FRAME_POINTER_REG;
+ paraloc^.reference.offset:=stack_offset;
+ inc(stack_offset,align(paralen,4));
+ paralen := 0;
+ end;
+ end;
+ end;
+ result:=stack_offset;
+// writeln('stack offset:',stack_offset);
+ end;
+
+
+{
+
+ if push_addr_param(hp.varspez,paradef,p.proccalloption) then
+ paracgsize:=OS_ADDR
+ else
+ begin
+ paracgsize:=def_cgsize(paradef);
+ if paracgsize=OS_NO then
+ paracgsize:=OS_ADDR;
+ end;
+ hp.paraloc[side].size:=paracgsize;
+ hp.paraloc[side].Alignment:=std_param_align;
+ paraloc:=hp.paraloc[side].add_location;
+ paraloc^.size:=paracgsize;
+ paraloc^.loc:=LOC_REFERENCE;
+ if side=callerside then
+ paraloc^.reference.index:=NR_STACK_POINTER_REG
+ else
+ paraloc^.reference.index:=NR_FRAME_POINTER_REG;
+ paraloc^.reference.offset:=target_info.first_parm_offset+parasize;
+ end;
+ create_funcretloc_info(p,side);
+ result:=parasize;
+ end;
+}
+
+ function tm68kparamanager.parsefuncretloc(p : tabstractprocdef; const s : string) : boolean;
+ begin
+ result:=false;
+ case target_info.system of
+ system_m68k_amiga:
+ begin
+ if s='D0' then
+ p.exp_funcretloc:=NR_D0
+ else if s='D1' then
+ p.exp_funcretloc:=NR_D1
+ else if s='D2' then
+ p.exp_funcretloc:=NR_D2
+ else if s='D3' then
+ p.exp_funcretloc:=NR_D3
+ else if s='D4' then
+ p.exp_funcretloc:=NR_D4
+ else if s='D5' then
+ p.exp_funcretloc:=NR_D5
+ else if s='D6' then
+ p.exp_funcretloc:=NR_D6
+ else if s='D7' then
+ p.exp_funcretloc:=NR_D7
+ else if s='A0' then
+ p.exp_funcretloc:=NR_A0
+ else if s='A1' then
+ p.exp_funcretloc:=NR_A1
+ else if s='A2' then
+ p.exp_funcretloc:=NR_A2
+ else if s='A3' then
+ p.exp_funcretloc:=NR_A3
+ else if s='A4' then
+ p.exp_funcretloc:=NR_A4
+ else if s='A5' then
+ p.exp_funcretloc:=NR_A5
+ { 'A6' is problematic, since it's the frame pointer in fpc,
+ so it should be saved before a call! }
+ else if s='A6' then
+ p.exp_funcretloc:=NR_A6
+ { 'A7' is the stack pointer on 68k, can't be overwritten by API calls }
+ else
+ p.exp_funcretloc:=NR_NO;
+
+ if p.exp_funcretloc<>NR_NO then result:=true;
+ end;
+ else
+ internalerror(2005121801);
+ end;
+ end;
+
+
+ function tm68kparamanager.parseparaloc(p : tparavarsym;const s : string) : boolean;
+ var
+ paraloc : pcgparalocation;
+ begin
+ result:=false;
+ case target_info.system of
+ system_m68k_amiga:
+ begin
+ p.paraloc[callerside].alignment:=4;
+ paraloc:=p.paraloc[callerside].add_location;
+ paraloc^.loc:=LOC_REGISTER;
+ paraloc^.size:=def_cgsize(p.vardef);
+ { pattern is always uppercase'd }
+ if s='D0' then
+ paraloc^.register:=NR_D0
+ else if s='D1' then
+ paraloc^.register:=NR_D1
+ else if s='D2' then
+ paraloc^.register:=NR_D2
+ else if s='D3' then
+ paraloc^.register:=NR_D3
+ else if s='D4' then
+ paraloc^.register:=NR_D4
+ else if s='D5' then
+ paraloc^.register:=NR_D5
+ else if s='D6' then
+ paraloc^.register:=NR_D6
+ else if s='D7' then
+ paraloc^.register:=NR_D7
+ else if s='A0' then
+ paraloc^.register:=NR_A0
+ else if s='A1' then
+ paraloc^.register:=NR_A1
+ else if s='A2' then
+ paraloc^.register:=NR_A2
+ else if s='A3' then
+ paraloc^.register:=NR_A3
+ else if s='A4' then
+ paraloc^.register:=NR_A4
+ else if s='A5' then
+ paraloc^.register:=NR_A5
+ { 'A6' is problematic, since it's the frame pointer in fpc,
+ so it should be saved before a call! }
+ else if s='A6' then
+ paraloc^.register:=NR_A6
+ { 'A7' is the stack pointer on 68k, can't be overwritten by API calls }
+ else
+ exit;
+
+ { copy to callee side }
+ p.paraloc[calleeside].add_location^:=paraloc^;
+ end;
+ else
+ internalerror(200405092);
+ end;
+ result:=true;
+ end;
+
+
+ procedure tm68kparamanager.createtempparaloc(list: TAsmList;calloption : tproccalloption;parasym : tparavarsym;can_use_final_stack_loc : boolean;var cgpara:TCGPara);
+ var
+ paraloc : pcgparalocation;
+ begin
+ paraloc:=parasym.paraloc[callerside].location;
+ { Never a need for temps when value is pushed (calls inside parameters
+ will simply allocate even more stack space for their parameters) }
+ if not(use_fixed_stack) then
+ can_use_final_stack_loc:=true;
+ inherited createtempparaloc(list,calloption,parasym,can_use_final_stack_loc,cgpara);
+ end;
+
+ function tm68kparamanager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;
+ var
+ cur_stack_offset: aword;
+ curintreg, curfloatreg: tsuperregister;
+ begin
+ init_values(curintreg,curfloatreg,cur_stack_offset);
+
+ result:=create_paraloc_info_intern(p,callerside,p.paras,curintreg,curfloatreg,cur_stack_offset);
+ if (p.proccalloption in [pocall_cdecl,pocall_cppdecl]) then
+ { just continue loading the parameters in the registers }
+ result:=create_paraloc_info_intern(p,callerside,varargspara,curintreg,curfloatreg,cur_stack_offset)
+ else
+ internalerror(200410231);
+ end;
+
+
+begin
+ paramanager:=tm68kparamanager.create;
+end.
diff --git a/closures/compiler/m68k/cpupi.pas b/closures/compiler/m68k/cpupi.pas
new file mode 100644
index 0000000000..2ed0f87dae
--- /dev/null
+++ b/closures/compiler/m68k/cpupi.pas
@@ -0,0 +1,41 @@
+{
+ Copyright (c) 2002 by Florian Klaempfl
+
+ This unit contains the CPU specific part of tprocinfo
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+
+{ This unit contains the CPU specific part of tprocinfo. }
+unit cpupi;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ procinfo,cgbase,psub;
+
+ type
+ tm68kprocinfo = class(tcgprocinfo)
+ end;
+
+ implementation
+
+begin
+ cprocinfo:=tm68kprocinfo;
+end.
diff --git a/closures/compiler/m68k/cputarg.pas b/closures/compiler/m68k/cputarg.pas
new file mode 100644
index 0000000000..ad73f0f145
--- /dev/null
+++ b/closures/compiler/m68k/cputarg.pas
@@ -0,0 +1,61 @@
+{
+ Copyright (c) 2001-2002 by Peter Vreman
+
+ Includes the m68k dependent target units
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit cputarg;
+
+{$i fpcdefs.inc}
+
+interface
+
+
+implementation
+
+ uses
+ systems { prevent a syntax error when nothing is included }
+
+{**************************************
+ Targets
+**************************************}
+
+ {$ifndef NOTARGETLINUX}
+ ,t_linux
+ {$endif}
+ {$ifndef NOTARGETAMIGA}
+ ,t_amiga
+ {$endif}
+ {$ifndef NOTARGETPALMOS}
+ ,t_palmos
+ {$endif}
+
+{**************************************
+ Assembler Readers
+**************************************}
+
+ ,ra68kmot
+
+{**************************************
+ Assemblers
+**************************************}
+
+ ,ag68kgas
+ ;
+
+end.
diff --git a/closures/compiler/m68k/itcpugas.pas b/closures/compiler/m68k/itcpugas.pas
new file mode 100644
index 0000000000..2f70bec349
--- /dev/null
+++ b/closures/compiler/m68k/itcpugas.pas
@@ -0,0 +1,138 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit contains the m68k GAS instruction tables
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit itcpugas;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cpubase,cgbase;
+
+ const
+ gas_op2str : op2strtable=
+ { warning: CPU32 opcodes are not fully compatible with the MC68020. }
+ { 68000 only opcodes }
+ ( '',
+ 'abcd','add','adda','addi','addq','addx','and','andi',
+ 'asl','asr','bcc','bcs','beq','bge','bgt','bhi',
+ 'ble','bls','blt','bmi','bne','bpl','bvc','bvs',
+ 'bchg','bclr','bra','bset','bsr','btst','chk',
+ 'clr','cmp','cmpa','cmpi','cmpm','dbcc','dbcs','dbeq','dbge',
+ 'dbgt','dbhi','dble','dbls','dblt','dbmi','dbne','dbra',
+ 'dbpl','dbt','dbvc','dbvs','dbf','divs','divu',
+ 'eor','eori','exg','illegal','ext','jmp','jsr',
+ 'lea','link','lsl','lsr','move','movea','movei','moveq',
+ 'movem','movep','muls','mulu','nbcd','neg','negx',
+ 'nop','not','or','ori','pea','rol','ror','roxl',
+ 'roxr','rtr','rts','sbcd','scc','scs','seq','sge',
+ 'sgt','shi','sle','sls','slt','smi','sne',
+ 'spl','st','svc','svs','sf','sub','suba','subi','subq',
+ 'subx','swap','tas','trap','trapv','tst','unlk',
+ 'rte','reset','stop',
+ { mc68010 instructions }
+ 'bkpt','movec','moves','rtd',
+ { mc68020 instructions }
+ 'bfchg','bfclr','bfexts','bfextu','bfffo',
+ 'bfins','bfset','bftst','callm','cas','cas2',
+ 'chk2','cmp2','divsl','divul','extb','pack','rtm',
+ 'trapcc','tracs','trapeq','trapf','trapge','trapgt',
+ 'traphi','traple','trapls','traplt','trapmi','trapne',
+ 'trappl','trapt','trapvc','trapvs','unpk',
+ { fpu processor instructions - directly supported only. }
+ { ieee aware and misc. condition codes not supported }
+ 'fabs','fadd',
+ 'fbeq','fbne','fbngt','fbgt','fbge','fbnge',
+ 'fblt','fbnlt','fble','fbgl','fbngl','fbgle','fbngle',
+ 'fdbeq','fdbne','fdbgt','fdbngt','fdbge','fdbnge',
+ 'fdblt','fdbnlt','fdble','fdbgl','fdbngl','fdbgle','fdbngle',
+ 'fseq','fsne','fsgt','fsngt','fsge','fsnge',
+ 'fslt','fsnlt','fsle','fsgl','fsngl','fsgle','fsngle',
+ 'fcmp','fdiv','fmove','fmovem',
+ 'fmul','fneg','fnop','fsqrt','fsub','fsgldiv',
+ 'fsflmul','ftst',
+ 'ftrapeq','ftrapne','ftrapgt','ftrapngt','ftrapge','ftrapnge',
+ 'ftraplt','ftrapnlt','ftraple','ftrapgl','ftrapngl','ftrapgle','ftrapngle',
+ { protected instructions }
+ 'cprestore','cpsave',
+ { fpu unit protected instructions }
+ { and 68030/68851 common mmu instructions }
+ { (this may include 68040 mmu instructions) }
+ 'frestore','fsave','pflush','pflusha','pload','pmove','ptest',
+ { useful for assembly language output }
+ 'label','db','s','b','fb');
+
+ function gas_regnum_search(const s:string):Tregister;
+ function gas_regname(r:Tregister):string;
+
+ implementation
+
+ const
+ gas_regname_table : array[tregisterindex] of string[7] = (
+ {r386att.inc contains the AT&T name of each register.}
+ {$i r68kgas.inc}
+ );
+
+ gas_regname_index : array[tregisterindex] of tregisterindex = (
+ {r386ari.inc contains an index which sorts att_regname_table by
+ ATT name.}
+ {$i r68kgri.inc}
+ );
+
+
+ function findreg_by_gasname(const s:string):byte;
+ var
+ i,p : tregisterindex;
+ begin
+ {Binary search.}
+ p:=0;
+ i:=regnumber_count_bsstart;
+ repeat
+ if (p+i<=high(tregisterindex)) and (gas_regname_table[gas_regname_index[p+i]]<=s) then
+ p:=p+i;
+ i:=i shr 1;
+ until i=0;
+ if gas_regname_table[gas_regname_index[p]]=s then
+ findreg_by_gasname:=gas_regname_index[p]
+ else
+ findreg_by_gasname:=0;
+ end;
+
+
+ function gas_regnum_search(const s:string):Tregister;
+ begin
+ result:=regnumber_table[findreg_by_gasname(s)];
+ end;
+
+
+ function gas_regname(r:Tregister):string;
+ var
+ p : tregisterindex;
+ begin
+ p:=findreg_by_number(r);
+ if p<>0 then
+ result:=gas_regname_table[p]
+ else
+ result:='%'+generic_regname(r);
+ end;
+
+end.
diff --git a/closures/compiler/m68k/m68kreg.dat b/closures/compiler/m68k/m68kreg.dat
new file mode 100644
index 0000000000..9ff2289155
--- /dev/null
+++ b/closures/compiler/m68k/m68kreg.dat
@@ -0,0 +1,44 @@
+;
+; Motorola 680x0 registers
+;
+; layout
+; <name>,<type>,<value>,<stdname>,<stabidx>
+;
+NO,$00,$00,INVALID,INVALID,-1
+
+D0,$01,$00,d0,%d0,0
+D1,$01,$01,d1,%d1,1
+D2,$01,$02,d2,%d2,2
+D3,$01,$03,d3,%d3,3
+D4,$01,$04,d4,%d4,4
+D5,$01,$05,d5,%d5,5
+D6,$01,$06,d6,%d6,6
+D7,$01,$07,d7,%d7,7
+
+FP0,$02,$00,fp0,%fp0,16
+FP1,$02,$01,fp1,%fp1,17
+FP2,$02,$02,fp2,%fp2,18
+FP3,$02,$03,fp3,%fp3,19
+FP4,$02,$04,fp4,%fp4,20
+FP5,$02,$05,fp5,%fp5,21
+FP6,$02,$06,fp6,%fp6,22
+FP7,$02,$07,fp7,%fp7,23
+
+PC,$05,$00,pc,%pc,24
+CCR,$05,$01,ccr,%ccr,0
+FPCR,$05,$02,fpcr,%fpcr,0
+SR,$05,$03,sr,%sr,0
+SSP,$05,$04,ssp,%ssp,0
+DFC,$05,$05,dfc,%dfc,0
+SFC,$05,$06,sfc,%sfc,0
+VBR,$05,$07,vbr,%vbr,0
+FPSR,$05,$08,fpsr,%fpsr,0
+
+A0,$06,$00,a0,%a0,8
+A1,$06,$01,a1,%a1,9
+A2,$06,$02,a2,%a2,10
+A3,$06,$03,a3,%a3,11
+A4,$06,$04,a4,%a4,12
+A5,$06,$05,a5,%a5,13
+A6,$06,$06,a6,%a6,14
+SP,$06,$07,sp,%sp,15
diff --git a/closures/compiler/m68k/n68kadd.pas b/closures/compiler/m68k/n68kadd.pas
new file mode 100644
index 0000000000..0c243c55ca
--- /dev/null
+++ b/closures/compiler/m68k/n68kadd.pas
@@ -0,0 +1,546 @@
+{
+ Copyright (c) 2000-2002 by Florian Klaempfl and Jonas Maebe
+
+ Code generation for add nodes on the Motorola 680x0 family
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit n68kadd;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,nadd,ncgadd,cpubase;
+
+
+ type
+ t68kaddnode = class(tcgaddnode)
+ private
+ function getresflags(unsigned: boolean) : tresflags;
+ protected
+ procedure second_addfloat;override;
+ procedure second_cmpfloat;override;
+ procedure second_cmpordinal;override;
+ procedure second_cmpsmallset;override;
+ procedure second_cmp64bit;override;
+ procedure second_cmpboolean;override;
+ end;
+
+
+implementation
+
+ uses
+ globtype,systems,
+ cutils,verbose,globals,
+ symconst,symdef,paramgr,
+ aasmbase,aasmtai,aasmdata,aasmcpu,defutil,htypechk,
+ cgbase,cpuinfo,pass_1,pass_2,regvars,
+ cpupara,cgutils,procinfo,
+ ncon,nset,
+ ncgutil,tgobj,rgobj,rgcpu,cgobj,cg64f32;
+
+{*****************************************************************************
+ Helpers
+*****************************************************************************}
+
+
+ function t68kaddnode.getresflags(unsigned : boolean) : tresflags;
+ begin
+ case nodetype of
+ equaln : getresflags:=F_E;
+ unequaln : getresflags:=F_NE;
+ else
+ if not(unsigned) then
+ begin
+ if nf_swapped in flags then
+ case nodetype of
+ ltn : getresflags:=F_G;
+ lten : getresflags:=F_GE;
+ gtn : getresflags:=F_L;
+ gten : getresflags:=F_LE;
+ end
+ else
+ case nodetype of
+ ltn : getresflags:=F_L;
+ lten : getresflags:=F_LE;
+ gtn : getresflags:=F_G;
+ gten : getresflags:=F_GE;
+ end;
+ end
+ else
+ begin
+ if nf_swapped in flags then
+ case nodetype of
+ ltn : getresflags:=F_A;
+ lten : getresflags:=F_AE;
+ gtn : getresflags:=F_B;
+ gten : getresflags:=F_BE;
+ end
+ else
+ case nodetype of
+ ltn : getresflags:=F_B;
+ lten : getresflags:=F_BE;
+ gtn : getresflags:=F_A;
+ gten : getresflags:=F_AE;
+ end;
+ end;
+ end;
+ end;
+
+{*****************************************************************************
+ AddFloat
+*****************************************************************************}
+
+ procedure t68kaddnode.second_addfloat;
+ var
+ op : TAsmOp;
+ cmpop : boolean;
+ begin
+ pass_left_right;
+
+ cmpop:=false;
+ case nodetype of
+ addn :
+ op:=A_FADD;
+ muln :
+ op:=A_FMUL;
+ subn :
+ op:=A_FSUB;
+ slashn :
+ op:=A_FDIV;
+ ltn,lten,gtn,gten,
+ equaln,unequaln :
+ begin
+// op:=A_FCMPO;
+ cmpop:=true;
+ end;
+ else
+ internalerror(200403182);
+ end;
+
+ // get the operands in the correct order, there are no special cases
+ // here, everything is register-based
+ if nf_swapped in flags then
+ swapleftright;
+
+ // put both operands in a register
+ location_force_fpureg(current_asmdata.CurrAsmList,right.location,true);
+ location_force_fpureg(current_asmdata.CurrAsmList,left.location,true);
+
+ // initialize de result
+ if not cmpop then
+ begin
+ location_reset(location,LOC_FPUREGISTER,def_cgsize(resultdef));
+ if left.location.loc = LOC_FPUREGISTER then
+ location.register := left.location.register
+ else if right.location.loc = LOC_FPUREGISTER then
+ location.register := right.location.register
+ else
+ location.register := cg.getfpuregister(current_asmdata.CurrAsmList,location.size);
+ end
+ else
+ begin
+ location_reset(location,LOC_FLAGS,OS_NO);
+ // FIX ME!
+// location.resflags := getresflags;
+ end;
+
+ // emit the actual operation
+ if not cmpop then
+ begin
+ {
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(op,
+ location.register,left.location.register,
+ right.location.register))
+ }
+ end
+ else
+ begin
+{ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(op,
+ newreg(R_SPECIALREGISTER,location.resflags.cr,R_SUBNONE),left.location.register,right.location.register))}
+ end;
+ end;
+
+
+ procedure t68kaddnode.second_cmpfloat;
+ begin
+ pass_left_right;
+
+{
+ if (nf_swapped in flags) then
+ swapleftright;
+}
+ { force fpureg as location, left right doesn't matter
+ as both will be in a fpureg }
+ location_force_fpureg(current_asmdata.CurrAsmList,left.location,true);
+ location_force_fpureg(current_asmdata.CurrAsmList,right.location,true);
+
+ location_reset(location,LOC_FLAGS,OS_NO);
+ location.resflags:=getresflags(true);
+{
+ if nodetype in [equaln,unequaln] then
+ current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_CMF,
+ left.location.register,right.location.register),
+ cgsize2fpuoppostfix[def_cgsize(resultdef)]))
+ else
+ current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_CMFE,
+ left.location.register,right.location.register),
+ cgsize2fpuoppostfix[def_cgsize(resultdef)]));
+
+ location_reset(location,LOC_FLAGS,OS_NO);
+ location.resflags:=getresflags(false);
+}
+ end;
+
+
+
+
+{*****************************************************************************
+ Smallsets
+*****************************************************************************}
+
+ procedure t68kaddnode.second_cmpsmallset;
+ var
+ tmpreg : tregister;
+ begin
+ location_reset(location,LOC_FLAGS,OS_NO);
+
+ case nodetype of
+ equaln,
+ unequaln :
+ begin
+ {emit_compare(true);}
+ end;
+ lten,gten:
+ begin
+ If (not(nf_swapped in flags) and
+ (nodetype = lten)) or
+ ((nf_swapped in flags) and
+ (nodetype = gten)) then
+ swapleftright;
+ // now we have to check whether left >= right
+ tmpreg := cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+ if left.location.loc = LOC_CONSTANT then
+ begin
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_AND,OS_INT,
+ not(left.location.value),right.location.register,tmpreg);
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg(A_TST,S_L,tmpreg));
+ // the two instructions above should be folded together by
+ // the peepholeoptimizer
+ end
+ else
+ begin
+ if right.location.loc = LOC_CONSTANT then
+ begin
+ cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_INT,
+ aword(right.location.value),tmpreg);
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_AND,S_L,
+ tmpreg,left.location.register));
+ end
+ else
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_AND,S_L,
+ right.location.register,left.location.register));
+ end;
+// cg.ungetcpuregister(current_asmdata.CurrAsmList,tmpreg);
+ location.resflags := getresflags(true);
+ end;
+ else
+ internalerror(2002072701);
+ end;
+
+
+ end;
+
+
+{*****************************************************************************
+ Ordinals
+*****************************************************************************}
+
+ procedure t68kaddnode.second_cmpordinal;
+ var
+ unsigned : boolean;
+ useconst : boolean;
+ tmpreg : tregister;
+ op : tasmop;
+ begin
+// writeln('second_cmpordinal');
+ pass_left_right;
+ { set result location }
+ location_reset(location,LOC_JUMP,OS_NO);
+
+ { load values into registers (except constants) }
+ force_reg_left_right(true, false);
+
+ { determine if the comparison will be unsigned }
+ unsigned:=not(is_signed(left.resultdef)) or
+ not(is_signed(right.resultdef));
+
+ // get the constant on the right if there is one
+ if (left.location.loc = LOC_CONSTANT) then
+ swapleftright;
+ // can we use an immediate, or do we have to load the
+ // constant in a register first?
+ if (right.location.loc = LOC_CONSTANT) then
+ begin
+{$ifdef extdebug}
+ if (right.location.size in [OS_64,OS_S64]) and (hi(right.location.value64)<>0) and ((hi(right.location.value64)<>-1) or unsigned) then
+ internalerror(2002080301);
+{$endif extdebug}
+ if (nodetype in [equaln,unequaln]) then
+ if (unsigned and
+ (right.location.value > high(word))) or
+ (not unsigned and
+ (longint(right.location.value) < low(smallint)) or
+ (longint(right.location.value) > high(smallint))) then
+ { we can then maybe use a constant in the 'othersigned' case
+ (the sign doesn't matter for // equal/unequal)}
+ unsigned := not unsigned;
+
+ if (unsigned and
+ ((right.location.value) <= high(word))) or
+ (not(unsigned) and
+ (longint(right.location.value) >= low(smallint)) and
+ (longint(right.location.value) <= high(smallint))) then
+ useconst := true
+ else
+ begin
+ useconst := false;
+ tmpreg := cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+ cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_INT,
+ aword(right.location.value),tmpreg);
+ end
+ end
+ else
+ useconst := false;
+ location.loc := LOC_FLAGS;
+ location.resflags := getresflags(unsigned);
+ op := A_CMP;
+ if (right.location.loc = LOC_CONSTANT) then
+ if useconst then
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(op,S_L,
+ left.location.register,longint(right.location.value)))
+ else
+ begin
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op,S_L,
+ left.location.register,tmpreg));
+// cg.ungetcpuregister(current_asmdata.CurrAsmList,tmpreg);
+ end
+ else
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op,S_L,
+ left.location.register,right.location.register));
+ end;
+
+{*****************************************************************************
+ Boolean
+*****************************************************************************}
+
+ procedure t68kaddnode.second_cmpboolean;
+ var
+ cgop : TOpCg;
+ cgsize : TCgSize;
+ isjump : boolean;
+ otl,ofl : tasmlabel;
+ begin
+// writeln('second_cmpboolean');
+ if (torddef(left.resultdef).ordtype in [pasbool8,bool8bit]) or
+ (torddef(right.resultdef).ordtype in [pasbool8,bool8bit]) then
+ cgsize:=OS_8
+ else
+ if (torddef(left.resultdef).ordtype in [pasbool16,bool16bit]) or
+ (torddef(right.resultdef).ordtype in [pasbool16,bool16bit]) then
+ cgsize:=OS_16
+ else
+ cgsize:=OS_32;
+
+ if (cs_full_boolean_eval in current_settings.localswitches) or
+ (nodetype in [unequaln,ltn,lten,gtn,gten,equaln,xorn]) then
+ begin
+ if left.nodetype in [ordconstn,realconstn] then
+ swapleftright;
+
+ isjump:=(left.location.loc=LOC_JUMP);
+ if isjump then
+ begin
+ otl:=current_procinfo.CurrTrueLabel;
+ current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
+ ofl:=current_procinfo.CurrFalseLabel;
+ current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel);
+ end;
+ secondpass(left);
+ if left.location.loc in [LOC_FLAGS,LOC_JUMP] then begin
+// writeln('ajjaj');
+ location_force_reg(current_asmdata.CurrAsmList,left.location,cgsize,false);
+// writeln('reccs?');
+ end;
+ if isjump then
+ begin
+ current_procinfo.CurrTrueLabel:=otl;
+ current_procinfo.CurrFalseLabel:=ofl;
+ end;
+
+ isjump:=(right.location.loc=LOC_JUMP);
+ if isjump then
+ begin
+ otl:=current_procinfo.CurrTrueLabel;
+ current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
+ ofl:=current_procinfo.CurrFalseLabel;
+ current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel);
+ end;
+ secondpass(right);
+ if right.location.loc in [LOC_FLAGS,LOC_JUMP] then
+ location_force_reg(current_asmdata.CurrAsmList,right.location,cgsize,false);
+ if isjump then
+ begin
+ current_procinfo.CurrTrueLabel:=otl;
+ current_procinfo.CurrFalseLabel:=ofl;
+ end;
+
+ location_reset(location,LOC_FLAGS,OS_NO);
+
+ force_reg_left_right(true,false);
+
+ if (left.location.loc = LOC_CONSTANT) then
+ swapleftright;
+
+ if (right.location.loc <> LOC_CONSTANT) then
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CMP,S_L,
+ left.location.register,right.location.register))
+ else
+ current_asmdata.CurrAsmList.concat(taicpu.op_const_reg(A_CMP,S_L,
+ longint(right.location.value),left.location.register));
+ location.resflags := getresflags(true);
+ end;
+
+ //release_reg_left_right;
+ end;
+
+
+{*****************************************************************************
+ 64-bit
+*****************************************************************************}
+
+ procedure t68kaddnode.second_cmp64bit;
+ begin
+ // writeln('second_cmp64bit');
+ pass_left_right;
+
+
+// load_left_right(true,false);
+(*
+ case nodetype of
+ ltn,lten,
+ gtn,gten:
+ begin
+ emit_cmp64_hi;
+ firstjmp64bitcmp;
+ emit_cmp64_lo;
+ secondjmp64bitcmp;
+ end;
+ equaln,unequaln:
+ begin
+ // instead of doing a complicated compare, do
+ // (left.hi xor right.hi) or (left.lo xor right.lo)
+ // (somewhate optimized so that no superfluous 'mr's are
+ // generated)
+ if (left.location.loc = LOC_CONSTANT) then
+ swapleftright;
+ if (right.location.loc = LOC_CONSTANT) then
+ begin
+ if left.location.loc = LOC_REGISTER then
+ begin
+ tempreg64.reglo := left.location.register64.reglo;
+ tempreg64.reghi := left.location.register64.reghi;
+ end
+ else
+ begin
+ if (aword(right.location.valueqword) <> 0) then
+ tempreg64.reglo := cg.getintregister(current_asmdata.CurrAsmList)
+ else
+ tempreg64.reglo := left.location.register64.reglo;
+ if ((right.location.valueqword shr 32) <> 0) then
+ tempreg64.reghi := cg.getintregister(current_asmdata.CurrAsmList)
+ else
+ tempreg64.reghi := left.location.register64.reghi;
+ end;
+
+ if (aword(right.location.valueqword) <> 0) then
+ { negative values can be handled using SUB, }
+ { positive values < 65535 using XOR. }
+ if (longint(right.location.valueqword) >= -32767) and
+ (longint(right.location.valueqword) < 0) then
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SUB,OS_INT,
+ aword(right.location.valueqword),
+ left.location.register64.reglo,tempreg64.reglo)
+ else
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_XOR,OS_INT,
+ aword(right.location.valueqword),
+ left.location.register64.reglo,tempreg64.reglo);
+
+ if ((right.location.valueqword shr 32) <> 0) then
+ if (longint(right.location.valueqword shr 32) >= -32767) and
+ (longint(right.location.valueqword shr 32) < 0) then
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SUB,OS_INT,
+ aword(right.location.valueqword shr 32),
+ left.location.register64.reghi,tempreg64.reghi)
+ else
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_XOR,OS_INT,
+ aword(right.location.valueqword shr 32),
+ left.location.register64.reghi,tempreg64.reghi);
+ end
+ else
+ begin
+ tempreg64.reglo := cg.getintregister(current_asmdata.CurrAsmList);
+ tempreg64.reghi := cg.getintregister(current_asmdata.CurrAsmList);
+ cg64.a_op64_reg_reg_reg(current_asmdata.CurrAsmList,OP_XOR,
+ left.location.register64,right.location.register64,
+ tempreg64);
+ end;
+
+ cg.a_reg_alloc(current_asmdata.CurrAsmList,R_0);
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_OR_,R_0,
+ tempreg64.reglo,tempreg64.reghi));
+ cg.a_reg_dealloc(current_asmdata.CurrAsmList,R_0);
+ if (tempreg64.reglo <> left.location.register64.reglo) then
+ cg.ungetregister(current_asmdata.CurrAsmList,tempreg64.reglo);
+ if (tempreg64.reghi <> left.location.register64.reghi) then
+ cg.ungetregister(current_asmdata.CurrAsmList,tempreg64.reghi);
+
+ location_reset(location,LOC_FLAGS,OS_NO);
+ location.resflags := getresflags;
+ end;
+ else
+ internalerror(2002072803);
+ end;
+
+
+ { set result location }
+ { (emit_compare sets it to LOC_FLAGS for compares, so set the }
+ { real location only now) (JM) }
+ if cmpop and
+ not(nodetype in [equaln,unequaln]) then
+ location_reset(location,LOC_JUMP,OS_NO);
+*)
+ location_reset(location,LOC_JUMP,OS_NO);
+ // writeln('second_cmp64_exit');
+ end;
+
+
+begin
+ caddnode:=t68kaddnode;
+end.
diff --git a/closures/compiler/m68k/n68kcal.pas b/closures/compiler/m68k/n68kcal.pas
new file mode 100644
index 0000000000..d9763acd9a
--- /dev/null
+++ b/closures/compiler/m68k/n68kcal.pas
@@ -0,0 +1,86 @@
+{
+ Copyright (c) 2002 by Florian Klaempfl
+
+ Implements the M68K specific part of call nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit n68kcal;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ symdef,node,ncal,ncgcal;
+
+ type
+ tm68kcallnode = class(tcgcallnode)
+ procedure do_syscall;override;
+ end;
+
+
+implementation
+
+ uses
+ globtype,systems,
+ cutils,verbose,globals,
+ symconst,symbase,symsym,symtable,defutil,paramgr,parabase,
+ cgbase,pass_2,
+ cpuinfo,cpubase,aasmbase,aasmtai,aasmdata,aasmcpu,
+ nmem,nld,ncnv,
+ ncgutil,cgutils,cgobj,tgobj,regvars,rgobj,rgcpu,
+ cg64f32,cgcpu,cpupi,procinfo;
+
+
+ procedure tm68kcallnode.do_syscall;
+ var
+ tmpref: treference;
+ tmpref2: treference;
+ begin
+ case target_info.system of
+ system_m68k_amiga:
+ begin
+ if po_syscall_legacy in tprocdef(procdefinition).procoptions then
+ begin
+ { save base pointer on syscalls }
+ { FIXME: probably this will need to be extended to save all regs (KB) }
+ reference_reset_base(tmpref2, NR_STACK_POINTER_REG, 0, 4);
+ tmpref2.direction := dir_dec;
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_ref(A_MOVE,S_L,NR_FRAME_POINTER_REG,tmpref2));
+
+ { the actuall call }
+ reference_reset_base(tmpref,NR_A6,-tprocdef(procdefinition).extnumber,4);
+ current_asmdata.CurrAsmList.concat(taicpu.op_ref(A_JSR,S_NO,tmpref));
+
+ { restore frame pointer }
+ reference_reset_base(tmpref2, NR_STACK_POINTER_REG, 0, 4);
+ tmpref2.direction := dir_inc;
+ current_asmdata.CurrAsmList.concat(taicpu.op_ref_reg(A_MOVE,S_L,tmpref2,NR_FRAME_POINTER_REG));
+ end
+ else
+ internalerror(2005010403);
+ end;
+ else
+ internalerror(2004042901);
+ end;
+ end;
+
+
+begin
+ ccallnode:=tm68kcallnode;
+end.
diff --git a/closures/compiler/m68k/n68kcnv.pas b/closures/compiler/m68k/n68kcnv.pas
new file mode 100644
index 0000000000..8dde10c83d
--- /dev/null
+++ b/closures/compiler/m68k/n68kcnv.pas
@@ -0,0 +1,257 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate m68k assembler for type converting nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit n68kcnv;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,ncnv,ncgcnv,defcmp;
+
+ type
+ tm68ktypeconvnode = class(tcgtypeconvnode)
+ protected
+ function first_int_to_real: tnode; override;
+ procedure second_int_to_real;override;
+ procedure second_int_to_bool;override;
+// procedure pass_generate_code;override;
+ end;
+
+implementation
+
+ uses
+ verbose,globals,systems,
+ symconst,symdef,aasmbase,aasmtai,aasmdata,
+ defutil,
+ cgbase,pass_1,pass_2,
+ ncon,ncal,
+ ncgutil,
+ cpubase,aasmcpu,
+ rgobj,tgobj,cgobj,cgutils,globtype,cgcpu;
+
+
+{*****************************************************************************
+ FirstTypeConv
+*****************************************************************************}
+
+ function tm68ktypeconvnode.first_int_to_real: tnode;
+ var
+ fname: string[32];
+ begin
+ { In case we are in emulation mode, we must
+ always call the helpers
+ }
+ if (cs_fp_emulation in current_settings.moduleswitches) then
+ begin
+ result := inherited first_int_to_real;
+ exit;
+ end
+ else
+ { converting a 64bit integer to a float requires a helper }
+ if is_64bitint(left.resultdef) then
+ begin
+ if is_signed(left.resultdef) then
+ fname := 'fpc_int64_to_double'
+ else
+ fname := 'fpc_qword_to_double';
+ result := ccallnode.createintern(fname,ccallparanode.create(
+ left,nil));
+ left:=nil;
+ firstpass(result);
+ exit;
+ end
+ else
+ { other integers are supposed to be 32 bit }
+ begin
+ if is_signed(left.resultdef) then
+ inserttypeconv(left,s32inttype)
+ else
+ { the fpu always considers 32-bit values as signed
+ therefore we need to call the helper in case of
+ a cardinal value.
+ }
+ begin
+ fname := 'fpc_longword_to_double';
+ result := ccallnode.createintern(fname,ccallparanode.create(
+ left,nil));
+ left:=nil;
+ firstpass(result);
+ exit;
+ end;
+ firstpass(left);
+ end;
+ result := nil;
+ location.loc:=LOC_FPUREGISTER;
+ end;
+
+
+{*****************************************************************************
+ SecondTypeConv
+*****************************************************************************}
+
+
+
+ procedure tm68ktypeconvnode.second_int_to_real;
+
+ var
+ tempconst: trealconstnode;
+ ref: treference;
+ valuereg, tempreg, leftreg, tmpfpureg: tregister;
+ signed : boolean;
+ scratch_used : boolean;
+ opsize : tcgsize;
+ begin
+ scratch_used := false;
+ location_reset(location,LOC_FPUREGISTER,def_cgsize(resultdef));
+ signed := is_signed(left.resultdef);
+ opsize := def_cgsize(left.resultdef);
+ { has to be handled by a helper }
+ if is_64bitint(left.resultdef) then
+ internalerror(200110011);
+ { has to be handled by a helper }
+ if not signed then
+ internalerror(20020814);
+
+ location.register:=cg.getfpuregister(current_asmdata.CurrAsmList,opsize);
+ if not(left.location.loc in [LOC_REGISTER,LOC_CREGISTER,LOC_REFERENCE,LOC_CREFERENCE]) then
+ location_force_reg(current_asmdata.CurrAsmList,left.location,OS_INT,false);
+ case left.location.loc of
+ LOC_REGISTER, LOC_CREGISTER:
+ begin
+ leftreg := left.location.register;
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FMOVE,TCGSize2OpSize[opsize],leftreg,
+ location.register));
+ end;
+ LOC_REFERENCE,LOC_CREFERENCE:
+ begin
+ current_asmdata.CurrAsmList.concat(taicpu.op_ref_reg(A_FMOVE,TCGSize2OpSize[opsize],
+ left.location.reference,location.register));
+ end
+ else
+ internalerror(200110012);
+ end;
+ end;
+
+
+ procedure tm68ktypeconvnode.second_int_to_bool;
+ var
+ hreg1,
+ hreg2 : tregister;
+ resflags : tresflags;
+ opsize : tcgsize;
+ newsize : tcgsize;
+ begin
+ secondpass(left);
+
+{ TODO: needs LOC_JUMP support, because called for bool_to_bool from ncgcnv }
+
+ { Explicit typecasts from any ordinal type to a boolean type }
+ { must not change the ordinal value }
+ if (nf_explicit in flags) and
+ not(left.location.loc in [LOC_FLAGS,LOC_JUMP]) then
+ begin
+ location_copy(location,left.location);
+ newsize:=def_cgsize(resultdef);
+ { change of size? change sign only if location is LOC_(C)REGISTER? Then we have to sign/zero-extend }
+ if (tcgsize2size[newsize]<>tcgsize2size[left.location.size]) or
+ ((newsize<>left.location.size) and (location.loc in [LOC_REGISTER,LOC_CREGISTER])) then
+ location_force_reg(current_asmdata.CurrAsmList,location,newsize,true)
+ else
+ location.size:=newsize;
+{ ACTIVATE when loc_jump support is added
+ current_procinfo.CurrTrueLabel:=oldTrueLabel;
+ current_procinfo.CurrFalseLabel:=oldFalseLabel;
+}
+ exit;
+ end;
+
+ location_reset(location,LOC_REGISTER,def_cgsize(left.resultdef));
+ opsize := def_cgsize(left.resultdef);
+ case left.location.loc of
+ LOC_CREFERENCE,LOC_REFERENCE :
+ begin
+ { can we optimize it, or do we need to fix the ref. ? }
+ if isvalidrefoffset(left.location.reference) then
+ begin
+ current_asmdata.CurrAsmList.concat(taicpu.op_ref(A_TST,TCGSize2OpSize[opsize],
+ left.location.reference));
+ end
+ else
+ begin
+ hreg2:=cg.getintregister(current_asmdata.CurrAsmList,opsize);
+ cg.a_load_ref_reg(current_asmdata.CurrAsmList,opsize,opsize,
+ left.location.reference,hreg2);
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg(A_TST,TCGSize2OpSize[opsize],hreg2));
+// cg.ungetcpuregister(current_asmdata.CurrAsmList,hreg2);
+ end;
+// reference_release(current_asmdata.CurrAsmList,left.location.reference);
+ resflags:=F_NE;
+ hreg1:=cg.getintregister(current_asmdata.CurrAsmList,opsize);
+ end;
+ LOC_REGISTER,LOC_CREGISTER :
+ begin
+ hreg2:=left.location.register;
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg(A_TST,TCGSize2OpSize[opsize],hreg2));
+// cg.ungetcpuregister(current_asmdata.CurrAsmList,hreg2);
+ hreg1:=cg.getintregister(current_asmdata.CurrAsmList,opsize);
+ resflags:=F_NE;
+ end;
+ LOC_FLAGS :
+ begin
+ hreg1:=cg.getintregister(current_asmdata.CurrAsmList,opsize);
+ resflags:=left.location.resflags;
+ end;
+ else
+ internalerror(200512182);
+ end;
+ cg.g_flags2reg(current_asmdata.CurrAsmList,location.size,resflags,hreg1);
+ if (is_cbool(resultdef)) then
+ cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_NEG,location.size,hreg1,hreg1);
+ location.register := hreg1;
+ end;
+
+{
+ procedure tm68ktypeconvnode.pass_generate_code;
+{$ifdef TESTOBJEXT2}
+ var
+ r : preference;
+ nillabel : plabel;
+{$endif TESTOBJEXT2}
+ begin
+ { this isn't good coding, I think tc_bool_2_int, shouldn't be }
+ { type conversion (FK) }
+
+ if not(convtype in [tc_bool_2_int,tc_bool_2_bool]) then
+ begin
+ secondpass(left);
+ location_copy(location,left.location);
+ if codegenerror then
+ exit;
+ end;
+ second_call_helper(convtype);
+ end;
+}
+
+begin
+ ctypeconvnode:=tm68ktypeconvnode;
+end.
diff --git a/closures/compiler/m68k/n68kmat.pas b/closures/compiler/m68k/n68kmat.pas
new file mode 100644
index 0000000000..453ec29895
--- /dev/null
+++ b/closures/compiler/m68k/n68kmat.pas
@@ -0,0 +1,361 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate 680x0 assembler for math nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit n68kmat;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,nmat,ncgmat,cpubase,cgbase;
+
+ type
+
+
+ tm68knotnode = class(tnotnode)
+ procedure pass_generate_code;override;
+ end;
+
+ tm68kmoddivnode = class(tcgmoddivnode)
+ procedure emit_div_reg_reg(signed: boolean;denum,num : tregister);override;
+ procedure emit_mod_reg_reg(signed: boolean;denum,num : tregister);override;
+ end;
+
+ tm68kshlshrnode = class(tshlshrnode)
+ procedure pass_generate_code;override;
+ { everything will be handled in pass_2 }
+ function first_shlshr64bitint: tnode; override;
+ end;
+
+
+implementation
+
+ uses
+ globtype,systems,
+ cutils,verbose,globals,
+ symconst,symdef,aasmbase,aasmtai,aasmdata,aasmcpu,
+ pass_1,pass_2,procinfo,
+ ncon,
+ cpuinfo,paramgr,defutil,parabase,
+ tgobj,ncgutil,cgobj,cgutils,rgobj,rgcpu,cgcpu,cg64f32;
+
+
+
+
+{*****************************************************************************
+ TM68KNOTNODE
+*****************************************************************************}
+
+ procedure tm68knotnode.pass_generate_code;
+ var
+ hl : tasmlabel;
+ opsize : tcgsize;
+ begin
+ opsize:=def_cgsize(resultdef);
+ if is_boolean(resultdef) then
+ begin
+ { the second pass could change the location of left }
+ { if it is a register variable, so we've to do }
+ { this before the case statement }
+ if left.location.loc<>LOC_JUMP then
+ secondpass(left);
+
+ case left.location.loc of
+ LOC_JUMP :
+ begin
+ location_reset(location,LOC_JUMP,OS_NO);
+ hl:=current_procinfo.CurrTrueLabel;
+ current_procinfo.CurrTrueLabel:=current_procinfo.CurrFalseLabel;
+ current_procinfo.CurrFalseLabel:=hl;
+ secondpass(left);
+ maketojumpbool(current_asmdata.CurrAsmList,left,lr_load_regvars);
+ hl:=current_procinfo.CurrTrueLabel;
+ current_procinfo.CurrTrueLabel:=current_procinfo.CurrFalseLabel;
+ current_procinfo.CurrFalseLabel:=hl;
+ end;
+ LOC_FLAGS :
+ begin
+ location_copy(location,left.location);
+// location_release(current_asmdata.CurrAsmList,left.location);
+ inverse_flags(location.resflags);
+ end;
+ LOC_CONSTANT,
+ LOC_REGISTER,
+ LOC_CREGISTER,
+ LOC_REFERENCE,
+ LOC_CREFERENCE :
+ begin
+ location_force_reg(current_asmdata.CurrAsmList,left.location,def_cgsize(resultdef),true);
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg(A_TST,tcgsize2opsize[opsize],left.location.register));
+// location_release(current_asmdata.CurrAsmList,left.location);
+ location_reset(location,LOC_FLAGS,OS_NO);
+ location.resflags:=F_E;
+ end;
+ else
+ internalerror(200203224);
+ end;
+ end
+ else if is_64bitint(left.resultdef) then
+ begin
+ secondpass(left);
+ location_copy(location,left.location);
+ location_force_reg(current_asmdata.CurrAsmList,location,OS_64,false);
+ cg64.a_op64_loc_reg(current_asmdata.CurrAsmList,OP_NOT,OS_64,location,
+ joinreg64(location.register64.reglo,location.register64.reghi));
+ end
+ else
+ begin
+ secondpass(left);
+ location_force_reg(current_asmdata.CurrAsmList,left.location,def_cgsize(left.resultdef),false);
+ location_copy(location,left.location);
+ if location.loc=LOC_CREGISTER then
+ location.register := cg.getintregister(current_asmdata.CurrAsmList,opsize);
+ { perform the NOT operation }
+ cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_NOT,opsize,location.register,left.location.register);
+ end;
+ end;
+
+
+{*****************************************************************************
+ TM68KMODDIVNODE
+*****************************************************************************}
+ procedure tm68kmoddivnode.emit_div_reg_reg(signed: boolean;denum,num : tregister);
+ var
+ continuelabel : tasmlabel;
+ reg_d0,reg_d1 : tregister;
+ paraloc1 : tcgpara;
+ begin
+ { no RTL call, so inline a zero denominator verification }
+ if current_settings.cputype <> cpu_MC68000 then
+ begin
+ { verify if denominator is zero }
+ current_asmdata.getjumplabel(continuelabel);
+ { compare against zero, if not zero continue }
+ cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,OS_S32,OC_NE,0,denum,continuelabel);
+// paraloc1.init;
+// cg.a_load_const_cgpara(current_asmdata.CurrAsmList,OS_S32,200,paramanager.getintparaloc(pocall_default,1,paraloc1));
+
+ cg.a_call_name(current_asmdata.CurrAsmList,'FPC_HANDLEERROR',false);
+ cg.a_label(current_asmdata.CurrAsmList, continuelabel);
+ if signed then
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_DIVS,S_L,denum,num))
+ else
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_DIVU,S_L,denum,num));
+ { result should be in denuminator }
+ cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_INT,OS_INT,num,denum);
+ end
+ else
+ begin
+ { On MC68000/68010 mw must pass through RTL routines }
+ reg_d0:=NR_D0;
+ cg.getcpuregister(current_asmdata.CurrAsmList,NR_D0);
+ reg_d1:=NR_D1;
+ cg.getcpuregister(current_asmdata.CurrAsmList,NR_D1);
+ { put numerator in d0 }
+ cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_INT,OS_INT,num,reg_d0);
+ { put denum in D1 }
+ cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_INT,OS_INT,denum,reg_d1);
+ if signed then
+ cg.a_call_name(current_asmdata.CurrAsmList,'FPC_DIV_LONGINT',false)
+ else
+ cg.a_call_name(current_asmdata.CurrAsmList,'FPC_DIV_CARDINAL',false);
+ cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_INT,OS_INT,reg_d0,denum);
+ cg.ungetcpuregister(current_asmdata.CurrAsmList,reg_d0);
+ cg.ungetcpuregister(current_asmdata.CurrAsmList,reg_d1);
+ end;
+ end;
+
+
+ procedure tm68kmoddivnode.emit_mod_reg_reg(signed: boolean;denum,num : tregister);
+ var tmpreg : tregister;
+ continuelabel : tasmlabel;
+ signlabel : tasmlabel;
+ reg_d0,reg_d1 : tregister;
+ begin
+// writeln('emit mod reg reg');
+ { no RTL call, so inline a zero denominator verification }
+ if current_settings.cputype <> cpu_MC68000 then
+ begin
+ { verify if denominator is zero }
+ current_asmdata.getjumplabel(continuelabel);
+ { compare against zero, if not zero continue }
+ cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,OS_S32,OC_NE,0,denum,continuelabel);
+// cg.a_load_const_cgpara(current_asmdata.CurrAsmList, OS_S32,200,paramanager.getintparaloc(pocall_default,1));
+ cg.a_call_name(current_asmdata.CurrAsmList,'FPC_HANDLEERROR',false);
+ cg.a_label(current_asmdata.CurrAsmList, continuelabel);
+
+ tmpreg:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+
+ { we have to prepare the high register with the }
+ { correct sign. i.e we clear it, check if the low dword reg }
+ { which will participate in the division is signed, if so we}
+ { we extend the sign to the high doword register by inverting }
+ { all the bits. }
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg(A_CLR,S_L,tmpreg));
+ current_asmdata.getjumplabel(signlabel);
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg(A_TST,S_L,tmpreg));
+ cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,OS_S32,OC_A,0,tmpreg,signlabel);
+ { its a negative value, therefore change sign }
+ cg.a_label(current_asmdata.CurrAsmList,signlabel);
+ { tmpreg:num / denum }
+
+ if signed then
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_DIVSL,S_L,denum,tmpreg,num))
+ else
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_DIVUL,S_L,denum,tmpreg,num));
+ { remainder in tmpreg }
+ cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_INT,OS_INT,tmpreg,denum);
+// cg.ungetcpuregister(current_asmdata.CurrAsmList,tmpreg);
+ end
+ else
+ begin
+ { On MC68000/68010 mw must pass through RTL routines }
+ Reg_d0:=NR_D0;
+ cg.getcpuregister(current_asmdata.CurrAsmList,NR_D0);
+ Reg_d1:=NR_D1;
+ cg.getcpuregister(current_asmdata.CurrAsmList,NR_D1);
+ { put numerator in d0 }
+ cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_INT,OS_INT,num,Reg_D0);
+ { put denum in D1 }
+ cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_INT,OS_INT,denum,Reg_D1);
+ if signed then
+ cg.a_call_name(current_asmdata.CurrAsmList,'FPC_MOD_LONGINT',false)
+ else
+ cg.a_call_name(current_asmdata.CurrAsmList,'FPC_MOD_CARDINAL',false);
+ cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_INT,OS_INT,Reg_D0,denum);
+ cg.ungetcpuregister(current_asmdata.CurrAsmList,Reg_D0);
+ cg.ungetcpuregister(current_asmdata.CurrAsmList,Reg_D1);
+ end;
+// writeln('exits');
+ end;
+
+
+{*****************************************************************************
+ TM68KSHLRSHRNODE
+*****************************************************************************}
+
+ function tm68kShlShrNode.first_shlshr64bitint:TNode;
+ begin
+ { 2nd pass is our friend }
+ result := nil;
+ end;
+
+
+{ TODO: FIX ME!!! shlshrnode needs review}
+ procedure tm68kshlshrnode.pass_generate_code;
+ var
+ hregister,resultreg,hregister1,
+ hreg64hi,hreg64lo : tregister;
+ op : topcg;
+ shiftval: aint;
+ begin
+ secondpass(left);
+ secondpass(right);
+ if is_64bit(left.resultdef) then
+ begin
+ location_reset(location,LOC_REGISTER,OS_64);
+
+ { load left operator in a register }
+ location_force_reg(current_asmdata.CurrAsmList,left.location,OS_64,false);
+ hreg64hi:=left.location.register64.reghi;
+ hreg64lo:=left.location.register64.reglo;
+
+ shiftval := tordconstnode(right).value.svalue;
+ shiftval := shiftval and 63;
+ if shiftval > 31 then
+ begin
+ if nodetype = shln then
+ begin
+ cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_32,0,hreg64hi);
+ if (shiftval and 31) <> 0 then
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SHL,OS_32,shiftval and 31,hreg64lo,hreg64lo);
+ end
+ else
+ begin
+ cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_32,0,hreg64lo);
+ if (shiftval and 31) <> 0 then
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SHR,OS_32,shiftval and 31,hreg64hi,hreg64hi);
+ end;
+ location.register64.reglo:=hreg64hi;
+ location.register64.reghi:=hreg64lo;
+ end
+ else
+ begin
+ hregister:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
+ if nodetype = shln then
+ begin
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SHR,OS_32,32-shiftval,hreg64lo,hregister);
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SHL,OS_32,shiftval,hreg64hi,hreg64hi);
+ cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,OP_OR,OS_32,hregister,hreg64hi,hreg64hi);
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SHL,OS_32,shiftval,hreg64lo,hreg64lo);
+ end
+ else
+ begin
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SHL,OS_32,32-shiftval,hreg64hi,hregister);
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SHR,OS_32,shiftval,hreg64lo,hreg64lo);
+ cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,OP_OR,OS_32,hregister,hreg64lo,hreg64lo);
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SHR,OS_32,shiftval,hreg64hi,hreg64hi);
+ end;
+ location.register64.reghi:=hreg64hi;
+ location.register64.reglo:=hreg64lo;
+ end;
+ end
+ else
+ begin
+ { load left operators in a register }
+ location_force_reg(current_asmdata.CurrAsmList,left.location,def_cgsize(left.resultdef),true);
+ location_copy(location,left.location);
+ resultreg := location.register;
+ hregister1 := location.register;
+ if (location.loc = LOC_CREGISTER) then
+ begin
+ location.loc := LOC_REGISTER;
+ resultreg := cg.GetIntRegister(current_asmdata.CurrAsmList,OS_INT);
+ location.register := resultreg;
+ end;
+ { determine operator }
+ if nodetype=shln then
+ op:=OP_SHL
+ else
+ op:=OP_SHR;
+ { shifting by a constant directly coded: }
+ if (right.nodetype=ordconstn) then
+ begin
+ if tordconstnode(right).value.svalue and 31<>0 then
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,op,OS_32,tordconstnode(right).value.svalue and 31,hregister1,resultreg)
+ end
+ else
+ begin
+ { load shift count in a register if necessary }
+ location_force_reg(current_asmdata.CurrAsmList,right.location,def_cgsize(right.resultdef),true);
+ cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,op,OS_32,right.location.register,hregister1,resultreg);
+ end;
+ end;
+ end;
+
+
+
+begin
+ cnotnode:=tm68knotnode;
+ cmoddivnode:=tm68kmoddivnode;
+ cshlshrnode:=tm68kshlshrnode;
+end.
diff --git a/closures/compiler/m68k/r68kcon.inc b/closures/compiler/m68k/r68kcon.inc
new file mode 100644
index 0000000000..2e8f8716fb
--- /dev/null
+++ b/closures/compiler/m68k/r68kcon.inc
@@ -0,0 +1,35 @@
+{ don't edit, this file is generated from m68kreg.dat }
+NR_NO = tregister($00000000);
+NR_D0 = tregister($01000000);
+NR_D1 = tregister($01000001);
+NR_D2 = tregister($01000002);
+NR_D3 = tregister($01000003);
+NR_D4 = tregister($01000004);
+NR_D5 = tregister($01000005);
+NR_D6 = tregister($01000006);
+NR_D7 = tregister($01000007);
+NR_FP0 = tregister($02000000);
+NR_FP1 = tregister($02000001);
+NR_FP2 = tregister($02000002);
+NR_FP3 = tregister($02000003);
+NR_FP4 = tregister($02000004);
+NR_FP5 = tregister($02000005);
+NR_FP6 = tregister($02000006);
+NR_FP7 = tregister($02000007);
+NR_PC = tregister($05000000);
+NR_CCR = tregister($05000001);
+NR_FPCR = tregister($05000002);
+NR_SR = tregister($05000003);
+NR_SSP = tregister($05000004);
+NR_DFC = tregister($05000005);
+NR_SFC = tregister($05000006);
+NR_VBR = tregister($05000007);
+NR_FPSR = tregister($05000008);
+NR_A0 = tregister($06000000);
+NR_A1 = tregister($06000001);
+NR_A2 = tregister($06000002);
+NR_A3 = tregister($06000003);
+NR_A4 = tregister($06000004);
+NR_A5 = tregister($06000005);
+NR_A6 = tregister($06000006);
+NR_SP = tregister($06000007);
diff --git a/closures/compiler/m68k/r68kgas.inc b/closures/compiler/m68k/r68kgas.inc
new file mode 100644
index 0000000000..ee47e9ad64
--- /dev/null
+++ b/closures/compiler/m68k/r68kgas.inc
@@ -0,0 +1,35 @@
+{ don't edit, this file is generated from m68kreg.dat }
+'INVALID',
+'%d0',
+'%d1',
+'%d2',
+'%d3',
+'%d4',
+'%d5',
+'%d6',
+'%d7',
+'%fp0',
+'%fp1',
+'%fp2',
+'%fp3',
+'%fp4',
+'%fp5',
+'%fp6',
+'%fp7',
+'%pc',
+'%ccr',
+'%fpcr',
+'%sr',
+'%ssp',
+'%dfc',
+'%sfc',
+'%vbr',
+'%fpsr',
+'%a0',
+'%a1',
+'%a2',
+'%a3',
+'%a4',
+'%a5',
+'%a6',
+'%sp'
diff --git a/closures/compiler/m68k/r68kgri.inc b/closures/compiler/m68k/r68kgri.inc
new file mode 100644
index 0000000000..17ba5dc3a9
--- /dev/null
+++ b/closures/compiler/m68k/r68kgri.inc
@@ -0,0 +1,35 @@
+{ don't edit, this file is generated from m68kreg.dat }
+26,
+27,
+28,
+29,
+30,
+31,
+32,
+18,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+8,
+22,
+9,
+10,
+11,
+12,
+13,
+14,
+15,
+16,
+19,
+25,
+17,
+23,
+33,
+20,
+21,
+24,
+0
diff --git a/closures/compiler/m68k/r68knor.inc b/closures/compiler/m68k/r68knor.inc
new file mode 100644
index 0000000000..c1e8cc2f30
--- /dev/null
+++ b/closures/compiler/m68k/r68knor.inc
@@ -0,0 +1,2 @@
+{ don't edit, this file is generated from m68kreg.dat }
+34
diff --git a/closures/compiler/m68k/r68knum.inc b/closures/compiler/m68k/r68knum.inc
new file mode 100644
index 0000000000..0dc71ce16f
--- /dev/null
+++ b/closures/compiler/m68k/r68knum.inc
@@ -0,0 +1,35 @@
+{ don't edit, this file is generated from m68kreg.dat }
+tregister($00000000),
+tregister($01000000),
+tregister($01000001),
+tregister($01000002),
+tregister($01000003),
+tregister($01000004),
+tregister($01000005),
+tregister($01000006),
+tregister($01000007),
+tregister($02000000),
+tregister($02000001),
+tregister($02000002),
+tregister($02000003),
+tregister($02000004),
+tregister($02000005),
+tregister($02000006),
+tregister($02000007),
+tregister($05000000),
+tregister($05000001),
+tregister($05000002),
+tregister($05000003),
+tregister($05000004),
+tregister($05000005),
+tregister($05000006),
+tregister($05000007),
+tregister($05000008),
+tregister($06000000),
+tregister($06000001),
+tregister($06000002),
+tregister($06000003),
+tregister($06000004),
+tregister($06000005),
+tregister($06000006),
+tregister($06000007)
diff --git a/closures/compiler/m68k/r68krni.inc b/closures/compiler/m68k/r68krni.inc
new file mode 100644
index 0000000000..d6364bb31a
--- /dev/null
+++ b/closures/compiler/m68k/r68krni.inc
@@ -0,0 +1,35 @@
+{ don't edit, this file is generated from m68kreg.dat }
+0,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+8,
+9,
+10,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+20,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+31,
+32,
+33
diff --git a/closures/compiler/m68k/r68ksri.inc b/closures/compiler/m68k/r68ksri.inc
new file mode 100644
index 0000000000..44010ba66a
--- /dev/null
+++ b/closures/compiler/m68k/r68ksri.inc
@@ -0,0 +1,35 @@
+{ don't edit, this file is generated from m68kreg.dat }
+0,
+26,
+27,
+28,
+29,
+30,
+31,
+32,
+18,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+8,
+22,
+9,
+10,
+11,
+12,
+13,
+14,
+15,
+16,
+19,
+25,
+17,
+23,
+33,
+20,
+21,
+24
diff --git a/closures/compiler/m68k/r68ksta.inc b/closures/compiler/m68k/r68ksta.inc
new file mode 100644
index 0000000000..ed8d142fe4
--- /dev/null
+++ b/closures/compiler/m68k/r68ksta.inc
@@ -0,0 +1,35 @@
+{ don't edit, this file is generated from m68kreg.dat }
+-1,
+0,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+16,
+17,
+18,
+19,
+20,
+21,
+22,
+23,
+24,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+8,
+9,
+10,
+11,
+12,
+13,
+14,
+15
diff --git a/closures/compiler/m68k/r68kstd.inc b/closures/compiler/m68k/r68kstd.inc
new file mode 100644
index 0000000000..3719f1f96b
--- /dev/null
+++ b/closures/compiler/m68k/r68kstd.inc
@@ -0,0 +1,35 @@
+{ don't edit, this file is generated from m68kreg.dat }
+'INVALID',
+'d0',
+'d1',
+'d2',
+'d3',
+'d4',
+'d5',
+'d6',
+'d7',
+'fp0',
+'fp1',
+'fp2',
+'fp3',
+'fp4',
+'fp5',
+'fp6',
+'fp7',
+'pc',
+'ccr',
+'fpcr',
+'sr',
+'ssp',
+'dfc',
+'sfc',
+'vbr',
+'fpsr',
+'a0',
+'a1',
+'a2',
+'a3',
+'a4',
+'a5',
+'a6',
+'sp'
diff --git a/closures/compiler/m68k/r68ksup.inc b/closures/compiler/m68k/r68ksup.inc
new file mode 100644
index 0000000000..8677c2a633
--- /dev/null
+++ b/closures/compiler/m68k/r68ksup.inc
@@ -0,0 +1,35 @@
+{ don't edit, this file is generated from m68kreg.dat }
+RS_NO = $00;
+RS_D0 = $00;
+RS_D1 = $01;
+RS_D2 = $02;
+RS_D3 = $03;
+RS_D4 = $04;
+RS_D5 = $05;
+RS_D6 = $06;
+RS_D7 = $07;
+RS_FP0 = $00;
+RS_FP1 = $01;
+RS_FP2 = $02;
+RS_FP3 = $03;
+RS_FP4 = $04;
+RS_FP5 = $05;
+RS_FP6 = $06;
+RS_FP7 = $07;
+RS_PC = $00;
+RS_CCR = $01;
+RS_FPCR = $02;
+RS_SR = $03;
+RS_SSP = $04;
+RS_DFC = $05;
+RS_SFC = $06;
+RS_VBR = $07;
+RS_FPSR = $08;
+RS_A0 = $00;
+RS_A1 = $01;
+RS_A2 = $02;
+RS_A3 = $03;
+RS_A4 = $04;
+RS_A5 = $05;
+RS_A6 = $06;
+RS_SP = $07;
diff --git a/closures/compiler/m68k/ra68k.pas b/closures/compiler/m68k/ra68k.pas
new file mode 100644
index 0000000000..611ad4dcd3
--- /dev/null
+++ b/closures/compiler/m68k/ra68k.pas
@@ -0,0 +1,371 @@
+{
+ Copyright (c) 1998-2003 by Carl Eric Codere and Peter Vreman
+
+ Handles the common 68k assembler reader routines
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit ra68k;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ aasmbase,aasmtai,aasmdata,aasmcpu,
+ cpubase,rautils,cclasses;
+
+ type
+ Tm68kOperand=class(TOperand)
+ end;
+
+ Tm68kInstruction=class(TInstruction)
+ opsize : topsize;
+ function ConcatInstruction(p : TAsmList):tai;override;
+ function ConcatLabeledInstr(p : TAsmList):tai;
+ end;
+
+ implementation
+
+ uses
+ verbose,cgbase;
+
+{*****************************************************************************
+ TM68kInstruction
+*****************************************************************************}
+
+ function TM68kInstruction.ConcatInstruction(p : TAsmList):tai;
+ begin
+ result:=inherited ConcatInstruction(p);
+ if assigned(result) then
+ taicpu(result).opsize:=opsize;
+ end;
+{
+ function TM68kInstruction.ConcatInstruction(p : TAsmList):tai;
+ var
+ fits : boolean;
+ begin
+ writeln('jaj mami');
+ result:=nil;
+ fits := FALSE;
+ { setup specific opcodetions for first pass }
+
+ { Setup special operands }
+ { Convert to general form as to conform to the m68k opcode table }
+ if (opcode = A_ADDA) or (opcode = A_ADDI)
+ then opcode := A_ADD
+ else
+ { CMPM excluded because of GAS v1.34 BUG }
+ if (opcode = A_CMPA) or
+ (opcode = A_CMPI) then
+ opcode := A_CMP
+ else
+ if opcode = A_EORI then
+ opcode := A_EOR
+ else
+ if opcode = A_MOVEA then
+ opcode := A_MOVE
+ else
+ if opcode = A_ORI then
+ opcode := A_OR
+ else
+ if (opcode = A_SUBA) or (opcode = A_SUBI) then
+ opcode := A_SUB;
+
+ { Setup operand types }
+
+(*
+ in opcode <> A_MOVEM then
+ begin
+
+ while not(fits) do
+ begin
+ { set the opcodetion cache, if the opcodetion }
+ { occurs the first time }
+ if (it[i].i=opcode) and (ins_cache[opcode]=-1) then
+ ins_cache[opcode]:=i;
+
+ if (it[i].i=opcode) and (instr.ops=it[i].ops) then
+ begin
+ { first fit }
+ case instr.ops of
+ 0 : begin
+ fits:=true;
+ break;
+ end;
+ 1 :
+ begin
+ if (optyp1 and it[i].o1)<>0 then
+ begin
+ fits:=true;
+ break;
+ end;
+ end;
+ 2 : if ((optyp1 and it[i].o1)<>0) and
+ ((optyp2 and it[i].o2)<>0) then
+ begin
+ fits:=true;
+ break;
+ end
+ 3 : if ((optyp1 and it[i].o1)<>0) and
+ ((optyp2 and it[i].o2)<>0) and
+ ((optyp3 and it[i].o3)<>0) then
+ begin
+ fits:=true;
+ break;
+ end;
+ end; { end case }
+ end; { endif }
+ if it[i].i=A_NONE then
+ begin
+ { NO MATCH! }
+ Message(asmr_e_invalid_combination_opcode_and_operand);
+ exit;
+ end;
+ inc(i);
+ end; { end while }
+ *)
+ fits:=TRUE;
+
+ { We add the opcode to the opcode linked list }
+ if fits then
+ begin
+ case ops of
+ 0:
+ if opsize <> S_NO then
+ result:=(taicpu.op_none(opcode,opsize))
+ else
+ result:=(taicpu.op_none(opcode,S_NO));
+ 1: begin
+ case operands[1].opr.typ of
+ OPR_SYMBOL:
+ begin
+ result:=(taicpu.op_sym_ofs(opcode,
+ opsize, operands[1].opr.symbol,operands[1].opr.symofs));
+ end;
+ OPR_CONSTANT:
+ begin
+ result:=(taicpu.op_const(opcode,
+ opsize, operands[1].opr.val));
+ end;
+ OPR_REGISTER:
+ result:=(taicpu.op_reg(opcode,opsize,operands[1].opr.reg));
+ OPR_REFERENCE:
+ if opsize <> S_NO then
+ begin
+ result:=(taicpu.op_ref(opcode,
+ opsize,operands[1].opr.ref));
+ end
+ else
+ begin
+ { special jmp and call case with }
+ { symbolic references. }
+ if opcode in [A_BSR,A_JMP,A_JSR,A_BRA,A_PEA] then
+ begin
+ result:=(taicpu.op_ref(opcode,
+ S_NO,operands[1].opr.ref));
+ end
+ else
+ Message(asmr_e_invalid_opcode_and_operand);
+ end;
+ OPR_NONE:
+ Message(asmr_e_invalid_opcode_and_operand);
+ else
+ begin
+ Message(asmr_e_invalid_opcode_and_operand);
+ end;
+ end;
+ end;
+ 2: begin
+ { source }
+ case operands[1].opr.typ of
+ { reg,reg }
+ { reg,ref }
+ OPR_REGISTER:
+ begin
+ case operands[2].opr.typ of
+ OPR_REGISTER:
+ begin
+ result:=(taicpu.op_reg_reg(opcode,
+ opsize,operands[1].opr.reg,operands[2].opr.reg));
+ end;
+ OPR_REFERENCE:
+ result:=(taicpu.op_reg_ref(opcode,
+ opsize,operands[1].opr.reg,operands[2].opr.ref));
+ else { else case }
+ begin
+ Message(asmr_e_invalid_opcode_and_operand);
+ end;
+ end; { end second operand case for OPR_REGISTER }
+ end;
+ { regset, ref }
+ OPR_regset:
+ begin
+ case operands[2].opr.typ of
+ OPR_REFERENCE :
+ result:=(taicpu.op_regset_ref(opcode,
+ opsize,operands[1].opr.regset,operands[2].opr.ref));
+ else
+ begin
+ Message(asmr_e_invalid_opcode_and_operand);
+ end;
+ end; { end second operand case for OPR_regset }
+ end;
+
+ { const,reg }
+ { const,const }
+ { const,ref }
+ OPR_CONSTANT:
+ case operands[2].opr.typ of
+ { constant, constant does not have a specific size. }
+ OPR_CONSTANT:
+ result:=(taicpu.op_const_const(opcode,
+ S_NO,operands[1].opr.val,operands[2].opr.val));
+ OPR_REFERENCE:
+ begin
+ result:=(taicpu.op_const_ref(opcode,
+ opsize,operands[1].opr.val,
+ operands[2].opr.ref))
+ end;
+ OPR_REGISTER:
+ begin
+ result:=(taicpu.op_const_reg(opcode,
+ opsize,operands[1].opr.val,
+ operands[2].opr.reg))
+ end;
+ else
+ begin
+ Message(asmr_e_invalid_opcode_and_operand);
+ end;
+ end; { end second operand case for OPR_CONSTANT }
+ { ref,reg }
+ { ref,ref }
+ OPR_REFERENCE:
+ case operands[2].opr.typ of
+ OPR_REGISTER:
+ begin
+ result:=(taicpu.op_ref_reg(opcode,
+ opsize,operands[1].opr.ref,
+ operands[2].opr.reg));
+ end;
+ OPR_regset:
+ begin
+ result:=(taicpu.op_ref_regset(opcode,
+ opsize,operands[1].opr.ref,
+ operands[2].opr.regset));
+ end;
+ OPR_REFERENCE: { special opcodes }
+ result:=(taicpu.op_ref_ref(opcode,
+ opsize,operands[1].opr.ref,
+ operands[2].opr.ref));
+ else
+ begin
+ Message(asmr_e_invalid_opcode_and_operand);
+ end;
+ end; { end second operand case for OPR_REFERENCE }
+ OPR_SYMBOL: case operands[2].opr.typ of
+ OPR_REFERENCE:
+ begin
+ result:=(taicpu.op_sym_ofs_ref(opcode,
+ opsize,operands[1].opr.symbol,operands[1].opr.symofs,
+ operands[2].opr.ref))
+ end;
+ OPR_REGISTER:
+ begin
+ result:=(taicpu.op_sym_ofs_reg(opcode,
+ opsize,operands[1].opr.symbol,operands[1].opr.symofs,
+ operands[2].opr.reg))
+ end;
+ else
+ begin
+ Message(asmr_e_invalid_opcode_and_operand);
+ end;
+ end; { end second operand case for OPR_SYMBOL }
+ else
+ begin
+ Message(asmr_e_invalid_opcode_and_operand);
+ end;
+ end; { end first operand case }
+ end;
+ 3: begin
+ if (opcode = A_DIVSL) or (opcode = A_DIVUL) or (opcode = A_MULU)
+ or (opcode = A_MULS) or (opcode = A_DIVS) or (opcode = A_DIVU) then
+ begin
+ if (operands[1].opr.typ <> OPR_REGISTER)
+ or (operands[2].opr.typ <> OPR_REGISTER)
+ or (operands[3].opr.typ <> OPR_REGISTER) then
+ begin
+ Message(asmr_e_invalid_opcode_and_operand);
+ end
+ else
+ begin
+ result:=(taicpu. op_reg_reg_reg(opcode,opsize,
+ operands[1].opr.reg,operands[2].opr.reg,operands[3].opr.reg));
+ end;
+ end
+ else
+ Message(asmr_e_invalid_opcode_and_operand);
+ end;
+ end; { end case }
+ end;
+ if assigned(result) then
+ p.concat(result);
+ end;
+}
+
+ function TM68kInstruction.ConcatLabeledInstr(p : TAsmList):tai;
+ begin
+ if ((opcode >= A_BCC) and (opcode <= A_BVS)) or
+ (opcode = A_BRA) or (opcode = A_BSR) or
+ (opcode = A_JMP) or (opcode = A_JSR) or
+ ((opcode >= A_FBEQ) and (opcode <= A_FBNGLE)) then
+ begin
+ if ops > 2 then
+ Message(asmr_e_invalid_opcode_and_operand)
+ else if operands[1].opr.typ <> OPR_SYMBOL then
+ Message(asmr_e_invalid_opcode_and_operand)
+ else if (operands[1].opr.typ = OPR_SYMBOL) and
+ (ops = 1) then
+ if assigned(operands[1].opr.symbol) and
+ (operands[1].opr.symofs=0) then
+ result:=taicpu.op_sym(opcode,S_NO,
+ operands[1].opr.symbol)
+ else
+ Message(asmr_e_invalid_opcode_and_operand);
+ end
+ else if ((opcode >= A_DBCC) and (opcode <= A_DBF))
+ or ((opcode >= A_FDBEQ) and (opcode <= A_FDBNGLE)) then
+ begin
+ if (ops<>2) or
+ (operands[1].opr.typ <> OPR_REGISTER) or
+ (operands[2].opr.typ <> OPR_SYMBOL) or
+ (operands[2].opr.symofs <> 0) then
+ Message(asmr_e_invalid_opcode_and_operand)
+ else
+ result:=taicpu.op_reg_sym(opcode,opsize,operands[1].opr.reg,
+ operands[2].opr.symbol);
+ end
+ else
+ Message(asmr_e_invalid_opcode_and_operand);
+ if assigned(result) then
+ p.concat(result);
+ end;
+
+
+
+
+end.
diff --git a/closures/compiler/m68k/ra68kmot.pas b/closures/compiler/m68k/ra68kmot.pas
new file mode 100644
index 0000000000..b61ecbe50b
--- /dev/null
+++ b/closures/compiler/m68k/ra68kmot.pas
@@ -0,0 +1,1835 @@
+{
+ Copyright (c) 1998-2000 by Carl Eric Codere
+
+ This unit does the parsing process for the motorola inline assembler
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit ra68kmot;
+
+{$i fpcdefs.inc}
+
+{**********************************************************************}
+{ WARNING }
+{**********************************************************************}
+{ Any modification in the order or removal of terms in the tables }
+{ in m68k.pas and asmo68k.pas will BREAK the code in this unit, }
+{ unless the appropriate changes are made to this unit. Addition }
+{ of terms though, will not change the code herein. }
+{**********************************************************************}
+
+{---------------------------------------------------------------------------}
+{ LEFT TO DO }
+{---------------------------------------------------------------------------}
+{ o Add support for sized indexing such as in d0.l }
+{ presently only (an,dn) is supported for indexing -- }
+{ size defaults to LONG. }
+{ o Add support for MC68020 opcodes. }
+{ o Add support for MC68020 adressing modes. }
+{ o Add operand checking with m68k opcode table in ConcatOpCode }
+{ o Add Floating point support }
+{---------------------------------------------------------------------------}
+
+ interface
+
+
+ uses
+ cutils,
+ globtype,cclasses,cpubase,
+ symconst,
+ aasmbase,
+ rabase,rasm,ra68k,rautils;
+
+ type
+ tasmtoken = (
+ AS_NONE,AS_LABEL,AS_LLABEL,AS_STRING,AS_HEXNUM,AS_OCTALNUM,
+ AS_BINNUM,AS_COMMA,AS_LBRACKET,AS_RBRACKET,AS_LPAREN,
+ AS_RPAREN,AS_COLON,AS_DOT,AS_PLUS,AS_MINUS,AS_STAR,AS_INTNUM,
+ AS_SEPARATOR,AS_ID,AS_REGISTER,AS_OPCODE,AS_SLASH,AS_APPT,AS_REALNUM,
+ AS_ALIGN,
+ {------------------ Assembler directives --------------------}
+ AS_DB,AS_DW,AS_DD,AS_XDEF,AS_END,
+ {------------------ Assembler Operators --------------------}
+ AS_MOD,AS_SHL,AS_SHR,AS_NOT,AS_AND,AS_OR,AS_XOR);
+
+ tasmkeyword = string[10];
+
+ tm68kmotreader = class(tasmreader)
+ actasmtoken : tasmtoken;
+ prevasmtoken : tasmtoken;
+ procedure SetupTables;
+ function Assemble: tlinkedlist;override;
+ function is_asmopcode(const s: string) : boolean;
+ Function is_asmdirective(const s: string):boolean;
+ function is_register(const s:string):boolean;
+ procedure GetToken;
+ function consume(t : tasmtoken):boolean;
+ function findopcode(s: string; var opsize: topsize): tasmop;
+ Function BuildExpression(allow_symbol : boolean; asmsym : pshortstring) : longint;
+ Procedure BuildConstant(maxvalue: longint);
+ Procedure BuildRealConstant(typ : tfloattype);
+ Procedure BuildScaling(const oper:tm68koperand);
+ Function BuildRefExpression: longint;
+ procedure BuildReference(const oper:tm68koperand);
+ Procedure BuildOperand(const oper:tm68koperand);
+ Procedure BuildStringConstant(asciiz: boolean);
+ Procedure BuildOpCode(instr:Tm68kinstruction);
+ end;
+
+
+Implementation
+
+ uses
+ { global }
+ globals,verbose,
+ systems,
+ { aasm }
+ cpuinfo,aasmtai,aasmdata,aasmcpu,
+ cgbase,
+ { symtable }
+ symbase,symtype,symsym,symdef,symtable,
+ { pass 1 }
+ nbas,
+ { parser }
+ scanner,ag68kgas,
+ itcpugas
+ ;
+
+const
+ firstdirective = AS_DB;
+ lastdirective = AS_END;
+ firstoperator = AS_MOD;
+ lastoperator = AS_XOR;
+
+ _count_asmdirectives = longint(lastdirective)-longint(firstdirective);
+ _count_asmoperators = longint(lastoperator)-longint(firstoperator);
+
+ _asmdirectives : array[0.._count_asmdirectives] of tasmkeyword =
+ ('DC.B','DC.W','DC.L','XDEF','END');
+
+ { problems with shl,shr,not,and,or and xor, they are }
+ { context sensitive. }
+ _asmoperators : array[0.._count_asmoperators] of tasmkeyword = (
+ 'MOD','SHL','SHR','NOT','AND','OR','XOR');
+
+ token2str : array[tasmtoken] of tasmkeyword=(
+ 'NONE','LABEL','LLABEL','STRING','HEXNUM','OCTALNUM',
+ 'BINNUM',',','[',']','(',
+ ')',':','.','+','-','*','INTNUM',
+ 'SEPARATOR','ID','REGISTER','OPCODE','/','APPT','REALNUM',
+ 'ALIGN',
+ {------------------ Assembler directives --------------------}
+ 'DB','DW','DD','XDEF','END',
+ {------------------ Assembler Operators --------------------}
+ 'MOD','SHL','SHR','NOT','AND','OR','XOR');
+
+const
+ firsttoken : boolean = TRUE;
+ operandnum : byte = 0;
+
+ procedure tm68kmotreader.SetupTables;
+ { creates uppercased symbol tables for speed access }
+ var
+ i : tasmop;
+ Begin
+ { opcodes }
+ iasmops:=TFPHashList.create;
+ for i:=firstop to lastop do
+ iasmops.Add(upper(gas_op2str[i]),Pointer(PtrInt(i)));
+ end;
+
+
+ {---------------------------------------------------------------------}
+ { Routines for the tokenizing }
+ {---------------------------------------------------------------------}
+
+ function tm68kmotreader.is_asmopcode(const s: string):boolean;
+ var
+ hs : string;
+ j : byte;
+ begin
+ is_asmopcode:=false;
+ { first of all we remove the suffix }
+ j:=pos('.',s);
+ if j>0 then
+ hs:=copy(s,1,j-1)
+ else
+ hs:=s;
+
+ { Search opcodes }
+ actopcode:=tasmop(PtrInt(iasmops.Find(hs)));
+ if actopcode<>A_NONE then
+ begin
+ actasmtoken:=AS_OPCODE;
+ result:=TRUE;
+ exit;
+ end;
+ end;
+
+
+
+ Function tm68kmotreader.is_asmdirective(const s: string):boolean;
+ var
+ i:byte;
+ begin
+ result:=false;
+ for i:=0 to _count_asmdirectives do
+ begin
+ if s=_asmdirectives[i] then
+ begin
+ actasmtoken := tasmtoken(longint(firstdirective)+i);
+ result:=true;
+ exit;
+ end;
+ end;
+ end;
+
+
+ function tm68kmotreader.is_register(const s:string):boolean;
+ begin
+ is_register:=false;
+ // FIX ME!!! Ugly, needs a proper fix (KB)
+ actasmregister:=gas_regnum_search('%'+lower(s));
+ if actasmregister<>NR_NO then
+ begin
+ is_register:=true;
+ actasmtoken:=AS_REGISTER;
+ end;
+ end;
+
+
+ Procedure tm68kmotreader.GetToken;
+ {*********************************************************************}
+ { FUNCTION GetToken: tinteltoken; }
+ { Description: This routine returns intel assembler tokens and }
+ { does some minor syntax error checking. }
+ {*********************************************************************}
+ var
+ token: tasmtoken;
+ forcelabel: boolean;
+ begin
+ forcelabel := FALSE;
+ actasmpattern :='';
+ {* INIT TOKEN TO NOTHING *}
+ token := AS_NONE;
+ { while space and tab , continue scan... }
+ while c in [' ',#9] do
+ c:=current_scanner.asmgetchar;
+
+ if not (c in [#10,#13,'{',';']) then
+ current_scanner.gettokenpos;
+ { Possiblities for first token in a statement: }
+ { Local Label, Label, Directive, Prefix or Opcode.... }
+ if firsttoken and not (c in [#10,#13,'{',';']) then
+ begin
+
+ firsttoken := FALSE;
+ if c = '@' then
+ begin
+ token := AS_LLABEL; { this is a local label }
+ { Let us point to the next character }
+ c := current_scanner.asmgetchar;
+ end;
+
+
+
+ while c in ['A'..'Z','a'..'z','0'..'9','_','@','.'] do
+ begin
+ { if there is an at_sign, then this must absolutely be a label }
+ if c = '@' then forcelabel:=TRUE;
+ actasmpattern := actasmpattern + c;
+ c := current_scanner.asmgetchar;
+ end;
+
+ uppervar(actasmpattern);
+
+ if c = ':' then
+ begin
+ case token of
+ AS_NONE: token := AS_LABEL;
+ AS_LLABEL: ; { do nothing }
+ end; { end case }
+ { let us point to the next character }
+ c := current_scanner.asmgetchar;
+ actasmtoken := token;
+ exit;
+ end;
+
+ { Are we trying to create an identifier with }
+ { an at-sign...? }
+ if forcelabel then
+ Message(asmr_e_none_label_contain_at);
+
+ If is_asmopcode(actasmpattern) then
+ exit;
+ if is_asmdirective(actasmpattern) then
+ exit
+ else
+ begin
+ actasmtoken := AS_NONE;
+ Message1(asmr_e_invalid_or_missing_opcode,actasmpattern);
+ end;
+ end
+ else { else firsttoken }
+ { Here we must handle all possible cases }
+ begin
+ case c of
+
+ '@': { possiblities : - local label reference , such as in jmp @local1 }
+ { - @Result, @Code or @Data special variables. }
+ begin
+ actasmpattern := c;
+ c:= current_scanner.asmgetchar;
+ while c in ['A'..'Z','a'..'z','0'..'9','_','@','.'] do
+ begin
+ actasmpattern := actasmpattern + c;
+ c := current_scanner.asmgetchar;
+ end;
+ uppervar(actasmpattern);
+ actasmtoken := AS_ID;
+ exit;
+ end;
+ { identifier, register, opcode, prefix or directive }
+ 'A'..'Z','a'..'z','_': begin
+ actasmpattern := c;
+ c:= current_scanner.asmgetchar;
+ while c in ['A'..'Z','a'..'z','0'..'9','_','.'] do
+ begin
+ actasmpattern := actasmpattern + c;
+ c := current_scanner.asmgetchar;
+ end;
+ uppervar(actasmpattern);
+
+ If is_asmopcode(actasmpattern) then
+ exit;
+ if is_register(actasmpattern) then
+ exit;
+ if is_asmdirective(actasmpattern) then
+ exit;
+ { this is surely an identifier }
+ actasmtoken := AS_ID;
+ exit;
+ end;
+ { override operator... not supported }
+ '&': begin
+ c:=current_scanner.asmgetchar;
+ actasmtoken := AS_AND;
+ end;
+ { string or character }
+ '''' :
+ begin
+ actasmpattern:='';
+ while true do
+ begin
+ if c = '''' then
+ begin
+ c:=current_scanner.asmgetchar;
+ if c=#10 then
+ begin
+ Message(scan_f_string_exceeds_line);
+ break;
+ end;
+ repeat
+ if c=''''then
+ begin
+ c:=current_scanner.asmgetchar;
+ if c='''' then
+ begin
+ actasmpattern:=actasmpattern+'''';
+ c:=current_scanner.asmgetchar;
+ if c=#10 then
+ begin
+ Message(scan_f_string_exceeds_line);
+ break;
+ end;
+ end
+ else break;
+ end
+ else
+ begin
+ actasmpattern:=actasmpattern+c;
+ c:=current_scanner.asmgetchar;
+ if c=#10 then
+ begin
+ Message(scan_f_string_exceeds_line);
+ break
+ end;
+ end;
+ until false; { end repeat }
+ end
+ else break; { end if }
+ end; { end while }
+ token:=AS_STRING;
+ actasmtoken := token;
+ exit;
+ end;
+ '$' : begin
+ c:=current_scanner.asmgetchar;
+ while c in ['0'..'9','A'..'F','a'..'f'] do
+ begin
+ actasmpattern := actasmpattern + c;
+ c := current_scanner.asmgetchar;
+ end;
+ actasmtoken := AS_HEXNUM;
+ exit;
+ end;
+ ',' : begin
+ actasmtoken := AS_COMMA;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+ '(' : begin
+ actasmtoken := AS_LPAREN;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+ ')' : begin
+ actasmtoken := AS_RPAREN;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+ ':' : begin
+ actasmtoken := AS_COLON;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+{ '.' : begin
+ actasmtoken := AS_DOT;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end; }
+ '+' : begin
+ actasmtoken := AS_PLUS;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+ '-' : begin
+ actasmtoken := AS_MINUS;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+ '*' : begin
+ actasmtoken := AS_STAR;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+ '/' : begin
+ actasmtoken := AS_SLASH;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+ '<' : begin
+ c := current_scanner.asmgetchar;
+ { invalid characters }
+ if c <> '<' then
+ Message(asmr_e_invalid_char_smaller);
+ { still assume << }
+ actasmtoken := AS_SHL;
+ c := current_scanner.asmgetchar;
+ exit;
+ end;
+ '>' : begin
+ c := current_scanner.asmgetchar;
+ { invalid characters }
+ if c <> '>' then
+ Message(asmr_e_invalid_char_greater);
+ { still assume << }
+ actasmtoken := AS_SHR;
+ c := current_scanner.asmgetchar;
+ exit;
+ end;
+ '|' : begin
+ actasmtoken := AS_OR;
+ c := current_scanner.asmgetchar;
+ exit;
+ end;
+ '^' : begin
+ actasmtoken := AS_XOR;
+ c := current_scanner.asmgetchar;
+ exit;
+ end;
+ '#' : begin
+ actasmtoken:=AS_APPT;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+ '%' : begin
+ c:=current_scanner.asmgetchar;
+ while c in ['0','1'] do
+ begin
+ actasmpattern := actasmpattern + c;
+ c := current_scanner.asmgetchar;
+ end;
+ actasmtoken := AS_BINNUM;
+ exit;
+ end;
+ { integer number }
+ '0'..'9': begin
+ actasmpattern := c;
+ c := current_scanner.asmgetchar;
+ while c in ['0'..'9'] do
+ begin
+ actasmpattern := actasmpattern + c;
+ c:= current_scanner.asmgetchar;
+ end;
+ actasmtoken := AS_INTNUM;
+ exit;
+ end;
+ ';' : begin
+ repeat
+ c:=current_scanner.asmgetchar;
+ until c=#10;
+ firsttoken := TRUE;
+ actasmtoken:=AS_SEPARATOR;
+ end;
+
+ '{',#13,#10 : begin
+ c:=current_scanner.asmgetchar;
+ firsttoken := TRUE;
+ actasmtoken:=AS_SEPARATOR;
+ end;
+ else
+ begin
+ Message(scan_f_illegal_char);
+ end;
+
+ end; { end case }
+ end; { end else if }
+ end;
+
+
+ {---------------------------------------------------------------------}
+ { Routines for the parsing }
+ {---------------------------------------------------------------------}
+
+ function tm68kmotreader.consume(t : tasmtoken):boolean;
+ var
+ p: pointer;
+ begin
+ Consume:=true;
+ if t<>actasmtoken then
+ begin
+ p:=nil;
+ dword(p^):=0;
+ Message2(scan_f_syn_expected,token2str[t],token2str[actasmtoken]);
+ Consume:=false;
+ end;
+ repeat
+ gettoken;
+ until actasmtoken<>AS_NONE;
+ end;
+
+
+ function tm68kmotreader.findopcode(s: string; var opsize: topsize): tasmop;
+ {*********************************************************************}
+ { FUNCTION findopcode(s: string): tasmop; }
+ { Description: Determines if the s string is a valid opcode }
+ { if so returns correct tasmop token. }
+ {*********************************************************************}
+ var
+ j: byte;
+ op_size: string;
+ begin
+ findopcode := A_NONE;
+ j:=pos('.',s);
+ if j<>0 then
+ begin
+ op_size:=copy(s,j+1,1);
+ case op_size[1] of
+ { For the motorola only opsize size is used to }
+ { determine the size of the operands. }
+ 'B': opsize := S_B;
+ 'W': opsize := S_W;
+ 'L': opsize := S_L;
+ 'S': opsize := S_FS;
+ 'D': opsize := S_FD;
+ 'X': opsize := S_FX;
+ else
+ Message1(asmr_e_unknown_opcode,s);
+ end;
+ { delete everything starting from dot }
+ delete(s,j,length(s));
+ end;
+ result:=actopcode;
+ end;
+
+
+
+
+ Function tm68kmotreader.BuildExpression(allow_symbol : boolean; asmsym : pshortstring) : longint;
+ {*********************************************************************}
+ { FUNCTION BuildExpression: longint }
+ { Description: This routine calculates a constant expression to }
+ { a given value. The return value is the value calculated from }
+ { the expression. }
+ { The following tokens (not strings) are recognized: }
+ { (,),SHL,SHR,/,*,NOT,OR,XOR,AND,MOD,+/-,numbers,ID to constants. }
+ {*********************************************************************}
+ { ENTRY: On entry the token should be any valid expression token. }
+ { EXIT: On Exit the token points to either COMMA or SEPARATOR }
+ { ERROR RECOVERY: Tries to find COMMA or SEPARATOR token by consuming }
+ { invalid tokens. }
+ {*********************************************************************}
+ var expr: string;
+ hs, tempstr: string;
+ sym : tsym;
+ srsymtable : TSymtable;
+ hl : tasmlabel;
+ l : longint;
+ errorflag: boolean;
+ begin
+ errorflag := FALSE;
+ expr := '';
+ tempstr := '';
+ if allow_symbol then
+ asmsym^:='';
+ Repeat
+ Case actasmtoken of
+ AS_LPAREN: begin
+ Consume(AS_LPAREN);
+ expr := expr + '(';
+ end;
+ AS_RPAREN: begin
+ Consume(AS_RPAREN);
+ expr := expr + ')';
+ end;
+ AS_SHL: begin
+ Consume(AS_SHL);
+ expr := expr + '<';
+ end;
+ AS_SHR: begin
+ Consume(AS_SHR);
+ expr := expr + '>';
+ end;
+ AS_SLASH: begin
+ Consume(AS_SLASH);
+ expr := expr + '/';
+ end;
+ AS_MOD: begin
+ Consume(AS_MOD);
+ expr := expr + '%';
+ end;
+ AS_STAR: begin
+ Consume(AS_STAR);
+ expr := expr + '*';
+ end;
+ AS_PLUS: begin
+ Consume(AS_PLUS);
+ expr := expr + '+';
+ end;
+ AS_MINUS: begin
+ Consume(AS_MINUS);
+ expr := expr + '-';
+ end;
+ AS_AND: begin
+ Consume(AS_AND);
+ expr := expr + '&';
+ end;
+ AS_NOT: begin
+ Consume(AS_NOT);
+ expr := expr + '~';
+ end;
+ AS_XOR: begin
+ Consume(AS_XOR);
+ expr := expr + '^';
+ end;
+ AS_OR: begin
+ Consume(AS_OR);
+ expr := expr + '|';
+ end;
+ AS_ID: begin
+ if SearchIConstant(actasmpattern,l) then
+ begin
+ str(l, tempstr);
+ expr := expr + tempstr;
+ Consume(AS_ID);
+ End else
+ if not allow_symbol then
+ begin
+ Message(asmr_e_syn_constant);
+ l := 0;
+ End else
+ begin
+ hs:='';
+ if (expr[Length(expr)]='+') then
+ Delete(expr,Length(expr),1)
+ else if expr<>'' then
+ begin
+ Message(asmr_e_invalid_constant_expression);
+ break;
+ End;
+ tempstr:=actasmpattern;
+ consume(AS_ID);
+ if (length(tempstr)>1) and (tempstr[1]='@') then
+ begin
+ CreateLocalLabel(tempstr,hl,false);
+ hs:=hl.name
+ end
+ else if SearchLabel(tempstr,hl,false) then
+ hs:=hl.name
+ else
+ begin
+ asmsearchsym(tempstr,sym,srsymtable);
+ if assigned(sym) then
+ begin
+ case sym.typ of
+ paravarsym,
+ localvarsym :
+ begin
+ Message(asmr_e_no_local_or_para_allowed);
+ hs:=tabstractvarsym(sym).mangledname;
+ end;
+ staticvarsym :
+ hs:=tstaticvarsym(sym).mangledname;
+ procsym :
+ begin
+ if tprocsym(sym).procdeflist.count>1 then
+ Message(asmr_w_calling_overload_func);
+ hs:=tprocdef(tprocsym(sym).procdeflist[0]).mangledname;
+ end;
+ typesym :
+ begin
+ if not(ttypesym(sym).typedef.typ in [recorddef,objectdef]) then
+ Message(asmr_e_wrong_sym_type);
+ end;
+ else
+ Message(asmr_e_wrong_sym_type);
+ end;
+ end
+ else
+ Message1(sym_e_unknown_id,tempstr);
+ end;
+ { symbol found? }
+ if hs<>'' then
+ begin
+ if asmsym^='' then
+ asmsym^:=hs
+ else
+ Message(asmr_e_cant_have_multiple_relocatable_symbols);
+ end;
+ end;
+ end;
+ AS_INTNUM: begin
+ expr := expr + actasmpattern;
+ Consume(AS_INTNUM);
+ end;
+ AS_BINNUM: begin
+ tempstr := tostr(ParseVal(actasmpattern,2));
+ if tempstr = '' then
+ Message(asmr_e_error_converting_binary);
+ expr:=expr+tempstr;
+ Consume(AS_BINNUM);
+ end;
+
+ AS_HEXNUM: begin
+ tempstr := tostr(ParseVal(actasmpattern,16));
+ if tempstr = '' then
+ Message(asmr_e_error_converting_hexadecimal);
+ expr:=expr+tempstr;
+ Consume(AS_HEXNUM);
+ end;
+ AS_OCTALNUM: begin
+ tempstr := tostr(ParseVal(actasmpattern,8));
+ if tempstr = '' then
+ Message(asmr_e_error_converting_octal);
+ expr:=expr+tempstr;
+ Consume(AS_OCTALNUM);
+ end;
+ { go to next term }
+ AS_COMMA: begin
+ if not ErrorFlag then
+ BuildExpression := CalculateExpression(expr)
+ else
+ BuildExpression := 0;
+ Exit;
+ end;
+ { go to next symbol }
+ AS_SEPARATOR: begin
+ if not ErrorFlag then
+ BuildExpression := CalculateExpression(expr)
+ else
+ BuildExpression := 0;
+ Exit;
+ end;
+ else
+ begin
+ { only write error once. }
+ if not errorflag then
+ Message(asmr_e_invalid_constant_expression);
+ { consume tokens until we find COMMA or SEPARATOR }
+ Consume(actasmtoken);
+ errorflag := TRUE;
+ End;
+ end;
+ Until false;
+ end;
+
+
+ Procedure tm68kmotreader.BuildRealConstant(typ : tfloattype);
+ {*********************************************************************}
+ { PROCEDURE BuilRealConst }
+ { Description: This routine calculates a constant expression to }
+ { a given value. The return value is the value calculated from }
+ { the expression. }
+ { The following tokens (not strings) are recognized: }
+ { +/-,numbers and real numbers }
+ {*********************************************************************}
+ { ENTRY: On entry the token should be any valid expression token. }
+ { EXIT: On Exit the token points to either COMMA or SEPARATOR }
+ { ERROR RECOVERY: Tries to find COMMA or SEPARATOR token by consuming }
+ { invalid tokens. }
+ {*********************************************************************}
+ var expr: string;
+ r : extended;
+ code : word;
+ negativ : boolean;
+ errorflag: boolean;
+ begin
+ errorflag := FALSE;
+ Repeat
+ negativ:=false;
+ expr := '';
+ if actasmtoken=AS_PLUS then Consume(AS_PLUS)
+ else if actasmtoken=AS_MINUS then
+ begin
+ negativ:=true;
+ consume(AS_MINUS);
+ end;
+ Case actasmtoken of
+ AS_INTNUM: begin
+ expr := actasmpattern;
+ Consume(AS_INTNUM);
+ end;
+ AS_REALNUM: begin
+ expr := actasmpattern;
+ { in ATT syntax you have 0d in front of the real }
+ { should this be forced ? yes i think so, as to }
+ { conform to gas as much as possible. }
+ if (expr[1]='0') and (upper(expr[2])='D') then
+ expr:=copy(expr,3,255);
+ Consume(AS_REALNUM);
+ end;
+ AS_BINNUM: begin
+ { checking for real constants with this should use }
+ { real DECODING otherwise the compiler will crash! }
+ Message(asmr_e_invalid_float_expr);
+ expr:='0.0';
+ Consume(AS_BINNUM);
+ end;
+
+ AS_HEXNUM: begin
+ { checking for real constants with this should use }
+ { real DECODING otherwise the compiler will crash! }
+ Message(asmr_e_invalid_float_expr);
+ expr:='0.0';
+ Consume(AS_HEXNUM);
+ end;
+ AS_OCTALNUM: begin
+ { checking for real constants with this should use }
+ { real DECODING otherwise the compiler will crash! }
+ { xxxToDec using reals could be a solution, but the }
+ { problem is that these will crash the m68k compiler }
+ { when compiling -- because of lack of good fpu }
+ { support. }
+ Message(asmr_e_invalid_float_expr);
+ expr:='0.0';
+ Consume(AS_OCTALNUM);
+ end;
+ else
+ begin
+ { only write error once. }
+ if not errorflag then
+ Message(asmr_e_invalid_float_expr);
+ { consume tokens until we find COMMA or SEPARATOR }
+ Consume(actasmtoken);
+ errorflag := TRUE;
+ End;
+
+ end;
+ { go to next term }
+ if (actasmtoken=AS_COMMA) or (actasmtoken=AS_SEPARATOR) then
+ begin
+ if negativ then expr:='-'+expr;
+ val(expr,r,code);
+ if code<>0 then
+ begin
+ r:=0;
+ Message(asmr_e_invalid_float_expr);
+ ConcatRealConstant(curlist,r,typ);
+ End
+ else
+ begin
+ ConcatRealConstant(curlist,r,typ);
+ End;
+ end
+ else
+ Message(asmr_e_invalid_float_expr);
+ Until actasmtoken=AS_SEPARATOR;
+ end;
+
+
+ Procedure tm68kmotreader.BuildConstant(maxvalue: longint);
+ {*********************************************************************}
+ { PROCEDURE BuildConstant }
+ { Description: This routine takes care of parsing a DB,DD,or DW }
+ { line and adding those to the assembler node. Expressions, range- }
+ { checking are fullly taken care of. }
+ { maxvalue: $ff -> indicates that this is a DB node. }
+ { $ffff -> indicates that this is a DW node. }
+ { $ffffffff -> indicates that this is a DD node. }
+ {*********************************************************************}
+ { EXIT CONDITION: On exit the routine should point to AS_SEPARATOR. }
+ {*********************************************************************}
+ var
+ expr: string;
+ value : longint;
+ begin
+ Repeat
+ Case actasmtoken of
+ AS_STRING: begin
+ if maxvalue <> $ff then
+ Message(asmr_e_string_not_allowed_as_const);
+ expr := actasmpattern;
+ if length(expr) > 1 then
+ Message(asmr_e_string_not_allowed_as_const);
+ Consume(AS_STRING);
+ Case actasmtoken of
+ AS_COMMA: Consume(AS_COMMA);
+ AS_SEPARATOR: ;
+ else
+ Message(asmr_e_invalid_string_expression);
+ end; { end case }
+ ConcatString(curlist,expr);
+ end;
+ AS_INTNUM,AS_BINNUM,
+ AS_OCTALNUM,AS_HEXNUM:
+ begin
+ value:=BuildExpression(false,nil);
+ ConcatConstant(curlist,value,maxvalue);
+ end;
+ AS_ID:
+ begin
+ value:=BuildExpression(false,nil);
+ if value > maxvalue then
+ begin
+ Message(asmr_e_constant_out_of_bounds);
+ { assuming a value of maxvalue }
+ value := maxvalue;
+ end;
+ ConcatConstant(curlist,value,maxvalue);
+ end;
+ { These terms can start an assembler expression }
+ AS_PLUS,AS_MINUS,AS_LPAREN,AS_NOT: begin
+ value := BuildExpression(false,nil);
+ ConcatConstant(curlist,value,maxvalue);
+ end;
+ AS_COMMA: begin
+ Consume(AS_COMMA);
+ END;
+ AS_SEPARATOR: ;
+
+ else
+ begin
+ Message(asmr_e_syntax_error);
+ end;
+ end; { end case }
+ Until actasmtoken = AS_SEPARATOR;
+ end;
+
+
+ Procedure TM68kMotreader.BuildScaling(const oper:tm68koperand);
+ {*********************************************************************}
+ { Takes care of parsing expression starting from the scaling value }
+ { up to and including possible field specifiers. }
+ { EXIT CONDITION: On exit the routine should point to AS_SEPARATOR }
+ { or AS_COMMA. On entry should point to the AS_STAR token. }
+ {*********************************************************************}
+ var str:string;
+ l: longint;
+ code: integer;
+ begin
+ Consume(AS_STAR);
+ if (oper.opr.ref.scalefactor <> 0)
+ and (oper.opr.ref.scalefactor <> 1) then
+ Message(asmr_e_wrong_base_index);
+ case actasmtoken of
+ AS_INTNUM: str := actasmpattern;
+ AS_HEXNUM: str := Tostr(ParseVal(actasmpattern,16));
+ AS_BINNUM: str := Tostr(ParseVal(actasmpattern,2));
+ AS_OCTALNUM: str := Tostr(ParseVal(actasmpattern,8));
+ else
+ Message(asmr_e_syntax_error);
+ end;
+ val(str, l, code);
+ if code <> 0 then
+ Message(asmr_e_wrong_scale_factor);
+ if ((l = 2) or (l = 4) or (l = 8) or (l = 1)) and (code = 0) then
+ begin
+ oper.opr.ref.scalefactor := l;
+ end
+ else
+ begin
+ Message(asmr_e_wrong_scale_factor);
+ oper.opr.ref.scalefactor := 0;
+ end;
+ if oper.opr.ref.index = NR_NO then
+ begin
+ Message(asmr_e_wrong_base_index);
+ oper.opr.ref.scalefactor := 0;
+ end;
+ { Consume the scaling number }
+ Consume(actasmtoken);
+ if actasmtoken = AS_RPAREN then
+ Consume(AS_RPAREN)
+ else
+ Message(asmr_e_wrong_scale_factor);
+ { // .Field.Field ... or separator/comma // }
+ if actasmtoken in [AS_COMMA,AS_SEPARATOR] then
+ begin
+ end
+ else
+ Message(asmr_e_syntax_error);
+ end;
+
+
+ Function TM68kMotreader.BuildRefExpression: longint;
+ {*********************************************************************}
+ { FUNCTION BuildRefExpression: longint }
+ { Description: This routine calculates a constant expression to }
+ { a given value. The return value is the value calculated from }
+ { the expression. }
+ { The following tokens (not strings) are recognized: }
+ { SHL,SHR,/,*,NOT,OR,XOR,AND,MOD,+/-,numbers,ID to constants. }
+ {*********************************************************************}
+ { ENTRY: On entry the token should be any valid expression token. }
+ { EXIT: On Exit the token points to the LPAREN token. }
+ { ERROR RECOVERY: Tries to find COMMA or SEPARATOR token by consuming }
+ { invalid tokens. }
+ {*********************************************************************}
+ var tempstr: string;
+ expr: string;
+ l : longint;
+ errorflag : boolean;
+ begin
+ errorflag := FALSE;
+ tempstr := '';
+ expr := '';
+ Repeat
+ Case actasmtoken of
+ AS_RPAREN: begin
+ Message(asmr_e_syntax_error);
+ Consume(AS_RPAREN);
+ end;
+ AS_SHL: begin
+ Consume(AS_SHL);
+ expr := expr + '<';
+ end;
+ AS_SHR: begin
+ Consume(AS_SHR);
+ expr := expr + '>';
+ end;
+ AS_SLASH: begin
+ Consume(AS_SLASH);
+ expr := expr + '/';
+ end;
+ AS_MOD: begin
+ Consume(AS_MOD);
+ expr := expr + '%';
+ end;
+ AS_STAR: begin
+ Consume(AS_STAR);
+ expr := expr + '*';
+ end;
+ AS_PLUS: begin
+ Consume(AS_PLUS);
+ expr := expr + '+';
+ end;
+ AS_MINUS: begin
+ Consume(AS_MINUS);
+ expr := expr + '-';
+ end;
+ AS_AND: begin
+ Consume(AS_AND);
+ expr := expr + '&';
+ end;
+ AS_NOT: begin
+ Consume(AS_NOT);
+ expr := expr + '~';
+ end;
+ AS_XOR: begin
+ Consume(AS_XOR);
+ expr := expr + '^';
+ end;
+ AS_OR: begin
+ Consume(AS_OR);
+ expr := expr + '|';
+ end;
+ { End of reference }
+ AS_LPAREN: begin
+ if not ErrorFlag then
+ BuildRefExpression := CalculateExpression(expr)
+ else
+ BuildRefExpression := 0;
+ { no longer in an expression }
+ exit;
+ end;
+ AS_ID:
+ begin
+ if NOT SearchIConstant(actasmpattern,l) then
+ begin
+ Message(asmr_e_syn_constant);
+ l := 0;
+ end;
+ str(l, tempstr);
+ expr := expr + tempstr;
+ Consume(AS_ID);
+ end;
+ AS_INTNUM: begin
+ expr := expr + actasmpattern;
+ Consume(AS_INTNUM);
+ end;
+ AS_BINNUM: begin
+ tempstr := Tostr(ParseVal(actasmpattern,2));
+ if tempstr = '' then
+ Message(asmr_e_error_converting_binary);
+ expr:=expr+tempstr;
+ Consume(AS_BINNUM);
+ end;
+
+ AS_HEXNUM: begin
+ tempstr := Tostr(ParseVal(actasmpattern,16));
+ if tempstr = '' then
+ Message(asmr_e_error_converting_hexadecimal);
+ expr:=expr+tempstr;
+ Consume(AS_HEXNUM);
+ end;
+ AS_OCTALNUM: begin
+ tempstr := Tostr(ParseVal(actasmpattern,8));
+ if tempstr = '' then
+ Message(asmr_e_error_converting_octal);
+ expr:=expr+tempstr;
+ Consume(AS_OCTALNUM);
+ end;
+ else
+ begin
+ { write error only once. }
+ if not errorflag then
+ Message(asmr_e_invalid_constant_expression);
+ BuildRefExpression := 0;
+ if actasmtoken in [AS_COMMA,AS_SEPARATOR] then exit;
+ { consume tokens until we find COMMA or SEPARATOR }
+ Consume(actasmtoken);
+ errorflag := TRUE;
+ end;
+ end;
+ Until false;
+ end;
+
+
+
+ {*********************************************************************}
+ { PROCEDURE BuildBracketExpression }
+ { Description: This routine builds up an expression after a LPAREN }
+ { token is encountered. }
+ { On entry actasmtoken should be equal to AS_LPAREN }
+ {*********************************************************************}
+ { EXIT CONDITION: On exit the routine should point to either the }
+ { AS_COMMA or AS_SEPARATOR token. }
+ {*********************************************************************}
+ procedure TM68kMotreader.BuildReference(const oper:tm68koperand);
+ var
+ l:longint;
+ code: integer;
+ str: string;
+ begin
+ Consume(AS_LPAREN);
+ case actasmtoken of
+ { // (reg ... // }
+ AS_REGISTER:
+ begin
+ oper.opr.ref.base := actasmregister;
+ Consume(AS_REGISTER);
+ { can either be a register or a right parenthesis }
+ { // (reg) // }
+ { // (reg)+ // }
+ if actasmtoken=AS_RPAREN then
+ begin
+ Consume(AS_RPAREN);
+ if actasmtoken = AS_PLUS then
+ begin
+ if (oper.opr.ref.direction <> dir_none) then
+ Message(asmr_e_no_inc_and_dec_together)
+ else
+ oper.opr.ref.direction := dir_inc;
+ Consume(AS_PLUS);
+ end;
+ if not (actasmtoken in [AS_COMMA,AS_SEPARATOR]) then
+ begin
+ Message(asmr_e_invalid_reference_syntax);
+ { error recovery ... }
+ while actasmtoken <> AS_SEPARATOR do
+ Consume(actasmtoken);
+ end;
+ exit;
+ end;
+ { // (reg,reg .. // }
+ Consume(AS_COMMA);
+ if actasmtoken = AS_REGISTER then
+ begin
+ oper.opr.ref.index :=
+ actasmregister;
+ Consume(AS_REGISTER);
+ { check for scaling ... }
+ case actasmtoken of
+ AS_RPAREN:
+ begin
+ Consume(AS_RPAREN);
+ if not (actasmtoken in [AS_COMMA,AS_SEPARATOR]) then
+ begin
+ { error recovery ... }
+ Message(asmr_e_invalid_reference_syntax);
+ while actasmtoken <> AS_SEPARATOR do
+ Consume(actasmtoken);
+ end;
+ exit;
+ end;
+ AS_STAR:
+ begin
+ BuildScaling(oper);
+ end;
+ else
+ begin
+ Message(asmr_e_invalid_reference_syntax);
+ while (actasmtoken <> AS_SEPARATOR) do
+ Consume(actasmtoken);
+ end;
+ end; { end case }
+ end
+ else
+ begin
+ Message(asmr_e_invalid_reference_syntax);
+ while (actasmtoken <> AS_SEPARATOR) do
+ Consume(actasmtoken);
+ end;
+ end;
+ AS_HEXNUM,AS_OCTALNUM, { direct address }
+ AS_BINNUM,AS_INTNUM:
+ begin
+ case actasmtoken of
+ AS_INTNUM: str := actasmpattern;
+ AS_HEXNUM: str := Tostr(ParseVal(actasmpattern,16));
+ AS_BINNUM: str := Tostr(ParseVal(actasmpattern,2));
+ AS_OCTALNUM: str := Tostr(ParseVal(actasmpattern,8));
+ else
+ Message(asmr_e_syntax_error);
+ end;
+ Consume(actasmtoken);
+ val(str, l, code);
+ if code <> 0 then
+ Message(asmr_e_invalid_reference_syntax)
+ else
+ oper.opr.ref.offset := l;
+ Consume(AS_RPAREN);
+ if not (actasmtoken in [AS_COMMA,AS_SEPARATOR]) then
+ begin
+ { error recovery ... }
+ Message(asmr_e_invalid_reference_syntax);
+ while actasmtoken <> AS_SEPARATOR do
+ Consume(actasmtoken);
+ end;
+ exit;
+ end;
+ else
+ begin
+ Message(asmr_e_invalid_reference_syntax);
+ while (actasmtoken <> AS_SEPARATOR) do
+ Consume(actasmtoken);
+ end;
+ end;
+ end;
+
+
+
+
+ Procedure TM68kMotreader.BuildOperand(const oper:tm68koperand);
+ {*********************************************************************}
+ { EXIT CONDITION: On exit the routine should point to either the }
+ { AS_COMMA or AS_SEPARATOR token. }
+ {*********************************************************************}
+ var
+ expr: string;
+ tempstr: string;
+ lab: tasmlabel;
+ l : longint;
+ i: Tsuperregister;
+ r:Tregister;
+ hl: tasmlabel;
+ reg_one, reg_two: tregister;
+ regset: tcpuregisterset;
+ p: pointer;
+ begin
+ regset := [];
+ tempstr := '';
+ case actasmtoken of
+ { // Memory reference // }
+ AS_LPAREN:
+ begin
+ Oper.InitRef;
+ BuildReference(oper);
+ end;
+ { // Constant expression // }
+ AS_APPT: begin
+ Consume(AS_APPT);
+ if not (oper.opr.typ in [OPR_NONE,OPR_CONSTANT]) then
+ Message(asmr_e_invalid_operand_type);
+ { identifiers are handled by BuildExpression }
+ oper.opr.typ := OPR_CONSTANT;
+ oper.opr.val :=BuildExpression(true,@tempstr);
+ if tempstr<>'' then
+ begin
+ l:=oper.opr.val;
+ oper.opr.typ := OPR_SYMBOL;
+ oper.opr.symofs := l;
+ oper.opr.symbol := current_asmdata.RefAsmSymbol(tempstr);
+ end;
+ end;
+ { // Constant memory offset . // }
+ { // This must absolutely be followed by ( // }
+ AS_HEXNUM,AS_INTNUM,
+ AS_BINNUM,AS_OCTALNUM,AS_PLUS:
+ begin
+ Oper.InitRef;
+ oper.opr.ref.offset:=BuildRefExpression;
+ BuildReference(oper);
+ end;
+ { // A constant expression, or a Variable ref. // }
+ AS_ID: begin
+ Oper.InitRef;
+ if actasmpattern[1] = '@' then
+ { // Label or Special symbol reference // }
+ begin
+ if actasmpattern = '@RESULT' then
+ oper.SetUpResult
+ else
+ if actasmpattern = 'SELF' then
+ oper.SetUpSelf
+ else
+ if (actasmpattern = '@CODE') or (actasmpattern = '@DATA') then
+ Message(asmr_w_CODE_and_DATA_not_supported)
+ else
+ begin
+ delete(actasmpattern,1,1);
+ if actasmpattern = '' then
+ Message(asmr_e_null_label_ref_not_allowed);
+ CreateLocalLabel(actasmpattern,lab,false);
+ oper.opr.typ := OPR_SYMBOL;
+ oper.opr.symbol := lab;
+ oper.opr.symofs := 0;
+// labeled := TRUE;
+ end;
+ Consume(AS_ID);
+ if not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) then
+ Message(asmr_e_syntax_error);
+ end
+ { probably a variable or normal expression }
+ { or a procedure (such as in CALL ID) }
+ else
+ begin
+ { is it a constant ? }
+ if SearchIConstant(actasmpattern,l) then
+ begin
+ Oper.InitRef;
+ oper.opr.ref.offset:=BuildRefExpression;
+ BuildReference(oper);
+ end
+ else { is it a label variable ? }
+
+ { // ID[ , ID.Field.Field or simple ID // }
+ { check if this is a label, if so then }
+ { emit it as a label. }
+ if SearchLabel(actasmpattern,hl,false) then
+ begin
+ oper.opr.typ := OPR_SYMBOL;
+ oper.opr.symbol := hl;
+ oper.opr.symofs := 0;
+// labeled := TRUE;
+ Consume(AS_ID);
+ if not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) then
+ Message(asmr_e_syntax_error);
+
+ end
+ else begin
+ expr:=actasmpattern;
+ Consume(AS_ID);
+ { typecasting? }
+ if SearchType(expr,l) then
+ begin
+ oper.hastype:=true;
+ oper.typesize:=l;
+ case actasmtoken of
+ AS_LPAREN :
+ begin
+ { Support Type([Reference]) }
+ Consume(AS_LPAREN);
+ BuildOperand(oper{,true});
+ Consume(AS_RPAREN);
+ end;
+ AS_LBRACKET :
+ begin
+ { Support Var.Type[Index] }
+ { Convert @label.Byte[1] to reference }
+ if oper.opr.typ=OPR_SYMBOL then
+ oper.initref;
+ end;
+ end;
+ end
+ else
+ begin
+ if not oper.SetupVar(expr,false) then
+ begin
+ { not a variable, check special variables.. }
+ if expr = 'SELF' then
+ oper.SetupSelf
+ else begin
+ writeln('unknown id: ',expr);
+ Message1(sym_e_unknown_id,expr);
+ end;
+ expr:='';
+ end;
+ end;
+// Message1(sym_e_unknown_id,actasmpattern);
+ end;
+
+ case actasmtoken of
+ AS_LPAREN: { indexing }
+ BuildReference(oper);
+ AS_SEPARATOR,AS_COMMA: begin
+ end;
+ else
+ Message(asmr_e_syntax_error);
+ end;
+
+ end;
+ end;
+
+ { // Pre-decrement mode reference or constant mem offset. // }
+ AS_MINUS: begin
+ Consume(AS_MINUS);
+ if actasmtoken = AS_LPAREN then
+ begin
+ Oper.InitRef;
+ { indicate pre-decrement mode }
+ oper.opr.ref.direction := dir_dec;
+ BuildReference(oper);
+ end
+ else
+ if actasmtoken in [AS_OCTALNUM,AS_HEXNUM,AS_BINNUM,AS_INTNUM] then
+ begin
+ Oper.InitRef;
+ oper.opr.ref.offset:=BuildRefExpression;
+ { negate because was preceded by a negative sign! }
+ oper.opr.ref.offset:=-oper.opr.ref.offset;
+ BuildReference(oper);
+ end
+ else
+ begin
+ Message(asmr_e_syntax_error);
+ while not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) do
+ Consume(actasmtoken);
+ end;
+ end;
+ { // Register, a variable reference or a constant reference // }
+ AS_REGISTER: begin
+// writeln('register! ',actasmpattern);
+ { save the type of register used. }
+ tempstr := actasmpattern;
+ Consume(AS_REGISTER);
+ { // Simple register // }
+ if (actasmtoken = AS_SEPARATOR) or (actasmtoken = AS_COMMA) then
+ begin
+// writeln('simple reg');
+ if not (oper.opr.typ in [OPR_NONE,OPR_REGISTER]) then
+ Message(asmr_e_invalid_operand_type);
+ oper.opr.typ := OPR_REGISTER;
+ oper.opr.reg := actasmregister;
+ end
+ else
+ { HERE WE MUST HANDLE THE SPECIAL CASE OF MOVEM AND FMOVEM }
+ { // Individual register listing // }
+ if (actasmtoken = AS_SLASH) then
+ begin
+ r:=actasmregister;
+ if getregtype(r)<>R_INTREGISTER then
+ internalerror(200302191);
+ include(regset,getsupreg(r));
+ Consume(AS_SLASH);
+ if actasmtoken = AS_REGISTER then
+ begin
+ While not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) do
+ begin
+ case actasmtoken of
+ AS_REGISTER: begin
+ if getregtype(r)<>R_INTREGISTER then
+ internalerror(200302191);
+ include(regset,getsupreg(r));
+ Consume(AS_REGISTER);
+ end;
+ AS_SLASH: Consume(AS_SLASH);
+ AS_SEPARATOR,AS_COMMA: break;
+ else
+ begin
+ Message(asmr_e_invalid_reg_list_in_movem);
+ Consume(actasmtoken);
+ end;
+ end; { end case }
+ end; { end while }
+ oper.opr.typ:= OPR_regset;
+ oper.opr.regset := regset;
+ end
+ else
+ { error recovery ... }
+ begin
+ Message(asmr_e_invalid_reg_list_in_movem);
+ while not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) do
+ Consume(actasmtoken);
+ end;
+ end
+ else
+ { // Range register listing // }
+ if (actasmtoken = AS_MINUS) then
+ begin
+ Consume(AS_MINUS);
+ reg_one:=actasmregister;
+ if actasmtoken <> AS_REGISTER then
+ begin
+ Message(asmr_e_invalid_reg_list_in_movem);
+ while not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) do
+ Consume(actasmtoken);
+ end
+ else
+ begin
+ { determine the register range ... }
+ reg_two:=actasmregister;
+ if getregtype(reg_two)<>R_INTREGISTER then
+ internalerror(200302191);
+ if getsupreg(reg_one) > getsupreg(reg_two) then
+ for i:=getsupreg(reg_two) to getsupreg(reg_one) do
+ include(regset,i)
+ else
+ for i:=getsupreg(reg_one) to getsupreg(reg_two) do
+ include(regset,i);
+ Consume(AS_REGISTER);
+ if not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) then
+ begin
+ Message(asmr_e_invalid_reg_list_in_movem);
+ while not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) do
+ Consume(actasmtoken);
+ end;
+ { set up instruction }
+ oper.opr.typ:= OPR_regset;
+ oper.opr.regset := regset;
+ end;
+ end
+ else
+ { DIVSL/DIVS/MULS/MULU with long for MC68020 only }
+ if (actasmtoken = AS_COLON) then
+ begin
+ if (current_settings.cputype = cpu_MC68020) or (cs_compilesystem in current_settings.moduleswitches) then
+ begin
+ Consume(AS_COLON);
+ if (actasmtoken = AS_REGISTER) then
+ begin
+ { set up old field, since register is valid }
+ oper.opr.typ := OPR_REGISTER;
+ oper.opr.reg := actasmregister;
+ Inc(operandnum);
+ oper.opr.typ := OPR_REGISTER;
+ oper.opr.reg := actasmregister;
+ Consume(AS_REGISTER);
+ if not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) then
+ begin
+ Message(asmr_e_invalid_reg_list_for_opcode);
+ while not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) do
+ Consume(actasmtoken);
+ end;
+ end;
+ end
+ else
+ begin
+ Message1(asmr_e_higher_cpu_mode_required,'68020');
+ if not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) then
+ begin
+ Message(asmr_e_invalid_reg_list_for_opcode);
+ while not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) do
+ Consume(actasmtoken);
+ end;
+ end;
+ end
+ else
+ Message(asmr_e_invalid_register);
+ end;
+ AS_SEPARATOR, AS_COMMA: ;
+ else
+ begin
+ writeln('looofasz');
+ Message(asmr_e_invalid_opcode_and_operand);
+ Consume(actasmtoken);
+ end;
+ end; { end case }
+ end;
+
+
+
+ Procedure tm68kmotreader.BuildStringConstant(asciiz: boolean);
+ {*********************************************************************}
+ { PROCEDURE BuildStringConstant }
+ { Description: Takes care of a ASCII, or ASCIIZ directive. }
+ { asciiz: boolean -> if true then string will be null terminated. }
+ {*********************************************************************}
+ { EXIT CONDITION: On exit the routine should point to AS_SEPARATOR. }
+ { On ENTRY: Token should point to AS_STRING }
+ {*********************************************************************}
+ var
+ expr: string;
+ errorflag : boolean;
+ begin
+ errorflag := FALSE;
+ Repeat
+ Case actasmtoken of
+ AS_STRING: begin
+ expr:=actasmpattern;
+ if asciiz then
+ expr:=expr+#0;
+ ConcatPasString(curlist,expr);
+ Consume(AS_STRING);
+ end;
+ AS_COMMA: begin
+ Consume(AS_COMMA);
+ END;
+ AS_SEPARATOR: ;
+ else
+ begin
+ Consume(actasmtoken);
+ if not errorflag then
+ Message(asmr_e_invalid_string_expression);
+ errorflag := TRUE;
+ end;
+ end; { end case }
+ Until actasmtoken = AS_SEPARATOR;
+ end;
+
+
+ Procedure TM68kmotReader.BuildOpCode(instr:Tm68kinstruction);
+ {*********************************************************************}
+ { PROCEDURE BuildOpcode; }
+ { Description: Parses the intel opcode and operands, and writes it }
+ { in the TInstruction object. }
+ {*********************************************************************}
+ { EXIT CONDITION: On exit the routine should point to AS_SEPARATOR. }
+ { On ENTRY: Token should point to AS_OPCODE }
+ {*********************************************************************}
+ var
+ operandnum : longint;
+ begin
+ { // opcode // }
+ { allow for newline as in gas styled syntax }
+ { under DOS you get two AS_SEPARATOR !! }
+ while actasmtoken=AS_SEPARATOR do
+ Consume(AS_SEPARATOR);
+ if (actasmtoken <> AS_OPCODE) then
+ begin
+ Message(asmr_e_invalid_or_missing_opcode);
+ { error recovery }
+ While not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) do
+ Consume(actasmtoken);
+ exit;
+ end
+ else
+ begin
+ Instr.opcode := findopcode(actasmpattern,instr.opsize);
+ Consume(AS_OPCODE);
+ { // Zero operand opcode ? // }
+ if actasmtoken = AS_SEPARATOR then
+ exit
+ else
+ operandnum := 1;
+ end;
+
+ While actasmtoken <> AS_SEPARATOR do
+ begin
+ case actasmtoken of
+ { // Operand delimiter // }
+ AS_COMMA: begin
+ if operandnum > Max_Operands then
+ Message(asmr_e_too_many_operands)
+ else
+ Inc(operandnum);
+ Consume(AS_COMMA);
+ end;
+ { // End of asm operands for this opcode // }
+ AS_SEPARATOR: ;
+ else
+ BuildOperand(Instr.Operands[operandnum] as tm68koperand);
+ end; { end case }
+ end; { end while }
+ instr.Ops:=operandnum;
+ end;
+
+
+
+
+ function tm68kmotreader.Assemble: tlinkedlist;
+ var
+ hl: tasmlabel;
+ instr : TM68kInstruction;
+ begin
+ Message(asmr_d_start_reading);
+ firsttoken := TRUE;
+ operandnum := 0;
+ { sets up all opcode and register tables in uppercase }
+ if not _asmsorted then
+ begin
+ SetupTables;
+ _asmsorted := TRUE;
+ end;
+ curlist:=TAsmList.Create;
+ { setup label linked list }
+ LocalLabelList:=TLocalLabelList.Create;
+ c:=current_scanner.asmgetchar;
+ gettoken;
+ while actasmtoken<>AS_END do
+ begin
+ case actasmtoken of
+ AS_LLABEL:
+ begin
+ if CreateLocalLabel(actasmpattern,hl,true) then
+ ConcatLabel(curlist,hl);
+ Consume(AS_LLABEL);
+ end;
+ AS_LABEL:
+ begin
+ { when looking for Pascal labels, these must }
+ { be in uppercase. }
+ if SearchLabel(upper(actasmpattern),hl,true) then
+ ConcatLabel(curlist,hl)
+ else
+ Message1(asmr_e_unknown_label_identifier,actasmpattern);
+ Consume(AS_LABEL);
+ end;
+ AS_DW:
+ begin
+ Consume(AS_DW);
+ BuildConstant($ffff);
+ end;
+ AS_DB:
+ begin
+ Consume(AS_DB);
+ BuildConstant($ff);
+ end;
+ AS_DD:
+ begin
+ Consume(AS_DD);
+ BuildConstant(longint($ffffffff));
+ end;
+ AS_XDEF:
+ begin
+ Consume(AS_XDEF);
+ if actasmtoken=AS_ID then
+ ConcatPublic(curlist,actasmpattern);
+ Consume(AS_ID);
+ if actasmtoken<>AS_SEPARATOR then
+ Consume(AS_SEPARATOR);
+ end;
+ AS_ALIGN:
+ begin
+ Message(asmr_w_align_not_supported);
+ while actasmtoken <> AS_SEPARATOR do
+ Consume(actasmtoken);
+ end;
+ AS_OPCODE:
+ begin
+ instr:=TM68kInstruction.Create(tm68koperand);
+ BuildOpcode(instr);
+// instr.AddReferenceSizes;
+// instr.SetInstructionOpsize;
+// instr.CheckOperandSizes;
+ if instr.labeled then
+ instr.ConcatLabeledInstr(curlist)
+ else begin
+ instr.ConcatInstruction(curlist);
+ end;
+ instr.Free;
+{
+ instr.init;
+ BuildOpcode;
+ instr.ops := operandnum;
+ if instr.labeled then
+ ConcatLabeledInstr(instr)
+ else
+ ConcatOpCode(instr);
+ instr.done;}
+ end;
+ AS_SEPARATOR:
+ begin
+ Consume(AS_SEPARATOR);
+ { let us go back to the first operand }
+ operandnum := 0;
+ end;
+ AS_END:
+ { end assembly block }
+ ;
+ else
+ begin
+ Message(asmr_e_syntax_error);
+ { error recovery }
+ Consume(actasmtoken);
+ end;
+ end; { end case }
+ end; { end while }
+
+ { Check LocalLabelList }
+ LocalLabelList.CheckEmitted;
+ LocalLabelList.Free;
+
+ assemble:=curlist;
+ Message(asmr_d_finish_reading);
+ end;
+
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+const
+ asmmode_m68k_mot_info : tasmmodeinfo =
+ (
+ id : asmmode_m68k_mot;
+ idtxt : 'MOTOROLA';
+ casmreader : tm68kmotreader;
+ );
+
+ asmmode_m68k_standard_info : tasmmodeinfo =
+ (
+ id : asmmode_standard;
+ idtxt : 'STANDARD';
+ casmreader : tm68kmotreader;
+ );
+
+begin
+ RegisterAsmMode(asmmode_m68k_mot_info);
+ RegisterAsmMode(asmmode_m68k_standard_info);
+end.
diff --git a/closures/compiler/m68k/rgcpu.pas b/closures/compiler/m68k/rgcpu.pas
new file mode 100644
index 0000000000..a981d73a75
--- /dev/null
+++ b/closures/compiler/m68k/rgcpu.pas
@@ -0,0 +1,40 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit implements the register allocator for m68k
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+
+unit rgcpu;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ aasmbase,aasmtai,aasmdata,
+ cpubase,
+ rgobj;
+
+ type
+ trgcpu = class(trgobj)
+ end;
+
+ implementation
+
+end.
diff --git a/closures/compiler/macho.pas b/closures/compiler/macho.pas
new file mode 100644
index 0000000000..8885db4383
--- /dev/null
+++ b/closures/compiler/macho.pas
@@ -0,0 +1,2103 @@
+unit macho;
+{
+ * Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ }
+
+{ converted by Dmitry Boyarintsev 2009 }
+
+{$mode objfpc}{$H+}
+
+interface
+
+{$IFDEF FPC}
+{$PACKRECORDS C}
+{$PACKENUM 4}
+{$ENDIF}
+
+
+// mach/$arch/machine.h
+// $arch can be: i386, x86_64, ppc, arm
+// currently used is i386
+
+type
+ integer_t = Integer;
+ uint8_t = Byte;
+
+ int16_t = SmallInt;
+ uint16_t = Word;
+
+ uint32_t = LongWord;
+ int32_t = Integer;
+
+ uint64_t = QWord;
+
+// mach/thread_status.h
+
+{$ifdef i386}
+
+{$endif i386}
+
+// mach/machine.h
+
+type
+ cpu_type_t = integer_t;
+ cpu_subtype_t = integer_t;
+ cpu_threadtype_t = integer_t;
+
+const
+ CPU_STATE_MAX = 4;
+
+ CPU_STATE_USER = 0;
+ CPU_STATE_SYSTEM = 1;
+ CPU_STATE_IDLE = 2;
+ CPU_STATE_NICE = 3;
+
+ {* Capability bits used in the definition of cpu_type. }
+ CPU_ARCH_MASK = $ff000000; { mask for architecture bits }
+ CPU_ARCH_ABI64 = $01000000; { 64 bit ABI }
+
+ { Machine types known by all. }
+
+ CPU_TYPE_ANY = -1;
+ CPU_TYPE_VAX = 1;
+ CPU_TYPE_MC680x0 = 6;
+ CPU_TYPE_X86 = 7;
+ CPU_TYPE_I386 = CPU_TYPE_X86; { compatibility }
+ CPU_TYPE_X86_64 = CPU_TYPE_X86 or CPU_ARCH_ABI64;
+ // skip CPU_TYPE_MIPS = 8;
+ CPU_TYPE_MC98000 = 10;
+ CPU_TYPE_HPPA = 11;
+ CPU_TYPE_ARM = 12;
+ CPU_TYPE_MC88000 = 13;
+ CPU_TYPE_SPARC = 14;
+ CPU_TYPE_I860 = 15;
+ // skip CPU_TYPE_ALPHA = 16; */
+
+ CPU_TYPE_POWERPC = 18;
+ CPU_TYPE_POWERPC64 = CPU_TYPE_POWERPC or CPU_ARCH_ABI64;
+
+{*
+ * Machine subtypes (these are defined here, instead of in a machine
+ * dependent directory, so that any program can get all definitions
+ * regardless of where is it compiled).
+ *}
+
+{*
+ * Capability bits used in the definition of cpu_subtype.
+ *}
+ CPU_SUBTYPE_MASK = $ff000000; { mask for feature flags }
+ CPU_SUBTYPE_LIB64 = $80000000; { 64 bit libraries }
+
+
+{*
+ * Object files that are hand-crafted to run on any
+ * implementation of an architecture are tagged with
+ * CPU_SUBTYPE_MULTIPLE. This functions essentially the same as
+ * the "ALL" subtype of an architecture except that it allows us
+ * to easily find object files that may need to be modified
+ * whenever a new implementation of an architecture comes out.
+ *
+ * It is the responsibility of the implementor to make sure the
+ * software handles unsupported implementations elegantly.
+ *}
+ CPU_SUBTYPE_MULTIPLE = -1;
+ CPU_SUBTYPE_LITTLE_ENDIAN = 0;
+ CPU_SUBTYPE_BIG_ENDIAN = 1;
+
+{*
+ * Machine threadtypes.
+ * This is none - not defined - for most machine types/subtypes.
+ *}
+ CPU_THREADTYPE_NONE = 0;
+
+{*
+ * VAX subtypes (these do *not* necessary conform to the actual cpu
+ * ID assigned by DEC available via the SID register).
+ *}
+
+ CPU_SUBTYPE_VAX_ALL = 0;
+ CPU_SUBTYPE_VAX780 = 1;
+ CPU_SUBTYPE_VAX785 = 2;
+ CPU_SUBTYPE_VAX750 = 3;
+ CPU_SUBTYPE_VAX730 = 4;
+ CPU_SUBTYPE_UVAXI = 5;
+ CPU_SUBTYPE_UVAXII = 6;
+ CPU_SUBTYPE_VAX8200 = 7;
+ CPU_SUBTYPE_VAX8500 = 8;
+ CPU_SUBTYPE_VAX8600 = 9;
+ CPU_SUBTYPE_VAX8650 = 10;
+ CPU_SUBTYPE_VAX8800 = 11;
+ CPU_SUBTYPE_UVAXIII = 12;
+
+{*
+ * 680x0 subtypes
+ *
+ * The subtype definitions here are unusual for historical reasons.
+ * NeXT used to consider 68030 code as generic 68000 code. For
+ * backwards compatability:
+ *
+ * CPU_SUBTYPE_MC68030 symbol has been preserved for source code
+ * compatability.
+ *
+ * CPU_SUBTYPE_MC680x0_ALL has been defined to be the same
+ * subtype as CPU_SUBTYPE_MC68030 for binary comatability.
+ *
+ * CPU_SUBTYPE_MC68030_ONLY has been added to allow new object
+ * files to be tagged as containing 68030-specific instructions.
+ *}
+
+ CPU_SUBTYPE_MC680x0_ALL = 1;
+ CPU_SUBTYPE_MC68030 = 1; { compat }
+ CPU_SUBTYPE_MC68040 = 2;
+ CPU_SUBTYPE_MC68030_ONLY = 3;
+
+ {* I386 subtypes *}
+
+ CPU_SUBTYPE_I386_ALL = 3 + (0 shl 4);
+ CPU_SUBTYPE_386 = 3 + (0 shl 4);
+ CPU_SUBTYPE_486 = 4 + (0 shl 4);
+ CPU_SUBTYPE_486SX = 4 + (8 shl 4); // 8 << 4 = 128
+ CPU_SUBTYPE_586 = 5 + (0 shl 4);
+ CPU_SUBTYPE_PENT = 5 + (0 shl 4);
+ CPU_SUBTYPE_PENTPRO = 6 + (1 shl 4);
+ CPU_SUBTYPE_PENTII_M3 = 6 + (3 shl 4);
+ CPU_SUBTYPE_PENTII_M5 = 6 + (5 shl 4);
+ CPU_SUBTYPE_CELERON = 7 + (6 shl 4);
+ CPU_SUBTYPE_CELERON_MOBILE = 7 + (7 shl 4);
+ CPU_SUBTYPE_PENTIUM_3 = 8 + (0 shl 4);
+ CPU_SUBTYPE_PENTIUM_3_M = 8 + (1 shl 4);
+ CPU_SUBTYPE_PENTIUM_3_XEON = 8 + (2 shl 4);
+ CPU_SUBTYPE_PENTIUM_M = 9 + (0 shl 4);
+ CPU_SUBTYPE_PENTIUM_4 = 10 + (0 shl 4);
+ CPU_SUBTYPE_PENTIUM_4_M = 10 + (1 shl 4);
+ CPU_SUBTYPE_ITANIUM = 11 + (0 shl 4);
+ CPU_SUBTYPE_ITANIUM_2 = 11 + (1 shl 4);
+ CPU_SUBTYPE_XEON = 12 + (0 shl 4);
+ CPU_SUBTYPE_XEON_MP = 12 + (1 shl 4);
+
+ CPU_SUBTYPE_INTEL_FAMILY_MAX = 15;
+ CPU_SUBTYPE_INTEL_MODEL_ALL = 0;
+
+ {* X86 subtypes. *}
+
+ CPU_SUBTYPE_X86_ALL = 3;
+ CPU_SUBTYPE_X86_64_ALL = 3;
+ CPU_SUBTYPE_X86_ARCH1 = 4;
+
+
+ CPU_THREADTYPE_INTEL_HTT = 1;
+
+ {* Mips subtypes. *}
+
+ CPU_SUBTYPE_MIPS_ALL = 0;
+ CPU_SUBTYPE_MIPS_R2300 = 1;
+ CPU_SUBTYPE_MIPS_R2600 = 2;
+ CPU_SUBTYPE_MIPS_R2800 = 3;
+ CPU_SUBTYPE_MIPS_R2000a = 4; {* pmax *}
+ CPU_SUBTYPE_MIPS_R2000 = 5;
+ CPU_SUBTYPE_MIPS_R3000a = 6; { 3max *}
+ CPU_SUBTYPE_MIPS_R3000 = 7;
+
+ {* MC98000 (PowerPC) subtypes *}
+ CPU_SUBTYPE_MC98000_ALL = 0;
+ CPU_SUBTYPE_MC98601 = 1;
+
+{*
+ * HPPA subtypes for Hewlett-Packard HP-PA family of
+ * risc processors. Port by NeXT to 700 series.
+ *}
+
+ CPU_SUBTYPE_HPPA_ALL = 0;
+ CPU_SUBTYPE_HPPA_7100 = 0; {* compat *}
+ CPU_SUBTYPE_HPPA_7100LC = 1;
+
+ {* MC88000 subtypes. *}
+
+ CPU_SUBTYPE_MC88000_ALL = 0;
+ CPU_SUBTYPE_MC88100 = 1;
+ CPU_SUBTYPE_MC88110 = 2;
+
+ {* SPARC subtypes *}
+ CPU_SUBTYPE_SPARC_ALL = 0;
+
+ {* I860 subtypes *}
+ CPU_SUBTYPE_I860_ALL = 0;
+ CPU_SUBTYPE_I860_860 = 1;
+
+ {* PowerPC subtypes *}
+
+ CPU_SUBTYPE_POWERPC_ALL = 0;
+ CPU_SUBTYPE_POWERPC_601 = 1;
+ CPU_SUBTYPE_POWERPC_602 = 2;
+ CPU_SUBTYPE_POWERPC_603 = 3;
+ CPU_SUBTYPE_POWERPC_603e = 4;
+ CPU_SUBTYPE_POWERPC_603ev = 5;
+ CPU_SUBTYPE_POWERPC_604 = 6;
+ CPU_SUBTYPE_POWERPC_604e = 7;
+ CPU_SUBTYPE_POWERPC_620 = 8;
+ CPU_SUBTYPE_POWERPC_750 = 9;
+ CPU_SUBTYPE_POWERPC_7400 = 10;
+ CPU_SUBTYPE_POWERPC_7450 = 11;
+ CPU_SUBTYPE_POWERPC_970 = 100;
+
+ {* ARM subtypes *}
+ CPU_SUBTYPE_ARM_ALL = 0;
+ CPU_SUBTYPE_ARM_V4T = 5;
+ CPU_SUBTYPE_ARM_V6 = 6;
+ CPU_SUBTYPE_ARM_V5TEJ = 7;
+ CPU_SUBTYPE_ARM_XSCALE = 8;
+
+{*
+ * CPU families (sysctl hw.cpufamily)
+ *
+ * These are meant to identify the CPU's marketing name - an
+ * application can map these to (possibly) localized strings.
+ * NB: the encodings of the CPU families are intentionally arbitrary.
+ * There is no ordering, and you should never try to deduce whether
+ * or not some feature is available based on the family.
+ * Use feature flags (eg, hw.optional.altivec) to test for optional
+ * functionality.
+ *}
+ CPUFAMILY_UNKNOWN = 0;
+ CPUFAMILY_POWERPC_G3 = $cee41549;
+ CPUFAMILY_POWERPC_G4 = $77c184ae;
+ CPUFAMILY_POWERPC_G5 = $ed76d8aa;
+ CPUFAMILY_INTEL_6_13 = $aa33392b;
+ CPUFAMILY_INTEL_6_14 = $73d67300; { "Intel Core Solo" and "Intel Core Duo" (32-bit Pentium-M with SSE3) }
+ CPUFAMILY_INTEL_6_15 = $426f69ef; { "Intel Core 2 Duo" }
+ CPUFAMILY_INTEL_6_23 = $78ea4fbc; { Penryn }
+ CPUFAMILY_INTEL_6_26 = $6b5a4cd2; { Nehalem }
+ CPUFAMILY_ARM_9 = $e73283ae;
+ CPUFAMILY_ARM_11 = $8ff620d8;
+ CPUFAMILY_ARM_XSCALE = $53b005f5;
+
+ CPUFAMILY_INTEL_YONAH = CPUFAMILY_INTEL_6_14;
+ CPUFAMILY_INTEL_MEROM = CPUFAMILY_INTEL_6_15;
+ CPUFAMILY_INTEL_PENRYN = CPUFAMILY_INTEL_6_23;
+ CPUFAMILY_INTEL_NEHALEM = CPUFAMILY_INTEL_6_26;
+
+ CPUFAMILY_INTEL_CORE = CPUFAMILY_INTEL_6_14;
+ CPUFAMILY_INTEL_CORE2 = CPUFAMILY_INTEL_6_15;
+
+// mach/vm_prot.h
+type
+ vm_prot_t = Integer;
+
+const
+ VM_PROT_NONE = $00;
+
+ VM_PROT_READ = $01; {* read permission *}
+ VM_PROT_WRITE = $02; {* write permission *}
+ VM_PROT_EXECUTE = $04; {* execute permission *}
+
+{*
+ * The default protection for newly-created virtual memory
+ *}
+
+ VM_PROT_DEFAULT = VM_PROT_READ or VM_PROT_WRITE;
+
+{*
+ * The maximum privileges possible, for parameter checking.
+ *}
+
+ VM_PROT_ALL = VM_PROT_READ or VM_PROT_WRITE or VM_PROT_EXECUTE;
+
+{*
+ * An invalid protection value.
+ * Used only by memory_object_lock_request to indicate no change
+ * to page locks. Using -1 here is a bad idea because it
+ * looks like VM_PROT_ALL and then some.
+ *}
+
+ VM_PROT_NO_CHANGE = $08;
+
+{*
+ * When a caller finds that he cannot obtain write permission on a
+ * mapped entry, the following flag can be used. The entry will
+ * be made "needs copy" effectively copying the object (using COW),
+ * and write permission will be added to the maximum protections
+ * for the associated entry.
+ *}
+
+ VM_PROT_COPY = $10;
+
+
+{*
+ * Another invalid protection value.
+ * Used only by memory_object_data_request upon an object
+ * which has specified a copy_call copy strategy. It is used
+ * when the kernel wants a page belonging to a copy of the
+ * object, and is only asking the object as a result of
+ * following a shadow chain. This solves the race between pages
+ * being pushed up by the memory manager and the kernel
+ * walking down the shadow chain.
+ *}
+
+ VM_PROT_WANTS_COPY = $10;
+
+
+{ Constant for the magic field of the mach_header (32-bit architectures) the mach magic number }
+
+const
+ MH_MAGIC = $feedface;
+ MH_CIGAM = $cefaedfe; { NXSwapInt(MH_MAGIC) }
+
+
+type
+ { * The 32-bit mach header appears at the very beginning of the object file for 32-bit architectures. }
+ mach_header = record
+ magic : uint32_t; { mach magic number identifier }
+ cputype : cpu_type_t; { cpu specifier }
+ cpusubtype : cpu_subtype_t; { machine specifier }
+ filetype : uint32_t; { type of file }
+ ncmds : uint32_t; { number of load commands }
+ sizeofcmds : uint32_t; { the size of all the load commands }
+ flags : uint32_t; { flags }
+ end;
+ pmach_header = ^mach_header;
+
+type
+ {* The 64-bit mach header appears at the very beginning of object files for
+ * 64-bit architectures. }
+ mach_header_64 = record
+ magic : uint32_t; { mach magic number identifier }
+ cputype : cpu_type_t; { cpu specifier }
+ cpusubtype : cpu_subtype_t; { machine specifier }
+ filetype : uint32_t; { type of file }
+ ncmds : uint32_t; { number of load commands }
+ sizeofcmds : uint32_t; { the size of all the load commands }
+ flags : uint32_t; { flags }
+ reserved : uint32_t; { reserved }
+ end;
+ pmach_header_64 = ^mach_header_64;
+
+ { Constant for the magic field of the mach_header_64 (64-bit architectures) }
+ { the 64-bit mach magic number }
+
+const
+ MH_MAGIC_64 = $feedfacf;
+ MH_CIGAM_64 = $cffaedfe; { NXSwapInt(MH_MAGIC_64) }
+
+ {* The layout of the file depends on the filetype. For all but the MH_OBJECT
+ * file type the segments are padded out and aligned on a segment alignment
+ * boundary for efficient demand pageing. The MH_EXECUTE, MH_FVMLIB, MH_DYLIB,
+ * MH_DYLINKER and MH_BUNDLE file types also have the headers included as part
+ * of their first segment.
+ *
+ * The file type MH_OBJECT is a compact format intended as output of the
+ * assembler and input (and possibly output) of the link editor (the .o
+ * format). All sections are in one unnamed segment with no segment padding.
+ * This format is used as an executable format when the file is so small the
+ * segment padding greatly increases its size.
+ *
+ * The file type MH_PRELOAD is an executable format intended for things that
+ * are not executed under the kernel (proms, stand alones, kernels, etc). The
+ * format can be executed under the kernel but may demand paged it and not
+ * preload it before execution.
+ *
+ * A core file is in MH_CORE format and can be any in an arbritray legal
+ * Mach-O file.
+ *
+ * Constants for the filetype field of the mach_header }
+const
+ MH_OBJECT = $1; { relocatable object file }
+ MH_EXECUTE = $2; { demand paged executable file }
+ MH_FVMLIB = $3; { fixed VM shared library file }
+ MH_CORE = $4; { core file }
+ MH_PRELOAD = $5; { preloaded executable file }
+ MH_DYLIB = $6; { dynamically bound shared library }
+ MH_DYLINKER = $7; { dynamic link editor }
+ MH_BUNDLE = $8; { dynamically bound bundle file }
+ MH_DYLIB_STUB = $9; { shared library stub for static }
+ MH_DSYM = $a; { linking only, no section contents }
+ { companion file with only debug sections }
+
+const
+ { Constants for the flags field of the mach_header }
+
+ MH_NOUNDEFS = $1; { the object file has no undefined references }
+ MH_INCRLINK = $2; { the object file is the output of an incremental link against a base file and can't be link edited again }
+ MH_DYLDLINK = $4; { the object file is input for the dynamic linker and can't be staticly link edited again }
+ MH_BINDATLOAD = $8; { the object file's undefined references are bound by the dynamic linker when loaded. }
+ MH_PREBOUND = $10; { the file has its dynamic undefined references prebound. }
+ MH_SPLIT_SEGS = $20; { the file has its read-only and read-write segments split }
+ MH_LAZY_INIT = $40; { the shared library init routine is to be run lazily via catching memory faults to its writeable segments (obsolete) }
+ MH_TWOLEVEL = $80; { the image is using two-level name space bindings }
+ MH_FORCE_FLAT = $100; { the executable is forcing all images to use flat name space bindings }
+ MH_NOMULTIDEFS = $200; { this umbrella guarantees no multiple defintions of symbols in its sub-images so the two-level namespace hints can always be used. }
+ MH_NOFIXPREBINDING = $400; { do not have dyld notify the prebinding agent about this executable }
+ MH_PREBINDABLE = $800; { the binary is not prebound but can have its prebinding redone. only used when MH_PREBOUND is not set. }
+ MH_ALLMODSBOUND = $1000; { indicates that this binary binds to all two-level namespace modules of }
+ { its dependent libraries. only used when MH_PREBINDABLE and MH_TWOLEVEL are both set. }
+ MH_SUBSECTIONS_VIA_SYMBOLS = $2000; { safe to divide up the sections into sub-sections via symbols for dead code stripping }
+ MH_CANONICAL = $4000; { the binary has been canonicalized via the unprebind operation }
+ MH_WEAK_DEFINES = $8000; { the final linked image contains external weak symbols }
+ MH_BINDS_TO_WEAK = $10000; { the final linked image uses weak symbols }
+ MH_ALLOW_STACK_EXECUTION = $20000; { When this bit is set, all stacks in the task will be given stack }
+ { execution privilege. Only used in MH_EXECUTE filetypes. }
+ MH_ROOT_SAFE = $40000; { When this bit is set, the binary declares it is safe for use in processes with uid zero }
+ MH_SETUID_SAFE = $80000; { When this bit is set, the binary declares it is safe for use in processes when issetugid() is true }
+ MH_NO_REEXPORTED_DYLIBS = $100000; { When this bit is set on a dylib, the static linker does not need to examine dependent dylibs to see if any are re-exported }
+ MH_PIE = $200000; { When this bit is set, the OS will load the main executable at a random address. Only used in MH_EXECUTE filetypes. }
+
+ {
+ * The load commands directly follow the mach_header. The total size of all
+ * of the commands is given by the sizeofcmds field in the mach_header. All
+ * load commands must have as their first two fields cmd and cmdsize. The cmd
+ * field is filled in with a constant for that command type. Each command type
+ * has a structure specifically for it. The cmdsize field is the size in bytes
+ * of the particular load command structure plus anything that follows it that
+ * is a part of the load command (i.e. section structures, strings, etc.). To
+ * advance to the next load command the cmdsize can be added to the offset or
+ * pointer of the current load command. The cmdsize for 32-bit architectures
+ * MUST be a multiple of 4 bytes and for 64-bit architectures MUST be a multiple
+ * of 8 bytes (these are forever the maximum alignment of any load commands).
+ * The padded bytes must be zero. All tables in the object file must also
+ * follow these rules so the file can be memory mapped. Otherwise the pointers
+ * to these tables will not work well or at all on some machines. With all
+ * padding zeroed like objects will compare byte for byte.
+ }
+
+type
+ load_command = record
+ cmd : uint32_t; { type of load command }
+ cmdsize : uint32_t; { total size of command in bytes }
+ end;
+ pload_command = ^load_command;
+
+ {
+ * After MacOS X 10.1 when a new load command is added that is required to be
+ * understood by the dynamic linker for the image to execute properly the
+ * LC_REQ_DYLD bit will be or'ed into the load command constant. If the dynamic
+ * linker sees such a load command it it does not understand will issue a
+ * "unknown load command required for execution" error and refuse to use the
+ * image. Other load commands without this bit that are not understood will
+ * simply be ignored.
+ }
+const
+ LC_REQ_DYLD = $80000000;
+
+{ Constants for the cmd field of all load commands, the type }
+const
+ LC_SEGMENT = $1; { segment of this file to be mapped }
+ LC_SYMTAB = $2; { link-edit stab symbol table info }
+ LC_SYMSEG = $3; { link-edit gdb symbol table info (obsolete) }
+ LC_THREAD = $4; { thread }
+ LC_UNIXTHREAD = $5; { unix thread (includes a stack) }
+ LC_LOADFVMLIB = $6; { load a specified fixed VM shared library }
+ LC_IDFVMLIB = $7; { fixed VM shared library identification }
+ LC_IDENT = $8; { object identification info (obsolete) }
+ LC_FVMFILE = $9; { fixed VM file inclusion (internal use) }
+ LC_PREPAGE = $a; { prepage command (internal use) }
+ LC_DYSYMTAB = $b; { dynamic link-edit symbol table info }
+ LC_LOAD_DYLIB = $c; { load a dynamically linked shared library }
+ LC_ID_DYLIB = $d; { dynamically linked shared lib ident }
+ LC_LOAD_DYLINKER = $e; { load a dynamic linker }
+ LC_ID_DYLINKER = $f; { dynamic linker identification }
+ LC_PREBOUND_DYLIB = $10; { modules prebound for a dynamically linked shared library }
+ LC_ROUTINES = $11; { image routines }
+ LC_SUB_FRAMEWORK = $12; { sub framework }
+ LC_SUB_UMBRELLA = $13; { sub umbrella }
+ LC_SUB_CLIENT = $14; { sub client }
+ LC_SUB_LIBRARY = $15; { sub library }
+ LC_TWOLEVEL_HINTS = $16; { two-level namespace lookup hints }
+ LC_PREBIND_CKSUM = $17; { prebind checksum }
+ LC_LOAD_WEAK_DYLIB = $18 or LC_REQ_DYLD; { load a dynamically linked shared library that is allowed to be missing (all symbols are weak imported). }
+ LC_SEGMENT_64 = $19; { 64-bit segment of this file to be mapped }
+ LC_ROUTINES_64 = $1a; { 64-bit image routines }
+ LC_UUID = $1b; { the uuid }
+ LC_RPATH = $1c or LC_REQ_DYLD; { runpath additions }
+ LC_CODE_SIGNATURE = $1d; { local of code signature }
+ LC_SEGMENT_SPLIT_INFO = $1e; { local of info to split segments }
+ LC_REEXPORT_DYLIB = $1f or LC_REQ_DYLD; { load and re-export dylib }
+ LC_LAZY_LOAD_DYLIB = $20; { delay load of dylib until first use }
+ LC_ENCRYPTION_INFO = $21; { encrypted segment information }
+ {
+ * A variable length string in a load command is represented by an lc_str
+ * union. The strings are stored just after the load command structure and
+ * the offset is from the start of the load command structure. The size
+ * of the string is reflected in the cmdsize field of the load command.
+ * Once again any padded bytes to bring the cmdsize field to a multiple
+ * of 4 bytes must be zero.
+ }
+ { offset to the string }
+{$ifndef __LP64__}
+ { pointer to the string }
+{$endif}
+
+type
+ lc_str = record
+ case longint of
+ 0 : ( offset : uint32_t );
+ 1 : ( ptr : ^char );
+ end;
+
+ {
+ * The segment load command indicates that a part of this file is to be
+ * mapped into the task's address space. The size of this segment in memory,
+ * vmsize, maybe equal to or larger than the amount to map from this file,
+ * filesize. The file is mapped starting at fileoff to the beginning of
+ * the segment in memory, vmaddr. The rest of the memory of the segment,
+ * if any, is allocated zero fill on demand. The segment's maximum virtual
+ * memory protection and initial virtual memory protection are specified
+ * by the maxprot and initprot fields. If the segment has sections then the
+ * section structures directly follow the segment command and their size is
+ * reflected in cmdsize.
+ }
+
+ { for 32-bit architectures }
+
+ segment_command = record
+ cmd : uint32_t; { LC_SEGMENT }
+ cmdsize : uint32_t; { includes sizeof section structs }
+ segname : array[0..15] of char; { segment name }
+ vmaddr : uint32_t; { memory address of this segment }
+ vmsize : uint32_t; { memory size of this segment }
+ fileoff : uint32_t; { file offset of this segment }
+ filesize : uint32_t; { amount to map from the file }
+ maxprot : vm_prot_t; { maximum VM protection }
+ initprot : vm_prot_t; { initial VM protection }
+ nsects : uint32_t; { number of sections in segment }
+ flags : uint32_t; { flags }
+ end;
+ psegment_command = ^segment_command;
+
+ {
+ * The 64-bit segment load command indicates that a part of this file is to be
+ * mapped into a 64-bit task's address space. If the 64-bit segment has
+ * sections then section_64 structures directly follow the 64-bit segment
+ * command and their size is reflected in cmdsize.
+ }
+ { for 64-bit architectures }
+
+ segment_command_64 = record
+ cmd : uint32_t; { LC_SEGMENT_64 }
+ cmdsize : uint32_t; { includes sizeof section_64 structs }
+ segname : array[0..15] of char; { segment name }
+ vmaddr : uint64_t; { memory address of this segment }
+ vmsize : uint64_t; { memory size of this segment }
+ fileoff : uint64_t; { file offset of this segment }
+ filesize : uint64_t; { amount to map from the file }
+ maxprot : vm_prot_t; { maximum VM protection }
+ initprot : vm_prot_t; { initial VM protection }
+ nsects : uint32_t; { number of sections in segment }
+ flags : uint32_t; { flags }
+ end;
+ psegment_command_64 = ^segment_command_64;
+
+ { Constants for the flags field of the segment_command }
+
+const
+ SG_HIGHVM = $1; { the file contents for this segment is for }
+ { the high part of the VM space, the low part }
+ { is zero filled (for stacks in core files) }
+
+ SG_FVMLIB = $2; { this segment is the VM that is allocated by }
+ { a fixed VM library, for overlap checking in }
+ { the link editor }
+
+ SG_NORELOC = $4; { this segment has nothing that was relocated }
+ { in it and nothing relocated to it, that is }
+ { it maybe safely replaced without relocation }
+
+ SG_PROTECTED_VERSION_1 = $8; { This segment is protected. If the }
+ { segment starts at file offset 0, the }
+ { first page of the segment is not }
+ { protected. All other pages of the }
+ { segment are protected. }
+
+ {* A segment is made up of zero or more sections. Non-MH_OBJECT files have
+ * all of their segments with the proper sections in each, and padded to the
+ * specified segment alignment when produced by the link editor. The first
+ * segment of a MH_EXECUTE and MH_FVMLIB format file contains the mach_header
+ * and load commands of the object file before its first section. The zero
+ * fill sections are always last in their segment (in all formats). This
+ * allows the zeroed segment padding to be mapped into memory where zero fill
+ * sections might be. The gigabyte zero fill sections, those with the section
+ * type S_GB_ZEROFILL, can only be in a segment with sections of this type.
+ * These segments are then placed after all other segments.
+ *
+ * The MH_OBJECT format has all of its sections in one segment for
+ * compactness. There is no padding to a specified segment boundary and the
+ * mach_header and load commands are not part of the segment.
+ *
+ * Sections with the same section name, sectname, going into the same segment,
+ * segname, are combined by the link editor. The resulting section is aligned
+ * to the maximum alignment of the combined sections and is the new section's
+ * alignment. The combined sections are aligned to their original alignment in
+ * the combined section. Any padded bytes to get the specified alignment are
+ * zeroed.
+ *
+ * The format of the relocation entries referenced by the reloff and nreloc
+ * fields of the section structure for mach object files is described in the
+ * header file <reloc.h>. }
+
+type
+ { for 32-bit architectures }
+ section = record
+ sectname : array[0..15] of char; { name of this section }
+ segname : array[0..15] of char; { segment this section goes in }
+ addr : uint32_t; { memory address of this section }
+ size : uint32_t; { size in bytes of this section }
+ offset : uint32_t; { file offset of this section }
+ align : uint32_t; { section alignment (power of 2) }
+ reloff : uint32_t; { file offset of relocation entries }
+ nreloc : uint32_t; { number of relocation entries }
+ flags : uint32_t; { flags (section type and attributes) }
+ reserved1 : uint32_t; { reserved (for offset or index) }
+ reserved2 : uint32_t; { reserved (for count or sizeof) }
+ end;
+ psection = ^section;
+
+
+ { for 64-bit architectures }
+ section_64 = record
+ sectname : array[0..15] of char; { name of this section }
+ segname : array[0..15] of char; { segment this section goes in }
+ addr : uint64_t; { memory address of this section }
+ size : uint64_t; { size in bytes of this section }
+ offset : uint32_t; { file offset of this section }
+ align : uint32_t; { section alignment (power of 2) }
+ reloff : uint32_t; { file offset of relocation entries }
+ nreloc : uint32_t; { number of relocation entries }
+ flags : uint32_t; { flags (section type and attributes) }
+ reserved1 : uint32_t; { reserved (for offset or index) }
+ reserved2 : uint32_t; { reserved (for count or sizeof) }
+ reserved3 : uint32_t; { reserved }
+ end;
+ psection_64 = ^section_64;
+
+ {* The flags field of a section structure is separated into two parts a section
+ * type and section attributes. The section types are mutually exclusive (it
+ * can only have one type) but the section attributes are not (it may have more
+ * than one attribute). }
+
+ { 256 section types }
+
+const
+ SECTION_TYPE = $000000ff; { Constants for the type of a section }
+ SECTION_ATTRIBUTES = $ffffff00; { 24 section attributes }
+ S_REGULAR = $0; { regular section }
+ S_ZEROFILL = $1; { zero fill on demand section }
+ S_CSTRING_LITERALS = $2; { section with only literal C strings }
+ S_4BYTE_LITERALS = $3; { section with only 4 byte literals }
+ S_8BYTE_LITERALS = $4; { section with only 8 byte literals }
+ S_LITERAL_POINTERS = $5; { section with only pointers to literals }
+
+ {* For the two types of symbol pointers sections and the symbol stubs section
+ * they have indirect symbol table entries. For each of the entries in the
+ * section the indirect symbol table entries, in corresponding order in the
+ * indirect symbol table, start at the index stored in the reserved1 field
+ * of the section structure. Since the indirect symbol table entries
+ * correspond to the entries in the section the number of indirect symbol table
+ * entries is inferred from the size of the section divided by the size of the
+ * entries in the section. For symbol pointers sections the size of the entries
+ * in the section is 4 bytes and for symbol stubs sections the byte size of the
+ * stubs is stored in the reserved2 field of the section structure. }
+
+ S_NON_LAZY_SYMBOL_POINTERS = $6; { section with only non-lazy symbol pointers }
+ S_LAZY_SYMBOL_POINTERS = $7; { section with only lazy symbol pointers }
+ S_SYMBOL_STUBS = $8; { section with only symbol stubs, byte size of stub in the reserved2 field }
+ S_MOD_INIT_FUNC_POINTERS = $9; { section with only function pointers for initialization }
+ S_MOD_TERM_FUNC_POINTERS = $a; { section with only function pointers for termination }
+ S_COALESCED = $b; { section contains symbols that are to be coalesced }
+ S_GB_ZEROFILL = $c; { zero fill on demand section (that can be larger than 4 gigabytes) }
+ S_INTERPOSING = $d; { section with only pairs of function pointers for interposing }
+ S_16BYTE_LITERALS = $e; { section with only 16 byte literals }
+ S_DTRACE_DOF = $f; { section contains DTrace Object Format }
+ S_LAZY_DYLIB_SYMBOL_POINTERS = $10; { section with only lazy symbol pointers to lazy loaded dylibs }
+
+ {* Constants for the section attributes part of the flags field of a section structure. }
+
+ SECTION_ATTRIBUTES_USR = $ff000000; { User setable attributes }
+
+ S_ATTR_PURE_INSTRUCTIONS = $80000000; { section contains only true machine instructions }
+ S_ATTR_NO_TOC = $40000000; { section contains coalesced symbols }
+ { that are not to be in a ranlib table of contents }
+ S_ATTR_STRIP_STATIC_SYMS = $20000000; { ok to strip static symbols this section }
+ { in files with the MH_DYLDLINK flag }
+ S_ATTR_NO_DEAD_STRIP = $10000000; { no dead stripping }
+ S_ATTR_LIVE_SUPPORT = $08000000; { blocks are live if they reference live blocks }
+ S_ATTR_SELF_MODIFYING_CODE = $04000000; { Used with i386 code stubs written on by dyld }
+
+ {
+ * If a segment contains any sections marked with S_ATTR_DEBUG then all
+ * sections in that segment must have this attribute. No section other than
+ * a section marked with this attribute may reference the contents of this
+ * section. A section with this attribute may contain no symbols and must have
+ * a section type S_REGULAR. The static linker will not copy section contents
+ * from sections with this attribute into its output file. These sections
+ * generally contain DWARF debugging info.
+ } { a debug section }
+ S_ATTR_DEBUG = $02000000;
+ { system setable attributes }
+ SECTION_ATTRIBUTES_SYS = $00ffff00;
+ { section contains some
+ machine instructions }
+ S_ATTR_SOME_INSTRUCTIONS = $00000400;
+ { section has external
+ relocation entries }
+ S_ATTR_EXT_RELOC = $00000200;
+ { section has local
+ relocation entries }
+ S_ATTR_LOC_RELOC = $00000100;
+ {
+ * The names of segments and sections in them are mostly meaningless to the
+ * link-editor. But there are few things to support traditional UNIX
+ * executables that require the link-editor and assembler to use some names
+ * agreed upon by convention.
+ *
+ * The initial protection of the "__TEXT" segment has write protection turned
+ * off (not writeable).
+ *
+ * The link-editor will allocate common symbols at the end of the "__common"
+ * section in the "__DATA" segment. It will create the section and segment
+ * if needed.
+ }
+ { The currently known segment names and the section names in those segments }
+
+
+ SEG_PAGEZERO = '__PAGEZERO'; { the pagezero segment which has no }
+ { protections and catches NULL references for MH_EXECUTE files }
+
+ SEG_TEXT = '__TEXT'; { the tradition UNIX text segment }
+ SECT_TEXT = '__text'; { the real text part of the text }
+ SECT_FVMLIB_INIT0 = '__fvmlib_init0'; { the fvmlib initialization section }
+ SECT_FVMLIB_INIT1 = '__fvmlib_init1'; { the section following the fvmlib initialization section }
+
+ SEG_DATA = '__DATA'; { the tradition UNIX data segment }
+ SECT_DATA = '__data'; { the real initialized data section no padding, no bss overlap }
+ SECT_BSS = '__bss'; { the real uninitialized data section no padding }
+ SECT_COMMON = '__common'; { the section common symbols are allocated in by the link editor }
+
+ SEG_OBJC = '__OBJC'; { objective-C runtime segment }
+ SECT_OBJC_SYMBOLS = '__symbol_table'; { symbol table }
+ SECT_OBJC_MODULES = '__module_info'; { module information }
+ SECT_OBJC_STRINGS = '__selector_strs'; { string table }
+ SECT_OBJC_REFS = '__selector_refs'; { string table }
+
+ SEG_ICON = '__ICON'; { the icon segment }
+ SECT_ICON_HEADER = '__header'; { the icon headers }
+ SECT_ICON_TIFF = '__tiff'; { the icons in tiff format }
+
+ SEG_LINKEDIT = '__LINKEDIT'; { the segment containing all structs }
+ { created and maintained by the linkeditor. }
+ { Created with -seglinkedit option to ld(1) for MH_EXECUTE and FVMLIB file types only }
+
+ SEG_UNIXSTACK = '__UNIXSTACK'; { the unix stack segment }
+
+ SEG_IMPORT = '__IMPORT'; { the segment for the self (dyld) }
+ { modifing code stubs that has read, write and execute permissions }
+
+ {* Fixed virtual memory shared libraries are identified by two things. The
+ * target pathname (the name of the library as found for execution), and the
+ * minor version number. The address of where the headers are loaded is in
+ * header_addr. (THIS IS OBSOLETE and no longer supported). }
+
+type
+ fvmlib = record
+ name : lc_str; { library's target pathname }
+ minor_version : uint32_t; { library's minor version number }
+ header_addr : uint32_t; { library's header address }
+ end;
+
+ {* A fixed virtual shared library (filetype == MH_FVMLIB in the mach header)
+ * contains a fvmlib_command (cmd == LC_IDFVMLIB) to identify the library.
+ * An object that uses a fixed virtual shared library also contains a
+ * fvmlib_command (cmd == LC_LOADFVMLIB) for each library it uses.
+ * (THIS IS OBSOLETE and no longer supported). }
+
+ fvmlib_command = record
+ cmd : uint32_t; { LC_IDFVMLIB or LC_LOADFVMLIB }
+ cmdsize : uint32_t; { includes pathname string }
+ fvmlib : fvmlib; { the library identification }
+ end;
+ pfvmlib_command = ^fvmlib_command;
+
+ {* Dynamicly linked shared libraries are identified by two things. The
+ * pathname (the name of the library as found for execution), and the
+ * compatibility version number. The pathname must match and the compatibility
+ * number in the user of the library must be greater than or equal to the
+ * library being used. The time stamp is used to record the time a library was
+ * built and copied into user so it can be use to determined if the library used
+ * at runtime is exactly the same as used to built the program. }
+
+ dylib = record
+ name : lc_str; { library's path name }
+ timestamp : uint32_t; { library's build time stamp }
+ current_version : uint32_t; { library's current version number }
+ compatibility_version : uint32_t; { library's compatibility vers number }
+ end;
+
+ {* A dynamically linked shared library (filetype == MH_DYLIB in the mach header)
+ * contains a dylib_command (cmd == LC_ID_DYLIB) to identify the library.
+ * An object that uses a dynamically linked shared library also contains a
+ * dylib_command (cmd == LC_LOAD_DYLIB, LC_LOAD_WEAK_DYLIB, or
+ * LC_REEXPORT_DYLIB) for each library it uses. }
+
+ dylib_command = record
+ cmd : uint32_t; { LC_ID_DYLIB, LC_LOAD_DYLIB,WEAK_DYLIB, LC_REEXPORT_DYLIB }
+ cmdsize : uint32_t; { includes pathname string }
+ dylib : dylib; { the library identification }
+ end;
+ pdylib_command = ^dylib_command;
+
+ {* A dynamically linked shared library may be a subframework of an umbrella
+ * framework. If so it will be linked with "-umbrella umbrella_name" where
+ * Where "umbrella_name" is the name of the umbrella framework. A subframework
+ * can only be linked against by its umbrella framework or other subframeworks
+ * that are part of the same umbrella framework. Otherwise the static link
+ * editor produces an error and states to link against the umbrella framework.
+ * The name of the umbrella framework for subframeworks is recorded in the
+ * following structure. }
+
+ sub_framework_command = record
+ cmd : uint32_t; { LC_SUB_FRAMEWORK }
+ cmdsize : uint32_t; { includes umbrella string }
+ umbrella : lc_str; { the umbrella framework name }
+ end;
+ psub_framework_command = ^sub_framework_command;
+
+
+ {* For dynamically linked shared libraries that are subframework of an umbrella
+ * framework they can allow clients other than the umbrella framework or other
+ * subframeworks in the same umbrella framework. To do this the subframework
+ * is built with "-allowable_client client_name" and an LC_SUB_CLIENT load
+ * command is created for each -allowable_client flag. The client_name is
+ * usually a framework name. It can also be a name used for bundles clients
+ * where the bundle is built with "-client_name client_name". }
+
+ sub_client_command = record
+ cmd : uint32_t; { LC_SUB_CLIENT }
+ cmdsize : uint32_t; { includes client string }
+ client : lc_str; { the client name }
+ end;
+ psub_client_command = ^sub_client_command;
+
+ {
+ * A dynamically linked shared library may be a sub_umbrella of an umbrella
+ * framework. If so it will be linked with "-sub_umbrella umbrella_name" where
+ * Where "umbrella_name" is the name of the sub_umbrella framework. When
+ * staticly linking when -twolevel_namespace is in effect a twolevel namespace
+ * umbrella framework will only cause its subframeworks and those frameworks
+ * listed as sub_umbrella frameworks to be implicited linked in. Any other
+ * dependent dynamic libraries will not be linked it when -twolevel_namespace
+ * is in effect. The primary library recorded by the static linker when
+ * resolving a symbol in these libraries will be the umbrella framework.
+ * Zero or more sub_umbrella frameworks may be use by an umbrella framework.
+ * The name of a sub_umbrella framework is recorded in the following structure.
+ }
+
+ sub_umbrella_command = record
+ cmd : uint32_t; { LC_SUB_UMBRELLA }
+ cmdsize : uint32_t; { includes sub_umbrella string }
+ sub_umbrella : lc_str; { the sub_umbrella framework name }
+ end;
+
+ {* A dynamically linked shared library may be a sub_library of another shared
+ * library. If so it will be linked with "-sub_library library_name" where
+ * Where "library_name" is the name of the sub_library shared library. When
+ * staticly linking when -twolevel_namespace is in effect a twolevel namespace
+ * shared library will only cause its subframeworks and those frameworks
+ * listed as sub_umbrella frameworks and libraries listed as sub_libraries to
+ * be implicited linked in. Any other dependent dynamic libraries will not be
+ * linked it when -twolevel_namespace is in effect. The primary library
+ * recorded by the static linker when resolving a symbol in these libraries
+ * will be the umbrella framework (or dynamic library). Zero or more sub_library
+ * shared libraries may be use by an umbrella framework or (or dynamic library).
+ * The name of a sub_library framework is recorded in the following structure.
+ * For example /usr/lib/libobjc_profile.A.dylib would be recorded as "libobjc".}
+
+ sub_library_command = record
+ cmd : uint32_t; { LC_SUB_LIBRARY }
+ cmdsize : uint32_t; { includes sub_library string }
+ sub_library : lc_str; { the sub_library name }
+ end;
+ psub_library_command = ^sub_library_command;
+
+ {* A program (filetype == MH_EXECUTE) that is
+ * prebound to its dynamic libraries has one of these for each library that
+ * the static linker used in prebinding. It contains a bit vector for the
+ * modules in the library. The bits indicate which modules are bound (1) and
+ * which are not (0) from the library. The bit for module 0 is the low bit
+ * of the first byte. So the bit for the Nth module is:
+ * (linked_modules[N/8] >> N%8) & 1 }
+
+ prebound_dylib_command = record
+ cmd : uint32_t; { LC_PREBOUND_DYLIB }
+ cmdsize : uint32_t; { includes strings }
+ name : lc_str; { library's path name }
+ nmodules : uint32_t; { number of modules in library }
+ linked_modules : lc_str; { bit vector of linked modules }
+ end;
+ pprebound_dylib_command = ^prebound_dylib_command;
+
+
+ {* A program that uses a dynamic linker contains a dylinker_command to identify
+ * the name of the dynamic linker (LC_LOAD_DYLINKER). And a dynamic linker
+ * contains a dylinker_command to identify the dynamic linker (LC_ID_DYLINKER).
+ * A file can have at most one of these.}
+
+ dylinker_command = record
+ cmd : uint32_t; { LC_ID_DYLINKER or LC_LOAD_DYLINKER }
+ cmdsize : uint32_t; { includes pathname string }
+ name : lc_str; { dynamic linker's path name }
+ end;
+ pdylinker_command = ^dylinker_command;
+
+ {
+ * Thread commands contain machine-specific data structures suitable for
+ * use in the thread state primitives. The machine specific data structures
+ * follow the struct thread_command as follows.
+ * Each flavor of machine specific data structure is preceded by an unsigned
+ * long constant for the flavor of that data structure, an uint32_t
+ * that is the count of longs of the size of the state data structure and then
+ * the state data structure follows. This triple may be repeated for many
+ * flavors. The constants for the flavors, counts and state data structure
+ * definitions are expected to be in the header file <machine/thread_status.h>.
+ * These machine specific data structures sizes must be multiples of
+ * 4 bytes The cmdsize reflects the total size of the thread_command
+ * and all of the sizes of the constants for the flavors, counts and state
+ * data structures.
+ *
+ * For executable objects that are unix processes there will be one
+ * thread_command (cmd == LC_UNIXTHREAD) created for it by the link-editor.
+ * This is the same as a LC_THREAD, except that a stack is automatically
+ * created (based on the shell's limit for the stack size). Command arguments
+ * and environment variables are copied onto that stack.
+ }
+
+ thread_command = record
+ cmd : uint32_t; { LC_THREAD or LC_UNIXTHREAD }
+ cmdsize : uint32_t; { total size of this command }
+ flavor : uint32_t; { uint32_t flavor flavor of thread state }
+ count : uint32_t; { uint32_t count count of longs in thread state }
+ { struct XXX_thread_state state thread state for this flavor }
+ { ... }
+ end;
+ pthread_command = ^thread_command;
+
+ {* The routines command contains the address of the dynamic shared library
+ * initialization routine and an index into the module table for the module
+ * that defines the routine. Before any modules are used from the library the
+ * dynamic linker fully binds the module that defines the initialization routine
+ * and then calls it. This gets called before any module initialization
+ * routines (used for C++ static constructors) in the library. }
+ { for 32-bit architectures }
+
+ routines_command = record
+ cmd : uint32_t; { LC_ROUTINES }
+ cmdsize : uint32_t; { total size of this command }
+ init_address : uint32_t; { address of initialization routine }
+ init_module : uint32_t; { index into the module table that the init routine is defined in }
+ reserved1 : uint32_t;
+ reserved2 : uint32_t;
+ reserved3 : uint32_t;
+ reserved4 : uint32_t;
+ reserved5 : uint32_t;
+ reserved6 : uint32_t;
+ end;
+ proutines_command = ^routines_command;
+
+ { * The 64-bit routines command. Same use as above. }
+ { for 64-bit architectures }
+
+ routines_command_64 = record
+ cmd : uint32_t; { LC_ROUTINES_64 }
+ cmdsize : uint32_t; { total size of this command }
+ init_address : uint64_t; { address of initialization routine }
+ init_module : uint64_t; { index into the module table that }
+ { the init routine is defined in }
+ reserved1 : uint64_t;
+ reserved2 : uint64_t;
+ reserved3 : uint64_t;
+ reserved4 : uint64_t;
+ reserved5 : uint64_t;
+ reserved6 : uint64_t;
+ end;
+ proutines_command_64 = ^routines_command_64;
+
+ {* The symtab_command contains the offsets and sizes of the link-edit 4.3BSD
+ * "stab" style symbol table information as described in the header files
+ * <nlist.h> and <stab.h>.
+ }
+
+ symtab_command = record
+ cmd : uint32_t; { LC_SYMTAB }
+ cmdsize : uint32_t; { sizeof(struct symtab_command) }
+ symoff : uint32_t; { symbol table offset }
+ nsyms : uint32_t; { number of symbol table entries }
+ stroff : uint32_t; { string table offset }
+ strsize : uint32_t; { string table size in bytes }
+ end;
+ psymtab_command = ^symtab_command;
+
+ {
+ * This is the second set of the symbolic information which is used to support
+ * the data structures for the dynamically link editor.
+ *
+ * The original set of symbolic information in the symtab_command which contains
+ * the symbol and string tables must also be present when this load command is
+ * present. When this load command is present the symbol table is organized
+ * into three groups of symbols:
+ * local symbols (static and debugging symbols) - grouped by module
+ * defined external symbols - grouped by module (sorted by name if not lib)
+ * undefined external symbols (sorted by name if MH_BINDATLOAD is not set,
+ * and in order the were seen by the static
+ * linker if MH_BINDATLOAD is set)
+ * In this load command there are offsets and counts to each of the three groups
+ * of symbols.
+ *
+ * This load command contains a the offsets and sizes of the following new
+ * symbolic information tables:
+ * table of contents
+ * module table
+ * reference symbol table
+ * indirect symbol table
+ * The first three tables above (the table of contents, module table and
+ * reference symbol table) are only present if the file is a dynamically linked
+ * shared library. For executable and object modules, which are files
+ * containing only one module, the information that would be in these three
+ * tables is determined as follows:
+ * table of contents - the defined external symbols are sorted by name
+ * module table - the file contains only one module so everything in the
+ * file is part of the module.
+ * reference symbol table - is the defined and undefined external symbols
+ *
+ * For dynamically linked shared library files this load command also contains
+ * offsets and sizes to the pool of relocation entries for all sections
+ * separated into two groups:
+ * external relocation entries
+ * local relocation entries
+ * For executable and object modules the relocation entries continue to hang
+ * off the section structures.
+ }
+
+ dysymtab_command = record
+ cmd : uint32_t; { LC_DYSYMTAB }
+ cmdsize : uint32_t; { sizeof(struct dysymtab_command) }
+ {
+ * The symbols indicated by symoff and nsyms of the LC_SYMTAB load command
+ * are grouped into the following three groups:
+ * local symbols (further grouped by the module they are from)
+ * defined external symbols (further grouped by the module they are from)
+ * undefined symbols
+ *
+ * The local symbols are used only for debugging. The dynamic binding
+ * process may have to use them to indicate to the debugger the local
+ * symbols for a module that is being bound.
+ *
+ * The last two groups are used by the dynamic binding process to do the
+ * binding (indirectly through the module table and the reference symbol
+ * table when this is a dynamically linked shared library file).
+ }
+ ilocalsym : uint32_t; { index to local symbols }
+ nlocalsym : uint32_t; { number of local symbols }
+ iextdefsym : uint32_t; { index to externally defined symbols }
+ nextdefsym : uint32_t; { number of externally defined symbols }
+ iundefsym : uint32_t; { index to undefined symbols }
+ nundefsym : uint32_t; { number of undefined symbols }
+ {
+ * For the for the dynamic binding process to find which module a symbol
+ * is defined in the table of contents is used (analogous to the ranlib
+ * structure in an archive) which maps defined external symbols to modules
+ * they are defined in. This exists only in a dynamically linked shared
+ * library file. For executable and object modules the defined external
+ * symbols are sorted by name and is use as the table of contents.
+ }
+ tocoff : uint32_t; { file offset to table of contents }
+ ntoc : uint32_t; { number of entries in table of contents }
+ {
+ * To support dynamic binding of "modules" (whole object files) the symbol
+ * table must reflect the modules that the file was created from. This is
+ * done by having a module table that has indexes and counts into the merged
+ * tables for each module. The module structure that these two entries
+ * refer to is described below. This exists only in a dynamically linked
+ * shared library file. For executable and object modules the file only
+ * contains one module so everything in the file belongs to the module.
+ }
+ modtaboff : uint32_t; { file offset to module table }
+ nmodtab : uint32_t; { number of module table entries }
+ {
+ * To support dynamic module binding the module structure for each module
+ * indicates the external references (defined and undefined) each module
+ * makes. For each module there is an offset and a count into the
+ * reference symbol table for the symbols that the module references.
+ * This exists only in a dynamically linked shared library file. For
+ * executable and object modules the defined external symbols and the
+ * undefined external symbols indicates the external references.
+ }
+ extrefsymoff : uint32_t; { offset to referenced symbol table }
+ nextrefsyms : uint32_t; { number of referenced symbol table entries }
+ {
+ * The sections that contain "symbol pointers" and "routine stubs" have
+ * indexes and (implied counts based on the size of the section and fixed
+ * size of the entry) into the "indirect symbol" table for each pointer
+ * and stub. For every section of these two types the index into the
+ * indirect symbol table is stored in the section header in the field
+ * reserved1. An indirect symbol table entry is simply a 32bit index into
+ * the symbol table to the symbol that the pointer or stub is referring to.
+ * The indirect symbol table is ordered to match the entries in the section.
+ }
+ indirectsymoff : uint32_t; { file offset to the indirect symbol table }
+ nindirectsyms : uint32_t; { number of indirect symbol table entries }
+ { * To support relocating an individual module in a library file quickly the
+ * external relocation entries for each module in the library need to be
+ * accessed efficiently. Since the relocation entries can't be accessed
+ * through the section headers for a library file they are separated into
+ * groups of local and external entries further grouped by module. In this
+ * case the presents of this load command who's extreloff, nextrel,
+ * locreloff and nlocrel fields are non-zero indicates that the relocation
+ * entries of non-merged sections are not referenced through the section
+ * structures (and the reloff and nreloc fields in the section headers are
+ * set to zero).
+ *
+ * Since the relocation entries are not accessed through the section headers
+ * this requires the r_address field to be something other than a section
+ * offset to identify the item to be relocated. In this case r_address is
+ * set to the offset from the vmaddr of the first LC_SEGMENT command.
+ * For MH_SPLIT_SEGS images r_address is set to the the offset from the
+ * vmaddr of the first read-write LC_SEGMENT command.
+ *
+ * The relocation entries are grouped by module and the module table
+ * entries have indexes and counts into them for the group of external
+ * relocation entries for that the module.
+ *
+ * For sections that are merged across modules there must not be any
+ * remaining external relocation entries for them (for merged sections
+ * remaining relocation entries must be local).
+ }
+ extreloff : uint32_t; { offset to external relocation entries }
+ nextrel : uint32_t; { number of external relocation entries }
+ { * All the local relocation entries are grouped together (they are not
+ * grouped by their module since they are only used if the object is moved
+ * from it staticly link edited address). }
+ locreloff : uint32_t; { offset to local relocation entries }
+ nlocrel : uint32_t; { number of local relocation entries }
+ end;
+
+ {
+ * An indirect symbol table entry is simply a 32bit index into the symbol table
+ * to the symbol that the pointer or stub is refering to. Unless it is for a
+ * non-lazy symbol pointer section for a defined symbol which strip(1) as
+ * removed. In which case it has the value INDIRECT_SYMBOL_LOCAL. If the
+ * symbol was also absolute INDIRECT_SYMBOL_ABS is or'ed with that.
+ }
+
+const
+ INDIRECT_SYMBOL_LOCAL = $80000000;
+ INDIRECT_SYMBOL_ABS = $40000000;
+
+type
+ dylib_table_of_contents = record { a table of contents entry }
+ symbol_index : uint32_t; { the defined external symbol (index into the symbol table) }
+ module_index : uint32_t; { index into the module table this symbol is defined in }
+ end;
+
+ dylib_module = record { a module table entry }
+ module_name : uint32_t; { the module name (index into string table) }
+ iextdefsym : uint32_t; { index into externally defined symbols }
+ nextdefsym : uint32_t; { number of externally defined symbols }
+ irefsym : uint32_t; { index into reference symbol table }
+ nrefsym : uint32_t; { number of reference symbol table entries }
+ ilocalsym : uint32_t; { index into symbols for local symbols }
+ nlocalsym : uint32_t; { number of local symbols }
+ iextrel : uint32_t; { index into external relocation entries }
+ nextrel : uint32_t; { number of external relocation entries }
+ iinit_iterm : uint32_t; { low 16 bits are the index into the init
+ section, high 16 bits are the index into
+ the term section }
+ ninit_nterm : uint32_t; { low 16 bits are the number of init section
+ entries, high 16 bits are the number of
+ term section entries }
+ objc_module_info_addr : uint32_t; { for this module address of the start of the (__OBJC,__module_info) section }
+ objc_module_info_size : uint32_t; { for this module size of the (__OBJC,__module_info) section }
+ end;
+
+ dylib_module_64 = record { a 64-bit module table entry }
+ module_name : uint32_t; { the module name (index into string table) }
+ iextdefsym : uint32_t; { index into externally defined symbols }
+ nextdefsym : uint32_t; { number of externally defined symbols }
+ irefsym : uint32_t; { index into reference symbol table }
+ nrefsym : uint32_t; { number of reference symbol table entries }
+ ilocalsym : uint32_t; { index into symbols for local symbols }
+ nlocalsym : uint32_t; { number of local symbols }
+ iextrel : uint32_t; { index into external relocation entries }
+ nextrel : uint32_t; { number of external relocation entries }
+ iinit_iterm : uint32_t; { low 16 bits are the index into the init
+ section, high 16 bits are the index into
+ the term section }
+ ninit_nterm : uint32_t; { low 16 bits are the number of init section
+ entries, high 16 bits are the number of
+ term section entries }
+ objc_module_info_size : uint32_t; { for this module size of the (__OBJC,__module_info) section }
+ objc_module_info_addr : uint64_t; { for this module address of the start of the (__OBJC,__module_info) section }
+ end;
+
+ {
+ * The entries in the reference symbol table are used when loading the module
+ * (both by the static and dynamic link editors) and if the module is unloaded
+ * or replaced. Therefore all external symbols (defined and undefined) are
+ * listed in the module's reference table. The flags describe the type of
+ * reference that is being made. The constants for the flags are defined in
+ * <mach-o/nlist.h> as they are also used for symbol table entries.
+ }
+ { index into the symbol table }
+ { flags to indicate the type of reference }
+ dylib_reference = record
+ flag0 : longint;
+ end;
+
+
+{ const
+ bm_dylib_reference_isym = $FFFFFF;
+ bp_dylib_reference_isym = 0;
+ bm_dylib_reference_flags = $FF000000;
+ bp_dylib_reference_flags = 24;
+
+ function isym(var a : dylib_reference) : uint32_t;
+ procedure set_isym(var a : dylib_reference; __isym : uint32_t);
+ function flags(var a : dylib_reference) : uint32_t;
+ procedure set_flags(var a : dylib_reference; __flags : uint32_t);}
+
+ {* The twolevel_hints_command contains the offset and number of hints in the
+ * two-level namespace lookup hints table.}
+
+type
+ twolevel_hints_command = record
+ cmd : uint32_t; { LC_TWOLEVEL_HINTS }
+ cmdsize : uint32_t; { sizeof(struct twolevel_hints_command) }
+ offset : uint32_t; { offset to the hint table }
+ nhints : uint32_t; { number of hints in the hint table }
+ end;
+
+ {
+ * The entries in the two-level namespace lookup hints table are twolevel_hint
+ * structs. These provide hints to the dynamic link editor where to start
+ * looking for an undefined symbol in a two-level namespace image. The
+ * isub_image field is an index into the sub-images (sub-frameworks and
+ * sub-umbrellas list) that made up the two-level image that the undefined
+ * symbol was found in when it was built by the static link editor. If
+ * isub-image is 0 the the symbol is expected to be defined in library and not
+ * in the sub-images. If isub-image is non-zero it is an index into the array
+ * of sub-images for the umbrella with the first index in the sub-images being
+ * 1. The array of sub-images is the ordered list of sub-images of the umbrella
+ * that would be searched for a symbol that has the umbrella recorded as its
+ * primary library. The table of contents index is an index into the
+ * library's table of contents. This is used as the starting point of the
+ * binary search or a directed linear search.
+ }
+ { index into the sub images }
+ { index into the table of contents }
+ twolevel_hint = record
+ flag0 : longint;
+ end;
+
+
+{ const
+ bm_twolevel_hint_isub_image = $FF;
+ bp_twolevel_hint_isub_image = 0;
+ bm_twolevel_hint_itoc = $FFFFFF00;
+ bp_twolevel_hint_itoc = 8;
+
+ function isub_image(var a : twolevel_hint) : uint32_t;
+ procedure set_isub_image(var a : twolevel_hint; __isub_image : uint32_t);
+ function itoc(var a : twolevel_hint) : uint32_t;
+ procedure set_itoc(var a : twolevel_hint; __itoc : uint32_t);
+}
+
+type
+ {* The prebind_cksum_command contains the value of the original check sum for
+ * prebound files or zero. When a prebound file is first created or modified
+ * for other than updating its prebinding information the value of the check sum
+ * is set to zero. When the file has it prebinding re-done and if the value of
+ * the check sum is zero the original check sum is calculated and stored in
+ * cksum field of this load command in the output file. If when the prebinding
+ * is re-done and the cksum field is non-zero it is left unchanged from the
+ * input file. }
+
+ prebind_cksum_command = record
+ cmd : uint32_t; { LC_PREBIND_CKSUM }
+ cmdsize : uint32_t; { sizeof(struct prebind_cksum_command) }
+ cksum : uint32_t; { the check sum or zero }
+ end;
+ pprebind_cksum_command = ^prebind_cksum_command;
+
+
+ {* The uuid load command contains a single 128-bit unique random number that
+ * identifies an object produced by the static link editor. }
+
+ uuid_command = record
+ cmd : uint32_t; { LC_UUID }
+ cmdsize : uint32_t; { sizeof(struct uuid_command) }
+ uuid : array[0..15] of uint8_t; { the 128-bit uuid }
+ end;
+ puuid_command = ^uuid_command;
+
+
+ {* The rpath_command contains a path which at runtime should be added to
+ * the current run path used to find @rpath prefixed dylibs.}
+
+ rpath_command = record
+ cmd : uint32_t; { LC_RPATH }
+ cmdsize : uint32_t; { includes string }
+ path : lc_str; { path to add to run path }
+ end;
+ prpath_command = ^rpath_command;
+
+
+ {* The linkedit_data_command contains the offsets and sizes of a blob
+ * of data in the __LINKEDIT segment.}
+
+ linkedit_data_command = record
+ cmd : uint32_t; { LC_CODE_SIGNATURE or LC_SEGMENT_SPLIT_INFO }
+ cmdsize : uint32_t; { sizeof(struct linkedit_data_command) }
+ dataoff : uint32_t; { file offset of data in __LINKEDIT segment }
+ datasize : uint32_t; { file size of data in __LINKEDIT segment }
+ end;
+ plinkedit_data_command = ^linkedit_data_command;
+
+
+ {* The encryption_info_command contains the file offset and size of an
+ * of an encrypted segment.}
+
+ encryption_info_command = record
+ cmd : uint32_t; { LC_ENCRYPTION_INFO }
+ cmdsize : uint32_t; { sizeof(struct encryption_info_command) }
+ cryptoff : uint32_t; { file offset of encrypted range }
+ cryptsize : uint32_t; { file size of encrypted range }
+ cryptid : uint32_t; { which enryption system, 0 means not-encrypted yet }
+ end;
+ pencryption_info_command = ^encryption_info_command;
+
+
+ {* The symseg_command contains the offset and size of the GNU style
+ * symbol table information as described in the header file <symseg.h>.
+ * The symbol roots of the symbol segments must also be aligned properly
+ * in the file. So the requirement of keeping the offsets aligned to a
+ * multiple of a 4 bytes translates to the length field of the symbol
+ * roots also being a multiple of a long. Also the padding must again be
+ * zeroed. (THIS IS OBSOLETE and no longer supported). }
+
+ symseg_command = record
+ cmd : uint32_t; { LC_SYMSEG }
+ cmdsize : uint32_t; { sizeof(struct symseg_command) }
+ offset : uint32_t; { symbol segment offset }
+ size : uint32_t; { symbol segment size in bytes }
+ end;
+ psymseg_command = ^symseg_command;
+
+
+ {* The ident_command contains a free format string table following the
+ * ident_command structure. The strings are null terminated and the size of
+ * the command is padded out with zero bytes to a multiple of 4 bytes/
+ * (THIS IS OBSOLETE and no longer supported).}
+
+ ident_command = record
+ cmd : uint32_t; { LC_IDENT }
+ cmdsize : uint32_t; { strings that follow this command }
+ end;
+ pident_command = ^ident_command;
+
+
+ {* The fvmfile_command contains a reference to a file to be loaded at the
+ * specified virtual address. (Presently, this command is reserved for
+ * internal use. The kernel ignores this command when loading a program into
+ * memory). }
+
+ fvmfile_command = record
+ cmd : uint32_t; { LC_FVMFILE }
+ cmdsize : uint32_t; { includes pathname string }
+ name : lc_str; { files pathname }
+ header_addr : uint32_t; { files virtual address }
+ end;
+ pfvmfile_command = ^fvmfile_command;
+
+
+ {* This header file describes the structures of the file format for "fat"
+ * architecture specific file (wrapper design). At the begining of the file
+ * there is one fat_header structure followed by a number of fat_arch
+ * structures. For each architecture in the file, specified by a pair of
+ * cputype and cpusubtype, the fat_header describes the file offset, file
+ * size and alignment in the file of the architecture specific member.
+ * The padded bytes in the file to place each member on it's specific alignment
+ * are defined to be read as zeros and can be left as "holes" if the file system
+ * can support them as long as they read as zeros.
+ *
+ * All structures defined here are always written and read to/from disk
+ * in big-endian order.}
+ {* <mach/machine.h> is needed here for the cpu_type_t and cpu_subtype_t types
+ * and contains the constants for the possible values of these types.}
+
+const
+ FAT_MAGIC = $cafebabe;
+ FAT_CIGAM = $bebafeca;
+
+type
+ fat_header = record
+ magic : uint32_t; { FAT_MAGIC }
+ nfat_arch : uint32_t; { number of structs that follow }
+ end;
+
+ fat_arch = record
+ cputype : cpu_type_t; { cpu specifier (int) }
+ cpusubtype : cpu_subtype_t; { machine specifier (int) }
+ offset : uint32_t; { file offset to this object file }
+ size : uint32_t; { size of this object file }
+ align : uint32_t; { alignment as a power of 2 }
+ end;
+
+
+ {
+ * Format of a symbol table entry of a Mach-O file for 32-bit architectures.
+ * Modified from the BSD format. The modifications from the original format
+ * were changing n_other (an unused field) to n_sect and the addition of the
+ * N_SECT type. These modifications are required to support symbols in a larger
+ * number of sections not just the three sections (text, data and bss) in a BSD
+ * file.
+ }
+
+type
+ nlist = record
+ n_un : record
+ case longint of
+ {$ifndef __LP64__}
+ 0 : ( n_name : Pchar ); { for use when in-core }
+ {$endif}
+ 1 : ( n_strx : int32_t ); { index into the string table }
+ end;
+ n_type : uint8_t; { type flag, see below }
+ n_sect : uint8_t; { section number or NO_SECT }
+ n_desc : int16_t; { see <mach-o/stab.h> }
+ n_value : uint32_t; { value of this symbol (or stab offset) }
+ end;
+ pnlist = ^nlist;
+
+ {* This is the symbol table entry structure for 64-bit architectures.}
+ nlist_64 = record
+ n_un : record
+ case longint of
+ 0 : ( n_strx : uint32_t ); { index into the string table }
+ end;
+ n_type : uint8_t; { type flag, see below }
+ n_sect : uint8_t; { section number or NO_SECT }
+ n_desc : uint16_t; { see <mach-o/stab.h> }
+ n_value : uint64_t; { value of this symbol (or stab offset) }
+ end;
+ pnlist_64 = ^nlist_64;
+
+ {* Symbols with a index into the string table of zero (n_un.n_strx == 0) are
+ * defined to have a null, "", name. Therefore all string indexes to non null
+ * names must not have a zero string index. This is bit historical information
+ * that has never been well documented. }
+ {* The n_type field really contains four fields:
+ * unsigned char N_STAB:3,
+ * N_PEXT:1,
+ * N_TYPE:3,
+ * N_EXT:1;
+ * which are used via the following masks.}
+
+const
+ N_STAB = $e0; { if any of these bits set, a symbolic debugging entry }
+ N_PEXT = $10; { private external symbol bit }
+ N_TYPE = $0e; { mask for the type bits }
+ N_EXT = $01; { external symbol bit, set for external symbols }
+
+ {* Only symbolic debugging entries have some of the N_STAB bits set and if any
+ * of these bits are set then it is a symbolic debugging entry (a stab). In
+ * which case then the values of the n_type field (the entire field) are given
+ * in <mach-o/stab.h> }
+
+ {* Values for N_TYPE bits of the n_type field. }
+
+ N_UNDF = $0; { undefined, n_sect == NO_SECT }
+ N_ABS = $2; { absolute, n_sect == NO_SECT }
+ N_SECT = $e; { defined in section number n_sect }
+ N_PBUD = $c; { prebound undefined (defined in a dylib) }
+ N_INDR = $a; { indirect }
+
+ {* If the type is N_INDR then the symbol is defined to be the same as another
+ * symbol. In this case the n_value field is an index into the string table
+ * of the other symbol's name. When the other symbol is defined then they both
+ * take on the defined type and value.}
+
+ {* If the type is N_SECT then the n_sect field contains an ordinal of the
+ * section the symbol is defined in. The sections are numbered from 1 and
+ * refer to sections in order they appear in the load commands for the file
+ * they are in. This means the same ordinal may very well refer to different
+ * sections in different files.
+ *
+ * The n_value field for all symbol table entries (including N_STAB's) gets
+ * updated by the link editor based on the value of it's n_sect field and where
+ * the section n_sect references gets relocated. If the value of the n_sect
+ * field is NO_SECT then it's n_value field is not changed by the link editor.}
+
+ NO_SECT = 0; { symbol is not in any section }
+ MAX_SECT = 255; { 1 thru 255 inclusive }
+ {* Common symbols are represented by undefined (N_UNDF) external (N_EXT) types
+ * who's values (n_value) are non-zero. In which case the value of the n_value
+ * field is the size (in bytes) of the common symbol. The n_sect field is set
+ * to NO_SECT. The alignment of a common symbol may be set as a power of 2
+ * between 2^1 and 2^15 as part of the n_desc field using the macros below. If
+ * the alignment is not set (a value of zero) then natural alignment based on
+ * the size is used.}
+
+ { ----- Process manually -----
+ #define GET_COMM_ALIGN(n_desc) (((n_desc) >> 8) & 0x0f)
+ #define SET_COMM_ALIGN(n_desc,align) \
+ (n_desc) = (((n_desc) & 0xf0ff) | (((align) & 0x0f) << 8))
+ }
+
+ {* To support the lazy binding of undefined symbols in the dynamic link-editor,
+ * the undefined symbols in the symbol table (the nlist structures) are marked
+ * with the indication if the undefined reference is a lazy reference or
+ * non-lazy reference. If both a non-lazy reference and a lazy reference is
+ * made to the same symbol the non-lazy reference takes precedence. A reference
+ * is lazy only when all references to that symbol are made through a symbol
+ * pointer in a lazy symbol pointer section.
+ *
+ * The implementation of marking nlist structures in the symbol table for
+ * undefined symbols will be to use some of the bits of the n_desc field as a
+ * reference type. The mask REFERENCE_TYPE will be applied to the n_desc field
+ * of an nlist structure for an undefined symbol to determine the type of
+ * undefined reference (lazy or non-lazy).
+ *
+ * The constants for the REFERENCE FLAGS are propagated to the reference table
+ * in a shared library file. In that case the constant for a defined symbol,
+ * REFERENCE_FLAG_DEFINED, is also used.}
+
+ { Reference type bits of the n_desc field of undefined symbols }
+ REFERENCE_TYPE = $7;
+
+ { types of references }
+ REFERENCE_FLAG_UNDEFINED_NON_LAZY = 0;
+ REFERENCE_FLAG_UNDEFINED_LAZY = 1;
+ REFERENCE_FLAG_DEFINED = 2;
+ REFERENCE_FLAG_PRIVATE_DEFINED = 3;
+ REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY = 4;
+ REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY = 5;
+
+ {* To simplify stripping of objects that use are used with the dynamic link
+ * editor, the static link editor marks the symbols defined an object that are
+ * referenced by a dynamicly bound object (dynamic shared libraries, bundles).
+ * With this marking strip knows not to strip these symbols.}
+ REFERENCED_DYNAMICALLY = $0010;
+
+ {* For images created by the static link editor with the -twolevel_namespace
+ * option in effect the flags field of the mach header is marked with
+ * MH_TWOLEVEL. And the binding of the undefined references of the image are
+ * determined by the static link editor. Which library an undefined symbol is
+ * bound to is recorded by the static linker in the high 8 bits of the n_desc
+ * field using the SET_LIBRARY_ORDINAL macro below. The ordinal recorded
+ * references the libraries listed in the Mach-O's LC_LOAD_DYLIB load commands
+ * in the order they appear in the headers. The library ordinals start from 1.
+ * For a dynamic library that is built as a two-level namespace image the
+ * undefined references from module defined in another use the same nlist struct
+ * an in that case SELF_LIBRARY_ORDINAL is used as the library ordinal. For
+ * defined symbols in all images they also must have the library ordinal set to
+ * SELF_LIBRARY_ORDINAL. The EXECUTABLE_ORDINAL refers to the executable
+ * image for references from plugins that refer to the executable that loads
+ * them.
+ *
+ * The DYNAMIC_LOOKUP_ORDINAL is for undefined symbols in a two-level namespace
+ * image that are looked up by the dynamic linker with flat namespace semantics.
+ * This ordinal was added as a feature in Mac OS X 10.3 by reducing the
+ * value of MAX_LIBRARY_ORDINAL by one. So it is legal for existing binaries
+ * or binaries built with older tools to have 0xfe (254) dynamic libraries. In
+ * this case the ordinal value 0xfe (254) must be treated as a library ordinal
+ * for compatibility.}
+
+ { was #define dname(params) para_def_expr }
+ { argument types are unknown }
+ { return type might be wrong }
+// function GET_LIBRARY_ORDINAL(n_desc : longint) : longint;
+
+ { -- Process Manually ---
+ #define SET_LIBRARY_ORDINAL(n_desc,ordinal) \
+ (n_desc) = (((n_desc) & 0x00ff) | (((ordinal) & 0xff) << 8))
+ }
+
+const
+ SELF_LIBRARY_ORDINAL = $0;
+ MAX_LIBRARY_ORDINAL = $fd;
+ DYNAMIC_LOOKUP_ORDINAL = $fe;
+ EXECUTABLE_ORDINAL = $ff;
+
+ {* The bit 0x0020 of the n_desc field is used for two non-overlapping purposes
+ * and has two different symbolic names, N_NO_DEAD_STRIP and N_DESC_DISCARDED. }
+
+ {* The N_NO_DEAD_STRIP bit of the n_desc field only ever appears in a
+ * relocatable .o file (MH_OBJECT filetype). And is used to indicate to the
+ * static link editor it is never to dead strip the symbol.}
+ N_NO_DEAD_STRIP = $0020; { symbol is not to be dead stripped }
+
+
+
+ {* The N_DESC_DISCARDED bit of the n_desc field never appears in linked image.
+ * But is used in very rare cases by the dynamic link editor to mark an in
+ * memory symbol as discared and longer used for linking. }
+ N_DESC_DISCARDED = $0020; { symbol is discarded }
+
+ {* The N_WEAK_REF bit of the n_desc field indicates to the dynamic linker that
+ * the undefined symbol is allowed to be missing and is to have the address of
+ * zero when missing. }
+ N_WEAK_REF = $0040; { symbol is weak referenced }
+
+ {* The N_WEAK_DEF bit of the n_desc field indicates to the static and dynamic
+ * linkers that the symbol definition is weak, allowing a non-weak symbol to
+ * also be used which causes the weak definition to be discared. Currently this
+ * is only supported for symbols in coalesed sections. }
+ N_WEAK_DEF = $0080; { coalesed symbol is a weak definition }
+
+ {* The N_REF_TO_WEAK bit of the n_desc field indicates to the dynamic linker
+ * that the undefined symbol should be resolved using flat namespace searching. }
+ N_REF_TO_WEAK = $0080; { reference to a weak symbol }
+
+ {* The N_ARM_THUMB_DEF bit of the n_desc field indicates that the symbol is
+ * a defintion of a Thumb function. }
+ N_ARM_THUMB_DEF = $0008; { symbol is a Thumb function (ARM) }
+
+ {* There are two known orders of table of contents for archives. The first is
+ * the order ranlib(1) originally produced and still produces without any
+ * options. This table of contents has the archive member name "__.SYMDEF"
+ * This order has the ranlib structures in the order the objects appear in the
+ * archive and the symbol names of those objects in the order of symbol table.
+ * The second know order is sorted by symbol name and is produced with the -s
+ * option to ranlib(1). This table of contents has the archive member name
+ * "__.SYMDEF SORTED" and many programs (notably the 1.0 version of ld(1) can't
+ * tell the difference between names because of the imbedded blank in the name
+ * and works with either table of contents). This second order is used by the
+ * post 1.0 link editor to produce faster linking. The original 1.0 version of
+ * ranlib(1) gets confused when it is run on a archive with the second type of
+ * table of contents because it and ar(1) which it uses use different ways to
+ * determined the member name (ar(1) treats all blanks in the name as
+ * significant and ranlib(1) only checks for the first one).}
+
+const
+ SYMDEF = '__.SYMDEF';
+ SYMDEF_SORTED = '__.SYMDEF SORTED';
+
+ {
+ * Structure of the __.SYMDEF table of contents for an archive.
+ * __.SYMDEF begins with a long giving the size in bytes of the ranlib
+ * structures which immediately follow, and then continues with a string
+ * table consisting of a long giving the number of bytes of strings which
+ * follow and then the strings themselves. The ran_strx fields index the
+ * string table whose first byte is numbered 0.
+ }
+
+type
+ ranlib = record
+ ran_un : record
+ case longint of
+ 0 : ( ran_strx : uint32_t );
+ 1 : ( ran_name : ^char );
+ end;
+ ran_off : uint32_t;
+ end;
+
+type
+ {* Format of a relocation entry of a Mach-O file. Modified from the 4.3BSD
+ * format. The modifications from the original format were changing the value
+ * of the r_symbolnum field for "local" (r_extern == 0) relocation entries.
+ * This modification is required to support symbols in an arbitrary number of
+ * sections not just the three sections (text, data and bss) in a 4.3BSD file.
+ * Also the last 4 bits have had the r_type tag added to them. }
+
+ relocation_info = record
+ r_address : int32_t; { offset in the section to what is being relocated }
+ r_info : longint;
+ // r_symbolnum:24, {* symbol index if r_extern == 1 or section ordinal if r_extern == 0 *}
+ // r_pcrel:1; {* was relocated pc relative already *}
+ // r_length:2; {* 0=byte, 1=word, 2=long, 3=quad *}
+ // r_extern:1; {* does not include value of sym referenced *}
+ // r_type:4; {* if not 0, machine specific relocation type *}
+ end;
+
+
+{ absolute relocation type for Mach-O files }
+
+const
+ R_ABS = 0;
+ R_SCATTERED = $80000000; { mask to be applied to the r_address field }
+ { of a relocation_info structure to tell that }
+ { is is really a scattered_relocation_info }
+ { stucture }
+
+ {
+ * The r_address is not really the address as it's name indicates but an offset.
+ * In 4.3BSD a.out objects this offset is from the start of the "segment" for
+ * which relocation entry is for (text or data). For Mach-O object files it is
+ * also an offset but from the start of the "section" for which the relocation
+ * entry is for. See comments in <mach-o/loader.h> about the r_address feild
+ * in images for used with the dynamic linker.
+ *
+ * In 4.3BSD a.out objects if r_extern is zero then r_symbolnum is an ordinal
+ * for the segment the symbol being relocated is in. These ordinals are the
+ * symbol types N_TEXT, N_DATA, N_BSS or N_ABS. In Mach-O object files these
+ * ordinals refer to the sections in the object file in the order their section
+ * structures appear in the headers of the object file they are in. The first
+ * section has the ordinal 1, the second 2, and so on. This means that the
+ * same ordinal in two different object files could refer to two different
+ * sections. And further could have still different ordinals when combined
+ * by the link-editor. The value R_ABS is used for relocation entries for
+ * absolute symbols which need no further relocation.
+ }
+ {
+ * For RISC machines some of the references are split across two instructions
+ * and the instruction does not contain the complete value of the reference.
+ * In these cases a second, or paired relocation entry, follows each of these
+ * relocation entries, using a PAIR r_type, which contains the other part of the
+ * reference not contained in the instruction. This other part is stored in the
+ * pair's r_address field. The exact number of bits of the other part of the
+ * reference store in the r_address field is dependent on the particular
+ * relocation type for the particular architecture.
+ }
+ {
+ * To make scattered loading by the link editor work correctly "local"
+ * relocation entries can't be used when the item to be relocated is the value
+ * of a symbol plus an offset (where the resulting expresion is outside the
+ * block the link editor is moving, a blocks are divided at symbol addresses).
+ * In this case. where the item is a symbol value plus offset, the link editor
+ * needs to know more than just the section the symbol was defined. What is
+ * needed is the actual value of the symbol without the offset so it can do the
+ * relocation correctly based on where the value of the symbol got relocated to
+ * not the value of the expression (with the offset added to the symbol value).
+ * So for the NeXT 2.0 release no "local" relocation entries are ever used when
+ * there is a non-zero offset added to a symbol. The "external" and "local"
+ * relocation entries remain unchanged.
+ *
+ * The implemention is quite messy given the compatibility with the existing
+ * relocation entry format. The ASSUMPTION is that a section will never be
+ * bigger than 2**24 - 1 (0x00ffffff or 16,777,215) bytes. This assumption
+ * allows the r_address (which is really an offset) to fit in 24 bits and high
+ * bit of the r_address field in the relocation_info structure to indicate
+ * it is really a scattered_relocation_info structure. Since these are only
+ * used in places where "local" relocation entries are used and not where
+ * "external" relocation entries are used the r_extern field has been removed.
+ *
+ * For scattered loading to work on a RISC machine where some of the references
+ * are split across two instructions the link editor needs to be assured that
+ * each reference has a unique 32 bit reference (that more than one reference is
+ * NOT sharing the same high 16 bits for example) so it move each referenced
+ * item independent of each other. Some compilers guarantees this but the
+ * compilers don't so scattered loading can be done on those that do guarantee
+ * this.
+ }
+
+ {
+ * The reason for the ifdef's of __BIG_ENDIAN__ and __LITTLE_ENDIAN__ are that
+ * when stattered relocation entries were added the mistake of using a mask
+ * against a structure that is made up of bit fields was used. To make this
+ * design work this structure must be laid out in memory the same way so the
+ * mask can be applied can check the same bit each time (r_scattered).
+ }
+
+
+type
+ scattered_relocation_info = record
+ {$ifdef ENDIAN_BIG}
+ r_info : longint; { r_scattered:1, /* 1=scattered, 0=non-scattered (see above) */
+ r_pcrel:1, /* was relocated pc relative already */
+ r_length:2, /* 0=byte, 1=word, 2=long, 3=quad */
+ r_type:4, /* if not 0, machine specific relocation type */
+ r_address:24; /* offset in the section to what is being relocated */}
+ r_value : int32_t; {* the value the item to be relocated is refering to (without any offset added) *}
+ {$else}
+ r_value : int32_t;
+ r_info : longint; {* r_address:24, /* offset in the section to what is being relocated */
+ r_type:4, /* if not 0, machine specific relocation type */
+ r_length:2, /* 0=byte, 1=word, 2=long, 3=quad */
+ r_pcrel:1, /* was relocated pc relative already */
+ r_scattered:1; /* 1=scattered, 0=non-scattered (see above) */ *}
+ {$endif}
+ end;
+
+ {
+ * Relocation types used in a generic implementation. Relocation entries for
+ * normal things use the generic relocation as discribed above and their r_type
+ * is GENERIC_RELOC_VANILLA (a value of zero).
+ *
+ * Another type of generic relocation, GENERIC_RELOC_SECTDIFF, is to support
+ * the difference of two symbols defined in different sections. That is the
+ * expression "symbol1 - symbol2 + constant" is a relocatable expression when
+ * both symbols are defined in some section. For this type of relocation the
+ * both relocations entries are scattered relocation entries. The value of
+ * symbol1 is stored in the first relocation entry's r_value field and the
+ * value of symbol2 is stored in the pair's r_value field.
+ *
+ * A special case for a prebound lazy pointer is needed to beable to set the
+ * value of the lazy pointer back to its non-prebound state. This is done
+ * using the GENERIC_RELOC_PB_LA_PTR r_type. This is a scattered relocation
+ * entry where the r_value feild is the value of the lazy pointer not prebound.
+ }
+
+const
+ GENERIC_RELOC_VANILLA = 0; { generic relocation as discribed above }
+ GENERIC_RELOC_PAIR = 1; { Only follows a GENERIC_RELOC_SECTDIFF }
+ GENERIC_RELOC_SECTDIFF = 2;
+ GENERIC_RELOC_PB_LA_PTR = 3; { prebound lazy pointer }
+ GENERIC_RELOC_LOCAL_SECTDIFF = 4;
+
+{*
+ * Relocations for x86_64 are a bit different than for other architectures in
+ * Mach-O: Scattered relocations are not used. Almost all relocations produced
+ * by the compiler are external relocations. An external relocation has the
+ * r_extern bit set to 1 and the r_symbolnum field contains the symbol table
+ * index of the target label.
+ *
+ * When the assembler is generating relocations, if the target label is a local
+ * label (begins with 'L'), then the previous non-local label in the same
+ * section is used as the target of the external relocation. An addend is used
+ * with the distance from that non-local label to the target label. Only when
+ * there is no previous non-local label in the section is an internal
+ * relocation used.
+ *
+ * The addend (i.e. the 4 in _foo+4) is encoded in the instruction (Mach-O does
+ * not have RELA relocations). For PC-relative relocations, the addend is
+ * stored directly in the instruction. This is different from other Mach-O
+ * architectures, which encode the addend minus the current section offset.
+ *
+ * The relocation types are:
+ *
+ * X86_64_RELOC_UNSIGNED // for absolute addresses
+ * X86_64_RELOC_SIGNED // for signed 32-bit displacement
+ * X86_64_RELOC_BRANCH // a CALL/JMP instruction with 32-bit displacement
+ * X86_64_RELOC_GOT_LOAD // a MOVQ load of a GOT entry
+ * X86_64_RELOC_GOT // other GOT references
+ * X86_64_RELOC_SUBTRACTOR // must be followed by a X86_64_RELOC_UNSIGNED
+ *
+ * The following are sample assembly instructions, followed by the relocation
+ * and section content they generate in an object file:
+ *
+ * call _foo
+ * r_type=X86_64_RELOC_BRANCH, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_foo
+ * E8 00 00 00 00
+ *
+ * call _foo+4
+ * r_type=X86_64_RELOC_BRANCH, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_foo
+ * E8 04 00 00 00
+ *
+ * movq _foo@GOTPCREL(%rip), %rax
+ * r_type=X86_64_RELOC_GOT_LOAD, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_foo
+ * 48 8B 05 00 00 00 00
+ *
+ * pushq _foo@GOTPCREL(%rip)
+ * r_type=X86_64_RELOC_GOT, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_foo
+ * FF 35 00 00 00 00
+ *
+ * movl _foo(%rip), %eax
+ * r_type=X86_64_RELOC_SIGNED, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_foo
+ * 8B 05 00 00 00 00
+ *
+ * movl _foo+4(%rip), %eax
+ * r_type=X86_64_RELOC_SIGNED, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_foo
+ * 8B 05 04 00 00 00
+ *
+ * movb $0x12, _foo(%rip)
+ * r_type=X86_64_RELOC_SIGNED, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_foo
+ * C6 05 FF FF FF FF 12
+ *
+ * movl $0x12345678, _foo(%rip)
+ * r_type=X86_64_RELOC_SIGNED, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_foo
+ * C7 05 FC FF FF FF 78 56 34 12
+ *
+ * .quad _foo
+ * r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_foo
+ * 00 00 00 00 00 00 00 00
+ *
+ * .quad _foo+4
+ * r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_foo
+ * 04 00 00 00 00 00 00 00
+ *
+ * .quad _foo - _bar
+ * r_type=X86_64_RELOC_SUBTRACTOR, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_bar
+ * r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_foo
+ * 00 00 00 00 00 00 00 00
+ *
+ * .quad _foo - _bar + 4
+ * r_type=X86_64_RELOC_SUBTRACTOR, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_bar
+ * r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_foo
+ * 04 00 00 00 00 00 00 00
+ *
+ * .long _foo - _bar
+ * r_type=X86_64_RELOC_SUBTRACTOR, r_length=2, r_extern=1, r_pcrel=0, r_symbolnum=_bar
+ * r_type=X86_64_RELOC_UNSIGNED, r_length=2, r_extern=1, r_pcrel=0, r_symbolnum=_foo
+ * 00 00 00 00
+ *
+ * lea L1(%rip), %rax
+ * r_type=X86_64_RELOC_SIGNED, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_prev
+ * 48 8d 05 12 00 00 00
+ * // assumes _prev is the first non-local label 0x12 bytes before L1
+ *
+ * lea L0(%rip), %rax
+ * r_type=X86_64_RELOC_SIGNED, r_length=2, r_extern=0, r_pcrel=1, r_symbolnum=3
+ * 48 8d 05 56 00 00 00
+ * // assumes L0 is in third section, has an address of 0x00000056 in .o
+ * // file, and there is no previous non-local label
+ *
+ * .quad L1
+ * r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_prev
+ * 12 00 00 00 00 00 00 00
+ * // assumes _prev is the first non-local label 0x12 bytes before L1
+ *
+ * .quad L0
+ * r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_extern=0, r_pcrel=0, r_symbolnum=3
+ * 56 00 00 00 00 00 00 00
+ * // assumes L0 is in third section, has an address of 0x00000056 in .o
+ * // file, and there is no previous non-local label
+ *
+ * .quad _foo - .
+ * r_type=X86_64_RELOC_SUBTRACTOR, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_prev
+ * r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_foo
+ * EE FF FF FF FF FF FF FF
+ * // assumes _prev is the first non-local label 0x12 bytes before this
+ * // .quad
+ *
+ * .quad _foo - L1
+ * r_type=X86_64_RELOC_SUBTRACTOR, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_prev
+ * r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_foo
+ * EE FF FF FF FF FF FF FF
+ * // assumes _prev is the first non-local label 0x12 bytes before L1
+ *
+ * .quad L1 - _prev
+ * // No relocations. This is an assembly time constant.
+ * 12 00 00 00 00 00 00 00
+ * // assumes _prev is the first non-local label 0x12 bytes before L1
+ *
+ *
+ *
+ * In final linked images, there are only two valid relocation kinds:
+ *
+ * r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_pcrel=0, r_extern=1, r_symbolnum=sym_index
+ * This tells dyld to add the address of a symbol to a pointer sized (8-byte)
+ * piece of data (i.e on disk the 8-byte piece of data contains the addend). The
+ * r_symbolnum contains the index into the symbol table of the target symbol.
+ *
+ * r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_pcrel=0, r_extern=0, r_symbolnum=0
+ * This tells dyld to adjust the pointer sized (8-byte) piece of data by the amount
+ * the containing image was loaded from its base address (e.g. slide).
+ *
+ *}
+
+const
+ X86_64_RELOC_UNSIGNED = 0; // for absolute addresses
+ X86_64_RELOC_SIGNED = 1; // for signed 32-bit displacement
+ X86_64_RELOC_BRANCH = 2; // a CALL/JMP instruction with 32-bit displacement
+ X86_64_RELOC_GOT_LOAD = 3; // a MOVQ load of a GOT entry
+ X86_64_RELOC_GOT = 4; // other GOT references
+ X86_64_RELOC_SUBTRACTOR = 5; // must be followed by a X86_64_RELOC_UNSIGNED
+ X86_64_RELOC_SIGNED_1 = 6; // for signed 32-bit displacement with a -1 addend
+ X86_64_RELOC_SIGNED_2 = 7; // for signed 32-bit displacement with a -2 addend
+ X86_64_RELOC_SIGNED_4 = 8; // for signed 32-bit displacement with a -4 addend
+
+
+
+
+ {* Relocation types used in the ppc implementation. Relocation entries for
+ * things other than instructions use the same generic relocation as discribed
+ * above and their r_type is RELOC_VANILLA. The rest of the relocation types
+ * are for instructions. Since they are for instructions the r_address field
+ * indicates the 32 bit instruction that the relocation is to be preformed on.
+ * The fields r_pcrel and r_length are ignored for non-RELOC_VANILLA r_types
+ * except for PPC_RELOC_BR14.
+ *
+ * For PPC_RELOC_BR14 if the r_length is the unused value 3, then the branch was
+ * statically predicted setting or clearing the Y-bit based on the sign of the
+ * displacement or the opcode. If this is the case the static linker must flip
+ * the value of the Y-bit if the sign of the displacement changes for non-branch
+ * always conditions.
+ }
+
+const
+ PPC_RELOC_VANILLA = 0; { generic relocation as discribed above }
+ PPC_RELOC_PAIR = 1; { the second relocation entry of a pair }
+ PPC_RELOC_BR14 = 2; { 14 bit branch displacement (to a word address) }
+ PPC_RELOC_BR24 = 3; { 24 bit branch displacement (to a word address) }
+ PPC_RELOC_HI16 = 4; { a PAIR follows with the low half }
+ PPC_RELOC_LO16 = 5; { a PAIR follows with the high half }
+ PPC_RELOC_HA16 = 6; { Same as the RELOC_HI16 except the low 16 bits and the }
+ { * high 16 bits are added together with the low 16 bits }
+ { * sign extened first. This means if bit 15 of the low }
+ { * 16 bits is set the high 16 bits stored in the }
+ { * instruction will be adjusted. }
+ PPC_RELOC_LO14 = 7; { Same as the LO16 except that the low 2 bits are not }
+ { * stored in the instruction and are always zero. This }
+ { * is used in double word load/store instructions. }
+ PPC_RELOC_SECTDIFF = 8; { a PAIR follows with subtract symbol value }
+ PPC_RELOC_PB_LA_PTR = 9; { prebound lazy pointer }
+ PPC_RELOC_HI16_SECTDIFF = 10; { section difference forms of above. a PAIR }
+ PPC_RELOC_LO16_SECTDIFF = 11; { follows these with subtract symbol value }
+ PPC_RELOC_HA16_SECTDIFF = 12;
+ PPC_RELOC_JBSR = 13;
+ PPC_RELOC_LO14_SECTDIFF = 14;
+ PPC_RELOC_LOCAL_SECTDIFF = 15; { like PPC_RELOC_SECTDIFF, but the symbol referenced was local. }
+
+ {
+ * Symbolic debugger symbols. The comments give the conventional use for
+ *
+ * .stabs "n_name", n_type, n_sect, n_desc, n_value
+ *
+ * where n_type is the defined constant and not listed in the comment. Other
+ * fields not listed are zero. n_sect is the section ordinal the entry is
+ * refering to.
+ }
+
+const
+ N_GSYM = $20; { global symbol: name,,NO_SECT,type,0 }
+ N_FNAME = $22; { procedure name (f77 kludge): name,,NO_SECT,0,0 }
+ N_FUN = $24; { procedure: name,,n_sect,linenumber,address }
+ N_STSYM = $26; { static symbol: name,,n_sect,type,address }
+ N_LCSYM = $28; { .lcomm symbol: name,,n_sect,type,address }
+ N_BNSYM = $2e; { begin nsect sym: 0,,n_sect,0,address }
+ N_OPT = $3c; { emitted with gcc2_compiled and in gcc source }
+ N_RSYM = $40; { register sym: name,,NO_SECT,type,register }
+ N_SLINE = $44; { src line: 0,,n_sect,linenumber,address }
+ N_ENSYM = $4e; { end nsect sym: 0,,n_sect,0,address }
+ N_SSYM = $60; { structure elt: name,,NO_SECT,type,struct_offset }
+ N_SO = $64; { source file name: name,,n_sect,0,address }
+ N_OSO = $66; { object file name: name,,0,0,st_mtime }
+ N_LSYM = $80; { local sym: name,,NO_SECT,type,offset }
+ N_BINCL = $82; { include file beginning: name,,NO_SECT,0,sum }
+ N_SOL = $84; { #included file name: name,,n_sect,0,address }
+ N_PARAMS = $86; { compiler parameters: name,,NO_SECT,0,0 }
+ N_VERSION = $88; { compiler version: name,,NO_SECT,0,0 }
+ N_OLEVEL = $8A; { compiler -O level: name,,NO_SECT,0,0 }
+ N_PSYM = $a0; { parameter: name,,NO_SECT,type,offset }
+ N_EINCL = $a2; { include file end: name,,NO_SECT,0,0 }
+ N_ENTRY = $a4; { alternate entry: name,,n_sect,linenumber,address }
+ N_LBRAC = $c0; { left bracket: 0,,NO_SECT,nesting level,address }
+ N_EXCL = $c2; { deleted include file: name,,NO_SECT,0,sum }
+ N_RBRAC = $e0; { right bracket: 0,,NO_SECT,nesting level,address }
+ N_BCOMM = $e2; { begin common: name,,NO_SECT,0,0 }
+ N_ECOMM = $e4; { end common: name,,n_sect,0,0 }
+ N_ECOML = $e8; { end common (local name): 0,,n_sect,0,address }
+ N_LENG = $fe; { second stab entry with length information }
+ { * for the berkeley pascal compiler, pc(1): }
+ N_PC = $30; { global pascal symbol: name,,NO_SECT,subtype,line }
+
+implementation
+
+end.
+
+
+
diff --git a/closures/compiler/machoutils.pas b/closures/compiler/machoutils.pas
new file mode 100644
index 0000000000..b9060b3127
--- /dev/null
+++ b/closures/compiler/machoutils.pas
@@ -0,0 +1,1466 @@
+{
+ Copyright (c) 2009-2010 by Dmitry Boyarintsev
+
+ Contains utility routines and types for handling mach-o structure and types.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+
+}
+
+unit machoutils;
+
+interface
+
+{$mode objfpc}{$h+}
+
+uses
+ macho;
+
+ type
+ TRawWriter=class(TObject)
+ public
+ procedure WriteRaw(const data; datasize: Integer); virtual; abstract;
+ end;
+
+ TRawReader=class(TObject)
+ public
+ function ReadRaw(var data; datasize: Integer): Integer; virtual; abstract;
+ function Seek(pos: qword): Boolean; virtual; abstract;
+ function ReadPos: qword; virtual; abstract;
+ end;
+
+ TMachHeader=record
+ cputype : cpu_type_t;
+ cpusubtype : cpu_subtype_t;
+ filetype : longword;
+ ncmds : longword;
+ sizeofcmds : longword;
+ flags : longword;
+ end;
+
+ TSegmentName=string[16];
+ TSectionName=TSegmentName;
+
+ TMachoSegment=record
+ segname : TSegmentName;
+ vmaddr : qword;
+ vmsize : qword;
+ fileoff : qword;
+ filesize : qword;
+ maxprot : vm_prot_t;
+ initprot : vm_prot_t;
+ nsects : longword;
+ flags : longword;
+ end;
+
+ TMachoSection=record
+ sectname : TSectionName;
+ segname : TSegmentName;
+ addr : uint64_t;
+ size : uint64_t;
+ offset : uint32_t;
+ align : uint32_t;
+ reloff : uint32_t;
+ nreloc : uint32_t;
+ flags : uint32_t;
+
+ indirectIndex : Integer; // reserved1 for LAZY and NON_LAZY pointers
+ stubSize : Integer; // reserved2 for S_SYMBOL_STUBS
+ end;
+
+ TMachoRoutine=record
+ init_address : uint64_t; { address of initialization routine }
+ init_module : uint64_t; { index into the module table that }
+ end;
+
+ { TMachoWriter }
+
+ TMachoWriter=class(TObject)
+ private
+ fwriter : TRawWriter;
+ fown : Boolean;
+ protected
+ public
+ constructor Create(ARawWriter: TRawWriter; AllowFreeWriter: Boolean);
+ destructor Destroy; override;
+
+ { non platform specific writer }
+ procedure WriteData(const data; dataSize: Integer);
+ procedure WriteUint8(i: uint8_t);
+
+ { endian specific writer }
+ procedure WriteUint16(i: uint16_t); virtual; abstract;
+ procedure WriteUint32(i: uint32_t); virtual; abstract;
+ procedure WriteUint64(i: uint64_t); virtual; abstract;
+
+ { endian and ptr-size specific writer }
+ procedure WritePtr(ofs: QWord); virtual; abstract; // ptr is 32 bit for 32-bit platforms
+
+ { macro utility methods }
+
+ procedure WriteHeader(const hdr: TMachHeader); virtual; abstract;
+ procedure WriteSegmentCmd(const seg: TMachoSegment; cmdSize: LongWord); virtual; abstract;
+ procedure WriteSection(const sec: TMachoSection); virtual; abstract;
+ procedure WriteRoutineCmd(const rt: TMachoRoutine); virtual; abstract;
+ procedure WriteLoadCommand(const cmd: load_command); virtual; abstract; overload;
+ procedure WriteLoadCommand(cmd, cmdsize: Integer); overload;
+ procedure WriteRelocation(const ri: relocation_info); virtual; abstract;
+ procedure WriteScatterReloc(const ri: scattered_relocation_info); virtual; abstract;
+ procedure WriteNList(const list: nlist_64); virtual; abstract;
+ end;
+
+ { TLE32MachoWriter }
+
+ TLE32MachoWriter=class(TMachoWriter)
+ public
+ procedure WriteUint16(i: uint16_t); override;
+ procedure WriteUint32(i: uint32_t); override;
+ procedure WriteUint64(i: uint64_t); override;
+ procedure WritePtr(ofs: QWord); override;
+
+ procedure WriteHeader(const hdr: TMachHeader); override;
+ procedure WriteSegmentCmd(const seg: TMachoSegment; ACmdSize: LongWord); override;
+ procedure WriteSection(const sec: TMachoSection); override;
+ procedure WriteRoutineCmd(const rt: TMachoRoutine); override;
+ procedure WriteLoadCommand(const cmd: load_command); override;
+ procedure WriteRelocation(const ri: relocation_info); override;
+ procedure WriteScatterReloc(const ri: scattered_relocation_info); override;
+ procedure WriteNList(const list: nlist_64); override;
+ end;
+
+ { TLE64MachoWriter }
+
+ TLE64MachoWriter=class(TLE32MachoWriter)
+ public
+ procedure WritePtr(ofs: QWord); override;
+
+ procedure WriteHeader(const hdr: TMachHeader); override;
+ procedure WriteSegmentCmd(const seg: TMachoSegment; acmdSize: LongWord); override;
+ procedure WriteSection(const sec: TMachoSection); override;
+ procedure WriteRoutineCmd(const rt: TMachoRoutine); override;
+ procedure WriteNList(const list: nlist_64); override;
+ end;
+
+ { TBE32MachoWriter }
+
+ TBE32MachoWriter=class(TMachoWriter)
+ public
+ procedure WriteUint16(i: uint16_t); override;
+ procedure WriteUint32(i: uint32_t); override;
+ procedure WriteUint64(i: uint64_t); override;
+ procedure WritePtr(ofs: QWord); override;
+
+ procedure WriteHeader(const hdr: TMachHeader); override;
+ procedure WriteSegmentCmd(const seg: TMachoSegment; acmdSize: LongWord); override;
+ procedure WriteSection(const sec: TMachoSection); override;
+ procedure WriteRoutineCmd(const rt: TMachoRoutine); override;
+ procedure WriteLoadCommand(const cmd: load_command); override;
+ procedure WriteRelocation(const ri: relocation_info); override;
+ procedure WriteScatterReloc(const ri: scattered_relocation_info); override;
+ procedure WriteNList(const list: nlist_64); override;
+ end;
+
+ { TBE64MachoWriter }
+
+ TBE64MachoWriter=class(TBE32MachoWriter)
+ public
+ procedure WritePtr(ofs: QWord); override;
+
+ procedure WriteHeader(const hdr: TMachHeader); override;
+ procedure WriteSegmentCmd(const seg: TMachoSegment; acmdSize: LongWord); override;
+ procedure WriteSection(const sec: TMachoSection); override;
+ procedure WriteRoutineCmd(const rt: TMachoRoutine); override;
+ procedure WriteNList(const list: nlist_64); override;
+ end;
+
+
+ { TLEMachoStructConverter }
+
+ { converter for Little-endian structures to Host }
+ TLEMachoStructConverter = class(TObject)
+ public
+ procedure ConvertMachoHeader(const mh: mach_header; var hdr: TMachHeader); virtual;
+ procedure ConvertMachoHeader64(const mh: mach_header_64; var hdr: TMachHeader); virtual;
+ procedure ConvertLoadCommand(var cmd: load_command); virtual;
+ procedure ConvertSegment(const segcmd: segment_command; var segment: TMachoSegment); virtual;
+ procedure ConvertSegment64(const segcmd: segment_command_64; var segment: TMachoSegment); virtual;
+ procedure ConvertSection(const sec: section; var section: TMachoSection); virtual;
+ procedure ConvertSection64(const sec: section_64; var section: TMachoSection); virtual;
+
+ procedure ConvertUInt16(var v: Word); virtual;
+ procedure ConvertUInt32(var v: LongWord); virtual;
+ procedure ConvertUInt64(var v: qWord); virtual;
+ end;
+
+ { converter for Big-endian structures to Host }
+ TBEMachoStructConverter = class(TLEMachoStructConverter);
+
+ {common}
+ TMachoStructConverter = TLEMachoStructConverter;
+
+ { TMachoReader }
+
+ TMachoReader=class(TObject)
+ private
+ fReader : TRawReader;
+ HdrOfs : qword;
+ fCnv : TMachoStructConverter;
+ fHdr : TMachHeader;
+ is64 : Boolean;
+ cmdofs : array of qword;
+ cmds : array of load_command;
+ protected
+ function IntReadStruct: Boolean;
+ public
+ constructor Create(ARawReader: TRawReader; StartOfs: QWord=0);
+ function ReadHeader(var hdr: TMachHeader): Boolean;
+ function ReadCommandID(index: LongWord; var cmd: load_command): Boolean;
+ function GetCmdOfs(index: LongWord): qword;
+
+ function ReadSegmentCommand(cmdindex: LongWord; var segment: TMachoSegment): Boolean;
+ function ReadSection(segindex, secindex: LongWord; var machsection: TMachoSection): Boolean;
+
+ function ReadSymTabCmd(var symcmd: symtab_command): Boolean;
+
+ function ReadUInt32(var v: LongWord): Boolean;
+ function ReadData(var data; dataSize: Integer): Integer;
+
+ {todo: ReadNList - using index of symbol, instead of file offset?}
+ function GetNListSize: Integer;
+ function ReadNList(fileofs: qword; var nsym: nlist_64): Boolean;
+
+ procedure Seek(apos: qword);
+ end;
+
+ const
+ seg_TEXT : TSegmentName = '__TEXT';
+ seg_DATA : TSegmentName = '__DATA';
+ seg_OBJC : TSegmentName = '__OBJC';
+ seg_IMPORT : TSegmentName = '__IMPORT';
+ seg_DWARF : TSegmentName = '__DWARF';
+
+ function AllocMachoWriter(cputarget: cpu_type_t; ARawWriter: TRawWriter; AllowFreeWriter: Boolean): TMachoWriter;
+
+ function sizeMachHeader(cputarget: cpu_type_t): integer; inline;
+ function sizeSegment(cputarget: cpu_type_t): integer; inline;
+ function sizeSection(cputarget: cpu_type_t): integer; inline;
+ function sizeNList(cputarget: cpu_type_t): integer; inline;
+
+ function AlignAddr(cputarget: cpu_type_t; addr: qword): qword;
+
+ procedure InitSegment(var seg: TMachoSegment);
+
+ function MakeSectionName(const segName, secName: shortstring): shortstring;
+ function GetSegmentSectionName(const objSecName: shortstring; var segName, secName: shortstring): shortstring;
+
+ function GetSectionFlags(const segName, secName: shortstring): LongWord;
+
+ type
+ TRelocInfoLength = (ril_byte = 0, ril_word = 1, ril_long = 2, ril_quad = 3);
+
+ procedure RelocInfo(addr, symnum, reltype: integer; len: TRelocInfoLength; pcrel, extern: Boolean; var info: relocation_info);
+ procedure ScatterRelocInfo(value, addr, reltype: integer; len: TRelocInfoLength; pcrel: Boolean; var info: scattered_relocation_info);
+
+ function GetReserved1(const macho: TMachoSection): integer;
+ function GetReserved2(const macho: TMachoSection): integer;
+
+ function GetStubSize(cputarget: Integer; Pic: Boolean): Integer;
+ function MachoAlign(al: integer): integer;
+
+implementation
+
+ function MachoAlign(al: integer): integer;
+ begin
+ Result:=0;
+ al:=al shr 1;
+ while al>0 do
+ begin
+ inc(Result);
+ al:=al shr 1;
+ end;
+ end;
+
+
+ function AllocConverter(magic: LongWord): TMachoStructConverter;
+ begin
+ {$ifdef ENDIAN_BIG}
+ if magic=MH_MAGIC then
+ Result:=TBEMachoStructConverter.Create
+ else
+ Result:=TLEMachoStructConverter.Create;
+ {$else}
+ if magic=MH_MAGIC then
+ Result:=TLEMachoStructConverter.Create
+ else
+ Result:=TBEMachoStructConverter.Create;
+ {$endif}
+ end;
+
+
+ {result values are used from aggas.pas, see TGNUAssembler.WriteSection }
+ function GetStubSize(cputarget: Integer; Pic: Boolean): Integer;
+ begin
+ case cputarget of
+ CPU_TYPE_I386, CPU_TYPE_X86_64:
+ Result:=5;
+ CPU_TYPE_POWERPC, CPU_TYPE_POWERPC64:
+ if Pic then
+ Result:=32
+ else
+ Result:=16;
+ CPU_TYPE_ARM:
+ if Pic then
+ Result:=16
+ else
+ Result:=12;
+ else
+ Result:=-1;
+ end;
+ end;
+
+
+ function GetReserved1(const macho: TMachoSection): integer;
+ begin
+ case macho.flags and SECTION_TYPE of
+ S_NON_LAZY_SYMBOL_POINTERS, S_LAZY_SYMBOL_POINTERS:
+ Result:=macho.indirectIndex;
+ else
+ Result:=0;
+ end;
+ end;
+
+
+ function GetReserved2(const macho: TMachoSection): integer;
+ begin
+ case macho.flags and SECTION_TYPE of
+ S_SYMBOL_STUBS:
+ Result:=macho.stubSize
+ else
+ Result:=0;
+ end;
+ end;
+
+
+ procedure RelocInfo(addr, symnum, reltype: integer; len: TRelocInfoLength; pcrel, extern: Boolean; var info: relocation_info);
+ {$ifdef ENDIAN_BIG}
+ const
+ relbit : array [Boolean] of Integer = (0, 1 shl 7);
+ extbit : array [Boolean] of Integer = (0, 1 shl 4);
+ ri_len_mask : array [TRelocInfoLength] of Integer = (0 shl 5, 1 shl 5, 2 shl 5, 3 shl 5);
+ begin
+ info.r_address:=addr;
+ info.r_info:=((symnum and $FFFFFF) shl 8) or // r_symbolnum:24
+ relbit[pcrel] or // r_pcrel:1;
+ ri_len_mask[len] or // r_length:2;
+ extbit[extern] or // r_extern:1;
+ (reltype and $F); // r_type:4;
+ end;
+ {$else}
+ const
+ relbit : array [Boolean] of Integer = (0, 1 shl 24);
+ extbit : array [Boolean] of Integer = (0, 1 shl 27);
+ ri_len_mask : array [TRelocInfoLength] of Integer = (0 shl 25, 1 shl 25, 2 shl 25, 3 shl 25);
+ begin
+ info.r_address:=addr;
+ info.r_info:=(symnum and $FFFFFF) or // r_symbolnum:24
+ relbit[pcrel] or // r_pcrel:1;
+ extbit[extern] or // r_length:2;
+ ri_len_mask[len] or // r_extern:1;
+ (reltype shl 28); // r_type:4;
+ end;
+ {$endif}
+
+
+const
+ si_len_mask: array [TRelocInfoLength] of Integer = (0 shl 28, 1 shl 28, 2 shl 28, 3 shl 28);
+ si_type_ofs = 24;
+ si_pcrel_bit = 1 shl 30;
+ si_scatter_bit = 1 shl 31;
+ si_addr_ofs = 0;
+
+
+ procedure ScatterRelocInfo(value, addr, reltype: integer; len: TRelocInfoLength; pcrel: Boolean; var info: scattered_relocation_info);
+ const
+ relbit : array [Boolean] of Integer = (0, si_pcrel_bit);
+ begin
+ // big endian
+ info.r_info:=si_scatter_bit or // r_scattered:1, /* 1=scattered, 0=non-scattered (see above) */
+ relbit[pcrel] or // r_pcrel:1, /* was relocated pc relative already */
+ si_len_mask[len] or // r_length:2, /* 0=byte, 1=word, 2=long, 3=quad */
+ ((reltype and $F) shl si_type_ofs) or // r_type:4, /* if not 0, machine specific relocation type */
+ ((addr and $FFFFFF) shl si_addr_ofs); // r_address:24; /* offset in the section to what is being relocated */}
+ info.r_value:=value;
+ // little endian
+ // r_address:24, /* offset in the section to what is being relocated */
+ // r_type:4, /* if not 0, machine specific relocation type */
+ // r_length:2, /* 0=byte, 1=word, 2=long, 3=quad */
+ // r_pcrel:1, /* was relocated pc relative already */
+ // r_scattered:1; /* 1=scattered, 0=non-scattered (see above) */ *}
+ end;
+
+
+ function GetSectionFlags(const segName, secName: shortstring): LongWord;
+ begin
+ Result:=0;
+ if segName = seg_DATA then
+ begin
+ if secName = '__nl_symbol_ptr' then
+ Result:=Result or S_NON_LAZY_SYMBOL_POINTERS
+ else if secName = '__la_symbol_ptr' then
+ Result:=Result or S_LAZY_SYMBOL_POINTERS
+ else if secName = '__common' then
+ Result:=Result or S_ZEROFILL
+ end
+ else if segName = seg_TEXT then
+ begin
+ if (secName = '__text') then
+ Result:=Result or S_ATTR_PURE_INSTRUCTIONS or S_ATTR_SOME_INSTRUCTIONS
+ else if secName = '__textcoal_nt' then
+ Result:=Result or S_ATTR_PURE_INSTRUCTIONS or S_ATTR_SOME_INSTRUCTIONS or S_COALESCED
+ else if secName = '.fpc' then
+ Result:=Result or S_ATTR_NO_DEAD_STRIP
+ else if secName = '__cstring' then
+ Result:=Result or S_CSTRING_LITERALS;
+ end
+ else if (segName = seg_IMPORT) then
+ begin
+ if (secName = '__jump_table') then
+ Result:=Result or S_SYMBOL_STUBS or S_ATTR_SELF_MODIFYING_CODE or S_ATTR_SOME_INSTRUCTIONS
+ end
+ else if (segName=seg_OBJC) then
+ begin
+ Result:=S_ATTR_NO_DEAD_STRIP;
+ if secName='__message_refs' then
+ Result:=Result or S_ATTR_NO_DEAD_STRIP or S_LITERAL_POINTERS
+ else if secName='__cls_refs' then
+ Result:=Result or S_ATTR_NO_DEAD_STRIP or S_LITERAL_POINTERS;
+ end;
+ end;
+
+
+ function MakeSectionName(const segName, secName: shortstring): shortstring;
+ begin
+ if segName = '' then
+ Result:=secName
+ else
+ Result:=segName+' '+secName;
+ end;
+
+
+ function GetSegmentSectionName(const objSecName: shortstring; var segName, secName: shortstring): shortstring;
+ var
+ i : integer;
+ begin
+ i:=Pos(' ', objSecName);
+ if i>0 then
+ begin
+ segName:=copy(objsecName, 1, i-1);
+ secName:=copy(objsecName, i+1, length(objsecName)-i);
+ end
+ else
+ begin
+ segName:='';
+ secName:=objSecName;
+ end;
+ Result:=objSecName;
+ end;
+
+
+ procedure InitSegment(var seg: TMachoSegment);
+ begin
+ FillChar(seg, sizeof(seg), 0);
+ seg.initprot:=VM_PROT_ALL;
+ seg.maxprot:=VM_PROT_ALL;
+ end;
+
+
+ const
+ is64MachHeaderSize : array [Boolean] of Integer = ( sizeof(mach_header), sizeof(mach_header_64));
+ is64SectionSize : array [Boolean] of Integer = ( sizeof(section), sizeof(section_64));
+ is64SegmentSize : array [Boolean] of Integer = ( sizeof(segment_command), sizeof(segment_command_64));
+ is64NListSize : array [Boolean] of Integer = (sizeof(nlist), sizeof(nlist_64));
+
+ function AlignAddr(cputarget: cpu_type_t; addr: qword): qword;
+ var
+ md : array [Boolean] of integer = (4, 8);
+ p : PtrUInt;
+ begin
+ p:=addr;
+ p:=align(p, md[cputarget and CPU_ARCH_ABI64 > 0]);
+ Result:=qword(p);
+ end;
+
+
+ function sizeMachHeader(cputarget: cpu_type_t): integer;
+ begin
+ Result:=is64MachHeaderSize[ cputarget and CPU_ARCH_ABI64 > 0];
+ end;
+
+
+ function sizeSegment(cputarget: cpu_type_t): integer;
+ begin
+ Result:=is64SegmentSize[ cputarget and CPU_ARCH_ABI64 > 0];
+ end;
+
+
+ function sizeSection(cputarget: cpu_type_t): integer;
+ begin
+ Result:=is64SectionSize[ cputarget and CPU_ARCH_ABI64 > 0];
+ end;
+
+
+ function sizeNList(cputarget: cpu_type_t): integer; inline;
+ begin
+ Result:=is64NlistSize[ cputarget and CPU_ARCH_ABI64 > 0];
+ end;
+
+
+ function AllocMachoWriter(cputarget: cpu_type_t; ARawWriter: TRawWriter; AllowFreeWriter: Boolean): TMachoWriter;
+ begin
+ case cputarget of
+ CPU_TYPE_I386,
+ CPU_TYPE_ARM: Result:=TLE32MachoWriter.Create(ARawWriter, AllowFreeWriter);
+ CPU_TYPE_X86_64: Result:=TLE64MachoWriter.Create(ARawWriter, AllowFreeWriter);
+ CPU_TYPE_POWERPC: Result:=TBE32MachoWriter.Create(ARawWriter, AllowFreeWriter);
+ CPU_TYPE_POWERPC64: Result:=TBE64MachoWriter.Create(ARawWriter, AllowFreeWriter);
+ else
+ begin
+ if AllowFreeWriter then
+ ARawWriter.Free;
+ Result:=nil;
+ end;
+ end;
+ end;
+
+
+ { TMachoWriter }
+
+ procedure TMachoWriter.WriteData(const data; dataSize: Integer);
+ begin
+ if not assigned(fwriter) then
+ Exit;
+ fwriter.WriteRaw(data, dataSize);
+ end;
+
+
+ procedure TMachoWriter.WriteUint8(i: uint8_t);
+ begin
+ WriteData(i, sizeof(i));
+ end;
+
+
+ procedure TMachoWriter.WriteLoadCommand(cmd, cmdsize: Integer);
+ var
+ m : load_command;
+ begin
+ m.cmd:=cmd;
+ m.cmdsize:=cmdsize;
+ WriteLoadCommand(m);
+ end;
+
+
+ constructor TMachoWriter.Create(ARawWriter: TRawWriter; AllowFreeWriter: Boolean);
+ begin
+ inherited Create;
+ fwriter:=ARawWriter;
+ fown:=AllowFreeWriter;
+ end;
+
+
+ destructor TMachoWriter.Destroy;
+ begin
+ if fown then
+ fwriter.Free;
+ inherited Destroy;
+ end;
+
+
+ { TLE32MachoWriter }
+
+ procedure TLE32MachoWriter.WriteHeader(const hdr: TMachHeader);
+ var
+ m : mach_header;
+ begin
+ with m do
+ begin
+ magic:=NtoLE(MH_MAGIC);
+ cputype:=NtoLE(hdr.cputype);
+ cpusubtype:=NtoLE(hdr.cpusubtype);
+ filetype:=NtoLE(hdr.filetype);
+ ncmds:=NtoLE(hdr.ncmds);
+ sizeofcmds:=NtoLE(hdr.sizeofcmds);
+ flags:=NtoLE(hdr.flags);
+ end;
+ WriteData(m, sizeof(m));
+ end;
+
+
+ procedure TLE32MachoWriter.WriteSegmentCmd(const seg: TMachoSegment; ACmdSize: LongWord);
+ var
+ m : segment_command;
+ begin
+ with m do
+ begin
+ cmd:=NtoLE(LC_SEGMENT);
+ cmdsize:=NtoLE(ACmdSize);
+ segname:=seg.segname;
+ vmaddr:=NtoLE(uint32_t(seg.vmaddr));
+ vmsize:=NtoLE(uint32_t(seg.vmsize));
+ fileoff:=NtoLE(uint32_t(seg.fileoff));
+ filesize:=NtoLE(uint32_t(seg.filesize));
+ maxprot:=NtoLE(seg.maxprot);
+ initprot:=NtoLE(seg.initprot);
+ nsects:=NtoLE(seg.nsects);
+ flags:=NtoLE(seg.flags);
+ end;
+ WriteData(m, sizeof(m));
+ end;
+
+
+ procedure TLE32MachoWriter.WriteSection(const sec: TMachoSection);
+ var
+ m : section;
+ begin
+ FillChar(m, sizeof(m), 0);
+ with m do
+ begin
+ sectname:=sec.sectname;
+ segname:=sec.segname;
+ addr:=NtoLE(sec.addr);
+ size:=NtoLE(sec.size);
+ offset:=NtoLE(sec.offset);
+ align:=NtoLE(sec.align);
+ reloff:=NtoLE(sec.reloff);
+ nreloc:=NtoLE(sec.nreloc);
+ flags:=NtoLE(sec.flags);
+ reserved1:=NtoLE( GetReserved1(sec));
+ reserved2:=NtoLE( GetReserved2(sec));
+ end;
+ WriteData(m, sizeof(m));
+ end;
+
+
+ procedure TLE32MachoWriter.WriteRoutineCmd(const rt: TMachoRoutine);
+ var
+ m : routines_command;
+ begin
+ FillChar(m, sizeof(m), 0);
+ with m do
+ begin
+ cmd:=NtoLE(LC_ROUTINES);
+ cmdsize:=NtoLE(sizeof(m));
+ init_address:=NtoLE(rt.init_address);
+ init_module:=NtoLE(rt.init_module);
+ end;
+ WriteData(m, sizeof(m));
+ end;
+
+
+ procedure TLE32MachoWriter.WriteLoadCommand(const cmd: load_command);
+ var
+ m : load_command;
+ begin
+ m.cmd:=NtoLE(cmd.cmd);
+ m.cmdsize:=NtoLE(cmd.cmdsize);
+ WriteData(m, sizeof(m));
+ end;
+
+
+ procedure TLE32MachoWriter.WriteRelocation(const ri: relocation_info);
+ var
+ m : relocation_info;
+ begin
+ m.r_address:=NtoLE(ri.r_address);
+ m.r_info:=NtoLE(ri.r_info);
+ WriteData(m, sizeof(m));
+ end;
+
+
+ procedure TLE32MachoWriter.WriteScatterReloc(const ri: scattered_relocation_info);
+ var
+ m : LongWord;
+ begin
+ m:=LongWord(ri.r_info);
+ WriteUint32(NtoLE(m));
+
+ m:=LongWord(ri.r_value);
+ WriteUint32(NtoLE(m));
+ end;
+
+
+ procedure TLE32MachoWriter.WriteNList(const list: nlist_64);
+ var
+ m : nlist;
+ begin
+ m.n_un.n_strx:=NtoLe(list.n_un.n_strx);
+ m.n_type:=NtoLe(list.n_type);
+ m.n_sect:=NtoLe(list.n_sect);
+ m.n_desc:=NtoLe(list.n_desc);
+ m.n_value:=NtoLe(list.n_value);
+ WriteData(m, sizeof(m));
+ end;
+
+
+ procedure TLE32MachoWriter.WriteUint16(i: uint16_t);
+ var
+ m: uint16_t;
+ begin
+ m:=NtoLE(i);
+ WriteData(m, sizeof(m));
+ end;
+
+
+ procedure TLE32MachoWriter.WriteUint32(i: uint32_t);
+ var
+ m: uint32_t;
+ begin
+ m:=NtoLE(i);
+ WriteData(m, sizeof(m));
+ end;
+
+
+ procedure TLE32MachoWriter.WriteUint64(i: uint64_t);
+ var
+ m: uint64_t;
+ begin
+ m:=NtoLE(i);
+ WriteData(m, sizeof(m));
+ end;
+
+
+ procedure TLE32MachoWriter.WritePtr(ofs: QWord);
+ var
+ m: uint32_t;
+ begin
+ m:=NtoLE(ofs);
+ WriteData(m, sizeof(m));
+ end;
+
+
+ { TLE64MachoWriter }
+
+ procedure TLE64MachoWriter.WritePtr(ofs: QWord);
+ var
+ m : uint64_t;
+ begin
+ m:=NtoLE(ofs);
+ Writedata(m, sizeof(m));
+ end;
+
+
+ procedure TLE64MachoWriter.WriteHeader(const hdr: TMachHeader);
+ var
+ m : mach_header_64;
+ begin
+ with m do
+ begin
+ magic:=NtoLE(MH_MAGIC_64);
+ cputype:=NtoLE(hdr.cputype);
+ cpusubtype:=NtoLE(hdr.cpusubtype);
+ filetype:=NtoLE(hdr.filetype);
+ ncmds:=NtoLE(hdr.ncmds);
+ sizeofcmds:=NtoLE(hdr.sizeofcmds);
+ flags:=NtoLE(hdr.flags);
+ reserved:=0;
+ end;
+ WriteData(m, sizeof(m));
+ end;
+
+
+ procedure TLE64MachoWriter.WriteSegmentCmd(const seg: TMachoSegment; acmdSize: LongWord);
+ var
+ m : segment_command_64;
+ begin
+ with m do
+ begin
+ cmd:=NtoLE(LC_SEGMENT_64);
+ cmdsize:=NtoLE(acmdSize);
+ segname:=seg.segname;
+ vmaddr:=NtoLE(seg.vmaddr);
+ vmsize:=NtoLE(seg.vmsize);
+ fileoff:=NtoLE(seg.fileoff);
+ filesize:=NtoLE(seg.filesize);
+ maxprot:=NtoLE(seg.maxprot);
+ initprot:=NtoLE(seg.initprot);
+ nsects:=NtoLE(seg.nsects);
+ flags:=NtoLE(seg.flags);
+ end;
+ WriteData(m, sizeof(m));
+ end;
+
+
+ procedure TLE64MachoWriter.WriteSection(const sec: TMachoSection);
+ var
+ m : section_64;
+ begin
+ FillChar(m, sizeof(m), 0);
+ with m do
+ begin
+ sectname:=sec.sectname;
+ segname:=sec.segname;
+ addr:=NtoLE(sec.addr);
+ size:=NtoLE(sec.size);
+ offset:=NtoLE(sec.offset);
+ align:=NtoLE(sec.align);
+ reloff:=NtoLE(sec.reloff);
+ nreloc:=NtoLE(sec.nreloc);
+ flags:=NtoLE(sec.flags);
+ reserved1:=NtoLE( GetReserved1(sec));
+ reserved2:=NtoLE( GetReserved2(sec));
+ end;
+ WriteData(m, sizeof(m));
+ end;
+
+
+ procedure TLE64MachoWriter.WriteRoutineCmd(const rt: TMachoRoutine);
+ var
+ m : routines_command_64;
+ begin
+ FillChar(m, sizeof(m), 0);
+ with m do
+ begin
+ cmd:=NtoLE(LC_ROUTINES);
+ cmdsize:=NtoLE(sizeof(m));
+ init_address:=NtoLE(rt.init_address);
+ init_module:=NtoLE(rt.init_module);
+ end;
+ WriteData(m, sizeof(m));
+ end;
+
+
+ procedure TLE64MachoWriter.WriteNList(const list: nlist_64);
+ var
+ m : nlist_64;
+ begin
+ m.n_un.n_strx:=NtoLe(list.n_un.n_strx);
+ m.n_type:=NtoLe(list.n_type);
+ m.n_sect:=NtoLe(list.n_sect);
+ m.n_desc:=NtoLe(list.n_desc);
+ m.n_value:=NtoLe(list.n_value);
+ WriteData(m, sizeof(m));
+ end;
+
+
+ { TBE32MachoWriter }
+
+ procedure TBE32MachoWriter.WriteHeader(const hdr: TMachHeader);
+ var
+ m : mach_header;
+ begin
+ with m do
+ begin
+ magic:=NtoBE(MH_MAGIC);
+ cputype:=NtoBE(hdr.cputype);
+ cpusubtype:=NtoBE(hdr.cpusubtype);
+ filetype:=NtoBE(hdr.filetype);
+ ncmds:=NtoBE(hdr.ncmds);
+ sizeofcmds:=NtoBE(hdr.sizeofcmds);
+ flags:=NtoBE(hdr.flags);
+ end;
+ WriteData(m, sizeof(m));
+ end;
+
+
+ procedure TBE32MachoWriter.WriteSegmentCmd(const seg: TMachoSegment; acmdSize: LongWord);
+ var
+ m : segment_command;
+ begin
+ with m do
+ begin
+ cmd:=NtoBE(LC_SEGMENT);
+ cmdsize:=NtoBE(acmdSize);
+ segname:=seg.segname;
+ vmaddr:=NtoBE(uint32_t(seg.vmaddr));
+ vmsize:=NtoBE(uint32_t(seg.vmsize));
+ fileoff:=NtoBE(uint32_t(seg.fileoff));
+ filesize:=NtoBE(uint32_t(seg.filesize));
+ maxprot:=NtoBE(seg.maxprot);
+ initprot:=NtoBE(seg.initprot);
+ nsects:=NtoBE(seg.nsects);
+ flags:=NtoBE(seg.flags);
+ end;
+ WriteData(m, sizeof(m));
+ end;
+
+
+ procedure TBE32MachoWriter.WriteSection(const sec: TMachoSection);
+ var
+ m : section;
+ begin
+ FillChar(m, sizeof(m), 0);
+ with m do
+ begin
+ sectname:=sec.sectname;
+ segname:=sec.segname;
+ addr:=NtoBE(sec.addr);
+ size:=NtoBE(sec.size);
+ offset:=NtoBE(sec.offset);
+ align:=NtoBE(sec.align);
+ reloff:=NtoBE(sec.reloff);
+ nreloc:=NtoBE(sec.nreloc);
+ flags:=NtoBE(sec.flags);
+ reserved1:=NtoBE( GetReserved1(sec));
+ reserved2:=NtoBE( GetReserved2(sec));
+ end;
+ WriteData(m, sizeof(m));
+ end;
+
+
+ procedure TBE32MachoWriter.WriteRoutineCmd(const rt: TMachoRoutine);
+ var
+ m : routines_command;
+ begin
+ FillChar(m, sizeof(m), 0);
+ with m do
+ begin
+ cmd:=NtoBE(LC_ROUTINES);
+ cmdsize:=NtoBE(sizeof(m));
+ init_address:=NtoBE(rt.init_address);
+ init_module:=NtoBE(rt.init_module);
+ end;
+ WriteData(m, sizeof(m));
+ end;
+
+
+ procedure TBE32MachoWriter.WriteLoadCommand(const cmd: load_command);
+ var
+ m : load_command;
+ begin
+ m.cmd:=NtoBE(cmd.cmd);
+ m.cmdsize:=NtoBE(cmd.cmdsize);
+ WriteData(m, sizeof(m));
+ end;
+
+
+ procedure TBE32MachoWriter.WriteRelocation(const ri: relocation_info);
+ var
+ m : relocation_info;
+ begin
+ m.r_address:=NtoBE(ri.r_address);
+ m.r_info:=NtoBE(ri.r_info);
+ WriteData(m, sizeof(m));
+ end;
+
+
+ procedure TBE32MachoWriter.WriteScatterReloc(const ri: scattered_relocation_info);
+ var
+ m : LongWord;
+ begin
+ m:=LongWord(ri.r_info);
+ WriteUint32(NtoBE(m));
+
+ m:=LongWord(ri.r_value);
+ WriteUint32(NtoBE(m));
+ end;
+
+
+ procedure TBE32MachoWriter.WriteNList(const list: nlist_64);
+ var
+ m : nlist;
+ begin
+ m.n_un.n_strx:=NtoBe(list.n_un.n_strx);
+ m.n_type:=NtoBe(list.n_type);
+ m.n_sect:=NtoBe(list.n_sect);
+ m.n_desc:=NtoBe(list.n_desc);
+ m.n_value:=NtoBe(list.n_value);
+ WriteData(m, sizeof(m));
+ end;
+
+
+ procedure TBE32MachoWriter.WriteUint16(i: uint16_t);
+ var
+ m: uint16_t;
+ begin
+ m:=NtoBE(i);
+ WriteData(m, sizeof(m));
+ end;
+
+
+ procedure TBE32MachoWriter.WriteUint32(i: uint32_t);
+ var
+ m: uint32_t;
+ begin
+ m:=NtoBE(i);
+ WriteData(m, sizeof(m));
+ end;
+
+
+ procedure TBE32MachoWriter.WriteUint64(i: uint64_t);
+ var
+ m: uint64_t;
+ begin
+ m:=NtoBE(i);
+ WriteData(m, sizeof(m));
+ end;
+
+
+ procedure TBE32MachoWriter.WritePtr(ofs: QWord);
+ var
+ m: uint32_t;
+ begin
+ m:=NtoBE(ofs);
+ WriteData(m, sizeof(m));
+ end;
+
+
+ { TBE64MachoWriter }
+
+ procedure TBE64MachoWriter.WritePtr(ofs: QWord);
+ var
+ m : uint64_t;
+ begin
+ m:=NtoBE(ofs);
+ Writedata(m, sizeof(m));
+ end;
+
+
+ procedure TBE64MachoWriter.WriteHeader(const hdr: TMachHeader);
+ var
+ m : mach_header_64;
+ begin
+ with m do
+ begin
+ magic:=NtoBE(MH_MAGIC_64);
+ cputype:=NtoBE(hdr.cputype);
+ cpusubtype:=NtoBE(hdr.cpusubtype);
+ filetype:=NtoBE(hdr.filetype);
+ ncmds:=NtoBE(hdr.ncmds);
+ sizeofcmds:=NtoBE(hdr.sizeofcmds);
+ flags:=NtoBE(hdr.flags);
+ reserved:=0;
+ end;
+ WriteData(m, sizeof(m));
+ end;
+
+
+ procedure TBE64MachoWriter.WriteSegmentCmd(const seg: TMachoSegment; acmdSize: LongWord);
+ var
+ m : segment_command_64;
+ begin
+ with m do
+ begin
+ cmd:=NtoBE(LC_SEGMENT_64);
+ cmdsize:=NtoBE(acmdSize);
+ segname:=seg.segname;
+ vmaddr:=NtoBE(seg.vmaddr);
+ vmsize:=NtoBE(seg.vmsize);
+ fileoff:=NtoBE(seg.fileoff);
+ filesize:=NtoBE(seg.filesize);
+ maxprot:=NtoBE(seg.maxprot);
+ initprot:=NtoBE(seg.initprot);
+ nsects:=NtoBE(seg.nsects);
+ flags:=NtoBE(seg.flags);
+ end;
+ WriteData(m, sizeof(m));
+ end;
+
+
+ procedure TBE64MachoWriter.WriteSection(const sec: TMachoSection);
+ var
+ m : section_64;
+ begin
+ FillChar(m, sizeof(m), 0);
+ with m do
+ begin
+ sectname:=sec.sectname;
+ segname:=sec.segname;
+ addr:=NtoBE(sec.addr);
+ size:=NtoBE(sec.size);
+ offset:=NtoBE(sec.offset);
+ align:=NtoBE(sec.align);
+ reloff:=NtoBE(sec.reloff);
+ nreloc:=NtoBE(sec.nreloc);
+ flags:=NtoBE(sec.flags);
+ reserved1:=NtoBE( GetReserved1(sec));
+ reserved2:=NtoBE( GetReserved2(sec));
+ end;
+ WriteData(m, sizeof(m));
+ end;
+
+
+ procedure TBE64MachoWriter.WriteRoutineCmd(const rt: TMachoRoutine);
+ var
+ m : routines_command_64;
+ begin
+ FillChar(m, sizeof(m), 0);
+ with m do
+ begin
+ cmd:=NtoBE(LC_ROUTINES);
+ cmdsize:=NtoBE(sizeof(m));
+ init_address:=NtoBE(rt.init_address);
+ init_module:=NtoBE(rt.init_module);
+ end;
+ WriteData(m, sizeof(m));
+ end;
+
+
+ procedure TBE64MachoWriter.WriteNList(const list: nlist_64);
+ var
+ m : nlist_64;
+ begin
+ m.n_un.n_strx:=NtoBe(list.n_un.n_strx);
+ m.n_type:=NtoBe(list.n_type);
+ m.n_sect:=NtoBe(list.n_sect);
+ m.n_desc:=NtoBe(list.n_desc);
+ m.n_value:=NtoBe(list.n_value);
+ WriteData(m, sizeof(m));
+ end;
+
+
+ { TMachoReader }
+
+ constructor TMachoReader.Create(ARawReader: TRawReader; StartOfs: QWord=0);
+ begin
+ inherited Create;
+ fReader:=ARawReader;
+ hdrofs:=StartOfs;
+ end;
+
+
+ function TMachoReader.IntReadStruct: Boolean;
+ var
+ m : mach_header_64;
+ i : Integer;
+ p : qword;
+ begin
+ Result:=false;
+ if not fReader.Seek(hdrofs) then
+ Exit;
+ //todo:
+ fReader.ReadRaw(m, sizeof(mach_header_64));
+ fCnv:=AllocConverter(m.magic);
+ fCnv.ConvertMachoHeader(pmach_header(@m)^, fhdr);
+ is64:=fhdr.cputype and CPU_ARCH_ABI64>0;
+ Result:=true;
+
+ SetLength(cmds, fHdr.ncmds);
+ if fHdr.ncmds>0 then
+ begin
+ if is64 then
+ p:=sizeof(mach_header_64)
+ else
+ p:=sizeof(mach_header);
+
+ SetLength(cmdofs, fHdr.ncmds);
+ for i:=0 to fHdr.ncmds - 1 do
+ begin
+ cmdofs[i]:=p;
+ fReader.Seek(p);
+ fReader.ReadRaw(cmds[i], sizeof(cmds[i]));
+ fCnv.ConvertLoadCommand(cmds[i]);
+ inc(p, cmds[i].cmdsize);
+ end;
+ end;
+ end;
+
+
+ function TMachoReader.ReadHeader(var hdr: TMachHeader): Boolean;
+ begin
+ if not Assigned(fCnv) then
+ Result:=IntReadStruct
+ else
+ Result:=true;
+ hdr:=fhdr;
+ end;
+
+
+ function TMachoReader.ReadCommandID(index: LongWord; var cmd: load_command): Boolean;
+ begin
+ if not Assigned(fCnv) then
+ IntReadStruct;
+ Result:={(index>=0) and }(index<fHdr.ncmds);
+ if not Result then
+ Exit;
+ Result:=true;
+ cmd:=cmds[index];
+ end;
+
+
+ function TMachoReader.ReadSegmentCommand(cmdindex: LongWord; var segment: TMachoSegment): Boolean;
+ var
+ seg64 : segment_command_64;
+ seg32 : segment_command;
+ begin
+ if not Assigned(fCnv) then
+ IntReadStruct;
+
+ Result:={(cmdindex>=0) and }
+ (cmdindex<fHdr.ncmds) and
+ (cmds[cmdindex].cmd in [LC_SEGMENT, LC_SEGMENT_64]);
+
+ if Result then
+ begin
+ fReader.Seek(cmdofs[cmdindex]);
+ if is64 then
+ begin
+ Result:=fReader.ReadRaw(seg64, sizeof(seg64))=sizeof(seg64);
+ if Result then
+ fCnv.ConvertSegment64(seg64, segment);
+ end
+ else
+ begin
+ Result:=fReader.ReadRaw(seg32, sizeof(seg32))=sizeof(seg32);
+ if Result then
+ fCnv.ConvertSegment(seg32, segment);
+ end;
+ end;
+ end;
+
+
+ function TMachoReader.GetCmdOfs(index: LongWord): qword;
+ begin
+ if not Assigned(fCnv) then
+ IntReadStruct;
+
+ if {(index<0) or}
+ (index>=longword(length(cmdofs))) then
+ Result:=0
+ else
+ Result:=cmdofs[index];
+ end;
+
+
+ function TMachoReader.ReadSection(segindex, secindex: LongWord; var machsection: TMachoSection): Boolean;
+ var
+ ofs : qword;
+ is64bit : Boolean;
+ buf : array [0..sizeof(section_64)-1] of byte;
+ const
+ sectsize : array[Boolean] of LongWord = ( sizeof(macho.section), sizeof(macho.section_64));
+ segsize : array[Boolean] of LongWord = ( sizeof(macho.segment_command), sizeof(macho.segment_command_64));
+ begin
+ if not Assigned(fCnv) then
+ IntReadStruct;
+ Result:={(secindex>=0) and (segindex>=0) and }(segindex<fHdr.ncmds) and (cmds[segindex].cmd in [LC_SEGMENT, LC_SEGMENT_64]);
+ if not Result then
+ Exit;
+
+ is64bit:=cmds[segindex].cmd=LC_SEGMENT_64;
+ Result:=secindex<(cmds[segindex].cmdsize-segsize[is64bit]) div sectsize[is64bit];
+ if not Result then
+ Exit;
+
+ ofs:=cmdofs[segindex]+segsize[is64bit]+sectsize[is64]*secindex;
+ fReader.Seek(ofs);
+ fReader.ReadRaw(buf, segsize[is64bit]);
+ if is64bit then
+ fCnv.ConvertSection64( psection_64(@buf)^, machsection)
+ else
+ fCnv.ConvertSection( psection(@buf)^, machsection);
+ end;
+
+
+ function TMachoReader.ReadUInt32(var v: LongWord): Boolean;
+ begin
+ if not Assigned(fCnv) then
+ IntReadStruct;
+ Result:=Assigned(fCnv) and (fReader.ReadRaw(v, sizeof(v))=sizeof(v));
+ if Result then
+ fCnv.ConvertUint32(v);
+ end;
+
+
+ function TMachoReader.ReadData(var data; dataSize: Integer): Integer;
+ begin
+ Result:=fReader.ReadRaw(data, dataSize);
+ end;
+
+
+ function TMachoReader.GetNListSize: Integer;
+ begin
+ if is64 then
+ Result:=sizeof(nlist_64)
+ else
+ Result:=sizeof(nlist);
+ end;
+
+
+ function TMachoReader.ReadNList(fileofs: qword; var nsym: nlist_64): Boolean;
+ var
+ n32 : nlist;
+ begin
+ fReader.Seek(fileofs);
+ if is64 then
+ Result:=fReader.ReadRaw(nsym, sizeof(nlist_64))=sizeof(nlist_64)
+ else
+ begin
+ Result:=fReader.ReadRaw(n32, sizeof(nlist))=sizeof(nlist);
+ nsym.n_un.n_strx:=n32.n_un.n_strx;
+ nsym.n_desc:=n32.n_desc;
+ nsym.n_sect:=n32.n_sect;
+ nsym.n_type:=n32.n_type;
+ nsym.n_value:=n32.n_value;
+ end;
+ fCnv.ConvertUInt32(nsym.n_un.n_strx);
+ fCnv.ConvertUInt16(nsym.n_desc);
+ fCnv.ConvertUInt64(nsym.n_value);
+ end;
+
+
+ function TMachoReader.ReadSymTabCmd(var symcmd: symtab_command): Boolean;
+ var
+ i : Integer;
+ p : qword;
+ begin
+ if not Assigned(fCnv) then
+ IntReadStruct;
+
+ for i:=0 to length(cmds)-1 do
+ if cmds[i].cmd=LC_SYMTAB then
+ begin
+ p:=fReader.ReadPos;
+ fReader.Seek(cmdofs[i]);
+ fReader.ReadRaw(symcmd, sizeof(symcmd));
+ fCnv.ConvertUInt32(symcmd.cmd);
+ fCnv.ConvertUInt32(symcmd.cmdsize);
+ fCnv.ConvertUInt32(symcmd.symoff);
+ fCnv.ConvertUInt32(symcmd.nsyms);
+ fCnv.ConvertUInt32(symcmd.stroff);
+ fCnv.ConvertUInt32(symcmd.strsize);
+ fReader.Seek(p);
+ Result:=true;
+ Exit;
+ end;
+ Result:=false;
+ end;
+
+
+ procedure TMachoReader.Seek(apos: qword);
+ begin
+ fReader.Seek(apos);
+ end;
+
+
+ { TLEMachoStructConverter }
+
+ procedure TLEMachoStructConverter.ConvertMachoHeader(const mh: mach_header; var hdr: TMachHeader);
+ begin
+ hdr.cputype:=LEToN(mh.cputype);
+ hdr.cpusubtype:=LEtoN(mh.cpusubtype);
+ hdr.filetype:=LEToN(mh.filetype);
+ hdr.ncmds:=LEToN(mh.ncmds);
+ hdr.sizeofcmds:=LEToN(mh.ncmds);
+ hdr.flags:=LEToN(mh.flags);
+ end;
+
+
+ procedure TLEMachoStructConverter.ConvertMachoHeader64(const mh: mach_header_64; var hdr: TMachHeader);
+ begin
+ hdr.cputype:=LEToN(mh.cputype);
+ hdr.cpusubtype:=LEtoN(mh.cpusubtype);
+ hdr.filetype:=LEToN(mh.filetype);
+ hdr.ncmds:=LEToN(mh.ncmds);
+ hdr.sizeofcmds:=LEToN(mh.ncmds);
+ hdr.flags:=LEToN(mh.flags);
+ end;
+
+
+ procedure TLEMachoStructConverter.ConvertLoadCommand(var cmd: load_command);
+ begin
+ cmd.cmd:=LEToN(cmd.cmd);
+ cmd.cmdsize:=LEToN(cmd.cmdsize);
+ end;
+
+
+ procedure TLEMachoStructConverter.ConvertSegment(const segcmd: segment_command; var segment: TMachoSegment);
+ begin
+ FillChar(segment, sizeof(segment), 0);
+ segment.segname:=segcmd.segname;
+ segment.vmaddr:=LEToN(segcmd.vmaddr);
+ segment.vmsize:=LEToN(segcmd.vmsize);
+ segment.fileoff:=LEToN(segcmd.fileoff);
+ segment.filesize:=LEToN(segcmd.filesize);
+ segment.maxprot:=LEToN(segcmd.maxprot);
+ segment.initprot:=LEToN(segcmd.initprot);
+ writelN('segcmd.nsects = ', segcmd.nsects);
+ segment.nsects:=LEToN(segcmd.nsects);
+ segment.flags:=LEToN(segcmd.flags);
+ //todo: reserved!?
+ end;
+
+
+ procedure TMachoStructConverter.ConvertSegment64(const segcmd: segment_command_64; var segment: TMachoSegment);
+ begin
+ FillChar(segment, sizeof(segment), 0);
+ segment.segname:=segcmd.segname;
+ segment.vmaddr:=LEToN(segcmd.vmaddr);
+ segment.vmsize:=LEToN(segcmd.vmsize);
+ segment.fileoff:=LEToN(segcmd.fileoff);
+ segment.filesize:=LEToN(segcmd.filesize);
+ segment.maxprot:=LEToN(segcmd.maxprot);
+ segment.initprot:=LEToN(segcmd.initprot);
+ segment.nsects:=LEToN(segcmd.nsects);
+ segment.flags:=LEToN(segcmd.flags);
+ //todo: reserved!?
+ end;
+
+
+ procedure TMachoStructConverter.ConvertSection(const sec: section; var section: TMachoSection);
+ begin
+ FillChar(section, sizeof(section), 0);
+ section.sectname:=sec.sectname;
+ section.segname:=sec.segname;
+ section.addr:=LEToN(sec.addr);
+ section.size:=LEToN(sec.size);
+ section.offset:=LEToN(sec.offset);
+ section.align:=LEToN(sec.align);
+ section.reloff:=LEToN(sec.reloff);
+ section.nreloc:=LEToN(sec.nreloc);
+ section.flags:=LEToN(sec.flags);
+ //todo:
+ //section.indirectIndex : Integer; // reserved1 for LAZY and NON_LAZY pointers
+ //section.stubSize : Integer; // reserved2 for S_SYMBOL_STUBS
+ end;
+
+
+ procedure TMachoStructConverter.ConvertSection64(const sec: section_64; var section: TMachoSection);
+ begin
+ FillChar(section, sizeof(section), 0);
+ section.sectname:=sec.sectname;
+ section.segname:=sec.segname;
+ section.addr:=LEToN(sec.addr);
+ section.size:=LEToN(sec.size);
+ section.offset:=LEToN(sec.offset);
+ section.align:=LEToN(sec.align);
+ section.reloff:=LEToN(sec.reloff);
+ section.nreloc:=LEToN(sec.nreloc);
+ section.flags:=LEToN(sec.flags);
+ //todo:
+ //section.indirectIndex : Integer; // reserved1 for LAZY and NON_LAZY pointers
+ //section.stubSize : Integer; // reserved2 for S_SYMBOL_STUBS
+ end;
+
+
+ procedure TMachoStructConverter.ConvertUInt32(var v: LongWord);
+ begin
+ v:=LEtoN(v);
+ end;
+
+
+ procedure TMachoStructConverter.ConvertUInt64(var v: qword);
+ begin
+ v:=LEtoN(v);
+ end;
+
+
+ procedure TMachoStructConverter.ConvertUInt16(var v: Word);
+ begin
+ v:=LEToN(v);
+ end;
+
+end.
+
diff --git a/closures/compiler/mips/aasmcpu.pas b/closures/compiler/mips/aasmcpu.pas
new file mode 100644
index 0000000000..263d2a242b
--- /dev/null
+++ b/closures/compiler/mips/aasmcpu.pas
@@ -0,0 +1,449 @@
+{
+ Copyright (c) 1999-2009 by Mazen Neifer and David Zhang
+
+ Contains the assembler object for the MIPSEL
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit aasmcpu;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ cclasses,
+ globtype, globals, verbose,
+ aasmbase, aasmsym, aasmtai,
+ cgbase, cgutils, cpubase, cpuinfo;
+
+const
+ { "mov reg,reg" source operand number }
+ O_MOV_SOURCE = 0;
+ { "mov reg,reg" source operand number }
+ O_MOV_DEST = 1;
+
+type
+ taicpu = class(tai_cpu_abstract_sym)
+ delayslot_annulled: boolean; { conditinal opcode with ,a }
+ constructor op_none(op: tasmop);
+
+ constructor op_reg(op: tasmop; _op1: tregister);
+ constructor op_const(op: tasmop; _op1: longint);
+ constructor op_ref(op: tasmop; const _op1: treference);
+
+ constructor op_reg_reg(op: tasmop; _op1, _op2: tregister);
+ constructor op_reg_ref(op: tasmop; _op1: tregister; const _op2: treference);
+ constructor op_reg_const(op: tasmop; _op1: tregister; _op2: longint);
+
+ constructor op_reg_reg_reg(op: tasmop; _op1, _op2, _op3: tregister);
+
+ constructor op_reg_reg_ref(op: tasmop; _op1, _op2: tregister; const _op3: treference);
+ constructor op_reg_reg_const(op: tasmop; _op1, _op2: tregister; _op3: aint);
+
+ { this is for Jmp instructions }
+ constructor op_sym(op: tasmop; _op1: tasmsymbol);
+ constructor op_reg_reg_sym(op: tasmop; _op1, _op2: tregister; _op3: tasmsymbol);
+ constructor op_reg_sym(op: tasmop; _op1: tregister; _op2: tasmsymbol);
+ constructor op_sym_ofs(op: tasmop; _op1: tasmsymbol; _op1ofs: longint);
+
+ { register allocation }
+ function is_same_reg_move(regtype: Tregistertype): boolean; override;
+
+ { register spilling code }
+ function spilling_get_operation_type(opnr: longint): topertype; override;
+ end;
+
+ tai_align = class(tai_align_abstract)
+ { nothing to add }
+ end;
+
+ procedure InitAsm;
+ procedure DoneAsm;
+
+ function spilling_create_load(const ref: treference; r: tregister): taicpu;
+ function spilling_create_store(r: tregister; const ref: treference): taicpu;
+
+implementation
+
+{*****************************************************************************
+ taicpu Constructors
+*****************************************************************************}
+
+
+
+constructor taicpu.op_none(op: tasmop);
+begin
+ inherited Create(op);
+end;
+
+
+constructor taicpu.op_reg(op: tasmop; _op1: tregister);
+begin
+ inherited Create(op);
+ ops := 1;
+ loadreg(0, _op1);
+end;
+
+
+constructor taicpu.op_ref(op: tasmop; const _op1: treference);
+begin
+ inherited Create(op);
+ ops := 1;
+ loadref(0, _op1);
+end;
+
+
+constructor taicpu.op_const(op: tasmop; _op1: longint);
+begin
+ inherited Create(op);
+ ops := 1;
+ loadconst(0, _op1);
+end;
+
+
+constructor taicpu.op_reg_reg(op: tasmop; _op1, _op2: tregister);
+begin
+ inherited Create(op);
+ ops := 2;
+ loadreg(0, _op1);
+ loadreg(1, _op2);
+end;
+
+constructor taicpu.op_reg_const(op: tasmop; _op1: tregister; _op2: longint);
+begin
+ inherited Create(op);
+ ops := 2;
+ loadreg(0, _op1);
+ loadconst(1, _op2);
+end;
+
+
+constructor taicpu.op_reg_ref(op: tasmop; _op1: tregister; const _op2: treference);
+begin
+ inherited Create(op);
+ ops := 2;
+ loadreg(0, _op1);
+ loadref(1, _op2);
+end;
+
+
+constructor taicpu.op_reg_reg_reg(op: tasmop; _op1, _op2, _op3: tregister);
+begin
+ inherited Create(op);
+ ops := 3;
+ loadreg(0, _op1);
+ loadreg(1, _op2);
+ loadreg(2, _op3);
+end;
+
+
+constructor taicpu.op_reg_reg_ref(op: tasmop; _op1, _op2: tregister; const _op3: treference);
+ begin
+ inherited create(op);
+ ops := 3;
+ loadreg(0, _op1);
+ loadreg(1, _op2);
+ loadref(2, _op3);
+end;
+
+constructor taicpu.op_reg_reg_const(op: tasmop; _op1, _op2: tregister; _op3: aint);
+ begin
+ inherited create(op);
+ ops := 3;
+ loadreg(0, _op1);
+ loadreg(1, _op2);
+ loadconst(2, _op3);
+end;
+
+
+
+constructor taicpu.op_sym(op: tasmop; _op1: tasmsymbol);
+begin
+ inherited Create(op);
+ is_jmp := op in [A_J, A_BEQI, A_BNEI, A_BLTI, A_BLEI, A_BGTI, A_BGEI,
+ A_BLTUI, A_BLEUI, A_BGTUI, A_BGEUI,
+ A_BEQ, A_BNE, A_BLT, A_BLE, A_BGT, A_BGE,
+ A_BLTU, A_BLEU, A_BGTU, A_BGEU
+ ];
+
+ ops := 1;
+ loadsymbol(0, _op1, 0);
+end;
+
+constructor taicpu.op_reg_reg_sym(op: tasmop; _op1, _op2: tregister; _op3: tasmsymbol);
+begin
+ inherited create(op);
+ is_jmp := op in [A_J,
+ A_BEQI, A_BNEI, A_BLTI, A_BLEI, A_BGTI, A_BGEI, A_BLTUI, A_BLEUI,
+ A_BGTUI, A_BGEUI,
+ A_BEQ, A_BNE, A_BLT, A_BLE, A_BGT, A_BGE, A_BLTU, A_BLEU, A_BGTU, A_BGEU];
+ ops := 3;
+ loadreg(0, _op1);
+ loadreg(1, _op2);
+ loadsymbol(2, _op3, 0);
+end;
+
+constructor taicpu.op_reg_sym(op: tasmop; _op1: tregister; _op2: tasmsymbol);
+begin
+ inherited create(op);
+ is_jmp := op in [A_J,
+ A_BEQI, A_BNEI, A_BLTI, A_BLEI, A_BGTI, A_BGEI, A_BLTUI, A_BLEUI,
+ A_BGTUI, A_BGEUI,
+ A_BEQ, A_BNE, A_BLT, A_BLE, A_BGT, A_BGE, A_BLTU, A_BLEU, A_BGTU, A_BGEU, A_BGTZ];
+ ops := 2;
+ loadreg(0, _op1);
+ loadsymbol(1, _op2, 0);
+end;
+
+constructor taicpu.op_sym_ofs(op: tasmop; _op1: tasmsymbol; _op1ofs: longint);
+begin
+ inherited Create(op);
+ ops := 1;
+ loadsymbol(0, _op1, _op1ofs);
+end;
+
+
+function taicpu.is_same_reg_move(regtype: Tregistertype): boolean;
+begin
+ Result := (
+ ((opcode = A_MOVE) and (regtype = R_INTREGISTER)) or
+ ((regtype = R_FPUREGISTER) and (opcode in [A_MOV_S, A_MOV_D]))
+ ) and
+ (oper[0]^.reg = oper[1]^.reg);
+end;
+
+
+ function taicpu.spilling_get_operation_type(opnr: longint): topertype;
+ type
+ op_write_set_type = set of TAsmOp;
+ const
+ op_write_set: op_write_set_type =
+ [A_NEG,
+ A_NEGU,
+ A_LI,
+ A_DLI,
+ A_LA,
+ A_MOVE,
+ A_LB,
+ A_LBU,
+ A_LH,
+ A_LHU,
+ A_LW,
+ A_LWU,
+ A_LWL,
+ A_LWR,
+ A_LD,
+ A_LDL,
+ A_LDR,
+ A_LL,
+ A_LLD,
+ A_ADDI,
+ A_DADDI,
+ A_ADDIU,
+ A_DADDIU,
+ A_SLTI,
+ A_SLTIU,
+ A_ANDI,
+ A_ORI,
+ A_XORI,
+ A_LUI,
+ A_DNEG,
+ A_DNEGU,
+ A_ADD,
+ A_DADD,
+ A_ADDU,
+ A_DADDU,
+ A_SUB,
+ A_DSUB,
+ A_SUBU,
+ A_DSUBU,
+ A_SLT,
+ A_SLTU,
+ A_AND,
+ A_OR,
+ A_XOR,
+ A_NOR,
+ A_MUL,
+ A_MULO,
+ A_MULOU,
+ A_DMUL,
+ A_DMULO,
+ A_DMULOU,
+ A_DIV,
+ A_DIVU,
+ A_DDIV,
+ A_DDIVU,
+ A_REM,
+ A_REMU,
+ A_DREM,
+ A_DREMU,
+ A_MULT,
+ A_DMULT,
+ A_MULTU,
+ A_DMULTU,
+ A_MFHI,
+ A_MFLO,
+ A_MULTG,
+ A_DMULTG,
+ A_MULTUG,
+ A_DMULTUG,
+ A_DIVG,
+ A_DDIVG,
+ A_DIVUG,
+ A_DDIVUG,
+ A_MODG,
+ A_DMODG,
+ A_MODUG,
+ A_DMODUG,
+
+ A_SLL,
+ A_SRL,
+ A_SRA,
+ A_SLLV,
+ A_SRLV,
+ A_SRAV,
+ A_DSLL,
+ A_DSRL,
+ A_DSRA,
+ A_DSLLV,
+ A_DSRLV,
+ A_DSRAV,
+ A_DSLL32,
+ A_DSRL32,
+ A_DSRA32,
+ A_LWC1,
+ A_LDC1,
+
+
+ A_ADD_S,
+ A_ADD_D,
+ A_SUB_S,
+ A_SUB_D,
+ A_MUL_S,
+ A_MUL_D,
+ A_DIV_S,
+ A_DIV_D,
+ A_ABS_S,
+ A_ABS_D,
+ A_NEG_S,
+ A_NEG_D,
+ A_SQRT_S,
+ A_SQRT_D,
+ A_MOV_S,
+ A_MOV_D,
+ A_CVT_S_D,
+ A_CVT_S_W,
+ A_CVT_S_L,
+ A_CVT_D_S,
+ A_CVT_D_W,
+ A_CVT_D_L,
+ A_CVT_W_S,
+ A_CVT_W_D,
+ A_CVT_L_S,
+ A_CVT_L_D,
+ A_ROUND_W_S,
+ A_ROUND_W_D,
+ A_ROUND_L_S,
+ A_ROUND_L_D,
+ A_TRUNC_W_S,
+ A_TRUNC_W_D,
+ A_TRUNC_L_S,
+ A_TRUNC_L_D,
+ A_CEIL_W_S,
+ A_CEIL_W_D,
+ A_CEIL_L_S,
+ A_CEIL_L_D,
+ A_FLOOR_W_S,
+ A_FLOOR_W_D,
+ A_FLOOR_L_S,
+ A_FLOOR_L_D,
+ A_SEQ,
+ A_SGE,
+ A_SGEU,
+ A_SGT,
+ A_SGTU,
+ A_SLE,
+ A_SLEU,
+ A_SNE];
+
+ begin
+ result := operand_read;
+ if opcode in op_write_set then
+ if opnr = 0 then
+ result := operand_write;
+ end;
+
+
+ function spilling_create_load(const ref: treference; r: tregister): taicpu;
+ begin
+ case getregtype(r) of
+ R_INTREGISTER :
+ result:=taicpu.op_reg_ref(A_LW,r,ref);
+ R_FPUREGISTER :
+ begin
+ case getsubreg(r) of
+ R_SUBFS :
+ result:=taicpu.op_reg_ref(A_LWC1,r,ref);
+ R_SUBFD :
+ result:=taicpu.op_reg_ref(A_LDC1,r,ref);
+ else
+ internalerror(200401042);
+ end;
+ end
+ else
+ internalerror(200401041);
+ end;
+ end;
+
+
+ function spilling_create_store(r: tregister; const ref: treference): taicpu;
+ begin
+ case getregtype(r) of
+ R_INTREGISTER :
+ result:=taicpu.op_reg_ref(A_SW,r,ref);
+ R_FPUREGISTER :
+ begin
+ case getsubreg(r) of
+ R_SUBFS :
+ result:=taicpu.op_reg_ref(A_SWC1,r,ref);
+ R_SUBFD :
+ result:=taicpu.op_reg_ref(A_SDC1,r,ref);
+ else
+ internalerror(200401042);
+ end;
+ end
+ else
+ internalerror(200401041);
+ end;
+ end;
+
+
+procedure InitAsm;
+ begin
+ end;
+
+
+procedure DoneAsm;
+ begin
+ end;
+
+
+begin
+ cai_cpu := taicpu;
+ cai_align := tai_align;
+end.
diff --git a/closures/compiler/mips/aoptcpu.pas b/closures/compiler/mips/aoptcpu.pas
new file mode 100644
index 0000000000..cb656af36e
--- /dev/null
+++ b/closures/compiler/mips/aoptcpu.pas
@@ -0,0 +1,41 @@
+{
+ Copyright (c) 1998-2004 by Jonas Maebe
+
+ This unit calls the optimization procedures to optimize the assembler
+ code for sparc
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+
+unit aoptcpu;
+
+{$i fpcdefs.inc}
+
+ Interface
+
+ uses
+ cpubase, aoptobj, aoptcpub, aopt;
+
+ Type
+ TCpuAsmOptimizer = class(TAsmOptimizer)
+ End;
+
+ Implementation
+
+begin
+ casmoptimizer:=TCpuAsmOptimizer;
+end.
diff --git a/closures/compiler/mips/aoptcpub.pas b/closures/compiler/mips/aoptcpub.pas
new file mode 100644
index 0000000000..ef5d869669
--- /dev/null
+++ b/closures/compiler/mips/aoptcpub.pas
@@ -0,0 +1,119 @@
+ {
+ Copyright (c) 1998-2009 by Jonas Maebe and David Zhang
+
+ This unit contains several types and constants necessary for the
+ optimizer to work on the MIPSEL architecture
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+Unit aoptcpub; { Assembler OPTimizer CPU specific Base }
+
+{$i fpcdefs.inc}
+
+{ enable the following define if memory references can have both a base and }
+{ index register in 1 operand }
+
+{$define RefsHaveIndexReg}
+
+{ enable the following define if memory references can have a scaled index }
+
+{ define RefsHaveScale}
+
+{ enable the following define if memory references can have a segment }
+{ override }
+
+{ define RefsHaveSegment}
+
+Interface
+
+Uses
+ cpubase,aasmcpu,AOptBase;
+
+Type
+
+{ type of a normal instruction }
+ TInstr = Taicpu;
+ PInstr = ^TInstr;
+
+{ ************************************************************************* }
+{ **************************** TCondRegs ********************************** }
+{ ************************************************************************* }
+{ Info about the conditional registers }
+ TCondRegs = Object
+ Constructor Init;
+ Destructor Done;
+ End;
+
+{ ************************************************************************* }
+{ **************************** TAoptBaseCpu ******************************* }
+{ ************************************************************************* }
+
+ TAoptBaseCpu = class(TAoptBase)
+ End;
+
+
+{ ************************************************************************* }
+{ ******************************* Constants ******************************* }
+{ ************************************************************************* }
+Const
+
+{ the maximum number of things (registers, memory, ...) a single instruction }
+{ changes }
+
+ MaxCh = 3;
+
+{ the maximum number of operands an instruction has }
+
+ MaxOps = 3;
+
+{Oper index of operand that contains the source (reference) with a load }
+{instruction }
+
+ LoadSrc = 0;
+
+{Oper index of operand that contains the destination (register) with a load }
+{instruction }
+
+ LoadDst = 1;
+
+{Oper index of operand that contains the source (register) with a store }
+{instruction }
+
+ StoreSrc = 0;
+
+{Oper index of operand that contains the destination (reference) with a load }
+{instruction }
+
+ StoreDst = 1;
+
+ aopt_uncondjmp = A_J;
+ aopt_condjmp = A_BEQ;
+
+Implementation
+
+{ ************************************************************************* }
+{ **************************** TCondRegs ********************************** }
+{ ************************************************************************* }
+Constructor TCondRegs.init;
+Begin
+End;
+
+Destructor TCondRegs.Done; {$ifdef inl} inline; {$endif inl}
+Begin
+End;
+
+End.
diff --git a/closures/compiler/mips/aoptcpud.pas b/closures/compiler/mips/aoptcpud.pas
new file mode 100644
index 0000000000..cb8c5d319f
--- /dev/null
+++ b/closures/compiler/mips/aoptcpud.pas
@@ -0,0 +1,36 @@
+{
+ Copyright (c) 1998-2004 by Jonas Maebe, member of the Free Pascal
+ Development Team
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+Unit aoptcpud;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ aoptda;
+
+ type
+ TAOptDFACpu = class(TAOptDFA)
+ end;
+
+ implementation
+
+end.
diff --git a/closures/compiler/mips/cgcpu.pas b/closures/compiler/mips/cgcpu.pas
new file mode 100644
index 0000000000..6a88661bf3
--- /dev/null
+++ b/closures/compiler/mips/cgcpu.pas
@@ -0,0 +1,1980 @@
+{
+ Copyright (c) 1998-2009 by Florian Klaempfl and David Zhang
+
+ This unit implements the code generator for the MIPSEL
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit cgcpu;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ globtype, parabase,
+ cgbase, cgutils, cgobj, cg64f32,
+ aasmbase, aasmtai, aasmcpu, aasmdata,
+ cpubase, cpuinfo,
+ node, symconst, SymType, symdef,
+ rgcpu;
+
+type
+ TCgMPSel = class(tcg)
+ public
+ procedure init_register_allocators; override;
+ procedure done_register_allocators; override;
+ function getfpuregister(list: tasmlist; size: Tcgsize): Tregister; override;
+/// { needed by cg64 }
+ procedure make_simple_ref(list: tasmlist; var ref: treference);
+ procedure make_simple_ref_fpu(list: tasmlist; var ref: treference);
+ procedure handle_load_store(list: tasmlist; isstore: boolean; op: tasmop; reg: tregister; ref: treference);
+ procedure handle_load_store_fpu(list: tasmlist; isstore: boolean; op: tasmop; reg: tregister; ref: treference);
+ procedure handle_reg_const_reg(list: tasmlist; op: Tasmop; src: tregister; a: tcgint; dst: tregister);
+
+ { parameter }
+ procedure a_load_const_cgpara(list: tasmlist; size: tcgsize; a: tcgint; const paraloc: TCGPara); override;
+ procedure a_load_ref_cgpara(list: tasmlist; sz: tcgsize; const r: TReference; const paraloc: TCGPara); override;
+ procedure a_loadaddr_ref_cgpara(list: tasmlist; const r: TReference; const paraloc: TCGPara); override;
+ procedure a_loadfpu_reg_cgpara(list: tasmlist; size: tcgsize; const r: tregister; const paraloc: TCGPara); override;
+ procedure a_loadfpu_ref_cgpara(list: tasmlist; size: tcgsize; const ref: treference; const paraloc: TCGPara); override;
+ procedure a_call_name(list: tasmlist; const s: string; weak : boolean); override;
+ procedure a_call_reg(list: tasmlist; Reg: TRegister); override;
+ { General purpose instructions }
+ procedure a_op_const_reg(list: tasmlist; Op: TOpCG; size: tcgsize; a: tcgint; reg: TRegister); override;
+ procedure a_op_reg_reg(list: tasmlist; Op: TOpCG; size: TCGSize; src, dst: TRegister); override;
+ procedure a_op_const_reg_reg(list: tasmlist; op: TOpCg; size: tcgsize; a: tcgint; src, dst: tregister); override;
+ procedure a_op_reg_reg_reg(list: tasmlist; op: TOpCg; size: tcgsize; src1, src2, dst: tregister); override;
+ procedure a_op_const_reg_reg_checkoverflow(list: tasmlist; op: TOpCg; size: tcgsize; a: tcgint; src, dst: tregister; setflags: boolean; var ovloc: tlocation); override;
+ procedure a_op_reg_reg_reg_checkoverflow(list: tasmlist; op: TOpCg; size: tcgsize; src1, src2, dst: tregister; setflags: boolean; var ovloc: tlocation); override;
+ { move instructions }
+ procedure a_load_const_reg(list: tasmlist; size: tcgsize; a: tcgint; reg: tregister); override;
+ procedure a_load_const_ref(list: tasmlist; size: tcgsize; a: tcgint; const ref: TReference); override;
+ procedure a_load_reg_ref(list: tasmlist; FromSize, ToSize: TCgSize; reg: TRegister; const ref: TReference); override;
+ procedure a_load_ref_reg(list: tasmlist; FromSize, ToSize: TCgSize; const ref: TReference; reg: tregister); override;
+ procedure a_load_reg_reg(list: tasmlist; FromSize, ToSize: TCgSize; reg1, reg2: tregister); override;
+ procedure a_loadaddr_ref_reg(list: tasmlist; const ref: TReference; r: tregister); override;
+ { fpu move instructions }
+ procedure a_loadfpu_reg_reg(list: tasmlist; fromsize, tosize: tcgsize; reg1, reg2: tregister); override;
+ procedure a_loadfpu_ref_reg(list: tasmlist; fromsize, tosize: tcgsize; const ref: TReference; reg: tregister); override;
+ procedure a_loadfpu_reg_ref(list: tasmlist; fromsize, tosize: tcgsize; reg: tregister; const ref: TReference); override;
+ { comparison operations }
+ procedure a_cmp_const_reg_label(list: tasmlist; size: tcgsize; cmp_op: topcmp; a: tcgint; reg: tregister; l: tasmlabel); override;
+ procedure a_cmp_reg_reg_label(list: tasmlist; size: tcgsize; cmp_op: topcmp; reg1, reg2: tregister; l: tasmlabel); override;
+ procedure a_jmp_always(List: tasmlist; l: TAsmLabel); override;
+ procedure a_jmp_name(list: tasmlist; const s: string); override;
+ procedure a_jmp_cond(list: tasmlist; cond: TOpCmp; l: tasmlabel); { override;}
+ procedure g_overflowCheck(List: tasmlist; const Loc: TLocation; def: TDef); override;
+ procedure g_overflowCheck_loc(List: tasmlist; const Loc: TLocation; def: TDef; ovloc: tlocation); override;
+ procedure g_proc_entry(list: tasmlist; localsize: longint; nostackframe: boolean); override;
+ procedure g_proc_exit(list: tasmlist; parasize: longint; nostackframe: boolean); override;
+ procedure g_concatcopy(list: tasmlist; const Source, dest: treference; len: tcgint); override;
+ procedure g_concatcopy_unaligned(list: tasmlist; const Source, dest: treference; len: tcgint); override;
+ procedure g_concatcopy_move(list: tasmlist; const Source, dest: treference; len: tcgint);
+ procedure g_intf_wrapper(list: tasmlist; procdef: tprocdef; const labelname: string; ioffset: longint); override;
+ { Transform unsupported methods into Internal errors }
+ procedure a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; size: TCGSize; src, dst: TRegister); override;
+ procedure g_stackpointer_alloc(list : TAsmList;localsize : longint);override;
+ end;
+
+ TCg64MPSel = class(tcg64f32)
+ public
+ procedure a_load64_reg_ref(list: tasmlist; reg: tregister64; const ref: treference); override;
+ procedure a_load64_ref_reg(list: tasmlist; const ref: treference; reg: tregister64); override;
+ procedure a_load64_ref_cgpara(list: tasmlist; const r: treference; const paraloc: tcgpara); override;
+ procedure a_op64_reg_reg(list: tasmlist; op: TOpCG; size: tcgsize; regsrc, regdst: TRegister64); override;
+ procedure a_op64_const_reg(list: tasmlist; op: TOpCG; size: tcgsize; Value: int64; regdst: TRegister64); override;
+ procedure a_op64_const_reg_reg(list: tasmlist; op: TOpCG; size: tcgsize; Value: int64; regsrc, regdst: tregister64); override;
+ procedure a_op64_reg_reg_reg(list: tasmlist; op: TOpCG; size: tcgsize; regsrc1, regsrc2, regdst: tregister64); override;
+ procedure a_op64_const_reg_reg_checkoverflow(list: tasmlist; op: TOpCG; size: tcgsize; Value: int64; regsrc, regdst: tregister64; setflags: boolean; var ovloc: tlocation); override;
+ procedure a_op64_reg_reg_reg_checkoverflow(list: tasmlist; op: TOpCG; size: tcgsize; regsrc1, regsrc2, regdst: tregister64; setflags: boolean; var ovloc: tlocation); override;
+ end;
+
+ procedure create_codegen;
+
+implementation
+
+uses
+ globals, verbose, systems, cutils,
+ paramgr, fmodule,
+ tgobj,
+ procinfo, cpupi;
+
+var
+ cgcpu_calc_stackframe_size: aint;
+
+
+ function f_TOpCG2AsmOp(op: TOpCG; size: tcgsize): TAsmOp;
+ begin
+ if size = OS_32 then
+ case op of
+ OP_ADD: { simple addition }
+ f_TOpCG2AsmOp := A_ADDU;
+ OP_AND: { simple logical and }
+ f_TOpCG2AsmOp := A_AND;
+ OP_DIV: { simple unsigned division }
+ f_TOpCG2AsmOp := A_DIVU;
+ OP_IDIV: { simple signed division }
+ f_TOpCG2AsmOp := A_DIV;
+ OP_IMUL: { simple signed multiply }
+ f_TOpCG2AsmOp := A_MULT;
+ OP_MUL: { simple unsigned multiply }
+ f_TOpCG2AsmOp := A_MULTU;
+ OP_NEG: { simple negate }
+ f_TOpCG2AsmOp := A_NEGU;
+ OP_NOT: { simple logical not }
+ f_TOpCG2AsmOp := A_NOT;
+ OP_OR: { simple logical or }
+ f_TOpCG2AsmOp := A_OR;
+ OP_SAR: { arithmetic shift-right }
+ f_TOpCG2AsmOp := A_SRA;
+ OP_SHL: { logical shift left }
+ f_TOpCG2AsmOp := A_SLL;
+ OP_SHR: { logical shift right }
+ f_TOpCG2AsmOp := A_SRL;
+ OP_SUB: { simple subtraction }
+ f_TOpCG2AsmOp := A_SUBU;
+ OP_XOR: { simple exclusive or }
+ f_TOpCG2AsmOp := A_XOR;
+ else
+ InternalError(2007070401);
+ end{ case }
+ else
+ case op of
+ OP_ADD: { simple addition }
+ f_TOpCG2AsmOp := A_ADDU;
+ OP_AND: { simple logical and }
+ f_TOpCG2AsmOp := A_AND;
+ OP_DIV: { simple unsigned division }
+ f_TOpCG2AsmOp := A_DIVU;
+ OP_IDIV: { simple signed division }
+ f_TOpCG2AsmOp := A_DIV;
+ OP_IMUL: { simple signed multiply }
+ f_TOpCG2AsmOp := A_MULT;
+ OP_MUL: { simple unsigned multiply }
+ f_TOpCG2AsmOp := A_MULTU;
+ OP_NEG: { simple negate }
+ f_TOpCG2AsmOp := A_NEGU;
+ OP_NOT: { simple logical not }
+ f_TOpCG2AsmOp := A_NOT;
+ OP_OR: { simple logical or }
+ f_TOpCG2AsmOp := A_OR;
+ OP_SAR: { arithmetic shift-right }
+ f_TOpCG2AsmOp := A_SRA;
+ OP_SHL: { logical shift left }
+ f_TOpCG2AsmOp := A_SLL;
+ OP_SHR: { logical shift right }
+ f_TOpCG2AsmOp := A_SRL;
+ OP_SUB: { simple subtraction }
+ f_TOpCG2AsmOp := A_SUBU;
+ OP_XOR: { simple exclusive or }
+ f_TOpCG2AsmOp := A_XOR;
+ else
+ InternalError(2007010701);
+ end;{ case }
+ end;
+
+ function f_TOpCG2AsmOp_ovf(op: TOpCG; size: tcgsize): TAsmOp;
+ begin
+ if size = OS_32 then
+ case op of
+ OP_ADD: { simple addition }
+ f_TOpCG2AsmOp_ovf := A_ADD;
+ OP_AND: { simple logical and }
+ f_TOpCG2AsmOp_ovf := A_AND;
+ OP_DIV: { simple unsigned division }
+ f_TOpCG2AsmOp_ovf := A_DIVU;
+ OP_IDIV: { simple signed division }
+ f_TOpCG2AsmOp_ovf := A_DIV;
+ OP_IMUL: { simple signed multiply }
+ f_TOpCG2AsmOp_ovf := A_MULO;
+ OP_MUL: { simple unsigned multiply }
+ f_TOpCG2AsmOp_ovf := A_MULOU;
+ OP_NEG: { simple negate }
+ f_TOpCG2AsmOp_ovf := A_NEG;
+ OP_NOT: { simple logical not }
+ f_TOpCG2AsmOp_ovf := A_NOT;
+ OP_OR: { simple logical or }
+ f_TOpCG2AsmOp_ovf := A_OR;
+ OP_SAR: { arithmetic shift-right }
+ f_TOpCG2AsmOp_ovf := A_SRA;
+ OP_SHL: { logical shift left }
+ f_TOpCG2AsmOp_ovf := A_SLL;
+ OP_SHR: { logical shift right }
+ f_TOpCG2AsmOp_ovf := A_SRL;
+ OP_SUB: { simple subtraction }
+ f_TOpCG2AsmOp_ovf := A_SUB;
+ OP_XOR: { simple exclusive or }
+ f_TOpCG2AsmOp_ovf := A_XOR;
+ else
+ InternalError(2007070403);
+ end{ case }
+ else
+ case op of
+ OP_ADD: { simple addition }
+ f_TOpCG2AsmOp_ovf := A_ADD;
+ OP_AND: { simple logical and }
+ f_TOpCG2AsmOp_ovf := A_AND;
+ OP_DIV: { simple unsigned division }
+ f_TOpCG2AsmOp_ovf := A_DIVU;
+ OP_IDIV: { simple signed division }
+ f_TOpCG2AsmOp_ovf := A_DIV;
+ OP_IMUL: { simple signed multiply }
+ f_TOpCG2AsmOp_ovf := A_MULO;
+ OP_MUL: { simple unsigned multiply }
+ f_TOpCG2AsmOp_ovf := A_MULOU;
+ OP_NEG: { simple negate }
+ f_TOpCG2AsmOp_ovf := A_NEG;
+ OP_NOT: { simple logical not }
+ f_TOpCG2AsmOp_ovf := A_NOT;
+ OP_OR: { simple logical or }
+ f_TOpCG2AsmOp_ovf := A_OR;
+ OP_SAR: { arithmetic shift-right }
+ f_TOpCG2AsmOp_ovf := A_SRA;
+ OP_SHL: { logical shift left }
+ f_TOpCG2AsmOp_ovf := A_SLL;
+ OP_SHR: { logical shift right }
+ f_TOpCG2AsmOp_ovf := A_SRL;
+ OP_SUB: { simple subtraction }
+ f_TOpCG2AsmOp_ovf := A_SUB;
+ OP_XOR: { simple exclusive or }
+ f_TOpCG2AsmOp_ovf := A_XOR;
+ else
+ InternalError(2007010703);
+ end;{ case }
+ end;
+
+ function f_TOp64CG2AsmOp(op: TOpCG): TAsmOp;
+ begin
+ case op of
+ OP_ADD: { simple addition }
+ f_TOp64CG2AsmOp := A_DADDU;
+ OP_AND: { simple logical and }
+ f_TOp64CG2AsmOp := A_AND;
+ OP_DIV: { simple unsigned division }
+ f_TOp64CG2AsmOp := A_DDIVU;
+ OP_IDIV: { simple signed division }
+ f_TOp64CG2AsmOp := A_DDIV;
+ OP_IMUL: { simple signed multiply }
+ f_TOp64CG2AsmOp := A_DMULO;
+ OP_MUL: { simple unsigned multiply }
+ f_TOp64CG2AsmOp := A_DMULOU;
+ OP_NEG: { simple negate }
+ f_TOp64CG2AsmOp := A_DNEGU;
+ OP_NOT: { simple logical not }
+ f_TOp64CG2AsmOp := A_NOT;
+ OP_OR: { simple logical or }
+ f_TOp64CG2AsmOp := A_OR;
+ OP_SAR: { arithmetic shift-right }
+ f_TOp64CG2AsmOp := A_DSRA;
+ OP_SHL: { logical shift left }
+ f_TOp64CG2AsmOp := A_DSLL;
+ OP_SHR: { logical shift right }
+ f_TOp64CG2AsmOp := A_DSRL;
+ OP_SUB: { simple subtraction }
+ f_TOp64CG2AsmOp := A_DSUBU;
+ OP_XOR: { simple exclusive or }
+ f_TOp64CG2AsmOp := A_XOR;
+ else
+ InternalError(2007010702);
+ end;{ case }
+ end;
+
+
+
+procedure TCgMPSel.make_simple_ref(list: tasmlist; var ref: treference);
+var
+ tmpreg, tmpreg1: tregister;
+ tmpref: treference;
+begin
+ tmpreg := NR_NO;
+ { Be sure to have a base register }
+ if (ref.base = NR_NO) then
+ begin
+ ref.base := ref.index;
+ ref.index := NR_NO;
+ end;
+ if (cs_create_pic in current_settings.moduleswitches) and
+ assigned(ref.symbol) then
+ begin
+ tmpreg := GetIntRegister(list, OS_INT);
+ reference_reset(tmpref,sizeof(aint));
+ tmpref.symbol := ref.symbol;
+ tmpref.refaddr := addr_pic;
+ if not (pi_needs_got in current_procinfo.flags) then
+ internalerror(200501161);
+ tmpref.index := current_procinfo.got;
+ list.concat(taicpu.op_reg_ref(A_LW, tmpreg, tmpref));
+ ref.symbol := nil;
+ if (ref.index <> NR_NO) then
+ begin
+ list.concat(taicpu.op_reg_reg_reg(A_ADDU, tmpreg, ref.index, tmpreg));
+ ref.index := tmpreg;
+ end
+ else
+ begin
+ if ref.base <> NR_NO then
+ ref.index := tmpreg
+ else
+ ref.base := tmpreg;
+ end;
+ end;
+ { When need to use LUI, do it first }
+ if assigned(ref.symbol) or
+ (ref.offset < simm16lo) or
+ (ref.offset > simm16hi) then
+ begin
+ tmpreg := GetIntRegister(list, OS_INT);
+ reference_reset(tmpref,sizeof(aint));
+ tmpref.symbol := ref.symbol;
+ tmpref.offset := ref.offset;
+ tmpref.refaddr := addr_high;
+ list.concat(taicpu.op_reg_ref(A_LUI, tmpreg, tmpref));
+ if (ref.offset = 0) and (ref.index = NR_NO) and
+ (ref.base = NR_NO) then
+ begin
+ ref.refaddr := addr_low;
+ end
+ else
+ begin
+ { Load the low part is left }
+ tmpref.refaddr := addr_low;
+ list.concat(taicpu.op_reg_reg_ref(A_ADDIU, tmpreg, tmpreg, tmpref));
+ ref.offset := 0;
+ { symbol is loaded }
+ ref.symbol := nil;
+ end;
+ if (ref.index <> NR_NO) then
+ begin
+ list.concat(taicpu.op_reg_reg_reg(A_ADDU, tmpreg, ref.index, tmpreg));
+ ref.index := tmpreg;
+ end
+ else
+ begin
+ if ref.base <> NR_NO then
+ ref.index := tmpreg
+ else
+ ref.base := tmpreg;
+ end;
+ end;
+ if (ref.base <> NR_NO) then
+ begin
+ if (ref.index <> NR_NO) and (ref.offset = 0) then
+ begin
+ tmpreg1 := GetIntRegister(list, OS_INT);
+ list.concat(taicpu.op_reg_reg_reg(A_ADDU, tmpreg1, ref.base, ref.index));
+ ref.base := tmpreg1;
+ ref.index := NR_NO;
+ end
+ else if (ref.index <> NR_NO) and
+ ((ref.offset <> 0) or assigned(ref.symbol)) then
+ begin
+ if tmpreg = NR_NO then
+ tmpreg := GetIntRegister(list, OS_INT);
+ list.concat(taicpu.op_reg_reg_reg(A_ADDU, tmpreg, ref.base, ref.index));
+ ref.base := tmpreg;
+ ref.index := NR_NO;
+ end;
+ end;
+end;
+
+procedure TCgMPSel.make_simple_ref_fpu(list: tasmlist; var ref: treference);
+var
+ tmpreg, tmpreg1: tregister;
+ tmpref: treference;
+begin
+ tmpreg := NR_NO;
+ { Be sure to have a base register }
+ if (ref.base = NR_NO) then
+ begin
+ ref.base := ref.index;
+ ref.index := NR_NO;
+ end;
+ if (cs_create_pic in current_settings.moduleswitches) and
+ assigned(ref.symbol) then
+ begin
+ tmpreg := GetIntRegister(list, OS_INT);
+ reference_reset(tmpref,sizeof(aint));
+ tmpref.symbol := ref.symbol;
+ tmpref.refaddr := addr_pic;
+ if not (pi_needs_got in current_procinfo.flags) then
+ internalerror(200501161);
+ tmpref.index := current_procinfo.got;
+ list.concat(taicpu.op_reg_ref(A_LW, tmpreg, tmpref));
+ ref.symbol := nil;
+ if (ref.index <> NR_NO) then
+ begin
+ list.concat(taicpu.op_reg_reg_reg(A_ADDU, tmpreg, ref.index, tmpreg));
+ ref.index := tmpreg;
+ end
+ else
+ begin
+ if ref.base <> NR_NO then
+ ref.index := tmpreg
+ else
+ ref.base := tmpreg;
+ end;
+ end;
+ { When need to use LUI, do it first }
+ if (not assigned(ref.symbol)) and (ref.index = NR_NO) and
+ (ref.offset > simm16lo + 1000) and (ref.offset < simm16hi - 1000)
+ then
+ exit;
+
+ tmpreg1 := GetIntRegister(list, OS_INT);
+ if assigned(ref.symbol) then
+ begin
+ reference_reset(tmpref,sizeof(aint));
+ tmpref.symbol := ref.symbol;
+ tmpref.offset := ref.offset;
+ tmpref.refaddr := addr_high;
+ list.concat(taicpu.op_reg_ref(A_LUI, tmpreg1, tmpref));
+ { Load the low part }
+
+ tmpref.refaddr := addr_low;
+ list.concat(taicpu.op_reg_reg_ref(A_ADDIU, tmpreg1, tmpreg1, tmpref));
+ { symbol is loaded }
+ ref.symbol := nil;
+ end
+ else
+ list.concat(taicpu.op_reg_const(A_LI, tmpreg1, ref.offset));
+
+ if (ref.index <> NR_NO) then
+ begin
+ list.concat(taicpu.op_reg_reg_reg(A_ADDU, tmpreg1, ref.index, tmpreg1));
+ ref.index := NR_NO
+ end;
+ if ref.base <> NR_NO then
+ list.concat(taicpu.op_reg_reg_reg(A_ADDU, tmpreg1, ref.base, tmpreg1));
+ ref.base := tmpreg1;
+ ref.offset := 0;
+end;
+
+procedure TCgMPSel.handle_load_store(list: tasmlist; isstore: boolean; op: tasmop; reg: tregister; ref: treference);
+begin
+ make_simple_ref(list, ref);
+ list.concat(taicpu.op_reg_ref(op, reg, ref));
+end;
+
+procedure TCgMPSel.handle_load_store_fpu(list: tasmlist; isstore: boolean; op: tasmop; reg: tregister; ref: treference);
+begin
+ make_simple_ref_fpu(list, ref);
+ list.concat(taicpu.op_reg_ref(op, reg, ref));
+end;
+
+
+procedure TCgMPSel.handle_reg_const_reg(list: tasmlist; op: Tasmop; src: tregister; a: tcgint; dst: tregister);
+var
+ tmpreg: tregister;
+begin
+ if (a < simm16lo) or
+ (a > simm16hi) then
+ begin
+ tmpreg := GetIntRegister(list, OS_INT);
+ a_load_const_reg(list, OS_INT, a, tmpreg);
+ list.concat(taicpu.op_reg_reg_reg(op, dst, src, tmpreg));
+ end
+ else
+ list.concat(taicpu.op_reg_reg_const(op, dst, src, a));
+end;
+
+
+{****************************************************************************
+ Assembler code
+****************************************************************************}
+
+procedure TCgMPSel.init_register_allocators;
+begin
+ inherited init_register_allocators;
+
+ if (cs_create_pic in current_settings.moduleswitches) and
+ (pi_needs_got in current_procinfo.flags) then
+ begin
+ current_procinfo.got := NR_GP;
+ rg[R_INTREGISTER] := Trgcpu.Create(R_INTREGISTER, R_SUBD,
+ [RS_R4, RS_R5, RS_R6, RS_R7, RS_R8, RS_R9, RS_R10, RS_R11,
+ RS_R12, RS_R13, RS_R14 {, RS_R15 for tmp_const in ncpuadd.pas} {, RS_R24, RS_R25}],
+ first_int_imreg, []);
+ end
+ else
+ rg[R_INTREGISTER] := Trgcpu.Create(R_INTREGISTER, R_SUBD,
+ [RS_R4, RS_R5, RS_R6, RS_R7, RS_R8, RS_R9, RS_R10, RS_R11,
+ RS_R12, RS_R13, RS_R14 {, RS_R15 for tmp_const in ncpuadd.pas} {, RS_R24=VMT, RS_R25=PIC jump}],
+ first_int_imreg, []);
+
+ rg[R_FPUREGISTER] := trgcpu.Create(R_FPUREGISTER, R_SUBFS{R_SUBFD},
+ [RS_F0, RS_F2, RS_F4, RS_F6,
+ RS_F8, RS_F10, RS_F12, RS_F14,
+ RS_F16, RS_F18, RS_F20, RS_F22,
+ RS_F24, RS_F26, RS_F28, RS_F30],
+ first_fpu_imreg, []);
+end;
+
+
+
+procedure TCgMPSel.done_register_allocators;
+begin
+ rg[R_INTREGISTER].Free;
+ rg[R_FPUREGISTER].Free;
+ inherited done_register_allocators;
+end;
+
+
+function TCgMPSel.getfpuregister(list: tasmlist; size: Tcgsize): Tregister;
+begin
+ if size = OS_F64 then
+ Result := rg[R_FPUREGISTER].getregister(list, R_SUBFD)
+ else
+ Result := rg[R_FPUREGISTER].getregister(list, R_SUBFS);
+end;
+
+
+procedure TCgMPSel.a_load_const_cgpara(list: tasmlist; size: tcgsize; a: tcgint; const paraloc: TCGPara);
+var
+ Ref: TReference;
+begin
+ paraloc.check_simple_location;
+ paramanager.allocparaloc(list,paraloc.location);
+ case paraloc.location^.loc of
+ LOC_REGISTER, LOC_CREGISTER:
+ a_load_const_reg(list, size, a, paraloc.location^.Register);
+ LOC_REFERENCE:
+ begin
+ with paraloc.location^.Reference do
+ begin
+ if (Index = NR_SP) and (Offset < Target_info.first_parm_offset) then
+ InternalError(2002081104);
+ reference_reset_base(ref, index, offset, sizeof(aint));
+ end;
+ a_load_const_ref(list, size, a, ref);
+ end;
+ else
+ InternalError(2002122200);
+ end;
+end;
+
+
+procedure TCgMPSel.a_load_ref_cgpara(list: tasmlist; sz: TCgSize; const r: TReference; const paraloc: TCGPara);
+var
+ ref: treference;
+ tmpreg: TRegister;
+begin
+ paraloc.check_simple_location;
+ paramanager.allocparaloc(list,paraloc.location);
+ with paraloc.location^ do
+ begin
+ case loc of
+ LOC_REGISTER, LOC_CREGISTER:
+ a_load_ref_reg(list, sz, sz, r, Register);
+ LOC_REFERENCE:
+ begin
+ with Reference do
+ begin
+ if (Index = NR_SP) and (Offset < Target_info.first_parm_offset) then
+ InternalError(2002081104);
+ reference_reset_base(ref, index, offset, sizeof(aint));
+ end;
+ tmpreg := GetIntRegister(list, OS_INT);
+ a_load_ref_reg(list, sz, sz, r, tmpreg);
+ a_load_reg_ref(list, sz, sz, tmpreg, ref);
+ end;
+ else
+ internalerror(2002081103);
+ end;
+ end;
+end;
+
+
+procedure TCgMPSel.a_loadaddr_ref_cgpara(list: tasmlist; const r: TReference; const paraloc: TCGPara);
+var
+ Ref: TReference;
+ TmpReg: TRegister;
+begin
+ paraloc.check_simple_location;
+ paramanager.allocparaloc(list,paraloc.location);
+ with paraloc.location^ do
+ begin
+ case loc of
+ LOC_REGISTER, LOC_CREGISTER:
+ a_loadaddr_ref_reg(list, r, Register);
+ LOC_REFERENCE:
+ begin
+ reference_reset(ref,sizeof(aint));
+ ref.base := reference.index;
+ ref.offset := reference.offset;
+ tmpreg := GetAddressRegister(list);
+ a_loadaddr_ref_reg(list, r, tmpreg);
+ a_load_reg_ref(list, OS_ADDR, OS_ADDR, tmpreg, ref);
+ end;
+ else
+ internalerror(2002080701);
+ end;
+ end;
+end;
+
+
+procedure TCgMPSel.a_loadfpu_ref_cgpara(list: tasmlist; size: tcgsize; const ref: treference; const paraloc: TCGPara);
+var
+ href, href2: treference;
+ hloc: pcgparalocation;
+begin
+ href := ref;
+ hloc := paraloc.location;
+ while assigned(hloc) do
+ begin
+ paramanager.allocparaloc(list,hloc);
+ case hloc^.loc of
+ LOC_REGISTER:
+ a_load_ref_reg(list, hloc^.size, hloc^.size, href, hloc^.Register);
+ LOC_REFERENCE:
+ begin
+ reference_reset_base(href2, hloc^.reference.index, hloc^.reference.offset, sizeof(aint));
+ a_load_ref_ref(list, hloc^.size, hloc^.size, href, href2);
+ end;
+ else
+ internalerror(200408241);
+ end;
+ Inc(href.offset, tcgsize2size[hloc^.size]);
+ hloc := hloc^.Next;
+ end;
+end;
+
+
+procedure TCgMPSel.a_loadfpu_reg_cgpara(list: tasmlist; size: tcgsize; const r: tregister; const paraloc: TCGPara);
+var
+ href: treference;
+begin
+ tg.GetTemp(list, TCGSize2Size[size], sizeof(aint), tt_normal, href);
+ a_loadfpu_reg_ref(list, size, size, r, href);
+ a_loadfpu_ref_cgpara(list, size, href, paraloc);
+ tg.Ungettemp(list, href);
+end;
+
+
+procedure TCgMPSel.a_call_name(list: tasmlist; const s: string; weak: boolean);
+begin
+ list.concat(taicpu.op_sym(A_JAL,current_asmdata.RefAsmSymbol(s)));
+ { Delay slot }
+ list.concat(taicpu.op_none(A_NOP));
+end;
+
+
+procedure TCgMPSel.a_call_reg(list: tasmlist; Reg: TRegister);
+begin
+ list.concat(taicpu.op_reg(A_JALR, reg));
+ { Delay slot }
+ list.concat(taicpu.op_none(A_NOP));
+end;
+
+
+{********************** load instructions ********************}
+
+procedure TCgMPSel.a_load_const_reg(list: tasmlist; size: TCGSize; a: tcgint; reg: TRegister);
+begin
+ if (a = 0) then
+ list.concat(taicpu.op_reg_reg(A_MOVE, reg, NR_R0))
+ { LUI allows to set the upper 16 bits, so we'll take full advantage of it }
+ else if (a and aint($ffff)) = 0 then
+ list.concat(taicpu.op_reg_const(A_LUI, reg, a shr 16))
+ else if (a >= simm16lo) and (a <= simm16hi) then
+ list.concat(taicpu.op_reg_reg_const(A_ADDIU, reg, NR_R0, a))
+ else if (a>=0) and (a <= 65535) then
+ list.concat(taicpu.op_reg_reg_const(A_ORI, reg, NR_R0, a))
+ else
+ begin
+ list.concat(taicpu.op_reg_const(A_LI, reg, a ));
+ end;
+end;
+
+
+procedure TCgMPSel.a_load_const_ref(list: tasmlist; size: tcgsize; a: tcgint; const ref: TReference);
+begin
+ if a = 0 then
+ a_load_reg_ref(list, size, size, NR_R0, ref)
+ else
+ inherited a_load_const_ref(list, size, a, ref);
+end;
+
+
+procedure TCgMPSel.a_load_reg_ref(list: tasmlist; FromSize, ToSize: TCGSize; reg: tregister; const Ref: TReference);
+var
+ op: tasmop;
+begin
+
+ if (TCGSize2Size[fromsize] >= TCGSize2Size[tosize]) then
+ fromsize := tosize;
+ case fromsize of
+ { signed integer registers }
+ OS_8,
+ OS_S8:
+ Op := A_SB;
+ OS_16,
+ OS_S16:
+ Op := A_SH;
+ OS_32,
+ OS_S32:
+ Op := A_SW;
+ else
+ InternalError(2002122100);
+ end;
+ handle_load_store(list, True, op, reg, ref);
+end;
+
+
+procedure TCgMPSel.a_load_ref_reg(list: tasmlist; FromSize, ToSize: TCgSize; const ref: TReference; reg: tregister);
+var
+ op: tasmop;
+begin
+ if (TCGSize2Size[fromsize] >= TCGSize2Size[tosize]) then
+ fromsize := tosize;
+ case fromsize of
+ OS_S8:
+ Op := A_LB;{Load Signed Byte}
+ OS_8:
+ Op := A_LBU;{Load Unsigned Byte}
+ OS_S16:
+ Op := A_LH;{Load Signed Halfword}
+ OS_16:
+ Op := A_LHU;{Load Unsigned Halfword}
+ OS_S32:
+ Op := A_LW;{Load Word}
+ OS_32:
+ Op := A_LW;//A_LWU;{Load Unsigned Word}
+ OS_S64,
+ OS_64:
+ Op := A_LD;{Load a Long Word}
+ else
+ InternalError(2002122101);
+ end;
+ handle_load_store(list, False, op, reg, ref);
+end;
+
+
+procedure TCgMPSel.a_load_reg_reg(list: tasmlist; fromsize, tosize: tcgsize; reg1, reg2: tregister);
+var
+ instr: taicpu;
+begin
+ if (tcgsize2size[tosize] < tcgsize2size[fromsize]) or
+ (
+ (tcgsize2size[tosize] = tcgsize2size[fromsize]) and
+ (tosize <> fromsize) and not (fromsize in [OS_32, OS_S32])
+ ) then
+ begin
+ case tosize of
+ OS_8:
+ a_op_const_reg_reg(list, OP_AND, tosize, $ff, reg1, reg2);
+ OS_16:
+ a_op_const_reg_reg(list, OP_AND, tosize, $ffff, reg1, reg2);
+ OS_32,
+ OS_S32:
+ begin
+ instr := taicpu.op_reg_reg(A_MOVE, reg2, reg1);
+ list.Concat(instr);
+ { Notify the register allocator that we have written a move instruction so
+ it can try to eliminate it. }
+ add_move_instruction(instr);
+ end;
+ OS_S8:
+ begin
+ list.concat(taicpu.op_reg_reg_const(A_SLL, reg2, reg1, 24));
+ list.concat(taicpu.op_reg_reg_const(A_SRA, reg2, reg2, 24));
+ end;
+ OS_S16:
+ begin
+ list.concat(taicpu.op_reg_reg_const(A_SLL, reg2, reg1, 16));
+ list.concat(taicpu.op_reg_reg_const(A_SRA, reg2, reg2, 16));
+ end;
+ else
+ internalerror(2002090901);
+ end;
+ end
+ else
+ begin
+ if reg1 <> reg2 then
+ begin
+ { same size, only a register mov required }
+ instr := taicpu.op_reg_reg(A_MOVE, reg2, reg1);
+ list.Concat(instr);
+// { Notify the register allocator that we have written a move instruction so
+// it can try to eliminate it. }
+
+ add_move_instruction(instr);
+ end;
+ end;
+end;
+
+
+procedure TCgMPSel.a_loadaddr_ref_reg(list: tasmlist; const ref: TReference; r: tregister);
+var
+ tmpref, href: treference;
+ hreg, tmpreg: tregister;
+ r_used: boolean;
+begin
+ r_used := false;
+ href := ref;
+ if (href.base = NR_NO) and (href.index <> NR_NO) then
+ internalerror(200306171);
+
+ if (cs_create_pic in current_settings.moduleswitches) and
+ assigned(href.symbol) then
+ begin
+ tmpreg := r; //GetIntRegister(list, OS_ADDR);
+ r_used := true;
+ reference_reset(tmpref,sizeof(aint));
+ tmpref.symbol := href.symbol;
+ tmpref.refaddr := addr_pic;
+ if not (pi_needs_got in current_procinfo.flags) then
+ internalerror(200501161);
+ tmpref.base := current_procinfo.got;
+ list.concat(taicpu.op_reg_ref(A_LW, tmpreg, tmpref));
+ href.symbol := nil;
+ if (href.index <> NR_NO) then
+ begin
+ list.concat(taicpu.op_reg_reg_reg(A_ADDU, tmpreg, href.index, tmpreg));
+ href.index := tmpreg;
+ end
+ else
+ begin
+ if href.base <> NR_NO then
+ href.index := tmpreg
+ else
+ href.base := tmpreg;
+ end;
+ end;
+
+
+ if assigned(href.symbol) or
+ (href.offset < simm16lo) or
+ (href.offset > simm16hi) then
+ begin
+ if (href.base = NR_NO) and (href.index = NR_NO) then
+ hreg := r
+ else
+ hreg := GetAddressRegister(list);
+ reference_reset(tmpref,sizeof(aint));
+ tmpref.symbol := href.symbol;
+ tmpref.offset := href.offset;
+ tmpref.refaddr := addr_high;
+ list.concat(taicpu.op_reg_ref(A_LUI, hreg, tmpref));
+ { Only the low part is left }
+ tmpref.refaddr := addr_low;
+ list.concat(taicpu.op_reg_reg_ref(A_ADDIU, hreg, hreg, tmpref));
+ if href.base <> NR_NO then
+ begin
+ if href.index <> NR_NO then
+ begin
+ list.concat(taicpu.op_reg_reg_reg(A_ADDU, hreg, href.base, hreg));
+ list.concat(taicpu.op_reg_reg_reg(A_ADDU, r, hreg, href.index));
+ end
+ else
+ list.concat(taicpu.op_reg_reg_reg(A_ADDU, r, hreg, href.base));
+ end;
+ end
+ else
+ { At least small offset, maybe base and maybe index }
+ if (href.offset >= simm16lo) and
+ (href.offset <= simm16hi) then
+ begin
+ if href.index <> NR_NO then { Both base and index }
+ begin
+ if href.offset = 0 then
+ begin
+ list.concat(taicpu.op_reg_reg_reg(A_ADDU, r, href.base, href.index));
+ end
+ else
+ begin
+ if r_used then
+ hreg := GetAddressRegister(list)
+ else
+ hreg := r;
+ list.concat(taicpu.op_reg_reg_const(A_ADDIU, hreg, href.base, href.offset));
+ list.concat(taicpu.op_reg_reg_reg(A_ADDU, r, hreg, href.index));
+ end
+ end
+ else if href.base <> NR_NO then { Only base }
+ begin
+ list.concat(taicpu.op_reg_reg_const(A_ADDIU, r, href.base, href.offset));
+ end
+ else
+ { only offset, can be generated by absolute }
+ a_load_const_reg(list, OS_ADDR, href.offset, r);
+ end
+ else
+ internalerror(200703111);
+end;
+
+procedure TCgMPSel.a_loadfpu_reg_reg(list: tasmlist; fromsize, tosize: tcgsize; reg1, reg2: tregister);
+const
+ FpuMovInstr: array[OS_F32..OS_F64] of TAsmOp =
+ (A_MOV_S, A_MOV_D);
+var
+ instr: taicpu;
+begin
+ if reg1 <> reg2 then
+ begin
+ instr := taicpu.op_reg_reg(fpumovinstr[tosize], reg2, reg1);
+ list.Concat(instr);
+ { Notify the register allocator that we have written a move instruction so
+ it can try to eliminate it. }
+ add_move_instruction(instr);
+ end;
+end;
+
+
+procedure TCgMPSel.a_loadfpu_ref_reg(list: tasmlist; fromsize, tosize: tcgsize; const ref: TReference; reg: tregister);
+var
+ tmpref: treference;
+ tmpreg: tregister;
+begin
+ case tosize of
+ OS_F32:
+ handle_load_store_fpu(list, False, A_LWC1, reg, ref);
+ OS_F64:
+ handle_load_store_fpu(list, False, A_LDC1, reg, ref);
+ else
+ InternalError(2007042701);
+ end;
+end;
+
+procedure TCgMPSel.a_loadfpu_reg_ref(list: tasmlist; fromsize, tosize: tcgsize; reg: tregister; const ref: TReference);
+var
+ tmpref: treference;
+ tmpreg: tregister;
+begin
+ case tosize of
+ OS_F32:
+ handle_load_store_fpu(list, True, A_SWC1, reg, ref);
+ OS_F64:
+ handle_load_store_fpu(list, True, A_SDC1, reg, ref);
+ else
+ InternalError(2007042702);
+ end;
+end;
+
+procedure TCgMPSel.a_op_const_reg(list: tasmlist; Op: TOpCG; size: tcgsize; a: tcgint; reg: TRegister);
+var
+ power: longint;
+ tmpreg1: tregister;
+begin
+ if ((op = OP_MUL) or (op = OP_IMUL)) then
+ begin
+ if ispowerof2(a, power) then
+ begin
+ { can be done with a shift }
+ if power < 32 then
+ begin
+ list.concat(taicpu.op_reg_reg_const(A_SLL, reg, reg, power));
+ exit;
+ end;
+ end;
+ end;
+ if ((op = OP_SUB) or (op = OP_ADD)) then
+ begin
+ if (a = 0) then
+ exit;
+ end;
+
+ if Op in [OP_NEG, OP_NOT] then
+ internalerror(200306011);
+ if (a = 0) then
+ begin
+ if (Op = OP_IMUL) or (Op = OP_MUL) then
+ list.concat(taicpu.op_reg_reg(A_MOVE, reg, NR_R0))
+ else
+ list.concat(taicpu.op_reg_reg_reg(f_TOpCG2AsmOp(op, size), reg, reg, NR_R0))
+ end
+ else
+ begin
+ if op = OP_IMUL then
+ begin
+ tmpreg1 := GetIntRegister(list, OS_INT);
+ a_load_const_reg(list, OS_INT, a, tmpreg1);
+ list.concat(taicpu.op_reg_reg(A_MULT, reg, tmpreg1));
+ list.concat(taicpu.op_reg(A_MFLO, reg));
+ end
+ else if op = OP_MUL then
+ begin
+ tmpreg1 := GetIntRegister(list, OS_INT);
+ a_load_const_reg(list, OS_INT, a, tmpreg1);
+ list.concat(taicpu.op_reg_reg(A_MULTU, reg, tmpreg1));
+ list.concat(taicpu.op_reg(A_MFLO, reg));
+ end
+ else
+ handle_reg_const_reg(list, f_TOpCG2AsmOp(op, size), reg, a, reg);
+ end;
+end;
+
+
+procedure TCgMPSel.a_op_reg_reg(list: tasmlist; Op: TOpCG; size: TCGSize; src, dst: TRegister);
+var
+ a: aint;
+begin
+ case Op of
+ OP_NEG:
+ list.concat(taicpu.op_reg_reg(A_NEG, dst, src));
+ OP_NOT:
+ begin
+ list.concat(taicpu.op_reg_reg(A_NOT, dst, src));
+ end;
+ else
+ begin
+ if op = OP_IMUL then
+ begin
+ list.concat(taicpu.op_reg_reg(A_MULT, dst, src));
+ list.concat(taicpu.op_reg(A_MFLO, dst));
+ end
+ else if op = OP_MUL then
+ begin
+ list.concat(taicpu.op_reg_reg(A_MULTU, dst, src));
+ list.concat(taicpu.op_reg(A_MFLO, dst));
+ end
+ else
+ begin
+ list.concat(taicpu.op_reg_reg_reg(f_TOpCG2AsmOp(op, size), dst, dst, src));
+ end;
+ end;
+ end;
+end;
+
+
+procedure TCgMPSel.a_op_const_reg_reg(list: tasmlist; op: TOpCg; size: tcgsize; a: tcgint; src, dst: tregister);
+var
+ power: longint;
+ tmpreg1: tregister;
+begin
+ case op of
+ OP_MUL,
+ OP_IMUL:
+ begin
+ if ispowerof2(a, power) then
+ begin
+ { can be done with a shift }
+ if power < 32 then
+ list.concat(taicpu.op_reg_reg_const(A_SLL, dst, src, power))
+ else
+ inherited a_op_const_reg_reg(list, op, size, a, src, dst);
+ exit;
+ end;
+ end;
+ OP_SUB,
+ OP_ADD:
+ begin
+ if (a = 0) then
+ begin
+ a_load_reg_reg(list, size, size, src, dst);
+ exit;
+ end;
+ end;
+ end;
+ if op = OP_IMUL then
+ begin
+ tmpreg1 := GetIntRegister(list, OS_INT);
+ a_load_const_reg(list, OS_INT, a, tmpreg1);
+ list.concat(taicpu.op_reg_reg(A_MULT, src, tmpreg1));
+ list.concat(taicpu.op_reg(A_MFLO, dst));
+ end
+ else if op = OP_MUL then
+ begin
+ tmpreg1 := GetIntRegister(list, OS_INT);
+ a_load_const_reg(list, OS_INT, a, tmpreg1);
+ list.concat(taicpu.op_reg_reg(A_MULTU, src, tmpreg1));
+ list.concat(taicpu.op_reg(A_MFLO, dst));
+ end
+ else
+ handle_reg_const_reg(list, f_TOpCG2AsmOp(op, size), src, a, dst);
+end;
+
+
+procedure TCgMPSel.a_op_reg_reg_reg(list: tasmlist; op: TOpCg; size: tcgsize; src1, src2, dst: tregister);
+begin
+
+ list.concat(taicpu.op_reg_reg_reg(f_TOpCG2AsmOp(op, size), dst, src2, src1));
+end;
+
+
+procedure TCgMPSel.a_op_const_reg_reg_checkoverflow(list: tasmlist; op: TOpCg; size: tcgsize; a: tcgint; src, dst: tregister; setflags: boolean; var ovloc: tlocation);
+var
+ tmpreg1: tregister;
+begin
+ ovloc.loc := LOC_VOID;
+ case op of
+ OP_SUB,
+ OP_ADD:
+ begin
+ if (a = 0) then
+ begin
+ a_load_reg_reg(list, size, size, src, dst);
+ exit;
+ end;
+ end;
+ end;{case}
+
+ case op of
+ OP_ADD:
+ begin
+ if setflags then
+ handle_reg_const_reg(list, f_TOpCG2AsmOp_ovf(op, size), src, a, dst)
+ else
+ handle_reg_const_reg(list, f_TOpCG2AsmOp(op, size), src, a, dst);
+ end;
+ OP_SUB:
+ begin
+ if setflags then
+ handle_reg_const_reg(list, f_TOpCG2AsmOp_ovf(op, size), src, a, dst)
+ else
+ handle_reg_const_reg(list, f_TOpCG2AsmOp(op, size), src, a, dst);
+ end;
+ OP_MUL:
+ begin
+ if setflags then
+ handle_reg_const_reg(list, f_TOpCG2AsmOp_ovf(op, size), src, a, dst)
+ else
+ begin
+ tmpreg1 := GetIntRegister(list, OS_INT);
+ a_load_const_reg(list, OS_INT, a, tmpreg1);
+ list.concat(taicpu.op_reg_reg(f_TOpCG2AsmOp(op, size),src, tmpreg1));
+ list.concat(taicpu.op_reg(A_MFLO, dst));
+ end;
+ end;
+ OP_IMUL:
+ begin
+ if setflags then
+ handle_reg_const_reg(list, f_TOpCG2AsmOp_ovf(op, size), src, a, dst)
+ else
+ begin
+ tmpreg1 := GetIntRegister(list, OS_INT);
+ a_load_const_reg(list, OS_INT, a, tmpreg1);
+ list.concat(taicpu.op_reg_reg(f_TOpCG2AsmOp(op, size),src, tmpreg1));
+ list.concat(taicpu.op_reg(A_MFLO, dst));
+ end;
+ end;
+ OP_XOR, OP_OR, OP_AND:
+ begin
+ handle_reg_const_reg(list, f_TOpCG2AsmOp_ovf(op, size), src, a, dst);
+ end;
+ else
+ internalerror(2007012601);
+ end;
+end;
+
+
+procedure TCgMPSel.a_op_reg_reg_reg_checkoverflow(list: tasmlist; op: TOpCg; size: tcgsize; src1, src2, dst: tregister; setflags: boolean; var ovloc: tlocation);
+begin
+ ovloc.loc := LOC_VOID;
+ case op of
+ OP_ADD:
+ begin
+ if setflags then
+ list.concat(taicpu.op_reg_reg_reg(f_TOpCG2AsmOp_ovf(op, size), dst, src2, src1))
+ else
+ list.concat(taicpu.op_reg_reg_reg(f_TOpCG2AsmOp(op, size), dst, src2, src1));
+ end;
+ OP_SUB:
+ begin
+ if setflags then
+ list.concat(taicpu.op_reg_reg_reg(f_TOpCG2AsmOp_ovf(op, size), dst, src2, src1))
+ else
+ list.concat(taicpu.op_reg_reg_reg(f_TOpCG2AsmOp(op, size), dst, src2, src1));
+ end;
+ OP_MUL:
+ begin
+ if setflags then
+ list.concat(taicpu.op_reg_reg_reg(f_TOpCG2AsmOp_ovf(op, size), dst, src2, src1))
+ else
+ begin
+ list.concat(taicpu.op_reg_reg(f_TOpCG2AsmOp(op, size), src2, src1));
+ list.concat(taicpu.op_reg(A_MFLO, dst));
+ end;
+ end;
+ OP_IMUL:
+ begin
+ if setflags then
+ list.concat(taicpu.op_reg_reg_reg(f_TOpCG2AsmOp_ovf(op, size), dst, src2, src1))
+ else
+ begin
+ list.concat(taicpu.op_reg_reg(f_TOpCG2AsmOp(op, size), src2, src1));
+ list.concat(taicpu.op_reg(A_MFLO, dst));
+ end;
+ end;
+ OP_XOR, OP_OR, OP_AND:
+ begin
+ list.concat(taicpu.op_reg_reg_reg(f_TOpCG2AsmOp_ovf(op, size), dst, src2, src1));
+ end;
+ else
+ internalerror(2007012602);
+ end;
+end;
+
+
+
+{*************** compare instructructions ****************}
+
+procedure TCgMPSel.a_cmp_const_reg_label(list: tasmlist; size: tcgsize; cmp_op: topcmp; a: tcgint; reg: tregister; l: tasmlabel);
+var
+ tmpreg: tregister;
+begin
+if a = 0 then
+ tmpreg := NR_R0
+else
+begin
+ tmpreg := GetIntRegister(list, OS_INT);
+ list.concat(taicpu.op_reg_const(A_LI, tmpreg, a));
+end;
+ case cmp_op of
+ OC_EQ: { equality comparison }
+ list.concat(taicpu.op_reg_reg_sym(A_BEQ, reg, tmpreg, l));
+ OC_GT: { greater than (signed) }
+ list.concat(taicpu.op_reg_reg_sym(A_BGT, reg, tmpreg, l));
+ OC_LT: { less than (signed) }
+ list.concat(taicpu.op_reg_reg_sym(A_BLT, reg, tmpreg, l));
+ OC_GTE: { greater or equal than (signed) }
+ list.concat(taicpu.op_reg_reg_sym(A_BGE, reg, tmpreg, l));
+ OC_LTE: { less or equal than (signed) }
+ list.concat(taicpu.op_reg_reg_sym(A_BLE, reg, tmpreg, l));
+ OC_NE: { not equal }
+ list.concat(taicpu.op_reg_reg_sym(A_BNE, reg, tmpreg, l));
+ OC_BE: { less or equal than (unsigned) }
+ list.concat(taicpu.op_reg_reg_sym(A_BLEU, reg, tmpreg, l));
+ OC_B: { less than (unsigned) }
+ list.concat(taicpu.op_reg_reg_sym(A_BLTU, reg, tmpreg, l));
+ OC_AE: { greater or equal than (unsigned) }
+ list.concat(taicpu.op_reg_reg_sym(A_BGEU, reg, tmpreg, l));
+ OC_A: { greater than (unsigned) }
+ list.concat(taicpu.op_reg_reg_sym(A_BGTU, reg, tmpreg, l));
+ else
+ internalerror(200701071);
+ end;
+ list.Concat(TAiCpu.Op_none(A_NOP));
+end;
+
+
+procedure TCgMPSel.a_cmp_reg_reg_label(list: tasmlist; size: tcgsize; cmp_op: topcmp; reg1, reg2: tregister; l: tasmlabel);
+begin
+ case cmp_op of
+ OC_EQ: { equality comparison }
+ list.concat(taicpu.op_reg_reg_sym(A_BEQ, reg2, reg1, l));
+ OC_GT: { greater than (signed) }
+ list.concat(taicpu.op_reg_reg_sym(A_BGT, reg2, reg1, l));
+ OC_LT: { less than (signed) }
+ list.concat(taicpu.op_reg_reg_sym(A_BLT, reg2, reg1, l));
+ OC_GTE: { greater or equal than (signed) }
+ list.concat(taicpu.op_reg_reg_sym(A_BGE, reg2, reg1, l));
+ OC_LTE: { less or equal than (signed) }
+ list.concat(taicpu.op_reg_reg_sym(A_BLE, reg2, reg1, l));
+ OC_NE: { not equal }
+ list.concat(taicpu.op_reg_reg_sym(A_BNE, reg2, reg1, l));
+ OC_BE: { less or equal than (unsigned) }
+ list.concat(taicpu.op_reg_reg_sym(A_BLEU, reg2, reg1, l));
+ OC_B: { less than (unsigned) }
+ list.concat(taicpu.op_reg_reg_sym(A_BLTU, reg2, reg1, l));
+ OC_AE: { greater or equal than (unsigned) }
+ list.concat(taicpu.op_reg_reg_sym(A_BGEU, reg2, reg1, l));
+ OC_A: { greater than (unsigned) }
+ list.concat(taicpu.op_reg_reg_sym(A_BGTU, reg2, reg1, l));
+ else
+ internalerror(200701072);
+ end;{ case }
+ list.Concat(TAiCpu.Op_none(A_NOP));
+end;
+
+
+procedure TCgMPSel.a_jmp_always(List: tasmlist; l: TAsmLabel);
+begin
+ List.Concat(TAiCpu.op_sym(A_J,l));
+ { Delay slot }
+ list.Concat(TAiCpu.Op_none(A_NOP));
+end;
+
+
+procedure TCgMPSel.a_jmp_name(list: tasmlist; const s: string);
+begin
+ List.Concat(TAiCpu.op_sym(A_J, current_asmdata.RefAsmSymbol(s)));
+ { Delay slot }
+ list.Concat(TAiCpu.Op_none(A_NOP));
+end;
+
+
+procedure TCgMPSel.a_jmp_cond(list: tasmlist; cond: TOpCmp; l: TAsmLabel);
+begin
+ internalerror(200701181);
+end;
+
+
+procedure TCgMPSel.g_overflowCheck(List: tasmlist; const Loc: TLocation; def: TDef);
+begin
+// this is an empty procedure
+end;
+
+procedure TCgMPSel.g_overflowCheck_loc(List: tasmlist; const Loc: TLocation; def: TDef; ovloc: tlocation);
+begin
+
+// this is an empty procedure
+
+end;
+
+{ *********** entry/exit code and address loading ************ }
+
+procedure TCgMPSel.g_proc_entry(list: tasmlist; localsize: longint; nostackframe: boolean);
+var
+ regcounter, firstregfpu, firstreggpr: TSuperRegister;
+ href: treference;
+ usesfpr, usesgpr, gotgot: boolean;
+ regcounter2, firstfpureg: Tsuperregister;
+ cond: tasmcond;
+ instr: taicpu;
+
+begin
+ if STK2_dummy <> 0 then
+ begin
+ list.concat(Taicpu.Op_reg_reg_const(A_P_STK2, STK2_PTR, STK2_PTR, -STK2_dummy));
+ end;
+
+ if nostackframe then
+ exit;
+
+ usesfpr := False;
+ if not (po_assembler in current_procinfo.procdef.procoptions) then
+ case target_info.abi of
+ abi_powerpc_aix:
+ firstfpureg := RS_F14;
+ abi_powerpc_sysv:
+ firstfpureg := RS_F14;
+ abi_default:
+ firstfpureg := RS_F14;
+ else
+ internalerror(2003122903);
+ end;
+ for regcounter := firstfpureg to RS_F31 do
+ begin
+ if regcounter in rg[R_FPUREGISTER].used_in_proc then
+ begin
+ usesfpr := True;
+ firstregfpu := regcounter;
+ break;
+ end;
+ end;
+
+ usesgpr := False;
+ if not (po_assembler in current_procinfo.procdef.procoptions) then
+ for regcounter2 := RS_R13 to RS_R31 do
+ begin
+ if regcounter2 in rg[R_INTREGISTER].used_in_proc then
+ begin
+ usesgpr := True;
+ firstreggpr := regcounter2;
+ break;
+ end;
+ end;
+
+
+ LocalSize := align(LocalSize, 8);
+
+ cgcpu_calc_stackframe_size := LocalSize;
+ list.concat(Taicpu.Op_reg_reg_const(A_P_FRAME, NR_FRAME_POINTER_REG, NR_R31, LocalSize));
+ list.concat(Taicpu.op_none(A_P_SET_NOREORDER));
+ list.concat(Taicpu.op_none(A_P_SET_NOMACRO));
+ list.concat(Taicpu.Op_reg_reg_const(A_P_SW, NR_FRAME_POINTER_REG, NR_STACK_POINTER_REG, -LocalSize));
+ list.concat(Taicpu.Op_reg_reg_const(A_P_SW, NR_R31, NR_STACK_POINTER_REG, -LocalSize + 4));
+ list.concat(Taicpu.op_reg_reg(A_MOVE, NR_FRAME_POINTER_REG, NR_STACK_POINTER_REG));
+ list.concat(Taicpu.Op_reg_reg_const(A_ADDIU, NR_STACK_POINTER_REG, NR_STACK_POINTER_REG, -LocalSize));
+ if (cs_create_pic in current_settings.moduleswitches) and
+ (pi_needs_got in current_procinfo.flags) then
+ begin
+ current_procinfo.got := NR_GP;
+ end;
+end;
+
+
+
+
+procedure TCgMPSel.g_proc_exit(list: tasmlist; parasize: longint; nostackframe: boolean);
+var
+ hr: treference;
+ localsize: aint;
+begin
+ localsize := cgcpu_calc_stackframe_size;
+ if paramanager.ret_in_param(current_procinfo.procdef.returndef, current_procinfo.procdef.proccalloption) then
+ begin
+ reference_reset(hr,sizeof(aint));
+ hr.offset := 12;
+ hr.refaddr := addr_full;
+ if nostackframe then
+ begin
+ if STK2_dummy <> 0 then
+ list.concat(Taicpu.Op_reg_reg_const(A_P_STK2, STK2_PTR, STK2_PTR, STK2_dummy));
+ list.concat(taicpu.op_reg(A_J, NR_R31));
+ list.concat(Taicpu.op_none(A_NOP));
+ end
+ else
+ begin
+
+ list.concat(Taicpu.Op_reg_reg_const(A_P_LW, NR_FRAME_POINTER_REG, NR_STACK_POINTER_REG, 0));
+ list.concat(Taicpu.Op_reg_reg_const(A_P_LW, NR_R31, NR_STACK_POINTER_REG, 4));
+ list.concat(Taicpu.Op_reg_reg_const(A_ADDIU, NR_STACK_POINTER_REG, NR_STACK_POINTER_REG, localsize));
+ if STK2_dummy <> 0 then
+ list.concat(Taicpu.Op_reg_reg_const(A_P_STK2, STK2_PTR, STK2_PTR, STK2_dummy));
+ list.concat(taicpu.op_reg(A_J, NR_R31));
+ list.concat(Taicpu.op_none(A_NOP));
+ list.concat(Taicpu.op_none(A_P_SET_MACRO));
+ list.concat(Taicpu.op_none(A_P_SET_REORDER));
+
+ end;
+ end
+ else
+ begin
+ if nostackframe then
+ begin
+ if STK2_dummy <> 0 then
+ list.concat(Taicpu.Op_reg_reg_const(A_P_STK2, STK2_PTR, STK2_PTR, STK2_dummy));
+ list.concat(taicpu.op_reg(A_J, NR_R31));
+ list.concat(Taicpu.op_none(A_NOP));
+ list.concat(Taicpu.op_none(A_P_SET_MACRO));
+ list.concat(Taicpu.op_none(A_P_SET_REORDER));
+ end
+ else
+ begin
+ list.concat(Taicpu.Op_reg_reg_const(A_P_LW, NR_FRAME_POINTER_REG, NR_STACK_POINTER_REG, 0));
+ list.concat(Taicpu.Op_reg_reg_const(A_P_LW, NR_R31, NR_STACK_POINTER_REG, 4));
+ list.concat(Taicpu.Op_reg_reg_const(A_ADDIU, NR_STACK_POINTER_REG, NR_STACK_POINTER_REG, localsize));
+ if STK2_dummy <> 0 then
+ list.concat(Taicpu.Op_reg_reg_const(A_P_STK2, STK2_PTR, STK2_PTR, STK2_dummy));
+ list.concat(taicpu.op_reg(A_J, NR_R31));
+ list.concat(Taicpu.op_none(A_NOP));
+ list.concat(Taicpu.op_none(A_P_SET_MACRO));
+ list.concat(Taicpu.op_none(A_P_SET_REORDER));
+ end;
+ end;
+end;
+
+
+
+{ ************* concatcopy ************ }
+
+procedure TCgMPSel.g_concatcopy_move(list: tasmlist; const Source, dest: treference; len: tcgint);
+var
+ paraloc1, paraloc2, paraloc3: TCGPara;
+begin
+ paraloc1.init;
+ paraloc2.init;
+ paraloc3.init;
+ paramanager.getintparaloc(pocall_default, 1, paraloc1);
+ paramanager.getintparaloc(pocall_default, 2, paraloc2);
+ paramanager.getintparaloc(pocall_default, 3, paraloc3);
+ a_load_const_cgpara(list, OS_INT, len, paraloc3);
+ a_loadaddr_ref_cgpara(list, dest, paraloc2);
+ a_loadaddr_ref_cgpara(list, Source, paraloc1);
+ paramanager.freecgpara(list, paraloc3);
+ paramanager.freecgpara(list, paraloc2);
+ paramanager.freecgpara(list, paraloc1);
+ alloccpuregisters(list, R_INTREGISTER, paramanager.get_volatile_registers_int(pocall_default));
+ alloccpuregisters(list, R_FPUREGISTER, paramanager.get_volatile_registers_fpu(pocall_default));
+ a_call_name(list, 'FPC_MOVE', false);
+ dealloccpuregisters(list, R_FPUREGISTER, paramanager.get_volatile_registers_fpu(pocall_default));
+ dealloccpuregisters(list, R_INTREGISTER, paramanager.get_volatile_registers_int(pocall_default));
+ paraloc3.done;
+ paraloc2.done;
+ paraloc1.done;
+end;
+
+
+procedure TCgMPSel.g_concatcopy(list: tasmlist; const Source, dest: treference; len: tcgint);
+var
+ tmpreg1, hreg, countreg: TRegister;
+ src, dst: TReference;
+ lab: tasmlabel;
+ Count, count2: aint;
+begin
+ if len > high(longint) then
+ internalerror(2002072704);
+ { anybody wants to determine a good value here :)? }
+ if len > 100 then
+ g_concatcopy_move(list, Source, dest, len)
+ else
+ begin
+ reference_reset(src,sizeof(aint));
+ reference_reset(dst,sizeof(aint));
+ { load the address of source into src.base }
+ src.base := GetAddressRegister(list);
+ a_loadaddr_ref_reg(list, Source, src.base);
+ { load the address of dest into dst.base }
+ dst.base := GetAddressRegister(list);
+ a_loadaddr_ref_reg(list, dest, dst.base);
+ { generate a loop }
+ Count := len div 4;
+ if Count > 4 then
+ begin
+ { the offsets are zero after the a_loadaddress_ref_reg and just }
+ { have to be set to 8. I put an Inc there so debugging may be }
+ { easier (should offset be different from zero here, it will be }
+ { easy to notice in the generated assembler }
+ countreg := GetIntRegister(list, OS_INT);
+ tmpreg1 := GetIntRegister(list, OS_INT);
+ a_load_const_reg(list, OS_INT, Count, countreg);
+ { explicitely allocate R_O0 since it can be used safely here }
+ { (for holding date that's being copied) }
+ current_asmdata.getjumplabel(lab);
+ a_label(list, lab);
+ list.concat(taicpu.op_reg_ref(A_LW, tmpreg1, src));
+ list.concat(taicpu.op_reg_ref(A_SW, tmpreg1, dst));
+ list.concat(taicpu.op_reg_reg_const(A_ADDIU, src.base, src.base, 4));
+ list.concat(taicpu.op_reg_reg_const(A_ADDIU, dst.base, dst.base, 4));
+ list.concat(taicpu.op_reg_reg_const(A_ADDIU, countreg, countreg, -1));
+ list.concat(taicpu.op_reg_sym(A_BGTZ, countreg, lab));
+ list.concat(taicpu.op_none(A_NOP));
+ len := len mod 4;
+ end;
+ { unrolled loop }
+ Count := len div 4;
+ if Count > 0 then
+ begin
+ tmpreg1 := GetIntRegister(list, OS_INT);
+ for count2 := 1 to Count do
+ begin
+ list.concat(taicpu.op_reg_ref(A_LW, tmpreg1, src));
+ list.concat(taicpu.op_reg_ref(A_SW, tmpreg1, dst));
+ Inc(src.offset, 4);
+ Inc(dst.offset, 4);
+ end;
+ len := len mod 4;
+ end;
+ if (len and 4) <> 0 then
+ begin
+ hreg := GetIntRegister(list, OS_INT);
+ a_load_ref_reg(list, OS_32, OS_32, src, hreg);
+ a_load_reg_ref(list, OS_32, OS_32, hreg, dst);
+ Inc(src.offset, 4);
+ Inc(dst.offset, 4);
+ end;
+ { copy the leftovers }
+ if (len and 2) <> 0 then
+ begin
+ hreg := GetIntRegister(list, OS_INT);
+ a_load_ref_reg(list, OS_16, OS_16, src, hreg);
+ a_load_reg_ref(list, OS_16, OS_16, hreg, dst);
+ Inc(src.offset, 2);
+ Inc(dst.offset, 2);
+ end;
+ if (len and 1) <> 0 then
+ begin
+ hreg := GetIntRegister(list, OS_INT);
+ a_load_ref_reg(list, OS_8, OS_8, src, hreg);
+ a_load_reg_ref(list, OS_8, OS_8, hreg, dst);
+ end;
+ end;
+end;
+
+
+procedure TCgMPSel.g_concatcopy_unaligned(list: tasmlist; const Source, dest: treference; len: tcgint);
+var
+ src, dst: TReference;
+ tmpreg1, countreg: TRegister;
+ i: aint;
+ lab: tasmlabel;
+begin
+ if len > 31 then
+ g_concatcopy_move(list, Source, dest, len)
+ else
+ begin
+ reference_reset(src,sizeof(aint));
+ reference_reset(dst,sizeof(aint));
+ { load the address of source into src.base }
+ src.base := GetAddressRegister(list);
+ a_loadaddr_ref_reg(list, Source, src.base);
+ { load the address of dest into dst.base }
+ dst.base := GetAddressRegister(list);
+ a_loadaddr_ref_reg(list, dest, dst.base);
+ { generate a loop }
+ if len > 4 then
+ begin
+ { the offsets are zero after the a_loadaddress_ref_reg and just }
+ { have to be set to 8. I put an Inc there so debugging may be }
+ { easier (should offset be different from zero here, it will be }
+ { easy to notice in the generated assembler }
+ countreg := GetIntRegister(list, OS_INT);
+ tmpreg1 := GetIntRegister(list, OS_INT);
+ a_load_const_reg(list, OS_INT, len, countreg);
+ { explicitely allocate R_O0 since it can be used safely here }
+ { (for holding date that's being copied) }
+ current_asmdata.getjumplabel(lab);
+ a_label(list, lab);
+ list.concat(taicpu.op_reg_ref(A_LBU, tmpreg1, src));
+ list.concat(taicpu.op_reg_ref(A_SB, tmpreg1, dst));
+ list.concat(taicpu.op_reg_reg_const(A_ADDIU, src.base, src.base, 1));
+ list.concat(taicpu.op_reg_reg_const(A_ADDIU, dst.base, dst.base, 1));
+ list.concat(taicpu.op_reg_reg_const(A_ADDIU, countreg, countreg, -1));
+ list.concat(taicpu.op_reg_sym(A_BGTZ, countreg, lab));
+ list.concat(taicpu.op_none(A_NOP));
+ end
+ else
+ begin
+ { unrolled loop }
+ tmpreg1 := GetIntRegister(list, OS_INT);
+ for i := 1 to len do
+ begin
+ list.concat(taicpu.op_reg_ref(A_LBU, tmpreg1, src));
+ list.concat(taicpu.op_reg_ref(A_SB, tmpreg1, dst));
+ Inc(src.offset);
+ Inc(dst.offset);
+ end;
+ end;
+ end;
+end;
+
+
+procedure TCgMPSel.g_intf_wrapper(list: tasmlist; procdef: tprocdef; const labelname: string; ioffset: longint);
+ procedure loadvmttor24;
+ var
+ href: treference;
+ begin
+ reference_reset_base(href, NR_R2, 0, sizeof(aint)); { return value }
+ cg.a_load_ref_reg(list, OS_ADDR, OS_ADDR, href, NR_R24);
+ end;
+
+
+ procedure op_onr24methodaddr;
+ var
+ href : treference;
+ begin
+ if (procdef.extnumber=$ffff) then
+ Internalerror(200006139);
+ { call/jmp vmtoffs(%eax) ; method offs }
+ reference_reset_base(href, NR_R24, tobjectdef(procdef.struct).vmtmethodoffset(procdef.extnumber), sizeof(aint));
+ cg.a_load_ref_reg(list, OS_ADDR, OS_ADDR, href, NR_R24);
+ list.concat(taicpu.op_reg(A_JR, NR_R24));
+ end;
+var
+ make_global: boolean;
+ href: treference;
+begin
+ if procdef.proctypeoption <> potype_none then
+ Internalerror(200006137);
+ if not assigned(procdef.struct) or
+ (procdef.procoptions * [po_classmethod, po_staticmethod,
+ po_methodpointer, po_interrupt, po_iocheck] <> []) then
+ Internalerror(200006138);
+ if procdef.owner.symtabletype <> objectsymtable then
+ Internalerror(200109191);
+
+ make_global := False;
+ if (not current_module.is_unit) or create_smartlink or
+ (procdef.owner.defowner.owner.symtabletype = globalsymtable) then
+ make_global := True;
+
+ if make_global then
+ List.concat(Tai_symbol.Createname_global(labelname, AT_FUNCTION, 0))
+ else
+ List.concat(Tai_symbol.Createname(labelname, AT_FUNCTION, 0));
+
+ { set param1 interface to self }
+ g_adjust_self_value(list, procdef, ioffset);
+
+ if (po_virtualmethod in procdef.procoptions) and
+ not is_objectpascal_helper(procdef.struct) then
+ begin
+ loadvmttor24;
+ op_onr24methodaddr;
+ end
+ else
+ list.concat(taicpu.op_sym(A_B,current_asmdata.RefAsmSymbol(procdef.mangledname)));
+ { Delay slot }
+ list.Concat(TAiCpu.Op_none(A_NOP));
+
+ List.concat(Tai_symbol_end.Createname(labelname));
+end;
+
+procedure TCgMPSel.g_stackpointer_alloc(list : TAsmList;localsize : longint);
+ begin
+ Comment(V_Error,'TCgMPSel.g_stackpointer_alloc method not implemented');
+ end;
+
+procedure TCgMPSel.a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; size: TCGSize; src, dst: TRegister);
+ begin
+ Comment(V_Error,'TCgMPSel.a_bit_scan_reg_reg method not implemented');
+ end;
+
+{****************************************************************************
+ TCG64_MIPSel
+****************************************************************************}
+
+
+procedure TCg64MPSel.a_load64_reg_ref(list: tasmlist; reg: tregister64; const ref: treference);
+var
+ tmpref: treference;
+begin
+ { Override this function to prevent loading the reference twice }
+ tmpref := ref;
+ cg.a_load_reg_ref(list, OS_S32, OS_S32, reg.reglo, tmpref);
+ Inc(tmpref.offset, 4);
+ cg.a_load_reg_ref(list, OS_S32, OS_S32, reg.reghi, tmpref);
+end;
+
+
+procedure TCg64MPSel.a_load64_ref_reg(list: tasmlist; const ref: treference; reg: tregister64);
+var
+ tmpref: treference;
+begin
+ { Override this function to prevent loading the reference twice }
+ tmpref := ref;
+ cg.a_load_ref_reg(list, OS_S32, OS_S32, tmpref, reg.reglo);
+ Inc(tmpref.offset, 4);
+ cg.a_load_ref_reg(list, OS_S32, OS_S32, tmpref, reg.reghi);
+end;
+
+
+procedure TCg64MPSel.a_load64_ref_cgpara(list: tasmlist; const r: treference; const paraloc: tcgpara);
+var
+ hreg64: tregister64;
+begin
+ { Override this function to prevent loading the reference twice.
+ Use here some extra registers, but those are optimized away by the RA }
+ hreg64.reglo := cg.GetIntRegister(list, OS_S32);
+ hreg64.reghi := cg.GetIntRegister(list, OS_S32);
+ a_load64_ref_reg(list, r, hreg64);
+ a_load64_reg_cgpara(list, hreg64, paraloc);
+end;
+
+
+
+
+procedure TCg64MPSel.a_op64_reg_reg(list: tasmlist; op: TOpCG; size: tcgsize; regsrc, regdst: TRegister64);
+var
+ op1, op2, op_call64: TAsmOp;
+ tmpreg1, tmpreg2: TRegister;
+begin
+ tmpreg1 := NR_TCR12; //GetIntRegister(list, OS_INT);
+ tmpreg2 := NR_TCR13; //GetIntRegister(list, OS_INT);
+
+ case op of
+ OP_ADD:
+ begin
+ list.concat(taicpu.op_reg_reg_reg(A_ADDU, tmpreg1, regsrc.reglo, regdst.reglo));
+ list.concat(taicpu.op_reg_reg_reg(A_SLTU, NR_TCR10, tmpreg1, regsrc.reglo));
+ list.concat(taicpu.op_reg_reg_reg(A_ADDU, tmpreg2, regsrc.reghi, regdst.reghi));
+ list.concat(taicpu.op_reg_reg_reg(A_ADDU, NR_TCR10, NR_TCR10, tmpreg2));
+ list.concat(Taicpu.Op_reg_reg(A_MOVE, regdst.reglo, tmpreg1));
+ list.concat(Taicpu.Op_reg_reg(A_MOVE, regdst.reghi, NR_TCR10));
+ exit;
+ end;
+ OP_AND:
+ begin
+ list.concat(taicpu.op_reg_reg_reg(A_AND, regdst.reglo, regsrc.reglo, regdst.reglo));
+ list.concat(taicpu.op_reg_reg_reg(A_AND, regdst.reghi, regsrc.reghi, regdst.reghi));
+ exit;
+ end;
+
+ OP_NEG:
+ begin
+ list.concat(taicpu.op_reg_reg_reg(A_SUBU, regdst.reglo, NR_R0, regsrc.reglo));
+ list.concat(taicpu.op_reg_reg_reg(A_SLTU, NR_TCR10, NR_R0, regdst.reglo));
+ list.concat(taicpu.op_reg_reg_reg(A_SUBU, regdst.reghi, NR_R0, regsrc.reghi));
+ list.concat(taicpu.op_reg_reg_reg(A_SUBU, NR_TCR10, regdst.reghi, NR_TCR10));
+ list.concat(Taicpu.Op_reg_reg(A_MOVE, regdst.reghi, NR_TCR10));
+ exit;
+ end;
+ OP_NOT:
+ begin
+ list.concat(taicpu.op_reg_reg_reg(A_NOR, regdst.reglo, NR_R0, regsrc.reglo));
+ list.concat(taicpu.op_reg_reg_reg(A_NOR, regdst.reghi, NR_R0, regsrc.reghi));
+ exit;
+ end;
+ OP_OR:
+ begin
+ list.concat(taicpu.op_reg_reg_reg(A_OR, regdst.reglo, regsrc.reglo, regdst.reglo));
+ list.concat(taicpu.op_reg_reg_reg(A_OR, regdst.reghi, regsrc.reghi, regdst.reghi));
+ exit;
+ end;
+ OP_SUB:
+ begin
+ list.concat(taicpu.op_reg_reg_reg(A_SUBU, tmpreg1, regdst.reglo, regsrc.reglo));
+ list.concat(taicpu.op_reg_reg_reg(A_SLTU, NR_TCR10, regdst.reglo, tmpreg1));
+ list.concat(taicpu.op_reg_reg_reg(A_SUBU, tmpreg2, regdst.reghi, regsrc.reghi));
+ list.concat(taicpu.op_reg_reg_reg(A_SUBU, tmpreg2, tmpreg2, NR_TCR10));
+ list.concat(Taicpu.Op_reg_reg(A_MOVE, regdst.reglo, tmpreg1));
+ list.concat(Taicpu.Op_reg_reg(A_MOVE, regdst.reghi, tmpreg2));
+ exit;
+ end;
+ OP_XOR:
+ begin
+ list.concat(taicpu.op_reg_reg_reg(A_XOR, regdst.reglo, regdst.reglo, regsrc.reglo));
+ list.concat(taicpu.op_reg_reg_reg(A_XOR, regdst.reghi, regsrc.reghi, regdst.reghi));
+ exit;
+ end;
+ else
+ internalerror(200306017);
+
+ end; {case}
+
+
+
+end;
+
+
+procedure TCg64MPSel.a_op64_const_reg(list: tasmlist; op: TOpCG; size: tcgsize; Value: int64; regdst: TRegister64);
+var
+ op1, op2: TAsmOp;
+begin
+ case op of
+ OP_NEG,
+ OP_NOT:
+ internalerror(200306017);
+ end;
+ a_op64_const_reg_reg(list, op, size, value, regdst, regdst);
+
+end;
+
+
+procedure TCg64MPSel.a_op64_const_reg_reg(list: tasmlist; op: TOpCG; size: tcgsize; Value: int64; regsrc, regdst: tregister64);
+var
+ l: tlocation;
+begin
+ a_op64_const_reg_reg_checkoverflow(list, op, size, Value, regsrc, regdst, False, l);
+end;
+
+
+procedure TCg64MPSel.a_op64_reg_reg_reg(list: tasmlist; op: TOpCG; size: tcgsize; regsrc1, regsrc2, regdst: tregister64);
+var
+ l: tlocation;
+begin
+ a_op64_reg_reg_reg_checkoverflow(list, op, size, regsrc1, regsrc2, regdst, False, l);
+end;
+
+
+procedure TCg64MPSel.a_op64_const_reg_reg_checkoverflow(list: tasmlist; op: TOpCG; size: tcgsize; Value: int64; regsrc, regdst: tregister64; setflags: boolean; var ovloc: tlocation);
+var
+ op1, op2: TAsmOp;
+ tmpreg1: TRegister;
+begin
+ tmpreg1 := NR_TCR12;
+ case op of
+ OP_NEG,
+ OP_NOT:
+ internalerror(200306017);
+ end;
+
+ list.concat(taicpu.op_reg_const(A_LI, NR_TCR10, aint(hi(Value))));
+ list.concat(taicpu.op_reg_const(A_LI, NR_TCR11, aint(lo(Value))));
+ case op of
+ OP_ADD:
+ begin
+ list.concat(taicpu.op_reg_reg_reg(A_ADDU, regdst.reglo, regsrc.reglo, NR_TCR10));
+ list.concat(taicpu.op_reg_reg_reg(A_SLTU, tmpreg1, regdst.reglo, regsrc.reglo));
+ list.concat(taicpu.op_reg_reg_reg(A_ADDU, regdst.reghi, regsrc.reghi, NR_TCR11));
+ list.concat(taicpu.op_reg_reg_reg(A_ADDU, tmpreg1, tmpreg1, regdst.reghi));
+ list.concat(Taicpu.Op_reg_reg(A_MOVE, regdst.reghi, tmpreg1));
+ exit;
+ end;
+ OP_AND:
+ begin
+ list.concat(taicpu.op_reg_reg_reg(A_AND, regdst.reglo, regsrc.reglo, NR_TCR10));
+ list.concat(taicpu.op_reg_reg_reg(A_AND, regdst.reghi, regsrc.reghi, NR_TCR11));
+ exit;
+ end;
+
+ OP_OR:
+ begin
+ list.concat(taicpu.op_reg_reg_reg(A_OR, regdst.reglo, regsrc.reglo, NR_TCR10));
+ list.concat(taicpu.op_reg_reg_reg(A_OR, regdst.reghi, regsrc.reghi, NR_TCR11));
+ exit;
+ end;
+ OP_SUB:
+ begin
+ list.concat(taicpu.op_reg_reg_reg(A_SUBU, regdst.reglo, regsrc.reglo, NR_TCR10));
+ list.concat(taicpu.op_reg_reg_reg(A_SLTU, tmpreg1, regsrc.reglo, regdst.reglo));
+ list.concat(taicpu.op_reg_reg_reg(A_SUBU, regdst.reghi, regsrc.reghi, NR_TCR11));
+ list.concat(taicpu.op_reg_reg_reg(A_SUBU, tmpreg1, regdst.reghi, tmpreg1));
+ list.concat(Taicpu.Op_reg_reg(A_MOVE, regdst.reghi, tmpreg1));
+ exit;
+ end;
+ OP_XOR:
+ begin
+ list.concat(taicpu.op_reg_reg_reg(A_XOR, regdst.reglo, regsrc.reglo, NR_TCR10));
+ list.concat(taicpu.op_reg_reg_reg(A_XOR, regdst.reghi, regsrc.reghi, NR_TCR11));
+ exit;
+ end;
+ else
+ internalerror(200306017);
+ end;
+
+end;
+
+
+procedure TCg64MPSel.a_op64_reg_reg_reg_checkoverflow(list: tasmlist; op: TOpCG; size: tcgsize; regsrc1, regsrc2, regdst: tregister64; setflags: boolean; var ovloc: tlocation);
+var
+ op1, op2: TAsmOp;
+ tmpreg1, tmpreg2: TRegister;
+
+begin
+ tmpreg1 := NR_TCR12;
+ tmpreg2 := NR_TCR13;
+
+ case op of
+ OP_NEG,
+ OP_NOT:
+ internalerror(200306017);
+ end;
+ case op of
+ OP_ADD:
+ begin
+ list.concat(taicpu.op_reg_reg_reg(A_ADDU, tmpreg1, regsrc2.reglo, regsrc1.reglo));
+ list.concat(taicpu.op_reg_reg_reg(A_SLTU, NR_TCR10, tmpreg1, regsrc2.reglo));
+ list.concat(taicpu.op_reg_reg_reg(A_ADDU, tmpreg2, regsrc2.reghi, regsrc1.reghi));
+ list.concat(taicpu.op_reg_reg_reg(A_ADDU, regdst.reghi, NR_TCR10, tmpreg2));
+ list.concat(Taicpu.Op_reg_reg(A_MOVE, regdst.reglo, tmpreg1));
+ exit;
+ end;
+ OP_AND:
+ begin
+ list.concat(taicpu.op_reg_reg_reg(A_AND, regdst.reglo, regsrc2.reglo, regsrc1.reglo));
+ list.concat(taicpu.op_reg_reg_reg(A_AND, regdst.reghi, regsrc2.reghi, regsrc1.reghi));
+ exit;
+ end;
+ OP_OR:
+ begin
+ list.concat(taicpu.op_reg_reg_reg(A_OR, regdst.reglo, regsrc2.reglo, regsrc1.reglo));
+ list.concat(taicpu.op_reg_reg_reg(A_OR, regdst.reghi, regsrc2.reghi, regsrc1.reghi));
+ exit;
+ end;
+ OP_SUB:
+ begin
+ list.concat(taicpu.op_reg_reg_reg(A_SUBU, tmpreg1, regsrc2.reglo, regsrc1.reglo));
+ list.concat(taicpu.op_reg_reg_reg(A_SLTU, NR_TCR10, regsrc2.reglo, tmpreg1));
+ list.concat(taicpu.op_reg_reg_reg(A_SUBU, tmpreg2, regsrc2.reghi, regsrc1.reghi));
+ list.concat(taicpu.op_reg_reg_reg(A_SUBU, regdst.reghi, tmpreg2, NR_TCR10));
+ list.concat(Taicpu.Op_reg_reg(A_MOVE, regdst.reglo, tmpreg1));
+ exit;
+ end;
+ OP_XOR:
+ begin
+ list.concat(taicpu.op_reg_reg_reg(A_XOR, regdst.reglo, regsrc2.reglo, regsrc1.reglo));
+ list.concat(taicpu.op_reg_reg_reg(A_XOR, regdst.reghi, regsrc2.reghi, regsrc1.reghi));
+ exit;
+ end;
+ else
+ internalerror(200306017);
+
+ end; {case}
+
+end;
+
+
+ procedure create_codegen;
+ begin
+ cg:=TCgMPSel.Create;
+ cg64:=TCg64MPSel.Create;
+ end;
+
+end.
diff --git a/closures/compiler/mips/cpubase.pas b/closures/compiler/mips/cpubase.pas
new file mode 100644
index 0000000000..c075394ffd
--- /dev/null
+++ b/closures/compiler/mips/cpubase.pas
@@ -0,0 +1,397 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl and Peter Vreman
+
+ Contains the base types for MIPS
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+{# Base unit for processor information. This unit contains
+ enumerations of registers, opcodes, sizes, and other
+ such things which are processor specific.
+}
+unit cpubase;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ cutils,cclasses,
+ globtype,globals,
+ cpuinfo,
+ aasmbase,
+ cgbase
+ ;
+
+
+{*****************************************************************************
+ Assembler Opcodes
+*****************************************************************************}
+
+ type
+ TAsmOp=({$i opcode.inc});
+
+ { This should define the array of instructions as string }
+ op2strtable=array[tasmop] of string[11];
+
+ const
+ { First value of opcode enumeration }
+ firstop = low(tasmop);
+ { Last value of opcode enumeration }
+ lastop = high(tasmop);
+
+{*****************************************************************************
+ Registers
+*****************************************************************************}
+
+ type
+ { Number of registers used for indexing in tables }
+ tregisterindex=0..{$i rmipsnor.inc}-1;
+
+ const
+ { Available Superregisters }
+ {$i rmipssup.inc}
+
+ { No Subregisters }
+ R_SUBWHOLE = R_SUBNONE;
+
+ { Available Registers }
+ {$i rmipscon.inc}
+
+ { Integer Super registers first and last }
+ first_int_supreg = RS_R0;
+ first_int_imreg = $10;
+
+ { Float Super register first and last }
+ first_fpu_supreg = RS_F0;
+ first_fpu_imreg = $08;
+
+ { MM Super register first and last }
+ first_mm_supreg = RS_NO;
+ first_mm_imreg = RS_NO;
+
+{ TODO: Calculate bsstart}
+ regnumber_count_bsstart = 64;
+
+ regnumber_table : array[tregisterindex] of tregister = (
+ {$i rmipsnum.inc}
+ );
+
+ regstabs_table : array[tregisterindex] of shortint = (
+ {$i rmipssta.inc}
+ );
+
+ regdwarf_table : array[tregisterindex] of shortint = (
+ {$i rmipsdwf.inc}
+ );
+ { registers which may be destroyed by calls }
+ VOLATILE_INTREGISTERS = [RS_R0..RS_R3,RS_R12..RS_R15];
+ VOLATILE_FPUREGISTERS = [RS_F0..RS_F3];
+
+ type
+ totherregisterset = set of tregisterindex;
+
+{*****************************************************************************
+ Conditions
+*****************************************************************************}
+
+ type
+ TAsmCond=(C_None,
+ C_EQ, C_NE, C_LT, C_LE, C_GT, C_GE, C_LTU, C_LEU, C_GTU, C_GEU,
+ C_FEQ, {Equal}
+ C_FNE, {Not Equal}
+ C_FGT, {Greater}
+ C_FLT, {Less}
+ C_FGE, {Greater or Equal}
+ C_FLE {Less or Equal}
+
+ );
+
+ const
+ cond2str : array[TAsmCond] of string[3]=('',
+ 'eq','ne','lt','le','gt','ge','ltu','leu','gtu','geu',
+ 'feq','fne','fgt','flt','fge','fle'
+ );
+
+{*****************************************************************************
+ Constants
+*****************************************************************************}
+
+ const
+ max_operands = 4;
+
+ maxintregs = 31;
+ maxfpuregs = 8;
+ maxaddrregs = 0;
+
+{*****************************************************************************
+ Operand Sizes
+*****************************************************************************}
+
+ type
+ topsize = (S_NO,
+ S_B,S_W,S_L,S_BW,S_BL,S_WL,
+ S_IS,S_IL,S_IQ,
+ S_FS,S_FL,S_FX,S_D,S_Q,S_FV,S_FXX
+ );
+
+{*****************************************************************************
+ Constants
+*****************************************************************************}
+
+ const
+ maxvarregs = 7;
+ varregs : Array [1..maxvarregs] of tsuperregister =
+ (RS_R4,RS_R5,RS_R6,RS_R7,RS_R8,RS_R9,RS_R10);
+
+ maxfpuvarregs = 4;
+ fpuvarregs : Array [1..maxfpuvarregs] of tsuperregister =
+ (RS_F4,RS_F5,RS_F6,RS_F7);
+
+{*****************************************************************************
+ Default generic sizes
+*****************************************************************************}
+
+ { Defines the default address size for a processor, }
+ OS_ADDR = OS_32;
+ { the natural int size for a processor, }
+ OS_INT = OS_32;
+ OS_SINT = OS_S32;
+ { the maximum float size for a processor, }
+ OS_FLOAT = OS_F64;
+ { the size of a vector register for a processor }
+ OS_VECTOR = OS_M32;
+
+{*****************************************************************************
+ Generic Register names
+*****************************************************************************}
+
+ STK2_PTR = NR_R23;
+ NR_GP = NR_R28;
+ NR_SP = NR_R29;
+ NR_S8 = NR_R30;
+ NR_FP = NR_R30;
+ NR_RA = NR_R31;
+
+ RS_GP = RS_R28;
+ RS_SP = RS_R29;
+ RS_S8 = RS_R30;
+ RS_FP = RS_R30;
+ RS_RA = RS_R31;
+
+ {# Stack pointer register }
+ NR_STACK_POINTER_REG = NR_SP;
+ RS_STACK_POINTER_REG = RS_SP;
+ {# Frame pointer register }
+ NR_FRAME_POINTER_REG = NR_FP;
+ RS_FRAME_POINTER_REG = RS_FP;
+
+ NR_RETURN_ADDRESS_REG = NR_R7;
+ { the return_result_reg, is used inside the called function to store its return
+ value when that is a scalar value otherwise a pointer to the address of the
+ result is placed inside it }
+
+ { Results are returned in this register (32-bit values) }
+ NR_FUNCTION_RETURN_REG = NR_R2;
+ RS_FUNCTION_RETURN_REG = RS_R2;
+ { Low part of 64bit return value }
+ NR_FUNCTION_RETURN64_LOW_REG = NR_R2;
+ RS_FUNCTION_RETURN64_LOW_REG = RS_R2;
+ { High part of 64bit return value }
+ NR_FUNCTION_RETURN64_HIGH_REG = NR_R3;
+ RS_FUNCTION_RETURN64_HIGH_REG = RS_R3;
+ { The value returned from a function is available in this register }
+ NR_FUNCTION_RESULT_REG = NR_R2;
+ RS_FUNCTION_RESULT_REG = RS_R2;
+ { The lowh part of 64bit value returned from a function }
+ NR_FUNCTION_RESULT64_LOW_REG = NR_R2;
+ RS_FUNCTION_RESULT64_LOW_REG = RS_R2;
+ { The high part of 64bit value returned from a function }
+ NR_FUNCTION_RESULT64_HIGH_REG = NR_R3;
+ RS_FUNCTION_RESULT64_HIGH_REG = RS_R3;
+
+ NR_FPU_RESULT_REG = NR_F0;
+ NR_MM_RESULT_REG = NR_NO;
+
+ NR_TCR0 = NR_R15;
+ NR_TCR1 = NR_R3;
+
+ NR_TCR10 = NR_R20;
+ NR_TCR11 = NR_R21;
+ NR_TCR12 = NR_R18;
+ NR_TCR13 = NR_R19;
+
+
+{*****************************************************************************
+ GCC /ABI linking information
+*****************************************************************************}
+
+ const
+ { Registers which must be saved when calling a routine declared as
+ cppdecl, cdecl, stdcall, safecall, palmossyscall. The registers
+ saved should be the ones as defined in the target ABI and / or GCC.
+
+ This value can be deduced from the CALLED_USED_REGISTERS array in the
+ GCC source.
+ }
+ saved_standard_registers : array[0..0] of tsuperregister =
+ (RS_NO);
+
+ { this is only for the generic code which is not used for this architecture }
+ saved_mm_registers : array[0..0] of tsuperregister = (RS_NO);
+
+ { Required parameter alignment when calling a routine declared as
+ stdcall and cdecl. The alignment value should be the one defined
+ by GCC or the target ABI.
+
+ The value of this constant is equal to the constant
+ PARM_BOUNDARY / BITS_PER_UNIT in the GCC source.
+ }
+ std_param_align = 4;
+
+{*****************************************************************************
+ CPU Dependent Constants
+*****************************************************************************}
+
+ const
+ simm16lo = -32768;
+ simm16hi = 32767;
+
+{*****************************************************************************
+ Helpers
+*****************************************************************************}
+
+ function inverse_cond(const c: TAsmCond): TAsmCond; {$ifdef USEINLINE}inline;{$endif USEINLINE}
+ function conditions_equal(const c1, c2: TAsmCond): boolean; {$ifdef USEINLINE}inline;{$endif USEINLINE}
+
+ { Returns the tcgsize corresponding with the size of reg.}
+ function reg_cgsize(const reg: tregister) : tcgsize;
+ function cgsize2subreg(regtype: tregistertype; s:tcgsize):tsubregister;
+ function is_calljmp(o:tasmop):boolean;
+ function findreg_by_number(r:Tregister):tregisterindex;
+ function std_regnum_search(const s:string):Tregister;
+ function std_regname(r:Tregister):string;
+
+ var
+ STK2_dummy: aint;
+ STK2_Localsize: aint;
+
+ implementation
+
+ uses
+ rgBase,verbose;
+
+
+ const
+ std_regname_table : array[tregisterindex] of string[7] = (
+ {$i rmipsstd.inc}
+ );
+
+ regnumber_index : array[tregisterindex] of tregisterindex = (
+ {$i rmipsrni.inc}
+ );
+
+ std_regname_index : array[tregisterindex] of tregisterindex = (
+ {$i rmipssri.inc}
+ );
+
+
+ function cgsize2subreg(regtype: tregistertype; s:tcgsize):tsubregister;
+ begin
+ if s in [OS_64,OS_S64] then
+ cgsize2subreg:=R_SUBQ
+ else
+ cgsize2subreg:=R_SUBWHOLE;
+ end;
+
+
+ function reg_cgsize(const reg: tregister): tcgsize;
+ begin
+ case getregtype(reg) of
+ R_INTREGISTER :
+ reg_cgsize:=OS_32;
+ R_FPUREGISTER :
+ begin
+ if getsubreg(reg)=R_SUBFD then
+ result:=OS_F64
+ else
+ result:=OS_F32;
+ end;
+ else
+ internalerror(200303181);
+ end;
+ end;
+
+
+ function is_calljmp(o:tasmop):boolean;
+ begin
+ { This isn't 100% perfect because the arm allows jumps also by writing to PC=R15.
+ To overcome this problem we simply forbid that FPC generates jumps by loading R15 }
+ is_calljmp:= o in [A_J,A_JAL,A_JALR,{ A_JALX, }A_JR,
+ A_BEQ,A_BNE,A_BGEZ,A_BGEZAL,A_BGTZ,A_BLEZ,A_BLTZ,A_BLTZAL,
+ A_BEQL,A_BGEZALL,A_BGEZL,A_BGTZL,A_BLEZL,A_BLTZALL,A_BLTZL,A_BNEL];
+ end;
+
+
+ function inverse_cond(const c: TAsmCond): TAsmCond; {$ifdef USEINLINE}inline;{$endif USEINLINE}
+ const
+ inverse: array[TAsmCond] of TAsmCond=(C_None,
+ C_EQ, C_NE, C_LT, C_LE, C_GT, C_GE, C_LTU, C_LEU, C_GTU, C_GEU,
+ C_FEQ, {Equal}
+ C_FNE, {Not Equal}
+ C_FGT, {Greater}
+ C_FLT, {Less}
+ C_FGE, {Greater or Equal}
+ C_FLE {Less or Equal}
+
+ );
+ begin
+ result := inverse[c];
+ end; function findreg_by_number(r:Tregister):tregisterindex;
+ begin
+ result:=rgBase.findreg_by_number_table(r,regnumber_index);
+ end;
+
+
+ function conditions_equal(const c1, c2: TAsmCond): boolean; {$ifdef USEINLINE}inline;{$endif USEINLINE}
+ begin
+ result := c1 = c2;
+ end;
+
+
+ function std_regnum_search(const s:string):Tregister;
+ begin
+ result:=regnumber_table[findreg_by_name_table(s,std_regname_table,std_regname_index)];
+ end;
+
+
+ function std_regname(r:Tregister):string;
+ var
+ p : tregisterindex;
+ begin
+ p:=findreg_by_number_table(r,regnumber_index);
+ if p<>0 then
+ result:=std_regname_table[p]
+ else
+ result:=generic_regname(r);
+ end;
+
+
+begin
+ STK2_dummy := 10;
+ STK2_Localsize := 0;
+end.
diff --git a/closures/compiler/mips/cpugas.pas b/closures/compiler/mips/cpugas.pas
new file mode 100644
index 0000000000..d030f14f21
--- /dev/null
+++ b/closures/compiler/mips/cpugas.pas
@@ -0,0 +1,265 @@
+{
+ Copyright (c) 1999-2009 by Florian Klaempfl and David Zhang
+
+ This unit implements an asmoutput class for MIPS assembly syntax
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit cpugas;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ cpubase,
+ aasmtai, aasmcpu, assemble, aggas;
+
+ type
+ TMIPSGNUAssembler = class(TGNUassembler)
+ constructor create(smart: boolean); override;
+ end;
+
+ TMIPSInstrWriter = class(TCPUInstrWriter)
+ procedure WriteInstruction(hp : tai);override;
+ end;
+
+ implementation
+
+ uses
+ cutils, systems,
+ verbose, itcpugas, cgbase, cgutils;
+
+{****************************************************************************}
+{ GNU MIPS Assembler writer }
+{****************************************************************************}
+
+ constructor TMIPSGNUAssembler.create(smart: boolean);
+ begin
+ inherited create(smart);
+ InstrWriter := TMIPSInstrWriter.create(self);
+ end;
+
+
+{****************************************************************************}
+{ Helper routines for Instruction Writer }
+{****************************************************************************}
+
+ function GetReferenceString(var ref: TReference): string;
+ begin
+ GetReferenceString := '';
+ with ref do
+ begin
+ if (base = NR_NO) and (index = NR_NO) then
+ begin
+ if assigned(symbol) then
+ GetReferenceString := symbol.Name;
+ if offset > 0 then
+ GetReferenceString := GetReferenceString + '+' + ToStr(offset)
+ else if offset < 0 then
+ GetReferenceString := GetReferenceString + ToStr(offset);
+ case refaddr of
+ addr_high:
+ GetReferenceString := '%hi(' + GetReferenceString + ')';
+ addr_low:
+ GetReferenceString := '%lo(' + GetReferenceString + ')';
+ end;
+ end
+ else
+ begin
+ {$ifdef extdebug}
+ if assigned(symbol) and
+ not(refaddr in [addr_pic,addr_lo]) then
+ internalerror(2003052601);
+ {$endif extdebug}
+ if base <> NR_NO then
+ GetReferenceString := GetReferenceString + '(' + gas_regname(base) + ')';
+ if index = NR_NO then
+ begin
+ if offset <> 0 then
+ GetReferenceString := ToStr(offset) + GetReferenceString;
+ if assigned(symbol) then
+ begin
+ if refaddr = addr_low then
+ GetReferenceString := '%lo(' + symbol.Name + ')' + GetReferenceString
+ else
+ GetReferenceString := symbol.Name + {'+' +} GetReferenceString;
+ end;
+ end
+ else
+ begin
+ {$ifdef extdebug}
+ if (Offset<>0) or assigned(symbol) then
+ internalerror(2003052603);
+ {$endif extdebug}
+ GetReferenceString := GetReferenceString + '(' + gas_regname(index) + ')';
+
+ end;
+ end;
+ end;
+ end;
+
+
+ function getopstr(const Oper: TOper): string;
+ begin
+ with Oper do
+ case typ of
+ top_reg:
+ getopstr := gas_regname(reg);
+ top_const:
+ getopstr := tostr(longint(val));
+ top_ref:
+ if (oper.ref^.refaddr in [addr_no, addr_pic]) or ((oper.ref^.refaddr = addr_low) and ((oper.ref^.base <> NR_NO) or
+ (oper.ref^.index <> NR_NO))) then
+ getopstr := getreferencestring(ref^)
+ else
+ getopstr := getreferencestring(ref^);
+ else
+ internalerror(10001);
+ end;
+ end;
+
+ function getopstr_4(const Oper: TOper): string;
+ var
+ tmpref: treference;
+ begin
+ with Oper do
+ case typ of
+ top_ref:
+ begin
+ tmpref := ref^;
+ Inc(tmpref.offset, 4);
+ getopstr_4 := getreferencestring(tmpref);
+ end;
+ else
+ internalerror(2007050403);
+ end;
+ end;
+
+
+ procedure TMIPSInstrWriter.WriteInstruction(hp: Tai);
+ var
+ Op: TAsmOp;
+ s,s1: string;
+ i: integer;
+ tmpfpu: string;
+ tmpfpu_len: longint;
+ begin
+ if hp.typ <> ait_instruction then
+ exit;
+ op := taicpu(hp).opcode;
+
+ case op of
+ A_P_STK2:
+ begin
+ s1 := getopstr(taicpu(hp).oper[2]^);
+ STK2_LocalSize := align(STK2_LocalSize, 8);
+ if s1[1] = '-' then
+ str(-STK2_LocalSize, s1)
+ else
+ str(STK2_LocalSize, s1);
+ s := #9 + gas_op2str[A_ADDIU] + #9 + getopstr(taicpu(hp).oper[0]^)+ ',' + getopstr(taicpu(hp).oper[1]^) + ',' + s1;
+ owner.AsmWriteLn(s);
+ end;
+ A_P_FRAME:
+ begin
+ end;
+ A_P_SET_MACRO:
+ begin
+ s := #9 + '.set' + #9 + 'macro';
+ owner.AsmWriteLn(s);
+ end;
+ A_P_SET_REORDER:
+ begin
+ s := #9 + '.set' + #9 + 'reorder';
+ owner.AsmWriteLn(s);
+ end;
+ A_P_SET_NOMACRO:
+ begin
+ s := #9 + '.set' + #9 + 'nomacro';
+ owner.AsmWriteLn(s);
+ end;
+ A_P_SET_NOREORDER:
+ begin
+ s := #9 + '.set' + #9 + 'noreorder';
+ owner.AsmWriteLn(s);
+ end;
+ A_P_SW:
+ begin
+ s := #9 + gas_op2str[A_SW] + #9 + getopstr(taicpu(hp).oper[0]^)+ ',' + getopstr(taicpu(hp).oper[2]^) + '(' + getopstr(taicpu(hp).oper[1]^) + ')';
+ owner.AsmWriteLn(s);
+ end;
+ A_P_LW:
+ begin
+ s := #9 + gas_op2str[A_LW] + #9 + getopstr(taicpu(hp).oper[0]^)+ ',' + getopstr(taicpu(hp).oper[2]^) + '(' + getopstr(taicpu(hp).oper[1]^) + ')';
+ owner.AsmWriteLn(s);
+ end;
+ A_LDC1:
+ begin
+ tmpfpu := getopstr(taicpu(hp).oper[0]^);
+ s := #9 + gas_op2str[A_LWC1] + #9 + tmpfpu + ',' + getopstr(taicpu(hp).oper[1]^); // + '(' + getopstr(taicpu(hp).oper[1]^) + ')';
+ owner.AsmWriteLn(s);
+
+ tmpfpu_len := length(tmpfpu);
+ tmpfpu[tmpfpu_len] := succ(tmpfpu[tmpfpu_len]);
+ s := #9 + gas_op2str[A_LWC1] + #9 + tmpfpu + ',' + getopstr_4(taicpu(hp).oper[1]^); // + '(' + getopstr(taicpu(hp).oper[1]^) + ')';
+ owner.AsmWriteLn(s);
+ end;
+ A_SDC1:
+ begin
+ tmpfpu := getopstr(taicpu(hp).oper[0]^);
+ s := #9 + gas_op2str[A_SWC1] + #9 + tmpfpu + ',' + getopstr(taicpu(hp).oper[1]^); //+ ',' + getopstr(taicpu(hp).oper[2]^) + '(' + getopstr(taicpu(hp).oper[1]^) + ')';
+ owner.AsmWriteLn(s);
+
+ tmpfpu_len := length(tmpfpu);
+ tmpfpu[tmpfpu_len] := succ(tmpfpu[tmpfpu_len]);
+ s := #9 + gas_op2str[A_SWC1] + #9 + tmpfpu + ',' + getopstr_4(taicpu(hp).oper[1]^); //+ ',' + getopstr(taicpu(hp).oper[2]^) + '(' + getopstr(taicpu(hp).oper[1]^) + ')';
+ owner.AsmWriteLn(s);
+ end;
+ else
+ begin
+ s := #9 + gas_op2str[op] + cond2str[taicpu(hp).condition];
+ if taicpu(hp).delayslot_annulled then
+ s := s + ',a';
+ if taicpu(hp).ops > 0 then
+ begin
+ s := s + #9 + getopstr(taicpu(hp).oper[0]^);
+ for i := 1 to taicpu(hp).ops - 1 do
+ s := s + ',' + getopstr(taicpu(hp).oper[i]^);
+ end;
+ owner.AsmWriteLn(s);
+ end;
+ end;
+ end;
+
+
+ const
+ as_MIPSEL_as_info: tasminfo =
+ (
+ id: as_gas;
+ idtxt: 'AS';
+ asmbin: 'as';
+ asmcmd: '-mips2 -W -EL -o $OBJ $ASM';
+ supported_targets: [system_mips_linux,system_mipsel_linux];
+ flags: [af_allowdirect, af_needar, af_smartlink_sections];
+ labelprefix: '.L';
+ comment: '# ';
+ );
+
+begin
+ RegisterAssembler(as_MIPSEL_as_info, TMIPSGNUAssembler);
+end.
diff --git a/closures/compiler/mips/cpuinfo.pas b/closures/compiler/mips/cpuinfo.pas
new file mode 100644
index 0000000000..ddf0494b9c
--- /dev/null
+++ b/closures/compiler/mips/cpuinfo.pas
@@ -0,0 +1,79 @@
+{
+ Copyright (c) 1998-2002 by the Free Pascal development team
+
+ Basic Processor information for the ARM
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+Unit CPUInfo;
+
+Interface
+
+ uses
+ globtype;
+
+Type
+ bestreal = double;
+ ts32real = single;
+ ts64real = double;
+ ts80real = type double;
+ ts128real = type double;
+ ts64comp = comp;
+
+ pbestreal=^bestreal;
+
+ { possible supported processors for this target }
+ tcputype =
+ (cpu_none,
+ cpu_mips32
+ );
+
+ tfputype =(fpu_none,fpu_soft,fpu_mips2,fpu_mips3);
+
+Const
+ {# Size of native extended floating point type }
+ extended_size = 8;
+ {# Size of a multimedia register }
+ mmreg_size = 0;
+ { target cpu string (used by compiler options) }
+{$ifdef MIPSEL}
+ target_cpu_string = 'mipsel';
+{$else MIPSEL}
+ target_cpu_string = 'mips';
+{$endif MIPSEL}
+ { calling conventions supported by the code generator }
+ supported_calling_conventions : tproccalloptions = [
+ pocall_internproc,
+ pocall_stdcall,
+ { same as stdcall only different name mangling }
+ pocall_cdecl,
+ { same as stdcall only different name mangling }
+ pocall_cppdecl
+ ];
+
+ cputypestr : array[tcputype] of string[6] = ('',
+ 'MIPS32'
+ );
+
+ fputypestr : array[tfputype] of string[9] = ('',
+ 'SOFT',
+ 'FPU_MIPS2','FPU_MIPS3'
+ );
+
+ { Supported optimizations, only used for information }
+ supported_optimizerswitches = [cs_opt_regvar,cs_opt_loopunroll,cs_opt_nodecse];
+
+ level1optimizerswitches = [];
+ level2optimizerswitches = level1optimizerswitches + [cs_opt_regvar,cs_opt_stackframe,cs_opt_nodecse];
+ level3optimizerswitches = level2optimizerswitches + [cs_opt_loopunroll];
+
+Implementation
+
+end.
diff --git a/closures/compiler/mips/cpunode.pas b/closures/compiler/mips/cpunode.pas
new file mode 100644
index 0000000000..89ddf3058f
--- /dev/null
+++ b/closures/compiler/mips/cpunode.pas
@@ -0,0 +1,41 @@
+{******************************************************************************
+ Copyright (c) 2000 by Florian Klaempfl
+
+ Includes the MIPS code generator
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ *****************************************************************************}
+unit CpuNode;
+
+{$I fpcdefs.inc}
+
+interface
+{ This unit is used to define the specific CPU implementations. All needed
+actions are included in the INITALIZATION part of these units. This explains
+the behaviour of such a unit having just a USES clause! }
+
+implementation
+
+ uses
+ { generic nodes }
+ ncgbas,ncgld,ncgflw,ncgcnv,ncgmem,ncgcon,ncgcal,ncgset,ncginl,ncgopt,ncgmat,ncgobjc,
+ { to be able to only parts of the generic code,
+ the processor specific nodes must be included
+ after the generic one (FK)
+ }
+ ncpuadd,ncpucall,ncpumat,ncpuinln,ncpucnv,ncpuset;
+
+end.
diff --git a/closures/compiler/mips/cpupara.pas b/closures/compiler/mips/cpupara.pas
new file mode 100644
index 0000000000..c440940943
--- /dev/null
+++ b/closures/compiler/mips/cpupara.pas
@@ -0,0 +1,371 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl and David Zhang
+
+ Calling conventions for the MIPSEL
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *****************************************************************************}
+unit cpupara;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ globtype,
+ cclasses,
+ aasmtai,
+ cpubase,cpuinfo,
+ symconst,symbase,symsym,symtype,symdef,paramgr,parabase,cgbase;
+
+ type
+ TMIPSELParaManager=class(TParaManager)
+ function push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override;
+ function get_volatile_registers_int(calloption : tproccalloption):TCpuRegisterSet;override;
+ function get_volatile_registers_fpu(calloption : tproccalloption):TCpuRegisterSet;override;
+ {Returns a structure giving the information on the storage of the parameter
+ (which must be an integer parameter)
+ @param(nr Parameter number of routine, starting from 1)}
+ procedure getintparaloc(calloption : tproccalloption; nr : longint;var cgpara : TCGPara);override;
+ function create_paraloc_info(p : TAbstractProcDef; side: tcallercallee):longint;override;
+ function create_varargs_paraloc_info(p : TAbstractProcDef; varargspara:tvarargsparalist):longint;override;
+ function get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tcgpara;override;
+ private
+ procedure create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
+ procedure create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras: tparalist;
+ var intparareg,parasize:longint);
+ end;
+
+implementation
+
+ uses
+ cutils,verbose,systems,
+ defutil,
+ cgutils,cgobj;
+
+ type
+ tparasupregs = array[0..5] of tsuperregister;
+ pparasupregs = ^tparasupregs;
+ const
+ paraoutsupregs : tparasupregs = (RS_R4, RS_R5, RS_R6, RS_R7, RS_R8, RS_R9);
+ parainsupregs : tparasupregs = (RS_R4, RS_R5, RS_R6, RS_R7, RS_R8, RS_R9);
+
+
+ function TMIPSELParaManager.get_volatile_registers_int(calloption : tproccalloption):TCpuRegisterSet;
+ begin
+ result:=[RS_R16..RS_R23];
+ end;
+
+
+ function tMIPSELparamanager.get_volatile_registers_fpu(calloption : tproccalloption):TCpuRegisterSet;
+ begin
+ result:=[RS_F0..RS_F31];
+ end;
+
+
+ procedure TMIPSELParaManager.GetIntParaLoc(calloption : tproccalloption; nr : longint;var cgpara : tcgpara);
+ var
+ paraloc : pcgparalocation;
+ begin
+ if nr<1 then
+ InternalError(2002100806);
+ cgpara.reset;
+ cgpara.size:=OS_INT;
+ cgpara.intsize:=tcgsize2size[OS_INT];
+ cgpara.alignment:=std_param_align;
+ paraloc:=cgpara.add_location;
+ with paraloc^ do
+ begin
+ { The six first parameters are passed into registers } {MIPS first four}
+ dec(nr);
+ if nr<6 then //MIPSEL nr<6
+ begin
+ loc:=LOC_REGISTER;
+ register:=newreg(R_INTREGISTER,(RS_R4+nr),R_SUBWHOLE);
+ end
+ else
+ begin
+ { The other parameters are passed on the stack }
+ loc:=LOC_REFERENCE;
+ reference.index:=NR_STACK_POINTER_REG;
+ reference.offset:=92+(nr-6)*4;
+ end;
+ size:=OS_INT;
+ end;
+ end;
+
+ { true if a parameter is too large to copy and only the address is pushed }
+ function tMIPSELparamanager.push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;
+ begin
+ result:=false;
+ { var,out,constref always require address }
+ if varspez in [vs_var,vs_out,vs_constref] then
+ begin
+ result:=true;
+ exit;
+ end;
+ case def.typ of
+ recorddef,
+ arraydef,
+ variantdef,
+ formaldef :
+ push_addr_param:=true;
+ objectdef :
+ result:=is_object(def);
+ stringdef :
+ result:=(tstringdef(def).stringtype in [st_shortstring,st_longstring]);
+ procvardef :
+ result:=not tprocvardef(def).is_addressonly;
+ setdef :
+ result:=not(is_smallset(def));
+ end;
+ end;
+
+
+ procedure tMIPSELparamanager.create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
+ begin
+ p.funcretloc[side]:=get_funcretloc(p,side,p.returndef);
+ end;
+
+
+ function tMIPSELparamanager.get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tcgpara;
+ var
+ paraloc : pcgparalocation;
+ retcgsize : tcgsize;
+ begin
+ result.init;
+ result.alignment:=get_para_align(p.proccalloption);
+ { void has no location }
+ if is_void(def) then
+ begin
+ paraloc:=result.add_location;
+ result.size:=OS_NO;
+ result.intsize:=0;
+ paraloc^.size:=OS_NO;
+ paraloc^.loc:=LOC_VOID;
+ exit;
+ end;
+ { Constructors return self instead of a boolean }
+ if (p.proctypeoption=potype_constructor) then
+ begin
+ retcgsize:=OS_ADDR;
+ result.intsize:=sizeof(pint);
+ end
+ else
+ begin
+ retcgsize:=def_cgsize(def);
+ result.intsize:=def.size;
+ end;
+ result.size:=retcgsize;
+ { Return is passed as var parameter }
+ if ret_in_param(def,p.proccalloption) then
+ begin
+ paraloc:=result.add_location;
+ paraloc^.loc:=LOC_REFERENCE;
+ paraloc^.size:=retcgsize;
+ exit;
+ end;
+
+ paraloc:=result.add_location;
+ { Return in FPU register? }
+ if p.returndef.typ=floatdef then
+ begin
+ paraloc^.loc:=LOC_FPUREGISTER;
+ paraloc^.register:=NR_FPU_RESULT_REG;
+ if retcgsize=OS_F64 then
+ setsubreg(paraloc^.register,R_SUBFD);
+ paraloc^.size:=retcgsize;
+ end
+ else
+ { Return in register }
+ begin
+{$ifndef cpu64bit}
+ if retcgsize in [OS_64,OS_S64] then
+ begin
+ { high }
+ paraloc^.loc:=LOC_REGISTER;
+ if side=callerside then
+ paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG
+ else
+ paraloc^.register:=NR_FUNCTION_RETURN64_HIGH_REG;
+ paraloc^.size:=OS_32;
+ { low }
+ paraloc:=result.add_location;
+ paraloc^.loc:=LOC_REGISTER;
+ if side=callerside then
+ paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG
+ else
+ paraloc^.register:=NR_FUNCTION_RETURN64_LOW_REG;
+ paraloc^.size:=OS_32;
+ end
+ else
+{$endif cpu64bit}
+ begin
+ paraloc^.loc:=LOC_REGISTER;
+ paraloc^.size:=retcgsize;
+ if side=callerside then
+ paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize))
+ else
+ paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(R_INTREGISTER,retcgsize));
+ end;
+ end
+ end;
+
+ var
+ param_offset:array[0..20] of ^Aint;
+
+ procedure tMIPSELparamanager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee;paras:tparalist;
+ var intparareg,parasize:longint);
+ var
+ paraloc : pcgparalocation;
+ i : integer;
+ hp : tparavarsym;
+ paracgsize : tcgsize;
+ hparasupregs : pparasupregs;
+ paralen : longint;
+ begin
+ if side=callerside then
+ hparasupregs:=@paraoutsupregs
+ else
+ hparasupregs:=@parainsupregs;
+ for i:=0 to paras.count-1 do
+ begin
+
+ param_offset[i] := Nil;
+ hp:=tparavarsym(paras[i]);
+ { currently only support C-style array of const,
+ there should be no location assigned to the vararg array itself }
+ if (p.proccalloption in [pocall_cdecl,pocall_cppdecl]) and
+ is_array_of_const(hp.vardef) then
+ begin
+ paraloc:=hp.paraloc[side].add_location;
+ { hack: the paraloc must be valid, but is not actually used }
+ paraloc^.loc:=LOC_REGISTER;
+ paraloc^.register:=NR_R0;
+ paraloc^.size:=OS_ADDR;
+ break;
+ end;
+
+ if push_addr_param(hp.varspez,hp.vardef,p.proccalloption) then
+ paracgsize:=OS_ADDR
+ else
+ begin
+ paracgsize:=def_cgSize(hp.vardef);
+ if paracgsize=OS_NO then
+ paracgsize:=OS_ADDR;
+ end;
+ hp.paraloc[side].reset;
+ hp.paraloc[side].size:=paracgsize;
+ hp.paraloc[side].Alignment:=std_param_align;
+ paralen:=tcgsize2size[paracgsize];
+ hp.paraloc[side].intsize:=paralen;
+ while paralen>0 do
+ begin
+ paraloc:=hp.paraloc[side].add_location;
+ { Floats are passed in int registers,
+ We can allocate at maximum 32 bits per register }
+ if paracgsize in [OS_64,OS_S64,OS_F32,OS_F64] then
+ paraloc^.size:=OS_32
+ else
+ paraloc^.size:=paracgsize;
+ { ret in param? }
+ if vo_is_funcret in hp.varoptions then
+ begin
+ paraloc^.loc:=LOC_REFERENCE;
+ if side=callerside then
+ begin
+ paraloc^.reference.index := NR_STACK_POINTER_REG;
+ paraloc^.reference.offset:=target_info.first_parm_offset{1000}-12 - parasize;
+ end
+ else
+ begin
+ paraloc^.reference.index := NR_FRAME_POINTER_REG;
+ paraloc^.reference.offset:=target_info.first_parm_offset{1000}-4 - parasize;
+ param_offset[i] := @paraloc^.reference.offset;
+ end;
+ inc(parasize,align(tcgsize2size[paraloc^.size],sizeof(aint)));
+ end
+ { In case of po_delphi_nested_cc, the parent frame pointer
+ is always passed on the stack. }
+ else if (intparareg<=high(tparasupregs)) and
+ (not(vo_is_parentfp in hp.varoptions) or
+ not(po_delphi_nested_cc in p.procoptions)) then
+ begin
+ paraloc^.loc:=LOC_REGISTER;
+ paraloc^.register:=newreg(R_INTREGISTER,hparasupregs^[intparareg],R_SUBWHOLE);
+ inc(intparareg);
+ end
+ else
+ begin
+ paraloc^.loc:=LOC_REFERENCE;
+ if side=callerside then
+ begin
+ paraloc^.reference.index := {NR_R17;//}NR_STACK_POINTER_REG;
+ paraloc^.reference.offset:=target_info.first_parm_offset{1000}-12 - parasize;
+ end
+ else
+ begin
+ paraloc^.reference.index := {NR_R18;//}NR_FRAME_POINTER_REG;
+ paraloc^.reference.offset:=target_info.first_parm_offset{1000}-4 - parasize;
+ param_offset[i] := @paraloc^.reference.offset;
+ end;
+ { Parameters are aligned at 4 bytes }
+ inc(parasize,align(tcgsize2size[paraloc^.size],sizeof(aint)));
+ end;
+ dec(paralen,tcgsize2size[paraloc^.size]);
+ end;
+ end;
+ for i:=0 to paras.count-1 do
+ begin
+ if (side = calleeside) and (param_offset[i] <> nil) then
+ param_offset[i]^ := param_offset[i]^ + parasize - 8;
+ end;
+ end;
+
+
+ function TMIPSELParaManager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;
+ var
+ intparareg,
+ parasize : longint;
+ begin
+ intparareg:=0;
+ parasize:=0;
+ { calculate the registers for the normal parameters }
+ create_paraloc_info_intern(p,callerside,p.paras,intparareg,parasize);
+ { append the varargs }
+ create_paraloc_info_intern(p,callerside,varargspara,intparareg,parasize);
+ result:=parasize;
+ end;
+
+
+
+ function tMIPSELparamanager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;
+ var
+ intparareg,
+ parasize : longint;
+ begin
+ intparareg:=0;
+ parasize:=0;
+ create_paraloc_info_intern(p,side,p.paras,intparareg,parasize);
+ { Create Function result paraloc }
+ create_funcretloc_info(p,side);
+ { We need to return the size allocated on the stack }
+ result:=parasize;
+ end;
+
+
+begin
+ ParaManager:=TMIPSELParaManager.create;
+end.
diff --git a/closures/compiler/mips/cpupi.pas b/closures/compiler/mips/cpupi.pas
new file mode 100644
index 0000000000..1c2dd53afd
--- /dev/null
+++ b/closures/compiler/mips/cpupi.pas
@@ -0,0 +1,76 @@
+{
+ Copyright (c) 2002-2009 by Florian Klaempfl and David Zhang
+
+ This unit contains the CPU specific part of tprocinfo
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit cpupi;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cutils,
+ procinfo,cpuinfo,
+ psub;
+
+ type
+ TMIPSProcInfo=class(tcgprocinfo)
+ public
+ constructor create(aparent:tprocinfo);override;
+ function calc_stackframe_size:longint;override;
+ end;
+
+implementation
+
+ uses
+ systems,globals,
+ tgobj,paramgr,symconst;
+
+ constructor tmipsprocinfo.create(aparent:tprocinfo);
+ begin
+ inherited create(aparent);
+ maxpushedparasize:=0;
+ end;
+
+
+ function TMIPSProcInfo.calc_stackframe_size:longint;
+ begin
+ {
+ Stackframe layout:
+ %fp
+ <locals>
+ <temp>
+ <arguments 6-n for calling>
+ %sp+92
+ <space for arguments 0-5> \
+ <return pointer for calling> | included in first_parm_offset
+ <register window save area for calling> /
+ %sp
+
+ Alignment must be the max available, as doubles require
+ 8 byte alignment
+ }
+ result:=Align(tg.direction*tg.lasttemp+maxpushedparasize+target_info.first_parm_offset,current_settings.alignment.localalignmax);
+ end;
+
+
+begin
+ cprocinfo:=TMIPSProcInfo;
+end.
diff --git a/closures/compiler/mips/cputarg.pas b/closures/compiler/mips/cputarg.pas
new file mode 100644
index 0000000000..40fc726163
--- /dev/null
+++ b/closures/compiler/mips/cputarg.pas
@@ -0,0 +1,53 @@
+{
+ Copyright (c) 2001 by Peter Vreman
+
+ Includes the mips dependent target units
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit cputarg;
+
+{$i fpcdefs.inc}
+
+interface
+
+
+implementation
+
+ uses
+ systems { prevent a syntax error when nothing is included }
+
+{$ifndef NOOPT}
+ ,aoptcpu
+{$endif NOOPT}
+
+{**************************************
+ Targets
+**************************************}
+
+ {$ifndef NOTARGETLINUX}
+ ,t_linux
+ {$endif}
+
+{**************************************
+ Assemblers
+**************************************}
+
+ ,CpuGas
+ ;
+
+end.
diff --git a/closures/compiler/mips/itcpugas.pas b/closures/compiler/mips/itcpugas.pas
new file mode 100644
index 0000000000..294edf58c1
--- /dev/null
+++ b/closures/compiler/mips/itcpugas.pas
@@ -0,0 +1,101 @@
+{
+ Copyright (c) 1998-2009 by Mazen NEIFER and David Zhang
+
+ This unit contains the MIPS GAS instruction tables
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit itcpugas;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ cpubase, cgbase;
+
+const
+ gas_op2str: array[tasmop] of string[15] = ({$INCLUDE strinst.inc});
+
+function gas_regnum_search(const s: string): Tregister;
+function gas_regname(r: Tregister): string;
+
+
+implementation
+
+uses
+ cutils, verbose;
+
+const
+ gas_regname_table: array[tregisterindex] of string[7] = (
+ {$i rmipsstd.inc}
+ );
+
+ gas_regname_index: array[tregisterindex] of tregisterindex = (
+ {$i rmipssri.inc}
+ );
+
+
+function findreg_by_gasname(const s: string): tregisterindex;
+var
+ i, p: tregisterindex;
+begin
+ for p := low(tregisterindex) to high(tregisterindex) do
+ begin
+ if gas_regname_table[gas_regname_index[p]] = s then
+ begin
+ findreg_by_gasname := gas_regname_index[p];
+ exit
+ end;
+ end;
+ findreg_by_gasname := 0;
+end;
+
+
+function gas_regnum_search(const s: string): Tregister;
+begin
+ Result := regnumber_table[findreg_by_gasname(s)];
+end;
+
+
+function gas_regname(r: Tregister): string;
+var
+ hr: tregister;
+ p: longint;
+begin
+ { Double uses the same table as single }
+ hr := r;
+ case getsubreg(hr) of
+ R_SUBFD:
+ setsubreg(hr, R_SUBFS);
+ R_SUBL, R_SUBW, R_SUBD, R_SUBQ:
+ setsubreg(hr, R_SUBD);
+ end;
+ p := findreg_by_number(hr);
+ if p <> 0 then
+ Result := gas_regname_table[p]
+ else
+ Result := generic_regname(r);
+end;
+
+end.
+{
+ $Log: itcpugas.pas,v $
+ Revision 1.7 2005/02/14 17:13:10 peter
+ * truncate log
+
+}
diff --git a/closures/compiler/mips/mipsreg.dat b/closures/compiler/mips/mipsreg.dat
new file mode 100644
index 0000000000..c666d257cf
--- /dev/null
+++ b/closures/compiler/mips/mipsreg.dat
@@ -0,0 +1,83 @@
+;
+; MIPS registers
+;
+; layout
+; <name>,<value>,<stdname>,<gasname>,<stabidx>
+;
+NO,$00,$00,INVALID,INVALID,-1,-1
+
+R0,$01,$00,r0,r0,0,0
+R1,$01,$01,r1,r1,1,1
+R2,$01,$02,r2,r2,2,2
+R3,$01,$03,r3,r3,3,3
+R4,$01,$04,r4,r4,4,4
+R5,$01,$05,r5,r5,5,5
+R6,$01,$06,r6,r6,6,6
+R7,$01,$07,r7,r7,7,7
+R8,$01,$08,r8,r8,8,8
+R9,$01,$09,r9,r9,9,9
+R10,$01,$0a,r10,r10,10,10
+R11,$01,$0b,r11,r11,11,11
+R12,$01,$0c,r12,r12,12,12
+R13,$01,$0d,r13,r13,13,13
+R14,$01,$0e,r14,r14,14,14
+R15,$01,$0f,r15,r15,15,15
+R16,$01,$10,r16,r16,16,16
+R17,$01,$11,r17,r17,17,17
+R18,$01,$12,r18,r18,18,18
+R19,$01,$13,r19,r19,19,19
+R20,$01,$14,r20,r20,20,20
+R21,$01,$15,r21,r21,21,21
+R22,$01,$16,r22,r22,22,22
+R23,$01,$17,r23,r23,23,23
+R24,$01,$18,r24,r24,24,24
+R25,$01,$19,r25,r25,25,25
+R26,$01,$1a,r26,r26,26,26
+R27,$01,$1b,r27,r27,27,27
+R28,$01,$1c,r28,r28,28,28
+R29,$01,$1d,r29,r29,29,29
+R30,$01,$1e,r30,r30,30,30
+R31,$01,$1f,r31,r31,31,31
+
+F0,$02,$00,F0,f0,32,32
+F1,$02,$01,F1,f1,33,33
+F2,$02,$02,F2,f2,34,34
+F3,$02,$03,F3,f3,35,35
+F4,$02,$04,F4,f4,36,36
+F5,$02,$05,F5,f5,37,37
+F6,$02,$06,F6,f6,38,38
+F7,$02,$07,F7,f7,39,39
+F8,$02,$08,F8,f8,40,40
+F9,$02,$09,F9,f9,41,41
+F10,$02,$0a,F10,f10,42,42
+F11,$02,$0b,F11,f11,43,43
+F12,$02,$0c,F12,f12,44,44
+F13,$02,$0d,F13,f13,45,45
+F14,$02,$0e,F14,f14,46,46
+F15,$02,$0f,F15,f15,47,47
+F16,$02,$10,F16,f16,48,48
+F17,$02,$11,F17,f17,49,49
+F18,$02,$12,F18,f18,50,50
+F19,$02,$13,F19,f19,51,51
+F20,$02,$14,F20,f20,52,52
+F21,$02,$15,F21,f21,53,53
+F22,$02,$16,F22,f22,54,54
+F23,$02,$17,F23,f23,55,55
+F24,$02,$18,F24,f24,56,56
+F25,$02,$19,F25,f25,57,57
+F26,$02,$1a,F26,f26,58,58
+F27,$02,$1b,F27,f27,59,59
+F28,$02,$1c,F28,f28,60,60
+F29,$02,$1d,F29,f29,61,61
+F30,$02,$1e,F30,f30,62,62
+F31,$02,$1f,F31,f31,63,63
+
+PC,$05,$00,PC,pc,-1,-1
+HI,$05,$01,HI,hi,68,68
+LO,$05,$02,LO,lo,69,69
+CR,$05,$03,CR,cr,70,70
+FCR0,$05,$04,FCR0,fcr0,71,71
+FCR25,$05,$05,FCR25,fcr25,72,72
+FCR26,$05,$06,FCR26,fcr26,73,73
+FCR28,$05,$07,FCR28,fcr28,74,74
+FCSR,$05,$08,FCSR,fcsr,75,75
diff --git a/closures/compiler/mips/ncpuadd.pas b/closures/compiler/mips/ncpuadd.pas
new file mode 100644
index 0000000000..e1ba25794b
--- /dev/null
+++ b/closures/compiler/mips/ncpuadd.pas
@@ -0,0 +1,598 @@
+{
+ Copyright (c) 2000-2009 by Florian Klaempfl and David Zhang
+
+ Code generation for add nodes on the FVM32
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit ncpuadd;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ node, ncgadd, cpubase, aasmbase, cgbase;
+
+type
+ tmipsaddnode = class(tcgaddnode)
+ private
+ function cmp64_lt(left_reg, right_reg: TRegister64): TRegister;
+ function cmp64_le(left_reg, right_reg: TRegister64): TRegister;
+ function cmp64_eq(left_reg, right_reg: TRegister64): TRegister;
+ function cmp64_ne(left_reg, right_reg: TRegister64): TRegister;
+ function cmp64_ltu(left_reg, right_reg: TRegister64): TRegister;
+ function cmp64_leu(left_reg, right_reg: TRegister64): TRegister;
+
+ function GetRes_register(unsigned: boolean; this_reg, left_reg, right_reg: TRegister): TRegister;
+ function GetRes64_register(unsigned: boolean; {this_reg,} left_reg, right_reg: TRegister64): TRegister;
+ protected
+ procedure second_addfloat; override;
+ procedure second_cmpfloat; override;
+ procedure second_cmpboolean; override;
+ procedure second_cmpsmallset; override;
+ procedure second_cmp64bit; override;
+ procedure second_cmpordinal; override;
+ end;
+
+implementation
+
+uses
+ systems,
+ cutils, verbose,
+ paramgr,
+ aasmtai, aasmcpu, aasmdata,
+ defutil,
+ {cgbase,} cgcpu, cgutils,
+ cpupara,
+ ncon, nset, nadd,
+ ncgutil, cgobj;
+
+{*****************************************************************************
+ tmipsaddnode
+*****************************************************************************}
+function tmipsaddnode.GetRes_register(unsigned: boolean; this_reg, left_reg, right_reg: TRegister): TRegister;
+var
+ tmp_asm_op: tasmop;
+begin
+ case NodeType of
+ equaln:
+ tmp_asm_op := A_SEQ;
+ unequaln:
+ tmp_asm_op := A_SNE;
+ else
+ if not (unsigned) then
+ begin
+ if nf_swapped in flags then
+ case NodeType of
+ ltn:
+ tmp_asm_op := A_SGT;
+ lten:
+ tmp_asm_op := A_SGE;
+ gtn:
+ tmp_asm_op := A_SLT;
+ gten:
+ tmp_asm_op := A_SLE;
+ end
+ else
+ case NodeType of
+ ltn:
+ tmp_asm_op := A_SLT;
+ lten:
+ tmp_asm_op := A_SLE;
+ gtn:
+ tmp_asm_op := A_SGT;
+ gten:
+ tmp_asm_op := A_SGE;
+ end;
+ end
+ else
+ begin
+ if nf_swapped in Flags then
+ case NodeType of
+ ltn:
+ tmp_asm_op := A_SGTU;
+ lten:
+ tmp_asm_op := A_SGEU;
+ gtn:
+ tmp_asm_op := A_SLTU;
+ gten:
+ tmp_asm_op := A_SLEU;
+ end
+ else
+ case NodeType of
+ ltn:
+ tmp_asm_op := A_SLTU;
+ lten:
+ tmp_asm_op := A_SLEU;
+ gtn:
+ tmp_asm_op := A_SGTU;
+ gten:
+ tmp_asm_op := A_SGEU;
+ end;
+ end;
+ end;
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(tmp_asm_op, this_reg, left_reg, right_reg));
+ GetRes_register := this_reg;
+end;
+
+function tmipsaddnode.cmp64_eq(left_reg, right_reg: TRegister64): TRegister;
+var
+ lfcmp64_L4: tasmlabel;
+begin
+
+ current_asmdata.getjumplabel(lfcmp64_L4);
+
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_LI, NR_TCR10, 0));
+
+ current_asmdata.CurrAsmList.concat(Taicpu.op_reg_reg_sym(A_BNE, left_reg.reghi, right_reg.reghi, lfcmp64_L4));
+ current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP));
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_sym(A_BNE, left_reg.reglo, right_reg.reglo, lfcmp64_L4));
+ current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP));
+
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_LI, NR_TCR10, 1));
+
+ cg.a_label(current_asmdata.CurrAsmList, lfcmp64_L4);
+ cmp64_eq := NR_TCR10;
+end;
+
+function tmipsaddnode.cmp64_ne(left_reg, right_reg: TRegister64): TRegister;
+var
+ lfcmp64_L4: tasmlabel;
+begin
+
+ current_asmdata.getjumplabel(lfcmp64_L4);
+
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_LI, NR_TCR10, 1));
+
+ current_asmdata.CurrAsmList.concat(Taicpu.op_reg_reg_sym(A_BNE, left_reg.reghi, right_reg.reghi, lfcmp64_L4));
+ current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP));
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_sym(A_BNE, left_reg.reglo, right_reg.reglo, lfcmp64_L4));
+ current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP));
+
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_LI, NR_TCR10, 0));
+
+ cg.a_label(current_asmdata.CurrAsmList, lfcmp64_L4);
+ cmp64_ne := NR_TCR10;
+end;
+
+function tmipsaddnode.cmp64_lt(left_reg, right_reg: TRegister64): TRegister;
+var
+ lfcmp64_L4, lfcmp64_L5: tasmlabel;
+begin
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_LI, NR_TCR10, 0));
+
+ current_asmdata.getjumplabel(lfcmp64_L4);
+ current_asmdata.getjumplabel(lfcmp64_L5);
+
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SLT, NR_TCR11, left_reg.reghi, right_reg.reghi));
+ current_asmdata.CurrAsmList.concat(Taicpu.op_reg_reg_sym(A_BNE, NR_TCR11, NR_R0, lfcmp64_L5));
+ current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP));
+ current_asmdata.CurrAsmList.concat(Taicpu.op_reg_reg_sym(A_BNE, left_reg.reghi, right_reg.reghi, lfcmp64_L4));
+ current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP));
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SLTU, NR_TCR11, left_reg.reglo, right_reg.reglo));
+ current_asmdata.CurrAsmList.concat(Taicpu.op_reg_reg_sym(A_BNE, NR_TCR11, NR_R0, lfcmp64_L5));
+ current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP));
+ current_asmdata.CurrAsmList.concat(Taicpu.op_sym(A_B, lfcmp64_L4));
+ current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP));
+
+ cg.a_label(current_asmdata.CurrAsmList, lfcmp64_L5);
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_LI, NR_TCR10, 1));
+
+ cg.a_label(current_asmdata.CurrAsmList, lfcmp64_L4);
+ cmp64_lt := NR_TCR10;
+end;
+
+function tmipsaddnode.cmp64_le(left_reg, right_reg: TRegister64): TRegister;
+var
+ lfcmp64_L4, lfcmp64_L5: tasmlabel;
+begin
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_LI, NR_TCR10, 0));
+
+ current_asmdata.getjumplabel(lfcmp64_L4);
+ current_asmdata.getjumplabel(lfcmp64_L5);
+
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SLT, NR_TCR11, right_reg.reghi, left_reg.reghi));
+ current_asmdata.CurrAsmList.concat(Taicpu.op_reg_reg_sym(A_BNE, NR_TCR11, NR_R0, lfcmp64_L4));
+ current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP));
+ current_asmdata.CurrAsmList.concat(Taicpu.op_reg_reg_sym(A_BNE, right_reg.reghi, left_reg.reghi, lfcmp64_L5));
+ current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP));
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SLTU, NR_TCR11, right_reg.reglo, left_reg.reglo));
+ current_asmdata.CurrAsmList.concat(Taicpu.op_reg_reg_sym(A_BNE, NR_TCR11, NR_R0, lfcmp64_L4));
+ current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP));
+
+ cg.a_label(current_asmdata.CurrAsmList, lfcmp64_L5);
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_LI, NR_TCR10, 1));
+
+ cg.a_label(current_asmdata.CurrAsmList, lfcmp64_L4);
+ cmp64_le := NR_TCR10;
+end;
+
+function tmipsaddnode.cmp64_ltu(left_reg, right_reg: TRegister64): TRegister;
+var
+ lfcmp64_L4, lfcmp64_L5: tasmlabel;
+begin
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_LI, NR_TCR10, 0));
+
+ current_asmdata.getjumplabel(lfcmp64_L4);
+ current_asmdata.getjumplabel(lfcmp64_L5);
+
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SLTU, NR_TCR11, left_reg.reghi, right_reg.reghi));
+ current_asmdata.CurrAsmList.concat(Taicpu.op_reg_reg_sym(A_BNE, NR_TCR11, NR_R0, lfcmp64_L5));
+ current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP));
+ current_asmdata.CurrAsmList.concat(Taicpu.op_reg_reg_sym(A_BNE, left_reg.reghi, right_reg.reghi, lfcmp64_L4));
+ current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP));
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SLTU, NR_TCR11, left_reg.reglo, right_reg.reglo));
+ current_asmdata.CurrAsmList.concat(Taicpu.op_reg_reg_sym(A_BNE, NR_TCR11, NR_R0, lfcmp64_L5));
+ current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP));
+ current_asmdata.CurrAsmList.concat(Taicpu.op_sym(A_B, lfcmp64_L4));
+ current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP));
+
+ cg.a_label(current_asmdata.CurrAsmList, lfcmp64_L5);
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_LI, NR_TCR10, 1));
+
+ cg.a_label(current_asmdata.CurrAsmList, lfcmp64_L4);
+ cmp64_ltu := NR_TCR10;
+end;
+
+function tmipsaddnode.cmp64_leu(left_reg, right_reg: TRegister64): TRegister;
+var
+ lfcmp64_L4, lfcmp64_L5: tasmlabel;
+begin
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_LI, NR_TCR10, 0));
+
+ current_asmdata.getjumplabel(lfcmp64_L4);
+ current_asmdata.getjumplabel(lfcmp64_L5);
+
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SLTU, NR_TCR11, right_reg.reghi, left_reg.reghi));
+ current_asmdata.CurrAsmList.concat(Taicpu.op_reg_reg_sym(A_BNE, NR_TCR11, NR_R0, lfcmp64_L4));
+ current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP));
+ current_asmdata.CurrAsmList.concat(Taicpu.op_reg_reg_sym(A_BNE, right_reg.reghi, left_reg.reghi, lfcmp64_L5));
+ current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP));
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SLTU, NR_TCR11, right_reg.reglo, left_reg.reglo));
+ current_asmdata.CurrAsmList.concat(Taicpu.op_reg_reg_sym(A_BNE, NR_TCR11, NR_R0, lfcmp64_L4));
+ current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP));
+
+ cg.a_label(current_asmdata.CurrAsmList, lfcmp64_L5);
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_LI, NR_TCR10, 1));
+
+ cg.a_label(current_asmdata.CurrAsmList, lfcmp64_L4);
+ cmp64_leu := NR_TCR10;
+end;
+
+function tmipsaddnode.GetRes64_register(unsigned: boolean; //this_reg: TRegister;
+ left_reg, right_reg: TRegister64): TRegister;
+var
+ tmpreg: TRegister;
+ lfcmp64_L4, lfcmp_L5: tasmlabel;
+begin
+ case NodeType of
+ equaln:
+ begin
+ GetRes64_register := cmp64_eq(left_reg, right_reg);
+ end;
+ unequaln:
+ GetRes64_register := cmp64_ne(left_reg, right_reg);
+ else
+ if not (unsigned) then
+ begin
+ if nf_swapped in flags then
+ case NodeType of
+ ltn:
+ GetRes64_register := cmp64_lt(right_reg, left_reg);
+ lten:
+ GetRes64_register := cmp64_le(right_reg, left_reg);
+ gtn:
+ GetRes64_register := cmp64_lt(left_reg, right_reg);
+ gten:
+ GetRes64_register := cmp64_le(left_reg, right_reg);
+ end
+ else
+ case NodeType of
+ ltn:
+ GetRes64_register := cmp64_lt(left_reg, right_reg);
+ lten:
+ GetRes64_register := cmp64_le(left_reg, right_reg);
+ gtn:
+ GetRes64_register := cmp64_lt(right_reg, left_reg);
+ gten:
+ GetRes64_register := cmp64_le(right_reg, left_reg);
+ end;
+ end
+ else
+ begin
+ if nf_swapped in Flags then
+ case NodeType of
+ ltn:
+ GetRes64_register := cmp64_ltu(right_reg, left_reg);
+ lten:
+ GetRes64_register := cmp64_leu(right_reg, left_reg);
+ gtn:
+ GetRes64_register := cmp64_ltu(left_reg, right_reg);
+ gten:
+ GetRes64_register := cmp64_leu(left_reg, right_reg);
+ end
+ else
+ case NodeType of
+ ltn:
+ GetRes64_register := cmp64_ltu(left_reg, right_reg);
+ lten:
+ GetRes64_register := cmp64_leu(left_reg, right_reg);
+ gtn:
+ GetRes64_register := cmp64_ltu(right_reg, left_reg);
+ gten:
+ GetRes64_register := cmp64_leu(right_reg, left_reg);
+ end;
+ end;
+ end;
+end;
+
+procedure tmipsaddnode.second_addfloat;
+var
+ op: TAsmOp;
+begin
+ pass_left_right;
+ if (nf_swapped in flags) then
+ swapleftright;
+
+ { force fpureg as location, left right doesn't matter
+ as both will be in a fpureg }
+ location_force_fpureg(current_asmdata.CurrAsmList, left.location, True);
+ location_force_fpureg(current_asmdata.CurrAsmList, right.location, (left.location.loc <> LOC_CFPUREGISTER));
+
+ location_reset(location, LOC_FPUREGISTER, def_cgsize(resultdef));
+ if left.location.loc <> LOC_CFPUREGISTER then
+ location.Register := left.location.Register
+ else
+ location.Register := right.location.Register;
+
+ case nodetype of
+ addn:
+ begin
+ if location.size = OS_F64 then
+ op := A_ADD_D
+ else
+ op := A_ADD_S;
+ end;
+ muln:
+ begin
+ if location.size = OS_F64 then
+ op := A_MUL_D
+ else
+ op := A_MUL_S;
+ end;
+ subn:
+ begin
+ if location.size = OS_F64 then
+ op := A_SUB_D
+ else
+ op := A_SUB_S;
+ end;
+ slashn:
+ begin
+ if location.size = OS_F64 then
+ op := A_DIV_D
+ else
+ op := A_DIV_S;
+ end;
+ else
+ internalerror(200306014);
+ end;
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(op,
+ location.Register, left.location.Register, right.location.Register));
+
+end;
+
+
+procedure tmipsaddnode.second_cmpfloat;
+var
+ op: tasmop;
+ lfcmptrue, lfcmpfalse: tasmlabel;
+begin
+ pass_left_right;
+ if nf_swapped in flags then
+ swapleftright;
+
+ { force fpureg as location, left right doesn't matter
+ as both will be in a fpureg }
+ location_force_fpureg(current_asmdata.CurrAsmList, left.location, True);
+ location_force_fpureg(current_asmdata.CurrAsmList, right.location, True);
+
+ location_reset(location, LOC_REGISTER, OS_INT);
+ location.Register := NR_TCR0;
+
+ case NodeType of
+ equaln:
+ begin
+ if left.location.size = OS_F64 then
+ op := A_C_EQ_D
+ else
+ op := A_C_EQ_S;
+ current_asmdata.getjumplabel(lfcmpfalse);
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_OR, location.Register {NR_TCR0}, NR_R0, NR_R0));
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op, left.location.Register, right.location.Register));
+ current_asmdata.CurrAsmList.concat(Taicpu.op_sym(A_BC1F, lfcmpfalse)); //lfcmpfalse
+ current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP));
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_const(A_ORI, location.Register{NR_TCR0}, NR_R0, 1));
+ cg.a_label(current_asmdata.CurrAsmList, lfcmpfalse);
+
+ end;
+ unequaln:
+ begin
+ if left.location.size = OS_F64 then
+ op := A_C_EQ_D
+ else
+ op := A_C_EQ_S;
+ current_asmdata.getjumplabel(lfcmpfalse);
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_const(A_ORI, location.Register{NR_TCR0}, NR_R0, 1));
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op, left.location.Register, right.location.Register));
+ current_asmdata.CurrAsmList.concat(Taicpu.op_sym(A_BC1F, lfcmpfalse));
+ current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP));
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_OR, location.Register {NR_TCR0}, NR_R0, NR_R0));
+ cg.a_label(current_asmdata.CurrAsmList, lfcmpfalse);
+ end;
+ ltn:
+ begin
+ if left.location.size = OS_F64 then
+ op := A_C_LT_D
+ else
+ op := A_C_LT_S;
+ current_asmdata.getjumplabel(lfcmptrue);
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_const(A_ORI, location.Register{NR_TCR0}, NR_R0, 1));
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op, left.location.Register, right.location.Register));
+ current_asmdata.CurrAsmList.concat(Taicpu.op_sym(A_BC1T, lfcmptrue));
+ current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP));
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_OR, location.Register {NR_TCR0}, NR_R0, NR_R0));
+ cg.a_label(current_asmdata.CurrAsmList, lfcmptrue);
+ end;
+ lten:
+ begin
+ if left.location.size = OS_F64 then
+ op := A_C_LE_D
+ else
+ op := A_C_LE_S;
+ current_asmdata.getjumplabel(lfcmptrue);
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_const(A_ORI, location.Register{NR_TCR0}, NR_R0, 1));
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op, left.location.Register, right.location.Register));
+ current_asmdata.CurrAsmList.concat(Taicpu.op_sym(A_BC1T, lfcmptrue));
+ current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP));
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_OR, location.Register {NR_TCR0}, NR_R0, NR_R0));
+ cg.a_label(current_asmdata.CurrAsmList, lfcmptrue);
+ end;
+ gtn:
+ begin
+ if left.location.size = OS_F64 then
+ op := A_C_LT_D
+ else
+ op := A_C_LT_S;
+ current_asmdata.getjumplabel(lfcmptrue);
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_const(A_ORI, location.Register{NR_TCR0}, NR_R0, 1));
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op, right.location.Register, left.location.Register));
+ current_asmdata.CurrAsmList.concat(Taicpu.op_sym(A_BC1T, lfcmptrue));
+ current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP));
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_OR, location.Register {NR_TCR0}, NR_R0, NR_R0));
+ cg.a_label(current_asmdata.CurrAsmList, lfcmptrue);
+ end;
+ gten:
+ begin
+ if left.location.size = OS_F64 then
+ op := A_C_LE_D
+ else
+ op := A_C_LE_S;
+ current_asmdata.getjumplabel(lfcmptrue);
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_const(A_ORI, location.Register{NR_TCR0}, NR_R0, 1));
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op, right.location.Register, left.location.Register));
+ current_asmdata.CurrAsmList.concat(Taicpu.op_sym(A_BC1T, lfcmptrue));
+ current_asmdata.CurrAsmList.concat(TAiCpu.Op_none(A_NOP));
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_OR, location.Register {NR_TCR0}, NR_R0, NR_R0));
+ cg.a_label(current_asmdata.CurrAsmList, lfcmptrue);
+ end;
+ end; {case}
+end;
+
+
+procedure tmipsaddnode.second_cmpboolean;
+var
+ tmp_right_reg: TRegister;
+begin
+ pass_left_right;
+ force_reg_left_right(True, True);
+ tmp_right_reg := NR_NO;
+ if right.location.loc = LOC_CONSTANT then
+ begin
+ tmp_right_reg := cg.GetIntRegister(current_asmdata.CurrAsmList, OS_INT);
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_LI, tmp_right_reg, right.location.Value));
+ end
+ else
+ begin
+ tmp_right_reg := right.location.Register;
+ end;
+
+ location_reset(location, LOC_REGISTER, OS_INT);
+ location.Register := GetRes_register(True, NR_TCR0, left.location.Register, tmp_right_reg);
+
+end;
+
+
+procedure tmipsaddnode.second_cmpsmallset;
+var
+ tmp_right_reg: TRegister;
+begin
+ pass_left_right;
+ force_reg_left_right(True, True);
+
+ tmp_right_reg := NR_NO;
+
+ if right.location.loc = LOC_CONSTANT then
+ begin
+ tmp_right_reg := cg.GetIntRegister(current_asmdata.CurrAsmList, OS_INT);
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_LI, tmp_right_reg, right.location.Value));
+ end
+ else
+ begin
+ tmp_right_reg := right.location.Register;
+ end;
+
+
+ location_reset(location, LOC_REGISTER, OS_INT);
+ location.Register := GetRes_register(True, NR_TCR0, left.location.Register, tmp_right_reg);
+end;
+
+
+procedure tmipsaddnode.second_cmp64bit;
+var
+ unsigned : boolean;
+ tmp_left_reg: TRegister;
+
+begin
+ pass_left_right;
+ force_reg_left_right(false,false);
+
+ unsigned:=not(is_signed(left.resultdef)) or
+ not(is_signed(right.resultdef));
+
+ location_reset(location, LOC_REGISTER, OS_INT);
+ location.Register := GetRes64_register(unsigned, {NR_TCR0, }left.location.register64, right.location.register64); // NR_TCR0;
+end;
+
+
+procedure tmipsaddnode.second_cmpordinal;
+var
+ unsigned: boolean;
+ tmp_right_reg: TRegister;
+begin
+ pass_left_right;
+ force_reg_left_right(True, True);
+ unsigned := not (is_signed(left.resultdef)) or not (is_signed(right.resultdef));
+
+ tmp_right_reg := NR_NO;
+ if right.location.loc = LOC_CONSTANT then
+ begin
+ tmp_right_reg := cg.GetIntRegister(current_asmdata.CurrAsmList, OS_INT);
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_LI, tmp_right_reg, right.location.Value));
+ end
+ else
+ begin
+ tmp_right_reg := right.location.Register;
+ end;
+ location_reset(location, LOC_REGISTER, OS_INT);
+ location.Register := getres_register(unsigned, NR_TCR0, left.location.Register, tmp_right_reg);
+end;
+
+begin
+ caddnode := tmipsaddnode;
+end.
diff --git a/closures/compiler/mips/ncpucall.pas b/closures/compiler/mips/ncpucall.pas
new file mode 100644
index 0000000000..65db4569c9
--- /dev/null
+++ b/closures/compiler/mips/ncpucall.pas
@@ -0,0 +1,62 @@
+{
+ Copyright (c) 1998-2009 by Florian Klaempfl and David Zhang
+
+ Generate MIPSEL assembler for in call nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit ncpucall;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ ncgcal;
+
+type
+ tMIPSELcallnode = class(tcgcallnode)
+ procedure extra_call_code; override;
+ procedure extra_post_call_code; override;
+ end;
+
+
+implementation
+
+uses
+ cpubase,
+ aasmtai,aasmcpu,aasmdata,
+ paramgr,
+ ncal;
+
+procedure tMIPSELcallnode.extra_call_code;
+begin
+ if pushedparasize > 0 then
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_const(A_ADDIU, NR_STACK_POINTER_REG, NR_STACK_POINTER_REG, -pushedparasize));
+end;
+
+procedure tMIPSELcallnode.extra_post_call_code;
+begin
+ if pushedparasize > 0 then
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_const(A_ADDIU, NR_STACK_POINTER_REG, NR_STACK_POINTER_REG, pushedparasize));
+
+end;
+
+
+begin
+ ccallnode := TMIPSELCallNode;
+end.
diff --git a/closures/compiler/mips/ncpucnv.pas b/closures/compiler/mips/ncpucnv.pas
new file mode 100644
index 0000000000..18743252ad
--- /dev/null
+++ b/closures/compiler/mips/ncpucnv.pas
@@ -0,0 +1,286 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl and David Zhang
+
+ Generate MIPSEL assembler for type converting nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************}
+unit ncpucnv;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ node, ncnv, ncgcnv, defcmp;
+
+type
+ tMIPSELtypeconvnode = class(TCgTypeConvNode)
+ protected
+ { procedure second_int_to_int;override; }
+ { procedure second_string_to_string;override; }
+ { procedure second_cstring_to_pchar;override; }
+ { procedure second_string_to_chararray;override; }
+ { procedure second_array_to_pointer;override; }
+ function first_int_to_real: tnode; override;
+ { procedure second_pointer_to_array;override; }
+ { procedure second_chararray_to_string;override; }
+ { procedure second_char_to_string;override; }
+ procedure second_int_to_real; override;
+ procedure second_real_to_real; override;
+ { procedure second_cord_to_pointer;override; }
+ { procedure second_proc_to_procvar;override; }
+ { procedure second_bool_to_int;override; }
+ procedure second_int_to_bool; override;
+ { procedure second_load_smallset;override; }
+ { procedure second_ansistring_to_pchar;override; }
+ { procedure second_pchar_to_string;override; }
+ { procedure second_class_to_intf;override; }
+ { procedure second_char_to_char;override; }
+ end;
+
+implementation
+
+uses
+ verbose, globtype, globals, systems,
+ symconst, symdef, aasmbase, aasmtai, aasmdata,
+ defutil,
+ cgbase, cgutils, pass_1, pass_2, procinfo,
+ ncon, ncal,
+ ncgutil,
+ cpubase, aasmcpu,
+ tgobj, cgobj;
+
+
+{*****************************************************************************
+ FirstTypeConv
+*****************************************************************************}
+
+function tMIPSELtypeconvnode.first_int_to_real: tnode;
+var
+ fname: string[19];
+begin
+ { converting a 64bit integer to a float requires a helper }
+ if is_64bitint(left.resultdef) or
+ is_currency(left.resultdef) then
+ begin
+ { hack to avoid double division by 10000, as it's
+ already done by resulttypepass.resulttype_int_to_real }
+ if is_currency(left.resultdef) then
+ left.resultdef := s64inttype;
+ if is_signed(left.resultdef) then
+ fname := 'fpc_int64_to_double'
+ else
+ fname := 'fpc_qword_to_double';
+ Result := ccallnode.createintern(fname, ccallparanode.Create(
+ left, nil));
+ left := nil;
+ firstpass(Result);
+ exit;
+ end
+ else
+ { other integers are supposed to be 32 bit }
+ begin
+ if is_signed(left.resultdef) then
+ inserttypeconv(left, s32inttype)
+ else
+ inserttypeconv(left, u32inttype);
+ firstpass(left);
+ end;
+ Result := nil;
+ expectloc := LOC_FPUREGISTER;
+end;
+
+
+{*****************************************************************************
+ SecondTypeConv
+*****************************************************************************}
+
+procedure tMIPSELtypeconvnode.second_int_to_real;
+
+ procedure loadsigned;
+ begin
+ location_force_mem(current_asmdata.CurrAsmList, left.location);
+ location.Register := cg.getfpuregister(current_asmdata.CurrAsmList, location.size);
+ { Load memory in fpu register }
+ cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList, OS_F32, OS_F32, left.location.reference, location.Register);
+ tg.ungetiftemp(current_asmdata.CurrAsmList, left.location.reference);
+ { Convert value in fpu register from integer to float }
+ case tfloatdef(resultdef).floattype of
+ s32real:
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CVT_S_W, location.Register, location.Register));
+ s64real:
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CVT_D_W, location.Register, location.Register));
+ else
+ internalerror(200408011);
+ end;
+ end;
+
+var
+ href: treference;
+ hregister: tregister;
+ l1, l2: tasmlabel;
+
+begin
+ location_reset(location, LOC_FPUREGISTER, def_cgsize(resultdef));
+ if is_signed(left.resultdef) then
+ loadsigned
+ else
+ begin
+ current_asmdata.getdatalabel(l1);
+ current_asmdata.getjumplabel(l2);
+ reference_reset_symbol(href, l1, 0, sizeof(aint));
+ hregister := cg.getintregister(current_asmdata.CurrAsmList, OS_32);
+ cg.a_load_loc_reg(current_asmdata.CurrAsmList, OS_32, left.location, hregister);
+
+ loadsigned;
+
+ current_asmdata.CurrAsmList.concat(Taicpu.op_reg_reg_sym(A_BGE, hregister, NR_R0, l2));
+
+ case tfloatdef(resultdef).floattype of
+ { converting dword to s64real first and cut off at the end avoids precision loss }
+ s32real,
+ s64real:
+ begin
+ hregister := cg.getfpuregister(current_asmdata.CurrAsmList, OS_F64);
+ new_section(current_asmdata.asmlists[al_typedconsts],sec_rodata_norel,l1.name,const_align(8));
+ current_asmdata.asmlists[al_typedconsts].concat(Tai_label.Create(l1));
+
+ { I got this constant from a test program (FK) }
+ current_asmdata.asmlists[al_typedconsts].concat(Tai_const.Create_32bit(0));
+ current_asmdata.asmlists[al_typedconsts].concat(Tai_const.Create_32bit($0000f041));
+
+ cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList, OS_F64, OS_F64, href, hregister);
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_ADD_D, location.Register, hregister, location.Register));
+ cg.a_label(current_asmdata.CurrAsmList, l2);
+
+ { cut off if we should convert to single }
+ if tfloatdef(resultdef).floattype = s32real then
+ begin
+ hregister := location.Register;
+ location.Register := cg.getfpuregister(current_asmdata.CurrAsmList, location.size);
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CVT_S_D, location.Register, hregister));
+ end;
+ end;
+ else
+ internalerror(200410031);
+ end;
+ end;
+end;
+
+
+procedure tMIPSELtypeconvnode.second_real_to_real;
+const
+ conv_op: array[tfloattype, tfloattype] of tasmop = (
+ { from: s32 s64 s80 sc80 c64 cur f128 }
+ { s32 } (A_MOV_S, A_CVT_S_D, A_NONE, A_NONE, A_NONE, A_NONE, A_NONE),
+ { s64 } (A_CVT_D_S, A_MOV_D, A_NONE, A_NONE, A_NONE, A_NONE, A_NONE),
+ { s80 } (A_NONE, A_NONE, A_NONE, A_NONE, A_NONE, A_NONE, A_NONE),
+ { sc80 } (A_NONE, A_NONE, A_NONE, A_NONE, A_NONE, A_NONE, A_NONE),
+ { c64 } (A_NONE, A_NONE, A_NONE, A_NONE, A_NONE, A_NONE, A_NONE),
+ { cur } (A_NONE, A_NONE, A_NONE, A_NONE, A_NONE, A_NONE, A_NONE),
+ { f128 } (A_NONE, A_NONE, A_NONE, A_NONE, A_NONE, A_NONE, A_NONE)
+ );
+var
+ op: tasmop;
+begin
+ location_reset(location, LOC_FPUREGISTER, def_cgsize(resultdef));
+ location_force_fpureg(current_asmdata.CurrAsmList, left.location, False);
+ { Convert value in fpu register from integer to float }
+ op := conv_op[tfloatdef(resultdef).floattype, tfloatdef(left.resultdef).floattype];
+ if op = A_NONE then
+ internalerror(200401121);
+ location.Register := cg.getfpuregister(current_asmdata.CurrAsmList, location.size);
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op, location.Register, left.location.Register));
+end;
+
+
+procedure tMIPSELtypeconvnode.second_int_to_bool;
+var
+ hreg1, hreg2: tregister;
+ opsize: tcgsize;
+ hlabel, oldtruelabel, oldfalselabel: tasmlabel;
+begin
+ oldtruelabel := current_procinfo.CurrTrueLabel;
+ oldfalselabel := current_procinfo.CurrFalseLabel;
+ current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
+ current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel);
+ secondpass(left);
+ if codegenerror then
+ exit;
+
+ { byte(boolean) or word(wordbool) or longint(longbool) must }
+ { be accepted for var parameters }
+ if (nf_explicit in flags) and
+ (left.resultdef.size = resultdef.size) and
+ (left.location.loc in [LOC_REFERENCE, LOC_CREFERENCE, LOC_CREGISTER]) then
+ begin
+ location_copy(location, left.location);
+ current_procinfo.CurrTrueLabel := oldtruelabel;
+ current_procinfo.CurrFalseLabel := oldfalselabel;
+ exit;
+ end;
+ location_reset(location, LOC_REGISTER, def_cgsize(resultdef));
+ opsize := def_cgsize(left.resultdef);
+ case left.location.loc of
+ LOC_CREFERENCE, LOC_REFERENCE, LOC_REGISTER, LOC_CREGISTER:
+ begin
+ if left.location.loc in [LOC_CREFERENCE, LOC_REFERENCE] then
+ begin
+ hreg2 := cg.getintregister(current_asmdata.CurrAsmList, opsize);
+ cg.a_load_ref_reg(current_asmdata.CurrAsmList, opsize, opsize, left.location.reference, hreg2);
+ end
+ else
+ hreg2 := left.location.Register;
+{$ifndef cpu64bit}
+ if left.location.size in [OS_64, OS_S64] then
+ begin
+ hreg1 := cg.getintregister(current_asmdata.CurrAsmList, OS_32);
+ cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList, OP_OR, OS_32, hreg2, tregister(succ(longint(hreg2))), hreg1);
+ hreg2 := hreg1;
+ opsize := OS_32;
+ end;
+{$endif cpu64bit}
+ hreg1 := cg.getintregister(current_asmdata.CurrAsmList, opsize);
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SNE, hreg1, hreg2, NR_R0));
+ end;
+ LOC_JUMP:
+ begin
+ hreg1 := cg.getintregister(current_asmdata.CurrAsmList, OS_INT);
+ current_asmdata.getjumplabel(hlabel);
+ cg.a_label(current_asmdata.CurrAsmList, current_procinfo.CurrTrueLabel);
+ cg.a_load_const_reg(current_asmdata.CurrAsmList, OS_INT, 1, hreg1);
+ cg.a_jmp_always(current_asmdata.CurrAsmList, hlabel);
+ cg.a_label(current_asmdata.CurrAsmList, current_procinfo.CurrFalseLabel);
+ cg.a_load_const_reg(current_asmdata.CurrAsmList, OS_INT, 0, hreg1);
+ cg.a_label(current_asmdata.CurrAsmList, hlabel);
+ end;
+ else
+ internalerror(10062);
+ end;
+ location.Register := hreg1;
+
+ if location.size in [OS_64, OS_S64] then
+ internalerror(200408241);
+
+ current_procinfo.CurrTrueLabel := oldtruelabel;
+ current_procinfo.CurrFalseLabel := oldfalselabel;
+end;
+
+
+begin
+ ctypeconvnode := tMIPSELtypeconvnode;
+end.
diff --git a/closures/compiler/mips/ncpuinln.pas b/closures/compiler/mips/ncpuinln.pas
new file mode 100644
index 0000000000..5470e9492e
--- /dev/null
+++ b/closures/compiler/mips/ncpuinln.pas
@@ -0,0 +1,138 @@
+{
+ Copyright (c) 1998-2009 by Florian Klaempfl and David Zhang
+
+ Generate MIPSEL inline nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit ncpuinln;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ node, ninl, ncginl;
+
+type
+ tMIPSELinlinenode = class(tcgInlineNode)
+ function first_abs_real: tnode; override;
+ function first_sqr_real: tnode; override;
+ function first_sqrt_real: tnode; override;
+ procedure second_abs_real; override;
+ procedure second_sqr_real; override;
+ procedure second_sqrt_real; override;
+ private
+ procedure load_fpu_location;
+ end;
+
+
+implementation
+
+uses
+ systems,
+ globtype,
+ cutils, verbose,
+ symconst, symdef,
+ aasmtai, aasmcpu, aasmdata,
+ cgbase, pass_2,
+ cpubase, paramgr,
+ nbas, ncon, ncal, ncnv, nld,
+ ncgutil, cgobj, cgutils;
+
+{*****************************************************************************
+ tMIPSELinlinenode
+*****************************************************************************}
+
+procedure tMIPSELinlinenode.load_fpu_location;
+begin
+ secondpass(left);
+ location_force_fpureg(current_asmdata.CurrAsmList, left.location, True);
+ location_copy(location, left.location);
+ if left.location.loc = LOC_CFPUREGISTER then
+ begin
+ location.Register := cg.getfpuregister(current_asmdata.CurrAsmList, location.size);
+ location.loc := LOC_FPUREGISTER;
+ end;
+end;
+
+
+function tMIPSELinlinenode.first_abs_real: tnode;
+begin
+ expectloc := LOC_FPUREGISTER;
+ first_abs_real := nil;
+end;
+
+
+function tMIPSELinlinenode.first_sqr_real: tnode;
+begin
+ expectloc := LOC_FPUREGISTER;
+ first_sqr_real := nil;
+end;
+
+
+function tMIPSELinlinenode.first_sqrt_real: tnode;
+begin
+ expectloc := LOC_FPUREGISTER;
+ first_sqrt_real := nil;
+end;
+
+
+procedure tMIPSELinlinenode.second_abs_real;
+begin
+ load_fpu_location;
+ case tfloatdef(left.resultdef).floattype of
+ s32real:
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_ABS_s, location.Register, left.location.Register));
+ s64real:
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_ABS_d, location.Register, left.location.Register));
+ else
+ internalerror(200410031);
+ end;
+end;
+
+
+procedure tMIPSELinlinenode.second_sqr_real;
+begin
+ load_fpu_location;
+ case tfloatdef(left.resultdef).floattype of
+ s32real:
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_MUL_s, location.Register, left.location.Register, left.location.Register));
+ s64real:
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_MUL_d, location.Register, left.location.Register, left.location.Register));
+ else
+ internalerror(200410032);
+ end;
+end;
+
+
+procedure tMIPSELinlinenode.second_sqrt_real;
+begin
+ load_fpu_location;
+ case tfloatdef(left.resultdef).floattype of
+ s32real:
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_SQRT_s, location.Register, left.location.Register));
+ s64real:
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_SQRT_d, location.Register, left.location.Register));
+ else
+ internalerror(200410033);
+ end;
+end;
+
+begin
+ cInlineNode := tMIPSELinlinenode;
+end.
diff --git a/closures/compiler/mips/ncpumat.pas b/closures/compiler/mips/ncpumat.pas
new file mode 100644
index 0000000000..43d09598e8
--- /dev/null
+++ b/closures/compiler/mips/ncpumat.pas
@@ -0,0 +1,302 @@
+{
+David Zhang 2007/01/15
+ $Id: ncpumat.pas,v 1.23 2005/02/14 17:13:10 peter Exp $
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate MIPSel assembler for math nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit ncpumat;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ node, nmat, ncgmat;
+
+type
+ tMIPSELmoddivnode = class(tmoddivnode)
+ procedure pass_generate_code;override;
+ end;
+
+ tMIPSELshlshrnode = class(tshlshrnode)
+ procedure pass_generate_code;override;
+ { everything will be handled in pass_2 }
+ function first_shlshr64bitint: tnode; override;
+ end;
+
+ tMIPSELnotnode = class(tcgnotnode)
+ procedure second_boolean; override;
+ end;
+
+implementation
+
+uses
+ globtype, systems,
+ cutils, verbose, globals,
+ symconst,
+ aasmbase, aasmcpu, aasmtai, aasmdata,
+ defutil,
+ procinfo,
+ cgbase, cgobj, pass_2,
+ ncon,
+ cpubase,
+ ncgutil, cgcpu, cgutils;
+
+{*****************************************************************************
+ TMipselMODDIVNODE
+*****************************************************************************}
+
+procedure tMIPSELmoddivnode.pass_generate_code;
+var
+ power: longint;
+ tmpreg, numerator, divider, resultreg: tregister;
+begin
+ secondpass(left);
+ secondpass(right);
+ location_copy(location, left.location);
+
+ { put numerator in register }
+ location_force_reg(current_asmdata.CurrAsmList, left.location, def_cgsize(left.resultdef), True);
+ location_copy(location, left.location);
+ numerator := location.Register;
+
+ if (nodetype = modn) then
+ resultreg := cg.GetIntRegister(current_asmdata.CurrAsmList, OS_INT)
+ else
+ begin
+ if (location.loc = LOC_CREGISTER) then
+ begin
+ location.loc := LOC_REGISTER;
+ location.Register := cg.GetIntRegister(current_asmdata.CurrAsmList, OS_INT);
+ end;
+ resultreg := location.Register;
+ end;
+
+ if (nodetype = divn) and
+ (right.nodetype = ordconstn) and
+ ispowerof2(tordconstnode(right).Value.svalue, power) then
+ begin
+ tmpreg := cg.GetIntRegister(current_asmdata.CurrAsmList, OS_INT);
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_SAR, OS_INT, 31, numerator, tmpreg);
+ { if signed, tmpreg=right value-1, otherwise 0 }
+ cg.a_op_const_reg(current_asmdata.CurrAsmList, OP_AND, OS_INT, tordconstnode(right).Value.svalue - 1, tmpreg);
+ { add to the left value }
+ cg.a_op_reg_reg(current_asmdata.CurrAsmList, OP_ADD, OS_INT, tmpreg, numerator);
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_SAR, OS_INT, aword(power), numerator, resultreg);
+ end
+ else
+ begin
+ { load divider in a register if necessary }
+ location_force_reg(current_asmdata.CurrAsmList, right.location,
+ def_cgsize(right.resultdef), True);
+ divider := right.location.Register;
+
+
+ if (nodetype = modn) then
+ begin
+ if is_signed(right.resultdef) then
+ begin
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_REM, resultreg, numerator, divider));
+ end
+ else
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_REMU, resultreg, numerator, divider));
+ end
+ else
+ begin
+ if is_signed({left.resultdef}right.resultdef) then
+ begin
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_DIV, resultreg, numerator, divider));
+ end
+ else
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_DIVU, resultreg, numerator, divider));
+ end;
+ end;
+ { set result location }
+ location.loc := LOC_REGISTER;
+ location.Register := resultreg;
+end;
+
+
+{*****************************************************************************
+ TMIPSelSHLRSHRNODE
+*****************************************************************************}
+
+function TMIPSELShlShrNode.first_shlshr64bitint: TNode;
+begin
+ { 64bit without constants need a helper }
+ if is_64bit(left.resultdef) and
+ (right.nodetype <> ordconstn) then
+ begin
+ Result := inherited first_shlshr64bitint;
+ exit;
+ end;
+
+ Result := nil;
+end;
+
+
+procedure tMIPSELshlshrnode.pass_generate_code;
+var
+ hregister, resultreg, hregister1, hreg64hi, hreg64lo: tregister;
+ op: topcg;
+ shiftval: aword;
+begin
+ { 64bit without constants need a helper, and is
+ already replaced in pass1 }
+ if is_64bit(left.resultdef) and
+ (right.nodetype <> ordconstn) then
+ internalerror(200405301);
+
+ secondpass(left);
+ secondpass(right);
+ if is_64bit(left.resultdef) then
+ begin
+ location_reset(location, LOC_REGISTER, OS_64);
+
+ { load left operator in a register }
+ location_force_reg(current_asmdata.CurrAsmList, left.location, OS_64, False);
+
+
+ hreg64hi := left.location.register64.reghi;
+ hreg64lo := left.location.register64.reglo;
+
+ shiftval := tordconstnode(right).Value.svalue and 63;
+ if shiftval > 31 then
+ begin
+ if nodetype = shln then
+ begin
+ cg.a_load_const_reg(current_asmdata.CurrAsmList, OS_32, 0, hreg64hi);
+ if (shiftval and 31) <> 0 then
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_SHL, OS_32, shiftval and 31, hreg64lo, hreg64lo);
+ end
+ else
+ begin
+ cg.a_load_const_reg(current_asmdata.CurrAsmList, OS_32, 0, hreg64lo);
+ if (shiftval and 31) <> 0 then
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_SHR, OS_32, shiftval and 31, hreg64hi, hreg64hi);
+ end;
+ location.register64.reglo := hreg64hi;
+ location.register64.reghi := hreg64lo;
+ end
+ else
+ begin
+ hregister := cg.getintregister(current_asmdata.CurrAsmList, OS_32);
+ if nodetype = shln then
+ begin
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_SHR, OS_32, 32 - shiftval, hreg64lo, hregister);
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_SHL, OS_32, shiftval, hreg64hi, hreg64hi);
+ cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList, OP_OR, OS_32, hregister, hreg64hi, hreg64hi);
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_SHL, OS_32, shiftval, hreg64lo, hreg64lo);
+ end
+ else
+ begin
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_SHL, OS_32, 32 - shiftval, hreg64hi, hregister);
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_SHR, OS_32, shiftval, hreg64lo, hreg64lo);
+ cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList, OP_OR, OS_32, hregister, hreg64lo, hreg64lo);
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_SHR, OS_32, shiftval, hreg64hi, hreg64hi);
+ end;
+ location.register64.reghi := hreg64hi;
+ location.register64.reglo := hreg64lo;
+ end;
+ end
+ else
+ begin
+ { load left operators in a register }
+ location_force_reg(current_asmdata.CurrAsmList, left.location, def_cgsize(left.resultdef), True);
+ location_copy(location, left.location);
+ resultreg := location.Register;
+ hregister1 := location.Register;
+ if (location.loc = LOC_CREGISTER) then
+ begin
+ location.loc := LOC_REGISTER;
+ resultreg := cg.GetIntRegister(current_asmdata.CurrAsmList, OS_INT);
+ location.Register := resultreg;
+ end;
+ { determine operator }
+ if nodetype = shln then
+ op := OP_SHL
+ else
+ op := OP_SHR;
+ { shifting by a constant directly coded: }
+ if (right.nodetype = ordconstn) then
+ begin
+ if tordconstnode(right).Value.svalue and 31 <> 0 then
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, op, OS_32, tordconstnode(right).Value.svalue and 31, hregister1, resultreg);
+ end
+ else
+ begin
+ { load shift count in a register if necessary }
+ location_force_reg(current_asmdata.CurrAsmList, right.location, def_cgsize(right.resultdef), True);
+ cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList, op, OS_32, right.location.Register, hregister1, resultreg);
+ end;
+ end;
+end;
+
+
+{*****************************************************************************
+ TMIPSelNOTNODE
+*****************************************************************************}
+
+procedure tMIPSELnotnode.second_boolean;
+var
+ hl: tasmlabel;
+begin
+ { if the location is LOC_JUMP, we do the secondpass after the
+ labels are allocated
+ }
+ if left.expectloc = LOC_JUMP then
+ begin
+ hl := current_procinfo.CurrTrueLabel;
+ current_procinfo.CurrTrueLabel := current_procinfo.CurrFalseLabel;
+ current_procinfo.CurrFalseLabel := hl;
+ secondpass(left);
+ maketojumpbool(current_asmdata.CurrAsmList, left, lr_load_regvars);
+ hl := current_procinfo.CurrTrueLabel;
+ current_procinfo.CurrTrueLabel := current_procinfo.CurrFalseLabel;
+ current_procinfo.CurrFalseLabel := hl;
+ location.loc := LOC_JUMP;
+ end
+ else
+ begin
+ secondpass(left);
+ case left.location.loc of
+ LOC_FLAGS:
+ begin
+ internalerror(2007011501);
+ end;
+ LOC_REGISTER, LOC_CREGISTER, LOC_REFERENCE, LOC_CREFERENCE:
+ begin
+ location_force_reg(current_asmdata.CurrAsmList, left.location, def_cgsize(left.resultdef), True);
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SEQ, NR_TCR0, left.location.Register, NR_R0));
+ location_reset(location, LOC_REGISTER, OS_INT);
+ location.Register := NR_TCR0;
+ end;
+ else
+ internalerror(2003042401);
+ end;
+ end;
+end;
+
+
+begin
+ cmoddivnode := tMIPSELmoddivnode;
+ cshlshrnode := tMIPSELshlshrnode;
+ cnotnode := tMIPSELnotnode;
+end.
diff --git a/closures/compiler/mips/ncpuset.pas b/closures/compiler/mips/ncpuset.pas
new file mode 100644
index 0000000000..ec311d1e05
--- /dev/null
+++ b/closures/compiler/mips/ncpuset.pas
@@ -0,0 +1,130 @@
+{
+ Copyright (c) 1998-2004 by Florian Klaempfl and David Zhang
+
+ Generate MIPSEL assembler for in set/case nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit ncpuset;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ globtype,
+ nset,
+ ncgset;
+
+type
+ tcpucasenode = class(tcgcasenode)
+ protected
+ procedure optimizevalues(var max_linear_list: aint; var max_dist: aword); override;
+ function has_jumptable: boolean; override;
+ procedure genjumptable(hp: pcaselabel; min_, max_: aint); override;
+ end;
+
+
+implementation
+
+uses
+ globals,
+ systems,
+ constexp,
+ cpubase,
+ aasmbase, aasmtai, aasmcpu, aasmdata,
+ cgbase, cgutils, cgobj,
+ procinfo;
+
+procedure tcpucasenode.optimizevalues(var max_linear_list: aint; var max_dist: aword);
+begin
+ { give the jump table a higher priority }
+ max_dist := (max_dist * 3) div 2;
+end;
+
+
+function tcpucasenode.has_jumptable: boolean;
+begin
+ has_jumptable := True;
+end;
+
+
+procedure tcpucasenode.genjumptable(hp: pcaselabel; min_, max_: aint);
+var
+ table: tasmlabel;
+ last: TConstExprInt;
+ indexreg, jmpreg, basereg: tregister;
+ href: treference;
+ jumpsegment: TAsmlist;
+
+ procedure genitem(t: pcaselabel);
+ var
+ i: aint;
+ begin
+ if assigned(t^.less) then
+ genitem(t^.less);
+ { fill possible hole }
+ for i := last.svalue+1 to t^._low.svalue-1 do
+ jumpSegment.concat(Tai_const.Create_sym(elselabel));
+ for i := t^._low.svalue to t^._high.svalue do
+ jumpSegment.concat(Tai_const.Create_sym(blocklabel(t^.blockid)));
+ last := t^._high;
+ if assigned(t^.greater) then
+ genitem(t^.greater);
+ end;
+
+begin
+ jumpsegment := current_procinfo.aktlocaldata;
+ if not (jumptable_no_range) then
+ begin
+ { case expr less than min_ => goto elselabel }
+ cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList, opsize, jmp_lt, aint(min_), hregister, elselabel);
+ { case expr greater than max_ => goto elselabel }
+ cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList, opsize, jmp_gt, aint(max_), hregister, elselabel);
+ end;
+ current_asmdata.getjumplabel(table);
+ indexreg := cg.getaddressregister(current_asmdata.CurrAsmList);
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_SHL, OS_ADDR, 2, hregister, indexreg);
+ { create reference }
+ reference_reset_symbol(href, table, 0, sizeof(aint));
+ href.offset := (-aint(min_)) * 4;
+ basereg := cg.getaddressregister(current_asmdata.CurrAsmList);
+ cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList, href, basereg);
+
+ jmpreg := cg.getaddressregister(current_asmdata.CurrAsmList);
+
+ reference_reset(href, sizeof(aint));
+ href.index := indexreg;
+ href.base := basereg;
+ cg.a_load_ref_reg(current_asmdata.CurrAsmList, OS_ADDR, OS_ADDR, href, jmpreg);
+
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg(A_JR, jmpreg));
+ { Delay slot }
+ current_asmdata.CurrAsmList.concat(taicpu.op_none(A_NOP));
+ { generate jump table }
+ if not(cs_opt_size in current_settings.optimizerswitches) then
+ jumpSegment.concat(Tai_Align.Create_Op(4, 0));
+ jumpSegment.concat(Tai_label.Create(table));
+ last := min_;
+ genitem(hp);
+end;
+
+
+
+begin
+ ccasenode := tcpucasenode;
+end.
diff --git a/closures/compiler/mips/opcode.inc b/closures/compiler/mips/opcode.inc
new file mode 100644
index 0000000000..f58fd3aa32
--- /dev/null
+++ b/closures/compiler/mips/opcode.inc
@@ -0,0 +1,241 @@
+A_NONE,
+A_P_STK2,
+A_P_LW,
+A_P_SET_NOREORDER,
+A_P_SET_NOMACRO,
+A_P_SET_MACRO,
+A_P_SET_REORDER,
+A_P_FRAME,
+A_P_MASK,
+A_P_FMASK,
+A_P_SW,
+A_SPARC8UNIMP,
+A_NOP,
+A_NOT,
+A_NEG,
+A_NEGU,
+A_B,
+A_LI,
+A_DLI,
+A_LA,
+A_MOVE,
+A_LB,
+A_LBU,
+A_LH,
+A_LHU,
+A_LW,
+A_LWU,
+A_LWL,
+A_LWR,
+A_LD,
+A_LDL,
+A_LDR,
+A_LL,
+A_LLD,
+A_SB,
+A_SH,
+A_SW,
+A_SWL,
+A_SWR,
+A_SD,
+A_SDL,
+A_SDR,
+A_SC,
+A_SCD,
+A_SYNC,
+A_ADDI,
+A_DADDI,
+A_ADDIU,
+A_DADDIU,
+A_SLTI,
+A_SLTIU,
+A_ANDI,
+A_ORI,
+A_XORI,
+A_LUI,
+A_DNEG,
+A_DNEGU,
+A_ADD,
+A_DADD,
+A_ADDU,
+A_DADDU,
+A_SUB,
+A_DSUB,
+A_SUBU,
+A_DSUBU,
+A_SLT,
+A_SLTU,
+A_AND,
+A_OR,
+A_XOR,
+A_NOR,
+A_MUL,
+A_MULO,
+A_MULOU,
+A_DMUL,
+A_DMULO,
+A_DMULOU,
+A_DIV,
+A_DIVU,
+A_DDIV,
+A_DDIVU,
+A_REM,
+A_REMU,
+A_DREM,
+A_DREMU,
+A_MULT,
+A_DMULT,
+A_MULTU,
+A_DMULTU,
+A_MFHI,
+A_MTHI,
+A_MFLO,
+A_MTLO,
+A_MULTG,
+A_DMULTG,
+A_MULTUG,
+A_DMULTUG,
+A_DIVG,
+A_DDIVG,
+A_DIVUG,
+A_DDIVUG,
+A_MODG,
+A_DMODG,
+A_MODUG,
+A_DMODUG,
+A_J,
+A_JAL,
+A_JR,
+A_JALR,
+A_BEQ,
+A_BNE,
+A_BLEZ,
+A_BGTZ,
+A_BLTZ,
+A_BGEZ,
+A_BLTZAL,
+A_BGEZAL,
+A_BEQL,
+A_BNEL,
+A_BLEZL,
+A_BGTZL,
+A_BLTZL,
+A_BGEZL,
+A_BLTZALL,
+A_BGEZALL,
+A_SLL,
+A_SRL,
+A_SRA,
+A_SLLV,
+A_SRLV,
+A_SRAV,
+A_DSLL,
+A_DSRL,
+A_DSRA,
+A_DSLLV,
+A_DSRLV,
+A_DSRAV,
+A_DSLL32,
+A_DSRL32,
+A_DSRA32,
+A_LWC1,
+A_SWC1,
+A_LDC1,
+A_SDC1,
+A_MTC1,
+A_MFC1,
+A_DMTC1,
+A_DMFC1,
+A_CTC1,
+A_CFC1,
+A_ADD_S,
+A_ADD_D,
+A_SUB_S,
+A_SUB_D,
+A_MUL_S,
+A_MUL_D,
+A_DIV_S,
+A_DIV_D,
+A_ABS_S,
+A_ABS_D,
+A_NEG_S,
+A_NEG_D,
+A_SQRT_S,
+A_SQRT_D,
+A_MOV_S,
+A_MOV_D,
+A_CVT_S_D,
+A_CVT_S_W,
+A_CVT_S_L,
+A_CVT_D_S,
+A_CVT_D_W,
+A_CVT_D_L,
+A_CVT_W_S,
+A_CVT_W_D,
+A_CVT_L_S,
+A_CVT_L_D,
+A_ROUND_W_S,
+A_ROUND_W_D,
+A_ROUND_L_S,
+A_ROUND_L_D,
+A_TRUNC_W_S,
+A_TRUNC_W_D,
+A_TRUNC_L_S,
+A_TRUNC_L_D,
+A_CEIL_W_S,
+A_CEIL_W_D,
+A_CEIL_L_S,
+A_CEIL_L_D,
+A_FLOOR_W_S,
+A_FLOOR_W_D,
+A_FLOOR_L_S,
+A_FLOOR_L_D,
+A_BC1T,
+A_BC1F,
+A_BC1TL,
+A_BC1FL,
+A_C_EQ_D,
+A_C_EQ_S,
+A_C_LE_D,
+A_C_LE_S,
+A_C_LT_D,
+A_C_LT_S,
+A_BEQI,
+A_BNEI,
+A_BLTI,
+A_BLEI,
+A_BGTI,
+A_BGEI,
+A_BLTUI,
+A_BLEUI,
+A_BGTUI,
+A_BGEUI,
+A_BLT,
+A_BLE,
+A_BGT,
+A_BGE,
+A_BLTU,
+A_BLEU,
+A_BGTU,
+A_BGEU,
+A_SEQ,
+A_SGE,
+A_SGEU,
+A_SGT,
+A_SGTU,
+A_SLE,
+A_SLEU,
+A_SNE,
+A_SYSCALL,
+A_ADD64SUB,
+A_SUB64SUB,
+A_MUL64SUB,
+A_DIV64SUB,
+A_NEG64SUB,
+A_NOT64SUB,
+A_OR64SUB,
+A_SAR64SUB,
+A_SHL64SUB,
+A_SHR64SUB,
+A_XOR64SUB,
+A_END_DEF
diff --git a/closures/compiler/mips/rgcpu.pas b/closures/compiler/mips/rgcpu.pas
new file mode 100644
index 0000000000..280946debe
--- /dev/null
+++ b/closures/compiler/mips/rgcpu.pas
@@ -0,0 +1,165 @@
+{
+ Copyright (c) 1998-2009 by Florian Klaempfl and David Zhang
+
+ This unit implements the register allocator for MIPLEL
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+
+unit rgcpu;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ aasmbase,aasmcpu,aasmtai,aasmdata,
+ cgbase,cgutils,
+ cpubase,
+ rgobj;
+
+ type
+ trgcpu=class(trgobj)
+ procedure add_constraints(reg:tregister);override;
+ function get_spill_subreg(r : tregister) : tsubregister;override;
+ procedure do_spill_read(list:tasmlist;pos:tai;const spilltemp:treference;tempreg:tregister);override;
+ procedure do_spill_written(list:tasmlist;pos:tai;const spilltemp:treference;tempreg:tregister);override;
+ end;
+
+
+implementation
+
+ uses
+ globtype,
+ verbose,cutils,
+ cgobj;
+
+ procedure trgcpu.add_constraints(reg:tregister);
+ var
+ supreg,i : Tsuperregister;
+ begin
+ case getsubreg(reg) of
+ { Let 64bit floats conflict with all odd float regs }
+ R_SUBFD:
+ begin
+ supreg:=getsupreg(reg);
+ i:=RS_F1;
+ while (i<=RS_F31) do
+ begin
+ add_edge(supreg,i);
+ inc(i,2);
+ end;
+ end;
+ { Let 64bit ints conflict with all odd int regs }
+ R_SUBQ:
+ begin
+ supreg:=getsupreg(reg);
+ i:=RS_R1;
+ while (i<=RS_R31) do
+ begin
+ add_edge(supreg,i);
+ inc(i,2);
+ end;
+ end;
+ end;
+ end;
+
+
+ function trgcpu.get_spill_subreg(r : tregister) : tsubregister;
+ begin
+ if getregtype(r)=R_FPUREGISTER then
+ result:=getsubreg(r)
+ else
+ result:=defaultsub;
+ end;
+
+
+ procedure trgcpu.do_spill_read(list:tasmlist;pos:tai;const spilltemp:treference;tempreg:tregister);
+ var
+ helpins : tai;
+ tmpref : treference;
+ helplist : tasmlist;
+ hreg : tregister;
+ begin
+ if abs(spilltemp.offset)>4095 then
+ begin
+ helplist:=tasmlist.create;
+
+ if getregtype(tempreg)=R_INTREGISTER then
+ hreg:=tempreg
+ else
+ hreg:=cg.getintregister(helplist,OS_ADDR);
+
+ reference_reset(tmpref,sizeof(aint));
+ tmpref.offset:=spilltemp.offset;
+ tmpref.refaddr:=addr_high;
+ helplist.concat(taicpu.op_reg_ref(A_LUI,hreg,tmpref));
+
+ tmpref.refaddr:=addr_low;
+ helplist.concat(taicpu.op_reg_reg_ref(A_ADDIU,hreg,hreg,tmpref));
+ helplist.concat(taicpu.op_reg_reg_reg(A_ADDU,hreg,hreg,spilltemp.base));
+
+ reference_reset_base(tmpref,hreg,0,sizeof(aint));
+
+ helpins:=spilling_create_load(tmpref,tempreg);
+ helplist.concat(helpins);
+ list.insertlistafter(pos,helplist)
+ end
+ else
+ inherited do_spill_read(list,pos,spilltemp,tempreg);
+ end;
+
+
+ procedure trgcpu.do_spill_written(list:tasmlist;pos:tai;const spilltemp:treference;tempreg:tregister);
+ var
+ helpins : tai;
+ tmpref : treference;
+ helplist : tasmlist;
+ hreg : tregister;
+ begin
+ if abs(spilltemp.offset)>4095 then
+ begin
+ helplist:=tasmlist.create;
+
+ if getregtype(tempreg)=R_INTREGISTER then
+ hreg:=getregisterinline(helplist,[R_SUBWHOLE])
+ else
+ hreg:=cg.getintregister(helplist,OS_ADDR);
+
+ reference_reset(tmpref,sizeof(aint));
+ tmpref.offset:=spilltemp.offset;
+ tmpref.refaddr:=addr_high;
+ helplist.concat(taicpu.op_reg_ref(A_LUI,hreg,tmpref));
+
+ tmpref.refaddr:=addr_low;
+ helplist.concat(taicpu.op_reg_reg_ref(A_ADDIU,hreg,hreg,tmpref));
+ helplist.concat(taicpu.op_reg_reg_reg(A_ADDU,hreg,hreg,spilltemp.base));
+
+ reference_reset_base(tmpref,hreg,0,sizeof(aint));
+
+ helpins:=spilling_create_store(tempreg,tmpref);
+ helplist.concat(helpins);
+ if getregtype(tempreg)=R_INTREGISTER then
+ ungetregisterinline(helplist,hreg);
+
+ list.insertlistafter(pos,helplist)
+ end
+ else
+ inherited do_spill_written(list,pos,spilltemp,tempreg);
+ end;
+
+end.
diff --git a/closures/compiler/mips/rmipscon.inc b/closures/compiler/mips/rmipscon.inc
new file mode 100644
index 0000000000..e4dedd516e
--- /dev/null
+++ b/closures/compiler/mips/rmipscon.inc
@@ -0,0 +1,75 @@
+{ don't edit, this file is generated from mipsreg.dat }
+NR_NO = tregister($00000000);
+NR_R0 = tregister($01000000);
+NR_R1 = tregister($01000001);
+NR_R2 = tregister($01000002);
+NR_R3 = tregister($01000003);
+NR_R4 = tregister($01000004);
+NR_R5 = tregister($01000005);
+NR_R6 = tregister($01000006);
+NR_R7 = tregister($01000007);
+NR_R8 = tregister($01000008);
+NR_R9 = tregister($01000009);
+NR_R10 = tregister($0100000a);
+NR_R11 = tregister($0100000b);
+NR_R12 = tregister($0100000c);
+NR_R13 = tregister($0100000d);
+NR_R14 = tregister($0100000e);
+NR_R15 = tregister($0100000f);
+NR_R16 = tregister($01000010);
+NR_R17 = tregister($01000011);
+NR_R18 = tregister($01000012);
+NR_R19 = tregister($01000013);
+NR_R20 = tregister($01000014);
+NR_R21 = tregister($01000015);
+NR_R22 = tregister($01000016);
+NR_R23 = tregister($01000017);
+NR_R24 = tregister($01000018);
+NR_R25 = tregister($01000019);
+NR_R26 = tregister($0100001a);
+NR_R27 = tregister($0100001b);
+NR_R28 = tregister($0100001c);
+NR_R29 = tregister($0100001d);
+NR_R30 = tregister($0100001e);
+NR_R31 = tregister($0100001f);
+NR_F0 = tregister($02000000);
+NR_F1 = tregister($02000001);
+NR_F2 = tregister($02000002);
+NR_F3 = tregister($02000003);
+NR_F4 = tregister($02000004);
+NR_F5 = tregister($02000005);
+NR_F6 = tregister($02000006);
+NR_F7 = tregister($02000007);
+NR_F8 = tregister($02000008);
+NR_F9 = tregister($02000009);
+NR_F10 = tregister($0200000a);
+NR_F11 = tregister($0200000b);
+NR_F12 = tregister($0200000c);
+NR_F13 = tregister($0200000d);
+NR_F14 = tregister($0200000e);
+NR_F15 = tregister($0200000f);
+NR_F16 = tregister($02000010);
+NR_F17 = tregister($02000011);
+NR_F18 = tregister($02000012);
+NR_F19 = tregister($02000013);
+NR_F20 = tregister($02000014);
+NR_F21 = tregister($02000015);
+NR_F22 = tregister($02000016);
+NR_F23 = tregister($02000017);
+NR_F24 = tregister($02000018);
+NR_F25 = tregister($02000019);
+NR_F26 = tregister($0200001a);
+NR_F27 = tregister($0200001b);
+NR_F28 = tregister($0200001c);
+NR_F29 = tregister($0200001d);
+NR_F30 = tregister($0200001e);
+NR_F31 = tregister($0200001f);
+NR_PC = tregister($05000000);
+NR_HI = tregister($05000001);
+NR_LO = tregister($05000002);
+NR_CR = tregister($05000003);
+NR_FCR0 = tregister($05000004);
+NR_FCR25 = tregister($05000005);
+NR_FCR26 = tregister($05000006);
+NR_FCR28 = tregister($05000007);
+NR_FCSR = tregister($05000008);
diff --git a/closures/compiler/mips/rmipsdwf.inc b/closures/compiler/mips/rmipsdwf.inc
new file mode 100644
index 0000000000..35598a2ffe
--- /dev/null
+++ b/closures/compiler/mips/rmipsdwf.inc
@@ -0,0 +1,75 @@
+{ don't edit, this file is generated from mipsreg.dat }
+-1,
+0,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+8,
+9,
+10,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+20,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+31,
+32,
+33,
+34,
+35,
+36,
+37,
+38,
+39,
+40,
+41,
+42,
+43,
+44,
+45,
+46,
+47,
+48,
+49,
+50,
+51,
+52,
+53,
+54,
+55,
+56,
+57,
+58,
+59,
+60,
+61,
+62,
+63,
+-1,
+68,
+69,
+70,
+71,
+72,
+73,
+74,
+75
diff --git a/closures/compiler/mips/rmipsgas.inc b/closures/compiler/mips/rmipsgas.inc
new file mode 100644
index 0000000000..b81050d8c8
--- /dev/null
+++ b/closures/compiler/mips/rmipsgas.inc
@@ -0,0 +1,75 @@
+{ don't edit, this file is generated from mipsreg.dat }
+'INVALID',
+'r0',
+'r1',
+'r2',
+'r3',
+'r4',
+'r5',
+'r6',
+'r7',
+'r8',
+'r9',
+'r10',
+'r11',
+'r12',
+'r13',
+'r14',
+'r15',
+'r16',
+'r17',
+'r18',
+'r19',
+'r20',
+'r21',
+'r22',
+'r23',
+'r24',
+'r25',
+'r26',
+'r27',
+'r28',
+'r29',
+'r30',
+'r31',
+'f0',
+'f1',
+'f2',
+'f3',
+'f4',
+'f5',
+'f6',
+'f7',
+'f8',
+'f9',
+'f10',
+'f11',
+'f12',
+'f13',
+'f14',
+'f15',
+'f16',
+'f17',
+'f18',
+'f19',
+'f20',
+'f21',
+'f22',
+'f23',
+'f24',
+'f25',
+'f26',
+'f27',
+'f28',
+'f29',
+'f30',
+'f31',
+'pc',
+'hi',
+'lo',
+'cr',
+'fcr0',
+'fcr25',
+'fcr26',
+'fcr28',
+'fcsr'
diff --git a/closures/compiler/mips/rmipsgri.inc b/closures/compiler/mips/rmipsgri.inc
new file mode 100644
index 0000000000..a52df4ffa7
--- /dev/null
+++ b/closures/compiler/mips/rmipsgri.inc
@@ -0,0 +1,75 @@
+{ don't edit, this file is generated from mipsreg.dat }
+0,
+68,
+33,
+34,
+43,
+44,
+45,
+46,
+47,
+48,
+49,
+50,
+51,
+52,
+35,
+53,
+54,
+55,
+56,
+57,
+58,
+59,
+60,
+61,
+62,
+36,
+63,
+64,
+37,
+38,
+39,
+40,
+41,
+42,
+69,
+70,
+71,
+72,
+73,
+66,
+67,
+65,
+1,
+2,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+20,
+3,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+4,
+31,
+32,
+5,
+6,
+7,
+8,
+9,
+10
diff --git a/closures/compiler/mips/rmipsgss.inc b/closures/compiler/mips/rmipsgss.inc
new file mode 100644
index 0000000000..c618ae3c54
--- /dev/null
+++ b/closures/compiler/mips/rmipsgss.inc
@@ -0,0 +1,75 @@
+{ don't edit, this file is generated from mipsreg.dat }
+'INVALID',
+'0',
+'1',
+'2',
+'3',
+'4',
+'5',
+'6',
+'7',
+'8',
+'9',
+'10',
+'11',
+'12',
+'13',
+'14',
+'15',
+'16',
+'17',
+'18',
+'19',
+'20',
+'21',
+'22',
+'23',
+'24',
+'25',
+'26',
+'27',
+'28',
+'29',
+'30',
+'31',
+'0',
+'1',
+'2',
+'3',
+'4',
+'5',
+'6',
+'7',
+'8',
+'9',
+'10',
+'11',
+'12',
+'13',
+'14',
+'15',
+'16',
+'17',
+'18',
+'19',
+'20',
+'21',
+'22',
+'23',
+'24',
+'25',
+'26',
+'27',
+'28',
+'29',
+'30',
+'31',
+'pc',
+'hi',
+'lo',
+'cr',
+'fcr0',
+'fcr25',
+'fcr26',
+'fcr28',
+'fcsr'
diff --git a/closures/compiler/mips/rmipsnor.inc b/closures/compiler/mips/rmipsnor.inc
new file mode 100644
index 0000000000..a03cbf0309
--- /dev/null
+++ b/closures/compiler/mips/rmipsnor.inc
@@ -0,0 +1,2 @@
+{ don't edit, this file is generated from mipsreg.dat }
+74
diff --git a/closures/compiler/mips/rmipsnum.inc b/closures/compiler/mips/rmipsnum.inc
new file mode 100644
index 0000000000..ebd3e23c45
--- /dev/null
+++ b/closures/compiler/mips/rmipsnum.inc
@@ -0,0 +1,75 @@
+{ don't edit, this file is generated from mipsreg.dat }
+tregister($00000000),
+tregister($01000000),
+tregister($01000001),
+tregister($01000002),
+tregister($01000003),
+tregister($01000004),
+tregister($01000005),
+tregister($01000006),
+tregister($01000007),
+tregister($01000008),
+tregister($01000009),
+tregister($0100000a),
+tregister($0100000b),
+tregister($0100000c),
+tregister($0100000d),
+tregister($0100000e),
+tregister($0100000f),
+tregister($01000010),
+tregister($01000011),
+tregister($01000012),
+tregister($01000013),
+tregister($01000014),
+tregister($01000015),
+tregister($01000016),
+tregister($01000017),
+tregister($01000018),
+tregister($01000019),
+tregister($0100001a),
+tregister($0100001b),
+tregister($0100001c),
+tregister($0100001d),
+tregister($0100001e),
+tregister($0100001f),
+tregister($02000000),
+tregister($02000001),
+tregister($02000002),
+tregister($02000003),
+tregister($02000004),
+tregister($02000005),
+tregister($02000006),
+tregister($02000007),
+tregister($02000008),
+tregister($02000009),
+tregister($0200000a),
+tregister($0200000b),
+tregister($0200000c),
+tregister($0200000d),
+tregister($0200000e),
+tregister($0200000f),
+tregister($02000010),
+tregister($02000011),
+tregister($02000012),
+tregister($02000013),
+tregister($02000014),
+tregister($02000015),
+tregister($02000016),
+tregister($02000017),
+tregister($02000018),
+tregister($02000019),
+tregister($0200001a),
+tregister($0200001b),
+tregister($0200001c),
+tregister($0200001d),
+tregister($0200001e),
+tregister($0200001f),
+tregister($05000000),
+tregister($05000001),
+tregister($05000002),
+tregister($05000003),
+tregister($05000004),
+tregister($05000005),
+tregister($05000006),
+tregister($05000007),
+tregister($05000008)
diff --git a/closures/compiler/mips/rmipsrni.inc b/closures/compiler/mips/rmipsrni.inc
new file mode 100644
index 0000000000..18ce2cb19e
--- /dev/null
+++ b/closures/compiler/mips/rmipsrni.inc
@@ -0,0 +1,75 @@
+{ don't edit, this file is generated from mipsreg.dat }
+0,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+8,
+9,
+10,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+20,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+31,
+32,
+33,
+34,
+35,
+36,
+37,
+38,
+39,
+40,
+41,
+42,
+43,
+44,
+45,
+46,
+47,
+48,
+49,
+50,
+51,
+52,
+53,
+54,
+55,
+56,
+57,
+58,
+59,
+60,
+61,
+62,
+63,
+64,
+65,
+66,
+67,
+68,
+69,
+70,
+71,
+72,
+73
diff --git a/closures/compiler/mips/rmipssri.inc b/closures/compiler/mips/rmipssri.inc
new file mode 100644
index 0000000000..5af5c3069c
--- /dev/null
+++ b/closures/compiler/mips/rmipssri.inc
@@ -0,0 +1,75 @@
+{ don't edit, this file is generated from mipsreg.dat }
+68,
+33,
+34,
+43,
+44,
+45,
+46,
+47,
+48,
+49,
+50,
+51,
+52,
+35,
+53,
+54,
+55,
+56,
+57,
+58,
+59,
+60,
+61,
+62,
+36,
+63,
+64,
+37,
+38,
+39,
+40,
+41,
+42,
+69,
+70,
+71,
+72,
+73,
+66,
+0,
+67,
+65,
+1,
+2,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+20,
+3,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+4,
+31,
+32,
+5,
+6,
+7,
+8,
+9,
+10
diff --git a/closures/compiler/mips/rmipssta.inc b/closures/compiler/mips/rmipssta.inc
new file mode 100644
index 0000000000..35598a2ffe
--- /dev/null
+++ b/closures/compiler/mips/rmipssta.inc
@@ -0,0 +1,75 @@
+{ don't edit, this file is generated from mipsreg.dat }
+-1,
+0,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+8,
+9,
+10,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+20,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+31,
+32,
+33,
+34,
+35,
+36,
+37,
+38,
+39,
+40,
+41,
+42,
+43,
+44,
+45,
+46,
+47,
+48,
+49,
+50,
+51,
+52,
+53,
+54,
+55,
+56,
+57,
+58,
+59,
+60,
+61,
+62,
+63,
+-1,
+68,
+69,
+70,
+71,
+72,
+73,
+74,
+75
diff --git a/closures/compiler/mips/rmipsstd.inc b/closures/compiler/mips/rmipsstd.inc
new file mode 100644
index 0000000000..7f44888e61
--- /dev/null
+++ b/closures/compiler/mips/rmipsstd.inc
@@ -0,0 +1,75 @@
+{ don't edit, this file is generated from mipsreg.dat }
+'INVALID',
+'r0',
+'r1',
+'r2',
+'r3',
+'r4',
+'r5',
+'r6',
+'r7',
+'r8',
+'r9',
+'r10',
+'r11',
+'r12',
+'r13',
+'r14',
+'r15',
+'r16',
+'r17',
+'r18',
+'r19',
+'r20',
+'r21',
+'r22',
+'r23',
+'r24',
+'r25',
+'r26',
+'r27',
+'r28',
+'r29',
+'r30',
+'r31',
+'F0',
+'F1',
+'F2',
+'F3',
+'F4',
+'F5',
+'F6',
+'F7',
+'F8',
+'F9',
+'F10',
+'F11',
+'F12',
+'F13',
+'F14',
+'F15',
+'F16',
+'F17',
+'F18',
+'F19',
+'F20',
+'F21',
+'F22',
+'F23',
+'F24',
+'F25',
+'F26',
+'F27',
+'F28',
+'F29',
+'F30',
+'F31',
+'PC',
+'HI',
+'LO',
+'CR',
+'FCR0',
+'FCR25',
+'FCR26',
+'FCR28',
+'FCSR'
diff --git a/closures/compiler/mips/rmipssup.inc b/closures/compiler/mips/rmipssup.inc
new file mode 100644
index 0000000000..9999435836
--- /dev/null
+++ b/closures/compiler/mips/rmipssup.inc
@@ -0,0 +1,75 @@
+{ don't edit, this file is generated from mipsreg.dat }
+RS_NO = $00;
+RS_R0 = $00;
+RS_R1 = $01;
+RS_R2 = $02;
+RS_R3 = $03;
+RS_R4 = $04;
+RS_R5 = $05;
+RS_R6 = $06;
+RS_R7 = $07;
+RS_R8 = $08;
+RS_R9 = $09;
+RS_R10 = $0a;
+RS_R11 = $0b;
+RS_R12 = $0c;
+RS_R13 = $0d;
+RS_R14 = $0e;
+RS_R15 = $0f;
+RS_R16 = $10;
+RS_R17 = $11;
+RS_R18 = $12;
+RS_R19 = $13;
+RS_R20 = $14;
+RS_R21 = $15;
+RS_R22 = $16;
+RS_R23 = $17;
+RS_R24 = $18;
+RS_R25 = $19;
+RS_R26 = $1a;
+RS_R27 = $1b;
+RS_R28 = $1c;
+RS_R29 = $1d;
+RS_R30 = $1e;
+RS_R31 = $1f;
+RS_F0 = $00;
+RS_F1 = $01;
+RS_F2 = $02;
+RS_F3 = $03;
+RS_F4 = $04;
+RS_F5 = $05;
+RS_F6 = $06;
+RS_F7 = $07;
+RS_F8 = $08;
+RS_F9 = $09;
+RS_F10 = $0a;
+RS_F11 = $0b;
+RS_F12 = $0c;
+RS_F13 = $0d;
+RS_F14 = $0e;
+RS_F15 = $0f;
+RS_F16 = $10;
+RS_F17 = $11;
+RS_F18 = $12;
+RS_F19 = $13;
+RS_F20 = $14;
+RS_F21 = $15;
+RS_F22 = $16;
+RS_F23 = $17;
+RS_F24 = $18;
+RS_F25 = $19;
+RS_F26 = $1a;
+RS_F27 = $1b;
+RS_F28 = $1c;
+RS_F29 = $1d;
+RS_F30 = $1e;
+RS_F31 = $1f;
+RS_PC = $00;
+RS_HI = $01;
+RS_LO = $02;
+RS_CR = $03;
+RS_FCR0 = $04;
+RS_FCR25 = $05;
+RS_FCR26 = $06;
+RS_FCR28 = $07;
+RS_FCSR = $08;
diff --git a/closures/compiler/mips/strinst.inc b/closures/compiler/mips/strinst.inc
new file mode 100644
index 0000000000..10d6214ec0
--- /dev/null
+++ b/closures/compiler/mips/strinst.inc
@@ -0,0 +1,241 @@
+'none',
+'p_stk2',
+'p_lw',
+'p_set_noreorder',
+'p_set_nomacro',
+'p_set_macro',
+'p_set_reorder',
+'p_frame',
+'p_mask',
+'p_fmask',
+'p_sw',
+'sparc8unimp',
+'nop',
+'not',
+'neg',
+'negu',
+'b',
+'li',
+'dli',
+'la',
+'move',
+'lb',
+'lbu',
+'lh',
+'lhu',
+'lw',
+'lwu',
+'lwl',
+'lwr',
+'ld',
+'ldl',
+'ldr',
+'ll',
+'lld',
+'sb',
+'sh',
+'sw',
+'swl',
+'swr',
+'sd',
+'sdl',
+'sdr',
+'sc',
+'scd',
+'sync',
+'addi',
+'daddi',
+'addiu',
+'daddiu',
+'slti',
+'sltiu',
+'andi',
+'ori',
+'xori',
+'lui',
+'dneg',
+'dnegu',
+'add',
+'dadd',
+'addu',
+'daddu',
+'sub',
+'dsub',
+'subu',
+'dsubu',
+'slt',
+'sltu',
+'and',
+'or',
+'xor',
+'nor',
+'mul',
+'mulo',
+'mulou',
+'dmul',
+'dmulo',
+'dmulou',
+'div',
+'divu',
+'ddiv',
+'ddivu',
+'rem',
+'remu',
+'drem',
+'dremu',
+'mult',
+'dmult',
+'multu',
+'dmultu',
+'mfhi',
+'mthi',
+'mflo',
+'mtlo',
+'multg',
+'dmultg',
+'multug',
+'dmultug',
+'divg',
+'ddivg',
+'divug',
+'ddivug',
+'modg',
+'dmodg',
+'modug',
+'dmodug',
+'j',
+'jal',
+'jr',
+'jalr',
+'beq',
+'bne',
+'blez',
+'bgtz',
+'bltz',
+'bgez',
+'bltzal',
+'bgezal',
+'beql',
+'bnel',
+'blezl',
+'bgtzl',
+'bltzl',
+'bgezl',
+'bltzall',
+'bgezall',
+'sll',
+'srl',
+'sra',
+'sllv',
+'srlv',
+'srav',
+'dsll',
+'dsrl',
+'dsra',
+'dsllv',
+'dsrlv',
+'dsrav',
+'dsll32',
+'dsrl32',
+'dsra32',
+'lwc1',
+'swc1',
+'ldc1',
+'sdc1',
+'mtc1',
+'mfc1',
+'dmtc1',
+'dmfc1',
+'ctc1',
+'cfc1',
+'add.s',
+'add.d',
+'sub.s',
+'sub.d',
+'mul.s',
+'mul.d',
+'div.s',
+'div.d',
+'abs.s',
+'abs.d',
+'neg.s',
+'neg.d',
+'sqrt.s',
+'sqrt.d',
+'mov.s',
+'mov.d',
+'cvt.s.d',
+'cvt.s.w',
+'cvt.s.l',
+'cvt.d.s',
+'cvt.d.w',
+'cvt.d.l',
+'cvt.w.s',
+'cvt.w.d',
+'cvt.l.s',
+'cvt.l.d',
+'round.w.s',
+'round.w.d',
+'round.l.s',
+'round.l.d',
+'trunc.w.s',
+'trunc.w.d',
+'trunc.l.s',
+'trunc.l.d',
+'ceil.w.s',
+'ceil.w.d',
+'ceil.l.s',
+'ceil.l.d',
+'floor.w.s',
+'floor.w.d',
+'floor.l.s',
+'floor.l.d',
+'bc1t',
+'bc1f',
+'bc1tl',
+'bc1fl',
+'c.eq.d',
+'c.eq.s',
+'c.le.d',
+'c.le.s',
+'c.lt.d',
+'c.lt.s',
+'beqi',
+'bnei',
+'blti',
+'blei',
+'bgti',
+'bgei',
+'bltui',
+'bleui',
+'bgtui',
+'bgeui',
+'blt',
+'ble',
+'bgt',
+'bge',
+'bltu',
+'bleu',
+'bgtu',
+'bgeu',
+'seq',
+'sge',
+'sgeu',
+'sgt',
+'sgtu',
+'sle',
+'sleu',
+'sne',
+'syscall',
+'add64sub',
+'sub64sub',
+'mul64sub',
+'div64sub',
+'neg64sub',
+'not64sub',
+'or64sub',
+'sar64sub',
+'shl64sub',
+'shr64sub',
+'xor64sub',
+'end_def'
diff --git a/closures/compiler/msg/errorct.msg b/closures/compiler/msg/errorct.msg
new file mode 100644
index 0000000000..458e5b54b9
--- /dev/null
+++ b/closures/compiler/msg/errorct.msg
@@ -0,0 +1,2357 @@
+#
+# This file is part of the Free Pascal Compiler
+# Copyright (c) 1993-2008 by the Free Pascal Development team
+#
+# Catalan Language File for Free Pascal
+#
+# See the file COPYING.FPC, included in this distribution,
+# for details about the copyright.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#
+#
+# The constants are build in the following order:
+# <part>_<type>_<txtidentifier>
+#
+# <part> is the part of the compiler the message is used
+# asmr_ assembler parsing
+# asmw_ assembler writing/binary writers
+# unit_ unit handling
+# scan_ scanner
+# parser_ parser
+# type_ type checking
+# general_ general info
+# exec_ calls to assembler, linker, binder
+#
+# <type> the type of the message it should normally used for
+# f_ fatal error
+# e_ error
+# w_ warning
+# n_ note
+# h_ hint
+# i_ info
+# l_ add linenumber
+# u_ used
+# t_ tried
+# c_ conditional
+# d_ debug message
+# x_ executable informations
+#
+
+#
+# General
+#
+# 01017 is the last one used
+#
+# BeginOfTeX
+% \section{General compiler messages}
+% This section gives the compiler messages which are not fatal, but which
+% display useful information. The number of such messages can be
+% controlled with the various verbosity level \var{-v} switches.
+% \begin{description}
+general_t_compilername=01000_T_Compilador: $1
+% When the \var{-vt} switch is used, this line tells you what compiler
+% is used.
+general_d_sourceos=01001_D_SO d'origen: $1
+% When the \var{-vd} switch is used, this line tells you what the source
+% operating system is.
+general_i_targetos=01002_I_SO objectiu: $1
+% When the \var{-vd} switch is used, this line tells you what the target
+% operating system is.
+general_t_exepath=01003_T_S'està utilitzant el camí pels executables: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for its binaries.
+general_t_unitpath=01004_T_S'està utilitzant el camí de les unitats: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for compiled units. You can set this path with the \var{-Fu}
+general_t_includepath=01005_T_S'està utilitzant el camí dels inclosos: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for its include files (files used in \var{\{\$I xxx\}} statements).
+% You can set this path with the \var{-I} option.
+general_t_librarypath=01006_T_S'està utilitzant el camí per les biblioteques : $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for the libraries. You can set this path with the \var{-Fl} option.
+general_t_objectpath=01007_T_S'està utilitzant el camí dels objectes: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for object files you link in (files used in \var{\{\$L xxx\}} statements).
+% You can set this path with the \var{-Fo} option.
+general_i_abslines_compiled=01008_I_$1 Línies compilades, $2 seg
+% When the \var{-vi} switch is used, the compiler reports the number
+% of lines compiled, and the time it took to compile them (real time,
+% not program time).
+general_f_no_memory_left=01009_F_No hi ha prou memòria disponible
+% The compiler doesn't have enough memory to compile your program.
+% There are several remedies for this:
+% \begin{itemize}
+% \item If you're using the build option of the compiler, try compiling the
+% different units manually.
+% \item If you're compiling a huge program, split it up in units, and compile
+% these separately.
+% \item If the previous two don't work, recompile the compiler with a bigger
+% heap (you can use the \var{-Ch} option for this, \seeo{Ch})
+% \end{itemize}
+general_i_writingresourcefile=01010_I_S'està escrivint el fitxer de la taula del recurs: $1
+% This message is shown when the compiler writes the Resource String Table
+% file containing all the resource strings for a program.
+general_e_errorwritingresourcefile=01011_E_S'ha produït un error mentre s'escrivia el fitxer de la taula del recurs: $1
+% This message is shown when the compiler encountered an error when writing
+% the Resource String Table file
+general_i_fatal=01012_I_Fatal:
+% Prefix for Fatal Errors
+general_i_error=01013_I_Error:
+% Prefix for Errors
+general_i_warning=01014_I_Avís:
+% Prefix for Warnings
+general_i_note=01015_I_Nota:
+% Prefix for Notes
+general_i_hint=01016_I_Suggeriment:
+% Prefix for Hints
+general_e_path_does_not_exist=01017_E_El camí "$1" no existeix
+% The specified path does not exist
+general_e_compilation_aborted=01018_E_S'ha avortat la compilació
+% \end{description}
+#
+# Scanner
+#
+# 02066 is the last used one
+#
+% \section{Scanner messages.}
+% This section lists the messages that the scanner emits. The scanner takes
+% care of the lexical structure of the pascal file, i.e. it tries to find
+% reserved words, strings, etc. It also takes care of directives and
+% conditional compiling handling.
+% \begin{description}
+scan_f_end_of_file=02000_F_No s'esperava el final del fitxer
+% this typically happens in one of the following cases :
+% \begin{itemize}
+% \item The source file ends before the final \var{end.} statement.
+% This happens mostly when the \var{begin} and \var{end} statements aren't
+% balanced;
+% \item An include file ends in the middle of a statement.
+% \item A comment was not closed.
+% \end{itemize}
+scan_f_string_exceeds_line=02001_F_La cadena excedeix la línia
+% There is a missing closing 'in a string, so it occupies
+% multiple lines.
+scan_f_illegal_char=02002_F_Caràcter il·legal "$1" ($2)
+% An illegal character was encountered in the input file.
+scan_f_syn_expected=02003_F_S'ha trobat un error de sintaxi, s'esperava "$1" però s'ha trobat "$2"
+% This indicates that the compiler expected a different token than
+% the one you typed. It can occur almost everywhere where you make a
+% mistake against the pascal language.
+scan_t_start_include_file=02004_TL_S'està començant a llegir el fitxer inclòs $1
+% When you provide the \var{-vt} switch, the compiler tells you
+% when it starts reading an included file.
+scan_w_comment_level=02005_W_S'ha trobat nivell de comentari $1
+% When the \var{-vw} switch is used, then the compiler warns you if
+% it finds nested comments. Nested comments are not allowed in Turbo Pascal
+% and can be a possible source of errors.
+scan_n_ignored_switch=02008_N_S'ignora el commutador del compilador "$1"
+% With \var{-vn} on, the compiler warns if it ignores a switch
+scan_w_illegal_switch=02009_W_El commutador del compilador $1 no és vàlid
+% You included a compiler switch (i.e. \var{\{\$... \}}) which the compiler
+% does not recognise.
+scan_w_switch_is_global=02010_W_Falta el commutador d'efecte global
+% The compiler switch is misplaced, and should be located at
+% the start of the unit or program
+scan_e_illegal_char_const=02011_E_Constant de caràcter il·legal
+% This happens when you specify a character with its ASCII code, as in
+% \var{\#96}, but the number is either illegal, or out of range.
+scan_f_cannot_open_input=02012_F_No es pot obrir el fitxer "$1"
+% \fpc cannot find the program or unit source file you specified on the
+% command line.
+scan_f_cannot_open_includefile=02013_F_No es pot obrir el fitxer inclòs "$1"
+% \fpc cannot find the source file you specified in a \var{\{\$include..\}}
+% statement.
+scan_w_only_pack_records=02015_W_Els camps dels Registres només es poden alinear a 1,2,4 o 16 octets
+% You are specifying the \var{\{\$PACKRECORDS n\} } with an illegal value for
+% \var{n}. Only 1,2,4 or 16 are valid in this case.
+scan_w_only_pack_enum=02016_W_Els enumerats només es poden desar en 1,2 o 4 octets
+% You are specifying the \var{\{\$PACKENUM n\}} with an illegal value for
+% \var{n}. Only 1,2 or 4 are valid in this case.
+scan_e_endif_expected=02017_E_S'esperava $ENDIF per $1, s'ha definit $2 en $3 a la línia $4
+% Your conditional compilation statements are unbalanced.
+scan_e_preproc_syntax_error=02018_E_S'ha trobat un error de sintaxi mentre es processava una expressió de compilació condicional
+% There is an error in the expression following the \var{\{\$if ..\}}, $ifc or $setcd
+% compiler directives.
+scan_e_error_in_preproc_expr=02019_E_S'ha produït un error mentre s'avaluava una expressió de compilació condicional
+% There is an error in the expression following the \var{\{\$if ..\}}, $ifc or $setc
+% compiler directives.
+scan_w_macro_cut_after_255_chars=02020_W_Els continguts de la macro estan limitats a una longitud de 255 caràcters
+% The contents of macros cannot be longer than 255 characters.
+scan_e_endif_without_if=02021_E_ENDIF sense IF(N)DEF
+% Your \var{\{\$IFDEF ..\}} and {\{\$ENDIF\}} statements aren't balanced.
+scan_f_user_defined=02022_F_L'usuari ha definit: $1
+% A user defined fatal error occurred. see also the \progref
+scan_e_user_defined=02023_E_L'usuari ha definit: $1
+% A user defined error occurred. see also the \progref
+scan_w_user_defined=02024_W_L'usuari ha definit: $1
+% A user defined warning occurred. see also the \progref
+scan_n_user_defined=02025_N_L'usuari ha definit: $1
+% A user defined note was encountered. see also the \progref
+scan_h_user_defined=02026_H_L'usuari ha definit: $1
+% A user defined hint was encountered. see also the \progref
+scan_i_user_defined=02027_I_L'usuari ha definit: $1
+% User defined information was encountered. see also the \progref
+scan_e_keyword_cant_be_a_macro=02028_E_La paraula clau redefinida com a macro no té efecte
+% You cannot redefine keywords with macros.
+scan_f_macro_buffer_overflow=02029_F_Una macroinstrucció ha desbordat la memòria intermèdia mentre es llegia o s'expandia
+% Your macro or its result was too long for the compiler.
+scan_w_macro_too_deep=02030_W_L'expansió de les macroinstruccions excedeix una profunditat de 16.
+% When expanding a macro, macros have been nested to a level of 16.
+% The compiler will expand no further, since this may be a sign that
+% recursion is used.
+scan_w_wrong_styled_switch=02031_W_No es permeten els commutadors del compilador en comentaris de l'estil //
+% Compiler switches should be in normal pascal style comments
+scan_d_handling_switch=02032_DL_Manejant el commutador "$1"
+% When you set debugging info on (\var{-vd}) the compiler tells you when it
+% is evaluating conditional compile statements.
+scan_c_endif_found=02033_CL_S'ha trobat ENDIF $1
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifdef_found=02034_CL_S'ha trobat IFDEF $1, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifopt_found=02035_CL_S'ha trobat IFOPT $1, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_if_found=02036_CL_S'ha trobat IF $1, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifndef_found=02037_CL_S'ha trobat IFNDEF $1, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_else_found=02038_CL_S'ha trobat ELSE $1, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_skipping_until=02039_CL_S'ha omès fins ...
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements, and whether it is skipping or
+% compiling parts.
+scan_i_press_enter=02040_I_Premeu <retorn> per a continuar
+% When the \var{-vi} switch is used, the compiler stops compilation
+% and waits for the \var{Enter} key to be pressed when it encounters
+% a \var{\{\$STOP\}} directive.
+scan_w_unsupported_switch=02041_W_No es permet l'ús del commutador "$1"
+% When warnings are turned on (\var{-vw}) the compiler warns you about
+% unsupported switches. This means that the switch is used in Delphi or
+% Turbo Pascal, but not in \fpc
+scan_w_illegal_directive=02042_W_La directiva del compilador "$1" no és vàlida
+% When warings are turned on (\var{-vw}) the compiler warns you about
+% unrecognised switches. For a list of recognised switches, \progref
+scan_t_back_in=02043_TL_S'està tornant a $1
+% When you use (\var{-vt}) the compiler tells you when it has finished
+% reading an include file.
+scan_w_unsupported_app_type=02044_W_El tipus de l'aplicació "$1" no és compatible
+% You get this warning, if you specify an unknown application type
+% with the directive \var{\{\$APPTYPE\}}
+scan_w_app_type_not_support=02045_W_APPTYPE no és compatible amb el SO objectiu
+% The \var{\{\$APPTYPE\}} directive is supported by certain operanting
+% systems only.
+scan_w_description_not_support=02046_W_DESCRIPTION no és compatible amb el SO objectiu
+% The \var{\{\$DESCRIPTION\}} directive is not supported on this target OS
+scan_n_version_not_support=02047_N_VERSION no és compatible amb el SO objectiu
+% The \var{\{\$VERSION\}} directive is not supported on this target OS.
+scan_n_only_exe_version=02048_N_VERSION només es pot utilitzar en executables o DLLs
+% The \var{\{\$VERSION\}} directive is only used for executable or DLL sources.
+scan_w_wrong_version_ignored=02049_W_Format erroni de la directiva VERSION "$1"
+% The \var{\{\$VERSION\}} directive format is major_version.minor_version
+% where major_version and minor_version are words.
+scan_e_unsupported_asmmode_specifier=02050_E_L'estil d'assemblador especificat "$1" no és vàlid
+% When you specify an assembler mode with the \var{\{\$ASMMODE xxx\}}
+% the compiler didn't recognize the mode you specified.
+scan_w_no_asm_reader_switch_inside_asm=02051_W_No es permet el commutador de lector d'ASM dins d'una declaració ASM, "$1" serà efectiu a continuació
+% It is not possible to switch from one assembler reader to another
+% inside an assmebler block. The new reader will be used for next
+% assembler statements only.
+scan_e_wrong_switch_toggle=02052_E_El modificador del commutador és erroni, utilitzeu ON/OFF o +/-
+% You need to use ON or OFF or a + or - to toggle the switch
+scan_e_resourcefiles_not_supported=02053_E_No es permet l'ús dels fitxers del recurs en aquest destí
+% The target you are compiling for doesn't support resource files.
+scan_w_include_env_not_found=02054_W_No s'ha trobat la variable d'entorn "$1"
+% The included environment variable can't be found in the environment, it will
+% be replaced by an empty string instead.
+scan_e_invalid_maxfpureg_value=02055_E_El valor pel límit del registre FPU no és vàlid
+% Valid values for this directive are 0..8 and NORMAL/DEFAULT
+scan_w_only_one_resourcefile_supported=02056_W_Aquest destí només permet un fitxer d'origen
+% The target you are compiling for supports only one resource file.
+% The first resource file found is used, the others are discarded.
+scan_w_macro_support_turned_off=02057_W_El suport per a macroinstruccions està aturat
+% A macro declaration has been found, but macro support is currently off,
+% so the declaration will be ignored. To turn macro support on, compile with
+% -Sm on the commandline or add {\$MACRO ON\} in the source
+scan_e_invalid_interface_type=02058_E_S'ha especificat un tipus d'interfície no vàlida. Les interfícies vàlides son : COM, CORBA o DEFAULT.
+% The interface type that was specified is not supported
+scan_w_appid_not_support=02059_W_APPID només funciona amb el PalmOS
+% The \var{\{\$APPID}} directive is only supported for the PalmOS target.
+scan_w_appname_not_support=02060_W_APPNAME només funciona amb el PalmOS
+% The \var{\{\$APPNAME\}} directive is only supported for the PalmOS target
+scan_e_string_exceeds_255_chars=02061_E_Les constants de cadena no poden excedir els 255 caràcters
+% A single string contant can contain at most 255 chars. Try splitting up the
+% string in multiple smaller parts and concatenate them with a + operator.
+scan_f_include_deep_ten=02062_F_Els fitxers inclosos superen els 16 niats
+% When including include files the files have been nested to a level of 16
+% The compiler will expand no further, since this may be a sign that
+% recursion is used
+scan_e_too_many_push=02063_E_S'han trobat massa nivells de PUSH
+% A maximum of 20 levels is allowed. This error occurs only in mode MacPas
+scan_e_too_many_pop=02064_E_S'ha trobat POP sense PUSH anterior
+% This error occurs only in mode MacPas
+scan_e_error_macro_lacks_value=02065_E_La macroinstrucció o variable del temps de compilació "$1" no te cap valor
+% Thus the conditional compile time expression cannot be evaluated.
+scan_e_wrong_switch_toggle_default=02066_E_La posició del commutador és errònia, utilitzeu ON/OFF/DEFAULT o +/-/*
+% You need to use ON or OFF or DEFAULT or a + or - or * to toggle the switch
+scan_e_mode_switch_not_allowed=02067_E_Aquí no es permet el commutador de mode "$1"
+% A mode switch has already been encountered, or, in case of option -Mmacpas,
+% a mode switch occur after UNIT
+scan_e_error_macro_undefined=02068_E_La variable de temps de compilació "$1" no està definida
+% Thus the conditional compile time expression cannot be evaluated.
+% \end{description}
+#
+# Parser
+#
+# 03211 is the last used one
+#
+% \section{Parser messages}
+% This section lists all parser messages. The parser takes care of the
+% semantics of you language, i.e. it determines if your pascal constructs
+% are correct.
+% \begin{description}
+% \section{Parser messages}
+parser_e_syntax_error=03000_E_Analitzador - Error de sintaxi
+% An error against the Turbo Pascal language was encountered. This happens
+% typically when an illegal character is found in the sources file.
+parser_e_dont_nest_interrupt=03004_E_El procediment INTERRUPT no pot estar niat
+% An \VAR{INTERRUPT} procedure must be global.
+parser_w_proc_directive_ignored=03005_W_S'ignora el tipus de procediment "$1"
+% The specified is ignored fy FPC programs
+parser_e_no_overload_for_all_procs=03006_E_No totes les declaracions de "$1" s'han declarat amb OVERLOAD
+% When you want to use overloading using the \var{OVERLOAD} directive, then
+% all declarations need to have \var{OVERLOAD} specified.
+parser_e_export_name_double=03008_E_El nom de la funció exportada "$1" està dupllicat
+% Exported function names inside a specific DLL must all be different
+parser_e_export_ordinal_double=03009_E_L'índex de la funció exportada $1 no pot estar duplicat
+% Exported function names inside a specific DLL must all be different
+parser_e_export_invalid_index=03010_E_L'índex de la funció exportada no és vàlid
+% DLL function index must be in the range \var{1..\$FFFF}
+parser_w_parser_reloc_no_debug=03011_W_L'informació de la depuració de la biblioteca reassignada o executable $1 no funciona, es deshabilita.
+parser_w_parser_win32_debug_needs_WN=03012_W_Per permetre la depuració pel codi de win32, necessiteu deshabilitar la reassignació amb l'opció -WN
+% Stabs info is wrong for relocatable DLL or EXES use -WN
+% if you want to debug win32 executables.
+parser_e_constructorname_must_be_init=03013_E_El nom del constructor ha de ser INIT
+% You are declaring a constructor with a name which is not \var{init}, and the
+% \var{-Ss} switch is in effect. See the \var{-Ss} switch (\seeo{Ss}).
+parser_e_destructorname_must_be_done=03014_E_El nom del destructor ha de ser DONE
+% You are declaring a constructor with a name which is not \var{done}, and the
+% \var{-Ss} switch is in effect. See the \var{-Ss} switch (\seeo{Ss}).
+parser_e_proc_inline_not_supported=03016_E_No es permet l'ús del procediment tipus INLINE
+% You tried to compile a program with C++ style inlining, and forgot to
+% specify the \var{-Si} option (\seeo{Si}). The compiler doesn't support C++
+% styled inlining by default.
+parser_w_constructor_should_be_public=03018_W_El constructor ha de ser públic
+% Constructors must be in the 'public' part of an object (class) declaration.
+parser_w_destructor_should_be_public=03019_W_El destructor ha de ser públic
+% Destructors must be in the 'public' part of an object (class) declaration.
+parser_n_only_one_destructor=03020_N_La classe només ha de tenir un destructor
+% You can declare only one destructor for a class.
+parser_e_no_local_objects=03021_E_No es permeten les definicions de les classes locals
+% Classes must be defined globally. They cannot be defined inside a
+% procedure or function
+parser_f_no_anonym_objects=03022_F_No es permeten les definicions de classe anònimes
+% An invalid object (class) declaration was encountered, i.e. an
+% object or class without methods that isn't derived from another object or
+% class. For example:
+% \begin{verbatim}
+% Type o = object
+% a : longint;
+% end;
+% \end{verbatim}
+% will trigger this error.
+parser_n_object_has_no_vmt=03023_E_L'objecte "$1" no té VMT
+% This is a note indicating that the declared object has no
+% virtual method table
+parser_e_illegal_parameter_list=03024_E_La llista dels paràmetres no és vàlida
+% You are calling a function with parameters that are of a different type than
+% the declared parameters of the function.
+parser_e_wrong_parameter_size=03026_E_S'ha especificat una quantitat errònia de paràmetres
+% There is an error in the parameter list of the function or procedure,
+% the number of parameters is not correct.
+parser_e_overloaded_no_procedure=03027_E_L'identificador sobrecarregat "$1" no és una funció
+% The compiler encountered a symbol with the same name as an overloaded
+% function, but it is not a function it can overload.
+parser_e_overloaded_have_same_parameters=03028_E_Les funcions sobrecarregades tenen la mateixa llista de paràmetres
+% You're declaring overloaded functions, but with the same parameter list.
+% Overloaded function must have at least 1 different parameter in their
+% declaration.
+parser_e_header_dont_match_forward=03029_E_L'encapçalament de la funció no concorda amb la declaració posterior "$1"
+% You declared a function with same parameters but
+% different result type or function specifiers.
+parser_e_header_different_var_names=03030_E_L'encapçalament de la funció "$1" no concorda amb la posterior declaració : el nom de la variable canvia $2 => $3
+% You declared the function in the \var{interface} part, or with the
+% \var{forward} directive, but define it with a different parameter list.
+parser_n_duplicate_enum=03031_N_Els valors en tipus d'enumerats han de ser ascendents
+% \fpc allows enumeration constructions as in C. Given the following
+% declaration two declarations:
+% \begin{verbatim}
+% type a = (A_A,A_B,A_E:=6,A_UAS:=200);
+% type a = (A_A,A_B,A_E:=6,A_UAS:=4);
+% \end{verbatim}
+% The second declaration would produce an error. \var{A\_UAS} needs to have a
+% value higher than \var{A\_E}, i.e. at least 7.
+parser_e_no_with_for_variable_in_other_segments=03033_E_No es pot utilitzar WITH per les variables en un segment diferent
+% With stores a variable locally on the stack,
+% but this is not possible if the variable belongs to another segment.
+parser_e_too_much_lexlevel=03034_E_El niat de les funcions és superior a 31
+% You can nest function definitions only 31 times.
+parser_e_range_check_error=03035_E_S'ha produït un error de comprovació de l'abast mentre s'avaluaven les constants
+% The constants are out of their allowed range.
+parser_w_range_check_error=03036_W_S'ha produït un error de comprovació de l'abast mentre s'avaluaven les constants
+% The constants are out of their allowed range.
+parser_e_double_caselabel=03037_E_L'etiqueta de CASE està duplicada
+% You are specifying the same label 2 times in a \var{case} statement.
+parser_e_case_lower_less_than_upper_bound=03038_E_El límit superior de CASE és menor que el límit inferior
+% The upper bound of a \var{case} label is less than the lower bound and this
+% is useless
+parser_e_type_const_not_possible=03039_E_No es permeten les constants amb tipus de les classes
+% You cannot declare a constant of type class or object.
+parser_e_no_overloaded_procvars=03040_E_No es permeten les funcions variables de les funcions sobrecarregades
+% You are trying to assign an overloaded function to a procedural variable.
+% This is not allowed.
+parser_e_invalid_string_size=03041_E_La longitud d'una cadena ha de ser un valor entre 1 i 255
+% The length of a shortstring in Pascal is limited to 255 characters. You are
+% trying to declare a string with length lower than 1 or greater than 255
+parser_w_use_extended_syntax_for_objects=03042_W_Utilitzeu la sintaxi estesa de DISPOSE i NEW per les instàncies dels objectes
+% If you have a pointer \var{a} to a class type, then the statement
+% \var{new(a)} will not initialize the class (i.e. the constructor isn't
+% called), although space will be allocated. you should issue the
+% \var{new(a,init)} statement. This will allocate space, and call the
+% constructor of the object.
+parser_w_no_new_dispose_on_void_pointers=03043_W_L'utilització de NEW o DISPOSE en punters sense tipus no té sentit
+parser_e_no_new_dispose_on_void_pointers=03044_E_L'utilització de NEW o DISPOSE no és possible amb punters sense tipus
+% You cannot use \var{new(p)} or \var{dispose(p)} if \var{p} is an untyped pointer
+% because no size is associated to an untyped pointer.
+% Accepted for compatibility in \var{tp} and \var{delphi} modes.
+parser_e_class_id_expected=03045_E_S'esperava un identificador de classe
+% This happens when the compiler scans a procedure declaration that contains
+% a dot,
+% i.e., a object or class method, but the type in front of the dot is not
+% a known type.
+parser_e_no_type_not_allowed_here=03046_E_Aquí no es permet l'identificador de tipus
+% You cannot use a type inside an expression.
+parser_e_methode_id_expected=03047_E_S'esperava un identificador del mètode
+% This identifier is not a method.
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., a object or class method, but the procedure name is not a
+% procedure of this type.
+parser_e_header_dont_match_any_member=03048_E_L'encapçalament de la funció no concorda amb cap mètode d'aquesta classe "$1"
+% This identifier is not a method.
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., a object or class method, but the procedure name is not a
+% procedure of this type.
+parser_d_procedure_start=03049_DL_PROCEDURE/FUNCTION $1
+% When using the \var{-vd} switch, the compiler tells you when it starts
+% processing a procedure or function implementation.
+parser_e_error_in_real=03050_E_La constant de punt flotant no és vàlida
+% The compiler expects a floating point expression, and gets something else.
+parser_e_fail_only_in_constructor=03051_E_FAIL només es pot utilitzar en constructors
+% You are using the \var{fail} keyword outside a constructor method.
+parser_e_no_paras_for_destructor=03052_E_Els destructors no poden tenir paràmetres
+% You are declaring a destructor with a parameter list. Destructor methods
+% cannot have parameters.
+parser_e_only_class_methods_via_class_ref=03053_E_Els mètodes de la classe només es poden referir amb referències de classe
+% This error occurs in a situation like the following:
+% \begin{verbatim}
+% Type :
+% Tclass = Class of Tobject;
+%
+% Var C : TClass;
+%
+% begin
+% ...
+% C.free
+% \end{verbatim}
+% \var{Free} is not a class method and hence cannot be called with a class
+% reference.
+parser_e_only_class_methods=03054_E_Només els mètodes de la classe poden ser accedits en mètodes de classe
+% This is related to the previous error. You cannot call a method of an object
+% from a inside a class method. The following code would produce this error:
+% \begin{verbatim}
+% class procedure tobject.x;
+%
+% begin
+% free
+% \end{verbatim}
+% Because free is a normal method of a class it cannot be called from a class
+% method.
+parser_e_case_mismatch=03055_E_Els tipus d'una constant i CASE no concorden
+% One of the labels is not of the same type as the case variable.
+parser_e_illegal_symbol_exported=03056_E_No es pot exportar el símbol d'una biblioteca
+% You can only export procedures and functions when you write a library. You
+% cannot export variables or constants.
+parser_w_should_use_override=03057_W_ "$1" està amagant un mètode heretat
+% A method that is declared \var{virtual} in a parent class, should be
+% overridden in the descendent class with the \var{override} directive. If you
+% don't specify the \var{override} directive, you will hide the parent method;
+% you will not override it.
+parser_e_nothing_to_be_overridden=03058_E_No hi ha un mètode en una classe avantpassada per ser substituït: "$1"
+% You are trying to \var{override} a virtual method of a parent class that does
+% not exist.
+parser_e_no_procedure_to_access_property=03059_E_No s'ha subministrat un membre per accedir a la propietat
+% You specified no \var{read} directive for a property.
+parser_w_stored_not_implemented=03060_W_La directiva Stored encara no està implementada
+% The \var{stored} directive is not yet implemented
+parser_e_ill_property_access_sym=03061_E_El símbol per accedir a la propietat no és vàlid
+% There is an error in the \var{read} or \var{write} directives for an array
+% property. When you declare an array property, you can only access it with
+% procedures and functions. The following code woud cause such an error.
+% \begin{verbatim}
+% tmyobject = class
+% i : integer;
+% property x [i : integer]: integer read I write i;
+% \end{verbatim}
+%
+parser_e_cant_access_protected_member=03062_E_Aquí no es pot accedir a un camp protegit d'un objecte
+% Fields that are declared in a \var{protected} section of an object or class
+% declaration cannot be accessed outside the module wher the object is
+% defined, or outside descendent object methods.
+parser_e_cant_access_private_member=03063_E_Aquí no es pot accedir a un camp privat d'un objecte
+% Fields that are declared in a \var{private} section of an object or class
+% declaration cannot be accessed outside the module where the class is
+% defined.
+parser_e_overridden_methods_not_same_ret=03066_E_Els mètodes sobrecarregats han de retornar el mateix tipus: "$2" està sobrecarregat per "$1", el qual retorna un altre tipus
+% If you declare overridden methods in a class definition, they must
+% have the same return type.
+parser_e_dont_nest_export=03067_E_Les funcions declarades amb EXPORT no poden estar niades
+% You cannot declare a function or procedure within a function or procedure
+% that was declared as an export procedure.
+parser_e_methods_dont_be_export=03068_E_Els mètodes no poden ser EXPORTats
+% You cannot declare a procedure that is a method for an object as
+% \var{export}ed.
+parser_e_call_by_ref_without_typeconv=03069_E_Les trucades per paràmetres variables tenen que concordar exactament: s'ha obtingut "$1", s'esperava "$2"
+% When calling a function declared with \var{var} parameters, the variables in
+% the function call must be of exactly the same type. There is no automatic
+% type conversion.
+parser_e_no_super_class=03070_E_La classe no és un pare de la classe actual
+% When calling inherited methods, you are trying to call a method of a non-related
+% class. You can only call an inherited method of a parent class.
+parser_e_self_not_in_method=03071_E_SELF només és permet en mètodes
+% You are trying to use the \var{self} parameter outside an object's method.
+% Only methods get passed the \var{self} parameters.
+parser_e_generic_methods_only_in_methods=03072_E_Els mètodes només poden estar en altres mètodes cridats directament amb l'identificador del tipus de la classe
+% A construction like \var{sometype.somemethod} is only allowed in a method.
+parser_e_illegal_colon_qualifier=03073_E_Ús no vàlid de ":"
+% You are using the format \var{:} (colon) 2 times on an expression that
+% is not a real expression.
+parser_e_illegal_set_expr=03074_E_S'ha produït un error de comprovació de l'abast en el constructor del conjunt o hi ha element del conjunt duplicat
+% The declaration of a set contains an error. Either one of the elements is
+% outside the range of the set type, either two of the elements are in fact
+% the same.
+parser_e_pointer_to_class_expected=03075_E_S'esperava un punter a un objecte
+% You specified an illegal type in a \var{New} statement.
+% The extended syntax of \var{New} needs an object as a parameter.
+parser_e_expr_have_to_be_constructor_call=03076_E_L'expressió ha de ser una trucada al constructor
+% When using the extended syntax of \var{new}, you must specify the constructor
+% method of the object you are trying to create. The procedure you specified
+% is not a constructor.
+parser_e_expr_have_to_be_destructor_call=03077_E_L'expressió ha de ser una trucada al destructor
+% When using the extended syntax of \var{dispose}, you must specify the
+% destructor method of the object you are trying to dispose of.
+% The procedure you specified is not a destructor.
+parser_e_invalid_record_const=03078_E_L'ordre dels elements del registre no és correcte
+% When declaring a constant record, you specified the fields in the wrong
+% order.
+parser_e_false_with_expr=03079_E_El tipus de l'expressió ha de ser CLASS o RECORD
+% A \var{with} statement needs an argument that is of the type \var{record}
+% or \var{class}. You are using \var{with} on an expression that is not of
+% this type.
+parser_e_void_function=03080_E_Els procediments no poden retornar cap valor
+% In \fpc, you can specify a return value for a function when using
+% the \var{exit} statement. This error occurs when you try to do this with a
+% procedure. Procedures cannot return a value.
+parser_e_only_methods_allowed=03081_E_Els constructors, destructors i class operators han de ser mètodes
+% You're declaring a procedure as destructor, constructor or class operator, when the
+% procedure isn't a class method.
+parser_e_operator_not_overloaded=03082_E_L'operador no està sobrecarregat
+% You're trying to use an overloaded operator when it is not overloaded for
+% this type.
+parser_e_no_such_assignment=03083_E_No es pot sobrecarregar l'assignació per tipus iguals
+% You can not overload assignment for types
+% that the compiler considers as equal.
+parser_e_overload_impossible=03084_E_No es pot sobrecarregar l'operador
+% The combination of operator, arguments and return type are
+% incompatible.
+parser_e_no_reraise_possible=03085_E_Aquí no es pot rellançar una excepció
+% You are trying to raise an exception where it is not allowed. You can only
+% raise exceptions in an \var{except} block.
+parser_e_no_new_or_dispose_for_classes=03086_E_No es permet la sintaxi estesa de NEW o DISPOSE en una classe
+% You cannot generate an instance of a class with the extended syntax of
+% \var{new}. The constructor must be used for that. For the same reason, you
+% cannot call \var{dispose} to de-allocate an instance of a class, the
+% destructor must be used for that.
+parser_e_procedure_overloading_is_off=03088_E_La sobrecàrrega de procediments no està activada
+% When using the \var{-So} switch, procedure overloading is switched off.
+% Turbo Pascal does not support function overloading.
+parser_e_overload_operator_failed=03089_E_No es pot sobrecarregar aquest operador
+% You are trying to overload an operator which cannot be overloaded.
+% The following operators can be overloaded :
+% \begin{verbatim}
+% +, -, *, /, =, >, <, <=, >=, is, as, in, **, :=
+% \end{verbatim}
+parser_e_comparative_operator_return_boolean=03090_E_L'operador comparatiu ha de retornar un valor booleà
+% When overloading the \var{=} operator, the function must return a boolean
+% value.
+parser_e_only_virtual_methods_abstract=03091_E_Només els mètodes virtuals poden ser abstractes
+% You are declaring a method as abstract, when it is not declared to be
+% virtual.
+parser_f_unsupported_feature=03092_F_S'està fent ús d'una característica no permesa!
+% You're trying to force the compiler into doing something it cannot do yet.
+parser_e_mix_of_classes_and_objects=03093_E_No es permet la barreja de diferents tipus d'objectes (class, object, interface, etc)
+% You cannot derive \var{objects}, \var{classes}, \var{cppclasses} and
+% \var{interfaces} interttwined . E,g.
+% a class cannot have an object as parent and vice versa.
+parser_w_unknown_proc_directive_ignored=03094_W_Es desconeix la directiva del procediment "$1", s'ignora.
+parser_e_absolute_only_one_var=03095_E_Absolute només es pot associar a una variable
+% The procedure direcive you specified is unknown.
+% You cannot specify more than one variable before the \var{absolute} directive.
+% Thus, the following construct will provide this error:
+% \begin{verbatim}
+% Var Z : Longint;
+% X,Y : Longint absolute Z;
+% \end{verbatim}
+% \item [ absolute can only be associated a var or const ]
+% The address of a \var{absolute} directive can only point to a variable or a
+% typed constant. Therefore, the following code will produce this error:
+% \begin{verbatim}
+% Procedure X;
+%
+% var p : longint absolute x;
+% \end{verbatim}
+%
+parser_e_absolute_only_to_var_or_const=03096_E_ABSOLUTE només es pot associar a una variable o constant
+% The address of a \var{absolute} directive can only point to a variable or
+% constant. Therefore, the following code will produce this error:
+% \begin{verbatim}
+% Procedure X;
+%
+% var p : longint absolute x;
+% \end{verbatim}
+%
+parser_e_initialized_only_one_var=03097_E_Només es pot inicialitzar una variable
+% You cannot specify more than one variable with a initial value
+% in Delphi mode.
+parser_e_abstract_no_definition=03098_E_Els mètodes abstractes no han de tenir cap definició (en el cos de la funció)
+% Abstract methods can only be declared, you cannot implement them. They
+% should be overridden by a descendant class.
+parser_e_overloaded_must_be_all_global=03099_E_Aquesta funció sobrecarregada no pot ser local (ha de ser EXPORTED)
+% You are defining a overloaded function in the implementation part of a unit,
+% but there is no corresponding declaration in the interface part of the unit.
+parser_w_virtual_without_constructor=03100_W_Els mètodes virtuals s'utilitzen sense un constructor a "$1"
+% If you declare objects or classes that contain virtual methods, you need
+% to have a constructor and destructor to initialize them. The compiler
+% encountered an object or class with virtual methods that doesn't have
+% a constructor/destructor pair.
+parser_c_macro_defined=03101_CL_S'ha definit la macro: $1
+% When \var{-vc} is used, the compiler tells you when it defines macros.
+parser_c_macro_undefined=03102_CL_S'ha indefinit la macro: $1
+% When \var{-vc} is used, the compiler tells you when it undefines macros.
+parser_c_macro_set_to=03103_CL_S'ha ficat la macro $1 a $2
+% When \var{-vc} is used, the compiler tells you what values macros get.
+parser_i_compiling=03104_I_S'està compilant $1
+% When you turn on information messages (\var{-vi}), the compiler tells you
+% what units it is recompiling.
+parser_u_parsing_interface=03105_UL_S'està analitzant l'interfície de l'unitat $1
+% This tells you that the reading of the interface
+% of the current unit starts
+parser_u_parsing_implementation=03106_UL_S'està analitzant l'implementació de $1
+% This tells you that the code reading of the implementation
+% of the current unit, library or program starts
+parser_d_compiling_second_time=03107_DL_S'està compilant $1 per segona vegada
+% When you request debug messages (\var{-vd}) the compiler tells you what
+% units it recompiles for the second time.
+parser_e_no_property_found_to_override=03109_E_No s'ha trobat la propietat a sobreescriure
+% You want to overrride a property of a parent class, when there is, in fact,
+% no such property in the parent class.
+parser_e_only_one_default_property=03110_E_Només es permet una propietat predeterminada.
+% You specified a property as \var{Default}, but the class already has a
+% default property, and a class can have only one default property.
+parser_e_property_need_paras=03111_E_La propietat predeterminada ha de ser un conjunt de propietat
+% Only array properties of classes can be made \var{default} properties.
+parser_e_constructor_cannot_be_not_virtual=03112_E_Els constructors virtuals només son compatibles en models class object
+% You cannot have virtual constructors in objects. You can only have them
+% in classes.
+parser_e_no_default_property_available=03113_E_No hi ha cap propietat predeterminada disponible
+% You are trying to access a default property of a class, but this class (or one of
+% its ancestors) does not have a default property.
+parser_e_cant_have_published=03114_E_La classe no pot tenir una secció PUBLISHED, utilitzeu el commutador {$M+}
+% If you want a \var{published} section in a class definition, you must
+% use the \var{\{\$M+\}} switch, whch turns on generation of type
+% information.
+parser_e_forward_declaration_must_be_resolved=03115_E_La declaració posterior de la classe "$1" s'ha de resoldre aquí per poder utilitzar la classe com anvantpassada
+% To be able to use an object as an ancestor object, it must be defined
+% first. This error occurs in the following situation:
+% \begin{verbatim}
+% Type ParentClas = Class;
+% ChildClass = Class(ParentClass)
+% ...
+% end;
+% \end{verbatim}
+% Where \var{ParentClass} is declared but not defined.
+parser_e_no_local_operator=03116_E_No es permeten els operadors locals
+% You cannot overload locally, i.e. inside procedures or function
+% definitions.
+parser_e_proc_dir_not_allowed_in_interface=03117_E_No es permet la directiva de procediment "$1" en la secció INTERFACE
+% This procedure directive is not allowed in the \var{interface} section of
+% a unit. You can only use it in the \var{implementation} section.
+parser_e_proc_dir_not_allowed_in_implementation=03118_E_No es permet la directiva del procediment "$1" en la secció IMPLEMENTATION
+% This procedure directive is not defined in the \var{implementation} section of
+% a unit. You can only use it in the \var{interface} section.
+parser_e_proc_dir_not_allowed_in_procvar=03119_E_No es permet la directiva del procediment "$1" en la declaració procvar
+% This procedure directive cannot be part of a procedural of function
+% type declaration.
+parser_e_function_already_declared_public_forward=03120_E_La funció "$1" ja està declarada com Public/Forward
+% You will get this error if a function is defined as \var{forward} twice.
+% Or it is once in the \var{interface} section, and once as a \var{forward}
+% declaration in the \var{implmentation} section.
+parser_e_not_external_and_export=03121_E_No es poden utilitzar EXPORT i EXTERNAL conjuntament
+% These two procedure directives are mutually exclusive
+parser_w_not_supported_for_inline=03123_W_Encara no es permet "$1" dins de procediment/funció inserits
+% Inline procedures don't support this declaration.
+parser_w_inlining_disabled=03124_W_S'ha deshabilitat l'inseriment
+% Inlining of procedures is disabled.
+parser_i_writing_browser_log=03125_I_S'està escrivint el registre del navegador $1
+% When information messages are on, the compiler warns you when it
+% writes the browser log (generated with the \var{\{\$Y+ \}} switch).
+parser_h_maybe_deref_caret_missing=03126_H_Pot ser que falti la dereferència del punter
+% The compiler thinks that a pointer may need a dereference.
+parser_f_assembler_reader_not_supported=03127_F_El lector de l'assemblador seleccionat no és compatible
+% The selected assembler reader (with \var{\{\$ASMMODE xxx\}} is not
+% supported. The compiler can be compiled with or without support for a
+% particular assembler reader.
+earser_e_proc_dir_conflict=03128_E_La directiva del procediment "$1" té conflictes amb altres directives
+% You specified a procedure directive that conflicts with other directives.
+% for instance \var{cdecl} and \var{pascal} are mutually exclusive.
+parser_e_call_convention_dont_match_forward=03129_E_La convenció de la crida no concorda amb la posterior
+% This error happens when you declare a function or procedure with
+% e.g. \var{cdecl;} but omit this directive in the implementation, or vice
+% versa. The calling convention is part of the function declaration, and
+% must be repeated in the function definition.
+parser_e_property_cant_have_a_default_value=03131_E_La propietat no pot tenir un valor predeterminat
+% Set properties or indexed properties cannot have a default value.
+parser_e_property_default_value_must_const=03132_E_El valor predeterminat d'una propietat ha de ser constant
+% The value of a \var{default} declared property must be knwon at compile
+% time. The value you specified is only known at run time. This happens
+% .e.g. if you specify a variable name as a default value.
+parser_e_cant_publish_that=03133_E_No es pot publicar el símbol, només pot ser una classe
+% Only class type variables can be in a \var{published} section of a class
+% if they are not declared as a property.
+parser_e_cant_publish_that_property=03134_E_No es pot publicar aquest tipus de propietat
+% Properties in a \var{published} section cannot be array properties.
+% they must be moved to public sections. Properties in a \var{published}
+% section must be an ordinal type, a real type, strings or sets.
+parser_e_empty_import_name=03136_E_Es requereix nom d'importació
+% Some targets need a name for the imported procedure or a \var{cdecl} specifier
+parser_e_division_by_zero=03138_E_S'ha efectuat una divisió per zero
+% There is a divsion by zero encounted
+parser_e_invalid_float_operation=03139_E_L'operació de punt flotant no és vàlida
+% An operation on two real type values produced an overflow or a division
+% by zero.
+parser_e_array_lower_less_than_upper_bound=03140_E_El límit superior de l'abast és menor que el límit inferior
+% The upper bound of a an array declaration is less than the lower bound and this
+% is not possible
+parser_w_string_too_long=03141_W_La cadena "$1" és més llarga que "$2"
+% The size of the constant string is larger than the size you specified in
+% string type definition
+parser_e_string_larger_array=03142_E_La longitud de la cadena és major que el conjunt de caràcters
+% The size of the constant string is larger than the size you specified in
+% the array[x..y] of char definition
+parser_e_ill_msg_expr=03143_E_Hi ha una expressió il·legal després d'una directiva del missatge
+% \fpc supports only integer or string values as message constants
+parser_e_ill_msg_param=03144_E_Els manipuladors de missatges només accepten una crida per paràmetre de referència
+% A method declared with the \var{message}-directive as message handler
+% can take only one parameter which must be declared as call by reference
+% Parameters are declared as call by reference using the \var{var}-directive
+parser_e_duplicate_message_label=03145_E_L'etiqueta del missatge està duplicada: "$1"
+% A label for a message is used twice in one object/class
+parser_e_self_in_non_message_handler=03146_E_SELF només pot ser un paràmetre explícit en mètodes que son manipuladors dels missatges
+% The self parameter can be passed only explicit if it is a method which
+% is declared as message handler
+parser_e_threadvars_only_sg=03147_E_Les variables del fil només poden ser estàtiques o globals
+% Threadvars must be static or global, you can't declare a thread
+% local to a procedure. Local variables are always local to a thread,
+% because every thread has its own stack and local variables
+% are stored on the stack
+parser_f_direct_assembler_not_allowed=03148_F_L'assemblador directe no és compatible amb el format binari de la sortida
+% You can't use direct assembler when using a binary writer, choose an
+% other outputformat or use another assembler reader
+% \end{description}
+parser_w_no_objpas_use_mode=03149_W_No carregueu manualment l'unitat OBJPAS, utilitzeu {\$mode objfpc\} o {\$mode delphi\}
+% You are trying to load the ObjPas unit manual from a uses clause. This is
+% not a good idea. Use the \var{\{\$mode objfpc\}} or
+% \var{\{\$mode delphi\}}
+% directives which load the unit automatically
+parser_e_no_object_override=03150_E_No es pot utilitzar OVERRIDE en objectes
+% Override is not supported for objects, use \var{virtual} instead to override
+% a method of a parent object
+parser_e_cant_use_inittable_here=03151_E_No es poden utilitzar els tipus de dades que requereixen inicialització/finalització en registres variables
+% Some data type (e.g. \var{ansistring}) needs initialization/finalization
+% code which is implicitly generated by the compiler. Such data types
+% can't be used in the variant part of a record.
+parser_e_resourcestring_only_sg=03152_E_Les cadenes del recurs només poden ser estàtiques o globals
+% Resourcestring can not be declared local, only global or using the static
+% directive.
+parser_e_exit_with_argument_not__possible=03153_E_Aquí no es pot utilitzar Exit amb arguments
+% an exit statement with an argument for the return value can't be used here, this
+% can happen e.g. in \var{try..except} or \var{try..finally} blocks
+parser_e_stored_property_must_be_boolean=03154_E_El tipus del símbol ha de ser booleà
+% If you specify a storage symbol in a property declaration, it must be of
+% the type boolean
+parser_e_ill_property_storage_sym=03155_E_No es permet aquest símbol com a símbol per emmagatzemar
+% You can't use this type of symbol as storage specifier in property
+% declaration. You can use only methods with the result type boolean,
+% boolean class fields or boolean constants
+parser_e_only_publishable_classes_can__be_published=03156_E_Només les classes compilades amb el mode $M+ poden ser publicades
+% In the published section of a class can be only class as fields used which
+% are compiled in $M+ or which are derived from such a class. Normally
+% such a class should be derived from TPersitent
+parser_e_proc_directive_expected=03157_E_S'esperava la directiva del procediment
+% When declaring a procedure in a const block you used a ; after the
+% procedure declaration after which a procedure directive must follow.
+% Correct declarations are:
+% \begin{verbatim}
+% const
+% p : procedure;stdcall=nil;
+% p : procedure stdcall=nil;
+% \end{verbatim}
+parser_e_invalid_property_index_value=03158_E_El valor per un índex de la propietat ha de ser d'un tipus ordinal
+% The value you use to index a property must be of an ordinal type, for
+% example an integer or enumerated type.
+parser_e_procname_to_short_for_export=03159_E_El nom del procediment és massa curt per ser exportat
+% The length of the procedure/function name must be at least 2 characters
+% long. This is because of a bug in dlltool which doesn't parse the .def
+% file correct with a name of length 1.
+parser_e_dlltool_unit_var_problem=03160_E_No es pot generar una entrada DEFFILE per les variables globals d'una unitat
+parser_e_dlltool_unit_var_problem2=03161_E_Compileu sense l'opció -WD
+% You need to compile this file without the -WD switch on the
+% commandline
+parser_f_need_objfpc_or_delphi_mode=03162_F_Necessiteu el mode ObjFpc (-S2) o Delphi (-Sd) per compilar aquest mòdul
+% You need to use {\$MODE OBJFPC\} or {\$MODE DELPHI\} to compile this file
+% Or use the equivalent commandline switches -S2 or -Sd
+parser_e_no_export_with_index_for_target=03163_E_No es pot exportar amb índex sota $1
+% Exporting of functions or procedures with a specific index is not
+% supported on this target.
+parser_e_no_export_of_variables_for_target=03164_E_No es poden exportar variables sota $1
+% Exporting of variables is not supported on this target.
+parser_e_improper_guid_syntax=03165_E_La sintaxi de GUID no és apropiada
+parser_w_interface_mapping_notfound=03168_W_El procediment anomenat "$1" no sembla apropiat per implementar $2.$3
+parser_e_interface_id_expected=03169_E_S'esperava identificador d'interfície
+% This happens when the compiler scans a \var{class} declaration that contains
+% \var{interface} function name mapping code like this:
+% \begin{verbatim}
+% type
+% TMyObject = class (TObject, IDispach)
+% function IUnknown.QueryInterface=MyQueryInterface;
+% ....
+% \end{verbatim}
+% and the \var{interface} before the dot not listed in the inheritance list.
+parser_e_type_cant_be_used_in_array_index=03170_E_No es pot utilitzar el tipus "$1" com a índex de conjunt
+% Types like \var{qword} or \var{int64} aren't allowed as array index type
+parser_e_no_con_des_in_interfaces=03171_E_No es permeten els constructors i destructors a l'interfície
+% Constructor and destructor declarations aren't allowed in interface
+% In the most cases the method \var{QueryInterface} of \var{IUnknown} can
+% be used to create a new interface
+parser_e_no_access_specifier_in_interfaces=03172_E_No es poden utilitzar els especificadors d'accés en l'interfície
+% The access specifiers \var{public}, \var{private}, \var{protected} and
+% \var{published} can't be used in interfaces because all methods
+% of an interfaces must be public.
+parser_e_no_vars_in_interfaces=03173_E_Una interfície no pot contenir camps
+% Declarations of fields aren't allowed in interfaces. An interface
+% can contain only methods
+parser_e_no_local_proc_external=03174_E_No es poden declarar procediments locals com EXTERNAL
+% Declaring local procedures as external is not possible. Local procedures
+% get hidden parameters that will make the chance of errors very high
+parser_w_skipped_fields_before=03175_W_Alguns camps d'abans de "$1" no s'han inicialitzat
+% In Delphi mode, not all fields of a typed constant record have to be
+% initialized, but the compiler warms you when it detects such situations
+parser_e_skipped_fields_before=03176_E_Alguns camps d'abans de "$1" no s'han inicialitzat
+% In all syntax modes but Delphi mode, you can't leave some fields unitialized
+% in the middle of a typed constant record
+parser_w_skipped_fields_after=03177_W_Alguns camps de després de "$1" no s'han inicialitzat
+% You can leave some fields at the end of a type constant record unitialized
+% (the compiler will initialize them to zero automatically), this may be the cause
+% of subtle problems.
+parser_e_varargs_need_cdecl_and_external=03178_E_Directiva VarArgs sense CDecl i External
+% The varargs directive can only be used with procedures or functions
+% that are declared with \var{cdecl} and \var{external} directives. The varargs directive
+% is only meant to provide a compatible interface to C functions like printf.
+parser_e_self_call_by_value=03179_E_SELF ha de ser un paràmetre normal
+% You can't declare self as a const or var parameter, it must always be
+% a call-by-value parameter
+parser_e_interface_has_no_guid=03180_E_L'interfície "$1" no té identificació d'interfície
+% When you want to assign an interface to a constant, then the interface
+% must have a GUID value set.
+parser_e_illegal_field_or_method=03181_E_Es desconeix el camp de la classe o l'identificador del mètode "$1"
+% Properties must refer to a field or method in the same class
+parser_w_proc_overriding_calling=03182_W_S'està sobreescrivint la convenció de la crida "$1" amb "$2"
+% There are two directives in the procedure declaration that specify a calling
+% convention. Only the last directive will be used
+parser_e_noprocvarobj_const=03183_E_Les constants del tipus "procediment de l'objecte" només es poden inicialitzar amb NIL
+% You can't assign the address of a method to a typed constant which has a
+% "procedure of object" type, because such a constant requires two addresses:
+% that of the method (which is known at compile time) and that of the object or
+% class instance it operates an (which can't be known at compile time).
+parser_e_default_value_only_one_para=03184_E_El valor predeterminat només es pot assignar a un paràmetre
+parser_e_default_value_expected_for_para=03185_E_Es requereix el paràmetre predeterminat per "$1"
+parser_w_unsupported_feature=03186_W_No es permet l'ús d'aquesta característica!
+% You're trying to force the compiler into doing something it cannot do yet.
+parser_h_c_arrays_are_references=03187_H_Els conjunts del C es passen per referència
+% Any array passed to a C functions is passed
+% by a pointer (i.e. by reference).
+parser_e_C_array_of_const_must_be_last=03188_E_El conjunt de constants de C, han de ser l'últim argument
+% You can not add any other argument after an \var{array of const} for
+% \var{cdecl} functions, as the size pushed on stack for this argument is
+% not known.
+parser_h_type_redef=03189_H_S'ha tornat a definir el tipus "$1"
+% This is an indicator that a previously declared type is
+% being redefined as something else. This may, or may not
+% be, a cause for errors.
+parser_w_cdecl_has_no_high=03190_W_Les funcions declarades amb CDECL no tenen paràmetres alts
+% Functions declared with cdecl modifier do not pass an extra implicit parameter
+parser_w_cdecl_no_openstring=03191_W_Les funcions declarades amb CDECL no son compatibles amb les cadenes obertes
+% Openstring is not supported for cdecl'ared functions
+parser_e_initialized_not_for_threadvar=03192_E_No es poden inicialitzar variables definides com a variables del fil
+% Variables declared as threadvar can not be initialized with a default value
+% The variables will always be filled with zero at the start of a new thread
+parser_e_msg_only_for_classes=03193_E_Només es permet la directiva del missatge en classes
+% The message directive is only supported for Class types.
+parser_e_procedure_or_function_expected=03194_E_S'esperava procediment o funció
+% A class method can only be specified for procedures and functions
+parser_e_illegal_calling_convention=03195_E_S'ignora la directiva de la convenció de la crida: "$1"
+% Some calling conventions are supported only by certain CPUs. I.e. most
+% non-i386 ports support only the standard ABI calling convention of the CPU.
+parser_e_no_object_reintroduce=03196_E_No es pot utilitzar REINTRODUCE en els objectes
+% \var{REINTRODUCE} is not supported for objects
+parser_e_paraloc_only_one_para=03197_E_Cada argument ha de tenir la seva pròpia localització
+% if locations for arguments are specified explicity as it is required by
+% some syscalls conventions, each argument must have its only location,
+% things like \var{procedure p (i,j:longint 'r');} aren't allowed
+parser_e_paraloc_all_paras=03198_E_Cada argument ha de tenir una localització explicita
+% if one argument has an explicit argument location, all arguments of a procedure
+% must have one
+parser_e_illegal_explicit_paraloc=03199_E_No es coneix la localització de l'argument
+% The location specified for an argument isn't recognized by the compiler
+parser_e_32bitint_or_pointer_variable_expected=03200_E_S'esperava variable tipus Integer de 32 Bits o Pointer
+% The libbase for MorphOS/AmigaOS can be give only as \var{longint}, \var{dword} or any pointer variable.
+parser_e_goto_outside_proc=03201_E_No es permeten les declaracions GOTO entre diferents procediments
+% It is not allowed to use the \var{goto} statements referencing labels outside the
+% current procedure. The following example shows the problem:
+% \begin{verbatim}
+% ...
+% procedure p1;
+% label
+% l1:
+%
+% procedure p2;
+% begin
+% goto l1; // This goto ISN'T allowed
+% end;
+%
+% begin
+% p2
+% l1;
+% end;
+% ...
+%
+% \end{verbatim}
+parser_f_too_complex_proc=03202_F_El procediment és massa complex, requereix massa registres
+% Your procedure body is too long for the compiler. You should split the
+% procedure into multiple smaller procedures.
+parser_e_illegal_expression=03203_E_L'expressió és il·legal
+% This can occur under many circumstancies. Mostly when trying to evaluate
+% constant expressions
+parser_e_invalid_integer=03204_E_L'expressió amb INTEGER no és vàlida, el resultat ha de ser INTEGER
+% You made an expression which isn't an integer, and the compiler expects the
+% result to be an integer.
+parser_e_invalid_qualifier=03205_E_El qualificador és il·legal
+% One of the following is happening:
+% \begin{itemize}
+% \item You're trying to access a field of a variable that is not a record.
+% \item You're indexing a variable that is not an array.
+% \item You're dereferencing a variable that is not a pointer.
+% \end{itemize}
+parser_e_upper_lower_than_lower=03206_E_El límit més alt és inferior al límit més baix de l'abast
+% You are declaring a subrange, and the lower limit is higher than the high
+% limit of the range
+parser_e_macpas_exit_wrong_param=03207_E_La sortida del paràmetre ha de ser el nom del procediment on s'utilitza
+% Non local exit is not allowed. This error occurs only in mode MacPas.
+parser_e_illegal_assignment_to_count_var=03208_E_L'assignació de la variable "$1" del bucle FOR no és vàlida
+% The type of a \var{for} loop variable must be an ordinal type.
+% Loop variables cannot be reals or strings.
+parser_e_no_local_var_external=03209_E_No es pot declarar una variable local com EXTERNAL
+% Declaring local variables as external is not allowed. Only global variables can reference
+% to external variables.
+parser_e_proc_already_external=03210_E_El procediment ja està declarat com EXTERNAL
+% The procedure is already declared with the EXTERNAL directive in an interface of
+% forward declaration.
+parser_w_implicit_uses_of_variants_unit=03211_W_S'està utilitzant implícitament l'unitat Variants
+% The Variant type is used in the unit without any used unit using the variants unit.
+% The compiler has implicity added the Variants unit to the uses list.
+% To remove this warning, the Variants unit needs to be added to the USES statement.
+parser_e_no_static_method_in_interfaces=03212_E_No es poden utilitzar els mètodes de la classe i estàtics dins d'INTERFACES
+% The specifier \var{class} and directive \var{static} can be used in interfaces
+% because all methods of an interface must be public.
+parser_e_arithmetic_operation_overflow=03213_E_S'ha produït una sobrecàrrega en l'operació aritmètica
+% An operation on two integers values produced an overflow
+% \end{description}
+#
+# Type Checking
+#
+#
+# 04058 is the last used one
+#
+% \section{Type checking errors}
+% This section lists all errors that can occur when type checking is
+% performed.
+% \begin{description}
+type_e_mismatch=04000_E_Els tipus no concorden
+% This can happen in many cases:
+% \begin{itemize}
+% \item The variable you're assigning to is of a different type than the
+% expression in the assignment.
+% \item You are calling a function or procedure with parameters that are
+% incompatible with the parameters in the function or procedure definition.
+% \end{itemize}
+type_e_incompatible_types=04001_E_Els tipus son incompatibles: s'ha obtingut "$1", s'esperava "$2"
+% There is no conversion possible between the two types
+% Another possiblity is that they are declared in different
+% declarations:
+% \begin{verbatim}
+% Var
+% A1 : Array[1..10] Of Integer;
+% A2 : Array[1..10] Of Integer;
+%
+% Begin
+% A1:=A2; { This statement gives also this error, it
+% is due the strict type checking of pascal }
+% End.
+% \end{verbatim}
+type_e_not_equal_types=04002_E_Els tipus "$1" i "$2" no concorden
+% The types are not equal
+type_e_type_id_expected=04003_E_S'esperava un identificador de tipus
+% The identifier is not a type, or you forgot to supply a type identifier.
+type_e_variable_id_expected=04004_E_S'esperava un identificador de variable
+% This happens when you pass a constant to a routine (such as \var{Inc} var or \var{Dec})
+% when it expects a variable. You can only pass variables as arguments to these functions.
+type_e_integer_expr_expected=04005_E_S'esperava una expressió entera, però s'ha obtingut "$1"
+% The compiler expects an expression of type integer, but gets a different
+% type.
+type_e_boolean_expr_expected=04006_E_S'esperava una expressió booleana, però s'ha obtingut "$1"
+% The expression must be a boolean type, it should be return true or
+% false.
+type_e_ordinal_expr_expected=04007_E_S'esperava una expressió ordinal
+% The expression must be of ordinal type, i.e., maximum a \var{Longint}.
+% This happens, for instance, when you specify a second argument
+% to \var{Inc} or \var{Dec} that doesn't evaluate to an ordinal value.
+type_e_pointer_type_expected=04008_E_S'esperava un tipus punter, però s'ha obtingut "$1"
+% The variable or expression isn't of the type \var{pointer}. This
+% happens when you pass a variable that isn't a pointer to \var{New}
+% or \var{Dispose}.
+type_e_class_type_expected=04009_E_S'esperava un tipus de classe, però s'ha obtingut "$1"
+% The variable of expression isn't of the type \var{class}. This happens
+% typically when
+% \begin{enumerate}
+% \item The parent class in a class declaration isn't a class.
+% \item An exception handler (\var{On}) contains a type identifier that
+% isn't a class.
+% \end{enumerate}
+type_e_cant_eval_constant_expr=04011_E_No es pot avaluar l'expressió constant
+% This error can ocurr when the bounds of an array you declared does
+% not evaluate to ordinal constants
+type_e_set_element_are_not_comp=04012_E_Els elements del conjunt no son compatibles
+% You are trying to make an operation on two sets, when the set element types
+% are not the same. The base type of a set must be the same when taking the
+% union
+type_e_set_operation_unknown=04013_E_L'operació no està implementada pels conjunts
+% several binary operations are not defined for sets
+% like div mod ** (also >= <= for now)
+type_w_convert_real_2_comp=04014_W_S'està convertint automàticament el tipus de punt flotant a COMP, el qual és un tipus enter
+% An implicit type conversion from a real type to a \var{comp} is
+% encountered. Since \var{comp} is a 64 bit integer type, this may indicate
+% an error.
+type_h_use_div_for_int=04015_H_Utilitzeu DIV per obtenir un resultat enter
+% When hints are on, then an integer division with the '/' operator will
+% procuce this message, because the result will then be of type real
+type_e_strict_var_string_violation=04016_E_Els tipus de la cadena no concorden a causa del mode $V+
+% When compiling in \var{\{\$V+\}} mode, the string you pass as a parameter
+% should be of the exact same type as the declared parameter of the procedure.
+type_e_succ_and_pred_enums_with_assign_not_possible=04017_E_No es pot utilitzar SUCC o PRED en enumeracions amb assignació
+% When you declared an enumeration type which has assignments in it, as in C,
+% like in the following:
+% \begin{verbatim}
+% Tenum = (a,b,e:=5);
+% \end{verbatim}
+% you cannot use the \var{Succ} or \var{Pred} functions on them.
+type_e_cant_read_write_type=04018_E_No es poden llegir o escriure variables d'aquest tipus
+% You are trying to \var{read} or \var{write} a variable from or to a
+% file of type text, which doesn't support that. Only integer types,
+% reals, pchars and strings can be read from/written to a text file.
+% Booleans can only be written to text files.
+type_e_no_readln_writeln_for_typed_file=04019_E_No és pot utilitzar READLN o WRITELN en fitxers de tipus
+% \var{readln} and \var{writeln} are only allowed for text files.
+type_e_no_read_write_for_untyped_file=04020_E_No és pot utilitzar READ o WRITE en fitxers sense tipus
+% \var{read} and \var{write} are only allowed for text or typed files.
+type_e_typeconflict_in_set=04021_E_S'ha produït un conflicte de tipus entre els elements del conjunt
+% There is at least one set element which is of the wrong type, i.e. not of
+% the set type.
+type_w_maybe_wrong_hi_lo=04022_W_lo/hi(dword/qword) retorna el word/dword més alt/més baix
+% \fpc supports an overloaded version of \var{lo/hi} for \var{longint/dword}
+% which returns the lower/upper word of the argument. TP always uses
+% a 16 bit \var{lo/hi} which returns always bits 0..7 for \var{lo} and the
+% bits 8..15 for \var{hi}. If you want the TP behavior you have
+% to type case the argument to \var{word/integer}
+type_e_integer_or_real_expr_expected=04023_E_S'esperava una expressió tipus INTEGER o REAL
+% The first argument to \var{str} must a real or integer type.
+type_e_wrong_type_in_array_constructor=04024_E_El tipus "$1" no és correcte en el constructor del conjunt
+% You are trying to use a type in an array constructor which is not
+% allowed.
+type_e_wrong_parameter_type=04025_E_El tipus de l'argument num.$1 és incompatible: s'ha obtingut "$2", s'esperava "$3"
+% You are trying to pass an invalid type for the specified parameter.
+% \end{description}
+type_e_no_method_and_procedure_not_compatible=04026_E_El mètode (variable) i el procediment (variable) no son compatibles
+% You can't assign a method to a procedure variable or a procedure to a
+% method pointer.
+type_e_wrong_math_argument=04027_E_S'ha passat una constant il·legal a una funció matemàtica interna
+% The constant argument passed to a ln or sqrt function is out of
+% the definition range of these functions.
+type_e_no_addr_of_constant=04028_E_No es pot trobar l'adreça de les constants
+% It is not possible to get the address of a constant, because they
+% aren't stored in memory, you can try making it a typed constant.
+type_e_argument_cant_be_assigned=04029_E_No es pot assignar l'argument
+% Only expressions which can be on the left side of an
+% assignment can be passed as call by reference argument
+% Remark: Properties can be only
+% used on the left side of an assignment, but they cannot be used as arguments
+type_e_cannot_local_proc_to_procvar=04030_E_No es pot assignar el procediment/funció local a la variable del procediment
+% It's not allowed to assign a local procedure/function to a
+% procedure variable, because the calling of local procedure/function is
+% different. You can only assign local procedure/function to a void pointer.
+type_e_no_assign_to_addr=04031_E_No es poden assignar els valors a una adreça
+% It is not allowed to assign a value to an address of a variable, constant,
+% procedure or function. You can try compiling with -So if the identifier
+% is a procedure variable.
+type_e_no_assign_to_const=04032_E_No es poden assignar valors a una variable declarada com a constant
+% It's not allowed to assign a value to a variable which is declared
+% as a const. This is normally a parameter declared as const, to allow
+% changing the value make the parameter as a value parameter or a var.
+type_e_array_required=04033_E_Es requereix tipus de conjunt
+% If you are accessing a variable using an index '[<x>]' then
+% the type must be an array. In FPC mode also a pointer is allowed.
+type_e_interface_type_expected=04034_E_S'esperava tipus d'interfície, però s'ha obtingut "$1"
+type_w_mixed_signed_unsigned=04035_W_El resultat de la barreja d'expressions amb signe i paraules llargues és de 64 octets
+% If yoy divide (or calculate the modulus of) a signed expression by a longword (or vice versa),
+% or if you have overflow and/or range checking turned on and use an arithmetic
+% expression (+, -, *, div, mod) in which both signed numbers and longwords appear,
+% then everything has to be evaluated in 64bit which is slower than normal
+% 32bit arithmetic. You can avoid this by typecasting one operand so it
+% matches the result type of the other one.
+type_w_mixed_signed_unsigned2=04036_W_Barrejar expressions amb signe i cardinals aquí, pot causar errors de l'abast
+% If you use a binari operator (and, or, xor) and one of
+% the operands is a longword while the other one is a signed expression, then,
+% if range checking is turned on, you may get a range check error because in
+% such a case both operands are converted to longword before the operation is
+% matches the result type of the other one.
+type_e_typecast_wrong_size_for_assignment=04037_E_La conversió de tipus té diferents tamanys ($1 -> $2) en les assignacions
+% Type casting to a type with a different size is not allowed when the variable is
+% used for assigning.
+type_e_array_index_enums_with_assign_not_possible=04038_E_Els enumerats amb assignacions no es poden utilitzar com a índex de conjunts
+% When yoy declare an enumeration type which has assignments in it, as in C,
+% like the foloowing:
+% \begin{verbatim}
+% Tenum = (a,b,e:=5);
+% \end{verbatim}
+% yoy cannot use it as index of an array.
+type_e_classes_not_related=04039_E_Els tipus Class o Object "$1" i "$2" no estan relacionats
+% There is a typecast from one class or object to another while the class/object
+% are not related. This will probably lead to errors
+type_w_classes_not_related=04040_W_Els tipus de la classe "$1" i "$2" no estan relacionats
+% There is a typecast from one class or object to another while the class/object
+% are not related. This will probably lead to errors
+type_e_class_or_interface_type_expected=04041_E_S'esperava tipus de classe o interfície, però s'ha obtingut "$1"
+type_e_type_is_not_completly_defined=04042_E_No s'ha definit completament el tipus "$1"
+% The size of the constant string, which is assigned to a shortstring,
+% is longer than the maximum size of the shortstring
+type_w_signed_unsigned_always_false=04044_W_La comparació és sempre falsa a causa de l'abast dels valors
+% There is a comparison between an unsigned value and a signed constant which is
+% less than zero. Because of type promotion, the statement will always evaluate to
+% false. Explicitly typecast the constant to the correct range to avoid this problem.
+type_w_signed_unsigned_always_true=04045_W_La comparació és sempre vertadera a causa de l'abast dels valors
+% There is a comparison between an unsigned value and a signed constant which is
+% less than zero. Because of type promotion, the statement will always evaluate to
+% true. Explicitly typecast the constant to the correct range to avoid this problem.
+type_w_instance_with_abstract=04046_W_S'està construint una classe "$1" amb mètodes abstractes
+% An instance of a class is created which contains non_implemented abstract
+% methods. This will probably lead to a runtime error 211 in the code if that
+% routine is ever called. All abstract methods should be overridden.
+type_h_in_range_check=04047_H_L'operand esquerra per a l'operador d'IN ha de tenir el tamany d'un octet
+% The left operand of the \var{in} operator is not an ordinal or enumeration which fits
+% within 8-bits, this may lead to range check errors. The \var{in} operator
+% currently only supports a left operand which fits within a byte. In the case of
+% enumerations, the size of an element of an enumeration can be controlled with
+% the \var{\{\$PACKENUM\}} or \var{\{\$Zn\}} switches.
+type_w_smaller_possible_range_check=04048_W_El tamany dels tipus no concorden, possible pèrdua de dades / errors de l'abast
+type_h_smaller_possible_range_check=04049_H_El tamany dels tipus no concorden, possible pèrdua de dades / errors de l'abast
+% There is an assignement to a smaller type than the source type. This means that
+% this may cause a range-check error, or may lead to possible loss of data
+type_e_cant_take_address_of_abtract_method=04050_E_No es pot obtenir l'adreça d'un mètode abstracte
+% An abstract method has no body, so the address of an abstract method can not
+% be taken
+type_e_operator_not_allowed=04051_E_No es pot aplicar l'operador pel tipus d'operand
+% You are trying an operator that is not available for the type of the
+% operands
+type_e_constant_expr_expected=04052_E_S'esperava una expressió constant
+% The compiler expects an constant expression, but gets a variable expression.
+type_e_operator_not_supported_for_types=04053_E_L'operació "$1" no és compatible pels tipus "$2" i "$3"
+% The operation is not allowed for the supplied types
+type_e_illegal_type_conversion=04054_E_S'ha produït una conversió il·legal dels tipus: "$1" a "$2"
+% When doing a type-cast, you must take care that the sizes of the variable
+% and the destination type are the same
+type_h_pointer_to_longint_conv_not_portable=04055_H_La conversió entre ordinals i punters no és portable
+% If you typecast a pointer to a longint (or vice-versa), this code will not
+% compile on a machineusing 64-bit for pointer storage.
+type_w_pointer_to_longint_conv_not_portable=04056_W_La conversió entre ordinals i punters no és portable
+% If you typecast a pointer to a ordinal type of different size (or vice-versa)
+% this can cause problems. This is a warning to help finding the 32bit specific
+% code where cardinal/longint is used to typecast pointers to ordinals
+% A solution is to use the ptrint/ptruint types instead.
+type_e_cant_choose_overload_function=04057_E_No es pot determinar a quina funció sobrecarregada cridar.
+% You are calling overloaded functions with a parameter that does not correspond
+% to any of the declared function parameter lists. e.g. when you have declared
+% a function with parameters \var{word} and \var{longint}, and then you call
+% it with a parameter which is of type \var{integer}.
+type_e_illegal_count_var=04058_E_La variable del comptador no és vàlida
+% The type of a \var{for} loop variable must be an ordinal type.
+% Loop variables cannot be reals or strings.
+% \end{description}
+#
+# Symtable
+#
+# 05056 is the last used one
+#
+% \section{Symbol handling}
+% This section lists all the messages that concern the handling of symbols.
+% This means all things that have to do with procedure and variable names.
+% \begin{description}
+sym_e_id_not_found=05000_E_No s'ha trobat l'dentificador "$1"
+% The compiler doesn't know this symbol. Usually happens when you misspel
+% the name of a variable or procedure, or when you forgot to declare a
+% variable.
+sym_f_internal_error_in_symtablestack=05001_F_S'ha produït un error intern en SymTableStack()
+% An internal error occurred in the compiler; If you encounter such an error,
+% please contact the developers and try to provide an exact description of
+% the circumstances in which the error occurs.
+sym_e_duplicate_id=05002_E_L'identificador "$1" està duplicat
+% The identifier was already declared in the current scope.
+sym_h_duplicate_id_where=05003_H_L'identificador ja està definit en $1 en la línia $2
+% The identifier was already declared in a previous scope.
+sym_e_unknown_id=05004_E_Es desconeix l'identificador "$1"
+% The identifier encountered has not been declared, or is used outside the
+% scope where it is defined.
+sym_e_forward_not_resolved=05005_E_No s'ha resolt la declaració posterior "$1"
+% This can happen in two cases:
+% \begin{itemize}
+% \item This happens when you declare a function (in the \var{interface} part, or
+% with a \var{forward} directive, but do not implement it.
+% \item You reference a type which isn't declared in the current \var{type}
+% block.
+% \end{itemize}
+sym_e_error_in_type_def=05007_E_S'ha produït un error en la definició del tipus
+% There is an error in your definition of a new array type:
+% \item One of the range delimiters in an array declaration is err¢neous.
+% For example, \var{Array [1..1.25]} will trigger this error.
+sym_e_forward_type_not_resolved=05009_E_No s'ha resolt el tipus posterior "$1"
+% A symbolwas forward defined, but no declaration was encountered.
+sym_e_only_static_in_static=05010_E_Només les variables estàtiques poden ser utilitzades en mètodes estàtics o fora dels mètodes
+% A static method of an object can only access static variables.
+sym_f_type_must_be_rec_or_class=05012_F_S'esperava un tipus de registre o classe
+% The variable or expression isn't of the type \var{record} or \var{class}.
+sym_e_no_instance_of_abstract_object=05013_E_No es permeten les instàncies de les classes o els objectes amb un mètode abstracte
+% You are trying to generate an instance of a class which has an abstract
+% method that wasn't overridden.
+sym_w_label_not_defined=05014_W_No s'ha definit l'etiqueta "$1"
+% A label was declared, but not defined.
+sym_e_label_used_and_not_defined=05015_E_S'està utilitzant l'etiqueta "$1" però no està definida
+% A label was declared and used, but not defined.
+sym_e_ill_label_decl=05016_E_La declaració de l'etiqueta no és vàlida
+% This error should never happen; it occurs if a label is defined outside a
+% procedure or function.
+sym_e_goto_and_label_not_supported=05017_E_No es permeten GOTO i LABEL (utilitzeu el commutador -Sg)
+% You must compile a program which has \var{label}s and \var{goto} statements
+% with the \var{-Sg} switch. By default, \var{label} and \var{goto} aren't
+% supported.
+sym_e_label_not_found=05018_E_No s'ha trobat l'etiqueta
+% A \var{goto label} was encountered, but the label isn't declared.
+sym_e_id_is_no_label_id=05019_E_L'identificador no és una etiqueta
+% The identifier specified after the \var{goto} isn't of type label.
+sym_e_label_already_defined=05020_E_L'etiqueta ja està definida
+% You are defining a label twice. You can define a label only once.
+sym_e_ill_type_decl_set=05021_E_Declaració de tipus il·legal dels elements del conjunt
+% The declaration of a set contains an invalid type definition.
+sym_e_class_forward_not_resolved=05022_E_No s'ha resolt la definició de la classe posterior "$1"
+% You declared a class, but you did not implement it.
+sym_n_unit_not_used=05023_H_No s'utilitza l'unitat "$1" en $2
+% The unit referenced in the \var{uses} clause is not used.
+sym_h_para_identifier_not_used=05024_H_No s'utilitza el paràmetre "$1"
+% The identifier was declared (locally or globally) but
+% was not used (locally or globally).
+sym_n_local_identifier_not_used=05025_N_No s'utilitza la variable local "$1"
+% You have declared, but not used a variable in a procedure or function
+% implementation.
+sym_h_para_identifier_only_set=05026_H_S'ha assignat el paràmetre del valor "$1" però no s'utilitza
+% The identifier was declared (locally or globally)
+% set but not used (locally or globally).
+sym_n_local_identifier_only_set=05027_N_S'ha assignat la variable local "$1" però no s'utilitza
+% The variable in a procedure or function
+% implementation is declared, set but never used.
+sym_h_local_symbol_not_used=05028_H_No s'utilitza $1 local "$2"
+% A local symbol is never used.
+sym_n_private_identifier_not_used=05029_N_No s'utilitza el camp privat "$1.$2"
+sym_n_private_identifier_only_set=05030_N_S'ha assignat el camp privat "$1.$2" però no s'utilitza
+sym_n_private_method_not_used=05031_N_No s'utilitza el mètode privat "$1.$2"
+sym_e_set_expected=05032_E_S'esperava un tipus de conjunt
+% The variable or expression is not of type \var{set}. This happens in an
+% \var{in} statement.
+sym_w_function_result_not_set=05033_W_No s'ha definit el resultat de la funció
+% You can get this warning if the compiler thinks that a function return
+% value is not set. This will not be displayed for assembler procedures,
+% or procedures that contain assembler blocks.
+sym_w_wrong_C_pack=05034_W_El tipus "$1" no està alineat correctament en el registre actual pel C
+% Arrays with sizes not multiples of 4 will be wrongly aligned
+% for C structures.
+sym_e_illegal_field=05035_E_No es coneix l'identificador del camp del registre "$1"
+% The field doesn't exist in the record/object definition.
+sym_w_uninitialized_local_variable=05036_W_No s'ha inicialitzat la variable local "$1"
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_w_uninitialized_variable=05037_W_No s'ha inicialitzat la variable "$1"
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_e_id_no_member=05038_E_L'identificador "$1" no identifica cap membre
+% This error is generated when an identifier of a record,
+% field, or method is accessed while it is not defined.
+sym_h_param_list=05039_H_S'ha trobat la declaració: $1
+% You get this when you use the \var{-vh} switch. In case an overloaded
+% procedure is not found, then all candidate overloaded procedures are
+% listed, with their parameter lists.
+sym_e_segment_too_large=05040_E_L'element de dades és massa llarg
+% You get this when you declare an array whose size exceeds the
+% prescribed limit (2 Gb on 80368+/68020+ processors)
+sym_e_no_matching_implementation_found=05042_E_S'ha trobat una implementació pel mètode d'interfície "$1" que no concorda
+% There was no matching method found which could implement the interface
+% method. Check argument types and result type of the methods.
+sym_w_deprecated_symbol=05043_W_Es desaconsella el símbol "$1"
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{deprecated} is used. Deprecated symbols may no longer
+% be available in newer versions of the unit/library. Usage of this symbol
+% should be avoied as much as possible.
+sym_w_non_portable_symbol=05044_W_El símbol "$1" no és portable
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{platform} is used. This symbol's value, usage
+% and availability is platform specific and should not be used
+% if the source code must be portable.
+sym_w_non_implemented_symbol=05055_W_El símbol "$1" no està implementat
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{unimplemented} is used. This symbol is defined,
+% but is not yet implemented on this specific platform.
+sym_e_cant_create_unique_type=05056_E_No es pot crear un tipus únic a partir d'aquest tipus
+% Only simple types like ordinal, float and string types are supported when
+% redefining a type with \var{type newtype = type oldtype;}
+% \end{description}
+sym_h_uninitialized_local_variable=05057_H_La variable local "$1" no està inicialitzada
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_h_uninitialized_variable=05058_H_La variable "$1" no està inicialitzada
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+#
+# Codegenerator
+#
+# 06045 is the last used one
+#
+% \section{Code generator messages}
+% This section lists all messages that can be displayed if the code
+% generator encounters an error condition.
+% \begin{description}
+cg_e_parasize_too_big=06009_E_El tamany de la llista de paràmetres excedeix els 65535 octets
+% The I386 processor limits the parameter list to 65535 bytes (the \var{RET}
+% instruction causes this)
+cg_e_file_must_call_by_reference=06012_E_Els tipus del fitxer han de ser paràmetres variables
+% You cannot specify files as value parameters, i.e. they must always be
+% declared \var{var} parameters.
+cg_e_cant_use_far_pointer_there=06013_E_Aquí no es permet l'ús de punters de tipus FAR
+% Free Pascal doesn't support far pointers, so you cannot take the address of
+% an expression which has a far reference as a result. The \var{mem} construct
+% has a far reference as a result, so the following code will produce this
+% error:
+% \begin{verbatim}
+% var p : pointer;
+% ...
+% p:=@mem[a000:000];
+% \end{verbatim}
+cg_e_dont_call_exported_direct=06015_E_No es poden cridar les funcions declarades amb EXPORT
+% No longer in use.
+cg_w_member_cd_call_from_method=06016_W_Possiblement s'ha produït una crida il·legal d'un constructor o destructor
+% The compiler detected that a constructor or destructor is called within a
+% method. This will probably lead to problems, since contructors/destructors
+% require parameters on entry
+cg_n_inefficient_code=06017_N_El codi és ineficient
+% You statement seems dubious to the compiler.
+cg_w_unreachable_code=06018_W_Aquest codi no s'executa mai
+% You specified a construct which will never be executed. Example:
+% \begin{verbatim}
+% while false do
+% begin
+% {.. code ...}
+% end;
+% \end{verbatim}
+cg_e_cant_call_abstract_method=06020_E_Els mètodes abstractes no es poden cridar directament
+% You cannot call an abstract method directy, instead you must call a
+% overriding child method, because an abstract method isn't implemented.
+cg_d_register_weight=06027_DL_Registre $1 pes $2 $3
+% Debugging message. Shown when the compiler considers a variable for
+% keeping in the registers.
+cg_d_stackframe_omited=06029_DL_S'omet l'estructura de la pila
+% Some procedure/functions do not need a complete stack-frame, so it is omitted.
+% This message will be displayed when the {-vd} switch is used.
+cg_e_unable_inline_object_methods=06031_E_No es poden inserir mètodes d'objectes o classes
+% You cannot have inlined object methods.
+cg_e_unable_inline_procvar=06032_E_No es poden inserir crides a procvar
+% A procedure with a procedural variable call cannot be inlined.
+cg_e_no_code_for_inline_stored=06033_E_No hi ha codi enmagetzemat pel procediment inserit
+% The compiler couldn't store code for the inline procedure.
+cg_e_can_access_element_zero=06035_E_No es pot accedir a l'element zero d'un ansi/wide- o longstring, utilitzeu (set)length
+% You should use \var{setlength} to set the length of an ansi/wide/longstring
+% and \var{length} to get the length of such a string types
+cg_e_cannot_call_cons_dest_inside_with=06037_E_No es poden cridar constructors o destructors dins de la clàusula 'with'
+% Inside a \var{with} clause you cannot call a constructor or destructor for the
+% object you have in the \var{with} clause.
+cg_e_cannot_call_message_direct=06038_E_No es poden cridat els mètodes manipuladors de missatges directament
+% A message method handler method cannot be called directly if it contains an
+% explicit self argument
+cg_e_goto_inout_of_exception_block=06039_E_Hi ha un salt dins o fora d'un block d'excepció
+% It is not allowed to jump in or outside of an exception block like \var{try..finally..end;}:
+% \begin{verbatim}
+% label 1;
+%
+% ...
+%
+% try
+% if not(final) then
+% goto 1; // this line will cause an error
+% finally
+% ...
+% end;
+% 1:
+% ...
+% \end{verbatim}
+cg_e_control_flow_outside_finally=06040_E_No es permeten les declaracions de control de flux en un bloc finally
+% It isn't allowed to use the control flow statements \var{break},
+% \var{continue} and \var{exit}
+% inside a finally statement. The following example shows the problem:
+% \begin{verbatim}
+% ...
+% try
+% p;
+% finally
+% ...
+% exit; // This exit ISN'T allowed
+% end;
+% ...
+%
+% \end{verbatim}
+% If the procedure \var{p} raises an exception the finally block is
+% executed. If the execution reaches the exit, it's unclear what to do:
+% exiting the procedure or searching for another exception handler
+cg_w_parasize_too_big=06041_W_El tamany dels paràmetres excedeix el límit per determinades cpu's
+% This indicates that you are declaring more than 64k ok parameters, which
+% might not be supported on other processor targets.
+cg_w_localsize_to_big=06042_W_El tamany de la variable local excedeix el límit per determinades cpu's
+% This indicates that you are declaring more than 32k of local variables, which
+% might not be supported on other processor targets.
+cg_e_localsize_too_big=06043_E_Les variables locals excedeixen el límit permès
+% This indicates that you are declaring more than 32k of local variables, which
+% is not supported by this processor.
+cg_e_break_not_allowed=06044_E_No es permet BREAK
+% You're trying to use \var{break} outside a loop construction.
+cg_e_continue_not_allowed=06045_E_No es permet CONTINUE
+% You're trying to use \var{continue} outside a loop construction.
+% \end{description}
+# EndOfTeX
+#
+# Assembler reader
+#
+# 07097 is the last one used
+#
+asmr_d_start_reading=07000_DL_S'està començant l'analització del bloc d'assemblador $1
+% This informs you that an assembler block is being parsed
+asmr_d_finish_reading=07001_DL_S'ha finalitzat l'analizació del bloc d'assemblador $1
+% This informs you that an assembler block has finished.
+asmr_e_none_label_contain_at=07002_E_Un patró que no és una etiqueta conté @
+% A identifier which isn't a label can't contain a @.
+asmr_e_building_record_offset=07004_E_S'ha produït un error mentre es muntava el desplaçament del registre
+% There has an error occured while building the offset of a record/object
+% structure, this can happend when there is no field specified at all or
+% an unknown field identifier is used.
+asmr_e_offset_without_identifier=07005_E_S'està utilitzant OFFSET sense identificador
+% You can only use OFFSET with an identifier. Other syntaxes aren't
+% supported
+asmr_e_type_without_identifier=07006_E_S'està utilitzant TYPE sense identificador
+% You can only use TYPE with an identifier. Other syntaxes aren't
+% supported
+asmr_e_no_local_or_para_allowed=07007_E_Aquí no es poden utilitzar variables locals o paràmetres
+% You can't use a local variable or parameter here, mostly because the
+% addressing of locals and parameters is done using the frame pointer register so the
+% address can't be obtained directly.
+asmr_e_need_offset=07008_E_Aquí heu d'utilitzar OFFSET
+% You need to use OFFSET <id> here to get the address of the identifier.
+asmr_e_need_dollar=07009_E_Aquí heu d'utilitzar $
+% You need to use $<id> here to get the address of the identifier.
+asmr_e_cant_have_multiple_relocatable_symbols=07010_E_No es poden utilitzar multiples símbols reassignats
+% You can't have more than one relocatable symbol (variable/typed constant)
+% in one argument.
+asmr_e_only_add_relocatable_symbol=07011_E_Els símbols reassignats només es poden afegir
+% Relocatable symbols (variable/typed constant) can't be used with other
+% operators. Only addition is allowed.
+asmr_e_invalid_constant_expression=07012_E_L'expressió constant no és vàlida
+% There is an error in the constant expression.
+asmr_e_relocatable_symbol_not_allowed=07013_E_No es permet el símbol reassignat
+% You can't use a relocatable symbol (variable/typed constant) here.
+asmr_e_invalid_reference_syntax=07014_E_La sintaxi de la referència no és vàlida
+% There is an error in the reference.
+asmr_e_local_para_unreachable=07015_E_No podeu accedir a $1 des d'aquest codi
+% You can not read directly the value of local or para
+% of a higher level in assembler code (except for
+% local assembler code without parameter nor locals).
+asmr_e_local_label_not_allowed_as_ref=07016_E_No es permeten els símbols i etiquetes locals com a referències
+% You can't use local symbols/labels as references
+asmr_e_wrong_base_index=07017_E_L'utilització de la base i índex del registre no és vàlida
+% There is an error with the base and index register, they are
+% probably incorrect
+asmr_w_possible_object_field_bug=07018_W_Hi ha un possible error en la manipulació del camp de l'objecte
+% Fields of objects or classes can be reached directly in normal or objfpc
+% modes but TP and Delphi modes treat the field name as a simple offset.
+asmr_e_wrong_scale_factor=07019_E_S'ha especificat un factor de l'escala erroni
+% The scale factor given is wrong, only 1,2,4 and 8 are allowed
+asmr_e_multiple_index=07020_E_S'estan utilitzant múltiples registres d'índex
+% You are trying to use more than one index register
+asmr_e_invalid_operand_type=07021_E_El tipus de l'operand no és vàlid
+% The operand type doesn't match with the opcode used
+asmr_e_invalid_string_as_opcode_operand=07022_E_La cadena $1 no és vàlida com operand opcode
+% The string specified as operand is not correct with this opcode
+asmr_w_CODE_and_DATA_not_supported=07023_W_No es permet l'ús de @CODE i @DATA
+% @CODE and @DATA are unsupported and are ignored.
+asmr_e_null_label_ref_not_allowed=07024_E_No es permeten les referències a etiquetes nul·les
+asmr_e_expr_zero_divide=07025_E_Divisió per zero en l'avaluador asm
+% There is a division by zero in a constant expression
+asmr_e_expr_illegal=07026_E_L'expressió és il·legal
+% There is an illegal expression in a constant expression
+asmr_e_escape_seq_ignored=07027_E_S'ignora la seqüència d'escapament: $1
+% There is a C-styled string, but the escape sequence in the string
+% is unknown, and is therefore ignored
+asmr_e_invalid_symbol_ref=07028_E_La referència del símbol no és vàlida
+asmr_w_fwait_emu_prob=07029_W_Fwait pot causar problemes d'emulació amb emu387
+asmr_w_fadd_to_faddp=07030_W_S'ha traduït $1 sense operand a $1P
+asmr_w_enter_not_supported_by_linux=07031_W_El Kernel del Linux no permet l'instrucció ENTER
+% ENTER instruction can generate a stack page fault that is not
+% caught correctly by the i386 Linux page handler.
+asmr_w_calling_overload_func=07032_W_S'està cridant a una funció sobrecarregada en asm
+% There is a call to an overloaded method in the assembler block,
+% this might be the sign there is a problem
+asmr_e_unsupported_symbol_type=07033_E_El tipus del símbol no és compatible amb l'operand
+asmr_e_constant_out_of_bounds=07034_E_El valor de la constant està fora dels límits
+asmr_e_error_converting_decimal=07035_E_S'ha produït un error mentre es convertia el decimal $1
+% A constant decimal value doen not have the correct syntax
+asmr_e_error_converting_octal=07036_E_S'ha produït un error mentre es convertia l'octal $1
+% A constant octal value does not have the correct syntax
+asmr_e_error_converting_binary=07037_E_S'ha produït un error mentre es convertia el binari $1
+% A constant binary value does not have the correct syntax
+asmr_e_error_converting_hexadecimal=07038_E_S'ha produït un error mentre es convertia l'hexadecimal $1
+% A constant hexadecimal value does not have the correct syntax
+asmr_h_direct_global_to_mangled=07039_H_S'ha traduït $1 a $2
+asmr_w_direct_global_is_overloaded_func=07040_W_$1 està associat a una funció sobrecarregada
+asmr_e_cannot_use_SELF_outside_a_method=07041_E_No es pot utilitzar SELF fora d'un mètode
+% There is a reference to the \var{self} symbol while it is not
+% allowed. \var{self} can only be referenced inside methods
+asmr_e_cannot_use_OLDEBP_outside_nested_procedure=07042_E_No es pot utilitzar OLDEBP fora d'un procediment niat
+% There is a reference to the \var{oldebp} symbol while it is not
+% allowed. \var{oldebp} can only be referenced inside nested routines
+asmr_e_void_function=07043_W_Els procediments no poden retornar cap valor en codi asm
+% Trying to return a value while in a procedure. A procedure
+% does not have any return value
+asmr_e_SEG_not_supported=07044_E_No es permet SEG
+asmr_e_size_suffix_and_dest_dont_match=07045_E_El tamany de sufix i objectiu o el tamany de l'origen no concorden
+% The register size and the opcode size suffix does not match. This is
+% probably an error in the assembler statement
+asmr_w_size_suffix_and_dest_dont_match=07046_W_El tamany de sufix i objectiu o el tamany de l'origen no concorden
+% The register size and the opcode size suffix does not match. This is
+% probably an error in the assembler statement
+asmr_e_syntax_error=07047_E_Error de sintaxi de l'assemblador
+% There is an assembler syntax error
+asmr_e_invalid_opcode_and_operand=07048_E_La combinació d'opcode i operands no és vàlida
+% The opcode cannot be used with this type of operand
+asmr_e_syn_operand=07049_E_S'ha trobat un error de sintaxi de l'assemblador en l'operand
+asmr_e_syn_constant=07050_E_S'ha trobat un error de sintaxi de l'assemblador en la constant
+asmr_e_invalid_string_expression=07051_E_L'expressió de la cadena no és vàlida
+asmr_w_const32bit_for_address=07052_W_Constant amb símbol $1 per una adreça que no és en un punter
+% A constant expression represents an address which does not fit
+% into a pointer. The address is probably incorrect
+asmr_e_unknown_opcode=07053_E_Es desconeix l'opcode $1
+% This opcode is not known
+asmr_e_invalid_or_missing_opcode=07054_E_Falta opcode o no és vàlid
+asmr_e_invalid_prefix_and_opcode=07055_E_La combinació del prefix i l'opcode $1 no és vàlida
+asmr_e_invalid_override_and_opcode=07056_E_La combinació de override i opcode $1 no és vàlida
+asmr_e_too_many_operands=07057_E_Hi ha massa operands en la línia
+% There are too many operands for this opcode. Check your
+% assembler syntax
+asmr_w_near_ignored=07058_W_S'ignora NEAR
+asmr_w_far_ignored=07059_W_S'ignora FAR
+asmr_e_dup_local_sym=07060_E_El símbol local $1 està duplicat
+asmr_e_unknown_local_sym=07061_E_El símbol local $1 no està definit
+asmr_e_unknown_label_identifier=07062_E_No es coneix l'identificador de l''etiqueta $1
+asmr_e_invalid_register=07063_E_El nom del registre no és vàlid
+% There is an unknown register name used as operand
+asmr_e_invalid_fpu_register=07064_E_El nom del registre de punt flotant no és vàlid
+asmr_w_modulo_not_supported=07066_W_No es permet l'ús del mòdul
+asmr_e_invalid_float_const=07067_E_La constant de punt flotant $1 no és vàlida
+% The floating point constant declared in an assembler block is invalid
+asmr_e_invalid_float_expr=07068_E_L'expressió de punt flotant no és vàlida
+% The floating point expression declared in an assembler block is invalid
+asmr_e_wrong_sym_type=07069_E_El tipus del símbol no és correcte
+asmr_e_cannot_index_relative_var=07070_E_No es pot indexar una variable local o un paràmetre amb un registre
+% Trying to index using a base register a symbol which is already relative
+% to a register. This is not possible, and will probably lead to crashes.
+asmr_e_invalid_seg_override=07071_E_L'expressió que sobreescriu el segment no és vàlida
+asmr_w_id_supposed_external=07072_W_S'assumeix l'identificador $1 com extern
+% There is a reference to an undefined symbol. This will not result
+% in an error, since the symbol might be external, but may cause
+% problems at link time if the symbol is not defined anywhere.
+asmr_e_string_not_allowed_as_const=07073_E_No es permeten les cadenes com a constants
+% Character strings are not allowed as constants.
+asmr_e_no_var_type_specified=07074_E_No s'ha especificat el tipus de la variable
+% The syntax expects a type idenfitifer after the dot, but
+% none was found.
+asmr_w_assembler_code_not_returned_to_text=07075_E_El codi de l'assemblador no ha retornat a la secció de text
+% There was a directive in the assembler block to change sections,
+% but there is a missing return to the text section at the end
+% of the assembler block. This might cause errors during link time.
+asmr_e_not_directive_or_local_symbol=07076_E_$1 no és una directiva o un símbol local
+% This symbol is unknown.
+asmr_w_using_defined_as_local=07077_E_S'està utilitzant un nom definit com una etiqueta local
+asmr_e_dollar_without_identifier=07078_E_S'està utilitzant el símbol Dol·lar sense un identificador
+% A constant expression has an identifier which does not start with
+% the $ symbol.
+asmr_w_32bit_const_for_address=07079_W_L'adreça ha creat una constant de 32bit
+% A constant was used as an address. This is probably an error,
+% since using absolute addresses will probably not work.
+asmr_n_align_is_target_specific=07080_N_.align és específic de la plataforma, utilitzeu .balign o .p2align
+% Using the .align directive is platform specific, and its meaning will vary
+% from one platform to another.
+asmr_e_cannot_access_field_directly_for_parameters=07081_E_Els paràmetres no poden accedir directament als camps
+% You should load the parameter first into a register and then access the
+% fields using that register.
+asmr_e_cannot_access_object_field_directly=07082_E_No es pot accedir directament als camps dels objectes o classes
+% You should load the self pointer first into a register and then access the
+% fields using the register as base. By default the self pointer is available
+% in the esi register on i386.
+asmr_e_unable_to_determine_reference_size=07083_E_No s'ha especificat el tamany i no es pot determinar el tamany dels operands
+% You should specify explicity a size for the reference, because
+% compiler is unable to determine what size (byte, word, dword, etc.) it
+% should use for the reference.
+asmr_e_cannot_use_RESULT_here=07084_E_No es pot utilitzar RESULT en aquesta funció
+% Some functions which return complex types cannot use the \var{result}
+% keyword.
+asmr_w_adding_explicit_args_fXX=07086_W_"$1" sense operand s'ha traduït a "$1 %st,%st(1)"
+asmr_w_adding_explicit_first_arg_fXX=07087_W_"$1 %st(n)" s'ha traduït a "$1 %st,%st(n)"
+asmr_w_adding_explicit_second_arg_fXX=07088_W_"$1 %st(n)" s'ha traduït a "$1 %st(n),%st"
+asmr_e_invalid_char_smaller=07089_E_Aquí no es permet el caràcter <
+% The shift operator requires the << characters. Only one
+% of those characters was found.
+asmr_e_invalid_char_greater=07090_E_Aquí no es permet el caràcter >
+% The shift operator requires the >> characters. Only one
+% of those characters was found.
+asmr_w_align_not_supported=07093_W_No es permet l'ús d'ALIGN
+asmr_e_no_inc_and_dec_together=07094_E_Inc i Dec no poden estar junts
+% Trying to use an increment and a decrement within the same
+% opcode on the 680x0. This is impossible.
+asmr_e_invalid_reg_list_in_movem=07095_E_El reglist no és vàlid pel movem
+% Trying to use the \var{movem} opcode with invalid registers
+% to save or restore.
+asmr_e_invalid_reg_list_for_opcode=07096_E_El reglist no és vàlid per l'opcode
+asmr_e_68020_mode_required=07097_E_Es requereix un mode de cpu més alt ($1)
+% Trying to use an instruction which is not supported in the current
+% cpu mode. Use a higher cpu generation to be able to use this
+% opcode in your assembler block
+asmr_w_unable_to_determine_reference_size_using_dword=07098_W_No s'ha especificat i no es pot determinar el tamany dels operands, s'està utilitzant DWORD com a predeterminat
+% You should specify explicitly a size for the reference, because
+% the compiler is unable to determine what size (byte,word,dword,etc.) it
+% should use for the reference. This warning is only used in Delphi mode where
+% it falls back to use DWORD as default.
+asmr_e_illegal_shifterop_syntax=07099_E_S'ha trobat un error de sintaxi mentre s'analitzava un operand desplaçat
+% ARM only, ARM assembler supports a so called shifter operand. The used syntax isn't
+% a valid shifter operand. Example for an operation with shifter operand:
+% \begin{verbatim}
+% asm
+% orr r2,r2,r2,lsl #8
+% end;
+% \end{verbatim}
+#
+# Assembler/binary writers
+#
+# 08018 is the last one used
+#
+asmw_f_too_many_asm_files=08000_F_Hi ha massa arxius d'assemblador oberts
+% With smartlinking enabled, there are too many assembler
+% files generated. Disable smartlinking.
+asmw_f_assembler_output_not_supported=08001_F_L'assemblador de sortida seleccionat no és compatible
+asmw_f_comp_not_supported=08002_F_No es permet l'ús de COMP
+asmw_f_direct_not_supported=08003_F_Direct no és compatible amb els escriptors binaris
+% Direct assembler mode is not supported for binary writers.
+asmw_e_alloc_data_only_in_bss=08004_E_Només es permet l'assignació de dades en la secció bss
+asmw_f_no_binary_writer_selected=08005_F_No s'ha seleccionat un escriptor binari
+asmw_e_opcode_not_in_table=08006_E_Asm: L'opcode $1 no és a la taula
+asmw_e_invalid_opcode_and_operands=08007_E_Asm: $1 la combinació d'opcode i operands no és vàlida
+asmw_e_16bit_not_supported=08008_E_Asm: No es permeten les referències de 16 Bits
+asmw_e_invalid_effective_address=08009_E_Asm: L'adreça actual no és vàlida
+asmw_e_immediate_or_reference_expected=08010_E_Asm: S'esperava immediat o referència
+asmw_e_value_exceeds_bounds=08011_E_Asm: el valor $1 excedeix el límit $2
+asmw_e_short_jmp_out_of_range=08012_E_Asm: El salt curt està fora de l'abast $1
+asmw_e_undefined_label=08013_E_Asm: L'etiqueta $1 no està definida
+asmw_e_comp_not_supported=08014_E_Asm: El tipus comp no està permès en aquest objectiu
+asmw_e_extended_not_supported=08015_E_Asm: El tipus Extended no està permès en aquest objectiu
+asmw_e_duplicate_label=08016_E_Asm: L'etiqueta $1 està duplicada
+asmw_e_redefined_label=08017_E_Asm: S'ha tornat a definir l'etiqueta $1
+asmw_e_first_defined_label=08018_E_Asm: Aquí s'ha definit primer
+asmw_e_invalid_register=08019_E_Asm: el registre $1 no és vàlid
+#
+# Executing linker/assembler
+#
+# 09034 is the last one used
+#
+# BeginOfTeX
+%
+% \section{Errors of assembling/linking stage}
+% This section lists errors that occur when the compiler is processing the
+% command line or handling the configuration files.
+% \begin{description}
+exec_w_source_os_redefined=09000_W_S'ha tornat a definir el SO d'origen
+exec_i_assembling_pipe=09001_I_S'està assemblant (canonada) $1
+exec_d_cant_create_asmfile=09002_E_No es pot crear el fitxer d'assemblador $1
+% The mentioned file can't be create. Check if you've
+% permission to create this file
+exec_e_cant_create_objectfile=09003_E_No es pot creat el fitxer objecte $1
+% The mentioned file can't be create. Check if you've
+% permission to create this file
+exec_e_cant_create_archivefile=09004_E_No es pot crear l'arxiu $1
+% The mentioned file can't be create. Check if you've
+% permission to create this file
+exec_w_assembler_not_found=09005_W_No s'ha trobat l'assemblador $1, s'està canviant a assemblament extern
+exec_t_using_assembler=09006_T_S'està utilitzant l'assemblador $1
+exec_w_error_while_assembling=09007_W_S'ha produït un error mentre s'assemblava el codi de sortida $1
+% There was an error while assembling the file using an external assembler.
+% Consult the documentation of the assembler tool to find out more information
+% on this error.
+exec_w_cant_call_assembler=09008_W_No es pot cridar l'assemblador, error $1 canviant a assemblament extern
+exec_i_assembling=09009_I_S'està assemblant $1
+exec_i_assembling_smart=09010_I_S'està assemblant amb enllaçament intel·ligent $1
+exec_w_objfile_not_found=09011_W_No s'ha trobat l'objecte $1, l'enllaçament pot fallar !
+% One of the object file is missing, and linking will probably fail.
+% Check your paths.
+exec_w_libfile_not_found=09012_W_No s'ha trobat la biblioteca $1, l'enllaçament pot fallar !
+% One of the library file is missing, and linking will probably fail.
+% Check your paths.
+exec_w_error_while_linking=09013_W_S'ha produït un error mentre s'enllaçava
+% Generic error while linking.
+exec_w_cant_call_linker=09014_W_No es pot cridar l'enllaçador, s'està canviant a l'enllaçament extern
+exec_i_linking=09015_I_S'està enllaçant $1
+exec_w_util_not_found=09016_W_No s'ha trobat l'utilitat $1, s'està canviant a enllaçament extern
+exec_t_using_util=09017_T_S'està utilitzant l'utilitat $1
+exec_e_exe_not_supported=09018_E_No es permet la creació d'executables
+exec_e_dll_not_supported=09019_E_No es permet la creació de biblioteques dinàmiques/compartides
+exec_i_closing_script=09020_I_S'està tancant la seqüència $1
+exec_w_res_not_found=09021_W_No s'ha trobat el compilador del recurs, s'està canviant a mode extern
+exec_i_compilingresource=09022_I_S'està compilant el recurs $1
+exec_t_unit_not_static_linkable_switch_to_smart=09023_T_No es pot enllaçar estàticament l'unitat $1, s'està canviant a enllaçament intel·ligent
+exec_t_unit_not_smart_linkable_switch_to_static=09024_T_No es pot utilitzar l'enllaçament intel·ligent amb l'unitat $1, s'està canviant a enllaçament estàtic.
+exec_t_unit_not_shared_linkable_switch_to_static=09025_T_No es pot utilitzar l'enllaçament compartit amb l'unitat $1, s'està canviant a enllaçament estàtic
+exec_e_unit_not_smart_or_static_linkable=09026_E_No es pot enllaçar l'unitat $1 ni estàticament ni dinàmicament
+exec_e_unit_not_shared_or_static_linkable=09027_E_No es pot utilitzar l'enllaçament compartit ni estàtic amb l'unitat $1.
+%\end{description}
+# EndOfTeX
+#
+# Executable information
+#
+execinfo_f_cant_process_executable=09128_F_No es pot post-processar l'executable $1
+execinfo_f_cant_open_executable=09129_F_No es pot obrir l'executable $1
+execinfo_x_codesize=09130_X_Tamany del codi: $1 octets
+execinfo_x_initdatasize=09131_X_Tamany de les dades inicialitzades: $1 octets
+execinfo_x_uninitdatasize=09132_X_Tamany de les dades sense inicialitzar: $1 octets
+execinfo_x_stackreserve=09133_X_Espai reservat per la pila: $1 octets
+execinfo_x_stackcommit=09134_X_Espai utilitzat per la pila: $1 octets
+#
+# Unit loading
+#
+# 10041 is the last used one
+#
+# BeginOfTeX
+% \section{Unit loading messages.}
+% This section lists all messages that can occur when the compiler is
+% loading a unit from disk into memory. Many of these messages are
+% informational messages.
+% \begin{description}
+unit_t_unitsearch=10000_T_S'està cercant l'unitat: $1
+% When you use the \var{-vt}, the compiler tells you where it tries to find
+% unit files.
+unit_t_ppu_loading=10001_T_S'està carregant la PPU $1
+% When the \var{-vt} switch is used, the compiler tells you
+% what units it loads.
+unit_u_ppu_name=10002_U_Nom de la PPU: $1
+% When you use the \var{-vu} flag, the unit name is shown.
+unit_u_ppu_flags=10003_U_Senyaladors de la PPU: $1
+% When you use the \var{-vu} flag, the unit flags are shown.
+unit_u_ppu_crc=10004_U_Crc de la PPU: $1
+% When you use the \var{-vu} flag, the unit CRC check is shown.
+unit_u_ppu_time=10005_U_Temps de la PPU: $1
+% When you use the \var{-vu} flag, the unit time is shown.
+unit_u_ppu_file_too_short=10006_U_El fitxer PPU és massa curt
+% When you use the \var{-vu} flag, the unit time is shown.
+unit_u_ppu_invalid_header=10007_U_L'encapçalament de la PPU no és vàlid (no hi ha PPU al principi)
+% A unit file contains as the first three bytes the ascii codes of \var{PPU}
+unit_u_ppu_invalid_version=10008_U_La versió $1 de la PPU no és vàlida
+% This unit file was compiled with a different version of the compiler, and
+% cannot be read.
+unit_u_ppu_invalid_processor=10009_U_La PPU està compilada per a un altre processador
+% This unit file was compiled for a different processor type, and
+% cannot be read
+unit_u_ppu_invalid_target=10010_U_La PPU està compilada per un altre objectiu
+% This unit file was compiled for a different processor type, and
+% cannot be read
+unit_u_ppu_source=10011_U_font PPU: $1
+% When you use the \var{-vu} flag, the unit CRC check is shown.
+unit_u_ppu_write=10012_U_S'està escrivint $1
+% When you specify the \var{-vu} switch, the compiler will tell you where it
+% writes the unit file.
+unit_f_ppu_cannot_write=10013_F_No es pot escriure el fitxer PPU
+% An error occurred when writing the unit file.
+unit_f_ppu_read_error=10014_F_No es pot llegir el fitxer PPU
+% This means that the unit file was corrupted, and contains invalid
+% information. Recompilation will be necessary.
+unit_f_ppu_read_unexpected_end=10015_F_No s'esperava el final del fitxer PPU
+% Unexpected end of file. This may mean that the PPU file is
+% corrupted.
+unit_f_ppu_invalid_entry=10016_F_Entrada invàlida en el fitxer PPU: $1
+% The unit the compiler is trying to read is corrupted, or generated with a
+% newer version of the compiler.
+unit_f_ppu_dbx_count_problem=10017_F_Hi ha hagut un problema calculant el Dbx de la PPU
+% There is an inconsistency in the debugging information of the unit.
+unit_e_illegal_unit_name=10018_E_El nom de l'unitat és il·legal: $1
+% The name of the unit doesn't match the file name.
+unit_f_too_much_units=10019_F_Hi ha massa unitats
+% \fpc has a limit of 1024 units in a program. You can change this behavior
+% by changing the \var{maxunits} constant in the \file{files.pas} file of the
+% compiler, and recompiling the compiler.
+unit_f_circular_unit_reference=10020_F_Hi ha una referència circular entre les unitats $1 i $2
+% Two units are using each other in the interface part. This is only allowed
+% in the \var{implementation} part. At least one unit must contain the other one
+% in the \var{implementation} section.
+unit_f_cant_compile_unit=10021_F_No es pot compilar l'unitat $1, no hi ha les fonts disponibles
+% A unit was found that needs to be recompiled, but no sources are
+% available.
+unit_f_cant_find_ppu=10022_F_No es pot trobar l'unitat $1
+% You tried to use a unit of which the PPU file isn't found by the
+% compiler. Check your config files for the unit pathes
+unit_w_unit_name_error=10023_W_No es pot trobar l'unitat $1, però hi ha la $2
+unit_f_unit_name_error=10024_F_S'estava cercant l'unitat $1, però s'ha trobat $2
+% Dos truncation of 8 letters for unit PPU files
+% may lead to problems when unit name is longer than 8 letters.
+unit_w_switch_us_missed=10025_W_Per compilar l'unitat System es necessita el commutador -Us
+% When recompiling the system unit (it needs special treatment), the
+% \var{-Us} must be specified.
+unit_f_errors_in_unit=10026_F_Hi ha hagut $1 errors compilant el mòdul, s'ha aturat!
+% When the compiler encounters a fatal error or too many errors in a module
+% then it stops with this message.
+unit_u_load_unit=10027_U_S'està carregant desde $1 ($2) l'unitat $3
+% When you use the \var{-vu} flag, which unit is loaded from which unit is
+% shown.
+unit_u_recompile_crc_change=10028_U_S'està tornant a compilar $1, s'ha canviat la suma de verificació a $2
+unit_u_recompile_source_found_alone=10029_U_S'està tornant a compilar $1, només s'han trobat les fonts
+% When you use the \var{-vu} flag, these messages tell you why the current
+% unit is recompiled.
+unit_u_recompile_staticlib_is_older=10030_U_S'està tornant a compilar l'unitat, la biblioteca estàtica és més vella que el fitxer ppu
+% When you use the \var{-vu} flag, the compiler warns if the static library
+% of the unit are older than the unit file itself.
+unit_u_recompile_sharedlib_is_older=10031_U_S'està tornant a compilar l'unitat, la biblioteca compartida és més vella que el fitxer ppu
+% When you use the \var{-vu} flag, the compiler warns if the shared library
+% of the unit are older than the unit file itself.
+unit_u_recompile_obj_and_asm_older=10032_U_S'està tornant a compilar l'unitat, obj i asm son més vells que el fitxer ppu
+% When you use the \var{-vu} flag, the compiler warns if the assembler of
+% object file of the unit are older than the unit file itself.
+unit_u_recompile_obj_older_than_asm=10033_U_S'està tornant a compilar l'unitat, obj és més vell que asm
+% When you use the \var{-vu} flag, the compiler warns if the assembler
+% file of the unit is older than the object file of the unit.
+unit_u_parsing_interface=10034_U_S'està analitzant l'interfície de $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% parsing the interface part of the unit
+unit_u_parsing_implementation=10035_U_S'està analitzant l'implementació de $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% parsing the implementation part of the unit
+unit_u_second_load_unit=10036_U_S'està carregant l'unitat $1 per segona vegada
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% recompiling a unit for the second time. This can happend with interdepend
+% units.
+unit_u_check_time=10037_U_S'està comprovant el fitxer PPU $1 temps $2
+% When you use the \var{-vu} flag, the compiler show the filename and
+% date and time of the file which a recompile depends on
+### The following two error msgs is currently disabled
+# unit_h_cond_not_set_in_last_compile=10038_H_El condicional $1 no ha estat inicialitzat al començament de la última compilació de $2
+# % When recompilation of an unit ies required the compiler will check that
+# % the same conditionals are set for the recompilation. The compiler has
+# % found a conditional that currently is defined, but was not used the last
+# % time the unit was compiled
+# unit_h_cond_set_in_last_compile=10039_H_El condicional $1 ha estat inicialitzat al començament de la última compilació de $2
+# % When recompilation of an unit is required the compiler will check that
+# % the same conditionals are set for the recompilation. The compiler has
+# % found a conditional that was used the last time the unit was compiled, but
+# % the conditional is currently not defined.
+unit_w_cant_compile_unit_with_changed_incfile=10040_W_No es pot tornar a compilar l'unitat $1, però s'han trobat fitxers inclosos modificats
+% A unit was found to have modified include files, but
+% some source files were not found, so recompilation is impossible.
+unit_h_source_modified=10041_H_El fitxer $1 és més nou que la versió de la PPU $2
+% A modified source file for a unit was found that was compiled with the
+% release flag (-Ur). The unit will not implicitly be recompiled because
+% this release flag is set.
+unit_u_ppu_invalid_fpumode=10042_U_S'està utilitzant una unitat la qual no ha estat compilada amb el mode FPU correcte
+% Trying to compile code while using units which were not compiled with
+% the same floating point format mode. Either all code should be compiled
+% with FPU emulation on, or with FPU emulation off.
+unit_u_loading_interface_units=10043_U_S'estan carregant les unitats d'INTERFACE desde $1
+% When you use the \var{-vu} flag, the compiler warms that it starts
+% loading the units defined in the interface part of the unit
+unit_u_loading_implementation_units=10044_U_S'estan carregant les unitat d'IMPLEMENTATION desde $1
+% When you use the \var{-vu} flag, the compiler warms that it starts
+% loading the units defined in the implementation part of the unit
+unit_u_interface_crc_changed=10045_U_L'interfície CRC ha canviat per la unitat $1
+% When you use the \var{-vu} flag, the compiler warms that it the
+% CRC calculated for the interface has been changed after the implementation
+% has been parsed
+unit_u_implementation_crc_changed=10046_U_L'implementació CRC ha canviat per l'unitat $1
+% When you use the \var{-vu} flag, the compiler warms that it the
+% CRC calculated has been changed after the implementation
+% has been parsed
+unit_u_finished_compiling=10047_U_S'ha acabat la compilació de l'unitat $1
+% When you use the \var{-vu} flag, the compiler warms that it
+% has finished compiling the unit
+unit_u_add_depend_to=10048_U_S'ha afegit la dependència de $1 a $2
+% When you use the \var{-vu} flag, the compiler warms that it
+% has added a dependency between the two units
+unit_u_no_reload_is_caller=10049_U_No es torna a carregar, es crida: $1
+% When you use the \var{-vu} flag, the compiler warms that it
+% has will not reload the unit because it is the unit that wants
+% to load this unit
+unit_u_no_reload_in_second_compile=10050_U_No es torna a carregar, ja és en segona compilació: $1
+% When you use the \var{-vu} flag, the compiler warms that it
+% has will not reload the unit because it is already in a second recompile
+unit_u_flag_for_reload=10051_U_Senyalador per la recàrrega: $1
+% When you use the \var{-vu} flag, the compiler warms that it
+% has to reload the unit
+unit_u_forced_reload=10052_U_Es torna a carregar forçadament
+% When you use the \var{-vu} flag, the compiler warms that it
+% has is reloading the unit because it was required
+unit_u_previous_state=10053_U_Estat previ de $1: $2
+% When you use the \var{-vu} flag, the compiler shows the
+% previous state of the unit
+unit_u_second_compile_unit=10054_U_S'està compilant l'unitat $1 per segona vegada
+% When you use the \var{-vu} flag, the compiler warms that it starts
+% recompiling a unit for the second time. This can happend with independent
+% units
+unit_u_loading_unit=10055_U_S'està carregant l'unitat $1
+% When you use the \var{-vu} flag, the compiler warms that it starts
+% loading the unit
+unit_u_finished_loading_unit=10056_U_S'ha acabat la càrrega de l'unitat $1
+% When you use the \var{-vu} flag, the compiler warms that it finished
+% loading the unit
+unit_u_registering_new_unit=10057_U_S'està registrant l'unitat nova $1
+% When you use the \var{-vu} flag, the compiler warms that it has
+% found a new unit and registers it in the internal lists
+unit_u_reresolving_unit=10058_U_S'està tornant a resoldre l'unitat $1
+% When you use the \var{-vu} flag, the compiler warms that it
+% has to recalculate the internal data of the unit
+unit_u_skipping_reresolving_unit=10059_U_No es torna a resoldre l'unitat $1, encara s'estan carregant les unitats utilitzades
+% When you use the \var{-vu} flag, the compiler warms that it
+% skips to recalculate the internal data of the unit because there
+% is no data to racalculate
+% \end{description}
+# EndOfTeX
+#
+# Options
+#
+# 11039 is the las used one
+#
+option_usage=11000_O_$1 [opcions] <fitxer-entrada> [opcions]
+# BeginOfTeX
+%
+% \section{Command-line handling errors}
+% This section lists errors that occur when the compiler is processing the
+% command line or handling the configuration files.
+% \begin{description}
+option_only_one_source_support=11001_W_Només es permet un fitxer font
+% You can specify only one source file on the command line. The first
+% one will be compiled, others will be ignored. This may indicate that
+% you forgot a \var{'-'} sign.
+option_def_only_for_os2=11002_W_El fitxer DEF només pot ser creat per OS/2
+% This option can only be specified when you're compiling for OS/2
+option_no_nested_response_file=11003_E_No es permeten els fitxers de resposta niats
+% you cannot nest response files with the \var{@file} command-line option.
+option_no_source_found=11004_F_No hi ha el nom del fitxer font en la línia d'ordres
+% The compiler expects a source file name on the command line.
+option_no_option_found=11005_N_No hi ha cap opció dins del fitxer de configuració $1
+% The compiler didn't find any option in that config file.
+option_illegal_para=11006_E_El paràmetre $1 és il·legal
+% You specified an unknown option.
+option_help_pages_para=11007_H_-? escriu las pàgines de l'ajuda
+% When an unknown option is given, this message is diplayed.
+option_too_many_cfg_files=11008_F_Hi ha massa fitxers de configuració niats
+% You can only nest up to 16 config files.
+option_unable_open_file=11009_F_No es pot obrir el fitxer $1
+% The option file cannot be found.
+option_reading_further_from=11010_N_S'estan llegint les opcions addicionals de $1
+% Displayed when you have notes turned on, and the compiler switches
+% to another options file.
+option_target_is_already_set=11011_W_L'objectiu ja està posat a $1
+% Displayed if more than one \var{-T} option is specified.
+option_no_shared_lib_under_dos=11012_W_Les biblioteques compartides no estan permeses en la plataforma DOS, es canvia a estàtiques
+% If you specify \var{-CD} for the \dos platform, this message is displayed.
+% The compiler supports only static libraries under \dos
+option_too_many_ifdef=11013_F_Hi ha massa IF(N)DEFs
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_too_many_endif=11014_F_Hi ha massa ENDIFs
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_too_less_endif=11015_F_Hi ha un condicional obert al final del fitxer
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_no_debug_support=11016_W_Aquest executable no permet la generació d'informació del depurador
+% It is possible to have a compiler executable that doesn't support
+% the generation of debugging info. If you use such an executable with the
+% \var{-g} switch, this warning will be displayed.
+option_no_debug_support_recompile_fpc=11017_H_Proveu de tornar a compilar amb -dGDB
+% It is possible to have a compiler executable that doesn't support
+% the generation of debugging info. If you use such an executable with the
+% \var{-g} switch, this warning will be displayed.
+option_obsolete_switch=11018_E_Esteu utilitzant el commutador obsolet $1
+% this warns you when you use a switch that is not needed/supported anymore.
+% It is recommended that you remove the switch to overcome problems in the
+% future, when the switch meaning may change.
+option_obsolete_switch_use_new=11019_E_Esteu utilitzant el commutador obsolet $1, si us plau, utilitzeu $2
+% this warns you when you use a switch that is not supported anymore. You
+% must now use the second switch instead.
+% It is recommended that you change the switch to overcome problems in the
+% future, when the switch meaning may change.
+option_switch_bin_to_src_assembler=11020_N_S'està canviant a assemblador d'escriptura del codi font a predeterminat
+% this notifies you that the assembler has been changed because you used the
+% -a switch which can't be used with a binary assembler writer.
+option_incompatible_asm=11021_W_La sortida de l'assemblador seleccionada "$1" no és compatible amb "$2"
+option_asm_forced=11022_W_S'utilitza l'assemblador "$1" forçadament
+% The assembler output selected can not generate
+% object files with the correct format. Therefore, the
+% default assembler for this target is used instead.
+option_using_file=11026_T_S'estan llegint les opcions del fitxer $1
+% Options are also read from this file
+option_using_env=11027_T_S'estan llegint les opcions des de l'entorn $1
+% Options are also read from this environment string
+option_handling_option=11028_D_S'està gestionant l'opció "$1"
+% Debug info that an option is found and will be handled
+option_help_press_enter=11029__*** Premeu <Intro> ***
+option_start_reading_configfile=11030_H_S'està començant a llegir el fitxer de configuració $1
+% Starting of config file parsing.
+option_end_reading_configfile=11031_H_S'ha acabat de llegir el fitxer de configuració $1
+% End of config file parsing
+option_interpreting_option=11032_D_S'està executant l'opció "$1"
+option_interpreting_firstpass_option=11036_D_S'està executant l'opció "$1" per 1ª vegada
+option_interpreting_file_option=11033_D_S'està executant l'opció del fitxer "$1"
+option_read_config_file=11034_D=11034_D_S'està llegint el fitxer de configuració "$1"
+option_found_file=11035_D_S'ha trobat el nom del fitxer font "$1"
+% Additional infos about options, displayed
+% when you have debug option turned on.
+option_code_page_not_available=11039_E_La pàgina del codi no està disponible
+%\end{description}
+# EndOfTeX
+
+#
+# Logo (option -l)
+#
+option_logo=11023_[
+Free Pascal Compiler versió $FPCFULLVERSION [$FPCDATE] per $FPCCPU
+Copyright (c) 1993-2011 per Florian Klaempfl
+]
+
+#
+# Info (option -i)
+#
+option_info=11024_[
+Free Pascal Compiler versió $FPCVERSION
+
+Data del compilador : $FPCDATE
+CPU del compilador : $FPCCPU
+
+Plataformes compatibles :
+ $OSTARGETS
+
+Aquest programa ve sota la Llicència Pública General de GNU
+Per a més informació llegiu COPYING.FPC
+
+Comuniqueu les errades, suggeriments, etc a:
+ http://bugs.freepascal.org
+o
+ bugs@freepascal.org
+]
+
+#
+# Help pages (option -? and -h)
+#
+# The first character on the line indicates who will display this
+# line, the current possibilities are :
+# * = every target
+# 3 = 80x86 targets
+# 6 = 680x0 targets
+# e = in extended debug mode only
+# P = PowerPC targets
+# S = Sparc targets
+# V = Virtual machine targets
+# The second character also indicates who will display this line,
+# (if the above character was TRUE) the current possibilities are :
+# * = everyone
+# g = with GDB info supported by the compiler
+# O = OS/2
+# L = UNIX systems
+# The third character represents the indentation level.
+#
+option_help_pages=11025_[
+**0*_Poseu + després d'un commutador booleà per activar-lo, - per desactivar-lo
+**1a_El compilador no eliminarà el fitxer d'assemblador generat
+**2al_Escriu les línies del codi font en el fitxer de l'assemblador
+**2an_Escriu l'informació del node en el fitxer d'assemblador
+*L2ap_Utilitza canonades en lloc de crear fitxers temporals d'assemblador
+**2ar_Escriu info.d'alotj/desalotj del registre en el fitxer d'assemblador
+**2at_Escriu info.d'alotj/desalotj temporal en el fitxer d'assemblador
+**1A<x>_format de la sortida:
+**2Adefault_Utilitza assemblador predeterminat
+3*2Aas_Utilitza assemblador GNU AS
+3*2Anasmcoff_fitxer coff (Go32v2) utilitzant Nasm
+3*2Aasmelf_fitxer elf32 (Linux) utilitzant Nasm
+3*2Anasmwin32_fitxer objecte Win32 utilitzant Nasm
+3*2Anasmwdosx_fitxer objecte Win32/WDOSX utilitzant Nasm
+3*2Awasm_fitxer objecte utilitzant Wasm (Watcom)
+3*2Anasmobj_fitxer objecte utilitzant Nasm
+3*2Amasm_fitxer objecte utilitzant Masm (Microsoft)
+3*2Atasm_fitxer objecte utilitzant Tasm (Borland)
+3*2Aelf_elf32 (Linux) utilitzant escriptor intern
+3*2Acoff_coff (Go32v2) utilitzant escriptor intern
+3*2Apecoff_pecoff (Win32) utilitzant escriptor intern
+4*2Aas_assemblar utilitzant el GNU AS
+6*2Aas_fitxer objecte Unix utilitzant GNU AS
+6*2Agas_assemblador GNU Motorola
+6*2Amit_sintaxi MIT (antiga GAS)
+6*2Amot_assemblador Motorola estàndard
+A*2Aas_assemblar utilitzant GNU AS
+P*2Aas_assemblar utilitzant GNU AS
+S*2Aas_assemblar utilitzant GNU AS
+**1b_Genera informació de navegador
+**2bl_Genera informació dels símbols locals
+**1B_Munta tots els mòduls
+**1C<x>_Opcions de generació del codi:
+**2Cc<x>_predetermina la convenció de crida a <x>
+**2CD_Crea biblioteca dinàmica
+**2Ce_Compilació amb opcodes emulats de coma flotant
+**2Cf<x>_Selecciona instrucció fpu a utilitzar per <x>
+**2Cg_Genera codi PIC
+**2Ch<n>_<n> octets de la pila (entre 1023 i 67107840)
+**2Ci_Comprova E/S
+**2Cn_Omet l'enllaçament
+**2Co_Comprova el desbordament de les operacions amb enters
+**2Cr_Comprova l'abast
+**2CR_Verifica la validesa de la crida dels objectes del mètode
+**2Cs<n>_Posa el tamany de la pila a <n>
+**2Ct_Comprova la pila
+**2CX_Crea també biblioteca enllaçada intel·ligentment
+**1d<x>_Defineix el símbol <x>
+**1D_Genera un fitxer DEF
+**2Dd<x>_Posa la descripció a <x>
+**2Dv<x>_Posa la versió de DLL a <x>
+*O2Dw_Aplicació PM
+**1e<x>_Posa el camí a l'executable
+**1E_Igual que -Cn
+**1F<x>_Posa els noms dels fitxers i els camins:
+**2Fa<x>[,y]_Carrega primer les unitats <x> i [y], abans d'analitzar USES
+**2Fc<x>_Posa la pàgina del codi d'entrada a <x>
+**2FD<x>_Posa el directori on buscar les utilitats del compilador
+**2Fe<x>_Redirigeix la sortida dels errors a <x>
+**2FE<x>_Posa el path de sortida d'executables i unitats a <x>
+**2Fi<x>_Afegeix <x> al camí dels inclosos
+**2Fl<x>_Afegeix <x> al camí de les llibreries
+**2FL<x>_Utilitza <x> com enllaçador dinàmic
+**2Fo<x>_Afegeix <x> al camí dels objectes
+**2Fr<x>_Carrega el fitxer de missatges d'error <x>
+**2Fu<x>_Afegeix <x> al camí de les unitats
+**2FU<x>_Posa camí sortida de les unitats a <x>, substitueix -FE
+*g1g_Genera informació del depurador:
+*g2gc_genera controls pels punters
+*g2gd_Utilitza dbx
+*g2gg_Utilitza gsym
+*g2gh_Utilitza l'unitat de traçat de la pila (depura pèrdua de memòria)
+*g2gl_Utilitza l'unitat d'info. per mostrar +info per seguiments inversos
+*g2gv_Genera programes traçables amb valgrind
+*g2gw_Genera informació de depuració dwarf
+**1i_Informació:
+**2iD_Retorna la data del compilador
+**2iV_Retorna la versió del compilador
+**2iSO_Retorna el SO d'origen
+**2iSP_Retorna el processador d'origen
+**2iTO_Retorna el SO de destí
+**2iTP_Retorna el processador de destí
+**1I<x>_Afegeix <x> a la trajec.d'afegits
+**1k<x>_Passa <x> a l'enllaçador
+**1l_Escriu el logotipus
+**1M<x>_Fica el mode del llenguatge a <x>
+**2Mfpc_dialecte Free Pascal (predeterminat)
+**2Mobjfpc_Activa algunes extensions Delphi 2
+**2Mdelphi_Intenta ser compatible amb Delphi
+**2Mtp_Intenta ser compatible amb TP/BP 7.0
+**2Mgpc_Intenta ser compatible amb gpc
+**2Mmacpas_Intenta ser compatible amb dialectes Pascal del Macintosh
+**1n_No llegeix el fitxer de configuració predeterminat
+**1o<x>_Canvia el nom de l'executable produït a <x>
+**1O<x>_optimitzacions:
+3*2Og_genera codi més petit
+3*2OG_genera codi més ràpid (predeterminat)
+**2Or_manté determinades variables en els registres
+3*2Ou_habilita optimitzacions incertes (mireu docs)
+3*2O1_optimitzacions de nivell 1 (ràpides)
+3*2O2_optimitzacions de nivell 2 (-O1 + més lentes)
+3*2O3_optimitzacions de nivell 3 (-O2 repetidament, max 5 vegades)
+3*2Op<x>_processador de destí:
+3*3Op1_posa el processador de destí a 386/486
+3*3Op2_posa el processador de destí a Pentium/PentiumMMX (r)
+3*3Op3_posa el processador de destí a PPro/PII/c6x86/K6 (r)
+6*2Og_genera codi més petit
+6*2OG_genera codi més ràpid (predeterminat)
+6*2Ox_optimitza al màxim (Encara no és segur !!!)
+6*2O0_posa el processador de destí a MC68000
+6*2O2_posa el processador de destí a MC68020+ (predeterminat)
+**1pg_genera codi de perfil per gprof (defineix FPC_PROFILE)
+**1R<x>_Estil de lectura de l'assemblador:
+**2Rdefault_utilitza l'assemblador predeterminat
+3*2Ratt_llegeix assemblador d'estil AT&T
+3*2Rintel_llegeix assemblador d'estil Intel
+6*2RMOT_llegeix assemblador d'estil Motorola
+**1S<x>_Opcions de sintaxi:
+**2S2_Igual que -Mobjfpc
+**2Sc_Permet operadors tipus C (*=,+=,/= i -=)
+**2Sa_Inclou assertion code
+**2Sd_Igual que -Mdelphi
+**2Se_opcions d'error <x> és una combinació del següent:
+**3*_<n>: el compilador s'atura després de <n> errors (predeterminat és 1)
+**3*_w: el compilador s'atura també després dels avisos
+**3*_n: el compilador s'atura també després de les notes
+**3*_h: el compilador s'atura també després dels suggeriments
+**2Sg_Permet LABEL i GOTO
+**2Sh_Utilitza ansistrings
+**2Si_Permet INLINE estil C++
+**2SI<x>_posa l'estil de l'interfície a <x>
+**3SIcom_interfície compatible amb COM (predeterminat)
+**3SIcorba_interfície compatible amb CORBA
+**2Sm_Permet macros tipus C (globals)
+**2So_Igual que -Mtp
+**2Sp_Igual que -Mgpc
+**2Ss_El nom del constructor ha de ser init (destructor = done)
+**1s_No cridis l'assemblador ni l'enllaçador
+**2sh_Genera la seqüència per enllaçar a l'anfitrió
+**2st_Genera la seqüència per enllaçar al destí
+**2sr_Salta la fase de localització de registres (utilitzeu amb -alr)
+**1T<x>_sistema operatiu de destí:
+3*2Termx_OS/2 via EMX (incloent extensor EMX/RSX)
+3*2Tfreebsd_FreeBSD
+3*2go32v2_versió 2 de DJ Deloire DOS extender
+3*2Tlinux_Linux
+3*2Tnetbsd_NetBSD
+3*2Tnetware_Novell Netware Module (clib)
+3*2Tnetwlibc_Novell Netware Module (libc)
+3*2Topenbsd_OpenBSD
+3*2Tos2_OS/2 eComStation
+3*2Tsunos_SunOS/Solaris
+3*2Twatcom_Watcom compatible DOS extender
+3*2Twdosx_WDOSX DOS extender
+3*2Twin32_Windows 32 Bit
+4*2Tlinux_Linux
+6*2Tamiga_Commodore Amiga
+6*2Tatari_Atari ST/STe/TT
+6*2Tlinux_Linux-68k
+6*2Tmacos_Macintosh m68k (no compatible)
+6*2Tpalmos_PalmOS
+A*2Tlinux_Linux
+P*2Tdarwin_Darwin i MacOS X en PowerPC
+P*2Tlinux_Linux en PowerPC
+P*2Tmacos_MacOS (clàssic) en PowerPC
+P*2Tmorphos_MorphOS
+S*2Tlinux_Linux
+**1u<x>_Indefineix el símbol <x>
+**1U_Opcions de l'unitat:
+**2Un_No comprovar el nom de l'unitat
+**2Ur_generate release unit files
+**2Us_Compila una unitat del sistema
+**1v<x>_Detall. <x> és una combinació de les següents lletres :
+**2*_e : mostra errors (predet.) 0 : no mostrar res (excepte errors)
+**2*_w : mostra avisos u : mostra info de les unitats
+**2*_n : mostra notes t : mostra els fitxers selec./utilitz.
+**2*_h : mostra suggeriments c : mostra els condicionals
+**2*_i : mostra informació general d : mostra l'informació del depurador
+**2*_l : mostra números de línia r : compatibilitat Rhide/GCC
+**2*_a : mostra-ho tot x : informació de l'executable (win32)
+**2*_v : escriu fpcdebug.txt amb p : escriu tree.log amb arbre analitzat
+**2*_ molta informació de la depuració
+3*1W<x>_Opcions per a plataformes tipus Win32
+3*2WB<x>_Imatge a valor hexadecimal <x>
+3*2WC_Especifica aplicació tipus consola
+3*2WD_Utilitza DEFFILE per exportar les funcions de DLL o EXE
+3*2WF_Especifica aplicació tipus pantalla sencera (només OS/2)
+3*2WG_Especifica aplicació de tipus gràfic
+3*2WN_No generar codi deslocalitzat (necessari per la depuració)
+3*2WR_Genera codi reagrupat
+P*2WC_Especifica aplicació tipus consola (només MacOS)
+P*2WG_Especifica aplicació gràfica (només MacOS)
+P*2WT_Especifica aplicació tipus eina (eina MPW, només MacOS)
+**1X_Opcions de l'executable:
+**2Xc_passa --shared a l'enllaçador (només Unix)
+**2Xd_no utilitzar el camí normalitzat de biblioteques (necessària per compilar entre diferents SO)
+**2XD_intenta enllaçar les unitats dinàmicament (defineix FPC_LINK_DYNAMIC)
+**2XP<x>_avant posar el prefix <x> als noms de les utilitats binaries
+**2Xr<x>_posa el camí de les biblioteques a <x> (necessari per compilar entre diferents SO)
+**2Xs_elimina tots els símbols de l'executable
+**2XS_intenta enllaçar les unitats estàticament (predeterminat) (defineix FPC_LINK_STATIC)
+**2Xt_enllaça amb biblioteques estàtiques (es passa -static a l'enllaçador)
+**2XX_intenta enllaçar les unitats intel·ligentment (defineix FPC_LINK_SMART)
+**1*_
+**1?_mostra aquesta ajuda
+**1h_mostra aquesta ajuda sense esperar
+]
+
+#
+# The End...
diff --git a/closures/compiler/msg/errord.msg b/closures/compiler/msg/errord.msg
new file mode 100644
index 0000000000..9013b18937
--- /dev/null
+++ b/closures/compiler/msg/errord.msg
@@ -0,0 +1,3417 @@
+#
+# German (alternative, LATIN-US DOS) Language File for Free Pascal
+# Latest updates contributed by Karl-Michael Schindler aka mischi
+# <karl-michael.schindler at web.de>
+#
+# Based on errore.msg of SVN revision 18275
+#
+# This file is part of the Free Pascal Compiler
+# Copyright (c) 1998-2010 by the Free Pascal Development team
+#
+# See the file COPYING.FPC, included in this distribution,
+# for details about the copyright.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#
+#
+# The constants are build in the following order:
+# <part>_<type>_<txtidentifier>
+#
+# <part> is the part of the compiler the message is used
+# asmr_ assembler parsing
+# asmw_ assembler writing/binary writers
+# unit_ unit handling
+# scan_ scanner
+# parser_ parser
+# type_ type checking
+# general_ general info
+# exec_ calls to assembler, linker, binder
+# link_ internal linker
+#
+# <type> the type of the message it should normally used for
+# f_ fatal error
+# e_ error
+# w_ warning
+# n_ note
+# h_ hint
+# i_ info
+# l_ add linenumber
+# u_ used
+# t_ tried
+# c_ conditional
+# d_ debug message
+# x_ executable informations
+# o_ normal (e.g., "press enter to continue")
+#
+
+#
+# General
+#
+# 01025 is the last used one
+#
+# BeginOfTeX
+% \section{General compiler messages}
+% This section gives the compiler messages which are not fatal, but which
+% display useful information. The number of such messages can be
+% controlled with the various verbosity level \var{-v} switches.
+% \begin{description}
+general_t_compilername=01000_T_Compiler: $1
+% When the \var{-vt} switch is used, this line tells you what compiler
+% is used.
+general_d_sourceos=01001_D_Quellbetriebssystem: $1
+% When the \var{-vd} switch is used, this line tells you what the source
+% operating system is.
+general_i_targetos=01002_I_Zielbetriebssystem: $1
+% When the \var{-vd} switch is used, this line tells you what the target
+% operating system is.
+general_t_exepath=01003_T_Der Pfad der ausfhrbaren Datei ist: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for its binaries.
+general_t_unitpath=01004_T_Der Unitpfad ist: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for compiled units. You can set this path with the \var{-Fu} option.
+general_t_includepath=01005_T_Der Includepfad ist: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for its include files (files used in \var{\{\$I xxx\}} statements).
+% You can set this path with the \var{-Fi} option.
+general_t_librarypath=01006_T_Der Bibliothekspfad ist: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for the libraries. You can set this path with the \var{-Fl} option.
+general_t_objectpath=01007_T_Der Objektdateienpfad ist: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for object files you link in (files used in \var{\{\$L xxx\}} statements).
+% You can set this path with the \var{-Fo} option.
+general_i_abslines_compiled=01008_I_$1 Zeilen bersetzt, $2 Sekunden $3
+% When the \var{-vi} switch is used, the compiler reports the number
+% of lines compiled, and the time it took to compile them (real time,
+% not program time).
+general_f_no_memory_left=01009_F_Speicher voll
+% The compiler doesn't have enough memory to compile your program. There are
+% several remedies for this:
+% \begin{itemize}
+% \item If you're using the build option of the compiler, try compiling the
+% different units manually.
+% \item If you're compiling a huge program, split it up into units, and compile
+% these separately.
+% \item If the previous two don't work, recompile the compiler with a bigger
+% heap. (You can use the \var{-Ch} option for this, \seeo{Ch}.)
+% \end{itemize}
+general_i_writingresourcefile=01010_I_Resourcestringtabellendatei $1 wird geschrieben
+% This message is shown when the compiler writes the Resource String Table
+% file containing all the resource strings for a program.
+general_e_errorwritingresourcefile=01011_E_Fehler beim Schreiben der Resourcestringtabellendatei: $1
+% This message is shown when the compiler encounters an error when writing
+% the Resource String Table file.
+general_i_fatal=01012_I_Fataler Fehler:
+% Prefix for Fatal Errors.
+general_i_error=01013_I_Fehler:
+% Prefix for Errors.
+general_i_warning=01014_I_Warnung:
+% Prefix for Warnings.
+general_i_note=01015_I_Anmerkung:
+% Prefix for Notes.
+general_i_hint=01016_I_Hinweis:
+% Prefix for Hints.
+general_e_path_does_not_exist=01017_E_Der Pfad "$1" existiert nicht
+% The specified path does not exist.
+general_f_compilation_aborted=01018_F_šbersetzen abgebrochen
+% Compilation was aborted.
+general_text_bytes_code=01019_bytes Code
+% The size of the generated executable code, in bytes.
+general_text_bytes_data=01020_bytes Daten
+% The size of the generated program data, in bytes.
+general_i_number_of_warnings=01021_I_$1 Warnung(en) ausgegeben
+% Total number of warnings issued during compilation.
+general_i_number_of_hints=01022_I_$1 Hinweis(e) ausgegeben
+% Total number of hints issued during compilation.
+general_i_number_of_notes=01023_I_$1 Anmerkung(en) ausgegeben
+% Total number of notes issued during compilation.
+general_f_ioerror=01024_F_I/O Fehler: $1
+% During compilation an I/O error happened which allows no further compilation.
+general_f_oserror=01025_F_Betriebsystemfehler: $1
+% During compilation an operanting system error happened which allows no further compilation.
+%
+% \end{description}
+# EndOfTeX
+
+#
+# Scanner
+#
+# 02088 is the last used one
+#
+% \section{Scanner messages.}
+% This section lists the messages that the scanner emits. The scanner takes
+% care of the lexical structure of the pascal file, i.e. it tries to find
+% reserved words, strings, etc. It also takes care of directives and
+% conditional compilation handling.
+% \begin{description}
+scan_f_end_of_file=02000_F_Unerwartetes Dateiende
+% this typically happens in one of the following cases:
+% \begin{itemize}
+% \item The source file ends before the final \var{end.} statement. This
+% happens mostly when the \var{begin} and \var{end} statements aren't
+% balanced;
+% \item An include file ends in the middle of a statement.
+% \item A comment was not closed.
+% \end{itemize}
+scan_f_string_exceeds_line=02001_F_Zeichenkette geht ber das Zeilenende hinaus
+% You forgot probably to include the closing ' in a string, so it occupies
+% multiple lines.
+scan_f_illegal_char=02002_F_Unzul„ssiges Zeichen "$1" ($2)
+% An illegal character was encountered in the input file.
+scan_f_syn_expected=02003_F_Syntaxfehler, "$1" erwartet, aber "$2" vorgefunden
+% This indicates that the compiler expected a different token than
+% the one you typed. It can occur almost anywhere it is possible to make an error
+% against the Pascal language.
+scan_t_start_include_file=02004_TL_Die Include-Datei $1 wird jetzt gelesen
+% When you provide the \var{-vt} switch, the compiler tells you
+% when it starts reading an included file.
+scan_w_comment_level=02005_W_Kommentarschachtelungstiefe $1 gefunden
+% When the \var{-vw} switch is used, then the compiler warns you if
+% it finds nested comments. Nested comments are not allowed in Turbo Pascal
+% and Delphi, and can be a possible source of errors.
+scan_n_ignored_switch=02008_N_Compilerschalter $1 wurde ignoriert
+% With \var{-vn} on, the compiler warns if it ignores a switch.
+scan_w_illegal_switch=02009_W_Compilerschalter $1 ist ungltig
+% You included a compiler switch (i.e. \var{\{\$... \}}) which the compiler
+% does not recognise.
+scan_w_switch_is_global=02010_W_Dieser Compilerschalter hat globale Auswirkung
+% The compiler switch is misplaced, and should be located at
+% the start of the unit or program.
+scan_e_illegal_char_const=02011_E_Ungltige Char-Konstante
+% This happens when you specify a character with its ASCII code, as in
+% \var{\#96}, but the number is either illegal, or out of range.
+scan_f_cannot_open_input=02012_F_Datei $1 kann nicht ge”ffnet werden
+% \fpc cannot find the program or unit source file you specified on the
+% command line.
+scan_f_cannot_open_includefile=02013_F_Includedatei $1 kann nicht ge”ffnet werden
+% \fpc cannot find the source file you specified in a \var{\{\$include ..\}}
+% statement.
+scan_e_illegal_pack_records=02015_E_Ungltige Record Ausrichtung "$1"
+% You are specifying \var{\{\$PACKRECORDS n\} } or \var{\{\$ALIGN n\} }
+% with an illegal value for \var{n}. For \$PACKRECORDS valid alignments are 1, 2, 4, 8, 16, 32, C,
+% NORMAL, DEFAULT, and for \$ALIGN valid alignments are 1, 2, 4, 8, 16, 32, ON,
+% OFF. Under mode MacPas \$ALIGN also supports MAC68K, POWER and RESET.
+scan_e_illegal_pack_enum=02016_E_Ungltige minimale Gr”sse der Aufz„hlung "$1"
+% You are specifying the \var{\{\$PACKENUM n\}} with an illegal value for
+% \var{n}. Only 1,2,4, NORMAL or DEFAULT is valid here.
+scan_e_endif_expected=02017_E_$ENDIF erwartet fr $1 $2 definiert in $3 Zeile $4
+% Your conditional compilation statements are unbalanced.
+scan_e_preproc_syntax_error=02018_E_Syntaxfehler im Argument einer $if Direktive
+% There is an error in the expression following the \var{\{\$if ..\}}, \var{\{\$ifc \}}
+% or \var{\{\$setc \}} compiler directives.
+scan_e_error_in_preproc_expr=02019_E_Syntaxfehler im Kontext einer $if Direktive
+% There is an error in the expression following the \var{\{\$if ..\}} compiler
+% directive.
+scan_w_macro_cut_after_255_chars=02020_W_Inhalt des Makros wurde nach der Auswertung bei 255 Zeichen abgeschnitten
+% The contents of macros cannot be longer than 255 characters.
+scan_e_endif_without_if=02021_E_ENDIF ohne IF(N)DEF
+% Your \var{\{\$IFDEF ..\}} and {\{\$ENDIF\}} statements aren't balanced.
+scan_f_user_defined=02022_F_Benutzerdefiniert: $1
+% A user defined fatal error occurred. See also the \progref
+scan_e_user_defined=02023_E_Benutzerdefiniert: $1
+% A user defined error occurred. See also the \progref
+scan_w_user_defined=02024_W_Benutzerdefiniert: $1
+% A user defined warning occurred. See also the \progref
+scan_n_user_defined=02025_N_Benutzerdefiniert: $1
+% A user defined note was encountered. See also the \progref
+scan_h_user_defined=02026_H_Benutzerdefiniert: $1
+% A user defined hint was encountered. See also the \progref
+scan_i_user_defined=02027_I_Benutzerdefiniert: $1
+% User defined information was encountered. See also the \progref
+scan_e_keyword_cant_be_a_macro=02028_E_Ein Makro, das den selben Namen wie ein Schlsselwort hat, wird ignoriert
+% You cannot redefine keywords with macros.
+scan_f_macro_buffer_overflow=02029_F_Makropufferberlauf w„hrend des Lesens oder Expandierens eines Makros
+% Your macro or it's result was too long for the compiler.
+scan_w_macro_too_deep=02030_W_Expansion des Makros berschreitet eine Makroschachtelungstiefe von 16
+% When expanding a macro macros have been nested to a level of 16.
+% The compiler will expand no further, since this may be a sign that
+% recursion is used.
+scan_w_wrong_styled_switch=02031_W_Compilerschalter innerhalb von Kommentaren der Form // werden nicht unterstzt
+% Compiler switches should be in normal Pascal style comments.
+scan_d_handling_switch=02032_DL_Bearbeite Schalter "$1"
+% When you set debugging info on (\var{-vd}) the compiler tells you when it
+% is evaluating conditional compile statements.
+scan_c_endif_found=02033_CL_ENDIF $1 bearbeitet
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifdef_found=02034_CL_IFDEF $1 bearbeitet, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifopt_found=02035_CL_IFOPT $1 bearbeitet, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_if_found=02036_CL_IF $1 bearbeitet, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifndef_found=02037_CL_IFNDEF $1 bearbeitet, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_else_found=02038_CL_ELSE $1 bearbeitet, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_skipping_until=02039_CL_Quelltext wird ignoriert bis...
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements, and whether it is skipping or
+% compiling parts.
+scan_i_press_enter=02040_I_Drcken Sie <Return> um fortzusetzen
+% When the \var{-vi} switch is used, the compiler stops compilation
+% and waits for the \var{Enter} key to be pressed when it encounters
+% a \var{\{\$STOP\}} directive.
+scan_w_unsupported_switch=02041_W_Nicht untersttzter Schalter $1
+% When warings are turned on (\var{-vw}), the compiler warns you about
+% unsupported switches. This means that the switch is used in Delphi or
+% Turbo Pascal, but not in \fpc.
+scan_w_illegal_directive=02042_W_Ungltige Compilerdirektive $1
+% When warings are turned on (\var{-vw}), the compiler warns you about
+% unrecognised switches. For a list of recognised switches, see the \progref
+scan_t_back_in=02043_TL_Wieder zurck in $1
+% When you use the \var{-vt} switch, the compiler tells you when it has finished
+% reading an include file.
+scan_w_unsupported_app_type=02044_W_Nicht untersttzter Anwendungstyp: $1
+% You get this warning if you specify an unknown application type
+% with the directive \var{\{\$APPTYPE\}}.
+scan_w_app_type_not_support=02045_W_APPTYPE wird vom Zielbetriebssystem nicht untersttzt
+% The \var{\{\$APPTYPE\}} directive is supported by win32 applications only.
+scan_w_description_not_support=02046_W_Der Compilerschalter DESCRIPTION wird vom Zielbetriebssystem nicht untersttzt
+% The \var{\{\$DESCRIPTION\}} directive is not supported on this target OS.
+scan_n_version_not_support=02047_N_VERSION wird vom Zielbetriebssystem nicht untersttzt
+% The \var{\{\$VERSION\}} directive is not supported on this target OS.
+scan_n_only_exe_version=02048_N_VERSION kann in Units nicht verwendet werden
+% The \var{\{\$VERSION\}} directive is only used for executable or DLL sources.
+scan_w_wrong_version_ignored=02049_W_Falsches Format fr VERSION-Direktive $1
+% The \var{\{\$VERSION\}} directive format is major_version.minor_version
+% where major_version and minor_version are words.
+scan_e_illegal_asmmode_specifier=02050_E_Unbekannter Assemblermodusname: "$1"
+% When you specify an assembler mode with the \var{\{\$ASMMODE xxx\}} directive,
+% the compiler didn't recognize the mode you specified.
+scan_w_no_asm_reader_switch_inside_asm=02051_W_ASM-Leser-Schalter ist innerhalb einer Asm-Sequenz nicht m”glich, $1 wird erst in der n„chsten Sequenz wirksam
+% It is not possible to switch from one assembler reader to another
+% inside an assembler block. The new reader will be used for next
+% assembler statement only.
+scan_e_wrong_switch_toggle=02052_E_Parameter fr Schalter falsch, verwenden Sie ON/OFF oder +/-
+% You need to use ON or OFF or a + or - to toggle the switch.
+scan_e_resourcefiles_not_supported=02053_E_Resourcedateien werden vom aktuellen Zielbetriebssystem nicht untersttzt
+% The target you are compiling for doesn't support resource files.
+scan_w_include_env_not_found=02054_W_$1 ist keine Umgebungsvariable
+% The included environment variable can't be found in the environment; it will
+% be replaced by an empty string instead.
+scan_e_invalid_maxfpureg_value=02055_E_Nicht erlaubter Wert fr MAXFPUREGISTER-Direktive
+% Valid values for this directive are 0..8 and NORMAL/DEFAULT.
+scan_w_only_one_resourcefile_supported=02056_W_Vom aktuellen Zielbetriebssystem wird nur eine Resourcedatei untersttzt
+% Only one resource file can be supported for this target - this is the case of
+% OS/2 (EMX) currently. The first one found is used, the others are discarded.
+scan_w_macro_support_turned_off=02057_W_Makrountersttzung ist ausgeschaltet
+% A macro declaration has been found, but macro support is currently off,
+% so the declaration will be ignored. To turn macro support on compile with
+% -Sm on the command line or add \{\$MACRO ON\} in the source.
+scan_e_invalid_interface_type=02058_E_Unbekannter Interfacetyp. Untersttzt wird COM, CORBA und DEFAULT
+% The interface type that was specified is not supported.
+scan_w_appid_not_support=02059_W_APPID wird nur von PalmOS untersttzt
+% The \var{\{\$APPID\}} directive is only supported for the PalmOS target.
+scan_w_appname_not_support=02060_W_APPNAME wird nur von PalmOS untersttzt
+% The \var{\{\$APPNAME\}} directive is only supported for the PalmOS target.
+scan_e_string_exceeds_255_chars=02061_E_Zeichenkettenkonstanten k”nnen maximal 255 Zeichen lang sein
+% A single string constant can contain at most 255 chars. Try splitting up the
+% string into multiple smaller parts and concatenate them with a + operator.
+scan_f_include_deep_ten=02062_F_Include-Dateien k”nnen nur bis zu einer Tiefe von 16 geschachtelt werden
+% When including include files the files have been nested to a level of 16.
+% The compiler will expand no further, since this may be a sign that
+% recursion is used.
+scan_e_too_many_push=02063_F_Zu viele Ebenen von PUSH
+% A maximum of 20 levels is allowed. This error occurs only in mode MacPas.
+scan_e_too_many_pop=02064_E_POP ohne ein vorhergehendes PUSH
+% This error occurs only in mode MacPas.
+scan_e_error_macro_lacks_value=02065_E_Das Makro "$1" besitzt keinen Wert
+% Thus the conditional compiling expression cannot be evaluated.
+scan_e_wrong_switch_toggle_default=02066_E_Zum Modusumschalten kann nur ON/OFF/DEFAULT oder +/-/* verwendet werden
+% You need to use ON or OFF or DEFAULT or a + or - or * to toggle the switch.
+scan_e_mode_switch_not_allowed=02067_E_Der Modus Umschalter "$1" ist hier nicht erlaubt
+% A mode switch has already been encountered, or, in the case of option -Mmacpas,
+% a mode switch occurs after UNIT.
+scan_e_error_macro_undefined=02068_E_Die Compile time Variable oder das Makro "$1" ist nicht definiert.
+% Thus the conditional compile time expression cannot be evaluated. Only in mode MacPas.
+scan_e_utf8_bigger_than_65535=02069_E_Der UTF-8 Code ist gr”sser als 65535
+% \fpc handles UTF-8 strings internally as widestrings, i.e. the char codes are limited to 65535.
+scan_e_utf8_malformed=02070_E_Ungltige UTF-8 Zeichenkette
+% The given string isn't a valid UTF-8 string.
+scan_c_switching_to_utf8=02071_C_UTF-8 Signatur gefunden, verwende UTF-8 Code
+% The compiler found a UTF-8 encoding signature (\$ef, \$bb, \$bf) at the beginning of a file,
+% so it interprets it as a UTF-8 file.
+scan_e_compile_time_typeerror=02072_E_Compile time Ausdruck: Erwartete $1 aber erhielt $2 bei $3
+% The type-check of a compile time expression failed.
+scan_n_app_type_not_support=02073_N_APPTYPE wird vom Zielbetriebssystem nicht untersttzt
+% The \var{\{\$APPTYPE\}} directive is supported by certain operating systems only.
+scan_e_illegal_optimization_specifier=02074_E_"$1" ist eine ungltige Optimierung
+% You specified an optimization with the \var{\{\$OPTIMIZATION xxx\}} directive,
+% and the compiler didn't recognize the optimization you specified.
+scan_w_setpeflags_not_support=02075_W_SETPEFLAGS wird vom Zielbetriebssystem nicht untersttzt
+% The \var{\{\$SETPEFLAGS\}} directive is not supported by the target OS.
+scan_w_imagebase_not_support=02076_W_IMAGEBASE wird vom Zielbetriebssystem nicht untersttzt
+% The \var{\{\$IMAGEBASE\}} directive is not supported by the target OS.
+scan_w_minstacksize_not_support=02077_W_MINSTACKSIZE wird vom Zielbetriebssystem nicht untersttzt
+% The \var{\{\$IMAGEBASE\}} directive is not supported by the target OS.
+scan_w_maxstacksize_not_support=02078_W_MAXSTACKSIZE wird vom Zielbetriebssystem nicht untersttzt
+% The \var{\{\$MAXSTACKSIZE\}} directive is not supported by the target OS.
+scanner_e_illegal_warn_state=02079_E_Ungltiger Wert "$1" fr die $WARN Direktive
+% Only ON and OFF can be used as state with a \var{\{\$WARN\}} compiler directive.
+scan_e_only_packset=02080_E_Ungltiger Wert fr das set packing
+% Only 0, 1, 2, 4, 8, DEFAULT and NORMAL are allowed as packset parameters.
+scan_w_pic_ignored=02081_W_PIC Direktive oder Schalter wird ignoriert
+% Several targets, such as \windows, do not support nor need PIC,
+% so the PIC directive and switch are ignored.
+scan_w_unsupported_switch_by_target=02082_W_Der Schalter "$1" wird vom derzeit ausgew„hlten Zielbetriebssystem nicht untersttzt
+% Some compiler switches like \$E are not supported by all targets.
+scan_w_frameworks_darwin_only=02084_W_Framework-bezogene Optionen werden nur fr Darwin/Mac OS X untersttzt
+% Frameworks are not a known concept, or at least not supported by FPC,
+% on operating systems other than Darwin/Mac OS X.
+scan_e_illegal_minfpconstprec=02085_E_"$1" ist eine ungltige minimale Pr„zision von Fliesskommakonstanten
+% Valid minimal precisions for floating point constants are default, 32 and 64,
+% which mean respectively minimal (usually 32 bit), 32 bit and 64 bit precision.
+scan_w_multiple_main_name_overrides=02086_W_Der Name der "main" Prozedur wird mehrfach berschrieben. Es war bisher auf "$1" gesetzt
+% The name for the main entry procedure is specified more than once. Only the last
+% name will be used.
+scanner_w_illegal_warn_identifier=02087_W_Ungltige Bezeichner "$1" fr die $WARN Direktive
+% Identifier is not known by a \var{\{\$WARN\}} compiler directive.
+scanner_e_illegal_alignment_directive=02088_E_Ungltige "alignment" Direktive
+% The alignment directive is not valid. Either the alignment type is not known or the alignment
+% value is not a power of two.
+%
+% \end{description}
+# EndOfTeX
+
+#
+# Parser
+#
+# 03313 is the last used one
+#
+% \section{Parser messages}
+% This section lists all parser messages. The parser takes care of the
+% semantics of you language, i.e. it determines if your Pascal constructs
+% are correct.
+% \begin{description}
+parser_e_syntax_error=03000_E_Parser - Syntaxfehler
+% An error against the Turbo Pascal language was encountered. This typically
+% happens when an illegal character is found in the source file.
+parser_e_dont_nest_interrupt=03004_E_INTERRUPT-Prozeduren drfen nicht verschachtelt sein
+% An \VAR{INTERRUPT} procedure must be global.
+parser_w_proc_directive_ignored=03005_W_Prozedurtyp $1 wird ignoriert
+% The specified procedure directive is ignored by FPC programs.
+parser_e_no_overload_for_all_procs=03006_E_Nicht alle Deklarationen von "$1" sind mit OVERLOAD deklariert
+% When you want to use overloading using the \var{OVERLOAD} directive, then
+% all declarations need to have \var{OVERLOAD} specified.
+parser_e_export_name_double=03008_E_Doppelter Name fr exportierte Funktion $1
+% Exported function names inside a specific DLL must all be different.
+parser_e_export_ordinal_double=03009_E_Doppelter Index fr exportierte Funktion $1
+% Exported function names inside a specific DLL must all be different.
+parser_e_export_invalid_index=03010_E_Ungltiger Index for exportierte Funktion
+% DLL function index must be in the range \var{1..\$FFFF}.
+parser_w_parser_reloc_no_debug=03011_W_Fr relozierbare DLL oder ausfhrbare Datei $1 funktionieren keine Debug-Information, deaktiviert.
+% It is currently not possible to include debug information in a relocatable DLL.
+parser_w_parser_win32_debug_needs_WN=03012_W_Um Win32-Code debuggen zu k”nnen, mssen die Relozierungen mit -WN option abgeschaltet werden.
+% Stabs debug info is wrong for relocatable DLL or EXES. Use -WN
+% if you want to debug win32 executables.
+parser_e_constructorname_must_be_init=03013_E_Konstruktor-Name muss INIT sein
+% You are declaring a constructor with a name which isn't \var{init}, and the
+% \var{-Ss} switch is in effect. See the switch \seeo{Ss}.
+parser_e_destructorname_must_be_done=03014_E_Destruktor-Name muss DONE sein
+% You are declaring a constructor with a name which isn't \var{done}, and the
+% \var{-Ss} switch is in effect. See the switch \seeo{Ss}.
+parser_e_proc_inline_not_supported=03016_E_Schlsselwort INLINE nicht untersttzt
+% You tried to compile a program with C++ style inlining, and forgot to
+% specify the \var{-Si} option (\seeo{Si}). The compiler doesn't support C++
+% styled inlining by default.
+parser_w_constructor_should_be_public=03018_W_Konstruktor muss PUBLIC sein
+% Constructors must be in the 'public' part of an object (class) declaration.
+parser_w_destructor_should_be_public=03019_W_Destruktor muss PUBLIC sein
+% Destructors must be in the 'public' part of an object (class) declaration.
+parser_n_only_one_destructor=03020_N_Klasse darf nur einen Destruktor besitzen
+% You can declare only one destructor for a class.
+parser_e_no_local_objects=03021_E_Lokale Klassendefinitionen sind nicht zul„ssig
+% Classes must be defined globally. They cannot be defined inside a
+% procedure or function.
+parser_f_no_anonym_objects=03022_F_Anonyme Klassendefinitionen sind nicht zul„ssig
+% An invalid object (class) declaration was encountered, i.e. an
+% object or class without methods that isn't derived from another object or
+% class. For example:
+% \begin{verbatim}
+% Type o = object
+% a : longint;
+% end;
+% \end{verbatim}
+% will trigger this error.
+parser_n_object_has_no_vmt=03023_N_Das Objekt "$1" besitzt keine VMT
+% This is a note indicating that the declared object has no
+% virtual method table.
+parser_e_illegal_parameter_list=03024_E_Ungltige Parameterliste
+% You are calling a function with parameters that are of a different type than
+% the declared parameters of the function.
+parser_e_wrong_parameter_size=03026_E_Falsche Anzahl an Parameter im Aufruf von "$1" angegeben
+% There is an error in the parameter list of the function or procedure --
+% the number of parameters is not correct.
+parser_e_overloaded_no_procedure=03027_E_Bezeichner "$1" ist keine Funktion, overload nicht m”glich
+% The compiler encountered a symbol with the same name as an overloaded
+% function, but it isn't a function it can overload.
+parser_e_overloaded_have_same_parameters=03028_E_Overload-Funktion darf keine identische Parameterliste aufweisen
+% You're declaring overloaded functions, but with the same parameter list.
+% Overloaded function must have at least 1 different parameter in their
+% declaration.
+parser_e_header_dont_match_forward=03029_E_Funktionskopf unterscheidet sich von voriger Deklaration "$1"
+% You declared a function with the same parameters but
+% different result type or function specifiers.
+parser_e_header_different_var_names=03030_E_Funktionskopf von "$1" passt nicht zur Forward-Deklaration, Variablename „ndert sich: $2 => $3
+% You declared the function in the \var{interface} part, or with the
+% \var{forward} directive, but defined it with a different parameter list.
+parser_n_duplicate_enum=03031_N_Werte in Aufz„hlungen mssen aufsteigend sein
+% \fpc allows enumeration constructions as in C. Examine the following
+% two declarations:
+% \begin{verbatim}
+% type a = (A_A,A_B,A_E:=6,A_UAS:=200);
+% type a = (A_A,A_B,A_E:=6,A_UAS:=4);
+% \end{verbatim}
+% The second declaration would produce an error. \var{A\_UAS} needs to have a
+% value higher than \var{A\_E}, i.e. at least 7.
+parser_e_no_with_for_variable_in_other_segments=03033_E_WITH kann nicht auf Variablen in anderen Segmenten angewendet werden
+% With stores a variable locally on the stack,
+% but this is not possible if the variable belongs to another segment.
+parser_e_too_much_lexlevel=03034_E_Funktionsverschachtelung gr”sser als 31
+% You can nest function definitions only 31 levels deep.
+parser_e_range_check_error=03035_E_Bereichsprfungsfehler bei Konstantenbestimmung
+% The constants are out of their allowed range.
+parser_w_range_check_error=03036_W_Bereichsprfungsfehler bei Konstantenbestimmung
+% The constants are out of their allowed range.
+parser_e_double_caselabel=03037_E_doppelter CASE-Wert
+% You are specifying the same label 2 times in a \var{case} statement.
+parser_e_case_lower_less_than_upper_bound=03038_E_Obere Grenze der CASE-Bereichsangabe ist kleiner als untere Grenze
+% The upper bound of a \var{case} label is less than the lower bound and this
+% is useless.
+parser_e_type_const_not_possible=03039_E_Klassen oder Interfaces sind als typisierte Konstanten unzul„ssig
+% You cannot declare a constant of type class or object.
+parser_e_no_overloaded_procvars=03040_E_Funktionsvariablen von Overload-Funktionen sind unzul„ssig
+% You are trying to assign an overloaded function to a procedural variable.
+% This is not allowed.
+parser_e_invalid_string_size=03041_E_Stringl„nge muss ein Wert zwischen 1 und 255 sein
+% The length of a string in Pascal is limited to 255 characters. You are
+% trying to declare a string with length less than 1 or greater than 255.
+parser_w_use_extended_syntax_for_objects=03042_W_Benutzen Sie die erweiterte Syntax von NEW und DISPOSE fr Objekt-Instanzen
+% If you have a pointer \var{a} to an object type, then the statement
+% \var{new(a)} will not initialize the object (i.e. the constructor isn't
+% called), although space will be allocated. You should issue the
+% \var{new(a,init)} statement. This will allocate space, and call the
+% constructor of the object.
+parser_w_no_new_dispose_on_void_pointers=03043_W_Verwendung von NEW oder DISPOSE mit untypisierten Pointern ist ohne Aussage
+parser_e_no_new_dispose_on_void_pointers=03044_E_Verwendung von NEW oder DISPOSE mit untypisierten Pointern ist nicht m”glich
+% You cannot use \var{new(p)} or \var{dispose(p)} if \var{p} is an untyped pointer
+% because no size is associated to an untyped pointer.
+% It is accepted for compatibility in \var{TP} and \var{DELPHI} modes, but the
+% compiler will still warn you if it finds such a construct.
+parser_e_class_id_expected=03045_E_Klassenbezeichner erwartet
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., an object or class method, but the type in front of the dot is not
+% a known type.
+parser_e_no_type_not_allowed_here=03046_E_Typbezeichner ist hier nicht zul„ssig
+% You cannot use a type inside an expression.
+parser_e_methode_id_expected=03047_E_Methodenbezeichner erwartet
+% This identifier is not a method.
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., an object or class method, but the procedure name is not a
+% procedure of this type.
+parser_e_header_dont_match_any_member=03048_E_Funktionskopf passt zu keiner Methode der Klasse $1
+% This identifier is not a method.
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., an object or class method, but the procedure name is not a
+% procedure of this type.
+parser_d_procedure_start=03049_DL_Procedure/Function $1
+% When using the \var{-vd} switch, the compiler tells you when it starts
+% processing a procedure or function implementation.
+parser_e_error_in_real=03050_E_Ungltige Fliesskommakonstante
+% The compiler expects a floating point expression, and gets something else.
+parser_e_fail_only_in_constructor=03051_E_FAIL darf nur in Konstruktoren verwendet werden
+% You are using the \var{FAIL} instruction outside a constructor method.
+parser_e_no_paras_for_destructor=03052_E_Destruktoren k”nnen keine Parameter haben
+% You are declaring a destructor with a parameter list. Destructor methods
+% cannot have parameters.
+parser_e_only_class_members_via_class_ref=03053_E_Nur Klassenmethoden, Klasseneigenschaften und Klassenvariablen k”nnen ber den Klassennamen angesprochen werden
+% This error occurs in a situation like the following:
+% \begin{verbatim}
+% Type :
+% Tclass = Class of Tobject;
+%
+% Var C : TClass;
+%
+% begin
+% ...
+% C.free
+% \end{verbatim}
+% \var{Free} is not a class method and hence cannot be called with a class
+% reference.
+parser_e_only_class_members=03054_E_Nur Klassenmethoden, Klasseneigenschaften und Klassenvariablen k”nnen in einer Klassenmethode angesprochen werden
+% This is related to the previous error. You cannot call a method of an object
+% from inside a class method. The following code would produce this error:
+% \begin{verbatim}
+% class procedure tobject.x;
+%
+% begin
+% free
+% \end{verbatim}
+% Because free is a normal method of a class it cannot be called from a class
+% method.
+parser_e_case_mismatch=03055_E_Konstante und CASE-Typ passen nicht zueinander
+% One of the labels is not of the same type as the case variable.
+parser_e_illegal_symbol_exported=03056_E_Das Symbol kann nicht aus einer Bibliothek exportiert werden
+% You can only export procedures and functions when you write a library. You
+% cannot export variables or constants.
+parser_w_should_use_override=03057_W_Eine Inherit-Methode wird durch $1 verdeckt
+% A method that is declared \var{virtual} in a parent class, should be
+% overridden in the descendant class with the \var{override} directive. If you
+% don't specify the \var{override} directive, you will hide the parent method;
+% you will not override it.
+parser_e_nothing_to_be_overridden=03058_E_Es gibt keine Vorg„ngerklasse mit einer Methode, die damit berschrieben werden k”nnte: $1
+% You try to \var{override} a virtual method of a parent class that doesn't
+% exist.
+parser_e_no_procedure_to_access_property=03059_E_Es gibt keine Member-Funktion um auf diese Property zuzugreifen
+% You specified no \var{read} directive for a property.
+parser_w_stored_not_implemented=03060_W_Die Stored Property - Direktive ist noch nicht implementiert
+% This message is no longer used, as the \var{stored} directive has been implemented.
+parser_e_ill_property_access_sym=03061_E_Ungltiges Symbol fr den Zugriff auf die Property
+% There is an error in the \var{read} or \var{write} directives for an array
+% property. When you declare an array property, you can only access it with
+% procedures and functions. The following code would cause such an error.
+% \begin{verbatim}
+% tmyobject = class
+% i : integer;
+% property x [i : integer]: integer read I write i;
+% \end{verbatim}
+%
+parser_e_cant_access_protected_member=03062_E_Kann an dieser Stelle nicht auf das geschtzte Feld des Objekts zugreifen
+% Fields that are declared in a \var{protected} section of an object or class
+% declaration cannot be accessed outside the module where the object is
+% defined, or outside descendent object methods.
+parser_e_cant_access_private_member=03063_E_Kann an dieser Stelle nicht auf das private Feld des Objekts zugreifen
+% Fields that are declared in a \var{private} section of an object or class
+% declaration cannot be accessed outside the module where the class is
+% defined.
+parser_e_overridden_methods_not_same_ret=03066_E_šberschriebene, virtuelle Methoden mssen den gleichen Ergebnistyp haben: "$2" wird berschrieben von "$1"
+% If you declare overridden methods in a class definition, they must
+% have the same return type.
+parser_e_dont_nest_export=03067_E_Mit EXPORT deklarierte Funktionen drfen nicht verschachtelt sein
+% You cannot declare a function or procedure within a function or procedure
+% that was declared as an export procedure.
+parser_e_methods_dont_be_export=03068_E_Methoden drfen nicht EXPORTiert werden
+% You cannot declare a procedure that is a method for an object as
+% \var{export}ed. That is, your methods cannot be called from a C program.
+parser_e_call_by_ref_without_typeconv=03069_E_Aufrufe mit VAR-Parametern fr Argument-Nr. $1 mssen exakt stimmen: "$2" gefunden, "$3" erwartet
+% When calling a function declared with \var{var} parameters, the variables in
+% the function call must be of exactly the same type. There is no automatic
+% type conversion.
+parser_e_no_super_class=03070_E_Klasse ist keine Elternklasse zur aktuellen Klasse
+% When calling inherited methods, you are trying to call a method of a strange
+% class. You can only call an inherited method of a parent class.
+parser_e_self_not_in_method=03071_E_SELF ist nur in Methoden erlaubt
+% You are trying to use the \var{self} parameter outside an object's method.
+% Only methods get passed the \var{self} parameters.
+parser_e_generic_methods_only_in_methods=03072_E_Methoden drfen nur in anderen Methoden direkt mit dem Klassen-Typbezeichner aufgerufen werden
+% A construction like \var{sometype.somemethod} is only allowed in a method.
+parser_e_illegal_colon_qualifier=03073_E_Unzul„ssige Verwendung von ':'
+% You are using the format \var{:} (colon) 2 times on an expression that
+% is not a real expression.
+parser_e_illegal_set_expr=03074_E_Bereichsprfungsfehler im SET-Konstruktor oder doppeltes Set-Element
+% The declaration of a set contains an error. Either one of the elements is
+% outside the range of the set type, or two of the elements are in fact
+% the same.
+parser_e_pointer_to_class_expected=03075_E_Zeiger auf Objekt erwartet
+% You specified an illegal type in a \var{New} statement.
+% The extended synax of \var{New} needs an object as a parameter.
+parser_e_expr_have_to_be_constructor_call=03076_E_Ausdruck muss ein Konstruktor-Aufruf sein
+% When using the extended syntax of \var{new}, you must specify the constructor
+% method of the object you are trying to create. The procedure you specified
+% is not a constructor.
+parser_e_expr_have_to_be_destructor_call=03077_E_Ausdruck muss ein Destruktor-Aufruf sein
+% When using the extended syntax of \var{dispose}, you must specify the
+% destructor method of the object you are trying to dispose of.
+% The procedure you specified is not a destructor.
+parser_e_invalid_record_const=03078_E_Unzul„ssige Reihenfolge der Record-Elemente
+% When declaring a constant record, you specified the fields in the wrong
+% order.
+parser_e_false_with_expr=03079_E_Typ des Ausdrucks muss eine Klasse oder ein Recordtyp sein
+% A \var{with} statement needs an argument that is of the type \var{record}
+% or \var{class}. You are using \var{with} on an expression that is not of
+% this type.
+parser_e_void_function=03080_E_Prozeduren k”nnen keinen Wert zurckliefern
+% In \fpc, you can specify a return value for a function when using
+% the \var{exit} statement. This error occurs when you try to do this with a
+% procedure. Procedures cannot return a value.
+parser_e_only_methods_allowed=03081_E_Konstruktoren, Destruktoren und Klassenoperatoren mssen Methoden sein
+% You're declaring a procedure as destructor, constructor or class operator, when the
+% procedure isn't a class method.
+parser_e_operator_not_overloaded=03082_E_Operator besitzt kein Overload
+% You're trying to use an overloaded operator when it isn't overloaded for
+% this type.
+parser_e_no_such_assignment=03083_E_Es ist nicht m”glich, die Zuweisung fr gleiche Typen zu berladen
+% You cannot overload assignment for types
+% that the compiler considers as equal.
+parser_e_overload_impossible=03084_E_Unm”gliche Operator-.berladung
+% The combination of operator, arguments and return type are
+% incompatible.
+parser_e_no_reraise_possible=03085_E_Ausl”sen einer Exception an dieser Stelle nicht m”glich
+% You are trying to re-raise an exception where it is not allowed. You can only
+% re-raise exceptions in an \var{except} block.
+parser_e_no_new_or_dispose_for_classes=03086_E_Die erweiterte Syntax von New oder Dispose ist fr Klassen unzul„ssig
+% You cannot generate an instance of a class with the extended syntax of
+% \var{new}. The constructor must be used for that. For the same reason, you
+% cannot call \var{Dispose} to de-allocate an instance of a class, the
+% destructor must be used for that.
+parser_e_procedure_overloading_is_off=03088_E_Das šberladen von Prozeduren ist ausgeschaltet
+% When using the \var{-So} switch, procedure overloading is switched off.
+% Turbo Pascal does not support function overloading.
+parser_e_overload_operator_failed=03089_E_Es ist nicht m”glich, dieesen Operator zu berladen. Verwandte berladbare Operatoren sind "$1"
+% You are trying to overload an operator which cannot be overloaded.
+% The following operators can be overloaded :
+% \begin{verbatim}
+% +, -, *, /, =, >, <, <=, >=, is, as, in, **, :=
+% \end{verbatim}
+parser_e_comparative_operator_return_boolean=03090_E_Vergleichsoperator muss einen booleschen Wert zurckgeben
+% When overloading the \var{=} operator, the function must return a boolean
+% value.
+parser_e_only_virtual_methods_abstract=03091_E_Nur virtuelle Methoden k”nnen abstrakt sein
+% You are declaring a method as abstract, when it isn't declared to be
+% virtual.
+parser_f_unsupported_feature=03092_F_Benutzung einer nicht untersttzten Erweiterung!
+% You're trying to force the compiler into doing something it cannot do yet.
+parser_e_mix_of_classes_and_objects=03093_E_Das Mischen von Klassen und Objekten ist unzul„ssig
+% You cannot derive \var{objects}, \var{classes}, \var{cppclasses} and \var{interfaces} intertwined. E.g.
+% a class cannot have an object as parent and vice versa.
+parser_w_unknown_proc_directive_ignored=03094_W_Unbekannte Prozedur, Direktive $1 wurde ignoriert
+% The procedure direcive you secified is unknown.
+parser_e_absolute_only_one_var=03095_E_ABSOLUTE kann nur auf eine alleinstehende Variable angewendet werden
+% You cannot specify more than one variable before the \var{absolute} directive.
+% Thus, the following construct will provide this error:
+% \begin{verbatim}
+% Var Z : Longint;
+% X,Y : Longint absolute Z;
+% \end{verbatim}
+parser_e_absolute_only_to_var_or_const=03096_E_ABSOLUTE kann nur auf Variablen und Konstanten angewendet werden
+% The address of an \var{absolute} directive can only point to a variable or
+% constant. Therefore, the following code will produce this error:
+% \begin{verbatim}
+% Procedure X;
+%
+% var p : longint absolute x;
+% \end{verbatim}
+%
+parser_e_initialized_only_one_var=03097_E_Es kann nur EINE Variable initialisiert werden
+% You cannot specify more than one variable with a initial value in Delphi mode.
+parser_e_abstract_no_definition=03098_E_Abstrakte Methoden drfen keine Definition (mit Rumpf) haben
+% Abstract methods can only be declared, you cannot implement them. They
+% should be overridden by a descendant class.
+parser_e_overloaded_must_be_all_global=03099_E_Diese berladene Funktion darf nicht lokal sein (muss Exportiert werden)
+% You are defining an overloaded function in the implementation part of a unit,
+% but there is no corresponding declaration in the interface part of the unit.
+parser_w_virtual_without_constructor=03100_W_Virtuelle Methoden wurden ohne Konstruktor verwendet in $1
+% If you declare objects or classes that contain virtual methods, you need
+% to have a constructor and destructor to initialize them. The compiler
+% encountered an object or class with virtual methods that doesn't have
+% a constructor/destructor pair.
+parser_c_macro_defined=03101_CL_Makro definiert: $1
+% When \var{-vc} is used, the compiler tells you when it defines macros.
+parser_c_macro_undefined=03102_CL_Makrodefinition gel”scht: $1
+% When \var{-vc} is used, the compiler tells you when it undefines macros.
+parser_c_macro_set_to=03103_CL_Wert des Makros $1 auf $2 gesetzt
+% When \var{-vc} is used, the compiler tells you what values macros get.
+parser_i_compiling=03104_I_šbersetze $1
+% When you turn on information messages (\var{-vi}), the compiler tells you
+% what units it is recompiling.
+parser_u_parsing_interface=03105_UL_Parse Interface von Unit $1
+% This tells you that the reading of the interface
+% of the current unit has started
+parser_u_parsing_implementation=03106_UL_Parse Implementation von $1
+% This tells you that the code reading of the implementation
+% of the current unit, library or program starts
+parser_d_compiling_second_time=03107_DL_šbersetze $1 zum zweiten Mal
+% When you request debug messages (\var{-vd}) the compiler tells you what
+% units it recompiles for the second time.
+parser_e_no_property_found_to_override=03109_E_Es gibt keine Property diesen Namens, die berschrieben werden k”nnte
+% You want to overrride a property of a parent class, when there is, in fact,
+% no such property in the parent class.
+parser_e_only_one_default_property=03110_E_Es ist nur eine einzelne Default-Property erlaubt, vererbte Default-Property in Klasse $1 gefunden
+% You specified a property as \var{Default}, but a parent class already has a
+% default property, and a class can have only one default property.
+parser_e_property_need_paras=03111_E_Die Default-Property muss eine Array-Property sein
+% Only array properties of classes can be made \var{default} properties.
+parser_e_constructor_cannot_be_not_virtual=03112_E_Virtuelle Konstruktoren werden nur im Klassen-Objektmodell untersttzt
+% You cannot have virtual constructors in objects. You can only have them
+% in classes.
+parser_e_no_default_property_available=03113_E_Keine Default-Property verfgbar
+% You try to access a default property of a class, but this class (or one of
+% its ancestors) doesn't have a default property.
+parser_e_cant_have_published=03114_E_Die Klasse kann keinen PUBLISHED Bereich haben, benutzen Sie den {$M+} Schalter
+% If you want a \var{published} section in a class definition, you must
+% use the \var{\{\$M+\}} switch, which turns on generation of type
+% information.
+parser_e_forward_declaration_must_be_resolved=03115_E_Forward-Deklaration der Klasse $1 muss hier aufgel”st werden, wenn sie als Elternklasse benutzt werden soll
+% To be able to use an object as an ancestor object, it must be defined
+% first. This error occurs in the following situation:
+% \begin{verbatim}
+% Type ParentClas = Class;
+% ChildClass = Class(ParentClass)
+% ...
+% end;
+% \end{verbatim}
+% where \var{ParentClass} is declared but not defined.
+parser_e_no_local_operator=03116_E_Lokale Operatoren werden nicht untersttzt
+% You cannot overload locally, i.e. inside procedures or function
+% definitions.
+parser_e_proc_dir_not_allowed_in_interface=03117_E_Prozedur-Direktive $1 unzul„ssig im Interface-Bereich
+% This procedure directive is not allowed in the \var{interface} section of
+% a unit. You can only use it in the \var{implementation} section.
+parser_e_proc_dir_not_allowed_in_implementation=03118_E_Prozedur Direktive $1 unzul„ssig im Implementation-Bereich
+% This procedure directive is not allowed in the \var{implementation} section of
+% a unit. You can only use it in the \var{interface} section.
+parser_e_proc_dir_not_allowed_in_procvar=03119_E_Prozedur-Direktive $1 unzul„ssig in einer Procvar-Deklaration
+% This procedure directive cannot be part of a procedural of function
+% type declaration.
+parser_e_function_already_declared_public_forward=03120_E_Funktion ist bereits als Public oder Forward deklariert: $1
+% You will get this error if a function is defined as \var{forward} twice.
+% Or if it occurs in the \var{interface} section, and again as a \var{forward}
+% declaration in the \var{implementation} section.
+parser_e_not_external_and_export=03121_E_Kann nicht EXPORT und EXTERNAL gleichzeitig benutzen
+% These two procedure directives are mutually exclusive.
+parser_w_not_supported_for_inline=03123_W_$1 noch nicht innerhalb von inline Prozeduren/Funktionen untersttzt
+% Inline procedures don't support this declaration.
+parser_w_inlining_disabled=03124_W_Inlining deaktiviert
+% Inlining of procedures is disabled.
+parser_i_writing_browser_log=03125_I_Schreibe Browser-Log $1
+% When information messages are on, the compiler warns you when it
+% writes the browser log (generated with the \var{\{\$Y+\}} switch).
+parser_h_maybe_deref_caret_missing=03126_H_M”glicherweise fehlt eine Zeiger-Dereferenzierung
+% The compiler thinks that a pointer may need a dereference.
+parser_f_assembler_reader_not_supported=03127_F_Gew„hlter Assembler-Leser nicht untersttzt
+% The selected assembler reader (with \var{\{\$ASMMODE xxx\}} is not
+% supported. The compiler can be compiled with or without support for a
+% particular assembler reader.
+parser_e_proc_dir_conflict=03128_E_Prozedur-Direktive $1 steht in Konflikt mit anderen Direktiven
+% You specified a procedure directive that conflicts with other directives.
+% For instance \var{cdecl} and \var{pascal} are mutually exclusive.
+parser_e_call_convention_dont_match_forward=03129_E_Aufrufkonvention passt nicht zur Forward-Deklaration
+% This error happens when you declare a function or procedure with
+% e.g. \var{cdecl;} but omit this directive in the implementation, or vice
+% versa. The calling convention is part of the function declaration, and
+% must be repeated in the function definition.
+parser_e_property_cant_have_a_default_value=03131_E_Property kann keinen Vorgabewert haben
+% Set properties or indexed properties cannot have a default value.
+parser_e_property_default_value_must_const=03132_E_Der Vorgabewert einer Property muss eine Konstante sein
+% The value of a \var{default} declared property must be known at compile
+% time. The value you specified is only known at run time. This happens
+% e.g. if you specify a variable name as a default value.
+parser_e_cant_publish_that=03133_E_Symbol darf nicht PUBLISHED sein, dies kann nur eine Klasse sein
+% Only class type variables can be in a \var{published} section of a class
+% if they are not declared as a property.
+parser_e_cant_publish_that_property=03134_E_Diese Property-Art kann nicht PUBLISHED sein
+% Properties in a \var{published} section cannot be array properties.
+% They must be moved to public sections. Properties in a \var{published}
+% section must be an ordinal type, a real type, strings or sets.
+parser_e_empty_import_name=03136_E_Leerer Importname angegeben
+% Some targets need a name for the imported procedure or a \var{cdecl} specifier.
+parser_e_division_by_zero=03138_E_Division durch Null
+% A division by zero was encounted.
+parser_e_invalid_float_operation=03139_E_Ungltige Fliesskomma-Operation
+% An operation on two real type values produced an overflow or a division
+% by zero.
+parser_e_array_lower_less_than_upper_bound=03140_E_Obere Grenze des Bereichs ist kleiner als die untere Grenze
+% The upper bound of an array declaration is less than the lower bound and this
+% is not possible.
+parser_w_string_too_long=03141_W_String "$1" ist l„nger als $2
+% The size of the constant string is larger than the size you specified in
+% string type definition.
+parser_e_string_larger_array=03142_E_Stringl„nge ist gr”sser als die L„nge des "array of char"
+% The size of the constant string is larger than the size you specified in
+% the \var{Array[x..y] of char} definition.
+parser_e_ill_msg_expr=03143_E_Ungltiger Ausdruck nach der 'Message'-Direktive
+% \fpc supports only integer or string values as message constants.
+parser_e_ill_msg_param=03144_E_Message-Handler akzeptieren nur einen "Call by Reference" Parameter
+% A method declared with the \var{message} directive as message handler
+% can take only one parameter which must be declared as call by reference.
+% Parameters are declared as call by reference using the \var{var}-directive.
+parser_e_duplicate_message_label=03145_E_Doppeltes Message-Label: $1
+% A label for a message is used twice in one object/class.
+parser_e_self_in_non_message_handler=03146_E_SELF darf nur in Message-Handlern ein expliziter Parameter sein
+% The \var{Self} parameter can only be passed explicitly to a method which
+% is declared as message method handler
+parser_e_threadvars_only_sg=03147_E_Threadvariablen k”nnen nur statisch oder global sein
+% Threadvars must be static or global; you can't declare a thread
+% local to a procedure. Local variables are always local to a thread,
+% because every thread has its own stack and local variables
+% are stored on the stack.
+parser_f_direct_assembler_not_allowed=03148_F_Direkter Assembler wird f+r bin„res Ausgabeformat nicht untersttzt
+% You can't use direct assembler when using a binary writer. Choose an
+% other output format or use another assembler reader.
+parser_w_no_objpas_use_mode=03149_W_Laden Sie die OBJPAS Unit nicht manuell, benutzen Sie statdessen {$mode objfpc} oder {$mode delphi}
+% You are trying to load the \file{ObjPas} unit manually from a \var{uses} clause.
+% This is not a good idea. Use the \var{\{\$MODE OBJFPC\}} or
+% \var{\{\$mode delphi\}} directives which load the unit automatically.
+parser_e_no_object_override=03150_E_OVERRIDE darf in Objekten nicht verwendet werden
+% \var{Override} is not supported for objects, use \var{virtual} instead to override
+% a method of a parent object.
+parser_e_cant_use_inittable_here=03151_E_Datentypen, die ein Initialiserung oder Finalisierung ben”tigen, k”nnen in varianten Records nicht verwendet werden
+% Some data types (e.g. \var{ansistring}) need initialization/finalization
+% code which is implicitly generated by the compiler. Such data types
+% can't be used in the variant part of a record.
+parser_e_resourcestring_only_sg=03152_E_Resourcestrings drfen nur statisch oder global sein
+% Resourcestring cannot be declared local, only global or using the static
+% directive.
+parser_e_exit_with_argument_not__possible=03153_E_EXIT mit Argument darf hier nicht verwendet werden
+% An exit statement with an argument for the return value can't be used here. This
+% can happen for example in \var{try..except} or \var{try..finally} blocks.
+parser_e_stored_property_must_be_boolean=03154_E_Der Typ des STORED-Symbols muss boolesch sein
+% If you specify a storage symbol in a property declaration, it must be a
+% boolean type.
+parser_e_ill_property_storage_sym=03155_E_Dieses Symbol ist als Speichersymbol unzul„ssig
+% You can't use this type of symbol as storage specifier in property
+% declaration. You can use only methods with the result type boolean,
+% boolean class fields or boolean constants.
+parser_e_only_publishable_classes_can_be_published=03156_E_Nur Klassen, die im "$M+"-Modus bersetzt wurden, drfen published sein
+% A class-typed field in the published section of a class can only be a class which was
+% compiled in \var{\{\$M+\}} or which is derived from such a class. Normally
+% such a class should be derived from \var{TPersistent}.
+parser_e_proc_directive_expected=03157_E_Prozedurdirektive erwartet
+% This error is triggered when you have a \var{\{\$Calling\}} directive without
+% a calling convention specified.
+% It also happens when declaring a procedure in a const block and you
+% used a ; after a procedure declaration which must be followed by a
+% procedure directive.
+% Correct declarations are:
+% \begin{verbatim}
+% const
+% p : procedure;stdcall=nil;
+% p : procedure stdcall=nil;
+% \end{verbatim}
+parser_e_invalid_property_index_value=03158_E_Der Wert fr einen Property-Index muss ordinalen Typs sein
+% The value you use to index a property must be of an ordinal type, for
+% example an integer or enumerated type.
+parser_e_procname_to_short_for_export=03159_E_Prozedurname zu kurz um exportiert zu werden
+% The length of the procedure/function name must be at least 2 characters
+% long. This is because of a bug in dlltool which doesn't parse the .def
+% file correctly with a name of length 1.
+parser_e_dlltool_unit_var_problem=03160_E_Es kann kein DEFFILE-Eintrag fr unit-globale Variablen erzeugt werden
+parser_e_dlltool_unit_var_problem2=03161_E_šbersetze ohne "-WD"-Option
+% You need to compile this file without the -WD switch on the
+% command line.
+parser_f_need_objfpc_or_delphi_mode=03162_F_Es muss der Modus ObjFPC (-S2) oder Delphi (-Sd) aktiv sein, um dieses Modul zu bersetzen
+% You need to use \var{\{\$MODE OBJFPC\}} or \var{\{\$MODE DELPHI\}} to compile this file.
+% Or use the corresponding command line switch, either \var{-Mobjfpc} or \var{-MDelphi.}
+parser_e_no_export_with_index_for_target=03163_E_Der Index darf nicht kleiner als $1 sein
+% Exporting of functions or procedures with a specified index is not
+% supported on this target.
+parser_e_no_export_of_variables_for_target=03164_E_Das Ziel $1 untersttzt das Exportieren von Variablen nicht
+% Exporting of variables is not supported on this target.
+parser_e_improper_guid_syntax=03165_E_Falscher GUID-Syntax
+% The GUID indication does not have the proper syntax. It should be of the form
+% \begin{verbatim}
+% {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}
+% \end{verbatim}
+% Where each \var{X} represents a hexadecimal digit.
+parser_w_interface_mapping_notfound=03168_W_Eine Prozedur mit dem Namen "$1", die $2.$3 implementieren k”nnte, kann nicht gefunden werden
+% The compiler cannot find a suitable procedure which implements the given method of an interface.
+% A procedure with the same name is found, but the arguments do not match.
+parser_e_interface_id_expected=03169_E_Interface-Bezeichner erwartet
+% This happens when the compiler scans a \var{class} declaration that contains
+% \var{interface} function name mapping code like this:
+% \begin{verbatim}
+% type
+% TMyObject = class(TObject, IDispatch)
+% function IUnknown.QueryInterface=MyQueryInterface;
+% ....
+% \end{verbatim}
+% and the \var{interface} before the dot is not listed in the inheritance list.
+parser_e_type_cant_be_used_in_array_index=03170_E_Der Typ "$1" kann nicht als Array-Index verwendet werden
+% Types like \var{qword} or \var{int64} aren't allowed as array index type.
+parser_e_no_con_des_in_interfaces=03171_E_Kon- und Destruktoren sind in Interfaces nicht erlaubt
+% Constructor and destructor declarations aren't allowed in interfaces.
+% In the most cases method \var{QueryInterface} of \var{IUnknown} can
+% be used to create a new interface.
+parser_e_no_access_specifier_in_interfaces=03172_E_Zugriffsbezeichner k”nnen in INTERFACEs und OBJCPROTOCOLs nicht benutzt werden
+% The access specifiers \var{public}, \var{private}, \var{protected} and
+% \var{published} can't be used in interfaces, Objective-C protocols and categories because all methods
+% of an interface/protocol/category must be public.
+parser_e_no_vars_in_interfaces=03173_E_Ein Interface, ein Helfer, ein Objective-C Protokoll oder eine Kategorie darf keine Felder enthalten
+% Declarations of fields are not allowed in interfaces, helpers and Objective-C protocols and categories.
+% An interface/helper/protocol/category can contain only methods and properties with method read/write specifiers.
+parser_e_no_local_proc_external=03174_E_Eine lokale Prozedur kann nicht als EXTERNAL deklariert werden
+% Declaring local procedures as external is not possible. Local procedures
+% get hidden parameters that will make the chance of errors very high.
+parser_w_skipped_fields_before=03175_W_Einige Felder vor dem Feld "$1" sind nicht initialisiert
+% In Delphi mode, not all fields of a typed constant record have to be
+% initialized, but the compiler warns you when it detects such situations.
+parser_e_skipped_fields_before=03176_E_Einige Felder vor dem Feld "$1" sind nicht initialisiert
+% In all syntax modes but Delphi mode, you can't leave some fields uninitialized
+% in the middle of a typed constant record.
+parser_w_skipped_fields_after=03177_W_Einige Felder nach dem Feld "$1" sind nicht initialisiert
+% You can leave some fields at the end of a type constant record uninitialized
+% (The compiler will initialize them to zero automatically). This may be the cause
+% of subtle problems.
+parser_e_varargs_need_cdecl_and_external=03178_E_Verwendung von VarArgs (oder '...' in MacPas) ohne CDecl/CPPDecl/MWPascal oder External nicht m”glich
+% The varargs directive (or the ``...'' varargs parameter in MacPas mode) can only be
+% used with procedures or functions that are declared with \var{external} and one of
+% \var{cdecl}, \var{cppdecl} and \var{mwpascal}. This functionality
+% is only supported to provide a compatible interface to C functions like printf.
+parser_e_self_call_by_value=03179_E_Self muss ein Call-By-Value-Parameter sein
+% You can't declare \var{Self} as a const or var parameter, it must always be
+% a call-by-value parameter.
+parser_e_interface_has_no_guid=03180_E_Interface "$1" hat keine Interface-Identifikation
+% When you want to assign an interface to a constant, then the interface
+% must have a GUID value set.
+parser_e_illegal_field_or_method=03181_E_Klassenfeld oder Methoden-Bezeichner "$1" unbekannt
+% Properties must refer to a field or method in the same class.
+parser_w_proc_overriding_calling=03182_W_šberschreibe die Calling Convention "$1" mit "$2"
+% There are two directives in the procedure declaration that specify a calling
+% convention. Only the last directive will be used.
+parser_e_no_procvarobj_const=03183_E_Die Konstante des Typs "procedure of object" kann nur mit NIL initialisiert werden
+% You cannot assign the address of a method to a typed constant which has a
+% 'procedure of object' type, because such a constant requires two addresses:
+% that of the method (which is known at compile time) and that of the object or
+% class instance it operates on (which cannot be known at compile time).
+parser_e_default_value_only_one_para=03184_E_Der Default Value kann nur einem Parameter zugewiesen werden
+% It is not possible to specify a default value for several parameters at once.
+% The following is invalid:
+% \begin{verbatim}
+% Procedure MyProcedure (A,B : Integer = 0);
+% \end{verbatim}
+% Instead, this should be declared as
+% \begin{verbatim}
+% Procedure MyProcedure (A : Integer = 0; B : Integer = 0);
+% \end{verbatim}
+parser_e_default_value_expected_for_para=03185_E_Standard Parameter fr "$1" ben”tigt
+% The specified parameter requires a default value.
+parser_w_unsupported_feature=03186_W_Verwendung eines nicht untersttzten Features!
+% You're trying to force the compiler into doing something it cannot do yet.
+parser_h_c_arrays_are_references=03187_H_C Arrays werden "by reference" bergeben
+% Any array passed to a C function is passed
+% by a pointer (i.e. by reference).
+parser_e_C_array_of_const_must_be_last=03188_E_C array of const muss letztes Argument sein
+% You cannot add any other argument after an \var{array of const} for
+% \var{cdecl} functions, as the size pushed on stack for this argument is
+% not known.
+parser_h_type_redef=03189_H_Erneute Definition des Typs "$1"
+% This is an indicator that a previously declared type is
+% being redefined as something else. This may, or may not
+% be, a potential source of errors.
+parser_w_cdecl_has_no_high=03190_W_cdecl'ared Functionen haben keinen high Parameter
+% Functions declared with the \var{cdecl} modifier do not pass an extra implicit parameter.
+parser_w_cdecl_no_openstring=03191_W_cdecl'ared Functionen untersttzen keine open strings
+% Openstring is not supported for functions that have the \var{cdecl} modifier.
+parser_e_initialized_not_for_threadvar=03192_E_Als threadvar deklarierte Variable kann nicht initialisiert werden
+% Variables declared as threadvar cannot be initialized with a default value.
+% The variables will always be filled with zero at the start of a new thread.
+parser_e_msg_only_for_classes=03193_E_Message directive ist nur in Klassen erlaubt
+% The message directive is only supported for Class types.
+parser_e_procedure_or_function_expected=03194_E_Procedure oder Function erwartet
+% A class method can only be specified for procedures and functions.
+parser_e_illegal_calling_convention=03195_W_Calling convention directive ignoriert: "$1"
+% Some calling conventions are supported only by certain CPUs. I.e. most non-i386 ports support
+% only the standard ABI calling convention of the CPU.
+parser_e_no_object_reintroduce=03196_E_REINTRODUCE kann in Objekten nicht benutzt werden
+% \var{reintroduce} is not supported for objects, Objective-C classes and Objective-C protocols.
+parser_e_paraloc_only_one_para=03197_E_Jedes Argument muss seine eigene "location" haben
+% If locations for arguments are specified explicitly as it is required by
+% some syscall conventions, each argument must have its own location. Things
+% like
+% \begin{verbatim}
+% procedure p(i,j : longint 'r1');
+% \end{verbatim}
+% aren't allowed.
+parser_e_paraloc_all_paras=03198_E_Jedes Argument muss seine explizite "location" haben
+% If one argument has an explicit argument location, all arguments of a procedure
+% must have one.
+parser_e_illegal_explicit_paraloc=03199_E_"location" des Arguments unbekannt
+% The location specified for an argument isn't recognized by the compiler.
+parser_e_32bitint_or_pointer_variable_expected=03200_E_32 Bit-Integer oder Zeiger-Variable erwartet
+% The libbase for MorphOS/AmigaOS can be given only as \var{longint}, \var{dword} or any pointer variable.
+parser_e_goto_outside_proc=03201_E_Goto Statements zwischen verschiedenen Prozeduren sind nicht erlaubt
+% It isn't allowed to use \var{goto} statements referencing labels outside the
+% current procedure. The following example shows the problem:
+% \begin{verbatim}
+% ...
+% procedure p1;
+% label
+% l1;
+%
+% procedure p2;
+% begin
+% goto l1; // This goto ISN'T allowed
+% end;
+%
+% begin
+% p2
+% l1:
+% end;
+% ...
+%
+% \end{verbatim}
+parser_f_too_complex_proc=03202_F_Prozedur zu komplex, sie erfordert zu viele Register
+% Your procedure body is too long for the compiler. You should split the
+% procedure into multiple smaller procedures.
+parser_e_illegal_expression=03203_E_Ungltiger Ausdruck
+% This can occur under many circumstances. Usually when trying to evaluate
+% constant expressions.
+parser_e_invalid_integer=03204_E_Ungltiger integer Ausdruck
+% You made an expression which isn't an integer, and the compiler expects the
+% result to be an integer.
+parser_e_invalid_qualifier=03205_E_Ungltiger Qualifier
+% One of the following is happening :
+% \begin{itemize}
+% \item You're trying to access a field of a variable that is not a record.
+% \item You're indexing a variable that is not an array.
+% \item You're dereferencing a variable that is not a pointer.
+% \end{itemize}
+parser_e_upper_lower_than_lower=03206_E_High Range Limit < low Range Limit
+% You are declaring a subrange, and the high limit is less than the low limit of
+% the range.
+parser_e_macpas_exit_wrong_param=03207_E_Exits Parameter muss der Name der Prozedur sein, in der es benutzt wird
+% Non local exit is not allowed. This error occurs only in mode MacPas.
+parser_e_illegal_assignment_to_count_var=03208_E_Ungltige Zuweisung zur for-loop Variable "$1"
+% The type of a \var{for} loop variable must be an ordinal type.
+% Loop variables cannot be reals or strings. You also cannot assign values to
+% loop variables inside the loop (Except in Delphi and TP modes). Use a while or
+% repeat loop instead if you need to do something like that, since those
+% constructs were built for that.
+parser_e_no_local_var_external=03209_E_Lokale Variable kann nicht als EXTERNAL deklariert werden
+% Declaring local variables as external is not allowed. Only global variables can reference
+% external variables.
+parser_e_proc_already_external=03210_E_Prozedur ist bereits als EXTERNAL deklariert
+% The procedure is already declared with the EXTERNAL directive in an interface or
+% forward declaration.
+parser_w_implicit_uses_of_variants_unit=03211_W_Implizite Verwendung einer Variant Unit
+% The Variant type is used in the unit without any used unit using the Variants unit. The
+% compiler has implicitly added the Variants unit to the uses list. To remove this warning
+% the Variants unit needs to be added to the uses statement.
+parser_e_no_static_method_in_interfaces=03212_E_Class und statische Methoden k”nnen nicht in INTERFACES verwendet werden
+% The specifier \var{class} and directive \var{static} can't be used in interfaces
+% because all methods of an interface must be public.
+parser_e_arithmetic_operation_overflow=03213_E_šberlauf in arithmetischer Operation
+% An operation on two integer values produced an overflow.
+parser_e_protected_or_private_expected=03214_E_Protected oder private erwartet
+% \var{strict} can be only used together with \var{protected} or \var{private}.
+parser_e_illegal_slice=03215_E_SLICE kann nicht ausserhalb der Parameterliste benutzt werden
+% \var{slice} can be used only for arguments accepting an open array parameter.
+parser_e_dispinterface_cant_have_parent=03216_E_Ein DISPINTERFACE kann keine Elternklasse haben.
+% A DISPINTERFACE is a special type of interface which can't have a parent class. Dispinterface always derive from IDispatch type.
+parser_e_dispinterface_needs_a_guid=03217_E_Ein DISPINTERFACE ben”tigt einen GUID
+% A DISPINTERFACE always needs an interface identification (a GUID).
+parser_w_overridden_methods_not_same_ret=03218_W_šberschriebene Methoden mssen einen entsprechenden Rckgabetyp haben. Dieser Code kann abstrzen, weil er von einem Delphi Parser Bug abh„ngt (Methode "$2" wird durch "$1" berschrieben, die einen anderen Rckgabetyp hat).
+% If you declare overridden methods in a class definition, they must
+% have the same return type. Some versions of Delphi allow you to change the
+% return type of interface methods, and even to change procedures into
+% functions, but the resulting code may crash depending on the types used
+% and the way the methods are called.
+parser_e_dispid_must_be_ord_const=03219_E_Dispatch IDs mssen ganzzahlige Konstanten sein
+% The \var{dispid} keyword must be followed by an ordinal constant (the dispid index).
+parser_e_array_range_out_of_bounds=03220_E_Der Bereich des Array ist zu gross
+% Regardless of the size taken up by its elements, an array cannot have more
+% than high(ptrint) elements. Additionally, the range type must be a subrange
+% of ptrint.
+parser_e_packed_element_no_var_addr=03221_E_Bit packed Array-Elemente und Record-Felder haben keine Adressen
+% If you declare an array or record as \var{packed} in Mac Pascal mode
+% (or as \var{packed} in any mode with \var{\{\$bitpacking on\}}), it will
+% be packed at the bit level. This means it becomes impossible to take addresses
+% of individual array elements or record fields. The only exception to this rule
+% is in the case of packed arrays elements whose packed size is a multple of 8 bits.
+parser_e_packed_dynamic_open_array=03222_E_Dynamische Arrays k”nnen nicht packed sein
+% Only regular (and possibly in the future also open) arrays can be packed.
+parser_e_packed_element_no_loop=03223_E_Bit packed Array-Elemente und Record-Felder k”nnen nicht als Loop-Variable verwerndet werden
+% If you declare an array or record as \var{packed} in Mac Pascal mode
+% (or as \var{packed} in any mode with \var{\{\$bitpacking on\}}), it will
+% be packed at the bit level. For performance reasons, they cannot be
+% used as loop variables.
+parser_e_type_var_const_only_in_records_and_classes=03224_E_VAR, TYPE und CONST sind nur innerhalb Records, Objekten und Klassen erlaubt
+% The usage of VAR, TYPE and CONST to declare new types inside an object is allowed only inside
+% records, objects and classes.
+parser_e_cant_create_generics_of_this_type=03225_E_Dieser Typ kann nicht "generic" sein
+% Only Classes, Objects, Interfaces and Records are allowed to be used as generic.
+parser_w_no_lineinfo_use_switch=03226_W_Die LINEINFO Unit nicht manuell laden. Verwende statt dessen den Compilerschalter -gl
+% Do not use the \file{lineinfo} unit directly, Use the \var{-gl} switch which
+% automatically adds the correct unit for reading the selected type of debugging
+% information. The unit that needs to be used depends on the type of
+% debug information used when compiling the binary.
+parser_e_no_funcret_specified=03227_E_Kein Funktionsergebnistyp fr Funktion "$1" angegeben
+% The first time you declare a function you have to declare it completely,
+% including all parameters and the result type.
+parser_e_special_onlygenerics=03228_E_Spezialisierung wird nur fr generische Typen untersttzt
+% Types which are not generics can't be specialized.
+parser_e_no_generics_as_params=03229_E_Generische Typen k”nnen bei der Spezialisierung generischer Typen nicht als Parameter benutzt werden
+% When specializing a generic, only non-generic types can be used as parameters.
+parser_e_type_object_constants=03230_E_Konstanten eines Objekts, das ein VMT enth„lt, sind unzul„ssig
+% If an object requires a VMT either because it contains a constructor or virtual methods,
+% it's not allowed to create constants of it. In TP and Delphi mode this is allowed
+% for compatibility reasons.
+parser_e_label_outside_proc=03231_E_Die Address von Labels, die ausserhalb des aktuellen Scopes definiert wurden, k”nnen nicht verwendet werden
+% It isn't allowed to take the address of labels outside the
+% current procedure.
+parser_e_initialized_not_for_external=03233_E_Extern deklarierte Variablen k”nnen nicht intialisiert werden
+% Variables declared as external cannot be initialized with a default value.
+parser_e_illegal_function_result=03234_E_Ungltiger Funktionsergebnistyp
+% Some types like file types cannot be used as function result.
+parser_e_no_common_type=03235_E_"$1" und "$2" haben keinen gemeinsamen Typ
+% To perform an operation on integers, the compiler converts both operands
+% to their common type, which appears to be an invalid type. To determine the
+% common type of the operands, the compiler takes the minimum of the minimal values
+% of both types, and the maximum of the maximal values of both types. The common
+% type is then minimum..maximum.
+parser_e_no_generics_as_types=03236_E_Generische Typen k”nnen nicht ohne Spezialisierung als Typ fr eine Variable verwendet werden
+% Generics must be always specialized before being used as variable type.
+parser_w_register_list_ignored=03237_W_Registerliste wird in reinen Assemblerroutinen ignoriert
+% When using pure assembler routines, the list with modified registers is ignored.
+parser_e_implements_must_be_class_or_interface=03238_E_Die Implements-Eigenschaft muss einen Klassen- oder Interface-Typ haben
+% A property which implements an interface must be of type class or interface.
+parser_e_implements_must_have_correct_type=03239_E_Die Implements-Eigenschaft muss ein Interface mit dem richtigen Typ implementieren; es wurde Typ "$1" gefunden, aber Typ "$2" erwartet.
+% A property which implements an interface actually implements a different interface.
+parser_e_implements_must_read_specifier=03240_E_Die Implements-Eigenschaft muss einen Lesen-Bezeichner haben
+% A property which implements an interface must have at least a read specifier.
+parser_e_implements_must_not_have_write_specifier=03241_E_Die Implements-Eigenschaft darf keinen Schreib-Bezeichner haben
+% A property which implements an interface may not have a write specifier.
+parser_e_implements_must_not_have_stored_specifier=03242_E_Die Implements-Eigenschaft darf keinen Gespeichert-Bezeichner haben
+% A property which implements an interface may not have a stored specifier.
+parser_e_implements_uses_non_implemented_interface=03243_E_Die Implements-Eigenschaft benutzt das nicht implementierte Interface "$1"
+% The interface which is implemented by a property is not an interface implemented by the class.
+parser_e_unsupported_real=03244_E_Fliesskommavariablen werden fr dieses Ziel nicht untersttzt
+% The compiler parsed a floating point expression, but it is not supported.
+parser_e_class_doesnt_implement_interface=03245_E_Klasse "$1" implementiert das Interface "$2" nicht
+% The delegated interface is not implemented by the class given in the implements clause.
+parser_e_class_implements_must_be_interface=03246_E_Der von Implements benutzte Typ muss ein Interface sein
+% The \var{implements} keyword must be followed by an interface type.
+parser_e_cant_export_var_different_name=03247_E_Variablen k”nnen fr dieses Target nicht mit einem anderen Namen exportiert werden; fge der Deklaration den Namen mit einer "export" Direktive hinzu (Variablenname: $1, deklarierter Name fr den Export: $2)
+% On most targets it is not possible to change the name under which a variable
+% is exported inside the \var{exports} statement of a library.
+% In that case, you have to specify the export name at the point where the
+% variable is declared, using the \var{export} and \var{alias} directives.
+parser_e_weak_external_not_supported=03248_E_Schwache externe Symbole werden fr dieses Target nicht untersttzt
+% A "weak external" symbol is a symbol which may or may not exist at (either static
+% or dynamic) link time. This concept may not be available (or implemented yet)
+% on the current cpu/OS target.
+parser_e_forward_mismatch=03249_E_Forward Typdefinition passt nicht
+% Classes and interfaces being defined forward must have the same type
+% when being implemented. A forward interface cannot be changed into a class.
+parser_n_ignore_lower_visibility=03250_N_Die virtuelle Methode "$1" hat eine niedrigere Sichtbarkeit ($2) als die Elternklasse $3 ($4)
+% The virtual method overrides an method that is declared with a higher visibility. This might give
+% unexpected results. In case the new visibility is private than it might be that a call to inherited in a
+% new child class will call the higher visible method in a parent class and ignores the private method.
+parser_e_field_not_allowed_here=03251_E_Felder sind nach der Definition einer Methode oder Eigenschaft nicht erlaubt. Beginne vorher eine neue Sichtbarkeitssektion
+% Once a method or property has been defined in a class or object, you cannot define any fields afterwards
+% without starting a new visibility section (such as \var{public}, \var{private}, etc.). The reason is
+% that otherwise the source code can appear ambiguous to the compiler, since it is possible to use modifiers
+% such as \var{default} and \var{register} also as field names.
+parser_e_no_local_para_def=03252_E_Parameter oder Ergebnistypen k”nnen keine lokalen Typdeklarationen enthalten. Verwende eine getrennte Typdefinition in einem "type"-Block
+% In Pascal, types are not considered to be identical simply because they are semantically equivalent.
+% Two variables or parameters are only considered to be of the same type if they refer to the
+% same type definition.
+% As a result, it is not allowed to define new types inside parameter lists, because then it is impossible to
+% refer to the same type definition in the procedure headers of the interface and implementation of a unit
+% (both procedure headers would define a separate type). Keep in mind that expressions such as
+% ``file of byte'' or ``string[50]'' also define a new type.
+parser_e_abstract_and_sealed_conflict=03253_E_Konflikt zwischen ABSTRACT und SEALED
+% ABSTRACT and SEALED cannot be used together in one declaration
+parser_e_sealed_descendant=03254_E_Kann keinen Nachfahren der SEALED Klasse "$1" erzeugen
+% Sealed means that class cannot be derived by another class.
+parser_e_sealed_class_cannot_have_abstract_methods=03255_E_Eine SEALED Klasse kann keine ABSTRACT Methode haben
+% Sealed means that class cannot be derived. Therefore no one class is able to override an abstract method in a sealed class.
+parser_e_only_virtual_methods_final=03256_E_Nur virtuelle Methoden k”nnen final sein.
+% You are declaring a method as final, when it is not declared to be
+% virtual.
+parser_e_final_can_no_be_overridden=03257_E_Die finale Methode kann nicht berschrieben werden: "$1"
+% You are trying to \var{override} a virtual method of a parent class that does
+% not exist.
+parser_e_multiple_messages=03258_E_Pro Methode kann nur eine Nachricht verwendet werden
+% It is not possible to associate multiple messages with a single method.
+parser_e_invalid_enumerator_identifier=03259_E_Ungltiger Aufz„hlungsbezeichner: "$1"
+% Only "MoveNext" and "Current" enumerator identifiers are supported.
+parser_e_enumerator_identifier_required=03260_E_Aufz„hlungsbezeichner notwendig
+% "MoveNext" or "Current" identifier must follow the \var{enumerator} modifier.
+parser_e_enumerator_movenext_is_not_valid=03261_E_Die Aufz„hlungs-pattern-Methode "MoveNext" ist ungltig. Die Methode muss eine Funktion mit Rckgabetyp Boolean und ohne notwendige Argumente sein
+% "MoveNext" enumerator pattern method must be a function with Boolean return type and no required arguments
+parser_e_enumerator_current_is_not_valid=03262_E_Die Aufz„hlungs-pattern-Eigenschaft "Current" ist ungltig. Die Eigenschaft ben”tigt einen "Getter"
+% "Current" enumerator pattern property must have a getter
+parser_e_only_one_enumerator_movenext=03263_E_Pro Klasse/Objekt ist nur eine Aufz„hlungsmethode "MoveNext" erlaubt
+% Class or Object can have only one enumerator MoveNext declaration.
+parser_e_only_one_enumerator_current=03264_E_Pro Klasse/Objekt ist nur eine Aufz„hlungseigenschaft "Current" erlaubt
+% Class or Object can have only one enumerator Current declaration.
+parser_e_for_in_loop_cannot_be_used_for_the_type=03265_E_For in Schleife kann nicht fr den Typ "$1" verwendet werden
+% For in loop can be used not for all types. For example it cannot be used for the enumerations with jumps.
+parser_e_objc_requires_msgstr=03266_E_Objective-C Nachrichten erfordern, dass ihr Objective-C selector-Name mit der Direktive "message" angegeben wird
+% Objective-C messages require their Objective-C name (selector name) to be specified using the \var{message `someName:'} procedure directive.
+% While bindings to other languages automatically generate such names based on the identifier you use (by replacing
+% all underscores with colons), this is unsafe since nothing prevents an Objective-C method name to contain actual
+% colons.
+parser_e_objc_no_constructor_destructor=03267_E_Objective-C hat keine formalen Konstruktoren oder Destruktoren. Verwende die Nachrichten alloc, initXXX und dealloc
+% The Objective-C language does not have any constructors or destructors. While there are some messages with a similar
+% purpose (such as \var{init} and \var{dealloc}), these cannot be identified using automatic parsers and do not
+% guarantee anything like Pascal constructors/destructors (e.g., you have to take care of only calling ``designated''
+% inherited ``constructors''). For these reasons, we have opted to follow the standard Objective-C patterns for
+% instance creation/destruction.
+parser_e_message_string_too_long=03268_E_Der Name der Nachricht ist zu lang (max. 255 Zeichen)
+% Due to compiler implementation reasons, message names are currently limited to 255 characters.
+parser_e_objc_message_name_too_long=03269_E_Der Symbolname der Objective-C-Nachricht "$1" ist zu lang
+% Due to compiler implementation reasons, mangled message names (i.e., the symbol names used in the assembler
+% code) are currently limited to 255 characters.
+parser_h_no_objc_parent=03270_H_Definieren einer neuen Objective-C root-Klasse. Um sie von einer anderen root-Klasse abzuleiten (z.B. NSObject), gib diese als Elternklasse an
+% If no parent class is specified for an Object Pascal class, then it automatically derives from TObject.
+% Objective-C classes however do not automatically derive from NSObject, because one can have multiple
+% root classes in Objective-C. For example, in the Cocoa framework both NSObject and NSProxy are root classes.
+% Therefore, you have to explicitly define a parent class (such as NSObject) if you want to derive your
+% Objective-C class from it.
+parser_e_no_objc_published=03271_E_Objective-C Klassen k”nnen keinen Abschnitt published haben
+% In Object Pascal, ``published'' determines whether or not RTTI is generated. Since the Objective-C runtime always needs
+% RTTI for everything, this specified does not make sense for Objective-C classes.
+parser_f_need_objc=03272_F_Dieses Modul erfordert, dass der Objective-C Mode-Schalter bersetzt wird
+% This error indicates the use of Objective-C language features without an Objective-C mode switch
+% active. Enable one via the -M command line switch, or the {\$modeswitch x} directive.
+parser_e_must_use_override_objc=03273_E_Vererbte Methoden k”nnen nur in Objective-C berschrieben werden, fge "override" hinzu (Vererbte Methode ist in $1 definiert)
+parser_h_should_use_override_objc=03274_H_Vererbte Methoden k”nnen nur in Objective-C berschrieben werden, fge "override" hinzu (Vererbte Methode ist in $1 definiert)
+% It is not possible to \var{reintroduce} methods in Objective-C like in Object Pascal. Methods with the same
+% name always map to the same virtual method entry. In order to make this clear in the source code,
+% the compiler always requires the \var{override} directive to be specified when implementing overriding
+% Objective-C methods in Pascal. If the implementation is external, this rule is relaxed because Objective-C
+% does not have any \var{override}-style keyword (since it's the default and only behaviour in that language),
+% which makes it hard for automated header conversion tools to include it everywhere.
+% The type in which the inherited method is defined is explicitly mentioned, because this may either
+% be an objcclass or an objccategory.
+parser_e_objc_message_name_changed=03275_E_Der Nachrichtenname "$1" in der vererbten Klasse unterscheidet sich vom Nachrichtennamen "$2" in der aktuellen Klasse
+% An overriding Objective-C method cannot have a different message name than an inherited method. The reason
+% is that these message names uniquely define the message to the Objective-C runtime, which means that
+% giving them a different message name breaks the ``override'' semantics.
+parser_e_no_objc_unique=03276_E_Noch k”nnen eindeutige Kopien von Objective-C Typen nicht erstellt werden
+% Duplicating an Objective-C type using \var{type x = type y;} is not yet supported. You may be able to
+% obtain the desired effect using \var{type x = objcclass(y) end;} instead.
+parser_e_no_category_as_types=03277_E_Objective-C Kategorien und Object-Pascal Klassenhelfer k”nnen nicht als Typen benutzt werden
+% It is not possible to declare a variable as an instance of an Objective-C
+% category or an Object Pascal class helper. A category/class helper adds
+% methods to the scope of an existing class, but does not define a type by
+% itself. An exception of this rule is when inheriting an Object Pascal class
+% helper from another class helper.
+parser_e_no_category_override=03278_E_Kategorien berschreiben Methoden nicht, sondern ersetzen sie. "reintroduce" benutzen
+parser_e_must_use_reintroduce_objc=03279_E_Ersetzte Methoden k”nnen in Objective-C nur wieder eingefhrt werden, fge "reintroduce" hinzu (Ersetzte Methode ist in $1 definiert)
+parser_h_should_use_reintroduce_objc=03280_H_Ersetzte Methoden k”nnen in Objective-C nur wieder eingefhrt werden, fge "reintroduce" hinzu (Ersetzte Methode ist in $1 definiert)
+% A category replaces an existing method in an Objective-C class, rather than that it overrides it.
+% Calling an inherited method from an category method will call that method in
+% the extended class' parent, not in the extended class itself. The
+% replaced method in the original class is basically lost, and can no longer be
+% called or referred to. This behaviour corresponds somewhat more closely to
+% \var{reintroduce} than to \var{override} (although in case of \var{reintroduce}
+% in Object Pascal, hidden methods are still reachable via inherited).
+% The type in which the inherited method is defined is explicitly mentioned, because this may either
+% be an objcclass or an objccategory.
+parser_e_implements_getter_not_default_cc=03281_E_Getter fr das Interface implements mssen die voreingestellte calling convention des Ziels benutzen
+% Interface getters are called via a helper in the run time library, and hence
+% have to use the default calling convention for the target (\var{register} on
+% i386 and x86\_64, \var{stdcall} on other architectures).
+parser_e_no_refcounted_typed_file=03282_E_Typisierte Dateien k”nnen keine reference-counted Typen enthalten
+% The data in a typed file cannot be of a reference counted type (such as
+% \var{ansistring} or a record containing a field that is reference counted).
+parser_e_operator_not_overloaded_2=03283_E_šberladenener Operator nicht vorhanden: $2 "$1"
+% You are trying to use an overloaded operator when it is not overloaded for
+% this type.
+parser_e_operator_not_overloaded_3=03284_E_šberladenener Operator nicht vorhanden: "$1" $2 "$3"
+% You are trying to use an overloaded operator when it is not overloaded for
+% this type.
+parser_e_more_array_elements_expected=03285_E_Erwarte ein weiteres Element fr Array $1
+% When declaring a typed constant array, you provided to few elements to initialize the array
+parser_e_string_const_too_long=03286_E_Stringkonstante zu lang, so lange ansistrings ausgeschaltet sind
+% Only when a piece of code is compiled with ansistrings enabled (\var{\{\$H+\}}), string constants
+% longer than 255 characters are allowed.
+parser_e_invalid_univ_para=03287_E_Typ kann nicht als "univ" Parameter verwendet werden, weil seine Gr”áe zur Zeit der šbersetzung unbekannt ist: "$1"
+% \var{univ} parameters are compatible with all values of the same size, but this
+% cannot be checked in case a parameter's size is unknown at compile time.
+parser_e_only_one_class_constructor_allowed=03288_E_In der Klasse "$1" darf nur ein Klassenkonstruktor deklariert werden
+% You are trying to declare more than one class constructor but only one class constructor can be declared.
+parser_e_only_one_class_destructor_allowed=03289_E_In der Klasse "$1" darf nur ein Klassendestruktor deklariert werden
+% You are trying to declare more than one class destructor but only one class destructor can be declared.
+parser_e_no_paras_for_class_constructor=03290_E_Ein Klassenkonstruktur darf keine Parameter haben
+% You are declaring a class constructor with a parameter list. Class constructor methods
+% cannot have parameters.
+parser_e_no_paras_for_class_destructor=03291_E_Ein Klassendestruktur darf keine Parameter haben
+% You are declaring a class destructor with a parameter list. Class destructor methods
+% cannot have parameters.
+parser_f_modeswitch_objc_required=03292_F_Dieses Konstrukt erfordert, dass der Modenschalter \{\$modeswitch objectivec1\} aktiv ist
+% Objective-Pascal constructs are not supported when \{\$modeswitch ObjectiveC1\}
+% is not active.
+parser_e_widestring_to_ansi_compile_time=03293_E_Eine Unicodechar/string Konstante zur Zeit der šbersetzung nicht in eine ansi/shortstring Konstante konvertiert werden
+% It is not possible to use unicodechar and unicodestring constants in
+% constant expressions that have to be converted into an ansistring or shortstring
+% at compile time, for example inside typed constants. The reason is that the
+% compiler cannot know what the actual ansi encoding will be at run time.
+parser_e_objc_enumerator_2_0=03294_E_Objective-Pascal For-in Schleifen erfordern, dass der Modenschalter \{\$modeswitch ObjectiveC2\} aktiv ist
+% Objective-C ``fast enumeration'' support was added in Objective-C 2.0, and
+% hence the appropriate modeswitch has to be activated to expose this feature.
+% Note that Objective-C 2.0 programs require Mac OS X 10.5 or later.
+parser_e_objc_missing_enumeration_defs=03295_E_Der Kompiler findet die Typen NSFastEnumerationProtocol oder NSFastEnumerationState nicht in der Unit CocoaAll
+% Objective-C for-in loops (fast enumeration) require that the compiler can
+% find a unit called CocoaAll that contains definitions for the
+% NSFastEnumerationProtocol and NSFastEnumerationState types. If you get this
+% error, most likely the compiler is finding and loading an alternate CocoaAll
+% unit.
+parser_e_no_procvarnested_const=03296_E_Typisierte Konstanten des Typs 'procedure is nested' k”nnen nur mit NIL und globalen Prozeduren/Funktionen initialisiert werden
+% A nested procedural variable consists of two components: the address of the
+% procedure/function to call (which is always known at compile time), and also
+% a parent frame pointer (which is never known at compile time) in case the
+% procedural variable contains a reference to a nested procedure/function.
+% Therefore such typed constants can only be initialized with global
+% functions/procedures since these do not require a parent frame pointer.
+parser_f_no_generic_inside_generic=03297_F_Die Deklaration einer generischen Klasse innerhalb einer anderen generischen Klasse ist nicht erlaubt
+% At the moment, scanner supports recording of only one token buffer at the time
+% (guarded by internal error 200511173 in tscannerfile.startrecordtokens).
+% Since generics are implemented by recording tokens, it is not possible to
+% have declaration of generic class inside another generic class.
+parser_e_forward_protocol_declaration_must_be_resolved=03298_E_Vorw„rts-Deklarationen des ObjC-Protokolls "$1" mssen aufgel”st sein, bevor eine ObjC-Klasse ihr folgen kann
+% An objcprotocol must be fully defined before classes can conform to it.
+% This error occurs in the following situation:
+% \begin{verbatim}
+% Type MyProtocol = objcprotoocl;
+% ChildClass = Class(NSObject,MyProtocol)
+% ...
+% end;
+% \end{verbatim}
+% where \var{MyProtocol} is declared but not defined.
+parser_e_no_record_published=03299_E_Record -Typen k”nnen keine ”ffentlichen Abschnitte (published sections) haben
+% Published sections can be used only inside classes.
+parser_e_no_destructor_in_records=03300_E_Destruktoren sind in Records und Helfern nicht erlaubt
+% Destructor declarations aren't allowed in records or helpers.
+parser_e_class_methods_only_static_in_records=03301_E_Klassenmethoden mssen in Records statisch sein
+% Class methods declarations aren't allowed in records without static modifier.
+% Records have no inheritance and therefore non static class methods have no sence for them.
+parser_e_no_constructor_in_records=03302_E_Konstruktoren sind in Records und Recordhelfern nicht erlaubt
+% Constructor declarations aren't allowed in records or record helpers.
+parser_e_at_least_one_argument_must_be_of_type=03303_E_Entweder das Ergebnis oder mindestens ein Parameter mssen vom Typ "$1" sein
+% It is required that either the result of the routine or at least one of its parameters be of the specified type.
+% For example class operators either take an instance of the structured type in which they are defined, or they return one.
+parser_e_cant_use_type_parameters_here=03304_E_Typ-Parameter k”nnen initialization/finalization erfordern - Sie k”nnen deshalb nicht in varianten Rekords verwendet werden
+% Type parameters may be specialized with types which (e.g. \var{ansistring}) need initialization/finalization
+% code which is implicitly generated by the compiler.
+parser_e_externals_no_section=03305_E_"external" deklarierte Variablen drfen nicht in einer "custom section" sein
+% A section directive is not valid for variables being declared as external.
+parser_e_section_no_locals=03306_E_Nicht-statische und nicht-globale Variablen drfen keine Direktive "section" haben
+% A variable placed in a custom section is always statically allocated so it must be either a static or global variable.
+parser_e_not_allowed_in_helper=03307_E_"$1" ist in Helfertypen nicht erlaubt
+% Some directives and specifiers like "virtual", "dynamic", "override" aren't
+% allowed inside helper types in mode ObjFPC (they are ignored in mode Delphi),
+% because they have no meaning within helpers. Also "abstract" isn't allowed in
+% either mode.
+parser_e_no_class_constructor_in_helpers=03308_E_Klassenkonstruktoren sind in Helfern nicht erlaubt
+% Class constructor declarations aren't allowed in helpers.
+parser_e_inherited_not_in_record=03309_E_"inherited" ist in einem Record nicht erlaubt
+% As records don't suppport inheritance the use of "inherited" is prohibited for
+% these as well as for record helpers (in mode "Delphi" only).
+parser_e_no_types_in_local_anonymous_records=03310_E_Typ-Deklarationen sind in lokalen oder anonymen Records nicht erlaubt
+% Records with types must be defined globally. Types cannot be defined inside records which are defined in a
+% procedure or function or in anonymous records.
+parser_e_duplicate_implements_clause=03311_E_Zweifacher "implements"-Term fr das Interface "$1"
+% A class may delegate an interface using the "implements" clause only to a single property. Delegating it multiple times
+% is a error.
+parser_e_mapping_no_implements=03312_E_Das Interface "$1" kann nicht durch "$2" delegiert werden. Die Methode ist bereits aufgel”st
+% Method resolution clause maps a method of an interface to a method of the current class. Therefore the current class
+% has to implement the interface directly. Delegation is not possible.
+parser_e_implements_no_mapping=03313_E_Das Interface "$1" kann keine Methoden-Aufl”sung haben, "$2" delegiert es bereits
+% Method resoulution is only possible for interfaces that are implemented directly, not by delegation.
+%
+% \end{description}
+# EndOfTeX
+
+#
+# Type Checking
+#
+# 04103 is the last used one
+#
+% \section{Type checking errors}
+% This section lists all errors that can occur when type checking is
+% performed.
+% \begin{description}
+type_e_mismatch=04000_E_Typen passen nicht zusammen
+% This can happen in many cases:
+% \begin{itemize}
+% \item The variable you're assigning to is of a different type than the
+% expression in the assignment.
+% \item You are calling a function or procedure with parameters that are
+% incompatible with the parameters in the function or procedure definition.
+% \end{itemize}
+type_e_incompatible_types=04001_E_Inkompatible Typen: Habe "$1" erhalten, aber "$2" erwartet
+% There is no conversion possible between the two types.
+% Another possiblity is that they are declared in different
+% declarations:
+% \begin{verbatim}
+% Var
+% A1 : Array[1..10] Of Integer;
+% A2 : Array[1..10] Of Integer;
+%
+% Begin
+% A1:=A2; { This statement also gives this error. It
+% is due to the strict type checking of Pascal }
+% End.
+% \end{verbatim}
+type_e_not_equal_types=04002_E_Typen sind verschieden bei $1 und $2
+% The types are not equal.
+type_e_type_id_expected=04003_E_Typbezeichner erwartet
+% The identifier is not a type, or you forgot to supply a type identifier.
+type_e_variable_id_expected=04004_E_Variablenbezeichner erwartet
+% This happens when you pass a constant to a \var{Inc} var or \var{Dec}
+% procedure. You can only pass variables as arguments to these functions.
+type_e_integer_expr_expected=04005_E_Integer-Ausdruck erwartet, aber "$1" erhalten
+% The compiler expects an expression of type integer, but gets a different
+% type.
+type_e_boolean_expr_expected=04006_E_Booleschen Ausdruck erwartet, aber "$1" erhalten
+% The expression must be a boolean type. It should be return \var{True} or
+% \var{False}.
+type_e_ordinal_expr_expected=04007_E_Ganzzahliger Ausdruck erwartet
+% The expression must be of ordinal type, i.e., maximum a \var{Longint}.
+% This happens, for instance, when you specify a second argument
+% to \var{Inc} or \var{Dec} that doesn't evaluate to an ordinal value.
+type_e_pointer_type_expected=04008_E_Zeigertyp erwartet, aber "$1" erhalten
+% The variable or expression isn't of the type \var{pointer}. This
+% happens when you pass a variable that isn't a pointer to \var{New}
+% or \var{Dispose}.
+type_e_class_type_expected=04009_E_Klassentyp erwartet, aber "$1" erhalten
+% The variable or expression isn't of the type \var{class}. This happens
+% typically when
+% \begin{enumerate}
+% \item The parent class in a class declaration isn't a class.
+% \item An exception handler (\var{On}) contains a type identifier that
+% isn't a class.
+% \end{enumerate}
+type_e_cant_eval_constant_expr=04011_E_Kann konstanten Ausdruck nicht auswerten
+% This error can occur when the bounds of an array you declared do
+% not evaluate to ordinal constants.
+type_e_set_element_are_not_comp=04012_E_Set-Elemente sind nicht kompatibel
+% You are trying to perform an operation on two sets, when the set element types
+% are not the same. The base type of a set must be the same when taking the
+% union.
+type_e_set_operation_unknown=04013_E_Operation fr Sets nicht implementiert
+% several binary operations are not defined for sets.
+% These include: \var{div}, \var{mod}, \var{**}, \var{>=} and \var{<=}.
+% The last two may be defined for sets in the future.
+type_w_convert_real_2_comp=04014_W_Automatische Typumwandlung von Fliesskommatyp nach COMP (=integer mit 64 bit)
+% An implicit type conversion from a real type to a \var{comp} is
+% encountered. Since \var{Comp} is a 64 bit integer type, this may indicate
+% an error.
+type_h_use_div_for_int=04015_H_Verwenden sie DIV um ein Integer-Ergebnis zu erhalten
+% When hints are on, then an integer division with the '/' operator will
+% produce this message, because the result will then be of type real.
+type_e_strict_var_string_violation=04016_E_Stringtypen mssen im "$V+"-Modus exakt bereinstimmen
+% When compiling in \var{\{\$V+\}} mode, the string you pass as a parameter
+% should be of the exact same type as the declared parameter of the procedure.
+type_e_succ_and_pred_enums_with_assign_not_possible=04017_E_Succ oder Pred kann nicht auf Aufz„hlungen mit Zuweisungen angewendet werden
+% If you declare an enumeration type which has C-like assignments
+% in it, such as in the following:
+% \begin{verbatim}
+% Tenum = (a,b,e:=5);
+% \end{verbatim}
+% then you cannot use the \var{Succ} or \var{Pred} functions with this enumeration.
+type_e_cant_read_write_type=04018_E_Kann Variablen dieses Typs nicht lesen oder schreiben
+% You are trying to \var{read} or \var{write} a variable from or to a
+% file of type text, which doesn't support that variable's type.
+% Only integer types, reals, pchars and strings can be read from or
+% written to a text file. Booleans can only be written to text files.
+type_e_no_readln_writeln_for_typed_file=04019_E_Kann ReadLn und WriteLn nicht bei typisierten Dateien verwenden
+% \var{readln} and \var{writeln} are only allowed for text files.
+type_e_no_read_write_for_untyped_file=04020_E_Kann Read und Write nicht bei untypisierten Dateien verwenden
+% \var{read} and \var{write} are only allowed for text or typed files.
+type_e_typeconflict_in_set=04021_E_Typkonflikt zwischen den Elementen des Sets
+% There is at least one set element which is of the wrong type, i.e. not of
+% the set type.
+type_w_maybe_wrong_hi_lo=04022_W_lo/hi(dword/qword) gibt oberes/unteres Word/DWord zurck
+% \fpc supports an overloaded version of \var{lo/hi} for \var{longint/dword/int64/qword}
+% which returns the lower/upper word/dword of the argument. \tp always uses
+% a 16 bit \var{lo/hi} which always returns bits 0..7 for \var{lo} and the
+% bits 8..15 for \var{hi}. If you want the \tp behavior you have
+% to type cast the argument to a \var{word} or \var{integer}.
+type_e_integer_or_real_expr_expected=04023_E_Integer- oder Real-Ausdruck erwartet
+% The first argument to \var{str} must be a real or integer type.
+type_e_wrong_type_in_array_constructor=04024_E_Falscher Typ "$1" im Array-Konstruktor
+% You are trying to use a type in an array constructor which is not
+% allowed.
+type_e_wrong_parameter_type=04025_E_Inkompatible Typen fr Argument Nr. #$1: habe $2 erhalten, aber $3 erwartet
+% You are trying to pass an invalid type for the specified parameter.
+type_e_no_method_and_procedure_not_compatible=04026_E_Methode (Variable) und Prozedur (Variable) sind nicht kompatibel
+% You can't assign a method to a procedure variable or a procedure to a
+% method pointer.
+type_e_wrong_math_argument=04027_E_Unzul„ssige Konstante an interne Algebrafunktion bergeben
+% The constant argument passed to a \var{ln} or \var{sqrt} function is out of
+% the definition range of these functions.
+type_e_no_addr_of_constant=04028_E_Von Konstanten kann keine Adresse bestimmt werden
+% It's not possible to get the address of a constant, because they
+% aren't stored in memory, you can try making it a typed constant. This error
+% can also be displayed if you try to pass a property to a var parameter.
+type_e_argument_cant_be_assigned=04029_E_An das Argument kann nichts zugewiesen werden
+% Only expressions which can be on the left side of an
+% assignment can be passed as call by reference arguments.
+%
+% Remark: Properties can be used on the left side of an assignment,
+% nevertheless they cannot be used as arguments.
+type_e_cannot_local_proc_to_procvar=04030_E_Kann lokale Prozedur/Funktion nicht an Prozedurvariable zuweisen
+% It's not allowed to assign a local procedure/function to a
+% procedure variable, because the calling convention of a local procedure/function is
+% different. You can only assign local procedure/function to a void pointer.
+type_e_no_assign_to_addr=04031_E_Kann einer Adresse keine Werte zuweisen
+% It's not allowed to assign a value to an address of a variable,constant,
+% procedure or function. You can try compiling with -So if the identifier
+% is a procedure variable.
+type_e_no_assign_to_const=04032_E_Kann einer Konstanten keine Werte zuweisen
+% It's not allowed to assign a value to a variable which is declared
+% as a const. This is normally a parameter declared as const. To allow
+% changing the value, pass the parameter by value, or a parameter by reference
+% (using var).
+type_e_array_required=04033_E_Array Typ notwendig
+% If you are accessing a variable using an index '[<x>]' then
+% the type must be an array. In FPC mode a pointer is also allowed.
+type_e_interface_type_expected=04034_E_Interface Typ erwartet, aber "$1" erhalten
+% The compiler expected to encounter an interface type name, but got something else.
+% The following code would produce this error:
+% \begin{verbatim}
+% Type
+% TMyStream = Class(TStream,Integer)
+% \end{verbatim}
+type_h_mixed_signed_unsigned=04035_H_Mischen von signed Ausdrcken und Longwords ergibt ein 64bit Ergebnis
+% If you divide (or calculate the modulus of) a signed expression by a longword (or vice versa),
+% or if you have overflow and/or range checking turned on and use an arithmetic
+% expression (+, -, *, div, mod) in which both signed numbers and longwords appear,
+% then everything has to be evaluated in 64-bit arithmetic which is slower than normal
+% 32-bit arithmetic. You can avoid this by typecasting one operand so it
+% matches the result type of the other one.
+type_w_mixed_signed_unsigned2=04036_W_Mischen von signed Ausdrcken und kardinalen Typen hier kann einen Bereichsprfungsfehler verursachen
+% If you use a binary operator (and, or, xor) and one of
+% the operands is a longword while the other one is a signed expression, then,
+% if range checking is turned on, you may get a range check error because in
+% such a case both operands are converted to longword before the operation is
+% carried out. You can avoid this by typecasting one operand so it
+% matches the result type of the other one.
+type_e_typecast_wrong_size_for_assignment=04037_E_Typecast hat verschiedene Gr”ssen ($1 -> $2) in der Zuweisung
+% Type casting to a type with a different size is not allowed when the variable is
+% used in an assignment.
+type_e_array_index_enums_with_assign_not_possible=04038_E_enums mit Zuweisungen k”nnen nicht als Array-Index verwendet werden
+% When you declared an enumeration type which has C-like
+% assignments, such as in the following:
+% \begin{verbatim}
+% Tenum = (a,b,e:=5);
+% \end{verbatim}
+% you cannot use it as the index of an array.
+type_e_classes_not_related=04039_E_Klassen- oder Objekttypen "$1" and "$2" sind nicht verwandt
+% There is a typecast from one class or object to another while the class/object
+% are not related. This will probably lead to errors.
+type_w_classes_not_related=04040_W_Klassentypen "$1" und "$2" sind nicht verwandt
+% There is a typecast from one class to another while the classes
+% are not related. This will probably lead to errors.
+type_e_class_or_interface_type_expected=04041_E_Klassen- oder Interface-Typ erwartet, aber "$1" erhalten
+% The compiler expected a class or interface name, but got another type or identifier.
+type_e_type_is_not_completly_defined=04042_E_Typ "$1" ist nicht vollst„ndig definiert
+% This error occurs when a type is not complete: i.e. a pointer type which points to
+% an undefined type.
+type_w_string_too_long=04043_W_String literal hat mehr Zeichen als short string length
+% The size of the constant string, which is assigned to a shortstring,
+% is longer than the maximum size of the shortstring (255 characters).
+type_w_comparison_always_false=04044_W_Wegen der Bereiche der Konstanten und des Ausdrucks k”nnte das Vergleichsergebnis immer falsch sein
+% There is a comparison between a constant and an expression where the constant is out of the
+% valid range of values of the expression. Because of type promotion, the statement will always evaluate to
+% false. Explicitly typecast the constant or the expression to the correct range to avoid this warning
+% if you think the code is correct.
+type_w_comparison_always_true=04045_W_Wegen der Bereiche der Konstanten und des Ausdrucks k”nnte das Vergleichsergebnis immer richtig sein
+% There is a comparison between a constant and an expression where the constant is out of the
+% valid range of values of the expression. Because of type promotion, the statement will always evaluate to
+% true. Explicitly typecast the constant or the expression to the correct range to avoid this warning
+% if you think the code is correct.
+type_w_instance_with_abstract=04046_W_Konstruktion der Klasse "$1" mit der abstrakten Methode "$2"
+% An instance of a class is created which contains non-implemented abstract
+% methods. This will probably lead to a runtime error 211 in the code if that
+% routine is ever called. All abstract methods should be overridden.
+type_h_in_range_check=04047_H_Der linke Operand des IN Operators sollte byte Gr”sse haben
+% The left operand of the \var{in} operator is not an ordinal or enumeration which fits
+% within 8 bits. This may lead to range check errors. The \var{in} operator
+% currently only supports a left operand which fits within a byte. In the case of
+% enumerations, the size of an element of an enumeration can be controlled with
+% the \var{\{\$PACKENUM\}} or \var{\{\$Zn\}} switches.
+type_w_smaller_possible_range_check=04048_W_Unpassende Typgr”ssen, Gefahr des Datenverlusts oder Bereichsprfungsfehlers
+% There is an assignment to a smaller type than the source type. This means that
+% this may cause a range-check error, or may lead to possible loss of data.
+type_h_smaller_possible_range_check=04049_H_Unpassende Typgr”ssen, Gefahr des Datenverlusts oder Bereichsprfungsfehlers
+% There is an assignment to a smaller type than the source type. This means that
+% this may cause a range-check error, or may lead to possible loss of data.
+type_e_cant_take_address_of_abstract_method=04050_E_Die Adresse einer abstrakten Methode kann nicht verwendet werden
+% An abstract method has no body, so the address of an abstract method can't be taken.
+type_e_assignment_not_allowed=04051_E_Zuweisungen auf formale Parameter und offene Arrays sind nicht m”glich
+% You are trying to assign a value to a formal (untyped var, const or out)
+% parameter, or to an open array.
+type_e_constant_expr_expected=04052_E_Konstanter Ausdruck erwartet
+% The compiler expects an constant expression, but gets a variable expression.
+type_e_operator_not_supported_for_types=04053_E_Operation "$1" wird fr die Typen "$2" und "$3" nicht untersttzt
+% The operation is not allowed for the supplied types.
+type_e_illegal_type_conversion=04054_E_Illegale Typ-Konversion: "$1" nach "$2"
+% When doing a type-cast, you must take care that the sizes of the variable and
+% the destination type are the same.
+type_h_pointer_to_longint_conv_not_portable=04055_H_Konversion zwischen ordinalen Typen und Zeigern ist nicht portierbar
+% If you typecast a pointer to a longint (or vice-versa), this code will not compile
+% on a machine using 64 bits addressing.
+type_w_pointer_to_longint_conv_not_portable=04056_W_Konversion zwischen ordinalen Typen und Zeigern ist nicht portierbar
+% If you typecast a pointer to an ordinal type of a different size (or vice-versa), this can
+% cause problems. This is a warning to help in finding the 32-bit specific code where cardinal/longint is used
+% to typecast pointers to ordinals. A solution is to use the ptrint/ptruint types instead.
+type_e_cant_choose_overload_function=04057_E_Kann nicht bestimmen, welche der berladenen Funktionen aufgerufen werden soll
+% You're calling overloaded functions with a parameter that doesn't correspond
+% to any of the declared function parameter lists. e.g. when you have declared
+% a function with parameters \var{word} and \var{longint}, and then you call
+% it with a parameter which is of type \var{integer}.
+type_e_illegal_count_var=04058_E_Loop-Variable muss einen ordinalen Typ haben
+% The type of a \var{for} loop variable must be an ordinal type.
+% Loop variables cannot be reals or strings.
+type_w_double_c_varargs=04059_W_Der konstante Wert vom Typ real wird fr ein C Variablen-Argument zu double konvertiert. Erg„nze eine explizite Typ-Konversion (typecast), um das zu verhindern
+% In C, constant real values are double by default. For this reason, if you
+% pass a constant real value to a variable argument part of a C function, FPC
+% by default converts this constant to double as well. If you want to prevent
+% this from happening, add an explicit typecast around the constant.
+type_e_class_or_cominterface_type_expected=04060_E_Class oder COM interface Typ erwartet, statt dessen "$1" erhalten
+% Some operators, such as the AS operator, are only applicable to classes or COM interfaces.
+type_e_no_const_packed_array=04061_E_Konstante packed Arrays werden noch nicht untersttzt
+% You cannot declare a (bit)packed array as a typed constant.
+type_e_got_expected_packed_array=04062_E_Inkompatibler Typ fr Argument $1: Erhielt "$2" erwartete "(Bit)Packed Array"
+% The compiler expects a (bit)packed array as the specified parameter.
+type_e_got_expected_unpacked_array=04063_E_Inkompatibler Typ fr Argument $1: Erhielt "$2" erwartete "(not packed) Array"
+% The compiler expects a regular (i.e., not packed) array as the specified parameter.
+type_e_no_packed_inittable=04064_E_Elemente von packed Arrays k”nnen nicht von einem Typ sein, der initialisiert werden muss
+% Support for packed arrays of types that need initialization
+% (such as ansistrings, or records which contain ansistrings) is not yet implemented.
+type_e_no_const_packed_record=04065_E_Konstante packed Records und Objekte werden noch nicht untersttzt
+% You cannot declare a (bit)packed array as a typed constant at this time.
+type_w_untyped_arithmetic_unportable=04066_W_Arithmetik "$1" mit typenlosem Pointer ist nicht portierbar nach {$T+}, schlage typecast vor
+% Addition/subtraction from an untyped pointer may work differently in \var{\{\$T+\}}.
+% Use a typecast to a typed pointer.
+type_e_cant_take_address_of_local_subroutine=04076_E_Die Address einer Subroutine, die als local markiert ist, kann nicht verwendet werden
+% The address of a subroutine marked as local can't be taken.
+type_e_cant_export_local=04077_E_Eine Subroutine, die aus einer Unit als local markiert ist, kann nicht exportiert werden
+% A subroutine marked as local can't be exported from a unit.
+type_e_not_automatable=04078_E_Typ "$1" ist nicht "automatable"
+% Only byte, integer, longint, smallint, currency, single, double, ansistring,
+% widestring, tdatetime, variant, olevariant, wordbool and all interfaces are automatable.
+type_h_convert_add_operands_to_prevent_overflow=04079_H_Konvertierung des Operanden "$1" vor der Addition k”nnte šberlauf Fehler verhindern
+% Adding two types can cause overflow errors. Since you are converting the result to a larger type, you
+% could prevent such errors by converting the operands to this type before doing the addition.
+type_h_convert_sub_operands_to_prevent_overflow=04080_H_Konvertierung des Operanden "$1" vor der Subtraktion k”nnte šberlauf Fehler verhindern
+% Subtracting two types can cause overflow errors. Since you are converting the result to a larger type, you
+% could prevent such errors by converting the operands to this type before doing the subtraction.
+type_h_convert_mul_operands_to_prevent_overflow=04081_H_Konvertierung des Operanden "$1" vor der Multiplikation k”nnte šberlauf Fehler verhindern
+% Multiplying two types can cause overflow errors. Since you are converting the result to a larger type, you
+% could prevent such errors by converting the operands to this type before doing the multiplication.
+type_w_pointer_to_signed=04082_W_Die Konvertierung von Pointern in einen Integertyp mit Vorzeichen kann zu falschen Ergebnissen bei Vergleichen und zu Bereichsberschreitungen fhren; verwenden sie statt dessen besser einen Typ ohne Vorzeichen
+% The virtual address space on 32-bit machines runs from \$00000000 to \$ffffffff.
+% Many operating systems allow you to allocate memory above \$80000000.
+% For example both \windows and \linux allow pointers in the range \$0000000 to \$bfffffff.
+% If you convert pointers to signed types, this can cause overflow and range check errors,
+% but also \$80000000 < \$7fffffff. This can cause random errors in code like "if p>q".
+type_e_interface_has_no_guid=04083_E_Interface Typ $1 hat keine gltige GUID
+% When applying the as-operator to an interface or class, the desired interface (i.e. the right operand of the
+% as-operator) must have a valid GUID.
+type_e_invalid_objc_selector_name=04084_E_Ungltiger Objective-C-Selector-Name "$1"
+% An Objective-C selector cannot be empty, must be a valid identifier or a single colon,
+% and if it contains at least one colon it must also end in one.
+type_e_expected_objc_method_but_got=04085_E_Erwartete eine Objective-C-Methode, erhielt aber $1
+% A selector can only be created for Objective-C methods, not for any other kind
+% of procedure/function/method.
+type_e_expected_objc_method=04086_E_Erwartete eine Objective-C-Methode, oder den Namen einer konstanten Methode
+% A selector can only be created for Objective-C methods, either by specifying
+% the name using a string constant, or by using an Objective-C method identifier
+% that is visible in the current scope.
+type_e_no_type_info=04087_E_Fr diesen Typ steht keine Typ-Information zu Verfgung
+% Type information is not generated for some types, such as enumerations with gaps
+% in their value range (this includes enumerations whose lower bound is different
+% from zero).
+type_e_ordinal_or_string_expr_expected=04088_E_Ausdruck mit ordinalem Typ oder Zeichenkette erwartet
+% The expression must be an ordinal or string type.
+type_e_string_expr_expected=04089_E_Ausdruck mit Zeichenkette erwartet
+% The expression must be a string type.
+type_w_zero_to_nil=04090_W_Konvertiere 0 zu NIL
+% Use NIL rather than 0 when initialising a pointer.
+type_e_protocol_type_expected=04091_E_Objective-C Protokolltyp erwartet, erhielt aber "$1"
+% The compiler expected a protocol type name, but found something else.
+type_e_objc_type_unsupported=04092_E_Der Typ "$1" wird nicht fr die Verwendung mit der Objective-C Laufzeitumgebung untersttzt.
+% Objective-C makes extensive use of run time type information (RTTI). This format
+% is defined by the maintainers of the run time and can therefore not be adapted
+% to all possible Object Pascal types. In particular, types that depend on
+% reference counting by the compiler (such as ansistrings and certain kinds of
+% interfaces) cannot be used as fields of Objective-C classes, cannot be
+% directly passed to Objective-C methods, and cannot be encoded using \var{objc\_encode}.
+type_e_class_or_objcclass_type_expected=04093_E_Klasse oder Objective-C Klasse als Typ erwartet, erhielt aber "$1"
+% It is only possible to create class reference types of \var{class} and \var{objcclass}
+type_e_objcclass_type_expected=04094_E_Objective-C Klasse als Typ erwartet
+% The compiler expected an \var{objcclass} type
+type_w_procvar_univ_conflicting_para=04095_W_Erzwungener univ Parameter Typ in einer prozeduralen Variablen kann einen Absturz oder SpeicherKorruption verursachen: $1 auf $2
+% \var{univ} parameters are implicitly compatible with all types of the same size,
+% also in procedural variable definitions. That means that the following code is
+% legal, because \var{single} and \var{longint} have the same size:
+% \begin{verbatim}
+% {$mode macpas}
+% Type
+% TIntProc = procedure (l: univ longint);
+%
+% procedure test(s: single);
+% begin
+% writeln(s);
+% end;
+%
+% var
+% p: TIntProc;
+% begin
+% p:=test;
+% p(4);
+% end.
+% \end{verbatim}
+% This code may however crash on platforms that pass integers in registers and
+% floating point values on the stack, because then the stack will be unbalanced.
+% Note that this warning will not flagg all potentially dangerous situations.
+% when \var{test} returns.
+type_e_generics_cannot_reference_itself=04096_E_Typ-Parameter bei der Spezialisation von Generics k”nnen den aktuel spezialisierten Typ nicht referenzieren
+% Recursive specializations of generics like \var{Type MyType = specialize MyGeneric<MyType>;} are not possible.
+type_e_type_parameters_are_not_allowed_here=04097_E_Typ-Parameter sind fr nicht-generische Klassen/Record/Objekte Prozeduren und Funktionen nicht erlaubt
+% Type parameters are only allowed for methods of generic classes, records or objects
+type_e_generic_declaration_does_not_match=04098_E_Die generische Deklaration von "$1" unterscheidet sich vom der vorherigen Deklaration
+% Generic declaration does not match the previous declaration
+type_e_helper_type_expected=04099_E_Helfertyp erwartet
+% The compiler expected a \var{class helper} type.
+type_e_record_type_expected=04100_E_Recordtyp erwartet
+% The compiler expected a \var{record} type.
+type_e_class_helper_must_extend_subclass=04101_E_Abgeleitete Klassenhelfer mssen eine Unterklasse von "$1" oder die Klasse selbst erweitern
+% If a class helper inherits from another class helper the extended class must
+% extend either the same class as the parent class helper or a subclass of it
+type_e_record_helper_must_extend_same_record=04102_E_Abgeleitete Recordhelfer mssen "$1" erweitern
+% If a record helper inherits from another record helper it must extend the same
+% record that the parent record helper extended.
+type_e_procedures_return_no_value=04103_E_Ungltige Zuweisung, eine Prozedur gibt keinen Wert zurck
+% This error occurs when one tries to assign the result of a procedure or destructor call.
+% A procedure or destructor returns no value so this is not
+% possible.
+%
+% \end{description}
+# EndOfTeX
+
+#
+# Symtable
+#
+# 05084 is the last used one
+#
+% \section{Symbol handling}
+% This section lists all the messages that concern the handling of symbols.
+% This means all things that have to do with procedure and variable names.
+% \begin{description}
+sym_e_id_not_found=05000_E_Bezeichner "$1" nicht gefunden
+% The compiler doesn't know this symbol. Usually happens when you misspell
+% the name of a variable or procedure, or when you forget to declare a
+% variable.
+sym_f_internal_error_in_symtablestack=05001_F_Interner Fehler in SymTableStack()
+% An internal error occurred in the compiler; If you encounter such an error,
+% please contact the developers and try to provide an exact description of
+% the circumstances in which the error occurs.
+sym_e_duplicate_id=05002_E_Doppelter Bezeichner "$1"
+% The identifier was already declared in the current scope.
+sym_h_duplicate_id_where=05003_H_Bezeichner ist bereits definiert in $1 in Zeile $2
+% The identifier was already declared in a previous scope.
+sym_e_unknown_id=05004_E_Unbekannter Bezeichner "$1"
+% The identifier encountered hasn't been declared, or is used outside the
+% scope where it's defined.
+sym_e_forward_not_resolved=05005_E_Forward-Deklaration "$1" nicht gefunden
+% This can happen in two cases:
+% \begin{itemize}
+% \item You declare a function in the \var{interface} part, or
+% with a \var{forward} directive, but do not implement it.
+% \item You reference a type which isn't declared in the current \var{type}
+% block.
+% \end{itemize}
+sym_e_error_in_type_def=05007_E_Fehler in Typdefinition
+% There is an error in your definition of a new array type.
+% One of the range delimiters in an array declaration is erroneous.
+% For example, \var{Array [1..1.25]} will trigger this error.
+sym_e_forward_type_not_resolved=05009_E_Forward-Typ "$1" nicht gefunden
+% The compiler encountered an unknown type.
+sym_e_only_static_in_static=05010_E_Nur statische Variablen k”nnen in statischen oder „usseren Methoden verwendet werden
+% A static method of an object can only access static variables.
+sym_f_type_must_be_rec_or_class=05012_F_Record- oder Klassen-Typ erwartet
+% The variable or expression isn't of the type \var{record} or \var{class}.
+sym_e_no_instance_of_abstract_object=05013_E_Instanzen von Klassen oder Objekten mit abstrakten Methoden sind unzul„ssig
+% You are trying to generate an instance of a class which has an abstract
+% method that wasn't overridden.
+sym_w_label_not_defined=05014_W_Label "$1" nicht definiert
+% A label was declared, but not defined.
+sym_e_label_used_and_not_defined=05015_E_Label "$1" benutzt aber nicht definiert
+% A label was declared and used, but not defined.
+sym_e_ill_label_decl=05016_E_Ungltige Label-Deklaration
+% This error should never happen; it occurs if a label is defined outside a
+% procedure or function.
+sym_e_goto_and_label_not_supported=05017_E_GOTO und LABEL werden nicht untersttzt (verwenden Sie den Schalter -Sg)
+% You must use the -Sg switch to compile a program which has \var{label}s
+% and \var{goto} statements. By default, \var{label} and \var{goto} aren't
+% supported.
+sym_e_label_not_found=05018_E_Label nicht gefunden
+% A \var{goto label} was encountered, but the label wasn't declared.
+sym_e_id_is_no_label_id=05019_E_Bezeichner ist kein Label
+% The identifier specified after the \var{goto} isn't of type label.
+sym_e_label_already_defined=05020_E_Label ist bereits definiert
+% You are defining a label twice. You can define a label only once.
+sym_e_ill_type_decl_set=05021_E_Ungltige Typdeklaration von Set-Elementen
+% The declaration of a set contains an invalid type definition.
+sym_e_class_forward_not_resolved=05022_E_Forward-Klassendefinition nicht gefunden: $1
+% You declared a class, but you didn't implement it.
+sym_n_unit_not_used=05023_H_Unit "$1" wird von "$2" nicht verwendet
+% The unit referenced in the \var{uses} clause is not used.
+sym_h_para_identifier_not_used=05024_H_Parameter nicht verwendet: $1
+% This is a warning. The identifier was declared (locally or globally) but
+% wasn't used (locally or globally).
+sym_n_local_identifier_not_used=05025_N_Lokale Variable nicht verwendet: $1
+% You have declared, but not used, a variable in a procedure or function
+% implementation.
+sym_h_para_identifier_only_set=05026_H_Werte-Parameter "$1" wurde zugewiesen, aber nie verwendet
+% The identifier was declared (locally or globally) and
+% assigned to, but is not used (locally or globally) after the assignment.
+sym_n_local_identifier_only_set=05027_N_Lokale Variable "$1" wurde zugewiesen, aber nicht verwendet
+% The variable in a procedure or function implementation is declared and
+% assigned to, but is not used after the assignment.
+sym_h_local_symbol_not_used=05028_H_Lokales $1-Element "$2" wird nicht verwendet
+% A local symbol is never used.
+sym_n_private_identifier_not_used=05029_N_Privates Feld $1.$2 wird nie verwendet
+% The indicated private field is defined, but is never used in the code.
+sym_n_private_identifier_only_set=05030_N_Privates Feld $1.$2 wurde zugewiesen, aber nie verwendet
+% The indicated private field is declared and assigned to, but never read.
+sym_n_private_method_not_used=05031_N_Private Methode $1.$2 wird nie verwendet
+% The indicated private method is declared but is never used in the code.
+sym_e_set_expected=05032_E_Mengentyp erwartet
+% The variable or expression isn't of type \var{set}. This happens in an
+% \var{in} statement.
+sym_w_function_result_not_set=05033_W_Funktionsergebnis scheint nicht gesetzt zu sein
+% You can get this warning if the compiler thinks that a function return
+% value is not set. This will not be displayed for assembler procedures,
+% or procedures that contain assembler blocks.
+sym_w_wrong_C_pack=05034_W_Typ "$1" ist im aktuellen Record mit C-Packing nicht korrekt ausgerichtet
+% Arrays with sizes not multiples of 4 will be wrongly aligned
+% for C structures.
+sym_e_illegal_field=05035_E_Unbekannter Record-Feldbezeichner $1
+% The field doesn't exist in the record definition.
+sym_w_uninitialized_local_variable=05036_W_Lokale Variable "$1" wird verwendet, bevor ihr ein Wert zugewiesen wurde
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. it appears in the right-hand side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assignment).
+sym_w_uninitialized_variable=05037_W_Variable "$1" scheint nicht initialisiert worden zu sein
+% These messages are displayed if the compiler thinks that a variable will
+% be used (i.e. it appears in the right-hand side of an expression) when it
+% wasn't initialized first (i.e. appeared in the left-hand side of an
+% assignassignmentment).
+sym_e_id_no_member=05038_E_Bezeichener verweist nicht auf ein Element: $1
+% This error is generated when an identifier of a record,
+% field or method is accessed while it is not defined.
+sym_h_param_list=05039_H_Deklaration gefunden: $1
+% You get this when you use the \var{-vh} switch.In the case of an overloaded procedure
+% not being found. Then all candidate overloaded procedures are
+% listed, with their parameter lists.
+sym_e_segment_too_large=05040_E_Datensegment zu gross (max. 2GB)
+% You get this when you declare a data element whose size exceeds the
+% prescribed limit (2 Gb on 80386+/68020+ processors).
+sym_e_no_matching_implementation_found=05042_E_Keine passende Implementation der Interface Methode "$1" gefunden
+% There was no matching method found which could implement the interface
+% method. Check argument types and result type of the methods.
+sym_w_deprecated_symbol=05043_W_Symbol "$1" ist veraltet
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{deprecated} is used. Deprecated symbols may no longer
+% be available in newer versions of the unit / library. Use of this symbol
+% should be avoided as much as possible.
+sym_w_non_portable_symbol=05044_W_Symbol "$1" ist nicht portierbar
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{platform} is used. This symbol's value, use
+% and availability is platform specific and should not be used
+% if the source code must be portable.
+sym_w_non_implemented_symbol=05055_W_Symbol "$1" ist nicht implementiert
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{unimplemented} is used. This symbol is defined,
+% but is not yet implemented on this specific platform.
+sym_e_cant_create_unique_type=05056_E_Von diesem Typ kann kein eindeutiger Typ deklariert werden
+% Only simple types like ordinal, float and string types are supported when
+% redefining a type with \var{type newtype = type oldtype;}.
+sym_h_uninitialized_local_variable=05057_H_Die Variable "$1" scheint nicht initialisiert zu sein
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. it appears in the right-hand side of an expression) when it
+% was not initialized first (i.e. it did not appear in the left-hand side of an
+% assignment).
+sym_h_uninitialized_variable=05058_H_Die Variable "$1" scheint nicht initialisiert zu sein
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. it appears in the right-hand side of an expression) when it
+% was not initialized first (i.e. t did not appear in the left-hand side of an
+% assignment).
+sym_w_function_result_uninitialized=05059_W_Die Ergebnisvariable der Funktion scheint nicht initialisiert zu sein
+% This message is displayed if the compiler thinks that the function result
+% variable will be used (i.e. it appears in the right-hand side of an expression)
+% before it is initialized (i.e. before it appeared in the left-hand side of an
+% assignment).
+sym_h_function_result_uninitialized=05060_H_Die Ergebnisvariable der Funktion scheint nicht initialisiert zu sein
+% This message is displayed if the compiler thinks that the function result
+% variable will be used (i.e. it appears in the right-hand side of an expression)
+% before it is initialized (i.e. it appears in the left-hand side of an
+% assignment)
+sym_w_identifier_only_read=05061_W_Die Variable "$1" wird gelesen, obwohl ihr aber noch kein Wert zugewiesen wurde
+% You have read the value of a variable, but nowhere assigned a value to
+% it.
+sym_h_abstract_method_list=05062_H_Abstrakte Method "$1" gefunden
+% When getting a warning about constructing a class/object with abstract methods
+% you get this hint to assist you in finding the affected method.
+sym_w_experimental_symbol=05063_W_Symbol "$1" ist experimentell
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{experimental} is used. Experimental symbols
+% might disappear or change semantics in future versions. Usage of this symbol
+% should be avoided as much as possible.
+sym_w_forward_not_resolved=05064_W_Forward Deklaration "$1" wird nicht aufgel”st und deshalb als extern angenommen
+% This happens if you declare a function in the \var{interface} of a unit in macpas mode,
+% but do not implement it.
+sym_w_library_symbol=05065_W_Symbol "$1" geh”rt zu einer Bibliothek
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{library} is used. Library symbols may not be
+% available in other libraries.
+sym_w_deprecated_symbol_with_msg=05066_W_Symbol "$1" ist veraltet: "$2"
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{deprecated} is used. Deprecated symbols may no longer
+% be available in newer versions of the unit / library. Use of this symbol
+% should be avoided as much as possible.
+sym_e_no_enumerator=05067_E_Kann keinen Z„hler fr den Typ "$1" finden
+% This means that compiler cannot find an apropriate enumerator to use in the for-in loop.
+% To create an enumerator you need to defind an operator enumerator or add a public or published
+% GetEnumerator method to the class or object definition.
+sym_e_no_enumerator_move=05068_E_Kann keine Methode "MoveNext" in der Aufz„hlung "$1" finden
+% This means that compiler cannot find a public MoveNext method with the Boolean return type in
+% the enumerator class or object definition.
+sym_e_no_enumerator_current=05069_E_Kann keine Eigenschaft "Current" in der Aufz„hlung "$1" finden
+% This means that compiler cannot find a public Current property in the enumerator class or object
+% definition.
+sym_e_objc_para_mismatch=05070_E_Die Anzahl der deklarierten Parameter und die Anzahl der Doppelpunkte in der Nachrichtenzeichenkette stimmen nicht berein
+% In Objective-C, a message name automatically contains as many colons as parameters.
+% In order to prevent mistakes when specifying the message name in FPC, the compiler
+% checks whether this is also the case here. Note that in case of messages taking a
+% variable number of arguments translated to FPC via an \var{array of const} parameter,
+% this final \var{array of const} parameter is not counted. Neither are the hidden
+% \var{self} and \var{\_cmd} parameters.
+sym_n_private_type_not_used=05071_N_Privater Typ "$1.$2" wird nie benutzt
+% The indicated private type is declared but is never used in the code.
+sym_n_private_const_not_used=05072_N_Private Konstante "$1.$2" wird nie benutzt
+% The indicated private const is declared but is never used in the code.
+sym_n_private_property_not_used=05073_N_Private Eigenschaft "$1.$2" wird nie benutzt
+% The indicated private property is declared but is never used in the code.
+sym_w_deprecated_unit=05074_W_Unit "$1" ist veraltet
+% This means that a unit which is
+% declared as \var{deprecated} is used. Deprecated units may no longer
+% be available in newer versions of the library. Use of this unit
+% should be avoided as much as possible.
+sym_w_deprecated_unit_with_msg=05075_W_Unit "$1" ist veraltet: "$2"
+% This means that a unit which is
+% declared as \var{deprecated} is used. Deprecated units may no longer
+% be available in newer versions of the library. Use of this unit
+% should be avoided as much as possible.
+sym_w_non_portable_unit=05076_W_Unit "$1" ist plattformabh„ngig
+% This means that a unit which is
+% declared as \var{platform} is used. This unit use
+% and availability is platform specific and should not be used
+% if the source code must be portable.
+sym_w_library_unit=05077_W_Unit "$1" geh”rt zu einer Bibliothek
+% This means that a unit which is
+% declared as \var{library} is used. Library units may not be
+% available in other libraries.
+sym_w_non_implemented_unit=05078_W_Unit "$1" ist nicht implementiert
+% This means that a unit which is
+% declared as \var{unimplemented} is used. This unit is defined,
+% but is not yet implemented on this specific platform.
+sym_w_experimental_unit=05079_W_Unit "$1" ist experimentell
+% This means that a unit which is
+% declared as \var{experimental} is used. Experimental units
+% might disappear or change semantics in future versions. Usage of this unit
+% should be avoided as much as possible.
+sym_e_objc_formal_class_not_resolved=05080_E_Die vollst„ndige Definition der formal deklarierten ObjC-Klasse "$1" fehlt in diesem Geltungsbereich
+% Objecive-C classes can be imported formally, without using the the unit in which it is fully declared.
+% This enables making forward references to such classes and breaking circular dependencies amongst units.
+% However, as soon as you wish to actually do something with an entity of this class type (such as
+% access one of its fields, send a message to it, or use it to inherit from), the compiler requires the full definition
+% of the class to be in scope.
+sym_e_interprocgoto_into_init_final_code_not_allowed=05081_E_Gotos in die 'initialization'- oder 'finalization'-Bl”cke einer Unit sind nicht erlaubt
+% Gotos into initialization or finalization blockse of units are not allowed.
+sym_e_external_class_name_mismatch1=05082_E_Ungltiger externer Name "$1" fr die formale Klasse "$2"
+sym_e_external_class_name_mismatch2=05083_E_Hierhin muss die vollst„ndige Klassendefinition mit externem Namen "$1"
+% When a class is declared using a formal external definition, the actual external
+% definition (if any) must specify the same external name as the formal definition
+% (since both definitions refer to the same actual class type).
+sym_w_library_overload=05084_W_M”glicher Bibliothekenkonflikt: Das Symbol "$1" aus Bibliothek "$2" wurde auch in Bibliothek "$3" gefunden
+% Some OS do not have library specific namespaces, for those
+% OS, the function declared as "external 'libname' name 'funcname'",
+% the 'libname' part is only a hint, funcname might also be loaded
+% by another library. This warning appears if 'funcname' is used twice
+% with two different library names.
+%
+% \end{description}
+# EndOfTeX
+
+#
+# Codegenerator
+#
+# 06052 is the last used one
+#
+% \section{Code generator messages}
+% This section lists all messages that can be displayed if the code
+% generator encounters an error condition.
+% \begin{description}
+cg_e_parasize_too_big=06009_E_Gr”sse der Parameterliste bersteigt 65535 Bytes
+% The I386 processor limits the parameter list to 65535 bytes. (The \var{RET}
+% instruction causes this).
+cg_e_file_must_call_by_reference=06012_E_Dateitypen mssen VAR Parameter sein
+% You cannot specify files as value parameters, i.e., they must always be
+% declared \var{var} parameters.
+cg_e_cant_use_far_pointer_there=06013_E_Die Verwendung eines FAR-Zeigers ist in dieser Art nicht erlaubt
+% Free Pascal doesn't support far pointers, so you cannot take the address of
+% an expression which has a far reference as a result. The \var{mem} construct
+% has a far reference as a result, so the following code will produce this
+% error:
+% \begin{verbatim}
+% var p : pointer;
+% ...
+% p:=@mem[a000:000];
+% \end{verbatim}
+cg_e_dont_call_exported_direct=06015_E_Mit EXPORT deklarierte Funktionen k”nnen nicht aufgerufen werden
+% No longer in use.
+cg_w_member_cd_call_from_method=06016_W_M”glicherweise unzul„ssiger Aufruf eines Konstruktors oder Destruktors (passt nicht in diesen Kontext)
+% The compiler detected that a constructor or destructor is called within a
+% a method. This will probably lead to problems, since constructors / destructors
+% require parameters on entry.
+cg_n_inefficient_code=06017_N_Uneffiziente Programmierung
+% You construction seems dubious to the compiler.
+cg_w_unreachable_code=06018_W_Code wird niemals ausgefhrt
+% You specified a loop which will never be executed. Example:
+% \begin{verbatim}
+% while false do
+% begin
+% {.. code ...}
+% end;
+% \end{verbatim}
+cg_e_cant_call_abstract_method=06020_E_Abstrakte Methoden k”nnen nicht direkt aufgerufen werden
+% You cannot call an abstract method directly. Instead, you must call an
+% overriding child method, because an abstract method isn't implemented.
+cg_d_register_weight=06027_DL_Register $1 Gewichtung $2 $3
+% Debugging message. Shown when the compiler considers a variable for
+% keeping in the registers.
+cg_d_stackframe_omited=06029_DL_Stackframe wird ausgelassen
+% Some procedure/functions do not need a complete stack-frame, so it is omitted.
+% This message will be displayed when the {-vd} switch is used.
+cg_e_unable_inline_object_methods=06031_E_Objektmethoden k”nnen nicht Inline sein
+% You cannot have inlined object methods.
+cg_e_unable_inline_procvar=06032_E_Procvar-Aufrufe k”nnen nicht Inline sein
+% A procedure with a procedural variable call cannot be inlined.
+cg_e_no_code_for_inline_stored=06033_E_Kein Code fr Inline-Prozedur gespeichert
+% The compiler couldn't store code for the inline procedure.
+cg_e_can_access_element_zero=06035_E_Auf Element Null von Ansi/Wide- oder Longstring kann nicht zugegriffen werden, benutzen Sie stattdessen (Set)Length
+% You should use \var{setlength} to set the length of an ansi/wide/longstring
+% and \var{length} to get the length of such string type.
+cg_e_cannot_call_cons_dest_inside_with=06037_E_Konstruktoren und Destruktoren k”nnen in diesem Kontext nicht aufgerufen werden
+% Inside a \var{With} clause you cannot call a constructor or destructor for the
+% object you have in the \var{with} clause.
+cg_e_cannot_call_message_direct=06038_E_Kann Messagehandler-Methode nicht direkt aufrufen
+% A message method handler method can't be called directly if it contains an
+% explicit \var{Self} argument.
+cg_e_goto_inout_of_exception_block=06039_E_Sprung in- oder aus dem Exceptionblock heraus
+% It is not allowed to jump in or outside of an exception block like \var{try..finally..end;}.
+% For example, the following code will produce this error:
+
+% \begin{verbatim}
+% label 1;
+%
+% ...
+%
+% try
+% if not(final) then
+% goto 1; // this line will cause an error
+% finally
+% ...
+% end;
+% 1:
+% ...
+% \end{verbatim}
+cg_e_control_flow_outside_finally=06040_E_Kontrollfluss-Anweisungen sind in einem Finally-Block nicht erlaubt
+% It isn't allowed to use the control flow statements \var{break},
+% \var{continue} and \var{exit}
+% inside a finally statement. The following example shows the problem:
+% \begin{verbatim}
+% ...
+% try
+% p;
+% finally
+% ...
+% exit; // This exit ISN'T allowed
+% end;
+% ...
+%
+% \end{verbatim}
+% If the procedure \var{p} raises an exception the finally block is
+% executed. If the execution reaches the exit, it's unclear what to do:
+% exit the procedure or search for another exception handler.
+cg_w_parasize_too_big=06041_W_Gr”sse der Parameter berschreitet die Grenze fr bestimmte CPUs
+% This indicates that you are declaring more than 64K of parameters, which
+% might not be supported on other processor targets.
+cg_w_localsize_too_big=06042_W_Gr”sse der lokalen Variablen berschreitet die Grenze fr bestimmte CPUs
+% This indicates that you are declaring more than 32K of local variables, which
+% might not be supported on other processor targets.
+cg_e_localsize_too_big=06043_E_Gr”sse der lokalen Variablen berschreitet die untersttzte Grenze
+% This indicates that you are declaring more than 32K of local variables, which
+% is not supported by this processor.
+cg_e_break_not_allowed=06044_E_BREAK nicht zul„ssig
+% You're trying to use \var{break} outside a loop construction.
+cg_e_continue_not_allowed=06045_E_CONTINUE nicht zul„ssig
+% You're trying to use \var{continue} outside a loop construction.
+cg_f_unknown_compilerproc=06046_F_Unbekannte Compiler-Prozedur "$1". šberprfe, ob die korrekte Laufzeit-Bibliothek verwendet wird
+% The compiler expects that the runtime library contains certain subroutines. If you see this error
+% and you didn't change the runtime library code, it's very likely that the runtime library
+% you're using doesn't match the compiler in use. If you changed the runtime library this error means
+% that you removed a subroutine which the compiler needs for internal use.
+cg_f_unknown_system_type=06047_F_Systemtyp "$1" konnte nicht gefunden werden. šberprfe, ob die korrekte Laufzeit-Bibliothek verwendet wird
+% The compiler expects that the runtime library contains certain type definitions. If you see this error
+% and you didn't change the runtime library code, it's very likely that the runtime library
+% you're using doesn't match the compiler in use. If you changed the runtime library this error means
+% that you removed a type which the compiler needs for internal use.
+cg_h_inherited_ignored=06048_H_Geerbter Aufruf einer abstrakten Methode ignoriert
+% This message appears only in Delphi mode when you call an abstract method
+% of a parent class via \var{inherited;}. The call is then ignored.
+cg_e_goto_label_not_found=06049_E_Goto Label "$1": Das Label ist nicht definiert oder wurde bei der Optimierung entfernt
+% The label used in the goto definition is not defined or optimized away by the
+% unreachable code elemination.
+cg_f_unknown_type_in_unit=06050_F_Kann den Typ "$1" nicht in der Unit "$2" finden. šberprfe, ob die korrekte Laufzeit-Bibliothek verwendet wird
+% The compiler expects that the runtime library contains certain type definitions. If you see this error
+% and you didn't change the runtime library code, it's very likely that the runtime library
+% you're using doesn't match the compiler in use. If you changed the runtime library this error means
+% that you removed a type which the compiler needs for internal use.
+cg_e_interprocedural_goto_only_to_outer_scope_allowed=06051_E_Interprozedurale gotos sind nur in „uáere Subroutines erlaubt
+% Gotos between subroutines are only allowed if the goto jumps from an inner to an outer subroutine or
+% from a subroutine to the main program
+cg_e_labels_cannot_defined_outside_declaration_scope=06052_E_ Label mssen im selben Bereich definiert werden, in dem sie deklariert werden
+% In ISO mode, labels must be defined in the same scope as they are declared.
+cg_e_goto_across_procedures_with_exceptions_not_allowed=06053_E_Eine Prozedur, die explizite oder implizite Excpetion Frames enth„lt, darf nicht mit einem goto verlassen werden
+% Non-local gotos might not be used to leave procedures using exceptions either implicitly or explicitly. Procedures
+% which use automated types like ansistrings or class constructurs are affected by this too.
+%
+% \end{description}
+# EndOfTeX
+
+#
+# Assembler reader
+#
+# 07110 is the last used one
+#
+asmr_d_start_reading=07000_DL_Starte $1 Stil Assembler Parsen
+% This informs you that an assembler block is being parsed
+asmr_d_finish_reading=07001_DL_Beende $1 Stil Assembler Parsen
+% This informs you that an assembler block has finished.
+asmr_e_none_label_contain_at=07002_E_Nicht-Label Bezeichner enth„lt @
+% A identifier which isn't a label can't contain a @.
+asmr_e_building_record_offset=07004_E_Fehler beim Ermitteln des Recordoffsets
+% There has an error occured while building the offset of a record/object
+% structure, this can happend when there is no field specified at all or
+% an unknown field identifier is used.
+asmr_e_offset_without_identifier=07005_E_OFFSET ohne Bezeicner verwendet
+% You can only use OFFSET with an identifier. Other syntaxes aren't
+% supported
+asmr_e_type_without_identifier=07006_E_TYPE verwendet ohne Bezeichner
+% You can only use TYPE with an identifier. Other syntaxes aren't
+% supported
+asmr_e_no_local_or_para_allowed=07007_E_Lokale Variable oder Parameter k”nnen hier nicht verwendet werden
+% You can't use a local variable or parameter here, mostly because the
+% addressing of locals and parameters is done using the %ebp register so the
+% address can't be get directly.
+asmr_e_need_offset=07008_E_Hier muss OFFSET verwendet werden
+% You need to use OFFSET <id> here to get the address of the identifier.
+asmr_e_need_dollar=07009_E_Hier muss "$" verwendet werden
+% You need to use $<id> here to get the address of the identifier.
+asmr_e_cant_have_multiple_relocatable_symbols=07010_E_Verwendung von mehreren verschiebbaren Symbolen nicht m”glich
+% You can't have more than one relocatable symbol (variable/typed constant)
+% in one argument.
+asmr_e_only_add_relocatable_symbol=07011_E_Verschiebbares Symbol kann nur addiert werden
+% Relocatable symbols (variable/typed constant) can't be used with other
+% operators. Only addition is allowed.
+asmr_e_invalid_constant_expression=07012_E_Ungltiger Konstantenausdruck
+% There is an error in the constant expression.
+asmr_e_relocatable_symbol_not_allowed=07013_E_Verschiebbares Symbol ist nicht zul„ssig
+% You can't use a relocatable symbol (variable/typed constant) here.
+asmr_e_invalid_reference_syntax=07014_E_Ungltige Verweis-Syntax
+% There is an error in the reference.
+asmr_e_local_para_unreachable=07015_E_Sie k”nnen "$1" von diesem Code aus nicht erreichen
+% You cannot read directly the value of a local variable or parameter
+% of a higher level procedure in assembler code (except for
+% local assembler code without parameter nor locals).
+asmr_e_local_label_not_allowed_as_ref=07016_E_Lokale Symbole/Labels sind nicht als Referenz zul„ssig
+% You can't use local symbols/labels as references
+asmr_e_wrong_base_index=07017_E_Ungltige Verwendung von Basis- und Index-Registern
+% There is an error with the base and index register, they are
+% probably incorrect
+asmr_w_possible_object_field_bug=07018_W_M”glicher Fehler bei Objektfeld-Behandlung
+% Fields of objects or classes can be reached directly in normal or objfpc
+% modes but TP and Delphi modes treat the field name as a simple offset.
+asmr_e_wrong_scale_factor=07019_E_Falscher Skalierungsfaktor angegeben
+% The scale factor given is wrong, only 1,2,4 and 8 are allowed
+asmr_e_multiple_index=07020_E_Mehrfache Verwendung fon Index-Registern
+% You are trying to use more than one index register
+asmr_e_invalid_operand_type=07021_E_Ungltiger Operandentyp
+% The operand type doesn't match with the opcode used
+asmr_e_invalid_string_as_opcode_operand=07022_E_Unglitge Zeichenkette als Opcode-Operand: $1
+% The string specified as operand is not correct with this opcode
+asmr_w_CODE_and_DATA_not_supported=07023_W_@CODE und @DATA werden nicht untersttzt
+% @CODE and @DATA are unsupported and are ignored.
+asmr_e_null_label_ref_not_allowed=07024_E_Null-Label-Bezug nicht m”glich
+asmr_e_expr_zero_divide=07025_E_Division durch Null in Assembler-Ausdruck
+% There is a division by zero in a constant expression
+asmr_e_expr_illegal=07026_E_Ungltiger Ausdruck
+% There is an illegal expression in a constant expression
+asmr_e_escape_seq_ignored=07027_E_Escape-Sequenz ignoriert: $1
+% There is a C-styled string, but the escape sequence in the string
+% is unknown, and is therefore ignored
+asmr_e_invalid_symbol_ref=07028_E_Ungltige Symbolverwendung
+asmr_w_fwait_emu_prob=07029_W_FWAIT kann Emulationsprobleme mit emu387 verursachen
+asmr_w_fadd_to_faddp=07030_W_$1 ohne Operand wurde in $1P bersetzt
+asmr_w_enter_not_supported_by_linux=07031_W_Der ENTER-Befehl wird vom Linux-Kernel nicht untersttzt
+% ENTER instruction can generate a stack page fault that is not
+% caught correctly by the i386 Linux page handler.
+asmr_w_calling_overload_func=07032_W_Aufruf einer berladenen Funktion in Assembler
+% There is a call to an overloaded method in the assembler block,
+% this might be the sign there is a problem
+asmr_e_unsupported_symbol_type=07033_E_Nicht untersttzter Symboltyp fr Operand
+asmr_e_constant_out_of_bounds=07034_E_Wert der Konstante ausserhalb des zul„ssigen Bereichs
+asmr_e_error_converting_decimal=07035_E_Fehler beim Umwandeln in Dezimal $1
+% A constant decimal value does not have the correct syntax
+asmr_e_error_converting_octal=07036_E_Fehler beim Umwandeln in Oktal $1
+% A constant octal value does not have the correct syntax
+asmr_e_error_converting_binary=07037_E_Fehler beim Umwandeln in Bin„r $1
+% A constant binary value does not have the correct syntax
+asmr_e_error_converting_hexadecimal=07038_E_Fehler beim Umwandeln in Hexadezimal $1
+% A constant hexadecimal value does not have the correct syntax
+asmr_h_direct_global_to_mangled=07039_H_$1 bersetzt nach $2
+asmr_w_direct_global_is_overloaded_func=07040_W_$1 ist einer berladenen Funktion zugeordnet
+asmr_e_cannot_use_SELF_outside_a_method=07041_E_Kann SELF nicht ausserhalb einer Methode verwenden
+% There is a reference to the \var{self} symbol while it is not
+% allowed. \var{self} can only be referenced inside methods
+asmr_e_cannot_use_OLDEBP_outside_nested_procedure=07042_E_Kann OLDEBP ausserhalb einer verschachtelten Prozedur nicht verwenden
+% There is a reference to the \var{oldebp} symbol while it is not
+% allowed. \var{oldebp} can only be referenced inside nested routines
+asmr_e_void_function=07043_W_Prozeduren k”nnen keinen Wert im Assembler-Code zurckliefern
+% Trying to return a value while in a procedure. A procedure
+% does not have any return value
+asmr_e_SEG_not_supported=07044_E_SEG nicht untersttzt
+asmr_e_size_suffix_and_dest_dont_match=07045_E_Gr”ssensuffix und Ziel- oder Quellgr”sse passen nicht zusammen
+% The register size and the opcode size suffix don't match. This is
+% probably an error in the assembler statement
+asmr_w_size_suffix_and_dest_dont_match=07046_W_Gr”ssensuffix und Ziel- oder Quellgr”sse passen nicht zusammen
+% The register size and the opcode size suffix don't match. This is
+% probably an error in the assembler statement
+asmr_e_syntax_error=07047_E_Assembler Syntaxfehler
+% There is an assembler syntax error
+asmr_e_invalid_opcode_and_operand=07048_E_Ungltige Kombination von Opcode und Operanden
+% The opcode cannot be used with this type of operand
+asmr_e_syn_operand=07049_E_Assembler Syntaxfehler im Operanden
+asmr_e_syn_constant=07050_E_Assembler Syntaxfehler in Konstanten
+asmr_e_invalid_string_expression=07051_E_Ungltiger Stringausdruck
+asmr_w_const32bit_for_address=07052_W_Konstante mit Symbol $1 fr Adresse erzeugt, die kein Pointer ist
+% A constant expression represents an address which does not fit
+% into a pointer. The address is probably incorrect
+asmr_e_unknown_opcode=07053_E_Unbekannter Opcode $1
+% This opcode is not known
+asmr_e_invalid_or_missing_opcode=07054_E_Ungltiger oder fehlender Opcode
+asmr_e_invalid_prefix_and_opcode=07055_E_Ungltige Kombination von Prefix und Opcode: $1
+asmr_e_invalid_override_and_opcode=07056_E_Ungltige Kombination von Override und Opcode: $1
+asmr_e_too_many_operands=07057_E_Zu viele Operanden in der Zeile
+% There are too many operands for this opcode. Check your
+% assembler syntax
+asmr_w_near_ignored=07058_W_NEAR ignoriert
+asmr_w_far_ignored=07059_W_FAR ignoriert
+asmr_e_dup_local_sym=07060_E_Doppelters lokales Symbol $1
+asmr_e_unknown_local_sym=07061_E_Undefiniertes lokales Symbol $1
+asmr_e_unknown_label_identifier=07062_E_Unbekannter Label-Bezeichner $1
+asmr_e_invalid_register=07063_E_Ungltiger Registername
+% There is an unknown register name used as operand.
+asmr_e_invalid_fpu_register=07064_E_Ungltiger Name fr Fliesskommaregister
+% There is an unknown register name used as operand.
+asmr_w_modulo_not_supported=07066_W_Modulo nicht untersttzt
+asmr_e_invalid_float_const=07067_E_Ungltige Fliesskommakonstante $1
+% The floating point constant declared in an assembler block is
+% invalid.
+asmr_e_invalid_float_expr=07068_E_Ungltiger Fliesskommaausdruck
+% The floating point expression declared in an assembler block is
+% invalid.
+asmr_e_wrong_sym_type=07069_E_Falscher Symboltyp
+asmr_e_cannot_index_relative_var=07070_E_Kann lokale Variable oder Parameter nicht mit Register indizieren
+% Trying to index using a base register a symbol which is already relative
+% to a register. This is not possible, and will probably lead to crashes.
+asmr_e_invalid_seg_override=07071_E_Ungltiger Segmentoverride-Ausdruck
+asmr_w_id_supposed_external=07072_W_Bezeichner $1 ist vermutlich External
+% There is a reference to an undefined symbol. This will not result
+% in an error, since the symbol might be external, but may cause
+% problems at link time if the symbol is not defined anywhere.
+asmr_e_string_not_allowed_as_const=07073_E_Strings sind als Konstanten unzul„ssig
+% Character strings are not allowed as constants.
+asmr_e_no_var_type_specified=07074_E_Typ der Variablen nicht angegeben
+% The syntax expects a type idenfitifer after the dot, but
+% none was found.
+asmr_w_assembler_code_not_returned_to_text=07075_E_Assemblercode kehrt nicht zum Text zurck
+% There was a directive in the assembler block to change sections,
+% but there is a missing return to the text section at the end
+% of the assembler block. This might cause errors during link time.
+asmr_e_not_directive_or_local_symbol=07076_E_Keine Direktive oder lokales Symbol $1
+% This symbol is unknown.
+asmr_w_using_defined_as_local=07077_E_Verwendung eines definierten Namens als lokales Label
+asmr_e_dollar_without_identifier=07078_E_Dollarzeichen wird ohne Bezeichner verwendet
+% A constant expression has an identifier which does not start with
+% the $ symbol.
+asmr_w_32bit_const_for_address=07079_W_32-Bit-Konstante fr Adresse erzeugt
+% A constant was used as an address. This is probably an error,
+% since using absolute addresses will probably not work.
+asmr_n_align_is_target_specific=07080_N_.align ist abh„ngig von Zielplattform, verwende .balign oder .p2align
+% Using the .align directive is platform specific, and its meaning will vary
+% from one platform to another.
+asmr_e_cannot_access_field_directly_for_parameters=07081_E_Kann fr Parameter nicht direkt auf Felder zugreifen
+% You should load the parameter first into a register and then access the
+% fields using that register.
+asmr_e_cannot_access_object_field_directly=07082_E_Kann auf Felder von Objekten/Klassen nicht direkt zugreifen
+% You should load the self pointer first into a register and then access the
+% fields using the register as base. By default the self pointer is available
+% in the esi register on i386.
+asmr_e_unable_to_determine_reference_size=07083_E_Gr”sse nicht spezifiziert und auch keine M”glichkeit die Gr”sse der Operanden zu bestimmen
+% You should specify explicitly a size for the reference, because
+% the compiler is unable to determine what size (byte,word,dword,etc.) it
+% should use for the reference.
+asmr_e_cannot_use_RESULT_here=07084_E_RESULT kann in dieser Funktion nicht verwendet werden
+% Some functions which return complex types cannot use the \var{result}
+% keyword.
+asmr_w_adding_explicit_args_fXX=07086_W_"$1" ohne Operand bersetzt in "$1 %st,%st(1)"
+asmr_w_adding_explicit_first_arg_fXX=07087_W_"$1 %st(n)" bersetzt in "$1 %st,%st(n)"
+asmr_w_adding_explicit_second_arg_fXX=07088_W_"$1 %st(n)" bersetzt in "$1 %st(n),%st"
+asmr_e_invalid_char_smaller=07089_E_Das Zeichen < ist hier nicht erlaubt
+% The shift operator requires the << characters. Only one
+% of those characters was found.
+asmr_e_invalid_char_greater=07090_E_Das Zeichen > ist hier nicht erlaubt
+% The shift operator requires the >> characters. Only one
+% of those characters was found.
+asmr_w_align_not_supported=07093_W_ALIGN wird nicht untersttzt
+asmr_e_no_inc_and_dec_together=07094_E_Inc und Dec k”nnen nicht gemeinsam vorkommen
+% Trying to use an increment and a decrement within the same
+% opcode on the 680x0. This is impossible.
+asmr_e_invalid_reg_list_in_movem=07095_E_Ungltige Registerliste fr movem
+% Trying to use the \var{movem} opcode with invalid registers
+% to save or restore.
+asmr_e_invalid_reg_list_for_opcode=07096_E_Ungltige Registerliste fr diesen opcode
+asmr_e_higher_cpu_mode_required=07097_E_H”herer cpu Modus notwendig ($1)
+% Trying to use an instruction which is not supported in the current
+% cpu mode. Use a higher cpu generation to be able to use this
+% opcode in your assembler block
+asmr_w_unable_to_determine_reference_size_using_dword=07098_W_Gr”sse nicht spezifiziert und auch keine M”glichkeit die Gr”sse der Operanden zu bestimmen. Es wird DWORD als Voreinstellung verwendet
+% You should specify explicitly a size for the reference, because
+% the compiler is unable to determine what size (byte,word,dword,etc.) it
+% should use for the reference. This warning is only used in Delphi mode where
+% it falls back to use DWORD as default.
+asmr_e_illegal_shifterop_syntax=07099_E_Syntax Fehler beim Analysieren eines shifter Operanden
+% ARM only; ARM assembler supports a so called shifter operand. The used syntax isn't
+% a valid shifter operand. Example for an operation with shifter operand:
+% \begin{verbatim}
+% asm
+% orr r2,r2,r2,lsl #8
+% end;
+% \end{verbatim}
+asmr_e_packed_element=07100_E_Die Adresse der packed Komponente ist nicht an einer Byte Grenze
+% Packed components (record fields and array elements) may start at an arbitrary
+% bit inside a byte. On CPU which do not support bit-addressable memory (which
+% includes all currently supported CPUs by FPC) you will therefore get an error
+% message when trying to index arrays with elements whose size is not a multiple
+% of 8 bits. The same goes for accessing record fields with such an address.
+% multiple of 8 bits.
+asmr_w_unable_to_determine_reference_size_using_byte=07101_W_Gr”sse nicht angegeben und kann auch nicht aus der Gr”sse der Operanden bestimmt werden. Verwende BYTE als Voreinstellung
+% You should specify explicitly a size for the reference, because
+% the compiler is unable to determine what size (byte,word,dword,etc.) it
+% should use for the reference. This warning is only used in Delphi mode where
+% it falls back to use BYTE as default.
+asmr_w_no_direct_ebp_for_parameter=07102_W_Die Verwendung von +offset(%ebp) fr Parameter ist hier ungltig
+% Using direct 8(%ebp) reference for function/procedure parameters is invalid
+% if parameters are in registers.
+asmr_w_direct_ebp_for_parameter_regcall=07103_W_Die Verwendung von +offset(%ebp) ist nicht mit der regcall Konvention kompatibel
+% Using direct 8(%ebp) reference for function/procedure parameters is invalid
+% if parameters are in registers.
+asmr_w_direct_ebp_neg_offset=07104_W_Die Verwendung von -offset(%ebp) wird fr den Zugriff auf lokale Variablen nicht empfohlen
+% Using -8(%ebp) to access a local variable is not recommended
+asmr_w_direct_esp_neg_offset=07105_W_Verwendung von -offset(%esp); Zugriff kann einen Crash oder Datenverlust ausl”sen
+% Using -8(%esp) to access a local stack is not recommended, as
+% this stack portion can be overwritten by any function calls or interrupts.
+asmr_e_no_vmtoffset_possible=07106_E_VMTOffset muss in Kombination mit einer virtuellen Methode verwendet werden; "$1" ist aber nicht virtuell
+% Only virtual methods have VMT offsets
+asmr_e_need_pic_ref=07107_E_Erzeuge eigentlich PIC, aber die Referenz ist nicht PIC-sicher
+% The compiler has been configured to generate position-independent code
+% (PIC), but there are position-dependent references in the current
+% handwritten assembler instruction.
+asmr_e_mixing_regtypes=07108_E_Alle Register in einem Registerset mssen in T und Breite bereinstimmen
+% Instructions on the ARM architecture that take a register set as argument require that all registers
+% in this set are of the same kind (e.g., integer, vfp) and width (e.g., single precision, double precision).
+asmr_e_empty_regset=07109_E_Ein Registerset kann nicht leer sein
+% Instructions on the ARM architecture that take a register set as argument require that such a set
+% contains at least one register.
+asmr_w_useless_got_for_local=07110_W_@GOTPCREL ist nutzlos und bei lokalen Symbole m”glicherweise gef„hrlich
+% The use of @GOTPCREL supposes an extra indirection that is
+% not present if the symbol is local, which might lead to wrong asembler code
+
+#
+# Assembler/binary writers
+#
+# 08022 is the last used one
+#
+asmw_f_too_many_asm_files=08000_F_Zu viele Assembler-Dateien
+% With smartlinking enabled, there are too many assembler
+% files generated. Disable smartlinking.
+asmw_f_assembler_output_not_supported=08001_F_Gew„hlte Assemblerausgabe wird nicht untersttzt
+asmw_f_comp_not_supported=08002_F_Comp nicht untersttzt
+asmw_f_direct_not_supported=08003_F_Direct nicht untersttzt fr bin„res Schreiben
+% Direct assembler mode is not supported for binary writers.
+asmw_e_alloc_data_only_in_bss=08004_E_Allozieren von Daten ist nur in "bss"-Abschnitten zul„ssig
+asmw_f_no_binary_writer_selected=08005_F_Kein Bin„rschreiber ausgew„hlt
+asmw_e_opcode_not_in_table=08006_E_Asm: Opcode $1 nicht in Tabelle enthalten
+asmw_e_invalid_opcode_and_operands=08007_E_Asm: $1 ungltige Kombination von Opcode und Operanden
+asmw_e_16bit_not_supported=08008_E_Asm: 16-Bit-Verweise werden nicht untersttzt
+asmw_e_invalid_effective_address=08009_E_Asm: Ungltige effektive Adresse
+asmw_e_immediate_or_reference_expected=08010_E_Asm: Konstanter Ausdruck oder Referenz erwartet
+asmw_e_value_exceeds_bounds=08011_E_Asm: $1 Wert berschreitet Grenzen $2
+asmw_e_short_jmp_out_of_range=08012_E_Asm: "Short jump" ist ausserhalb des Bereichs $1
+asmw_e_undefined_label=08013_E_Asm: Undefiniertes Label: $1
+asmw_e_comp_not_supported=08014_E_Asm: Comp wird fr dieses Ziel nicht untersttzt
+asmw_e_extended_not_supported=08015_E_Asm: Extended Typ wird fr dieses Ziel nicht untersttzt
+asmw_e_duplicate_label=08016_E_Asm: Doppeltes Label $1
+asmw_e_redefined_label=08017_E_Asm: Neu definiertes Label $1
+asmw_e_first_defined_label=08018_E_Asm: First beginnt hier
+asmw_e_invalid_register=08019_E_Asm: Ungltiges Register $1
+asmw_e_16bit_32bit_not_supported=08020_E_Asm: 16 oder 32 Bit Referenzen werden nicht untersttzt
+asmw_e_64bit_not_supported=08021_E_Asm: 64 Bit Operanden werden nicht untersttzt
+asmw_e_bad_reg_with_rex=08022_E_Asm: AH,BH,CH oder DH k”nnen nicht in einer Instruktion verwendt werden, die den Prefix REX ben”tigt
+% x86_64 only: instruction encoding of this platform does not allow using
+% 8086 high byte registers (AH,BH,CH or DH) together with REX prefix in a single instruction.
+% The REX prefix is required whenever the instruction operand size is 64 bits, or
+% when it uses one of extended x86_64 registers (R8-R15 or XMM8-XMM15).
+
+#
+# Executing linker/assembler
+#
+# 09032 is the last used one
+#
+# BeginOfTeX
+%
+% \section{Errors of assembling/linking stage}
+% This section lists errors that occur when the compiler is processing the
+% command line or handling the configuration files.
+% \begin{description}
+exec_w_source_os_redefined=09000_W_Quellbetriebssystem wurde neu definiert
+% The source operating system is redefined.
+exec_i_assembling_pipe=09001_I_Assembliere (pipe) $1
+% Assembling using a pipe to an external assembler.
+exec_d_cant_create_asmfile=09002_E_Kann Assemblerdatei nicht erzeugen: $1
+% The mentioned file can't be created. Check if you have
+% access permissions to create this file.
+exec_e_cant_create_objectfile=09003_E_Kann Objektdatei nicht erzeugen: $1
+% The mentioned file can't be created. Check if you have
+% got access permissions to create this file.
+exec_e_cant_create_archivefile=09004_E_Kann Archivdatei nicht erzeugen: $1
+% The mentioned file can't be created. Check if you have
+% access permissions to create this file.
+exec_e_assembler_not_found=09005_E_Assembler $1 nicht gefunden, schalte um zu externem Assemblieren
+% The assembler program was not found. The compiler will produce a script that
+% can be used to assemble and link the program.
+exec_t_using_assembler=09006_T_Benutze Assembler: $1
+% An informational message saying which assembler is being used.
+exec_e_error_while_assembling=09007_E_Fehler beim Assemblieren des Exitcodes $1
+% There was an error while assembling the file using an external assembler.
+% Consult the documentation of the assembler tool to find out more information
+% on this error.
+exec_e_cant_call_assembler=09008_E_Assembler kann nicht aufgerufen werden, Fehler $1 schalte um zu externem Assemblieren
+% An error occurred when calling an external assembler. The compiler will produce a script that
+% can be used to assemble and link the program.
+exec_i_assembling=09009_I_Assembliere $1
+% An informational message stating which file is being assembled.
+exec_i_assembling_smart=09010_I_Assembliere mit Smartlinking $1
+% An informational message stating which file is being assembled using smartlinking.
+exec_w_objfile_not_found=09011_W_Objekt $1 nicht gefunden, Linken kann fehlschlagen!
+% One of the object files is missing, and linking will probably fail.
+% Check your paths.
+exec_w_libfile_not_found=09012_W_Bibliothek $1 nicht gefunden, Linken kann fehlschlagen!
+% One of the library file is missing, and linking will probably fail.
+% Check your paths.
+exec_e_error_while_linking=09013_E_Fehler beim Linken
+% Generic error while linking.
+exec_e_cant_call_linker=09014_E_Linker kann nicht aufgerufen werden, schalte um zu externem Linken
+% An error occurred when calling an external linker. The compiler will produce a script that
+% can be used to assemble and link the program.
+exec_i_linking=09015_I_Linke $1
+% An informational message, showing which program or library is being linked.
+exec_e_util_not_found=09016_E_Hilfsprogramm $1 nicht gefunden, schalte um zu externem Linken
+% An external tool was not found. The compiler will produce a script that
+% can be used to assemble and link or postprocess the program.
+exec_t_using_util=09017_T_Benutze Hilfsprogramm $1
+% An informational message, showing which external program (usually a postprocessor) is being used.
+exec_e_exe_not_supported=09018_E_Erzeugen von ausfhrbaren Dateien nicht untersttzt
+% Creating executable programs is not supported for this platform, because it was
+% not yet implemented in the compiler.
+exec_e_dll_not_supported=09019_E_Dynamische Bibliotheken nicht untersttzt
+% Creating dynamically loadable libraries is not supported for this platform, because it was
+% not yet implemented in the compiler.
+exec_i_closing_script=09020_I_Schliesse Skript $1
+% Informational message showing when writing of the external assembling and linking script is finished.
+exec_e_res_not_found=09021_E_Resource-Compiler "$1" nicht gefunden, schalte um auf externen Modus
+% An external resource compiler was not found. The compiler will produce a script that
+% can be used to assemble, compile resources and link or postprocess the program.
+exec_i_compilingresource=09022_I_šbersetze Resource $1
+% An informational message, showing which resource is being compiled.
+exec_t_unit_not_static_linkable_switch_to_smart=09023_T_Unit $1 kann nicht statisch gelinkt werden, schalte um zu smart Linken
+% Static linking was requested, but a unit which is not statically linkable was used.
+exec_t_unit_not_smart_linkable_switch_to_static=09024_T_Unit $1 kann nicht smart gelinkt werden, schalte um zu statischem Linken
+% Smart linking was requested, but a unit which is not smart-linkable was used.
+exec_t_unit_not_shared_linkable_switch_to_static=09025_T_Unit $1 kann nicht shared gelinkt werden, schalte um zu statischem Linken
+% Shared linking was requested, but a unit which is not shared-linkable was used.
+exec_e_unit_not_smart_or_static_linkable=09026_E_Unit $1 kann weder smart noch statisch gelinkt werden
+% Smart or static linking was requested, but a unit which cannot be used for either was used.
+exec_e_unit_not_shared_or_static_linkable=09027_E_Unit $1 kann weder shared noch statisch gelinkt werden
+% Shared or static linking was requested, but a unit which cannot be used for either was used.
+exec_d_resbin_params=09028_D_Resource Compiler "$1" wird mit "$2" als Kommandozeile aufgerufen
+% An informational message showing which command line is used for the resource compiler.
+exec_e_error_while_compiling_resources=09029_E_Fehler beim šbersetzen von Resourcen
+% The resource compiler or converter returned an error.
+exec_e_cant_call_resource_compiler=09030_E_Der Resource-Compiler "$1" kann nicht aufgerufen werden, schalte um auf externen Modus
+% An error occurred when calling a resource compiler. The compiler will produce
+% a script that can be used to assemble, compile resources and link or
+% postprocess the program.
+exec_e_cant_open_resource_file=09031_E_Kann die Resourcedatei "$1" nicht ”ffnen
+% An error occurred resource file cannot be opened.
+exec_e_cant_write_resource_file=09032_E_Kann die Resourcedatei "$1" nicht schreiben
+% An error occurred resource file cannot be written.
+%
+% \end{description}
+# EndOfTeX
+
+#
+# Executable information
+#
+# 09134 is the last used one
+#
+# BeginOfTeX
+% \section{Executable information messages.}
+% This section lists all messages that the compiler emits when an executable program is produced,
+% and only when the internal linker is used.
+% \begin{description}
+execinfo_f_cant_process_executable=09128_F_Kann ausfhrbare Datei nicht nachbearbeiten: $1
+% Fatal error when the compiler is unable to post-process an executable.
+execinfo_f_cant_open_executable=09129_F_Kann ausfhrbare Datei nicht ”ffnen: $1
+% Fatal error when the compiler cannot open the file for the executable.
+execinfo_x_codesize=09130_X_Gr”sse des Codes: $1 Bytes
+% Informational message showing the size of the produced code section.
+execinfo_x_initdatasize=09131_X_Gr”sse der initialisierten Daten: $1 Bytes
+% Informational message showing the size of the initialized data section.
+execinfo_x_uninitdatasize=09132_X_Gr”sse der nicht initialisierten Daten: $1 Bytes
+% Informational message showing the size of the uninitialized data section.
+execinfo_x_stackreserve=09133_X_Stack Bereich "reserved": $1 Bytes
+% Informational message showing the stack size that the compiler reserved for the executable.
+execinfo_x_stackcommit=09134_X_Stack Bereich "committed": $1 Bytes
+% Informational message showing the stack size that the compiler committed for the executable.
+%
+% \end{description}
+# EndOfTeX
+
+#
+# Internal linker messages
+#
+# 09201 is the last used one
+#
+# BeginOfTeX
+% \section{Linker messages}
+% This section lists messages produced by internal linker.
+% \begin{description}
+link_f_executable_too_big=09200_F_Das Programm - Image ist fr das Target $1 zu groá
+% Fatal error when resulting executable is too big.
+link_w_32bit_absolute_reloc=09201_W_Object Daei "$1" enth„lt eine 32-bit absolute Relocation auf Symbol "$2".
+% Warning when 64-bit object file contains 32-bit absolute relocations.
+% In such case an executable image can be loaded into lower 4Gb of
+% address space only.
+%
+% \end{description}
+# EndOfTeX
+
+#
+# Unit loading
+#
+# 10062 is the last used one
+#
+# BeginOfTeX
+% \section{Unit loading messages.}
+% This section lists all messages that can occur when the compiler is
+% loading a unit from disk into memory. Many of these mesages are
+% informational messages.
+% \begin{description}
+unit_t_unitsearch=10000_T_Suche Unit: $1
+% When you use the \var{-vt} option, the compiler tells you where it tries to find
+% unit files.
+unit_t_ppu_loading=10001_T_Lade PPU: $1
+% When the \var{-vt} switch is used, the compiler tells you
+% what units it loads.
+unit_u_ppu_name=10002_U_PPU-Name: $1
+% When you use the \var{-vu} flag, the unit name is shown.
+unit_u_ppu_flags=10003_U_PPU-Flags: $1
+% When you use the \var{-vu} flag, the unit flags are shown.
+unit_u_ppu_crc=10004_U_PPU-CRC: $1
+% When you use the \var{-vu} flag, the unit CRC check is shown.
+unit_u_ppu_time=10005_U_PPU-Zeit: $1
+% When you use the \var{-vu} flag, the unit time is shown.
+unit_u_ppu_file_too_short=10006_U_PPU-Datei zu kurz
+% When you use the \var{-vu} flag, the unit time is shown.
+unit_u_ppu_invalid_header=10007_U_PPU Ungltiger Header (kein PPU am Anfang)
+% A unit file contains as the first three bytes the ASCII codes of the characters \var{PPU}.
+unit_u_ppu_invalid_version=10008_U_PPU Ungltige Version $1
+% This unit file was compiled with a different version of the compiler, and
+% cannot be read.
+unit_u_ppu_invalid_processor=10009_U_PPU ist fr einen anderen Prozessor bersetzt
+% This unit file was compiled for a different processor type, and
+% cannot be read.
+unit_u_ppu_invalid_target=10010_U_PPU ist fr ein anderes Zielsystem bersetzt
+% This unit file was compiled for a different processor type, and
+% cannot be read.
+unit_u_ppu_source=10011_U_PPU Quelle: $1
+% When you use the \var{-vu} flag, the unit source file name is shown.
+unit_u_ppu_write=10012_U_Schreibe $1
+% When you specify the \var{-vu} switch, the compiler will tell you where it
+% writes the unit file.
+unit_f_ppu_cannot_write=10013_F_Kann PPU-Datei nicht schreiben
+% An error occurred when writing the unit file.
+unit_f_ppu_read_error=10014_F_Kann PPU-Datei nicht lesen
+% This means that the unit file was corrupted, and contains invalid
+% information. Recompilation will be necessary.
+unit_f_ppu_read_unexpected_end=10015_F_Unerwartetes Ende der PPU-Datei
+% Unexpected end of file. This may mean that the PPU file is
+% corrupted.
+unit_f_ppu_invalid_entry=10016_F_Ungltiger Eintrag in PPU-Datei: $1
+% The unit the compiler is trying to read is corrupted, or generated with a
+% newer version of the compiler.
+unit_f_ppu_dbx_count_problem=10017_F_PPU Dbx Z„hler-Problem
+% There is an inconsistency in the debugging information of the unit.
+unit_e_illegal_unit_name=10018_E_Ungltiger Unitname: $1
+% The name of the unit doesn't match the file name.
+unit_f_too_much_units=10019_F_Zu viele Units
+% \fpc has a limit of 1024 units in a program. You can change this behavior
+% by changing the \var{maxunits} constant in the \file{files.pas} file of the
+% compiler, and recompiling the compiler.
+unit_f_circular_unit_reference=10020_F_Gegenseitige Abh„ngigkeit von Units zwischen $1 und $2
+% Two units are using each other in the interface part. This is only allowed
+% in the \var{implementation} part. At least one unit must contain the other one
+% in the \var{implementation} section.
+unit_f_cant_compile_unit=10021_F_Kann Unit "$1" nicht bersetzen, keine Quellen vorhanden
+% A unit was found that needs to be recompiled, but no sources are
+% available.
+unit_f_cant_find_ppu=10022_F_Kann Unit "$1", die von "$2" benutzt wird, nicht finden
+% You tried to use a unit of which the PPU file isn't found by the
+% compiler. Check your configuration file for the unit paths.
+unit_w_unit_name_error=10023_W_Unit "$1" wurde nicht gefunden, aber "$2" existiert
+% This error message is no longer used.
+unit_f_unit_name_error=10024_F_Unit "$1" gesucht, aber "$2" gefunden
+% \dos truncation of 8 letters for unit PPU files
+% may lead to problems when unit name is longer than 8 letters.
+unit_w_switch_us_missed=10025_W_šbersetzen der Systemunit erfordert den Schalter -Us
+% When recompiling the system unit (it needs special treatment), the
+% \var{-Us} switch must be specified.
+unit_f_errors_in_unit=10026_F_Es traten $1 Fehler beim šbersetzen des Moduls auf, halte an
+% When the compiler encounters a fatal error or too many errors in a module
+% then it stops with this message.
+unit_u_load_unit=10027_U_Lade aus $1 ($2) die Unit $3
+% When you use the \var{-vu} flag, which unit is loaded from which unit is
+% shown.
+unit_u_recompile_crc_change=10028_U_šbersetze $1 erneut, Prfsumme fr $2 hat sich ge„ndert
+% The unit is recompiled because the checksum of a unit it depends on has
+% changed.
+unit_u_recompile_source_found_alone=10029_U_šbersetze "$1", nur Quellcode gefunden
+% When you use the \var{-vu} flag, these messages tell you why the current
+% unit is recompiled.
+unit_u_recompile_staticlib_is_older=10030_U_šbersetze Unit erneut, statische Bibliothek ist „lter als PPU-Datei
+% When you use the \var{-vu} flag, the compiler warns if the static library
+% of the unit is older than the unit file itself.
+unit_u_recompile_sharedlib_is_older=10031_U_šbersetze Unit erneut, gemeinsame Bibliothek ist „lter als PPU-Datei
+% When you use the \var{-vu} flag, the compiler warns if the shared library
+% of the unit is older than the unit file itself.
+unit_u_recompile_obj_and_asm_older=10032_U_šbersetze Unit erneut, obj und asm sind „lter als PPU-Datei
+% When you use the \var{-vu} flag, the compiler warns if the assembler of
+% object file of the unit is older than the unit file itself.
+unit_u_recompile_obj_older_than_asm=10033_U_šbersetze Unit erneut, obj ist „lter als asm
+% When you use the \var{-vu} flag, the compiler warns if the assembler
+% file of the unit is older than the object file of the unit.
+unit_u_parsing_interface=10034_U_Analysiere Interface von $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% parsing the interface part of the unit.
+unit_u_parsing_implementation=10035_U_Analysiere Implementation von $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% parsing the implementation part of the unit.
+unit_u_second_load_unit=10036_U_Zweites Laden fr Unit "$1"
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% recompiling a unit for the second time. This can happen with
+% interdependent units.
+unit_u_check_time=10037_U_PPU prfe Datei $1 Zeit $2
+% When you use the \var{-vu} flag, the compiler shows the filename and
+% date and time of the file on which a recompile depends.
+### The following two error msgs is currently disabled.
+#unit_h_cond_not_set_in_last_compile=10038_H_Conditional $1 wurde beim Start beim letzten šbersetzen von $2 nicht gesetzt
+#% when recompilation of an unit is required the compiler will check that
+#% the same conditionals are set for the recompiliation. The compiler has
+#% found a conditional that currently is defined, but was not used the last
+#% time the unit was compiled.
+#unit_h_cond_set_in_last_compile=10039_H_Conditional $1 wurde beim Start beim letzten šbersetzen von $2 gesetzt
+#% when recompilation of an unit is required the compiler will check that
+#% the same conditionals are set for the recompiliation. The compiler has
+#% found a conditional that was used the last time the unit was compiled, but
+#% the conditional is currently not defined.
+unit_w_cant_compile_unit_with_changed_incfile=10040_W_Kann Unit $1 nicht erneut bersetzen, aber ge„nderte Include-Datei gefunden
+% A unit was found to have modified include files, but
+% some source files were not found, so recompilation is impossible.
+unit_u_source_modified=10041_U_Datei $1 ist neuer als die, aus der die PPU Datei $2 erzeugt wird
+% A modified source file for a compiler unit was found.
+unit_u_ppu_invalid_fpumode=10042_U_Versuch eine Unit zu verwenden, die in einem anderen FPU Mode bersetzt wurde
+% Trying to compile code while using units which were not compiled with
+% the same floating point format mode. Either all code should be compiled
+% with FPU emulation on, or with FPU emulation off.
+unit_u_loading_interface_units=10043_U_Interface Units werden von $1 geladen
+% When you use the \var{-vu} flag, the compiler warns that it is starting
+% to load the units defined in the interface part of the unit.
+unit_u_loading_implementation_units=10044_U_Implementation Units werden von $1 geladen
+% When you use the \var{-vu} flag, the compiler warns that it is starting
+% to load the units defined in the implementation part of the unit.
+unit_u_interface_crc_changed=10045_U_Ge„nderte Interface CRC fr Unit $1
+% When you use the \var{-vu} flag, the compiler warns that the
+% CRC calculated for the interface has been changed after the implementation
+% has been parsed.
+unit_u_implementation_crc_changed=10046_U_Ge„nderte Implementation CRC fr Unit $1
+% When you use the \var{-vu} flag, the compiler warns that the
+% CRC calculated has been changed after the implementation
+% has been parsed.
+unit_u_finished_compiling=10047_U_šbersetzen der Unit $1 beendet
+% When you use the \var{-vu} flag, the compiler warns that it
+% has finished compiling the unit.
+unit_u_add_depend_to=10048_U_Abh„ngigkeit hinzufgen: $1 h„ngt von $2 ab
+% When you use the \var{-vu} flag, the compiler warns that it
+% has added a dependency between the two units.
+unit_u_no_reload_is_caller=10049_U_Kein erneutes Laden, Unit $1 ist die Aufrufende
+% When you use the \var{-vu} flag, the compiler warns that it
+% will not reload the unit because it is the unit that wants
+% to load this unit.
+unit_u_no_reload_in_second_compile=10050_U_Kein erneutes Laden der Unit, bereits beim zweiten šbersetzen: $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% will not reload the unit because it is already in a second recompile.
+unit_u_flag_for_reload=10051_U_Flag fr erneutes Laden: $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has to reload the unit.
+unit_u_forced_reload=10052_U_Erzwungenes erneutes Laden
+% When you use the \var{-vu} flag, the compiler warns that it
+% is reloading the unit because it was required.
+unit_u_previous_state=10053_U_Vorhergehender Status von $1: $2
+% When you use the \var{-vu} flag, the compiler shows the
+% previous state of the unit.
+unit_u_second_compile_unit=10054_U_$1 wird bereits bersetzt, zweites šbersetzen gesetzt
+% When you use the \var{-vu} flag, the compiler warns that it is starting
+% to recompile a unit for the second time. This can happen with interdependent
+% units.
+unit_u_loading_unit=10055_U_Unit $1 wird geladen
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% loading the unit.
+unit_u_finished_loading_unit=10056_U_Laden der Unit $1 beendet
+% When you use the \var{-vu} flag, the compiler warns that it finished
+% loading the unit.
+unit_u_registering_new_unit=10057_U_Registrierung der neuen Unit $1
+% When you use the \var{-vu} flag, the compiler warns that it has
+% found a new unit and is registering it in the internal lists.
+unit_u_reresolving_unit=10058_U_Erneutes resolving der Unit $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has to recalculate the internal data of the unit.
+unit_u_skipping_reresolving_unit=10059_U_Erneutes Resolving der Unit $1 wird bersprungen, benutzte Units werden noch geladen
+% When you use the \var{-vu} flag, the compiler warns that it is
+% skipping the recalculation of the internal data of the unit
+% because there is no data to recalculate.
+unit_u_unload_resunit=10060_U_Entlade die Resource-Unit $1 (wird nicht ben”tigt)
+% When you use the \var{-vu} flag, the compiler warns that it is unloading the
+% resource handling unit, since no resources are used.
+unit_e_different_wpo_file=10061_E_Unit $1 wurde mit einer anderen Feedback-Eingabe ($2, $3) fr die Gesamtprogramm-Optimierung (wpo) bersetzt. Bitte erneut ohne wpo oder mit der gleichen wpo-Feedback-Eingabe-Datei bersetzen
+% When a unit has been compiled using a particular whole program optimization (wpo) feedback file (\var{-FW<x>} \var{-OW<x>}),
+% this compiled version of the unit is specialised for that particular compilation scenario and cannot be used in
+% any other context. It has to be recompiled before you can use it in another program or with another wpo feedback input file.
+unit_u_indirect_crc_changed=10062_U_Die CRC des indirekten Interface (Objekte/Klassen) fr die unit $1 hat sich ge„ndert
+% When you use the \var{-vu} flag, the compiler warns that the
+% indirect CRC calculated for the unit (this is the CRC of all classes/objects/interfaces/$\ldots$
+% in the interfaces of units directly or indirectly used by this unit in the interface) has been changed after the
+% implementation has been parsed.
+%
+% \end{description}
+# EndOfTeX
+
+#
+# Options
+#
+# 11048 is the last used one
+#
+option_usage=11000_O_$1 [Optionen] <Eingabedatei> [Optionen]
+# BeginOfTeX
+%
+% \section{Command line handling errors}
+% This section lists errors that occur when the compiler is processing the
+% command line or handling the configuration files.
+% \begin{description}
+option_only_one_source_support=11001_W_Es wird nur eine Quelldatei untersttzt. Wechsel fr das Kompilieren von Quelldatei "$1" zu Quelldatei "$2"
+% You can specify only one source file on the command line. The last
+% one will be compiled, others will be ignored. This may indicate that
+% you forgot a \var{'-'} sign.
+option_def_only_for_os2=11002_W_DEF-Datei kann nur fr OS/2 erzeugt werden
+% This option can only be specified when you're compiling for OS/2.
+option_no_nested_response_file=11003_E_Verschachtelte Response-Dateien werden nicht untersttzt
+% You cannot nest response files with the \var{@file} command line option.
+option_no_source_found=11004_F_Kein Name fr Quelldatei auf der Kommandzeile
+% The compiler expects a source file name on the command line.
+option_no_option_found=11005_N_Keine Angaben in Konfigurationsdatei "$1" gefunden
+% The compiler didn't find any option in that config file.
+option_illegal_para=11006_E_Ungltiger Parameter: $1
+% You specified an unknown option.
+option_help_pages_para=11007_H_-? zeigt Hilfetext an
+% When an unknown option is given, this message is diplayed.
+option_too_many_cfg_files=11008_F_Zu viele verschachtelte Konfigurationsdateien
+% You can only nest up to 16 config files.
+option_unable_open_file=11009_F_Kann Datei nicht ”ffnen $1
+% The option file cannot be found.
+option_reading_further_from=11010_D_Lese weitere Optionen aus $1
+% Displayed when you have notes turned on, and the compiler switches
+% to another options file.
+option_target_is_already_set=11011_W_Zielsystem ist bereits gesetzt: $1
+% Displayed if more than one \var{-T} option is specified.
+option_no_shared_lib_under_dos=11012_W_Gemeinsame Bibliotheken sind auf der DOS Platform nicht verfgbar, verwende stattdessen statische Bibliotheken
+% If you specify \var{-CD} for the \dos platform, this message is displayed.
+% The compiler supports only static libraries under \dos.
+option_too_many_ifdef=11013_F_Zu viele \var{\#IF(N)DEFs} in Zeile $2 der Optionen-Datei $1
+% The \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_too_many_endif=11014_F_Unerwartetes \var{\#ENDIFs} in Zeile $2 der Optionen-Datei $1
+% The \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_too_less_endif=11015_F_Offene Bedingung am Ende der Optionen-Datei
+% The \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_no_debug_support=11016_W_Erzeugung von Debug-Informationen wird von dieser ausfhrbaren Datei nicht untersttzt
+% It is possible to have a compiler executable that doesn't support
+% the generation of debugging info. If you use such an executable with the
+% \var{-g} switch, this warning will be displayed.
+option_no_debug_support_recompile_fpc=11017_H_Versuchen Sie mit -dGDB erneut zu bersetzen
+% It is possible to have a compiler executable that doesn't support
+% the generation of debugging info. If you use such an executable with the
+% \var{-g} switch, this warning will be displayed.
+option_obsolete_switch=11018_W_Sie verwenden den nun berholten Schalter $1
+% This warns you when you use a switch that is not needed/supported anymore.
+% It is recommended that you remove the switch to overcome problems in the
+% future, when the meaning of the switch may change.
+option_obsolete_switch_use_new=11019_W_Sie benutzen den nun berholten Schalter $1, bitte benutzen Sie $2
+% This warns you when you use a switch that is not supported anymore. You
+% must now use the second switch instead.
+% It is recommended that you change the switch to overcome problems in the
+% future, when the meaning of the switch may change.
+option_switch_bin_to_src_assembler=11020_N_Schalte Assembler auf den Standard-Assembler-Quellcodeschreiber
+% This notifies you that the assembler has been changed because you used the
+% -a switch, which can't be used with a binary assembler writer.
+option_incompatible_asm=11021_W_Das gew„hlte Assembler-Ausgabeformat "$1" ist nicht mit "$2" kompatibel
+option_asm_forced=11022_W_Verwendung des Assemblers "$1" erzwungen
+% The assembler output selected cannot generate
+% object files with the correct format. Therefore, the
+% default assembler for this target is used instead.
+option_using_file=11026_T_Optionen werden aus der Datei $1 gelesen
+% Options are also read from this file.
+option_using_env=11027_T_Optionen werden aus dem environment $1 gelesen
+% Options are also read from this environment string.
+option_handling_option=11028_D_Handling der Option "$1"
+% Debug info that an option is found and will be handled.
+option_help_press_enter=11029_O_*** Drcken Sie die ENTER-Taste ***
+% Message shown when help is shown page per page. When pressing the ENTER
+% Key, the next page of help is shown. If you press q and then ENTER, the
+% compiler exits.
+option_start_reading_configfile=11030_H_Beginn des Lesens der Konfigurationsdatei $1
+% Start of configuration file parsing.
+option_end_reading_configfile=11031_H_Ende des Lesens der Konfigurationsdatei $1
+% End of configuration file parsing.
+option_interpreting_option=11032_D_Option "$1" interpretieren
+% The compiler is interpreting an option
+option_interpreting_firstpass_option=11036_D_firstpass Option "$1" interpretieren
+% The compiler is interpreting an option for the first time.
+option_interpreting_file_option=11033_D_Datei Option "$1" interpretieren
+% The compiler is interpreting an option which it read from the configuration file.
+option_read_config_file=11034_D_Konfigurationsdatei "$1" lesen
+% The compiler is starting to read the configuration file.
+option_found_file=11035_D_Name der Quelldatei "$1" gefunden
+% Additional information about options.
+% Displayed when you have the debug option turned on.
+option_code_page_not_available=11039_E_Unbekannte code page
+% An unknown code page for the source files was requested.
+% The compiler is compiled with support for several code pages built-in.
+% The requested code page is not in that list. You will need to recompile
+% the compiler with support for the codepage you need.
+option_config_is_dir=11040_F_Konfigurationsdatei $1 ist ein Verzeichnis
+% Directories cannot be used as configuration files.
+option_confict_asm_debug=11041_W_Die gew„hlte Assembler-Ausgabe "$1" kann kein Debug-Info erzeugen, Debugging ist ausgeschaltet
+% The selected assembler output cannot generate
+% debugging information, debugging option is therefore disabled.
+option_ppc386_deprecated=11042_W_Die Verwendung von ppc386.cfg wird beendet. Bitte statt dessen fpc.cfg benutzen
+% Using ppc386.cfg is still supported for historical reasons, however, for a multiplatform
+% system the naming makes no sense anymore. Please continue to use fpc.cfg instead.
+option_else_without_if=11043_F_Zur \var{\#ELSE} Direktive in Zeile $2 der Optionen-Datei $1 gibt es kein entsprechendes \var{\#IF(N)DEF}
+% An \var{\#ELSE} statement was found in the options file without a matching \var{\#IF(N)DEF} statement.
+option_unsupported_target=11044_F_Die Option "$1" wird auf der Zielplattform nicht oder noch nicht untersttzt
+% Not all options are supported or implemented for all target platforms. This message informs you that a chosen
+% option is incompatible with the currently selected target platform.
+option_unsupported_target_for_feature=11045_F_Das Feature "$1" wird fr die ausgew„hlte Zielplattform nicht oder noch nicht untersttzt
+% Not all features are supported or implemented for all target platforms. This message informs you that a chosen
+% feature is incompatible with the currently selected target platform.
+option_dwarf_smart_linking=11046_N_DWARF Debug-Information kann auf dieser Zielplattform nicht zusammen mit Smartlinking benutzt werden, es wird auf statisches Linken umgeschaltet
+% Smart linking is currently incompatble with DWARF debug information on most
+% platforms, so smart linking is disabled in such cases.
+option_ignored_target=11047_W_Option "$1" wird fr die ausgew„hlte Zielplattform ignoriert
+% Not all options are supported or implemented for all target platforms. This message informs you that a chosen
+% option is ignored for the currently selected target platform.
+option_debug_external_unsupported=11048_W_Schalte externe Debuginformation aus, weil es fr die gew„hlte Kombination Ziel/Debugformat nicht untersttzt wird
+% Not all debug formats can be stored in an external file on all platforms. In particular, on
+% Mac OS X only DWARF debug information can be stored externally.
+%
+% \end{description}
+# EndOfTeX
+
+#
+# Whole program optimization
+#
+# 12019 is the last used one
+#
+# BeginOfTeX
+%
+% \section{Whole program optimization messages}
+% This section lists errors that occur when the compiler is performing
+% whole program optimization.
+% \begin{description}
+wpo_cant_find_file=12000_F_Feedback-Datei "$1" fr die Gesamtprogramm-Optimierung kann nicht ge”ffnet werden
+% The compiler cannot open the specified feedback file with whole program optimization information.
+wpo_begin_processing=12001_D_Bearbeite die Informationen zur Gesamtprogramm-Optimierung aus der wpo-Feedback-Datei "$1"
+% The compiler starts processing whole program optimization information found in the named file.
+wpo_end_processing=12002_D_Bearbeitung der Informationen zur Gesamtprogramm-Optimierung aus der wpo-Feedback-Datei "$1" beendet
+% The compiler has finished processing the whole program optimization information found in the named file.
+wpo_expected_section=12003_E_Erwarte einen Sektions-Header, statt dessen "$2" in Zeile $1 der wpo-Feedback-Datei erhalten
+% The compiler expected a section header in the whole program optimization file (starting with \%),
+% but did not find it.
+wpo_no_section_handler=12004_W_Kein Handler fr die Sektion "$2" der Gesamtprogramm-Optimierung registriert (Zeile $1 der wpo-Feedback-Datei). Wird ignoriert
+% The compiler has no handler to deal with the mentioned whole program optimization information
+% section, and will therefore ignore it and skip to the next section.
+wpo_found_section=12005_D_Sektion "$1" der Gesamtprogramm-Optimierung mit Informationen ber "$2" gefunden
+% The compiler encountered a section with whole program optimization information, and according
+% to its handler this section contains information usable for the mentioned purpose.
+wpo_no_input_specified=12006_F_Die ausgew„hlte Gesamtprogramm-Optimierung erfordert eine bereits erzeugte Feedback-Datei (bitte mit -Fw angeben)
+% The compiler needs information gathered during a previous compilation run to perform the selected
+% whole program optimizations. You can specify the location of the feedback file containing this
+% information using the -Fw switch.
+wpo_not_enough_info=12007_E_Keine Informationen fr "$1" Gesamtprogramm-Optimierung gefunden
+% While you pointed the compiler to a file containing whole program optimization feedback, it
+% did not contain the information necessary to perform the selected optimizations. You most likely
+% have to recompile the program using the appropate -OWxxx switch.
+wpo_no_output_specified=12008_F_Gebe eine Feedback-Datei an, um die erzeugte Information fr die Gesamtprogramm-Optimierung zu speichern (mit der Option -FW)
+% You have to specify the feedback file in which the compiler has to store the whole program optimization
+% feedback that is generated during the compilation run. This can be done using the -FW switch.
+wpo_output_without_info_gen=12009_E_Erzeuge keine Information fr die Gesamtprogramm-Optimierung, obwohl eine Feedback-Datei dafr angegeben wurde (mit der Option -FW)
+% The compiler was instructed to store whole program optimization feedback into a file specified using -FW,
+% but not to actually generated any whole program optimization feedback. The classes of to be
+% generated information can be speciied using -OWxxx.
+wpo_input_without_info_use=12010_E_Gesamtprogramm-Optimierung wird nicht durchgefhrt, obwohl eine Feedback-Datei angegeben wurde (mit der Option -FW)
+% The compiler was not instructed to perform any whole program optimizations (no -Owxxx parameters),
+% but nevertheless an input file with such feedback was specified (using -Fwyyy). Since this can
+% indicate that you forgot to specify an -Owxxx parameter, the compiler generates an error in this case.
+wpo_skipping_unnecessary_section=12011_D_šberspringe die Sektion "$1" der Gesamtprogramm-Optimierung, weil sie nicht ben”tigt wird
+% The whole program optimization feedback file contains a section with information that is not
+% required by the selected whole program optimizations.
+wpo_duplicate_wpotype=12012_W_šberschreibe bereits gelesene Information "$1" aus der Feedback-Eingabe-Datei mit der Information in Sektion "$2"
+% The feedback file contains multiple sections that provide the same class of information (e.g.,
+% information about which virtual methods can be devirtualized). In this case, the information in last encountered
+% section is used. Turn on debugging output (-vd) to see which class of information is provided by each section.
+wpo_cannot_extract_live_symbol_info_strip=12013_E_Symbol "liveness" Information kann nicht aus dem Programm erhalten werden, wenn Symbole mit "strip" entfernt wurden. Benutze -Xs-
+% Certain symbol liveness collectors extract the symbol information from the linked program. If the symbol information
+% is stripped (option -Xs), this is not possible.
+wpo_cannot_extract_live_symbol_info_no_link=12014_E_Symbol "liveness" Information kann nicht aus dem Programm erhalten werden, wenn es nicht "linked" wird
+% Certain symbol liveness collectors extract the symbol information from the linked program. If the program is not
+% linked by the compiler, this is not possible.
+wpo_cannot_find_symbol_progs=12015_F_"$1" oder "$2" wurden nicht gefunden, um die Symbol "liveness" Information aus dem Programm zu erhalten
+% Certain symbol liveness collectors need a helper program to extract the symbol information from the linked program.
+% This helper program is normally 'nm', which is part of the GNU binutils.
+wpo_error_reading_symbol_file=12016_E_Fehler beim Lesen der "symbol liveness" Information durch "$1" erzeugt
+% An error occurred during the reading of the symbol liveness file that was generated using the 'nm' or 'objdump' program. The reason
+% can be that it was shorter than expected, or that its format was not understood.
+wpo_error_executing_symbol_prog=12017_F_Fehler bei der Ausfhrung von "$1" (exitcode: $2) um Symbolinformationen aus dem "gelinkten" Programm zu erhalten
+% Certain symbol liveness collectors need a helper program to extract the symbol information from the linked program.
+% The helper program produced the reported error code when it was run on the linked program.
+wpo_symbol_live_info_needs_smart_linking=12018_E_Die Sammlung der "symbol liveness" Information hilft nur bei smart linking, benutze -CX -XX
+% Whether or not a symbol is live is determined by looking whether it exists in the final linked program.
+% Without smart linking/dead code stripping, all symbols are always included, regardless of whether they are
+% actually used or not. So in that case all symbols will be seen as live, which makes this optimization ineffective.
+wpo_cant_create_feedback_file=12019_E_Die angegebene Feedback-Eingabe-Datei "$1" fr die Gesamtprogramm-Optimierung kann nicht erzeugt werden
+% The compiler is unable to create the file specified using the -FW parameter to store the whole program optimisation information.
+%
+% \end{description}
+# EndOfTeX
+
+#
+# Logo (option -l)
+#
+option_logo=11023_[
+Free Pascal Compiler Version $FPCFULLVERSION [$FPCDATE] fr $FPCTARGET
+Copyright (c) 1993-2011 Florian Kl„mpfl und andere
+]
+
+#
+# Info (option -i)
+#
+option_info=11024_[
+Free Pascal Compiler Version $FPCVERSION
+
+Compiler Datum: $FPCDATE
+Compiler Zielsystem: $FPCCPU
+
+Untersttzte Zielbetriebssysteme:
+ $OSTARGETS
+
+Untersttzte CPU Instruktionen:
+ $INSTRUCTIONSETS
+
+Untersttzte FPU Instruktionen:
+ $FPUINSTRUCTIONSETS
+
+Untersttzte ABI Ziele:
+ $ABITARGETS
+
+Untersttzte Optimierungen:
+ $OPTIMIZATIONS
+
+Untersttzte Gesamtprogramm-Optimierungen:
+ All
+ $WPOPTIMIZATIONS
+
+Untersttzte Microcontroller:
+ $CONTROLLERTYPES
+
+Dieses Programm unterliegt der GNU General Public Licence
+Weitere Informationen sind in COPYING.FPC zu finden
+
+Fehlerberichte, Vorschl„ge usw. bitte senden an:
+ http://bugs.freepascal.org
+oder
+ bugs@freepascal.org
+]
+
+#
+# Help pages (option -? and -h)
+#
+# The first character on the line indicates who will display this
+# line, the current possibilities are :
+# * = every target
+# 3 = 80x86 targets
+# 4 = x86_64
+# 6 = 680x0 targets
+# A = ARM
+# e = in extended debug mode only
+# P = PowerPC targets
+# S = Sparc targets
+# V = Virtual machine targets
+# The second character also indicates who will display this line,
+# (if the above character was TRUE) the current possibilities are :
+# * = everyone
+# g = with GDB info supported by the compiler
+# O = OS/2
+# L = UNIX systems
+# The third character represents the indentation level.
+#
+option_help_pages=11025_[
+**0*_Nach booleschen Optionen geben Sie + zum Ein- bzw. - zum Ausschalten an
+**1a_L”sche die erzeugte Assembler-Datei nicht
+**2al_Liste Quellcode-Zeilen in der Assembler-Datei
+**2an_Liste "node info" in der Assembler-Datei
+*L2ap_Benutze Pipes anstelle tempor„rer Assembler-Dateien
+**2ar_Liste Registerbelegungsinformation in Assembler-Datei
+**2at_Liste Temp. Variablenbelegungsinfo in Assembler-Datei
+**1A<x>_Ausgabe Format:
+**2Adefault_Benutze den "default" Assembler
+3*2Aas_Assembliere mit Hilfe von GNU AS
+3*2Amacho_Mach-O (Darwin, Intel 32 bit) mit Hilfe des internen Schreibers
+3*2Anasmcoff_COFF (Go32v2) Datei mit Hilfe von Nasm
+3*2Anasmelf_ELF32 (Linux) Datei mit Hilfe von Nasm
+3*2Anasmwin32_Win32 Object Datei mit Hilfe von Nasm
+3*2Anasmwdosx_Win32/WDOSX Object Datei mit Hilfe von Nasm
+3*2Awasm_obj Datei mit Hilfe von Wasm (Watcom)
+3*2Anasmobj_Obj Datei mit Hilfe von Nasm
+3*2Amasm_Obj Datei mit Hilfe von Masm (Microsoft)
+3*2Atasm_Obj Datei mit Hilfe von Tasm (Borland)
+3*2Aelf_ELF32 (Linux) mit Hilfe des internen Schreibers
+3*2Acoff_COFF (Go32v2) mit Hilfe des internen Schreibers
+3*2Apecoff_PE_COFF (Win32) mit Hilfe des internen Schreibers
+4*2Aas_Assembliere mit Hilfe von GNU AS
+4*2Agas_Assembliere mit Hilfe von GNU GAS
+4*2Agas-darwin_Assembliere darwin Mach-O64 mit Hilfe von GNU GAS
+4*2Amasm_Win64 Object Datei mit Hilfe von ml64 (Microsoft)
+4*2Apecoff_PE-COFF (Win64) mit Hilfe des internen Writer
+4*2Aelf_ELF (Linux-64bit) mit Hilfe des internen Writer
+6*2Aas_Unix o-Datei mit Hilfe von GNU AS
+6*2Agas_GNU Motorola Assembler
+6*2Amit_MIT Syntax (old GAS)
+6*2Amot_Standard Motorola Assembler
+A*2Aas_Assembliere mit Hilfe von GNU AS
+P*2Aas_Assembliere mit Hilfe von GNU AS
+S*2Aas_Assembliere mit Hilfe von GNU AS
+**1b_Erzeuge Browser-Info
+**2bl_Erzeuge Info zu lokalen Symbolen
+**1B_Erzeuge alle Module (Build)
+**1C<x>_Optionen fr Code-Erzeugung:
+**2C3<x>_Schalte ieee-Prfung von Konstanten ein
+**2Ca<x>_W„hle ABI aus; fpc -i gibt die m”glichen Werte aus
+**2Cb_Erzeuge "big-endian" Code
+**2Cc<x>_Setze "default calling convention" zu <x>
+**2CD_Erzeuge auch eine dynamische Bibliothek (nicht untersttzt)
+**2Ce_šbersetze mit emulierten Fliesskomma opcodes
+**2Cf<x>_W„hle den Fliesskomma instruction set aus; fpc -i gibt die m”glichen Werte aus
+**2CF<x>_Minimale Pr„zission von Fliesskommakonstanten (default, 32, 64)
+**2Cg_Erzeuge PIC code
+**2Ch<n>_<n> Bytes Heap (zwischen 1023 und 67107840)
+**2Ci_I/O-Prfung
+**2Cn_Lasse die Linkstufe aus
+**2Co_Prfe auf šberlauf von Integer-Operationen
+**2CO_Prfe auf m”glichen šberlauf von Integer-Operationen
+**2Cp<x>_W„hle instruction set aus; fpc -i gibt die m”glichen Werte aus
+**2CP<x>=<y>_ Einstellungen fr packing
+**3CPPACKSET=<y>_ <y> Belegung von Sets: 0, 1 oder DEFAULT oder NORMAL, 2, 4 und 8
+**2Cr_Fhre Bereichsprfung durch
+**2CR_Verifiziere die Gltigkiet des Aufrufs der Objektmethoden
+**2Cs<n>_Setze die Prfgr”sse des Stacks auf <n>
+**2Ct_Fhre Stackprfung durch (nur zum Testen, siehe Handbuch)
+**2Cx_Benutze Smartlinking
+**1d<x>_Definiere das Symbol <x>
+**1D_Erzeuge eine DEF-Datei
+**2Dd<x>_Setze Beschreibung zu <x>
+**2Dv<x>_Setze DLL Version zu <x>
+*O2Dw_Erzeuge PM-Anwendung
+**1e<x>_Setze Pfad zur ausfhrbaren Datei
+**1E_Genau wie -Cn
+**1fPIC_Genau wie -Cg
+**1F<x>_Dateinamen und Pfade:
+**2Fa<x>[,y]_Ein Program soll die Units <x> und [y] laden, bevor uses analysiert wird
+**2Fc<x>_Setze die Eingabe-Codepage zu <x>
+**2Fd_Schalte den internen Verzeichnis-Cache des Compilers aus
+**2FC<x>_Setze den Namen des RC Compiler-Bin„rprograms auf <x>
+**2FD<x>_Setze das Verzeichnis fr die Compiler-Hilfsprogramme
+**2Fe<x>_Leite die Fehlerausgabe um nach <x>
+**2Ff<x>_Erg„nze <x> zum Framework-Pfad (nur Darwin)
+**2FE<x>_Setze den Pfad fr Exe/Unit-Dateien auf <x>
+**2Fi<x>_Erg„nze <x> zum Include-Pfad
+**2Fl<x>_Erg„nze <x> zum Bibliotheks-Pfad
+**2FL<x>_Benutze <x> als dynamischen Linker
+**2Fm<x>_Lade die Unicode-Konversionstabelle aus <x>.txt im Compiler-Verzeichnis
+**2Fo<x>_Erg„nze <x> zum Objektdatei-Pfad
+**2Fr<x>_Lade die Fehler-Meldungs Datei <x>
+**2FR<x>_Setze den Resource (.res) Linker auf <x>
+**2Fu<x>_Erg„nze <x> zum Unit-Pfad
+**2FU<x>_Units werden nach <x> ausgegeben, hat Vorrang vor -FE
+**2FW<x>_Speichere das erzeugte Feedback fr die Gesamtprogramm-Optimierung in <x>
+**2Fw<x>_Lade das bereits gespeicherte Feedback fr die Gesamtprogramm-Optimierung aus <x>
+*g1g<x>_Erzeuge Informationen zur Fehlersuche:
+*g2gc_Zeigerberprfung
+*g2gh_Heaptrace-Unit einbinden
+*g2gl_Line info Unit einbinden, um mehr backtrace Informationen anzuzeigen
+*g2go<x>_Setze Optionen fr die Debug Informationen
+*g3godwarfsets_Schalte DWARF Debug Informationen fr Mengen (sets) ein (verhindert debugging mit gdb < 6.5)
+*g3gostabsabsincludes_ Absolute/volle Include-Datei-Pfade in Stabs speichern
+*g3godwarfmethodclassprefix_ Stelle Methodennamen in DWARF den Namen der Klasse voran
+*g2gp_Erhalte Gross/Kleinschreibung in Stabs-Symbolnamen
+*g2gs_Erzeuge Stabs-Debug-Informationen
+*g2gt_L”sche lokale Variablen (um eine Verwendung ohne Initialisierung zu finden)
+*g2gv_Erzeuge ein mit Valgrind verfolgbares (traceable) Programm
+*g2gw_Erzeuge DWARFv2-Debug-Informationen (wie -gw2)
+*g2gw2_Erzeuge DWARFv2-Debug-Informationen
+*g2gw3_Erzeuge DWARFv3-Debug-Informationen
+*g2gw4_Generate DWARFv4-Debug-Informationen (experimentell)
+**1i_Zeige alle Informationen ber den Compiler
+**2iD_Zeige Compilerdatum
+**2iV_Zeige Compilerversion
+**2iW_Zeige vollst„ndige Compilerversion
+**2iSO_Zeige Compilerbetriebssystem
+**2iSP_Zeige Compilerprozessor
+**2iTO_Zeige Zielbetriebssystem
+**2iTP_Zeige Zielprozessor
+**1I<x>_Erg„nze <x> zum Include-Pfad
+**1k<x>_šbergebe <x> an den Linker
+**1l_Zeige Logo
+**1M<x>_Setze Sprachmodus zu <x>
+**2Mfpc_Free Pascal Dialekt (Voreinstellung)
+**2Mobjfpc_Schalte einige Delphi 2 Erweiterungen ein
+**2Mdelphi_Versuche zu Delphi kompatibel zu sein
+**2Mtp_Versuche zu TP/BP 7.0 kompatibel zu sein
+**2Mmacpas_Versuche zu den MacIntosh Pascal-Dialekten kompatibel zu sein
+**1n_Standard-Konfigurationsdatei ignorieren
+**1N<x>_Node tree Optimierung
+**2Nu_Unroll loops
+**1o<x>_Die erzeugte, ausfhrbare Datei bekommt den Namen <x>
+**1O<x>_Optimierungen:
+**2O-_Optimierungen ausschalten
+**2O1_Level 1 Optimierung (schnell und Debugger freundlich)
+**2O2_Level 2 Optimierung (-O1 + schnelle Optimierungen)
+**2O3_Level 3 Optimierung (-O2 + langsame Optimierungen)
+**2Oa<x>=<y>_Ausrichtung (alignment) von Mengen
+**2Oo[NO]<x>_Optimierungen ein- oder ausschalten; fpc -i gibt die m”glichen Werte aus
+**2Op<x>_Setze Zielprozessor fr die Optimierung; fpc -i gibt die m”glichen Werte aus
+**2OW<x>_Erzeuge Feedback fr die Gesamtprogramm-Optimierung fr Optimierung <x>, siehe fpc -i fr m”gliche Werte
+**2Ow<x>_Fhre die Gesamtprogramm-Optimierung durch <x>, siehe fpc -i fr m”gliche Werte
+**2Os_Erzeuge krzeren Code
+**1pg_Erzeuge Profiler-Code fr gprof
+**1R<x>_Assembler Code Format:
+**2Rdefault_Benutze den default Assembler
+3*2Ratt_Lese Assembler Code im AT&T Format
+3*2Rintel_Lese Assembler im Intel Format
+6*2RMOT_Lese Assembler im Motorola Format
+**1S<x>_Syntax-Optionen:
+**2S2_Schalte einige der Delphi 2 Erweiterungen ein (wie -Mobjfpc)
+**2Sc_Untersttze spezielle C Operatoren (*=,+=,/= and -=)
+**2Sa_Erlaube assertion code.
+**2Sd_Sei Delphi-kompatibel (wie -Mdelphi)
+**2Se<x>_Fehler Optionen. <x> ist eine der folgenden Kombinationen:
+**3*_<n> : Compiler h„lt nach <n> Fehlern (Voreinstellung ist 1)
+**3*_w : Compiler h„lt auch nach Warnungen
+**3*_n : Compiler h„lt auch nach Anmerkungen
+**3*_h : Compiler h„lt auch nach Hinweisen
+**2Sg_Erlaube LABEL und GOTO
+**2Sh_Benutze ANSI-Strings
+**2Si_Benutze C++ artige INLINE
+**2Sk_Lade fpcylix Unit
+**2SI<x>_Setze den Stil des Interface zu <x>
+**3SIcom_COM kompatibles Interface (Voreinstellung)
+**3SIcorba_CORBA kompatibles Interface
+**2Sm_Untersttze Makros wie in C (global)
+**2So_Sei TP/BP 7.0 kompatibel (wie -Mtp)
+**2Ss_Konstruktor- und Destruktorname mssen "Init" und "Done" sein
+**2Sx_Exception Schlsselw”rter einschalten (Voreinstellung in Delphi/ObjFPC Moden)
+**2Sy_@<pointer> gibt einen typisierten Pointer zurck, genau wie $T+
+**1s_Rufe weder Assembler noch Linker auf (nur mit -a)
+**2sh_Erzeuge Script um auf dem Host zu linken
+**2st_Erzeuge Script um auf dem Zielsystem zu linken
+**2sr_šberspringe die Phase der "register allocation" (mit -alr benutzen)
+**1T<x>_Zielbetriebssystem::
+3*2Tdarwin_Darwin/Mac OS X
+3*2Temx_OS/2 via EMX (einschliesslich EMX/RSX extender)
+3*2Tfreebsd_FreeBSD
+3*2Tgo32v2_Version 2 des DJ Delorie DOS extender
+3*2Tlinux_Linux
+3*2Tnetbsd_NetBSD
+3*2Tnetware_Novell Netware Module (clib)
+3*2Tnetwlibc_Novell Netware Module (libc)
+3*2Topenbsd_OpenBSD
+3*2Tos2_OS/2 / eComStation
+3*2Tsunos_SunOS/Solaris
+3*2Tsymbian_Symbian OS
+3*2Tsolaris_Solaris
+3*2Twatcom_Watcom compatible DOS extender
+3*2Twdosx_WDOSX DOS extender
+3*2Twin32_Windows 32 Bit
+3*2Twince_Windows CE
+4*2Tdarwin_Darwin/Mac OS X
+4*2Twin64_Win64 (64 bit Windows systems)
+4*2Tlinux_Linux
+6*2Tamiga_Commodore Amiga
+6*2Tatari_Atari ST/STe/TT
+6*2Tlinux_Linux
+6*2Tpalmos_PalmOS
+A*2Tdarwin_Darwin/iPhoneOS/iOS
+A*2Tlinux_Linux
+A*2Twince_Windows CE
+P*2Tamiga_AmigaOS
+P*2Tdarwin_Darwin und Mac OS X
+P*2Tlinux_Linux
+P*2Tmacos_Mac OS (classic)
+P*2Tmorphos_MorphOS
+S*2Tsolaris_Solaris
+S*2Tlinux_Linux
+**1u<x>_Entferne die Definition fr das Symbol <x>
+**1U<x>_Unit-Optionen:
+**2Un_Prfe den Unitnamen nicht
+**2Ur_Erzeuge "release unit"-Dateien
+**2Us_Erzeuge eine Systemunit
+**1v<x>_Meldungen, <x> ist eine Kombination der folgenden Zeichen:
+**2*_e : Fehler (Standard) 0 : Nichts (ausser Fehlern)
+**2*_w : Warnungen u : Unit Informationen
+**2*_n : Anmerkungen t : Angesprochene/benutzte Dateien
+**2*_h : Hinweise c : Preprozessordirektiven
+**2*_i : Allgemeine Informationen d : Debug Informationen
+**2*_l : Zeilennummern r : Rhide/GCC kompatibler Modus
+**2*_s : Zeitstempel q : Nummer der Meldung
+**2*_a : Alles x : Exe-Datei Informationen (nur Win32)
+**2*_b : Schreibe bei Meldungen mit p : Schreibe tree.log mit Analysenbaum (parse tree)
+**2*_ Dateinamen den vollst„ndigen v : Schreibe fpcdebug.txt mit
+**2*_ Pfad ganz viel Information
+**2*_m<x>,<y> : Zeige die Meldungen mit den Nummern <x> und <y> nicht
+**1W<x>_Spezifiziere ein natives Programm (Windows)
+3*2WA_Spezifiziere ein natives Programm (Windows)
+4*2WA_Spezifiziere ein natives Programm (Windows)
+A*2WA_Spezifiziere ein natives Programm (Windows)
+3*2Wb_Erzeuge statt einer Bibliothek ein Bundle (Darwin)
+P*2Wb_Erzeuge statt einer Bibliothek ein Bundle (Darwin)
+p*2Wb_Erzeuge statt einer Bibliothek ein Bundle (Darwin)
+A*2Wb_Erzeuge statt einer Bibliothek ein Bundle (Darwin)
+4*2Wb_Erzeuge statt einer Bibliothek ein Bundle (Darwin)
+3*2WB_Erzeuge ein relozierbares Image (Windows, Symbian)
+3*2WBxxxx_Setze die Imagebasis auf xxxx (Windows, Symbian)
+4*2WB_Erzeuge ein relozierbares Image (Windows)
+4*2WBxxxx_Setze die Imagebasis auf xxxx (Windows, Symbian)
+A*2WB_Erzeuge ein relozierbares Image (Windows, Symbian)
+A*2WBxxxx_Setze die Imagebasis auf xxxx (Windows)
+3*2WC_Spezifiziere "console type application" (EMX, OS/2, Windows)
+4*2WC_Spezifiziere "console type application" (EMX, OS/2, Windows)
+A*2WC_Spezifiziere "console type application" (Windows)
+P*2WC_Spezifiziere "console type application" (Classic Mac OS)
+3*2WD_Benutze DEFFILE um Funktionen der DLL oder EXE zu exportieren (Windows)
+4*2WD_Benutze DEFFILE um Funktionen der DLL oder EXE zu exportieren (Windows)
+A*2WD_Benutze DEFFILE um Funktionen der DLL oder EXE zu exportieren (Windows)
+3*2We_Benutze externe Resourcen (Darwin)
+4*2We_Benutze externe Resourcen (Darwin)
+A*2We_Benutze externe Resourcen (Darwin)
+P*2We_Benutze externe Resourcen (Darwin)
+p*2We_Benutze externe Resourcen (Darwin)
+3*2WF_Spezifiziere "full-screen type application" (EMX, OS/2)
+3*2WG_Spezifiziere "graphic type application" (EMX, OS/2, Windows)
+4*2WG_Spezifiziere "graphic type application" (EMX, OS/2, Windows)
+A*2WG_Spezifiziere "graphic type application" (Windows)
+P*2WG_Spezifiziere "graphic type application" (Classic Mac OS)
+3*2Wi_Benutze interne Resourcen (Darwin)
+4*2Wi_Benutze interne Resourcen (Darwin)
+A*2Wi_Benutze interne Resourcen (Darwin)
+P*2Wi_Benutze interne Resourcen (Darwin)
+p*2Wi_Benutze interne Resourcen (Darwin)
+3*2WI_Die Verwendung der "import"-Abschnitte ein/ausschalten (Windows)
+4*2WI_Die Verwendung der "import"-Abschnitte ein/ausschalten (Windows)
+A*2WI_Die Verwendung der "import"-Abschnitte ein/ausschalten (Windows)
+3*2WN_Erzeuge keinen "relocation code" (notwendig fr debugging) (Windows)
+4*2WN_Erzeuge keinen "relocation code" (notwendig fr debugging) (Windows)
+A*2WN_Erzeuge keinen "relocation code" (notwendig fr debugging) (Windows)
+A*2Wpxxxx_Spezifiziere den Kontrollertyp, m”gliche Werte liefert fpc -i
+V*2Wpxxxx_Spezifiziere den Kontrollertyp, m”gliche Werte liefert fpc -i
+3*2WR_Erzeuge "relocation code" (Windows)
+4*2WR_Erzeuge "relocation code" (Windows)
+A*2WR_Erzeuge "relocation code" (Windows)
+P*2WF_Spezifiziere "MPW tool type application" (Classic Mac OS)
+**2WX_Erm”gliche den executable stack (Linux)
+**1X_Programm-Optionen:
+**2Xc_šbergebe --shared an den Linker (nur Unix)
+**2Xd_Den Standard Bibliotheks-Suchpfad NICHT nutzen (ben”tigt fr cross compile)
+**2Xe_Verwende den externen Linker
+**2Xg_Erstelle die Debug-Informationen in einer separaten Datei und einen "Debug-Link"-Abschnitt im ausfhrbaren Programm
+**2XD_Versuche Units dynamisch zu linken (definiert FPC_LINK_DYNAMIC)
+**2Xi_Verwende den internen Linker
+**2Xm_Erzeuge die "link map"
+**2XM<x>_Setze den Namen der 'main' program Routine (default ist 'main')
+**2XP<x>_Stelle den Namen der Compiler-Hilfsprogrammen den Prefix <x> voran
+**2Xr<x>_Setze den rlink-Pfad des Linker zu <x> (ben”tigt fr cross compile, siehe ld-Manual fr mehr Informationen) (BeOS, Linux)
+**2XR<x>_Stelle allen Linker-Suchpfaden den Namen <x> voran (BeOS, Darwin, FreeBSD, Linux, Mac OS, Solaris)
+**2Xs_Entferne alle Symbole aus der ausfhrbaren Datei
+**2XS_Versuche Units statisch zu linken (default) (definiert FPC_LINK_STATIC)
+**2Xt_Linke mit statischen Bibliotheken (-static wird an den Linker bergeben)
+**2XX_Versuche Units smart zu linken (definiert FPC_LINK_SMART)
+**1*_
+**1?_Zeigt diese Hilfe an
+**1h_Zeigt diese Hilfe ohne Warten an
+]
+
+#
+# The End...
+#
diff --git a/closures/compiler/msg/errorda.msg b/closures/compiler/msg/errorda.msg
new file mode 100644
index 0000000000..16f07e1ec2
--- /dev/null
+++ b/closures/compiler/msg/errorda.msg
@@ -0,0 +1,2501 @@
+#
+# $Id: errorda.msg 621 2006-07-02 15:44:03Z chrivers $
+# This file is part of the Free Pascal Compiler
+# Copyright (c) 1999-2000 by the Free Pascal Development team
+#
+# Danish Language File for Free Pascal
+#
+# Translation by Christian Iversen <chrivers@iversen-net.dk>
+#
+# This file is encoded in UTF-8, and based on r4084 of errore.eng
+#
+# See the file COPYING.FPC, included in this distribution,
+# for details about the copyright.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#
+#
+# The constants are build in the following order:
+# <part>_<type>_<txtidentifier>
+#
+# <part> is the part of the compiler the message is used
+# asmr_ assembler parsing
+# asmw_ assembler writing/binary writers
+
+# unit_ unit handling
+# scan_ scanner
+# parser_ parser
+# type_ type checking
+# general_ general info
+# exec_ calls to assembler, linker, binder
+#
+# <type> the type of the message it should normally used for
+# f_ fatal error
+# e_ error
+# w_ warning
+# n_ note
+# h_ hint
+# i_ info
+# l_ add linenumber
+# u_ used
+# t_ tried
+# c_ conditional
+# d_ debug message
+# x_ executable informations
+#
+
+#
+# General
+#
+# 01016 is the last used one
+#
+# BeginOfTeX
+% \section{General compiler messages}
+% This section gives the compiler messages which are not fatal, but which
+% display useful information. The number of such messages can be
+% controlled with the various verbosity level \var{-v} switches.
+% \begin{description}
+general_t_compilername=01000_T_Oversætter: $1
+% When the \var{-vt} switch is used, this line tells you what compiler
+% is used.
+general_d_sourceos=01001_D_Oversætter OS: $1
+% When the \var{-vd} switch is used, this line tells you what the source
+% operating system is.
+general_i_targetos=01002_I_Compilerer til OS: $1
+% When the \var{-vd} switch is used, this line tells you what the target
+% operating system is.
+general_t_exepath=01003_T_Sti til program: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for it's binaries.
+general_t_unitpath=01004_T_Sti til units: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for compiled units. You can set this path with the \var{-Fu}
+general_t_includepath=01005_T_Sti til include-filer: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for it's include files (files used in \var{\{\$I xxx\}} statements).
+% You can set this path with the \var{-I} option.
+general_t_librarypath=01006_T_Sti til biblioteker: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for the libraries. You can set this path with the \var{-Fl} option.
+general_t_objectpath=01007_T_Sti til objekter: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for object files you link in (files used in \var{\{\$L xxx\}} statements).
+% You can set this path with the \var{-Fo} option.
+general_i_abslines_compiled=01008_I_$1 linier kompileret, $2 sekunder
+% When the \var{-vi} switch is used, the compiler reports the number
+% of lines compiled, and the time it took to compile them (real time,
+% not program time).
+general_f_no_memory_left=01009_F_Ikke mere hukommelse!
+% The compiler doesn't have enough memory to compile your program. There are
+% several remedies for this:
+% \begin{itemize}
+% \item If you're using the build option of the compiler, try compiling the
+% different units manually.
+% \item If you're compiling a huge program, split it up in units, and compile
+% these separately.
+% \item If the previous two don't work, recompile the compiler with a bigger
+% heap (you can use the \var{-Ch} option for this, \seeo{Ch})
+% \end{itemize}
+general_i_writingresourcefile=01010_I_Skriver resourcestrengstabel til fil: $1
+% This message is shown when the compiler writes the Resource String Table
+% file containing all the resource strings for a program.
+general_e_errorwritingresourcefile=01011_E_Skriver resourcestrengtabel til fil: $1
+% This message is shown when the compiler encountered an error when writing
+% the Resource String Table file
+general_i_fatal=01012_I_Fatal fejl:
+% Prefix for Fatal Errors
+general_i_error=01013_I_Fejl:
+% Prefix for Errors
+general_i_warning=01014_I_Advarsel:
+% Prefix for Warnings
+general_i_note=01015_I_Bemærkning:
+% Prefix for Notes
+general_i_hint=01016_I_Hint:
+% Prefix for Hints
+general_e_path_does_not_exist=01017_E_Stien "$1" blev ikke fundet
+% The specified path does not exist.
+general_f_compilation_aborted=01018_F_Compilering afbrudt
+% \end{description}
+#
+# Scanner
+#
+# 02063 is the last used one
+#
+% \section{Scanner messages.}
+% This section lists the messages that the scanner emits. The scanner takes
+% care of the lexical structure of the pascal file, i.e. it tries to find
+% reserved words, strings, etc. It also takes care of directives and
+% conditional compiling handling.
+% \begin{description}
+scan_f_end_of_file=02000_F_Slutning af fil fundet mod forventning
+% this typically happens in one of the following cases :
+% \begin{itemize}
+% \item The source file ends before the final \var{end.} statement. This
+% happens mostly when the \var{begin} and \var{end} statements aren't
+% balanced;
+% \item An include file ends in the middle of a statement.
+% \item A comment was not closed
+% \end{itemize}
+scan_f_string_exceeds_line=02001_F_Streng overskrider slutning af linie
+% There is a missing closing ' in a string, so it occupies
+% multiple lines.
+scan_f_illegal_char=02002_F_Ugyldig karakter "$1" ($2)
+% An illegal character was encountered in the input file.
+scan_f_syn_expected=02003_F_Syntaxfejl, "$1" forventet men "$2" fundet
+% This indicates that the compiler expected a different token than
+% the one you typed. It can occur almost everywhere where you make a
+% mistake against the pascal language.
+scan_t_start_include_file=02004_TL_Læser includefil $1
+% When you provide the \var{-vt} switch, the compiler tells you
+% when it starts reading an included file.
+scan_w_comment_level=02005_W_Kommentarniveau $1 fundet
+% When the \var{-vw} switch is used, then the compiler warns you if
+% it finds nested comments. Nested comments are not allowed in Turbo Pascal
+% and can be a possible source of errors.
+scan_n_ignored_switch=02008_N_Ignorerer compilerindstilling "$1"
+% With \var{-vn} on, the compiler warns if it ignores a switch
+scan_w_illegal_switch=02009_W_Ugyldig compilerindstilling "$1"
+% You included a compiler switch (i.e. \var{\{\$... \}}) which the compiler
+% does not recognise
+scan_w_switch_is_global=02010_W_Fejlplaceret global compilerindstilling
+% The compiler switch is misplaced, and should be located at
+% the start of the unit or program.
+scan_e_illegal_char_const=02011_E_Ugyldig karakterkonstant
+% This happens when you specify a character with its ASCII code, as in
+% \var{\#96}, but the number is either illegal, or out of range.
+scan_f_cannot_open_input=02012_F_Kan ikke åbne filen "$1"
+% \fpc cannot find the program or unit source file you specified on the
+% command line.
+scan_f_cannot_open_includefile=02013_F_Kan ikke åbne includefilen "$1"
+% \fpc cannot find the source file you specified in a \var{\{\$include ..\}}
+% statement.
+scan_e_illegal_pack_records=02015_E_Ugyldig strukturopstillingsspecifikation "$1"
+% You are specifying the \var{\{\$PACKRECORDS n\} } or \var{\{\$ALIGN n\} }
+% with an illegal value for \var{n}. For \$PACKRECORDS valid alignments are 1, 2, 4, 8, 16, 32, C,
+% NORMAL, DEFAULT, and for \$ALIGN valid alignment are 1, 2, 4, 8, 16, 32, ON,
+% OFF. Under mode MacPas \$ALIGN also supports MAC68K, POWER and RESET.
+scan_e_illegal_pack_enum=02016_E_Ugyldig enumerations-minimumsstørrelsespecifikation "$1"
+% You are specifying the \var{\{\$PACKENUM n\}} with an illegal value for
+% \var{n}. Only 1,2,4, NORMAL or DEFAULT are valid here.
+scan_e_endif_expected=02017_E_$ENDIF forventet til $1 $2 defineret i $3 linie $4
+% Your conditional compilation statements are unbalanced.
+scan_e_preproc_syntax_error=02018_E_Syntaxfejl under læsning af betinget kompileret udtryk
+% There is an error in the expression following the \var{\{\$if ..\}}, $ifc or $setc compiler
+% directives.
+scan_e_error_in_preproc_expr=02019_E_Evaluerer betinget kompileret udtryk
+% There is an error in the expression following the \var{\{\$if ..\}}, $ifc or $setc compiler
+% directives.
+scan_w_macro_cut_after_255_chars=02020_W_Makroindhold er begrænset til 255 tegns længde
+% The contents of macros cannot be longer than 255 characters.
+scan_e_endif_without_if=02021_E_ENDIF uden IF(N)DEF
+% Your \var{\{\$IFDEF ..\}} and {\{\$ENDIF\}} statements aren't balanced.
+scan_f_user_defined=02022_F_Brugerdefineret: $1
+% A user defined fatal error occurred. see also the \progref
+scan_e_user_defined=02023_E_Brugerdefineret: $1
+% A user defined error occurred. see also the \progref
+scan_w_user_defined=02024_W_Brugerdefineret: $1
+% A user defined warning occurred. see also the \progref
+scan_n_user_defined=02025_N_Brugerdefineret: $1
+% A user defined note was encountered. see also the \progref
+scan_h_user_defined=02026_H_Brugerdefineret: $1
+% A user defined hint was encountered. see also the \progref
+scan_i_user_defined=02027_I_Brugerdefineret: $1
+% User defined information was encountered. see also the \progref
+scan_e_keyword_cant_be_a_macro=02028_E_Makroer kan ikke omdefinere nøgleord
+% You cannot redefine keywords with macros.
+scan_f_macro_buffer_overflow=02029_F_Overløb under læsning eller udvidelse af makro
+% Your macro or it's result was too long for the compiler.
+scan_w_macro_too_deep=02030_W_Makroudfoldning har oversteget 16 niveauer
+% When expanding a macro, macros have been nested to a level of 16.
+% The compiler will expand no further, since this may be a sign that
+% recursion is used.
+scan_w_wrong_styled_switch=02031_W_Compilerindstillinger understøttes ikke i // denne slags kommentarer
+% Compiler switches should be in normal pascal style comments.
+scan_d_handling_switch=02032_DL_HÃ¥ndterer indstilling "$1"
+% When you set debugging info on (\var{-vd}) the compiler tells you when it
+% is evaluating conditional compile statements.
+scan_c_endif_found=02033_CL_ENDIF $1 fundet
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifdef_found=02034_CL_IFDEF $1 fundet, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifopt_found=02035_CL_IFOPT $1 fundet, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_if_found=02036_CL_IF $1 fundet, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifndef_found=02037_CL_IFNDEF $1 fundet, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_else_found=02038_CL_ELSE $1 fundet, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_skipping_until=02039_CL_Springer over indtil...
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements, and whether it is skipping or
+% compiling parts.
+scan_i_press_enter=02040_I_Tryk <return> for at fortsætte
+% When the \var{-vi} switch is used, the compiler stops compilation
+% and waits for the \var{Enter} key to be pressed when it encounters
+% a \var{\{\$STOP\}} directive.
+scan_w_unsupported_switch=02041_W_Ugyldig compilerindstilling "$1"
+% When warnings are turned on (\var{-vw}) the compiler warns you about
+% unsupported switches. This means that the switch is used in Delphi or
+% Turbo Pascal, but not in \fpc
+scan_w_illegal_directive=02042_W_Ugyldig compilerindstilling "$1"
+% When warings are turned on (\var{-vw}) the compiler warns you about
+% unrecognised switches. For a list of recognised switches, \progref
+scan_t_back_in=02043_TL_Tilbage i $1
+% When you use (\var{-vt}) the compiler tells you when it has finished
+% reading an include file.
+scan_w_unsupported_app_type=02044_W_Ugyldig programtype: "$1"
+% You get this warning, ff you specify an unknown application type
+% with the directive \var{\{\$APPTYPE\}}
+scan_w_app_type_not_support=02045_W_APPTYPE understøttes ikke af det OS der kompileres til
+% The \var{\{\$APPTYPE\}} directive is supported by certain operating systems only.
+scan_w_description_not_support=02046_W_DESCRIPTION understøttes ikke af det OS der kompileres til
+% The \var{\{\$DESCRIPTION\}} directive is not supported on this target OS
+scan_n_version_not_support=02047_N_VERSION understøttes ikke af det OS der kompileres til
+% The \var{\{\$VERSION\}} directive is not supported on this target OS
+scan_n_only_exe_version=02048_N_VERSION er kun til programmer og DLL-filer
+% The \var{\{\$VERSION\}} directive is only used for executable or DLL sources.
+scan_w_wrong_version_ignored=02049_W_Direktivet VERSION har forkert format "$1"
+% The \var{\{\$VERSION\}} directive format is majorversion.minorversion
+% where majorversion and minorversion are words.
+scan_e_illegal_asmmode_specifier=02050_E_Ugyldig assemblerstil angivet "$1"
+% When you specify an assembler mode with the \var{\{\$ASMMODE xxx\}}
+% the compiler didn't recognize the mode you specified.
+scan_w_no_asm_reader_switch_inside_asm=02051_W_Kan ikke skifte assemblerlæser midt i en assemblerblok. Skifter til "$1" i næste blok
+% It is not possible to switch from one assembler reader to another
+% inside an assmebler block. The new reader will be used for next
+% assembler statements only.
+scan_e_wrong_switch_toggle=02052_E_Forkert indstillingsparameter. Brug ON/OFF eller +/-
+% You need to use ON or OFF or a + or - to toggle the switch
+scan_e_resourcefiles_not_supported=02053_E_Resourcefiler understøttes ikke af mål-operativsystemet
+% The target you are compiling for doesn't support resource files.
+scan_w_include_env_not_found=02054_W_Environment-værdien "$1" er ikke defineret
+% The included environment variable cannot be found in the environment, it will
+% be replaced by an empty string instead.
+scan_e_invalid_maxfpureg_value=02055_E_Ugyldig værdi for FPU-registergrænse
+% Valid values for this directive are 0..8 and NORMAL/DEFAULT
+scan_w_only_one_resourcefile_supported=02056_W_Mål-systemet understøtter kun én resourcefil
+% The target you are compiling for supports only one resource file.
+% The first resource file found is used, the others are discarded.
+scan_w_macro_support_turned_off=02057_W_Makrosupport er slået fra
+% A macro declaration has been found, but macro support is currently off,
+% so the declaration will be ignored. To turn macro support on compile with
+% -Sm on the commandline or add {$MACRO ON} in the source
+scan_e_invalid_interface_type=02058_E_Ugyldig interface-type angivet. Gyldige værdier er COM, CORBA eller DEFAULT.
+% The interface type that was specified is not supported
+scan_w_appid_not_support=02059_W_APPID understøttes kun til PalmOS
+% The \var{\{\$APPID\}} directive is only supported for the PalmOS target.
+scan_w_appname_not_support=02060_W_APPNAME understøttes kun til PalmOS
+% The \var{\{\$APPNAME\}} directive is only supported for the PalmOS target.
+scan_e_string_exceeds_255_chars=02061_E_Strengkonstanter kan ikke være længere end 255 tegn
+% A single string constant can contain at most 255 chars. Try splitting up the
+% string in multiple smaller parts and concatenate them with a + operator.
+scan_f_include_deep_ten=02062_F_Include-filer overskrider dypdegrænsen på 16 niveauer
+% When including include files the files have been nested to a level of 16.
+% The compiler will expand no further, since this may be a sign that
+% recursion is used.
+scan_e_too_many_push=02063_F_For mange niveauer af PUSH
+% A maximum of 20 levels is allowed. This error occur only in mode MacPas.
+scan_e_too_many_pop=02064_E_POP uden forudgående PUSH
+% This error occur only in mode MacPas.
+scan_e_error_macro_lacks_value=02065_E_Makro "$1" har ingen værdi
+% Thus the conditional compiling expression cannot be evaluated.
+% \end{description}
+#
+# Parser
+#
+# 03192 is the last used one
+#
+% \section{Parser messages}
+% This section lists all parser messages. The parser takes care of the
+% semantics of you language, i.e. it determines if your pascal constructs
+% are correct.
+% \begin{description}
+scan_e_wrong_switch_toggle_default=02066_E_Forkert indstillingsværdi, brug ON/OFF/DEFAULT eller +/-/*
+% You need to use ON or OFF or DEFAULT or a + or - or * to toggle the switch
+scan_e_mode_switch_not_allowed=02067_E_Tilstandstypeindstilling "$1" ikke tilladt her
+% A mode switch has already been encountered, or, in case of option -Mmacpas,
+% a mode switch occur after UNIT.
+scan_e_error_macro_undefined=02068_E_Kompileringstidsvariablen eller makroen "$1" er ikke defineret
+% Thus the conditional compile time expression cannot be evaluated. Only in mode MacPas.
+scan_e_utf8_bigger_than_65535=02069_E_UTF-8 kode større end 65535 fundet
+% \fpc handles utf-8 strings internally as widestrings e.g. the char codes are limited to 65535
+scan_e_utf8_malformed=02070_E_Ugyldig UTF-8-streng
+% The given string isn't a valid UTF-8 string
+scan_c_switching_to_utf8=02071_C_UTF-8-signatur fundet, benytter UTF-8-kodning
+% The compiler found an UTF-8 encoding signature (\$ef, \$bb, \$bf) at the beginning of a file,
+% so it interprets it as an UTF-8 file
+scan_e_compile_time_typeerror=02072_E_Kompileringstidsudtryk: Forventede $1, men fik $2 ved $3
+% Type check of a compile time expression failed.
+scan_n_app_type_not_support=02073_N_APPTYPE understøttes ikke af mål-operativsystemet
+% The \var{\{\$APPTYPE\}} directive is supported by certain operating systems only.
+% \end{description}
+#
+# Parser
+#
+# 03192 is the last used one
+#
+% \section{Parser messages}
+% This section lists all parser messages. The parser takes care of the
+% semantics of you language, i.e. it determines if your pascal constructs
+% are correct.
+% \begin{description}
+parser_e_syntax_error=03000_E_Parser - syntaxfejl
+% An error against the Turbo Pascal language was encountered. This happens
+% typically when an illegal character is found in the sources file.
+parser_e_dont_nest_interrupt=03004_E_INTERRUPT-procedure kan ikke indlejres
+% An \var{INTERRUPT} procedure must be global.
+parser_w_proc_directive_ignored=03005_W_Proceduretype "$1" ignoreret
+% The specified is ignored by FPC programs.
+parser_e_no_overload_for_all_procs=03006_E_Ikke alle erklæringer af "$1" er angivet med OVERLOAD
+% When you want to use overloading using the \var{OVERLOAD} directive, then
+% all declarations need to have \var{OVERLOAD} specified.
+parser_e_export_name_double=03008_E_Funktionsnavnet "$1" er angivet flere gange i en EXPORT-erklæring
+% Exported function names inside a specific DLL must all be different
+parser_e_export_ordinal_double=03009_E_Funktionsindex $1 er angivet flere gange i en EXPORT-erklæring
+% Exported function names inside a specific DLL must all be different
+parser_e_export_invalid_index=03010_E_Ugyldigt index for eksporteret funktion
+% DLL function index must be in the range \var{1..\$FFFF}
+parser_w_parser_reloc_no_debug=03011_W_Relokérbar DLL eller program $1 har ikke-fungerende debug-info. Slået fra.
+parser_w_parser_win32_debug_needs_WN=03012_W_For at tillade debugging i win32-kode, skal relokérbarhed slås fra med -WN
+% Stabs info is wrong for relocatable DLL or EXES use -WN
+% if you want to debug win32 executables.
+parser_e_constructorname_must_be_init=03013_E_Constructor-navnet skal være INIT
+% You are declaring an object constructor with a name which is not \var{init}, and the
+% \var{-Ss} switch is in effect. See the \var{-Ss} switch (\seeo{Ss}).
+parser_e_destructorname_must_be_done=03014_E_Destructor-navnet skal være DONE
+% You are declaring an object destructor with a name which is not \var{done}, and the
+% \var{-Ss} switch is in effect. See the \var{-Ss} switch (\seeo{Ss}).
+parser_e_proc_inline_not_supported=03016_E_Proceduretypen INLINE er ikke understøttet
+% You tried to compile a program with C++ style inlining, and forgot to
+% specify the \var{-Si} option (\seeo{Si}). The compiler does not support C++
+% styled inlining by default.
+parser_w_constructor_should_be_public=03018_W_Constructor bør være public
+% Constructors must be in the 'public' part of an object (class) declaration.
+parser_w_destructor_should_be_public=03019_W_Destructor bør være public
+% Destructors must be in the 'public' part of an object (class) declaration.
+parser_n_only_one_destructor=03020_N_En klasse skal kun have én destructor
+% You can declare only one destructor for a class.
+parser_e_no_local_objects=03021_E_Lokale klassedefinitioner er ikke tilladt
+% Classes must be defined globally. They cannot be defined inside a
+% procedure or function
+parser_f_no_anonym_objects=03022_F_Anonyme klassedefinitioner er ikke tilladt
+% An invalid object (class) declaration was encountered, i.e. an
+% object or class without methods that isn't derived from another object or
+% class. For example:
+% \begin{verbatim}
+% Type o = object
+% a : longint;
+% end;
+% \end{verbatim}
+% will trigger this error.
+parser_n_object_has_no_vmt=03023_N_Objektet "$1" har ingen VMT
+% This is a note indicating that the declared object has no
+% virtual method table.
+parser_e_illegal_parameter_list=03024_E_Ugyldig parameterliste
+% You are calling a function with parameters that are of a different type than
+% the declared parameters of the function.
+parser_e_wrong_parameter_size=03026_E_Forkert antal parametre angivet
+% There is an error in the parameter list of the function or procedure,
+% the number of parameters is not correct.
+parser_e_overloaded_no_procedure=03027_E_Overloaded navn "$1" er ikke en funktion
+% The compiler encountered a symbol with the same name as an overloaded
+% function, but it is not a function it can overload.
+parser_e_overloaded_have_same_parameters=03028_E_Overloadede funktioner har samme parametre
+% You're declaring overloaded functions, but with the same parameter list.
+% Overloaded function must have at least 1 different parameter in their
+% declaration.
+parser_e_header_dont_match_forward=03029_E_Functionserklæring passer ikke med forward-erklæringen $1
+% You declared a function with same parameters but
+% different result type or function modifiers.
+parser_e_header_different_var_names=03030_E_Funktionserklæringen "$1" passer ikke med forward - var-navn ændrer $2 => $3
+% You declared the function in the \var{interface} part, or with the
+% \var{forward} directive, but define it with a different parameter list.
+parser_n_duplicate_enum=03031_N_Værdier i enumerate-typer skal være stigende
+% \fpc allows enumeration constructions as in C. Given the following
+% declaration two declarations:
+% \begin{verbatim}
+% type a = (A_A,A_B,A_E:=6,A_UAS:=200);
+% type a = (A_A,A_B,A_E:=6,A_UAS:=4);
+% \end{verbatim}
+% The second declaration would produce an error. \var{A\_UAS} needs to have a
+% value higher than \var{A\_E}, i.e. at least 7.
+parser_e_no_with_for_variable_in_other_segments=03033_E_"With" kan ikke bruges til variabler i et andet segment
+% With stores a variable locally on the stack,
+% but this is not possible if the variable belongs to another segment.
+parser_e_too_much_lexlevel=03034_E_Funktionsindlejring over 31 niveauer
+% You can nest function definitions only 31 times.
+parser_e_range_check_error=03035_E_Værdiområdefejl under evaluering af konstanter
+% The constants are out of their allowed range.
+parser_w_range_check_error=03036_W_Værdiområdefejl under evaluering af konstanter
+% The constants are out of their allowed range.
+parser_e_double_caselabel=03037_E_Gentaget case-værdi
+% You are specifying the same label 2 times in a \var{case} statement.
+parser_e_case_lower_less_than_upper_bound=03038_E_Øvre grænse for case-værdiområde er mindre end den nedre grænse
+% The upper bound of a \var{case} label is less than the lower bound and this
+% is useless
+parser_e_type_const_not_possible=03039_E_Typegivne konstanter er ikke tilladt i klasser
+% You cannot declare a constant of type class or object.
+parser_e_no_overloaded_procvars=03040_E_Tildeling af overloaded funktion til procedurel variabel ikke tilladt
+% You are trying to assign an overloaded function to a procedural variable.
+% This is not allowed
+parser_e_invalid_string_size=03041_E_Strenglængdegrænse skal være mellem 1 og 255
+% The length of a shortstring in Pascal is limited to 255 characters. You are
+% trying to declare a string with length lower than 1 or greater than 255
+parser_w_use_extended_syntax_for_objects=03042_W_Brug udvidet syntax NEW og DISPOSE til instantiering af objekter
+% If you have a pointer \var{a} to a class type, then the statement
+% \var{new(a)} will not initialize the class (i.e. the constructor isn't
+% called), although space will be allocated. you should issue the
+% \var{new(a,init)} statement. This will allocate space, and call the
+% constructor of the object
+parser_w_no_new_dispose_on_void_pointers=03043_W_Brug af NEW eller DISPOSE på typeløse pointere er meningsløst
+parser_e_no_new_dispose_on_void_pointers=03044_E_Brug af NEW eller DISPOSE på typeløse pointere ikke muligt
+% You cannot use \var{new(p)} or \var{dispose(p)} if \var{p} is an untyped pointer
+% because no size is associated to an untyped pointer.
+% Accepted for compatibility in \var{tp} and \var{delphi} modes.
+parser_e_class_id_expected=03045_E_Klassenavn forventet
+% This happens when the compiler scans a procedure declaration that contains
+% a dot,
+% i.e., a object or class method, but the type in front of the dot is not
+% a known type.
+parser_e_no_type_not_allowed_here=03046_E_Typenavn ikke tilladt her
+% You cannot use a type inside an expression.
+parser_e_methode_id_expected=03047_E_Metodenavn forventet
+% This identifier is not a method.
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., a object or class method, but the procedure name is not a
+% procedure of this type.
+parser_e_header_dont_match_any_member=03048_E_Funktionserklæring passer ikke med nogen metoder i klassen "$1"
+% This identifier is not a method.
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., a object or class method, but the procedure name is not a
+% procedure of this type.
+parser_d_procedure_start=03049_DL_procedure/funktion $1
+% When using the \var{-vd} switch, the compiler tells you when it starts
+% processing a procedure or function implementation.
+parser_e_error_in_real=03050_E_Ugyldig kommetalskonstant
+% The compiler expects a floating point expression, and gets something else.
+parser_e_fail_only_in_constructor=03051_E_FAIL kan kun bruges i en constructor
+% You are using the \var{fail} keyword outside a constructor method.
+parser_e_no_paras_for_destructor=03052_E_En destructor kan ikke have parametre
+% You are declaring a destructor with a parameter list. Destructor methods
+% cannot have parameters.
+parser_e_only_class_methods_via_class_ref=03053_E_Kun klassemetoder kan refereres med en klassereference
+% This error occurs in a situation like the following:
+% \begin{verbatim}
+% Type :
+% Tclass = Class of Tobject;
+%
+% Var C : TClass;
+%
+% begin
+% ...
+% C.free
+% \end{verbatim}
+% \var{Free} is not a class method and hence cannot be called with a class
+% reference.
+parser_e_only_class_methods=03054_E_Kun klassemetoder kan tilgås i klassemetoder
+% This is related to the previous error. You cannot call a method of an object
+% from a inside a class method. The following code would produce this error:
+% \begin{verbatim}
+% class procedure tobject.x;
+%
+% begin
+% free
+% \end{verbatim}
+% Because free is a normal method of a class it cannot be called from a class
+% method.
+parser_e_case_mismatch=03055_E_Constant-type of CASE-type stemmer ikke overens
+% One of the labels is not of the same type as the case variable.
+parser_e_illegal_symbol_exported=03056_E_Symbolet kan ikke eksporteres fra et bibliotek
+% You can only export procedures and functions when you write a library. You
+% cannot export variables or constants.
+parser_w_should_use_override=03057_W_En nedarvet metode skjules af "$1"
+% A method that is declared \var{virtual} in a parent class, should be
+% overridden in the descendent class with the \var{override} directive. If you
+% don't specify the \var{override} directive, you will hide the parent method;
+% you will not override it.
+parser_e_nothing_to_be_overridden=03058_E_Der er ingen metode i super-klassen at override: "$1"
+% You are trying to \var{override} a virtual method of a parent class that does
+% not exist.
+parser_e_no_procedure_to_access_property=03059_E_Ingen læseadgang til egenskaben
+% You specified no \var{read} directive for a property.
+parser_w_stored_not_implemented=03060_W_Gemte egenskaber er endnu ikke implementeret
+% The \var{stored} directive is not yet implemented
+parser_e_ill_property_access_sym=03061_E_Ugyldig værdi for egenskabsadgang
+% There is an error in the \var{read} or \var{write} directives for an array
+% property. When you declare an array property, you can only access it with
+% procedures and functions. The following code woud cause such an error.
+% \begin{verbatim}
+% tmyobject = class
+% i : integer;
+% property x [i : integer]: integer read I write i;
+% \end{verbatim}
+%
+parser_e_cant_access_protected_member=03062_E_Kan ikke tilgå et protected felt i et objekt her
+% Fields that are declared in a \var{protected} section of an object or class
+% declaration cannot be accessed outside the module wher the object is
+% defined, or outside descendent object methods.
+parser_e_cant_access_private_member=03063_E_Kan ikke tilgå et private felt i et objekt her
+% Fields that are declared in a \var{private} section of an object or class
+% declaration cannot be accessed outside the module where the class is
+% defined.
+parser_e_overridden_methods_not_same_ret=03066_E_Metoder med "override" skal have samme retur-type: "$2" er overridet af "$1" der har en anden retur-type
+% If you declare overridden methods in a class definition, they must
+% have the same return type.
+parser_e_dont_nest_export=03067_E_EXPORT-erklærede funktioner kan ikke indlejres
+% You cannot declare a function or procedure within a function or procedure
+% that was declared as an export procedure.
+parser_e_methods_dont_be_export=03068_E_Metoder kan ikke EXPORT'es
+% You cannot declare a procedure that is a method for an object as
+% \var{export}ed.
+parser_e_call_by_ref_without_typeconv=03069_E_Kald med var-parametre skal passe præcist: Fandt "$1", "$2" forventet
+% When calling a function declared with \var{var} parameters, the variables in
+% the function call must be of exactly the same type. There is no automatic
+% type conversion.
+parser_e_no_super_class=03070_E_Klassen er ikke en super-klasse af den angivne klasse
+% When calling inherited methods, you are trying to call a method of a non-related
+% class. You can only call an inherited method of a parent class.
+parser_e_self_not_in_method=03071_E_SELF kan kun bruges i objekter
+% You are trying to use the \var{self} parameter outside an object's method.
+% Only methods get passed the \var{self} parameters.
+parser_e_generic_methods_only_in_methods=03072_E_methods can be only in other methods called direct with type identifier of the class
+% A construction like \var{sometype.somemethod} is only allowed in a method.
+parser_e_illegal_colon_qualifier=03073_E_Ugyldig brug af ':'
+% You are using the format \var{:} (colon) 2 times on an expression that
+% is not a real expression.
+parser_e_illegal_set_expr=03074_E_Værdigrænsefejl i set-constructor, eller genanvendt element-værdi
+% The declaration of a set contains an error. Either one of the elements is
+% outside the range of the set type, either two of the elements are in fact
+% the same.
+parser_e_pointer_to_class_expected=03075_E_Pointer til objekt forventet
+% You specified an illegal type in a \var{new} statement.
+% The extended syntax of \var{new} needs an object as a parameter.
+parser_e_expr_have_to_be_constructor_call=03076_E_Udtryk skal være constructor-kald
+% When using the extended syntax of \var{new}, you must specify the constructor
+% method of the object you are trying to create. The procedure you specified
+% is not a constructor.
+parser_e_expr_have_to_be_destructor_call=03077_E_Udtryk skal være destructor-kald
+% When using the extended syntax of \var{dispose}, you must specify the
+% destructor method of the object you are trying to dispose of.
+% The procedure you specified is not a destructor.
+parser_e_invalid_record_const=03078_E_Ugyldig rækkefølge af strukturelementer
+% When declaring a constant record, you specified the fields in the wrong
+% order.
+parser_e_false_with_expr=03079_E_Udtrykket skal være en klasse eller struktur
+% A \var{with} statement needs an argument that is of the type \var{record}
+% or \var{class}. You are using \var{with} on an expression that is not of
+% this type.
+parser_e_void_function=03080_E_Procedurer kan ikke returnere værdier
+% In \fpc, you can specify a return value for a function when using
+% the \var{exit} statement. This error occurs when you try to do this with a
+% procedure. Procedures cannot return a value.
+parser_e_only_methods_allowed=03081_E_constructors destructors og class operators skal være metoder
+% You're declaring a procedure as destructor, constructor or class operator, when the
+% procedure isn't a class method.
+parser_e_operator_not_overloaded=03082_E_Operatoren er ikke overloaded
+% You're trying to use an overloaded operator when it is not overloaded for
+% this type.
+parser_e_no_such_assignment=03083_E_Umuligt at overloade tildeling for ensartede typer
+% You can not overload assignment for types
+% that the compiler considers as equal.
+parser_e_overload_impossible=03084_E_Umuligt at overloade operatoren
+% The combination of operator, arguments and return type are
+% incompatible.
+parser_e_no_reraise_possible=03085_E_Re-raise er ikke muligt her
+% You are trying to raise an exception where it is not allowed. You can only
+% raise exceptions in an \var{except} block.
+parser_e_no_new_or_dispose_for_classes=03086_E_Den udvidede syntax af new og dispose er ikke gyldig for klasser
+% You cannot generate an instance of a class with the extended syntax of
+% \var{new}. The constructor must be used for that. For the same reason, you
+% cannot call \var{dispose} to de-allocate an instance of a class, the
+% destructor must be used for that.
+parser_e_procedure_overloading_is_off=03088_E_Procedure overloading er slået fra
+% When using the \var{-So} switch, procedure overloading is switched off.
+% Turbo Pascal does not support function overloading.
+parser_e_overload_operator_failed=03089_E_Det er ikke muligt at overloade denne operator (overload "=" i stedet)
+% You are trying to overload an operator which cannot be overloaded.
+% The following operators can be overloaded :
+% \begin{verbatim}
+% +, -, *, /, =, >, <, <=, >=, is, as, in, **, :=
+% \end{verbatim}
+parser_e_comparative_operator_return_boolean=03090_E_Sammenligningsoperationer skal returnere en sandhedsværdi
+% When overloading the \var{=} operator, the function must return a boolean
+% value.
+parser_e_only_virtual_methods_abstract=03091_E_Kun virtuelle metoder kan være abstrakte
+% You are declaring a method as abstract, when it is not declared to be
+% virtual.
+parser_f_unsupported_feature=03092_F_Ikke-understøttet konstruktion
+% You're trying to force the compiler into doing something it cannot do yet.
+parser_e_mix_of_classes_and_objects=03093_E_Det er ikke gyldigt at blande forskellige typer objekter (class, object, interface, etc)
+% You cannot derive \var{objects}, \var{classes}, \var{cppclasses} and \var{interfaces} interttwined . E.g.
+% a class cannot have an object as parent and vice versa.
+parser_w_unknown_proc_directive_ignored=03094_W_Ukendt procedure-direktev blev ignoreret: "$1"
+% The procedure directive you specified is unknown.
+parser_e_absolute_only_one_var=03095_E_Absolute kan kun associere én variabel
+% You cannot specify more than one variable before the \var{absolute} directive.
+% Thus, the following construct will provide this error:
+% \begin{verbatim}
+% Var Z : Longint;
+% X,Y : Longint absolute Z;
+% \end{verbatim}
+% \item [ absolute can only be associated a var or const ]
+% The address of a \var{absolute} directive can only point to a variable or a
+% typed constant. Therefore, the following code will produce this error:
+% \begin{verbatim}
+% Procedure X;
+%
+% var p : longint absolute x;
+% \end{verbatim}
+%
+parser_e_absolute_only_to_var_or_const=03096_E_Absolute kan kun associeres med én variabel eller konstant
+% The address of a \var{absolute} directive can only point to a variable or
+% constant. Therefore, the following code will produce this error:
+% \begin{verbatim}
+% Procedure X;
+%
+% var p : longint absolute x;
+% \end{verbatim}
+%
+parser_e_initialized_only_one_var=03097_E_Kun én variabel kan initialiseres
+% You cannot specify more than one variable with a initial value
+% in Delphi mode.
+parser_e_abstract_no_definition=03098_E_Abstrakte metoder må ikke implementeres
+% Abstract methods can only be declared, you cannot implement them. They
+% should be overridden by a descendant class.
+parser_e_overloaded_must_be_all_global=03099_E_Denne overloadede funktion kan ikke være lokal (skal eksporteres)
+% You are defining a overloaded function in the implementation part of a unit,
+% but there is no corresponding declaration in the interface part of the unit.
+parser_w_virtual_without_constructor=03100_W_Virtuelle metoder er brugt uden at have en constructor: "$1"
+% If you declare objects or classes that contain virtual methods, you need
+% to have a constructor and destructor to initialize them. The compiler
+% encountered an object or class with virtual methods that doesn't have
+% a constructor/destructor pair.
+parser_c_macro_defined=03101_CL_Makro defineret: $1
+% When \var{-vc} is used, the compiler tells you when it defines macros.
+parser_c_macro_undefined=03102_CL_Makro fjernet: $1
+% When \var{-vc} is used, the compiler tells you when it undefines macros.
+parser_c_macro_set_to=03103_CL_Makro $1 sat til $2
+% When \var{-vc} is used, the compiler tells you what values macros get.
+parser_i_compiling=03104_I_Compilerer $1
+% When you turn on information messages (\var{-vi}), the compiler tells you
+% what units it is recompiling.
+parser_u_parsing_interface=03105_UL_Parser interface-delen af unit $1
+% This tells you that the reading of the interface
+% of the current unit starts
+parser_u_parsing_implementation=03106_UL_Parser implementation-delen af unit $1
+% This tells you that the code reading of the implementation
+% of the current unit, library or program starts
+parser_d_compiling_second_time=03107_DL_Compilerer $1 for anden gang
+% When you request debug messages (\var{-vd}) the compiler tells you what
+% units it recompiles for the second time.
+parser_e_no_property_found_to_override=03109_E_Ingen egenskab at override
+% You want to overrride a property of a parent class, when there is, in fact,
+% no such property in the parent class.
+parser_e_only_one_default_property=03110_E_Kun én default-egenskab tilladt
+% You specified a property as \var{Default}, but the class already has a
+% default property, and a class can have only one default property.
+parser_e_property_need_paras=03111_E_Default-egenskaben skal være et array
+% Only array properties of classes can be made \var{default} properties.
+parser_e_constructor_cannot_be_not_virtual=03112_E_Virtuelle constructors er kun tilladt i klassemodellen
+% You cannot have virtual constructors in objects. You can only have them
+% in classes.
+parser_e_no_default_property_available=03113_E_Ingen default-egenskab tilgængelig
+% You are trying to access a default property of a class, but this class (or one of
+% it's ancestors) doesn't have a default property.
+parser_e_cant_have_published=03114_E_Klassen kan ikke have en published-sektion, brug {$M+}-indstillingen
+% If you want a \var{published} section in a class definition, you must
+% use the \var{\{\$M+\}} switch, whch turns on generation of type
+% information.
+parser_e_forward_declaration_must_be_resolved=03115_E_Forward-erklæring af klasse "$1" skal løses her, for at bruge klassen som super-klasse
+% To be able to use an object as an ancestor object, it must be defined
+% first. This error occurs in the following situation:
+% \begin{verbatim}
+% Type ParentClas = Class;
+% ChildClass = Class(ParentClass)
+% ...
+% end;
+% \end{verbatim}
+% Where \var{ParentClass} is declared but not defined.
+parser_e_no_local_operator=03116_E_Lokale operatorer ikke understøttet
+% You cannot overload locally, i.e. inside procedures or function
+% definitions.
+parser_e_proc_dir_not_allowed_in_interface=03117_E_Procedure-direktivet "$1" er ikke tilladt i interface-sektionen
+% This procedure directive is not allowed in the \var{interface} section of
+% a unit. You can only use it in the \var{implementation} section.
+parser_e_proc_dir_not_allowed_in_implementation=03118_E_Procedure-direktivet "$1" er ikke tilladt i implementation-sektionen
+% This procedure directive is not defined in the \var{implementation} section of
+% a unit. You can only use it in the \var{interface} section.
+parser_e_proc_dir_not_allowed_in_procvar=03119_E_Procedure-direktivet "$1" er ikke tilladt i procvar-erklæring
+% This procedure directive cannot be part of a procedural or function
+% type declaration.
+parser_e_function_already_declared_public_forward=03120_E_Funktionen "$1" er allerede erklæret Public/Forward
+% You will get this error if a function is defined as \var{forward} twice.
+% Or it is once in the \var{interface} section, and once as a \var{forward}
+% declaration in the \var{implmentation} section.
+parser_e_not_external_and_export=03121_E_Kan ikke bruge både EXPORT og EXTERNAL
+% These two procedure directives are mutually exclusive
+parser_w_not_supported_for_inline=03123_W_Deklarationen "$1" er endnu ikke understøttet i inline procedurer/funktioner
+% Inline procedures don't support this declaration.
+parser_w_inlining_disabled=03124_W_Inlining slået fra
+% Inlining of procedures is disabled.
+parser_i_writing_browser_log=03125_I_Skriver browser-log $1
+% When information messages are on, the compiler warns you when it
+% writes the browser log (generated with the \var{\{\$Y+ \}} switch).
+parser_h_maybe_deref_caret_missing=03126_H_MÃ¥ske mangler en pointer-dereference
+% The compiler thinks that a pointer may need a dereference.
+parser_f_assembler_reader_not_supported=03127_F_Valgt assembler-læser er ikke understøttet
+% The selected assembler reader (with \var{\{\$ASMMODE xxx\}} is not
+% supported. The compiler can be compiled with or without support for a
+% particular assembler reader.
+parser_e_proc_dir_conflict=03128_E_Procedure-direktivet "$1" er i konflikt med andre direktiver
+% You specified a procedure directive that conflicts with other directives.
+% for instance \var{cdecl} and \var{pascal} are mutually exclusive.
+parser_e_call_convention_dont_match_forward=03129_E_Kaldkonvention passer ikke med forward-erklæring
+% This error happens when you declare a function or procedure with
+% e.g. \var{cdecl;} but omit this directive in the implementation, or vice
+% versa. The calling convention is part of the function declaration, and
+% must be repeated in the function definition.
+parser_e_property_cant_have_a_default_value=03131_E_Egenskaben kan ikke have default-værdi
+% Set properties or indexed properties cannot have a default value.
+parser_e_property_default_value_must_const=03132_E_Default-værdien for en egenskab skal være konstant
+% The value of a \var{default} declared property must be known at compile
+% time. The value you specified is only known at run time. This happens
+% .e.g. if you specify a variable name as a default value.
+parser_e_cant_publish_that=03133_E_Variabler kan ikke være published, med mindre de er klasser
+% Only class type variables can be in a \var{published} section of a class
+% if they are not declared as a property.
+parser_e_cant_publish_that_property=03134_E_Egenskabs-typen er ikke understøttet i published
+% Properties in a \var{published} section cannot be array properties.
+% they must be moved to public sections. Properties in a \var{published}
+% section must be an ordinal type, a real type, strings or sets.
+parser_e_empty_import_name=03136_E_Et import-navn er krævet
+% Some targets need a name for the imported procedure or a \var{cdecl} specifier
+parser_e_division_by_zero=03138_E_Division med nul
+% There is a divsion by zero encounted
+parser_e_invalid_float_operation=03139_E_Ugyldig floating-point operation
+% An operation on two real type values produced an overflow or a division
+% by zero.
+parser_e_array_lower_less_than_upper_bound=03140_E_Øvre grænse er mindre end nedre grænse
+% The upper bound of a an array declaration is less than the lower bound and this
+% is not possible
+parser_w_string_too_long=03141_W_Strengen "$1" er længere end "$2"
+% The size of the constant string is larger than the size you specified in
+% string type definition
+parser_e_string_larger_array=03142_E_Strenglængde er større end længden af karakter-arrayet
+% The size of the constant string is larger than the size you specified in
+% the array[x..y] of char definition
+parser_e_ill_msg_expr=03143_E_Ugyldigt udtryk efter beskedddirektiv
+% \fpc supports only integer or string values as message constants
+parser_e_ill_msg_param=03144_E_Procedurerer til beskedhåndtering kan kun tage én parameter, der skal være en reference (var)
+% A method declared with the \var{message}-directive as message handler
+% can take only one parameter which must be declared as call by reference
+% Parameters are declared as call by reference using the \var{var}-directive
+parser_e_duplicate_message_label=03145_E_Gentaget besked-værdi: "$1"
+% A label for a message is used twice in one object/class
+parser_e_self_in_non_message_handler=03146_E_"Self" kan kun være en eksplicit parameter i metoder der er beskedhandlere
+% The self parameter can only be passed explicitly to a method which
+% is declared as message handler.
+parser_e_threadvars_only_sg=03147_E_Trådvariabler kan kun erklæres static eller globalt
+% Threadvars must be static or global, you can't declare a thread
+% local to a procedure. Local variables are always local to a thread,
+% because every thread has it's own stack and local variables
+% are stored on the stack
+parser_f_direct_assembler_not_allowed=03148_F_Direkte assembler er ikke understøttet i det binære udformat
+% You can't use direct assembler when using a binary writer, choose an
+% other outputformat or use another assembler reader
+parser_w_no_objpas_use_mode=03149_W_Inkludér ikke unit'en OBJPAS manuelt, brug i stedet {$mode objfpc} eller {$mode delphi}
+% You are trying to load the ObjPas unit manually from a uses clause. This is
+% not a good idea. Use the \var{\{\$mode objfpc\}} or
+% \var{\{\$mode delphi\}}
+% directives which load the unit automatically
+parser_e_no_object_override=03150_E_OVERRIDE kan ikke bruges i objekter
+% Override is not supported for objects, use \var{virtual} instead to override
+% a method of a parent object
+parser_e_cant_use_inittable_here=03151_E_Datatyper der kræver initialisering/afslutning kan ikke bruges i en variantstruktur
+% Some data type (e.g. \var{ansistring}) needs initialization/finalization
+% code which is implicitly generated by the compiler. Such data types
+% can't be used in the variant part of a record.
+parser_e_resourcestring_only_sg=03152_E_Strengresourcer kan kun være statiske eller globale
+% Resourcestring can not be declared local, only global or using the static
+% directive.
+parser_e_exit_with_argument_not__possible=03153_E_Exit med parametre kan ikke bruges her
+% an exit statement with an argument for the return value can't be used here, this
+% can happen e.g. in \var{try..except} or \var{try..finally} blocks
+parser_e_stored_property_must_be_boolean=03154_E_Storage-symbolet skal være en sandhedsværdi
+% If you specify a storage symbol in a property declaration, it must be of
+% the type boolean
+parser_e_ill_property_storage_sym=03155_E_Dette symbol er ikke tilladt som storage-symbol
+% You can't use this type of symbol as storage specifier in property
+% declaration. You can use only methods with the result type boolean,
+% boolean class fields or boolean constants
+parser_e_only_publishable_classes_can__be_published=03156_E_Kun klasser der er kompileret i med {$M+}-indstillingen kan bruge published
+% In the published section of a class can be only class as fields used which
+% are compiled in \var{\{\$M+\}} or which are derived from such a class. Normally
+% such a class should be derived from TPersitent
+parser_e_proc_directive_expected=03157_E_Procedure-direktiv forventet
+% When declaring a procedure in a const block you used a ; after the
+% procedure declaration after which a procedure directive must follow.
+% Correct declarations are:
+% \begin{verbatim}
+% const
+% p : procedure;stdcall=nil;
+% p : procedure stdcall=nil;
+% \end{verbatim}
+parser_e_invalid_property_index_value=03158_E_Værdien for egenskabs-indexet skal være en ordinal-type
+% The value you use to index a property must be of an ordinal type, for
+% example an integer or enumerated type.
+parser_e_procname_to_short_for_export=03159_E_Procedurenavn for kort til at eksportere
+% The length of the procedure/function name must be at least 2 characters
+% long. This is because of a bug in dlltool which doesn't parse the .def
+% file correct with a name of length 1.
+parser_e_dlltool_unit_var_problem=03160_E_Intet DEFFILE-opslag kan genereres for variabler der er globale i en unit
+parser_e_dlltool_unit_var_problem2=03161_E_Kompilér uden -WD indstillingen
+% You need to compile this file without the -WD switch on the
+% commandline
+parser_f_need_objfpc_or_delphi_mode=03162_F_Du skal bruge ObjFpc (-S2) eller Delphi (-Sd)-mode for at kompilere denne fil
+% You need to use {$mode objfpc} or {$mode delphi} to compile this file.
+% Or use the equivalent commandline switches -S2 or -Sd.
+parser_e_no_export_with_index_for_target=03163_E_Kan ikke eksportere med index under $1
+% Exporting of functions or procedures with a specified index is not
+% supported on this target.
+parser_e_no_export_of_variables_for_target=03164_E_Eksport af variabler ikke understøttet af målsystemet $1
+% Exporting of variables is not supported on this target.
+parser_e_improper_guid_syntax=03165_E_Ugyldig GUID-syntax
+parser_w_interface_mapping_notfound=03168_W_En procedure kaldet $1 der kan implementere $2 blev ikke fundet. $3
+parser_e_interface_id_expected=03169_E_Interface-navn krævet
+% This happens when the compiler scans a \var{class} declaration that contains
+% \var{interface} function name mapping code like this:
+% \begin{verbatim}
+% type
+% TMyObject = class(TObject, IDispatch)
+% function IUnknown.QueryInterface=MyQueryInterface;
+% ....
+% \end{verbatim}
+% and the \var{interface} before the dot not listed in the inheritance list.
+parser_e_type_cant_be_used_in_array_index=03170_E_Typen "$1" kan ikke bruges som index-type i et array
+% Types like \var{qword} or \var{int64} aren't allowed as array index type
+parser_e_no_con_des_in_interfaces=03171_E_Con- og destructors er ikke tilladt i interfaces
+% Constructor and destructor declarations aren't allowed in interface
+% In the most cases the method \var{QueryInterface} of \var{IUnknown} can
+% be used to create a new interface.
+parser_e_no_access_specifier_in_interfaces=03172_E_Adgangskrav kan ikke sættes i et interface
+% The access specifiers \var{public}, \var{private}, \var{protected} and
+% \var{pusblished} can't be used in interfaces because all methods
+% of an interfaces must be public.
+parser_e_no_vars_in_interfaces=03173_E_Et interface kan ikke indeholde felter
+% Declarations of fields aren't allowed in interfaces. An interface
+% can contain only methods
+parser_e_no_local_proc_external=03174_E_Kan ikke erklære en lokal procedure som ekstern
+% Declaring local procedures as external is not possible. Local procedures
+% get hidden parameters that will make the chance of errors very high
+parser_w_skipped_fields_before=03175_W_Visse felter i "$1" blev ikke initialiseret
+% In Delphi mode, not all fields of a typed constant record have to be
+% initialized, but the compiler warns you when it detects such situations.
+parser_e_skipped_fields_before=03176_E_Visse felter i "$1" blev ikke initialiseret
+% In all syntax modes but Delphi mode, you can't leave some fields uninitialized
+% in the middle of a typed constant record
+parser_w_skipped_fields_after=03177_W_Visse felter efter "$1" er ikke initialiseret
+% You can leave some fields at the end of a type constant record uninitialized
+% (the compiler will initialize them to zero automatically). This may be the cause
+% of subtle problems.
+parser_e_varargs_need_cdecl_and_external=03178_E_VarArgs-direktiv uden CDecl og External
+% The varargs directive can only be used with procedures or functions
+% that are declared with \var{cdecl} and \var{external} directives. The varargs directive
+% is only meant to provide a compatible interface to C functions like printf.
+parser_e_self_call_by_value=03179_E_Self skal være en almindelig (værdioverført) parameter
+% You can't declare self as a const or var parameter, it must always be
+% a call-by-value parameter
+parser_e_interface_has_no_guid=03180_E_Interfacet "$1" har intet GUID
+% When you want to assign an interface to a constant, then the interface
+% must have a GUID value set.
+parser_e_illegal_field_or_method=03181_E_Ukendt klassefelt eller metodenavn "$1"
+% Properties must refer to a field or method in the same class.
+parser_w_proc_overriding_calling=03182_W_Overrider kaldkonvention mellem "$1" og "$2"
+% There are two directives in the procedure declaration that specify a calling
+% convention. Only the last directive will be used
+parser_e_no_procvarobj_const=03183_E_Konstanter af typen "procedure of object" kan kun initialiseres med NIL
+% You can't assign the address of a method to a typed constant which has a
+% 'procedure of object' type, because such a constant requires two addresses:
+% that of the method (which is known at compile time) and that of the object or
+% class instance it operates on (which can not be known at compile time).
+parser_e_default_value_only_one_para=03184_E_Default-værdi kan kun tildeles én parameter
+parser_e_default_value_expected_for_para=03185_E_Default-værdi krævet for parameter "$1"
+parser_w_unsupported_feature=03186_W_Feature ikke understøttet
+% You're trying to force the compiler into doing something it cannot do yet.
+parser_h_c_arrays_are_references=03187_H_C-arrays videregives som reference
+% Any array passed to a C functions is passed
+% by a pointer (i.e. by reference).
+parser_e_C_array_of_const_must_be_last=03188_E_C-arrays af konstanter skal være det sidste element
+% You can not add any other argument after an \var{array of const} for
+% \var{cdecl} functions, as the size pushed on stack for this argument is
+% not known.
+parser_h_type_redef=03189_H_Type "$1" redefineret
+% This is an indicator that a previously declared type is
+% being redefined as something else. This may, or may not
+% be, a cause for errors.
+parser_w_cdecl_has_no_high=03190_W_cdecl'arerede funktioner har ingen "high"-parameter
+% Functions declared with cdecl modifier do not pass an extra implicit parameter.
+parser_w_cdecl_no_openstring=03191_W_cdecl'arerede funktioner understøtter ikke åbne strenge
+% Openstring is not supported for cdecl'ared functions.
+parser_e_initialized_not_for_threadvar=03192_E_Kan ikke initialisere variabler der er erklæret som threadvar
+% Variables declared as threadvar can not be initialized with a default value.
+% The variables will always be filled with zero at the start of a new thread.
+parser_e_msg_only_for_classes=03193_E_Message-direktivet kun gyldigt i klasser
+% The message directive is only supported for Class types.
+parser_e_procedure_or_function_expected=03194_E_Procedure eller Function forventet
+% A class method can only be specified for procedures and functions.
+parser_e_illegal_calling_convention=03195_W_Kaldkonventions-direktiv ignoreret: "$1"
+% Some calling conventions are supported only by certain CPUs. I.e. most non-i386 ports support
+% only the standard ABI calling convention of the CPU.
+parser_e_no_object_reintroduce=03196_E_REINTRODUCE kan ikke bruges i objekter
+% \var{reintroduce} is not supported for objects.
+parser_e_paraloc_only_one_para=03197_E_Hvert argument skal have sin egen pladsspecifikation
+% If locations for arguments are specified explicitly as it is required by
+% some syscall conventions, each argument must have it's only location, things
+% like \var{procedure p(i,j : longint 'r1');} aren't allowed
+parser_e_paraloc_all_paras=03198_E_Hvert argument skal have en specifik pladsspecifikatino
+% If one argument has an explicit argument location, all arguments of a procedure
+% must have one.
+parser_e_illegal_explicit_paraloc=03199_E_Ukendt pladsspecifikation parameter
+% The location specified for an argument isn't recognized by the compiler
+parser_e_32bitint_or_pointer_variable_expected=03200_E_32-bit heltal eller pointer forventet
+% The libbase for MorphOS/AmigaOS can be give only as \var{longint}, \var{dword} or any pointer variable.
+parser_e_goto_outside_proc=03201_E_Goto-erklæring ikke tilladt mellem forskellige procedurer
+% It isn't allowed to use the \var{goto} statements referencing labels outside the
+% current procedure. The following example shows the problem:
+% \begin{verbatim}
+% ...
+% procedure p1;
+% label
+% l1;
+%
+% procedure p2;
+% begin
+% goto l1; // This goto ISN'T allowed
+% end;
+%
+% begin
+% p2
+% l1:
+% end;
+% ...
+%
+% \end{verbatim}
+parser_f_too_complex_proc=03202_F_Procedure for kompleks, den kræver for mange registre
+% Your procedure body is too long for the compiler. You should split the
+% procedure into multiple smaller procedures.
+parser_e_illegal_expression=03203_E_Ugyldigt udtryk
+% This can occur under many circumstances. Mostly when trying to evaluate
+% constant expressions.
+parser_e_invalid_integer=03204_E_Ugyldigt heltalsudtryk
+% You made an expression which isn't an integer, and the compiler expects the
+% result to be an integer.
+parser_e_invalid_qualifier=03205_E_Ugyldigt udtryk
+% One of the following is happening :
+% \begin{itemize}
+% \item You're trying to access a field of a variable that is not a record.
+% \item You're indexing a variable that is not an array.
+% \item You're dereferencing a variable that is not a pointer.
+% \end{itemize}
+parser_e_upper_lower_than_lower=03206_E_Øvre grænse er mindre end nedre grænse
+% You are declaring a subrange, and the lower limit is higher than the high
+% limit of the range.
+parser_e_macpas_exit_wrong_param=03207_E_Parametren til Exit skal være navnet på den kaldende procedure
+% Non local exit is not allowed. This error occur only in mode MacPas.
+% \end{description}
+#
+# Type Checking
+#
+# 04049 is the last used one
+#
+% \section{Type checking errors}
+% This section lists all errors that can occur when type checking is
+% performed.
+% \begin{description}
+parser_e_illegal_assignment_to_count_var=03208_E_Ugyldig tildeling til for-løkkevariablen "$1"
+% The type of a \var{for} loop variable must be an ordinal type.
+% Loop variables cannot be reals or strings. You can also not assign values to
+% loop variables inside the loop (except in Delphi and TP modes). Use a while or
+% repeat loop instead if you need to do something like that, since those
+% constructs were built for that.
+parser_e_no_local_var_external=03209_E_Kan ikke erklære en lokal variabel som ekstern
+% Declaring local variables as external is not allowed. Only global variables can reference
+% to external variables.
+parser_e_proc_already_external=03210_E_Proceduren er allerede erklæret ekstern
+% The procedure is already declared with the EXTERNAL directive in an interface or
+% forward declaration.
+parser_w_implicit_uses_of_variants_unit=03211_W_Implicit brug af Variants-modulet.
+% The Variant type is used in the unit without any used unit using the Variants unit. The
+% compiler has implicitly added the Variants unit to the uses list. To remove this warning
+% the Variants unit needs to be added to the uses statement.
+parser_e_no_static_method_in_interfaces=03212_E_Klasse- og statiske metoder kan ikke benyttes i interfaces
+% The specifier \var{class} and directive \var{static} can't be used in interfaces
+% because all methods of an interfaces must be public.
+parser_e_arithmetic_operation_overflow=03213_E_Overløb i aritmetisk operation
+% An operation on two integers values produced an overflow
+parser_e_protected_or_private_expected=03214_E_"Protected" eller "private" forventet
+% \var{strict} can be only used together with \var{protected} or \var{private}.
+parser_e_illegal_slice=03215_E_"Slice" kan kun bruges med parameterlister
+% \var{slice} can be used only for arguments accepting an open array parameter
+parser_e_dispinterface_cant_have_parent=03216_E_Et DispInterface kan ikke nedarve fra en anden klasse
+% A DISPINMTERFACE is a special type of interface which can't have a parent class
+parser_e_dispinterface_needs_a_guid=03217_E_Et DispInterface kræver et GUID
+% A DISPINMTERFACE always needs an interface identification
+parser_w_overridden_methods_not_same_ret=03218_W_Metoder med "override" skal have relaterede returtyper. Denne kode kan fejle, da den afhænger af en fejl i Delphis parser ("$2" overrides af "$1", der har en anden returtype)
+% If you declare overridden methods in a class definition, they must
+% have the same return type. Some versions of Delphi allow you to change the
+% return type of interface methods, and even to change procedures into
+% functions, but the resulting code may crash depending on the types used
+% and the way the methods are called.
+% \end{description}
+#
+# Type Checking
+#
+# 04049 is the last used one
+#
+% \section{Type checking errors}
+% This section lists all errors that can occur when type checking is
+% performed.
+% \begin{description}
+type_e_mismatch=04000_E_Typefejl
+% This can happen in many cases:
+% \begin{itemize}
+% \item The variable you're assigning to is of a different type than the
+% expression in the assignment.
+% \item You are calling a function or procedure with parameters that are
+% incompatible with the parameters in the function or procedure definition.
+% \end{itemize}
+type_e_incompatible_types=04001_E_Inkompatible typer: fandt "$1" forventede "$2"
+% There is no conversion possible between the two types
+% Another possiblity is that they are declared in different
+% declarations:
+% \begin{verbatim}
+% Var
+% A1 : Array[1..10] Of Integer;
+% A2 : Array[1..10] Of Integer;
+%
+% Begin
+% A1:=A2; { This statement gives also this error, it
+% is due the strict type checking of pascal }
+% End.
+% \end{verbatim}
+type_e_not_equal_types=04002_E_Typeinkompatabilitet mellem "$1" og "$2"
+% The types are not equal
+type_e_type_id_expected=04003_E_Typenavn forventet
+% The identifier is not a type, or you forgot to supply a type identifier.
+type_e_variable_id_expected=04004_E_Variabelnavn forventet
+% This happens when you pass a constant to a routine (such as \var{Inc} var or \var{Dec})
+% when it expects a variable. You can only pass variables as arguments to these functions.
+type_e_integer_expr_expected=04005_E_Heltalsudtryk forventet, men "$1" fundet
+% The compiler expects an expression of type integer, but gets a different
+% type.
+type_e_boolean_expr_expected=04006_E_Sandhedsudtryk forventet, men "$1" fundet
+% The expression must be a boolean type, it should be return true or
+% false.
+type_e_ordinal_expr_expected=04007_E_Ordinaludtryk forventet
+% The expression must be of ordinal type, i.e., maximum a \var{Longint}.
+% This happens, for instance, when you specify a second argument
+% to \var{Inc} or \var{Dec} that doesn't evaluate to an ordinal value.
+type_e_pointer_type_expected=04008_E_Pointertype forventet, men "$1" fundet
+% The variable or expression isn't of the type \var{pointer}. This
+% happens when you pass a variable that isn't a pointer to \var{New}
+% or \var{Dispose}.
+type_e_class_type_expected=04009_E_Klasse forventet, men "$1" fundet
+% The variable of expression isn't of the type \var{class}. This happens
+% typically when
+% \begin{enumerate}
+% \item The parent class in a class declaration isn't a class.
+% \item An exception handler (\var{On}) contains a type identifier that
+% isn't a class.
+% \end{enumerate}
+type_e_cant_eval_constant_expr=04011_E_Kan ikke evaluere konstantudtryk
+% This error can occur when the bounds of an array you declared does
+% not evaluate to ordinal constants
+type_e_set_element_are_not_comp=04012_E_Setelementer er ikke kompatible
+% You are trying to make an operation on two sets, when the set element types
+% are not the same. The base type of a set must be the same when taking the
+% union
+type_e_set_operation_unknown=04013_E_Operationen er ikke implementeret for set
+% several binary operations are not defined for sets
+% like div mod ** (also >= <= for now)
+type_w_convert_real_2_comp=04014_W_Automatisk typekonversion fra kommatal til COMP, der er en heltalstype
+% An implicit type conversion from a real type to a \var{comp} is
+% encountered. Since \var{comp} is a 64 bit integer type, this may indicate
+% an error.
+type_h_use_div_for_int=04015_H_Brug DIV i stedet, for at få et heltalsresultat
+% When hints are on, then an integer division with the '/' operator will
+% procuce this message, because the result will then be of type real
+type_e_strict_var_string_violation=04016_E_Strengtyper passer ikke sammen, på grund af {$V+}-indstilling
+% When compiling in \var{\{\$V+\}} mode, the string you pass as a parameter
+% should be of the exact same type as the declared parameter of the procedure.
+type_e_succ_and_pred_enums_with_assign_not_possible=04017_E_succ() eller pred() på enumerate-typer med tildelte værdier er ikke gyldigt
+% When you declared an enumeration type which has assignments in it, as in C,
+% like in the following:
+% \begin{verbatim}
+% Tenum = (a,b,e:=5);
+% \end{verbatim}
+% you cannot use the \var{Succ} or \var{Pred} functions on them.
+type_e_cant_read_write_type=04018_E_Kan ikke læse eller skrive variabler af denne type
+% You are trying to \var{read} or \var{write} a variable from or to a
+% file of type text, which doesn't support that. Only integer types,
+% reals, pchars and strings can be read from/written to a text file.
+% Booleans can only be written to text files.
+type_e_no_readln_writeln_for_typed_file=04019_E_Kan ikke bruge readln og writeln på typede filer
+% \var{readln} and \var{writeln} are only allowed for text files.
+type_e_no_read_write_for_untyped_file=04020_E_Kan ikke bruge read eller write på utypede filer
+% \var{read} and \var{write} are only allowed for text or typed files.
+type_e_typeconflict_in_set=04021_E_Typekonflikt mellem setelementer
+% There is at least one set element which is of the wrong type, i.e. not of
+% the set type.
+type_w_maybe_wrong_hi_lo=04022_W_lo/hi(dword/qword) returnerer det øvre word/dword
+% \fpc supports an overloaded version of \var{lo/hi} for \var{longint/dword/int64/qword}
+% which returns the lower/upper word/dword of the argument. TP always uses
+% a 16 bit \var{lo/hi} which returns always bits 0..7 for \var{lo} and the
+% bits 8..15 for \var{hi}. If you want the TP behavior you have
+% to type cast the argument to \var{word/integer}
+type_e_integer_or_real_expr_expected=04023_E_Heltal eller kommatal forventet
+% The first argument to \var{str} must a real or integer type.
+type_e_wrong_type_in_array_constructor=04024_E_Forkert type "$1" i array-constructor
+% You are trying to use a type in an array constructor which is not
+% allowed.
+type_e_wrong_parameter_type=04025_E_Inkompatible typer for $1. parameter: "$2" fundet men "$3" forventet
+% You are trying to pass an invalid type for the specified parameter.
+type_e_no_method_and_procedure_not_compatible=04026_E_Metode (variabel) og Procedure (variabel) er ikke kompatible
+% You can't assign a method to a procedure variable or a procedure to a
+% method pointer.
+type_e_wrong_math_argument=04027_E_Ugyldig konstant givet til intern matematik-funktion
+% The constant argument passed to a ln or sqrt function is out of
+% the definition range of these functions.
+type_e_no_addr_of_constant=04028_E_Kan ikke beregne adressen af konstanter
+% It is not possible to get the address of a constant, because they
+% aren't stored in memory, you can try making it a typed constant.
+type_e_argument_cant_be_assigned=04029_E_Ugyldig tildeling
+% Only expressions which can be on the left side of an
+% assignment can be passed as call by reference argument
+% Remark: Properties can be only
+% used on the left side of an assignment, but they cannot be used as arguments
+type_e_cannot_local_proc_to_procvar=04030_E_Kan ikke tildele lokal procedure/funktion til procedure-variabel
+% It's not allowed to assign a local procedure/function to a
+% procedure variable, because the calling of local procedure/function is
+% different. You can only assign local procedure/function to a void pointer.
+type_e_no_assign_to_addr=04031_E_Kan ikke tildele værdi til en adresse
+% It is not allowed to assign a value to an address of a variable,constant,
+% procedure or function. You can try compiling with -So if the identifier
+% is a procedure variable.
+type_e_no_assign_to_const=04032_E_Kan ikke tildele til konstant-erklæret variabel
+% It's not allowed to assign a value to a variable which is declared
+% as a const. This is normally a parameter declared as const, to allow
+% changing the value make the parameter as a value parameter or a var.
+type_e_array_required=04033_E_Array-type krævet
+% If you are accessing a variable using an index '[<x>]' then
+% the type must be an array. In FPC mode also a pointer is allowed.
+type_e_interface_type_expected=04034_E_interface-type forventet, men "$1" fundet
+type_w_mixed_signed_unsigned=04035_W_Blanding af fortegnsudtryk og fortegnsfri udtryk giver 64-bit resultat
+% If you divide (or calculate the modulus of) a signed expression by a longword (or vice versa),
+% or if you have overflow and/or range checking turned on and use an arithmetic
+% expression (+, -, *, div, mod) in which both signed numbers and longwords appear,
+% then everything has to be evaluated in 64bit which is slower than normal
+% 32bit arithmetic. You can avoid this by typecasting one operand so it
+% matches the resulttype of the other one.
+type_w_mixed_signed_unsigned2=04036_W_Blanding af fortegnsudtryk og fortegnsfri udtryk her kan give værdiområdefejl
+% If you use a binary operator (and, or, xor) and one of
+% the operands is a longword while the other one is a signed expression, then,
+% if range checking is turned on, you may get a range check error because in
+% such a case both operands are converted to longword before the operation is
+% carried out. You can avoid this by typecasting one operand so it
+% matches the resulttype of the other one.
+type_e_typecast_wrong_size_for_assignment=04037_E_Typecast har forskellig størrelse ($1 -> $2) i tildeling
+% Type casting to a type with a different size is not allowed when the variable is
+% used for assigning.
+type_e_array_index_enums_with_assign_not_possible=04038_E_Enumerate-typer med tildelinger kan ikke bruges som index i arrays
+% When you declared an enumeration type which has assignments in it, as in C,
+% like in the following:
+% \begin{verbatim}
+% Tenum = (a,b,e:=5);
+% \end{verbatim}
+% you cannot use it as index of an array.
+type_e_classes_not_related=04039_E_Klasse- eller objekt-typerne "$1" og "$2" er ikke relaterede
+% There is a typecast from one class or object to another while the class/object
+% are not related. This will probably lead to errors
+type_w_classes_not_related=04040_W_Klasse- eller objekt-typerne "$1" og "$2" er ikke relaterede
+% There is a typecast from one class or object to another while the class/object
+% are not related. This will probably lead to errors
+type_e_class_or_interface_type_expected=04041_E_Klasse eller interface-type forventet, men "$1" fundet
+type_e_type_is_not_completly_defined=04042_E_Typen "$1" er ikke fuldt ud defineret
+type_w_string_too_long=04043_W_Strengkonstant har flere karakterer end længden af en kort streng
+% The size of the constant string, which is assigned to a shortstring,
+% is longer than the maximum size of the shortstring
+type_w_signed_unsigned_always_false=04044_W_Sammenligning er altid falsk, grundet værdiernes rækkevidde
+% There is a comparison between an unsigned value and a signed constant which is
+% less than zero. Because of type promotion, the statement will always evaluate to
+% false. Exlicitly typecast the constant to the correct range to avoid this problem.
+type_w_signed_unsigned_always_true=04045_W_Sammenligning er altid sand, grundet værdiernes rækkevidde
+% There is a comparison between an unsigned value and a signed constant which is
+% less than zero. Because of type promotion, the statement will always evaluate to
+% true. Exlicitly typecast the constant to the correct range to avoid this problem.
+type_w_instance_with_abstract=04046_W_Konstruerer klassen "$1" med abstrakte metoder
+% An instance of a class is created which contains non-implemented abstract
+% methods. This will probably lead to a runtime error 211 in the code if that
+% routine is ever called. All abstract methods should be overridden.
+type_h_in_range_check=04047_H_Den venstre operand til IN-operatoren skal være én byte stor
+% The left operand of the \var{in} operator is not an ordinal or enumeration which fits
+% within 8-bits, this may lead to range check errors. The \var{in} operator
+% currently only supports a left operand which fits within a byte. In the case of
+% enumerations, the size of an element of an enumeration can be controlled with
+% the \var{\{\$PACKENUM\}} or \var{\{\$Zn\}} switches.
+type_w_smaller_possible_range_check=04048_W_Forskel i typestørrelser. Muligt datatab eller værdigrænsefejl
+% There is an assignment to a smaller type than the source type. This means that
+% this may cause a range-check error, or may lead to possible loss of data.
+type_h_smaller_possible_range_check=04049_H_Forskel i typestørrelser. Muligt datatab eller værdigrænsefejl
+% There is an assignment to a smaller type than the source type. This means that
+% this may cause a range-check error, or may lead to possible loss of data.
+type_e_cant_take_address_of_abstract_method=04050_E_Kan ikke beregne adressen af en abstrakt metode
+% An abstract method has no body, so the address of an abstract method can't be taken.
+type_e_operator_not_allowed=04051_E_Operatoren kan ikke bruges på denne operand-type
+% You are trying an operator that is not available for the type of the
+% operands
+type_e_constant_expr_expected=04052_E_Konstant udtryk forventet
+% The compiler expects an constant expression, but gets a variable expression.
+type_e_operator_not_supported_for_types=04053_E_Operationen "$1" ikke understøttet for typerne "$2" og "$3"
+% The operation is not allowed for the supplied types
+type_e_illegal_type_conversion=04054_E_Ugyldig typekonvertering: "$1" til "$2"
+% When doing a type-cast, you must take care that the sizes of the variable and
+% the destination type are the same.
+type_h_pointer_to_longint_conv_not_portable=04055_H_Konvertering mellem ordinaltyper og pointere virker ikke på alle platforme
+% If you typecast a pointer to a longint (or vice-versa), this code will not compile
+% on a machine using 64-bit for pointer storage.
+type_w_pointer_to_longint_conv_not_portable=04056_W_Konvertering mellem ordinaltyper og pointere virker ikke på alle platforme
+% If you typecast a pointer to a ordinal type of a different size (or vice-versa), this can
+% cause problems. This is a warning to help finding the 32bit specific code where cardinal/longint is used
+% to typecast pointers to ordinals. A solution is to use the ptrint/ptruint types instead.
+type_e_cant_choose_overload_function=04057_E_Kan ikke bestemme hvilken overloaded funktion der skal kaldes
+% You're calling overloaded functions with a parameter that doesn't correspond
+% to any of the declared function parameter lists. e.g. when you have declared
+% a function with parameters \var{word} and \var{longint}, and then you call
+% it with a parameter which is of type \var{integer}.
+type_e_illegal_count_var=04058_E_Ugyldig tællevariabel
+% The type of a \var{for} loop variable must be an ordinal type.
+% Loop variables cannot be reals or strings.
+% \end{description}
+#
+# Symtable
+#
+# 05055 is the last used one
+#
+% \section{Symbol handling}
+% This section lists all the messages that concern the handling of symbols.
+% This means all things that have to do with procedurek and variable names.
+% \begin{description}
+sym_e_id_not_found=05000_E_Ukendt navn: "$1"
+% The compiler doesn't know this symbol. Usually happens when you misspel
+% the name of a variable or procedure, or when you forgot to declare a
+% variable.
+sym_f_internal_error_in_symtablestack=05001_F_Intern fejl i SymTableStack()
+% An internal error occurred in the compiler; If you encounter such an error,
+% please contact the developers and try to provide an exact description of
+% the circumstances in which the error occurs.
+sym_e_duplicate_id=05002_E_Generklæret navn "$1"
+% The identifier was already declared in the current scope.
+sym_h_duplicate_id_where=05003_H_Navnet er allerede brugt in $1, linie $2
+% The identifier was already declared in a previous scope.
+sym_e_unknown_id=05004_E_Ukendt navn: "$1"
+% The identifier encountered has not been declared, or is used outside the
+% scope where it is defined.
+sym_e_forward_not_resolved=05005_E_Forward-erklæring ikke løst: "$1"
+% This can happen in two cases:
+% \begin{itemize}
+% \item This happens when you declare a function (in the \var{interface} part, or
+% with a \var{forward} directive, but do not implement it.
+% \item You reference a type which isn't declared in the current \var{type}
+% block.
+% \end{itemize}
+sym_e_error_in_type_def=05007_E_Fejl i typeerklæring
+% There is an error in your definition of a new array type:
+% \item One of the range delimiters in an array declaration is erroneous.
+% For example, \var{Array [1..1.25]} will trigger this error.
+sym_e_forward_type_not_resolved=05009_E_Forward-type ikke erklæret: "$1"
+% A symbol was forward defined, but no declaration was encountered.
+sym_e_only_static_in_static=05010_E_Kun statiske variabler kan bruges i statiske metoder, eller uden for metoder
+% A static method of an object can only access static variables.
+sym_f_type_must_be_rec_or_class=05012_F_Struktur- eller klassetype forventet
+% The variable or expression isn't of the type \var{record} or \var{class}.
+sym_e_no_instance_of_abstract_object=05013_E_Instancer af klasser eller objekter med abstrakte metoder er ikke tilladt
+% You are trying to generate an instance of a class which has an abstract
+% method that wasn't overridden.
+sym_w_label_not_defined=05014_W_Label er ikke defineret "$1"
+% A label was declared, but not defined.
+sym_e_label_used_and_not_defined=05015_E_Label brugt men ikke defineret "$1"
+% A label was declared and used, but not defined.
+sym_e_ill_label_decl=05016_E_Ugyldig label-erklæring
+% This error should never happen; it occurs if a label is defined outside a
+% procedure or function.
+sym_e_goto_and_label_not_supported=05017_E_GOTO og LABEL er ikke understøttet (brug -Sg)
+% You must compile a program which has \var{label}s and \var{goto} statements
+% with the \var{-Sg} switch. By default, \var{label} and \var{goto} aren't
+% supported.
+sym_e_label_not_found=05018_E_Label ikke fundet
+% A \var{goto label} was encountered, but the label isn't declared.
+sym_e_id_is_no_label_id=05019_E_Navnet er ikke en label
+% The identifier specified after the \var{goto} isn't of type label.
+sym_e_label_already_defined=05020_E_Label er allerede defineret
+% You are defining a label twice. You can define a label only once.
+sym_e_ill_type_decl_set=05021_E_Ugyldig typeerklæring af setelementer
+% The declaration of a set contains an invalid type definition.
+sym_e_class_forward_not_resolved=05022_E_Forward-erklæring af klassen "$1" ikke løst
+% You declared a class, but you did not implement it.
+sym_n_unit_not_used=05023_H_Unit "$1" ikke brugt i "$2"
+% The unit referenced in the \var{uses} clause is not used.
+sym_h_para_identifier_not_used=05024_H_Parameter "$1" ikke brugt
+% The identifier was declared (locally or globally) but
+% was not used (locally or globally).
+sym_n_local_identifier_not_used=05025_N_Lokal variabel "$1" ikke brugt
+% You have declared, but not used a variable in a procedure or function
+% implementation.
+sym_h_para_identifier_only_set=05026_H_Værdiparameter "$1" er tildelt, men aldrig brugt
+% The identifier was declared (locally or globally)
+% set but not used (locally or globally).
+sym_n_local_identifier_only_set=05027_N_Lokal variabel "$1" er tildelt, men aldrig brugt
+% The variable in a procedure or function
+% implementation is declared, set but never used.
+sym_h_local_symbol_not_used=05028_H_Lokal $1 "$2" aldrig brugt
+% A local symbol is never used.
+sym_n_private_identifier_not_used=05029_N_Private-feltet "$1.$2" aldrig brugt
+sym_n_private_identifier_only_set=05030_N_Private-feltet "$1.$2" tildelt men aldrig brugt
+sym_n_private_method_not_used=05031_N_Private-metoden "$1.$2" aldrig brugt
+sym_e_set_expected=05032_E_Set-type forventet
+% The variable or expression is not of type \var{set}. This happens in an
+% \var{in} statement.
+sym_w_function_result_not_set=05033_W_Funktionsresultat ser ikke ud til at være sat
+% You can get this warning if the compiler thinks that a function return
+% value is not set. This will not be displayed for assembler procedures,
+% or procedures that contain assembler blocks.
+sym_w_wrong_C_pack=05034_W_Typen "$1" er ikke korrekt opstillet i C-struktur
+% Arrays with sizes not multiples of 4 will be wrongly aligned
+% for C structures.
+sym_e_illegal_field=05035_E_Ukendt feltnavn i struktur, "$1"
+% The field doesn't exist in the record/object definition.
+sym_w_uninitialized_local_variable=05036_W_Den lokale variabel "$1" er ikke initialiseret
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_w_uninitialized_variable=05037_W_Variablen "$1" er ikke initialiseret
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_e_id_no_member=05038_E_Strukturen har intet felt ved navn "$1"
+% This error is generated when an identifier of a record,
+% field, or method is accessed while it is not defined.
+sym_h_param_list=05039_H_Fandt erklæring: $1
+% You get this when you use the \var{-vh} switch. In case an overloaded
+% procedure is not found, then all candidate overloaded procedures are
+% listed, with their parameter lists.
+sym_e_segment_too_large=05040_E_Dataelement for stort
+% You get this when you declare a data element whose size exceeds the
+% prescribed limit (2 Gb on 80386+/68020+ processors)
+sym_e_no_matching_implementation_found=05042_E_Ingen passende implementation for interface-metoden "$1" fundet
+% There was no matching method found which could implement the interface
+% method. Check argument types and result type of the methods.
+sym_w_deprecated_symbol=05043_W_Symbolet "$1" er markeret forældet, og bør ikke anvendes
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{deprecated} is used. Deprecated symbols may no longer
+% be available in newer versions of the unit / library. Usage of this symbol
+% should be avoided as much as possible.
+sym_w_non_portable_symbol=05044_W_Symbolet "$1" er ikke portabelt
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{platform} is used. This symbol's value, usage
+% and availability is platform specific and should not be used
+% if the source code must be portable.
+sym_w_non_implemented_symbol=05055_W_Symbolet "$1" er ikke implementeret
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{unimplemented} is used. This symbol is defined,
+% but is not yet implemented on this specific platform.
+sym_e_cant_create_unique_type=05056_E_Kan ikke lave unik type fra denne type
+% Only simple types like ordinal, float and string types are supported when
+% redefining a type with \var{type newtype = type oldtype;}.
+% \end{description}
+#
+# Codegenerator
+#
+# 06040 is the last used one
+#
+% \section{Code generator messages}
+% This section lists all messages that can be displayed if the code
+% generator encounters an error condition.
+% \begin{description}
+sym_h_uninitialized_local_variable=05057_H_Den lokale variabel "$1" er ikke initialiseret
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_h_uninitialized_variable=05058_H_Variablen "$1" er ikke initialiseret
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_w_function_result_uninitialized=05059_W_Funktionsresultatet er ikke initialiseret
+% This message is displayed if the compiler thinks that the function result
+% variable will be used (i.e. appears in the right-hand-side of an expression)
+% before it is initialized (i.e. appeared in the left-hand side of an
+% assigment)
+sym_h_function_result_uninitialized=05060_H_Funktionsresultatet er ikke initialiseret
+% This message is displayed if the compiler thinks that the function result
+% variable will be used (i.e. appears in the right-hand-side of an expression)
+% before it is initialized (i.e. appeared in the left-hand side of an
+% assigment)
+sym_w_identifier_only_read=05061_W_Variablen "$1" bliver læst men aldrig tildelt
+% You have read the value of a variable, but nowhere assigned a value to
+% it.
+
+% \end{description}
+#
+# Codegenerator
+#
+# 06040 is the last used one
+#
+% \section{Code generator messages}
+% This section lists all messages that can be displayed if the code
+% generator encounters an error condition.
+% \begin{description}
+cg_e_parasize_too_big=06009_E_Den samlede parameterstørrelse overstiger 64KB
+% The I386 processor limits the parameter list to 65535 bytes (the \var{RET}
+% instruction causes this)
+cg_e_file_must_call_by_reference=06012_E_File-typer skal være var-parametre
+% You cannot specify files as value parameters, i.e. they must always be
+% declared \var{var} parameters.
+cg_e_cant_use_far_pointer_there=06013_E_Brugen af FAR-pointere er ikke tilladt her
+% Free Pascal doesn't support far pointers, so you cannot take the address of
+% an expression which has a far reference as a result. The \var{mem} construct
+% has a far reference as a result, so the following code will produce this
+% error:
+% \begin{verbatim}
+% var p : pointer;
+% ...
+% p:=@mem[a000:000];
+% \end{verbatim}
+cg_e_dont_call_exported_direct=06015_E_EXPORT-erklæringer kan ikke kaldes
+% No longer in use.
+cg_w_member_cd_call_from_method=06016_W_Mulig ugyldigt kald af constructor eller destructor
+% The compiler detected that a constructor or destructor is called within a
+% a method. This will probably lead to problems, since constructors / destructors
+% require parameters on entry.
+cg_n_inefficient_code=06017_N_Utilstrækkelig kode
+% Your statement seems dubious to the compiler.
+cg_w_unreachable_code=06018_W_Koden vil aldrig blive kørt
+% You specified a construct which will never be executed. Example:
+% \begin{verbatim}
+% while false do
+% begin
+% {.. code ...}
+% end;
+% \end{verbatim}
+cg_e_cant_call_abstract_method=06020_E_Abstrakte metoder kan ikke kaldes direkte
+% You cannot call an abstract method directy, instead you must call a
+% overriding child method, because an abstract method isn't implemented.
+cg_d_register_weight=06027_DL_Register $1 vægt $2 $3
+% Debugging message. Shown when the compiler considers a variable for
+% keeping in the registers.
+cg_d_stackframe_omited=06029_DL_Stakramme er udeladt
+% Some procedure/functions do not need a complete stack-frame, so it is omitted.
+% This message will be displayed when the {-vd} switch is used.
+cg_e_unable_inline_object_methods=06031_E_Objekt eller klassemetode kan ikke være inline
+% You cannot have inlined object methods.
+cg_e_unable_inline_procvar=06032_E_Procvar kald kan ikke være inline
+% A procedure with a procedural variable call cannot be inlined.
+cg_e_no_code_for_inline_stored=06033_E_Koden til inline-procedure ikke gemt
+% The compiler couldn't store code for the inline procedure.
+cg_e_can_access_element_zero=06035_E_Element nul af en ansi/wide/lang-strengtype kan ikke tilgås. Brug i stedet (set)length
+% You should use \var{setlength} to set the length of an ansi/wide/longstring
+% and \var{length} to get the length of such a string types
+cg_e_cannot_call_cons_dest_inside_with=06037_E_En constructor eller destructor kan ikke kaldes i en "with"-erklæring
+% Inside a \var{with} clause you cannot call a constructor or destructor for the
+% object you have in the \var{with} clause.
+cg_e_cannot_call_message_direct=06038_E_Kan ikke kalde beskedhåndteringsprocedure direkte
+% A message method handler method cannot be called directly if it contains an
+% explicit self argument
+cg_e_goto_inout_of_exception_block=06039_E_Jump ind eller ud af en untagelsesblok
+% It is not allowed to jump in or outside of an exception block like \var{try..finally..end;}:
+% \begin{verbatim}
+% label 1;
+%
+% ...
+%
+% try
+% if not(final) then
+% goto 1; // this line will cause an error
+% finally
+% ...
+% end;
+% 1:
+% ...
+% \end{verbatim}
+cg_e_control_flow_outside_finally=06040_E_Forløbs-ændrende erklæringer er ikke tilladt i en finally-blok
+% It isn't allowed to use the control flow statements \var{break},
+% \var{continue} and \var{exit}
+% inside a finally statement. The following example shows the problem:
+% \begin{verbatim}
+% ...
+% try
+% p;
+% finally
+% ...
+% exit; // This exit ISN'T allowed
+% end;
+% ...
+%
+% \end{verbatim}
+% If the procedure \var{p} raises an exception the finally block is
+% executed. If the execution reaches the exit, it's unclear what to do:
+% exiting the procedure or searching for another exception handler
+% \end{description}
+cg_w_parasize_too_big=06041_W_Parameterstørrelsen overstiger grænsen for visse CPUer
+% This indicates that you are declaring more than 64K of parameters, which
+% might not be supported on other processor targets.
+cg_w_localsize_too_big=06042_W_Størrelsen af lokale variabler overstiger grænsen for visse CPUer
+% This indicates that you are declaring more than 32K of lcoal variables, which
+% might not be supported on other processor targets.
+cg_e_localsize_too_big=06043_E_Størrelsen af lokale variabler overstiger understøttet størrelse
+% This indicates that you are declaring more than 32K of lcoal variables, which
+% is not supported by this processor.
+cg_e_break_not_allowed=06044_E_BREAK ikke tilladt uden for løkke-erklæringer
+% You're trying to use \var{break} outside a loop construction.
+cg_e_continue_not_allowed=06045_E_CONTINUE ikke tilladt uden for løkke-erklæringer
+% You're trying to use \var{continue} outside a loop construction.
+# EndOfTeX
+
+#
+# Assembler reader
+#
+# 07097 is the last used one
+#
+cg_f_unknown_compilerproc=06046_F_Ukendt compilerfunktion "$1". Undersøg om du bruger det korrekt køretidsbibliotek.
+% The compiler expects that the runtime library contains some subrountines. If you see this error
+% and you didn't mess with the runtime library, it's very likely that the runtime library
+% you're using doesn't match the used compiler. If you changed the runtime library this error means
+% that you removed a subroutine which the compiler needs for internal use.
+% \end{description}
+# EndOfTeX
+
+#
+# Assembler reader
+#
+# 07097 is the last used one
+#
+asmr_d_start_reading=07000_DL_Begynder assembler-parsing ($1)
+% This informs you that an assembler block is being parsed
+asmr_d_finish_reading=07001_DL_Afslutter assembler-parsing ($1)
+% This informs you that an assembler block has finished.
+asmr_e_none_label_contain_at=07002_E_Ikke-label navn indeholder @
+% A identifier which isn't a label can't contain a @.
+asmr_e_building_record_offset=07004_E_Fejl under opbygning af struktur-offset
+% There has an error occured while building the offset of a record/object
+% structure, this can happend when there is no field specified at all or
+% an unknown field identifier is used.
+asmr_e_offset_without_identifier=07005_E_OFFSET brugt uden navn
+% You can only use OFFSET with an identifier. Other syntaxes aren't
+% supported
+asmr_e_type_without_identifier=07006_E_TYPE brugt uden navn
+% You can only use TYPE with an identifier. Other syntaxes aren't
+% supported
+asmr_e_no_local_or_para_allowed=07007_E_Kan ikke bruge lokale variabler eller parametre her
+% You can't use a local variable or parameter here, mostly because the
+% addressing of locals and parameters is done using the frame pointer register so the
+% address can't be obtained directly.
+asmr_e_need_offset=07008_E_Nødvendigt at bruge OFFSET her
+% You need to use OFFSET <id> here to get the address of the identifier.
+asmr_e_need_dollar=07009_E_Nødvendigt at bruge $ her
+% You need to use $<id> here to get the address of the identifier.
+asmr_e_cant_have_multiple_relocatable_symbols=07010_E_Kan ikke bruge flere samtidige relokérbare symboler
+% You can't have more than one relocatable symbol (variable/typed constant)
+% in one argument.
+asmr_e_only_add_relocatable_symbol=07011_E_Relokérbare symboler kan kun adderes
+% Relocatable symbols (variable/typed constant) can't be used with other
+% operators. Only addition is allowed.
+asmr_e_invalid_constant_expression=07012_E_Ugyldigt konstantudtryk
+% There is an error in the constant expression.
+asmr_e_relocatable_symbol_not_allowed=07013_E_Relokérbart symbol ikke tilladt her
+% You can't use a relocatable symbol (variable/typed constant) here.
+asmr_e_invalid_reference_syntax=07014_E_Ugyldig referencesyntax
+% There is an error in the reference.
+asmr_e_local_para_unreachable=07015_E_Kan ikke tilgå $1 fra denne position
+% You can not read directly the value of local or para
+% of a higher level in assembler code (except for
+% local assembler code without parameter nor locals).
+asmr_e_local_label_not_allowed_as_ref=07016_E_Lokale symboler/labels er ikke gyldige referencer
+% You can't use local symbols/labels as references
+asmr_e_wrong_base_index=07017_E_Ugyldigt base- eller indexregister
+% There is an error with the base and index register, they are
+% probably incorrect
+asmr_w_possible_object_field_bug=07018_W_Mulig fejl i objektfelthåndtering
+% Fields of objects or classes can be reached directly in normal or objfpc
+% modes but TP and Delphi modes treat the field name as a simple offset.
+asmr_e_wrong_scale_factor=07019_E_Forkert skaleringsfaktor angivet
+% The scale factor given is wrong, only 1,2,4 and 8 are allowed
+asmr_e_multiple_index=07020_E_Mere end ét indexregister angivet
+% You are trying to use more than one index register
+asmr_e_invalid_operand_type=07021_E_Ugyldig operandtype
+% The operand type doesn't match with the opcode used
+asmr_e_invalid_string_as_opcode_operand=07022_E_Ugyldig streng som operand: $1
+% The string specified as operand is not correct with this opcode
+asmr_w_CODE_and_DATA_not_supported=07023_W_@CODE og @DATA ikke understøttet
+% @CODE and @DATA are unsupported and are ignored.
+asmr_e_null_label_ref_not_allowed=07024_E_Tomme labelreferencer er ikke tilladt
+asmr_e_expr_zero_divide=07025_E_Division med nul i assembler-evaluatoren
+% There is a division by zero in a constant expression
+asmr_e_expr_illegal=07026_E_Ugyldigt konstantudtryk
+% There is an illegal expression in a constant expression
+asmr_e_escape_seq_ignored=07027_E_Escape-sekvens ignoreret: $1
+% There is a C-styled string, but the escape sequence in the string
+% is unknown, and is therefore ignored
+asmr_e_invalid_symbol_ref=07028_E_Ugyldig symbolreference
+asmr_w_fwait_emu_prob=07029_W_FWAIT kan føre til emulationsproblemer med emu387
+asmr_w_fadd_to_faddp=07030_W_$1 uden operand oversat til $1P
+asmr_w_enter_not_supported_by_linux=07031_W_ENTER-instruktionen er ikke understøttet af Linux-kernen
+% ENTER instruction can generate a stack page fault that is not
+% caught correctly by the i386 Linux page handler.
+asmr_w_calling_overload_func=07032_W_Kald til overloaded funktion i assembler
+% There is a call to an overloaded method in the assembler block,
+% this might be the sign there is a problem
+asmr_e_unsupported_symbol_type=07033_E_Operandens symboltype er ikke understøttet
+asmr_e_constant_out_of_bounds=07034_E_Konstantværdi overskrider værdigrænse
+asmr_e_error_converting_decimal=07035_E_Fejl under konvertering af decimal $1
+% A constant decimal value does not have the correct syntax
+asmr_e_error_converting_octal=07036_E_Fejl under konvertering af octal $1
+% A constant octal value does not have the correct syntax
+asmr_e_error_converting_binary=07037_E_Fejl under konvertering af binær $1
+% A constant binary value does not have the correct syntax
+asmr_e_error_converting_hexadecimal=07038_E_Fejl under konvertering af hexadecimal $1
+% A constant hexadecimal value does not have the correct syntax
+asmr_h_direct_global_to_mangled=07039_H_$1 oversat til $2
+asmr_w_direct_global_is_overloaded_func=07040_W_$1 er associeret med en overloadet funktion
+asmr_e_cannot_use_SELF_outside_a_method=07041_E_Kan ikke tilgå SELF uden for en metode
+% There is a reference to the \var{self} symbol while it is not
+% allowed. \var{self} can only be referenced inside methods
+asmr_e_cannot_use_OLDEBP_outside_nested_procedure=07042_E_Kan ikke tilgå OLDEBP uden for en indlejret procedure
+% There is a reference to the \var{oldebp} symbol while it is not
+% allowed. \var{oldebp} can only be referenced inside nested routines
+asmr_e_void_function=07043_W_En procedure kan ikke returnere en værdi i assembler-kode
+% Trying to return a value while in a procedure. A procedure
+% does not have any return value
+asmr_e_SEG_not_supported=07044_E_SEG er ikke understøttet
+asmr_e_size_suffix_and_dest_dont_match=07045_E_Størrelses-suffix og destination- eller kildestørrelse stemmer ikke overens
+% The register size and the opcode size suffix don't match. This is
+% probably an error in the assembler statement
+asmr_w_size_suffix_and_dest_dont_match=07046_W_Størrelses-suffix og destination- eller kildestørrelse stemmer ikke overens
+% The register size and the opcode size suffix don't match. This is
+% probably an error in the assembler statement
+asmr_e_syntax_error=07047_E_Syntaxfejl i assemblerkode
+% There is an assembler syntax error
+asmr_e_invalid_opcode_and_operand=07048_E_Ugyldig kombination af operationskode og operand
+% The opcode cannot be used with this type of operand
+asmr_e_syn_operand=07049_E_Syntaxfejl i assembleroperand
+asmr_e_syn_constant=07050_E_Syntaxfejl i assemblerkonstant
+asmr_e_invalid_string_expression=07051_E_Ugyldigt strengudtryk
+asmr_w_const32bit_for_address=07052_W_adressekonstanten $1 er ikke en gyldig pointer
+% A constant expression represents an address which does not fit
+% into a pointer. The address is probably incorrect
+asmr_e_unknown_opcode=07053_E_Ukendt operationskode $1
+% This opcode is not known
+asmr_e_invalid_or_missing_opcode=07054_E_Ugyldig eller manglende operationskode
+asmr_e_invalid_prefix_and_opcode=07055_E_Ugyldig kombination af prefix og operationskode: $1
+asmr_e_invalid_override_and_opcode=07056_E_Ugyldig kombination af override og operationskode: $1
+asmr_e_too_many_operands=07057_E_For mange operander på linien
+% There are too many operands for this opcode. Check your
+% assembler syntax
+asmr_w_near_ignored=07058_W_NEAR ignoreret
+asmr_w_far_ignored=07059_W_FAR ignoreret
+asmr_e_dup_local_sym=07060_E_Gentaget lokalt symbol $1
+asmr_e_unknown_local_sym=07061_E_Ukendt lokalt symbol $1
+asmr_e_unknown_label_identifier=07062_E_Unknown labelnavn $1
+asmr_e_invalid_register=07063_E_Ugyldigt registernavn
+% There is an unknown register name used as operand.
+asmr_e_invalid_fpu_register=07064_E_Ugyldigt kommatalsregister-navn
+% There is an unknown register name used as operand.
+asmr_w_modulo_not_supported=07066_W_Modulo ikke understøttet
+asmr_e_invalid_float_const=07067_E_Ugyldig kommatalskonstant $1
+% The floating point constant declared in an assembler block is
+% invalid.
+asmr_e_invalid_float_expr=07068_E_Ugyldig kommatalsudtryk
+% The floating point expression declared in an assembler block is
+% invalid.
+asmr_e_wrong_sym_type=07069_E_Forkert symboltype
+asmr_e_cannot_index_relative_var=07070_E_Kan ikke indexere en lokal variabel eller parameter med et register
+% Trying to index using a base register a symbol which is already relative
+% to a register. This is not possible, and will probably lead to crashes.
+asmr_e_invalid_seg_override=07071_E_Ugyldigt segment-override-udtryk
+asmr_w_id_supposed_external=07072_W_Navnet $1 antages at være eksternt
+% There is a reference to an undefined symbol. This will not result
+% in an error, since the symbol might be external, but may cause
+% problems at link time if the symbol is not defined anywhere.
+asmr_e_string_not_allowed_as_const=07073_E_Strenge er ikke tilladte som konstanter
+% Character strings are not allowed as constants.
+asmr_e_no_var_type_specified=07074_Ingen variabeltype specificeret
+% The syntax expects a type idenfitifer after the dot, but
+% none was found.
+asmr_w_assembler_code_not_returned_to_text=07075_E_Assemblerkode returnerer ikke til tekst-sektionen
+% There was a directive in the assembler block to change sections,
+% but there is a missing return to the text section at the end
+% of the assembler block. This might cause errors during link time.
+asmr_e_not_directive_or_local_symbol=07076_E_Ikke et direktiv eller lokalt symbol $1
+% This symbol is unknown.
+asmr_w_using_defined_as_local=07077_E_Brug af defineret navn som lokal label
+asmr_e_dollar_without_identifier=07078_E_Dollar-token brugt uden navn
+% A constant expression has an identifier which does not start with
+% the $ symbol.
+asmr_w_32bit_const_for_address=07079_W_32-bit konstant brugt som adresse
+% A constant was used as an address. This is probably an error,
+% since using absolute addresses will probably not work.
+asmr_n_align_is_target_specific=07080_N_.align er mål-specifikt. Brug .balign eller .p2align
+% Using the .align directive is platform specific, and its meaning will vary
+% from one platform to another.
+asmr_e_cannot_access_field_directly_for_parameters=07081_E_Kan ikke tilgå felter fra parametre direkte
+% You should load the parameter first into a register and then access the
+% fields using that register.
+asmr_e_cannot_access_object_field_directly=07082_E_Kan ikke tilgå felter fra objekter/klasser direkte
+% You should load the self pointer first into a register and then access the
+% fields using the register as base. By default the self pointer is available
+% in the esi register on i386.
+asmr_e_unable_to_determine_reference_size=07083_E_Ingen størrelse angivet, og det var ikke muligt at fastslå størrelsen af operanderne
+% You should specify explicitly a size for the reference, because
+% the compiler is unable to determine what size (byte,word,dword,etc.) it
+% should use for the reference.
+asmr_e_cannot_use_RESULT_here=07084_E_Kan ikke bruge RESULT i denne funktion
+% Some functions which return complex types cannot use the \var{result}
+% keyword.
+asmr_w_adding_explicit_args_fXX=07086_W_"$1" uden operand oversat til "$1 %st,%st(1)"
+asmr_w_adding_explicit_first_arg_fXX=07087_W_"$1 %st(n)" oversat til "$1 %st,%st(n)"
+asmr_w_adding_explicit_second_arg_fXX=07088_W_"$1 %st(n)" oversat til "$1 %st(n),%st"
+asmr_e_invalid_char_smaller=07089_E_Karakter "<" ikke tilladt her (brug "<<" for logisk skift)
+% The shift operator requires the << characters. Only one
+% of those characters was found.
+asmr_e_invalid_char_greater=07090_E_Karakter ">" ikke tilladt her (brug ">>" for logisk skift)
+% The shift operator requires the >> characters. Only one
+% of those characters was found.
+asmr_w_align_not_supported=07093_W_ALIGN ikke understøttet
+asmr_e_no_inc_and_dec_together=07094_E_Inc og Dec kan ikke bruges sammen
+% Trying to use an increment and a decrement within the same
+% opcode on the 680x0. This is impossible.
+asmr_e_invalid_reg_list_in_movem=07095_E_Ugyldig registerliste til movem
+% Trying to use the \var{movem} opcode with invalid registers
+% to save or restore.
+asmr_e_invalid_reg_list_for_opcode=07096_E_Registerliste ikke gyldig for denne operationskode
+asmr_e_higher_cpu_mode_required=07097_E_Højere cpu-mode krævet ($1)
+% Trying to use an instruction which is not supported in the current
+% cpu mode. Use a higher cpu generation to be able to use this
+% opcode in your assembler block
+asmr_w_unable_to_determine_reference_size_using_dword=07098_W_Ingen størrelse angivet, og det var ikke muligt at fastslå størrelsen af operanderne. Bruger DWORD.
+% You should specify explicitly a size for the reference, because
+% the compiler is unable to determine what size (byte,word,dword,etc.) it
+% should use for the reference. This warning is only used in Delphi mode where
+% it falls back to use DWORD as default.
+#
+# Assembler/binary writers
+#
+# 08018 is the last used one
+#
+asmr_e_illegal_shifterop_syntax=07099_E_Syntaxfejl under parsning af skifteroperand
+% ARM only; ARM assembler supports a so called shifter operand. The used syntax isn't
+% a valid shifter operand. Example for an operation with shifter operand:
+% \begin{verbatim}
+% asm
+% orr r2,r2,r2,lsl #8
+% end;
+% \end{verbatim}
+#
+# Assembler/binary writers
+#
+# 08018 is the last used one
+#
+asmw_f_too_many_asm_files=08000_F_For mange assemblerfiler (forsøg uden smartlinking)
+% With smartlinking enabled, there are too many assembler
+% files generated. Disable smartlinking.
+asmw_f_assembler_output_not_supported=08001_F_Den valgte assemblerform understøttes ikke
+asmw_f_comp_not_supported=08002_F_Typen "Comp" er ikke understøttet
+asmw_f_direct_not_supported=08003_F_Direkte assembler-tilstand ikke understøttet for indbyggede filskrivere
+% Direct assembler mode is not supported for binary writers.
+asmw_e_alloc_data_only_in_bss=08004_E_Allokering af data kun tilladt i bss-sektionen
+asmw_f_no_binary_writer_selected=08005_F_Ingen binær filskriver valgt
+asmw_e_opcode_not_in_table=08006_E_Asm: Operationskode $1 ikke fundet i tabellen
+asmw_e_invalid_opcode_and_operands=08007_E_Asm: $1 ugyldig kombination af register og operationskode
+asmw_e_16bit_not_supported=08008_E_Asm: 16-bit referencer ikke understøttet
+asmw_e_invalid_effective_address=08009_E_Asm: Ugyldig effektiv adressering
+asmw_e_immediate_or_reference_expected=08010_E_Asm: Konstant eller reference forventet
+asmw_e_value_exceeds_bounds=08011_E_Asm: $1 værdi overstiger grænse $2
+asmw_e_short_jmp_out_of_range=08012_E_Asm: Kort hop er uden for rækkevidde $1
+asmw_e_undefined_label=08013_E_Asm: Ukendt labelnavn $1
+asmw_e_comp_not_supported=08014_E_Asm: Typen "Comp" er ikke understøttet på dette målsystem
+asmw_e_extended_not_supported=08015_E_Asm: Typen "Extended" er ikke understøttet på dette målsystem
+asmw_e_duplicate_label=08016_E_Asm: Genbrugt labelnavn $1
+asmw_e_redefined_label=08017_E_Asm: Redefineret labelnavn $1
+asmw_e_first_defined_label=08018_E_Asm: Først defineret her
+asmw_e_invalid_register=08019_E_Asm: Ugyldigt register $1
+
+#
+# Executing linker/assembler
+#
+# 09034 is the last used one
+#
+# BeginOfTeX
+%
+% \section{Errors of assembling/linking stage}
+% This section lists errors that occur when the compiler is processing the
+% command line or handling the configuration files.
+% \begin{description}
+exec_w_source_os_redefined=09000_W_Kilde-operativsystem redefineret
+exec_i_assembling_pipe=09001_I_Assembler (pipe) $1
+exec_d_cant_create_asmfile=09002_E_Kan ikke oprette assemblerfil: $1
+% The mentioned file can't be created. Check if you have got
+% access permissions to create this file
+exec_e_cant_create_objectfile=09003_E_Kan ikke oprette objektfil: $1
+% The mentioned file can't be created. Check if you've
+% got access permissions to create this file
+exec_e_cant_create_archivefile=09004_E_Kan ikke oprette arkivfil: $1
+% The mentioned file can't be created. Check if you've
+% access permissions to create this file
+exec_e_assembler_not_found=09005_E_Assembler $1 ikke fundet, skifter til ekstern assembler
+exec_t_using_assembler=09006_T_Bruger assembler: $1
+exec_e_error_while_assembling=09007_E_Fejl under assembling (returkode $1)
+% There was an error while assembling the file using an external assembler.
+% Consult the documentation of the assembler tool to find out more information
+% on this error.
+exec_e_cant_call_assembler=09008_E_Kan ikke kalde assembleren, fejl $1 under skift til ekstern assembler
+exec_i_assembling=09009_I_Assembler $1
+exec_i_assembling_smart=09010_I_Assembler med smartlinking $1
+exec_w_objfile_not_found=09011_W_Objektet $1 ikke fundet - linkningen kan fejle!
+% One of the object file is missing, and linking will probably fail.
+% Check your paths.
+exec_w_libfile_not_found=09012_W_Biblioteket $1 blev ikke fundet - linkningen kan fejle!
+% One of the library file is missing, and linking will probably fail.
+% Check your paths.
+exec_e_error_while_linking=09013_E_Fejl under linkning
+% Generic error while linking.
+exec_e_cant_call_linker=09014_E_Kan ikke starte linkeren, skifter til ekstern linker
+exec_i_linking=09015_I_Linker $1
+exec_e_util_not_found=09016_E_Hjælpeprogram $1 ikke fundet, skifter til ekstern linker
+exec_t_using_util=09017_T_Bruger hjælpeprogram $1
+exec_e_exe_not_supported=09018_E_Programbygning ikke understøttet
+exec_e_dll_not_supported=09019_E_Dynamisk/Delt bibliotek-bygning ikke understøttet
+exec_i_closing_script=09020_I_Lukker script $1
+exec_e_res_not_found=09021_E_resourcecompiler ikke fundet, skifter til ekstern
+exec_i_compilingresource=09022_I_Compilerer resourcen $1
+exec_t_unit_not_static_linkable_switch_to_smart=09023_T_unit $1 kan ikke linkes statisk. Skifter til smartlinking
+exec_t_unit_not_smart_linkable_switch_to_static=09024_T_unit $1 kan ikke smartlinkes. Skifter til statisk linking
+exec_t_unit_not_shared_linkable_switch_to_static=09025_T_unit $1 kan ikke linkes delt, skifter til statisk linking
+exec_e_unit_not_smart_or_static_linkable=09026_E_unit $1 kan ikke linkes smart eller statisk
+exec_e_unit_not_shared_or_static_linkable=09027_E_unit $1 kan ikke linkes delt eller statisk
+%\end{description}
+# EndOfTeX
+
+#
+# Executable information
+#
+exec_d_resbin_params=09028_D_Kalder resourcecompiler "$1" med "$2" som kommandolinie
+%\end{description}
+# EndOfTeX
+
+#
+# Executable information
+#
+execinfo_f_cant_process_executable=09128_F_Can't post process executable $1
+execinfo_f_cant_open_executable=09129_F_Kan ikke åbne programmet $1
+execinfo_x_codesize=09130_X_Størrelsen af koden: $1 bytes
+execinfo_x_initdatasize=09131_X_Størrelse af initialiseret data: $1 bytes
+execinfo_x_uninitdatasize=09132_X_Størrelse af uinitialiseret data: $1 bytes
+execinfo_x_stackreserve=09133_X_Reserveret stakstørrelse: $1 bytes
+execinfo_x_stackcommit=09134_X_Brugt stakstørrelse: $1 bytes
+
+#
+# Unit loading
+#
+# 10041 is the last used one
+#
+# BeginOfTeX
+% \section{Unit loading messages.}
+% This section lists all messages that can occur when the compiler is
+% loading a unit from disk into memory. Many of these messages are
+% informational messages.
+% \begin{description}
+unit_t_unitsearch=10000_T_Leder efter unit: $1
+% When you use the \var{-vt}, the compiler tells you where it tries to find
+% unit files.
+unit_t_ppu_loading=10001_T_Indlæser PPU $1
+% When the \var{-vt} switch is used, the compiler tells you
+% what units it loads.
+unit_u_ppu_name=10002_U_PPU Navn: $1
+% When you use the \var{-vu} flag, the unit name is shown.
+unit_u_ppu_flags=10003_U_PPU Flag: $1
+% When you use the \var{-vu} flag, the unit flags are shown.
+unit_u_ppu_crc=10004_U_PPU CRC: $1
+% When you use the \var{-vu} flag, the unit CRC check is shown.
+unit_u_ppu_time=10005_U_PPU Tid: $1
+% When you use the \var{-vu} flag, the time the unit was compiled is shown.
+unit_u_ppu_file_too_short=10006_U_PPU-filen er for kort
+% The ppufile is too short, not all declarations are present.
+unit_u_ppu_invalid_header=10007_U_PPU-filen har ugyldigt startinformation (ingen PPU i begyndelsen af filen)
+% A unit file contains as the first three bytes the ascii codes of \var{PPU}
+unit_u_ppu_invalid_version=10008_U_PPU ugyldig version $1
+% This unit file was compiled with a different version of the compiler, and
+% cannot be read.
+unit_u_ppu_invalid_processor=10009_U_PPU er kompileret til en anden processor
+% This unit file was compiled for a different processor type, and
+% cannot be read
+unit_u_ppu_invalid_target=10010_U_PPU er kompileret til et andet mål
+% This unit file was compiled for a different target, and
+% cannot be read
+unit_u_ppu_source=10011_U_PPU Kilde: $1
+% When you use the \var{-vu} flag, the unit CRC check is shown.
+unit_u_ppu_write=10012_U_Skriver $1
+% When you specify the \var{-vu} switch, the compiler will tell you where it
+% writes the unit file.
+unit_f_ppu_cannot_write=10013_F_Kan ikke skrive PPU-fil
+% An error occurred when writing the unit file.
+unit_f_ppu_read_error=10014_F_Fejl under læsning af PPU-fil
+% This means that the unit file was corrupted, and contains invalid
+% information. Recompilation will be necessary.
+unit_f_ppu_read_unexpected_end=10015_F_PPU-filen sluttede uventet
+% Unexpected end of file. This may mean that the PPU file is
+% corrupted.
+unit_f_ppu_invalid_entry=10016_F_Ugyldigt element $1 i PPU-fil
+% The unit the compiler is trying to read is corrupted, or generated with a
+% newer version of the compiler.
+unit_f_ppu_dbx_count_problem=10017_F_Problem med størrelsen af Dbx i PPU-filen
+% There is an inconsistency in the debugging information of the unit.
+unit_e_illegal_unit_name=10018_E_Ugyldigt unitnavn: $1
+% The name of the unit does not match the file name.
+unit_f_too_much_units=10019_F_For mange units
+% \fpc has a limit of 1024 units in a program. You can change this behavior
+% by changing the \var{maxunits} constant in the \file{fmodule.pas} file of the
+% compiler, and recompiling the compiler.
+unit_f_circular_unit_reference=10020_F_Cirkulær unit-reference mellem $1 og $2
+% Two units are using each other in the interface part. This is only allowed
+% in the \var{implementation} part. At least one unit must contain the other one
+% in the \var{implementation} section.
+unit_f_cant_compile_unit=10021_F_Kan ikke gencompilere $1, ingen kildekode tilgængelig
+% A unit was found that needs to be recompiled, but no sources are
+% available.
+unit_f_cant_find_ppu=10022_F_Kan ikke finde unit'en $1
+% You tried to use a unit of which the PPU file isn't found by the
+% compiler. Check your configuration file for the unit paths
+unit_w_unit_name_error=10023_W_Unit $1 blev ikke fundet, men $2 findes
+unit_f_unit_name_error=10024_F_Unit $1 blev eftersøgt, men $2 fundet
+% Dos truncation of 8 letters for unit PPU files
+% may lead to problems when unit name is longer than 8 letters.
+unit_w_switch_us_missed=10025_W_Compilering af systemunit'en kræver -Us indstillingen
+% When recompiling the system unit (it needs special treatment), the
+% \var{-Us} must be specified.
+unit_f_errors_in_unit=10026_F_Der var $1 fejl under compileringen af modulet, stopper
+% When the compiler encounters a fatal error or too many errors in a module
+% then it stops with this message.
+unit_u_load_unit=10027_U_Indlæser fra $1 ($2) unit $3
+% When you use the \var{-vu} flag, which unit is loaded from which unit is
+% shown.
+unit_u_recompile_crc_change=10028_U_Gencompilerer $1, checksum ændret for $2
+unit_u_recompile_source_found_alone=10029_U_Gencompilerer $1, kun kilden fundet
+% When you use the \var{-vu} flag, these messages tell you why the current
+% unit is recompiled.
+unit_u_recompile_staticlib_is_older=10030_U_Gencompilerer unit, statisk bibliotek er ældre end PPU-fil
+% When you use the \var{-vu} flag, the compiler warns if the static library
+% of the unit are older than the unit file itself.
+unit_u_recompile_sharedlib_is_older=10031_U_Gencompilerer unit, delt bibliotek er ældre end PPU-fil
+% When you use the \var{-vu} flag, the compiler warns if the shared library
+% of the unit are older than the unit file itself.
+unit_u_recompile_obj_and_asm_older=10032_U_Gencompilerer unit, objekt- og assemblerfil er ældre end PPU-fil
+% When you use the \var{-vu} flag, the compiler warns if the assembler or
+% object file of the unit are older than the unit file itself.
+unit_u_recompile_obj_older_than_asm=10033_U_Gencompilerer unit, objekt-filen er ældre end assemblerfilen
+% When you use the \var{-vu} flag, the compiler warns if the assembler
+% file of the unit is older than the object file of the unit.
+unit_u_parsing_interface=10034_U_Parser interfacet af $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% parsing the interface part of the unit
+unit_u_parsing_implementation=10035_U_Parser implementationen af $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% parsing the implementation part of the unit
+unit_u_second_load_unit=10036_U_Anden indlæsning for unit $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% recompiling a unit for the second time. This can happend with interdepend
+% units.
+unit_u_check_time=10037_U_PPU Check filen $1 tid $2
+% When you use the \var{-vu} flag, the compiler show the filename and
+% date and time of the file which a recompile depends on
+unit_w_cant_compile_unit_with_changed_incfile=10040_W_Kan ikke gencompilere unit $1, men der blev fundet ændrede includefiler
+% A unit was found to have modified include files, but
+% some source files were not found, so recompilation is impossible.
+unit_h_source_modified=10041_H_Filen $1 er nyere end PPU-filen $2 (Release-udgave)
+% A modified source file for a unit was found that was compiled with the
+% release flag (-Ur). The unit will not implicitly be recompiled because
+% this release flag is set.
+unit_u_ppu_invalid_fpumode=10042_U_Bruger en unit der der ikke er compileret i den korrekte FPU-mode
+% Trying to compile code while using units which were not compiled with
+% the same floating point format mode. Either all code should be compiled
+% with FPU emulation on, or with FPU emulation off.
+unit_u_loading_interface_units=10043_U_Indlæser interface-units fra $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% loading the units defined in the interface part of the unit.
+unit_u_loading_implementation_units=10044_U_Indlæser implementation-units fra $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% loading the units defined in the implementation part of the unit.
+unit_u_interface_crc_changed=10045_U_Interface-CRC ændret for unit $1
+% When you use the \var{-vu} flag, the compiler warns that it the
+% CRC calculated for the interface has been changed after the implementation
+% has been parsed.
+unit_u_implementation_crc_changed=10046_U_Implementation-CRC ændret for unit $1
+% When you use the \var{-vu} flag, the compiler warns that it the
+% CRC calculated has been changed after the implementation
+% has been parsed.
+unit_u_finished_compiling=10047_U_Færdiggjorde compileringen af unit $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has finished compiling the unit.
+unit_u_add_depend_to=10048_U_Tilføjede afhængighed af $1 til $2
+% When you use the \var{-vu} flag, the compiler warns that it
+% has added a dependency between the two units.
+unit_u_no_reload_is_caller=10049_U_Ingen genindlæsning, $1 er kalder
+% When you use the \var{-vu} flag, the compiler warns that it
+% has will not reload the unit because it is the unit that wants
+% to load this unit
+unit_u_no_reload_in_second_compile=10050_U_Ingen genindlæsning, allerede anden kompilering: $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has will not reload the unit because it is already in a second recompile
+unit_u_flag_for_reload=10051_U_Indstillinger for genindlæsning: $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has to reload the unit
+unit_u_forced_reload=10052_U_Tvungen genindlæsning
+% When you use the \var{-vu} flag, the compiler warns that it
+% has is reloading the unit because it was required
+unit_u_previous_state=10053_U_Tidligere tilstand af $1: $2
+% When you use the \var{-vu} flag, the compiler shows the
+% previous state of the unit
+unit_u_second_compile_unit=10054_U_Compilerer allerede $1, starter anden compilering
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% recompiling a unit for the second time. This can happend with interdepend
+% units.
+unit_u_loading_unit=10055_U_Indlæser unit $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% loading the unit.
+unit_u_finished_loading_unit=10056_U_Indlæsning af unit $1 færdig
+% When you use the \var{-vu} flag, the compiler warns that it finished
+% loading the unit.
+unit_u_registering_new_unit=10057_U_Registrering af unit $1
+% When you use the \var{-vu} flag, the compiler warns that it has
+% found a new unit and registers it in the internal lists.
+unit_u_reresolving_unit=10058_U_Genberegner unit $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has to recalculate the internal data of the unit
+unit_u_skipping_reresolving_unit=10059_U_Springer genberegning over for unit $1, indlæser stadig brugte units
+% When you use the \var{-vu} flag, the compiler warns that it
+% skips to recalculate the internal data of the unit because there
+% is no data to recalculate
+% \end{description}
+# EndOfTeX
+
+#
+# Options
+#
+# 11039 is the last used one
+#
+option_usage=11000_O_$1 [indstillinger] <inputfil> [indstillinger]
+# BeginOfTeX
+%
+% \section{Command-line handling errors}
+% This section lists errors that occur when the compiler is processing the
+% command line or handling the configuration files.
+% \begin{description}
+option_only_one_source_support=11001_W_Kun én kildefil understøttet
+% You can specify only one source file on the command line. The first
+% one will be compiled, others will be ignored. This may indicate that
+% you forgot a \var{'-'} sign.
+option_def_only_for_os2=11002_W_DEF-fil kan kun laves på OS/2
+% This option can only be specified when you're compiling for OS/2
+option_no_nested_response_file=11003_E_indlejrede svarfiler ikke understøttet
+% you cannot nest response files with the \var{@file} command-line option.
+option_no_source_found=11004_F_Ingen kildefil angivet på kommandolinien
+% The compiler expects a source file name on the command line.
+option_no_option_found=11005_N_Ingen indstillinger i konfigurationsfilen $1
+% The compiler didn't find any option in that config file.
+option_illegal_para=11006_E_Ugyldig parameter: $1
+% You specified an unknown option.
+option_help_pages_para=11007_H_-? udskriver hjælpe-beskeder
+% When an unknown option is given, this message is diplayed.
+option_too_many_cfg_files=11008_F_for mange indlejrede niveauer af konfigurationsfiler
+% You can only nest up to 16 config files.
+option_unable_open_file=11009_F_Kan ikke åbne filen $1
+% The option file cannot be found.
+option_reading_further_from=11010_D_Læser yderligere indstillinger fra $1
+% Displayed when you have notes turned on, and the compiler switches
+% to another options file.
+option_target_is_already_set=11011_W_MÃ¥l er allerede sat til: $1
+% Displayed if more than one \var{-T} option is specified.
+option_no_shared_lib_under_dos=11012_W_Delte biblioteker er ikke understøttet på DOS-platformen, går tilbage til statisk
+% If you specify \var{-CD} for the \dos platform, this message is displayed.
+% The compiler supports only static libraries under \dos
+option_too_many_ifdef=11013_F_for mange IF(N)DEF
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_too_many_endif=11014_F_for mange ENDIFs
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_too_less_endif=11015_F_Ã¥bne betingelser i slutningen af filen
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_no_debug_support=11016_W_generering af debug-information understøttes ikke at dette programformat
+% It is possible to have a compiler executable that doesn't support
+% the generation of debugging info. If you use such an executable with the
+% \var{-g} switch, this warning will be displayed.
+option_no_debug_support_recompile_fpc=11017_H_Prøv at gencompilere med -dGDB
+% It is possible to have a compiler executable that doesn't support
+% the generation of debugging info. If you use such an executable with the
+% \var{-g} switch, this warning will be displayed.
+option_obsolete_switch=11018_E_Du bruger $1 der er en forældet indstilling
+% this warns you when you use a switch that is not needed/supported anymore.
+% It is recommended that you remove the switch to overcome problems in the
+% future, when the switch meaning may change.
+option_obsolete_switch_use_new=11019_E_Du bruger $1 der er en forældet indstilling. Vær venlig at bruge $2
+% this warns you when you use a switch that is not supported anymore. You
+% must now use the second switch instead.
+% It is recommended that you change the switch to overcome problems in the
+% future, when the switch meaning may change.
+option_switch_bin_to_src_assembler=11020_N_Skifter til den standard-assembler der skriver direkte til assemblerfilerne
+% this notifies you that the assembler has been changed because you used the
+% -a switch which can't be used with a binary assembler writer.
+option_incompatible_asm=11021_W_Det valgte udformat for assemblerfiler "$1" er ikke kompatibelt med "$2"
+option_asm_forced=11022_W_brug af "$1" assembler gennemtvunget
+% The assembler output selected can not generate
+% object files with the correct format. Therefore, the
+% default assembler for this target is used instead.
+option_using_file=11026_T_Læser indstillinger fra filen $1
+% Options are also read from this file
+option_using_env=11027_T_Læser indstillinger fra environment $1
+% Options are also read from this environment string
+option_handling_option=11028_D_HÃ¥ndterer indstilling "$1"
+% Debug info that an option is found and will be handled
+option_help_press_enter=11029__*** tryk enter ***
+option_start_reading_configfile=11030_H_Begynder at læse konfigurationsfil $1
+% Starting of config file parsing.
+option_end_reading_configfile=11031_H_Er færdig med at læse konfigurationsfil $1
+% End of config file parsing.
+option_interpreting_option=11032_D_fortolker indstilling "$1"
+option_interpreting_firstpass_option=11036_D_fortolker indstilling til første gennemløb "$1"
+option_interpreting_file_option=11033_D_fortolker filindstilling "$1"
+option_read_config_file=11034_D_Læser konfigurationsfil "$1"
+option_found_file=11035_D_fandt kildefilen "$1"
+% Additional infos about options, displayed
+% when you have debug option turned on.
+option_code_page_not_available=11039_E_Ukendt tegnsæt
+%\end{description}
+# EndOfTeX
+
+#
+# Logo (option -l)
+#
+option_config_is_dir=11040_F_Konfigurationsfilen $1 er et directory
+% Directories can not be used as configuration files.
+%\end{description}
+# EndOfTeX
+
+#
+# Logo (option -l)
+#
+option_logo=11023_[
+Free Pascal Compiler version $FPCFULLVERSION [$FPCDATE] til $FPCTARGET
+Copyright (c) 1993-2011 Florian Klaempfl
+]
+
+#
+# Info (option -i)
+#
+option_info=11024_[
+Free Pascal Compiler version $FPCVERSION
+
+Compilerdato : $FPCDATE
+Compilerplatform : $FPCTARGET
+
+Understøttede platforme:
+ $OSTARGETS
+
+Dette program dækkes af reglerne for GNU General Public License
+Læs COPYING.FPC for mere information
+
+Indsend fejlbeskrivelser, forslag, etc til
+ http://bugs.freepascal.org
+og
+ bugs@freepascal.org
+
+For kommentarer vedrørende den danske oversættelse, skriv til
+ chrivers@iversen-net.dk
+]
+
+#
+# Help pages (option -? and -h)
+#
+# The first character on the line indicates who will display this
+# line, the current possibilities are :
+# * = every target
+# 3 = 80x86 targets
+# 6 = 680x0 targets
+# e = in extended debug mode only
+# P = PowerPC targets
+# S = Sparc targets
+# V = Virtual machine targets
+# The second character also indicates who will display this line,
+# (if the above character was TRUE) the current possibilities are :
+# * = everyone
+# g = with GDB info supported by the compiler
+# O = OS/2
+# L = UNIX systems
+# The third character represents the indentation level.
+#
+option_help_pages=11025_[
+**0*_sæt + efter en indstilling for at slå den til, - for at slå den fra
+**1a_compileren sletter ikke den genererede assemblerfil
+**2al_lav en liste over linienummer fra kildekoden i assemblerfilen
+**2ar_indsæt information om register(de)allokering i assemblerfilen
+**2at_indsæt information om midlertidige allokeringer i assemblerfilen
+**1b_generér browser-information
+**2bl_generér information om lokale symboler
+**1B_byg alle moduler
+**1C<x>_Indstillinger for kodegenerering
+**2CD_Byg også et dynamisk bibliotek (ikke understøttet)
+**2Ce_Compilér med emulerede kommatalsoperationer
+**2Cf_Vælg hvilket fpu-instruktionssæt der skal bruges
+**2Cg_Generér PIC-kode
+**2Ch<n>_Sæt heapstørrelsen til <n> bytes (mellem 1023 og 67107840)
+**2Ci_IO-checking
+**2Cn_spring link-stadiet over
+**2Co_check overflow af heltalsoperationer
+**2Cr_værdiområdecheck
+**2CR_verificér gyldigheden af objekters metodekald
+**2Cs<n>_set stakstørrelsen til <n>
+**2Ct_stakchecking
+**2CX_byg også et smartlinket bibliotek
+**1d<x>_definerer symbolet <x>
+*O1D_genererer en DEF-fil
+*O2Dd<x>_sætter beskrivelsen til <x>
+*O2Dw_PM-applikation
+**1e<x>_sæt stien til programmet
+**1E_samme som -Cn
+**1F<x>_sæt filnavne og stier:
+**2FD<x>_sætter mappen hvor der søges efter hjælpeprogrammer til compileren
+**2Fe<x>_videresend fejlbeskeder til <x>
+**2FE<x>_sæt exe/unit sti til <x>
+**2Fi<x>_tilføjer <x> til include-stien
+**2Fl<x>_tilføjer <x> til library-stien
+*L2FL<x>_bruger <x> som dynamisk linker
+**2Fo<x>_tilføjer <x> til object-stien
+**2Fr<x>_indlæser beskedfilen <x>
+**2Fu<x>_tilføjer <x> til unit-stien
+**2FU<x>_sæt unit-output-stien til <x>, overskriver -FE
+*g1g_Generér debug-information:
+*g2gg_brug gsym
+*g2gd_brug dbx
+*g2gh_brug heap-sporingsunit (til at finde memory leaks)
+*g2gl_brug line-infounit for at vise backtraces
+*g2gc_generér checks for pointere
+*g2gv_generér programmer der kan spores med valgrind
+*g2gw_generér dwarf debug-information
+**1i_information:
+**2iD_returnerer compilerdato
+**2iV_returnerer compilerversion
+**2iSO_returnerer compiler-OS
+**2iSP_returnerer compiler-processor
+**2iTO_returnerer mål-system
+**2iTP_returnerer mål-processor
+**1I<x>_tilføjer <x> til include-stien
+**1k<x>_videregiv <x> til linkeren
+**1l_skriv logo under kørsel
+**1M<x>_sæt sprogtilstand til <x>
+**2Mfpc_free pascal dialekt (standard)
+**2Mobjfpc_slå visse udvidelser fra Delphi 2 til
+**2Mdelphi_forsøg at være Delphi-kompatibel
+**2Mtp_forsøg at være Turbo/Borland Pascal 7.0-kompatibel
+**2Mgpc_forsøg at være GNU-Pascal-kompatibel
+**2Mmacpas_forsøg at være kompatibel med pascal-dialekter fra macintosh
+**1n_spring læsning af standardkonfigurationsfil over
+**1o<x>_ændr navnet af det producerede program til <x>
+**1pg_generér profileringskode til gprof (definerer FPC_PROFILE)
+*L1P_brug pipes i stedet for midlertidige assembler-filer
+**1S<x>_Syntaxindstillinger:
+**2S2_samme som -Mobjfpc
+**2Sc_understøttet operatorer som i C (*=,+=,/= and -=)
+**2Sa_bruger assertion-kode
+**2Sd_samme som -Mdelphi
+**2Se<x>_compileren stopper efter den <x>te fejl (standard er efter første fejl)
+**2Sg_tillad LABEL og GOTO
+**2Sh_brug ansistrenge
+**2Si_brug C++-lignende INLINE
+**2Sm_understøt makroer som I C (globalt)
+**2So_samme som -Mtp
+**2Sp_samme som -Mgpc
+**2Ss_constructor-navn skal være "init" (destructor-navn skal være "done")
+**1s_kør hverken assembler eller linker
+**2sh_generér script til linkning på værtscomputeren
+**2st_generér script til linkning på mål-computeren
+**2sr_spring registerallokerings-fasen over (optimeringer vil være slået fra)
+**1u<x>_fjerner definitionen af symbolet <x>
+**1U_Unit-indstillinger:
+**2Un_undersøg ikke om unit-navnet er korrekt
+**2Ur_generér release-unit-filer
+**2Us_compilér en system-enhed
+**1v<x>_Ekstra information. <x> er en kombination af følgende bogstaver:
+**2*_e : Vis fejl (standard) d : Vis debug-information
+**2*_w : Vis advarsler u : Vis unit-information
+**2*_n : Vis bemærkninger t : Vis forsøgte/benyttede filer
+**2*_h : Vis hints m : Vis definerede makroer
+**2*_i : Vis generel information p : Vis kompilerede procedurer
+**2*_l : Vis linienumre c : Vis betingelser
+**2*_a : Vis alt 0 : Vis intet (bortset fra fejl)
+**2*_b : Vis alle procedure- r : Rhide/GCC kompatabilitetstilstand
+**2*_ erklæringer hvis der x : Programinformation (kun på windows)
+**2*_ opstår en fejl
+**1V_skriv filen fpcdebug.txt med store mængder debug-information
+*L2Xc_link med c-biblioteket
+**2Xs_fjern alle symboler fra programfilen
+**2XP<x>_sæt <x> foran binutils-filnavnene
+**2XD_forsøg at linke dynamisk (definerer FPC_LINK_DYNAMIC)
+**2XS_forsøg at linke statisk (standard) (definerer FPC_LINK_STATIC)
+**2XX_forsøg at linke intelligent (definerer FPC_LINK_SMART)
+**0*_Processor-specifikke indstillinger:
+3*1A<x>_Udfilformat:
+3*2Aas_brug GNU AS som assembler
+3*2Anasmcoff_brug Nasm til at lave en coff-fil (Go32v2)
+3*2Anasmelf_brug Nasm til at lave en elf32-fil (Linux)
+3*2Awasm_brug Wasm til at lave en obj-fil (Watcom)
+3*2Anasmobj_brug Nasm til at lave en obj-fil
+3*2Amasm_brug Masm til at lave en obj-fil (Microsoft)
+3*2Atasm_brug Tasm til at lave en obj-fil (Borland)
+3*2Acoff_brug intern filgenerator til at lave coff-fil (Go32v2)
+3*2Apecoff_brug intern filgenerator til at lave pecoff-fil (Win32)
+3*1R<x>_Læsestil for assembler:
+3*2Ratt_Læs assemblerkode i AT&T-stil
+3*2Rintel_Læs assemblerkode i Intel-stil
+3*2Rdirect_Kopier assemblerkoden direkte ind i assemblerkildefilen
+3*1O<x>_Optimeringer:
+3*2Og_generér lille kode
+3*2OG_generér hurtig kode (standard)
+3*2Or_gem visse variabler i registre
+3*2Ou_slå usikre optimeringer til (se dokumentation)
+3*2O1_niveau-1 optimeringer (hurtige optimeringer)
+3*2O2_niveau-2 optimeringer (-O1 + langsommere optimeringer)
+3*2O3_niveau-3 optimeringer (-O2 gentaget, højst 5 gange)
+3*2Op<x>_MÃ¥lprocessor:
+3*3Op1_sæt målprocessor til 386/486
+3*3Op2_sæt målprocessor til Pentium/PentiumMMX (tm)
+3*3Op3_sæt målprocessor til PPro/PII/c6x86/K6 (tm)
+3*1T<x>_MÃ¥l-operativsystem:
+3*2Temx_OS/2 via EMX (bruger EMX/RSX extender)
+3*2Tgo32v2_Version 2 af DJ Delorie DOS extender
+3*2Tlinux_Linux
+3*2Tnetware_Novell Netware Module (clib)
+3*2Tnetwlibc_Novell Netware Module (libc)
+3*2Tos2_OS/2 / eComStation
+3*2Tsunos_SunOS/Solaris
+3*2Twatcom_Watcom kompatibel DOS extender
+3*2Twdosx_WDOSX DOS extender
+3*2Twin32_Windows 32 Bit
+3*1W<x>_Indstillinger for Win32-lignende mål:
+3*2WB<x>_sæt image base til <x> (hexadecimal)
+3*2WC_specificér konsolprogram
+3*2WD_brug DEFFILE til at eksportere funktioner fra DLL eller EXE
+3*2WF_specificér grafisk fuldskærmsprogram (kun OS/2)
+3*2WG_specificér grafisk programtype
+3*2WN_lav ikke-relokérbar kode (nødvendig til debugging)
+3*2WR_lav relokérbar kode
+6*1A<x>_Udfilformat
+6*2Aas_Brug GNU AS til at lave Unix o-filer
+6*2Agas_GNU Motorola assembler
+6*2Amit_MIT Syntax (old GAS)
+6*2Amot_Standard Motorola assembler
+6*1O_Optimeringer:
+6*2Oa_slå optimeringer til
+6*2Og_generér lille kode
+6*2OG_generér hurtig kode (standard)
+6*2Ox_optimer maksimalt (stadig ikke fejlfri!!)
+6*2O0_sæt målprocessor til MC68000
+6*2O2_sæt målprocessor til MC68020+ (standard)
+6*1R<x>_Læsestil for assembleren:
+6*2RMOT_Læs assemblerkode i motorola-stil
+6*1T<x>_MÃ¥l-operativsystem:
+6*2Tamiga_Commodore Amiga
+6*2Tatari_Atari ST/STe/TT
+6*2Tlinux_Linux-68k
+6*2Tmacos_Macintosh m68k (ikke understøttet)
+6*2Tpalmos_PalmOS
+P*1T<x>_MÃ¥l-operativsystem:
+P*2Tdarwin_Darwin og MacOS X på PowerPC
+P*2Tlinux_Linux på PowerPC
+P*2Tmacos_MacOS (klassisk) på PowerPC
+P*2Tmorphos_MorphOS
+P*2WC_Vælg konsoleapplikation (MacOS only)
+P*2WG_Vælg grafisk applikation (MacOS only)
+P*2WT_Vælg værktøjsapplikation (MPW tool, MacOS only)
+**1*_
+**1?_vis denne hjælp
+**1h_vis denne hjælp uden at vente på tastetryk
+]
+
+#
+# Slut :)
+#
+%%% general_e_path_does_not_exists=01017_E_Sti "$1" ikke fundet
+% The specified path does not exists.
+% \end{description}
+#
+# Scanner
+#
+# 02061 is the last used one
+#
+% \section{Scanner messages.}
+% This section lists the messages that the scanner emits. The scanner takes
+% care of the lexical structure of the pascal file, i.e. it tries to find
+% reserved words, strings, etc. It also takes care of directives and
+% conditional compiling handling.
+% \begin{description}
+%%% scan_w_only_pack_records=02015_W_Strukturfelter kan kun opstilles på 1,2,4,8,16 eller 32 bytes
+% You are specifying the \var{\{\$PACKRECORDS n\} } with an illegal value for
+% \var{n}. Only 1, 2, 4, 8, 16 and 32 are valid in this case.
+%%% scan_w_only_pack_enum=02016_W_Enumerate-typer kan kun gemmes i 1,2 eller 4 bytes
+% You are specifying the \var{\{\$PACKENUM n\}} with an illegal value for
+% \var{n}. Only 1,2 or 4 are valid in this case.
+%%% scan_w_macro_deep_ten=02030_W_Makroudvidelse har en dybdegrænse på 16 niveauer
+% When expanding a macro, macros have been nested to a level of 16.
+% The compiler will expand no further, since this may be a sign that
+% recursion is used.
+%%% parser_e_no_local_external=03174_E_Kan ikke erklære lokal procedure som EXTERNAL
+% Declaring local procedures as external is not possible. Local procedures
+% get hidden parameters that will make the chance of errors very high
+%%% parser_e_too_complex_expr=03202_E_Udtryk for komplekst - stakoverløb på FPU
+% Your expression is too long for the compiler. You should try dividing the
+% construct over multiple assignments.
+%%% sym_n_uninitialized_local_variable=05036_W_Lokal variabel "$1" ser ikke ud til at være initialiseret
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+%%% sym_n_uninitialized_variable=05037_W_Variablen "$1" ser ikke ud til at være initialiseret
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+%%% unit_h_cond_not_set_in_last_compile=10038_H_Betingelsen $1 var slået fra ved sidste compilering af $2
+% when recompilation of an unit is required the compiler will check that
+% the same conditionals are set for the recompiliation. The compiler has
+% found a conditional that currently is defined, but was not used the last
+% time the unit was compiled.
+%%% unit_h_cond_set_in_last_compile=10039_H_Betingelsen $1 var slået til ved sidste compilering af $2
+% when recompilation of an unit is required the compiler will check that
+% the same conditionals are set for the recompiliation. The compiler has
+% found a conditional that was used the last time the unit was compiled, but
+% the conditional is currently not defined.
+%%% option_defining_symbol=11037_D_Definerer symbolet $1
+%%% option_undefining_symbol=11038_D_Fjerner symbolet $1
+% Additional infos about options, displayed
+% when you have debug option turned on.
diff --git a/closures/compiler/msg/errordu.msg b/closures/compiler/msg/errordu.msg
new file mode 100644
index 0000000000..f13cca027d
--- /dev/null
+++ b/closures/compiler/msg/errordu.msg
@@ -0,0 +1,3418 @@
+#
+# German (UTF-8) Language File for Free Pascal
+# Latest updates contributed by Karl-Michael Schindler aka mischi
+# <karl-michael.schindler at web.de>
+#
+# Based on errore.msg of SVN revision 18275
+#
+# This file is part of the Free Pascal Compiler
+# Copyright (c) 1998-2010 by the Free Pascal Development team
+#
+# See the file COPYING.FPC, included in this distribution,
+# for details about the copyright.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#
+#
+# The constants are build in the following order:
+# <part>_<type>_<txtidentifier>
+#
+# <part> is the part of the compiler the message is used
+# asmr_ assembler parsing
+# asmw_ assembler writing/binary writers
+# unit_ unit handling
+# scan_ scanner
+# parser_ parser
+# type_ type checking
+# general_ general info
+# exec_ calls to assembler, linker, binder
+# link_ internal linker
+#
+# <type> the type of the message it should normally used for
+# f_ fatal error
+# e_ error
+# w_ warning
+# n_ note
+# h_ hint
+# i_ info
+# l_ add linenumber
+# u_ used
+# t_ tried
+# c_ conditional
+# d_ debug message
+# x_ executable informations
+# o_ normal (e.g., "press enter to continue")
+#
+
+#
+# General
+#
+# 01025 is the last used one
+#
+# BeginOfTeX
+% \section{General compiler messages}
+% This section gives the compiler messages which are not fatal, but which
+% display useful information. The number of such messages can be
+% controlled with the various verbosity level \var{-v} switches.
+% \begin{description}
+general_t_compilername=01000_T_Compiler: $1
+% When the \var{-vt} switch is used, this line tells you what compiler
+% is used.
+general_d_sourceos=01001_D_Quellbetriebssystem: $1
+% When the \var{-vd} switch is used, this line tells you what the source
+% operating system is.
+general_i_targetos=01002_I_Zielbetriebssystem: $1
+% When the \var{-vd} switch is used, this line tells you what the target
+% operating system is.
+general_t_exepath=01003_T_Der Pfad der ausführbaren Datei ist: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for its binaries.
+general_t_unitpath=01004_T_Der Unitpfad ist: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for compiled units. You can set this path with the \var{-Fu} option.
+general_t_includepath=01005_T_Der Includepfad ist: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for its include files (files used in \var{\{\$I xxx\}} statements).
+% You can set this path with the \var{-Fi} option.
+general_t_librarypath=01006_T_Der Bibliothekspfad ist: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for the libraries. You can set this path with the \var{-Fl} option.
+general_t_objectpath=01007_T_Der Objektdateienpfad ist: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for object files you link in (files used in \var{\{\$L xxx\}} statements).
+% You can set this path with the \var{-Fo} option.
+general_i_abslines_compiled=01008_I_$1 Zeilen übersetzt, $2 Sekunden $3
+% When the \var{-vi} switch is used, the compiler reports the number
+% of lines compiled, and the time it took to compile them (real time,
+% not program time).
+general_f_no_memory_left=01009_F_Speicher voll
+% The compiler doesn't have enough memory to compile your program. There are
+% several remedies for this:
+% \begin{itemize}
+% \item If you're using the build option of the compiler, try compiling the
+% different units manually.
+% \item If you're compiling a huge program, split it up into units, and compile
+% these separately.
+% \item If the previous two don't work, recompile the compiler with a bigger
+% heap. (You can use the \var{-Ch} option for this, \seeo{Ch}.)
+% \end{itemize}
+general_i_writingresourcefile=01010_I_Resourcestringtabellendatei $1 wird geschrieben
+% This message is shown when the compiler writes the Resource String Table
+% file containing all the resource strings for a program.
+general_e_errorwritingresourcefile=01011_E_Fehler beim Schreiben der Resourcestringtabellendatei: $1
+% This message is shown when the compiler encountered an error when writing
+% the Resource String Table file.
+general_i_fatal=01012_I_Fataler Fehler:
+% Prefix for Fatal Errors.
+general_i_error=01013_I_Fehler:
+% Prefix for Errors.
+general_i_warning=01014_I_Warnung:
+% Prefix for Warnings.
+general_i_note=01015_I_Anmerkung:
+% Prefix for Notes.
+general_i_hint=01016_I_Hinweis:
+% Prefix for Hints.
+general_e_path_does_not_exist=01017_E_Der Pfad "$1" existiert nicht
+% The specified path does not exist.
+general_f_compilation_aborted=01018_F_Ãœbersetzen abgebrochen
+% Compilation was aborted.
+general_text_bytes_code=01019_bytes Code
+% The size of the generated executable code, in bytes.
+general_text_bytes_data=01020_bytes Daten
+% The size of the generated program data, in bytes.
+general_i_number_of_warnings=01021_I_$1 Warnung(en) ausgegeben
+% Total number of warnings issued during compilation.
+general_i_number_of_hints=01022_I_$1 Hinweis(e) ausgegeben
+% Total number of hints issued during compilation.
+general_i_number_of_notes=01023_I_$1 Anmerkung(en) ausgegeben
+% Total number of notes issued during compilation.
+general_f_ioerror=01024_F_I/O Fehler: $1
+% During compilation an I/O error happened which allows no further compilation.
+general_f_oserror=01025_F_Betriebsystemfehler: $1
+% During compilation an operanting system error happened which allows no further compilation.
+%
+% \end{description}
+# EndOfTeX
+
+#
+# Scanner
+#
+# 02088 is the last used one
+#
+% \section{Scanner messages.}
+% This section lists the messages that the scanner emits. The scanner takes
+% care of the lexical structure of the pascal file, i.e. it tries to find
+% reserved words, strings, etc. It also takes care of directives and
+% conditional compilation handling.
+% \begin{description}
+scan_f_end_of_file=02000_F_Unerwartetes Dateiende
+% this typically happens in one of the following cases:
+% \begin{itemize}
+% \item The source file ends before the final \var{end.} statement. This
+% happens mostly when the \var{begin} and \var{end} statements aren't
+% balanced;
+% \item An include file ends in the middle of a statement.
+% \item A comment was not closed.
+% \end{itemize}
+scan_f_string_exceeds_line=02001_F_Zeichenkette geht über das Zeilenende hinaus
+% You forgot probably to include the closing ' in a string, so it occupies
+% multiple lines.
+scan_f_illegal_char=02002_F_Unzulässiges Zeichen "$1" ($2)
+% An illegal character was encountered in the input file.
+scan_f_syn_expected=02003_F_Syntaxfehler, "$1" erwartet, aber "$2" vorgefunden
+% This indicates that the compiler expected a different token than
+% the one you typed. It can occur almost anywhere it is possible to make an error
+% against the Pascal language.
+scan_t_start_include_file=02004_TL_Die Include-Datei $1 wird jetzt gelesen
+% When you provide the \var{-vt} switch, the compiler tells you
+% when it starts reading an included file.
+scan_w_comment_level=02005_W_Kommentarschachtelungstiefe $1 gefunden
+% When the \var{-vw} switch is used, then the compiler warns you if
+% it finds nested comments. Nested comments are not allowed in Turbo Pascal
+% and Delphi, and can be a possible source of errors.
+scan_n_ignored_switch=02008_N_Compilerschalter $1 wurde ignoriert
+% With \var{-vn} on, the compiler warns if it ignores a switch.
+scan_w_illegal_switch=02009_W_Compilerschalter $1 ist ungültig
+% You included a compiler switch (i.e. \var{\{\$... \}}) which the compiler
+% does not recognise.
+scan_w_switch_is_global=02010_W_Dieser Compilerschalter hat globale Auswirkung
+% The compiler switch is misplaced, and should be located at
+% the start of the unit or program.
+scan_e_illegal_char_const=02011_E_Ungültige Char-Konstante
+% This happens when you specify a character with its ASCII code, as in
+% \var{\#96}, but the number is either illegal, or out of range.
+scan_f_cannot_open_input=02012_F_Datei $1 kann nicht geöffnet werden
+% \fpc cannot find the program or unit source file you specified on the
+% command line.
+scan_f_cannot_open_includefile=02013_F_Includedatei $1 kann nicht geöffnet werden
+% \fpc cannot find the source file you specified in a \var{\{\$include ..\}}
+% statement.
+scan_e_illegal_pack_records=02015_E_Ungültige Record Ausrichtung "$1"
+% You are specifying \var{\{\$PACKRECORDS n\} } or \var{\{\$ALIGN n\} }
+% with an illegal value for \var{n}. For \$PACKRECORDS valid alignments are 1, 2, 4, 8, 16, 32, C,
+% NORMAL, DEFAULT, and for \$ALIGN valid alignments are 1, 2, 4, 8, 16, 32, ON,
+% OFF. Under mode MacPas \$ALIGN also supports MAC68K, POWER and RESET.
+scan_e_illegal_pack_enum=02016_E_Ungültige minimale Grösse der Aufzählung "$1"
+% You are specifying the \var{\{\$PACKENUM n\}} with an illegal value for
+% \var{n}. Only 1,2,4, NORMAL or DEFAULT is valid here.
+scan_e_endif_expected=02017_E_$ENDIF erwartet für $1 $2 definiert in $3 Zeile $4
+% Your conditional compilation statements are unbalanced.
+scan_e_preproc_syntax_error=02018_E_Syntaxfehler im Argument einer $if Direktive
+% There is an error in the expression following the \var{\{\$if ..\}}, \var{\{\$ifc \}}
+% or \var{\{\$setc \}} compiler directives.
+scan_e_error_in_preproc_expr=02019_E_Syntaxfehler im Kontext einer $if Direktive
+% There is an error in the expression following the \var{\{\$if ..\}} compiler
+% directive.
+scan_w_macro_cut_after_255_chars=02020_W_Inhalt des Makros wurde nach der Auswertung bei 255 Zeichen abgeschnitten
+% The contents of macros cannot be longer than 255 characters.
+scan_e_endif_without_if=02021_E_ENDIF ohne IF(N)DEF
+% Your \var{\{\$IFDEF ..\}} and {\{\$ENDIF\}} statements aren't balanced.
+scan_f_user_defined=02022_F_Benutzerdefiniert: $1
+% A user defined fatal error occurred. See also the \progref
+scan_e_user_defined=02023_E_Benutzerdefiniert: $1
+% A user defined error occurred. See also the \progref
+scan_w_user_defined=02024_W_Benutzerdefiniert: $1
+% A user defined warning occurred. See also the \progref
+scan_n_user_defined=02025_N_Benutzerdefiniert: $1
+% A user defined note was encountered. See also the \progref
+scan_h_user_defined=02026_H_Benutzerdefiniert: $1
+% A user defined hint was encountered. See also the \progref
+scan_i_user_defined=02027_I_Benutzerdefiniert: $1
+% User defined information was encountered. See also the \progref
+scan_e_keyword_cant_be_a_macro=02028_E_Ein Makro, das den selben Namen wie ein Schlüsselwort hat, wird ignoriert
+% You cannot redefine keywords with macros.
+scan_f_macro_buffer_overflow=02029_F_Makropufferüberlauf während des Lesens oder Expandierens eines Makros
+% Your macro or it's result was too long for the compiler.
+scan_w_macro_too_deep=02030_W_Expansion des Makros überschreitet eine Makroschachtelungstiefe von 16
+% When expanding a macro macros have been nested to a level of 16.
+% The compiler will expand no further, since this may be a sign that
+% recursion is used.
+scan_w_wrong_styled_switch=02031_W_Compilerschalter innerhalb von Kommentaren der Form // werden nicht untersützt
+% Compiler switches should be in normal Pascal style comments.
+scan_d_handling_switch=02032_DL_Bearbeite Schalter "$1"
+% When you set debugging info on (\var{-vd}) the compiler tells you when it
+% is evaluating conditional compile statements.
+scan_c_endif_found=02033_CL_ENDIF $1 bearbeitet
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifdef_found=02034_CL_IFDEF $1 bearbeitet, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifopt_found=02035_CL_IFOPT $1 bearbeitet, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_if_found=02036_CL_IF $1 bearbeitet, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifndef_found=02037_CL_IFNDEF $1 bearbeitet, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_else_found=02038_CL_ELSE $1 bearbeitet, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_skipping_until=02039_CL_Quelltext wird ignoriert bis...
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements, and whether it is skipping or
+% compiling parts.
+scan_i_press_enter=02040_I_Drücken Sie <Return> um fortzusetzen
+% When the \var{-vi} switch is used, the compiler stops compilation
+% and waits for the \var{Enter} key to be pressed when it encounters
+% a \var{\{\$STOP\}} directive.
+scan_w_unsupported_switch=02041_W_Nicht unterstützter Schalter $1
+% When warings are turned on (\var{-vw}), the compiler warns you about
+% unsupported switches. This means that the switch is used in Delphi or
+% Turbo Pascal, but not in \fpc.
+scan_w_illegal_directive=02042_W_Ungültige Compilerdirektive $1
+% When warings are turned on (\var{-vw}), the compiler warns you about
+% unrecognised switches. For a list of recognised switches, see the \progref
+scan_t_back_in=02043_TL_Wieder zurück in $1
+% When you use the \var{-vt} switch, the compiler tells you when it has finished
+% reading an include file.
+scan_w_unsupported_app_type=02044_W_Nicht unterstützter Anwendungstyp: $1
+% You get this warning if you specify an unknown application type
+% with the directive \var{\{\$APPTYPE\}}.
+scan_w_app_type_not_support=02045_W_APPTYPE wird vom Zielbetriebssystem nicht unterstützt
+% The \var{\{\$APPTYPE\}} directive is supported by win32 applications only.
+scan_w_description_not_support=02046_W_Der Compilerschalter DESCRIPTION wird vom Zielbetriebssystem nicht unterstützt
+% The \var{\{\$DESCRIPTION\}} directive is not supported on this target OS.
+scan_n_version_not_support=02047_N_VERSION wird vom Zielbetriebssystem nicht unterstützt
+% The \var{\{\$VERSION\}} directive is not supported on this target OS.
+scan_n_only_exe_version=02048_N_VERSION kann in Units nicht verwendet werden
+% The \var{\{\$VERSION\}} directive is only used for executable or DLL sources.
+scan_w_wrong_version_ignored=02049_W_Falsches Format für VERSION-Direktive $1
+% The \var{\{\$VERSION\}} directive format is major_version.minor_version
+% where major_version and minor_version are words.
+scan_e_illegal_asmmode_specifier=02050_E_Unbekannter Assemblermodusname: "$1"
+% When you specify an assembler mode with the \var{\{\$ASMMODE xxx\}} directive,
+% the compiler didn't recognize the mode you specified.
+scan_w_no_asm_reader_switch_inside_asm=02051_W_ASM-Leser-Schalter ist innerhalb einer Asm-Sequenz nicht möglich, $1 wird erst in der nächsten Sequenz wirksam
+% It is not possible to switch from one assembler reader to another
+% inside an assembler block. The new reader will be used for next
+% assembler statement only.
+scan_e_wrong_switch_toggle=02052_E_Parameter für Schalter falsch, verwenden Sie ON/OFF oder +/-
+% You need to use ON or OFF or a + or - to toggle the switch.
+scan_e_resourcefiles_not_supported=02053_E_Resourcedateien werden vom aktuellen Zielbetriebssystem nicht unterstützt
+% The target you are compiling for doesn't support resource files.
+scan_w_include_env_not_found=02054_W_$1 ist keine Umgebungsvariable
+% The included environment variable can't be found in the environment; it will
+% be replaced by an empty string instead.
+scan_e_invalid_maxfpureg_value=02055_E_Nicht erlaubter Wert für MAXFPUREGISTER-Direktive
+% Valid values for this directive are 0..8 and NORMAL/DEFAULT.
+scan_w_only_one_resourcefile_supported=02056_W_Vom aktuellen Zielbetriebssystem wird nur eine Resourcedatei unterstützt
+% Only one resource file can be supported for this target - this is the case of
+% OS/2 (EMX) currently. The first one found is used, the others are discarded.
+scan_w_macro_support_turned_off=02057_W_Makrounterstützung ist ausgeschaltet
+% A macro declaration has been found, but macro support is currently off,
+% so the declaration will be ignored. To turn macro support on compile with
+% -Sm on the command line or add \{\$MACRO ON\} in the source.
+scan_e_invalid_interface_type=02058_E_Unbekannter Interfacetyp. Unterstützt wird COM, CORBA und DEFAULT
+% The interface type that was specified is not supported.
+scan_w_appid_not_support=02059_W_APPID wird nur von PalmOS unterstützt
+% The \var{\{\$APPID\}} directive is only supported for the PalmOS target.
+scan_w_appname_not_support=02060_W_APPNAME wird nur von PalmOS unterstützt
+% The \var{\{\$APPNAME\}} directive is only supported for the PalmOS target.
+scan_e_string_exceeds_255_chars=02061_E_Zeichenkettenkonstanten können maximal 255 Zeichen lang sein
+% A single string constant can contain at most 255 chars. Try splitting up the
+% string into multiple smaller parts and concatenate them with a + operator.
+scan_f_include_deep_ten=02062_F_Include-Dateien können nur bis zu einer Tiefe von 16 geschachtelt werden
+% When including include files the files have been nested to a level of 16.
+% The compiler will expand no further, since this may be a sign that
+% recursion is used.
+scan_e_too_many_push=02063_F_Zu viele Ebenen von PUSH
+% A maximum of 20 levels is allowed. This error occurs only in mode MacPas.
+scan_e_too_many_pop=02064_E_POP ohne ein vorhergehendes PUSH
+% This error occurs only in mode MacPas.
+scan_e_error_macro_lacks_value=02065_E_Das Makro "$1" besitzt keinen Wert
+% Thus the conditional compiling expression cannot be evaluated.
+scan_e_wrong_switch_toggle_default=02066_E_Zum Modusumschalten kann nur ON/OFF/DEFAULT oder +/-/* verwendet werden
+% You need to use ON or OFF or DEFAULT or a + or - or * to toggle the switch.
+scan_e_mode_switch_not_allowed=02067_E_Der Modus Umschalter "$1" ist hier nicht erlaubt
+% A mode switch has already been encountered, or, in the case of option -Mmacpas,
+% a mode switch occurs after UNIT.
+scan_e_error_macro_undefined=02068_E_Die Compile time Variable oder das Makro "$1" ist nicht definiert.
+% Thus the conditional compile time expression cannot be evaluated. Only in mode MacPas.
+scan_e_utf8_bigger_than_65535=02069_E_Der UTF-8 Code ist grösser als 65535
+% \fpc handles UTF-8 strings internally as widestrings, i.e. the char codes are limited to 65535.
+scan_e_utf8_malformed=02070_E_Ungültige UTF-8 Zeichenkette
+% The given string isn't a valid UTF-8 string.
+scan_c_switching_to_utf8=02071_C_UTF-8 Signatur gefunden, verwende UTF-8 Code
+% The compiler found a UTF-8 encoding signature (\$ef, \$bb, \$bf) at the beginning of a file,
+% so it interprets it as a UTF-8 file.
+scan_e_compile_time_typeerror=02072_E_Compile time Ausdruck: Erwartete $1 aber erhielt $2 bei $3
+% The type-check of a compile time expression failed.
+scan_n_app_type_not_support=02073_N_APPTYPE wird vom Zielbetriebssystem nicht unterstützt
+% The \var{\{\$APPTYPE\}} directive is supported by certain operating systems only.
+scan_e_illegal_optimization_specifier=02074_E_"$1" ist eine ungültige Optimierung
+% You specified an optimization with the \var{\{\$OPTIMIZATION xxx\}} directive,
+% and the compiler didn't recognize the optimization you specified.
+scan_w_setpeflags_not_support=02075_W_SETPEFLAGS wird vom Zielbetriebssystem nicht unterstützt
+% The \var{\{\$SETPEFLAGS\}} directive is not supported by the target OS.
+scan_w_imagebase_not_support=02076_W_IMAGEBASE wird vom Zielbetriebssystem nicht unterstützt
+% The \var{\{\$IMAGEBASE\}} directive is not supported by the target OS.
+scan_w_minstacksize_not_support=02077_W_MINSTACKSIZE wird vom Zielbetriebssystem nicht unterstützt
+% The \var{\{\$IMAGEBASE\}} directive is not supported by the target OS.
+scan_w_maxstacksize_not_support=02078_W_MAXSTACKSIZE wird vom Zielbetriebssystem nicht unterstützt
+% The \var{\{\$MAXSTACKSIZE\}} directive is not supported by the target OS.
+scanner_e_illegal_warn_state=02079_E_Ungültiger Wert "$1" für die $WARN Direktive
+% Only ON and OFF can be used as state with a \var{\{\$WARN\}} compiler directive.
+scan_e_only_packset=02080_E_Ungültiger Wert für das set packing
+% Only 0, 1, 2, 4, 8, DEFAULT and NORMAL are allowed as packset parameters.
+scan_w_pic_ignored=02081_W_PIC Direktive oder Schalter wird ignoriert
+% Several targets, such as \windows, do not support nor need PIC,
+% so the PIC directive and switch are ignored.
+scan_w_unsupported_switch_by_target=02082_W_Der Schalter "$1" wird vom derzeit ausgewählten Zielbetriebssystem nicht unterstützt
+% Some compiler switches like \$E are not supported by all targets.
+scan_w_frameworks_darwin_only=02084_W_Framework-bezogene Optionen werden nur für Darwin/Mac OS X unterstützt
+% Frameworks are not a known concept, or at least not supported by FPC,
+% on operating systems other than Darwin/Mac OS X.
+scan_e_illegal_minfpconstprec=02085_E_"$1" ist eine ungültige minimale Präzision von Fliesskommakonstanten
+% Valid minimal precisions for floating point constants are default, 32 and 64,
+% which mean respectively minimal (usually 32 bit), 32 bit and 64 bit precision.
+scan_w_multiple_main_name_overrides=02086_W_Der Name der "main" Prozedur wird mehrfach überschrieben. Es war bisher auf "$1" gesetzt
+% The name for the main entry procedure is specified more than once. Only the last
+% name will be used.
+scanner_w_illegal_warn_identifier=02087_W_Ungültige Bezeichner "$1" für die $WARN Direktive
+% Identifier is not known by a \var{\{\$WARN\}} compiler directive.
+scanner_e_illegal_alignment_directive=02088_E_Ungültige "alignment" Direktive
+% The alignment directive is not valid. Either the alignment type is not known or the alignment
+% value is not a power of two.
+%
+% \end{description}
+# EndOfTeX
+
+#
+# Parser
+#
+# 03313 is the last used one
+#
+% \section{Parser messages}
+% This section lists all parser messages. The parser takes care of the
+% semantics of you language, i.e. it determines if your Pascal constructs
+% are correct.
+% \begin{description}
+parser_e_syntax_error=03000_E_Parser - Syntaxfehler
+% An error against the Turbo Pascal language was encountered. This typically
+% happens when an illegal character is found in the source file.
+parser_e_dont_nest_interrupt=03004_E_INTERRUPT-Prozeduren dürfen nicht verschachtelt sein
+% An \VAR{INTERRUPT} procedure must be global.
+parser_w_proc_directive_ignored=03005_W_Prozedurtyp $1 wird ignoriert
+% The specified procedure directive is ignored by FPC programs.
+parser_e_no_overload_for_all_procs=03006_E_Nicht alle Deklarationen von "$1" sind mit OVERLOAD deklariert
+% When you want to use overloading using the \var{OVERLOAD} directive, then
+% all declarations need to have \var{OVERLOAD} specified.
+parser_e_export_name_double=03008_E_Doppelter Name für exportierte Funktion $1
+% Exported function names inside a specific DLL must all be different.
+parser_e_export_ordinal_double=03009_E_Doppelter Index für exportierte Funktion $1
+% Exported function names inside a specific DLL must all be different.
+parser_e_export_invalid_index=03010_E_Ungültiger Index for exportierte Funktion
+% DLL function index must be in the range \var{1..\$FFFF}.
+parser_w_parser_reloc_no_debug=03011_W_Für relozierbare DLL oder ausführbare Datei $1 funktionieren keine Debug-Information, deaktiviert.
+% It is currently not possible to include debug information in a relocatable DLL.
+parser_w_parser_win32_debug_needs_WN=03012_W_Um Win32-Code debuggen zu können, müssen die Relozierungen mit -WN option abgeschaltet werden.
+% Stabs debug info is wrong for relocatable DLL or EXES. Use -WN
+% if you want to debug win32 executables.
+parser_e_constructorname_must_be_init=03013_E_Konstruktor-Name muss INIT sein
+% You are declaring a constructor with a name which isn't \var{init}, and the
+% \var{-Ss} switch is in effect. See the switch \seeo{Ss}.
+parser_e_destructorname_must_be_done=03014_E_Destruktor-Name muss DONE sein
+% You are declaring a constructor with a name which isn't \var{done}, and the
+% \var{-Ss} switch is in effect. See the switch \seeo{Ss}.
+parser_e_proc_inline_not_supported=03016_E_Schlüsselwort INLINE nicht unterstützt
+% You tried to compile a program with C++ style inlining, and forgot to
+% specify the \var{-Si} option (\seeo{Si}). The compiler doesn't support C++
+% styled inlining by default.
+parser_w_constructor_should_be_public=03018_W_Konstruktor muss PUBLIC sein
+% Constructors must be in the 'public' part of an object (class) declaration.
+parser_w_destructor_should_be_public=03019_W_Destruktor muss PUBLIC sein
+% Destructors must be in the 'public' part of an object (class) declaration.
+parser_n_only_one_destructor=03020_N_Klasse darf nur einen Destruktor besitzen
+% You can declare only one destructor for a class.
+parser_e_no_local_objects=03021_E_Lokale Klassendefinitionen sind nicht zulässig
+% Classes must be defined globally. They cannot be defined inside a
+% procedure or function.
+parser_f_no_anonym_objects=03022_F_Anonyme Klassendefinitionen sind nicht zulässig
+% An invalid object (class) declaration was encountered, i.e. an
+% object or class without methods that isn't derived from another object or
+% class. For example:
+% \begin{verbatim}
+% Type o = object
+% a : longint;
+% end;
+% \end{verbatim}
+% will trigger this error.
+parser_n_object_has_no_vmt=03023_N_Das Objekt "$1" besitzt keine VMT
+% This is a note indicating that the declared object has no
+% virtual method table.
+parser_e_illegal_parameter_list=03024_E_Ungültige Parameterliste
+% You are calling a function with parameters that are of a different type than
+% the declared parameters of the function.
+parser_e_wrong_parameter_size=03026_E_Falsche Anzahl an Parameter im Aufruf von "$1" angegeben
+% There is an error in the parameter list of the function or procedure --
+% the number of parameters is not correct.
+parser_e_overloaded_no_procedure=03027_E_Bezeichner "$1" ist keine Funktion, overload nicht möglich
+% The compiler encountered a symbol with the same name as an overloaded
+% function, but it isn't a function it can overload.
+parser_e_overloaded_have_same_parameters=03028_E_Overload-Funktion darf keine identische Parameterliste aufweisen
+% You're declaring overloaded functions, but with the same parameter list.
+% Overloaded function must have at least 1 different parameter in their
+% declaration.
+parser_e_header_dont_match_forward=03029_E_Funktionskopf unterscheidet sich von voriger Deklaration "$1"
+% You declared a function with the same parameters but
+% different result type or function specifiers.
+parser_e_header_different_var_names=03030_E_Funktionskopf von "$1" passt nicht zur Forward-Deklaration, Variablename ändert sich: $2 => $3
+% You declared the function in the \var{interface} part, or with the
+% \var{forward} directive, but defined it with a different parameter list.
+parser_n_duplicate_enum=03031_N_Werte in Aufzählungen müssen aufsteigend sein
+% \fpc allows enumeration constructions as in C. Examine the following
+% two declarations:
+% \begin{verbatim}
+% type a = (A_A,A_B,A_E:=6,A_UAS:=200);
+% type a = (A_A,A_B,A_E:=6,A_UAS:=4);
+% \end{verbatim}
+% The second declaration would produce an error. \var{A\_UAS} needs to have a
+% value higher than \var{A\_E}, i.e. at least 7.
+parser_e_no_with_for_variable_in_other_segments=03033_E_WITH kann nicht auf Variablen in anderen Segmenten angewendet werden
+% With stores a variable locally on the stack,
+% but this is not possible if the variable belongs to another segment.
+parser_e_too_much_lexlevel=03034_E_Funktionsverschachtelung grösser als 31
+% You can nest function definitions only 31 levels deep.
+parser_e_range_check_error=03035_E_Bereichsprüfungsfehler bei Konstantenbestimmung
+% The constants are out of their allowed range.
+parser_w_range_check_error=03036_W_Bereichsprüfungsfehler bei Konstantenbestimmung
+% The constants are out of their allowed range.
+parser_e_double_caselabel=03037_E_doppelter CASE-Wert
+% You are specifying the same label 2 times in a \var{case} statement.
+parser_e_case_lower_less_than_upper_bound=03038_E_Obere Grenze der CASE-Bereichsangabe ist kleiner als untere Grenze
+% The upper bound of a \var{case} label is less than the lower bound and this
+% is useless.
+parser_e_type_const_not_possible=03039_E_Klassen oder Interfaces 03229_Esind als typisierte Konstanten unzulässig
+% You cannot declare a constant of type class or object.
+parser_e_no_overloaded_procvars=03040_E_Funktionsvariablen von Overload-Funktionen sind unzulässig
+% You are trying to assign an overloaded function to a procedural variable.
+% This is not allowed.
+parser_e_invalid_string_size=03041_E_Stringlänge muss ein Wert zwischen 1 und 255 sein
+% The length of a string in Pascal is limited to 255 characters. You are
+% trying to declare a string with length less than 1 or greater than 255.
+parser_w_use_extended_syntax_for_objects=03042_W_Benutzen Sie die erweiterte Syntax von NEW und DISPOSE für Objekt-Instanzen
+% If you have a pointer \var{a} to an object type, then the statement
+% \var{new(a)} will not initialize the object (i.e. the constructor isn't
+% called), although space will be allocated. You should issue the
+% \var{new(a,init)} statement. This will allocate space, and call the
+% constructor of the object.
+parser_w_no_new_dispose_on_void_pointers=03043_W_Verwendung von NEW oder DISPOSE mit untypisierten Pointern ist ohne Aussage
+parser_e_no_new_dispose_on_void_pointers=03044_E_Verwendung von NEW oder DISPOSE mit untypisierten Pointern ist nicht möglich
+% You cannot use \var{new(p)} or \var{dispose(p)} if \var{p} is an untyped pointer
+% because no size is associated to an untyped pointer.
+% It is accepted for compatibility in \var{TP} and \var{DELPHI} modes, but the
+% compiler will still warn you if it finds such a construct.
+parser_e_class_id_expected=03045_E_Klassenbezeichner erwartet
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., an object or class method, but the type in front of the dot is not
+% a known type.
+parser_e_no_type_not_allowed_here=03046_E_Typbezeichner ist hier nicht zulässig
+% You cannot use a type inside an expression.
+parser_e_methode_id_expected=03047_E_Methodenbezeichner erwartet
+% This identifier is not a method.
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., an object or class method, but the procedure name is not a
+% procedure of this type.
+parser_e_header_dont_match_any_member=03048_E_Funktionskopf passt zu keiner Methode der Klasse $1
+% This identifier is not a method.
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., an object or class method, but the procedure name is not a
+% procedure of this type.
+parser_d_procedure_start=03049_DL_Procedure/Function $1
+% When using the \var{-vd} switch, the compiler tells you when it starts
+% processing a procedure or function implementation.
+parser_e_error_in_real=03050_E_Ungültige Fliesskommakonstante
+% The compiler expects a floating point expression, and gets something else.
+parser_e_fail_only_in_constructor=03051_E_FAIL darf nur in Konstruktoren verwendet werden
+% You are using the \var{FAIL} instruction outside a constructor method.
+parser_e_no_paras_for_destructor=03052_E_Destruktoren können keine Parameter haben
+% You are declaring a destructor with a parameter list. Destructor methods
+% cannot have parameters.
+parser_e_only_class_members_via_class_ref=03053_E_Nur Klassenmethoden, Klasseneigenschaften und Klassenvariablen können über den Klassennamen angesprochen werden
+% This error occurs in a situation like the following:
+% \begin{verbatim}
+% Type :
+% Tclass = Class of Tobject;
+%
+% Var C : TClass;
+%
+% begin
+% ...
+% C.free
+% \end{verbatim}
+% \var{Free} is not a class method and hence cannot be called with a class
+% reference.
+parser_e_only_class_members=03054_E_Nur Klassenmethoden, Klasseneigenschaften und Klassenvariablen können in einer Klassenmethode angesprochen werden
+% This is related to the previous error. You cannot call a method of an object
+% from inside a class method. The following code would produce this error:
+% \begin{verbatim}
+% class procedure tobject.x;
+%
+% begin
+% free
+% \end{verbatim}
+% Because free is a normal method of a class it cannot be called from a class
+% method.
+parser_e_case_mismatch=03055_E_Konstante und CASE-Typ passen nicht zueinander
+% One of the labels is not of the same type as the case variable.
+parser_e_illegal_symbol_exported=03056_E_Das Symbol kann nicht aus einer Bibliothek exportiert werden
+% You can only export procedures and functions when you write a library. You
+% cannot export variables or constants.
+parser_w_should_use_override=03057_W_Eine Inherit-Methode wird durch $1 verdeckt
+% A method that is declared \var{virtual} in a parent class, should be
+% overridden in the descendant class with the \var{override} directive. If you
+% don't specify the \var{override} directive, you will hide the parent method;
+% you will not override it.
+parser_e_nothing_to_be_overridden=03058_E_Es gibt keine Vorgängerklasse mit einer Methode, die damit überschrieben werden könnte: $1
+% You try to \var{override} a virtual method of a parent class that doesn't
+% exist.
+parser_e_no_procedure_to_access_property=03059_E_Es gibt keine Member-Funktion um auf diese Property zuzugreifen
+% You specified no \var{read} directive for a property.
+parser_w_stored_not_implemented=03060_W_Die Stored Property - Direktive ist noch nicht implementiert
+% This message is no longer used, as the \var{stored} directive has been implemented.
+parser_e_ill_property_access_sym=03061_E_Ungültiges Symbol für den Zugriff auf die Property
+% There is an error in the \var{read} or \var{write} directives for an array
+% property. When you declare an array property, you can only access it with
+% procedures and functions. The following code would cause such an error.
+% \begin{verbatim}
+% tmyobject = class
+% i : integer;
+% property x [i : integer]: integer read I write i;
+% \end{verbatim}
+%
+parser_e_cant_access_protected_member=03062_E_Kann an dieser Stelle nicht auf das geschützte Feld des Objekts zugreifen
+% Fields that are declared in a \var{protected} section of an object or class
+% declaration cannot be accessed outside the module where the object is
+% defined, or outside descendent object methods.
+parser_e_cant_access_private_member=03063_E_Kann an dieser Stelle nicht auf das private Feld des Objekts zugreifen
+% Fields that are declared in a \var{private} section of an object or class
+% declaration cannot be accessed outside the module where the class is
+% defined.
+parser_e_overridden_methods_not_same_ret=03066_E_Überschriebene, virtuelle Methoden müssen den gleichen Ergebnistyp haben: "$2" wird überschrieben von "$1"
+% If you declare overridden methods in a class definition, they must
+% have the same return type.
+parser_e_dont_nest_export=03067_E_Mit EXPORT deklarierte Funktionen dürfen nicht verschachtelt sein
+% You cannot declare a function or procedure within a function or procedure
+% that was declared as an export procedure.
+parser_e_methods_dont_be_export=03068_E_Methoden dürfen nicht EXPORTiert werden
+% You cannot declare a procedure that is a method for an object as
+% \var{export}ed. That is, your methods cannot be called from a C program.
+parser_e_call_by_ref_without_typeconv=03069_E_Aufrufe mit VAR-Parametern für Argument-Nr. $1 müssen exakt stimmen: "$2" gefunden, "$3" erwartet
+% When calling a function declared with \var{var} parameters, the variables in
+% the function call must be of exactly the same type. There is no automatic
+% type conversion.
+parser_e_no_super_class=03070_E_Klasse ist keine Elternklasse zur aktuellen Klasse
+% When calling inherited methods, you are trying to call a method of a strange
+% class. You can only call an inherited method of a parent class.
+parser_e_self_not_in_method=03071_E_SELF ist nur in Methoden erlaubt
+% You are trying to use the \var{self} parameter outside an object's method.
+% Only methods get passed the \var{self} parameters.
+parser_e_generic_methods_only_in_methods=03072_E_Methoden dürfen nur in anderen Methoden direkt mit dem Klassen-Typbezeichner aufgerufen werden
+% A construction like \var{sometype.somemethod} is only allowed in a method.
+parser_e_illegal_colon_qualifier=03073_E_Unzulässige Verwendung von ':'
+% You are using the format \var{:} (colon) 2 times on an expression that
+% is not a real expression.
+parser_e_illegal_set_expr=03074_E_Bereichsprüfungsfehler im SET-Konstruktor oder doppeltes Set-Element
+% The declaration of a set contains an error. Either one of the elements is
+% outside the range of the set type, or two of the elements are in fact
+% the same.
+parser_e_pointer_to_class_expected=03075_E_Zeiger auf Objekt erwartet
+% You specified an illegal type in a \var{New} statement.
+% The extended synax of \var{New} needs an object as a parameter.
+parser_e_expr_have_to_be_constructor_call=03076_E_Ausdruck muss ein Konstruktor-Aufruf sein
+% When using the extended syntax of \var{new}, you must specify the constructor
+% method of the object you are trying to create. The procedure you specified
+% is not a constructor.
+parser_e_expr_have_to_be_destructor_call=03077_E_Ausdruck muss ein Destruktor-Aufruf sein
+% When using the extended syntax of \var{dispose}, you must specify the
+% destructor method of the object you are trying to dispose of.
+% The procedure you specified is not a destructor.
+parser_e_invalid_record_const=03078_E_Unzulässige Reihenfolge der Record-Elemente
+% When declaring a constant record, you specified the fields in the wrong
+% order.
+parser_e_false_with_expr=03079_E_Typ des Ausdrucks muss eine Klasse oder ein Recordtyp sein
+% A \var{with} statement needs an argument that is of the type \var{record}
+% or \var{class}. You are using \var{with} on an expression that is not of
+% this type.
+parser_e_void_function=03080_E_Prozeduren können keinen Wert zurückliefern
+% In \fpc, you can specify a return value for a function when using
+% the \var{exit} statement. This error occurs when you try to do this with a
+% procedure. Procedures cannot return a value.
+parser_e_only_methods_allowed=03081_E_Konstruktoren, Destruktoren und Klassenoperatoren müssen Methoden sein
+% You're declaring a procedure as destructor, constructor or class operator, when the
+% procedure isn't a class method.
+parser_e_operator_not_overloaded=03082_E_Operator besitzt kein Overload
+% You're trying to use an overloaded operator when it isn't overloaded for
+% this type.
+parser_e_no_such_assignment=03083_E_Es ist nicht möglich, die Zuweisung für gleiche Typen zu überladen
+% You cannot overload assignment for types
+% that the compiler considers as equal.
+parser_e_overload_impossible=03084_E_Unmögliche Operator-.berladung
+% The combination of operator, arguments and return type are
+% incompatible.
+parser_e_no_reraise_possible=03085_E_Auslösen einer Exception an dieser Stelle nicht möglich
+% You are trying to re-raise an exception where it is not allowed. You can only
+% re-raise exceptions in an \var{except} block.
+parser_e_no_new_or_dispose_for_classes=03086_E_Die erweiterte Syntax von New oder Dispose ist für Klassen unzulässig
+% You cannot generate an instance of a class with the extended syntax of
+% \var{new}. The constructor must be used for that. For the same reason, you
+% cannot call \var{Dispose} to de-allocate an instance of a class, the
+% destructor must be used for that.
+parser_e_procedure_overloading_is_off=03088_E_Das Ãœberladen von Prozeduren ist ausgeschaltet
+% When using the \var{-So} switch, procedure overloading is switched off.
+% Turbo Pascal does not support function overloading.
+parser_e_overload_operator_failed=03089_E_Es ist nicht möglich, dieesen Operator zu überladen. Verwandte überladbare Operatoren sind "$1"
+% You are trying to overload an operator which cannot be overloaded.
+% The following operators can be overloaded :
+% \begin{verbatim}
+% +, -, *, /, =, >, <, <=, >=, is, as, in, **, :=
+% \end{verbatim}
+parser_e_comparative_operator_return_boolean=03090_E_Vergleichsoperator muss einen booleschen Wert zurückgeben
+% When overloading the \var{=} operator, the function must return a boolean
+% value.
+parser_e_only_virtual_methods_abstract=03091_E_Nur virtuelle Methoden können abstrakt sein
+% You are declaring a method as abstract, when it isn't declared to be
+% virtual.
+parser_f_unsupported_feature=03092_F_Benutzung einer nicht unterstützten Erweiterung!
+% You're trying to force the compiler into doing something it cannot do yet.
+parser_e_mix_of_classes_and_objects=03093_E_Das Mischen von Klassen und Objekten ist unzulässig
+% You cannot derive \var{objects}, \var{classes}, \var{cppclasses} and \var{interfaces} intertwined. E.g.
+% a class cannot have an object as parent and vice versa.
+parser_w_unknown_proc_directive_ignored=03094_W_Unbekannte Prozedur, Direktive $1 wurde ignoriert
+% The procedure direcive you secified is unknown.
+parser_e_absolute_only_one_var=03095_E_ABSOLUTE kann nur auf eine alleinstehende Variable angewendet werden
+% You cannot specify more than one variable before the \var{absolute} directive.
+% Thus, the following construct will provide this error:
+% \begin{verbatim}
+% Var Z : Longint;
+% X,Y : Longint absolute Z;
+% \end{verbatim}
+parser_e_absolute_only_to_var_or_const=03096_E_ABSOLUTE kann nur auf Variablen und Konstanten angewendet werden
+% The address of an \var{absolute} directive can only point to a variable or
+% constant. Therefore, the following code will produce this error:
+% \begin{verbatim}
+% Procedure X;
+%
+% var p : longint absolute x;
+% \end{verbatim}
+%
+parser_e_initialized_only_one_var=03097_E_Es kann nur EINE Variable initialisiert werden
+% You cannot specify more than one variable with a initial value in Delphi mode.
+parser_e_abstract_no_definition=03098_E_Abstrakte Methoden dürfen keine Definition (mit Rumpf) haben
+% Abstract methods can only be declared, you cannot implement them. They
+% should be overridden by a descendant class.
+parser_e_overloaded_must_be_all_global=03099_E_Diese überladene Funktion darf nicht lokal sein (muss Exportiert werden)
+% You are defining an overloaded function in the implementation part of a unit,
+% but there is no corresponding declaration in the interface part of the unit.
+parser_w_virtual_without_constructor=03100_W_Virtuelle Methoden wurden ohne Konstruktor verwendet in $1
+% If you declare objects or classes that contain virtual methods, you need
+% to have a constructor and destructor to initialize them. The compiler
+% encountered an object or class with virtual methods that doesn't have
+% a constructor/destructor pair.
+parser_c_macro_defined=03101_CL_Makro definiert: $1
+% When \var{-vc} is used, the compiler tells you when it defines macros.
+parser_c_macro_undefined=03102_CL_Makrodefinition gelöscht: $1
+% When \var{-vc} is used, the compiler tells you when it undefines macros.
+parser_c_macro_set_to=03103_CL_Wert des Makros $1 auf $2 gesetzt
+% When \var{-vc} is used, the compiler tells you what values macros get.
+parser_i_compiling=03104_I_Ãœbersetze $1
+% When you turn on information messages (\var{-vi}), the compiler tells you
+% what units it is recompiling.
+parser_u_parsing_interface=03105_UL_Parse Interface von Unit $1
+% This tells you that the reading of the interface
+% of the current unit has started
+parser_u_parsing_implementation=03106_UL_Parse Implementation von $1
+% This tells you that the code reading of the implementation
+% of the current unit, library or program starts
+parser_d_compiling_second_time=03107_DL_Ãœbersetze $1 zum zweiten Mal
+% When you request debug messages (\var{-vd}) the compiler tells you what
+% units it recompiles for the second time.
+parser_e_no_property_found_to_override=03109_E_Es gibt keine Property diesen Namens, die überschrieben werden könnte
+% You want to overrride a property of a parent class, when there is, in fact,
+% no such property in the parent class.
+parser_e_only_one_default_property=03110_E_Es ist nur eine einzelne Default-Property erlaubt, vererbte Default-Property in Klasse $1 gefunden
+% You specified a property as \var{Default}, but a parent class already has a
+% default property, and a class can have only one default property.
+parser_e_property_need_paras=03111_E_Die Default-Property muss eine Array-Property sein
+% Only array properties of classes can be made \var{default} properties.
+parser_e_constructor_cannot_be_not_virtual=03112_E_Virtuelle Konstruktoren werden nur im Klassen-Objektmodell unterstützt
+% You cannot have virtual constructors in objects. You can only have them
+% in classes.
+parser_e_no_default_property_available=03113_E_Keine Default-Property verfügbar
+% You try to access a default property of a class, but this class (or one of
+% its ancestors) doesn't have a default property.
+parser_e_cant_have_published=03114_E_Die Klasse kann keinen PUBLISHED Bereich haben, benutzen Sie den {$M+} Schalter
+% If you want a \var{published} section in a class definition, you must
+% use the \var{\{\$M+\}} switch, which turns on generation of type
+% information.
+parser_e_forward_declaration_must_be_resolved=03115_E_Forward-Deklaration der Klasse $1 muss hier aufgelöst werden, wenn sie als Elternklasse benutzt werden soll
+% To be able to use an object as an ancestor object, it must be defined
+% first. This error occurs in the following situation:
+% \begin{verbatim}
+% Type ParentClas = Class;
+% ChildClass = Class(ParentClass)
+% ...
+% end;
+% \end{verbatim}
+% where \var{ParentClass} is declared but not defined.
+parser_e_no_local_operator=03116_E_Lokale Operatoren werden nicht unterstützt
+% You cannot overload locally, i.e. inside procedures or function
+% definitions.
+parser_e_proc_dir_not_allowed_in_interface=03117_E_Prozedur-Direktive $1 unzulässig im Interface-Bereich
+% This procedure directive is not allowed in the \var{interface} section of
+% a unit. You can only use it in the \var{implementation} section.
+parser_e_proc_dir_not_allowed_in_implementation=03118_E_Prozedur Direktive $1 unzulässig im Implementation-Bereich
+% This procedure directive is not allowed in the \var{implementation} section of
+% a unit. You can only use it in the \var{interface} section.
+parser_e_proc_dir_not_allowed_in_procvar=03119_E_Prozedur-Direktive $1 unzulässig in einer Procvar-Deklaration
+% This procedure directive cannot be part of a procedural of function
+% type declaration.
+parser_e_function_already_declared_public_forward=03120_E_Funktion ist bereits als Public oder Forward deklariert: $1
+% You will get this error if a function is defined as \var{forward} twice.
+% Or if it occurs in the \var{interface} section, and again as a \var{forward}
+% declaration in the \var{implementation} section.
+parser_e_not_external_and_export=03121_E_Kann nicht EXPORT und EXTERNAL gleichzeitig benutzen
+% These two procedure directives are mutually exclusive.
+parser_w_not_supported_for_inline=03123_W_$1 noch nicht innerhalb von inline Prozeduren/Funktionen unterstützt
+% Inline procedures don't support this declaration.
+parser_w_inlining_disabled=03124_W_Inlining deaktiviert
+% Inlining of procedures is disabled.
+parser_i_writing_browser_log=03125_I_Schreibe Browser-Log $1
+% When information messages are on, the compiler warns you when it
+% writes the browser log (generated with the \var{\{\$Y+\}} switch).
+parser_h_maybe_deref_caret_missing=03126_H_Möglicherweise fehlt eine Zeiger-Dereferenzierung
+% The compiler thinks that a pointer may need a dereference.
+parser_f_assembler_reader_not_supported=03127_F_Gewählter Assembler-Leser nicht unterstützt
+% The selected assembler reader (with \var{\{\$ASMMODE xxx\}} is not
+% supported. The compiler can be compiled with or without support for a
+% particular assembler reader.
+parser_e_proc_dir_conflict=03128_E_Prozedur-Direktive $1 steht in Konflikt mit anderen Direktiven
+% You specified a procedure directive that conflicts with other directives.
+% For instance \var{cdecl} and \var{pascal} are mutually exclusive.
+parser_e_call_convention_dont_match_forward=03129_E_Aufrufkonvention passt nicht zur Forward-Deklaration
+% This error happens when you declare a function or procedure with
+% e.g. \var{cdecl;} but omit this directive in the implementation, or vice
+% versa. The calling convention is part of the function declaration, and
+% must be repeated in the function definition.
+parser_e_property_cant_have_a_default_value=03131_E_Property kann keinen Vorgabewert haben
+% Set properties or indexed properties cannot have a default value.
+parser_e_property_default_value_must_const=03132_E_Der Vorgabewert einer Property muss eine Konstante sein
+% The value of a \var{default} declared property must be known at compile
+% time. The value you specified is only known at run time. This happens
+% e.g. if you specify a variable name as a default value.
+parser_e_cant_publish_that=03133_E_Symbol darf nicht PUBLISHED sein, dies kann nur eine Klasse sein
+% Only class type variables can be in a \var{published} section of a class
+% if they are not declared as a property.
+parser_e_cant_publish_that_property=03134_E_Diese Property-Art kann nicht PUBLISHED sein
+% Properties in a \var{published} section cannot be array properties.
+% They must be moved to public sections. Properties in a \var{published}
+% section must be an ordinal type, a real type, strings or sets.
+parser_e_empty_import_name=03136_E_Leerer Importname angegeben
+% Some targets need a name for the imported procedure or a \var{cdecl} specifier.
+parser_e_division_by_zero=03138_E_Division durch Null
+% A division by zero was encounted.
+parser_e_invalid_float_operation=03139_E_Ungültige Fliesskomma-Operation
+% An operation on two real type values produced an overflow or a division
+% by zero.
+parser_e_array_lower_less_than_upper_bound=03140_E_Obere Grenze des Bereichs ist kleiner als die untere Grenze
+% The upper bound of an array declaration is less than the lower bound and this
+% is not possible.
+parser_w_string_too_long=03141_W_String "$1" ist länger als $2
+% The size of the constant string is larger than the size you specified in
+% string type definition.
+parser_e_string_larger_array=03142_E_Stringlänge ist grösser als die Länge des "array of char"
+% The size of the constant string is larger than the size you specified in
+% the \var{Array[x..y] of char} definition.
+parser_e_ill_msg_expr=03143_E_Ungültiger Ausdruck nach der 'Message'-Direktive
+% \fpc supports only integer or string values as message constants.
+parser_e_ill_msg_param=03144_E_Message-Handler akzeptieren nur einen "Call by Reference" Parameter
+% A method declared with the \var{message} directive as message handler
+% can take only one parameter which must be declared as call by reference.
+% Parameters are declared as call by reference using the \var{var}-directive.
+parser_e_duplicate_message_label=03145_E_Doppeltes Message-Label: $1
+% A label for a message is used twice in one object/class.
+parser_e_self_in_non_message_handler=03146_E_SELF darf nur in Message-Handlern ein expliziter Parameter sein
+% The \var{Self} parameter can only be passed explicitly to a method which
+% is declared as message method handler
+parser_e_threadvars_only_sg=03147_E_Threadvariablen können nur statisch oder global sein
+% Threadvars must be static or global; you can't declare a thread
+% local to a procedure. Local variables are always local to a thread,
+% because every thread has its own stack and local variables
+% are stored on the stack.
+parser_f_direct_assembler_not_allowed=03148_F_Direkter Assembler wird f+r binäres Ausgabeformat nicht unterstützt
+% You can't use direct assembler when using a binary writer. Choose an
+% other output format or use another assembler reader.
+parser_w_no_objpas_use_mode=03149_W_Laden Sie die OBJPAS Unit nicht manuell, benutzen Sie statdessen {$mode objfpc} oder {$mode delphi}
+% You are trying to load the \file{ObjPas} unit manually from a \var{uses} clause.
+% This is not a good idea. Use the \var{\{\$MODE OBJFPC\}} or
+% \var{\{\$mode delphi\}} directives which load the unit automatically.
+parser_e_no_object_override=03150_E_OVERRIDE darf in Objekten nicht verwendet werden
+% \var{Override} is not supported for objects, use \var{virtual} instead to override
+% a method of a parent object.
+parser_e_cant_use_inittable_here=03151_E_Datentypen, die ein Initialiserung oder Finalisierung benötigen, können in varianten Records nicht verwendet werden
+% Some data types (e.g. \var{ansistring}) need initialization/finalization
+% code which is implicitly generated by the compiler. Such data types
+% can't be used in the variant part of a record.
+parser_e_resourcestring_only_sg=03152_E_Resourcestrings dürfen nur statisch oder global sein
+% Resourcestring cannot be declared local, only global or using the static
+% directive.
+parser_e_exit_with_argument_not__possible=03153_E_EXIT mit Argument darf hier nicht verwendet werden
+% An exit statement with an argument for the return value can't be used here. This
+% can happen for example in \var{try..except} or \var{try..finally} blocks.
+parser_e_stored_property_must_be_boolean=03154_E_Der Typ des STORED-Symbols muss boolesch sein
+% If you specify a storage symbol in a property declaration, it must be a
+% boolean type.
+parser_e_ill_property_storage_sym=03155_E_Dieses Symbol ist als Speichersymbol unzulässig
+% You can't use this type of symbol as storage specifier in property
+% declaration. You can use only methods with the result type boolean,
+% boolean class fields or boolean constants.
+parser_e_only_publishable_classes_can_be_published=03156_E_Nur Klassen, die im "$M+"-Modus übersetzt wurden, dürfen published sein
+% A class-typed field in the published section of a class can only be a class which was
+% compiled in \var{\{\$M+\}} or which is derived from such a class. Normally
+% such a class should be derived from \var{TPersistent}.
+parser_e_proc_directive_expected=03157_E_Prozedurdirektive erwartet
+% This error is triggered when you have a \var{\{\$Calling\}} directive without
+% a calling convention specified.
+% It also happens when declaring a procedure in a const block and you
+% used a ; after a procedure declaration which must be followed by a
+% procedure directive.
+% Correct declarations are:
+% \begin{verbatim}
+% const
+% p : procedure;stdcall=nil;
+% p : procedure stdcall=nil;
+% \end{verbatim}
+parser_e_invalid_property_index_value=03158_E_Der Wert für einen Property-Index muss ordinalen Typs sein
+% The value you use to index a property must be of an ordinal type, for
+% example an integer or enumerated type.
+parser_e_procname_to_short_for_export=03159_E_Prozedurname zu kurz um exportiert zu werden
+% The length of the procedure/function name must be at least 2 characters
+% long. This is because of a bug in dlltool which doesn't parse the .def
+% file correctly with a name of length 1.
+parser_e_dlltool_unit_var_problem=03160_E_Es kann kein DEFFILE-Eintrag für unit-globale Variablen erzeugt werden
+parser_e_dlltool_unit_var_problem2=03161_E_Ãœbersetze ohne "-WD"-Option
+% You need to compile this file without the -WD switch on the
+% command line.
+parser_f_need_objfpc_or_delphi_mode=03162_F_Es muss der Modus ObjFPC (-S2) oder Delphi (-Sd) aktiv sein, um dieses Modul zu übersetzen
+% You need to use \var{\{\$MODE OBJFPC\}} or \var{\{\$MODE DELPHI\}} to compile this file.
+% Or use the corresponding command line switch, either \var{-Mobjfpc} or \var{-MDelphi.}
+parser_e_no_export_with_index_for_target=03163_E_Der Index darf nicht kleiner als $1 sein
+% Exporting of functions or procedures with a specified index is not
+% supported on this target.
+parser_e_no_export_of_variables_for_target=03164_E_Das Ziel $1 unterstützt das Exportieren von Variablen nicht
+% Exporting of variables is not supported on this target.
+parser_e_improper_guid_syntax=03165_E_Falscher GUID-Syntax
+% The GUID indication does not have the proper syntax. It should be of the form
+% \begin{verbatim}
+% {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}
+% \end{verbatim}
+% Where each \var{X} represents a hexadecimal digit.
+parser_w_interface_mapping_notfound=03168_W_Eine Prozedur mit dem Namen "$1", die $2.$3 implementieren könnte, kann nicht gefunden werden
+% The compiler cannot find a suitable procedure which implements the given method of an interface.
+% A procedure with the same name is found, but the arguments do not match.
+parser_e_interface_id_expected=03169_E_Interface-Bezeichner erwartet
+% This happens when the compiler scans a \var{class} declaration that contains
+% \var{interface} function name mapping code like this:
+% \begin{verbatim}
+% type
+% TMyObject = class(TObject, IDispatch)
+% function IUnknown.QueryInterface=MyQueryInterface;
+% ....
+% \end{verbatim}
+% and the \var{interface} before the dot is not listed in the inheritance list.
+parser_e_type_cant_be_used_in_array_index=03170_E_Der Typ "$1" kann nicht als Array-Index verwendet werden
+% Types like \var{qword} or \var{int64} aren't allowed as array index type.
+parser_e_no_con_des_in_interfaces=03171_E_Kon- und Destruktoren sind in Interfaces nicht erlaubt
+% Constructor and destructor declarations aren't allowed in interfaces.
+% In the most cases method \var{QueryInterface} of \var{IUnknown} can
+% be used to create a new interface.
+parser_e_no_access_specifier_in_interfaces=03172_E_Zugriffsbezeichner können in INTERFACEs und OBJCPROTOCOLs nicht benutzt werden
+% The access specifiers \var{public}, \var{private}, \var{protected} and
+% \var{published} can't be used in interfaces, Objective-C protocols and categories because all methods
+% of an interface/protocol/category must be public.
+parser_e_no_vars_in_interfaces=03173_E_Ein Interface, ein Helfer, ein Objective-C Protokoll oder eine Kategorie darf keine Felder enthalten
+% Declarations of fields are not allowed in interfaces, helpers and Objective-C protocols and categories.
+% An interface/helper/protocol/category can contain only methods and properties with method read/write specifiers.
+parser_e_no_local_proc_external=03174_E_Eine lokale Prozedur kann nicht als EXTERNAL deklariert werden
+% Declaring local procedures as external is not possible. Local procedures
+% get hidden parameters that will make the chance of errors very high.
+parser_w_skipped_fields_before=03175_W_Einige Felder vor dem Feld "$1" sind nicht initialisiert
+% In Delphi mode, not all fields of a typed constant record have to be
+% initialized, but the compiler warns you when it detects such situations.
+parser_e_skipped_fields_before=03176_E_Einige Felder vor dem Feld "$1" sind nicht initialisiert
+% In all syntax modes but Delphi mode, you can't leave some fields uninitialized
+% in the middle of a typed constant record.
+parser_w_skipped_fields_after=03177_W_Einige Felder nach dem Feld "$1" sind nicht initialisiert
+% You can leave some fields at the end of a type constant record uninitialized
+% (The compiler will initialize them to zero automatically). This may be the cause
+% of subtle problems.
+parser_e_varargs_need_cdecl_and_external=03178_E_Verwendung von VarArgs (oder '...' in MacPas) ohne CDecl/CPPDecl/MWPascal oder External nicht möglich
+% The varargs directive (or the ``...'' varargs parameter in MacPas mode) can only be
+% used with procedures or functions that are declared with \var{external} and one of
+% \var{cdecl}, \var{cppdecl} and \var{mwpascal}. This functionality
+% is only supported to provide a compatible interface to C functions like printf.
+parser_e_self_call_by_value=03179_E_Self muss ein Call-By-Value-Parameter sein
+% You can't declare \var{Self} as a const or var parameter, it must always be
+% a call-by-value parameter.
+parser_e_interface_has_no_guid=03180_E_Interface "$1" hat keine Interface-Identifikation
+% When you want to assign an interface to a constant, then the interface
+% must have a GUID value set.
+parser_e_illegal_field_or_method=03181_E_Klassenfeld oder Methoden-Bezeichner "$1" unbekannt
+% Properties must refer to a field or method in the same class.
+parser_w_proc_overriding_calling=03182_W_Ãœberschreibe die Calling Convention "$1" mit "$2"
+% There are two directives in the procedure declaration that specify a calling
+% convention. Only the last directive will be used.
+parser_e_no_procvarobj_const=03183_E_Die Konstante des Typs "procedure of object" kann nur mit NIL initialisiert werden
+% You cannot assign the address of a method to a typed constant which has a
+% 'procedure of object' type, because such a constant requires two addresses:
+% that of the method (which is known at compile time) and that of the object or
+% class instance it operates on (which cannot be known at compile time).
+parser_e_default_value_only_one_para=03184_E_Der Default Value kann nur einem Parameter zugewiesen werden
+% It is not possible to specify a default value for several parameters at once.
+% The following is invalid:
+% \begin{verbatim}
+% Procedure MyProcedure (A,B : Integer = 0);
+% \end{verbatim}
+% Instead, this should be declared as
+% \begin{verbatim}
+% Procedure MyProcedure (A : Integer = 0; B : Integer = 0);
+% \end{verbatim}
+parser_e_default_value_expected_for_para=03185_E_Standard Parameter für "$1" benötigt
+% The specified parameter requires a default value.
+parser_w_unsupported_feature=03186_W_Verwendung eines nicht unterstützten Features!
+% You're trying to force the compiler into doing something it cannot do yet.
+parser_h_c_arrays_are_references=03187_H_C Arrays werden "by reference" übergeben
+% Any array passed to a C function is passed
+% by a pointer (i.e. by reference).
+parser_e_C_array_of_const_must_be_last=03188_E_C array of const muss letztes Argument sein
+% You cannot add any other argument after an \var{array of const} for
+% \var{cdecl} functions, as the size pushed on stack for this argument is
+% not known.
+parser_h_type_redef=03189_H_Erneute Definition des Typs "$1"
+% This is an indicator that a previously declared type is
+% being redefined as something else. This may, or may not
+% be, a potential source of errors.
+parser_w_cdecl_has_no_high=03190_W_cdecl'ared Functionen haben keinen high Parameter
+% Functions declared with the \var{cdecl} modifier do not pass an extra implicit parameter.
+parser_w_cdecl_no_openstring=03191_W_cdecl'ared Functionen unterstützen keine open strings
+% Openstring is not supported for functions that have the \var{cdecl} modifier.
+parser_e_initialized_not_for_threadvar=03192_E_Als threadvar deklarierte Variable kann nicht initialisiert werden
+% Variables declared as threadvar cannot be initialized with a default value.
+% The variables will always be filled with zero at the start of a new thread.
+parser_e_msg_only_for_classes=03193_E_Message directive ist nur in Klassen erlaubt
+% The message directive is only supported for Class types.
+parser_e_procedure_or_function_expected=03194_E_Procedure oder Function erwartet
+% A class method can only be specified for procedures and functions.
+parser_e_illegal_calling_convention=03195_W_Calling convention directive ignoriert: "$1"
+% Some calling conventions are supported only by certain CPUs. I.e. most non-i386 ports support
+% only the standard ABI calling convention of the CPU.
+parser_e_no_object_reintroduce=03196_E_REINTRODUCE kann in Objekten nicht benutzt werden
+% \var{reintroduce} is not supported for objects, Objective-C classes and Objective-C protocols.
+parser_e_paraloc_only_one_para=03197_E_Jedes Argument muss seine eigene "location" haben
+% If locations for arguments are specified explicitly as it is required by
+% some syscall conventions, each argument must have its own location. Things
+% like
+% \begin{verbatim}
+% procedure p(i,j : longint 'r1');
+% \end{verbatim}
+% aren't allowed.
+parser_e_paraloc_all_paras=03198_E_Jedes Argument muss seine explizite "location" haben
+% If one argument has an explicit argument location, all arguments of a procedure
+% must have one.
+parser_e_illegal_explicit_paraloc=03199_E_"location" des Arguments unbekannt
+% The location specified for an argument isn't recognized by the compiler.
+parser_e_32bitint_or_pointer_variable_expected=03200_E_32 Bit-Integer oder Zeiger-Variable erwartet
+% The libbase for MorphOS/AmigaOS can be given only as \var{longint}, \var{dword} or any pointer variable.
+parser_e_goto_outside_proc=03201_E_Goto Statements zwischen verschiedenen Prozeduren sind nicht erlaubt
+% It isn't allowed to use \var{goto} statements referencing labels outside the
+% current procedure. The following example shows the problem:
+% \begin{verbatim}
+% ...
+% procedure p1;
+% label
+% l1;
+%
+% procedure p2;
+% begin
+% goto l1; // This goto ISN'T allowed
+% end;
+%
+% begin
+% p2
+% l1:
+% end;
+% ...
+%
+% \end{verbatim}
+parser_f_too_complex_proc=03202_F_Prozedur zu komplex, sie erfordert zu viele Register
+% Your procedure body is too long for the compiler. You should split the
+% procedure into multiple smaller procedures.
+parser_e_illegal_expression=03203_E_Ungültiger Ausdruck
+% This can occur under many circumstances. Usually when trying to evaluate
+% constant expressions.
+parser_e_invalid_integer=03204_E_Ungültiger integer Ausdruck
+% You made an expression which isn't an integer, and the compiler expects the
+% result to be an integer.
+parser_e_invalid_qualifier=03205_E_Ungültiger Qualifier
+% One of the following is happening :
+% \begin{itemize}
+% \item You're trying to access a field of a variable that is not a record.
+% \item You're indexing a variable that is not an array.
+% \item You're dereferencing a variable that is not a pointer.
+% \end{itemize}
+parser_e_upper_lower_than_lower=03206_E_High Range Limit < low Range Limit
+% You are declaring a subrange, and the high limit is less than the low limit of
+% the range.
+parser_e_macpas_exit_wrong_param=03207_E_Exits Parameter muss der Name der Prozedur sein, in der es benutzt wird
+% Non local exit is not allowed. This error occurs only in mode MacPas.
+parser_e_illegal_assignment_to_count_var=03208_E_Ungültige Zuweisung zur for-loop Variable "$1"
+% The type of a \var{for} loop variable must be an ordinal type.
+% Loop variables cannot be reals or strings. You also cannot assign values to
+% loop variables inside the loop (Except in Delphi and TP modes). Use a while or
+% repeat loop instead if you need to do something like that, since those
+% constructs were built for that.
+parser_e_no_local_var_external=03209_E_Lokale Variable kann nicht als EXTERNAL deklariert werden
+% Declaring local variables as external is not allowed. Only global variables can reference
+% external variables.
+parser_e_proc_already_external=03210_E_Prozedur ist bereits als EXTERNAL deklariert
+% The procedure is already declared with the EXTERNAL directive in an interface or
+% forward declaration.
+parser_w_implicit_uses_of_variants_unit=03211_W_Implizite Verwendung einer Variant Unit
+% The Variant type is used in the unit without any used unit using the Variants unit. The
+% compiler has implicitly added the Variants unit to the uses list. To remove this warning
+% the Variants unit needs to be added to the uses statement.
+parser_e_no_static_method_in_interfaces=03212_E_Class und statische Methoden können nicht in INTERFACES verwendet werden
+% The specifier \var{class} and directive \var{static} can't be used in interfaces
+% because all methods of an interface must be public.
+parser_e_arithmetic_operation_overflow=03213_E_Ãœberlauf in arithmetischer Operation
+% An operation on two integer values produced an overflow.
+parser_e_protected_or_private_expected=03214_E_Protected oder private erwartet
+% \var{strict} can be only used together with \var{protected} or \var{private}.
+parser_e_illegal_slice=03215_E_SLICE kann nicht ausserhalb der Parameterliste benutzt werden
+% \var{slice} can be used only for arguments accepting an open array parameter.
+parser_e_dispinterface_cant_have_parent=03216_E_Ein DISPINTERFACE kann keine Elternklasse haben.
+% A DISPINTERFACE is a special type of interface which can't have a parent class. Dispinterface always derive from IDispatch type.
+parser_e_dispinterface_needs_a_guid=03217_E_Ein DISPINTERFACE benötigt einen GUID
+% A DISPINTERFACE always needs an interface identification (a GUID).
+parser_w_overridden_methods_not_same_ret=03218_W_Überschriebene Methoden müssen einen entsprechenden Rückgabetyp haben. Dieser Code kann abstürzen, weil er von einem Delphi Parser Bug abhängt (Methode "$2" wird durch "$1" überschrieben, die einen anderen Rückgabetyp hat).
+% If you declare overridden methods in a class definition, they must
+% have the same return type. Some versions of Delphi allow you to change the
+% return type of interface methods, and even to change procedures into
+% functions, but the resulting code may crash depending on the types used
+% and the way the methods are called.
+parser_e_dispid_must_be_ord_const=03219_E_Dispatch IDs müssen ganzzahlige Konstanten sein
+% The \var{dispid} keyword must be followed by an ordinal constant (the dispid index).
+parser_e_array_range_out_of_bounds=03220_E_Der Bereich des Array ist zu gross
+% Regardless of the size taken up by its elements, an array cannot have more
+% than high(ptrint) elements. Additionally, the range type must be a subrange
+% of ptrint.
+parser_e_packed_element_no_var_addr=03221_E_Bit packed Array-Elemente und Record-Felder haben keine Adressen
+% If you declare an array or record as \var{packed} in Mac Pascal mode
+% (or as \var{packed} in any mode with \var{\{\$bitpacking on\}}), it will
+% be packed at the bit level. This means it becomes impossible to take addresses
+% of individual array elements or record fields. The only exception to this rule
+% is in the case of packed arrays elements whose packed size is a multple of 8 bits.
+parser_e_packed_dynamic_open_array=03222_E_Dynamische Arrays können nicht packed sein
+% Only regular (and possibly in the future also open) arrays can be packed.
+parser_e_packed_element_no_loop=03223_E_Bit packed Array-Elemente und Record-Felder können nicht als Loop-Variable verwerndet werden
+% If you declare an array or record as \var{packed} in Mac Pascal mode
+% (or as \var{packed} in any mode with \var{\{\$bitpacking on\}}), it will
+% be packed at the bit level. For performance reasons, they cannot be
+% used as loop variables.
+parser_e_type_var_const_only_in_records_and_classes=03224_E_VAR, TYPE und CONST sind nur innerhalb Records, Objekten und Klassen erlaubt
+% The usage of VAR, TYPE and CONST to declare new types inside an object is allowed only inside
+% records, objects and classes.
+parser_e_cant_create_generics_of_this_type=03225_E_Dieser Typ kann nicht "generic" sein
+% Only Classes, Objects, Interfaces and Records are allowed to be used as generic.
+parser_w_no_lineinfo_use_switch=03226_W_Die LINEINFO Unit nicht manuell laden. Verwende statt dessen den Compilerschalter -gl
+% Do not use the \file{lineinfo} unit directly, Use the \var{-gl} switch which
+% automatically adds the correct unit for reading the selected type of debugging
+% information. The unit that needs to be used depends on the type of
+% debug information used when compiling the binary.
+parser_e_no_funcret_specified=03227_E_Kein FunKtionsergebnistyp für Funktion "$1" angegeben
+% The first time you declare a function you have to declare it completely,
+% including all parameters and the result type.
+parser_e_special_onlygenerics=03228_E_Spezialisierung wird nur für generische Typen unterstützt
+% Types which are not generics can't be specialized.
+parser_e_no_generics_as_params=03229_E_Generische Typen können bei der Spezialisierung generischer Typen nicht als Parameter benutzt werden
+% When specializing a generic, only non-generic types can be used as parameters.
+parser_e_type_object_constants=03230_E_Konstanten eines Objekts, das ein VMT enthält, sind unzulässig
+% If an object requires a VMT either because it contains a constructor or virtual methods,
+% it's not allowed to create constants of it. In TP and Delphi mode this is allowed
+% for compatibility reasons.
+parser_e_label_outside_proc=03231_E_Die Address von Labels, die ausserhalb des aktuellen Scopes definiert wurden, können nicht verwendet werden
+% It isn't allowed to take the address of labels outside the
+% current procedure.
+parser_e_initialized_not_for_external=03233_E_Extern deklarierte Variablen können nicht intialisiert werden
+% Variables declared as external cannot be initialized with a default value.
+parser_e_illegal_function_result=03234_E_Ungültiger Funktionsergebnistyp
+% Some types like file types cannot be used as function result.
+parser_e_no_common_type=03235_E_"$1" und "$2" haben keinen gemeinsamen Typ
+% To perform an operation on integers, the compiler converts both operands
+% to their common type, which appears to be an invalid type. To determine the
+% common type of the operands, the compiler takes the minimum of the minimal values
+% of both types, and the maximum of the maximal values of both types. The common
+% type is then minimum..maximum.
+parser_e_no_generics_as_types=03236_E_Generische Typen können nicht ohne Spezialisierung als Typ für eine Variable verwendet werden
+% Generics must be always specialized before being used as variable type.
+parser_w_register_list_ignored=03237_W_Registerliste wird in reinen Assemblerroutinen ignoriert
+% When using pure assembler routines, the list with modified registers is ignored.
+parser_e_implements_must_be_class_or_interface=03238_E_Die Implements-Eigenschaft muss einen Klassen- oder Interface-Typ haben
+% A property which implements an interface must be of type class or interface.
+parser_e_implements_must_have_correct_type=03239_E_Die Implements-Eigenschaft muss ein Interface mit dem richtigen Typ implementieren; es wurde Typ "$1" gefunden, aber Typ "$2" erwartet.
+% A property which implements an interface actually implements a different interface.
+parser_e_implements_must_read_specifier=03240_E_Die Implements-Eigenschaft muss einen Lesen-Bezeichner haben
+% A property which implements an interface must have at least a read specifier.
+parser_e_implements_must_not_have_write_specifier=03241_E_Die Implements-Eigenschaft darf keinen Schreib-Bezeichner haben
+% A property which implements an interface may not have a write specifier.
+parser_e_implements_must_not_have_stored_specifier=03242_E_Die Implements-Eigenschaft darf keinen Gespeichert-Bezeichner haben
+% A property which implements an interface may not have a stored specifier.
+parser_e_implements_uses_non_implemented_interface=03243_E_Die Implements-Eigenschaft benutzt das nicht implementierte Interface "$1"
+% The interface which is implemented by a property is not an interface implemented by the class.
+parser_e_unsupported_real=03244_E_Fliesskommavariablen werden für dieses Ziel nicht unterstützt
+% The compiler parsed a floating point expression, but it is not supported.
+parser_e_class_doesnt_implement_interface=03245_E_Klasse "$1" implementiert das Interface "$2" nicht
+% The delegated interface is not implemented by the class given in the implements clause.
+parser_e_class_implements_must_be_interface=03246_E_Der von Implements benutzte Typ muss ein Interface sein
+% The \var{implements} keyword must be followed by an interface type.
+parser_e_cant_export_var_different_name=03247_E_Variablen können für dieses Target nicht mit einem anderen Namen exportiert werden; füge der Deklaration den Namen mit einer "export" Direktive hinzu (Variablenname: $1, deklarierter Name für den Export: $2)
+% On most targets it is not possible to change the name under which a variable
+% is exported inside the \var{exports} statement of a library.
+% In that case, you have to specify the export name at the point where the
+% variable is declared, using the \var{export} and \var{alias} directives.
+parser_e_weak_external_not_supported=03248_E_Schwache externe Symbole werden für dieses Target nicht unterstützt
+% A "weak external" symbol is a symbol which may or may not exist at (either static
+% or dynamic) link time. This concept may not be available (or implemented yet)
+% on the current cpu/OS target.
+parser_e_forward_mismatch=03249_E_Forward Typdefinition passt nicht
+% Classes and interfaces being defined forward must have the same type
+% when being implemented. A forward interface cannot be changed into a class.
+parser_n_ignore_lower_visibility=03250_N_Die virtuelle Methode "$1" hat eine niedrigere Sichtbarkeit ($2) als die Elternklasse $3 ($4)
+% The virtual method overrides an method that is declared with a higher visibility. This might give
+% unexpected results. In case the new visibility is private than it might be that a call to inherited in a
+% new child class will call the higher visible method in a parent class and ignores the private method.
+parser_e_field_not_allowed_here=03251_E_Felder sind nach der Definition einer Methode oder Eigenschaft nicht erlaubt. Beginne vorher eine neue Sichtbarkeitssektion
+% Once a method or property has been defined in a class or object, you cannot define any fields afterwards
+% without starting a new visibility section (such as \var{public}, \var{private}, etc.). The reason is
+% that otherwise the source code can appear ambiguous to the compiler, since it is possible to use modifiers
+% such as \var{default} and \var{register} also as field names.
+parser_e_no_local_para_def=03252_E_Parameter oder Ergebnistypen können keine lokalen Typdeklarationen enthalten. Verwende eine getrennte Typdefinition in einem "type"-Block
+% In Pascal, types are not considered to be identical simply because they are semantically equivalent.
+% Two variables or parameters are only considered to be of the same type if they refer to the
+% same type definition.
+% As a result, it is not allowed to define new types inside parameter lists, because then it is impossible to
+% refer to the same type definition in the procedure headers of the interface and implementation of a unit
+% (both procedure headers would define a separate type). Keep in mind that expressions such as
+% ``file of byte'' or ``string[50]'' also define a new type.
+parser_e_abstract_and_sealed_conflict=03253_E_Konflikt zwischen ABSTRACT und SEALED
+% ABSTRACT and SEALED cannot be used together in one declaration
+parser_e_sealed_descendant=03254_E_Kann keinen Nachfahren der SEALED Klasse "$1" erzeugen
+% Sealed means that class cannot be derived by another class.
+parser_e_sealed_class_cannot_have_abstract_methods=03255_E_Eine SEALED Klasse kann keine ABSTRACT Methode haben
+% Sealed means that class cannot be derived. Therefore no one class is able to override an abstract method in a sealed class.
+parser_e_only_virtual_methods_final=03256_E_Nur virtuelle Methoden können final sein.
+% You are declaring a method as final, when it is not declared to be
+% virtual.
+parser_e_final_can_no_be_overridden=03257_E_Die finale Methode kann nicht überschrieben werden: "$1"
+% You are trying to \var{override} a virtual method of a parent class that does
+% not exist.
+parser_e_multiple_messages=03258_E_Pro Methode kann nur eine Nachricht verwendet werden.
+% It is not possible to associate multiple messages with a single method.
+parser_e_invalid_enumerator_identifier=03259_E_Ungültiger Aufzählungsbezeichner: "$1"
+% Only "MoveNext" and "Current" enumerator identifiers are supported.
+parser_e_enumerator_identifier_required=03260_E_Aufzählungsbezeichner notwendig
+% "MoveNext" or "Current" identifier must follow the \var{enumerator} modifier.
+parser_e_enumerator_movenext_is_not_valid=03261_E_Die Aufzählungs-pattern-methode MoveNext ist ungültig. Die Methode muss eine Funktion mit Rückgabetyp Boolean und ohne notwendige Argumente sein.
+% "MoveNext" enumerator pattern method must be a function with Boolean return type and no required arguments
+parser_e_enumerator_current_is_not_valid=03262_E_Die Aufzählungs-pattern-Eigenschaft "Current" ist ungültig. Die Eigenschaft benötigt einen "Getter"
+% "Current" enumerator pattern property must have a getter
+parser_e_only_one_enumerator_movenext=03263_E_Pro Klasse/Objekt ist nur eine Aufzählungsmethode "MoveNext" erlaubt
+% Class or Object can have only one enumerator MoveNext declaration.
+parser_e_only_one_enumerator_current=03264_E_Pro Klasse/Objekt ist nur eine Aufzählungseigenschaft "Current" erlaubt
+% Class or Object can have only one enumerator Current declaration.
+parser_e_for_in_loop_cannot_be_used_for_the_type=03265_E_For in Schleife kann nicht für den Typ "$1" verwendet werden
+% For in loop can be used not for all types. For example it cannot be used for the enumerations with jumps.
+parser_e_objc_requires_msgstr=03266_E_Objective-C Nachrichten erfordern, dass ihr Objective-C selector-Name mit der Direktive "message" angegeben wird
+% Objective-C messages require their Objective-C name (selector name) to be specified using the \var{message `someName:'} procedure directive.
+% While bindings to other languages automatically generate such names based on the identifier you use (by replacing
+% all underscores with colons), this is unsafe since nothing prevents an Objective-C method name to contain actual
+% colons.
+parser_e_objc_no_constructor_destructor=03267_E_Objective-C hat keine formalen Konstruktoren oder Destruktoren. Verwende die Nachrichten alloc, initXXX und dealloc
+% The Objective-C language does not have any constructors or destructors. While there are some messages with a similar
+% purpose (such as \var{init} and \var{dealloc}), these cannot be identified using automatic parsers and do not
+% guarantee anything like Pascal constructors/destructors (e.g., you have to take care of only calling ``designated''
+% inherited ``constructors''). For these reasons, we have opted to follow the standard Objective-C patterns for
+% instance creation/destruction.
+parser_e_message_string_too_long=03268_E_Der Name der Nachricht ist zu lang (max. 255 Zeichen)
+% Due to compiler implementation reasons, message names are currently limited to 255 characters.
+parser_e_objc_message_name_too_long=03269_E_Der Symbolname der Objective-C-Nachricht "$1" ist zu lang
+% Due to compiler implementation reasons, mangled message names (i.e., the symbol names used in the assembler
+% code) are currently limited to 255 characters.
+parser_h_no_objc_parent=03270_H_Definieren einer neuen Objective-C root-Klasse. Um sie von einer anderen root-Klasse abzuleiten (z.B. NSObject), gib diese als Elternklasse an
+% If no parent class is specified for an Object Pascal class, then it automatically derives from TObject.
+% Objective-C classes however do not automatically derive from NSObject, because one can have multiple
+% root classes in Objective-C. For example, in the Cocoa framework both NSObject and NSProxy are root classes.
+% Therefore, you have to explicitly define a parent class (such as NSObject) if you want to derive your
+% Objective-C class from it.
+parser_e_no_objc_published=03271_E_Objective-C Klassen können keinen Abschnitt published haben
+% In Object Pascal, ``published'' determines whether or not RTTI is generated. Since the Objective-C runtime always needs
+% RTTI for everything, this specified does not make sense for Objective-C classes.
+parser_f_need_objc=03272_F_Dieses Modul erfordert, dass der Objective-C Mode-Schalter übersetzt wird
+% This error indicates the use of Objective-C language features without an Objective-C mode switch
+% active. Enable one via the -M command line switch, or the {\$modeswitch x} directive.
+parser_e_must_use_override_objc=03273_E_Vererbte Methoden können nur in Objective-C überschrieben werden, füge "override" hinzu (Vererbte Methode ist in $1 definiert)
+parser_h_should_use_override_objc=03274_H_Vererbte Methoden können nur in Objective-C überschrieben werden, füge "override" hinzu (Vererbte Methode ist in $1 definiert)
+% It is not possible to \var{reintroduce} methods in Objective-C like in Object Pascal. Methods with the same
+% name always map to the same virtual method entry. In order to make this clear in the source code,
+% the compiler always requires the \var{override} directive to be specified when implementing overriding
+% Objective-C methods in Pascal. If the implementation is external, this rule is relaxed because Objective-C
+% does not have any \var{override}-style keyword (since it's the default and only behaviour in that language),
+% which makes it hard for automated header conversion tools to include it everywhere.
+% The type in which the inherited method is defined is explicitly mentioned, because this may either
+% be an objcclass or an objccategory.
+parser_e_objc_message_name_changed=03275_E_Der Nachrichtenname "$1" in der vererbten Klasse unterscheidet sich vom Nachrichtennamen "$2" in der aktuellen Klasse
+% An overriding Objective-C method cannot have a different message name than an inherited method. The reason
+% is that these message names uniquely define the message to the Objective-C runtime, which means that
+% giving them a different message name breaks the ``override'' semantics.
+parser_e_no_objc_unique=03276_E_Noch können eindeutige Kopien von Objective-C Typen nicht erstellt werden
+% Duplicating an Objective-C type using \var{type x = type y;} is not yet supported. You may be able to
+% obtain the desired effect using \var{type x = objcclass(y) end;} instead.
+parser_e_no_category_as_types=03277_E_Objective-C Kategorien und Object-Pascal Klassenhelfer können nicht als Typen benutzt werden
+% It is not possible to declare a variable as an instance of an Objective-C
+% category or an Object Pascal class helper. A category/class helper adds
+% methods to the scope of an existing class, but does not define a type by
+% itself. An exception of this rule is when inheriting an Object Pascal class
+% helper from another class helper.
+parser_e_no_category_override=03278_E_Kategorien überschreiben Methoden nicht, sondern ersetzen sie. "reintroduce" benutzen
+parser_e_must_use_reintroduce_objc=03279_E_Ersetzte Methoden können in Objective-C nur wieder eingeführt werden, füge "reintroduce" hinzu (Ersetzte Methode ist in $1 definiert)
+parser_h_should_use_reintroduce_objc=03280_H_Ersetzte Methoden können in Objective-C nur wieder eingeführt werden, füge "reintroduce" hinzu (Ersetzte Methode ist in $1 definiert)
+% A category replaces an existing method in an Objective-C class, rather than that it overrides it.
+% Calling an inherited method from an category method will call that method in
+% the extended class' parent, not in the extended class itself. The
+% replaced method in the original class is basically lost, and can no longer be
+% called or referred to. This behaviour corresponds somewhat more closely to
+% \var{reintroduce} than to \var{override} (although in case of \var{reintroduce}
+% in Object Pascal, hidden methods are still reachable via inherited).
+% The type in which the inherited method is defined is explicitly mentioned, because this may either
+% be an objcclass or an objccategory.
+parser_e_implements_getter_not_default_cc=03281_E_Getter für das Interface implements müssen die voreingestellte calling convention des Ziels benutzen
+% Interface getters are called via a helper in the run time library, and hence
+% have to use the default calling convention for the target (\var{register} on
+% i386 and x86\_64, \var{stdcall} on other architectures).
+parser_e_no_refcounted_typed_file=03282_E_Typisierte Dateien können keine reference-counted Typen enthalten
+% The data in a typed file cannot be of a reference counted type (such as
+% \var{ansistring} or a record containing a field that is reference counted).
+parser_e_operator_not_overloaded_2=03283_E_Ãœberladenener Operator nicht vorhanden: $2 "$1"
+% You are trying to use an overloaded operator when it is not overloaded for
+% this type.
+parser_e_operator_not_overloaded_3=03284_E_Ãœberladenener Operator nicht vorhanden: "$1" $2 "$3"
+% You are trying to use an overloaded operator when it is not overloaded for
+% this type.
+parser_e_more_array_elements_expected=03285_E_Erwarte ein weiteres Element für Array $1
+% When declaring a typed constant array, you provided to few elements to initialize the array
+parser_e_string_const_too_long=03286_E_Stringkonstante zu lang, so lange ansistrings ausgeschaltet sind
+% Only when a piece of code is compiled with ansistrings enabled (\var{\{\$H+\}}), string constants
+% longer than 255 characters are allowed.
+parser_e_invalid_univ_para=03287_E_Typ kann nicht als "univ" Parameter verwendet werden, weil seine Größe zur Zeit der Übersetzung unbekannt ist: "$1"
+% \var{univ} parameters are compatible with all values of the same size, but this
+% cannot be checked in case a parameter's size is unknown at compile time.
+parser_e_only_one_class_constructor_allowed=03288_E_In der Klasse "$1" darf nur ein Klassenkonstruktor deklariert werden
+% You are trying to declare more than one class constructor but only one class constructor can be declared.
+parser_e_only_one_class_destructor_allowed=03289_E_In der Klasse "$1" darf nur ein Klassendestruktor deklariert werden
+% You are trying to declare more than one class destructor but only one class destructor can be declared.
+parser_e_no_paras_for_class_constructor=03290_E_Ein Klassenkonstruktur darf keine Parameter haben
+% You are declaring a class constructor with a parameter list. Class constructor methods
+% cannot have parameters.
+parser_e_no_paras_for_class_destructor=03291_E_Ein Klassendestruktur darf keine Parameter haben
+% You are declaring a class destructor with a parameter list. Class destructor methods
+% cannot have parameters.
+parser_f_modeswitch_objc_required=03292_F_Dieses Konstrukt erfordert, dass der Modenschalter \{\$modeswitch objectivec1\} aktiv ist
+% Objective-Pascal constructs are not supported when \{\$modeswitch ObjectiveC1\}
+% is not active.
+parser_e_widestring_to_ansi_compile_time=03293_E_Eine Unicodechar/string Konstante zur Zeit der Ãœbersetzung nicht in eine ansi/shortstring Konstante konvertiert werden
+% It is not possible to use unicodechar and unicodestring constants in
+% constant expressions that have to be converted into an ansistring or shortstring
+% at compile time, for example inside typed constants. The reason is that the
+% compiler cannot know what the actual ansi encoding will be at run time.
+parser_e_objc_enumerator_2_0=03294_E_Objective-Pascal For-in Schleifen erfordern, dass der Modenschalter \{\$modeswitch ObjectiveC2\} aktiv ist
+% Objective-C ``fast enumeration'' support was added in Objective-C 2.0, and
+% hence the appropriate modeswitch has to be activated to expose this feature.
+% Note that Objective-C 2.0 programs require Mac OS X 10.5 or later.
+parser_e_objc_missing_enumeration_defs=03295_E_Der Kompiler findet die Typen NSFastEnumerationProtocol oder NSFastEnumerationState nicht in der Unit CocoaAll
+% Objective-C for-in loops (fast enumeration) require that the compiler can
+% find a unit called CocoaAll that contains definitions for the
+% NSFastEnumerationProtocol and NSFastEnumerationState types. If you get this
+% error, most likely the compiler is finding and loading an alternate CocoaAll
+% unit.
+parser_e_no_procvarnested_const=03296_E_Typisierte Konstanten des Typs 'procedure is nested' können nur mit NIL und globalen Prozeduren/Funktionen initialisiert werden
+% A nested procedural variable consists of two components: the address of the
+% procedure/function to call (which is always known at compile time), and also
+% a parent frame pointer (which is never known at compile time) in case the
+% procedural variable contains a reference to a nested procedure/function.
+% Therefore such typed constants can only be initialized with global
+% functions/procedures since these do not require a parent frame pointer.
+parser_f_no_generic_inside_generic=03297_F_Die Deklaration einer generischen Klasse innerhalb einer anderen generischen Klasse ist nicht erlaubt
+% At the moment, scanner supports recording of only one token buffer at the time
+% (guarded by internal error 200511173 in tscannerfile.startrecordtokens).
+% Since generics are implemented by recording tokens, it is not possible to
+% have declaration of generic class inside another generic class.
+parser_e_forward_protocol_declaration_must_be_resolved=03298_E_Vorwärts-Deklarationen des ObjC-Protokolls "$1" müssen aufgelöst sein, bevor eine ObjC-Klasse ihr folgen kann
+% An objcprotocol must be fully defined before classes can conform to it.
+% This error occurs in the following situation:
+% \begin{verbatim}
+% Type MyProtocol = objcprotoocl;
+% ChildClass = Class(NSObject,MyProtocol)
+% ...
+% end;
+% \end{verbatim}
+% where \var{MyProtocol} is declared but not defined.
+parser_e_no_record_published=03299_E_Record -Typen können keine öffentlichen Abschnitte (published sections) haben
+% Published sections can be used only inside classes.
+parser_e_no_destructor_in_records=03300_E_Destruktoren sind in Records und Helfern nicht erlaubt
+% Destructor declarations aren't allowed in records or helpers.
+parser_e_class_methods_only_static_in_records=03301_E_Klassenmethoden müssen in Records statisch sein
+% Class methods declarations aren't allowed in records without static modifier.
+% Records have no inheritance and therefore non static class methods have no sence for them.
+parser_e_no_constructor_in_records=03302_E_Konstruktoren sind in Records und Recordhelfern nicht erlaubt
+% Constructor declarations aren't allowed in records or record helpers.
+parser_e_at_least_one_argument_must_be_of_type=03303_E_Entweder das Ergebnis oder mindestens ein Parameter müssen vom Typ "$1" sein
+% It is required that either the result of the routine or at least one of its parameters be of the specified type.
+% For example class operators either take an instance of the structured type in which they are defined, or they return one.
+parser_e_cant_use_type_parameters_here=03304_E_Typ-Parameter können initialization/finalization erfordern - Sie können deshalb nicht in varianten Rekords verwendet werden
+% Type parameters may be specialized with types which (e.g. \var{ansistring}) need initialization/finalization
+% code which is implicitly generated by the compiler.
+parser_e_externals_no_section=03305_E_"external" deklarierte Variablen dürfen nicht in einer "custom section" sein
+% A section directive is not valid for variables being declared as external.
+parser_e_section_no_locals=03306_E_Nicht-statische und nicht-globale Variablen dürfen keine Direktive "section" haben
+% A variable placed in a custom section is always statically allocated so it must be either a static or global variable.
+parser_e_not_allowed_in_helper=03307_E_"$1" ist in Helfertypen nicht erlaubt
+% Some directives and specifiers like "virtual", "dynamic", "override" aren't
+% allowed inside helper types in mode ObjFPC (they are ignored in mode Delphi),
+% because they have no meaning within helpers. Also "abstract" isn't allowed in
+% either mode.
+parser_e_no_class_constructor_in_helpers=03308_E_Klassenkonstruktoren sind in Helfern nicht erlaubt
+% Class constructor declarations aren't allowed in helpers.
+parser_e_inherited_not_in_record=03309_E_"inherited" ist in einem Record nicht erlaubt
+% As records don't suppport inheritance the use of "inherited" is prohibited for
+% these as well as for record helpers (in mode "Delphi" only).
+parser_e_no_types_in_local_anonymous_records=03310_E_Typ-Deklarationen sind in lokalen oder anonymen Records nicht erlaubt
+% Records with types must be defined globally. Types cannot be defined inside records which are defined in a
+% procedure or function or in anonymous records.
+parser_e_duplicate_implements_clause=03311_E_Zweifacher "implements"-Term für das Interface "$1"
+% A class may delegate an interface using the "implements" clause only to a single property. Delegating it multiple times
+% is a error.
+parser_e_mapping_no_implements=03312_E_Das Interface "$1" kann nicht durch "$2" delegiert werden. Die Methode ist bereits aufgelöst
+% Method resolution clause maps a method of an interface to a method of the current class. Therefore the current class
+% has to implement the interface directly. Delegation is not possible.
+parser_e_implements_no_mapping=03313_E_Das Interface "$1" kann keine Methoden-Auflösung haben, "$2" delegiert es bereits
+% Method resoulution is only possible for interfaces that are implemented directly, not by delegation.
+%
+% \end{description}
+# EndOfTeX
+
+#
+# Type Checking
+#
+# 04103 is the last used one
+#
+% \section{Type checking errors}
+% This section lists all errors that can occur when type checking is
+% performed.
+% \begin{description}
+type_e_mismatch=04000_E_Typen passen nicht zusammen
+% This can happen in many cases:
+% \begin{itemize}
+% \item The variable you're assigning to is of a different type than the
+% expression in the assignment.
+% \item You are calling a function or procedure with parameters that are
+% incompatible with the parameters in the function or procedure definition.
+% \end{itemize}
+type_e_incompatible_types=04001_E_Inkompatible Typen: Habe "$1" erhalten, aber "$2" erwartet
+% There is no conversion possible between the two types.
+% Another possiblity is that they are declared in different
+% declarations:
+% \begin{verbatim}
+% Var
+% A1 : Array[1..10] Of Integer;
+% A2 : Array[1..10] Of Integer;
+%
+% Begin
+% A1:=A2; { This statement also gives this error. It
+% is due to the strict type checking of Pascal }
+% End.
+% \end{verbatim}
+type_e_not_equal_types=04002_E_Typen sind verschieden bei $1 und $2
+% The types are not equal.
+type_e_type_id_expected=04003_E_Typbezeichner erwartet
+% The identifier is not a type, or you forgot to supply a type identifier.
+type_e_variable_id_expected=04004_E_Variablenbezeichner erwartet
+% This happens when you pass a constant to a \var{Inc} var or \var{Dec}
+% procedure. You can only pass variables as arguments to these functions.
+type_e_integer_expr_expected=04005_E_Integer-Ausdruck erwartet, aber "$1" erhalten
+% The compiler expects an expression of type integer, but gets a different
+% type.
+type_e_boolean_expr_expected=04006_E_Booleschen Ausdruck erwartet, aber "$1" erhalten
+% The expression must be a boolean type. It should be return \var{True} or
+% \var{False}.
+type_e_ordinal_expr_expected=04007_E_Ganzzahliger Ausdruck erwartet
+% The expression must be of ordinal type, i.e., maximum a \var{Longint}.
+% This happens, for instance, when you specify a second argument
+% to \var{Inc} or \var{Dec} that doesn't evaluate to an ordinal value.
+type_e_pointer_type_expected=04008_E_Zeigertyp erwartet, aber "$1" erhalten
+% The variable or expression isn't of the type \var{pointer}. This
+% happens when you pass a variable that isn't a pointer to \var{New}
+% or \var{Dispose}.
+type_e_class_type_expected=04009_E_Klassentyp erwartet, aber "$1" erhalten
+% The variable or expression isn't of the type \var{class}. This happens
+% typically when
+% \begin{enumerate}
+% \item The parent class in a class declaration isn't a class.
+% \item An exception handler (\var{On}) contains a type identifier that
+% isn't a class.
+% \end{enumerate}
+type_e_cant_eval_constant_expr=04011_E_Kann konstanten Ausdruck nicht auswerten
+% This error can occur when the bounds of an array you declared do
+% not evaluate to ordinal constants.
+type_e_set_element_are_not_comp=04012_E_Set-Elemente sind nicht kompatibel
+% You are trying to perform an operation on two sets, when the set element types
+% are not the same. The base type of a set must be the same when taking the
+% union.
+type_e_set_operation_unknown=04013_E_Operation für Sets nicht implementiert
+% several binary operations are not defined for sets.
+% These include: \var{div}, \var{mod}, \var{**}, \var{>=} and \var{<=}.
+% The last two may be defined for sets in the future.
+type_w_convert_real_2_comp=04014_W_Automatische Typumwandlung von Fliesskommatyp nach COMP (=integer mit 64 bit)
+% An implicit type conversion from a real type to a \var{comp} is
+% encountered. Since \var{Comp} is a 64 bit integer type, this may indicate
+% an error.
+type_h_use_div_for_int=04015_H_Verwenden sie DIV um ein Integer-Ergebnis zu erhalten
+% When hints are on, then an integer division with the '/' operator will
+% produce this message, because the result will then be of type real.
+type_e_strict_var_string_violation=04016_E_Stringtypen müssen im "$V+"-Modus exakt übereinstimmen
+% When compiling in \var{\{\$V+\}} mode, the string you pass as a parameter
+% should be of the exact same type as the declared parameter of the procedure.
+type_e_succ_and_pred_enums_with_assign_not_possible=04017_E_Succ oder Pred kann nicht auf Aufzählungen mit Zuweisungen angewendet werden
+% If you declare an enumeration type which has C-like assignments
+% in it, such as in the following:
+% \begin{verbatim}
+% Tenum = (a,b,e:=5);
+% \end{verbatim}
+% then you cannot use the \var{Succ} or \var{Pred} functions with this enumeration.
+type_e_cant_read_write_type=04018_E_Kann Variablen dieses Typs nicht lesen oder schreiben
+% You are trying to \var{read} or \var{write} a variable from or to a
+% file of type text, which doesn't support that variable's type.
+% Only integer types, reals, pchars and strings can be read from or
+% written to a text file. Booleans can only be written to text files.
+type_e_no_readln_writeln_for_typed_file=04019_E_Kann ReadLn und WriteLn nicht bei typisierten Dateien verwenden
+% \var{readln} and \var{writeln} are only allowed for text files.
+type_e_no_read_write_for_untyped_file=04020_E_Kann Read und Write nicht bei untypisierten Dateien verwenden
+% \var{read} and \var{write} are only allowed for text or typed files.
+type_e_typeconflict_in_set=04021_E_Typkonflikt zwischen den Elementen des Sets
+% There is at least one set element which is of the wrong type, i.e. not of
+% the set type.
+type_w_maybe_wrong_hi_lo=04022_W_lo/hi(dword/qword) gibt oberes/unteres Word/DWord zurück
+% \fpc supports an overloaded version of \var{lo/hi} for \var{longint/dword/int64/qword}
+% which returns the lower/upper word/dword of the argument. \tp always uses
+% a 16 bit \var{lo/hi} which always returns bits 0..7 for \var{lo} and the
+% bits 8..15 for \var{hi}. If you want the \tp behavior you have
+% to type cast the argument to a \var{word} or \var{integer}.
+type_e_integer_or_real_expr_expected=04023_E_Integer- oder Real-Ausdruck erwartet
+% The first argument to \var{str} must be a real or integer type.
+type_e_wrong_type_in_array_constructor=04024_E_Falscher Typ "$1" im Array-Konstruktor
+% You are trying to use a type in an array constructor which is not
+% allowed.
+type_e_wrong_parameter_type=04025_E_Inkompatible Typen für Argument Nr. #$1: habe $2 erhalten, aber $3 erwartet
+% You are trying to pass an invalid type for the specified parameter.
+type_e_no_method_and_procedure_not_compatible=04026_E_Methode (Variable) und Prozedur (Variable) sind nicht kompatibel
+% You can't assign a method to a procedure variable or a procedure to a
+% method pointer.
+type_e_wrong_math_argument=04027_E_Unzulässige Konstante an interne Algebrafunktion übergeben
+% The constant argument passed to a \var{ln} or \var{sqrt} function is out of
+% the definition range of these functions.
+type_e_no_addr_of_constant=04028_E_Von Konstanten kann keine Adresse bestimmt werden
+% It's not possible to get the address of a constant, because they
+% aren't stored in memory, you can try making it a typed constant. This error
+% can also be displayed if you try to pass a property to a var parameter.
+type_e_argument_cant_be_assigned=04029_E_An das Argument kann nichts zugewiesen werden
+% Only expressions which can be on the left side of an
+% assignment can be passed as call by reference arguments.
+%
+% Remark: Properties can be used on the left side of an assignment,
+% nevertheless they cannot be used as arguments.
+type_e_cannot_local_proc_to_procvar=04030_E_Kann lokale Prozedur/Funktion nicht an Prozedurvariable zuweisen
+% It's not allowed to assign a local procedure/function to a
+% procedure variable, because the calling convention of a local procedure/function is
+% different. You can only assign local procedure/function to a void pointer.
+type_e_no_assign_to_addr=04031_E_Kann einer Adresse keine Werte zuweisen
+% It's not allowed to assign a value to an address of a variable,constant,
+% procedure or function. You can try compiling with -So if the identifier
+% is a procedure variable.
+type_e_no_assign_to_const=04032_E_Kann einer Konstanten keine Werte zuweisen
+% It's not allowed to assign a value to a variable which is declared
+% as a const. This is normally a parameter declared as const. To allow
+% changing the value, pass the parameter by value, or a parameter by reference
+% (using var).
+type_e_array_required=04033_E_Array Typ notwendig
+% If you are accessing a variable using an index '[<x>]' then
+% the type must be an array. In FPC mode a pointer is also allowed.
+type_e_interface_type_expected=04034_E_Interface Typ erwartet, aber "$1" erhalten
+% The compiler expected to encounter an interface type name, but got something else.
+% The following code would produce this error:
+% \begin{verbatim}
+% Type
+% TMyStream = Class(TStream,Integer)
+% \end{verbatim}
+type_h_mixed_signed_unsigned=04035_H_Mischen von signed Ausdrücken und Longwords ergibt ein 64bit Ergebnis
+% If you divide (or calculate the modulus of) a signed expression by a longword (or vice versa),
+% or if you have overflow and/or range checking turned on and use an arithmetic
+% expression (+, -, *, div, mod) in which both signed numbers and longwords appear,
+% then everything has to be evaluated in 64-bit arithmetic which is slower than normal
+% 32-bit arithmetic. You can avoid this by typecasting one operand so it
+% matches the result type of the other one.
+type_w_mixed_signed_unsigned2=04036_W_Mischen von signed Ausdrücken und kardinalen Typen hier kann einen Bereichsprüfungsfehler verursachen
+% If you use a binary operator (and, or, xor) and one of
+% the operands is a longword while the other one is a signed expression, then,
+% if range checking is turned on, you may get a range check error because in
+% such a case both operands are converted to longword before the operation is
+% carried out. You can avoid this by typecasting one operand so it
+% matches the result type of the other one.
+type_e_typecast_wrong_size_for_assignment=04037_E_Typecast hat verschiedene Grössen ($1 -> $2) in der Zuweisung
+% Type casting to a type with a different size is not allowed when the variable is
+% used in an assignment.
+type_e_array_index_enums_with_assign_not_possible=04038_E_enums mit Zuweisungen können nicht als Array-Index verwendet werden
+% When you declared an enumeration type which has C-like
+% assignments, such as in the following:
+% \begin{verbatim}
+% Tenum = (a,b,e:=5);
+% \end{verbatim}
+% you cannot use it as the index of an array.
+type_e_classes_not_related=04039_E_Klassen- oder Objekttypen "$1" and "$2" sind nicht verwandt
+% There is a typecast from one class or object to another while the class/object
+% are not related. This will probably lead to errors.
+type_w_classes_not_related=04040_W_Klassentypen "$1" und "$2" sind nicht verwandt
+% There is a typecast from one class to another while the classes
+% are not related. This will probably lead to errors.
+type_e_class_or_interface_type_expected=04041_E_Klassen- oder Interface-Typ erwartet, aber "$1" erhalten
+% The compiler expected a class or interface name, but got another type or identifier.
+type_e_type_is_not_completly_defined=04042_E_Typ "$1" ist nicht vollständig definiert
+% This error occurs when a type is not complete: i.e. a pointer type which points to
+% an undefined type.
+type_w_string_too_long=04043_W_String literal hat mehr Zeichen als short string length
+% The size of the constant string, which is assigned to a shortstring,
+% is longer than the maximum size of the shortstring (255 characters).
+type_w_comparison_always_false=04044_W_Wegen der Bereiche der Konstanten und des Ausdrucks könnte das Vergleichsergebnis immer falsch sein
+% There is a comparison between a constant and an expression where the constant is out of the
+% valid range of values of the expression. Because of type promotion, the statement will always evaluate to
+% false. Explicitly typecast the constant or the expression to the correct range to avoid this warning
+% if you think the code is correct.
+type_w_comparison_always_true=04045_W_Wegen der Bereiche der Konstanten und des Ausdrucks könnte das Vergleichsergebnis immer richtig sein
+% There is a comparison between a constant and an expression where the constant is out of the
+% valid range of values of the expression. Because of type promotion, the statement will always evaluate to
+% true. Explicitly typecast the constant or the expression to the correct range to avoid this warning
+% if you think the code is correct.
+type_w_instance_with_abstract=04046_W_Konstruktion der Klasse "$1" mit der abstrakten Methode "$2"
+% An instance of a class is created which contains non-implemented abstract
+% methods. This will probably lead to a runtime error 211 in the code if that
+% routine is ever called. All abstract methods should be overridden.
+type_h_in_range_check=04047_H_Der linke Operand des IN Operators sollte byte Grösse haben
+% The left operand of the \var{in} operator is not an ordinal or enumeration which fits
+% within 8 bits. This may lead to range check errors. The \var{in} operator
+% currently only supports a left operand which fits within a byte. In the case of
+% enumerations, the size of an element of an enumeration can be controlled with
+% the \var{\{\$PACKENUM\}} or \var{\{\$Zn\}} switches.
+type_w_smaller_possible_range_check=04048_W_Unpassende Typgrössen, Gefahr des Datenverlusts oder Bereichsprüfungsfehlers
+% There is an assignment to a smaller type than the source type. This means that
+% this may cause a range-check error, or may lead to possible loss of data.
+type_h_smaller_possible_range_check=04049_H_Unpassende Typgrössen, Gefahr des Datenverlusts oder Bereichsprüfungsfehlers
+% There is an assignment to a smaller type than the source type. This means that
+% this may cause a range-check error, or may lead to possible loss of data.
+type_e_cant_take_address_of_abstract_method=04050_E_Die Adresse einer abstrakten Methode kann nicht verwendet werden
+% An abstract method has no body, so the address of an abstract method can't be taken.
+type_e_assignment_not_allowed=04051_E_Zuweisungen auf formale Parameter und offene Arrays sind nicht möglich
+% You are trying to assign a value to a formal (untyped var, const or out)
+% parameter, or to an open array.
+type_e_constant_expr_expected=04052_E_Konstanter Ausdruck erwartet
+% The compiler expects an constant expression, but gets a variable expression.
+type_e_operator_not_supported_for_types=04053_E_Operation "$1" wird für die Typen "$2" und "$3" nicht unterstützt
+% The operation is not allowed for the supplied types.
+type_e_illegal_type_conversion=04054_E_Illegale Typ-Konversion: "$1" nach "$2"
+% When doing a type-cast, you must take care that the sizes of
+ the variable and
+% the destination type are the same.
+type_h_pointer_to_longint_conv_not_portable=04055_H_Konversion zwischen ordinalen Typen und Zeigern ist nicht portierbar
+% If you typecast a pointer to a longint (or vice-versa), this code will not compile
+% on a machine using 64 bits addressing.
+type_w_pointer_to_longint_conv_not_portable=04056_W_Konversion zwischen ordinalen Typen und Zeigern ist nicht portierbar
+% If you typecast a pointer to an ordinal type of a different size (or vice-versa), this can
+% cause problems. This is a warning to help in finding the 32-bit specific code where cardinal/longint is used
+% to typecast pointers to ordinals. A solution is to use the ptrint/ptruint types instead.
+type_e_cant_choose_overload_function=04057_E_Kann nicht bestimmen, welche der überladenen Funktionen aufgerufen werden soll
+% You're calling overloaded functions with a parameter that doesn't correspond
+% to any of the declared function parameter lists. e.g. when you have declared
+% a function with parameters \var{word} and \var{longint}, and then you call
+% it with a parameter which is of type \var{integer}.
+type_e_illegal_count_var=04058_E_Loop-Variable muss einen ordinalen Typ haben
+% The type of a \var{for} loop variable must be an ordinal type.
+% Loop variables cannot be reals or strings.
+type_w_double_c_varargs=04059_W_Der konstante Wert vom Typ real wird für ein C Variablen-Argument zu double konvertiert. Ergänze eine explizite Typ-Konversion (typecast), um das zu verhindern
+% In C, constant real values are double by default. For this reason, if you
+% pass a constant real value to a variable argument part of a C function, FPC
+% by default converts this constant to double as well. If you want to prevent
+% this from happening, add an explicit typecast around the constant.
+type_e_class_or_cominterface_type_expected=04060_E_Class oder COM interface Typ erwartet, statt dessen "$1" erhalten
+% Some operators, such as the AS operator, are only applicable to classes or COM interfaces.
+type_e_no_const_packed_array=04061_E_Konstante packed Arrays werden noch nicht unterstützt
+% You cannot declare a (bit)packed array as a typed constant.
+type_e_got_expected_packed_array=04062_E_Inkompatibler Typ für Argument $1: Erhielt "$2" erwartete "(Bit)Packed Array"
+% The compiler expects a (bit)packed array as the specified parameter.
+type_e_got_expected_unpacked_array=04063_E_Inkompatibler Typ für Argument $1: Erhielt "$2" erwartete "(not packed) Array"
+% The compiler expects a regular (i.e., not packed) array as the specified parameter.
+type_e_no_packed_inittable=04064_E_Elemente von packed Arrays können nicht von einem Typ sein, der initialisiert werden muss
+% Support for packed arrays of types that need initialization
+% (such as ansistrings, or records which contain ansistrings) is not yet implemented.
+type_e_no_const_packed_record=04065_E_Konstante packed Records und Objekte werden noch nicht unterstützt
+% You cannot declare a (bit)packed array as a typed constant at this time.
+type_w_untyped_arithmetic_unportable=04066_W_Arithmetik "$1" mit typenlosem Pointer ist nicht portierbar nach {$T+}, schlage typecast vor
+% Addition/subtraction from an untyped pointer may work differently in \var{\{\$T+\}}.
+% Use a typecast to a typed pointer.
+type_e_cant_take_address_of_local_subroutine=04076_E_Die Address einer Subroutine, die als local markiert ist, kann nicht verwendet werden
+% The address of a subroutine marked as local can't be taken.
+type_e_cant_export_local=04077_E_Eine Subroutine, die aus einer Unit als local markiert ist, kann nicht exportiert werden
+% A subroutine marked as local can't be exported from a unit.
+type_e_not_automatable=04078_E_Typ "$1" ist nicht "automatable"
+% Only byte, integer, longint, smallint, currency, single, double, ansistring,
+% widestring, tdatetime, variant, olevariant, wordbool and all interfaces are automatable.
+type_h_convert_add_operands_to_prevent_overflow=04079_H_Konvertierung des Operanden "$1" vor der Addition könnte Überlauf Fehler verhindern
+% Adding two types can cause overflow errors. Since you are converting the result to a larger type, you
+% could prevent such errors by converting the operands to this type before doing the addition.
+type_h_convert_sub_operands_to_prevent_overflow=04080_H_Konvertierung des Operanden "$1" vor der Subtraktion könnte Überlauf Fehler verhindern
+% Subtracting two types can cause overflow errors. Since you are converting the result to a larger type, you
+% could prevent such errors by converting the operands to this type before doing the subtraction.
+type_h_convert_mul_operands_to_prevent_overflow=04081_H_Konvertierung des Operanden "$1" vor der Multiplikation könnte Überlauf Fehler verhindern
+% Multiplying two types can cause overflow errors. Since you are converting the result to a larger type, you
+% could prevent such errors by converting the operands to this type before doing the multiplication.
+type_w_pointer_to_signed=04082_W_Die Konvertierung von Pointern in einen Integertyp mit Vorzeichen kann zu falschen Ergebnissen bei Vergleichen und zu Bereichsüberschreitungen führen; verwenden sie statt dessen besser einen Typ ohne Vorzeichen
+% The virtual address space on 32-bit machines runs from \$00000000 to \$ffffffff.
+% Many operating systems allow you to allocate memory above \$80000000.
+% For example both \windows and \linux allow pointers in the range \$0000000 to \$bfffffff.
+% If you convert pointers to signed types, this can cause overflow and range check errors,
+% but also \$80000000 < \$7fffffff. This can cause random errors in code like "if p>q".
+type_e_interface_has_no_guid=04083_E_Interface Typ $1 hat keine gültige GUID
+% When applying the as-operator to an interface or class, the desired interface (i.e. the right operand of the
+% as-operator) must have a valid GUID.
+type_e_invalid_objc_selector_name=04084_E_Ungültiger Objective-C-Selector-Name "$1"
+% An Objective-C selector cannot be empty, must be a valid identifier or a single colon,
+% and if it contains at least one colon it must also end in one.
+type_e_expected_objc_method_but_got=04085_E_Erwartete eine Objective-C-Methode, erhielt aber $1
+% A selector can only be created for Objective-C methods, not for any other kind
+% of procedure/function/method.
+type_e_expected_objc_method=04086_E_Erwartete eine Objective-C-Methode, oder den Namen einer konstanten Methode
+% A selector can only be created for Objective-C methods, either by specifying
+% the name using a string constant, or by using an Objective-C method identifier
+% that is visible in the current scope.
+type_e_no_type_info=04087_E_Für diesen Typ steht keine Typ-Information zu Verfügung
+% Type information is not generated for some types, such as enumerations with gaps
+% in their value range (this includes enumerations whose lower bound is different
+% from zero).
+type_e_ordinal_or_string_expr_expected=04088_E_Ausdruck mit ordinalem Typ oder Zeichenkette erwartet
+% The expression must be an ordinal or string type.
+type_e_string_expr_expected=04089_E_Ausdruck mit Zeichenkette erwartet
+% The expression must be a string type.
+type_w_zero_to_nil=04090_W_Konvertiere 0 zu NIL
+% Use NIL rather than 0 when initialising a pointer.
+type_e_protocol_type_expected=04091_E_Objective-C Protokolltyp erwartet, erhielt aber "$1"
+% The compiler expected a protocol type name, but found something else.
+type_e_objc_type_unsupported=04092_E_Der Typ "$1" wird nicht für die Verwendung mit der Objective-C Laufzeitumgebung unterstützt.
+% Objective-C makes extensive use of run time type information (RTTI). This format
+% is defined by the maintainers of the run time and can therefore not be adapted
+% to all possible Object Pascal types. In particular, types that depend on
+% reference counting by the compiler (such as ansistrings and certain kinds of
+% interfaces) cannot be used as fields of Objective-C classes, cannot be
+% directly passed to Objective-C methods, and cannot be encoded using \var{objc\_encode}.
+type_e_class_or_objcclass_type_expected=04093_E_Klasse oder Objective-C Klasse als Typ erwartet, erhielt aber "$1"
+% It is only possible to create class reference types of \var{class} and \var{objcclass}
+type_e_objcclass_type_expected=04094_E_Objective-C Klasse als Typ erwartet
+% The compiler expected an \var{objcclass} type
+type_w_procvar_univ_conflicting_para=04095_W_Erzwungener univ Parameter Typ in einer prozeduralen Variablen kann einen Absturz oder SpeicherKorruption verursachen: $1 auf $2
+% \var{univ} parameters are implicitly compatible with all types of the same size,
+% also in procedural variable definitions. That means that the following code is
+% legal, because \var{single} and \var{longint} have the same size:
+% \begin{verbatim}
+% {$mode macpas}
+% Type
+% TIntProc = procedure (l: univ longint);
+%
+% procedure test(s: single);
+% begin
+% writeln(s);
+% end;
+%
+% var
+% p: TIntProc;
+% begin
+% p:=test;
+% p(4);
+% end.
+% \end{verbatim}
+% This code may however crash on platforms that pass integers in registers and
+% floating point values on the stack, because then the stack will be unbalanced.
+% Note that this warning will not flagg all potentially dangerous situations.
+% when \var{test} returns.
+type_e_generics_cannot_reference_itself=04096_E_Typ-Parameter bei der Spezialisation von Generics können den aktuel spezialisierten Typ nicht referenzieren
+% Recursive specializations of generics like \var{Type MyType = specialize MyGeneric<MyType>;} are not possible.
+type_e_type_parameters_are_not_allowed_here=04097_E_Typ-Parameter sind für nicht-generische Klassen/Record/Objekte Prozeduren und Funktionen nicht erlaubt
+% Type parameters are only allowed for methods of generic classes, records or objects
+type_e_generic_declaration_does_not_match=04098_E_Die generische Deklaration von "$1" unterscheidet sich vom der vorherigen Deklaration
+% Generic declaration does not match the previous declaration
+type_e_helper_type_expected=04099_E_Helfertyp erwartet
+% The compiler expected a \var{class helper} type.
+type_e_record_type_expected=04100_E_Recordtyp erwartet
+% The compiler expected a \var{record} type.
+type_e_class_helper_must_extend_subclass=04101_E_Abgeleitete Klassenhelfer müssen eine Unterklasse von "$1" oder die Klasse selbst erweitern
+% If a class helper inherits from another class helper the extended class must
+% extend either the same class as the parent class helper or a subclass of it
+type_e_record_helper_must_extend_same_record=04102_E_Abgeleitete Recordhelfer müssen "$1" erweitern
+% If a record helper inherits from another record helper it must extend the same
+% record that the parent record helper extended.
+type_e_procedures_return_no_value=04103_E_Ungültige Zuweisung, eine Prozedur gibt keinen Wert zurück
+% This error occurs when one tries to assign the result of a procedure or destructor call.
+% A procedure or destructor returns no value so this is not
+% possible.
+%
+% \end{description}
+# EndOfTeX
+
+#
+# Symtable
+#
+# 05084 is the last used one
+#
+% \section{Symbol handling}
+% This section lists all the messages that concern the handling of symbols.
+% This means all things that have to do with procedure and variable names.
+% \begin{description}
+sym_e_id_not_found=05000_E_Bezeichner "$1" nicht gefunden
+% The compiler doesn't know this symbol. Usually happens when you misspell
+% the name of a variable or procedure, or when you forget to declare a
+% variable.
+sym_f_internal_error_in_symtablestack=05001_F_Interner Fehler in SymTableStack()
+% An internal error occurred in the compiler; If you encounter such an error,
+% please contact the developers and try to provide an exact description of
+% the circumstances in which the error occurs.
+sym_e_duplicate_id=05002_E_Doppelter Bezeichner "$1"
+% The identifier was already declared in the current scope.
+sym_h_duplicate_id_where=05003_H_Bezeichner ist bereits definiert in $1 in Zeile $2
+% The identifier was already declared in a previous scope.
+sym_e_unknown_id=05004_E_Unbekannter Bezeichner "$1"
+% The identifier encountered hasn't been declared, or is used outside the
+% scope where it's defined.
+sym_e_forward_not_resolved=05005_E_Forward-Deklaration "$1" nicht gefunden
+% This can happen in two cases:
+% \begin{itemize}
+% \item You declare a function in the \var{interface} part, or
+% with a \var{forward} directive, but do not implement it.
+% \item You reference a type which isn't declared in the current \var{type}
+% block.
+% \end{itemize}
+sym_e_error_in_type_def=05007_E_Fehler in Typdefinition
+% There is an error in your definition of a new array type.
+% One of the range delimiters in an array declaration is erroneous.
+% For example, \var{Array [1..1.25]} will trigger this error.
+sym_e_forward_type_not_resolved=05009_E_Forward-Typ "$1" nicht gefunden
+% The compiler encountered an unknown type.
+sym_e_only_static_in_static=05010_E_Nur statische Variablen können in statischen oder äusseren Methoden verwendet werden
+% A static method of an object can only access static variables.
+sym_f_type_must_be_rec_or_class=05012_F_Record- oder Klassen-Typ erwartet
+% The variable or expression isn't of the type \var{record} or \var{class}.
+sym_e_no_instance_of_abstract_object=05013_E_Instanzen von Klassen oder Objekten mit abstrakten Methoden sind unzulässig
+% You are trying to generate an instance of a class which has an abstract
+% method that wasn't overridden.
+sym_w_label_not_defined=05014_W_Label "$1" nicht definiert
+% A label was declared, but not defined.
+sym_e_label_used_and_not_defined=05015_E_Label "$1" benutzt aber nicht definiert
+% A label was declared and used, but not defined.
+sym_e_ill_label_decl=05016_E_Ungültige Label-Deklaration
+% This error should never happen; it occurs if a label is defined outside a
+% procedure or function.
+sym_e_goto_and_label_not_supported=05017_E_GOTO und LABEL werden nicht unterstützt (verwenden Sie den Schalter -Sg)
+% You must use the -Sg switch to compile a program which has \var{label}s
+% and \var{goto} statements. By default, \var{label} and \var{goto} aren't
+% supported.
+sym_e_label_not_found=05018_E_Label nicht gefunden
+% A \var{goto label} was encountered, but the label wasn't declared.
+sym_e_id_is_no_label_id=05019_E_Bezeichner ist kein Label
+% The identifier specified after the \var{goto} isn't of type label.
+sym_e_label_already_defined=05020_E_Label ist bereits definiert
+% You are defining a label twice. You can define a label only once.
+sym_e_ill_type_decl_set=05021_E_Ungültige Typdeklaration von Set-Elementen
+% The declaration of a set contains an invalid type definition.
+sym_e_class_forward_not_resolved=05022_E_Forward-Klassendefinition nicht gefunden: $1
+% You declared a class, but you didn't implement it.
+sym_n_unit_not_used=05023_H_Unit "$1" wird von "$2" nicht verwendet
+% The unit referenced in the \var{uses} clause is not used.
+sym_h_para_identifier_not_used=05024_H_Parameter nicht verwendet: $1
+% This is a warning. The identifier was declared (locally or globally) but
+% wasn't used (locally or globally).
+sym_n_local_identifier_not_used=05025_N_Lokale Variable nicht verwendet: $1
+% You have declared, but not used, a variable in a procedure or function
+% implementation.
+sym_h_para_identifier_only_set=05026_H_Werte-Parameter "$1" wurde zugewiesen, aber nie verwendet
+% The identifier was declared (locally or globally) and
+% assigned to, but is not used (locally or globally) after the assignment.
+sym_n_local_identifier_only_set=05027_N_Lokale Variable "$1" wurde zugewiesen, aber nicht verwendet
+% The variable in a procedure or function implementation is declared and
+% assigned to, but is not used after the assignment.
+sym_h_local_symbol_not_used=05028_H_Lokales $1-Element "$2" wird nicht verwendet
+% A local symbol is never used.
+sym_n_private_identifier_not_used=05029_N_Privates Feld $1.$2 wird nie verwendet
+% The indicated private field is defined, but is never used in the code.
+sym_n_private_identifier_only_set=05030_N_Privates Feld $1.$2 wurde zugewiesen, aber nie verwendet
+% The indicated private field is declared and assigned to, but never read.
+sym_n_private_method_not_used=05031_N_Private Methode $1.$2 wird nie verwendet
+% The indicated private method is declared but is never used in the code.
+sym_e_set_expected=05032_E_Mengentyp erwartet
+% The variable or expression isn't of type \var{set}. This happens in an
+% \var{in} statement.
+sym_w_function_result_not_set=05033_W_Funktionsergebnis scheint nicht gesetzt zu sein
+% You can get this warning if the compiler thinks that a function return
+% value is not set. This will not be displayed for assembler procedures,
+% or procedures that contain assembler blocks.
+sym_w_wrong_C_pack=05034_W_Typ "$1" ist im aktuellen Record mit C-Packing nicht korrekt ausgerichtet
+% Arrays with sizes not multiples of 4 will be wrongly aligned
+% for C structures.
+sym_e_illegal_field=05035_E_Unbekannter Record-Feldbezeichner $1
+% The field doesn't exist in the record definition.
+sym_w_uninitialized_local_variable=05036_W_Lokale Variable "$1" wird verwendet, bevor ihr ein Wert zugewiesen wurde
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. it appears in the right-hand side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assignment).
+sym_w_uninitialized_variable=05037_W_Variable "$1" scheint nicht initialisiert worden zu sein
+% These messages are displayed if the compiler thinks that a variable will
+% be used (i.e. it appears in the right-hand side of an expression) when it
+% wasn't initialized first (i.e. appeared in the left-hand side of an
+% assignment).
+sym_e_id_no_member=05038_E_Bezeichener verweist nicht auf ein Element: $1
+% This error is generated when an identifier of a record,
+% field or method is accessed while it is not defined.
+sym_h_param_list=05039_H_Deklaration gefunden: $1
+% You get this when you use the \var{-vh} switch.In the case of an overloaded procedure
+% not being found. Then all candidate overloaded procedures are
+% listed, with their parameter lists.
+sym_e_segment_too_large=05040_E_Datensegment zu gross (max. 2GB)
+% You get this when you declare a data element whose size exceeds the
+% prescribed limit (2 Gb on 80386+/68020+ processors).
+sym_e_no_matching_implementation_found=05042_E_Keine passende Implementation der Interface Methode "$1" gefunden
+% There was no matching method found which could implement the interface
+% method. Check argument types and result type of the methods.
+sym_w_deprecated_symbol=05043_W_Symbol "$1" ist veraltet
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{deprecated} is used. Deprecated symbols may no longer
+% be available in newer versions of the unit / library. Use of this symbol
+% should be avoided as much as possible.
+sym_w_non_portable_symbol=05044_W_Symbol "$1" ist nicht portierbar
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{platform} is used. This symbol's value, use
+% and availability is platform specific and should not be used
+% if the source code must be portable.
+sym_w_non_implemented_symbol=05055_W_Symbol "$1" ist nicht implementiert
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{unimplemented} is used. This symbol is defined,
+% but is not yet implemented on this specific platform.
+sym_e_cant_create_unique_type=05056_E_Von diesem Typ kann kein eindeutiger Typ deklariert werden
+% Only simple types like ordinal, float and string types are supported when
+% redefining a type with \var{type newtype = type oldtype;}.
+sym_h_uninitialized_local_variable=05057_H_Die Variable "$1" scheint nicht initialisiert zu sein
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. it appears in the right-hand side of an expression) when it
+% was not initialized first (i.e. it did not appear in the left-hand side of an
+% assignment).
+sym_h_uninitialized_variable=05058_H_Die Variable "$1" scheint nicht initialisiert zu sein
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. it appears in the right-hand side of an expression) when it
+% was not initialized first (i.e. t did not appear in the left-hand side of an
+% assignment).
+sym_w_function_result_uninitialized=05059_W_Die Ergebnisvariable der Funktion scheint nicht initialisiert zu sein
+% This message is displayed if the compiler thinks that the function result
+% variable will be used (i.e. it appears in the right-hand side of an expression)
+% before it is initialized (i.e. before it appeared in the left-hand side of an
+% assignment).
+sym_h_function_result_uninitialized=05060_H_Die Ergebnisvariable der Funktion scheint nicht initialisiert zu sein
+% This message is displayed if the compiler thinks that the function result
+% variable will be used (i.e. it appears in the right-hand side of an expression)
+% before it is initialized (i.e. it appears in the left-hand side of an
+% assignment)
+sym_w_identifier_only_read=05061_W_Die Variable "$1" wird gelesen, obwohl ihr aber noch kein Wert zugewiesen wurde
+% You have read the value of a variable, but nowhere assigned a value to
+% it.
+sym_h_abstract_method_list=05062_H_Abstrakte Method "$1" gefunden
+% When getting a warning about constructing a class/object with abstract methods
+% you get this hint to assist you in finding the affected method.
+sym_w_experimental_symbol=05063_W_Symbol "$1" ist experimentell
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{experimental} is used. Experimental symbols
+% might disappear or change semantics in future versions. Usage of this symbol
+% should be avoided as much as possible.
+sym_w_forward_not_resolved=05064_W_Forward Deklaration "$1" wird nicht aufgelöst und deshalb als extern angenommen
+% This happens if you declare a function in the \var{interface} of a unit in macpas mode,
+% but do not implement it.
+sym_w_library_symbol=05065_W_Symbol "$1" gehört zu einer Bibliothek
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{library} is used. Library symbols may not be
+% available in other libraries.
+sym_w_deprecated_symbol_with_msg=05066_W_Symbol "$1" ist veraltet: "$2"
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{deprecated} is used. Deprecated symbols may no longer
+% be available in newer versions of the unit / library. Use of this symbol
+% should be avoided as much as possible.
+sym_e_no_enumerator=05067_E_Kann keinen Zähler für den Typ "$1" finden
+% This means that compiler cannot find an apropriate enumerator to use in the for-in loop.
+% To create an enumerator you need to defind an operator enumerator or add a public or published
+% GetEnumerator method to the class or object definition.
+sym_e_no_enumerator_move=05068_E_Kann keine Methode "MoveNext" in der Aufzählung "$1" finden
+% This means that compiler cannot find a public MoveNext method with the Boolean return type in
+% the enumerator class or object definition.
+sym_e_no_enumerator_current=05069_E_Kann keine Eigenschaft "Current" in der Aufzählung "$1" finden
+% This means that compiler cannot find a public Current property in the enumerator class or object
+% definition.
+sym_e_objc_para_mismatch=05070_E_Die Anzahl der deklarierten Parameter und die Anzahl der Doppelpunkte in der Nachrichtenzeichenkette stimmen nicht überein
+% In Objective-C, a message name automatically contains as many colons as parameters.
+% In order to prevent mistakes when specifying the message name in FPC, the compiler
+% checks whether this is also the case here. Note that in case of messages taking a
+% variable number of arguments translated to FPC via an \var{array of const} parameter,
+% this final \var{array of const} parameter is not counted. Neither are the hidden
+% \var{self} and \var{\_cmd} parameters.
+sym_n_private_type_not_used=05071_N_Privater Typ "$1.$2" wird nie benutzt
+% The indicated private type is declared but is never used in the code.
+sym_n_private_const_not_used=05072_N_Private Konstante "$1.$2" wird nie benutzt
+% The indicated private const is declared but is never used in the code.
+sym_n_private_property_not_used=05073_N_Private Eigenschaft "$1.$2" wird nie benutzt
+% The indicated private property is declared but is never used in the code.
+sym_w_deprecated_unit=05074_W_Unit "$1" ist veraltet
+% This means that a unit which is
+% declared as \var{deprecated} is used. Deprecated units may no longer
+% be available in newer versions of the library. Use of this unit
+% should be avoided as much as possible.
+sym_w_deprecated_unit_with_msg=05075_W_Unit "$1" ist veraltet: "$2"
+% This means that a unit which is
+% declared as \var{deprecated} is used. Deprecated units may no longer
+% be available in newer versions of the library. Use of this unit
+% should be avoided as much as possible.
+sym_w_non_portable_unit=05076_W_Unit "$1" ist plattformabhängig
+% This means that a unit which is
+% declared as \var{platform} is used. This unit use
+% and availability is platform specific and should not be used
+% if the source code must be portable.
+sym_w_library_unit=05077_W_Unit "$1" gehört zu einer Bibliothek
+% This means that a unit which is
+% declared as \var{library} is used. Library units may not be
+% available in other libraries.
+sym_w_non_implemented_unit=05078_W_Unit "$1" ist nicht implementiert
+% This means that a unit which is
+% declared as \var{unimplemented} is used. This unit is defined,
+% but is not yet implemented on this specific platform.
+sym_w_experimental_unit=05079_W_Unit "$1" ist experimentell
+% This means that a unit which is
+% declared as \var{experimental} is used. Experimental units
+% might disappear or change semantics in future versions. Usage of this unit
+% should be avoided as much as possible.
+sym_e_objc_formal_class_not_resolved=05080_E_Die vollständige Definition der formal deklarierten ObjC-Klasse "$1" fehlt in diesem Geltungsbereich
+% Objecive-C classes can be imported formally, without using the the unit in which it is fully declared.
+% This enables making forward references to such classes and breaking circular dependencies amongst units.
+% However, as soon as you wish to actually do something with an entity of this class type (such as
+% access one of its fields, send a message to it, or use it to inherit from), the compiler requires the full definition
+% of the class to be in scope.
+sym_e_interprocgoto_into_init_final_code_not_allowed=05081_E_Gotos in die 'initialization'- oder 'finalization'-Blöcke einer Unit sind nicht erlaubt
+% Gotos into initialization or finalization blockse of units are not allowed.
+sym_e_external_class_name_mismatch1=05082_E_Ungültiger externer Name "$1" für die formale Klasse "$2"
+sym_e_external_class_name_mismatch2=05083_E_Hierhin muss die vollständige Klassendefinition mit externem Namen "$1"
+% When a class is declared using a formal external definition, the actual external
+% definition (if any) must specify the same external name as the formal definition
+% (since both definitions refer to the same actual class type).
+sym_w_library_overload=05084_W_Möglicher Bibliothekenkonflikt: Das Symbol "$1" aus Bibliothek "$2" wurde auch in Bibliothek "$3" gefunden
+% Some OS do not have library specific namespaces, for those
+% OS, the function declared as "external 'libname' name 'funcname'",
+% the 'libname' part is only a hint, funcname might also be loaded
+% by another library. This warning appears if 'funcname' is used twice
+% with two different library names.
+%
+% \end{description}
+# EndOfTeX
+
+#
+# Codegenerator
+#
+# 06052 is the last used one
+#
+% \section{Code generator messages}
+% This section lists all messages that can be displayed if the code
+% generator encounters an error condition.
+% \begin{description}
+cg_e_parasize_too_big=06009_E_Grösse der Parameterliste übersteigt 65535 Bytes
+% The I386 processor limits the parameter list to 65535 bytes. (The \var{RET}
+% instruction causes this).
+cg_e_file_must_call_by_reference=06012_E_Dateitypen müssen VAR Parameter sein
+% You cannot specify files as value parameters, i.e., they must always be
+% declared \var{var} parameters.
+cg_e_cant_use_far_pointer_there=06013_E_Die Verwendung eines FAR-Zeigers ist in dieser Art nicht erlaubt
+% Free Pascal doesn't support far pointers, so you cannot take the address of
+% an expression which has a far reference as a result. The \var{mem} construct
+% has a far reference as a result, so the following code will produce this
+% error:
+% \begin{verbatim}
+% var p : pointer;
+% ...
+% p:=@mem[a000:000];
+% \end{verbatim}
+cg_e_dont_call_exported_direct=06015_E_Mit EXPORT deklarierte Funktionen können nicht aufgerufen werden
+% No longer in use.
+cg_w_member_cd_call_from_method=06016_W_Möglicherweise unzulässiger Aufruf eines Konstruktors oder Destruktors (passt nicht in diesen Kontext)
+% The compiler detected that a constructor or destructor is called within a
+% a method. This will probably lead to problems, since constructors / destructors
+% require parameters on entry.
+cg_n_inefficient_code=06017_N_Uneffiziente Programmierung
+% You construction seems dubious to the compiler.
+cg_w_unreachable_code=06018_W_Code wird niemals ausgeführt
+% You specified a loop which will never be executed. Example:
+% \begin{verbatim}
+% while false do
+% begin
+% {.. code ...}
+% end;
+% \end{verbatim}
+cg_e_cant_call_abstract_method=06020_E_Abstrakte Methoden können nicht direkt aufgerufen werden
+% You cannot call an abstract method directly. Instead, you must call an
+% overriding child method, because an abstract method isn't implemented.
+cg_d_register_weight=06027_DL_Register $1 Gewichtung $2 $3
+% Debugging message. Shown when the compiler considers a variable for
+% keeping in the registers.
+cg_d_stackframe_omited=06029_DL_Stackframe wird ausgelassen
+% Some procedure/functions do not need a complete stack-frame, so it is omitted.
+% This message will be displayed when the {-vd} switch is used.
+cg_e_unable_inline_object_methods=06031_E_Objektmethoden können nicht Inline sein
+% You cannot have inlined object methods.
+cg_e_unable_inline_procvar=06032_E_Procvar-Aufrufe können nicht Inline sein
+% A procedure with a procedural variable call cannot be inlined.
+cg_e_no_code_for_inline_stored=06033_E_Kein Code für Inline-Prozedur gespeichert
+% The compiler couldn't store code for the inline procedure.
+cg_e_can_access_element_zero=06035_E_Auf Element Null von Ansi/Wide- oder Longstring kann nicht zugegriffen werden, benutzen Sie stattdessen (Set)Length
+% You should use \var{setlength} to set the length of an ansi/wide/longstring
+% and \var{length} to get the length of such string type.
+cg_e_cannot_call_cons_dest_inside_with=06037_E_Konstruktoren und Destruktoren können in diesem Kontext nicht aufgerufen werden
+% Inside a \var{With} clause you cannot call a constructor or destructor for the
+% object you have in the \var{with} clause.
+cg_e_cannot_call_message_direct=06038_E_Kann Messagehandler-Methode nicht direkt aufrufen
+% A message method handler method can't be called directly if it contains an
+% explicit \var{Self} argument.
+cg_e_goto_inout_of_exception_block=06039_E_Sprung in- oder aus dem Exceptionblock heraus
+% It is not allowed to jump in or outside of an exception block like \var{try..finally..end;}.
+% For example, the following code will produce this error:
+
+% \begin{verbatim}
+% label 1;
+%
+% ...
+%
+% try
+% if not(final) then
+% goto 1; // this line will cause an error
+% finally
+% ...
+% end;
+% 1:
+% ...
+% \end{verbatim}
+cg_e_control_flow_outside_finally=06040_E_Kontrollfluss-Anweisungen sind in einem Finally-Block nicht erlaubt
+% It isn't allowed to use the control flow statements \var{break},
+% \var{continue} and \var{exit}
+% inside a finally statement. The following example shows the problem:
+% \begin{verbatim}
+% ...
+% try
+% p;
+% finally
+% ...
+% exit; // This exit ISN'T allowed
+% end;
+% ...
+%
+% \end{verbatim}
+% If the procedure \var{p} raises an exception the finally block is
+% executed. If the execution reaches the exit, it's unclear what to do:
+% exit the procedure or search for another exception handler.
+cg_w_parasize_too_big=06041_W_Grösse der Parameter überschreitet die Grenze für bestimmte CPUs
+% This indicates that you are declaring more than 64K of parameters, which
+% might not be supported on other processor targets.
+cg_w_localsize_too_big=06042_W_Grösse der lokalen Variablen überschreitet die Grenze für bestimmte CPUs
+% This indicates that you are declaring more than 32K of local variables, which
+% might not be supported on other processor targets.
+cg_e_localsize_too_big=06043_E_Grösse der lokalen Variablen überschreitet die unterstützte Grenze
+% This indicates that you are declaring more than 32K of local variables, which
+% is not supported by this processor.
+cg_e_break_not_allowed=06044_E_BREAK nicht zulässig
+% You're trying to use \var{break} outside a loop construction.
+cg_e_continue_not_allowed=06045_E_CONTINUE nicht zulässig
+% You're trying to use \var{continue} outside a loop construction.
+cg_f_unknown_compilerproc=06046_F_Unbekannte Compiler-Prozedur "$1". Überprüfe, ob die korrekte Laufzeit-Bibliothek verwendet wird.
+% The compiler expects that the runtime library contains certain subroutines. If you see this error
+% and you didn't change the runtime library code, it's very likely that the runtime library
+% you're using doesn't match the compiler in use. If you changed the runtime library this error means
+% that you removed a subroutine which the compiler needs for internal use.
+cg_f_unknown_system_type=06047_F_Systemtyp "$1" konnte nicht gefunden werden. Überprüfe ob die korrekte Laufzeit-Bibliothek verwendet wird.
+% The compiler expects that the runtime library contains certain type definitions. If you see this error
+% and you didn't change the runtime library code, it's very likely that the runtime library
+% you're using doesn't match the compiler in use. If you changed the runtime library this error means
+% that you removed a type which the compiler needs for internal use.
+cg_h_inherited_ignored=06048_H_Geerbter Aufruf einer abstrakten Methode ignoriert
+% This message appears only in Delphi mode when you call an abstract method
+% of a parent class via \var{inherited;}. The call is then ignored.
+cg_e_goto_label_not_found=06049_E_Goto Label "$1": Das Label ist nicht definiert oder wurde bei der Optimierung entfernt
+% The label used in the goto definition is not defined or optimized away by the
+% unreachable code elemination.
+cg_f_unknown_type_in_unit=06050_F_Kann den Typ "$1" nicht in der Unit "$2" finden. Überprüfe, ob die korrekte Laufzeit-Bibliothek verwendet wird
+% The compiler expects that the runtime library contains certain type definitions. If you see this error
+% and you didn't change the runtime library code, it's very likely that the runtime library
+% you're using doesn't match the compiler in use. If you changed the runtime library this error means
+% that you removed a type which the compiler needs for internal use.
+cg_e_interprocedural_goto_only_to_outer_scope_allowed=06051_E_Interprozedurale gotos sind nur in äußere Subroutines erlaubt
+% Gotos between subroutines are only allowed if the goto jumps from an inner to an outer subroutine or
+% from a subroutine to the main program
+cg_e_labels_cannot_defined_outside_declaration_scope=06052_E_ Label müssen im selben Bereich definiert werden, in dem sie deklariert werden
+% In ISO mode, labels must be defined in the same scope as they are declared.
+cg_e_goto_across_procedures_with_exceptions_not_allowed=06053_E_Eine Prozedur, die explizite oder implizite Excpetion Frames enthält, darf nicht mit einem goto verlassen werden
+% Non-local gotos might not be used to leave procedures using exceptions either implicitly or explicitly. Procedures
+% which use automated types like ansistrings or class constructurs are affected by this too.
+%
+% \end{description}
+# EndOfTeX
+
+#
+# Assembler reader
+#
+# 07110 is the last used one
+#
+asmr_d_start_reading=07000_DL_Starte $1 Stil Assembler Parsen
+% This informs you that an assembler block is being parsed
+asmr_d_finish_reading=07001_DL_Beende $1 Stil Assembler Parsen
+% This informs you that an assembler block has finished.
+asmr_e_none_label_contain_at=07002_E_Nicht-Label Bezeichner enthält @
+% A identifier which isn't a label can't contain a @.
+asmr_e_building_record_offset=07004_E_Fehler beim Ermitteln des Recordoffsets
+% There has an error occured while building the offset of a record/object
+% structure, this can happend when there is no field specified at all or
+% an unknown field identifier is used.
+asmr_e_offset_without_identifier=07005_E_OFFSET ohne Bezeicner verwendet
+% You can only use OFFSET with an identifier. Other syntaxes aren't
+% supported
+asmr_e_type_without_identifier=07006_E_TYPE verwendet ohne Bezeichner
+% You can only use TYPE with an identifier. Other syntaxes aren't
+% supported
+asmr_e_no_local_or_para_allowed=07007_E_Lokale Variable oder Parameter können hier nicht verwendet werden
+% You can't use a local variable or parameter here, mostly because the
+% addressing of locals and parameters is done using the %ebp register so the
+% address can't be get directly.
+asmr_e_need_offset=07008_E_Hier muss OFFSET verwendet werden
+% You need to use OFFSET <id> here to get the address of the identifier.
+asmr_e_need_dollar=07009_E_Hier muss "$" verwendet werden
+% You need to use $<id> here to get the address of the identifier.
+asmr_e_cant_have_multiple_relocatable_symbols=07010_E_Verwendung von mehreren verschiebbaren Symbolen nicht möglich
+% You can't have more than one relocatable symbol (variable/typed constant)
+% in one argument.
+asmr_e_only_add_relocatable_symbol=07011_E_Verschiebbares Symbol kann nur addiert werden
+% Relocatable symbols (variable/typed constant) can't be used with other
+% operators. Only addition is allowed.
+asmr_e_invalid_constant_expression=07012_E_Ungültiger Konstantenausdruck
+% There is an error in the constant expression.
+asmr_e_relocatable_symbol_not_allowed=07013_E_Verschiebbares Symbol ist nicht zulässig
+% You can't use a relocatable symbol (variable/typed constant) here.
+asmr_e_invalid_reference_syntax=07014_E_Ungültige Verweis-Syntax
+% There is an error in the reference.
+asmr_e_local_para_unreachable=07015_E_Sie können "$1" von diesem Code aus nicht erreichen
+% You cannot read directly the value of a local variable or parameter
+% of a higher level procedure in assembler code (except for
+% local assembler code without parameter nor locals).
+asmr_e_local_label_not_allowed_as_ref=07016_E_Lokale Symbole/Labels sind nicht als Referenz zulässig
+% You can't use local symbols/labels as references
+asmr_e_wrong_base_index=07017_E_Ungültige Verwendung von Basis- und Index-Registern
+% There is an error with the base and index register, they are
+% probably incorrect
+asmr_w_possible_object_field_bug=07018_W_Möglicher Fehler bei Objektfeld-Behandlung
+% Fields of objects or classes can be reached directly in normal or objfpc
+% modes but TP and Delphi modes treat the field name as a simple offset.
+asmr_e_wrong_scale_factor=07019_E_Falscher Skalierungsfaktor angegeben
+% The scale factor given is wrong, only 1,2,4 and 8 are allowed
+asmr_e_multiple_index=07020_E_Mehrfache Verwendung fon Index-Registern
+% You are trying to use more than one index register
+asmr_e_invalid_operand_type=07021_E_Ungültiger Operandentyp
+% The operand type doesn't match with the opcode used
+asmr_e_invalid_string_as_opcode_operand=07022_E_Ungülitge Zeichenkette als Opcode-Operand: $1
+% The string specified as operand is not correct with this opcode
+asmr_w_CODE_and_DATA_not_supported=07023_W_@CODE und @DATA werden nicht unterstützt
+% @CODE and @DATA are unsupported and are ignored.
+asmr_e_null_label_ref_not_allowed=07024_E_Null-Label-Bezug nicht möglich
+asmr_e_expr_zero_divide=07025_E_Division durch Null in Assembler-Ausdruck
+% There is a division by zero in a constant expression
+asmr_e_expr_illegal=07026_E_Ungültiger Ausdruck
+% There is an illegal expression in a constant expression
+asmr_e_escape_seq_ignored=07027_E_Escape-Sequenz ignoriert: $1
+% There is a C-styled string, but the escape sequence in the string
+% is unknown, and is therefore ignored
+asmr_e_invalid_symbol_ref=07028_E_Ungültige Symbolverwendung
+asmr_w_fwait_emu_prob=07029_W_FWAIT kann Emulationsprobleme mit emu387 verursachen
+asmr_w_fadd_to_faddp=07030_W_$1 ohne Operand wurde in $1P übersetzt
+asmr_w_enter_not_supported_by_linux=07031_W_Der ENTER-Befehl wird vom Linux-Kernel nicht unterstützt
+% ENTER instruction can generate a stack page fault that is not
+% caught correctly by the i386 Linux page handler.
+asmr_w_calling_overload_func=07032_W_Aufruf einer überladenen Funktion in Assembler
+% There is a call to an overloaded method in the assembler block,
+% this might be the sign there is a problem
+asmr_e_unsupported_symbol_type=07033_E_Nicht unterstützter Symboltyp für Operand
+asmr_e_constant_out_of_bounds=07034_E_Wert der Konstante ausserhalb des zulässigen Bereichs
+asmr_e_error_converting_decimal=07035_E_Fehler beim Umwandeln in Dezimal $1
+% A constant decimal value does not have the correct syntax
+asmr_e_error_converting_octal=07036_E_Fehler beim Umwandeln in Oktal $1
+% A constant octal value does not have the correct syntax
+asmr_e_error_converting_binary=07037_E_Fehler beim Umwandeln in Binär $1
+% A constant binary value does not have the correct syntax
+asmr_e_error_converting_hexadecimal=07038_E_Fehler beim Umwandeln in Hexadezimal $1
+% A constant hexadecimal value does not have the correct syntax
+asmr_h_direct_global_to_mangled=07039_H_$1 übersetzt nach $2
+asmr_w_direct_global_is_overloaded_func=07040_W_$1 ist einer überladenen Funktion zugeordnet
+asmr_e_cannot_use_SELF_outside_a_method=07041_E_Kann SELF nicht ausserhalb einer Methode verwenden
+% There is a reference to the \var{self} symbol while it is not
+% allowed. \var{self} can only be referenced inside methods
+asmr_e_cannot_use_OLDEBP_outside_nested_procedure=07042_E_Kann OLDEBP ausserhalb einer verschachtelten Prozedur nicht verwenden
+% There is a reference to the \var{oldebp} symbol while it is not
+% allowed. \var{oldebp} can only be referenced inside nested routines
+asmr_e_void_function=07043_W_Prozeduren können keinen Wert im Assembler-Code zurückliefern
+% Trying to return a value while in a procedure. A procedure
+% does not have any return value
+asmr_e_SEG_not_supported=07044_E_SEG nicht unterstützt
+asmr_e_size_suffix_and_dest_dont_match=07045_E_Grössensuffix und Ziel- oder Quellgrösse passen nicht zusammen
+% The register size and the opcode size suffix don't match. This is
+% probably an error in the assembler statement
+asmr_w_size_suffix_and_dest_dont_match=07046_W_Grössensuffix und Ziel- oder Quellgrösse passen nicht zusammen
+% The register size and the opcode size suffix don't match. This is
+% probably an error in the assembler statement
+asmr_e_syntax_error=07047_E_Assembler Syntaxfehler
+% There is an assembler syntax error
+asmr_e_invalid_opcode_and_operand=07048_E_Ungültige Kombination von Opcode und Operanden
+% The opcode cannot be used with this type of operand
+asmr_e_syn_operand=07049_E_Assembler Syntaxfehler im Operanden
+asmr_e_syn_constant=07050_E_Assembler Syntaxfehler in Konstanten
+asmr_e_invalid_string_expression=07051_E_Ungültiger Stringausdruck
+asmr_w_const32bit_for_address=07052_W_Konstante mit Symbol $1 für Adresse erzeugt, die kein Pointer ist
+% A constant expression represents an address which does not fit
+% into a pointer. The address is probably incorrect
+asmr_e_unknown_opcode=07053_E_Unbekannter Opcode $1
+% This opcode is not known
+asmr_e_invalid_or_missing_opcode=07054_E_Ungültiger oder fehlender Opcode
+asmr_e_invalid_prefix_and_opcode=07055_E_Ungültige Kombination von Prefix und Opcode: $1
+asmr_e_invalid_override_and_opcode=07056_E_Ungültige Kombination von Override und Opcode: $1
+asmr_e_too_many_operands=07057_E_Zu viele Operanden in der Zeile
+% There are too many operands for this opcode. Check your
+% assembler syntax
+asmr_w_near_ignored=07058_W_NEAR ignoriert
+asmr_w_far_ignored=07059_W_FAR ignoriert
+asmr_e_dup_local_sym=07060_E_Doppelters lokales Symbol $1
+asmr_e_unknown_local_sym=07061_E_Undefiniertes lokales Symbol $1
+asmr_e_unknown_label_identifier=07062_E_Unbekannter Label-Bezeichner $1
+asmr_e_invalid_register=07063_E_Ungültiger Registername
+% There is an unknown register name used as operand.
+asmr_e_invalid_fpu_register=07064_E_Ungültiger Name für Fliesskommaregister
+% There is an unknown register name used as operand.
+asmr_w_modulo_not_supported=07066_W_Modulo nicht unterstützt
+asmr_e_invalid_float_const=07067_E_Ungültige Fliesskommakonstante $1
+% The floating point constant declared in an assembler block is
+% invalid.
+asmr_e_invalid_float_expr=07068_E_Ungültiger Fliesskommaausdruck
+% The floating point expression declared in an assembler block is
+% invalid.
+asmr_e_wrong_sym_type=07069_E_Falscher Symboltyp
+asmr_e_cannot_index_relative_var=07070_E_Kann lokale Variable oder Parameter nicht mit Register indizieren
+% Trying to index using a base register a symbol which is already relative
+% to a register. This is not possible, and will probably lead to crashes.
+asmr_e_invalid_seg_override=07071_E_Ungültiger Segmentoverride-Ausdruck
+asmr_w_id_supposed_external=07072_W_Bezeichner $1 ist vermutlich External
+% There is a reference to an undefined symbol. This will not result
+% in an error, since the symbol might be external, but may cause
+% problems at link time if the symbol is not defined anywhere.
+asmr_e_string_not_allowed_as_const=07073_E_Strings sind als Konstanten unzulässig
+% Character strings are not allowed as constants.
+asmr_e_no_var_type_specified=07074_E_Typ der Variablen nicht angegeben
+% The syntax expects a type idenfitifer after the dot, but
+% none was found.
+asmr_w_assembler_code_not_returned_to_text=07075_E_Assemblercode kehrt nicht zum Text zurück
+% There was a directive in the assembler block to change sections,
+% but there is a missing return to the text section at the end
+% of the assembler block. This might cause errors during link time.
+asmr_e_not_directive_or_local_symbol=07076_E_Keine Direktive oder lokales Symbol $1
+% This symbol is unknown.
+asmr_w_using_defined_as_local=07077_E_Verwendung eines definierten Namens als lokales Label
+asmr_e_dollar_without_identifier=07078_E_Dollarzeichen wird ohne Bezeichner verwendet
+% A constant expression has an identifier which does not start with
+% the $ symbol.
+asmr_w_32bit_const_for_address=07079_W_32-Bit-Konstante für Adresse erzeugt
+% A constant was used as an address. This is probably an error,
+% since using absolute addresses will probably not work.
+asmr_n_align_is_target_specific=07080_N_.align ist abhängig von Zielplattform, verwende .balign oder .p2align
+% Using the .align directive is platform specific, and its meaning will vary
+% from one platform to another.
+asmr_e_cannot_access_field_directly_for_parameters=07081_E_Kann für Parameter nicht direkt auf Felder zugreifen
+% You should load the parameter first into a register and then access the
+% fields using that register.
+asmr_e_cannot_access_object_field_directly=07082_E_Kann auf Felder von Objekten/Klassen nicht direkt zugreifen
+% You should load the self pointer first into a register and then access the
+% fields using the register as base. By default the self pointer is available
+% in the esi register on i386.
+asmr_e_unable_to_determine_reference_size=07083_E_Grösse nicht spezifiziert und auch keine Möglichkeit die Grösse der Operanden zu bestimmen
+% You should specify explicitly a size for the reference, because
+% the compiler is unable to determine what size (byte,word,dword,etc.) it
+% should use for the reference.
+asmr_e_cannot_use_RESULT_here=07084_E_RESULT kann in dieser Funktion nicht verwendet werden
+% Some functions which return complex types cannot use the \var{result}
+% keyword.
+asmr_w_adding_explicit_args_fXX=07086_W_"$1" ohne Operand übersetzt in "$1 %st,%st(1)"
+asmr_w_adding_explicit_first_arg_fXX=07087_W_"$1 %st(n)" übersetzt in "$1 %st,%st(n)"
+asmr_w_adding_explicit_second_arg_fXX=07088_W_"$1 %st(n)" übersetzt in "$1 %st(n),%st"
+asmr_e_invalid_char_smaller=07089_E_Das Zeichen < ist hier nicht erlaubt
+% The shift operator requires the << characters. Only one
+% of those characters was found.
+asmr_e_invalid_char_greater=07090_E_Das Zeichen > ist hier nicht erlaubt
+% The shift operator requires the >> characters. Only one
+% of those characters was found.
+asmr_w_align_not_supported=07093_W_ALIGN wird nicht unterstützt
+asmr_e_no_inc_and_dec_together=07094_E_Inc und Dec können nicht gemeinsam vorkommen
+% Trying to use an increment and a decrement within the same
+% opcode on the 680x0. This is impossible.
+asmr_e_invalid_reg_list_in_movem=07095_E_Ungültige Registerliste für movem
+% Trying to use the \var{movem} opcode with invalid registers
+% to save or restore.
+asmr_e_invalid_reg_list_for_opcode=07096_E_Ungültige Registerliste für diesen opcode
+asmr_e_higher_cpu_mode_required=07097_E_Höherer cpu Modus notwendig ($1)
+% Trying to use an instruction which is not supported in the current
+% cpu mode. Use a higher cpu generation to be able to use this
+% opcode in your assembler block
+asmr_w_unable_to_determine_reference_size_using_dword=07098_W_Grösse nicht spezifiziert und auch keine Möglichkeit die Grösse der Operanden zu bestimmen. Es wird DWORD als Voreinstellung verwendet
+% You should specify explicitly a size for the reference, because
+% the compiler is unable to determine what size (byte,word,dword,etc.) it
+% should use for the reference. This warning is only used in Delphi mode where
+% it falls back to use DWORD as default.
+asmr_e_illegal_shifterop_syntax=07099_E_Syntax Fehler beim Analysieren eines shifter Operanden
+% ARM only; ARM assembler supports a so called shifter operand. The used syntax isn't
+% a valid shifter operand. Example for an operation with shifter operand:
+% \begin{verbatim}
+% asm
+% orr r2,r2,r2,lsl #8
+% end;
+% \end{verbatim}
+asmr_e_packed_element=07100_E_Die Adresse der packed Komponente ist nicht an einer Byte Grenze
+% Packed components (record fields and array elements) may start at an arbitrary
+% bit inside a byte. On CPU which do not support bit-addressable memory (which
+% includes all currently supported CPUs by FPC) you will therefore get an error
+% message when trying to index arrays with elements whose size is not a multiple
+% of 8 bits. The same goes for accessing record fields with such an address.
+% multiple of 8 bits.
+asmr_w_unable_to_determine_reference_size_using_byte=07101_W_Grösse nicht angegeben und kann auch nicht aus der Grösse der Operanden bestimmt werden. Verwende BYTE als Voreinstellung
+% You should specify explicitly a size for the reference, because
+% the compiler is unable to determine what size (byte,word,dword,etc.) it
+% should use for the reference. This warning is only used in Delphi mode where
+% it falls back to use BYTE as default.
+asmr_w_no_direct_ebp_for_parameter=07102_W_Die Verwendung von +offset(%ebp) für Parameter ist hier ungültig
+% Using direct 8(%ebp) reference for function/procedure parameters is invalid
+% if parameters are in registers.
+asmr_w_direct_ebp_for_parameter_regcall=07103_W_Die Verwendung von +offset(%ebp) ist nicht mit der regcall Konvention kompatibel
+% Using direct 8(%ebp) reference for function/procedure parameters is invalid
+% if parameters are in registers.
+asmr_w_direct_ebp_neg_offset=07104_W_Die Verwendung von -offset(%ebp) wird für den Zugriff auf lokale Variablen nicht empfohlen
+% Using -8(%ebp) to access a local variable is not recommended
+asmr_w_direct_esp_neg_offset=07105_W_Verwendung von -offset(%esp); Zugriff kann einen Crash oder Datenverlust auslösen
+% Using -8(%esp) to access a local stack is not recommended, as
+% this stack portion can be overwritten by any function calls or interrupts.
+asmr_e_no_vmtoffset_possible=07106_E_VMTOffset muss in Kombination mit einer virtuellen Methode verwendet werden; "$1" ist aber nicht virtuell
+% Only virtual methods have VMT offsets
+asmr_e_need_pic_ref=07107_E_Erzeuge eigentlich PIC, aber die Referenz ist nicht PIC-sicher
+% The compiler has been configured to generate position-independent code
+% (PIC), but there are position-dependent references in the current
+% handwritten assembler instruction.
+asmr_e_mixing_regtypes=07108_E_Alle Register in einem Registerset müssen in T und Breite übereinstimmen
+% Instructions on the ARM architecture that take a register set as argument require that all registers
+% in this set are of the same kind (e.g., integer, vfp) and width (e.g., single precision, double precision).
+asmr_e_empty_regset=07109_E_Ein Registerset kann nicht leer sein
+% Instructions on the ARM architecture that take a register set as argument require that such a set
+% contains at least one register.
+asmr_w_useless_got_for_local=07110_W_@GOTPCREL ist nutzlos und bei lokalen Symbole möglicherweise gefährlich
+% The use of @GOTPCREL supposes an extra indirection that is
+% not present if the symbol is local, which might lead to wrong asembler code
+
+#
+# Assembler/binary writers
+#
+# 08022 is the last used one
+#
+asmw_f_too_many_asm_files=08000_F_Zu viele Assembler-Dateien
+% With smartlinking enabled, there are too many assembler
+% files generated. Disable smartlinking.
+asmw_f_assembler_output_not_supported=08001_F_Gewählte Assemblerausgabe wird nicht unterstützt
+asmw_f_comp_not_supported=08002_F_Comp nicht unterstützt
+asmw_f_direct_not_supported=08003_F_Direct nicht unterstützt für binäres Schreiben
+% Direct assembler mode is not supported for binary writers.
+asmw_e_alloc_data_only_in_bss=08004_E_Allozieren von Daten ist nur in "bss"-Abschnitten zulässig
+asmw_f_no_binary_writer_selected=08005_F_Kein Binärschreiber ausgewählt
+asmw_e_opcode_not_in_table=08006_E_Asm: Opcode $1 nicht in Tabelle enthalten
+asmw_e_invalid_opcode_and_operands=08007_E_Asm: $1 ungültige Kombination von Opcode und Operanden
+asmw_e_16bit_not_supported=08008_E_Asm: 16-Bit-Verweise werden nicht unterstützt
+asmw_e_invalid_effective_address=08009_E_Asm: Ungültige effektive Adresse
+asmw_e_immediate_or_reference_expected=08010_E_Asm: Konstanter Ausdruck oder Referenz erwartet
+asmw_e_value_exceeds_bounds=08011_E_Asm: $1 Wert überschreitet Grenzen $2
+asmw_e_short_jmp_out_of_range=08012_E_Asm: "Short jump" ist ausserhalb des Bereichs $1
+asmw_e_undefined_label=08013_E_Asm: Undefiniertes Label: $1
+asmw_e_comp_not_supported=08014_E_Asm: Comp wird für dieses Ziel nicht unterstützt
+asmw_e_extended_not_supported=08015_E_Asm: Extended Typ wird für dieses Ziel nicht unterstützt
+asmw_e_duplicate_label=08016_E_Asm: Doppeltes Label $1
+asmw_e_redefined_label=08017_E_Asm: Neu definiertes Label $1
+asmw_e_first_defined_label=08018_E_Asm: First beginnt hier
+asmw_e_invalid_register=08019_E_Asm: Ungültiges Register $1
+asmw_e_16bit_32bit_not_supported=08020_E_Asm: 16 oder 32 Bit Referenzen werden nicht unterstützt
+asmw_e_64bit_not_supported=08021_E_Asm: 64 Bit Operanden werden nicht unterstützt
+asmw_e_bad_reg_with_rex=08022_E_Asm: AH,BH,CH oder DH können nicht in einer Instruktion verwendt werden, die den Prefix REX benötigt
+% x86_64 only: instruction encoding of this platform does not allow using
+% 8086 high byte registers (AH,BH,CH or DH) together with REX prefix in a single instruction.
+% The REX prefix is required whenever the instruction operand size is 64 bits, or
+% when it uses one of extended x86_64 registers (R8-R15 or XMM8-XMM15).
+
+#
+# Executing linker/assembler
+#
+# 09032 is the last used one
+#
+# BeginOfTeX
+%
+% \section{Errors of assembling/linking stage}
+% This section lists errors that occur when the compiler is processing the
+% command line or handling the configuration files.
+% \begin{description}
+exec_w_source_os_redefined=09000_W_Quellbetriebssystem wurde neu definiert
+% The source operating system is redefined.
+exec_i_assembling_pipe=09001_I_Assembliere (pipe) $1
+% Assembling using a pipe to an external assembler.
+exec_d_cant_create_asmfile=09002_E_Kann Assemblerdatei nicht erzeugen: $1
+% The mentioned file can't be created. Check if you have
+% access permissions to create this file.
+exec_e_cant_create_objectfile=09003_E_Kann Objektdatei nicht erzeugen: $1
+% The mentioned file can't be created. Check if you have
+% got access permissions to create this file.
+exec_e_cant_create_archivefile=09004_E_Kann Archivdatei nicht erzeugen: $1
+% The mentioned file can't be created. Check if you have
+% access permissions to create this file.
+exec_e_assembler_not_found=09005_E_Assembler $1 nicht gefunden, schalte um zu externem Assemblieren
+% The assembler program was not found. The compiler will produce a script that
+% can be used to assemble and link the program.
+exec_t_using_assembler=09006_T_Benutze Assembler: $1
+% An informational message saying which assembler is being used.
+exec_e_error_while_assembling=09007_E_Fehler beim Assemblieren des Exitcodes $1
+% There was an error while assembling the file using an external assembler.
+% Consult the documentation of the assembler tool to find out more information
+% on this error.
+exec_e_cant_call_assembler=09008_E_Assembler kann nicht aufgerufen werden, Fehler $1 schalte um zu externem Assemblieren
+% An error occurred when calling an external assembler. The compiler will produce a script that
+% can be used to assemble and link the program.
+exec_i_assembling=09009_I_Assembliere $1
+% An informational message stating which file is being assembled.
+exec_i_assembling_smart=09010_I_Assembliere mit Smartlinking $1
+% An informational message stating which file is being assembled using smartlinking.
+exec_w_objfile_not_found=09011_W_Objekt $1 nicht gefunden, Linken kann fehlschlagen!
+% One of the object files is missing, and linking will probably fail.
+% Check your paths.
+exec_w_libfile_not_found=09012_W_Bibliothek $1 nicht gefunden, Linken kann fehlschlagen!
+% One of the library file is missing, and linking will probably fail.
+% Check your paths.
+exec_e_error_while_linking=09013_E_Fehler beim Linken
+% Generic error while linking.
+exec_e_cant_call_linker=09014_E_Linker kann nicht aufgerufen werden, schalte um zu externem Linken
+% An error occurred when calling an external linker. The compiler will produce a script that
+% can be used to assemble and link the program.
+exec_i_linking=09015_I_Linke $1
+% An informational message, showing which program or library is being linked.
+exec_e_util_not_found=09016_E_Hilfsprogramm $1 nicht gefunden, schalte um zu externem Linken
+% An external tool was not found. The compiler will produce a script that
+% can be used to assemble and link or postprocess the program.
+exec_t_using_util=09017_T_Benutze Hilfsprogramm $1
+% An informational message, showing which external program (usually a postprocessor) is being used.
+exec_e_exe_not_supported=09018_E_Erzeugen von ausführbaren Dateien nicht unterstützt
+% Creating executable programs is not supported for this platform, because it was
+% not yet implemented in the compiler.
+exec_e_dll_not_supported=09019_E_Dynamische Bibliotheken nicht unterstützt
+% Creating dynamically loadable libraries is not supported for this platform, because it was
+% not yet implemented in the compiler.
+exec_i_closing_script=09020_I_Schliesse Skript $1
+% Informational message showing when writing of the external assembling and linking script is finished.
+exec_e_res_not_found=09021_E_Resource-Compiler "$1" nicht gefunden, schalte um auf externen Modus
+% An external resource compiler was not found. The compiler will produce a script that
+% can be used to assemble, compile resources and link or postprocess the program.
+exec_i_compilingresource=09022_I_Ãœbersetze Resource $1
+% An informational message, showing which resource is being compiled.
+exec_t_unit_not_static_linkable_switch_to_smart=09023_T_Unit $1 kann nicht statisch gelinkt werden, schalte um zu smart Linken
+% Static linking was requested, but a unit which is not statically linkable was used.
+exec_t_unit_not_smart_linkable_switch_to_static=09024_T_Unit $1 kann nicht smart gelinkt werden, schalte um zu statischem Linken
+% Smart linking was requested, but a unit which is not smart-linkable was used.
+exec_t_unit_not_shared_linkable_switch_to_static=09025_T_Unit $1 kann nicht shared gelinkt werden, schalte um zu statischem Linken
+% Shared linking was requested, but a unit which is not shared-linkable was used.
+exec_e_unit_not_smart_or_static_linkable=09026_E_Unit $1 kann weder smart noch statisch gelinkt werden
+% Smart or static linking was requested, but a unit which cannot be used for either was used.
+exec_e_unit_not_shared_or_static_linkable=09027_E_Unit $1 kann weder shared noch statisch gelinkt werden
+% Shared or static linking was requested, but a unit which cannot be used for either was used.
+exec_d_resbin_params=09028_D_Resource-Compiler "$1" wird mit "$2" als Kommandozeile aufgerufen
+% An informational message showing which command line is used for the resource compiler.
+exec_e_error_while_compiling_resources=09029_E_Fehler beim Ãœbersetzen von Resourcen
+% The resource compiler or converter returned an error.
+exec_e_cant_call_resource_compiler=09030_E_Der Resource-Compiler "$1" kann nicht aufgerufen werden, schalte um auf externen Modus
+% An error occurred when calling a resource compiler. The compiler will produce
+% a script that can be used to assemble, compile resources and link or
+% postprocess the program.
+exec_e_cant_open_resource_file=09031_E_Kann die Resourcedatei "$1" nicht öffnen
+% An error occurred resource file cannot be opened.
+exec_e_cant_write_resource_file=09032_E_Kann die Resourcedatei "$1" nicht schreiben
+% An error occurred resource file cannot be written.
+%
+% \end{description}
+# EndOfTeX
+
+#
+# Executable information
+#
+# 09134 is the last used one
+#
+# BeginOfTeX
+% \section{Executable information messages.}
+% This section lists all messages that the compiler emits when an executable program is produced,
+% and only when the internal linker is used.
+% \begin{description}
+execinfo_f_cant_process_executable=09128_F_Kann ausführbare Datei nicht nachbearbeiten: $1
+% Fatal error when the compiler is unable to post-process an executable.
+execinfo_f_cant_open_executable=09129_F_Kann ausführbare Datei nicht öffnen: $1
+% Fatal error when the compiler cannot open the file for the executable.
+execinfo_x_codesize=09130_X_Grösse des Codes: $1 Bytes
+% Informational message showing the size of the produced code section.
+execinfo_x_initdatasize=09131_X_Grösse der initialisierten Daten: $1 Bytes
+% Informational message showing the size of the initialized data section.
+execinfo_x_uninitdatasize=09132_X_Grösse der nicht initialisierten Daten: $1 Bytes
+% Informational message showing the size of the uninitialized data section.
+execinfo_x_stackreserve=09133_X_Stack Bereich "reserved": $1 Bytes
+% Informational message showing the stack size that the compiler reserved for the executable.
+execinfo_x_stackcommit=09134_X_Stack Bereich "committed": $1 Bytes
+% Informational message showing the stack size that the compiler committed for the executable.
+%
+% \end{description}
+# EndOfTeX
+
+#
+# Internal linker messages
+#
+# 09201 is the last used one
+#
+# BeginOfTeX
+% \section{Linker messages}
+% This section lists messages produced by internal linker.
+% \begin{description}
+link_f_executable_too_big=09200_F_Das Programm - Image ist für das Target $1 zu groß
+% Fatal error when resulting executable is too big.
+link_w_32bit_absolute_reloc=09201_W_Object Daei "$1" enthält eine 32-bit absolute Relocation auf Symbol "$2".
+% Warning when 64-bit object file contains 32-bit absolute relocations.
+% In such case an executable image can be loaded into lower 4Gb of
+% address space only.
+%
+% \end{description}
+# EndOfTeX
+
+#
+# Unit loading
+#
+# 10062 is the last used one
+#
+# BeginOfTeX
+% \section{Unit loading messages.}
+% This section lists all messages that can occur when the compiler is
+% loading a unit from disk into memory. Many of these mesages are
+% informational messages.
+% \begin{description}
+unit_t_unitsearch=10000_T_Suche Unit: $1
+% When you use the \var{-vt} option, the compiler tells you where it tries to find
+% unit files.
+unit_t_ppu_loading=10001_T_Lade PPU: $1
+% When the \var{-vt} switch is used, the compiler tells you
+% what units it loads.
+unit_u_ppu_name=10002_U_PPU-Name: $1
+% When you use the \var{-vu} flag, the unit name is shown.
+unit_u_ppu_flags=10003_U_PPU-Flags: $1
+% When you use the \var{-vu} flag, the unit flags are shown.
+unit_u_ppu_crc=10004_U_PPU-CRC: $1
+% When you use the \var{-vu} flag, the unit CRC check is shown.
+unit_u_ppu_time=10005_U_PPU-Zeit: $1
+% When you use the \var{-vu} flag, the unit time is shown.
+unit_u_ppu_file_too_short=10006_U_PPU-Datei zu kurz
+% When you use the \var{-vu} flag, the unit time is shown.
+unit_u_ppu_invalid_header=10007_U_PPU Ungültiger Header (kein PPU am Anfang)
+% A unit file contains as the first three bytes the ASCII codes of the characters \var{PPU}.
+unit_u_ppu_invalid_version=10008_U_PPU Ungültige Version $1
+% This unit file was compiled with a different version of the compiler, and
+% cannot be read.
+unit_u_ppu_invalid_processor=10009_U_PPU ist für einen anderen Prozessor übersetzt
+% This unit file was compiled for a different processor type, and
+% cannot be read.
+unit_u_ppu_invalid_target=10010_U_PPU ist für ein anderes Zielsystem übersetzt
+% This unit file was compiled for a different processor type, and
+% cannot be read.
+unit_u_ppu_source=10011_U_PPU Quelle: $1
+% When you use the \var{-vu} flag, the unit source file name is shown.
+unit_u_ppu_write=10012_U_Schreibe $1
+% When you specify the \var{-vu} switch, the compiler will tell you where it
+% writes the unit file.
+unit_f_ppu_cannot_write=10013_F_Kann PPU-Datei nicht schreiben
+% An error occurred when writing the unit file.
+unit_f_ppu_read_error=10014_F_Kann PPU-Datei nicht lesen
+% This means that the unit file was corrupted, and contains invalid
+% information. Recompilation will be necessary.
+unit_f_ppu_read_unexpected_end=10015_F_Unerwartetes Ende der PPU-Datei
+% Unexpected end of file. This may mean that the PPU file is
+% corrupted.
+unit_f_ppu_invalid_entry=10016_F_Ungültiger Eintrag in PPU-Datei: $1
+% The unit the compiler is trying to read is corrupted, or generated with a
+% newer version of the compiler.
+unit_f_ppu_dbx_count_problem=10017_F_PPU Dbx Zähler-Problem
+% There is an inconsistency in the debugging information of the unit.
+unit_e_illegal_unit_name=10018_E_Ungültiger Unitname: $1
+% The name of the unit doesn't match the file name.
+unit_f_too_much_units=10019_F_Zu viele Units
+% \fpc has a limit of 1024 units in a program. You can change this behavior
+% by changing the \var{maxunits} constant in the \file{files.pas} file of the
+% compiler, and recompiling the compiler.
+unit_f_circular_unit_reference=10020_F_Gegenseitige Abhängigkeit von Units zwischen $1 und $2
+% Two units are using each other in the interface part. This is only allowed
+% in the \var{implementation} part. At least one unit must contain the other one
+% in the \var{implementation} section.
+unit_f_cant_compile_unit=10021_F_Kann Unit "$1" nicht übersetzen, keine Quellen vorhanden
+% A unit was found that needs to be recompiled, but no sources are
+% available.
+unit_f_cant_find_ppu=10022_F_Kann Unit "$1", die von "$2" benutzt wird, nicht finden
+% You tried to use a unit of which the PPU file isn't found by the
+% compiler. Check your configuration file for the unit paths.
+unit_w_unit_name_error=10023_W_Unit "$1" wurde nicht gefunden, aber "$2" existiert
+% This error message is no longer used.
+unit_f_unit_name_error=10024_F_Unit "$1" gesucht, aber "$2" gefunden
+% \dos truncation of 8 letters for unit PPU files
+% may lead to problems when unit name is longer than 8 letters.
+unit_w_switch_us_missed=10025_W_Ãœbersetzen der Systemunit erfordert den Schalter -Us
+% When recompiling the system unit (it needs special treatment), the
+% \var{-Us} switch must be specified.
+unit_f_errors_in_unit=10026_F_Es traten $1 Fehler beim Ãœbersetzen des Moduls auf, halte an
+% When the compiler encounters a fatal error or too many errors in a module
+% then it stops with this message.
+unit_u_load_unit=10027_U_Lade aus $1 ($2) die Unit $3
+% When you use the \var{-vu} flag, which unit is loaded from which unit is
+% shown.
+unit_u_recompile_crc_change=10028_U_Übersetze $1 erneut, Prüfsumme für $2 hat sich geändert
+% The unit is recompiled because the checksum of a unit it depends on has
+% changed.
+unit_u_recompile_source_found_alone=10029_U_Ãœbersetze "$1", nur Quellcode gefunden
+% When you use the \var{-vu} flag, these messages tell you why the current
+% unit is recompiled.
+unit_u_recompile_staticlib_is_older=10030_U_Übersetze Unit erneut, statische Bibliothek ist älter als PPU-Datei
+% When you use the \var{-vu} flag, the compiler warns if the static library
+% of the unit is older than the unit file itself.
+unit_u_recompile_sharedlib_is_older=10031_U_Übersetze Unit erneut, gemeinsame Bibliothek ist älter als PPU-Datei
+% When you use the \var{-vu} flag, the compiler warns if the shared library
+% of the unit is older than the unit file itself.
+unit_u_recompile_obj_and_asm_older=10032_U_Übersetze Unit erneut, obj und asm sind älter als PPU-Datei
+% When you use the \var{-vu} flag, the compiler warns if the assembler of
+% object file of the unit is older than the unit file itself.
+unit_u_recompile_obj_older_than_asm=10033_U_Übersetze Unit erneut, obj ist älter als asm
+% When you use the \var{-vu} flag, the compiler warns if the assembler
+% file of the unit is older than the object file of the unit.
+unit_u_parsing_interface=10034_U_Analysiere Interface von $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% parsing the interface part of the unit.
+unit_u_parsing_implementation=10035_U_Analysiere Implementation von $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% parsing the implementation part of the unit.
+unit_u_second_load_unit=10036_U_Zweites Laden für Unit "$1"
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% recompiling a unit for the second time. This can happen with
+% interdependent units.
+unit_u_check_time=10037_U_PPU prüfe Datei $1 Zeit $2
+% When you use the \var{-vu} flag, the compiler shows the filename and
+% date and time of the file on which a recompile depends.
+### The following two error msgs is currently disabled.
+#unit_h_cond_not_set_in_last_compile=10038_H_Conditional $1 wurde beim Start beim letzten Ãœbersetzen von $2 nicht gesetzt
+#% when recompilation of an unit is required the compiler will check that
+#% the same conditionals are set for the recompiliation. The compiler has
+#% found a conditional that currently is defined, but was not used the last
+#% time the unit was compiled.
+#unit_h_cond_set_in_last_compile=10039_H_Conditional $1 wurde beim Start beim letzten Ãœbersetzen von $2 gesetzt
+#% when recompilation of an unit is required the compiler will check that
+#% the same conditionals are set for the recompiliation. The compiler has
+#% found a conditional that was used the last time the unit was compiled, but
+#% the conditional is currently not defined.
+unit_w_cant_compile_unit_with_changed_incfile=10040_W_Kann Unit $1 nicht erneut übersetzen, aber geänderte Include-Datei gefunden
+% A unit was found to have modified include files, but
+% some source files were not found, so recompilation is impossible.
+unit_u_source_modified=10041_U_Datei $1 ist neuer als die, aus der die PPU Datei $2 erzeugt wird
+% A modified source file for a compiler unit was found.
+unit_u_ppu_invalid_fpumode=10042_U_Versuch eine Unit zu verwenden, die in einem anderen FPU Mode übersetzt wurde
+% Trying to compile code while using units which were not compiled with
+% the same floating point format mode. Either all code should be compiled
+% with FPU emulation on, or with FPU emulation off.
+unit_u_loading_interface_units=10043_U_Interface Units werden von $1 geladen
+% When you use the \var{-vu} flag, the compiler warns that it is starting
+% to load the units defined in the interface part of the unit.
+unit_u_loading_implementation_units=10044_U_Implementation Units werden von $1 geladen
+% When you use the \var{-vu} flag, the compiler warns that it is starting
+% to load the units defined in the implementation part of the unit.
+unit_u_interface_crc_changed=10045_U_Geänderte Interface CRC für Unit $1
+% When you use the \var{-vu} flag, the compiler warns that the
+% CRC calculated for the interface has been changed after the implementation
+% has been parsed.
+unit_u_implementation_crc_changed=10046_U_Geänderte Implementation CRC für Unit $1
+% When you use the \var{-vu} flag, the compiler warns that the
+% CRC calculated has been changed after the implementation
+% has been parsed.
+unit_u_finished_compiling=10047_U_Ãœbersetzen der Unit $1 beendet
+% When you use the \var{-vu} flag, the compiler warns that it
+% has finished compiling the unit.
+unit_u_add_depend_to=10048_U_Abhängigkeit hinzufügen: $1 hängt von $2 ab
+% When you use the \var{-vu} flag, the compiler warns that it
+% has added a dependency between the two units.
+unit_u_no_reload_is_caller=10049_U_Kein erneutes Laden, Unit $1 ist die Aufrufende
+% When you use the \var{-vu} flag, the compiler warns that it
+% will not reload the unit because it is the unit that wants
+% to load this unit.
+unit_u_no_reload_in_second_compile=10050_U_Kein erneutes Laden der Unit, bereits beim zweiten Ãœbersetzen: $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% will not reload the unit because it is already in a second recompile.
+unit_u_flag_for_reload=10051_U_Flag für erneutes Laden: $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has to reload the unit.
+unit_u_forced_reload=10052_U_Erzwungenes erneutes Laden
+% When you use the \var{-vu} flag, the compiler warns that it
+% is reloading the unit because it was required.
+unit_u_previous_state=10053_U_Vorhergehender Status von $1: $2
+% When you use the \var{-vu} flag, the compiler shows the
+% previous state of the unit.
+unit_u_second_compile_unit=10054_U_$1 wird bereits übersetzt, zweites Übersetzen gesetzt
+% When you use the \var{-vu} flag, the compiler warns that it is starting
+% to recompile a unit for the second time. This can happen with interdependent
+% units.
+unit_u_loading_unit=10055_U_Unit $1 wird geladen
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% loading the unit.
+unit_u_finished_loading_unit=10056_U_Laden der Unit $1 beendet
+% When you use the \var{-vu} flag, the compiler warns that it finished
+% loading the unit.
+unit_u_registering_new_unit=10057_U_Registrierung der neuen Unit $1
+% When you use the \var{-vu} flag, the compiler warns that it has
+% found a new unit and is registering it in the internal lists.
+unit_u_reresolving_unit=10058_U_Erneutes resolving der Unit $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has to recalculate the internal data of the unit.
+unit_u_skipping_reresolving_unit=10059_U_Erneutes Resolving der Unit $1 wird übersprungen, benutzte Units werden noch geladen
+% When you use the \var{-vu} flag, the compiler warns that it is
+% skipping the recalculation of the internal data of the unit
+% because there is no data to recalculate.
+unit_u_unload_resunit=10060_U_Entlade die Resource-Unit $1 (wird nicht benötigt)
+% When you use the \var{-vu} flag, the compiler warns that it is unloading the
+% resource handling unit, since no resources are used.
+unit_e_different_wpo_file=10061_E_Unit $1 wurde mit einer anderen Feedback-Eingabe ($2, $3) für die Gesamtprogramm-Optimierung (wpo) übersetzt. Bitte erneut ohne wpo oder mit der gleichen wpo-Feedback-Eingabe-Datei übersetzen
+% When a unit has been compiled using a particular whole program optimization (wpo) feedback file (\var{-FW<x>} \var{-OW<x>}),
+% this compiled version of the unit is specialised for that particular compilation scenario and cannot be used in
+% any other context. It has to be recompiled before you can use it in another program or with another wpo feedback input file.
+unit_u_indirect_crc_changed=10062_U_Die CRC des indirekten Interface (Objekte/Klassen) für die unit $1 hat sich geändert
+% When you use the \var{-vu} flag, the compiler warns that the
+% indirect CRC calculated for the unit (this is the CRC of all classes/objects/interfaces/$\ldots$
+% in the interfaces of units directly or indirectly used by this unit in the interface) has been changed after the
+% implementation has been parsed.
+%
+% \end{description}
+# EndOfTeX
+
+#
+# Options
+#
+# 11048 is the last used one
+#
+option_usage=11000_O_$1 [Optionen] <Eingabedatei> [Optionen]
+# BeginOfTeX
+%
+% \section{Command line handling errors}
+% This section lists errors that occur when the compiler is processing the
+% command line or handling the configuration files.
+% \begin{description}
+option_only_one_source_support=11001_W_Es wird nur eine Quelldatei unterstützt. Wechsel für das Kompilieren von Quelldatei "$1" zu Quelldatei "$2"
+% You can specify only one source file on the command line. The last
+% one will be compiled, others will be ignored. This may indicate that
+% you forgot a \var{'-'} sign.
+option_def_only_for_os2=11002_W_DEF-Datei kann nur für OS/2 erzeugt werden
+% This option can only be specified when you're compiling for OS/2.
+option_no_nested_response_file=11003_E_Verschachtelte Response-Dateien werden nicht unterstützt
+% You cannot nest response files with the \var{@file} command line option.
+option_no_source_found=11004_F_Kein Name für Quelldatei auf der Kommandzeile
+% The compiler expects a source file name on the command line.
+option_no_option_found=11005_N_Keine Angaben in Konfigurationsdatei "$1" gefunden
+% The compiler didn't find any option in that config file.
+option_illegal_para=11006_E_Ungültiger Parameter: $1
+% You specified an unknown option.
+option_help_pages_para=11007_H_-? zeigt Hilfetext an
+% When an unknown option is given, this message is diplayed.
+option_too_many_cfg_files=11008_F_Zu viele verschachtelte Konfigurationsdateien
+% You can only nest up to 16 config files.
+option_unable_open_file=11009_F_Kann Datei nicht öffnen $1
+% The option file cannot be found.
+option_reading_further_from=11010_D_Lese weitere Optionen aus $1
+% Displayed when you have notes turned on, and the compiler switches
+% to another options file.
+option_target_is_already_set=11011_W_Zielsystem ist bereits gesetzt: $1
+% Displayed if more than one \var{-T} option is specified.
+option_no_shared_lib_under_dos=11012_W_Gemeinsame Bibliotheken sind auf der DOS Platform nicht verfügbar, verwende stattdessen statische Bibliotheken
+% If you specify \var{-CD} for the \dos platform, this message is displayed.
+% The compiler supports only static libraries under \dos.
+option_too_many_ifdef=11013_F_Zu viele \var{\#IF(N)DEFs} in Zeile $2 der Optionen-Datei $1
+% The \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_too_many_endif=11014_F_Unerwartetes \var{\#ENDIFs} in Zeile $2 der Optionen-Datei $1
+% The \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_too_less_endif=11015_F_Offene Bedingung am Ende der Optionen-Datei
+% The \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_no_debug_support=11016_W_Erzeugung von Debug-Informationen wird von dieser ausführbaren Datei nicht unterstützt
+% It is possible to have a compiler executable that doesn't support
+% the generation of debugging info. If you use such an executable with the
+% \var{-g} switch, this warning will be displayed.
+option_no_debug_support_recompile_fpc=11017_H_Versuchen Sie mit -dGDB erneut zu übersetzen
+% It is possible to have a compiler executable that doesn't support
+% the generation of debugging info. If you use such an executable with the
+% \var{-g} switch, this warning will be displayed.
+option_obsolete_switch=11018_W_Sie verwenden den nun überholten Schalter $1
+% This warns you when you use a switch that is not needed/supported anymore.
+% It is recommended that you remove the switch to overcome problems in the
+% future, when the meaning of the switch may change.
+option_obsolete_switch_use_new=11019_W_Sie benutzen den nun überholten Schalter $1, bitte benutzen Sie $2
+% This warns you when you use a switch that is not supported anymore. You
+% must now use the second switch instead.
+% It is recommended that you change the switch to overcome problems in the
+% future, when the meaning of the switch may change.
+option_switch_bin_to_src_assembler=11020_N_Schalte Assembler auf den Standard-Assembler-Quellcodeschreiber
+% This notifies you that the assembler has been changed because you used the
+% -a switch, which can't be used with a binary assembler writer.
+option_incompatible_asm=11021_W_Das gewählte Assembler-Ausgabeformat "$1" ist nicht mit "$2" kompatibel
+option_asm_forced=11022_W_Verwendung des Assemblers "$1" erzwungen
+% The assembler output selected cannot generate
+% object files with the correct format. Therefore, the
+% default assembler for this target is used instead.
+option_using_file=11026_T_Optionen werden aus der Datei $1 gelesen
+% Options are also read from this file.
+option_using_env=11027_T_Optionen werden aus dem environment $1 gelesen
+% Options are also read from this environment string.
+option_handling_option=11028_D_Handling der Option "$1"
+% Debug info that an option is found and will be handled.
+option_help_press_enter=11029_O_*** Drücken Sie die ENTER-Taste ***
+% Message shown when help is shown page per page. When pressing the ENTER
+% Key, the next page of help is shown. If you press q and then ENTER, the
+% compiler exits.
+option_start_reading_configfile=11030_H_Beginn des Lesens der Konfigurationsdatei $1
+% Start of configuration file parsing.
+option_end_reading_configfile=11031_H_Ende des Lesens der Konfigurationsdatei $1
+% End of configuration file parsing.
+option_interpreting_option=11032_D_Option "$1" interpretieren
+% The compiler is interpreting an option
+option_interpreting_firstpass_option=11036_D_firstpass Option "$1" interpretieren
+% The compiler is interpreting an option for the first time.
+option_interpreting_file_option=11033_D_Datei Option "$1" interpretieren
+% The compiler is interpreting an option which it read from the configuration file.
+option_read_config_file=11034_D_Konfigurationsdatei "$1" lesen
+% The compiler is starting to read the configuration file.
+option_found_file=11035_D_Name der Quelldatei "$1" gefunden
+% Additional information about options.
+% Displayed when you have the debug option turned on.
+option_code_page_not_available=11039_E_Unbekannte code page
+% An unknown code page for the source files was requested.
+% The compiler is compiled with support for several code pages built-in.
+% The requested code page is not in that list. You will need to recompile
+% the compiler with support for the codepage you need.
+option_config_is_dir=11040_F_Konfigurationsdatei $1 ist ein Verzeichnis
+% Directories cannot be used as configuration files.
+option_confict_asm_debug=11041_W_Die gewählte Assembler-Ausgabe "$1" kann kein Debug-Info erzeugen, Debugging ist ausgeschaltet
+% The selected assembler output cannot generate
+% debugging information, debugging option is therefore disabled.
+option_ppc386_deprecated=11042_W_Die Verwendung von ppc386.cfg wird beendet. Bitte statt dessen fpc.cfg benutzen
+% Using ppc386.cfg is still supported for historical reasons, however, for a multiplatform
+% system the naming makes no sense anymore. Please continue to use fpc.cfg instead.
+option_else_without_if=11043_F_Zur \var{\#ELSE} Direktive in Zeile $2 der Optionen-Datei $1 gibt es kein entsprechendes \var{\#IF(N)DEF}
+% An \var{\#ELSE} statement was found in the options file without a matching \var{\#IF(N)DEF} statement.
+option_unsupported_target=11044_F_Die Option "$1" wird auf der Zielplattform nicht oder noch nicht unterstützt
+% Not all options are supported or implemented for all target platforms. This message informs you that a chosen
+% option is incompatible with the currently selected target platform.
+option_unsupported_target_for_feature=11045_F_Das Feature "$1" wird für die ausgewählte Zielplattform nicht oder noch nicht unterstützt
+% Not all features are supported or implemented for all target platforms. This message informs you that a chosen
+% feature is incompatible with the currently selected target platform.
+option_dwarf_smart_linking=11046_N_DWARF Debug-Information kann auf dieser Zielplattform nicht zusammen mit Smartlinking benutzt werden, es wird auf statisches Linken umgeschaltet
+% Smart linking is currently incompatble with DWARF debug information on most
+% platforms, so smart linking is disabled in such cases.
+option_ignored_target=11047_W_Option "$1" wird für die ausgewählte Zielplattform ignoriert
+% Not all options are supported or implemented for all target platforms. This message informs you that a chosen
+% option is ignored for the currently selected target platform.
+option_debug_external_unsupported=11048_W_Schalte externe Debuginformation aus, weil es für die gewählte Kombination Ziel/Debugformat nicht unterstützt wird
+% Not all debug formats can be stored in an external file on all platforms. In particular, on
+% Mac OS X only DWARF debug information can be stored externally.
+%
+% \end{description}
+# EndOfTeX
+
+#
+# Whole program optimization
+#
+# 12019 is the last used one
+#
+# BeginOfTeX
+%
+% \section{Whole program optimization messages}
+% This section lists errors that occur when the compiler is performing
+% whole program optimization.
+% \begin{description}
+wpo_cant_find_file=12000_F_Feedback-Datei "$1" für die Gesamtprogramm-Optimierung kann nicht geöffnet werden
+% The compiler cannot open the specified feedback file with whole program optimization information.
+wpo_begin_processing=12001_D_Bearbeite die Informationen zur Gesamtprogramm-Optimierung aus der wpo-Feedback-Datei "$1"
+% The compiler starts processing whole program optimization information found in the named file.
+wpo_end_processing=12002_D_Bearbeitung der Informationen zur Gesamtprogramm-Optimierung aus der wpo-Feedback-Datei "$1" beendet
+% The compiler has finished processing the whole program optimization information found in the named file.
+wpo_expected_section=12003_E_Erwarte einen Sektions-Header, statt dessen "$2" in Zeile $1 der wpo-Feedback-Datei erhalten
+% The compiler expected a section header in the whole program optimization file (starting with \%),
+% but did not find it.
+wpo_no_section_handler=12004_W_Kein Handler für die Sektion "$2" der Gesamtprogramm-Optimierung registriert (Zeile $1 der wpo-Feedback-Datei). Wird ignoriert
+% The compiler has no handler to deal with the mentioned whole program optimization information
+% section, and will therefore ignore it and skip to the next section.
+wpo_found_section=12005_D_Sektion "$1" der Gesamtprogramm-Optimierung mit Informationen über "$2" gefunden
+% The compiler encountered a section with whole program optimization information, and according
+% to its handler this section contains information usable for the mentioned purpose.
+wpo_no_input_specified=12006_F_Die ausgewählte Gesamtprogramm-Optimierung erfordert eine bereits erzeugte Feedback-Datei (bitte mit -Fw angeben)
+% The compiler needs information gathered during a previous compilation run to perform the selected
+% whole program optimizations. You can specify the location of the feedback file containing this
+% information using the -Fw switch.
+wpo_not_enough_info=12007_E_Keine Informationen für "$1" Gesamtprogramm-Optimierung gefunden
+% While you pointed the compiler to a file containing whole program optimization feedback, it
+% did not contain the information necessary to perform the selected optimizations. You most likely
+% have to recompile the program using the appropate -OWxxx switch.
+wpo_no_output_specified=12008_F_Gebe eine Feedback-Datei an, um die erzeugte Information für die Gesamtprogramm-Optimierung zu speichern (mit der Option -FW)
+% You have to specify the feedback file in which the compiler has to store the whole program optimization
+% feedback that is generated during the compilation run. This can be done using the -FW switch.
+wpo_output_without_info_gen=12009_E_Erzeuge keine Information für die Gesamtprogramm-Optimierung, obwohl eine Feedback-Datei dafür angegeben wurde (mit der Option -FW)
+% The compiler was instructed to store whole program optimization feedback into a file specified using -FW,
+% but not to actually generated any whole program optimization feedback. The classes of to be
+% generated information can be speciied using -OWxxx.
+wpo_input_without_info_use=12010_E_Gesamtprogramm-Optimierung wird nicht durchgeführt, obwohl eine Feedback-Datei angegeben wurde (mit der Option -FW)
+% The compiler was not instructed to perform any whole program optimizations (no -Owxxx parameters),
+% but nevertheless an input file with such feedback was specified (using -Fwyyy). Since this can
+% indicate that you forgot to specify an -Owxxx parameter, the compiler generates an error in this case.
+wpo_skipping_unnecessary_section=12011_D_Überspringe die Sektion "$1" der Gesamtprogramm-Optimierung, weil sie nicht benötigt wird
+% The whole program optimization feedback file contains a section with information that is not
+% required by the selected whole program optimizations.
+wpo_duplicate_wpotype=12012_W_Ãœberschreibe bereits gelesene Information "$1" aus der Feedback-Eingabe-Datei mit der Information in Sektion "$2"
+% The feedback file contains multiple sections that provide the same class of information (e.g.,
+% information about which virtual methods can be devirtualized). In this case, the information in last encountered
+% section is used. Turn on debugging output (-vd) to see which class of information is provided by each section.
+wpo_cannot_extract_live_symbol_info_strip=12013_E_Symbol "liveness" Information kann nicht aus dem Programm erhalten werden, wenn Symbole mit "strip" entfernt wurden. Benutze -Xs-
+% Certain symbol liveness collectors extract the symbol information from the linked program. If the symbol information
+% is stripped (option -Xs), this is not possible.
+wpo_cannot_extract_live_symbol_info_no_link=12014_E_Symbol "liveness" Information kann nicht aus dem Programm erhalten werden, wenn es nicht "linked" wird
+% Certain symbol liveness collectors extract the symbol information from the linked program. If the program is not
+% linked by the compiler, this is not possible.
+wpo_cannot_find_symbol_progs=12015_F_"$1" oder "$2" wurden nicht gefunden, um die Symbol "liveness" Information aus dem Programm zu erhalten
+% Certain symbol liveness collectors need a helper program to extract the symbol information from the linked program.
+% This helper program is normally 'nm', which is part of the GNU binutils.
+wpo_error_reading_symbol_file=12016_E_Fehler beim Lesen der "symbol liveness" Information durch "$1" erzeugt
+% An error occurred during the reading of the symbol liveness file that was generated using the 'nm' or 'objdump' program. The reason
+% can be that it was shorter than expected, or that its format was not understood.
+wpo_error_executing_symbol_prog=12017_F_Fehler bei der Ausführung von "$1" (exitcode: $2) um Symbolinformationen aus dem "gelinkten" Programm zu erhalten
+% Certain symbol liveness collectors need a helper program to extract the symbol information from the linked program.
+% The helper program produced the reported error code when it was run on the linked program.
+wpo_symbol_live_info_needs_smart_linking=12018_E_Die Sammlung der "symbol liveness" Information hilft nur bei smart linking, benutze -CX -XX
+% Whether or not a symbol is live is determined by looking whether it exists in the final linked program.
+% Without smart linking/dead code stripping, all symbols are always included, regardless of whether they are
+% actually used or not. So in that case all symbols will be seen as live, which makes this optimization ineffective.
+wpo_cant_create_feedback_file=12019_E_Die angegebene Feedback-Eingabe-Datei "$1" für die Gesamtprogramm-Optimierung kann nicht erzeugt werden
+% The compiler is unable to create the file specified using the -FW parameter to store the whole program optimisation information.
+%
+% \end{description}
+# EndOfTeX
+
+#
+# Logo (option -l)
+#
+option_logo=11023_[
+Free Pascal Compiler Version $FPCFULLVERSION [$FPCDATE] für $FPCTARGET
+Copyright (c) 1993-2011 Florian Klämpfl und andere
+]
+
+#
+# Info (option -i)
+#
+option_info=11024_[
+Free Pascal Compiler Version $FPCVERSION
+
+Compiler Datum: $FPCDATE
+Compiler Zielsystem: $FPCCPU
+
+Unterstützte Zielbetriebssysteme:
+ $OSTARGETS
+
+Unterstützte CPU Instruktionen:
+ $INSTRUCTIONSETS
+
+Unterstützte FPU Instruktionen:
+ $FPUINSTRUCTIONSETS
+
+Unterstützte ABI Ziele:
+ $ABITARGETS
+
+Unterstützte Optimierungen:
+ $OPTIMIZATIONS
+
+Unterstützte Gesamtprogramm-Optimierungen:
+ All
+ $WPOPTIMIZATIONS
+
+Unterstützte Microcontroller:
+ $CONTROLLERTYPES
+
+Dieses Programm unterliegt der GNU General Public Licence
+Weitere Informationen sind in COPYING.FPC zu finden
+
+Fehlerberichte, Vorschläge usw. bitte senden an:
+ http://bugs.freepascal.org
+oder
+ bugs@freepascal.org
+]
+
+#
+# Help pages (option -? and -h)
+#
+# The first character on the line indicates who will display this
+# line, the current possibilities are :
+# * = every target
+# 3 = 80x86 targets
+# 4 = x86_64
+# 6 = 680x0 targets
+# A = ARM
+# e = in extended debug mode only
+# P = PowerPC targets
+# S = Sparc targets
+# V = Virtual machine targets
+# The second character also indicates who will display this line,
+# (if the above character was TRUE) the current possibilities are :
+# * = everyone
+# g = with GDB info supported by the compiler
+# O = OS/2
+# L = UNIX systems
+# The third character represents the indentation level.
+#
+option_help_pages=11025_[
+**0*_Nach booleschen Optionen geben Sie + zum Ein- bzw. - zum Ausschalten an
+**1a_Lösche die erzeugte Assembler-Datei nicht
+**2al_Liste Quellcode-Zeilen in der Assembler-Datei
+**2an_Liste "node info" in der Assembler-Datei
+*L2ap_Benutze Pipes anstelle temporärer Assembler-Dateien
+**2ar_Liste Registerbelegungsinformation in Assembler-Datei
+**2at_Liste Temp. Variablenbelegungsinfo in Assembler-Datei
+**1A<x>_Ausgabe Format:
+**2Adefault_Benutze den "default" Assembler
+3*2Aas_Assembliere mit Hilfe von GNU AS
+3*2Amacho_Mach-O (Darwin, Intel 32 bit) mit Hilfe des internen Schreibers
+3*2Anasmcoff_COFF (Go32v2) Datei mit Hilfe von Nasm
+3*2Anasmelf_ELF32 (Linux) Datei mit Hilfe von Nasm
+3*2Anasmwin32_Win32 Object Datei mit Hilfe von Nasm
+3*2Anasmwdosx_Win32/WDOSX Object Datei mit Hilfe von Nasm
+3*2Awasm_Obj Datei mit Hilfe von Wasm (Watcom)
+3*2Anasmobj_Obj Datei mit Hilfe von Nasm
+3*2Amasm_Obj Datei mit Hilfe von Masm (Microsoft)
+3*2Atasm_Obj Datei mit Hilfe von Tasm (Borland)
+3*2Aelf_ELF32 (Linux) mit Hilfe des internen Schreibers
+3*2Acoff_COFF (Go32v2) mit Hilfe des internen Schreibers
+3*2Apecoff_PE_COFF (Win32) mit Hilfe des internen Schreibers
+4*2Aas_Assembliere mit Hilfe von GNU AS
+4*2Agas_Assembliere mit Hilfe von GNU GAS
+4*2Agas-darwin_Assembliere darwin Mach-O64 mit Hilfe von GNU GAS
+4*2Amasm_Win64 Object Datei mit Hilfe von ml64 (Microsoft)
+4*2Apecoff_PE-COFF (Win64) mit Hilfe des internen Writer
+4*2Aelf_ELF (Linux-64bit) mit Hilfe des internen Writer
+6*2Aas_Unix o-file mit Hilfe von GNU AS
+6*2Agas_GNU Motorola Assembler
+6*2Amit_MIT Syntax (old GAS)
+6*2Amot_Standard Motorola Assembler
+A*2Aas_Assembliere mit Hilfe von GNU AS
+P*2Aas_Assembliere mit Hilfe von GNU AS
+S*2Aas_Assembliere mit Hilfe von GNU AS
+**1b_Erzeuge Browser-Info
+**2bl_Erzeuge Info zu lokalen Symbolen
+**1B_Erzeuge alle Module (Build)
+**1C<x>_Optionen für Code-Erzeugung:
+**2C3<x>_Schalte ieee-Prüfung von Konstanten ein
+**2Ca<x>_Wähle ABI aus; fpc -i gibt die möglichen Werte aus
+**2Cb_Erzeuge "big-endian" Code
+**2Cc<x>_Setze "default calling convention" zu <x>
+**2CD_Erzeuge auch eine dynamische Bibliothek (nicht unterstützt)
+**2Ce_Ãœbersetze mit emulierten Fliesskomma opcodes
+**2Cf<x>_Wähle den Fliesskomma instruction set aus; fpc -i gibt die möglichen Werte aus
+**2CF<x>_Minimale Präzission von Fliesskommakonstanten (default, 32, 64)
+**2Cg_Erzeuge PIC code
+**2Ch<n>_<n> Bytes Heap (zwischen 1023 und 67107840)
+**2Ci_I/O-Prüfung
+**2Cn_Lasse die Linkstufe aus
+**2Co_Prüfe auf Überlauf von Integer-Operationen
+**2CO_Prüfe auf möglichen Überlauf von Integer-Operationen
+**2Cp<x>_Wähle instruction set aus; fpc -i gibt die möglichen Werte aus
+**2CP<x>=<y>_ Einstellungen für packing
+**3CPPACKSET=<y>_ <y> Belegung von Sets: 0, 1 oder DEFAULT oder NORMAL, 2, 4 und 8
+**2Cr_Führe Bereichsprüfung durch
+**2CR_Verifiziere die Gültigkiet des Aufrufs der Objektmethoden
+**2Cs<n>_Setze die Prüfgrösse des Stacks auf <n>
+**2Ct_Führe Stackprüfung durch (nur zum Testen, siehe Handbuch)
+**2Cx_Benutze Smartlinking
+**1d<x>_Definiere das Symbol <x>
+**1D_Erzeuge eine DEF-Datei
+**2Dd<x>_Setze Beschreibung zu <x>
+**2Dv<x>_Setze DLL Version zu <x>
+*O2Dw_Erzeuge PM-Anwendung
+**1e<x>_Setze Pfad zur ausführbaren Datei
+**1E_Genau wie -Cn
+**1fPIC_Genau wie -Cg
+**1F<x>_Dateinamen und Pfade:
+**2Fa<x>[,y]_Ein Program soll die Units <x> und [y] laden, bevor uses analysiert wird
+**2Fc<x>_Setze die Eingabe-Codepage zu <x>
+**2FC<x>_Setze den Namen des RC Compiler-Binärprograms auf <x>
+**2Fd_Schalte den internen Verzeichnis-Cache des Compilers aus
+**2FD<x>_Setze das Verzeichnis für die Compiler-Hilfsprogramme
+**2Fe<x>_Leite die Fehlerausgabe um nach <x>
+**2Ff<x>_Ergänze <x> zum Framework-Pfad (nur Darwin)
+**2FE<x>_Setze den Pfad für Exe/Unit-Dateien auf <x>
+**2Fi<x>_Ergänze <x> zum Include-Pfad
+**2Fl<x>_Ergänze <x> zum Bibliotheks-Pfad
+**2FL<x>_Benutze <x> als dynamischen Linker
+**2Fm<x>_Lade die Unicode-Konversionstabelle aus <x>.txt im Compiler-Verzeichnis
+**2Fo<x>_Ergänze <x> zum Objektdatei-Pfad
+**2Fr<x>_Lade die Fehlermeldungs-Datei <x>
+**2FR<x>_Setze den Resource (.res) Linker auf <x>
+**2Fu<x>_Ergänze <x> zum Unit-Pfad
+**2FU<x>_Units werden nach <x> ausgegeben, hat Vorrang vor -FE
+**2FW<x>_Speichere das erzeugte Feedback für die Gesamtprogramm-Optimierung in <x>
+**2Fw<x>_Lade das bereits gespeicherte Feedback für die Gesamtprogramm-Optimierung aus <x>
+*g1g<x>_Erzeuge Informationen zur Fehlersuche:
+*g2gc_Zeigerüberprüfung
+*g2gh_Heaptrace-Unit einbinden
+*g2gl_Line info Unit einbinden, um mehr backtrace Informationen anzuzeigen
+*g2go<x>_Setze Optionen für die Debug Informationen
+*g3godwarfsets_Schalte DWARF Debug Informationen für Mengen (sets) ein (verhindert debugging mit gdb < 6.5)
+*g3gostabsabsincludes_ Absolute/volle Include-Datei-Pfade in Stabs speichern
+*g3godwarfmethodclassprefix_ Stelle Methodennamen in DWARF den Namen der Klasse voran
+*g2gp_Erhalte Gross/Kleinschreibung in Stabs-Symbolnamen
+*g2gs_Erzeuge Stabs-Debug-Informationen
+*g2gt_Lösche lokale Variablen (um eine Verwendung ohne Initialisierung zu finden)
+*g2gv_Erzeuge ein mit Valgrind verfolgbares (traceable) Programm
+*g2gw_Erzeuge DWARFv2-Debug-Informationen (wie -gw2)
+*g2gw2_Erzeuge DWARFv2-Debug-Informationen
+*g2gw3_Erzeuge DWARFv3-Debug-Informationen
+*g2gw4_Generate DWARFv4-Debug-Informationen (experimentell)
+**1i_Zeige alle Informationen über den Compiler
+**2iD_Zeige Compilerdatum
+**2iV_Zeige Compilerversion
+**2iW_Zeige vollständige Compilerversion
+**2iSO_Zeige Compilerbetriebssystem
+**2iSP_Zeige Compilerprozessor
+**2iTO_Zeige Zielbetriebssystem
+**2iTP_Zeige Zielprozessor
+**1I<x>_Ergänze <x> zum Include-Pfad
+**1k<x>_Ãœbergebe <x> an den Linker
+**1l_Zeige Logo
+**1M<x>_Setze Sprachmodus zu <x>
+**2Mfpc_Free Pascal Dialekt (Voreinstellung)
+**2Mobjfpc_Schalte einige Delphi 2 Erweiterungen ein
+**2Mdelphi_Versuche zu Delphi kompatibel zu sein
+**2Mtp_Versuche zu TP/BP 7.0 kompatibel zu sein
+**2Mmacpas_Versuche zu den MacIntosh Pascal-Dialekten kompatibel zu sein
+**1n_Standard-Konfigurationsdatei ignorieren
+**1N<x>_Node tree Optimierung
+**2Nu_Unroll loops
+**1o<x>_Die erzeugte, ausführbare Datei bekommt den Namen <x>
+**1O<x>_Optimierungen:
+**2O-_Optimierungen ausschalten
+**2O1_Level 1 Optimierung (schnell und Debugger freundlich)
+**2O2_Level 2 Optimierung (-O1 + schnelle Optimierungen)
+**2O3_Level 3 Optimierung (-O2 + langsame Optimierungen)
+**2Oa<x>=<y>_Ausrichtung (alignment) von Mengen
+**2Oo[NO]<x>_Optimierungen ein- oder ausschalten; fpc -i gibt die möglichen Werte aus
+**2Op<x>_Setze Zielprozessor für die Optimierung; fpc -i gibt die möglichen Werte aus
+**2OW<x>_Erzeuge Feedback für die Gesamtprogramm-Optimierung für Optimierung <x>, siehe fpc -i für mögliche Werte
+**2Ow<x>_Führe die Gesamtprogramm-Optimierung durch <x>, siehe fpc -i für mögliche Werte
+**2Os_Erzeuge kürzeren Code
+**1pg_Erzeuge Profiler-Code für gprof
+**1R<x>_Assembler Code Format:
+**2Rdefault_Benutze den default Assembler
+3*2Ratt_Lese Assembler Code im AT&T Format
+3*2Rintel_Lese Assembler im Intel Format
+6*2RMOT_Lese Assembler im Motorola Format
+**1S<x>_Syntax-Optionen:
+**2S2_Schalte einige der Delphi 2 Erweiterungen ein (wie -Mobjfpc)
+**2Sc_Unterstütze spezielle C Operatoren (*=,+=,/= and -=)
+**2Sa_Erlaube assertion code.
+**2Sd_Sei Delphi-kompatibel (wie -Mdelphi)
+**2Se<x>_Fehler Optionen. <x> ist eine der folgenden Kombinationen:
+**3*_<n> : Compiler hält nach <n> Fehlern (Voreinstellung ist 1)
+**3*_w : Compiler hält auch nach Warnungen
+**3*_n : Compiler hält auch nach Anmerkungen
+**3*_h : Compiler hält auch nach Hinweisen
+**2Sg_Erlaube LABEL und GOTO
+**2Sh_Benutze ANSI-Strings
+**2Si_Benutze C++ artige INLINE
+**2Sk_Lade fpcylix Unit
+**2SI<x>_Setze den Stil des Interface zu <x>
+**3SIcom_COM kompatibles Interface (Voreinstellung)
+**3SIcorba_CORBA kompatibles Interface
+**2Sm_Unterstütze Makros wie in C (global)
+**2So_Sei TP/BP 7.0 kompatibel (wie -Mtp)
+**2Ss_Konstruktor- und Destruktorname müssen "Init" und "Done" sein
+**2Sx_Exception Schlüsselwörter einschalten (Voreinstellung in Delphi/ObjFPC Moden)
+**2Sy_@<pointer> gibt einen typisierten Pointer zurück, genau wie $T+
+**1s_Rufe weder Assembler noch Linker auf (nur mit -a)
+**2sh_Erzeuge Script um auf dem Host zu linken
+**2st_Erzeuge Script um auf dem Zielsystem zu linken
+**2sr_Ãœberspringe die Phase der "register allocation" (mit -alr benutzen)
+**1T<x>_Zielbetriebssystem::
+3*2Tdarwin_Darwin/Mac OS X
+3*2Temx_OS/2 via EMX (einschliesslich EMX/RSX extender)
+3*2Tfreebsd_FreeBSD
+3*2Tgo32v2_Version 2 des DJ Delorie DOS extender
+3*2Tlinux_Linux
+3*2Tnetbsd_NetBSD
+3*2Tnetware_Novell Netware Module (clib)
+3*2Tnetwlibc_Novell Netware Module (libc)
+3*2Topenbsd_OpenBSD
+3*2Tos2_OS/2 / eComStation
+3*2Tsunos_SunOS/Solaris
+3*2Tsymbian_Symbian OS
+3*2Tsolaris_Solaris
+3*2Twatcom_Watcom compatible DOS extender
+3*2Twdosx_WDOSX DOS extender
+3*2Twin32_Windows 32 Bit
+3*2Twince_Windows CE
+4*2Tdarwin_Darwin/Mac OS X
+4*2Tlinux_Linux
+4*2Twin64_Win64 (64 bit Windows systems)
+6*2Tamiga_Commodore Amiga
+6*2Tatari_Atari ST/STe/TT
+6*2Tlinux_Linux
+6*2Tpalmos_PalmOS
+A*2Tdarwin_Darwin/iPhoneOS/iOS
+A*2Tlinux_Linux
+A*2Twince_Windows CE
+P*2Tamiga_AmigaOS
+P*2Tdarwin_Darwin und Mac OS X
+P*2Tlinux_Linux
+P*2Tmacos_Mac OS (classic)
+P*2Tmorphos_MorphOS
+S*2Tsolaris_Solaris
+S*2Tlinux_Linux
+**1u<x>_Entferne die Definition für das Symbol <x>
+**1U<x>_Unit-Optionen:
+**2Un_Prüfe den Unitnamen nicht
+**2Ur_Erzeuge "release unit"-Dateien
+**2Us_Erzeuge eine Systemunit
+**1v<x>_Meldungen, <x> ist eine Kombination der folgenden Zeichen:
+**2*_e : Fehler (Standard) 0 : Nichts (ausser Fehlern)
+**2*_w : Warnungen u : Unit Informationen
+**2*_n : Anmerkungen t : Angesprochene/benutzte Dateien
+**2*_h : Hinweise c : Preprozessordirektiven
+**2*_i : Allgemeine Informationen d : Debug Informationen
+**2*_l : Zeilennummern r : Rhide/GCC kompatibler Modus
+**2*_s : Zeitstempel q : Nummer der Meldung
+**2*_a : Alles x : Exe-Datei Informationen (nur Win32)
+**2*_b : Schreibe bei Meldungen mit p : Schreibe tree.log mit Analysenbaum (parse tree)
+**2*_ Dateinamen den vollständigen v : Schreibe fpcdebug.txt mit
+**2*_ Pfad ganz viel Information
+**2*_m<x>,<y> : Zeige die Meldungen mit den Nummern <x> und <y> nicht
+**1W<x>_Spezifiziere ein natives Programm (Windows)
+3*2WA_Spezifiziere ein natives Programm (Windows)
+4*2WA_Spezifiziere ein natives Programm (Windows)
+A*2WA_Spezifiziere ein natives Programm (Windows)
+3*2Wb_Erzeuge statt einer Bibliothek ein Bundle (Darwin)
+P*2Wb_Erzeuge statt einer Bibliothek ein Bundle (Darwin)
+p*2Wb_Erzeuge statt einer Bibliothek ein Bundle (Darwin)
+A*2Wb_Erzeuge statt einer Bibliothek ein Bundle (Darwin)
+4*2Wb_Erzeuge statt einer Bibliothek ein Bundle (Darwin)
+3*2WB_Erzeuge ein relozierbares Image (Windows, Symbian)
+3*2WBxxxx_Setze die Imagebasis auf xxxx (Windows, Symbian)
+4*2WB_Erzeuge ein relozierbares Image (Windows)
+4*2WBxxxx_Setze die Imagebasis auf xxxx (Windows, Symbian)
+A*2WB_Erzeuge ein relozierbares Image (Windows, Symbian)
+A*2WBxxxx_Setze die Imagebasis auf xxxx (Windows)
+3*2WC_Spezifiziere "console type application" (EMX, OS/2, Windows)
+4*2WC_Spezifiziere "console type application" (EMX, OS/2, Windows)
+A*2WC_Spezifiziere "console type application" (Windows)
+P*2WC_Spezifiziere "console type application" (Classic Mac OS)
+3*2WD_Benutze DEFFILE um Funktionen der DLL oder EXE zu exportieren (Windows)
+4*2WD_Benutze DEFFILE um Funktionen der DLL oder EXE zu exportieren (Windows)
+A*2WD_Benutze DEFFILE um Funktionen der DLL oder EXE zu exportieren (Windows)
+3*2We_Benutze externe Resourcen (Darwin)
+4*2We_Benutze externe Resourcen (Darwin)
+A*2We_Benutze externe Resourcen (Darwin)
+P*2We_Benutze externe Resourcen (Darwin)
+p*2We_Benutze externe Resourcen (Darwin)
+3*2WF_Spezifiziere "full-screen type application" (EMX, OS/2)
+3*2WG_Spezifiziere "graphic type application" (EMX, OS/2, Windows)
+4*2WG_Spezifiziere "graphic type application" (EMX, OS/2, Windows)
+A*2WG_Spezifiziere "graphic type application" (Windows)
+P*2WG_Spezifiziere "graphic type application" (Classic Mac OS)
+3*2Wi_Benutze interne Resourcen (Darwin)
+4*2Wi_Benutze interne Resourcen (Darwin)
+A*2Wi_Benutze interne Resourcen (Darwin)
+P*2Wi_Benutze interne Resourcen (Darwin)
+p*2Wi_Benutze interne Resourcen (Darwin)
+3*2WI_Die Verwendung der "import"-Abschnitte ein/ausschalten (Windows)
+4*2WI_Die Verwendung der "import"-Abschnitte ein/ausschalten (Windows)
+A*2WI_Die Verwendung der "import"-Abschnitte ein/ausschalten (Windows)
+3*2WN_Erzeuge keinen "relocation code" (notwendig für debugging) (Windows)
+4*2WN_Erzeuge keinen "relocation code" (notwendig für debugging) (Windows)
+A*2WN_Erzeuge keinen "relocation code" (notwendig für debugging) (Windows)
+A*2Wpxxxx_Spezifiziere den Kontrollertyp, mögliche Werte liefert fpc -i
+V*2Wpxxxx_Spezifiziere den Kontrollertyp, mögliche Werte liefert fpc -i
+3*2WR_Erzeuge "relocation code" (Windows)
+4*2WR_Erzeuge "relocation code" (Windows)
+A*2WR_Erzeuge "relocation code" (Windows)
+P*2WF_Spezifiziere "MPW tool type application" (Classic Mac OS)
+**2WX_Ermögliche den executable stack (Linux)
+**1X_Programm-Optionen:
+**2Xc_Ãœbergebe --shared an den Linker (nur Unix)
+**2Xd_Den Standard Bibliotheks-Suchpfad NICHT nutzen (benötigt für cross compile)
+**2Xe_Verwende den externen Linker
+**2Xg_Erstelle die Debug-Informationen in einer separaten Datei und einen "Debug-Link"-Abschnitt im ausführbaren Programm
+**2XD_Versuche Units dynamisch zu linken (definiert FPC_LINK_DYNAMIC)
+**2Xi_Verwende den internen Linker
+**2Xm_Erzeuge die "link map"
+**2XM<x>_Setze den Namen der 'main' program Routine (default ist 'main')
+**2XP<x>_Stelle den Namen der Compiler-Hilfsprogrammen den Prefix <x> voran
+**2Xr<x>_Setze den rlink-Pfad des Linker zu <x> (benötigt für cross compile, siehe ld-Manual für mehr Informationen) (BeOS, Linux)
+**2XR<x>_Stelle allen Linker-Suchpfaden den Namen <x> voran (BeOS, Darwin, FreeBSD, Linux, Mac OS, Solaris)
+**2Xs_Entferne alle Symbole aus der ausführbaren Datei
+**2XS_Versuche Units statisch zu linken (default) (definiert FPC_LINK_STATIC)
+**2Xt_Linke mit statischen Bibliotheken (-static wird an den Linker übergeben)
+**2XX_Versuche Units smart zu linken (definiert FPC_LINK_SMART)
+**1*_
+**1?_Zeigt diese Hilfe an
+**1h_Zeigt diese Hilfe ohne Warten an
+]
+
+#
+# The End...
+#
diff --git a/closures/compiler/msg/errore.msg b/closures/compiler/msg/errore.msg
new file mode 100644
index 0000000000..0611192936
--- /dev/null
+++ b/closures/compiler/msg/errore.msg
@@ -0,0 +1,3445 @@
+#
+# This file is part of the Free Pascal Compiler
+# Copyright (c) 1999-2009 by the Free Pascal Development team
+#
+# English (default) Language File for Free Pascal
+#
+# See the file COPYING.FPC, included in this distribution,
+# for details about the copyright.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#
+#
+# The constants are build in the following order:
+# <part>_<type>_<txtidentifier>
+#
+# <part> is the part of the compiler the message is used
+# asmr_ assembler parsing
+# asmw_ assembler writing/binary writers
+# unit_ unit handling
+# scan_ scanner
+# parser_ parser
+# type_ type checking
+# general_ general info
+# exec_ calls to assembler, external linker, binder
+# link_ internal linker
+#
+# <type> the type of the message it should normally used for
+# f_ fatal error
+# e_ error
+# w_ warning
+# n_ note
+# h_ hint
+# i_ info
+# l_ add linenumber
+# u_ used
+# t_ tried
+# c_ conditional
+# d_ debug message
+# x_ executable informations
+# o_ normal (e.g., "press enter to continue")
+#
+# <type> can contain a minus sign at the beginning to mark that
+# the message is off by default. Look at type_w_explicit_string_cast
+# for example.
+
+#
+# General
+#
+# 01023 is the last used one
+#
+# BeginOfTeX
+% \section{General compiler messages}
+% This section gives the compiler messages which are not fatal, but which
+% display useful information. The number of such messages can be
+% controlled with the various verbosity level \var{-v} switches.
+% \begin{description}
+general_t_compilername=01000_T_Compiler: $1
+% When the \var{-vt} switch is used, this line tells you what compiler
+% is used.
+general_d_sourceos=01001_D_Compiler OS: $1
+% When the \var{-vd} switch is used, this line tells you what the source
+% operating system is.
+general_i_targetos=01002_I_Target OS: $1
+% When the \var{-vd} switch is used, this line tells you what the target
+% operating system is.
+general_t_exepath=01003_T_Using executable path: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for its binaries.
+general_t_unitpath=01004_T_Using unit path: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for compiled units. You can set this path with the \var{-Fu} option.
+general_t_includepath=01005_T_Using include path: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for its include files (files used in \var{\{\$I xxx\}} statements).
+% You can set this path with the \var{-Fi} option.
+general_t_librarypath=01006_T_Using library path: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for the libraries. You can set this path with the \var{-Fl} option.
+general_t_objectpath=01007_T_Using object path: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for object files you link in (files used in \var{\{\$L xxx\}} statements).
+% You can set this path with the \var{-Fo} option.
+general_i_abslines_compiled=01008_I_$1 lines compiled, $2 sec$3
+% When the \var{-vi} switch is used, the compiler reports the number
+% of lines compiled, and the time it took to compile them (real time,
+% not program time).
+general_f_no_memory_left=01009_F_No memory left
+% The compiler doesn't have enough memory to compile your program. There are
+% several remedies for this:
+% \begin{itemize}
+% \item If you're using the build option of the compiler, try compiling the
+% different units manually.
+% \item If you're compiling a huge program, split it up into units, and compile
+% these separately.
+% \item If the previous two don't work, recompile the compiler with a bigger
+% heap. (You can use the \var{-Ch} option for this, \seeo{Ch}.)
+% \end{itemize}
+general_i_writingresourcefile=01010_I_Writing Resource String Table file: $1
+% This message is shown when the compiler writes the Resource String Table
+% file containing all the resource strings for a program.
+general_e_errorwritingresourcefile=01011_E_Writing Resource String Table file: $1
+% This message is shown when the compiler encounters an error when writing
+% the Resource String Table file.
+general_i_fatal=01012_I_Fatal:
+% Prefix for Fatal Errors.
+general_i_error=01013_I_Error:
+% Prefix for Errors.
+general_i_warning=01014_I_Warning:
+% Prefix for Warnings.
+general_i_note=01015_I_Note:
+% Prefix for Notes.
+general_i_hint=01016_I_Hint:
+% Prefix for Hints.
+general_e_path_does_not_exist=01017_E_Path "$1" does not exist
+% The specified path does not exist.
+general_f_compilation_aborted=01018_F_Compilation aborted
+% Compilation was aborted.
+general_text_bytes_code=01019_bytes code
+% The size of the generated executable code, in bytes.
+general_text_bytes_data=01020_bytes data
+% The size of the generated program data, in bytes.
+general_i_number_of_warnings=01021_I_$1 warning(s) issued
+% Total number of warnings issued during compilation.
+general_i_number_of_hints=01022_I_$1 hint(s) issued
+% Total number of hints issued during compilation.
+general_i_number_of_notes=01023_I_$1 note(s) issued
+% Total number of notes issued during compilation.
+general_f_ioerror=01024_F_I/O error: $1
+% During compilation an I/O error happened which allows no further compilation.
+general_f_oserror=01025_F_Operating system error: $1
+% During compilation an operanting system error happened which allows no further compilation.
+% \end{description}
+#
+# Scanner
+#
+# 02087 is the last used one
+#
+% \section{Scanner messages.}
+% This section lists the messages that the scanner emits. The scanner takes
+% care of the lexical structure of the pascal file, i.e. it tries to find
+% reserved words, strings, etc. It also takes care of directives and
+% conditional compilation handling.
+% \begin{description}
+scan_f_end_of_file=02000_F_Unexpected end of file
+% This typically happens in one of the following cases:
+% \begin{itemize}
+% \item The source file ends before the final \var{end.} statement. This
+% happens mostly when the \var{begin} and \var{end} statements aren't
+% balanced;
+% \item An include file ends in the middle of a statement.
+% \item A comment was not closed.
+% \end{itemize}
+scan_f_string_exceeds_line=02001_F_String exceeds line
+% There is a missing closing ' in a string, so it occupies
+% multiple lines.
+scan_f_illegal_char=02002_F_illegal character "$1" ($2)
+% An illegal character was encountered in the input file.
+scan_f_syn_expected=02003_F_Syntax error, "$1" expected but "$2" found
+% This indicates that the compiler expected a different token than
+% the one you typed. It can occur almost anywhere it is possible to make an error
+% against the Pascal language.
+scan_t_start_include_file=02004_TL_Start reading includefile $1
+% When you provide the \var{-vt} switch, the compiler tells you
+% when it starts reading an included file.
+scan_w_comment_level=02005_W_Comment level $1 found
+% When the \var{-vw} switch is used, then the compiler warns you if
+% it finds nested comments. Nested comments are not allowed in Turbo Pascal
+% and Delphi, and can be a possible source of errors.
+scan_n_ignored_switch=02008_N_Ignored compiler switch "$1"
+% With \var{-vn} on, the compiler warns if it ignores a switch.
+scan_w_illegal_switch=02009_W_Illegal compiler switch "$1"
+% You included a compiler switch (i.e. \var{\{\$... \}}) which the compiler
+% does not recognise.
+scan_w_switch_is_global=02010_W_Misplaced global compiler switch
+% The compiler switch is misplaced, and should be located at
+% the start of the unit or program.
+scan_e_illegal_char_const=02011_E_Illegal char constant
+% This happens when you specify a character with its ASCII code, as in
+% \var{\#96}, but the number is either illegal, or out of range.
+scan_f_cannot_open_input=02012_F_Can't open file "$1"
+% \fpc cannot find the program or unit source file you specified on the
+% command line.
+scan_f_cannot_open_includefile=02013_F_Can't open include file "$1"
+% \fpc cannot find the source file you specified in a \var{\{\$include ..\}}
+% statement.
+scan_e_illegal_pack_records=02015_E_Illegal record alignment specifier "$1"
+% You are specifying \var{\{\$PACKRECORDS n\} } or \var{\{\$ALIGN n\} }
+% with an illegal value for \var{n}. For \$PACKRECORDS valid alignments are 1, 2, 4, 8, 16, 32, C,
+% NORMAL, DEFAULT, and for \$ALIGN valid alignments are 1, 2, 4, 8, 16, 32, ON,
+% OFF. Under mode MacPas \$ALIGN also supports MAC68K, POWER and RESET.
+scan_e_illegal_pack_enum=02016_E_Illegal enum minimum-size specifier "$1"
+% You are specifying the \var{\{\$PACKENUM n\}} with an illegal value for
+% \var{n}. Only 1,2,4, NORMAL or DEFAULT is valid here.
+scan_e_endif_expected=02017_E_$ENDIF expected for $1 $2 defined in $3 line $4
+% Your conditional compilation statements are unbalanced.
+scan_e_preproc_syntax_error=02018_E_Syntax error while parsing a conditional compiling expression
+% There is an error in the expression following the \var{\{\$if ..\}}, \var{\{\$ifc \}}
+% or \var{\{\$setc \}} compiler directives.
+scan_e_error_in_preproc_expr=02019_E_Evaluating a conditional compiling expression
+% There is an error in the expression following the \var{\{\$if ..\}}, $ifc or $setc compiler
+% directives.
+scan_w_macro_cut_after_255_chars=02020_W_Macro contents are limited to 255 characters in length
+% The contents of macros cannot be longer than 255 characters.
+scan_e_endif_without_if=02021_E_ENDIF without IF(N)DEF
+% Your \var{\{\$IFDEF ..\}} and {\{\$ENDIF\}} statements aren't balanced.
+scan_f_user_defined=02022_F_User defined: $1
+% A user defined fatal error occurred. See also the \progref.
+scan_e_user_defined=02023_E_User defined: $1
+% A user defined error occurred. See also the \progref.
+scan_w_user_defined=02024_W_User defined: $1
+% A user defined warning occurred. See also the \progref.
+scan_n_user_defined=02025_N_User defined: $1
+% A user defined note was encountered. See also the \progref.
+scan_h_user_defined=02026_H_User defined: $1
+% A user defined hint was encountered. See also the \progref.
+scan_i_user_defined=02027_I_User defined: $1
+% User defined information was encountered. See also the \progref.
+scan_e_keyword_cant_be_a_macro=02028_E_Keyword redefined as macro has no effect
+% You cannot redefine keywords with macros.
+scan_f_macro_buffer_overflow=02029_F_Macro buffer overflow while reading or expanding a macro
+% Your macro or its result was too long for the compiler.
+scan_w_macro_too_deep=02030_W_Expanding of macros exceeds a depth of 16.
+% When expanding a macro, macros have been nested to a level of 16.
+% The compiler will expand no further, since this may be a sign that
+% recursion is used.
+scan_w_wrong_styled_switch=02031_W_compiler switches aren't supported in // styled comments
+% Compiler switches should be in normal Pascal style comments.
+scan_d_handling_switch=02032_DL_Handling switch "$1"
+% When you set debugging info on (\var{-vd}) the compiler tells you when it
+% is evaluating conditional compile statements.
+scan_c_endif_found=02033_CL_ENDIF $1 found
+% When you turn on conditional messages (\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifdef_found=02034_CL_IFDEF $1 found, $2
+% When you turn on conditional messages (\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifopt_found=02035_CL_IFOPT $1 found, $2
+% When you turn on conditional messages (\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_if_found=02036_CL_IF $1 found, $2
+% When you turn on conditional messages (\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifndef_found=02037_CL_IFNDEF $1 found, $2
+% When you turn on conditional messages (\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_else_found=02038_CL_ELSE $1 found, $2
+% When you turn on conditional messages (\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_skipping_until=02039_CL_Skipping until...
+% When you turn on conditional messages (\var{-vc}), the compiler tells you
+% where it encounters conditional statements, and whether it is skipping or
+% compiling parts.
+scan_i_press_enter=02040_I_Press <return> to continue
+% When the \var{-vi} switch is used, the compiler stops compilation
+% and waits for the \var{Enter} key to be pressed when it encounters
+% a \var{\{\$STOP\}} directive.
+scan_w_unsupported_switch=02041_W_Unsupported switch "$1"
+% When warnings are turned on (\var{-vw}), the compiler warns you about
+% unsupported switches. This means that the switch is used in Delphi or
+% Turbo Pascal, but not in \fpc.
+scan_w_illegal_directive=02042_W_Illegal compiler directive "$1"
+% When warnings are turned on (\var{-vw}), the compiler warns you about
+% unrecognised switches. For a list of recognised switches, see the \progref.
+scan_t_back_in=02043_TL_Back in $1
+% When you use the \var{-vt} switch, the compiler tells you when it has finished
+% reading an include file.
+scan_w_unsupported_app_type=02044_W_Unsupported application type: "$1"
+% You get this warning if you specify an unknown application type
+% with the directive \var{\{\$APPTYPE\}}.
+scan_w_app_type_not_support=02045_W_APPTYPE is not supported by the target OS
+% The \var{\{\$APPTYPE\}} directive is supported by certain operating systems only.
+scan_w_description_not_support=02046_W_DESCRIPTION is not supported by the target OS
+% The \var{\{\$DESCRIPTION\}} directive is not supported on this target OS.
+scan_n_version_not_support=02047_N_VERSION is not supported by target OS
+% The \var{\{\$VERSION\}} directive is not supported on this target OS.
+scan_n_only_exe_version=02048_N_VERSION only for exes or DLLs
+% The \var{\{\$VERSION\}} directive is only used for executable or DLL sources.
+scan_w_wrong_version_ignored=02049_W_Wrong format for VERSION directive "$1"
+% The \var{\{\$VERSION\}} directive format is majorversion.minorversion
+% where majorversion and minorversion are words.
+scan_e_illegal_asmmode_specifier=02050_E_Illegal assembler style specified "$1"
+% When you specify an assembler mode with the \var{\{\$ASMMODE xxx\}} directive,
+% the compiler didn't recognize the mode you specified.
+scan_w_no_asm_reader_switch_inside_asm=02051_W_ASM reader switch is not possible inside asm statement, "$1" will be effective only for next
+% It is not possible to switch from one assembler reader to another
+% inside an assembler block. The new reader will be used for next
+% assembler statements only.
+scan_e_wrong_switch_toggle=02052_E_Wrong switch toggle, use ON/OFF or +/-
+% You need to use ON or OFF or a + or - to toggle the switch.
+scan_e_resourcefiles_not_supported=02053_E_Resource files are not supported for this target
+% The target you are compiling for doesn't support resource files.
+scan_w_include_env_not_found=02054_W_Include environment "$1" not found in environment
+% The included environment variable can't be found in the environment; it will
+% be replaced by an empty string instead.
+scan_e_invalid_maxfpureg_value=02055_E_Illegal value for FPU register limit
+% Valid values for this directive are 0..8 and NORMAL/DEFAULT.
+scan_w_only_one_resourcefile_supported=02056_W_Only one resource file is supported for this target
+% The target you are compiling for supports only one resource file.
+% The first resource file found is used, the others are discarded.
+scan_w_macro_support_turned_off=02057_W_Macro support has been turned off
+% A macro declaration has been found, but macro support is currently off,
+% so the declaration will be ignored. To turn macro support on compile with
+% -Sm on the command line or add \{\$MACRO ON\} in the source.
+scan_e_invalid_interface_type=02058_E_Illegal interface type specified. Valids are COM, CORBA or DEFAULT.
+% The interface type that was specified is not supported.
+scan_w_appid_not_support=02059_W_APPID is only supported for PalmOS
+% The \var{\{\$APPID\}} directive is only supported for the PalmOS target.
+scan_w_appname_not_support=02060_W_APPNAME is only supported for PalmOS
+% The \var{\{\$APPNAME\}} directive is only supported for the PalmOS target.
+scan_e_string_exceeds_255_chars=02061_E_Constant strings can't be longer than 255 chars
+% A single string constant can contain at most 255 chars. Try splitting up the
+% string into multiple smaller parts and concatenate them with a + operator.
+scan_f_include_deep_ten=02062_F_Including include files exceeds a depth of 16.
+% When including include files the files have been nested to a level of 16.
+% The compiler will expand no further, since this may be a sign that
+% recursion is used.
+scan_e_too_many_push=02063_F_Too many levels of PUSH
+% A maximum of 20 levels is allowed. This error occurs only in mode MacPas.
+scan_e_too_many_pop=02064_E_A POP without a preceding PUSH
+% This error occurs only in mode MacPas.
+scan_e_error_macro_lacks_value=02065_E_Macro or compile time variable "$1" does not have any value
+% Thus the conditional compile time expression cannot be evaluated.
+scan_e_wrong_switch_toggle_default=02066_E_Wrong switch toggle, use ON/OFF/DEFAULT or +/-/*
+% You need to use ON or OFF or DEFAULT or a + or - or * to toggle the switch.
+scan_e_mode_switch_not_allowed=02067_E_Mode switch "$1" not allowed here
+% A mode switch has already been encountered, or, in the case of option -Mmacpas,
+% a mode switch occurs after UNIT.
+scan_e_error_macro_undefined=02068_E_Compile time variable or macro "$1" is not defined.
+% Thus the conditional compile time expression cannot be evaluated. Only in mode MacPas.
+scan_e_utf8_bigger_than_65535=02069_E_UTF-8 code greater than 65535 found
+% \fpc handles UTF-8 strings internally as widestrings, i.e. the char codes are limited to 65535.
+scan_e_utf8_malformed=02070_E_Malformed UTF-8 string
+% The given string isn't a valid UTF-8 string.
+scan_c_switching_to_utf8=02071_C_UTF-8 signature found, using UTF-8 encoding
+% The compiler found a UTF-8 encoding signature (\$ef, \$bb, \$bf) at the beginning of a file,
+% so it interprets it as a UTF-8 file.
+scan_e_compile_time_typeerror=02072_E_Compile time expression: Wanted $1 but got $2 at $3
+% The type-check of a compile time expression failed.
+scan_n_app_type_not_support=02073_N_APPTYPE is not supported by the target OS
+% The \var{\{\$APPTYPE\}} directive is supported by certain operating systems only.
+scan_e_illegal_optimization_specifier=02074_E_Illegal optimization specified "$1"
+% You specified an optimization with the \var{\{\$OPTIMIZATION xxx\}} directive,
+% and the compiler didn't recognize the optimization you specified.
+scan_w_setpeflags_not_support=02075_W_SETPEFLAGS is not supported by the target OS
+% The \var{\{\$SETPEFLAGS\}} directive is not supported by the target OS.
+scan_w_imagebase_not_support=02076_W_IMAGEBASE is not supported by the target OS
+% The \var{\{\$IMAGEBASE\}} directive is not supported by the target OS.
+scan_w_minstacksize_not_support=02077_W_MINSTACKSIZE is not supported by the target OS
+% The \var{\{\$MINSTACKSIZE\}} directive is not supported by the target OS.
+scan_w_maxstacksize_not_support=02078_W_MAXSTACKSIZE is not supported by the target OS
+% The \var{\{\$MAXSTACKSIZE\}} directive is not supported by the target OS.
+scanner_e_illegal_warn_state=02079_E_Illegal state "$1" for $WARN directive
+% Only ON and OFF can be used as state with a \var{\{\$WARN\}} compiler directive.
+scan_e_only_packset=02080_E_Illegal set packing value
+% Only 0, 1, 2, 4, 8, DEFAULT and NORMAL are allowed as packset parameters.
+scan_w_pic_ignored=02081_W_PIC directive or switch ignored
+% Several targets, such as \windows, do not support nor need PIC,
+% so the PIC directive and switch are ignored.
+scan_w_unsupported_switch_by_target=02082_W_The switch "$1" is not supported by the currently selected target
+% Some compiler switches like \$E are not supported by all targets.
+scan_w_frameworks_darwin_only=02084_W_Framework-related options are only supported for Darwin/Mac OS X
+% Frameworks are not a known concept, or at least not supported by FPC,
+% on operating systems other than Darwin/Mac OS X.
+scan_e_illegal_minfpconstprec=02085_E_Illegal minimal floating point constant precision "$1"
+% Valid minimal precisions for floating point constants are default, 32 and 64,
+% which mean respectively minimal (usually 32 bit), 32 bit and 64 bit precision.
+scan_w_multiple_main_name_overrides=02086_W_Overriding name of "main" procedure multiple times, was previously set to "$1"
+% The name for the main entry procedure is specified more than once. Only the last
+% name will be used.
+scanner_w_illegal_warn_identifier=02087_W_Illegal identifier "$1" for $WARN directive
+% Identifier is not known by a \var{\{\$WARN\}} compiler directive.
+scanner_e_illegal_alignment_directive=02088_E_Illegal alignment directive
+% The alignment directive is not valid. Either the alignment type is not known or the alignment
+% value is not a power of two.
+% \end{description}
+#
+# Parser
+#
+# 03314 is the last used one
+#
+% \section{Parser messages}
+% This section lists all parser messages. The parser takes care of the
+% semantics of you language, i.e. it determines if your Pascal constructs
+% are correct.
+% \begin{description}
+parser_e_syntax_error=03000_E_Parser - Syntax Error
+% An error against the Turbo Pascal language was encountered. This typically
+% happens when an illegal character is found in the source file.
+parser_e_dont_nest_interrupt=03004_E_INTERRUPT procedure can't be nested
+% An \var{INTERRUPT} procedure must be global.
+parser_w_proc_directive_ignored=03005_W_Procedure type "$1" ignored
+% The specified procedure directive is ignored by FPC programs.
+parser_e_no_overload_for_all_procs=03006_E_Not all declarations of "$1" are declared with OVERLOAD
+% When you want to use overloading using the \var{OVERLOAD} directive, then
+% all declarations need to have \var{OVERLOAD} specified.
+parser_e_export_name_double=03008_E_Duplicate exported function name "$1"
+% Exported function names inside a specific DLL must all be different.
+parser_e_export_ordinal_double=03009_E_Duplicate exported function index $1
+% Exported function indexes inside a specific DLL must all be different.
+parser_e_export_invalid_index=03010_E_Invalid index for exported function
+% DLL function index must be in the range \var{1..\$FFFF}.
+parser_w_parser_reloc_no_debug=03011_W_Relocatable DLL or executable $1 debug info does not work, disabled.
+% It is currently not possible to include debug information in a relocatable DLL.
+parser_w_parser_win32_debug_needs_WN=03012_W_To allow debugging for win32 code you need to disable relocation with -WN option
+% Stabs debug info is wrong for relocatable DLL or EXES. Use -WN
+% if you want to debug win32 executables.
+parser_e_constructorname_must_be_init=03013_E_Constructor name must be INIT
+% You are declaring an object constructor with a name which is not \var{init}, and the
+% \var{-Ss} switch is in effect. See the switch \seeo{Ss}.
+parser_e_destructorname_must_be_done=03014_E_Destructor name must be DONE
+% You are declaring an object destructor with a name which is not \var{done}, and the
+% \var{-Ss} switch is in effect. See the switch \seeo{Ss}.
+parser_e_proc_inline_not_supported=03016_E_Procedure type INLINE not supported
+% You tried to compile a program with C++ style inlining, and forgot to
+% specify the \var{-Si} option (\seeo{Si}). The compiler doesn't support C++
+% styled inlining by default.
+parser_w_constructor_should_be_public=03018_W_Constructor should be public
+% Constructors must be in the 'public' part of an object (class) declaration.
+parser_w_destructor_should_be_public=03019_W_Destructor should be public
+% Destructors must be in the 'public' part of an object (class) declaration.
+parser_n_only_one_destructor=03020_N_Class should have one destructor only
+% You can declare only one destructor for a class.
+parser_e_no_local_objects=03021_E_Local class definitions are not allowed
+% Classes must be defined globally. They cannot be defined inside a
+% procedure or function.
+parser_f_no_anonym_objects=03022_F_Anonymous class definitions are not allowed
+% An invalid object (class) declaration was encountered, i.e. an
+% object or class without methods that isn't derived from another object or
+% class. For example:
+% \begin{verbatim}
+% Type o = object
+% a : longint;
+% end;
+% \end{verbatim}
+% will trigger this error.
+parser_n_object_has_no_vmt=03023_N_The object "$1" has no VMT
+% This is a note indicating that the declared object has no
+% virtual method table.
+parser_e_illegal_parameter_list=03024_E_Illegal parameter list
+% You are calling a function with parameters that are of a different type than
+% the declared parameters of the function.
+parser_e_wrong_parameter_size=03026_E_Wrong number of parameters specified for call to "$1"
+% There is an error in the parameter list of the function or procedure --
+% the number of parameters is not correct.
+parser_e_overloaded_no_procedure=03027_E_overloaded identifier "$1" isn't a function
+% The compiler encountered a symbol with the same name as an overloaded
+% function, but it is not a function it can overload.
+parser_e_overloaded_have_same_parameters=03028_E_overloaded functions have the same parameter list
+% You're declaring overloaded functions, but with the same parameter list.
+% Overloaded function must have at least 1 different parameter in their
+% declaration.
+parser_e_header_dont_match_forward=03029_E_function header doesn't match the previous declaration "$1"
+% You declared a function with the same parameters but
+% different result type or function modifiers.
+parser_e_header_different_var_names=03030_E_function header "$1" doesn't match forward : var name changes $2 => $3
+% You declared the function in the \var{interface} part, or with the
+% \var{forward} directive, but defined it with a different parameter list.
+parser_n_duplicate_enum=03031_N_Values in enumeration types have to be ascending
+% \fpc allows enumeration constructions as in C. Examine the following
+% two declarations:
+% \begin{verbatim}
+% type a = (A_A,A_B,A_E:=6,A_UAS:=200);
+% type a = (A_A,A_B,A_E:=6,A_UAS:=4);
+% \end{verbatim}
+% The second declaration would produce an error. \var{A\_UAS} needs to have a
+% value higher than \var{A\_E}, i.e. at least 7.
+parser_e_no_with_for_variable_in_other_segments=03033_E_With cannot be used for variables in a different segment
+% With stores a variable locally on the stack,
+% but this is not possible if the variable belongs to another segment.
+parser_e_too_much_lexlevel=03034_E_function nesting > 31
+% You can nest function definitions only 31 levels deep.
+parser_e_range_check_error=03035_E_range check error while evaluating constants
+% The constants are out of their allowed range.
+parser_w_range_check_error=03036_W_range check error while evaluating constants
+% The constants are out of their allowed range.
+parser_e_double_caselabel=03037_E_duplicate case label
+% You are specifying the same label 2 times in a \var{case} statement.
+parser_e_case_lower_less_than_upper_bound=03038_E_Upper bound of case range is less than lower bound
+% The upper bound of a \var{case} label is less than the lower bound and this
+% is useless.
+parser_e_type_const_not_possible=03039_E_typed constants of classes or interfaces are not allowed
+% You cannot declare a constant of type class or object.
+parser_e_no_overloaded_procvars=03040_E_functions variables of overloaded functions are not allowed
+% You are trying to assign an overloaded function to a procedural variable.
+% This is not allowed.
+parser_e_invalid_string_size=03041_E_string length must be a value from 1 to 255
+% The length of a shortstring in Pascal is limited to 255 characters. You are
+% trying to declare a string with length less than 1 or greater than 255.
+parser_w_use_extended_syntax_for_objects=03042_W_use extended syntax of NEW and DISPOSE for instances of objects
+% If you have a pointer \var{a} to an object type, then the statement
+% \var{new(a)} will not initialize the object (i.e. the constructor isn't
+% called), although space will be allocated. You should issue the
+% \var{new(a,init)} statement. This will allocate space, and call the
+% constructor of the object.
+parser_w_no_new_dispose_on_void_pointers=03043_W_use of NEW or DISPOSE for untyped pointers is meaningless
+parser_e_no_new_dispose_on_void_pointers=03044_E_use of NEW or DISPOSE is not possible for untyped pointers
+% You cannot use \var{new(p)} or \var{dispose(p)} if \var{p} is an untyped pointer
+% because no size is associated to an untyped pointer.
+% It is accepted for compatibility in \var{TP} and \var{DELPHI} modes, but the
+% compiler will still warn you if it finds such a construct.
+parser_e_class_id_expected=03045_E_class identifier expected
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., an object or class method, but the type in front of the dot is not
+% a known type.
+parser_e_no_type_not_allowed_here=03046_E_type identifier not allowed here
+% You cannot use a type inside an expression.
+parser_e_methode_id_expected=03047_E_method identifier expected
+% This identifier is not a method.
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., an object or class method, but the procedure name is not a
+% procedure of this type.
+parser_e_header_dont_match_any_member=03048_E_function header doesn't match any method of this class "$1"
+% This identifier is not a method.
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., an object or class method, but the procedure name is not a
+% procedure of this type.
+parser_d_procedure_start=03049_DL_procedure/function $1
+% When using the \var{-vd} switch, the compiler tells you when it starts
+% processing a procedure or function implementation.
+parser_e_error_in_real=03050_E_Illegal floating point constant
+% The compiler expects a floating point expression, and gets something else.
+parser_e_fail_only_in_constructor=03051_E_FAIL can be used in constructors only
+% You are using the \var{fail} keyword outside a constructor method.
+parser_e_no_paras_for_destructor=03052_E_Destructors can't have parameters
+% You are declaring a destructor with a parameter list. Destructor methods
+% cannot have parameters.
+parser_e_only_class_members_via_class_ref=03053_E_Only class methods, class properties and class variables can be referred with class references
+% This error occurs in a situation like the following:
+% \begin{verbatim}
+% Type :
+% Tclass = Class of Tobject;
+%
+% Var C : TClass;
+%
+% begin
+% ...
+% C.free
+% \end{verbatim}
+% \var{Free} is not a class method and hence cannot be called with a class
+% reference.
+parser_e_only_class_members=03054_E_Only class methods, class properties and class variables can be accessed in class methods
+% This is related to the previous error. You cannot call a method of an object
+% from inside a class method. The following code would produce this error:
+% \begin{verbatim}
+% class procedure tobject.x;
+%
+% begin
+% free
+% \end{verbatim}
+% Because free is a normal method of a class it cannot be called from a class
+% method.
+parser_e_case_mismatch=03055_E_Constant and CASE types do not match
+% One of the labels is not of the same type as the case variable.
+parser_e_illegal_symbol_exported=03056_E_The symbol can't be exported from a library
+% You can only export procedures and functions when you write a library. You
+% cannot export variables or constants.
+parser_w_should_use_override=03057_W_An inherited method is hidden by "$1"
+% A method that is declared \var{virtual} in a parent class, should be
+% overridden in the descendant class with the \var{override} directive. If you
+% don't specify the \var{override} directive, you will hide the parent method;
+% you will not override it.
+parser_e_nothing_to_be_overridden=03058_E_There is no method in an ancestor class to be overridden: "$1"
+% You are trying to \var{override} a virtual method of a parent class that does
+% not exist.
+parser_e_no_procedure_to_access_property=03059_E_No member is provided to access property
+% You specified no \var{read} directive for a property.
+parser_w_stored_not_implemented=03060_W_Stored property directive is not yet implemented
+% This message is no longer used, as the \var{stored} directive has been implemented.
+parser_e_ill_property_access_sym=03061_E_Illegal symbol for property access
+% There is an error in the \var{read} or \var{write} directives for an array
+% property. When you declare an array property, you can only access it with
+% procedures and functions. The following code would cause such an error.
+% \begin{verbatim}
+% tmyobject = class
+% i : integer;
+% property x [i : integer]: integer read I write i;
+% \end{verbatim}
+%
+parser_e_cant_access_protected_member=03062_E_Cannot access a protected field of an object here
+% Fields that are declared in a \var{protected} section of an object or class
+% declaration cannot be accessed outside the module where the object is
+% defined, or outside descendent object methods.
+parser_e_cant_access_private_member=03063_E_Cannot access a private field of an object here
+% Fields that are declared in a \var{private} section of an object or class
+% declaration cannot be accessed outside the module where the class is
+% defined.
+parser_e_overridden_methods_not_same_ret=03066_E_Overridden methods must have the same return type: "$2" is overridden by "$1" which has another return type
+% If you declare overridden methods in a class definition, they must
+% have the same return type.
+parser_e_dont_nest_export=03067_E_EXPORT declared functions can't be nested
+% You cannot declare a function or procedure within a function or procedure
+% that was declared as an export procedure.
+parser_e_methods_dont_be_export=03068_E_Methods can't be EXPORTed
+% You cannot declare a procedure that is a method for an object as
+% \var{export}ed.
+parser_e_call_by_ref_without_typeconv=03069_E_Call by var for arg no. $1 has to match exactly: Got "$2" expected "$3"
+% When calling a function declared with \var{var} parameters, the variables in
+% the function call must be of exactly the same type. There is no automatic
+% type conversion.
+parser_e_no_super_class=03070_E_Class isn't a parent class of the current class
+% When calling inherited methods, you are trying to call a method of a non-related
+% class. You can only call an inherited method of a parent class.
+parser_e_self_not_in_method=03071_E_SELF is only allowed in methods
+% You are trying to use the \var{self} parameter outside an object's method.
+% Only methods get passed the \var{self} parameters.
+parser_e_generic_methods_only_in_methods=03072_E_Methods can be only in other methods called direct with type identifier of the class
+% A construction like \var{sometype.somemethod} is only allowed in a method.
+parser_e_illegal_colon_qualifier=03073_E_Illegal use of ':'
+% You are using the format \var{:} (colon) 2 times on an expression that
+% is not a real expression.
+parser_e_illegal_set_expr=03074_E_range check error in set constructor or duplicate set element
+% The declaration of a set contains an error. Either one of the elements is
+% outside the range of the set type, or two of the elements are in fact
+% the same.
+parser_e_pointer_to_class_expected=03075_E_Pointer to object expected
+% You specified an illegal type in a \var{new} statement.
+% The extended syntax of \var{new} needs an object as a parameter.
+parser_e_expr_have_to_be_constructor_call=03076_E_Expression must be constructor call
+% When using the extended syntax of \var{new}, you must specify the constructor
+% method of the object you are trying to create. The procedure you specified
+% is not a constructor.
+parser_e_expr_have_to_be_destructor_call=03077_E_Expression must be destructor call
+% When using the extended syntax of \var{dispose}, you must specify the
+% destructor method of the object you are trying to dispose of.
+% The procedure you specified is not a destructor.
+parser_e_invalid_record_const=03078_E_Illegal order of record elements
+% When declaring a constant record, you specified the fields in the wrong
+% order.
+parser_e_false_with_expr=03079_E_Expression type must be class or record type
+% A \var{with} statement needs an argument that is of the type \var{record}
+% or \var{class}. You are using \var{with} on an expression that is not of
+% this type.
+parser_e_void_function=03080_E_Procedures can't return a value
+% In \fpc, you can specify a return value for a function when using
+% the \var{exit} statement. This error occurs when you try to do this with a
+% procedure. Procedures cannot return a value.
+parser_e_only_methods_allowed=03081_E_constructors, destructors and class operators must be methods
+% You're declaring a procedure as destructor, constructor or class operator, when the
+% procedure isn't a class method.
+parser_e_operator_not_overloaded=03082_E_Operator is not overloaded
+% You're trying to use an overloaded operator when it is not overloaded for
+% this type.
+parser_e_no_such_assignment=03083_E_Impossible to overload assignment for equal types
+% You cannot overload assignment for types
+% that the compiler considers as equal.
+parser_e_overload_impossible=03084_E_Impossible operator overload
+% The combination of operator, arguments and return type are
+% incompatible.
+parser_e_no_reraise_possible=03085_E_Re-raise isn't possible there
+% You are trying to re-raise an exception where it is not allowed. You can only
+% re-raise exceptions in an \var{except} block.
+parser_e_no_new_or_dispose_for_classes=03086_E_The extended syntax of new or dispose isn't allowed for a class
+% You cannot generate an instance of a class with the extended syntax of
+% \var{new}. The constructor must be used for that. For the same reason, you
+% cannot call \var{dispose} to de-allocate an instance of a class, the
+% destructor must be used for that.
+parser_e_procedure_overloading_is_off=03088_E_Procedure overloading is switched off
+% When using the \var{-So} switch, procedure overloading is switched off.
+% Turbo Pascal does not support function overloading.
+parser_e_overload_operator_failed=03089_E_It is not possible to overload this operator. Related overloadable operators (if any) are: $1
+% You are trying to overload an operator which cannot be overloaded.
+% The following operators can be overloaded :
+% \begin{verbatim}
+% +, -, *, /, =, >, <, <=, >=, is, as, in, **, :=
+% \end{verbatim}
+parser_e_comparative_operator_return_boolean=03090_E_Comparative operator must return a boolean value
+% When overloading the \var{=} operator, the function must return a boolean
+% value.
+parser_e_only_virtual_methods_abstract=03091_E_Only virtual methods can be abstract
+% You are declaring a method as abstract, when it is not declared to be
+% virtual.
+parser_f_unsupported_feature=03092_F_Use of unsupported feature!
+% You're trying to force the compiler into doing something it cannot do yet.
+parser_e_mix_of_classes_and_objects=03093_E_The mix of different kind of objects (class, object, interface, etc) isn't allowed
+% You cannot derive \var{objects}, \var{classes}, \var{cppclasses} and \var{interfaces} intertwined. E.g.
+% a class cannot have an object as parent and vice versa.
+parser_w_unknown_proc_directive_ignored=03094_W_Unknown procedure directive had to be ignored: "$1"
+% The procedure directive you specified is unknown.
+parser_e_absolute_only_one_var=03095_E_absolute can only be associated to one variable
+% You cannot specify more than one variable before the \var{absolute} directive.
+% Thus, the following construct will provide this error:
+% \begin{verbatim}
+% Var Z : Longint;
+% X,Y : Longint absolute Z;
+% \end{verbatim}
+parser_e_absolute_only_to_var_or_const=03096_E_absolute can only be associated with a var or const
+% The address of an \var{absolute} directive can only point to a variable or
+% constant. Therefore, the following code will produce this error:
+% \begin{verbatim}
+% Procedure X;
+%
+% var p : longint absolute x;
+% \end{verbatim}
+parser_e_initialized_only_one_var=03097_E_Only one variable can be initialized
+% You cannot specify more than one variable with a initial value in Delphi mode.
+parser_e_abstract_no_definition=03098_E_Abstract methods shouldn't have any definition (with function body)
+% Abstract methods can only be declared, you cannot implement them. They
+% should be overridden by a descendant class.
+parser_e_overloaded_must_be_all_global=03099_E_This overloaded function can't be local (must be exported)
+% You are defining an overloaded function in the implementation part of a unit,
+% but there is no corresponding declaration in the interface part of the unit.
+parser_w_virtual_without_constructor=03100_W_Virtual methods are used without a constructor in "$1"
+% If you declare objects or classes that contain virtual methods, you need
+% to have a constructor and destructor to initialize them. The compiler
+% encountered an object or class with virtual methods that doesn't have
+% a constructor/destructor pair.
+parser_c_macro_defined=03101_CL_Macro defined: $1
+% When \var{-vc} is used, the compiler tells you when it defines macros.
+parser_c_macro_undefined=03102_CL_Macro undefined: $1
+% When \var{-vc} is used, the compiler tells you when it undefines macros.
+parser_c_macro_set_to=03103_CL_Macro $1 set to $2
+% When \var{-vc} is used, the compiler tells you what values macros get.
+parser_i_compiling=03104_I_Compiling $1
+% When you turn on information messages (\var{-vi}), the compiler tells you
+% what units it is recompiling.
+parser_u_parsing_interface=03105_UL_Parsing interface of unit $1
+% This tells you that the reading of the interface
+% of the current unit has started
+parser_u_parsing_implementation=03106_UL_Parsing implementation of $1
+% This tells you that the code reading of the implementation
+% of the current unit, library or program starts
+parser_d_compiling_second_time=03107_DL_Compiling $1 for the second time
+% When you request debug messages (\var{-vd}) the compiler tells you what
+% units it recompiles for the second time.
+parser_e_no_property_found_to_override=03109_E_No property found to override
+% You want to override a property of a parent class, when there is, in fact,
+% no such property in the parent class.
+parser_e_only_one_default_property=03110_E_Only one default property is allowed
+% You specified a property as \var{Default}, but the class already has a
+% default property, and a class can have only one default property.
+parser_e_property_need_paras=03111_E_The default property must be an array property
+% Only array properties of classes can be made \var{default} properties.
+parser_e_constructor_cannot_be_not_virtual=03112_E_Virtual constructors are only supported in class object model
+% You cannot have virtual constructors in objects. You can only have them
+% in classes.
+parser_e_no_default_property_available=03113_E_No default property available
+% You are trying to access a default property of a class, but this class (or one of
+% its ancestors) doesn't have a default property.
+parser_e_cant_have_published=03114_E_The class can't have a published section, use the {$M+} switch
+% If you want a \var{published} section in a class definition, you must
+% use the \var{\{\$M+\}} switch, which turns on generation of type
+% information.
+parser_e_forward_declaration_must_be_resolved=03115_E_Forward declaration of class "$1" must be resolved here to use the class as ancestor
+% To be able to use an object as an ancestor object, it must be defined
+% first. This error occurs in the following situation:
+% \begin{verbatim}
+% Type ParentClas = Class;
+% ChildClass = Class(ParentClass)
+% ...
+% end;
+% \end{verbatim}
+% where \var{ParentClass} is declared but not defined.
+parser_e_no_local_operator=03116_E_Local operators not supported
+% You cannot overload locally, i.e. inside procedures or function
+% definitions.
+parser_e_proc_dir_not_allowed_in_interface=03117_E_Procedure directive "$1" not allowed in interface section
+% This procedure directive is not allowed in the \var{interface} section of
+% a unit. You can only use it in the \var{implementation} section.
+parser_e_proc_dir_not_allowed_in_implementation=03118_E_Procedure directive "$1" not allowed in implementation section
+% This procedure directive is not allowed in the \var{implementation} section of
+% a unit. You can only use it in the \var{interface} section.
+parser_e_proc_dir_not_allowed_in_procvar=03119_E_Procedure directive "$1" not allowed in procvar declaration
+% This procedure directive cannot be part of a procedural or function
+% type declaration.
+parser_e_function_already_declared_public_forward=03120_E_Function is already declared Public/Forward "$1"
+% You will get this error if a function is defined as \var{forward} twice.
+% Or if it occurs in the \var{interface} section, and again as a \var{forward}
+% declaration in the \var{implementation} section.
+parser_e_not_external_and_export=03121_E_Can't use both EXPORT and EXTERNAL
+% These two procedure directives are mutually exclusive.
+parser_w_not_supported_for_inline=03123_W_"$1" not yet supported inside inline procedure/function
+% Inline procedures don't support this declaration.
+parser_w_inlining_disabled=03124_W_Inlining disabled
+% Inlining of procedures is disabled.
+parser_i_writing_browser_log=03125_I_Writing Browser log $1
+% When information messages are on, the compiler warns you when it
+% writes the browser log (generated with the \var{\{\$Y+ \}} switch).
+parser_h_maybe_deref_caret_missing=03126_H_may be pointer dereference is missing
+% The compiler thinks that a pointer may need a dereference.
+parser_f_assembler_reader_not_supported=03127_F_Selected assembler reader not supported
+% The selected assembler reader (with \var{\{\$ASMMODE xxx\}} is not
+% supported. The compiler can be compiled with or without support for a
+% particular assembler reader.
+parser_e_proc_dir_conflict=03128_E_Procedure directive "$1" has conflicts with other directives
+% You specified a procedure directive that conflicts with other directives.
+% For instance \var{cdecl} and \var{pascal} are mutually exclusive.
+parser_e_call_convention_dont_match_forward=03129_E_Calling convention doesn't match forward
+% This error happens when you declare a function or procedure with
+% e.g. \var{cdecl;} but omit this directive in the implementation, or vice
+% versa. The calling convention is part of the function declaration, and
+% must be repeated in the function definition.
+parser_e_property_cant_have_a_default_value=03131_E_Property can't have a default value
+% Set properties or indexed properties cannot have a default value.
+parser_e_property_default_value_must_const=03132_E_The default value of a property must be constant
+% The value of a \var{default} declared property must be known at compile
+% time. The value you specified is only known at run time. This happens
+% e.g. if you specify a variable name as a default value.
+parser_e_cant_publish_that=03133_E_Symbol can't be published, can be only a class
+% Only class type variables can be in a \var{published} section of a class
+% if they are not declared as a property.
+parser_e_cant_publish_that_property=03134_E_This kind of property can't be published
+% Properties in a \var{published} section cannot be array properties.
+% They must be moved to public sections. Properties in a \var{published}
+% section must be an ordinal type, a real type, strings or sets.
+parser_e_empty_import_name=03136_E_An import name is required
+% Some targets need a name for the imported procedure or a \var{cdecl} specifier.
+parser_e_division_by_zero=03138_E_Division by zero
+% A division by zero was encounted.
+parser_e_invalid_float_operation=03139_E_Invalid floating point operation
+% An operation on two real type values produced an overflow or a division
+% by zero.
+parser_e_array_lower_less_than_upper_bound=03140_E_Upper bound of range is less than lower bound
+% The upper bound of an array declaration is less than the lower bound and this
+% is not possible.
+parser_w_string_too_long=03141_W_string "$1" is longer than "$2"
+% The size of the constant string is larger than the size you specified in
+% string type definition.
+parser_e_string_larger_array=03142_E_string length is larger than array of char length
+% The size of the constant string is larger than the size you specified in
+% the \var{Array[x..y] of char} definition.
+parser_e_ill_msg_expr=03143_E_Illegal expression after message directive
+% \fpc supports only integer or string values as message constants.
+parser_e_ill_msg_param=03144_E_Message handlers can take only one call by ref. parameter
+% A method declared with the \var{message} directive as message handler
+% can take only one parameter which must be declared as call by reference.
+% Parameters are declared as call by reference using the \var{var}-directive.
+parser_e_duplicate_message_label=03145_E_Duplicate message label: "$1"
+% A label for a message is used twice in one object/class.
+parser_e_self_in_non_message_handler=03146_E_Self can only be an explicit parameter in methods which are message handlers
+% The \var{Self} parameter can only be passed explicitly to a method which
+% is declared as message handler.
+parser_e_threadvars_only_sg=03147_E_Threadvars can be only static or global
+% Threadvars must be static or global; you can't declare a thread
+% local to a procedure. Local variables are always local to a thread,
+% because every thread has its own stack and local variables
+% are stored on the stack.
+parser_f_direct_assembler_not_allowed=03148_F_Direct assembler not supported for binary output format
+% You can't use direct assembler when using a binary writer. Choose an
+% other output format or use another assembler reader.
+parser_w_no_objpas_use_mode=03149_W_Don't load OBJPAS unit manually, use \{\$mode objfpc\} or \{\$mode delphi\} instead
+% You are trying to load the \file{ObjPas} unit manually from a \var{uses} clause.
+% This is not a good idea. Use the \var{\{\$MODE OBJFPC\}} or
+% \var{\{\$mode delphi\}} directives which load the unit automatically.
+parser_e_no_object_override=03150_E_OVERRIDE can't be used in objects
+% \var{Override} is not supported for objects, use \var{virtual} instead to override
+% a method of a parent object.
+parser_e_cant_use_inittable_here=03151_E_Data types which require initialization/finalization can't be used in variant records
+% Some data types (e.g. \var{ansistring}) need initialization/finalization
+% code which is implicitly generated by the compiler. Such data types
+% can't be used in the variant part of a record.
+parser_e_resourcestring_only_sg=03152_E_Resourcestrings can be only static or global
+% Resourcestring cannot be declared local, only global or using the static
+% directive.
+parser_e_exit_with_argument_not__possible=03153_E_Exit with argument can't be used here
+% An exit statement with an argument for the return value can't be used here. This
+% can happen for example in \var{try..except} or \var{try..finally} blocks.
+parser_e_stored_property_must_be_boolean=03154_E_The type of the storage symbol must be boolean
+% If you specify a storage symbol in a property declaration, it must be a
+% boolean type.
+parser_e_ill_property_storage_sym=03155_E_This symbol isn't allowed as storage symbol
+% You can't use this type of symbol as storage specifier in property
+% declaration. You can use only methods with the result type boolean,
+% boolean class fields or boolean constants.
+parser_e_only_publishable_classes_can_be_published=03156_E_Only classes which are compiled in $M+ mode can be published
+% A class-typed field in the published section of a class can only be a class which was
+% compiled in \var{\{\$M+\}} or which is derived from such a class. Normally
+% such a class should be derived from \var{TPersistent}.
+parser_e_proc_directive_expected=03157_E_Procedure directive expected
+% This error is triggered when you have a \var{\{\$Calling\}} directive without
+% a calling convention specified.
+% It also happens when declaring a procedure in a const block and you
+% used a ; after a procedure declaration which must be followed by a
+% procedure directive.
+% Correct declarations are:
+% \begin{verbatim}
+% const
+% p : procedure;stdcall=nil;
+% p : procedure stdcall=nil;
+% \end{verbatim}
+parser_e_invalid_property_index_value=03158_E_The value for a property index must be of an ordinal type
+% The value you use to index a property must be of an ordinal type, for
+% example an integer or enumerated type.
+parser_e_procname_to_short_for_export=03159_E_Procedure name too short to be exported
+% The length of the procedure/function name must be at least 2 characters
+% long. This is because of a bug in dlltool which doesn't parse the .def
+% file correctly with a name of length 1.
+parser_e_dlltool_unit_var_problem=03160_E_No DEFFILE entry can be generated for unit global vars
+parser_e_dlltool_unit_var_problem2=03161_E_Compile without -WD option
+% You need to compile this file without the -WD switch on the
+% command line.
+parser_f_need_objfpc_or_delphi_mode=03162_F_You need ObjFpc (-S2) or Delphi (-Sd) mode to compile this module
+% You need to use \var{\{\$MODE OBJFPC\}} or \var{\{\$MODE DELPHI\}} to compile this file.
+% Or use the corresponding command line switch, either \var{-Mobjfpc} or \var{-MDelphi.}
+parser_e_no_export_with_index_for_target=03163_E_Can't export with index under $1
+% Exporting of functions or procedures with a specified index is not
+% supported on this target.
+parser_e_no_export_of_variables_for_target=03164_E_Exporting of variables is not supported under $1
+% Exporting of variables is not supported on this target.
+parser_e_improper_guid_syntax=03165_E_Improper GUID syntax
+% The GUID indication does not have the proper syntax. It should be of the form
+% \begin{verbatim}
+% {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}
+% \end{verbatim}
+% Where each \var{X} represents a hexadecimal digit.
+parser_w_interface_mapping_notfound=03168_W_Procedure named "$1" not found that is suitable for implementing the $2.$3
+% The compiler cannot find a suitable procedure which implements the given method of an interface.
+% A procedure with the same name is found, but the arguments do not match.
+parser_e_interface_id_expected=03169_E_interface identifier expected
+% This happens when the compiler scans a \var{class} declaration that contains
+% \var{interface} function name mapping code like this:
+% \begin{verbatim}
+% type
+% TMyObject = class(TObject, IDispatch)
+% function IUnknown.QueryInterface=MyQueryInterface;
+% ....
+% \end{verbatim}
+% and the \var{interface} before the dot is not listed in the inheritance list.
+parser_e_type_cant_be_used_in_array_index=03170_E_Type "$1" can't be used as array index type
+% Types like \var{qword} or \var{int64} aren't allowed as array index type.
+parser_e_no_con_des_in_interfaces=03171_E_Con- and destructors aren't allowed in interfaces
+% Constructor and destructor declarations aren't allowed in interfaces.
+% In the most cases method \var{QueryInterface} of \var{IUnknown} can
+% be used to create a new interface.
+parser_e_no_access_specifier_in_interfaces=03172_E_Access specifiers can't be used in INTERFACEs and OBJCPROTOCOLs
+% The access specifiers \var{public}, \var{private}, \var{protected} and
+% \var{published} can't be used in interfaces, Objective-C protocols and categories because all methods
+% of an interface/protocol/category must be public.
+parser_e_no_vars_in_interfaces=03173_E_An interface, helper or Objective-C protocol or category cannot contain fields
+% Declarations of fields are not allowed in interfaces, helpers and Objective-C protocols and categories.
+% An interface/helper/protocol/category can contain only methods and properties with method read/write specifiers.
+parser_e_no_local_proc_external=03174_E_Can't declare local procedure as EXTERNAL
+% Declaring local procedures as external is not possible. Local procedures
+% get hidden parameters that will make the chance of errors very high.
+parser_w_skipped_fields_before=03175_W_Some fields coming before "$1" weren't initialized
+% In Delphi mode, not all fields of a typed constant record have to be
+% initialized, but the compiler warns you when it detects such situations.
+parser_e_skipped_fields_before=03176_E_Some fields coming before "$1" weren't initialized
+% In all syntax modes but Delphi mode, you can't leave some fields uninitialized
+% in the middle of a typed constant record.
+parser_w_skipped_fields_after=03177_W_Some fields coming after "$1" weren't initialized
+% You can leave some fields at the end of a type constant record uninitialized
+% (The compiler will initialize them to zero automatically). This may be the cause
+% of subtle problems.
+parser_e_varargs_need_cdecl_and_external=03178_E_VarArgs directive (or '...' in MacPas) without CDecl/CPPDecl/MWPascal and External
+% The varargs directive (or the ``...'' varargs parameter in MacPas mode) can only be
+% used with procedures or functions that are declared with \var{external} and one of
+% \var{cdecl}, \var{cppdecl} and \var{mwpascal}. This functionality
+% is only supported to provide a compatible interface to C functions like printf.
+parser_e_self_call_by_value=03179_E_Self must be a normal (call-by-value) parameter
+% You can't declare \var{Self} as a const or var parameter, it must always be
+% a call-by-value parameter.
+parser_e_interface_has_no_guid=03180_E_Interface "$1" has no interface identification
+% When you want to assign an interface to a constant, then the interface
+% must have a GUID value set.
+parser_e_illegal_field_or_method=03181_E_Unknown class field or method identifier "$1"
+% Properties must refer to a field or method in the same class.
+parser_w_proc_overriding_calling=03182_W_Overriding calling convention "$1" with "$2"
+% There are two directives in the procedure declaration that specify a calling
+% convention. Only the last directive will be used.
+parser_e_no_procvarobj_const=03183_E_Typed constants of the type "procedure of object" can only be initialized with NIL
+% You cannot assign the address of a method to a typed constant which has a
+% 'procedure of object' type, because such a constant requires two addresses:
+% that of the method (which is known at compile time) and that of the object or
+% class instance it operates on (which cannot be known at compile time).
+parser_e_default_value_only_one_para=03184_E_Default value can only be assigned to one parameter
+% It is not possible to specify a default value for several parameters at once.
+% The following is invalid:
+% \begin{verbatim}
+% Procedure MyProcedure (A,B : Integer = 0);
+% \end{verbatim}
+% Instead, this should be declared as
+% \begin{verbatim}
+% Procedure MyProcedure (A : Integer = 0; B : Integer = 0);
+% \end{verbatim}
+parser_e_default_value_expected_for_para=03185_E_Default parameter required for "$1"
+% The specified parameter requires a default value.
+parser_w_unsupported_feature=03186_W_Use of unsupported feature!
+% You're trying to force the compiler into doing something it cannot do yet.
+parser_h_c_arrays_are_references=03187_H_C arrays are passed by reference
+% Any array passed to a C function is passed
+% by a pointer (i.e. by reference).
+parser_e_C_array_of_const_must_be_last=03188_E_C array of const must be the last argument
+% You cannot add any other argument after an \var{array of const} for
+% \var{cdecl} functions, as the size pushed on stack for this argument is
+% not known.
+parser_h_type_redef=03189_H_Type "$1" redefinition
+% This is an indicator that a previously declared type is
+% being redefined as something else. This may, or may not
+% be, a potential source of errors.
+parser_w_cdecl_has_no_high=03190_W_cdecl'ared functions have no high parameter
+% Functions declared with the \var{cdecl} modifier do not pass an extra implicit parameter.
+parser_w_cdecl_no_openstring=03191_W_cdecl'ared functions do not support open strings
+% Openstring is not supported for functions that have the \var{cdecl} modifier.
+parser_e_initialized_not_for_threadvar=03192_E_Cannot initialize variables declared as threadvar
+% Variables declared as threadvar cannot be initialized with a default value.
+% The variables will always be filled with zero at the start of a new thread.
+parser_e_msg_only_for_classes=03193_E_Message directive is only allowed in Classes
+% The message directive is only supported for Class types.
+parser_e_procedure_or_function_expected=03194_E_Procedure or Function expected
+% A class method can only be specified for procedures and functions.
+parser_e_illegal_calling_convention=03195_W_Calling convention directive ignored: "$1"
+% Some calling conventions are supported only by certain CPUs. I.e. most non-i386 ports support
+% only the standard ABI calling convention of the CPU.
+parser_e_no_object_reintroduce=03196_E_REINTRODUCE can't be used in objects
+% \var{reintroduce} is not supported for objects, Objective-C classes and Objective-C protocols.
+parser_e_paraloc_only_one_para=03197_E_Each argument must have its own location
+% If locations for arguments are specified explicitly as it is required by
+% some syscall conventions, each argument must have its own location. Things
+% like
+% \begin{verbatim}
+% procedure p(i,j : longint 'r1');
+% \end{verbatim}
+% aren't allowed.
+parser_e_paraloc_all_paras=03198_E_Each argument must have an explicit location
+% If one argument has an explicit argument location, all arguments of a procedure
+% must have one.
+parser_e_illegal_explicit_paraloc=03199_E_Unknown argument location
+% The location specified for an argument isn't recognized by the compiler.
+parser_e_32bitint_or_pointer_variable_expected=03200_E_32 Bit-Integer or pointer variable expected
+% The libbase for MorphOS/AmigaOS can be given only as \var{longint}, \var{dword} or any pointer variable.
+parser_e_goto_outside_proc=03201_E_Goto statements aren't allowed between different procedures
+% It isn't allowed to use \var{goto} statements referencing labels outside the
+% current procedure. The following example shows the problem:
+% \begin{verbatim}
+% ...
+% procedure p1;
+% label
+% l1;
+%
+% procedure p2;
+% begin
+% goto l1; // This goto ISN'T allowed
+% end;
+%
+% begin
+% p2
+% l1:
+% end;
+% ...
+%
+% \end{verbatim}
+parser_f_too_complex_proc=03202_F_Procedure too complex, it requires too many registers
+% Your procedure body is too long for the compiler. You should split the
+% procedure into multiple smaller procedures.
+parser_e_illegal_expression=03203_E_Illegal expression
+% This can occur under many circumstances. Usually when trying to evaluate
+% constant expressions.
+parser_e_invalid_integer=03204_E_Invalid integer expression
+% You made an expression which isn't an integer, and the compiler expects the
+% result to be an integer.
+parser_e_invalid_qualifier=03205_E_Illegal qualifier
+% One of the following is happening :
+% \begin{itemize}
+% \item You're trying to access a field of a variable that is not a record.
+% \item You're indexing a variable that is not an array.
+% \item You're dereferencing a variable that is not a pointer.
+% \end{itemize}
+parser_e_upper_lower_than_lower=03206_E_High range limit < low range limit
+% You are declaring a subrange, and the high limit is less than the low limit of
+% the range.
+parser_e_macpas_exit_wrong_param=03207_E_Exit's parameter must be the name of the procedure it is used in
+% Non local exit is not allowed. This error occurs only in mode MacPas.
+parser_e_illegal_assignment_to_count_var=03208_E_Illegal assignment to for-loop variable "$1"
+% The type of a \var{for} loop variable must be an ordinal type.
+% Loop variables cannot be reals or strings. You also cannot assign values to
+% loop variables inside the loop (Except in Delphi and TP modes). Use a while or
+% repeat loop instead if you need to do something like that, since those
+% constructs were built for that.
+parser_e_no_local_var_external=03209_E_Can't declare local variable as EXTERNAL
+% Declaring local variables as external is not allowed. Only global variables can reference
+% external variables.
+parser_e_proc_already_external=03210_E_Procedure is already declared EXTERNAL
+% The procedure is already declared with the EXTERNAL directive in an interface or
+% forward declaration.
+parser_w_implicit_uses_of_variants_unit=03211_W_Implicit uses of Variants unit
+% The Variant type is used in the unit without any used unit using the Variants unit. The
+% compiler has implicitly added the Variants unit to the uses list. To remove this warning
+% the Variants unit needs to be added to the uses statement.
+parser_e_no_static_method_in_interfaces=03212_E_Class and static methods can't be used in INTERFACES
+% The specifier \var{class} and directive \var{static} can't be used in interfaces
+% because all methods of an interface must be public.
+parser_e_arithmetic_operation_overflow=03213_E_Overflow in arithmetic operation
+% An operation on two integer values produced an overflow.
+parser_e_protected_or_private_expected=03214_E_Protected or private expected
+% \var{strict} can be only used together with \var{protected} or \var{private}.
+parser_e_illegal_slice=03215_E_SLICE can't be used outside of parameter list
+% \var{slice} can be used only for arguments accepting an open array parameter.
+parser_e_dispinterface_cant_have_parent=03216_E_A DISPINTERFACE can't have a parent class
+% A DISPINTERFACE is a special type of interface which can't have a parent class. Dispinterface always derive from IDispatch type.
+parser_e_dispinterface_needs_a_guid=03217_E_A DISPINTERFACE needs a guid
+% A DISPINTERFACE always needs an interface identification (a GUID).
+parser_w_overridden_methods_not_same_ret=03218_W_Overridden methods must have a related return type. This code may crash, it depends on a Delphi parser bug ("$2" is overridden by "$1" which has another return type)
+% If you declare overridden methods in a class definition, they must
+% have the same return type. Some versions of Delphi allow you to change the
+% return type of interface methods, and even to change procedures into
+% functions, but the resulting code may crash depending on the types used
+% and the way the methods are called.
+parser_e_dispid_must_be_ord_const=03219_E_Dispatch IDs must be ordinal constants
+% The \var{dispid} keyword must be followed by an ordinal constant (the dispid index).
+parser_e_array_range_out_of_bounds=03220_E_The range of the array is too large
+% Regardless of the size taken up by its elements, an array cannot have more
+% than high(ptrint) elements. Additionally, the range type must be a subrange
+% of ptrint.
+parser_e_packed_element_no_var_addr=03221_E_The address cannot be taken of bit packed array elements and record fields
+% If you declare an array or record as \var{packed} in Mac Pascal mode
+% (or as \var{packed} in any mode with \var{\{\$bitpacking on\}}), it will
+% be packed at the bit level. This means it becomes impossible to take addresses
+% of individual array elements or record fields. The only exception to this rule
+% is in the case of packed arrays elements whose packed size is a multple of 8 bits.
+parser_e_packed_dynamic_open_array=03222_E_Dynamic arrays cannot be packed
+% Only regular (and possibly in the future also open) arrays can be packed.
+parser_e_packed_element_no_loop=03223_E_Bit packed array elements and record fields cannot be used as loop variables
+% If you declare an array or record as \var{packed} in Mac Pascal mode
+% (or as \var{packed} in any mode with \var{\{\$bitpacking on\}}), it will
+% be packed at the bit level. For performance reasons, they cannot be
+% used as loop variables.
+parser_e_type_var_const_only_in_records_and_classes=03224_E_VAR, TYPE and CONST are allowed only in records, objects and classes
+% The usage of VAR, TYPE and CONST to declare new types inside an object is allowed only inside
+% records, objects and classes.
+parser_e_cant_create_generics_of_this_type=03225_E_This type can't be a generic
+% Only Classes, Objects, Interfaces and Records are allowed to be used as generic.
+parser_w_no_lineinfo_use_switch=03226_W_Don't load LINEINFO unit manually, Use the -gl compiler switch instead
+% Do not use the \file{lineinfo} unit directly, Use the \var{-gl} switch which
+% automatically adds the correct unit for reading the selected type of debugging
+% information. The unit that needs to be used depends on the type of
+% debug information used when compiling the binary.
+parser_e_no_funcret_specified=03227_E_No function result type specified for function "$1"
+% The first time you declare a function you have to declare it completely,
+% including all parameters and the result type.
+parser_e_special_onlygenerics=03228_E_Specialization is only supported for generic types
+% Types which are not generics can't be specialized.
+parser_e_no_generics_as_params=03229_E_Generics can't be used as parameters when specializing generics
+% When specializing a generic, only non-generic types can be used as parameters.
+parser_e_type_object_constants=03230_E_Constants of objects containing a VMT aren't allowed
+% If an object requires a VMT either because it contains a constructor or virtual methods,
+% it's not allowed to create constants of it. In TP and Delphi mode this is allowed
+% for compatibility reasons.
+parser_e_label_outside_proc=03231_E_Taking the address of labels defined outside the current scope isn't allowed
+% It isn't allowed to take the address of labels outside the
+% current procedure.
+parser_e_initialized_not_for_external=03233_E_Cannot initialize variables declared as external
+% Variables declared as external cannot be initialized with a default value.
+parser_e_illegal_function_result=03234_E_Illegal function result type
+% Some types like file types cannot be used as function result.
+parser_e_no_common_type=03235_E_No common type possible between "$1" and "$2"
+% To perform an operation on integers, the compiler converts both operands
+% to their common type, which appears to be an invalid type. To determine the
+% common type of the operands, the compiler takes the minimum of the minimal values
+% of both types, and the maximum of the maximal values of both types. The common
+% type is then minimum..maximum.
+parser_e_no_generics_as_types=03236_E_Generics without specialization cannot be used as a type for a variable
+% Generics must be always specialized before being used as variable type.
+parser_w_register_list_ignored=03237_W_Register list is ignored for pure assembler routines
+% When using pure assembler routines, the list with modified registers is ignored.
+parser_e_implements_must_be_class_or_interface=03238_E_Implements property must have class or interface type
+% A property which implements an interface must be of type class or interface.
+parser_e_implements_must_have_correct_type=03239_E_Implements-property must implement interface of correct type, found "$1" expected "$2"
+% A property which implements an interface actually implements a different interface.
+parser_e_implements_must_read_specifier=03240_E_Implements-property must have read specifier
+% A property which implements an interface must have at least a read specifier.
+parser_e_implements_must_not_have_write_specifier=03241_E_Implements-property must not have write-specifier
+% A property which implements an interface may not have a write specifier.
+parser_e_implements_must_not_have_stored_specifier=03242_E_Implements-property must not have stored-specifier
+% A property which implements an interface may not have a stored specifier.
+parser_e_implements_uses_non_implemented_interface=03243_E_Implements-property used on unimplemented interface: "$1"
+% The interface which is implemented by a property is not an interface implemented by the class.
+parser_e_unsupported_real=03244_E_Floating point not supported for this target
+% The compiler parsed a floating point expression, but it is not supported.
+parser_e_class_doesnt_implement_interface=03245_E_Class "$1" does not implement interface "$2"
+% The delegated interface is not implemented by the class given in the implements clause.
+parser_e_class_implements_must_be_interface=03246_E_Type used by implements must be an interface
+% The \var{implements} keyword must be followed by an interface type.
+parser_e_cant_export_var_different_name=03247_E_Variables cannot be exported with a different name on this target, add the name to the declaration using the "export" directive (variable name: $1, declared export name: $2)
+% On most targets it is not possible to change the name under which a variable
+% is exported inside the \var{exports} statement of a library.
+% In that case, you have to specify the export name at the point where the
+% variable is declared, using the \var{export} and \var{alias} directives.
+parser_e_weak_external_not_supported=03248_E_Weak external symbols are not supported for the current target
+% A "weak external" symbol is a symbol which may or may not exist at (either static
+% or dynamic) link time. This concept may not be available (or implemented yet)
+% on the current cpu/OS target.
+parser_e_forward_mismatch=03249_E_Forward type definition does not match
+% Classes and interfaces being defined forward must have the same type
+% when being implemented. A forward interface cannot be changed into a class.
+parser_n_ignore_lower_visibility=03250_N_Virtual method "$1" has a lower visibility ($2) than parent class $3 ($4)
+% The virtual method overrides an method that is declared with a higher visibility. This might give
+% unexpected results. In case the new visibility is private than it might be that a call to inherited in a
+% new child class will call the higher visible method in a parent class and ignores the private method.
+parser_e_field_not_allowed_here=03251_E_Fields cannot appear after a method or property definition, start a new visibility section first
+% Once a method or property has been defined in a class or object, you cannot define any fields afterwards
+% without starting a new visibility section (such as \var{public}, \var{private}, etc.). The reason is
+% that otherwise the source code can appear ambiguous to the compiler, since it is possible to use modifiers
+% such as \var{default} and \var{register} also as field names.
+parser_e_no_local_para_def=03252_E_Parameters or result types cannot contain local type definitions. Use a separate type definition in a type block.
+% In Pascal, types are not considered to be identical simply because they are semantically equivalent.
+% Two variables or parameters are only considered to be of the same type if they refer to the
+% same type definition.
+% As a result, it is not allowed to define new types inside parameter lists, because then it is impossible to
+% refer to the same type definition in the procedure headers of the interface and implementation of a unit
+% (both procedure headers would define a separate type). Keep in mind that expressions such as
+% ``file of byte'' or ``string[50]'' also define a new type.
+parser_e_abstract_and_sealed_conflict=03253_E_ABSTRACT and SEALED conflict
+% ABSTRACT and SEALED cannot be used together in one declaration
+parser_e_sealed_descendant=03254_E_Cannot create a descendant of the sealed class "$1"
+% Sealed means that class cannot be derived by another class.
+parser_e_sealed_class_cannot_have_abstract_methods=03255_E_SEALED class cannot have an ABSTRACT method
+% Sealed means that class cannot be derived. Therefore no one class is able to override an abstract method in a sealed class.
+parser_e_only_virtual_methods_final=03256_E_Only virtual methods can be final
+% You are declaring a method as final, when it is not declared to be
+% virtual.
+parser_e_final_can_no_be_overridden=03257_E_Final method cannot be overridden: "$1"
+% You are trying to \var{override} a virtual method of a parent class that does
+% not exist.
+parser_e_multiple_messages=03258_E_Only one message can be used per method.
+% It is not possible to associate multiple messages with a single method.
+parser_e_invalid_enumerator_identifier=03259_E_Invalid enumerator identifier: "$1"
+% Only "MoveNext" and "Current" enumerator identifiers are supported.
+parser_e_enumerator_identifier_required=03260_E_Enumerator identifier required
+% "MoveNext" or "Current" identifier must follow the \var{enumerator} modifier.
+parser_e_enumerator_movenext_is_not_valid=03261_E_Enumerator MoveNext pattern method is not valid. Method must be a function with the Boolean return type and no required arguments.
+% "MoveNext" enumerator pattern method must be a function with Boolean return type and no required arguments
+parser_e_enumerator_current_is_not_valid=03262_E_Enumerator Current pattern property is not valid. Property must have a getter.
+% "Current" enumerator pattern property must have a getter
+parser_e_only_one_enumerator_movenext=03263_E_Only one enumerator MoveNext method is allowed per class/object
+% Class or Object can have only one enumerator MoveNext declaration.
+parser_e_only_one_enumerator_current=03264_E_Only one enumerator Current property is allowed per class/object
+% Class or Object can have only one enumerator Current declaration.
+parser_e_for_in_loop_cannot_be_used_for_the_type=03265_E_For in loop cannot be used for the type "$1"
+% For in loop can be used not for all types. For example it cannot be used for the enumerations with jumps.
+parser_e_objc_requires_msgstr=03266_E_Objective-C messages require their Objective-C selector name to be specified using the "message" directive.
+% Objective-C messages require their Objective-C name (selector name) to be specified using the \var{message `someName:'} procedure directive.
+% While bindings to other languages automatically generate such names based on the identifier you use (by replacing
+% all underscores with colons), this is unsafe since nothing prevents an Objective-C method name to contain actual
+% colons.
+parser_e_objc_no_constructor_destructor=03267_E_Objective-C does not have formal constructors nor destructors. Use the alloc, initXXX and dealloc messages.
+% The Objective-C language does not have any constructors or destructors. While there are some messages with a similar
+% purpose (such as \var{init} and \var{dealloc}), these cannot be identified using automatic parsers and do not
+% guarantee anything like Pascal constructors/destructors (e.g., you have to take care of only calling ``designated''
+% inherited ``constructors''). For these reasons, we have opted to follow the standard Objective-C patterns for
+% instance creation/destruction.
+parser_e_message_string_too_long=03268_E_Message name is too long (max. 255 characters)
+% Due to compiler implementation reasons, message names are currently limited to 255 characters.
+parser_e_objc_message_name_too_long=03269_E_Objective-C message symbol name for "$1" is too long
+% Due to compiler implementation reasons, mangled message names (i.e., the symbol names used in the assembler
+% code) are currently limited to 255 characters.
+parser_h_no_objc_parent=03270_H_Defining a new Objective-C root class. To derive from another root class (e.g., NSObject), specify it as the parent class.
+% If no parent class is specified for an Object Pascal class, then it automatically derives from TObject.
+% Objective-C classes however do not automatically derive from NSObject, because one can have multiple
+% root classes in Objective-C. For example, in the Cocoa framework both NSObject and NSProxy are root classes.
+% Therefore, you have to explicitly define a parent class (such as NSObject) if you want to derive your
+% Objective-C class from it.
+parser_e_no_objc_published=03271_E_Objective-C classes cannot have published sections.
+% In Object Pascal, ``published'' determines whether or not RTTI is generated. Since the Objective-C runtime always needs
+% RTTI for everything, this specified does not make sense for Objective-C classes.
+parser_f_need_objc=03272_F_This module requires an Objective-C mode switch to be compiled
+% This error indicates the use of Objective-C language features without an Objective-C mode switch
+% active. Enable one via the -M command line switch, or the {\$modeswitch x} directive.
+parser_e_must_use_override_objc=03273_E_Inherited methods can only be overridden in Objective-C, add "override" (inherited method defined in $1)
+parser_h_should_use_override_objc=03274_H_Inherited methods can only be overridden in Objective-C, add "override" (inherited method defined in $1).
+% It is not possible to \var{reintroduce} methods in Objective-C like in Object Pascal. Methods with the same
+% name always map to the same virtual method entry. In order to make this clear in the source code,
+% the compiler always requires the \var{override} directive to be specified when implementing overriding
+% Objective-C methods in Pascal. If the implementation is external, this rule is relaxed because Objective-C
+% does not have any \var{override}-style keyword (since it's the default and only behaviour in that language),
+% which makes it hard for automated header conversion tools to include it everywhere.
+% The type in which the inherited method is defined is explicitly mentioned, because this may either
+% be an objcclass or an objccategory.
+parser_e_objc_message_name_changed=03275_E_Message name "$1" in inherited class is different from message name "$2" in current class.
+% An overriding Objective-C method cannot have a different message name than an inherited method. The reason
+% is that these message names uniquely define the message to the Objective-C runtime, which means that
+% giving them a different message name breaks the ``override'' semantics.
+parser_e_no_objc_unique=03276_E_It is not yet possible to make unique copies of Objective-C types
+% Duplicating an Objective-C type using \var{type x = type y;} is not yet supported. You may be able to
+% obtain the desired effect using \var{type x = objcclass(y) end;} instead.
+parser_e_no_category_as_types=03277_E_Objective-C categories and Object Pascal class helpers cannot be used as types
+% It is not possible to declare a variable as an instance of an Objective-C
+% category or an Object Pascal class helper. A category/class helper adds
+% methods to the scope of an existing class, but does not define a type by
+% itself. An exception of this rule is when inheriting an Object Pascal class
+% helper from another class helper.
+parser_e_no_category_override=03278_E_Categories do not override, but replace methods. Use "reintroduce" instead.
+parser_e_must_use_reintroduce_objc=03279_E_Replaced methods can only be reintroduced in Objective-C, add "reintroduce" (replaced method defined in $1).
+parser_h_should_use_reintroduce_objc=03280_H_Replaced methods can only be reintroduced in Objective-C, add "reintroduce" (replaced method defined in $1).
+% A category replaces an existing method in an Objective-C class, rather than that it overrides it.
+% Calling an inherited method from an category method will call that method in
+% the extended class' parent, not in the extended class itself. The
+% replaced method in the original class is basically lost, and can no longer be
+% called or referred to. This behaviour corresponds somewhat more closely to
+% \var{reintroduce} than to \var{override} (although in case of \var{reintroduce}
+% in Object Pascal, hidden methods are still reachable via inherited).
+% The type in which the inherited method is defined is explicitly mentioned, because this may either
+% be an objcclass or an objccategory.
+parser_e_implements_getter_not_default_cc=03281_E_Getter for implements interface must use the target's default calling convention.
+% Interface getters are called via a helper in the run time library, and hence
+% have to use the default calling convention for the target (\var{register} on
+% i386 and x86\_64, \var{stdcall} on other architectures).
+parser_e_no_refcounted_typed_file=03282_E_Typed files cannot contain reference-counted types.
+% The data in a typed file cannot be of a reference counted type (such as
+% \var{ansistring} or a record containing a field that is reference counted).
+parser_e_operator_not_overloaded_2=03283_E_Operator is not overloaded: $2 "$1"
+% You are trying to use an overloaded operator when it is not overloaded for
+% this type.
+parser_e_operator_not_overloaded_3=03284_E_Operator is not overloaded: "$1" $2 "$3"
+% You are trying to use an overloaded operator when it is not overloaded for
+% this type.
+parser_e_more_array_elements_expected=03285_E_Expected another $1 array elements
+% When declaring a typed constant array, you provided to few elements to initialize the array
+parser_e_string_const_too_long=03286_E_String constant too long while ansistrings are disabled
+% Only when a piece of code is compiled with ansistrings enabled (\var{\{\$H+\}}), string constants
+% longer than 255 characters are allowed.
+parser_e_invalid_univ_para=03287_E_Type cannot be used as univ parameter because its size is unknown at compile time: "$1"
+% \var{univ} parameters are compatible with all values of the same size, but this
+% cannot be checked in case a parameter's size is unknown at compile time.
+parser_e_only_one_class_constructor_allowed=03288_E_Only one class constructor can be declared in class: "$1"
+% You are trying to declare more than one class constructor but only one class constructor can be declared.
+parser_e_only_one_class_destructor_allowed=03289_E_Only one class destructor can be declared in class: "$1"
+% You are trying to declare more than one class destructor but only one class destructor can be declared.
+parser_e_no_paras_for_class_constructor=03290_E_Class constructors can't have parameters
+% You are declaring a class constructor with a parameter list. Class constructor methods
+% cannot have parameters.
+parser_e_no_paras_for_class_destructor=03291_E_Class destructors can't have parameters
+% You are declaring a class destructor with a parameter list. Class destructor methods
+% cannot have parameters.
+parser_f_modeswitch_objc_required=03292_F_This construct requires the \{\$modeswitch objectivec1\} mode switch to be active
+% Objective-Pascal constructs are not supported when \{\$modeswitch ObjectiveC1\}
+% is not active.
+parser_e_widestring_to_ansi_compile_time=03293_E_Unicodechar/string constants cannot be converted to ansi/shortstring at compile-time
+% It is not possible to use unicodechar and unicodestring constants in
+% constant expressions that have to be converted into an ansistring or shortstring
+% at compile time, for example inside typed constants. The reason is that the
+% compiler cannot know what the actual ansi encoding will be at run time.
+parser_e_objc_enumerator_2_0=03294_E_For-in Objective-Pascal loops require \{\$modeswitch ObjectiveC2\} to be active
+% Objective-C ``fast enumeration'' support was added in Objective-C 2.0, and
+% hence the appropriate modeswitch has to be activated to expose this feature.
+% Note that Objective-C 2.0 programs require Mac OS X 10.5 or later.
+parser_e_objc_missing_enumeration_defs=03295_E_The compiler cannot find the NSFastEnumerationProtocol or NSFastEnumerationState type in the CocoaAll unit
+% Objective-C for-in loops (fast enumeration) require that the compiler can
+% find a unit called CocoaAll that contains definitions for the
+% NSFastEnumerationProtocol and NSFastEnumerationState types. If you get this
+% error, most likely the compiler is finding and loading an alternate CocoaAll
+% unit.
+parser_e_no_procvarnested_const=03296_E_Typed constants of the type 'procedure is nested' can only be initialized with NIL and global procedures/functions
+% A nested procedural variable consists of two components: the address of the
+% procedure/function to call (which is always known at compile time), and also
+% a parent frame pointer (which is never known at compile time) in case the
+% procedural variable contains a reference to a nested procedure/function.
+% Therefore such typed constants can only be initialized with global
+% functions/procedures since these do not require a parent frame pointer.
+parser_f_no_generic_inside_generic=03297_F_Declaration of generic class inside another generic class is not allowed
+% At the moment, scanner supports recording of only one token buffer at the time
+% (guarded by internal error 200511173 in tscannerfile.startrecordtokens).
+% Since generics are implemented by recording tokens, it is not possible to
+% have declaration of generic class inside another generic class.
+parser_e_forward_protocol_declaration_must_be_resolved=03298_E_Forward declaration of objcprotocol "$1" must be resolved before an objcclass can conform to it
+% An objcprotocol must be fully defined before classes can conform to it.
+% This error occurs in the following situation:
+% \begin{verbatim}
+% Type MyProtocol = objcprotoocl;
+% ChildClass = Class(NSObject,MyProtocol)
+% ...
+% end;
+% \end{verbatim}
+% where \var{MyProtocol} is declared but not defined.
+parser_e_no_record_published=03299_E_Record types cannot have published sections
+% Published sections can be used only inside classes.
+parser_e_no_destructor_in_records=03300_E_Destructors aren't allowed in records or helpers
+% Destructor declarations aren't allowed in records or helpers.
+parser_e_class_methods_only_static_in_records=03301_E_Class methods must be static in records
+% Class methods declarations aren't allowed in records without static modifier.
+% Records have no inheritance and therefore non static class methods have no sence for them.
+parser_e_no_constructor_in_records=03302_E_Constructors aren't allowed in records or record helpers
+% Constructor declarations aren't allowed in records or record helpers.
+parser_e_at_least_one_argument_must_be_of_type=03303_E_Either the result or at least one parameter must be of type "$1"
+% It is required that either the result of the routine or at least one of its parameters be of the specified type.
+% For example class operators either take an instance of the structured type in which they are defined, or they return one.
+parser_e_cant_use_type_parameters_here=03304_E_Type parameters may require initialization/finalization - can't be used in variant records
+% Type parameters may be specialized with types which (e.g. \var{ansistring}) need initialization/finalization
+% code which is implicitly generated by the compiler.
+parser_e_externals_no_section=03305_E_Variables being declared as external cannot be in a custom section
+% A section directive is not valid for variables being declared as external.
+parser_e_section_no_locals=03306_E_Non-static and non-global variables cannot have a section directive
+% A variable placed in a custom section is always statically allocated so it must be either a static or global variable.
+parser_e_not_allowed_in_helper=03307_E_"$1" is not allowed in helper types
+% Some directives and specifiers like "virtual", "dynamic", "override" aren't
+% allowed inside helper types in mode ObjFPC (they are ignored in mode Delphi),
+% because they have no meaning within helpers. Also "abstract" isn't allowed in
+% either mode.
+parser_e_no_class_constructor_in_helpers=03308_E_Class constructors aren't allowed in helpers
+% Class constructor declarations aren't allowed in helpers.
+parser_e_inherited_not_in_record=03309_E_The use of "inherited" is not allowed in a record
+% As records don't suppport inheritance the use of "inherited" is prohibited for
+% these as well as for record helpers (in mode "Delphi" only).
+parser_e_no_types_in_local_anonymous_records=03310_E_Type declarations are not allowed in local or anonymous records
+% Records with types must be defined globally. Types cannot be defined inside records which are defined in a
+% procedure or function or in anonymous records.
+parser_e_duplicate_implements_clause=03311_E_Duplicate implements clause for interface "$1"
+% A class may delegate an interface using the "implements" clause only to a single property. Delegating it multiple times
+% is a error.
+parser_e_mapping_no_implements=03312_E_Interface "$1" can't be delegated by "$2", it already has method resolutions
+% Method resolution clause maps a method of an interface to a method of the current class. Therefore the current class
+% has to implement the interface directly. Delegation is not possible.
+parser_e_implements_no_mapping=03313_E_Interface "$1" can't have method resolutions, "$2" already delegates it
+% Method resoulution is only possible for interfaces that are implemented directly, not by delegation.
+parser_e_invalid_codepage=03314_E_Invalid codepage
+% When declaring a string with a given codepage, the range of valid codepages values is limited
+% to 0 to 65535.
+% \end{description}
+# Type Checking
+#
+# 04108 is the last used one
+#
+% \section{Type checking errors}
+% This section lists all errors that can occur when type checking is
+% performed.
+% \begin{description}
+type_e_mismatch=04000_E_Type mismatch
+% This can happen in many cases:
+% \begin{itemize}
+% \item The variable you're assigning to is of a different type than the
+% expression in the assignment.
+% \item You are calling a function or procedure with parameters that are
+% incompatible with the parameters in the function or procedure definition.
+% \end{itemize}
+type_e_incompatible_types=04001_E_Incompatible types: got "$1" expected "$2"
+% There is no conversion possible between the two types.
+% Another possiblity is that they are declared in different
+% declarations:
+% \begin{verbatim}
+% Var
+% A1 : Array[1..10] Of Integer;
+% A2 : Array[1..10] Of Integer;
+%
+% Begin
+% A1:=A2; { This statement also gives this error. It
+% is due to the strict type checking of Pascal }
+% End.
+% \end{verbatim}
+type_e_not_equal_types=04002_E_Type mismatch between "$1" and "$2"
+% The types are not equal.
+type_e_type_id_expected=04003_E_Type identifier expected
+% The identifier is not a type, or you forgot to supply a type identifier.
+type_e_variable_id_expected=04004_E_Variable identifier expected
+% This happens when you pass a constant to a routine (such as \var{Inc} var or \var{Dec})
+% when it expects a variable. You can only pass variables as arguments to these functions.
+type_e_integer_expr_expected=04005_E_Integer expression expected, but got "$1"
+% The compiler expects an expression of type integer, but gets a different
+% type.
+type_e_boolean_expr_expected=04006_E_Boolean expression expected, but got "$1"
+% The expression must be a boolean type. It should be return \var{True} or
+% \var{False}.
+type_e_ordinal_expr_expected=04007_E_Ordinal expression expected
+% The expression must be of ordinal type, i.e., maximum a \var{Longint}.
+% This happens, for instance, when you specify a second argument
+% to \var{Inc} or \var{Dec} that doesn't evaluate to an ordinal value.
+type_e_pointer_type_expected=04008_E_pointer type expected, but got "$1"
+% The variable or expression isn't of the type \var{pointer}. This
+% happens when you pass a variable that isn't a pointer to \var{New}
+% or \var{Dispose}.
+type_e_class_type_expected=04009_E_class type expected, but got "$1"
+% The variable or expression isn't of the type \var{class}. This happens
+% typically when
+% \begin{enumerate}
+% \item The parent class in a class declaration isn't a class.
+% \item An exception handler (\var{On}) contains a type identifier that
+% isn't a class.
+% \end{enumerate}
+type_e_cant_eval_constant_expr=04011_E_Can't evaluate constant expression
+% This error can occur when the bounds of an array you declared do
+% not evaluate to ordinal constants.
+type_e_set_element_are_not_comp=04012_E_Set elements are not compatible
+% You are trying to perform an operation on two sets, when the set element types
+% are not the same. The base type of a set must be the same when taking the
+% union.
+type_e_set_operation_unknown=04013_E_Operation not implemented for sets
+% several binary operations are not defined for sets.
+% These include: \var{div}, \var{mod}, \var{**}, \var{>=} and \var{<=}.
+% The last two may be defined for sets in the future.
+type_w_convert_real_2_comp=04014_W_Automatic type conversion from floating type to COMP which is an integer type
+% An implicit type conversion from a real type to a \var{comp} is
+% encountered. Since \var{comp} is a 64 bit integer type, this may indicate
+% an error.
+type_h_use_div_for_int=04015_H_use DIV instead to get an integer result
+% When hints are on, then an integer division with the '/' operator will
+% produce this message, because the result will then be of type real.
+type_e_strict_var_string_violation=04016_E_String types have to match exactly in $V+ mode
+% When compiling in \var{\{\$V+\}} mode, the string you pass as a parameter
+% should be of the exact same type as the declared parameter of the procedure.
+type_e_succ_and_pred_enums_with_assign_not_possible=04017_E_succ or pred on enums with assignments not possible
+% If you declare an enumeration type which has C-like assignments
+% in it, such as in the following:
+% \begin{verbatim}
+% Tenum = (a,b,e:=5);
+% \end{verbatim}
+% then you cannot use the \var{Succ} or \var{Pred} functions with this enumeration.
+type_e_cant_read_write_type=04018_E_Can't read or write variables of this type
+% You are trying to \var{read} or \var{write} a variable from or to a
+% file of type text, which doesn't support that variable's type.
+% Only integer types, reals, pchars and strings can be read from or
+% written to a text file. Booleans can only be written to text files.
+type_e_no_readln_writeln_for_typed_file=04019_E_Can't use readln or writeln on typed file
+% \var{readln} and \var{writeln} are only allowed for text files.
+type_e_no_read_write_for_untyped_file=04020_E_Can't use read or write on untyped file.
+% \var{read} and \var{write} are only allowed for text or typed files.
+type_e_typeconflict_in_set=04021_E_Type conflict between set elements
+% There is at least one set element which is of the wrong type, i.e. not of
+% the set type.
+type_w_maybe_wrong_hi_lo=04022_W_lo/hi(dword/qword) returns the upper/lower word/dword
+% \fpc supports an overloaded version of \var{lo/hi} for \var{longint/dword/int64/qword}
+% which returns the lower/upper word/dword of the argument. \tp always uses
+% a 16 bit \var{lo/hi} which always returns bits 0..7 for \var{lo} and the
+% bits 8..15 for \var{hi}. If you want the \tp behavior you have
+% to type cast the argument to a \var{word} or \var{integer}.
+type_e_integer_or_real_expr_expected=04023_E_Integer or real expression expected
+% The first argument to \var{str} must be a real or integer type.
+type_e_wrong_type_in_array_constructor=04024_E_Wrong type "$1" in array constructor
+% You are trying to use a type in an array constructor which is not
+% allowed.
+type_e_wrong_parameter_type=04025_E_Incompatible type for arg no. $1: Got "$2", expected "$3"
+% You are trying to pass an invalid type for the specified parameter.
+type_e_no_method_and_procedure_not_compatible=04026_E_Method (variable) and Procedure (variable) are not compatible
+% You can't assign a method to a procedure variable or a procedure to a
+% method pointer.
+type_e_wrong_math_argument=04027_E_Illegal constant passed to internal math function
+% The constant argument passed to a \var{ln} or \var{sqrt} function is out of
+% the definition range of these functions.
+type_e_no_addr_of_constant=04028_E_Can't take the address of constant expressions
+% It is not possible to get the address of a constant expression, because they
+% aren't stored in memory. You can try making it a typed constant. This error
+% can also be displayed if you try to pass a property to a var parameter.
+type_e_argument_cant_be_assigned=04029_E_Argument can't be assigned to
+% Only expressions which can be on the left side of an
+% assignment can be passed as call by reference arguments.
+%
+% Remark: Properties can be used on the left side of an assignment,
+% nevertheless they cannot be used as arguments.
+type_e_cannot_local_proc_to_procvar=04030_E_Can't assign local procedure/function to procedure variable
+% It's not allowed to assign a local procedure/function to a
+% procedure variable, because the calling convention of a local procedure/function is
+% different. You can only assign local procedure/function to a void pointer.
+type_e_no_assign_to_addr=04031_E_Can't assign values to an address
+% It is not allowed to assign a value to an address of a variable, constant,
+% procedure or function. You can try compiling with -So if the identifier
+% is a procedure variable.
+type_e_no_assign_to_const=04032_E_Can't assign values to const variable
+% It's not allowed to assign a value to a variable which is declared
+% as a const. This is normally a parameter declared as const. To allow
+% changing the value, pass the parameter by value, or a parameter by reference
+% (using var).
+type_e_array_required=04033_E_Array type required
+% If you are accessing a variable using an index '[<x>]' then
+% the type must be an array. In FPC mode a pointer is also allowed.
+type_e_interface_type_expected=04034_E_interface type expected, but got "$1"
+% The compiler expected to encounter an interface type name, but got something else.
+% The following code would produce this error:
+% \begin{verbatim}
+% Type
+% TMyStream = Class(TStream,Integer)
+% \end{verbatim}
+type_h_mixed_signed_unsigned=04035_H_Mixing signed expressions and longwords gives a 64bit result
+% If you divide (or calculate the modulus of) a signed expression by a longword (or vice versa),
+% or if you have overflow and/or range checking turned on and use an arithmetic
+% expression (+, -, *, div, mod) in which both signed numbers and longwords appear,
+% then everything has to be evaluated in 64-bit arithmetic which is slower than normal
+% 32-bit arithmetic. You can avoid this by typecasting one operand so it
+% matches the result type of the other one.
+type_w_mixed_signed_unsigned2=04036_W_Mixing signed expressions and cardinals here may cause a range check error
+% If you use a binary operator (and, or, xor) and one of
+% the operands is a longword while the other one is a signed expression, then,
+% if range checking is turned on, you may get a range check error because in
+% such a case both operands are converted to longword before the operation is
+% carried out. You can avoid this by typecasting one operand so it
+% matches the result type of the other one.
+type_e_typecast_wrong_size_for_assignment=04037_E_Typecast has different size ($1 -> $2) in assignment
+% Type casting to a type with a different size is not allowed when the variable is
+% used in an assignment.
+type_e_array_index_enums_with_assign_not_possible=04038_E_enums with assignments can't be used as array index
+% When you declared an enumeration type which has C-like
+% assignments, such as in the following:
+% \begin{verbatim}
+% Tenum = (a,b,e:=5);
+% \end{verbatim}
+% you cannot use it as the index of an array.
+type_e_classes_not_related=04039_E_Class or Object types "$1" and "$2" are not related
+% There is a typecast from one class or object to another while the class/object
+% are not related. This will probably lead to errors.
+type_w_classes_not_related=04040_W_Class types "$1" and "$2" are not related
+% There is a typecast from one class to another while the classes
+% are not related. This will probably lead to errors.
+type_e_class_or_interface_type_expected=04041_E_Class or interface type expected, but got "$1"
+% The compiler expected a class or interface name, but got another type or identifier.
+type_e_type_is_not_completly_defined=04042_E_Type "$1" is not completely defined
+% This error occurs when a type is not complete: i.e. a pointer type which points to
+% an undefined type.
+type_w_string_too_long=04043_W_String literal has more characters than short string length
+% The size of the constant string, which is assigned to a shortstring,
+% is longer than the maximum size of the shortstring (255 characters).
+type_w_comparison_always_false=04044_W_Comparison might be always false due to range of constant and expression
+% There is a comparison between a constant and an expression where the constant is out of the
+% valid range of values of the expression. Because of type promotion, the statement will always evaluate to
+% false. Explicitly typecast the constant or the expression to the correct range to avoid this warning
+% if you think the code is correct.
+type_w_comparison_always_true=04045_W_Comparison might be always true due to range of constant and expression
+% There is a comparison between a constant and an expression where the constant is out of the
+% valid range of values of the expression. Because of type promotion, the statement will always evaluate to
+% true. Explicitly typecast the constant or the expression to the correct range to avoid this warning
+% if you think the code is correct.
+type_w_instance_with_abstract=04046_W_Constructing a class "$1" with abstract method "$2"
+% An instance of a class is created which contains non-implemented abstract
+% methods. This will probably lead to a runtime error 211 in the code if that
+% routine is ever called. All abstract methods should be overridden.
+type_h_in_range_check=04047_H_The left operand of the IN operator should be byte sized
+% The left operand of the \var{in} operator is not an ordinal or enumeration which fits
+% within 8 bits. This may lead to range check errors. The \var{in} operator
+% currently only supports a left operand which fits within a byte. In the case of
+% enumerations, the size of an element of an enumeration can be controlled with
+% the \var{\{\$PACKENUM\}} or \var{\{\$Zn\}} switches.
+type_w_smaller_possible_range_check=04048_W_Type size mismatch, possible loss of data / range check error
+% There is an assignment to a smaller type than the source type. This means that
+% this may cause a range-check error, or may lead to possible loss of data.
+type_h_smaller_possible_range_check=04049_H_Type size mismatch, possible loss of data / range check error
+% There is an assignment to a smaller type than the source type. This means that
+% this may cause a range-check error, or may lead to possible loss of data.
+type_e_cant_take_address_of_abstract_method=04050_E_The address of an abstract method can't be taken
+% An abstract method has no body, so the address of an abstract method can't be taken.
+type_e_assignment_not_allowed=04051_E_Assignments to formal parameters and open arrays are not possible
+% You are trying to assign a value to a formal (untyped var, const or out)
+% parameter, or to an open array.
+type_e_constant_expr_expected=04052_E_Constant Expression expected
+% The compiler expects an constant expression, but gets a variable expression.
+type_e_operator_not_supported_for_types=04053_E_Operation "$1" not supported for types "$2" and "$3"
+% The operation is not allowed for the supplied types.
+type_e_illegal_type_conversion=04054_E_Illegal type conversion: "$1" to "$2"
+% When doing a type-cast, you must take care that the sizes of the variable and
+% the destination type are the same.
+type_h_pointer_to_longint_conv_not_portable=04055_H_Conversion between ordinals and pointers is not portable
+% If you typecast a pointer to a longint (or vice-versa), this code will not compile
+% on a machine using 64 bits addressing.
+type_w_pointer_to_longint_conv_not_portable=04056_W_Conversion between ordinals and pointers is not portable
+% If you typecast a pointer to an ordinal type of a different size (or vice-versa), this can
+% cause problems. This is a warning to help in finding the 32-bit specific code where cardinal/longint is used
+% to typecast pointers to ordinals. A solution is to use the ptrint/ptruint types instead.
+type_e_cant_choose_overload_function=04057_E_Can't determine which overloaded function to call
+% You're calling overloaded functions with a parameter that doesn't correspond
+% to any of the declared function parameter lists. e.g. when you have declared
+% a function with parameters \var{word} and \var{longint}, and then you call
+% it with a parameter which is of type \var{integer}.
+type_e_illegal_count_var=04058_E_Illegal counter variable
+% The type of a \var{for} loop variable must be an ordinal type.
+% Loop variables cannot be reals or strings.
+type_w_double_c_varargs=04059_W_Converting constant real value to double for C variable argument, add explicit typecast to prevent this.
+% In C, constant real values are double by default. For this reason, if you
+% pass a constant real value to a variable argument part of a C function, FPC
+% by default converts this constant to double as well. If you want to prevent
+% this from happening, add an explicit typecast around the constant.
+type_e_class_or_cominterface_type_expected=04060_E_Class or COM interface type expected, but got "$1"
+% Some operators, such as the AS operator, are only applicable to classes or COM interfaces.
+type_e_no_const_packed_array=04061_E_Constant packed arrays are not yet supported
+% You cannot declare a (bit)packed array as a typed constant.
+type_e_got_expected_packed_array=04062_E_Incompatible type for arg no. $1: Got "$2" expected "(Bit)Packed Array"
+% The compiler expects a (bit)packed array as the specified parameter.
+type_e_got_expected_unpacked_array=04063_E_Incompatible type for arg no. $1: Got "$2" expected "(not packed) Array"
+% The compiler expects a regular (i.e., not packed) array as the specified parameter.
+type_e_no_packed_inittable=04064_E_Elements of packed arrays cannot be of a type which need to be initialised
+% Support for packed arrays of types that need initialization
+% (such as ansistrings, or records which contain ansistrings) is not yet implemented.
+type_e_no_const_packed_record=04065_E_Constant packed records and objects are not yet supported
+% You cannot declare a (bit)packed array as a typed constant at this time.
+type_w_untyped_arithmetic_unportable=04066_W_Arithmetic "$1" on untyped pointer is unportable to {$T+}, suggest typecast
+% Addition/subtraction from an untyped pointer may work differently in \var{\{\$T+\}}.
+% Use a typecast to a typed pointer.
+type_e_cant_take_address_of_local_subroutine=04076_E_Can't take address of a subroutine marked as local
+% The address of a subroutine marked as local can't be taken.
+type_e_cant_export_local=04077_E_Can't export subroutine marked as local from a unit
+% A subroutine marked as local can't be exported from a unit.
+type_e_not_automatable=04078_E_Type is not automatable: "$1"
+% Only byte, integer, longint, smallint, currency, single, double, ansistring,
+% widestring, tdatetime, variant, olevariant, wordbool and all interfaces are automatable.
+type_h_convert_add_operands_to_prevent_overflow=04079_H_Converting the operands to "$1" before doing the add could prevent overflow errors.
+% Adding two types can cause overflow errors. Since you are converting the result to a larger type, you
+% could prevent such errors by converting the operands to this type before doing the addition.
+type_h_convert_sub_operands_to_prevent_overflow=04080_H_Converting the operands to "$1" before doing the subtract could prevent overflow errors.
+% Subtracting two types can cause overflow errors. Since you are converting the result to a larger type, you
+% could prevent such errors by converting the operands to this type before doing the subtraction.
+type_h_convert_mul_operands_to_prevent_overflow=04081_H_Converting the operands to "$1" before doing the multiply could prevent overflow errors.
+% Multiplying two types can cause overflow errors. Since you are converting the result to a larger type, you
+% could prevent such errors by converting the operands to this type before doing the multiplication.
+type_w_pointer_to_signed=04082_W_Converting pointers to signed integers may result in wrong comparison results and range errors, use an unsigned type instead.
+% The virtual address space on 32-bit machines runs from \$00000000 to \$ffffffff.
+% Many operating systems allow you to allocate memory above \$80000000.
+% For example both \windows and \linux allow pointers in the range \$0000000 to \$bfffffff.
+% If you convert pointers to signed types, this can cause overflow and range check errors,
+% but also \$80000000 < \$7fffffff. This can cause random errors in code like "if p>q".
+type_e_interface_has_no_guid=04083_E_Interface type $1 has no valid GUID
+% When applying the as-operator to an interface or class, the desired interface (i.e. the right operand of the
+% as-operator) must have a valid GUID.
+type_e_invalid_objc_selector_name=04084_E_Invalid selector name "$1"
+% An Objective-C selector cannot be empty, must be a valid identifier or a single colon,
+% and if it contains at least one colon it must also end in one.
+type_e_expected_objc_method_but_got=04085_E_Expected Objective-C method, but got $1
+% A selector can only be created for Objective-C methods, not for any other kind
+% of procedure/function/method.
+type_e_expected_objc_method=04086_E_Expected Objective-C method or constant method name
+% A selector can only be created for Objective-C methods, either by specifying
+% the name using a string constant, or by using an Objective-C method identifier
+% that is visible in the current scope.
+type_e_no_type_info=04087_E_No type info available for this type
+% Type information is not generated for some types, such as enumerations with gaps
+% in their value range (this includes enumerations whose lower bound is different
+% from zero).
+type_e_ordinal_or_string_expr_expected=04088_E_Ordinal or string expression expected
+% The expression must be an ordinal or string type.
+type_e_string_expr_expected=04089_E_String expression expected
+% The expression must be a string type.
+type_w_zero_to_nil=04090_W_Converting 0 to NIL
+% Use NIL rather than 0 when initialising a pointer.
+type_e_protocol_type_expected=04091_E_Objective-C protocol type expected, but got "$1"
+% The compiler expected a protocol type name, but found something else.
+type_e_objc_type_unsupported=04092_E_The type "$1" is not supported for interaction with the Objective-C runtime.
+% Objective-C makes extensive use of run time type information (RTTI). This format
+% is defined by the maintainers of the run time and can therefore not be adapted
+% to all possible Object Pascal types. In particular, types that depend on
+% reference counting by the compiler (such as ansistrings and certain kinds of
+% interfaces) cannot be used as fields of Objective-C classes, cannot be
+% directly passed to Objective-C methods, and cannot be encoded using \var{objc\_encode}.
+type_e_class_or_objcclass_type_expected=04093_E_Class or objcclass type expected, but got "$1"
+% It is only possible to create class reference types of \var{class} and \var{objcclass}
+type_e_objcclass_type_expected=04094_E_Objcclass type expected
+% The compiler expected an \var{objcclass} type
+type_w_procvar_univ_conflicting_para=04095_W_Coerced univ parameter type in procedural variable may cause crash or memory corruption: $1 to $2
+% \var{univ} parameters are implicitly compatible with all types of the same size,
+% also in procedural variable definitions. That means that the following code is
+% legal, because \var{single} and \var{longint} have the same size:
+% \begin{verbatim}
+% {$mode macpas}
+% Type
+% TIntProc = procedure (l: univ longint);
+%
+% procedure test(s: single);
+% begin
+% writeln(s);
+% end;
+%
+% var
+% p: TIntProc;
+% begin
+% p:=test;
+% p(4);
+% end.
+% \end{verbatim}
+% This code may however crash on platforms that pass integers in registers and
+% floating point values on the stack, because then the stack will be unbalanced.
+% Note that this warning will not flagg all potentially dangerous situations.
+% when \var{test} returns.
+type_e_generics_cannot_reference_itself=04096_E_Type parameters of specializations of generics cannot reference the currently specialized type
+% Recursive specializations of generics like \var{Type MyType = specialize MyGeneric<MyType>;} are not possible.
+type_e_type_parameters_are_not_allowed_here=04097_E_Type parameters are not allowed on non-generic class/record/object procedure or function
+% Type parameters are only allowed for methods of generic classes, records or objects
+type_e_generic_declaration_does_not_match=04098_E_Generic declaration of "$1" differs from previous declaration
+% Generic declaration does not match the previous declaration
+type_e_helper_type_expected=04099_E_Helper type expected
+% The compiler expected a \var{class helper} type.
+type_e_record_type_expected=04100_E_Record type expected
+% The compiler expected a \var{record} type.
+type_e_class_helper_must_extend_subclass=04101_E_Derived class helper must extend a subclass of "$1" or the class itself
+% If a class helper inherits from another class helper the extended class must
+% extend either the same class as the parent class helper or a subclass of it
+type_e_record_helper_must_extend_same_record=04102_E_Derived record helper must extend "$1"
+% If a record helper inherits from another record helper it must extend the same
+% record that the parent record helper extended.
+type_e_procedures_return_no_value=04103_E_Invalid assignment, procedures return no value
+% This error occurs when one tries to assign the result of a procedure or destructor call.
+% A procedure or destructor returns no value so this is not
+% possible.
+type_w_implicit_string_cast=04104_W_Implicit string type conversion from "$1" to "$2"
+% An implicit type conversion from an ansi string type to an unicode string type is
+% encountered. To avoid this warning perform an explicit type conversion.
+type_w_implicit_string_cast_loss=04105_W_Implicit string type conversion with potential data loss from "$1" to "$2"
+% An implicit type conversion from an unicode string type to an ansi string type is
+% encountered. This conversion can lose data since not all unicode characters may be represented in the codepage of
+% destination string type.
+type_w_explicit_string_cast=04106_-W_Explicit string typecast from "$1" to "$2"
+% An explicit typecast from an ansi string type to an unicode string type is
+% encountered. This warning is off by default. You can turn it on to see all suspicious string conversions.
+type_w_explicit_string_cast_loss=04107_-W_Explicit string typecast with potential data loss from "$1" to "$2"
+% An explicit typecast from an unicode string type to an ansi string type is
+% encountered. This conversion can lose data since not all unicode characters may be represented in the codepage of
+% destination string type. This warning is off by default. You can turn it on to see all the places with lossy string
+% conversions.
+type_w_unicode_data_loss=04108_W_Unicode constant cast with potential data loss
+% Conversion from a WideChar to AnsiChar can lose data since now all unicode characters may be represented in the current
+% system codepage
+% \end{description}
+#
+# Symtable
+#
+# 05084 is the last used one
+#
+% \section{Symbol handling}
+% This section lists all the messages that concern the handling of symbols.
+% This means all things that have to do with procedure and variable names.
+% \begin{description}
+sym_e_id_not_found=05000_E_Identifier not found "$1"
+% The compiler doesn't know this symbol. Usually happens when you misspell
+% the name of a variable or procedure, or when you forget to declare a
+% variable.
+sym_f_internal_error_in_symtablestack=05001_F_Internal Error in SymTableStack()
+% An internal error occurred in the compiler; If you encounter such an error,
+% please contact the developers and try to provide an exact description of
+% the circumstances in which the error occurs.
+sym_e_duplicate_id=05002_E_Duplicate identifier "$1"
+% The identifier was already declared in the current scope.
+sym_h_duplicate_id_where=05003_H_Identifier already defined in $1 at line $2
+% The identifier was already declared in a previous scope.
+sym_e_unknown_id=05004_E_Unknown identifier "$1"
+% The identifier encountered has not been declared, or is used outside the
+% scope where it is defined.
+sym_e_forward_not_resolved=05005_E_Forward declaration not solved "$1"
+% This can happen in two cases:
+% \begin{itemize}
+% \item You declare a function in the \var{interface} part, or
+% with a \var{forward} directive, but do not implement it.
+% \item You reference a type which isn't declared in the current \var{type}
+% block.
+% \end{itemize}
+sym_e_error_in_type_def=05007_E_Error in type definition
+% There is an error in your definition of a new array type.
+% One of the range delimiters in an array declaration is erroneous.
+% For example, \var{Array [1..1.25]} will trigger this error.
+sym_e_forward_type_not_resolved=05009_E_Forward type not resolved "$1"
+% A symbol was forward defined, but no declaration was encountered.
+sym_e_only_static_in_static=05010_E_Only static variables can be used in static methods or outside methods
+% A static method of an object can only access static variables.
+sym_f_type_must_be_rec_or_class=05012_F_record or class type expected
+% The variable or expression isn't of the type \var{record} or \var{class}.
+sym_e_no_instance_of_abstract_object=05013_E_Instances of classes or objects with an abstract method are not allowed
+% You are trying to generate an instance of a class which has an abstract
+% method that wasn't overridden.
+sym_w_label_not_defined=05014_W_Label not defined "$1"
+% A label was declared, but not defined.
+sym_e_label_used_and_not_defined=05015_E_Label used but not defined "$1"
+% A label was declared and used, but not defined.
+sym_e_ill_label_decl=05016_E_Illegal label declaration
+% This error should never happen; it occurs if a label is defined outside a
+% procedure or function.
+sym_e_goto_and_label_not_supported=05017_E_GOTO and LABEL are not supported (use switch -Sg)
+% You must use the -Sg switch to compile a program which has \var{label}s
+% and \var{goto} statements. By default, \var{label} and \var{goto} aren't
+% supported.
+sym_e_label_not_found=05018_E_Label not found
+% A \var{goto label} was encountered, but the label wasn't declared.
+sym_e_id_is_no_label_id=05019_E_identifier isn't a label
+% The identifier specified after the \var{goto} isn't of type label.
+sym_e_label_already_defined=05020_E_label already defined
+% You are defining a label twice. You can define a label only once.
+sym_e_ill_type_decl_set=05021_E_illegal type declaration of set elements
+% The declaration of a set contains an invalid type definition.
+sym_e_class_forward_not_resolved=05022_E_Forward class definition not resolved "$1"
+% You declared a class, but you did not implement it.
+sym_n_unit_not_used=05023_H_Unit "$1" not used in $2
+% The unit referenced in the \var{uses} clause is not used.
+sym_h_para_identifier_not_used=05024_H_Parameter "$1" not used
+% The identifier was declared (locally or globally) but
+% was not used (locally or globally).
+sym_n_local_identifier_not_used=05025_N_Local variable "$1" not used
+% You have declared, but not used, a variable in a procedure or function
+% implementation.
+sym_h_para_identifier_only_set=05026_H_Value parameter "$1" is assigned but never used
+% The identifier was declared (locally or globally) and
+% assigned to, but is not used (locally or globally) after the assignment.
+sym_n_local_identifier_only_set=05027_N_Local variable "$1" is assigned but never used
+% The variable in a procedure or function implementation is declared and
+% assigned to, but is not used after the assignment.
+sym_h_local_symbol_not_used=05028_H_Local $1 "$2" is not used
+% A local symbol is never used.
+sym_n_private_identifier_not_used=05029_N_Private field "$1.$2" is never used
+% The indicated private field is defined, but is never used in the code.
+sym_n_private_identifier_only_set=05030_N_Private field "$1.$2" is assigned but never used
+% The indicated private field is declared and assigned to, but never read.
+sym_n_private_method_not_used=05031_N_Private method "$1.$2" never used
+% The indicated private method is declared but is never used in the code.
+sym_e_set_expected=05032_E_Set type expected
+% The variable or expression is not of type \var{set}. This happens in an
+% \var{in} statement.
+sym_w_function_result_not_set=05033_W_Function result does not seem to be set
+% You can get this warning if the compiler thinks that a function return
+% value is not set. This will not be displayed for assembler procedures,
+% or procedures that contain assembler blocks.
+sym_w_wrong_C_pack=05034_W_Type "$1" is not aligned correctly in current record for C
+% Arrays with sizes not multiples of 4 will be wrongly aligned
+% for C structures.
+sym_e_illegal_field=05035_E_Unknown record field identifier "$1"
+% The field doesn't exist in the record/object definition.
+sym_w_uninitialized_local_variable=05036_W_Local variable "$1" does not seem to be initialized
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. it appears in the right-hand side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assignment).
+sym_w_uninitialized_variable=05037_W_Variable "$1" does not seem to be initialized
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. it appears in the right-hand side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assignment).
+sym_e_id_no_member=05038_E_identifier idents no member "$1"
+% This error is generated when an identifier of a record,
+% field or method is accessed while it is not defined.
+sym_h_param_list=05039_H_Found declaration: $1
+% You get this when you use the \var{-vh} switch.In the case of an overloaded procedure
+% not being found. Then all candidate overloaded procedures are
+% listed, with their parameter lists.
+sym_e_segment_too_large=05040_E_Data element too large
+% You get this when you declare a data element whose size exceeds the
+% prescribed limit (2 Gb on 80386+/68020+ processors).
+sym_e_no_matching_implementation_found=05042_E_No matching implementation for interface method "$1" found
+% There was no matching method found which could implement the interface
+% method. Check argument types and result type of the methods.
+sym_w_deprecated_symbol=05043_W_Symbol "$1" is deprecated
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{deprecated} is used. Deprecated symbols may no longer
+% be available in newer versions of the unit / library. Use of this symbol
+% should be avoided as much as possible.
+sym_w_non_portable_symbol=05044_W_Symbol "$1" is not portable
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{platform} is used. This symbol's value, use
+% and availability is platform specific and should not be used
+% if the source code must be portable.
+sym_w_non_implemented_symbol=05055_W_Symbol "$1" is not implemented
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{unimplemented} is used. This symbol is defined,
+% but is not yet implemented on this specific platform.
+sym_e_cant_create_unique_type=05056_E_Can't create unique type from this type
+% Only simple types like ordinal, float and string types are supported when
+% redefining a type with \var{type newtype = type oldtype;}.
+sym_h_uninitialized_local_variable=05057_H_Local variable "$1" does not seem to be initialized
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. it appears in the right-hand side of an expression) when it
+% was not initialized first (i.e. it did not appear in the left-hand side of an
+% assignment).
+sym_h_uninitialized_variable=05058_H_Variable "$1" does not seem to be initialized
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. it appears in the right-hand side of an expression) when it
+% was not initialized first (i.e. t did not appear in the left-hand side of an
+% assignment).
+sym_w_function_result_uninitialized=05059_W_Function result variable does not seem to initialized
+% This message is displayed if the compiler thinks that the function result
+% variable will be used (i.e. it appears in the right-hand side of an expression)
+% before it is initialized (i.e. before it appeared in the left-hand side of an
+% assignment).
+sym_h_function_result_uninitialized=05060_H_Function result variable does not seem to be initialized
+% This message is displayed if the compiler thinks that the function result
+% variable will be used (i.e. it appears in the right-hand side of an expression)
+% before it is initialized (i.e. it appears in the left-hand side of an
+% assignment)
+sym_w_identifier_only_read=05061_W_Variable "$1" read but nowhere assigned
+% You have read the value of a variable, but nowhere assigned a value to
+% it.
+sym_h_abstract_method_list=05062_H_Found abstract method: $1
+% When getting a warning about constructing a class/object with abstract methods
+% you get this hint to assist you in finding the affected method.
+sym_w_experimental_symbol=05063_W_Symbol "$1" is experimental
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{experimental} is used. Experimental symbols
+% might disappear or change semantics in future versions. Usage of this symbol
+% should be avoided as much as possible.
+sym_w_forward_not_resolved=05064_W_Forward declaration "$1" not resolved, assumed external
+% This happens if you declare a function in the \var{interface} of a unit in macpas mode,
+% but do not implement it.
+sym_w_library_symbol=05065_W_Symbol "$1" is belongs to a library
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{library} is used. Library symbols may not be
+% available in other libraries.
+sym_w_deprecated_symbol_with_msg=05066_W_Symbol "$1" is deprecated: "$2"
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{deprecated} is used. Deprecated symbols may no longer
+% be available in newer versions of the unit / library. Use of this symbol
+% should be avoided as much as possible.
+sym_e_no_enumerator=05067_E_Cannot find an enumerator for the type "$1"
+% This means that compiler cannot find an apropriate enumerator to use in the for-in loop.
+% To create an enumerator you need to defind an operator enumerator or add a public or published
+% GetEnumerator method to the class or object definition.
+sym_e_no_enumerator_move=05068_E_Cannot find a "MoveNext" method in enumerator "$1"
+% This means that compiler cannot find a public MoveNext method with the Boolean return type in
+% the enumerator class or object definition.
+sym_e_no_enumerator_current=05069_E_Cannot find a "Current" property in enumerator "$1"
+% This means that compiler cannot find a public Current property in the enumerator class or object
+% definition.
+sym_e_objc_para_mismatch=05070_E_Mismatch between number of declared parameters and number of colons in message string.
+% In Objective-C, a message name automatically contains as many colons as parameters.
+% In order to prevent mistakes when specifying the message name in FPC, the compiler
+% checks whether this is also the case here. Note that in case of messages taking a
+% variable number of arguments translated to FPC via an \var{array of const} parameter,
+% this final \var{array of const} parameter is not counted. Neither are the hidden
+% \var{self} and \var{\_cmd} parameters.
+sym_n_private_type_not_used=05071_N_Private type "$1.$2" never used
+% The indicated private type is declared but is never used in the code.
+sym_n_private_const_not_used=05072_N_Private const "$1.$2" never used
+% The indicated private const is declared but is never used in the code.
+sym_n_private_property_not_used=05073_N_Private property "$1.$2" never used
+% The indicated private property is declared but is never used in the code.
+sym_w_deprecated_unit=05074_W_Unit "$1" is deprecated
+% This means that a unit which is
+% declared as \var{deprecated} is used. Deprecated units may no longer
+% be available in newer versions of the library. Use of this unit
+% should be avoided as much as possible.
+sym_w_deprecated_unit_with_msg=05075_W_Unit "$1" is deprecated: "$2"
+% This means that a unit which is
+% declared as \var{deprecated} is used. Deprecated units may no longer
+% be available in newer versions of the library. Use of this unit
+% should be avoided as much as possible.
+sym_w_non_portable_unit=05076_W_Unit "$1" is not portable
+% This means that a unit which is
+% declared as \var{platform} is used. This unit use
+% and availability is platform specific and should not be used
+% if the source code must be portable.
+sym_w_library_unit=05077_W_Unit "$1" is belongs to a library
+% This means that a unit which is
+% declared as \var{library} is used. Library units may not be
+% available in other libraries.
+sym_w_non_implemented_unit=05078_W_Unit "$1" is not implemented
+% This means that a unit which is
+% declared as \var{unimplemented} is used. This unit is defined,
+% but is not yet implemented on this specific platform.
+sym_w_experimental_unit=05079_W_Unit "$1" is experimental
+% This means that a unit which is
+% declared as \var{experimental} is used. Experimental units
+% might disappear or change semantics in future versions. Usage of this unit
+% should be avoided as much as possible.
+sym_e_objc_formal_class_not_resolved=05080_E_No complete definition of the formally declared objcclass "$1" is in scope
+% Objecive-C classes can be imported formally, without using the the unit in which it is fully declared.
+% This enables making forward references to such classes and breaking circular dependencies amongst units.
+% However, as soon as you wish to actually do something with an entity of this class type (such as
+% access one of its fields, send a message to it, or use it to inherit from), the compiler requires the full definition
+% of the class to be in scope.
+sym_e_interprocgoto_into_init_final_code_not_allowed=05081_E_Gotos into initialization or finalization blocks of units are not allowed
+% Gotos into initialization or finalization blockse of units are not allowed.
+sym_e_external_class_name_mismatch1=05082_E_Invalid external name "$1" for formal class "$2"
+sym_e_external_class_name_mismatch2=05083_E_Complete class definition with external name "$1" here
+% When a class is declared using a formal external definition, the actual external
+% definition (if any) must specify the same external name as the formal definition
+% (since both definitions refer to the same actual class type).
+sym_w_library_overload=05084_W_Possible library conflict: symbol "$1" from library "$2" also found in library "$3"
+% Some OS do not have library specific namespaces, for those
+% OS, the function declared as "external 'libname' name 'funcname'",
+% the 'libname' part is only a hint, funcname might also be loaded
+% by another library. This warning appears if 'funcname' is used twice
+% with two different library names.
+%
+% \end{description}
+#
+# Codegenerator
+#
+# 06049 is the last used one
+#
+% \section{Code generator messages}
+% This section lists all messages that can be displayed if the code
+% generator encounters an error condition.
+% \begin{description}
+cg_e_parasize_too_big=06009_E_Parameter list size exceeds 65535 bytes
+% The I386 processor limits the parameter list to 65535 bytes. (The \var{RET}
+% instruction causes this.)
+cg_e_file_must_call_by_reference=06012_E_File types must be var parameters
+% You cannot specify files as value parameters, i.e., they must always be
+% declared \var{var} parameters.
+cg_e_cant_use_far_pointer_there=06013_E_The use of a far pointer isn't allowed there
+% Free Pascal doesn't support far pointers, so you cannot take the address of
+% an expression which has a far reference as a result. The \var{mem} construct
+% has a far reference as a result, so the following code will produce this
+% error:
+% \begin{verbatim}
+% var p : pointer;
+% ...
+% p:=@mem[a000:000];
+% \end{verbatim}
+cg_e_dont_call_exported_direct=06015_E_EXPORT declared functions can't be called
+% No longer in use.
+cg_w_member_cd_call_from_method=06016_W_Possible illegal call of constructor or destructor
+% The compiler detected that a constructor or destructor is called within a
+% a method. This will probably lead to problems, since constructors / destructors
+% require parameters on entry.
+cg_n_inefficient_code=06017_N_Inefficient code
+% Your statement seems dubious to the compiler.
+cg_w_unreachable_code=06018_W_unreachable code
+% You specified a construct which will never be executed. Example:
+% \begin{verbatim}
+% while false do
+% begin
+% {.. code ...}
+% end;
+% \end{verbatim}
+cg_e_cant_call_abstract_method=06020_E_Abstract methods can't be called directly
+% You cannot call an abstract method directly. Instead, you must call an
+% overriding child method, because an abstract method isn't implemented.
+cg_d_register_weight=06027_DL_Register $1 weight $2 $3
+% Debugging message. Shown when the compiler considers a variable for
+% keeping in the registers.
+cg_d_stackframe_omited=06029_DL_Stack frame is omitted
+% Some procedure/functions do not need a complete stack-frame, so it is omitted.
+% This message will be displayed when the {-vd} switch is used.
+cg_e_unable_inline_object_methods=06031_E_Object or class methods can't be inline.
+% You cannot have inlined object methods.
+cg_e_unable_inline_procvar=06032_E_Procvar calls cannot be inline.
+% A procedure with a procedural variable call cannot be inlined.
+cg_e_no_code_for_inline_stored=06033_E_No code for inline procedure stored
+% The compiler couldn't store code for the inline procedure.
+cg_e_can_access_element_zero=06035_E_Element zero of an ansi/wide- or longstring can't be accessed, use (set)length instead
+% You should use \var{setlength} to set the length of an ansi/wide/longstring
+% and \var{length} to get the length of such string type.
+cg_e_cannot_call_cons_dest_inside_with=06037_E_Constructors or destructors cannot be called inside a 'with' clause
+% Inside a \var{with} clause you cannot call a constructor or destructor for the
+% object you have in the \var{with} clause.
+cg_e_cannot_call_message_direct=06038_E_Cannot call message handler methods directly
+% A message method handler method cannot be called directly if it contains an
+% explicit \var{Self} argument.
+cg_e_goto_inout_of_exception_block=06039_E_Jump in or outside of an exception block
+% It is not allowed to jump in or outside of an exception block like \var{try..finally..end;}.
+% For example, the following code will produce this error:
+
+% \begin{verbatim}
+% label 1;
+%
+% ...
+%
+% try
+% if not(final) then
+% goto 1; // this line will cause an error
+% finally
+% ...
+% end;
+% 1:
+% ...
+% \end{verbatim}
+cg_e_control_flow_outside_finally=06040_E_Control flow statements aren't allowed in a finally block
+% It isn't allowed to use the control flow statements \var{break},
+% \var{continue} and \var{exit}
+% inside a finally statement. The following example shows the problem:
+% \begin{verbatim}
+% ...
+% try
+% p;
+% finally
+% ...
+% exit; // This exit ISN'T allowed
+% end;
+% ...
+%
+% \end{verbatim}
+% If the procedure \var{p} raises an exception the finally block is
+% executed. If the execution reaches the exit, it's unclear what to do:
+% exit the procedure or search for another exception handler.
+cg_w_parasize_too_big=06041_W_Parameters size exceeds limit for certain cpu's
+% This indicates that you are declaring more than 64K of parameters, which
+% might not be supported on other processor targets.
+cg_w_localsize_too_big=06042_W_Local variable size exceed limit for certain cpu's
+% This indicates that you are declaring more than 32K of local variables, which
+% might not be supported on other processor targets.
+cg_e_localsize_too_big=06043_E_Local variables size exceeds supported limit
+% This indicates that you are declaring more than 32K of local variables, which
+% is not supported by this processor.
+cg_e_break_not_allowed=06044_E_BREAK not allowed
+% You're trying to use \var{break} outside a loop construction.
+cg_e_continue_not_allowed=06045_E_CONTINUE not allowed
+% You're trying to use \var{continue} outside a loop construction.
+cg_f_unknown_compilerproc=06046_F_Unknown compilerproc "$1". Check if you use the correct run time library.
+% The compiler expects that the runtime library contains certain subroutines. If you see this error
+% and you didn't change the runtime library code, it's very likely that the runtime library
+% you're using doesn't match the compiler in use. If you changed the runtime library this error means
+% that you removed a subroutine which the compiler needs for internal use.
+cg_f_unknown_system_type=06047_F_Cannot find system type "$1". Check if you use the correct run time library.
+% The compiler expects that the runtime library contains certain type definitions. If you see this error
+% and you didn't change the runtime library code, it's very likely that the runtime library
+% you're using doesn't match the compiler in use. If you changed the runtime library this error means
+% that you removed a type which the compiler needs for internal use.
+cg_h_inherited_ignored=06048_H_Inherited call to abstract method ignored
+% This message appears only in Delphi mode when you call an abstract method
+% of a parent class via \var{inherited;}. The call is then ignored.
+cg_e_goto_label_not_found=06049_E_Goto label "$1" not defined or optimized away
+% The label used in the goto definition is not defined or optimized away by the
+% unreachable code elemination.
+cg_f_unknown_type_in_unit=06050_F_Cannot find type "$1" in unit "$2". Check if you use the correct run time library.
+% The compiler expects that the runtime library contains certain type definitions. If you see this error
+% and you didn't change the runtime library code, it's very likely that the runtime library
+% you're using doesn't match the compiler in use. If you changed the runtime library this error means
+% that you removed a type which the compiler needs for internal use.
+cg_e_interprocedural_goto_only_to_outer_scope_allowed=06051_E_Interprocedural gotos are allowed only to outer subroutines
+% Gotos between subroutines are only allowed if the goto jumps from an inner to an outer subroutine or
+% from a subroutine to the main program
+cg_e_labels_cannot_defined_outside_declaration_scope=06052_E_Label must be defined in the same scope as it is declared
+% In ISO mode, labels must be defined in the same scope as they are declared.
+cg_e_goto_across_procedures_with_exceptions_not_allowed=06053_E_Leaving procedures containing explicit or implicit exceptions frames using goto is not allowed
+% Non-local gotos might not be used to leave procedures using exceptions either implicitly or explicitly. Procedures
+% which use automated types like ansistrings or class constructurs are affected by this too.
+cg_e_mod_only_defined_for_pos_quotient=06054_E_In ISO mode, the mod operator is defined only for positive quotient
+% In ISO pascal, only positive values are allowed for the quotient: \var{n mod m} is only valid if \var{m>0}.
+% \end{description}
+# EndOfTeX
+
+#
+# Assembler reader
+#
+# 07110 is the last used one
+#
+asmr_d_start_reading=07000_DL_Starting $1 styled assembler parsing
+% This informs you that an assembler block is being parsed
+asmr_d_finish_reading=07001_DL_Finished $1 styled assembler parsing
+% This informs you that an assembler block has finished.
+asmr_e_none_label_contain_at=07002_E_Non-label pattern contains @
+% A identifier which isn't a label can't contain a @.
+asmr_e_building_record_offset=07004_E_Error building record offset
+% There has an error occured while building the offset of a record/object
+% structure, this can happend when there is no field specified at all or
+% an unknown field identifier is used.
+asmr_e_offset_without_identifier=07005_E_OFFSET used without identifier
+% You can only use OFFSET with an identifier. Other syntaxes aren't
+% supported
+asmr_e_type_without_identifier=07006_E_TYPE used without identifier
+% You can only use TYPE with an identifier. Other syntaxes aren't
+% supported
+asmr_e_no_local_or_para_allowed=07007_E_Cannot use local variable or parameters here
+% You can't use a local variable or parameter here, mostly because the
+% addressing of locals and parameters is done using the frame pointer register so the
+% address can't be obtained directly.
+asmr_e_need_offset=07008_E_need to use OFFSET here
+% You need to use OFFSET <id> here to get the address of the identifier.
+asmr_e_need_dollar=07009_E_need to use $ here
+% You need to use $<id> here to get the address of the identifier.
+asmr_e_cant_have_multiple_relocatable_symbols=07010_E_Cannot use multiple relocatable symbols
+% You can't have more than one relocatable symbol (variable/typed constant)
+% in one argument.
+asmr_e_only_add_relocatable_symbol=07011_E_Relocatable symbol can only be added
+% Relocatable symbols (variable/typed constant) can't be used with other
+% operators. Only addition is allowed.
+asmr_e_invalid_constant_expression=07012_E_Invalid constant expression
+% There is an error in the constant expression.
+asmr_e_relocatable_symbol_not_allowed=07013_E_Relocatable symbol is not allowed
+% You can't use a relocatable symbol (variable/typed constant) here.
+asmr_e_invalid_reference_syntax=07014_E_Invalid reference syntax
+% There is an error in the reference.
+asmr_e_local_para_unreachable=07015_E_You cannot reach $1 from that code
+% You cannot read directly the value of a local variable or parameter
+% of a higher level procedure in assembler code (except for
+% local assembler code without parameter nor locals).
+asmr_e_local_label_not_allowed_as_ref=07016_E_Local symbols/labels aren't allowed as references
+% You can't use local symbols/labels as references
+asmr_e_wrong_base_index=07017_E_Invalid base and index register usage
+% There is an error with the base and index register, they are
+% probably incorrect
+asmr_w_possible_object_field_bug=07018_W_Possible error in object field handling
+% Fields of objects or classes can be reached directly in normal or objfpc
+% modes but TP and Delphi modes treat the field name as a simple offset.
+asmr_e_wrong_scale_factor=07019_E_Wrong scale factor specified
+% The scale factor given is wrong, only 1,2,4 and 8 are allowed
+asmr_e_multiple_index=07020_E_Multiple index register usage
+% You are trying to use more than one index register
+asmr_e_invalid_operand_type=07021_E_Invalid operand type
+% The operand type doesn't match with the opcode used
+asmr_e_invalid_string_as_opcode_operand=07022_E_Invalid string as opcode operand: $1
+% The string specified as operand is not correct with this opcode
+asmr_w_CODE_and_DATA_not_supported=07023_W_@CODE and @DATA not supported
+% @CODE and @DATA are unsupported and are ignored.
+asmr_e_null_label_ref_not_allowed=07024_E_Null label references are not allowed
+asmr_e_expr_zero_divide=07025_E_Divide by zero in asm evaluator
+% There is a division by zero in a constant expression
+asmr_e_expr_illegal=07026_E_Illegal expression
+% There is an illegal expression in a constant expression
+asmr_e_escape_seq_ignored=07027_E_escape sequence ignored: $1
+% There is a C-styled string, but the escape sequence in the string
+% is unknown, and is therefore ignored
+asmr_e_invalid_symbol_ref=07028_E_Invalid symbol reference
+asmr_w_fwait_emu_prob=07029_W_Fwait can cause emulation problems with emu387
+asmr_w_fadd_to_faddp=07030_W_$1 without operand translated into $1P
+asmr_w_enter_not_supported_by_linux=07031_W_ENTER instruction is not supported by Linux kernel
+% ENTER instruction can generate a stack page fault that is not
+% caught correctly by the i386 Linux page handler.
+asmr_w_calling_overload_func=07032_W_Calling an overload function in assembler
+% There is a call to an overloaded method in the assembler block,
+% this might be the sign there is a problem
+asmr_e_unsupported_symbol_type=07033_E_Unsupported symbol type for operand
+asmr_e_constant_out_of_bounds=07034_E_Constant value out of bounds
+asmr_e_error_converting_decimal=07035_E_Error converting decimal $1
+% A constant decimal value does not have the correct syntax
+asmr_e_error_converting_octal=07036_E_Error converting octal $1
+% A constant octal value does not have the correct syntax
+asmr_e_error_converting_binary=07037_E_Error converting binary $1
+% A constant binary value does not have the correct syntax
+asmr_e_error_converting_hexadecimal=07038_E_Error converting hexadecimal $1
+% A constant hexadecimal value does not have the correct syntax
+asmr_h_direct_global_to_mangled=07039_H_$1 translated to $2
+asmr_w_direct_global_is_overloaded_func=07040_W_$1 is associated to an overloaded function
+asmr_e_cannot_use_SELF_outside_a_method=07041_E_Cannot use SELF outside a method
+% There is a reference to the \var{self} symbol while it is not
+% allowed. \var{self} can only be referenced inside methods
+asmr_e_cannot_use_OLDEBP_outside_nested_procedure=07042_E_Cannot use OLDEBP outside a nested procedure
+% There is a reference to the \var{oldebp} symbol while it is not
+% allowed. \var{oldebp} can only be referenced inside nested routines
+asmr_e_void_function=07043_W_Procedures can't return any value in asm code
+% Trying to return a value while in a procedure. A procedure
+% does not have any return value
+asmr_e_SEG_not_supported=07044_E_SEG not supported
+asmr_e_size_suffix_and_dest_dont_match=07045_E_Size suffix and destination or source size do not match
+% The register size and the opcode size suffix don't match. This is
+% probably an error in the assembler statement
+asmr_w_size_suffix_and_dest_dont_match=07046_W_Size suffix and destination or source size do not match
+% The register size and the opcode size suffix don't match. This is
+% probably an error in the assembler statement
+asmr_e_syntax_error=07047_E_Assembler syntax error
+% There is an assembler syntax error
+asmr_e_invalid_opcode_and_operand=07048_E_Invalid combination of opcode and operands
+% The opcode cannot be used with this type of operand
+asmr_e_syn_operand=07049_E_Assembler syntax error in operand
+asmr_e_syn_constant=07050_E_Assembler syntax error in constant
+asmr_e_invalid_string_expression=07051_E_Invalid String expression
+asmr_w_const32bit_for_address=07052_W_constant with symbol $1 for address which is not on a pointer
+% A constant expression represents an address which does not fit
+% into a pointer. The address is probably incorrect
+asmr_e_unknown_opcode=07053_E_Unrecognized opcode $1
+% This opcode is not known
+asmr_e_invalid_or_missing_opcode=07054_E_Invalid or missing opcode
+asmr_e_invalid_prefix_and_opcode=07055_E_Invalid combination of prefix and opcode: $1
+asmr_e_invalid_override_and_opcode=07056_E_Invalid combination of override and opcode: $1
+asmr_e_too_many_operands=07057_E_Too many operands on line
+% There are too many operands for this opcode. Check your
+% assembler syntax
+asmr_w_near_ignored=07058_W_NEAR ignored
+asmr_w_far_ignored=07059_W_FAR ignored
+asmr_e_dup_local_sym=07060_E_Duplicate local symbol $1
+asmr_e_unknown_local_sym=07061_E_Undefined local symbol $1
+asmr_e_unknown_label_identifier=07062_E_Unknown label identifier $1
+asmr_e_invalid_register=07063_E_Invalid register name
+% There is an unknown register name used as operand.
+asmr_e_invalid_fpu_register=07064_E_Invalid floating point register name
+% There is an unknown register name used as operand.
+asmr_w_modulo_not_supported=07066_W_Modulo not supported
+asmr_e_invalid_float_const=07067_E_Invalid floating point constant $1
+% The floating point constant declared in an assembler block is
+% invalid.
+asmr_e_invalid_float_expr=07068_E_Invalid floating point expression
+% The floating point expression declared in an assembler block is
+% invalid.
+asmr_e_wrong_sym_type=07069_E_Wrong symbol type
+asmr_e_cannot_index_relative_var=07070_E_Cannot index a local var or parameter with a register
+% Trying to index using a base register a symbol which is already relative
+% to a register. This is not possible, and will probably lead to crashes.
+asmr_e_invalid_seg_override=07071_E_Invalid segment override expression
+asmr_w_id_supposed_external=07072_W_Identifier $1 supposed external
+% There is a reference to an undefined symbol. This will not result
+% in an error, since the symbol might be external, but may cause
+% problems at link time if the symbol is not defined anywhere.
+asmr_e_string_not_allowed_as_const=07073_E_Strings not allowed as constants
+% Character strings are not allowed as constants.
+asmr_e_no_var_type_specified=07074_E_No type of variable specified
+% The syntax expects a type idenfitifer after the dot, but
+% none was found.
+asmr_w_assembler_code_not_returned_to_text=07075_E_assembler code not returned to text section
+% There was a directive in the assembler block to change sections,
+% but there is a missing return to the text section at the end
+% of the assembler block. This might cause errors during link time.
+asmr_e_not_directive_or_local_symbol=07076_E_Not a directive or local symbol $1
+% This symbol is unknown.
+asmr_w_using_defined_as_local=07077_E_Using a defined name as a local label
+asmr_e_dollar_without_identifier=07078_E_Dollar token is used without an identifier
+% A constant expression has an identifier which does not start with
+% the $ symbol.
+asmr_w_32bit_const_for_address=07079_W_32bit constant created for address
+% A constant was used as an address. This is probably an error,
+% since using absolute addresses will probably not work.
+asmr_n_align_is_target_specific=07080_N_.align is target specific, use .balign or .p2align
+% Using the .align directive is platform specific, and its meaning will vary
+% from one platform to another.
+asmr_e_cannot_access_field_directly_for_parameters=07081_E_Can't access fields directly for parameters
+% You should load the parameter first into a register and then access the
+% fields using that register.
+asmr_e_cannot_access_object_field_directly=07082_E_Can't access fields of objects/classes directly
+% You should load the self pointer first into a register and then access the
+% fields using the register as base. By default the self pointer is available
+% in the esi register on i386.
+asmr_e_unable_to_determine_reference_size=07083_E_No size specified and unable to determine the size of the operands
+% You should specify explicitly a size for the reference, because
+% the compiler is unable to determine what size (byte,word,dword,etc.) it
+% should use for the reference.
+asmr_e_cannot_use_RESULT_here=07084_E_Cannot use RESULT in this function
+% Some functions which return complex types cannot use the \var{result}
+% keyword.
+asmr_w_adding_explicit_args_fXX=07086_W_"$1" without operand translated into "$1 %st,%st(1)"
+asmr_w_adding_explicit_first_arg_fXX=07087_W_"$1 %st(n)" translated into "$1 %st,%st(n)"
+asmr_w_adding_explicit_second_arg_fXX=07088_W_"$1 %st(n)" translated into "$1 %st(n),%st"
+asmr_e_invalid_char_smaller=07089_E_Char < not allowed here
+% The shift operator requires the << characters. Only one
+% of those characters was found.
+asmr_e_invalid_char_greater=07090_E_Char > not allowed here
+% The shift operator requires the >> characters. Only one
+% of those characters was found.
+asmr_w_align_not_supported=07093_W_ALIGN not supported
+asmr_e_no_inc_and_dec_together=07094_E_Inc and Dec cannot be together
+% Trying to use an increment and a decrement within the same
+% opcode on the 680x0. This is impossible.
+asmr_e_invalid_reg_list_in_movem=07095_E_Invalid reglist for movem
+% Trying to use the \var{movem} opcode with invalid registers
+% to save or restore.
+asmr_e_invalid_reg_list_for_opcode=07096_E_Reglist invalid for opcode
+asmr_e_higher_cpu_mode_required=07097_E_Higher cpu mode required ($1)
+% Trying to use an instruction which is not supported in the current
+% cpu mode. Use a higher cpu generation to be able to use this
+% opcode in your assembler block
+asmr_w_unable_to_determine_reference_size_using_dword=07098_W_No size specified and unable to determine the size of the operands, using DWORD as default
+% You should specify explicitly a size for the reference, because
+% the compiler is unable to determine what size (byte,word,dword,etc.) it
+% should use for the reference. This warning is only used in Delphi mode where
+% it falls back to use DWORD as default.
+asmr_e_illegal_shifterop_syntax=07099_E_Syntax error while trying to parse a shifter operand
+% ARM only; ARM assembler supports a so called shifter operand. The used syntax isn't
+% a valid shifter operand. Example for an operation with shifter operand:
+% \begin{verbatim}
+% asm
+% orr r2,r2,r2,lsl #8
+% end;
+% \end{verbatim}
+asmr_e_packed_element=07100_E_Address of packed component is not at a byte boundary
+% Packed components (record fields and array elements) may start at an arbitrary
+% bit inside a byte. On CPU which do not support bit-addressable memory (which
+% includes all currently supported CPUs by FPC) you will therefore get an error
+% message when trying to index arrays with elements whose size is not a multiple
+% of 8 bits. The same goes for accessing record fields with such an address.
+% multiple of 8 bits.
+asmr_w_unable_to_determine_reference_size_using_byte=07101_W_No size specified and unable to determine the size of the operands, using BYTE as default
+% You should specify explicitly a size for the reference, because
+% the compiler is unable to determine what size (byte,word,dword,etc.) it
+% should use for the reference. This warning is only used in Delphi mode where
+% it falls back to use BYTE as default.
+asmr_w_no_direct_ebp_for_parameter=07102_W_Use of +offset(%ebp) for parameters invalid here
+% Using direct 8(%ebp) reference for function/procedure parameters is invalid
+% if parameters are in registers.
+asmr_w_direct_ebp_for_parameter_regcall=07103_W_Use of +offset(%ebp) is not compatible with regcall convention
+% Using direct 8(%ebp) reference for function/procedure parameters is invalid
+% if parameters are in registers.
+asmr_w_direct_ebp_neg_offset=07104_W_Use of -offset(%ebp) is not recommended for local variable access
+% Using -8(%ebp) to access a local variable is not recommended
+asmr_w_direct_esp_neg_offset=07105_W_Use of -offset(%esp), access may cause a crash or value may be lost
+% Using -8(%esp) to access a local stack is not recommended, as
+% this stack portion can be overwritten by any function calls or interrupts.
+asmr_e_no_vmtoffset_possible=07106_E_VMTOffset must be used in combination with a virtual method, and "$1" is not virtual
+% Only virtual methods have VMT offsets
+asmr_e_need_pic_ref=07107_E_Generating PIC, but reference is not PIC-safe
+% The compiler has been configured to generate position-independent code
+% (PIC), but there are position-dependent references in the current
+% handwritten assembler instruction.
+asmr_e_mixing_regtypes=07108_E_All registers in a register set must be of the same kind and width
+% Instructions on the ARM architecture that take a register set as argument require that all registers
+% in this set are of the same kind (e.g., integer, vfp) and width (e.g., single precision, double precision).
+asmr_e_empty_regset=07109_E_A register set cannot be empty
+% Instructions on the ARM architecture that take a register set as argument require that such a set
+% contains at least one register.
+
+asmr_w_useless_got_for_local=07110_W_@GOTPCREL is useless and potentially dangereous for local symbols
+% The use of @GOTPCREL supposes an extra indirection that is
+% not present if the symbol is local, which might lead to wrong asembler code
+asmr_w_general_segment_with_constant=07111_W_Constant with general purpose segment register
+% General purpose register should not have constant offsets
+% as OS memory allocation might not be compatible with that.
+asmr_e_bad_seh_directive_offset=07112_E_Invalid offset value for $1
+% Win64 SEH directives have certain restrictions on possible offset values, e.g. they should
+% be positive and have 3 or 4 low bits clear.
+asmr_e_bad_seh_directive_register=07113_E_Invalid register for $1
+% Win64 SEH directives accept only 64-bit integer registers or XMM registers.
+asmr_e_seh_in_pure_asm_only=07114_E_SEH directives are allowed only in pure assembler procedures
+% Win64 SEH directives are allowed only in pure assembler procedures, not in assembler
+% blocks of regular procedures.
+asmr_e_unsupported_directive=07115_E_Directive "$1" is not supported for the current target
+
+
+#
+# Assembler/binary writers
+#
+# 08022 is the last used one
+#
+asmw_f_too_many_asm_files=08000_F_Too many assembler files
+% With smartlinking enabled, there are too many assembler
+% files generated. Disable smartlinking.
+asmw_f_assembler_output_not_supported=08001_F_Selected assembler output not supported
+asmw_f_comp_not_supported=08002_F_Comp not supported
+asmw_f_direct_not_supported=08003_F_Direct not support for binary writers
+% Direct assembler mode is not supported for binary writers.
+asmw_e_alloc_data_only_in_bss=08004_E_Allocating of data is only allowed in bss section
+asmw_f_no_binary_writer_selected=08005_F_No binary writer selected
+asmw_e_opcode_not_in_table=08006_E_Asm: Opcode $1 not in table
+asmw_e_invalid_opcode_and_operands=08007_E_Asm: $1 invalid combination of opcode and operands
+asmw_e_16bit_not_supported=08008_E_Asm: 16 Bit references not supported
+asmw_e_invalid_effective_address=08009_E_Asm: Invalid effective address
+asmw_e_immediate_or_reference_expected=08010_E_Asm: Immediate or reference expected
+asmw_e_value_exceeds_bounds=08011_E_Asm: $1 value exceeds bounds $2
+asmw_e_short_jmp_out_of_range=08012_E_Asm: Short jump is out of range $1
+asmw_e_undefined_label=08013_E_Asm: Undefined label $1
+asmw_e_comp_not_supported=08014_E_Asm: Comp type not supported for this target
+asmw_e_extended_not_supported=08015_E_Asm: Extended type not supported for this target
+asmw_e_duplicate_label=08016_E_Asm: Duplicate label $1
+asmw_e_redefined_label=08017_E_Asm: Redefined label $1
+asmw_e_first_defined_label=08018_E_Asm: First defined here
+asmw_e_invalid_register=08019_E_Asm: Invalid register $1
+asmw_e_16bit_32bit_not_supported=08020_E_Asm: 16 or 32 Bit references not supported
+asmw_e_64bit_not_supported=08021_E_Asm: 64 Bit operands not supported
+asmw_e_bad_reg_with_rex=08022_E_Asm: AH,BH,CH or DH cannot be used in an instruction requiring REX prefix
+% x86_64 only: instruction encoding of this platform does not allow using
+% 8086 high byte registers (AH,BH,CH or DH) together with REX prefix in a single instruction.
+% The REX prefix is required whenever the instruction operand size is 64 bits, or
+% when it uses one of extended x86_64 registers (R8-R15 or XMM8-XMM15).
+asmw_e_missing_endprologue=08023_E_Missing .seh_endprologue directive
+% x86_64-win64 only: Normally, SEH directives are handled internally by compiler.
+% However, in pure assembler procedures .seh_endprologue directive is required
+% if other SEH directives are present.
+asmw_e_prologue_too_large=08024_E_Function prologue exceeds 255 bytes
+% x86_64-win64: .seh_prologue directive must be placed within 255 bytes from function start.
+asmw_e_handlerdata_no_handler=08025_E_.seh_handlerdata directive without preceding .seh_handler
+% x86_64-win64: If .seh_handlerdata directive is used, then a .seh_handler directive must be
+% present earlier in the same function.
+
+#
+# Executing linker/assembler
+#
+# 09033 is the last used one
+#
+# BeginOfTeX
+%
+% \section{Errors of assembling/linking stage}
+% This section lists errors that occur when the compiler is processing the
+% command line or handling the configuration files.
+% \begin{description}
+exec_w_source_os_redefined=09000_W_Source operating system redefined
+% The source operating system is redefined.
+exec_i_assembling_pipe=09001_I_Assembling (pipe) $1
+% Assembling using a pipe to an external assembler.
+exec_d_cant_create_asmfile=09002_E_Can't create assembler file: $1
+% The mentioned file can't be created. Check if you have
+% access permissions to create this file.
+exec_e_cant_create_objectfile=09003_E_Can't create object file: $1 (error code: $2)
+% The mentioned file can't be created. Check if you have
+% got access permissions to create this file.
+exec_e_cant_create_archivefile=09004_E_Can't create archive file: $1
+% The mentioned file can't be created. Check if you have
+% access permissions to create this file.
+exec_e_assembler_not_found=09005_E_Assembler $1 not found, switching to external assembling
+% The assembler program was not found. The compiler will produce a script that
+% can be used to assemble and link the program.
+exec_t_using_assembler=09006_T_Using assembler: $1
+% An informational message saying which assembler is being used.
+exec_e_error_while_assembling=09007_E_Error while assembling exitcode $1
+% There was an error while assembling the file using an external assembler.
+% Consult the documentation of the assembler tool to find out more information
+% on this error.
+exec_e_cant_call_assembler=09008_E_Can't call the assembler, error $1 switching to external assembling
+% An error occurred when calling an external assembler. The compiler will produce a script that
+% can be used to assemble and link the program.
+exec_i_assembling=09009_I_Assembling $1
+% An informational message stating which file is being assembled.
+exec_i_assembling_smart=09010_I_Assembling with smartlinking $1
+% An informational message stating which file is being assembled using smartlinking.
+exec_w_objfile_not_found=09011_W_Object $1 not found, Linking may fail !
+% One of the object files is missing, and linking will probably fail.
+% Check your paths.
+exec_w_libfile_not_found=09012_W_Library $1 not found, Linking may fail !
+% One of the library files is missing, and linking will probably fail.
+% Check your paths.
+exec_e_error_while_linking=09013_E_Error while linking
+% Generic error while linking.
+exec_e_cant_call_linker=09014_E_Can't call the linker, switching to external linking
+% An error occurred when calling an external linker. The compiler will produce a script that
+% can be used to assemble and link the program.
+exec_i_linking=09015_I_Linking $1
+% An informational message, showing which program or library is being linked.
+exec_e_util_not_found=09016_E_Util $1 not found, switching to external linking
+% An external tool was not found. The compiler will produce a script that
+% can be used to assemble and link or postprocess the program.
+exec_t_using_util=09017_T_Using util $1
+% An informational message, showing which external program (usually a postprocessor) is being used.
+exec_e_exe_not_supported=09018_E_Creation of Executables not supported
+% Creating executable programs is not supported for this platform, because it was
+% not yet implemented in the compiler.
+exec_e_dll_not_supported=09019_E_Creation of Dynamic/Shared Libraries not supported
+% Creating dynamically loadable libraries is not supported for this platform, because it was
+% not yet implemented in the compiler.
+exec_i_closing_script=09020_I_Closing script $1
+% Informational message showing when writing of the external assembling and linking script is finished.
+exec_e_res_not_found=09021_E_resource compiler "$1" not found, switching to external mode
+% An external resource compiler was not found. The compiler will produce a script that
+% can be used to assemble, compile resources and link or postprocess the program.
+exec_i_compilingresource=09022_I_Compiling resource $1
+% An informational message, showing which resource is being compiled.
+exec_t_unit_not_static_linkable_switch_to_smart=09023_T_unit $1 can't be statically linked, switching to smart linking
+% Static linking was requested, but a unit which is not statically linkable was used.
+exec_t_unit_not_smart_linkable_switch_to_static=09024_T_unit $1 can't be smart linked, switching to static linking
+% Smart linking was requested, but a unit which is not smart-linkable was used.
+exec_t_unit_not_shared_linkable_switch_to_static=09025_T_unit $1 can't be shared linked, switching to static linking
+% Shared linking was requested, but a unit which is not shared-linkable was used.
+exec_e_unit_not_smart_or_static_linkable=09026_E_unit $1 can't be smart or static linked
+% Smart or static linking was requested, but a unit which cannot be used for either was used.
+exec_e_unit_not_shared_or_static_linkable=09027_E_unit $1 can't be shared or static linked
+% Shared or static linking was requested, but a unit which cannot be used for either was used.
+exec_d_resbin_params=09028_D_Calling resource compiler "$1" with "$2" as command line
+% An informational message showing which command line is used for the resource compiler.
+exec_e_error_while_compiling_resources=09029_E_Error while compiling resources
+% The resource compiler or converter returned an error.
+exec_e_cant_call_resource_compiler=09030_E_Can't call the resource compiler "$1", switching to external mode
+% An error occurred when calling a resource compiler. The compiler will produce
+% a script that can be used to assemble, compile resources and link or
+% postprocess the program.
+exec_e_cant_open_resource_file=09031_E_Can't open resource file "$1"
+% An error occurred resource file cannot be opened.
+exec_e_cant_write_resource_file=09032_E_Can't write resource file "$1"
+% An error occurred resource file cannot be written.
+exec_n_backquote_cat_file_not_found=09033_N_File "$1" not found for backquoted cat command
+% The compiler did not find the file that should be expanded into linker parameters
+%\end{description}
+# EndOfTeX
+
+#
+# Executable information
+#
+# 09134 is the last used one
+#
+# BeginOfTeX
+% \section{Executable information messages.}
+% This section lists all messages that the compiler emits when an executable program is produced,
+% and only when the internal linker is used.
+% \begin{description}
+execinfo_f_cant_process_executable=09128_F_Can't post process executable $1
+% Fatal error when the compiler is unable to post-process an executable.
+execinfo_f_cant_open_executable=09129_F_Can't open executable $1
+% Fatal error when the compiler cannot open the file for the executable.
+execinfo_x_codesize=09130_X_Size of Code: $1 bytes
+% Informational message showing the size of the produced code section.
+execinfo_x_initdatasize=09131_X_Size of initialized data: $1 bytes
+% Informational message showing the size of the initialized data section.
+execinfo_x_uninitdatasize=09132_X_Size of uninitialized data: $1 bytes
+% Informational message showing the size of the uninitialized data section.
+execinfo_x_stackreserve=09133_X_Stack space reserved: $1 bytes
+% Informational message showing the stack size that the compiler reserved for the executable.
+execinfo_x_stackcommit=09134_X_Stack space committed: $1 bytes
+% Informational message showing the stack size that the compiler committed for the executable.
+%\end{description}
+# EndOfTeX
+
+#
+# Internal linker messages
+#
+# 09200 is the last used one
+#
+# BeginOfTeX
+% \section{Linker messages}
+% This section lists messages produced by internal linker.
+% \begin{description}
+link_f_executable_too_big=09200_F_Executable image size is too big for $1 target.
+% Fatal error when resulting executable is too big.
+link_w_32bit_absolute_reloc=09201_W_Object file "$1" contains 32-bit absolute relocation to symbol "$2".
+% Warning when 64-bit object file contains 32-bit absolute relocations.
+% In such case an executable image can be loaded into lower 4Gb of
+% address space only.
+%\end{description}
+# EndOfTeX
+
+#
+# Unit loading
+#
+# 10062 is the last used one
+#
+# BeginOfTeX
+% \section{Unit loading messages.}
+% This section lists all messages that can occur when the compiler is
+% loading a unit from disk into memory. Many of these messages are
+% informational messages.
+% \begin{description}
+unit_t_unitsearch=10000_T_Unitsearch: $1
+% When you use the \var{-vt} option, the compiler tells you where it tries to find
+% unit files.
+unit_t_ppu_loading=10001_T_PPU Loading $1
+% When the \var{-vt} switch is used, the compiler tells you
+% what units it loads.
+unit_u_ppu_name=10002_U_PPU Name: $1
+% When you use the \var{-vu} flag, the unit name is shown.
+unit_u_ppu_flags=10003_U_PPU Flags: $1
+% When you use the \var{-vu} flag, the unit flags are shown.
+unit_u_ppu_crc=10004_U_PPU Crc: $1
+% When you use the \var{-vu} flag, the unit CRC check is shown.
+unit_u_ppu_time=10005_U_PPU Time: $1
+% When you use the \var{-vu} flag, the time the unit was compiled is shown.
+unit_u_ppu_file_too_short=10006_U_PPU File too short
+% The ppufile is too short, not all declarations are present.
+unit_u_ppu_invalid_header=10007_U_PPU Invalid Header (no PPU at the begin)
+% A unit file contains as the first three bytes the ASCII codes of the characters \var{PPU}.
+unit_u_ppu_invalid_version=10008_U_PPU Invalid Version $1
+% This unit file was compiled with a different version of the compiler, and
+% cannot be read.
+unit_u_ppu_invalid_processor=10009_U_PPU is compiled for another processor
+% This unit file was compiled for a different processor type, and
+% cannot be read.
+unit_u_ppu_invalid_target=10010_U_PPU is compiled for another target
+% This unit file was compiled for a different target, and
+% cannot be read.
+unit_u_ppu_source=10011_U_PPU Source: $1
+% When you use the \var{-vu} flag, the unit source file name is shown.
+unit_u_ppu_write=10012_U_Writing $1
+% When you specify the \var{-vu} switch, the compiler will tell you where it
+% writes the unit file.
+unit_f_ppu_cannot_write=10013_F_Can't Write PPU-File
+% An error occurred when writing the unit file.
+unit_f_ppu_read_error=10014_F_Error reading PPU-File
+% This means that the unit file was corrupted, and contains invalid
+% information. Recompilation will be necessary.
+unit_f_ppu_read_unexpected_end=10015_F_unexpected end of PPU-File
+% Unexpected end of file. This may mean that the PPU file is
+% corrupted.
+unit_f_ppu_invalid_entry=10016_F_Invalid PPU-File entry: $1
+% The unit the compiler is trying to read is corrupted, or generated with a
+% newer version of the compiler.
+unit_f_ppu_dbx_count_problem=10017_F_PPU Dbx count problem
+% There is an inconsistency in the debugging information of the unit.
+unit_e_illegal_unit_name=10018_E_Illegal unit name: $1
+% The name of the unit does not match the file name.
+unit_f_too_much_units=10019_F_Too much units
+% \fpc has a limit of 1024 units in a program. You can change this behavior
+% by changing the \var{maxunits} constant in the \file{fmodule.pas} file of the
+% compiler, and recompiling the compiler.
+unit_f_circular_unit_reference=10020_F_Circular unit reference between $1 and $2
+% Two units are using each other in the interface part. This is only allowed
+% in the \var{implementation} part. At least one unit must contain the other one
+% in the \var{implementation} section.
+unit_f_cant_compile_unit=10021_F_Can't compile unit $1, no sources available
+% A unit was found that needs to be recompiled, but no sources are
+% available.
+unit_f_cant_find_ppu=10022_F_Can't find unit $1 used by $2
+% You tried to use a unit of which the PPU file isn't found by the
+% compiler. Check your configuration file for the unit paths.
+unit_w_unit_name_error=10023_W_Unit $1 was not found but $2 exists
+% This error message is no longer used.
+unit_f_unit_name_error=10024_F_Unit $1 searched but $2 found
+% \dos truncation of 8 letters for unit PPU files
+% may lead to problems when unit name is longer than 8 letters.
+unit_w_switch_us_missed=10025_W_Compiling the system unit requires the -Us switch
+% When recompiling the system unit (it needs special treatment), the
+% \var{-Us} switch must be specified.
+unit_f_errors_in_unit=10026_F_There were $1 errors compiling module, stopping
+% When the compiler encounters a fatal error or too many errors in a module
+% then it stops with this message.
+unit_u_load_unit=10027_U_Load from $1 ($2) unit $3
+% When you use the \var{-vu} flag, which unit is loaded from which unit is
+% shown.
+unit_u_recompile_crc_change=10028_U_Recompiling $1, checksum changed for $2
+% The unit is recompiled because the checksum of a unit it depends on has
+% changed.
+unit_u_recompile_source_found_alone=10029_U_Recompiling $1, source found only
+% When you use the \var{-vu} flag, these messages tell you why the current
+% unit is recompiled.
+unit_u_recompile_staticlib_is_older=10030_U_Recompiling unit, static lib is older than ppufile
+% When you use the \var{-vu} flag, the compiler warns if the static library
+% of the unit is older than the unit file itself.
+unit_u_recompile_sharedlib_is_older=10031_U_Recompiling unit, shared lib is older than ppufile
+% When you use the \var{-vu} flag, the compiler warns if the shared library
+% of the unit is older than the unit file itself.
+unit_u_recompile_obj_and_asm_older=10032_U_Recompiling unit, obj and asm are older than ppufile
+% When you use the \var{-vu} flag, the compiler warns if the assembler or
+% object file of the unit is older than the unit file itself.
+unit_u_recompile_obj_older_than_asm=10033_U_Recompiling unit, obj is older than asm
+% When you use the \var{-vu} flag, the compiler warns if the assembler
+% file of the unit is older than the object file of the unit.
+unit_u_parsing_interface=10034_U_Parsing interface of $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% parsing the interface part of the unit.
+unit_u_parsing_implementation=10035_U_Parsing implementation of $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% parsing the implementation part of the unit.
+unit_u_second_load_unit=10036_U_Second load for unit $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% recompiling a unit for the second time. This can happen with
+% interdependent units.
+unit_u_check_time=10037_U_PPU Check file $1 time $2
+% When you use the \var{-vu} flag, the compiler shows the filename and
+% date and time of the file on which a recompile depends.
+### The following two error msgs is currently disabled.
+#unit_h_cond_not_set_in_last_compile=10038_H_Conditional $1 was not set at startup in last compilation of $2
+#% when recompilation of an unit is required the compiler will check that
+#% the same conditionals are set for the recompiliation. The compiler has
+#% found a conditional that currently is defined, but was not used the last
+#% time the unit was compiled.
+#unit_h_cond_set_in_last_compile=10039_H_Conditional $1 was set at startup in last compilation of $2
+#% when recompilation of an unit is required the compiler will check that
+#% the same conditionals are set for the recompiliation. The compiler has
+#% found a conditional that was used the last time the unit was compiled, but
+#% the conditional is currently not defined.
+unit_w_cant_compile_unit_with_changed_incfile=10040_W_Can't recompile unit $1, but found modifed include files
+% A unit was found to have modified include files, but
+% some source files were not found, so recompilation is impossible.
+unit_u_source_modified=10041_U_File $1 is newer than the one used for creating PPU file $2
+% A modified source file for a compiler unit was found.
+unit_u_ppu_invalid_fpumode=10042_U_Trying to use a unit which was compiled with a different FPU mode
+% Trying to compile code while using units which were not compiled with
+% the same floating point format mode. Either all code should be compiled
+% with FPU emulation on, or with FPU emulation off.
+unit_u_loading_interface_units=10043_U_Loading interface units from $1
+% When you use the \var{-vu} flag, the compiler warns that it is starting
+% to load the units defined in the interface part of the unit.
+unit_u_loading_implementation_units=10044_U_Loading implementation units from $1
+% When you use the \var{-vu} flag, the compiler warns that it is starting
+% to load the units defined in the implementation part of the unit.
+unit_u_interface_crc_changed=10045_U_Interface CRC changed for unit $1
+% When you use the \var{-vu} flag, the compiler warns that the
+% CRC calculated for the interface has been changed after the implementation
+% has been parsed.
+unit_u_implementation_crc_changed=10046_U_Implementation CRC changed for unit $1
+% When you use the \var{-vu} flag, the compiler warns that the
+% CRC calculated has been changed after the implementation
+% has been parsed.
+unit_u_finished_compiling=10047_U_Finished compiling unit $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has finished compiling the unit.
+unit_u_add_depend_to=10048_U_Adding dependency: $1 depends on $2
+% When you use the \var{-vu} flag, the compiler warns that it
+% has added a dependency between the two units.
+unit_u_no_reload_is_caller=10049_U_No reload, is caller: $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% will not reload the unit because it is the unit that wants
+% to load this unit.
+unit_u_no_reload_in_second_compile=10050_U_No reload, already in second compile: $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% will not reload the unit because it is already in a second recompile.
+unit_u_flag_for_reload=10051_U_Flag for reload: $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has to reload the unit.
+unit_u_forced_reload=10052_U_Forced reloading
+% When you use the \var{-vu} flag, the compiler warns that it
+% is reloading the unit because it was required.
+unit_u_previous_state=10053_U_Previous state of $1: $2
+% When you use the \var{-vu} flag, the compiler shows the
+% previous state of the unit.
+unit_u_second_compile_unit=10054_U_Already compiling $1, setting second compile
+% When you use the \var{-vu} flag, the compiler warns that it is starting
+% to recompile a unit for the second time. This can happen with interdependent
+% units.
+unit_u_loading_unit=10055_U_Loading unit $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% loading the unit.
+unit_u_finished_loading_unit=10056_U_Finished loading unit $1
+% When you use the \var{-vu} flag, the compiler warns that it finished
+% loading the unit.
+unit_u_registering_new_unit=10057_U_Registering new unit $1
+% When you use the \var{-vu} flag, the compiler warns that it has
+% found a new unit and is registering it in the internal lists.
+unit_u_reresolving_unit=10058_U_Re-resolving unit $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has to recalculate the internal data of the unit.
+unit_u_skipping_reresolving_unit=10059_U_Skipping re-resolving unit $1, still loading used units
+% When you use the \var{-vu} flag, the compiler warns that it is
+% skipping the recalculation of the internal data of the unit
+% because there is no data to recalculate.
+unit_u_unload_resunit=10060_U_Unloading resource unit $1 (not needed)
+% When you use the \var{-vu} flag, the compiler warns that it is unloading the
+% resource handling unit, since no resources are used.
+unit_e_different_wpo_file=10061_E_Unit $1 was compiled using a different whole program optimization feedback input ($2, $3); recompile it without wpo or use the same wpo feedback input file for this compilation invocation
+% When a unit has been compiled using a particular whole program optimization (wpo) feedback file (\var{-FW<x>} \var{-OW<x>}),
+% this compiled version of the unit is specialised for that particular compilation scenario and cannot be used in
+% any other context. It has to be recompiled before you can use it in another program or with another wpo feedback input file.
+unit_u_indirect_crc_changed=10062_U_Indirect interface (objects/classes) CRC changed for unit $1
+% When you use the \var{-vu} flag, the compiler warns that the
+% indirect CRC calculated for the unit (this is the CRC of all classes/objects/interfaces/$\ldots$
+% in the interfaces of units directly or indirectly used by this unit in the interface) has been changed after the
+% implementation has been parsed.
+% \end{description}
+# EndOfTeX
+
+#
+# Options
+#
+# 11049 is the last used one
+#
+option_usage=11000_O_$1 [options] <inputfile> [options]
+# BeginOfTeX
+%
+% \section{Command line handling errors}
+% This section lists errors that occur when the compiler is processing the
+% command line or handling the configuration files.
+% \begin{description}
+option_only_one_source_support=11001_W_Only one source file supported, changing source file to compile from "$1" into "$2"
+% You can specify only one source file on the command line. The last
+% one will be compiled, others will be ignored. This may indicate that
+% you forgot a \var{'-'} sign.
+option_def_only_for_os2=11002_W_DEF file can be created only for OS/2
+% This option can only be specified when you're compiling for OS/2.
+option_no_nested_response_file=11003_E_nested response files are not supported
+% You cannot nest response files with the \var{@file} command line option.
+option_no_source_found=11004_F_No source file name in command line
+% The compiler expects a source file name on the command line.
+option_no_option_found=11005_N_No option inside $1 config file
+% The compiler didn't find any option in that config file.
+option_illegal_para=11006_E_Illegal parameter: $1
+% You specified an unknown option.
+option_help_pages_para=11007_H_-? writes help pages
+% When an unknown option is given, this message is diplayed.
+option_too_many_cfg_files=11008_F_Too many config files nested
+% You can only nest up to 16 config files.
+option_unable_open_file=11009_F_Unable to open file $1
+% The option file cannot be found.
+option_reading_further_from=11010_D_Reading further options from $1
+% Displayed when you have notes turned on, and the compiler switches
+% to another options file.
+option_target_is_already_set=11011_W_Target is already set to: $1
+% Displayed if more than one \var{-T} option is specified.
+option_no_shared_lib_under_dos=11012_W_Shared libs not supported on DOS platform, reverting to static
+% If you specify \var{-CD} for the \dos platform, this message is displayed.
+% The compiler supports only static libraries under \dos.
+option_too_many_ifdef=11013_F_In options file $1 at line $2 too many \var{\#IF(N)DEFs} encountered
+% The \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_too_many_endif=11014_F_In options file $1 at line $2 unexpected \var{\#ENDIFs} encountered
+% The \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_too_less_endif=11015_F_Open conditional at the end of the options file
+% The \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_no_debug_support=11016_W_Debug information generation is not supported by this executable
+% It is possible to have a compiler executable that doesn't support
+% the generation of debugging info. If you use such an executable with the
+% \var{-g} switch, this warning will be displayed.
+option_no_debug_support_recompile_fpc=11017_H_Try recompiling with -dGDB
+% It is possible to have a compiler executable that doesn't support
+% the generation of debugging info. If you use such an executable with the
+% \var{-g} switch, this warning will be displayed.
+option_obsolete_switch=11018_W_You are using the obsolete switch $1
+% This warns you when you use a switch that is not needed/supported anymore.
+% It is recommended that you remove the switch to overcome problems in the
+% future, when the meaning of the switch may change.
+option_obsolete_switch_use_new=11019_W_You are using the obsolete switch $1, please use $2
+% This warns you when you use a switch that is not supported anymore. You
+% must now use the second switch instead.
+% It is recommended that you change the switch to overcome problems in the
+% future, when the meaning of the switch may change.
+option_switch_bin_to_src_assembler=11020_N_Switching assembler to default source writing assembler
+% This notifies you that the assembler has been changed because you used the
+% -a switch, which can't be used with a binary assembler writer.
+option_incompatible_asm=11021_W_Assembler output selected "$1" is not compatible with "$2"
+option_asm_forced=11022_W_"$1" assembler use forced
+% The assembler output selected cannot generate
+% object files with the correct format. Therefore, the
+% default assembler for this target is used instead.
+option_using_file=11026_T_Reading options from file $1
+% Options are also read from this file.
+option_using_env=11027_T_Reading options from environment $1
+% Options are also read from this environment string.
+option_handling_option=11028_D_Handling option "$1"
+% Debug info that an option is found and will be handled.
+option_help_press_enter=11029_O_*** press enter ***
+% Message shown when help is shown page per page. When pressing the ENTER
+% Key, the next page of help is shown. If you press q and then ENTER, the
+% compiler exits.
+option_start_reading_configfile=11030_H_Start of reading config file $1
+% Start of configuration file parsing.
+option_end_reading_configfile=11031_H_End of reading config file $1
+% End of configuration file parsing.
+option_interpreting_option=11032_D_interpreting option "$1"
+% The compiler is interpreting an option
+option_interpreting_firstpass_option=11036_D_interpreting firstpass option "$1"
+% The compiler is interpreting an option for the first time.
+option_interpreting_file_option=11033_D_interpreting file option "$1"
+% The compiler is interpreting an option which it read from the configuration file.
+option_read_config_file=11034_D_Reading config file "$1"
+% The compiler is starting to read the configuration file.
+option_found_file=11035_D_found source file name "$1"
+% Additional information about options.
+% Displayed when you have the debug option turned on.
+option_code_page_not_available=11039_E_Unknown codepage
+% An unknown codepage for the source files was requested.
+% The compiler is compiled with support for several codepages built-in.
+% The requested codepage is not in that list. You will need to recompile
+% the compiler with support for the codepage you need.
+option_config_is_dir=11040_F_Config file $1 is a directory
+% Directories cannot be used as configuration files.
+option_confict_asm_debug=11041_W_Assembler output selected "$1" cannot generate debug info, debugging disabled
+% The selected assembler output cannot generate
+% debugging information, debugging option is therefore disabled.
+option_ppc386_deprecated=11042_W_Use of ppc386.cfg is deprecated, please use fpc.cfg instead
+% Using ppc386.cfg is still supported for historical reasons, however, for a multiplatform
+% system the naming makes no sense anymore. Please continue to use fpc.cfg instead.
+option_else_without_if=11043_F_In options file $1 at line $2 \var{\#ELSE} directive without \var{\#IF(N)DEF} found
+% An \var{\#ELSE} statement was found in the options file without a matching \var{\#IF(N)DEF} statement.
+option_unsupported_target=11044_F_Option "$1" is not, or not yet, supported on the current target platform
+% Not all options are supported or implemented for all target platforms. This message informs you that a chosen
+% option is incompatible with the currently selected target platform.
+option_unsupported_target_for_feature=11045_F_The feature "$1" is not, or not yet, supported on the selected target platform
+% Not all features are supported or implemented for all target platforms. This message informs you that a chosen
+% feature is incompatible with the currently selected target platform.
+option_dwarf_smart_linking=11046_N_DWARF debug information cannot be used with smart linking on this target, switching to static linking
+% Smart linking is currently incompatble with DWARF debug information on most
+% platforms, so smart linking is disabled in such cases.
+option_ignored_target=11047_W_Option "$1" is ignored for the current target platform.
+% Not all options are supported or implemented for all target platforms. This message informs you that a chosen
+% option is ignored for the currently selected target platform.
+option_debug_external_unsupported=11048_W_Disabling external debug information because it is unsupported for the selected target/debug format combination.
+% Not all debug formats can be stored in an external file on all platforms. In particular, on
+% Mac OS X only DWARF debug information can be stored externally.
+option_dwarf_smartlink_creation=11049_N_DWARF debug information cannot be used with smart linking with external assembler, disabling static library creation.
+% Smart linking is currently incompatble with DWARF debug information on most
+% platforms, so smart linking is disabled in such cases.
+%\end{description}
+# EndOfTeX
+
+#
+# Whole program optimization
+#
+# 12019 is the last used one
+#
+# BeginOfTeX
+%
+% \section{Whole program optimization messages}
+% This section lists errors that occur when the compiler is performing
+% whole program optimization.
+% \begin{description}
+wpo_cant_find_file=12000_F_Cannot open whole program optimization feedback file "$1"
+% The compiler cannot open the specified feedback file with whole program optimization information.
+wpo_begin_processing=12001_D_Processing whole program optimization information in wpo feedback file "$1"
+% The compiler starts processing whole program optimization information found in the named file.
+wpo_end_processing=12002_D_Finished processing the whole program optimization information in wpo feedback file "$1"
+% The compiler has finished processing the whole program optimization information found in the named file.
+wpo_expected_section=12003_E_Expected section header, but got "$2" at line $1 of wpo feedback file
+% The compiler expected a section header in the whole program optimization file (starting with \%),
+% but did not find it.
+wpo_no_section_handler=12004_W_No handler registered for whole program optimization section "$2" at line $1 of wpo feedback file, ignoring
+% The compiler has no handler to deal with the mentioned whole program optimization information
+% section, and will therefore ignore it and skip to the next section.
+wpo_found_section=12005_D_Found whole program optimization section "$1" with information about "$2"
+% The compiler encountered a section with whole program optimization information, and according
+% to its handler this section contains information usable for the mentioned purpose.
+wpo_no_input_specified=12006_F_The selected whole program optimizations require a previously generated feedback file (use -Fw to specify)
+% The compiler needs information gathered during a previous compilation run to perform the selected
+% whole program optimizations. You can specify the location of the feedback file containing this
+% information using the -Fw switch.
+wpo_not_enough_info=12007_E_No collected information necessary to perform "$1" whole program optimization found
+% While you pointed the compiler to a file containing whole program optimization feedback, it
+% did not contain the information necessary to perform the selected optimizations. You most likely
+% have to recompile the program using the appropate -OWxxx switch.
+wpo_no_output_specified=12008_F_Specify a whole program optimization feedback file to store the generated info in (using -FW)
+% You have to specify the feedback file in which the compiler has to store the whole program optimization
+% feedback that is generated during the compilation run. This can be done using the -FW switch.
+wpo_output_without_info_gen=12009_E_Not generating any whole program optimization information, yet a feedback file was specified (using -FW)
+% The compiler was instructed to store whole program optimization feedback into a file specified using -FW,
+% but not to actually generated any whole program optimization feedback. The classes of to be
+% generated information can be speciied using -OWxxx.
+wpo_input_without_info_use=12010_E_Not performing any whole program optimizations, yet an input feedback file was specified (using -Fw)
+% The compiler was not instructed to perform any whole program optimizations (no -Owxxx parameters),
+% but nevertheless an input file with such feedback was specified (using -Fwyyy). Since this can
+% indicate that you forgot to specify an -Owxxx parameter, the compiler generates an error in this case.
+wpo_skipping_unnecessary_section=12011_D_Skipping whole program optimization section "$1", because not needed by the requested optimizations
+% The whole program optimization feedback file contains a section with information that is not
+% required by the selected whole program optimizations.
+wpo_duplicate_wpotype=12012_W_Overriding previously read information for "$1" from feedback input file using information in section "$2"
+% The feedback file contains multiple sections that provide the same class of information (e.g.,
+% information about which virtual methods can be devirtualized). In this case, the information in last encountered
+% section is used. Turn on debugging output (-vd) to see which class of information is provided by each section.
+wpo_cannot_extract_live_symbol_info_strip=12013_E_Cannot extract symbol liveness information from program when stripping symbols, use -Xs-
+% Certain symbol liveness collectors extract the symbol information from the linked program. If the symbol information
+% is stripped (option -Xs), this is not possible.
+wpo_cannot_extract_live_symbol_info_no_link=12014_E_Cannot extract symbol liveness information from program when when not linking
+% Certain symbol liveness collectors extract the symbol information from the linked program. If the program is not
+% linked by the compiler, this is not possible.
+wpo_cannot_find_symbol_progs=12015_F_Cannot find "$1" or "$2" to extract symbol liveness information from linked program
+% Certain symbol liveness collectors need a helper program to extract the symbol information from the linked program.
+% This helper program is normally 'nm', which is part of the GNU binutils.
+wpo_error_reading_symbol_file=12016_E_Error during reading symbol liveness information produced by "$1"
+% An error occurred during the reading of the symbol liveness file that was generated using the 'nm' or 'objdump' program. The reason
+% can be that it was shorter than expected, or that its format was not understood.
+wpo_error_executing_symbol_prog=12017_F_Error executing "$1" (exitcode: $2) to extract symbol information from linked program
+% Certain symbol liveness collectors need a helper program to extract the symbol information from the linked program.
+% The helper program produced the reported error code when it was run on the linked program.
+wpo_symbol_live_info_needs_smart_linking=12018_E_Collection of symbol liveness information can only help when using smart linking, use -CX -XX
+% Whether or not a symbol is live is determined by looking whether it exists in the final linked program.
+% Without smart linking/dead code stripping, all symbols are always included, regardless of whether they are
+% actually used or not. So in that case all symbols will be seen as live, which makes this optimization ineffective.
+wpo_cant_create_feedback_file=12019_E_Cannot create specified whole program optimisation feedback file "$1"
+% The compiler is unable to create the file specified using the -FW parameter to store the whole program optimisation information.
+%\end{description}
+# EndOfTeX
+
+
+#
+# Logo (option -l)
+#
+option_logo=11023_[
+Free Pascal Compiler version $FPCFULLVERSION [$FPCDATE] for $FPCCPU
+Copyright (c) 1993-2011 by Florian Klaempfl and others
+]
+
+#
+# Info (option -i)
+#
+option_info=11024_[
+Free Pascal Compiler version $FPCVERSION
+
+Compiler Date : $FPCDATE
+Compiler CPU Target: $FPCCPU
+
+Supported targets:
+ $OSTARGETS
+
+Supported CPU instruction sets:
+ $INSTRUCTIONSETS
+
+Supported FPU instruction sets:
+ $FPUINSTRUCTIONSETS
+
+Supported ABI targets:
+ $ABITARGETS
+
+Supported Optimizations:
+ $OPTIMIZATIONS
+
+Supported Whole Program Optimizations:
+ All
+ $WPOPTIMIZATIONS
+
+Supported Microcontroller types:
+ $CONTROLLERTYPES
+
+This program comes under the GNU General Public Licence
+For more information read COPYING.FPC
+
+Report bugs, suggestions, etc. to:
+ http://bugs.freepascal.org
+or
+ bugs@freepascal.org
+]
+
+#
+# Help pages (option -? and -h)
+#
+# The first character on the line indicates who will display this
+# line, the current possibilities are :
+# * = every target
+# 3 = 80x86 targets
+# 4 = x86_64
+# 6 = 680x0 targets
+# A = ARM
+# e = in extended debug mode only
+# P = PowerPC targets
+# S = Sparc targets
+# V = Virtual machine targets
+# The second character also indicates who will display this line,
+# (if the above character was TRUE) the current possibilities are :
+# * = everyone
+# g = with GDB info supported by the compiler
+# O = OS/2
+# L = UNIX systems
+# The third character represents the indentation level.
+#
+option_help_pages=11025_[
+**0*_Put + after a boolean switch option to enable it, - to disable it
+**1a_The compiler doesn't delete the generated assembler file
+**2al_List sourcecode lines in assembler file
+**2an_List node info in assembler file
+*L2ap_Use pipes instead of creating temporary assembler files
+**2ar_List register allocation/release info in assembler file
+**2at_List temp allocation/release info in assembler file
+**1A<x>_Output format:
+**2Adefault_Use default assembler
+3*2Aas_Assemble using GNU AS
+3*2Amacho_Mach-O (Darwin, Intel 32 bit) using internal writer
+3*2Anasmcoff_COFF (Go32v2) file using Nasm
+3*2Anasmelf_ELF32 (Linux) file using Nasm
+3*2Anasmwin32_Win32 object file using Nasm
+3*2Anasmwdosx_Win32/WDOSX object file using Nasm
+3*2Awasm_Obj file using Wasm (Watcom)
+3*2Anasmobj_Obj file using Nasm
+3*2Amasm_Obj file using Masm (Microsoft)
+3*2Atasm_Obj file using Tasm (Borland)
+3*2Aelf_ELF (Linux) using internal writer
+3*2Acoff_COFF (Go32v2) using internal writer
+3*2Apecoff_PE-COFF (Win32) using internal writer
+4*2Aas_Assemble using GNU AS
+4*2Agas_Assemble using GNU GAS
+4*2Agas-darwin_Assemble darwin Mach-O64 using GNU GAS
+4*2Amasm_Win64 object file using ml64 (Microsoft)
+4*2Apecoff_PE-COFF (Win64) using internal writer
+4*2Aelf_ELF (Linux-64bit) using internal writer
+6*2Aas_Unix o-file using GNU AS
+6*2Agas_GNU Motorola assembler
+6*2Amit_MIT Syntax (old GAS)
+6*2Amot_Standard Motorola assembler
+A*2Aas_Assemble using GNU AS
+P*2Aas_Assemble using GNU AS
+S*2Aas_Assemble using GNU AS
+**1b_Generate browser info
+**2bl_Generate local symbol info
+**1B_Build all modules
+**1C<x>_Code generation options:
+**2C3<x>_Turn on ieee error checking for constants
+**2Ca<x>_Select ABI, see fpc -i for possible values
+**2Cb_Generate big-endian code
+**2Cc<x>_Set default calling convention to <x>
+**2CD_Create also dynamic library (not supported)
+**2Ce_Compilation with emulated floating point opcodes
+**2Cf<x>_Select fpu instruction set to use, see fpc -i for possible values
+**2CF<x>_Minimal floating point constant precision (default, 32, 64)
+**2Cg_Generate PIC code
+**2Ch<n>_<n> bytes heap (between 1023 and 67107840)
+**2Ci_IO-checking
+**2Cn_Omit linking stage
+**2Co_Check overflow of integer operations
+**2CO_Check for possible overflow of integer operations
+**2Cp<x>_Select instruction set, see fpc -i for possible values
+**2CP<x>=<y>_ packing settings
+**3CPPACKSET=<y>_ <y> set allocation: 0, 1 or DEFAULT or NORMAL, 2, 4 and 8
+**2Cr_Range checking
+**2CR_Verify object method call validity
+**2Cs<n>_Set stack checking size to <n>
+**2Ct_Stack checking (for testing only, see manual)
+**2CX_Create also smartlinked library
+**1d<x>_Defines the symbol <x>
+**1D_Generate a DEF file
+**2Dd<x>_Set description to <x>
+**2Dv<x>_Set DLL version to <x>
+*O2Dw_PM application
+**1e<x>_Set path to executable
+**1E_Same as -Cn
+**1fPIC_Same as -Cg
+**1F<x>_Set file names and paths:
+**2Fa<x>[,y]_(for a program) load units <x> and [y] before uses is parsed
+**2Fc<x>_Set input codepage to <x>
+**2FC<x>_Set RC compiler binary name to <x>
+**2Fd_Disable the compiler's internal directory cache
+**2FD<x>_Set the directory where to search for compiler utilities
+**2Fe<x>_Redirect error output to <x>
+**2Ff<x>_Add <x> to framework path (Darwin only)
+**2FE<x>_Set exe/unit output path to <x>
+**2Fi<x>_Add <x> to include path
+**2Fl<x>_Add <x> to library path
+**2FL<x>_Use <x> as dynamic linker
+**2Fm<x>_Load unicode conversion table from <x>.txt in the compiler dir
+**2Fo<x>_Add <x> to object path
+**2Fr<x>_Load error message file <x>
+**2FR<x>_Set resource (.res) linker to <x>
+**2Fu<x>_Add <x> to unit path
+**2FU<x>_Set unit output path to <x>, overrides -FE
+**2FW<x>_Store generated whole-program optimization feedback in <x>
+**2Fw<x>_Load previously stored whole-program optimization feedback from <x>
+*g1g_Generate debug information (default format for target)
+*g2gc_Generate checks for pointers
+*g2gh_Use heaptrace unit (for memory leak/corruption debugging)
+*g2gl_Use line info unit (show more info with backtraces)
+*g2go<x>_Set debug information options
+*g3godwarfsets_ Enable DWARF 'set' type debug information (breaks gdb < 6.5)
+*g3gostabsabsincludes_ Store absolute/full include file paths in Stabs
+*g3godwarfmethodclassprefix_ Prefix method names in DWARF with class name
+*g2gp_Preserve case in stabs symbol names
+*g2gs_Generate Stabs debug information
+*g2gt_Trash local variables (to detect uninitialized uses)
+*g2gv_Generates programs traceable with Valgrind
+*g2gw_Generate DWARFv2 debug information (same as -gw2)
+*g2gw2_Generate DWARFv2 debug information
+*g2gw3_Generate DWARFv3 debug information
+*g2gw4_Generate DWARFv4 debug information (experimental)
+**1i_Information
+**2iD_Return compiler date
+**2iV_Return short compiler version
+**2iW_Return full compiler version
+**2iSO_Return compiler OS
+**2iSP_Return compiler host processor
+**2iTO_Return target OS
+**2iTP_Return target processor
+**1I<x>_Add <x> to include path
+**1k<x>_Pass <x> to the linker
+**1l_Write logo
+**1M<x>_Set language mode to <x>
+**2Mfpc_Free Pascal dialect (default)
+**2Mobjfpc_FPC mode with Object Pascal support
+**2Mdelphi_Delphi 7 compatibility mode
+**2Mtp_TP/BP 7.0 compatibility mode
+**2Mmacpas_Macintosh Pascal dialects compatibility mode
+**1n_Do not read the default config files
+**1N<x>_Node tree optimizations
+**2Nu_Unroll loops
+**1o<x>_Change the name of the executable produced to <x>
+**1O<x>_Optimizations:
+**2O-_Disable optimizations
+**2O1_Level 1 optimizations (quick and debugger friendly)
+**2O2_Level 2 optimizations (-O1 + quick optimizations)
+**2O3_Level 3 optimizations (-O2 + slow optimizations)
+**2Oa<x>=<y>_Set alignment
+**2Oo[NO]<x>_Enable or disable optimizations, see fpc -i for possible values
+**2Op<x>_Set target cpu for optimizing, see fpc -i for possible values
+**2OW<x>_Generate whole-program optimization feedback for optimization <x>, see fpc -i for possible values
+**2Ow<x>_Perform whole-program optimization <x>, see fpc -i for possible values
+**2Os_Optimize for size rather than speed
+**1pg_Generate profile code for gprof (defines FPC_PROFILE)
+**1R<x>_Assembler reading style:
+**2Rdefault_Use default assembler for target
+3*2Ratt_Read AT&T style assembler
+3*2Rintel_Read Intel style assembler
+6*2RMOT_Read motorola style assembler
+**1S<x>_Syntax options:
+**2S2_Same as -Mobjfpc
+**2Sc_Support operators like C (*=,+=,/= and -=)
+**2Sa_Turn on assertions
+**2Sd_Same as -Mdelphi
+**2Se<x>_Error options. <x> is a combination of the following:
+**3*_<n> : Compiler halts after the <n> errors (default is 1)
+**3*_w : Compiler also halts after warnings
+**3*_n : Compiler also halts after notes
+**3*_h : Compiler also halts after hints
+**2Sg_Enable LABEL and GOTO (default in -Mtp and -Mdelphi)
+**2Sh_Use ansistrings by default instead of shortstrings
+**2Si_Turn on inlining of procedures/functions declared as "inline"
+**2Sk_Load fpcylix unit
+**2SI<x>_Set interface style to <x>
+**3SIcom_COM compatible interface (default)
+**3SIcorba_CORBA compatible interface
+**2Sm_Support macros like C (global)
+**2So_Same as -Mtp
+**2Ss_Constructor name must be init (destructor must be done)
+**2Sx_Enable exception keywords (default in Delphi/ObjFPC modes)
+**2Sy_@<pointer> returns a typed pointer, same as $T+
+**1s_Do not call assembler and linker
+**2sh_Generate script to link on host
+**2st_Generate script to link on target
+**2sr_Skip register allocation phase (use with -alr)
+**1T<x>_Target operating system:
+3*2Tdarwin_Darwin/Mac OS X
+3*2Temx_OS/2 via EMX (including EMX/RSX extender)
+3*2Tfreebsd_FreeBSD
+3*2Tgo32v2_Version 2 of DJ Delorie DOS extender
+3*2Tiphonesim_ iPhoneSimulator from iOS SDK 3.2+ (older versions: -Tdarwin)
+3*2Tlinux_Linux
+3*2Tnetbsd_NetBSD
+3*2Tnetware_Novell Netware Module (clib)
+3*2Tnetwlibc_Novell Netware Module (libc)
+3*2Topenbsd_OpenBSD
+3*2Tos2_OS/2 / eComStation
+3*2Tsunos_SunOS/Solaris
+3*2Tsymbian_Symbian OS
+3*2Tsolaris_Solaris
+3*2Twatcom_Watcom compatible DOS extender
+3*2Twdosx_WDOSX DOS extender
+3*2Twin32_Windows 32 Bit
+3*2Twince_Windows CE
+4*2Tdarwin_Darwin/Mac OS X
+4*2Tlinux_Linux
+4*2Twin64_Win64 (64 bit Windows systems)
+6*2Tamiga_Commodore Amiga
+6*2Tatari_Atari ST/STe/TT
+6*2Tlinux_Linux
+6*2Tpalmos_PalmOS
+A*2Tdarwin_Darwin/iPhoneOS/iOS
+A*2Tlinux_Linux
+A*2Twince_Windows CE
+P*2Tamiga_AmigaOS
+P*2Tdarwin_Darwin/Mac OS X
+P*2Tlinux_Linux
+P*2Tmacos_Mac OS (classic)
+P*2Tmorphos_MorphOS
+S*2Tsolaris_Solaris
+S*2Tlinux_Linux
+**1u<x>_Undefines the symbol <x>
+**1U_Unit options:
+**2Un_Do not check where the unit name matches the file name
+**2Ur_Generate release unit files (never automatically recompiled)
+**2Us_Compile a system unit
+**1v<x>_Be verbose. <x> is a combination of the following letters:
+**2*_e : Show errors (default) 0 : Show nothing (except errors)
+**2*_w : Show warnings u : Show unit info
+**2*_n : Show notes t : Show tried/used files
+**2*_h : Show hints c : Show conditionals
+**2*_i : Show general info d : Show debug info
+**2*_l : Show linenumbers r : Rhide/GCC compatibility mode
+**2*_s : Show time stamps q : Show message numbers
+**2*_a : Show everything x : Executable info (Win32 only)
+**2*_b : Write file names messages p : Write tree.log with parse tree
+**2*_ with full path v : Write fpcdebug.txt with
+**2*_ lots of debugging info
+**2*_m<x>,<y> : Don't show messages numbered <x> and <y>
+**1W<x>_Target-specific options (targets)
+3*2WA_Specify native type application (Windows)
+4*2WA_Specify native type application (Windows)
+A*2WA_Specify native type application (Windows)
+3*2Wb_Create a bundle instead of a library (Darwin)
+P*2Wb_Create a bundle instead of a library (Darwin)
+p*2Wb_Create a bundle instead of a library (Darwin)
+A*2Wb_Create a bundle instead of a library (Darwin)
+4*2Wb_Create a bundle instead of a library (Darwin)
+3*2WB_Create a relocatable image (Windows, Symbian)
+3*2WBxxxx_Set image base to xxxx (Windows, Symbian)
+4*2WB_Create a relocatable image (Windows)
+4*2WBxxxx_Set image base to xxxx (Windows)
+A*2WB_Create a relocatable image (Windows, Symbian)
+A*2WBxxxx_Set image base to xxxx (Windows, Symbian)
+3*2WC_Specify console type application (EMX, OS/2, Windows)
+4*2WC_Specify console type application (EMX, OS/2, Windows)
+A*2WC_Specify console type application (Windows)
+P*2WC_Specify console type application (Classic Mac OS)
+3*2WD_Use DEFFILE to export functions of DLL or EXE (Windows)
+4*2WD_Use DEFFILE to export functions of DLL or EXE (Windows)
+A*2WD_Use DEFFILE to export functions of DLL or EXE (Windows)
+3*2We_Use external resources (Darwin)
+4*2We_Use external resources (Darwin)
+A*2We_Use external resources (Darwin)
+P*2We_Use external resources (Darwin)
+p*2We_Use external resources (Darwin)
+3*2WF_Specify full-screen type application (EMX, OS/2)
+3*2WG_Specify graphic type application (EMX, OS/2, Windows)
+4*2WG_Specify graphic type application (EMX, OS/2, Windows)
+A*2WG_Specify graphic type application (Windows)
+P*2WG_Specify graphic type application (Classic Mac OS)
+3*2Wi_Use internal resources (Darwin)
+4*2Wi_Use internal resources (Darwin)
+A*2Wi_Use internal resources (Darwin)
+P*2Wi_Use internal resources (Darwin)
+p*2Wi_Use internal resources (Darwin)
+3*2WI_Turn on/off the usage of import sections (Windows)
+4*2WI_Turn on/off the usage of import sections (Windows)
+A*2WI_Turn on/off the usage of import sections (Windows)
+3*2WN_Do not generate relocation code, needed for debugging (Windows)
+4*2WN_Do not generate relocation code, needed for debugging (Windows)
+A*2WN_Do not generate relocation code, needed for debugging (Windows)
+A*2Wpxxxx_Specify the controller type, see fpc -i for possible values
+V*2Wpxxxx_Specify the controller type, see fpc -i for possible values
+3*2WR_Generate relocation code (Windows)
+4*2WR_Generate relocation code (Windows)
+A*2WR_Generate relocation code (Windows)
+P*2WT_Specify MPW tool type application (Classic Mac OS)
+**2WX_Enable executable stack (Linux)
+**1X_Executable options:
+**2Xc_Pass --shared/-dynamic to the linker (BeOS, Darwin, FreeBSD, Linux)
+**2Xd_Do not use standard library search path (needed for cross compile)
+**2Xe_Use external linker
+**2Xg_Create debuginfo in a separate file and add a debuglink section to executable
+**2XD_Try to link units dynamically (defines FPC_LINK_DYNAMIC)
+**2Xi_Use internal linker
+**2Xm_Generate link map
+**2XM<x>_Set the name of the 'main' program routine (default is 'main')
+**2XP<x>_Prepend the binutils names with the prefix <x>
+**2Xr<x>_Set the linker's rlink-path to <x> (needed for cross compile, see the ld manual for more information) (BeOS, Linux)
+**2XR<x>_Prepend <x> to all linker search paths (BeOS, Darwin, FreeBSD, Linux, Mac OS, Solaris)
+**2Xs_Strip all symbols from executable
+**2XS_Try to link units statically (default, defines FPC_LINK_STATIC)
+**2Xt_Link with static libraries (-static is passed to linker)
+**2XX_Try to smartlink units (defines FPC_LINK_SMART)
+**1*_
+**1?_Show this help
+**1h_Shows this help without waiting
+]
+
+#
+# The End...
diff --git a/closures/compiler/msg/errores.msg b/closures/compiler/msg/errores.msg
new file mode 100644
index 0000000000..de54fd789d
--- /dev/null
+++ b/closures/compiler/msg/errores.msg
@@ -0,0 +1,2375 @@
+# **************** don't edit! *******************
+# edit erroresu.msg and convert it to iso-8859-15
+# by e.g.
+# recode utf-8..iso-8859-15
+# and save it as errores.msg
+# ************************************************
+#
+# This file is part of the Free Pascal Compiler
+# Copyright (c) 1999-2000 by the Free Pascal Development team
+#
+# Spanish Language File for Free Pascal
+#
+# See the file COPYING.FPC, included in this distribution,
+# for details about the copyright.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#
+#
+# The constants are build in the following order:
+# <part>_<type>_<txtidentifier>
+#
+# <part> is the part of the compiler the message is used
+# asmr_ assembler parsing
+# asmw_ assembler writing/binary writers
+
+# unit_ unit handling
+# scan_ scanner
+# parser_ parser
+# type_ type checking
+# general_ general info
+# exec_ calls to assembler, linker, binder
+#
+# <type> the type of the message it should normally used for
+# f_ fatal error
+# e_ error
+# w_ warning
+# n_ note
+# h_ hint
+# i_ info
+# l_ add linenumber
+# u_ used
+# t_ tried
+# c_ conditional
+# d_ debug message
+# x_ executable informations
+#
+
+#
+# General
+#
+# 01016 is the last used one
+#
+# BeginOfTeX
+% \section{General compiler messages}
+% This section gives the compiler messages which are not fatal, but which
+% display useful information. The number of such messages can be
+% controlled with the various verbosity level \var{-v} switches.
+% \begin{description}
+general_t_compilername=01000_T_Compilador: $1
+% When the \var{-vt} switch is used, this line tells you what compiler
+% is used.
+general_d_sourceos=01001_D_SO del host: $1
+% When the \var{-vd} switch is used, this line tells you what the source
+% operating system is.
+general_i_targetos=01002_I_SO de destino: $1
+% When the \var{-vd} switch is used, this line tells you what the target
+% operating system is.
+general_t_exepath=01003_T_Usando la ruta para ejecutables: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for its binaries.
+general_t_unitpath=01004_T_Usando la ruta para unidades: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for compiled units. You can set this path with the \var{-Fu}
+general_t_includepath=01005_T_Usando la ruta para inclusiones: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for its include files (files used in \var{\{\$I xxx\}} statements).
+% You can set this path with the \var{-I} option.
+general_t_librarypath=01006_T_Usando la ruta para bibliotecas: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for the libraries. You can set this path with the \var{-Fl} option.
+general_t_objectpath=01007_T_Usando la ruta para objetos: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for object files you link in (files used in \var{\{\$L xxx\}} statements).
+% You can set this path with the \var{-Fo} option.
+general_i_abslines_compiled=01008_I_$1 Líneas compiladas, $2 seg
+% When the \var{-vi} switch is used, the compiler reports the number
+% of lines compiled, and the time it took to compile them (real time,
+% not program time).
+general_f_no_memory_left=01009_F_No queda suficiente memoria disponible
+% The compiler doesn't have enough memory to compile your program. There are
+% several remedies for this:
+% \begin{itemize}
+% \item If you're using the build option of the compiler, try compiling the
+% different units manually.
+% \item If you're compiling a huge program, split it up in units, and compile
+% these separately.
+% \item If the previous two don't work, recompile the compiler with a bigger
+% heap (you can use the \var{-Ch} option for this, \seeo{Ch})
+% \end{itemize}
+general_i_writingresourcefile=01010_I_Escribiendo archivo de recursos de tabla de cadenas: $1
+% This message is shown when the compiler writes the Resource String Table
+% file containing all the resource strings for a program.
+general_e_errorwritingresourcefile=01011_E_Escribiendo archivo de recursos de tabla de cadenas: $1
+% This message is shown when the compiler encountered an error when writing
+% the Resource String Table file
+general_i_fatal=01012_I_Fatal:
+% Prefix for Fatal Errors
+general_i_error=01013_I_Error:
+% Prefix for Errors
+general_i_warning=01014_I_Aviso:
+% Prefix for Warnings
+general_i_note=01015_I_Nota:
+% Prefix for Notes
+general_i_hint=01016_I_Consejo:
+% Prefix for Hints
+general_e_path_does_not_exist=01017_E_La ruta "$1" no existe
+% The specified path does not exist.
+general_e_compilation_aborted=01018_E_Compilación abortada
+% \end{description}
+#
+# Scanner
+#
+# 02063 is the last used one
+#
+% \section{Scanner messages.}
+% This section lists the messages that the scanner emits. The scanner takes
+% care of the lexical structure of the pascal file, i.e. it tries to find
+% reserved words, strings, etc. It also takes care of directives and
+% conditional compiling handling.
+% \begin{description}
+scan_f_end_of_file=02000_F_Final de fichero inesperado
+% this typically happens in one of the following cases :
+% \begin{itemize}
+% \item The source file ends before the final \var{end.} statement. This
+% happens mostly when the \var{begin} and \var{end} statements aren't
+% balanced;
+% \item An include file ends in the middle of a statement.
+% \item A comment was not closed
+% \end{itemize}
+scan_f_string_exceeds_line=02001_F_La cadena excede la línea
+% There is a missing closing ' in a string, so it occupies
+% multiple lines.
+scan_f_illegal_char=02002_F_Caracter inválido
+% An illegal character was encountered in the input file.
+scan_f_syn_expected=02003_F_Error de sintaxis, se esperaba "$1" pero se encontró "$2"
+% This indicates that the compiler expected a different token than
+% the one you typed. It can occur almost everywhere where you make a
+% mistake against the pascal language.
+scan_t_start_include_file=02004_TL_Empezando a leer el fichero incluido $1
+% When you provide the \var{-vt} switch, the compiler tells you
+% when it starts reading an included file.
+scan_w_comment_level=02005_W_Nivel de comentario anidado $1 encontrado
+% When the \var{-vw} switch is used, then the compiler warns you if
+% it finds nested comments. Nested comments are not allowed in Turbo Pascal
+% and can be a possible source of errors.
+scan_n_ignored_switch=02008_N_Directiva de compilación $1 ignorado
+% With \var{-vn} on, the compiler warns if it ignores a switch
+scan_w_illegal_switch=02009_W_Directiva de compilación $i inválida
+% You included a compiler switch (i.e. \var{\{\$... \}}) which the compiler
+% does not recognise
+scan_w_switch_is_global=02010_W_Esta opción de compilacion tiene un efecto global
+% The compiler switch is misplaced, and should be located at
+% the start of the unit or program.
+scan_e_illegal_char_const=02011_E_Constante de caracter inválido
+% This happens when you specify a character with its ASCII code, as in
+% \var{\#96}, but the number is either illegal, or out of range.
+scan_f_cannot_open_input=02012_F_No se puede abrir el fichero "$1"
+% \fpc cannot find the program or unit source file you specified on the
+% command line.
+scan_f_cannot_open_includefile=02013_F_No se puede abrir el fichero de inclusion "$1"
+% \fpc cannot find the source file you specified in a \var{\{\$include ..\}}
+% statement.
+scan_w_only_pack_records=02015_W_Los campos de los registros pueden ser alineados solo a 1, 2, 4 o 16 bytes
+% You are specifying the \var{\{\$PACKRECORDS n\} } with an illegal value for
+% \var{n}. Only 1, 2, 4, 8, 16 and 32 are valid in this case.
+scan_w_only_pack_enum=02016_W_Los tipos enumerados solo pueden ser almacenados en 1, 2 o 4 bytes
+% You are specifying the \var{\{\$PACKENUM n\}} with an illegal value for
+% \var{n}. Only 1,2 or 4 are valid in this case.
+scan_e_endif_expected=02017_E_$1 esperado para $2 definido en la línea $3
+% Your conditional compilation statements are unbalanced.
+scan_e_preproc_syntax_error=02018_E_Error de sintaxis mientras se procesaba una expresión de compilación condicional
+% There is an error in the expression following the \var{\{\$if ..\}}, $ifc or $setc compiler
+% directives.
+scan_e_error_in_preproc_expr=02019_E_Evaluando una expresión de compilación condicional
+% There is an error in the expression following the \var{\{\$if ..\}}, $ifc or $setc compiler
+% directives.
+scan_w_macro_cut_after_255_chars=02020_W_El contenido de las macros esta limitado a 255 caracteres de longitud
+% The contents of macros cannot be longer than 255 characters.
+scan_e_endif_without_if=02021_E_ENDIF sin IF(N)DEF
+% Your \var{\{\$IFDEF ..\}} and {\{\$ENDIF\}} statements aren't balanced.
+scan_f_user_defined=02022_F_Error de usuario: $1
+% A user defined fatal error occurred. see also the \progref
+scan_e_user_defined=02023_E_Error de usuario: $1
+% A user defined error occurred. see also the \progref
+scan_w_user_defined=02024_W_Aviso de usuario: $1
+% A user defined warning occurred. see also the \progref
+scan_n_user_defined=02025_N_Nota de usuario: $1
+% A user defined note was encountered. see also the \progref
+scan_h_user_defined=02026_H_Consejo de usuario: $1
+% A user defined hint was encountered. see also the \progref
+scan_i_user_defined=02027_I_Informacion de usuario: $1
+% User defined information was encountered. see also the \progref
+scan_e_keyword_cant_be_a_macro=02028_E_Palabra clave redefinida como macro no tiene efecto
+% You cannot redefine keywords with macros.
+scan_f_macro_buffer_overflow=02029_F_Desbordamiento del buffer de macro durante la lextura o expansión
+% Your macro or its result was too long for the compiler.
+can_w_macro_too_deep=02030_W_La expansión de macros excede una profundidad de 16.
+% When expanding a macro, macros have been nested to a level of 16.
+% The compiler will expand no further, since this may be a sign that
+% recursion is used.
+scan_w_wrong_styled_switch=02031_W_Las directivas de compilacióon no estan soportadas en comentarios estilo //
+% Compiler switches should be in normal pascal style comments.
+scan_d_handling_switch=02032_DL_Manejando la directiva "$1"
+% When you set debugging info on (\var{-vd}) the compiler tells you when it
+% is evaluating conditional compile statements.
+scan_c_endif_found=02033_CL_ENDIF $1 encontrado
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifdef_found=02034_CL_IFDEF $1 encontrado, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifopt_found=02035_CL_IFOPT $1 encontrado, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_if_found=02036_CL_IF $1 encontrado, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifndef_found=02037_CL_IFNDEF $1 encontrado, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_else_found=02038_CL_ELSE $1 encontrado, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_skipping_until=02039_CL_Omitiendo hasta...
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements, and whether it is skipping or
+% compiling parts.
+scan_i_press_enter=02040_I_Presione <retorno> para continuar
+% When the \var{-vi} switch is used, the compiler stops compilation
+% and waits for the \var{Enter} key to be pressed when it encounters
+% a \var{\{\$STOP\}} directive.
+scan_w_unsupported_switch=02041_W_Conmutador "$1" no soportado
+% When warnings are turned on (\var{-vw}) the compiler warns you about
+% unsupported switches. This means that the switch is used in Delphi or
+% Turbo Pascal, but not in \fpc
+scan_w_illegal_directive=02042_W_Directiva de compilación "$1" inválida
+% When warings are turned on (\var{-vw}) the compiler warns you about
+% unrecognised switches. For a list of recognised switches, \progref
+scan_t_back_in=02043_TL_Vuelve en $1
+% When you use (\var{-vt}) the compiler tells you when it has finished
+% reading an include file.
+scan_w_unsupported_app_type=02044_W_Tipo de aplicación no soportada: "$1"
+% You get this warning, if you specify an unknown application type
+% with the directive \var{\{\$APPTYPE\}}
+scan_w_app_type_not_support=02045_W_APPTYPE no es soportado por el SO de destino
+% The \var{\{\$APPTYPE\}} directive is supported by certain operating systems only.
+scan_w_description_not_support=02046_W_DESCRIPTION no es soportado por el SO de destino
+% The \var{\{\$DESCRIPTION\}} directive is not supported on this target OS
+scan_n_version_not_support=02047_N_VERSION no es soportado por el SO de destino
+% The \var{\{\$VERSION\}} directive is not supported on this target OS
+scan_n_only_exe_version=02048_N_VERSION sólo para EXEs o DLLs
+% The \var{\{\$VERSION\}} directive is only used for executable or DLL sources.
+scan_w_wrong_version_ignored=02049_W_Formato erroneo para la directiva VERSION: "$1"
+% The \var{\{\$VERSION\}} directive format is majorversion.minorversion
+% where majorversion and minorversion are words.
+scan_e_illegal_asmmode_specifier=02050_E_Estilo de ensamblador inváalido especificado: "$1"
+% When you specify an assembler mode with the \var{\{\$ASMMODE xxx\}}
+% the compiler didn't recognize the mode you specified.
+scan_w_no_asm_reader_switch_inside_asm=02051_W_No es posible cambiar el lector dentro de una sentencia asm. "$1" solo sera efectivo en los siguientes
+% It is not possible to switch from one assembler reader to another
+% inside an assmebler block. The new reader will be used for next
+% assembler statements only.
+scan_e_wrong_switch_toggle=02052_E_Modificador de conmutador erróneo, use ON/OFF o +/-
+% You need to use ON or OFF or a + or - to toggle the switch
+scan_e_resourcefiles_not_supported=02053_E_Los ficheros de recursos no son soportados por la plataforma de destino
+% The target you are compiling for doesn't support resource files.
+scan_w_include_env_not_found=02054_W_Variable de entorno incluida "$1" no encontrada.
+% The included environment variable can't be found in the environment, it will
+% be replaced by an empty string instead.
+scan_e_invalid_maxfpureg_value=02055_E_Valor inválido para el registro de la FPU
+% Valid values for this directive are 0..8 and NORMAL/DEFAULT
+scan_w_only_one_resourcefile_supported=02056_W_La plataforma de destino solo soporta un archivo de recursos
+% The target you are compiling for supports only one resource file.
+% The first resource file found is used, the others are discarded.
+scan_w_macro_support_turned_off=02057_W_El soporte para macros ha sido deshabilitado
+% A macro declaration has been found, but macro support is currently off,
+% so the declaration will be ignored. To turn macro support on compile with
+% -Sm on the commandline or add \{\$MACRO ON\} in the source
+scan_e_invalid_interface_type=02058_E_El tipo de interfaz especificado es inválido. Debe ser COM, CORBA o DEFAULT
+% The interface type that was specified is not supported
+scan_w_appid_not_support=02059_W_APPID solo esta soportado para PalmOS
+% The \var{\{\$APPID\}} directive is only supported for the PalmOS target.
+scan_w_appname_not_support=02060_W_APPNAME solo esta soportado para PalmOS
+% The \var{\{\$APPNAME\}} directive is only supported for the PalmOS target.
+scan_e_string_exceeds_255_chars=02061_E_Las constantes de cadena no pueden ser de mas de 255 caracteres de longitud
+% A single string constant can contain at most 255 chars. Try splitting up the
+% string in multiple smaller parts and concatenate them with a + operator.
+scan_f_include_deep_ten=02062_F_La inclusion de archivos no puede exceder 16 niveles
+% When including include files the files have been nested to a level of 16.
+% The compiler will expand no further, since this may be a sign that
+% recursion is used.
+scan_e_too_many_push=02063_F_Demasiados niveles de PUSH
+% A maximum of 20 levels is allowed. This error occurs only in mode MacPas.
+scan_e_too_many_pop=02064_E_A POP sin un PUSH previo
+% This error occurs only in mode MacPas.
+scan_e_error_macro_lacks_value=02065_E_Macro o variable de compilación "$1" no tiene ningún valor
+% Thus the conditional compiling expression cannot be evaluated.
+scan_e_wrong_switch_toggle_default=02066_E_Valor invalido para el conmutado, use ON/OFF/DEFAULT o +/-/*
+% You need to use ON or OFF or DEFAULT or a + or - or * to toggle the switch
+scan_e_mode_switch_not_allowed=02067_E_No esta permitido cambiar de modo a "$1" aqui
+% A mode switch has already been encountered, or, in case of option -Mmacpas,
+% a mode switch occur after UNIT.
+scan_e_error_macro_undefined=02068_E_Variable en tiempo de compilación "$1" no ha sido definida.
+% Thus the conditional compile time expression cannot be evaluated.
+% \end{description}
+#
+# Parser
+#
+# 03192 is the last used one
+#
+% \section{Parser messages}
+% This section lists all parser messages. The parser takes care of the
+% semantics of you language, i.e. it determines if your pascal constructs
+% are correct.
+% \begin{description}
+parser_e_syntax_error=03000_E_Analizador - Error de sintaxis
+% An error against the Turbo Pascal language was encountered. This happens
+% typically when an illegal character is found in the sources file.
+parser_e_dont_nest_interrupt=03004_E_Los procedimientos INTERRUPT no pueden ser anidados
+% An \var{INTERRUPT} procedure must be global.
+parser_w_proc_directive_ignored=03005_W_Tipo de procedimiento "$1" ignorado
+% The specified is ignored by FPC programs.
+parser_e_no_overload_for_all_procs=03006_E_No todas las declaraciones de "$1" llevan OVERLOAD
+% When you want to use overloading using the \var{OVERLOAD} directive, then
+% all declarations need to have \var{OVERLOAD} specified.
+parser_e_export_name_double=03008_E_Nombre de funcion exportada "$1" duplicado
+% Exported function names inside a specific DLL must all be different
+parser_e_export_ordinal_double=03009_E_Indice de funcion exportada "$1" duplicado
+% Exported function names inside a specific DLL must all be different
+parser_e_export_invalid_index=03010_E_Indice de funcion exportada inválido
+% DLL function index must be in the range \var{1..\$FFFF}
+parser_w_parser_reloc_no_debug=03011_W_La informacion de depurado $1 para ejecutables o DLLs reubicables no funciona. Desactivado.
+parser_w_parser_win32_debug_needs_WN=03012_W_Para permitir el depurado en win32 las reubicaciones deben ser desactivadas con la opcion -WN
+% Stabs info is wrong for relocatable DLL or EXES use -WN
+% if you want to debug win32 executables.
+parser_e_constructorname_must_be_init=03013_E_El nombre del constructor debe ser INIT
+% You are declaring an object constructor with a name which is not \var{init}, and the
+% \var{-Ss} switch is in effect. See the \var{-Ss} switch (\seeo{Ss}).
+parser_e_destructorname_must_be_done=03014_E_El nombre del destructor debe ser DONE
+% You are declaring an object destructor with a name which is not \var{done}, and the
+% \var{-Ss} switch is in effect. See the \var{-Ss} switch (\seeo{Ss}).
+parser_e_proc_inline_not_supported=03016_E_Procedimientos tipo INLINE no soportados
+% You tried to compile a program with C++ style inlining, and forgot to
+% specify the \var{-Si} option (\seeo{Si}). The compiler doesn't support C++
+% styled inlining by default.
+parser_w_constructor_should_be_public=03018_W_El constructor debería ser público
+% Constructors must be in the 'public' part of an object (class) declaration.
+parser_w_destructor_should_be_public=03019_W_El destructor debería ser público
+% Destructors must be in the 'public' part of an object (class) declaration.
+parser_n_only_one_destructor=03020_N_Una clase debería tener solo un destructor
+% You can declare only one destructor for a class.
+parser_e_no_local_objects=03021_E_Las definiciones de clases locales no están permitidas
+% Classes must be defined globally. They cannot be defined inside a
+% procedure or function
+parser_f_no_anonym_objects=03022_F_Las definiciones de clases anónimas no están permitidas
+% An invalid object (class) declaration was encountered, i.e. an
+% object or class without methods that isn't derived from another object or
+% class. For example:
+% \begin{verbatim}
+% Type o = object
+% a : longint;
+% end;
+% \end{verbatim}
+% will trigger this error.
+parser_n_object_has_no_vmt=03023_N_El objeto "$1" no tiene VMT
+% This is a note indicating that the declared object has no
+% virtual method table.
+parser_e_illegal_parameter_list=03024_E_Lista de parámetros inválida
+% You are calling a function with parameters that are of a different type than
+% the declared parameters of the function.
+parser_e_wrong_parameter_size=03026_E_Numero de parámetros incorrecto
+% There is an error in the parameter list of the function or procedure,
+% the number of parameters is not correct.
+parser_e_overloaded_no_procedure=03027_E_el identificador sobrecargado "$1" no es una función
+% The compiler encountered a symbol with the same name as an overloaded
+% function, but it is not a function it can overload.
+parser_e_overloaded_have_same_parameters=03028_E_funciones sobrecargadas tienen los mismos par metros
+% You're declaring overloaded functions, but with the same parameter list.
+% Overloaded function must have at least 1 different parameter in their
+% declaration.
+parser_e_header_dont_match_forward=03029_E_la cabecera de la función no concuerda con la declaración posterior "$1"
+% You declared a function with same parameters but
+% different result type or function modifiers.
+parser_e_header_different_var_names=03030_E_la cabecera de la funcion "$1" no concuerda con la posterior declaración : el nombre de la variable cambia $2 => $3
+% You declared the function in the \var{interface} part, or with the
+% \var{forward} directive, but define it with a different parameter list.
+parser_n_duplicate_enum=03031_N_el orden de los valores en una enumeracion debe ser ascendente
+% \fpc allows enumeration constructions as in C. Given the following
+% declaration two declarations:
+% \begin{verbatim}
+% type a = (A_A,A_B,A_E:=6,A_UAS:=200);
+% type a = (A_A,A_B,A_E:=6,A_UAS:=4);
+% \end{verbatim}
+% The second declaration would produce an error. \var{A\_UAS} needs to have a
+% value higher than \var{A\_E}, i.e. at least 7.
+parser_e_no_with_for_variable_in_other_segments=03033_E_With no puede ser usado con variables en segmentos diferentes
+% With stores a variable locally on the stack,
+% but this is not possible if the variable belongs to another segment.
+parser_e_too_much_lexlevel=03034_E_Anidado de funciones > 31
+% You can nest function definitions only 31 times.
+parser_e_range_check_error=03035_E_error en la comprobación de rangos mientras se evaluaban constantes
+% The constants are out of their allowed range.
+parser_w_range_check_error=03036_W_error en la comprobacion de rangos mientras se evaluaban constantes
+% The constants are out of their allowed range.
+parser_e_double_caselabel=03037_E_etiqueta de caso duplicada
+% You are specifying the same label 2 times in a \var{case} statement.
+parser_e_case_lower_less_than_upper_bound=03038_E_El líimite superior del caso es menor que el inferior
+% The upper bound of a \var{case} label is less than the lower bound and this
+% is useless
+parser_e_type_const_not_possible=03039_E_no se permiten constantes con tipo de clases
+% You cannot declare a constant of type class or object.
+parser_e_no_overloaded_procvars=03040_E_no se permite asignar a variables de funcion funciones sobrecargadas
+% You are trying to assign an overloaded function to a procedural variable.
+% This is not allowed
+parser_e_invalid_string_size=03041_E_la longitud de una cadena tiene que ser un valor entre 1 y 255
+% The length of a shortstring in Pascal is limited to 255 characters. You are
+% trying to declare a string with length lower than 1 or greater than 255
+parser_w_use_extended_syntax_for_objects=03042_W_use la sintaxis estendida de DISPOSE y NEW para instancias de objetos
+% If you have a pointer \var{a} to a class type, then the statement
+% \var{new(a)} will not initialize the class (i.e. the constructor isn't
+% called), although space will be allocated. you should issue the
+% \var{new(a,init)} statement. This will allocate space, and call the
+% constructor of the object
+parser_w_no_new_dispose_on_void_pointers=03043_W_el uso de NEW o DISPOSE para punteros sin tipo no tiene sentido
+parser_e_no_new_dispose_on_void_pointers=03044_E_el uso de NEW o DISPOSE no es posible con punteros sin tipo
+% You cannot use \var{new(p)} or \var{dispose(p)} if \var{p} is an untyped pointer
+% because no size is associated to an untyped pointer.
+% Accepted for compatibility in \var{tp} and \var{delphi} modes.
+parser_e_class_id_expected=03045_E_identificador de clase esperado
+% This happens when the compiler scans a procedure declaration that contains
+% a dot,
+% i.e., a object or class method, but the type in front of the dot is not
+% a known type.
+parser_e_no_type_not_allowed_here=03046_E_identificador de tipo no permitido aquí
+% You cannot use a type inside an expression.
+parser_e_methode_id_expected=03047_E_identificador de método esperado
+% This identifier is not a method.
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., a object or class method, but the procedure name is not a
+% procedure of this type.
+parser_e_header_dont_match_any_member=03048_E_la cabecera de la funcion no concuerda con ningún método de esta clase "$1"
+% This identifier is not a method.
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., a object or class method, but the procedure name is not a
+% procedure of this type.
+parser_d_procedure_start=03049_DL_proceduimiento/función $1
+% When using the \var{-vd} switch, the compiler tells you when it starts
+% processing a procedure or function implementation.
+parser_e_error_in_real=03050_E_Constante de punto flotante inválida
+% The compiler expects a floating point expression, and gets something else.
+parser_e_fail_only_in_constructor=03051_E_FAIL solo puede ser usado en constructores
+% You are using the \var{fail} keyword outside a constructor method.
+parser_e_no_paras_for_destructor=03052_E_Los destructores no pueden tener parámetros
+% You are declaring a destructor with a parameter list. Destructor methods
+% cannot have parameters.
+parser_e_only_class_methods_via_class_ref=03053_E_Solo los métodos de clases pueden ser referidos con referencias de clase
+% This error occurs in a situation like the following:
+% \begin{verbatim}
+% Type :
+% Tclass = Class of Tobject;
+%
+% Var C : TClass;
+%
+% begin
+% ...
+% C.free
+% \end{verbatim}
+% \var{Free} is not a class method and hence cannot be called with a class
+% reference.
+parser_e_only_class_methods=03054_E_Los métodos de clase solo pueden ser acceder a otros métodos de clase
+% This is related to the previous error. You cannot call a method of an object
+% from a inside a class method. The following code would produce this error:
+% \begin{verbatim}
+% class procedure tobject.x;
+%
+% begin
+% free
+% \end{verbatim}
+% Because free is a normal method of a class it cannot be called from a class
+% method.
+parser_e_case_mismatch=03055_E_Los tipos de la constante y del CASE no concuerdan
+% One of the labels is not of the same type as the case variable.
+parser_e_illegal_symbol_exported=03056_E_El símbolo no puede ser exportado de una librería
+% You can only export procedures and functions when you write a library. You
+% cannot export variables or constants.
+parser_w_should_use_override=03057_W_Un método heredado ha sido ocultado por "$1"
+% A method that is declared \var{virtual} in a parent class, should be
+% overridden in the descendent class with the \var{override} directive. If you
+% don't specify the \var{override} directive, you will hide the parent method;
+% you will not override it.
+parser_e_nothing_to_be_overridden=03058_E_No hay un método en una clase antepasada para ser substituido: "$1"
+% You are trying to \var{override} a virtual method of a parent class that does
+% not exist.
+parser_e_no_procedure_to_access_property=03059_E_No se suministro un miembro para acceder a propiedad
+% You specified no \var{read} directive for a property.
+parser_w_stored_not_implemented=03060_W_La directiva de propiedad Stored no esta implementada aún
+% The \var{stored} directive is not yet implemented
+parser_e_ill_property_access_sym=03061_E_símbolo inváalido para el acceso a la propiedad
+% There is an error in the \var{read} or \var{write} directives for an array
+% property. When you declare an array property, you can only access it with
+% procedures and functions. The following code woud cause such an error.
+% \begin{verbatim}
+% tmyobject = class
+% i : integer;
+% property x [i : integer]: integer read I write i;
+% \end{verbatim}
+%
+parser_e_cant_access_protected_member=03062_E_No se puede acceder a un campo protegido de un objeto aquí
+% Fields that are declared in a \var{protected} section of an object or class
+% declaration cannot be accessed outside the module wher the object is
+% defined, or outside descendent object methods.
+parser_e_cant_access_private_member=03063_E_No se puede acceder a un campo privado de un objeto aquí
+% Fields that are declared in a \var{private} section of an object or class
+% declaration cannot be accessed outside the module where the class is
+% defined.
+parser_e_overridden_methods_not_same_ret=03066_E_los métodos reemplazados deben tener el mismo tipo de dato devuelto: "$2" es reemplazado por "$1" que devuelve otro tipo
+% If you declare overridden methods in a class definition, they must
+% have the same return type.
+parser_e_dont_nest_export=03067_E_Las funciones declarados como EXPORT no pueden estar anidados
+% You cannot declare a function or procedure within a function or procedure
+% that was declared as an export procedure.
+parser_e_methods_dont_be_export=03068_E_los métodos no pueden ser EXPORTados
+% You cannot declare a procedure that is a method for an object as
+% \var{export}ed.
+parser_e_call_by_ref_without_typeconv=03069_E_en llamadas con parámetros VAR los tipos deben coincidir exactamente. Se recibio "$1" cuando se esperaba "$2"
+% When calling a function declared with \var{var} parameters, the variables in
+% the function call must be of exactly the same type. There is no automatic
+% type conversion.
+parser_e_no_super_class=03070_E_La clase no es un ancestor de la clase actual
+% When calling inherited methods, you are trying to call a method of a non-related
+% class. You can only call an inherited method of a parent class.
+parser_e_self_not_in_method=03071_E_SELF solo está permitido en métodos
+% You are trying to use the \var{self} parameter outside an object's method.
+% Only methods get passed the \var{self} parameters.
+parser_e_generic_methods_only_in_methods=03072_E_los métodos solo pueden estar en otros métodos llamados directamente con el tipo identificador de la clase
+% A construction like \var{sometype.somemethod} is only allowed in a method.
+parser_e_illegal_colon_qualifier=03073_E_Uso inválido de ':'
+% You are using the format \var{:} (colon) 2 times on an expression that
+% is not a real expression.
+parser_e_illegal_set_expr=03074_E_Error en la comprobación de rangos en el constructor del set, o elemento duplicado en el set
+% The declaration of a set contains an error. Either one of the elements is
+% outside the range of the set type, either two of the elements are in fact
+% the same.
+parser_e_pointer_to_class_expected=03075_E_Se esperaba un puntero a objeto
+% You specified an illegal type in a \var{new} statement.
+% The extended syntax of \var{new} needs an object as a parameter.
+parser_e_expr_have_to_be_constructor_call=03076_E_La expresión tiene que ser una llamada al constructor
+% When using the extended syntax of \var{new}, you must specify the constructor
+% method of the object you are trying to create. The procedure you specified
+% is not a constructor.
+parser_e_expr_have_to_be_destructor_call=03077_E_La expresión tiene que ser una llamada al destructor
+% When using the extended syntax of \var{dispose}, you must specify the
+% destructor method of the object you are trying to dispose of.
+% The procedure you specified is not a destructor.
+parser_e_invalid_record_const=03078_E_Orden de los campos del registro incorrecto
+% When declaring a constant record, you specified the fields in the wrong
+% order.
+parser_e_false_with_expr=03079_E_El tipo de la expresión tiene que ser class o record
+% A \var{with} statement needs an argument that is of the type \var{record}
+% or \var{class}. You are using \var{with} on an expression that is not of
+% this type.
+parser_e_void_function=03080_E_Los procedimientos no pueden devolver ningún valor
+% In \fpc, you can specify a return value for a function when using
+% the \var{exit} statement. This error occurs when you try to do this with a
+% procedure. Procedures cannot return a value.
+parser_e_only_methods_allowed=03081_E_constructores, destructors y class operators deben ser métodos
+% You're declaring a procedure as destructor, constructor or class operator, when the
+% procedure isn't a class method.
+parser_e_operator_not_overloaded=03082_E_El operador no esta sobrecargado
+% You're trying to use an overloaded operator when it is not overloaded for
+% this type.
+parser_e_no_such_assignment=03083_E_Imposible sobrecargar operador de asignacion para tipos iguales
+% You can not overload assignment for types
+% that the compiler considers as equal.
+parser_e_overload_impossible=03084_E_Sobrecarga de operador imposible
+% The combination of operator, arguments and return type are
+% incompatible.
+parser_e_no_reraise_possible=03085_E_Re-lanzamiento de la excepcion no es posible aquí
+% You are trying to raise an exception where it is not allowed. You can only
+% raise exceptions in an \var{except} block.
+parser_e_no_new_or_dispose_for_classes=03086_E_La sintaxis extendida de new o dispose no está permitida para una clase
+% You cannot generate an instance of a class with the extended syntax of
+% \var{new}. The constructor must be used for that. For the same reason, you
+% cannot call \var{dispose} to de-allocate an instance of a class, the
+% destructor must be used for that.
+parser_e_procedure_overloading_is_off=03088_E_La sobrecarga de funciones no esta activada
+% When using the \var{-So} switch, procedure overloading is switched off.
+% Turbo Pascal does not support function overloading.
+parser_e_overload_operator_failed=03089_E_No es posible sobrecargar este operador (sobrecarge en cambio "=" )
+% You are trying to overload an operator which cannot be overloaded.
+% The following operators can be overloaded :
+% \begin{verbatim}
+% +, -, *, /, =, >, <, <=, >=, is, as, in, **, :=
+% \end{verbatim}
+parser_e_comparative_operator_return_boolean=03090_E_Operador comparativo tiene que devolver un valor booleano
+% When overloading the \var{=} operator, the function must return a boolean
+% value.
+parser_e_only_virtual_methods_abstract=03091_E_Solo los métodos virtuales pueden ser abstractos
+% You are declaring a method as abstract, when it is not declared to be
+% virtual.
+parser_f_unsupported_feature=03092_F_Uso de característica no soportada!
+% You're trying to force the compiler into doing something it cannot do yet.
+parser_e_mix_of_classes_and_objects=03093_E_No se permite la mezcla de objetos de diferentes tipos (class, object, interface, etc)
+% You cannot derive \var{objects}, \var{classes}, \var{cppclasses} and \var{interfaces} interttwined . E.g.
+% a class cannot have an object as parent and vice versa.
+parser_w_unknown_proc_directive_ignored=03094_W_Directiva de procedimiento desconocida fue ignorada: "$1"
+% The procedure directive you specified is unknown.
+parser_e_absolute_only_one_var=03095_E_absolute solo puede estar asociado a una variable
+% You cannot specify more than one variable before the \var{absolute} directive.
+% Thus, the following construct will provide this error:
+% \begin{verbatim}
+% Var Z : Longint;
+% X,Y : Longint absolute Z;
+% \end{verbatim}
+% \item [ absolute can only be associated a var or const ]
+% The address of a \var{absolute} directive can only point to a variable or a
+% typed constant. Therefore, the following code will produce this error:
+% \begin{verbatim}
+% Procedure X;
+%
+% var p : longint absolute x;
+% \end{verbatim}
+%
+parser_e_absolute_only_to_var_or_const=03096_E_absolute solo puede ser asociado con var o const
+% The address of a \var{absolute} directive can only point to a variable or
+% constant. Therefore, the following code will produce this error:
+% \begin{verbatim}
+% Procedure X;
+%
+% var p : longint absolute x;
+% \end{verbatim}
+%
+parser_e_initialized_only_one_var=03097_E_Solo una variable puede ser inicializada
+% You cannot specify more than one variable with a initial value
+% in Delphi mode.
+parser_e_abstract_no_definition=03098_E_Métodos abstractos no deberían tener ninguna definición (con el cuerpo de la función)
+% Abstract methods can only be declared, you cannot implement them. They
+% should be overridden by a descendant class.
+parser_e_overloaded_must_be_all_global=03099_E_Esta función sobrecargada no puede ser local (debe ser exportada)
+% You are defining a overloaded function in the implementation part of a unit,
+% but there is no corresponding declaration in the interface part of the unit.
+parser_w_virtual_without_constructor=03100_W_Métodos virtuales están siendo usados sin un constructor en "$1"
+% If you declare objects or classes that contain virtual methods, you need
+% to have a constructor and destructor to initialize them. The compiler
+% encountered an object or class with virtual methods that doesn't have
+% a constructor/destructor pair.
+parser_c_macro_defined=03101_CL_Macro definido: $1
+% When \var{-vc} is used, the compiler tells you when it defines macros.
+parser_c_macro_undefined=03102_CL_Macro indefinido: $1
+% When \var{-vc} is used, the compiler tells you when it undefines macros.
+parser_c_macro_set_to=03103_CL_Macro $1 asignado a $2
+% When \var{-vc} is used, the compiler tells you what values macros get.
+parser_i_compiling=03104_I_Compilando $1
+% When you turn on information messages (\var{-vi}), the compiler tells you
+% what units it is recompiling.
+parser_u_parsing_interface=03105_UL_Interpretando interfaz de la unidad $1
+% This tells you that the reading of the interface
+% of the current unit starts
+parser_u_parsing_implementation=03106_UL_Interpretando implementacion de la unidad $1
+% This tells you that the code reading of the implementation
+% of the current unit, library or program starts
+parser_d_compiling_second_time=03107_DL_Compilando $1 por segunda vez
+% When you request debug messages (\var{-vd}) the compiler tells you what
+% units it recompiles for the second time.
+parser_e_no_property_found_to_override=03109_E_No se encontro la propiedad a reemplazar
+% You want to overrride a property of a parent class, when there is, in fact,
+% no such property in the parent class.
+parser_e_only_one_default_property=03110_E_Sólo se permite una única propiedad por defecto
+% You specified a property as \var{Default}, but the class already has a
+% default property, and a class can have only one default property.
+parser_e_property_need_paras=03111_E_La propiedad por defecto tiene que ser un array
+% Only array properties of classes can be made \var{default} properties.
+parser_e_constructor_cannot_be_not_virtual=03112_E_Solo las clases soportan constructores virtuales
+% You cannot have virtual constructors in objects. You can only have them
+% in classes.
+parser_e_no_default_property_available=03113_E_No hay propiedad por defecto disponible
+% You are trying to access a default property of a class, but this class (or one of
+% its ancestors) doesn't have a default property.
+parser_e_cant_have_published=03114_E_La clase no puede tener una sección published, use el conmutador {$M+}
+% If you want a \var{published} section in a class definition, you must
+% use the \var{\{\$M+\}} switch, whch turns on generation of type
+% information.
+parser_e_forward_declaration_must_be_resolved=03115_E_Declaración posterior de la clase "$1" tiene que ser resuelta aquí para usar la clase como antepasado
+% To be able to use an object as an ancestor object, it must be defined
+% first. This error occurs in the following situation:
+% \begin{verbatim}
+% Type ParentClas = Class;
+% ChildClass = Class(ParentClass)
+% ...
+% end;
+% \end{verbatim}
+% Where \var{ParentClass} is declared but not defined.
+parser_e_no_local_operator=03116_E_Operadores locales no soportados
+% You cannot overload locally, i.e. inside procedures or function
+% definitions.
+parser_e_proc_dir_not_allowed_in_interface=03117_E_Directiva de procedimiento "$1" no permitida en la sección de interfaz
+% This procedure directive is not allowed in the \var{interface} section of
+% a unit. You can only use it in the \var{implementation} section.
+parser_e_proc_dir_not_allowed_in_implementation=03118_E_Directiva de procedimiento "$1" no permitida en la sección de implementacion
+% This procedure directive is not defined in the \var{implementation} section of
+% a unit. You can only use it in the \var{interface} section.
+parser_e_proc_dir_not_allowed_in_procvar=03119_E_Directiva de procedimiento "$1" no permitida en la declaración de tipo
+% This procedure directive cannot be part of a procedural or function
+% type declaration.
+parser_e_function_already_declared_public_forward=03120_E_La función esta actualmente declarada como Public/Forward "$1"
+% You will get this error if a function is defined as \var{forward} twice.
+% Or it is once in the \var{interface} section, and once as a \var{forward}
+% declaration in the \var{implmentation} section.
+parser_e_not_external_and_export=03121_E_No se pueden usar ambos EXPORT y EXTERNAL
+% These two procedure directives are mutually exclusive
+parser_w_not_supported_for_inline=03123_W_"$1" aún no soportado en procedimientos/funciones inline
+% Inline procedures don't support this declaration.
+parser_w_inlining_disabled=03124_W_Inlining deshabilitado
+% Inlining of procedures is disabled.
+parser_i_writing_browser_log=03125_I_Escribiendo Browser log $1
+% When information messages are on, the compiler warns you when it
+% writes the browser log (generated with the \var{\{\$Y+ \}} switch).
+parser_h_maybe_deref_caret_missing=03126_H_podría ser que falte la de-referencia del puntero
+% The compiler thinks that a pointer may need a dereference.
+parser_f_assembler_reader_not_supported=03127_F_Lector del ensamblador seleccionado no soportado
+% The selected assembler reader (with \var{\{\$ASMMODE xxx\}} is not
+% supported. The compiler can be compiled with or without support for a
+% particular assembler reader.
+parser_e_proc_dir_conflict=03128_E_Directiva de procedimiento "$1" causa conflicto con otras directivas
+% You specified a procedure directive that conflicts with other directives.
+% for instance \var{cdecl} and \var{pascal} are mutually exclusive.
+parser_e_call_convention_dont_match_forward=03129_E_La convencion de llamada actual no concuerda con la definida anteriormente
+% This error happens when you declare a function or procedure with
+% e.g. \var{cdecl;} but omit this directive in the implementation, or vice
+% versa. The calling convention is part of the function declaration, and
+% must be repeated in the function definition.
+parser_e_property_cant_have_a_default_value=03131_E_La propiedad no puede tener un valor por defecto
+% Set properties or indexed properties cannot have a default value.
+parser_e_property_default_value_must_const=03132_E_El valor por defecto de una propiedad tiene que ser constante
+% The value of a \var{default} declared property must be known at compile
+% time. The value you specified is only known at run time. This happens
+% .e.g. if you specify a variable name as a default value.
+parser_e_cant_publish_that=03133_E_El símbolo no puede ser published, solo puede ser una clase
+% Only class type variables can be in a \var{published} section of a class
+% if they are not declared as a property.
+parser_e_cant_publish_that_property=03134_E_Este tipo de propiedad no puede ser published
+% Properties in a \var{published} section cannot be array properties.
+% they must be moved to public sections. Properties in a \var{published}
+% section must be an ordinal type, a real type, strings or sets.
+parser_e_empty_import_name=03136_E_Se requiere un nombre de importación
+% Some targets need a name for the imported procedure or a \var{cdecl} specifier
+parser_e_division_by_zero=03138_E_Division por cero
+% There is a divsion by zero encounted
+parser_e_invalid_float_operation=03139_E_Operacion de punto flotante no válida
+% An operation on two real type values produced an overflow or a division
+% by zero.
+parser_e_array_lower_less_than_upper_bound=03140_E_Límite superior del rango es menor que el límite inferior
+% The upper bound of a an array declaration is less than the lower bound and this
+% is not possible
+parser_w_string_too_long=03141_W_La cadena "$1" es mas larga que $2
+% The size of the constant string is larger than the size you specified in
+% string type definition
+parser_e_string_larger_array=03142_E_La longitud de la cadena es mayor que el tamaño array de carácteres
+% The size of the constant string is larger than the size you specified in
+% the array[x..y] of char definition
+parser_e_ill_msg_expr=03143_E_Expresión inválida tras la directiva de mensaje
+% \fpc supports only integer or string values as message constants
+parser_e_ill_msg_param=03144_E_Los méetodos de manejo de mensajes deben tener un único parámetro por referencia
+% A method declared with the \var{message}-directive as message handler
+% can take only one parameter which must be declared as call by reference
+% Parameters are declared as call by reference using the \var{var}-directive
+parser_e_duplicate_message_label=03145_E_Etiqueta de mensaje duplicada: "$1"
+% A label for a message is used twice in one object/class
+parser_e_self_in_non_message_handler=03146_E_Self solo puede ser un parámetro explícito en manejadores de mensajes
+% The self parameter can only be passed explicitly to a method which
+% is declared as message handler.
+parser_e_threadvars_only_sg=03147_E_Threadvars sólo pueden ser globales o estáticos
+% Threadvars must be static or global, you can't declare a thread
+% local to a procedure. Local variables are always local to a thread,
+% because every thread has its own stack and local variables
+% are stored on the stack
+parser_f_direct_assembler_not_allowed=03148_F_Ensamblador directo no soportado para formato binario de salida
+% You can't use direct assembler when using a binary writer, choose an
+% other outputformat or use another assembler reader
+parser_w_no_objpas_use_mode=03149_W_No carges manuamente la unidad OBJPAS, usa \{\$mode objfpc\} o \{\$mode delphi\}
+% You are trying to load the ObjPas unit manually from a uses clause. This is
+% not a good idea. Use the \var{\{\$mode objfpc\}} or
+% \var{\{\$mode delphi\}}
+% directives which load the unit automatically
+parser_e_no_object_override=03150_E_OVERRIDE no puede ser usado en objetos
+% Override is not supported for objects, use \var{virtual} instead to override
+% a method of a parent object
+parser_e_cant_use_inittable_here=03151_E_Tipos de datos que requieran inicializacion/finalizacion no pueden ser usados en registros variables
+% Some data type (e.g. \var{ansistring}) needs initialization/finalization
+% code which is implicitly generated by the compiler. Such data types
+% can't be used in the variant part of a record.
+parser_e_resourcestring_only_sg=03152_E_Resourcestrings solo pueden ser globales o estáaticos
+% Resourcestring can not be declared local, only global or using the static
+% directive.
+parser_e_exit_with_argument_not__possible=03153_E_Exit con parámetro no puede ser usado aquí
+% an exit statement with an argument for the return value can't be used here, this
+% can happen e.g. in \var{try..except} or \var{try..finally} blocks
+parser_e_stored_property_must_be_boolean=03154_E_El tipo del símbolo en stored debe ser de tipo booleano
+% If you specify a storage symbol in a property declaration, it must be of
+% the type boolean
+parser_e_ill_property_storage_sym=03155_E_Este símbolo no puede ser usado en storage para una propiedad
+% You can't use this type of symbol as storage specifier in property
+% declaration. You can use only methods with the result type boolean,
+% boolean class fields or boolean constants
+parser_e_only_publishable_classes_can__be_published=03156_E_Solo clases compiladas en $M+ pueden ser publicadas
+% In the published section of a class can be only class as fields used which
+% are compiled in \var{\{\$M+\}} or which are derived from such a class. Normally
+% such a class should be derived from TPersitent
+parser_e_proc_directive_expected=03157_E_Directiva de procedimiento esperada
+% When declaring a procedure in a const block you used a ; after the
+% procedure declaration after which a procedure directive must follow.
+% Correct declarations are:
+% \begin{verbatim}
+% const
+% p : procedure;stdcall=nil;
+% p : procedure stdcall=nil;
+% \end{verbatim}
+parser_e_invalid_property_index_value=03158_E_El valor para el índice de una propiedad debe ser de tipo ordinal
+% The value you use to index a property must be of an ordinal type, for
+% example an integer or enumerated type.
+parser_e_procname_to_short_for_export=03159_E_Nombre del procedimiento demasiado corto para ser exportado
+% The length of the procedure/function name must be at least 2 characters
+% long. This is because of a bug in dlltool which doesn't parse the .def
+% file correct with a name of length 1.
+parser_e_dlltool_unit_var_problem=03160_E_No se puede generar una entrada DEFFILE para las variables globales de la unidad
+parser_e_dlltool_unit_var_problem2=03161_E_Compile sin la opcion -WD
+% You need to compile this file without the -WD switch on the
+% commandline
+parser_f_need_objfpc_or_delphi_mode=03162_F_Se requiere el modo ObjFpc (-S2) o Delphi (-Sd) para compilar este módulo
+% You need to use \{\$mode objfpc\} or \{\$mode delphi\} to compile this file.
+% Or use the equivalent commandline switches -S2 or -Sd.
+parser_e_no_export_with_index_for_target=03163_E_No se pueden exportar funciones o procedimientos por indice en $1
+% Exporting of functions or procedures with a specified index is not
+% supported on this target.
+parser_e_no_export_of_variables_for_target=03164_E_Exportar variables no esta soportado en $1
+% Exporting of variables is not supported on this target.
+parser_e_improper_guid_syntax=03165_E_Sintaxis de GUID incorrecta
+parser_w_interface_mapping_notfound=03168_W_No se encontro el procedimiento de nombre "$1" apropiado para implementar $2.$3
+parser_e_interface_id_expected=03169_E_identificador de interfaz esperado
+% This happens when the compiler scans a \var{class} declaration that contains
+% \var{interface} function name mapping code like this:
+% \begin{verbatim}
+% type
+% TMyObject = class(TObject, IDispatch)
+% function IUnknown.QueryInterface=MyQueryInterface;
+% ....
+% \end{verbatim}
+% and the \var{interface} before the dot not listed in the inheritance list.
+parser_e_type_cant_be_used_in_array_index=03170_E_El tipo "$1" no puede ser usado como indice en arrays
+% Types like \var{qword} or \var{int64} aren't allowed as array index type
+parser_e_no_con_des_in_interfaces=03171_E_No se permiten constructores/destructores en interfaces
+% Constructor and destructor declarations aren't allowed in interface
+% In the most cases the method \var{QueryInterface} of \var{IUnknown} can
+% be used to create a new interface.
+parser_e_no_access_specifier_in_interfaces=03172_E_No se permiten especificadores de acceso en interfaces
+% The access specifiers \var{public}, \var{private}, \var{protected} and
+% \var{pusblished} can't be used in interfaces because all methods
+% of an interfaces must be public.
+parser_e_no_vars_in_interfaces=03173_E_Una interfaz no puede contener campos
+% Declarations of fields aren't allowed in interfaces. An interface
+% can contain only methods
+parser_e_no_local_proc_external=03174_E_No se puede declarar un procedimiento local como externo
+% Declaring local procedures as external is not possible. Local procedures
+% get hidden parameters that will make the chance of errors very high
+parser_w_skipped_fields_before=03175_W_Algunos campos anteriores a "$1" no fueron inicializados
+% In Delphi mode, not all fields of a typed constant record have to be
+% initialized, but the compiler warns you when it detects such situations.
+parser_e_skipped_fields_before=03176_E_Algunos campos anteriores a "$1" no fueron inicializados
+% In all syntax modes but Delphi mode, you can't leave some fields uninitialized
+% in the middle of a typed constant record
+parser_w_skipped_fields_after=03177_W_Algunos campos tras "$1" no fueron inicializados
+% You can leave some fields at the end of a type constant record uninitialized
+% (the compiler will initialize them to zero automatically). This may be the cause
+% of subtle problems.
+parser_e_varargs_need_cdecl_and_external=03178_E_Directiva VarArgs sólo es válida con CDecl o External
+% The varargs directive can only be used with procedures or functions
+% that are declared with \var{cdecl} and \var{external} directives. The varargs directive
+% is only meant to provide a compatible interface to C functions like printf.
+parser_e_self_call_by_value=03179_E_Self debe ser un parámetro normal por valor
+% You can't declare self as a const or var parameter, it must always be
+% a call-by-value parameter
+parser_e_interface_has_no_guid=03180_E_La interfaz "$1" no tiene identificacion
+% When you want to assign an interface to a constant, then the interface
+% must have a GUID value set.
+parser_e_illegal_field_or_method=03181_E_Campo de la clase o método desconocido "$1"
+% Properties must refer to a field or method in the same class.
+parser_w_proc_overriding_calling=03182_W_Varias convenciones de llamada especificadas, "$1" ignorado al especificar "$2"
+% There are two directives in the procedure declaration that specify a calling
+% convention. Only the last directive will be used
+parser_e_no_procvarobj_const=03183_E_constantes con tipo de tipo Procedure/Function (...) of Object solo pueden ser inicializados a NIL
+% You can't assign the address of a method to a typed constant which has a
+% 'procedure of object' type, because such a constant requires two addresses:
+% that of the method (which is known at compile time) and that of the object or
+% class instance it operates on (which can not be known at compile time).
+parser_e_default_value_only_one_para=03184_E_Sólo se puede asignar valor por defecto a un parámetro
+parser_e_default_value_expected_for_para=03185_E_Parámetro por defecto requerido para "$1"
+parser_w_unsupported_feature=03186_W_¡Uso de una caracteristica no soportada!
+% You're trying to force the compiler into doing something it cannot do yet.
+parser_h_c_arrays_are_references=03187_H_Arrays tipo C son pasados por referencia
+% Any array passed to a C functions is passed
+% by a pointer (i.e. by reference).
+parser_e_C_array_of_const_must_be_last=03188_E_Array tipo C de const debe ser el ultimo parámetro
+% You can not add any other argument after an \var{array of const} for
+% \var{cdecl} functions, as the size pushed on stack for this argument is
+% not known.
+parser_h_type_redef=03189_H_Redefinición del tipo "$1"
+% This is an indicator that a previously declared type is
+% being redefined as something else. This may, or may not
+% be, a cause for errors.
+parser_w_cdecl_has_no_high=03190_W_Procedimientos y funciones declarados como cdecl no reciben de parámetro el límite superior
+% Functions declared with cdecl modifier do not pass an extra implicit parameter.
+parser_w_cdecl_no_openstring=03191_W_open strings no son soportados en funciones cdecl
+% Openstring is not supported for cdecl'ared functions.
+parser_e_initialized_not_for_threadvar=03192_E_No se pueden inicializar variables declaradas como threadvar
+% Variables declared as threadvar can not be initialized with a default value.
+% The variables will always be filled with zero at the start of a new thread.
+parser_e_msg_only_for_classes=03193_E_La directiva Message sólo es valida en clases
+% The message directive is only supported for Class types.
+parser_e_procedure_or_function_expected=03194_E_Se esperaba un procedimiento o funcion
+% A class method can only be specified for procedures and functions.
+parser_e_illegal_calling_convention=03195_W_Directiva de convención de llama "$1" ignorada
+% Some calling conventions are supported only by certain CPUs. I.e. most non-i386 ports support
+% only the standard ABI calling convention of the CPU.
+parser_e_no_object_reintroduce=03196_E_REINTRODUCE no puede ser utilizado en objetos
+% \var{reintroduce} is not supported for objects.
+parser_e_paraloc_only_one_para=03197_E_Cada parámetro debe tener su propia posición
+% If locations for arguments are specified explicitly as it is required by
+% some syscall conventions, each argument must have it's only location, things
+% like \var{procedure p(i,j : longint 'r1');} aren't allowed
+parser_e_paraloc_all_paras=03198_E_Cada parámetro debe tener su propia posición
+% If one argument has an explicit argument location, all arguments of a procedure
+% must have one.
+parser_e_illegal_explicit_paraloc=03199_E_Localizacón en el segmento desconocida
+% The location specified for an argument isn't recognized by the compiler
+parser_e_32bitint_or_pointer_variable_expected=03200_E_Se esperaba una variable entera de 32 bits o un puntero
+% The libbase for MorphOS/AmigaOS can be give only as \var{longint}, \var{dword} or any pointer variable.
+parser_e_goto_outside_proc=03201_E_No se puede usar Goto para saltar a otro procedimiento
+% It isn't allowed to use the \var{goto} statements referencing labels outside the
+% current procedure. The following example shows the problem:
+% \begin{verbatim}
+% ...
+% procedure p1;
+% label
+% l1;
+%
+% procedure p2;
+% begin
+% goto l1; // This goto ISN'T allowed
+% end;
+%
+% begin
+% p2
+% l1:
+% end;
+% ...
+%
+% \end{verbatim}
+parser_f_too_complex_proc=03202_F_Procedimiento demasiado complejo. Se requieren demasiados registros
+% Your procedure body is too long for the compiler. You should split the
+% procedure into multiple smaller procedures.
+parser_e_illegal_expression=03203_E_Expresión inválida
+% This can occur under many circumstances. Mostly when trying to evaluate
+% constant expressions.
+parser_e_invalid_integer=03204_E_La expresión no evalua un número entero
+% You made an expression which isn't an integer, and the compiler expects the
+% result to be an integer.
+parser_e_invalid_qualifier=03205_E_calificador inválido
+% One of the following is happening :
+% \begin{itemize}
+% \item You're trying to access a field of a variable that is not a record.
+% \item You're indexing a variable that is not an array.
+% \item You're dereferencing a variable that is not a pointer.
+% \end{itemize}
+parser_e_upper_lower_than_lower=03206_E_El limite superior especificado es menor que el inferior
+% You are declaring a subrange, and the lower limit is higher than the high
+% limit of the range.
+parser_e_macpas_exit_wrong_param=03207_E_El parámetro de Exit debe ser el nombre del mismo procedimiento en el que está
+% Non local exit is not allowed. This error occurs only in mode MacPas.
+parser_e_illegal_assignment_to_count_var=03208_E_Asignación inválida a la variable de bucle "$1"
+% The type of a \var{for} loop variable must be an ordinal type.
+% Loop variables cannot be reals or strings.
+parser_e_no_local_var_external=03209_E_No se puede declarar una variable local como externa
+% Declaring local variables as external is not allowed. Only global variables can reference
+% to external variables.
+parser_e_proc_already_external=03210_E_El procedimiento ya ha sido declarado como externo con anterioridad
+% The procedure is already declared with the EXTERNAL directive in an interface or
+% forward declaration.
+parser_w_implicit_uses_of_variants_unit=03211_W_Uso implícito de la unidad Variants
+% The Variant type is used in the unit without any used unit using the Variants unit. The
+% compiler has implicitly added the Variants unit to the uses list. To remove this warning
+% the Variants unit needs to be added to the uses statement.
+parser_e_no_static_method_in_interfaces=03212_E_Clases y métodos estáticos no pueden ser utilizados en interfaces
+% The specifier \var{class} and directive \var{static} can't be used in interfaces
+% because all methods of an interfaces must be public.
+parser_e_arithmetic_operation_overflow=03213_E_Desbordamiento en la operación aritmética
+% An operation on two integers values produced an overflow
+% \end{description}
+#
+# Type Checking
+#
+# 04049 is the last used one
+#
+% \section{Type checking errors}
+% This section lists all errors that can occur when type checking is
+% performed.
+% \begin{description}
+type_e_mismatch=04000_E_Los tipos no concuerdan
+% This can happen in many cases:
+% \begin{itemize}
+% \item The variable you're assigning to is of a different type than the
+% expression in the assignment.
+% \item You are calling a function or procedure with parameters that are
+% incompatible with the parameters in the function or procedure definition.
+% \end{itemize}
+type_e_incompatible_types=04001_E_Tipos incompatibles: se encontró "$1" esperado "$2"
+% There is no conversion possible between the two types
+% Another possiblity is that they are declared in different
+% declarations:
+% \begin{verbatim}
+% Var
+% A1 : Array[1..10] Of Integer;
+% A2 : Array[1..10] Of Integer;
+%
+% Begin
+% A1:=A2; { This statement gives also this error, it
+% is due the strict type checking of pascal }
+% End.
+% \end{verbatim}
+type_e_not_equal_types=04002_E_Los tipos $1 y $2 no concuerdan
+% The types are not equal
+type_e_type_id_expected=04003_E_Identificador de tipo esperado
+% The identifier is not a type, or you forgot to supply a type identifier.
+type_e_variable_id_expected=04004_E_Identificador de variable esperado
+% This happens when you pass a constant to a routine (such as \var{Inc} var or \var{Dec})
+% when it expects a variable. You can only pass variables as arguments to these functions.
+type_e_integer_expr_expected=04005_E_expression entera esperada, pero se encontró "$1"
+% The compiler expects an expression of type integer, but gets a different
+% type.
+type_e_boolean_expr_expected=04006_E_Expresion booleana esperada, pero se encontró "$1"
+% The expression must be a boolean type, it should be return true or
+% false.
+type_e_ordinal_expr_expected=04007_E_Espresión ordinal esperada
+% The expression must be of ordinal type, i.e., maximum a \var{Longint}.
+% This happens, for instance, when you specify a second argument
+% to \var{Inc} or \var{Dec} that doesn't evaluate to an ordinal value.
+type_e_pointer_type_expected=04008_E_Se esperaba un tipo puntero, pero se encontró "$1"
+% The variable or expression isn't of the type \var{pointer}. This
+% happens when you pass a variable that isn't a pointer to \var{New}
+% or \var{Dispose}.
+type_e_class_type_expected=04009_E_Se esperaba un tipo de clase, pero se encontró "$1"
+% The variable of expression isn't of the type \var{class}. This happens
+% typically when
+% \begin{enumerate}
+% \item The parent class in a class declaration isn't a class.
+% \item An exception handler (\var{On}) contains a type identifier that
+% isn't a class.
+% \end{enumerate}
+type_e_cant_eval_constant_expr=04011_E_No se puede evaluar la espresión constante
+% This error can occur when the bounds of an array you declared does
+% not evaluate to ordinal constants
+type_e_set_element_are_not_comp=04012_E_Elementos de sets incompatibles
+% You are trying to make an operation on two sets, when the set element types
+% are not the same. The base type of a set must be the same when taking the
+% union
+type_e_set_operation_unknown=04013_E_Operación no implementada para sets
+% several binary operations are not defined for sets
+% like div mod ** (also >= <= for now)
+type_w_convert_real_2_comp=04014_W_Conversion automática de tipo de punto flotante a COMP el cual es un tipo entero
+% An implicit type conversion from a real type to a \var{comp} is
+% encountered. Since \var{comp} is a 64 bit integer type, this may indicate
+% an error.
+type_h_use_div_for_int=04015_H_usa DIV para tener un resultado entero
+% When hints are on, then an integer division with the '/' operator will
+% procuce this message, because the result will then be of type real
+type_e_strict_var_string_violation=04016_E_Tipos de cadena no concuerdan por la presencia de la opción $V+
+% When compiling in \var{\{\$V+\}} mode, the string you pass as a parameter
+% should be of the exact same type as the declared parameter of the procedure.
+type_e_succ_and_pred_enums_with_assign_not_possible=04017_E_No se permite el uso de Succ o Pred en enumeraciones que tienen valores asignados explícitamente
+% When you declared an enumeration type which has assignments in it, as in C,
+% like in the following:
+% \begin{verbatim}
+% Tenum = (a,b,e:=5);
+% \end{verbatim}
+% you cannot use the \var{Succ} or \var{Pred} functions on them.
+type_e_cant_read_write_type=04018_E_No se puede leer o escribir variables de este tipo
+% You are trying to \var{read} or \var{write} a variable from or to a
+% file of type text, which doesn't support that. Only integer types,
+% reals, pchars and strings can be read from/written to a text file.
+% Booleans can only be written to text files.
+type_e_no_readln_writeln_for_typed_file=04019_E_No se puede utilizar readln o writeln en ficheros con tipo
+% \var{readln} and \var{writeln} are only allowed for text files.
+type_e_no_read_write_for_untyped_file=04020_E_No se pueden usar read o write en ficheros sin tipo
+% \var{read} and \var{write} are only allowed for text or typed files.
+type_e_typeconflict_in_set=04021_E_El set contiene un elemento que no es de tipo compatible
+% There is at least one set element which is of the wrong type, i.e. not of
+% the set type.
+type_w_maybe_wrong_hi_lo=04022_W_lo/hi(longint/dword) devuelve la parte superior/inferior de tipo word
+% \fpc supports an overloaded version of \var{lo/hi} for \var{longint/dword/int64/qword}
+% which returns the lower/upper word/dword of the argument. TP always uses
+% a 16 bit \var{lo/hi} which returns always bits 0..7 for \var{lo} and the
+% bits 8..15 for \var{hi}. If you want the TP behavior you have
+% to type cast the argument to \var{word/integer}
+type_e_integer_or_real_expr_expected=04023_E_Espresión entera o real esperada
+% The first argument to \var{str} must a real or integer type.
+type_e_wrong_type_in_array_constructor=04024_E_Tipo "$1" erróneo en el constructor del array
+% You are trying to use a type in an array constructor which is not
+% allowed.
+type_e_wrong_parameter_type=04025_E_Tipo incompatible para el parámetro número $1: Se recibió "$2", cuando se esperaba "$3"
+% You are trying to pass an invalid type for the specified parameter.
+type_e_no_method_and_procedure_not_compatible=04026_E_Variables de tipo método y procedimiento no son compatibles entre si
+% You can't assign a method to a procedure variable or a procedure to a
+% method pointer.
+type_e_wrong_math_argument=04027_E_Constante pasada a la función matematica interna no válida
+% The constant argument passed to a ln or sqrt function is out of
+% the definition range of these functions.
+type_e_no_addr_of_constant=04028_E_No se puede obtener una dirección de una constante
+% It is not possible to get the address of a constant, because they
+% aren't stored in memory, you can try making it a typed constant.
+type_e_argument_cant_be_assigned=04029_E_No se puede asignar un valor al parámetro
+% Only expressions which can be on the left side of an
+% assignment can be passed as call by reference argument
+% Remark: Properties can be only
+% used on the left side of an assignment, but they cannot be used as arguments
+type_e_cannot_local_proc_to_procvar=04030_E_No se puede asignar un prodecimiento o funcion local a una variable
+% It's not allowed to assign a local procedure/function to a
+% procedure variable, because the calling of local procedure/function is
+% different. You can only assign local procedure/function to a void pointer.
+type_e_no_assign_to_addr=04031_E_No se puede asignar un valor a una dirección
+% It is not allowed to assign a value to an address of a variable,constant,
+% procedure or function. You can try compiling with -So if the identifier
+% is a procedure variable.
+type_e_no_assign_to_const=04032_E_No se pueden asignar valores a variables constantes
+% It's not allowed to assign a value to a variable which is declared
+% as a const. This is normally a parameter declared as const, to allow
+% changing the value make the parameter as a value parameter or a var.
+type_e_array_required=04033_E_Se requiere un array para usar [ ]
+% If you are accessing a variable using an index '[<x>]' then
+% the type must be an array. In FPC mode also a pointer is allowed.
+type_e_interface_type_expected=04034_E_Se esperaba "interface" pero se encontró "$1"
+type_w_mixed_signed_unsigned=04035_W_Operaciones mezclando enteros de 32 bits con signo son convertidas a 64 bits
+% If you divide (or calculate the modulus of) a signed expression by a longword (or vice versa),
+% or if you have overflow and/or range checking turned on and use an arithmetic
+% expression (+, -, *, div, mod) in which both signed numbers and longwords appear,
+% then everything has to be evaluated in 64bit which is slower than normal
+% 32bit arithmetic. You can avoid this by typecasting one operand so it
+% matches the result type of the other one.
+type_w_mixed_signed_unsigned2=04036_W_Mezclar operando con signo y sin signo aqui puede causar errores de comprobación de rango
+% If you use a binary operator (and, or, xor) and one of
+% the operands is a longword while the other one is a signed expression, then,
+% if range checking is turned on, you may get a range check error because in
+% such a case both operands are converted to longword before the operation is
+% carried out. You can avoid this by typecasting one operand so it
+% matches the result type of the other one.
+type_e_typecast_wrong_size_for_assignment=04037_E_La conversión de tipos ($1 -> $2) en la asignación tiene diferentes tamaños
+% Type casting to a type with a different size is not allowed when the variable is
+% used for assigning.
+type_e_array_index_enums_with_assign_not_possible=04038_E_No se pueden usar enums con asignaciones como indices de arrays
+% When you declared an enumeration type which has assignments in it, as in C,
+% like in the following:
+% \begin{verbatim}
+% Tenum = (a,b,e:=5);
+% \end{verbatim}
+% you cannot use it as index of an array.
+type_e_classes_not_related=04039_E_Las clases u objetos "$1" y "$2" no están relacionados
+% There is a typecast from one class or object to another while the class/object
+% are not related. This will probably lead to errors
+type_w_classes_not_related=04040_W_Los tipos de clases "$1" y "$2" no están relacionados
+% There is a typecast from one class or object to another while the class/object
+% are not related. This will probably lead to errors
+type_e_class_or_interface_type_expected=04041_E_Se esperaba una clase o interfaz, pero se encotró "$1"
+type_e_type_is_not_completly_defined=04042_E_El tipo "$1" no esta definido completamente aún
+type_w_string_too_long=04043_W_La cadena contiene mas caracteres que los admitidos por una cadena corta
+% The size of the constant string, which is assigned to a shortstring,
+% is longer than the maximum size of the shortstring
+type_w_signed_unsigned_always_false=04044_W_La comparación es siempre falsa debido a los rangos de los valores
+% There is a comparison between an unsigned value and a signed constant which is
+% less than zero. Because of type promotion, the statement will always evaluate to
+% false. Exlicitly typecast the constant to the correct range to avoid this problem.
+type_w_signed_unsigned_always_true=04045_W_La comparación es siempre verdadera debido a los rangos de los valores
+% There is a comparison between an unsigned value and a signed constant which is
+% less than zero. Because of type promotion, the statement will always evaluate to
+% true. Exlicitly typecast the constant to the correct range to avoid this problem.
+type_w_instance_with_abstract=04046_W_Constuyendo un objeto de clase "$1" que contiene métodos abstractos
+% An instance of a class is created which contains non-implemented abstract
+% methods. This will probably lead to a runtime error 211 in the code if that
+% routine is ever called. All abstract methods should be overridden.
+type_h_in_range_check=04047_H_El operando a la izquierda de IN debe ser de tamaño un byte
+% The left operand of the \var{in} operator is not an ordinal or enumeration which fits
+% within 8-bits, this may lead to range check errors. The \var{in} operator
+% currently only supports a left operand which fits within a byte. In the case of
+% enumerations, the size of an element of an enumeration can be controlled with
+% the \var{\{\$PACKENUM\}} or \var{\{\$Zn\}} switches.
+type_w_smaller_possible_range_check=04048_W_Diferencia del tamaño de los tipos puede causar pérdida de datos o errores de comprobación de rango
+% There is an assignment to a smaller type than the source type. This means that
+% this may cause a range-check error, or may lead to possible loss of data.
+type_h_smaller_possible_range_check=04049_H_Diferencia del tamaño de los tipos puede causar pérdida de datos o errores de comprobación de rango
+% There is an assignment to a smaller type than the source type. This means that
+% this may cause a range-check error, or may lead to possible loss of data.
+type_e_cant_take_address_of_abstract_method=04050_E_No se puede obtener la dirección de un método abstracto
+% An abstract method has no body, so the address of an abstract method can't be taken.
+type_e_operator_not_allowed=04051_E_El operador no es aplicable con los operandos especificados
+% You are trying an operator that is not available for the type of the
+% operands
+type_e_constant_expr_expected=04052_E_Se esperaba una expresió constante
+% The compiler expects an constant expression, but gets a variable expression.
+type_e_operator_not_supported_for_types=04053_E_La operacion "$1" no está soportada para los tipos "$2" y "$3"
+% The operation is not allowed for the supplied types
+type_e_illegal_type_conversion=04054_E_No es posible realizar una conversión de "$1" a "$2"
+% When doing a type-cast, you must take care that the sizes of the variable and
+% the destination type are the same.
+type_h_pointer_to_longint_conv_not_portable=04055_H_La conversion entre punteros y ordinales no es portable
+% If you typecast a pointer to a longint (or vice-versa), this code will not compile
+% on a machine using 64-bit for pointer storage.
+type_w_pointer_to_longint_conv_not_portable=04056_W_La conversion entre punteros y ordinales no es portable
+% If you typecast a pointer to a ordinal type of a different size (or vice-versa), this can
+% cause problems. This is a warning to help finding the 32bit specific code where cardinal/longint is used
+% to typecast pointers to ordinals. A solution is to use the ptrint/ptruint types instead.
+type_e_cant_choose_overload_function=04057_E_No se pudo determinar que funcion sobrecargada llamar
+% You're calling overloaded functions with a parameter that doesn't correspond
+% to any of the declared function parameter lists. e.g. when you have declared
+% a function with parameters \var{word} and \var{longint}, and then you call
+% it with a parameter which is of type \var{integer}.
+type_e_illegal_count_var=04058_E_Variable de contador inválida
+% The type of a \var{for} loop variable must be an ordinal type.
+% Loop variables cannot be reals or strings.
+% \end{description}
+#
+# Symtable
+#
+# 05055 is the last used one
+#
+% \section{Symbol handling}
+% This section lists all the messages that concern the handling of symbols.
+% This means all things that have to do with procedure and variable names.
+% \begin{description}
+sym_e_id_not_found=05000_E_Identificador no encontrado "$1"
+% The compiler doesn't know this symbol. Usually happens when you misspel
+% the name of a variable or procedure, or when you forgot to declare a
+% variable.
+sym_f_internal_error_in_symtablestack=05001_F_Error interno en SymTableStack()
+% An internal error occurred in the compiler; If you encounter such an error,
+% please contact the developers and try to provide an exact description of
+% the circumstances in which the error occurs.
+sym_e_duplicate_id=05002_E_Identificador duplicado "$1"
+% The identifier was already declared in the current scope.
+sym_h_duplicate_id_where=05003_H_El identificador ya está definido en $1 en la línea $2
+% The identifier was already declared in a previous scope.
+sym_e_unknown_id=05004_E_Identificador desconocido "$1"
+% The identifier encountered has not been declared, or is used outside the
+% scope where it is defined.
+sym_e_forward_not_resolved=05005_E_Declaración posterior no solucionada "$1"
+% This can happen in two cases:
+% \begin{itemize}
+% \item This happens when you declare a function (in the \var{interface} part, or
+% with a \var{forward} directive, but do not implement it.
+% \item You reference a type which isn't declared in the current \var{type}
+% block.
+% \end{itemize}
+sym_e_error_in_type_def=05007_E_Error en definición de tipo
+% There is an error in your definition of a new array type:
+% \item One of the range delimiters in an array declaration is erroneous.
+% For example, \var{Array [1..1.25]} will trigger this error.
+sym_e_forward_type_not_resolved=05009_E_Tipo posterior no resuelto "$1"
+% A symbol was forward defined, but no declaration was encountered.
+sym_e_only_static_in_static=05010_E_Solo las variables estáticas pueden ser usadas en métodos estáticos o fuera de métodos
+% A static method of an object can only access static variables.
+sym_f_type_must_be_rec_or_class=05012_F_tipo record o class esperado
+% The variable or expression isn't of the type \var{record} or \var{class}.
+sym_e_no_instance_of_abstract_object=05013_E_No se permiten instancias de clases u objetos con un métodos abstractos
+% You are trying to generate an instance of a class which has an abstract
+% method that wasn't overridden.
+sym_w_label_not_defined=05014_W_Etiqueta no definida "$1"
+% A label was declared, but not defined.
+sym_e_label_used_and_not_defined=05015_E_Etiqueta "$1" usada pero no definida
+% A label was declared and used, but not defined.
+sym_e_ill_label_decl=05016_E_Declaración inválida de la etiqueta
+% This error should never happen; it occurs if a label is defined outside a
+% procedure or function.
+sym_e_goto_and_label_not_supported=05017_E_GOTO y LABEL no son soportados (debe ser habilitado con -Sg)
+% You must compile a program which has \var{label}s and \var{goto} statements
+% with the \var{-Sg} switch. By default, \var{label} and \var{goto} aren't
+% supported.
+sym_e_label_not_found=05018_E_Etiqueta no encontrada
+% A \var{goto label} was encountered, but the label isn't declared.
+sym_e_id_is_no_label_id=05019_E_el identificador no es una etiqueta
+% The identifier specified after the \var{goto} isn't of type label.
+sym_e_label_already_defined=05020_E_Etiqueta ya definida
+% You are defining a label twice. You can define a label only once.
+sym_e_ill_type_decl_set=05021_E_Definicion de tipo set inválida
+% The declaration of a set contains an invalid type definition.
+sym_e_class_forward_not_resolved=05022_E_Definición posterior de la clase "$1" no resuelta
+% You declared a class, but you did not implement it.
+sym_n_unit_not_used=05023_H_Unidad "$1" no utilizada en $2
+% The unit referenced in the \var{uses} clause is not used.
+sym_h_para_identifier_not_used=05024_H_Parámetro "$1" no usado
+% The identifier was declared (locally or globally) but
+% was not used (locally or globally).
+sym_n_local_identifier_not_used=05025_N_Variable local no usada "$1"
+% You have declared, but not used a variable in a procedure or function
+% implementation.
+sym_h_para_identifier_only_set=05026_H_Valor asignado a "$1" pero no utilizado
+% The identifier was declared (locally or globally)
+% set but not used (locally or globally).
+sym_n_local_identifier_only_set=05027_N_Valor asignado a la variable local "$1" no utilizado
+% The variable in a procedure or function
+% implementation is declared, set but never used.
+sym_h_local_symbol_not_used=05028_H_Símbolo local $1 "$2" no utilizado
+% A local symbol is never used.
+sym_n_private_identifier_not_used=05029_N_Campo privado $1.$2 no utilizado
+sym_n_private_identifier_only_set=05030_N_Valor asignado al campo privado $1.$2 pero nunca es utilizado
+sym_n_private_method_not_used=05031_N_Método privado $1.$2 no utilizado
+sym_e_set_expected=05032_E_Tipo set esperado
+% The variable or expression is not of type \var{set}. This happens in an
+% \var{in} statement.
+sym_w_function_result_not_set=05033_W_El resultado de la función puede no haber sido asignado
+% You can get this warning if the compiler thinks that a function return
+% value is not set. This will not be displayed for assembler procedures,
+% or procedures that contain assembler blocks.
+sym_w_wrong_C_pack=05034_W_El tipo "$1" no esta correctamente alineado para C
+% Arrays with sizes not multiples of 4 will be wrongly aligned
+% for C structures.
+sym_e_illegal_field=05035_E_Identificador de campo de registro desconocido: "$1"
+% The field doesn't exist in the record/object definition.
+sym_w_uninitialized_local_variable=05036_W_La variable local "$1" no parace haber sido inicializada
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_w_uninitialized_variable=05037_W_La variable "$1" no parece haber sido inicializada
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_e_id_no_member=05038_E_El identificador "$1" no identifica ningún miembro
+% This error is generated when an identifier of a record,
+% field, or method is accessed while it is not defined.
+sym_h_param_list=05039_H_Declaracion encontrada: $1
+% You get this when you use the \var{-vh} switch. In case an overloaded
+% procedure is not found, then all candidate overloaded procedures are
+% listed, with their parameter lists.
+sym_e_segment_too_large=05040_E_Segmento de datos demasiado grande
+% You get this when you declare a data element whose size exceeds the
+% prescribed limit (2 Gb on 80386+/68020+ processors)
+sym_e_no_matching_implementation_found=05042_E_No se encontro una implementación para el método "$1" de la interfaz
+% There was no matching method found which could implement the interface
+% method. Check argument types and result type of the methods.
+sym_w_deprecated_symbol=05043_W_Símbolo "$1" desaconsejado
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{deprecated} is used. Deprecated symbols may no longer
+% be available in newer versions of the unit / library. Usage of this symbol
+% should be avoided as much as possible.
+sym_w_non_portable_symbol=05044_W_El símbolo "$1" no es portable
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{platform} is used. This symbol's value, usage
+% and availability is platform specific and should not be used
+% if the source code must be portable.
+sym_w_non_implemented_symbol=05055_W_El símbolo "$1" no está implementado
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{unimplemented} is used. This symbol is defined,
+% but is not yet implemented on this specific platform.
+sym_e_cant_create_unique_type=05056_E_No se puede crear un tipo único a partir de este tipo
+% Only simple types like ordinal, float and string types are supported when
+% redefining a type with \var{type newtype = type oldtype;}.
+sym_h_uninitialized_local_variable=05057_H_La variable local "$1" no parece haber sido inicializada
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_h_uninitialized_variable=05058_H_La variable "$1" no parece haber sido inicializada
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+% \end{description}
+#
+# Codegenerator
+#
+# 06040 is the last used one
+#
+% \section{Code generator messages}
+% This section lists all messages that can be displayed if the code
+% generator encounters an error condition.
+% \begin{description}
+cg_e_parasize_too_big=06009_E_El tamaño de la lista de par metros excede 65535 bytes
+% The I386 processor limits the parameter list to 65535 bytes (the \var{RET}
+% instruction causes this)
+cg_e_file_must_call_by_reference=06012_E_Los tipos File deben ser pasados por referencia
+% You cannot specify files as value parameters, i.e. they must always be
+% declared \var{var} parameters.
+cg_e_cant_use_far_pointer_there=06013_E_El uso de punteros "far" no esta permitido aqií
+% Free Pascal doesn't support far pointers, so you cannot take the address of
+% an expression which has a far reference as a result. The \var{mem} construct
+% has a far reference as a result, so the following code will produce this
+% error:
+% \begin{verbatim}
+% var p : pointer;
+% ...
+% p:=@mem[a000:000];
+% \end{verbatim}
+cg_e_dont_call_exported_direct=06015_E_las funciones declaradas como EXPORT no pueden ser llamadas
+% No longer in use.
+cg_w_member_cd_call_from_method=06016_W_Posible llamada inválida de un constructor o destructor
+% The compiler detected that a constructor or destructor is called within a
+% a method. This will probably lead to problems, since constructors / destructors
+% require parameters on entry.
+cg_n_inefficient_code=06017_N_código ineficiente
+% Your statement seems dubious to the compiler.
+cg_w_unreachable_code=06018_W_El código no será ejecutado nunca
+% You specified a construct which will never be executed. Example:
+% \begin{verbatim}
+% while false do
+% begin
+% {.. code ...}
+% end;
+% \end{verbatim}
+cg_e_cant_call_abstract_method=06020_E_Los métodos abstractos no pueden ser llamados directamente
+% You cannot call an abstract method directy, instead you must call a
+% overriding child method, because an abstract method isn't implemented.
+cg_d_register_weight=06027_DL_Registro $1 peso $2 $3
+% Debugging message. Shown when the compiler considers a variable for
+% keeping in the registers.
+cg_d_stackframe_omited=06029_DL_Se omite generar stack frame
+% Some procedure/functions do not need a complete stack-frame, so it is omitted.
+% This message will be displayed when the {-vd} switch is used.
+cg_e_unable_inline_object_methods=06031_E_Métodos de objetos o clases no pueden ser inline
+% You cannot have inlined object methods.
+cg_e_unable_inline_procvar=06032_E_Variables de procedimiento o función no pueden ser inline
+% A procedure with a procedural variable call cannot be inlined.
+cg_e_no_code_for_inline_stored=06033_E_No hay código almacenado para procedimientos inline
+% The compiler couldn't store code for the inline procedure.
+cg_e_can_access_element_zero=06035_E_No se puede acceder al elemento 0 de cadenas largas, use SetLength/Length
+% You should use \var{setlength} to set the length of an ansi/wide/longstring
+% and \var{length} to get the length of such a string types
+cg_e_cannot_call_cons_dest_inside_with=06037_E_No se pueden llamar a constructores o destructores en with
+% Inside a \var{with} clause you cannot call a constructor or destructor for the
+% object you have in the \var{with} clause.
+cg_e_cannot_call_message_direct=06038_E_No se pueden llamar a métodos manejadores de mensajes directamente
+% A message method handler method cannot be called directly if it contains an
+% explicit self argument
+cg_e_goto_inout_of_exception_block=06039_E_Salto fuera de un bloque de excepción
+% It is not allowed to jump in or outside of an exception block like \var{try..finally..end;}:
+% \begin{verbatim}
+% label 1;
+%
+% ...
+%
+% try
+% if not(final) then
+% goto 1; // this line will cause an error
+% finally
+% ...
+% end;
+% 1:
+% ...
+% \end{verbatim}
+cg_e_control_flow_outside_finally=06040_E_No se admiten instrucciones de control de flujo en un bloque finally
+% It isn't allowed to use the control flow statements \var{break},
+% \var{continue} and \var{exit}
+% inside a finally statement. The following example shows the problem:
+% \begin{verbatim}
+% ...
+% try
+% p;
+% finally
+% ...
+% exit; // This exit ISN'T allowed
+% end;
+% ...
+%
+% \end{verbatim}
+% If the procedure \var{p} raises an exception the finally block is
+% executed. If the execution reaches the exit, it's unclear what to do:
+% exiting the procedure or searching for another exception handler
+cg_w_parasize_too_big=06041_W_El tamaño del parámetro excede el límite de algunas CPU
+% This indicates that you are declaring more than 64K of parameters, which
+% might not be supported on other processor targets.
+cg_w_localsize_too_big=06042_W_El tamaño de las variables locales excede el límite de algunas CPU
+% This indicates that you are declaring more than 32K of lcoal variables, which
+% might not be supported on other processor targets.
+cg_e_localsize_too_big=06043_E_El tamaño de las variables locales excede el límite de la CPU de destino
+% This indicates that you are declaring more than 32K of lcoal variables, which
+% is not supported by this processor.
+cg_e_break_not_allowed=06044_E_BREAK no permitido aquí
+% You're trying to use \var{break} outside a loop construction.
+cg_e_continue_not_allowed=06045_E_CONTINUE no permitido aquí
+% You're trying to use \var{continue} outside a loop construction.
+% \end{description}
+# EndOfTeX
+
+#
+# Assembler reader
+#
+# 07097 is the last used one
+#
+asmr_d_start_reading=07000_DL_Iniciando interpretado de ensamblador de estilo $1
+% This informs you that an assembler block is being parsed
+asmr_d_finish_reading=07001_DL_Finalizado interpretado de ensamblador de estilo $1
+% This informs you that an assembler block has finished.
+asmr_e_none_label_contain_at=07002_E_Una patrón que no es una etiqueta contiene @
+% A identifier which isn't a label can't contain a @.
+asmr_e_building_record_offset=07004_E_Error construyendo desplazamiento de registro (record)
+% There has an error occured while building the offset of a record/object
+% structure, this can happend when there is no field specified at all or
+% an unknown field identifier is used.
+asmr_e_offset_without_identifier=07005_E_OFFSET usado sin identificador
+% You can only use OFFSET with an identifier. Other syntaxes aren't
+% supported
+asmr_e_type_without_identifier=07006_E_TYPE usado sin identificador
+% You can only use TYPE with an identifier. Other syntaxes aren't
+% supported
+asmr_e_no_local_or_para_allowed=07007_E_No es posible usar una variable local o parámetro aquí
+% You can't use a local variable or parameter here, mostly because the
+% addressing of locals and parameters is done using the frame pointer register so the
+% address can't be obtained directly.
+asmr_e_need_offset=07008_E_Es necesario el uso de OFFSET aquí
+% You need to use OFFSET <id> here to get the address of the identifier.
+asmr_e_need_dollar=07009_E_Es necesario el uso de $ auqí
+% You need to use $<id> here to get the address of the identifier.
+asmr_e_cant_have_multiple_relocatable_symbols=07010_E_No es posible utilizar varios símbolos reubicables
+% You can't have more than one relocatable symbol (variable/typed constant)
+% in one argument.
+asmr_e_only_add_relocatable_symbol=07011_E_Símbolos reubicables solo pueden ser añadidos
+% Relocatable symbols (variable/typed constant) can't be used with other
+% operators. Only addition is allowed.
+asmr_e_invalid_constant_expression=07012_E_Espresió constante inválida
+% There is an error in the constant expression.
+asmr_e_relocatable_symbol_not_allowed=07013_E_Símbolo reubicable no permitido
+% You can't use a relocatable symbol (variable/typed constant) here.
+asmr_e_invalid_reference_syntax=07014_E_Sintaxis de referencia inválida
+% There is an error in the reference.
+asmr_e_local_para_unreachable=07015_E_No se puede llegar a $1 desde este código
+% You can not read directly the value of local or para
+% of a higher level in assembler code (except for
+% local assembler code without parameter nor locals).
+asmr_e_local_label_not_allowed_as_ref=07016_E_No está permitido el uso símbolos locales o etiquetas como referencias
+% You can't use local symbols/labels as references
+asmr_e_wrong_base_index=07017_E_Uso inválido de registros indice y base
+% There is an error with the base and index register, they are
+% probably incorrect
+asmr_w_possible_object_field_bug=07018_W_Posible error en el manejo de campos de objetos
+% Fields of objects or classes can be reached directly in normal or objfpc
+% modes but TP and Delphi modes treat the field name as a simple offset.
+asmr_e_wrong_scale_factor=07019_E_Factor de escala erróneo
+% The scale factor given is wrong, only 1,2,4 and 8 are allowed
+asmr_e_multiple_index=07020_E_Uso de multiples registros índice
+% You are trying to use more than one index register
+asmr_e_invalid_operand_type=07021_E_Tipo del operando no válido
+% The operand type doesn't match with the opcode used
+asmr_e_invalid_string_as_opcode_operand=07022_E_Cadena no vólida como operando de esta instrucción: $1
+% The string specified as operand is not correct with this opcode
+asmr_w_CODE_and_DATA_not_supported=07023_W_@CODE y @DATA no son soportados
+% @CODE and @DATA are unsupported and are ignored.
+asmr_e_null_label_ref_not_allowed=07024_E_Referencias a etiqueta nula no permitida
+asmr_e_expr_zero_divide=07025_E_Division entre cero en el evaluador de ensamblador
+% There is a division by zero in a constant expression
+asmr_e_expr_illegal=07026_E_Expresión inválida
+% There is an illegal expression in a constant expression
+asmr_e_escape_seq_ignored=07027_E_Sequencia de escape ignorada: $1
+% There is a C-styled string, but the escape sequence in the string
+% is unknown, and is therefore ignored
+asmr_e_invalid_symbol_ref=07028_E_Referencia a símbolo inválida
+asmr_w_fwait_emu_prob=07029_W_Fwait puede causar problemas de emulación con emu387
+asmr_w_fadd_to_faddp=07030_W_$1 sin operando interpretado como $1P
+asmr_w_enter_not_supported_by_linux=07031_W_La instruccion ENTER no está soportada por el kernel de Linux
+% ENTER instruction can generate a stack page fault that is not
+% caught correctly by the i386 Linux page handler.
+asmr_w_calling_overload_func=07032_W_Llamando a una funcion sobrecargada desde ensamblador
+% There is a call to an overloaded method in the assembler block,
+% this might be the sign there is a problem
+asmr_e_unsupported_symbol_type=07033_E_Tipo de símbolo no soportado para el operando
+asmr_e_constant_out_of_bounds=07034_E_Valor de la constante fuera de rango
+asmr_e_error_converting_decimal=07035_E_Error convirtiendo decimal $1
+% A constant decimal value does not have the correct syntax
+asmr_e_error_converting_octal=07036_E_Error convirtiendo octal $1
+% A constant octal value does not have the correct syntax
+asmr_e_error_converting_binary=07037_E_Error convirtiendo binario $1
+% A constant binary value does not have the correct syntax
+asmr_e_error_converting_hexadecimal=07038_E_Error convirtiendo hexadecimal $1
+% A constant hexadecimal value does not have the correct syntax
+asmr_h_direct_global_to_mangled=07039_H_$1 traducido a $2
+asmr_w_direct_global_is_overloaded_func=07040_W_$1 esta asociado a una función sobrecargada
+asmr_e_cannot_use_SELF_outside_a_method=07041_E_No se puede usar SELF fuera de un método
+% There is a reference to the \var{self} symbol while it is not
+% allowed. \var{self} can only be referenced inside methods
+asmr_e_cannot_use_OLDEBP_outside_nested_procedure=07042_E_No se puede usar OLDEBP fuera de un procedimiento anidado
+% There is a reference to the \var{oldebp} symbol while it is not
+% allowed. \var{oldebp} can only be referenced inside nested routines
+asmr_e_void_function=07043_W_No es posible devolver un valor en procedimientos desde código asm
+% Trying to return a value while in a procedure. A procedure
+% does not have any return value
+asmr_e_SEG_not_supported=07044_E_SEG no soportado
+asmr_e_size_suffix_and_dest_dont_match=07045_E_No concuerdan el tamaño del prefijo y el del origen o destino
+% The register size and the opcode size suffix don't match. This is
+% probably an error in the assembler statement
+asmr_w_size_suffix_and_dest_dont_match=07046_W_No concuerdan el tamaño del prefijo y el del origen o destino
+% The register size and the opcode size suffix don't match. This is
+% probably an error in the assembler statement
+asmr_e_syntax_error=07047_E_Error de sintaxis de ensamblador
+% There is an assembler syntax error
+asmr_e_invalid_opcode_and_operand=07048_E_Combinación inválida de operacion y operandos
+% The opcode cannot be used with this type of operand
+asmr_e_syn_operand=07049_E_Error de sintaxis de ensamblador en operando
+asmr_e_syn_constant=07050_E_Error de sintaxis de ensamblador en constante
+asmr_e_invalid_string_expression=07051_E_Espresión de cadena noáv lida
+asmr_w_const32bit_for_address=07052_W_constante con la direccion del símbolo $1 que no es un puntero
+% A constant expression represents an address which does not fit
+% into a pointer. The address is probably incorrect
+asmr_e_unknown_opcode=07053_E_Instrucción $1 no reconocida
+% This opcode is not known
+asmr_e_invalid_or_missing_opcode=07054_E_Falta la instrucción o no es válida
+asmr_e_invalid_prefix_and_opcode=07055_E_Combinación de prefijo y operación inválidos: $1
+asmr_e_invalid_override_and_opcode=07056_E_Combinación de sobrecarga y operación inválidos: $1
+asmr_e_too_many_operands=07057_E_Demasiados operandos en la línea
+% There are too many operands for this opcode. Check your
+% assembler syntax
+asmr_w_near_ignored=07058_W_NEAR ignorado
+asmr_w_far_ignored=07059_W_FAR ignorado
+asmr_e_dup_local_sym=07060_E_Símbolo local duplicado $1
+asmr_e_unknown_local_sym=07061_E_Símbolo local indefinido $1
+asmr_e_unknown_label_identifier=07062_E_Identificador de etiqueta desconocido $1
+asmr_e_invalid_register=07063_E_Nombre de registro incorrecto
+% There is an unknown register name used as operand.
+asmr_e_invalid_fpu_register=07064_E_Nombre de registro de punto flotante no válido
+% There is an unknown register name used as operand.
+asmr_w_modulo_not_supported=07066_W_Modulo no soportado
+asmr_e_invalid_float_const=07067_E_Constante de punto flotante no válida $1
+% The floating point constant declared in an assembler block is
+% invalid.
+asmr_e_invalid_float_expr=07068_E_Espresión de punto flotante no válida
+% The floating point expression declared in an assembler block is
+% invalid.
+asmr_e_wrong_sym_type=07069_E_Tipo de símbolo erróneo
+asmr_e_cannot_index_relative_var=07070_E_No se puede indexar una var. local o un parámetro con un registro
+% Trying to index using a base register a symbol which is already relative
+% to a register. This is not possible, and will probably lead to crashes.
+asmr_e_invalid_seg_override=07071_E_Espresión reemplazo de segmento inválida
+asmr_w_id_supposed_external=07072_W_Identificador $1 se supone externo
+% There is a reference to an undefined symbol. This will not result
+% in an error, since the symbol might be external, but may cause
+% problems at link time if the symbol is not defined anywhere.
+asmr_e_string_not_allowed_as_const=07073_E_Cadenas no permitidas como constantes
+% Character strings are not allowed as constants.
+asmr_e_no_var_type_specified=07074_E_No hay tipo de variable especificado
+% The syntax expects a type idenfitifer after the dot, but
+% none was found.
+asmr_w_assembler_code_not_returned_to_text=07075_E_Código ensamblador no devuelto a sección de texto
+% There was a directive in the assembler block to change sections,
+% but there is a missing return to the text section at the end
+% of the assembler block. This might cause errors during link time.
+asmr_e_not_directive_or_local_symbol=07076_E_No es una directiva o un símbolo local $1
+% This symbol is unknown.
+asmr_w_using_defined_as_local=07077_E_Usando un nombre definido como una etiqueta local
+asmr_e_dollar_without_identifier=07078_E_Tóken de dólar usado sin identificador
+% A constant expression has an identifier which does not start with
+% the $ symbol.
+asmr_w_32bit_const_for_address=07079_W_Constante de 32 bits creada para la dirección
+% A constant was used as an address. This is probably an error,
+% since using absolute addresses will probably not work.
+asmr_n_align_is_target_specific=07080_N_.align es dependiente de la plataforma, use .balign o .p2align
+% Using the .align directive is platform specific, and its meaning will vary
+% from one platform to another.
+asmr_e_cannot_access_field_directly_for_parameters=07081_E_No se puede acceder directamente a los campos de los parámetros
+% You should load the parameter first into a register and then access the
+% fields using that register.
+asmr_e_cannot_access_object_field_directly=07082_E_No se puede acceder directamente a los campos de objetos o clases
+% You should load the self pointer first into a register and then access the
+% fields using the register as base. By default the self pointer is available
+% in the esi register on i386.
+asmr_e_unable_to_determine_reference_size=07083_E_No se especificó un tamaño y no es posible determinar el tamaño del operando
+% You should specify explicitly a size for the reference, because
+% the compiler is unable to determine what size (byte,word,dword,etc.) it
+% should use for the reference.
+asmr_e_cannot_use_RESULT_here=07084_E_No se puede utilizar RESULT en esta función
+% Some functions which return complex types cannot use the \var{result}
+% keyword.
+asmr_w_adding_explicit_args_fXX=07086_W_"$1" sin operando traducido como "$1 %st,%st(1)"
+asmr_w_adding_explicit_first_arg_fXX=07087_W_"$1 %st(n)" traducido como "$1 %st,%st(n)"
+asmr_w_adding_explicit_second_arg_fXX=07088_W_"$1 %st(n)" traducido como "$1 %st(n),%st"
+asmr_e_invalid_char_smaller=07089_E_El carácter < no está permitido aquí
+% The shift operator requires the << characters. Only one
+% of those characters was found.
+asmr_e_invalid_char_greater=07090_E_El carácter > no está permitido aqui
+% The shift operator requires the >> characters. Only one
+% of those characters was found.
+asmr_w_align_not_supported=07093_W_ALIGN no es soportado
+asmr_e_no_inc_and_dec_together=07094_E_Inc y Dec no pueden estar juntos en la misma instrucción
+% Trying to use an increment and a decrement within the same
+% opcode on the 680x0. This is impossible.
+asmr_e_invalid_reg_list_in_movem=07095_E_Lista de registros inválida para movem
+% Trying to use the \var{movem} opcode with invalid registers
+% to save or restore.
+asmr_e_invalid_reg_list_for_opcode=07096_E_Lista de registros inválida para la instrucción
+asmr_e_higher_cpu_mode_required=07097_E_Se requiere un modo de CPU superior ($1)
+% Trying to use an instruction which is not supported in the current
+% cpu mode. Use a higher cpu generation to be able to use this
+% opcode in your assembler block
+asmr_w_unable_to_determine_reference_size_using_dword=07098_W_No se especificó el tamaño del operando y no pudo ser determinado. Se utilizará DWORD por defecto
+% You should specify explicitly a size for the reference, because
+% the compiler is unable to determine what size (byte,word,dword,etc.) it
+% should use for the reference. This warning is only used in Delphi mode where
+% it falls back to use DWORD as default.
+asmr_e_illegal_shifterop_syntax=07099_E_Error de sintaxis tratando de interpretar un operando de desplazamiento
+% ARM only; ARM assembler supports a so called shifter operand. The used syntax isn't
+% a valid shifter operand. Example for an operation with shifter operand:
+% \begin{verbatim}
+% asm
+% orr r2,r2,r2,lsl #8
+% end;
+% \end{verbatim}
+#
+# Assembler/binary writers
+#
+# 08018 is the last used one
+#
+asmw_f_too_many_asm_files=08000_F_Demasiados archivos de ensamblador abiertos
+% With smartlinking enabled, there are too many assembler
+% files generated. Disable smartlinking.
+asmw_f_assembler_output_not_supported=08001_F_Salida a ensamblador seleccionada no soportada
+asmw_f_comp_not_supported=08002_F_Comp no soportado
+asmw_f_direct_not_supported=08003_F_Direct no soportado por escritores binarios
+% Direct assembler mode is not supported for binary writers.
+asmw_e_alloc_data_only_in_bss=08004_E_Sólo esta permitido alojar datos en la seccion bss
+asmw_f_no_binary_writer_selected=08005_F_No hay seleccionado un escritor binario
+asmw_e_opcode_not_in_table=08006_E_Asm: Opcode $1 no está en la tabla
+asmw_e_invalid_opcode_and_operands=08007_E_Asm: $1 combinacion inválida de opcode y operandos
+asmw_e_16bit_not_supported=08008_E_Asm: Referencias de 16 Bit no soportadas
+asmw_e_invalid_effective_address=08009_E_Asm: Dirección efectiva no válida
+asmw_e_immediate_or_reference_expected=08010_E_Asm: Inmediato o referencia esperado
+asmw_e_value_exceeds_bounds=08011_E_Asm: $1 valor excede los límites $2
+asmw_e_short_jmp_out_of_range=08012_E_Asm: Salto corto es fuera de rango $1
+asmw_e_undefined_label=08013_E_Asm: Etiqueta no definida $1
+asmw_e_comp_not_supported=08014_E_Asm: El tipo Comp no está soportado en esta plataforma
+asmw_e_extended_not_supported=08015_E_Asm: El tipo Extended no está soportado en esta plataforma
+asmw_e_duplicate_label=08016_E_Asm: Etiquita $1 duplicada
+asmw_e_redefined_label=08017_E_Asm: Etiqueta $1 redefinida
+asmw_e_first_defined_label=08018_E_Asm: Se definió por primera vez aquí
+asmw_e_invalid_register=08019_E_Asm: Registro $1 inválido
+
+#
+# Executing linker/assembler
+#
+# 09034 is the last used one
+#
+# BeginOfTeX
+%
+% \section{Errors of assembling/linking stage}
+% This section lists errors that occur when the compiler is processing the
+% command line or handling the configuration files.
+% \begin{description}
+exec_w_source_os_redefined=09000_W_Sistema operativo de origen redefinido
+exec_i_assembling_pipe=09001_I_Ensamblando (pipe) $1
+exec_d_cant_create_asmfile=09002_E_No se puede crear fichero ensamblador $1
+% The mentioned file can't be created. Check if you have got
+% access permissions to create this file
+exec_e_cant_create_objectfile=09003_E_No se puede crear fichero objeto: $1
+% The mentioned file can't be created. Check if you've
+% got access permissions to create this file
+exec_e_cant_create_archivefile=09004_E_No se puede crear fichero de archivado: $1
+% The mentioned file can't be created. Check if you've
+% access permissions to create this file
+exec_e_assembler_not_found=09005_E_Ensamblador $1 no encontrado, cambiando a ensamblado externo
+exec_t_using_assembler=09006_T_Usando ensamblador: $1
+exec_e_error_while_assembling=09007_E_Error mientras se ensamblaba, codigo de terminación $1
+% There was an error while assembling the file using an external assembler.
+% Consult the documentation of the assembler tool to find out more information
+% on this error.
+exec_e_cant_call_assembler=09008_E_No se pudo llamar al ensamblador, error $1. Cambiando a ensamblador externo
+exec_i_assembling=09009_I_Ensamblando $1
+exec_i_assembling_smart=09010_I_Assembling con enlazado inteligente $1
+exec_w_objfile_not_found=09011_W_Objeto $1 no encontrado, el enlazado podria fallar!
+% One of the object file is missing, and linking will probably fail.
+% Check your paths.
+exec_w_libfile_not_found=09012_W_Librería $1 no encontrada, el enlazado podria fallar!
+% One of the library file is missing, and linking will probably fail.
+% Check your paths.
+exec_e_error_while_linking=09013_E_Error durante el enlazado
+% Generic error while linking.
+exec_e_cant_call_linker=09014_E_No se puede llamar al enlazador, cambiando a enlazado externo
+exec_i_linking=09015_I_Enlazando $1
+exec_e_util_not_found=09016_E_Utilidad $1 no encontrada, cambiando a enlazado externo
+exec_t_using_util=09017_T_Utilizando utilidad $1
+exec_e_exe_not_supported=09018_E_Creacion de ejecutables no soportado
+exec_e_dll_not_supported=09019_E_Creacion de librerías dinámicas/compartidas no soportado
+exec_i_closing_script=09020_I_Cerrando script $1
+exec_e_res_not_found=09021_E_Compilador de recursos no encontrado, cambiando a modo externo
+exec_i_compilingresource=09022_I_Compilando resource $1
+exec_t_unit_not_static_linkable_switch_to_smart=09023_T_La unidad $1 no puede ser enlazada estáticamente, cambiando a enlazado inteligente
+exec_t_unit_not_smart_linkable_switch_to_static=09024_T_La unidad $1 no puede ser enlazada inteligentemente, cambiando a enlazado estático
+exec_t_unit_not_shared_linkable_switch_to_static=09025_T_La unidad $1 no admite enlazado compartido, cambiando a enlazado estático
+exec_e_unit_not_smart_or_static_linkable=09026_E_La unidad $1 no puede ser enlazada estática o inteligentemente
+exec_e_unit_not_shared_or_static_linkable=09027_E_La unidad $1 no admite enlazado compartido o estático
+%\end{description}
+# EndOfTeX
+
+#
+# Executable information
+#
+execinfo_f_cant_process_executable=09128_F_No se puede post-procesar el ejecutable $1
+execinfo_f_cant_open_executable=09129_F_No se puede abrir el ejecutable $1
+execinfo_x_codesize=09130_X_Tamaño de Código: $1 bytes
+execinfo_x_initdatasize=09131_X_Tamaño de datos inicializados: $1 bytes
+execinfo_x_uninitdatasize=09132_X_Tamaño de datos sin inicializar: $1 bytes
+execinfo_x_stackreserve=09133_X_Espacio reservado para la pila: $1 bytes
+execinfo_x_stackcommit=09134_X_Stack space commited: $1 bytes
+
+#
+# Unit loading
+#
+# 10041 is the last used one
+#
+# BeginOfTeX
+% \section{Unit loading messages.}
+% This section lists all messages that can occur when the compiler is
+% loading a unit from disk into memory. Many of these messages are
+% informational messages.
+% \begin{description}
+unit_t_unitsearch=10000_T_Buscando unidad: $1
+% When you use the \var{-vt}, the compiler tells you where it tries to find
+% unit files.
+unit_t_ppu_loading=10001_T_Cargando PPU $1
+% When the \var{-vt} switch is used, the compiler tells you
+% what units it loads.
+unit_u_ppu_name=10002_U_PPU Nombre: $1
+% When you use the \var{-vu} flag, the unit name is shown.
+unit_u_ppu_flags=10003_U_PPU Banderas: $1
+% When you use the \var{-vu} flag, the unit flags are shown.
+unit_u_ppu_crc=10004_U_PPU CRC: $1
+% When you use the \var{-vu} flag, the unit CRC check is shown.
+unit_u_ppu_time=10005_U_PPU Fecha: $1
+% When you use the \var{-vu} flag, the time the unit was compiled is shown.
+unit_u_ppu_file_too_short=10006_U_Fichero PPU demasiado corto
+% The ppufile is too short, not all declarations are present.
+unit_u_ppu_invalid_header=10007_U_Cabecera PPU inválida (no comienza por PPU)
+% A unit file contains as the first three bytes the ascii codes of \var{PPU}
+unit_u_ppu_invalid_version=10008_U_Versión $1 inválida
+% This unit file was compiled with a different version of the compiler, and
+% cannot be read.
+unit_u_ppu_invalid_processor=10009_U_PPU está compilada para otro procesador
+% This unit file was compiled for a different processor type, and
+% cannot be read
+unit_u_ppu_invalid_target=10010_U_PPU está compilada para otra plataforma
+% This unit file was compiled for a different target, and
+% cannot be read
+unit_u_ppu_source=10011_U_Origen PPU: $1
+% When you use the \var{-vu} flag, the unit CRC check is shown.
+unit_u_ppu_write=10012_U_Escribiendo $1
+% When you specify the \var{-vu} switch, the compiler will tell you where it
+% writes the unit file.
+unit_f_ppu_cannot_write=10013_F_No se puede escribir el fichero PPU
+% An error occurred when writing the unit file.
+unit_f_ppu_read_error=10014_F_Error leyendo fichero PPU
+% This means that the unit file was corrupted, and contains invalid
+% information. Recompilation will be necessary.
+unit_f_ppu_read_unexpected_end=10015_F_Fin de fichero inesperado
+% Unexpected end of file. This may mean that the PPU file is
+% corrupted.
+unit_f_ppu_invalid_entry=10016_F_Entrada inválida en fichero PPU: $1
+% The unit the compiler is trying to read is corrupted, or generated with a
+% newer version of the compiler.
+unit_f_ppu_dbx_count_problem=10017_F_Problema en el contador PPU Dbx
+% There is an inconsistency in the debugging information of the unit.
+unit_e_illegal_unit_name=10018_E_Nombre de unidad inválido: $1
+% The name of the unit does not match the file name.
+unit_f_too_much_units=10019_F_Demasiades unidades
+% \fpc has a limit of 1024 units in a program. You can change this behavior
+% by changing the \var{maxunits} constant in the \file{fmodule.pas} file of the
+% compiler, and recompiling the compiler.
+unit_f_circular_unit_reference=10020_F_Referencia circular entre unidades $1 y $2
+% Two units are using each other in the interface part. This is only allowed
+% in the \var{implementation} part. At least one unit must contain the other one
+% in the \var{implementation} section.
+unit_f_cant_compile_unit=10021_F_No se puede compilar la unidad $1, no hay código fuente disponible
+% A unit was found that needs to be recompiled, but no sources are
+% available.
+unit_f_cant_find_ppu=10022_F_No se puede encontrar la unidad $1
+% You tried to use a unit of which the PPU file isn't found by the
+% compiler. Check your configuration file for the unit paths
+unit_w_unit_name_error=10023_W_La unidad $1 no pudo ser encontrada, pero $2 existe
+unit_f_unit_name_error=10024_F_Se buscó la unidad $1 pero se encontró $2
+% Dos truncation of 8 letters for unit PPU files
+% may lead to problems when unit name is longer than 8 letters.
+unit_w_switch_us_missed=10025_W_Compilar la unidad System requiere el conmutador -Us
+% When recompiling the system unit (it needs special treatment), the
+% \var{-Us} must be specified.
+unit_f_errors_in_unit=10026_F_Hubo $1 errores compilando el modulo, parando
+% When the compiler encounters a fatal error or too many errors in a module
+% then it stops with this message.
+unit_u_load_unit=10027_U_Cargado de $1 ($2) unidad $3
+% When you use the \var{-vu} flag, which unit is loaded from which unit is
+% shown.
+unit_u_recompile_crc_change=10028_U_Recompilando $1, checksum cambiado por $2
+unit_u_recompile_source_found_alone=10029_U_Recompilando $1, solo se encontró el código fuente
+% When you use the \var{-vu} flag, these messages tell you why the current
+% unit is recompiled.
+unit_u_recompile_staticlib_is_older=10030_U_Recompilando unidad, la lib estática es más antigua que la ppu
+% When you use the \var{-vu} flag, the compiler warns if the static library
+% of the unit are older than the unit file itself.
+unit_u_recompile_sharedlib_is_older=10031_U_Recompilando unidad, la lib compartida es más antigua que la ppu
+% When you use the \var{-vu} flag, the compiler warns if the shared library
+% of the unit are older than the unit file itself.
+unit_u_recompile_obj_and_asm_older=10032_U_Recompilando unidad, obj y asm son más antiguos que ppu
+% When you use the \var{-vu} flag, the compiler warns if the assembler or
+% object file of the unit are older than the unit file itself.
+unit_u_recompile_obj_older_than_asm=10033_U_Recompilando unidad, obj es más antiguo que asm
+% When you use the \var{-vu} flag, the compiler warns if the assembler
+% file of the unit is older than the object file of the unit.
+unit_u_parsing_interface=10034_U_Interpretando interfaz de $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% parsing the interface part of the unit
+unit_u_parsing_implementation=10035_U_Interpretando implementacion de $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% parsing the implementation part of the unit
+unit_u_second_load_unit=10036_U_Segunda carga para la unidad $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% recompiling a unit for the second time. This can happend with interdepend
+% units.
+unit_u_check_time=10037_U_Chequeo de fichero PPU $1 fecha $2
+% When you use the \var{-vu} flag, the compiler show the filename and
+% date and time of the file which a recompile depends on
+### The following two error msgs is currently disabled.
+#unit_h_cond_not_set_in_last_compile=10038_H_Conditional $1 was not set at startup in last compilation of $2
+#% when recompilation of an unit is required the compiler will check that
+#% the same conditionals are set for the recompiliation. The compiler has
+#% found a conditional that currently is defined, but was not used the last
+#% time the unit was compiled.
+#unit_h_cond_set_in_last_compile=10039_H_Conditional $1 was set at startup in last compilation of $2
+#% when recompilation of an unit is required the compiler will check that
+#% the same conditionals are set for the recompiliation. The compiler has
+#% found a conditional that was used the last time the unit was compiled, but
+#% the conditional is currently not defined.
+unit_w_cant_compile_unit_with_changed_incfile=10040_W_No se pudo recompilar la unida $1, pero se encontraron ficheros de inclusió modificados
+% A unit was found to have modified include files, but
+% some source files were not found, so recompilation is impossible.
+unit_h_source_modified=10041_H_El fichero $1 es mas moderno que la versión Release del archivo PPU $2
+% A modified source file for a unit was found that was compiled with the
+% release flag (-Ur). The unit will not implicitly be recompiled because
+% this release flag is set.
+unit_u_ppu_invalid_fpumode=10042_U_Se esta utilizando una unidad que no fue compilada con el modo de FPU correcto
+% Trying to compile code while using units which were not compiled with
+% the same floating point format mode. Either all code should be compiled
+% with FPU emulation on, or with FPU emulation off.
+unit_u_loading_interface_units=10043_U_Cargando unidades de interfaz de $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% loading the units defined in the interface part of the unit.
+unit_u_loading_implementation_units=10044_U_Cargando unidades de implementación de $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% loading the units defined in the implementation part of the unit.
+unit_u_interface_crc_changed=10045_U_CRC de la interfaz de la unidad $1 cambiado
+% When you use the \var{-vu} flag, the compiler warns that it the
+% CRC calculated for the interface has been changed after the implementation
+% has been parsed.
+unit_u_implementation_crc_changed=10046_U_CRC de la implementacion de la unidad $1 cambiado
+% When you use the \var{-vu} flag, the compiler warns that it the
+% CRC calculated has been changed after the implementation
+% has been parsed.
+unit_u_finished_compiling=10047_U_Finalizando compilado de la unidad $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has finished compiling the unit.
+unit_u_add_depend_to=10048_U_Añadida dependencia de $1 a $2
+% When you use the \var{-vu} flag, the compiler warns that it
+% has added a dependency between the two units.
+unit_u_no_reload_is_caller=10049_U_No hay recarga, es llamada de: $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has will not reload the unit because it is the unit that wants
+% to load this unit
+unit_u_no_reload_in_second_compile=10050_U_No hay recarga, ya se esta en la segunda compilación de: $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has will not reload the unit because it is already in a second recompile
+unit_u_flag_for_reload=10051_U_Marcado para recarga: $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has to reload the unit
+unit_u_forced_reload=10052_U_Recarga forzada
+% When you use the \var{-vu} flag, the compiler warns that it
+% has is reloading the unit because it was required
+unit_u_previous_state=10053_U_Estado anterior de $1: $2
+% When you use the \var{-vu} flag, the compiler shows the
+% previous state of the unit
+unit_u_second_compile_unit=10054_U_Ya se está compilando $1, estableciendo segunda compilación
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% recompiling a unit for the second time. This can happend with interdepend
+% units.
+unit_u_loading_unit=10055_U_Cargando unidad $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% loading the unit.
+unit_u_finished_loading_unit=10056_U_Carga de la unidad $1 completada
+% When you use the \var{-vu} flag, the compiler warns that it finished
+% loading the unit.
+unit_u_registering_new_unit=10057_U_Registrando nueva unidad $1
+% When you use the \var{-vu} flag, the compiler warns that it has
+% found a new unit and registers it in the internal lists.
+unit_u_reresolving_unit=10058_U_Re-resolviendo unidad $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has to recalculate the internal data of the unit
+unit_u_skipping_reresolving_unit=10059_U_Saltando re-resolución de $1, aún se estan cargando las unidades utilizadas
+% When you use the \var{-vu} flag, the compiler warns that it
+% skips to recalculate the internal data of the unit because there
+% is no data to recalculate
+% \end{description}
+# EndOfTeX
+
+#
+# Options
+#
+# 11039 is the last used one
+#
+option_usage=11000_O_$1 [opciones] <fichero_entrada> [opciones]
+# BeginOfTeX
+%
+% \section{Command-line handling errors}
+% This section lists errors that occur when the compiler is processing the
+% command line or handling the configuration files.
+% \begin{description}
+option_only_one_source_support=11001_W_Solo es soportado un fichero fuente
+% You can specify only one source file on the command line. The first
+% one will be compiled, others will be ignored. This may indicate that
+% you forgot a \var{'-'} sign.
+option_def_only_for_os2=11002_W_Fichero DEF solo puede ser creado para OS/2
+% This option can only be specified when you're compiling for OS/2
+option_no_nested_response_file=11003_E_Ficheros de respuesta anidados no son soportados
+% you cannot nest response files with the \var{@file} command-line option.
+option_no_source_found=11004_F_No hay fichero fuente en la línea de comandos
+% The compiler expects a source file name on the command line.
+option_no_option_found=11005_N_No hay opciones en el archivo de configuración $1
+% The compiler didn't find any option in that config file.
+option_illegal_para=11006_E_Parámetro incorrecto: $1
+% You specified an unknown option.
+option_help_pages_para=11007_H_-? escribe las páginas de ayuda
+% When an unknown option is given, this message is diplayed.
+option_too_many_cfg_files=11008_F_Demasiados ficheros de configuración anidados
+% You can only nest up to 16 config files.
+option_unable_open_file=11009_F_Imposible abrir fichero $1
+% The option file cannot be found.
+option_reading_further_from=11010_D_Leyendo opciones adicionales de $1
+% Displayed when you have notes turned on, and the compiler switches
+% to another options file.
+option_target_is_already_set=11011_W_Destino está ya puesto a: $1
+% Displayed if more than one \var{-T} option is specified.
+option_no_shared_lib_under_dos=11012_W_Librerías compartidas no soportadas en la plataforma DOS, regresando a estáticas
+% If you specify \var{-CD} for the \dos platform, this message is displayed.
+% The compiler supports only static libraries under \dos
+option_too_many_ifdef=11013_F_demasiados IF(N)DEFs
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_too_many_endif=11014_F_demasiados ENDIFs
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_too_less_endif=11015_F_condicional abierto al final del fichero
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_no_debug_support=11016_W_La generación de información de depuración no es soportada por este ejecutable
+% It is possible to have a compiler executable that doesn't support
+% the generation of debugging info. If you use such an executable with the
+% \var{-g} switch, this warning will be displayed.
+option_no_debug_support_recompile_fpc=11017_H_Prueba recompilando con -dGDB
+% It is possible to have a compiler executable that doesn't support
+% the generation of debugging info. If you use such an executable with the
+% \var{-g} switch, this warning will be displayed.
+option_obsolete_switch=11018_E_Estas usando el conmutador obsoleto $1
+% this warns you when you use a switch that is not needed/supported anymore.
+% It is recommended that you remove the switch to overcome problems in the
+% future, when the switch meaning may change.
+option_obsolete_switch_use_new=11019_E_Estás usando el conmutador obsoleto $1, porfavor usa $2
+% this warns you when you use a switch that is not supported anymore. You
+% must now use the second switch instead.
+% It is recommended that you change the switch to overcome problems in the
+% future, when the switch meaning may change.
+option_switch_bin_to_src_assembler=11020_N_Cambiando a ensamblador de escritura de código fuente por defecto
+% this notifies you that the assembler has been changed because you used the
+% -a switch which can't be used with a binary assembler writer.
+option_incompatible_asm=11021_W_La salida de ensamblador "$1" no es compatible con "$2"
+option_asm_forced=11022_W_Forzado el uso de ensamblador "$1"
+% The assembler output selected can not generate
+% object files with the correct format. Therefore, the
+% default assembler for this target is used instead.
+option_using_file=11026_T_Leyendo opciones del fichero $1
+% Options are also read from this file
+option_using_env=11027_T_Leyendo opciones del entorno $1
+% Options are also read from this environment string
+option_handling_option=11028_D_Procesando pción "$1"
+% Debug info that an option is found and will be handled
+option_help_press_enter=11029__*** presione retorno ***
+option_start_reading_configfile=11030_H_Inicio de lectura del archivo de configuración $1
+% Starting of config file parsing.
+option_end_reading_configfile=11031_H_Fin de lectura del archivo de configuración $1
+% End of config file parsing.
+option_interpreting_option=11032_D_Interpretando opción "$1"
+option_interpreting_firstpass_option=11036_D_Interpretando primera pasada de la opción "$1"
+option_interpreting_file_option=11033_D_Interpretando opción de archivo "$1"
+option_read_config_file=11034_D_Leyendo archivo de configuración "$1"
+option_found_file=11035_D_encontrado nombre del archivo fuente "$1"
+% Additional infos about options, displayed
+% when you have debug option turned on.
+option_code_page_not_available=11039_E_Código de página desconocido
+%\end{description}
+# EndOfTeX
+
+#
+# Logo (option -l)
+#
+option_logo=11023_[
+Free Pascal Compiler version $FPCFULLVERSION [$FPCDATE] for $FPCCPU
+Copyright (c) 1993-2011 by Florian Klaempfl
+]
+
+#
+# Info (option -i)
+#
+option_info=11024_[
+Free Pascal Compiler versión $FPCVERSION
+
+Fecha del Compilador : $FPCDATE
+CPU de destino : $FPCCPU
+
+Plataformas soportadas:
+ $OSTARGETS
+
+Sets de instrucciones de la CPU soportados:
+ $INSTRUCTIONSETS
+
+Sets de instrucciones de la FPU soportados:
+ $FPUINSTRUCTIONSETS
+
+Este programa esta bajo la licencia GNU General Public Licence
+Para mas informació lea COPYING.FPC
+
+Para informar de errores, sugerencias, etc:
+ http://bugs.freepascal.org
+o
+ bugs@freepascal.org
+]
+
+#
+# Help pages (option -? and -h)
+#
+# The first character on the line indicates who will display this
+# line, the current possibilities are :
+# * = every target
+# 3 = 80x86 targets
+# 6 = 680x0 targets
+# e = in extended debug mode only
+# P = PowerPC targets
+# S = Sparc targets
+# V = Virtual machine targets
+# The second character also indicates who will display this line,
+# (if the above character was TRUE) the current possibilities are :
+# * = everyone
+# g = with GDB info supported by the compiler
+# O = OS/2
+# L = UNIX systems
+# The third character represents the indentation level.
+#
+option_help_pages=11025_[
+**0*_ponga + tras un conmutador booleano para activarlo, - para desactivarlo
+**1a_el compilador no borra los ficheros de ensamblador generados
+**2al_incluir los números de línea del codigo fuente en el archivo ensamblador
+**2an_incluir la informacion de nodos en el archivo ensamblador generado
+*L2ap_usar tuberías (pipes) en lugar de crear archivos de ensamblado temporales
+**2ar_incluir reserva y liberació de registros en el archivo ensamblador
+**2at_incluir informacion de reserva y liberación temporales en el archivo ensamblador
+**1A<x>_formato de salida:
+**2Adefault_usar ensamblador por defecto
+3*2Aas_ensamblar usando GNU AS
+3*2Anasmcoff_coff (Go32v2) usando Nasm
+3*2Anasmelf_elf32 (Linux) usando Nasm
+3*2Anasmwin32_objeto Win32 usando Nasm
+3*2Anasmwdosx_objeto Win32/WDOSX usando Nasm
+3*2Awasm_fichero obj usando Wasm (Watcom)
+3*2Anasmobj_fichero obj usando Nasm
+3*2Amasm_fichero obj usando Masm (Microsoft)
+3*2Atasm_fichero obj usando Tasm (Borland)
+3*2Aelf_elf32 (Linux) usando escritor interno
+3*2Acoff_coff (Go32v2) usando escritor interno
+3*2Apecoff_pecoff (Win32) usando escritor interno
+4*2Aas_ensamblar usando GNU AS
+6*2Aas_archivo o de Unix usando GNU AS
+6*2Agas_ensamblador GNU Motorola
+6*2Amit_Sintaxis MIT (GAS antiguo)
+6*2Amot_Ensamblador Motorola estándar
+A*2Aas_ensamblar usando GNU AS
+P*2Aas_ensamblar usando GNU AS
+S*2Aas_ensamblar usando GNU AS
+**1b_generar informacion de navegado
+**2bl_generar informació de símbolos locales
+**1B_construir(build) todos los modulos
+**1C<x>_opciones de generado de código:
+**2Cc<x>_cambiar la convencion de llamada por defecto a <x>
+**2CD_crear adicionalmente una librería dinámica (no soportado)
+**2Ce_Compilar con opcodes de punto flotante emulados
+**2Cf<x>_Cambiar el set de instrucciones de la FPU usado, fpc -i para posibles valores<x>
+**2Cg_Generar código PIC
+**2Ch<n>_<n> bytes heap (entre 1023 y 67107840)
+**2Ci_Comprobación de E/S
+**2Cn_omitir etapa de enlazado
+**2Co_comprobar desbordamiento en operaciones de enteros
+**2Cp<x>_Cambiar el set de instrucciones usado, fpc -i para posibles valores
+**2Cr_comprobación de rango
+**2CR_verificar validez de objetos de llamada
+**2Cs<n>_definir el tamaño de la pila a <n>
+**2Ct_comprobación de pila
+**2CX_crear adicionalmente una librerí con enlazado inteligente
+**1d<x>_define el símbol <x>
+**1D_generar fichero DEF
+**2Dd<x>_establece la descripción a <x>
+**2Dv<x>_establece la version de la DLL a <x>
+*O2Dw_Aplicación PM
+**1e<x>_establecer ruta al ejecutable
+**1E_igual que -Cn
+**1F<x>_establecer ficheros y rutas:
+**2Fa<x>[,y]_para hacer que el programa cargue las unidades <x> e [y] antes de procesar su uses
+**2Fc<x>_establece el código de pagina de la entrada a <x>
+**2FD<x>_establece la ruta donde buscar las utilidades del compilador
+**2Fe<x>_redirige la salida de errores a <x>
+**2FE<x>_establece la ruta de destino de exe/unidades a <x>
+**2Fi<x>_añade <x> a las rutas de inclusión
+**2Fl<x>_añade <x> a las rutas de librerías
+**2FL<x>_usa <x> como enlazador dinámico
+**2Fo<x>_añade <x> a las rutas de objetos
+**2Fr<x>_load error message file <x>
+**2Fu<x>_adds <x> a las rutas de unidades
+**2FU<x>_establece la ruta de salida de unidades a <x>, reemplaza -FE anteriores
+*g1g_generar información de depurado:
+*g2gc_generar comprobación de punteros
+*g2gd_usar dbx
+*g2gg_usar gsym
+*g2gh_usar unidad de trazado de memoria (para depurar pérdidas de memoria)
+*g2gl_usar informacion de líneas de las unidades para la traza de ejecución (backtrace)
+*g2gv_genera programas trazables con valgrind
+*g2gw_generar información de depurado dwarf
+**1i_información
+**2iD_devuelve la fecha del compilador
+**2iV_devuelve la versión del compilador
+**2iSO_devuelve el SO del compilador
+**2iSP_devuelve el procesador del compilador
+**2iTO_devuelve el SO de destino
+**2iTP_devuelve el procesador de destino
+**1I<x>_añade <x> a las rutas de iclusión
+**1k<x>_Pasar <x> al enlazador
+**1l_mostrar logo
+**1M<x>_establecer modo del lenguaje a <x>
+**2Mfpc_dialecto de free pascal(default)
+**2Mobjfpc_activar algunas extensiones de Delphi 2
+**2Mdelphi_tratar de ser compatible con Delphi
+**2Mtp_tratar de ser compatible con TP/BP 7.0
+**2Mgpc_tratar de ser compatible con gpc
+**2Mmacpas_tratar de ser compatible con dialectos de macintosh pascal
+**1n_no leer la configuración por defecto
+**1o<x>_cambiar el nombre del ejecutable producido a <x>
+**1O<x>_optimizaciones:
+3*2Og_generar código más pequeño
+3*2OG_generar código más rápido (defecto)
+**2Or_mantener algunas variables en registros
+3*2Ou_activar optimizaciones inseguras (ver docs)
+3*2O1_optimizaciones nivel 1 (optimizaciones rápidas)
+3*2O2_optimizaciones nivel 2 (-O1 + optimizaciones más lentas)
+3*2O3_optimizaciones nivel 3 (-O2 repetidamente, max 5 veces)
+3*2Op<x>_procesador de destino:
+3*3Op1_establecer procesador de destino a 386/486
+3*3Op2_establecer procesador de destino a Pentium/PentiumMMX (tm)
+3*3Op3_establecer procesador de destino a PPro/PII/c6x86/K6 (tm)
+6*2Og_generar código más pequeño
+6*2OG_generatr código más rápido (defecto)
+6*2Ox_optimizar al máximo (AUN CON ERRORES!!!)
+6*2O0_establecer procesador de destino a MC68000
+6*2O2_establecer procesador de destino a MC68020+ (defecto)
+**1pg_generar código de perfilado gprof (define FPC_PROFILE)
+**1R<x>_estilo de lectura de ensamblador:
+**2Rdefault_usar ensamblador por defecto
+3*2Ratt_leer ensamblador estilo AT&T
+3*2Rintel_leer ensamblador estilo Intel
+6*2RMOT_leer ensamblador estilo motorola
+**1S<x>_opciones de sintaxis:
+**2S2_igual que -Mobjfpc
+**2Sc_soportar operadores estilo C (*=,+=,/= and -=)
+**2Sa_incluir código de aserción.
+**2Sd_igual que -Mdelphi
+**2Se<x>_opciones de error. <x> es una combinación de los siguientes:
+**3*_<n> : detener el compilador tras <n> errores (por defecto 1)
+**3*_w : detener también tras avisos
+**3*_n : detener también tras notas
+**3*_h : detener también tras consejos
+**2Sg_permitir LABEL y GOTO
+**2Sh_Usar cadenas largas (ansistrings)
+**2Si_soportar INLINE estilo C++
+**2SI<x>_establecer estilo de interfaz a <x>
+**3SIcom_interfaces compatibles COM (defecto)
+**3SIcorba_interfaces compatibles CORBA
+**2Sm_soportar macros tipo C (global)
+**2So_igual que -Mtp
+**2Sp_igual que -Mgpc
+**2Ss_el nombre del constructor debe ser init (el destructor debe ser done)
+**1s_no llamar al ensamblador ni enlazador
+**2sh_Generar script para enlazar en host
+**2st_Generar script para enlazar en destino
+**2sr_Saltar fase de reserva de registros (usar con -alr)
+**1T<x>_Sistema operativo de destino:
+3*2Temx_OS/2 usando EMX (incluyendo extensor EMX/RSX)
+3*2Tfreebsd_FreeBSD
+3*2Tgo32v2_Version 2 de DJ Delorie DOS extender
+3*2Tlinux_Linux
+3*2Tnetbsd_NetBSD
+3*2Tnetware_Novell Netware Module (clib)
+3*2Tnetwlibc_Novell Netware Module (libc)
+3*2Topenbsd_OpenBSD
+3*2Tos2_OS/2 / eComStation
+3*2Tsunos_SunOS/Solaris
+3*2Twatcom_extensor DOS compatible Watcom
+3*2Twdosx_extensor WDOSX DOS
+3*2Twin32_Windows 32 Bit
+4*2Tlinux_Linux
+6*2Tamiga_Commodore Amiga
+6*2Tatari_Atari ST/STe/TT
+6*2Tlinux_Linux-68k
+6*2Tmacos_Macintosh m68k (no soportado)
+6*2Tpalmos_PalmOS
+A*2Tlinux_Linux
+P*2Tdarwin_Darwin y MacOS X en PowerPC
+P*2Tlinux_Linux en PowerPC
+P*2Tmacos_MacOS (clásico) en PowerPC
+P*2Tmorphos_MorphOS
+S*2Tlinux_Linux
+**1u<x>_elimina la definición del símbolo <x>
+**1U_opciones de unidad:
+**2Un_no comprobar el nombre de la unidad
+**2Ur_generar unidades para distribución (release)
+**2Us_compilar la unidad System
+**1v<x>_Mostrar detalles. <x> es una combinación de las siguientes letras:
+**2*_e : Mostrar errores (defecto) 0 : No mostrar nada (excepto errores)
+**2*_w : Mostrar avisos u : Mostrar info. de la unidad
+**2*_n : Mostrar notas t : Mostrar archivos usados / intentados
+**2*_h : Mostrar consejos c : Mostrar condicionales
+**2*_i : Mostrar info. general d : Mostrar info. de depurado
+**2*_l : Mostrar num de lineas r : Modo compatible con Rhide/GCC
+**2*_a : Mostrar todo x : Info. del ejecutable (Win32 solo)
+**2*_v : escribe fpcdebug.txt con p : Escribir el árbol de parser en tree.log
+**2*_ mucha informacón de depurado
+3*1W<x>_opciones de Win32 o similares
+3*2WB<x>_Establece la dirección hex de base a <x>
+3*2WC_Especifica que la aplicación es de consola
+3*2WD_Usa DEFFILE para exportar funciones de la DLL o EXE
+3*2WF_Especifica aplicación de pantalla completa (OS/2 sólo)
+3*2WG_Especifica que la aplicación es para entorno gráfico
+3*2WN_No generar código de reubicación (necesario para depurar)
+3*2WR_Generar código de reubicación
+P*2WC_Especifica aplicación de colnsola (MacOS sólo)
+P*2WG_Especifica aplicación gráfica (MacOS sólo)
+P*2WT_Especifica aplicación de tipo herramienta (herramienta MPW, MacOS sólo)
+**1X_opciones de ejecutable:
+**2Xc_pasar --shared al enlazador (Unix sólo)
+**2Xd_no utilizar la ruta de librería por defecto (necesario para compilación cruzada)
+**2XD_tratar de enlazar dinámicamente (define FPC_LINK_DYNAMIC)
+**2XP<x>_pone <x> delante de los nombres de binutils
+**2Xr<x>_establece la ruta de librerías a <x> (necesario para compilación cruzada)
+**2Xs_eliminar todos los símbolos del ejecutable
+**2XS_tratar de enlazar estáticamente (defecto) (define FPC_LINK_STATIC)
+**2Xt_enlazar con librerias estáticas (-static es pasado al enlazador)
+**2XX_tratar de enlazar inteligentemente (define FPC_LINK_SMART)
+**1*_
+**1?_muestra esta ayuda
+**1h_muestra esta ayuda sin esperas
+]
+
+#
+# The End...
diff --git a/closures/compiler/msg/errorf.msg b/closures/compiler/msg/errorf.msg
new file mode 100644
index 0000000000..fe00908011
--- /dev/null
+++ b/closures/compiler/msg/errorf.msg
@@ -0,0 +1,1899 @@
+#
+# This file is part of the Free Pascal Compiler
+# Copyright (c) 1998-2000 by the Free Pascal Development team
+#
+# French (cp850) Language File for Free Pascal
+#
+# See the file COPYING.FPC, included in this distribution,
+# for details about the copyright.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#
+#
+# The constants are build in the following order:
+# <part>_<type>_<txtidentifier>
+#
+# <part> is the part of the compiler the message is used
+# asmr_ assembler parsing
+# asmw_ assembler writing/binary writers
+# unit_ unit handling
+# scan_ scanner
+# parser_ parser
+# type_ type checking
+# general_ general info
+# exec_ calls to assembler, linker, binder
+#
+# <type> the type of the message it should normally used for
+# f_ fatal error
+# e_ error
+# w_ warning
+# n_ note
+# h_ hint
+# i_ info
+# l_ linenumber
+# u_ used
+# t_ tried
+# m_ macro
+# p_ procedure
+# c_ conditional
+# d_ debug message
+# b_ display overloaded procedures
+# x_ executable informations
+#
+
+#
+# General
+#
+# BeginOfTeX
+% \section{General compiler messages}
+% This section gives the compiler messages which are not fatal, but which
+% display useful information. The number of such messages can be
+% controlled with the various verbosity level \var{-v} switches.
+% \begin{description}
+general_t_compilername=01000_T_Compilateur : $1
+% When the \var{-vt} switch is used, this line tells you what compiler
+% is used.
+general_d_sourceos=01001_D_SystŠme d'exploitation source : $1
+% When the \var{-vd} switch is used, this line tells you what the source
+% operating system is.
+general_i_targetos=01002_I_SystŠme d'exploitation cible : $1
+% When the \var{-vd} switch is used, this line tells you what the target
+% operating system is.
+general_t_exepath=01003_T_R‚pertoire pour fichiers executables : $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for its binaries.
+general_t_unitpath=01004_T_R‚pertoire de recherche d'unit‚s : $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for compiled units. You can set this path with the \var{-Fu}
+general_t_includepath=01005_T_R‚pertoire pour recherche de fichiers inclus : $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for its include files (files used in \var{\{\$I xxx\}} statements).
+% You can set this path with the \var{-I} option.
+general_t_librarypath=01006_T_R‚pertoire pour librairies : $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for the libraries. You can set this path with the \var{-Fl} option.
+general_t_objectpath=01007_T_R‚pertoire pour fichiers objets : $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for object files you link in (files used in \var{\{\$L xxx\}} statements).
+% You can set this path with the \var{-Fo} option.
+general_i_abslines_compiled=01008_I_$1 lignes compil‚es, $2 secondes
+% When the \var{-vi} switch is used, the compiler reports the number
+% of lines compiled, and the time it took to compile them (real time,
+% not program time).
+general_f_no_memory_left=01009_F_Plus de m‚moire disponible
+% The compiler doesn't have enough memory to compile your program. There are
+% several remedies for this:
+% \begin{itemize}
+% \item If you're using the build option of the compiler, try compiling the
+% different units manually.
+% \item If you're compiling a huge program, split it up in units, and compile
+% these separately.
+% \item If the previous two don't work, recompile the compiler with a bigger
+% heap (you can use the \var{-Ch} option for this, \seeo{Ch})
+% \end{itemize}
+% \end{description}
+#
+# Scanner
+#
+% \section{Scanner messages.}
+% This section lists the messages that the scanner emits. The scanner takes
+% care of the lexical structure of the pascal file, i.e. it tries to find
+% reserved words, strings, etc. It also takes care of directives and
+% conditional compiling handling.
+% \begin{description}
+general_i_writingresourcefile=01010_I_Ecriture du fichier Resource : $1
+% This message is shown when the compiler writes the Resource String Table
+% file containing all the resource strings for a program.
+general_e_errorwritingresourcefile=01011_E_Ecriture du fichier Resource String Table : $1
+% This message is shown when the compiler encountered an error when writing
+% the Resource String Table file
+% \end{description}
+#
+# Scanner
+#
+% \section{Scanner messages.}
+% This section lists the messages that the scanner emits. The scanner takes
+% care of the lexical structure of the pascal file, i.e. it tries to find
+% reserved words, strings, etc. It also takes care of directives and
+% conditional compiling handling.
+% \begin{description}
+scan_f_end_of_file=02000_F_Fin de fichier inattendue
+% this typically happens in on of the following cases :
+% \begin{itemize}
+% \item The source file ends befor then final \var{end.} statement. This
+% happens mostly when the \var{begin} and \var{end} statements aren't
+% balanced;
+% \item An include file ends in the middle of a statement.
+% \item A comment wasn't closed.
+% \end{itemize}
+scan_f_string_exceeds_line=02001_F_String au-del… de la fin de ligne
+% You forgot probably to include the closing ' in a string, so it occupies
+% multiple lines.
+scan_f_illegal_char=02002_F_caractŠre ill‚gal
+% An illegal character was encountered in the input file.
+scan_f_syn_expected=02003_F_Erreur de syntaxe, $1 attendu mais $2 trouv‚
+% This indicates that the compiler expected a different token than
+% the one you typed. It can occur almost everywhere where you make a
+% mistake against the pascal language.
+scan_t_start_include_file=02004_T_D‚but de lecture du fichier inclus $1
+% When you provide the \var{-vt} switch, the compiler tells you
+% when it starts reading an included file.
+scan_w_comment_level=02005_W_Commentaire de niveau $1
+% When the \var{-vw} switch is used, then the compiler warns you if
+% it finds nested comments. Nested comments are not allowed in Turbo Pascal
+% and can be a possible source of errors.
+scan_n_far_directive_ignored=02006_N_$F directive (FAR) ignor‚e
+% The \var{FAR} directive is a 16-bit construction which is recorgnised
+% but ignored by the compiler, since it produces 32 bit code.
+scan_n_stack_check_global_under_linux=02007_N_Le controle de la gestion de la pile est global sous Linux
+% Stack checking with the \var{-Cs} switch is ignored under \linux, since
+% \linux does this for you. Only displayed when \var{-vn} is used.
+scan_n_ignored_switch=02008_N_Switch "$1" ignor‚
+% With \var{-vn} on, the compiler warns if it ignores a switch
+scan_w_illegal_switch=02009_W_Switch "$1" ill‚gal
+% You included a compiler switch (i.e. \var{\{\$... \}}) which the compiler
+% doesn't know.
+scan_w_switch_is_global=02010_W_Ce switch a un effet global
+% When \var{-vw} is used, the compiler warns if a switch is global.
+scan_e_illegal_char_const=02011_E_Constante de type char ill‚gale
+% This happens when you specify a character with its ASCII code, as in
+% \var{\#96}, but the number is either illegal, or out of range. The range
+% is 1-255.
+scan_f_cannot_open_input=02012_F_Impossible d'ouvrir le fichier $1
+% \fpc cannot find the program or unit source file you specified on the
+% command line.
+scan_f_cannot_open_includefile=02013_F_Impossible d'ouvrir le fichier inclus $1
+% \fpc cannot find the source file you specified in a \var{\{\$include \}}
+% stateent.
+scan_e_too_much_endifs=02014_E_Trop de $ENDIFs ou de $ELSEs
+% Your \var{\{\$IFDEF ..\}} and {\{\$ENDIF\}} statements aren't balanced.
+scan_w_only_pack_records=02015_W_L'alignement des Records peut uniquement ˆtre de 1,2,4,8 ou 16 bytes
+% You are specifying the \var{\{\$PACKRECORDS n\} } with an illegal value for
+% \var{n}. Only 1,2,4 or 16 are valid in this case.
+scan_w_only_pack_enum=02016_W_Les ‚numerations peuvent seulement ˆtre sauvegard‚s en 1,2 ou 4 bytes
+% You are specifying the \var{\{\$PACKENUM n\}} with an illegal value for
+% \var{n}. Only 1,2 or 4 are valid in this case.
+scan_e_endif_expected=02017_E_$1 attendu pour $2 d‚fini … la ligne $3
+% Your conditional compilation statements are unbalanced.
+scan_e_preproc_syntax_error=02018_E_Erreur de syntaxe pendant l'interpr‚tation d'une directive de compilation
+% There is an error in the expression following the \var{\{\$if \}} compiler
+% directive.
+scan_e_error_in_preproc_expr=02019_E_Erreur d'‚valuation d'une directive de compilation
+% There is an error in the expression following the \var{\{\$if \}} compiler
+% directive.
+scan_w_macro_cut_after_255_chars=02020_W_Le contenu d'une macro est tronqu‚ … 255 caractŠres
+% The contents of macros cannot be longer than 255 characters. This is a
+% safety in the compiler, to prevent buffer overflows. This is shown as a
+% warning, i.e. when the \var{-vw} switch is used.
+scan_e_endif_without_if=02021_E_ENDIF sans IF(N)DEF
+% Your \var{\{\$IFDEF ..\}} and {\{\$ENDIF\}} statements aren't balanced.
+scan_f_user_defined=02022_F_D‚fini par l'utilisateur : $1
+% A user defined fatal error occurred. see also the \progref
+scan_e_user_defined=02023_E_D‚fini par l'utilisateur : $1
+% A user defined error occurred. see also the \progref
+scan_w_user_defined=02024_W_D‚fini par l'utilisateur : $1
+% A user defined warning occurred. see also the \progref
+scan_n_user_defined=02025_N_D‚fini par l'utilisateur : $1
+% A user defined note was encountered. see also the \progref
+scan_h_user_defined=02026_H_D‚fini par l'utilisateur : $1
+% A user defined hint was encountered. see also the \progref
+scan_i_user_defined=02027_I_D‚fini par l'utilisateur : $1
+% User defined information was encountered. see also the \progref
+scan_e_keyword_cant_be_a_macro=02028_E_Impossible de redefinir un mot r‚serv‚
+% You cannot redefine keywords with macros.
+scan_f_macro_buffer_overflow=02029_F_D‚bordement du buffer de la macro en lecture ou expansion
+% Your macro or its result was too long for the compiler.
+scan_w_macro_deep_ten=02030_W_L'expansion des macros d‚passe un niveau de 16.
+% When expanding a macro macros have been nested to a level of 16.
+% The compiler will expand no further, since this may be a sign that
+% recursion is used.
+scan_e_wrong_styled_switch=02031_E_Les directives de compilation entre (* ... *) ne sont pas accept‚es
+% Compiler switches should always be between \var{\{ \}} comment delimiters.
+scan_d_handling_switch=02032_D_Interpr‚tation switch "$1"
+% When you set debugging info on (\var{-vd}) the compiler tells you when it
+% is evaluating conditional compile statements.
+scan_c_endif_found=02033_C_ENDIF $1 trouv‚
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifdef_found=02034_C_IFDEF $1 trouv‚, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifopt_found=02035_C_IFOPT $1 trouv‚, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_if_found=02036_C_IF $1 trouv‚, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifndef_found=02037_C_IFNDEF $1 trouv‚, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_else_found=02038_C_ELSE $1 trouv‚, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_skipping_until=02039_C_Passant jusqu'…...
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements, and whether it is skipping or
+% compiling parts.
+scan_i_press_enter=02040_I_Appuyez sur <Entr‚e> pour continuer
+% When the \var{-vi} switch is used, the compiler stops compilation
+% and waits for the \var{Enter} key to be pressed when it encounters
+% a \var{\{\$STOP\}} directive.
+scan_w_unsupported_switch=02041_W_Switch non support‚ $1
+% When warings are turned on (\var{-vw}) the compiler warns you about
+% unsupported switches. This means that the switch is used in Delphi or
+% Turbo Pascal, but not in \fpc
+scan_w_illegal_directive=02042_W_directive de compilation ill‚gale $1
+% When warings are turned on (\var{-vw}) the compiler warns you about
+% unrecognised switches. For a list of recognised switches, \progref
+scan_t_back_in=02043_T_De retour dans $1
+% When you use (\var{-vt}) the compiler tells you when it has finished
+% reading an include file.
+scan_w_unsupported_app_type=02044_W_Type d'application non support‚e : $1
+% You get this warning, if you specify an unknown application type
+% with the directive $APPTYPE
+scan_w_app_type_not_support=02045_W_$APPTYPE non support‚ par OS cible
+% The $APPTYPE directive is supported by win32 applications only
+scan_w_decription_not_support=02046_W_DESCRIPTION est support‚ seulement pour OS2 et Win32
+% The \var{\{\$DESCRIPTION\}} directive is only supported for OS2 and Win32 targets.
+scan_n_version_not_support=02047_N_VERSION non support‚ par OS cible
+% The \var{\{\$VERSION\}} directive is only supported by win32 target.
+scan_n_only_exe_version=02048_N_VERSION seulement pour exes ou DLLs
+% The \var{\{\$VERSION\}} directive is only used for executable or DLL sources.
+scan_w_wrong_version_ignored=02049_W_Mauvais format de la directive VERSION $1
+% The \var{\{\$VERSION\}} directive format is major_version.minor_version
+% where major_version and minor_version are words.
+scan_w_unsupported_asmmode_specifier=02050_W_Style assembleur non support‚ $1
+% When you specify an assembler mode with the \var{\{\$ASMMODE xxx\}}
+% the compiler didn't recognize the mode you specified.
+scan_w_no_asm_reader_switch_inside_asm=02051_W_Changement de type d'interpr‚teur ASM … l'int‚rieur de code assembleur, $1 sera effectif seulement pour le prochain
+% It is not possible to switch from one assembler reader to another
+% inside an assmebler block. The new reader will be used for next
+% assembler statement only.
+scan_e_wrong_switch_toggle=02052_E_Mauvais argument de switch, utilisez ON/OFF ou +/-
+% You need to use ON or OFF or a + or - to toggle the switch
+scan_e_resourcefiles_not_supported=02053_E_Fichiers ressource non support‚ pour cette cible
+% The target you are compiling for doesn't support Resource files. The
+% only target which can use resource files is Win32
+scan_w_include_env_not_found=02054_W_Include pour variable d'environment $1 non trouv‚
+% The included environment variable can't be found in the environment, it'll
+% be replaced by an empty string instead.
+scan_e_invalid_maxfpureg_value=02055_E_Valeur invalide pour nombre limite de variables en registre FPU
+% Valid values for this directive are 0..8 and NORMAL/DEFAULT
+% \end{description}
+#
+# Parser
+#
+% \section{Parser messages}
+% This section lists all parser messages. The parser takes care of the
+% semantics of you language, i.e. it determines if your pascal constructs
+% are correct.
+% \begin{description}
+scan_w_only_one_resourcefile_supported=02056_W_Un fichier ressource est seulement support‚ pour cette cible
+% Only one resource file can be supported for this target - this is the case of
+% OS/2 (EMX) currently. The first one found is used, the others are discarded.
+%
+% \end{description}
+#
+# Parser
+#
+% \section{Parser messages}
+% This section lists all parser messages. The parser takes care of the
+% semantics of you language, i.e. it determines if your pascal constructs
+% are correct.
+% \begin{description}
+parser_e_syntax_error=03000_E_Parseur - Erreur de syntaxe
+% An error against the Turbo Pascal language was encountered. This happens
+% typically when an illegal character is found in the sources file.
+parser_w_proc_far_ignored=03001_W_Directive pour proc‚dure FAR ignor‚
+% This is a warning. \var{FAR} is a construct for 8 or 16 bit programs. Since
+% the compile generates 32 bit programs, it ignores this directive.
+parser_w_proc_near_ignored=03002_W_Directive pour proc‚dure NEAR ignor‚
+% This is a warning. \var{NEAR} is a construct for 8 or 16 bit programs. Since
+% the compile generates 32 bit programs, it ignores this directive.
+parser_w_proc_interrupt_ignored=03003_W_Directive pour proc‚dure INTERRUPT ignor‚
+% This is a warning. \var{INTERRUPT} is a i386 specific construct
+% and is igonred for other processors.
+parser_e_dont_nest_interrupt=03004_E_Une proc‚dure de type INTERRUPT ne peut ˆtre locale
+% An \VAR{INTERRUPT} procedure must be global.
+parser_w_proc_directive_ignored=03005_W_Procedure type $1 ignored
+% This is a warning. \var{REGISTER},\var{REINTRODUCE} is ignored by FPC programs for now.
+% This is introduced first for Delphi compatibility.
+parser_e_no_overload_for_all_procs=03006_E_Not all declarations of $1 are declared with OVERLOAD
+% When you want to use overloading using the \var{OVERLOAD} directive, then
+% all declarations need to have \var{OVERLOAD} specified.
+parser_e_no_dll_file_specified=03007_E_Pas de fichier DLL sp‚cifi‚
+% No longer in use.
+parser_e_export_name_double=03008_E_Nom de fonction export‚e doubl‚ $1
+% Exported function names inside a specific DLL must all be different
+parser_e_export_ordinal_double=03009_E_Index de fonction export‚e doubl‚ $1
+% Exported function names inside a specific DLL must all be different
+parser_e_export_invalid_index=03010_E_Index non valide pour fonction export‚e
+% DLL function index must be in the range 1..$FFFF
+parser_w_parser_reloc_no_debug=03011_W_Les DLL ou EXE relogeables sont incompatibles avec les informations de d‚bogage, d‚bogage d‚sactiv‚.
+parser_w_parser_win32_debug_needs_WN=03012_W_Pour permettre le d‚bogage de code win32, utilisez l'option -WN
+% Stabs info is wrong for relocatable DLL or EXES use -WN
+% if you want to debug win32 executables.
+parser_e_constructorname_must_be_init=03013_E_Le nom du constructeur doit ˆtre INIT
+% You are declaring a constructor with a name which isn't \var{init}, and the
+% \var{-Ss} switch is in effect. See the \var{-Ss} switch (\seeo{Ss}).
+parser_e_destructorname_must_be_done=03014_E_Le nom du destructeur doit ˆtre DONE
+% You are declaring a constructor with a name which isn't \var{done}, and the
+% \var{-Ss} switch is in effect. See the \var{-Ss} switch (\seeo{Ss}).
+parser_e_illegal_open_parameter=03015_E_ParamŠtre ouvert non valide
+% You are trying to use the wrong type for an open parameter.
+parser_e_proc_inline_not_supported=03016_E_Directive de fonction INLINE non support‚e
+% You tried to compile a program with C++ style inlining, and forgot to
+% specify the \var{-Si} option (\seeo{Si}). The compiler doesn't support C++
+% styled inlining by default.
+parser_w_priv_meth_not_virtual=03017_W_Les m‚thodes priv‚es ne devraient pas ˆtre virutelles
+% You declared a method in the private part of a object (class) as
+% \var{virtual}. This is not allowed. Private methods cannot be overridden
+% anyway.
+parser_w_constructor_should_be_public=03018_W_Le constructeur devrait ˆtre public
+% Constructors must be in the 'public' part of an object (class) declaration.
+parser_w_destructor_should_be_public=03019_W_Le destructeur devrait ˆtre public
+% Destructors must be in the 'public' part of an object (class) declaration.
+parser_n_only_one_destructor=03020_N_Les classes ne devraient avoir qu'un selu destructeur
+% You can declare only one destructor for a class.
+parser_e_no_local_objects=03021_E_Les D‚finitions locales de classes ne sont pas autoris‚es
+% Classes must be defined globally. They cannot be defined inside a
+% procedure or function
+parser_f_no_anonym_objects=03022_F_Les d‚finitions de classes anonymes sont interdites
+% An invalid object (class) declaration was encountered, i.e. an
+% object or class without methods that isn't derived from another object or
+% class. For example:
+% \begin{verbatim}
+% Type o = object
+% a : longint;
+% end;
+% \end{verbatim}
+% will trigger this error.
+parser_object_has_no_vmt=03023_E_L'object $1 n'a pas de table de m‚thodes virtuelles (VMT)
+parser_e_illegal_parameter_list=03024_E_Liste de paramŠtres ill‚gale
+% You are calling a function with parameters that are of a different type than
+% the declared parameters of the function.
+parser_e_wrong_parameter_type=03025_E_Mauvais type pour paramŠtre #$1
+% There is an error in the parameter list of the function or procedure.
+% The compiler cannot determine the error more accurate than this.
+parser_e_wrong_parameter_size=03026_E_Mauvais nombre de paramŠtres sp‚cifi‚
+% There is an error in the parameter list of the function or procedure,
+% the number of parameters is not correct.
+parser_e_overloaded_no_procedure=03027_E_L'identificateur surcharg‚ $1 n'est pas une fonction
+% The compiler encountered a symbol with the same name as an overloaded
+% function, but it isn't a function it can overload.
+parser_e_overloaded_have_same_parameters=03028_E_Les fonctions surcharg‚es ont les mˆmes paramŠtres
+% You're declaring overloaded functions, but with the same parameter list.
+% Overloaded function must have at least 1 different parameter in their
+% declaration.
+parser_e_header_dont_match_forward=03029_E_L'entˆte de la fonction ne correspond pas … la d‚claration $1
+% You declared a function with same parameters but
+% different result type or function specifiers.
+parser_e_header_different_var_names=03030_E_L'entˆte de la fonction $1 ne correspond pas … la d‚claration : le nom de variable change $2 => $3
+% You declared the function in the \var{interface} part, or with the
+% \var{forward} directive, but define it with a different parameter list.
+parser_n_duplicate_enum=03031_N_Les valeurs d'une ‚num‚ration doivent ˆtre en ordre ascendant
+% \fpc allows enumeration constructions as in C. Given the following
+% declaration two declarations:
+% \begin{verbatim}
+% type a = (A_A,A_B,A_E:=6,A_UAS:=200);
+% type a = (A_A,A_B,A_E:=6,A_UAS:=4);
+% \end{verbatim}
+% The second declaration would produce an error. \var{A\_UAS} needs to have a
+% value higher than \var{A\_E}, i.e. at least 7.
+parser_n_interface_name_diff_implementation_name=03032_N_Les noms d'interface et d'implementation sont diff‚rents $1 => $2
+% This note warns you if the implementation and interface names of a
+% functions are different, but they have the same mangled name. This
+% is important when using overloaded functions (but should produce no error).
+parser_e_no_with_for_variable_in_other_segments=03033_E_With ne peut ˆtre utilis‚ pour des variables dans un autre segment
+% With stores a variable locally on the stack,
+% but this is not possible if the variable belongs to another segment.
+parser_e_too_much_lexlevel=03034_E_Niveau d'inbrication de fonctions > 31
+% You can nest function definitions only 31 times.
+parser_e_range_check_error=03035_E_Erreur d'intervalle dans l'‚valuation d'une constante
+% The constants are out of their allowed range.
+parser_w_range_check_error=03036_W_Erreur d'intervalle dans l'‚valuation d'une constante
+% The constants are out of their allowed range.
+parser_e_double_caselabel=03037_E_Valeur en double dans une instruction CASE
+% You are specifying the same label 2 times in a \var{case} statement.
+parser_e_case_lower_less_than_upper_bound=03038_E_Valeur max inf‚rieure … la valeur min dans CASE
+% The upper bound of a \var{case} label is less than the lower bound and this
+% is useless
+parser_e_type_const_not_possible=03039_E_Les constantes typ‚es de classes sont interdites
+% You cannot declare a constant of type class or object.
+parser_e_no_overloaded_procvars=03040_E_Impossible d'assigner … une variable fonctionelle une fonction surcharg‚e
+% You are trying to assign an overloaded function to a procedural variable.
+% This isn't allowed.
+parser_e_invalid_string_size=03041_E_La longueur d'une STRING doit ˆtre situ‚e entre 1 et 255
+% The length of a string in Pascal is limited to 255 characters. You are
+% trying to declare a string with length lower than 1 or greater than 255
+% (This is not true for \var{Longstrings} and \var{AnsiStrings}.
+parser_w_use_extended_syntax_for_objects=03042_W_Utilisez la syntaxe ‚tendue de NEW et DISPOSE pour les objets
+% If you have a pointer \var{a} to a class type, then the statement
+% \var{new(a)} will not initialize the class (i.e. the constructor isn't
+% called), although space will be allocated. you should issue the
+% \var{new(a,init)} statement. This will allocate space, and call the
+% constructor of the class.
+parser_w_no_new_dispose_on_void_pointers=03043_W_L'usage de NEW ou DISPOSE pour des pointeurs non typ‚s est sans signification meaningless
+parser_e_no_new_dispose_on_void_pointers=03044_E_L'usage de NEW ou DISPOSE pour des pointeurs non typ‚s est sans signification meaningless
+% You cannot use \var{new(p)} or \var{dispose(p)} if \var{p} is an untyped pointer
+% because no size is associated to an untyped pointer.
+% Accepted for compatibility in \var{tp} and \vat{delphi} modes.
+parser_e_class_id_expected=03045_E_Identificateur de classe attendu
+% This happens when the compiler scans a procedure declaration that contains
+% a dot,
+% i.e., a object or class method, but the type in front of the dot is not
+% a known type.
+parser_e_no_type_not_allowed_here=03046_E_Identificateur de type interdit ici
+% You cannot use a type inside an expression.
+parser_e_methode_id_expected=03047_E_Identificateur de m‚thode attendu
+% This identifier is not a method.
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., a object or class method, but the procedure name is not a
+% procedure of this type.
+parser_e_header_dont_match_any_member=03048_E_La fonction ne correspond … aucune m‚thode de cette classe $1
+% This identifier is not a method.
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., a object or class method, but the procedure name is not a
+% procedure of this type.
+parser_p_procedure_start=03049_P_proc‚dure/fonction $1
+% When using the \var{-vp} switch, the compiler tells you when it starts
+% processing a procedure or function implementation.
+parser_e_error_in_real=03050_E_Constante r‚elle ill‚gale
+% The compiler expects a floating point expression, and gets something else.
+parser_e_fail_only_in_constructor=03051_E_FAIL peut uniquement ˆtre utilis‚ dans un constructeur
+% You are using the \var{FAIL} instruction outside a constructor method.
+parser_e_no_paras_for_destructor=03052_E_Les destructeurs ne peuvent avoir de paramŠtres
+% You are declaring a destructor with a parameter list. Destructor methods
+% cannot have parameters.
+parser_e_only_class_methods_via_class_ref=03053_E_Seules des m‚thodes de classes peuvent ˆtre r‚f‚r‚ avec des r‚f‚rences de classes
+% This error occurs in a situation like the following:
+% \begin{verbatim}
+% Type :
+% Tclass = Class of Tobject;
+%
+% Var C : TClass;
+%
+% begin
+% ...
+% C.free
+% \end{verbatim}
+% \var{Free} is not a class method and hence cannot be called with a class
+% reference.
+parser_e_only_class_methods=03054_E_Seuls des m‚thodes de classes peuvent ˆtre appel‚s dans une m‚thode de classe
+% This is related to the previous error. You cannot call a method of an object
+% from a inside a class method. The following code would produce this error:
+% \begin{verbatim}
+% class procedure tobject.x;
+%
+% begin
+% free
+% \end{verbatim}
+% Because free is a normal method of a class it cannot be called from a class
+% method.
+parser_e_case_mismatch=03055_E_La constante et le type de CASE ne conserpodnet pas
+% One of the labels is not of the same type as the case variable.
+parser_e_illegal_symbol_exported=03056_E_Le symbole ne peut ˆtre export‚ d'une librairie
+% You can only export procedures and functions when you write a library. You
+% cannot export variables or constants.
+parser_w_should_use_override=03057_W_Une m‚thode h‚rit‚e est cach‚e par $1
+% A method that is declared \var{virtual} in a parent class, should be
+% overridden in the descendent class with the \var{override} directive. If you
+% don't specify the \var{override} directive, you will hide the parent method;
+% you will not override it.
+parser_e_nothing_to_be_overridden=03058_E_Il n'y a pas de m‚thode dans l'ancˆtre que l'on peut surcharger : $1
+% You try to \var{override} a virtual method of a parent class that doesn't
+% exist.
+parser_e_no_procedure_to_access_property=03059_E_Il manque un champ pour sp‚cifier l'accŠss … la property
+% You specified no \var{read} directive for a property.
+parser_w_stored_not_implemented=03060_W_Directive de property Stored non implement‚e
+% The \var{stored} directive is not yet implemented
+parser_e_ill_property_access_sym=03061_E_Symbole ill‚gal pour accŠs … la property
+% There is an error in the \var{read} or \var{write} directives for an array
+% property. When you declare an array property, you can only access it with
+% procedures and functions. The following code woud cause such an error.
+% \begin{verbatim}
+% tmyobject = class
+% i : integer;
+% property x [i : integer]: integer read I write i;
+% \end{verbatim}
+%
+parser_e_cant_access_protected_member=03062_E_Impossible d'acc‚der … un champ "protected" d'un object ici
+% Fields that are declared in a \var{protected} section of an object or class
+% declaration cannot be accessed outside the module wher the object is
+% defined, or outside descendent object methods.
+parser_e_cant_access_private_member=03063_E_Impossible d'acc‚der … un champ "private" d'un object ici
+% Fields that are declared in a \var{private} section of an object or class
+% declaration cannot be accessed outside the module where the class is
+% defined.
+parser_w_overloaded_are_not_both_virtual=03064_W_M‚thode surchargeant une m‚thode virtuelle devrait ˆtre virtuelle : $1
+% If you declare overloaded methods in a class, then they should either all be
+% virtual, or none. You shouldn't mix them.
+parser_w_overloaded_are_not_both_non_virtual=03065_W_M‚thode surchargeant une m‚thode non virtuelle devrait ˆtre non virtuelle : $1
+% If you declare overloaded methods in a class, then they should either all be
+% virtual, or none. You shouldn't mix them.
+parser_e_overloaded_methodes_not_same_ret=03066_E_M‚thodes virtuelles surcharg‚es doivent avoir le mˆme type r‚sultat : $1
+% If you declare virtual overloaded methods in a class definition, they must
+% have the same return type.
+parser_e_dont_nest_export=03067_E_Des fonctions d‚clar‚es comme EXPORT ne peuvent ˆtre locales
+% You cannot declare a function or procedure within a function or procedure
+% that was declared as an export procedure.
+parser_e_methods_dont_be_export=03068_E_Les m‚thodes ne peuvent pas ˆtre EXPORT‚es
+% You cannot declare a procedure that is a method for an object as
+% \var{export}ed. That is, your methods cannot be called from a C program.
+parser_e_call_by_ref_without_typeconv=03069_E_Un appel avec paramŠtre par variable doivent ˆtre du type exact de la d‚claration
+% When calling a function declared with \var{var} parameters, the variables in
+% the function call must be of exactly the same type. There is no automatic
+% type conversion.
+parser_e_no_super_class=03070_E_Cette classe n'est pas un paarent de la classe actuelle
+% When calling inherited methods, you are trying to call a method of a strange
+% class. You can only call an inherited method of a parent class.
+parser_e_self_not_in_method=03071_E_SELF est seulement possible dans les m‚thodes
+% You are trying to use the \var{self} parameter outside an object's method.
+% Only methods get passed the \var{self} parameters.
+parser_e_generic_methods_only_in_methods=03072_E_Les m‚thodes ne peuvent ˆtre appel‚s avec un type qu'… l'int‚rieur d'une m‚thode
+% A construction like \var{sometype.somemethod} is only allowed in a method.
+parser_e_illegal_colon_qualifier=03073_E_Utilisation non valide de ':'
+% You are using the format \var{:} (colon) 2 times on an expression that
+% is not a real expression.
+parser_e_illegal_set_expr=03074_E_Erreur d'intervalle ou ‚l‚ment dupliqu‚ dans un constructeur d'ensemble
+% The declaration of a set contains an error. Either one of the elements is
+% outside the range of the set type, either two of the elements are in fact
+% the same.
+parser_e_pointer_to_class_expected=03075_E_Pointeur d'object attendu
+% You specified an illegal type in a \var{New} statement.
+% The extended synax of \var{New} needs an object as a parameter.
+parser_e_expr_have_to_be_constructor_call=03076_E_Expression doit ˆtre un appel … un constructeur
+% When using the extended syntax of \var{new}, you must specify the constructor
+% method of the object you are trying to create. The procedure you specified
+% is not a constructor.
+parser_e_expr_have_to_be_destructor_call=03077_E_Expression doit ˆtre un appel … un destructeur
+% When using the extended syntax of \var{dispose}, you must specify the
+% destructor method of the object you are trying to dispose of.
+% The procedure you specified is not a destructor.
+parser_e_invalid_record_const=03078_E_Mauvais ordre des ‚l‚ments d'un record
+% When declaring a constant record, you specified the fields in the wrong
+% order.
+parser_e_false_with_expr=03079_E_L'expression doit ˆtre de type record ou objet
+% A \var{with} statement needs an argument that is of the type \var{record}
+% or \var{class}. You are using \var{with} on an expression that is not of
+% this type.
+parser_e_void_function=03080_E_Les proc‚dures ne peuvent retourner une valeur
+% In \fpc, you can specify a return value for a function when using
+% the \var{exit} statement. This error occurs when you try to do this with a
+% procedure. Procedures cannot return a value.
+parser_e_only_methods_allowed=03081_E_Les constructeurs, destructeurs et class operators doivent ˆtre des m‚thodes
+% You're declaring a procedure as destructor, constructor or class operator, when the
+% procedure isn't a class method.
+parser_e_operator_not_overloaded=03082_E_Operator n'est pas surcharg‚
+% You're trying to use an overloaded operator when it isn't overloaded for
+% this type.
+parser_e_no_such_assignment=03083_E_Impossible de surcharger l'assignement pour des types ‚gaux
+% You can not overload assignment for types
+% that the compiler considers as equal.
+parser_e_overload_impossible=03084_E_Impossible operator overload
+% The combination of operator, arguments and return type are
+% incompatible.
+parser_e_no_reraise_possible=03085_E_Re-raise impossible ici
+% You are trying to raise an exception where it isn't allowed. You can only
+% raise exceptions in an \var{except} block.
+parser_e_no_new_or_dispose_for_classes=03086_E_La syntaxe ‚tendue de new ou dispose n'est pas valide pour une classe
+% You cannot generate an instance of a class with the extended syntax of
+% \var{new}. The constructor must be used for that. For the same reason, you
+% cannot call \var{Dispose} to de-allocate an instance of a class, the
+% destructor must be used for that.
+parser_e_asm_incomp_with_function_return=03087_E_Directive "Assembler" incompatible avec le type de la fonction
+% You're trying to implement a \var{assembler} function, but the return type
+% of the function doesn't allow that.
+parser_e_procedure_overloading_is_off=03088_E_L'overloading de proc‚dure est d‚sactiv‚
+% When using the \var{-So} switch, procedure overloading is switched off.
+% Turbo Pascal does not support function overloading.
+parser_e_overload_operator_failed=03089_E_Impossible de red‚finir cet op‚rateur
+% You are trying to overload an operator which cannot be overloaded.
+% The following operators can be overloaded :
+% \begin{verbatim}
+% +, -, *, /, =, >, <, <=, >=, is, as, in, **, :=
+% \end{verbatim}
+parser_e_comparative_operator_return_boolean=03090_E_Un op‚ratuer de comparaison doit retourner une valeur bool‚enne
+% When overloading the \var{=} operator, the function must return a boolean
+% value.
+parser_e_only_virtual_methods_abstract=03091_E_Seule une m‚thode virtuelle peut ˆtre abstraite
+% You are declaring a method as abstract, when it isn't declared to be
+% virtual.
+parser_f_unsupported_feature=03092_F_Utilisation d'une caract‚ristique non support‚e !
+% You're trying to force the compiler into doing something it cannot do yet.
+parser_e_mix_of_classes_and_objects=03093_E_Il est interdit de m‚langer des objets et des classes
+% You cannot derive \var{objects} and \var{classes} intertwined . That is,
+% a class cannot have an object as parent and vice versa.
+parser_w_unknown_proc_directive_ignored=03094_W_Directive de proc‚dure non reconnue a due ˆtre ignor‚e : $1
+% The procedure direcive you secified is unknown. Recognised procedure
+% directives are \var{cdecl}, \var{stdcall}, \var{popstack}, \var{pascal}
+% \var{register}, \var{export}.
+parser_e_absolute_only_one_var=03095_E_absolute put seulement ˆtre associ‚ … une seule variable
+% You cannot specify more than one variable before the \var{absolute} directive.
+% Thus, the following construct will provide this error:
+% \begin{verbatim}
+% Var Z : Longint;
+% X,Y : Longint absolute Z;
+% \end{verbatim}
+% \item [ absolute can only be associated a var or const ]
+% The address of a \var{absolute} directive can only point to a variable or
+% constant. Therefore, the following code will produce this error:
+% \begin{verbatim}
+% Procedure X;
+%
+% var p : longint absolute x;
+% \end{verbatim}
+%
+parser_e_absolute_only_to_var_or_const=03096_E_absolute peut seulement ˆtre associ‚ … une variable ou une constante
+% The address of a \var{absolute} directive can only point to a variable or
+% constant. Therefore, the following code will produce this error:
+% \begin{verbatim}
+% Procedure X;
+%
+% var p : longint absolute x;
+% \end{verbatim}
+%
+parser_e_initialized_only_one_var=03097_E_Seule UNE variable peut ˆtre initialis‚e
+% You cannot specify more than one variable with a initial value
+% in Delphi syntax.
+parser_e_abstract_no_definition=03098_E_Les m‚thodes "Abstract" ne peuvent pas avoir d'implementation
+% Abstract methods can only be declared, you cannot implement them. They
+% should be overridden by a descendant class.
+parser_e_overloaded_must_be_all_global=03099_E_Cette fonction surcharg‚e ne peut ˆtre locale (doit ˆtre export‚e)
+% You are defining a overloaded function in the implementation part of a unit,
+% but there is no corresponding declaration in the interface part of the unit.
+parser_w_virtual_without_constructor=03100_W_Des m‚thodes virtuelles sont utilis‚es sans constructeur pour $1
+% If you declare objects or classes that contain virtual methods, you need
+% to have a constructor and destructor to initialize them. The compiler
+% encountered an object or class with virtual methods that doesn't have
+% a constructor/destructor pair.
+parser_m_macro_defined=03101_M_Macro d‚finie : $1
+% When \var{-vm} is used, the compiler tells you when it defines macros.
+parser_m_macro_undefined=03102_M_Macro non d‚finie : $1
+% When \var{-vm} is used, the compiler tells you when it undefines macros.
+parser_m_macro_set_to=03103_M_Macro $1 … pour valeur $2
+% When \var{-vm} is used, the compiler tells you what values macros get.
+parser_i_compiling=03104_I_Compilation de $1
+% When you turn on information messages (\var{-vi}), the compiler tells you
+% what units it is recompiling.
+parser_u_parsing_interface=03105_U_Lecture de l'interface de l'unit‚ $1
+% This tells you that the reading of the interface
+% of the current unit starts
+parser_u_parsing_implementation=03106_U_Lecture de l'implementation de $1
+% This tells you that the code reading of the implementation
+% of the current unit, library or program starts
+parser_d_compiling_second_time=03107_D_Compilation de $1 pour la seconde fois
+% When you request debug messages (\var{-vd}) the compiler tells you what
+% units it recompiles for the second time.
+parser_e_no_paras_allowed=03108_E_Les propri‚t‚s vecteurs ne sont pas accept‚es ici
+% You cannot use array properties at that point.
+parser_e_no_property_found_to_override=03109_E_Aucune propri‚t‚ trouv‚e pour override
+% You want to overrride a property of a parent class, when there is, in fact,
+% no such property in the parent class.
+parser_e_only_one_default_property=03110_E_Seule une propri‚t‚ pard‚faut autoris‚e, il y en a une dans la classe $1
+% You specified a property as \var{Default}, but a parent class already has a
+% default property, and a class can have only one default property.
+parser_e_property_need_paras=03111_E_La propri‚t‚ par d‚faut doit ˆtre une propri‚t‚ vecteur
+% Only array properties of classes can be made \var{default} properties.
+parser_e_constructor_cannot_be_not_virtual=03112_E_Les constructeurs virtuels sont seulement possible pour les classes
+% You cannot have virtual constructors in objects. You can only have them
+% in classes.
+parser_e_no_default_property_available=03113_E_Pas de propri‚t‚ par d‚faut
+% You try to access a default property of a class, but this class (or one of
+% its ancestors) doesn't have a default property.
+parser_e_cant_have_published=03114_E_PUBLISHED non autoris‚ ici pour des classes, utilisez {$M+}
+% If you want a \var{published} section in a class definition, you must
+% use the \var{\{\$M+\}} switch, whch turns on generation of type
+% information.
+parser_e_forward_declaration_must_be_resolved=03115_E_La d‚claration anticip‚e de la classe $1 doit ˆtre r‚solue ici pour pouvoir ˆtreparent
+% To be able to use an object as an ancestor object, it must be defined
+% first. This error occurs in the following situation:
+% \begin{verbatim}
+% Type ParentClas = Class;
+% ChildClass = Class(ParentClass)
+% ...
+% end;
+% \end{verbatim}
+% Where \var{ParentClass} is declared but not defined.
+parser_e_no_local_operator=03116_E_Les op‚rateurs ne peuvent ˆtre locaux
+% You cannot overload locally, i.e. inside procedures or function
+% definitions.
+parser_e_proc_dir_not_allowed_in_interface=03117_E_La directive de proc‚dure $1 n'est pas autoris‚e en interface
+% This procedure directive is not allowed in the \var{interface} section of
+% a unit. You can only use it in the \var{implementation} section.
+parser_e_proc_dir_not_allowed_in_implementation=03118_E_La directive de proc‚dure $1 n'est pas autoris‚e en impl‚mentation
+% This procedure directive is not defined in the \var{implementation} section of
+% a unit. You can only use it in the \var{interface} section.
+parser_e_proc_dir_not_allowed_in_procvar=03119_E_La directive de proc‚dure n'est pas valide pour une variable
+% This procedure directive cannot be part of a procedural of function
+% type declaration.
+parser_e_function_already_declared_public_forward=03120_E_La fonction $1 est d‚j… d‚clar‚e comme publique ou forward
+% You will get this error if a function is defined as \var{forward} twice.
+% Or it is once in the \var{interface} section, and once as a \var{forward}
+% declaration in the \var{implmentation} section.
+parser_e_not_external_and_export=03121_E_EXPORT et EXTERNAL sont incompatibles
+% These two procedure directives are mutually exclusive
+parser_e_name_keyword_expected=03122_E_Le mot r‚serv‚ NAME est requis ici
+% The definition of an external variable needs a \var{name} clause.
+parser_w_not_supported_for_inline=03123_W_$1 n'est pas support‚ pour des fonctions INLINE
+% Inline procedures don't support this declaration.
+parser_w_inlining_disabled=03124_W_Inlining d‚sactiv‚
+% Inlining of procedures is disabled.
+parser_i_writing_browser_log=03125_I_Ecriture du Browser log $1
+% When information messages are on, the compiler warns you when it
+% writes the browser log (generated with the \var{\{\$Y+ \}} switch).
+parser_h_maybe_deref_caret_missing=03126_H_le d‚r‚f‚rencement du pointeur semble manquer
+% The compiler thinks that a pointer may need a dereference.
+parser_f_assembler_reader_not_supported=03127_F_Lecteur de code assembleur non support‚
+% The selected assembler reader (with \var{\{\$ASMMODE xxx\}} is not
+% supported. The compiler can be compiled with or without support for a
+% particular assembler reader.
+parser_e_proc_dir_conflict=03128_E_La directive de proc‚dure $1 est en conflit avec d'autres directives
+% You specified a procedure directive that conflicts with other directives.
+% for instance \var{cdecl} and \var{pascal} are mutually exclusive.
+parser_e_call_convention_dont_match_forward=03129_E_La convention d'appel ne correspond pas … la fonction pr‚d‚finie
+% This error happens when you declare a function or procedure with
+% e.g. \var{cdecl;} but omit this directive in the implementation, or vice
+% versa. The calling convention is part of the function declaration, and
+% must be repeated in the function definition.
+parser_e_register_calling_not_supported=03130_E_Appel avec registres (fastcall) non support‚
+% The \var{register} calling convention, i.e., arguments are passed in
+% registers instead of on the stack is not supported. Arguments are always
+% passed on the stack.
+parser_e_property_cant_have_a_default_value=03131_E_Cette propri‚t‚ ne peut avoir de valeur par d‚faut
+% Set properties or indexed properties cannot have a default value.
+parser_e_property_default_value_must_const=03132_E_La valeur par d‚faut d'une propri‚t‚ doit ˆtre une constante
+% The value of a \var{default} declared property must be knwon at compile
+% time. The value you specified is only known at run time. This happens
+% .e.g. if you specify a variable name as a default value.
+parser_e_cant_publish_that=03133_E_Ce symbole n'est pas une classe et ne peut donc pas ˆtre PUBLISHED
+% Only class type variables can be in a \var{published} section of a class
+% if they are not declared as a property.
+parser_e_cant_publish_that_property=03134_E_Ce genre de propri‚t‚ ne peut ˆtre PUBLISHED
+% Properties in a \var{published} section cannot be array properties.
+% they must be moved to public sections. Properties in a \var{published}
+% section must be an ordinal type, a real type, strings or sets.
+parser_w_empty_import_name=03135_W_Nom d'importation vide
+% Both index and name for the import are 0 or empty
+parser_e_empty_import_name=03136_W_Empty import name specified
+% Some targets need a name for the imported procedure or a cdecl specifier
+parser_e_used_proc_name_changed=03137_E_Le nom interne de la fonction … chang‚ aprŠs son usage
+% This is an internal error; please report any occurrences of this error
+% to the \fpc team.
+parser_e_division_by_zero=03138_E_Division par z‚ro
+% There is a divsion by zero encounted
+parser_e_invalid_float_operation=03139_E_Op‚ration en virgule flottatne invalide
+% An operation on two real type values produced an overflow or a division
+% by zero.
+parser_e_array_lower_less_than_upper_bound=03140_E_Limite sup‚rieure inf‚rieure … la limite inf‚rieure d'un intervalle
+% The upper bound of a \var{case} label is less than the lower bound and this
+% is not possible
+parser_w_string_too_long=03141_W_String "$1" est plus long que $2
+% The size of the constant string is larger than the size you specified in
+% string type definition
+parser_e_string_larger_array=03142_E_longueur du String sup‚rieure … la longueur du CHAR ARRAY
+% The size of the constant string is larger than the size you specified in
+% the array[x..y] of char definition
+parser_e_ill_msg_expr=03143_E_Expression invalide aprŠs directive MESSAGE
+% \fpc supports only integer or string values as message constants
+parser_e_ill_msg_param=03144_E_MESSAGE handler peuvent seulement accepter un paramŠtre par r‚f‚rence
+% A method declared with the \var{message}-directive as message handler
+% can take only one parameter which must be declared as call by reference
+% Parameters are declared as call by reference using the \var{var}-directive
+parser_e_duplicate_message_label=03145_E_Duplicate message label: %1
+% A label for a message is used twice in one object/class
+parser_e_self_in_non_message_handler=03146_E_SELF ne peut ˆtre un paramŠtre explicite que dans les MESSAGE handlers
+% The self parameter can be passed only explicit if it is a method which
+% is declared as message method handler
+parser_e_threadvars_only_sg=03147_E_THREADVARS peuvent seulement ˆtre statiques ou globaux
+% Threadvars must be static or global, you can't declare a thread
+% local to a procedure. Local variables are always local to a thread,
+% because every thread has its own stack and local variables
+% are stored on the stack
+parser_f_direct_assembler_not_allowed=03148_F_Assembleur direct non support‚ pour la sortie binaire
+% You can't use direct assembler when using a binary writer, choose an
+% other outputformat or use another assembler reader
+parser_w_no_objpas_use_mode=03149_W_Ne chargez pas l'unit‚ OBJPAS manuellement, utilisez {$mode objfpc} ou {$mode delphi}
+% You're trying to load the ObjPas unit manual from a uses clause. This is
+% not a good idea to do, you can better use the {$mode objfpc} or {$mode delphi}
+% directives which load the unit automatically
+parser_e_no_object_override=03150_E_OVERRIDE nepeut ˆtre utilis‚ pour des objets
+% Override isn't support for objects, use VIRTUAL instead to override
+% a method of an anchestor object
+% \end{description}
+#
+# Type Checking
+#
+% \section{Type checking errors}
+% This section lists all errors that can occur when type checking is
+% performed.
+% \begin{description}
+parser_e_cant_use_inittable_here=03151_E_Les types de donn‚es n‚cessitant des initialisations ne peuvent faire partie de RECORD variables
+% Some data type (e.g. \var{ansistring}) needs initialization/finalization
+% code which is implicitly generated by the compiler. Such data types
+% can't be used in the variant part of a record.
+parser_e_resourcestring_only_sg=03152_E_RESOURCESTRINGS doivent ˆtre statiques ou globaux
+% Resourcestring can not be declared local, only global or using the static
+% directive.
+parser_e_exit_with_argument_not__possible=03153_E_Exit avec un argument ne peut ˆtre utilis‚ ici
+% an exit statement with an argument for the return value can't be used here, this
+% can happen e.g. in \var{try..except} or \var{try..finally} blocks
+parser_e_stored_property_must_be_boolean=03154_E_Le type du symbole STORED doit ˆtre un bool‚en
+% If you specify a storage symbol in a property declaration, it must be of
+% the type boolean
+parser_e_ill_property_storage_sym=03155_E_Ce symbole n'est pas admis comme symbole STORED
+% You can't use this type of symbol as storage specifier in property
+% declaration. You can use only methods with the result type boolean,
+% boolean class fields or boolean constants
+parser_e_only_publishable_classes_can__be_published=03156_E_Selues les classes compil‚es en mode $M+ peuvent ˆtre PUBLISHED
+% In the published section of a class can be only class as fields used which
+% are compiled in $M+ or which are derived from such a class. Normally
+% such a class should be derived from TPersitent
+parser_e_proc_directive_expected=03157_E_Directive de proc‚dure attendue
+% When declaring a procedure in a const block you used a ; after the
+% procedure declaration after which a procedure directive must follow.
+% Correct declarations are:
+% \begin{verbatim}
+% const
+% p : procedure;stdcall=nil;
+% p : procedure stdcall=nil;
+% \end{verbatim}
+parser_e_invalid_property_index_value=03158_E_Le type d'un index de propri‚t‚ doit ˆtre un type ordinal
+% The value you use to index a property must be of an ordinal type, for
+% example an integer or enumerated type.
+parser_e_procname_to_short_for_export=03159_E_Nom de proc‚dure trop court pour ˆtre exprot‚
+% The length of the procedure/function name must be at least 2 characters
+% long. This is because of a bug in dlltool which doesn't parse the .def
+% file correct with a name of length 1.
+parser_e_dlltool_unit_var_problem=03160_E_Impossible de cr‚er une entr‚e DEFFILE pour des variables globales d'unit‚s
+parser_e_dlltool_unit_var_problem2=03161_E_Compilez sans l'option -WD
+% \end{description}
+#
+# Type Checking
+#
+% \section{Type checking errors}
+% This section lists all errors that can occur when type checking is
+% performed.
+% \begin{description}
+type_e_mismatch=04000_E_Incompatibilit‚ de types
+% This can happen in many cases:
+% \begin{itemize}
+% \item The variable you're assigning to is of a different type than the
+% expression in the assignment.
+% \item You are calling a function or procedure with parameters that are
+% incompatible with the parameters in the function or procedure definition.
+% \end{itemize}
+type_e_incompatible_types=04001_E_Incompatible types: got $1 expected $2
+% There is no conversion possible between the two types
+type_e_not_equal_types=04002_E_Incompatibilit‚ de types entre $1 et $2
+% The types are not equal
+type_e_type_id_expected=04003_E_Identificateur de type attendu
+% The identifier is not a type, or you forgot to supply a type identifier.
+type_e_variable_id_expected=04004_E_Identificateur de variable attendu
+% This happens when you pass a constant to a \var{Inc} var or \var{Dec}
+% procedure. You can only pass variables as arguments to these functions.
+type_e_integer_expr_expected=04005_E_Integer expression expected
+% The compiler expects an expression of type integer, but gets a different
+% type.
+type_e_boolean_expr_expected=04006_E_Expression bool‚enne attendue, mais "$1" obtenu
+% The expression must be a boolean type, it should be return true or
+% false.
+type_e_ordinal_expr_expected=04007_E_Expression ordinale attendue
+% The expression must be of ordinal type, i.e., maximum a \var{Longint}.
+% This happens, for instance, when you specify a second argument
+% to \var{Inc} or \var{Dec} that doesn't evaluate to an ordinal value.
+type_e_pointer_type_expected=04008_E_Type pointeur attendu
+% The variable or expression isn't of the type \var{pointer}. This
+% happens when you pass a variable that isn't a pointer to \var{New}
+% or \var{Dispose}.
+type_e_class_type_expected=04009_E_Type classe attendu
+% The variable of expression isn't of the type \var{class}. This happens
+% typically when
+% \begin{enumerate}
+% \item The parent class in a class declaration isn't a class.
+% \item An exception handler (\var{On}) contains a type identifier that
+% isn't a class.
+% \end{enumerate}
+type_e_varid_or_typeid_expected=04010_E_Identificateur de variable ou de type attendu
+% The argument to the \var{High} or \var{Low} function is not a variable
+% nor a type identifier.
+type_e_cant_eval_constant_expr=04011_E_Impossible d'‚valuer l'expression constante
+% No longer in use.
+type_e_set_element_are_not_comp=04012_E_Elements d'ensembles non compatibles
+% You are trying to make an operation on two sets, when the set element types
+% are not the same. The base type of a set must be the same when taking the
+% union
+type_e_set_operation_unknown=04013_E_Op‚ration non permise pour des ensembles
+% several binary operations are not defined for sets
+% like div mod ** (also >= <= for now)
+type_w_convert_real_2_comp=04014_W_Conversion automatique de r‚el vers COMP qui est un type entier
+% An implicit type conversion from a real type to a \var{comp} is
+% encountered. Since \var{Comp} is a 64 bit integer type, this may indicate
+% an error.
+type_h_use_div_for_int=04015_H_Utilisez DIV pour obtenir un r‚sultat entier
+% When hints are on, then an integer division with the '/' operator will
+% procuce this message, because the result will then be of type real
+type_e_strict_var_string_violation=04016_E_Types string incompatibles, … cause du mode $V+
+% When compiling in \var{\{\$V+ \}} mode, the string you pass as a parameter
+% should be of the exact same type as the declared parameter of the procedure.
+type_e_succ_and_pred_enums_with_assign_not_possible=04017_E_succ ou pred impossible pour des ‚num‚rations avec valeurs fix‚es
+% When you declared an enumeration type which has assignments in it, as in C,
+% like in the following:
+% \begin{verbatim}
+% Tenum = (a,b,e:=5);
+% \end{verbatim}
+% you cannot use the \var{Succ} or \var{Pred} functions on them.
+type_e_cant_read_write_type=04018_E_Impossible de lire ou d'‚crire des variables de ce type
+% You are trying to \var{read} or \var{write} a variable from or to a
+% file of type text, which doesn't support that. Only integer types,
+% booleans, reals, pchars and strings can be read from/written to a text file.
+type_e_no_readln_writeln_for_typed_file=04019_E_Impossible d'utiliser READLN ou WRITELN pour un ficher typ‚
+% \var{readln} and \var{writeln} are only allowed for text files.
+type_e_no_read_write_for_untyped_file=04020_E_Impossible d'utiliser READ ou WRITE pour un FILE non typ‚
+% \var{read} and \var{write} are only allowed for text or typed files.
+type_e_typeconflict_in_set=04021_E_Confit de type pour des ‚l‚ments d'un ensemble
+% There is at least one set element which is of the wrong type, i.e. not of
+% the set type.
+type_w_maybe_wrong_hi_lo=04022_W_lo/hi(longint/dword) retourne le word bas/haut
+% \fpc supports an overloaded version of \var{lo/hi} for \var{longint/dword}
+% which returns the lower/upper word of the argument. TP always uses
+% a 16 bit \var{lo/hi} which returns always bits 0..7 for \var{lo} and the
+% bits 8..15 for \var{hi}. If you want the TP behavior you have
+% to type case the argument to \var{word/integer}
+type_e_integer_or_real_expr_expected=04023_E_Expression entiŠre ou r‚elle attendue
+% The first argument to \var{str} must a real or integer type.
+type_e_wrong_type_in_array_constructor=04024_E_Mauvais type dans array constructor
+% You are trying to use a type in an array constructor which is not
+% allowed.
+type_e_wrong_parameter_type=04025_E_Type incompatible type pour arg #$1: $2 au lieu de $3
+% You are trying to pass an invalid type for the specified parameter.
+% \end{description}
+type_e_no_method_and_procedure_not_compatible=04026_E_Method (variable) et Procedure (variable) sont incompatibles
+% You can't assign a method to a procedure variable or a procedure to a
+% method pointer.
+type_e_wrong_math_argument=04027_E_Constante invalide pass‚e … une fonction math‚matique interne
+% The constant argument passed to a ln or sqrt function is out of
+% the definition range of these functions.
+type_e_no_addr_of_constant=04028_E_Impossible d'obtenir l'adresse d'une constante
+% It's not possible to get the address of a constant, because they
+% aren't stored in memory, you can try making it a typed constant.
+% \end{description}
+#
+# Symtable
+#
+% \section{Symbol handling}
+% This section lists all the messages that concern the handling of symbols.
+% This means all things that have to do with procedure and variable names.
+% \begin{description}
+#
+# Symtable
+#
+% \section{Symbol handling}
+% This section lists all the messages that concern the handling of symbols.
+% This means all things that have to do with procedure and variable names.
+% \begin{description}
+type_e_argument_cant_be_assigned=04029_E_Impossible d'assigner une valeur … l'argument
+% Only expressions which can be on the left side of an
+% assignment can be passed as call by reference argument
+% Remark: Properties can be only
+% used on the left side of an assignment, but they can't be used as arguments
+type_e_cannot_local_proc_to_procvar=04030_E_Impossible d'assigner une fonction ou proc‚dure locale … une variable de proc‚dure
+% It's not allowed to assign a local procedure/function to a
+% procedure variable, because the calling of local procedure/function is
+% different. You can only assign local procedure/function to a void pointer.
+type_e_no_assign_to_addr=04031_E_Can't assign values to an address
+% It's not allowed to assign a value to an address of a variable,constant,
+% procedure or function. You can try compiling with -So if the identifier
+% is a procedure variable.
+type_e_no_assign_to_const=04032_E_Can't assign values to const variable
+% It's not allowed to assign a value to a variable which is declared
+% as a const. This is normally a parameter declared as const, to allow
+% changing make the parameter value or var.
+% \end{description}
+#
+# Symtable
+#
+% \section{Symbol handling}
+% This section lists all the messages that concern the handling of symbols.
+% This means all things that have to do with procedure and variable names.
+% \begin{description}
+sym_e_id_not_found=05000_E_Identificateur non trouv‚ $1
+% The compiler doesn't know this symbol. Usually happens when you misspel
+% the name of a variable or procedure, or when you forgot to declare a
+% variable.
+sym_f_internal_error_in_symtablestack=05001_F_Internal Error in SymTableStack()
+% An internal error occurred in the compiler; If you encounter such an error,
+% please contact the developers and try to provide an exact description of
+% the circumstances in which the error occurs.
+sym_e_duplicate_id=05002_E_Duplicate identifier $1
+% The identifier was already declared in the current scope.
+sym_h_duplicate_id_where=05003_H_Identifier already defined in $1 at line $2
+% The identifier was already declared in a previous scope.
+sym_e_unknown_id=05004_E_Unknown identifier $1
+% The identifier encountered hasn't been declared, or is used outside the
+% scope where it's defined.
+sym_e_forward_not_resolved=05005_E_Forward declaration not solved $1
+% This can happen in two cases:
+% \begin{itemize}
+% \item This happens when you declare a function (in the \var{interface} part, or
+% with a \var{forward} directive, but do not implement it.
+% \item You reference a type which isn't declared in the current \var{type}
+% block.
+% \end{itemize}
+sym_f_id_already_typed=05006_F_Identifier type already defined as type
+% You are trying to redefine a type.
+sym_e_error_in_type_def=05007_E_Error in type definition
+% There is an error in your definition of a new array type:
+% \item One of the range delimiters in an array declaration is erroneous.
+% For example, \var{Array [1..1.25]} will trigger this error.
+sym_e_type_id_not_defined=05008_E_Type identifier not defined
+% The type identifier has not been defined yet.
+sym_e_forward_type_not_resolved=05009_E_Forward type not resolved $1
+% The compiler encountered an unknown type.
+sym_e_only_static_in_static=05010_E_Only static variables can be used in static methods or outside methods
+% A static method of an object can only access static variables.
+sym_e_invalid_call_tvarsymmangledname=05011_E_Invalid call to tvarsym.mangledname()
+% An internal error occurred in the compiler; If you encounter such an error,
+% please contact the developers and try to provide an exact description of
+% the circumstances in which the error occurs.
+sym_f_type_must_be_rec_or_class=05012_F_record or class type expected
+% The variable or expression isn't of the type \var{record} or \var{class}.
+sym_e_no_instance_of_abstract_object=05013_E_Instances of classes or objects with an abstract method are not allowed
+% You are trying to generate an instance of a class which has an abstract
+% method that wasn't overridden.
+sym_w_label_not_defined=05014_W_Label not defined $1
+% A label was declared, but not defined.
+sym_e_label_used_and_not_defined=05015_E_Label used but not defined $1
+% A label was declared and used, but not defined.
+sym_e_ill_label_decl=05016_E_Illegal label declaration
+% This error should never happen; it occurs if a label is defined outside a
+% procedure or function.
+sym_e_goto_and_label_not_supported=05017_E_GOTO und LABEL are not supported (use switch -Sg)
+% You must compile a program which has \var{label}s and \var{goto} statements
+% with the \var{-Sg} switch. By default, \var{label} and \var{goto} aren't
+% supported.
+sym_e_label_not_found=05018_E_Label not found
+% A \var{goto label} was encountered, but the label isn't declared.
+sym_e_id_is_no_label_id=05019_E_identifier isn't a label
+% The identifier specified after the \var{goto} isn't of type label.
+sym_e_label_already_defined=05020_E_label already defined
+% You are defining a label twice. You can define a label only once.
+sym_e_ill_type_decl_set=05021_E_illegal type declaration of set elements
+% The declaration of a set contains an invalid type definition.
+sym_e_class_forward_not_resolved=05022_E_Forward class definition not resolved $1
+% You declared a class, but you didn't implement it.
+sym_n_unit_not_used=05023_H_Unit $1 not used in $2
+% The unit referenced in the \var{uses} clause is not used.
+sym_h_para_identifier_not_used=05024_H_Parameter not used $1
+% This is a warning. The identifier was declared (locally or globally) but
+% wasn't used (locally or globally).
+sym_n_local_identifier_not_used=05025_N_Local variable not used $1
+% You have declared, but not used a variable in a procedure or function
+% implementation.
+sym_h_para_identifier_only_set=05026_H_Value parameter $1 is assigned but never used
+% This is a warning. The identifier was declared (locally or globally)
+% set but not used (locally or globally).
+sym_n_local_identifier_only_set=05027_N_Local variable $1 is assigned but never used
+% The variable in a procedure or function
+% implementation is declared, set but never used.
+sym_h_local_symbol_not_used=05028_H_Local $1 $2 is not used
+% A local symbol is never used.
+sym_n_private_identifier_not_used=05029_N_Private field $1.$2 is never used
+sym_n_private_identifier_only_set=05030_N_Private field $1.$2 is assigned but never used
+sym_n_private_method_not_used=05031_N_Private method $1.$2 never used
+
+sym_e_set_expected=05032_E_Set type expected
+% The variable or expression isn't of type \var{set}. This happens in an
+% \var{in} statement.
+sym_w_function_result_not_set=05033_W_Function result does not seem to be set
+% You can get this warning if the compiler thinks that a function return
+% value is not set. This will not be displayed for assembler procedures,
+% or procedures that contain assembler blocks.
+sym_w_wrong_C_pack=05034_W_Type $1 is not aligned correctly in current record for C
+% Arrays with sizes not multiples of 4 will be wrongly aligned
+% for C structures.
+sym_e_illegal_field=05035_E_Unknown record field identifier $1
+% The field doesn't exist in the record definition.
+sym_n_uninitialized_local_variable=05036_W_Local variable $1 does not seem to be initialized
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% wasn't initialized first (i.e. appeared in the right-hand side of an
+% assigment)
+sym_n_uninitialized_variable=05037_W_Variable $1 does not seem to be initialized
+% These messages are displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% wasn't initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_e_id_no_member=05038_E_identifier idents no member $1
+% When using the extended syntax of \var{new}, you must specify the constructor
+% method of the class you are trying to create. The procedure you specified
+% does not exist.
+sym_b_param_list=05039_B_Found declaration: $1
+% You get this when you use the \var{-vb} switch. In case an overloaded
+% procedure is not found, then all candidate overloaded procedures are
+% listed, with their parameter lists.
+% \end{description}
+#
+# Codegenerator
+#
+% \section{Code generator messages}
+% This section lists all messages that can be displayed if the code
+% generator encounters an error condition.
+% \begin{description}
+sym_e_segment_too_large=05040_E_Data segment too large (max. 2GB)
+% You get this when you declare an array whose size exceeds the 2GB limit.
+% \end{description}
+#
+# Codegenerator
+#
+% \section{Code generator messages}
+% This section lists all messages that can be displayed if the code
+% generator encounters an error condition.
+% \begin{description}
+cg_e_break_not_allowed=06000_E_BREAK not allowed
+% You're trying to use \var{break} outside a loop construction.
+cg_e_continue_not_allowed=06001_E_CONTINUE not allowed
+% You're trying to use \var{continue} outside a loop construction.
+cg_e_too_complex_expr=06002_E_Expression too complicated - FPU stack overflow
+% Your expression is too long for the compiler. You should try dividing the
+% construct over multiple assignments.
+cg_e_illegal_expression=06003_E_Illegal expression
+% This can occur under many circumstances. Mostly when trying to evaluate
+% constant expressions.
+cg_e_invalid_integer=06004_E_Invalid integer expression
+% You made an expression which isn't an integer, and the compiler expects the
+% result to be an integer.
+cg_e_invalid_qualifier=06005_E_Illegal qualifier
+% One of the following is happening :
+% \begin{itemize}
+% \item You're trying to access a field of a variable that is not a record.
+% \item You're indexing a variable that is not an array.
+% \item You're dereferencing a variable that is not a pointer.
+% \end{itemize}
+cg_e_upper_lower_than_lower=06006_E_High range limit < low range limit
+% You are declaring a subrange, and the lower limit is higher than the high
+% limit of the range.
+cg_e_illegal_count_var=06007_E_Illegal counter variable
+% The type of a \var{for} loop variable must be an ordinal type.
+% Loop variables cannot be reals or strings.
+cg_e_cant_choose_overload_function=06008_E_Can't determine which overloaded function to call
+% You're calling overloaded functions with a parameter that doesn't correspond
+% to any of the declared function parameter lists. e.g. when you have declared
+% a function with parameters \var{word} and \var{longint}, and then you call
+% it with a parameter which is of type \var{integer}.
+cg_e_parasize_too_big=06009_E_Parameter list size exceeds 65535 bytes
+% The I386 processor limits the parameter list to 65535 bytes (the \var{RET}
+% instruction causes this)
+cg_e_illegal_type_conversion=06010_E_Illegal type conversion
+% When doing a type-cast, you must take care that the sizes of the variable and
+% the destination type are the same.
+cg_d_pointer_to_longint_conv_not_portable=06011_D_Conversion between ordinals and pointers is not portable across platforms
+% If you typecast a pointer to a longint, this code will not compile
+% on a machine using 64bit for pointer storage.
+cg_e_file_must_call_by_reference=06012_E_File types must be var parameters
+% You cannot specify files as value parameters, i.e. they must always be
+% declared \var{var} parameters.
+cg_e_cant_use_far_pointer_there=06013_E_The use of a far pointer isn't allowed there
+% Free Pascal doesn't support far pointers, so you cannot take the address of
+% an expression which has a far reference as a result. The \var{mem} construct
+% has a far reference as a result, so the following code will produce this
+% error:
+% \begin{verbatim}
+% var p : pointer;
+% ...
+% p:=@mem[a000:000];
+% \end{verbatim}
+cg_e_var_must_be_reference=06014_E_illegal call by reference parameters
+% You are trying to pass a constant or an expression to a procedure that
+% requires a \var{var} parameter. Only variables can be passed as a \var{var}
+% parameter.
+cg_e_dont_call_exported_direct=06015_E_EXPORT declared functions can't be called
+% No longer in use.
+cg_w_member_cd_call_from_method=06016_W_Possible illegal call of constructor or destructor (doesn't match to this context)
+% No longer in use.
+cg_n_inefficient_code=06017_N_Inefficient code
+% You construction seems dubious to the compiler.
+cg_w_unreachable_code=06018_W_unreachable code
+% You specified a loop which will never be executed. Example:
+% \begin{verbatim}
+% while false do
+% begin
+% {.. code ...}
+% end;
+% \end{verbatim}
+cg_e_stackframe_with_esp=06019_E_procedure call with stackframe ESP/SP
+% The compiler encountered a procedure or function call inside a
+% procedure that uses a \var{ESP/SP} stackframe. Normally, when a call is
+% done the procedure needs a \var{EBP} stackframe.
+cg_e_cant_call_abstract_method=06020_E_Abstract methods can't be called directly
+% You cannot call an abstract method directy, instead you must call a
+% overriding child method, because an abstract method isn't implemented.
+cg_f_internal_error_in_getfloatreg=06021_F_Internal Error in getfloatreg(), allocation failure
+% An internal error occurred in the compiler; If you encounter such an error,
+% please contact the developers and try to provide an exact description of
+% the circumstances in which the error occurs.
+cg_f_unknown_float_type=06022_F_Unknown float type
+% The compiler cannot determine the kind of float that occurs in an expression.
+cg_f_secondvecn_base_defined_twice=06023_F_SecondVecn() base defined twice
+% An internal error occurred in the compiler; If you encounter such an error,
+% please contact the developers and try to provide an exact description of
+% the circumstances in which the error occurs.
+cg_f_extended_cg68k_not_supported=06024_F_Extended cg68k not supported
+% The var{extended} type is not supported on the m68k platform.
+cg_f_32bit_not_supported_in_68000=06025_F_32-bit unsigned not supported in MC68000 mode
+% The cardinal is not supported on the m68k platform.
+cg_f_internal_error_in_secondinline=06026_F_Internal Error in secondinline()
+% An internal error occurred in the compiler; If you encounter such an error,
+% please contact the developers and try to provide an exact description of
+% the circumstances in which the error occurs.
+cg_d_register_weight=06027_D_Register $1 weight $2 $3
+% Debugging message. Shown when the compiler considers a variable for
+% keeping in the registers.
+cg_e_stacklimit_in_local_routine=06028_E_Stack limit excedeed in local routine
+% Your code requires a too big stack. Some operating systems pose limits
+% on the stack size. You should use less variables or try ro put large
+% variables on the heap.
+cg_d_stackframe_omited=06029_D_Stack frame is omitted
+% Some procedure/functions do not need a complete stack-frame, so it is omitted.
+% This message will be displayed when the {-vd} switch is used.
+cg_w_64bit_range_check_not_supported=06030_W_Range check for 64 bit integers is not supported on this target
+% 64 bit range check is not yet implemented for 32 bit processors.
+cg_e_unable_inline_object_methods=06031_E_Object or class methods can't be inline.
+% You cannot have inlined object methods.
+cg_e_unable_inline_procvar=06032_E_Procvar calls can't be inline.
+% A procedure with a procedural variable call cannot be inlined.
+cg_e_no_code_for_inline_stored=06033_E_No code for inline procedure stored
+% The compiler couldn't store code for the inline procedure.
+cg_e_no_call_to_interrupt=06034_E_Direct call of interrupt procedure $1 is not possible
+% You can not call an interrupt procedure directly from FPC code
+cg_e_can_access_element_zero=06035_E_Element zero of an ansi/wide- or longstring can't be accessed, use (set)length instead
+% You should use \var{setlength} to set the length of an ansi/wide/longstring
+% and \var{length} to get the length of such kinf of string
+cg_e_include_not_implemented=06036_E_Include and exclude not implemented in this case
+% \var{include} and \var{exclude} are only partially
+% implemented for \var{i386} processors
+% and not at all for \var{m68k} processors.
+cg_e_cannot_call_cons_dest_inside_with=06037_E_Constructors or destructors can not be called inside a 'with' clause
+% Inside a \var{With} clause you cannot call a constructor or destructor for the
+% object you have in the \var{with} clause.
+cg_e_cannot_call_message_direct=06038_E_Cannot call message handler method directly
+% A message method handler method can't be called directly if it contains an
+% explicit self argument
+% \end{description}
+# EndOfTeX
+#
+# Assembler reader
+#
+cg_e_goto_inout_of_exception_block=06039_E_Jump in or outside of an exception block
+% It isn't allowed to jump in or outside of an exception block like \var{try..finally..end;}:
+% \begin{verbatim}
+% label 1;
+%
+% ...
+%
+% try
+% if not(final) then
+% goto 1; // this line will cause an error
+% finally
+% ...
+% end;
+% 1:
+% ...
+% \end{verbatim}
+% \end{description}
+cg_e_control_flow_outside_finally=06040_E_Control flow statements aren't allowed in a finally block
+% It isn't allowed to use the control flow statements \var{break},
+% \var{continue} and \var{exit}
+% inside a finally statement. The following example shows the problem:
+% \begin{verbatim}
+% ...
+% try
+% p;
+% finally
+% ...
+% exit; // This exit ISN'T allowed
+% end;
+% ...
+%
+% \end{verbatim}
+% If the procedure \var{p} raises an exception the finally block is
+% executed. If the execution reaches the exit, it's unclear what to do:
+% exiting the procedure or searching for another exception handler
+# EndOfTeX
+asmr_d_start_reading=07000_D_Starting $1 styled assembler parsing
+% This informs you that an assembler block is being parsed
+asmr_d_finish_reading=07001_D_Finished $1 styled assembler parsing
+% This informs you that an assembler block has finished.
+asmr_e_none_label_contain_at=07002_E_Non-label pattern contains @
+% A identifier which isn't a label can't contain a @.
+asmr_w_override_op_not_supported=07003_W_Override operator not supported
+% The Override operator is not supported
+asmr_e_building_record_offset=07004_E_Error building record offset
+% There has an error occured while building the offset of a record/object
+% structure, this can happend when there is no field specified at all or
+% an unknown field identifier is used.
+asmr_e_offset_without_identifier=07005_E_OFFSET used without identifier
+% You can only use OFFSET with an identifier. Other syntaxes aren't
+% supported
+asmr_e_type_without_identifier=07006_E_TYPE utilis‚ sans identificateur
+% You can only use TYPE with an identifier. Other syntaxes aren't
+% supported
+asmr_e_no_local_or_para_allowed=07007_E_Cannot use local variable or parameters here
+% You can't use a local variable or parameter here, mostly because the
+% addressing of locals and parameters is done using the %ebp register so the
+% address can't be get directly.
+asmr_e_need_offset=07008_E_need to use OFFSET here
+% You need to use OFFSET <id> here to get the address of the identifier.
+asmr_e_need_dollar=07009_E_need to use $ here
+% You need to use $<id> here to get the address of the identifier.
+asmr_e_cant_have_multiple_relocatable_symbols=07010_E_Cannot use multiple relocatable symbols
+% You can't have more than one relocatable symbol (variable/typed constant)
+% in one argument.
+asmr_e_only_add_relocatable_symbol=07011_E_Relocatable symbol can only be added
+% Relocatable symbols (variable/typed constant) can't be used with other
+% operators. Only addition is allowed.
+asmr_e_invalid_constant_expression=07012_E_Invalid constant expression
+% There is an error in the constant expression.
+asmr_e_relocatable_symbol_not_allowed=07013_E_Relocatable symbol is not allowed
+% You can't use a relocatable symbol (variable/typed constant) here.
+asmr_e_invalid_reference_syntax=07014_E_Invalid reference syntax
+% There is an error in the reference.
+asmr_e_local_para_unreachable=07015_E_Impossible d'atteindre $1 depuis ce code
+% You can not read directly the value of local or para
+% of a higher level in assembler code (except for
+% local assembler code without parameter nor locals).
+asmr_e_local_label_not_allowed_as_ref=07016_E_Local symboles/labels ne sont pas autoris‚s
+% You can't use local symbols/labels as references
+asmr_e_wrong_base_index=07017_E_Invalid base and index register usage
+% There is an error with the base and index register
+asmr_w_possible_object_field_bug=07018_W_Erreur possible dans l'utilisation d'un champ d'un object
+% Fields of objects or classes can be reached directly in normal or objfpc
+% modes but TP and Delphi modes treat the field name as a simple offset.
+asmr_e_wrong_scale_factor=07019_E_Wrong scale factor specified
+% The scale factor given is wrong, only 1,2,4 and 8 are allowed
+asmr_e_multiple_index=07020_E_Multiple index register usage
+% You are trying to use more than one index register
+asmr_e_invalid_operand_type=07021_E_Invalid operand type
+% The operand type doesn't match with the opcode used
+asmr_e_invalid_string_as_opcode_operand=07022_E_Invalid string as opcode operand: $1
+% The string specified as operand is not correct with this opcode
+asmr_w_CODE_and_DATA_not_supported=07023_W_@CODE and @DATA not supported
+% @CODE and @DATA are unsupported and are ignored.
+asmr_e_null_label_ref_not_allowed=07024_E_Null label references are not allowed
+asmr_e_expr_zero_divide=07025_E_Divide by zero in asm evaluator
+asmr_e_expr_illegal=07026_E_Illegal expression
+asmr_e_escape_seq_ignored=07027_E_escape sequence ignored: $1
+asmr_e_invalid_symbol_ref=07028_E_Invalid symbol reference
+asmr_w_fwait_emu_prob=07029_W_Fwait can cause emulation problems with emu387
+asmr_w_fadd_to_faddp=07030_W_FADD without operand translated into FADDP
+asmr_w_enter_not_supported_by_linux=07031_W_ENTER instruction is not supported by Linux kernel
+% ENTER instruction can generate a stack page fault that is not
+% caught correctly by the i386 Linux page handler.
+asmr_w_calling_overload_func=07032_W_Calling an overload function in assembler
+asmr_e_unsupported_symbol_type=07033_E_Unsupported symbol type for operand
+asmr_e_constant_out_of_bounds=07034_E_Constant value out of bounds
+asmr_e_error_converting_decimal=07035_E_Error converting decimal $1
+asmr_e_error_converting_octal=07036_E_Error converting octal $1
+asmr_e_error_converting_binary=07037_E_Error converting binary $1
+asmr_e_error_converting_hexadecimal=07038_E_Error converting hexadecimal $1
+asmr_h_direct_global_to_mangled=07039_H_$1 translated to $2
+asmr_w_direct_global_is_overloaded_func=07040_W_$1 is associated to an overloaded function
+asmr_e_cannot_use_SELF_outside_a_method=07041_E_Cannot use SELF outside a method
+asmr_e_cannot_use_OLDEBP_outside_nested_procedure=07042_E_Cannot use OLDEBP outside a nested procedure
+asmr_e_void_function=07043_W_Functions with void return value can't return any value in asm code
+asmr_e_SEG_not_supported=07044_E_SEG not supported
+asmr_e_size_suffix_and_dest_dont_match=07045_E_Size suffix and destination or source size do not match
+asmr_w_size_suffix_and_dest_dont_match=07046_W_Size suffix and destination or source size do not match
+asmr_e_syntax_error=07047_E_Assembler syntax error
+asmr_e_invalid_opcode_and_operand=07048_E_Invalid combination of opcode and operands
+asmr_e_syn_operand=07049_E_Assembler syntax error in operand
+asmr_e_syn_constant=07050_E_Assembler syntax error in constant
+asmr_e_invalid_string_expression=07051_E_Invalid String expression
+asmr_w_const32bit_for_address=07052_bit constant created for address
+asmr_e_unknown_opcode=07053_E_Instruction non reconnue $1
+asmr_e_invalid_or_missing_opcode=07054_E_Invalid or missing opcode
+asmr_e_invalid_prefix_and_opcode=07055_E_Invalid combination of prefix and opcode: $1
+asmr_e_invalid_override_and_opcode=07056_E_Invalid combination of override and opcode: $1
+asmr_e_too_many_operands=07057_E_Too many operands on line
+asmr_w_near_ignored=07058_W_NEAR ignored
+asmr_w_far_ignored=07059_W_FAR ignored
+asmr_e_dup_local_sym=07060_E_Duplicate local symbol $1
+asmr_e_unknown_local_sym=07061_E_Undefined local symbol $1
+asmr_e_unknown_label_identifier=07062_E_Unknown label identifier $1
+asmr_e_invalid_register=07063_E_Invalid register name
+asmr_e_invalid_fpu_register=07064_E_Invalid floating point register name
+asmr_e_nor_not_supported=07065_E_NOR not supported
+asmr_w_modulo_not_supported=07066_W_Modulo not supported
+asmr_e_invalid_float_const=07067_E_Invalid floating point constant $1
+asmr_e_invalid_float_expr=07068_E_Invalid floating point expression
+asmr_e_wrong_sym_type=07069_E_Wrong symbol type
+asmr_e_cannot_index_relative_var=07070_E_Cannot index a local var or parameter with a register
+asmr_e_invalid_seg_override=07071_E_Invalid segment override expression
+asmr_w_id_supposed_external=07072_W_Identifier $1 supposed external
+asmr_e_string_not_allowed_as_const=07073_E_Strings not allowed as constants
+asmr_e_no_var_type_specified=07074_No type of variable specified
+asmr_w_assembler_code_not_returned_to_text=07075_E_assembler code not returned to text section
+asmr_e_not_directive_or_local_symbol=07076_E_Not a directive or local symbol $1
+asmr_w_using_defined_as_local=07077_E_Using a defined name as a local label
+#
+# Assembler/binary writers
+#
+asmr_e_dollar_without_identifier=07078_E_Dollar utilis‚ sans identificateur
+asmr_w_32bit_const_for_address=07079_W_32bit constante cr‚‚e pour une addresse
+asmr_n_align_is_target_specific=07080_N_.align d‚pend de la cible, utilisez .balign ou .p2align
+asmr_e_cannot_access_field_directly_for_parameters=07081_E_Impossible d'acc‚der directement aux champs pour des paramŠtres
+% You should load the parameter first into a register and then access the
+% fields using that register.
+asmr_e_cannot_access_object_field_directly=07082_E_Impossible d'acc‚der aux champs d'objectsou de classes directement
+% You should load the self pointer first into a register and then access the
+% fields using the register as base. By default the self pointer is available
+% in the esi register on i386.
+#
+# Assembler/binary writers
+#
+asmw_f_too_many_asm_files=08000_F_Too many assembler files
+asmw_f_assembler_output_not_supported=08001_F_Selected assembler output not supported
+asmw_f_comp_not_supported=08002_F_Comp not supported
+asmw_f_direct_not_supported=08003_F_Direct not support for binary writers
+asmw_e_alloc_data_only_in_bss=08004_E_Allocating of data is only allowed in bss section
+asmw_f_no_binary_writer_selected=08005_F_No binary writer selected
+asmw_e_opcode_not_in_table=08006_E_Asm: Opcode $1 not in table
+asmw_e_invalid_opcode_and_operands=08007_E_Asm: $1 invalid combination of opcode and operands
+asmw_e_16bit_not_supported=08008_E_Asm: 16 Bit references not supported
+asmw_e_invalid_effective_address=08009_E_Asm: Invalid effective address
+asmw_e_immediate_or_reference_expected=08010_E_Asm: Immediate or reference expected
+asmw_e_value_exceeds_bounds=08011_E_Asm: $1 value exceeds bounds $2
+asmw_e_short_jmp_out_of_range=08012_E_Asm: Short jump is out of range $1
+#
+# Executing linker/assembler
+#
+asmw_e_undefined_label=08013_E_Asm: Label $1 non d‚fini
+
+#
+# Executing linker/assembler
+#
+# BeginOfTeX
+%
+% \section{Errors of assembling/linking stage}
+% This section lists errors that occur when the compiler is processing the
+% command line or handling the configuration files.
+% \begin{description}
+exec_w_source_os_redefined=09000_W_Source operating system redefined
+exec_i_assembling_pipe=09001_I_Assembling (pipe) $1
+exec_d_cant_create_asmfile=09002_E_Can't create assember file $1
+% The mentioned file can't be create. Check if you've
+% permission to create this file
+exec_e_cant_create_objectfile=09003_E_Impossible de cr‚er le fichier object : $1
+% The mentioned file can't be create. Check if you've
+% permission to create this file
+exec_e_cant_create_archivefile=09004_E_Impossible de cr‚er le fichier archive : $1
+% The mentioned file can't be create. Check if you've
+% permission to create this file
+exec_w_assembler_not_found=09005_W_Assembler $1 not found, switching to external assembling
+exec_t_using_assembler=09006_T_Using assembler: $1
+exec_w_error_while_assembling=09007_W_Error while assembling exitcode $1
+exec_w_cant_call_assembler=09008_W_Can't call the assembler, error $1 switching to external assembling
+exec_i_assembling=09009_I_Assembling $1
+exec_i_assembling_smart=09010_I_Assemblage smartlink $1
+exec_w_objfile_not_found=09011_W_Object $1 not found, Linking may fail !
+exec_w_libfile_not_found=09012_W_Library $1 not found, Linking may fail !
+exec_w_error_while_linking=09013_W_Error while linking
+exec_w_cant_call_linker=09014_W_Can't call the linker, switching to external linking
+exec_i_linking=09015_I_Linking $1
+exec_w_util_not_found=09016_W_Utilitaire $1 non trouv‚, force la liaison externe
+exec_t_using_util=09017_T_Utilitaire $1 trouv‚
+exec_e_exe_not_supported=09018_E_Cr‚ation d'executables impossible
+exec_e_dll_not_supported=09019_E_Dynamic Libraries not supported
+exec_i_closing_script=09020_I_Closing script $1
+exec_w_res_not_found=09021_W_resource compiler not found, switching to external mode
+exec_i_compilingresource=09022_I_Compiling resource $1
+#
+# Executable information
+#
+execinfo_f_cant_process_executable=09128_F_Can't post process executable $1
+execinfo_f_cant_open_executable=09129_F_Can't open executable $1
+execinfo_x_codesize=09130_X_Size of Code: $1 bytes
+execinfo_x_initdatasize=09131_X_Size of initialized data: $1 bytes
+execinfo_x_uninitdatasize=09132_X_Size of uninitialized data: $1 bytes
+execinfo_x_stackreserve=09133_X_Stack space reserved: $1 bytes
+execinfo_x_stackcommit=09134_X_Stack space commited: $1 bytes
+# Unit loading
+#
+# BeginOfTeX
+% \section{Unit loading messages.}
+% This section lists all messages that can occur when the compiler is
+% loading a unit from disk into memory. Many of these mesages are
+% informational messages.
+% \begin{description}
+unit_t_unitsearch=10000_T_Unitsearch: $1
+% When you use the \var{-vt}, the compiler tells you where it tries to find
+% unit files.
+unit_t_ppu_loading=10001_T_PPU Loading $1
+% When the \var{-vt} switch is used, the compiler tells you
+% what units it loads.
+unit_u_ppu_name=10002_U_PPU Name: $1
+% When you use the \var{-vu} flag, the unit name is shown.
+unit_u_ppu_flags=10003_U_PPU Flags: $1
+% When you use the \var{-vu} flag, the unit flags are shown.
+unit_u_ppu_crc=10004_U_PPU Crc: $1
+% When you use the \var{-vu} flag, the unit CRC check is shown.
+unit_u_ppu_time=10005_U_PPU Time: $1
+% When you use the \var{-vu} flag, the unit time is shown.
+unit_u_ppu_file_too_short=10006_U_PPU File too short
+% When you use the \var{-vu} flag, the unit time is shown.
+unit_u_ppu_invalid_header=10007_U_PPU Invalid Header (no PPU at the begin)
+% A unit file contains as the first three bytes the ascii codes of \var{PPU}
+unit_u_ppu_invalid_version=10008_U_PPU Invalid Version $1
+% This unit file was compiled with a different version of the compiler, and
+% cannot be read.
+unit_u_ppu_invalid_processor=10009_U_PPU is compiled for another processor
+% This unit file was compiled for a different processor type, and
+% cannot be read
+unit_u_ppu_invalid_target=10010_U_PPU is compiled for another target
+% This unit file was compiled for a different processor type, and
+% cannot be read
+unit_u_ppu_source=10011_U_PPU Source: $1
+% When you use the \var{-vu} flag, the unit CRC check is shown.
+unit_u_ppu_write=10012_U_Writing $1
+% When you specify the \var{-vu} switch, the compiler will tell you where it
+% writes the unit file.
+unit_f_ppu_cannot_write=10013_F_Can't Write PPU-File
+% An err
+unit_f_ppu_read_error=10014_F_reading PPU-File
+% Unexpected end of file
+unit_f_ppu_read_unexpected_end=10015_F_unexpected end of PPU-File
+% This means that the unit file was corrupted, and contains invalid
+% information. Recompilation will be necessary.
+unit_f_ppu_invalid_entry=10016_F_Invalid PPU-File entry: $1
+% The unit the compiler is trying to read is corrupted, or generated with a
+% newer version of the compiler.
+unit_f_ppu_dbx_count_problem=10017_F_PPU Dbx count problem
+% There is an inconsistency in the debugging information of the unit.
+unit_e_illegal_unit_name=10018_E_Illegal unit name: $1
+% The name of the unit doesn't match the file name.
+unit_f_too_much_units=10019_F_Too much units
+% \fpc has a limit of 1024 units in a program. You can change this behavior
+% by changing the \var{maxunits} constant in the \file{files.pas} file of the
+% compiler, and recompiling the compiler.
+unit_f_circular_unit_reference=10020_F_Circular unit reference between $1 and $2
+% Two units are using each other in the interface part. This is only allowed
+% in the \var{implementation} part. At least one unit must contain the other one
+% in the \var{implementation} section.
+unit_f_cant_compile_unit=10021_F_Can't compile unit $1, no sources available
+% A unit was found that needs to be recompiled, but no sources are
+% available.
+unit_f_cant_find_ppu=10022_F_Impossible de trouver l'unit‚ $1
+% You tried to use a unit of which the PPU file isn't found by the
+% compiler. Check your config files for the unit pathes
+unit_w_unit_name_error=10023_W_Unit‚ $1 non trouv‚ mais $2 existe
+unit_f_unit_name_error=10024_F_Unit‚ $1 cherch‚ mais $2 trouv‚
+% Dos truncation of 8 letters for unit PPU files
+% may lead to problems when unit name is longer than 8 letters.
+unit_w_switch_us_missed=10025_W_Compiling the system unit requires the -Us switch
+% When recompiling the system unit (it needs special treatment), the
+% \var{-Us} must be specified.
+unit_f_errors_in_unit=10026_F_There were $1 errors compiling module, stopping
+% When the compiler encounters a fatal error or too many errors in a module
+% then it stops with this message.
+unit_u_load_unit=10027_U_Load from $1 ($2) unit $3
+% When you use the \var{-vu} flag, which unit is loaded from which unit is
+% shown.
+unit_u_recompile_crc_change=10028_U_Recompiling $1, checksum changed for $2
+unit_u_recompile_source_found_alone=10029_U_Recompiling $1, source found only
+% When you use the \var{-vu} flag, these messages tell you why the current
+% unit is recompiled.
+unit_u_recompile_staticlib_is_older=10030_U_Recompiling unit, static lib is older than ppufile
+% When you use the \var{-vu} flag, the compiler warns if the static library
+% of the unit are older than the unit file itself.
+unit_u_recompile_sharedlib_is_older=10031_U_Recompiling unit, shared lib is older than ppufile
+% When you use the \var{-vu} flag, the compiler warns if the shared library
+% of the unit are older than the unit file itself.
+unit_u_recompile_obj_and_asm_older=10032_U_Recompiling unit, obj and asm are older than ppufile
+% When you use the \var{-vu} flag, the compiler warns if the assembler of
+% object file of the unit are older than the unit file itself.
+unit_u_recompile_obj_older_than_asm=10033_U_Recompiling unit, obj is older than asm
+% When you use the \var{-vu} flag, the compiler warns if the assembler
+% file of the unit is older than the object file of the unit.
+unit_u_start_parse_interface=10034_U_Parsing interface of $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% parsing the interface part of the unit
+unit_u_start_parse_implementation=10035_U_Parsing implementation of $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% parsing the implementation part of the unit
+unit_u_second_load_unit=10036_U_Second load for unit $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% recompiling a unit for the second time. This can happend with interdepend
+% units.
+unit_u_check_time=10037_U_PPU Check file $1 time $2
+% When you use the \var{-vu} flag, the compiler show the filename and
+% date and time of the file which a recompile depends on
+% \end{description}
+# EndOfTeX
+
+#
+# Options
+#
+option_usage=11000_O_$1 [options] <inputfile> [options]
+# BeginOfTeX
+%
+% \section{Command-line handling errors}
+% This section lists errors that occur when the compiler is processing the
+% command line or handling the configuration files.
+% \begin{description}
+option_only_one_source_support=11001_W_Only one source file supported
+% You can specify only one source file on the command line. The first
+% one will be compiled, others will be ignored. This may indicate that
+% you forgot a \var{'-'} sign.
+option_def_only_for_os2=11002_W_DEF file can be created only for OS/2
+% This option can only be specified when you're compiling for OS/2
+option_no_nested_response_file=11003_E_nested response files are not supported
+% you cannot nest response files with the \var {@file} command-line option.
+option_no_source_found=11004_F_No source file name in command line
+% The compiler expects a source file name on the command line.
+option_no_option_found=11005_N_Aucune option trouv‚e dans le fichier de configuration $1
+% The compiler didn't find any option in that config file.
+option_illegal_para=11006_E_Illegal parameter: $1
+% You specified an unknown option.
+option_help_pages_para=11007_H_-? writes help pages
+% When an unknown option is given, this message is diplayed.
+option_too_many_cfg_files=11008_F_Too many config files nested
+% You can only nest up to 16 config files.
+option_unable_open_file=11009_F_Unable to open file $1
+% The option file cannot be found.
+option_reading_further_from=11010_N_Reading further options from $1
+% Displayed when you have notes turned on, and the compiler switches
+% to another options file.
+option_target_is_already_set=11011_W_Target is already set to: $1
+% Displayed if more than one \var{-T} option is specified.
+option_no_shared_lib_under_dos=11012_W_Shared libs not supported on DOS platform, reverting to static
+% If you specify \var{-CD} for the \dos platform, this message is displayed.
+% The compiler supports only static libraries under \dos
+option_too_many_ifdef=11013_F_too many IF(N)DEFs
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_too_many_endif=11014_F_too many ENDIFs
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_too_less_endif=11015_F_open conditional at the end of the file
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_no_debug_support=11016_W_Debug information generation is not supported by this executable
+% It is possible to have a compiler executable that doesn't support
+% the generation of debugging info. If you use such an executable with the
+% \var{-g} switch, this warning will be displayed.
+option_no_debug_support_recompile_fpc=11017_H_Try recompiling with -dGDB
+% It is possible to have a compiler executable that doesn't support
+% the generation of debugging info. If you use such an executable with the
+% \var{-g} switch, this warning will be displayed.
+option_obsolete_switch=11018_W_You are using the obsolete switch $1
+% this warns you when you use a switch that is not needed/supported anymore.
+% It is recommended that you remove the switch to overcome problems in the
+% future, when the switch meaning may change.
+option_obsolete_switch_use_new=11019_W_You are using the obsolete switch $1, please use $2
+% this warns you when you use a switch that is not supported anymore. You
+% must now use the second switch instead.
+% It is recommended that you change the switch to overcome problems in the
+% future, when the switch meaning may change.
+option_switch_bin_to_src_assembler=11020_N_Switching assembler to default source writing assembler
+% this notifies you that the assembler has been changed because you used the
+% -a switch which can't be used with a binary assembler writer.
+option_incompatible_asm=11021_W_Assembler output selected "$1" is not compatible with "$2"
+option_asm_forced=11022_W_"$1" assembler use forced
+% The assembler output selected can not generate
+% object files with the correct format. Therefore, the
+% default assembler for this target is used instead.
+%\end{description}
+# EndOfTeX
+
+#
+# Logo (option -l)
+#
+option_logo=11023_[
+Compilateur Free Pascal version $FPCFULLVERSION [$FPCDATE] pour $FPCTARGET
+Copyright (c) 1998-2011 by Florian Klaempfl
+]
+
+#
+# Info (option -i)
+#
+option_info=11024_[
+Compilateur Free Pascal version $FPCVERSION
+
+Date du compilateur : $FPCDATE
+Cible du compilateur : $FPCTARGET
+# the next lines are NOT translated on purpose !!!
+
+This program comes under the GNU General Public Licence
+For more information read COPYING.FPC
+
+Report bugs,suggestions etc to:
+ http://bugs.freepascal.org
+ou
+ bugs@freepascal.org
+]
+
+#
+# Help pages (option -? and -h)
+#
+option_help_pages=11025_[
+**0*_mettre + aprŠs un bool‚en pour activer l'option, - pour la d‚sactiver
+**1a_conserve les fichiers assembleurs cr‚‚s pendant la compilation
+**2al_liste le code source dans les fichiers assembleur
+**2ar_liste les allocations de registres dans les fichiers assembleur
+**2at_liste les allocations de donn‚es temporaire dans la pile
+**1b_g‚nŠre les informations pour le browser
+**2bl_g‚nŠre les informations locales ‚galement
+**1B_recompile toutes les unit‚s
+**1C<x>_options de g‚n‚ration de code :
+3*2CD_cr‚erune librairie dynamique
+**2Ch<n>_<n> taille du tas en bytes (entre 1023 et 67107840)
+**2Ci_IO-checking
+**2Cn_pas de linking
+**2Co_g‚nŠre des tests d'overflow pour les op‚rations sur les entiers
+**2Cr_Controle d'intervalles
+**2Cs<n>_sp‚cifie <n> comme taille de la pile
+**2Ct_test de d‚bordement de pile
+3*2CS_cr‚er une librairie statique
+3*2Cx_utiliser le smartlinking
+**1d<x>_d‚finit le symbole <x>
+*O1D_g‚nŠre un fichier DEF
+*O2Dd<x>_assigne la description … <x>
+*O2Dw_application en mode prot‚g‚
+**1e<x>_d‚finit le chemin vers l'ex‚cutable
+**1E_comme -Cn
+**1F<x>_d‚finit des chemins et noms de fichiers :
+**2FD<x>_d‚finit le r‚pertoire o— chercher les utilitaires de compilation
+**2Fe<x>_redirige les erreurs vers le fichier <x>
+**2FE<x>_r‚pertoire pour les exe/unit‚s : <x>
+**2Fi<x>_ajoute <x> … la liste des r‚pertoires pour fichiers inclus
+**2Fl<x>_ajoute <x> … la liste des r‚pertoires pour librairies
+*L2FL<x>_utilises <x> comme lieur dynamique
+**2Fo<x>_ajoute <x> … la liste des r‚pertoires pour fichiers objets
+**2Fr<x>_charge le fichier erreur <x>
+**2Fu<x>_ajoute <x> … la liste des r‚pertoires pour unit‚s
+**2FU<x>_d‚finit le r‚pertoire d'‚criture des unit‚s … <x>, en d‚pit de -FE
+*g1g<x>_g‚nŠre des informations de d‚bogage :
+*g2gg_utilise gsym
+*g2gd_utilise dbx
+*g2gh_use l'unit‚ de tracage du tas
+*g2gc_generate checks for pointers
+**1i_information
+**2iD_donne la date du compilateur
+**2iV_donne la version du compilateur
+**2iSO_donne l'OS du compilateur
+**2iSP_donne le processeur du compilateur
+**2iTO_donne l'OS cible
+**2iTP_donne le processeur cible
+**1I<x>_ajoute <x> … la liste des r‚pertoires pour fichiers inclus
+**1k<x>_transmet <x> au linker
+**1l_‚crit le logo
+**1n_ne pas lire le fichier de configuration par d‚faut
+**1o<x>_change le nom de l'executable en <x>
+**1pg_g‚nŠre du code pour profiler avec gprof
+*L1P_utilise des pipes au lieu de cr‚er des fichiers temporaires
+**1S<x>_options de syntaxe :
+**2S2_autorise quelques extensions Delphi 2
+**2Sc_autorise les operateurs type C (*=,+=,/= et -=)
+**2Sd_essaye d'ˆtre compatible avec Delphi
+**2Se_stoppe la compilation … la premiŠre erreur
+**2Sg_autorise LABEL et GOTO
+**2Sh_Utilise les ansistrings
+**2Si_supporte les INLINE type C++
+**2Sm_support des macros comme C (global)
+**2So_essaye d'ˆtre compatible avec TP/BP 7.0
+**2Sp_essaye d'ˆtre compatible avec GPC
+**2Ss_les constructeurs doivent s'appeler init (et les destructeurs done)
+**1s_n'appelle pas l'assembleur ni le linker
+**1u<x>_rend le symbole <x> non d‚fini
+**1U_options d'unit‚s :
+**2Un_ne pas v‚rifier le nom de l'unit‚
+**2Us_compiler en temps qu'unit‚ systŠme
+**1v<x>_donne des informations. <x> est une combination des lettres suivantes :
+**2*_e : montre les erreurs (d‚faut) d : informations de d‚boggage
+**2*_w : montre les avertissements u : montre les info sur les unit‚s
+**2*_n : montre les notes t : montre les fichiers essay‚s/utilis‚s
+**2*_h : montre les suggestions m : montre les macros d‚finies
+**2*_i : montre des infos g‚n‚rales p : montre les proc‚dures compil‚es
+**2*_l : montre les num‚ros de lignes c : montre les conditionniels
+**2*_a : montre tout 0 : ne montre rien (sauf les erreurs)
+**2*_b : montre toutes les proc‚dures r : mode compatibilit‚ Rhide/GCC
+**2*_ quand une erreur survient x : infos Executable (Win32 seulement)
+**2*_
+**1X_options pour executable :
+*L2Xc_lien avec librairie C
+**2XD_lien avec la librarie dynamique (d‚finit FPC_LINK_DYNAMIC)
+**2Xs_enlˆve tous les symboles de l'executable
+**2XS_lien avec les librairies statiques (d‚finit FPC_LINK_STATIC)
+**0*_options sp‚cifiques au processeur :
+3*1A<x>_format de sortie :
+3*2Aas_fichier objet g‚n‚r‚ par GNU AS
+3*2Aasaout_fichier objet g‚n‚r‚ par GNU AS pour aout (Go32v1)
+3*2Anasmcoff_fichier COFF (Go32v2) avec Nasm
+3*2Anasmelf_fichier ELF32 (Linux) avec Nasm
+3*2Anasmobj_fichier OBJ avec Nasm
+3*2Amasm_fichier OBJ avec Masm (Microsoft)
+3*2Atasm_fichier OBJ avec Tasm (Borland)
+3*2Acoff_coff (Go32v2) using internal writer
+3*2Apecoff_pecoff (Win32) using internal writer
+3*1R<x>_type lecture assembleur :
+3*2Ratt_lit l'assembleur AT&T
+3*2Rintel_lit l'assembleur Intel
+3*2Rdirect_copie le texte assembleur directement dans le fichier assembleur
+3*1O<x>_optimisations :
+3*2Og_g‚nŠre du code compact
+3*2OG_g‚nŠre du code rapide (defaut)
+3*2Or_garde certaines variables dans des registres (toujours BUGGY!!!)
+3*2Ou_autorise les optimisations incertaines (voir docs)
+3*2O1_optimisations niveau 1 (optimisations rapides)
+3*2O2_optimisations niveau 2 (-O1 + optimisations plus lentes)
+3*2O3_optimisations niveau 3 (comme -O2u)
+3*2Op<x>_processeur cible :
+3*3Op1_d‚finit 386/486 comme processeur cible
+3*3Op2_d‚finit Pentium/PentiumMMX (tm) comme processeur cycle
+3*3Op3_d‚finit PPro/PII/c6x86/K6 (tm) comme processeur cycle
+3*1T<x>_systŠme d'expliotation cible:
+3*2TEMX_OS/2 via EMX (et les extensions EMX/RSX)
+3*2TGO32V2_version 2 de l'extension DOS de DJ Delorie
+3*2TLINUX_Linux
+3*2TNETWARE_Novell Netware Module (clib)
+3*2Tnetwlibc_Novell Netware Module (libc)
+3*2TOS2_OS/2 / eComStation
+3*2TSUNOS_SunOS/Solaris
+3*2TWDOSX_WDOSX DOS extension
+3*2TWIN32_Windows 32 Bits
+6*1A<x>_output format
+6*2Aas_Unix o-file using GNU AS
+6*2Agas_GNU Motorola assembler
+6*2Amit_MIT Syntax (old GAS)
+6*2Amot_Standard Motorola assembler
+6*1O_optimizations:
+6*2Oa_turn on the optimizer
+6*2Og_generate smaller code
+6*2OG_generate faster code (default)
+6*2Ox_optimize maximum (still BUGGY!!!)
+6*2O2_set target processor to a MC68020+
+6*1R<x>_styles d'assembleur :
+6*2RMOT_lire l'assembleur type motorola
+6*1T<x>_SystŠme d'exploitation cible :
+6*2TAMIGA_Commodore Amiga
+6*2TATARI_Atari ST/STe/TT
+6*2TMACOS_Macintosh m68k
+6*2TLINUX_Linux-68k
+**1*_
+**1?_affiche cette aide
+6*1R<x>_version de l'assembleur lu
+6*2RMOT_read motorola style assembler
+6*1T<x>_Target operating system:
+6*2TAMIGA_Commodore Amiga
+6*2TATARI_Atari ST/STe/TT
+6*2TMACOS_Macintosh m68k
+6*2TLINUX_Linux-68k
+**1*_
+**1?_shows this help
+**1h_affiche cette aide sans attente
+]
+
+#
+# The End...
diff --git a/closures/compiler/msg/errorfi.msg b/closures/compiler/msg/errorfi.msg
new file mode 100644
index 0000000000..16d742c014
--- /dev/null
+++ b/closures/compiler/msg/errorfi.msg
@@ -0,0 +1,2517 @@
+#
+# This file is part of the Free Pascal Compiler
+# Copyright (c) 1999-2008 by the Free Pascal Development team
+#
+# French (ISO 8859-1) Language File for Free Pascal
+# Latest updates contributed by Rémi Dorlet <remi at dorlet.org>
+# Based on errore.msg of SVN revision 4165
+#
+# See the file COPYING.FPC, included in this distribution,
+# for details about the copyright.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#
+#
+# The constants are build in the following order:
+# <part>_<type>_<txtidentifier>
+#
+# <part> is the part of the compiler the message is used
+# asmr_ assembler parsing
+# asmw_ assembler writing/binary writers
+# unit_ unit handling
+# scan_ scanner
+# parser_ parser
+# type_ type checking
+# general_ general info
+# exec_ calls to assembler, linker, binder
+#
+# <type> the type of the message it should normally used for
+# f_ fatal error
+# e_ error
+# w_ warning
+# n_ note
+# h_ hint
+# i_ info
+# l_ add linenumber
+# u_ used
+# t_ tried
+# c_ conditional
+# d_ debug message
+# x_ executable informations
+#
+#
+# General
+#
+# 01023 is the last used one
+#
+general_text_bytes_code=01019_Code de type octet
+general_text_bytes_data=01020_Donnée de type octet
+# BeginOfTeX
+% \section{General compiler messages}
+% This section gives the compiler messages which are not fatal, but which
+% display useful information. The number of such messages can be
+% controlled with the various verbosity level \var{-v} switches.
+% \begin{description}
+general_t_compilername=01000_T_Compilateur: $1
+% When the \var{-vt} switch is used, this line tells you what compiler
+% is used.
+general_d_sourceos=01001_D_Système d'exploitation du compilateur: $1
+% When the \var{-vd} switch is used, this line tells you what the source
+% operating system is.
+general_i_targetos=01002_I_Système d'exploitation cible: $1
+% When the \var{-vd} switch is used, this line tells you what the target
+% operating system is.
+general_t_exepath=01003_T_Répertoire des fichiers exécutables: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for its binaries.
+general_t_unitpath=01004_T_Répertoire de recherche des unités: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for compiled units. You can set this path with the \var{-Fu}
+general_t_includepath=01005_T_Répertoire de recherche des fichiers inclus: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for its include files (files used in \var{\{\$I xxx\}} statements).
+% You can set this path with the \var{-I} option.
+general_t_librarypath=01006_T_Répertoire de recherche des bibliothèques: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for the libraries. You can set this path with the \var{-Fl} option.
+general_t_objectpath=01007_T_Répertoire de recherche des fichiers objet: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for object files you link in (files used in \var{\{\$L xxx\}} statements).
+% You can set this path with the \var{-Fo} option.
+general_i_abslines_compiled=01008_I_$1 lignes compilées, $2 sec$3
+% When the \var{-vi} switch is used, the compiler reports the number
+% of lines compiled, and the time it took to compile them (real time,
+% not program time).
+general_f_no_memory_left=01009_F_Plus de mémoire disponible
+% The compiler doesn't have enough memory to compile your program. There are
+% several remedies for this:
+% \begin{itemize}
+% \item If you're using the build option of the compiler, try compiling the
+% different units manually.
+% \item If you're compiling a huge program, split it up in units, and compile
+% these separately.
+% \item If the previous two don't work, recompile the compiler with a bigger
+% heap (you can use the \var{-Ch} option for this, \seeo{Ch})
+% \end{itemize}
+general_i_writingresourcefile=01010_I_Écriture du fichier de ressource: $1
+% This message is shown when the compiler writes the Resource String Table
+% file containing all the resource strings for a program.
+general_e_errorwritingresourcefile=01011_E_Écriture du fichier de chaînes de ressource: $1
+% This message is shown when the compiler encountered an error when writing
+% the Resource String Table file
+general_i_fatal=01012_I_Fatal:
+% Prefix for Fatal Errors
+general_i_error=01013_I_Erreur:
+% Prefix for Errors
+general_i_warning=01014_I_Attention:
+% Prefix for Warnings
+general_i_note=01015_I_Note:
+% Prefix for Notes
+general_i_hint=01016_I_Conseil:
+% Prefix for Hints
+general_e_path_does_not_exist=01017_E_Le chemin "$1" n'existe pas
+% The specified path does not exist.
+general_f_compilation_aborted=01018_F_Compilation interrompue
+% Compilation was aborted.
+general_i_number_of_warnings=01021_I_$1 avertissement(s) émis
+% Total number of warnings issued during compilation.
+general_i_number_of_hints=01022_I_$1 conseil(s) émis
+% Total number of hints issued during compilation.
+general_i_number_of_notes=01023_I_$1 note(s) émises
+% Total number of notes issued during compilation.
+% \end{description}
+#
+# Scanner
+#
+# 02063 is the last used one
+#
+% \section{Scanner messages.}
+% This section lists the messages that the scanner emits. The scanner takes
+% care of the lexical structure of the pascal file, i.e. it tries to find
+% reserved words, strings, etc. It also takes care of directives and
+% conditional compiling handling.
+% \begin{description}
+scan_f_end_of_file=02000_F_Fin de fichier inattendue
+% this typically happens in one of the following cases :
+% \begin{itemize}
+% \item The source file ends before the final \var{end.} statement. This
+% happens mostly when the \var{begin} and \var{end} statements aren't
+% balanced;
+% \item An include file ends in the middle of a statement.
+% \item A comment was not closed
+% \end{itemize}
+scan_f_string_exceeds_line=02001_F_Chaîne de caractères sur plus d'une ligne
+% There is a missing closing ' in a string, so it occupies
+% multiple lines.
+scan_f_illegal_char=02002_F_Caractère "$1" illégal ($2)
+% An illegal character was encountered in the input file.
+scan_f_syn_expected=02003_F_Erreur de syntaxe, "$1" attendu mais "$2" trouvé
+% This indicates that the compiler expected a different token than
+% the one you typed. It can occur almost everywhere where you make a
+% mistake against the pascal language.
+scan_t_start_include_file=02004_T_Début de lecture du fichier include $1
+% When you provide the \var{-vt} switch, the compiler tells you
+% when it starts reading an included file.
+scan_w_comment_level=02005_W_Commentaire de niveau $1 trouvé
+% When the \var{-vw} switch is used, then the compiler warns you if
+% it finds nested comments. Nested comments are not allowed in Turbo Pascal
+% and can be a possible source of errors.
+scan_n_ignored_switch=02008_N_Commutateur "$1" ignoré
+% With \var{-vn} on, the compiler warns if it ignores a switch
+scan_w_illegal_switch=02009_W_Commutateur "$1" illégal
+% You included a compiler switch (i.e. \var{\{\$... \}}) which the compiler
+% does not recognise
+scan_w_switch_is_global=02010_W_Commutateur global mal placé
+% The compiler switch is misplaced, and should be located at
+% the start of the unit or program.
+scan_e_illegal_char_const=02011_E_Constante de type char illégale
+% This happens when you specify a character with its ASCII code, as in
+% \var{\#96}, but the number is either illegal, or out of range.
+scan_f_cannot_open_input=02012_F_Impossible d'ouvrir le fichier "$1"
+% \fpc cannot find the program or unit source file you specified on the
+% command line.
+scan_f_cannot_open_includefile=02013_F_Impossible d'ouvrir le fichier include "$1"
+% \fpc cannot find the source file you specified in a \var{\{\$include ..\}}
+% statement.
+scan_e_illegal_pack_records=02015_E_Paramètre d'alignement de record incorrect "$1"
+% You are specifying the \var{\{\$PACKRECORDS n\} } or \var{\{\$ALIGN n\} }
+% with an illegal value for \var{n}. For \$PACKRECORDS valid alignments are 1, 2, 4, 8, 16, 32, C,
+% NORMAL, DEFAULT, and for \$ALIGN valid alignment are 1, 2, 4, 8, 16, 32, ON,
+% OFF. Under mode MacPas \$ALIGN also supports MAC68K, POWER and RESET.
+scan_e_illegal_pack_enum=02016_E_Paramètre de taille minimum d'énumération incorrect "$1"
+% You are specifying the \var{\{\$PACKENUM n\}} with an illegal value for
+% \var{n}. Only 1,2,4, NORMAL or DEFAULT are valid here.
+scan_e_endif_expected=02017_E_$ENDIF attendu pour $1 $2 défini dans $3 à la ligne $4
+% Your conditional compilation statements are unbalanced.
+scan_e_preproc_syntax_error=02018_E_Erreur de syntaxe pendant l'interprétation d'une directive de compilation
+% There is an error in the expression following the \var{\{\$if ..\}}, $ifc or $setc compiler
+% directives.
+scan_e_error_in_preproc_expr=02019_E_Évaluation d'une directive de compilation
+% There is an error in the expression following the \var{\{\$if ..\}}, $ifc or $setc compiler
+% directives.
+scan_w_macro_cut_after_255_chars=02020_W_Le contenu d'une macro est tronqué à 255 caractères
+% The contents of macros cannot be longer than 255 characters.
+scan_e_endif_without_if=02021_E_ENDIF sans IF(N)DEF
+% Your \var{\{\$IFDEF ..\}} and {\{\$ENDIF\}} statements aren't balanced.
+scan_f_user_defined=02022_F_Défini par l'utilisateur : $1
+% A user defined fatal error occurred. see also the \progref
+scan_e_user_defined=02023_E_Défini par l'utilisateur : $1
+% A user defined error occurred. see also the \progref
+scan_w_user_defined=02024_W_Défini par l'utilisateur : $1
+% A user defined warning occurred. see also the \progref
+scan_n_user_defined=02025_N_Défini par l'utilisateur : $1
+% A user defined note was encountered. see also the \progref
+scan_h_user_defined=02026_H_Défini par l'utilisateur : $1
+% A user defined hint was encountered. see also the \progref
+scan_i_user_defined=02027_I_Défini par l'utilisateur : $1
+% User defined information was encountered. see also the \progref
+scan_e_keyword_cant_be_a_macro=02028_E_La redéfinition d'un mot réservé en tant que macro est dans effet
+% You cannot redefine keywords with macros.
+scan_f_macro_buffer_overflow=02029_F_Débordement de tampon lors de la lecture ou de l'expansion d'une macro
+% Your macro or its result was too long for the compiler.
+scan_w_macro_too_deep=02030_W_L'expansion des macros dépasse une profondeur de 16.
+% When expanding a macro, macros have been nested to a level of 16.
+% The compiler will expand no further, since this may be a sign that
+% recursion is used.
+scan_w_wrong_styled_switch=02031_W_Les commutateurs du compilateur ne sont pas supportés dans les commentaires de style //
+% Compiler switches should be in normal pascal style comments.
+scan_d_handling_switch=02032_D_Interprétation du commutateur "$1"
+% When you set debugging info on (\var{-vd}) the compiler tells you when it
+% is evaluating conditional compile statements.
+scan_c_endif_found=02033_CL_ENDIF $1 trouvé
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifdef_found=02034_CL_IFDEF $1 trouvé, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifopt_found=02035_CL_IFOPT $1 trouvé, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_if_found=02036_CL_IF $1 trouvé, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifndef_found=02037_CL_IFNDEF $1 trouvé, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_else_found=02038_CL_ELSE $1 trouvé, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_skipping_until=02039_CL_Passant jusqu'à...
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements, and whether it is skipping or
+% compiling parts.
+scan_i_press_enter=02040_I_Appuyez sur <Entrée> pour continuer
+% When the \var{-vi} switch is used, the compiler stops compilation
+% and waits for the \var{Enter} key to be pressed when it encounters
+% a \var{\{\$STOP\}} directive.
+scan_w_unsupported_switch=02041_W_Commutateur "$1" non supporté
+% When warnings are turned on (\var{-vw}) the compiler warns you about
+% unsupported switches. This means that the switch is used in Delphi or
+% Turbo Pascal, but not in \fpc
+scan_w_illegal_directive=02042_W_Directive de compilation "$1" illégale
+% When warings are turned on (\var{-vw}) the compiler warns you about
+% unrecognised switches. For a list of recognised switches, \progref
+scan_t_back_in=02043_T_De retour dans $1
+% When you use (\var{-vt}) the compiler tells you when it has finished
+% reading an include file.
+scan_w_unsupported_app_type=02044_W_Type d'application non supportée : $1
+% You get this warning, if you specify an unknown application type
+% with the directive \var{\{\$APPTYPE\}}
+scan_w_app_type_not_support=02045_W_$APPTYPE n'est pas supporté par l'OS cible
+% The \var{\{\$APPTYPE\}} directive is supported by certain operating systems only.
+scan_w_description_not_support=02046_W_DESCRIPTION n'est pas supporté par l'OS cible
+% The \var{\{\$DESCRIPTION\}} directive is not supported on this target OS
+scan_n_version_not_support=02047_N_VERSION non supporté par l'OS cible
+% The \var{\{\$VERSION\}} directive is not supported on this target OS
+scan_n_only_exe_version=02048_N_VERSION seulement pour les EXE et les DLL
+% The \var{\{\$VERSION\}} directive is only used for executable or DLL sources.
+scan_w_wrong_version_ignored=02049_W_Mauvais format de la directive VERSION "$1"
+% The \var{\{\$VERSION\}} directive format is majorversion.minorversion
+% where majorversion and minorversion are words.
+scan_e_illegal_asmmode_specifier=02050_E_Style d'assembleur incorrect "$1"
+% When you specify an assembler mode with the \var{\{\$ASMMODE xxx\}}
+% the compiler didn't recognize the mode you specified.
+scan_w_no_asm_reader_switch_inside_asm=02051_W_Changement de type d'interpréteur ASM à l'intérieur de code assembleur, $1 sera effectif seulement pour le prochain
+% It is not possible to switch from one assembler reader to another
+% inside an assembler block. The new reader will be used for next
+% assembler statements only.
+scan_e_wrong_switch_toggle=02052_E_Mauvais argument de commutateur, utilisez ON/OFF ou +/-
+% You need to use ON or OFF or a + or - to toggle the switch
+scan_e_resourcefiles_not_supported=02053_E_Fichiers de ressources non supportés pour cette cible
+% The target you are compiling for doesn't support resource files.
+scan_w_include_env_not_found=02054_W_Variable d'environment "$1" non trouvée
+% The included environment variable can't be found in the environment, it will
+% be replaced by an empty string instead.
+scan_e_invalid_maxfpureg_value=02055_E_Valeur invalide pour nombre limite de variables en registre FPU
+% Valid values for this directive are 0..8 and NORMAL/DEFAULT
+scan_w_only_one_resourcefile_supported=02056_W_Un seul fichier de ressource est supporté pour cette cible
+% The target you are compiling for supports only one resource file.
+% The first resource file found is used, the others are discarded.
+scan_w_macro_support_turned_off=02057_W_L'utilisation des macros à été désactivée
+
+% A macro declaration has been found, but macro support is currently off,
+% so the declaration will be ignored. To turn macro support on compile with
+% -Sm on the commandline or add \{\$MACRO ON\} in the source
+scan_e_invalid_interface_type=02058_E_Type d'interface spécifié incorrect. Les valeurs acceptées sont COM, CORBA et DEFAULT.
+% The interface type that was specified is not supported
+scan_w_appid_not_support=02059_W_APPID n'est supporté que pour PalmOS
+% The \var{\{\$APPID\}} directive is only supported for the PalmOS target.
+scan_w_appname_not_support=02060_W_APPNAME n'est supporté que pour PalmOS
+% The \var{\{\$APPNAME\}} directive is only supported for the PalmOS target.
+scan_e_string_exceeds_255_chars=02061_E_Les constantes chaîne de caractères ne peuvent dépasser 255 caractères
+% A single string constant can contain at most 255 chars. Try splitting up the
+% string in multiple smaller parts and concatenate them with a + operator.
+scan_f_include_deep_ten=02062_F_La profondeur des inclusions de fichiers include dépasse 16.
+% When including include files the files have been nested to a level of 16.
+% The compiler will expand no further, since this may be a sign that
+% recursion is used.
+scan_e_too_many_push=02063_F_Trop de niveaux de PUSH
+% A maximum of 20 levels is allowed. This error occurs only in mode MacPas.
+scan_e_too_many_pop=02064_E_Un POP non précédé d'un PUSH
+% This error occurs only in mode MacPas.
+scan_e_error_macro_lacks_value=02065_E_Macro ou variable d´heure de compilation "$1" sans valeur
+% Thus the conditional compile time expression cannot be evaluated.
+scan_e_wrong_switch_toggle_default=02066_E_Mauvais argument de commutateur, utilisez ON/OFF/DEFAULT ou +/-/*
+% You need to use ON or OFF or DEFAULT or a + or - or * to toggle the switch
+scan_e_mode_switch_not_allowed=02067_E_Le commutateur de mode "$1" n'est pas autorisé ici
+% A mode switch has already been encountered, or, in case of option -Mmacpas,
+% a mode switch occur after UNIT.
+scan_e_error_macro_undefined=02068_E_Macro ou variable d´heure de compilation "$1" non définie
+% Thus the conditional compile time expression cannot be evaluated. Only in mode MacPas.
+scan_e_utf8_bigger_than_65535=02069_E_Code UTF-8 supérieur à 65535 trouvé
+% \fpc handles utf-8 strings internally as widestrings e.g. the char codes are limited to 65535
+scan_e_utf8_malformed=02070_E_Chaîne UTF-8 malformée
+% The given string isn't a valid UTF-8 string
+scan_c_switching_to_utf8=02071_C_Signature UTF-8 trouvée, utilisation de l'encodage UTF-8
+% The compiler found an UTF-8 encoding signature (\$ef, \$bb, \$bf) at the beginning of a file,
+% so it interprets it as an UTF-8 file
+scan_e_compile_time_typeerror=02072_E_Heure de compilation: $1 attendue mais $2 à $3 obtenue
+% Type check of a compile time expression failed.
+scan_n_app_type_not_support=02073_N_APPTYPE n'est pas supporté par l'OS cible
+% The \var{\{\$APPTYPE\}} directive is supported by certain operating systems only.
+scan_e_illegal_optimization_specifier=02074_E_Optimisation "$1" spécifiée incorrecte
+% When you specify an optimization with the \var{\{\$OPTIMIZATION xxx\}}
+% the compiler didn't recognize the optimization you specified.
+scan_w_setpeflags_not_support=02075_W_SETPEFLAGS n'est pas supporté par l'OS cible
+% The \var{\{\$SETPEFLAGS\}} directive is not supported by the target OS
+scan_w_imagebase_not_support=02076_W_IMAGEBASE n'est pas supporté par l'OS cible
+% The \var{\{\$IMAGEBASE\}} directive is not supported by the target OS
+scan_w_minstacksize_not_support=02077_W_MINSTACKSIZE n'est pas supporté sur l'OS cible
+% The \var{\{\$MINSTACKSIZE\}} directive is not supported by the target OS
+scan_w_maxstacksize_not_support=02078_W_MAXSTACKSIZE n'est pas supporté sur l'OS cible
+% The \var{\{\$MAXSTACKSIZE\}} directive is not supported by the target OS
+% \end{description}
+#
+# Parser
+#
+# 03192 is the last used one
+#
+% \section{Parser messages}
+% This section lists all parser messages. The parser takes care of the
+% semantics of you language, i.e. it determines if your pascal constructs
+% are correct.
+% \begin{description}
+parser_e_syntax_error=03000_E_Analyseur syntaxique - Erreur de syntaxe
+% An error against the Turbo Pascal language was encountered. This happens
+% typically when an illegal character is found in the sources file.
+parser_e_dont_nest_interrupt=03004_E_Une procédure de type INTERRUPT ne peut pas être imbriquée
+% An \var{INTERRUPT} procedure must be global.
+parser_w_proc_directive_ignored=03005_W_Type procédure "$1" ignoré
+% The specified procedure directive is ignored by FPC programs.
+parser_e_no_overload_for_all_procs=03006_E_Toutes les déclaration de "$1" ne sont pas déclarées OVERLOAD
+% When you want to use overloading using the \var{OVERLOAD} directive, then
+% all declarations need to have \var{OVERLOAD} specified.
+parser_e_export_name_double=03008_E_Nom de fonction exportée "$1" dupliqué
+% Exported function names inside a specific DLL must all be different
+parser_e_export_ordinal_double=03009_E_Index de fonction exportée "$1" dupliqué
+% Exported function names inside a specific DLL must all be different
+parser_e_export_invalid_index=03010_E_Index de fonction exportée invalide
+% DLL function index must be in the range \var{1..\$FFFF}
+parser_w_parser_reloc_no_debug=03011_W_Les DLL ou EXE relogeables sont incompatibles avec les informations de débogage, débogage désactivé.
+parser_w_parser_win32_debug_needs_WN=03012_W_Pour permettre le débogage de code win32, utilisez l'option -WN
+% Stabs info is wrong for relocatable DLL or EXES use -WN
+% if you want to debug win32 executables.
+parser_e_constructorname_must_be_init=03013_E_Le nom du constructeur doit être INIT
+% You are declaring an object constructor with a name which is not \var{init}, and the
+% \var{-Ss} switch is in effect. See the \var{-Ss} switch (\seeo{Ss}).
+parser_e_destructorname_must_be_done=03014_E_Le nom du destructeur doit être DONE
+% You are declaring an object destructor with a name which is not \var{done}, and the
+% \var{-Ss} switch is in effect. See the \var{-Ss} switch (\seeo{Ss}).
+parser_e_proc_inline_not_supported=03016_E_Procédure INLINE non supportée
+% You tried to compile a program with C++ style inlining, and forgot to
+% specify the \var{-Si} option (\seeo{Si}). The compiler doesn't support C++
+% styled inlining by default.
+parser_w_constructor_should_be_public=03018_W_Le constructeur devrait être public
+% Constructors must be in the 'public' part of an object (class) declaration.
+parser_w_destructor_should_be_public=03019_W_Le destructeur devrait être public
+% Destructors must be in the 'public' part of an object (class) declaration.
+parser_n_only_one_destructor=03020_N_Les classes ne doivent avoir qu'un seul destructeur
+% You can declare only one destructor for a class.
+parser_e_no_local_objects=03021_E_Les définitions de classes locales ne sont pas autorisées
+% Classes must be defined globally. They cannot be defined inside a
+% procedure or function
+parser_f_no_anonym_objects=03022_F_Les définitions de classes anonymes sont interdites
+% An invalid object (class) declaration was encountered, i.e. an
+% object or class without methods that isn't derived from another object or
+% class. For example:
+% \begin{verbatim}
+% Type o = object
+% a : longint;
+% end;
+% \end{verbatim}
+% will trigger this error.
+parser_n_object_has_no_vmt=03023_N_L'objet "$1" n'a pas de VMT
+% This is a note indicating that the declared object has no
+% virtual method table.
+parser_e_illegal_parameter_list=03024_E_Liste de paramètres illégale
+% You are calling a function with parameters that are of a different type than
+% the declared parameters of the function.
+parser_e_wrong_parameter_size=03026_E_Mauvais nombre de paramètres spécifié
+% There is an error in the parameter list of the function or procedure,
+% the number of parameters is not correct.
+parser_e_overloaded_no_procedure=03027_E_L'identificateur surchargé "$1" n'est pas une fonction
+% The compiler encountered a symbol with the same name as an overloaded
+% function, but it is not a function it can overload.
+parser_e_overloaded_have_same_parameters=03028_E_Les fonctions surchargées ont les mêmes paramètres
+% You're declaring overloaded functions, but with the same parameter list.
+% Overloaded function must have at least 1 different parameter in their
+% declaration.
+parser_e_header_dont_match_forward=03029_E_L'en-tête de la fonction ne correspond pas à la déclaration anticipée "$1"
+% You declared a function with same parameters but
+% different result type or function modifiers.
+parser_e_header_different_var_names=03030_E_L'entête de la fonction "$1" ne correspond pas à sa déclaration anticipée : le nom de variable change $2 => $3
+% You declared the function in the \var{interface} part, or with the
+% \var{forward} directive, but define it with a different parameter list.
+parser_n_duplicate_enum=03031_N_Les valeurs d'une énumération doivent être en ordre croissant
+% \fpc allows enumeration constructions as in C. Given the following
+% declaration two declarations:
+% \begin{verbatim}
+% type a = (A_A,A_B,A_E:=6,A_UAS:=200);
+% type a = (A_A,A_B,A_E:=6,A_UAS:=4);
+% \end{verbatim}
+% The second declaration would produce an error. \var{A\_UAS} needs to have a
+% value higher than \var{A\_E}, i.e. at least 7.
+parser_e_no_with_for_variable_in_other_segments=03033_E_With ne peut pas être utilisé avec les variables d'un autre segment
+% With stores a variable locally on the stack,
+% but this is not possible if the variable belongs to another segment.
+parser_e_too_much_lexlevel=03034_E_Niveau d'inbrication de fonctions > 31
+% You can nest function definitions only 31 times.
+parser_e_range_check_error=03035_E_Erreur d'intervalle dans l'évaluation d'une constante
+% The constants are out of their allowed range.
+parser_w_range_check_error=03036_W_Erreur d'intervalle dans l'évaluation d'une constante
+% The constants are out of their allowed range.
+parser_e_double_caselabel=03037_E_Valeur dupliquée dans une instruction CASE
+% You are specifying the same label 2 times in a \var{case} statement.
+parser_e_case_lower_less_than_upper_bound=03038_E_Valeur max. inférieure à la valeur min. dans l'instruction CASE
+% The upper bound of a \var{case} label is less than the lower bound and this
+% is useless
+parser_e_type_const_not_possible=03039_E_Les constantes typées de classes sont interdites
+% You cannot declare a constant of type class or object.
+parser_e_no_overloaded_procvars=03040_E_Les variables fonction de fonctions surchargées ne sont pas autorisées
+% You are trying to assign an overloaded function to a procedural variable.
+% This is not allowed
+parser_e_invalid_string_size=03041_E_La longueur d'une chaîne doit être comprise entre 1 et 255
+% The length of a shortstring in Pascal is limited to 255 characters. You are
+% trying to declare a string with length lower than 1 or greater than 255
+parser_w_use_extended_syntax_for_objects=03042_W_Utilisez la syntaxe étendue de NEW et DISPOSE pour les instances d'objet
+% If you have a pointer \var{a} to a class type, then the statement
+% \var{new(a)} will not initialize the class (i.e. the constructor isn't
+% called), although space will be allocated. you should issue the
+% \var{new(a,init)} statement. This will allocate space, and call the
+% constructor of the object
+parser_w_no_new_dispose_on_void_pointers=03043_W_L'usage de NEW ou DISPOSE pour des pointeurs non typés n'a pas de sens
+parser_e_no_new_dispose_on_void_pointers=03044_E_L'usage de NEW ou DISPOSE pour des pointeurs non typés est impossible
+% You cannot use \var{new(p)} or \var{dispose(p)} if \var{p} is an untyped pointer
+% because no size is associated to an untyped pointer.
+% Accepted for compatibility in \var{tp} and \var{delphi} modes.
+parser_e_class_id_expected=03045_E_Identificateur de classe attendu
+% This happens when the compiler scans a procedure declaration that contains
+% a dot,
+% i.e., a object or class method, but the type in front of the dot is not
+% a known type.
+parser_e_no_type_not_allowed_here=03046_E_Identificateur de type interdit ici
+% You cannot use a type inside an expression.
+parser_e_methode_id_expected=03047_E_Identificateur de méthode attendu
+% This identifier is not a method.
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., a object or class method, but the procedure name is not a
+% procedure of this type.
+parser_e_header_dont_match_any_member=03048_E_L'en-tête de la fonction ne correspond à aucune méthode de cette classe "$1"
+% This identifier is not a method.
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., a object or class method, but the procedure name is not a
+% procedure of this type.
+parser_d_procedure_start=03049_DL_procédure/fonction $1
+% When using the \var{-vd} switch, the compiler tells you when it starts
+% processing a procedure or function implementation.
+parser_e_error_in_real=03050_E_Constante réelle illégale
+% The compiler expects a floating point expression, and gets something else.
+parser_e_fail_only_in_constructor=03051_E_FAIL ne peut être utilisé que dans un constructeur
+% You are using the \var{fail} keyword outside a constructor method.
+parser_e_no_paras_for_destructor=03052_E_Les destructeurs ne peuvent pas avoir de paramètres
+% You are declaring a destructor with a parameter list. Destructor methods
+% cannot have parameters.
+parser_e_only_class_methods_via_class_ref=03053_E_Seules des références de classe peuvent faire référence à des méthodes de classe
+% This error occurs in a situation like the following:
+% \begin{verbatim}
+% Type :
+% Tclass = Class of Tobject;
+%
+% Var C : TClass;
+%
+% begin
+% ...
+% C.free
+% \end{verbatim}
+% \var{Free} is not a class method and hence cannot be called with a class
+% reference.
+parser_e_only_class_methods=03054_E_Seules des méthodes de classe peuvent être appelées dans des méthodes de classe
+% This is related to the previous error. You cannot call a method of an object
+% from a inside a class method. The following code would produce this error:
+% \begin{verbatim}
+% class procedure tobject.x;
+%
+% begin
+% free
+% \end{verbatim}
+% Because free is a normal method of a class it cannot be called from a class
+% method.
+parser_e_case_mismatch=03055_E_La constante et l'instruction CASE ne sont pas du même type
+% One of the labels is not of the same type as the case variable.
+parser_e_illegal_symbol_exported=03056_E_Le symbole ne peut pas être exporté depuis une bibliothèque
+% You can only export procedures and functions when you write a library. You
+% cannot export variables or constants.
+parser_w_should_use_override=03057_W_Une méthode héritée est cachée par "$1"
+% A method that is declared \var{virtual} in a parent class, should be
+% overridden in the descendent class with the \var{override} directive. If you
+% don't specify the \var{override} directive, you will hide the parent method;
+% you will not override it.
+parser_e_nothing_to_be_overridden=03058_E_Il n'y a pas de méthode dans la classe ancêtre que l'on peut surcharger : "$1"
+% You are trying to \var{override} a virtual method of a parent class that does
+% not exist.
+parser_e_no_procedure_to_access_property=03059_E_Aucun membre n'est fourni pour accéder à la propriété
+% You specified no \var{read} directive for a property.
+parser_w_stored_not_implemented=03060_W_Directive de propriété stockée non encore implementée
+% The \var{stored} directive is not yet implemented
+parser_e_ill_property_access_sym=03061_E_Symbole illégal pour l'accès à la propriété
+% There is an error in the \var{read} or \var{write} directives for an array
+% property. When you declare an array property, you can only access it with
+% procedures and functions. The following code would cause such an error.
+% \begin{verbatim}
+% tmyobject = class
+% i : integer;
+% property x [i : integer]: integer read I write i;
+% \end{verbatim}
+%
+parser_e_cant_access_protected_member=03062_E_Impossible d'accéder aux champs "protected" d'un object ici
+% Fields that are declared in a \var{protected} section of an object or class
+% declaration cannot be accessed outside the module where the object is
+% defined, or outside descendent object methods.
+parser_e_cant_access_private_member=03063_E_Impossible d'accéder aux champs "private" d'un object ici
+% Fields that are declared in a \var{private} section of an object or class
+% declaration cannot be accessed outside the module where the class is
+% defined.
+parser_e_overridden_methods_not_same_ret=03066_E_Les méthodes surchargées doivent renvoyer le même type: "$2" est surchargée par "$1" qui retourne un type différent
+% If you declare overridden methods in a class definition, they must
+% have the same return type.
+parser_e_dont_nest_export=03067_E_Les fonctions déclarées comme EXPORT ne peuvent pas être imbriquées
+% You cannot declare a function or procedure within a function or procedure
+% that was declared as an export procedure.
+parser_e_methods_dont_be_export=03068_E_Les méthodes ne peuvent pas être EXPORTées
+% You cannot declare a procedure that is a method for an object as
+% \var{export}ed.
+parser_e_call_by_ref_without_typeconv=03069_E_Les paramètres passés par adresse doivent être du même type que la déclaration: "$1" spécifié mais "$2" attendu
+% When calling a function declared with \var{var} parameters, the variables in
+% the function call must be of exactly the same type. There is no automatic
+% type conversion.
+parser_e_no_super_class=03070_E_Cette classe n'est pas un parent de la classe actuelle
+% When calling inherited methods, you are trying to call a method of a non-related
+% class. You can only call an inherited method of a parent class.
+parser_e_self_not_in_method=03071_E_Self n'est possible que dans les méthodes
+% You are trying to use the \var{self} parameter outside an object's method.
+% Only methods get passed the \var{self} parameters.
+parser_e_generic_methods_only_in_methods=03072_E_Une méthode ne peut être appelée avec son identificateur de classe qu'à partir d'une méthode
+% A construction like \var{sometype.somemethod} is only allowed in a method.
+parser_e_illegal_colon_qualifier=03073_E_Utilisation non valide de ':'
+% You are using the format \var{:} (colon) 2 times on an expression that
+% is not a real expression.
+parser_e_illegal_set_expr=03074_E_Erreur d'intervalle dans un constructeur d'ensemble ou élément d'ensemble dupliqué
+% The declaration of a set contains an error. Either one of the elements is
+% outside the range of the set type, either two of the elements are in fact
+% the same.
+parser_e_pointer_to_class_expected=03075_E_Pointeur sur un objet attendu
+% You specified an illegal type in a \var{new} statement.
+% The extended syntax of \var{new} needs an object as a parameter.
+parser_e_expr_have_to_be_constructor_call=03076_E_L'expression doit être un appel à un constructeur
+% When using the extended syntax of \var{new}, you must specify the constructor
+% method of the object you are trying to create. The procedure you specified
+% is not a constructor.
+parser_e_expr_have_to_be_destructor_call=03077_E_L'expression doit être un appel à un destructeur
+% When using the extended syntax of \var{dispose}, you must specify the
+% destructor method of the object you are trying to dispose of.
+% The procedure you specified is not a destructor.
+parser_e_invalid_record_const=03078_E_Mauvais ordre des éléments d'un record
+% When declaring a constant record, you specified the fields in the wrong
+% order.
+parser_e_false_with_expr=03079_E_L'expression doit être une classe ou un record
+% A \var{with} statement needs an argument that is of the type \var{record}
+% or \var{class}. You are using \var{with} on an expression that is not of
+% this type.
+parser_e_void_function=03080_E_Les procédures ne peuvent pas retourner une valeur
+% In \fpc, you can specify a return value for a function when using
+% the \var{exit} statement. This error occurs when you try to do this with a
+% procedure. Procedures cannot return a value.
+parser_e_only_methods_allowed=03081_E_Les constructeurs, les destructeurs et les class operators doivent être des méthodes
+% You're declaring a procedure as destructor, constructor or class operators, when the
+% procedure isn't a class method.
+parser_e_operator_not_overloaded=03082_E_L'opérateur n'est pas surchargé
+% You're trying to use an overloaded operator when it is not overloaded for
+% this type.
+parser_e_no_such_assignment=03083_E_Impossible de surcharger l'affectation de types équivalents
+% You can not overload assignment for types
+% that the compiler considers as equal.
+parser_e_overload_impossible=03084_E_Surcharge d'opérateur impossible
+% The combination of operator, arguments and return type are
+% incompatible.
+parser_e_no_reraise_possible=03085_E_Redéclenchement d'exception impossible ici
+% You are trying to raise an exception where it is not allowed. You can only
+% raise exceptions in an \var{except} block.
+parser_e_no_new_or_dispose_for_classes=03086_E_La syntaxe étendue de new ou dispose n'est pas autorisée pour une classe
+% You cannot generate an instance of a class with the extended syntax of
+% \var{new}. The constructor must be used for that. For the same reason, you
+% cannot call \var{dispose} to de-allocate an instance of a class, the
+% destructor must be used for that.
+parser_e_procedure_overloading_is_off=03088_E_La surcharge de procédures est désactivée
+% When using the \var{-So} switch, procedure overloading is switched off.
+% Turbo Pascal does not support function overloading.
+parser_e_overload_operator_failed=03089_E_Impossible de surcharger cet opérateur
+% You are trying to overload an operator which cannot be overloaded.
+% The following operators can be overloaded :
+% \begin{verbatim}
+% +, -, *, /, =, >, <, <=, >=, is, as, in, **, :=
+% \end{verbatim}
+parser_e_comparative_operator_return_boolean=03090_E_Un opératuer de comparaison doit retourner une valeur booléenne
+% When overloading the \var{=} operator, the function must return a boolean
+% value.
+parser_e_only_virtual_methods_abstract=03091_E_Seules les méthodes virtuelles peuvent être abstraites
+% You are declaring a method as abstract, when it is not declared to be
+% virtual.
+parser_f_unsupported_feature=03092_F_Utilisation d'une caractéristique non supportée !
+% You're trying to force the compiler into doing something it cannot do yet.
+parser_e_mix_of_classes_and_objects=03093_E_Le mélange de différents types d'objets (classe, objet, interface, etc.) est interdit
+% You cannot derive \var{objects}, \var{classes}, \var{cppclasses} and \var{interfaces} interttwined . E.g.
+% a class cannot have an object as parent and vice versa.
+parser_w_unknown_proc_directive_ignored=03094_W_Une directive de procédure inconnue a due être ignorée : "$1"
+% The procedure directive you specified is unknown.
+parser_e_absolute_only_one_var=03095_E_absolute ne peut être associé qu'à une seule variable
+% You cannot specify more than one variable before the \var{absolute} directive.
+% Thus, the following construct will provide this error:
+% \begin{verbatim}
+% Var Z : Longint;
+% X,Y : Longint absolute Z;
+% \end{verbatim}
+% \item [ absolute can only be associated a var or const ]
+% The address of a \var{absolute} directive can only point to a variable or a
+% typed constant. Therefore, the following code will produce this error:
+% \begin{verbatim}
+% Procedure X;
+%
+% var p : longint absolute x;
+% \end{verbatim}
+%
+parser_e_absolute_only_to_var_or_const=03096_E_absolute ne peut être associé qu'à une variable ou une constante
+% The address of a \var{absolute} directive can only point to a variable or
+% constant. Therefore, the following code will produce this error:
+% \begin{verbatim}
+% Procedure X;
+%
+% var p : longint absolute x;
+% \end{verbatim}
+%
+parser_e_initialized_only_one_var=03097_E_Seule UNE variable peut être initialisée
+% You cannot specify more than one variable with a initial value
+% in Delphi mode.
+parser_e_abstract_no_definition=03098_E_Les méthodes abstraites ne doivent pas avoir d'implementation
+% Abstract methods can only be declared, you cannot implement them. They
+% should be overridden by a descendant class.
+parser_e_overloaded_must_be_all_global=03099_E_Cette fonction surchargée ne peut pas être locale (elle doit être exportée)
+% You are defining a overloaded function in the implementation part of a unit,
+% but there is no corresponding declaration in the interface part of the unit.
+parser_w_virtual_without_constructor=03100_W_Des méthodes virtuelles sont utilisées sans constructeur dans "$1"
+% If you declare objects or classes that contain virtual methods, you need
+% to have a constructor and destructor to initialize them. The compiler
+% encountered an object or class with virtual methods that doesn't have
+% a constructor/destructor pair.
+parser_c_macro_defined=03101_CL_Macro définie: $1
+% When \var{-vc} is used, the compiler tells you when it defines macros.
+parser_c_macro_undefined=03102_CL_Macro non défine: $1
+% When \var{-vc} is used, the compiler tells you when it undefines macros.
+parser_c_macro_set_to=03103_CL_Macro $1 définie à $2
+% When \var{-vc} is used, the compiler tells you what values macros get.
+parser_i_compiling=03104_I_Compilation de $1
+% When you turn on information messages (\var{-vi}), the compiler tells you
+% what units it is recompiling.
+parser_u_parsing_interface=03105_U_Analyse syntaxique de l'interface de l'unité $1
+% This tells you that the reading of the interface
+% of the current unit starts
+parser_u_parsing_implementation=03106_U_Analyse syntaxique de l'implémentation de $1
+% This tells you that the code reading of the implementation
+% of the current unit, library or program starts
+parser_d_compiling_second_time=03107_DL_Compilation de $1 pour la seconde fois
+% When you request debug messages (\var{-vd}) the compiler tells you what
+% units it recompiles for the second time.
+parser_e_no_property_found_to_override=03109_E_Aucune propriété à surcharger n'a été trouvée
+% You want to override a property of a parent class, when there is, in fact,
+% no such property in the parent class.
+parser_e_only_one_default_property=03110_E_Une seule propriété par défaut est autorisée
+% You specified a property as \var{Default}, but the class already has a
+% default property, and a class can have only one default property.
+parser_e_property_need_paras=03111_E_La propriété par défaut doit être de type tableau
+% Only array properties of classes can be made \var{default} properties.
+parser_e_constructor_cannot_be_not_virtual=03112_E_Les constructeurs virtuels ne sont possibles que pour les classes
+% You cannot have virtual constructors in objects. You can only have them
+% in classes.
+parser_e_no_default_property_available=03113_E_Pas de propriété par défaut disponible
+% You are trying to access a default property of a class, but this class (or one of
+% its ancestors) doesn't have a default property.
+parser_e_cant_have_published=03114_E_La classe ne peut pas avoir une section "published", utilisez le commutateur {$M+}
+% If you want a \var{published} section in a class definition, you must
+% use the \var{\{\$M+\}} switch, whch turns on generation of type
+% information.
+parser_e_forward_declaration_must_be_resolved=03115_E_La déclaration anticipée de la classe "$1" doit être résolue ici pour pouvoir utiliser la classe comme ancêtre
+% To be able to use an object as an ancestor object, it must be defined
+% first. This error occurs in the following situation:
+% \begin{verbatim}
+% Type ParentClas = Class;
+% ChildClass = Class(ParentClass)
+% ...
+% end;
+% \end{verbatim}
+% Where \var{ParentClass} is declared but not defined.
+parser_e_no_local_operator=03116_E_Les opérateurs locaux ne sont pas supportés
+% You cannot overload locally, i.e. inside procedures or function
+% definitions.
+parser_e_proc_dir_not_allowed_in_interface=03117_E_La directive de procédure "$1" n'est pas autorisée dans la section interface
+% This procedure directive is not allowed in the \var{interface} section of
+% a unit. You can only use it in the \var{implementation} section.
+parser_e_proc_dir_not_allowed_in_implementation=03118_E_La directive de procédure "$1" n'est pas autorisée dans la section implementation
+% This procedure directive is not defined in the \var{implementation} section of
+% a unit. You can only use it in the \var{interface} section.
+parser_e_proc_dir_not_allowed_in_procvar=03119_E_La directive de procédure "$1" n'est pas autorisée dans la déclaration
+% This procedure directive cannot be part of a procedural or function
+% type declaration.
+parser_e_function_already_declared_public_forward=03120_E_La fonction "$1" est déjà déclarée comme Public ou Forward
+% You will get this error if a function is defined as \var{forward} twice.
+% Or it is once in the \var{interface} section, and once as a \var{forward}
+% declaration in the \var{implmentation} section.
+parser_e_not_external_and_export=03121_E_Impossible d'utiliser à la fois EXPORT et EXTERNAL
+% These two procedure directives are mutually exclusive
+parser_w_not_supported_for_inline=03123_W_"$1" n'est pas encore supporté à l'intérieur de procédures/fonctions INLINE
+% Inline procedures don't support this declaration.
+parser_w_inlining_disabled=03124_W_Inlining désactivé
+% Inlining of procedures is disabled.
+parser_i_writing_browser_log=03125_I_Ecriture du Browser log $1
+% When information messages are on, the compiler warns you when it
+% writes the browser log (generated with the \var{\{\$Y+ \}} switch).
+parser_h_maybe_deref_caret_missing=03126_H_Le déréférencement du pointeur semble manquer
+% The compiler thinks that a pointer may need a dereference.
+parser_f_assembler_reader_not_supported=03127_F_Lecteur de code assembleur sélectionné non supporté
+% The selected assembler reader (with \var{\{\$ASMMODE xxx\}} is not
+% supported. The compiler can be compiled with or without support for a
+% particular assembler reader.
+parser_e_proc_dir_conflict=03128_E_La directive de procédure "$1" entre en conflit avec d'autres directives
+% You specified a procedure directive that conflicts with other directives.
+% for instance \var{cdecl} and \var{pascal} are mutually exclusive.
+parser_e_call_convention_dont_match_forward=03129_E_La convention d'appel ne correspond pas à la déclaration anticipée
+% This error happens when you declare a function or procedure with
+% e.g. \var{cdecl;} but omit this directive in the implementation, or vice
+% versa. The calling convention is part of the function declaration, and
+% must be repeated in the function definition.
+parser_e_property_cant_have_a_default_value=03131_E_Cette propriété ne peut pas avoir de valeur par défaut
+% Set properties or indexed properties cannot have a default value.
+parser_e_property_default_value_must_const=03132_E_La valeur par défaut d'une propriété doit être une constante
+% The value of a \var{default} declared property must be known at compile
+% time. The value you specified is only known at run time. This happens
+% .e.g. if you specify a variable name as a default value.
+parser_e_cant_publish_that=03133_E_Ce symbole ne peut pas être "published", il ne peut être qu'une classe
+% Only class type variables can be in a \var{published} section of a class
+% if they are not declared as a property.
+parser_e_cant_publish_that_property=03134_E_Ce genre de propriété ne peut pas être PUBLISHED
+% Properties in a \var{published} section cannot be array properties.
+% they must be moved to public sections. Properties in a \var{published}
+% section must be an ordinal type, a real type, strings or sets.
+parser_e_empty_import_name=03136_W_Un nom d'import est requis
+% Some targets need a name for the imported procedure or a \var{cdecl} specifier
+parser_e_division_by_zero=03138_E_Division par zéro
+% There is a division by zero encounted
+parser_e_invalid_float_operation=03139_E_Opération en virgule flottante invalide
+% An operation on two real type values produced an overflow or a division
+% by zero.
+parser_e_array_lower_less_than_upper_bound=03140_E_Limite supérieure de l'intervalle plus petite que la limite inférieure
+% The upper bound of a an array declaration is less than the lower bound and this
+% is not possible
+parser_w_string_too_long=03141_W_La chaîne "$1" est plus longue que $2
+% The size of the constant string is larger than the size you specified in
+% string type definition
+parser_e_string_larger_array=03142_E_Longueur de chaîne supérieure à la longueur d'un tableau de caractères
+% The size of the constant string is larger than the size you specified in
+% the array[x..y] of char definition
+parser_e_ill_msg_expr=03143_E_Expression illégale après la directive Message
+% \fpc supports only integer or string values as message constants
+parser_e_ill_msg_param=03144_E_Les gestionnaires de message ne peuvent accepter qu'un paramètre par référence
+% A method declared with the \var{message}-directive as message handler
+% can take only one parameter which must be declared as call by reference
+% Parameters are declared as call by reference using the \var{var}-directive
+parser_e_duplicate_message_label=03145_E_Message dupliqué dans un objet ou une classe: "%1"
+% A label for a message is used twice in one object/class
+parser_e_self_in_non_message_handler=03146_E_Self ne peut être qu'un paramètre explicite dans les gestionnaires de message
+% The self parameter can only be passed explicitly to a method which
+% is declared as message handler.
+parser_e_threadvars_only_sg=03147_E_Les variables de Threads peuvent seulement être statiques ou globales
+% Threadvars must be static or global, you can't declare a thread
+% local to a procedure. Local variables are always local to a thread,
+% because every thread has its own stack and local variables
+% are stored on the stack
+parser_f_direct_assembler_not_allowed=03148_F_Assembleur direct non supporté pour la sortie binaire
+% You can't use direct assembler when using a binary writer, choose an
+% other outputformat or use another assembler reader
+parser_w_no_objpas_use_mode=03149_W_Ne chargez pas l'unité OBJPAS manuellement, utilisez de préférence \{\$mode Objfpc\} ou \{\$mode Delphi\}
+% You are trying to load the ObjPas unit manually from a uses clause. This is
+% not a good idea. Use the \var{\{\$mode objfpc\}} or
+% \var{\{\$mode delphi\}}
+% directives which load the unit automatically
+parser_e_no_object_override=03150_E_OVERRIDE ne peut pas être utilisé avec des objets
+% Override is not supported for objects, use \var{virtual} instead to override
+% a method of a parent object
+parser_e_cant_use_inittable_here=03151_E_Les types de données nécessitant une initialisation/finalisation ne peuvent pas être utilisés dans des records variants
+% Some data type (e.g. \var{ansistring}) needs initialization/finalization
+% code which is implicitly generated by the compiler. Such data types
+% can't be used in the variant part of a record.
+parser_e_resourcestring_only_sg=03152_E_Les chaînes de ressource ne peuvent être que statiques ou globales
+% Resourcestring can not be declared local, only global or using the static
+% directive.
+parser_e_exit_with_argument_not__possible=03153_E_Exit avec un argument ne peut pas être utilisé ici
+% an exit statement with an argument for the return value can't be used here, this
+% can happen e.g. in \var{try..except} or \var{try..finally} blocks
+parser_e_stored_property_must_be_boolean=03154_E_Le type du symbole STORED doit être un booléen
+% If you specify a storage symbol in a property declaration, it must be of
+% the type boolean
+parser_e_ill_property_storage_sym=03155_E_Ce symbole n'est pas admis comme symbole STORED
+% You can't use this type of symbol as storage specifier in property
+% declaration. You can use only methods with the result type boolean,
+% boolean class fields or boolean constants
+parser_e_only_publishable_classes_can__be_published=03156_E_Seules les classes compilées avec le mode $M+ peuvent être PUBLISHED
+% In the published section of a class can be only class as fields used which
+% are compiled in \var{\{\$M+\}} or which are derived from such a class. Normally
+% such a class should be derived from TPersitent
+parser_e_proc_directive_expected=03157_E_Directive de procédure attendue
+% This error is triggered when you have a \var{\{\$Calling\}} directive without
+% a calling convention specified.
+% It also happens when declaring a procedure in a const block and you
+% used a ; after a procedure declaration which must be followed by a
+% procedure directive.
+% Correct declarations are:
+% \begin{verbatim}
+% const
+% p : procedure;stdcall=nil;
+% p : procedure stdcall=nil;
+% \end{verbatim}
+parser_e_invalid_property_index_value=03158_E_La valeur d'un index de propriété doit être de type scalaire
+% The value you use to index a property must be of an ordinal type, for
+% example an integer or enumerated type.
+parser_e_procname_to_short_for_export=03159_E_Nom de procédure trop court pour être exporté
+% The length of the procedure/function name must be at least 2 characters
+% long. This is because of a bug in dlltool which doesn't parse the .def
+% file correct with a name of length 1.
+parser_e_dlltool_unit_var_problem=03160_E_Impossible de créer une entrée DEFFILE pour des variables globales d'unité
+parser_e_dlltool_unit_var_problem2=03161_E_Compilez sans l'option -WD
+% You need to compile this file without the -WD switch on the
+% commandline
+parser_f_need_objfpc_or_delphi_mode=03162_F_Vous devez utilisez le mode ObjFpc (-S2) ou Delphi (-Sd) pour compiler ce module
+% You need to use \{\$mode objfpc\} or \{\$mode delphi\} to compile this file.
+% Or use the equivalent commandline switches -S2 or -Sd.
+parser_e_no_export_with_index_for_target=03163_E_Impossible d'exporter avec un index sous $1
+% Exporting of functions or procedures with a specified index is not
+% supported on this target.
+parser_e_no_export_of_variables_for_target=03164_E_L'export de variables n'est pas supporté sous $1
+% Exporting of variables is not supported on this target.
+parser_e_improper_guid_syntax=03165_E_Syntaxe GUID incorrecte
+% The GUID indication does not have the proper syntax. It should be of the form
+% \begin{verbatim}
+% {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}
+% \end{verbatim}
+% Where each \var{X} represents a hexadecimal digit.
+parser_w_interface_mapping_notfound=03168_W_Impossible de trouver la procédure nommée "$1" nécessaire à l'implémentation de $2.$3
+% The compiler cannot find a suitable procedure which implements the given method of an interface.
+% A procedure with the same name is found, but the arguments do not match.
+parser_e_interface_id_expected=03169_E_Identificateur d'interface attendu
+% This happens when the compiler scans a \var{class} declaration that contains
+% \var{interface} function name mapping code like this:
+% \begin{verbatim}
+% type
+% TMyObject = class(TObject, IDispatch)
+% function IUnknown.QueryInterface=MyQueryInterface;
+% ....
+% \end{verbatim}
+% and the \var{interface} before the dot not listed in the inheritance list.
+parser_e_type_cant_be_used_in_array_index=03170_E_Le type "$1" ne peut être utilisé comme indice de tableau
+% Types like \var{qword} or \var{int64} aren't allowed as array index type
+parser_e_no_con_des_in_interfaces=03171_E_Constructeurs et destructeurs ne sont pas autorisés dans les interfaces
+% Constructor and destructor declarations aren't allowed in interface
+% In the most cases the method \var{QueryInterface} of \var{IUnknown} can
+% be used to create a new interface.
+parser_e_no_access_specifier_in_interfaces=03172_E_Les descripteurs de portée ne peuvent pas être utilisés dans les INTERFACES
+% The access specifiers \var{public}, \var{private}, \var{protected} and
+% \var{pusblished} can't be used in interfaces because all methods
+% of an interfaces must be public.
+parser_e_no_vars_in_interfaces=03173_E_Une interface ne peut pas contenir de propriétés
+% Declarations of fields aren't allowed in interfaces. An interface
+% can contain only methods
+parser_e_no_local_proc_external=03174_E_Impossible de déclarer une procédure locale comme EXTERNAL
+% Declaring local procedures as external is not possible. Local procedures
+% get hidden parameters that will make the chance of errors very high
+parser_w_skipped_fields_before=03175_W_Certaines propriétés avant "$1" n'ont pas été initialisées
+% In Delphi mode, not all fields of a typed constant record have to be
+% initialized, but the compiler warns you when it detects such situations.
+parser_e_skipped_fields_before=03176_E_Certaines propriétés situées avant "$1" n'ont pas été initialisées
+% In all syntax modes but Delphi mode, you can't leave some fields uninitialized
+% in the middle of a typed constant record
+parser_w_skipped_fields_after=03177_W_Certaines propriétés après "$1" n'ont pas été initialisées
+% You can leave some fields at the end of a type constant record uninitialized
+% (the compiler will initialize them to zero automatically). This may be the cause
+% of subtle problems.
+parser_e_varargs_need_cdecl_and_external=03178_E_Directive VarArgs sans CDecl ni External
+% The varargs directive can only be used with procedures or functions
+% that are declared with \var{cdecl} and \var{external} directives. The varargs directive
+% is only meant to provide a compatible interface to C functions like printf.
+parser_e_self_call_by_value=03179_E_Self doit être un paramètre normal (appel par valeur)
+% You can't declare self as a const or var parameter, it must always be
+% a call-by-value parameter
+parser_e_interface_has_no_guid=03180_E_L'interface "$1" n'a pas d'identification d'interface
+% When you want to assign an interface to a constant, then the interface
+% must have a GUID value set.
+parser_e_illegal_field_or_method=03181_E_Champ de classe ou identificateur de méthode "$1" inconnu
+% Properties must refer to a field or method in the same class.
+parser_w_proc_overriding_calling=03182_W_Surcharge de la convention d'appel "$1" avec "$2"
+% There are two directives in the procedure declaration that specify a calling
+% convention. Only the last directive will be used
+parser_e_no_procvarobj_const=03183_E_Les constantes typées de la forme "procedure of object" ne peuvent être initialisées qu'avec NIL
+% You can't assign the address of a method to a typed constant which has a
+% 'procedure of object' type, because such a constant requires two addresses:
+% that of the method (which is known at compile time) and that of the object or
+% class instance it operates on (which can not be known at compile time).
+parser_e_default_value_only_one_para=03184_E_Une valeur par défaut ne peut être affectée qu'à un paramètre
+% It is not possible to specify a default value for several parameters at once.
+% The following is invalid:
+% \begin{verbatim}
+% Procedure MyProcedure (A,B : Integer = 0);
+% \end{verbatim}
+% Instead, this should be declared as
+% \begin{verbatim}
+% Procedure MyProcedure (A : Integer = 0; B : Integer = 0);
+% \end{verbatim}
+parser_e_default_value_expected_for_para=03185_E_Paramètre par défaut requis pour "$1"
+% The specified parameter requires a default value.
+parser_w_unsupported_feature=03186_W_Fonctionnalité non supportée
+% You're trying to force the compiler into doing something it cannot do yet.
+parser_h_c_arrays_are_references=03187_H_Les tableaux C sont passés par référence
+% Any array passed to a C functions is passed
+% by a pointer (i.e. by reference).
+parser_e_C_array_of_const_must_be_last=03188_E_Un tableau de constantes C doit être le dernier argument
+% You can not add any other argument after an \var{array of const} for
+% \var{cdecl} functions, as the size pushed on stack for this argument is
+% not known.
+parser_h_type_redef=03189_H_Redéfinition du Type "$1"
+% This is an indicator that a previously declared type is
+% being redefined as something else. This may, or may not
+% be, a cause for errors.
+parser_w_cdecl_has_no_high=03190_W_les fonctions cdecl n'ont pas de paramètre implicite
+% Functions declared with cdecl modifier do not pass an extra implicit parameter.
+parser_w_cdecl_no_openstring=03191_W_Les fonctions cdecl n'acceptent pas les chaînes ouvertes
+% Openstring is not supported for cdecl'ared functions.
+parser_e_initialized_not_for_threadvar=03192_E_Impossible d'initialiser des variables de thread
+% Variables declared as threadvar can not be initialized with a default value.
+% The variables will always be filled with zero at the start of a new thread.
+parser_e_msg_only_for_classes=03193_E_La directive Message n'est autorisée que dans les classes
+% The message directive is only supported for Class types.
+parser_e_procedure_or_function_expected=03194_E_Procédure ou foncction attendue
+% A class method can only be specified for procedures and functions.
+parser_e_illegal_calling_convention=03195_W_Directive de convention d'appel ignorée: "$1"
+% Some calling conventions are supported only by certain CPUs. I.e. most non-i386 ports support
+% only the standard ABI calling convention of the CPU.
+parser_e_no_object_reintroduce=03196_E_REINTRODUCE ne peut pas être utilisé avec des objets
+% \var{reintroduce} is not supported for objects.
+parser_e_paraloc_only_one_para=03197_E_Chaque argument doit avoir son propre emplacement
+% If locations for arguments are specified explicitly as it is required by
+% some syscall conventions, each argument must have it's only location, things
+% like \var{procedure p(i,j : longint 'r1');} aren't allowed
+parser_e_paraloc_all_paras=03198_E_Chaque argument doit avoir un emplacement explicite
+% If one argument has an explicit argument location, all arguments of a procedure
+% must have one.
+parser_e_illegal_explicit_paraloc=03199_E_Emplacement d'argument inconnu
+% The location specified for an argument isn't recognized by the compiler
+parser_e_32bitint_or_pointer_variable_expected=03200_E_Variable entière sur 32 bits ou pointeur attendu
+% The libbase for MorphOS/AmigaOS can be give only as \var{longint}, \var{dword} or any pointer variable.
+parser_e_goto_outside_proc=03201_E_Les instructions Goto ne sont pas autorisées entre procédures différentes
+% It isn't allowed to use the \var{goto} statements referencing labels outside the
+% current procedure. The following example shows the problem:
+% \begin{verbatim}
+% ...
+% procedure p1;
+% label
+% l1;
+%
+% procedure p2;
+% begin
+% goto l1; // This goto ISN'T allowed
+% end;
+%
+% begin
+% p2
+% l1:
+% end;
+% ...
+%
+% \end{verbatim}
+parser_f_too_complex_proc=03202_F_Procédure trop complexe, nécessite trop de registres
+% Your procedure body is too long for the compiler. You should split the
+% procedure into multiple smaller procedures.
+parser_e_illegal_expression=03203_E_Expression illégale
+% This can occur under many circumstances. Mostly when trying to evaluate
+% constant expressions.
+parser_e_invalid_integer=03204_E_Expression entière incorrecte
+% You made an expression which isn't an integer, and the compiler expects the
+% result to be an integer.
+parser_e_invalid_qualifier=03205_E_Qualificateur incorrect
+% One of the following is happening :
+% \begin{itemize}
+% \item You're trying to access a field of a variable that is not a record.
+% \item You're indexing a variable that is not an array.
+% \item You're dereferencing a variable that is not a pointer.
+% \end{itemize}
+parser_e_upper_lower_than_lower=03206_E_Limite haute < limite basse
+% You are declaring a subrange, and the lower limit is higher than the high
+% limit of the range.
+parser_e_macpas_exit_wrong_param=03207_E_Le paramètre de sortie doit être le nom de la procédure dans laquelle il est utilisé
+% Non local exit is not allowed. This error occurs only in mode MacPas.
+parser_e_illegal_assignment_to_count_var=03208_E_Affectation illégale à la variable de boucle for "$1"
+% The type of a \var{for} loop variable must be an ordinal type.
+% Loop variables cannot be reals or strings. You can also not assign values to
+% loop variables inside the loop (except in Delphi and TP modes). Use a while or
+% repeat loop instead if you need to do something like that, since those
+% constructs were built for that.
+parser_e_no_local_var_external=03209_E_Impossible de déclarer une variable locale comme EXTERNAL
+% Declaring local variables as external is not allowed. Only global variables can reference
+% to external variables.
+parser_e_proc_already_external=03210_E_Procédure déjà déclarée EXTERNAL
+% The procedure is already declared with the EXTERNAL directive in an interface or
+% forward declaration.
+parser_w_implicit_uses_of_variants_unit=03211_W_Utilisation implicite de l'unité Variants
+% The Variant type is used in the unit without any used unit using the Variants unit. The
+% compiler has implicitly added the Variants unit to the uses list. To remove this warning
+% the Variants unit needs to be added to the uses statement.
+parser_e_no_static_method_in_interfaces=03212_E_Les méthodes de classe et les méthodes statiques ne peuvent pas être utilisées dans les interfaces
+% The specifier \var{class} and directive \var{static} can't be used in interfaces
+% because all methods of an interfaces must be public.
+parser_e_arithmetic_operation_overflow=03213_E_Dépassement dans une opération arithmétique
+% An operation on two integers values produced an overflow
+parser_e_protected_or_private_expected=03214_E_Protected ou private attendu
+% \var{strict} can be only used together with \var{protected} or \var{private}.
+parser_e_illegal_slice=03215_E_SLICE ne peut pas être utilisée en dehors d'une liste de paramètres
+% \var{slice} can be used only for arguments accepting an open array parameter
+parser_e_dispinterface_cant_have_parent=03216_E_Une DISPINTERFACE ne peut pas avoir de classe parent
+% A DISPINMTERFACE is a special type of interface which can't have a parent class
+parser_e_dispinterface_needs_a_guid=03217_E_Une DISPINTERFACE requiert un GUID
+% A DISPINMTERFACE always needs an interface identification
+parser_w_overridden_methods_not_same_ret=03218_W_Les méthodes surchargées doivent avoir un type de résultat similaire. Ce code peut "crasher", il dépend d'un bug de l'analyseur syntaxique de Delphi ("$2" est surchargé par "$1" qui a un type de résultat différent)
+% If you declare overridden methods in a class definition, they must
+% have the same return type. Some versions of Delphi allow you to change the
+% return type of interface methods, and even to change procedures into
+% functions, but the resulting code may crash depending on the types used
+% and the way the methods are called.
+parser_e_dispid_must_be_ord_const=03219_E_Les Dispatch ID doivent être des constantes scalaires
+% \end{description}
+#
+# Type Checking
+#
+# 04049 is the last used one
+#
+% \section{Type checking errors}
+% This section lists all errors that can occur when type checking is
+% performed.
+% \begin{description}
+type_e_mismatch=04000_E_Type non valable
+% This can happen in many cases:
+% \begin{itemize}
+% \item The variable you're assigning to is of a different type than the
+% expression in the assignment.
+% \item You are calling a function or procedure with parameters that are
+% incompatible with the parameters in the function or procedure definition.
+% \end{itemize}
+type_e_incompatible_types=04001_E_Types incompatibles: $1 spécifié mais $2 attendu
+% There is no conversion possible between the two types
+% Another possiblity is that they are declared in different
+% declarations:
+% \begin{verbatim}
+% Var
+% A1 : Array[1..10] Of Integer;
+% A2 : Array[1..10] Of Integer;
+%
+% Begin
+% A1:=A2; { This statement gives also this error, it
+% is due the strict type checking of pascal }
+% End.
+% \end{verbatim}
+type_e_not_equal_types=04002_E_Incompatibilité de types entre $1 et $2
+% The types are not equal
+type_e_type_id_expected=04003_E_Identificateur de type attendu
+% The identifier is not a type, or you forgot to supply a type identifier.
+type_e_variable_id_expected=04004_E_Identificateur de variable attendu
+% This happens when you pass a constant to a routine (such as \var{Inc} var or \var{Dec})
+% when it expects a variable. You can only pass variables as arguments to these functions.
+type_e_integer_expr_expected=04005_E_Expression entière attendue, "$1" spécifié
+% The compiler expects an expression of type integer, but gets a different
+% type.
+type_e_boolean_expr_expected=04006_E_Expression booléenne attendue mais "$1" spécifié
+% The expression must be a boolean type, it should be return true or
+% false.
+type_e_ordinal_expr_expected=04007_E_Expression ordinale attendue
+% The expression must be of ordinal type, i.e., maximum a \var{Longint}.
+% This happens, for instance, when you specify a second argument
+% to \var{Inc} or \var{Dec} that doesn't evaluate to an ordinal value.
+type_e_pointer_type_expected=04008_E_Type pointeur attendu, "$1" spécifié
+% The variable or expression isn't of the type \var{pointer}. This
+% happens when you pass a variable that isn't a pointer to \var{New}
+% or \var{Dispose}.
+type_e_class_type_expected=04009_E_Type classe attendu mais "$1" spécifié
+% The variable of expression isn't of the type \var{class}. This happens
+% typically when
+% \begin{enumerate}
+% \item The parent class in a class declaration isn't a class.
+% \item An exception handler (\var{On}) contains a type identifier that
+% isn't a class.
+% \end{enumerate}
+type_e_cant_eval_constant_expr=04011_E_Impossible d'évaluer l'expression constante
+% This error can occur when the bounds of an array you declared does
+% not evaluate to ordinal constants
+type_e_set_element_are_not_comp=04012_E_Éléments de l'ensemble incompatibles
+% You are trying to make an operation on two sets, when the set element types
+% are not the same. The base type of a set must be the same when taking the
+% union
+type_e_set_operation_unknown=04013_E_Opération non implémentée pour des ensembles
+% several binary operations are not defined for sets
+% like div mod ** (also >= <= for now)
+type_w_convert_real_2_comp=04014_W_Conversion automatique d'un réel vers COMP qui est un type entier
+% An implicit type conversion from a real type to a \var{comp} is
+% encountered. Since \var{comp} is a 64 bit integer type, this may indicate
+% an error.
+type_h_use_div_for_int=04015_H_Utilisez DIV pour obtenir un résultat entier
+% When hints are on, then an integer division with the '/' operator will
+% procuce this message, because the result will then be of type real
+type_e_strict_var_string_violation=04016_E_Types de chaînes incompatibles à cause du mode $V+
+% When compiling in \var{\{\$V+\}} mode, the string you pass as a parameter
+% should be of the exact same type as the declared parameter of the procedure.
+type_e_succ_and_pred_enums_with_assign_not_possible=04017_E_Succ ou Pred impossible pour des énumérations contenant des affectations
+% When you declared an enumeration type which has assignments in it, as in C,
+% like in the following:
+% \begin{verbatim}
+% Tenum = (a,b,e:=5);
+% \end{verbatim}
+% you cannot use the \var{Succ} or \var{Pred} functions on them.
+type_e_cant_read_write_type=04018_E_Impossible de lire ou d'écrire des variables de ce type
+% You are trying to \var{read} or \var{write} a variable from or to a
+% file of type text, which doesn't support that. Only integer types,
+% reals, pchars and strings can be read from/written to a text file.
+% Booleans can only be written to text files.
+type_e_no_readln_writeln_for_typed_file=04019_E_Impossible d'utiliser ReadLn ou WriteLn sur un ficher typé
+% \var{readln} and \var{writeln} are only allowed for text files.
+type_e_no_read_write_for_untyped_file=04020_E_Impossible d'utiliser Read ou Write sur un fichier non typé
+% \var{read} and \var{write} are only allowed for text or typed files.
+type_e_typeconflict_in_set=04021_E_Conflit de type dans les éléments de l'ensemble
+% There is at least one set element which is of the wrong type, i.e. not of
+% the set type.
+type_w_maybe_wrong_hi_lo=04022_W_Lo/Hi(Longint/DWord) retourne le mot ou le double mot de poids fort ou de poids faible
+% \fpc supports an overloaded version of \var{lo/hi} for \var{longint/dword/int64/qword}
+% which returns the lower/upper word/dword of the argument. TP always uses
+% a 16 bit \var{lo/hi} which returns always bits 0..7 for \var{lo} and the
+% bits 8..15 for \var{hi}. If you want the TP behavior you have
+% to type cast the argument to \var{word/integer}
+type_e_integer_or_real_expr_expected=04023_E_Expression entière ou réelle attendue
+% The first argument to \var{str} must a real or integer type.
+type_e_wrong_type_in_array_constructor=04024_E_Mauvais type "$1" dans le constructeur
+% You are trying to use a type in an array constructor which is not
+% allowed.
+type_e_wrong_parameter_type=04025_E_Type incompatible pour l'argument no. $1: $2 spécifié au lieu de $3
+% You are trying to pass an invalid type for the specified parameter.
+type_e_no_method_and_procedure_not_compatible=04026_E_Méthodes (variable) et procédures (variable) sont incompatibles
+% You can't assign a method to a procedure variable or a procedure to a
+% method pointer.
+type_e_wrong_math_argument=04027_E_Constante invalide passée à une fonction mathématique interne
+% The constant argument passed to a ln or sqrt function is out of
+% the definition range of these functions.
+type_e_no_addr_of_constant=04028_E_Impossible d'obtenir l'adresse des constantes
+% It is not possible to get the address of a constant, because they
+% aren't stored in memory, you can try making it a typed constant.
+type_e_argument_cant_be_assigned=04029_E_Cet argument ne peut pas être passé par référence
+% Only expressions which can be on the left side of an
+% assignment can be passed as call by reference argument
+% Remark: Properties can be only
+% used on the left side of an assignment, but they cannot be used as arguments
+type_e_cannot_local_proc_to_procvar=04030_E_Impossible d'assigner une fonction ou une procédure locale à une variable de type procédure
+% It's not allowed to assign a local procedure/function to a
+% procedure variable, because the calling of local procedure/function is
+% different. You can only assign local procedure/function to a void pointer.
+type_e_no_assign_to_addr=04031_E_Impossible d'affecter des valeurs à une adresse
+% It is not allowed to assign a value to an address of a variable,constant,
+% procedure or function. You can try compiling with -So if the identifier
+% is a procedure variable.
+type_e_no_assign_to_const=04032_E_Impossible d'affecter des valeurs à une constante
+% It's not allowed to assign a value to a variable which is declared
+% as a const. This is normally a parameter declared as const, to allow
+% changing the value make the parameter as a value parameter or a var.
+type_e_array_required=04033_E_Type de tableau requis
+% If you are accessing a variable using an index '[<x>]' then
+% the type must be an array. In FPC mode also a pointer is allowed.
+type_e_interface_type_expected=04034_E_Type interface attendu, "$1" spécifié
+% The compiler expected to encounter an interface type name, but got something else.
+% The following code would provoke this error:
+% \begin{verbatim}
+% Type
+% TMyStream = Class(TStream,Integer)
+% \end{verbatim}
+type_w_mixed_signed_unsigned=04035_W_Le mélange d'expressions signées et de mots longs (longwords) donne un résultat sur 64 bits
+% If you divide (or calculate the modulus of) a signed expression by a longword (or vice versa),
+% or if you have overflow and/or range checking turned on and use an arithmetic
+% expression (+, -, *, div, mod) in which both signed numbers and longwords appear,
+% then everything has to be evaluated in 64bit which is slower than normal
+% 32bit arithmetic. You can avoid this by typecasting one operand so it
+% matches the result type of the other one.
+type_w_mixed_signed_unsigned2=04036_W_Le mélange d'expressions signées et de cardinaux ici peut provoquer une erreur de dépassement d'intervalle
+% If you use a binary operator (and, or, xor) and one of
+% the operands is a longword while the other one is a signed expression, then,
+% if range checking is turned on, you may get a range check error because in
+% such a case both operands are converted to longword before the operation is
+% carried out. You can avoid this by typecasting one operand so it
+% matches the result type of the other one.
+type_e_typecast_wrong_size_for_assignment=04037_E_Transtypage de types de tailles différentes ($1 -> $2) dans l'affectation
+% Type casting to a type with a different size is not allowed when the variable is
+% used for assigning.
+type_e_array_index_enums_with_assign_not_possible=04038_E_Les énumérations contenant des affectations ne peuvent pas être utilisées comme index de tableau
+% When you declared an enumeration type which has assignments in it, as in C,
+% like in the following:
+% \begin{verbatim}
+% Tenum = (a,b,e:=5);
+% \end{verbatim}
+% you cannot use it as index of an array.
+type_e_classes_not_related=04039_E_Les types de classe ou d'objet "$1" et "$2" ne sont pas compatibles
+% There is a typecast from one class or object to another while the class/object
+% are not related. This will probably lead to errors
+type_w_classes_not_related=04040_W_Classes "$1" et "$2" incompatibles
+% There is a typecast from one class or object to another while the class/object
+% are not related. This will probably lead to errors
+type_e_class_or_interface_type_expected=04041_E_Classe ou interface attendue mais "$1" spécifié
+% The compiler expected a class or interface name, but got another type or identifier.
+type_e_type_is_not_completly_defined=04042_E_Le type "$1" n'est pas complètement défini
+% This error occurs when a type is not complete: i.e. a pointer type which points to
+% an undefined type.
+type_w_string_too_long=04043_W_La chaîne contient plus de caractères que ne peut en contenir une chaîne courte
+% The size of the constant string, which is assigned to a shortstring,
+% is longer than the maximum size of the shortstring
+type_w_signed_unsigned_always_false=04044_W_La comparaison est toujours FAUSSE du fait de l'intervalle des valeurs
+% There is a comparison between an unsigned value and a signed constant which is
+% less than zero. Because of type promotion, the statement will always evaluate to
+% false. Exlicitly typecast the constant to the correct range to avoid this problem.
+type_w_signed_unsigned_always_true=04045_W_La comparaison est toujours VRAIE du fait de l'intervalle des valeurs
+% There is a comparison between an unsigned value and a signed constant which is
+% less than zero. Because of type promotion, the statement will always evaluate to
+% true. Exlicitly typecast the constant to the correct range to avoid this problem.
+type_w_instance_with_abstract=04046_W_Construction d´une classe "$1" avec des méthodes abstraites
+% An instance of a class is created which contains non-implemented abstract
+% methods. This will probably lead to a runtime error 211 in the code if that
+% routine is ever called. All abstract methods should be overridden.
+type_h_in_range_check=L´opérande à gauche de l´opérateur IN doit avoir la longueur d´un octet (8 bits)
+% The left operand of the \var{in} operator is not an ordinal or enumeration which fits
+% within 8-bits, this may lead to range check errors. The \var{in} operator
+% currently only supports a left operand which fits within a byte. In the case of
+% enumerations, the size of an element of an enumeration can be controlled with
+% the \var{\{\$PACKENUM\}} or \var{\{\$Zn\}} switches.
+type_w_smaller_possible_range_check=04048_W_Divergence de taille des types, risque de perte de données ou d'erreur de dépassement d'intervalle
+% There is an assignment to a smaller type than the source type. This means that
+% this may cause a range-check error, or may lead to possible loss of data.
+type_h_smaller_possible_range_check=04049_H_Taille des types non concordante, possibilité de perte de données ou d´erreur de dépassement d´intervalle
+% There is an assignment to a smaller type than the source type. This means that
+% this may cause a range-check error, or may lead to possible loss of data.
+type_e_cant_take_address_of_abstract_method=04050_E_L'adresse d'une méthode abstraite ne peut pas être utilisée
+% An abstract method has no body, so the address of an abstract method can't be taken.
+type_e_operator_not_allowed=04051_E_L'opérateur n'est pas utilisable pour le type d'opérande
+% You are trying an operator that is not available for the type of the
+% operands
+type_e_constant_expr_expected=04052_E_Expression constante attendue
+% The compiler expects an constant expression, but gets a variable expression.
+type_e_operator_not_supported_for_types=04053_E_L'opération "$1" n'est pas supportée pour les types "$2" et "$3"
+% The operation is not allowed for the supplied types
+type_e_illegal_type_conversion=04054_E_Conversion de types illégale: de "$1" vers "$2"
+% When doing a type-cast, you must take care that the sizes of the variable and
+% the destination type are the same.
+type_h_pointer_to_longint_conv_not_portable=La conversion entre types scalaires et pointeurs n´est pas portable
+% If you typecast a pointer to a longint (or vice-versa), this code will not compile
+% on a machine using 64-bit for pointer storage.
+type_w_pointer_to_longint_conv_not_portable=04056_W_La conversion entre cardinaux et pointeurs n'est pas portable
+% If you typecast a pointer to a ordinal type of a different size (or vice-versa), this can
+% cause problems. This is a warning to help finding the 32bit specific code where cardinal/longint is used
+% to typecast pointers to ordinals. A solution is to use the ptrint/ptruint types instead.
+type_e_cant_choose_overload_function=04057_E_Impossible de déterminer quelle fonction overload appeler
+% You're calling overloaded functions with a parameter that doesn't correspond
+% to any of the declared function parameter lists. e.g. when you have declared
+% a function with parameters \var{word} and \var{longint}, and then you call
+% it with a parameter which is of type \var{integer}.
+type_e_illegal_count_var=04058_E_Variable de boucle FOR invalide
+% The type of a \var{for} loop variable must be an ordinal type.
+% Loop variables cannot be reals or strings.
+type_w_double_c_varargs=04059_W_Conversion d'une valeur réelle constante en valeur double pour un paramètre variable C, ajoutez un transtypage explicite pour éviter ceci
+% In C, constant real values are double by default. For this reason, if you
+% pass a constant real value to a variable argument part of a C function, FPC
+% by default converts this constant to double as well. If you want to prevent
+% this from happening, add an explicit typecast around the constant.
+type_e_class_or_cominterface_type_expected=04060_E_Classe ou interface COM attendue mais "$1" spécifié
+% Some operators like the AS operator are only appliable to classes or COM interfaces.
+% \end{description}
+#
+# Symtable
+#
+# 05060 is the last used one
+#
+% \section{Symbol handling}
+% This section lists all the messages that concern the handling of symbols.
+% This means all things that have to do with procedure and variable names.
+% \begin{description}
+sym_e_id_not_found=05000_E_Identificateur "$1" non trouvé
+% The compiler doesn't know this symbol. Usually happens when you misspel
+% the name of a variable or procedure, or when you forgot to declare a
+% variable.
+sym_f_internal_error_in_symtablestack=05001_F_Erreur interne dans SymTableStack()
+% An internal error occurred in the compiler; If you encounter such an error,
+% please contact the developers and try to provide an exact description of
+% the circumstances in which the error occurs.
+sym_e_duplicate_id=05002_E_Double déclaration de l'identificateur "$1"
+% The identifier was already declared in the current scope.
+sym_h_duplicate_id_where=05003_H_Identificateur déjà défini dans $1 à la ligne $2
+% The identifier was already declared in a previous scope.
+sym_e_unknown_id=05004_E_Identificateur "$1" inconnu
+% The identifier encountered has not been declared, or is used outside the
+% scope where it is defined.
+sym_e_forward_not_resolved=05005_E_Déclaration forward "$1" non résolue
+% This can happen in two cases:
+% \begin{itemize}
+% \item This happens when you declare a function (in the \var{interface} part, or
+% with a \var{forward} directive, but do not implement it.
+% \item You reference a type which isn't declared in the current \var{type}
+% block.
+% \end{itemize}
+sym_e_error_in_type_def=05007_E_Erreur dans la définition du type
+% There is an error in your definition of a new array type:
+% \item One of the range delimiters in an array declaration is erroneous.
+% For example, \var{Array [1..1.25]} will trigger this error.
+sym_e_forward_type_not_resolved=05009_E_Déclaration forward "$1" non résolue
+% A symbol was forward defined, but no declaration was encountered.
+sym_e_only_static_in_static=05010_E_Seules les variables statiques peuvent être utilisées dans les méthodes statiques ou en dehors des méthodes
+% A static method of an object can only access static variables.
+sym_f_type_must_be_rec_or_class=05012_F_Type record ou classe attendu
+% The variable or expression isn't of the type \var{record} or \var{class}.
+sym_e_no_instance_of_abstract_object=05013_E_Les instances de classes ou les objets avec une méthode abstraite ne sont pas autorisés
+% You are trying to generate an instance of a class which has an abstract
+% method that wasn't overridden.
+sym_w_label_not_defined=05014_W_Label non défini $1
+% A label was declared, but not defined.
+sym_e_label_used_and_not_defined=05015_E_Le Label "$1" est utilisé mais indéfini
+% A label was declared and used, but not defined.
+sym_e_ill_label_decl=05016_E_Déclaration de label illégale
+% This error should never happen; it occurs if a label is defined outside a
+% procedure or function.
+sym_e_goto_and_label_not_supported=05017_E_GOTO et LABEL non supportés (utilisez l'option -Sg)
+% You must compile a program which has \var{label}s and \var{goto} statements
+% with the \var{-Sg} switch. By default, \var{label} and \var{goto} aren't
+% supported.
+sym_e_label_not_found=05018_E_Label non trouvé
+% A \var{goto label} was encountered, but the label isn't declared.
+sym_e_id_is_no_label_id=05019_E_L'identificateur n'est pas un label
+% The identifier specified after the \var{goto} isn't of type label.
+sym_e_label_already_defined=05020_E_Label déjà défini
+% You are defining a label twice. You can define a label only once.
+sym_e_ill_type_decl_set=05021_E_Déclaration de type d'éléments d'ensemble illégale
+% The declaration of a set contains an invalid type definition.
+sym_e_class_forward_not_resolved=05022_E_Déclaration forward de classe "$1" non résolue
+% You declared a class, but you did not implement it.
+sym_n_unit_not_used=05023_H_L'unité $1 n'est pas utilisée par $2
+% The unit referenced in the \var{uses} clause is not used.
+sym_h_para_identifier_not_used=05024_H_Le paramètre "$1" n'est pas utilisé
+% The identifier was declared (locally or globally) but
+% was not used (locally or globally).
+sym_n_local_identifier_not_used=05025_N_La variable locale "$1" n'est pas utilisée
+% You have declared, but not used a variable in a procedure or function
+% implementation.
+sym_h_para_identifier_only_set=05026_H_La valeur du paramètre "$1" est définie mais jamais utilisée
+% The identifier was declared (locally or globally)
+% set but not used (locally or globally).
+sym_n_local_identifier_only_set=05027_N_La variable locale "$1" a une valeur mais n'est jamais utilisée
+% The variable in a procedure or function
+% implementation is declared, set but never used.
+sym_h_local_symbol_not_used=05028_H_Le symbole local $1 "$2" n'est pas utilisé
+% A local symbol is never used.
+sym_n_private_identifier_not_used=05029_N_Le champ privé "$1.$2" n'est jamais utilisé
+% The indicated private field is defined, but is never used in the code.
+sym_n_private_identifier_only_set=05030_N_Le champ privé "$1.$2" a une valeur mais n'est jamais utilisé
+% The indicated private field is declared, assigned but never read.
+sym_n_private_method_not_used=05031_N_La méthode privée "$1.$2" n'est jamais utilisée
+% The indicated private method is declared but is never used in the code.
+sym_e_set_expected=05032_E_Type ensemble attendu
+% The variable or expression is not of type \var{set}. This happens in an
+% \var{in} statement.
+sym_w_function_result_not_set=05033_W_Le résultat de la fonction semble indéfini
+% You can get this warning if the compiler thinks that a function return
+% value is not set. This will not be displayed for assembler procedures,
+% or procedures that contain assembler blocks.
+sym_w_wrong_C_pack=05034_W_Le type $1 n'est pas aligné correctement pour C dans l'enregistrement courant
+% Arrays with sizes not multiples of 4 will be wrongly aligned
+% for C structures.
+sym_e_illegal_field=05035_E_Identificateur de champ "$1" inconnu
+% The field doesn't exist in the record/object definition.
+sym_w_uninitialized_local_variable=05036_W_La variable locale "$1" ne semble pas être initialisée
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_w_uninitialized_variable=05037_W_La variable "$1" ne semble pas être initialisée
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_e_id_no_member=05038_E_L'identificateur "$1" n'a pas de membres
+% This error is generated when an identifier of a record,
+% field, or method is accessed while it is not defined.
+sym_h_param_list=05039_H_Déclaration trouvée: $1
+% You get this when you use the \var{-vh} switch. In case an overloaded
+% procedure is not found, then all candidate overloaded procedures are
+% listed, with their parameter lists.
+sym_e_segment_too_large=05040_E_Donnée trop grande (max. 2GB)
+% You get this when you declare a data element whose size exceeds the
+% prescribed limit (2 Gb on 80386+/68020+ processors)
+sym_e_no_matching_implementation_found=05042_E_Aucune implémentation correspondante pour la méthode "$1" trouvée dans l'interface
+% There was no matching method found which could implement the interface
+% method. Check argument types and result type of the methods.
+sym_w_deprecated_symbol=05043_W_Le symbole "$1" est déprécié
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{deprecated} is used. Deprecated symbols may no longer
+% be available in newer versions of the unit / library. Usage of this symbol
+% should be avoided as much as possible.
+sym_w_non_portable_symbol=05044_W_Le symbole "$1" n'est pas portable
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{platform} is used. This symbol's value, usage
+% and availability is platform specific and should not be used
+% if the source code must be portable.
+sym_w_non_implemented_symbol=05055_W_Le symbole "$1" n'est pas implémenté
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{unimplemented} is used. This symbol is defined,
+% but is not yet implemented on this specific platform.
+sym_e_cant_create_unique_type=05056_E_Impossible de créer un type unique depuis ce type
+% Only simple types like ordinal, float and string types are supported when
+% redefining a type with \var{type newtype = type oldtype;}.
+sym_h_uninitialized_local_variable=05057_H_La variable locale "$1" ne semble pas initialisée
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_h_uninitialized_variable=05058_H_La variable "$1" ne semble pas initialisée
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_w_function_result_uninitialized=05059_W_La variable Result de la fonction ne semble pas initialisée
+% This message is displayed if the compiler thinks that the function result
+% variable will be used (i.e. appears in the right-hand-side of an expression)
+% before it is initialized (i.e. appeared in the left-hand side of an
+% assigment)
+sym_h_function_result_uninitialized=05060_H_La variable Result de la fonction ne semble pas initialisée
+% This message is displayed if the compiler thinks that the function result
+% variable will be used (i.e. appears in the right-hand-side of an expression)
+% before it is initialized (i.e. appeared in the left-hand side of an
+% assigment)
+sym_w_identifier_only_read=05061_W_La variable "$1" est lue mais ne reçoit de valeur nulle part
+% You have read the value of a variable, but nowhere assigned a value to
+% it.
+% \end{description}
+#
+# Codegenerator
+#
+# 06040 is the last used one
+#
+% \section{Code generator messages}
+% This section lists all messages that can be displayed if the code
+% generator encounters an error condition.
+% \begin{description}
+cg_e_parasize_too_big=06009_E_La taille de la liste de paramètre dépasse 65535 octets
+% The I386 processor limits the parameter list to 65535 bytes (the \var{RET}
+% instruction causes this)
+cg_e_file_must_call_by_reference=06012_E_Les paramètres de type File doivent être passés par adresse
+% You cannot specify files as value parameters, i.e. they must always be
+% declared \var{var} parameters.
+cg_e_cant_use_far_pointer_there=06013_E_L'utilisation d'un pointeur long n'est pas autorisée ici
+% Free Pascal doesn't support far pointers, so you cannot take the address of
+% an expression which has a far reference as a result. The \var{mem} construct
+% has a far reference as a result, so the following code will produce this
+% error:
+% \begin{verbatim}
+% var p : pointer;
+% ...
+% p:=@mem[a000:000];
+% \end{verbatim}
+cg_e_dont_call_exported_direct=06015_E_Les fonctions déclarées EXPORT ne peuvent pas être appelées
+% No longer in use.
+cg_w_member_cd_call_from_method=06016_W_Appel probablement illégal d'un constructeur ou d'un destructeur
+% The compiler detected that a constructor or destructor is called within a
+% a method. This will probably lead to problems, since constructors / destructors
+% require parameters on entry.
+cg_n_inefficient_code=06017_N_Code inefficace
+% Your statement seems dubious to the compiler.
+cg_w_unreachable_code=06018_W_Code inaccessible
+% You specified a construct which will never be executed. Example:
+% \begin{verbatim}
+% while false do
+% begin
+% {.. code ...}
+% end;
+% \end{verbatim}
+cg_e_cant_call_abstract_method=06020_E_Les méthodes abstraites ne peuvent pas être appelées directement
+% You cannot call an abstract method directy, instead you must call a
+% overriding child method, because an abstract method isn't implemented.
+cg_d_register_weight=06027_DL_Registre $1 poids $2 $3
+% Debugging message. Shown when the compiler considers a variable for
+% keeping in the registers.
+cg_d_stackframe_omited=06029_DL_Cadre de pile omis
+% Some procedure/functions do not need a complete stack-frame, so it is omitted.
+% This message will be displayed when the {-vd} switch is used.
+cg_e_unable_inline_object_methods=06031_E_Un object ou des méthodes de classe ne peuvent pas être "inline".
+% You cannot have inlined object methods.
+cg_e_unable_inline_procvar=06032_E_Les appels à des variables procédure ne peuvent pas être "inline".
+% A procedure with a procedural variable call cannot be inlined.
+cg_e_no_code_for_inline_stored=06033_E_Pas de code pour la procédure inline stockée
+% The compiler couldn't store code for the inline procedure.
+cg_e_can_access_element_zero=06035_E_Impossible d'accéder à l'élément zéro d'une chaîne ANSI, large ou longue, utilisez à la place (set)length
+% You should use \var{setlength} to set the length of an ansi/wide/longstring
+% and \var{length} to get the length of such a string types
+cg_e_cannot_call_cons_dest_inside_with=06037_E_Constructeurs et destructeurs ne peuvent pas être appelés à l'intérieur d'une clause 'with'
+% Inside a \var{with} clause you cannot call a constructor or destructor for the
+% object you have in the \var{with} clause.
+cg_e_cannot_call_message_direct=06038_E_Impossible d'appeler directement les méthodes du gestionnaire de messages
+% A message method handler method cannot be called directly if it contains an
+% explicit self argument
+cg_e_goto_inout_of_exception_block=06039_E_Saut à l'intérieur ou en dehors d'un bloc de traitement d'une exception
+% It is not allowed to jump in or outside of an exception block like \var{try..finally..end;}:
+% \begin{verbatim}
+% label 1;
+%
+% ...
+%
+% try
+% if not(final) then
+% goto 1; // this line will cause an error
+% finally
+% ...
+% end;
+% 1:
+% ...
+% \end{verbatim}
+cg_e_control_flow_outside_finally=06040_E_Les instructions de contrôle d'exécution ne sont pas autorisées dans un bloc finally
+% It isn't allowed to use the control flow statements \var{break},
+% \var{continue} and \var{exit}
+% inside a finally statement. The following example shows the problem:
+% \begin{verbatim}
+% ...
+% try
+% p;
+% finally
+% ...
+% exit; // This exit ISN'T allowed
+% end;
+% ...
+%
+% \end{verbatim}
+% If the procedure \var{p} raises an exception the finally block is
+% executed. If the execution reaches the exit, it's unclear what to do:
+% exiting the procedure or searching for another exception handler
+cg_w_parasize_too_big=06041_W_La taille des paramètres dépasse la limite supportée par certains processeurs.
+% This indicates that you are declaring more than 64K of parameters, which
+% might not be supported on other processor targets.
+cg_w_localsize_too_big=06042_W_La taille de la variable locale dépasse la limite supportée par certains processeurs.
+% This indicates that you are declaring more than 32K of local variables, which
+% might not be supported on other processor targets.
+cg_e_localsize_too_big=06043_E_La taille des variables locales dépasse la limite supportée
+% This indicates that you are declaring more than 32K of local variables, which
+% is not supported by this processor.
+cg_e_break_not_allowed=06044_E_BREAK non autorisé
+% You're trying to use \var{break} outside a loop construction.
+cg_e_continue_not_allowed=06045_E_CONTINUE non autorisé
+% You're trying to use \var{continue} outside a loop construction.
+cg_f_unknown_compilerproc=06046_F_Procédure "$1" inconnue. Verifiez que vous utilisez la bonne version de bibliothèque d'exécution.
+% The compiler expects that the runtime library contains some subrountines. If you see this error
+% and you didn't mess with the runtime library, it's very likely that the runtime library
+% you're using doesn't match the used compiler. If you changed the runtime library this error means
+% that you removed a subroutine which the compiler needs for internal use.
+% \end{description}
+# EndOfTeX
+#
+# Assembler reader
+#
+# 07097 is the last used one
+#
+asmr_d_start_reading=07000_DL_Début d'analyse assembleur de style $1
+% This informs you that an assembler block is being parsed
+asmr_d_finish_reading=07001_DL_Analyse assembleur de style $1 terminée
+% This informs you that an assembler block has finished.
+asmr_e_none_label_contain_at=07002_E_Un identificateur qui n'est pas un label contient @
+% A identifier which isn't a label can't contain a @.
+asmr_e_building_record_offset=07004_E_Erreur de construction de l'offset du record
+% There has an error occured while building the offset of a record/object
+% structure, this can happend when there is no field specified at all or
+% an unknown field identifier is used.
+asmr_e_offset_without_identifier=07005_E_OFFSET utilisé sans identificateur
+% You can only use OFFSET with an identifier. Other syntaxes aren't
+% supported
+asmr_e_type_without_identifier=07006_E_TYPE utilisé sans identificateur
+% You can only use TYPE with an identifier. Other syntaxes aren't
+% supported
+asmr_e_no_local_or_para_allowed=07007_E_Impossible d'utiliser une variable locale ou des paramètres ici
+% You can't use a local variable or parameter here, mostly because the
+% addressing of locals and parameters is done using the frame pointer register so the
+% address can't be obtained directly.
+asmr_e_need_offset=07008_E_Utilisation d'OFFSET nécessaire
+% You need to use OFFSET <id> here to get the address of the identifier.
+asmr_e_need_dollar=07009_E_Utilisation de $ nécessaire
+% You need to use $<id> here to get the address of the identifier.
+asmr_e_cant_have_multiple_relocatable_symbols=07010_E_Impossible d'utiliser plusieurs symboles relogeables
+% You can't have more than one relocatable symbol (variable/typed constant)
+% in one argument.
+asmr_e_only_add_relocatable_symbol=07011_E_Les symboles relogeables ne peuvent qu'être ajoutés
+% Relocatable symbols (variable/typed constant) can't be used with other
+% operators. Only addition is allowed.
+asmr_e_invalid_constant_expression=07012_E_Expression contante incorrecte
+% There is an error in the constant expression.
+asmr_e_relocatable_symbol_not_allowed=07013_E_Symbole relogeable non autorisé
+% You can't use a relocatable symbol (variable/typed constant) here.
+asmr_e_invalid_reference_syntax=07014_E_Syntaxe de référence incorrecte
+% There is an error in the reference.
+asmr_e_local_para_unreachable=07015_E_Impossible d´atteindre $1 depuis ce code
+% You can not read directly the value of a local variable or parameter
+% of a higher level procedure in assembler code (except for
+% local assembler code without parameter nor locals).
+asmr_e_local_label_not_allowed_as_ref=07016_E_Les symboles locaux et les labels ne sont pas autorisés en tant que références
+% You can't use local symbols/labels as references
+asmr_e_wrong_base_index=07017_E_Utilisation d'un registre de base et d'un index de registre incorrecte
+% There is an error with the base and index register, they are
+% probably incorrect
+asmr_w_possible_object_field_bug=07018_W_Erreur possible dans la gestion d'un champ d'objet
+% Fields of objects or classes can be reached directly in normal or objfpc
+% modes but TP and Delphi modes treat the field name as a simple offset.
+asmr_e_wrong_scale_factor=07019_E_Facteur d'échelle spécifié incorrect
+% The scale factor given is wrong, only 1,2,4 and 8 are allowed
+asmr_e_multiple_index=07020_E_Utilisation d'index de registre multiples
+% You are trying to use more than one index register
+asmr_e_invalid_operand_type=07021_E_Type de paramètre incorrect
+% The operand type doesn't match with the opcode used
+asmr_e_invalid_string_as_opcode_operand=07022_E_Paramètre chaîne incorrect pour le code opération: $1
+% The string specified as operand is not correct with this opcode
+asmr_w_CODE_and_DATA_not_supported=07023_W_@CODE et @DATA non supportés
+% @CODE and @DATA are unsupported and are ignored.
+asmr_e_null_label_ref_not_allowed=07024_E_Référence à un label Null non autorisée
+asmr_e_expr_zero_divide=07025_E_Division par zéro dans l'évaluateur assembleur
+% There is a division by zero in a constant expression
+asmr_e_expr_illegal=07026_E_Expression illégale
+% There is an illegal expression in a constant expression
+asmr_e_escape_seq_ignored=07027_E_Séquence d'échappement ignorée: $1
+% There is a C-styled string, but the escape sequence in the string
+% is unknown, and is therefore ignored
+asmr_e_invalid_symbol_ref=07028_E_Référence au symbole incorrecte
+asmr_w_fwait_emu_prob=07029_W_Fwait peut causer des problèmes d'émulation avec emu387
+asmr_w_fadd_to_faddp=07030_W_$1 sans paramètre traduit en $1P
+asmr_w_enter_not_supported_by_linux=07031_W_Instruction ENTER non supportée par le noyau Linux
+% ENTER instruction can generate a stack page fault that is not
+% caught correctly by the i386 Linux page handler.
+asmr_w_calling_overload_func=07032_W_Appel d'une fonction surchargée en assembleur
+% There is a call to an overloaded method in the assembler block,
+% this might be the sign there is a problem
+asmr_e_unsupported_symbol_type=07033_E_Type de symbole non supporté
+asmr_e_constant_out_of_bounds=07034_E_Valeur de constante hors intervalle
+asmr_e_error_converting_decimal=07035_E_Erreur de conversion décimale $1
+% A constant decimal value does not have the correct syntax
+asmr_e_error_converting_octal=07036_E_Erreur de conversion octale $1
+% A constant octal value does not have the correct syntax
+asmr_e_error_converting_binary=07037_E_Erreur de conversion binaire $1
+% A constant binary value does not have the correct syntax
+asmr_e_error_converting_hexadecimal=07038_E_Erreur de conversion hexadecimale $1
+% A constant hexadecimal value does not have the correct syntax
+asmr_h_direct_global_to_mangled=07039_H_$1 traduit en $2
+asmr_w_direct_global_is_overloaded_func=07040_W_$1 est associé(e) à une fonction surchargée
+asmr_e_cannot_use_SELF_outside_a_method=07041_E_Impossible d'utiliser SELF en dehors d'une méthode
+% There is a reference to the \var{self} symbol while it is not
+% allowed. \var{self} can only be referenced inside methods
+asmr_e_cannot_use_OLDEBP_outside_nested_procedure=07042_E_Impossible d'utiliser OLDEBP en dehors d'une procédure imbriquée
+% There is a reference to the \var{oldebp} symbol while it is not
+% allowed. \var{oldebp} can only be referenced inside nested routines
+asmr_e_void_function=07043_W_Les procédures ne peuvent pas retourner de valeur en code assembleur
+% Trying to return a value while in a procedure. A procedure
+% does not have any return value
+asmr_e_SEG_not_supported=07044_E_SEG non supporté
+asmr_e_size_suffix_and_dest_dont_match=07045_E_La taille du suffixe et celle de la destination ou de la source ne correspondent pas
+% The register size and the opcode size suffix don't match. This is
+% probably an error in the assembler statement
+asmr_w_size_suffix_and_dest_dont_match=07046_W_La taille du suffixe ne correspond pas à celle de la destination ou de la source
+% The register size and the opcode size suffix don't match. This is
+% probably an error in the assembler statement
+asmr_e_syntax_error=07047_E_Erreur de syntaxe assembleur
+% There is an assembler syntax error
+asmr_e_invalid_opcode_and_operand=07048_E_Combinaison de codes opération et de paramètres incorrecte
+% The opcode cannot be used with this type of operand
+asmr_e_syn_operand=07049_E_Erreur de syntaxe assembleur dans le paramètre
+asmr_e_syn_constant=07050_E_Erreur de syntaxe assembleur dans la constante
+asmr_e_invalid_string_expression=07051_E_Expression chaîne incorrecte
+asmr_w_const32bit_for_address=07052_W_Constante avec symbole $1 utilisée comme adresse n'est pas un pointeur
+% A constant expression represents an address which does not fit
+% into a pointer. The address is probably incorrect
+asmr_e_unknown_opcode=07053_E_Code opération $1 non reconnu
+% This opcode is not known
+asmr_e_invalid_or_missing_opcode=07054_E_Code opération incorrect ou manquant
+asmr_e_invalid_prefix_and_opcode=07055_E_Combinaison invalide de prefix avec un code opération: $1
+asmr_e_invalid_override_and_opcode=07056_E_Combinaison invalide de override avec un code opération: $1
+asmr_e_too_many_operands=07057_E_Nombre de paramètres insuffisant
+% There are too many operands for this opcode. Check your
+% assembler syntax
+asmr_w_near_ignored=07058_W_NEAR ignoré
+asmr_w_far_ignored=07059_W_FAR ignoré
+asmr_e_dup_local_sym=07060_E_Symbole local $1 dupliqué
+asmr_e_unknown_local_sym=07061_E_Symbole local $1 inconnu
+asmr_e_unknown_label_identifier=07062_E_Identificateur de label $1 inconnu
+asmr_e_invalid_register=07063_E_Nom de registre incorrect
+% There is an unknown register name used as operand.
+asmr_e_invalid_fpu_register=07064_E_Nom de registre de calcul réel incorrect
+% There is an unknown register name used as operand.
+asmr_w_modulo_not_supported=07066_W_Modulo non supporté
+asmr_e_invalid_float_const=07067_E_Constante réelle $1 invalide
+% The floating point constant declared in an assembler block is
+% invalid.
+asmr_e_invalid_float_expr=07068_E_Expression réelle invalide
+% The floating point expression declared in an assembler block is
+% invalid.
+asmr_e_wrong_sym_type=07069_E_Type de symbole incorrect
+asmr_e_cannot_index_relative_var=07070_E_Impossible d'indicer directement une variable locale ou un paramètre avec un registre
+% Trying to index using a base register a symbol which is already relative
+% to a register. This is not possible, and will probably lead to crashes.
+asmr_e_invalid_seg_override=07071_E_Expression d'override du segment incorrecte
+asmr_w_id_supposed_external=07072_W_Identificateur $1 supposé external
+% There is a reference to an undefined symbol. This will not result
+% in an error, since the symbol might be external, but may cause
+% problems at link time if the symbol is not defined anywhere.
+asmr_e_string_not_allowed_as_const=07073_E_Constantes chaînes non autorisées
+% Character strings are not allowed as constants.
+asmr_e_no_var_type_specified=07074_Type de variable non spécifié
+% The syntax expects a type idenfitifer after the dot, but
+% none was found.
+asmr_w_assembler_code_not_returned_to_text=07075_E_Code assembleur non retourné à la section text
+% There was a directive in the assembler block to change sections,
+% but there is a missing return to the text section at the end
+% of the assembler block. This might cause errors during link time.
+asmr_e_not_directive_or_local_symbol=07076_E_$1 n'est pas une directive ou un symbole local
+% This symbol is unknown.
+asmr_w_using_defined_as_local=07077_E_Utilisation d'un nom défini comme label local
+asmr_e_dollar_without_identifier=07078_E_Dollar utilisé sans identificateur
+% A constant expression has an identifier which does not start with
+% the $ symbol.
+asmr_w_32bit_const_for_address=07079_W_Constante 32 bits créée comme adresse
+% A constant was used as an address. This is probably an error,
+% since using absolute addresses will probably not work.
+asmr_n_align_is_target_specific=07080_N_.align dépend de la cible, utilisez .balign ou .p2align
+% Using the .align directive is platform specific, and its meaning will vary
+% from one platform to another.
+asmr_e_cannot_access_field_directly_for_parameters=07081_E_Impossible d'accéder directement aux champs transmis en paramètres
+% You should load the parameter first into a register and then access the
+% fields using that register.
+asmr_e_cannot_access_object_field_directly=07082_E_Impossible d'accéder directement aux champs d'objets ou de classes
+% You should load the self pointer first into a register and then access the
+% fields using the register as base. By default the self pointer is available
+% in the esi register on i386.
+asmr_e_unable_to_determine_reference_size=07083_E_Taille non spécifiée et impossibilité de déterminer la taille des paramètres
+% You should specify explicitly a size for the reference, because
+% the compiler is unable to determine what size (byte,word,dword,etc.) it
+% should use for the reference.
+asmr_e_cannot_use_RESULT_here=Impossible d'utiliser RESULT dans cette fonction
+% Some functions which return complex types cannot use the \var{result}
+% keyword.
+asmr_w_adding_explicit_args_fXX=07086_W_"$1" sans paramètre traduit en "$1 %st,%st(1)"
+asmr_w_adding_explicit_first_arg_fXX=07087_W_"$1 %st(n)" traduit en "$1 %st,%st(n)"
+asmr_w_adding_explicit_second_arg_fXX=07088_W_"$1 %st(n)" traduit en "$1 %st(n),%st"
+asmr_e_invalid_char_smaller=07089_E_Caractère < non autorisé ici
+% The shift operator requires the << characters. Only one
+% of those characters was found.
+asmr_e_invalid_char_greater=07090_E_Caractère > non autorisé ici
+% The shift operator requires the >> characters. Only one
+% of those characters was found.
+asmr_w_align_not_supported=07093_W_ALIGN non supporté
+asmr_e_no_inc_and_dec_together=07094_E_Inc et Dec ne peuvent pas être ensemble
+% Trying to use an increment and a decrement within the same
+% opcode on the 680x0. This is impossible.
+asmr_e_invalid_reg_list_in_movem=07095_E_Liste de registres invalide pour l'opération movem
+% Trying to use the \var{movem} opcode with invalid registers
+% to save or restore.
+asmr_e_invalid_reg_list_for_opcode=07096_E_Liste de registres invalide pour le code opération
+asmr_e_higher_cpu_mode_required=07097_E_Mode CPU supérieur nécessaire ($1)
+% Trying to use an instruction which is not supported in the current
+% cpu mode. Use a higher cpu generation to be able to use this
+% opcode in your assembler block
+asmr_w_unable_to_determine_reference_size_using_dword=07098_W_Taille non spécifiée et impossible de déterminer la taille des paramètres, utilisation de DWORD par défaut
+% You should specify explicitly a size for the reference, because
+% the compiler is unable to determine what size (byte,word,dword,etc.) it
+% should use for the reference. This warning is only used in Delphi mode where
+% it falls back to use DWORD as default.
+asmr_e_illegal_shifterop_syntax=07099_E_Erreur de syntaxe durant l'analyse d'une opération de décalage
+% ARM only; ARM assembler supports a so called shifter operand. The used syntax isn't
+% a valid shifter operand. Example for an operation with shifter operand:
+% \begin{verbatim}
+% asm
+% orr r2,r2,r2,lsl #8
+% end;
+% \end{verbatim}
+#
+# Assembler/binary writers
+#
+# 08018 is the last used one
+#
+asmw_f_too_many_asm_files=08000_F_Trop peu de fichiers assembleur
+% With smartlinking enabled, there are too many assembler
+% files generated. Disable smartlinking.
+asmw_f_assembler_output_not_supported=08001_F_Résultat de l'assembleur sélectionné non supporté
+asmw_f_comp_not_supported=08002_F_Comp non supporté
+asmw_f_direct_not_supported=08003_F_Direct non supporté pour les 'writers' binaires
+% Direct assembler mode is not supported for binary writers.
+asmw_e_alloc_data_only_in_bss=08004_E_Allocation de données supportée uniquement dans la section bss
+asmw_f_no_binary_writer_selected=08005_F_Aucun 'writer' binaire sélectionné
+asmw_e_opcode_not_in_table=08006_E_Asm: Code opération $1 absent de la liste
+asmw_e_invalid_opcode_and_operands=08007_E_Asm: $1 combinaison du code opération et des paramètres incorrecte
+asmw_e_16bit_not_supported=08008_E_Asm: référence 16 bits non supportée
+asmw_e_invalid_effective_address=08009_E_Asm: Adresse effective incorrecte
+asmw_e_immediate_or_reference_expected=08010_E_Asm: Immediate ou référence attendue
+asmw_e_value_exceeds_bounds=08011_E_Asm: la valeur $1 dépasse les limites $2
+asmw_e_short_jmp_out_of_range=08012_E_Asm: Saut court hors limites $1
+asmw_e_undefined_label=08013_E_Asm: Label $1 non défini
+asmw_e_comp_not_supported=08014_E_Asm: type Comp non supporté pour cette cible
+asmw_e_extended_not_supported=08015_E_Asm: type Extended non supporté pour cette cible
+asmw_e_duplicate_label=08016_E_Asm: label $1 dupliqué
+asmw_e_redefined_label=08017_E_Asm: label $1 redéfini
+asmw_e_first_defined_label=08018_E_Asm: Première définition
+asmw_e_invalid_register=08019_E_Asm: Registre $1 incorrect
+asmw_e_16bit_32bit_not_supported=08020_E_Asm: références 16 et 32 bits non supportées
+asmw_e_64bit_not_supported=08021_E_Asm: paramètres 64 bits non supportés
+#
+# Executing linker/assembler
+#
+# 09034 is the last used one
+#
+# BeginOfTeX
+%
+% \section{Errors of assembling/linking stage}
+% This section lists errors that occur when the compiler is processing the
+% command line or handling the configuration files.
+% \begin{description}
+exec_w_source_os_redefined=09000_W_Système d'exploitation source redéfini
+% The source operating system is redefined.
+exec_i_assembling_pipe=09001_I_Assemblage (pipe) de $1
+% Assembling using a pipe to an external assembler.
+exec_d_cant_create_asmfile=09002_E_Impossible de créer le fichier assembleur: $1
+% The mentioned file can't be created. Check if you have got
+% access permissions to create this file
+exec_e_cant_create_objectfile=09003_E_Impossible de créer le fichier object: $1
+% The mentioned file can't be created. Check if you've
+% got access permissions to create this file
+exec_e_cant_create_archivefile=09004_E_Impossible de créer le fichier archive: $1
+% The mentioned file can't be created. Check if you've
+% access permissions to create this file
+exec_e_assembler_not_found=09005_E_Assembleur $1 non trouvé, utilisation d'un assembleur externe
+% The assembler program was not found. The compiler will produce a script that
+% can be used to assemble and link the program.
+exec_t_using_assembler=09006_T_Utilisation de l'assembleur: $1
+% Information message saying which assembler is being used.
+exec_e_error_while_assembling=09007_E_Erreur durant l'assemblage, code de sortie $1
+% There was an error while assembling the file using an external assembler.
+% Consult the documentation of the assembler tool to find out more information
+% on this error.
+exec_e_cant_call_assembler=09008_E_Impossible d'appeler l'assembleur, erreur $1, utilisation d'un assembleur externe
+% An error occurred when calling an external assembler, The compiler will produce a script that
+% can be used to assemble and link the program.
+exec_i_assembling=09009_I_Assemblage de $1
+% An informational message stating which file is being assembled.
+exec_i_assembling_smart=09010_I_Assemblage avec édition intelligente des liens de $1
+% An informational message stating which file is being assembled using smartlinking.
+exec_w_objfile_not_found=09011_W_Objet $1 non trouvé, l'édition des liens peut échouer !
+% One of the object file is missing, and linking will probably fail.
+% Check your paths.
+exec_w_libfile_not_found=09012_W_Bibliothèque $1 non trouvée, l'édition des liens peut échouer !
+% One of the library file is missing, and linking will probably fail.
+% Check your paths.
+exec_e_error_while_linking=09013_E_Erreur durant l'édition des liens
+% Generic error while linking.
+exec_e_cant_call_linker=09014_E_Impossible d'appeler l'éditeur de liens, utilisation d'un éditeur de liens externe
+% An error occurred when calling an external linker, The compiler will produce a script that
+% can be used to assemble and link the program.
+exec_i_linking=09015_I_Édition des liens de $1
+% An informational message, showing which program or library is being linked.
+exec_e_util_not_found=09016_E_Utilitaire $1 non trouvé, utilisation d'un éditeur de liens externe
+% An external tool was not found, the compiler will produce a script that
+% can be used to assemble and link or postprocess the program.
+exec_t_using_util=09017_T_Utilisation de l'utilitaire $1
+% An informational message, showing which external program (usually a postprocessor) is being used.
+exec_e_exe_not_supported=09018_E_Création d'exécutables non supportée
+% Creating executable programs is not supported for this platform, because it was
+% not yet implemented in the compiler.
+exec_e_dll_not_supported=09019_E_Création de bibliothèques dynamiques/partagées non supportée
+% Creating dynamically loadable libraries is not supported for this platform, because it was
+% not yet implemented in the compiler.
+exec_i_closing_script=09020_I_Fermeture du script $1
+% Informational message showing when the external assembling an linking script is finished.
+exec_e_res_not_found=09021_E_Compilateur de ressource non trouvé, utilisation d'un compilateur externe
+% An external resource compiler was not found, the compiler will produce a script that
+% can be used to assemble, compile resources and link or postprocess the program.
+exec_i_compilingresource=09022_I_Compilation de la resource $1
+% An informational message, showing which resource is being compiled.
+exec_t_unit_not_static_linkable_switch_to_smart=09023_T_Édition statique des liens de l'unité $1 impossible, utilisation d'une édition intelligente des liens
+% Statical linking was requested, but a unit which is not statically linkable was used.
+exec_t_unit_not_smart_linkable_switch_to_static=09024_T_Édition intelligente des liens de l'unité $1 impossible, utilisation d'une édition de liens statique
+% Smart linking was requested, but a unit which is not smart-linkable was used.
+exec_t_unit_not_shared_linkable_switch_to_static=09025_T_Édition des liens partagée de l'unité $1 impossible, utilisation d'une édition de liens statique
+% Shared linking was requested, but a unit which is not shared-linkable was used.
+exec_e_unit_not_smart_or_static_linkable=09026_E_Édition intelligente ou statique des liens de l'unité $1 impossible
+% Smart or static linking was requested, but a unit which cannot be used for either was used.
+exec_e_unit_not_shared_or_static_linkable=09027_E_Édition des liens partagée ou statique de l'unité $1 impossible
+% Shared or static linking was requested, but a unit which cannot be used for either was used.
+exec_d_resbin_params=09028_D_Exécution du compilateur de ressource "$1" avec "$2" comme ligne de commande
+% An informational message showing which command-line is used for the resource compiler.
+%\end{description}
+# EndOfTeX
+#
+# Executable information
+#
+# BeginOfTeX
+% \section{Executable information messages.}
+% This section lists all messages that the compiler emits when an executable program is produced,
+% and only when the internal linker is used.
+% \begin{description}
+execinfo_f_cant_process_executable=09128_F_Post-traitement de l'exécutable $1 impossible
+% Fatal error when the compiler is unable to post-process an executable.
+execinfo_f_cant_open_executable=09129_F_Impossible d'ouvrir l'exécutable $1
+% Fatal error when the compiler cannot open the file for the executable.
+execinfo_x_codesize=09130_X_Taille du code: $1 octets
+% Informational message showing the size of the produced code section.
+execinfo_x_initdatasize=09131_X_Taille des données initialisées: $1 octets
+% Informational message showing the size of the initialized data section.
+execinfo_x_uninitdatasize=09132_X_Taille des données non-initialisées: $1 octets
+% Informational message showing the size of the uninitialized data section.
+execinfo_x_stackreserve=09133_X_Taille de pile réservée: $1 octets
+% Informational message showing the stack size that the compiler reserved for the executable.
+execinfo_x_stackcommit=09134_X_Taille de pile validée: $1 octets
+% Informational message showing the stack size that the compiler committed for the executable.
+%\end{description}
+# EndOfTeX
+#
+# Unit loading
+#
+# 10041 is the last used one
+#
+# BeginOfTeX
+% \section{Unit loading messages.}
+% This section lists all messages that can occur when the compiler is
+% loading a unit from disk into memory. Many of these messages are
+% informational messages.
+% \begin{description}
+unit_t_unitsearch=10000_T_Recherche de l'unité $1
+% When you use the \var{-vt}, the compiler tells you where it tries to find
+% unit files.
+unit_t_ppu_loading=10001_T_Chargement du fichier PPU $1
+% When the \var{-vt} switch is used, the compiler tells you
+% what units it loads.
+unit_u_ppu_name=10002_U_Fichier PPU: $1
+% When you use the \var{-vu} flag, the unit name is shown.
+unit_u_ppu_flags=10003_U_Drapeaux PPU: $1
+% When you use the \var{-vu} flag, the unit flags are shown.
+unit_u_ppu_crc=10004_U_Somme de contrôle du fichier PPU: $1
+% When you use the \var{-vu} flag, the unit CRC check is shown.
+unit_u_ppu_time=10005_U_Fichier PPU compilé à $1
+% When you use the \var{-vu} flag, the time the unit was compiled is shown.
+unit_u_ppu_file_too_short=10006_U_Fichier PPU trop court
+% The ppufile is too short, not all declarations are present.
+unit_u_ppu_invalid_header=10007_U_En-tête PPU invalide (PPU non trouvé au début)
+% A unit file contains as the first three bytes the ascii codes of \var{PPU}
+unit_u_ppu_invalid_version=10008_U_Version $1 de fichier PPU invalide
+% This unit file was compiled with a different version of the compiler, and
+% cannot be read.
+unit_u_ppu_invalid_processor=10009_U_Fichier PPU compilé pour un autre processeur
+% This unit file was compiled for a different processor type, and
+% cannot be read
+unit_u_ppu_invalid_target=10010_U_Fichier PPU compilé pour une autre cible
+% This unit file was compiled for a different target, and
+% cannot be read
+unit_u_ppu_source=10011_U_Fichier source: $1
+% When you use the \var{-vu} flag, the unit source file name is shown.
+unit_u_ppu_write=10012_U_Écriture de $1
+% When you specify the \var{-vu} switch, the compiler will tell you where it
+% writes the unit file.
+unit_f_ppu_cannot_write=10013_F_Impossible d'écrire le fichier PPU
+% An error occurred when writing the unit file.
+unit_f_ppu_read_error=10014_F_Erreur lors de la lecture du fichier PPU
+% This means that the unit file was corrupted, and contains invalid
+% information. Recompilation will be necessary.
+unit_f_ppu_read_unexpected_end=10015_F_Fin de fichier PPU inattendue
+% Unexpected end of file. This may mean that the PPU file is
+% corrupted.
+unit_f_ppu_invalid_entry=10016_F_Entrée invalide dans le fichier PPU $1
+% The unit the compiler is trying to read is corrupted, or generated with a
+% newer version of the compiler.
+unit_f_ppu_dbx_count_problem=10017_F_PPU Dbx count problem
+% There is an inconsistency in the debugging information of the unit.
+unit_e_illegal_unit_name=10018_E_Nom d'unité illégal: $1
+% The name of the unit does not match the file name.
+unit_f_too_much_units=10019_F_Trop d'unités
+% \fpc has a limit of 1024 units in a program. You can change this behavior
+% by changing the \var{maxunits} constant in the \file{fmodule.pas} file of the
+% compiler, and recompiling the compiler.
+unit_f_circular_unit_reference=10020_F_Référence circulaire entre les unités $1 et $2
+% Two units are using each other in the interface part. This is only allowed
+% in the \var{implementation} part. At least one unit must contain the other one
+% in the \var{implementation} section.
+unit_f_cant_compile_unit=10021_F_Compilation de l'unité $1 impossible, pas de sources disponibles
+% A unit was found that needs to be recompiled, but no sources are
+% available.
+unit_f_cant_find_ppu=10022_F_Impossible de trouver l'unité $1
+% You tried to use a unit of which the PPU file isn't found by the
+% compiler. Check your configuration file for the unit paths
+unit_w_unit_name_error=10023_W_Unité $1 non trouvée mais $2 existe
+% This error message is no longer used.
+unit_f_unit_name_error=10024_F_Unité $1 cherchée mais $2 trouvée
+% Dos truncation of 8 letters for unit PPU files
+% may lead to problems when unit name is longer than 8 letters.
+unit_w_switch_us_missed=10025_W_La compilation de l´unité System requiert l´option -Us
+% When recompiling the system unit (it needs special treatment), the
+% \var{-Us} must be specified.
+unit_f_errors_in_unit=10026_F_$1 erreurs lors de la compilation du module, arrêt
+% When the compiler encounters a fatal error or too many errors in a module
+% then it stops with this message.
+unit_u_load_unit=10027_U_Chargement à partir de $1 ($2) de l'unité $3
+% When you use the \var{-vu} flag, which unit is loaded from which unit is
+% shown.
+unit_u_recompile_crc_change=10028_U_Recompilation de $1, la somme de contrôle est maintenant $2
+% The unit is recompiled because the checksum of a unit it depends on has
+% changed.
+unit_u_recompile_source_found_alone=10029_U_Recompilation de $1, seul le source a été trouvé
+% When you use the \var{-vu} flag, these messages tell you why the current
+% unit is recompiled.
+unit_u_recompile_staticlib_is_older=10030_U_Recompilation de l'unité, la bibliothèque statique est plus ancienne que le fichier PPU
+% When you use the \var{-vu} flag, the compiler warns if the static library
+% of the unit are older than the unit file itself.
+unit_u_recompile_sharedlib_is_older=10031_U_Recompilation de l'unité, la bibliothèque partagée est plus ancienne que le fichier PPU
+% When you use the \var{-vu} flag, the compiler warns if the shared library
+% of the unit are older than the unit file itself.
+unit_u_recompile_obj_and_asm_older=10032_U_Recompilation de l'unité, les fichiers OBJ et ASM sont plus anciens que le fichier PPU
+% When you use the \var{-vu} flag, the compiler warns if the assembler or
+% object file of the unit are older than the unit file itself.
+unit_u_recompile_obj_older_than_asm=10033_U_Recompilation de l'unité, le fichier OBJ est plus ancien que le fichier ASM
+% When you use the \var{-vu} flag, the compiler warns if the assembler
+% file of the unit is older than the object file of the unit.
+unit_u_parsing_interface=10034_U_Analyse de l'interface de $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% parsing the interface part of the unit
+unit_u_parsing_implementation=10035_U_Analyse de l'implémentation de $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% parsing the implementation part of the unit
+unit_u_second_load_unit=10036_U_Deuxième compilation de l'unité $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% recompiling a unit for the second time. This can happend with interdepend
+% units.
+unit_u_check_time=10037_U_Vérification du fichier PPU $1, date/heure $2
+% When you use the \var{-vu} flag, the compiler show the filename and
+% date and time of the file which a recompile depends on
+### The following two error msgs are currently disabled.
+#unit_h_cond_not_set_in_last_compile=10038_H_Conditional $1 was not set at startup in last compilation of $2
+#% when recompilation of an unit is required the compiler will check that
+#% the same conditionals are set for the recompiliation. The compiler has
+#% found a conditional that currently is defined, but was not used the last
+#% time the unit was compiled.
+#unit_h_cond_set_in_last_compile=10039_H_Conditional $1 was set at startup in last compilation of $2
+#% when recompilation of an unit is required the compiler will check that
+#% the same conditionals are set for the recompiliation. The compiler has
+#% found a conditional that was used the last time the unit was compiled, but
+#% the conditional is currently not defined.
+unit_w_cant_compile_unit_with_changed_incfile=10040_W_Impossible de recompiler l'unité $1 alors que des fichiers inclus ont été trouvés
+% A unit was found to have modified include files, but
+% some source files were not found, so recompilation is impossible.
+unit_h_source_modified=10041_H_Le fichier $1 est plus récent que le fichier PPU $2
+% A modified source file for a unit was found that was compiled with the
+% release flag (-Ur). The unit will not implicitly be recompiled because
+% this release flag is set.
+unit_u_ppu_invalid_fpumode=10042_U_Utilisation d'une unité compilée avec un mode FPU incorrect
+% Trying to compile code while using units which were not compiled with
+% the same floating point format mode. Either all code should be compiled
+% with FPU emulation on, or with FPU emulation off.
+unit_u_loading_interface_units=10043_U_Chargement des unités déclarées dans l'interface de $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% loading the units defined in the interface part of the unit.
+unit_u_loading_implementation_units=10044_U_Chargement des unités déclarées dans l'implementation de $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% loading the units defined in the implementation part of the unit.
+unit_u_interface_crc_changed=10045_U_La somme de contrôle de l'interface de l'unité $1 a changé
+% When you use the \var{-vu} flag, the compiler warns that it the
+% CRC calculated for the interface has been changed after the implementation
+% has been parsed.
+unit_u_implementation_crc_changed=10046_U_La somme de contrôle de l'implémentation de l'unité $1 a changé
+% When you use the \var{-vu} flag, the compiler warns that it the
+% CRC calculated has been changed after the implementation
+% has been parsed.
+unit_u_finished_compiling=10047_U_Recompilation de l'unité $1 terminée
+% When you use the \var{-vu} flag, the compiler warns that it
+% has finished compiling the unit.
+unit_u_add_depend_to=10048_U_Ajout d'une dépendance entre $1 et $2
+% When you use the \var{-vu} flag, the compiler warns that it
+% has added a dependency between the two units.
+unit_u_no_reload_is_caller=10049_U_Pas de rechargement de $1 qui est l'unité appelante
+% When you use the \var{-vu} flag, the compiler warns that it
+% has will not reload the unit because it is the unit that wants
+% to load this unit
+unit_u_no_reload_in_second_compile=10050_U_Pas de rechargement de $1 déjà en cours de recompilation
+% When you use the \var{-vu} flag, the compiler warns that it
+% has will not reload the unit because it is already in a second recompile
+unit_u_flag_for_reload=10051_U_Nécessité de recharger $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has to reload the unit
+unit_u_forced_reload=10052_U_Rechargement forcé
+% When you use the \var{-vu} flag, the compiler warns that it
+% has is reloading the unit because it was required
+unit_u_previous_state=10053_U_État précédent de l'unité $1 : $2
+% When you use the \var{-vu} flag, the compiler shows the
+% previous state of the unit
+unit_u_second_compile_unit=10054_U_Recompilation de l'unité $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% recompiling a unit for the second time. This can happend with interdepend
+% units.
+unit_u_loading_unit=10055_U_Chargement de l'unité $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% loading the unit.
+unit_u_finished_loading_unit=10056_U_Chargement de l'unité $1 terminé
+% When you use the \var{-vu} flag, the compiler warns that it finished
+% loading the unit.
+unit_u_registering_new_unit=10057_U_Enregistrement de la nouvelle unité $1
+% When you use the \var{-vu} flag, the compiler warns that it has
+% found a new unit and registers it in the internal lists.
+unit_u_reresolving_unit=10058_U_Re-résolution de l'unité $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has to recalculate the internal data of the unit
+unit_u_skipping_reresolving_unit=10059_U_Saut de la re-resolution de l'unité $1, chargement des unités utilisées
+% When you use the \var{-vu} flag, the compiler warns that it
+% skips to recalculate the internal data of the unit because there
+% is no data to recalculate
+% \end{description}
+# EndOfTeX
+#
+# Options
+#
+# 11039 is the last used one
+#
+option_usage=11000_O_$1 [options] <nom_fichier> [options]
+# BeginOfTeX
+%
+% \section{Command-line handling errors}
+% This section lists errors that occur when the compiler is processing the
+% command line or handling the configuration files.
+% \begin{description}
+option_only_one_source_support=11001_W_Un seul fichier source supporté
+% You can specify only one source file on the command line. The first
+% one will be compiled, others will be ignored. This may indicate that
+% you forgot a \var{'-'} sign.
+option_def_only_for_os2=11002_W_Les fichiers DEF ne peuvent être créés que pour OS/2
+% This option can only be specified when you're compiling for OS/2
+option_no_nested_response_file=11003_E_Les fichiers de réponse imbriqués ne sont pas supportés
+% you cannot nest response files with the \var{@file} command-line option.
+option_no_source_found=11004_F_Pas de nom de fichier source sur la ligne de commande
+% The compiler expects a source file name on the command line.
+option_no_option_found=11005_N_Aucune option trouvée dans le fichier de configuration $1
+% The compiler didn't find any option in that config file.
+option_illegal_para=11006_E_Paramètre illégal: $1
+% You specified an unknown option.
+option_help_pages_para=11007_H_-? génère les pages d'aide
+% When an unknown option is given, this message is diplayed.
+option_too_many_cfg_files=11008_F_Trop de fichiers de configuration imbriqués
+% You can only nest up to 16 config files.
+option_unable_open_file=11009_F_Ouverture du fichier $1 impossible
+% The option file cannot be found.
+option_reading_further_from=11010_D_Lecture d'options supplémentaires depuis $1
+% Displayed when you have notes turned on, and the compiler switches
+% to another options file.
+option_target_is_already_set=11011_W_La destination est déjà définie à: $1
+% Displayed if more than one \var{-T} option is specified.
+option_no_shared_lib_under_dos=11012_W_Bibliothèques partagées non supportées sous DOS, retour à une édition de liens statique
+% If you specify \var{-CD} for the \dos platform, this message is displayed.
+% The compiler supports only static libraries under \dos
+option_too_many_ifdef=11013_F_Trop de IF(N)DEF
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_too_many_endif=11014_F_Trop de ENDIF
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_too_less_endif=11015_F_Directive de compilation conditionnelle non fermée à la fin du fichier
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_no_debug_support=11016_W_La génération d'informations de débogage n'est pas supportée par cet exécutable
+% It is possible to have a compiler executable that doesn't support
+% the generation of debugging info. If you use such an executable with the
+% \var{-g} switch, this warning will be displayed.
+option_no_debug_support_recompile_fpc=11017_H_Essayez de recompiler avec -dGDB
+% It is possible to have a compiler executable that doesn't support
+% the generation of debugging info. If you use such an executable with the
+% \var{-g} switch, this warning will be displayed.
+option_obsolete_switch=11018_W_Vous utilisez le commutateur obsolète $1
+% this warns you when you use a switch that is not needed/supported anymore.
+% It is recommended that you remove the switch to overcome problems in the
+% future, when the switch meaning may change.
+option_obsolete_switch_use_new=11019_W_Vous utilisez le commutateur obsolète $1, veuillez utiliser $2
+% this warns you when you use a switch that is not supported anymore. You
+% must now use the second switch instead.
+% It is recommended that you change the switch to overcome problems in the
+% future, when the switch meaning may change.
+option_switch_bin_to_src_assembler=11020_N_Switching assembler to default source writing assembler
+% this notifies you that the assembler has been changed because you used the
+% -a switch which can't be used with a binary assembler writer.
+option_incompatible_asm=11021_W_La sortie assembleur "$1" n'est pas compatible avec "$2"
+option_asm_forced=11022_W_Utilisation de l'assembleur "$1" forcée
+% The assembler output selected can not generate
+% object files with the correct format. Therefore, the
+% default assembler for this target is used instead.
+option_using_file=11026_T_Lecture des options depuis le fichier $1
+% Options are also read from this file
+option_using_env=11027_T_Lecture des options depuis la variable d'environnement $1
+% Options are also read from this environment string
+option_handling_option=11028_D_Utilisation de l'option "$1"
+% Debug info that an option is found and will be handled
+option_help_press_enter=11029__*** Appuyez sur Entrée ***
+option_start_reading_configfile=11030_H_Début de la lecture du fichier de configuration $1
+% Starting of config file parsing.
+option_end_reading_configfile=11031_H_Fin de la lecture du fichier de configuration $1
+% End of config file parsing.
+option_interpreting_option=11032_D_Interprétation de l'option "$1"
+option_interpreting_firstpass_option=11036_D_Interprétation de l'option de 1ère passe "$1"
+option_interpreting_file_option=11033_D_Interprétation de l'option de fichier "$1"
+option_read_config_file=11034_D_Lecture du fichier de configuration "$1"
+option_found_file=11035_D_Fichier source "$1" trouvé
+% Additional infos about options, displayed
+% when you have debug option turned on.
+option_code_page_not_available=11039_E_Page de codes inconnue
+option_config_is_dir=11040_F_Le fichier de configuration $1 est un répertoire
+% Directories can not be used as configuration files.
+%\end{description}
+# EndOfTeX
+#
+# Logo (option -l)
+#
+option_logo=11023_[ Compilateur Free Pascal version $FPCFULLVERSION [$FPCDATE] for $FPCCPU
+Copyright (c) 1993-2011, Florian Klaempfl ]
+#
+# Info (option -i)
+#
+option_info=11024_[ Compilateur Free Pascal version $FPCVERSION
+Date du compilateur: $FPCDATE
+Processeur cible: $FPCCPU
+Cibles supportées: $OSTARGETS
+Jeu d'instructions CPU supportés: $INSTRUCTIONSETS
+Jeu d'instructions FPU supportés: $FPUINSTRUCTIONSETS
+Optimisations supportées: $OPTIMIZATIONS
+Ce programme est fourni sous la License Publique Générale GNU (GNU GPL).
+Pour plus d'informations, consultez le fichier COPYING.FPC.
+Rapports de bogues, suggestions, etc. à:
+ http://bugs.freepascal.org
+ou
+ bugs@freepascal.org ]
+#
+# Help pages (option -? and -h)
+#
+# The first character on the line indicates who will display this
+# line, the current possibilities are :
+# * = every target
+# 3 = 80x86 targets
+# 6 = 680x0 targets
+# e = in extended debug mode only
+# P = PowerPC targets
+# S = Sparc targets
+# V = Virtual machine targets
+# The second character also indicates who will display this line,
+# (if the above character was TRUE) the current possibilities are :
+# * = everyone
+# g = with GDB info supported by the compiler
+# O = OS/2
+# L = UNIX systems
+# The third character represents the indentation level.
+#
+option_help_pages=11025_[
+**0*_mettre + après un booléen pour activer l'option, - pour la désactiver
+**1a_conserve les fichiers assembleurs créés pendant la compilation
+**2al_liste le code source dans les fichiers assembleur
+**2an_liste les infos de noeud dans le fichier assembleur
+*L2ap_utilise des pipes au lieu de fichiers assembleur temporaires
+**2ar_liste les allocations de registres dans les fichiers assembleur
+**2at_liste les allocations de données temporaire dans la pile
+**1A<x>_format de sortie :
+**2Adefault_utilise l'assembleur défini par défaut
+3*2Aas_fichier objet généré par GNU AS
+3*2Anasmcoff_fichier COFF (Go32v2) avec Nasm
+3*2Anasmelf_fichier ELF32 (Linux) avec Nasm
+3*2Anasmwin32_fichier objet Win32 utilisant Nasm
+3*2Anasmwdosx_fichier objet Win32/WDOSX utilisant Nasm
+3*2Awasm_fichier objet utilisant Wasm (Watcom)
+3*2Anasmobj_fichier OBJ avec Nasm
+3*2Amasm_fichier OBJ avec Masm (Microsoft)
+3*2Atasm_fichier OBJ avec Tasm (Borland)
+3*2Aelf_elf32 (Linux) utilisant le writer interne
+3*2Acoff_coff (Go32v2) using internal writer
+3*2Apecoff_pecoff (Win32) using internal writer
+4*2Aas_fichier objet généré par GNU AS
+6*2Aas_fichier .o Unix utilisant GNU AS
+6*2Agas_assembleur GNU Motorola
+6*2Amit_syntaxe MIT (anciennement GAS)
+6*2Amot_assembleur Motorola standard
+A*2Aas_assembler avec GNU AS
+P*2Aas_assembler avec GNU AS
+S*2Aas_assembler avec GNU AS
+**1b_génère les informations pour le browser
+**2bl_génère les informations locales également
+**1B_recompile toutes les unités
+**1C<x>_options de génération de code :
+**2Cc<x>_définir les convention d'appel <x> par défaut
+**2CD_créer une bibliothèque dynamique
+**2Ce_compilation avec émulation des opérations à virgule flottante
+**2Cf<x>_sélectionner le jeu d'instructions FPU à utiliser, voir fpc -i pour les valeurs possibles
+**2Cg_Générer du code PIC
+**2Ch<n>_<n> taille du tas en bytes (entre 1023 et 67107840)
+**2Ci_IO-checking
+**2Cn_pas de linking
+**2Co_génère des tests d'overflow pour les opérations sur les entiers
+**2Cp<x>_sélectionner le jeu d'instructions, voir fpc -i pour les valeurs possibles
+**2Cr_controle d'intervalles
+**2CR_vérifier la validité de l'appel à la méthode d'objet
+**2Cs<n>_spécifie <n> comme taille de la pile
+**2Ct_test de débordement de pile
+**2CX_créer également une bibliothèque avec liens optimisés
+**1d<x>_définit le symbole <x>
+**1D_génère un fichier DEF
+**2Dd<x>_assigne la description à <x>
+**2Dv<x>_affecter la version <x> à la DLL
+*O2Dw_application en mode protégé
+**1e<x>_définit le chemin vers l'exécutable
+**1E_comme -Cn
+**1F<x>_définit des chemins et noms de fichiers :
+**2Fa<x>[,y]_Pour un programme charger d'abord les unités <x> et [y] avant que uses ne soit analysé
+**2Fc<x>_Utiliser la page de codes <x> en entrée
+**2FD<x>_définit le répertoire où chercher les utilitaires de compilation
+**2Fe<x>_redirige les erreurs vers le fichier <x>
+**2FE<x>_répertoire pour les exe/unités : <x>
+**2Fi<x>_ajoute <x> à la liste des répertoires pour fichiers inclus
+**2Fl<x>_ajoute <x> à la liste des répertoires pour librairies
+**2FL<x>_utilises <x> comme lieur dynamique
+**2Fo<x>_ajoute <x> à la liste des répertoires pour fichiers objets
+**2Fr<x>_charge le fichier erreur <x>
+**2Fu<x>_ajoute <x> à la liste des répertoires pour unités
+**2FU<x>_définit le répertoire d'écriture des unités à <x>, en dépit de -FE
+*g1g<x>_génère des informations de débogage :
+*g2gc_générer des contrôles pour les pointeurs
+*g2gd_utilise dbx
+*g2gg_utilise gsym
+*g2gh_use l'unité de tracage du tas
+*g2gl_utiliser l'unité line info pour montrer plus de détails dans les traces
+*g2gv_générer des programmes traçables avec valgrind
+*g2gw_générer des infos de débogage au format dwarf
+**1i_information
+**2iD_donne la date du compilateur
+**2iV_donne la version du compilateur
+**2iW_retourner la version complète du compilateur
+**2iSO_donne l'OS du compilateur
+**2iSP_donne le processeur du compilateur
+**2iTO_donne l'OS cible
+**2iTP_donne le processeur cible
+**1I<x>_ajoute <x> à la liste des répertoires pour fichiers inclus
+**1k<x>_transmet <x> au linker
+**1l_écrit le logo
+**1M<x>_utiliser le type de langage <x>
+**2Mfpc_dialecte Free Pascal (par défaut)
+**2Mobjfpc_activation de certaines extensions Delphi 2
+**2Mdelphi_essaye d'être compatible avec Delphi
+**2Mtp_essaye d'être compatible avec TP/BP 7.0
+**2Mgpc_essaye d'être compatible avec gpc
+**2Mmacpas_essaye d'être compatible avec les dialectes Pascal du Macintosh
+**1n_ne pas lire le fichier de configuration par défaut
+**1o<x>_change le nom de l'executable en <x>
+**1O<x>_optimisations :
+3*2Oa_définir l'alignement <type>=<values>
+3*2Og_génère du code compact
+3*2OG_génère du code rapide (defaut)
+3*2Or_garde certaines variables dans des registres
+3*2Ou_autorise les optimisations incertaines (voir docs)
+3*2O1_optimisations niveau 1 (optimisations rapides)
+3*2O2_optimisations niveau 2 (-O1 + optimisations plus lentes)
+3*2O3_optimisations niveau 3 (comme -O2u)
+3*2Op<x>_processeur cible :
+3*3Op1_définit 386/486 comme processeur cible
+3*3Op2_définit Pentium/PentiumMMX (tm) comme processeur cycle
+3*3Op3_définit PPro/PII/c6x86/K6 (tm) comme processeur cycle
+3*3Op4_définit Pentium 4 (tm) comme processeur cycle
+3*3Op5_définit Pentium M (tm) comme processeur cycle
+6*2Og_génère du code compact
+6*2OG_génère du code rapide (par défaut)
+6*2Ox_optimiser au maximum (encore BOGUÉ !!!)
+6*2O0_définir le processeur cible MC68000
+6*2O2_définir le processeur cible MC68020+
+**1pg_génère du code pour profiler avec gprof (définit FPC_PROFILE)
+3*1R<x>_type lecture assembleur :
+3*2Ratt_lit l'assembleur AT&T
+3*2Rintel_lit l'assembleur Intel
+6*2RMOT_lire l'assembleur type motorola
+**1S<x>_options de syntaxe :
+**2S2_identique à -Mobjfpc
+**2Sa_include assertion code.
+**2Sc_autorise les operateurs type C (*=,+=,/= et -=)
+**2Sd_identique à -Mdelphi
+**2Se<x>_erreur d'options. <x> est une combinaison de :
+**3*_<n> : le compilateur s'arrête après <n> erreurs (1 par défaut)
+**3*_w : le compilateur s'arrête également en cas d'avertissements
+**3*_n : le compilateur s'arrête également en cas de notes
+**3*_h : le compilateur s'arrête également en cas de suggestions
+**2Sg_autorise LABEL et GOTO
+**2Sh_utilise les ansistrings
+**2Si_supporte les INLINE type C++
+**2SI<x>_définir le style d'interface <x>
+**3SIcom_interface compatible COM (par défaut)
+**3SIcorba_interface compatible CORBA
+**2Sk_charger l'unité fpcylix
+**2Sm_support des macros comme C (global)
+**2So_identique à -Mtp
+**2Sp_identique à -Mgpc
+**2Ss_les constructeurs doivent s'appeler init (et les destructeurs done)
+**1s_n'appelle pas l'assembleur ni le linker
+**2sh_générer un script à lier sur l'hôte
+**2st_générer un script à lier sur la cible
+**2sr_passer la phase d'allocation de registre (à utiliser avec -alr)
+**1T<x>_système d'expliotation cible:
+3*2Temx_OS/2 via EMX (et les extensions EMX/RSX)
+3*2Tfreebsd_FreeBSD
+3*2Tgo32v2_version 2 de l'extension DOS de DJ Delorie
+3*2Tlinux_Linux
+3*2Tnetbsd_NetBSD
+3*2Tnetware_Novell Netware Module (clib)
+3*2Tnetwlibc_Novell Netware Module (libc)
+3*2Topenbsd_OpenBSD
+3*2Tos2_OS/2 / eComStation
+3*2Tsunos_SunOS/Solaris
+3*2Twatcom_DOS extender compatible avec Watcom
+3*2Twdosx_WDOSX DOS extension
+3*2Twin32_Windows 32 Bits
+4*2Tlinux_Linux
+6*2Tamiga_Commodore Amiga
+6*2Tatari_Atari ST/STe/TT
+6*2Tlinux_Linux/m68k
+6*2Tmacos_Macintosh m68k
+6*2Tpalmos_PalmOS
+A*2Tlinux_Linux
+P*2Tdarwin_Darwin et MacOS X pour PowerPC
+P*2Tlinux_Linux pour PowerPC
+P*2Tmacos_MacOS (classique) pour PowerPC
+P*2Tmorphos_MorphOS
+S*2Tlinux_Linux
+**1u<x>_rend le symbole <x> non défini
+**1U_options d'unités :
+**2Un_ne pas vérifier le nom de l'unité
+**2Ur_générer des fichiers d'unité distribuables
+**2Us_compiler en temps qu'unité système
+**1v<x>_donne des informations. <x> est une combination des lettres suivantes :
+**2*_e : montre les erreurs (défaut) 0 : ne montre rien (sauf les erreurs)
+**2*_w : montre les avertissements u : montre les info sur les unités
+**2*_n : montre les notes t : montre les fichiers essayés/utilisés
+**2*_h : montre les suggestions c : montre les conditionniels
+**2*_i : montre des infos générales d : informations de déboggage
+**2*_l : montre les numéros de lignes r : mode compatibilité Rhide/GCC
+**2*_a : montre tout x : infos Executable (Win32 seulement)
+**2*_b : montre le nom des fichiers avec chemin complet dans les messages
+**2*_v : écrit fpcdebug.txt avec p : écrit tree.log avec arbre d'analyse
+**2*_ un maximum d'informations de débogage
+3*1W<x>_options pour cibles de type Win32
+3*2WB_créer une image relogeable
+3*2WB<x>_définir la base de l'Image à la valeur hexadecimale <x>
+3*2WC_générer une application console
+3*2WD_utiliser DEFFILE pour exporter les fonction de la DLL ou de l'EXE
+3*2WF_générer une application plein écran (OS/2 seulement)
+3*2WG_générer une application graphique
+3*2WN_ne pas générer de code relogeable (nécessaire pour le débogage)
+3*2WR_générer du code relogeable
+P*2WC_générer une application console (MacOS seulement)
+P*2WG_générer une application graphique (MacOS seulement)
+P*2WT_générer une application utilitaire (MPW tool, MacOS seulement)
+**1X_options pour executable :
+**2Xc_passer --shared à l'éditeur de liens (Unix seulement)
+**2Xd_ne pas utiliser le chemin de recherche des bibliothèques standard (nécessaire à la compilation pour une autre cible)
+**2XD_lien avec la librarie dynamique (définit FPC_LINK_DYNAMIC)
+**2Xm_générer un fichier MAP
+**2XM<x>_définir le nom de la procédure 'main' ('main' par défaut)
+**2XP<x>_prepend the binutils names with the prefix <x>
+**2Xr<x>_définir <x> comme chemin de recherche des bibliothèques (nécessaire à la compilation pour une autre cible)
+**2Xs_enlêve tous les symboles de l'executable
+**2XS_lien avec les librairies statiques (définit FPC_LINK_STATIC)
+**2Xt_lier avec des bibliothèques statiques (-static est passé à l'éditeur de liens)
+**2XX_essayer de lier les unités intelligemment (définit FPC_LINK_SMART)
+**1*_
+**1?_affiche cette aide
+**1h_affiche cette aide sans attente
+]
+
+#
+# The End...
diff --git a/closures/compiler/msg/errorhe.msg b/closures/compiler/msg/errorhe.msg
new file mode 100644
index 0000000000..e2fbbac9c3
--- /dev/null
+++ b/closures/compiler/msg/errorhe.msg
@@ -0,0 +1,2708 @@
+#
+# This file is part of the Free Pascal Compiler
+# Copyright (c) 1999-2008 by the Free Pascal Development team
+#
+# Hebrew (CP1255) language file for Free Pascal Compiler
+# Contributed by Ido Kanner <idokan at gmail.com> and Dotan Kamber <kamberd at yahoo.com>
+# Based on errore.msg of SVN revision 8988
+#
+# See the file COPYING.FPC, included in this distribution,
+# for details about the copyright.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#
+#
+# The constants are build in the following order:
+# <part>_<type>_<txtidentifier>
+#
+# <part> is the part of the compiler the message is used
+# asmr_ assembler parsing
+# asmw_ assembler writing/binary writers
+# unit_ unit handling
+# scan_ scanner
+# parser_ parser
+# type_ type checking
+# general_ general info
+# exec_ calls to assembler, linker, binder
+#
+# <type> the type of the message it should normally used for
+# f_ fatal error
+# e_ error
+# w_ warning
+# n_ note
+# h_ hint
+# i_ info
+# l_ add linenumber
+# u_ used
+# t_ tried
+# c_ conditional
+# d_ debug message
+# x_ executable informations
+#
+
+#
+# General
+#
+# 01023 is the last used one
+#
+# BeginOfTeX
+% \section{General compiler messages}
+% This section gives the compiler messages which are not fatal, but which
+% display useful information. The number of such messages can be
+% controlled with the various verbosity level \var{-v} switches.
+% \begin{description}
+general_t_compilername=01000_T_îäãø: $1
+% When the \var{-vt} switch is used, this line tells you what compiler
+% is used.
+general_d_sourceos=01001_D_îòøëú äôòìä: $1
+% When the \var{-vd} switch is used, this line tells you what the source
+% operating system is.
+general_i_targetos=01002_I_îòøëú äôòìä îéåòãú: $1
+% When the \var{-vd} switch is used, this line tells you what the target
+% operating system is.
+general_t_exepath=01003_T_îùúîù áðúéá äøöä: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for its binaries.
+general_t_unitpath=01004_T_îùúîù áðúéá äéçéãåú: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for compiled units. You can set this path with the \var{-Fu}
+general_t_includepath=01005_T_îùúîù áðúéá äîåñó: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for its include files (files used in \var{\{\$I xxx\}} statements).
+% You can set this path with the \var{-I} option.
+general_t_librarypath=01006_T_îùúîù áðúéá äñôøéä: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for the libraries. You can set this path with the \var{-Fl} option.
+general_t_objectpath=01007_T_Using object path: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for object files you link in (files used in \var{\{\$L xxx\}} statements).
+% You can set this path with the \var{-Fo} option.
+general_i_abslines_compiled=01008_I_$1 ùåøåú äåãøå, á$2 ùðéåú
+% When the \var{-vi} switch is used, the compiler reports the number
+% of lines compiled, and the time it took to compile them (real time,
+% not program time).
+general_f_no_memory_left=01009_F_ìà ðùàø æëøåï
+% The compiler doesn't have enough memory to compile your program. There are
+% several remedies for this:
+% \begin{itemize}
+% \item If you're using the build option of the compiler, try compiling the
+% different units manually.
+% \item If you're compiling a huge program, split it up in units, and compile
+% these separately.
+% \item If the previous two don't work, recompile the compiler with a bigger
+% heap (you can use the \var{-Ch} option for this, \seeo{Ch})
+% \end{itemize}
+general_i_writingresourcefile=01010_I_ëåúá àú ÷åáõ îùàáé èáìú äîçøåæåú: $1
+% This message is shown when the compiler writes the Resource String Table
+% file containing all the resource strings for a program.
+general_e_errorwritingresourcefile=01011_E_ëåúá àú ÷åáõ îùàáé èáìú äîçøåæåú: $1
+% This message is shown when the compiler encountered an error when writing
+% the Resource String Table file
+general_i_fatal=01012_I_ùâéàä ÷øéèéú:
+% Prefix for Fatal Errors
+general_i_error=01013_I_ùâéàä:
+% Prefix for Errors
+general_i_warning=01014_I_äúøàä:
+% Prefix for Warnings
+general_i_note=01015_I_äòøä:
+% Prefix for Notes
+general_i_hint=01016_I_øîæ:
+% Prefix for Hints
+general_e_path_does_not_exist=01017_E_äðúéá "$1" àéðå ÷ééí
+% The specified path does not exist.
+general_f_compilation_aborted=01018_F_ääéãåø áåèì
+% Compilation was aborted.
+general_text_bytes_code=01019_bytes code
+general_text_bytes_data=01020_bytes data
+general_i_number_of_warnings=01021_I_àæäøåú $1 äåðô÷å
+% Total number of warnings issued during compilation.
+general_i_number_of_hints=01022_I_äåðô÷å $1 øîæéí
+% Total number of hints issued during compilation.
+general_i_number_of_notes=01023_I_äåðô÷å $1 äòøåú
+% Total number of notes issued during compilation.
+% \end{description}
+#
+# Scanner
+#
+# 02084 is the last used one
+#
+% \section{Scanner messages.}
+% This section lists the messages that the scanner emits. The scanner takes
+% care of the lexical structure of the pascal file, i.e. it tries to find
+% reserved words, strings, etc. It also takes care of directives and
+% conditional compiling handling.
+% \begin{description}
+scan_f_end_of_file=02000_F_ñåó ÷åáõ ìà öôåé
+% this typically happens in one of the following cases :
+% \begin{itemize}
+% \item The source file ends before the final \var{end.} statement. This
+% happens mostly when the \var{begin} and \var{end} statements aren't
+% balanced;
+% \item An include file ends in the middle of a statement.
+% \item A comment was not closed
+% \end{itemize}
+scan_f_string_exceeds_line=02001_F_îçøåæú âåìùú îùåøä
+% There is a missing closing ' in a string, so it occupies
+% multiple lines.
+scan_f_illegal_char=02002_F_úå ìà çå÷é "$1" ($2)
+% An illegal character was encountered in the input file.
+scan_f_syn_expected=02003_F_ùâéàú úçáéø: îöôä ì "$1" àáì "$2" ðîöà
+% This indicates that the compiler expected a different token than
+% the one you typed. It can occur almost everywhere where you make a
+% mistake against the pascal language.
+scan_t_start_include_file=02004_TL_îúçéì ÷øéàä ùì ÷åáõ úåñôåú $1
+% When you provide the \var{-vt} switch, the compiler tells you
+% when it starts reading an included file.
+scan_w_comment_level=02005_W_øîú äòøåú $1 ðîöàä
+% When the \var{-vw} switch is used, then the compiler warns you if
+% it finds nested comments. Nested comments are not allowed in Turbo Pascal
+% and can be a possible source of errors.
+scan_n_ignored_switch=02008_N_îúòìí îîúâ îäãø "$1"
+% With \var{-vn} on, the compiler warns if it ignores a switch
+scan_w_illegal_switch=02009_W_îúâ îäãø "$1" àéðå çå÷é
+% You included a compiler switch (i.e. \var{\{\$... \}}) which the compiler
+% does not recognise
+scan_w_switch_is_global=02010_W_îé÷åí ùâåé ìîúâ îäãø âìåáìé
+% The compiler switch is misplaced, and should be located at
+% the start of the unit or program.
+scan_e_illegal_char_const=02011_E_úå ÷áåò ìà çå÷é
+% This happens when you specify a character with its ASCII code, as in
+% \var{\#96}, but the number is either illegal, or out of range.
+scan_f_cannot_open_input=02012_F_ìà ðéúï ìôúåç àú ÷åáõ "$1"
+% \fpc cannot find the program or unit source file you specified on the
+% command line.
+scan_f_cannot_open_includefile=02013_F_ìà ðéúï ìôúåç àú ÷åáõ äúåñôåú "$1"
+% \fpc cannot find the source file you specified in a \var{\{\$include ..\}}
+% statement.
+scan_e_illegal_pack_records=02015_E_ééùåø øùåîä ìà çå÷é îééöâ "$1"
+% You are specifying the \var{\{\$PACKRECORDS n\} } or \var{\{\$ALIGN n\} }
+% with an illegal value for \var{n}. For \$PACKRECORDS valid alignments are 1, 2, 4, 8, 16, 32, C,
+% NORMAL, DEFAULT, and for \$ALIGN valid alignment are 1, 2, 4, 8, 16, 32, ON,
+% OFF. Under mode MacPas \$ALIGN also supports MAC68K, POWER and RESET.
+scan_e_illegal_pack_enum=02016_E_îñôø îéðéîìé ùì îðééä äîééöâ "$1" àéðå çå÷é
+% You are specifying the \var{\{\$PACKENUM n\}} with an illegal value for
+% \var{n}. Only 1,2,4, NORMAL or DEFAULT are valid here.
+scan_e_endif_expected=02017_E_îöôä ì$ENDIF áäâãøä $1 $2 äðîöàú á$3 ùåøä $4
+% Your conditional compilation statements are unbalanced.
+scan_e_preproc_syntax_error=02018_E_ùâéàú úçáéø áòú ðéúåç îùôè úðàé
+% There is an error in the expression following the \var{\{\$if ..\}}, $ifc or $setc compiler
+% directives.
+scan_e_error_in_preproc_expr=02019_E_äòøëú îùôè úðàé
+% There is an error in the expression following the \var{\{\$if ..\}}, $ifc or $setc compiler
+% directives.
+scan_w_macro_cut_after_255_chars=02020_W_úåëï äî÷øå îåâáì ìàåøê ùì 255 úååéí
+% The contents of macros cannot be longer than 255 characters.
+scan_e_endif_without_if=02021_E_ENDIF ììà IF(N)DEF
+% Your \var{\{\$IFDEF ..\}} and {\{\$ENDIF\}} statements aren't balanced.
+scan_f_user_defined=02022_F_äâãøú îùúîù: $1
+% A user defined fatal error occurred. see also the \progref
+scan_e_user_defined=02023_E_äâãøú îùúîù: $1
+% A user defined error occurred. see also the \progref
+scan_w_user_defined=02024_W_äâãøú îùúîù: $1
+% A user defined warning occurred. see also the \progref
+scan_n_user_defined=02025_N_äâãøú îùúîù: $1
+% A user defined note was encountered. see also the \progref
+scan_h_user_defined=02026_H_äâãøú îùúîù: $1
+% A user defined hint was encountered. see also the \progref
+scan_i_user_defined=02027_I_äâãøú îùúîù: $1
+% User defined information was encountered. see also the \progref
+scan_e_keyword_cant_be_a_macro=02028_E_îéìú îôúç äîåâãøú îçãù ëî÷øå àéðä îëéìä äùôòä
+% You cannot redefine keywords with macros.
+scan_f_macro_buffer_overflow=02029_F_âìéùú îàâø î÷øå áòú ÷øéàä àå äøçáä ùì î÷øå
+% Your macro or its result was too long for the compiler.
+scan_w_macro_too_deep=02030_W_äøçáú î÷øå âåìùú îòåî÷ ùì 16.
+% When expanding a macro, macros have been nested to a level of 16.
+% The compiler will expand no further, since this may be a sign that
+% recursion is used.
+scan_w_wrong_styled_switch=02031_W_ îúâé ôòåìú îäãø àéðí ðúîëéí áäòøåú îñåâ //
+% Compiler switches should be in normal pascal style comments.
+scan_d_handling_switch=02032_DL_îèôì áîúâ "$1"
+% When you set debugging info on (\var{-vd}) the compiler tells you when it
+% is evaluating conditional compile statements.
+scan_c_endif_found=02033_CL_ðîöà ENDIF $1
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifdef_found=02034_CL_ðîöà IFDEF $1, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifopt_found=02035_CL_ðîöà IFOPT $1, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_if_found=02036_CL_ðîöà IF $1, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifndef_found=02037_CL_ðîöà IFNDEF $1, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_else_found=02038_CL_ðîöà ELSE $1, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_skipping_until=02039_CL_îãìâ...
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements, and whether it is skipping or
+% compiling parts.
+scan_i_press_enter=02040_I_ìçõ òì <return> ìäîùéê
+% When the \var{-vi} switch is used, the compiler stops compilation
+% and waits for the \var{Enter} key to be pressed when it encounters
+% a \var{\{\$STOP\}} directive.
+scan_w_unsupported_switch=02041_W_îúâ "$1" àéðå ðúîê
+% When warnings are turned on (\var{-vw}) the compiler warns you about
+% unsupported switches. This means that the switch is used in Delphi or
+% Turbo Pascal, but not in \fpc
+scan_w_illegal_directive=02042_W_äåøàú äîäãø "$1" àéðä çå÷éú
+% When warings are turned on (\var{-vw}) the compiler warns you about
+% unrecognised switches. For a list of recognised switches, \progref
+scan_t_back_in=02043_TL_çæøä á$1
+% When you use (\var{-vt}) the compiler tells you when it has finished
+% reading an include file.
+scan_w_unsupported_app_type=02044_W_àéï úîéëä ìñåâ äàôìé÷öéä: "$1"
+% You get this warning, if you specify an unknown application type
+% with the directive \var{\{\$APPTYPE\}}
+scan_w_app_type_not_support=02045_W_APPTYPE àéðå ðúîê ò"é ääîòøëú äôòìä äîáå÷ùú
+% The \var{\{\$APPTYPE\}} directive is supported by certain operating systems only.
+scan_w_description_not_support=02046_W_DESCRIPTION àéðå ðúîê ò"é îòøëú ääôòìä äîáå÷ùú
+% The \var{\{\$DESCRIPTION\}} directive is not supported on this target OS
+scan_n_version_not_support=02047_N_VERSION àéðå ðúîê ò"é îòøëú äôòìä äîáå÷ùú
+% The \var{\{\$VERSION\}} directive is not supported on this target OS
+scan_n_only_exe_version=02048_N_VERSION ø÷ ì÷áöé exe àå DLL
+% The \var{\{\$VERSION\}} directive is only used for executable or DLL sources.
+scan_w_wrong_version_ignored=02049_W_ôåøîè ùâåé ìäåøàú VERSION: "$1"
+% The \var{\{\$VERSION\}} directive format is majorversion.minorversion
+% where majorversion and minorversion are words.
+scan_e_illegal_asmmode_specifier=02050_E_ñâðåï äàñîáìø ùöåééï "$1" àéðå çå÷é
+% When you specify an assembler mode with the \var{\{\$ASMMODE xxx\}}
+% the compiler didn't recognize the mode you specified.
+scan_w_no_asm_reader_switch_inside_asm=02051_W_îúâ ÷åøà äASM àéðå àôùøé áúåê îùôè àñîáìé. "$1" éäéä éùôéò ø÷ áäëøæä äáàä/
+% It is not possible to switch from one assembler reader to another
+% inside an assembler block. The new reader will be used for next
+% assembler statements only.
+scan_e_wrong_switch_toggle=02052_E_ùéîåù ùâåé áîúâ. äùúîù áON/OFF àå á +/-
+% You need to use ON or OFF or a + or - to toggle the switch
+scan_e_resourcefiles_not_supported=02053_E_÷åáõ äîùàáéí àéðå ðúîê áéòã äðáçø
+% The target you are compiling for doesn't support resource files.
+scan_w_include_env_not_found=02054_W_îùúðä äñáéáä "$1" ìà ðîöà áñáéáä
+% The included environment variable can't be found in the environment, it will
+% be replaced by an empty string instead.
+scan_e_invalid_maxfpureg_value=02055_E_òøê ìà çå÷é ìäâáìåú àåâø äFPC
+% Valid values for this directive are 0..8 and NORMAL/DEFAULT
+scan_w_only_one_resourcefile_supported=02056_W_ø÷ ÷åáõ îùàáéí àçã ðúîê áéòã æä
+% The target you are compiling for supports only one resource file.
+% The first resource file found is used, the others are discarded.
+scan_w_macro_support_turned_off=02057_W_äúîéëä áî÷øå ëåáä
+% A macro declaration has been found, but macro support is currently off,
+% so the declaration will be ignored. To turn macro support on compile with
+% -Sm on the commandline or add \{\$MACRO ON\} in the source
+scan_e_invalid_interface_type=02058_E_äåëøæ ñåâ îîù÷ ìà çå÷é. äâãøåú çå÷éåú äí COM, CORBA àå DEFAULT
+% The interface type that was specified is not supported
+scan_w_appid_not_support=02059_W_APPID ðúîê ø÷ áPALMOS
+% The \var{\{\$APPID\}} directive is only supported for the PalmOS target.
+scan_w_appname_not_support=02060_W_APPNAME ðúîê ø÷ áPALMOS
+% The \var{\{\$APPNAME\}} directive is only supported for the PalmOS target.
+scan_e_string_exceeds_255_chars=02061_E_îçøåæú ÷áåòä ìà éëåìä ìäéåú îòì 255 úååéí
+% A single string constant can contain at most 255 chars. Try splitting up the
+% string in multiple smaller parts and concatenate them with a + operator.
+scan_f_include_deep_ten=02062_F_äåñôú ÷áöé äinclude âìù îòåî÷ ä16
+% When including include files the files have been nested to a level of 16.
+% The compiler will expand no further, since this may be a sign that
+% recursion is used.
+scan_e_too_many_push=02063_F_éåúø îéãé ùëáåú PUSH
+% A maximum of 20 levels is allowed. This error occurs only in mode MacPas.
+scan_e_too_many_pop=02064_E_POP ììà ùçøåø ùì PUSH
+% This error occurs only in mode MacPas.
+scan_e_error_macro_lacks_value=02065_E_î÷øå "$1" ìà îëéì òøëéí
+% Thus the conditional compile time expression cannot be evaluated.
+scan_e_wrong_switch_toggle_default=02066_E_ùéîåù áîúâ ùâåé, äùúîù á ON/OFF/DEFAULT àå á+/-/*
+% You need to use ON or OFF or DEFAULT or a + or - or * to toggle the switch
+scan_e_mode_switch_not_allowed=02067_E_îöá îúâ "$1" ìà îåøùä
+% A mode switch has already been encountered, or, in case of option -Mmacpas,
+% a mode switch occur after UNIT.
+scan_e_error_macro_undefined=02068_E_îùúðä æîï äéãåø "$1" ìà äåâãø.
+% Thus the conditional compile time expression cannot be evaluated. Only in mode MacPas.
+scan_e_utf8_bigger_than_65535=02069_E_ðîöà ÷åã UTF-8 âáåää éåúø î65535
+% \fpc handles utf-8 strings internally as widestrings e.g. the char codes are limited to 65535
+scan_e_utf8_malformed=02070_E_îçøåæú UTF-8 ú÷åìä
+% The given string isn't a valid UTF-8 string
+scan_c_switching_to_utf8=02071_C_UTF-8 signature found, using UTF-8 encoding
+% The compiler found an UTF-8 encoding signature (\$ef, \$bb, \$bf) at the beginning of a file,
+% so it interprets it as an UTF-8 file
+scan_e_compile_time_typeerror=02072_E_áéèåé áæîï äéãåø: ðãøù $1 àáì äú÷áì $2 á$3
+% Type check of a compile time expression failed.
+scan_n_app_type_not_support=02073_N_APPTYPE ìà ðúîê áîòøëú ääôòìä äîáå÷ùú
+% The \var{\{\$APPTYPE\}} directive is supported by certain operating systems only.
+scan_e_illegal_optimization_specifier=02074_E_ñåô÷ îéèåá ìà çå÷é "$1"
+% When you specify an optimization with the \var{\{\$OPTIMIZATION xxx\}}
+% the compiler didn't recognize the optimization you specified.
+scan_w_setpeflags_not_support=02075_W_SETPEFLAGS àéðå ðúîê áîòøëú ääôòìä äîáå÷ùú
+% The \var{\{\$SETPEFLAGS\}} directive is not supported by the target OS
+scan_w_imagebase_not_support=02076_W_IMAGEBASE àéðå ðúîê òì éãé îòøëú ääôòìä äîáå÷ùú
+% The \var{\{\$IMAGEBASE\}} directive is not supported by the target OS
+scan_w_minstacksize_not_support=02077_W_MINSTACKSIZE àéðå ðúîê òì éãé îòøëú ääôòìä äîáå÷ùú
+% The \var{\{\$MINSTACKSIZE\}} directive is not supported by the target OS
+scan_w_maxstacksize_not_support=02078_W_MAXSTACKSIZE àéðå ðúîê òì éãé îòøëú ääôòìä äîáå÷ùú
+% The \var{\{\$MAXSTACKSIZE\}} directive is not supported by the target OS
+scanner_e_illegal_warn_state=02079_E_ùéîåù ìà çå÷é áäðçéú $WARN
+% Only ON and OFF can be used as state with a \$warn compiler directive
+scan_e_only_packset=02080_E_òøê ùì àøéæä ìà çå÷é
+% Only 0, 1, 2, 4, 8, DEFAULT and NORMAL are allowed as packset parameter
+scan_w_pic_ignored=02081_W_îúòìí îäåøàú PIC
+% Several targets like windows do not support neither need PIC so the PIC directive and switch are
+% ignored.
+scan_w_unsupported_switch_by_target=02082_W_äîúâ "$1" àéðå ðúîê áñåâ úåöàä ùðáçø
+% Some compiler switches like \$E are not supported by all targets.
+scan_w_frameworks_darwin_only=02084_W_àôùøåéåú îáåññåú îñâøú ðúîëåú ø÷ òáåø Darwin/Mac OS X
+% Frameworks are not a known concept, or at least not supported by FPC, on operating systems other than Darwin/Mac OS X.
+scan_e_illegal_minfpconstprec=02085_E_ãéå÷ äòøê ä÷áåò ùì äð÷åãä äòùøåðéú äîéðéîìéú "$1" àéðå çå÷é
+% Valid minimal precisions for floating point constants are default, 32 and 64, which mean respectively minimal (usually 32 bit), 32 bit and 64 bit precision.
+% \end{description}
+#
+# Parser
+#
+# 03192 is the last used one
+#
+% \section{Parser messages}
+% This section lists all parser messages. The parser takes care of the
+% semantics of you language, i.e. it determines if your pascal constructs
+% are correct.
+% \begin{description}
+parser_e_syntax_error=03000_E_îôøù - ùâéàä úçáéøéú
+% An error against the Turbo Pascal language was encountered. This happens
+% typically when an illegal character is found in the sources file.
+parser_e_dont_nest_interrupt=03004_E_ôøåöãåøú ôñé÷ä àéðä éëåìä ìäéåú î÷åððú
+% An \var{INTERRUPT} procedure must be global.
+parser_w_proc_directive_ignored=03005_W_îúòìí îñåâ ôøåöãåøä "$1"
+% The specified procedure directive is ignored by FPC programs.
+parser_e_no_overload_for_all_procs=03006_E_ìà ëì ääëæøåú ùì "$1" áòìåú äëøæú OVERLOAD
+% When you want to use overloading using the \var{OVERLOAD} directive, then
+% all declarations need to have \var{OVERLOAD} specified.
+parser_e_export_name_double=03008_E_ëôéìåéåú áééöåà ùí äôåð÷öéä "$1"
+% Exported function names inside a specific DLL must all be different
+parser_e_export_ordinal_double=03009_E_ëôéìåéåú áééöåà àéðã÷ñ äôåð÷öéä "$1"
+% Exported function names inside a specific DLL must all be different
+parser_e_export_invalid_index=03010_E_àéðã÷ñ ìà ú÷éï ìééöåà äôåð÷öéä
+% DLL function index must be in the range \var{1..\$FFFF}
+parser_w_parser_reloc_no_debug=03011_W_ùéðåé îé÷åí ðúåðé äðéôåé ìà òåáãéí ì÷áöé DLL àå ÷áöé äøöä. äúáèì.
+parser_w_parser_win32_debug_needs_WN=03012_W_ìàôùø ðéôåé ùâéàåú ìwin32 éù ìáèì àú ùéðåé äîé÷åí ò"é äàôùøåú -WN
+% Stabs info is wrong for relocatable DLL or EXES use -WN
+% if you want to debug win32 executables.
+parser_e_constructorname_must_be_init=03013_E_ùí éåöø çééá ìäéåú INIT
+% You are declaring an object constructor with a name which is not \var{init}, and the
+% \var{-Ss} switch is in effect. See the \var{-Ss} switch (\seeo{Ss}).
+parser_e_destructorname_must_be_done=03014_E_ùí äåøñ çééá ìäéåú DONE
+% You are declaring an object destructor with a name which is not \var{done}, and the
+% \var{-Ss} switch is in effect. See the \var{-Ss} switch (\seeo{Ss}).
+parser_e_proc_inline_not_supported=03016_E_ôøåöãåøú INLINE ìà ðúîëú
+% You tried to compile a program with C++ style inlining, and forgot to
+% specify the \var{-Si} option (\seeo{Si}). The compiler doesn't support C++
+% styled inlining by default.
+parser_w_constructor_should_be_public=03018_W_éåöø öøéê ìäéåú öéáåøé
+% Constructors must be in the 'public' part of an object (class) declaration.
+parser_w_destructor_should_be_public=03019_W_äåøñ öøéê ìäéåú öéáåøé
+% Destructors must be in the 'public' part of an object (class) declaration.
+parser_n_only_one_destructor=03020_N_îçì÷ä öøéëä äåøñ àçã áìáã
+% You can declare only one destructor for a class.
+parser_e_no_local_objects=03021_E_äâãøåú îçì÷ä î÷åîéåú àéðí îåøùåú
+% Classes must be defined globally. They cannot be defined inside a
+% procedure or function
+parser_f_no_anonym_objects=03022_F_äâãøåú îçì÷ä àðåðéîéåú àéðí îåøùåú
+% An invalid object (class) declaration was encountered, i.e. an
+% object or class without methods that isn't derived from another object or
+% class. For example:
+% \begin{verbatim}
+% Type o = object
+% a : longint;
+% end;
+% \end{verbatim}
+% will trigger this error.
+parser_n_object_has_no_vmt=03023_N_äàåáéé÷è "$1" ììà VMT
+% This is a note indicating that the declared object has no
+% virtual method table.
+parser_e_illegal_parameter_list=03024_E_øùéîú ôøîèøéí ìà çå÷éú
+% You are calling a function with parameters that are of a different type than
+% the declared parameters of the function.
+parser_e_wrong_parameter_size=03026_E_îñôø ùâåé ùì ôøîèøéí öåéï òáåø ä÷øéàä ì "$1"
+% There is an error in the parameter list of the function or procedure,
+% the number of parameters is not correct.
+parser_e_overloaded_no_procedure=03027_E_îæää äîøåáä ùéîåù "$1" àéðå ôåð÷öéä
+% The compiler encountered a symbol with the same name as an overloaded
+% function, but it is not a function it can overload.
+parser_e_overloaded_have_same_parameters=03028_E_ôåð÷öéåú îøåáåú ùéîåù îëéìåú àú àåúí øùéîú ôøîèøéí
+% You're declaring overloaded functions, but with the same parameter list.
+% Overloaded function must have at least 1 different parameter in their
+% declaration.
+parser_e_header_dont_match_forward=03029_E_äâãøú äôåð÷öéä àéðä úåàîú àú ääâãøä ä÷åãîú "$1"
+% You declared a function with same parameters but
+% different result type or function modifiers.
+parser_e_header_different_var_names=03030_E_äâãøú äôåð÷öéä "$1" àéðä úåàîú àú äîéîåù: ùí îùúðä äùúðä $2 => $3
+% You declared the function in the \var{interface} part, or with the
+% \var{forward} directive, but define it with a different parameter list.
+parser_n_duplicate_enum=03031_N_òøëéí áñåâ îðéä çééáéí ìäéåú áñãø òåìä
+% \fpc allows enumeration constructions as in C. Given the following
+% declaration two declarations:
+% \begin{verbatim}
+% type a = (A_A,A_B,A_E:=6,A_UAS:=200);
+% type a = (A_A,A_B,A_E:=6,A_UAS:=4);
+% \end{verbatim}
+% The second declaration would produce an error. \var{A\_UAS} needs to have a
+% value higher than \var{A\_E}, i.e. at least 7.
+parser_e_no_with_for_variable_in_other_segments=03033_E_With àéðå îñåâì ìäùúîù áîùúðéí îî÷èò ùåðä
+% With stores a variable locally on the stack,
+% but this is not possible if the variable belongs to another segment.
+parser_e_too_much_lexlevel=03034_E_ôåð÷öéä î÷åððú > 31
+% You can nest function definitions only 31 times.
+parser_e_range_check_error=03035_E_ùâéàä ááãé÷ú èååç áòú äòøëú ÷áåòéí
+% The constants are out of their allowed range.
+parser_w_range_check_error=03036_W_ùâéàä ááãé÷ú èååç áòú äòøëú ÷áåòéí
+% The constants are out of their allowed range.
+parser_e_double_caselabel=03037_E_äëæøú úååéú ëôåìä ácase
+% You are specifying the same label 2 times in a \var{case} statement.
+parser_e_case_lower_less_than_upper_bound=03038_E_äèååç äñåôé ÷èï îäèååç ääúçìúé
+% The upper bound of a \var{case} label is less than the lower bound and this
+% is useless
+parser_e_type_const_not_possible=03039_E_äëøæú èéôåñ ÷áåòéí ùì îçì÷åú àå îîù÷éí àñåøä
+% You cannot declare a constant of type class or object.
+parser_e_no_overloaded_procvars=03040_E_îùúðéí ùì ôåð÷öéåú îøåáåú ùéîåù àéðí îåøùåú
+% You are trying to assign an overloaded function to a procedural variable.
+% This is not allowed
+parser_e_invalid_string_size=03041_E_àåøê îçøåæú çééá ìäéåú òí òøëéí î1 ì255
+% The length of a shortstring in Pascal is limited to 255 characters. You are
+% trying to declare a string with length lower than 1 or greater than 255
+parser_w_use_extended_syntax_for_objects=03042_W_äùúîù áúçáéø îåøçá ùì NEW åDISPOSE ìòåú÷éí ùì àåáéé÷è
+% If you have a pointer \var{a} to a class type, then the statement
+% \var{new(a)} will not initialize the class (i.e. the constructor isn't
+% called), although space will be allocated. you should issue the
+% \var{new(a,init)} statement. This will allocate space, and call the
+% constructor of the object
+parser_w_no_new_dispose_on_void_pointers=03043_W_äùéîåù áîöáéò ìà îåâãø òí NEW å DISPOSE çñø îùîòåú
+parser_e_no_new_dispose_on_void_pointers=03044_E_áìúé àôùøé ìäùúîù áîöáéò ìà îåâãø òí NEW àå DISPOSE
+% You cannot use \var{new(p)} or \var{dispose(p)} if \var{p} is an untyped pointer
+% because no size is associated to an untyped pointer.
+% Accepted for compatibility in \var{tp} and \var{delphi} modes.
+parser_e_class_id_expected=03045_E_îöôä ìîæää îçì÷ä
+% This happens when the compiler scans a procedure declaration that contains
+% a dot,
+% i.e., a object or class method, but the type in front of the dot is not
+% a known type.
+parser_e_no_type_not_allowed_here=03046_E_ñåâ îæää ìà îåøùä áîé÷åí äðåëçé
+% You cannot use a type inside an expression.
+parser_e_methode_id_expected=03047_E_îöôä ìîæää îúåãé
+% This identifier is not a method.
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., a object or class method, but the procedure name is not a
+% procedure of this type.
+parser_e_header_dont_match_any_member=03048_E_äâãøú äôåð÷öéä ìà æää ìîúåãåú ùì äîçì÷ä "$1"
+% This identifier is not a method.
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., a object or class method, but the procedure name is not a
+% procedure of this type.
+parser_d_procedure_start=03049_DL_ôøåöãåøä/ôåð÷öéä $1
+% When using the \var{-vd} switch, the compiler tells you when it starts
+% processing a procedure or function implementation.
+parser_e_error_in_real=03050_E_÷áåò ùì îñôø îîùé àéðå çå÷é
+% The compiler expects a floating point expression, and gets something else.
+parser_e_fail_only_in_constructor=03051_E_FAIL éëåì ìäéåú áùéîåù ø÷ áúåê éåöø
+% You are using the \var{fail} keyword outside a constructor method.
+parser_e_no_paras_for_destructor=03052_E_äåøñéí ìà éëåìéí ìäëéì ôøîèøéí
+% You are declaring a destructor with a parameter list. Destructor methods
+% cannot have parameters.
+parser_e_only_class_methods_via_class_ref=03053_E_ø÷ îúåãåú îçì÷ä éëåìåú ìäéåú îåâãøåú áäúééçñåú îçì÷ä
+% This error occurs in a situation like the following:
+% \begin{verbatim}
+% Type :
+% Tclass = Class of Tobject;
+%
+% Var C : TClass;
+%
+% begin
+% ...
+% C.free
+% \end{verbatim}
+% \var{Free} is not a class method and hence cannot be called with a class
+% reference.
+parser_e_only_class_methods=03054_E_ø÷ îúåãú îçì÷ä éëåìä ìâùú ìîúåãú îçì÷ä
+% This is related to the previous error. You cannot call a method of an object
+% from a inside a class method. The following code would produce this error:
+% \begin{verbatim}
+% class procedure tobject.x;
+%
+% begin
+% free
+% \end{verbatim}
+% Because free is a normal method of a class it cannot be called from a class
+% method.
+parser_e_case_mismatch=03055_E_÷áåòéí åñåâ CASE àéðí îúàéîéí
+% One of the labels is not of the same type as the case variable.
+parser_e_illegal_symbol_exported=03056_E_ìà ðéúï ìééöà àú äñîì îñôøééä
+% You can only export procedures and functions when you write a library. You
+% cannot export variables or constants.
+parser_w_should_use_override=03057_W_îúåãú éøåùä ðñúøú ò"é "$1"
+% A method that is declared \var{virtual} in a parent class, should be
+% overridden in the descendent class with the \var{override} directive. If you
+% don't specify the \var{override} directive, you will hide the parent method;
+% you will not override it.
+parser_e_nothing_to_be_overridden=03058_E_àéï îúåãä áîçì÷ä ùì äàá àùø ðéúï ìùëúá: "$1"
+% You are trying to \var{override} a virtual method of a parent class that does
+% not exist.
+parser_e_no_procedure_to_access_property=03059_E_ìà ðéúï îñôø ìâùú ìîàôééï
+% You specified no \var{read} directive for a property.
+parser_w_stored_not_implemented=03060_W_îàôééï ùîåø àéðå îáåöò òãééï
+% The \var{stored} directive is not yet implemented
+parser_e_ill_property_access_sym=03061_E_ñéîï ìà çå÷é ìâéùú äîàôééï
+% There is an error in the \var{read} or \var{write} directives for an array
+% property. When you declare an array property, you can only access it with
+% procedures and functions. The following code would cause such an error.
+% \begin{verbatim}
+% tmyobject = class
+% i : integer;
+% property x [i : integer]: integer read I write i;
+% \end{verbatim}
+%
+parser_e_cant_access_protected_member=03062_E_ìà ðéúï ìâùú ìùãä îåâï áàåáéé÷è äðåëçé
+% Fields that are declared in a \var{protected} section of an object or class
+% declaration cannot be accessed outside the module where the object is
+% defined, or outside descendent object methods.
+parser_e_cant_access_private_member=03063_E_ìà ðéúï ìâùú ìùãä ôøèé áàåá÷ééè äðåëçé
+% Fields that are declared in a \var{private} section of an object or class
+% declaration cannot be accessed outside the module where the class is
+% defined.
+parser_e_overridden_methods_not_same_ret=03066_E_îúåãä îøåáú ùéîåù çééáú ìäéåú æää áñåâ äîùúðä: "$2" áùéîåù ò"é "$1", àùø îëéìä ñåâ îùúðä àçø
+% If you declare overridden methods in a class definition, they must
+% have the same return type.
+parser_e_dont_nest_export=03067_E_äâããøú ôåð÷öéåú EXPORT ìà éëåìåú ìäéåú î÷åððåú
+% You cannot declare a function or procedure within a function or procedure
+% that was declared as an export procedure.
+parser_e_methods_dont_be_export=03068_E_àé àôùø ìééöà àú äîúåãä
+% You cannot declare a procedure that is a method for an object as
+% \var{export}ed.
+parser_e_call_by_ref_without_typeconv=03069_E_äùéîåù áôøîèø ùì îùúðä çééá ìäéåú æää: îëéì "$1" îöôä ì"$2"
+% When calling a function declared with \var{var} parameters, the variables in
+% the function call must be of exactly the same type. There is no automatic
+% type conversion.
+parser_e_no_super_class=03070_E_äîçì÷ä àéððä îçì÷ú àá ùì äîçì÷ä äðåëçéú
+% When calling inherited methods, you are trying to call a method of a non-related
+% class. You can only call an inherited method of a parent class.
+parser_e_self_not_in_method=03071_E_SELF îåøùä ø÷ áîúåãåú
+% You are trying to use the \var{self} parameter outside an object's method.
+% Only methods get passed the \var{self} parameters.
+parser_e_generic_methods_only_in_methods=03072_E_îúåãåú éëåìåú ìäé÷øà éùéøåú ø÷ áúåê îúåãåú àçøåú òí ñåâ îæää ùìäîçì÷ä
+% A construction like \var{sometype.somemethod} is only allowed in a method.
+parser_e_illegal_colon_qualifier=03073_E_ùéîåù ìà çå÷é ùì ':'
+% You are using the format \var{:} (colon) 2 times on an expression that
+% is not a real expression.
+parser_e_illegal_set_expr=03074_E_ùâéàä ááãé÷ú èååç áñãøú éåöøéí àå ùëôåì ñãøä
+% The declaration of a set contains an error. Either one of the elements is
+% outside the range of the set type, either two of the elements are in fact
+% the same.
+parser_e_pointer_to_class_expected=03075_E_îöôä ìîöáéò àåáéé÷è
+% You specified an illegal type in a \var{new} statement.
+% The extended syntax of \var{new} needs an object as a parameter.
+parser_e_expr_have_to_be_constructor_call=03076_E_äáéèåé çééá ìäéåú ÷øéàú éåöø
+% When using the extended syntax of \var{new}, you must specify the constructor
+% method of the object you are trying to create. The procedure you specified
+% is not a constructor.
+parser_e_expr_have_to_be_destructor_call=03077_E_äáéèåé çééá ìäéåú ÷øéàú äåøñ
+% When using the extended syntax of \var{dispose}, you must specify the
+% destructor method of the object you are trying to dispose of.
+% The procedure you specified is not a destructor.
+parser_e_invalid_record_const=03078_E_ñãø ìà çå÷é ùì àìîðèéí áøùåîä
+% When declaring a constant record, you specified the fields in the wrong
+% order.
+parser_e_false_with_expr=03079_E_ñåâ áéèåé çééá ìäéåú áéèåé øùåîä àå îçì÷ä
+% A \var{with} statement needs an argument that is of the type \var{record}
+% or \var{class}. You are using \var{with} on an expression that is not of
+% this type.
+parser_e_void_function=03080_E_ôøåöãåøä ìà éëåìä ìäçæéø òøê
+% In \fpc, you can specify a return value for a function when using
+% the \var{exit} statement. This error occurs when you try to do this with a
+% procedure. Procedures cannot return a value.
+parser_e_only_methods_allowed=03081_E_äéåöøéí åääåøñéí çééáéí ìäéåú îúåãééí
+% You're declaring a procedure as destructor, constructor or class operator, when the
+% procedure isn't a class method.
+parser_e_operator_not_overloaded=03082_E_äàåôøéèåø ìà îøåáä ùéîåù
+% You're trying to use an overloaded operator when it is not overloaded for
+% this type.
+parser_e_no_such_assignment=03083_E_ìà ðéúï ìäöéá òøëéí ìñåâéí îøåáé ùéîåù
+% You can not overload assignment for types
+% that the compiler considers as equal.
+parser_e_overload_impossible=03084_E_áìúé àôùøé ìäùúîù áàåôøèåø îøåáä ùéîåù
+% The combination of operator, arguments and return type are
+% incompatible.
+parser_e_no_reraise_possible=03085_E_ìà ðéúï ìäøéí çøéâä
+% You are trying to raise an exception where it is not allowed. You can only
+% raise exceptions in an \var{except} block.
+parser_e_no_new_or_dispose_for_classes=03086_E_äúçáéø äîåøçá ùì NEW àå DISPOSE ìà îåøùä ìîçì÷åú
+% You cannot generate an instance of a class with the extended syntax of
+% \var{new}. The constructor must be used for that. For the same reason, you
+% cannot call \var{dispose} to de-allocate an instance of a class, the
+% destructor must be used for that.
+parser_e_procedure_overloading_is_off=03088_E_äàôùøåú ìôøåöãåøåú îøåáåú ùéîåù ëáåé
+% When using the \var{-So} switch, procedure overloading is switched off.
+% Turbo Pascal does not support function overloading.
+parser_e_overload_operator_failed=03089_E_ìà ðéúï ìäòîéñ òì ñåâ äàåôøèåø äðåëçé. äòîñú äàåôøèåøéí ä÷ùåøéí ìôòåìä (àí áëìì) äí: $1
+% You are trying to overload an operator which cannot be overloaded.
+% The following operators can be overloaded :
+% \begin{verbatim}
+% +, -, *, /, =, >, <, <=, >=, is, as, in, **, :=
+% \end{verbatim}
+parser_e_comparative_operator_return_boolean=03090_E_àåôøèåø äùååàúé çééá ìäçæéø òøê áåìéàðé
+% When overloading the \var{=} operator, the function must return a boolean
+% value.
+parser_e_only_virtual_methods_abstract=03091_E_ø÷ ùéèä ååéøèåàìéú éëåìä ìäéåú îåôùè
+% You are declaring a method as abstract, when it is not declared to be
+% virtual.
+parser_f_unsupported_feature=03092_F_ùéîåù áàåôöéä ìà ðúîëú!
+% You're trying to force the compiler into doing something it cannot do yet.
+parser_e_mix_of_classes_and_objects=03093_E_äòøáåá ùì òöîéí ùåðéí (îçì÷åú, òöí, îîù÷ åëå') àéðå îåøùä
+% You cannot derive \var{objects}, \var{classes}, \var{cppclasses} and \var{interfaces} interttwined . E.g.
+% a class cannot have an object as parent and vice versa.
+parser_w_unknown_proc_directive_ignored=03094_W_îúòìí îäðçéú äùâøä: "$1"
+% The procedure directive you specified is unknown.
+parser_e_absolute_only_one_var=03095_E_absolute ðéúï ìùéîåù ø÷ òí îùúðä àçú
+% You cannot specify more than one variable before the \var{absolute} directive.
+% Thus, the following construct will provide this error:
+% \begin{verbatim}
+% Var Z : Longint;
+% X,Y : Longint absolute Z;
+% \end{verbatim}
+% \item [ absolute can only be associated a var or const ]
+% The address of a \var{absolute} directive can only point to a variable or a
+% typed constant. Therefore, the following code will produce this error:
+% \begin{verbatim}
+% Procedure X;
+%
+% var p : longint absolute x;
+% \end{verbatim}
+%
+parser_e_absolute_only_to_var_or_const=03096_E_ðéúï ìäùúîù áabsolute ø÷ òí îùúðä àå ÷áåò
+% The address of a \var{absolute} directive can only point to a variable or
+% constant. Therefore, the following code will produce this error:
+% \begin{verbatim}
+% Procedure X;
+%
+% var p : longint absolute x;
+% \end{verbatim}
+%
+parser_e_initialized_only_one_var=03097_E_ðéúï ìàúçì ø÷ îùúðä àçã
+% You cannot specify more than one variable with a initial value
+% in Delphi mode.
+parser_e_abstract_no_definition=03098_E_îúåãä îåôùèú àéðä æ÷å÷ä ìäâãøä (òí âåó ùì ôåð÷öéä)
+% Abstract methods can only be declared, you cannot implement them. They
+% should be overridden by a descendant class.
+parser_e_overloaded_must_be_all_global=03099_E_äòîñú äéúø ùì äôåð÷öéä àéðä éëåìä ìäéåú î÷åîéú (çééáú ìäéåú îéåöàú)
+% You are defining a overloaded function in the implementation part of a unit,
+% but there is no corresponding declaration in the interface part of the unit.
+parser_w_virtual_without_constructor=03100_W_ùéîåù áîúåãåú ååéøèåàìéåú ììà éåöø á "$1"
+% If you declare objects or classes that contain virtual methods, you need
+% to have a constructor and destructor to initialize them. The compiler
+% encountered an object or class with virtual methods that doesn't have
+% a constructor/destructor pair.
+parser_c_macro_defined=03101_CL_äâãøú îà÷øå: $1
+% When \var{-vc} is used, the compiler tells you when it defines macros.
+parser_c_macro_undefined=03102_CL_îà÷øå ìà îåâãø: $1
+% When \var{-vc} is used, the compiler tells you when it undefines macros.
+parser_c_macro_set_to=03103_CL_îà÷øå $1 îåâãø ë $2
+% When \var{-vc} is used, the compiler tells you what values macros get.
+parser_i_compiling=03104_I_îäãø $1
+% When you turn on information messages (\var{-vi}), the compiler tells you
+% what units it is recompiling.
+parser_u_parsing_interface=03105_UL_îôøù àú äîîù÷ ùì äéçéãä $1
+% This tells you that the reading of the interface
+% of the current unit starts
+parser_u_parsing_implementation=03106_UL_îôøù àú äáéöåò ùì $1
+% This tells you that the code reading of the implementation
+% of the current unit, library or program starts
+parser_d_compiling_second_time=03107_DL_îäãø àú $1 áôòí äùðééä
+% When you request debug messages (\var{-vd}) the compiler tells you what
+% units it recompiles for the second time.
+parser_e_no_property_found_to_override=03109_E_ìà ðîöàä úëåðä ìò÷éôä
+% You want to override a property of a parent class, when there is, in fact,
+% no such property in the parent class.
+parser_e_only_one_default_property=03110_E_ø÷ úëåðä àçú òí áøéøú îçãì îåøùú
+% You specified a property as \var{Default}, but the class already has a
+% default property, and a class can have only one default property.
+parser_e_property_need_paras=03111_E_äúåðä òí áøéøú îçãì çééáú ìäéåú úëåðä ùì îòøê
+% Only array properties of classes can be made \var{default} properties.
+parser_e_constructor_cannot_be_not_virtual=03112_E_éåöøéí ååéøèåàìéí ðúîëéí ø÷ áîçì÷ä
+% You cannot have virtual constructors in objects. You can only have them
+% in classes.
+parser_e_no_default_property_available=03113_E_òøê áøéøú îçãì àéðå ÷ééí ìúëåðä
+% You are trying to access a default property of a class, but this class (or one of
+% its ancestors) doesn't have a default property.
+parser_e_cant_have_published=03114_E_äîçì÷ä àéðä éëåìä ìäëéì àú çúê published, äùúîù áîúâ {$M+}
+% If you want a \var{published} section in a class definition, you must
+% use the \var{\{\$M+\}} switch, whch turns on generation of type
+% information.
+parser_e_forward_declaration_must_be_resolved=03115_E_ðãøùú äâãøä øàùåðéú ùì äîçì÷ä "$1" ìôðé äùéîåù áä ëîçì÷ä éåøùú
+% To be able to use an object as an ancestor object, it must be defined
+% first. This error occurs in the following situation:
+% \begin{verbatim}
+% Type ParentClas = Class;
+% ChildClass = Class(ParentClass)
+% ...
+% end;
+% \end{verbatim}
+% Where \var{ParentClass} is declared but not defined.
+parser_e_no_local_operator=03116_E_äùéîåù áàåôøéèåø î÷åîé àéðå ðúîê
+% You cannot overload locally, i.e. inside procedures or function
+% definitions.
+parser_e_proc_dir_not_allowed_in_interface=03117_E_î÷ãí ùéâøä "$1" àéðå îåøùä áùéîåù áúåê äîîù÷
+% This procedure directive is not allowed in the \var{interface} section of
+% a unit. You can only use it in the \var{implementation} section.
+parser_e_proc_dir_not_allowed_in_implementation=03118_E_î÷ãí ùéâøä "$1" àéðå îåøùä áçì÷ äáéöåòé
+% This procedure directive is not defined in the \var{implementation} section of
+% a unit. You can only use it in the \var{interface} section.
+parser_e_proc_dir_not_allowed_in_procvar=03119_E_î÷ãí ùéâøä "$1" àéðå îåøùä ëçì÷ îäâãøú äùéâøä
+% This procedure directive cannot be part of a procedural or function
+% type declaration.
+parser_e_function_already_declared_public_forward=03120_E_äâãøú äôåð÷öéä "$1" ëáø áåöòä
+% You will get this error if a function is defined as \var{forward} twice.
+% Or it is once in the \var{interface} section, and once as a \var{forward}
+% declaration in the \var{implmentation} section.
+parser_e_not_external_and_export=03121_E_ìà ðéúï ìäùúîù âí á EXPORT åâí EXTERNAL
+% These two procedure directives are mutually exclusive
+parser_w_not_supported_for_inline=03123_W_"$1" àéðå ðúîê òãééï áúåê ôåð÷öéú/ùâøú inline
+% Inline procedures don't support this declaration.
+parser_w_inlining_disabled=03124_W_äùéîåù äéùéø îáåèì
+% Inlining of procedures is disabled.
+parser_i_writing_browser_log=03125_I_ëåúá éåîï ãôãôï $1
+% When information messages are on, the compiler warns you when it
+% writes the browser log (generated with the \var{\{\$Y+ \}} switch).
+parser_h_maybe_deref_caret_missing=03126_H_ééúëï ëé çñø úåëï ìîöáéò
+% The compiler thinks that a pointer may need a dereference.
+parser_f_assembler_reader_not_supported=03127_F_àéï úîéëä áîàñó äðáçø
+% The selected assembler reader (with \var{\{\$ASMMODE xxx\}} is not
+% supported. The compiler can be compiled with or without support for a
+% particular assembler reader.
+parser_e_proc_dir_conflict=03128_E_î÷ãí äùéâøä "$1" îúðâù òí î÷ãîéí àçøéí
+% You specified a procedure directive that conflicts with other directives.
+% for instance \var{cdecl} and \var{pascal} are mutually exclusive.
+parser_e_call_convention_dont_match_forward=03129_E_äùéîåù áäâãøä äðåëçéú àéðå æää ìäâãøä äøàùåðéú
+% This error happens when you declare a function or procedure with
+% e.g. \var{cdecl;} but omit this directive in the implementation, or vice
+% versa. The calling convention is part of the function declaration, and
+% must be repeated in the function definition.
+parser_e_property_cant_have_a_default_value=03131_E_úëåðåú àéðï éëåìåú ìäëéì òøê áøéøú îçãì
+% Set properties or indexed properties cannot have a default value.
+parser_e_property_default_value_must_const=03132_E_òøê áøéøú äîçãì÷ ùú äúëåðä çééá ìäéåú ÷áåò
+% The value of a \var{default} declared property must be known at compile
+% time. The value you specified is only known at run time. This happens
+% .e.g. if you specify a variable name as a default value.
+parser_e_cant_publish_that=03133_E_äñîì àéðå éëåì ìäéåú áùéîåù áúåê îçì÷ä ììà äâãøúå áúåê äîçì÷ä
+% Only class type variables can be in a \var{published} section of a class
+% if they are not declared as a property.
+parser_e_cant_publish_that_property=03134_E_ñåâ æä ùì úëåðä àéðå éëåì ìäéåú áùéîåù
+% Properties in a \var{published} section cannot be array properties.
+% they must be moved to public sections. Properties in a \var{published}
+% section must be an ordinal type, a real type, strings or sets.
+parser_e_empty_import_name=03136_E_ðãøù ùí ééáåà
+% Some targets need a name for the imported procedure or a \var{cdecl} specifier
+parser_e_division_by_zero=03138_E_çìå÷ áàôñ
+% There is a division by zero encounted
+parser_e_invalid_float_operation=03139_E_ôòåìú òùøåðéú ìà çå÷éú
+% An operation on two real type values produced an overflow or a division
+% by zero.
+parser_e_array_lower_less_than_upper_bound=03140_E_äâáåì äòìéåï ðîåê éåúø îäâáåì äúçúåï
+% The upper bound of a an array declaration is less than the lower bound and this
+% is not possible
+parser_w_string_too_long=03141_W_àåøê äîçøåæú ùì "$1" àøåê éåúø î "$1"
+% The size of the constant string is larger than the size you specified in
+% string type definition
+parser_e_string_larger_array=03142_E_àåøê äîçøåæú àøåê éåúø îàåøê îòøê äúååéí
+% The size of the constant string is larger than the size you specified in
+% the array[x..y] of char definition
+parser_e_ill_msg_expr=03143_E_äúåëï ùì äáéèåé ìàçø ääåãòä àéðå çå÷é
+% \fpc supports only integer or string values as message constants
+parser_e_ill_msg_param=03144_E_èéôåì áäåãòåú çééá ìäéåú áîáðä ÷áåò ùì ôøîèøéí
+% A method declared with the \var{message}-directive as message handler
+% can take only one parameter which must be declared as call by reference
+% Parameters are declared as call by reference using the \var{var}-directive
+parser_e_duplicate_message_label=03145_E_úååéú äåãòä ëôåìä: "$1"
+% A label for a message is used twice in one object/class
+parser_e_self_in_non_message_handler=03146_E_Self çééá ìäéåú ôøîèø áîúåãä ùì îèôì ääåãòåú
+% The self parameter can only be passed explicitly to a method which
+% is declared as message handler.
+parser_e_threadvars_only_sg=03147_E_Threadvars çééáéí ìäéåú ñèèééí àå âìåáìééí
+% Threadvars must be static or global, you can't declare a thread
+% local to a procedure. Local variables are always local to a thread,
+% because every thread has its own stack and local variables
+% are stored on the stack
+parser_f_direct_assembler_not_allowed=03148_F_äùéîåù áîàñó äðåëçé àéðå úåîê áåñâ äúåöàä äáéðàøéú
+% You can't use direct assembler when using a binary writer, choose an
+% other outputformat or use another assembler reader
+parser_w_no_objpas_use_mode=03149_W_àñåø ì÷øåà ìéçéãú OBJPAS éùéøåú, éù ìäùúîù á \{\$mode objfpc\} àå á \{\$mode delphi\} áî÷åí
+% You are trying to load the ObjPas unit manually from a uses clause. This is
+% not a good idea. Use the \var{\{\$mode objfpc\}} or
+% \var{\{\$mode delphi\}}
+% directives which load the unit automatically
+parser_e_no_object_override=03150_E_OVERRIDE àéðå éëåì ìäéåú áùéîåù áàåáéé÷èéí
+% Override is not supported for objects, use \var{virtual} instead to override
+% a method of a parent object
+parser_e_cant_use_inittable_here=03151_E_èéôåñé ðúåðéí àùø ãåøùéí àúçåì àå ñéëåí àéðí éëåìéí ìäéåú áøùåîåú variant
+% Some data type (e.g. \var{ansistring}) needs initialization/finalization
+% code which is implicitly generated by the compiler. Such data types
+% can't be used in the variant part of a record.
+parser_e_resourcestring_only_sg=03152_E_ìà ðéúï ìäâãéø Resourcestring áúåø äâãøä î÷åîéú, ø÷ äâãøä âìåáìéú àå ñèèéú
+% Resourcestring can not be declared local, only global or using the static
+% directive.
+parser_e_exit_with_argument_not__possible=03153_E_äùéîåù áùéâøä exit àéðå éëåì ìäúáöò áîé÷åí äðåëçé
+% an exit statement with an argument for the return value can't be used here, this
+% can happen e.g. in \var{try..except} or \var{try..finally} blocks
+parser_e_stored_property_must_be_boolean=03154_E_èéôåñ äðúåðéí áñéîåì äàçñåï çééá ìäéåú áåìéàðé
+% If you specify a storage symbol in a property declaration, it must be of
+% the type boolean
+parser_e_ill_property_storage_sym=03155_E_äñéîåì àéðå éëåì ìäùîù ëñéîåì ìàçñåï
+% You can't use this type of symbol as storage specifier in property
+% declaration. You can use only methods with the result type boolean,
+% boolean class fields or boolean constants
+parser_e_only_publishable_classes_can_be_published=03156_E_ø÷ îçì÷ä äîäåãøú áîöá $M+ éëåìä ìäéåú àéæåø ä published
+% In the published section of a class can be only class as fields used which
+% are compiled in \var{\{\$M+\}} or which are derived from such a class. Normally
+% such a class should be derived from TPersitent
+parser_e_proc_directive_expected=03157_E_îöôä ìäðçééú ùéâøä
+% This error is triggered when you have a \var{\{\$Calling\}} directive without
+% a calling convention specified.
+% It also happens when declaring a procedure in a const block and you
+% used a ; after a procedure declaration which must be followed by a
+% procedure directive.
+% Correct declarations are:
+% \begin{verbatim}
+% const
+% p : procedure;stdcall=nil;
+% p : procedure stdcall=nil;
+% \end{verbatim}
+parser_e_invalid_property_index_value=03158_E_äòøê äàéðã÷ñ ùì äúëåðä çééá ìäéåú èéôåñ îñåãø
+% The value you use to index a property must be of an ordinal type, for
+% example an integer or enumerated type.
+parser_e_procname_to_short_for_export=03159_E_ùí äùâøä ÷öø îéãé ìééöåà
+% The length of the procedure/function name must be at least 2 characters
+% long. This is because of a bug in dlltool which doesn't parse the .def
+% file correct with a name of length 1.
+parser_e_dlltool_unit_var_problem=03160_E_ìà ðéúï ìééöø çì÷ DEFFILE ìîùúðéí âìåáìééí áéçéãä
+parser_e_dlltool_unit_var_problem2=03161_E_äãø ììà ùéîåù á -WD
+% You need to compile this file without the -WD switch on the
+% commandline
+parser_f_need_objfpc_or_delphi_mode=03162_F_éù ìäùúîù áîöá ObjFpc (-S2) àå áîöá Delphi (-Sd) ìäãø àú äîåãåì
+% You need to use \{\$mode objfpc\} or \{\$mode delphi\} to compile this file.
+% Or use the equivalent commandline switches -S2 or -Sd.
+parser_e_no_export_with_index_for_target=03163_E_àé àôùø ìééöà òí àéðã÷ñ úçú $1
+% Exporting of functions or procedures with a specified index is not
+% supported on this target.
+parser_e_no_export_of_variables_for_target=03164_E_ééöåà ùì îùúîù àéðå ðúîê á$1
+% Exporting of variables is not supported on this target.
+parser_e_improper_guid_syntax=03165_E_úçáéø GUID àéðå çå÷é
+% The GUID indication does not have the proper syntax. It should be of the form
+% \begin{verbatim}
+% {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}
+% \end{verbatim}
+% Where each \var{X} represents a hexadecimal digit.
+parser_w_interface_mapping_notfound=03168_W_äùâøä "$1" ðîöàä àê ììà äôøîèøéí äîáå÷ùéí ùì $2.$3
+% The compiler cannot find a suitable procedure which implements the given method of an interface.
+% A procedure with the same name is found, but the arguments do not match.
+parser_e_interface_id_expected=03169_E_îöôä ìîæää îîù÷
+% This happens when the compiler scans a \var{class} declaration that contains
+% \var{interface} function name mapping code like this:
+% \begin{verbatim}
+% type
+% TMyObject = class(TObject, IDispatch)
+% function IUnknown.QueryInterface=MyQueryInterface;
+% ....
+% \end{verbatim}
+% and the \var{interface} before the dot not listed in the inheritance list.
+parser_e_type_cant_be_used_in_array_index=03170_E_äñåâ "$1" àéðå éëåì ìäéåú áùéîåù áúåø ñåâ àéðã÷ñ ìîòøê
+% Types like \var{qword} or \var{int64} aren't allowed as array index type
+parser_e_no_con_des_in_interfaces=03171_E_éåöø åäåøñ àéðí îåøùéí áîîù÷éí
+% Constructor and destructor declarations aren't allowed in interface
+% In the most cases the method \var{QueryInterface} of \var{IUnknown} can
+% be used to create a new interface.
+parser_e_no_access_specifier_in_interfaces=03172_E_îæää ëðéñä àéðå éëåì ìäéåú áùéîåù òí îîù÷éí
+% The access specifiers \var{public}, \var{private}, \var{protected} and
+% \var{pusblished} can't be used in interfaces because all methods
+% of an interfaces must be public.
+parser_e_no_vars_in_interfaces=03173_E_îîù÷ àéðå éëåì ìäëéì ùãåú
+% Declarations of fields aren't allowed in interfaces. An interface
+% can contain only methods
+parser_e_no_local_proc_external=03174_E_ìà ðéúï ìäâãéø ùâøä î÷åîéú ëçéöåðéú
+% Declaring local procedures as external is not possible. Local procedures
+% get hidden parameters that will make the chance of errors very high
+parser_w_skipped_fields_before=03175_W_çì÷ îäùãåú äáàéí ìôðé "$1" ìà àåúçìå
+% In Delphi mode, not all fields of a typed constant record have to be
+% initialized, but the compiler warns you when it detects such situations.
+parser_e_skipped_fields_before=03176_E_çì÷ îäùãåú äáàéí ìôðé "$1" ìà àåúçìå
+% In all syntax modes but Delphi mode, you can't leave some fields uninitialized
+% in the middle of a typed constant record
+parser_w_skipped_fields_after=03177_W_çì÷ îäùãåú äáàéí àçøé "$1" ìà àåúçìå
+% You can leave some fields at the end of a type constant record uninitialized
+% (the compiler will initialize them to zero automatically). This may be the cause
+% of subtle problems.
+parser_e_varargs_need_cdecl_and_external=03178_E_äùéîåù áVarArgs (àå '...' áMacPas) çééá ìäéåú áùéîåù òí CDecl/CPPDecl/MWPascal å External
+% The varargs directive (or the ``...'' varargs parameter in MacPas mode) can only be used with procedures or functions
+% that are declared with \var{external} and one of \var{cdecl}, \var{cppdecl} and \var{mwpascal}. This functionality
+% is only supported to provide a compatible interface to C functions like printf.
+parser_e_self_call_by_value=03179_E_Self çééá ìäéåú ôøîèø øâéì (call-by-value)
+% You can't declare self as a const or var parameter, it must always be
+% a call-by-value parameter
+parser_e_interface_has_no_guid=03180_E_äîîù÷ "$1" àéðå îëéì îæää GUID
+% When you want to assign an interface to a constant, then the interface
+% must have a GUID value set.
+parser_e_illegal_field_or_method=03181_E_äîæää ùì ùãä àå îúåãä ùì îçì÷ä "$1" àéðí éãåòéí
+% Properties must refer to a field or method in the same class.
+parser_w_proc_overriding_calling=03182_W_òåìä òì îåñëîåú äôòìä "$1" òí "$2"
+% There are two directives in the procedure declaration that specify a calling
+% convention. Only the last directive will be used
+parser_e_no_procvarobj_const=03183_E_ðéúï ìàúçì èéôåñ ÷áåò ùì "procedure of object" ø÷ òí NIL
+% You can't assign the address of a method to a typed constant which has a
+% 'procedure of object' type, because such a constant requires two addresses:
+% that of the method (which is known at compile time) and that of the object or
+% class instance it operates on (which can not be known at compile time).
+parser_e_default_value_only_one_para=03184_E_òøê áøéøú îçãì éëåì ìäéåú áùéîåù ø÷ òí ôøîèø àçã
+% It is not possible to specify a default value for several parameters at once.
+% The following is invalid:
+% \begin{verbatim}
+% Procedure MyProcedure (A,B : Integer = 0);
+% \end{verbatim}
+% Instead, this should be declared as
+% \begin{verbatim}
+% Procedure MyProcedure (A : Integer = 0; B : Integer = 0);
+% \end{verbatim}
+parser_e_default_value_expected_for_para=03185_E_ôøîèø áøéøú îçãì ãøåù òáåø "$1"
+% The specified parameter requires a default value.
+parser_w_unsupported_feature=03186_W_ùéîåù áîàôééï ìà ðúîê !
+% You're trying to force the compiler into doing something it cannot do yet.
+parser_h_c_arrays_are_references=03187_H_îòøëéí ùì C îåòáøéí ëäôðéä
+% Any array passed to a C functions is passed
+% by a pointer (i.e. by reference).
+parser_e_C_array_of_const_must_be_last=03188_E_îòøê C ùì ÷áåò çééá ìäéåú äàøâåîðè äàçøåï
+% You can not add any other argument after an \var{array of const} for
+% \var{cdecl} functions, as the size pushed on stack for this argument is
+% not known.
+parser_h_type_redef=03189_H_äâãøä îçåãùú ùì äèéôåñ "$1"
+% This is an indicator that a previously declared type is
+% being redefined as something else. This may, or may not
+% be, a cause for errors.
+parser_w_cdecl_has_no_high=03190_W_àéï ìôåð÷öéåú cdecl ôøîèø âáåää
+% Functions declared with cdecl modifier do not pass an extra implicit parameter.
+parser_w_cdecl_no_openstring=03191_W_ôåð÷öéåú cdecel àéðï úåîëåú á open string
+% Openstring is not supported for cdecl'ared functions.
+parser_e_initialized_not_for_threadvar=03192_E_àéï àôùøåú ìàúçì îùúðä äîåâãø ëthreadvar
+% Variables declared as threadvar can not be initialized with a default value.
+% The variables will always be filled with zero at the start of a new thread.
+parser_e_msg_only_for_classes=03193_E_ðéúï ìäùúîù áäðçééú message ø÷ áúåê îçì÷ä
+% The message directive is only supported for Class types.
+parser_e_procedure_or_function_expected=03194_E_îöôä ìùéâøä àå ôåð÷öéä
+% A class method can only be specified for procedures and functions.
+parser_e_illegal_calling_convention=03195_W_îúòìí îîåñëîú ääôòìä: "$1"
+% Some calling conventions are supported only by certain CPUs. I.e. most non-i386 ports support
+% only the standard ABI calling convention of the CPU.
+parser_e_no_object_reintroduce=03196_E_ìà ðéúï ìäùúîù áREINTRODUCE áúåê àåáéé÷è
+% \var{reintroduce} is not supported for objects.
+parser_e_paraloc_only_one_para=03197_E_ëì àøâåîðè çééá ìäëéì îé÷åí òöîàé.
+% If locations for arguments are specified explicitly as it is required by
+% some syscall conventions, each argument must have it's only location, things
+% like \var{procedure p(i,j : longint 'r1');} aren't allowed
+parser_e_paraloc_all_paras=03198_E_ëì àøâåîðè çééá ìäëéì îé÷åí îåâãø
+% If one argument has an explicit argument location, all arguments of a procedure
+% must have one.
+parser_e_illegal_explicit_paraloc=03199_E_îé÷åí àøâåîðè ìà éãåò
+% The location specified for an argument isn't recognized by the compiler
+parser_e_32bitint_or_pointer_variable_expected=03200_E_îöôä ìñåâ îùúðä ùì îñôø ùìí 32-Bit àå îöáéò
+% The libbase for MorphOS/AmigaOS can be give only as \var{longint}, \var{dword} or any pointer variable.
+parser_e_goto_outside_proc=03201_E_ìà ðéúï ìäùîù ágoto áéï ùðé ùéâøåú
+% It isn't allowed to use the \var{goto} statements referencing labels outside the
+% current procedure. The following example shows the problem:
+% \begin{verbatim}
+% ...
+% procedure p1;
+% label
+% l1;
+%
+% procedure p2;
+% begin
+% goto l1; // This goto ISN'T allowed
+% end;
+%
+% begin
+% p2
+% l1:
+% end;
+% ...
+%
+% \end{verbatim}
+parser_f_too_complex_proc=03202_F_äùéâøä îñåáëú îéãé åãåøùú ùéîåù ùì àåâøéí øáéí îéãé
+% Your procedure body is too long for the compiler. You should split the
+% procedure into multiple smaller procedures.
+parser_e_illegal_expression=03203_E_áéèåé ìà çå÷é
+% This can occur under many circumstances. Mostly when trying to evaluate
+% constant expressions.
+parser_e_invalid_integer=03204_E_äáéèåé ùì äîñôø äùìí àéðå çå÷é
+% You made an expression which isn't an integer, and the compiler expects the
+% result to be an integer.
+parser_e_invalid_qualifier=03205_E_ùéîåù ìà çå÷é áîáçéï
+% One of the following is happening :
+% \begin{itemize}
+% \item You're trying to access a field of a variable that is not a record.
+% \item You're indexing a variable that is not an array.
+% \item You're dereferencing a variable that is not a pointer.
+% \end{itemize}
+parser_e_upper_lower_than_lower=03206_E_èååç ääâáìä äâáåää ÷èï îèååç ääâáìä äðîåëä
+% You are declaring a subrange, and the lower limit is higher than the high
+% limit of the range.
+parser_e_macpas_exit_wrong_param=03207_E_äôøîèø ùì Exit çééá ìäéåú ùí äùéâøä úçúéå äåà ðîöà
+% Non local exit is not allowed. This error occurs only in mode MacPas.
+parser_e_illegal_assignment_to_count_var=03208_E_äöáä ìà çå÷éú ùì äîùúðä áìåìàú ä for "$1"
+% The type of a \var{for} loop variable must be an ordinal type.
+% Loop variables cannot be reals or strings. You can also not assign values to
+% loop variables inside the loop (except in Delphi and TP modes). Use a while or
+% repeat loop instead if you need to do something like that, since those
+% constructs were built for that.
+parser_e_no_local_var_external=03209_E_ìà ðéúï ìäâãéø îùúðéí î÷åîééí ëçéöåðééí
+% Declaring local variables as external is not allowed. Only global variables can reference
+% to external variables.
+parser_e_proc_already_external=03210_E_äùéâøä ëáø îåâãøú ëçéöåðéú
+% The procedure is already declared with the EXTERNAL directive in an interface or
+% forward declaration.
+parser_w_implicit_uses_of_variants_unit=03211_W_ùéîåù îùúîò áéçéãú Variants
+% The Variant type is used in the unit without any used unit using the Variants unit. The
+% compiler has implicitly added the Variants unit to the uses list. To remove this warning
+% the Variants unit needs to be added to the uses statement.
+parser_e_no_static_method_in_interfaces=03212_E_äùéîåù áîçì÷ä åîúåãåú ñèèééí àéðí éëåìéåú ìäéåú áùéîåù áîîù÷
+% The specifier \var{class} and directive \var{static} can't be used in interfaces
+% because all methods of an interfaces must be public.
+parser_e_arithmetic_operation_overflow=03213_E_âìéùä áôòåìä îúîèéú
+% An operation on two integers values produced an overflow
+parser_e_protected_or_private_expected=03214_E_îöôä ìàéæåø Protected àå Private
+% \var{strict} can be only used together with \var{protected} or \var{private}.
+parser_e_illegal_slice=03215_E_SLICE àéð éëåì ìäéåú áùéîåù îçåõ ìøùéîú ôøîèøéí
+% \var{slice} can be used only for arguments accepting an open array parameter
+parser_e_dispinterface_cant_have_parent=03216_E_îçì÷ú DISPINTERFACE àéðä éëåìä ìäëéì äåøä
+% A DISPINMTERFACE is a special type of interface which can't have a parent class
+parser_e_dispinterface_needs_a_guid=03217_E_DISPINTERFACE çééá GUID
+% A DISPINMTERFACE always needs an interface identification
+parser_w_overridden_methods_not_same_ret=03218_W_äîúåãåú äçãùåú çééáåú ìäçæéø àú àåúå èéôåñ ðúåðéí. ä÷åã äðåëçé éëåì ìâøåí ì÷øéñä áò÷áåú áàâ ùì äîôøù ùì ãìôé (“$2” òåìä òì “$1” àùø îëéì èéôåñ ðúåðéí àçø áäçæøä)
+% If you declare overridden methods in a class definition, they must
+% have the same return type. Some versions of Delphi allow you to change the
+% return type of interface methods, and even to change procedures into
+% functions, but the resulting code may crash depending on the types used
+% and the way the methods are called.
+parser_e_dispid_must_be_ord_const=03219_E_îæää Dispatch çééá ìäéåú ÷áåò áòì òøê ñéãåøé
+parser_e_array_range_out_of_bounds=03220_E_äèååç ùì äîòøê âáåää îéãé
+% Regardless of the size taken up by its elements, an array cannot have more
+% than high(ptrint) elements. Additionally, the range type must be a subrange
+% of ptrint.
+parser_e_packed_element_no_var_addr=03221_E_ìà ðéúï ìîöåà àú äëúåáú ùì áéè äîòøê àøåæ, àìîðèéí àå ùãåú ùì äîòøê
+% If you declare an array or record as \var{packed} in Mac Pascal mode (or as \var{packed} in any mode with \var{\{\$bitpacking on\}}), it will
+% be packed at the bit level. This means it becomes impossible to take addresses
+% of individual array elements or record fields. The only exception to this rule is in case of packed arrays elements
+% whose packed size is a multple of 8 bits.
+parser_e_packed_dynamic_open_array=03222_E_ìà ðéúï ìàøåæ îòøê ãéðàîé
+% Only regular (and possibly in the future also open) arrays can be packed
+parser_e_packed_element_no_loop=03223_E_àìîðèéí åùãåú ùì îòøëé áéè àøåæéí àéðí éëåìéí ìùîù ëîùúðéí ììåìàåú
+% If you declare an array or record as \var{packed} in Mac Pascal mode (or as \var{packed} in any mode with \var{\{\$bitpacking on\}}), it will
+% be packed at the bit level. For performance reasons, they cannot be
+% used as loop variables.
+parser_e_type_and_var_only_in_generics=03224_E_ðéúï ìäùúîù á VAR å TYPE ø÷ òí generics
+% The usage of VAR and TYPE to declare new types inside an object is allowed only inside
+% generics.
+parser_e_cant_create_generics_of_this_type=03225_E_äèéôåñ àéðå éëåì ìäéåú generic
+% Only Classes, Objects, Interfaces and Records are allowed to be used as generic
+parser_w_no_lineinfo_use_switch=03226_W_àéï ìèòåï àú äñôøééä LINEINFO áöåøä éãðéú. òì îðú ìäùúîù áñôøééä éù ìäùúîù áîúâ -gl áî÷åí
+% Do not use the LINEINFO unit directly, Use the \var{-gl} switch which automatically adds the
+% unit for reading the selected type of debugging information instead.
+parser_e_no_funcret_specified=03227_E_ìà öåééï èéôåñ äçæøä òáåø äôåð÷öéä "$1"
+% The first time you declare a function you have to declare it completely,
+% including all parameters and the result type.
+parser_e_special_onlygenerics=03228_E_äùéîåù áSpecialization îåøùä ø÷ ëàùø îùúîùéí áèéôåñé generic
+% Types not being generics can't be specialized
+parser_e_no_generics_as_params=03229_E_ìà ðéúï ìäùúîù ágenerics áúåø ôøîèøéí ëàùø éù ùéîåù á spezializing generics
+% When specializing a generic, only non-generic types can be used as parameters.
+parser_e_type_object_constants=03230_E_äùéîåù á÷áåòéí ùì àåáéé÷èéí äîëéìéí VMT àéðå îåøùä
+% If an object requires a VMT either because it contains a constructor or virtual methods,
+% it's not allowed to create constants of it. In TP and Delphi mode this is allowed
+% for compatibility reasons.
+parser_e_label_outside_proc=03231_E_ùéîåù áëúåáú ùì úååéåú äîåëøæåú îçåõ ìîúçí äðåëçé àéðå îåøùä
+% It isn't allowed to take the addresss of labels outside the
+% current procedure.
+parser_e_initialized_not_for_external=03233_E_ìà ðéúï ìàúçì òøê áøéøú îçãì ìîùúðéí äîåâãøéí ëexternal
+% Variables declared as external can not be initialized with a default value.
+parser_e_illegal_function_result=03234_E_èéôåñ äçæøä ùì äôåð÷öéä àéðå çå÷é
+% Some types like file types can not be used as function result
+parser_e_no_common_type=03235_E_àéï èéôåñ îùåúó ì "$1" å "$2"
+% To perform an operation beween integers, the compiler converts both operands
+% to their common type, which appears to be an invalid type. To determine the
+% common type of the operands, the compiler takes the minimum of the minimal values
+% of both types, and the maximum of the maximal values of both types. The common
+% type is then minimum..maximum.
+parser_e_no_generics_as_types=03236_E_Generics ììà specialization àéðå éëåì ìäéåú áùéîåù áúåø èéôåñ ìîùúðä
+% Generics must be always specialized before being used as variable type
+parser_w_register_list_ignored=03237_W_îúòìí îøùéîú äàåâøéí òáåø ùâøåú assemblter èäåøåú
+% When using pure assembler routines, the list with modified registers is ignored.
+
+% \end{description}
+#
+# Type Checking
+#
+# 04049 is the last used one
+#
+% \section{Type checking errors}
+% This section lists all errors that can occur when type checking is
+% performed.
+% \begin{description}
+type_e_mismatch=04000_E_èéôåñ ðúåðéí ìà çåôó
+% This can happen in many cases:
+% \begin{itemize}
+% \item The variable you're assigning to is of a different type than the
+% expression in the assignment.
+% \item You are calling a function or procedure with parameters that are
+% incompatible with the parameters in the function or procedure definition.
+% \end{itemize}
+type_e_incompatible_types=04001_E_èéôåñ ðúåðéí ìà úåàí: ðòùä ùéîåù á "$1" îöôä ì"$2"
+% There is no conversion possible between the two types
+% Another possiblity is that they are declared in different
+% declarations:
+% \begin{verbatim}
+% Var
+% A1 : Array[1..10] Of Integer;
+% A2 : Array[1..10] Of Integer;
+%
+% Begin
+% A1:=A2; { This statement gives also this error, it
+% is due the strict type checking of pascal }
+% End.
+% \end{verbatim}
+type_e_not_equal_types=04002_E_àé äúàîä áéï èéôåñé äðúåðéí "$1" å "$2"
+% The types are not equal
+type_e_type_id_expected=04003_E_îöôä ìèéôåñ ðúåðéí
+% The identifier is not a type, or you forgot to supply a type identifier.
+type_e_variable_id_expected=04004_E_îöôä ìîæää ùì îùúðä
+% This happens when you pass a constant to a routine (such as \var{Inc} var or \var{Dec})
+% when it expects a variable. You can only pass variables as arguments to these functions.
+type_e_integer_expr_expected=04005_E_îöôä ìîñôø ùìí, àê äú÷áì "$1"
+% The compiler expects an expression of type integer, but gets a different
+% type.
+type_e_boolean_expr_expected=04006_E_îöôä ìáéèåé áåìéàðé, àê äú÷áì "$1"
+% The expression must be a boolean type, it should be return true or
+% false.
+type_e_ordinal_expr_expected=04007_E_îöôä ìèéôåñ ñåãø
+% The expression must be of ordinal type, i.e., maximum a \var{Longint}.
+% This happens, for instance, when you specify a second argument
+% to \var{Inc} or \var{Dec} that doesn't evaluate to an ordinal value.
+type_e_pointer_type_expected=04008_E_îöôä ìîöáéò, àê äú÷áì "$1"
+% The variable or expression isn't of the type \var{pointer}. This
+% happens when you pass a variable that isn't a pointer to \var{New}
+% or \var{Dispose}.
+type_e_class_type_expected=04009_E_îöôä ìîçì÷ä, àê äú÷áì "$1"
+% The variable of expression isn't of the type \var{class}. This happens
+% typically when
+% \begin{enumerate}
+% \item The parent class in a class declaration isn't a class.
+% \item An exception handler (\var{On}) contains a type identifier that
+% isn't a class.
+% \end{enumerate}
+type_e_cant_eval_constant_expr=04011_E_ìà ðéúï ìðúç àú äáéèåé ä÷áåò
+% This error can occur when the bounds of an array you declared does
+% not evaluate to ordinal constants
+type_e_set_element_are_not_comp=04012_E_äàìîðèéí ùì ä÷áåöä àéðí úåàîéí
+% You are trying to make an operation on two sets, when the set element types
+% are not the same. The base type of a set must be the same when taking the
+% union
+type_e_set_operation_unknown=04013_E_äôòåìä àéðä áùéîåù òí ÷áåöåú
+% several binary operations are not defined for sets
+% like div mod ** (also >= <= for now)
+type_w_convert_real_2_comp=04014_W_äîøä àåèåîèéú ùì èéôåñ òùøåðé ì COMP àùø äåà îñôø ùìí
+% An implicit type conversion from a real type to a \var{comp} is
+% encountered. Since \var{comp} is a 64 bit integer type, this may indicate
+% an error.
+type_h_use_div_for_int=04015_H_äùúîù áDIV áî÷åí òì îðú ì÷áì úåöàä ùì îñôø ùìí
+% When hints are on, then an integer division with the '/' operator will
+% procuce this message, because the result will then be of type real
+type_e_strict_var_string_violation=04016_E_èéôåñ äîçøåæú àéðí úåàí áâìì äùéîåù áîúâ $V+
+% When compiling in \var{\{\$V+\}} mode, the string you pass as a parameter
+% should be of the exact same type as the declared parameter of the procedure.
+type_e_succ_and_pred_enums_with_assign_not_possible=04017_E_ìà ðéúï ìäöéá òøëéí ìîðéåú úåê ùéîåù ásucc àå pred
+% When you declared an enumeration type which has assignments in it, as in C,
+% like in the following:
+% \begin{verbatim}
+% Tenum = (a,b,e:=5);
+% \end{verbatim}
+% you cannot use the \var{Succ} or \var{Pred} functions on them.
+type_e_cant_read_write_type=04018_E_ìà ðéúï ì÷øåà àå ìëúåá îùúðéí îäñåâ äðåëçé
+% You are trying to \var{read} or \var{write} a variable from or to a
+% file of type text, which doesn't support that. Only integer types,
+% reals, pchars and strings can be read from/written to a text file.
+% Booleans can only be written to text files.
+type_e_no_readln_writeln_for_typed_file=04019_E_ìà ðéúï ìäùúîù áreadln åwriteln òì èéôåñ ðúåðéí îñåâ file
+% \var{readln} and \var{writeln} are only allowed for text files.
+type_e_no_read_write_for_untyped_file=04020_E_ìà ðéúï ì÷øåà àå ìëúåá èéôåñ ìà îåâø ùì ÷áöéí
+% \var{read} and \var{write} are only allowed for text or typed files.
+type_e_typeconflict_in_set=04021_E_äúðâùåú ùì èéôåñ ðúåðéí áúåê àéáøéí ùì ÷áåöä
+% There is at least one set element which is of the wrong type, i.e. not of
+% the set type.
+type_w_maybe_wrong_hi_lo=04022_W_lo/hi(dword/qword) îçæéø àú äòøê äòìéåï/úçúåï ùì word/dword
+% \fpc supports an overloaded version of \var{lo/hi} for \var{longint/dword/int64/qword}
+% which returns the lower/upper word/dword of the argument. TP always uses
+% a 16 bit \var{lo/hi} which returns always bits 0..7 for \var{lo} and the
+% bits 8..15 for \var{hi}. If you want the TP behavior you have
+% to type cast the argument to \var{word/integer}
+type_e_integer_or_real_expr_expected=04023_E_îöôä ìáéèåé ùì îñôø ùìí àå îñôø îîùé
+% The first argument to \var{str} must a real or integer type.
+type_e_wrong_type_in_array_constructor=04024_E_ùéîåù ùâåé áèéôåñ "$1" áúåê éåöø äîòøê
+% You are trying to use a type in an array constructor which is not
+% allowed.
+type_e_wrong_parameter_type=04025_E_èéôåñ ìà îúàéí ìàøâåîðè îñôø $1: äú÷áì "$2", îöôä ì"$3"
+% You are trying to pass an invalid type for the specified parameter.
+type_e_no_method_and_procedure_not_compatible=04026_E_äîùúðä ùì äîúåãä åäùâøä àéðí úåàîéí
+% You can't assign a method to a procedure variable or a procedure to a
+% method pointer.
+type_e_wrong_math_argument=04027_E_áéèåé ÷áåò ìà çå÷é äåæï ìôåð÷öéä îúîèéú ôðéîéú
+% The constant argument passed to a ln or sqrt function is out of
+% the definition range of these functions.
+type_e_no_addr_of_constant=04028_E_ìà ðéúï ì÷áì àú äëúåáú ùì ä÷áåò
+% It is not possible to get the address of a constant expression, because they
+% aren't stored in memory. You can try making it a typed constant. This error
+% can also be displayed if you try to pass a property to a var parameter.
+type_e_argument_cant_be_assigned=04029_E_ìà ðéúï ìäùéí àú äàøâåîðè
+% Only expressions which can be on the left side of an
+% assignment can be passed as call by reference argument
+% Remark: Properties can be only
+% used on the left side of an assignment, but they cannot be used as arguments
+type_e_cannot_local_proc_to_procvar=04030_E_ìà ðéúï ìùééê ôåð÷öéä/ùéâøä î÷åîéú ìîùúðä îñåâ ùéâøä
+% It's not allowed to assign a local procedure/function to a
+% procedure variable, because the calling of local procedure/function is
+% different. You can only assign local procedure/function to a void pointer.
+type_e_no_assign_to_addr=04031_E_ìà ðéúï ìùééê òøê ìëúåáú
+% It is not allowed to assign a value to an address of a variable,constant,
+% procedure or function. You can try compiling with -So if the identifier
+% is a procedure variable.
+type_e_no_assign_to_const=04032_E_ìà ðéúï ìùééê òøê ìîùúðä ÷áåò
+% It's not allowed to assign a value to a variable which is declared
+% as a const. This is normally a parameter declared as const, to allow
+% changing the value make the parameter as a value parameter or a var.
+type_e_array_required=04033_E_ðãøù îùúðä îñåâ îòøê
+% If you are accessing a variable using an index '[<x>]' then
+% the type must be an array. In FPC mode also a pointer is allowed.
+type_e_interface_type_expected=04034_E_îöôä ìèéôåñ îñåâ îîù÷, àáì äú÷áì "$1"
+% The compiler expected to encounter an interface type name, but got something else.
+% The following code would provoke this error:
+% \begin{verbatim}
+% Type
+% TMyStream = Class(TStream,Integer)
+% \end{verbatim}
+type_w_mixed_signed_unsigned=04035_W_òéøáåá áéèåéé ñéîðéí ålongwords îñô÷éí úåöàä ùì 64bit
+% If you divide (or calculate the modulus of) a signed expression by a longword (or vice versa),
+% or if you have overflow and/or range checking turned on and use an arithmetic
+% expression (+, -, *, div, mod) in which both signed numbers and longwords appear,
+% then everything has to be evaluated in 64bit which is slower than normal
+% 32bit arithmetic. You can avoid this by typecasting one operand so it
+% matches the result type of the other one.
+type_w_mixed_signed_unsigned2=04036_W_òøáåá áéèåéé ñéîðéí åîñôøéí ùìîéí âáåäéí òìåì ìâøåí ìùâéàú èååç îñôøéí
+% If you use a binary operator (and, or, xor) and one of
+% the operands is a longword while the other one is a signed expression, then,
+% if range checking is turned on, you may get a range check error because in
+% such a case both operands are converted to longword before the operation is
+% carried out. You can avoid this by typecasting one operand so it
+% matches the result type of the other one.
+type_e_typecast_wrong_size_for_assignment=04037_E_éùðå äáãì áâåãì áäöáä ùì typecast ($1-> $2)
+% Type casting to a type with a different size is not allowed when the variable is
+% used for assigning.
+type_e_array_index_enums_with_assign_not_possible=04038_E_îðéåú òí úåëï ùì äöáä àéðí éëåìéí ìùîù áúåø àéðã÷ñ ìîòøê
+% When you declared an enumeration type which has assignments in it, as in C,
+% like in the following:
+% \begin{verbatim}
+% Tenum = (a,b,e:=5);
+% \end{verbatim}
+% you cannot use it as index of an array.
+type_e_classes_not_related=04039_E_àéï ÷éøáä áéï èéôåñé îçì÷åú àå àåáéé÷èéí ùì "$1" å "$2"
+% There is a typecast from one class or object to another while the class/object
+% are not related. This will probably lead to errors
+type_w_classes_not_related=04040_W_àéï ÷éøáä áéï èéôåñé äîçì÷åú ùì "$1" å "$2"
+% There is a typecast from one class or object to another while the class/object
+% are not related. This will probably lead to errors
+type_e_class_or_interface_type_expected=04041_E_îöôä ìèéôåñé îçì÷åú àå îîù÷éí, àáì "$1" äú÷áì
+% The compiler expected a class or interface name, but got another type or identifier.
+type_e_type_is_not_completly_defined=04042_E_äèéôåñ "$1" ìà äåâãø áîìåàå
+% This error occurs when a type is not complete: i.e. a pointer type which points to
+% an undefined type.
+type_w_string_too_long=04043_W_äúåëï ùì äîçøåæú îëéì éåúø úååéí îîä ùðéúï ìäëéì áàåøê ùì îçøåæú ÷öøä
+% The size of the constant string, which is assigned to a shortstring,
+% is longer than the maximum size of the shortstring
+type_w_signed_unsigned_always_false=04044_W_ääùååàä úîéã úçæéø òøê ùì false áâìì èååç äòøëéí
+% There is a comparison between an unsigned value and a signed constant which is
+% less than zero. Because of type promotion, the statement will always evaluate to
+% false. Exlicitly typecast the constant to the correct range to avoid this problem.
+type_w_signed_unsigned_always_true=04045_W_ääùååàä úîéã úçæéø òøê ùì true áâìì èååç äòøëéí
+% There is a comparison between an unsigned value and a signed constant which is
+% less than zero. Because of type promotion, the statement will always evaluate to
+% true. Exlicitly typecast the constant to the correct range to avoid this problem.
+type_w_instance_with_abstract=04046_W_îàúçì àú äîçì÷ä "$1" òí îúåãåú ìà îîåîùåú
+% An instance of a class is created which contains non-implemented abstract
+% methods. This will probably lead to a runtime error 211 in the code if that
+% routine is ever called. All abstract methods should be overridden.
+type_h_in_range_check=04047_H_äòøê äùîàìé ùì äàåôøðã IN öøéê ìäéåú áâåãì ùì áéú
+% The left operand of the \var{in} operator is not an ordinal or enumeration which fits
+% within 8-bits, this may lead to range check errors. The \var{in} operator
+% currently only supports a left operand which fits within a byte. In the case of
+% enumerations, the size of an element of an enumeration can be controlled with
+% the \var{\{\$PACKENUM\}} or \var{\{\$Zn\}} switches.
+type_w_smaller_possible_range_check=04048_W_âåãì äèéôåñ àéðå îúàéí, éùðä àôùøåú ìàéáåã îéãò àå ùâéàä ááãé÷ú äèååç
+% There is an assignment to a smaller type than the source type. This means that
+% this may cause a range-check error, or may lead to possible loss of data.
+type_h_smaller_possible_range_check=04049_H_âåãì äèéôåñ àéðå îúàéí, éùðä àôùøåú ìàéáåã îéãò àå ùâéàä ááãé÷ú äèååç
+% There is an assignment to a smaller type than the source type. This means that
+% this may cause a range-check error, or may lead to possible loss of data.
+type_e_cant_take_address_of_abstract_method=04050_E_ìà ðéúï ìñô÷ àú ëúåáú äîúåãä äîåâãøú ë abstract
+% An abstract method has no body, so the address of an abstract method can't be taken.
+type_e_assignment_not_allowed=04051_E_ìà ðéúï ìùééê àú äòøê ìôøîèøéí øùîééí åîòøëéí ôúåçéí
+% You are trying to assign a value to a formal (untyped var, const or out)
+% parameter, or to an open array.
+type_e_constant_expr_expected=04052_E_îöôä ìáéèåé ÷áåò
+% The compiler expects an constant expression, but gets a variable expression.
+type_e_operator_not_supported_for_types=04053_E_äôòåìä "$1" àéðä ðúîëú ìèéôåñéí "$1" å "$3"
+% The operation is not allowed for the supplied types
+type_e_illegal_type_conversion=04054_E_äîøä ìà çå÷éú ùì äèéôåñ ùì "$1" ì "$2"
+% When doing a type-cast, you must take care that the sizes of the variable and
+% the destination type are the same.
+type_h_pointer_to_longint_conv_not_portable=04055_H_ääîøä áéï îñôø ìîöáéò àéðä àôùøéú áëì äîòøëåú
+% If you typecast a pointer to a longint (or vice-versa), this code will not compile
+% on a machine using 64-bit for pointer storage.
+type_w_pointer_to_longint_conv_not_portable=04056_W_ääîøä áéï îñôø ìîöáéò àéðä àôùøéú áëì äîòøëåú
+% If you typecast a pointer to a ordinal type of a different size (or vice-versa), this can
+% cause problems. This is a warning to help finding the 32bit specific code where cardinal/longint is used
+% to typecast pointers to ordinals. A solution is to use the ptrint/ptruint types instead.
+type_e_cant_choose_overload_function=04057_E_ìà ðéúï ìäçìéè áàéæå ôåð÷öéú òîåñú éúø ìäùúîù
+% You're calling overloaded functions with a parameter that doesn't correspond
+% to any of the declared function parameter lists. e.g. when you have declared
+% a function with parameters \var{word} and \var{longint}, and then you call
+% it with a parameter which is of type \var{integer}.
+type_e_illegal_count_var=04058_E_îùúðä ñôéøä ìà çå÷é
+% The type of a \var{for} loop variable must be an ordinal type.
+% Loop variables cannot be reals or strings.
+type_w_double_c_varargs=04059_W_îîéø àú äèéôåñ real ìèéôåñ double ìîùúðä C. äåñó typecast ñôöéôé ìîðåò àú äîöá.
+% In C, constant real values are double by default. For this reason, if you
+% pass a constant real value to a variable argument part of a C function, FPC
+% by default converts this constant to double as well. If you want to prevent
+% this from happening, add an explicit typecast around the constant.
+type_e_class_or_cominterface_type_expected=04060_E_îöôä ìèéôåñ îçì÷ä àå îîù÷ COM, àáì äú÷áì "$1"
+% Some operators like the AS operator are only appliable to classes or COM interfaces.
+type_e_no_const_packed_array=04061_E_àéï úîéëä áîòøê ÷áåò ãçåñ
+% You cannot declare a (bit)packed array as a typed constant.
+type_e_got_expected_packed_array=04062_E_çåñø úàéîåú ìèéôåñ äðúåðéí ùì àøâåîðè $1. äú÷áì: "$2" îöà ì "(bit)packed array"
+% The compiler expects a (bit)packed array as the specified parameter
+type_e_got_expected_unpacked_array=04063_E_çåñø úàéîåú èéôåñ äðúåðéí ùì àøâåîðè $1. äú÷áì "$2" îöôä ì "(not packed) Array"
+% The compiler expects a regular (i.e., not packed) array as the specified parameter
+type_e_no_packed_inittable=04064_E_àìîèéí ùì îòøê ãçåñ àéðí éëåìéí ìäéåú îèéôåñ ðúåðéí àùø ãåøù àúçåì
+% Support for packed arrays of types that need initialization (such as ansistrings, or records which contain ansistrings) is not yet implemented.
+type_e_no_const_packed_record=04065_E_àéï úîéëä ìøùåîåú åàáéé÷èéí ÷áåòéí åãçåñéí
+% You cannot declare a (bit)packed array as a typed constant at this time.
+type_w_untyped_arithmetic_unportable=04066_W_çéùåá "$1" òì èéôåñ ìà îåâãø ùì îöáéò àéðå ðúîê áîöá {$T+}, àê ðéúï ìäùúîù átypecast
+% Addition/subtraction from untyped pointer may work differently in \var{\{\$T+\}}, use typecast to typed pointer
+type_e_cant_take_address_of_local_subroutine=04076_E_ìà ðéúï ì÷çú àú ëúåáú äùéâøä äîñåîðú ëî÷åîéú
+% The address of a subroutine marked as local can't be taken.
+type_e_cant_export_local=04077_E_ìà ðéúï ìééöà ùéâøä äîñåîðú ëî÷åîéú áúåê éçéãä
+% A subroutine marked as local can't be export from a unit.
+type_e_not_automatable=04078_E_äèéôåñ àéðå àåèåîè: "$1"
+% Only byte, integer, longint, smallint, currency, single, double, ansistring,
+% widestring, tdatetime, variant, olevariant, wordbool and all interfaces are automatable.
+type_h_convert_add_operands_to_prevent_overflow=04079_H_äîøú äàåôøðã ì"$1" ìôðé ôòåìú äçéáåø, éëåì ìîðåò ùâéàåú âìéùä.
+% Adding two types can cause overflow errors. Since you are converting the result to a larger type, you
+% could prevent such errors by converting the operands to this type before doing the addition.
+type_h_convert_sub_operands_to_prevent_overflow=04080_H_äîøú äàåôøðã ì"$1" ìôðé ôòåìú äçéáåø éëåìä ìîðåò ùâéàåú âìéùä.
+% Subtracting two types can cause overflow errors. Since you are converting the result to a larger type, you
+% could prevent such errors by converting the operands to this type before doing the subtraction.
+type_h_convert_mul_operands_to_prevent_overflow=04081_H_äîøú äàåôøðã "$1" ìôðé ôòåìú äëôì éëåìä ìîðåò ùâéàåú âìéùä.
+% Multiplying two types can cause overflow errors. Since you are converting the result to a larger type, you
+% could prevent such errors by converting the operands to this type before doing the multiplication.
+type_w_pointer_to_signed=04082_W_äîøú îöáéòéí ìîñôøéí ùìîéí òí ñéîï òìåìä ìâøåí ìùâéàåú áúåöàåú äùååàä åáèååçéí. éù ìäùúîù áî÷åí æàú áèéôåñ ììà ñéîï.
+% The virtual address space on 32-bit machines runs from \$00000000 to \$ffffffff. Many operating systems allow you to
+% allocate memory above \$80000000, for example both Windows and Linux allow pointers in the range \$0000000 to \$bfffffff.
+% If you convert pointers to signed types, this can cause overflow and range check errors, but also \$80000000 < \$7fffffff.
+% This can cause random errors in code like "if p>q".
+% \end{description}
+#
+# Symtable
+#
+# 05060 is the last used one
+#
+% \section{Symbol handling}
+% This section lists all the messages that concern the handling of symbols.
+% This means all things that have to do with procedure and variable names.
+% \begin{description}
+sym_e_id_not_found=05000_E_äîæää ìà ðîöà "$1"
+% The compiler doesn't know this symbol. Usually happens when you misspel
+% the name of a variable or procedure, or when you forgot to declare a
+% variable.
+sym_f_internal_error_in_symtablestack=05001_F_ùâéàä ôðéîéú áSymTableStack()
+% An internal error occurred in the compiler; If you encounter such an error,
+% please contact the developers and try to provide an exact description of
+% the circumstances in which the error occurs.
+sym_e_duplicate_id=05002_E_îæää ëôåì "$1"
+% The identifier was already declared in the current scope.
+sym_h_duplicate_id_where=05003_H_äîæää ëáø îåâãø á$1 áùåøä $2
+% The identifier was already declared in a previous scope.
+sym_e_unknown_id=05004_E_îæää ìà îåëø "$1"
+% The identifier encountered has not been declared, or is used outside the
+% scope where it is defined.
+sym_e_forward_not_resolved=05005_E_äâãøú Forward ìà îîåîùú
+% This can happen in two cases:
+% \begin{itemize}
+% \item This happens when you declare a function (in the \var{interface} part, or
+% with a \var{forward} directive, but do not implement it.
+% \item You reference a type which isn't declared in the current \var{type}
+% block.
+% \end{itemize}
+sym_e_error_in_type_def=05007_E_ùâéàä áäâãøú èéôåñ
+% There is an error in your definition of a new array type:
+% \item One of the range delimiters in an array declaration is erroneous.
+% For example, \var{Array [1..1.25]} will trigger this error.
+sym_e_forward_type_not_resolved=05009_E_äâãøú äèéôåñ ìà äåùìä "$1"
+% A symbol was forward defined, but no declaration was encountered.
+sym_e_only_static_in_static=05010_E_ø÷ îùúðéí ñèèééí éëåìéí ìäéåú áùéîåù òí îúåãåú ñèèéåú àå îçåõ ìîèåãåú
+% A static method of an object can only access static variables.
+sym_f_type_must_be_rec_or_class=05012_F_îöôä ìèéôåñ ùì øùåîä àå èéôåñ ùì îçì÷ä
+% The variable or expression isn't of the type \var{record} or \var{class}.
+sym_e_no_instance_of_abstract_object=05013_E_àãâí ùì îçì÷åú àå àåáéé÷èéí òí îúåãåú abstract àéðí îåøùéí
+% You are trying to generate an instance of a class which has an abstract
+% method that wasn't overridden.
+sym_w_label_not_defined=05014_W_äúååéú "$1" àéðä îåâãøú
+% A label was declared, but not defined.
+sym_e_label_used_and_not_defined=05015_E_äúååéú "$1" áùéîåù, àáì ìà îâãøú
+% A label was declared and used, but not defined.
+sym_e_ill_label_decl=05016_E_äâãøú úååéú ìà çå÷éú
+% This error should never happen; it occurs if a label is defined outside a
+% procedure or function.
+sym_e_goto_and_label_not_supported=05017_E_GOTO å LABEL àéðí ðúîëéí (äùúîù áîúâ -Sg)
+% You must compile a program which has \var{label}s and \var{goto} statements
+% with the \var{-Sg} switch. By default, \var{label} and \var{goto} aren't
+% supported.
+sym_e_label_not_found=05018_E_äúååéú ìà ðîöàä
+% A \var{goto label} was encountered, but the label isn't declared.
+sym_e_id_is_no_label_id=05019_E_äîæää àéðå úååéú
+% The identifier specified after the \var{goto} isn't of type label.
+sym_e_label_already_defined=05020_E_äúååéú ëáø äåâãøä
+% You are defining a label twice. You can define a label only once.
+sym_e_ill_type_decl_set=05021_E_äâãøú èéôåñ ñéãøä ìà çå÷éú
+% The declaration of a set contains an invalid type definition.
+sym_e_class_forward_not_resolved=05022_E_äâãøä î÷ãéîä ùì îçì÷ä "$1" ìà îîåîùú
+% You declared a class, but you did not implement it.
+sym_n_unit_not_used=05023_H_äéçéãä "$1" àéðä áùéîåù á $2
+% The unit referenced in the \var{uses} clause is not used.
+sym_h_para_identifier_not_used=05024_H_äôøîèø "$1" àéðå áùéîåù
+% The identifier was declared (locally or globally) but
+% was not used (locally or globally).
+sym_n_local_identifier_not_used=05025_N_äîùúðä äî÷åîé "$1" àéðå áùéîåù
+% You have declared, but not used a variable in a procedure or function
+% implementation.
+sym_h_para_identifier_only_set=05026_H_äòøê ùì äôøîèø "$1" äåæï àê äåà ìà áùéîåù
+% The identifier was declared (locally or globally)
+% set but not used (locally or globally).
+sym_n_local_identifier_only_set=05027_N_äòøê ùì äôøîèø "$1" äåæï àê äåà ìà áùéîåù
+% The variable in a procedure or function
+% implementation is declared, set but never used.
+sym_h_local_symbol_not_used=05028_H_$1 "$2" î÷åîé ìà áùéîåù
+% A local symbol is never used.
+sym_n_private_identifier_not_used=05029_N_ùãä ôøèé "$1.$2" ìà áùéîåù
+% The indicated private field is defined, but is never used in the code.
+sym_n_private_identifier_only_set=05030_N_äùãä äôøèé "$1.$2" áòì òøê, àê ìà áùéîåù
+% The indicated private field is declared, assigned but never read.
+sym_n_private_method_not_used=05031_N_äîúåãä äôøèéú "$1.$2" àéðä áùéîåù
+% The indicated private method is declared but is never used in the code.
+sym_e_set_expected=05032_E_îöôä ìèéôåñ ñãøä
+% The variable or expression is not of type \var{set}. This happens in an
+% \var{in} statement.
+sym_w_function_result_not_set=05033_W_äôåð÷öéä ëðøàä ìà îçæéøä òøê
+% You can get this warning if the compiler thinks that a function return
+% value is not set. This will not be displayed for assembler procedures,
+% or procedures that contain assembler blocks.
+sym_w_wrong_C_pack=05034_W_äèéôåñ "$1" àéðå îééåùø ðëåï ìøùåîä ùì ùôú C
+% Arrays with sizes not multiples of 4 will be wrongly aligned
+% for C structures.
+sym_e_illegal_field=05035_E_ùãä ùì øùåîä ìà çå÷é "$1"
+% The field doesn't exist in the record/object definition.
+sym_w_uninitialized_local_variable=05036_W_äîùúðä äî÷åîé "$1" àéðå ðøàä îàåúçì
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_w_uninitialized_variable=05037_W_äîùúðä "$1" àéðå ðøàä îàåúçì
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_e_id_no_member=05038_E_äîæää áùéîåù àéðå çáø á"$1"
+% This error is generated when an identifier of a record,
+% field, or method is accessed while it is not defined.
+sym_h_param_list=05039_H_ðîöàä ääëøæä: $1
+% You get this when you use the \var{-vh} switch. In case an overloaded
+% procedure is not found, then all candidate overloaded procedures are
+% listed, with their parameter lists.
+sym_e_segment_too_large=05040_E_âåãì äîéãò ùì äàìîðè âãåì îéãé
+% You get this when you declare a data element whose size exceeds the
+% prescribed limit (2 Gb on 80386+/68020+ processors)
+sym_e_no_matching_implementation_found=05042_E_ìà ðîöà áéöåò ìîúåãä "$1" ùì äîîù÷
+% There was no matching method found which could implement the interface
+% method. Check argument types and result type of the methods.
+sym_w_deprecated_symbol=05043_W_äñéîåì "$1" îéåùï
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{deprecated} is used. Deprecated symbols may no longer
+% be available in newer versions of the unit / library. Usage of this symbol
+% should be avoided as much as possible.
+sym_w_non_portable_symbol=05044_W_äñéîåì "$1" àéðå ðééã
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{platform} is used. This symbol's value, usage
+% and availability is platform specific and should not be used
+% if the source code must be portable.
+sym_w_non_implemented_symbol=05055_W_äñéîåì "$1" àéðå îáåöò
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{unimplemented} is used. This symbol is defined,
+% but is not yet implemented on this specific platform.
+sym_e_cant_create_unique_type=05056_E_ìà ðéúï ìéöåø èéôåñ ééçåãé îäèéôåñ äðåëçé
+% Only simple types like ordinal, float and string types are supported when
+% redefining a type with \var{type newtype = type oldtype;}.
+sym_h_uninitialized_local_variable=05057_H_äîùúðä äî÷åîé "$1" àéðå ðøàä îàåúçì
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_h_uninitialized_variable=05058_H_äîùúðä "$1" àéðå ðøàä îàåúçì
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_w_function_result_uninitialized=05059_W_äòøê äîåçæø îäôåð÷öéä àéðå ðøàä ëîàåúçì
+% This message is displayed if the compiler thinks that the function result
+% variable will be used (i.e. appears in the right-hand-side of an expression)
+% before it is initialized (i.e. appeared in the left-hand side of an
+% assigment)
+sym_h_function_result_uninitialized=05060_H_äòøê äîåçæø îäôåð÷öéä àéðå ðøàä ëîàåúçì
+% This message is displayed if the compiler thinks that the function result
+% variable will be used (i.e. appears in the right-hand-side of an expression)
+% before it is initialized (i.e. appeared in the left-hand side of an
+% assigment)
+sym_w_identifier_only_read=05061_W_äîùúðä "$1" ð÷øà, àê îòåìí ìà ÷éáì úåëï
+% You have read the value of a variable, but nowhere assigned a value to
+% it.
+sym_h_abstract_method_list=05062_H_ðîöàä îúåãä îåôùèú: $1
+% When getting a warning about constructing a class/object with abstract methods
+% you get this hint to find the affected method.
+% \end{description}
+#
+# Codegenerator
+#
+# 06040 is the last used one
+#
+% \section{Code generator messages}
+% This section lists all messages that can be displayed if the code
+% generator encounters an error condition.
+% \begin{description}
+cg_e_parasize_too_big=06009_E_äâåãø ùì øùéîú ôøîèøéí âãåìä î 65535 áúéí
+% The I386 processor limits the parameter list to 65535 bytes (the \var{RET}
+% instruction causes this)
+cg_e_file_must_call_by_reference=06012_E_èéôåñ ùì ÷åáõ çééá ìäéåú îùúðä îåâãø
+% You cannot specify files as value parameters, i.e. they must always be
+% declared \var{var} parameters.
+cg_e_cant_use_far_pointer_there=06013_E_äùéîåù áîöáéò far àéðå îåøùä áîé÷åí äðåëçé
+% Free Pascal doesn't support far pointers, so you cannot take the address of
+% an expression which has a far reference as a result. The \var{mem} construct
+% has a far reference as a result, so the following code will produce this
+% error:
+% \begin{verbatim}
+% var p : pointer;
+% ...
+% p:=@mem[a000:000];
+% \end{verbatim}
+cg_e_dont_call_exported_direct=06015_E_ìà ðéúï ì÷øåà ìôåð÷öéåú òí äâãøú EXPORT
+% No longer in use.
+cg_w_member_cd_call_from_method=06016_W_ëðøàä ÷øéàä ìà çå÷éú ùì éåöø àå äåøñ
+% The compiler detected that a constructor or destructor is called within a
+% a method. This will probably lead to problems, since constructors / destructors
+% require parameters on entry.
+cg_n_inefficient_code=06017_N_çñø ÷åã
+% Your statement seems dubious to the compiler.
+cg_w_unreachable_code=06018_W_ìà ðéúï ìäøéõ àú ÷èò ä÷åã
+% You specified a construct which will never be executed. Example:
+% \begin{verbatim}
+% while false do
+% begin
+% {.. code ...}
+% end;
+% \end{verbatim}
+cg_e_cant_call_abstract_method=06020_E_ìà ðéúï ì÷øåà ìîúåãåú Abstract áöåøä éùéøä
+% You cannot call an abstract method directy, instead you must call a
+% overriding child method, because an abstract method isn't implemented.
+cg_d_register_weight=06027_DL_Register $1 îù÷ì $2 $3
+% Debugging message. Shown when the compiler considers a variable for
+% keeping in the registers.
+cg_d_stackframe_omited=06029_DL_îùîéè àú îñâøú äîçñðéú
+% Some procedure/functions do not need a complete stack-frame, so it is omitted.
+% This message will be displayed when the {-vd} switch is used.
+cg_e_unable_inline_object_methods=06031_E_îúåãåú ùì àåáéé÷è àå îçì÷ä àéðí éëåìéí ìäéåú inline
+% You cannot have inlined object methods.
+cg_e_unable_inline_procvar=06032_E_÷øéàåú Procvar àéðí éëåìéí ìäéåú inline
+% A procedure with a procedural variable call cannot be inlined.
+cg_e_no_code_for_inline_stored=06033_E_àéï ÷åã ìôøåöãåøåú inline
+% The compiler couldn't store code for the inline procedure.
+cg_e_can_access_element_zero=06035_E_àìîðè äàôñ ùì ansi/wide- àå longstring ìà ðâéù, äùúîù á (set)length áî÷åí
+% You should use \var{setlength} to set the length of an ansi/wide/longstring
+% and \var{length} to get the length of such a string types
+cg_e_cannot_call_cons_dest_inside_with=06037_E_ìà ðéúï ì÷øåà ìéåöøéí àå äåøñéí áúåê çì÷ ùì 'with'
+% Inside a \var{with} clause you cannot call a constructor or destructor for the
+% object you have in the \var{with} clause.
+cg_e_cannot_call_message_direct=06038_E_ìà ðéúï ì÷øåà ìîúåãåú ùì îèôì äåãàåú áöåøä éùéøä
+% A message method handler method cannot be called directly if it contains an
+% explicit self argument
+cg_e_goto_inout_of_exception_block=06039_E_÷ôéöä àì úåê àå îçåõ ìáìå÷ ùì exception
+% It is not allowed to jump in or outside of an exception block like \var{try..finally..end;}:
+% \begin{verbatim}
+% label 1;
+%
+% ...
+%
+% try
+% if not(final) then
+% goto 1; // this line will cause an error
+% finally
+% ...
+% end;
+% 1:
+% ...
+% \end{verbatim}
+cg_e_control_flow_outside_finally=06040_E_äùéîåù ááéèåééí äùåìèéí áæøéîú ä÷åã àéðí îåøùéí áçì÷ ä finally
+% It isn't allowed to use the control flow statements \var{break},
+% \var{continue} and \var{exit}
+% inside a finally statement. The following example shows the problem:
+% \begin{verbatim}
+% ...
+% try
+% p;
+% finally
+% ...
+% exit; // This exit ISN'T allowed
+% end;
+% ...
+%
+% \end{verbatim}
+% If the procedure \var{p} raises an exception the finally block is
+% executed. If the execution reaches the exit, it's unclear what to do:
+% exiting the procedure or searching for another exception handler
+cg_w_parasize_too_big=06041_W_âåãì äôøîèéí âåìù àú ääâáìåú ùì çì÷ îäîòáãéí
+% This indicates that you are declaring more than 64K of parameters, which
+% might not be supported on other processor targets.
+cg_w_localsize_too_big=06042_W_äâåãì ùì äîùúðä äî÷åîé âåìù îäâáìåú ùì çì÷ îäîòáãéí
+% This indicates that you are declaring more than 32K of local variables, which
+% might not be supported on other processor targets.
+cg_e_localsize_too_big=06043_E_âåãì îùúðéí î÷åîééí âåìù îäâáìåú äðúîëåú
+% This indicates that you are declaring more than 32K of local variables, which
+% is not supported by this processor.
+cg_e_break_not_allowed=06044_E_BREAK àéðå îåøùä
+% You're trying to use \var{break} outside a loop construction.
+cg_e_continue_not_allowed=06045_E_CONTINUE àéðå îåøùä
+% You're trying to use \var{continue} outside a loop construction.
+cg_f_unknown_compilerproc=06046_F_compilerproc "$1" ìà éãåò. áãå÷ àí äùúîù áñôøééú æîï äøéöä äðëåðä.
+% The compiler expects that the runtime library contains certain subroutines. If you see this error
+% and you didn't change the runtime library code, it's very likely that the runtime library
+% you're using doesn't match the used compiler. If you changed the runtime library this error means
+% that you removed a subroutine which the compiler needs for internal use.
+cg_f_unknown_system_type=06047_F_ìà ðéúï ìîöåà èéôåñ îòøëú "$1". áãå÷ äàí àúä îùúîù áñôøééú æîï äøéöä òãëðéú.
+% The compiler expects that the runtime library contains certain type definitions. If you see this error
+% and you didn't change the runtime library code, it's very likely that the runtime library
+% you're using doesn't match the used compiler. If you changed the runtime library this error means
+% that you removed a type which the compiler needs for internal use.
+cg_h_inherited_ignored=06048_H_îúòìí îäùéîåù áinherited áîúåãä îñåâ abstract
+% This messages appears only in Delphi mode when you call an abstract method
+% of a parent class via \var{inherited;}. The call is then ignored.
+cg_e_goto_label_not_found=06049_E_úååéú ä Goto "$1" ìà äåâãøä àå ìà òáøä àåôèéîéæöéä
+% The label used in the goto definition is not defined or optimized away by the
+% unreachable code elemination.
+% \end{description}
+# EndOfTeX
+
+#
+# Assembler reader
+#
+# 07105 is the last used one
+#
+asmr_d_start_reading=07000_DL_îúçéì áñâðåï îôøù àñîáìø $1
+% This informs you that an assembler block is being parsed
+asmr_d_finish_reading=07001_DL_äñúééí ðéúåç ñâðåï àñîáìø $1
+% This informs you that an assembler block has finished.
+asmr_e_none_label_contain_at=07002_E_úáðéú ììà úååéú îëéìä àú äúå @
+% A identifier which isn't a label can't contain a @.
+asmr_e_building_record_offset=07004_E_ùâéàä ááðééú äéñè äøùåîä
+% There has an error occured while building the offset of a record/object
+% structure, this can happend when there is no field specified at all or
+% an unknown field identifier is used.
+asmr_e_offset_without_identifier=07005_E_ðòùä ùéîåù áOFFSET ììà îæää
+% You can only use OFFSET with an identifier. Other syntaxes aren't
+% supported
+asmr_e_type_without_identifier=07006_E_ðòùä ùéîåù áTYPE ììà îæää
+% You can only use TYPE with an identifier. Other syntaxes aren't
+% supported
+asmr_e_no_local_or_para_allowed=07007_E_ìà ðéúï ìäùúîù áîùúîä î÷åîé àå ôøîèø áîé÷åí äðåëçé
+% You can't use a local variable or parameter here, mostly because the
+% addressing of locals and parameters is done using the frame pointer register so the
+% address can't be obtained directly.
+asmr_e_need_offset=07008_E_éù öåøê ìäùúîù á OFFSET
+% You need to use OFFSET <id> here to get the address of the identifier.
+asmr_e_need_dollar=07009_E_éù öåøê ìäùúîù á$
+% You need to use $<id> here to get the address of the identifier.
+asmr_e_cant_have_multiple_relocatable_symbols=07010_E_ìà ðéúï ìäùúîù á relocatable symbols îøåáéí
+% You can't have more than one relocatable symbol (variable/typed constant)
+% in one argument.
+asmr_e_only_add_relocatable_symbol=07011_E_ðéúï ìäåñéó ø÷ relocatable symbol
+% Relocatable symbols (variable/typed constant) can't be used with other
+% operators. Only addition is allowed.
+asmr_e_invalid_constant_expression=07012_E_áéèåé ÷áåò ìà çå÷é
+% There is an error in the constant expression.
+asmr_e_relocatable_symbol_not_allowed=07013_E_Relocatable symbol àéðå îåøùä
+% You can't use a relocatable symbol (variable/typed constant) here.
+asmr_e_invalid_reference_syntax=07014_E_úçáéø äôðéåú ìà çå÷é
+% There is an error in the reference.
+asmr_e_local_para_unreachable=07015_E_ìà ðéúï ìâùú ì $1 îä÷åã
+% You can not read directly the value of a local variable or parameter
+% of a higher level procedure in assembler code (except for
+% local assembler code without parameter nor locals).
+asmr_e_local_label_not_allowed_as_ref=07016_E_ñéîåìéí/úååéåú î÷åîéåú àéðí îåøùéí ëäôðéåú
+% You can't use local symbols/labels as references
+asmr_e_wrong_base_index=07017_E_ùéîåù ùâåé ááñéñ åàéðã÷ñ ùì àåâø
+% There is an error with the base and index register, they are
+% probably incorrect
+asmr_w_possible_object_field_bug=07018_W_éúëï ëé éù ùâéàä áèéôåì äùãåú ùì àåáéé÷è
+% Fields of objects or classes can be reached directly in normal or objfpc
+% modes but TP and Delphi modes treat the field name as a simple offset.
+asmr_e_wrong_scale_factor=07019_E_öåééï èååç ñåìí ùâåé
+% The scale factor given is wrong, only 1,2,4 and 8 are allowed
+asmr_e_multiple_index=07020_E_ùéîåù îøåáä áàéð÷ñ äàåâø
+% You are trying to use more than one index register
+asmr_e_invalid_operand_type=07021_E_èéôåñ àåôøðã ùâåé
+% The operand type doesn't match with the opcode used
+asmr_e_invalid_string_as_opcode_operand=07022_E_àùéîåù áîçøåæú ëàåôøðã opcode ùâåé: $1
+% The string specified as operand is not correct with this opcode
+asmr_w_CODE_and_DATA_not_supported=07023_W_äùéîåù á@CODE å@DATA ìà ðúîê
+% @CODE and @DATA are unsupported and are ignored.
+asmr_e_null_label_ref_not_allowed=07024_E_äúééçñåú ìúååéú øé÷ä àéðä îåøùú
+asmr_e_expr_zero_divide=07025_E_çéìå÷ áàôñ áäòøëú asm
+% There is a division by zero in a constant expression
+asmr_e_expr_illegal=07026_E_áéèåé ìà çå÷é
+% There is an illegal expression in a constant expression
+asmr_e_escape_seq_ignored=07027_E_îúòìí îøöó ÷éãåã: $1
+% There is a C-styled string, but the escape sequence in the string
+% is unknown, and is therefore ignored
+asmr_e_invalid_symbol_ref=07028_E_äúééçñåú ñéîåì ìà ú÷éðä
+asmr_w_fwait_emu_prob=07029_W_FWAIT îñåâì ìâøåí ìáòéåú çé÷åé áemu387
+asmr_w_fadd_to_faddp=07030_W_$1 ììà úøâåí àåôøðã ì$1P
+asmr_w_enter_not_supported_by_linux=07031_W_äåøàú ENTER àéðä ðúîëú ò"é ìéáú Linux
+% ENTER instruction can generate a stack page fault that is not
+% caught correctly by the i386 Linux page handler.
+asmr_w_calling_overload_func=07032_W_îáöò ÷øéàä ìôåð÷öéä îùåëúáú áassembler
+% There is a call to an overloaded method in the assembler block,
+% this might be the sign there is a problem
+asmr_e_unsupported_symbol_type=07033_E_èéôåñ äñéîåì ùì äàåôøðã àéðå ðúîê
+asmr_e_constant_out_of_bounds=07034_E_úåëï ä÷áåò îçåõ ìâáåìåú
+asmr_e_error_converting_decimal=07035_E_ùâéàä áæîï äîøä ãöéîìéú $1
+% A constant decimal value does not have the correct syntax
+asmr_e_error_converting_octal=07036_E_ùâéàä áæîï äîøä àå÷èìéú $1
+% A constant octal value does not have the correct syntax
+asmr_e_error_converting_binary=07037_E_ùâéàä áæîï äîøä áéðøéú $1
+% A constant binary value does not have the correct syntax
+asmr_e_error_converting_hexadecimal=07038_E_ùâéàä áæîï äîøä ä÷ñä-ãöéîìéú $1
+% A constant hexadecimal value does not have the correct syntax
+asmr_h_direct_global_to_mangled=07039_H_$1 úåøâí ì $2
+asmr_w_direct_global_is_overloaded_func=07040_W_$1 îùåééê ìôåð÷öéä îùåëúáú
+asmr_e_cannot_use_SELF_outside_a_method=07041_E_ìà ðéúï ìäùúîù á SELF îçåõ ìîúåãä
+% There is a reference to the \var{self} symbol while it is not
+% allowed. \var{self} can only be referenced inside methods
+asmr_e_cannot_use_OLDEBP_outside_nested_procedure=07042_E_ìà ðéúï ìäùúîù á OLDEBP îçåõ ìôøåöãåøä î÷åððú
+% There is a reference to the \var{oldebp} symbol while it is not
+% allowed. \var{oldebp} can only be referenced inside nested routines
+asmr_e_void_function=07043_W_ôøåöãåøåú àéðí éëåìéí ìäçæéø òøê áúåê ÷åã assembly
+% Trying to return a value while in a procedure. A procedure
+% does not have any return value
+asmr_e_SEG_not_supported=07044_E_SEG àéðå ðúîê
+asmr_e_size_suffix_and_dest_dont_match=07045_E_âåãì ñåôé åéòã, àå î÷åø äâåãì àéðí úåàîéí
+% The register size and the opcode size suffix don't match. This is
+% probably an error in the assembler statement
+asmr_w_size_suffix_and_dest_dont_match=07046_W_âåãì ñåôé åéòã, àå î÷åø äâåãì àéðí úåàîéí
+% The register size and the opcode size suffix don't match. This is
+% probably an error in the assembler statement
+asmr_e_syntax_error=07047_E_ùâéàä áúçáéø Assembler
+% There is an assembler syntax error
+asmr_e_invalid_opcode_and_operand=07048_E_ùéìåá ìà çå÷é áéï opcode åàåôøðã
+% The opcode cannot be used with this type of operand
+asmr_e_syn_operand=07049_E_ùâéàä áúçáéø àåôøðã áAssembler
+asmr_e_syn_constant=07050_E_ùâéàä áúçáéø ÷áåò áAssembler
+asmr_e_invalid_string_expression=07051_E_áéèåé îçøåæú ìà ú÷éï
+asmr_w_const32bit_for_address=07052_W_ä÷áåò áòì äñéîåì $1 ìëúåáú, äåà ìà îöáéò
+% A constant expression represents an address which does not fit
+% into a pointer. The address is probably incorrect
+asmr_e_unknown_opcode=07053_E_opcode $1 àéðå îåëø
+% This opcode is not known
+asmr_e_invalid_or_missing_opcode=07054_E_opcode çñø àå ìà ú÷éï
+asmr_e_invalid_prefix_and_opcode=07055_E_ùéìåá ùì úçéìéú åopcode ìà ú÷éï : $1
+asmr_e_invalid_override_and_opcode=07056_E_äùéìåá ùì ùëúåá åopcode ìà ú÷éï: $1
+asmr_e_too_many_operands=07057_E_Too many operands on line
+% There are too many operands for this opcode. Check your
+% assembler syntax
+asmr_w_near_ignored=07058_W_îúòìí îNEAR
+asmr_w_far_ignored=07059_W_îúòìí î FAR
+asmr_e_dup_local_sym=07060_E_ùéëôåì ùì äñéîåì äî÷åîé $1
+asmr_e_unknown_local_sym=07061_E_äñéîåì äî÷åîé $1 àéðå îåâãø
+asmr_e_unknown_label_identifier=07062_E_îæää úååéú $1 ìà éãåò
+asmr_e_invalid_register=07063_E_ùí àåâø ùâåé
+% There is an unknown register name used as operand.
+asmr_e_invalid_fpu_register=07064_E_ùí àåâø ìð÷åãä öôä ìà ú÷éï
+% There is an unknown register name used as operand.
+asmr_w_modulo_not_supported=07066_W_îåãåìå ìà ðúîê
+asmr_e_invalid_float_const=07067_E_÷áåò ùì ð÷åãä öôä ìà ú÷éï $1
+% The floating point constant declared in an assembler block is
+% invalid.
+asmr_e_invalid_float_expr=07068_E_áéèåé ìà ú÷éï ùì ð÷åãä öôä
+% The floating point expression declared in an assembler block is
+% invalid.
+asmr_e_wrong_sym_type=07069_E_ñåâ ñéîåì ùâåé
+asmr_e_cannot_index_relative_var=07070_E_ìà ðéúï ìùîåø öéåï ùì ôøîèø àå îùúðä î÷åîé òí àåâø
+% Trying to index using a base register a symbol which is already relative
+% to a register. This is not possible, and will probably lead to crashes.
+asmr_e_invalid_seg_override=07071_E_áéèåé äîé÷èò äîùåëúá àéðå ú÷éï
+asmr_w_id_supposed_external=07072_W_äîæää $1 àéðå ðîöà, îðéç ùäîæää çéöåðé
+% There is a reference to an undefined symbol. This will not result
+% in an error, since the symbol might be external, but may cause
+% problems at link time if the symbol is not defined anywhere.
+asmr_e_string_not_allowed_as_const=07073_E_äîçøåæåú àéðï îåøùåú ìäéåú ÷áåòåú
+% Character strings are not allowed as constants.
+asmr_e_no_var_type_specified=07074_ìà öåééï èéôåñ äîùúðä
+% The syntax expects a type idenfitifer after the dot, but
+% none was found.
+asmr_w_assembler_code_not_returned_to_text=07075_E_÷åã äassembler ìà çæø ìàéæåø äè÷ñè
+% There was a directive in the assembler block to change sections,
+% but there is a missing return to the text section at the end
+% of the assembler block. This might cause errors during link time.
+asmr_e_not_directive_or_local_symbol=07076_E_$1 äåà ìà äðçéä àå ñéîåì î÷åîé
+% This symbol is unknown.
+asmr_w_using_defined_as_local=07077_E_îùúîù áäâãøú äùí ëúååéú î÷åîéú
+asmr_e_dollar_without_identifier=07078_E_äùéîåù áúå äãåìø îúáöò ììà îæää
+% A constant expression has an identifier which does not start with
+% the $ symbol.
+asmr_w_32bit_const_for_address=07079_W_îñô÷ ëúåáú ùì 32 ñéáéåú ì÷áåò
+% A constant was used as an address. This is probably an error,
+% since using absolute addresses will probably not work.
+asmr_n_align_is_target_specific=07080_N_äùéîåù á.align îáåññ òì ñåâ éòã, äùúîù á.balign àå .p2align
+% Using the .align directive is platform specific, and its meaning will vary
+% from one platform to another.
+asmr_e_cannot_access_field_directly_for_parameters=07081_E_ìà ðéúï ìäùúîù áöåøä éùéøä áùãåú ùì ôøîèøéí
+% You should load the parameter first into a register and then access the
+% fields using that register.
+asmr_e_cannot_access_object_field_directly=07082_E_ìà ðéúï ìâùú áöåøä éùéøä ìùãåú ùì àåáéé÷èéí/îçì÷åú
+% You should load the self pointer first into a register and then access the
+% fields using the register as base. By default the self pointer is available
+% in the esi register on i386.
+asmr_e_unable_to_determine_reference_size=07083_E_ìà ðéúï ì÷áåò àú âåãì äàåôøðãéí ììà öéåï ùì äâåãì
+% You should specify explicitly a size for the reference, because
+% the compiler is unable to determine what size (byte,word,dword,etc.) it
+% should use for the reference.
+asmr_e_cannot_use_RESULT_here=07084_E_ìà ðéúï ìäùúîù áRESULT áôåð÷öéä äðåëçéú
+% Some functions which return complex types cannot use the \var{result}
+% keyword.
+asmr_w_adding_explicit_args_fXX=07086_W_"$1" ììà úøâåí ùì àåôøðãéí ì "$1 %st,%st(1)"
+asmr_w_adding_explicit_first_arg_fXX=07087_W_"$1 %st(n)" úåøâí ì "$1 %st,%st(n)"
+asmr_w_adding_explicit_second_arg_fXX=07088_W_"$1 %st(n)" úåøâí ì "$1 %st(n),%st"
+asmr_e_invalid_char_smaller=07089_E_äúå > àéðå îåøùä ëàï
+% The shift operator requires the << characters. Only one
+% of those characters was found.
+asmr_e_invalid_char_greater=07090_E_äúå < àéðå îåøùä ëàï
+% The shift operator requires the >> characters. Only one
+% of those characters was found.
+asmr_w_align_not_supported=07093_W_ALIGN àéðå ðúîê
+asmr_e_no_inc_and_dec_together=07094_E_äùéîåù INC å DEC àéðí éëåìéí ìäâéò áééçã
+% Trying to use an increment and a decrement within the same
+% opcode on the 680x0. This is impossible.
+asmr_e_invalid_reg_list_in_movem=07095_E_ùéîåù áreglist ì movem ìà ú÷éï
+% Trying to use the \var{movem} opcode with invalid registers
+% to save or restore.
+asmr_e_invalid_reg_list_for_opcode=07096_E_ùéîåù ùâåé áreglist ìopcode
+asmr_e_higher_cpu_mode_required=07097_E_æ÷å÷ ìîöá îòáã âáåää éåúø ($1)
+% Trying to use an instruction which is not supported in the current
+% cpu mode. Use a higher cpu generation to be able to use this
+% opcode in your assembler block
+asmr_w_unable_to_determine_reference_size_using_dword=07098_W_ìà öåééï âåãì ùì àåôøðã åìà ðéúï ìðçù àú äâåãì, îùúîù áDWORD ëáøéøú îçãì
+% You should specify explicitly a size for the reference, because
+% the compiler is unable to determine what size (byte,word,dword,etc.) it
+% should use for the reference. This warning is only used in Delphi mode where
+% it falls back to use DWORD as default.
+asmr_e_illegal_shifterop_syntax=07099_E_ùâéàú úçáéø áòú ðéñéåï ìôøù äñèú àåôøðã
+% ARM only; ARM assembler supports a so called shifter operand. The used syntax isn't
+% a valid shifter operand. Example for an operation with shifter operand:
+% \begin{verbatim}
+% asm
+% orr r2,r2,r2,lsl #8
+% end;
+% \end{verbatim}
+asmr_e_packed_element=07100_E_äëúåáú ùì øëéá àøåæ àéðå ðîöà áèååç ùì áéú
+% Packed components (record fields and array elements) may start at an arbitrary
+% bit inside a byte. On CPU which do not support bit-addressable memory (which
+% includes all currently supported CPUs by FPC) you will therefore get an error
+% message when trying to index arrays with elements whose size is not a multiple
+% of 8 bits. The same goes for accessing record fields with such an address.
+% multiple of 8 bits.
+asmr_w_unable_to_determine_reference_size_using_byte=07101_W_ìà öåééï âåãì, åäîäãø àéðå îöìéç ì÷áåò àú âåãì äàåôøðã, îùúîù áâåãì BYTE áúåø áøéøú îçãì
+% You should specify explicitly a size for the reference, because
+% the compiler is unable to determine what size (byte,word,dword,etc.) it
+% should use for the reference. This warning is only used in Delphi mode where
+% it falls back to use BYTE as default.
+asmr_w_no_direct_ebp_for_parameter=07102_W_ìà ðéúï ìäùúîù á+äñè(%ebp) áîé÷åí äðåëé òáåø äôøîèøéí
+% Using direct 8(%ebp) reference for function/procedure parameters is invalid
+% if parameters are in registers.
+asmr_w_direct_ebp_for_parameter_regcall=07103_W_äùéîåù á+äñè(%ebp) àéðå úåàí òí îåñëîåú ä regcall
+% Using direct 8(%ebp) reference for function/procedure parameters is invalid
+% if parameters are in registers.
+asmr_w_direct_ebp_neg_offset=07104_W_äùéîåù á-äñè(%ebp) àéðå îåîìõ òáåø âéùä ìîùúðéí î÷åîééí
+% Using -8(%ebp) to access a local variable is not recommended
+asmr_w_direct_esp_neg_offset=07105_W_äùéîåù á-äñè(%ebp) òìåì ìâøåí ì÷øéñä ùì äúåëðéú àå ìàéáåã äîéãò
+% Using -8(%esp) to access a local stack is not recommended, as
+% this stack portion can be overwritten by any function calls or interrupts.
+asmr_e_no_vmtoffset_possible=07106_E_äùéîåù á VMTOffset çééá ìäâéò áùéìåá ùì îúåãåú ååéøèåàìéåú å "$1" àéðå ååéøèåàìé
+% \end{verbatim}
+#
+# Assembler/binary writers
+#
+# 08018 is the last used one
+#
+asmw_f_too_many_asm_files=08000_F_éåúø îéãé ÷áöé assembler
+% With smartlinking enabled, there are too many assembler
+% files generated. Disable smartlinking.
+asmw_f_assembler_output_not_supported=08001_F_ñåâ äôìè ùì äassembler àéðå ðúîê
+asmw_f_comp_not_supported=08002_F_Comp àéðå ðúîê
+asmw_f_direct_not_supported=08003_F_îöá éùéø ùì assembler àéðå ðúîê ò"é ëåúáéí áéðàøééí
+% Direct assembler mode is not supported for binary writers.
+asmw_e_alloc_data_only_in_bss=08004_E_àúçåì äîéãò îåøùä ø÷ áçì÷ äbss
+asmw_f_no_binary_writer_selected=08005_F_ìà ðáçø ëåúá áéðàøé
+asmw_e_opcode_not_in_table=08006_E_Asm: Opcode $1 äåà ìà èáìä
+asmw_e_invalid_opcode_and_operands=08007_E_Asm: $1 äéðå ùéìåá ùâåé áéï opcode ìáéï àåôøðã
+asmw_e_16bit_not_supported=08008_E_Asm: äúééçñåú ùì 16 ñéáéåú àéðå ðúîê
+asmw_e_invalid_effective_address=08009_E_Asm: îòï áôòåì ìà ú÷éï
+asmw_e_immediate_or_reference_expected=08010_E_Asm: îöôä ìäúééçñåú ìàåôøðã àå àåôøðã îéãé
+asmw_e_value_exceeds_bounds=08011_E_Asm: $1 âåìù îäâáåìåú $2
+asmw_e_short_jmp_out_of_range=08012_E_Asm: Short jump îçåõ ìèååç $1
+asmw_e_undefined_label=08013_E_Asm: úååéú ìà îåâãøú $1
+asmw_e_comp_not_supported=08014_E_Asm: äèéôåñ COMP ìà ðúîê áéòã äîáå÷ù
+asmw_e_extended_not_supported=08015_E_Asm: äèéôåñ Extended àéðå ðúîê áéòã äîáå÷ù
+asmw_e_duplicate_label=08016_E_Asm: úååéåú ëôåìä $1
+asmw_e_redefined_label=08017_E_Asm: îâãéø îçãù àú äúååéú $1
+asmw_e_first_defined_label=08018_E_Asm: îåâãø ëàï ìøàùåðä
+asmw_e_invalid_register=08019_E_Asm: àåâø ùâåé $1
+asmw_e_16bit_32bit_not_supported=08020_E_Asm: ääúééçñåú ì16 àå 32 ñéáéåú àéðä ðúîëú
+asmw_e_64bit_not_supported=08021_E_Asm: äàåôøðè 64 ñéáéåú àéðå ðúîê
+
+#
+# Executing linker/assembler
+#
+# 09034 is the last used one
+#
+# BeginOfTeX
+%
+% \section{Errors of assembling/linking stage}
+% This section lists errors that occur when the compiler is processing the
+% command line or handling the configuration files.
+% \begin{description}
+exec_w_source_os_redefined=09000_W_î÷åø îòøëú ääôòìä îåâãø îçãù
+% The source operating system is redefined.
+exec_i_assembling_pipe=09001_I_îøëéá (öéðåø) $1
+% Assembling using a pipe to an external assembler.
+exec_d_cant_create_asmfile=09002_E_ìà ðéúï ìéöåø àú ÷åáõ äassembler $1
+% The mentioned file can't be created. Check if you have got
+% access permissions to create this file
+exec_e_cant_create_objectfile=09003_E_ìà ðéúï ìéöåø àú ÷åáõ àåáéé÷è $1
+% The mentioned file can't be created. Check if you've
+% got access permissions to create this file
+exec_e_cant_create_archivefile=09004_E_ìà ðéúï ìéöåø àú ÷åáõ äàøëéåï $1
+% The mentioned file can't be created. Check if you've
+% access permissions to create this file
+exec_e_assembler_not_found=09005_E_äî÷ùø $1 àéðå ðîöà, òåáø ìîàñó çéöåðé
+% The assembler program was not found. The compiler will produce a script that
+% can be used to assemble and link the program.
+exec_t_using_assembler=09006_T_îùúîù áîàñó: $1
+% Information message saying which assembler is being used.
+exec_e_error_while_assembling=09007_E_ùâéàä áæîï àéñåó ÷åã éöéàä $1
+% There was an error while assembling the file using an external assembler.
+% Consult the documentation of the assembler tool to find out more information
+% on this error.
+exec_e_cant_call_assembler=09008_E_ìà ðéúï ìäøéõ àú äîàñó, ùâéàä $1, îøéõ îàñó çéöåðé
+% An error occurred when calling an external assembler, The compiler will produce a script that
+% can be used to assemble and link the program.
+exec_i_assembling=09009_I_î÷ùø $1
+% An informational message stating which file is being assembled.
+exec_i_assembling_smart=09010_I_àåñó òí smartlinking $1
+% An informational message stating which file is being assembled using smartlinking.
+exec_w_objfile_not_found=09011_W_äàåáéé÷è $1 ìà ðîöà, ðøàä ùäàéñåó éëùì !
+% One of the object file is missing, and linking will probably fail.
+% Check your paths.
+exec_w_libfile_not_found=09012_W_äñôøééä $1 ìà ðîöàä, ðøàä ùäàéñåó éëùì !
+% One of the library file is missing, and linking will probably fail.
+% Check your paths.
+exec_e_error_while_linking=09013_E_ùâéàä áæîï ÷éùåø
+% Generic error while linking.
+exec_e_cant_call_linker=09014_E_ìà ðéúï ìäøéõ àú äî÷ùø, òåáø ìî÷ùø çéöåðé
+% An error occurred when calling an external linker, The compiler will produce a script that
+% can be used to assemble and link the program.
+exec_i_linking=09015_I_î÷ùø $1
+% An informational message, showing which program or library is being linked.
+exec_e_util_not_found=09016_E_äëìé $1 ìà ðîöà, òåáø ìî÷ùø çéöåðé
+% An external tool was not found, the compiler will produce a script that
+% can be used to assemble and link or postprocess the program.
+exec_t_using_util=09017_T_îùúîù áëìé $1
+% An informational message, showing which external program (usually a postprocessor) is being used.
+exec_e_exe_not_supported=09018_E_àéï úîéëä áéöéøú ÷áöé øéöä
+% Creating executable programs is not supported for this platform, because it was
+% not yet implemented in the compiler.
+exec_e_dll_not_supported=09019_E_àéï úîéëä áéöéøú ñôøéåú ãéðîéåú/îùåúôåú
+% Creating dynamically loadable libraries is not supported for this platform, because it was
+% not yet implemented in the compiler.
+exec_i_closing_script=09020_I_ñåâø àú äúñøéè $1
+% Informational message showing when the external assembling an linking script is finished.
+exec_e_res_not_found=09021_E_îäãø îùàáéí ìà ðîöà, òåáø ìîöá çéöåðé
+% An external resource compiler was not found, the compiler will produce a script that
+% can be used to assemble, compile resources and link or postprocess the program.
+exec_i_compilingresource=09022_I_îäãø àú äîùàá $1
+% An informational message, showing which resource is being compiled.
+exec_t_unit_not_static_linkable_switch_to_smart=09023_T_ìà ðéúï ì÷ùø àú äéçéãä $1 áöåøä ñèèéú, òåáø ì÷éùåø çëí
+% Statical linking was requested, but a unit which is not statically linkable was used.
+exec_t_unit_not_smart_linkable_switch_to_static=09024_T_ìà ðéúï ì÷ùø áöåøä çëîä àú äéçéãä $1, òåáø ì÷éùåø ñèèé
+% Smart linking was requested, but a unit which is not smart-linkable was used.
+exec_t_unit_not_shared_linkable_switch_to_static=09025_T_ìà ðéúï ì÷ùø àú äéçéãä $1 á÷éùåø îùåúó, òåáø ì÷éùåø ñèèé
+% Shared linking was requested, but a unit which is not shared-linkable was used.
+exec_e_unit_not_smart_or_static_linkable=09026_E_ìà ðéúï ì÷ùø àú äéçéãä $1 á÷éùåø çëí àå á÷éùåø ñèèé
+% Smart or static linking was requested, but a unit which cannot be used for either was used.
+exec_e_unit_not_shared_or_static_linkable=09027_E_ìà ðéúï ì÷ùø àú äéçéãä $1 á÷éùåø îùåúó àå ñèèé
+% Shared or static linking was requested, but a unit which cannot be used for either was used.
+exec_d_resbin_params=09028_D_îøéõ àú îäãø äîùàáéí "$1" òí "$2" áúåø ùåøú ô÷åãä
+% An informational message showing which command-line is used for the resource compiler.
+%\end{description}
+# EndOfTeX
+
+#
+# Executable information
+#
+# BeginOfTeX
+% \section{Executable information messages.}
+% This section lists all messages that the compiler emits when an executable program is produced,
+% and only when the internal linker is used.
+% \begin{description}
+execinfo_f_cant_process_executable=09128_F_ìà îöìéç ìáöò îòáø ñåôé òì ÷åáõ ääøöä $1
+% Fatal error when the compiler is unable to post-process an executable.
+execinfo_f_cant_open_executable=09129_F_ìà îöìéç ìôúåç àú ÷åáõ äøéöä $1
+% Fatal error when the compiler cannot open the file for the executable.
+execinfo_x_codesize=09130_X_âåãì ä÷åã: $1 áúéí
+% Informational message showing the size of the produced code section.
+execinfo_x_initdatasize=09131_X_äâåãì ùì îéãò îàåúçì: $1 áúéí
+% Informational message showing the size of the initialized data section.
+execinfo_x_uninitdatasize=09132_X_îéãò ùì îéãò ìà îàåúçì: $1 áúéí
+% Informational message showing the size of the uninitialized data section.
+execinfo_x_stackreserve=09133_X_âåãì äîçñðéú äùîåøä: $1 áúéí
+% Informational message showing the stack size that the compiler reserved for the executable.
+execinfo_x_stackcommit=09134_X_âåãì äîçñðéú áùéîåù: $1 áúéí
+% Informational message showing the stack size that the compiler commites for the executable.
+%\end{description}
+# EndOfTeX
+
+#
+# Unit loading
+#
+# 10041 is the last used one
+#
+# BeginOfTeX
+% \section{Unit loading messages.}
+% This section lists all messages that can occur when the compiler is
+% loading a unit from disk into memory. Many of these messages are
+% informational messages.
+% \begin{description}
+unit_t_unitsearch=10000_T_îçôù àú äéçéãä: $1
+% When you use the \var{-vt}, the compiler tells you where it tries to find
+% unit files.
+unit_t_ppu_loading=10001_T_èåòï àú ÷åáõ ä PPU $1
+% When the \var{-vt} switch is used, the compiler tells you
+% what units it loads.
+unit_u_ppu_name=10002_U_ùí ä PPU: $1
+% When you use the \var{-vu} flag, the unit name is shown.
+unit_u_ppu_flags=10003_U_ãâìé PPU: $1
+% When you use the \var{-vu} flag, the unit flags are shown.
+unit_u_ppu_crc=10004_U_PPU Crc: $1
+% When you use the \var{-vu} flag, the unit CRC check is shown.
+unit_u_ppu_time=10005_U_æîï PPU: $1
+% When you use the \var{-vu} flag, the time the unit was compiled is shown.
+unit_u_ppu_file_too_short=10006_U_÷åáõ äPPU ÷öø îéãé
+% The ppufile is too short, not all declarations are present.
+unit_u_ppu_invalid_header=10007_U_äøàù ùì ÷åáõ ä PPU àéðå ú÷éï (ä÷åáõ àéðå îëéì PPU áäúçìä)
+% A unit file contains as the first three bytes the ascii codes of \var{PPU}
+unit_u_ppu_invalid_version=10008_U_âøñä ìà ú÷éðä ùì äPPU $1
+% This unit file was compiled with a different version of the compiler, and
+% cannot be read.
+unit_u_ppu_invalid_processor=10009_U_÷åáõ äPPU äåãø ìîòáã àçø
+% This unit file was compiled for a different processor type, and
+% cannot be read
+unit_u_ppu_invalid_target=10010_U_÷åáõ äPPU äåãø ìîèøä àçøú
+% This unit file was compiled for a different target, and
+% cannot be read
+unit_u_ppu_source=10011_U_î÷åø äPPU: $1
+% When you use the \var{-vu} flag, the unit source file name is shown.
+unit_u_ppu_write=10012_U_ëåúá $1
+% When you specify the \var{-vu} switch, the compiler will tell you where it
+% writes the unit file.
+unit_f_ppu_cannot_write=10013_F_ìà ëåúá àú ÷åáõ ä PPU
+% An error occurred when writing the unit file.
+unit_f_ppu_read_error=10014_F_ùâéàä áæîï ÷øéàú ÷åáõ ä PPU
+% This means that the unit file was corrupted, and contains invalid
+% information. Recompilation will be necessary.
+unit_f_ppu_read_unexpected_end=10015_F_ñåó ÷åáõ ìà öôåé (÷åáõ PPU)
+% Unexpected end of file. This may mean that the PPU file is
+% corrupted.
+unit_f_ppu_invalid_entry=10016_F_ëðéñä ìà ú÷éðä á÷åáõ ä PPU: $1
+% The unit the compiler is trying to read is corrupted, or generated with a
+% newer version of the compiler.
+unit_f_ppu_dbx_count_problem=10017_F_áòéä áñôéøú Dbx á÷åáõ PPU
+% There is an inconsistency in the debugging information of the unit.
+unit_e_illegal_unit_name=10018_E_ùí éçéãä ìà ú÷éï: $1
+% The name of the unit does not match the file name.
+unit_f_too_much_units=10019_F_éåúø îéãé éçéãåú
+% \fpc has a limit of 1024 units in a program. You can change this behavior
+% by changing the \var{maxunits} constant in the \file{fmodule.pas} file of the
+% compiler, and recompiling the compiler.
+unit_f_circular_unit_reference=10020_F_÷øéàä îòâìéú áéï äéçéãåú $1 å $2
+% Two units are using each other in the interface part. This is only allowed
+% in the \var{implementation} part. At least one unit must contain the other one
+% in the \var{implementation} section.
+unit_f_cant_compile_unit=10021_F_àéï îñôé÷ îùàáéí òì îðú ìäãø àú äéçéãä $1
+% A unit was found that needs to be recompiled, but no sources are
+% available.
+unit_f_cant_find_ppu=10022_F_ìà îåöà àú äéçéãä $1
+% You tried to use a unit of which the PPU file isn't found by the
+% compiler. Check your configuration file for the unit paths
+unit_w_unit_name_error=10023_W_äéçéãä $1 ìà ðîöàä, àáì $2 ÷ééí
+% This error message is no longer used.
+unit_f_unit_name_error=10024_F_îçôù àú äéçéãä $1, àáì $2 ðîöà
+% Dos truncation of 8 letters for unit PPU files
+% may lead to problems when unit name is longer than 8 letters.
+unit_w_switch_us_missed=10025_W_äéãåø éçéãú system ãåøùú àú äîúâ -Us
+% When recompiling the system unit (it needs special treatment), the
+% \var{-Us} must be specified.
+unit_f_errors_in_unit=10026_F_òåöø ìàçø ùðîöàå $1 ùâéàåú áæîï äéãåø äîåãåì
+% When the compiler encounters a fatal error or too many errors in a module
+% then it stops with this message.
+unit_u_load_unit=10027_U_èåòï $1 ($2) éçéãä $3
+% When you use the \var{-vu} flag, which unit is loaded from which unit is
+% shown.
+unit_u_recompile_crc_change=10028_U_îäãø àú $1 ìàçø ùäçúéîä ùåðúä ì $2
+% The unit is recompiled because the checksum of a unit it depends on has
+% changed.
+unit_u_recompile_source_found_alone=10029_U_ðîöà ø÷ ÷åã î÷åø, îäãø îçãù àú $1
+% When you use the \var{-vu} flag, these messages tell you why the current
+% unit is recompiled.
+unit_u_recompile_staticlib_is_older=10030_U_îäãø îçãù àú äéçéãä. äñôøééä äñèèéú éùðä éåúø î÷åáõ ä PPU
+% When you use the \var{-vu} flag, the compiler warns if the static library
+% of the unit are older than the unit file itself.
+unit_u_recompile_sharedlib_is_older=10031_U_îäãø îçãù àú äéçéãä. äñôøééä äîùåúôú éùðä éåúø î÷åáõ ä PPU
+% When you use the \var{-vu} flag, the compiler warns if the shared library
+% of the unit are older than the unit file itself.
+unit_u_recompile_obj_and_asm_older=10032_U_îäãø îçãù àú ä äéçéãä. ÷áöé ä obj åäasm éùðéí éåúø î÷åáõ ä PPU
+% When you use the \var{-vu} flag, the compiler warns if the assembler or
+% object file of the unit are older than the unit file itself.
+unit_u_recompile_obj_older_than_asm=10033_U_îäãø îçãù àú äéçéãä. ÷åáõ äobj éùï éåúø î÷åáõ äasm
+% When you use the \var{-vu} flag, the compiler warns if the assembler
+% file of the unit is older than the object file of the unit.
+unit_u_parsing_interface=10034_U_îôøù àú çì÷ äîîù÷ ùì $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% parsing the interface part of the unit
+unit_u_parsing_implementation=10035_U_îôøù àú çì÷ äáéöåòé ùì $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% parsing the implementation part of the unit
+unit_u_second_load_unit=10036_U_èòéðä ùðééä ùì äéçéãä $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% recompiling a unit for the second time. This can happend with interdepend
+% units.
+unit_u_check_time=10037_U_áãé÷ú ÷åáõ PPU $1 æîï $2
+% When you use the \var{-vu} flag, the compiler show the filename and
+% date and time of the file which a recompile depends on
+### The following two error msgs is currently disabled.
+#unit_h_cond_not_set_in_last_compile=10038_H_äúðàéí ùì $1 ìà äåâãøå áäúçìú äøéöä áäéãåø äàçøåï ùì $2
+#% when recompilation of an unit is required the compiler will check that
+#% the same conditionals are set for the recompiliation. The compiler has
+#% found a conditional that currently is defined, but was not used the last
+#% time the unit was compiled.
+#unit_h_cond_set_in_last_compile=10039_H_äúðàéí ùì $1 äåâãøå áäúçìú äøéöä áäéãåø äàçøåï ùì $2
+#% when recompilation of an unit is required the compiler will check that
+#% the same conditionals are set for the recompiliation. The compiler has
+#% found a conditional that was used the last time the unit was compiled, but
+#% the conditional is currently not defined.
+unit_w_cant_compile_unit_with_changed_incfile=10040_W_ìà ðéúï ìäãø àú äéçéãä $1 ìîøåú ù÷áöé äinclude ùåðå
+% A unit was found to have modified include files, but
+% some source files were not found, so recompilation is impossible.
+unit_u_source_modified=10041_U_ä÷åáõ $1 çãù éåúø îä÷åáõ PPU $2
+% A modified source file for a compiler unit was found.
+unit_u_ppu_invalid_fpumode=10042_U_îðñä ìäùúîù áéçéãä àùø äåãøä ìîöá FPU ùåðä
+% Trying to compile code while using units which were not compiled with
+% the same floating point format mode. Either all code should be compiled
+% with FPU emulation on, or with FPU emulation off.
+unit_u_loading_interface_units=10043_U_èåòï àú çì÷ äîîù÷ ùì äéçéãåú î $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% loading the units defined in the interface part of the unit.
+unit_u_loading_implementation_units=10044_U_èåòï àú äçì÷ äáéöåòé ùì äéçéãåú î $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% loading the units defined in the implementation part of the unit.
+unit_u_interface_crc_changed=10045_U_çúéîú ä CRC ùì çì÷ äîîù÷ äùúðä áéçéãä $1
+% When you use the \var{-vu} flag, the compiler warns that it the
+% CRC calculated for the interface has been changed after the implementation
+% has been parsed.
+unit_u_implementation_crc_changed=10046_U_çúéîú äCRC ùì äçì÷ äáéöåòé äùúðä ìéçéãä $1
+% When you use the \var{-vu} flag, the compiler warns that it the
+% CRC calculated has been changed after the implementation
+% has been parsed.
+unit_u_finished_compiling=10047_U_äñúééí äéãåø äéçéãä $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has finished compiling the unit.
+unit_u_add_depend_to=10048_U_îåñéó àú äúìåú ùì $1 ì$2
+% When you use the \var{-vu} flag, the compiler warns that it
+% has added a dependency between the two units.
+unit_u_no_reload_is_caller=10049_U_àéï ÷øéàä îçåãùú ùì ä÷åáõ áùáéì $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has will not reload the unit because it is the unit that wants
+% to load this unit
+unit_u_no_reload_in_second_compile=10050_U_àéï èòéðä îçãù, áæîï äéãåø ùðé ùì äéçéãä $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has will not reload the unit because it is already in a second recompile
+unit_u_flag_for_reload=10051_U_ãâì ìèòéðä îçåãùú: $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has to reload the unit
+unit_u_forced_reload=10052_U_ëåôä òì èòéðä îçåãùú
+% When you use the \var{-vu} flag, the compiler warns that it
+% has is reloading the unit because it was required
+unit_u_previous_state=10053_U_äîöá äéùï ùì $1: $2
+% When you use the \var{-vu} flag, the compiler shows the
+% previous state of the unit
+unit_u_second_compile_unit=10054_U_ðîöà ëáø áúäìéê äéãåø $1, îééùí äéãåø ùðé
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% recompiling a unit for the second time. This can happend with interdepend
+% units.
+unit_u_loading_unit=10055_U_èåòï àú äéçéãä $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% loading the unit.
+unit_u_finished_loading_unit=10056_U_îñééí ìèòåï àú äéçéãä $1
+% When you use the \var{-vu} flag, the compiler warns that it finished
+% loading the unit.
+unit_u_registering_new_unit=10057_U_øåùí éçéãä çãùä $1
+% When you use the \var{-vu} flag, the compiler warns that it has
+% found a new unit and registers it in the internal lists.
+unit_u_reresolving_unit=10058_U_îçùá îçãù àú äéçéãä $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has to recalculate the internal data of the unit
+unit_u_skipping_reresolving_unit=10059_U_îãìâ òì èòéðä îçåãùú ùì äéçéãä $1, òãééï áæîï èòéðú éçéãåú áùéîåù
+% When you use the \var{-vu} flag, the compiler warns that it
+% skips to recalculate the internal data of the unit because there
+% is no data to recalculate
+% \end{description}
+# EndOfTeX
+
+#
+# Options
+#
+# 11041 is the last used one
+#
+option_usage=11000_O_$1 [options] <inputfile> [options]
+# BeginOfTeX
+%
+% \section{Command-line handling errors}
+% This section lists errors that occur when the compiler is processing the
+% command line or handling the configuration files.
+% \begin{description}
+option_only_one_source_support=11001_W_úåîê ø÷ á÷åáõ î÷åø àçã áùåøú äô÷åãä
+% You can specify only one source file on the command line. The first
+% one will be compiled, others will be ignored. This may indicate that
+% you forgot a \var{'-'} sign.
+option_def_only_for_os2=11002_W_ðéúï ìéöåø àú ÷åáõ ä DEF ø÷ ìOS/2
+% This option can only be specified when you're compiling for OS/2
+option_no_nested_response_file=11003_E_àéï úîéëä á÷áöé úâåáä î÷åððéí
+% you cannot nest response files with the \var{@file} command-line option.
+option_no_source_found=11004_F_ìà öåééï ÷åáõ î÷åø áùåøú äô÷åãä
+% The compiler expects a source file name on the command line.
+option_no_option_found=11005_N_ìà öåéðå àôùøåéåú áúåê ÷åáõ ääâãøåú $1
+% The compiler didn't find any option in that config file.
+option_illegal_para=11006_E_ôøîèø ìà çå÷é: $1
+% You specified an unknown option.
+option_help_pages_para=11007_H_-? ëåúá ãôé òæøä
+% When an unknown option is given, this message is diplayed.
+option_too_many_cfg_files=11008_F_éåúø îéãé ÷áöé äâãøåú î÷åððéí
+% You can only nest up to 16 config files.
+option_unable_open_file=11009_F_ìà ðéúï ìôúåç àú ä÷åáõ $1
+% The option file cannot be found.
+option_reading_further_from=11010_D_÷åøà äâãøåú ðåñôåú î $1
+% Displayed when you have notes turned on, and the compiler switches
+% to another options file.
+option_target_is_already_set=11011_W_äîèøä ëáø äåâãøä ì: $1
+% Displayed if more than one \var{-T} option is specified.
+option_no_shared_lib_under_dos=11012_W_DOS àéðå úåîê áñôøéåú îùåúôåú, çåæø ìñôøéåú ñèèéåú
+% If you specify \var{-CD} for the \dos platform, this message is displayed.
+% The compiler supports only static libraries under \dos
+option_too_many_ifdef=11013_F_IF(N)DEF øáéí îéãé
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_too_many_endif=11014_F_ENDIF øáéí îéãé
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_too_less_endif=11015_F_úðàé ôúåç áñåó ä÷åáõ
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_no_debug_support=11016_W_îéãò ðéôåé ùâéàåú àéðå ðúîê áñåâ ÷åáõ äøéöä äîáå÷ù
+% It is possible to have a compiler executable that doesn't support
+% the generation of debugging info. If you use such an executable with the
+% \var{-g} switch, this warning will be displayed.
+option_no_debug_support_recompile_fpc=11017_H_ðñä ìäãø îçãù òí äîúâ -dGDB
+% It is possible to have a compiler executable that doesn't support
+% the generation of debugging info. If you use such an executable with the
+% \var{-g} switch, this warning will be displayed.
+option_obsolete_switch=11018_W_àúä îùúîù áîúâ äîéåùï $1
+% this warns you when you use a switch that is not needed/supported anymore.
+% It is recommended that you remove the switch to overcome problems in the
+% future, when the switch meaning may change.
+option_obsolete_switch_use_new=11019_W_àúä îùúîù áîúâ äîéåùï $1, äùúîù áîúâ $2 áî÷åí
+% this warns you when you use a switch that is not supported anymore. You
+% must now use the second switch instead.
+% It is recommended that you change the switch to overcome problems in the
+% future, when the switch meaning may change.
+option_switch_bin_to_src_assembler=11020_N_îòáéø àú äàåñó ìîöá áøéøú îçãì ùì ëúéáú îàñó
+% this notifies you that the assembler has been changed because you used the
+% -a switch which can't be used with a binary assembler writer.
+option_incompatible_asm=11021_W_äúåëï äðáçø ùì äassembler "$1" àéðå îúàéí ì "$2"
+option_asm_forced=11022_W_äúåëï ùì äîàñó "$1" ìà îñåâì ìéöåø ÷áöé àåáéé÷è, îùúîù áîàñó áøéøú äîçãì áî÷åí
+% The assembler output selected can not generate
+% object files with the correct format. Therefore, the
+% default assembler for this target is used instead.
+option_using_file=11026_T_÷åøà àôùøåéåú îä÷åáõ $1
+% Options are also read from this file
+option_using_env=11027_T_÷åøà àôùøåéåú îäñáéáä $1
+% Options are also read from this environment string
+option_handling_option=11028_D_îèôì áàôùøåú "$1"
+% Debug info that an option is found and will be handled
+option_help_press_enter=11029__*** ìçõ òì enter ***
+option_start_reading_configfile=11030_H_îúçéì á÷øéàú ÷åáõ ääâãøåú $1
+% Starting of config file parsing.
+option_end_reading_configfile=11031_H_ñéåí ÷øéàú ÷åáõ ääâãøåú $1
+% End of config file parsing.
+option_interpreting_option=11032_D_îôøù àú äàôùøåú "$1"
+option_interpreting_firstpass_option=11036_D_îôøù àú äîòáø äøàùåï òì äàôùøåú "$1"
+option_interpreting_file_option=11033_D_îôøù àú äâãøú ä÷åáõ "$1"
+option_read_config_file=11034_D_÷åøà àú ÷åáõ ääâãøåú "$1"
+option_found_file=11035_D_ðîöà ÷åáõ î÷åø áùí "$1"
+% Additional infos about options, displayed
+% when you have debug option turned on.
+option_code_page_not_available=11039_E_÷åã ãó ìà éãåò
+option_config_is_dir=11040_F_ðîöàä ñôøééä áî÷åí ÷åáõ ääâãøåú $1
+% Directories can not be used as configuration files.
+option_confict_asm_debug=11041_W_ñåâ äôìè ùì äîàñó ùðáçø "$1" àéðå éëåì ìéöåø îéãò òáåø ðéôåé ùâéàåú. îáèì ðéôåé ùâéàåú
+% The assembler output selected can not generate
+% debugging information, debugging option is therefore disabled.
+%\end{description}
+# EndOfTeX
+
+#
+# Logo (option -l)
+#
+option_logo=11023_[
+Free Pascal Compiler version $FPCFULLVERSION [$FPCDATE] for $FPCCPU
+Copyright (c) 1993-2011 by Florian Klaempfl
+]
+
+#
+# Info (option -i)
+#
+option_info=11024_[
+Free Pascal Compiler version $FPCVERSION
+
+úàøéê îäãø : $FPCDATE
+îäãø ìîòáã: $FPCCPU
+
+îòøëåú äôòìä ðúîëåú:
+ $OSTARGETS
+
+äåøàåú îòáã ðúîëåú:
+ $INSTRUCTIONSETS
+
+äåøàåú ðúîëåú ùì éçéãú ð÷åãä öôä:
+ $FPUINSTRUCTIONSETS
+
+úîéëú äîéèåá:
+ $OPTIMIZATIONS
+
+äúåëðä îåâùú úçú øéùéåï GNU General Public License
+ìîéãò ðåñó éù ì÷øåà àú COPYING.FPC
+
+ãéååç òì ú÷ìåú (áàâéí), äöòåú åëå':
+ http://bugs.freepascal.org
+
+ bugs@freepascal.org
+]
+
+#
+# Help pages (option -? and -h)
+#
+# The first character on the line indicates who will display this
+# line, the current possibilities are :
+# * = every target
+# 3 = 80x86 targets
+# 6 = 680x0 targets
+# e = in extended debug mode only
+# P = PowerPC targets
+# S = Sparc targets
+# V = Virtual machine targets
+# The second character also indicates who will display this line,
+# (if the above character was TRUE) the current possibilities are :
+# * = everyone
+# g = with GDB info supported by the compiler
+# O = OS/2
+# L = UNIX systems
+# The third character represents the indentation level.
+#
+option_help_pages=11025_[
+**0*_äåñó àú äñéîï + ìàçø àôùøåú îúâ áåìéàðé ìàôùø àú äàôùøåú, äåñó àú äñéîï - ìáèì àú äàôùøåú
+**1a_äîäãø àéðå îåç÷ àú ÷åáõ äassembler ùðåöø
+**2al_øåùí øùéîä ùì ùåøåú ÷åã î÷åø á÷åáõ äassembler
+**2an_øùéîú îéãò ùì öîúéí á÷åáõ äassembler
+*L2ap_äùúîù áöéðåøåú áî÷åí ÷áöé assembler æîðééí
+**2ar_øùéîä àåãåú øéùåí ùì ä÷öàä/ùçøåø á÷åáõ äassembler
+**2at_øùéîä æîðéú àåãåú ä÷öàä/ùçøåø á÷åáõ äassembler
+**1A<x>_úñãéøé ôìè:
+**2Adefault_äùúîù áîàñó áøéøú îçãì
+3*2Aas_àñåó òí GNU AS
+3*2Anasmcoff_÷åáõ COFF (Go32v2) áùéîåù òí Nasm
+3*2Anasmelf_÷åáõ ELF32 (Linux) áùéîåù òí Nasm
+3*2Anasmwin32_÷åáõ àåáéé÷è Win32 áùéîåù òí Nasm
+3*2Anasmwdosx_÷åáõ àåáéé÷è Win32/WDOSX áùéîåù òí Nasm
+3*2Awasm_÷åáõ obj áùéîåù òí Wasm (Watcom)
+3*2Anasmobj_÷åáõ obj áùéîåù òí Nasm
+3*2Amasm_÷åáõ obj áùéîåù òí Masm (Microsoft)
+3*2Atasm_÷åáõ obj áùéîåù Tasm (Borland)
+3*2Aelf_÷åáõ ELF32 (Linux) áùéîåù ëåúá ôðéîé
+3*2Acoff_÷åáõ OFF (Go32v2) áùéîåù ëåúá ôðéîé
+3*2Apecoff_÷åáõ pecoff (Win32) áùéîåù ëåúá ôðéîé
+4*2Aas_àñåó òí GNU AS
+6*2Aas_÷åáõ-o Unix áùéîåù GNU AS
+6*2Agas_GNU Motorola assembler
+6*2Amit_MIT Syntax (GAS éùï)
+6*2Amot_Motorola assembler ú÷ðé
+A*2Aas_àñåó òí GNU AS
+P*2Aas_àñåó òí GNU AS
+S*2Aas_àñåó òí GNU AS
+**1b_ééöø îéãò ìãôãåó
+**2bl_ééöø îéãò òì ñîìéí î÷åîééí
+**1B_áðä àú ëì äîåãåìéí
+**1C<x>_àôùøåéåú éöéøú ÷åã:
+**2Cc<x>_÷åáò îåñëîåú äôòìä áøéøú îçãì ì <ñ>
+**2CD_öåø âí ñôøééä ãéðàîéú (ìà ðúîê)
+**2Ce_îäãø òí äãîééä ùì opcodes äùééëéí ìð÷åãä öôä
+**2Cf<x>_áçø äåøàåú FPU ìùéîåù, øàä fpc -i ìòøëéí àôùøééí
+**2CF<x>_ãéå÷ ð÷åãä òùøåðéú ÷áåòä îéðéîìéú (default, 32, 64)
+**2Cg_öåø ÷åã PIC
+**2Ch<n>_ëîåú ùì <n> áúéí ì îöáåø (áéï 1023 å67107840)
+**2Ci_áãé÷ú IO
+**2Cn_äùîè îöá ÷éùåø
+**2Co_áãå÷ âìéùä ùì ôòåìåú îñôø ùìí
+**2CO_áãå÷ òáåø ôòåìåú âìéùä àôùøåéåú ùì îñôø ùìí
+**2Cp<x>_áçø ÷áåöú äåøàåú, øàä fpc -i ìòøëéí àôùøééí
+**2CP<x>=<y>_äâãøåú àøéæä
+**3CPPACKSET=<y>_ <y> îñãø ä÷öàä: 0, 1 àå DEFAULT àå NORMAL, 2, 4 å 8
+**2Cr_áãé÷ú èååç
+**2CR_ååãà ÷øéàä ú÷éðä ìîúåãä
+**2Cs<n>_÷áò âåãì îçñðéú ì <n>
+**2Ct_áãé÷ú îçñðéú
+**2CX_öåø âí ñôøééä ùì ÷éùåø çëí
+**1d<x>_îâãéø àú äñîì <x>
+**1D_éåöø ÷åáõ DEF
+**2Dd<x>_éåöø úàåø ì <x>
+**2Dv<x>_éåöø âøñú DLL ì <x>
+*O2Dw_éùåí PM
+**1e<x>_÷åáò ðúéá ì÷åáõ øéöä
+**1E_æää ì -Cn
+**1fPIC_æää ì -Cg
+**1F<x>_÷åáò ùí ÷áöéí åîé÷åîéí:
+**2Fa<x>[,y]_÷åãí èåòï àú äéçéãåú <x> å [y] øàùåðåú, ìôðé ðéúåç ùåøú ä uses
+**2Fc<x>_÷åáò ÷åã ãó ùì ÷ìè ì<x>
+**2FC<x>_÷áò ùí îäãø RC áéðàøé ì <x>
+**2FD<x>_÷åáò àú äñôøééä áä àôùø ìçôù àú ëìé äòæø ùì äîäãø
+**2Fe<x>_äôðä äåãòåú ùâéàä ì<x>
+**2Ff<x>_äåñó àú <x> ìðúéá äîñâøú (ø÷ á Darwin)
+**2FE<x>_äôðä ôìè ùì exe/unit ìðúéá <x>
+**2Fi<x>_îåñéó àú <x> ìøùéîú äðúéáéí
+**2Fl<x>_îåñéó àú <x> ìøùéîú äðúéáéí ùì äñôøéä
+**2FL<x>_îùúîù á<x> ëî÷ùø ãéðàîé
+**2Fm<x>_èåòï èáìú äîøä ùì éåðé÷åã îä÷åáõ x>.txt> îñôøééú äîäãø
+**2Fo<x>_îåñéó àú <x> ìøùéðú äðúéáéí ùì àåáéé÷è
+**2Fr<x>_èåòï ÷åáõ äåãòåú ùâéàä <x>
+**2FR<x>_÷áò î÷ùø ì÷åáõ res ì <x>
+**2Fu<x>_îåñéó àú <x> ìøùéîú äðúéáéí ùì éçéãä
+**2FU<x>_÷åáò àú äîé÷åí äôìè ùì äéçéãåú ì <x> åîùëúá àú -FE
+*g1g_éåöø îéãò ìðéôåé ùâéàåú
+*g2gc_éåöø áãé÷åú ìîöáéòéí
+*g2gh_äùúîù áéçéãä heaptrace (òáåø ãìéôåú æëøåï/áòéåú áðéôåé ùâéàåú)
+*g2gl_äùúîù áéçéãú îéãò ùì ùåøä ìäöéâ îéãò ðåñó ìbacktraces
+*g2go<x>_öåø àôùøåéåú ìðéôåé ùâéàåú
+*g3godwarfsets_àôùø îéãò ìðéäåì îéãò òáåø ðéôåé ùâéàåú ùì Dwarf (ùåáø àú gdb < 6.5)
+*g2gp_îùîø âåãì ùîåú ñîìé ästabs
+*g2gs_îééöø îéãò ìðéôåé ùâéàåú stub
+*g2gt_ìëìê îùúðéí î÷åîééí (ìæéäåé îéãò ìà îàåúçì)
+*g2gv_îééöø úåëðåú òí éëåìú îò÷á ùì valgrind
+*g2gw_îééöø îéãò ìðéôåé ùâéàåú ìdwarf
+*g2gw2_îéöø îéãò ìðéôåé ùâéàåú dwarf-2
+*g2gw3_îéöø îéãò ìðéôåé ùâéàåú dwarf-3
+**1i_îéãò
+**2iD_äöâ úàøéê äîäãø
+**2iV_äöâ âøñú äîäãø
+**2iW_äöâ âøñä îìàä ùì äîäãø
+**2iSO_äöâ îòøëú äôòìä ùì äîäãø
+**2iSP_äöâ âøñú îòáã ùì äîäãø
+**2iTO_äöâ àú äîèøä ùì îòøëú ääôòìä
+**2iTP_äöâ àú äîèøä ùì äîòáã
+**1I<x>_äåñó àú <x> ìøùéîú äðúéáéí ìäåñôä
+**1k<x>_äòáø àú <x> ìî÷ùø
+**1l_ëúåá ñîìéì
+**1M<x>_äâãø îöá ùôä ì <x>
+**2Mfpc_ãéàì÷è ùì Free Pascal (áøéøú îçãì)
+**2Mobjfpc_àôùø ëîä úåñôåú ùì Delphi 2
+**2Mdelphi_îðñä ìäéåú úåàí Delphi
+**2Mtp_îðñä ìäéåú úåàí ì TP/BP 7.0
+**2Mmacpas_îðñä ìäéåú úåàí ììäâ ùì Macintosh Pascal
+**1n_àì ú÷øà àú ÷åáõ äâãøåú áøéøú äîçãì
+**1N<x>_îéèåá öîúé òõ
+**2Nu_ìâåìì ìåìàåú
+**1o<x>_ùðä àú ùí ÷åáõ äøéöä ùäú÷áì ì <x>
+**1O<x>_îéèåáéí:
+**2O-_áèì îéèåá
+**2O1_îéèåá øîä 1 (îäéø åèåá ìðéôåé ùâéàåú)
+**2O2_îéèåá øîä 2 (-O1 + îéèåá îäéø)
+**2O3_îéèåá øîä 3 (-O2 + îéèåá àéèé)
+**2Oa<x>=<y>_÷áò ééùåø
+**2Oo[NO]<x>_ò"î ìàôùø àå ìàôùø îéèåáéí, øàä fpc -i ìàôùøåéåú
+**2Op<x>_ì÷áéòú îéèåá ìîòáã ðáçø, øàä fpc -i ìàôùøåéåú
+**2Os_öåø ÷åã ÷èï
+**1pg_öåø ÷åã ôøåôéì òáåø gprof (îâãéø àú FPC_PROFILE)
+**1R<x>_ñâðåï ÷øéàú äàñó:
+**2Rdefault_äùúîù áîàñó áøéøú îçãì
+3*2Ratt_÷øà ñâðåï î÷ùø ùì AT&T
+3*2Rintel_÷øà ñâðåï î÷ùø ùì Intel
+6*2RMOT_÷øà ñâðåï î÷ùø ùì Motorola
+**1S<x>_àôùøåéåú úçáéø:
+**2S2_æää ì -Mobjfpc
+**2Sc_úåîê àåôøèåøéí áñâðåï C (*=, +=, /= å -=)
+**2Sa_äåñó ÷åã èòðú úðàé ÷áéòä (assertion)
+**2Sd_æää ì -Mdelphi
+**2Se<x>_àôùøåéåú ùâéàä. <x> äéðå äùéìåá äáà:
+**3*_<n> : äîäãø òåöø ìàçø <n> ùâéàåú (áøéøú îçãì äéà 1)
+**3*_w : äîäãø òåöø âí ìàçø àæäøåú
+**3*_n : äîäãø òåöø ìàçø äòøåú
+**3*_h : äîäãø òåöø ìàçø øîæéí
+**2Sg_àôùø LABEL å GOTO
+**2Sh_äùúîù á ansistrings
+**2Si_úîåê áñâðåï C++ ùì INLINE
+**2Sk_èòï àú äéçéãä fpcylix
+**2SI<x>_÷áò ñâðåï îîù÷ ì<x>
+**3SIcom_úåàí îîù÷é COM (áøéøú îçãì)
+**3SIcorba_úåàí îîù÷é CORBA
+**2Sm_úîåê áî÷øå ãåîéí ìC (âìåáìééí)
+**2So_æää ì -Mtp
+**2Ss_ùí éåöø çééá ìäéåú init (ùí äåøñ çééá ìäéåú done)
+**2Sx_àôùø îéìåú îôúç ìexception (áøéøú îçãì áîöáé Delphi/ObjFPC)
+**1s_àì ú÷øà ìîàñó åäî÷ùø
+**2sh_öåø úñøéè ì÷éùåø áîàøç
+**2st_öåø úñøéè ì÷éùåø áîèøä
+**2sr_ãìâ òì øéùåí ä÷öàú îåôò (äùúîù áééçã òí -alr)
+**1T<x>_îèøú îòøëú ääôòìä:
+3*2Temx_OS/2 áùéîåù EMX ( áééçã òí äøçáú EMX/RSX)
+3*2Tfreebsd_FreeBSD
+3*2Tgo32v2_âøñä 2 ùì äøçáú DJ Delorie DOS
+3*2Tlinux_Linux
+3*2Tnetbsd_NetBSD
+3*2Tnetware_Novell Netware Module (clib)
+3*2Tnetwlibc_Novell Netware Module (libc)
+3*2Topenbsd_OpenBSD
+3*2Tos2_OS/2 / eComStation
+3*2Tsunos_SunOS/Solaris
+3*2Twatcom_Watcom úåàí äøçáú DOS
+3*2Twdosx_WDOSX äøçáú DOS
+3*2Twin32_Windows 32 ñéáéåú
+3*2Twince_Windows CE
+4*2Tlinux_Linux
+6*2Tamiga_Commodore Amiga
+6*2Tatari_Atari ST/STe/TT
+6*2Tlinux_Linux/m68k
+6*2Tmacos_Macintosh m68k (ìà ðúîê)
+6*2Tpalmos_PalmOS
+A*2Tlinux_Linux
+A*2Twince_Windows CE
+P*2Tamiga_AmigaOS òì PowerPC
+P*2Tdarwin_Darwin å Mac OS X òì PowerPC
+P*2Tlinux_Linux òì PowerPC
+P*2Tmacos_Mac OS (÷ìàñé) òì PowerPC
+P*2Tmorphos_MorphOS
+S*2Tlinux_Linux
+**1u<x>_îñéø àú ääâãøä ùì äñîì <x>
+**1U_äâãøåú éçéãä:
+**2Un_àì úáãå÷ àú ùí äéçéãä
+**2Ur_öåø ÷áöé ùçøåø ùì éçéãåú
+**2Us_äãø àú éçéãú äsystem
+**1v<x>_úäéä îôåøè éåúø. <x> äéðå ùéìåá ùì äúååéí äáàéí:
+**2*_e : äöâ äåãòåú ùâéàä (áøéøú îçãì)
+**2*_0 : àì úöéâ ëìåí (ìîòè äåãòåú ùâéàä)
+**2*_w : äöâ àæäøåú
+**2*_u : äöâ îéãò òì éçéãä
+**2*_n : äöâ äòøåú
+**2*_t : äöâ ÷áöéí ùäéå áùéîåù
+**2*_h : äöâ øîæéí
+**2*_c : äöâ úðàéí
+**2*_i : äöâ îéãò ëììé
+**2*_d : äöâ îéãò ìðôåé ùâéàåú
+**2*_l : äöâ îñôøé ùåøåú
+**2*_r : îöá úåàí Rhide/GCC
+**2*_a : äöâ äëåì
+**2*_x : äöâ îéãò òì ÷åáõ äøéöä (ø÷ áWin32)
+**2*_b : ëúåá äåãòåú òí ùîåú ÷áöéí åðúéáéí îìàéí
+**2*_v : ëúåá àú ä÷åáõ fpcdebug.txt òí äøáä îéãò òì ðéôåé ùâéàåú
+**2*_p : ëúåá àú ä÷åáõ tree.log òí ðéúåç òõ
+3*1W<x>_àôùøåú îáåññú îèøä (îèøåú)
+A*1W<x>_àôùøåú îáåññú îèøä (îèøåú)
+P*1W<x>_àôùøåú îáåññú îèøä (îèøåú)
+3*2Wb_öåø çáéìä áî÷åí ñôøééä (Darwin)
+P*2Wb_öåø çáéìä áî÷åí ñôøééä (Darwin)
+p*2Wb_öåø çáéìä áî÷åí ñôøééä (Darwin)
+3*2WB_öåø úîåðä äðéúðú ìîé÷åí îçåãù (Windows)
+A*2WB_öåø úîåðä äðéúðú ìîé÷åí îçåãù (Windows, Symbian)
+3*2WC_îöééï àôìé÷öéä îñåâ îñåó (EMX, OS/2, Windows)
+A*2WC_îöééï àôìé÷öéä îñåâ îñåó (Windows)
+P*2WC_îöééï àôìé÷öéä îñåâ îñåó (Classic Mac OS)
+3*2WD_äùúîù á DEFFILE ìééöà ôð÷öéåú ùì DLL àå EXE (Windows)
+A*2WD_äùúîù á DEFFILE ìééöà ôð÷öéåú ùì DLL àå EXE (Windows)
+3*2WF_îöééï àôìé÷öéä îñåâ îñê îìà (EMX, OS/2)
+3*2WG_îöééï àôìé÷öéä îñåâ âøôé (EMX, OS/2, Windows)
+A*2WG_îöééï àôìé÷öéä îñåâ âøôé (Windows)
+P*2WG_îöééï àôìé÷öéä îñåâ âøôé (Classic Mac OS)
+3*2WN_àì úöåø ÷åã îùðä îé÷åí, ðãøù òáåø ðéôåé ùâéàåú (Windows)
+A*2WN_àì úöåø ÷åã îùðä îé÷åí, ðãøù òáåø ðéôåé ùâéàåú (Windows)
+3*2WR_úéöåø ÷åã îùðä îé÷åí (Windows)
+A*2WR_úéöåø ÷åã îùðä îé÷åí (Windows)
+P*2WT_öééï àôìé÷öéä îñåâ ëìé MPW (Classic Mac OS)
+**1X_äâãøåú øéöä:
+**2Xc_äòáø --shared/-dynamic ìî÷ùø (BeOS, Darwin, FreeBSD, Linux)
+**2Xd_àì úùúîù áðúéá çéôåù äñôøéåú äñèðãøèéåú (ðãøù òáåø äéãåø ìàøëéè÷èåøåú àçøåú)
+**2Xe_äùúîù áî÷ùø çéöåðé
+**2XD_ðñä ì÷ùø éçéãåú áöåøä ãéðàîéú (îâãéø FPC_LINK_DYNAMIC)
+**2Xi_äùúîù áî÷ùø ôðéîé
+**2Xm_öåø îôú ÷éùåøéí
+**2XM<x>_äâãø àú äùí ùì øåèéðä ä'òé÷øéú' ùì äúåëðä (áøéøú îçãì äåà 'main')
+**2XP<x>_öøó àú äùîåú äîâéòéí òí äúçéìéú <x> îbinutils
+**2Xr<x>_äâãø àú ðúéá çéôåù äñôøéåú ì <x> (ðãøù òáåø äéãåø ìàøëéè÷èåøåú àçøåú) (BeOS, Linux)
+**2XR<x>_öøó àú <x> ìëì ðúéáé äçéôåù ùì äî÷ùø (BeOS, Darwin, FreeBSD, Linux, Mac OS, Solaris)
+**2Xs_ð÷ä àú ëì äñîìéí î÷áöé ääøöä
+**2XS_ðñä ì÷ùø éçéãåú áöåøä ñèèéú (áøéøú îçãì, îâãéø FPC_LINK_STATIC)
+**2Xt_÷ùø òí ñôøéåú ñèèéåú (îòáéø -static ìî÷ùø)
+**2XX_úðñä ìáöò smartlink ìéçéãåú (îâãéø FPC_LINK_SMART)
+**1*_
+**1?_äöâ àú òæøä æå
+**1h_äöâ òæøä æå ììà ìçëåú
+
+]
+
+#
+# The End...
diff --git a/closures/compiler/msg/errorheu.msg b/closures/compiler/msg/errorheu.msg
new file mode 100644
index 0000000000..16afb09bb0
--- /dev/null
+++ b/closures/compiler/msg/errorheu.msg
@@ -0,0 +1,2708 @@
+#
+# This file is part of the Free Pascal Compiler
+# Copyright (c) 1999-2008 by the Free Pascal Development team
+#
+# Hebrew (UTF8) language file for Free Pascal Compiler
+# Contributed by Ido Kanner <idokan at gmail.com> and Dotan Kamber <kamberd at yahoo.com>
+# Based on errore.msg of SVN revision 8988
+#
+# See the file COPYING.FPC, included in this distribution,
+# for details about the copyright.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#
+#
+# The constants are build in the following order:
+# <part>_<type>_<txtidentifier>
+#
+# <part> is the part of the compiler the message is used
+# asmr_ assembler parsing
+# asmw_ assembler writing/binary writers
+# unit_ unit handling
+# scan_ scanner
+# parser_ parser
+# type_ type checking
+# general_ general info
+# exec_ calls to assembler, linker, binder
+#
+# <type> the type of the message it should normally used for
+# f_ fatal error
+# e_ error
+# w_ warning
+# n_ note
+# h_ hint
+# i_ info
+# l_ add linenumber
+# u_ used
+# t_ tried
+# c_ conditional
+# d_ debug message
+# x_ executable informations
+#
+
+#
+# General
+#
+# 01023 is the last used one
+#
+# BeginOfTeX
+% \section{General compiler messages}
+% This section gives the compiler messages which are not fatal, but which
+% display useful information. The number of such messages can be
+% controlled with the various verbosity level \var{-v} switches.
+% \begin{description}
+general_t_compilername=01000_T_מהדר: $1
+% When the \var{-vt} switch is used, this line tells you what compiler
+% is used.
+general_d_sourceos=01001_D_מערכת הפעלה: $1
+% When the \var{-vd} switch is used, this line tells you what the source
+% operating system is.
+general_i_targetos=01002_I_מערכת הפעלה מיועדת: $1
+% When the \var{-vd} switch is used, this line tells you what the target
+% operating system is.
+general_t_exepath=01003_T_משתמש בנתיב הרצה: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for its binaries.
+general_t_unitpath=01004_T_משתמש בנתיב היחידות: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for compiled units. You can set this path with the \var{-Fu}
+general_t_includepath=01005_T_משתמש בנתיב המוסף: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for its include files (files used in \var{\{\$I xxx\}} statements).
+% You can set this path with the \var{-I} option.
+general_t_librarypath=01006_T_משתמש בנתיב הספריה: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for the libraries. You can set this path with the \var{-Fl} option.
+general_t_objectpath=01007_T_Using object path: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for object files you link in (files used in \var{\{\$L xxx\}} statements).
+% You can set this path with the \var{-Fo} option.
+general_i_abslines_compiled=01008_I_$1 שורות הודרו, ב$2 שניות
+% When the \var{-vi} switch is used, the compiler reports the number
+% of lines compiled, and the time it took to compile them (real time,
+% not program time).
+general_f_no_memory_left=01009_F_×œ× × ×©×ר זכרון
+% The compiler doesn't have enough memory to compile your program. There are
+% several remedies for this:
+% \begin{itemize}
+% \item If you're using the build option of the compiler, try compiling the
+% different units manually.
+% \item If you're compiling a huge program, split it up in units, and compile
+% these separately.
+% \item If the previous two don't work, recompile the compiler with a bigger
+% heap (you can use the \var{-Ch} option for this, \seeo{Ch})
+% \end{itemize}
+general_i_writingresourcefile=01010_I_כותב ×ת קובץ מש×בי טבלת המחרוזות: $1
+% This message is shown when the compiler writes the Resource String Table
+% file containing all the resource strings for a program.
+general_e_errorwritingresourcefile=01011_E_כותב ×ת קובץ מש×בי טבלת המחרוזות: $1
+% This message is shown when the compiler encountered an error when writing
+% the Resource String Table file
+general_i_fatal=01012_I_שגי××” קריטית:
+% Prefix for Fatal Errors
+general_i_error=01013_I_שגי××”:
+% Prefix for Errors
+general_i_warning=01014_I_התר××”:
+% Prefix for Warnings
+general_i_note=01015_I_הערה:
+% Prefix for Notes
+general_i_hint=01016_I_רמז:
+% Prefix for Hints
+general_e_path_does_not_exist=01017_E_הנתיב "$1" ×ינו קיי×
+% The specified path does not exist.
+general_f_compilation_aborted=01018_F_ההידור בוטל
+% Compilation was aborted.
+general_text_bytes_code=01019_bytes code
+general_text_bytes_data=01020_bytes data
+general_i_number_of_warnings=01021_I_×זהרות $1 הונפקו
+% Total number of warnings issued during compilation.
+general_i_number_of_hints=01022_I_הונפקו $1 רמזי×
+% Total number of hints issued during compilation.
+general_i_number_of_notes=01023_I_הונפקו $1 הערות
+% Total number of notes issued during compilation.
+% \end{description}
+#
+# Scanner
+#
+# 02084 is the last used one
+#
+% \section{Scanner messages.}
+% This section lists the messages that the scanner emits. The scanner takes
+% care of the lexical structure of the pascal file, i.e. it tries to find
+% reserved words, strings, etc. It also takes care of directives and
+% conditional compiling handling.
+% \begin{description}
+scan_f_end_of_file=02000_F_סוף קובץ ×œ× ×¦×¤×•×™
+% this typically happens in one of the following cases :
+% \begin{itemize}
+% \item The source file ends before the final \var{end.} statement. This
+% happens mostly when the \var{begin} and \var{end} statements aren't
+% balanced;
+% \item An include file ends in the middle of a statement.
+% \item A comment was not closed
+% \end{itemize}
+scan_f_string_exceeds_line=02001_F_מחרוזת גולשת משורה
+% There is a missing closing ' in a string, so it occupies
+% multiple lines.
+scan_f_illegal_char=02002_F_תו ×œ× ×—×•×§×™ "$1" ($2)
+% An illegal character was encountered in the input file.
+scan_f_syn_expected=02003_F_שגי×ת תחביר: מצפה ל "$1" ×בל "$2" נמצ×
+% This indicates that the compiler expected a different token than
+% the one you typed. It can occur almost everywhere where you make a
+% mistake against the pascal language.
+scan_t_start_include_file=02004_TL_מתחיל קרי××” של קובץ תוספות $1
+% When you provide the \var{-vt} switch, the compiler tells you
+% when it starts reading an included file.
+scan_w_comment_level=02005_W_רמת הערות $1 נמצ××”
+% When the \var{-vw} switch is used, then the compiler warns you if
+% it finds nested comments. Nested comments are not allowed in Turbo Pascal
+% and can be a possible source of errors.
+scan_n_ignored_switch=02008_N_×ž×ª×¢×œ× ×ž×ž×ª×’ מהדר "$1"
+% With \var{-vn} on, the compiler warns if it ignores a switch
+scan_w_illegal_switch=02009_W_מתג מהדר "$1" ×ינו חוקי
+% You included a compiler switch (i.e. \var{\{\$... \}}) which the compiler
+% does not recognise
+scan_w_switch_is_global=02010_W_×ž×™×§×•× ×©×’×•×™ למתג מהדר גלובלי
+% The compiler switch is misplaced, and should be located at
+% the start of the unit or program.
+scan_e_illegal_char_const=02011_E_תו קבוע ×œ× ×—×•×§×™
+% This happens when you specify a character with its ASCII code, as in
+% \var{\#96}, but the number is either illegal, or out of range.
+scan_f_cannot_open_input=02012_F_×œ× × ×™×ª×Ÿ לפתוח ×ת קובץ "$1"
+% \fpc cannot find the program or unit source file you specified on the
+% command line.
+scan_f_cannot_open_includefile=02013_F_×œ× × ×™×ª×Ÿ לפתוח ×ת קובץ התוספות "$1"
+% \fpc cannot find the source file you specified in a \var{\{\$include ..\}}
+% statement.
+scan_e_illegal_pack_records=02015_E_יישור רשומה ×œ× ×—×•×§×™ מייצג "$1"
+% You are specifying the \var{\{\$PACKRECORDS n\} } or \var{\{\$ALIGN n\} }
+% with an illegal value for \var{n}. For \$PACKRECORDS valid alignments are 1, 2, 4, 8, 16, 32, C,
+% NORMAL, DEFAULT, and for \$ALIGN valid alignment are 1, 2, 4, 8, 16, 32, ON,
+% OFF. Under mode MacPas \$ALIGN also supports MAC68K, POWER and RESET.
+scan_e_illegal_pack_enum=02016_E_מספר מינימלי של מנייה המייצג "$1" ×ינו חוקי
+% You are specifying the \var{\{\$PACKENUM n\}} with an illegal value for
+% \var{n}. Only 1,2,4, NORMAL or DEFAULT are valid here.
+scan_e_endif_expected=02017_E_מצפה ל$ENDIF בהגדרה $1 $2 הנמצ×ת ב$3 שורה $4
+% Your conditional compilation statements are unbalanced.
+scan_e_preproc_syntax_error=02018_E_שגי×ת תחביר בעת ניתוח משפט תנ××™
+% There is an error in the expression following the \var{\{\$if ..\}}, $ifc or $setc compiler
+% directives.
+scan_e_error_in_preproc_expr=02019_E_הערכת משפט תנ××™
+% There is an error in the expression following the \var{\{\$if ..\}}, $ifc or $setc compiler
+% directives.
+scan_w_macro_cut_after_255_chars=02020_W_תוכן המקרו מוגבל ל×ורך של 255 תווי×
+% The contents of macros cannot be longer than 255 characters.
+scan_e_endif_without_if=02021_E_ENDIF ×œ×œ× IF(N)DEF
+% Your \var{\{\$IFDEF ..\}} and {\{\$ENDIF\}} statements aren't balanced.
+scan_f_user_defined=02022_F_הגדרת משתמש: $1
+% A user defined fatal error occurred. see also the \progref
+scan_e_user_defined=02023_E_הגדרת משתמש: $1
+% A user defined error occurred. see also the \progref
+scan_w_user_defined=02024_W_הגדרת משתמש: $1
+% A user defined warning occurred. see also the \progref
+scan_n_user_defined=02025_N_הגדרת משתמש: $1
+% A user defined note was encountered. see also the \progref
+scan_h_user_defined=02026_H_הגדרת משתמש: $1
+% A user defined hint was encountered. see also the \progref
+scan_i_user_defined=02027_I_הגדרת משתמש: $1
+% User defined information was encountered. see also the \progref
+scan_e_keyword_cant_be_a_macro=02028_E_מילת מפתח המוגדרת מחדש כמקרו ××™× ×” מכילה השפעה
+% You cannot redefine keywords with macros.
+scan_f_macro_buffer_overflow=02029_F_גלישת מ×גר מקרו בעת קרי××” ×ו הרחבה של מקרו
+% Your macro or its result was too long for the compiler.
+scan_w_macro_too_deep=02030_W_הרחבת מקרו גולשת מעומק של 16.
+% When expanding a macro, macros have been nested to a level of 16.
+% The compiler will expand no further, since this may be a sign that
+% recursion is used.
+scan_w_wrong_styled_switch=02031_W_ מתגי פעולת מהדר ××™× × × ×ª×ž×›×™× ×‘×”×¢×¨×•×ª מסוג //
+% Compiler switches should be in normal pascal style comments.
+scan_d_handling_switch=02032_DL_מטפל במתג "$1"
+% When you set debugging info on (\var{-vd}) the compiler tells you when it
+% is evaluating conditional compile statements.
+scan_c_endif_found=02033_CL_× ×ž×¦× ENDIF $1
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifdef_found=02034_CL_× ×ž×¦× IFDEF $1, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifopt_found=02035_CL_× ×ž×¦× IFOPT $1, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_if_found=02036_CL_× ×ž×¦× IF $1, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifndef_found=02037_CL_× ×ž×¦× IFNDEF $1, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_else_found=02038_CL_× ×ž×¦× ELSE $1, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_skipping_until=02039_CL_מדלג...
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements, and whether it is skipping or
+% compiling parts.
+scan_i_press_enter=02040_I_לחץ על <return> להמשיך
+% When the \var{-vi} switch is used, the compiler stops compilation
+% and waits for the \var{Enter} key to be pressed when it encounters
+% a \var{\{\$STOP\}} directive.
+scan_w_unsupported_switch=02041_W_מתג "$1" ×ינו נתמך
+% When warnings are turned on (\var{-vw}) the compiler warns you about
+% unsupported switches. This means that the switch is used in Delphi or
+% Turbo Pascal, but not in \fpc
+scan_w_illegal_directive=02042_W_הור×ת המהדר "$1" ××™× ×” חוקית
+% When warings are turned on (\var{-vw}) the compiler warns you about
+% unrecognised switches. For a list of recognised switches, \progref
+scan_t_back_in=02043_TL_חזרה ב$1
+% When you use (\var{-vt}) the compiler tells you when it has finished
+% reading an include file.
+scan_w_unsupported_app_type=02044_W_×ין תמיכה לסוג ×”×פליקציה: "$1"
+% You get this warning, if you specify an unknown application type
+% with the directive \var{\{\$APPTYPE\}}
+scan_w_app_type_not_support=02045_W_APPTYPE ×ינו נתמך ×¢"×™ ההמערכת הפעלה המבוקשת
+% The \var{\{\$APPTYPE\}} directive is supported by certain operating systems only.
+scan_w_description_not_support=02046_W_DESCRIPTION ×ינו נתמך ×¢"×™ מערכת ההפעלה המבוקשת
+% The \var{\{\$DESCRIPTION\}} directive is not supported on this target OS
+scan_n_version_not_support=02047_N_VERSION ×ינו נתמך ×¢"×™ מערכת הפעלה המבוקשת
+% The \var{\{\$VERSION\}} directive is not supported on this target OS
+scan_n_only_exe_version=02048_N_VERSION רק לקבצי exe ×ו DLL
+% The \var{\{\$VERSION\}} directive is only used for executable or DLL sources.
+scan_w_wrong_version_ignored=02049_W_פורמט שגוי להור×ת VERSION: "$1"
+% The \var{\{\$VERSION\}} directive format is majorversion.minorversion
+% where majorversion and minorversion are words.
+scan_e_illegal_asmmode_specifier=02050_E_סגנון ×”×סמבלר שצויין "$1" ×ינו חוקי
+% When you specify an assembler mode with the \var{\{\$ASMMODE xxx\}}
+% the compiler didn't recognize the mode you specified.
+scan_w_no_asm_reader_switch_inside_asm=02051_W_מתג ×§×•×¨× ×”ASM ×ינו ×פשרי בתוך משפט ×סמבלי. "$1" ×™×”×™×” ישפיע רק בהכרזה הב××”/
+% It is not possible to switch from one assembler reader to another
+% inside an assembler block. The new reader will be used for next
+% assembler statements only.
+scan_e_wrong_switch_toggle=02052_E_שימוש שגוי במתג. השתמש בON/OFF ×ו ב +/-
+% You need to use ON or OFF or a + or - to toggle the switch
+scan_e_resourcefiles_not_supported=02053_E_קובץ המש××‘×™× ×ינו נתמך ביעד הנבחר
+% The target you are compiling for doesn't support resource files.
+scan_w_include_env_not_found=02054_W_משתנה הסביבה "$1" ×œ× × ×ž×¦× ×‘×¡×‘×™×‘×”
+% The included environment variable can't be found in the environment, it will
+% be replaced by an empty string instead.
+scan_e_invalid_maxfpureg_value=02055_E_ערך ×œ× ×—×•×§×™ להגבלות ×וגר ×”FPC
+% Valid values for this directive are 0..8 and NORMAL/DEFAULT
+scan_w_only_one_resourcefile_supported=02056_W_רק קובץ מש××‘×™× ×חד נתמך ביעד ×–×”
+% The target you are compiling for supports only one resource file.
+% The first resource file found is used, the others are discarded.
+scan_w_macro_support_turned_off=02057_W_התמיכה במקרו כובה
+% A macro declaration has been found, but macro support is currently off,
+% so the declaration will be ignored. To turn macro support on compile with
+% -Sm on the commandline or add \{\$MACRO ON\} in the source
+scan_e_invalid_interface_type=02058_E_הוכרז סוג ממשק ×œ× ×—×•×§×™. הגדרות חוקיות ×”× COM, CORBA ×ו DEFAULT
+% The interface type that was specified is not supported
+scan_w_appid_not_support=02059_W_APPID נתמך רק בPALMOS
+% The \var{\{\$APPID\}} directive is only supported for the PalmOS target.
+scan_w_appname_not_support=02060_W_APPNAME נתמך רק בPALMOS
+% The \var{\{\$APPNAME\}} directive is only supported for the PalmOS target.
+scan_e_string_exceeds_255_chars=02061_E_מחרוזת קבועה ×œ× ×™×›×•×œ×” להיות מעל 255 תווי×
+% A single string constant can contain at most 255 chars. Try splitting up the
+% string in multiple smaller parts and concatenate them with a + operator.
+scan_f_include_deep_ten=02062_F_הוספת קבצי הinclude גלש מעומק ה16
+% When including include files the files have been nested to a level of 16.
+% The compiler will expand no further, since this may be a sign that
+% recursion is used.
+scan_e_too_many_push=02063_F_יותר מידי שכבות PUSH
+% A maximum of 20 levels is allowed. This error occurs only in mode MacPas.
+scan_e_too_many_pop=02064_E_POP ×œ×œ× ×©×—×¨×•×¨ של PUSH
+% This error occurs only in mode MacPas.
+scan_e_error_macro_lacks_value=02065_E_מקרו "$1" ×œ× ×ž×›×™×œ ערכי×
+% Thus the conditional compile time expression cannot be evaluated.
+scan_e_wrong_switch_toggle_default=02066_E_שימוש במתג שגוי, השתמש ב ON/OFF/DEFAULT ×ו ב+/-/*
+% You need to use ON or OFF or DEFAULT or a + or - or * to toggle the switch
+scan_e_mode_switch_not_allowed=02067_E_מצב מתג "$1" ×œ× ×ž×•×¨×©×”
+% A mode switch has already been encountered, or, in case of option -Mmacpas,
+% a mode switch occur after UNIT.
+scan_e_error_macro_undefined=02068_E_משתנה זמן הידור "$1" ×œ× ×”×•×’×“×¨.
+% Thus the conditional compile time expression cannot be evaluated. Only in mode MacPas.
+scan_e_utf8_bigger_than_65535=02069_E_× ×ž×¦× ×§×•×“ UTF-8 גבוהה יותר מ65535
+% \fpc handles utf-8 strings internally as widestrings e.g. the char codes are limited to 65535
+scan_e_utf8_malformed=02070_E_מחרוזת UTF-8 תקולה
+% The given string isn't a valid UTF-8 string
+scan_c_switching_to_utf8=02071_C_UTF-8 signature found, using UTF-8 encoding
+% The compiler found an UTF-8 encoding signature (\$ef, \$bb, \$bf) at the beginning of a file,
+% so it interprets it as an UTF-8 file
+scan_e_compile_time_typeerror=02072_E_ביטוי בזמן הידור: נדרש $1 ×בל התקבל $2 ב$3
+% Type check of a compile time expression failed.
+scan_n_app_type_not_support=02073_N_APPTYPE ×œ× × ×ª×ž×š במערכת ההפעלה המבוקשת
+% The \var{\{\$APPTYPE\}} directive is supported by certain operating systems only.
+scan_e_illegal_optimization_specifier=02074_E_סופק מיטוב ×œ× ×—×•×§×™ "$1"
+% When you specify an optimization with the \var{\{\$OPTIMIZATION xxx\}}
+% the compiler didn't recognize the optimization you specified.
+scan_w_setpeflags_not_support=02075_W_SETPEFLAGS ×ינו נתמך במערכת ההפעלה המבוקשת
+% The \var{\{\$SETPEFLAGS\}} directive is not supported by the target OS
+scan_w_imagebase_not_support=02076_W_IMAGEBASE ×ינו נתמך על ידי מערכת ההפעלה המבוקשת
+% The \var{\{\$IMAGEBASE\}} directive is not supported by the target OS
+scan_w_minstacksize_not_support=02077_W_MINSTACKSIZE ×ינו נתמך על ידי מערכת ההפעלה המבוקשת
+% The \var{\{\$MINSTACKSIZE\}} directive is not supported by the target OS
+scan_w_maxstacksize_not_support=02078_W_MAXSTACKSIZE ×ינו נתמך על ידי מערכת ההפעלה המבוקשת
+% The \var{\{\$MAXSTACKSIZE\}} directive is not supported by the target OS
+scanner_e_illegal_warn_state=02079_E_שימוש ×œ× ×—×•×§×™ בהנחית $WARN
+% Only ON and OFF can be used as state with a \$warn compiler directive
+scan_e_only_packset=02080_E_ערך של ×ריזה ×œ× ×—×•×§×™
+% Only 0, 1, 2, 4, 8, DEFAULT and NORMAL are allowed as packset parameter
+scan_w_pic_ignored=02081_W_×ž×ª×¢×œ× ×ž×”×•×¨×ת PIC
+% Several targets like windows do not support neither need PIC so the PIC directive and switch are
+% ignored.
+scan_w_unsupported_switch_by_target=02082_W_המתג "$1" ×ינו נתמך בסוג תוצ××” שנבחר
+% Some compiler switches like \$E are not supported by all targets.
+scan_w_frameworks_darwin_only=02084_W_×פשרויות מבוססות מסגרת נתמכות רק עבור Darwin/Mac OS X
+% Frameworks are not a known concept, or at least not supported by FPC, on operating systems other than Darwin/Mac OS X.
+scan_e_illegal_minfpconstprec=02085_E_דיוק הערך הקבוע של הנקודה העשרונית המינימלית "$1" ×ינו חוקי
+% Valid minimal precisions for floating point constants are default, 32 and 64, which mean respectively minimal (usually 32 bit), 32 bit and 64 bit precision.
+% \end{description}
+#
+# Parser
+#
+# 03192 is the last used one
+#
+% \section{Parser messages}
+% This section lists all parser messages. The parser takes care of the
+% semantics of you language, i.e. it determines if your pascal constructs
+% are correct.
+% \begin{description}
+parser_e_syntax_error=03000_E_מפרש - שגי××” תחבירית
+% An error against the Turbo Pascal language was encountered. This happens
+% typically when an illegal character is found in the sources file.
+parser_e_dont_nest_interrupt=03004_E_פרוצדורת פסיקה ××™× ×” יכולה להיות מקוננת
+% An \var{INTERRUPT} procedure must be global.
+parser_w_proc_directive_ignored=03005_W_×ž×ª×¢×œ× ×ž×¡×•×’ פרוצדורה "$1"
+% The specified procedure directive is ignored by FPC programs.
+parser_e_no_overload_for_all_procs=03006_E_×œ× ×›×œ ההכזרות של "$1" בעלות הכרזת OVERLOAD
+% When you want to use overloading using the \var{OVERLOAD} directive, then
+% all declarations need to have \var{OVERLOAD} specified.
+parser_e_export_name_double=03008_E_כפילויות ×‘×™×™×¦×•× ×©× ×”×¤×•× ×§×¦×™×” "$1"
+% Exported function names inside a specific DLL must all be different
+parser_e_export_ordinal_double=03009_E_כפילויות ×‘×™×™×¦×•× ×ינדקס הפונקציה "$1"
+% Exported function names inside a specific DLL must all be different
+parser_e_export_invalid_index=03010_E_×ינדקס ×œ× ×ª×§×™×Ÿ ×œ×™×™×¦×•× ×”×¤×•× ×§×¦×™×”
+% DLL function index must be in the range \var{1..\$FFFF}
+parser_w_parser_reloc_no_debug=03011_W_שינוי ×ž×™×§×•× × ×ª×•× ×™ הניפוי ×œ× ×¢×•×‘×“×™× ×œ×§×‘×¦×™ DLL ×ו קבצי הרצה. התבטל.
+parser_w_parser_win32_debug_needs_WN=03012_W_ל×פשר ניפוי שגי×ות לwin32 יש לבטל ×ת שינוי ×”×ž×™×§×•× ×¢"×™ ×”×פשרות -WN
+% Stabs info is wrong for relocatable DLL or EXES use -WN
+% if you want to debug win32 executables.
+parser_e_constructorname_must_be_init=03013_E_×©× ×™×•×¦×¨ חייב להיות INIT
+% You are declaring an object constructor with a name which is not \var{init}, and the
+% \var{-Ss} switch is in effect. See the \var{-Ss} switch (\seeo{Ss}).
+parser_e_destructorname_must_be_done=03014_E_×©× ×”×•×¨×¡ חייב להיות DONE
+% You are declaring an object destructor with a name which is not \var{done}, and the
+% \var{-Ss} switch is in effect. See the \var{-Ss} switch (\seeo{Ss}).
+parser_e_proc_inline_not_supported=03016_E_פרוצדורת INLINE ×œ× × ×ª×ž×›×ª
+% You tried to compile a program with C++ style inlining, and forgot to
+% specify the \var{-Si} option (\seeo{Si}). The compiler doesn't support C++
+% styled inlining by default.
+parser_w_constructor_should_be_public=03018_W_יוצר צריך להיות ציבורי
+% Constructors must be in the 'public' part of an object (class) declaration.
+parser_w_destructor_should_be_public=03019_W_הורס צריך להיות ציבורי
+% Destructors must be in the 'public' part of an object (class) declaration.
+parser_n_only_one_destructor=03020_N_מחלקה צריכה הורס ×חד בלבד
+% You can declare only one destructor for a class.
+parser_e_no_local_objects=03021_E_הגדרות מחלקה מקומיות ××™× × ×ž×•×¨×©×•×ª
+% Classes must be defined globally. They cannot be defined inside a
+% procedure or function
+parser_f_no_anonym_objects=03022_F_הגדרות מחלקה ×נונימיות ××™× × ×ž×•×¨×©×•×ª
+% An invalid object (class) declaration was encountered, i.e. an
+% object or class without methods that isn't derived from another object or
+% class. For example:
+% \begin{verbatim}
+% Type o = object
+% a : longint;
+% end;
+% \end{verbatim}
+% will trigger this error.
+parser_n_object_has_no_vmt=03023_N_×”×ובייקט "$1" ×œ×œ× VMT
+% This is a note indicating that the declared object has no
+% virtual method table.
+parser_e_illegal_parameter_list=03024_E_רשימת ×¤×¨×ž×˜×¨×™× ×œ× ×—×•×§×™×ª
+% You are calling a function with parameters that are of a different type than
+% the declared parameters of the function.
+parser_e_wrong_parameter_size=03026_E_מספר שגוי של ×¤×¨×ž×˜×¨×™× ×¦×•×™×Ÿ עבור הקרי××” ל "$1"
+% There is an error in the parameter list of the function or procedure,
+% the number of parameters is not correct.
+parser_e_overloaded_no_procedure=03027_E_מזהה המרובה שימוש "$1" ×ינו פונקציה
+% The compiler encountered a symbol with the same name as an overloaded
+% function, but it is not a function it can overload.
+parser_e_overloaded_have_same_parameters=03028_E_פונקציות מרובות שימוש מכילות ×ת ××•×ª× ×¨×©×™×ž×ª פרמטרי×
+% You're declaring overloaded functions, but with the same parameter list.
+% Overloaded function must have at least 1 different parameter in their
+% declaration.
+parser_e_header_dont_match_forward=03029_E_הגדרת הפונקציה ××™× ×” תו×מת ×ת ההגדרה הקודמת "$1"
+% You declared a function with same parameters but
+% different result type or function modifiers.
+parser_e_header_different_var_names=03030_E_הגדרת הפונקציה "$1" ××™× ×” תו×מת ×ת המימוש: ×©× ×ž×©×ª× ×” השתנה $2 => $3
+% You declared the function in the \var{interface} part, or with the
+% \var{forward} directive, but define it with a different parameter list.
+parser_n_duplicate_enum=03031_N_×¢×¨×›×™× ×‘×¡×•×’ מניה ×—×™×™×‘×™× ×œ×”×™×•×ª בסדר עולה
+% \fpc allows enumeration constructions as in C. Given the following
+% declaration two declarations:
+% \begin{verbatim}
+% type a = (A_A,A_B,A_E:=6,A_UAS:=200);
+% type a = (A_A,A_B,A_E:=6,A_UAS:=4);
+% \end{verbatim}
+% The second declaration would produce an error. \var{A\_UAS} needs to have a
+% value higher than \var{A\_E}, i.e. at least 7.
+parser_e_no_with_for_variable_in_other_segments=03033_E_With ×ינו מסוגל להשתמש ×‘×ž×©×ª× ×™× ×ž×ž×§×˜×¢ שונה
+% With stores a variable locally on the stack,
+% but this is not possible if the variable belongs to another segment.
+parser_e_too_much_lexlevel=03034_E_פונקציה מקוננת > 31
+% You can nest function definitions only 31 times.
+parser_e_range_check_error=03035_E_שגי××” בבדיקת טווח בעת הערכת קבועי×
+% The constants are out of their allowed range.
+parser_w_range_check_error=03036_W_שגי××” בבדיקת טווח בעת הערכת קבועי×
+% The constants are out of their allowed range.
+parser_e_double_caselabel=03037_E_הכזרת תווית כפולה בcase
+% You are specifying the same label 2 times in a \var{case} statement.
+parser_e_case_lower_less_than_upper_bound=03038_E_הטווח הסופי קטן מהטווח ההתחלתי
+% The upper bound of a \var{case} label is less than the lower bound and this
+% is useless
+parser_e_type_const_not_possible=03039_E_הכרזת טיפוס ×§×‘×•×¢×™× ×©×œ מחלקות ×ו ×ž×ž×©×§×™× ×סורה
+% You cannot declare a constant of type class or object.
+parser_e_no_overloaded_procvars=03040_E_×ž×©×ª× ×™× ×©×œ פונקציות מרובות שימוש ××™× × ×ž×•×¨×©×•×ª
+% You are trying to assign an overloaded function to a procedural variable.
+% This is not allowed
+parser_e_invalid_string_size=03041_E_×ורך מחרוזת חייב להיות ×¢× ×¢×¨×›×™× ×ž1 ל255
+% The length of a shortstring in Pascal is limited to 255 characters. You are
+% trying to declare a string with length lower than 1 or greater than 255
+parser_w_use_extended_syntax_for_objects=03042_W_השתמש בתחביר מורחב של NEW וDISPOSE ×œ×¢×•×ª×§×™× ×©×œ ×ובייקט
+% If you have a pointer \var{a} to a class type, then the statement
+% \var{new(a)} will not initialize the class (i.e. the constructor isn't
+% called), although space will be allocated. you should issue the
+% \var{new(a,init)} statement. This will allocate space, and call the
+% constructor of the object
+parser_w_no_new_dispose_on_void_pointers=03043_W_השימוש במצביע ×œ× ×ž×•×’×“×¨ ×¢× NEW ו DISPOSE חסר משמעות
+parser_e_no_new_dispose_on_void_pointers=03044_E_בלתי ×פשרי להשתמש במצביע ×œ× ×ž×•×’×“×¨ ×¢× NEW ×ו DISPOSE
+% You cannot use \var{new(p)} or \var{dispose(p)} if \var{p} is an untyped pointer
+% because no size is associated to an untyped pointer.
+% Accepted for compatibility in \var{tp} and \var{delphi} modes.
+parser_e_class_id_expected=03045_E_מצפה למזהה מחלקה
+% This happens when the compiler scans a procedure declaration that contains
+% a dot,
+% i.e., a object or class method, but the type in front of the dot is not
+% a known type.
+parser_e_no_type_not_allowed_here=03046_E_סוג מזהה ×œ× ×ž×•×¨×©×” ×‘×ž×™×§×•× ×”× ×•×›×—×™
+% You cannot use a type inside an expression.
+parser_e_methode_id_expected=03047_E_מצפה למזהה מתודי
+% This identifier is not a method.
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., a object or class method, but the procedure name is not a
+% procedure of this type.
+parser_e_header_dont_match_any_member=03048_E_הגדרת הפונקציה ×œ× ×–×”×” למתודות של המחלקה "$1"
+% This identifier is not a method.
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., a object or class method, but the procedure name is not a
+% procedure of this type.
+parser_d_procedure_start=03049_DL_פרוצדורה/פונקציה $1
+% When using the \var{-vd} switch, the compiler tells you when it starts
+% processing a procedure or function implementation.
+parser_e_error_in_real=03050_E_קבוע של מספר ממשי ×ינו חוקי
+% The compiler expects a floating point expression, and gets something else.
+parser_e_fail_only_in_constructor=03051_E_FAIL יכול להיות בשימוש רק בתוך יוצר
+% You are using the \var{fail} keyword outside a constructor method.
+parser_e_no_paras_for_destructor=03052_E_×”×•×¨×¡×™× ×œ× ×™×›×•×œ×™× ×œ×”×›×™×œ פרמטרי×
+% You are declaring a destructor with a parameter list. Destructor methods
+% cannot have parameters.
+parser_e_only_class_methods_via_class_ref=03053_E_רק מתודות מחלקה יכולות להיות מוגדרות בהתייחסות מחלקה
+% This error occurs in a situation like the following:
+% \begin{verbatim}
+% Type :
+% Tclass = Class of Tobject;
+%
+% Var C : TClass;
+%
+% begin
+% ...
+% C.free
+% \end{verbatim}
+% \var{Free} is not a class method and hence cannot be called with a class
+% reference.
+parser_e_only_class_methods=03054_E_רק מתודת מחלקה יכולה לגשת למתודת מחלקה
+% This is related to the previous error. You cannot call a method of an object
+% from a inside a class method. The following code would produce this error:
+% \begin{verbatim}
+% class procedure tobject.x;
+%
+% begin
+% free
+% \end{verbatim}
+% Because free is a normal method of a class it cannot be called from a class
+% method.
+parser_e_case_mismatch=03055_E_×§×‘×•×¢×™× ×•×¡×•×’ CASE ××™× × ×ž×ª×ימי×
+% One of the labels is not of the same type as the case variable.
+parser_e_illegal_symbol_exported=03056_E_×œ× × ×™×ª×Ÿ ×œ×™×™×¦× ×ת הסמל מספרייה
+% You can only export procedures and functions when you write a library. You
+% cannot export variables or constants.
+parser_w_should_use_override=03057_W_מתודת ירושה נסתרת ע"י "$1"
+% A method that is declared \var{virtual} in a parent class, should be
+% overridden in the descendent class with the \var{override} directive. If you
+% don't specify the \var{override} directive, you will hide the parent method;
+% you will not override it.
+parser_e_nothing_to_be_overridden=03058_E_×ין מתודה במחלקה של ×”×ב ×שר ניתן לשכתב: "$1"
+% You are trying to \var{override} a virtual method of a parent class that does
+% not exist.
+parser_e_no_procedure_to_access_property=03059_E_×œ× × ×™×ª×Ÿ מספר לגשת למ×פיין
+% You specified no \var{read} directive for a property.
+parser_w_stored_not_implemented=03060_W_מ×פיין שמור ×ינו מבוצע עדיין
+% The \var{stored} directive is not yet implemented
+parser_e_ill_property_access_sym=03061_E_סימן ×œ× ×—×•×§×™ לגישת המ×פיין
+% There is an error in the \var{read} or \var{write} directives for an array
+% property. When you declare an array property, you can only access it with
+% procedures and functions. The following code would cause such an error.
+% \begin{verbatim}
+% tmyobject = class
+% i : integer;
+% property x [i : integer]: integer read I write i;
+% \end{verbatim}
+%
+parser_e_cant_access_protected_member=03062_E_×œ× × ×™×ª×Ÿ לגשת לשדה מוגן ב×ובייקט הנוכחי
+% Fields that are declared in a \var{protected} section of an object or class
+% declaration cannot be accessed outside the module where the object is
+% defined, or outside descendent object methods.
+parser_e_cant_access_private_member=03063_E_×œ× × ×™×ª×Ÿ לגשת לשדה פרטי ב×ובקייט הנוכחי
+% Fields that are declared in a \var{private} section of an object or class
+% declaration cannot be accessed outside the module where the class is
+% defined.
+parser_e_overridden_methods_not_same_ret=03066_E_מתודה מרובת שימוש חייבת להיות ×–×”×” בסוג המשתנה: "$2" בשימוש ×¢"×™ "$1", ×שר מכילה סוג משתנה ×חר
+% If you declare overridden methods in a class definition, they must
+% have the same return type.
+parser_e_dont_nest_export=03067_E_הגדדרת פונקציות EXPORT ×œ× ×™×›×•×œ×•×ª להיות מקוננות
+% You cannot declare a function or procedure within a function or procedure
+% that was declared as an export procedure.
+parser_e_methods_dont_be_export=03068_E_××™ ×פשר ×œ×™×™×¦× ×ת המתודה
+% You cannot declare a procedure that is a method for an object as
+% \var{export}ed.
+parser_e_call_by_ref_without_typeconv=03069_E_השימוש בפרמטר של משתנה חייב להיות זהה: מכיל "$1" מצפה ל"$2"
+% When calling a function declared with \var{var} parameters, the variables in
+% the function call must be of exactly the same type. There is no automatic
+% type conversion.
+parser_e_no_super_class=03070_E_המחלקה ××™× × ×” מחלקת ×ב של המחלקה הנוכחית
+% When calling inherited methods, you are trying to call a method of a non-related
+% class. You can only call an inherited method of a parent class.
+parser_e_self_not_in_method=03071_E_SELF מורשה רק במתודות
+% You are trying to use the \var{self} parameter outside an object's method.
+% Only methods get passed the \var{self} parameters.
+parser_e_generic_methods_only_in_methods=03072_E_מתודות יכולות ×œ×”×™×§×¨× ×™×©×™×¨×•×ª רק בתוך מתודות ×חרות ×¢× ×¡×•×’ מזהה שלהמחלקה
+% A construction like \var{sometype.somemethod} is only allowed in a method.
+parser_e_illegal_colon_qualifier=03073_E_שימוש ×œ× ×—×•×§×™ של ':'
+% You are using the format \var{:} (colon) 2 times on an expression that
+% is not a real expression.
+parser_e_illegal_set_expr=03074_E_שגי××” בבדיקת טווח בסדרת ×™×•×¦×¨×™× ×ו שכפול סדרה
+% The declaration of a set contains an error. Either one of the elements is
+% outside the range of the set type, either two of the elements are in fact
+% the same.
+parser_e_pointer_to_class_expected=03075_E_מצפה למצביע ×ובייקט
+% You specified an illegal type in a \var{new} statement.
+% The extended syntax of \var{new} needs an object as a parameter.
+parser_e_expr_have_to_be_constructor_call=03076_E_הביטוי חייב להיות קרי×ת יוצר
+% When using the extended syntax of \var{new}, you must specify the constructor
+% method of the object you are trying to create. The procedure you specified
+% is not a constructor.
+parser_e_expr_have_to_be_destructor_call=03077_E_הביטוי חייב להיות קרי×ת הורס
+% When using the extended syntax of \var{dispose}, you must specify the
+% destructor method of the object you are trying to dispose of.
+% The procedure you specified is not a destructor.
+parser_e_invalid_record_const=03078_E_סדר ×œ× ×—×•×§×™ של ××œ×ž× ×˜×™× ×‘×¨×©×•×ž×”
+% When declaring a constant record, you specified the fields in the wrong
+% order.
+parser_e_false_with_expr=03079_E_סוג ביטוי חייב להיות ביטוי רשומה ×ו מחלקה
+% A \var{with} statement needs an argument that is of the type \var{record}
+% or \var{class}. You are using \var{with} on an expression that is not of
+% this type.
+parser_e_void_function=03080_E_פרוצדורה ×œ× ×™×›×•×œ×” להחזיר ערך
+% In \fpc, you can specify a return value for a function when using
+% the \var{exit} statement. This error occurs when you try to do this with a
+% procedure. Procedures cannot return a value.
+parser_e_only_methods_allowed=03081_E_×”×™×•×¦×¨×™× ×•×”×”×•×¨×¡×™× ×—×™×™×‘×™× ×œ×”×™×•×ª מתודיי×
+% You're declaring a procedure as destructor or constructor, when the
+% procedure isn't a class method.
+parser_e_operator_not_overloaded=03082_E_×”×ופריטור ×œ× ×ž×¨×•×‘×” שימוש
+% You're trying to use an overloaded operator when it is not overloaded for
+% this type.
+parser_e_no_such_assignment=03083_E_×œ× × ×™×ª×Ÿ להציב ×¢×¨×›×™× ×œ×¡×•×’×™× ×ž×¨×•×‘×™ שימוש
+% You can not overload assignment for types
+% that the compiler considers as equal.
+parser_e_overload_impossible=03084_E_בלתי ×פשרי להשתמש ב×ופרטור מרובה שימוש
+% The combination of operator, arguments and return type are
+% incompatible.
+parser_e_no_reraise_possible=03085_E_×œ× × ×™×ª×Ÿ ×œ×”×¨×™× ×—×¨×™×’×”
+% You are trying to raise an exception where it is not allowed. You can only
+% raise exceptions in an \var{except} block.
+parser_e_no_new_or_dispose_for_classes=03086_E_התחביר המורחב של NEW ×ו DISPOSE ×œ× ×ž×•×¨×©×” למחלקות
+% You cannot generate an instance of a class with the extended syntax of
+% \var{new}. The constructor must be used for that. For the same reason, you
+% cannot call \var{dispose} to de-allocate an instance of a class, the
+% destructor must be used for that.
+parser_e_procedure_overloading_is_off=03088_E_×”×פשרות לפרוצדורות מרובות שימוש כבוי
+% When using the \var{-So} switch, procedure overloading is switched off.
+% Turbo Pascal does not support function overloading.
+parser_e_overload_operator_failed=03089_E_×œ× × ×™×ª×Ÿ להעמיס על סוג ×”×ופרטור הנוכחי. העמסת ×”××•×¤×¨×˜×•×¨×™× ×”×§×©×•×¨×™× ×œ×¤×¢×•×œ×” (×× ×‘×›×œ×œ) ×”×: $1
+% You are trying to overload an operator which cannot be overloaded.
+% The following operators can be overloaded :
+% \begin{verbatim}
+% +, -, *, /, =, >, <, <=, >=, is, as, in, **, :=
+% \end{verbatim}
+parser_e_comparative_operator_return_boolean=03090_E_×ופרטור השוו×תי חייב להחזיר ערך בולי×× ×™
+% When overloading the \var{=} operator, the function must return a boolean
+% value.
+parser_e_only_virtual_methods_abstract=03091_E_רק שיטה ווירטו×לית יכולה להיות מופשט
+% You are declaring a method as abstract, when it is not declared to be
+% virtual.
+parser_f_unsupported_feature=03092_F_שימוש ב×ופציה ×œ× × ×ª×ž×›×ª!
+% You're trying to force the compiler into doing something it cannot do yet.
+parser_e_mix_of_classes_and_objects=03093_E_הערבוב של ×¢×¦×ž×™× ×©×•× ×™× (מחלקות, עצ×, ממשק וכו') ×ינו מורשה
+% You cannot derive \var{objects}, \var{classes}, \var{cppclasses} and \var{interfaces} interttwined . E.g.
+% a class cannot have an object as parent and vice versa.
+parser_w_unknown_proc_directive_ignored=03094_W_×ž×ª×¢×œ× ×ž×”× ×—×™×ª השגרה: "$1"
+% The procedure directive you specified is unknown.
+parser_e_absolute_only_one_var=03095_E_absolute ניתן לשימוש רק ×¢× ×ž×©×ª× ×” ×חת
+% You cannot specify more than one variable before the \var{absolute} directive.
+% Thus, the following construct will provide this error:
+% \begin{verbatim}
+% Var Z : Longint;
+% X,Y : Longint absolute Z;
+% \end{verbatim}
+% \item [ absolute can only be associated a var or const ]
+% The address of a \var{absolute} directive can only point to a variable or a
+% typed constant. Therefore, the following code will produce this error:
+% \begin{verbatim}
+% Procedure X;
+%
+% var p : longint absolute x;
+% \end{verbatim}
+%
+parser_e_absolute_only_to_var_or_const=03096_E_ניתן להשתמש בabsolute רק ×¢× ×ž×©×ª× ×” ×ו קבוע
+% The address of a \var{absolute} directive can only point to a variable or
+% constant. Therefore, the following code will produce this error:
+% \begin{verbatim}
+% Procedure X;
+%
+% var p : longint absolute x;
+% \end{verbatim}
+%
+parser_e_initialized_only_one_var=03097_E_ניתן ל×תחל רק משתנה ×חד
+% You cannot specify more than one variable with a initial value
+% in Delphi mode.
+parser_e_abstract_no_definition=03098_E_מתודה מופשטת ××™× ×” זקוקה להגדרה (×¢× ×’×•×£ של פונקציה)
+% Abstract methods can only be declared, you cannot implement them. They
+% should be overridden by a descendant class.
+parser_e_overloaded_must_be_all_global=03099_E_העמסת היתר של הפונקציה ××™× ×” יכולה להיות מקומית (חייבת להיות מיוצ×ת)
+% You are defining a overloaded function in the implementation part of a unit,
+% but there is no corresponding declaration in the interface part of the unit.
+parser_w_virtual_without_constructor=03100_W_שימוש במתודות ווירטו×ליות ×œ×œ× ×™×•×¦×¨ ב "$1"
+% If you declare objects or classes that contain virtual methods, you need
+% to have a constructor and destructor to initialize them. The compiler
+% encountered an object or class with virtual methods that doesn't have
+% a constructor/destructor pair.
+parser_c_macro_defined=03101_CL_הגדרת מ×קרו: $1
+% When \var{-vc} is used, the compiler tells you when it defines macros.
+parser_c_macro_undefined=03102_CL_מ×קרו ×œ× ×ž×•×’×“×¨: $1
+% When \var{-vc} is used, the compiler tells you when it undefines macros.
+parser_c_macro_set_to=03103_CL_מ×קרו $1 מוגדר ×› $2
+% When \var{-vc} is used, the compiler tells you what values macros get.
+parser_i_compiling=03104_I_מהדר $1
+% When you turn on information messages (\var{-vi}), the compiler tells you
+% what units it is recompiling.
+parser_u_parsing_interface=03105_UL_מפרש ×ת הממשק של היחידה $1
+% This tells you that the reading of the interface
+% of the current unit starts
+parser_u_parsing_implementation=03106_UL_מפרש ×ת הביצוע של $1
+% This tells you that the code reading of the implementation
+% of the current unit, library or program starts
+parser_d_compiling_second_time=03107_DL_מהדר ×ת $1 ×‘×¤×¢× ×”×©× ×™×™×”
+% When you request debug messages (\var{-vd}) the compiler tells you what
+% units it recompiles for the second time.
+parser_e_no_property_found_to_override=03109_E_×œ× × ×ž×¦××” תכונה לעקיפה
+% You want to override a property of a parent class, when there is, in fact,
+% no such property in the parent class.
+parser_e_only_one_default_property=03110_E_רק תכונה ×חת ×¢× ×‘×¨×™×¨×ª מחדל מורשת
+% You specified a property as \var{Default}, but the class already has a
+% default property, and a class can have only one default property.
+parser_e_property_need_paras=03111_E_התונה ×¢× ×‘×¨×™×¨×ª מחדל חייבת להיות תכונה של מערך
+% Only array properties of classes can be made \var{default} properties.
+parser_e_constructor_cannot_be_not_virtual=03112_E_×™×•×¦×¨×™× ×•×•×™×¨×˜×•××œ×™× × ×ª×ž×›×™× ×¨×§ במחלקה
+% You cannot have virtual constructors in objects. You can only have them
+% in classes.
+parser_e_no_default_property_available=03113_E_ערך ברירת מחדל ×ינו ×§×™×™× ×œ×ª×›×•× ×”
+% You are trying to access a default property of a class, but this class (or one of
+% its ancestors) doesn't have a default property.
+parser_e_cant_have_published=03114_E_המחלקה ××™× ×” יכולה להכיל ×ת חתך published, השתמש במתג {$M+}
+% If you want a \var{published} section in a class definition, you must
+% use the \var{\{\$M+\}} switch, whch turns on generation of type
+% information.
+parser_e_forward_declaration_must_be_resolved=03115_E_נדרשת הגדרה ר×שונית של המחלקה "$1" לפני השימוש בה כמחלקה יורשת
+% To be able to use an object as an ancestor object, it must be defined
+% first. This error occurs in the following situation:
+% \begin{verbatim}
+% Type ParentClas = Class;
+% ChildClass = Class(ParentClass)
+% ...
+% end;
+% \end{verbatim}
+% Where \var{ParentClass} is declared but not defined.
+parser_e_no_local_operator=03116_E_השימוש ב×ופריטור מקומי ×ינו נתמך
+% You cannot overload locally, i.e. inside procedures or function
+% definitions.
+parser_e_proc_dir_not_allowed_in_interface=03117_E_×ž×§×“× ×©×™×’×¨×” "$1" ×ינו מורשה בשימוש בתוך הממשק
+% This procedure directive is not allowed in the \var{interface} section of
+% a unit. You can only use it in the \var{implementation} section.
+parser_e_proc_dir_not_allowed_in_implementation=03118_E_×ž×§×“× ×©×™×’×¨×” "$1" ×ינו מורשה בחלק הביצועי
+% This procedure directive is not defined in the \var{implementation} section of
+% a unit. You can only use it in the \var{interface} section.
+parser_e_proc_dir_not_allowed_in_procvar=03119_E_×ž×§×“× ×©×™×’×¨×” "$1" ×ינו מורשה כחלק מהגדרת השיגרה
+% This procedure directive cannot be part of a procedural or function
+% type declaration.
+parser_e_function_already_declared_public_forward=03120_E_הגדרת הפונקציה "$1" כבר בוצעה
+% You will get this error if a function is defined as \var{forward} twice.
+% Or it is once in the \var{interface} section, and once as a \var{forward}
+% declaration in the \var{implmentation} section.
+parser_e_not_external_and_export=03121_E_×œ× × ×™×ª×Ÿ להשתמש ×’× ×‘ EXPORT ×•×’× EXTERNAL
+% These two procedure directives are mutually exclusive
+parser_w_not_supported_for_inline=03123_W_"$1" ×ינו נתמך עדיין בתוך פונקצית/שגרת inline
+% Inline procedures don't support this declaration.
+parser_w_inlining_disabled=03124_W_השימוש הישיר מבוטל
+% Inlining of procedures is disabled.
+parser_i_writing_browser_log=03125_I_כותב יומן דפדפן $1
+% When information messages are on, the compiler warns you when it
+% writes the browser log (generated with the \var{\{\$Y+ \}} switch).
+parser_h_maybe_deref_caret_missing=03126_H_ייתכן כי חסר תוכן למצביע
+% The compiler thinks that a pointer may need a dereference.
+parser_f_assembler_reader_not_supported=03127_F_×ין תמיכה במ×סף הנבחר
+% The selected assembler reader (with \var{\{\$ASMMODE xxx\}} is not
+% supported. The compiler can be compiled with or without support for a
+% particular assembler reader.
+parser_e_proc_dir_conflict=03128_E_×ž×§×“× ×”×©×™×’×¨×” "$1" מתנגש ×¢× ×ž×§×“×ž×™× ×חרי×
+% You specified a procedure directive that conflicts with other directives.
+% for instance \var{cdecl} and \var{pascal} are mutually exclusive.
+parser_e_call_convention_dont_match_forward=03129_E_השימוש בהגדרה הנוכחית ×ינו ×–×”×” להגדרה הר×שונית
+% This error happens when you declare a function or procedure with
+% e.g. \var{cdecl;} but omit this directive in the implementation, or vice
+% versa. The calling convention is part of the function declaration, and
+% must be repeated in the function definition.
+parser_e_property_cant_have_a_default_value=03131_E_תכונות ×ינן יכולות להכיל ערך ברירת מחדל
+% Set properties or indexed properties cannot have a default value.
+parser_e_property_default_value_must_const=03132_E_ערך ברירת המחדלק שת התכונה חייב להיות קבוע
+% The value of a \var{default} declared property must be known at compile
+% time. The value you specified is only known at run time. This happens
+% .e.g. if you specify a variable name as a default value.
+parser_e_cant_publish_that=03133_E_הסמל ×ינו יכול להיות בשימוש בתוך מחלקה ×œ×œ× ×”×’×“×¨×ª×• בתוך המחלקה
+% Only class type variables can be in a \var{published} section of a class
+% if they are not declared as a property.
+parser_e_cant_publish_that_property=03134_E_סוג ×–×” של תכונה ×ינו יכול להיות בשימוש
+% Properties in a \var{published} section cannot be array properties.
+% they must be moved to public sections. Properties in a \var{published}
+% section must be an ordinal type, a real type, strings or sets.
+parser_e_empty_import_name=03136_E_נדרש ×©× ×™×™×‘×•×
+% Some targets need a name for the imported procedure or a \var{cdecl} specifier
+parser_e_division_by_zero=03138_E_חלוק ב×פס
+% There is a division by zero encounted
+parser_e_invalid_float_operation=03139_E_פעולת עשרונית ×œ× ×—×•×§×™×ª
+% An operation on two real type values produced an overflow or a division
+% by zero.
+parser_e_array_lower_less_than_upper_bound=03140_E_הגבול העליון נמוך יותר מהגבול התחתון
+% The upper bound of a an array declaration is less than the lower bound and this
+% is not possible
+parser_w_string_too_long=03141_W_×ורך המחרוזת של "$1" ×רוך יותר מ "$1"
+% The size of the constant string is larger than the size you specified in
+% string type definition
+parser_e_string_larger_array=03142_E_×ורך המחרוזת ×רוך יותר מ×ורך מערך התווי×
+% The size of the constant string is larger than the size you specified in
+% the array[x..y] of char definition
+parser_e_ill_msg_expr=03143_E_התוכן של הביטוי ל×חר ההודעה ×ינו חוקי
+% \fpc supports only integer or string values as message constants
+parser_e_ill_msg_param=03144_E_טיפול בהודעות חייב להיות במבנה קבוע של פרמטרי×
+% A method declared with the \var{message}-directive as message handler
+% can take only one parameter which must be declared as call by reference
+% Parameters are declared as call by reference using the \var{var}-directive
+parser_e_duplicate_message_label=03145_E_תווית הודעה כפולה: "$1"
+% A label for a message is used twice in one object/class
+parser_e_self_in_non_message_handler=03146_E_Self חייב להיות פרמטר במתודה של מטפל ההודעות
+% The self parameter can only be passed explicitly to a method which
+% is declared as message handler.
+parser_e_threadvars_only_sg=03147_E_Threadvars ×—×™×™×‘×™× ×œ×”×™×•×ª ×¡×˜×˜×™×™× ×ו גלובליי×
+% Threadvars must be static or global, you can't declare a thread
+% local to a procedure. Local variables are always local to a thread,
+% because every thread has its own stack and local variables
+% are stored on the stack
+parser_f_direct_assembler_not_allowed=03148_F_השימוש במ×סף הנוכחי ×ינו תומך בוסג התוצ××” הבינ×רית
+% You can't use direct assembler when using a binary writer, choose an
+% other outputformat or use another assembler reader
+parser_w_no_objpas_use_mode=03149_W_×סור ×œ×§×¨×•× ×œ×™×—×™×“×ª OBJPAS ישירות, יש להשתמש ב \{\$mode objfpc\} ×ו ב \{\$mode delphi\} במקו×
+% You are trying to load the ObjPas unit manually from a uses clause. This is
+% not a good idea. Use the \var{\{\$mode objfpc\}} or
+% \var{\{\$mode delphi\}}
+% directives which load the unit automatically
+parser_e_no_object_override=03150_E_OVERRIDE ×ינו יכול להיות בשימוש ב×ובייקטי×
+% Override is not supported for objects, use \var{virtual} instead to override
+% a method of a parent object
+parser_e_cant_use_inittable_here=03151_E_טיפוסי × ×ª×•× ×™× ×שר ×“×•×¨×©×™× ×תחול ×ו ×¡×™×›×•× ××™× × ×™×›×•×œ×™× ×œ×”×™×•×ª ברשומות variant
+% Some data type (e.g. \var{ansistring}) needs initialization/finalization
+% code which is implicitly generated by the compiler. Such data types
+% can't be used in the variant part of a record.
+parser_e_resourcestring_only_sg=03152_E_×œ× × ×™×ª×Ÿ להגדיר Resourcestring בתור הגדרה מקומית, רק הגדרה גלובלית ×ו סטטית
+% Resourcestring can not be declared local, only global or using the static
+% directive.
+parser_e_exit_with_argument_not__possible=03153_E_השימוש בשיגרה exit ×ינו יכול להתבצע ×‘×ž×™×§×•× ×”× ×•×›×—×™
+% an exit statement with an argument for the return value can't be used here, this
+% can happen e.g. in \var{try..except} or \var{try..finally} blocks
+parser_e_stored_property_must_be_boolean=03154_E_טיפוס ×”× ×ª×•× ×™× ×‘×¡×™×ž×•×œ ×”×חסון חייב להיות בולי×× ×™
+% If you specify a storage symbol in a property declaration, it must be of
+% the type boolean
+parser_e_ill_property_storage_sym=03155_E_הסימול ×ינו יכול להשמש כסימול ל×חסון
+% You can't use this type of symbol as storage specifier in property
+% declaration. You can use only methods with the result type boolean,
+% boolean class fields or boolean constants
+parser_e_only_publishable_classes_can_be_published=03156_E_רק מחלקה המהודרת במצב $M+ יכולה להיות ×יזור ×” published
+% In the published section of a class can be only class as fields used which
+% are compiled in \var{\{\$M+\}} or which are derived from such a class. Normally
+% such a class should be derived from TPersitent
+parser_e_proc_directive_expected=03157_E_מצפה להנחיית שיגרה
+% This error is triggered when you have a \var{\{\$Calling\}} directive without
+% a calling convention specified.
+% It also happens when declaring a procedure in a const block and you
+% used a ; after a procedure declaration which must be followed by a
+% procedure directive.
+% Correct declarations are:
+% \begin{verbatim}
+% const
+% p : procedure;stdcall=nil;
+% p : procedure stdcall=nil;
+% \end{verbatim}
+parser_e_invalid_property_index_value=03158_E_הערך ×”×ינדקס של התכונה חייב להיות טיפוס מסודר
+% The value you use to index a property must be of an ordinal type, for
+% example an integer or enumerated type.
+parser_e_procname_to_short_for_export=03159_E_×©× ×”×©×’×¨×” קצר מידי לייצו×
+% The length of the procedure/function name must be at least 2 characters
+% long. This is because of a bug in dlltool which doesn't parse the .def
+% file correct with a name of length 1.
+parser_e_dlltool_unit_var_problem=03160_E_×œ× × ×™×ª×Ÿ לייצר חלק DEFFILE ×œ×ž×©×ª× ×™× ×’×œ×•×‘×œ×™×™× ×‘×™×—×™×“×”
+parser_e_dlltool_unit_var_problem2=03161_E_הדר ×œ×œ× ×©×™×ž×•×© ב -WD
+% You need to compile this file without the -WD switch on the
+% commandline
+parser_f_need_objfpc_or_delphi_mode=03162_F_יש להשתמש במצב ObjFpc (-S2) ×ו במצב Delphi (-Sd) להדר ×ת המודול
+% You need to use \{\$mode objfpc\} or \{\$mode delphi\} to compile this file.
+% Or use the equivalent commandline switches -S2 or -Sd.
+parser_e_no_export_with_index_for_target=03163_E_××™ ×פשר ×œ×™×™×¦× ×¢× ×ינדקס תחת $1
+% Exporting of functions or procedures with a specified index is not
+% supported on this target.
+parser_e_no_export_of_variables_for_target=03164_E_×™×™×¦×•× ×©×œ משתמש ×ינו נתמך ב$1
+% Exporting of variables is not supported on this target.
+parser_e_improper_guid_syntax=03165_E_תחביר GUID ×ינו חוקי
+% The GUID indication does not have the proper syntax. It should be of the form
+% \begin{verbatim}
+% {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}
+% \end{verbatim}
+% Where each \var{X} represents a hexadecimal digit.
+parser_w_interface_mapping_notfound=03168_W_השגרה "$1" נמצ××” ×ך ×œ×œ× ×”×¤×¨×ž×˜×¨×™× ×”×ž×‘×•×§×©×™× ×©×œ $2.$3
+% The compiler cannot find a suitable procedure which implements the given method of an interface.
+% A procedure with the same name is found, but the arguments do not match.
+parser_e_interface_id_expected=03169_E_מצפה למזהה ממשק
+% This happens when the compiler scans a \var{class} declaration that contains
+% \var{interface} function name mapping code like this:
+% \begin{verbatim}
+% type
+% TMyObject = class(TObject, IDispatch)
+% function IUnknown.QueryInterface=MyQueryInterface;
+% ....
+% \end{verbatim}
+% and the \var{interface} before the dot not listed in the inheritance list.
+parser_e_type_cant_be_used_in_array_index=03170_E_הסוג "$1" ×ינו יכול להיות בשימוש בתור סוג ×ינדקס למערך
+% Types like \var{qword} or \var{int64} aren't allowed as array index type
+parser_e_no_con_des_in_interfaces=03171_E_יוצר והורס ××™× × ×ž×•×¨×©×™× ×‘×ž×ž×©×§×™×
+% Constructor and destructor declarations aren't allowed in interface
+% In the most cases the method \var{QueryInterface} of \var{IUnknown} can
+% be used to create a new interface.
+parser_e_no_access_specifier_in_interfaces=03172_E_מזהה כניסה ×ינו יכול להיות בשימוש ×¢× ×ž×ž×©×§×™×
+% The access specifiers \var{public}, \var{private}, \var{protected} and
+% \var{pusblished} can't be used in interfaces because all methods
+% of an interfaces must be public.
+parser_e_no_vars_in_interfaces=03173_E_ממשק ×ינו יכול להכיל שדות
+% Declarations of fields aren't allowed in interfaces. An interface
+% can contain only methods
+parser_e_no_local_proc_external=03174_E_×œ× × ×™×ª×Ÿ להגדיר שגרה מקומית כחיצונית
+% Declaring local procedures as external is not possible. Local procedures
+% get hidden parameters that will make the chance of errors very high
+parser_w_skipped_fields_before=03175_W_חלק מהשדות הב××™× ×œ×¤× ×™ "$1" ×œ× ×ותחלו
+% In Delphi mode, not all fields of a typed constant record have to be
+% initialized, but the compiler warns you when it detects such situations.
+parser_e_skipped_fields_before=03176_E_חלק מהשדות הב××™× ×œ×¤× ×™ "$1" ×œ× ×ותחלו
+% In all syntax modes but Delphi mode, you can't leave some fields uninitialized
+% in the middle of a typed constant record
+parser_w_skipped_fields_after=03177_W_חלק מהשדות הב××™× ×חרי "$1" ×œ× ×ותחלו
+% You can leave some fields at the end of a type constant record uninitialized
+% (the compiler will initialize them to zero automatically). This may be the cause
+% of subtle problems.
+parser_e_varargs_need_cdecl_and_external=03178_E_השימוש בVarArgs (×ו '...' בMacPas) חייב להיות בשימוש ×¢× CDecl/CPPDecl/MWPascal ו External
+% The varargs directive (or the ``...'' varargs parameter in MacPas mode) can only be used with procedures or functions
+% that are declared with \var{external} and one of \var{cdecl}, \var{cppdecl} and \var{mwpascal}. This functionality
+% is only supported to provide a compatible interface to C functions like printf.
+parser_e_self_call_by_value=03179_E_Self חייב להיות פרמטר רגיל (call-by-value)
+% You can't declare self as a const or var parameter, it must always be
+% a call-by-value parameter
+parser_e_interface_has_no_guid=03180_E_הממשק "$1" ×ינו מכיל מזהה GUID
+% When you want to assign an interface to a constant, then the interface
+% must have a GUID value set.
+parser_e_illegal_field_or_method=03181_E_המזהה של שדה ×ו מתודה של מחלקה "$1" ××™× × ×™×“×•×¢×™×
+% Properties must refer to a field or method in the same class.
+parser_w_proc_overriding_calling=03182_W_עולה על מוסכמות הפעלה "$1" ×¢× "$2"
+% There are two directives in the procedure declaration that specify a calling
+% convention. Only the last directive will be used
+parser_e_no_procvarobj_const=03183_E_ניתן ל×תחל טיפוס קבוע של "procedure of object" רק ×¢× NIL
+% You can't assign the address of a method to a typed constant which has a
+% 'procedure of object' type, because such a constant requires two addresses:
+% that of the method (which is known at compile time) and that of the object or
+% class instance it operates on (which can not be known at compile time).
+parser_e_default_value_only_one_para=03184_E_ערך ברירת מחדל יכול להיות בשימוש רק ×¢× ×¤×¨×ž×˜×¨ ×חד
+% It is not possible to specify a default value for several parameters at once.
+% The following is invalid:
+% \begin{verbatim}
+% Procedure MyProcedure (A,B : Integer = 0);
+% \end{verbatim}
+% Instead, this should be declared as
+% \begin{verbatim}
+% Procedure MyProcedure (A : Integer = 0; B : Integer = 0);
+% \end{verbatim}
+parser_e_default_value_expected_for_para=03185_E_פרמטר ברירת מחדל דרוש עבור "$1"
+% The specified parameter requires a default value.
+parser_w_unsupported_feature=03186_W_שימוש במ×פיין ×œ× × ×ª×ž×š !
+% You're trying to force the compiler into doing something it cannot do yet.
+parser_h_c_arrays_are_references=03187_H_×ž×¢×¨×›×™× ×©×œ C ×ž×•×¢×‘×¨×™× ×›×”×¤× ×™×”
+% Any array passed to a C functions is passed
+% by a pointer (i.e. by reference).
+parser_e_C_array_of_const_must_be_last=03188_E_מערך C של קבוע חייב להיות ×”×רגומנט ×”×חרון
+% You can not add any other argument after an \var{array of const} for
+% \var{cdecl} functions, as the size pushed on stack for this argument is
+% not known.
+parser_h_type_redef=03189_H_הגדרה מחודשת של הטיפוס "$1"
+% This is an indicator that a previously declared type is
+% being redefined as something else. This may, or may not
+% be, a cause for errors.
+parser_w_cdecl_has_no_high=03190_W_×ין לפונקציות cdecl פרמטר גבוהה
+% Functions declared with cdecl modifier do not pass an extra implicit parameter.
+parser_w_cdecl_no_openstring=03191_W_פונקציות cdecel ×ינן תומכות ב open string
+% Openstring is not supported for cdecl'ared functions.
+parser_e_initialized_not_for_threadvar=03192_E_×ין ×פשרות ל×תחל משתנה המוגדר ×›threadvar
+% Variables declared as threadvar can not be initialized with a default value.
+% The variables will always be filled with zero at the start of a new thread.
+parser_e_msg_only_for_classes=03193_E_ניתן להשתמש בהנחיית message רק בתוך מחלקה
+% The message directive is only supported for Class types.
+parser_e_procedure_or_function_expected=03194_E_מצפה לשיגרה ×ו פונקציה
+% A class method can only be specified for procedures and functions.
+parser_e_illegal_calling_convention=03195_W_×ž×ª×¢×œ× ×ž×ž×•×¡×›×ž×ª ההפעלה: "$1"
+% Some calling conventions are supported only by certain CPUs. I.e. most non-i386 ports support
+% only the standard ABI calling convention of the CPU.
+parser_e_no_object_reintroduce=03196_E_×œ× × ×™×ª×Ÿ להשתמש בREINTRODUCE בתוך ×ובייקט
+% \var{reintroduce} is not supported for objects.
+parser_e_paraloc_only_one_para=03197_E_כל ×רגומנט חייב להכיל ×ž×™×§×•× ×¢×¦×ž××™.
+% If locations for arguments are specified explicitly as it is required by
+% some syscall conventions, each argument must have it's only location, things
+% like \var{procedure p(i,j : longint 'r1');} aren't allowed
+parser_e_paraloc_all_paras=03198_E_כל ×רגומנט חייב להכיל ×ž×™×§×•× ×ž×•×’×“×¨
+% If one argument has an explicit argument location, all arguments of a procedure
+% must have one.
+parser_e_illegal_explicit_paraloc=03199_E_×ž×™×§×•× ×רגומנט ×œ× ×™×“×•×¢
+% The location specified for an argument isn't recognized by the compiler
+parser_e_32bitint_or_pointer_variable_expected=03200_E_מצפה לסוג משתנה של מספר ×©×œ× 32-Bit ×ו מצביע
+% The libbase for MorphOS/AmigaOS can be give only as \var{longint}, \var{dword} or any pointer variable.
+parser_e_goto_outside_proc=03201_E_×œ× × ×™×ª×Ÿ להשמש בgoto בין שני שיגרות
+% It isn't allowed to use the \var{goto} statements referencing labels outside the
+% current procedure. The following example shows the problem:
+% \begin{verbatim}
+% ...
+% procedure p1;
+% label
+% l1;
+%
+% procedure p2;
+% begin
+% goto l1; // This goto ISN'T allowed
+% end;
+%
+% begin
+% p2
+% l1:
+% end;
+% ...
+%
+% \end{verbatim}
+parser_f_too_complex_proc=03202_F_השיגרה מסובכת מידי ודורשת שימוש של ××•×’×¨×™× ×¨×‘×™× ×ž×™×“×™
+% Your procedure body is too long for the compiler. You should split the
+% procedure into multiple smaller procedures.
+parser_e_illegal_expression=03203_E_ביטוי ×œ× ×—×•×§×™
+% This can occur under many circumstances. Mostly when trying to evaluate
+% constant expressions.
+parser_e_invalid_integer=03204_E_הביטוי של המספר ×”×©×œ× ×ינו חוקי
+% You made an expression which isn't an integer, and the compiler expects the
+% result to be an integer.
+parser_e_invalid_qualifier=03205_E_שימוש ×œ× ×—×•×§×™ במבחין
+% One of the following is happening :
+% \begin{itemize}
+% \item You're trying to access a field of a variable that is not a record.
+% \item You're indexing a variable that is not an array.
+% \item You're dereferencing a variable that is not a pointer.
+% \end{itemize}
+parser_e_upper_lower_than_lower=03206_E_טווח ההגבלה הגבוהה קטן מטווח ההגבלה הנמוכה
+% You are declaring a subrange, and the lower limit is higher than the high
+% limit of the range.
+parser_e_macpas_exit_wrong_param=03207_E_הפרמטר של Exit חייב להיות ×©× ×”×©×™×’×¨×” תחתיו ×”×•× × ×ž×¦×
+% Non local exit is not allowed. This error occurs only in mode MacPas.
+parser_e_illegal_assignment_to_count_var=03208_E_הצבה ×œ× ×—×•×§×™×ª של המשתנה בלול×ת ×” for "$1"
+% The type of a \var{for} loop variable must be an ordinal type.
+% Loop variables cannot be reals or strings. You can also not assign values to
+% loop variables inside the loop (except in Delphi and TP modes). Use a while or
+% repeat loop instead if you need to do something like that, since those
+% constructs were built for that.
+parser_e_no_local_var_external=03209_E_×œ× × ×™×ª×Ÿ להגדיר ×ž×©×ª× ×™× ×ž×§×•×ž×™×™× ×›×—×™×¦×•× ×™×™×
+% Declaring local variables as external is not allowed. Only global variables can reference
+% to external variables.
+parser_e_proc_already_external=03210_E_השיגרה כבר מוגדרת כחיצונית
+% The procedure is already declared with the EXTERNAL directive in an interface or
+% forward declaration.
+parser_w_implicit_uses_of_variants_unit=03211_W_שימוש משתמע ביחידת Variants
+% The Variant type is used in the unit without any used unit using the Variants unit. The
+% compiler has implicitly added the Variants unit to the uses list. To remove this warning
+% the Variants unit needs to be added to the uses statement.
+parser_e_no_static_method_in_interfaces=03212_E_השימוש במחלקה ומתודות ×¡×˜×˜×™×™× ××™× × ×™×›×•×œ×™×•×ª להיות בשימוש בממשק
+% The specifier \var{class} and directive \var{static} can't be used in interfaces
+% because all methods of an interfaces must be public.
+parser_e_arithmetic_operation_overflow=03213_E_גלישה בפעולה מתמטית
+% An operation on two integers values produced an overflow
+parser_e_protected_or_private_expected=03214_E_מצפה ל×יזור Protected ×ו Private
+% \var{strict} can be only used together with \var{protected} or \var{private}.
+parser_e_illegal_slice=03215_E_SLICE ××™×  יכול להיות בשימוש מחוץ לרשימת פרמטרי×
+% \var{slice} can be used only for arguments accepting an open array parameter
+parser_e_dispinterface_cant_have_parent=03216_E_מחלקת DISPINTERFACE ××™× ×” יכולה להכיל הורה
+% A DISPINMTERFACE is a special type of interface which can't have a parent class
+parser_e_dispinterface_needs_a_guid=03217_E_DISPINTERFACE חייב GUID
+% A DISPINMTERFACE always needs an interface identification
+parser_w_overridden_methods_not_same_ret=03218_W_המתודות החדשות חייבות להחזיר ×ת ×ותו טיפוס נתוני×. הקוד הנוכחי יכול ×œ×’×¨×•× ×œ×§×¨×™×¡×” בעקבות ב××’ של המפרש של דלפי (“$2†עולה על “$1†×שר מכיל טיפוס × ×ª×•× ×™× ×חר בהחזרה)
+% If you declare overridden methods in a class definition, they must
+% have the same return type. Some versions of Delphi allow you to change the
+% return type of interface methods, and even to change procedures into
+% functions, but the resulting code may crash depending on the types used
+% and the way the methods are called.
+parser_e_dispid_must_be_ord_const=03219_E_מזהה Dispatch חייב להיות קבוע בעל ערך סידורי
+parser_e_array_range_out_of_bounds=03220_E_הטווח של המערך גבוהה מידי
+% Regardless of the size taken up by its elements, an array cannot have more
+% than high(ptrint) elements. Additionally, the range type must be a subrange
+% of ptrint.
+parser_e_packed_element_no_var_addr=03221_E_×œ× × ×™×ª×Ÿ ×œ×ž×¦×•× ×ת הכתובת של ביט המערך ×רוז, ××œ×ž× ×˜×™× ×ו שדות של המערך
+% If you declare an array or record as \var{packed} in Mac Pascal mode (or as \var{packed} in any mode with \var{\{\$bitpacking on\}}), it will
+% be packed at the bit level. This means it becomes impossible to take addresses
+% of individual array elements or record fields. The only exception to this rule is in case of packed arrays elements
+% whose packed size is a multple of 8 bits.
+parser_e_packed_dynamic_open_array=03222_E_×œ× × ×™×ª×Ÿ ל×רוז מערך דינ×מי
+% Only regular (and possibly in the future also open) arrays can be packed
+parser_e_packed_element_no_loop=03223_E_××œ×ž× ×˜×™× ×•×©×“×•×ª של מערכי ביט ××¨×•×–×™× ××™× × ×™×›×•×œ×™× ×œ×©×ž×© ×›×ž×©×ª× ×™× ×œ×œ×•×œ×ות
+% If you declare an array or record as \var{packed} in Mac Pascal mode (or as \var{packed} in any mode with \var{\{\$bitpacking on\}}), it will
+% be packed at the bit level. For performance reasons, they cannot be
+% used as loop variables.
+parser_e_type_and_var_only_in_generics=03224_E_ניתן להשתמש ב VAR ו TYPE רק ×¢× generics
+% The usage of VAR and TYPE to declare new types inside an object is allowed only inside
+% generics.
+parser_e_cant_create_generics_of_this_type=03225_E_הטיפוס ×ינו יכול להיות generic
+% Only Classes, Objects, Interfaces and Records are allowed to be used as generic
+parser_w_no_lineinfo_use_switch=03226_W_×ין לטעון ×ת הספרייה LINEINFO בצורה ידנית. על מנת להשתמש בספרייה יש להשתמש במתג -gl במקו×
+% Do not use the LINEINFO unit directly, Use the \var{-gl} switch which automatically adds the
+% unit for reading the selected type of debugging information instead.
+parser_e_no_funcret_specified=03227_E_×œ× ×¦×•×™×™×Ÿ טיפוס החזרה עבור הפונקציה "$1"
+% The first time you declare a function you have to declare it completely,
+% including all parameters and the result type.
+parser_e_special_onlygenerics=03228_E_השימוש בSpecialization מורשה רק ×›×שר ×ž×©×ª×ž×©×™× ×‘×˜×™×¤×•×¡×™ generic
+% Types not being generics can't be specialized
+parser_e_no_generics_as_params=03229_E_×œ× × ×™×ª×Ÿ להשתמש בgenerics בתור ×¤×¨×ž×˜×¨×™× ×›×שר יש שימוש ב spezializing generics
+% When specializing a generic, only non-generic types can be used as parameters.
+parser_e_type_object_constants=03230_E_השימוש ×‘×§×‘×•×¢×™× ×©×œ ××•×‘×™×™×§×˜×™× ×”×ž×›×™×œ×™× VMT ×ינו מורשה
+% If an object requires a VMT either because it contains a constructor or virtual methods,
+% it's not allowed to create constants of it. In TP and Delphi mode this is allowed
+% for compatibility reasons.
+parser_e_label_outside_proc=03231_E_שימוש בכתובת של תוויות המוכרזות מחוץ ×œ×ž×ª×—× ×”× ×•×›×—×™ ×ינו מורשה
+% It isn't allowed to take the addresss of labels outside the
+% current procedure.
+parser_e_initialized_not_for_external=03233_E_×œ× × ×™×ª×Ÿ ל×תחל ערך ברירת מחדל ×œ×ž×©×ª× ×™× ×”×ž×•×’×“×¨×™× ×›external
+% Variables declared as external can not be initialized with a default value.
+parser_e_illegal_function_result=03234_E_טיפוס החזרה של הפונקציה ×ינו חוקי
+% Some types like file types can not be used as function result
+parser_e_no_common_type=03235_E_×ין טיפוס משותף ל "$1" ו "$2"
+% To perform an operation beween integers, the compiler converts both operands
+% to their common type, which appears to be an invalid type. To determine the
+% common type of the operands, the compiler takes the minimum of the minimal values
+% of both types, and the maximum of the maximal values of both types. The common
+% type is then minimum..maximum.
+parser_e_no_generics_as_types=03236_E_Generics ×œ×œ× specialization ×ינו יכול להיות בשימוש בתור טיפוס למשתנה
+% Generics must be always specialized before being used as variable type
+parser_w_register_list_ignored=03237_W_×ž×ª×¢×œ× ×ž×¨×©×™×ž×ª ×”××•×’×¨×™× ×¢×‘×•×¨ שגרות assemblter טהורות
+% When using pure assembler routines, the list with modified registers is ignored.
+
+% \end{description}
+#
+# Type Checking
+#
+# 04049 is the last used one
+#
+% \section{Type checking errors}
+% This section lists all errors that can occur when type checking is
+% performed.
+% \begin{description}
+type_e_mismatch=04000_E_טיפוס × ×ª×•× ×™× ×œ× ×—×•×¤×£
+% This can happen in many cases:
+% \begin{itemize}
+% \item The variable you're assigning to is of a different type than the
+% expression in the assignment.
+% \item You are calling a function or procedure with parameters that are
+% incompatible with the parameters in the function or procedure definition.
+% \end{itemize}
+type_e_incompatible_types=04001_E_טיפוס × ×ª×•× ×™× ×œ× ×ª×•××: נעשה שימוש ב "$1" מצפה ל"$2"
+% There is no conversion possible between the two types
+% Another possiblity is that they are declared in different
+% declarations:
+% \begin{verbatim}
+% Var
+% A1 : Array[1..10] Of Integer;
+% A2 : Array[1..10] Of Integer;
+%
+% Begin
+% A1:=A2; { This statement gives also this error, it
+% is due the strict type checking of pascal }
+% End.
+% \end{verbatim}
+type_e_not_equal_types=04002_E_××™ הת×מה בין טיפוסי ×”× ×ª×•× ×™× "$1" ו "$2"
+% The types are not equal
+type_e_type_id_expected=04003_E_מצפה לטיפוס נתוני×
+% The identifier is not a type, or you forgot to supply a type identifier.
+type_e_variable_id_expected=04004_E_מצפה למזהה של משתנה
+% This happens when you pass a constant to a routine (such as \var{Inc} var or \var{Dec})
+% when it expects a variable. You can only pass variables as arguments to these functions.
+type_e_integer_expr_expected=04005_E_מצפה למספר של×, ×ך התקבל "$1"
+% The compiler expects an expression of type integer, but gets a different
+% type.
+type_e_boolean_expr_expected=04006_E_מצפה לביטוי בולי×× ×™, ×ך התקבל "$1"
+% The expression must be a boolean type, it should be return true or
+% false.
+type_e_ordinal_expr_expected=04007_E_מצפה לטיפוס סודר
+% The expression must be of ordinal type, i.e., maximum a \var{Longint}.
+% This happens, for instance, when you specify a second argument
+% to \var{Inc} or \var{Dec} that doesn't evaluate to an ordinal value.
+type_e_pointer_type_expected=04008_E_מצפה למצביע, ×ך התקבל "$1"
+% The variable or expression isn't of the type \var{pointer}. This
+% happens when you pass a variable that isn't a pointer to \var{New}
+% or \var{Dispose}.
+type_e_class_type_expected=04009_E_מצפה למחלקה, ×ך התקבל "$1"
+% The variable of expression isn't of the type \var{class}. This happens
+% typically when
+% \begin{enumerate}
+% \item The parent class in a class declaration isn't a class.
+% \item An exception handler (\var{On}) contains a type identifier that
+% isn't a class.
+% \end{enumerate}
+type_e_cant_eval_constant_expr=04011_E_×œ× × ×™×ª×Ÿ לנתח ×ת הביטוי הקבוע
+% This error can occur when the bounds of an array you declared does
+% not evaluate to ordinal constants
+type_e_set_element_are_not_comp=04012_E_×”××œ×ž× ×˜×™× ×©×œ הקבוצה ××™× × ×ª×•×מי×
+% You are trying to make an operation on two sets, when the set element types
+% are not the same. The base type of a set must be the same when taking the
+% union
+type_e_set_operation_unknown=04013_E_הפעולה ××™× ×” בשימוש ×¢× ×§×‘×•×¦×•×ª
+% several binary operations are not defined for sets
+% like div mod ** (also >= <= for now)
+type_w_convert_real_2_comp=04014_W_המרה ×וטומטית של טיפוס עשרוני ל COMP ×שר ×”×•× ×ž×¡×¤×¨ של×
+% An implicit type conversion from a real type to a \var{comp} is
+% encountered. Since \var{comp} is a 64 bit integer type, this may indicate
+% an error.
+type_h_use_div_for_int=04015_H_השתמש בDIV ×‘×ž×§×•× ×¢×œ מנת לקבל תוצ××” של מספר של×
+% When hints are on, then an integer division with the '/' operator will
+% procuce this message, because the result will then be of type real
+type_e_strict_var_string_violation=04016_E_טיפוס המחרוזת ××™× × ×ª×•×× ×‘×’×œ×œ השימוש במתג $V+
+% When compiling in \var{\{\$V+\}} mode, the string you pass as a parameter
+% should be of the exact same type as the declared parameter of the procedure.
+type_e_succ_and_pred_enums_with_assign_not_possible=04017_E_×œ× × ×™×ª×Ÿ להציב ×¢×¨×›×™× ×œ×ž× ×™×•×ª תוך שימוש בsucc ×ו pred
+% When you declared an enumeration type which has assignments in it, as in C,
+% like in the following:
+% \begin{verbatim}
+% Tenum = (a,b,e:=5);
+% \end{verbatim}
+% you cannot use the \var{Succ} or \var{Pred} functions on them.
+type_e_cant_read_write_type=04018_E_×œ× × ×™×ª×Ÿ ×œ×§×¨×•× ×ו לכתוב ×ž×©×ª× ×™× ×ž×”×¡×•×’ הנוכחי
+% You are trying to \var{read} or \var{write} a variable from or to a
+% file of type text, which doesn't support that. Only integer types,
+% reals, pchars and strings can be read from/written to a text file.
+% Booleans can only be written to text files.
+type_e_no_readln_writeln_for_typed_file=04019_E_×œ× × ×™×ª×Ÿ להשתמש בreadln וwriteln על טיפוס × ×ª×•× ×™× ×ž×¡×•×’ file
+% \var{readln} and \var{writeln} are only allowed for text files.
+type_e_no_read_write_for_untyped_file=04020_E_×œ× × ×™×ª×Ÿ ×œ×§×¨×•× ×ו לכתוב טיפוס ×œ× ×ž×•×’×¨ של קבצי×
+% \var{read} and \var{write} are only allowed for text or typed files.
+type_e_typeconflict_in_set=04021_E_התנגשות של טיפוס × ×ª×•× ×™× ×‘×ª×•×š ××™×‘×¨×™× ×©×œ קבוצה
+% There is at least one set element which is of the wrong type, i.e. not of
+% the set type.
+type_w_maybe_wrong_hi_lo=04022_W_lo/hi(dword/qword) מחזיר ×ת הערך העליון/תחתון של word/dword
+% \fpc supports an overloaded version of \var{lo/hi} for \var{longint/dword/int64/qword}
+% which returns the lower/upper word/dword of the argument. TP always uses
+% a 16 bit \var{lo/hi} which returns always bits 0..7 for \var{lo} and the
+% bits 8..15 for \var{hi}. If you want the TP behavior you have
+% to type cast the argument to \var{word/integer}
+type_e_integer_or_real_expr_expected=04023_E_מצפה לביטוי של מספר ×©×œ× ×ו מספר ממשי
+% The first argument to \var{str} must a real or integer type.
+type_e_wrong_type_in_array_constructor=04024_E_שימוש שגוי בטיפוס "$1" בתוך יוצר המערך
+% You are trying to use a type in an array constructor which is not
+% allowed.
+type_e_wrong_parameter_type=04025_E_טיפוס ×œ× ×ž×ª××™× ×œ×רגומנט מספר $1: התקבל "$2", מצפה ל"$3"
+% You are trying to pass an invalid type for the specified parameter.
+type_e_no_method_and_procedure_not_compatible=04026_E_המשתנה של המתודה והשגרה ××™× × ×ª×•×מי×
+% You can't assign a method to a procedure variable or a procedure to a
+% method pointer.
+type_e_wrong_math_argument=04027_E_ביטוי קבוע ×œ× ×—×•×§×™ הוזן לפונקציה מתמטית פנימית
+% The constant argument passed to a ln or sqrt function is out of
+% the definition range of these functions.
+type_e_no_addr_of_constant=04028_E_×œ× × ×™×ª×Ÿ לקבל ×ת הכתובת של הקבוע
+% It is not possible to get the address of a constant expression, because they
+% aren't stored in memory. You can try making it a typed constant. This error
+% can also be displayed if you try to pass a property to a var parameter.
+type_e_argument_cant_be_assigned=04029_E_×œ× × ×™×ª×Ÿ ×œ×”×©×™× ×ת ×”×רגומנט
+% Only expressions which can be on the left side of an
+% assignment can be passed as call by reference argument
+% Remark: Properties can be only
+% used on the left side of an assignment, but they cannot be used as arguments
+type_e_cannot_local_proc_to_procvar=04030_E_×œ× × ×™×ª×Ÿ לשייך פונקציה/שיגרה מקומית למשתנה מסוג שיגרה
+% It's not allowed to assign a local procedure/function to a
+% procedure variable, because the calling of local procedure/function is
+% different. You can only assign local procedure/function to a void pointer.
+type_e_no_assign_to_addr=04031_E_×œ× × ×™×ª×Ÿ לשייך ערך לכתובת
+% It is not allowed to assign a value to an address of a variable,constant,
+% procedure or function. You can try compiling with -So if the identifier
+% is a procedure variable.
+type_e_no_assign_to_const=04032_E_×œ× × ×™×ª×Ÿ לשייך ערך למשתנה קבוע
+% It's not allowed to assign a value to a variable which is declared
+% as a const. This is normally a parameter declared as const, to allow
+% changing the value make the parameter as a value parameter or a var.
+type_e_array_required=04033_E_נדרש משתנה מסוג מערך
+% If you are accessing a variable using an index '[<x>]' then
+% the type must be an array. In FPC mode also a pointer is allowed.
+type_e_interface_type_expected=04034_E_מצפה לטיפוס מסוג ממשק, ×בל התקבל "$1"
+% The compiler expected to encounter an interface type name, but got something else.
+% The following code would provoke this error:
+% \begin{verbatim}
+% Type
+% TMyStream = Class(TStream,Integer)
+% \end{verbatim}
+type_w_mixed_signed_unsigned=04035_W_עירבוב ביטויי ×¡×™×ž× ×™× ×•longwords ×ž×¡×¤×§×™× ×ª×•×¦××” של 64bit
+% If you divide (or calculate the modulus of) a signed expression by a longword (or vice versa),
+% or if you have overflow and/or range checking turned on and use an arithmetic
+% expression (+, -, *, div, mod) in which both signed numbers and longwords appear,
+% then everything has to be evaluated in 64bit which is slower than normal
+% 32bit arithmetic. You can avoid this by typecasting one operand so it
+% matches the result type of the other one.
+type_w_mixed_signed_unsigned2=04036_W_ערבוב ביטויי ×¡×™×ž× ×™× ×•×ž×¡×¤×¨×™× ×©×œ×ž×™× ×’×‘×•×”×™× ×¢×œ×•×œ ×œ×’×¨×•× ×œ×©×’×™×ת טווח מספרי×
+% If you use a binary operator (and, or, xor) and one of
+% the operands is a longword while the other one is a signed expression, then,
+% if range checking is turned on, you may get a range check error because in
+% such a case both operands are converted to longword before the operation is
+% carried out. You can avoid this by typecasting one operand so it
+% matches the result type of the other one.
+type_e_typecast_wrong_size_for_assignment=04037_E_ישנו הבדל בגודל בהצבה של typecast ($1-> $2)
+% Type casting to a type with a different size is not allowed when the variable is
+% used for assigning.
+type_e_array_index_enums_with_assign_not_possible=04038_E_מניות ×¢× ×ª×•×›×Ÿ של הצבה ××™× × ×™×›×•×œ×™× ×œ×©×ž×© בתור ×ינדקס למערך
+% When you declared an enumeration type which has assignments in it, as in C,
+% like in the following:
+% \begin{verbatim}
+% Tenum = (a,b,e:=5);
+% \end{verbatim}
+% you cannot use it as index of an array.
+type_e_classes_not_related=04039_E_×ין קירבה בין טיפוסי מחלקות ×ו ××•×‘×™×™×§×˜×™× ×©×œ "$1" ו "$2"
+% There is a typecast from one class or object to another while the class/object
+% are not related. This will probably lead to errors
+type_w_classes_not_related=04040_W_×ין קירבה בין טיפוסי המחלקות של "$1" ו "$2"
+% There is a typecast from one class or object to another while the class/object
+% are not related. This will probably lead to errors
+type_e_class_or_interface_type_expected=04041_E_מצפה לטיפוסי מחלקות ×ו ממשקי×, ×בל "$1" התקבל
+% The compiler expected a class or interface name, but got another type or identifier.
+type_e_type_is_not_completly_defined=04042_E_הטיפוס "$1" ×œ× ×”×•×’×“×¨ במלו×ו
+% This error occurs when a type is not complete: i.e. a pointer type which points to
+% an undefined type.
+type_w_string_too_long=04043_W_התוכן של המחרוזת מכיל יותר ×ª×•×•×™× ×ž×ž×” שניתן להכיל ב×ורך של מחרוזת קצרה
+% The size of the constant string, which is assigned to a shortstring,
+% is longer than the maximum size of the shortstring
+type_w_signed_unsigned_always_false=04044_W_ההשוו××” תמיד תחזיר ערך של false בגלל טווח הערכי×
+% There is a comparison between an unsigned value and a signed constant which is
+% less than zero. Because of type promotion, the statement will always evaluate to
+% false. Exlicitly typecast the constant to the correct range to avoid this problem.
+type_w_signed_unsigned_always_true=04045_W_ההשוו××” תמיד תחזיר ערך של true בגלל טווח הערכי×
+% There is a comparison between an unsigned value and a signed constant which is
+% less than zero. Because of type promotion, the statement will always evaluate to
+% true. Exlicitly typecast the constant to the correct range to avoid this problem.
+type_w_instance_with_abstract=04046_W_מ×תחל ×ת המחלקה "$1" ×¢× ×ž×ª×•×“×•×ª ×œ× ×ž×ž×•×ž×©×•×ª
+% An instance of a class is created which contains non-implemented abstract
+% methods. This will probably lead to a runtime error 211 in the code if that
+% routine is ever called. All abstract methods should be overridden.
+type_h_in_range_check=04047_H_הערך השמ×לי של ×”×ופרנד IN צריך להיות בגודל של בית
+% The left operand of the \var{in} operator is not an ordinal or enumeration which fits
+% within 8-bits, this may lead to range check errors. The \var{in} operator
+% currently only supports a left operand which fits within a byte. In the case of
+% enumerations, the size of an element of an enumeration can be controlled with
+% the \var{\{\$PACKENUM\}} or \var{\{\$Zn\}} switches.
+type_w_smaller_possible_range_check=04048_W_גודל הטיפוס ×ינו מת××™×, ישנה ×פשרות ל×יבוד מידע ×ו שגי××” בבדיקת הטווח
+% There is an assignment to a smaller type than the source type. This means that
+% this may cause a range-check error, or may lead to possible loss of data.
+type_h_smaller_possible_range_check=04049_H_גודל הטיפוס ×ינו מת××™×, ישנה ×פשרות ל×יבוד מידע ×ו שגי××” בבדיקת הטווח
+% There is an assignment to a smaller type than the source type. This means that
+% this may cause a range-check error, or may lead to possible loss of data.
+type_e_cant_take_address_of_abstract_method=04050_E_×œ× × ×™×ª×Ÿ לספק ×ת כתובת המתודה המוגדרת ×› abstract
+% An abstract method has no body, so the address of an abstract method can't be taken.
+type_e_assignment_not_allowed=04051_E_×œ× × ×™×ª×Ÿ לשייך ×ת הערך ×œ×¤×¨×ž×˜×¨×™× ×¨×©×ž×™×™× ×•×ž×¢×¨×›×™× ×¤×ª×•×—×™×
+% You are trying to assign a value to a formal (untyped var, const or out)
+% parameter, or to an open array.
+type_e_constant_expr_expected=04052_E_מצפה לביטוי קבוע
+% The compiler expects an constant expression, but gets a variable expression.
+type_e_operator_not_supported_for_types=04053_E_הפעולה "$1" ××™× ×” נתמכת ×œ×˜×™×¤×•×¡×™× "$1" ו "$3"
+% The operation is not allowed for the supplied types
+type_e_illegal_type_conversion=04054_E_המרה ×œ× ×—×•×§×™×ª של הטיפוס של "$1" ל "$2"
+% When doing a type-cast, you must take care that the sizes of the variable and
+% the destination type are the same.
+type_h_pointer_to_longint_conv_not_portable=04055_H_ההמרה בין מספר למצביע ××™× ×” ×פשרית בכל המערכות
+% If you typecast a pointer to a longint (or vice-versa), this code will not compile
+% on a machine using 64-bit for pointer storage.
+type_w_pointer_to_longint_conv_not_portable=04056_W_ההמרה בין מספר למצביע ××™× ×” ×פשרית בכל המערכות
+% If you typecast a pointer to a ordinal type of a different size (or vice-versa), this can
+% cause problems. This is a warning to help finding the 32bit specific code where cardinal/longint is used
+% to typecast pointers to ordinals. A solution is to use the ptrint/ptruint types instead.
+type_e_cant_choose_overload_function=04057_E_×œ× × ×™×ª×Ÿ להחליט ב×יזו פונקצית עמוסת יתר להשתמש
+% You're calling overloaded functions with a parameter that doesn't correspond
+% to any of the declared function parameter lists. e.g. when you have declared
+% a function with parameters \var{word} and \var{longint}, and then you call
+% it with a parameter which is of type \var{integer}.
+type_e_illegal_count_var=04058_E_משתנה ספירה ×œ× ×—×•×§×™
+% The type of a \var{for} loop variable must be an ordinal type.
+% Loop variables cannot be reals or strings.
+type_w_double_c_varargs=04059_W_ממיר ×ת הטיפוס real לטיפוס double למשתנה C. הוסף typecast ספציפי למנוע ×ת המצב.
+% In C, constant real values are double by default. For this reason, if you
+% pass a constant real value to a variable argument part of a C function, FPC
+% by default converts this constant to double as well. If you want to prevent
+% this from happening, add an explicit typecast around the constant.
+type_e_class_or_cominterface_type_expected=04060_E_מצפה לטיפוס מחלקה ×ו ממשק COM, ×בל התקבל "$1"
+% Some operators like the AS operator are only appliable to classes or COM interfaces.
+type_e_no_const_packed_array=04061_E_×ין תמיכה במערך קבוע דחוס
+% You cannot declare a (bit)packed array as a typed constant.
+type_e_got_expected_packed_array=04062_E_חוסר ת×ימות לטיפוס ×”× ×ª×•× ×™× ×©×œ ×רגומנט $1. התקבל: "$2" ×ž×¦× ×œ "(bit)packed array"
+% The compiler expects a (bit)packed array as the specified parameter
+type_e_got_expected_unpacked_array=04063_E_חוסר ת×ימות טיפוס ×”× ×ª×•× ×™× ×©×œ ×רגומנט $1. התקבל "$2" מצפה ל "(not packed) Array"
+% The compiler expects a regular (i.e., not packed) array as the specified parameter
+type_e_no_packed_inittable=04064_E_××œ×ž×˜×™× ×©×œ מערך דחוס ××™× × ×™×›×•×œ×™× ×œ×”×™×•×ª מטיפוס × ×ª×•× ×™× ×שר דורש ×תחול
+% Support for packed arrays of types that need initialization (such as ansistrings, or records which contain ansistrings) is not yet implemented.
+type_e_no_const_packed_record=04065_E_×ין תמיכה לרשומות ו××‘×™×™×§×˜×™× ×§×‘×•×¢×™× ×•×“×—×•×¡×™×
+% You cannot declare a (bit)packed array as a typed constant at this time.
+type_w_untyped_arithmetic_unportable=04066_W_חישוב "$1" על טיפוס ×œ× ×ž×•×’×“×¨ של מצביע ×ינו נתמך במצב {$T+}, ×ך ניתן להשתמש בtypecast
+% Addition/subtraction from untyped pointer may work differently in \var{\{\$T+\}}, use typecast to typed pointer
+type_e_cant_take_address_of_local_subroutine=04076_E_×œ× × ×™×ª×Ÿ לקחת ×ת כתובת השיגרה המסומנת כמקומית
+% The address of a subroutine marked as local can't be taken.
+type_e_cant_export_local=04077_E_×œ× × ×™×ª×Ÿ ×œ×™×™×¦× ×©×™×’×¨×” המסומנת כמקומית בתוך יחידה
+% A subroutine marked as local can't be export from a unit.
+type_e_not_automatable=04078_E_הטיפוס ×ינו ×וטומט: "$1"
+% Only byte, integer, longint, smallint, currency, single, double, ansistring,
+% widestring, tdatetime, variant, olevariant, wordbool and all interfaces are automatable.
+type_h_convert_add_operands_to_prevent_overflow=04079_H_המרת ×”×ופרנד ל"$1" לפני פעולת החיבור, יכול למנוע שגי×ות גלישה.
+% Adding two types can cause overflow errors. Since you are converting the result to a larger type, you
+% could prevent such errors by converting the operands to this type before doing the addition.
+type_h_convert_sub_operands_to_prevent_overflow=04080_H_המרת ×”×ופרנד ל"$1" לפני פעולת החיבור יכולה למנוע שגי×ות גלישה.
+% Subtracting two types can cause overflow errors. Since you are converting the result to a larger type, you
+% could prevent such errors by converting the operands to this type before doing the subtraction.
+type_h_convert_mul_operands_to_prevent_overflow=04081_H_המרת ×”×ופרנד "$1" לפני פעולת הכפל יכולה למנוע שגי×ות גלישה.
+% Multiplying two types can cause overflow errors. Since you are converting the result to a larger type, you
+% could prevent such errors by converting the operands to this type before doing the multiplication.
+type_w_pointer_to_signed=04082_W_המרת ×ž×¦×‘×™×¢×™× ×œ×ž×¡×¤×¨×™× ×©×œ×ž×™× ×¢× ×¡×™×ž×Ÿ עלולה ×œ×’×¨×•× ×œ×©×’×™×ות בתוצ×ות השוו××” ובטווחי×. יש להשתמש ×‘×ž×§×•× ×–×ת בטיפוס ×œ×œ× ×¡×™×ž×Ÿ.
+% The virtual address space on 32-bit machines runs from \$00000000 to \$ffffffff. Many operating systems allow you to
+% allocate memory above \$80000000, for example both Windows and Linux allow pointers in the range \$0000000 to \$bfffffff.
+% If you convert pointers to signed types, this can cause overflow and range check errors, but also \$80000000 < \$7fffffff.
+% This can cause random errors in code like "if p>q".
+% \end{description}
+#
+# Symtable
+#
+# 05060 is the last used one
+#
+% \section{Symbol handling}
+% This section lists all the messages that concern the handling of symbols.
+% This means all things that have to do with procedure and variable names.
+% \begin{description}
+sym_e_id_not_found=05000_E_המזהה ×œ× × ×ž×¦× "$1"
+% The compiler doesn't know this symbol. Usually happens when you misspel
+% the name of a variable or procedure, or when you forgot to declare a
+% variable.
+sym_f_internal_error_in_symtablestack=05001_F_שגי××” פנימית בSymTableStack()
+% An internal error occurred in the compiler; If you encounter such an error,
+% please contact the developers and try to provide an exact description of
+% the circumstances in which the error occurs.
+sym_e_duplicate_id=05002_E_מזהה כפול "$1"
+% The identifier was already declared in the current scope.
+sym_h_duplicate_id_where=05003_H_המזהה כבר מוגדר ב$1 בשורה $2
+% The identifier was already declared in a previous scope.
+sym_e_unknown_id=05004_E_מזהה ×œ× ×ž×•×›×¨ "$1"
+% The identifier encountered has not been declared, or is used outside the
+% scope where it is defined.
+sym_e_forward_not_resolved=05005_E_הגדרת Forward ×œ× ×ž×ž×•×ž×©×ª
+% This can happen in two cases:
+% \begin{itemize}
+% \item This happens when you declare a function (in the \var{interface} part, or
+% with a \var{forward} directive, but do not implement it.
+% \item You reference a type which isn't declared in the current \var{type}
+% block.
+% \end{itemize}
+sym_e_error_in_type_def=05007_E_שגי××” בהגדרת טיפוס
+% There is an error in your definition of a new array type:
+% \item One of the range delimiters in an array declaration is erroneous.
+% For example, \var{Array [1..1.25]} will trigger this error.
+sym_e_forward_type_not_resolved=05009_E_הגדרת הטיפוס ×œ× ×”×•×©×œ×” "$1"
+% A symbol was forward defined, but no declaration was encountered.
+sym_e_only_static_in_static=05010_E_רק ×ž×©×ª× ×™× ×¡×˜×˜×™×™× ×™×›×•×œ×™× ×œ×”×™×•×ª בשימוש ×¢× ×ž×ª×•×“×•×ª סטטיות ×ו מחוץ למטודות
+% A static method of an object can only access static variables.
+sym_f_type_must_be_rec_or_class=05012_F_מצפה לטיפוס של רשומה ×ו טיפוס של מחלקה
+% The variable or expression isn't of the type \var{record} or \var{class}.
+sym_e_no_instance_of_abstract_object=05013_E_××“×’× ×©×œ מחלקות ×ו ××•×‘×™×™×§×˜×™× ×¢× ×ž×ª×•×“×•×ª abstract ××™× × ×ž×•×¨×©×™×
+% You are trying to generate an instance of a class which has an abstract
+% method that wasn't overridden.
+sym_w_label_not_defined=05014_W_התווית "$1" ××™× ×” מוגדרת
+% A label was declared, but not defined.
+sym_e_label_used_and_not_defined=05015_E_התווית "$1" בשימוש, ×בל ×œ× ×ž×’×“×¨×ª
+% A label was declared and used, but not defined.
+sym_e_ill_label_decl=05016_E_הגדרת תווית ×œ× ×—×•×§×™×ª
+% This error should never happen; it occurs if a label is defined outside a
+% procedure or function.
+sym_e_goto_and_label_not_supported=05017_E_GOTO ו LABEL ××™× × × ×ª×ž×›×™× (השתמש במתג -Sg)
+% You must compile a program which has \var{label}s and \var{goto} statements
+% with the \var{-Sg} switch. By default, \var{label} and \var{goto} aren't
+% supported.
+sym_e_label_not_found=05018_E_התווית ×œ× × ×ž×¦××”
+% A \var{goto label} was encountered, but the label isn't declared.
+sym_e_id_is_no_label_id=05019_E_המזהה ×ינו תווית
+% The identifier specified after the \var{goto} isn't of type label.
+sym_e_label_already_defined=05020_E_התווית כבר הוגדרה
+% You are defining a label twice. You can define a label only once.
+sym_e_ill_type_decl_set=05021_E_הגדרת טיפוס סידרה ×œ× ×—×•×§×™×ª
+% The declaration of a set contains an invalid type definition.
+sym_e_class_forward_not_resolved=05022_E_הגדרה מקדימה של מחלקה "$1" ×œ× ×ž×ž×•×ž×©×ª
+% You declared a class, but you did not implement it.
+sym_n_unit_not_used=05023_H_היחידה "$1" ××™× ×” בשימוש ב $2
+% The unit referenced in the \var{uses} clause is not used.
+sym_h_para_identifier_not_used=05024_H_הפרמטר "$1" ×ינו בשימוש
+% The identifier was declared (locally or globally) but
+% was not used (locally or globally).
+sym_n_local_identifier_not_used=05025_N_המשתנה המקומי "$1" ×ינו בשימוש
+% You have declared, but not used a variable in a procedure or function
+% implementation.
+sym_h_para_identifier_only_set=05026_H_הערך של הפרמטר "$1" הוזן ×ך ×”×•× ×œ× ×‘×©×™×ž×•×©
+% The identifier was declared (locally or globally)
+% set but not used (locally or globally).
+sym_n_local_identifier_only_set=05027_N_הערך של הפרמטר "$1" הוזן ×ך ×”×•× ×œ× ×‘×©×™×ž×•×©
+% The variable in a procedure or function
+% implementation is declared, set but never used.
+sym_h_local_symbol_not_used=05028_H_$1 "$2" מקומי ×œ× ×‘×©×™×ž×•×©
+% A local symbol is never used.
+sym_n_private_identifier_not_used=05029_N_שדה פרטי "$1.$2" ×œ× ×‘×©×™×ž×•×©
+% The indicated private field is defined, but is never used in the code.
+sym_n_private_identifier_only_set=05030_N_השדה הפרטי "$1.$2" בעל ערך, ×ך ×œ× ×‘×©×™×ž×•×©
+% The indicated private field is declared, assigned but never read.
+sym_n_private_method_not_used=05031_N_המתודה הפרטית "$1.$2" ××™× ×” בשימוש
+% The indicated private method is declared but is never used in the code.
+sym_e_set_expected=05032_E_מצפה לטיפוס סדרה
+% The variable or expression is not of type \var{set}. This happens in an
+% \var{in} statement.
+sym_w_function_result_not_set=05033_W_הפונקציה כנר××” ×œ× ×ž×—×–×™×¨×” ערך
+% You can get this warning if the compiler thinks that a function return
+% value is not set. This will not be displayed for assembler procedures,
+% or procedures that contain assembler blocks.
+sym_w_wrong_C_pack=05034_W_הטיפוס "$1" ×ינו מייושר נכון לרשומה של שפת C
+% Arrays with sizes not multiples of 4 will be wrongly aligned
+% for C structures.
+sym_e_illegal_field=05035_E_שדה של רשומה ×œ× ×—×•×§×™ "$1"
+% The field doesn't exist in the record/object definition.
+sym_w_uninitialized_local_variable=05036_W_המשתנה המקומי "$1" ×ינו נר××” מ×ותחל
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_w_uninitialized_variable=05037_W_המשתנה "$1" ×ינו נר××” מ×ותחל
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_e_id_no_member=05038_E_המזהה בשימוש ×ינו חבר ב"$1"
+% This error is generated when an identifier of a record,
+% field, or method is accessed while it is not defined.
+sym_h_param_list=05039_H_נמצ××” ההכרזה: $1
+% You get this when you use the \var{-vh} switch. In case an overloaded
+% procedure is not found, then all candidate overloaded procedures are
+% listed, with their parameter lists.
+sym_e_segment_too_large=05040_E_גודל המידע של ×”×למנט גדול מידי
+% You get this when you declare a data element whose size exceeds the
+% prescribed limit (2 Gb on 80386+/68020+ processors)
+sym_e_no_matching_implementation_found=05042_E_×œ× × ×ž×¦× ×‘×™×¦×•×¢ למתודה "$1" של הממשק
+% There was no matching method found which could implement the interface
+% method. Check argument types and result type of the methods.
+sym_w_deprecated_symbol=05043_W_הסימול "$1" מיושן
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{deprecated} is used. Deprecated symbols may no longer
+% be available in newer versions of the unit / library. Usage of this symbol
+% should be avoided as much as possible.
+sym_w_non_portable_symbol=05044_W_הסימול "$1" ×ינו נייד
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{platform} is used. This symbol's value, usage
+% and availability is platform specific and should not be used
+% if the source code must be portable.
+sym_w_non_implemented_symbol=05055_W_הסימול "$1" ×ינו מבוצע
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{unimplemented} is used. This symbol is defined,
+% but is not yet implemented on this specific platform.
+sym_e_cant_create_unique_type=05056_E_×œ× × ×™×ª×Ÿ ליצור טיפוס ייחודי מהטיפוס הנוכחי
+% Only simple types like ordinal, float and string types are supported when
+% redefining a type with \var{type newtype = type oldtype;}.
+sym_h_uninitialized_local_variable=05057_H_המשתנה המקומי "$1" ×ינו נר××” מ×ותחל
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_h_uninitialized_variable=05058_H_המשתנה "$1" ×ינו נר××” מ×ותחל
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_w_function_result_uninitialized=05059_W_הערך המוחזר מהפונקציה ×ינו נר××” כמ×ותחל
+% This message is displayed if the compiler thinks that the function result
+% variable will be used (i.e. appears in the right-hand-side of an expression)
+% before it is initialized (i.e. appeared in the left-hand side of an
+% assigment)
+sym_h_function_result_uninitialized=05060_H_הערך המוחזר מהפונקציה ×ינו נר××” כמ×ותחל
+% This message is displayed if the compiler thinks that the function result
+% variable will be used (i.e. appears in the right-hand-side of an expression)
+% before it is initialized (i.e. appeared in the left-hand side of an
+% assigment)
+sym_w_identifier_only_read=05061_W_המשתנה "$1" נקר×, ×ך ×ž×¢×•×œ× ×œ× ×§×™×‘×œ תוכן
+% You have read the value of a variable, but nowhere assigned a value to
+% it.
+sym_h_abstract_method_list=05062_H_נמצ××” מתודה מופשטת: $1
+% When getting a warning about constructing a class/object with abstract methods
+% you get this hint to find the affected method.
+% \end{description}
+#
+# Codegenerator
+#
+# 06040 is the last used one
+#
+% \section{Code generator messages}
+% This section lists all messages that can be displayed if the code
+% generator encounters an error condition.
+% \begin{description}
+cg_e_parasize_too_big=06009_E_הגודר של רשימת ×¤×¨×ž×˜×¨×™× ×’×“×•×œ×” מ 65535 בתי×
+% The I386 processor limits the parameter list to 65535 bytes (the \var{RET}
+% instruction causes this)
+cg_e_file_must_call_by_reference=06012_E_טיפוס של קובץ חייב להיות משתנה מוגדר
+% You cannot specify files as value parameters, i.e. they must always be
+% declared \var{var} parameters.
+cg_e_cant_use_far_pointer_there=06013_E_השימוש במצביע far ×ינו מורשה ×‘×ž×™×§×•× ×”× ×•×›×—×™
+% Free Pascal doesn't support far pointers, so you cannot take the address of
+% an expression which has a far reference as a result. The \var{mem} construct
+% has a far reference as a result, so the following code will produce this
+% error:
+% \begin{verbatim}
+% var p : pointer;
+% ...
+% p:=@mem[a000:000];
+% \end{verbatim}
+cg_e_dont_call_exported_direct=06015_E_×œ× × ×™×ª×Ÿ ×œ×§×¨×•× ×œ×¤×•× ×§×¦×™×•×ª ×¢× ×”×’×“×¨×ª EXPORT
+% No longer in use.
+cg_w_member_cd_call_from_method=06016_W_כנר××” קרי××” ×œ× ×—×•×§×™×ª של יוצר ×ו הורס
+% The compiler detected that a constructor or destructor is called within a
+% a method. This will probably lead to problems, since constructors / destructors
+% require parameters on entry.
+cg_n_inefficient_code=06017_N_חסר קוד
+% Your statement seems dubious to the compiler.
+cg_w_unreachable_code=06018_W_×œ× × ×™×ª×Ÿ להריץ ×ת קטע הקוד
+% You specified a construct which will never be executed. Example:
+% \begin{verbatim}
+% while false do
+% begin
+% {.. code ...}
+% end;
+% \end{verbatim}
+cg_e_cant_call_abstract_method=06020_E_×œ× × ×™×ª×Ÿ ×œ×§×¨×•× ×œ×ž×ª×•×“×•×ª Abstract בצורה ישירה
+% You cannot call an abstract method directy, instead you must call a
+% overriding child method, because an abstract method isn't implemented.
+cg_d_register_weight=06027_DL_Register $1 משקל $2 $3
+% Debugging message. Shown when the compiler considers a variable for
+% keeping in the registers.
+cg_d_stackframe_omited=06029_DL_משמיט ×ת מסגרת המחסנית
+% Some procedure/functions do not need a complete stack-frame, so it is omitted.
+% This message will be displayed when the {-vd} switch is used.
+cg_e_unable_inline_object_methods=06031_E_מתודות של ×ובייקט ×ו מחלקה ××™× × ×™×›×•×œ×™× ×œ×”×™×•×ª inline
+% You cannot have inlined object methods.
+cg_e_unable_inline_procvar=06032_E_קרי×ות Procvar ××™× × ×™×›×•×œ×™× ×œ×”×™×•×ª inline
+% A procedure with a procedural variable call cannot be inlined.
+cg_e_no_code_for_inline_stored=06033_E_×ין קוד לפרוצדורות inline
+% The compiler couldn't store code for the inline procedure.
+cg_e_can_access_element_zero=06035_E_×למנט ×”×פס של ansi/wide- ×ו longstring ×œ× × ×’×™×©, השתמש ב (set)length במקו×
+% You should use \var{setlength} to set the length of an ansi/wide/longstring
+% and \var{length} to get the length of such a string types
+cg_e_cannot_call_cons_dest_inside_with=06037_E_×œ× × ×™×ª×Ÿ ×œ×§×¨×•× ×œ×™×•×¦×¨×™× ×ו ×”×•×¨×¡×™× ×‘×ª×•×š חלק של 'with'
+% Inside a \var{with} clause you cannot call a constructor or destructor for the
+% object you have in the \var{with} clause.
+cg_e_cannot_call_message_direct=06038_E_×œ× × ×™×ª×Ÿ ×œ×§×¨×•× ×œ×ž×ª×•×“×•×ª של מטפל הוד×ות בצורה ישירה
+% A message method handler method cannot be called directly if it contains an
+% explicit self argument
+cg_e_goto_inout_of_exception_block=06039_E_קפיצה ×ל תוך ×ו מחוץ לבלוק של exception
+% It is not allowed to jump in or outside of an exception block like \var{try..finally..end;}:
+% \begin{verbatim}
+% label 1;
+%
+% ...
+%
+% try
+% if not(final) then
+% goto 1; // this line will cause an error
+% finally
+% ...
+% end;
+% 1:
+% ...
+% \end{verbatim}
+cg_e_control_flow_outside_finally=06040_E_השימוש ×‘×‘×™×˜×•×™×™× ×”×©×•×œ×˜×™× ×‘×–×¨×™×ž×ª הקוד ××™× × ×ž×•×¨×©×™× ×‘×—×œ×§ ×” finally
+% It isn't allowed to use the control flow statements \var{break},
+% \var{continue} and \var{exit}
+% inside a finally statement. The following example shows the problem:
+% \begin{verbatim}
+% ...
+% try
+% p;
+% finally
+% ...
+% exit; // This exit ISN'T allowed
+% end;
+% ...
+%
+% \end{verbatim}
+% If the procedure \var{p} raises an exception the finally block is
+% executed. If the execution reaches the exit, it's unclear what to do:
+% exiting the procedure or searching for another exception handler
+cg_w_parasize_too_big=06041_W_גודל ×”×¤×¨×ž×˜×™× ×’×•×œ×© ×ת ההגבלות של חלק מהמעבדי×
+% This indicates that you are declaring more than 64K of parameters, which
+% might not be supported on other processor targets.
+cg_w_localsize_too_big=06042_W_הגודל של המשתנה המקומי גולש מהגבלות של חלק מהמעבדי×
+% This indicates that you are declaring more than 32K of local variables, which
+% might not be supported on other processor targets.
+cg_e_localsize_too_big=06043_E_גודל ×ž×©×ª× ×™× ×ž×§×•×ž×™×™× ×’×•×œ×© מהגבלות הנתמכות
+% This indicates that you are declaring more than 32K of local variables, which
+% is not supported by this processor.
+cg_e_break_not_allowed=06044_E_BREAK ×ינו מורשה
+% You're trying to use \var{break} outside a loop construction.
+cg_e_continue_not_allowed=06045_E_CONTINUE ×ינו מורשה
+% You're trying to use \var{continue} outside a loop construction.
+cg_f_unknown_compilerproc=06046_F_compilerproc "$1" ×œ× ×™×“×•×¢. בדוק ×× ×”×©×ª×ž×© בספריית זמן הריצה הנכונה.
+% The compiler expects that the runtime library contains certain subroutines. If you see this error
+% and you didn't change the runtime library code, it's very likely that the runtime library
+% you're using doesn't match the used compiler. If you changed the runtime library this error means
+% that you removed a subroutine which the compiler needs for internal use.
+cg_f_unknown_system_type=06047_F_×œ× × ×™×ª×Ÿ ×œ×ž×¦×•× ×˜×™×¤×•×¡ מערכת "$1". בדוק ×”×× ×תה משתמש בספריית זמן הריצה עדכנית.
+% The compiler expects that the runtime library contains certain type definitions. If you see this error
+% and you didn't change the runtime library code, it's very likely that the runtime library
+% you're using doesn't match the used compiler. If you changed the runtime library this error means
+% that you removed a type which the compiler needs for internal use.
+cg_h_inherited_ignored=06048_H_×ž×ª×¢×œ× ×ž×”×©×™×ž×•×© בinherited במתודה מסוג abstract
+% This messages appears only in Delphi mode when you call an abstract method
+% of a parent class via \var{inherited;}. The call is then ignored.
+cg_e_goto_label_not_found=06049_E_תווית ×” Goto "$1" ×œ× ×”×•×’×“×¨×” ×ו ×œ× ×¢×‘×¨×” ×ופטימיזציה
+% The label used in the goto definition is not defined or optimized away by the
+% unreachable code elemination.
+% \end{description}
+# EndOfTeX
+
+#
+# Assembler reader
+#
+# 07105 is the last used one
+#
+asmr_d_start_reading=07000_DL_מתחיל בסגנון מפרש ×סמבלר $1
+% This informs you that an assembler block is being parsed
+asmr_d_finish_reading=07001_DL_×”×¡×ª×™×™× × ×™×ª×•×— סגנון ×סמבלר $1
+% This informs you that an assembler block has finished.
+asmr_e_none_label_contain_at=07002_E_תבנית ×œ×œ× ×ª×•×•×™×ª מכילה ×ת התו @
+% A identifier which isn't a label can't contain a @.
+asmr_e_building_record_offset=07004_E_שגי××” בבניית היסט הרשומה
+% There has an error occured while building the offset of a record/object
+% structure, this can happend when there is no field specified at all or
+% an unknown field identifier is used.
+asmr_e_offset_without_identifier=07005_E_נעשה שימוש בOFFSET ×œ×œ× ×ž×–×”×”
+% You can only use OFFSET with an identifier. Other syntaxes aren't
+% supported
+asmr_e_type_without_identifier=07006_E_נעשה שימוש בTYPE ×œ×œ× ×ž×–×”×”
+% You can only use TYPE with an identifier. Other syntaxes aren't
+% supported
+asmr_e_no_local_or_para_allowed=07007_E_×œ× × ×™×ª×Ÿ להשתמש במשתמה מקומי ×ו פרמטר ×‘×ž×™×§×•× ×”× ×•×›×—×™
+% You can't use a local variable or parameter here, mostly because the
+% addressing of locals and parameters is done using the frame pointer register so the
+% address can't be obtained directly.
+asmr_e_need_offset=07008_E_יש צורך להשתמש ב OFFSET
+% You need to use OFFSET <id> here to get the address of the identifier.
+asmr_e_need_dollar=07009_E_יש צורך להשתמש ב$
+% You need to use $<id> here to get the address of the identifier.
+asmr_e_cant_have_multiple_relocatable_symbols=07010_E_×œ× × ×™×ª×Ÿ להשתמש ב relocatable symbols מרובי×
+% You can't have more than one relocatable symbol (variable/typed constant)
+% in one argument.
+asmr_e_only_add_relocatable_symbol=07011_E_ניתן להוסיף רק relocatable symbol
+% Relocatable symbols (variable/typed constant) can't be used with other
+% operators. Only addition is allowed.
+asmr_e_invalid_constant_expression=07012_E_ביטוי קבוע ×œ× ×—×•×§×™
+% There is an error in the constant expression.
+asmr_e_relocatable_symbol_not_allowed=07013_E_Relocatable symbol ×ינו מורשה
+% You can't use a relocatable symbol (variable/typed constant) here.
+asmr_e_invalid_reference_syntax=07014_E_תחביר הפניות ×œ× ×—×•×§×™
+% There is an error in the reference.
+asmr_e_local_para_unreachable=07015_E_×œ× × ×™×ª×Ÿ לגשת ל $1 מהקוד
+% You can not read directly the value of a local variable or parameter
+% of a higher level procedure in assembler code (except for
+% local assembler code without parameter nor locals).
+asmr_e_local_label_not_allowed_as_ref=07016_E_סימולי×/תוויות מקומיות ××™× × ×ž×•×¨×©×™× ×›×”×¤× ×™×•×ª
+% You can't use local symbols/labels as references
+asmr_e_wrong_base_index=07017_E_שימוש שגוי בבסיס ו×ינדקס של ×וגר
+% There is an error with the base and index register, they are
+% probably incorrect
+asmr_w_possible_object_field_bug=07018_W_יתכן ×›×™ יש שגי××” בטיפול השדות של ×ובייקט
+% Fields of objects or classes can be reached directly in normal or objfpc
+% modes but TP and Delphi modes treat the field name as a simple offset.
+asmr_e_wrong_scale_factor=07019_E_צויין טווח ×¡×•×œ× ×©×’×•×™
+% The scale factor given is wrong, only 1,2,4 and 8 are allowed
+asmr_e_multiple_index=07020_E_שימוש מרובה ב×ינקס ×”×וגר
+% You are trying to use more than one index register
+asmr_e_invalid_operand_type=07021_E_טיפוס ×ופרנד שגוי
+% The operand type doesn't match with the opcode used
+asmr_e_invalid_string_as_opcode_operand=07022_E_×שימוש במחרוזת ×›×ופרנד opcode שגוי: $1
+% The string specified as operand is not correct with this opcode
+asmr_w_CODE_and_DATA_not_supported=07023_W_השימוש ב@CODE ו@DATA ×œ× × ×ª×ž×š
+% @CODE and @DATA are unsupported and are ignored.
+asmr_e_null_label_ref_not_allowed=07024_E_התייחסות לתווית ריקה ××™× ×” מורשת
+asmr_e_expr_zero_divide=07025_E_חילוק ב×פס בהערכת asm
+% There is a division by zero in a constant expression
+asmr_e_expr_illegal=07026_E_ביטוי ×œ× ×—×•×§×™
+% There is an illegal expression in a constant expression
+asmr_e_escape_seq_ignored=07027_E_×ž×ª×¢×œ× ×ž×¨×¦×£ קידוד: $1
+% There is a C-styled string, but the escape sequence in the string
+% is unknown, and is therefore ignored
+asmr_e_invalid_symbol_ref=07028_E_התייחסות סימול ×œ× ×ª×§×™× ×”
+asmr_w_fwait_emu_prob=07029_W_FWAIT מסוגל ×œ×’×¨×•× ×œ×‘×¢×™×•×ª חיקוי בemu387
+asmr_w_fadd_to_faddp=07030_W_$1 ×œ×œ× ×ª×¨×’×•× ×ופרנד ל$1P
+asmr_w_enter_not_supported_by_linux=07031_W_הור×ת ENTER ××™× ×” נתמכת ×¢"×™ ליבת Linux
+% ENTER instruction can generate a stack page fault that is not
+% caught correctly by the i386 Linux page handler.
+asmr_w_calling_overload_func=07032_W_מבצע קרי××” לפונקציה משוכתבת בassembler
+% There is a call to an overloaded method in the assembler block,
+% this might be the sign there is a problem
+asmr_e_unsupported_symbol_type=07033_E_טיפוס הסימול של ×”×ופרנד ×ינו נתמך
+asmr_e_constant_out_of_bounds=07034_E_תוכן הקבוע מחוץ לגבולות
+asmr_e_error_converting_decimal=07035_E_שגי××” בזמן המרה דצימלית $1
+% A constant decimal value does not have the correct syntax
+asmr_e_error_converting_octal=07036_E_שגי××” בזמן המרה ×וקטלית $1
+% A constant octal value does not have the correct syntax
+asmr_e_error_converting_binary=07037_E_שגי××” בזמן המרה בינרית $1
+% A constant binary value does not have the correct syntax
+asmr_e_error_converting_hexadecimal=07038_E_שגי××” בזמן המרה הקסה-דצימלית $1
+% A constant hexadecimal value does not have the correct syntax
+asmr_h_direct_global_to_mangled=07039_H_$1 ×ª×•×¨×’× ×œ $2
+asmr_w_direct_global_is_overloaded_func=07040_W_$1 משוייך לפונקציה משוכתבת
+asmr_e_cannot_use_SELF_outside_a_method=07041_E_×œ× × ×™×ª×Ÿ להשתמש ב SELF מחוץ למתודה
+% There is a reference to the \var{self} symbol while it is not
+% allowed. \var{self} can only be referenced inside methods
+asmr_e_cannot_use_OLDEBP_outside_nested_procedure=07042_E_×œ× × ×™×ª×Ÿ להשתמש ב OLDEBP מחוץ לפרוצדורה מקוננת
+% There is a reference to the \var{oldebp} symbol while it is not
+% allowed. \var{oldebp} can only be referenced inside nested routines
+asmr_e_void_function=07043_W_פרוצדורות ××™× × ×™×›×•×œ×™× ×œ×”×—×–×™×¨ ערך בתוך קוד assembly
+% Trying to return a value while in a procedure. A procedure
+% does not have any return value
+asmr_e_SEG_not_supported=07044_E_SEG ×ינו נתמך
+asmr_e_size_suffix_and_dest_dont_match=07045_E_גודל סופי ויעד, ×ו מקור הגודל ××™× × ×ª×•×מי×
+% The register size and the opcode size suffix don't match. This is
+% probably an error in the assembler statement
+asmr_w_size_suffix_and_dest_dont_match=07046_W_גודל סופי ויעד, ×ו מקור הגודל ××™× × ×ª×•×מי×
+% The register size and the opcode size suffix don't match. This is
+% probably an error in the assembler statement
+asmr_e_syntax_error=07047_E_שגי××” בתחביר Assembler
+% There is an assembler syntax error
+asmr_e_invalid_opcode_and_operand=07048_E_שילוב ×œ× ×—×•×§×™ בין opcode ו×ופרנד
+% The opcode cannot be used with this type of operand
+asmr_e_syn_operand=07049_E_שגי××” בתחביר ×ופרנד בAssembler
+asmr_e_syn_constant=07050_E_שגי××” בתחביר קבוע בAssembler
+asmr_e_invalid_string_expression=07051_E_ביטוי מחרוזת ×œ× ×ª×§×™×Ÿ
+asmr_w_const32bit_for_address=07052_W_הקבוע בעל הסימול $1 לכתובת, ×”×•× ×œ× ×ž×¦×‘×™×¢
+% A constant expression represents an address which does not fit
+% into a pointer. The address is probably incorrect
+asmr_e_unknown_opcode=07053_E_opcode $1 ×ינו מוכר
+% This opcode is not known
+asmr_e_invalid_or_missing_opcode=07054_E_opcode חסר ×ו ×œ× ×ª×§×™×Ÿ
+asmr_e_invalid_prefix_and_opcode=07055_E_שילוב של תחילית וopcode ×œ× ×ª×§×™×Ÿ : $1
+asmr_e_invalid_override_and_opcode=07056_E_השילוב של שכתוב וopcode ×œ× ×ª×§×™×Ÿ: $1
+asmr_e_too_many_operands=07057_E_Too many operands on line
+% There are too many operands for this opcode. Check your
+% assembler syntax
+asmr_w_near_ignored=07058_W_×ž×ª×¢×œ× ×žNEAR
+asmr_w_far_ignored=07059_W_×ž×ª×¢×œ× ×ž FAR
+asmr_e_dup_local_sym=07060_E_שיכפול של הסימול המקומי $1
+asmr_e_unknown_local_sym=07061_E_הסימול המקומי $1 ×ינו מוגדר
+asmr_e_unknown_label_identifier=07062_E_מזהה תווית $1 ×œ× ×™×“×•×¢
+asmr_e_invalid_register=07063_E_×©× ×וגר שגוי
+% There is an unknown register name used as operand.
+asmr_e_invalid_fpu_register=07064_E_×©× ×וגר לנקודה צפה ×œ× ×ª×§×™×Ÿ
+% There is an unknown register name used as operand.
+asmr_w_modulo_not_supported=07066_W_מודולו ×œ× × ×ª×ž×š
+asmr_e_invalid_float_const=07067_E_קבוע של נקודה צפה ×œ× ×ª×§×™×Ÿ $1
+% The floating point constant declared in an assembler block is
+% invalid.
+asmr_e_invalid_float_expr=07068_E_ביטוי ×œ× ×ª×§×™×Ÿ של נקודה צפה
+% The floating point expression declared in an assembler block is
+% invalid.
+asmr_e_wrong_sym_type=07069_E_סוג סימול שגוי
+asmr_e_cannot_index_relative_var=07070_E_×œ× × ×™×ª×Ÿ לשמור ציון של פרמטר ×ו משתנה מקומי ×¢× ×וגר
+% Trying to index using a base register a symbol which is already relative
+% to a register. This is not possible, and will probably lead to crashes.
+asmr_e_invalid_seg_override=07071_E_ביטוי המיקטע המשוכתב ×ינו תקין
+asmr_w_id_supposed_external=07072_W_המזהה $1 ×ינו נמצ×, מניח שהמזהה חיצוני
+% There is a reference to an undefined symbol. This will not result
+% in an error, since the symbol might be external, but may cause
+% problems at link time if the symbol is not defined anywhere.
+asmr_e_string_not_allowed_as_const=07073_E_המחרוזות ×ינן מורשות להיות קבועות
+% Character strings are not allowed as constants.
+asmr_e_no_var_type_specified=07074_×œ× ×¦×•×™×™×Ÿ טיפוס המשתנה
+% The syntax expects a type idenfitifer after the dot, but
+% none was found.
+asmr_w_assembler_code_not_returned_to_text=07075_E_קוד ×”assembler ×œ× ×—×–×¨ ל×יזור הטקסט
+% There was a directive in the assembler block to change sections,
+% but there is a missing return to the text section at the end
+% of the assembler block. This might cause errors during link time.
+asmr_e_not_directive_or_local_symbol=07076_E_$1 ×”×•× ×œ× ×”× ×—×™×” ×ו סימול מקומי
+% This symbol is unknown.
+asmr_w_using_defined_as_local=07077_E_משתמש בהגדרת ×”×©× ×›×ª×•×•×™×ª מקומית
+asmr_e_dollar_without_identifier=07078_E_השימוש בתו הדולר מתבצע ×œ×œ× ×ž×–×”×”
+% A constant expression has an identifier which does not start with
+% the $ symbol.
+asmr_w_32bit_const_for_address=07079_W_מספק כתובת של 32 סיביות לקבוע
+% A constant was used as an address. This is probably an error,
+% since using absolute addresses will probably not work.
+asmr_n_align_is_target_specific=07080_N_השימוש ב.align מבוסס על סוג יעד, השתמש ב.balign ×ו .p2align
+% Using the .align directive is platform specific, and its meaning will vary
+% from one platform to another.
+asmr_e_cannot_access_field_directly_for_parameters=07081_E_×œ× × ×™×ª×Ÿ להשתמש בצורה ישירה בשדות של פרמטרי×
+% You should load the parameter first into a register and then access the
+% fields using that register.
+asmr_e_cannot_access_object_field_directly=07082_E_×œ× × ×™×ª×Ÿ לגשת בצורה ישירה לשדות של ×ובייקטי×/מחלקות
+% You should load the self pointer first into a register and then access the
+% fields using the register as base. By default the self pointer is available
+% in the esi register on i386.
+asmr_e_unable_to_determine_reference_size=07083_E_×œ× × ×™×ª×Ÿ לקבוע ×ת גודל ×”××•×¤×¨× ×“×™× ×œ×œ× ×¦×™×•×Ÿ של הגודל
+% You should specify explicitly a size for the reference, because
+% the compiler is unable to determine what size (byte,word,dword,etc.) it
+% should use for the reference.
+asmr_e_cannot_use_RESULT_here=07084_E_×œ× × ×™×ª×Ÿ להשתמש בRESULT בפונקציה הנוכחית
+% Some functions which return complex types cannot use the \var{result}
+% keyword.
+asmr_w_adding_explicit_args_fXX=07086_W_"$1" ×œ×œ× ×ª×¨×’×•× ×©×œ ××•×¤×¨× ×“×™× ×œ "$1 %st,%st(1)"
+asmr_w_adding_explicit_first_arg_fXX=07087_W_"$1 %st(n)" ×ª×•×¨×’× ×œ "$1 %st,%st(n)"
+asmr_w_adding_explicit_second_arg_fXX=07088_W_"$1 %st(n)" ×ª×•×¨×’× ×œ "$1 %st(n),%st"
+asmr_e_invalid_char_smaller=07089_E_התו > ×ינו מורשה ×›×ן
+% The shift operator requires the << characters. Only one
+% of those characters was found.
+asmr_e_invalid_char_greater=07090_E_התו < ×ינו מורשה ×›×ן
+% The shift operator requires the >> characters. Only one
+% of those characters was found.
+asmr_w_align_not_supported=07093_W_ALIGN ×ינו נתמך
+asmr_e_no_inc_and_dec_together=07094_E_השימוש INC ו DEC ××™× × ×™×›×•×œ×™× ×œ×”×’×™×¢ בייחד
+% Trying to use an increment and a decrement within the same
+% opcode on the 680x0. This is impossible.
+asmr_e_invalid_reg_list_in_movem=07095_E_שימוש בreglist ל movem ×œ× ×ª×§×™×Ÿ
+% Trying to use the \var{movem} opcode with invalid registers
+% to save or restore.
+asmr_e_invalid_reg_list_for_opcode=07096_E_שימוש שגוי בreglist לopcode
+asmr_e_higher_cpu_mode_required=07097_E_זקוק למצב מעבד גבוהה יותר ($1)
+% Trying to use an instruction which is not supported in the current
+% cpu mode. Use a higher cpu generation to be able to use this
+% opcode in your assembler block
+asmr_w_unable_to_determine_reference_size_using_dword=07098_W_×œ× ×¦×•×™×™×Ÿ גודל של ×ופרנד ×•×œ× × ×™×ª×Ÿ לנחש ×ת הגודל, משתמש בDWORD כברירת מחדל
+% You should specify explicitly a size for the reference, because
+% the compiler is unable to determine what size (byte,word,dword,etc.) it
+% should use for the reference. This warning is only used in Delphi mode where
+% it falls back to use DWORD as default.
+asmr_e_illegal_shifterop_syntax=07099_E_שגי×ת תחביר בעת ניסיון לפרש הסטת ×ופרנד
+% ARM only; ARM assembler supports a so called shifter operand. The used syntax isn't
+% a valid shifter operand. Example for an operation with shifter operand:
+% \begin{verbatim}
+% asm
+% orr r2,r2,r2,lsl #8
+% end;
+% \end{verbatim}
+asmr_e_packed_element=07100_E_הכתובת של רכיב ×רוז ×ינו × ×ž×¦× ×‘×˜×•×•×— של בית
+% Packed components (record fields and array elements) may start at an arbitrary
+% bit inside a byte. On CPU which do not support bit-addressable memory (which
+% includes all currently supported CPUs by FPC) you will therefore get an error
+% message when trying to index arrays with elements whose size is not a multiple
+% of 8 bits. The same goes for accessing record fields with such an address.
+% multiple of 8 bits.
+asmr_w_unable_to_determine_reference_size_using_byte=07101_W_×œ× ×¦×•×™×™×Ÿ גודל, והמהדר ×ינו מצליח לקבוע ×ת גודל ×”×ופרנד, משתמש בגודל BYTE בתור ברירת מחדל
+% You should specify explicitly a size for the reference, because
+% the compiler is unable to determine what size (byte,word,dword,etc.) it
+% should use for the reference. This warning is only used in Delphi mode where
+% it falls back to use BYTE as default.
+asmr_w_no_direct_ebp_for_parameter=07102_W_×œ× × ×™×ª×Ÿ להשתמש ב+הסט(%ebp) ×‘×ž×™×§×•× ×”× ×•×›×™ עבור הפרמטרי×
+% Using direct 8(%ebp) reference for function/procedure parameters is invalid
+% if parameters are in registers.
+asmr_w_direct_ebp_for_parameter_regcall=07103_W_השימוש ב+הסט(%ebp) ×ינו תו×× ×¢× ×ž×•×¡×›×ž×•×ª ×” regcall
+% Using direct 8(%ebp) reference for function/procedure parameters is invalid
+% if parameters are in registers.
+asmr_w_direct_ebp_neg_offset=07104_W_השימוש ב-הסט(%ebp) ×ינו מומלץ עבור גישה ×œ×ž×©×ª× ×™× ×ž×§×•×ž×™×™×
+% Using -8(%ebp) to access a local variable is not recommended
+asmr_w_direct_esp_neg_offset=07105_W_השימוש ב-הסט(%ebp) עלול ×œ×’×¨×•× ×œ×§×¨×™×¡×” של התוכנית ×ו ל×יבוד המידע
+% Using -8(%esp) to access a local stack is not recommended, as
+% this stack portion can be overwritten by any function calls or interrupts.
+asmr_e_no_vmtoffset_possible=07106_E_השימוש ב VMTOffset חייב להגיע בשילוב של מתודות ווירטו×ליות ו "$1" ×ינו ווירטו×לי
+% \end{verbatim}
+#
+# Assembler/binary writers
+#
+# 08018 is the last used one
+#
+asmw_f_too_many_asm_files=08000_F_יותר מידי קבצי assembler
+% With smartlinking enabled, there are too many assembler
+% files generated. Disable smartlinking.
+asmw_f_assembler_output_not_supported=08001_F_סוג הפלט של ×”assembler ×ינו נתמך
+asmw_f_comp_not_supported=08002_F_Comp ×ינו נתמך
+asmw_f_direct_not_supported=08003_F_מצב ישיר של assembler ×ינו נתמך ×¢"×™ ×›×•×ª×‘×™× ×‘×™× ×ריי×
+% Direct assembler mode is not supported for binary writers.
+asmw_e_alloc_data_only_in_bss=08004_E_×תחול המידע מורשה רק בחלק ×”bss
+asmw_f_no_binary_writer_selected=08005_F_×œ× × ×‘×—×¨ כותב בינ×רי
+asmw_e_opcode_not_in_table=08006_E_Asm: Opcode $1 ×”×•× ×œ× ×˜×‘×œ×”
+asmw_e_invalid_opcode_and_operands=08007_E_Asm: $1 הינו שילוב שגוי בין opcode לבין ×ופרנד
+asmw_e_16bit_not_supported=08008_E_Asm: התייחסות של 16 סיביות ×ינו נתמך
+asmw_e_invalid_effective_address=08009_E_Asm: מען בפעול ×œ× ×ª×§×™×Ÿ
+asmw_e_immediate_or_reference_expected=08010_E_Asm: מצפה להתייחסות ל×ופרנד ×ו ×ופרנד מידי
+asmw_e_value_exceeds_bounds=08011_E_Asm: $1 גולש מהגבולות $2
+asmw_e_short_jmp_out_of_range=08012_E_Asm: Short jump מחוץ לטווח $1
+asmw_e_undefined_label=08013_E_Asm: תווית ×œ× ×ž×•×’×“×¨×ª $1
+asmw_e_comp_not_supported=08014_E_Asm: הטיפוס COMP ×œ× × ×ª×ž×š ביעד המבוקש
+asmw_e_extended_not_supported=08015_E_Asm: הטיפוס Extended ×ינו נתמך ביעד המבוקש
+asmw_e_duplicate_label=08016_E_Asm: תוויות כפולה $1
+asmw_e_redefined_label=08017_E_Asm: מגדיר מחדש ×ת התווית $1
+asmw_e_first_defined_label=08018_E_Asm: מוגדר ×›×ן לר×שונה
+asmw_e_invalid_register=08019_E_Asm: ×וגר שגוי $1
+asmw_e_16bit_32bit_not_supported=08020_E_Asm: ההתייחסות ל16 ×ו 32 סיביות ××™× ×” נתמכת
+asmw_e_64bit_not_supported=08021_E_Asm: ×”×ופרנט 64 סיביות ×ינו נתמך
+
+#
+# Executing linker/assembler
+#
+# 09034 is the last used one
+#
+# BeginOfTeX
+%
+% \section{Errors of assembling/linking stage}
+% This section lists errors that occur when the compiler is processing the
+% command line or handling the configuration files.
+% \begin{description}
+exec_w_source_os_redefined=09000_W_מקור מערכת ההפעלה מוגדר מחדש
+% The source operating system is redefined.
+exec_i_assembling_pipe=09001_I_מרכיב (צינור) $1
+% Assembling using a pipe to an external assembler.
+exec_d_cant_create_asmfile=09002_E_×œ× × ×™×ª×Ÿ ליצור ×ת קובץ ×”assembler $1
+% The mentioned file can't be created. Check if you have got
+% access permissions to create this file
+exec_e_cant_create_objectfile=09003_E_×œ× × ×™×ª×Ÿ ליצור ×ת קובץ ×ובייקט $1
+% The mentioned file can't be created. Check if you've
+% got access permissions to create this file
+exec_e_cant_create_archivefile=09004_E_×œ× × ×™×ª×Ÿ ליצור ×ת קובץ ×”×רכיון $1
+% The mentioned file can't be created. Check if you've
+% access permissions to create this file
+exec_e_assembler_not_found=09005_E_המקשר $1 ×ינו נמצ×, עובר למ×סף חיצוני
+% The assembler program was not found. The compiler will produce a script that
+% can be used to assemble and link the program.
+exec_t_using_assembler=09006_T_משתמש במ×סף: $1
+% Information message saying which assembler is being used.
+exec_e_error_while_assembling=09007_E_שגי××” בזמן ×יסוף קוד יצי××” $1
+% There was an error while assembling the file using an external assembler.
+% Consult the documentation of the assembler tool to find out more information
+% on this error.
+exec_e_cant_call_assembler=09008_E_×œ× × ×™×ª×Ÿ להריץ ×ת המ×סף, שגי××” $1, מריץ מ×סף חיצוני
+% An error occurred when calling an external assembler, The compiler will produce a script that
+% can be used to assemble and link the program.
+exec_i_assembling=09009_I_מקשר $1
+% An informational message stating which file is being assembled.
+exec_i_assembling_smart=09010_I_×וסף ×¢× smartlinking $1
+% An informational message stating which file is being assembled using smartlinking.
+exec_w_objfile_not_found=09011_W_×”×ובייקט $1 ×œ× × ×ž×¦×, נר××” שה×יסוף יכשל !
+% One of the object file is missing, and linking will probably fail.
+% Check your paths.
+exec_w_libfile_not_found=09012_W_הספרייה $1 ×œ× × ×ž×¦××”, נר××” שה×יסוף יכשל !
+% One of the library file is missing, and linking will probably fail.
+% Check your paths.
+exec_e_error_while_linking=09013_E_שגי××” בזמן קישור
+% Generic error while linking.
+exec_e_cant_call_linker=09014_E_×œ× × ×™×ª×Ÿ להריץ ×ת המקשר, עובר למקשר חיצוני
+% An error occurred when calling an external linker, The compiler will produce a script that
+% can be used to assemble and link the program.
+exec_i_linking=09015_I_מקשר $1
+% An informational message, showing which program or library is being linked.
+exec_e_util_not_found=09016_E_הכלי $1 ×œ× × ×ž×¦×, עובר למקשר חיצוני
+% An external tool was not found, the compiler will produce a script that
+% can be used to assemble and link or postprocess the program.
+exec_t_using_util=09017_T_משתמש בכלי $1
+% An informational message, showing which external program (usually a postprocessor) is being used.
+exec_e_exe_not_supported=09018_E_×ין תמיכה ביצירת קבצי ריצה
+% Creating executable programs is not supported for this platform, because it was
+% not yet implemented in the compiler.
+exec_e_dll_not_supported=09019_E_×ין תמיכה ביצירת ספריות דינמיות/משותפות
+% Creating dynamically loadable libraries is not supported for this platform, because it was
+% not yet implemented in the compiler.
+exec_i_closing_script=09020_I_סוגר ×ת התסריט $1
+% Informational message showing when the external assembling an linking script is finished.
+exec_e_res_not_found=09021_E_מהדר מש××‘×™× ×œ× × ×ž×¦×, עובר למצב חיצוני
+% An external resource compiler was not found, the compiler will produce a script that
+% can be used to assemble, compile resources and link or postprocess the program.
+exec_i_compilingresource=09022_I_מהדר ×ת המש×ב $1
+% An informational message, showing which resource is being compiled.
+exec_t_unit_not_static_linkable_switch_to_smart=09023_T_×œ× × ×™×ª×Ÿ לקשר ×ת היחידה $1 בצורה סטטית, עובר לקישור ×—×›×
+% Statical linking was requested, but a unit which is not statically linkable was used.
+exec_t_unit_not_smart_linkable_switch_to_static=09024_T_×œ× × ×™×ª×Ÿ לקשר בצורה חכמה ×ת היחידה $1, עובר לקישור סטטי
+% Smart linking was requested, but a unit which is not smart-linkable was used.
+exec_t_unit_not_shared_linkable_switch_to_static=09025_T_×œ× × ×™×ª×Ÿ לקשר ×ת היחידה $1 בקישור משותף, עובר לקישור סטטי
+% Shared linking was requested, but a unit which is not shared-linkable was used.
+exec_e_unit_not_smart_or_static_linkable=09026_E_×œ× × ×™×ª×Ÿ לקשר ×ת היחידה $1 בקישור ×—×›× ×ו בקישור סטטי
+% Smart or static linking was requested, but a unit which cannot be used for either was used.
+exec_e_unit_not_shared_or_static_linkable=09027_E_×œ× × ×™×ª×Ÿ לקשר ×ת היחידה $1 בקישור משותף ×ו סטטי
+% Shared or static linking was requested, but a unit which cannot be used for either was used.
+exec_d_resbin_params=09028_D_מריץ ×ת מהדר המש××‘×™× "$1" ×¢× "$2" בתור שורת פקודה
+% An informational message showing which command-line is used for the resource compiler.
+%\end{description}
+# EndOfTeX
+
+#
+# Executable information
+#
+# BeginOfTeX
+% \section{Executable information messages.}
+% This section lists all messages that the compiler emits when an executable program is produced,
+% and only when the internal linker is used.
+% \begin{description}
+execinfo_f_cant_process_executable=09128_F_×œ× ×ž×¦×œ×™×— לבצע מעבר סופי על קובץ ההרצה $1
+% Fatal error when the compiler is unable to post-process an executable.
+execinfo_f_cant_open_executable=09129_F_×œ× ×ž×¦×œ×™×— לפתוח ×ת קובץ הריצה $1
+% Fatal error when the compiler cannot open the file for the executable.
+execinfo_x_codesize=09130_X_גודל הקוד: $1 בתי×
+% Informational message showing the size of the produced code section.
+execinfo_x_initdatasize=09131_X_הגודל של מידע מ×ותחל: $1 בתי×
+% Informational message showing the size of the initialized data section.
+execinfo_x_uninitdatasize=09132_X_מידע של מידע ×œ× ×ž×ותחל: $1 בתי×
+% Informational message showing the size of the uninitialized data section.
+execinfo_x_stackreserve=09133_X_גודל המחסנית השמורה: $1 בתי×
+% Informational message showing the stack size that the compiler reserved for the executable.
+execinfo_x_stackcommit=09134_X_גודל המחסנית בשימוש: $1 בתי×
+% Informational message showing the stack size that the compiler commites for the executable.
+%\end{description}
+# EndOfTeX
+
+#
+# Unit loading
+#
+# 10041 is the last used one
+#
+# BeginOfTeX
+% \section{Unit loading messages.}
+% This section lists all messages that can occur when the compiler is
+% loading a unit from disk into memory. Many of these messages are
+% informational messages.
+% \begin{description}
+unit_t_unitsearch=10000_T_מחפש ×ת היחידה: $1
+% When you use the \var{-vt}, the compiler tells you where it tries to find
+% unit files.
+unit_t_ppu_loading=10001_T_טוען ×ת קובץ ×” PPU $1
+% When the \var{-vt} switch is used, the compiler tells you
+% what units it loads.
+unit_u_ppu_name=10002_U_×©× ×” PPU: $1
+% When you use the \var{-vu} flag, the unit name is shown.
+unit_u_ppu_flags=10003_U_דגלי PPU: $1
+% When you use the \var{-vu} flag, the unit flags are shown.
+unit_u_ppu_crc=10004_U_PPU Crc: $1
+% When you use the \var{-vu} flag, the unit CRC check is shown.
+unit_u_ppu_time=10005_U_זמן PPU: $1
+% When you use the \var{-vu} flag, the time the unit was compiled is shown.
+unit_u_ppu_file_too_short=10006_U_קובץ הPPU קצר מידי
+% The ppufile is too short, not all declarations are present.
+unit_u_ppu_invalid_header=10007_U_הר×ש של קובץ ×” PPU ×ינו תקין (הקובץ ×ינו מכיל PPU בהתחלה)
+% A unit file contains as the first three bytes the ascii codes of \var{PPU}
+unit_u_ppu_invalid_version=10008_U_גרסה ×œ× ×ª×§×™× ×” של ×”PPU $1
+% This unit file was compiled with a different version of the compiler, and
+% cannot be read.
+unit_u_ppu_invalid_processor=10009_U_קובץ ×”PPU הודר למעבד ×חר
+% This unit file was compiled for a different processor type, and
+% cannot be read
+unit_u_ppu_invalid_target=10010_U_קובץ ×”PPU הודר למטרה ×חרת
+% This unit file was compiled for a different target, and
+% cannot be read
+unit_u_ppu_source=10011_U_מקור הPPU: $1
+% When you use the \var{-vu} flag, the unit source file name is shown.
+unit_u_ppu_write=10012_U_כותב $1
+% When you specify the \var{-vu} switch, the compiler will tell you where it
+% writes the unit file.
+unit_f_ppu_cannot_write=10013_F_×œ× ×›×•×ª×‘ ×ת קובץ ×” PPU
+% An error occurred when writing the unit file.
+unit_f_ppu_read_error=10014_F_שגי××” בזמן קרי×ת קובץ ×” PPU
+% This means that the unit file was corrupted, and contains invalid
+% information. Recompilation will be necessary.
+unit_f_ppu_read_unexpected_end=10015_F_סוף קובץ ×œ× ×¦×¤×•×™ (קובץ PPU)
+% Unexpected end of file. This may mean that the PPU file is
+% corrupted.
+unit_f_ppu_invalid_entry=10016_F_כניסה ×œ× ×ª×§×™× ×” בקובץ ×” PPU: $1
+% The unit the compiler is trying to read is corrupted, or generated with a
+% newer version of the compiler.
+unit_f_ppu_dbx_count_problem=10017_F_בעיה בספירת Dbx בקובץ PPU
+% There is an inconsistency in the debugging information of the unit.
+unit_e_illegal_unit_name=10018_E_×©× ×™×—×™×“×” ×œ× ×ª×§×™×Ÿ: $1
+% The name of the unit does not match the file name.
+unit_f_too_much_units=10019_F_יותר מידי יחידות
+% \fpc has a limit of 1024 units in a program. You can change this behavior
+% by changing the \var{maxunits} constant in the \file{fmodule.pas} file of the
+% compiler, and recompiling the compiler.
+unit_f_circular_unit_reference=10020_F_קרי××” מעגלית בין היחידות $1 ו $2
+% Two units are using each other in the interface part. This is only allowed
+% in the \var{implementation} part. At least one unit must contain the other one
+% in the \var{implementation} section.
+unit_f_cant_compile_unit=10021_F_×ין מספיק מש××‘×™× ×¢×œ מנת להדר ×ת היחידה $1
+% A unit was found that needs to be recompiled, but no sources are
+% available.
+unit_f_cant_find_ppu=10022_F_×œ× ×ž×•×¦× ×ת היחידה $1
+% You tried to use a unit of which the PPU file isn't found by the
+% compiler. Check your configuration file for the unit paths
+unit_w_unit_name_error=10023_W_היחידה $1 ×œ× × ×ž×¦××”, ×בל $2 קיי×
+% This error message is no longer used.
+unit_f_unit_name_error=10024_F_מחפש ×ת היחידה $1, ×בל $2 נמצ×
+% Dos truncation of 8 letters for unit PPU files
+% may lead to problems when unit name is longer than 8 letters.
+unit_w_switch_us_missed=10025_W_הידור יחידת system דורשת ×ת המתג -Us
+% When recompiling the system unit (it needs special treatment), the
+% \var{-Us} must be specified.
+unit_f_errors_in_unit=10026_F_עוצר ל×חר שנמצ×ו $1 שגי×ות בזמן הידור המודול
+% When the compiler encounters a fatal error or too many errors in a module
+% then it stops with this message.
+unit_u_load_unit=10027_U_טוען $1 ($2) יחידה $3
+% When you use the \var{-vu} flag, which unit is loaded from which unit is
+% shown.
+unit_u_recompile_crc_change=10028_U_מהדר ×ת $1 ל×חר שהחתימה שונתה ל $2
+% The unit is recompiled because the checksum of a unit it depends on has
+% changed.
+unit_u_recompile_source_found_alone=10029_U_× ×ž×¦× ×¨×§ קוד מקור, מהדר מחדש ×ת $1
+% When you use the \var{-vu} flag, these messages tell you why the current
+% unit is recompiled.
+unit_u_recompile_staticlib_is_older=10030_U_מהדר מחדש ×ת היחידה. הספרייה הסטטית ישנה יותר מקובץ ×” PPU
+% When you use the \var{-vu} flag, the compiler warns if the static library
+% of the unit are older than the unit file itself.
+unit_u_recompile_sharedlib_is_older=10031_U_מהדר מחדש ×ת היחידה. הספרייה המשותפת ישנה יותר מקובץ ×” PPU
+% When you use the \var{-vu} flag, the compiler warns if the shared library
+% of the unit are older than the unit file itself.
+unit_u_recompile_obj_and_asm_older=10032_U_מהדר מחדש ×ת ×” היחידה. קבצי ×” obj והasm ×™×©× ×™× ×™×•×ª×¨ מקובץ ×” PPU
+% When you use the \var{-vu} flag, the compiler warns if the assembler or
+% object file of the unit are older than the unit file itself.
+unit_u_recompile_obj_older_than_asm=10033_U_מהדר מחדש ×ת היחידה. קובץ ×”obj ישן יותר מקובץ ×”asm
+% When you use the \var{-vu} flag, the compiler warns if the assembler
+% file of the unit is older than the object file of the unit.
+unit_u_parsing_interface=10034_U_מפרש ×ת חלק הממשק של $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% parsing the interface part of the unit
+unit_u_parsing_implementation=10035_U_מפרש ×ת חלק הביצועי של $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% parsing the implementation part of the unit
+unit_u_second_load_unit=10036_U_טעינה שנייה של היחידה $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% recompiling a unit for the second time. This can happend with interdepend
+% units.
+unit_u_check_time=10037_U_בדיקת קובץ PPU $1 זמן $2
+% When you use the \var{-vu} flag, the compiler show the filename and
+% date and time of the file which a recompile depends on
+### The following two error msgs is currently disabled.
+#unit_h_cond_not_set_in_last_compile=10038_H_התנ××™× ×©×œ $1 ×œ× ×”×•×’×“×¨×• בהתחלת הריצה בהידור ×”×חרון של $2
+#% when recompilation of an unit is required the compiler will check that
+#% the same conditionals are set for the recompiliation. The compiler has
+#% found a conditional that currently is defined, but was not used the last
+#% time the unit was compiled.
+#unit_h_cond_set_in_last_compile=10039_H_התנ××™× ×©×œ $1 הוגדרו בהתחלת הריצה בהידור ×”×חרון של $2
+#% when recompilation of an unit is required the compiler will check that
+#% the same conditionals are set for the recompiliation. The compiler has
+#% found a conditional that was used the last time the unit was compiled, but
+#% the conditional is currently not defined.
+unit_w_cant_compile_unit_with_changed_incfile=10040_W_×œ× × ×™×ª×Ÿ להדר ×ת היחידה $1 למרות שקבצי ×”include שונו
+% A unit was found to have modified include files, but
+% some source files were not found, so recompilation is impossible.
+unit_u_source_modified=10041_U_הקובץ $1 חדש יותר מהקובץ PPU $2
+% A modified source file for a compiler unit was found.
+unit_u_ppu_invalid_fpumode=10042_U_מנסה להשתמש ביחידה ×שר הודרה למצב FPU שונה
+% Trying to compile code while using units which were not compiled with
+% the same floating point format mode. Either all code should be compiled
+% with FPU emulation on, or with FPU emulation off.
+unit_u_loading_interface_units=10043_U_טוען ×ת חלק הממשק של היחידות מ $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% loading the units defined in the interface part of the unit.
+unit_u_loading_implementation_units=10044_U_טוען ×ת החלק הביצועי של היחידות מ $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% loading the units defined in the implementation part of the unit.
+unit_u_interface_crc_changed=10045_U_חתימת ה CRC של חלק הממשק השתנה ביחידה $1
+% When you use the \var{-vu} flag, the compiler warns that it the
+% CRC calculated for the interface has been changed after the implementation
+% has been parsed.
+unit_u_implementation_crc_changed=10046_U_חתימת הCRC של החלק הביצועי השתנה ליחידה $1
+% When you use the \var{-vu} flag, the compiler warns that it the
+% CRC calculated has been changed after the implementation
+% has been parsed.
+unit_u_finished_compiling=10047_U_×”×¡×ª×™×™× ×”×™×“×•×¨ היחידה $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has finished compiling the unit.
+unit_u_add_depend_to=10048_U_מוסיף ×ת התלות של $1 ל$2
+% When you use the \var{-vu} flag, the compiler warns that it
+% has added a dependency between the two units.
+unit_u_no_reload_is_caller=10049_U_×ין קרי××” מחודשת של הקובץ בשביל $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has will not reload the unit because it is the unit that wants
+% to load this unit
+unit_u_no_reload_in_second_compile=10050_U_×ין טעינה מחדש, בזמן הידור שני של היחידה $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has will not reload the unit because it is already in a second recompile
+unit_u_flag_for_reload=10051_U_דגל לטעינה מחודשת: $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has to reload the unit
+unit_u_forced_reload=10052_U_כופה על טעינה מחודשת
+% When you use the \var{-vu} flag, the compiler warns that it
+% has is reloading the unit because it was required
+unit_u_previous_state=10053_U_המצב הישן של $1: $2
+% When you use the \var{-vu} flag, the compiler shows the
+% previous state of the unit
+unit_u_second_compile_unit=10054_U_× ×ž×¦× ×›×‘×¨ בתהליך הידור $1, ×ž×™×™×©× ×”×™×“×•×¨ שני
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% recompiling a unit for the second time. This can happend with interdepend
+% units.
+unit_u_loading_unit=10055_U_טוען ×ת היחידה $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% loading the unit.
+unit_u_finished_loading_unit=10056_U_×ž×¡×™×™× ×œ×˜×¢×•×Ÿ ×ת היחידה $1
+% When you use the \var{-vu} flag, the compiler warns that it finished
+% loading the unit.
+unit_u_registering_new_unit=10057_U_×¨×•×©× ×™×—×™×“×” חדשה $1
+% When you use the \var{-vu} flag, the compiler warns that it has
+% found a new unit and registers it in the internal lists.
+unit_u_reresolving_unit=10058_U_מחשב מחדש ×ת היחידה $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has to recalculate the internal data of the unit
+unit_u_skipping_reresolving_unit=10059_U_מדלג על טעינה מחודשת של היחידה $1, עדיין בזמן טעינת יחידות בשימוש
+% When you use the \var{-vu} flag, the compiler warns that it
+% skips to recalculate the internal data of the unit because there
+% is no data to recalculate
+% \end{description}
+# EndOfTeX
+
+#
+# Options
+#
+# 11041 is the last used one
+#
+option_usage=11000_O_$1 [options] <inputfile> [options]
+# BeginOfTeX
+%
+% \section{Command-line handling errors}
+% This section lists errors that occur when the compiler is processing the
+% command line or handling the configuration files.
+% \begin{description}
+option_only_one_source_support=11001_W_תומך רק בקובץ מקור ×חד בשורת הפקודה
+% You can specify only one source file on the command line. The first
+% one will be compiled, others will be ignored. This may indicate that
+% you forgot a \var{'-'} sign.
+option_def_only_for_os2=11002_W_ניתן ליצור ×ת קובץ ×” DEF רק לOS/2
+% This option can only be specified when you're compiling for OS/2
+option_no_nested_response_file=11003_E_×ין תמיכה בקבצי תגובה מקונני×
+% you cannot nest response files with the \var{@file} command-line option.
+option_no_source_found=11004_F_×œ× ×¦×•×™×™×Ÿ קובץ מקור בשורת הפקודה
+% The compiler expects a source file name on the command line.
+option_no_option_found=11005_N_×œ× ×¦×•×™× ×• ×פשרויות בתוך קובץ ההגדרות $1
+% The compiler didn't find any option in that config file.
+option_illegal_para=11006_E_פרמטר ×œ× ×—×•×§×™: $1
+% You specified an unknown option.
+option_help_pages_para=11007_H_-? כותב דפי עזרה
+% When an unknown option is given, this message is diplayed.
+option_too_many_cfg_files=11008_F_יותר מידי קבצי הגדרות מקונני×
+% You can only nest up to 16 config files.
+option_unable_open_file=11009_F_×œ× × ×™×ª×Ÿ לפתוח ×ת הקובץ $1
+% The option file cannot be found.
+option_reading_further_from=11010_D_×§×•×¨× ×”×’×“×¨×•×ª נוספות מ $1
+% Displayed when you have notes turned on, and the compiler switches
+% to another options file.
+option_target_is_already_set=11011_W_המטרה כבר הוגדרה ל: $1
+% Displayed if more than one \var{-T} option is specified.
+option_no_shared_lib_under_dos=11012_W_DOS ×ינו תומך בספריות משותפות, חוזר לספריות סטטיות
+% If you specify \var{-CD} for the \dos platform, this message is displayed.
+% The compiler supports only static libraries under \dos
+option_too_many_ifdef=11013_F_IF(N)DEF ×¨×‘×™× ×ž×™×“×™
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_too_many_endif=11014_F_ENDIF ×¨×‘×™× ×ž×™×“×™
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_too_less_endif=11015_F_תנ××™ פתוח בסוף הקובץ
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_no_debug_support=11016_W_מידע ניפוי שגי×ות ×ינו נתמך בסוג קובץ הריצה המבוקש
+% It is possible to have a compiler executable that doesn't support
+% the generation of debugging info. If you use such an executable with the
+% \var{-g} switch, this warning will be displayed.
+option_no_debug_support_recompile_fpc=11017_H_נסה להדר מחדש ×¢× ×”×ž×ª×’ -dGDB
+% It is possible to have a compiler executable that doesn't support
+% the generation of debugging info. If you use such an executable with the
+% \var{-g} switch, this warning will be displayed.
+option_obsolete_switch=11018_W_×תה משתמש במתג המיושן $1
+% this warns you when you use a switch that is not needed/supported anymore.
+% It is recommended that you remove the switch to overcome problems in the
+% future, when the switch meaning may change.
+option_obsolete_switch_use_new=11019_W_×תה משתמש במתג המיושן $1, השתמש במתג $2 במקו×
+% this warns you when you use a switch that is not supported anymore. You
+% must now use the second switch instead.
+% It is recommended that you change the switch to overcome problems in the
+% future, when the switch meaning may change.
+option_switch_bin_to_src_assembler=11020_N_מעביר ×ת ×”×וסף למצב ברירת מחדל של כתיבת מ×סף
+% this notifies you that the assembler has been changed because you used the
+% -a switch which can't be used with a binary assembler writer.
+option_incompatible_asm=11021_W_התוכן הנבחר של ×”assembler "$1" ×ינו מת××™× ×œ "$2"
+option_asm_forced=11022_W_התוכן של המ×סף "$1" ×œ× ×ž×¡×•×’×œ ליצור קבצי ×ובייקט, משתמש במ×סף ברירת המחדל במקו×
+% The assembler output selected can not generate
+% object files with the correct format. Therefore, the
+% default assembler for this target is used instead.
+option_using_file=11026_T_×§×•×¨× ×פשרויות מהקובץ $1
+% Options are also read from this file
+option_using_env=11027_T_×§×•×¨× ×פשרויות מהסביבה $1
+% Options are also read from this environment string
+option_handling_option=11028_D_מטפל ב×פשרות "$1"
+% Debug info that an option is found and will be handled
+option_help_press_enter=11029__*** לחץ על enter ***
+option_start_reading_configfile=11030_H_מתחיל בקרי×ת קובץ ההגדרות $1
+% Starting of config file parsing.
+option_end_reading_configfile=11031_H_×¡×™×•× ×§×¨×™×ת קובץ ההגדרות $1
+% End of config file parsing.
+option_interpreting_option=11032_D_מפרש ×ת ×”×פשרות "$1"
+option_interpreting_firstpass_option=11036_D_מפרש ×ת המעבר הר×שון על ×”×פשרות "$1"
+option_interpreting_file_option=11033_D_מפרש ×ת הגדרת הקובץ "$1"
+option_read_config_file=11034_D_×§×•×¨× ×ת קובץ ההגדרות "$1"
+option_found_file=11035_D_× ×ž×¦× ×§×•×‘×¥ מקור ×‘×©× "$1"
+% Additional infos about options, displayed
+% when you have debug option turned on.
+option_code_page_not_available=11039_E_קוד דף ×œ× ×™×“×•×¢
+option_config_is_dir=11040_F_נמצ××” ספרייה ×‘×ž×§×•× ×§×•×‘×¥ ההגדרות $1
+% Directories can not be used as configuration files.
+option_confict_asm_debug=11041_W_סוג הפלט של המ×סף שנבחר "$1" ×ינו יכול ליצור מידע עבור ניפוי שגי×ות. מבטל ניפוי שגי×ות
+% The assembler output selected can not generate
+% debugging information, debugging option is therefore disabled.
+%\end{description}
+# EndOfTeX
+
+#
+# Logo (option -l)
+#
+option_logo=11023_[
+Free Pascal Compiler version $FPCFULLVERSION [$FPCDATE] for $FPCCPU
+Copyright (c) 1993-2011 by Florian Klaempfl
+]
+
+#
+# Info (option -i)
+#
+option_info=11024_[
+Free Pascal Compiler version $FPCVERSION
+
+ת×ריך מהדר : $FPCDATE
+מהדר למעבד: $FPCCPU
+
+מערכות הפעלה נתמכות:
+ $OSTARGETS
+
+הור×ות מעבד נתמכות:
+ $INSTRUCTIONSETS
+
+הור×ות נתמכות של יחידת נקודה צפה:
+ $FPUINSTRUCTIONSETS
+
+תמיכת המיטוב:
+ $OPTIMIZATIONS
+
+התוכנה מוגשת תחת רישיון GNU General Public License
+למידע נוסף יש ×œ×§×¨×•× ×ת COPYING.FPC
+
+דיווח על תקלות (ב××’×™×), הצעות וכו':
+ http://bugs.freepascal.org
+
+ bugs@freepascal.org
+]
+
+#
+# Help pages (option -? and -h)
+#
+# The first character on the line indicates who will display this
+# line, the current possibilities are :
+# * = every target
+# 3 = 80x86 targets
+# 6 = 680x0 targets
+# e = in extended debug mode only
+# P = PowerPC targets
+# S = Sparc targets
+# V = Virtual machine targets
+# The second character also indicates who will display this line,
+# (if the above character was TRUE) the current possibilities are :
+# * = everyone
+# g = with GDB info supported by the compiler
+# O = OS/2
+# L = UNIX systems
+# The third character represents the indentation level.
+#
+option_help_pages=11025_[
+**0*_הוסף ×ת הסימן + ל×חר ×פשרות מתג בולי×× ×™ ל×פשר ×ת ×”×פשרות, הוסף ×ת הסימן - לבטל ×ת ×”×פשרות
+**1a_המהדר ×ינו מוחק ×ת קובץ ×”assembler שנוצר
+**2al_×¨×•×©× ×¨×©×™×ž×” של שורות קוד מקור בקובץ ×”assembler
+**2an_רשימת מידע של ×¦×ž×ª×™× ×‘×§×•×‘×¥ ×”assembler
+*L2ap_השתמש בצינורות ×‘×ž×§×•× ×§×‘×¦×™ assembler זמניי×
+**2ar_רשימה ×ודות ×¨×™×©×•× ×©×œ הקצ××”/שחרור בקובץ ×”assembler
+**2at_רשימה זמנית ×ודות הקצ××”/שחרור בקובץ ×”assembler
+**1A<x>_תסדירי פלט:
+**2Adefault_השתמש במ×סף ברירת מחדל
+3*2Aas_×סוף ×¢× GNU AS
+3*2Anasmcoff_קובץ COFF (Go32v2) בשימוש ×¢× Nasm
+3*2Anasmelf_קובץ ELF32 (Linux) בשימוש ×¢× Nasm
+3*2Anasmwin32_קובץ ×ובייקט Win32 בשימוש ×¢× Nasm
+3*2Anasmwdosx_קובץ ×ובייקט Win32/WDOSX בשימוש ×¢× Nasm
+3*2Awasm_קובץ obj בשימוש ×¢× Wasm (Watcom)
+3*2Anasmobj_קובץ obj בשימוש ×¢× Nasm
+3*2Amasm_קובץ obj בשימוש ×¢× Masm (Microsoft)
+3*2Atasm_קובץ obj בשימוש Tasm (Borland)
+3*2Aelf_קובץ ELF32 (Linux) בשימוש כותב פנימי
+3*2Acoff_קובץ OFF (Go32v2) בשימוש כותב פנימי
+3*2Apecoff_קובץ pecoff (Win32) בשימוש כותב פנימי
+4*2Aas_×סוף ×¢× GNU AS
+6*2Aas_קובץ-o Unix בשימוש GNU AS
+6*2Agas_GNU Motorola assembler
+6*2Amit_MIT Syntax (GAS ישן)
+6*2Amot_Motorola assembler תקני
+A*2Aas_×סוף ×¢× GNU AS
+P*2Aas_×סוף ×¢× GNU AS
+S*2Aas_×סוף ×¢× GNU AS
+**1b_ייצר מידע לדפדוף
+**2bl_ייצר מידע על ×¡×ž×œ×™× ×ž×§×•×ž×™×™×
+**1B_בנה ×ת כל המודולי×
+**1C<x>_×פשרויות יצירת קוד:
+**2Cc<x>_קובע מוסכמות הפעלה ברירת מחדל ל <ס>
+**2CD_צור ×’× ×¡×¤×¨×™×™×” דינ×מית (×œ× × ×ª×ž×š)
+**2Ce_מהדר ×¢× ×”×“×ž×™×™×” של opcodes ×”×©×™×™×›×™× ×œ× ×§×•×“×” צפה
+**2Cf<x>_בחר הור×ות FPU לשימוש, ר××” fpc -i ×œ×¢×¨×›×™× ×פשריי×
+**2CF<x>_דיוק נקודה עשרונית קבועה מינימלית (default, 32, 64)
+**2Cg_צור קוד PIC
+**2Ch<n>_כמות של <n> ×‘×ª×™× ×œ מצבור (בין 1023 ו67107840)
+**2Ci_בדיקת IO
+**2Cn_השמט מצב קישור
+**2Co_בדוק גלישה של פעולות מספר של×
+**2CO_בדוק עבור פעולות גלישה ×פשרויות של מספר של×
+**2Cp<x>_בחר קבוצת הור×ות, ר××” fpc -i ×œ×¢×¨×›×™× ×פשריי×
+**2CP<x>=<y>_הגדרות ×ריזה
+**3CPPACKSET=<y>_ <y> מסדר הקצ××”: 0, 1 ×ו DEFAULT ×ו NORMAL, 2, 4 ו 8
+**2Cr_בדיקת טווח
+**2CR_×•×•×“× ×§×¨×™××” תקינה למתודה
+**2Cs<n>_קבע גודל מחסנית ל <n>
+**2Ct_בדיקת מחסנית
+**2CX_צור ×’× ×¡×¤×¨×™×™×” של קישור ×—×›×
+**1d<x>_מגדיר ×ת הסמל <x>
+**1D_יוצר קובץ DEF
+**2Dd<x>_יוצר ת×ור ל <x>
+**2Dv<x>_יוצר גרסת DLL ל <x>
+*O2Dw_×™×©×•× PM
+**1e<x>_קובע נתיב לקובץ ריצה
+**1E_זהה ל -Cn
+**1fPIC_זהה ל -Cg
+**1F<x>_קובע ×©× ×§×‘×¦×™× ×•×ž×™×§×•×ž×™×:
+**2Fa<x>[,y]_×§×•×“× ×˜×•×¢×Ÿ ×ת היחידות <x> ו [y] ר×שונות, לפני ניתוח שורת ×” uses
+**2Fc<x>_קובע קוד דף של קלט ל<x>
+**2FC<x>_קבע ×©× ×ž×”×“×¨ RC בינ×רי ל <x>
+**2FD<x>_קובע ×ת הספרייה בה ×פשר לחפש ×ת כלי העזר של המהדר
+**2Fe<x>_הפנה הודעות שגי××” ל<x>
+**2Ff<x>_הוסף ×ת <x> לנתיב המסגרת (רק ב Darwin)
+**2FE<x>_הפנה פלט של exe/unit לנתיב <x>
+**2Fi<x>_מוסיף ×ת <x> לרשימת הנתיבי×
+**2Fl<x>_מוסיף ×ת <x> לרשימת ×”× ×ª×™×‘×™× ×©×œ הספריה
+**2FL<x>_משתמש ב<x> כמקשר דינ×מי
+**2Fm<x>_טוען טבלת המרה של יוניקוד מהקובץ x>.txt> מספריית המהדר
+**2Fo<x>_מוסיף ×ת <x> לרשינת ×”× ×ª×™×‘×™× ×©×œ ×ובייקט
+**2Fr<x>_טוען קובץ הודעות שגי××” <x>
+**2FR<x>_קבע מקשר לקובץ res ל <x>
+**2Fu<x>_מוסיף ×ת <x> לרשימת ×”× ×ª×™×‘×™× ×©×œ יחידה
+**2FU<x>_קובע ×ת ×”×ž×™×§×•× ×”×¤×œ×˜ של היחידות ל <x> ומשכתב ×ת -FE
+*g1g_יוצר מידע לניפוי שגי×ות
+*g2gc_יוצר בדיקות למצביעי×
+*g2gh_השתמש ביחידה heaptrace (עבור דליפות זכרון/בעיות בניפוי שגי×ות)
+*g2gl_השתמש ביחידת מידע של שורה להציג מידע נוסף לbacktraces
+*g2go<x>_צור ×פשרויות לניפוי שגי×ות
+*g3godwarfsets_×פשר מידע לניהול מידע עבור ניפוי שגי×ות של Dwarf (שובר ×ת gdb < 6.5)
+*g2gp_משמר גודל שמות סמלי הstabs
+*g2gs_מייצר מידע לניפוי שגי×ות stub
+*g2gt_לכלך ×ž×©×ª× ×™× ×ž×§×•×ž×™×™× (לזיהוי מידע ×œ× ×ž×ותחל)
+*g2gv_מייצר תוכנות ×¢× ×™×›×•×œ×ª מעקב של valgrind
+*g2gw_מייצר מידע לניפוי שגי×ות לdwarf
+*g2gw2_מיצר מידע לניפוי שגי×ות dwarf-2
+*g2gw3_מיצר מידע לניפוי שגי×ות dwarf-3
+**1i_מידע
+**2iD_הצג ת×ריך המהדר
+**2iV_הצג גרסת המהדר
+**2iW_הצג גרסה מל××” של המהדר
+**2iSO_הצג מערכת הפעלה של המהדר
+**2iSP_הצג גרסת מעבד של המהדר
+**2iTO_הצג ×ת המטרה של מערכת ההפעלה
+**2iTP_הצג ×ת המטרה של המעבד
+**1I<x>_הוסף ×ת <x> לרשימת ×”× ×ª×™×‘×™× ×œ×”×•×¡×¤×”
+**1k<x>_העבר ×ת <x> למקשר
+**1l_כתוב סמליל
+**1M<x>_הגדר מצב שפה ל <x>
+**2Mfpc_די×לקט של Free Pascal (ברירת מחדל)
+**2Mobjfpc_×פשר כמה תוספות של Delphi 2
+**2Mdelphi_מנסה להיות תו×× Delphi
+**2Mtp_מנסה להיות תו×× ×œ TP/BP 7.0
+**2Mmacpas_מנסה להיות תו×× ×œ×œ×”×’ של Macintosh Pascal
+**1n_×ל ×ª×§×¨× ×ת קובץ הגדרות ברירת המחדל
+**1N<x>_מיטוב צמתי עץ
+**2Nu_לגולל לול×ות
+**1o<x>_שנה ×ת ×©× ×§×•×‘×¥ הריצה שהתקבל ל <x>
+**1O<x>_מיטובי×:
+**2O-_בטל מיטוב
+**2O1_מיטוב רמה 1 (מהיר וטוב לניפוי שגי×ות)
+**2O2_מיטוב רמה 2 (-O1 + מיטוב מהיר)
+**2O3_מיטוב רמה 3 (-O2 + מיטוב ×יטי)
+**2Oa<x>=<y>_קבע יישור
+**2Oo[NO]<x>_×¢"מ ל×פשר ×ו ל×פשר מיטובי×, ר××” fpc -i ל×פשרויות
+**2Op<x>_לקביעת מיטוב למעבד נבחר, ר××” fpc -i ל×פשרויות
+**2Os_צור קוד קטן
+**1pg_צור קוד פרופיל עבור gprof (מגדיר ×ת FPC_PROFILE)
+**1R<x>_סגנון קרי×ת ×”×סף:
+**2Rdefault_השתמש במ×סף ברירת מחדל
+3*2Ratt_×§×¨× ×¡×’× ×•×Ÿ מקשר של AT&T
+3*2Rintel_×§×¨× ×¡×’× ×•×Ÿ מקשר של Intel
+6*2RMOT_×§×¨× ×¡×’× ×•×Ÿ מקשר של Motorola
+**1S<x>_×פשרויות תחביר:
+**2S2_זהה ל -Mobjfpc
+**2Sc_תומך ××•×¤×¨×˜×•×¨×™× ×‘×¡×’× ×•×Ÿ C (*=, +=, /= ו -=)
+**2Sa_הוסף קוד טענת תנ××™ קביעה (assertion)
+**2Sd_זהה ל -Mdelphi
+**2Se<x>_×פשרויות שגי××”. <x> הינו השילוב הב×:
+**3*_<n> : המהדר עוצר ל×חר <n> שגי×ות (ברירת מחדל ×”×™× 1)
+**3*_w : המהדר עוצר ×’× ×œ×חר ×זהרות
+**3*_n : המהדר עוצר ל×חר הערות
+**3*_h : המהדר עוצר ל×חר רמזי×
+**2Sg_×פשר LABEL ו GOTO
+**2Sh_השתמש ב ansistrings
+**2Si_תמוך בסגנון C++ של INLINE
+**2Sk_טען ×ת היחידה fpcylix
+**2SI<x>_קבע סגנון ממשק ל<x>
+**3SIcom_תו×× ×ž×ž×©×§×™ COM (ברירת מחדל)
+**3SIcorba_תו×× ×ž×ž×©×§×™ CORBA
+**2Sm_תמוך במקרו ×“×•×ž×™× ×œC (גלובליי×)
+**2So_זהה ל -Mtp
+**2Ss_×©× ×™×•×¦×¨ חייב להיות init (×©× ×”×•×¨×¡ חייב להיות done)
+**2Sx_×פשר מילות מפתח לexception (ברירת מחדל במצבי Delphi/ObjFPC)
+**1s_×ל ×ª×§×¨× ×œ×ž×סף והמקשר
+**2sh_צור תסריט לקישור במ×רח
+**2st_צור תסריט לקישור במטרה
+**2sr_דלג על ×¨×™×©×•× ×”×§×¦×ת מופע (השתמש בייחד ×¢× -alr)
+**1T<x>_מטרת מערכת ההפעלה:
+3*2Temx_OS/2 בשימוש EMX ( בייחד ×¢× ×”×¨×—×‘×ª EMX/RSX)
+3*2Tfreebsd_FreeBSD
+3*2Tgo32v2_גרסה 2 של הרחבת DJ Delorie DOS
+3*2Tlinux_Linux
+3*2Tnetbsd_NetBSD
+3*2Tnetware_Novell Netware Module (clib)
+3*2Tnetwlibc_Novell Netware Module (libc)
+3*2Topenbsd_OpenBSD
+3*2Tos2_OS/2 / eComStation
+3*2Tsunos_SunOS/Solaris
+3*2Twatcom_Watcom תו×× ×”×¨×—×‘×ª DOS
+3*2Twdosx_WDOSX הרחבת DOS
+3*2Twin32_Windows 32 סיביות
+3*2Twince_Windows CE
+4*2Tlinux_Linux
+6*2Tamiga_Commodore Amiga
+6*2Tatari_Atari ST/STe/TT
+6*2Tlinux_Linux/m68k
+6*2Tmacos_Macintosh m68k (×œ× × ×ª×ž×š)
+6*2Tpalmos_PalmOS
+A*2Tlinux_Linux
+A*2Twince_Windows CE
+P*2Tamiga_AmigaOS על PowerPC
+P*2Tdarwin_Darwin ו Mac OS X על PowerPC
+P*2Tlinux_Linux על PowerPC
+P*2Tmacos_Mac OS (קל×סי) על PowerPC
+P*2Tmorphos_MorphOS
+S*2Tlinux_Linux
+**1u<x>_מסיר ×ת ההגדרה של הסמל <x>
+**1U_הגדרות יחידה:
+**2Un_×ל תבדוק ×ת ×©× ×”×™×—×™×“×”
+**2Ur_צור קבצי שחרור של יחידות
+**2Us_הדר ×ת יחידת ×”system
+**1v<x>_תהיה מפורט יותר. <x> הינו שילוב של ×”×ª×•×•×™× ×”×‘××™×:
+**2*_e : הצג הודעות שגי××” (ברירת מחדל)
+**2*_0 : ×ל תציג ×›×œ×•× (למעט הודעות שגי××”)
+**2*_w : הצג ×זהרות
+**2*_u : הצג מידע על יחידה
+**2*_n : הצג הערות
+**2*_t : הצג ×§×‘×¦×™× ×©×”×™×• בשימוש
+**2*_h : הצג רמזי×
+**2*_c : הצג תנ××™×
+**2*_i : הצג מידע כללי
+**2*_d : הצג מידע לנפוי שגי×ות
+**2*_l : הצג מספרי שורות
+**2*_r : מצב תו×× Rhide/GCC
+**2*_a : הצג הכול
+**2*_x : הצג מידע על קובץ הריצה (רק בWin32)
+**2*_b : כתוב הודעות ×¢× ×©×ž×•×ª ×§×‘×¦×™× ×•× ×ª×™×‘×™× ×ž×œ××™×
+**2*_v : כתוב ×ת הקובץ fpcdebug.txt ×¢× ×”×¨×‘×” מידע על ניפוי שגי×ות
+**2*_p : כתוב ×ת הקובץ tree.log ×¢× × ×™×ª×•×— ×¢×¥
+3*1W<x>_×פשרות מבוססת מטרה (מטרות)
+A*1W<x>_×פשרות מבוססת מטרה (מטרות)
+P*1W<x>_×פשרות מבוססת מטרה (מטרות)
+3*2Wb_צור חבילה ×‘×ž×§×•× ×¡×¤×¨×™×™×” (Darwin)
+P*2Wb_צור חבילה ×‘×ž×§×•× ×¡×¤×¨×™×™×” (Darwin)
+p*2Wb_צור חבילה ×‘×ž×§×•× ×¡×¤×¨×™×™×” (Darwin)
+3*2WB_צור תמונה הניתנת ×œ×ž×™×§×•× ×ž×—×•×“×© (Windows)
+A*2WB_צור תמונה הניתנת ×œ×ž×™×§×•× ×ž×—×•×“×© (Windows, Symbian)
+3*2WC_מציין ×פליקציה מסוג מסוף (EMX, OS/2, Windows)
+A*2WC_מציין ×פליקציה מסוג מסוף (Windows)
+P*2WC_מציין ×פליקציה מסוג מסוף (Classic Mac OS)
+3*2WD_השתמש ב DEFFILE ×œ×™×™×¦× ×¤× ×§×¦×™×•×ª של DLL ×ו EXE (Windows)
+A*2WD_השתמש ב DEFFILE ×œ×™×™×¦× ×¤× ×§×¦×™×•×ª של DLL ×ו EXE (Windows)
+3*2WF_מציין ×פליקציה מסוג מסך ×ž×œ× (EMX, OS/2)
+3*2WG_מציין ×פליקציה מסוג גרפי (EMX, OS/2, Windows)
+A*2WG_מציין ×פליקציה מסוג גרפי (Windows)
+P*2WG_מציין ×פליקציה מסוג גרפי (Classic Mac OS)
+3*2WN_×ל תצור קוד משנה מיקו×, נדרש עבור ניפוי שגי×ות (Windows)
+A*2WN_×ל תצור קוד משנה מיקו×, נדרש עבור ניפוי שגי×ות (Windows)
+3*2WR_תיצור קוד משנה ×ž×™×§×•× (Windows)
+A*2WR_תיצור קוד משנה ×ž×™×§×•× (Windows)
+P*2WT_ציין ×פליקציה מסוג כלי MPW (Classic Mac OS)
+**1X_הגדרות ריצה:
+**2Xc_העבר --shared/-dynamic למקשר (BeOS, Darwin, FreeBSD, Linux)
+**2Xd_×ל תשתמש בנתיב חיפוש הספריות הסטנדרטיות (נדרש עבור הידור ל×רכיטקטורות ×חרות)
+**2Xe_השתמש במקשר חיצוני
+**2XD_נסה לקשר יחידות בצורה דינ×מית (מגדיר FPC_LINK_DYNAMIC)
+**2Xi_השתמש במקשר פנימי
+**2Xm_צור מפת קישורי×
+**2XM<x>_הגדר ×ת ×”×©× ×©×œ רוטינה ×”'עיקרית' של התוכנה (ברירת מחדל ×”×•× 'main')
+**2XP<x>_צרף ×ת השמות ×”×ž×’×™×¢×™× ×¢Ã ×”×ª×—×™×œ×™×ª <x> מbinutils
+**2Xr<x>_הגדר ×ת נתיב חיפוש הספריות ל <x> (נדרש עבור הידור ל×רכיטקטורות ×חרות) (BeOS, Linux)
+**2XR<x>_צרף ×ת <x> לכל נתיבי החיפוש של המקשר (BeOS, Darwin, FreeBSD, Linux, Mac OS, Solaris)
+**2Xs_נקה ×ת כל ×”×¡×ž×œ×™× ×ž×§×‘×¦×™ ההרצה
+**2XS_נסה לקשר יחידות בצורה סטטית (ברירת מחדל, מגדיר FPC_LINK_STATIC)
+**2Xt_קשר ×¢× ×¡×¤×¨×™×•×ª סטטיות (מעביר -static למקשר)
+**2XX_תנסה לבצע smartlink ליחידות (מגדיר FPC_LINK_SMART)
+**1*_
+**1?_הצג ×ת עזרה זו
+**1h_הצג עזרה זו ×œ×œ× ×œ×—×›×•×ª
+
+]
+
+#
+# The End...
diff --git a/closures/compiler/msg/errorid.msg b/closures/compiler/msg/errorid.msg
new file mode 100644
index 0000000000..4c03e14317
--- /dev/null
+++ b/closures/compiler/msg/errorid.msg
@@ -0,0 +1,2715 @@
+# $Id: errorid.msg,v 1.124 2007/09/20 02:52:50 zaenal Exp $
+# This file is part of the Free Pascal Compiler
+# Copyright (c) 1999-2008 by the Free Pascal Development team
+#
+# Indonesian Language File for Free Pascal
+# Contributed by Zaenal Mutaqin <ade999 at gmail.com>
+#
+# See the file COPYING.FPC, included in this distribution,
+# for details about the copyright.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#
+#
+# The constants are build in the following order:
+# <part>_<type>_<txtidentifier>
+#
+# <part> is the part of the compiler the message is used
+# asmr_ assembler parsing
+# asmw_ assembler writing/binary writers
+# unit_ unit handling
+# scan_ scanner
+# parser_ parser
+# type_ type checking
+# general_ general info
+# exec_ calls to assembler, linker, binder
+#
+# <type> the type of the message it should normally used for
+# f_ fatal error
+# e_ error
+# w_ warning
+# n_ note
+# h_ hint
+# i_ info
+# l_ add linenumber
+# u_ used
+# t_ tried
+# c_ conditional
+# d_ debug message
+# x_ executable informations
+#
+
+#
+# Umum
+#
+# 01023 is the last used one
+#
+# BeginOfTeX
+% \section{Pesan kompilator umum}
+% Seksi ini memberikanpesan kompilator yang tidak fatal, tapi
+% menampilkan informasi berguna. Jumlah pesan itu dapat dikontrol
+% dengan berbagai saklar tingkat tampilan \var{-v}.
+% \begin{description}
+general_t_compilername=01000_T_Kompilator: $1
+% Saat saklar \var{-vt} dipakai, baris ini memberitahu anda kompilator apa
+% yang dipakai.
+general_d_sourceos=01001_D_OS Kompilator: $1
+% Saat saklar \var{-vd} dipakai, baris ini memberitahu anda apa sistem operasi
+% sumbernya.
+general_i_targetos=01002_I_OS Target: $1
+% Saat saklar \var{-vd} dipakai, baris ini memberitahu anda apa sistem operasi
+% targetnya.
+general_t_exepath=01003_T_Menggunakan path executable: $1
+% Saat saklar \var{-vt} dipakai, baris ini memberitahu anda ke mana kompilator
+% mencari binernya.
+general_t_unitpath=01004_T_Menggunakan path unit: $1
+% Saat saklar \var{-vt} dipakai, baris ini memberitahu anda ke mana kompilator
+% mencari unit terkompilasinya. Anda bisa menyetel path ini dengan \var{-Fu}
+general_t_includepath=01005_T_Menggunakan path include: $1
+% Saat saklar \var{-vt} dipakai, baris ini memberitahu anda ke mana kompilator
+% mencari file include-nya (file dipakai dalam pernyataan \var{\{\$I xxx\}}).
+% Anda dapat menyetel path ini dengan opsi \var{-I}.
+general_t_librarypath=01006_T_Menggunakan path librari: $1
+% Saat saklar \var{-vt} dipakai, baris ini memberitahu anda ke mana kompilator
+% mencari librari. Anda dapat menyetel path ini dengan opsi \var{-Fl}.
+general_t_objectpath=01007_T_Menggunakan path obyek: $1
+% Saat saklar \var{-vt} dipakai, baris ini memberitahu anda ke mana kompilator
+% mencari file obyek yang anda link (file dipakai dalam pernyataan \var{\{\$L xxx\}}).
+% Anda dapat menyetel path ini dengan opsi \var{-Fo}.
+general_i_abslines_compiled=01008_I_$1 baris dikompilasi, $2 det$3
+% Saat saklar \var{-vi} dipakai, kompilator melaporkan jumlah baris yang
+% dikompilasi, dan waktu yang diperlukan untuk mengompilasinya (waktu nyata,
+% bukan waktu program).
+general_f_no_memory_left=01009_F_Memori tidak tersisa
+% Kompilator kekurangan memori untuk mengkompilasi program anda. Ada beberapa
+% beberapa obat untuk hal ini:
+% \begin{itemize}
+% \item Jika anda menggunakan opsi pembangunan kompilator, coba mengompilasi
+% unit-unit berbeda secara manual.
+% \item Jika anda mengompilasi program besar, pisahkan dalam units, dan
+% kompilasi ini secara terpisah.
+% \item Jika kedua item sebelumnya tidak bekerja, rekompilasi kompilator dengan
+% heap lebih besar (anda dapat memakai opsi \var{-Ch} untuk ini, \lihat o{Ch})
+% \end{itemize}
+general_i_writingresourcefile=01010_I_Menulis file Tabel String Resource: $1
+% Pesan ini ditampilkan saat kompilator menuliskan file Resource String Table
+% yang berisi semua string sumber untuk sebuah program.
+general_e_errorwritingresourcefile=01011_E_Menulis file Tabel String Resource: $1
+% Pesan ini ditampilkan saat kompilator menemukan kesalahaan ketika menulis
+% file Resource String Table
+general_i_fatal=01012_I_Fatal:
+% Prefiks untuk Kesalahan Fatal
+general_i_error=01013_I_Kesalahan:
+% Prefiks untuk Kesalahan
+general_i_warning=01014_I_Peringatan:
+% Prefiks untuk Peringatan
+general_i_note=01015_I_Catatan:
+% Prefiks untuk Catatan
+general_i_hint=01016_I_Petunjuk:
+% Prefiks untuk Petunjuk
+general_e_path_does_not_exist=01017_E_Path "$1" tidak ada
+% Path yang ditetapkan tidak ada.
+general_f_compilation_aborted=01018_F_Kompilasi dibatalkan
+% Kompilasi sudah dibatalkan.
+general_text_bytes_code=01019_byte kode
+general_text_bytes_data=01020_byte data
+general_i_number_of_warnings=01021_I_$1 peringatan diterbitkan
+% Jumlah peringatan yang diterbitkan selama kompilasi.
+general_i_number_of_hints=01022_I_$1 petunjuk diterbitkan
+% Jumlah petunjuk yang diterbitkan selama kompilasi.
+general_i_number_of_notes=01023_I_$1 catatan diterbitkan
+% Jumlah catatan yang diterbitkan selama kompilasi.
+% \end{description}
+#
+# Scanner
+#
+# 02084 is the last used one
+#
+% \section{Pesan pemindai.}
+% Seksi ini mendaftarkan pesan-pesan yang dikeluarkan pemindai. Pemindai
+% memelihara struktur leksikal atas file pascal, misalnya ia mencoba menemukan
+% kata-kata terpakai, string, dll. Ia juga memelihara direktif dan penanganan
+% kompilasi kondisional.
+% \begin{description}
+scan_f_end_of_file=02000_F_Akhir file tidak diharapkan
+% Ini biasanya terjadi dalam salah satu kasus berikut :
+% \begin{itemize}
+% \item File sumber berakhir sebelum pernyataan \var{end.} final. Ini
+% terjadi umumnya saat pernyataan \var{begin} dan \var{end} tidak
+% seimbang;
+% \item File include berakhir ditengah-tengah sebuah pernyataan.
+% \item Sebuah komentar tidak ditutup
+% \end{itemize}
+scan_f_string_exceeds_line=02001_F_String melebihi baris
+% Kekurangan penutup ' dalam sebuah string, maka ia melibatkan
+% multipel baris.
+scan_f_illegal_char=02002_F_Karakter tidak benar "$1" ($2)
+% Sebuah karakter yang ditemukan tidak benar dalam file input.
+scan_f_syn_expected=02003_F_Sintaks salah, "$1" diharapkan tetapi "$2" ditemukan
+% Ini menunjukan bahwa kompilator mengharapkan token yang berbeda daripada
+% yang anda ketikan. Ini bisa terjadi hampir di manapun anda membuat sebuah
+% kesalahan terhadap bahasa pascal.
+scan_t_start_include_file=02004_TL_Mulai membaca file include $1
+% Ketika anda menyediakan saklar \var{-vt}, kompilator memberitahu anda
+% kapan ia mulai membaca sebuah file yang disertakan.
+scan_w_comment_level=02005_W_Tingkat komentar $1 ditemukan
+% Saat saklar \var{-vw} dipakai, maka kompilator memperingatkan anda bila
+% ia menemukan komentar berulang. Komentar berulang tidak dibolehkan dalam
+% Turbo Pascal dan mungkin menjadi sumber kesalahan.
+scan_n_ignored_switch=02008_N_Saklar kompilator "$1" diabaikan
+% Dengan \var{-vn} hidup, kompilator memperingatkan bila ia mengabaikan saklar
+scan_w_illegal_switch=02009_W_Saklar kompilator "$1" tidak benar
+% Anda menyertakan saklar kompilator (misalnya \var{\{\$... \}}) yang tidak
+% dikenal oleh kompilator
+scan_w_switch_is_global=02010_W_Saklar global kompilator salah tempat
+% Saklar kompilator salah menempatkan, anda harus ditempatkan di awal
+% unit atau program.
+scan_e_illegal_char_const=02011_E_Konstan char tidak benar
+% Ini terjadi saat anda menetapkan karakter dengan kode ASCII-nya, seperti
+% dalam \var{\#96}, tapi angka baik tidak benar ataupun di luar jangkauan.
+scan_f_cannot_open_input=02012_F_Tidak bisa membuka file "$1"
+% \fpc todal dapat menemukan program atau file sumber unit yang anda tetapkan
+% pada baris perintah.
+scan_f_cannot_open_includefile=02013_F_Tidak bisa membuka file include "$1"
+% \fpc tidak bisa menemukan file sumber yang anda tetapkan dalam pernyataan
+% \var{\{\$include ..\}}.
+scan_e_illegal_pack_records=02015_E_Pembeda penjajaran record "$1"
+% Anda menetapkan \var{\{\$PACKRECORDS n\} } atau \var{\{\$ALIGN n\} }
+% dengan nilai tidak benar untuk \var{n}. Penjajaran yang benar untuk \$PACKRECORDS adalah 1, 2, 4, 8, 16, 32, C,
+% NORMAL, DEFAULT, dan penjajaran yang benar untuk \$ALIGN adalah 1, 2, 4, 8, 16, 32, ON,
+% OFF. Di bawah mode MacPas \$ALIGN juga mendukung MAC68K, POWER dan RESET.
+scan_e_illegal_pack_enum=02016_E_Pembeda besar-minimum enum "$1" tidak benar
+% Anda menetapkan \var{\{\$PACKENUM n\}} dengan nilai yang tidak benar untuk
+% \var{n}. Hanya 1,2,4, NORMAL atau DEFAULT yang benar di sini.
+scan_e_endif_expected=02017_E_$ENDIF diharapkan untuk $1 $2 didefinisikan dalam $3 baris $4
+% Pernyataan kompilasi kondisional anda tidak seimbang.
+scan_e_preproc_syntax_error=02018_E_Sintaks salah saat mengurai ekspresi kompilasi kondisional
+% Ini adalah kesalahan dalam ekspresi mengikuti direktori kompilator \var{\{\$if ..\}},
+% $ifc atau $setc.
+scan_e_error_in_preproc_expr=02019_E_Mengevaluasi ekspresi kompilasi kondisional
+% Ini adalah kesalahan dalam ekspresi mengikuti direktori kompilator \var{\{\$if ..\}},
+% $ifc atau $setc.
+scan_w_macro_cut_after_255_chars=02020_W_Panjang isi makro dibatasi 255 karakter
+% Isi dari makro tidak bisa lebih panjang dari 255 karakter.
+scan_e_endif_without_if=02021_E_ENDIF tanpa IF(N)DEF
+% Pernyataan \var{\{\$IFDEF ..\}} dan {\{\$ENDIF\}} anda tidak seimbang.
+scan_f_user_defined=02022_F_Didefinisikan pengguna: $1
+% Yang didefinisikan pengguna terjadi kesalahan fatal. Lihat juga \progref
+scan_e_user_defined=02023_E_Didefinisikan pengguna: $1
+% Kesalahanyang didefinisikan pengguna terjadi. Lihat juga \progref
+scan_w_user_defined=02024_W_Didefinisikan pengguna: $1
+% Peringtan yang didefinisikan pengguna ditemukan. Lihat juga \progref
+scan_n_user_defined=02025_N_Didefinisikan pengguna: $1
+% Catatan yang didefinisikan pengguna ditemukan. Lihat juga \progref
+scan_h_user_defined=02026_H_Didefinisikan pengguna: $1
+% Petunjuk yang didefinisikan pengguna ditemukan. Lihat juga \progref
+scan_i_user_defined=02027_I_Didefinisikan pengguna: $1
+% Informasi yang didefinisikan pengguna ditemukan. Lihat juga \progref
+scan_e_keyword_cant_be_a_macro=02028_E_Kata kunci didefiniskan ulang sebagai makro tidak berpengaruh
+% Anda tidak dapat mendefinisikan kata kunci dengan makro.
+scan_f_macro_buffer_overflow=02029_F_Bufer makro berlebihan saat membaca atau melebarkan makro
+% Makro anda atau hasilnya terlalu panjang bagi kompilator.
+scan_w_macro_too_deep=02030_W_Pelebaran makro melebihi kedalaman 16.
+% Ketika melebarkan sebuah makro, makro diulang sampai tingkat 16.
+% Kompilator tidak akan melebarkannya lagi, karena ini berupa tanda bahwa
+% rekursi yang digunakan.
+scan_w_wrong_styled_switch=02031_W_Saklar kompilator tidak didukung dalam gaya komentar //
+% Saklar kompilator harus dalam komentar gaya pascal normal.
+scan_d_handling_switch=02032_DL_Penanganan saklar "$1"
+% Ketika anda menyetel info debugging pada (\var{-vd}) kompilator memberitahu
+% anda saatia mengevaluasi pernyataan kompilasi kondisional.
+scan_c_endif_found=02033_CL_ENDIF $1 ditemukan
+% Ketika anda menghidupkan pesan kondisional (\var{-vc}), kompilator memberitahu
+% anda di aman ia menemukanpernyataan kondisional.
+scan_c_ifdef_found=02034_CL_IFDEF $1 ditemukan, $2
+% Ketika anda menghidupkan pesan kondisioinal (\var{-vc}), kompilator memberitahu
+% anda di mana ia menemukan pernyataan kondisional.
+scan_c_ifopt_found=02035_CL_IFOPT $1 ditemukan, $2
+% Ketika anda menghidupkan pesan kondisioinal (\var{-vc}), kompilator memberitahu
+% anda di mana ia menemukan pernyataan kondisional.
+scan_c_if_found=02036_CL_IF $1 ditemukan, $2
+% Ketika anda menghidupkan pesan kondisioinal (\var{-vc}), kompilator memberitahu
+% anda di mana ia menemukan pernyataan kondisional.
+scan_c_ifndef_found=02037_CL_IFNDEF $1 ditemukan, $2
+% Ketika anda menghidupkan pesan kondisioinal (\var{-vc}), kompilator memberitahu
+% anda di mana ia menemukan pernyataan kondisional.
+scan_c_else_found=02038_CL_ELSE $1 ditemukan, $2
+% Ketika anda menghidupkan pesan kondisioinal (\var{-vc}), kompilator memberitahu
+% anda di mana ia menemukan pernyataan kondisional.
+scan_c_skipping_until=02039_CL_Melewati sampai...
+% Ketika anda menghidupkan pesan kondisioinal (\var{-vc}), kompilator memberitahu
+% anda di mana ia menemukan pernyataan kondisional, dan apakah ia melewati atau
+% mengompilasi bagiannya.
+scan_i_press_enter=02040_I_Tekan <return> untuk melanjutkan
+% Saat saklar \var{-vi} dipakai, kompilator berhenti mengompilasi dan menunggu
+% tombol \var{Enter} ditekan bila ia menemukan direktif
+% \var{\{\$STOP\}}.
+scan_w_unsupported_switch=02041_W_Saklar "$1" tidak didukung
+% Saat peringatan dihidupkan (\var{-vw}) kompilator memperingatkan anda tentang
+% saklar yang tidak didukung. Ini berarti bahwa saklar yang dipakai dalam Delphi
+% atau Turbo Pascal, tetapi tidak dalam \fpc
+scan_w_illegal_directive=02042_W_Direktif kompilator "$1" tidak benar
+% Saat peringatan dihidupkan (\var{-vw}) kompilator memperingatkan anda tentang
+% saklar yang tidak dikenal. Untuk daftar saklar yang dikenal, \progref
+scan_t_back_in=02043_TL_Kembali dalam $1
+% Saat anda memakai (\var{-vt}) kompilator memberitahu anda kapan ia selesai
+% membaca sebuah file include.
+scan_w_unsupported_app_type=02044_W_Tipe aplikasi tidak didukung: "$1"
+% Anda mendapat peringatan ini, jika anda menetapkan tipe aplikasi tidak dikenal
+% dengan direktif \var{\{\$APPTYPE\}}
+scan_w_app_type_not_support=02045_W_APPTYPE tidak didukung oleh OS target
+% Direktif \var{\{\$APPTYPE\}} hanya didukung oleh sistem operasi tertentu.
+scan_w_description_not_support=02046_W_DESCRIPTION tidak didukung oleh OS target
+% Direktif \var{\{\$DESCRIPTION\}} tidak didukung pada OS target ini
+scan_n_version_not_support=02047_N_VERSION tidak didukung oleh OS target
+% Direktif \var{\{\$VERSION\}} tidak didukung pada OS target ini
+scan_n_only_exe_version=02048_N_VERSION hanya untuk EXE atau DLL
+% Direktif \var{\{\$VERSION\}} hanya dipakai untuk executable atau sumber DLL.
+scan_w_wrong_version_ignored=02049_W_Format salah untuk direktif VERSION "$1"
+% Format direktif \var{\{\$VERSION\}} adalah versiutama.versiminor
+% di mana versiutama dan versiminor adalah word.
+scan_e_illegal_asmmode_specifier=02050_E_Gaya assembler yang ditetapkan "$1" tidak benar
+% Ketika anda menetapkan mode assembler dengan \var{\{\$ASMMODE xxx\}}
+% kompilator tidak mengenal mode yang anda tetapkan.
+scan_w_no_asm_reader_switch_inside_asm=02051_W_Saklar pembaca ASM tidak mungkin di dalam pernyataan asm, "$1" hanya efektif untuk next
+% Tidak mungkin untuk beralih dari satu pembaca assembler ke yang lainnya
+% di dalam blok assembler. Pembaca baru hanya akan dipakai untuk pernyataan
+% assembler next saja.
+scan_e_wrong_switch_toggle=02052_E_Saklar toggle salah, gunakan ON/OFF atau +/-
+% Anda perlu menggunakan ON atau OFF atau + atau - untuk menghidup matikan saklar
+scan_e_resourcefiles_not_supported=02053_E_File resource tidak didukung untuk target ini
+% Target yang anda kompilasi tidak mendukung file resource.
+scan_w_include_env_not_found=02054_W_Lingkungan include "$1" tidak ditemukan dalam lingkungan
+% Variabel lingkungan yang disertakan tidak ditemukan dalam lingkungan, sebaliknya
+% ia akan diganti dengan string kosong.
+scan_e_invalid_maxfpureg_value=02055_E_Nilai batas register FPU tidak benar
+% Nilai yang benar untuk direktif ini adalah 0..8 dan NORMAL/DEFAULT
+scan_w_only_one_resourcefile_supported=02056_W_Hanya satu file resource didukung untuk target ini
+% Target yang anda kompilasi hanya mendukung satu file resource.
+% File resource pertama yang ditemukan akan dipakai, yuang lain diabaikan.
+scan_w_macro_support_turned_off=02057_W_Dukungan makro telah dimatikan
+% Deklarasi makro ditemukan, tapi dukungan makro sudah dimatikan,
+% maka deklarasi akan diabaikan. Untuk menghidupkan dukungan makro, kompilasi dengan
+% -Sm pada baris perintah atau tambah \{\$MACRO ON\} dalam sumber file
+scan_e_invalid_interface_type=02058_E_Tipe antarmuka yang ditetapkan tidak benar. Yang benar COM, CORBA atau DEFAULT.
+% Tipe antarmuka yang ditetapkan tidak didukung
+scan_w_appid_not_support=02059_W_APPID hanya didukung pada PalmOS
+% Direktif \var{\{\$APPID\}} hanya didukung jika target PalmOS.
+scan_w_appname_not_support=02060_W_APPNAME hanya didukung oleh PalmOS
+% Direktif \var{\{\$APPNAME\}} hanya didukung oleh target PalmOS.
+scan_e_string_exceeds_255_chars=02061_E_Konstan string tidak boleh lebih panjang dari 255 karakter
+% Konstan string tunggal dapat berisi paling banyak 255 karakter. Coba untuk
+% memisahkan string dalam bagian multipel lebih kecil dan tambah dengan operator +.
+scan_f_include_deep_ten=02062_F_Menyertakan file include melebihi kedalaman 16.
+% Ketika menyertakan file include, file sudah diulang ke tingkat 16.
+% Kompilator tidak akan melebarkannya lagi, karena ini sebagai tanda bahwa
+% rekursi yang dipakai.
+scan_e_too_many_push=02063_F_Terlalu banyak tingkat PUSH
+% Maksimum 20 tingkat dibolehkan. Kesalahan ini hanya terjadi dalam mode MacPas.
+scan_e_too_many_pop=02064_E_POP tanpa didahului PUSH
+% Kesalahan ini hanya terjadi dalam mode MacPas.
+scan_e_error_macro_lacks_value=02065_E_Makro atau variabel waktu kompilasi "$1" tidak memiliki nilai
+% Ekspresi waktu kompilasi kondisional tidak bisa dievaluasi.
+scan_e_wrong_switch_toggle_default=02066_E_Saklar toggle salah, gunakan ON/OFF/DEFAULT atau +/-/*
+% Anda perlu menggunakan ON atau OFF atau DEFAULT atau + atau - atau * untuk men-toggle saklar
+scan_e_mode_switch_not_allowed=02067_E_Saklar mode "$1" tidak diijinkan di sini
+% Saklar mode sudah ditemukan, atau dalam hal opsi -Mmacpas,
+% saklar mode terjadi setelah UNIT.
+scan_e_error_macro_undefined=02068_E_Variabel waktu kompilasi atau makro "$1" tidak didefinisikan.
+% Ekspresi waktu kompilasi kondisional tidak bisa dievaluasi. Hanya dalam mode MacPas.
+scan_e_utf8_bigger_than_65535=02069_E_Kode UTF-8 lebih besar dari 65535 ditemukan
+% \fpc menangani string utf-8 secara internal sebagai widestring misalnya kode karakter dibatasi ke 65535
+scan_e_utf8_malformed=02070_E_String UTF-8 salah bentuk
+% String yang diberikan bukan string UTF-8 yang benar
+scan_c_switching_to_utf8=02071_C_Tanda UTF-8 ditemukan, menggunakan enkode UTF-8
+% Kompilator menemukan tanda enkode UTF-8 (\$ef, \$bb, \$bf) di awal file,
+% maka ia menganggapnya sebagai file UTF-8
+scan_e_compile_time_typeerror=02072_E_Ekspresi waktu kompilasi: Diinginkan $1 tapi didapat $2 pada $3
+% Pemeriksaan tipe pada ekspresi waktu kompilasi gagal.
+scan_n_app_type_not_support=02073_N_APPTYPE tidak didukung oleh OS target
+% Direktif \var{\{\$APPTYPE\}} hanya didukung oleh sistem operasi tertentu.
+scan_e_illegal_optimization_specifier=02074_E_Optimasi yang ditetapkan "$1" tidak benar
+% Ketika anda menetapkan optimasi dengan \var{\{\$OPTIMIZATION xxx\}}
+% kompilator tidak mengenali optimasi yang anda tetapkan.
+scan_w_setpeflags_not_support=02075_W_SETPEFLAGS tidak didukung oleh OS target
+% Direktif \var{\{\$SETPEFLAGS\}} tidak didukung oleh OS target
+scan_w_imagebase_not_support=02076_W_IMAGEBASE tidak dudkung oleh OS target
+% Direktif \var{\{\$IMAGEBASE\}} tidak dudkung oleh OS target
+scan_w_minstacksize_not_support=02077_W_MINSTACKSIZE tidak dudkung oleh OS target
+% Direktif \var{\{\$MINSTACKSIZE\}} tidak dudkung oleh OS target
+scan_w_maxstacksize_not_support=02078_W_MAXSTACKSIZE tidak dudkung oleh OS target
+% Direktif \var{\{\$MAXSTACKSIZE\}} tidak dudkung oleh OS target
+scanner_e_illegal_warn_state=02079_E_Kondisi direktif $WARN tidak benar
+% Hanya ON dan OFF bisa dipakai sebagai kondisi dengan direktif kompilator \$warn
+scan_e_only_packset=02080_E_Nilai set packing tidak benar
+% Hanya 0, 1, 2, 4, 8, DEFAULT dan NORMAL diijinkan sebagai parameter packset
+scan_w_pic_ignored=02081_W_Direktif PIC atau saklar diabaikan
+% Beberapa target seperti windows tidak mendukung PIC maka direktif PIC dan
+% saklar diabaikan.
+scan_w_unsupported_switch_by_target=02082_W_Saklar "$1" tidak didukung oleh target yang dipilih saat ini
+% Beberapa saklar kompilator seperti \$E tidak didukung oleh semua target.
+scan_w_frameworks_darwin_only=02084_W_Opsi terkait-framework hanya didukung oleh Darwin/Mac OS X
+% Frameworks bukan konsep yang dikenal, atau setidaknya didukung oleh FPC, pada sistem operasi selain Darwin/Mac OS X.
+scan_e_illegal_minfpconstprec=02085_E_Konstan presisi pecahan minimal "$1" tidak benar
+% Presisi minimal yang benar untuk konstan floating point adalah standar, 32 dan 64, yang berarti masing-masing presisi minimal (biasanya 32 bit), 32 bit dan 64 bit.
+% \end{description}
+#
+# Parser
+#
+# 03235 is the last used one
+#
+% \section{Pesan pengurai}
+% Seksi ini mendaftarkan semua pesan pengurai. Pengurai memelihara semantik
+% atas bahasa anda, misalnya ia menentukan apakah konstruksi pascal anda
+% sudah benar atau tidak.
+% \begin{description}
+parser_e_syntax_error=03000_E_Pengurai - Sintaks Salah
+% Kesalahan terhadap bahasa Turbo Pascal ditemukan. Ini terjadi biasanya
+% saat karakter tidak benar ditemukan dalam file sumber.
+parser_e_dont_nest_interrupt=03004_E_Prosedur INTERRUPT tidak bisa diulang
+% Prosedur \var{INTERRUPT} harus global.
+parser_w_proc_directive_ignored=03005_W_Tipe prosedur "$1" diabaikan
+% Direktif procedure yang dietapkan diabaikan oleh program FPC.
+parser_e_no_overload_for_all_procs=03006_E_Tidak semua deklarasi "$1" dideklarasikan dengan OVERLOAD
+% Ketika anda ingin menggunakan direktif \var{OVERLOAD}, maka semua
+% deklarasi perlu menetapkan \var{OVERLOAD}.
+parser_e_export_name_double=03008_E_Duplikasi nama fungsi yang diekspor "$1"
+% Nama-nama fungsi yang diekspor di dalam DLL tertentu semuanya harus berbeda
+parser_e_export_ordinal_double=03009_E_Duplikasi indeks fungsi yang diekspor $1
+% Indeks fungsi yang diekspor di dalam DLL tertentu semuanya harus berbeda
+parser_e_export_invalid_index=03010_E_Indeks untuk fungsi yang diekspor tidak benar
+% Indeks fungsi DLL harus dalam jangkauan \var{1..\$FFFF}
+parser_w_parser_reloc_no_debug=03011_W_DLL yang bisa direlokasi atau info debug executable $1 tidak bekerja, dimatikan.
+parser_w_parser_win32_debug_needs_WN=03012_W_Untuk membolehkan men-debug pada kode win32 anda perlu mematikan relokasi dengan opsi -WN
+% Info stab salah untuk DLL atau EXE yang bisa direlokasi, gunakan -WN
+% jika anda ingin men-debug win32 executable.
+parser_e_constructorname_must_be_init=03013_E_Nama konstruktor harus INIT
+% Anda mendeklarasikan konstruktor obyek dengan nama yang bukan \var{init}, dan
+% saklar \var{-Ss} dipakai. Lihat saklar \var{-Ss} (\seeo{Ss}).
+parser_e_destructorname_must_be_done=03014_E_Nama destruktor harus DONE
+% Anda mendeklarasikan destruktor obyek yang bukan \var{done}, dan saklar
+% \var{-Ss} dipakai. Lihat saklar \var{-Ss} (\seeo{Ss}).
+parser_e_proc_inline_not_supported=03016_E_Tipe prosedur INLINE tidak didukung
+% Anda mencoba untuk mengompilasi program dengan gaya inline C++, dan lupa
+% menetapkan opsi \var{-Si} (\seeo{Si}). Standarnya kompilator tidak mendukung
+% gaya inline C++.
+parser_w_constructor_should_be_public=03018_W_Konstruktor harus public
+% Konstruktor harus dalam bagian 'public' pada sebuah deklarasi obyek (class).
+parser_w_destructor_should_be_public=03019_W_Destruktor harus public
+% Destruktor harus dalam bagian 'public' pada sebuah deklarasi obyek (class).
+parser_n_only_one_destructor=03020_N_Class harus memiliki hanya satu destruktor
+% Anda dapat mendeklarasikan hanya satu destruktor untuk sebuah kelas.
+parser_e_no_local_objects=03021_E_Definisi kelas lokal tidak dibolehkan
+% Kelas harus didefinisikan secara global. Tidak bisa didefinisikan di dalam
+% sebuah procedure atau function
+parser_f_no_anonym_objects=03022_F_Definisi kelas anonim tidak dibolehkan
+% Deklarasi obyek (class) tidak benar ditemukan, misalnya obyek atau kelas
+% tanpa metode yang tidak berasal dari obyek atau kelas
+% Sebagai contoh:
+% \begin{verbatim}
+% Type o = object
+% a : longint;
+% end;
+% \end{verbatim}
+% akan memicu kesalahan ini.
+parser_n_object_has_no_vmt=03023_N_Obyek "$1" tidak memiliki VMT
+% Ini adalah sebuah catatan yang menunjukan bahwa obyek yang dideklarasikan
+% tidak memiliki tabel metode virtual.
+parser_e_illegal_parameter_list=03024_E_Daftar parameter tidak benar
+% Anda memanggil sebuah fungsi dengan parameter yang tipenya berbeda dengan
+% yang parameternya dideklarasikan pada fungsi.
+parser_e_wrong_parameter_size=03026_E_Jumlah parameter salah yang ditetapkan untuk memanggil "$1"
+% Ada kesalahan dalam daftar parameter pada fungsi atau prosedur,
+% jumlah parameter tidak benar.
+parser_e_overloaded_no_procedure=03027_E_pembeda yang di-overload "$1" bukan sebuah fungsi
+% Kompilator menemukan simbol dengan nama sama seperti fungsi yang di-overload,
+% tapi ia bukan sebuah fungsi yang bisa di-overload.
+parser_e_overloaded_have_same_parameters=03028_E_fungsi yang di-overload memiliki daftar parameter sama
+% Anda mendeklarasikan fungsi yang di-overload, tapi dengan daftar parameter yang sama.
+% Fungsi yang di-overload harus memiliki setidaknya 1 parameter berbeda dalam
+% deklarasinya.
+parser_e_header_dont_match_forward=03029_E_Header fungsi tidak sama dengan deklarasi "$1" sebelumnya
+% Anda mendeklarasikan sebuah fungsi dengan parameter yang sama tetapi
+% tipe hasil atau pengubah fungsi berbeda.
+parser_e_header_different_var_names=03030_E_header fungsi "$1" tidak sama yang didepan : nama var berubah $2 => $3
+% Anda mendeklarasikan fungsi dalam bagian \var{interface}, atau dengan direktif
+% \var{forward}, tapi mendefinisikannya dengan daftar parameter yang berbeda.
+parser_n_duplicate_enum=03031_N_Nilai dalam tipe enumerasi harus membesar
+% \fpc membolehkan konstruksi enumeration seperti dalam C. Contoh berikut
+% mendeklarasikan dua deklarasi:
+% \begin{verbatim}
+% type a = (A_A,A_B,A_E:=6,A_UAS:=200);
+% type a = (A_A,A_B,A_E:=6,A_UAS:=4);
+% \end{verbatim}
+% Deklarasi kedua akan menghasilkan kesalahan. \var{A\_UAS} perlu mempunyai
+% nilai lebih tinggi daripada \var{A\_E}, misalnya minimal 7.
+parser_e_no_with_for_variable_in_other_segments=03033_E_With tidak bisa dipakai untuk variabel dalam segmen berbeda
+% With menyimpan variabel secara lokal pada stack, tapi ini tidak mungkin
+% jika variabel dimiliki oleh segmen lain.
+parser_e_too_much_lexlevel=03034_E_pengulangan fungsi > 31
+% Anda dapat mengulang definisi function hanya 31 kali.
+parser_e_range_check_error=03035_E_kesalahan pemeriksaan jangkauan saat mengevaluasi konstan
+% Konstan di luar dari jangkauan yang dibolehkan.
+parser_w_range_check_error=03036_W_kesalahan pemeriksaan jangkauan saat mengevaluasi konstan
+% Konstan di luar dari jangkauan yang dibolehkan.
+parser_e_double_caselabel=03037_E_duplikasi label case
+% Anda menetapkan label yang sama 2 kali dalam pernyataan \var{case}.
+parser_e_case_lower_less_than_upper_bound=03038_E_Batas atas jangkauan case kurang dari batas bawah
+% Batas atas dari label \var{case} kurang dari batas lebih bawah dan ini
+% sia-sia
+parser_e_type_const_not_possible=03039_E_Tipe konstan pada kelas atau interfaces tidak dibolehkan
+% Anda tidak bisa mendeklarasikan konstan dari tipe class atau object.
+parser_e_no_overloaded_procvars=03040_E_variabel fungsi pada fungsi yang di-overload tidak dibolehkan
+% Anda mencoba untuk menempatkan fungsi yang di-overload ke variabel prosedural.
+% Ini tidak dibolehkan
+parser_e_invalid_string_size=03041_E_panjang string harus berupa nilai dari 1 sampai 255
+% Panjang shortstring dalam Pascal dibatasi 255 karakter. Anda mencoba untuk
+% mendeklarasikan string dengan panjang lebih rendah dari 1 atau lebih besar dari 255
+parser_w_use_extended_syntax_for_objects=03042_W_gunakan sintaks diperluas NEW dan DISPOSE untuk turunan obyek
+% Jika anda mempunyai pointer \var{a} ke tipe kelas, maka pernyataan
+% \var{new(a)} tidak akan menginisialisasi kelas (misalnya konstruktor tidak
+% dipanggil), meskipun ruang akan dialokasikan. Anda harus menerbitkan pernyataan
+% \var{new(a,init)}. Ini akan mengalokasikan ruang, dan memanggil konstruktor
+% obyek
+parser_w_no_new_dispose_on_void_pointers=03043_W_Menggunakan NEW atau DISPOSE untuk pointer untyped sia-sia
+parser_e_no_new_dispose_on_void_pointers=03044_E_Menggunakan NEW atau DISPOSE tidak mungkin untuk pointer untyped
+% Anda tidak bisa menggunakan \var{new(p)} atau \var{dispose(p)} jika \var{p} adalah pointer untyped
+% karena tidak ada ukuran yang terkait dengan pointer untyped.
+% Diterima untuk kompatibilitas dalam mode \var{tp} dan \var{delphi}.
+parser_e_class_id_expected=03045_E_pengenal kelas diharapkan
+% Ini terjadi saat kompilator memindai deklarasi procedure yang berisi
+% sebuah titik,
+% misalnya, metode obyek atau kelas, tapi tipe di depan titik bukan
+% tipe yang dikenal.
+parser_e_no_type_not_allowed_here=03046_E_pengenal type tidak dibolehkan di sini
+% Anda tidak bisa menggunakan sebuah type di dalam ekspresi.
+parser_e_methode_id_expected=03047_E_pengenal metode diharapkan
+% Pengenal ini bukan sebuah metode.
+% Ini terjadi saat kompilator memindai deklarasi sebuah procedure yang berisi
+% sebuah titik, misalnya nama obyek atau kelas, tapi nama prosedure bukan
+% prosedur dari tipe ini.
+parser_e_header_dont_match_any_member=03048_E_header fungsi tidak ada yang menyamai metode pada kelas "$1"
+% Pengenal ini bukan sebuah metode.
+% Ini terjadi saat kompilator memindai deklarasi prosedur yang berisi sebuah
+% titik, misalnya nama obyek atau kelas, tapi nama prosedure bukan
+% prosedur dari tipe ini.
+parser_d_procedure_start=03049_DL_procedure/function $1
+% Ketika menggunakan saklar \var{-vd}, kompilator memberitahu anda saat ia mulai
+% memproses sebuah implementasi procedure atau function.
+parser_e_error_in_real=03050_E_Konstan floating point tidak benar
+% Kompilator mengharapkan ekspresi floating point, dan mendapatkan yang lain.
+parser_e_fail_only_in_constructor=03051_E_FAIL hanya dapat dipakai dalam konstruktor
+% Anda menggunakan kata kunci \var{fail} di luar metode konstruktor.
+parser_e_no_paras_for_destructor=03052_E_Destruktor tidak bisa mempunyai parameter
+% Anda mendeklarasikan sebuah destruktor dengan daftar parameter. Metode destruktor
+% tidak bisa memiliki parameter.
+parser_e_only_class_methods_via_class_ref=03053_E_Hanya metode kelas dapat dirujuk dengan referensi kelas
+% Kesalahan ini terjadi dalam situasi seperti berikut:
+% \begin{verbatim}
+% Type :
+% Tclass = Class of Tobject;
+%
+% Var C : TClass;
+%
+% begin
+% ...
+% C.free
+% \end{verbatim}
+% \var{Free} bukan metode kelas dan tidak bisa dipanggil dengan referensi
+% kelas.
+parser_e_only_class_methods=03054_E_Hanya metode kelas bisa diakses dalam metode kelas
+% Ini terkait dengan kesalahan sebelumnya. Anda tidak bisa memanggil metode obyek dari
+% dalam metode kelas. Kode berikut akan menghasilkan kesalahan ini:
+% \begin{verbatim}
+% class procedure tobject.x;
+%
+% begin
+% free
+% \end{verbatim}
+% Karena free adalah metode normal sebuah kelas, ia tidak bisa dipanggil dari
+% metode kelas.
+parser_e_case_mismatch=03055_E_Tipe konstan dan CASE tidak sama
+% Salah satu label tidak memiliki tipe yang sama seperti variabel case.
+parser_e_illegal_symbol_exported=03056_E_Simbol tidak bisa diekspor dari sebuah librari
+% Anda hanya bisa mengekspor prosedur dan fungsi saat anda menulis sebuah librari. Anda
+% tidak bisa mengekspor variabel atau konstan.
+parser_w_should_use_override=03057_W_Metode yang diturunkan tidak terlihat oleh "$1"
+% Metode yang dideklarasikan \v ar{virtual} dalam kelas leluhur, harus diganti
+% dalam kelas turunannya dengan direktif \var{override}. Jika anda tidak
+% menetapkan direktif \var{override}, anda akan menyembunyikan metode leluhur;
+% anda tidak akan menggantinya.
+parser_e_nothing_to_be_overridden=03058_E_Tidak ada metode dalam kelas leluhur untuk diganti: "$1"
+% Anda mencoba untuk \var{override} sebuah metode virtual pada kelas leluhur yang tidak
+% ada.
+parser_e_no_procedure_to_access_property=03059_E_Tidak ada anggota yang disediakan untuk mengakses properti
+% Anda tidak menetapkan direktif \var{read} untuk sebuah properti.
+parser_w_stored_not_implemented=03060_W_Direktif properti tersimpan belum diimplementasikan
+% Direktif \var{stored} belum diimplementasikan
+parser_e_ill_property_access_sym=03061_E_Simbol tidak benar untuk akses properti
+% Ada kesalahan dalam direktif \var{read} atau \var{write} untuk sebuah properti
+% array. Ketika anda mendeklarasikan sebuah properti array, anda hanya bisa
+% mengaksesnya dengan prosedur atau fungsi. Kode berikut akan membuat kesalahan
+% \begin{verbatim}
+% tmyobject = class
+% i : integer;
+% property x [i : integer]: integer read I write i;
+% \end{verbatim}
+%
+parser_e_cant_access_protected_member=03062_E_Tidak bisa mengakses field protected pada obyek di sini
+% Field yang dideklarasikan dalam seksi \var{protected} pada deklarasi obyek
+% atau kelas tidak bisa diakses dari luar modul di mana obyek itu
+% didefinisikan, atau di luar metode obyek turunannya.
+parser_e_cant_access_private_member=03063_E_Tidak bisa mengakses field private pada obyek di sini
+% Field yang dideklarasikan dalam seksi \var{private} pada deklarasi obyek
+% atau kelas tidak bisa diakses dari luar modul di mana obyek itu
+% didefinisikan, atau di luar metode obyek turunannya.
+parser_e_overridden_methods_not_same_ret=03066_E_Metode yang diganti harus mengembalikan tipe: "$2" diganti oleh "$1" yang menghasilkan tipe lain
+% Jika anda mendeklarasikan metode pengganti dalam definisi kelas, keduanya harus
+% memiliki tipe hasil yang sama.
+parser_e_dont_nest_export=03067_E_Fungsi yang dideklarasikan EXPORT tidak bisa diulang
+% Anda tidak bisa mendeklarasikan sebuah fungsi atau prosedur di dalam function atau
+% procedure yang sudah dideklarasikan sebagai prosedur ekspor.
+parser_e_methods_dont_be_export=03068_E_Method tidak bisa DIEKSPOR
+% Anda tidak bisa mendeklarasikan procedure yang metode obyeknya bisa
+% di-\var{export}.
+parser_e_call_by_ref_without_typeconv=03069_E_Panggilan dengan var untuk arg no. $1 harus sama persis: Didapat "$2" diharapkan "$3"
+% Ketika memanggil fungsi yang dideklarasikan dengan parameter \var{var}, variabel
+% dalam pemanggil fungsi harus tipe yang persis sama. Tidak ada konversi tipe
+% otomatis.
+parser_e_no_super_class=03070_E_Kelas bukan kelas leluhur dari kelas saat ini
+% Ketika memanggil metode turunan, anda mencoba untuk memanggil metode kelas
+% tidak berkaitan. Anda hanya dapat memanggil metode turunan dari kelas leluhurnya.
+parser_e_self_not_in_method=03071_E_SELF hanya dibolehkan dalam metode
+% Anda mencoba menggunakan parameter \var{self} di luar metode obyek.
+% Hanya metode yang dioper parameter \var{self}.
+parser_e_generic_methods_only_in_methods=03072_E_Metode hanya bisa dalam metode lain memanggil secara langsung dengan pengenal tipe kelas
+% Konstruksi seperti \var{sometype.somemethod} hanya dibolehkan dalam sebuah metode.
+parser_e_illegal_colon_qualifier=03073_E_Penggunaan ':' tidak benar
+% Ada menggunakan format \var{:} (titik dua) 2 kali pada ekspresi yang
+% bukan ekspresi real.
+parser_e_illegal_set_expr=03074_E_Kesalahan pemeriksaan jangkauan dalam set konstruktor atau duplikasi set elemen
+% Deklarasi dari sebuah set berisi kesalahan. Baik salah satu elemen di luar
+% jangkauan dari set type, atau dua elemen sebenarnya
+% sama.
+parser_e_pointer_to_class_expected=03075_E_Pointer pada obyek diharapkan
+% Anda menetapkan tipe yang tidak benar dalam pernyataan \var{new}.
+% Sintaks diperluas dari \var{new} memerlukan obyek sebagai parameter.
+parser_e_expr_have_to_be_constructor_call=03076_E_Ekspresi harus panggilan konstruktor
+% Ketika menggunakan sintaks diperluas \var{new}, anda harus menetapkan metode
+% konstruktor dari obyek yang sedang anda coba buat. Prosedur yang anda tetapkan
+% bukan sebuah konstruktor.
+parser_e_expr_have_to_be_destructor_call=03077_E_Ekspresi harus panggilan destruktor
+% Ketika menggunakan sintaks diperluas \var{dispose}, anda harus menetapkan
+% metode destructor dari obyek yang sedang anda coba dispose.
+% Prosedure yang anda tetapkan bukan sebuah destruktor.
+parser_e_invalid_record_const=03078_E_Urutan elemen record tidak benar
+% Ketika mendeklarasikan konstan record, anda menetapkan field dalam urutan
+% yang salah.
+parser_e_false_with_expr=03079_E_Tipe ekspresi harus tipe kelas atau record
+% Pernyataan \var{with} memerlukan argumen yang tipenya adalah \var{record}
+% atau \var{class}. Anda mencoba menggunakan \var{with} pada ekspresi yang
+% bukan tipe ini.
+parser_e_void_function=03080_E_Prosedur tidak mengembalikan nilai
+% Dalam \fpc, anda dapat menetapkan nilai balik untuk sebuah fungsi saat
+% memakai pernyataan \var{exit}. Kesalahan ini terjadi ketika anda mencoba untuk
+% melakukan ini dengan prosedur. Prosedure tidak bisa mengembalikan nilai.
+parser_e_only_methods_allowed=03081_E_konstruktor, destruktor dan class operator harus sebuah metode
+% Anda mendeklarasikan sebuah procedure sebagai destruktor, konstructor atau class operator, ketika
+% prosedure bukan metode kelas.
+parser_e_operator_not_overloaded=03082_E_Operator tidak di-overload
+% Anda mencoba untuk menggunakan operator yang di-overload saat ia bukan tipe
+% untuk di-overload.
+parser_e_no_such_assignment=03083_E_Tidak mungkin untuk meng-overload penempatan tipe yang sama
+% Anda tidak bisa meng-overload penempatan tipe yang dianggap oleh
+% kompilator sebagai sama.
+parser_e_overload_impossible=03084_E_Overload operator tidak mungkin
+% Kombinasi operator, argumen dan tipe balik tidak
+% kompatibel.
+parser_e_no_reraise_possible=03085_E_Re-raise tidak mungkin di sini
+% Anda mencoba untuk memunculkan eksepsi yang tidak diperbolehkan. Anda hanya
+% dapat memunculkan eksepsi dalam sebuah blok \var{except}.
+parser_e_no_new_or_dispose_for_classes=03086_E_Sintaks diperluas pada new atau dispose tidak diijinkan untuk sebuah kelas
+% Anda tidak bisa membuat turunan kelas dengan sintaks yang diperluas
+% \var{new}. Konstruktor harus dipakai untuk itu. Untuk alasan yang sama, anda
+% tidak bisa memanggil \var{dispose} untuk dealokasi turunan kelas, destruktor
+% harus dipakai untuk itu.
+parser_e_procedure_overloading_is_off=03088_E_Procedure overloading dimatikan
+% Ketika menggunakan saklar \var{-So}, procedure overloading dimatikan.
+% Turbo Pascal tidak mendukung overload fungsi.
+parser_e_overload_operator_failed=03089_E_Tidak mungkinuntuk meng-overload operator ini. Operator yang bisa di-overload terkait (bila ada) adalah: $1
+% Anda mencoba untuk meng-overload sebuah operator yang tidak bisa di-overload.
+% Operator berikut dapat di-overload :
+% \begin{verbatim}
+% +, -, *, /, =, >, <, <=, >=, is, as, in, **, :=
+% \end{verbatim}
+parser_e_comparative_operator_return_boolean=03090_E_Operator komparatif harus mengembalikan nilai boolean
+% Ketika meng-overload operator \var{=}, fungsi harus mengembalikan nilai
+% boolean.
+parser_e_only_virtual_methods_abstract=03091_E_Hanya metode virtual dapat berupa abstak
+% Anda mendeklarasikan metode sebagai abstrak, ketika ia tidak dideklarasikan menjadi
+% virtual.
+parser_f_unsupported_feature=03092_F_Penggunaan fitur yang tidak didukung!
+% Anda mencoba untuk memaksa kompilator melakukan sesuatu yang belum bisa dilakukannya.
+parser_e_mix_of_classes_and_objects=03093_E_Campuran dari jenis obyek berbeda (class, object, interface, dll) tidak dibolehkan
+% Anda tidak dapat menurunkan \var{objects}, \var{classes}, \var{cppclasses} dan \var{interfaces} misalnya
+% sebuah kelas tidak memiliki obyek sebagai leluhurnya dan sebaliknya.
+parser_w_unknown_proc_directive_ignored=03094_W_Direktif procedure tidak dikenal harus diabaikan: "$1"
+% Direktif procedure yang anda tetapkan tidak dikenal.
+parser_e_absolute_only_one_var=03095_E_absolute hanya bisa dikaitkan ke satu variabel
+% Anda tidak bisa menetapkan lebih dari satu variabel sebelum direktif \var{absolute}.
+% Selanjutnya, konstruksi berikut akan menghasilkan kesalahan ini:
+% \begin{verbatim}
+% Var Z : Longint;
+% X,Y : Longint absolute Z;
+% \end{verbatim}
+% \item [ absolute hanya bisa dikaitkan ke sebuah var atau const ]
+% Alamat dari direktif \var{absolute} hanya dapat mengarah ke variabel atau
+% tipe konstan. Oleh karena itu, kode berikut akan menghasilkan kesalahan ini:
+% \begin{verbatim}
+% Procedure X;
+%
+% var p : longint absolute x;
+% \end{verbatim}
+%
+parser_e_absolute_only_to_var_or_const=03096_E_absolute hanya bisa dikaitkan dengan var atau const
+% Alamat direktif \var{absolute} hanya bisa mengarah ke variabel atau konstan.
+% Oleh karena itu, kode berikut akan menghasilkan kesalahan ini:
+% \begin{verbatim}
+% Procedure X;
+%
+% var p : longint absolute x;
+% \end{verbatim}
+%
+parser_e_initialized_only_one_var=03097_E_Hanya satu variabel dapat diinisialisasi
+% Anda tidak dapat menetapkan lebih dari satu variabel dengan nilai awal
+% dalam mode Delphi.
+parser_e_abstract_no_definition=03098_E_Metode abstract tidak boleh memiliki definisi apapun (dengan badan fungsi)
+% Metode abstract hanya bisa dideklarasikan, anda tidak bisa mengimplementasikannya. Ia
+% harus diganti dengan kelas turunannya.
+parser_e_overloaded_must_be_all_global=03099_E_Fungsi yang di-overload ini tidak boleh lokal (harus diekspor)
+% Anda mendefinisikan fungsi yang di-overload dalam bagian implementation pada sebuah
+% unit, tapi tidak ada deklarasi terkait dalam bagian interface dari unit itu.
+parser_w_virtual_without_constructor=03100_W_Metode virtual dipakai tanpa sebuah constructor dalam "$1"
+% Jika anda mendeklarasikan obyek atau kelas yang berisi metode virtual, anda perlu
+% mempunyai constructor dan destructor untuk menginisialisasinya. Kompilator
+% menemukan obyek atau kelas dengan metode virtual yang tidak memiliki pasangan
+% constructor/destructor.
+parser_c_macro_defined=03101_CL_Makro didefinisikan: $1
+% Ketika \var{-vc} dipakai, kompilator memberitahu anda saat ia mendefinisikan makro.
+parser_c_macro_undefined=03102_CL_Makro tidak didefinisikan: $1
+% Ketika \var{-vc} dipakai, kompilator memberitahu anda saat ia tidak mendefinisikan makro.
+parser_c_macro_set_to=03103_CL_Makro $1 disetel ke $2
+% Ketika \var{-vc} dipakai, kompilator memberitahu anda nilai apa yang didapat makro.
+parser_i_compiling=03104_I_Mengompilasi $1
+% Ketika anda menghidupkan pesan informasi (\var{-vi}), kompilator memebritahu
+% anda unit apa yang sedang dikompilasi.
+parser_u_parsing_interface=03105_UL_Menguraikan interface dari unit $1
+% Ini memberitahu anda bahwa pembacaan interface dari unit saat ini
+% dimulai
+parser_u_parsing_implementation=03106_UL_Menguraikan implementation dari $1
+% Ini memberitahu anda bahwa pembacaan implementation dari unit saat ini,
+% librari atau program dimulai
+parser_d_compiling_second_time=03107_DL_Mengompilasi $1 untuk kedua kalinya
+% Ketika anda meminta pesan debug (\var{-vd}) kompilator memberitahu anda unit
+% apa yang dikompilasi untuk kedua kalinya.
+parser_e_no_property_found_to_override=03109_E_Tidak ada properti yang ditemukan untuk diganti
+% Anda ingin mengganti sebuah properti dari kelas leluhur, saat ia ada,
+% kenyataannya, tidak ada properti seperti itu dalam kelas leluhur.
+parser_e_only_one_default_property=03110_E_Hanya sati properti default yang dibolehkan
+% Anda menetapkan properti sebagai \var{Default}, tapi kelas sudah mempunyai
+% properti default, dan kelas hanya dapat memiliki satu properti default.
+parser_e_property_need_paras=03111_E_Properti default harus berupa properti array
+% Hanya properti array dari kelas dapat dibuat menjadi properti \var{default}.
+parser_e_constructor_cannot_be_not_virtual=03112_E_Konstruktor virtual hanya didukung dalam model obyek kelas
+% Anda tidak bisa memiliki konstruktor virtual dalam obyek. Anda hanya memilikinya
+% dalam kelas.
+parser_e_no_default_property_available=03113_E_Tidak ada properti default yang tersedia
+% Anda mencoba mengakses properti default pada sebuah kelas, tapi kelas ini
+% atau salah satu leluhurnya) tidak mempunyai properti default.
+parser_e_cant_have_published=03114_E_Kelas tidak mempunyai seksi published, pakai saklar {$M+}
+% Jika anda ingin seksi \var{published} dalam sebuah definisi class, anda harus
+% menggunakan saklar \var{\{\$M+\}}, yang menghidupkan pembuatan informasi
+% type.
+parser_e_forward_declaration_must_be_resolved=03115_E_Deklarasi forward dari kelas "$1" harus dipecahkan di sini untuk menggunakan kelas sebagai leluhur
+% Agar bisa menggunakan obyek sebagai obyek leluhur, ia harus didefinisikan
+% lebih dahulu. Kesalahan ini terjadi dalam situasi berikut:
+% \begin{verbatim}
+% Type ParentClas = Class;
+% ChildClass = Class(ParentClass)
+% ...
+% end;
+% \end{verbatim}
+% Di mana \var{ParentClass} dideklarasikan tapi tidak didefinisikan.
+parser_e_no_local_operator=03116_E_Operator lokal tidak didukung
+% Anda tidak bisa meng-overload secara lokal, misalnya di dalam definisi
+% prosedur atau fungsi.
+parser_e_proc_dir_not_allowed_in_interface=03117_E_Direktif procedure "$1" tidak dibolehkan dalam seksi interface
+% Direktif prosedur ini tidak dibolehkan dalam seksi \var{interface} dari
+% sebuah unit. Anda hnya bisa menggunakannya dalam seksi \var{implementation}.
+parser_e_proc_dir_not_allowed_in_implementation=03118_E_Direktif procedure "$1" tidak dibolehkan dalam seksi implementation
+% Direktif prosedur ini tidak didefinisikan dalam seksi \var{implementation} pada
+% sebuah unit. Anda hanya bisa menggunakannya dalam seksi \var{interface}.
+parser_e_proc_dir_not_allowed_in_procvar=03119_E_Direktif prosedur "$1" tidak dibolehkan dalam deklarasi procvar
+% Direktif prosedur ini tidak bisa berupa bagian dari deklarasi tipe prosedural
+% atau fungsi.
+parser_e_function_already_declared_public_forward=03120_E_Fungsi sudah dideklarasikan Public/Forward "$1"
+% Anda akan mendapat kesalahan ini jika fungsi didefiniskan sebagai \var{forward} dua kali.
+% Atau sekali dalam seksi \var{interface}, dan sekali sebagai deklarasi
+% \var{forward} dalam seksi \var{implmentation}.
+parser_e_not_external_and_export=03121_E_Tidak bisa menggunakan EXPORT dan EXTERNAL
+% Dua prosedur ini adalah mutual eksklusif
+parser_w_not_supported_for_inline=03123_W_"$1" belum didukung di dalam inline procedure/function
+% Inline procedures tidak mendukung deklarasi ini.
+parser_w_inlining_disabled=03124_W_Inlining dimatikan
+% Inlining dari prosedur dimatikan.
+parser_i_writing_browser_log=03125_I_Menulis log Browser $1
+% Ketika pesan informasi hidup, kompilator memperingatkan anda saat ia
+% menulis log browser (dibuat dengan saklar \var{\{\$Y+ \}}).
+parser_h_maybe_deref_caret_missing=03126_H_mungkin dereferensi pointer hilang
+% Kompilator berpikir bahwa pointer mungkin memerlukan dereferensi.
+parser_f_assembler_reader_not_supported=03127_F_Pembaca assembler yang dipilih tidak didukung
+% Pembaca assembler yang dipilih (dengan \var{\{\$ASMMODE xxx\}} tidak
+% didukung. Kompilator dapat dikompilasi dengan atau tanpa dukungan pembaca
+% assembler tertentu.
+parser_e_proc_dir_conflict=03128_E_Direktif prosedur "$1" konflik dengan direktif lain
+% Anda menetapkan direktif prosedur yang konflik dengan direktif lainnya.
+% Sebagai contoh \var{cdecl} dan \var{pascal} adalah mutual eksklusif.
+parser_e_call_convention_dont_match_forward=03129_E_Konvensi pemanggilan forward tidak sama
+% Kesalahan ini terjadi ketika anda mendeklarasikan fungsi atau prosedur dengan
+% misalnya \var{cdecl;} tapi mengabaikan direktif ini dalam implementasi, atau
+% sebaliknya. Konvensi pemanggilan adalah bagian dari deklarasi fungsi, dan
+% harus diulang dalam definisi fungsi.
+parser_e_property_cant_have_a_default_value=03131_E_Properti tidak bisa memiliki nilai default
+% Set properti atau properti berindeks tidak bisa mempunyai nilai default.
+parser_e_property_default_value_must_const=03132_E_Nilai default pada properti harus konstan
+% Nilai dari properti yang dideklarasikan \var{default} harus dikenal waktu
+% dikompilasi. nilai yang anda tetapkan hanya dikenal saat run time. Ini terjadi
+% misalnya jika anda menetapkan sebuah nama variabel sebagai nilai default.
+parser_e_cant_publish_that=03133_E_Simbol tidak bisa dipublikasi, hanya bisa sebuah kelas
+% Hanya variabel tipe kelas yang bisa berada dalam seksi \var{published} pada
+% sebuah kelas jika ia tidak dideklarasikan sebagai sebuah properti.
+parser_e_cant_publish_that_property=03134_E_Jenis properti ini tidak bisa dipublikasi
+% Properti dalam seksi \var{published} tidak bisa berupa properti array.
+% ia harus dipindahkan ke seksi public. Properti dalam seksi \var{published}
+% harus berupa tipe ordinal, tipe real, string atau set.
+parser_e_empty_import_name=03136_E_Nama import diperlukan
+% Beberapa target memerlukan nama untuk prosedur yang diimpor atau pembeda \var{cdecl}
+parser_e_division_by_zero=03138_E_Pembagian dengan nol
+% Ada pembagian dengan nol yang ditemukan
+parser_e_invalid_float_operation=03139_E_Operasi floating point tidak benar
+% Operasi pada dua nilai tipe real menhasilkan overflow atau pembagian dengan
+% nol.
+parser_e_array_lower_less_than_upper_bound=03140_E_Batas atas jangkauan kurang dari batas lebih rendah
+% Batas lebih atas pada deklarasi array kurang dari batas lebih rendah dan ini
+% mungkin
+parser_w_string_too_long=03141_W_string "$1" lebih panjang dari "$2"
+% Ukuran konstan string lebih besar dari ukuran yang anda tetapkan dalam
+% definisi tipe string
+parser_e_string_larger_array=03142_E_panjang string lebih besar dari panjang array of char
+% Ukuran konstan string lebih besar dari ukuran yang anda tetapkan dalam
+% definisi array[x..y] of char
+parser_e_ill_msg_expr=03143_E_Ekspresi tidak benar setelah direktif pesan
+% \fpc hanya mendukung nilai integer atau string sebagai konstan pesan
+parser_e_ill_msg_param=03144_E_Pengendali pesan hanya dapat mengambil satu panggilan dengan parameter ref.
+% Metode yang dideklarasikan dengan direktif-\var{message} sebagai pengendali
+% pesan hanya mengambil satu parameter yang harus dideklarasikan sebagai
+% panggilan dengan referensi. Parameter dideklarasikan sebagai panggilan dengan
+% referensi menggunakan direktif-\var{var}
+parser_e_duplicate_message_label=03145_E_Duplikasi label pesan: "$1"
+% Label untuk sebuah pesan dipakai dua kali dalam satu object/class
+parser_e_self_in_non_message_handler=03146_E_Self hanya bisa berupa parameter eksplisit dalam metode yang merupakan pengendali pesan
+% Parameter self hanya dapat dioper secara eksplisit ke metode yang
+% dideklarasikan sebagai pengendali pesan.
+parser_e_threadvars_only_sg=03147_E_Threadvars hanya bisa berupa static atau global
+% Threadvars harus berupa static atau global, anda tidak bisa mendeklarasikan
+% lokal thread ke prosedur. Variabel lokal selalu lokal bagi thread, karena
+% setiap thread memiliki stack-nya sendiri dan variabel lokal disimpan pada
+% stack
+parser_f_direct_assembler_not_allowed=03148_F_Assembler langsung tidak didukung untuk format output biner
+% Anda tidak dapat menggunakan assembler langsung saat menggunakan penulis biner,
+% pilih format output lain atau gunakan pembaca assembler lain
+parser_w_no_objpas_use_mode=03149_W_Jangan ambil unit OBJPAS secara manual, sebaliknya gunakan \{\$mode objfpc\} atau \{\$mode delphi\}
+% Anda mencoba untuk mengambil unit ObjPas secara manual dari kausul uses. Ini
+% bukan ide yang baik. Gunakan direktif \var{\{\$mode objfpc\}} atau
+% \var{\{\$mode delphi\}}
+% yang mengambil unit secara otomatis
+parser_e_no_object_override=03150_E_OVERRIDE tidak bisa dipakai dalam obyek
+% Override tidak didukung untuk obyek, sebaliknya gunakan \var{virtual} untuk
+% mengganti metode obyek leluhur
+parser_e_cant_use_inittable_here=03151_E_Tipe data yang memerlukan initialization/finalization tidak bisa dipakai dalam variant record
+% Beberapa tipe data (misalnya \var{ansistring}) memerlukan kode initialization/finalization
+% yang secara implisit dibuat oleh kompilator. Tipe data sepert itu tidak
+% bisa dipakai dalam bagian varian pada sebuah record.
+parser_e_resourcestring_only_sg=03152_E_Resourcestring hanya berupa static atau global
+% Resourcestring tidak bisa dideklarasikan lokal, hanya global atau menggunakan
+% direktif static.
+parser_e_exit_with_argument_not__possible=03153_E_Exit dengan argumen tidak bisa dipakai di sini
+% Pernyataan exit dengan sebuah argumen untuk nilai balik tidak bisa dipakai
+% di sini, ini terjadi misalnya dalam blok \var{try..except} atau \var{try..finally}
+parser_e_stored_property_must_be_boolean=03154_E_Tipe penyimpanan simbol harus boolean
+% Jika anda menetapkan penyimpanan simbol dalam deklarasi properti, ia harus
+% berupa tipe boolean
+parser_e_ill_property_storage_sym=03155_E_Simbol ini tidak diijinkan sebagai penyimpanan simbol
+% Anda tidak bisa menggunakan tipe ini pada simbol sebagai pembeda penyimpanan
+% dalam deklarasi properti. Anda hanya bia menggunakan metode dengan tipe hasil
+% boolean, field kelas boolean atau konstan boolean
+parser_e_only_publishable_classes_can_be_published=03156_E_Hanya kelas yang dikompilasi dalam mode $M+ yang bisa dipublikasikan
+% Dalam seksi published dari kelas hanya bisa berupa kelas sebagai field yang dipakai
+% dikompilasi dalam \var{\{\$M+\}} atau yang diturunkan dari kelas seperti itu.
+% Normalnya kelas demikian harus dideklarasikan dari TPersitent
+parser_e_proc_directive_expected=03157_E_Direktif prosedur diharapkan
+% Kesalahan ini dipicu ketika anda mempunyai direktif \var{\{\$Calling\}} tanpa
+% konvensi pemanggilan yang ditetapkan.
+% Ia juga terjadi saat mendeklarasikan prosedur dalam blok const dan anda
+% menggunakan sebuah ; setelah deklarasi procedure yang harus diikuti oleh
+% sebuah direktif procedure.
+% Deklarasi yang benar adalah:
+% \begin{verbatim}
+% const
+% p : procedure;stdcall=nil;
+% p : procedure stdcall=nil;
+% \end{verbatim}
+parser_e_invalid_property_index_value=03158_E_Nilai indeks properti harus tipe ordinal
+% Nilai yang anda pakai untuk mengindeks properti harus berupa tipe ordinal,
+% sebagai contoh tipe integer atau dienumerasi.
+parser_e_procname_to_short_for_export=03159_E_Nama prosedur terlalu pendek untuk diekspor
+% Panjang nama procedure/function harus setidaknya 2 karakter. Ini dikarenakan
+% bug dalam dlltool yang tidak menguraikan file .def dengan benar
+% dengan panjang nama 1.
+parser_e_dlltool_unit_var_problem=03160_E_Tidak ada entri DEFFILE dapat dibuat untuk unit global vars
+parser_e_dlltool_unit_var_problem2=03161_E_Kompilasi tanpa opsi -WD
+% Anda perlu mengompilasi file ini tanpa saklar -WD pada baris
+% perintah
+parser_f_need_objfpc_or_delphi_mode=03162_F_Anda perlu ObjFpc (-S2) atau mode Delphi (-Sd) untuk mengompilasi modul ini
+% Anda perlu menggunakan \{\$mode objfpc\} atau \{\$mode delphi\} untuk
+% mengompilasi file ini. Atau gunakan saklar commandline yang sama -S2 atau -Sd.
+parser_e_no_export_with_index_for_target=03163_E_Tidak bisa mengekspor dengan indeks di bawah $1
+% Mengekspor fungsi atau prosedur dengan indeks yang ditetapkan tidak didukung
+% pada target ini.
+parser_e_no_export_of_variables_for_target=03164_E_Mengekspor variabel tidak didukung di bawah $1
+% Mengekspor variabel tidak didukung pada target ini.
+parser_e_improper_guid_syntax=03165_E_Sintaks GUID tidak benar
+% Indikasi GUID tidak memiliki sintaks yang benar. Ia seharusnya dalam bentuk
+% \begin{verbatim}
+% {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}
+% \end{verbatim}
+% Di mana setiap \var{X} mewakili digit heksadesimal.
+parser_w_interface_mapping_notfound=03168_W_Prosedur bernama "$1" tidak meemukan yang sesuai untuk mengimplementasikan $2.$3
+% Kompilator tidak bisa menemukan prosedur yang cocok yang mengimplementasikan metode
+% yang diberikan pada interface. Prosedur dengan nama sama ditemukan, tapi argumen tidak sama.
+parser_e_interface_id_expected=03169_E_pengenal interface diharapkan
+% Ini terjadi ketika kompilator memindai deklarasi \var{class} yang berisi
+% \var{interface} nama fungsi memetakan kode seperti ini:
+% \begin{verbatim}
+% type
+% TMyObject = class(TObject, IDispatch)
+% function IUnknown.QueryInterface=MyQueryInterface;
+% ....
+% \end{verbatim}
+% dan \var{interface} sebelum titik tidak didaftarkan dalam daftar turunan.
+parser_e_type_cant_be_used_in_array_index=03170_E_Tipe "$1" tidak bisa dipakai sebagai tipe indeks array
+% Tipe seperti \var{qword} atau \var{int64} tidak dibolehkan sebagai tipe indeks array
+parser_e_no_con_des_in_interfaces=03171_E_Con- dan destruktor tidak dibolehkan dalam interface
+% Deklarasi konstruktor dan destruktor tidak dibolehkan dalam interface
+% Dalam banyak kasus metode \var{QueryInterface} pada \var{IUnknown} dapat
+% dipakai untuk membuat interface baru.
+parser_e_no_access_specifier_in_interfaces=03172_E_Pembeda akses tidak bisa dipakai dalam INTERFACE
+% Pembeda akses \var{public}, \var{private}, \var{protected} dan
+% \var{pusblished} tidak bisa dipakai dalam interfaces karena semua metode
+% pada interfaces harus public.
+parser_e_no_vars_in_interfaces=03173_E_Interface tidak bisa berisi field
+% Deklarasi field tidak dibolehkan dalam interface. Interface hanya dapat
+% berisi metode
+parser_e_no_local_proc_external=03174_E_Tidak bisa mendeklarasikan prosedur lokal sebagai EXTERNAL
+% Mendeklarasikan prosedur lokal sebagai external tidak mungkin. Prosedur lokal
+% mendapat parameter tersembunyi yang akan menjadi peluang kesalahan sangat tinggi
+parser_w_skipped_fields_before=03175_W_Beberapa field datang sebelum "$1" diinisialisasi
+% Dalam mode Delphi, tidak semua field dari record tipe konstan harus
+% diinisialisasi, tapi kompilator memperingatkan anda saat ia mendeteksi situasi itu.
+parser_e_skipped_fields_before=03176_E_Beberapa field datang sebelum "$1" diinisialisasi
+% Dalam semua mode sintaks kecuali mode Delphi, anda tidak bisa meninggalkan
+% beberapa field tidak diinisialisasi di tengah konstan tipe record
+parser_w_skipped_fields_after=03177_W_Beberapa field datang setelah "$1" tidak diinisialisasi
+% Anda dapat meninggalkan beberapa fields di akhir konstan tipe record tidak
+% diinisialisasi (kompilator akan menginisialisasinya ke nol secara otomatis).
+% Ini dapat menjadi penyebab masalah yang kentara.
+parser_e_varargs_need_cdecl_and_external=03178_E_Direktif VarArgs (atau '...' dalam MacPas) tanpa CDecl/CPPDecl/MWPascal dan External
+% Direktif varargs (atau parameter varargs ``...'' dalam mode MacPas) hanya bisa
+% dipakai dengan prosedur atau fungsi yang dideklarasikan dengan \var{external} dan salah satu
+% dari \var{cdecl}, \var{cppdecl} dan \var{mwpascal}. Fungsionalitas ini hanya
+% didukung untuk menyediakan interface kompatibel terhadap fungsi C seperti printf.
+parser_e_self_call_by_value=03179_E_Self harus berupa parameter normal (dipanggil-dengan-nilai)
+% Anda tidak bisa mendeklarasikan self sebagai parameter const atau var, ia harus
+% selalu berupa parameter dipanggil-dengan-nilai
+parser_e_interface_has_no_guid=03180_E_Interface "$1" tidak mempunyai identifikasi interface
+% Ketika anda ingin menempatkan interface ke konstan, maka interface harus
+% sudah menyetel nilai GUID.
+parser_e_illegal_field_or_method=03181_E_Field class atau pengenal metode "$1" tidak dikenal
+% Properti harus merujuk ke sebuah field atau metode dalam kelas yang sama.
+parser_w_proc_overriding_calling=03182_W_Mengganti konvensi pemanggilan "$1" dengan "$2"
+% Ada dua direktif dalam deklarasi prosedur yang menetapkan konvensi
+% pemanggilan. Hanya direktif terakhir yang akan dipakai
+parser_e_no_procvarobj_const=03183_E_Tipe konstan dari tipe "procedure of object" hanya dapat diinisialisasi dengan NIL
+% Anda tidak bisa menempatkan alamat sebuah metode ke tipe konstan yang
+% memiliki tipe 'procedure of object', karena konstan memerlukan dua alamat:
+% yang metodenya (dikenal saat waktu kompilasi) dan yang obyeknya atau turunan
+% beroperasi pada kelasnya (yang tidak dapat dikenal saat waktu kompilasi).
+parser_e_default_value_only_one_para=03184_E_Nilai default hanya bisa ditempatkan ke satu parameter
+% Tidak mungkin untuk menetapkan nilai default untuk beberapa parameters sekaligus.
+% Yang berikut adalah tidak benar:
+% \begin{verbatim}
+% Procedure MyProcedure (A,B : Integer = 0);
+% \end{verbatim}
+% Lebih baik, deklarasikan sebagai
+% \begin{verbatim}
+% Procedure MyProcedure (A : Integer = 0; B : Integer = 0);
+% \end{verbatim}
+parser_e_default_value_expected_for_para=03185_E_Parameter default diperlukan untuk "$1"
+% Parameter yang ditetapkan memerlukan nilai default.
+parser_w_unsupported_feature=03186_W_Penggunaan fitur yang tidak didukung!
+% Anda mencoba untuk memaksa kompilator melakukan yang belum bisa dilakukannya.
+parser_h_c_arrays_are_references=03187_H_Array C dikirimkan dengan referensi
+% Setiap array yang dikirimkan ke fungsi C dioper dengan pointer
+% (misalnya dengan referensi).
+parser_e_C_array_of_const_must_be_last=03188_E_Array of const pada C harus argumen terakhir
+% Anda tidak bisa menambah argumen lain setelah \var{array of const} untuk
+% fungsi \var{cdecl}, karena ukuran yang disimpan pada stack untuk argumen ini
+% tidak diketahui.
+parser_h_type_redef=03189_H_Redefinisi tipe "$1"
+% Ini adalah indikator yang sebelumnya tipe dideklarasikan sedang didefinisikan
+% ulang sebagai yang lain. Ini bisa menjadi atau tidak penyebab dari
+% kesalahan.
+parser_w_cdecl_has_no_high=03190_W_fungsi cdecl yang dideklarasikan tidak memiliki parameter tinggi
+% Fungsi yang dideklarasikan dengan pengubah cdecl tidak mengirimkan parameter ekstra implisit.
+parser_w_cdecl_no_openstring=03191_W_fungsi cdecl yang dideklarasikan tidak mendukung string terbuka
+% Openstring tidak didukung untuk fungsi yang dideklarasikan cdecl.
+parser_e_initialized_not_for_threadvar=03192_E_Tidak bisa menginisialisasi variabel yang dideklarasikan sebagai threadvar
+% Variabel yang dideklarasikan sebagai threadvar tidak bisa diinisialisasi dengan
+% nilai default. Variabel akan selalu diisi dengan nol di awal thread baru.
+parser_e_msg_only_for_classes=03193_E_Direktif message hanya dibolehkan dalam Kelas
+% Direktif pesan hanya didukung untuk tipe Class.
+parser_e_procedure_or_function_expected=03194_E_Procedure atau Function diharapkan
+% Metode kelas hanya bisa ditetapkan untuk prosedur dan fungsi.
+parser_e_illegal_calling_convention=03195_W_Direktif konvensi pemanggilan diabaikan: "$1"
+% Beberapa konvensi pemanggilan hanya didukung oleh CPU tertentu. Misalnya dukungan banyak non-i386 port
+% hanya konvensi pemanggilan standar ABI pada CPU.
+parser_e_no_object_reintroduce=03196_E_REINTRODUCE tidak bisa dipakai dalam obyek
+% \var{reintroduce} tidak didukung untuk obyek.
+parser_e_paraloc_only_one_para=03197_E_Setiap argumen harus memiliki lokasi sendiri
+% Jika lokasi untuk argumen ditetapkan secara eksplisit karena ia diperlukan oleh
+% beberapa konvensi syscall, setiap argumen harus memiliki lokasinya sendiri, hal
+% seperti \var{procedure p(i,j : longint 'r1');} tidak diijinkan
+parser_e_paraloc_all_paras=03198_E_Setiap argumen harus memiliki lokasi eksplisit
+% Jika satu argumen mempunyai lokasi argumen eksplisit, semua argument pada
+% prosedur harus memilikinya.
+parser_e_illegal_explicit_paraloc=03199_E_Lokasi argumen tidak dikenal
+% Lokasi yang ditetapkan untuk argumen tidak dikenal oleh kompilator
+parser_e_32bitint_or_pointer_variable_expected=03200_E_32 Bit-Integer atau variabel pointer diharapkan
+% Libbase untuk MorphOS/AmigaOS hanya dapat diberikan sebagai \var{longint}, \var{dword} atau variabel pointer.
+parser_e_goto_outside_proc=03201_E_Pernyataan goto tidak dibolehkan diantara prosedure yang berbeda
+% Tidak diperkenankan menggunakan pernyataan \var{goto} mereferensi label di luar
+% prosedur saat ini. Contoh berikut menampilkan masalah ini:
+% \begin{verbatim}
+% ...
+% procedure p1;
+% label
+% l1;
+%
+% procedure p2;
+% begin
+% goto l1; // Goto ini TIDAK diijinkan
+% end;
+%
+% begin
+% p2
+% l1:
+% end;
+% ...
+%
+% \end{verbatim}
+parser_f_too_complex_proc=03202_F_Prosedur terlalu kompleks, memerlukan terlalu banyak register
+% Badan prosedur anda terlalu panjang bagi kompilator. Anda harus memisahkan
+% prosedur ke dalam multipel prosedure lebih kecil.
+parser_e_illegal_expression=03203_E_Ekspresi tidak benar
+% Ini dapat terjadi di bawah banyak keadaan. Terutama saat mencoba untuk
+% mengevaluasi ekspresi konstan.
+parser_e_invalid_integer=03204_E_Ekspresi integer tidak benar
+% Anda membuat ekspresi yang bukan integer, dan kompilator mengharapkan hasilnya
+% adalah integer.
+parser_e_invalid_qualifier=03205_E_Kualifier tidak benar
+% Salah satu dari yang berikut terjadi :
+% \begin{itemize}
+% \item Anda mencoba untuk mengakses field variabel yang bukan sebuah record.
+% \item Anda mengindeks variabel yang bukan sebuah array.
+% \item Anda medereferensi variabel yang bukan sebuah pointer.
+% \end{itemize}
+parser_e_upper_lower_than_lower=03206_E_Batas tinggi jakauan < batas rendah jangkauan
+% You are declaring a subrange, and the lower limit is higher than the high
+% limit of the range.
+parser_e_macpas_exit_wrong_param=03207_E_Parameter Exit harus berupa nama prosedur yang dipakai
+% Exit non lokal tidak dibolehkan. Kesalahan ini hanya terjadi dalam mode MacPas.
+parser_e_illegal_assignment_to_count_var=03208_E_Penempatan ke variabel for-loop "$1" tidak benar
+% Tipe variabel \var{for} loop harus berupa tipe ordinal.
+% Variabel loop tidak bisa real atau string. Anda juga tidak bisa menempatkan
+% nilai ke variabel loop di dalam loop (kecuali dalam mode Delphi dan TP).
+% Sebaliknya gunakan while atau repeat loop jika anda perlu melakukan sesuatu
+% seperti itu, karena konstruksinya dibangun untuk itu.
+parser_e_no_local_var_external=03209_E_Tidak bisa mendeklarasikan variabel lokal sebagai EXTERNAL
+% Mendeklarasikan variabel lokal sebagai external tidak dibolehkan. Hanya
+% variabel global dapat mereferensi ke variabel external.
+parser_e_proc_already_external=03210_E_Procedure sudah dideklarasikan EXTERNAL
+% Prosedur sudah dideklarasikan dengan direktif EXTERNAL dalam interface atau
+% deklarasi forward.
+parser_w_implicit_uses_of_variants_unit=03211_W_Penggunaan implisit unit Variants
+% Tipe Variant dipakai dalam unit tanpa menggunakan unit Variants. Kompilator
+% telah menambahkan secara implisit unit Variants ke akhir daftar uses. Untuk
+% menghapus peringatan ini, unit Variants perlu ditambahkan ke pernyataan uses.
+parser_e_no_static_method_in_interfaces=03212_E_Kelas dan metode statis tidak bisa dipakai dalam INTERFACE
+% Pembeda \var{class} dan direktif \var{static} tidak bisa dipakai dalam interface
+% karena semua metode interface harus public.
+parser_e_arithmetic_operation_overflow=03213_E_Overflow dalam operasi aritmatika
+% Operasi pada dua nilai integer menghasilkan overflow
+parser_e_protected_or_private_expected=03214_E_Protected atau private diharapkan
+% \var{strict} hanya bisa dipakai bersama dengan \var{protected} atau \var{private}.
+parser_e_illegal_slice=03215_E_SLICE tidak bisa dipakai di luar daftar parameter
+% \var{slice} hanya bisa dipakai untuk argumen yang menerima parameter array terbuka
+parser_e_dispinterface_cant_have_parent=03216_E_DISPINTERFACE tidak bisa mempunyai kelas leluhur
+% DISPINMTERFACE adalah tipe khusus interface yang tidak memiliki kelas leluhur
+parser_e_dispinterface_needs_a_guid=03217_E_DISPINTERFACE memerlukan sebuah guid
+% DISPINMTERFACE selalu memerlukan identifikasi interface
+parser_w_overridden_methods_not_same_ret=03218_W_Metode yang diganti harus tipe balik terkait. Kode ini mungkin rusak, ia tergantung pada bug pengurai Delphi ("$2" diganti dengan "$1" yang mempunyai tipe balik lain)
+% Jika anda mendeklarasikan metode pengganti dalam definisi kelas, ia harus
+% mempunyai tipe balik yang sama. Beberapa versi Delphi membolehkan anda untuk
+% mengubah tipe balik pada metode interface, dan bahkan mengubah prosedur menjadi
+% fungsi, tapi kode hasil bisa rusak tergantung pada tipe yang dipakai dan
+% cara metode dipanggil.
+parser_e_dispid_must_be_ord_const=03219_E_Dispatch ID harus konstan ordinal
+parser_e_array_range_out_of_bounds=03220_E_Jangkauan array terlalu besar
+% Meskipun ukuran tergantung elemennya, array tidak bisa memiliki lebih dari
+% high(ptrint) elemen. Sebagai tambahan, tipe jangkauan harus sub jangkauan
+% dari ptrint.
+parser_e_packed_element_no_var_addr=03221_E_Alamat tidak bisa diambil dari elemen packed array dan field record
+% Jika anda mendeklarasikan array atau record sebagai \var{packed} dalam mode Mac Pascal
+% (atau sebagai \var{packed} dalam setiap mode dengan \var{\{\$bitpacking on\}}),
+% ia akan di-packed di tingkat bit. Ini berarti ia menjadi tidak mungkin untuk
+% mengambil alamat dari elemen individual array atau field record. Ini hanya
+% kekecualian pada aturan ini bila elemen packed array yang ukuran pemadatannya
+% adalah multpele dari 8 bit.
+parser_e_packed_dynamic_open_array=03222_E_Array dinamis tidak bisa dipadatkan
+% Hanya array reguler (dan mungkin ke depan juga yang terbuka) dapat dipadatkan
+parser_e_packed_element_no_loop=03223_E_Bit elemen packed array dan field record tidak bisa dipakai sebagai variabel loop
+% Jika anda mendeklarasikan array atau record sebagai \var{packed} dalam mode Mac Pascal (atau sebagai \var{packed} dalam setiap mode \var{\{\$bitpacking on\}}),
+% ia akan dipadatkan di tingkat bit. Untuk alasan performansi, ia tidak bisa
+% dipakai sebagai variabel loop.
+parser_e_type_and_var_only_in_generics=03224_E_VAR dan TYPE hanya dibolehkan dalam generik
+% Penggunaan VAR dan TYPE untuk mendeklarasikan tipe baru di dalam sebuah obyek
+% hanya dibolehkan di dalam generik.
+parser_e_cant_create_generics_of_this_type=03225_E_Tipe ini tidak bisa generik
+% Hanya Class, Object, Interface dan Record dibolehkan untuk dipakai sebagai generik
+parser_w_no_lineinfo_use_switch=03226_W_Jangan ambil unit LINEINFO secara manual, sebaliknya gunakan saklar kompilator -gl
+% Jangan menggunakan unit LINEINFO secara langsung, gunakan saklar \var{-gl}
+% yang secara otomatis menambahkan unit untuk membaca tipe informasi debug.
+parser_e_no_funcret_specified=03227_E_Tidak ada tipe hasil fungsi yang ditetapkan untuk "$1"
+% Pertama kali anda mendeklarasikan fungsi anda harus mendeklarasikannya dengan lengkap,
+% termasuk seluruh parameter dan tipe hasil.
+parser_e_special_onlygenerics=03228_E_Specialization hanya didukung untuk tipe generik
+% Tipe yang bukan generik tidak bisa di spesialisasi
+parser_e_no_generics_as_params=03229_E_Generik tidak bisa dipakai sebagai parameter saat menspesialisasi generik
+% Ketika menspesialisasi generik, hanya tipe non-generik yang dapat dipakai sebagai parameter.
+parser_e_type_object_constants=03230_E_Konstan obyek yang berisi VMT tidak dibolehkan
+% Jika sebuah obyek memerlukan VMT baik karena ia berisi konstruktor ataupun metode virtual,
+% tidak diijinkan untuk membuat konstan darinya. Dalam mode TP dan Delphi ini
+% dibolehkan untuk alasan kompatibilitas.
+parser_e_label_outside_proc=03231_E_Mengambil alamat label yang didefinisikan di luar lingkup saat ini tidak dibolehkan
+% Tidak diperbolehkan untuk mengambil alamat label di luar prosedur
+% saat ini.
+parser_f_no_anonymous_specializations=03232_F_Spesialisasi generik anonim tidak diperbolehkan
+% Sesuatu seperti
+% \begin{verbatim}
+% var
+% MyLinkedList: specialize TLinkedList<TFixedString15>;
+% \end{verbatim}
+% tidak dibolehkan. Deklarasikan tipe spesialisasi lebih dulu:
+% \begin{verbatim}
+% type
+% TMyLinkedList = specialize TLinkedList<TFixedString15>;
+% var
+% MyLinkedList: TMyLinkedList
+% \end{verbatim}
+parser_e_initialized_not_for_external=03233_E_Tidak bisa menginisialisasi variabel yang dideklarasikan sebagai external
+% Variabel yang dideklarasikan sebagai external tidak bisa diinisialisasi dengan nilai default.
+parser_e_illegal_function_result=03234_E_Tipe hasil fungsi tidak benar
+% Beberapa tipe seperti tipe file tidak bisa dipakai sebagai hasil fungsi.
+parser_e_no_common_type=03235_E_Tidak ada tipe umum yang mungkin antara "$1" dan "$2"
+% Untuk melakukan operasi diantara integer, kompilator mengubah kedua operand
+% ke tipe umum, yang terlihat tipe tidak benar. Untuk menentukan tipe umum
+% dari operand, kompilator mengambil minimum dari nilai minimal kedua tipe,
+% dan maksimum dari maksimal nilai kedua tipe. Tipe umum adalah
+% minimum..maksimum.
+parser_e_no_generics_as_types=03236_E_Generik tanpa spesialisasi tidak bisa dipakai sebagai tipe untuk variabel
+% Generik harus selalu dispesialisasi sebelum dipakai sebagai tipe variabel
+% \end{description}
+#
+# Pemeriksaan Tipe
+#
+# 04082 is the last used one
+#
+% \section{Kesalahan pemeriksaan tipe}
+% Seksi ini mendaftarkan semua kesalahan yang terjadi saat pemeriksaan tipe
+% dilakukan.
+% \begin{description}
+type_e_mismatch=04000_E_Tipe tidak sama
+% Ini terjadi dalam banyak kasus:
+% \begin{itemize}
+% \item Variabel yang anda tempatkan adalah tipe berbeda dari ekspresi dalam
+% penempatan.
+% \item Anda memanggil fungsi atau prosedur dengan parameters yang tidak
+% kompatibel dengan parameter dalam definisi fungsi atau prosedur.
+% \end{itemize}
+type_e_incompatible_types=04001_E_Tipe tidak kompatibel: didapat "$1" diharapkan "$2"
+% Tidak ada konversi yang mungkin diantara kedua tipe
+% Kemungkinan lain adalah bahwa keduanya dideklarasikan dalam deklarasi yang
+% berbeda:
+% \begin{verbatim}
+% Var
+% A1 : Array[1..10] Of Integer;
+% A2 : Array[1..10] Of Integer;
+%
+% Begin
+% A1:=A2; { Pernyataan ini juga menghasilkan kesalahan, ini
+% dikarenakan pemeriksaan tipe ketat pada pascal }
+% End.
+% \end{verbatim}
+type_e_not_equal_types=04002_E_Tipe tidak sama antara "$1" dan "$2"
+% Tipe tidak persis sama
+type_e_type_id_expected=04003_E_Pengenal tipe diharapkan
+% Pengenal bukan sebuah tipe, atau anda lupa menyertakan pengenal tipe.
+type_e_variable_id_expected=04004_E_Pengenal variabel diharapkan
+% Ini terjadi saat anda mengirimkan konstan ke sebuah rutin (seperti \var{Inc} var atau \var{Dec})
+% ketia ia mengharapkan sebuah variabel. Anda juga bisa mengirimkan variabel
+% sebagai argumen ke fungsi ini.
+type_e_integer_expr_expected=04005_E_Ekspresi integer diharapkan, tapi didapat "$1"
+% Kompilator mengharapkan ekspresi tipe integer, tetapi mendapatkan tipe yang
+% berbeda.
+type_e_boolean_expr_expected=04006_E_Ekspresi boolean diharapkan, tapi didapat "$1"
+% Ekspresi harus tipe boolean, ia harus mengembalikan true atau false.
+type_e_ordinal_expr_expected=04007_E_Ekspresi Ordinal diharapkan
+% Ekspresi harus tipe ordinal, misalnya maksimum \var{Longint}.
+% Ini terjadi, misalnya ketika anda menetapkan argumen kedua
+% ke \var{Inc} atau \var{Dec} yang tidak mengevaluasi ke nilai ordinal.
+type_e_pointer_type_expected=04008_E_Tipe pointer diharapkan, tapi didapat "$1"
+% Ekspresi variabel bukan tipe \var{pointer}. Ini terjadi ketika anda
+% mengirimkan variabel yang bukan pointer ke \var{New} atau \var{Dispose}.
+type_e_class_type_expected=04009_E_Tipe class diharapkan, tapi didapat "$1"
+% Ekspresi variabel bukan tipe \var{class}. Ini terjadi biasanya ketika
+% \begin{enumerate}
+% \item Kelas leluhur dalam deklarasi kelas bukan sebuah class.
+% \item Pengendali eksepsi (\var{On}) berisi pengenal tipe yang bukan sebuah
+% class.
+% \end{enumerate}
+type_e_cant_eval_constant_expr=04011_E_Tidak bisa mengevaluasi ekspresi konstan
+% Kesalahan ini bisa terjadi ketika batas array yang anda deklarasikan tidak
+% mengevaluasi konstan ordinal
+type_e_set_element_are_not_comp=04012_E_Set elemen tidak kompatibel
+% Anda mencoba untuk membuat operasi pada dua set, ketika set tipe elemen
+% tidak sama. Tipe basis dari sebuah set harus sama saat mengambil union
+type_e_set_operation_unknown=04013_E_Operasi tidak diimplementasikan untuk set
+% Beberapa operasi biner tidak mendefinisikan untuk set seperti
+% div mod ** (juga >= <= untuk saat ini)
+type_w_convert_real_2_comp=04014_W_Konversi tipe otomatis dari tipe floating ke COMP yang adalah tipe integer
+% Konversi tipe implisit dari tipe real ke \var{comp} ditemukan. Karena
+% \var{comp} adalah tipe integer 64 bit, ini bisa menandakan kesalahan.
+type_h_use_div_for_int=04015_H_Sebaiknya gunakan DIV untuk mendapatkan hasil integer
+% Ketika petunjuk dihidupkan, maka pembagian integer dengan operator '/' akan
+% memunculkan pesan ini, karena hasil kemudian akan berupa tipe real
+type_e_strict_var_string_violation=04016_E_Tipe string tidak sama, karena mode $V+
+% Ketika mengompilasi dalam mode \var{\{\$V+\}}, string yang anda kirimkan sebagai parameter
+% harus tipe yang sama persis seperti parameter yang dideklarasikan pada procedure.
+type_e_succ_and_pred_enums_with_assign_not_possible=04017_E_succ atau pred pada enums dengan penempatan tidak mungkin
+% Ketika anda mendeklarasikan tipe enumerasi yang mempunyai penempatan di dalamnya, seperti pada C,
+% seperti yang berikut:
+% \begin{verbatim}
+% Tenum = (a,b,e:=5);
+% \end{verbatim}
+% anda tidak bisas menggunakan fungsi \var{Succ} atau \var{Pred} padanya.
+type_e_cant_read_write_type=04018_E_Tidak bisa membaca atau menulis variabel dari tipe ini
+% Anda mencoba untuk \var{read} atau \var{write} variabel dari atau ke sebuah
+% file tipe teks, yang tidak mendukung itu. Hanya tipe integer, real, pchar,
+% dan string dapat dibaca dari/ditulis ke file teks. Boolean hanya dapat
+% ditulis ke file teks.
+type_e_no_readln_writeln_for_typed_file=04019_E_Tidak bisa menggunakan readln atau writeln pada file
+% \var{readln} dan \var{writeln} hanya dibolehkan untuk file teks.
+type_e_no_read_write_for_untyped_file=04020_E_Tidak bisa memakai baca atau tulis pada file untyped.
+% \var{read} dan \var{write} hanya dibolehkan untuk file teks atau biner.
+type_e_typeconflict_in_set=04021_E_Tipe konflik diantara set elemen
+% Ada setidaknya satu set elemen yang tipenya salah, misalnya bukan dari
+% tipe set.
+type_w_maybe_wrong_hi_lo=04022_W_lo/hi(dword/qword) mengembalikan upper/lower word/dword
+% \fpc mendukung versi di-overload atas \var{lo/hi} untuk \var{longint/dword/int64/qword}
+% yang mengembalikan lower/upper word/dword pada argumen. TP selalu menggunakan
+% 16 bit \var{lo/hi} yang selalu mengembalikan bit 0..7 untuk \var{lo} dan
+% bit 8..15 untuk \var{hi}. Jika anda menginginkan perilaku TP anda harus
+% type cast argumennya ke \var{word/integer}
+type_e_integer_or_real_expr_expected=04023_E_Ekspresi integer atau real diharapkan
+% Argumen pertama pada \var{str} harus tipe real atau integer.
+type_e_wrong_type_in_array_constructor=04024_E_Tipe "$1" salah dalam konstruktor array
+% Anda mencoba untuk menggunakan tipe dalam konstruktor array yang tidak
+% dibolehkan.
+type_e_wrong_parameter_type=04025_E_Tipe tidak kompatibel untuk arg no. $1: Didapat "$2", diharapkan "$3"
+% Anda mencoba untuk mengirimkan tipe yang salah untuk parameter yang ditetapkan.
+type_e_no_method_and_procedure_not_compatible=04026_E_Metode (variabel) dan Prosedur (variabel) tidak kompatibel
+% Anda tidak bisa menempatkan sebuah metode ke variabel prosedur atau prosedur
+% ke sebuah pointer metode.
+type_e_wrong_math_argument=04027_E_Konstan yang dikirimkan ke fungsi math internal tidak benar
+% Argumen konstan yang dikirimkan ke fungsi ln atau sqrt di luar jangkauan
+% definisi pada fungsi ini.
+type_e_no_addr_of_constant=04028_E_Tidak bisas mengambil alamat dari ekspresi konstan
+% Tidak mungkin untuk mendapatkan alamat ekspresi konstan, karena tidak disimpan
+% dalam memori. Anda dapat mencoba membuat tipe konstan. Kesalahan ini juga bisa
+% ditampilkan jika anda mencoba mengirimkan properti ke parameter var.
+type_e_argument_cant_be_assigned=04029_E_Argumen tidak bisa ditempatkan
+% Hanya ekspresi yang bisa di sisi kiri dari penempatan yang bisa dikirimkan
+% sebagai panggilan dengan referensi argumen.
+% Catatan: Properti hanya bisa dipakai pada sisi kiri dari penempatan,
+% tapi ia tidak bisas digunakan sebagai argumen
+type_e_cannot_local_proc_to_procvar=04030_E_Tidak bisa menempatkan prosedur/fungsi lokal ke variabel prosedur
+% Tidak dibolehkan untuk menempatkan prosedur/fungsi lokal ke sebuah variabel
+% prosedur, karena pemanggilan prosedur/fungsi lokal berbeda. Anda hanya bisa
+% menempatkan prosedur/fungsi lokal ke sebuah pointer.
+type_e_no_assign_to_addr=04031_E_Tidak bisa menempatkan nilai ke alamat
+% Tidak dibolehkan untuk menempatkan nilai ke alamat dari variabel, konstan,
+% prosedur atau fungsi. Anda dapat mencoba mengompilasi dengan -So jika pengenal
+% adalah variabel procedure.
+type_e_no_assign_to_const=04032_E_Tidak bisa menempatkan nilai ke variabel const
+% Tidak dibolehkan untuk menempatkan nilai ke variabel yang dideklarasikan
+% sebagai const. Ini biasanya parameter dideklarasikan sebagai const, untuk
+% membolehkan perubahan nilai buat parameter sebagai parameter nilai atau var.
+type_e_array_required=04033_E_Tipe array diperlukan
+% Jika anda mengakses variabel menggunakan sebuah indeks '[<x>]' maka tipenya
+% harus array. Dalam mode FPC, pointer juga dibolehkan.
+type_e_interface_type_expected=04034_E_tipe interface diharapkan, tapi didapat "$1"
+% Kompilator berharap menemukan nama tipe interface, tapi didapatkan yang lain.
+% Kode berikut akan menimbulkan kesalahan ini:
+% \begin{verbatim}
+% Type
+% TMyStream = Class(TStream,Integer)
+% \end{verbatim}
+type_w_mixed_signed_unsigned=04035_W_Mencampur ekspresi bertanda dan longword memberikan hasil 64bit
+% Jika anda membagi (atau menghitung modulus dari) ekspresi bertanda dengan
+% longword (atau sebaliknya), atau jika anda memiliki overflow dan/atau
+% menghidupkan pemeriksaan jangkauan dan menggunakan ekspresi aritmatika
+% (+, -, *, div, mod) dalam kedua angka bertanda dan longwords muncul,
+% maka kesemuanya harus dievaluasi dalam 64bit yang lebih lambat daripada
+% aritmatika 32bit normal. Anda bisa menghindari ini dengan typecasting satu
+% operand agar ia sesuai tipe hasil atas yang lainnya.
+type_w_mixed_signed_unsigned2=04036_W_Mencampur ekspresi bertanda dan cardinal di sini dapat menyebabkan kesalahan pemeriksaan jangkauan
+% Jika anda menggunakan operator biner (and, or, xor) dan salah satu operand
+% adalah longword sementara yang lainnya ekspresi bertanda, maka jika
+% pemeriksaan jangkauan dihidupkan, anda akan mendapatkan kesalahan pemeriksaan
+% jangkauan, karena kedua operand dikonversi ke longword sebelum operasi
+% dilakukan. Anda dapat menghindari ini dengan typecasting satu operand agar
+% sesuai dengan tipe hasil atas yang lain.
+type_e_typecast_wrong_size_for_assignment=04037_E_Typecast mempunyai ukuran berbeda ($1 -> $2) dalam penempatan
+% Type casting ke sebuah tipe dengan ukuran berbeda tidak dibolehkan saat
+% variabel dipakai untuk penempatan.
+type_e_array_index_enums_with_assign_not_possible=04038_E_enum dengan penempatan tidak bisa dipakai sebagai indeks array
+% Ketika anda mendeklarasikan tipe enumerasi yang memiliki penempatan
+% didalamnya, seperti dalam C, sepeprti berikut:
+% \begin{verbatim}
+% Tenum = (a,b,e:=5);
+% \end{verbatim}
+% anda tidak bisa menggunakannya sebagai indeks dari sebuah array.
+type_e_classes_not_related=04039_E_Tipe Class atau Object "$1" dan "$2" tidak berkaitan
+% Ada typecast dari satu kelas atau obyek ke yang lain sementara kelas/obyek itu
+% tidak ada kaitannya. Ini akan menimbulkan kesalahan
+type_w_classes_not_related=04040_W_Tipe kelas "$1" dan "$2" tidak berkaitan
+% Ada typecast dari satu kelas atau obyek ke yang lain sementara kelas/obyek itu
+% tidak ada kaitannya. Ini akan menimbulkan kesalahan
+type_e_class_or_interface_type_expected=04041_E_Tipe Class atau interface diharapkan, tapi didapat "$1"
+% Kompilator mengharapkan nama kelas atau interface, tapi mendapatkan tipe atau pengenal lain.
+type_e_type_is_not_completly_defined=04042_E_Tipe "$1" tidak sepenuhnya didefinisikan
+% Kesalahan ini terjadi saat tipe tidak lengkap: misalnya tipe pointer yang
+% mengarah ke tipe tidak terdefinisi.
+type_w_string_too_long=04043_W_Literal string memiliki lebih banyak karakter daripada panjang short string
+% Ukuran string konstan, yang ditempatkan ke shortstring, lebih panjang daripada
+% ukuran maksimum shortstring
+type_w_signed_unsigned_always_false=04044_W_Perbandingan selalu salah karena jangkauan nilai
+% Ada perbandingan antara nilai unsigned dan konstan bertanda yang kurang dari
+% nol. Karena promosi tipe, pernyataan akan selalu dievaluasi menjadi false.
+% Typecast secara eksplisit konstan ke jangkauan yang benar guna menghindari masalah ini.
+type_w_signed_unsigned_always_true=04045_W_Perbandingan selalu true karena jangkauan nilai
+% Ada perbandingan antara nilai unsigned dan konstan bertanda yang kurang dari
+% nol. Karena promosi tipe, pernyataan akan selalu dievaluasi menjadi true.
+% Typecast secara eksplisit konstan ke jangkauan yang benar guna menghindari masalah ini.
+type_w_instance_with_abstract=04046_W_Membentuk sebuah kelas "$1" dengan metode abstrak
+% Turunan kelas dibuat yang berisi metode abstrak tidak diimplementasikan. Ini
+% dapat membawa kesalahan runtime 211 dalam kode jika rutin itu tidak pernah
+% dibersihkan. Semua metode abstrak harus diganti.
+type_h_in_range_check=04047_H_Operand kiri pada operator IN harus berukuran byte
+% Operand kiri pada operator \var{in} bukan ordinal atau enumerasi yang sesuai
+% dalam 8-bits, ini dapat mengakibatkan kesalahan pemeriksaan jangkauan.
+% Operator \var{in} saat ini hanya mendukung operand kiri yang sesuai dalam byte.
+% Dalam hal enumerasi, ukuran elemen pada enumerasi dapat dikontrol dengan
+% saklar \var{\{\$PACKENUM\}} atau \var{\{\$Zn\}}.
+type_w_smaller_possible_range_check=04048_W_Ukuran tipe tidak sama, kemungkinan kehilangan data / kesalahan pemeriksaan jangkauan
+% Ada penempatan ke tipe lebih kecil daripada tipe sumber. Ini berarti bahwa
+% ini dapat menyebabkan kesalahan pemeriksaan jangkauan, atau dapat mengakibatkan kehilangan data.
+type_h_smaller_possible_range_check=04049_H_Ukuran tipe tidak sama, kemungkinan kehilangan data / kesalahan pemeriksaan jangkauan
+% Ada penempatan ke tipe lebih kecil daripada tipe sumber. Ini berarti bahwa
+% ini dapat menyebabkan kesalahan pemeriksaan jangkauan, atau dapat mengakibatkan kehilangan data.
+type_e_cant_take_address_of_abstract_method=04050_E_Alamat metode abstrak tidak bisa diambil
+% Metode abstrak tidak memiliki badan, maka alamat metode abstrak tidak bisa diambil.
+type_e_assignment_not_allowed=04051_E_Penempatan ke parameter formal dan array terbuka tidak mungkin
+% Anda mencoba untuk menempatkan nilai ke parameter formal (untyped var, const
+% atau out), atau ke array terbuka.
+type_e_constant_expr_expected=04052_E_Ekspresi Konstan diharapkan
+% Kompilator mengharapkan ekspresi konstan, tapi mendapatkan ekspresi variabel.
+type_e_operator_not_supported_for_types=04053_E_Operasi "$1" tidak didukung untuk tipe "$2" dan "$3"
+% Operasi tidak dibolehkan untuk tipe yang disediakan
+type_e_illegal_type_conversion=04054_E_Konversi tipe tidak benar: "$1" ke "$2"
+% Ketika melakukan type-cast, anda harus berhati-hati bahwa ukuran variabel dan tipe
+% tujuan adalah sama.
+type_h_pointer_to_longint_conv_not_portable=04055_H_Konversi antara ordinal dan pointer tidak portabel
+% Jika anda melakukan typecast pointer ke longint (atau sebaliknya), kode ini
+% tidak akan dikompilasi pada mesin menggunakan 64-bit untuk penyimpanan pointer.
+type_w_pointer_to_longint_conv_not_portable=04056_W_Konversi antara ordinal dan pointer tidak portabel
+% Jika anda melakukan typecast pointer ke tipe ordinal pada ukuran berbeda
+% (atau sebaliknya), ini dapat menyebabkan masalah. Ini adalah peringatan untuk
+% membantu menemukan kode spesifik 32bit di mana cardinal/longint dipakai
+% untuk typecast pointer ke ordinal. Solusinya sebaiknya menggunakan tipe ptrint/ptruint.
+type_e_cant_choose_overload_function=04057_E_Tidak dapat menentukan fungsi di-overload mana yang dipanggil
+% Anda memanggil fungsi di-overload dengan parameter yang tidak terkait ke daftar
+% parameter fungsi yang dideklarasikan di manapun. Misalnya saat anda
+% mendeklarasikan fungsi dengan parameter \var{word} dan \var{longint}, kemudian
+% anda memanggilnya dengan parameter yang tipenya \var{integer}.
+type_e_illegal_count_var=04058_E_Variabel penghitung tidak benar
+% Tipe variabel loop \var{for} harus tipe ordinal. Variabel loop tidak bisa
+% real atau string.
+type_w_double_c_varargs=04059_W_Mengkonversi konstan nilai real ke double untuk argumen variabel C, tambah typecast eksplisit untuk menghindarinya.
+% Dalam C, nilai konstan real adalah double standarnya. Untuk alasan ini, jika
+% anda mengirimkan nilai konstan real ke argumen variabel bagian dari fungsi C,
+% standarnya FPC mengkonversi konstan ini ke double juga. Jika anda ingin
+% menghindari ini terjadi, tambah typecast eksplisit disekitar konstan.
+type_e_class_or_cominterface_type_expected=04060_E_Tipe Class atau interface COM diharapkan, tapi didapat "$1"
+% Beberapa operator seperti operator AS hanya berlaku pada kelas atau interface COM.
+type_e_no_const_packed_array=04061_E_Konstan packed arrays belum didukung
+% Anda tidak bisa mendeklarasikan (bit)packed array sebagai konstan type.
+type_e_got_expected_packed_array=04062_E_Tipe tidak kompatibel untuk arg no. $1: Didapat "$2" diharapkan "(Bit)Packed Array"
+% Kompilator mengharapkan (bit)packed array sebagai parameter yang dietapkan
+type_e_got_expected_unpacked_array=04063_E_Tipe tidak kompatibel untuk arg no. $1: Didapat "$2" diharapkan "(Bit)Packed Array"
+% Kompilator mengharapkan reguler (misalnya bukan packed) array sebagai parameter yang ditetapkan
+type_e_no_packed_inittable=04064_E_Elemen pada packed arrays tidak bisa dari tipe yang perlu diinisialisasi
+% Dukungan untuk packed array daru tuoe yang memerlukan inisialisasi (seperti
+% ansistring, atau record yang berisi ansistring) belum diimplementasikan.
+type_e_no_const_packed_record=04065_E_Konstan packed record dan obyek belum didukung
+% Anda tidak bisa mendeklarasikan (bit)packed array sebagai typed konstan pada saat ini.
+type_w_untyped_arithmetic_unportable=04066_W_Aritmatika "$1" pada pointer untyped tidak portabel bagi {$T+}, disarankan typecast
+% Penambahan/pengurangan dari pointer untyped mungkin bekerja secara berbeda
+% dalam \var{\{\$T+\}}, gunakan typecast untuk pointer typed
+type_e_cant_take_address_of_local_subroutine=04076_E_Tidak bisa mengambil alamat dari subrutin yang ditandai sebagai lokal
+% Alamat subrutin yang ditandai sebagai lokal tidak bisa diambil.
+type_e_cant_export_local=04077_E_Tidak bisa mengekspor subrutin yang ditandai sebagai lokal dari sebuah unit
+% Subrutin yang ditandai sebagai lokal tidak bisa diekspor dari sebuah unit.
+type_e_not_automatable=04078_E_Tipe tidak bisa diotomasi: "$1"
+% Hanya byte, integer, longint, smallint, currency, single, double, ansistring,
+% widestring, tdatetime, variant, olevariant, wordbool dan semua interface bisa diotomasi.
+type_h_convert_add_operands_to_prevent_overflow=04079_H_Mengkonversi operand ke "$1" sebelum melakukan penambahan dapat menghindari kesalahan overflow.
+% Menambah dua tipe dapat menyebabkan kesalahan overflow. Karena anda
+% mengkonversi hasil ke tipe lebih besar, anda dapat menghindari kesalahan
+% seperti itu dengan mengubah operand ke tipe ini sebelum melakukan penambahan.
+type_h_convert_sub_operands_to_prevent_overflow=04080_H_Mengkonversi operand ke "$1" sebelum melakukan pengurangan dapat menghindari kesalahan overflow.
+% Pengurangan dua tipe dapat menyebabkan kesalahan overflow. Karena anda
+% mengkonversi hasil ke tipe lebih besar, anda menghindari
+% seperti itu dengan mengubah operand ke tipe ini sebelum melakukan pengurangan.
+type_h_convert_mul_operands_to_prevent_overflow=04081_H_Mengkonversi operand ke "$1" sebelum melakukan perkalian dapat menghindari kesalahan overflow.
+% Perkalian dua tipe dapat menyebabkan kesalahan overflow. Karena anda
+% mengkonversi hasil ke tipe lebih besar, anda menghindari
+% seperti itu dengan mengubah operand ke tipe ini sebelum melakukan pengurangan.
+type_w_pointer_to_signed=04082_W_Mengkonversi pointer ke integer bertanda dapat membuat hasil perbandingan yang salah dan kesalahan jangkauan, sebaiknya gunakan tipe unsigned.
+% Ruang alamat virtual pada mesin 32-bit berjalan dari \$00000000 sampai
+% \$ffffffff. Banyak sistem operasi membeolehkan anda untuk mengalokasikan
+% memori di atas \$80000000, sebagai contoh Windows dan Linux membolehkan
+% pointer dalam jangkauan \$0000000 sampai \$bfffffff. Jika anda mengkonversi
+% pointer ke tipe bertanda, ini dapat menyebabkan overflow dan kesalahan
+% pemeriksaan jangkauan, tapi juga \$80000000 < \$7fffffff.
+% Ini bisa menyebabkan kesalahan acak dalam kode seperti "if p>q".
+% \end{description}
+#
+# Symtable
+#
+# 05060 is the last used one
+#
+% \section{Penanganan simbol}
+% Seksi ini mendaftarkan semua pesan yang berkenaan dengan penanganan simbol.
+% Ini berarti semua hal yang harus dilakukan dengan prosedur dan nama variabel.
+% \begin{description}
+sym_e_id_not_found=05000_E_Pengenal tidak ditemukan "$1"
+% Kompilator tidak mengetahui simbol ini. Biasanya terjadi ketika anda salah
+% mengeja nama variabel atau prosedur, atau ketika anda lupa untuk
+% mendeklarasikan variabel.
+sym_f_internal_error_in_symtablestack=05001_F_Kesalahan Internal dalam SymTableStack()
+% Kesalahan internal terjadi dalam kompilator; Jika anda menemukan kesalahan ini,
+% silahkan hubungi para pengembang dan coba untuk menyertakan penjelasan pasti
+% dari keadaan di mana kesalahan terjadi.
+sym_e_duplicate_id=05002_E_Duplikasi pengenal "$1"
+% Pengenal sudah dideklarasikan dalam lingkup saat ini.
+sym_h_duplicate_id_where=05003_H_Pengenal sudah didefinisikan dalam $1 pada baris $2
+% Pengenal sudah dideklarasikan dalam lingkup sebelumnya.
+sym_e_unknown_id=05004_E_Pengenal "$1" tidak dikenal
+% Pengenal ditemukan belum dideklarasikan, atai dipakai di luar lingkup
+% di mana ia didefinisikan.
+sym_e_forward_not_resolved=05005_E_Deklarasi fotidak memecahkan "$1"
+% Ini dapat terjadi dalam dua kasus:
+% \begin{itemize}
+% \item Ini terjadi saat anda mendeklarasikan fungsi bagian (dalam \var{interface},
+% atau dengan direktif \var{forward}, tapi tidak mengimplementasikannya.
+% \item Anda mereferensi tipe yang tidak dideklarasikan dalam blok \var{type}
+% saat ini.
+% \end{itemize}
+sym_e_error_in_type_def=05007_E_Kesalahan dalam definisi tipe
+% Ada kesalahan dalam definisi anda pada tipe array baru:
+% \item Salah satu pembatas jangkauan dalam deklarasi array salah.
+% Sebagai contoh, \var{Array [1..1.25]} akan memicu kesalahan ini.
+sym_e_forward_type_not_resolved=05009_E_Tipe forward tidak memecahkan "$1"
+% Simbol forward didefinisikan, tapi tidak ada deklarasi yang ditemukan.
+sym_e_only_static_in_static=05010_E_Hanya variabel statis bisa dipakai dalam metode statis atau di luar metode
+% Metode statis pada obyek hanya bisa mengakses variabel statis.
+sym_f_type_must_be_rec_or_class=05012_F_tipe record atau class diharapkan
+% Variabel atau ekspresi bukan tipe \var{record} atau \var{class}.
+sym_e_no_instance_of_abstract_object=05013_E_Turunan kelas atau obyek dengan metode abstrak tidak dibolehkan
+% Anda mencoba untuk membuat turunan kelas yang memiliki metode abstrak yang
+% tidak diganti.
+sym_w_label_not_defined=05014_W_Label tidak didefinisikan "$1"
+% Label dideklarasikan, tapi tidak didefinisikan.
+sym_e_label_used_and_not_defined=05015_E_Label dipakai tapi tidak didefinisikan "$1"
+% Label dideklarasikan dan dipakai, tapi tidak didefinisikan.
+sym_e_ill_label_decl=05016_E_Deklarasi label tidak benar
+% Kesalahan ini seharusnya tidak pernah terjadi; ia terjadi jika label
+% didefinisikan di luar prosedur atau fungsi.
+sym_e_goto_and_label_not_supported=05017_E_GOTO dan LABEL tidak didukung (gunakan saklar -Sg)
+% Anda harus mengompilasi program yang mempunyai pernyataan \var{label}s dan \var{goto}
+% dengan saklar \var{-Sg}. Standarnya, \var{label} dan \var{goto} tidak
+% didukung.
+sym_e_label_not_found=05018_E_Label tidak ditemukan
+% \var{goto label} ditemukan, tapi label tidak dideklarasikan.
+sym_e_id_is_no_label_id=05019_E_pengenal bukan sebuah label
+% Pengenal ditetapkan setelah \var{goto} bukan tipe label.
+sym_e_label_already_defined=05020_E_label sudah didefinisikan
+% Anda mendefinisikan label dua kali. Anda bisa mendefinisikan label hanya sekali.
+sym_e_ill_type_decl_set=05021_E_deklarasi tipe tidak benar pada set elemen
+% Deklarasi sebuah set berisi definisi tipe yang tidak benar.
+sym_e_class_forward_not_resolved=05022_E_Definisi kelas forward tidak memecahkan "$1"
+% Anda mendeklarasikan kelas, tapi anda tidak mengimplementasikannya.
+sym_n_unit_not_used=05023_H_Unit "$1" tidak dipakai dalam $2
+% Unit yang direferensi ulang dalam klausul \var{uses} tidak dipakai.
+sym_h_para_identifier_not_used=05024_H_Parameter "$1" tidak dipakai
+% Pengenal dideklarasikan (secara lokal atau global) tapi tidak dipakai
+% (secara lokal atau global).
+sym_n_local_identifier_not_used=05025_N_Variabel lokal "$1" tidak dipakai
+% Anda telah mendeklarasikan, tapi tidak menggunakan variabel dalam implementasi
+% prosedur atau fungsi.
+sym_h_para_identifier_only_set=05026_H_Parameter nilai "$1" ditempati tetapi tidak dipakai
+% Pengenal dideklarasikan (secara lokal atau global) dan disetel tapi tidak
+% dipakai (secara lokal atau global).
+sym_n_local_identifier_only_set=05027_N_Variabel lokal "$1" ditempati tapi tidak dipakai
+% Implementasi variabel dalam prosedur atau fungsi dideklarasikan, disetel
+% tapi tidak pernah digunakan.
+sym_h_local_symbol_not_used=05028_H_Lokal $1 "$2" tidak dipakai
+% Simbol lokal tidak pernah digunakan.
+sym_n_private_identifier_not_used=05029_N_Field private "$1.$2" tidak pernah dipakai
+% Field private didefinisikan, tapi tidak pernah dipakai dalam kode.
+sym_n_private_identifier_only_set=05030_N_Field private "$1.$2" ditempati tapi tidak pernah dipakai
+% Field private dideklarasikan, ditempati tapi tidak pernah dibaca.
+sym_n_private_method_not_used=05031_N_Metode private "$1.$2" tidak pernah dipakai
+% Metode private dideklarasikan tapi tidak pernah dipakai dalam kode.
+sym_e_set_expected=05032_E_Tipe set diharapkan
+% Variabel atau ekspresi bukan tipe \var{set}. Ini terjadi dalam pernyataan
+% \var{in}.
+sym_w_function_result_not_set=05033_W_Hasil fungsi nampaknya belum disetel
+% Anda mendapatkan peringatan ini jika kompilator berpikir bahwa nilai kembalian
+% fungsi tidak disetel. Ini tidak akan ditampilkan untuk prosedur assembler,
+% atau prosedur yang berisi blok assembler.
+sym_w_wrong_C_pack=05034_W_Tipe "$1" tidak dijajarkan dengan benar dalam record saat ini untuk C
+% Array dengan ukuran tidak multipel dari 4 akan dijajarkan secara salah untuk
+% struktur C.
+sym_e_illegal_field=05035_E_Pengenal field record "$1" tidak dikenal
+% Field tidak ada dalam definisi record/object.
+sym_w_uninitialized_local_variable=05036_W_Variabel lokal "$1" nampaknya belum diinisialisasi
+% Pesan ini ditampilkan jika kompilator berpikir bahwa variabel akan dipakai
+% (misalnya muncul dalam ekspresi sisi-tangan-kanan) saat ia tidak
+% diinisialisasi lebih dulu (misalnya muncul dalam sisi tangan-kiri pada
+% penempatan)
+sym_w_uninitialized_variable=05037_W_Variabel "$1" nampaknya belum diinisialisasi
+% Pesan ini ditampilkan jika kompilator berpikir bahwa variabel akan dipakai
+% (misalnya muncul dalam sisi tangan-kanan dari ekspresi) saat ia tidak
+% diinisialisasi lebih dulu (misalnya muncul dalam sisi tangan-kiri pada
+% penempatan)
+sym_e_id_no_member=05038_E_pengenal idents tanpa anggota "$1"
+% Kesalahan ini dibuat ketika pengenal record, field, atau metode diakses
+% sementara ia tidak didefinisikan.
+sym_h_param_list=05039_H_Ditemukan deklarasi: $1
+% Anda mendapatkan ini ketika anda menggunakan saklar \var{-vh}. Dalam hal
+% prosedur yang di-overload tidak ditemukan, maka semua kandidat prosedur yang
+% di-overload didaftarkan, dengan daftar parameternya.
+sym_e_segment_too_large=05040_E_Elemen data terlalu besar
+% Anda mendapatkan in ketika anda mendeklarasikan elemen data yang ukurannya
+% melebihi batas yang ditetapkan (2 Gb pada prosesor 80386+/68020+)
+sym_e_no_matching_implementation_found=05042_E_Tidak ada implementasi yang sesuai untuk metode interface "$1" yang ditemukan
+% Tidak ada metode yang sama ditemukan yang dapat mengimplementasi metode
+% interface. Periksa tipe argumen dan tipe hasil pada metode.
+sym_w_deprecated_symbol=05043_W_Simbol "$1" tidak dipakai lagi
+% Ini berarti bahwa simbol (variabel, rutin, dll...) yang dideklarasikan
+% sebagai \var{deprecated} diterbitkan. Simbol deprecated mungkin tidak lagi
+% tersedia dalam versi lebih baru atas unit / librari. Penggunaan simbol
+% harus dihindari sebaik mungkin.
+sym_w_non_portable_symbol=05044_W_Simbol "$1" tidak portabel
+% Ini berarti bahwa sebuah simbol (variabel, rutin, dll...) yang dideklarasikan
+% sebagai \var{platform} dipakai. Nilai simbol ini, penggunaannya serta
+% ketersediaannya adalah spesifik platform dan tidak boleh dipakai jika kode
+% sumber harus portabel.
+sym_w_non_implemented_symbol=05055_W_Simbol "$1" tidak diimplementasikan
+% Ini berarti bahwa sebuah simbol (variabel, rutin, dll...) yang dideklarasikan
+% sebagai \var{unimplemented} dipakai. Simbol ini didefinisikan, tapi belum
+% diimplementasikan pada spesifik platform ini.
+sym_e_cant_create_unique_type=05056_E_Tidak bisa membuat tipe unik dari tipe ini
+% Hanya tipe sederhana seperti ordinal, float dan tipe string didukung ketika
+% mendefinisikan ulang tipe dengan \var{type newtype = type oldtype;}.
+sym_h_uninitialized_local_variable=05057_H_Variabel lokal "$1" nampaknya belum diinisialisasi
+% Pesan ini ditampilkan jika kompilator berpikir bahwa variabel yang akan
+% dipakai (misalnya muncul dalam sisi-tangan-kiri atas ekspresi) saat ia tidak
+% diinisialisasi lebih dulu (misalnya muncul dalam sisi tangan-kiri pada
+% penempatan)
+sym_h_uninitialized_variable=05058_H_Variabel "$1" nampaknya tidak diinisialisasi
+% Pesan ini ditampilkan jika kompilator berpikir bahwa variabel yang akan
+% dipakai (misalnya muncul dalam sisi-tangan-kiri atas ekspresi) saat ia tidak
+% diinisialisasi lebih dulu (misalnya muncul dalam sisi tangan-kiri pada
+% penempatan)
+sym_w_function_result_uninitialized=05059_W_Variabel hasil fungsi nampaknya tidak diinisialisasi
+% Pesan ini ditampilkan jika kompilator berpikir bahwa variabel hasil fungsi yang
+% akan dipakai (misalnya muncul dalam sisi-tangan-kiri atas ekspresi) saat ia
+% tidak diinisialisasi lebih dulu (misalnya muncul dalam sisi tangan-kiri pada
+% penempatan)
+sym_h_function_result_uninitialized=05060_H_Variabel hasil fungsi nampaknya tidak diinisialisasi
+% Pesan ini ditampilkan jika kompilator berpikir bahwa variabel hasil fungsi
+% yang akan dipakai (misalnya muncul dalam sisi-tangan-kanan atas ekspresi) saat
+% tidak diinisialisasi lebih dulu (misalnya muncul dalam sisi tangan-kanan pada
+% penempatan)
+sym_w_identifier_only_read=05061_W_Variabel "$1" dibaca tapi tida ditempati dimanapun
+% Anda membaca nilai sebuah variabel, tapi tidak menempatkan nilainya ke
+% manapun.
+sym_h_abstract_method_list=05062_H_Ditemukan metode abstrak: $1
+% Ketika mendapatkan peringatan mengenai pembentukan class/object dengan metode
+% abstrak anda mendapatkan petunjuk ini untuk menemukan metode yang dipengaruhi.
+% \end{description}
+#
+# Codegenerator
+#
+# 06040 is the last used one
+#
+% \section{Pesan pembuat kode}
+% Seksi ini mendaftarkan semua pesan yang dapat ditampilkan jika generator
+% kode menemukan kondisi kesalahan.
+% \begin{description}
+cg_e_parasize_too_big=06009_E_Ukuran daftar parameter melebihi 65535 byte
+% Prosesor I386 membatasi daftar parameter ke 65535 byte (instruksi \var{RET}
+% menyebabkan ini)
+cg_e_file_must_call_by_reference=06012_E_Tipe file harus parameter var
+% Anda tidak bisa menetapkan file sebagai parameter nilai, misalnya ia harus
+% selalu dideklarasikan parameter \var{var}.
+cg_e_cant_use_far_pointer_there=06013_E_Penggunaan pointer far tidak dibolehkan di sini
+% Free Pascal tidak mendukung pointer far, maka anda tidak bisa mengambil alamat
+% sebuah ekspresi yang memiliki referensi far sebagai hasil. Konstruksi \var{mem}
+% mempunyai referensi far sebagai hasil, maka kode berikut akan menghasilkan
+% kesalahan ini:
+% \begin{verbatim}
+% var p : pointer;
+% ...
+% p:=@mem[a000:000];
+% \end{verbatim}
+cg_e_dont_call_exported_direct=06015_E_Fungsi yang dideklarasikan EXPORT tidak bisa dipanggil
+% Tidak dipakai lagi.
+cg_w_member_cd_call_from_method=06016_W_Kemungkinan tidak benar pemanggilan atas constructor atau destructor
+% Kompilator mendeteksi bahwa constructor atau destructor dipanggil di dalam
+% sebuah metode. Ini mungkin akan menimbulkan masalah, karena constructors/
+% destructors memerlukan parameter saat masuk.
+cg_n_inefficient_code=06017_N_Kode tidak efisien
+% Pernyataan anda nampaknya diragukan oleh kompilator.
+cg_w_unreachable_code=06018_W_Kode tidak bisa dicapai
+% Anda menetapkan sebuah konstruksi yang tidak akan pernah dieksekusi. Contoh:
+% \begin{verbatim}
+% while false do
+% begin
+% {.. code ...}
+% end;
+% \end{verbatim}
+cg_e_cant_call_abstract_method=06020_E_Metode abstrak tidak bisa dipanggil secara langsung
+% Anda tidak bisa memanggil metode abstrak secara langsung, sebaliknya anda
+% harus memanggil metode anak penggantinya, karena metode abstrak tidak diterapkan.
+cg_d_register_weight=06027_DL_Register $1 bobot $2 $3
+% Pesan debug. Ditampilkan saat kompilator menganggap variabel untuk dipelihara
+% dalam register.
+cg_d_stackframe_omited=06029_DL_Bingkai stack diabaikan
+% Beberapa prosedur/fungsi tidak memerlukan bingkai stack lengkap, maka ia
+% diabaikan. Pesan ini akan ditampilkan saat saklar {-vd} dipakai.
+cg_e_unable_inline_object_methods=06031_E_Metode obyek atau kelas tidak bisa inline.
+% Anda tidak bisa mempunyai metode obyek inlined.
+cg_e_unable_inline_procvar=06032_E_Pemanggilan procvar tidak dalam inline.
+% Prosedur dengan pemanggilan variabel prosedural tidak bisa disejajarkan.
+cg_e_no_code_for_inline_stored=06033_E_Tidak ada kode untuk prosedur inline tersimpan
+% Kompilator tidak bisa menyimpan kode untuk prosedur inline.
+cg_e_can_access_element_zero=06035_E_Elemen nol dari ansi/wide- atau longstring tidak dapat diakses, sebaiknya gunakan (set)length
+% Anda harus menggunakan \var{setlength} untuk menyetel panjang ansi/wide/longstring
+% dan \var{length} untuk mendapatkan panjang dari tipe string tersebut
+cg_e_cannot_call_cons_dest_inside_with=06037_E_Konstruktor atau Destruktor tidak bisa dipanggil di dalam klausul 'with'
+% Di dalam klausul \var{with} anda tidak dapat memanggil sebuah konstruktor
+% atau destruktor untuk obyek yang anda miliki dalam klausul \var{with}.
+cg_e_cannot_call_message_direct=06038_E_Tidak bisa memanggil metode pengendali pesan secara langsung
+% Pengendali metode pesan tidak bisa dipanggil secara langsung jika ia berisi
+% argumen self eksplisit
+cg_e_goto_inout_of_exception_block=06039_E_Lompat masuk atau keluar blok eksepsi
+% Tidak dibolehkan untuk melompat masuk atau keluar dari blok eksepsi seperti \var{try..finally..end;}:
+% \begin{verbatim}
+% label 1;
+%
+% ...
+%
+% try
+% if not(final) then
+% goto 1; // baris ini akan menimbulkan kesalahan
+% finally
+% ...
+% end;
+% 1:
+% ...
+% \end{verbatim}
+cg_e_control_flow_outside_finally=06040_E_Pernyataan alur kontrol tidak dibolehkan dalam blok finally
+% Tidak dibolehkan untuk menggunakan pernyataan alur kontrol \var{break},
+% \var{continue} dan \var{exit}
+% di dalam pernyataan finally. Contoh berikut menampilkan masalah ini:
+% \begin{verbatim}
+% ...
+% try
+% p;
+% finally
+% ...
+% exit; // Exit ini TIDAK diperbolehkan
+% end;
+% ...
+%
+% \end{verbatim}
+% Jika prosedur \var{p} memunculkan eksepsi blok finally dijalankan. Jika
+% eksekusi mencapai exit, tidak jelas apa yang dilakukan:
+% keluar prosedur, atau mencari pengendali eksepsi yang lain
+cg_w_parasize_too_big=06041_W_Ukuran parameters melebihi batas cpu tertentu
+% Ini menunjukan bahwa anda mendeklarasikan lebih dari 64K parameter, yang
+% mungkin tidak didukung pada prosesor target.
+cg_w_localsize_too_big=06042_W_Ukuran variabel lokal melebihi batas untuk cpu tertetnu
+% Ini menunjukan bahwa anda mendeklarasikan lebih dari 32K varbael lokal, yang
+% mungkin tidak didukung pada prosesor target.
+cg_e_localsize_too_big=06043_E_Ukuran variabel lokal melebihi batas yang didukung
+% Ini menunjukan bahwa anda mendeklarasikan lebih dari 32K variabel lokal, yang
+% tidak didukung oleh prosesor ini.
+cg_e_break_not_allowed=06044_E_BREAK tidak diperbolehkan
+% Anda mencoba untuk menggunakan \var{break} di luar konstruksi loop.
+cg_e_continue_not_allowed=06045_E_CONTINUE tidak diperbolehkan
+% Anda mencoba untuk menggunakan \var{continue} di luar konstruksi loop.
+cg_f_unknown_compilerproc=06046_F_Tidak dikenal compilerproc "$1". Periksa apakah anda menggunakan run time library yang benar.
+% Kompilator mengharapkan bahwa runtime library berisi subrutin tertentu. Jika
+% anda melihat kesalahan ini dan anda tidak mengubah kode runtime library,
+% nampaknya runtime library yang anda pakai tidak sesuai dengan kompilator.
+% Jika anda mengubah runtime library kesalahan ini berarti bahwa anda
+% menghapus subrutin yang diperlukan kompilator untuk pemakaian internalnya.
+cg_f_unknown_system_type=06047_F_Tidak bisa menemukan tipe sistem "$1". Periksa apakah anda menggunakan run time library yang benar.
+% Kompilator mengharapkan bahwa runtime library berisi definisi tipe tertentu.
+% Jika anda melihat kesalahan ini dan anda tidak mengubah kode runtime library,
+% nampaknya runtime library yang anda pakai tidak sesuai dengan kompilator.
+% Jika anda mengubah runtime library kesalahan ini berarti bahwa anda
+% menghapus subrutin yang diperlukan kompilator untuk pemakaian internalnya.
+cg_h_inherited_ignored=06048_H_Pemanggilan turunan ke metode abstrak diabaikan
+% Pesan ini hanya muncul dalam mode Delphi ketika anda memanggil metode abstract
+% dari kelas leluhur via \var{inherited;}. Pemanggilan in kemudian diabaikan.
+% \end{description}
+# EndOfTeX
+
+#
+# Assembler reader
+#
+# 07105 is the last used one
+#
+asmr_d_start_reading=07000_DL_Mulai penguraian assembler gaya $1
+% Ini memberitahu anda bahwa blok assembler sedang diuraikan
+asmr_d_finish_reading=07001_DL_Selesasi penguraian assembler gaya $1
+% Ini memberitahu anda bahwa blok assembler sudah selesai.
+asmr_e_none_label_contain_at=07002_E_Pola non-label berisi @
+% Pembeda yang bukan label tidak bisa berisi sebuah @.
+asmr_e_building_record_offset=07004_E_Kesalahan pembangunan ofset record
+% Terjadi kesalahan saat membangun ofset struktur record/object,
+% ini bisa terjadi ketika tidak ada field yang ditetapkan sama sekali
+% atau pembeda field yang dipakai tidak dikenal.
+asmr_e_offset_without_identifier=07005_E_OFFSET dipakai tanpa pembeda
+% Abda hanya bisa menggunakan OFFSET dengan sebuah pembeda. Sintaks lain tidak
+% didukung
+asmr_e_type_without_identifier=07006_E_TYPE dipakai tanpa pembeda
+% Anda hanya bisa menggunakan TYPE dengan sebuah pembeda. Sintaks lain tidak
+% didukung
+asmr_e_no_local_or_para_allowed=07007_E_Tidak bisa menggunakan variabel lokal atau parameters di sini
+% Anda tidak dapat menggunakan variabel lokal atau parameter di sini, karena
+% pengalamatan lokal dan parameter dikerjakan menggunakan bingkai register pointer
+% agar alamat tidak bisa diperoleh secara langsung.
+asmr_e_need_offset=07008_E_perlu memakai OFFSET di sini
+% Anda perlu menggunakan OFFSET <id> di sini untuk mendapatkan alamat pengenal.
+asmr_e_need_dollar=07009_E_perlu memakai $ di sini
+% Anda perlu menggunakan $<id> di sini untuk mendapatkan alamat pengenal.
+asmr_e_cant_have_multiple_relocatable_symbols=07010_E_Tidak bisa menggunakan multipel simbol relocatable
+% Anda tidak bisa mempunyai lebih dari satu simbol relocatable (variabel/konstan type)
+% dalam satu argumen.
+asmr_e_only_add_relocatable_symbol=07011_E_Simbol relocatable hanya dapat ditambahkan
+% Simbol relocatable (variabel/konstan type) tidak bisa dipakai dengan operator
+% lain. Hanya tambahan yang dibolehkan.
+asmr_e_invalid_constant_expression=07012_E_Ekspresi konstan tidak benar
+% Ada kesalahan dalam ekspresi konstan.
+asmr_e_relocatable_symbol_not_allowed=07013_E_Simbol relocatable tidak dibolehkan
+% Anda tidak bisa menggunakan simbol relocatable (variabel/konstan type) di sini.
+asmr_e_invalid_reference_syntax=07014_E_Sintaks referensi tidak benar
+% Ada kesalahan dalam referensi.
+asmr_e_local_para_unreachable=07015_E_Anda tidak dapat mencapai $1 dari kode itu
+% Anda tidak dapat membaca secara langsung nilai variabel lokal atau parameter
+% dari tingkat prosedur lebih tinggi dalam kode assembler (kecuali untuk kode
+% assembler lokal tanpa parameter maupun local).
+asmr_e_local_label_not_allowed_as_ref=07016_E_Simbol local/label tidak dibolehkan sebagai referensi
+% Anda tidak bisa menggunakan simbol lokal/label sebagai referensi
+asmr_e_wrong_base_index=07017_E_Penggunaan basis dan indeks register tidak benar
+% Ada kesalahan dengan base dan index register, keduanya mungkin
+% tidak benar
+asmr_w_possible_object_field_bug=07018_W_Kemungkinan kesalahan dalam penanganan field obyek
+% Field obyek atau kelas dapat dicapai secara langsung dalam mode normal atau
+% objfpc tapi mode TP dan Delphi memperlakukan nama field sebagai ofset sederhana.
+asmr_e_wrong_scale_factor=07019_E_Faktor skala yang ditetapkan salah
+% Faktor skala yang diberikan salah, hanya 1,2,4 dan 8 yang dibolehkan
+asmr_e_multiple_index=07020_E_Penggunaan multipel indeks register
+% Anda mencoba menggunakan lebih dari satu indeks register
+asmr_e_invalid_operand_type=07021_E_Tipe operand tidak benar
+% Tipe operand tidak sama dengan opcode yang dipakai
+asmr_e_invalid_string_as_opcode_operand=07022_E_String sebagai opcode operand tidak benar: $1
+% String yang ditetapkan sebagai operand tidak sama dengan opcode ini
+asmr_w_CODE_and_DATA_not_supported=07023_W_@CODE dan @DATA tidak didukung
+% @CODE dan @DATA tidak didukung dan diabaikan.
+asmr_e_null_label_ref_not_allowed=07024_E_Referensi label null tidak dibolehkan
+asmr_e_expr_zero_divide=07025_E_Pembagian dengan nol dalam evaluator asm
+% Ada pembagian dengan nol dalam ekspresi konstan
+asmr_e_expr_illegal=07026_E_Ekspresi tidak benar
+% Ada ekspresi tidak benar dalam ekspresi konstan
+asmr_e_escape_seq_ignored=07027_E_urutan escape diabaikan: $1
+% Ada string bergaya-C, tapi urutan escape dalam string tidak dikenal,
+% dan karenanya diabaikan
+asmr_e_invalid_symbol_ref=07028_E_Referensi simbol tidak benar
+asmr_w_fwait_emu_prob=07029_W_Fwait dapat menyebabkan masalah emulasi dengan emu387
+asmr_w_fadd_to_faddp=07030_W_$1 tanpa operand diterjemahkan menjadi $1P
+asmr_w_enter_not_supported_by_linux=07031_W_Instruksi ENTER tidak didukung oleh Linux kernel
+% Instruksi ENTER dapat membuat kesalahan halaman stack yang tidak ditangkap
+% dengan benar oleh pengendali halaman i386 Linux.
+asmr_w_calling_overload_func=07032_W_Pemanggilan fungsi overload dalam assembler
+% Ada panggilan ke metode yang di-overload dalam blok assembler, ini dapat
+% menjadi tanda di sana ada masalah
+asmr_e_unsupported_symbol_type=07033_E_Tipe simbol untuk operand tidak didukung
+asmr_e_constant_out_of_bounds=07034_E_Nilai konstan di luar jangkauan
+asmr_e_error_converting_decimal=07035_E_Kesalahan konversi desimal $1
+% Nilai konstan desimal tidak memiliki sintaks yang benar
+asmr_e_error_converting_octal=07036_E_Kesalahan konversi oktal $1
+% Nilai konstan oktal tidak memiliki sintaks yang benar
+asmr_e_error_converting_binary=07037_E_Kesalahan konversi biner $1
+% Nilai konstan biner tidak memiliki sintaks yang benar
+asmr_e_error_converting_hexadecimal=07038_E_Kesalahan konversi heksadesimal $1
+% Nilai konstan heksadesimal tidak memiliki sintaks yang benar
+asmr_h_direct_global_to_mangled=07039_H_$1 diterjemahkan menjadi $2
+asmr_w_direct_global_is_overloaded_func=07040_W_$1 dikaitkan ke fungsi yang di-overload
+asmr_e_cannot_use_SELF_outside_a_method=07041_E_Tidak bisa menggunakan SELF di luar metode
+% Ada referensi ke simbol \var{self} sementara ia tidak diijinkan.
+% \var{self} hanya bisa direferensi di dalam metode
+asmr_e_cannot_use_OLDEBP_outside_nested_procedure=07042_E_Tidak bisa menggunakan OLDEBP di luar prosedure yang diulang
+% Ada referensi ke simbol \var{oldebp} sementara ia tidak diijinkan.
+% \var{oldebp} hanya bisa direferensi di dalam rutin yang diulang
+asmr_e_void_function=07043_W_Prosedure tidak bisa mengembalikan setiap nilai dalam kode asm
+% Mencoba untuk mengembalikan nilai saat dalam sebuah prosedur. Sebuah prosedur
+% tidak mempunyai nilai balik
+asmr_e_SEG_not_supported=07044_E_SEG tidak didukung
+asmr_e_size_suffix_and_dest_dont_match=07045_E_Ukuran sufiks dan tujuan atau sumber tidak sama
+% Ukuran register dan sufiks ukuran opcode tidak sama. Ini mungkin kesalahan
+% dalam pernyataan assembler
+asmr_w_size_suffix_and_dest_dont_match=07046_W_Ukuran sufiks dan tujuan atau sumber tidak sama
+% Ukuran register dan sufiks ukuran opcode tidak sama. Ini mungkin kesalahan
+% dalam pernyataan assembler
+asmr_e_syntax_error=07047_E_Sintaks assembler salah
+% Ada kesalahan dalam sintaks assembler
+asmr_e_invalid_opcode_and_operand=07048_E_Kombinasi opcode dan operand tidak benar
+% Opcode tidak bisa dipakai dengan tipe operand ini
+asmr_e_syn_operand=07049_E_Sintaks assembler salah dalam operand
+asmr_e_syn_constant=07050_E_Kesalahan sintaks assembler dalam konstan
+asmr_e_invalid_string_expression=07051_E_Ekspresi String tidak benar
+asmr_w_const32bit_for_address=07052_W_konstan dengan simbol $1 untuk alamat yang tidak pada pointer
+% Ekspresi konstan mewakili alamat yang tidak sesuai ke dalam sebuah pointer.
+% Alamat mungkin tidak benar
+asmr_e_unknown_opcode=07053_E_Opcode $1 tidak dikenal
+% Opcode ini tidak dikenal
+asmr_e_invalid_or_missing_opcode=07054_E_Tidak benar atau opcode hilang
+asmr_e_invalid_prefix_and_opcode=07055_E_Kombinasi prefiks dan opcode tidak benar: $1
+asmr_e_invalid_override_and_opcode=07056_E_Kombinasi override dan opcode tidak benar: $1
+asmr_e_too_many_operands=07057_E_Terlalu banyak operand pada baris
+% Ada terlalu banyak operand untuk opcode ini. Periksa sintaks assembler
+% anda
+asmr_w_near_ignored=07058_W_NEAR diabaikan
+asmr_w_far_ignored=07059_W_FAR diabaikan
+asmr_e_dup_local_sym=07060_E_Duplikasi simbol lokal $1
+asmr_e_unknown_local_sym=07061_E_Simbol lokal $1 tidak didefinisikan
+asmr_e_unknown_label_identifier=07062_E_Pengenal label tidak dikenal $1
+asmr_e_invalid_register=07063_E_Nama register tidak benar
+% Ada nama register tidak dikenal yang dipakai sebagai operand.
+asmr_e_invalid_fpu_register=07064_E_Nama register floating point tidak benar
+% Ada nama register tidak dikenal yang dipakai sebagai operand.
+asmr_w_modulo_not_supported=07066_W_Modulo tidak didukung
+asmr_e_invalid_float_const=07067_E_Konstan floating point $1 tidak benar
+% Konstan floating point yang dideklarasikan dalam blok assembler tidak
+% benar.
+asmr_e_invalid_float_expr=07068_E_Ekspresi floating point tidak benar
+% Ekspresi floating point yang dideklarasikan dalam blok assembler tidak
+% benar.
+asmr_e_wrong_sym_type=07069_E_Tipe simbol salah
+asmr_e_cannot_index_relative_var=07070_E_Tidak bisa mengindeks var lokal atau parameter dengan register
+% Mencoba untuk mengindeks menggunakan basis register simbol yang sudah relatif
+% bagi register. Ini tidak mungkin, dan mungkin akan membawa kerusakan.
+asmr_e_invalid_seg_override=07071_E_Ekspresi penggantian segmen tidak benar
+asmr_w_id_supposed_external=07072_W_Pengenal $1 dianggap eksternal
+% Ada referensi ke simbol yang tidak didefinisikan. Ini tidak menghasilkan
+% kesalahan, karena simbol mungkin eksternal, tapi dapat menyebabkan masalah
+% saat waktu link jika simbol tidak didefinisikan dimanapun.
+asmr_e_string_not_allowed_as_const=07073_E_String tidak diijinkan sebagai konstan
+% String karakter tidak dibolehkan sebagai konstan.
+asmr_e_no_var_type_specified=07074_Tidak ada tipe variabel yang ditetapkan
+% Sintaks mengharapkan tipe pengenal setelah titik, tapi tidak menemukan
+% apapun.
+asmr_w_assembler_code_not_returned_to_text=07075_E_kode assembler tidak dikembaliken ke seksi text
+% Ada direktif dalam blok assembler untuk mengubah seksi, tapi di sana
+% ada kekuarangan untuk ke seksi text di akhir blok assembler. Ini dapat
+% menyebabkan kesalahan selama waktu link.
+asmr_e_not_directive_or_local_symbol=07076_E_Bukan direktif atau simbol lokal $1
+% Simbol ini tidak dikenal.
+asmr_w_using_defined_as_local=07077_E_Menggunakan nama yang didefinisikan sebagai label lokal
+asmr_e_dollar_without_identifier=07078_E_Token dolar dipakai tanpa sebuah pengenal
+% Ekspresi konstan memiliki pengenal yang tidak diawali dengan simbol $
+asmr_w_32bit_const_for_address=07079_W_Konstan 32bit dibuat untuk alamat
+% Konstan dipakai sebagai alamat. Ini mungkin kesalahan karena menggunakan
+% alamat absolut yang mungkin tidak akan bekerja.
+asmr_n_align_is_target_specific=07080_N_.align adalah spesifik target, gunakan .balign atau .p2align
+% Menggunakan direktif .align adalah spesifik platform, dan artinya akan
+% berlainan dari satu platform ke yang lainnya.
+asmr_e_cannot_access_field_directly_for_parameters=07081_E_Tidak bisa mengakses field secara langsung untuk parameter
+% Anda harus mengambil parameter lebih duku ke dalam register dan kemudian
+% mengakses field menggunakan register itu.
+asmr_e_cannot_access_object_field_directly=07082_E_Tidak bisa mengakses field dari obyek/kelas secara langsung
+% Anda harus mengambil pointer self lebih dulu ke dalam register dan mengakses
+% field menggunakan register sebagai basis. Standarnya pointer self tersedia
+% dalam register esi pada i386.
+asmr_e_unable_to_determine_reference_size=07083_E_Tidak ada ukuran yang ditetapkan dan tidak bisa menentukan besar operand
+% Anda harus menetapkan secara eksplisit ukuran untuk referensi, karena kompilator
+% tidak bisa menentukan ukuran apa (byte, word, dword, dll) ia harus dipakai
+% untuk referensi.
+asmr_e_cannot_use_RESULT_here=07084_E_Tidak bisa menggunakan RESULT dalam fungsi ini
+% Beberapa fungsi yang mengembalikan tipe kompleks tidak bisa menggunakan kata
+% kunci \var{result}.
+asmr_w_adding_explicit_args_fXX=07086_W_"$1" tanpa operand yang diterjemahkan ke dalam "$1 %st,%st(1)"
+asmr_w_adding_explicit_first_arg_fXX=07087_W_"$1 %st(n)" diterjemahkan ke dalam "$1 %st,%st(n)"
+asmr_w_adding_explicit_second_arg_fXX=07088_W_"$1 %st(n)" diterjemahkan ke dalam "$1 %st(n),%st"
+asmr_e_invalid_char_smaller=07089_E_Char < tidak dibolehkan di sini
+% Operator shift memerlukan karakter <<. Hanya salah satu dari karakter itu
+% yang ditemukan.
+asmr_e_invalid_char_greater=07090_E_Char > tidak dibolehkan di sini
+% Operator shift memerlukan karakter >>. Hanya salah satu dari karakter itu
+% yang ditemukan.
+asmr_w_align_not_supported=07093_W_ALIGN tidak didukung
+asmr_e_no_inc_and_dec_together=07094_E_Inc dan Dec tidak bisa bersamaan
+% Mencoba untuk menggunakan increment dan decrement di dalam opcode yang sama
+% pada 680x0. Ini tidak mungkin.
+asmr_e_invalid_reg_list_in_movem=07095_E_reglist untuk movem tidak benar
+% Mencoba untuk menggunakan opcode \var{movem} dengan register yang tidak
+% benar untuk menyimpan dan mengembalikan.
+asmr_e_invalid_reg_list_for_opcode=07096_E_Reglist tidak benar untuk opcode
+asmr_e_higher_cpu_mode_required=07097_E_Mode cpu lebih tinggi diperlukan ($1)
+% Mencoba untuk menggunakan instruksi yang tidak didukung dalam mode cpu saat
+% ini. Gunakan pembuatan cpu lebih tinggi agar bisa menggunakan opcode ini
+% dalam blok assembler anda
+asmr_w_unable_to_determine_reference_size_using_dword=07098_W_Tidak ada ukuran yang ditetapkan dan tidak bisa menentukan besar operands, menggunakan DWORD sebagai standar
+% Anda harus menetapkan secara eksplisit ukuran untuk referensi, karena
+% kompilator tidak dapat menentukan ukuran apa (byte, word, dword, dll)
+% yang harus dipakai untuk referensi. Peringatan ini hanya dipakai dalam mode
+% Delphi di mana ia kembali menggunakan DWORD sebagai standar.
+asmr_e_illegal_shifterop_syntax=07099_E_Kesalahan sintaks saat mencoba mengurai shifter operand
+% Hanya ARM; ARM assembler mendukung apa yang disebut shifter operand. Sintaks
+% yang dipakai bukan shifter operand yang benar. Contoh untuk operasi dengan shifter operand:
+% \begin{verbatim}
+% asm
+% orr r2,r2,r2,lsl #8
+% end;
+% \end{verbatim}
+asmr_e_packed_element=07100_E_Alamat komponen yang di-packed tidak pada batasan byte
+% Komponen yang di-packed (field record dan elemen array) dapat dimulai pada bit
+% mana saja di dalam sebuah byte. Pada CPU yang tidak mendukung memori
+% dialamatkan-bit (yang menyertakan semua CPU yang didukung oleh FPC saat ini) anda akan
+% mendapatkan pesan kesalahan saat mencoba untuk mengindeks arrays dengan elemen
+% yang ukurannya bukan multipel dari 8 bit. Hal yang sama untuk mengakses field record
+% dengan alamat demikian dengan multipel dari 8 bit.
+asmr_w_unable_to_determine_reference_size_using_byte=07101_W_Ukuran tidak ditetapkan dan tidak bisa menentukan besar dari operand, menggunakan BYTE sebagai standar
+% Anda harus menetapkan secara eksplisit ukuran untuk referensi, karena
+% kompilator tidak dapat menentukan ukuran apa (byte, word, dword, dll)
+% yang harus dipakai untuk referensi. Peringatan ini hanya dipakai dalam mode
+% Delphi di mana ia kembali menggunakan BYTE sebagai standar.
+asmr_w_no_direct_ebp_for_parameter=07102_W_Penggunaan +offset(%ebp) untuk parameter di sini tidak benar
+% Menggunakan referensi 8(%ebp) langsung untuk parameter fungsi/prosedur tidak
+% benar jika parameter ada dalam register.
+asmr_w_direct_ebp_for_parameter_regcall=07103_W_Penggunaan +offset(%ebp) tidak kompatibel dengan konvensi regcall
+% Menggunakan referensi 8(%ebp) langsung untuk parameter fungsi/prosedur tidak
+% benar jika parameter ada dalam register.
+asmr_w_direct_ebp_neg_offset=07104_W_Penggunaan -offset(%ebp) tidak direkomendasikan untuk akses variabel lokal
+% Menggunakan -8(%ebp) untuk mengakses variabel lokal tidak direkomendasikan
+asmr_w_direct_esp_neg_offset=07105_W_Penggunaan -offset(%esp), akses dapat menyebabkan kerusakan atau nilai bisa hilang
+% Menggunakan -8(%esp) untuk mengakses stack lokal tidak direkomendasikan karena
+% bagian stack ini dapat diganti oleh setiap panggilan fungsi atau interrupt.
+asmr_e_no_vmtoffset_possible=07106_E_VMTOffset harus dipakai dalam kombinasi dengan metode virtual, dan "$1" bukanlah virtual
+%
+#
+# Assembler/binary writers
+#
+# 08018 is the last used one
+#
+asmw_f_too_many_asm_files=08000_F_Terlalu banyak file assembler
+% Dengan menghidupkan smartlinking, ada terlalu banyak file assembler yang dibuat.
+% Matikan smartlinking.
+asmw_f_assembler_output_not_supported=08001_F_Output assembler yang dipilih tidak didukung
+asmw_f_comp_not_supported=08002_F_Comp tidak didukung
+asmw_f_direct_not_supported=08003_F_Direct tidak mendukung penulis biner
+% Mode assembler direct tidak mendukung penulis biner.
+asmw_e_alloc_data_only_in_bss=08004_E_Alikasi data hanya dibolehkan dalam seksi bss
+asmw_f_no_binary_writer_selected=08005_F_Tidak ada penulis biner yang dipilih
+asmw_e_opcode_not_in_table=08006_E_Asm: Opcode $1 tidak dalam tabel
+asmw_e_invalid_opcode_and_operands=08007_E_Asm: $1 kombinasi opcode dan operan tidak benar
+asmw_e_16bit_not_supported=08008_E_Asm: referensi 16 Bit tidak didukung
+asmw_e_invalid_effective_address=08009_E_Asm: Alamat efektif tidak benar
+asmw_e_immediate_or_reference_expected=08010_E_Asm: Immediate atau referensi diharapkan
+asmw_e_value_exceeds_bounds=08011_E_Asm: $1 nilai melebihi batasan $2
+asmw_e_short_jmp_out_of_range=08012_E_Asm: Lompat pendek di luar jangkauan $1
+asmw_e_undefined_label=08013_E_Asm: Label tidak didefinisikan $1
+asmw_e_comp_not_supported=08014_E_Asm: Tipe Comp tidak didukung untuk target ini
+asmw_e_extended_not_supported=08015_E_Asm: Tipe Extended tidak didukung untuk target ini
+asmw_e_duplicate_label=08016_E_Asm: Duplikasi label $1
+asmw_e_redefined_label=08017_E_Asm: Redefinisi label $1
+asmw_e_first_defined_label=08018_E_Asm: Pertama didefinisikan di sini
+asmw_e_invalid_register=08019_E_Asm: register tidak benar $1
+asmw_e_16bit_32bit_not_supported=08020_E_Asm: Referensi 16 atau 32 Bit tidak didukung
+asmw_e_64bit_not_supported=08021_E_Asm: 64 Bit operand tidak didukung
+
+#
+# Menjalankan linker/assembler
+#
+# 09034 is the last used one
+#
+# BeginOfTeX
+%
+% \section{Kesalahan tahap assembling/linking}
+% Seksi ini mendaftarkan kesalahan yang terjadi saat kompilator memproses
+% baris perintah atau menangani file konfigurasi.
+% \begin{description}
+exec_w_source_os_redefined=09000_W_Sistem operasi sumber didefinisikan ulang
+% Sistem operasi sumber didefinisikan ulang.
+exec_i_assembling_pipe=09001_I_Assembling (pipe) $1
+% Meng-assembling menggunakan pipa ke assembler eksternal.
+exec_d_cant_create_asmfile=09002_E_Tidak bisa membuat file assembler: $1
+% File yang disebutkan tadi tidak bisa dibuat. Periksa apakah anda memiliki
+% perijinan akses untuk membuat file ini
+exec_e_cant_create_objectfile=09003_E_Tidak bisa membuat file obyek: $1
+% File yang disebutkan tadi tidak bisa dibuat. Periksa apakah anda memiliki
+% perijinan akses untuk membuat file ini
+exec_e_cant_create_archivefile=09004_E_Tidak bisa membuat file arsip: $1
+% File yang disebutkan tadi tidak bisa dibuat. Periksa apakah anda memiliki
+% perijinan akses untuk membuat file ini
+exec_e_assembler_not_found=09005_E_Assembler $1 tidak ditemukan, beralih ke assmembling eksternal
+% Program assembler tidak ditemukan. Kompilator akan menghasilkannaskah yang
+% dapat dipakai untuk meng-assemble dan me-link program.
+exec_t_using_assembler=09006_T_Menggunakan assembler: $1
+% Pesan informasi yang mengatakan assembler mana yang sedang dipakai.
+exec_e_error_while_assembling=09007_E_Kesaslahan saat meng-assembling exitcode $1
+% Ada kesalahan saat meng-assembling file menggunakan assembler eksternal.
+% Lihat dokumentasi piranti assembler guna mencari informasi lebih jauh
+% mengenai kesalahan ini.
+exec_e_cant_call_assembler=09008_E_Tidak bisa memanggil assembler, kesalahan $1 beralih ke assembling eksternal
+% Kesalahan terjadi saat memanggil assembler eksternal, kompilator akan menghasilkan
+% naskah yang dapat dipakai untuk meng-assemble dan link program.
+exec_i_assembling=09009_I_Pemasangan $1
+% Pesan informasional yang menyatakan file yang sedang dipasang.
+exec_i_assembling_smart=09010_I_Memasang dengan smartlinking $1
+% Pesan informasional yang menyatakan file mana yang sedang dipasang menggunakan smartlinking.
+exec_w_objfile_not_found=09011_W_Obyek $1 tidak ditemukan, Linking bisa gagal !
+% Salah satu file obyek hilang, dan linking kemungkinan akan gagal.
+% Periksa path anda.
+exec_w_libfile_not_found=09012_W_Librari $1 tidak ditemukan, Linking bisa gagal !
+% Salah satu file librari hilang, dan linking kemungkinan akan gagal.
+% Periksa path anda.
+exec_e_error_while_linking=09013_E_Kesalahan saat me-link
+% Kesalahan umum saat melakukan linking.
+exec_e_cant_call_linker=09014_E_Tidak bisa memanggil linker, beralih ke eksternal linking
+% Kesalahan terjadi saat memanggil linker eksternal, kompulator akan membuat naskah
+% yang bisa dipakai untuk memasang dan me-link program.
+exec_i_linking=09015_I_Linking $1
+% Pesan informasional, menampilkan program atau librari mana yang sedang di-link.
+exec_e_util_not_found=09016_E_Util $1 tidak ditemukan, beralih ke eksternal linking
+% Piranti eksternal tidak ditemukan, kompilator akan membuat naskah yang
+% dapat dipakai untuk memasang dan me-link atau memproses akhir program.
+exec_t_using_util=09017_T_Menggunakan util $1
+% Pesan informasional, menampilkan program eksternal mana (biasanya pemroses akhir) yang dipakai.
+exec_e_exe_not_supported=09018_E_Pembuatan Executable tidak didukung
+% Pembuatan program executable tidak didukung untuk platform ini, karena belum
+% diimplementasikan dalam kompilator.
+exec_e_dll_not_supported=09019_E_Pembuatan Librari Dinamis/Berbagai tidak didukung
+% Pembuatan dynamically loadable libraries tidak didukung untuk platform ini,
+% karena belum diimplementasikan dalam kompilator.
+exec_i_closing_script=09020_I_Menutup naskah $1
+% Pesan informasional yang tampil saat naskah linking assembling eskternal selesai.
+exec_e_res_not_found=09021_E_kompilator resource tidak ditemukan, beralih ke mode eksternal
+% Kompilator resource eksternal tidak ditemukan, kompilator akan membuat naskah yang dapat
+% dipakai untuk memasang, mengompilasi resources dan me-link atau memproses akhir program.
+exec_i_compilingresource=09022_I_Mengompilasi resource $1
+% Pesan informasional, menampilkan resource mana yang sedang dikompilasi.
+exec_t_unit_not_static_linkable_switch_to_smart=09023_T_unit $1 tidak bisa di-link secara statis, beralih ke smart linking
+% Link statis diminta, tapi unit yang dipakai bukan yang bisa di-link secara statis.
+exec_t_unit_not_smart_linkable_switch_to_static=09024_T_unit $1 tidak bisa di-link smart, beralih ke linking statis
+% Smart linking diminta, tapi unit yang dipakai bukan yang bisa di-link samart.
+exec_t_unit_not_shared_linkable_switch_to_static=09025_T_unit $1 tidak bisa di-link berbagi, berlaih ke linking statis
+% Link berbagi yang diminta, tapi unit yang dipakai bukan yang bisa berbagi link.
+exec_e_unit_not_smart_or_static_linkable=09026_E_unit $1 tidak bisa di-link smart atau statis
+% Link smart atau statis diminta, tapi unit yang dipakai tidak bisa digunakan untuk keduanya.
+exec_e_unit_not_shared_or_static_linkable=09027_E_unit $1 tidak bisa di-link berbagi ataupun statis
+% Link berbagi atau statis yang diminta, tapi unit bukan yang bisa melakukan keduanya.
+exec_d_resbin_params=09028_D_Memanggil kompilator resource "$1" dengan "$2" sebagai baris perintah
+% Pesan informasional yang menampilkan baris perintah mana yang dipakai untuk kompilator resource.
+%\end{description}
+# EndOfTeX
+
+#
+# Informasi Executable
+#
+# BeginOfTeX
+% \section{Pesan informasi executable.}
+% Seksi ini mendaftarkan semua pesan yang dikeluarkan kompilator saat program
+% executable dihasilkan, dan hanya ketika linker internal yang dipakai.
+% \begin{description}
+execinfo_f_cant_process_executable=09128_F_Tidak dapat memproses akhir executable $1
+% Kesalahan fatal saat kompilator tidak bisa memproses akhir sebuah executable.
+execinfo_f_cant_open_executable=09129_F_Tidak bisa membuka executable $1
+% Kesalahan fatal saat kompilator tidak bisa membuka file untuk executable.
+execinfo_x_codesize=09130_X_Besar Kode: $1 byte
+% Pesan informasional yang menampilkan ukuran seksi kode yang dihasilkan.
+execinfo_x_initdatasize=09131_X_Besar data diinisialisasi: $1 byte
+% Pesan informasional yang menampilkan ukuran seksi data diinisialisasi.
+execinfo_x_uninitdatasize=09132_X_Besar data tidak diinisialisasi: $1 byte
+% Pesan informasional yang menampilkan ukuran seksi data yang tidak diinisialisasi.
+execinfo_x_stackreserve=09133_X_Ruang stack terpakai: $1 byte
+% Pesan informasional yang menampilkan ukuran stack yang dipakai kompilator untuk executable.
+execinfo_x_stackcommit=09134_X_Ruang stack dikomit: $1 byte
+% Pesan informasional yang menampilkan ukuran stack yang dikomit oleh kompilator untuk executable.
+%\end{description}
+# EndOfTeX
+
+#
+# Pengambilan Unit
+#
+# 10041 is the last used one
+#
+# BeginOfTeX
+% \section{Pesan pengambilan unit.}
+% Seksi ini mendaftarkan semua pesan yang dapat terjadi saat kompilator
+% menggambil unit dari disk ke dalam memori. Banyak dari pesan ini berupa
+% pesan informasional.
+% \begin{description}
+unit_t_unitsearch=10000_T_Pencarian unit: $1
+% Ketika anda menggunakan saklar \var{-vt}, kompilator memberitahu anda ke mana
+% ia mencoba mencari file unit.
+unit_t_ppu_loading=10001_T_Pengambilan PPU $1
+% Saat saklar \var{-vt} dipakai, kompilator memberitahu anda
+% unit apa yang diambil.
+unit_u_ppu_name=10002_U_Nama PPU: $1
+% Saat anda menggunakan flag \var{-vu}, nama unit ditampilkan.
+unit_u_ppu_flags=10003_U_Flag PPU: $1
+% Saat anda menggunakan flag \var{-vu}, flag unit ditampilkan.
+unit_u_ppu_crc=10004_U_Crc PPU: $1
+% Saat anda memakai flag \var{-vu}, pemeriksaan CRC unit ditampilkan.
+unit_u_ppu_time=10005_U_Waktu PPU: $1
+% Saat anda memakai flag \var{-vu}, waktu unit dikompilasi ditampilkan.
+unit_u_ppu_file_too_short=10006_U_File PPU terlalu pendek
+% File ppu terlalu pendek, tidak semua deklarasi ada di sana.
+unit_u_ppu_invalid_header=10007_U_Header PPU tidak benar (tanpa PPU di awal)
+% File unit berisi tiga byte pertama kode ascii \var{PPU}
+unit_u_ppu_invalid_version=10008_U_Versi PPU tidak benar $1
+% File unit ini dikompilasi dengan versi kompilator berbeda, dan
+% tidak bisa dibaca.
+unit_u_ppu_invalid_processor=10009_U_PPU dikompilasi untuk prosesor lain
+% File unit dikompilasi untuk tipe prosesor berbeda, dan
+% tidak bisa dibaca
+unit_u_ppu_invalid_target=10010_U_PPU dikompilasi untuk target lain
+% File unit dikompilasi untuk target berbeda, dan
+% tidak bisa dibaca
+unit_u_ppu_source=10011_U_Sumber PPU: $1
+% Saat anda memakai flag \var{-vu}, nama file sumber ditampilkan.
+unit_u_ppu_write=10012_U_Menuliskan $1
+% Saat anda menetapkan saklar \var{-vu}, kompilator akan memberitahu anda
+% di mana ia menulis file unit.
+unit_f_ppu_cannot_write=10013_F_Tidak bisa Menulis File-PPU
+% Kesalahan terjadi saat menuliskan file unit.
+unit_f_ppu_read_error=10014_F_Kesalahan membaca File-PPU
+% Ini berarti bahwa file unit sudah rusak, dan berisi informasi tidak benar.
+% Diperlukan rekompilasi.
+unit_f_ppu_read_unexpected_end=10015_F_akhir File-PPU diharapkan
+% Akhir file tidak diharapkan. Ini berarti bahwa file PPU
+% rusak.
+unit_f_ppu_invalid_entry=10016_F_Entri File-PPU tidak benar: $1
+% Unit yang coba dibaca kompilator rusak, atau dibuat dengan versi
+% kompilator lebih baru.
+unit_f_ppu_dbx_count_problem=10017_F_Masalah jumlah PPU Dbx
+% Ada ketidak konsistenan dalam informasi debug pada unit.
+unit_e_illegal_unit_name=10018_E_Nama unit tidak benar: $1
+% Nama unit tidak sama dengan nama file.
+unit_f_too_much_units=10019_F_Terlalu banyak unit
+% \fpc mempunyai batasan 1024 unit dalam sebuah program. Anda dapat mengubah
+% perliaku ini dengan mengubah konstan \var{maxunits} dalam file \file{fmodule.pas}
+% pada kompilator, dan mengompilasi ulang kompilator.
+unit_f_circular_unit_reference=10020_F_Referensi unit berputar antara $1 dan $2
+% Dua unit saling menggunakan bagian interface. Ini hanya dibolehkan dalam
+% bagian \var{implementation}. Setidaknya satu unit harus berisi satu yang
+% lain dalam seksi \var{implementation}.
+unit_f_cant_compile_unit=10021_F_Tidak bisa mengompilasi unit $1, tidak ada sumber tersedia
+% Unit ditemukan yang memerlukan kompilasi ulang, tapi tidak ada file sumber
+% yang tersedia.
+unit_f_cant_find_ppu=10022_F_Tidak bisa menemukan unit $1 yang dipakai oleh $2
+% Anda mencoba untuk memakai sebuah unit di mana file PPU tidak ditemukan oleh
+% kompilator. Periksas file konfigurasi anda untuk path unit
+unit_w_unit_name_error=10023_W_Unit $1 tidak ditemukan tapi $2 ada
+% Pesan kesalahan ini tidak dipakai lagi.
+unit_f_unit_name_error=10024_F_Unit $1 dicari tapi $2 yang ditemukan
+% Pemotongan Dos pada 8 huruf untuk file unit PPU dapat membawa
+% masalah saat nama unit lebih panjang dari 8 huruf.
+unit_w_switch_us_missed=10025_W_Mengompilasi unit sistem memerlukan saklar -Us
+% Ketika mengompilasi ulang unit sistem (ia memerlukan perlakuan khusus),
+% \var{-Us} harus ditetapkan.
+unit_f_errors_in_unit=10026_F_Ada $1 kesalahan dalam mengompilasi modul, dihentikan
+% Saat kompilator menemukan sebuah kesalahan fatal atau terlalu banyak kesalahan
+% dalam sebuah modul maka ia berhenti dengan pesan ini.
+unit_u_load_unit=10027_U_Diambil dari $1 ($2) unit $3
+% Saat anda memakai flag \var{-vu}, yang mana unit diambil dari unit itu
+% ditampilkan.
+unit_u_recompile_crc_change=10028_U_Rekompilasi $1, checksum berubah untuk $2
+% Unit dikompilasi ulang karena checksum unit di mana ia bergantung padanya
+% sudah berubah.
+unit_u_recompile_source_found_alone=10029_U_Rekompilasi $1, hanya ditemukan sumber
+% Saat anda menggunakan flag \var{-vu}, pesan ini memberitahu anda mengapa
+% unit saat ini dikompilasi ulang.
+unit_u_recompile_staticlib_is_older=10030_U_Rekompilasi unit, lib statis lebih lama dari ppufile
+% Saat anda menggunakan flag \var{-vu}, kompilator memperingatkan bila unit
+% librari statis lebih lama dari file unit itu sendiri.
+unit_u_recompile_sharedlib_is_older=10031_U_Rekompilasi unit, lib berbagi lebih lama dari ppufile
+% Saat anda menggunakan flag \var{-vu}, kompilator memperingatkan bila unit
+% librari berbagi lebih lama dari file unit itu sendiri.
+unit_u_recompile_obj_and_asm_older=10032_U_Rekompilasi unit, obj dan asm lebih lama dari ppufile
+% Saat anda menggunakan flag \var{-vu}, kompilator memperingatkan bila assembler
+% atau file obyek pada unit lebih lama dari file unit itu sendiri.
+unit_u_recompile_obj_older_than_asm=10033_U_Rekompilasi unit, obj lebih lama dari asm
+% Saat anda menggunakan flag \var{-vu}, kompilator memperingatkan bila file
+% assembler pada unit lebih lama dari file obyek dalam unit.
+unit_u_parsing_interface=10034_U_Menguraikan interface pada $1
+% Saat anda menggunakan flag \var{-vu}, kompilator memperingatkan bahwa ia
+% mulai menguraikan bagian interface pada unit
+unit_u_parsing_implementation=10035_U_Menguraikan implementation pada $1
+% Saat anda menggunakan flag \var{-vu}, kompilator memperingatkan bahwa ia
+% mulai menguraikan bagian implementation pada unit
+unit_u_second_load_unit=10036_U_Pengambilan kedua untuk unit $1
+% Saat anda menggunakan flag \var{-vu}, kompilator memperingatkan bahwa ia
+% mulai mengompilasi ulang unit untuk kedua kali. Ini dapat terjadi dengan
+% unit interdependensi.
+unit_u_check_time=10037_U_Pemeriksaan file PPU $1 waktu $2
+% Saat anda menggunakan flag \var{-vu}, kompilator menampilkan nama file dan
+% tanggal serta waktu rekompilasi file diandalkan
+### Dua pesan kesalahan berikut saat ini dimatikan.
+#unit_h_cond_not_set_in_last_compile=10038_H_Kondisional $1 tidak disetel di awal dalam kompilasi terkahir $2
+#% Saat rekompilasi unit diperlukan, kompilator akan memeriksa kondisional
+#% yang sama yang disetel untuk rekompilasi. Kompilator sudah menemukan
+#% kondisional yang saat ini didefinisikan, tapi tidak dipakai terakhir kali
+#% unit direkompilasi.
+#unit_h_cond_set_in_last_compile=10039_H_Kondisional $1 disetel di awal dalam kompilasi terakhir $2
+#% Saat rekompilasi unit memerlukan kompilator memeriksa bahwa kondisional
+#% yang sama disetel untuk rekompilasi. Kompilator sudah menemukan sebuah
+#% kondisional yang dipakai terakhir kali unit dikompilasi, tetapi
+#% kondisional saat ini tidak didefinisikan.
+unit_w_cant_compile_unit_with_changed_incfile=10040_W_Tidak bisa merekompilasi unit $1, tapi ditemukan file include yang dimodifikasi
+% Sebuah unit ditemukan di mana file include sudah diubah, tapi
+% beberapa file sumber tidak ditemukan, maka rekompilasi tidak memungkinkan.
+unit_u_source_modified=10041_U_File $1 lebih baru daripada file PPU $2
+% File sumber dimodifikasi untuk unit yang ditemukan kompilator.
+unit_u_ppu_invalid_fpumode=10042_U_Mencoba menggunakan unit yang dikompilasi dengan mode FPU berbeda
+% Mencoba untuk mengompilasi kode sementara menggunakan unit yang tidak
+% dikompilasi dengan mode format pecahan yang sama. Baik semua kode harus
+% dikompilasi dengan emulasi FPU on ataupun dengan emulasi FPU off.
+unit_u_loading_interface_units=10043_U_Mengambil unit interface dari $1
+% Saat anda menggunakan flag \var{-vu}, kompilator meperingatkan bahwa ia
+% mulai mengambil unit yang didefinisikan dalam bagian interface pada unit.
+unit_u_loading_implementation_units=10044_U_Mengambil implementation unit dari $1
+% Saat anda menggunakan flag \var{-vu}, kompilator meperingatkan bahwa ia
+% mulai mengambil unit yang didefinisikan dalam bagian implementation pada unit.
+unit_u_interface_crc_changed=10045_U_CRC Interface berubah untuk unit $1
+% Saat anda menggunakan flag \var{-vu}, kompilator meperingatkan bahwa
+% CRC yang dihitung untuk interface sudah berubah setelah interface
+% diuraikan.
+unit_u_implementation_crc_changed=10046_U_CRC Implementation berubah untuk unit $1
+% Saat anda menggunakan flag \var{-vu}, kompilator meperingatkan bahwa
+% CRC yang dihitung sudah diubah setelah implementation
+% diuraikan.
+unit_u_finished_compiling=10047_U_Selesai mengompilasi unit $1
+% Saat anda menggunakan flag \var{-vu}, kompilator meperingatkan bahwa ia
+% selesai mengompilasi unit.
+unit_u_add_depend_to=10048_U_Menambah dependensi $1 ke $2
+% Saat anda menggunakan flag \var{-vu}, kompilator meperingatkan bahwa ia
+% sudah menambahkan dependensi antara dua unit.
+unit_u_no_reload_is_caller=10049_U_Tidak mengambil ulang, pemanggil: $1
+% Saat anda menggunakan flag \var{-vu}, kompilator meperingatkan bahwa ia
+% tidak akan mengambil ulang unit karena ia adalah unit yang ingin
+% mengambil unit ini
+unit_u_no_reload_in_second_compile=10050_U_No reload, already in second compile: $1
+% Saat anda menggunakan flag \var{-vu}, kompilator meperingatkan bahwa ia
+% tidak akan mengambil ulang unit karena sudah dalam rekompilasi kedua
+unit_u_flag_for_reload=10051_U_Flag untuk mengambil ulang: $1
+% Saat anda menggunakan flag \var{-vu}, kompilator meperingatkan bahwa ia
+% harus mengambil ulang unit
+unit_u_forced_reload=10052_U_Pemaksaan pengambilan ulang
+% Saat anda menggunakan flag \var{-vu}, kompilator meperingatkan bahwa ia
+% mengambil ulang unit karen unit diperlukan
+unit_u_previous_state=10053_U_Keadaan $1 sebelumnya: $2
+% Saat anda menggunakan flag \var{-vu}, kompilator menampilkan
+% keadaan unit sebelumnya
+unit_u_second_compile_unit=10054_U_Sudah mengompilasi $1, menyetel kompilasi kedua
+% Saat anda menggunakan flag \var{-vu}, kompilator meperingatkan bahwa ia
+% mulai mengompilasi ulang unit untuk kedua kali. Ini bisa terjadi dengan
+% unit interdependensi.
+unit_u_loading_unit=10055_U_Mengambil unit $1
+% Saat anda menggunakan flag \var{-vu}, kompilator meperingatkan bahwa ia
+% mulai mengambil unit.
+unit_u_finished_loading_unit=10056_U_Selesai mengambil unit $1
+% Saat anda menggunakan flag \var{-vu}, kompilator meperingatkan bahwa ia
+% selesai mengambil unit.
+unit_u_registering_new_unit=10057_U_Mendaftarkan unit baru $1
+% Saat anda menggunakan flag \var{-vu}, kompilator meperingatkan bahwa ia
+% telah menemukan unit baru dan mendaftarkannya dalam daftar internal.
+unit_u_reresolving_unit=10058_U_Memecahkan ulang unit $1
+% Saat anda menggunakan flag \var{-vu}, kompilator meperingatkan bahwa ia
+% harus menghitung ulang data internal pada unit
+unit_u_skipping_reresolving_unit=10059_U_Melewati pemecahan ulang unit $1, masih mengambil unit yang dipakai
+% Saat anda menggunakan flag \var{-vu}, kompilator memperingatkan bahwa ia
+% mulai melewati untuk menghitung ulang data internal pada unit karena di sana
+% tidak ada data untuk dihitung ulang
+% \end{description}
+# EndOfTeX
+
+#
+# Opsi
+#
+# 11041 is the last used one
+#
+option_usage=11000_O_$1 [opsi] <inputfile> [opsi]
+# BeginOfTeX
+%
+% \section{Kesaslahan penanganan baris perintah}
+% Seksi ini mendaftarkan kesalahan yang terjadi saat kompilator memproses
+% baris perintah atau menangani file konfigurasi.
+% \begin{description}
+option_only_one_source_support=11001_W_Hanya satu file sumber didukung
+% Anda dapat menetapkan hanya satu file sumber pada baris perintah. Yang
+% pertama akan dikompilasi, yang lainnya akan diabaikan. Ini menunjukan bahwa
+% anda melupakan tanda \var{'-'}.
+option_def_only_for_os2=11002_W_File DEF hanya dapat dibuat untuk OS/2
+% Opsi ini hanya ditetapkan ketika anda mengompilasi untuk OS/2
+option_no_nested_response_file=11003_E_File respon berulang tidak didukung
+% Anda tidak bisa mengulang file respon dengan opsi baris perintah \var{@file}.
+option_no_source_found=11004_F_Nama file sumber tidak ada dalam baris perintah
+% Kompilator mengharapkan nama file sumber pada baris perintah.
+option_no_option_found=11005_N_Tidak ada opsi di dalam file konfig $1
+% Kompilator tidak menemukan setiap opsi dalam file konfig.
+option_illegal_para=11006_E_Parameter tidak benar: $1
+% Anda menetapkan opsi yang tidak dikenal.
+option_help_pages_para=11007_H_-? menulis halaman bantuan
+% Ketika sebuah opsi tidak dikenal diberikan, pesan ini ditampilkan.
+option_too_many_cfg_files=11008_F_Terlalu banyak file konfig yang diulang
+% Anda hanya bisa mengulang sampai 16 file konfigurasi.
+option_unable_open_file=11009_F_Tidak bisa membuka file $1
+% File opsi tidak bisa ditemukan.
+option_reading_further_from=11010_D_Membaca opsi lanjutan dari $1
+% Ditampilkan saat anda menghidupkan catatan, dan kompilator beralih ke
+% file opsi lain.
+option_target_is_already_set=11011_W_Target sudah disetel ke: $1
+% Ditampilkan jika lebih dari satu opsi \var{-T} ditetapkan.
+option_no_shared_lib_under_dos=11012_W_Libs berbagi tidak didukung pada DOS platform, membalikan ke statis
+% Jika anda menetapkan \var{-CD} untuk platform \dos, pesan ini ditampilkan.
+% Kompilator hanya mendukung libari statis di bawah \dos
+option_too_many_ifdef=11013_F_terlalu banyak IF(N)DEF
+% Pernyataan \var{\#IF(N)DEF} dalam file opsi tidak seimbang dengan pernyataan
+% \var{\#ENDIF}.
+option_too_many_endif=11014_F_terlalu banyak ENDIF
+% Pernyataan \var{\#IF(N)DEF} dalam file opsi tidak seimbang dengan pernyataan
+% \var{\#ENDIF}.
+option_too_less_endif=11015_F_Kondisional terbuka di akhir file
+% Pernyataan \var{\#IF(N)DEF} dalam file opsi tidak seimbang dengan pernyataan
+% \var{\#ENDIF}.
+option_no_debug_support=11016_W_Pembuatan informasi debug tidak didukung oleh executable ini
+% Dimungkinkan untuk memiliki executable kompilator yang tidak mendukung
+% pembuatan info debug. Jika anda menggunakan executable seperti itu dengan
+% saklar \var{-g}, peringatan ini akan ditampilkan.
+option_no_debug_support_recompile_fpc=11017_H_Coba rekompilasi dengan -dGDB
+% Dimungkinkan untuk memiliki executable kompilator yang tidak mendukung
+% pembuatan info debug. Jika anda menggunakan executable seperti itu dengan
+% saklar \var{-g}, peringatan ini akan ditampilkan.
+option_obsolete_switch=11018_W_Anda menggunakan saklar tidak terpakai $1
+% Ini memperingatkan anda saat anda menggunakan saklar yang tidak diperlukan/didukung lagi.
+% Direkomendasikan bahwa anda menghapus saklar untuk menghindari masalah di masa
+% mendatang, saat saklar mungkin diubah.
+option_obsolete_switch_use_new=11019_W_Anda menggunakan saklar tidak terpakai $1, silahkan pakai $2
+% Ini memperingatkan anda saat anda memakai saklar yang tidak didukung lagi.
+% sekarang sebaliknya anda harus menggunakan saklar kedua.
+% Direkomendasikan bahwa anda menghapus saklar untuk menghindari masalah di masa
+% mendatang, saat saklar mungkin diubah.
+option_switch_bin_to_src_assembler=11020_N_Beralih assembler ke penulisan sumber assembler standar
+% Ini memberitahu anda bahwa assembler sudah diubah karena anda menggunakan
+% saklar -a yang tidak bisa dipakai dengan penulis assembler biner.
+option_incompatible_asm=11021_W_Output assembler yang dipilih "$1" tidak kompatibel dengan "$2"
+option_asm_forced=11022_W_"$1" assembler dipaksa dipakai
+% Output assembler yang dipilih tidak dapat menghasilkan
+% file obyek dengan format yang benar. Oleh karena itu, sebaliknya
+% assembler standar untuk target ini digunakan.
+option_using_file=11026_T_Membaca opsi dari file $1
+% Opsi juga dibaca dari file ini
+option_using_env=11027_T_Membaca opsi dari lingkungan $1
+% Opsi juga dibaca dari string lingkungan ini
+option_handling_option=11028_D_Menangani opsi "$1"
+% Info debug yang opsinya ditemukan akan ditangani
+option_help_press_enter=11029__*** tekan enter ***
+option_start_reading_configfile=11030_H_Mulai membaca file konfigurasi $1
+% Memulai penguraian file konfigurasi.
+option_end_reading_configfile=11031_H_Akhir pembacaan file konfigurasi $1
+% Akhir penguraian file konfigurasi.
+option_interpreting_option=11032_D_menginterpretasikan opsi "$1"
+option_interpreting_firstpass_option=11036_D_menginterpretasikan operan opsi pertama "$1"
+option_interpreting_file_option=11033_D_menginterpretasikan opsi file "$1"
+option_read_config_file=11034_D_Membaca file konfigurasi "$1"
+option_found_file=11035_D_ditemukan nama file sumber "$1"
+% Info tambahan mengenai opsi, ditampilkan saat anda menghidupkan opsi
+% debug.
+option_code_page_not_available=11039_E_Halaman kode tidak dikenal
+option_config_is_dir=11040_F_File konfigurasi $1 adalah sebuah direktori
+% Direktori tidak bisa dipakai sebagai file konfigurasi.
+option_confict_asm_debug=11041_W_Output assembler yang dipilih "$1" tidak bisa menghasilkan info debug, debugging dimatikan
+% Output assembler yang dipilih tidak dapat membuat informasi debug,
+% oleh karenanya opsi debug dimatikan.
+%\end{description}
+# EndOfTeX
+
+#
+# Logo (option -l)
+#
+option_logo=11023_[
+Free Pascal Compiler versi $FPCFULLVERSION [$FPCDATE] untuk $FPCCPU
+Hak Cipta (c) 1993-2011 oleh Florian Klaempfl
+]
+
+#
+# Info (option -i)
+#
+option_info=11024_[
+Free Pascal Compiler versi $FPCVERSION
+
+Tanggal Kompilator : $FPCDATE
+Target CPU Kompilator: $FPCCPU
+
+Target didukung:
+ $OSTARGETS
+
+Set instruksi CPU didukung:
+ $INSTRUCTIONSETS
+
+Set instruksi FPU didukung:
+ $FPUINSTRUCTIONSETS
+
+Optimasi Didukung:
+ $OPTIMIZATIONS
+
+Program ini datang bersama GNU General Public Licence
+Untuk informasi lebih jauh baca COPYING.FPC
+
+Laporkan bugs, saran, dll ke:
+ http://bugs.freepascal.org
+atau
+ bugs@freepascal.org
+]
+
+#
+# Halaman bantuan (opsi -? dan -h)
+#
+# Karakter pertama pada baris menunjukan siapa yang akan menampilkan baris
+# ini, kemungkinan saat ini ialah :
+# * = setiap target
+# 3 = 80x86 target
+# 6 = 680x0 target
+# e = hanya dalam mode debug diperluas
+# P = PowerPC target
+# S = Sparc target
+# V = Target mesin virtual
+# Karakter kedua juga menunjukan siapa yang akan menampilkan baris ini,
+# (jika karakter di atas adalah BENAR) kemungkinan saat ini ialah :
+# * = setiap orang
+# g = dengan info GDB yang didukung oleh kompilator
+# O = OS/2
+# L = Sistem UNIX
+# Karakter ketiga mewakili tingkat indentasi.
+#
+option_help_pages=11025_[
+**0*_Tambah + setelah opsi saklar boolean untuk menghidupkannya, - untuk mematikan
+**1a_Kompilator tidak menghapus file assembler yang dibuat
+**2al_Daftarkan baris kode sumber dalam file assembler
+**2an_Daftarkan info node dalam file assembler
+*L2ap_Gunakan pipa daripada pembuatan file assembler sementara
+**2ar_Daftarkan info alokasi/pelepasan register dalam file assembler
+**2at_Daftarkan info alokasi/pelepasan temp dalam file assembler
+**1A<x>_Format output:
+**2Adefault_Gunakan assembler standar
+3*2Aas_Assemble menggunakan GNU AS
+3*2Anasmcoff_File COFF (Go32v2) menggunakan Nasm
+3*2Anasmelf_File ELF32 (Linux) menggunakan Nasm
+3*2Anasmwin32_File obyek Win32 menggunakan Nasm
+3*2Anasmwdosx_File obyek Win32/WDOSX menggunakan Nasm
+3*2Awasm_File Obj menggunakan Wasm (Watcom)
+3*2Anasmobj_File Obj menggunakan Nasm
+3*2Amasm_File Obj menggunakan Masm (Microsoft)
+3*2Atasm_File Obj menggunakan Tasm (Borland)
+3*2Aelf_ELF (Linux) menggunakan penulis internal
+3*2Acoff_COFF (Go32v2) menggunakan penulis internal
+3*2Apecoff_PE-COFF (Win32) menggunakan penulis internal
+4*2Aas_Rangkai menggunakan GNU AS
+6*2Aas_File-0 Unix menggunakan GNU AS
+6*2Agas_GNU Motorola assembler
+6*2Amit_Sintaks MIT (GAS lama)
+6*2Amot_Standard Motorola assembler
+A*2Aas_Rangkai menggunakan GNU AS
+P*2Aas_Rangkai menggunakan GNU AS
+S*2Aas_Rangkai menggunakan GNU AS
+**1b_Hasilkan info browser
+**2bl_Hasilkan info simbol lokal
+**1B_Bangun seluruh modul
+**1C<x>_Opsi pembuatan kode:
+**2Cc<x>_Setel konvensi pemanggilan standar ke <x>
+**2CD_Buat juga librari dinamis (tidak didukung)
+**2Ce_Kompilasi dengan opcode pecahan diemulasikan
+**2Cf<x>_Pilih set instruksi fpu yang dipakai, lihat fpc -i untuk nilai yang mungkin
+**2CF<x>_Minimal presisi konstan pecahan (standar, 32, 64)
+**2Cg_Hasilkan kode PIC
+**2Ch<n>_<n> byte heap (antara 1023 dan 67107840)
+**2Ci_Pemeriksaan-IO
+**2Cn_Abaikan tahap linking
+**2Co_Periksa kelebihan untuk operasi integer
+**2Cp<x>_Pilih set instruksi, lihat fpc -i untuk nilai yang mungkin
+**2CP<x>=<y>_ setelan pemadatan
+**3CPPACKSET=<y>_ <y> setel alokasi: 0, 1 atau DEFAULT atau NORMAL, 2, 4 dan 8
+**2Cr_Pemeriksaan jangkauan
+**2CR_Verifikasi kebenaran pemanggilan metode obyek
+**2Cs<n>_Setel besar stack menjadi <n>
+**2Ct_Pemeriksaan stack
+**2CX_Buat juga librari smartlinked
+**1d<x>_Definisikan simbol <x>
+**1D_Hasilkan file DEF
+**2Dd<x>_Setel deskripsi menjadi <x>
+**2Dv<x>_Setel versi DLL menjadi <x>
+*O2Dw_Aplikasi PM
+**1e<x>_Setel path ke executable
+**1E_Sama seperti -Cn
+**1fPIC_Sama seperti -Cg
+**1F<x>_Setel nama file dan path:
+**2Fa<x>[,y]_(untuk sebuah program) ambil unit <x> dan [y] sebelum uses diuraikan
+**2Fc<x>_Setel input codepage menjadi <x>
+**2FC<x>_Setel nama biner kompilator RC menjadi <x>
+**2FD<x>_Setel direktori ke mana untuk menjcari utilitas kompilator
+**2Fe<x>_Alihkan output kesalahan ke <x>
+**2Ff<x>_Tambah <x> ke path kerangka kerja (hanya Darwin)
+**2FE<x>_Setel path output exe/unit ke <x>
+**2Fi<x>_Tambah <x> ke path include
+**2Fl<x>_Tambah <x> ke path librari
+**2FL<x>_Gunakan <x> sebagai linker dinamis
+**2Fm<x>_Ambil tabel konversi unicode dari <x>.txt dalam dir kompilator
+**2Fo<x>_Tambah <x> ke path obyek
+**2Fr<x>_Ambil file pesan kesalahan <x>
+**2FR<x>_Setel linker resource (.res) ke <x>
+**2Fu<x>_Tambah <x> ke path unit
+**2FU<x>_Setel path output unit ke <x>, ganti -FE
+*g1g_Hasilkan informasi debug (format standar untuk target)
+*g2gc_Hasilkan pemeriksaan untuk pointer
+*g2gh_Gunakan unit heaptrace (untuk men-debug kebocoran/kerusakan memori)
+*g2gl_Gunakan info baris unit (tampilkan info lebih lengkap dengan backtraces)
+*g2go<x>_Setel opsi informasi debug
+*g3godwarfsets_ Hidupkan informasi setelan debug Dwarf (pecahkan gdb < 6.5)
+*g2gp_Siapkan jenis huruf dalam nama simbol stabs
+*g2gs_Hasilkan informasi debug stabs
+*g2gt_Bersihkan variabel lokal (untuk mendeteksi uses tak terinisialisasi)
+*g2gv_Hasilkan program yang bisa dilacak oleh valgrind
+*g2gw_Hasilkan informasi debug dwarf-2 (sama seperti -gw2)
+*g2gw2_Hasilkan informasi debug dwarf-2
+*g2gw3_Hasilkan informasi debug dwarf-3
+**1i_Informasi
+**2iD_Kembalikan tanggal kompilator
+**2iV_Kembalikan versi pendek kompilator
+**2iW_Kembalikan versi lengkap kompilator
+**2iSO_Kemblikan OS kompilator
+**2iSP_Kembalikan prosesor host kompilator
+**2iTO_Kembalikan OS target
+**2iTP_Kembalikan prosesor target
+**1I<x>_Tambah <x> ke path include
+**1k<x>_Operkan <x> ke linker
+**1l_Tulis logo
+**1M<x>_Setel mode bahasa menjadi <x>
+**2Mfpc_Dialek Free Pascal (standar)
+**2Mobjfpc_Mode FPC dengan dukungan Obyek Pascal
+**2Mdelphi_Mode kompatibilitas Delphi 7
+**2Mtp_Mode kompatibilitas TP/BP 7.0
+**2Mmacpas_Mode kompatibilitas dialek Macintosh Pascal
+**1n_Jangan baca file konfigurasi standar
+**1N<x>_Optimasi susunan node
+**2Nu_Jangan gulung pengulangan
+**1o<x>_Ubah nama executable yang dihasilkan ke <x>
+**1O<x>_Optimasi:
+**2O-_Matikan optimasi
+**2O1_Optimasi tingkat 1 (cepat dan ramah debugger)
+**2O2_Optimasi tingkat 2 (-O1 + optimasi cepat)
+**2O3_Optimasi tingkat 3 (-O2 + optimasi lambat)
+**2Oa<x>=<y>_Setel penjajaran
+**2Oo[NO]<x>_Hidupkan atau matikan optimasi, lihat fpc -i untuk nilai yang mungkin
+**2Op<x>_Setel cpu target untuk optimasi, lihat fpc -i untuk nilai yang mungkin
+**2Os_Optimasi untuk ukuran daripada kecepatan
+**1pg_Hasilkan kode profil untuk gprof (definisikan FPC_PROFILE)
+**1R<x>_Gaya pembacaan assembler:
+**2Rdefault_Gunakan assembler standar untuk target
+3*2Ratt_Baca gaya assembler AT&T
+3*2Rintel_Baca gaya assembler Intel
+6*2RMOT_Baca gaya assembler Motorola
+**1S<x>_Opsi sintaks:
+**2S2_Sama seperti -Mobjfpc
+**2Sc_Dukung operator seperti C (*=,+=,/= and -=)
+**2Sa_Hidupkan assertions
+**2Sd_Sama seperti -Mdelphi
+**2Se<x>_Opsi kesalahan. <x> adalah kombinasi dari yang berikut:
+**3*_<n> : Kompilator batal setelah <n> kesalahan (standarnya 1)
+**3*_w : Kompilator juga batal setelah peringatan
+**3*_n : Kompilator juga batal setelah catatan
+**3*_h : Kompilator juga batal setelah petunjuk
+**2Sg_Hidupkan LABEL dan GOTO (standar dalam -Mtp dan -Mdelphi)
+**2Sh_Gunakan ansistrings secara standar daripada shortstrings
+**2Si_Hidupkan inlining procedures/functions yang dideklarisak sebagai "inline"
+**2Sk_Ambil unit fpcylix
+**2SI<x>_Setel gaya antarmuka ke <x>
+**3SIcom_Antarmuka kompatibel COM (standar)
+**3SIcorba_Antarmuka kompatibel CORBA
+**2Sm_Dukung makro seperti C (global)
+**2So_Sama seperti -Mtp
+**2Ss_Nama konstruktor harus init (destruktor harus done)
+**2Sx_Hidupkan kata kunci exception (standar dalam mode Delphi/ObjFPC)
+**1s_Jangan panggil assembler dan linker
+**2sh_Hasilkan naskah untuk me-link pada host
+**2st_Hasilkan naskah untuk me-link pada target
+**2sr_Lewati tahap alokasi register (gunakan dengan -alr)
+**1T<x>_Sistem operasi target:
+3*2Temx_OS/2 via EMX (termasuk EMX/RSX extender)
+3*2Tfreebsd_FreeBSD
+3*2Tgo32v2_Versi 2 pada DJ Delorie DOS extender
+3*2Tlinux_Linux
+3*2Tnetbsd_NetBSD
+3*2Tnetware_Novell Netware Module (clib)
+3*2Tnetwlibc_Novell Netware Module (libc)
+3*2Topenbsd_OpenBSD
+3*2Tos2_OS/2 / eComStation
+3*2Tsunos_SunOS/Solaris
+3*2Twatcom_Watcom kompatibel DOS extender
+3*2Twdosx_WDOSX DOS extender
+3*2Twin32_Windows 32 Bit
+3*2Twince_Windows CE
+4*2Tlinux_Linux
+6*2Tamiga_Commodore Amiga
+6*2Tatari_Atari ST/STe/TT
+6*2Tlinux_Linux/m68k
+6*2Tmacos_Macintosh m68k (tidak didukung)
+6*2Tpalmos_PalmOS
+A*2Tlinux_Linux
+A*2Twince_Windows CE
+P*2Tamiga_AmigaOS pada PowerPC
+P*2Tdarwin_Darwin dan Mac OS X pada PowerPC
+P*2Tlinux_Linux pada PowerPC
+P*2Tmacos_Mac OS (klasik) pada PowerPC
+P*2Tmorphos_MorphOS
+S*2Tlinux_Linux
+**1u<x>_Simbol tidak didefinisikan <x>
+**1U_Opsi unit:
+**2Un_Jangan periksa di mana nama unit sama dengan nama file
+**2Ur_Hasilkan file unit rilis (jangan dikompilasi secara otomatis)
+**2Us_Kompilasi unit sistem
+**1v<x>_Ditampilkan. <x> adalah kombinasi dari huruf berikut:
+**2*_e : Tampilkan kesalahan (default) 0 : Jangan tampilkan (kecuali kesalahan)
+**2*_w : Tampilkan peringatan u : Tampilkan info unit
+**2*_n : Tampilkan catatan t : Tampilkan file yang dicoba/dipakai
+**2*_h : Tampilkan petunjuk c : Tampilkan kondisional
+**2*_i : Tampilkan info umum d : Tampilkan info debug
+**2*_l : Tampilkan nomor baris r : Mode kompatibilitas Rhide/GCC
+**2*_a : Tampilkan semuanya x : Info executable (hanya Win32)
+**2*_b : Tulis pesan nama file dengan path lengkap
+**2*_v : Tulis fpcdebug.txt dengan p : Tulis tree.log dengan susunan urai
+**2*_ banyak info debug
+3*1W<x>_Opsi spesifik-target (target)
+A*1W<x>_Opsi spesifik-target (target)
+P*1W<x>_Opsi spesifik-target (target)
+3*2Wb_Buat sebuah bundel daripada sebuah librari (Darwin)
+P*2Wb_Buat sebuah bundel daripada sebuah librari (Darwin)
+p*2Wb_Buat sebuah bundel daripada sebuah librari (Darwin)
+3*2WB_Buat citra relokatabel (Windows)
+A*2WB_Buat citra relokatabel (Windows, Symbian)
+3*2WC_Tetapkan aplikasi tipe konsol (EMX, OS/2, Windows)
+A*2WC_Tetapkan aplikasi tipe konsol (Windows)
+P*2WC_Tetapkan aplikasi tipe konsol (Mac OS Klasik)
+3*2WD_Gunakan DEFFILE untuk mengekspor fungsi DLL atau EXE (Windows)
+A*2WD_Gunakan DEFFILE untuk mengekspor fungsi DLL atau EXE (Windows)
+3*2WF_Tetapkan aplikasi tipe layar-penuh (EMX, OS/2)
+3*2WG_Tetapkan aplikasi tipe grafis (EMX, OS/2, Windows)
+A*2WG_Tetapkan aplikasi tipe grafis (Windows)
+P*2WG_Tetapkan aplikasi tipe grafis (Classic Mac OS)
+3*2WN_Jangan hasilkan kode relokasi, diperlukan untuk debugging (Windows)
+A*2WN_Jangan hasilkan kode relokasi, diperlukan untuk debugging (Windows)
+3*2WR_Hasilkan kode relokasi (Windows)
+A*2WR_Hasilkan kode relokasi (Windows)
+P*2WT_Tetapkan aplikasi tipe piranti MPW (Mac OS Klasik)
+**1X_Opsi executable:
+**2Xc_Oper --shared/-dynamic ke linker (BeOS, Darwin, FreeBSD, Linux)
+**2Xd_Jangan gunakan path pencarian librari standar (diperlukan untuk kompilasi silang)
+**2Xe_Gunakan linker eksternal
+**2XD_Coba untuk me-link unit secara dinamis (definisikan FPC_LINK_DYNAMIC)
+**2Xi_Gunakan linker internal
+**2Xm_Hasilkan peta link
+**2XM<x>_Set nama rutin program 'main' (standarnya 'main')
+**2XP<x>_Awali nama binutils dengan prefiks <x>
+**2Xr<x>_Setel path pencarian librari ke <x> (diperlukan untuk kompilasi silang)
+**2Xs_Buang semua simbol dari executable
+**2XS_Coba untuk me-link unit secara statis (standar, definisikan FPC_LINK_STATIC)
+**2Xt_Link dengan librari statis (-static dioper ke linker)
+**2XX_Coba untuk smartlink unit (definisikan FPC_LINK_SMART)
+**1*_
+**1?_Tampilkan bantuan ini
+**1h_Tampilkan bantuan ini tanpa menunggu
+]
+
+#
+# The End...
diff --git a/closures/compiler/msg/erroriu.msg b/closures/compiler/msg/erroriu.msg
new file mode 100644
index 0000000000..217f99b022
--- /dev/null
+++ b/closures/compiler/msg/erroriu.msg
@@ -0,0 +1,3048 @@
+#
+# This file is part of the Free Pascal Compiler
+# Copyright (c) 1999-2009 by the Free Pascal Development team
+#
+# Italian Language File for Free Pascal
+# Contributed by Massimo Soricetti <notturno at quipo.it>
+# Translation for FPC 2.4.2, april 16, 2011, Tolentino, Italy
+#
+# See the file COPYING.FPC, included in this distribution,
+# for details about the copyright.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#
+#
+# The constants are build in the following order:
+# <part>_<type>_<txtidentifier>
+#
+# <part> is the part of the compiler the message is used
+# asmr_ assembler parsing
+# asmw_ assembler writing/binary writers
+# unit_ unit handling
+# scan_ scanner
+# parser_ parser
+# type_ type checking
+# general_ general info
+# exec_ calls to assembler, external linker, binder
+# link_ internal linker
+#
+# <type> the type of the message it should normally used for
+# f_ fatal error
+# e_ error
+# w_ warning
+# n_ note
+# h_ hint
+# i_ info
+# l_ add linenumber
+# u_ used
+# t_ tried
+# c_ conditional
+# d_ debug message
+# x_ executable informations
+# o_ normal (e.g., "press enter to continue")
+#
+
+#
+# General
+#
+# 01023 is the last used one
+#
+# BeginOfTeX
+% \section{General compiler messages}
+% This section gives the compiler messages which are not fatal, but which
+% display useful information. The number of such messages can be
+% controlled with the various verbosity level \var{-v} switches.
+% \begin{description}
+general_t_compilername=01000_T_Compilatore: $1
+% When the \var{-vt} switch is used, this line tells you what compiler
+% is used.
+general_d_sourceos=01001_D_Sistema operativo del compilatore: $1
+% When the \var{-vd} switch is used, this line tells you what the source
+% operating system is.
+general_i_targetos=01002_I_Sistema operativo di destinazione: $1
+% When the \var{-vd} switch is used, this line tells you what the target
+% operating system is.
+general_t_exepath=01003_T_Path degli eseguibili: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for its binaries.
+general_t_unitpath=01004_T_Path delle unit: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for compiled units. You can set this path with the \var{-Fu} option.
+general_t_includepath=01005_T_Path degli include: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for its include files (files used in \var{\{\$I xxx\}} statements).
+% You can set this path with the \var{-Fi} option.
+general_t_librarypath=01006_T_Path delle library: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for the libraries. You can set this path with the \var{-Fl} option.
+general_t_objectpath=01007_T_Path dei file oggetto: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for object files you link in (files used in \var{\{\$L xxx\}} statements).
+% You can set this path with the \var{-Fo} option.
+general_i_abslines_compiled=01008_I_$1 righe compilate, $2 sec $3 min
+% When the \var{-vi} switch is used, the compiler reports the number
+% of lines compiled, and the time it took to compile them (real time,
+% not program time).
+general_f_no_memory_left=01009_F_Memoria esaurita
+% The compiler doesn't have enough memory to compile your program. There are
+% several remedies for this:
+% \begin{itemize}
+% \item If you're using the build option of the compiler, try compiling the
+% different units manually.
+% \item If you're compiling a huge program, split it up into units, and compile
+% these separately.
+% \item If the previous two don't work, recompile the compiler with a bigger
+% heap. (You can use the \var{-Ch} option for this, \seeo{Ch}.)
+% \end{itemize}
+general_i_writingresourcefile=01010_I_Scrivo il file di risorse della stringtable: $1
+% This message is shown when the compiler writes the Resource String Table
+% file containing all the resource strings for a program.
+general_e_errorwritingresourcefile=01011_E_Scrivo il file di risorse della stringtable: $1
+% This message is shown when the compiler encounters an error when writing
+% the Resource String Table file.
+#
+#
+# La finestra dei messaggi di Lazarus filtra via tutto quello che non comincia
+# con uno di questi cinque prefissi in inglese (o meglio Lazarus versione 0.9.30 lo fa)
+# per cui, almeno per ora, ce li dobbiamo tenere :-(
+# Fanno eccezione 'Fatale' e 'Errore' perché sono identici alle versioni inglesi, ma più lunghi.
+#
+#
+general_i_fatal=01012_I_Fatale:
+% Prefix for Fatal Errors.
+general_i_error=01013_I_Errore:
+% Prefix for Errors.
+general_i_warning=01014_I_Warning:
+% Prefix for Warnings.
+general_i_note=01015_I_Note:
+% Prefix for Notes.
+general_i_hint=01016_I_Hint:
+% Prefix for Hints.
+general_e_path_does_not_exist=01017_E_Il path "$1" non esiste
+% The specified path does not exist.
+general_f_compilation_aborted=01018_F_Compilazione abortita
+% Compilation was aborted.
+general_text_bytes_code=01019_I_$1 byte di codice
+% The size of the generated executable code, in bytes.
+general_text_bytes_data=01020_I_$1 byte di dati
+% The size of the generated program data, in bytes.
+general_i_number_of_warnings=01021_I_$1 attenzioni date
+% Total number of warnings issued during compilation.
+general_i_number_of_hints=01022_I_$1 consigli dati
+% Total number of hints issued during compilation.
+general_i_number_of_notes=01023_I_$1 note date
+% Total number of notes issued during compilation.
+% \end{description}
+#
+# Scanner
+#
+# 02086 is the last used one
+#
+% \section{Scanner messages.}
+% This section lists the messages that the scanner emits. The scanner takes
+% care of the lexical structure of the pascal file, i.e. it tries to find
+% reserved words, strings, etc. It also takes care of directives and
+% conditional compilation handling.
+% \begin{description}
+scan_f_end_of_file=02000_F_Il file è terminato troppo presto
+% This typically happens in one of the following cases:
+% \begin{itemize}
+% \item The source file ends before the final \var{end.} statement. This
+% happens mostly when the \var{begin} and \var{end} statements aren't
+% balanced;
+% \item An include file ends in the middle of a statement.
+% \item A comment was not closed.
+% \end{itemize}
+scan_f_string_exceeds_line=02001_F_La stringa continua su più righe
+% There is a missing closing ' in a string, so it occupies
+% multiple lines.
+scan_f_illegal_char=02002_F_il carattere "$1" ($2) non è ammesso
+% An illegal character was encountered in the input file.
+scan_f_syn_expected=02003_F_Errore di sintassi: era atteso "$1" ma non "$2"
+% This indicates that the compiler expected a different token than
+% the one you typed. It can occur almost anywhere it is possible to make an error
+% against the Pascal language.
+scan_t_start_include_file=02004_TL_Inizio lettura del file include $1
+% When you provide the \var{-vt} switch, the compiler tells you
+% when it starts reading an included file.
+scan_w_comment_level=02005_W_Trovato commento di livello $1
+% When the \var{-vw} switch is used, then the compiler warns you if
+% it finds nested comments. Nested comments are not allowed in Turbo Pascal
+% and Delphi, and can be a possible source of errors.
+scan_n_ignored_switch=02008_N_Ignorato lo switch "$1" del compilatore
+% With \var{-vn} on, the compiler warns if it ignores a switch.
+scan_w_illegal_switch=02009_W_Lo switch "$1" del compilatore non è ammesso
+% You included a compiler switch (i.e. \var{\{\$... \}}) which the compiler
+% does not recognise.
+scan_w_switch_is_global=02010_W_Switch globale del compilatore fuori posto
+% The compiler switch is misplaced, and should be located at
+% the start of the unit or program.
+scan_e_illegal_char_const=02011_E_Costante carattere illegale
+% This happens when you specify a character with its ASCII code, as in
+% \var{\#96}, but the number is either illegal, or out of range.
+scan_f_cannot_open_input=02012_F_Impossibile aprire il file "$1"
+% \fpc cannot find the program or unit source file you specified on the
+% command line.
+scan_f_cannot_open_includefile=02013_F_Impossibile aprire il file include "$1"
+% \fpc cannot find the source file you specified in a \var{\{\$include ..\}}
+% statement.
+scan_e_illegal_pack_records=02015_E_L'allineamento dei record a "$1" è illegale
+% You are specifying \var{\{\$PACKRECORDS n\} } or \var{\{\$ALIGN n\} }
+% with an illegal value for \var{n}. For \$PACKRECORDS valid alignments are 1, 2, 4, 8, 16, 32, C,
+% NORMAL, DEFAULT, and for \$ALIGN valid alignments are 1, 2, 4, 8, 16, 32, ON,
+% OFF. Under mode MacPas \$ALIGN also supports MAC68K, POWER and RESET.
+scan_e_illegal_pack_enum=02016_E_La dimensione minima "$1" per gli enum è illegale
+% You are specifying the \var{\{\$PACKENUM n\}} with an illegal value for
+% \var{n}. Only 1,2,4, NORMAL or DEFAULT is valid here.
+scan_e_endif_expected=02017_E_$ENDIF previsto per $1 $2 definito in $3 riga $4
+% Your conditional compilation statements are unbalanced.
+scan_e_preproc_syntax_error=02018_E_Errore di sintassi nel parsing di una espressione di compilazione condizionale
+% There is an error in the expression following the \var{\{\$if ..\}}, \var{\{\$ifc \}}
+% or \var{\{\$setc \}} compiler directives.
+scan_e_error_in_preproc_expr=02019_E_Espressione di compilazione condizionale errata
+% There is an error in the expression following the \var{\{\$if ..\}}, $ifc or $setc compiler
+% directives.
+scan_w_macro_cut_after_255_chars=02020_W_Le macro sono limitate a 255 caratteri di lunghezza
+% The contents of macros cannot be longer than 255 characters.
+scan_e_endif_without_if=02021_E_ENDIF senza IF(N)DEF
+% Your \var{\{\$IFDEF ..\}} and {\{\$ENDIF\}} statements aren't balanced.
+scan_f_user_defined=02022_F_Definito dall'utente: $1
+% A user defined fatal error occurred. See also the \progref.
+scan_e_user_defined=02023_E_Definito dall'utente: $1
+% A user defined error occurred. See also the \progref.
+scan_w_user_defined=02024_W_Definito dall'utente: $1
+% A user defined warning occurred. See also the \progref.
+scan_n_user_defined=02025_N_Definito dall'utente: $1
+% A user defined note was encountered. See also the \progref.
+scan_h_user_defined=02026_H_Definito dall'utente: $1
+% A user defined hint was encountered. See also the \progref.
+scan_i_user_defined=02027_I_Definito dall'utente: $1
+% User defined information was encountered. See also the \progref.
+scan_e_keyword_cant_be_a_macro=02028_E_Ridefinire parole chiave nelle macro non ha alcun effetto
+% You cannot redefine keywords with macros.
+scan_f_macro_buffer_overflow=02029_F_Buffer overflow di una macro durante la lettura o l'espansione
+% Your macro or its result was too long for the compiler.
+scan_w_macro_too_deep=02030_W_L'espansione della macro ha superato profondità 16
+% When expanding a macro, macros have been nested to a level of 16.
+% The compiler will expand no further, since this may be a sign that
+% recursion is used.
+scan_w_wrong_styled_switch=02031_W_Gli switch del compilatore non funzionano nei commenti che iniziano con //
+% Compiler switches should be in normal Pascal style comments.
+scan_d_handling_switch=02032_DL_Valutazione dello switch "$1"
+% When you set debugging info on (\var{-vd}) the compiler tells you when it
+% is evaluating conditional compile statements.
+scan_c_endif_found=02033_CL_ENDIF $1 trovato
+% When you turn on conditional messages (\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifdef_found=02034_CL_IFDEF $1 trovato, $2
+% When you turn on conditional messages (\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifopt_found=02035_CL_IFOPT $1 trovato, $2
+% When you turn on conditional messages (\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_if_found=02036_CL_IF $1 trovato, $2
+% When you turn on conditional messages (\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifndef_found=02037_CL_IFNDEF $1 trovato, $2
+% When you turn on conditional messages (\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_else_found=02038_CL_ELSE $1 trovato, $2
+% When you turn on conditional messages (\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_skipping_until=02039_CL_Sarà ignorato tutto fino a...
+% When you turn on conditional messages (\var{-vc}), the compiler tells you
+% where it encounters conditional statements, and whether it is skipping or
+% compiling parts.
+scan_i_press_enter=02040_I_Premere <Invio> per continuare
+% When the \var{-vi} switch is used, the compiler stops compilation
+% and waits for the \var{Enter} key to be pressed when it encounters
+% a \var{\{\$STOP\}} directive.
+scan_w_unsupported_switch=02041_W_Switch "$1" non supportato
+% When warnings are turned on (\var{-vw}), the compiler warns you about
+% unsupported switches. This means that the switch is used in Delphi or
+% Turbo Pascal, but not in \fpc.
+scan_w_illegal_directive=02042_W_La direttiva "$1" del compilatore è illegale
+% When warnings are turned on (\var{-vw}), the compiler warns you about
+% unrecognised switches. For a list of recognised switches, see the \progref.
+scan_t_back_in=02043_TL_Torno in $1
+% When you use the \var{-vt} switch, the compiler tells you when it has finished
+% reading an include file.
+scan_w_unsupported_app_type=02044_W_Tipo di programma "$1" non supportato
+% You get this warning if you specify an unknown application type
+% with the directive \var{\{\$APPTYPE\}}.
+scan_w_app_type_not_support=02045_W_APPTYPE non è supportato dall'OS destinazione
+% The \var{\{\$APPTYPE\}} directive is supported by certain operating systems only.
+scan_w_description_not_support=02046_W_DESCRIPTION non è supportata dall'OS di destinazione
+% The \var{\{\$DESCRIPTION\}} direttiva non è supportata da questo OS destinazione.
+scan_n_version_not_support=02047_N_VERSION non è supportata dall'OS di destinazione
+% The \var{\{\$VERSION\}} direttiva non è supportata da questo OS destinazione.
+scan_n_only_exe_version=02048_N_VERSION vale solo per exe o DLL
+% The \var{\{\$VERSION\}} direttiva è usata solo per sorgenti eseguibili o DLL.
+scan_w_wrong_version_ignored=02049_W_Formato errato per la direttiva VERSION "$1"
+% The \var{\{\$VERSION\}} directive format is majorversion.minorversion
+% where majorversion and minorversion are words.
+scan_e_illegal_asmmode_specifier=02050_E_Lo stile assembler "$1" è illegale
+% When you specify an assembler mode with the \var{\{\$ASMMODE xxx\}} directive,
+% the compiler didn't recognize the mode you specified.
+scan_w_no_asm_reader_switch_inside_asm=02051_W_Lo switch lettore ASM non è ammesso in una istruzione asm: "$1" sarà valido solo per la prossima
+% It is not possible to switch from one assembler reader to another
+% inside an assembler block. The new reader will be used for next
+% assembler statements only.
+scan_e_wrong_switch_toggle=02052_E_Interruttore switch errato, usare ON/OFF o +/-
+% You need to use ON or OFF or a + or - to toggle the switch.
+scan_e_resourcefiles_not_supported=02053_E_I resource file non sono supportati per questa destinazione
+% The target you are compiling for doesn't support resource files.
+scan_w_include_env_not_found=02054_W_La variabile ambiente "$1" per inclusione non esiste
+% The included environment variable can't be found in the environment; it will
+% be replaced by an empty string instead.
+scan_e_invalid_maxfpureg_value=02055_E_Valore illegale per limiti registri FPU
+% Valid values for this directive are 0..8 and NORMAL/DEFAULT.
+scan_w_only_one_resourcefile_supported=02056_W_Questa destinazione supporta solo un file di risorse
+% The target you are compiling for supports only one resource file.
+% The first resource file found is used, the others are discarded.
+scan_w_macro_support_turned_off=02057_W_Il supporto alle macro è disabilitato: macro ignorata
+% A macro declaration has been found, but macro support is currently off,
+% so the declaration will be ignored. To turn macro support on compile with
+% -Sm on the command line or add \{\$MACRO ON\} in the source.
+scan_e_invalid_interface_type=02058_E_Tipo di interfaccia illegale. Sono ammessi COM, CORBA o DEFAULT.
+% The interface type that was specified is not supported.
+scan_w_appid_not_support=02059_W_APPID è supportata solo da PalmOS
+% The \var{\{\$APPID\}} directive is only supported for the PalmOS target.
+scan_w_appname_not_support=02060_W_APPNAME è supportata solo da PalmOS
+% The \var{\{\$APPNAME\}} directive is only supported for the PalmOS target.
+scan_e_string_exceeds_255_chars=02061_E_Le costanti stringa devono essere lunghe non più di 255 caratteri
+% A single string constant can contain at most 255 chars. Try splitting up the
+% string into multiple smaller parts and concatenate them with a + operator.
+scan_f_include_deep_ten=02062_F_La inclusione nidificata di file include ha superato profondità 16.
+% When including include files the files have been nested to a level of 16.
+% The compiler will expand no further, since this may be a sign that
+% recursion is used.
+scan_e_too_many_push=02063_F_Troppi livelli di PUSH
+% A maximum of 20 levels is allowed. This error occurs only in mode MacPas.
+scan_e_too_many_pop=02064_E_Trovata POP senza una PUSH precedente
+% This error occurs only in mode MacPas.
+scan_e_error_macro_lacks_value=02065_E_La variable "$1" in una macro o espressione a tempo di compilazione non ha valore
+% Thus the conditional compile time expression cannot be evaluated.
+scan_e_wrong_switch_toggle_default=02066_E_Interruttore switch errato, usare ON/OFF/DEFAULT o +/-/*
+% You need to use ON or OFF or DEFAULT or a + or - or * to toggle the switch.
+scan_e_mode_switch_not_allowed=02067_E_Lo switch modale "$1" non è ammesso qui
+% A mode switch has already been encountered, or, in the case of option -Mmacpas,
+% a mode switch occurs after UNIT.
+scan_e_error_macro_undefined=02068_E_La variabile o macro "$1" a tempo di compilazione non è definita.
+% Thus the conditional compile time expression cannot be evaluated. Only in mode MacPas.
+scan_e_utf8_bigger_than_65535=02069_E_Trovato un codice UTF-8 maggiore di 65535
+% \fpc handles UTF-8 strings internally as widestrings, i.e. the char codes are limited to 65535.
+scan_e_utf8_malformed=02070_E_Stringa UTF-8 malformata
+% The given string isn't a valid UTF-8 string.
+scan_c_switching_to_utf8=02071_C_Trovata firma UTF-8, uso codifica UTF-8
+% The compiler found a UTF-8 encoding signature (\$ef, \$bb, \$bf) at the beginning of a file,
+% so it interprets it as a UTF-8 file.
+scan_e_compile_time_typeerror=02072_E_Espressione a tempo di compilazione: previsto $1 ma trovato $2 in $3
+% The type-check of a compile time expression failed.
+scan_n_app_type_not_support=02073_N_APPTYPE non è supportato dall'OS di destinazione
+% The \var{\{\$APPTYPE\}} directive is supported by certain operating systems only.
+scan_e_illegal_optimization_specifier=02074_E_L'ottimizzazione specificata "$1" è illegale
+% You specified an optimization with the \var{\{\$OPTIMIZATION xxx\}} directive,
+% and the compiler didn't recognize the optimization you specified.
+scan_w_setpeflags_not_support=02075_W_SETPEFLAGS non è supportato dall'OS di destinazione
+% The \var{\{\$SETPEFLAGS\}} directive is not supported by the target OS.
+scan_w_imagebase_not_support=02076_W_IMAGEBASE non è supportato dall'OS di destinazione
+% The \var{\{\$IMAGEBASE\}} directive is not supported by the target OS.
+scan_w_minstacksize_not_support=02077_W_MINSTACKSIZE non è supportato dall'OS di destinazione
+% The \var{\{\$MINSTACKSIZE\}} directive is not supported by the target OS.
+scan_w_maxstacksize_not_support=02078_W_MAXSTACKSIZE non è supportato dall'OS di destinazione
+% The \var{\{\$MAXSTACKSIZE\}} directive non è supportato dall'OS di destinazione
+scanner_e_illegal_warn_state=02079_E_Stato illegale per la direttiva $WARN
+% Only ON and OFF can be used as state with a \var{\{\$WARN\}} compiler directive.
+scan_e_only_packset=02080_E_Valore illegale di set packing
+% Only 0, 1, 2, 4, 8, DEFAULT and NORMAL are allowed as packset parameters.
+scan_w_pic_ignored=02081_W_Direttiva o switch PIC ignorati
+% Several targets, such as \windows, do not support nor need PIC,
+% so the PIC directive and switch are ignored.
+scan_w_unsupported_switch_by_target=02082_W_Lo switch "$1" non è supportato dalla destinazione scelta
+% Some compiler switches like \$E are not supported by all targets.
+scan_w_frameworks_darwin_only=02084_W_Le opzioni relative al framework sono supportate solo da Darwin/Mac OS X
+% Frameworks are not a known concept, or at least not supported by FPC,
+% on operating systems other than Darwin/Mac OS X.
+scan_e_illegal_minfpconstprec=02085_E_Precisione minima per costanti floating point "$1" illegale
+% Valid minimal precisions for floating point constants are default, 32 and 64,
+% which mean respectively minimal (usually 32 bit), 32 bit and 64 bit precision.
+scan_w_multiple_main_name_overrides=02086_W_Nome della procedura "main" ridefinito: il vecchio nome era "$1"
+% The name for the main entry procedure is specified more than once. Only the last
+% name will be used.
+% \end{description}
+#
+# Parser
+#
+# 03265 is the last used one
+#
+% \section{Parser messages}
+% This section lists all parser messages. The parser takes care of the
+% semantics of you language, i.e. it determines if your Pascal constructs
+% are correct.
+% \begin{description}
+parser_e_syntax_error=03000_E_Analisi - Errore di sintassi
+% An error against the Turbo Pascal language was encountered. This typically
+% happens when an illegal character is found in the source file.
+parser_e_dont_nest_interrupt=03004_E_Le procedure INTERRUPT non possono essere nidificate
+% An \var{INTERRUPT} procedure must be global.
+parser_w_proc_directive_ignored=03005_W_Tipo di procedura "$1" ignorato
+% The specified procedure directive is ignored by FPC programs.
+parser_e_no_overload_for_all_procs=03006_E_Non tutte le dichiarazioni di "$1" sono dichiarate con OVERLOAD
+% When you want to use overloading using the \var{OVERLOAD} directive, then
+% all declarations need to have \var{OVERLOAD} specified.
+parser_e_export_name_double=03008_E_Nome di funzione esportata "$1" duplicato
+% Exported function names inside a specific DLL must all be different.
+parser_e_export_ordinal_double=03009_E_Indice di funzione esportata $1 duplicato
+% Exported function indexes inside a specific DLL must all be different.
+parser_e_export_invalid_index=03010_E_Indice di funzione esportata non valido
+% DLL function index must be in the range \var{1..\$FFFF}.
+parser_w_parser_reloc_no_debug=03011_W_Impossibile creare info di debug per DLL o eseguibile $1, perché è rilocabile.
+% It is currently not possible to include debug information in a relocatable DLL.
+parser_w_parser_win32_debug_needs_WN=03012_W_Per generare info di debug per codice win32 bisogna disabilitare la rilocazione con l'ozione -WN
+% Stabs debug info is wrong for relocatable DLL or EXES. Use -WN
+% if you want to debug win32 executables.
+parser_e_constructorname_must_be_init=03013_E_Il nome del costruttore deve essere INIT
+% You are declaring an object constructor with a name which is not \var{init}, and the
+% \var{-Ss} switch is in effect. See the switch \seeo{Ss}.
+parser_e_destructorname_must_be_done=03014_E_Il nome del distruttore deve essere DONE
+% You are declaring an object destructor with a name which is not \var{done}, and the
+% \var{-Ss} switch is in effect. See the switch \seeo{Ss}.
+parser_e_proc_inline_not_supported=03016_E_Tipo di procedura INLINE non supportato
+% You tried to compile a program with C++ style inlining, and forgot to
+% specify the \var{-Si} option (\seeo{Si}). The compiler doesn't support C++
+% styled inlining by default.
+parser_w_constructor_should_be_public=03018_W_Il costruttore dovrebbe essere pubblico
+% Constructors must be in the 'public' part of an object (class) declaration.
+parser_w_destructor_should_be_public=03019_W_Il distruttore dovrebbe essere pubblico
+% Destructors must be in the 'public' part of an object (class) declaration.
+parser_n_only_one_destructor=03020_N_Una classe dovrebbe avere un solo distruttore
+% You can declare only one destructor for a class.
+parser_e_no_local_objects=03021_E_Non sono ammesse definizioni di classi locali
+% Classes must be defined globally. They cannot be defined inside a
+% procedure or function.
+parser_f_no_anonym_objects=03022_F_Non sono ammesse definizioni di classi anonime
+% An invalid object (class) declaration was encountered, i.e. an
+% object or class without methods that isn't derived from another object or
+% class. For example:
+% \begin{verbatim}
+% Type o = object
+% a : longint;
+% end;
+% \end{verbatim}
+% will trigger this error.
+parser_n_object_has_no_vmt=03023_N_L'oggetto "$1" non ha VMT
+% This is a note indicating that the declared object has no
+% virtual method table.
+parser_e_illegal_parameter_list=03024_E_Lista di parametri illegale
+% You are calling a function with parameters that are of a different type than
+% the declared parameters of the function.
+parser_e_wrong_parameter_size=03026_E_La chiamata a "$1" ha un numero errato di parametri
+% There is an error in the parameter list of the function or procedure --
+% the number of parameters is not correct.
+parser_e_overloaded_no_procedure=03027_E_L'identificatore overloaded "$1" non è una funzione
+% The compiler encountered a symbol with the same name as an overloaded
+% function, but it is not a function it can overload.
+parser_e_overloaded_have_same_parameters=03028_E_ Due o più funzioni overloaded hanno gli stessi parametri
+% You're declaring overloaded functions, but with the same parameter list.
+% Overloaded function must have at least 1 different parameter in their
+% declaration.
+parser_e_header_dont_match_forward=03029_E_La definizione della funzione è diversa dalla dichiarazione "$1"
+% You declared a function with the same parameters but
+% different result type or function modifiers.
+parser_e_header_different_var_names=03030_E_La definizione della funzione "$1" è diversa dalla dichiarazione: $2 cambia in $3
+% You declared the function in the \var{interface} part, or with the
+% \var{forward} directive, but defined it with a different parameter list.
+parser_n_duplicate_enum=03031_N_I valori nei tipi enumerazioni devono essere ascendenti
+% \fpc allows enumeration constructions as in C. Examine the following
+% two declarations:
+% \begin{verbatim}
+% type a = (A_A,A_B,A_E:=6,A_UAS:=200);
+% type a = (A_A,A_B,A_E:=6,A_UAS:=4);
+% \end{verbatim}
+% The second declaration would produce an error. \var{A\_UAS} needs to have a
+% value higher than \var{A\_E}, i.e. at least 7.
+parser_e_no_with_for_variable_in_other_segments=03033_E_Non si può usare With per variabili in un segmento diverso
+% With stores a variable locally on the stack,
+% but this is not possible if the variable belongs to another segment.
+parser_e_too_much_lexlevel=03034_E_Nidificazione di funzioni supera profondità 31
+% You can nest function definitions only 31 levels deep.
+parser_e_range_check_error=03035_E_Costanti fuori dalla gamma di valori ammessa
+% The constants are out of their allowed range.
+parser_w_range_check_error=03036_W_Costanti fuori dalla gamma di valori ammessa
+% The constants are out of their allowed range.
+parser_e_double_caselabel=03037_E_etichetta case duplicata
+% You are specifying the same label 2 times in a \var{case} statement.
+parser_e_case_lower_less_than_upper_bound=03038_E_Il limite superiore di un intervallo case è minore del limite inferiore
+% The upper bound of a \var{case} label is less than the lower bound and this
+% is useless.
+parser_e_type_const_not_possible=03039_E_costanti di tipo classe o interfaccia non sono permesse
+% You cannot declare a constant of type class or object.
+parser_e_no_overloaded_procvars=03040_E_Variabili di funzioni in funzioni overloaded non sono permesse
+% You are trying to assign an overloaded function to a procedural variable.
+% This is not allowed.
+parser_e_invalid_string_size=03041_E_La lunghezza di una stringa deve essere fra 1 e 255
+% The length of a shortstring in Pascal is limited to 255 characters. You are
+% trying to declare a string with length less than 1 or greater than 255.
+parser_w_use_extended_syntax_for_objects=03042_W_usate la sintassi estesa di NEW e DISPOSE per le istanze di oggetti
+% If you have a pointer \var{a} to an object type, then the statement
+% \var{new(a)} will not initialize the object (i.e. the constructor isn't
+% called), although space will be allocated. You should issue the
+% \var{new(a,init)} statement. This will allocate space, and call the
+% constructor of the object.
+parser_w_no_new_dispose_on_void_pointers=03043_W_non ha senso usare NEW o DISPOSE con puntatori senza tipo
+parser_e_no_new_dispose_on_void_pointers=03044_E_usare NEW o DISPOSE con puntatori senza tipo non è permesso
+% You cannot use \var{new(p)} or \var{dispose(p)} if \var{p} is an untyped pointer
+% because no size is associated to an untyped pointer.
+% It is accepted for compatibility in \var{TP} and \var{DELPHI} modes, but the
+% compiler will still warn you if it finds such a construct.
+parser_e_class_id_expected=03045_E_Qui era atteso un identificatore di classe (ma non c'è)
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., an object or class method, but the type in front of the dot is not
+% a known type.
+parser_e_no_type_not_allowed_here=03046_E_gli identificatori di tipo non sono permessi qui
+% You cannot use a type inside an expression.
+parser_e_methode_id_expected=03047_E_Qui era atteso un identificatore di metodo (ma non c'è)
+% This identifier is not a method.
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., an object or class method, but the procedure name is not a
+% procedure of this type.
+parser_e_header_dont_match_any_member=03048_E_La definizione della funzione non corrisponde a nessun metodo di questa classe "$1"
+% This identifier is not a method.
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., an object or class method, but the procedure name is not a
+% procedure of this type.
+parser_d_procedure_start=03049_DL_procedura/funzione $1
+% When using the \var{-vd} switch, the compiler tells you when it starts
+% processing a procedure or function implementation.
+parser_e_error_in_real=03050_E_Costante in virgola mobile illegale
+% The compiler expects a floating point expression, and gets something else.
+parser_e_fail_only_in_constructor=03051_E_FAIL si può usare solo nei costruttori
+% You are using the \var{fail} keyword outside a constructor method.
+parser_e_no_paras_for_destructor=03052_E_I distruttori non possono avere parametri
+% You are declaring a destructor with a parameter list. Destructor methods
+% cannot have parameters.
+parser_e_only_class_methods_via_class_ref=03053_E_Solo i metodi di classe si possono chiamare riferendosi a una classe
+% This error occurs in a situation like the following:
+% \begin{verbatim}
+% Type :
+% Tclass = Class of Tobject;
+%
+% Var C : TClass;
+%
+% begin
+% ...
+% C.free
+% \end{verbatim}
+% \var{Free} is not a class method and hence cannot be called with a class
+% reference.
+parser_e_only_class_methods=03054_E_Solo i metodi di classe si possono chiamare da altri metodi di classe
+% This is related to the previous error. You cannot call a method of an object
+% from inside a class method. The following code would produce this error:
+% \begin{verbatim}
+% class procedure tobject.x;
+%
+% begin
+% free
+% \end{verbatim}
+% Because free is a normal method of a class it cannot be called from a class
+% method.
+parser_e_case_mismatch=03055_E_I tipi di un CASE e della sua costante non corrispondono
+% One of the labels is not of the same type as the case variable.
+parser_e_illegal_symbol_exported=03056_E_Simbolo non è esportabile da una libreria
+% You can only export procedures and functions when you write a library. You
+% cannot export variables or constants.
+parser_w_should_use_override=03057_W_Un metodo ereditato è nascosto da "$1"
+% A method that is declared \var{virtual} in a parent class, should be
+% overridden in the descendant class with the \var{override} directive. If you
+% don't specify the \var{override} directive, you will hide the parent method;
+% you will not override it.
+parser_e_nothing_to_be_overridden=03058_E_Non c'è un metodo "$1" da sovrascrivere nella classe padre
+% You are trying to \var{override} a virtual method of a parent class that does
+% not exist.
+parser_e_no_procedure_to_access_property=03059_E_Non sono forniti membri per accedere alla proprietà
+% You specified no \var{read} directive for a property.
+parser_w_stored_not_implemented=03060_W_Direttiva di proprietà stored non ancora implementata
+% This message is no longer used, as the \var{stored} directive has been implemented.
+parser_e_ill_property_access_sym=03061_E_Simbolo illegale per l'accesso alla proprietà
+% There is an error in the \var{read} or \var{write} directives for an array
+% property. When you declare an array property, you can only access it with
+% procedures and functions. The following code would cause such an error.
+% \begin{verbatim}
+% tmyobject = class
+% i : integer;
+% property x [i : integer]: integer read I write i;
+% \end{verbatim}
+%
+parser_e_cant_access_protected_member=03062_E_Qui non si può accedere alla parte protetta di un oggetto
+% Fields that are declared in a \var{protected} section of an object or class
+% declaration cannot be accessed outside the module where the object is
+% defined, or outside descendent object methods.
+parser_e_cant_access_private_member=03063_E_Qui non si può accedere alla parte privata di un oggetto
+% Fields that are declared in a \var{private} section of an object or class
+% declaration cannot be accessed outside the module where the class is
+% defined.
+parser_e_overridden_methods_not_same_ret=03066_E_I metodi overridden devono avere lo stesso tipo di ritorno: "$2" è overriden da "$1" che ritorna un tipo diverso
+% If you declare overridden methods in a class definition, they must
+% have the same return type.
+parser_e_dont_nest_export=03067_E_Funzioni dichiarate EXPORT non possono essere nidificate
+% You cannot declare a function or procedure within a function or procedure
+% that was declared as an export procedure.
+parser_e_methods_dont_be_export=03068_E_I metodi di classe non si possono dichiarare EXPORT
+% You cannot declare a procedure that is a method for an object as
+% \var{export}ed.
+parser_e_call_by_ref_without_typeconv=03069_E_I tipi nelle chiamate a funzioni var $1 devono corrispondere esattamente: passato "$2" ma serviva "$3"
+% When calling a function declared with \var{var} parameters, the variables in
+% the function call must be of exactly the same type. There is no automatic
+% type conversion.
+parser_e_no_super_class=03070_E_La classe non è una classe padre della classe corrente
+% When calling inherited methods, you are trying to call a method of a non-related
+% class. You can only call an inherited method of a parent class.
+parser_e_self_not_in_method=03071_E_SELF is only allowed in methods
+% You are trying to use the \var{self} parameter outside an object's method.
+% Only methods get passed the \var{self} parameters.
+parser_e_generic_methods_only_in_methods=03072_E_Solo i metodi si possono chiamare direttamente da altri metodi con l'identificatore della classe
+% A construction like \var{sometype.somemethod} is only allowed in a method.
+parser_e_illegal_colon_qualifier=03073_E_Uso illegale di ':'
+% You are using the format \var{:} (colon) 2 times on an expression that
+% is not a real expression.
+parser_e_illegal_set_expr=03074_E_Errore di intervallo in un costruttore di insiemi, oppure elemento di insieme duplicato
+% The declaration of a set contains an error. Either one of the elements is
+% outside the range of the set type, or two of the elements are in fact
+% the same.
+parser_e_pointer_to_class_expected=03075_E_Qui era atteso un puntatore a un elemento
+% You specified an illegal type in a \var{new} statement.
+% The extended syntax of \var{new} needs an object as a parameter.
+parser_e_expr_have_to_be_constructor_call=03076_E_L'espressione deve essere la chiamata di un costruttore
+% When using the extended syntax of \var{new}, you must specify the constructor
+% method of the object you are trying to create. The procedure you specified
+% is not a constructor.
+parser_e_expr_have_to_be_destructor_call=03077_E_L'espressione deve essere la chiamata di un distruttore
+% When using the extended syntax of \var{dispose}, you must specify the
+% destructor method of the object you are trying to dispose of.
+% The procedure you specified is not a destructor.
+parser_e_invalid_record_const=03078_E_Elementi del record disposti in ordine illegale
+% When declaring a constant record, you specified the fields in the wrong
+% order.
+parser_e_false_with_expr=03079_E_L'espressione deve essere un tipo classe o record
+% A \var{with} statement needs an argument that is of the type \var{record}
+% or \var{class}. You are using \var{with} on an expression that is not of
+% this type.
+parser_e_void_function=03080_E_Le procedure non possono ritornare un valore
+% In \fpc, you can specify a return value for a function when using
+% the \var{exit} statement. This error occurs when you try to do this with a
+% procedure. Procedures cannot return a value.
+parser_e_constructors_always_objects=03081_E_Costruttori e distruttori devono essere metodi
+% You're declaring a procedure as destructor or constructor, when the
+% procedure isn't a class method.
+parser_e_operator_not_overloaded=03082_E_L'operatore non ha overload per il tipo specificato
+% You're trying to use an overloaded operator when it is not overloaded for
+% this type.
+parser_e_no_such_assignment=03083_E_Impossibile fare l'overload dell'assegnazione fra tipi uguali
+% You cannot overload assignment for types
+% that the compiler considers as equal.
+parser_e_overload_impossible=03084_E_Overload di operatore impossibile
+% The combination of operator, arguments and return type are
+% incompatible.
+parser_e_no_reraise_possible=03085_E_Il rilancio di un'eccezione non è permesso qui
+% You are trying to re-raise an exception where it is not allowed. You can only
+% re-raise exceptions in an \var{except} block.
+parser_e_no_new_or_dispose_for_classes=03086_E_La sintassi estesa di new o dispose non è permessa per una classe
+% You cannot generate an instance of a class with the extended syntax of
+% \var{new}. The constructor must be used for that. For the same reason, you
+% cannot call \var{dispose} to de-allocate an instance of a class, the
+% destructor must be used for that.
+parser_e_procedure_overloading_is_off=03088_E_L'overloading di procedure è disabilitato
+% When using the \var{-So} switch, procedure overloading is switched off.
+% Turbo Pascal does not support function overloading.
+parser_e_overload_operator_failed=03089_E_Impossibile fare l'overload di questo operatore. Operatori overloadabili simili (se esistono): $1
+% You are trying to overload an operator which cannot be overloaded.
+% The following operators can be overloaded :
+% \begin{verbatim}
+% +, -, *, /, =, >, <, <=, >=, is, as, in, **, :=
+% \end{verbatim}
+parser_e_comparative_operator_return_boolean=03090_E_L'operatore di confronto deve dare un valore booleano
+% When overloading the \var{=} operator, the function must return a boolean
+% value.
+parser_e_only_virtual_methods_abstract=03091_E_Solo i metodi virtuali possono essere astratti
+% You are declaring a method as abstract, when it is not declared to be
+% virtual.
+parser_f_unsupported_feature=03092_F_Uso di capacità non supportata!
+% You're trying to force the compiler into doing something it cannot do yet.
+parser_e_mix_of_classes_and_objects=03093_E_The mix of different kind of objects (class, object, interface, etc) isn't allowed
+% You cannot derive \var{objects}, \var{classes}, \var{cppclasses} and \var{interfaces} intertwined. E.g.
+% a class cannot have an object as parent and vice versa.
+parser_w_unknown_proc_directive_ignored=03094_W_Ignorata una direttiva di procedura sconosciuta: "$1"
+% The procedure directive you specified is unknown.
+parser_e_absolute_only_one_var=03095_E_ABSOLUTE si può associare solo a una variabile
+% You cannot specify more than one variable before the \var{absolute} directive.
+% Thus, the following construct will provide this error:
+% \begin{verbatim}
+% Var Z : Longint;
+% X,Y : Longint absolute Z;
+% \end{verbatim}
+parser_e_absolute_only_to_var_or_const=03096_E_ABSOLUTE si può associare solo a variabili o costanti
+% The address of an \var{absolute} directive can only point to a variable or
+% constant. Therefore, the following code will produce this error:
+% \begin{verbatim}
+% Procedure X;
+%
+% var p : longint absolute x;
+% \end{verbatim}
+parser_e_initialized_only_one_var=03097_E_Si può inizializzare solo una variabile alla volta
+% You cannot specify more than one variable with a initial value in Delphi mode.
+parser_e_abstract_no_definition=03098_E_I metodi astratti non dovrebbero avere definizioni (il corpo funzione)
+% Abstract methods can only be declared, you cannot implement them. They
+% should be overridden by a descendant class.
+parser_e_overloaded_must_be_all_global=03099_E_Questa funzione overloaded non può essere locale: deve essere esportata
+% You are defining an overloaded function in the implementation part of a unit,
+% but there is no corresponding declaration in the interface part of the unit.
+parser_w_virtual_without_constructor=03100_W_In "$1" dei metodi virtuali sono usati senza costruttore
+% If you declare objects or classes that contain virtual methods, you need
+% to have a constructor and destructor to initialize them. The compiler
+% encountered an object or class with virtual methods that doesn't have
+% a constructor/destructor pair.
+parser_c_macro_defined=03101_CL_Macro definita: $1
+% When \var{-vc} is used, the compiler tells you when it defines macros.
+parser_c_macro_undefined=03102_CL_Macro non definita: $1
+% When \var{-vc} is used, the compiler tells you when it undefines macros.
+parser_c_macro_set_to=03103_CL_Macro $1 impostata a $2
+% When \var{-vc} is used, the compiler tells you what values macros get.
+parser_i_compiling=03104_I_Compilando $1
+% When you turn on information messages (\var{-vi}), the compiler tells you
+% what units it is recompiling.
+parser_u_parsing_interface=03105_UL_Interfaccia di analisi della unit $1
+% This tells you that the reading of the interface
+% of the current unit has started
+parser_u_parsing_implementation=03106_UL_Analisi dell'implementazione di $1
+% This tells you that the code reading of the implementation
+% of the current unit, library or program starts
+parser_d_compiling_second_time=03107_DL_Compilando $1 per la seconda volta
+% When you request debug messages (\var{-vd}) the compiler tells you what
+% units it recompiles for the second time.
+parser_e_no_property_found_to_override=03109_E_Non ci sono proprietà di cui fare l'override
+% You want to override a property of a parent class, when there is, in fact,
+% no such property in the parent class.
+parser_e_only_one_default_property=03110_E_E' permessa solo una proprietà di default
+% You specified a property as \var{Default}, but the class already has a
+% default property, and a class can have only one default property.
+parser_e_property_need_paras=03111_E_La proprietà di default deve essere una proprietà array
+% Only array properties of classes can be made \var{default} properties.
+parser_e_constructor_cannot_be_not_virtual=03112_E_Costruttori virtuali sono supportati solo nel modello di oggetto classe
+% You cannot have virtual constructors in objects. You can only have them
+% in classes.
+parser_e_no_default_property_available=03113_E_Nessuna proprietà di default disponibile
+% You are trying to access a default property of a class, but this class (or one of
+% its ancestors) doesn't have a default property.
+parser_e_cant_have_published=03114_E_La classe non può avere una sezione pubblicata, usare lo switch {$M+}
+% If you want a \var{published} section in a class definition, you must
+% use the \var{\{\$M+\}} switch, which turns on generation of type
+% information.
+parser_e_forward_declaration_must_be_resolved=03115_E_La dichiarazione della classe "$1" deve essere risolta qui per poterla usare come padre
+% To be able to use an object as an ancestor object, it must be defined
+% first. This error occurs in the following situation:
+% \begin{verbatim}
+% Type ParentClas = Class;
+% ChildClass = Class(ParentClass)
+% ...
+% end;
+% \end{verbatim}
+% where \var{ParentClass} is declared but not defined.
+parser_e_no_local_operator=03116_E_Operatori locali non supportati
+% You cannot overload locally, i.e. inside procedures or function
+% definitions.
+parser_e_proc_dir_not_allowed_in_interface=03117_E_Direttiva di procedura "$1" non è permessa nella sezione interfaccia
+% This procedure directive is not allowed in the \var{interface} section of
+% a unit. You can only use it in the \var{implementation} section.
+parser_e_proc_dir_not_allowed_in_implementation=03118_E_Direttiva di procedura "$1" non è permessa nella sezione implementazione
+% This procedure directive is not allowed in the \var{implementation} section of
+% a unit. You can only use it in the \var{interface} section.
+parser_e_proc_dir_not_allowed_in_procvar=03119_E_Direttiva di procedura "$1" non è permessa in dichiarazioni procvar
+% This procedure directive cannot be part of a procedural or function
+% type declaration.
+parser_e_function_already_declared_public_forward=03120_E_La funzione è già dichiarata Public/Forward "$1"
+% You will get this error if a function is defined as \var{forward} twice.
+% Or if it occurs in the \var{interface} section, and again as a \var{forward}
+% declaration in the \var{implementation} section.
+parser_e_not_external_and_export=03121_E_Non si possono usare sia EXPORT che EXTERNAL
+% These two procedure directives are mutually exclusive.
+parser_w_not_supported_for_inline=03123_W_"$1" non è ancora supportata all'interno di procedure o funzioni inline
+% Inline procedures don't support this declaration.
+parser_w_inlining_disabled=03124_W_Inlining disabilitato
+% Inlining of procedures is disabled.
+parser_i_writing_browser_log=03125_I_Scrivo il log del browser $1
+% When information messages are on, the compiler warns you when it
+% writes the browser log (generated with the \var{\{\$Y+ \}} switch).
+parser_h_maybe_deref_caret_missing=03126_H_Forse bisogna prima dereferenziare un puntatore
+% The compiler thinks that a pointer may need a dereference.
+parser_f_assembler_reader_not_supported=03127_F_Il lettore assembler scelto non è supportato
+% The selected assembler reader (with \var{\{\$ASMMODE xxx\}} is not
+% supported. The compiler can be compiled with or without support for a
+% particular assembler reader.
+parser_e_proc_dir_conflict=03128_E_Direttiva di procedura "$1" è in conflitto con altre direttive
+% You specified a procedure directive that conflicts with other directives.
+% For instance \var{cdecl} and \var{pascal} are mutually exclusive.
+parser_e_call_convention_dont_match_forward=03129_E_La convenzione di chiamata non corrisponde alla dichiarazione
+% This error happens when you declare a function or procedure with
+% e.g. \var{cdecl;} but omit this directive in the implementation, or vice
+% versa. The calling convention is part of the function declaration, and
+% must be repeated in the function definition.
+parser_e_property_cant_have_a_default_value=03131_E_La proprietà non può avere un valore di default
+% Set properties or indexed properties cannot have a default value.
+parser_e_property_default_value_must_const=03132_E_Il valore di default di una proprietà deve essere costante
+% The value of a \var{default} declared property must be known at compile
+% time. The value you specified is only known at run time. This happens
+% e.g. if you specify a variable name as a default value.
+parser_e_cant_publish_that=03133_E_Questo simbolo non può essere pubblicato, può essere solo una classe
+% Only class type variables can be in a \var{published} section of a class
+% if they are not declared as a property.
+parser_e_cant_publish_that_property=03134_E_This kind of property can't be published
+% Properties in a \var{published} section cannot be array properties.
+% They must be moved to public sections. Properties in a \var{published}
+% section must be an ordinal type, a real type, strings or sets.
+parser_e_empty_import_name=03136_E_E' necessario un nome di importazione
+% Some targets need a name for the imported procedure or a \var{cdecl} specifier.
+parser_e_division_by_zero=03138_E_Divisione per zero
+% A division by zero was encounted.
+parser_e_invalid_float_operation=03139_E_Operazione in virgola mobile non valida
+% An operation on two real type values produced an overflow or a division
+% by zero.
+parser_e_array_lower_less_than_upper_bound=03140_E_Limite superiore dell'intervallo minore del limite inferiore
+% The upper bound of an array declaration is less than the lower bound and this
+% is not possible.
+parser_w_string_too_long=03141_W_La stringa "$1" è più lunga di "$2"
+% The size of the constant string is larger than the size you specified in
+% string type definition.
+parser_e_string_larger_array=03142_E_La stringa è più lunga dell'array di char
+% The size of the constant string is larger than the size you specified in
+% the \var{Array[x..y] of char} definition.
+parser_e_ill_msg_expr=03143_E_Espressione illegale dopo la direttiva di messaggio
+% \fpc supports only integer or string values as message constants.
+parser_e_ill_msg_param=03144_E_I gestori di messaggi possono prendere un solo parametro, dichiarato come chiamata per riferimento
+% A method declared with the \var{message} directive as message handler
+% can take only one parameter which must be declared as call by reference.
+% Parameters are declared as call by reference using the \var{var}-directive.
+parser_e_duplicate_message_label=03145_E_Label di messaggio duplicata: "$1"
+% A label for a message is used twice in one object/class.
+parser_e_self_in_non_message_handler=03146_E_In metodi che gestiscono messaggi, il parametro Self può essere solo esplicito
+% The \var{Self} parameter can only be passed explicitly to a method which
+% is declared as message handler.
+parser_e_threadvars_only_sg=03147_E_Le threadvars possono essere solo statiche o globali
+% Threadvars must be static or global; you can't declare a thread
+% local to a procedure. Local variables are always local to a thread,
+% because every thread has its own stack and local variables
+% are stored on the stack.
+parser_f_direct_assembler_not_allowed=03148_F_L'assembler diretto non è supportato dal formato binario di output
+% You can't use direct assembler when using a binary writer. Choose an
+% other output format or use another assembler reader.
+parser_w_no_objpas_use_mode=03149_W_Non caricare manualmente la unit OBJPAS, usare \{\$mode objfpc\} oppure \{\$mode delphi\}
+% You are trying to load the \file{ObjPas} unit manually from a \var{uses} clause.
+% This is not a good idea. Use the \var{\{\$MODE OBJFPC\}} or
+% \var{\{\$mode delphi\}} directives which load the unit automatically.
+parser_e_no_object_override=03150_E_OVERRIDE non si può usare negli oggetti
+% \var{Override} is not supported for objects, use \var{virtual} instead to override
+% a method of a parent object.
+parser_e_cant_use_inittable_here=03151_E_I Tipi di dato che richiedono inizializzazione/finalizzazione non si possono usare in record variant
+% Some data types (e.g. \var{ansistring}) need initialization/finalization
+% code which is implicitly generated by the compiler. Such data types
+% can't be used in the variant part of a record.
+parser_e_resourcestring_only_sg=03152_E_Le resourcestring possono essere solo o statiche o globali
+% Resourcestring cannot be declared local, only global or using the static
+% directive.
+parser_e_exit_with_argument_not__possible=03153_E_L'istruzione Exit con argomenti non si può usare qui
+% An exit statement with an argument for the return value can't be used here. This
+% can happen for example in \var{try..except} or \var{try..finally} blocks.
+parser_e_stored_property_must_be_boolean=03154_E_Il simbolo di storage deve essere di tipo boolean
+% If you specify a storage symbol in a property declaration, it must be a
+% boolean type.
+parser_e_ill_property_storage_sym=03155_E_Questo simbolo non è ammesso come simbolo di storage
+% You can't use this type of symbol as storage specifier in property
+% declaration. You can use only methods with the result type boolean,
+% boolean class fields or boolean constants.
+parser_e_only_publishable_classes_can_be_published=03156_E_Si possono pubblicare solo classi compilate nel modo $M+
+% A class-typed field in the published section of a class can only be a class which was
+% compiled in \var{\{\$M+\}} or which is derived from such a class. Normally
+% such a class should be derived from \var{TPersistent}.
+parser_e_proc_directive_expected=03157_E_Qui era attesa una direttiva di procedura (ma non c'è)
+% This error is triggered when you have a \var{\{\$Calling\}} directive without
+% a calling convention specified.
+% It also happens when declaring a procedure in a const block and you
+% used a ; after a procedure declaration which must be followed by a
+% procedure directive.
+% Correct declarations are:
+% \begin{verbatim}
+% const
+% p : procedure;stdcall=nil;
+% p : procedure stdcall=nil;
+% \end{verbatim}
+parser_e_invalid_property_index_value=03158_E_Il valore di un indice di proprietà deve essere un tipo ordinale
+% The value you use to index a property must be of an ordinal type, for
+% example an integer or enumerated type.
+parser_e_procname_to_short_for_export=03159_E_Il nome di procedura è troppo corto per poterlo esportare
+% The length of the procedure/function name must be at least 2 characters
+% long. This is because of a bug in dlltool which doesn't parse the .def
+% file correctly with a name of length 1.
+parser_e_dlltool_unit_var_problem=03160_E_Non si possono generare voci DEFFILE per la variabili globali di una unit
+parser_e_dlltool_unit_var_problem2=03161_E_Questo file deve essere compilato senza l'opzione -WD
+% You need to compile this file without the -WD switch on the
+% command line.
+parser_f_need_objfpc_or_delphi_mode=03162_F_Questo file deve essere compilato in modo ObjFpc (-S2) o Delphi (-Sd)
+% You need to use \var{\{\$MODE OBJFPC\}} or \var{\{\$MODE DELPHI\}} to compile this file.
+% Or use the corresponding command line switch, either \var{-Mobjfpc} or \var{-MDelphi.}
+parser_e_no_export_with_index_for_target=03163_E_Impossibile esportare con indice sulla piattaforma $1
+% Exporting of functions or procedures with a specified index is not
+% supported on this target.
+parser_e_no_export_of_variables_for_target=03164_E_L'esportazione di variabili non è supportata sulla piattaforma $1
+% Exporting of variables is not supported on this target.
+parser_e_improper_guid_syntax=03165_E_Sintassi GUID errata
+% The GUID indication does not have the proper syntax. It should be of the form
+% \begin{verbatim}
+% {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}
+% \end{verbatim}
+% Where each \var{X} represents a hexadecimal digit.
+parser_w_interface_mapping_notfound=03168_W_Non c'è nessuna procedura di nome "$1" adatta per implementare $2.$3
+% The compiler cannot find a suitable procedure which implements the given method of an interface.
+% A procedure with the same name is found, but the arguments do not match.
+parser_e_interface_id_expected=03169_E_era atteso un identificatore di interfaccia (ma non c'è)
+% This happens when the compiler scans a \var{class} declaration that contains
+% \var{interface} function name mapping code like this:
+% \begin{verbatim}
+% type
+% TMyObject = class(TObject, IDispatch)
+% function IUnknown.QueryInterface=MyQueryInterface;
+% ....
+% \end{verbatim}
+% and the \var{interface} before the dot is not listed in the inheritance list.
+parser_e_type_cant_be_used_in_array_index=03170_E_Il tipo "$1" non si può usare come indice di un array
+% Types like \var{qword} or \var{int64} aren't allowed as array index type.
+parser_e_no_con_des_in_interfaces=03171_E_Le interfacce non possono avere né costruttori né distruttori
+% Constructor and destructor declarations aren't allowed in interfaces.
+% In the most cases method \var{QueryInterface} of \var{IUnknown} can
+% be used to create a new interface.
+parser_e_no_access_specifier_in_interfaces=03172_E_Non si possono usare specificatori d'accesso in INTERFACES
+% The access specifiers \var{public}, \var{private}, \var{protected} and
+% \var{published} can't be used in interfaces because all methods
+% of an interface must be public.
+parser_e_no_vars_in_interfaces=03173_E_Una interfaccia non può contenere campi
+% Declarations of fields aren't allowed in interfaces. An interface
+% can contain only methods and properties with method read/write specifiers.
+parser_e_no_local_proc_external=03174_E_Le procedure locali non si possono dichiarare EXTERNAL
+% Declaring local procedures as external is not possible. Local procedures
+% get hidden parameters that will make the chance of errors very high.
+parser_w_skipped_fields_before=03175_W_Alcuni campi all'inizio di "$1" non sono stati inizializzati
+% In Delphi mode, not all fields of a typed constant record have to be
+% initialized, but the compiler warns you when it detects such situations.
+parser_e_skipped_fields_before=03176_E_Alcuni campi all'inizio di "$1" non sono stati inizializzati
+% In all syntax modes but Delphi mode, you can't leave some fields uninitialized
+% in the middle of a typed constant record.
+parser_w_skipped_fields_after=03177_W_Alcuni campi alla fine di "$1" non sono stati inizializzati
+% You can leave some fields at the end of a type constant record uninitialized
+% (The compiler will initialize them to zero automatically). This may be the cause
+% of subtle problems.
+parser_e_varargs_need_cdecl_and_external=03178_E_Trovata direttiva VarArgs (o '...' in MacPas) senza CDecl/CPPDecl/MWPascal ed External
+% The varargs directive (or the ``...'' varargs parameter in MacPas mode) can only be
+% used with procedures or functions that are declared with \var{external} and one of
+% \var{cdecl}, \var{cppdecl} and \var{mwpascal}. This functionality
+% is only supported to provide a compatible interface to C functions like printf.
+parser_e_self_call_by_value=03179_E_Self deve essere un normale parametro (chiamata per valore)
+% You can't declare \var{Self} as a const or var parameter, it must always be
+% a call-by-value parameter.
+parser_e_interface_has_no_guid=03180_E_L'interfaccia "$1" non ha identificazione di interfaccia
+% When you want to assign an interface to a constant, then the interface
+% must have a GUID value set.
+parser_e_illegal_field_or_method=03181_E_Identificatore di classe sconosciuto per campo o metodo "$1"
+% Properties must refer to a field or method in the same class.
+parser_w_proc_overriding_calling=03182_W_Forzatura della convenzione di chiamata "$1" a "$2"
+% There are two directives in the procedure declaration that specify a calling
+% convention. Only the last directive will be used.
+parser_e_no_procvarobj_const=03183_E_Costanti tipizzate del tipo "procedura di oggetto" possono solo essere inizializzate con NIL
+% You can't assign the address of a method to a typed constant which has a
+% 'procedure of object' type, because such a constant requires two addresses:
+% that of the method (which is known at compile time) and that of the object or
+% class instance it operates on (which cannot be known at compile time).
+parser_e_default_value_only_one_para=03184_E_I valori di default si possono assegnare solo a un parametro per volta
+% It is not possible to specify a default value for several parameters at once.
+% The following is invalid:
+% \begin{verbatim}
+% Procedure MyProcedure (A,B : Integer = 0);
+% \end{verbatim}
+% Instead, this should be declared as
+% \begin{verbatim}
+% Procedure MyProcedure (A : Integer = 0; B : Integer = 0);
+% \end{verbatim}
+parser_e_default_value_expected_for_para=03185_E_Parametro di default necessario per "$1"
+% The specified parameter requires a default value.
+parser_w_unsupported_feature=03186_W_Uso di capacità non supportata!
+% You're trying to force the compiler into doing something it cannot do yet.
+parser_h_c_arrays_are_references=03187_H_Array C sono passati per riferimento
+% Any array passed to a C function is passed
+% by a pointer (i.e. by reference).
+parser_e_C_array_of_const_must_be_last=03188_E_Array C di const devono essere l'ultimo argomento
+% You cannot add any other argument after an \var{array of const} for
+% \var{cdecl} functions, as the size pushed on stack for this argument is
+% not known.
+parser_h_type_redef=03189_H_Ridefinizione del tipo "$1"
+% This is an indicator that a previously declared type is
+% being redefined as something else. This may, or may not
+% be, a potential source of errors.
+parser_w_cdecl_has_no_high=03190_W_Le funzioni dichiarate cdecl non passano parametri impliciti extra
+% Functions declared with the \var{cdecl} modifier do not pass an extra implicit parameter.
+parser_w_cdecl_no_openstring=03191_W_Le funzioni dichiarate cdecl non supportano stringhe aperte
+% Openstring is not supported for functions that have the \var{cdecl} modifier.
+parser_e_initialized_not_for_threadvar=03192_E_Le variabili dichiarate come threadvar non si possono inizializzare
+% Variables declared as threadvar cannot be initialized with a default value.
+% The variables will always be filled with zero at the start of a new thread.
+parser_e_msg_only_for_classes=03193_E_La direttiva Message è permessa solo nelle classi
+% The message directive is only supported for Class types.
+parser_e_procedure_or_function_expected=03194_E_Era attesa una procedura o una funzione (ma non ci sono)
+% A class method can only be specified for procedures and functions.
+parser_e_illegal_calling_convention=03195_W_Direttiva di convenzione di chiamata "$1" ignorata
+% Some calling conventions are supported only by certain CPUs. I.e. most non-i386 ports support
+% only the standard ABI calling convention of the CPU.
+parser_e_no_object_reintroduce=03196_E_REINTRODUCE non si può usare negli oggetti
+% \var{reintroduce} is not supported for objects.
+parser_e_paraloc_only_one_para=03197_E_Ogni argomento deve avere la sua collocazione
+% If locations for arguments are specified explicitly as it is required by
+% some syscall conventions, each argument must have its own location. Things
+% like
+% \begin{verbatim}
+% procedure p(i,j : longint 'r1');
+% \end{verbatim}
+% aren't allowed.
+parser_e_paraloc_all_paras=03198_E_Ogni argomento deve avere una collocazione esplicita
+% If one argument has an explicit argument location, all arguments of a procedure
+% must have one.
+parser_e_illegal_explicit_paraloc=03199_E_Collocazione dell'argomento sconosciuta
+% The location specified for an argument isn't recognized by the compiler.
+parser_e_32bitint_or_pointer_variable_expected=03200_E_Qui era attesa una variabile intera o puntatore a 32 Bit (ma non c'è)
+% The libbase for MorphOS/AmigaOS can be given only as \var{longint}, \var{dword} or any pointer variable.
+parser_e_goto_outside_proc=03201_E_Le istruzioni Goto fra procedure diverse non sono permesse
+% It isn't allowed to use \var{goto} statements referencing labels outside the
+% current procedure. The following example shows the problem:
+% \begin{verbatim}
+% ...
+% procedure p1;
+% label
+% l1;
+%
+% procedure p2;
+% begin
+% goto l1; // This goto ISN'T allowed
+% end;
+%
+% begin
+% p2
+% l1:
+% end;
+% ...
+%
+% \end{verbatim}
+parser_f_too_complex_proc=03202_F_Procedura troppo complessa, richiede troppi registri
+% Your procedure body is too long for the compiler. You should split the
+% procedure into multiple smaller procedures.
+parser_e_illegal_expression=03203_E_Espressione illegale
+% This can occur under many circumstances. Usually when trying to evaluate
+% constant expressions.
+parser_e_invalid_integer=03204_E_Espressione intera non valida
+% You made an expression which isn't an integer, and the compiler expects the
+% result to be an integer.
+parser_e_invalid_qualifier=03205_E_Qualificatore illegale
+% One of the following is happening :
+% \begin{itemize}
+% \item You're trying to access a field of a variable that is not a record.
+% \item You're indexing a variable that is not an array.
+% \item You're dereferencing a variable that is not a pointer.
+% \end{itemize}
+parser_e_upper_lower_than_lower=03206_E_Limite superiore di intervallo minore del limite inferiore
+% You are declaring a subrange, and the high limit is less than the low limit of
+% the range.
+parser_e_macpas_exit_wrong_param=03207_E_I parametri di Exit devono essere il nome della procedura in cui è usato
+% Non local exit is not allowed. This error occurs only in mode MacPas.
+parser_e_illegal_assignment_to_count_var=03208_E_Assegnazione illegale della variabile "$1" del ciclo for-loop
+% The type of a \var{for} loop variable must be an ordinal type.
+% Loop variables cannot be reals or strings. You also cannot assign values to
+% loop variables inside the loop (Except in Delphi and TP modes). Use a while or
+% repeat loop instead if you need to do something like that, since those
+% constructs were built for that.
+parser_e_no_local_var_external=03209_E_Le variabili locali non si possono dichiarare EXTERNAL
+% Declaring local variables as external is not allowed. Only global variables can reference
+% external variables.
+parser_e_proc_already_external=03210_E_La procedura è già dichiarata EXTERNAL
+% The procedure is already declared with the EXTERNAL directive in an interface or
+% forward declaration.
+parser_w_implicit_uses_of_variants_unit=03211_W_Uso implicito della unit Variants
+% The Variant type is used in the unit without any used unit using the Variants unit. The
+% compiler has implicitly added the Variants unit to the uses list. To remove this warning
+% the Variants unit needs to be added to the uses statement.
+parser_e_no_static_method_in_interfaces=03212_E_Classi e metodi statici non si possono usare in INTERFACES
+% The specifier \var{class} and directive \var{static} can't be used in interfaces
+% because all methods of an interface must be public.
+parser_e_arithmetic_operation_overflow=03213_E_Overflow in una operazione aritmetica
+% An operation on two integer values produced an overflow.
+parser_e_protected_or_private_expected=03214_E_Qui erano attesi Protected oppure private (ma non ci sono)
+% \var{strict} can be only used together with \var{protected} or \var{private}.
+parser_e_illegal_slice=03215_E_SLICE non si può usare fuori dalla lista dei parametri
+% \var{slice} can be used only for arguments accepting an open array parameter.
+parser_e_dispinterface_cant_have_parent=03216_E_Una DISPINTERFACE non può avere una classe antenato
+% A DISPINTERFACE is a special type of interface which can't have a parent class.
+parser_e_dispinterface_needs_a_guid=03217_E_Una DISPINTERFACE deve avere un GUID
+% A DISPINTERFACE always needs an interface identification (a GUID).
+parser_w_overridden_methods_not_same_ret=03218_W_I metodi overloadati devono avere un tipo di ritorno analogo. Questo codice può crashare a causa di un bug nel parser Delphi ("$2" è overloadato da "$1" che ritorna un tipo diverso)
+% If you declare overridden methods in a class definition, they must
+% have the same return type. Some versions of Delphi allow you to change the
+% return type of interface methods, and even to change procedures into
+% functions, but the resulting code may crash depending on the types used
+% and the way the methods are called.
+parser_e_dispid_must_be_ord_const=03219_E_Gli ID Dispatch devono essere costanti ordinali
+% The \var{dispid} keyword must be followed by an ordinal constant (the dispid index).
+parser_e_array_range_out_of_bounds=03220_E_L'intervallo dell'array è troppo grande
+% Regardless of the size taken up by its elements, an array cannot have more
+% than high(ptrint) elements. Additionally, the range type must be a subrange
+% of ptrint.
+parser_e_packed_element_no_var_addr=03221_E_Non si può accedere agli indirizzi di elementi di array o campi di record bit packed
+% If you declare an array or record as \var{packed} in Mac Pascal mode
+% (or as \var{packed} in any mode with \var{\{\$bitpacking on\}}), it will
+% be packed at the bit level. This means it becomes impossible to take addresses
+% of individual array elements or record fields. The only exception to this rule
+% is in the case of packed arrays elements whose packed size is a multple of 8 bits.
+parser_e_packed_dynamic_open_array=03222_E_Gli array dinamici non possono essere packed
+% Only regular (and possibly in the future also open) arrays can be packed.
+parser_e_packed_element_no_loop=03223_E_Non si possono usare elementi di array o campi di record bit packed come variabili di un loop
+% If you declare an array or record as \var{packed} in Mac Pascal mode
+% (or as \var{packed} in any mode with \var{\{\$bitpacking on\}}), it will
+% be packed at the bit level. For performance reasons, they cannot be
+% used as loop variables.
+parser_e_type_and_var_only_in_generics=03224_E_VAR e TYPE sono permessi solo nei generic
+% The usage of VAR and TYPE to declare new types inside an object is allowed only inside
+% generics.
+parser_e_cant_create_generics_of_this_type=03225_E_Questo tipo non può essere un generic
+% Only Classes, Objects, Interfaces and Records are allowed to be used as generic.
+parser_w_no_lineinfo_use_switch=03226_W_Non caricare la unit LINEINFO manualmente, Usare lo switch -gl del compilatore per farlo
+% Do not use the \file{lineinfo} unit directly, Use the \var{-gl} switch which
+% automatically adds the correct unit for reading the selected type of debugging
+% information. The unit that needs to be used depends on the type of
+% debug information used when compiling the binary.
+parser_e_no_funcret_specified=03227_E_La funzione "$1" deve dichiarare il tipo del suo risultato
+% The first time you declare a function you have to declare it completely,
+% including all parameters and the result type.
+parser_e_special_onlygenerics=03228_E_La specializzazione è supportata solo per i tipi generici
+% Types which are not generics can't be specialized.
+parser_e_no_generics_as_params=03229_E_Non si possono usare generici come parametri al momento della loro specializzazione
+% When specializing a generic, only non-generic types can be used as parameters.
+parser_e_type_object_constants=03230_E_Costanti di oggetti contenenti un VMT non sono permesse
+% If an object requires a VMT either because it contains a constructor or virtual methods,
+% it's not allowed to create constants of it. In TP and Delphi mode this is allowed
+% for compatibility reasons.
+parser_e_label_outside_proc=03231_E_Non è ammesso prendere l'indirizzo di label definite fuori della visibilità corrente
+% It isn't allowed to take the address of labels outside the
+% current procedure.
+parser_e_initialized_not_for_external=03233_E_Non si possono inizializzare variabili dichiarate external
+% Variables declared as external cannot be initialized with a default value.
+parser_e_illegal_function_result=03234_E_Il tipo del risultato della funzione è illegale
+% Some types like file types cannot be used as function result.
+parser_e_no_common_type=03235_E_Non esistono tipi in comune fra "$1" e "$2"
+% To perform an operation on integers, the compiler converts both operands
+% to their common type, which appears to be an invalid type. To determine the
+% common type of the operands, the compiler takes the minimum of the minimal values
+% of both types, and the maximum of the maximal values of both types. The common
+% type is then minimum..maximum.
+parser_e_no_generics_as_types=03236_E_Generici senza specializzazione non si possono usare come tipi per una variabile
+% Generics must be always specialized before being used as variable type.
+parser_w_register_list_ignored=03237_W_Le liste di registri sono ignorate per routines in assembler puro
+% When using pure assembler routines, the list with modified registers is ignored.
+parser_e_implements_must_be_class_or_interface=03238_E_La proprietà IMPLEMENTS deve avere un tipo classe o interfaccia
+% A property which implements an interface must be of type class or interface.
+parser_e_implements_must_have_correct_type=03239_E_Le proprietà IMPLEMENTS devono implementare interfacce del tipo giusto. Trovato tipo "$1" ma serviva "$2"
+% A property which implements an interface actually implements a different interface.
+parser_e_implements_must_read_specifier=03240_E_Le proprietà IMPLEMENTS devono avere specificatore di lettura
+% A property which implements an interface must have at least a read specifier.
+parser_e_implements_must_not_have_write_specifier=03241_E_Le proprietà IMPLEMENTS non devono avere specificatore di scrittura
+% A property which implements an interface may not have a write specifier.
+parser_e_implements_must_not_have_stored_specifier=03242_E_Le proprietà IMPLEMENTS non devono avere specificatore stored
+% A property which implements an interface may not have a stored specifier.
+parser_e_implements_uses_non_implemented_interface=03243_E_Proprietà IMPLEMENTS usata su una interfaccia non implementata: "$1"
+% The interface which is implemented by a property is not an interface implemented by the class.
+parser_e_unsupported_real=03244_E_Questa destinazione non supporta la virgola mobile
+% The compiler parsed a floating point expression, but it is not supported.
+parser_e_class_doesnt_implement_interface=03245_E_La classe "$1" non implementa l'interfaccia "$2"
+% The delegated interface is not implemented by the class given in the implements clause.
+parser_e_class_implements_must_be_interface=03246_E_Il tipo usato da IMPLEMENTS deve essere un'interfaccia
+% The \var{implements} keyword must be followed by an interface type.
+parser_e_cant_export_var_different_name=03247_E_Non si possono esportare variabili con un nome diverso su questa destinazione, aggiungere il nome alla dichiarazione con la direttiva "export" (nome variabile: $1, nome di export dichiarato: $2)
+% On most targets it is not possible to change the name under which a variable
+% is exported inside the \var{exports} statement of a library.
+% In that case, you have to specify the export name at the point where the
+% variable is declared, using the \var{export} and \var{alias} directives.
+parser_e_weak_external_not_supported=03248_E_La destinazione attuale non supporta simboli esterni deboli
+% A "weak external" symbol is a symbol which may or may not exist at (either static
+% or dynamic) link time. This concept may not be available (or implemented yet)
+% on the current cpu/OS target.
+parser_e_forward_mismatch=03249_E_La dichiarazione e l'implementazione del tipo non corrispondono
+% Classes and interfaces being defined forward must have the same type
+% when being implemented. A forward interface cannot be changed into a class.
+parser_n_ignore_lower_visibility=03250_N_Il metodo virtuale "$1" ha una visibilità minore ($2) della classe padre $3 ($4)
+% The virtual method overrides a method that is declared with a higher visibility. This might give
+% unexpected results. In case the new visibility is private than it might be that a call to inherited in a
+% new child class will call the higher visible method in a parent class and ignores the private method.
+parser_e_field_not_allowed_here=03251_E_I campi non possono comparire dopo la definizione di un metodo o di una proprietà: iniziare una nuova sezione di visibilità prima
+% Once a method or property has been defined in a class or object, you cannot define any fields afterwards
+% without starting a new visibility section (such as \var{public}, \var{private}, etc.). The reason is
+% that otherwise the source code can appear ambiguous to the compiler, since it is possible to use modifiers
+% such as \var{default} and \var{register} also as field names.
+parser_e_no_local_para_def=03252_E_I parametri non possono contenere definizioni di tipo locali. Usate una definizione di tipo a parte in un blocco type.
+% In Pascal, types are not considered to be identical simply because they are semantically equivalent.
+% Two variables or parameters are only considered to be of the same type if they refer to the
+% same type definition.
+% As a result, it is not allowed to define new types inside parameter lists, because then it is impossible to
+% refer to the same type definition in the procedure headers of the interface and implementation of a unit
+% (both procedure headers would define a separate type). Keep in mind that expressions such as
+% ``file of byte'' or ``string[50]'' also define a new type.
+parser_e_abstract_and_sealed_conflict=03253_E_Conflitto fra ABSTRACT e SEALED
+% ABSTRACT and SEALED cannot be used together in one declaration
+parser_e_sealed_descendant=03254_E_Non posso creare discendenti dalla classe "$1", perché è SEALED
+% Sealed means that class cannot be derived by another class.
+parser_e_sealed_class_cannot_have_abstract_methods=03255_E_Le classi SEALED non possono avere metodi ABSTRACT
+% Sealed means that class cannot be derived. Therefore no one class is able to override an abstract method in a sealed class.
+parser_e_only_virtual_methods_final=03256_E_Solo i metodi virtuali possono essere final
+% You are declaring a method as final, when it is not declared to be
+% virtual.
+parser_e_final_can_no_be_overridden=03257_E_I metodi final non si possono overloadare: "$1"
+% You are trying to \var{override} a virtual method of a parent class that does
+% not exist.
+parser_e_invalid_enumerator_identifier=03259_E_Identificatore di enumeratore non valido: "$1"
+% Only "MoveNext" and "Current" enumerator identifiers are supported.
+parser_e_enumerator_identifier_required=03260_E_E' necessario un identificatore di enumeratore
+% "MoveNext" or "Current" identifier must follow the \var{enumerator} modifier.
+parser_e_enumerator_movenext_is_not_valid=03261_E_Il metodo pattern enumerator MoveNext non è valido. Il metodo deve essere una funzione con tipo di ritorno boolean e senza argomenti.
+% "MoveNext" enumerator pattern method must be a function with Boolean return type and no required arguments
+parser_e_enumerator_current_is_not_valid=03262_E_La proprietà del pattern enumerator Current non è valida. La proprietà deve avere un getter.
+% "Current" enumerator pattern property must have a getter
+parser_e_only_one_enumerator_movenext=03263_E_E' permesso un solo metodo enumerator MoveNext per classe/oggetto
+% Class or Object can have only one enumerator MoveNext declaration.
+parser_e_only_one_enumerator_current=03264_E_E' permessa una sola proprietà enumerator Current per classe/oggetto
+% Class or Object can have only one enumerator Current declaration.
+parser_e_for_in_loop_cannot_be_used_for_the_type=03265_E_Non si possono usare for in loop per il tipo "$1"
+% For in loop can be used not for all types. For example it cannot be used for the enumerations with jumps.
+% \end{description}
+#
+# Type Checking
+#
+# 04087 is the last used one
+#
+% \section{Type checking errors}
+% This section lists all errors that can occur when type checking is
+% performed.
+% \begin{description}
+type_e_mismatch=04000_E_Type mismatch
+% This can happen in many cases:
+% \begin{itemize}
+% \item The variable you're assigning to is of a different type than the
+% expression in the assignment.
+% \item You are calling a function or procedure with parameters that are
+% incompatible with the parameters in the function or procedure definition.
+% \end{itemize}
+type_e_incompatible_types=04001_E_Incompatible types: got "$1" expected "$2"
+% There is no conversion possible between the two types.
+% Another possiblity is that they are declared in different
+% declarations:
+% \begin{verbatim}
+% Var
+% A1 : Array[1..10] Of Integer;
+% A2 : Array[1..10] Of Integer;
+%
+% Begin
+% A1:=A2; { This statement also gives this error. It
+% is due to the strict type checking of Pascal }
+% End.
+% \end{verbatim}
+type_e_not_equal_types=04002_E_I tipi "$1" e "$2" devono essere uguali ma non lo sono
+% The types are not equal.
+type_e_type_id_expected=04003_E_Qui era atteso un identificatore di tipo (ma non c'è)
+% The identifier is not a type, or you forgot to supply a type identifier.
+type_e_variable_id_expected=04004_E_Qui era atteso un identificatore di variabile (ma non c'è)
+% This happens when you pass a constant to a routine (such as \var{Inc} var or \var{Dec})
+% when it expects a variable. You can only pass variables as arguments to these functions.
+type_e_integer_expr_expected=04005_E_Qui era attesa una espressione intera, invece c'è "$1"
+% The compiler expects an expression of type integer, but gets a different
+% type.
+type_e_boolean_expr_expected=04006_E_Qui era attesa una espressione booleana, invece c'è "$1"
+% The expression must be a boolean type. It should be return \var{True} or
+% \var{False}.
+type_e_ordinal_expr_expected=04007_E_Qui era attesa una espressione ordinale (ma non c'è)
+% The expression must be of ordinal type, i.e., maximum a \var{Longint}.
+% This happens, for instance, when you specify a second argument
+% to \var{Inc} or \var{Dec} that doesn't evaluate to an ordinal value.
+type_e_pointer_type_expected=04008_E_Qui era atteso un tipo puntatore, invece c'è "$1"
+% The variable or expression isn't of the type \var{pointer}. This
+% happens when you pass a variable that isn't a pointer to \var{New}
+% or \var{Dispose}.
+type_e_class_type_expected=04009_E_Qui era atteso un tipo classe, invece c'è "$1"
+% The variable or expression isn't of the type \var{class}. This happens
+% typically when
+% \begin{enumerate}
+% \item The parent class in a class declaration isn't a class.
+% \item An exception handler (\var{On}) contains a type identifier that
+% isn't a class.
+% \end{enumerate}
+type_e_cant_eval_constant_expr=04011_E_L'espressione da valutare non ritorna una costante
+% This error can occur when the bounds of an array you declared do
+% not evaluate to ordinal constants.
+type_e_set_element_are_not_comp=04012_E_Gli elementi dell'insieme non sono compatibili
+% You are trying to perform an operation on two sets, when the set element types
+% are not the same. The base type of a set must be the same when taking the
+% union.
+type_e_set_operation_unknown=04013_E_questa operazione non è implementata per gli insiemi
+% several binary operations are not defined for sets.
+% These include: \var{div}, \var{mod}, \var{**}, \var{>=} and \var{<=}.
+% The last two may be defined for sets in the future.
+type_w_convert_real_2_comp=04014_W_Conversione automatica di tipo da virgola mobile a COMP (che è un tipo intero)
+% An implicit type conversion from a real type to a \var{comp} is
+% encountered. Since \var{comp} is a 64 bit integer type, this may indicate
+% an error.
+type_h_use_div_for_int=04015_H_L'operatore di divisione fra tipi interi è 'DIV' e non '/'
+% When hints are on, then an integer division with the '/' operator will
+% produce this message, because the result will then be of type real.
+type_e_strict_var_string_violation=04016_E_I tipi stringa non corrispondono, a causa dello switch $V+
+% When compiling in \var{\{\$V+\}} mode, the string you pass as a parameter
+% should be of the exact same type as the declared parameter of the procedure.
+type_e_succ_and_pred_enums_with_assign_not_possible=04017_E_Non si possono usare succ o pred su enums con assegnazione stile C
+% If you declare an enumeration type which has C-like assignments
+% in it, such as in the following:
+% \begin{verbatim}
+% Tenum = (a,b,e:=5);
+% \end{verbatim}
+% then you cannot use the \var{Succ} or \var{Pred} functions with this enumeration.
+type_e_cant_read_write_type=04018_E_Le variabili di questo tipo non si possono leggere o scrivere da file direttamente
+% You are trying to \var{read} or \var{write} a variable from or to a
+% file of type text, which doesn't support that variable's type.
+% Only integer types, reals, pchars and strings can be read from or
+% written to a text file. Booleans can only be written to text files.
+type_e_no_readln_writeln_for_typed_file=04019_E_Non si possono usare readln o writeln su file che non sono di tipo testo
+% \var{readln} and \var{writeln} are only allowed for text files.
+type_e_no_read_write_for_untyped_file=04020_E_Non si possono usare read o write su file senza tipo.
+% \var{read} and \var{write} are only allowed for text or typed files.
+type_e_typeconflict_in_set=04021_E_Conflitto di tipo fra elementi dell'insieme
+% There is at least one set element which is of the wrong type, i.e. not of
+% the set type.
+type_w_maybe_wrong_hi_lo=04022_W_lo/hi(dword/qword) ritorna la word/dword inferiore/superiore
+% \fpc supports an overloaded version of \var{lo/hi} for \var{longint/dword/int64/qword}
+% which returns the lower/upper word/dword of the argument. \tp always uses
+% a 16 bit \var{lo/hi} which always returns bits 0..7 for \var{lo} and the
+% bits 8..15 for \var{hi}. If you want the \tp behavior you have
+% to type cast the argument to a \var{word} or \var{integer}.
+type_e_integer_or_real_expr_expected=04023_E_Qui era attesa una espressione intera o reale
+% The first argument to \var{str} must be a real or integer type.
+type_e_wrong_type_in_array_constructor=04024_E_Tipo "$1" errato nel costruttore dell'array
+% You are trying to use a type in an array constructor which is not
+% allowed.
+type_e_wrong_parameter_type=04025_E_Tipo incompatibile per l'argomento n. $1: trovato "$2", serviva "$3"
+% You are trying to pass an invalid type for the specified parameter.
+type_e_no_method_and_procedure_not_compatible=04026_E_Non si può assegnare un metodo a una variabile procedura, né una procedura a un puntatore a metodo
+% You can't assign a method to a procedure variable or a procedure to a
+% method pointer.
+type_e_wrong_math_argument=04027_E_Passata una costante illegale a una funzione matematica interna
+% The constant argument passed to a \var{ln} or \var{sqrt} function is out of
+% the definition range of these functions.
+type_e_no_addr_of_constant=04028_E_Non si può ottenere l'indirizzo di una espressione costante
+% It is not possible to get the address of a constant expression, because they
+% aren't stored in memory. You can try making it a typed constant. This error
+% can also be displayed if you try to pass a property to a var parameter.
+type_e_argument_cant_be_assigned=04029_E_A questo argomento non possono essere assegnati valori
+% Only expressions which can be on the left side of an
+% assignment can be passed as call by reference arguments.
+%
+% Remark: Properties can be used on the left side of an assignment,
+% nevertheless they cannot be used as arguments.
+type_e_cannot_local_proc_to_procvar=04030_E_Non si possono assegnare procedure/funzioni locali a variabili procedura
+% It's not allowed to assign a local procedure/function to a
+% procedure variable, because the calling convention of a local procedure/function is
+% different. You can only assign local procedure/function to a void pointer.
+type_e_no_assign_to_addr=04031_E_Non si possono assegnare valori a un indirizzo di memoria
+% It is not allowed to assign a value to an address of a variable, constant,
+% procedure or function. You can try compiling with -So if the identifier
+% is a procedure variable.
+type_e_no_assign_to_const=04032_E_Non si possono assegnare valori a variabili dichiarate const
+% It's not allowed to assign a value to a variable which is declared
+% as a const. This is normally a parameter declared as const. To allow
+% changing the value, pass the parameter by value, or a parameter by reference
+% (using var).
+type_e_array_required=04033_E_E' richiesto un tipo array
+% If you are accessing a variable using an index '[<x>]' then
+% the type must be an array. In FPC mode a pointer is also allowed.
+type_e_interface_type_expected=04034_Qui era atteso un tipo interfaccia, invece c'è "$1"
+% The compiler expected to encounter an interface type name, but got something else.
+% The following code would produce this error:
+% \begin{verbatim}
+% Type
+% TMyStream = Class(TStream,Integer)
+% \end{verbatim}
+type_h_mixed_signed_unsigned=04035_H_Mescolare longword ed espressioni con segno dà un risultato a 64bit
+% If you divide (or calculate the modulus of) a signed expression by a longword (or vice versa),
+% or if you have overflow and/or range checking turned on and use an arithmetic
+% expression (+, -, *, div, mod) in which both signed numbers and longwords appear,
+% then everything has to be evaluated in 64-bit arithmetic which is slower than normal
+% 32-bit arithmetic. You can avoid this by typecasting one operand so it
+% matches the result type of the other one.
+type_w_mixed_signed_unsigned2=04036_W_In questo punto, mescolare espressioni con segno e tipi cardinali può provocare un errore di controllo range
+% If you use a binary operator (and, or, xor) and one of
+% the operands is a longword while the other one is a signed expression, then,
+% if range checking is turned on, you may get a range check error because in
+% such a case both operands are converted to longword before the operation is
+% carried out. You can avoid this by typecasting one operand so it
+% matches the result type of the other one.
+type_e_typecast_wrong_size_for_assignment=04037_E_La conversione di tipo causa dimensioni diverse ($1 -> $2) nell'assegnazione
+% Type casting to a type with a different size is not allowed when the variable is
+% used in an assignment.
+type_e_array_index_enums_with_assign_not_possible=04038_E_Gli enum con assegnazione non si possono usare come indici di array
+% When you declared an enumeration type which has C-like
+% assignments, such as in the following:
+% \begin{verbatim}
+% Tenum = (a,b,e:=5);
+% \end{verbatim}
+% you cannot use it as the index of an array.
+type_e_classes_not_related=04039_E_I tipi classe o oggetto "$1" e "$2" non sono correlati. Conversione di tipo impossibile.
+% There is a typecast from one class or object to another while the class/object
+% are not related. This will probably lead to errors.
+type_w_classes_not_related=04040_W_I tipi classe "$1" e "$2" non sono correlati.
+% There is a typecast from one class to another while the classes
+% are not related. This will probably lead to errors.
+type_e_class_or_interface_type_expected=04041_E_Qui era atteso un tipo classe o interfaccia, invece c'è il tipo "$1"
+% The compiler expected a class or interface name, but got another type or identifier.
+type_e_type_is_not_completly_defined=04042_E_Il tipo "$1" non è completamente definito
+% This error occurs when a type is not complete: i.e. a pointer type which points to
+% an undefined type.
+type_w_string_too_long=04043_W_Il letterale stringa è troppo lungo per una short string (lunghezza maggiore di 255)
+% The size of the constant string, which is assigned to a shortstring,
+% is longer than the maximum size of the shortstring (255 characters).
+type_w_signed_unsigned_always_false=04044_W_A causa dei range diversi, il confronto è sempre FALSE
+% There is a comparison between an unsigned value and a signed constant which is
+% less than zero. Because of type promotion, the statement will always evaluate to
+% false. Explicitly typecast the constant to the correct range to avoid this problem.
+type_w_signed_unsigned_always_true=04045_W_A causa dei range diversi, il confronto è sempre TRUE
+% There is a comparison between an unsigned value and a signed constant which is
+% less than zero. Because of type promotion, the statement will always evaluate to
+% true. Explicitly typecast the constant to the correct range to avoid this problem.
+type_w_instance_with_abstract=04046_W_Costruzione della classe "$1" con metodo "$2" astratto
+% An instance of a class is created which contains non-implemented abstract
+% methods. This will probably lead to a runtime error 211 in the code if that
+% routine is ever called. All abstract methods should be overriden.
+type_h_in_range_check=04047_H_L'operando a sinistra dell'operatore IN dovrebbe avere la dimensione di un byte
+% The left operand of the \var{in} operator is not an ordinal or enumeration which fits
+% within 8 bits. This may lead to range check errors. The \var{in} operator
+% currently only supports a left operand which fits within a byte. In the case of
+% enumerations, the size of an element of an enumeration can be controlled with
+% the \var{\{\$PACKENUM\}} or \var{\{\$Zn\}} switches.
+type_w_smaller_possible_range_check=04048_W_Differenza nella dimensione dei tipi: possibili perdite di dati o errori di overflow
+% There is an assignment to a smaller type than the source type. This means that
+% this may cause a range-check error, or may lead to possible loss of data.
+type_h_smaller_possible_range_check=04049_H_Differenza nella dimensione dei tipi: possibili perdite di dati o errori di overflow
+% There is an assignment to a smaller type than the source type. This means that
+% this may cause a range-check error, or may lead to possible loss of data.
+type_e_cant_take_address_of_abstract_method=04050_E_Non si può prendere l'indirizzo di un metodo astratto
+% An abstract method has no body, so the address of an abstract method can't be taken.
+type_e_assignment_not_allowed=04051_E_Non si possono assegnare valori a parametri formali o ad array aperti
+% You are trying to assign a value to a formal (untyped var, const or out)
+% parameter, or to an open array.
+type_e_constant_expr_expected=04052_E_Qui era attesa una espressione costante
+% The compiler expects an constant expression, but gets a variable expression.
+type_e_operator_not_supported_for_types=04053_E_L'operazione "$1" non è possibile sui tipi "$2" e "$3"
+% The operation is not allowed for the supplied types.
+type_e_illegal_type_conversion=04054_E_La conversione dal tipo "$1" al tipo "$2" è illegale
+% When doing a type-cast, you must take care that the sizes of the variable and
+% the destination type are the same.
+type_h_pointer_to_longint_conv_not_portable=04055_H_La conversione fra ordinali e puntatori non è portabile
+% If you typecast a pointer to a longint (or vice-versa), this code will not compile
+% on a machine using 64 bits addressing.
+type_w_pointer_to_longint_conv_not_portable=04056_W_La conversione fra ordinali e puntatori non è portabile
+% If you typecast a pointer to an ordinal type of a different size (or vice-versa), this can
+% cause problems. This is a warning to help in finding the 32-bit specific code where cardinal/longint is used
+% to typecast pointers to ordinals. A solution is to use the ptrint/ptruint types instead.
+type_e_cant_choose_overload_function=04057_E_La funzione non ha alcun overload per parametri di questo tipo
+% You're calling overloaded functions with a parameter that doesn't correspond
+% to any of the declared function parameter lists. e.g. when you have declared
+% a function with parameters \var{word} and \var{longint}, and then you call
+% it with a parameter which is of type \var{integer}.
+type_e_illegal_count_var=04058_E_La variabile contatore del loop deve essere un tipo ordinale
+% The type of a \var{for} loop variable must be an ordinal type.
+% Loop variables cannot be reals or strings.
+type_w_double_c_varargs=04059_W_Conversione di costanti real a double per variabili argomento C: aggiungere un typecast esplicito per prevenirlo.
+% In C, constant real values are double by default. For this reason, if you
+% pass a constant real value to a variable argument part of a C function, FPC
+% by default converts this constant to double as well. If you want to prevent
+% this from happening, add an explicit typecast around the constant.
+type_e_class_or_cominterface_type_expected=04060_E_Qui era atteso un tipo interfaccia classe o COM, invece c'è il tipo "$1"
+% Some operators, such as the AS operator, are only applicable to classes or COM interfaces.
+type_e_no_const_packed_array=04061_E_Array packed costanti non sono ancora supportati
+% You cannot declare a (bit)packed array as a typed constant.
+type_e_got_expected_packed_array=04062_E_Tipo incompatibile: argomento n. $1 di tipo "$2", invece deve essere "(Bit)Packed Array"
+% The compiler expects a (bit)packed array as the specified parameter.
+type_e_got_expected_unpacked_array=04063_E_Tipo incompatibile: argomento n. $1 di tipo "$2", invece deve essere "(not packed) Array"
+% The compiler expects a regular (i.e., not packed) array as the specified parameter.
+type_e_no_packed_inittable=04064_E_Gli elementi di un array packed non possono essere di un tipo che deve essere inizializzato
+% Support for packed arrays of types that need initialization
+% (such as ansistrings, or records which contain ansistrings) is not yet implemented.
+type_e_no_const_packed_record=04065_E_Oggetti o record packed costanti non sono ancora supportati
+% You cannot declare a (bit)packed array as a typed constant at this time.
+type_w_untyped_arithmetic_unportable=04066_W_L'aritmetica "$1" su puntatori senza tipo non è portabile su {$T+}, si suggerisce un typecast
+% Addition/subtraction from an untyped pointer may work differently in \var{\{\$T+\}}.
+% Use a typecast to a typed pointer.
+type_e_cant_take_address_of_local_subroutine=04076_E_Non si può prendere l'indirizzo di una subroutine marcata come local
+% The address of a subroutine marked as local can't be taken.
+type_e_cant_export_local=04077_E_Una subroutine marcata come local non è esportabile fuori dalla unit
+% A subroutine marked as local can't be exported from a unit.
+type_e_not_automatable=04078_E_Il tipo "$1" non è automatizzabile
+% Only byte, integer, longint, smallint, currency, single, double, ansistring,
+% widestring, tdatetime, variant, olevariant, wordbool and all interfaces are automatable.
+type_h_convert_add_operands_to_prevent_overflow=04079_H_Convertire gli operandi a "$1" prima dell'addizione può evitare errori di overflow
+% Adding two types can cause overflow errors. Since you are converting the result to a larger type, you
+% could prevent such errors by converting the operands to this type before doing the addition.
+type_h_convert_sub_operands_to_prevent_overflow=04080_H_Convertire gli operandi a "$1" prima della sottrazione può evitare errori di overflow
+% Subtracting two types can cause overflow errors. Since you are converting the result to a larger type, you
+% could prevent such errors by converting the operands to this type before doing the subtraction.
+type_h_convert_mul_operands_to_prevent_overflow=04081_H_Convertire gli operandi a "$1" prima della moltiplicazione può evitare errori di overflow
+% Multiplying two types can cause overflow errors. Since you are converting the result to a larger type, you
+% could prevent such errors by converting the operands to this type before doing the multiplication.
+type_w_pointer_to_signed=04082_W_Convertire puntatori in interi con segno può portare a confronti errati ed errori di range: meglio usare un tipo senza segno
+% The virtual address space on 32-bit machines runs from \$00000000 to \$ffffffff.
+% Many operating systems allow you to allocate memory above \$80000000.
+% For example both \windows and \linux allow pointers in the range \$0000000 to \$bfffffff.
+% If you convert pointers to signed types, this can cause overflow and range check errors,
+% but also \$80000000 < \$7fffffff. This can cause random errors in code like "if p>q".
+type_interface_has_no_guid=04083_E_Il tipo interfaccia $1 non ha un GUID valido
+% When applying the as-operator to an interface or class, the desired interface (i.e. the right operand of the
+% as-operator) must have a valid GUID.
+type_e_invalid_objc_selector_name=04084_E_Nome di selettore non valido
+% An Objective-C selector cannot be empty, must be a valid identifier or a single colon,
+% and if it contains at least one colon it must also end in one.
+type_e_expected_objc_method_but_got=04085_E_Qui era atteso un metodo Objective-C, invece c'è $1
+% A selector can only be created for Objective-C methods, not for any other kind
+% of procedure/function/method.
+type_e_expected_objc_method=04086_E_Qui era atteso un metodo Objective-C o un nome di un metodo costante
+% A selector can only be created for Objective-C methods, either by specifying
+% the name using a string constant, or by using an Objective-C method identifier
+% that is visible in the current scope.
+type_e_no_type_info=04087_E_Nessuna informazione sul tipo disponibile per questo tipo
+% Type information is not generated for some types, such as enumerations with gaps
+% in their value range (this includes enumerations whose lower bound is different
+% from zero).
+% \end{description}
+#
+# Symtable
+#
+# 05069 is the last used one
+#
+% \section{Symbol handling}
+% This section lists all the messages that concern the handling of symbols.
+% This means all things that have to do with procedure and variable names.
+% \begin{description}
+sym_e_id_not_found=05000_E_Identificatore "$1" non trovato
+% The compiler doesn't know this symbol. Usually happens when you misspell
+% the name of a variable or procedure, or when you forget to declare a
+% variable.
+sym_f_internal_error_in_symtablestack=05001_F_Errore interno del compilatore in SymTableStack()
+% An internal error occurred in the compiler; If you encounter such an error,
+% please contact the developers and try to provide an exact description of
+% the circumstances in which the error occurs.
+sym_e_duplicate_id=05002_E_Identificatore "$1" duplicato
+% The identifier was already declared in the current scope.
+sym_h_duplicate_id_where=05003_H_Identificatore già definito in $1 alla riga $2
+% The identifier was already declared in a previous scope.
+sym_e_unknown_id=05004_E_Identificatore "$1" sconosciuto
+% The identifier encountered has not been declared, or is used outside the
+% scope where it is defined.
+sym_e_forward_not_resolved=05005_E_Dichiarazione "$1" priva di implementazione
+% This can happen in two cases:
+% \begin{itemize}
+% \item You declare a function in the \var{interface} part, or
+% with a \var{forward} directive, but do not implement it.
+% \item You reference a type which isn't declared in the current \var{type}
+% block.
+% \end{itemize}
+sym_e_error_in_type_def=05007_E_Errore nella definizione del tipo
+% There is an error in your definition of a new array type.
+% One of the range delimiters in an array declaration is erroneous.
+% For example, \var{Array [1..1.25]} will trigger this error.
+sym_e_forward_type_not_resolved=05009_E_Tipo "$1" dichiarato ma non implementato
+% A symbol was forward defined, but no declaration was encountered.
+sym_e_only_static_in_static=05010_E_Al di fuori dei metodi o nei metodi statici si possono usare solo variabli statiche
+% A static method of an object can only access static variables.
+sym_f_type_must_be_rec_or_class=05012_F_Qui era atteso un tipo record o classe
+% The variable or expression isn't of the type \var{record} or \var{class}.
+sym_e_no_instance_of_abstract_object=05013_E_Non sono permesse istanze di classi o di oggetti con un metodo astratto
+% You are trying to generate an instance of a class which has an abstract
+% method that wasn't overridden.
+sym_w_label_not_defined=05014_W_Label "$1" non definita
+% A label was declared, but not defined.
+sym_e_label_used_and_not_defined=05015_E_Label "$1" usata ma non definita
+% A label was declared and used, but not defined.
+sym_e_ill_label_decl=05016_E_Dichiarazione di label illegale
+% This error should never happen; it occurs if a label is defined outside a
+% procedure or function.
+sym_e_goto_and_label_not_supported=05017_E_GOTO e LABEL non sono supportati (usare lo switch -Sg)
+% You must use the -Sg switch to compile a program which has \var{label}s
+% and \var{goto} statements. By default, \var{label} and \var{goto} aren't
+% supported.
+sym_e_label_not_found=05018_E_Label non trovata
+% A \var{goto label} was encountered, but the label wasn't declared.
+sym_e_id_is_no_label_id=05019_E_L'identificatore non è una label
+% The identifier specified after the \var{goto} isn't of type label.
+sym_e_label_already_defined=05020_E_Label già definita
+% You are defining a label twice. You can define a label only once.
+sym_e_ill_type_decl_set=05021_E_La dichiarazione del tipo di un elemento in un insieme è illegale
+% The declaration of a set contains an invalid type definition.
+sym_e_class_forward_not_resolved=05022_E_Classe "$1" dichiarata ma non implementata
+% You declared a class, but you did not implement it.
+sym_n_unit_not_used=05023_H_La unit "$1" non è usata in $2
+% The unit referenced in the \var{uses} clause is not used.
+sym_h_para_identifier_not_used=05024_H_Parametro "$1" non usato
+% The identifier was declared (locally or globally) but
+% was not used (locally or globally).
+sym_n_local_identifier_not_used=05025_N_Variabile locale "$1" non usata
+% You have declared, but not used, a variable in a procedure or function
+% implementation.
+sym_h_para_identifier_only_set=05026_H_Al parametro "$1" è assegnato un valore, ma poi non viene mai usato
+% The identifier was declared (locally or globally) and
+% assigned to, but is not used (locally or globally) after the assignment.
+sym_n_local_identifier_only_set=05027_N_La variabile locale "$1" è assegnata ma non viene mai usata
+% The variable in a procedure or function implementation is declared and
+% assigned to, but is not used after the assignment.
+sym_h_local_symbol_not_used=05028_H_Locale $1 "$2" non è mai usato
+% A local symbol is never used.
+sym_n_private_identifier_not_used=05029_N_Il campo privato "$1.$2" non viene mai usato
+% The indicated private field is defined, but is never used in the code.
+sym_n_private_identifier_only_set=05030_N_Il campo privato "$1.$2" è assegnato ma poi non viene mai usato
+% The indicated private field is declared and assigned to, but never read.
+sym_n_private_method_not_used=05031_N_Il metodo privato "$1.$2" non è mai usato
+% The indicated private method is declared but is never used in the code.
+sym_e_set_expected=05032_E_Qui era atteso un tipo insieme
+% The variable or expression is not of type \var{set}. This happens in an
+% \var{in} statement.
+sym_w_function_result_not_set=05033_W_Il valore di ritorno della funzione non sembra essere mai assegnato
+% You can get this warning if the compiler thinks that a function return
+% value is not set. This will not be displayed for assembler procedures,
+% or procedures that contain assembler blocks.
+sym_w_wrong_C_pack=05034_W_Il tipo "$1" non è allineato correttamente per il linguaggio C
+% Arrays with sizes not multiples of 4 will be wrongly aligned
+% for C structures.
+sym_e_illegal_field=05035_E_L'identificatore del campo di un record "$1" è sconosciuto
+% The field doesn't exist in the record/object definition.
+sym_w_uninitialized_local_variable=05036_W_La variabile locale "$1" non sembra essere inizializzata
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. it appears in the right-hand side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assignment).
+sym_w_uninitialized_variable=05037_W_La variabile "$1" non sembra essere inizializzata
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. it appears in the right-hand side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assignment).
+sym_e_id_no_member=05038_E_L'identificatore "$1" non identifica alcun membro
+% This error is generated when an identifier of a record,
+% field or method is accessed while it is not defined.
+sym_h_param_list=05039_H_Trovata dichiarazione: $1
+% You get this when you use the \var{-vh} switch.In the case of an overloaded procedure
+% not being found. Then all candidate overloaded procedures are
+% listed, with their parameter lists.
+sym_e_segment_too_large=05040_E_Elemento dati troppo grande
+% You get this when you declare a data element whose size exceeds the
+% prescribed limit (2 Gb on 80386+/68020+ processors).
+sym_e_no_matching_implementation_found=05042_E_Non ci sono implementazioni corrispondenti per il metodo di interfaccia "$1"
+% There was no matching method found which could implement the interface
+% method. Check argument types and result type of the methods.
+sym_w_deprecated_symbol=05043_W_Il simbolo "$1" è deprecato
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{deprecated} is used. Deprecated symbols may no longer
+% be available in newer versions of the unit / library. Use of this symbol
+% should be avoided as much as possible.
+sym_w_non_portable_symbol=05044_W_Il simbolo "$1" non è portabile
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{platform} is used. This symbol's value, use
+% and availability is platform specific and should not be used
+% if the source code must be portable.
+sym_w_non_implemented_symbol=05055_W_Il simbolo "$1" non è implementato
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{unimplemented} is used. This symbol is defined,
+% but is not yet implemented on this specific platform.
+sym_e_cant_create_unique_type=05056_E_Non si può creare un tipo univoco dal tipo fornito
+% Only simple types like ordinal, float and string types are supported when
+% redefining a type with \var{type newtype = type oldtype;}.
+sym_h_uninitialized_local_variable=05057_H_La variabile locale "$1" non sembra essere inizializzata
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. it appears in the right-hand side of an expression) when it
+% was not initialized first (i.e. it did not appear in the left-hand side of an
+% assignment).
+sym_h_uninitialized_variable=05058_H_La variabile "$1" non sembra essere inizializzata
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. it appears in the right-hand side of an expression) when it
+% was not initialized first (i.e. t did not appear in the left-hand side of an
+% assignment).
+sym_w_function_result_uninitialized=05059_W_La variabile risultato della funzione sembra non essere ancora stata assegnata
+% This message is displayed if the compiler thinks that the function result
+% variable will be used (i.e. it appears in the right-hand side of an expression)
+% before it is initialized (i.e. before it appeared in the left-hand side of an
+% assignment).
+sym_h_function_result_uninitialized=05060_H_La variabile risultato della funzione sembra non essere ancora stata assegnata
+% This message is displayed if the compiler thinks that the function result
+% variable will be used (i.e. it appears in the right-hand side of an expression)
+% before it is initialized (i.e. it appears in the left-hand side of an
+% assignment)
+sym_w_identifier_only_read=05061_W_La variabile "$1" è letta ma mai assegnata
+% You have read the value of a variable, but nowhere assigned a value to
+% it.
+sym_h_abstract_method_list=05062_H_Trovato metodo astratto: $1
+% When getting a warning about constructing a class/object with abstract methods
+% you get this hint to assist you in finding the affected method.
+sym_w_experimental_symbol=05063_W_Il simbolo "$1" è sperimentale
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{experimental} is used. Experimental symbols
+% might disappear or change semantics in future versions. Usage of this symbol
+% should be avoided as much as possible.
+sym_w_forward_not_resolved=05064_W_Dichiarazione "$1" non implementata, si assume che sia external
+% This happens if you declare a function in the \var{interface} of a unit in macpas mode,
+% but do not implement it.
+sym_w_library_symbol=05065_W_Il simbolo "$1" appartiene a una libreria
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{library} is used. Library symbols may not be
+% available in other libraries.
+sym_w_deprecated_symbol_with_msg=05066_W_Il simbolo "$1" è deprecato: "$2"
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{deprecated} is used. Deprecated symbols may no longer
+% be available in newer versions of the unit / library. Use of this symbol
+% should be avoided as much as possible.
+sym_e_no_enumerator=05067_E_Non c'è un enumeratore per il tipo "$1"
+% This means that compiler cannot find an apropriate enumerator to use in the for-in loop.
+% To create an enumerator you need to defind an operator enumerator or add a public or published
+% GetEnumerator method to the class or object definition.
+sym_e_no_enumerator_move=05068_E_Non c'è un metodo "MoveNext" nell'enumeratore "$1"
+% This means that compiler cannot find a public MoveNext method with the Boolean return type in
+% the enumerator class or object definition.
+sym_e_no_enumerator_current=05069_E_Non c'è una proprietà "Current" nell'enumeratore "$1"
+% This means that compiler cannot find a public Current property in the enumerator class or object
+% definition.
+% \end{description}
+#
+# Codegenerator
+#
+# 06049 is the last used one
+#
+% \section{Code generator messages}
+% This section lists all messages that can be displayed if the code
+% generator encounters an error condition.
+% \begin{description}
+cg_e_parasize_too_big=06009_E_La lista dei parametri è più grande di 65535 bytes
+% The I386 processor limits the parameter list to 65535 bytes. (The \var{RET}
+% instruction causes this.)
+cg_e_file_must_call_by_reference=06012_E_I tipi file devono essere parametri var
+% You cannot specify files as value parameters, i.e., they must always be
+% declared \var{var} parameters.
+cg_e_cant_use_far_pointer_there=06013_E_Usare un puntatore far non è permesso qui
+% Free Pascal doesn't support far pointers, so you cannot take the address of
+% an expression which has a far reference as a result. The \var{mem} construct
+% has a far reference as a result, so the following code will produce this
+% error:
+% \begin{verbatim}
+% var p : pointer;
+% ...
+% p:=@mem[a000:000];
+% \end{verbatim}
+cg_e_dont_call_exported_direct=06015_E_Le funzioni dichiarare EXPORT non possono essere chiamate
+% No longer in use.
+cg_w_member_cd_call_from_method=06016_W_Possibile chiamata illegale di un costruttore o distruttore
+% The compiler detected that a constructor or destructor is called within a
+% a method. This will probably lead to problems, since constructors / destructors
+% require parameters on entry.
+cg_n_inefficient_code=06017_N_Codice inefficiente
+% Your statement seems dubious to the compiler.
+cg_w_unreachable_code=06018_W_Codice irraggiungibile
+% You specified a construct which will never be executed. Example:
+% \begin{verbatim}
+% while false do
+% begin
+% {.. code ...}
+% end;
+% \end{verbatim}
+cg_e_cant_call_abstract_method=06020_E_I metodi astratti non possono essere chiamati direttamente
+% You cannot call an abstract method directly. Instead, you must call an
+% overriding child method, because an abstract method isn't implemented.
+cg_d_register_weight=06027_DL_Il Registro $1 pesa $2 $3
+% Debugging message. Shown when the compiler considers a variable for
+% keeping in the registers.
+cg_d_stackframe_omited=06029_DL_Stack frame omesso
+% Some procedure/functions do not need a complete stack-frame, so it is omitted.
+% This message will be displayed when the {-vd} switch is used.
+cg_e_unable_inline_object_methods=06031_E_I metodi di oggetti e classi non possono essere inline
+% You cannot have inlined object methods.
+cg_e_unable_inline_procvar=06032_E_Chiamate procvar non possono essere inline
+% A procedure with a procedural variable call cannot be inlined.
+cg_e_no_code_for_inline_stored=06033_E_Non è stato memorizzato codice per la procedura inline
+% The compiler couldn't store code for the inline procedure.
+cg_e_can_access_element_zero=06035_E_Non si può accedere all'elemento zero di una ansi/wide/longstring, usare (set)length
+% You should use \var{setlength} to set the length of an ansi/wide/longstring
+% and \var{length} to get the length of such string type.
+cg_e_cannot_call_cons_dest_inside_with=06037_E_Non si possono chiamare costruttoro o distruttori all'interno di una clausola 'with'
+% Inside a \var{with} clause you cannot call a constructor or destructor for the
+% object you have in the \var{with} clause.
+cg_e_cannot_call_message_direct=06038_E_I metodi gestori di messaggi non possono essere chiamati direttamente
+% A message method handler method cannot be called directly if it contains an
+% explicit \var{Self} argument.
+cg_e_goto_inout_of_exception_block=06039_E_Non è permesso saltare da dentro a fuori un blocco di gestione delle eccezioni o viceversa
+% It is not allowed to jump in or outside of an exception block like \var{try..finally..end;}.
+% For example, the following code will produce this error:
+
+% \begin{verbatim}
+% label 1;
+%
+% ...
+%
+% try
+% if not(final) then
+% goto 1; // this line will cause an error
+% finally
+% ...
+% end;
+% 1:
+% ...
+% \end{verbatim}
+cg_e_control_flow_outside_finally=06040_E_Le istruzioni 'break', 'continue' ed 'exit' non sono ammesse in un blocco finally
+% It isn't allowed to use the control flow statements \var{break},
+% \var{continue} and \var{exit}
+% inside a finally statement. The following example shows the problem:
+% \begin{verbatim}
+% ...
+% try
+% p;
+% finally
+% ...
+% exit; // This exit ISN'T allowed
+% end;
+% ...
+%
+% \end{verbatim}
+% If the procedure \var{p} raises an exception the finally block is
+% executed. If the execution reaches the exit, it's unclear what to do:
+% exit the procedure or search for another exception handler.
+cg_w_parasize_too_big=06041_W_La dimensione dei parametri eccede il limite massimo di alcune CPU
+% This indicates that you are declaring more than 64K of parameters, which
+% might not be supported on other processor targets.
+cg_w_localsize_too_big=06042_W_La dimensione delle variabili locali eccede il limite massimo di alcune CPU
+% This indicates that you are declaring more than 32K of local variables, which
+% might not be supported on other processor targets.
+cg_e_localsize_too_big=06043_E_La dimensione delle variabili locali è eccessiva
+% This indicates that you are declaring more than 32K of local variables, which
+% is not supported by this processor.
+cg_e_break_not_allowed=06044_E_BREAK non è permesso fuori da un loop
+% You're trying to use \var{break} outside a loop construction.
+cg_e_continue_not_allowed=06045_E_CONTINUE non è permesso fuori da un loop
+% You're trying to use \var{continue} outside a loop construction.
+cg_f_unknown_compilerproc=06046_F_Compilerproc "$1" sconosciuta. Verificate di stare usando la giusta libreria di runtime
+% The compiler expects that the runtime library contains certain subroutines. If you see this error
+% and you didn't change the runtime library code, it's very likely that the runtime library
+% you're using doesn't match the compiler in use. If you changed the runtime library this error means
+% that you removed a subroutine which the compiler needs for internal use.
+cg_f_unknown_system_type=06047_F_Il tipo di sistema "$1" non esiste. Verificate di stare usando la giusta libreria di runtime.
+% The compiler expects that the runtime library contains certain type definitions. If you see this error
+% and you didn't change the runtime library code, it's very likely that the runtime library
+% you're using doesn't match the compiler in use. If you changed the runtime library this error means
+% that you removed a type which the compiler needs for internal use.
+cg_h_inherited_ignored=06048_H_Ignorata una chiamata ereditata a un metodo astratto
+% This message appears only in Delphi mode when you call an abstract method
+% of a parent class via \var{inherited;}. The call is then ignored.
+cg_e_goto_label_not_found=06049_E_La label goto "$1" non è definita o è stata eliminata dalle ottimizzazioni
+% The label used in the goto definition is not defined or optimized away by the
+% unreachable code elemination.
+% \end{description}
+# EndOfTeX
+
+#
+# Assembler reader
+#
+# 07107 is the last used one
+#
+asmr_d_start_reading=07000_DL_Inizio analisi assembler stile $1
+% This informs you that an assembler block is being parsed
+asmr_d_finish_reading=07001_DL_Fine analisi assembler stile $1
+% This informs you that an assembler block has finished.
+asmr_e_none_label_contain_at=07002_E_Il pattern contiene @ ma non è una label
+% A identifier which isn't a label can't contain a @.
+asmr_e_building_record_offset=07004_E_Errore nella costruzione dell'offset di un record
+% There has an error occured while building the offset of a record/object
+% structure, this can happend when there is no field specified at all or
+% an unknown field identifier is used.
+asmr_e_offset_without_identifier=07005_E_usato OFFSET senza identificatore
+% You can only use OFFSET with an identifier. Other syntaxes aren't
+% supported
+asmr_e_type_without_identifier=07006_E_usato TYPE senza identificatore
+% You can only use TYPE with an identifier. Other syntaxes aren't
+% supported
+asmr_e_no_local_or_para_allowed=07007_E_Qui non si possono usare variabili o parametri locali
+% You can't use a local variable or parameter here, mostly because the
+% addressing of locals and parameters is done using the frame pointer register so the
+% address can't be obtained directly.
+asmr_e_need_offset=07008_E_Qui è necessario usare OFFSET
+% You need to use OFFSET <id> here to get the address of the identifier.
+asmr_e_need_dollar=07009_E_Qui è necessario usare $
+% You need to use $<id> here to get the address of the identifier.
+asmr_e_cant_have_multiple_relocatable_symbols=07010_E_Si può usare un solo simbolo rilocabile per ogni argomento
+% You can't have more than one relocatable symbol (variable/typed constant)
+% in one argument.
+asmr_e_only_add_relocatable_symbol=07011_E_Un simbolo rilocabile puà solo essere sommato
+% Relocatable symbols (variable/typed constant) can't be used with other
+% operators. Only addition is allowed.
+asmr_e_invalid_constant_expression=07012_E_Espressione costante non valida
+% There is an error in the constant expression.
+asmr_e_relocatable_symbol_not_allowed=07013_E_I simboli rilocabili non sono permessi qui
+% You can't use a relocatable symbol (variable/typed constant) here.
+asmr_e_invalid_reference_syntax=07014_E_Sintassi del reference non valida
+% There is an error in the reference.
+asmr_e_local_para_unreachable=07015_E_Impossibile raggiungere $1 da quel codice
+% You cannot read directly the value of a local variable or parameter
+% of a higher level procedure in assembler code (except for
+% local assembler code without parameter nor locals).
+asmr_e_local_label_not_allowed_as_ref=07016_E_Simboli o label locali non sono ammessi come reference
+% You can't use local symbols/labels as references
+asmr_e_wrong_base_index=07017_E_Uso errato dei registri base e indice
+% There is an error with the base and index register, they are
+% probably incorrect
+asmr_w_possible_object_field_bug=07018_W_Possibile errore nella gestione dei campi di un oggetto
+% Fields of objects or classes can be reached directly in normal or objfpc
+% modes but TP and Delphi modes treat the field name as a simple offset.
+asmr_e_wrong_scale_factor=07019_E_Specificato un fattore di scala errato
+% The scale factor given is wrong, only 1,2,4 and 8 are allowed
+asmr_e_multiple_index=07020_E_Uso di registri indice multipli
+% You are trying to use more than one index register
+asmr_e_invalid_operand_type=07021_E_Tipo di operando non valido
+% The operand type doesn't match with the opcode used
+asmr_e_invalid_string_as_opcode_operand=07022_E_Stringa non valida come operando dell'opcode: $1
+% The string specified as operand is not correct with this opcode
+asmr_w_CODE_and_DATA_not_supported=07023_W_@CODE e @DATA non supportati
+% @CODE and @DATA are unsupported and are ignored.
+asmr_e_null_label_ref_not_allowed=07024_E_Non sono ammessi riferimenti a label nulle
+asmr_e_expr_zero_divide=07025_E_Divisione per zero in una espressione asm costante
+% There is a division by zero in a constant expression
+asmr_e_expr_illegal=07026_E_Espressione illegale
+% There is an illegal expression in a constant expression
+asmr_e_escape_seq_ignored=07027_E_Ignorata sequenza di escape: $1
+% There is a C-styled string, but the escape sequence in the string
+% is unknown, and is therefore ignored
+asmr_e_invalid_symbol_ref=07028_E_Riferimento a simbolo non valido
+asmr_w_fwait_emu_prob=07029_W_Fwait può creare problemi di emulazione con emu387
+asmr_w_fadd_to_faddp=07030_W_$1 senza operandi tradotto in $1P
+asmr_w_enter_not_supported_by_linux=07031_W_L'istruzione ENTER non è supportata dal kernel Linux
+% ENTER instruction can generate a stack page fault that is not
+% caught correctly by the i386 Linux page handler.
+asmr_w_calling_overload_func=07032_W_Chiamata da assembler di una funzione overloaded
+% There is a call to an overloaded method in the assembler block,
+% this might be the sign there is a problem
+asmr_e_unsupported_symbol_type=07033_E_Tipo di simbolo non supportato per l'operando
+asmr_e_constant_out_of_bounds=07034_E_Costante fuori dai limiti
+asmr_e_error_converting_decimal=07035_E_Errore nella conversione decimale $1
+% A constant decimal value does not have the correct syntax
+asmr_e_error_converting_octal=07036_E_Errore nella conversione ottale $1
+% A constant octal value does not have the correct syntax
+asmr_e_error_converting_binary=07037_E_Errore nella conversione binaria $1
+% A constant binary value does not have the correct syntax
+asmr_e_error_converting_hexadecimal=07038_E_Errore nella conversione esadecimale $1
+% A constant hexadecimal value does not have the correct syntax
+asmr_h_direct_global_to_mangled=07039_H_$1 tradotto con $2
+asmr_w_direct_global_is_overloaded_func=07040_W_$1 è associato a una funzione overloaded
+asmr_e_cannot_use_SELF_outside_a_method=07041_E_Non si può usare SELF al di fuori di un metodo
+% There is a reference to the \var{self} symbol while it is not
+% allowed. \var{self} can only be referenced inside methods
+asmr_e_cannot_use_OLDEBP_outside_nested_procedure=07042_E_Non si può usare OLDEBP al di fuori di una procedura nidificata
+% There is a reference to the \var{oldebp} symbol while it is not
+% allowed. \var{oldebp} can only be referenced inside nested routines
+asmr_e_void_function=07043_W_Le procedure non possono ritornare alcun valore nel codice assembler
+% Trying to return a value while in a procedure. A procedure
+% does not have any return value
+asmr_e_SEG_not_supported=07044_E_SEG non supportato
+asmr_e_size_suffix_and_dest_dont_match=07045_E_Il suffisso di dimensione e la dimensione della destinazione non corrispondono
+% The register size and the opcode size suffix don't match. This is
+% probably an error in the assembler statement
+asmr_w_size_suffix_and_dest_dont_match=07046_W_Il suffisso di dimensione e la dimensione della destinazione non corrispondono
+% The register size and the opcode size suffix don't match. This is
+% probably an error in the assembler statement
+asmr_e_syntax_error=07047_E_Errore di sintassi nell'assembler
+% There is an assembler syntax error
+asmr_e_invalid_opcode_and_operand=07048_E_Combinazione di opcode e operandi non valida
+% The opcode cannot be used with this type of operand
+asmr_e_syn_operand=07049_E_Errore di sintassi nell'operando assembler
+asmr_e_syn_constant=07050_E_Errore di sintassi nella costante assembler
+asmr_e_invalid_string_expression=07051_E_Espressione stringa non valida
+asmr_w_const32bit_for_address=07052_W_costante con simbolo di indirizzo $1 che non entra in un puntatore
+% A constant expression represents an address which does not fit
+% into a pointer. The address is probably incorrect
+asmr_e_unknown_opcode=07053_E_Opcode $1 non riconosciuto
+% This opcode is not known
+asmr_e_invalid_or_missing_opcode=07054_E_Opcode non valido o mancante
+asmr_e_invalid_prefix_and_opcode=07055_E_Combinazione di prefisso e opcode: $1
+asmr_e_invalid_override_and_opcode=07056_E_Combinazione di override e opcode $1 non valida
+asmr_e_too_many_operands=07057_E_Troppi operandi su una sola riga
+% There are too many operands for this opcode. Check your
+% assembler syntax
+asmr_w_near_ignored=07058_W_NEAR ignorato
+asmr_w_far_ignored=07059_W_FAR ignorato
+asmr_e_dup_local_sym=07060_E_Simbolo locale $1 ignorato
+asmr_e_unknown_local_sym=07061_E_Simbolo locale $1 non definito
+asmr_e_unknown_label_identifier=07062_E_Identificatore label $1 non riconosciuto
+asmr_e_invalid_register=07063_E_Nome di registro non valido
+% There is an unknown register name used as operand.
+asmr_e_invalid_fpu_register=07064_E_Nome di registro virgola mobile non valido
+% There is an unknown register name used as operand.
+asmr_w_modulo_not_supported=07066_W_Modulo non supportato
+asmr_e_invalid_float_const=07067_E_Costante in virgola mobile $1 non valida
+% The floating point constant declared in an assembler block is
+% invalid.
+asmr_e_invalid_float_expr=07068_E_Espressione in virgola mobile non valida
+% The floating point expression declared in an assembler block is
+% invalid.
+asmr_e_wrong_sym_type=07069_E_Tipo di simbolo errato
+asmr_e_cannot_index_relative_var=07070_E_Non si possono indicizzare una variabile o un parametro locali con un registro
+% Trying to index using a base register a symbol which is already relative
+% to a register. This is not possible, and will probably lead to crashes.
+asmr_e_invalid_seg_override=07071_E_Espressione di override di segmento non valida
+asmr_w_id_supposed_external=07072_W_L'identificatore $1 non è definito: sarà considerato esterno
+% There is a reference to an undefined symbol. This will not result
+% in an error, since the symbol might be external, but may cause
+% problems at link time if the symbol is not defined anywhere.
+asmr_e_string_not_allowed_as_const=07073_E_Le stringhe non sono ammesse come costanti
+% Character strings are not allowed as constants.
+asmr_e_no_var_type_specified=07074_Nessun tipo di variabile specificato
+% The syntax expects a type identifier after the dot, but
+% none was found.
+asmr_w_assembler_code_not_returned_to_text=07075_E_Il codice assembler non è tornato nella sezione text
+% There was a directive in the assembler block to change sections,
+% but there is a missing return to the text section at the end
+% of the assembler block. This might cause errors during link time.
+asmr_e_not_directive_or_local_symbol=07076_E_$1 non è una direttiva né un simbolo locale
+% This symbol is unknown.
+asmr_w_using_defined_as_local=07077_E_Uso di un nome definito come label locale
+asmr_e_dollar_without_identifier=07078_E_Il token '$' è usato senza identificatori
+% A constant expression has an identifier which does not start with
+% the $ symbol.
+asmr_w_32bit_const_for_address=07079_W_Creata una costante a 32 bit per l'indirizzo
+% A constant was used as an address. This is probably an error,
+% since using absolute addresses will probably not work.
+asmr_n_align_is_target_specific=07080_N_.align è specifico per la destinazione: usare .balign oppure .p2align
+% Using the .align directive is platform specific, and its meaning will vary
+% from one platform to another.
+asmr_e_cannot_access_field_directly_for_parameters=07081_E_Non si può accedere direttamente dal parametro ai campi
+% You should load the parameter first into a register and then access the
+% fields using that register.
+asmr_e_cannot_access_object_field_directly=07082_E_Non si può accedere direttamente dalla classe/oggetto ai campi
+% You should load the self pointer first into a register and then access the
+% fields using the register as base. By default the self pointer is available
+% in the esi register on i386.
+asmr_e_unable_to_determine_reference_size=07083_E_Dimensione degli operandi non specificata ed impossibile da determinare
+% You should specify explicitly a size for the reference, because
+% the compiler is unable to determine what size (byte,word,dword,etc.) it
+% should use for the reference.
+asmr_e_cannot_use_RESULT_here=07084_E_Non si può usare RESULT in questa funzione
+% Some functions which return complex types cannot use the \var{result}
+% keyword.
+asmr_w_adding_explicit_args_fXX=07086_W_"$1" senza operandi tradotto con "$1 %st,%st(1)"
+asmr_w_adding_explicit_first_arg_fXX=07087_W_"$1 %st(n)" tradotto con "$1 %st,%st(n)"
+asmr_w_adding_explicit_second_arg_fXX=07088_W_"$1 %st(n)" tradotto con "$1 %st(n),%st"
+asmr_e_invalid_char_smaller=07089_E_Il carattere '<' non è permesso qui
+% The shift operator requires the << characters. Only one
+% of those characters was found.
+asmr_e_invalid_char_greater=07090_E_Il carattere '>' non è permesso qui
+% The shift operator requires the >> characters. Only one
+% of those characters was found.
+asmr_w_align_not_supported=07093_W_ALIGN non è supportato
+asmr_e_no_inc_and_dec_together=07094_E_Non si possono usare Inc e Dec insieme
+% Trying to use an increment and a decrement within the same
+% opcode on the 680x0. This is impossible.
+asmr_e_invalid_reg_list_in_movem=07095_E_La reglist per movem non è valida
+% Trying to use the \var{movem} opcode with invalid registers
+% to save or restore.
+asmr_e_invalid_reg_list_for_opcode=07096_E_La reglist per l'opcode non è valida
+asmr_e_higher_cpu_mode_required=07097_E_Necessaria una classe di cpu più alta ($1)
+% Trying to use an instruction which is not supported in the current
+% cpu mode. Use a higher cpu generation to be able to use this
+% opcode in your assembler block
+asmr_w_unable_to_determine_reference_size_using_dword=07098_W_Dimensione degli operandi non specificata ed impossibile da determinare, assunta DWORD come default
+% You should specify explicitly a size for the reference, because
+% the compiler is unable to determine what size (byte,word,dword,etc.) it
+% should use for the reference. This warning is only used in Delphi mode where
+% it falls back to use DWORD as default.
+asmr_e_illegal_shifterop_syntax=07099_E_Errore di sintassi nell'analisi di un operando shifter
+% ARM only; ARM assembler supports a so called shifter operand. The used syntax isn't
+% a valid shifter operand. Example for an operation with shifter operand:
+% \begin{verbatim}
+% asm
+% orr r2,r2,r2,lsl #8
+% end;
+% \end{verbatim}
+asmr_e_packed_element=07100_E_Indirizzo di componenti packed non allineato al byte
+% Packed components (record fields and array elements) may start at an arbitrary
+% bit inside a byte. On CPU which do not support bit-addressable memory (which
+% includes all currently supported CPUs by FPC) you will therefore get an error
+% message when trying to index arrays with elements whose size is not a multiple
+% of 8 bits. The same goes for accessing record fields with such an address.
+% multiple of 8 bits.
+asmr_w_unable_to_determine_reference_size_using_byte=07101_W_Dimensione degli operandi non specificata ed impossibile da determinare, assunta BYTE come default
+% You should specify explicitly a size for the reference, because
+% the compiler is unable to determine what size (byte,word,dword,etc.) it
+% should use for the reference. This warning is only used in Delphi mode where
+% it falls back to use BYTE as default.
+asmr_w_no_direct_ebp_for_parameter=07102_W_Qui non si può usare +offset(%ebp) per i parametri
+% Using direct 8(%ebp) reference for function/procedure parameters is invalid
+% if parameters are in registers.
+asmr_w_direct_ebp_for_parameter_regcall=07103_W_Usare +offset(%ebp) non è compatibile con la convenzione di chiamata regcall
+% Using direct 8(%ebp) reference for function/procedure parameters is invalid
+% if parameters are in registers.
+asmr_w_direct_ebp_neg_offset=07104_W_Usare -offset(%ebp) non è consigliato per accedere a variabili locali
+% Using -8(%ebp) to access a local variable is not recommended
+asmr_w_direct_esp_neg_offset=07105_W_Usando -offset(%esp), l'accesso può causare un crash o perdite di dati
+% Using -8(%esp) to access a local stack is not recommended, as
+% this stack portion can be overwritten by any function calls or interrupts.
+asmr_e_no_vmtoffset_possible=07106_E_VMTOffset deve essere usato in combinazione con un metodo virtuale, ma "$1" non lo è
+% Only virtual methods have VMT offsets
+asmr_e_need_pic_ref=07107_E_Non si può generare PIC: ci sono reference dipendenti dalla posizione
+% The compiler has been configured to generate position-independent code
+% (PIC), but there are position-dependent references in the current
+% handwritten assembler instruction.
+#
+# Assembler/binary writers
+#
+# 08020 is the last used one
+#
+asmw_f_too_many_asm_files=08000_F_Troppi file assembler
+% With smartlinking enabled, there are too many assembler
+% files generated. Disable smartlinking.
+asmw_f_assembler_output_not_supported=08001_F_L'assembler di output selezionato non è supportato
+asmw_f_comp_not_supported=08002_F_Comp not supported
+asmw_f_direct_not_supported=08003_F_Modo diretto non supportato perscrittori binari
+% Direct assembler mode is not supported for binary writers.
+asmw_e_alloc_data_only_in_bss=08004_E_Si possono allocare dati solo nella sezione bss
+asmw_f_no_binary_writer_selected=08005_F_Nessuno scrittore binario selezionato
+asmw_e_opcode_not_in_table=08006_E_Asm: L'opcode $1 non è in tabella
+asmw_e_invalid_opcode_and_operands=08007_E_Asm: $1 combinazione di opcode e operandi non valida
+asmw_e_16bit_not_supported=08008_E_Asm: riferimenti a 16 Bit non sono supportati
+asmw_e_invalid_effective_address=08009_E_Asm: indirizzo effettivo non valido
+asmw_e_immediate_or_reference_expected=08010_E_Asm: era previsto un immediate o un reference
+asmw_e_value_exceeds_bounds=08011_E_Asm: valore $1 fuori dal limite $2
+asmw_e_short_jmp_out_of_range=08012_E_Asm: lo short jump è fuori dal limite $1
+asmw_e_undefined_label=08013_E_Asm: Label $1 non definita
+asmw_e_comp_not_supported=08014_E_Asm: il tipo comp non è supportato per questa destinazione
+asmw_e_extended_not_supported=08015_E_Asm: il tipo extended non è supportato per questa destinazione
+asmw_e_duplicate_label=08016_E_Asm: label $1 duplicata
+asmw_e_redefined_label=08017_E_Asm: label $1 ridefinita
+asmw_e_first_defined_label=08018_E_Asm: definito qui per la prima volta
+asmw_e_invalid_register=08019_E_Asm: registro $1 non valido
+asmw_e_16bit_32bit_not_supported=08020_E_Asm: riferimenti a 16 o a 32 Bit non supportati
+asmw_e_64bit_not_supported=08021_E_Asm: operandi a 64 Bit non supportati
+
+#
+# Executing linker/assembler
+#
+# 09032 is the last used one
+#
+# BeginOfTeX
+%
+% \section{Errors of assembling/linking stage}
+% This section lists errors that occur when the compiler is processing the
+% command line or handling the configuration files.
+% \begin{description}
+exec_w_source_os_redefined=09000_W_Sistema operativo sorgente ridefinito
+% The source operating system is redefined.
+exec_i_assembling_pipe=09001_I_Uso del'assemblatore $1 (tramite pipe)
+% Assembling using a pipe to an external assembler.
+exec_d_cant_create_asmfile=09002_E_Non posso creare il file assembler $1
+% The mentioned file can't be created. Check if you have
+% access permissions to create this file.
+exec_e_cant_create_objectfile=09003_E_Non posso creare il file oggetto: $1
+% The mentioned file can't be created. Check if you have
+% got access permissions to create this file.
+exec_e_cant_create_archivefile=09004_E_Non posso creare il file archivio: $1
+% The mentioned file can't be created. Check if you have
+% access permissions to create this file.
+exec_e_assembler_not_found=09005_E_Assemblatore $1 non trovato, sarà usato un assemblatore esterno
+% The assembler program was not found. The compiler will produce a script that
+% can be used to assemble and link the program.
+exec_t_using_assembler=09006_T_Assemblatore in uso: $1
+% An informational message saying which assembler is being used.
+exec_e_error_while_assembling=09007_E_Errore nell'assembaggio dell'exitcode $1
+% There was an error while assembling the file using an external assembler.
+% Consult the documentation of the assembler tool to find out more information
+% on this error.
+exec_e_cant_call_assembler=09008_E_Non è possibile chiamare l'assemblatore, errore $1: sarà usato un assemblatore esterno
+% An error occurred when calling an external assembler. The compiler will produce a script that
+% can be used to assemble and link the program.
+exec_i_assembling=09009_I_Assemblaggio di $1
+% An informational message stating which file is being assembled.
+exec_i_assembling_smart=09010_I_Assemblaggio con smartlinking di $1
+% An informational message stating which file is being assembled using smartlinking.
+exec_w_objfile_not_found=09011_W_Oggetto $1 non trovato, il linking potrebbe fallire!
+% One of the object files is missing, and linking will probably fail.
+% Check your paths.
+exec_w_libfile_not_found=09012_W_Libreria $1 non trovata, il linking potrebbe fallire!
+% One of the library files is missing, and linking will probably fail.
+% Check your paths.
+exec_e_error_while_linking=09013_E_Errore durante il linking
+% Generic error while linking.
+exec_e_cant_call_linker=09014_E_Impossibile chiamare il linker, sarà usato un linker esterno
+% An error occurred when calling an external linker. The compiler will produce a script that
+% can be used to assemble and link the program.
+exec_i_linking=09015_I_Linking di $1
+% An informational message, showing which program or library is being linked.
+exec_e_util_not_found=09016_E_Utility $1 non trovata, sarà usato un linker esterno
+% An external tool was not found. The compiler will produce a script that
+% can be used to assemble and link or postprocess the program.
+exec_t_using_util=09017_T_Uso di utility $1
+% An informational message, showing which external program (usually a postprocessor) is being used.
+exec_e_exe_not_supported=09018_E_La creazione di eseguibili non è supportata
+% Creating executable programs is not supported for this platform, because it was
+% not yet implemented in the compiler.
+exec_e_dll_not_supported=09019_E_La creazione di librerie dinamiche o condivise non è supportata
+% Creating dynamically loadable libraries is not supported for this platform, because it was
+% not yet implemented in the compiler.
+exec_i_closing_script=09020_I_Chiusura dello script $1
+% Informational message showing when writing of the external assembling and linking script is finished.
+exec_e_res_not_found=09021_E_Compilatore di risorse "$1" non trovato, creazione di uno script esterno
+% An external resource compiler was not found. The compiler will produce a script that
+% can be used to assemble, compile resources and link or postprocess the program.
+exec_i_compilingresource=09022_I_Compilazione della risorsa $1
+% An informational message, showing which resource is being compiled.
+exec_t_unit_not_static_linkable_switch_to_smart=09023_T_La unit $1 non si può linkare staticamente, sarà usato lo smart linking
+% Static linking was requested, but a unit which is not statically linkable was used.
+exec_t_unit_not_smart_linkable_switch_to_static=09024_T_La unit $1 deve essere linkata staticamente
+% Smart linking was requested, but a unit which is not smart-linkable was used.
+exec_t_unit_not_shared_linkable_switch_to_static=09025_T_La unit $1 non si può linkare in modo shared o smart
+% Shared linking was requested, but a unit which is not shared-linkable was used.
+exec_e_unit_not_smart_or_static_linkable=09026_E_La unit $1 deve essere linkata in modo shared
+% Smart or static linking was requested, but a unit which cannot be used for either was used.
+exec_e_unit_not_shared_or_static_linkable=09027_E_La unit $1 non si può linkare in modo shared o statico
+% Shared or static linking was requested, but a unit which cannot be used for either was used.
+exec_d_resbin_params=09028_D_Chiamata al compilatore di risorse "$1" con riga di comando "$2"
+% An informational message showing which command line is used for the resource compiler.
+exec_e_error_while_compiling_resources=09029_E_Errore nella compilazione delle risorse
+% The resource compiler or converter returned an error.
+exec_e_cant_call_resource_compiler=09030_E_Impossibile chiamare il compilatore di risorse "$1", creazione di uno script esterno
+% An error occurred when calling a resource compiler. The compiler will produce
+% a script that can be used to assemble, compile resources and link or
+% postprocess the program.
+exec_e_cant_open_resource_file=09031_E_Impossibile aprire il file di risorse "$1"
+% An error occurred resource file cannot be opened.
+exec_e_cant_write_resource_file=09032_E_Impossibile scrivere il file di risorse "$1"
+% An error occurred resource file cannot be written.
+%\end{description}
+# EndOfTeX
+
+#
+# Executable information
+#
+# 09134 is the last used one
+#
+# BeginOfTeX
+% \section{Executable information messages.}
+% This section lists all messages that the compiler emits when an executable program is produced,
+% and only when the internal linker is used.
+% \begin{description}
+execinfo_f_cant_process_executable=09128_F_Impossibile postprocessare l'eseguibile $1
+% Fatal error when the compiler is unable to post-process an executable.
+execinfo_f_cant_open_executable=09129_F_Impossibile aprire l'eseguibile $1
+% Fatal error when the compiler cannot open the file for the executable.
+execinfo_x_codesize=09130_X_Dimnesione del codice: $1 byte
+% Informational message showing the size of the produced code section.
+execinfo_x_initdatasize=09131_X_Dimensione dei dati inizializzati: $1 byte
+% Informational message showing the size of the initialized data section.
+execinfo_x_uninitdatasize=09132_X_Dimensione dei dati non inizializzati: $1 byte
+% Informational message showing the size of the uninitialized data section.
+execinfo_x_stackreserve=09133_X_Spazio di stack riservato: $1 byte
+% Informational message showing the stack size that the compiler reserved for the executable.
+execinfo_x_stackcommit=09134_X_Spazio di stack impegnato: $1 byte
+% Informational message showing the stack size that the compiler committed for the executable.
+%\end{description}
+# EndOfTeX
+
+#
+# Internal linker messages
+#
+# 09200 is the last used one
+#
+# BeginOfTeX
+% \section{Linker messages}
+% This section lists messages produced by internal linker.
+% \begin{description}
+link_f_executable_too_big=09200_F_L'immagine dell'eseguibile è troppo grande per la destinazione $1.
+% Fatal error when resulting executable is too big.
+link_w_32bit_absolute_reloc=09201_W_Il file oggetto "$1" contiene rilocazioni assolute a 32-bit al simbolo "$2".
+% Warning when 64-bit object file contains 32-bit absolute relocations.
+% In such case an executable image can be loaded into lower 4Gb of
+% address space only.
+%\end{description}
+# EndOfTeX
+
+#
+# Unit loading
+#
+# 10061 is the last used one
+#
+# BeginOfTeX
+% \section{Unit loading messages.}
+% This section lists all messages that can occur when the compiler is
+% loading a unit from disk into memory. Many of these messages are
+% informational messages.
+% \begin{description}
+unit_t_unitsearch=10000_T_Ricerca della unit: $1
+% When you use the \var{-vt} option, the compiler tells you where it tries to find
+% unit files.
+unit_t_ppu_loading=10001_T_Caricamento del PPU $1
+% When the \var{-vt} switch is used, the compiler tells you
+% what units it loads.
+unit_u_ppu_name=10002_U_Nome del PPU: $1
+% When you use the \var{-vu} flag, the unit name is shown.
+unit_u_ppu_flags=10003_U_Flag del PPU: $1
+% When you use the \var{-vu} flag, the unit flags are shown.
+unit_u_ppu_crc=10004_U_Crc del PPU: $1
+% When you use the \var{-vu} flag, the unit CRC check is shown.
+unit_u_ppu_time=10005_U_Ora del PPU: $1
+% When you use the \var{-vu} flag, the time the unit was compiled is shown.
+unit_u_ppu_file_too_short=10006_U_File PPU troppo corto
+% The ppufile is too short, not all declarations are present.
+unit_u_ppu_invalid_header=10007_U_Header del PPU non valido (non c'è PPU all'inizio)
+% A unit file contains as the first three bytes the ASCII codes of the characters \var{PPU}.
+unit_u_ppu_invalid_version=10008_U_Versione del PPU $1 non valida
+% This unit file was compiled with a different version of the compiler, and
+% cannot be read.
+unit_u_ppu_invalid_processor=10009_U_Il PPU è compilato per un altro processore
+% This unit file was compiled for a different processor type, and
+% cannot be read.
+unit_u_ppu_invalid_target=10010_U_Il PPU è compilato per un'altra destinazione
+% This unit file was compiled for a different target, and
+% cannot be read.
+unit_u_ppu_source=10011_U_Sorgente del PPU: $1
+% When you use the \var{-vu} flag, the unit source file name is shown.
+unit_u_ppu_write=10012_U_Scrittura di $1
+% When you specify the \var{-vu} switch, the compiler will tell you where it
+% writes the unit file.
+unit_f_ppu_cannot_write=10013_F_Impossibile scrivere il file PPU
+% An error occurred when writing the unit file.
+unit_f_ppu_read_error=10014_F_Impossibile leggere il file PPU
+% This means that the unit file was corrupted, and contains invalid
+% information. Recompilation will be necessary.
+unit_f_ppu_read_unexpected_end=10015_F_Fine del file PPU inaspettata
+% Unexpected end of file. This may mean that the PPU file is
+% corrupted.
+unit_f_ppu_invalid_entry=10016_F_Voce del file PPU non valida: $1
+% The unit the compiler is trying to read is corrupted, or generated with a
+% newer version of the compiler.
+unit_f_ppu_dbx_count_problem=10017_F_Problemi nel conteggi Dbx nel PPU
+% There is an inconsistency in the debugging information of the unit.
+unit_e_illegal_unit_name=10018_E_Nome della unit $1 illegale
+% The name of the unit does not match the file name.
+unit_f_too_much_units=10019_F_Troppe unit
+% \fpc has a limit of 1024 units in a program. You can change this behavior
+% by changing the \var{maxunits} constant in the \file{fmodule.pas} file of the
+% compiler, and recompiling the compiler.
+unit_f_circular_unit_reference=10020_F_Riferimento circolare fra le unit $1 e $2
+% Two units are using each other in the interface part. This is only allowed
+% in the \var{implementation} part. At least one unit must contain the other one
+% in the \var{implementation} section.
+unit_f_cant_compile_unit=10021_F_Impossibile compilare la unit $1, i sorgenti non sono disponibili
+% A unit was found that needs to be recompiled, but no sources are
+% available.
+unit_f_cant_find_ppu=10022_F_Impossibile trovare la unit unit $1 usata da $2
+% You tried to use a unit of which the PPU file isn't found by the
+% compiler. Check your configuration file for the unit paths.
+unit_w_unit_name_error=10023_W_La unit $1 non è stata trovata ma la $2 esiste
+% This error message is no longer used.
+unit_f_unit_name_error=10024_F_Cercata la unit $1 ma trovata la $2
+% \dos truncation of 8 letters for unit PPU files
+% may lead to problems when unit name is longer than 8 letters.
+unit_w_switch_us_missed=10025_W_E' necessario lo switch -Us per compilare la unit 'system'
+% When recompiling the system unit (it needs special treatment), the
+% \var{-Us} switch must be specified.
+unit_f_errors_in_unit=10026_F_Riscontrati $1 errori nella compilazione del modulo: terminata.
+% When the compiler encounters a fatal error or too many errors in a module
+% then it stops with this message.
+unit_u_load_unit=10027_U_Caricamento da $1 ($2) unit $3
+% When you use the \var{-vu} flag, which unit is loaded from which unit is
+% shown.
+unit_u_recompile_crc_change=10028_U_Ricompilazione di $1, il checksum di $2 è cambiato
+% The unit is recompiled because the checksum of a unit it depends on has
+% changed.
+unit_u_recompile_source_found_alone=10029_U_Ricompilazione di $1, trovato solo il sorgente
+% When you use the \var{-vu} flag, these messages tell you why the current
+% unit is recompiled.
+unit_u_recompile_staticlib_is_older=10030_U_La libreria statica è più vecchia del file PPU: ricompilo la unit
+% When you use the \var{-vu} flag, the compiler warns if the static library
+% of the unit is older than the unit file itself.
+unit_u_recompile_sharedlib_is_older=10031_U_La libreria condivisa è più vecchia del file PPU: ricompilo la unit
+% When you use the \var{-vu} flag, the compiler warns if the shared library
+% of the unit is older than the unit file itself.
+unit_u_recompile_obj_and_asm_older=10032_U_i file obj e asm sono più vecchi del file PPU: ricompilo la unit
+% When you use the \var{-vu} flag, the compiler warns if the assembler or
+% object file of the unit is older than the unit file itself.
+unit_u_recompile_obj_older_than_asm=10033_U_Il file obj è più vecchio del file asm: ricompilo la unit
+% When you use the \var{-vu} flag, the compiler warns if the assembler
+% file of the unit is older than the object file of the unit.
+unit_u_parsing_interface=10034_U_Analisi dell'interfaccia di $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% parsing the interface part of the unit.
+unit_u_parsing_implementation=10035_U_Analisi dell'implementazione di $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% parsing the implementation part of the unit.
+unit_u_second_load_unit=10036_U_Secondo caricamento della unit $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% recompiling a unit for the second time. This can happen with
+% interdependent units.
+unit_u_check_time=10037_U_PPU Controllo del file $1 ora $2
+% When you use the \var{-vu} flag, the compiler shows the filename and
+% date and time of the file on which a recompile depends.
+### The following two error msgs is currently disabled.
+#unit_h_cond_not_set_in_last_compile=10038_H_Il condizionale $1 non era settato all'inizio dell'ultima compilazione di $2
+#% when recompilation of an unit is required the compiler will check that
+#% the same conditionals are set for the recompiliation. The compiler has
+#% found a conditional that currently is defined, but was not used the last
+#% time the unit was compiled.
+#unit_h_cond_set_in_last_compile=10039_H_Il condizionale $1 era settato all'inizio dell'ultima compilazione di $2
+#% when recompilation of an unit is required the compiler will check that
+#% the same conditionals are set for the recompiliation. The compiler has
+#% found a conditional that was used the last time the unit was compiled, but
+#% the conditional is currently not defined.
+unit_w_cant_compile_unit_with_changed_incfile=10040_W_Impossibile ricompilare la unit $1, ma sono stati trovati file include modificati
+% A unit was found to have modified include files, but
+% some source files were not found, so recompilation is impossible.
+unit_u_source_modified=10041_U_Il file $1 è più recente del file PPU $2
+% A modified source file for a compiler unit was found.
+unit_u_ppu_invalid_fpumode=10042_U_Tentativo di usare una unit compilata con un modo FPU diverso
+% Trying to compile code while using units which were not compiled with
+% the same floating point format mode. Either all code should be compiled
+% with FPU emulation on, or with FPU emulation off.
+unit_u_loading_interface_units=10043_U_Caricamento delle unit dall'interfaccia di $1
+% When you use the \var{-vu} flag, the compiler warns that it is starting
+% to load the units defined in the interface part of the unit.
+unit_u_loading_implementation_units=10044_U_Caricamento delle unit dall'implementazione di $1
+% When you use the \var{-vu} flag, the compiler warns that it is starting
+% to load the units defined in the implementation part of the unit.
+unit_u_interface_crc_changed=10045_U_Il CRC dell'interfaccia per la unit $1 è cambiato
+% When you use the \var{-vu} flag, the compiler warns that the
+% CRC calculated for the interface has been changed after the implementation
+% has been parsed.
+unit_u_implementation_crc_changed=10046_U_Il CRC dell'implementazione per la unit $1 è cambiato
+% When you use the \var{-vu} flag, the compiler warns that the
+% CRC calculated has been changed after the implementation
+% has been parsed.
+unit_u_finished_compiling=10047_U_Compilazione della unit $1 terminata
+% When you use the \var{-vu} flag, the compiler warns that it
+% has finished compiling the unit.
+unit_u_add_depend_to=10048_U_Aggiunta dipendenza da $1 a $2
+% When you use the \var{-vu} flag, the compiler warns that it
+% has added a dependency between the two units.
+unit_u_no_reload_is_caller=10049_U_Nessun ricaricamento, chiamante: $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% will not reload the unit because it is the unit that wants
+% to load this unit.
+unit_u_no_reload_in_second_compile=10050_U_Nessun ricaricamento, già in ricompilazione: $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% will not reload the unit because it is already in a second recompile.
+unit_u_flag_for_reload=10051_U_Flag per il ricaricamento: $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has to reload the unit.
+unit_u_forced_reload=10052_U_Ricaricamento forzato
+% When you use the \var{-vu} flag, the compiler warns that it
+% is reloading the unit because it was required.
+unit_u_previous_state=10053_U_Stato precedente di $1: $2
+% When you use the \var{-vu} flag, the compiler shows the
+% previous state of the unit.
+unit_u_second_compile_unit=10054_U_Unit $1 già in fase di compilazione, sarà compilata una seconda volta
+% When you use the \var{-vu} flag, the compiler warns that it is starting
+% to recompile a unit for the second time. This can happen with interdependent
+% units.
+unit_u_loading_unit=10055_U_Caricamento della unit $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% loading the unit.
+unit_u_finished_loading_unit=10056_U_Finito di caricare la unit $1
+% When you use the \var{-vu} flag, the compiler warns that it finished
+% loading the unit.
+unit_u_registering_new_unit=10057_U_Registrazione della nuova unit $1
+% When you use the \var{-vu} flag, the compiler warns that it has
+% found a new unit and is registering it in the internal lists.
+unit_u_reresolving_unit=10058_U_Ri-risoluzione della unit $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has to recalculate the internal data of the unit.
+unit_u_skipping_reresolving_unit=10059_U_Abortita ri-risoluzione della unit $1, ancora caricamento delle unit usate
+% When you use the \var{-vu} flag, the compiler warns that it is
+% skipping the recalculation of the internal data of the unit
+% because there is no data to recalculate.
+unit_u_unload_resunit=10060_U_Unit di risorse $1 scaricata perché non necessaria
+% When you use the \var{-vu} flag, the compiler warns that it is unloading the
+% resource handling unit, since no resources are used.
+unit_e_different_wpo_file=10061_E_La unit $1 è compilata con un diverso feedback di ottimizzazione globale ($2, $3); ricompilarla senza wpo o usare lo stesso file input wpo per questa compilazione
+% When a unit has been compiled using a particular ottimizzazione globale (wpo) feedback file (\var{-FW<x>} \var{-OW<x>}),
+% this compiled version of the unit is specialised for that particular compilation scenario and cannot be used in
+% any other context. It has to be recompiled before you can use it in another program or with another wpo feedback input file.
+% \end{description}
+# EndOfTeX
+
+#
+# Options
+#
+# 11047 is the last used one
+#
+option_usage=11000_O_$1 [options] <inputfile> [options]
+# BeginOfTeX
+%
+% \section{Command line handling errors}
+% This section lists errors that occur when the compiler is processing the
+% command line or handling the configuration files.
+% \begin{description}
+option_only_one_source_support=11001_W_Supportato un solo file sorgente, cambio il file sorgente da compilare da "$1" in "$2"
+% You can specify only one source file on the command line. The last
+% one will be compiled, others will be ignored. This may indicate that
+% you forgot a \var{'-'} sign.
+option_def_only_for_os2=11002_W_I file DEF si possono creare solo per OS/2
+% This option can only be specified when you're compiling for OS/2.
+option_no_nested_response_file=11003_E_I file di risposta nidificati non sono supportati
+% You cannot nest response files with the \var{@file} command line option.
+option_no_source_found=11004_F_Nella riga di comando manca il nome del file sorgente
+% The compiler expects a source file name on the command line.
+option_no_option_found=11005_N_Non ci sono opzioni nel file di configurazione $1
+% The compiler didn't find any option in that config file.
+option_illegal_para=11006_E_Parametro $1 illegale
+% You specified an unknown option.
+option_help_pages_para=11007_H_-? fornisce le pagine di aiuto
+% When an unknown option is given, this message is displayed.
+option_too_many_cfg_files=11008_F_Troppi file di configurazione nidificati
+% You can only nest up to 16 config files.
+option_unable_open_file=11009_F_Impossibile aprire il file $1
+% The option file cannot be found.
+option_reading_further_from=11010_D_Lettura di ulteriori opzioni da $1
+% Displayed when you have notes turned on, and the compiler switches
+% to another options file.
+option_target_is_already_set=11011_W_Destinazione già impostata a: $1
+% Displayed if more than one \var{-T} option is specified.
+option_no_shared_lib_under_dos=11012_W_Le librerie condivise non sono supportate sotto DOS: passaggio a librerie statiche
+% If you specify \var{-CD} for the \dos platform, this message is displayed.
+% The compiler supports only static libraries under \dos.
+option_too_many_ifdef=11013_F_Nel file opzioni $1 alla riga $2 ci sono troppi \var{\#IF(N)DEFs}
+% The \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_too_many_endif=11014_F_Nel file opzioni $1 alla riga $2 c'è un \var{\#ENDIFs} che non dovrebbe esserci
+% The \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_too_less_endif=11015_F_Condizionale aperto alla fine del file di opzioni
+% The \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_no_debug_support=11016_W_La generazione delle informazioni di debug non è supportata da questo eseguibile
+% It is possible to have a compiler executable that doesn't support
+% the generation of debugging info. If you use such an executable with the
+% \var{-g} switch, this warning will be displayed.
+option_no_debug_support_recompile_fpc=11017_H_Provate a ricompilare il compilatore con -dGDB
+% It is possible to have a compiler executable that doesn't support
+% the generation of debugging info. If you use such an executable with the
+% \var{-g} switch, this warning will be displayed.
+option_obsolete_switch=11018_W_State usando lo switch $1 che è obsoleto
+% This warns you when you use a switch that is not needed/supported anymore.
+% It is recommended that you remove the switch to overcome problems in the
+% future, when the meaning of the switch may change.
+option_obsolete_switch_use_new=11019_W_State usando lo switch $1, che è obsoleto: si prega usare $2 al suo posto
+% This warns you when you use a switch that is not supported anymore. You
+% must now use the second switch instead.
+% It is recommended that you change the switch to overcome problems in the
+% future, when the meaning of the switch may change.
+option_switch_bin_to_src_assembler=11020_N_Cambio dell'assemblatore a quello di scrittora dei sorgenti di default
+% This notifies you that the assembler has been changed because you used the
+% -a switch, which can't be used with a binary assembler writer.
+option_incompatible_asm=11021_W_L'output assembler selezionato "$1" non è compatibile con "$2"
+option_asm_forced=11022_W_Forzato l'uso dell'assemblatore "$1"
+% The assembler output selected cannot generate
+% object files with the correct format. Therefore, the
+% default assembler for this target is used instead.
+option_using_file=11026_T_Lettura delle opzioni dal file $1
+% Options are also read from this file.
+option_using_env=11027_T_Lettura dell opzioni dall'ambiente $1
+% Options are also read from this environment string.
+option_handling_option=11028_D_Gestione dell'opzione "$1"
+% Debug info that an option is found and will be handled.
+option_help_press_enter=11029_O_*** premere invio ***
+% Message shown when help is shown page per page. When pressing the ENTER
+% Key, the next page of help is shown. If you press q and then ENTER, the
+% compiler exits.
+option_start_reading_configfile=11030_H_Inizio lettura del file di configurazione $1
+% Start of configuration file parsing.
+option_end_reading_configfile=11031_H_Fine lettura del file di configurazione $1
+% End of configuration file parsing.
+option_interpreting_option=11032_D_Interpretando l'opzione "$1"
+% The compiler is interpreting an option
+option_interpreting_firstpass_option=11036_D_Interpretando l'opzione "$1" (primo passo)
+% The compiler is interpreting an option for the first time.
+option_interpreting_file_option=11033_D_Interpretando l'opzione da file "$1"
+% The compiler is interpreting an option which it read from the configuration file.
+option_read_config_file=11034_D_Lettura del file di configurazione "$1"
+% The compiler is starting to read the configuration file.
+option_found_file=11035_D_trovato nome di file sorgente "$1"
+% Additional information about options.
+% Displayed when you have the debug option turned on.
+option_code_page_not_available=11039_E_Codepage (lingua del sorgente) sconosciuta
+% An unknown code page for the source files was requested.
+% The compiler is compiled with support for several code pages built-in.
+% The requested code page is not in that list. You will need to recompile
+% the compiler with support for the codepage you need.
+option_config_is_dir=11040_F_Il file di configurazione $1 è una directory
+% Directories cannot be used as configuration files.
+option_confict_asm_debug=11041_W_L'assemblatore selezionato "$1" non può gneerare informazioni di debug: debugging disabilitato
+% The selected assembler output cannot generate
+% debugging information, debugging option is therefore disabled.
+option_ppc386_deprecated=11042_W_L'uso di ppc386.cfg è deprecato, prego usate fpc.cfg al suo posto
+% Using ppc386.cfg is still supported for historical reasons, however, for a multiplatform
+% system the naming makes no sense anymore. Please continue to use fpc.cfg instead.
+option_else_without_if=11043_F_Nel file opzioni $1 alla riga $2 c'è una direttiva \var{\#ELSE} senza il \var{\#IF(N)DEF} corrispondente
+% An \var{\#ELSE} statement was found in the options file without a matching \var{\#IF(N)DEF} statement.
+option_unsupported_target=11044_F_L'opzione "$1" non è supportata sulla destinazione corrente
+% Not all options are supported or implemented for all target platforms. This message informs you that a chosen
+% option is incompatible with the currently selected target platform.
+option_unsupported_target_for_feature=11045_F_La capacità "$1" non è supportata sulla destinazione corrente
+% Not all features are supported or implemented for all target platforms. This message informs you that a chosen
+% feature is incompatible with the currently selected target platform.
+option_dwarf_smart_linking=11046_N_Le informazioni di debug DWARF non si possono usare con lo smart linking: passaggio al linking statico
+% Smart linking is currently incompatble with DWARF debug information on most
+% platforms, so smart linking is disabled in such cases.
+option_ignored_target=11047_W_L'opzione "$1" è ignorata per la destinazione corrente
+% Not all options are supported or implemented for all target platforms. This message informs you that a chosen
+% option is ignored for the currently selected target platform.
+%\end{description}
+# EndOfTeX
+
+#
+# Whole program optimization
+#
+# 12019 is the last used one
+#
+# BeginOfTeX
+%
+% \section{Whole program optimization messages}
+% This section lists errors that occur when the compiler is performing
+% ottimizzazione globale.
+% \begin{description}
+wpo_cant_find_file=12000_F_Impossibile aprire il file di feedback "$1" per la ottimizzazione globale
+% The compiler cannot open the specified feedback file with ottimizzazione globale information.
+wpo_begin_processing=12001_D_Elaborazione dell'informazione per l'ottimizzazione globale dal file di feedback "$1"
+% The compiler starts processing ottimizzazione globale information found in the named file.
+wpo_end_processing=12002_D_Fine elaborazione dell'informazione per l'ottimizzazione globale dal file di feedback "$1"
+% The compiler has finished processing the ottimizzazione globale information found in the named file.
+wpo_expected_section=12003_E_Header di sezione errato: trovato "$2" alla riga $1 del file di feedback
+% The compiler expected a section header in the ottimizzazione globale file (starting with \%),
+% but did not find it.
+wpo_no_section_handler=12004_W_Nessun handler registrato per la sezione ottimizzazione globale "$2" alla riga $1 del file feedback wpo: sezione ignorata
+% The compiler has no handler to deal with the mentioned ottimizzazione globale information
+% section, and will therefore ignore it and skip to the next section.
+wpo_found_section=12005_D_Trovata sezione WPO "$1" con informazioni su "$2"
+% The compiler encountered a section with ottimizzazione globale information, and according
+% to its handler this section contains information usable for the mentioned purpose.
+wpo_no_input_specified=12006_F_Le ottimizzazioni globali selezionate richiedono un file di feedback pre-generato (usare -Fw per specificarlo)
+% The compiler needs information gathered during a previous compilation run to perform the selected
+% ottimizzazione globales. You can specify the location of the feedback file containing this
+% information using the -Fw switch.
+wpo_not_enough_info=12007_E_Non sono state trovate le informazioni necessarie per eseguire le ottimizzazioni globali "$1"
+% While you pointed the compiler to a file containing ottimizzazione globale feedback, it
+% did not contain the information necessary to perform the selected optimizations. You most likely
+% have to recompile the program using the appropriate -OWxxx switch.
+wpo_no_output_specified=12008_F_Specificare un file di feedback (usando -FW) in cui memorizzare le informazioni per l'ottimizzazione globale
+% You have to specify the feedback file in which the compiler has to store the ottimizzazione globale
+% feedback that is generated during the compilation run. This can be done using the -FW switch.
+wpo_output_without_info_gen=12009_E_Non saranno generate informazioni per l'ottimizzazione globale, ma è stato comunque specificato un file (con -FW)
+% The compiler was instructed to store ottimizzazione globale feedback into a file specified using -FW,
+% but not to actually generated any ottimizzazione globale feedback. The classes of to be
+% generated information can be speciied using -OWxxx.
+wpo_input_without_info_use=12010_E_Non saranno generate informazioni per l'ottimizzazione globale, ma è stato comunque specificato un file (con -Fw)
+% The compiler was not instructed to perform any ottimizzazione globales (no -Owxxx parameters),
+% but nevertheless an input file with such feedback was specified (using -Fwyyy). Since this can
+% indicate that you forgot to specify an -Owxxx parameter, the compiler generates an error in this case.
+wpo_skipping_unnecessary_section=12011_D_Sezione del file di feedback "$1" ignorata, perché non necessaria per le ottimizzazioni richieste
+% The ottimizzazione globale feedback file contains a section with information that is not
+% required by the selected ottimizzazione globales.
+wpo_duplicate_wpotype=12012_W_Sovrascrittura delle informazioni già lette dal file di feedback "$1" con le informazioni nella sezione "$2"
+% The feedback file contains multiple sections that provide the same class of information (e.g.,
+% information about which virtual methods can be devirtualized). In this case, the information in last encountered
+% section is used. Turn on debugging output (-vd) to see which class of information is provided by each section.
+wpo_cannot_extract_live_symbol_info_strip=12013_E_Impossibile estrarre informazioni di vitalità dei simboli se il programma ne è privo: usate -Xs-
+% Certain symbol liveness collectors extract the symbol information from the linked program. If the symbol information
+% is stripped (option -Xs), this is not possible.
+wpo_cannot_extract_live_symbol_info_no_link=12014_E_Impossibile estrarre informazioni di vitalità dei simboli se il programma non è in fase di linking
+% Certain symbol liveness collectors extract the symbol information from the linked program. If the program is not
+% linked by the compiler, this is not possible.
+wpo_cannot_find_symbol_progs=12015_F_Impossibile trovare "$1" o "$2" per estrarre informazioni di vitalità dei simboli dal programma linkato
+% Certain symbol liveness collectors need a helper program to extract the symbol information from the linked program.
+% This helper program is normally 'nm', which is part of the GNU binutils.
+wpo_error_reading_symbol_file=12016_E_Errore nella lettura delle informazioni di vitalità dei simboli prodotte da "$1"
+% An error occurred during the reading of the symbol liveness file that was generated using the 'nm' or 'objdump' program. The reason
+% can be that it was shorter than expected, or that its format was not understood.
+wpo_error_executing_symbol_prog=12017_F_Errore nell'esecuzione di "$1" (exitcode: $2) per l'estrazione di informazioni sui simboli dal programma linkato
+% Certain symbol liveness collectors need a helper program to extract the symbol information from the linked program.
+% The helper program produced the reported error code when it was run on the linked program.
+wpo_symbol_live_info_needs_smart_linking=12018_E_La raccolta di informazioni sulla vitalità dei simboli è utile solo in caso di smart linking: usate -CX -XX
+% Whether or not a symbol is live is determined by looking whether it exists in the final linked program.
+% Without smart linking/dead code stripping, all symbols are always included, regardless of whether they are
+% actually used or not. So in that case all symbols will be seen as live, which makes this optimization ineffective.
+wpo_cant_create_feedback_file=12019_E_Impossibile creare il file di feedback "$1" per l'ottimizzazione globale
+% The compiler is unable to create the file specified using the -FW parameter to store the whole program optimisation information.
+%\end{description}
+# EndOfTeX
+
+
+#
+# Logo (option -l)
+#
+option_logo=11023_[
+Compilatore Free Pascal, versione $FPCFULLVERSION [$FPCDATE] per $FPCCPU
+Copyright (c) 1993-2010 di Florian Klaempfl
+]
+
+#
+# Info (option -i)
+#
+option_info=11024_[
+Compilatore Free Pascal, versione $FPCVERSION
+
+Data creazione del compilatore : $FPCDATE
+CPU nativa del compilatore : $FPCCPU
+
+Destinazioni supportate:
+ $OSTARGETS
+
+Set di istruzioni di CPU supportate:
+ $INSTRUCTIONSETS
+
+Set di istruzioni di FPU supportate:
+ $FPUINSTRUCTIONSETS
+
+Destinazioni ABI supportate:
+ $ABITARGETS
+
+Ottimizzazioni supportate:
+ $OPTIMIZATIONS
+
+Ottimizzazioni globali supportate:
+ All
+ $WPOPTIMIZATIONS
+
+Tipi di microcontroller supportati:
+ $CONTROLLERTYPES
+
+Questo programma è distribuito sotto la GNU General Public Licence
+Per ulteriori informazioni leggere il file COPYING.FPC
+
+Riferire difetti, suggerimenti ecc. a:
+ http://bugs.freepascal.org
+oppure a
+ bugs@freepascal.org
+]
+
+#
+# Help pages (option -? and -h)
+#
+# The first character on the line indicates who will display this
+# line, the current possibilities are :
+# * = every target
+# 3 = 80x86 targets
+# 6 = 680x0 targets
+# e = in extended debug mode only
+# P = PowerPC targets
+# S = Sparc targets
+# V = Virtual machine targets
+# The second character also indicates who will display this line,
+# (if the above character was TRUE) the current possibilities are :
+# * = everyone
+# g = with GDB info supported by the compiler
+# O = OS/2
+# L = UNIX systems
+# The third character represents the indentation level.
+#
+option_help_pages=11025_[
+**0*_Mettere + dopo uno switch per attivarlo, - per disattivarlo
+**1a_Il compilatore non cancella i file asm generati
+**2al_Elenca le linee del codice sorgente nel file asm
+**2an_Elenca informazioni sui nodi nel file assembler
+*L2ap_Usa pipes invece di creare file assembler temporanei
+**2ar_Elenca info allocaz./rilascio registri nel file asm
+**2at_Elenca info allocaz./rilascio nei file asm
+**1A<x>_Formato di uscita:
+**2Adefault_Usa l'assemblatore di default
+3*2Aas_Assembla usando GNU AS
+3*2Anasmcoff_File COFF (Go32v2) con Nasm
+3*2Anasmelf_File ELF32 (Linux) con Nasm
+3*2Anasmwin32_File oggetto Win32 con Nasm
+3*2Anasmwdosx_File oggetto Win32/WDOSX con Nasm
+3*2Awasm_File oggetto con Wasm (Watcom)
+3*2Anasmobj_File oggetto con Nasm
+3*2Amasm_File oggetto con Masm (Microsoft)
+3*2Atasm_File oggetto con Tasm (Borland)
+3*2Aelf_File ELF (Linux) con assemblatore interno
+3*2Acoff_File COFF (Go32v2) con assemblatore interno
+3*2Apecoff_File PE-COFF (Win32) con assemblatore interno
+4*2Aas_Assembla using GNU AS
+6*2Aas_Unix o-file using GNU AS
+6*2Agas_GNU Motorola assembler
+6*2Amit_MIT Syntax (old GAS)
+6*2Amot_Usa l'assemblatore standard Motorola
+A*2Aas_Assembla con GNU AS
+P*2Aas_Assembla con GNU AS
+S*2Aas_Assembla con GNU AS
+**1b_Genera info per il browser
+**2bl_Genera info sui simboli locali
+**1B_Costruisce tutti i moduli
+**1C<x>_Opzioni di generazione del codice:
+**2Ca<x>_Seleziona l'ABI, vedi fpc -i per i valori possibili
+**2Cb_Genera codice big-endian
+**2Cc<x>_Imposta la convenzione di chiamata di default a <x>
+**2CD_Crea anche la libreria dinamica (non supportato)
+**2Ce_Compilazione con opcode in virgola mobile emulati
+**2Cf<x>_Sceglie il set di istruzioni FPU, (vedi fpc -i)
+**2CF<x>_Precisione minima per costanti virgola mobile (default/32/64)
+**2Cg_Genera codice position-independent (PIC)
+**2Ch<n>_<n> dimensione in byte dello heap
+**3*_ (fra 1023 e 67107840)
+**2Ci_controllo dell'I/O
+**2Cn_Non fare il linking
+**2Co_Controlla l'overflow di operazioni su interi
+**2CO_Controlla il possibile overflow di operazioni su interi
+**2Cp<x>_Scegli il set di istruzioni,
+**3*_ (vedi fpc -i per i valori possibili)
+**2CP<x>=<y>_ impostazioni per il packing
+**3CPPACKSET=<y>_ <y> imposta l'allocazione:
+**3*_ (0, 1 o DEFAULT o NORMAL, 2, 4 e 8)
+**2Cr_Controllo degli intervalli (range)
+**2CR_Controlla la validità di chiamate a metodi di oggetti
+**2Cs<n>_Imposta controllo validità dello stack a <n>
+**2Ct_Controllo stack (solo testing, vedi manuale)
+**2CX_Crea anche librerie smartlinked
+**1d<x>_Definisce il simbolo <x>
+**1D_Genera un file DEF
+**2Dd<x>_Imposta descrizione a <x>
+**2Dv<x>_Imposta versione della DLL a <x>
+*O2Dw_Applicazione PM
+**1e<x>_Imposta il path all'eseguibile
+**1E_Identico a -Cn
+**1fPIC_Identico a -Cg
+**1F<x>_Imposta nomi di file e path:
+**2Fa<x>[,y]_(programma) carica unit <x> e [y]
+**3*_ (prima di parsare la sezione uses)
+**2Fc<x>_Imposta codepage di input a <x>
+**2FC<x>_Imposta il nome dell'exe del compilatore RC a <x>
+**2Fd_Disabilita cache interna delle dir. del compilatore
+**2FD<x>_Imposta la directory in cui cercare le utility
+**2Fe<x>_Redirezione l'output degli errori a <x>
+**2Ff<x>_Aggiunge <x> al path del framework (solo Darwin)
+**2FE<x>_Imposta il path di output exe/unit a <x>
+**2Fi<x>_Aggiunge <x> al path degli include
+**2Fl<x>_Aggiunge <x> al path delle library
+**2FL<x>_Usa <x> come linker dinamico
+**2Fm<x>_Carica tabella conversione unicode da <x>.txt
+**3*_ (nella directory del compilatore)
+**2Fo<x>_Aggiunge <x> al path dei file oggetto
+**2Fr<x>_Carica file dei messaggi di errore <x>
+**2FR<x>_Imposta linker delle risorse (.res) a <x>
+**2Fu<x>_Aggiunge <x> al path delle unit
+**2FU<x>_Setta output path delle unit a <x>, sovrascrive -FE
+**2FW<x>_Memorizza il feedback per l'ottimizz. globale in <x>
+**2Fw<x>_Carica info ottimizz. globale dal feedback file <x>
+*g1g_Genera info di debug (formato di default per la destinaz.)
+*g2gc_Genera controlli per i puntatori
+*g2gh_Usa unit heaptrace (debug di memory leak o corruzioni)
+*g2gl_Usa unit line info (mostra più info con i backtrace)
+*g2go<x>_Imposta opzioni delle informazioni di debug
+*g3godwarfsets_Abilita debug info tipo DWARF 'set'
+*g3*_ (attenzione: fa crashare gdb < 6.5)
+*g3gostabsabsincludes_Memorizza path assoluto per
+*g3*_ gli include file in Stabs
+*g3godwarfmethodclassprefix_Prefissa i nomi dei metodi
+**3*_ in DWARF con il nome di classe
+*g2gp_Conserva maiuscole nei nomi di simboli stabs
+*g2gs_Genera info di debug Stabs
+*g2gt_Scarta variabili locali
+*g3*_ (rileva il loro uso non inizializzato)
+*g2gv_Genera programmi tracciabili con Valgrind
+*g2gw_Genera info di debug DWARFv2 (come -gw2)
+*g2gw2_Genera info di debug DWARFv2
+*g2gw3_Genera info di debug DWARFv3
+**1i_Informazioni
+**2iD_Ritorna la data del compilatore
+**2iV_Ritorna la versione breve del compilatore
+**2iW_Ritorna la versione completa del compilatore
+**2iSO_Ritorna il sistema operativo del compilatore
+**2iSP_Ritorna la CPU ospite del compilatore
+**2iTO_Ritorna il sistema operativo di destinazione
+**2iTP_Ritorna la CPU di destinazione
+**1I<x>_Aggiunge <x> al path degli include file
+**1k<x>_Passa <x> al linker
+**1l_Scrive il logo
+**1M<x>_Imposta il modo del linguaggio a <x>
+**2Mfpc_Dialetto Free Pascal (default)
+**2Mobjfpc_Modo FPC con supporto Object Pascal
+**2Mdelphi_Modo compatibilità Delphi 7
+**2Mtp_Modo compatibilità TP/BP 7.0
+**2Mmacpas_Modo compatibilità Macintosh Pascal e dialetti
+**1n_Non leggere i file configurazione di default
+**1N<x>_Ottimizzazioni dell'albero dei nodi
+**2Nu_Srotola i loop
+**1o<x>_Rinomina l'eseguibile prodotto in <x>
+**1O<x>_Ottimizzazioni:
+**2O-_Disabilita le ottimizzazioni
+**2O1_Ottimizzazione livello 1
+**3*_ (rapide e trasparenti al debugger)
+**2O2_Ottimizzazione livello 2 (-O1 + ottimizz. veloce)
+**2O3_Ottimizzazione livello 3 (-O2 + ottimizz. lenta)
+**2Oa<x>=<y>_Imposta allineamento
+**2Oo[NO]<x>_Abilita/disabilita ottimizzazioni,
+**3*_ (vedi fpc -i per possibili valori)
+**2Op<x>_Imposta ottimizzazione per una CPU specifica,
+**3*_ (vedi fpc -i per possibili valori)
+**2OW<x>_Genera feedback per l'ottimizz. globale <x> (vedi fpc -i)
+**2Ow<x>_Esegue ottimizzazione globale <x> (vedi fpc -i)
+**2Os_Ottimizza per la dimensione e non per la velocità
+**1pg_Genera codici di profiling per gprof (FPC_PROFILE: on)
+**1R<x>_Stile di lettura assembler:
+**2Rdefault_Usa assembler di default per la destinazione
+3*2Ratt_Leggi assembler stile AT&T
+3*2Rintel_Leggi assembler stile Intel
+6*2RMOT_Leggi assembler stile motorola
+**1S<x>_Opzioni di sintassi:
+**2S2_Come -Mobjfpc
+**2Sc_Supporta operatori simil-C (*=,+=,/= e -=)
+**2Sa_Abilita le asserzioni
+**2Sd_Come -Mdelphi
+**2Se<x>_Opzioni sugli errori. <x> è la combinazione di:
+**3*_<n> : Il compilatore si ferma dopo <n> errori (default = 1)
+**3*_w : Il compilatore si ferma anche con warning
+**3*_n : Il compilatore si ferma anche con note
+**3*_h : Il compilatore si ferma anche con consigli
+**2Sg_Abilita LABEL e GOTO (default in -Mtp e -Mdelphi)
+**2Sh_Usa ansistring per default invece di shortstring
+**2Si_Abilita l'inlining di procedure e funzioni
+**3*_ dichiarate come "inline"
+**2Sk_Carica unit fpcylix
+**2SI<x>_Imposta stile di interfacce a <x>
+**3SIcom_Interfaccia COM compatibile (default)
+**3SIcorba_Interfaccia CORBA compatible
+**2Sm_Supporta macro simil-C (global)
+**2So_Come -Mtp
+**2Ss_Il nome del costruttore deve essere 'init'
+**3*_ (e il nome del distruttore deve essere 'done')
+**2St_Permetti la parola chiave static negli oggetti
+**2Sx_Abilita la parola chiave exception
+**3*_ (default nei modi Delphi/ObjFPC)
+**1s_Non chiamare assembler e linker
+**2sh_Genera script per il linking sull'host
+**2st_Genera script per il linking sulla destinazione
+**2sr_Salta la fase di allocazione dei registri (usare con -alr)
+**1T<x>_Sistema operativo di destinazione:
+3*2Temx_OS/2 via EMX (inclusi extender EMX/RSX)
+3*2Tfreebsd_FreeBSD
+3*2Tgo32v2_DJ Delorie DOS extender versione 2
+3*2Tlinux_Linux
+3*2Tnetbsd_NetBSD
+3*2Tnetware_Novell Netware Module (clib)
+3*2Tnetwlibc_Novell Netware Module (libc)
+3*2Topenbsd_OpenBSD
+3*2Tos2_OS/2 / eComStation
+3*2Tsunos_SunOS/Solaris
+3*2Tsymbian_Symbian OS
+3*2Twatcom_DOS extender compatibile Watcom
+3*2Twdosx_WDOSX DOS extender
+3*2Twin32_Windows 32 Bit
+3*2Twince_Windows CE
+4*2Tlinux_Linux
+6*2Tamiga_Commodore Amiga
+6*2Tatari_Atari ST/STe/TT
+6*2Tlinux_Linux/m68k
+6*2Tmacos_Macintosh m68k (non supportato)
+6*2Tpalmos_PalmOS
+A*2Tlinux_Linux
+A*2Twince_Windows CE
+P*2Tamiga_AmigaOS su PowerPC
+P*2Tdarwin_Darwin e Mac OS X su PowerPC
+P*2Tlinux_Linux su PowerPC
+P*2Tmacos_Mac OS (classic) su PowerPC
+P*2Tmorphos_MorphOS
+S*2Tlinux_Linux
+**1u<x>_Elimina il simbolo <x>
+**1U_Opzioni per le unit:
+**2Un_Non controllare se i nomi della unit e
+**3*_ del file che la contiene sono uguali
+**2Ur_Genera file di release delle unit
+**3*_ (niente ricompilazione automatica)
+**2Us_Compila una unit di sistema
+**1v<x>_Prolisso. <x> è una combinazione dei seguenti:
+**2*_e : Mostra errori (default) 0 : Mostra solo errori e basta
+**2*_w : Mostra warning u : Mostra info sulla unit
+**2*_n : Mostra note t : Mostra files usati/tentati
+**2*_h : Mostra consigli c : Mostra i condizionali
+**2*_i : Mostra info generiche d : Mostra info di debug
+**2*_l : Mostra numri di riga r : Modo compatibile Rhide/GCC
+**2*_s : Mostra date/ore q : Mostra numeri dei messaggi
+**2*_a : Mostra tutto x : Info degli exe (solo Win32)
+**2*_b : Nei messaggi scrivi nomi p : Scrivi parse tree in tree.log
+**2*_ file con path completo v : Scrivi fpcdebug.txt con
+**2*_ molte informazioni di debug
+**2*_m<x>,<y> : Non mostrare messaggi con i numeri <x> e <y>
+3*1W<x>_Opzioni specifiche della destinazione (destinazioni)
+A*1W<x>_Opzioni specifiche della destinazione (destinazioni)
+P*1W<x>_Opzioni specifiche della destinazione (destinazioni)
+p*1W<x>_Opzioni specifiche della destinazione (destinazioni)
+3*2Wb_Crea un bundle e non una libreria (Darwin)
+P*2Wb_Crea un bundle e non una libreria (Darwin)
+p*2Wb_Crea un bundle e non una libreria (Darwin)
+3*2WB_Crea una immagine rilocabile (Windows)
+A*2WB_Crea una immagine rilocabile (Windows, Symbian)
+3*2WC_Specifica applicazione di tipo console
+3*3*_ (EMX, OS/2, Windows)
+A*2WC_Specifica applicazione console (Windows)
+P*2WC_Specifica applicazione console (Classic Mac OS)
+3*2WD_Usa DEFFILE per esportare funz. di DLL o EXE (Windows)
+A*2WD_Usa DEFFILE per esportare funz. di DLL o EXE (Windows)
+3*2We_Usa risorse esterne (Darwin)
+P*2We_Usa risorse esterne (Darwin)
+p*2We_Usa risorse esterne (Darwin)
+3*2WF_Specifica un'applicazione a tutto schermo (EMX, OS/2)
+3*2WG_Specifica una applicazione grafica (EMX, OS/2, Windows)
+A*2WG_Specifica una applicazione grafica (Windows)
+P*2WG_Specifica una applicazione grafica (Classic Mac OS)
+3*2Wi_Usa risorse interne (Darwin)
+P*2Wi_Usa risorse interne (Darwin)
+p*2Wi_Usa risorse interne (Darwin)
+3*2WN_Non generare codice di rilocazione,
+3*3*_ (necessario per il debug sotto Windows)
+A*2WN_Non generare codice di rilocazione,
+A*3*_(necessario per il debug sotto Windows)
+3*2WR_Genera codice di rilocazione (Windows)
+A*2WR_Genera codice di rilocazione (Windows)
+P*2WT_Specifica applicazione tipo tool MPW (Classic Mac OS)
+3*2WX_Abilita stack dell'eseguibile (Linux)
+A*2WX_Abilita stack dell'eseguibile (Linux)
+p*2WX_Abilita stack dell'eseguibile (Linux)
+P*2WX_Abilita stack dell'eseguibile (Linux)
+**1X_Opzioni per gli eseguibili:
+**2Xc_Passa --shared/-dynamic al linker
+**3*_ (BeOS, Darwin, FreeBSD, Linux)
+**2Xd_Non usare il path per la standard library
+**3*_ (per crosscompilazione)
+**2Xe_Usa linker esterno
+**2Xg_Metti le info di debug in un file diverso e inserisci
+**3*_ una sezione debuglink nell'eseguibile
+**2XD_Cerca di linkare le unit dinamicamente
+**3*_ (FPC_LINK_DYNAMIC: on)
+**2Xi_Usa linker interno
+**2Xm_Genera la mappa di linking
+**2XM<x>_Rinomina la routine 'main' del programma (default: main)
+**2XP<x>_Aggiunge il prefisso <x> ai nomi delle binutils
+**2Xr<x>_Pone il path rlink del linker a <x>
+**3*_ per crosscompilazioni, vedi manuale di ld (BeOS, Linux)
+**2XR<x>_Prepone <x> ai path del linker
+**3*_ (BeOS, Darwin, FreeBSD, Linux, Mac OS, Solaris)
+**2Xs_Elimina tutti i simboli dall'eseguibile finale
+**2XS_Prova a linkare tutte le unit staticamente
+**3*_ (default, FPC_LINK_STATIC: on)
+**2Xt_Linka a librerie statiche (passa -static al linker)
+**2XX_Prova a usare lo smartlinking (FPC_LINK_SMART: on)
+**1*_
+**1?_Mostra questo help
+**1h_Mostra questo help senza interruzioni
+]
+
+#
+# The End...
diff --git a/closures/compiler/msg/errorn.msg b/closures/compiler/msg/errorn.msg
new file mode 100644
index 0000000000..ac7bef7f8a
--- /dev/null
+++ b/closures/compiler/msg/errorn.msg
@@ -0,0 +1,2372 @@
+#
+# This file is part of the Free Pascal Compiler
+# Copyright (c) 1999-2008 by the Free Pascal Development team
+#
+# Dutch Language File for Free Pascal in CP850 (just one line in help affected)
+# Latest updates contributed by Matthijs Willemstein <matthijs at willemstein.net>
+# Based on errore.msg of SVN revision 3982
+#
+# See the file COPYING.FPC, included in this distribution,
+# for details about the copyright.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#
+#
+# The constants are build in the following order:
+# <part>_<type>_<txtidentifier>
+#
+# <part> is the part of the compiler the message is used
+# asmr_ assembler parsing
+# asmw_ assembler writing/binary writers
+# unit_ unit handling
+# scan_ scanner
+# parser_ parser
+# type_ type checking
+# general_ general info
+# exec_ calls to assembler, linker, binder
+#
+# <type> the type of the message it should normally used for
+# f_ fatal error
+# e_ error
+# w_ warning
+# n_ note
+# h_ hint
+# i_ info
+# l_ add linenumber
+# u_ used
+# t_ tried
+# c_ conditional
+# d_ debug message
+# x_ executable informations
+#
+#
+# General
+#
+# 01023 is the last used one
+#
+general_text_bytes_code=01019_bytes code
+general_text_bytes_data=01020_bytes data
+# BeginOfTeX
+% \section{General compiler messages}
+% This section gives the compiler messages which are not fatal, but which
+% display useful information. The number of such messages can be
+% controlled with the various verbosity level \var{-v} switches.
+% \begin{description}
+general_t_compilername=01000_T_Gebruikte compiler: $1
+% When the \var{-vt} switch is used, this line tells you what compiler
+% is used.
+general_d_sourceos=01001_D_Bronsysteem: $1
+% When the \var{-vd} switch is used, this line tells you what the source
+% operating system is.
+general_i_targetos=01002_I_Doelsysteem: $1
+% When the \var{-vd} switch is used, this line tells you what the target
+% operating system is.
+general_t_exepath=01003_T_Programmalocatie: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for its binaries.
+general_t_unitpath=01004_T_Locatie units: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for compiled units. You can set this path with the \var{-Fu}
+general_t_includepath=01005_T_Locatie includes: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for its include files (files used in \var{\{\$I xxx\}} statements).
+% You can set this path with the \var{-I} option.
+general_t_librarypath=01006_T_Locatie bibliotheken: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for the libraries. You can set this path with the \var{-Fl} option.
+general_t_objectpath=01007_T_Locatie objectbestanden: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for object files you link in (files used in \var{\{\$L xxx\}} statements).
+% You can set this path with the \var{-Fo} option.
+general_i_abslines_compiled=01008_I_$1 Regels gecompileerd, $2 sec.
+% When the \var{-vi} switch is used, the compiler reports the number
+% of lines compiled, and the time it took to compile them (real time,
+% not program time).
+general_f_no_memory_left=01009_F_Geen geheugen meer vrij
+% The compiler doesn't have enough memory to compile your program. There are
+% several remedies for this:
+% \begin{itemize}
+% \item If you're using the build option of the compiler, try compiling the
+% different units manually.
+% \item If you're compiling a huge program, split it up in units, and compile
+% these separately.
+% \item If the previous two don't work, recompile the compiler with a bigger
+% heap (you can use the \var{-Ch} option for this, \seeo{Ch})
+% \end{itemize}
+general_i_writingresourcefile=01010_I_Schrijven van resource string tabel bestand: $1
+% This message is shown when the compiler writes the Resource String Table
+% file containing all the resource strings for a program.
+general_e_errorwritingresourcefile=01011_E_Schrijven van resource string tabel bestand: $1
+% This message is shown when the compiler encountered an error when writing
+% the Resource String Table file
+general_i_fatal=01012_I_Fatale fout:
+% Prefix for Fatal Errors
+general_i_error=01013_I_Fout:
+% Prefix for Errors
+general_i_warning=01014_I_Waarschuwing:
+% Prefix for Warnings
+general_i_note=01015_I_Noot:
+% Prefix for Notes
+general_i_hint=01016_I_Tip:
+% Prefix for Hints
+general_e_path_does_not_exist=01017_E_Pad "$1" bestaat niet
+% The specified path does not exist.
+general_f_compilation_aborted=01018_F_Compilatie afgebroken
+% Compilation was aborted.
+general_i_number_of_warnings=01021_I_$1 warning(s) issued
+% Total number of warnings issued during compilation.
+general_i_number_of_hints=01022_I_$1 hint(s) issued
+% Total number of hints issued during compilation.
+general_i_number_of_notes=01023_I_$1 tip(s) gegeven
+#
+# Scanner
+#
+# 02063 is the last used one
+#
+% Total number of notes issued during compilation.
+% \end{description}
+% \section{Scanner messages.}
+% This section lists the messages that the scanner emits. The scanner takes
+% care of the lexical structure of the pascal file, i.e. it tries to find
+% reserved words, strings, etc. It also takes care of directives and
+% conditional compiling handling.
+% \begin{description}
+scan_f_end_of_file=02000_F_Onverwacht einde van bestand
+% this typically happens in one of the following cases :
+% \begin{itemize}
+% \item The source file ends before the final \var{end.} statement. This
+% happens mostly when the \var{begin} and \var{end} statements aren't
+% balanced;
+% \item An include file ends in the middle of a statement.
+% \item A comment was not closed
+% \end{itemize}
+scan_f_string_exceeds_line=02001_F_String langer dan regel
+% There is a missing closing ' in a string, so it occupies
+% multiple lines.
+scan_f_illegal_char=02002_F_ongeldig teken "$1" ($2)
+% An illegal character was encountered in the input file.
+scan_f_syn_expected=02003_F_Taalfout: $2 verwacht in kolom $1
+% This indicates that the compiler expected a different token than
+% the one you typed. It can occur almost everywhere where you make a
+% mistake against the pascal language.
+scan_t_start_include_file=02004_TL_Ingevoegd bestand $1 word geopend
+% When you provide the \var{-vt} switch, the compiler tells you
+% when it starts reading an included file.
+scan_w_comment_level=02005_W_Commentaar van niveau $1 gevonden
+% When the \var{-vw} switch is used, then the compiler warns you if
+% it finds nested comments. Nested comments are not allowed in Turbo Pascal
+% and can be a possible source of errors.
+scan_n_ignored_switch=02008_N_Genegeerde compileroptie $1
+% With \var{-vn} on, the compiler warns if it ignores a switch
+scan_w_illegal_switch=02009_W_Foutieve compileroptie $1
+% You included a compiler switch (i.e. \var{\{\$... \}}) which the compiler
+% does not recognise
+scan_w_switch_is_global=02010_W_Deze compileroptie heeft ook een globaal effect
+% The compiler switch is misplaced, and should be located at
+% the start of the unit or program.
+scan_e_illegal_char_const=02011_E_Foutieve constante voor een karakter
+% This happens when you specify a character with its ASCII code, as in
+% \var{\#96}, but the number is either illegal, or out of range.
+scan_f_cannot_open_input=02012_F_Kan bestand "$1" niet openen
+% \fpc cannot find the program or unit source file you specified on the
+% command line.
+scan_f_cannot_open_includefile=02013_F_Kan ingevoerd bestand niet openen $1
+% \fpc cannot find the source file you specified in a \var{\{\$include ..\}}
+% statement.
+scan_e_illegal_pack_records=02015_E_Ongeldige alignatie-aanduiding voor records: "$1"
+% You are specifying the \var{\{\$PACKRECORDS n\} } or \var{\{\$ALIGN n\} }
+% with an illegal value for \var{n}. For \$PACKRECORDS valid alignments are 1, 2, 4, 8, 16, 32, C,
+% NORMAL, DEFAULT, and for \$ALIGN valid alignment are 1, 2, 4, 8, 16, 32, ON,
+% OFF. Under mode MacPas \$ALIGN also supports MAC68K, POWER and RESET.
+scan_e_illegal_pack_enum=02016_E_Ongeldige enumeratie grootte aanduiding "$1"
+% You are specifying the \var{\{\$PACKENUM n\}} with an illegal value for
+% \var{n}. Only 1,2,4, NORMAL or DEFAULT are valid here.
+scan_e_endif_expected=02017_E_$ENDIF verwacht voor $1 op $2 $3 lijn $4
+% Your conditional compilation statements are unbalanced.
+scan_e_preproc_syntax_error=02018_E_Taalfout bij het compileren van een conditionele compilatie uitdrukking
+% There is an error in the expression following the \var{\{\$if ..\}}, $ifc or $setc compiler
+% directives.
+scan_e_error_in_preproc_expr=02019_E_Evalueren van een conditionele compilatie uitdrukking
+% There is an error in the expression following the \var{\{\$if ..\}}, $ifc or $setc compiler
+% directives.
+scan_w_macro_cut_after_255_chars=02020_W_Macro inhoud is afgekapt op 255 karakters voor evaluatie
+% The contents of macros cannot be longer than 255 characters.
+scan_e_endif_without_if=02021_E_ENDIF zonder IF(N)DEF
+% Your \var{\{\$IFDEF ..\}} and {\{\$ENDIF\}} statements aren't balanced.
+scan_f_user_defined=02022_F_Gebruiker definitie: $1
+% A user defined fatal error occurred. see also the \progref
+scan_e_user_defined=02023_E_Gebruiker definitie: $1
+% A user defined error occurred. see also the \progref
+scan_w_user_defined=02024_W_Gebruiker definitie: $1
+% A user defined warning occurred. see also the \progref
+scan_n_user_defined=02025_N_Gebruiker definitie: $1
+% A user defined note was encountered. see also the \progref
+scan_h_user_defined=02026_H_Gebruiker definitie: $1
+% A user defined hint was encountered. see also the \progref
+scan_i_user_defined=02027_I_Gebruiker definitie: $1
+% User defined information was encountered. see also the \progref
+scan_e_keyword_cant_be_a_macro=02028_E_Sleutelwoord herdefinieren als macro heeft geen effect
+% You cannot redefine keywords with macros.
+scan_f_macro_buffer_overflow=02029_F_Macro buffer overflow bij lezen of expansie van macro
+% Your macro or its result was too long for the compiler.
+scan_w_macro_too_deep=02030_W_Uitwerken van macros heeft niveau 16 overschreden
+% When expanding a macro, macros have been nested to a level of 16.
+% The compiler will expand no further, since this may be a sign that
+% recursion is used.
+scan_w_wrong_styled_switch=02031_W_Compiler opties in delphi commentaar stijl zijn niet ondersteund
+% Compiler switches should be in normal pascal style comments.
+scan_d_handling_switch=02032_DL_Behandel schakelaar "$1"
+% When you set debugging info on (\var{-vd}) the compiler tells you when it
+% is evaluating conditional compile statements.
+scan_c_endif_found=02033_CL_ENDIF $1 gevonden
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifdef_found=02034_CL_IFDEF $1 gevonden, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifopt_found=02035_CL_IFOPT $1 gevonden, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_if_found=02036_CL_IF $1 gevonden, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifndef_found=02037_CL_IFNDEF $1 gevonden, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_else_found=02038_CL_ELSE $1 gevonden, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_skipping_until=02039_CL_Negeer tot...
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements, and whether it is skipping or
+% compiling parts.
+scan_i_press_enter=02040_I_Druk <return> om verder te gaan
+% When the \var{-vi} switch is used, the compiler stops compilation
+% and waits for the \var{Enter} key to be pressed when it encounters
+% a \var{\{\$STOP\}} directive.
+scan_w_unsupported_switch=02041_W_Niet ondersteunde optie $1
+% When warnings are turned on (\var{-vw}) the compiler warns you about
+% unsupported switches. This means that the switch is used in Delphi or
+% Turbo Pascal, but not in \fpc
+scan_w_illegal_directive=02042_W_Ongeldige compiler optie $1
+% When warings are turned on (\var{-vw}) the compiler warns you about
+% unrecognised switches. For a list of recognised switches, \progref
+scan_t_back_in=02043_TL_Terug in $1
+% When you use (\var{-vt}) the compiler tells you when it has finished
+% reading an include file.
+scan_w_unsupported_app_type=02044_W_Niet ondersteund programmatype: $1
+% You get this warning, if you specify an unknown application type
+% with the directive \var{\{\$APPTYPE\}}
+scan_w_app_type_not_support=02045_W_$APPTYPE niet ondersteund op doelsysteem
+% The \var{\{\$APPTYPE\}} directive is supported by certain operating systems only.
+scan_w_description_not_support=02046_W_DESCRIPTIION is niet ondersteund op het geselecteerde OS
+% The \var{\{\$DESCRIPTION\}} directive is not supported on this target OS
+scan_n_version_not_support=02047_N_VERSION is niet ondersteund door het doel OS.
+% The \var{\{\$VERSION\}} directive is not supported on this target OS
+scan_n_only_exe_version=02048_N_VERSION kan alleen voor executables of bibliotheken
+% The \var{\{\$VERSION\}} directive is only used for executable or DLL sources.
+scan_w_wrong_version_ignored=02049_W_verkeerd formaat voor VERSION directive $1
+% The \var{\{\$VERSION\}} directive format is majorversion.minorversion
+% where majorversion and minorversion are words.
+scan_e_illegal_asmmode_specifier=02050_E_Ongeldige assembler-stijl opgegeven: "$1"
+% When you specify an assembler mode with the \var{\{\$ASMMODE xxx\}}
+% the compiler didn't recognize the mode you specified.
+scan_w_no_asm_reader_switch_inside_asm=02051_W_ASM lezer-optie is niet mogelijk in een asm instructie, $1 ingesteld voor volgende blok
+% It is not possible to switch from one assembler reader to another
+% inside an assembler block. The new reader will be used for next
+% assembler statements only.
+scan_e_wrong_switch_toggle=02052_E_Verkeerde optiewaarde, gebruik ON/OFF of +/-
+% You need to use ON or OFF or a + or - to toggle the switch
+scan_e_resourcefiles_not_supported=02053_E_Resource bestanden worden niet ondersteund op doel OS
+% The target you are compiling for doesn't support resource files.
+scan_w_include_env_not_found=02054_W_Include omgevingsvariabele $1 niet gevonden in omgeving
+% The included environment variable can't be found in the environment, it will
+% be replaced by an empty string instead.
+scan_e_invalid_maxfpureg_value=02055_E_Ongeldige waarde voor FPU register limiet
+% Valid values for this directive are 0..8 and NORMAL/DEFAULT
+scan_w_only_one_resourcefile_supported=02056_W_Slechts 1 resource bestand ondersteund voor dit operating systeem.
+% The target you are compiling for supports only one resource file.
+% The first resource file found is used, the others are discarded.
+scan_w_macro_support_turned_off=02057_W_Macro ondersteuning is uitgeschakeld
+% A macro declaration has been found, but macro support is currently off,
+% so the declaration will be ignored. To turn macro support on compile with
+% -Sm on the commandline or add \{\$MACRO ON\} in the source
+scan_e_invalid_interface_type=02058_E_Ongeldig interface type opgegeven. Geldige waarden zijn COM, CORBA of DEFAULT
+% The interface type that was specified is not supported
+scan_w_appid_not_support=02059_W_APPID is slechts ondersteund op PalmOS
+% The \var{\{\$APPID\}} directive is only supported for the PalmOS target.
+scan_w_appname_not_support=02060_W_APPNAME is slechts ondersteund op PalmOS
+% The \var{\{\$APPNAME\}} directive is only supported for the PalmOS target.
+scan_e_string_exceeds_255_chars=02061_E_Constante tekenreeksen (strings) kunnen niet langer dan 255 karakters zijn.
+% A single string constant can contain at most 255 chars. Try splitting up the
+% string in multiple smaller parts and concatenate them with a + operator.
+scan_f_include_deep_ten=02062_F_Include bestanden kunnen maar tot op 16 niveaus genest worden
+% When including include files the files have been nested to a level of 16.
+% The compiler will expand no further, since this may be a sign that
+% recursion is used.
+scan_e_too_many_push=02063_F_Te veel PUSH niveaus
+% A maximum of 20 levels is allowed. This error occurs only in mode MacPas.
+scan_e_too_many_pop=02064_E_POP instructie zonder voorafgaande PUSH instructie
+% This error occurs only in mode MacPas.
+scan_e_error_macro_lacks_value=02065_E_Macro of compilatie-variabele "$1" heeft geen waarde
+% Thus the conditional compile time expression cannot be evaluated.
+scan_e_wrong_switch_toggle_default=02066_E_Verkeerde schakel-waarde. Gebruik ON/OFF/DEFAULT of +/-/*
+% You need to use ON or OFF or DEFAULT or a + or - or * to toggle the switch
+scan_e_mode_switch_not_allowed=02067_E_MODE schakel "$1" is niet toegestaan op deze plaats.
+% A mode switch has already been encountered, or, in case of option -Mmacpas,
+% a mode switch occur after UNIT.
+scan_e_error_macro_undefined=02068_E_Macro of compilatie-variabele "$1" is niet gedefinieerd
+% Thus the conditional compile time expression cannot be evaluated. Only in mode MacPas.
+scan_e_utf8_bigger_than_65535=02069_E_UTF-8 code groter dan 65535 gevonden
+% \fpc handles utf-8 strings internally as widestrings e.g. the char codes are limited to 65535
+scan_e_utf8_malformed=02070_E_Ongeldige UTF-8 tekenreeks
+% The given string isn't a valid UTF-8 string
+scan_c_switching_to_utf8=02071_C_UTF-8 handtekening gevonden, gebruik UTF-8 codering
+% The compiler found an UTF-8 encoding signature (\$ef, \$bb, \$bf) at the beginning of a file,
+% so it interprets it as an UTF-8 file
+scan_e_compile_time_typeerror=02072_E_Compilatie-expressie: "$1" gevraagd, maar kreeg "$2" op "$3"
+% Type check of a compile time expression failed.
+scan_n_app_type_not_support=02073_N_APPTYPE wordt niet ondersteund door het doel OS
+% The \var{\{\$APPTYPE\}} directive is supported by certain operating systems only.
+scan_e_illegal_optimization_specifier=02074_E_Ongeldige optimalisatie gegeven &quot;$1&quot;
+% When you specify an optimization with the \var{\{\$OPTIMIZATION xxx\}}
+% the compiler didn't recognize the optimization you specified.
+scan_w_setpeflags_not_support=02075_W_SETPEFLAGS wordt niet ondersteund door het doel OS
+% The \var{\{\$SETPEFLAGS\}} directive is not supported by the target OS
+scan_w_imagebase_not_support=02076_W_IMAGEBASE wordt niet ondersteunddoor het doel OS
+% The \var{\{\$IMAGEBASE\}} directive is not supported by the target OS
+scan_w_minstacksize_not_support=02077_W_MINSTACKSIZE wordt niet ondersteund door het doel OS
+% The \var{\{\$MINSTACKSIZE\}} directive is not supported by the target OS
+scan_w_maxstacksize_not_support=02078_W_MAXSTACKSIZE wordt niet ondersteund door het doel OS
+#
+# Parser
+#
+# 03192 is the last used one
+#
+% The \var{\{\$MAXSTACKSIZE\}} directive is not supported by the target OS
+% \end{description}
+% \section{Parser messages}
+% This section lists all parser messages. The parser takes care of the
+% semantics of you language, i.e. it determines if your pascal constructs
+% are correct.
+% \begin{description}
+parser_e_syntax_error=03000_E_Parser - Taalfout
+% An error against the Turbo Pascal language was encountered. This happens
+% typically when an illegal character is found in the sources file.
+parser_e_dont_nest_interrupt=03004_E_INTERRUPT procedures kunnen niet genest worden
+% An \var{INTERRUPT} procedure must be global.
+parser_w_proc_directive_ignored=03005_W_Procedure type $1 ignored
+% The specified procedure directive is ignored by FPC programs.
+parser_e_no_overload_for_all_procs=03006_E_Not all declarations of $1 are declared with OVERLOAD
+% When you want to use overloading using the \var{OVERLOAD} directive, then
+% all declarations need to have \var{OVERLOAD} specified.
+parser_e_export_name_double=03008_E_Dubbel geexporteerde functienaam $1
+% Exported function names inside a specific DLL must all be different
+parser_e_export_ordinal_double=03009_E_Dubbel geexporteerde functie index $1
+% Exported function names inside a specific DLL must all be different
+parser_e_export_invalid_index=03010_E_Ongeldige index for geexporteerde functie
+% DLL function index must be in the range \var{1..\$FFFF}
+parser_w_parser_reloc_no_debug=03011_W_Relocatable bibliotheek of applicatie $1 debug informatie niet ondersteund.
+parser_w_parser_win32_debug_needs_WN=03012_W_Om win32 code te debuggen moet relocatie afgezet worden door de -WN optie
+% Stabs info is wrong for relocatable DLL or EXES use -WN
+% if you want to debug win32 executables.
+parser_e_constructorname_must_be_init=03013_E_Constructornaam moet INIT zijn
+% You are declaring an object constructor with a name which is not \var{init}, and the
+% \var{-Ss} switch is in effect. See the \var{-Ss} switch (\seeo{Ss}).
+parser_e_destructorname_must_be_done=03014_E_Destructornaam moet DONE zijn
+% You are declaring an object destructor with a name which is not \var{done}, and the
+% \var{-Ss} switch is in effect. See the \var{-Ss} switch (\seeo{Ss}).
+parser_e_proc_inline_not_supported=03016_E_Procedure type INLINE wordt niet ondersteund
+% You tried to compile a program with C++ style inlining, and forgot to
+% specify the \var{-Si} option (\seeo{Si}). The compiler doesn't support C++
+% styled inlining by default.
+parser_w_constructor_should_be_public=03018_W_Constructor mag niet private or protected zijn
+% Constructors must be in the 'public' part of an object (class) declaration.
+parser_w_destructor_should_be_public=03019_W_Destructor mag niet private or protected zijn
+% Destructors must be in the 'public' part of an object (class) declaration.
+parser_n_only_one_destructor=03020_N_Klasse heeft slechts 1 destructor
+% You can declare only one destructor for a class.
+parser_e_no_local_objects=03021_E_Lokale klassedefinities zijn niet toegestaan
+% Classes must be defined globally. They cannot be defined inside a
+% procedure or function
+parser_f_no_anonym_objects=03022_F_Anonieme klassedefinities zijn niet toegestaan
+% An invalid object (class) declaration was encountered, i.e. an
+% object or class without methods that isn't derived from another object or
+% class. For example:
+% \begin{verbatim}
+% Type o = object
+% a : longint;
+% end;
+% \end{verbatim}
+% will trigger this error.
+parser_n_object_has_no_vmt=03023_N_Het object "$1" heeft geen VMT
+% This is a note indicating that the declared object has no
+% virtual method table.
+parser_e_illegal_parameter_list=03024_E_Foutieve parameterlijst
+% You are calling a function with parameters that are of a different type than
+% the declared parameters of the function.
+parser_e_wrong_parameter_size=03026_E_Onjuist aantal parameters meegegeven
+% There is an error in the parameter list of the function or procedure,
+% the number of parameters is not correct.
+parser_e_overloaded_no_procedure=03027_E_Overladen symbool "$1" is geen procedure of functie
+% The compiler encountered a symbol with the same name as an overloaded
+% function, but it is not a function it can overload.
+parser_e_overloaded_have_same_parameters=03028_E_Overroepen procedures hebben identieke parameterlijst
+% You're declaring overloaded functions, but with the same parameter list.
+% Overloaded function must have at least 1 different parameter in their
+% declaration.
+parser_e_header_dont_match_forward=03029_E_Declaratie komt niet overeen met eerdere declaratie: $1
+% You declared a function with same parameters but
+% different result type or function modifiers.
+parser_e_header_different_var_names=03030_E_Procedurehoofding $1 komt niet overeen met eerdere declaratie: variabelenaam veranderd $2 => $3
+% You declared the function in the \var{interface} part, or with the
+% \var{forward} directive, but define it with a different parameter list.
+parser_n_duplicate_enum=03031_N_Waarden in opsommingstypes moeten steeds stijgen
+% \fpc allows enumeration constructions as in C. Given the following
+% declaration two declarations:
+% \begin{verbatim}
+% type a = (A_A,A_B,A_E:=6,A_UAS:=200);
+% type a = (A_A,A_B,A_E:=6,A_UAS:=4);
+% \end{verbatim}
+% The second declaration would produce an error. \var{A\_UAS} needs to have a
+% value higher than \var{A\_E}, i.e. at least 7.
+parser_e_no_with_for_variable_in_other_segments=03033_E_With kan niet gebruikt worden voor variabelen in verschillende segmenten
+% With stores a variable locally on the stack,
+% but this is not possible if the variable belongs to another segment.
+parser_e_too_much_lexlevel=03034_E_Procedure meer dan 31 keer genest
+% You can nest function definitions only 31 times.
+parser_e_range_check_error=03035_E_Bereikfout bij evalueren constanten
+% The constants are out of their allowed range.
+parser_w_range_check_error=03036_W_Bereikscontrolefout bij evalueren constantes.
+% The constants are out of their allowed range.
+parser_e_double_caselabel=03037_E_Dubbel case-element
+% You are specifying the same label 2 times in a \var{case} statement.
+parser_e_case_lower_less_than_upper_bound=03038_E_Bovengrens van casebereik is lager dan ondergrens
+% The upper bound of a \var{case} label is less than the lower bound and this
+% is useless
+parser_e_type_const_not_possible=03039_E_Getypeerde constanten van klassen zijn niet toegestaan
+% You cannot declare a constant of type class or object.
+parser_e_no_overloaded_procvars=03040_E_Procedurele variabelen van overroepen procedures zijn niet toegestaan
+% You are trying to assign an overloaded function to a procedural variable.
+% This is not allowed
+parser_e_invalid_string_size=03041_E_Stringlengte moet tussen 1 en 255 liggen
+% The length of a shortstring in Pascal is limited to 255 characters. You are
+% trying to declare a string with length lower than 1 or greater than 255
+parser_w_use_extended_syntax_for_objects=03042_W_Gebruik de uitgebreide syntax van DISPOSE en NEW om nieuwe instanties van klassen te genereren
+% If you have a pointer \var{a} to a class type, then the statement
+% \var{new(a)} will not initialize the class (i.e. the constructor isn't
+% called), although space will be allocated. you should issue the
+% \var{new(a,init)} statement. This will allocate space, and call the
+% constructor of the object
+parser_w_no_new_dispose_on_void_pointers=03043_W_Het gebruik van NEW of DISPOSE voor pointers zonder type is zinloos
+parser_e_no_new_dispose_on_void_pointers=03044_E_Het gebruik van NEW of DISPOSE is niet mogelijk voor pointers zonder type
+% You cannot use \var{new(p)} or \var{dispose(p)} if \var{p} is an untyped pointer
+% because no size is associated to an untyped pointer.
+% Accepted for compatibility in \var{tp} and \var{delphi} modes.
+parser_e_class_id_expected=03045_E_Klasse verwacht
+% This happens when the compiler scans a procedure declaration that contains
+% a dot,
+% i.e., a object or class method, but the type in front of the dot is not
+% a known type.
+parser_e_no_type_not_allowed_here=03046_E_Typesymbool is hier niet toegestaan
+% You cannot use a type inside an expression.
+parser_e_methode_id_expected=03047_E_Methode verwacht
+% This identifier is not a method.
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., a object or class method, but the procedure name is not a
+% procedure of this type.
+parser_e_header_dont_match_any_member=03048_E_Proceduredeclaratie komt niet overeen met een methode van deze klasse $1
+% This identifier is not a method.
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., a object or class method, but the procedure name is not a
+% procedure of this type.
+parser_d_procedure_start=03049_DL_procedure/functie $1
+% When using the \var{-vd} switch, the compiler tells you when it starts
+% processing a procedure or function implementation.
+parser_e_error_in_real=03050_E_Foutieve vlottende-komma constante
+% The compiler expects a floating point expression, and gets something else.
+parser_e_fail_only_in_constructor=03051_E_FAIL mag alleen in constructors gebruikt worden
+% You are using the \var{fail} keyword outside a constructor method.
+parser_e_no_paras_for_destructor=03052_E_Destructors hebben geen parameters
+% You are declaring a destructor with a parameter list. Destructor methods
+% cannot have parameters.
+parser_e_only_class_methods_via_class_ref=03053_E_Alleen klassemethoden kunnen gerefereerd worden via een klasse
+% This error occurs in a situation like the following:
+% \begin{verbatim}
+% Type :
+% Tclass = Class of Tobject;
+%
+% Var C : TClass;
+%
+% begin
+% ...
+% C.free
+% \end{verbatim}
+% \var{Free} is not a class method and hence cannot be called with a class
+% reference.
+parser_e_only_class_methods=03054_E_Alleen klassemethoden zijn toegankelijk in klassen
+% This is related to the previous error. You cannot call a method of an object
+% from a inside a class method. The following code would produce this error:
+% \begin{verbatim}
+% class procedure tobject.x;
+%
+% begin
+% free
+% \end{verbatim}
+% Because free is a normal method of a class it cannot be called from a class
+% method.
+parser_e_case_mismatch=03055_E_Type van constante komt niet overeen met dat van de case uitrukking
+% One of the labels is not of the same type as the case variable.
+parser_e_illegal_symbol_exported=03056_E_Het symbool kan niet uitgevoerd worden uit een bibliotheek
+% You can only export procedures and functions when you write a library. You
+% cannot export variables or constants.
+parser_w_should_use_override=03057_W_Een virtuele methode moet met OVERRIDE overroepen worden: $1
+% A method that is declared \var{virtual} in a parent class, should be
+% overridden in the descendent class with the \var{override} directive. If you
+% don't specify the \var{override} directive, you will hide the parent method;
+% you will not override it.
+parser_e_nothing_to_be_overridden=03058_E_Er is geen geerfde methode die overroepen kan worden: $1
+% You are trying to \var{override} a virtual method of a parent class that does
+% not exist.
+parser_e_no_procedure_to_access_property=03059_E_Er is geen lid om de eigenschap te bereiken
+% You specified no \var{read} directive for a property.
+parser_w_stored_not_implemented=03060_W_Stored prorperty directive is not yet implemented
+% The \var{stored} directive is not yet implemented
+parser_e_ill_property_access_sym=03061_E_Ongeldig symbool voor eigenschaptoegang
+% There is an error in the \var{read} or \var{write} directives for an array
+% property. When you declare an array property, you can only access it with
+% procedures and functions. The following code would cause such an error.
+% \begin{verbatim}
+% tmyobject = class
+% i : integer;
+% property x [i : integer]: integer read I write i;
+% \end{verbatim}
+%
+parser_e_cant_access_protected_member=03062_E_Kan niet in beschermd veld van een object schrijven
+% Fields that are declared in a \var{protected} section of an object or class
+% declaration cannot be accessed outside the module where the object is
+% defined, or outside descendent object methods.
+parser_e_cant_access_private_member=03063_E_Kan niet in prive-veld van een object schrijven
+% Fields that are declared in a \var{private} section of an object or class
+% declaration cannot be accessed outside the module where the class is
+% defined.
+parser_e_overridden_methods_not_same_ret=03066_E_Overridden methodes moeten dezelfde resultaat type hebben: "$2" wordt overridden door "$1" met een ander type
+% If you declare overridden methods in a class definition, they must
+% have the same return type.
+parser_e_dont_nest_export=03067_E_Als EXPORT gedeclareerde procedures kunnen niet genest worden
+% You cannot declare a function or procedure within a function or procedure
+% that was declared as an export procedure.
+parser_e_methods_dont_be_export=03068_E_Methoden kunnen niet geexporteerd worden.
+% You cannot declare a procedure that is a method for an object as
+% \var{export}ed.
+parser_e_call_by_ref_without_typeconv=03069_E_Typen van referentieparameters moeten exact overeenkomen. "$1" gekregen, "$2" verwacht.
+% When calling a function declared with \var{var} parameters, the variables in
+% the function call must be of exactly the same type. There is no automatic
+% type conversion.
+parser_e_no_super_class=03070_E_Deze klasse is geen ouderklasse van de huidige klasse
+% When calling inherited methods, you are trying to call a method of a non-related
+% class. You can only call an inherited method of a parent class.
+parser_e_self_not_in_method=03071_E_SELF is alleen toegelaten in methoden.
+% You are trying to use the \var{self} parameter outside an object's method.
+% Only methods get passed the \var{self} parameters.
+parser_e_generic_methods_only_in_methods=03072_E_Methoden kunnen alleen in andere methoden worden aangeroepen met type symbool
+% A construction like \var{sometype.somemethod} is only allowed in a method.
+parser_e_illegal_colon_qualifier=03073_E_Ongeldig gebruik van ':'
+% You are using the format \var{:} (colon) 2 times on an expression that
+% is not a real expression.
+parser_e_illegal_set_expr=03074_E_Bereikfout in setconstructor of dubbel setelement
+% The declaration of a set contains an error. Either one of the elements is
+% outside the range of the set type, either two of the elements are in fact
+% the same.
+parser_e_pointer_to_class_expected=03075_E_Pointer naar klasse verwacht
+% You specified an illegal type in a \var{new} statement.
+% The extended syntax of \var{new} needs an object as a parameter.
+parser_e_expr_have_to_be_constructor_call=03076_E_Uitdrukking moet een constructoraanroep zijn.
+% When using the extended syntax of \var{new}, you must specify the constructor
+% method of the object you are trying to create. The procedure you specified
+% is not a constructor.
+parser_e_expr_have_to_be_destructor_call=03077_E_Uitdrukking moet een destructoraanroep zijn
+% When using the extended syntax of \var{dispose}, you must specify the
+% destructor method of the object you are trying to dispose of.
+% The procedure you specified is not a destructor.
+parser_e_invalid_record_const=03078_E_Ongeldige volgorde van record leden
+% When declaring a constant record, you specified the fields in the wrong
+% order.
+parser_e_false_with_expr=03079_E_Type van uitdrukking moet class of record type zijn
+% A \var{with} statement needs an argument that is of the type \var{record}
+% or \var{class}. You are using \var{with} on an expression that is not of
+% this type.
+parser_e_void_function=03080_E_Procedures kunnen geen resultaat teruggeven
+% In \fpc, you can specify a return value for a function when using
+% the \var{exit} statement. This error occurs when you try to do this with a
+% procedure. Procedures cannot return a value.
+parser_e_only_methods_allowed=03081_E_Constructors, destructors en class operators moeten methoden zijn
+% You're declaring a procedure as destructor, constructor or class operator, when the
+% procedure isn't a class method.
+parser_e_operator_not_overloaded=03082_E_Operator is niet hergedefineerd
+% You're trying to use an overloaded operator when it is not overloaded for
+% this type.
+parser_e_no_such_assignment=03083_E_Het is niet toegestaan de toewijzingsoperator te overroepen voor gelijke typen
+% You can not overload assignment for types
+% that the compiler considers as equal.
+parser_e_overload_impossible=03084_E_Het overroepen van deze operator is onmogelijk
+% The combination of operator, arguments and return type are
+% incompatible.
+parser_e_no_reraise_possible=03085_E_Re-raise is hier niet mogelijk
+% You are trying to raise an exception where it is not allowed. You can only
+% raise exceptions in an \var{except} block.
+parser_e_no_new_or_dispose_for_classes=03086_E_De uitgebreide syntax van NEW of DISPOSE is niet toegestaan voor klassen
+% You cannot generate an instance of a class with the extended syntax of
+% \var{new}. The constructor must be used for that. For the same reason, you
+% cannot call \var{dispose} to de-allocate an instance of a class, the
+% destructor must be used for that.
+parser_e_procedure_overloading_is_off=03088_E_Procedure overroepen is afgezet
+% When using the \var{-So} switch, procedure overloading is switched off.
+% Turbo Pascal does not support function overloading.
+parser_e_overload_operator_failed=03089_E_Deze operator kan niet overroepen worden.
+% You are trying to overload an operator which cannot be overloaded.
+% The following operators can be overloaded :
+% \begin{verbatim}
+% +, -, *, /, =, >, <, <=, >=, is, as, in, **, :=
+% \end{verbatim}
+parser_e_comparative_operator_return_boolean=03090_E_Vergelijkingsoperator moet een boolean type als resultaat hebben.
+% When overloading the \var{=} operator, the function must return a boolean
+% value.
+parser_e_only_virtual_methods_abstract=03091_E_Enkel virtuele methoden kunnen abstract zijn
+% You are declaring a method as abstract, when it is not declared to be
+% virtual.
+parser_f_unsupported_feature=03092_F_Gebruik van niet ondersteunde functionaliteit!
+% You're trying to force the compiler into doing something it cannot do yet.
+parser_e_mix_of_classes_and_objects=03093_E_CLASSES and OBJECTS kunnen niet gemengd worden.
+% You cannot derive \var{objects}, \var{classes}, \var{cppclasses} and \var{interfaces} interttwined . E.g.
+% a class cannot have an object as parent and vice versa.
+parser_w_unknown_proc_directive_ignored=03094_W_Onbekende proceduredirective is genegeerd: $1
+% The procedure directive you specified is unknown.
+parser_e_absolute_only_one_var=03095_E_Absolute kan maar aan een variabele verbonden worden.
+% You cannot specify more than one variable before the \var{absolute} directive.
+% Thus, the following construct will provide this error:
+% \begin{verbatim}
+% Var Z : Longint;
+% X,Y : Longint absolute Z;
+% \end{verbatim}
+% \item [ absolute can only be associated a var or const ]
+% The address of a \var{absolute} directive can only point to a variable or a
+% typed constant. Therefore, the following code will produce this error:
+% \begin{verbatim}
+% Procedure X;
+%
+% var p : longint absolute x;
+% \end{verbatim}
+%
+parser_e_absolute_only_to_var_or_const=03096_E_Absolute kan slechts aan variabelen of constanten verbonden worden.
+% The address of a \var{absolute} directive can only point to a variable or
+% constant. Therefore, the following code will produce this error:
+% \begin{verbatim}
+% Procedure X;
+%
+% var p : longint absolute x;
+% \end{verbatim}
+%
+parser_e_initialized_only_one_var=03097_E_Slechts 1 variabele kan geinitialiseerd worden.
+% You cannot specify more than one variable with a initial value
+% in Delphi mode.
+parser_e_abstract_no_definition=03098_E_Abtracte methoden kunnen niet gedefineerd worden
+% Abstract methods can only be declared, you cannot implement them. They
+% should be overridden by a descendant class.
+parser_e_overloaded_must_be_all_global=03099_E_Deze overroepen procedure kan niet lokaal zijn (moet geexporteerd worden)
+% You are defining a overloaded function in the implementation part of a unit,
+% but there is no corresponding declaration in the interface part of the unit.
+parser_w_virtual_without_constructor=03100_W_Gebruik van virtuele methoden zonder constructor in "$1"
+% If you declare objects or classes that contain virtual methods, you need
+% to have a constructor and destructor to initialize them. The compiler
+% encountered an object or class with virtual methods that doesn't have
+% a constructor/destructor pair.
+parser_c_macro_defined=03101_CL_Macro gedefinieerd: $1
+% When \var{-vc} is used, the compiler tells you when it defines macros.
+parser_c_macro_undefined=03102_CL_Macro definitie verwijderd: $1
+% When \var{-vc} is used, the compiler tells you when it undefines macros.
+parser_c_macro_set_to=03103_CL_Macro $1 heeft waarde $2 gekregen
+% When \var{-vc} is used, the compiler tells you what values macros get.
+parser_i_compiling=03104_I_Compilatie van $1
+% When you turn on information messages (\var{-vi}), the compiler tells you
+% what units it is recompiling.
+parser_u_parsing_interface=03105_UL_Parsen van de interface van unit $1
+% This tells you that the reading of the interface
+% of the current unit starts
+parser_u_parsing_implementation=03106_UL_Parsen van de implementatie van unit $1
+% This tells you that the code reading of the implementation
+% of the current unit, library or program starts
+parser_d_compiling_second_time=03107_DL_Compilatie van $1 voor de tweede keer.
+% When you request debug messages (\var{-vd}) the compiler tells you what
+% units it recompiles for the second time.
+parser_e_no_property_found_to_override=03109_E_Geen eigenschap gevonden om te herdefinieren
+% You want to override a property of a parent class, when there is, in fact,
+% no such property in the parent class.
+parser_e_only_one_default_property=03110_E_Slechts 1 standaardeigenschap is toegestaan, geerfde standaardeigenschap in kind gevonden.
+% You specified a property as \var{Default}, but the class already has a
+% default property, and a class can have only one default property.
+parser_e_property_need_paras=03111_E_Standaardeigenschappen moeten van type array zijn.
+% Only array properties of classes can be made \var{default} properties.
+parser_e_constructor_cannot_be_not_virtual=03112_E_Virtuele constructors worden alleen ondersteunt in het klassemodel
+% You cannot have virtual constructors in objects. You can only have them
+% in classes.
+parser_e_no_default_property_available=03113_E_Geen standaardeigenschap gevonden
+% You are trying to access a default property of a class, but this class (or one of
+% its ancestors) doesn't have a default property.
+parser_e_cant_have_published=03114_E_De klasse kan geen gepubliceerde sectie hebben, gebruik {$M+}
+% If you want a \var{published} section in a class definition, you must
+% use the \var{\{\$M+\}} switch, whch turns on generation of type
+% information.
+parser_e_forward_declaration_must_be_resolved=03115_E_Declaratie van klasse $1 moet worden opgelost om de klasse als ouder te gebruiken
+% To be able to use an object as an ancestor object, it must be defined
+% first. This error occurs in the following situation:
+% \begin{verbatim}
+% Type ParentClas = Class;
+% ChildClass = Class(ParentClass)
+% ...
+% end;
+% \end{verbatim}
+% Where \var{ParentClass} is declared but not defined.
+parser_e_no_local_operator=03116_E_Lokale operatoren worden niet ondersteund
+% You cannot overload locally, i.e. inside procedures or function
+% definitions.
+parser_e_proc_dir_not_allowed_in_interface=03117_E_Procedure directive $1 niet toegestaan in interfacesectie
+% This procedure directive is not allowed in the \var{interface} section of
+% a unit. You can only use it in the \var{implementation} section.
+parser_e_proc_dir_not_allowed_in_implementation=03118_E_Procedure directive $1 niet toegestaan in implementatiesectie
+% This procedure directive is not defined in the \var{implementation} section of
+% a unit. You can only use it in the \var{interface} section.
+parser_e_proc_dir_not_allowed_in_procvar=03119_E_Procedure directive $1 niet toegestaan in procvar declaratie
+% This procedure directive cannot be part of a procedural or function
+% type declaration.
+parser_e_function_already_declared_public_forward=03120_E_Functie is al publiek/forward gedeclareerd $1
+% You will get this error if a function is defined as \var{forward} twice.
+% Or it is once in the \var{interface} section, and once as a \var{forward}
+% declaration in the \var{implmentation} section.
+parser_e_not_external_and_export=03121_E_Kan niet zowel EXPORT als EXTERNAL gebruiken
+% These two procedure directives are mutually exclusive
+parser_w_not_supported_for_inline=03123_W_$1 wordt niet ondersteund voor inline procedure/functie
+% Inline procedures don't support this declaration.
+parser_w_inlining_disabled=03124_W_Inlining uitgeschakeld
+% Inlining of procedures is disabled.
+parser_i_writing_browser_log=03125_I_Schrijven van browser logfile $1
+% When information messages are on, the compiler warns you when it
+% writes the browser log (generated with the \var{\{\$Y+ \}} switch).
+parser_h_maybe_deref_caret_missing=03126_H_misschien is het een pointer, ^ ontbreekt dan
+% The compiler thinks that a pointer may need a dereference.
+parser_f_assembler_reader_not_supported=03127_F_Geselecteerde assemblerlezer wordt niet ondersteund
+% The selected assembler reader (with \var{\{\$ASMMODE xxx\}} is not
+% supported. The compiler can be compiled with or without support for a
+% particular assembler reader.
+parser_e_proc_dir_conflict=03128_E_Procedure directive $1 geeft conflicten met andere directives
+% You specified a procedure directive that conflicts with other directives.
+% for instance \var{cdecl} and \var{pascal} are mutually exclusive.
+parser_e_call_convention_dont_match_forward=03129_E_Aanroep conventie klopt niet met voorwaartse
+% This error happens when you declare a function or procedure with
+% e.g. \var{cdecl;} but omit this directive in the implementation, or vice
+% versa. The calling convention is part of the function declaration, and
+% must be repeated in the function definition.
+parser_e_property_cant_have_a_default_value=03131_E_Eigenschap kan geen standaard waarde hebben
+% Set properties or indexed properties cannot have a default value.
+parser_e_property_default_value_must_const=03132_E_De standaard waarde van een eigenschap moet een constante zijn
+% The value of a \var{default} declared property must be known at compile
+% time. The value you specified is only known at run time. This happens
+% .e.g. if you specify a variable name as a default value.
+parser_e_cant_publish_that=03133_E_Symbool kan niet worden gepubliceerd, alleen mogelijk voor een klasse
+% Only class type variables can be in a \var{published} section of a class
+% if they are not declared as a property.
+parser_e_cant_publish_that_property=03134_E_Dit soort eigenschappen kunnen niet worden gepubliceerd
+% Properties in a \var{published} section cannot be array properties.
+% they must be moved to public sections. Properties in a \var{published}
+% section must be an ordinal type, a real type, strings or sets.
+parser_e_empty_import_name=03136_E_Lege importnaam opgegeven
+% Some targets need a name for the imported procedure or a \var{cdecl} specifier
+parser_e_division_by_zero=03138_E_Deling door nul
+% There is a division by zero encounted
+parser_e_invalid_float_operation=03139_E_Ongeldige vlottende-komma bewerking.
+% An operation on two real type values produced an overflow or a division
+% by zero.
+parser_e_array_lower_less_than_upper_bound=03140_E_Bovengrens van bereik is lager dan ondergrens
+% The upper bound of a an array declaration is less than the lower bound and this
+% is not possible
+parser_w_string_too_long=03141_W_string "$1" is langer dan $2
+% The size of the constant string is larger than the size you specified in
+% string type definition
+parser_e_string_larger_array=03142_E_Stringlengte moet tussen 1 en 255 liggen
+% The size of the constant string is larger than the size you specified in
+% the array[x..y] of char definition
+parser_e_ill_msg_expr=03143_E_Ongeldige uitdrukking achter message optie
+% \fpc supports only integer or string values as message constants
+parser_e_ill_msg_param=03144_E_Message handlers aanvaarden slechts 1 variabele parameter
+% A method declared with the \var{message}-directive as message handler
+% can take only one parameter which must be declared as call by reference
+% Parameters are declared as call by reference using the \var{var}-directive
+parser_e_duplicate_message_label=03145_E_Dubbel message label: $1
+% A label for a message is used twice in one object/class
+parser_e_self_in_non_message_handler=03146_E_Self kan alleen een explicite parameter zijn bij string message handlers
+% The self parameter can only be passed explicitly to a method which
+% is declared as message handler.
+parser_e_threadvars_only_sg=03147_E_Threadvariabelen kunnen alleen globaal of statisch zijn
+% Threadvars must be static or global, you can't declare a thread
+% local to a procedure. Local variables are always local to a thread,
+% because every thread has its own stack and local variables
+% are stored on the stack
+parser_f_direct_assembler_not_allowed=03148_F_Directe assemblercode wordt niet ondersteund door de interne assembler.
+% You can't use direct assembler when using a binary writer, choose an
+% other outputformat or use another assembler reader
+parser_w_no_objpas_use_mode=03149_W_Laad de OBJPAS unit niet manueel, gebruik {$mode objfpc} of {$mode delphi}.
+% You are trying to load the ObjPas unit manually from a uses clause. This is
+% not a good idea. Use the \var{\{\$mode objfpc\}} or
+% \var{\{\$mode delphi\}}
+% directives which load the unit automatically
+parser_e_no_object_override=03150_E_OVERRIDE kan niet gebruikt worden in objecten
+% Override is not supported for objects, use \var{virtual} instead to override
+% a method of a parent object
+parser_e_cant_use_inittable_here=03151_E_Datatypen die initialisatie/finalisatie vereisen zijn niet toegestaan in variabele records.
+% Some data type (e.g. \var{ansistring}) needs initialization/finalization
+% code which is implicitly generated by the compiler. Such data types
+% can't be used in the variant part of a record.
+parser_e_resourcestring_only_sg=03152_E_Resourcestrings kunnen alleen statisch of globaal zijn.
+% Resourcestring can not be declared local, only global or using the static
+% directive.
+parser_e_exit_with_argument_not__possible=03153_E_Exit met parameter is hier niet toegestaan
+% an exit statement with an argument for the return value can't be used here, this
+% can happen e.g. in \var{try..except} or \var{try..finally} blocks
+parser_e_stored_property_must_be_boolean=03154_E_De stored directive verwacht een boolean argument.
+% If you specify a storage symbol in a property declaration, it must be of
+% the type boolean
+parser_e_ill_property_storage_sym=03155_E_Dit symbool is niet toegestaan achter het stored sleutelwoord.
+% You can't use this type of symbol as storage specifier in property
+% declaration. You can use only methods with the result type boolean,
+% boolean class fields or boolean constants
+parser_e_only_publishable_classes_can__be_published=03156_E_Alleen klassen gecompileerd in $M+ modus kunnen een published sectie hebben.
+% In the published section of a class can be only class as fields used which
+% are compiled in \var{\{\$M+\}} or which are derived from such a class. Normally
+% such a class should be derived from TPersitent
+parser_e_proc_directive_expected=03157_E_Proceduredirective verwacht.
+% This error is triggered when you have a \var{\{\$Calling\}} directive without
+% a calling convention specified.
+% It also happens when declaring a procedure in a const block and you
+% used a ; after a procedure declaration which must be followed by a
+% procedure directive.
+% Correct declarations are:
+% \begin{verbatim}
+% const
+% p : procedure;stdcall=nil;
+% p : procedure stdcall=nil;
+% \end{verbatim}
+parser_e_invalid_property_index_value=03158_E_De waarde voor een eigenschapindex moet een ordinale waarde zijn.
+% The value you use to index a property must be of an ordinal type, for
+% example an integer or enumerated type.
+parser_e_procname_to_short_for_export=03159_E_Procedurenaam te kort om te exporteren.
+% The length of the procedure/function name must be at least 2 characters
+% long. This is because of a bug in dlltool which doesn't parse the .def
+% file correct with a name of length 1.
+parser_e_dlltool_unit_var_problem=03160_E_Kan geen DEFFILE item genereren voor globale variabelen.
+parser_e_dlltool_unit_var_problem2=03161_E_Compileer zonder -WD optie
+% You need to compile this file without the -WD switch on the
+% commandline
+parser_f_need_objfpc_or_delphi_mode=03162_F_U moet OBJFPC (-S2) of DELPHI (-Sd) mode gebruiken om deze code te compileren
+% You need to use \{\$mode objfpc\} or \{\$mode delphi\} to compile this file.
+% Or use the equivalent commandline switches -S2 or -Sd.
+parser_e_no_export_with_index_for_target=03163_E_Kan niet exporteren met indexen kleiner dan $1
+% Exporting of functions or procedures with a specified index is not
+% supported on this target.
+parser_e_no_export_of_variables_for_target=03164_E_Exporteren van variabelen is niet ondersteund op $1
+% Exporting of variables is not supported on this target.
+parser_e_improper_guid_syntax=03165_E_Ongeldige GUID aanduiding
+parser_w_interface_mapping_notfound=03168_W_PGeen procedure genaamd "$1" om "$2.$3" te implementeren gevonden
+parser_e_interface_id_expected=03169_E_Interface aanduiding verwacht
+% This happens when the compiler scans a \var{class} declaration that contains
+% \var{interface} function name mapping code like this:
+% \begin{verbatim}
+% type
+% TMyObject = class(TObject, IDispatch)
+% function IUnknown.QueryInterface=MyQueryInterface;
+% ....
+% \end{verbatim}
+% and the \var{interface} before the dot not listed in the inheritance list.
+parser_e_type_cant_be_used_in_array_index=03170_E_Type "$1" kan niet als array index type gebruikt worden
+% Types like \var{qword} or \var{int64} aren't allowed as array index type
+parser_e_no_con_des_in_interfaces=03171_E_Constructors and destructors zijn niet toegestaan in interfaces
+% Constructor and destructor declarations aren't allowed in interface
+% In the most cases the method \var{QueryInterface} of \var{IUnknown} can
+% be used to create a new interface.
+parser_e_no_access_specifier_in_interfaces=03172_E_Toegangsmethoden kunnen niet gebruikt worden in interfaces
+% The access specifiers \var{public}, \var{private}, \var{protected} and
+% \var{pusblished} can't be used in interfaces because all methods
+% of an interfaces must be public.
+parser_e_no_vars_in_interfaces=03173_E_Een interface definitie kan geen velden bevatten
+% Declarations of fields aren't allowed in interfaces. An interface
+% can contain only methods
+parser_e_no_local_proc_external=03174_E_Can lokale procedure niet als EXTERNAL definieren
+% Declaring local procedures as external is not possible. Local procedures
+% get hidden parameters that will make the chance of errors very high
+parser_w_skipped_fields_before=03175_W_Sommige velden voor "$1" zijn niet geinitialiseerd
+% In Delphi mode, not all fields of a typed constant record have to be
+% initialized, but the compiler warns you when it detects such situations.
+parser_e_skipped_fields_before=03176_E_Sommige velden voor "$1" zijn niet geinitialiseerd
+% In all syntax modes but Delphi mode, you can't leave some fields uninitialized
+% in the middle of a typed constant record
+parser_w_skipped_fields_after=03177_W_Sommige velden na "$1" zijn niet geinitialiseerd
+% You can leave some fields at the end of a type constant record uninitialized
+% (the compiler will initialize them to zero automatically). This may be the cause
+% of subtle problems.
+parser_e_varargs_need_cdecl_and_external=03178_E_VARARGS aanduiding zonder CDECL of EXTERNAL
+% The varargs directive can only be used with procedures or functions
+% that are declared with \var{cdecl} and \var{external} directives. The varargs directive
+% is only meant to provide a compatible interface to C functions like printf.
+parser_e_self_call_by_value=03179_E_SELF moet een normale waarde parameter zijn
+% You can't declare self as a const or var parameter, it must always be
+% a call-by-value parameter
+parser_e_interface_has_no_guid=03180_E_Interface "$1" heeft geen interface definitie
+% When you want to assign an interface to a constant, then the interface
+% must have a GUID value set.
+parser_e_illegal_field_or_method=03181_E_Ongekend klasse-veld of methode aanduiding "$1"
+% Properties must refer to a field or method in the same class.
+parser_w_proc_overriding_calling=03182_W_Aanroep-modus "$1" vervangen door "$2"
+% There are two directives in the procedure declaration that specify a calling
+% convention. Only the last directive will be used
+parser_e_no_procvarobj_const=03183_E_Getypeerde constanten van type "procedure of object" kunnen alleen met NIL geinitialiseerd worden
+% You can't assign the address of a method to a typed constant which has a
+% 'procedure of object' type, because such a constant requires two addresses:
+% that of the method (which is known at compile time) and that of the object or
+% class instance it operates on (which can not be known at compile time).
+parser_e_default_value_only_one_para=03184_E_De default aanduiding kan maar bij 1 parameter horen.
+parser_e_default_value_expected_for_para=03185_E_Default parameter vereist voor "$1"
+parser_w_unsupported_feature=03186_W_Gebruik van niet-ondersteunde mogelijkheden
+% You're trying to force the compiler into doing something it cannot do yet.
+parser_h_c_arrays_are_references=03187_H_C arrays worden via referentie doorgegeven
+% Any array passed to a C functions is passed
+% by a pointer (i.e. by reference).
+parser_e_C_array_of_const_must_be_last=03188_E_"C array of const" moet het laatste argument zijn
+% You can not add any other argument after an \var{array of const} for
+% \var{cdecl} functions, as the size pushed on stack for this argument is
+% not known.
+parser_h_type_redef=03189_H_Type "$1" herdefinitie
+% This is an indicator that a previously declared type is
+% being redefined as something else. This may, or may not
+% be, a cause for errors.
+parser_w_cdecl_has_no_high=03190_W_CDECL functies hebben geen HIGH parameter
+% Functions declared with cdecl modifier do not pass an extra implicit parameter.
+parser_w_cdecl_no_openstring=03191_W_CDECL functies ondersteunen geen open strings
+% Openstring is not supported for cdecl'ared functions.
+parser_e_initialized_not_for_threadvar=03192_E_Kan THREADVAR variabelen niet initialiseren
+% Variables declared as threadvar can not be initialized with a default value.
+% The variables will always be filled with zero at the start of a new thread.
+parser_e_msg_only_for_classes=03193_E_de MESSAGE aanduiding is alleen toegestaan in classes
+% The message directive is only supported for Class types.
+parser_e_procedure_or_function_expected=03194_E_Procedure of functie verwacht
+% A class method can only be specified for procedures and functions.
+parser_e_illegal_calling_convention=03195_W_Aanroep-specificatie genegeerd: "$1"
+% Some calling conventions are supported only by certain CPUs. I.e. most non-i386 ports support
+% only the standard ABI calling convention of the CPU.
+parser_e_no_object_reintroduce=03196_E_REINTRODUCE kan niet in objecten worden gebruikt
+% \var{reintroduce} is not supported for objects.
+parser_e_paraloc_only_one_para=03197_E_Elk argument moet zijn eigen locatie hebben
+% If locations for arguments are specified explicitly as it is required by
+% some syscall conventions, each argument must have it's only location, things
+% like \var{procedure p(i,j : longint 'r1');} aren't allowed
+parser_e_paraloc_all_paras=03198_E_Elk argument moet een expliciete locatie hebben
+% If one argument has an explicit argument location, all arguments of a procedure
+% must have one.
+parser_e_illegal_explicit_paraloc=03199_E_Ongekende argument locatie
+% The location specified for an argument isn't recognized by the compiler
+parser_e_32bitint_or_pointer_variable_expected=03200_E_32-bit integer of pointer variabele verwacht
+% The libbase for MorphOS/AmigaOS can be give only as \var{longint}, \var{dword} or any pointer variable.
+parser_e_goto_outside_proc=03201_E_GOTO opdrachten zijn niet toegestaan tussen verschillende procedures
+% It isn't allowed to use the \var{goto} statements referencing labels outside the
+% current procedure. The following example shows the problem:
+% \begin{verbatim}
+% ...
+% procedure p1;
+% label
+% l1;
+%
+% procedure p2;
+% begin
+% goto l1; // This goto ISN'T allowed
+% end;
+%
+% begin
+% p2
+% l1:
+% end;
+% ...
+%
+% \end{verbatim}
+parser_f_too_complex_proc=03202_F_Procedure te moeilijk, te veel registers vereist
+% Your procedure body is too long for the compiler. You should split the
+% procedure into multiple smaller procedures.
+parser_e_illegal_expression=03203_E_Ongeldige uitdrukking
+% This can occur under many circumstances. Mostly when trying to evaluate
+% constant expressions.
+parser_e_invalid_integer=03204_E_Ongeldige integer uitdrukking
+% You made an expression which isn't an integer, and the compiler expects the
+% result to be an integer.
+parser_e_invalid_qualifier=03205_E_Ongeldige aanduiding
+% One of the following is happening :
+% \begin{itemize}
+% \item You're trying to access a field of a variable that is not a record.
+% \item You're indexing a variable that is not an array.
+% \item You're dereferencing a variable that is not a pointer.
+% \end{itemize}
+parser_e_upper_lower_than_lower=03206_E_Bovengrens kleiner dan ondergrens
+% You are declaring a subrange, and the lower limit is higher than the high
+% limit of the range.
+parser_e_macpas_exit_wrong_param=03207_E_Exit parameter moet de naam zijn van de procedure waarin het gebruikt wordt
+% Non local exit is not allowed. This error occurs only in mode MacPas.
+parser_e_illegal_assignment_to_count_var=03208_E_Ongeldige toekenning aan lus-variabele "$1"
+% The type of a \var{for} loop variable must be an ordinal type.
+% Loop variables cannot be reals or strings. You can also not assign values to
+% loop variables inside the loop (except in Delphi and TP modes). Use a while or
+% repeat loop instead if you need to do something like that, since those
+% constructs were built for that.
+parser_e_no_local_var_external=03209_E_Kan een locale variabele niet als EXTERNAL aanduiden
+% Declaring local variables as external is not allowed. Only global variables can reference
+% to external variables.
+parser_e_proc_already_external=03210_E_De procedure is reeds als EXTERNAL aangeduid
+% The procedure is already declared with the EXTERNAL directive in an interface or
+% forward declaration.
+parser_w_implicit_uses_of_variants_unit=03211_W_Impliciet gebruik van de VARIANTS unit
+% The Variant type is used in the unit without any used unit using the Variants unit. The
+% compiler has implicitly added the Variants unit to the uses list. To remove this warning
+% the Variants unit needs to be added to the uses statement.
+parser_e_no_static_method_in_interfaces=03212_E_Class en statische methoden kunnen niet gebruikt worden in interfaces
+% The specifier \var{class} and directive \var{static} can't be used in interfaces
+% because all methods of an interfaces must be public.
+parser_e_arithmetic_operation_overflow=03213_E_Overflow in wiskundige berekening
+% An operation on two integers values produced an overflow
+parser_e_protected_or_private_expected=03214_E_Protected of Private verwacht
+% \var{strict} can be only used together with \var{protected} or \var{private}.
+parser_e_illegal_slice=03215_E_SLICE kan niet buiten de parameter lijst gebruikt worden
+% \var{slice} can be used only for arguments accepting an open array parameter
+parser_e_dispinterface_cant_have_parent=03216_E_Een DISPINTERFACE kan geen ouderklasse hebben.
+% A DISPINMTERFACE is a special type of interface which can't have a parent class
+parser_e_dispinterface_needs_a_guid=03217_E_Een DISPINTERFACE moet een GUID hebben
+% A DISPINMTERFACE always needs an interface identification
+parser_w_overridden_methods_not_same_ret=03218_W_Methodes die worden override-n moeten een soortgelijke return type hebben. Deze code kan crahsen omdat het afhankelijk is van een Delphi parser bug. (&quot;$2&quot; wordt override-n door &quot;$1&quot;, deze heeft een andere return type)
+% If you declare overridden methods in a class definition, they must
+% have the same return type. Some versions of Delphi allow you to change the
+% return type of interface methods, and even to change procedures into
+% functions, but the resulting code may crash depending on the types used
+% and the way the methods are called.
+parser_e_dispid_must_be_ord_const=03219_E_Bericht ID-s moeten ordinale constanten zijn.
+#
+# Type Checking
+#
+# 04049 is the last used one
+#
+% \end{description}
+% \section{Type checking errors}
+% This section lists all errors that can occur when type checking is
+% performed.
+% \begin{description}
+type_e_mismatch=04000_E_Typen stemmen niet overeen
+% This can happen in many cases:
+% \begin{itemize}
+% \item The variable you're assigning to is of a different type than the
+% expression in the assignment.
+% \item You are calling a function or procedure with parameters that are
+% incompatible with the parameters in the function or procedure definition.
+% \end{itemize}
+type_e_incompatible_types=04001_E_Incompatibele typen: kreeg $1, verwachtte $2
+% There is no conversion possible between the two types
+% Another possiblity is that they are declared in different
+% declarations:
+% \begin{verbatim}
+% Var
+% A1 : Array[1..10] Of Integer;
+% A2 : Array[1..10] Of Integer;
+%
+% Begin
+% A1:=A2; { This statement gives also this error, it
+% is due the strict type checking of pascal }
+% End.
+% \end{verbatim}
+type_e_not_equal_types=04002_E_Typen komen niet overeen $1 en $2
+% The types are not equal
+type_e_type_id_expected=04003_E_Typesymbool verwacht
+% The identifier is not a type, or you forgot to supply a type identifier.
+type_e_variable_id_expected=04004_E_Variabelesymbool verwacht
+% This happens when you pass a constant to a routine (such as \var{Inc} var or \var{Dec})
+% when it expects a variable. You can only pass variables as arguments to these functions.
+type_e_integer_expr_expected=04005_E_Gehele uitdrukking verwacht, $1 gekregen
+% The compiler expects an expression of type integer, but gets a different
+% type.
+type_e_boolean_expr_expected=04006_E_Boolean waarde verwacht, kreeg echter "$1"
+% The expression must be a boolean type, it should be return true or
+% false.
+type_e_ordinal_expr_expected=04007_E_Ordinale expressie verwacht
+% The expression must be of ordinal type, i.e., maximum a \var{Longint}.
+% This happens, for instance, when you specify a second argument
+% to \var{Inc} or \var{Dec} that doesn't evaluate to an ordinal value.
+type_e_pointer_type_expected=04008_E_Pointer type verwacht, "$1" gekregen
+% The variable or expression isn't of the type \var{pointer}. This
+% happens when you pass a variable that isn't a pointer to \var{New}
+% or \var{Dispose}.
+type_e_class_type_expected=04009_E_Klasse type verwacht, "$1" gekregen
+% The variable of expression isn't of the type \var{class}. This happens
+% typically when
+% \begin{enumerate}
+% \item The parent class in a class declaration isn't a class.
+% \item An exception handler (\var{On}) contains a type identifier that
+% isn't a class.
+% \end{enumerate}
+type_e_cant_eval_constant_expr=04011_E_Kan constante expressie niet evalueren
+% This error can occur when the bounds of an array you declared does
+% not evaluate to ordinal constants
+type_e_set_element_are_not_comp=04012_E_Elementen van set zijn niet compatible
+% You are trying to make an operation on two sets, when the set element types
+% are not the same. The base type of a set must be the same when taking the
+% union
+type_e_set_operation_unknown=04013_E_Bewerking niet ondersteund voor sets
+% several binary operations are not defined for sets
+% like div mod ** (also >= <= for now)
+type_w_convert_real_2_comp=04014_W_Typeconversie van vlottende-komma type naar COMP, wat een integer type is.
+% An implicit type conversion from a real type to a \var{comp} is
+% encountered. Since \var{comp} is a 64 bit integer type, this may indicate
+% an error.
+type_h_use_div_for_int=04015_H_Gebruik DIV voor gehele getallen om geheel resultaat te krijgen
+% When hints are on, then an integer division with the '/' operator will
+% procuce this message, because the result will then be of type real
+type_e_strict_var_string_violation=04016_E_String typen stemmen niet overeen wegens de $V+ modus
+% When compiling in \var{\{\$V+\}} mode, the string you pass as a parameter
+% should be of the exact same type as the declared parameter of the procedure.
+type_e_succ_and_pred_enums_with_assign_not_possible=04017_E_SUCC of PRED op enumeratietypen met toekenningen zijn niet mogelijk
+% When you declared an enumeration type which has assignments in it, as in C,
+% like in the following:
+% \begin{verbatim}
+% Tenum = (a,b,e:=5);
+% \end{verbatim}
+% you cannot use the \var{Succ} or \var{Pred} functions on them.
+type_e_cant_read_write_type=04018_E_Kan dit type variabelen niet lezen of schrijven
+% You are trying to \var{read} or \var{write} a variable from or to a
+% file of type text, which doesn't support that. Only integer types,
+% reals, pchars and strings can be read from/written to a text file.
+% Booleans can only be written to text files.
+type_e_no_readln_writeln_for_typed_file=04019_E_Kan geen readln of writeln op getypeerde bestanden doen.
+% \var{readln} and \var{writeln} are only allowed for text files.
+type_e_no_read_write_for_untyped_file=04020_E_Kan geen read of write doen op ongetypeerde bestanden.
+% \var{read} and \var{write} are only allowed for text or typed files.
+type_e_typeconflict_in_set=04021_E_Typeconflict tussen setelementen.
+% There is at least one set element which is of the wrong type, i.e. not of
+% the set type.
+type_w_maybe_wrong_hi_lo=04022_W_lo/hi(longint/dword) geeft hoog/laag (ipv byte) woord terug.
+% \fpc supports an overloaded version of \var{lo/hi} for \var{longint/dword/int64/qword}
+% which returns the lower/upper word/dword of the argument. TP always uses
+% a 16 bit \var{lo/hi} which returns always bits 0..7 for \var{lo} and the
+% bits 8..15 for \var{hi}. If you want the TP behavior you have
+% to type cast the argument to \var{word/integer}
+type_e_integer_or_real_expr_expected=04023_E_Integer of vlottende-komma uitdrukking verwacht
+% The first argument to \var{str} must a real or integer type.
+type_e_wrong_type_in_array_constructor=04024_E_Verkeerd type "$1" in array constructor
+% You are trying to use a type in an array constructor which is not
+% allowed.
+type_e_wrong_parameter_type=04025_E_Incompatibel type voor argument #$1: kreeg $2, verwachtte $3
+% You are trying to pass an invalid type for the specified parameter.
+type_e_no_method_and_procedure_not_compatible=04026_E_Methode (variabele) en Procedure (variable) zijn niet compatible
+% You can't assign a method to a procedure variable or a procedure to a
+% method pointer.
+type_e_wrong_math_argument=04027_E_Ongeldige constante opgegeven aan interne wiskundige functie
+% The constant argument passed to a ln or sqrt function is out of
+% the definition range of these functions.
+type_e_no_addr_of_constant=04028_E_Een constante heeft geen adres
+% It is not possible to get the address of a constant, because they
+% aren't stored in memory, you can try making it a typed constant.
+type_e_argument_cant_be_assigned=04029_E_Kan geen waarde toekennen aan argument
+% Only expressions which can be on the left side of an
+% assignment can be passed as call by reference argument
+% Remark: Properties can be only
+% used on the left side of an assignment, but they cannot be used as arguments
+type_e_cannot_local_proc_to_procvar=04030_E_Kan geen lokale procedure toekennen aan procedure variabele
+% It's not allowed to assign a local procedure/function to a
+% procedure variable, because the calling of local procedure/function is
+% different. You can only assign local procedure/function to a void pointer.
+type_e_no_assign_to_addr=04031_E_Kan geen waarde toekennen aan een adres
+% It is not allowed to assign a value to an address of a variable,constant,
+% procedure or function. You can try compiling with -So if the identifier
+% is a procedure variable.
+type_e_no_assign_to_const=04032_E_Kan geen waarde toekennen aan constante
+% It's not allowed to assign a value to a variable which is declared
+% as a const. This is normally a parameter declared as const, to allow
+% changing the value make the parameter as a value parameter or a var.
+type_e_array_required=04033_E_ARRAY type verwacht
+% If you are accessing a variable using an index '[<x>]' then
+% the type must be an array. In FPC mode also a pointer is allowed.
+type_e_interface_type_expected=04034_E_Interface type verwacht, maar kreeg "$1"
+type_w_mixed_signed_unsigned=04035_W_Mengen van mogelijk negatieve uitdrukkingen en longwords geeft een 64-bits resultaat
+% If you divide (or calculate the modulus of) a signed expression by a longword (or vice versa),
+% or if you have overflow and/or range checking turned on and use an arithmetic
+% expression (+, -, *, div, mod) in which both signed numbers and longwords appear,
+% then everything has to be evaluated in 64bit which is slower than normal
+% 32bit arithmetic. You can avoid this by typecasting one operand so it
+% matches the result type of the other one.
+type_w_mixed_signed_unsigned2=04036_W_Mengen van mogelijk negatieve uitdrukkingen en cardinals kan tot range check fouten leiden
+% If you use a binary operator (and, or, xor) and one of
+% the operands is a longword while the other one is a signed expression, then,
+% if range checking is turned on, you may get a range check error because in
+% such a case both operands are converted to longword before the operation is
+% carried out. You can avoid this by typecasting one operand so it
+% matches the result type of the other one.
+type_e_typecast_wrong_size_for_assignment=04037_E_Typecast heeft een verschillende grootte ($1 -> $2) in toekenning
+% Type casting to a type with a different size is not allowed when the variable is
+% used for assigning.
+type_e_array_index_enums_with_assign_not_possible=04038_E_enumeratie typen met vaste waarden kunnen niet als array index gebruikt worden
+% When you declared an enumeration type which has assignments in it, as in C,
+% like in the following:
+% \begin{verbatim}
+% Tenum = (a,b,e:=5);
+% \end{verbatim}
+% you cannot use it as index of an array.
+type_e_classes_not_related=04039_E_Klasse of object types "$1" en "$2" zijn niet verwant
+% There is a typecast from one class or object to another while the class/object
+% are not related. This will probably lead to errors
+type_w_classes_not_related=04040_W_Klasse types "$1" en "$2" zijn niet verwant
+% There is a typecast from one class or object to another while the class/object
+% are not related. This will probably lead to errors
+type_e_class_or_interface_type_expected=04041_E_Klasse of interface type verwacht, maar kreeg "$1"
+type_e_type_is_not_completly_defined=04042_E_Type "$1" is niet volledig gedefinieerd
+type_w_string_too_long=04043_W_String constante heeft meer karakters dan de lengte van een shortstring
+% The size of the constant string, which is assigned to a shortstring,
+% is longer than the maximum size of the shortstring
+type_w_signed_unsigned_always_false=04044_W_De vergelijking is steeds onwaar omwille van de interval waarden
+% There is a comparison between an unsigned value and a signed constant which is
+% less than zero. Because of type promotion, the statement will always evaluate to
+% false. Exlicitly typecast the constant to the correct range to avoid this problem.
+type_w_signed_unsigned_always_true=04045_W_e vergelijking is steeds waar omwille van de interval waarden
+% There is a comparison between an unsigned value and a signed constant which is
+% less than zero. Because of type promotion, the statement will always evaluate to
+% true. Exlicitly typecast the constant to the correct range to avoid this problem.
+type_w_instance_with_abstract=04046_W_Constructie van een klasse "$1" met abstracte methoden
+% An instance of a class is created which contains non-implemented abstract
+% methods. This will probably lead to a runtime error 211 in the code if that
+% routine is ever called. All abstract methods should be overridden.
+type_h_in_range_check=04047_H_De linker operand van de IN operator moet de grootte van een byte hebben
+% The left operand of the \var{in} operator is not an ordinal or enumeration which fits
+% within 8-bits, this may lead to range check errors. The \var{in} operator
+% currently only supports a left operand which fits within a byte. In the case of
+% enumerations, the size of an element of an enumeration can be controlled with
+% the \var{\{\$PACKENUM\}} or \var{\{\$Zn\}} switches.
+type_w_smaller_possible_range_check=04048_W_Grootte-fout voor type, mogelijk verlies van gegevens/interval-check fout
+% There is an assignment to a smaller type than the source type. This means that
+% this may cause a range-check error, or may lead to possible loss of data.
+type_h_smaller_possible_range_check=04049_H_Grootte-fout voor type, mogelijk verlies van gegevens/interval-check fout
+% There is an assignment to a smaller type than the source type. This means that
+% this may cause a range-check error, or may lead to possible loss of data.
+type_e_cant_take_address_of_abstract_method=04050_E_Het adres van een abstracte methode kan niet opgevraagd worden
+% An abstract method has no body, so the address of an abstract method can't be taken.
+type_e_operator_not_allowed=04051_E_De operator kan niet gebruikt worden op dit type operand
+% You are trying an operator that is not available for the type of the
+% operands
+type_e_constant_expr_expected=04052_E_Constante uitdrukking verwacht
+% The compiler expects an constant expression, but gets a variable expression.
+type_e_operator_not_supported_for_types=04053_E_Operatie "$1" niet ondersteund voor types "$2" en "$3"
+% The operation is not allowed for the supplied types
+type_e_illegal_type_conversion=04054_E_Ongeldige type-conversie: "$1" naar "$2"
+% When doing a type-cast, you must take care that the sizes of the variable and
+% the destination type are the same.
+type_h_pointer_to_longint_conv_not_portable=04055_H_Conversies tussen ordinalen en pointers is niet overzetbaar naar andere platformen
+% If you typecast a pointer to a longint (or vice-versa), this code will not compile
+% on a machine using 64-bit for pointer storage.
+type_w_pointer_to_longint_conv_not_portable=04056_W_Conversies tussen ordinalen en pointers is niet overzetbaar naar andere platformen
+% If you typecast a pointer to a ordinal type of a different size (or vice-versa), this can
+% cause problems. This is a warning to help finding the 32bit specific code where cardinal/longint is used
+% to typecast pointers to ordinals. A solution is to use the ptrint/ptruint types instead.
+type_e_cant_choose_overload_function=04057_E_Kan niet beslissen welke overladen functie te kiezen
+% You're calling overloaded functions with a parameter that doesn't correspond
+% to any of the declared function parameter lists. e.g. when you have declared
+% a function with parameters \var{word} and \var{longint}, and then you call
+% it with a parameter which is of type \var{integer}.
+type_e_illegal_count_var=04058_E_Ongeldige lus variabele
+% The type of a \var{for} loop variable must be an ordinal type.
+% Loop variables cannot be reals or strings.
+type_w_double_c_varargs=04059_W_Converteer een real constante waarde naar een double voor C compatbiliteit, doe een expliciete type cast om dit te voorkomen.
+% In C, constant real values are double by default. For this reason, if you
+% pass a constant real value to a variable argument part of a C function, FPC
+% by default converts this constant to double as well. If you want to prevent
+% this from happening, add an explicit typecast around the constant.
+type_e_class_or_cominterface_type_expected=04060_E_Verwachtte een classe- of COM-interface, maar kreeg "$1"
+#
+# Symtable
+#
+# 05060 is the last used one
+#
+% Some operators like the AS operator are only appliable to classes or COM interfaces.
+% \end{description}
+% \section{Symbol handling}
+% This section lists all the messages that concern the handling of symbols.
+% This means all things that have to do with procedure and variable names.
+% \begin{description}
+sym_e_id_not_found=05000_E_Symbool niet gevonden $1
+% The compiler doesn't know this symbol. Usually happens when you misspel
+% the name of a variable or procedure, or when you forgot to declare a
+% variable.
+sym_f_internal_error_in_symtablestack=05001_F_Interne fout in SymTableStack()
+% An internal error occurred in the compiler; If you encounter such an error,
+% please contact the developers and try to provide an exact description of
+% the circumstances in which the error occurs.
+sym_e_duplicate_id=05002_E_Dubbel symbool $1
+% The identifier was already declared in the current scope.
+sym_h_duplicate_id_where=05003_H_Symbool reeds gedefinieerd in $1 op lijn $2
+% The identifier was already declared in a previous scope.
+sym_e_unknown_id=05004_E_Onbekende symbool $1
+% The identifier encountered has not been declared, or is used outside the
+% scope where it is defined.
+sym_e_forward_not_resolved=05005_E_Voorwaartse declaratie niet opgelost $1
+% This can happen in two cases:
+% \begin{itemize}
+% \item This happens when you declare a function (in the \var{interface} part, or
+% with a \var{forward} directive, but do not implement it.
+% \item You reference a type which isn't declared in the current \var{type}
+% block.
+% \end{itemize}
+sym_e_error_in_type_def=05007_E_Fout in type definitie
+% There is an error in your definition of a new array type:
+% \item One of the range delimiters in an array declaration is erroneous.
+% For example, \var{Array [1..1.25]} will trigger this error.
+sym_e_forward_type_not_resolved=05009_E_Forward declaratie niet opgelost $1
+% A symbol was forward defined, but no declaration was encountered.
+sym_e_only_static_in_static=05010_E_Alleen statische variabelen kunnen gebruikt worden in statische methoden
+% A static method of an object can only access static variables.
+sym_f_type_must_be_rec_or_class=05012_F_Record- of klassetype verwacht
+% The variable or expression isn't of the type \var{record} or \var{class}.
+sym_e_no_instance_of_abstract_object=05013_E_U kunt geen vertegenwoordiger van een klasse met abstracte methoden instantieren
+% You are trying to generate an instance of a class which has an abstract
+% method that wasn't overridden.
+sym_w_label_not_defined=05014_W_Label niet gedefineerd $1
+% A label was declared, but not defined.
+sym_e_label_used_and_not_defined=05015_E_Label "$1" gebruikt maar niet gedefinieerd
+% A label was declared and used, but not defined.
+sym_e_ill_label_decl=05016_E_Label foutief gedefineerd
+% This error should never happen; it occurs if a label is defined outside a
+% procedure or function.
+sym_e_goto_and_label_not_supported=05017_E_GOTO en LABEL zijn afgezet (gebruik -Sg)
+% You must compile a program which has \var{label}s and \var{goto} statements
+% with the \var{-Sg} switch. By default, \var{label} and \var{goto} aren't
+% supported.
+sym_e_label_not_found=05018_E_Label niet gevonden
+% A \var{goto label} was encountered, but the label isn't declared.
+sym_e_id_is_no_label_id=05019_E_Symbool is geen label
+% The identifier specified after the \var{goto} isn't of type label.
+sym_e_label_already_defined=05020_E_Label is al gedefineerd
+% You are defining a label twice. You can define a label only once.
+sym_e_ill_type_decl_set=05021_E_Type declaratie van set elementen is foutief
+% The declaration of a set contains an invalid type definition.
+sym_e_class_forward_not_resolved=05022_E_Voorwaartse definitie van klasse niet opgelost $1
+% You declared a class, but you did not implement it.
+sym_n_unit_not_used=05023_H_Unit $1 wordt niet gebruikt in $2
+% The unit referenced in the \var{uses} clause is not used.
+sym_h_para_identifier_not_used=05024_H_Parameter niet gebruikt $1
+% The identifier was declared (locally or globally) but
+% was not used (locally or globally).
+sym_n_local_identifier_not_used=05025_N_Lokale variabele niet gebruikt $1
+% You have declared, but not used a variable in a procedure or function
+% implementation.
+sym_h_para_identifier_only_set=05026_H_Waarde parameter $1 is gedeclareerd maar niet gebruikt.
+% The identifier was declared (locally or globally)
+% set but not used (locally or globally).
+sym_n_local_identifier_only_set=05027_N_Lokale variabele $1 gedeclareerd maar niet gebruikt.
+% The variable in a procedure or function
+% implementation is declared, set but never used.
+sym_h_local_symbol_not_used=05028_H_Lokaal $1 $2 is niet gebruikt
+% A local symbol is never used.
+sym_n_private_identifier_not_used=05029_N_Privaat veld $1.$2 wordt niet gebruikt
+sym_n_private_identifier_only_set=05030_N_Privaat veld $1.$2 gedeclareerd maar niet gebruikt.
+sym_n_private_method_not_used=05031_N_Private methode $1.$2 wordt nooit gebruikt.
+sym_e_set_expected=05032_E_Set type verwacht
+% The variable or expression is not of type \var{set}. This happens in an
+% \var{in} statement.
+sym_w_function_result_not_set=05033_W_Resultaat van functie lijkt niet te zijn toegekend
+% You can get this warning if the compiler thinks that a function return
+% value is not set. This will not be displayed for assembler procedures,
+% or procedures that contain assembler blocks.
+sym_w_wrong_C_pack=05034_W_Type $1 is not aligned correctly in current record for C
+% Arrays with sizes not multiples of 4 will be wrongly aligned
+% for C structures.
+sym_e_illegal_field=05035_E_Onbekend record lid $1
+% The field doesn't exist in the record/object definition.
+sym_w_uninitialized_local_variable=05036_W_Lokale variabele "$1" lijkt niet geinitialiseerd
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_w_uninitialized_variable=05037_W_okale variabele "$1" lijkt niet geinitialiseerd
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_e_id_no_member=05038_E_Geen lid met de naam $1
+% This error is generated when an identifier of a record,
+% field, or method is accessed while it is not defined.
+sym_h_param_list=05039_H_NDeclaratie "$1" gevonden
+% You get this when you use the \var{-vh} switch. In case an overloaded
+% procedure is not found, then all candidate overloaded procedures are
+% listed, with their parameter lists.
+sym_e_segment_too_large=05040_E_Data segment te groot (max. 2GB)
+% You get this when you declare a data element whose size exceeds the
+% prescribed limit (2 Gb on 80386+/68020+ processors)
+sym_e_no_matching_implementation_found=05042_E_Geen overeenstemmende implementatie voor interface methode "$1" gevonden
+% There was no matching method found which could implement the interface
+% method. Check argument types and result type of the methods.
+sym_w_deprecated_symbol=05043_W_Symbool "$1" is afgeraden
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{deprecated} is used. Deprecated symbols may no longer
+% be available in newer versions of the unit / library. Usage of this symbol
+% should be avoided as much as possible.
+sym_w_non_portable_symbol=05044_W_Symbool "$1" is niet overzetbaar naar andere platformen
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{platform} is used. This symbol's value, usage
+% and availability is platform specific and should not be used
+% if the source code must be portable.
+sym_w_non_implemented_symbol=05055_W_Symbool "$1" is niet geimplementeerd
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{unimplemented} is used. This symbol is defined,
+% but is not yet implemented on this specific platform.
+sym_e_cant_create_unique_type=05056_E_Kan geen uniek type aanmaken van dit type
+% Only simple types like ordinal, float and string types are supported when
+% redefining a type with \var{type newtype = type oldtype;}.
+sym_h_uninitialized_local_variable=05057_H_ Lokale variabele "$1" lijkt niet geinitialiseerd
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_h_uninitialized_variable=05058_H_Lokale variabele "$1" lijkt niet geinitialiseerd
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_w_function_result_uninitialized=05059_W_Het resultaat van de Functie lijkt niet geinitialiseerd.
+% This message is displayed if the compiler thinks that the function result
+% variable will be used (i.e. appears in the right-hand-side of an expression)
+% before it is initialized (i.e. appeared in the left-hand side of an
+% assigment)
+sym_h_function_result_uninitialized=05060_H_Het resultaat van de functie lijkt niet geinitialiseerd te zijn.
+% This message is displayed if the compiler thinks that the function result
+% variable will be used (i.e. appears in the right-hand-side of an expression)
+% before it is initialized (i.e. appeared in the left-hand side of an
+% assigment)
+sym_w_identifier_only_read=05061_W_Variabele &quot;$1&quot; wordt gelezen, maar krijgt nergens een waarde
+#
+# Codegenerator
+#
+# 06040 is the last used one
+#
+% You have read the value of a variable, but nowhere assigned a value to
+% it.
+% \end{description}
+% \section{Code generator messages}
+% This section lists all messages that can be displayed if the code
+% generator encounters an error condition.
+% \begin{description}
+cg_e_parasize_too_big=06009_E_Parameters gebruiken meer dan 64 kilobyte
+% The I386 processor limits the parameter list to 65535 bytes (the \var{RET}
+% instruction causes this)
+cg_e_file_must_call_by_reference=06012_E_File variabelen moeten altijd var parameters zijn
+% You cannot specify files as value parameters, i.e. they must always be
+% declared \var{var} parameters.
+cg_e_cant_use_far_pointer_there=06013_E_U kunt daar geen far pointer gebruiken
+% Free Pascal doesn't support far pointers, so you cannot take the address of
+% an expression which has a far reference as a result. The \var{mem} construct
+% has a far reference as a result, so the following code will produce this
+% error:
+% \begin{verbatim}
+% var p : pointer;
+% ...
+% p:=@mem[a000:000];
+% \end{verbatim}
+cg_e_dont_call_exported_direct=06015_E_Procedures die als EXPORT gedeclareerd staan kunnen niet aangeroepen worden
+% No longer in use.
+cg_w_member_cd_call_from_method=06016_W_Mogelijke ongeldige aanroep van constructor of destructor
+% The compiler detected that a constructor or destructor is called within a
+% a method. This will probably lead to problems, since constructors / destructors
+% require parameters on entry.
+cg_n_inefficient_code=06017_N_Inefficiente code
+% Your statement seems dubious to the compiler.
+cg_w_unreachable_code=06018_W_Deze code wordt nooit uitgevoerd
+% You specified a construct which will never be executed. Example:
+% \begin{verbatim}
+% while false do
+% begin
+% {.. code ...}
+% end;
+% \end{verbatim}
+cg_e_cant_call_abstract_method=06020_E_Abstracte methoden kunnen niet direct aangeroepen worden
+% You cannot call an abstract method directy, instead you must call a
+% overriding child method, because an abstract method isn't implemented.
+cg_d_register_weight=06027_DL_Register $1 gewicht $2 $3
+% Debugging message. Shown when the compiler considers a variable for
+% keeping in the registers.
+cg_d_stackframe_omited=06029_DL_Stackframe wordt niet gemaakt
+% Some procedure/functions do not need a complete stack-frame, so it is omitted.
+% This message will be displayed when the {-vd} switch is used.
+cg_e_unable_inline_object_methods=06031_E_Kan inline niet gebruiken voor object methoden
+% You cannot have inlined object methods.
+cg_e_unable_inline_procvar=06032_E_Kan inline niet gebruiken voor procvar aanroepen
+% A procedure with a procedural variable call cannot be inlined.
+cg_e_no_code_for_inline_stored=06033_E_Geen code voor inline procedure opgeslagen
+% The compiler couldn't store code for the inline procedure.
+cg_e_can_access_element_zero=06035_E_Element nul van een ansi/wide- of longstring is niet toegankelijk, gebruik (set)length.
+% You should use \var{setlength} to set the length of an ansi/wide/longstring
+% and \var{length} to get the length of such a string types
+cg_e_cannot_call_cons_dest_inside_with=06037_E_Constructors of destructors kunnen niet aangeroepen worden binnen een 'with' clausule
+% Inside a \var{with} clause you cannot call a constructor or destructor for the
+% object you have in the \var{with} clause.
+cg_e_cannot_call_message_direct=06038_E_Een message handler methode kan niet direct aangeroepen worden.
+% A message method handler method cannot be called directly if it contains an
+% explicit self argument
+cg_e_goto_inout_of_exception_block=06039_E_Sprong in of uit een exception blok
+% It is not allowed to jump in or outside of an exception block like \var{try..finally..end;}:
+% \begin{verbatim}
+% label 1;
+%
+% ...
+%
+% try
+% if not(final) then
+% goto 1; // this line will cause an error
+% finally
+% ...
+% end;
+% 1:
+% ...
+% \end{verbatim}
+cg_e_control_flow_outside_finally=06040_E_Control flow statements niet toegestaan in een finally blok
+% It isn't allowed to use the control flow statements \var{break},
+% \var{continue} and \var{exit}
+% inside a finally statement. The following example shows the problem:
+% \begin{verbatim}
+% ...
+% try
+% p;
+% finally
+% ...
+% exit; // This exit ISN'T allowed
+% end;
+% ...
+%
+% \end{verbatim}
+% If the procedure \var{p} raises an exception the finally block is
+% executed. If the execution reaches the exit, it's unclear what to do:
+% exiting the procedure or searching for another exception handler
+cg_w_parasize_too_big=06041_W_Grootte van de parameters is te groot voor bepaalde CPUs
+% This indicates that you are declaring more than 64K of parameters, which
+% might not be supported on other processor targets.
+cg_w_localsize_too_big=06042_W_Grootte van lokale variabelen is te groot voor sommige CPUs
+% This indicates that you are declaring more than 32K of local variables, which
+% might not be supported on other processor targets.
+cg_e_localsize_too_big=06043_E_Lokale variabelen te groot
+% This indicates that you are declaring more than 32K of local variables, which
+% is not supported by this processor.
+cg_e_break_not_allowed=06044_E_BREAK niet toegelaten
+% You're trying to use \var{break} outside a loop construction.
+cg_e_continue_not_allowed=06045_E_CONTINUE niet toegelaten
+% You're trying to use \var{continue} outside a loop construction.
+cg_f_unknown_compilerproc=06046_F_Ongekende schakel-aanduiding "$1". Kijk na of u de correcte looptijd bibliotheek gebruikt
+# EndOfTeX
+#
+# Assembler reader
+#
+# 07097 is the last used one
+#
+% The compiler expects that the runtime library contains some subrountines. If you see this error
+% and you didn't mess with the runtime library, it's very likely that the runtime library
+% you're using doesn't match the used compiler. If you changed the runtime library this error means
+% that you removed a subroutine which the compiler needs for internal use.
+% \end{description}
+asmr_d_start_reading=07000_DL_Begonnen met verwerken van $1 assembler
+% This informs you that an assembler block is being parsed
+asmr_d_finish_reading=07001_DL_Gedaan met verwerken van $1 assembler
+% This informs you that an assembler block has finished.
+asmr_e_none_label_contain_at=07002_E_Symbool dat geen label is bevat "@"
+% A identifier which isn't a label can't contain a @.
+asmr_e_building_record_offset=07004_E_Fout bij berekenen offset in record
+% There has an error occured while building the offset of a record/object
+% structure, this can happend when there is no field specified at all or
+% an unknown field identifier is used.
+asmr_e_offset_without_identifier=07005_E_OFFSET gebruikt zonder symbool
+% You can only use OFFSET with an identifier. Other syntaxes aren't
+% supported
+asmr_e_type_without_identifier=07006_E_TYPE gebruikt zonder symbool
+% You can only use TYPE with an identifier. Other syntaxes aren't
+% supported
+asmr_e_no_local_or_para_allowed=07007_E_Kan hier geen lokale variabele of parameter gebruiken
+% You can't use a local variable or parameter here, mostly because the
+% addressing of locals and parameters is done using the frame pointer register so the
+% address can't be obtained directly.
+asmr_e_need_offset=07008_E_OFFSET moet hier gebruikt worden
+% You need to use OFFSET <id> here to get the address of the identifier.
+asmr_e_need_dollar=07009_E_Gebruik van $ is hier verplicht
+% You need to use $<id> here to get the address of the identifier.
+asmr_e_cant_have_multiple_relocatable_symbols=07010_E_Kan niet meerdere verplaatsbare symbolen gebruiken
+% You can't have more than one relocatable symbol (variable/typed constant)
+% in one argument.
+asmr_e_only_add_relocatable_symbol=07011_E_Een verplaatsbaar symbool kan enkel toegevoegd worden
+% Relocatable symbols (variable/typed constant) can't be used with other
+% operators. Only addition is allowed.
+asmr_e_invalid_constant_expression=07012_E_Ongeldige constante uitdrukking
+% There is an error in the constant expression.
+asmr_e_relocatable_symbol_not_allowed=07013_E_Verplaatsbaar symbool niet toegelaten
+% You can't use a relocatable symbol (variable/typed constant) here.
+asmr_e_invalid_reference_syntax=07014_E_Ongeldige geheugenlocatie schrijfwijze
+% There is an error in the reference.
+asmr_e_local_para_unreachable=07015_E_$1 niet bereikbaar vanuit deze code
+% You can not read directly the value of a local variable or parameter
+% of a higher level procedure in assembler code (except for
+% local assembler code without parameter nor locals).
+asmr_e_local_label_not_allowed_as_ref=07016_E_Lokale symbolen/labels niet toegestaan als referenties
+% You can't use local symbols/labels as references
+asmr_e_wrong_base_index=07017_E_Ongeldig gebruik van basis en index register
+% There is an error with the base and index register, they are
+% probably incorrect
+asmr_w_possible_object_field_bug=07018_W_Mogelijke fout in behandeling velden van object.
+% Fields of objects or classes can be reached directly in normal or objfpc
+% modes but TP and Delphi modes treat the field name as a simple offset.
+asmr_e_wrong_scale_factor=07019_E_Ongeldige schaalfactor
+% The scale factor given is wrong, only 1,2,4 and 8 are allowed
+asmr_e_multiple_index=07020_E_Meervoudig indexregister gebruik
+% You are trying to use more than one index register
+asmr_e_invalid_operand_type=07021_E_Ongeldig operandus type
+% The operand type doesn't match with the opcode used
+asmr_e_invalid_string_as_opcode_operand=07022_E_Ongeldige tekenreeks als instructie operandus: $1
+% The string specified as operand is not correct with this opcode
+asmr_w_CODE_and_DATA_not_supported=07023_W_@CODE en @DATA worden niet ondersteund
+% @CODE and @DATA are unsupported and are ignored.
+asmr_e_null_label_ref_not_allowed=07024_E_Null label verwijzingen zijn niet toegelaten
+asmr_e_expr_zero_divide=07025_E_Deling door nul
+% There is a division by zero in a constant expression
+asmr_e_expr_illegal=07026_E_Ongeldige uitdrukking
+% There is an illegal expression in a constant expression
+asmr_e_escape_seq_ignored=07027_E_Expliciete reeks genegeerd: $1
+% There is a C-styled string, but the escape sequence in the string
+% is unknown, and is therefore ignored
+asmr_e_invalid_symbol_ref=07028_E_Ongeldige symboolverwijzing
+asmr_w_fwait_emu_prob=07029_W_Fwait kan emulatieproblemen met emu387 veroorzaken
+asmr_w_fadd_to_faddp=07030_W_$1 zonder operand vertaald naar $1P
+asmr_w_enter_not_supported_by_linux=07031_W_De ENTER instructie wordt niet ondersteund door de Linux kernel
+% ENTER instruction can generate a stack page fault that is not
+% caught correctly by the i386 Linux page handler.
+asmr_w_calling_overload_func=07032_W_Een overroepen functie wordt aangeroepen vanuit assemblercode
+% There is a call to an overloaded method in the assembler block,
+% this might be the sign there is a problem
+asmr_e_unsupported_symbol_type=07033_E_Niet ondersteund symbool type voor operandus
+asmr_e_constant_out_of_bounds=07034_E_Constante waarde valt buiten bereik
+asmr_e_error_converting_decimal=07035_E_Fout bij omzetten van decimaal getal $1
+% A constant decimal value does not have the correct syntax
+asmr_e_error_converting_octal=07036_E_Fout bij omzetten van octaal getal $1
+% A constant octal value does not have the correct syntax
+asmr_e_error_converting_binary=07037_E_Fout bij omzetten van binair getal $1
+% A constant binary value does not have the correct syntax
+asmr_e_error_converting_hexadecimal=07038_E_Fout bij omzetten van hexadecimaal getal $1
+% A constant hexadecimal value does not have the correct syntax
+asmr_h_direct_global_to_mangled=07039_H_$1 vertaald naar $2
+asmr_w_direct_global_is_overloaded_func=07040_W_$1 is geassocieerd met een overroepen functie
+asmr_e_cannot_use_SELF_outside_a_method=07041_E_Kan SELF niet buiten een methode gebruiken
+% There is a reference to the \var{self} symbol while it is not
+% allowed. \var{self} can only be referenced inside methods
+asmr_e_cannot_use_OLDEBP_outside_nested_procedure=07042_E_Kan OLDEBP niet buiten een genestelde procedure gebruiken
+% There is a reference to the \var{oldebp} symbol while it is not
+% allowed. \var{oldebp} can only be referenced inside nested routines
+asmr_e_void_function=07043_W_Functies met een ongedefinieerde teruggeefwaarde kunnen geen waarde teruggeven
+% Trying to return a value while in a procedure. A procedure
+% does not have any return value
+asmr_e_SEG_not_supported=07044_E_SEG niet ondersteund
+asmr_e_size_suffix_and_dest_dont_match=07045_E_Grootte-achtervoegsel en doel- of brongrootte komen niet overeen
+% The register size and the opcode size suffix don't match. This is
+% probably an error in the assembler statement
+asmr_w_size_suffix_and_dest_dont_match=07046_W_Grootte-achtervoegsel en doel- of brongrootte komen niet overeen
+% The register size and the opcode size suffix don't match. This is
+% probably an error in the assembler statement
+asmr_e_syntax_error=07047_E_Assembler taalfout
+% There is an assembler syntax error
+asmr_e_invalid_opcode_and_operand=07048_E_Ongeldige combinatie van instructie en operandi
+% The opcode cannot be used with this type of operand
+asmr_e_syn_operand=07049_E_Assembler taalfout in operandum
+asmr_e_syn_constant=07050_E_Assembler taalfout in constante
+asmr_e_invalid_string_expression=07051_E_Ongeldige String uitdrukking
+asmr_w_const32bit_for_address=07052_W_ Constante met symbool $1 voor adres dat zich niet op een pointer bevindt
+% A constant expression represents an address which does not fit
+% into a pointer. The address is probably incorrect
+asmr_e_unknown_opcode=07053_E_Ongekende opcode $1
+% This opcode is not known
+asmr_e_invalid_or_missing_opcode=07054_E_Ongeldige of ontbrekende instructie
+asmr_e_invalid_prefix_and_opcode=07055_E_Ongeldige combinatie van voorvoegsel en instructie: $1
+asmr_e_invalid_override_and_opcode=07056_E_Ongeldige combinatie van segment overroeping en instructie: $1
+asmr_e_too_many_operands=07057_E_Te veel operandi op een lijn
+% There are too many operands for this opcode. Check your
+% assembler syntax
+asmr_w_near_ignored=07058_W_NEAR genegeerd
+asmr_w_far_ignored=07059_W_FAR genegeerd
+asmr_e_dup_local_sym=07060_E_Dubbel lokaal symbool $1
+asmr_e_unknown_local_sym=07061_E_Niet gedefinieerd lokaal symbool $1
+asmr_e_unknown_label_identifier=07062_E_Onbekende labelnaam $1
+asmr_e_invalid_register=07063_E_Ongeldige register naam
+% There is an unknown register name used as operand.
+asmr_e_invalid_fpu_register=07064_E_Ongeldig vlottende-komma registernaam
+% There is an unknown register name used as operand.
+asmr_w_modulo_not_supported=07066_W_Modulo wordt niet ondersteund
+asmr_e_invalid_float_const=07067_E_Ongeldige vlottende-komma constante $1
+% The floating point constant declared in an assembler block is
+% invalid.
+asmr_e_invalid_float_expr=07068_E_Ongeldige vlottende-komma uitdrukking
+% The floating point expression declared in an assembler block is
+% invalid.
+asmr_e_wrong_sym_type=07069_E_Verkeerd symbool type
+asmr_e_cannot_index_relative_var=07070_E_Een lokale variabele of parameter kan niet geindedxeerd worden met een register
+% Trying to index using a base register a symbol which is already relative
+% to a register. This is not possible, and will probably lead to crashes.
+asmr_e_invalid_seg_override=07071_E_Ongeldige segment overroeping
+asmr_w_id_supposed_external=07072_W_Symbool $1 wordt verondersteld extern te zijn
+% There is a reference to an undefined symbol. This will not result
+% in an error, since the symbol might be external, but may cause
+% problems at link time if the symbol is not defined anywhere.
+asmr_e_string_not_allowed_as_const=07073_E_Strings zijn niet toegelaten als constante
+% Character strings are not allowed as constants.
+asmr_e_no_var_type_specified=07074_Geen type van de variabele gegeven
+% The syntax expects a type idenfitifer after the dot, but
+% none was found.
+asmr_w_assembler_code_not_returned_to_text=07075_E_De assembler code stopt niet in een '.text' gedeelte
+% There was a directive in the assembler block to change sections,
+% but there is a missing return to the text section at the end
+% of the assembler block. This might cause errors during link time.
+asmr_e_not_directive_or_local_symbol=07076_E_Geen aanwijzing of lokaal symbool $1
+% This symbol is unknown.
+asmr_w_using_defined_as_local=07077_E_Een gedfinieerde naam wordt gebruikt als assembler label
+asmr_e_dollar_without_identifier=07078_E_Dollar teken gebruikt zonder identifier
+% A constant expression has an identifier which does not start with
+% the $ symbol.
+asmr_w_32bit_const_for_address=07079_W_32bit constante aangemaakt voor adres
+% A constant was used as an address. This is probably an error,
+% since using absolute addresses will probably not work.
+asmr_n_align_is_target_specific=07080_N_.align is doel specifiek, gebruik .balign of .p2align
+% Using the .align directive is platform specific, and its meaning will vary
+% from one platform to another.
+asmr_e_cannot_access_field_directly_for_parameters=07081_E_Kan velden niet direct gebruiken voor parameters.
+% You should load the parameter first into a register and then access the
+% fields using that register.
+asmr_e_cannot_access_object_field_directly=07082_E_Kan velden van objecten/klassen niet direct aanspreken
+% You should load the self pointer first into a register and then access the
+% fields using the register as base. By default the self pointer is available
+% in the esi register on i386.
+asmr_e_unable_to_determine_reference_size=07083_E_Geen grootte aangegegeven en kan de grootte van de operanden niet bepalen
+% You should specify explicitly a size for the reference, because
+% the compiler is unable to determine what size (byte,word,dword,etc.) it
+% should use for the reference.
+asmr_e_cannot_use_RESULT_here=07084_E_Kan RESULT aanduiding niet gebruiken in deze functie
+% Some functions which return complex types cannot use the \var{result}
+% keyword.
+asmr_w_adding_explicit_args_fXX=07086_W_"$1" zonder operand vertaald naar "$1 %st,%st(1)"
+asmr_w_adding_explicit_first_arg_fXX=07087_W_"$1 %st(n)" vertaald naar "$1 %st,%st(n)"
+asmr_w_adding_explicit_second_arg_fXX=07088_W_"$1 %st(n)" vertaald naar "$1 %st(n),%st"
+asmr_e_invalid_char_smaller=07089_E_Karakter < hier niet toegestaan
+% The shift operator requires the << characters. Only one
+% of those characters was found.
+asmr_e_invalid_char_greater=07090_E_Karakter > hier niet toegestaan
+% The shift operator requires the >> characters. Only one
+% of those characters was found.
+asmr_w_align_not_supported=07093_W_ALIGN niet ondersteund
+asmr_e_no_inc_and_dec_together=07094_E_INC en DEC kunnen niet samengaan
+% Trying to use an increment and a decrement within the same
+% opcode on the 680x0. This is impossible.
+asmr_e_invalid_reg_list_in_movem=07095_E_Ongeldige register lijst voor movem
+% Trying to use the \var{movem} opcode with invalid registers
+% to save or restore.
+asmr_e_invalid_reg_list_for_opcode=07096_E_Ongeldige register lijst voor opcode
+asmr_e_higher_cpu_mode_required=07097_E_hogere CPU mode vereist ($1)
+% Trying to use an instruction which is not supported in the current
+% cpu mode. Use a higher cpu generation to be able to use this
+% opcode in your assembler block
+asmr_w_unable_to_determine_reference_size_using_dword=07098_W_Grootte niet opgegeven en kan de grootte van de operanden niet bepalen. De standaard DWORD wordt gebruikt
+% You should specify explicitly a size for the reference, because
+% the compiler is unable to determine what size (byte,word,dword,etc.) it
+% should use for the reference. This warning is only used in Delphi mode where
+% it falls back to use DWORD as default.
+asmr_e_illegal_shifterop_syntax=07099_E_Syntax fout bij het bepalen van een shift operand
+#
+# Assembler/binary writers
+#
+# 08018 is the last used one
+#
+% ARM only; ARM assembler supports a so called shifter operand. The used syntax isn't
+% a valid shifter operand. Example for an operation with shifter operand:
+% \begin{verbatim}
+% asm
+% orr r2,r2,r2,lsl #8
+% end;
+% \end{verbatim}
+asmw_f_too_many_asm_files=08000_F_Te veel assemblerbestanden
+% With smartlinking enabled, there are too many assembler
+% files generated. Disable smartlinking.
+asmw_f_assembler_output_not_supported=08001_F_De geselecteerde assembler modus wordt hier niet ondersteund
+asmw_f_comp_not_supported=08002_F_Het COMP type wordt hier niet ondersteund
+asmw_f_direct_not_supported=08003_F_Directe assembler modus wordt niet ondersteund door de binaire assemblerschrijver
+% Direct assembler mode is not supported for binary writers.
+asmw_e_alloc_data_only_in_bss=08004_E_Ruimte voor gegevens reserveren mag enkel in een bss gedeelte
+asmw_f_no_binary_writer_selected=08005_F_Binaire assemblerschrijver geselecteerd
+asmw_e_opcode_not_in_table=08006_E_Asm: Opcode $1 not gevonden in interne tabel
+asmw_e_invalid_opcode_and_operands=08007_E_Asm: $1 Ongeldige combinatie van instructie en operandi
+asmw_e_16bit_not_supported=08008_E_Asm: 16 Bit geheugenlocaties worden niet ondersteund
+asmw_e_invalid_effective_address=08009_E_Asm: Ongeldig direct adres
+asmw_e_immediate_or_reference_expected=08010_E_Asm: Constante of geheugenadres verwacht
+asmw_e_value_exceeds_bounds=08011_E_Asm: $1 waarde overschrijdt grenzen van $2
+asmw_e_short_jmp_out_of_range=08012_E_Asm: Korte spronginstructie gaat te ver $1
+asmw_e_undefined_label=08013_E_Asm: Ongedefinieerd label $1
+asmw_e_comp_not_supported=08014_E_Asm: COMP type niet ondersteund voor dit platfirl
+asmw_e_extended_not_supported=08015_E_Asm: EXTENDED type niet ondersteund voor dit platform
+asmw_e_duplicate_label=08016_E_Asm: Label dubbel gebruikt: $1
+asmw_e_redefined_label=08017_E_Asm: Label opnieuw gedefinieerd: $1
+asmw_e_first_defined_label=08018_E_Asm: eerste definitie hier
+asmw_e_invalid_register=08019_E_Asm: ongeldig register $1
+asmw_e_16bit_32bit_not_supported=08020_E_Asm: 16 or 32 Bit references not supported
+asmw_e_64bit_not_supported=08021_E_Asm: 64 Bit operands not supported
+#
+# Executing linker/assembler
+#
+# 09034 is the last used one
+#
+# BeginOfTeX
+%
+% \section{Errors of assembling/linking stage}
+% This section lists errors that occur when the compiler is processing the
+% command line or handling the configuration files.
+% \begin{description}
+exec_w_source_os_redefined=09000_W_Bronbesturingssysteem geherdefinieerd
+exec_i_assembling_pipe=09001_I_Assembleren (pijp) van $1
+exec_d_cant_create_asmfile=09002_E_Kan geen assembler bestand $1 niet maken
+% The mentioned file can't be created. Check if you have got
+% access permissions to create this file
+exec_e_cant_create_objectfile=09003_E_Kan geen object bestand openen: $1
+% The mentioned file can't be created. Check if you've
+% got access permissions to create this file
+exec_e_cant_create_archivefile=09004_E_kan geen archief bestand openen: $1
+% The mentioned file can't be created. Check if you've
+% access permissions to create this file
+exec_e_assembler_not_found=09005_E_Assembler $1 niet gevonden. Schakel over op externe assemblage
+exec_t_using_assembler=09006_T_Gebruikte assembler: $1
+exec_e_error_while_assembling=09007_E_Fout bij het assembleren, exit code $1
+% There was an error while assembling the file using an external assembler.
+% Consult the documentation of the assembler tool to find out more information
+% on this error.
+exec_e_cant_call_assembler=09008_E_Kan de assembler niet oproepen, fout $1. Schakel over op externe assemblage
+exec_i_assembling=09009_I_Assembleren van $1
+exec_i_assembling_smart=09010_I_Assembleren slim-link $1
+exec_w_objfile_not_found=09011_W_Bestand $1 niet gevonden, linken kan foutlopen !
+% One of the object file is missing, and linking will probably fail.
+% Check your paths.
+exec_w_libfile_not_found=09012_W_Bibliotheek $1 niet gevonden, linken kan foutlopen !
+% One of the library file is missing, and linking will probably fail.
+% Check your paths.
+exec_e_error_while_linking=09013_E_Fout bij het linken
+% Generic error while linking.
+exec_e_cant_call_linker=09014_E_Kan de linker niet oproepen, schakel over op extern linken
+exec_i_linking=09015_I_Linken van $1
+exec_e_util_not_found=09016_E_Gereedschap $1 niet gevonden, schakel over op extern linken
+exec_t_using_util=09017_T_Gebruik tool $1
+exec_e_exe_not_supported=09018_E_Creatie van executable bestanden niet ondersteund.
+exec_e_dll_not_supported=09019_E_Dynamische bibliotheken niet ondersteund
+exec_i_closing_script=09020_I_Afsluiten batch $1
+exec_e_res_not_found=09021_E_Resource compiler niet gevonde, schakel over op externe modus
+exec_i_compilingresource=09022_I_Compileer resource $1
+exec_t_unit_not_static_linkable_switch_to_smart=09023_T_Unit $1 kan niet statisch gelinkt worden. Schakel over op slim linken
+exec_t_unit_not_smart_linkable_switch_to_static=09024_T_Unit $1 kan niet slim gelinkt worden. Schakel over op statisch linken
+exec_t_unit_not_shared_linkable_switch_to_static=09025_T_Unit $1 kan niet gedeeld gelinkt worden, Schakel over op statisch linken
+exec_e_unit_not_smart_or_static_linkable=09026_E_Unit $1 kan niet slim of statisch gelinkt worden
+exec_e_unit_not_shared_or_static_linkable=09027_E_Unit $1 kan niet gedeeld of statisch gelinkt worden
+exec_d_resbin_params=09028_D_Oproep resource compiler "$1" met "$2" als commando-lijn opties
+# EndOfTeX
+#
+# Executable information
+#
+%\end{description}
+execinfo_f_cant_process_executable=09128_F_Kan applicatie niet nabehandelen $1
+execinfo_f_cant_open_executable=09129_F_Kan applicatie niet openen $1
+execinfo_x_codesize=09130_X_Grootte van de code: $1 bytes
+execinfo_x_initdatasize=09131_X_Grootte van geinitialiseerde data: $1 bytes
+execinfo_x_uninitdatasize=09132_X_Grootte van niet-geinitialiseerde data: $1 bytes
+execinfo_x_stackreserve=09133_X_Gereserveerde stackruimte: $1 bytes
+execinfo_x_stackcommit=09134_X_Toegewezen stackruimte: $1 bytes
+#
+# Unit loading
+#
+# 10041 is the last used one
+#
+# BeginOfTeX
+% \section{Unit loading messages.}
+% This section lists all messages that can occur when the compiler is
+% loading a unit from disk into memory. Many of these messages are
+% informational messages.
+% \begin{description}
+unit_t_unitsearch=10000_T_Unit zoeken: $1
+% When you use the \var{-vt}, the compiler tells you where it tries to find
+% unit files.
+unit_t_ppu_loading=10001_T_PPU Laden $1
+% When the \var{-vt} switch is used, the compiler tells you
+% what units it loads.
+unit_u_ppu_name=10002_U_PPU Naam: $1
+% When you use the \var{-vu} flag, the unit name is shown.
+unit_u_ppu_flags=10003_U_PPU Vlaggen: $1
+% When you use the \var{-vu} flag, the unit flags are shown.
+unit_u_ppu_crc=10004_U_PPU CRC: $1
+% When you use the \var{-vu} flag, the unit CRC check is shown.
+unit_u_ppu_time=10005_U_PPU Tijd: $1
+% When you use the \var{-vu} flag, the time the unit was compiled is shown.
+unit_u_ppu_file_too_short=10006_U_PPU bestand te kort
+% The ppufile is too short, not all declarations are present.
+unit_u_ppu_invalid_header=10007_U_PPU Ongeldige kop (geen PPU aan het begin)
+% A unit file contains as the first three bytes the ascii codes of \var{PPU}
+unit_u_ppu_invalid_version=10008_U_PPU Ongeldige versie $1
+% This unit file was compiled with a different version of the compiler, and
+% cannot be read.
+unit_u_ppu_invalid_processor=10009_U_PPU is gecompileerd voor een andere processor
+% This unit file was compiled for a different processor type, and
+% cannot be read
+unit_u_ppu_invalid_target=10010_U_PPU is gecompileerd voor een ander doelsysteem
+% This unit file was compiled for a different target, and
+% cannot be read
+unit_u_ppu_source=10011_U_PPU bron: $1
+% When you use the \var{-vu} flag, the unit source file name is shown.
+unit_u_ppu_write=10012_U_Schrijven van $1
+% When you specify the \var{-vu} switch, the compiler will tell you where it
+% writes the unit file.
+unit_f_ppu_cannot_write=10013_F_Kan PPU bestand niet schrijven
+% An error occurred when writing the unit file.
+unit_f_ppu_read_error=10014_F_Lezen van PPU bestand
+% This means that the unit file was corrupted, and contains invalid
+% information. Recompilation will be necessary.
+unit_f_ppu_read_unexpected_end=10015_F_Onverwacht einde van PPU-bestand
+% Unexpected end of file. This may mean that the PPU file is
+% corrupted.
+unit_f_ppu_invalid_entry=10016_F_Ongeldig PPU bestand post: $1
+% The unit the compiler is trying to read is corrupted, or generated with a
+% newer version of the compiler.
+unit_f_ppu_dbx_count_problem=10017_F_PPU Dbx aantal probleem
+% There is an inconsistency in the debugging information of the unit.
+unit_e_illegal_unit_name=10018_E_Ongeldige unitnaam: $1
+% The name of the unit does not match the file name.
+unit_f_too_much_units=10019_F_Te veel units
+% \fpc has a limit of 1024 units in a program. You can change this behavior
+% by changing the \var{maxunits} constant in the \file{fmodule.pas} file of the
+% compiler, and recompiling the compiler.
+unit_f_circular_unit_reference=10020_F_Uses statement veroorzaakt vicieuze cirkel tussen $1 en $2
+% Two units are using each other in the interface part. This is only allowed
+% in the \var{implementation} part. At least one unit must contain the other one
+% in the \var{implementation} section.
+unit_f_cant_compile_unit=10021_F_Kan unit $1 niet compileren, geen broncode beschikbaar
+% A unit was found that needs to be recompiled, but no sources are
+% available.
+unit_f_cant_find_ppu=10022_F_Kan unit $1 niet vinden
+% You tried to use a unit of which the PPU file isn't found by the
+% compiler. Check your configuration file for the unit paths
+unit_w_unit_name_error=10023_W_Unit $1 niet gevonden maar $2 bestaat
+unit_f_unit_name_error=10024_F_Unit $1 gezocht maar $2 gevonden
+% Dos truncation of 8 letters for unit PPU files
+% may lead to problems when unit name is longer than 8 letters.
+unit_w_switch_us_missed=10025_W_De systeemunit compileren vereist de -Us schakelaar
+% When recompiling the system unit (it needs special treatment), the
+% \var{-Us} must be specified.
+unit_f_errors_in_unit=10026_F_Er waren fouten $1 bij het compileren van een module, compilatie gestopt.
+% When the compiler encounters a fatal error or too many errors in a module
+% then it stops with this message.
+unit_u_load_unit=10027_U_Laden van $1 ($2) unit $3
+% When you use the \var{-vu} flag, which unit is loaded from which unit is
+% shown.
+unit_u_recompile_crc_change=10028_U_Hercompileer $1, checksum voor $2 veranderd
+unit_u_recompile_source_found_alone=10029_U_herkompileer $1, alleen bron gevonden
+% When you use the \var{-vu} flag, these messages tell you why the current
+% unit is recompiled.
+unit_u_recompile_staticlib_is_older=10030_U_Hercompileer unit, statische bibliotheek ouder dan ppu-bestand
+% When you use the \var{-vu} flag, the compiler warns if the static library
+% of the unit are older than the unit file itself.
+unit_u_recompile_sharedlib_is_older=10031_U_Hercompileer unit, dynamische bibliotheek ouder dan ppu-bestand
+% When you use the \var{-vu} flag, the compiler warns if the shared library
+% of the unit are older than the unit file itself.
+unit_u_recompile_obj_and_asm_older=10032_U_Hercompileer unit, object en asm zijn ouder dan ppu-bestand
+% When you use the \var{-vu} flag, the compiler warns if the assembler or
+% object file of the unit are older than the unit file itself.
+unit_u_recompile_obj_older_than_asm=10033_U_Hercompileer unit, object is ouder dan assembler
+% When you use the \var{-vu} flag, the compiler warns if the assembler
+% file of the unit is older than the object file of the unit.
+unit_u_parsing_interface=10034_U_Interface van $1 wordt geparsed
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% parsing the interface part of the unit
+unit_u_parsing_implementation=10035_U_Implementatie van $1 wordt geparsed
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% parsing the implementation part of the unit
+unit_u_second_load_unit=10036_U_Tweede maal unit $1 laden
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% recompiling a unit for the second time. This can happend with interdepend
+% units.
+unit_u_check_time=10037_U_PPU Controleren van bestand $1 tijd $2
+### The following two error msgs is currently disabled.
+#unit_h_cond_not_set_in_last_compile=10038_H_Conditional $1 was not set at startup in last compilation of $2
+#% when recompilation of an unit is required the compiler will check that
+#% the same conditionals are set for the recompiliation. The compiler has
+#% found a conditional that currently is defined, but was not used the last
+#% time the unit was compiled.
+#unit_h_cond_set_in_last_compile=10039_H_Conditional $1 was set at startup in last compilation of $2
+#% when recompilation of an unit is required the compiler will check that
+#% the same conditionals are set for the recompiliation. The compiler has
+#% found a conditional that was used the last time the unit was compiled, but
+#% the conditional is currently not defined.
+% When you use the \var{-vu} flag, the compiler show the filename and
+% date and time of the file which a recompile depends on
+unit_w_cant_compile_unit_with_changed_incfile=10040_W_Kan unit $1 niet hercompileren, maar vond gewijzigde include bestanden
+% A unit was found to have modified include files, but
+% some source files were not found, so recompilation is impossible.
+unit_h_source_modified=10041_H_Bestand $1 is nieuwer dan release PPU bestand $2
+% A modified source file for a unit was found that was compiled with the
+% release flag (-Ur). The unit will not implicitly be recompiled because
+% this release flag is set.
+unit_u_ppu_invalid_fpumode=10042_U_Er wordt een unit gebruikt die niet met de correcte FPU modus is gecompileerd
+% Trying to compile code while using units which were not compiled with
+% the same floating point format mode. Either all code should be compiled
+% with FPU emulation on, or with FPU emulation off.
+unit_u_loading_interface_units=10043_U_Laden van interface units voor unit $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% loading the units defined in the interface part of the unit.
+unit_u_loading_implementation_units=10044_U_Laden van implementatie units voor unit $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% loading the units defined in the implementation part of the unit.
+unit_u_interface_crc_changed=10045_U_Interface CRC voor unit $1 is gewijzigd
+% When you use the \var{-vu} flag, the compiler warns that it the
+% CRC calculated for the interface has been changed after the implementation
+% has been parsed.
+unit_u_implementation_crc_changed=10046_U_Implementatie CRC voor unit $1 is gewijzigd
+% When you use the \var{-vu} flag, the compiler warns that it the
+% CRC calculated has been changed after the implementation
+% has been parsed.
+unit_u_finished_compiling=10047_U_Klaar met compileren van unit $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has finished compiling the unit.
+unit_u_add_depend_to=10048_U_Afhankelijkheid van $1 toegevoegd aan $2
+% When you use the \var{-vu} flag, the compiler warns that it
+% has added a dependency between the two units.
+unit_u_no_reload_is_caller=10049_U_Niet herladen, oproeper is: $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has will not reload the unit because it is the unit that wants
+% to load this unit
+unit_u_no_reload_in_second_compile=10050_U_Niet herladen, reads in tweede compilatie: $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has will not reload the unit because it is already in a second recompile
+unit_u_flag_for_reload=10051_U_Vlaggen voor herladen: $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has to reload the unit
+unit_u_forced_reload=10052_U_Verplicht herladen
+% When you use the \var{-vu} flag, the compiler warns that it
+% has is reloading the unit because it was required
+unit_u_previous_state=10053_U_Vorige toestand van $1: $2
+% When you use the \var{-vu} flag, the compiler shows the
+% previous state of the unit
+unit_u_second_compile_unit=10054_U_$1 wordt reeds gecompileerd, tweede compile wordt gezet
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% recompiling a unit for the second time. This can happend with interdepend
+% units.
+unit_u_loading_unit=10055_U_Laden unit $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% loading the unit.
+unit_u_finished_loading_unit=10056_U_Klaar met laden van unit $1
+% When you use the \var{-vu} flag, the compiler warns that it finished
+% loading the unit.
+unit_u_registering_new_unit=10057_U_Nieuwe unit $1 wordt geregistreerd
+% When you use the \var{-vu} flag, the compiler warns that it has
+% found a new unit and registers it in the internal lists.
+unit_u_reresolving_unit=10058_U_Opnieuw oplossen van unit $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has to recalculate the internal data of the unit
+unit_u_skipping_reresolving_unit=10059_U_Oplossen van unit $1 wordt overgeslagen, gebruikte units worden nog geladen
+# EndOfTeX
+#
+# Options
+#
+# 11039 is the last used one
+#
+% When you use the \var{-vu} flag, the compiler warns that it
+% skips to recalculate the internal data of the unit because there
+% is no data to recalculate
+% \end{description}
+option_usage=11000_O_$1 [opties] <bestand> [opties]
+# BeginOfTeX
+%
+% \section{Command-line handling errors}
+% This section lists errors that occur when the compiler is processing the
+% command line or handling the configuration files.
+% \begin{description}
+option_only_one_source_support=11001_W_Maar een (1) bronbestand wordt ondersteunt
+% You can specify only one source file on the command line. The first
+% one will be compiled, others will be ignored. This may indicate that
+% you forgot a \var{'-'} sign.
+option_def_only_for_os2=11002_W_Een DEF file kan alleen worden gemaakt voor OS/2
+% This option can only be specified when you're compiling for OS/2
+option_no_nested_response_file=11003_E_Geneste optie bestanden niet ondersteund
+% you cannot nest response files with the \var{@file} command-line option.
+option_no_source_found=11004_F_Geen bronbestand op de commando-lijn
+% The compiler expects a source file name on the command line.
+option_no_option_found=11005_N_geen opties in configuratie bestand $1
+% The compiler didn't find any option in that config file.
+option_illegal_para=11006_E_Ongeldige parameter: $1
+% You specified an unknown option.
+option_help_pages_para=11007_H_-? druk hulp af
+% When an unknown option is given, this message is diplayed.
+option_too_many_cfg_files=11008_F_Te veel geneste instellingsbestanden
+% You can only nest up to 16 config files.
+option_unable_open_file=11009_F_Kan bestand $1 niet openen
+% The option file cannot be found.
+option_reading_further_from=11010_D_Meer instellingen worden gelezen van $1
+% Displayed when you have notes turned on, and the compiler switches
+% to another options file.
+option_target_is_already_set=11011_W_Doel is reeds ingesteld op: $1
+% Displayed if more than one \var{-T} option is specified.
+option_no_shared_lib_under_dos=11012_W_Shared bibliotheken niet onderteund onder DOS, val terug op statisch
+% If you specify \var{-CD} for the \dos platform, this message is displayed.
+% The compiler supports only static libraries under \dos
+option_too_many_ifdef=11013_F_Te veel IF(N)DEFs
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_too_many_endif=11014_F_Te veel ENDIFs
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_too_less_endif=11015_F_Open voorwaardelijke aan eind van bestand
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_no_debug_support=11016_W_Debug informatie generatie wordt niet ondersteund door deze applicatie
+% It is possible to have a compiler executable that doesn't support
+% the generation of debugging info. If you use such an executable with the
+% \var{-g} switch, this warning will be displayed.
+option_no_debug_support_recompile_fpc=11017_H_Hercompileer de compiler-applicatie met -dGDB
+% It is possible to have a compiler executable that doesn't support
+% the generation of debugging info. If you use such an executable with the
+% \var{-g} switch, this warning will be displayed.
+option_obsolete_switch=11018_W_U gebruikt een in onbruik geraakte schakeloptie $1
+% this warns you when you use a switch that is not needed/supported anymore.
+% It is recommended that you remove the switch to overcome problems in the
+% future, when the switch meaning may change.
+option_obsolete_switch_use_new=11019_W_U gebruikt een in onbruik geraakte schakeloptie $1, gebruik $2 a.u.b.
+% this warns you when you use a switch that is not supported anymore. You
+% must now use the second switch instead.
+% It is recommended that you change the switch to overcome problems in the
+% future, when the switch meaning may change.
+option_switch_bin_to_src_assembler=11020_N_De assembler wordt veranderd in de standaard assemblerschrijver
+% this notifies you that the assembler has been changed because you used the
+% -a switch which can't be used with a binary assembler writer.
+option_incompatible_asm=11021_W_Geselecteerde assembler "$1" is niet verenigbaar met "$2"
+option_asm_forced=11022_W_Gebruik van "$1" assembler opgelegd
+% The assembler output selected can not generate
+% object files with the correct format. Therefore, the
+% default assembler for this target is used instead.
+option_using_file=11026_T_Opties worden gelezen van bestand $1
+% Options are also read from this file
+option_using_env=11027_T_Opties worden gelezen van omgevingsvariabelen $1
+% Options are also read from this environment string
+option_handling_option=11028_D_Behandelen van optie "$1"
+% Debug info that an option is found and will be handled
+option_help_press_enter=11029__***Druk op de ENTER toets***
+option_start_reading_configfile=11030_H_Start lezen van configuratie bestand $1
+% Starting of config file parsing.
+option_end_reading_configfile=11031_H_Einde van lezen van configuratie bestand $1
+% End of config file parsing.
+option_interpreting_option=11032_D_Optie $1 wordt behandeld
+option_interpreting_firstpass_option=11036_D_Behandel prioritaire optie "$1"
+option_interpreting_file_option=11033_D_Behandel bestandsoptie "$1"
+option_read_config_file=11034_D_Lezen configuratie bestand "$1"
+option_found_file=11035_D_Bronbestand "$1" gevonden
+% Additional infos about options, displayed
+% when you have debug option turned on.
+option_code_page_not_available=11039_E_Ongekende coderingspagina
+option_config_is_dir=11040_F_Config bestand $1 is een directorie
+# EndOfTeX
+#
+# Logo (option -l)
+#
+% Directories can not be used as configuration files.
+%\end{description}
+option_logo=11023_[
+Free Pascal Compiler versie $FPCFULLVERSION [$FPCDATE] voor $FPCTARGET
+Copyright (c) 1998-2011 door Florian Klaempfl en anderen
+]
+#
+# Info (option -i)
+#
+option_info=11024_[
+Free Pascal Compiler versie $FPCVERSION
+Compiler datum: $FPCDATE
+Compiler doelsysteem: $FPCTARGET
+Dit programma wordt verspreid onder de GNU General Public Licence
+Voor meer informatie, lees COPYING.FPC. Hiervan is helaas geen
+Nederlandse vertaling beschikbaar.
+ http://bugs.freepascal.org
+of
+ bugs@freepascal.org
+]
+#
+# Help pages (option -? and -h)
+#
+# The first character on the line indicates who will display this
+# line, the current possibilities are :
+# * = every target
+# 3 = 80x86 targets
+# 6 = 680x0 targets
+# e = in extended debug mode only
+# P = PowerPC targets
+# S = Sparc targets
+# V = Virtual machine targets
+# The second character also indicates who will display this line,
+# (if the above character was TRUE) the current possibilities are :
+# * = everyone
+# g = with GDB info supported by the compiler
+# O = OS/2
+# L = UNIX systems
+# The third character represents the indentation level.
+#
+option_help_pages=11025_[
+**0*_+ schakelt optie aan, - af
+**1a_De compiler verwijdert gegenereerd assemblerbestand niet
+**2al_Toon broncode in assemblerbestand
+**2ar_Toon registerreservering/-vrijgave in assemblerbestand
+**2at_Toon reservering/vrijgave van tijdelijke ruimte in assemblerbestand
+**1b_genereer browserinfo
+**2bl_genereer info voor lokale symbolen info
+**1B_Bouw alle modules
+**1C_Codegeneratie opties
+3*2CD_Creeer dynamische bibliotheek
+**2Ch<n>_<n> bytes heap (tussen 1023 en 67107840)
+**2Ci_IO-checking
+**2Cn_Laat linken achterwege
+**2Co_Controleer overflow van integeroperaties
+**2Cr_Bereikcontrole (range check)
+**2Cs<n>_Stel stackgrootte in op <n>
+**2Ct_Stackcontrole
+3*2CS_Cre‰er dynamische bibliotheek
+3*2Cx_Gebruik slim linken
+**1d<x>_definieer het symbool <x>
+*O1D_genereer een DEF bestand
+*O2Dd<x>_Zet beschrijving op <x>
+*O2Dw_PM applicatie
+**1e<x>_Zet pad naar applicaties
+**1E_Zelfde als -Cn
+**1F_Zet bestandsnamen en paden
+**2Fe<x>_Zend foutboodschappen naar bestand <x>
+*L2Fg<x>_Zelfde als -Fl
+**2Fi<x>_Voegt <x> toe aan invoegpad
+**2Fl<x>_Voegt <x> toe aan bibliotheek-pad
+*L2FL<x>_Gebruik <x> als dynamische linker
+**2Fo<x>_Voeg <x> toe aan object-pad
+**2Fr<x>_Lees foutmeldingen uit bestand <x>
+**2Fu<x>_Voeg <x> toe aan unit pad
+**2FU<x>_Schrijf units in folder <x>, (primeert op -FE)
+*g1g_genereer debuginformatie
+*g2gg_gebruik gsym
+*g2gd_gebruik dbx
+*g2gh_laad heaptrc unit automatisch
+*g2gl_Gebruik regelinformatie unit voor meer informatie in backtraces
+*g2gc_genereer controles voor pointers
+**1i_informatie
+**2iD_Toon compilerdatum
+**2iV_Toon compilerversie
+**2iSO_Toon compiler-OS
+**2iSP_Toon compilerprocessor
+**2iTO_Toon doel-OS
+**2iTP_Toon doelprocessor
+**1I<x>_Voeg <x> toe aan invoegpad
+**1k<x>_Geef <x> door aan de linker
+**1l_Druk logo af
+**1n_Standaard configuratie bestand niet lezen
+**1o<x>_Stel de naam van het applicatiebestand in op <x>
+**1pg_genereer profile code voor gprof
+*L1P_Gebruik pipes in plaats van tijdelijke assembler bestanden
+**1S_Syntaxisinstellingen
+**2S2_Schakel Delphi-2-uitbreidingen in
+**2Sc_Ondersteun operatoren als in C (*=,+=,/= en -=)
+**2sa_Voeg assertion code toe
+**2S2_Tracht Delphi compatibel te zijn
+**2Se<x>_Compiler stopt na <x> fouten (standaard 1)
+**2Sg_Laat LABEL en GOTO toe
+**2Sh_Gebruik ansistrings
+**2Si_Ondersteun INLINE
+**2Sm_Ondersteun macros zoals in C (globaal)
+**2So_Probeer TP/BP-7.0-compatibel te zijn
+**2Sp_Probeer GNU-Pascal-compatibel te zijn
+**2Ss_Constructor naam moet init zijn (destructor moet done zijn)
+**1s_Roep assembler en linker niet op (slechts met -a)
+**1sh_Genereer een script om op het hostplatform te linken
+**1sr_Voer geen registertoewijzing uit (optimalisaties worden uitgeschakeld)
+**1st_Genereer een script om op het doelplatform te linken
+**1u<x>_Verwijdert symbooldefinitie <x>
+**1U_unit opties
+**2Un_Unit naam niet nagaan
+**2Us_Compileer een systeemunit
+**1v<x>_Wees uitvoerig. <x> is een combinatie van volgende letters:
+**2*_e : Toon fouten (standaard) d : Toon debug informatie
+**2*_w : Toon waarschuwingen u : Toon gebruikte bestanden
+**2*_n : Toon notas t : Toon geteste bestanden
+**2*_h : Toon hints m : Toon gedefinieerde macros
+**2*_i : Toon algemene informatie p : Toon gecompileerde routines
+**2*_l : Toon regelnummers c : Toon voorwaardelijken
+**2*_a : Toon alles 0 : Toon alleen fouten
+**2*_b : Toon alle procedures r : Rhide-/GCC-compatibiliteitsmodus
+**2*_ declaraties indien een x : Executable informatie (alleen Win32)
+**2*_ fout optreedt
+**1X_applicatie instellingen
+*L2Xc_link met de C bibliotheek
+**2Xs_verwijder alle symbolen uit applicatie
+**2XD_link met dynamische bibliotheken (definieert FPC_LINK_DYNAMIC)
+**2XS_link met statische bibliotheken (definieert FPC_LINK_STATIC)
+**2XS_link slim (definieert FPC_LINK_STATIC_SMART)
+**0*_Processor specifieke instellingen:
+3*1A_Output formaat
+3*2Aas_assembleer met GNU AS
+3*2Aasaout_assembleer met GNU AS voor aout (Go32v1)
+3*2Anasmcoff_Coff (Go32v2) bestand met Nasm
+3*2Anasmelf_elf32 (linux) bestand met Nasm
+3*2Anasmobj_obj bestand met Nasm
+3*2Amasm_obj bestand met Masm (Microsoft)
+3*2Atasm_obj bestand met Tasm (Borland)
+3*2Acoff_coff (Go32v2) met interne assembler
+3*2Apecoff_pecoff (Win32) met interne assembler
+3*1R<x>_Geef de grammatica voor de assemblerlezer op:
+3*2Ratt_Lees assembler in AT&T-stijl
+3*2Rintel_Lees assembler in Intelstijl
+3*2Rdirect_Kopieer assemblercode rechtstreeks naar assemblerbestand
+**1O<x>_optimalisaties
+**2O1_Niveau 1 optimalisaties (snel en debug-vriendelijk )
+**2O2_Niveau 2 optimalisaties (-O1 + snelle optimalisaties)
+**2O3_Niveau 3 optimalisaties (-O2 + trage optimalisaties)
+**2Oa<x>=<y>_Stel alignering in
+**2Oo[NO]<x>_Schakel optimalisatie x aan of uit, zie fpc -i voor mogelijke waarden
+**2Op<x>_Stel doel-cpu in voor optimalisaties, zie fpc -i voor mogelijke waarden
+**2Os_Genereer kleinere code
+6*1T<x>_Doel besturingssysteem:
+3*2TGO32V2_versie 2 of DJ Delorie DOS-extender
+3*2TLINUX_Linux
+3*2TOS2_OS/2 / eComStation
+3*2TWIN32_Windows 32-bit
+3*1W<x>_Opties voor het Win32-doelplatform
+3*2WB<x>_Stel Image base in op (hexadecimale) waarde <x>
+3*2WC_Maak een console applicatie
+3*2WD_Gebruik DEFFILE om functies van bibliotheek of applicatie te exporteren
+3*2WG_Maak een grafische applicatie
+3*2WN_Genereer geen relocatiecode (nodig voor debuggen)
+3*2WR_Genereer relocatiecode
+6*1A_output formaat
+6*2Aas_Unix o-bestand met GNU AS
+6*2Agas_GNU Motorola-assembler
+6*2Amit_MIT Syntax (oude GAS)
+6*2Amot_Standaard Motorola-assembler
+6*1O_optimalisaties
+6*2Oa_Gebruik de optimalisaties
+6*2Og_Genereer kleinere code
+6*2OG_Genereer snellere code (standaard)
+6*2Ox_Optimizeer maximaal (nog steeds BUGGY!!!)
+6*2O2_Stel doelprocessor in op MC68020+
+6*1R<x>_assembler reading style:
+6*2RMOT_read motorola style assembler
+6*1T<x>_Target operating system:
+6*2TAMIGA_Commodore Amiga
+6*2TATARI_Atari ST/STe/TT
+6*2TMACOS_Macintosh m68k
+6*2TLINUX_Linux-68k
+**1*_
+**1?_Toont deze hulp
+**1h_Toont deze hulp zonder wachten
+]
diff --git a/closures/compiler/msg/errorpl.msg b/closures/compiler/msg/errorpl.msg
new file mode 100644
index 0000000000..0cec618f6a
--- /dev/null
+++ b/closures/compiler/msg/errorpl.msg
@@ -0,0 +1,2385 @@
+#
+# This file is part of the Free Pascal Compiler
+# Copyright (c) 1999-2000 by the Free Pascal Development team
+#
+# Polish (CP 852) Language File for Free Pascal
+#
+# See the file COPYING.FPC, included in this distribution,
+# for details about the copyright.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#
+#
+# The constants are build in the following order:
+# <part>_<type>_<txtidentifier>
+#
+# <part> is the part of the compiler the message is used
+# asmr_ assembler parsing
+# asmw_ assembler writing/binary writers
+
+# unit_ unit handling
+# scan_ scanner
+# parser_ parser
+# type_ type checking
+# general_ general info
+# exec_ calls to assembler, linker, binder
+#
+# <type> the type of the message it should normally used for
+# f_ fatal error
+# e_ error
+# w_ warning
+# n_ note
+# h_ hint
+# i_ info
+# l_ linenumber
+# u_ used
+# t_ tried
+# c_ conditional
+# d_ debug message
+# x_ executable informations
+#
+
+#
+# General
+#
+# 01016 is the last used one
+#
+# BeginOfTeX
+% \section{General compiler messages}
+% This section gives the compiler messages which are not fatal, but which
+% display useful information. The number of such messages can be
+% controlled with the various verbosity level \var{-v} switches.
+% \begin{description}
+general_t_compilername=01000_T_Kompilator: $1
+% When the \var{-vt} switch is used, this line tells you what compiler
+% is used.
+general_d_sourceos=01001_D_OS kompilatora: $1
+% When the \var{-vd} switch is used, this line tells you what the source
+% operating system is.
+general_i_targetos=01002_I_Docelowy OS: $1
+% When the \var{-vd} switch is used, this line tells you what the target
+% operating system is.
+general_t_exepath=01003_T_—cie¾ka narz©dzi: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for its binaries.
+general_t_unitpath=01004_T_—cie¾ka moduˆ¢w: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for compiled units. You can set this path with the \var{-Fu}
+general_t_includepath=01005_T_—cie¾ka include'¢w: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for its include files (files used in \var{\{\$I xxx\}} statements).
+% You can set this path with the \var{-I} option.
+general_t_librarypath=01006_T_—cie¾ka bibliotek: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for the libraries. You can set this path with the \var{-Fl} option.
+general_t_objectpath=01007_T_—cie¾ka obiekt¢w: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for object files you link in (files used in \var{\{\$L xxx\}} statements).
+% You can set this path with the \var{-Fo} option.
+general_i_abslines_compiled=01008_I_$1 linii skompilowanych w $2 sek
+% When the \var{-vi} switch is used, the compiler reports the number
+% of lines compiled, and the time it took to compile them (real time,
+% not program time).
+general_f_no_memory_left=01009_F_Brak pami©ci
+% The compiler doesn't have enough memory to compile your program. There are
+% several remedies for this:
+% \begin{itemize}
+% \item If you're using the build option of the compiler, try compiling the
+% different units manually.
+% \item If you're compiling a huge program, split it up in units, and compile
+% these separately.
+% \item If the previous two don't work, recompile the compiler with a bigger
+% heap (you can use the \var{-Ch} option for this, \seeo{Ch})
+% \end{itemize}
+general_i_writingresourcefile=01010_I_Zapisywanie pliku zasob¢w: $1
+% This message is shown when the compiler writes the Resource String Table
+% file containing all the resource strings for a program.
+general_e_errorwritingresourcefile=01011_E_Bˆ¥d podczas zapisywania pliku zasob¢w: $1
+% This message is shown when the compiler encountered an error when writing
+% the Resource String Table file
+general_i_fatal=01012_I_Bˆ¥d krytyczny:
+% Prefix for Fatal Errors
+general_i_error=01013_I_Bˆ¥d:
+% Prefix for Errors
+general_i_warning=01014_I_Ostrze¾enie:
+% Prefix for Warnings
+general_i_note=01015_I_Nota:
+% Prefix for Notes
+general_i_hint=01016_I_Podpowied«:
+% Prefix for Hints
+general_e_path_does_not_exist=01017_E_—cie¾ka "$1" nie istnieje
+% The specified path does not exist.
+general_e_compilation_aborted=01018_E_Kompilacja zatrzymana
+% \end{description}
+#
+# Scanner
+#
+# 02063 is the last used one
+#
+% \section{Scanner messages.}
+% This section lists the messages that the scanner emits. The scanner takes
+% care of the lexical structure of the pascal file, i.e. it tries to find
+% reserved words, strings, etc. It also takes care of directives and
+% conditional compiling handling.
+% \begin{description}
+scan_f_end_of_file=02000_F_Nieoczekiwany koniec pliku
+% this typically happens in one of the following cases :
+% \begin{itemize}
+% \item The source file ends before the final \var{end.} statement. This
+% happens mostly when the \var{begin} and \var{end} statements aren't
+% balanced;
+% \item An include file ends in the middle of a statement.
+% \item A comment wasn't closed.
+% \end{itemize}
+scan_f_string_exceeds_line=02001_F_String przekracza jedn¥ lini©
+% You forgot probably to include the closing ' in a string, so it occupies
+% multiple lines.
+scan_f_illegal_char=02002_F_Nieprawidˆowy znak $1 ($2)
+% An illegal character was encountered in the input file.
+scan_f_syn_expected=02003_F_Bˆ¥d skˆadni, oczekiwano $1 ale napotkano $2
+% This indicates that the compiler expected a different token than
+% the one you typed. It can occur almost everywhere where you make a
+% mistake against the pascal language.
+scan_t_start_include_file=02004_T_Rozpocz©cie czytania pliku include $1
+% When you provide the \var{-vt} switch, the compiler tells you
+% when it starts reading an included file.
+scan_w_comment_level=02005_W_Znaleziono komentarz $1 stopnia
+% When the \var{-vw} switch is used, then the compiler warns you if
+% it finds nested comments. Nested comments are not allowed in Turbo Pascal
+% and can be a possible source of errors.
+scan_n_ignored_switch=02008_N_Zignorowany przeˆ¥cznik kompilatora $1
+% With \var{-vn} on, the compiler warns if it ignores a switch
+scan_w_illegal_switch=02009_W_Nieprawidˆowy przeˆ¥cznik kompilatora $1
+% You included a compiler switch (i.e. \var{\{\$... \}}) which the compiler
+% doesn't know.
+scan_w_switch_is_global=02010_W_Przeˆ¥cznik globalny w nieprawidˆowym miejscu
+% The compiler switch is misplaced, and should be located at
+% the start of the unit or program.
+scan_e_illegal_char_const=02011_E_Nieprawidˆowa staˆa znakowa
+% This happens when you specify a character with its ASCII code, as in
+% \var{\#96}, but the number is either illegal, or out of range.
+scan_f_cannot_open_input=02012_F_Nie mo¾na otworzy† pliku $1
+% \fpc cannot find the program or unit source file you specified on the
+% command line.
+scan_f_cannot_open_includefile=02013_F_Nie mo¾na otworzy† pliku include $1
+% \fpc cannot find the source file you specified in a \var{\{\$include ..\}}
+% statement.
+scan_w_only_pack_records=02015_W_Pola rekord¢w mog¥ by† wyr¢wnane tylko do 1,2,4,8,16 lub 32 bajt¢w
+% You are specifying the \var{\{\$PACKRECORDS n\} } or \var{\{\$ALIGN n\} }
+% with an illegal value for \var{n}. For $PACKRECORDS valid alignments are 1, 2, 4, 8, 16, 32, C,
+% NORMAL, DEFAULT, and for $ALIGN valid alignment are 1, 2, 4, 8, 16, 32, ON,
+% OFF. Under mode MacPas $ALIGN also supports MAC68K, POWER and RESET.
+scan_w_only_pack_enum=02016_W_Wyliczenia mog¥ by† zapisane tylko na 1, 2 lub 4 bajtach
+% You are specifying the \var{\{\$PACKENUM n\}} with an illegal value for
+% \var{n}. Only 1,2 or 4 are valid in this case.
+scan_e_endif_expected=02017_E_Oczekiwano $ENDIF dla $1 $2 zdefiniowanych w linii $3
+% Your conditional compilation statements are unbalanced.
+scan_e_preproc_syntax_error=02018_E_Bˆ¥d skˆadni podczas parsowania dyrektyw kompilacji warunkowej
+% There is an error in the expression following the \var{\{\$if ..\}} compiler
+% directive.
+scan_e_error_in_preproc_expr=02019_E_Bˆ¥d obliczania wyra¾enia kompilacji warunkowej
+% There is an error in the expression following the \var{\{\$if ..\}} compiler
+% directive.
+scan_w_macro_cut_after_255_chars=02020_W_Tre˜† makra zostaˆa obci©ta po 255 znaku
+% The contents of macros canno be longer than 255 characters.
+scan_e_endif_without_if=02021_E_ENDIF bez IF(N)DEF
+% Your \var{\{\$IFDEF ..\}} and {\{\$ENDIF\}} statements aren't balanced.
+scan_f_user_defined=02022_F_Zdefiniowany przez u¾ytkownika: $1
+% A user defined fatal error occurred. see also the \progref
+scan_e_user_defined=02023_E_Zdefiniowany przez u¾ytkownika: $1
+% A user defined error occurred. see also the \progref
+scan_w_user_defined=02024_W_Zdefiniowane przez u¾ytkownika: $1
+% A user defined warning occurred. see also the \progref
+scan_n_user_defined=02025_N_Zdefiniowana przez u¾ytkownika: $1
+% A user defined note was encountered. see also the \progref
+scan_h_user_defined=02026_H_Zdefiniowana przez u¾ytkownika: $1
+% A user defined hint was encountered. see also the \progref
+scan_i_user_defined=02027_I_Zdefiniowana przez u¾ytkownika: $1
+% User defined information was encountered. see also the \progref
+scan_e_keyword_cant_be_a_macro=02028_E_Sˆowo kluczowe nie mo¾e zosta† przedefiniowane przez makro
+% You cannot redefine keywords with macros.
+scan_f_macro_buffer_overflow=02029_F_Przepeˆnienie bufora podczas czytania lub rozwijania makra
+% Your macro or its result was too long for the compiler.
+scan_e_macro_deep_ten=02030_E_Rozwijanie makra przerwane po 16 rozwini©ciach.
+% When expanding a macro macros have been nested to a level of 16.
+% The compiler will expand no further, since this may be a sign that
+% recursion is used.
+scan_e_wrong_styled_switch=02031_E_Przeˆ¥czniki kompilatora nie s¥ dozwolone w komentarzach typu (* ... *)
+% Compiler switches should always be between \var{\{ \}} comment delimiters.
+scan_d_handling_switch=02032_D_Obsˆugiwanie przeˆ¥cznika "$1"
+% When you set debugging info on (\var{-vd}) the compiler tells you when it
+% is evaluating conditional compile statements.
+scan_c_endif_found=02033_C_Znaleziono ENDIF $1
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifdef_found=02034_C_Znaleziono IFDEF $1 , $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifopt_found=02035_C_Znalezino IFOPT $1 , $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_if_found=02036_C_Znaleziono IF $1 , $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifndef_found=02037_C_Znaleziono IFNDEF $1 , $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_else_found=02038_C_Znaleziono ELSE $1 , $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_skipping_until=02039_C_Omijanie...
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements, and whether it is skipping or
+% compiling parts.
+scan_i_press_enter=02040_I_Naci˜nij <enter> aby kontynuowa†
+% When the \var{-vi} switch is used, the compiler stops compilation
+% and waits for the \var{Enter} key to be pressed when it encounters
+% a \var{\{\$STOP\}} directive.
+scan_w_unsupported_switch=02041_W_Nieobsˆugiwany przeˆ¥cznik $1
+% When warnings are turned on (\var{-vw}) the compiler warns you about
+% unsupported switches. This means that the switch is used in Delphi or
+% Turbo Pascal, but not in \fpc
+scan_w_illegal_directive=02042_W_Nieprawidˆowa dyrektywa $1
+% When warings are turned on (\var{-vw}) the compiler warns you about
+% unrecognised switches. For a list of recognised switches, \progref
+scan_t_back_in=02043_TL_Z powrotem w $1
+% When you use (\var{-vt}) the compiler tells you when it has finished
+% reading an include file.
+scan_w_unsupported_app_type=02044_W_Nieprawidˆowy typ aplikacji: $1
+% You get this warning, if you specify an unknown application type
+% with the directive \var{\{\$APPTYPE\}}
+scan_w_app_type_not_support=02045_W_Typ aplikacji nieobsˆugiwany przez docelowy OS
+% The \var{\{\$APPTYPE\}} directive is supported by win32 applications only.
+scan_w_description_not_support=02046_W_Dyrektywa DESCRIPTION jest obsˆugiwany tylko przez OS2 i Win32
+% The \var{\{\$DESCRIPTION\}} directive is only supported for OS2 and Win32 targets.
+scan_n_version_not_support=02047_N_Dyrektywa VERSION nie jest obsˆugiwana przez OS
+% The \var{\{\$VERSION\}} directive is only supported by win32 target.
+scan_n_only_exe_version=02048_N_Dyrektywa VERSION jest dost©na tylko dla program¢w i DLLi
+% The \var{\{\$VERSION\}} directive is only used for executable or DLL sources.
+scan_w_wrong_version_ignored=02049_W_Nieprawidˆowy format dyrektywy VERSION $1
+% The \var{\{\$VERSION\}} directive format is majorversion.minorversion
+% where majorversion and minorversion are words.
+scan_w_unsupported_asmmode_specifier=02050_W_Nieprawidˆowy styl asemblera $1
+% When you specify an assembler mode with the \var{\{\$ASMMODE xxx\}}
+% the compiler didn't recognize the mode you specified.
+scan_w_no_asm_reader_switch_inside_asm=02051_W_Przeˆ¥cznik stylu asemblera niedozwolony w bloku asemblera, $1 b©dzie dziaˆa† dopiero w nast©pnym bloku
+% It is not possible to switch from one assembler reader to another
+% inside an assmebler block. The new reader will be used for next
+% assembler statement only.
+scan_e_wrong_switch_toggle=02052_E_Zˆa warto˜† przeˆ¥cznika, u¾yj ON/OFF lub +/-
+% You need to use ON or OFF or a + or - to toggle the switch
+scan_e_resourcefiles_not_supported=02053_E_Pliki zasob¢w nie s¥ obsˆugiwane przez OS
+% The target you are compiling for doesn't support resource files.
+scan_w_include_env_not_found=02054_W_Zmienna ˜rodowiskowa $1 nie odnaleziona
+% The included environment variable can't be found in the environment, it'll
+% be replaced by an empty string instead.
+scan_e_invalid_maxfpureg_value=02055_E_Nieprawidˆowa warto˜† limitu rejestru FPU
+% Valid values for this directive are 0..8 and NORMAL/DEFAULT
+scan_w_only_one_resourcefile_supported=02056_W_Tylko jeden plik zasob¢w jest obsˆugiwany przez docelowy OS
+% The target you are compiling for supports only one resource file.
+% The first resource file found is used, the others are discarded.
+scan_w_macro_support_turned_off=02057_W_Obsˆuga makr jest wyˆ¥czona
+% A macro declaration has been found, but macro support is currently off,
+% so the declaration will be ignored. To turn macro support on compile with
+% -Sm on the commandline or add {$MACRO ON} in the source
+scan_e_invalid_interface_type=02058_E_Nieprawidˆowy typ interfejsu. Prawidˆowe s¥ COM, CORBA i DEFAULT.
+% The interface type that was specified is not supported
+scan_w_appid_not_support=02060_W_APPNAME jest obsˆugiwane tylko przez PalmOS
+% The \var{\{\$APPID\}} directive is only supported for the PalmOS target.
+scan_w_appname_not_support=02061_W_Dyrektywa APPNAME jest obsˆugiwana tylko przez PalmOS
+% The \var{\{\$APPNAME\}} directive is only supported for the PalmOS target.
+scan_e_string_exceeds_255_chars=02061_E_Staˆe ˆaäcuchowe nie mog¥ by† dˆu¾sze ni¾ 255 znak¢w
+% A single string constant can contain at most 255 chars. Try splitting up the
+% string in multiple smaller parts and concatenate them with a + operator.
+scan_f_include_deep_ten=02062_F_Przekroczono maksymaln¥ ilo˜† zagnie¾d¾onych include (16)
+% When including include files the files have been nested to a level of 16.
+% The compiler will expand no further, since this may be a sign that
+% recursion is used.
+scan_e_too_many_push=02063_F_Zbyt du¾o poziom¢w PUSH
+% A maximum of 20 levels is allowed. This error occurs only in mode MacPas.
+scan_e_too_many_pop=02064_E_Napotkano POP bez poprzedzaj¥cego go PUSH
+% This error occurs only in mode MacPas.
+scan_e_error_macro_lacks_value=02065_E_Makro lub zmienna "$1" nie ma przypisanej warto˜ci
+% Thus the conditional compile time expression cannot be evaluated.
+scan_e_wrong_switch_toggle_default=02066_E_Nieprawidˆowy przeˆ¥cznik, u¾yj ON/OFF/DEFAULT lub +/-/*
+% You need to use ON or OFF or DEFAULT or a + or - or * to toggle the switch
+scan_e_mode_switch_not_allowed=02067_E_Przeˆ¥cznik trybu "$1" jest niedozwolony w tym miejscu
+% A mode switch has already been encountered, or, in case of option -Mmacpas,
+% a mode switch occur after UNIT.
+scan_e_error_macro_undefined=02068_E_Zmienna "$1" jest niezdefiniowana
+% Thus the conditional compile time expression cannot be evaluated.
+scan_e_utf8_bigger_than_65535=02069_E_Napotkano kod UTF-8 wi©kszy od 65535
+% \fpc handles utf-8 strings internally as widestrings e.g. the char codes are limited to 65535
+scan_e_utf8_malformed=02070_E_Znieksztaˆcony string UTF-8
+% The given string isn't a valid UTF-8 string
+scan_c_switching_to_utf8=02071_C_Napotkano sygnatur© UTF-8, u¾ycie kodowania UTF-8
+% The compiler found an UTF-8 encoding signature ($ef, $bb, $bf) at the beginning of a file,
+% so it interprets it as an UTF-8 file
+% \end{description}
+#
+# Parser
+#
+# 03192 is the last used one
+#
+% \section{Parser messages}
+% This section lists all parser messages. The parser takes care of the
+% semantics of you language, i.e. it determines if your pascal constructs
+% are correct.
+% \begin{description}
+parser_e_syntax_error=03000_E_Parser - Bˆ¥d skˆadni
+% An error against the Turbo Pascal language was encountered. This happens
+% typically when an illegal character is found in the sources file.
+parser_e_dont_nest_interrupt=03004_E_Procedura typu INTERRUPT nie mo¾e by† zagnie¾d¾ona
+% An \var{INTERRUPT} procedure must be global.
+parser_w_proc_directive_ignored=03005_W_Dyrektywa $1 zignorowana
+% The specified is ignored by FPC programs.
+parser_e_no_overload_for_all_procs=03006_E_Nie wszystkie deklaracje $1 s¥ przeci¥¾one
+% When you want to use overloading using the \var{OVERLOAD} directive, then
+% all declarations need to have \var{OVERLOAD} specified.
+parser_e_export_name_double=03008_E_Zduplikowana nazwa eksportu $1
+% Exported function names inside a specific DLL must all be different
+parser_e_export_ordinal_double=03009_E_Zduplikowany indeks eksportowanej funkcji $1
+% Exported function names inside a specific DLL must all be different
+parser_e_export_invalid_index=03010_E_Nieprawidˆowa warto˜† indeksu funkcji
+% DLL function index must be in the range \var{1..\$FFFF}
+parser_w_parser_reloc_no_debug=03011_W_Informacje debugera w DLLu lub programie $1 nie dziaˆaj¥, wyˆ¥czone.
+parser_w_parser_win32_debug_needs_WN=03012_W_Aby m¢c debugowa† kod win32 musisz wyˆ¥czy† generowanie kodu relokacji przeˆ¥cznikiem -WN
+% Stabs info is wrong for relocatable DLL or EXES use -WN
+% if you want to debug win32 executables.
+parser_e_constructorname_must_be_init=03013_E_Konstruktor musi nazywa† si© INIT
+% You are declaring a constructor with a name which isn't \var{init}, and the
+% \var{-Ss} switch is in effect. See the \var{-Ss} switch (\seeo{Ss}).
+parser_e_destructorname_must_be_done=03014_E_Destruktor musi nazywa† si© DONE
+% You are declaring an object destructor with a name which is not \var{done}, and the
+% \var{-Ss} switch is in effect. See the \var{-Ss} switch (\seeo{Ss}).
+parser_e_proc_inline_not_supported=03016_E_Typ INLINE nieobsˆugiwany (u¾yj opcji -Si)
+% You tried to compile a program with C++ style inlining, and forgot to
+% specify the \var{-Si} option (\seeo{Si}). The compiler doesn't support C++
+% styled inlining by default.
+parser_w_constructor_should_be_public=03018_W_Konstruktor powinien by† publiczny
+% Constructors must be in the 'public' part of an object (class) declaration.
+parser_w_destructor_should_be_public=03019_W_Destruktor powinien by† publiczny
+% Destructors must be in the 'public' part of an object (class) declaration.
+parser_n_only_one_destructor=03020_N_Klasa powinna mie† tylko jeden destruktor
+% You can declare only one destructor for a class.
+parser_e_no_local_objects=03021_E_Definicje lokalne w klasie s¥ niedozwolone
+% Classes must be defined globally. They cannot be defined inside a
+% procedure or function
+parser_f_no_anonym_objects=03022_F_Definicje anonimowych klas s¥ niedozwolone
+% An invalid object (class) declaration was encountered, i.e. an
+% object or class without methods that isn't derived from another object or
+% class. For example:
+% \begin{verbatim}
+% Type o = object
+% a : longint;
+% end;
+% \end{verbatim}
+% will trigger this error.
+parser_object_has_no_vmt=03023_E_Obiekt $1 nie posiada VMT
+% This is a note indicating that the declared object has no
+% virtual method table.
+parser_e_illegal_parameter_list=03024_E_Nieprawidˆowa lista parametr¢w
+% You are calling a function with parameters that are of a different type than
+% the declared parameters of the function.
+parser_e_wrong_parameter_size=03026_E_Nieprawidˆowa ilo˜† parametr¢w
+% There is an error in the parameter list of the function or procedure,
+% the number of parameters is not correct.
+parser_e_overloaded_no_procedure=03027_E_Przeci¥¾ony identyfikator $1 nie jest funkcj¥
+% The compiler encountered a symbol with the same name as an overloaded
+% function, but it is not a function it can overload.
+parser_e_overloaded_have_same_parameters=03028_E_Przeci¥¾ona funkcja musi mie† chocia¾ jeden parametr wyr¢¾niaj¥cy
+% You're declaring overloaded functions, but with the same parameter list.
+% Overloaded function must have at least 1 different parameter in their
+% declaration.
+parser_e_header_dont_match_forward=03029_E_Nagˆ¢wek funkcji nie pasuje do deklaracji $1
+% You declared a function with same parameters but
+% different result type or function modifiers.
+parser_e_header_different_var_names=03030_E_Nagˆ¢wek funkcji $1 nie pasuje : nazwy parametr¢w zmienione $2 => $3
+% You declared the function in the \var{interface} part, or with the
+% \var{forward} directive, but define it with a different parameter list.
+parser_n_duplicate_enum=03031_N_Ci¥g warto˜ci typu wyliczeniowego musi by† rosn¥cy
+% \fpc allows enumeration constructions as in C. Given the following
+% declaration two declarations:
+% \begin{verbatim}
+% type a = (A_A,A_B,A_E:=6,A_UAS:=200);
+% type a = (A_A,A_B,A_E:=6,A_UAS:=4);
+% \end{verbatim}
+% The second declaration would produce an error. \var{A\_UAS} needs to have a
+% value higher than \var{A\_E}, i.e. at least 7.
+parser_e_no_with_for_variable_in_other_segments=03033_E_With nie mo¾e by† u¾yte ze zmiennymi w innym segmencie
+% With stores a variable locally on the stack,
+% but this is not possible if the variable belongs to another segment.
+parser_e_too_much_lexlevel=03034_E_Przekroczono limit zagnie¾d¾enia funkcji
+% You can nest function definitions only 31 times.
+parser_e_range_check_error=03035_E_Bˆ¥d zakresu podczas obliczania staˆej
+% The constants are out of their allowed range.
+parser_w_range_check_error=03036_W_Bˆ¥d zakresu podczas obliczania staˆej
+% The constants are out of their allowed range.
+parser_e_double_caselabel=03037_E_Zduplikowana etykieta w instrukcji case
+% You are specifying the same label 2 times in a \var{case} statement.
+parser_e_case_lower_less_than_upper_bound=03038_E_G¢rna granica zakresu jest mniejsza od dolnej
+% The upper bound of a \var{case} label is less than the lower bound and this
+% is useless
+parser_e_type_const_not_possible=03039_E_Staˆa typowana nie mo¾e by† klas¥ ani obiektem
+% You cannot declare a constant of type class or object.
+parser_e_no_overloaded_procvars=03040_E_Do zmiennych proceduralnych nie mo¾na przypisa† przeci¥¾onych funkcji
+% You are trying to assign an overloaded function to a procedural variable.
+% This isn't allowed.
+parser_e_invalid_string_size=03041_E_Dˆugo˜† stringa musi zawiera† si© mi©dzy 1 a 255
+% The length of a shortstring in Pascal is limited to 255 characters. You are
+% trying to declare a string with length lower than 1 or greater than 255
+parser_w_use_extended_syntax_for_objects=03042_W_U¾yj rozszerzonej skˆadni NEW i DISPOSE dla obiekt¢w
+% If you have a pointer \var{a} to a class type, then the statement
+% \var{new(a)} will not initialize the class (i.e. the constructor isn't
+% called), although space will be allocated. you should issue the
+% \var{new(a,init)} statement. This will allocate space, and call the
+% constructor of the class.
+parser_w_no_new_dispose_on_void_pointers=03043_W_U¾ycie NEW lub DISPOSE nie ma sensu dla nietypowanych wska«nik¢w
+parser_e_no_new_dispose_on_void_pointers=03044_E_U¾ycie NEW lub DISPOSE jest niemo¾liwe dla nietypowanych wska«nik¢w
+% You cannot use \var{new(p)} or \var{dispose(p)} if \var{p} is an untyped pointer
+% because no size is associated to an untyped pointer.
+% Accepted for compatibility in \var{tp} and \var{delphi} modes.
+parser_e_class_id_expected=03045_E_Oczekiwano identyfikatora klasy
+% This happens when the compiler scans a procedure declaration that contains
+% a dot,
+% i.e., a object or class method, but the type in front of the dot is not
+% a known type.
+parser_e_no_type_not_allowed_here=03046_E_Identyfikator typu jest niedozwolony w tym miejscu
+% You cannot use a type inside an expression.
+parser_e_methode_id_expected=03047_E_Oczekiwano identyfikatora metody
+% This identifier is not a method.
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., a object or class method, but the procedure name is not a
+% procedure of this type.
+parser_e_header_dont_match_any_member=03048_E_Nagˆ¢wek funkcji nie pasuje do ¾adnej metody tej klasy $1
+% This identifier is not a method.
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., a object or class method, but the procedure name is not a
+% procedure of this type.
+parser_d_procedure_start=03049_DL_Procedura/Funkcja $1
+% When using the \var{-vp} switch, the compiler tells you when it starts
+% processing a procedure or function implementation.
+parser_e_error_in_real=03050_E_Nieprawidˆowa warto˜† staˆej zmiennoprzecinkowej
+% The compiler expects a floating point expression, and gets something else.
+parser_e_fail_only_in_constructor=03051_E_FAIL mo¾e by† u¾yte tylko w konstruktorach
+% You are using the \var{FAIL} instruction outside a constructor method.
+parser_e_no_paras_for_destructor=03052_E_Destruktory nie mog¥ mie† parametr¢w
+% You are declaring a destructor with a parameter list. Destructor methods
+% cannot have parameters.
+parser_e_only_class_methods_via_class_ref=03053_E_Tylko metody klasy mog¥ by† wywoˆywane w ten spos¢b
+% This error occurs in a situation like the following:
+% \begin{verbatim}
+% Type :
+% Tclass = Class of Tobject;
+%
+% Var C : TClass;
+%
+% begin
+% ...
+% C.free
+% \end{verbatim}
+% \var{Free} is not a class method and hence cannot be called with a class
+% reference.
+parser_e_only_class_methods=03054_E_W metodach klasy mo¾esz u¾ywa† tylko metod klasy
+% This is related to the previous error. You cannot call a method of an object
+% from a inside a class method. The following code would produce this error:
+% \begin{verbatim}
+% class procedure tobject.x;
+%
+% begin
+% free
+% \end{verbatim}
+% Because free is a normal method of a class it cannot be called from a class
+% method.
+parser_e_case_mismatch=03055_E_Staˆa i zmienna u¾yta w CASE nie s¥ tego samego typu
+% One of the labels is not of the same type as the case variable.
+parser_e_illegal_symbol_exported=03056_E_Symbol nie mo¾e by† wyeksportowany
+% You can only export procedures and functions when you write a library. You
+% cannot export variables or constants.
+parser_w_should_use_override=03057_W_Dziedziczona metoda jest ukryta przez $1
+% A method that is declared \var{virtual} in a parent class, should be
+% overridden in the descendent class with the \var{override} directive. If you
+% don't specify the \var{override} directive, you will hide the parent method;
+% you will not override it.
+parser_e_nothing_to_be_overridden=03058_E_Nie ma takiej metody w dziedziczonej klasie: $1
+% You are trying to \var{override} a virtual method of a parent class that does
+% not exist.
+parser_e_no_procedure_to_access_property=03059_E_Brak metody do odczytania wˆasno˜ci
+% You specified no \var{read} directive for a property.
+parser_w_stored_not_implemented=03060_W_Dyrektywa stored nie jest jeszcze zaimplementowana
+% The \var{stored} directive is not yet implemented
+parser_e_ill_property_access_sym=03061_E_Nieprawidˆowy symbol dla dost©pu do wˆasno˜ci
+% There is an error in the \var{read} or \var{write} directives for an array
+% property. When you declare an array property, you can only access it with
+% procedures and functions. The following code woud cause such an error.
+% \begin{verbatim}
+% tmyobject = class
+% i : integer;
+% property x [i : integer]: integer read I write i;
+% \end{verbatim}
+%
+parser_e_cant_access_protected_member=03062_E_Nie mo¾na si© odwoˆywa† do pola protected obiektu w tym miejscu
+% Fields that are declared in a \var{protected} section of an object or class
+% declaration cannot be accessed outside the module wher the object is
+% defined, or outside descendent object methods.
+parser_e_cant_access_private_member=03063_E_Nie mo¾na si© odwoˆywa† do pola private obiektu w tym miejscu
+% Fields that are declared in a \var{private} section of an object or class
+% declaration cannot be accessed outside the module where the class is
+% defined.
+parser_e_overridden_methods_not_same_ret=03066_E_Przeci¥¾one metody wirtualne powinny mie† taki sam typ zwracanych warto˜ci: "$2" jest przeci¥¾one przez "$" o innym zwracanym typie
+% If you declare overridden methods in a class definition, they must
+% have the same return type.
+parser_e_dont_nest_export=03067_E_Eksportowane funkcje nie mog¥ by† zagnie¾d¾one
+% You cannot declare a function or procedure within a function or procedure
+% that was declared as an export procedure.
+parser_e_methods_dont_be_export=03068_E_Metody nie mog¥ by† eksportowane
+% You cannot declare a procedure that is a method for an object as
+% \var{export}ed. That is, your methods cannot be called from a C program.
+parser_e_call_by_ref_without_typeconv=03069_E_Przy przekazywaniu przez referencj© parametry musz¥ by† tego samego typu: Otrzymano $1, a oczekiwano $2
+% When calling a function declared with \var{var} parameters, the variables in
+% the function call must be of exactly the same type. There is no automatic
+% type conversion.
+parser_e_no_super_class=03070_E_Ta klasa nie jest przodkiem bie¾¥cej klasy
+% When calling inherited methods, you are trying to call a method of a strange
+% class. You can only call an inherited method of a parent class.
+parser_e_self_not_in_method=03071_E_SELF jest dost©pne tylko w metodach
+% You are trying to use the \var{self} parameter outside an object's method.
+% Only methods get passed the \var{self} parameters.
+parser_e_generic_methods_only_in_methods=03072_E_Metody mog¥ by† wywoˆane bezpo˜rednio identyfikatorem typu klasy tylko w innych metodach
+% A construction like \var{sometype.somemethod} is only allowed in a method.
+parser_e_illegal_colon_qualifier=03073_E_Nieprawidˆowe u¾ycie ':'
+% You are using the format \var{:} (colon) 2 times on an expression that
+% is not a real expression.
+parser_e_illegal_set_expr=03074_E_Bˆ¥d zakresu lub zduplikowany element w deklaracji zbioru
+% The declaration of a set contains an error. Either one of the elements is
+% outside the range of the set type, either two of the elements are in fact
+% the same.
+parser_e_pointer_to_class_expected=03075_E_Oczekiwano wska«nika do obiektu
+% You specified an illegal type in a \var{New} statement.
+% The extended syntax of \var{new} needs an object as a parameter.
+parser_e_expr_have_to_be_constructor_call=03076_E_Wyra¾enie musi by† wywoˆaniem konstruktora
+% When using the extended syntax of \var{new}, you must specify the constructor
+% method of the object you are trying to create. The procedure you specified
+% is not a constructor.
+parser_e_expr_have_to_be_destructor_call=03077_E_Wyra¾enie musi by† wywoˆaniem destruktora
+% When using the extended syntax of \var{dispose}, you must specify the
+% destructor method of the object you are trying to dispose of.
+% The procedure you specified is not a destructor.
+parser_e_invalid_record_const=03078_E_Nieprawidˆowa kolejno˜† element¢w rekordu
+% When declaring a constant record, you specified the fields in the wrong
+% order.
+parser_e_false_with_expr=03079_E_Wyra¾enie musi by† rekordem lub klas¥
+% A \var{with} statement needs an argument that is of the type \var{record}
+% or \var{class}. You are using \var{with} on an expression that is not of
+% this type.
+parser_e_void_function=03080_E_Procedury nie mog¥ zwraca† warto˜ci
+% In \fpc, you can specify a return value for a function when using
+% the \var{exit} statement. This error occurs when you try to do this with a
+% procedure. Procedures cannot return a value.
+parser_e_only_methods_allowed=03081_E_Konstruktory, destruktory i class operators musz¥ by† metodami
+% You're declaring a procedure as destructor, constructor or class operator, when the
+% procedure isn't a class method.
+parser_e_operator_not_overloaded=03082_E_Operator nie jest przeci¥¾ony
+% You're trying to use an overloaded operator when it isn't overloaded for
+% this type.
+parser_e_no_such_assignment=03083_E_Nie mo¾a przeci¥¾y† przypisania dla takich samych typ¢w
+% You can not overload assignment for types
+% that the compiler considers as equal.
+parser_e_overload_impossible=03084_E_Niemo¾liwe przeci¥¾enie operatora
+% The combination of operator, arguments and return type are
+% incompatible.
+parser_e_no_reraise_possible=03085_E_Ponowne wywoˆanie wyj¥tku niemo¾liwe w tym miejscu
+% You are trying to raise an exception where it isn't allowed. You can only
+% raise exceptions in an \var{except} block.
+parser_e_no_new_or_dispose_for_classes=03086_E_Rozszerzona skˆadnia new i dispose jest niedozwolona dla klas
+% You cannot generate an instance of a class with the extended syntax of
+% \var{new}. The constructor must be used for that. For the same reason, you
+% cannot call \var{Dispose} to de-allocate an instance of a class, the
+% destructor must be used for that.
+parser_e_procedure_overloading_is_off=03088_E_Przeci¥¾anie procedur jest wyˆ¥czone
+% When using the \var{-So} switch, procedure overloading is switched off.
+% Turbo Pascal does not support function overloading.
+parser_e_overload_operator_failed=03089_E_Przeci¥¾enie tego operatora jest niemo¾liwe
+% You are trying to overload an operator which cannot be overloaded.
+% The following operators can be overloaded :
+% \begin{verbatim}
+% +, -, *, /, =, >, <, <=, >=, is, as, in, **, :=
+% \end{verbatim}
+parser_e_comparative_operator_return_boolean=03090_E_Operator por¢wnania musi zwraca† warto˜† typu Boolean
+% When overloading the \var{=} operator, the function must return a boolean
+% value.
+parser_e_only_virtual_methods_abstract=03091_E_Tylko metody wirtualne mog¥ by† abstrakcyjne
+% You are declaring a method as abstract, when it isn't declared to be
+% virtual.
+parser_f_unsupported_feature=03092_F_U¾ycie nieobsˆugiwanej funkcji kompilatora!
+% You're trying to force the compiler into doing something it cannot do yet.
+parser_e_mix_of_classes_and_objects=03093_E_Mieszanie r¢¾nych typ¢w obiekt¢w (obiekt¢w, klas, interfejs¢w) jest niedozwolone
+% You cannot derive \var{objects}, \var{classes}, \var{cppclasses} and \var{interfaces} interttwined . E.g.
+% a class cannot have an object as parent and vice versa.
+parser_w_unknown_proc_directive_ignored=03094_W_Nieznana dyrektywa procedury zostaˆa zignorowana: $1
+% The procedure directive you specified is unknown.
+parser_e_absolute_only_one_var=03095_E_Absolute mo¾e by† powi¥zane tylko z jedn¥ zmienn¥
+% You cannot specify more than one variable before the \var{absolute} directive.
+% Thus, the following construct will provide this error:
+% \begin{verbatim}
+% Var Z : Longint;
+% X,Y : Longint absolute Z;
+% \end{verbatim}
+% \item [ absolute can only be associated a var or const ]
+% The address of a \var{absolute} directive can only point to a variable or a
+% typed constant. Therefore, the following code will produce this error:
+% \begin{verbatim}
+% Procedure X;
+%
+% var p : longint absolute x;
+% \end{verbatim}
+%
+parser_e_absolute_only_to_var_or_const=03096_E_Absolute mo¾e by† u¾yte tylko w stosunku do zmiennej lub staˆej
+% The address of a \var{absolute} directive can only point to a variable or
+% constant. Therefore, the following code will produce this error:
+% \begin{verbatim}
+% Procedure X;
+%
+% var p : longint absolute x;
+% \end{verbatim}
+%
+parser_e_initialized_only_one_var=03097_E_Tylko jedna zmienna mo¾e by† zainicjowana
+% You cannot specify more than one variable with a initial value
+% in Delphi mode.
+parser_e_abstract_no_definition=03098_E_Metody abstrakcyjne nie mog¥ by† zaimplementowane
+% Abstract methods can only be declared, you cannot implement them. They
+% should be overridden by a descendant class.
+parser_e_overloaded_must_be_all_global=03099_E_Ta przeci¥¾ona funkcja nie mo¾e by† lokalna (musi by† wyeksportowana)
+% You are defining a overloaded function in the implementation part of a unit,
+% but there is no corresponding declaration in the interface part of the unit.
+parser_w_virtual_without_constructor=03100_W_Metody wirtualne u¾yte bez konstruktora $1
+% If you declare objects or classes that contain virtual methods, you need
+% to have a constructor and destructor to initialize them. The compiler
+% encountered an object or class with virtual methods that doesn't have
+% a constructor/destructor pair.
+parser_c_macro_defined=03101_CL_Makro zdefiniowane: $1
+% When \var{-vm} is used, the compiler tells you when it defines macros.
+parser_c_macro_undefined=03102_CL_Makro wymazane: $1
+% When \var{-vm} is used, the compiler tells you when it undefines macros.
+parser_c_macro_set_to=03103_CL_Makro $1 ustawione na $2
+% When \var{-vm} is used, the compiler tells you what values macros get.
+parser_i_compiling=03104_I_Kompilowanie $1
+% When you turn on information messages (\var{-vi}), the compiler tells you
+% what units it is recompiling.
+parser_u_parsing_interface=03105_UL_Parsowanie cz©˜ci interface moduˆu $1
+% This tells you that the reading of the interface
+% of the current unit starts
+parser_u_parsing_implementation=03106_UL_Parsowanie cz©˜ci implementation moduˆu $1
+% This tells you that the code reading of the implementation
+% of the current unit, library or program starts
+parser_d_compiling_second_time=03107_DL_Kompilowanie $1 po raz drugi
+% When you request debug messages (\var{-vd}) the compiler tells you what
+% units it recompiles for the second time.
+parser_e_no_property_found_to_override=03109_E_Nie znaleziono wˆasno˜ci do przeci¥¾enia
+% You want to overrride a property of a parent class, when there is, in fact,
+% no such property in the parent class.
+parser_e_only_one_default_property=03110_E_Dozwolona jest tylko jedna wˆasno˜† domy˜lna, a znaleziono odziedziczon¥ wˆasno˜† domy˜ln¥ $1
+% You specified a property as \var{Default}, but a parent class already has a
+% default property, and a class can have only one default property.
+parser_e_property_need_paras=03111_E_Wˆasno˜ci¥ domy˜ln¥ musi by† tablica
+% Only array properties of classes can be made \var{default} properties.
+parser_e_constructor_cannot_be_not_virtual=03112_E_Wirtualne konstruktory s¥ dost©pne tylko w klasach
+% You cannot have virtual constructors in objects. You can only have them
+% in classes.
+parser_e_no_default_property_available=03113_E_Brak domy˜lnej wˆasno˜ci w tej klasie
+% You are trying to access a default property of a class, but this class (or one of
+% its ancestors) doesn't have a default property.
+parser_e_cant_have_published=03114_E_Klasa nie mo¾e mie† sekcji published, u¾yj przeˆ¥cznika {$M+}
+% If you want a \var{published} section in a class definition, you must
+% use the \var{\{\$M+\}} switch, whch turns on generation of type
+% information.
+parser_e_forward_declaration_must_be_resolved=03115_E_Deklaracja naprz¢d klasy $1 musi by† rozwi¥zana, aby u¾y† klasy jako przodka innej klasy
+% To be able to use an object as an ancestor object, it must be defined
+% first. This error occurs in the following situation:
+% \begin{verbatim}
+% Type ParentClas = Class;
+% ChildClass = Class(ParentClass)
+% ...
+% end;
+% \end{verbatim}
+% Where \var{ParentClass} is declared but not defined.
+parser_e_no_local_operator=03116_E_Lokalne przeci¥¾enia operator¢w niedost©pne
+% You cannot overload locally, i.e. inside procedures or function
+% definitions.
+parser_e_proc_dir_not_allowed_in_interface=03117_E_Dyrektywa $1 niedozwolona w sekcji interface
+% This procedure directive is not allowed in the \var{interface} section of
+% a unit. You can only use it in the \var{implementation} section.
+parser_e_proc_dir_not_allowed_in_implementation=03118_E_Dyrektywa $1 niedozwolona w sekcji implementation
+% This procedure directive is not defined in the \var{implementation} section of
+% a unit. You can only use it in the \var{interface} section.
+parser_e_proc_dir_not_allowed_in_procvar=03119_E_Dyrektywa $1 niedozwolona w deklaracji typu proceduralnego
+% This procedure directive cannot be part of a procedural or function
+% type declaration.
+parser_e_function_already_declared_public_forward=03120_E_Funkcja jest ju¾ zadeklarowana jako Public/Forward $1
+% You will get this error if a function is defined as \var{forward} twice.
+% Or it is once in the \var{interface} section, and once as a \var{forward}
+% declaration in the \var{implmentation} section.
+parser_e_not_external_and_export=03121_E_Nie mo¾na u¾y† jednocze˜nie EXPORT i EXTERNAL
+% These two procedure directives are mutually exclusive
+parser_w_not_supported_for_inline=03123_W_$1 nieobsˆugiwane w procedurze/funkcji inline
+% Inline procedures don't support this declaration.
+parser_w_inlining_disabled=03124_W_Inline wyˆ¥czone
+% Inlining of procedures is disabled.
+parser_i_writing_browser_log=03125_I_Zapisywanie logu przegl¥darki $1
+% When information messages are on, the compiler warns you when it
+% writes the browser log (generated with the \var{\{\$Y+ \}} switch).
+parser_h_maybe_deref_caret_missing=03126_H_Mo¾liwe, ¾e brakuje dereferencji wska«nika
+% The compiler thinks that a pointer may need a dereference.
+parser_f_assembler_reader_not_supported=03127_F_Wybrany tryb asemblera nie jest obsˆugiwany
+% The selected assembler reader (with \var{\{\$ASMMODE xxx\}} is not
+% supported. The compiler can be compiled with or without support for a
+% particular assembler reader.
+parser_e_proc_dir_conflict=03128_E_Dyrektywa $1 koliduje z innymi dyrektywami
+% You specified a procedure directive that conflicts with other directives.
+% for instance \var{cdecl} and \var{pascal} are mutually exclusive.
+parser_e_call_convention_dont_match_forward=03129_E_Konwencja wywoˆywania musi by† taka sama w cz©sci interface i implementation
+% This error happens when you declare a function or procedure with
+% e.g. \var{cdecl;} but omit this directive in the implementation, or vice
+% versa. The calling convention is part of the function declaration, and
+% must be repeated in the function definition.
+parser_e_property_cant_have_a_default_value=03131_E_Ta wˆasno˜† nie mo¾e mie† domy˜lnej warto˜ci
+% Set properties or indexed properties cannot have a default value.
+parser_e_property_default_value_must_const=03132_E_Domy˜lna warto˜† wˆasno˜ci musi by† staˆ¥
+% The value of a \var{default} declared property must be known at compile
+% time. The value you specified is only known at run time. This happens
+% .e.g. if you specify a variable name as a default value.
+parser_e_cant_publish_that=03133_E_Symbol nie mo¾e by† w sekcji published
+% Only class type variables can be in a \var{published} section of a class
+% if they are not declared as a property.
+parser_e_cant_publish_that_property=03134_E_Ten typ warto˜ci nie mo¾e by† w sekcji published
+% Properties in a \var{published} section cannot be array properties.
+% they must be moved to public sections. Properties in a \var{published}
+% section must be an ordinal type, a real type, strings or sets.
+parser_e_empty_import_name=03136_W_Wymagana jest nazwa importu
+% Some targets need a name for the imported procedure or a \var{cdecl} specifier
+parser_e_division_by_zero=03138_E_Dzielenie przez zero
+% There is a divsion by zero encounted
+parser_e_invalid_float_operation=03139_E_Nieprawidˆowa operacja zmiennoprzecinkowa
+% An operation on two real type values produced an overflow or a division
+% by zero.
+parser_e_array_lower_less_than_upper_bound=03140_E_G¢rna granica zakresu jest mniejsza od dolnej
+% The upper bound of a an array declaration is less than the lower bound and this
+% is not possible
+parser_w_string_too_long=03141_W_String "$1" jest dˆu¾szy ni¾ $2
+% The size of the constant string is larger than the size you specified in
+% string type definition
+parser_e_string_larger_array=03142_E_Dˆugo˜† stringa jest wi©ksza ni¾ dˆugo˜† tablicy znak¢w
+% The size of the constant string is larger than the size you specified in
+% the array[x..y] of char definition
+parser_e_ill_msg_expr=03143_E_Nieprawidˆowe wyra¾enie przy dyrektywie message
+% \fpc supports only integer or string values as message constants
+parser_e_ill_msg_param=03144_E_Funkcje obsˆuguj¥ce komunikaty (message) mog¥ pobiera† tylko jeden parametr przez referencj©
+% A method declared with the \var{message}-directive as message handler
+% can take only one parameter which must be declared as call by reference
+% Parameters are declared as call by reference using the \var{var}-directive
+parser_e_duplicate_message_label=03145_E_Zduplikowana etykieta komunikatu: $1
+% A label for a message is used twice in one object/class
+parser_e_self_in_non_message_handler=03146_E_Self mo¾e by† parametrem tylko metod obsˆuguj¥cych komunikaty
+% The self parameter can only be passed explicitly to a method which
+% is declared as message handler.
+parser_e_threadvars_only_sg=03147_E_Zmienne threadvar mog¥ by† tylko statyczne lub globalne
+% Threadvars must be static or global, you can't declare a thread
+% local to a procedure. Local variables are always local to a thread,
+% because every thread has its own stack and local variables
+% are stored on the stack
+parser_f_direct_assembler_not_allowed=03148_F_Wstawki asemblera niedost©pne gdy wyj˜ciowym formatem jest wbudowane zapisywanie binarne
+% You can't use direct assembler when using a binary writer, choose an
+% other outputformat or use another assembler reader
+parser_w_no_objpas_use_mode=03149_W_Nie ˆaduj moduˆu OBJPAS bezpo˜rednio - u¾yj trybu obiektowego (objfpc, delphi)
+% You are trying to load the ObjPas unit manually from a uses clause. This is
+% not a good idea. Use the \var{\{\$mode objfpc\}} or
+% \var{\{\$mode delphi\}}
+% directives which load the unit automatically
+parser_e_no_object_override=03150_E_OVERRIDE nie mo¾e by† u¾yte dla obiekt¢w
+% Override is not supported for objects, use \var{virtual} instead to override
+% a method of a parent object
+parser_e_cant_use_inittable_here=03151_E_Typy danych wymagaj¥ce inicjalizacji/finalizcji nie mog¥ by† u¾yte w rekordach z wariantami
+% Some data type (e.g. \var{ansistring}) needs initialization/finalization
+% code which is implicitly generated by the compiler. Such data types
+% can't be used in the variant part of a record.
+parser_e_resourcestring_only_sg=03152_E_Resourcestring mo¾e by† tylko statyczny lub globalny
+% Resourcestring can not be declared local, only global or using the static
+% directive.
+parser_e_exit_with_argument_not__possible=03153_E_Exit z argumentem nie mo¾e by† tu u¾yte
+% an exit statement with an argument for the return value can't be used here, this
+% can happen e.g. in \var{try..except} or \var{try..finally} blocks
+parser_e_stored_property_must_be_boolean=03154_E_Symbol przechowywania wˆasno˜ci musi by† typu boolean
+% If you specify a storage symbol in a property declaration, it must be of
+% the type boolean
+parser_e_ill_property_storage_sym=03155_E_Ten symbol nie mo¾e by† symbolem przechowywania wˆasno˜ci
+% You can't use this type of symbol as storage specifier in property
+% declaration. You can use only methods with the result type boolean,
+% boolean class fields or boolean constants
+parser_e_only_publishable_classes_can__be_published=03156_E_Tylko klasy skompilowane w trybie $M+ mog¥ by† w sekcji published
+% In the published section of a class can be only class as fields used which
+% are compiled in \var{\{\$M+\}} or which are derived from such a class. Normally
+% such a class should be derived from TPersitent
+parser_e_proc_directive_expected=03157_E_Oczekiwano dyrektywy procedury
+% When declaring a procedure in a const block you used a ; after the
+% procedure declaration after which a procedure directive must follow.
+% Correct declarations are:
+% \begin{verbatim}
+% const
+% p : procedure;stdcall=nil;
+% p : procedure stdcall=nil;
+% \end{verbatim}
+parser_e_invalid_property_index_value=03158_E_Warto˜† indeksu wˆasno˜ci musi by† typu porz¥dkowego
+% The value you use to index a property must be of an ordinal type, for
+% example an integer or enumerated type.
+parser_e_procname_to_short_for_export=03159_E_Zbyt kr¢tka nazwa procedury, aby eksportowa†
+% The length of the procedure/function name must be at least 2 characters
+% long. This is because of a bug in dlltool which doesn't parse the .def
+% file correct with a name of length 1.
+parser_e_dlltool_unit_var_problem=03160_E_Nie mo¾na wygenerowa† pozycji DEFFILE dla zmiennych globalnych moduˆu
+parser_e_dlltool_unit_var_problem2=03161_E_Skompiluj bez opcji -WD
+% You need to compile this file without the -WD switch on the
+% commandline
+parser_f_need_objfpc_or_delphi_mode=03162_F_Aby skompilowa† ten moduˆ wymagany jest tryb ObjFpc (-S2) lub Delphi (-Sd)
+% You need to use {$mode objfpc} or {$mode delphi} to compile this file.
+% Or use the equivalent commandline switches -S2 or -Sd.
+parser_e_no_export_with_index_for_target=03163_E_Nie mo¾na wyeksportowa† z indeksem pod $1
+% Exporting of functions or procedures with a specified index is not
+% supported on this target.
+parser_e_no_export_of_variables_for_target=03164_E_Nie mo¾na wyeksportowa† zmiennych pod $1
+% Exporting of variables is not supported on this target.
+parser_e_improper_guid_syntax=03165_E_Nieprawidˆowa skˆadnia identyfikatora GUID
+parser_w_interface_mapping_notfound=03168_W_Nie znaleziono procedury "$1", kt¢ra mogˆaby implementowa† $2.$3
+parser_e_interface_id_expected=03169_E_Oczekiwano interfejsu
+% This happens when the compiler scans a \var{class} declaration that contains
+% \var{interface} function name mapping code like this:
+% \begin{verbatim}
+% type
+% TMyObject = class(TObject, IDispatch)
+% function IUnknown.QueryInterface=MyQueryInterface;
+% ....
+% \end{verbatim}
+% and the \var{interface} before the dot not listed in the inheritance list.
+parser_e_type_cant_be_used_in_array_index=03170_E_Typ "$1" nie mo¾e by† u¾yty jako indeks tablicy
+% Types like \var{qword} or \var{int64} aren't allowed as array index type
+parser_e_no_con_des_in_interfaces=03171_E_Konstruktory i destruktory s¥ niedozwolone w interfejsach
+% Constructor and destructor declarations aren't allowed in interface
+% In the most cases the method \var{QueryInterface} of \var{IUnknown} can
+% be used to create a new interface.
+parser_e_no_access_specifier_in_interfaces=03172_E_Okre˜lenia dost©pu nie mog¥ by† u¾yte w interfejsach
+% The access specifiers \var{public}, \var{private}, \var{protected} and
+% \var{pusblished} can't be used in interfaces because all methods
+% of an interfaces must be public.
+parser_e_no_vars_in_interfaces=03173_E_Interfejs nie mo¾e posiada† p¢l
+% Declarations of fields aren't allowed in interfaces. An interface
+% can contain only methods
+parser_e_no_local_external=03174_E_Lokalne procedury nie mog¥ by† zadeklarowane jako EXTERNAL
+% Declaring local procedures as external is not possible. Local procedures
+% get hidden parameters that will make the chance of errors very high
+parser_w_skipped_fields_before=03175_W_Niekt¢re pola przed "$1" nie zostaˆy zainicjalizowane
+% In Delphi mode, not all fields of a typed constant record have to be
+% initialized, but the compiler warns you when it detects such situations.
+parser_e_skipped_fields_before=03176_E_Niekt¢re pola przed "$1" nie zostaˆy zainicjalizowane
+% In all syntax modes but Delphi mode, you can't leave some fields uninitialized
+% in the middle of a typed constant record
+parser_w_skipped_fields_after=03177_W_Niekt¢re pola po "$1" nie zostaˆy zainicjalizowane
+% You can leave some fields at the end of a type constant record uninitialized
+% (the compiler will initialize them to zero automatically). This may be the cause
+% of subtle problems.
+parser_e_varargs_need_cdecl_and_external=03178_E_Dyrektywa VarArgs bez CDecl i External
+% The varargs directive can only be used with procedures or functions
+% that are declared with \var{cdecl} and \var{external} directives. The varargs directive
+% is only meant to provide a compatible interface to C functions like printf.
+parser_e_self_call_by_value=03179_E_Self musi by† normalnym parametrem (przekazywanym przez warto˜†)
+% You can't declare self as a const or var parameter, it must always be
+% a call-by-value parameter
+parser_e_interface_has_no_guid=03180_E_Interfejs "$1" nie posiada identyfikatora GUID
+% When you want to assign an interface to a constant, then the interface
+% must have a GUID value set.
+parser_e_illegal_field_or_method=03181_E_Nieznana metoda albo pole klasy "$1"
+% Properties must refer to a field or method in the same class.
+parser_w_proc_overriding_calling=03182_W_Zmiana sposobu wywoˆywania z "$1" na "$2"
+% There are two directives in the procedure declaration that specify a calling
+% convention. Only the last directive will be used
+parser_e_no_procvarobj_const=03183_E_Typowane staˆe typu "procedure of object" mog¥ by† inicjowane tylko NILem
+% You can't assign the address of a method to a typed constant which has a
+% 'procedure of object' type, because such a constant requires two addresses:
+% that of the method (which is known at compile time) and that of the object or
+% class instance it operates on (which can not be known at compile time).
+parser_e_default_value_only_one_para=03184_E_Domy˜lna warto˜† mo¾e by† przypisana tylko jednemu parametrowi
+parser_e_default_value_expected_for_para=03185_E_Domy˜lna warto˜† wymagana dla "$1"
+parser_w_unsupported_feature=03186_W_U¾ycie (jeszcze) nieobsˆugiwanej funkcji kompilatora!
+% You're trying to force the compiler into doing something it cannot do yet.
+parser_h_c_arrays_are_references=03187_H_Tablice C s¥ przekazywane przez referencj©
+% Any array passed to a C functions is passed
+% by a pointer (i.e. by reference).
+parser_e_C_array_of_const_must_be_last=03188_E_Tablica staˆych musi by† ostatnim argumentem
+% You can not add any other argument after an \var{array of const} for
+% \var{cdecl} functions, as the size pushed on stack for this argument is
+% not known.
+parser_h_type_redef=03189_H_Powt¢rna definicja typu "$1"
+% This is an indicator that a previously declared type is
+% being redefined as something else. This may, or may not
+% be, a cause for errors.
+parser_w_cdecl_has_no_high=03190_W_Funkcje cdecl nie maj¥ parametru high
+% Functions declared with cdecl modifier do not pass an extra implicit parameter.
+parser_w_cdecl_no_openstring=03191_W_Funkcje cdecl nie obsˆuguj¥ open strings
+%Openstring is not supported for cdecl'ared functions.
+parser_e_initialized_not_for_threadvar=03192_E_Nie mo¾na zainicjalizowa† zmiennych zadeklarowanych jako threadvar
+% Variables declared as threadvar can not be initialized with a default value.
+% The variables will always be filled with zero at the start of a new thread.
+parser_e_msg_only_for_classes=03193_E_Dyrektywa Message jest dozwolona tylko w klasach
+% The message directive is only supported for Class types.
+parser_e_procedure_or_function_expected=03194_E_Oczekiwano procedury lub funkcji
+% A class method can only be specified for procedures and functions.
+parser_e_illegal_calling_convention=03195_W_Dyrektywa "$1" zignorowana
+% Some calling conventions are supported only by certain CPUs. I.e. most non-i386 ports support
+% only the standard ABI calling convention of the CPU.
+parser_e_no_object_reintroduce=03196_E_Nie mo¾na u¾y† REINTRODUCE dla obiekt¢w
+% \var{reintroduce} is not supported for objects.
+parser_e_paraloc_only_one_para=03197_E_Ka¾dy argument musi posiada† swoj¥ pozycj©
+% If locations for arguments are specified explicitly as it is required by
+% some syscall conventions, each argument must have it's only location, things
+% like \var{procedure p(i,j : longint 'r1');} aren't allowed
+parser_e_paraloc_all_paras=03198_E_Ka¾dy argument musi posiada† swoj¥ pozycj©
+% If one argument has an explicit argument location, all arguments of a procedure
+% must have one.
+parser_e_illegal_explicit_paraloc=03199_E_Nieznana pozycja argumentu
+% The location specified for an argument isn't recognized by the compiler
+parser_e_32bitint_or_pointer_variable_expected=03200_E_Oczekiwano 32 bitowej liczby typu Integer albo wska«nika
+% The libbase for MorphOS/AmigaOS can be give only as \var{longint}, \var{dword} or any pointer variable.
+parser_e_goto_outside_proc=03201_E_Nie mo¾na u¾y† instrukcji GOTO pomi©dzy procedurami
+% It isn't allowed to use the \var{goto} statements referencing labels outside the
+% current procedure. The following example shows the problem:
+% \begin{verbatim}
+% ...
+% procedure p1;
+% label
+% l1;
+%
+% procedure p2;
+% begin
+% goto l1; // This goto ISN'T allowed
+% end;
+%
+% begin
+% p2
+% l1:
+% end;
+% ...
+%
+% \end{verbatim}
+parser_f_too_complex_proc=03202_F_Zbyt rozbudowana procedura, spr¢buj rozbi† j¥ na mniejsze
+% Your procedure body is too long for the compiler. You should split the
+% procedure into multiple smaller procedures.
+parser_e_illegal_expression=03203_E_Nieprawidˆowe wyra¾enie
+% This can occur under many circumstances. Mostly when trying to evaluate
+% constant expressions.
+parser_e_invalid_integer=03204_E_Nieprawidˆowe wyra¾enie (powinno zw¢ci† liczb© caˆkowit¥)
+% You made an expression which isn't an integer, and the compiler expects the
+% result to be an integer.
+parser_e_invalid_qualifier=03205_E_Nieprawidˆowy kwalifikator
+% One of the following is happening :
+% \begin{itemize}
+% \item You're trying to access a field of a variable that is not a record.
+% \item You're indexing a variable that is not an array.
+% \item You're dereferencing a variable that is not a pointer.
+% \end{itemize}
+parser_e_upper_lower_than_lower=03206_E_G¢rna granica zakresu jest mniejsza od dolnej
+% You are declaring a subrange, and the lower limit is higher than the high
+% limit of the range.
+parser_e_macpas_exit_wrong_param=03207_E_Parametr funkcji EXIT musi by† nazw¥ procedury, w kt¢rej jej u¾yto
+% Non local exit is not allowed. This error occurs only in mode MacPas.
+parser_e_illegal_assignment_to_count_var=03208_E_Nieprawidˆowe przypisanie do licznika p©tli "$1"
+% The type of a \var{for} loop variable must be an ordinal type.
+% Loop variables cannot be reals or strings.
+parser_e_no_local_var_external=03209_E_Lokalne zmienne nie mog¥ by† zadeklarowane jako EXTERNAL
+% Declaring local variables as external is not allowed. Only global variables can reference
+% to external variables.
+parser_e_proc_already_external=03210_E_Procedura ju¾ zadeklarowana jako EXTERNAL
+% The procedure is already declared with the EXTERNAL directive in an interface or
+% forward declaration.
+parser_w_implicit_uses_of_variants_unit=03211_W_Dopisanie moduˆu Variants do sekcji uses
+% The Variant type is used in the unit without any used unit using the Variants unit. The
+% compiler has implicitly added the Variants unit to the uses list. To remove this warning
+% the Variants unit needs to be added to the uses statement.
+parser_e_no_static_method_in_interfaces=03212_E_Metody statyczne nie mog¥ by† u¾yte w interfejsach
+% The specifier \var{class} and directive \var{static} can't be used in interfaces
+% because all methods of an interfaces must be public.
+parser_e_arithmetic_operation_overflow=03213_E_Wyst¥piˆo przepeˆnienie w operacji arytmetycznej
+% An operation on two integers values produced an overflow
+parser_e_protected_or_private_expected=03214_E_Oczekiwano "protected" albo "private"
+% \var{strict} can be only used together with \var{protected} or \var{private}.
+% \end{description}
+#
+# Type Checking
+#
+# 04049 is the last one used
+#
+% \section{Type checking errors}
+% This section lists all errors that can occur when type checking is
+% performed.
+% \begin{description}
+type_e_mismatch=04000_E_Nieprawidˆowy typ
+% This can happen in many cases:
+% \begin{itemize}
+% \item The variable you're assigning to is of a different type than the
+% expression in the assignment.
+% \item You are calling a function or procedure with parameters that are
+% incompatible with the parameters in the function or procedure definition.
+% \end{itemize}
+type_e_incompatible_types=04001_E_Niezgodno˜† typ¢w: otrzymano "$1" oczekiwano "$2"
+% There is no conversion possible between the two types
+% Another possiblity is that they are declared in different
+% declarations:
+% \begin{verbatim}
+% Var
+% A1 : Array[1..10] Of Integer;
+% A2 : Array[1..10] Of Integer;
+%
+% Begin
+% A1:=A2; { This statement gives also this error, it
+% is due the strict type checking of pascal }
+% End.
+% \end{verbatim}
+type_e_not_equal_types=04002_E_Niezgodno˜† typ¢w pomi©dzy $1 i $2
+% The types are not equal
+type_e_type_id_expected=04003_E_Oczekiwano identyfikatora typu
+% The identifier is not a type, or you forgot to supply a type identifier.
+type_e_variable_id_expected=04004_E_Oczekiwano identyfikatora zmiennej
+% This happens when you pass a constant to a routine (such as \var{Inc} var or \var{Dec})
+% when it expects a variable. You can only pass variables as arguments to these functions.
+type_e_integer_expr_expected=04005_E_Oczekiwano wyra¾enia caˆkowitego, ale otrzymano "$1"
+% The compiler expects an expression of type integer, but gets a different
+% type.
+type_e_boolean_expr_expected=04006_E_Oczekiwano wyra¾enia logicznego, ale otrzymano "$1"
+% The expression must be a boolean type, it should be return true or
+% false.
+type_e_ordinal_expr_expected=04007_E_Oczekiwano wyra¾enia porz¥dkowego
+% The expression must be of ordinal type, i.e., maximum a \var{Longint}.
+% This happens, for instance, when you specify a second argument
+% to \var{Inc} or \var{Dec} that doesn't evaluate to an ordinal value.
+type_e_pointer_type_expected=04008_E_Oczekiwano wska«nika, ale otrzymano "$1"
+% The variable or expression isn't of the type \var{pointer}. This
+% happens when you pass a variable that isn't a pointer to \var{New}
+% or \var{Dispose}.
+type_e_class_type_expected=04009_E_Oczekiwano klasy, ale otrzymano "$1"
+% The variable of expression isn't of the type \var{class}. This happens
+% typically when
+% \begin{enumerate}
+% \item The parent class in a class declaration isn't a class.
+% \item An exception handler (\var{On}) contains a type identifier that
+% isn't a class.
+% \end{enumerate}
+type_e_cant_eval_constant_expr=04011_E_Nie mo¾na obliczy† warto˜ci wyra¾enia
+% This error can occur when the bounds of an array you declared does
+% not evaluate to ordinal constants
+type_e_set_element_are_not_comp=04012_E_Niekompatybilne elementy zbioru
+% You are trying to make an operation on two sets, when the set element types
+% are not the same. The base type of a set must be the same when taking the
+% union
+type_e_set_operation_unknown=04013_E_Operacja niezaimplementowana dla zbioru
+% several binary operations are not defined for sets
+% like div mod ** (also >= <= for now)
+type_w_convert_real_2_comp=04014_W_Konwersja typu zmiennoprzecinkowego do caˆkowitego typu COMP
+% An implicit type conversion from a real type to a \var{comp} is
+% encountered. Since \var{Comp} is a 64 bit integer type, this may indicate
+% an error.
+type_h_use_div_for_int=04015_H_U¾yj DIV zamiast '/' aby wynik byˆ caˆkowity
+% When hints are on, then an integer division with the '/' operator will
+% procuce this message, because the result will then be of type real
+type_e_strict_var_string_violation=04016_E_Typy string¢w nie pasuj¥ z powodu trybu $V+
+% When compiling in \var{\{\$V+\}} mode, the string you pass as a parameter
+% should be of the exact same type as the declared parameter of the procedure.
+type_e_succ_and_pred_enums_with_assign_not_possible=04017_E_Succ i Pred nie dziaˆaj¥ dla wyliczeä z przypisaniami
+% When you declared an enumeration type which has assignments in it, as in C,
+% like in the following:
+% \begin{verbatim}
+% Tenum = (a,b,e:=5);
+% \end{verbatim}
+% you cannot use the \var{Succ} or \var{Pred} functions on them.
+type_e_cant_read_write_type=04018_E_Nie mo¾na zapisa† lub odczyta† zmiennych tego typu
+% You are trying to \var{read} or \var{write} a variable from or to a
+% file of type text, which doesn't support that. Only integer types,
+% reals, pchars and strings can be read from/written to a text file.
+% Booleans can only be written to text files.
+type_e_no_readln_writeln_for_typed_file=04019_E_Nie mo¾na u¾y† readln ani writeln na pliku tego typu
+% \var{readln} and \var{writeln} are only allowed for text files.
+type_e_no_read_write_for_untyped_file=04020_E_Nie mo¾na u¾y† readln ani writeln na nietypowanym pliku
+% \var{read} and \var{write} are only allowed for text or typed files.
+type_e_typeconflict_in_set=04021_E_Konflikt typ¢w pomi©dzy elementami zbioru
+% There is at least one set element which is of the wrong type, i.e. not of
+% the set type.
+type_w_maybe_wrong_hi_lo=04022_W_lo/hi(dword/qword) zwraca starsze/mˆodsze sˆowo/podw¢jne sˆowo
+% \fpc supports an overloaded version of \var{lo/hi} for \var{longint/dword/int64/qword}
+% which returns the lower/upper word/dword of the argument. TP always uses
+% a 16 bit \var{lo/hi} which returns always bits 0..7 for \var{lo} and the
+% bits 8..15 for \var{hi}. If you want the TP behavior you have
+% to type cast the argument to \var{word/integer}
+type_e_integer_or_real_expr_expected=04023_E_Oczekiwano wyra¾enia caˆkowitego lub zmiennoprzecinkowego
+% The first argument to \var{str} must a real or integer type.
+type_e_wrong_type_in_array_constructor=04024_E_Nieprawidˆowy typ $1 w konstruktorze tablicy
+% You are trying to use a type in an array constructor which is not
+% allowed.
+type_e_wrong_parameter_type=04025_E_Nieprawidˆowy typ parametru nr $1: Otrzymano $2, a oczekiwano $3
+% You are trying to pass an invalid type for the specified parameter.
+type_e_no_method_and_procedure_not_compatible=04026_E_Metoda i Procedura nie s¥ zgodne (jako zmienne)
+% You can't assign a method to a procedure variable or a procedure to a
+% method pointer.
+type_e_wrong_math_argument=04027_E_Nieprawidˆowa staˆa przekazana do wbudowanej funkcji matematycznej
+% The constant argument passed to a ln or sqrt function is out of
+% the definition range of these functions.
+type_e_no_addr_of_constant=04028_E_Nie mo¾na pobra† adresu staˆej
+% It's not possible to get the address of a constant, because they
+% aren't stored in memory, you can try making it a typed constant.
+type_e_argument_cant_be_assigned=04029_E_Ten argument nie mo¾e by† przekazany przez referencj©
+% Only expressions which can be on the left side of an
+% assignment can be passed as call by reference argument
+% Remark: Properties can be only
+% used on the left side of an assignment, but they can't be used as arguments
+type_e_cannot_local_proc_to_procvar=04030_E_Nie mo¾na przypisa† lokalnej procedury/funkcji do zmiennej proceduralnej
+% It's not allowed to assign a local procedure/function to a
+% procedure variable, because the calling of local procedure/function is
+% different. You can only assign local procedure/function to a void pointer.
+type_e_no_assign_to_addr=04031_E_Nie mo¾na przypisa† warto˜ci adresowi
+% It is not allowed to assign a value to an address of a variable, constant,
+% procedure or function. You can try compiling with -So if the identifier
+% is a procedure variable.
+type_e_no_assign_to_const=04032_E_Nie mo¾na staˆej przypisa† warto˜ci
+% It's not allowed to assign a value to a variable which is declared
+% as a const. This is normally a parameter declared as const, to allow
+% changing the value make the parameter as a value parameter or a var.
+type_e_array_required=04033_E_Dozwolone tylko dla tablic
+% If you are accessing a variable using an index '[<x>]' then
+% the type must be an array. In FPC mode also a pointer is allowed.
+type_e_interface_type_expected=04034_E_Oczekiwano interfejsu ale otrzymano "$1"
+type_w_mixed_signed_unsigned=04035_W_U¾ywanie zmiennych typu Cardinal w wyra¾eniach ze znakiem daje 64bitowy wynik
+% If you divide (or calculate the modulus of) a signed expression by a longword (or vice versa),
+% or if you have overflow and/or range checking turned on and use an arithmetical
+% expression (+, -, *, div, mod) in which both signed numbers and longwords appear,
+% then everything has to be evaluated in 64bit which is slower than normal
+% 32bit arithmetic. You can avoid this by typecasting one operand so it
+% matches the result type of the other one.
+type_w_mixed_signed_unsigned2=04036_W_U¾ywanie zmiennych typu Cardinal w wyra¾eniach ze znakiem mo¾e spowodowa† bˆ¥d zakresu w tym miejscu
+% If you use a binary operator (and, or, xor) and one of
+% the operands is a cardinal while the other one is a signed expression, then,
+% if range checking is turned on, you may get a range check error because in
+% such a case both operands are converted to cardinal before the operation is
+% carried out. You can avoid this by typecasting one operand so it
+% matches the result type of the other one.
+type_e_typecast_wrong_size_for_assignment=04037_E_Rzutowanie typ¢w r¢¾nych rozmiar¢w ($1 -> $2) w przypisaniu
+% Type casting to a type with a different size is not allowed when the variable is
+% used for assigning.
+type_e_array_index_enums_with_assign_not_possible=04038_E_Typ wyliczeniowy z przypisanymi warto˜ciami nie moze by† u¾yty do ideksowania tablicy
+% When you declared an enumeration type which has assignments in it, as in C,
+% like in the following:
+% \begin{verbatim}
+% Tenum = (a,b,e:=5);
+% \end{verbatim}
+% you cannot use it as index of an array.
+type_e_classes_not_related=04039_E_Typy obiektowe "$1" i "$2" nie s¥ pokrewne
+% There is a typecast from one class or object to another while the class/object
+% are not related. This will probably lead to errors
+type_w_classes_not_related=04040_W_Typy obiektowe "$1" i "$2" nie s¥ pokrewne
+% There is a typecast from one class or object to another while the class/object
+% are not related. This will probably lead to errors
+type_e_class_or_interface_type_expected=04041_E_Oczekiwano klasy lub interfejsu ale otrzymano "$1"
+type_e_type_is_not_completly_defined=04042_E_Typ "$1" nie jest kompletnie zdefiniowany
+type_w_string_too_long=04043_W_Przekroczona maksymalna dˆugo˜† ˆaäcucha
+% The size of the constant string, which is assigned to a shortstring,
+% is longer than the maximum size of the shortstring
+type_w_signed_unsigned_always_false=04044_W_To por¢wnanie zawsze zwraca faˆsz z powodu zakres¢w warto˜ci zmiennych
+% There is a comparison between an unsigned value and a signed constant which is
+% less than zero. Because of type promotion, the statement will always evaluate to
+% false. Exlicitly typecast the constant to the correct range to avoid this problem.
+type_w_signed_unsigned_always_true=04045_W_To por¢wnanie zawsze zwraca faˆsz z powodu zakres¢w warto˜ci zmiennych
+% There is a comparison between an unsigned value and a signed constant which is
+% less than zero. Because of type promotion, the statement will always evaluate to
+% true. Exlicitly typecast the constant to the correct range to avoid this problem.
+type_w_instance_with_abstract=04046_W_Tworzenie klasy "$1" posiadaj¥cej metody abstrakcyjne
+% An instance of a class is created which contains non-implemented abstract
+% methods. This will probably lead to a runtime error 211 in the code if that
+% routine is ever called. All abstract methods should be overridden.
+type_h_in_range_check=04047_H_Lewy operand operatora IN powinien by† wielko˜ci jednego bajta
+% The left operand of the \var{in} operator is not an ordinal or enumeration which fits
+% within 8-bits, this may lead to range check errors. The \var{in} operator
+% currently only supports a left operand which fits within a byte. In the case of
+% enumerations, the size of an element of an enumeration can be controlled with
+% the \var{\{\$PACKENUM\}} or \var{\{\$Zn\}} switches.
+type_w_smaller_possible_range_check=04048_W_Typy r¢¾nej wielko˜ci - mo¾liwa utrata danych lub bˆ¥d zakresu
+% There is an assignment to a smaller type than the source type. This means that
+% this may cause a range-check error, or may lead to possible loss of data.
+type_h_smaller_possible_range_check=04049_H_Typy r¢¾nej wielko˜ci - mo¾liwa utrata danych lub bˆ¥d zakresu
+% There is an assignment to a smaller type than the source type. This means that
+% this may cause a range-check error, or may lead to possible loss of data.
+type_e_cant_take_address_of_abstract_method=04050_E_Nie mo¾na uzyska† adresu metody abstrakcyjnej
+% An abstract method has no body, so the address of an abstract method can't be taken.
+type_e_operator_not_allowed=04051_E_Operator nie pasuje do operandu
+% You are trying an operator that is not available for the type of the
+% operands
+type_e_constant_expr_expected=04052_E_Oczekiwano staˆego wyra¾enia
+% The compiler expects an constant expression, but gets a variable expression.
+type_e_operator_not_supported_for_types=04053_E_Operacja "$1" niedozwolona dla typ¢w "$2" i "$3"
+% The operation is not allowed for the supplied types
+type_e_illegal_type_conversion=04054_E_Nieprawidˆowa konwersja typ¢w: "$1" do "$2"
+% When doing a type-cast, you must take care that the sizes of the variable and
+% the destination type are the same.
+type_h_pointer_to_longint_conv_not_portable=04055_H_Konwersja pomi©dzy typami caˆkowitymi i wska«nikami jest nieprzeno˜na
+% If you typecast a pointer to a longint (or vice-versa), this code will not compile
+% on a machine using 64-bit for pointer storage.
+type_w_pointer_to_longint_conv_not_portable=04056_W_Konwersja pomi©dzy typami caˆkowitymi i wska«nikami jest nieprzeno˜na
+% If you typecast a pointer to a ordinal type of a different size (or vice-versa), this can
+% cause problems. This is a warning to help finding the 32bit specific code where cardinal/longint is used
+% to typecast pointers to ordinals. A solution is to use the ptrint/ptruint types instead.
+type_e_cant_choose_overload_function=04057_E_Nie mo¾na okre˜li†, kt¢r¥ z przeci¥¾onych funkcji wywoˆa†
+% You're calling overloaded functions with a parameter that doesn't correspond
+% to any of the declared function parameter lists. e.g. when you have declared
+% a function with parameters \var{word} and \var{longint}, and then you call
+% it with a parameter which is of type \var{integer}.
+type_e_illegal_count_var=04058_E_Nieprawidˆowy typ licznika p©tli
+% The type of a \var{for} loop variable must be an ordinal type.
+% Loop variables cannot be reals or strings.
+% \end{description}
+#
+# Symtable
+#
+# 05055 is the last one used
+#
+% \section{Symbol handling}
+% This section lists all the messages that concern the handling of symbols.
+% This means all things that have to do with procedure and variable names.
+% \begin{description}
+sym_e_id_not_found=05000_E_Nie odnaleziono identyfikatora $1
+% The compiler doesn't know this symbol. Usually happens when you misspel
+% the name of a variable or procedure, or when you forgot to declare a
+% variable.
+sym_f_internal_error_in_symtablestack=05001_F_Bˆ¥d wewn©trzny w SymTableStack()
+% An internal error occurred in the compiler; If you encounter such an error,
+% please contact the developers and try to provide an exact description of
+% the circumstances in which the error occurs.
+sym_e_duplicate_id=05002_E_Zduplikowany identyfikator $1
+% The identifier was already declared in the current scope.
+sym_h_duplicate_id_where=05003_H_Identyfikator ju¾ zdefiniowany w $1 w lini $2
+% The identifier was already declared in a previous scope.
+sym_e_unknown_id=05004_E_Nieznany identyfikator $1
+% The identifier encountered has not been declared, or is used outside the
+% scope where it is defined.
+sym_e_forward_not_resolved=05005_E_Deklaracaja naprz¢d nie rozwi¥zana $1
+% This can happen in two cases:
+% \begin{itemize}
+% \item This happens when you declare a function (in the \var{interface} part, or
+% with a \var{forward} directive, but do not implement it.
+% \item You reference a type which isn't declared in the current \var{type}
+% block.
+% \end{itemize}
+sym_e_error_in_type_def=05007_E_Bˆ¥d w definicji typu
+% There is an error in your definition of a new array type:
+% \item One of the range delimiters in an array declaration is erroneous.
+% For example, \var{Array [1..1.25]} will trigger this error.
+sym_e_forward_type_not_resolved=05009_E_Brak definicji typu $1
+% A symbol was forward defined, but no declaration was encountered.
+sym_e_only_static_in_static=05010_E_Tylko zmienne statyczne mog¥ by† u¾ywane w metodach statycznych
+% A static method of an object can only access static variables.
+sym_f_type_must_be_rec_or_class=05012_F_Oczekiwano rekordu lub klasy
+% The variable or expression isn't of the type \var{record} or \var{class}.
+sym_e_no_instance_of_abstract_object=05013_E_Instancje klas i obiekt¢w z metodami abstrakcyjnymi niedozwolone
+% You are trying to generate an instance of a class which has an abstract
+% method that wasn't overridden.
+sym_w_label_not_defined=05014_W_Etykieta nie zostaˆa zdefiniowana $1
+% A label was declared, but not defined.
+sym_e_label_used_and_not_defined=05015_E_Etykieta niezdefiniowana przed u¾yciem $1
+% A label was declared and used, but not defined.
+sym_e_ill_label_decl=05016_E_Nieprawidˆowa deklaracja etykiety
+% This error should never happen; it occurs if a label is defined outside a
+% procedure or function.
+sym_e_goto_and_label_not_supported=05017_E_GOTO i LABEL nieobsˆugiwane (u¾yj opcji -Sg)
+% You must compile a program which has \var{label}s and \var{goto} statements
+% with the \var{-Sg} switch. By default, \var{label} and \var{goto} aren't
+% supported.
+sym_e_label_not_found=05018_E_Nie odnaleziono etykiety
+% A \var{goto label} was encountered, but the label isn't declared.
+sym_e_id_is_no_label_id=05019_E_Identyfikator nie jest etykiet¥
+% The identifier specified after the \var{goto} isn't of type label.
+sym_e_label_already_defined=05020_E_Powt¢rna definicja etykiety
+% You are defining a label twice. You can define a label only once.
+sym_e_ill_type_decl_set=05021_E_Nieprawidˆowa deklaracja typu zbiorowego
+% The declaration of a set contains an invalid type definition.
+sym_e_class_forward_not_resolved=05022_E_Brak implementacji klasy $1
+% You declared a class, but you didn't implement it.
+sym_n_unit_not_used=05023_H_Moduˆ $1 nieu¾ywany w $2
+% The unit referenced in the \var{uses} clause is not used.
+sym_h_para_identifier_not_used=05024_H_Parametr $1 nieu¾ywany
+% The identifier was declared (locally or globally) but
+% was not used (locally or globally).
+sym_n_local_identifier_not_used=05025_N_Lokalna zmienna $1 nieu¾ywana
+% You have declared, but not used a variable in a procedure or function
+% implementation.
+sym_h_para_identifier_only_set=05026_H_Warto˜c przypisana do $1 nie jest nigdzie u¾yta
+% The identifier was declared (locally or globally)
+% set but not used (locally or globally).
+sym_n_local_identifier_only_set=05027_N_Warto˜c przypisana do $1 nie jest nigdzie u¾yta
+% The variable in a procedure or function
+% implementation is declared, set but never used.
+sym_h_local_symbol_not_used=05028_H_Lokalna(y) $1 $2 nie zostaˆ(a) u¾yta(y)
+% A local symbol is never used.
+sym_n_private_identifier_not_used=05029_N_Prywatne pole $1.$2 nieu¾ywane
+sym_n_private_identifier_only_set=05030_N_Warto˜c przypisana do lokalnego pola $1.$2 nie jest nigdzie u¾yta
+sym_n_private_method_not_used=05031_N_Metoda prywatna $1.$2 nieu¾ywana
+sym_e_set_expected=05032_E_Oczekiwano typu zbiorowego
+% The variable or expression is not of type \var{set}. This happens in an
+% \var{in} statement.
+sym_w_function_result_not_set=05033_W_Nie wygl¥da na to, ¾eby warto˜† zwracana przez funkcj© byˆa ustawiona
+% You can get this warning if the compiler thinks that a function return
+% value is not set. This will not be displayed for assembler procedures,
+% or procedures that contain assembler blocks.
+sym_w_wrong_C_pack=05034_W_Typ $1 jest «le wyr¢wnany dla C w bie¾¥cym rekordzie
+% Arrays with sizes not multiples of 4 will be wrongly aligned
+% for C structures.
+sym_e_illegal_field=05035_E_Nieznany identyfikator pola rekordu $1
+% The field doesn't exist in the record definition.
+sym_n_uninitialized_local_variable=05036_W_Nie wygl¥da na to, ¾eby lokalna zmienna $1 byˆa zainicjowana
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_n_uninitialized_variable=05037_W_Nie wygl¥da na to, ¾eby zmienna $1 byˆa zainicjowana
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_e_id_no_member=05038_E_Identyfikator nie wskazuje ¾adnej metody ani pola $1
+% This error is generated when an identifier of a record,
+% field, or method is accessed while it is not defined.
+sym_h_param_list=05039_H_Znaleziono deklaracj©: $1
+% You get this when you use the \var{-vb} switch. In case an overloaded
+% procedure is not found, then all candidate overloaded procedures are
+% listed, with their parameter lists.
+sym_e_segment_too_large=05040_E_Element jest zbyt du¾y
+% You get this when you declare a data element whose size exceeds the
+% prescribed limit (2 Gb on 80386+/68020+ processors)
+sym_e_no_matching_implementation_found=05042_E_Nie znaleziono implementacji metody interfejsu "$1"
+% There was no matching method found which could implement the interface
+% method. Check argument types and result type of the methods.
+sym_w_deprecated_symbol=05043_W_Symbol "$1" jest przestarzaˆy
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{deprecated} is used. Deprecated symbols may no longer
+% be available in newer versions of the unit / library. Usage of this symbol
+% should be avoided as much as possible.
+sym_w_non_portable_symbol=05044_W_Symbolu "$1" nie da si© przenie˜† na inne platformy
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{platform} is used. This symbol's value, usage
+% and availability is platform specific and should not be used
+% if the source code must be portable.
+sym_w_non_implemented_symbol=05055_W_Symbol "$1" nie jest zaimplementowany
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{unimplemented} is used. This symbol is defined,
+% but is not yet implemented on this specific platform.
+sym_e_cant_create_unique_type=05056_E_Nie mo¾na utworzy† unikalnego typu z tego typu
+% Only simple types like ordinal, float and string types are supported when
+% redefining a type with \var{type newtype = type oldtype;}.
+sym_h_uninitialized_local_variable=05057_H_Zmienna lokalna "$1" mo¾e nie by† zainicjalizowana
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_h_uninitialized_variable=05058_H_Zmienna "$1" mo¾e nie by† zainicjalizowana
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+% \end{description}
+#
+# Codegenerator
+#
+# 06040 is the last used one
+#
+% \section{Code generator messages}
+% This section lists all messages that can be displayed if the code
+% generator encounters an error condition.
+% \begin{description}
+cg_e_parasize_too_big=06009_E_Rozmiar listy parametr¢w przekracza 65535 bajt¢w
+% The I386 processor limits the parameter list to 65535 bytes (the \var{RET}
+% instruction causes this)
+cg_e_file_must_call_by_reference=06012_E_Zmienne plikowe musz¥ by† przekazywane przez referencje
+% You cannot specify files as value parameters, i.e. they must always be
+% declared \var{var} parameters.
+cg_e_cant_use_far_pointer_there=06013_E_U¾ycie wska«nika far niedozwolone w tym miejscu
+% Free Pascal doesn't support far pointers, so you cannot take the address of
+% an expression which has a far reference as a result. The \var{mem} construct
+% has a far reference as a result, so the following code will produce this
+% error:
+% \begin{verbatim}
+% var p : pointer;
+% ...
+% p:=@mem[a000:000];
+% \end{verbatim}
+cg_e_dont_call_exported_direct=06015_E_EXPORT declared functions can't be called
+% No longer in use.
+cg_w_member_cd_call_from_method=06016_W_Mo¾liwe nieprawidˆowe wywoˆanie konstruktora/destruktora
+% The compiler detected that a constructor or destructor is called within a
+% a method. This will probably lead to problems, since constructors / destructors
+% require parameters on entry.
+cg_n_inefficient_code=06017_N_Niewydajny kod
+% Your statement seems dubious to the compiler.
+cg_w_unreachable_code=06018_W_Kod nie zostanie nigdy wykonany
+% You specified a construct which will never be executed. Example:
+% \begin{verbatim}
+% while false do
+% begin
+% {.. code ...}
+% end;
+% \end{verbatim}
+cg_e_cant_call_abstract_method=06020_E_Nie mo¾na bezpo˜rednio wywoˆa† metod abstrakcyjnych
+% You cannot call an abstract method directy, instead you must call a
+% overriding child method, because an abstract method isn't implemented.
+cg_d_register_weight=06027_DL_Rejestr $1 waga $2 $3
+% Debugging message. Shown when the compiler considers a variable for
+% keeping in the registers.
+cg_d_stackframe_omited=06029_DL_Pomini©to ramk© stosu
+% Some procedure/functions do not need a complete stack-frame, so it is omitted.
+% This message will be displayed when the {-vd} switch is used.
+cg_e_unable_inline_object_methods=06031_E_Metody obiekt¢w i klas nie mog¥ by† inline
+% You cannot have inlined object methods.
+cg_e_unable_inline_procvar=06032_E_Wywoˆania procedur ze zmiennych proceduralnych nie mog¥ by† inline
+% A procedure with a procedural variable call cannot be inlined.
+cg_e_no_code_for_inline_stored=06033_E_Brak kodu dla procedury inline
+% The compiler couldn't store code for the inline procedure.
+cg_e_can_access_element_zero=06035_E_Brak dost©pu do zerowego elementu ansi/wide- lub longstringa, u¾yj (set)length
+% You should use \var{setlength} to set the length of an ansi/wide/longstring
+% and \var{length} to get the length of such kinf of string
+cg_e_cannot_call_cons_dest_inside_with=06037_E_Konstruktory i destruktory nie mog¥ by† wywoˆywane w klauzuli 'with'
+% Inside a \var{with} clause you cannot call a constructor or destructor for the
+% object you have in the \var{with} clause.
+cg_e_cannot_call_message_direct=06038_E_Nie mo¾na wywoˆa† bezpo˜rednio metody obsˆuguj¥cej komunikaty
+% A message method handler method cannot be called directly if it contains an
+% explicit self argument
+cg_e_goto_inout_of_exception_block=06039_E_Skok do bloku lub poza blok exception
+% It is not allowed to jump in or outside of an exception block like \var{try..finally..end;}:
+% \begin{verbatim}
+% label 1;
+%
+% ...
+%
+% try
+% if not(final) then
+% goto 1; // this line will cause an error
+% finally
+% ...
+% end;
+% 1:
+% ...
+% \end{verbatim}
+cg_e_control_flow_outside_finally=06040_E_Break, Continue i Exit nie s¥ dozwolone w bloku finally
+% It isn't allowed to use the control flow statements \var{break},
+% \var{continue} and \var{exit}
+% inside a finally statement. The following example shows the problem:
+% \begin{verbatim}
+% ...
+% try
+% p;
+% finally
+% ...
+% exit; // This exit ISN'T allowed
+% end;
+% ...
+%
+% \end{verbatim}
+% If the procedure \var{p} raises an exception the finally block is
+% executed. If the execution reaches the exit, it's unclear what to do:
+% exiting the procedure or searching for another exception handler
+cg_w_parasize_too_big=06041_W_Rozmiar parametr¢w przekroczyˆ limit dla niekt¢rych procesor¢w
+% This indicates that you are declaring more than 64K of parameters, which
+% might not be supported on other processor targets.
+cg_w_localsize_too_big=06042_W_Rozmiar zmiennych lokalnych przekroczyˆ limit dla dla niekt¢rych procesor¢w
+% This indicates that you are declaring more than 32K of lcoal variables, which
+% might not be supported on other processor targets.
+cg_e_localsize_too_big=06043_E_Rozmiar zmiennych lokalnych przekroczyˆ dopuszczalny limit
+% This indicates that you are declaring more than 32K of lcoal variables, which
+% is not supported by this processor.
+cg_e_break_not_allowed=06044_E_BREAK mo¾na u¾y† tylko wewn¥trz p©tli
+% You're trying to use \var{break} outside a loop construction.
+cg_e_continue_not_allowed=06045_E_CONTINUE mo¾na u¾y† tylko wewn¥trz p©tli
+% You're trying to use \var{continue} outside a loop construction.
+% \end{description}
+# EndOfTeX
+
+#
+# Assembler reader
+#
+# 07097 is the last used one
+#
+asmr_d_start_reading=07000_DL_Rozpocz©cie parsowania bloku asemblera w stylu $1
+% This informs you that an assembler block is being parsed
+asmr_d_finish_reading=07001_DL_Zakoäczenie parsowania bloku asemblera w stylu $1
+% This informs you that an assembler block has finished.
+asmr_e_none_label_contain_at=07002_E_½aden identyfikator (poza etykietami) nie mo¾e zawiera† @
+% A identifier which isn't a label can't contain a @.
+asmr_e_building_record_offset=07004_E_Bˆ¥d tworzenia offsetu rekordu
+% There has an error occured while building the offset of a record/object
+% structure, this can happend when there is no field specified at all or
+% an unknown field identifier is used.
+asmr_e_offset_without_identifier=07005_E_OFFSET u¾yty bez identyfikatora
+% You can only use OFFSET with an identifier. Other syntaxes aren't
+% supported
+asmr_e_type_without_identifier=07006_E_TYPE u¾yte bez identyfikatora
+% You can only use TYPE with an identifier. Other syntaxes aren't
+% supported
+asmr_e_no_local_or_para_allowed=07007_E_Nie mo¾na u¾ywa† lokalnych zmiennych i parametr¢w w tym miejscu
+% You can't use a local variable or parameter here, mostly because the
+% addressing of locals and parameters is done using the frame pointer register so the
+% address can't be obtained directly.
+asmr_e_need_offset=07008_E_Nale¾y tu u¾y† OFFSET
+% You need to use OFFSET <id> here to get the address of the identifier.
+asmr_e_need_dollar=07009_E_Nale¾y u¾y† tu $
+% You need to use $<id> here to get the address of the identifier.
+asmr_e_cant_have_multiple_relocatable_symbols=07010_E_Mo¾na u¾y† tylko jednego symbolu relokacyjnego
+% You can't have more than one relocatable symbol (variable/typed constant)
+% in one argument.
+asmr_e_only_add_relocatable_symbol=07011_E_Symbole relokacyjne mog¥ by† tylko dodane
+% Relocatable symbols (variable/typed constant) can't be used with other
+% operators. Only addition is allowed.
+asmr_e_invalid_constant_expression=07012_E_Nieprawidˆowe staˆe wyra¾enie
+% There is an error in the constant expression.
+asmr_e_relocatable_symbol_not_allowed=07013_E_Nie mo¾na u¾y† symbolu relokacyjnego w tym miejscu
+% You can't use a relocatable symbol (variable/typed constant) here.
+asmr_e_invalid_reference_syntax=07014_E_Nieprawidˆowa skˆadnia referencji
+% There is an error in the reference.
+asmr_e_local_para_unreachable=07015_E_Nie mo¾na osi¥gn¥† $1 z tego kodu
+% You can not read directly the value of local or para
+% of a higher level in assembler code (except for
+% local assembler code without parameter nor locals).
+asmr_e_local_label_not_allowed_as_ref=07016_E_Lokalne symbole/etykiety nie s¥ dozwolone jako referencje
+% You can't use local symbols/labels as references
+asmr_e_wrong_base_index=07017_E_Nieprawidˆowe u¾ycie rejestru indeksu i bazy
+% There is an error with the base and index register, they are
+% probably incorrect
+asmr_w_possible_object_field_bug=07018_W_Mo¾liwy bˆ¥d w obsˆugiwaniu pola obiektu
+% Fields of objects or classes can be reached directly in normal or objfpc
+% modes but TP and Delphi modes treat the field name as a simple offset.
+asmr_e_wrong_scale_factor=07019_E_Nieprawidˆowa skala
+% The scale factor given is wrong, only 1,2,4 and 8 are allowed
+asmr_e_multiple_index=07020_E_U¾ycie wielu rejestr¢w indeksu
+% You are trying to use more than one index register
+asmr_e_invalid_operand_type=07021_E_Nieprawidˆowy typ operandu
+% The operand type doesn't match with the opcode used
+asmr_e_invalid_string_as_opcode_operand=07022_E_Nieprawidˆowy string jako operand: $1
+% The string specified as operand is not correct with this opcode
+asmr_w_CODE_and_DATA_not_supported=07023_W_@CODE i @DATA nieobsˆugiwane
+% @CODE and @DATA are unsupported and are ignored.
+asmr_e_null_label_ref_not_allowed=07024_E_Puste etykiety referencji s¥ niedozwolone
+asmr_e_expr_zero_divide=07025_E_Dzielenie przez zero
+% There is a division by zero in a constant expression
+asmr_e_expr_illegal=07026_E_Nieprawidˆowe wyra¾enie
+% There is an illegal expression in a constant expression
+asmr_e_escape_seq_ignored=07027_E_Sekwencja zignorowana: $1
+% There is a C-styled string, but the escape sequence in the string
+% is unknown, and is therefore ignored
+asmr_e_invalid_symbol_ref=07028_E_Nieprawidˆowa referencja symbolu
+asmr_w_fwait_emu_prob=07029_W_Fwait mo¾e powodowa† problemy emulacji z emu387
+asmr_w_fadd_to_faddp=07030_W_$1 bez operandu przetˆumaczone na $1P
+asmr_w_enter_not_supported_by_linux=07031_W_Instrukcja ENTER nie jest obsˆugiwana przez j¥dro Linuksa
+% ENTER instruction can generate a stack page fault that is not
+% caught correctly by the i386 Linux page handler.
+asmr_w_calling_overload_func=07032_W_Wywoˆanie przeci¥¾onej funkcji z poziomu asemblera
+% There is a call to an overloaded method in the assembler block,
+% this might be the sign there is a problem
+asmr_e_unsupported_symbol_type=07033_E_Nieobsˆugiwany typ symbolu dla operandu
+asmr_e_constant_out_of_bounds=07034_E_Warto˜† staˆa przekracza zakres
+asmr_e_error_converting_decimal=07035_E_Bˆ¥d konwersji liczby dziesi©tnej $1
+% A constant decimal value does not have the correct syntax
+asmr_e_error_converting_octal=07036_E_Bˆ¥d konwersji liczby ¢semkowej $1
+% A constant octal value does not have the correct syntax
+asmr_e_error_converting_binary=07037_E_Bˆ¥d konwersji liczby dw¢jkowej $1
+% A constant binary value does not have the correct syntax
+asmr_e_error_converting_hexadecimal=07038_E_Bˆ¥d konwersji liczby szesnastkowej $1
+% A constant hexadecimal value does not have the correct syntax
+asmr_h_direct_global_to_mangled=07039_H_$1 przetˆumaczone na $2
+asmr_w_direct_global_is_overloaded_func=07040_W_$1 jest przypisane do przeci¥¾onej funkcji
+asmr_e_cannot_use_SELF_outside_a_method=07041_E_Nie mo¾na u¾y† SELF poza metod¥
+% There is a reference to the \var{self} symbol while it is not
+% allowed. \var{self} can only be referenced inside methods
+asmr_e_cannot_use_OLDEBP_outside_nested_procedure=07042_E_Nie mo¾na u¾y† OLDEBP poza zagnie¾d¾on¥ procedur¥
+% There is a reference to the \var{oldebp} symbol while it is not
+% allowed. \var{oldebp} can only be referenced inside nested routines
+asmr_e_void_function=07043_W_Procedury nie mog¥ zwraca† warto˜ci w kodzie asemblera
+% Trying to return a value while in a procedure. A procedure
+% does not have any return value
+asmr_e_SEG_not_supported=07044_E_SEG nie obsˆugiwane
+asmr_e_size_suffix_and_dest_dont_match=07045_E_Przyrostek okre˜laj¥cy rozmiar nie pasuje do «r¢dˆa lub celu
+% The register size and the opcode size suffix don't match. This is
+% probably an error in the assembler statement
+asmr_w_size_suffix_and_dest_dont_match=07046_W_Przyrostek okre˜laj¥cy rozmiar nie pasuje do «r¢dˆa lub celu
+% The register size and the opcode size suffix don't match. This is
+% probably an error in the assembler statement
+asmr_e_syntax_error=07047_E_Bˆ¥d skˆadni asemblera
+% There is an assembler syntax error
+asmr_e_invalid_opcode_and_operand=07048_E_Nieprawidˆowa kombinacja opkodu i operandu
+% The opcode cannot be used with this type of operand
+asmr_e_syn_operand=07049_E_Bˆ¥d skˆadni asemblera w operandzie
+asmr_e_syn_constant=07050_E_Bˆ¥d skˆadni asemblera w staˆej
+asmr_e_invalid_string_expression=07051_E_Nieprawidˆowe wyra¾enie ze stringiem
+asmr_w_const32bit_for_address=07052_W_Staˆa $1 prawdopodobnie nie powinna by† wska«nikiem
+% A constant expression represents an address which does not fit
+% into a pointer. The address is probably incorrect
+asmr_e_unknown_opcode=07053_E_Nieznany opkod $1
+% This opcode is not known
+asmr_e_invalid_or_missing_opcode=07054_E_Nieprawidˆowy opkod lub brak opkodu
+asmr_e_invalid_prefix_and_opcode=07055_E_Nieprawidˆowa kombinacja prefiksu i opkodu: $1
+asmr_e_invalid_override_and_opcode=07056_E_Nieprawidˆowa kombinacja override i opkodu: $1
+asmr_e_too_many_operands=07057_E_Zbyt du¾o operand¢w
+% There are too many operands for this opcode. Check your
+% assembler syntax
+asmr_w_near_ignored=07058_W_NEAR zignorowane
+asmr_w_far_ignored=07059_W_FAR zignorowane
+asmr_e_dup_local_sym=07060_E_Zduplikowany symbol lokalny $1
+asmr_e_unknown_local_sym=07061_E_Niezdefiniowany symbol lokalny $1
+asmr_e_unknown_label_identifier=07062_E_Nieznana etykieta $1
+asmr_e_invalid_register=07063_E_Nieprawidˆowa nazwa rejestru
+% There is an unknown register name used as operand.
+asmr_e_invalid_fpu_register=07064_E_Nieprawidˆowa nazwa rejestru zmiennoprzecinkowego
+% There is an unknown register name used as operand.
+asmr_w_modulo_not_supported=07066_W_Modulo nieobsˆugiwane
+asmr_e_invalid_float_const=07067_E_Nieprawidˆowa staˆa zmiennoprzecinkowa $1
+% The floating point constant declared in an assembler block is
+% invalid.
+asmr_e_invalid_float_expr=07068_E_Nieprawidˆowe wyra¾enie zmiennoprzecinkowe
+% The floating point expression declared in an assembler block is
+% invalid.
+asmr_e_wrong_sym_type=07069_E_Nieprawidˆowy typ symbolu
+asmr_e_cannot_index_relative_var=07070_E_Nie mo¾na ideksowa† rejestrem zmiennej lokalnej/parametru
+% Trying to index using a base register a symbol which is already relative
+% to a register. This is not possible, and will probably lead to crashes.
+asmr_e_invalid_seg_override=07071_E_Invalid segment override expression
+asmr_w_id_supposed_external=07072_W_Identifier $1 supposed external
+% There is a reference to an undefined symbol. This will not result
+% in an error, since the symbol might be external, but may cause
+% problems at link time if the symbol is not defined anywhere.
+asmr_e_string_not_allowed_as_const=07073_E_Stringi nie mog¥ by† staˆymi
+% Character strings are not allowed as constants.
+asmr_e_no_var_type_specified=07074_Nie okre˜lono typu zmiennej
+% The syntax expects a type idenfitifer after the dot, but
+% none was found.
+asmr_w_assembler_code_not_returned_to_text=07075_E_brak powrotu do sekcji text w kodzie asemblera
+% There was a directive in the assembler block to change sections,
+% but there is a missing return to the text section at the end
+% of the assembler block. This might cause errors during link time.
+asmr_e_not_directive_or_local_symbol=07076_E_To nie jest ani dyrektywa, ani symbol lokalny: $1
+% This symbol is unknown.
+asmr_w_using_defined_as_local=07077_E_U¾ycie zdefiniowanej nazwy jako lokalnej etykiety
+asmr_e_dollar_without_identifier=07078_E_Brak identyfikatora przy znaku dolara
+% A constant expression has an identifier which does not start with
+% the $ symbol.
+asmr_w_32bit_const_for_address=07079_W_32bitowa staˆa u¾yta jako adres
+% A constant was used as an address. This is probably an error,
+% since using absolute addresses will probably not work.
+asmr_n_align_is_target_specific=07080_N_.align nie jest przeno˜ne mi©dzy platformami, u¾yj .balign lub .p2align
+% Using the .align directive is platform specific, and its meaning will vary
+% from one platform to another.
+asmr_e_cannot_access_field_directly_for_parameters=07081_E_Nie mo¾na odwoˆywa† si© bezpo˜rednio do p¢l parametr¢w
+% You should load the parameter first into a register and then access the
+% fields using that register.
+asmr_e_cannot_access_object_field_directly=07082_E_Nie mo¾na odwoˆywa† si© bezpo˜rednio do p¢l obiekt¢w/klas
+% You should load the self pointer first into a register and then access the
+% fields using the register as base. By default the self pointer is available
+% in the esi register on i386.
+asmr_e_unable_to_determine_reference_size=07083_E_Nie okre˜lono rozmiaru operandu
+% You should specify explicitly a size for the reference, because
+% the compiler is unable to determine what size (byte,word,dword,etc.) it
+% should use for the reference.
+asmr_e_cannot_use_RESULT_here=07084_E_Nie mo¾na u¾y† RESULT w tej funkcji
+% Some functions which return complex types cannot use the \var{result}
+% keyword.
+asmr_w_adding_explicit_args_fXX=07086_W_"$1" bez operandu przetˆumaczone na "$1 %st,%st(1)"
+asmr_w_adding_explicit_first_arg_fXX=07087_W_"$1 %st(n)" przetˆumaczone na "$1 %st,%st(n)"
+asmr_w_adding_explicit_second_arg_fXX=07088_W_"$1 %st(n)" przetˆumaczone na "$1 %st(n),%st"
+asmr_e_invalid_char_smaller=07089_E_Znak < niedozwolony w tym miejscu
+% The shift operator requires the << characters. Only one
+% of those characters was found.
+asmr_e_invalid_char_greater=07090_E_Znak > niedozwolony w tym miejscu
+% The shift operator requires the >> characters. Only one
+% of those characters was found.
+asmr_w_align_not_supported=07093_W_ALIGN nieobsˆugiwane
+asmr_e_no_inc_and_dec_together=07094_E_Inc i Dec nie mog¥ wyst©powa† razem
+% Trying to use an increment and a decrement within the same
+% opcode on the 680x0. This is impossible.
+asmr_e_invalid_reg_list_in_movem=07095_E_Nieprawidˆowa lista rejestr¢w dla movem
+% Trying to use the \var{movem} opcode with invalid registers
+% to save or restore.
+asmr_e_invalid_reg_list_for_opcode=07096_E_Nieprawidˆowa lista rejestr¢w dla opkodu
+asmr_e_higher_cpu_mode_required=07097_E_Ta instrukcja wymaga wy¾szego typu procesora ($1)
+% Trying to use an instruction which is not supported in the current
+% cpu mode. Use a higher cpu generation to be able to use this
+% opcode in your assembler block
+asmr_w_unable_to_determine_reference_size_using_dword=07098_W_Nie okre˜lono rozmiaru operand¢w, domy˜lne u¾ycie DWORD
+% You should specify explicitly a size for the reference, because
+% the compiler is unable to determine what size (byte,word,dword,etc.) it
+% should use for the reference. This warning is only used in Delphi mode where
+% it falls back to use DWORD as default.
+asmr_e_illegal_shifterop_syntax=07099_E_Bˆ¥d skˆadni przy operandzie shifter
+% ARM only; ARM assembler supports a so called shifter operand. The used syntax isn't
+% a valid shifter operand. Example for an operation with shifter operand:
+% \begin{verbatim}
+% asm
+% orr r2,r2,r2,lsl #8
+% end;
+% \end{verbatim}
+#
+# Assembler/binary writers
+#
+# 08018 is the last used one
+#
+asmw_f_too_many_asm_files=08000_F_Zbyt du¾o plik¢w asemblera
+% With smartlinking enabled, there are too many assembler
+% files generated. Disable smartlinking.
+asmw_f_assembler_output_not_supported=08001_F_Wybrany typ wyj˜ciowy asemblera nieobsˆugiwany
+asmw_f_comp_not_supported=08002_F_Comp nieobsˆugiwany
+asmw_f_direct_not_supported=08003_F_Direct nieobsˆugiwane przy zapisywaniu bezpo˜rednim
+% Direct assembler mode is not supported for binary writers.
+asmw_e_alloc_data_only_in_bss=08004_E_Alokacja danych jest dozwolona tylko w sekcji bss
+asmw_f_no_binary_writer_selected=08005_F_Nie wybrano sposobu zapisywania binari¢w
+asmw_e_opcode_not_in_table=08006_E_Asm: Brak opkodu $1 w tablicy
+asmw_e_invalid_opcode_and_operands=08007_E_Asm: $1 nieprawidˆowa kombinacja opkodu i operand¢w
+asmw_e_16bit_not_supported=08008_E_Asm: 16bitowe referencje nieobsˆugiwane
+asmw_e_invalid_effective_address=08009_E_Asm: Nieprawidˆowy adres efektywny
+asmw_e_immediate_or_reference_expected=08010_E_Asm: Immediate or reference expected
+asmw_e_value_exceeds_bounds=08011_E_Asm: $1 warto˜† przekracza zakres $2
+asmw_e_short_jmp_out_of_range=08012_E_Asm: Kr¢tki skok poza zasi©g $1
+asmw_e_undefined_label=08013_E_Asm: Nieznana etykieta $1
+asmw_e_comp_not_supported=08014_E_Asm: Typ Comp nieobsˆugiwany dla tego celu
+asmw_e_extended_not_supported=08015_E_Asm: Typ Extended nieobsˆugiwany dla tego celu
+asmw_e_duplicate_label=08016_E_Asm: Zduplikowana etykieta $1
+asmw_e_redefined_label=08017_E_Asm: Etykieta powt¢rnie zdefiniowana $1
+asmw_e_first_defined_label=08018_E_Asm: Najpierw zdefiniowana tutaj
+asmw_e_invalid_register=08019_E_Asm: Nieprawidˆowy rejestr $1
+
+#
+# Executing linker/assembler
+#
+# 09034 is the last used one
+#
+# BeginOfTeX
+%
+% \section{Errors of assembling/linking stage}
+% This section lists errors that occur when the compiler is processing the
+% command line or handling the configuration files.
+% \begin{description}
+exec_w_source_os_redefined=09000_W_Zmieniono «r¢dˆowy system operacyjny
+exec_i_assembling_pipe=09001_I_Asemblowanie (potok) $1
+exec_d_cant_create_asmfile=09002_E_Nie mo¾na utworzy† plik¢w asemblera: $1
+% The mentioned file can't be created. Check if you have got
+% access permissions to create this file
+exec_e_cant_create_objectfile=09003_E_Nie mo¾na utworzy† pliku: $1
+% The mentioned file can't be created. Check if you've
+% got access permissions to create this file
+exec_e_cant_create_archivefile=09004_E_Nie mo¾na utworzy† pliku: $1
+% The mentioned file can't be created. Check if you've
+% access permissions to create this file
+exec_e_assembler_not_found=09005_E_Assembler $1 nie znaleziony, przeˆ¥czenie na zewn©trzn¥ asemblacj©
+exec_t_using_assembler=09006_T_U¾ywanie assemblera: $1
+exec_e_error_while_assembling=09007_E_Bˆ¥d asemblera, kod wyj˜cia $1
+% There was an error while assembling the file using an external assembler.
+% Consult the documentation of the assembler tool to find out more information
+% on this error.
+exec_e_cant_call_assembler=09008_E_Nie mo¾na wywoˆa† asemblera, bˆ¥d $1 przeˆ¥czenie na zewn©trzn¥ asemblacj©
+exec_i_assembling=09009_I_Asemblowanie $1
+exec_i_assembling_smart=09010_I_Asemblowanie do linkowania smart $1
+exec_w_objfile_not_found=09011_W_Obiekt $1 nieodnaleziony, linkowanie mo¾e si© nie powie˜†!
+% One of the object file is missing, and linking will probably fail.
+% Check your paths.
+exec_w_libfile_not_found=09012_W_Biblioteka $1 nieodnaleziona, Linkowanie mo¾e si© nie powie˜†!
+% One of the library file is missing, and linking will probably fail.
+% Check your paths.
+exec_e_error_while_linking=09013_E_Bˆ¥d podczas linkowania
+% Generic error while linking.
+exec_e_cant_call_linker=09014_E_Nie mo¾na wywoˆa† linkera, przeˆ¥czenie na zewn©trzne linkowanie
+exec_i_linking=09015_I_Linkowanie $1
+exec_e_util_not_found=09016_E_Narz©dzie $1 nieodnalezione, przeˆ¥czenie na zewn©trzne linkowanie
+exec_t_using_util=09017_T_Uruchamianie $1
+exec_e_exe_not_supported=09018_E_Tworzenie plik¢w wykonywalnych nieobsˆugiwane
+exec_e_dll_not_supported=09019_E_Tworzenie bibliotek dynamicznych/wsp¢ˆdzielonych nieobsˆugiwane
+exec_i_closing_script=09020_I_Zamykanie skryptu $1
+exec_e_res_not_found=09021_E_Kompilator zasob¢w nieodnaleziony, przeˆ¥czenie na tryb zewn©trzny
+exec_i_compilingresource=09022_I_Kompilacja zasobu $1
+exec_t_unit_not_static_linkable_switch_to_smart=09023_T_Moduˆ $1 nie mo¾e by† linkowany statycznie, przeˆ¥czenie na linkowanie smart
+exec_t_unit_not_smart_linkable_switch_to_static=09024_T_Moduˆ $1 nie moze by† linkowany smart, przeˆ¥czenie na linkowanie statyczne
+exec_t_unit_not_shared_linkable_switch_to_static=09025_T_Moduˆ $1 nie mo¾e by† linkowany dynamicznie, przeˆ¥czenie na linkowanie statyczne
+exec_e_unit_not_smart_or_static_linkable=09026_E_Moduˆ $1 nie mo¾e by† linkowany statycznie ani smart
+exec_e_unit_not_shared_or_static_linkable=09027_E_Moduˆ $1 nie mo¾e by† linkowany statycznie ani dynamicznie
+%\end{description}
+# EndOfTeX
+
+#
+# Executable information
+#
+execinfo_f_cant_process_executable=09128_F_Nie mo¾na przetwarza† pliku $1
+execinfo_f_cant_open_executable=09129_F_Nie mo¾na otworzy† pliku wykonywalnego $1
+execinfo_x_codesize=09130_X_Rozmiar kodu: $1 bajt¢w
+execinfo_x_initdatasize=09131_X_Rozmiar zainicjowanych danych: $1 bajt¢w
+execinfo_x_uninitdatasize=09132_X_Rozmiar niezainicjowanych danych: $1 bajt¢w
+execinfo_x_stackreserve=09133_X_Zarezerwowany rozmiar stosu: $1 bajt¢w
+execinfo_x_stackcommit=09134_X_Aktywny rozmiar stosu: $1 bajt¢w
+
+#
+# Unit loading
+#
+# 10041 is the last used one
+#
+# BeginOfTeX
+% \section{Unit loading messages.}
+% This section lists all messages that can occur when the compiler is
+% loading a unit from disk into memory. Many of these mesages are
+% informational messages.
+% \begin{description}
+unit_t_unitsearch=10000_T_Poszukiwanie moduˆu: $1
+% When you use the \var{-vt}, the compiler tells you where it tries to find
+% unit files.
+unit_t_ppu_loading=10001_T_Otwieranie PPU $1
+% When the \var{-vt} switch is used, the compiler tells you
+% what units it loads.
+unit_u_ppu_name=10002_U_Nazwa PPU: $1
+% When you use the \var{-vu} flag, the unit name is shown.
+unit_u_ppu_flags=10003_U_Flagi PPU: $1
+% When you use the \var{-vu} flag, the unit flags are shown.
+unit_u_ppu_crc=10004_U_Crc PPU: $1
+% When you use the \var{-vu} flag, the unit CRC check is shown.
+unit_u_ppu_time=10005_U_Czas PPU: $1
+% When you use the \var{-vu} flag, the time the unit was compiled is shown.
+unit_u_ppu_file_too_short=10006_U_Plik PPU zbyt kr¢tki
+% The ppufile is too short, not all declarations are present.
+unit_u_ppu_invalid_header=10007_U_Nieprawidˆowy nagˆ¢wek PPU (brak PPU na pocz¥tku)
+% A unit file contains as the first three bytes the ascii codes of \var{PPU}
+unit_u_ppu_invalid_version=10008_U_Nieprawidˆowa wersja PPU $1
+% This unit file was compiled with a different version of the compiler, and
+% cannot be read.
+unit_u_ppu_invalid_processor=10009_U_PPU jest skompilowany dla innego procesora
+% This unit file was compiled for a different processor type, and
+% cannot be read
+unit_u_ppu_invalid_target=10010_U_PPU skompilowany dla innej platformy docelowej
+% This unit file was compiled for a different target, and
+% cannot be read
+unit_u_ppu_source=10011_U_r¢dˆo PPU: $1
+% When you use the \var{-vu} flag, the unit CRC check is shown.
+unit_u_ppu_write=10012_U_Zapisywanie $1
+% When you specify the \var{-vu} switch, the compiler will tell you where it
+% writes the unit file.
+unit_f_ppu_cannot_write=10013_F_Nie mo¾na zapisa† pliku PPU
+% An error occurred when writing the unit file.
+unit_f_ppu_read_error=10014_F_Bˆ¥d podczas czytania pliku PPU
+% This means that the unit file was corrupted, and contains invalid
+% information. Recompilation will be necessary.
+unit_f_ppu_read_unexpected_end=10015_F_Nieoczekiwane zakoäczenie pliku PPU
+% Unexpected end of file. This may mean that the PPU file is
+% corrupted.
+unit_f_ppu_invalid_entry=10016_F_Nieprawidˆowy plik PPU: $1
+% The unit the compiler is trying to read is corrupted, or generated with a
+% newer version of the compiler.
+unit_f_ppu_dbx_count_problem=10017_F_Bˆ¥d podczas liczenia PPU Dbx
+% There is an inconsistency in the debugging information of the unit.
+unit_e_illegal_unit_name=10018_E_Nieprawidˆowa nazwa moduˆu: $1
+% The name of the unit does not match the file name.
+unit_f_too_much_units=10019_F_Zbyt du¾o moduˆ¢w
+% \fpc has a limit of 1024 units in a program. You can change this behavior
+% by changing the \var{maxunits} constant in the \file{files.pas} file of the
+% compiler, and recompiling the compiler.
+unit_f_circular_unit_reference=10020_F_Zap©tlone nawi¥zanie pomi©dzy moduˆami $1 i $2
+% Two units are using each other in the interface part. This is only allowed
+% in the \var{implementation} part. At least one unit must contain the other one
+% in the \var{implementation} section.
+unit_f_cant_compile_unit=10021_F_Nie mo¾na skompilowa† moduˆu $1, brak «r¢deˆ
+% A unit was found that needs to be recompiled, but no sources are
+% available.
+unit_f_cant_find_ppu=10022_F_Nie mo¾na znale«† moduˆu $1
+% You tried to use a unit of which the PPU file isn't found by the
+% compiler. Check your config files for the unit pathes
+unit_w_unit_name_error=10023_W_Nie znaleziono moduˆu $1 ale istnieje $2
+unit_f_unit_name_error=10024_F_Szukano moduˆu $1 ale znaleziono tylko $2
+% Dos truncation of 8 letters for unit PPU files
+% may lead to problems when unit name is longer than 8 letters.
+unit_w_switch_us_missed=10025_W_Kompilowanie moduˆu System wymaga u¾ycia przeˆ¥cznika -Us
+% When recompiling the system unit (it needs special treatment), the
+% \var{-Us} must be specified.
+unit_f_errors_in_unit=10026_F_Napotkano $1 bˆ©d¢w podczas kompilacji moduˆu, zatrzymanie
+% When the compiler encounters a fatal error or too many errors in a module
+% then it stops with this message.
+unit_u_load_unit=10027_U_adowanie z $1 ($2) moduˆu $3
+% When you use the \var{-vu} flag, which unit is loaded from which unit is
+% shown.
+unit_u_recompile_crc_change=10028_U_Rekompilacja $1, suma kontrolna zmieniona dla $2
+unit_u_recompile_source_found_alone=10029_U_Rekompilacja $1, znaleziono tylko «r¢dˆo
+% When you use the \var{-vu} flag, these messages tell you why the current
+% unit is recompiled.
+unit_u_recompile_staticlib_is_older=10030_U_Rekompilacja moduˆu, biblioteka statyczna jest starsza ni¾ plik ppu
+% When you use the \var{-vu} flag, the compiler warns if the static library
+% of the unit are older than the unit file itself.
+unit_u_recompile_sharedlib_is_older=10031_U_Rekompilacja moduˆu, biblioteka wsp¢ˆdzielona jest starsza ni¾ plik ppu
+% When you use the \var{-vu} flag, the compiler warns if the shared library
+% of the unit are older than the unit file itself.
+unit_u_recompile_obj_and_asm_older=10032_U_Rekompilacja moduˆu, obj i asm s¥ starsze ni¾ plik ppu
+% When you use the \var{-vu} flag, the compiler warns if the assembler or
+% object file of the unit are older than the unit file itself.
+unit_u_recompile_obj_older_than_asm=10033_U_Rekompilacja moduˆu, obj jest starszy ni¾ asm
+% When you use the \var{-vu} flag, the compiler warns if the assembler
+% file of the unit is older than the object file of the unit.
+unit_u_parsing_interface=10034_U_Parsowanie cz©˜ci interface moduˆu $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% parsing the interface part of the unit
+unit_u_parsing_implementation=10035_U_Parsowanie cz©˜ci implementation moduˆu $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% parsing the implementation part of the unit
+unit_u_second_load_unit=10036_U_Drugie zaˆadowanie pliku $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% recompiling a unit for the second time. This can happend with interdepend
+% units.
+unit_u_check_time=10037_U_Sprawdzanie pliku PPU: $1 czas: $2
+% When you use the \var{-vu} flag, the compiler show the filename and
+% date and time of the file which a recompile depends on
+### The following two error msgs is currently disabled.
+#unit_h_cond_not_set_in_last_compile=10038_H_Warunek $1 nie byˆ ustawiony na pocz¥tku ostatniej kompilacji moduˆu $2
+#% when recompilation of an unit is required the compiler will check that
+#% the same conditionals are set for the recompiliation. The compiler has
+#% found a conditional that currently is defined, but was not used the last
+#% time the unit was compiled.
+#unit_h_cond_set_in_last_compile=10039_H_Warunek $1 nie byˆ ustawiony na pocz¥tku ostatniej kompilacji moduˆu $2
+#% when recompilation of an unit is required the compiler will check that
+#% the same conditionals are set for the recompiliation. The compiler has
+#% found a conditional that was used the last time the unit was compiled, but
+#% the conditional is currently not defined.
+unit_w_cant_compile_unit_with_changed_incfile=10040_W_Nie mo¾na skompilowa† moduˆu $1, znaleziono zmodyfikowane pliki include
+% A unit was found to have modified include files, but
+% some source files were not found, so recompilation is impossible.
+unit_h_source_modified=10041_H_Plik $1 jest nowszy ni¾ plik $2
+% A modified source file for a unit was found that was compiled with the
+% release flag (-Ur). The unit will not implicitly be recompiled because
+% this release flag is set.
+unit_u_ppu_invalid_fpumode=10042_U_U¾ycie moduˆu skompilowanego z innym formatem zapisu liczb zmiennoprzecinkowych
+% Trying to compile code while using units which were not compiled with
+% the same floating point format mode. Either all code should be compiled
+% with FPU emulation on, or with FPU emulation off.
+unit_u_loading_interface_units=10043_U_adowanie moduˆ¢w z cz©«ci interface moduˆu $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% loading the units defined in the interface part of the unit.
+unit_u_loading_implementation_units=10044_U_adowanie moduˆ¢w z cz©«ci implementation moduˆu $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% loading the units defined in the implementation part of the unit.
+unit_u_interface_crc_changed=10045_U_Zmieniona suma CRC sekcji interface moduˆu $1
+% When you use the \var{-vu} flag, the compiler warns that it the
+% CRC calculated for the interface has been changed after the implementation
+% has been parsed.
+unit_u_implementation_crc_changed=10046_U_Zmieniona suma CRC sekcji implementation moduˆu $1
+% When you use the \var{-vu} flag, the compiler warns that it the
+% CRC calculated has been changed after the implementation
+% has been parsed.
+unit_u_finished_compiling=10047_U_Zakoäczono kompilacj© moduˆu $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has finished compiling the unit.
+unit_u_add_depend_to=10048_U_Dodanie zale¾no˜ci $1 do $2
+% When you use the \var{-vu} flag, the compiler warns that it
+% has added a dependency between the two units.
+unit_u_no_reload_is_caller=10049_U_Omini©cie przeˆadowania moduˆu, to ten sam moduˆ: $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has will not reload the unit because it is the unit that wants
+% to load this unit
+unit_u_no_reload_in_second_compile=10050_U_Omini©cie przeˆadowania moduˆu, trwa druga kompilacaja: $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has will not reload the unit because it is already in a second recompile
+unit_u_flag_for_reload=10051_U_Flaga do przeˆadowania: $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has to reload the unit
+unit_u_forced_reload=10052_U_Wymuszone przeˆadowanie moduˆu
+% When you use the \var{-vu} flag, the compiler warns that it
+% has is reloading the unit because it was required
+unit_u_previous_state=10053_U_Poprzedni stan moduˆu $1: $2
+% When you use the \var{-vu} flag, the compiler shows the
+% previous state of the unit
+unit_u_second_compile_unit=10054_U_Ju¾ kompilowane $1, ustawienie drugiej kompilacji
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% recompiling a unit for the second time. This can happend with interdepend
+% units.
+unit_u_loading_unit=10055_U_adowanie moduˆu $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% loading the unit.
+unit_u_finished_loading_unit=10056_U_Zakoäczenie ˆadowania moduˆu $1
+% When you use the \var{-vu} flag, the compiler warns that it finished
+% loading the unit.
+unit_u_registering_new_unit=10057_U_Rejestrowanie nowego moduˆu $1
+% When you use the \var{-vu} flag, the compiler warns that it has
+% found a new unit and registers it in the internal lists.
+unit_u_reresolving_unit=10058_U_Powt¢rne odnajdowanie moduˆu $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has to recalculate the internal data of the unit
+unit_u_skipping_reresolving_unit=10059_U_Omini©cie powt¢rnego odnajdowania moduˆu $1, ci¥gle ˆaduje u¾ywane moduˆy
+% When you use the \var{-vu} flag, the compiler warns that it
+% skips to recalculate the internal data of the unit because there
+% is no data to recalculate
+% \end{description}
+# EndOfTeX
+
+#
+# Options
+#
+# 11039 is the last used one
+#
+option_usage=11000_O_$1 [opcje] <nazwapliku> [opcje]
+# BeginOfTeX
+%
+% \section{Command-line handling errors}
+% This section lists errors that occur when the compiler is processing the
+% command line or handling the configuration files.
+% \begin{description}
+option_only_one_source_support=11001_W_Obsˆugiwany tylko jeden plik «r¢dˆowy
+% You can specify only one source file on the command line. The first
+% one will be compiled, others will be ignored. This may indicate that
+% you forgot a \var{'-'} sign.
+option_def_only_for_os2=11002_W_Plik DEF mo¾e by† stworzony tylko pod OS/2
+% This option can only be specified when you're compiling for OS/2
+option_no_nested_response_file=11003_E_Zagnie¾d¾enia plik¢w nieobsˆugiwane
+% you cannot nest response files with the \var{@file} command-line option.
+option_no_source_found=11004_F_Brak nazwy pliku w lini poleceä
+% The compiler expects a source file name on the command line.
+option_no_option_found=11005_N_Brak opcji w pliku konfiguracyjnym $1
+% The compiler didn't find any option in that config file.
+option_illegal_para=11006_E_Nieprawidˆowy parametr: $1
+% You specified an unknown option.
+option_help_pages_para=11007_H_-? wy˜wietla pomoc
+% When an unknown option is given, this message is diplayed.
+option_too_many_cfg_files=11008_F_Za du¾o zagnie¾d¾onych plik¢w konfiguracyjnych
+% You can only nest up to 16 config files.
+option_unable_open_file=11009_F_Nie mo¾na otworzy† pliku konfiguracyjnego $1
+% The option file cannot be found.
+option_reading_further_from=11010_D_Czytanie dalszych opcji z $1
+% Displayed when you have notes turned on, and the compiler switches
+% to another options file.
+option_target_is_already_set=11011_W_Cel jest ju¾ ustawiony na: $1
+% Displayed if more than one \var{-T} option is specified.
+option_no_shared_lib_under_dos=11012_W_Biblioteki wsp¢ˆdzielone nie s¥ obsˆugiwane w DOSie, reverting to static
+% If you specify \var{-CD} for the \dos platform, this message is displayed.
+% The compiler supports only static libraries under \dos
+option_too_many_ifdef=11013_F_Za du¾o IF(N)DEF
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_too_many_endif=11014_F_Za du¾o ENDIF
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_too_less_endif=11015_F_Warunek wci¥¾ otwarty na koäcu pliku
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_no_debug_support=11016_W_Generowanie informacji do debugowania nieobsˆugiwane przez t¥ wersj© kompilatora
+% It is possible to have a compiler executable that doesn't support
+% the generation of debugging info. If you use such an executable with the
+% \var{-g} switch, this warning will be displayed.
+option_no_debug_support_recompile_fpc=11017_H_Spr¢buj przekompilowa† z -dGDB
+% It is possible to have a compiler executable that doesn't support
+% the generation of debugging info. If you use such an executable with the
+% \var{-g} switch, this warning will be displayed.
+option_obsolete_switch=11018_E_U¾ycie przedawnionego przeˆ¥cznika $1
+% this warns you when you use a switch that is not needed/supported anymore.
+% It is recommended that you remove the switch to overcome problems in the
+% future, when the switch meaning may change.
+option_obsolete_switch_use_new=11019_E_U¾ycie przedawnionego przeˆ¥cznika $1, prosz© u¾y† $2
+% this warns you when you use a switch that is not supported anymore. You
+% must now use the second switch instead.
+% It is recommended that you change the switch to overcome problems in the
+% future, when the switch meaning may change.
+option_switch_bin_to_src_assembler=11020_N_Przeˆ¥czenie na domy˜lny zapis asemblera
+% this notifies you that the assembler has been changed because you used the
+% -a switch which can't be used with a binary assembler writer.
+option_incompatible_asm=11021_W_Wybrane wyj˜cie asemblera "$1" nie jest zgodne z "$2"
+option_asm_forced=11022_W_Wymuszenie u¾ycia asemblera "$1"
+% The assembler output selected can not generate
+% object files with the correct format. Therefore, the
+% default assembler for this target is used instead.
+option_using_file=11026_T_Czytanie opcji z pliku $1
+% Options are also read from this file
+option_using_env=11027_T_Czytanie opcji ze zmiennej ˜rodowiskowej $1
+% Options are also read from this environment string
+option_handling_option=11028_D_Obsˆugiwanie opcji "$1"
+% Debug info that an option is found and will be handled
+option_help_press_enter=11029__*** naci˜nij enter ***
+option_start_reading_configfile=11030_H_Rozpocz©to czytanie pliku konfiguracyjnego $1
+% Starting of config file parsing.
+option_end_reading_configfile=11031_H_Zakoäczono czytanie pliku konfiguracyjnego $1
+% End of config file parsing.
+option_interpreting_option=11032_D_Interpretowanie opcji "$1"
+option_interpreting_firstpass_option=11036_D_Interpretowanie opcji "$1"
+option_interpreting_file_option=11033_D_Interpretowanie opcji plikowej "$1"
+option_read_config_file=11034_D_Czytanie pliku konfiguracyjnego "$1"
+option_found_file=11035_D_Znaleziono nazw© pliku «r¢dˆowego "$1"
+% Additional infos about options, displayed
+% when you have debug option turned on.
+option_code_page_not_available=11039_E_Nieznana strona kodowa
+%\end{description}
+# EndOfTeX
+
+#
+# Logo (option -l)
+#
+option_logo=11023_[
+Free Pascal Compiler wersja $FPCFULLVERSION [$FPCDATE] dla $FPCCPU
+Copyright (c) 1993-2011 by Florian Klaempfl
+]
+
+#
+# Info (option -i)
+#
+option_info=11024_[
+Free Pascal Compiler wersja $FPCVERSION
+
+Data kompilatora : $FPCDATE
+Platforma docelowa: $FPCCPU
+
+Wspierane platformy:
+ $OSTARGETS
+
+Wspierane instrukcje CPU:
+ $INSTRUCTIONSETS
+
+Wspierane instrukcje FPU:
+ $FPUINSTRUCTIONSETS
+
+Ten program jest oparty na GNU General Public Licence
+Przeczytaj COPYING.FPC aby dowiedzie† si© wi©cej
+
+Zgˆaszanie bˆ©d¢w, sugestii itp.
+ http://bugs.freepascal.org
+lub
+ bugs@freepascal.org
+]
+
+#
+# Help pages (option -? and -h)
+#
+# The first character on the line indicates who will display this
+# line, the current possibilities are :
+# * = every target
+# 3 = 80x86 targets
+# 6 = 680x0 targets
+# e = in extended debug mode only
+# P = PowerPC targets
+# S = Sparc targets
+# V = Virtual machine targets
+# The second character also indicates who will display this line,
+# (if the above character was TRUE) the current possibilities are :
+# * = everyone
+# g = with GDB info supported by the compiler
+# O = OS/2
+# L = UNIX systems
+# The third character represents the indentation level.
+#
+option_help_pages=11025_[
+**0*_wpisz + po przeˆ¥czniku aby go aktywowa†, - aby dezaktywowa†
+**1a_kompilator nie usuwa wygenerowanego pliku asemblera
+**2al_wypisuje numery linii do pliku asemblera
+**2an_wypisuje informacje o w©zˆach do pliku asemblera
+*L2ap_u¾ycie potok¢w zamiast tymczasowych plik¢w asemblera
+**2ar_wypisuje alokacje/zwalnianie rejestr¢w do pliku asemblera
+**2at_wypisuje tymczasowe alokacje/zwalnianie do pliku asemblera
+**1A<x>_format wyj˜ciowy:
+**2Adefault_u¾ycie domy˜lnego asemblera
+3*2Aas_asemblacja przy u¾yciu GNU AS
+3*2Anasmcoff_plik coff (Go32v2) przy u¾yciu Nasm
+3*2Anasmelf_plik elf32 (Linux) przy u¾yciu Nasm
+3*2Anasmwin32_plik obj (Win32) przy u¾yciu Nasm
+3*2Anasmwdosx_plik obj (Win32/WDOSX) przy u¾yciu Nasm
+3*2Awasm_plik obj przy u¾yciu Wasm (Watcom)
+3*2Anasmobj_plik obj przy u¾yciu Nasm
+3*2Amasm_plik obj przy u¾yciu Masm (Microsoft)
+3*2Atasm_plik obj przy u¾yciu Tasm (Borland)
+3*2Aelf_bezpo˜redni zapis do pliku elf32 (Linux)
+3*2Acoff_bezpo˜redni zapis do pliku coff (Go32v2)
+3*2Apecoff_bezpo˜redni zapis do pliku pecoff (Win32)
+4*2Aas_asemblacja przy u¾yciu GNU AS
+6*2Aas_o-file (Unix) przy u¾yciu GNU AS
+6*2Agas_asembler GNU Motorola
+6*2Amit_skˆadnia MIT (dawniej GAS)
+6*2Amot_standardowy asembler Motorola
+A*2Aas_asemblacja przy u¾yciu GNU AS
+P*2Aas_asemblacja przy u¾yciu GNU AS
+S*2Aas_asemblacja przy u¾yciu GNU AS
+**1b_generuje informacje przegl¥darki
+**2bl_generuje informacje o lokalnych symbolach
+**1B_budowanie wszystkich moduˆ¢w
+**1C<x>_opcje generacji kodu:
+**2Cc<x>_ustawia domy˜lny spos¢b wywoˆania funkcji/procedur na <x>
+**2CD_tworzenie tak¾e bibliotek dynamicznych (niedost©pne)
+**2Ce_kompilacja z emulowanymi opkodami zmiennoprzecinkowymi
+**2Cf<x>_ustawia u¾ywany zbi¢r instrukcji FPU na <x> (u¾yj "fpc -i", aby zobaczy† mo¾liwe warto˜ci)
+**2Cg_generowanie kodu PIC
+**2Ch<n>_rozmiar sterty w bajtach (pomi©dzy 1023 i 67107840)
+**2Ci_sprawdzanie operacji wej˜cia/wyj˜cia
+**2Cn_pomini©cie etapu linkowania
+**2Co_sprawdzanie przepeˆnienia liczb caˆkowitych
+**2Cp<x>_ustawia u¾ywany zbi¢r instrukcji na <x> (u¾yj "fpc -i", aby zobaczy† mo¾liwe warto˜ci)
+**2Cr_sprawdzanie zakresu
+**2CR_sprawdzanie poprawno˜ci wywoˆywania metod obiekt¢w
+**2Cs<n>_ustawienie rozmiar stosu na <n>
+**2Ct_sprawdzanie stosu
+**2CX_tworzenie bibliotek smartlinked
+**1d<x>_zdefiniowanie symbolu <x>
+*O1D_generacja pliku DEF
+*O2Dd<x>_ustawienie opisu na <x>
+**2Dv<x>_ustawienie wersji DLL na <x>
+*O2Dw_aplikacja PM
+**1e<x>_ustawienie ˜cie¾ki do asemblera i linkera
+**1E_to samo co -Cn
+**1F<x>_ustawianie nazw i ˜cie¾ek:
+**2Fa<x>[,y]_wczytuje <x> (i [y]) zanim zostani¥ wczytane moduˆy z sekcji USES
+**2Fc<x>_ustawienie strony kodowej «r¢deˆ na <x>
+**2FD<x>_ustawienie katalogu z narz©dziami kompilatora
+**2Fe<x>_przekierowanie komunikat¢w o bˆ©dach do pliku <x>
+**2FE<x>_ustawienie katalogu dla skompilowanych program¢w/moduˆ¢w na <x>
+**2Fi<x>_dodanie <x> do ˜cie¾ki include'¢w
+**2Fl<x>_dodanie <x> do ˜cie¾ki bibliotek
+**2FL<x>_u¾ycie <x> jako dynamicznego linkera
+**2Fo<x>_dodanie <x> do ˜cie¾ki obiekt¢w
+**2Fr<x>_ˆadowanie pliku <x> z komunikatami bˆ©d¢w
+**2Fu<x>_dodanie <x> do ˜cie¾ki moduˆ¢w
+**2FU<x>_ustawienie katalogu dla skompilowanych moduˆ¢w, uniewa¾nia -FE
+*g1g_generacja informacji debuggera:
+*g2gc_generacja kodu sprawdzaj¥cego wska«niki
+*g2gd_u¾ycie dbx
+*g2gg_u¾ycie gsym
+*g2gh_u¾ycie moduˆu ˜ledzenia sterty(do wykrywania wyciek¢w pami©ci)
+*g2gl_u¾ycie moduˆu z informacjami o numerach linii programu
+*g2gv_generacja kodu mo¾liwego do ˜ledzenia przy pomocy valgrind
+*g2gw_generacja informacji debuggera dwarf
+**1i_informacje
+**2iD_zwraca dat© kompilatora
+**2iV_zwraca wersj© kompilatora
+**2iSO_zwraca OS kompilatora
+**2iSP_zwraca typ procesora kompilatora
+**2iTO_zwraca docelowy OS
+**2iTP_zwraca docelowy typ kompilatora
+**1I<x>_dodanie <x> do ˜cie¾ki include'¢w
+**1k<x>_podanie <x> do linkera
+**1l_wypisanie logo
+**1M<x>_ustawia tryb j©zyka na <x>
+**2Mfpc_dialekt free pascala (domy˜lny)
+**2Mobjfpc_wˆ¥czenie niekt¢rych rozszerzeä Delphi 2
+**2Mdelphi_kompatybilno˜† z Delphi
+**2Mtp_kompatybilno˜† z TP/BP 7.0
+**2Mgpc_kompatybilno˜† z gpc
+**2Mmac_kompatybilno˜† z dialektami pascala na Macintosha
+**1n_zignorowanie standardowego pliku konfiguracyjnego
+**1N<x>optymalizacje w©zˆ¢w drzewa
+**2Nu_rozwijanie p©tli
+**1o<x>_zmiana nazwy skompilowanego programu na <x>
+3*1O<x>_optymalizacje:
+3*2Og_generacja mniejszego kodu
+3*2OG_generacja szybszego kodu (domy˜lne)
+3*2Or_trzymanie niekt¢rych zmiennych w rejestrach
+3*2Ou_wˆ¥czenie niepewnych optymalizacji (zobacz w dokumentacji)
+3*2O1_optymalizacje pierwszego stopnia (szybkie)
+3*2O2_optymalizacje drugiego stopnia (-O1 + wolniejsze)
+3*2O3_optymalizacje trzeciego stopnia (powtarzane maksymalnie 5 razy -02)
+3*2Op<x>_procesor docelowy:
+3*3Op1_ustawienie procesora docelowego na 386/486
+3*3Op2_ustawienie procesora docelowego na Pentium/PentiumMMX (tm)
+3*3Op3_ustawienie procesora docelowego na PPro/PII/c6x86/K6 (tm)
+6*2Og_generacja mniejszego kodu
+6*2OG_generacja szybszego kodu (domy˜lne)
+6*2Ox_maksymalne optymalizacje (ci¥gle zawieraj¥ B¨DY!!!)
+6*2O0_ustawia docelowy procesor na MC68000
+6*2O2_ustawia docelowy procesor na MC68020+ (domy˜lne)
+**1pg_generacja kodu do profilowania przy pomocy gprof (definiuje FPC_PROFILE)
+**1R<x>_styl asemblera u¾ywanego w «r¢dˆach:
+**2Rdefault_u¾ycie domy˜lnego asemblera
+3*2Ratt_styl AT&T
+3*2Rintel_styl Intel
+6*2RMOT_styl Motorola
+**1S<x>_opcje skˆadni:
+**2S2_to samo co -Mobjfpc
+**2Sc_wspieranie operator¢w C (*=,+=,/= oraz -=)
+**2Sa_doˆ¥czanie kodu asercji
+**2Sd_to samo co -Mdelphi
+**2Se<x>_opcje bˆ©d¢w. <x> jest kombinacj¥:
+**3*_<n> : kompilator zatrzymuje si© po <x> bˆ©dach (domy˜lnie 1)
+**3*_w : kompilator zatrzymuje si© tak¾e na ostrze¾eniach
+**3*_n : kompilator zatrzymuje si© tak¾e na notkach
+**3*_h : kompilator zatrzymuje si© tak¾e na podpowiedziach
+**2Sg_zezwolenie na LABEL i GOTO
+**2Sh_u¾ycie ansistring¢w
+**2Si_wspieranie INLINE w stylu C++
+**2SI<x>_ustawia styl interfejs¢w na <x>
+**3SIcom_interfejsy kompatybilne z COM (domy˜lne)
+**3SIcorba_interfejsy kompatybilne z CORBA
+**2Sm_wspieranie makr jak w C (opcja globalna)
+**2So_to samo co -Mtp
+**2Sp_to samo co -Mgpc
+**2Ss_konstruktory musz¥ mie† nazw© init (destruktory - done)
+**1s_pomini©cie wywoˆania asemblera i linkera
+**2sh_generacja skryptu do linkowania na ho˜cie
+**2st_generacja skryptu do linkowania na celu
+**2sr_omini©cie fazy alokowania rejestr¢w (u¾ywaj z -alr)
+**1T<x>_docelowy system operacyjny:
+3*2Temx_OS/2 na EMX (wliczaj¥c EMX/RSX extender)
+3*2Tfreebsd_FreeBSD
+3*2Tgo32v2_DJ Delorie DOS extender - wersja 2
+3*2Tlinux_Linux
+3*2Tnetbsd_NetBSD
+3*2Tnetware_Novell Netware Module (clib)
+3*2Tnetwlibc_Novell Netware Module (libc)
+3*2Topenbsd_OpenBSD
+3*2Tos2_OS/2 / eComStation
+3*2Tsunos_SunOS/Solaris
+3*2Twatcom_DOS extendery zgodne z Watcomem
+3*2Twdosx_WDOSX DOS extender
+3*2Twin32_32-bitowy Windows
+4*2Tlinux_Linux
+6*2Tamiga_Commodore Amiga
+6*2Tatari_Atari ST/STe/TT
+6*2Tlinux_Linux-68k
+6*2Tmacos_Macintosh m68k (nie wspierane)
+6*2Tpalmos_PalmOS
+A*2Tlinux_Linux
+P*2Tdarwin_Darwin i MacOS X na PowerPC
+P*2Tlinux_Linux na PowerPC
+P*2Tmacos_MacOS (klasyczny) na PowerPC
+P*2Tmorphos_MorphOS
+S*2Tlinux_Linux
+**1u<x>_usuni©cie symbolu <x>
+**1U_opcje moduˆ¢w:
+**2Un_pomini©cie sprawdzania nazwy moduˆu
+**2Ur_generacja moduˆu do wydania (release)
+**2Us_kompilacja moduˆu system
+**1v<x>_obszerne opisy. <x> jest kombinacj¥ nast©puj¥cych liter i cyfr:
+**2*_e : pokazuje bˆ©dy (domy˜lne) 0 : nic nie pokazuje (opr¢cz bˆ©d¢w)
+**2*_w : pokazuje ostrze¾enia u : pokazuje informacje o moduˆach
+**2*_n : pokazuje notki t : pokazuje pr¢bowane/u¾yte pliki
+**2*_h : pokazuje podpowiedzi c : pokazuje warunki
+**2*_i : pokazuje og¢lne informacje d : pokazuje informacje debugowania
+**2*_l : pokazuje numery lini r : tryb kompatybilno˜ci z Rhide/GCC
+**2*_a : pokazuje wszystko x : informacje o pliku exe (tylko Win32)
+**2*_v : zapisuje plik fpcdebug.txt p : zapisuje tree.log z drzewem
+**2*_ z du¾¥ ilo˜ci¥ informacji parsowania
+3*1W<x>_opcje dla Win32 i podobnych
+3*2WB_tworzenie relokacyjnego obrazu
+3*2WB<x>_ustawienie bazy obrazu na szesnastkow¥ warto˜† <x>
+3*2WC_aplikacja konsolowa
+3*2WD_u¾ycie DEFFILE do eksportu funkcji z DLLa lub EXE
+3*2WF_aplikacja peˆnoekranowa (tylko OS/2)
+3*2WG_aplikacja graficzna
+3*2WN_nie generuje kodu relokacji (potrzebne do debugowania)
+3*2WR_generuje kod relokacji
+P*2WC_aplikacja konsolowa (tylko MacOS)
+P*2WG_aplikacja graficzna (tylko MacOS)
+P*2WT_aplikacja narz©dziowa (narz©dzie MPW, tylko MacOS)
+**1X_opcje plik¢w wykonywalnych:
+**2Xc_podaje --shared do linkera (tylko Unix)
+**2Xd_nie u¾ywa standardowej ˜cie¾ki bibliotek (potrzebne do cross-kompilacji)
+**2XD_linkowanie dynamiczne (definiuje FPC_LINK_DYNAMIC)
+**2Xm_generuje link map
+**2XM<x>_ustawia nazw© gˆ¢wnego bloku programu (domy˜lnie 'main')
+**2XP<x>_poprzedza nazw© binutils tekstem <x>
+**2Xr<x>_ustawia ˜cie¾k© bibliotek na <x> (potrzebne do cross-kompilacji)
+**2Xs_wyci©cie wszystkich symboli z pliku
+**2XS_linkowanie statycznie (domy˜lne)(definiuje FPC_LINK_STATIC)
+**2Xt_linkuje z bibliotekami statycznymi (podaje -static do linkera)
+**2XX_linkowanie smart (definiuje FPC_LINK_SMART)
+**1*_
+**1?_pokazanie pomocy
+**1h_pokazanie pomocy bez zatrzymywania
+]
+
+#
+# The End...
diff --git a/closures/compiler/msg/errorpli.msg b/closures/compiler/msg/errorpli.msg
new file mode 100644
index 0000000000..2660eaf4b8
--- /dev/null
+++ b/closures/compiler/msg/errorpli.msg
@@ -0,0 +1,2385 @@
+#
+# This file is part of the Free Pascal Compiler
+# Copyright (c) 1999-2000 by the Free Pascal Development team
+#
+# Polish (ISO 8859-2) Language File for Free Pascal
+#
+# See the file COPYING.FPC, included in this distribution,
+# for details about the copyright.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#
+#
+# The constants are build in the following order:
+# <part>_<type>_<txtidentifier>
+#
+# <part> is the part of the compiler the message is used
+# asmr_ assembler parsing
+# asmw_ assembler writing/binary writers
+
+# unit_ unit handling
+# scan_ scanner
+# parser_ parser
+# type_ type checking
+# general_ general info
+# exec_ calls to assembler, linker, binder
+#
+# <type> the type of the message it should normally used for
+# f_ fatal error
+# e_ error
+# w_ warning
+# n_ note
+# h_ hint
+# i_ info
+# l_ linenumber
+# u_ used
+# t_ tried
+# c_ conditional
+# d_ debug message
+# x_ executable informations
+#
+
+#
+# General
+#
+# 01016 is the last used one
+#
+# BeginOfTeX
+% \section{General compiler messages}
+% This section gives the compiler messages which are not fatal, but which
+% display useful information. The number of such messages can be
+% controlled with the various verbosity level \var{-v} switches.
+% \begin{description}
+general_t_compilername=01000_T_Kompilator: $1
+% When the \var{-vt} switch is used, this line tells you what compiler
+% is used.
+general_d_sourceos=01001_D_OS kompilatora: $1
+% When the \var{-vd} switch is used, this line tells you what the source
+% operating system is.
+general_i_targetos=01002_I_Docelowy OS: $1
+% When the \var{-vd} switch is used, this line tells you what the target
+% operating system is.
+general_t_exepath=01003_T_¦cie¿ka narzêdzi: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for its binaries.
+general_t_unitpath=01004_T_¦cie¿ka modu³ów: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for compiled units. You can set this path with the \var{-Fu}
+general_t_includepath=01005_T_¦cie¿ka include'ów: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for its include files (files used in \var{\{\$I xxx\}} statements).
+% You can set this path with the \var{-I} option.
+general_t_librarypath=01006_T_¦cie¿ka bibliotek: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for the libraries. You can set this path with the \var{-Fl} option.
+general_t_objectpath=01007_T_¦cie¿ka obiektów: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for object files you link in (files used in \var{\{\$L xxx\}} statements).
+% You can set this path with the \var{-Fo} option.
+general_i_abslines_compiled=01008_I_$1 linii skompilowanych w $2 sek
+% When the \var{-vi} switch is used, the compiler reports the number
+% of lines compiled, and the time it took to compile them (real time,
+% not program time).
+general_f_no_memory_left=01009_F_Brak pamiêci
+% The compiler doesn't have enough memory to compile your program. There are
+% several remedies for this:
+% \begin{itemize}
+% \item If you're using the build option of the compiler, try compiling the
+% different units manually.
+% \item If you're compiling a huge program, split it up in units, and compile
+% these separately.
+% \item If the previous two don't work, recompile the compiler with a bigger
+% heap (you can use the \var{-Ch} option for this, \seeo{Ch})
+% \end{itemize}
+general_i_writingresourcefile=01010_I_Zapisywanie pliku zasobów: $1
+% This message is shown when the compiler writes the Resource String Table
+% file containing all the resource strings for a program.
+general_e_errorwritingresourcefile=01011_E_B³±d podczas zapisywania pliku zasobów: $1
+% This message is shown when the compiler encountered an error when writing
+% the Resource String Table file
+general_i_fatal=01012_I_B³±d krytyczny:
+% Prefix for Fatal Errors
+general_i_error=01013_I_B³±d:
+% Prefix for Errors
+general_i_warning=01014_I_Ostrze¿enie:
+% Prefix for Warnings
+general_i_note=01015_I_Nota:
+% Prefix for Notes
+general_i_hint=01016_I_Podpowied¼:
+% Prefix for Hints
+general_e_path_does_not_exist=01017_E_¦cie¿ka "$1" nie istnieje
+% The specified path does not exist.
+general_e_compilation_aborted=01018_E_Kompilacja zatrzymana
+% \end{description}
+#
+# Scanner
+#
+# 02063 is the last used one
+#
+% \section{Scanner messages.}
+% This section lists the messages that the scanner emits. The scanner takes
+% care of the lexical structure of the pascal file, i.e. it tries to find
+% reserved words, strings, etc. It also takes care of directives and
+% conditional compiling handling.
+% \begin{description}
+scan_f_end_of_file=02000_F_Nieoczekiwany koniec pliku
+% this typically happens in one of the following cases :
+% \begin{itemize}
+% \item The source file ends before the final \var{end.} statement. This
+% happens mostly when the \var{begin} and \var{end} statements aren't
+% balanced;
+% \item An include file ends in the middle of a statement.
+% \item A comment wasn't closed.
+% \end{itemize}
+scan_f_string_exceeds_line=02001_F_String przekracza jedn± liniê
+% You forgot probably to include the closing ' in a string, so it occupies
+% multiple lines.
+scan_f_illegal_char=02002_F_Nieprawid³owy znak $1 ($2)
+% An illegal character was encountered in the input file.
+scan_f_syn_expected=02003_F_B³±d sk³adni, oczekiwano $1 ale napotkano $2
+% This indicates that the compiler expected a different token than
+% the one you typed. It can occur almost everywhere where you make a
+% mistake against the pascal language.
+scan_t_start_include_file=02004_T_Rozpoczêcie czytania pliku include $1
+% When you provide the \var{-vt} switch, the compiler tells you
+% when it starts reading an included file.
+scan_w_comment_level=02005_W_Znaleziono komentarz $1 stopnia
+% When the \var{-vw} switch is used, then the compiler warns you if
+% it finds nested comments. Nested comments are not allowed in Turbo Pascal
+% and can be a possible source of errors.
+scan_n_ignored_switch=02008_N_Zignorowany prze³±cznik kompilatora $1
+% With \var{-vn} on, the compiler warns if it ignores a switch
+scan_w_illegal_switch=02009_W_Nieprawid³owy prze³±cznik kompilatora $1
+% You included a compiler switch (i.e. \var{\{\$... \}}) which the compiler
+% doesn't know.
+scan_w_switch_is_global=02010_W_Prze³±cznik globalny w nieprawid³owym miejscu
+% The compiler switch is misplaced, and should be located at
+% the start of the unit or program.
+scan_e_illegal_char_const=02011_E_Nieprawid³owa sta³a znakowa
+% This happens when you specify a character with its ASCII code, as in
+% \var{\#96}, but the number is either illegal, or out of range.
+scan_f_cannot_open_input=02012_F_Nie mo¿na otworzyæ pliku $1
+% \fpc cannot find the program or unit source file you specified on the
+% command line.
+scan_f_cannot_open_includefile=02013_F_Nie mo¿na otworzyæ pliku include $1
+% \fpc cannot find the source file you specified in a \var{\{\$include ..\}}
+% statement.
+scan_w_only_pack_records=02015_W_Pola rekordów mog± byæ wyrównane tylko do 1,2,4,8,16 lub 32 bajtów
+% You are specifying the \var{\{\$PACKRECORDS n\} } or \var{\{\$ALIGN n\} }
+% with an illegal value for \var{n}. For $PACKRECORDS valid alignments are 1, 2, 4, 8, 16, 32, C,
+% NORMAL, DEFAULT, and for $ALIGN valid alignment are 1, 2, 4, 8, 16, 32, ON,
+% OFF. Under mode MacPas $ALIGN also supports MAC68K, POWER and RESET.
+scan_w_only_pack_enum=02016_W_Wyliczenia mog± byæ zapisane tylko na 1, 2 lub 4 bajtach
+% You are specifying the \var{\{\$PACKENUM n\}} with an illegal value for
+% \var{n}. Only 1,2 or 4 are valid in this case.
+scan_e_endif_expected=02017_E_Oczekiwano $ENDIF dla $1 $2 zdefiniowanych w linii $3
+% Your conditional compilation statements are unbalanced.
+scan_e_preproc_syntax_error=02018_E_B³±d sk³adni podczas parsowania dyrektyw kompilacji warunkowej
+% There is an error in the expression following the \var{\{\$if ..\}} compiler
+% directive.
+scan_e_error_in_preproc_expr=02019_E_B³±d obliczania wyra¿enia kompilacji warunkowej
+% There is an error in the expression following the \var{\{\$if ..\}} compiler
+% directive.
+scan_w_macro_cut_after_255_chars=02020_W_Tre¶æ makra zosta³a obciêta po 255 znaku
+% The contents of macros canno be longer than 255 characters.
+scan_e_endif_without_if=02021_E_ENDIF bez IF(N)DEF
+% Your \var{\{\$IFDEF ..\}} and {\{\$ENDIF\}} statements aren't balanced.
+scan_f_user_defined=02022_F_Zdefiniowany przez u¿ytkownika: $1
+% A user defined fatal error occurred. see also the \progref
+scan_e_user_defined=02023_E_Zdefiniowany przez u¿ytkownika: $1
+% A user defined error occurred. see also the \progref
+scan_w_user_defined=02024_W_Zdefiniowane przez u¿ytkownika: $1
+% A user defined warning occurred. see also the \progref
+scan_n_user_defined=02025_N_Zdefiniowana przez u¿ytkownika: $1
+% A user defined note was encountered. see also the \progref
+scan_h_user_defined=02026_H_Zdefiniowana przez u¿ytkownika: $1
+% A user defined hint was encountered. see also the \progref
+scan_i_user_defined=02027_I_Zdefiniowana przez u¿ytkownika: $1
+% User defined information was encountered. see also the \progref
+scan_e_keyword_cant_be_a_macro=02028_E_S³owo kluczowe nie mo¿e zostaæ przedefiniowane przez makro
+% You cannot redefine keywords with macros.
+scan_f_macro_buffer_overflow=02029_F_Przepe³nienie bufora podczas czytania lub rozwijania makra
+% Your macro or its result was too long for the compiler.
+scan_e_macro_deep_ten=02030_E_Rozwijanie makra przerwane po 16 rozwiniêciach.
+% When expanding a macro macros have been nested to a level of 16.
+% The compiler will expand no further, since this may be a sign that
+% recursion is used.
+scan_e_wrong_styled_switch=02031_E_Prze³±czniki kompilatora nie s± dozwolone w komentarzach typu (* ... *)
+% Compiler switches should always be between \var{\{ \}} comment delimiters.
+scan_d_handling_switch=02032_D_Obs³ugiwanie prze³±cznika "$1"
+% When you set debugging info on (\var{-vd}) the compiler tells you when it
+% is evaluating conditional compile statements.
+scan_c_endif_found=02033_C_Znaleziono ENDIF $1
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifdef_found=02034_C_Znaleziono IFDEF $1 , $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifopt_found=02035_C_Znalezino IFOPT $1 , $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_if_found=02036_C_Znaleziono IF $1 , $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifndef_found=02037_C_Znaleziono IFNDEF $1 , $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_else_found=02038_C_Znaleziono ELSE $1 , $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_skipping_until=02039_C_Omijanie...
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements, and whether it is skipping or
+% compiling parts.
+scan_i_press_enter=02040_I_Naci¶nij <enter> aby kontynuowaæ
+% When the \var{-vi} switch is used, the compiler stops compilation
+% and waits for the \var{Enter} key to be pressed when it encounters
+% a \var{\{\$STOP\}} directive.
+scan_w_unsupported_switch=02041_W_Nieobs³ugiwany prze³±cznik $1
+% When warnings are turned on (\var{-vw}) the compiler warns you about
+% unsupported switches. This means that the switch is used in Delphi or
+% Turbo Pascal, but not in \fpc
+scan_w_illegal_directive=02042_W_Nieprawid³owa dyrektywa $1
+% When warings are turned on (\var{-vw}) the compiler warns you about
+% unrecognised switches. For a list of recognised switches, \progref
+scan_t_back_in=02043_TL_Z powrotem w $1
+% When you use (\var{-vt}) the compiler tells you when it has finished
+% reading an include file.
+scan_w_unsupported_app_type=02044_W_Nieprawid³owy typ aplikacji: $1
+% You get this warning, if you specify an unknown application type
+% with the directive \var{\{\$APPTYPE\}}
+scan_w_app_type_not_support=02045_W_Typ aplikacji nieobs³ugiwany przez docelowy OS
+% The \var{\{\$APPTYPE\}} directive is supported by win32 applications only.
+scan_w_description_not_support=02046_W_Dyrektywa DESCRIPTION jest obs³ugiwany tylko przez OS2 i Win32
+% The \var{\{\$DESCRIPTION\}} directive is only supported for OS2 and Win32 targets.
+scan_n_version_not_support=02047_N_Dyrektywa VERSION nie jest obs³ugiwana przez OS
+% The \var{\{\$VERSION\}} directive is only supported by win32 target.
+scan_n_only_exe_version=02048_N_Dyrektywa VERSION jest dostêna tylko dla programów i DLLi
+% The \var{\{\$VERSION\}} directive is only used for executable or DLL sources.
+scan_w_wrong_version_ignored=02049_W_Nieprawid³owy format dyrektywy VERSION $1
+% The \var{\{\$VERSION\}} directive format is majorversion.minorversion
+% where majorversion and minorversion are words.
+scan_w_unsupported_asmmode_specifier=02050_W_Nieprawid³owy styl asemblera $1
+% When you specify an assembler mode with the \var{\{\$ASMMODE xxx\}}
+% the compiler didn't recognize the mode you specified.
+scan_w_no_asm_reader_switch_inside_asm=02051_W_Prze³±cznik stylu asemblera niedozwolony w bloku asemblera, $1 bêdzie dzia³aæ dopiero w nastêpnym bloku
+% It is not possible to switch from one assembler reader to another
+% inside an assmebler block. The new reader will be used for next
+% assembler statement only.
+scan_e_wrong_switch_toggle=02052_E_Z³a warto¶æ prze³±cznika, u¿yj ON/OFF lub +/-
+% You need to use ON or OFF or a + or - to toggle the switch
+scan_e_resourcefiles_not_supported=02053_E_Pliki zasobów nie s± obs³ugiwane przez OS
+% The target you are compiling for doesn't support resource files.
+scan_w_include_env_not_found=02054_W_Zmienna ¶rodowiskowa $1 nie odnaleziona
+% The included environment variable can't be found in the environment, it'll
+% be replaced by an empty string instead.
+scan_e_invalid_maxfpureg_value=02055_E_Nieprawid³owa warto¶æ limitu rejestru FPU
+% Valid values for this directive are 0..8 and NORMAL/DEFAULT
+scan_w_only_one_resourcefile_supported=02056_W_Tylko jeden plik zasobów jest obs³ugiwany przez docelowy OS
+% The target you are compiling for supports only one resource file.
+% The first resource file found is used, the others are discarded.
+scan_w_macro_support_turned_off=02057_W_Obs³uga makr jest wy³±czona
+% A macro declaration has been found, but macro support is currently off,
+% so the declaration will be ignored. To turn macro support on compile with
+% -Sm on the commandline or add {$MACRO ON} in the source
+scan_e_invalid_interface_type=02058_E_Nieprawid³owy typ interfejsu. Prawid³owe s± COM, CORBA i DEFAULT.
+% The interface type that was specified is not supported
+scan_w_appid_not_support=02060_W_APPNAME jest obs³ugiwane tylko przez PalmOS
+% The \var{\{\$APPID\}} directive is only supported for the PalmOS target.
+scan_w_appname_not_support=02061_W_Dyrektywa APPNAME jest obs³ugiwana tylko przez PalmOS
+% The \var{\{\$APPNAME\}} directive is only supported for the PalmOS target.
+scan_e_string_exceeds_255_chars=02061_E_Sta³e ³añcuchowe nie mog± byæ d³u¿sze ni¿ 255 znaków
+% A single string constant can contain at most 255 chars. Try splitting up the
+% string in multiple smaller parts and concatenate them with a + operator.
+scan_f_include_deep_ten=02062_F_Przekroczono maksymaln± ilo¶æ zagnie¿d¿onych include (16)
+% When including include files the files have been nested to a level of 16.
+% The compiler will expand no further, since this may be a sign that
+% recursion is used.
+scan_e_too_many_push=02063_F_Zbyt du¿o poziomów PUSH
+% A maximum of 20 levels is allowed. This error occurs only in mode MacPas.
+scan_e_too_many_pop=02064_E_Napotkano POP bez poprzedzaj±cego go PUSH
+% This error occurs only in mode MacPas.
+scan_e_error_macro_lacks_value=02065_E_Makro lub zmienna "$1" nie ma przypisanej warto¶ci
+% Thus the conditional compile time expression cannot be evaluated.
+scan_e_wrong_switch_toggle_default=02066_E_Nieprawid³owy prze³±cznik, u¿yj ON/OFF/DEFAULT lub +/-/*
+% You need to use ON or OFF or DEFAULT or a + or - or * to toggle the switch
+scan_e_mode_switch_not_allowed=02067_E_Prze³±cznik trybu "$1" jest niedozwolony w tym miejscu
+% A mode switch has already been encountered, or, in case of option -Mmacpas,
+% a mode switch occur after UNIT.
+scan_e_error_macro_undefined=02068_E_Zmienna "$1" jest niezdefiniowana
+% Thus the conditional compile time expression cannot be evaluated.
+scan_e_utf8_bigger_than_65535=02069_E_Napotkano kod UTF-8 wiêkszy od 65535
+% \fpc handles utf-8 strings internally as widestrings e.g. the char codes are limited to 65535
+scan_e_utf8_malformed=02070_E_Zniekszta³cony string UTF-8
+% The given string isn't a valid UTF-8 string
+scan_c_switching_to_utf8=02071_C_Napotkano sygnaturê UTF-8, u¿ycie kodowania UTF-8
+% The compiler found an UTF-8 encoding signature ($ef, $bb, $bf) at the beginning of a file,
+% so it interprets it as an UTF-8 file
+% \end{description}
+#
+# Parser
+#
+# 03192 is the last used one
+#
+% \section{Parser messages}
+% This section lists all parser messages. The parser takes care of the
+% semantics of you language, i.e. it determines if your pascal constructs
+% are correct.
+% \begin{description}
+parser_e_syntax_error=03000_E_Parser - B³±d sk³adni
+% An error against the Turbo Pascal language was encountered. This happens
+% typically when an illegal character is found in the sources file.
+parser_e_dont_nest_interrupt=03004_E_Procedura typu INTERRUPT nie mo¿e byæ zagnie¿d¿ona
+% An \var{INTERRUPT} procedure must be global.
+parser_w_proc_directive_ignored=03005_W_Dyrektywa $1 zignorowana
+% The specified is ignored by FPC programs.
+parser_e_no_overload_for_all_procs=03006_E_Nie wszystkie deklaracje $1 s± przeci±¿one
+% When you want to use overloading using the \var{OVERLOAD} directive, then
+% all declarations need to have \var{OVERLOAD} specified.
+parser_e_export_name_double=03008_E_Zduplikowana nazwa eksportu $1
+% Exported function names inside a specific DLL must all be different
+parser_e_export_ordinal_double=03009_E_Zduplikowany indeks eksportowanej funkcji $1
+% Exported function names inside a specific DLL must all be different
+parser_e_export_invalid_index=03010_E_Nieprawid³owa warto¶æ indeksu funkcji
+% DLL function index must be in the range \var{1..\$FFFF}
+parser_w_parser_reloc_no_debug=03011_W_Informacje debugera w DLLu lub programie $1 nie dzia³aj±, wy³±czone.
+parser_w_parser_win32_debug_needs_WN=03012_W_Aby móc debugowaæ kod win32 musisz wy³±czyæ generowanie kodu relokacji prze³±cznikiem -WN
+% Stabs info is wrong for relocatable DLL or EXES use -WN
+% if you want to debug win32 executables.
+parser_e_constructorname_must_be_init=03013_E_Konstruktor musi nazywaæ siê INIT
+% You are declaring a constructor with a name which isn't \var{init}, and the
+% \var{-Ss} switch is in effect. See the \var{-Ss} switch (\seeo{Ss}).
+parser_e_destructorname_must_be_done=03014_E_Destruktor musi nazywaæ siê DONE
+% You are declaring an object destructor with a name which is not \var{done}, and the
+% \var{-Ss} switch is in effect. See the \var{-Ss} switch (\seeo{Ss}).
+parser_e_proc_inline_not_supported=03016_E_Typ INLINE nieobs³ugiwany (u¿yj opcji -Si)
+% You tried to compile a program with C++ style inlining, and forgot to
+% specify the \var{-Si} option (\seeo{Si}). The compiler doesn't support C++
+% styled inlining by default.
+parser_w_constructor_should_be_public=03018_W_Konstruktor powinien byæ publiczny
+% Constructors must be in the 'public' part of an object (class) declaration.
+parser_w_destructor_should_be_public=03019_W_Destruktor powinien byæ publiczny
+% Destructors must be in the 'public' part of an object (class) declaration.
+parser_n_only_one_destructor=03020_N_Klasa powinna mieæ tylko jeden destruktor
+% You can declare only one destructor for a class.
+parser_e_no_local_objects=03021_E_Definicje lokalne w klasie s± niedozwolone
+% Classes must be defined globally. They cannot be defined inside a
+% procedure or function
+parser_f_no_anonym_objects=03022_F_Definicje anonimowych klas s± niedozwolone
+% An invalid object (class) declaration was encountered, i.e. an
+% object or class without methods that isn't derived from another object or
+% class. For example:
+% \begin{verbatim}
+% Type o = object
+% a : longint;
+% end;
+% \end{verbatim}
+% will trigger this error.
+parser_object_has_no_vmt=03023_E_Obiekt $1 nie posiada VMT
+% This is a note indicating that the declared object has no
+% virtual method table.
+parser_e_illegal_parameter_list=03024_E_Nieprawid³owa lista parametrów
+% You are calling a function with parameters that are of a different type than
+% the declared parameters of the function.
+parser_e_wrong_parameter_size=03026_E_Nieprawid³owa ilo¶æ parametrów
+% There is an error in the parameter list of the function or procedure,
+% the number of parameters is not correct.
+parser_e_overloaded_no_procedure=03027_E_Przeci±¿ony identyfikator $1 nie jest funkcj±
+% The compiler encountered a symbol with the same name as an overloaded
+% function, but it is not a function it can overload.
+parser_e_overloaded_have_same_parameters=03028_E_Przeci±¿ona funkcja musi mieæ chocia¿ jeden parametr wyró¿niaj±cy
+% You're declaring overloaded functions, but with the same parameter list.
+% Overloaded function must have at least 1 different parameter in their
+% declaration.
+parser_e_header_dont_match_forward=03029_E_Nag³ówek funkcji nie pasuje do deklaracji $1
+% You declared a function with same parameters but
+% different result type or function modifiers.
+parser_e_header_different_var_names=03030_E_Nag³ówek funkcji $1 nie pasuje : nazwy parametrów zmienione $2 => $3
+% You declared the function in the \var{interface} part, or with the
+% \var{forward} directive, but define it with a different parameter list.
+parser_n_duplicate_enum=03031_N_Ci±g warto¶ci typu wyliczeniowego musi byæ rosn±cy
+% \fpc allows enumeration constructions as in C. Given the following
+% declaration two declarations:
+% \begin{verbatim}
+% type a = (A_A,A_B,A_E:=6,A_UAS:=200);
+% type a = (A_A,A_B,A_E:=6,A_UAS:=4);
+% \end{verbatim}
+% The second declaration would produce an error. \var{A\_UAS} needs to have a
+% value higher than \var{A\_E}, i.e. at least 7.
+parser_e_no_with_for_variable_in_other_segments=03033_E_With nie mo¿e byæ u¿yte ze zmiennymi w innym segmencie
+% With stores a variable locally on the stack,
+% but this is not possible if the variable belongs to another segment.
+parser_e_too_much_lexlevel=03034_E_Przekroczono limit zagnie¿d¿enia funkcji
+% You can nest function definitions only 31 times.
+parser_e_range_check_error=03035_E_B³±d zakresu podczas obliczania sta³ej
+% The constants are out of their allowed range.
+parser_w_range_check_error=03036_W_B³±d zakresu podczas obliczania sta³ej
+% The constants are out of their allowed range.
+parser_e_double_caselabel=03037_E_Zduplikowana etykieta w instrukcji case
+% You are specifying the same label 2 times in a \var{case} statement.
+parser_e_case_lower_less_than_upper_bound=03038_E_Górna granica zakresu jest mniejsza od dolnej
+% The upper bound of a \var{case} label is less than the lower bound and this
+% is useless
+parser_e_type_const_not_possible=03039_E_Sta³a typowana nie mo¿e byæ klas± ani obiektem
+% You cannot declare a constant of type class or object.
+parser_e_no_overloaded_procvars=03040_E_Do zmiennych proceduralnych nie mo¿na przypisaæ przeci±¿onych funkcji
+% You are trying to assign an overloaded function to a procedural variable.
+% This isn't allowed.
+parser_e_invalid_string_size=03041_E_D³ugo¶æ stringa musi zawieraæ siê miêdzy 1 a 255
+% The length of a shortstring in Pascal is limited to 255 characters. You are
+% trying to declare a string with length lower than 1 or greater than 255
+parser_w_use_extended_syntax_for_objects=03042_W_U¿yj rozszerzonej sk³adni NEW i DISPOSE dla obiektów
+% If you have a pointer \var{a} to a class type, then the statement
+% \var{new(a)} will not initialize the class (i.e. the constructor isn't
+% called), although space will be allocated. you should issue the
+% \var{new(a,init)} statement. This will allocate space, and call the
+% constructor of the class.
+parser_w_no_new_dispose_on_void_pointers=03043_W_U¿ycie NEW lub DISPOSE nie ma sensu dla nietypowanych wska¼ników
+parser_e_no_new_dispose_on_void_pointers=03044_E_U¿ycie NEW lub DISPOSE jest niemo¿liwe dla nietypowanych wska¼ników
+% You cannot use \var{new(p)} or \var{dispose(p)} if \var{p} is an untyped pointer
+% because no size is associated to an untyped pointer.
+% Accepted for compatibility in \var{tp} and \var{delphi} modes.
+parser_e_class_id_expected=03045_E_Oczekiwano identyfikatora klasy
+% This happens when the compiler scans a procedure declaration that contains
+% a dot,
+% i.e., a object or class method, but the type in front of the dot is not
+% a known type.
+parser_e_no_type_not_allowed_here=03046_E_Identyfikator typu jest niedozwolony w tym miejscu
+% You cannot use a type inside an expression.
+parser_e_methode_id_expected=03047_E_Oczekiwano identyfikatora metody
+% This identifier is not a method.
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., a object or class method, but the procedure name is not a
+% procedure of this type.
+parser_e_header_dont_match_any_member=03048_E_Nag³ówek funkcji nie pasuje do ¿adnej metody tej klasy $1
+% This identifier is not a method.
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., a object or class method, but the procedure name is not a
+% procedure of this type.
+parser_d_procedure_start=03049_DL_Procedura/Funkcja $1
+% When using the \var{-vp} switch, the compiler tells you when it starts
+% processing a procedure or function implementation.
+parser_e_error_in_real=03050_E_Nieprawid³owa warto¶æ sta³ej zmiennoprzecinkowej
+% The compiler expects a floating point expression, and gets something else.
+parser_e_fail_only_in_constructor=03051_E_FAIL mo¿e byæ u¿yte tylko w konstruktorach
+% You are using the \var{FAIL} instruction outside a constructor method.
+parser_e_no_paras_for_destructor=03052_E_Destruktory nie mog± mieæ parametrów
+% You are declaring a destructor with a parameter list. Destructor methods
+% cannot have parameters.
+parser_e_only_class_methods_via_class_ref=03053_E_Tylko metody klasy mog± byæ wywo³ywane w ten sposób
+% This error occurs in a situation like the following:
+% \begin{verbatim}
+% Type :
+% Tclass = Class of Tobject;
+%
+% Var C : TClass;
+%
+% begin
+% ...
+% C.free
+% \end{verbatim}
+% \var{Free} is not a class method and hence cannot be called with a class
+% reference.
+parser_e_only_class_methods=03054_E_W metodach klasy mo¿esz u¿ywaæ tylko metod klasy
+% This is related to the previous error. You cannot call a method of an object
+% from a inside a class method. The following code would produce this error:
+% \begin{verbatim}
+% class procedure tobject.x;
+%
+% begin
+% free
+% \end{verbatim}
+% Because free is a normal method of a class it cannot be called from a class
+% method.
+parser_e_case_mismatch=03055_E_Sta³a i zmienna u¿yta w CASE nie s± tego samego typu
+% One of the labels is not of the same type as the case variable.
+parser_e_illegal_symbol_exported=03056_E_Symbol nie mo¿e byæ wyeksportowany
+% You can only export procedures and functions when you write a library. You
+% cannot export variables or constants.
+parser_w_should_use_override=03057_W_Dziedziczona metoda jest ukryta przez $1
+% A method that is declared \var{virtual} in a parent class, should be
+% overridden in the descendent class with the \var{override} directive. If you
+% don't specify the \var{override} directive, you will hide the parent method;
+% you will not override it.
+parser_e_nothing_to_be_overridden=03058_E_Nie ma takiej metody w dziedziczonej klasie: $1
+% You are trying to \var{override} a virtual method of a parent class that does
+% not exist.
+parser_e_no_procedure_to_access_property=03059_E_Brak metody do odczytania w³asno¶ci
+% You specified no \var{read} directive for a property.
+parser_w_stored_not_implemented=03060_W_Dyrektywa stored nie jest jeszcze zaimplementowana
+% The \var{stored} directive is not yet implemented
+parser_e_ill_property_access_sym=03061_E_Nieprawid³owy symbol dla dostêpu do w³asno¶ci
+% There is an error in the \var{read} or \var{write} directives for an array
+% property. When you declare an array property, you can only access it with
+% procedures and functions. The following code woud cause such an error.
+% \begin{verbatim}
+% tmyobject = class
+% i : integer;
+% property x [i : integer]: integer read I write i;
+% \end{verbatim}
+%
+parser_e_cant_access_protected_member=03062_E_Nie mo¿na siê odwo³ywaæ do pola protected obiektu w tym miejscu
+% Fields that are declared in a \var{protected} section of an object or class
+% declaration cannot be accessed outside the module wher the object is
+% defined, or outside descendent object methods.
+parser_e_cant_access_private_member=03063_E_Nie mo¿na siê odwo³ywaæ do pola private obiektu w tym miejscu
+% Fields that are declared in a \var{private} section of an object or class
+% declaration cannot be accessed outside the module where the class is
+% defined.
+parser_e_overridden_methods_not_same_ret=03066_E_Przeci±¿one metody wirtualne powinny mieæ taki sam typ zwracanych warto¶ci: "$2" jest przeci±¿one przez "$" o innym zwracanym typie
+% If you declare overridden methods in a class definition, they must
+% have the same return type.
+parser_e_dont_nest_export=03067_E_Eksportowane funkcje nie mog± byæ zagnie¿d¿one
+% You cannot declare a function or procedure within a function or procedure
+% that was declared as an export procedure.
+parser_e_methods_dont_be_export=03068_E_Metody nie mog± byæ eksportowane
+% You cannot declare a procedure that is a method for an object as
+% \var{export}ed. That is, your methods cannot be called from a C program.
+parser_e_call_by_ref_without_typeconv=03069_E_Przy przekazywaniu przez referencjê parametry musz± byæ tego samego typu: Otrzymano $1, a oczekiwano $2
+% When calling a function declared with \var{var} parameters, the variables in
+% the function call must be of exactly the same type. There is no automatic
+% type conversion.
+parser_e_no_super_class=03070_E_Ta klasa nie jest przodkiem bie¿±cej klasy
+% When calling inherited methods, you are trying to call a method of a strange
+% class. You can only call an inherited method of a parent class.
+parser_e_self_not_in_method=03071_E_SELF jest dostêpne tylko w metodach
+% You are trying to use the \var{self} parameter outside an object's method.
+% Only methods get passed the \var{self} parameters.
+parser_e_generic_methods_only_in_methods=03072_E_Metody mog± byæ wywo³ane bezpo¶rednio identyfikatorem typu klasy tylko w innych metodach
+% A construction like \var{sometype.somemethod} is only allowed in a method.
+parser_e_illegal_colon_qualifier=03073_E_Nieprawid³owe u¿ycie ':'
+% You are using the format \var{:} (colon) 2 times on an expression that
+% is not a real expression.
+parser_e_illegal_set_expr=03074_E_B³±d zakresu lub zduplikowany element w deklaracji zbioru
+% The declaration of a set contains an error. Either one of the elements is
+% outside the range of the set type, either two of the elements are in fact
+% the same.
+parser_e_pointer_to_class_expected=03075_E_Oczekiwano wska¼nika do obiektu
+% You specified an illegal type in a \var{New} statement.
+% The extended syntax of \var{new} needs an object as a parameter.
+parser_e_expr_have_to_be_constructor_call=03076_E_Wyra¿enie musi byæ wywo³aniem konstruktora
+% When using the extended syntax of \var{new}, you must specify the constructor
+% method of the object you are trying to create. The procedure you specified
+% is not a constructor.
+parser_e_expr_have_to_be_destructor_call=03077_E_Wyra¿enie musi byæ wywo³aniem destruktora
+% When using the extended syntax of \var{dispose}, you must specify the
+% destructor method of the object you are trying to dispose of.
+% The procedure you specified is not a destructor.
+parser_e_invalid_record_const=03078_E_Nieprawid³owa kolejno¶æ elementów rekordu
+% When declaring a constant record, you specified the fields in the wrong
+% order.
+parser_e_false_with_expr=03079_E_Wyra¿enie musi byæ rekordem lub klas±
+% A \var{with} statement needs an argument that is of the type \var{record}
+% or \var{class}. You are using \var{with} on an expression that is not of
+% this type.
+parser_e_void_function=03080_E_Procedury nie mog± zwracaæ warto¶ci
+% In \fpc, you can specify a return value for a function when using
+% the \var{exit} statement. This error occurs when you try to do this with a
+% procedure. Procedures cannot return a value.
+parser_e_only_methods_allowed=03081_E_Konstruktory, destructory i class operators musz± byæ metodami
+% You're declaring a procedure as destructor, constructor or class operator, when the
+% procedure isn't a class method.
+parser_e_operator_not_overloaded=03082_E_Operator nie jest przeci±¿ony
+% You're trying to use an overloaded operator when it isn't overloaded for
+% this type.
+parser_e_no_such_assignment=03083_E_Nie mo¿a przeci±¿yæ przypisania dla takich samych typów
+% You can not overload assignment for types
+% that the compiler considers as equal.
+parser_e_overload_impossible=03084_E_Niemo¿liwe przeci±¿enie operatora
+% The combination of operator, arguments and return type are
+% incompatible.
+parser_e_no_reraise_possible=03085_E_Ponowne wywo³anie wyj±tku niemo¿liwe w tym miejscu
+% You are trying to raise an exception where it isn't allowed. You can only
+% raise exceptions in an \var{except} block.
+parser_e_no_new_or_dispose_for_classes=03086_E_Rozszerzona sk³adnia new i dispose jest niedozwolona dla klas
+% You cannot generate an instance of a class with the extended syntax of
+% \var{new}. The constructor must be used for that. For the same reason, you
+% cannot call \var{Dispose} to de-allocate an instance of a class, the
+% destructor must be used for that.
+parser_e_procedure_overloading_is_off=03088_E_Przeci±¿anie procedur jest wy³±czone
+% When using the \var{-So} switch, procedure overloading is switched off.
+% Turbo Pascal does not support function overloading.
+parser_e_overload_operator_failed=03089_E_Przeci±¿enie tego operatora jest niemo¿liwe
+% You are trying to overload an operator which cannot be overloaded.
+% The following operators can be overloaded :
+% \begin{verbatim}
+% +, -, *, /, =, >, <, <=, >=, is, as, in, **, :=
+% \end{verbatim}
+parser_e_comparative_operator_return_boolean=03090_E_Operator porównania musi zwracaæ warto¶æ typu Boolean
+% When overloading the \var{=} operator, the function must return a boolean
+% value.
+parser_e_only_virtual_methods_abstract=03091_E_Tylko metody wirtualne mog± byæ abstrakcyjne
+% You are declaring a method as abstract, when it isn't declared to be
+% virtual.
+parser_f_unsupported_feature=03092_F_U¿ycie nieobs³ugiwanej funkcji kompilatora!
+% You're trying to force the compiler into doing something it cannot do yet.
+parser_e_mix_of_classes_and_objects=03093_E_Mieszanie ró¿nych typów obiektów (obiektów, klas, interfejsów) jest niedozwolone
+% You cannot derive \var{objects}, \var{classes}, \var{cppclasses} and \var{interfaces} interttwined . E.g.
+% a class cannot have an object as parent and vice versa.
+parser_w_unknown_proc_directive_ignored=03094_W_Nieznana dyrektywa procedury zosta³a zignorowana: $1
+% The procedure directive you specified is unknown.
+parser_e_absolute_only_one_var=03095_E_Absolute mo¿e byæ powi±zane tylko z jedn± zmienn±
+% You cannot specify more than one variable before the \var{absolute} directive.
+% Thus, the following construct will provide this error:
+% \begin{verbatim}
+% Var Z : Longint;
+% X,Y : Longint absolute Z;
+% \end{verbatim}
+% \item [ absolute can only be associated a var or const ]
+% The address of a \var{absolute} directive can only point to a variable or a
+% typed constant. Therefore, the following code will produce this error:
+% \begin{verbatim}
+% Procedure X;
+%
+% var p : longint absolute x;
+% \end{verbatim}
+%
+parser_e_absolute_only_to_var_or_const=03096_E_Absolute mo¿e byæ u¿yte tylko w stosunku do zmiennej lub sta³ej
+% The address of a \var{absolute} directive can only point to a variable or
+% constant. Therefore, the following code will produce this error:
+% \begin{verbatim}
+% Procedure X;
+%
+% var p : longint absolute x;
+% \end{verbatim}
+%
+parser_e_initialized_only_one_var=03097_E_Tylko jedna zmienna mo¿e byæ zainicjowana
+% You cannot specify more than one variable with a initial value
+% in Delphi mode.
+parser_e_abstract_no_definition=03098_E_Metody abstrakcyjne nie mog± byæ zaimplementowane
+% Abstract methods can only be declared, you cannot implement them. They
+% should be overridden by a descendant class.
+parser_e_overloaded_must_be_all_global=03099_E_Ta przeci±¿ona funkcja nie mo¿e byæ lokalna (musi byæ wyeksportowana)
+% You are defining a overloaded function in the implementation part of a unit,
+% but there is no corresponding declaration in the interface part of the unit.
+parser_w_virtual_without_constructor=03100_W_Metody wirtualne u¿yte bez konstruktora $1
+% If you declare objects or classes that contain virtual methods, you need
+% to have a constructor and destructor to initialize them. The compiler
+% encountered an object or class with virtual methods that doesn't have
+% a constructor/destructor pair.
+parser_c_macro_defined=03101_CL_Makro zdefiniowane: $1
+% When \var{-vm} is used, the compiler tells you when it defines macros.
+parser_c_macro_undefined=03102_CL_Makro wymazane: $1
+% When \var{-vm} is used, the compiler tells you when it undefines macros.
+parser_c_macro_set_to=03103_CL_Makro $1 ustawione na $2
+% When \var{-vm} is used, the compiler tells you what values macros get.
+parser_i_compiling=03104_I_Kompilowanie $1
+% When you turn on information messages (\var{-vi}), the compiler tells you
+% what units it is recompiling.
+parser_u_parsing_interface=03105_UL_Parsowanie czê¶ci interface modu³u $1
+% This tells you that the reading of the interface
+% of the current unit starts
+parser_u_parsing_implementation=03106_UL_Parsowanie czê¶ci implementation modu³u $1
+% This tells you that the code reading of the implementation
+% of the current unit, library or program starts
+parser_d_compiling_second_time=03107_DL_Kompilowanie $1 po raz drugi
+% When you request debug messages (\var{-vd}) the compiler tells you what
+% units it recompiles for the second time.
+parser_e_no_property_found_to_override=03109_E_Nie znaleziono w³asno¶ci do przeci±¿enia
+% You want to overrride a property of a parent class, when there is, in fact,
+% no such property in the parent class.
+parser_e_only_one_default_property=03110_E_Dozwolona jest tylko jedna w³asno¶æ domy¶lna, a znaleziono odziedziczon± w³asno¶æ domy¶ln± $1
+% You specified a property as \var{Default}, but a parent class already has a
+% default property, and a class can have only one default property.
+parser_e_property_need_paras=03111_E_W³asno¶ci± domy¶ln± musi byæ tablica
+% Only array properties of classes can be made \var{default} properties.
+parser_e_constructor_cannot_be_not_virtual=03112_E_Wirtualne konstruktory s± dostêpne tylko w klasach
+% You cannot have virtual constructors in objects. You can only have them
+% in classes.
+parser_e_no_default_property_available=03113_E_Brak domy¶lnej w³asno¶ci w tej klasie
+% You are trying to access a default property of a class, but this class (or one of
+% its ancestors) doesn't have a default property.
+parser_e_cant_have_published=03114_E_Klasa nie mo¿e mieæ sekcji published, u¿yj prze³±cznika {$M+}
+% If you want a \var{published} section in a class definition, you must
+% use the \var{\{\$M+\}} switch, whch turns on generation of type
+% information.
+parser_e_forward_declaration_must_be_resolved=03115_E_Deklaracja naprzód klasy $1 musi byæ rozwi±zana, aby u¿yæ klasy jako przodka innej klasy
+% To be able to use an object as an ancestor object, it must be defined
+% first. This error occurs in the following situation:
+% \begin{verbatim}
+% Type ParentClas = Class;
+% ChildClass = Class(ParentClass)
+% ...
+% end;
+% \end{verbatim}
+% Where \var{ParentClass} is declared but not defined.
+parser_e_no_local_operator=03116_E_Lokalne przeci±¿enia operatorów niedostêpne
+% You cannot overload locally, i.e. inside procedures or function
+% definitions.
+parser_e_proc_dir_not_allowed_in_interface=03117_E_Dyrektywa $1 niedozwolona w sekcji interface
+% This procedure directive is not allowed in the \var{interface} section of
+% a unit. You can only use it in the \var{implementation} section.
+parser_e_proc_dir_not_allowed_in_implementation=03118_E_Dyrektywa $1 niedozwolona w sekcji implementation
+% This procedure directive is not defined in the \var{implementation} section of
+% a unit. You can only use it in the \var{interface} section.
+parser_e_proc_dir_not_allowed_in_procvar=03119_E_Dyrektywa $1 niedozwolona w deklaracji typu proceduralnego
+% This procedure directive cannot be part of a procedural or function
+% type declaration.
+parser_e_function_already_declared_public_forward=03120_E_Funkcja jest ju¿ zadeklarowana jako Public/Forward $1
+% You will get this error if a function is defined as \var{forward} twice.
+% Or it is once in the \var{interface} section, and once as a \var{forward}
+% declaration in the \var{implmentation} section.
+parser_e_not_external_and_export=03121_E_Nie mo¿na u¿yæ jednocze¶nie EXPORT i EXTERNAL
+% These two procedure directives are mutually exclusive
+parser_w_not_supported_for_inline=03123_W_$1 nieobs³ugiwane w procedurze/funkcji inline
+% Inline procedures don't support this declaration.
+parser_w_inlining_disabled=03124_W_Inline wy³±czone
+% Inlining of procedures is disabled.
+parser_i_writing_browser_log=03125_I_Zapisywanie logu przegl±darki $1
+% When information messages are on, the compiler warns you when it
+% writes the browser log (generated with the \var{\{\$Y+ \}} switch).
+parser_h_maybe_deref_caret_missing=03126_H_Mo¿liwe, ¿e brakuje dereferencji wska¼nika
+% The compiler thinks that a pointer may need a dereference.
+parser_f_assembler_reader_not_supported=03127_F_Wybrany tryb asemblera nie jest obs³ugiwany
+% The selected assembler reader (with \var{\{\$ASMMODE xxx\}} is not
+% supported. The compiler can be compiled with or without support for a
+% particular assembler reader.
+parser_e_proc_dir_conflict=03128_E_Dyrektywa $1 koliduje z innymi dyrektywami
+% You specified a procedure directive that conflicts with other directives.
+% for instance \var{cdecl} and \var{pascal} are mutually exclusive.
+parser_e_call_convention_dont_match_forward=03129_E_Konwencja wywo³ywania musi byæ taka sama w czêsci interface i implementation
+% This error happens when you declare a function or procedure with
+% e.g. \var{cdecl;} but omit this directive in the implementation, or vice
+% versa. The calling convention is part of the function declaration, and
+% must be repeated in the function definition.
+parser_e_property_cant_have_a_default_value=03131_E_Ta w³asno¶æ nie mo¿e mieæ domy¶lnej warto¶ci
+% Set properties or indexed properties cannot have a default value.
+parser_e_property_default_value_must_const=03132_E_Domy¶lna warto¶æ w³asno¶ci musi byæ sta³±
+% The value of a \var{default} declared property must be known at compile
+% time. The value you specified is only known at run time. This happens
+% .e.g. if you specify a variable name as a default value.
+parser_e_cant_publish_that=03133_E_Symbol nie mo¿e byæ w sekcji published
+% Only class type variables can be in a \var{published} section of a class
+% if they are not declared as a property.
+parser_e_cant_publish_that_property=03134_E_Ten typ warto¶ci nie mo¿e byæ w sekcji published
+% Properties in a \var{published} section cannot be array properties.
+% they must be moved to public sections. Properties in a \var{published}
+% section must be an ordinal type, a real type, strings or sets.
+parser_e_empty_import_name=03136_W_Wymagana jest nazwa importu
+% Some targets need a name for the imported procedure or a \var{cdecl} specifier
+parser_e_division_by_zero=03138_E_Dzielenie przez zero
+% There is a divsion by zero encounted
+parser_e_invalid_float_operation=03139_E_Nieprawid³owa operacja zmiennoprzecinkowa
+% An operation on two real type values produced an overflow or a division
+% by zero.
+parser_e_array_lower_less_than_upper_bound=03140_E_Górna granica zakresu jest mniejsza od dolnej
+% The upper bound of a an array declaration is less than the lower bound and this
+% is not possible
+parser_w_string_too_long=03141_W_String "$1" jest d³u¿szy ni¿ $2
+% The size of the constant string is larger than the size you specified in
+% string type definition
+parser_e_string_larger_array=03142_E_D³ugo¶æ stringa jest wiêksza ni¿ d³ugo¶æ tablicy znaków
+% The size of the constant string is larger than the size you specified in
+% the array[x..y] of char definition
+parser_e_ill_msg_expr=03143_E_Nieprawid³owe wyra¿enie przy dyrektywie message
+% \fpc supports only integer or string values as message constants
+parser_e_ill_msg_param=03144_E_Funkcje obs³uguj±ce komunikaty (message) mog± pobieraæ tylko jeden parametr przez referencjê
+% A method declared with the \var{message}-directive as message handler
+% can take only one parameter which must be declared as call by reference
+% Parameters are declared as call by reference using the \var{var}-directive
+parser_e_duplicate_message_label=03145_E_Zduplikowana etykieta komunikatu: $1
+% A label for a message is used twice in one object/class
+parser_e_self_in_non_message_handler=03146_E_Self mo¿e byæ parametrem tylko metod obs³uguj±cych komunikaty
+% The self parameter can only be passed explicitly to a method which
+% is declared as message handler.
+parser_e_threadvars_only_sg=03147_E_Zmienne threadvar mog± byæ tylko statyczne lub globalne
+% Threadvars must be static or global, you can't declare a thread
+% local to a procedure. Local variables are always local to a thread,
+% because every thread has its own stack and local variables
+% are stored on the stack
+parser_f_direct_assembler_not_allowed=03148_F_Wstawki asemblera niedostêpne gdy wyj¶ciowym formatem jest wbudowane zapisywanie binarne
+% You can't use direct assembler when using a binary writer, choose an
+% other outputformat or use another assembler reader
+parser_w_no_objpas_use_mode=03149_W_Nie ³aduj modu³u OBJPAS bezpo¶rednio - u¿yj trybu obiektowego (objfpc, delphi)
+% You are trying to load the ObjPas unit manually from a uses clause. This is
+% not a good idea. Use the \var{\{\$mode objfpc\}} or
+% \var{\{\$mode delphi\}}
+% directives which load the unit automatically
+parser_e_no_object_override=03150_E_OVERRIDE nie mo¿e byæ u¿yte dla obiektów
+% Override is not supported for objects, use \var{virtual} instead to override
+% a method of a parent object
+parser_e_cant_use_inittable_here=03151_E_Typy danych wymagaj±ce inicjalizacji/finalizcji nie mog± byæ u¿yte w rekordach z wariantami
+% Some data type (e.g. \var{ansistring}) needs initialization/finalization
+% code which is implicitly generated by the compiler. Such data types
+% can't be used in the variant part of a record.
+parser_e_resourcestring_only_sg=03152_E_Resourcestring mo¿e byæ tylko statyczny lub globalny
+% Resourcestring can not be declared local, only global or using the static
+% directive.
+parser_e_exit_with_argument_not__possible=03153_E_Exit z argumentem nie mo¿e byæ tu u¿yte
+% an exit statement with an argument for the return value can't be used here, this
+% can happen e.g. in \var{try..except} or \var{try..finally} blocks
+parser_e_stored_property_must_be_boolean=03154_E_Symbol przechowywania w³asno¶ci musi byæ typu boolean
+% If you specify a storage symbol in a property declaration, it must be of
+% the type boolean
+parser_e_ill_property_storage_sym=03155_E_Ten symbol nie mo¿e byæ symbolem przechowywania w³asno¶ci
+% You can't use this type of symbol as storage specifier in property
+% declaration. You can use only methods with the result type boolean,
+% boolean class fields or boolean constants
+parser_e_only_publishable_classes_can__be_published=03156_E_Tylko klasy skompilowane w trybie $M+ mog± byæ w sekcji published
+% In the published section of a class can be only class as fields used which
+% are compiled in \var{\{\$M+\}} or which are derived from such a class. Normally
+% such a class should be derived from TPersitent
+parser_e_proc_directive_expected=03157_E_Oczekiwano dyrektywy procedury
+% When declaring a procedure in a const block you used a ; after the
+% procedure declaration after which a procedure directive must follow.
+% Correct declarations are:
+% \begin{verbatim}
+% const
+% p : procedure;stdcall=nil;
+% p : procedure stdcall=nil;
+% \end{verbatim}
+parser_e_invalid_property_index_value=03158_E_Warto¶æ indeksu w³asno¶ci musi byæ typu porz±dkowego
+% The value you use to index a property must be of an ordinal type, for
+% example an integer or enumerated type.
+parser_e_procname_to_short_for_export=03159_E_Zbyt krótka nazwa procedury, aby eksportowaæ
+% The length of the procedure/function name must be at least 2 characters
+% long. This is because of a bug in dlltool which doesn't parse the .def
+% file correct with a name of length 1.
+parser_e_dlltool_unit_var_problem=03160_E_Nie mo¿na wygenerowaæ pozycji DEFFILE dla zmiennych globalnych modu³u
+parser_e_dlltool_unit_var_problem2=03161_E_Skompiluj bez opcji -WD
+% You need to compile this file without the -WD switch on the
+% commandline
+parser_f_need_objfpc_or_delphi_mode=03162_F_Aby skompilowaæ ten modu³ wymagany jest tryb ObjFpc (-S2) lub Delphi (-Sd)
+% You need to use {$mode objfpc} or {$mode delphi} to compile this file.
+% Or use the equivalent commandline switches -S2 or -Sd.
+parser_e_no_export_with_index_for_target=03163_E_Nie mo¿na wyeksportowaæ z indeksem pod $1
+% Exporting of functions or procedures with a specified index is not
+% supported on this target.
+parser_e_no_export_of_variables_for_target=03164_E_Nie mo¿na wyeksportowaæ zmiennych pod $1
+% Exporting of variables is not supported on this target.
+parser_e_improper_guid_syntax=03165_E_Nieprawid³owa sk³adnia identyfikatora GUID
+parser_w_interface_mapping_notfound=03168_W_Nie znaleziono procedury "$1", która mog³aby implementowaæ $2.$3
+parser_e_interface_id_expected=03169_E_Oczekiwano interfejsu
+% This happens when the compiler scans a \var{class} declaration that contains
+% \var{interface} function name mapping code like this:
+% \begin{verbatim}
+% type
+% TMyObject = class(TObject, IDispatch)
+% function IUnknown.QueryInterface=MyQueryInterface;
+% ....
+% \end{verbatim}
+% and the \var{interface} before the dot not listed in the inheritance list.
+parser_e_type_cant_be_used_in_array_index=03170_E_Typ "$1" nie mo¿e byæ u¿yty jako indeks tablicy
+% Types like \var{qword} or \var{int64} aren't allowed as array index type
+parser_e_no_con_des_in_interfaces=03171_E_Konstruktory i destruktory s± niedozwolone w interfejsach
+% Constructor and destructor declarations aren't allowed in interface
+% In the most cases the method \var{QueryInterface} of \var{IUnknown} can
+% be used to create a new interface.
+parser_e_no_access_specifier_in_interfaces=03172_E_Okre¶lenia dostêpu nie mog± byæ u¿yte w interfejsach
+% The access specifiers \var{public}, \var{private}, \var{protected} and
+% \var{pusblished} can't be used in interfaces because all methods
+% of an interfaces must be public.
+parser_e_no_vars_in_interfaces=03173_E_Interfejs nie mo¿e posiadaæ pól
+% Declarations of fields aren't allowed in interfaces. An interface
+% can contain only methods
+parser_e_no_local_external=03174_E_Lokalne procedury nie mog± byæ zadeklarowane jako EXTERNAL
+% Declaring local procedures as external is not possible. Local procedures
+% get hidden parameters that will make the chance of errors very high
+parser_w_skipped_fields_before=03175_W_Niektóre pola przed "$1" nie zosta³y zainicjalizowane
+% In Delphi mode, not all fields of a typed constant record have to be
+% initialized, but the compiler warns you when it detects such situations.
+parser_e_skipped_fields_before=03176_E_Niektóre pola przed "$1" nie zosta³y zainicjalizowane
+% In all syntax modes but Delphi mode, you can't leave some fields uninitialized
+% in the middle of a typed constant record
+parser_w_skipped_fields_after=03177_W_Niektóre pola po "$1" nie zosta³y zainicjalizowane
+% You can leave some fields at the end of a type constant record uninitialized
+% (the compiler will initialize them to zero automatically). This may be the cause
+% of subtle problems.
+parser_e_varargs_need_cdecl_and_external=03178_E_Dyrektywa VarArgs bez CDecl i External
+% The varargs directive can only be used with procedures or functions
+% that are declared with \var{cdecl} and \var{external} directives. The varargs directive
+% is only meant to provide a compatible interface to C functions like printf.
+parser_e_self_call_by_value=03179_E_Self musi byæ normalnym parametrem (przekazywanym przez warto¶æ)
+% You can't declare self as a const or var parameter, it must always be
+% a call-by-value parameter
+parser_e_interface_has_no_guid=03180_E_Interfejs "$1" nie posiada identyfikatora GUID
+% When you want to assign an interface to a constant, then the interface
+% must have a GUID value set.
+parser_e_illegal_field_or_method=03181_E_Nieznana metoda albo pole klasy "$1"
+% Properties must refer to a field or method in the same class.
+parser_w_proc_overriding_calling=03182_W_Zmiana sposobu wywo³ywania z "$1" na "$2"
+% There are two directives in the procedure declaration that specify a calling
+% convention. Only the last directive will be used
+parser_e_no_procvarobj_const=03183_E_Typowane sta³e typu "procedure of object" mog± byæ inicjowane tylko NILem
+% You can't assign the address of a method to a typed constant which has a
+% 'procedure of object' type, because such a constant requires two addresses:
+% that of the method (which is known at compile time) and that of the object or
+% class instance it operates on (which can not be known at compile time).
+parser_e_default_value_only_one_para=03184_E_Domy¶lna warto¶æ mo¿e byæ przypisana tylko jednemu parametrowi
+parser_e_default_value_expected_for_para=03185_E_Domy¶lna warto¶æ wymagana dla "$1"
+parser_w_unsupported_feature=03186_W_U¿ycie (jeszcze) nieobs³ugiwanej funkcji kompilatora!
+% You're trying to force the compiler into doing something it cannot do yet.
+parser_h_c_arrays_are_references=03187_H_Tablice C s± przekazywane przez referencjê
+% Any array passed to a C functions is passed
+% by a pointer (i.e. by reference).
+parser_e_C_array_of_const_must_be_last=03188_E_Tablica sta³ych musi byæ ostatnim argumentem
+% You can not add any other argument after an \var{array of const} for
+% \var{cdecl} functions, as the size pushed on stack for this argument is
+% not known.
+parser_h_type_redef=03189_H_Powtórna definicja typu "$1"
+% This is an indicator that a previously declared type is
+% being redefined as something else. This may, or may not
+% be, a cause for errors.
+parser_w_cdecl_has_no_high=03190_W_Funkcje cdecl nie maj± parametru high
+% Functions declared with cdecl modifier do not pass an extra implicit parameter.
+parser_w_cdecl_no_openstring=03191_W_Funkcje cdecl nie obs³uguj± open strings
+%Openstring is not supported for cdecl'ared functions.
+parser_e_initialized_not_for_threadvar=03192_E_Nie mo¿na zainicjalizowaæ zmiennych zadeklarowanych jako threadvar
+% Variables declared as threadvar can not be initialized with a default value.
+% The variables will always be filled with zero at the start of a new thread.
+parser_e_msg_only_for_classes=03193_E_Dyrektywa Message jest dozwolona tylko w klasach
+% The message directive is only supported for Class types.
+parser_e_procedure_or_function_expected=03194_E_Oczekiwano procedury lub funkcji
+% A class method can only be specified for procedures and functions.
+parser_e_illegal_calling_convention=03195_W_Dyrektywa "$1" zignorowana
+% Some calling conventions are supported only by certain CPUs. I.e. most non-i386 ports support
+% only the standard ABI calling convention of the CPU.
+parser_e_no_object_reintroduce=03196_E_Nie mo¿na u¿yæ REINTRODUCE dla obiektów
+% \var{reintroduce} is not supported for objects.
+parser_e_paraloc_only_one_para=03197_E_Ka¿dy argument musi posiadaæ swoj± pozycjê
+% If locations for arguments are specified explicitly as it is required by
+% some syscall conventions, each argument must have it's only location, things
+% like \var{procedure p(i,j : longint 'r1');} aren't allowed
+parser_e_paraloc_all_paras=03198_E_Ka¿dy argument musi posiadaæ swoj± pozycjê
+% If one argument has an explicit argument location, all arguments of a procedure
+% must have one.
+parser_e_illegal_explicit_paraloc=03199_E_Nieznana pozycja argumentu
+% The location specified for an argument isn't recognized by the compiler
+parser_e_32bitint_or_pointer_variable_expected=03200_E_Oczekiwano 32 bitowej liczby typu Integer albo wska¼nika
+% The libbase for MorphOS/AmigaOS can be give only as \var{longint}, \var{dword} or any pointer variable.
+parser_e_goto_outside_proc=03201_E_Nie mo¿na u¿yæ instrukcji GOTO pomiêdzy procedurami
+% It isn't allowed to use the \var{goto} statements referencing labels outside the
+% current procedure. The following example shows the problem:
+% \begin{verbatim}
+% ...
+% procedure p1;
+% label
+% l1;
+%
+% procedure p2;
+% begin
+% goto l1; // This goto ISN'T allowed
+% end;
+%
+% begin
+% p2
+% l1:
+% end;
+% ...
+%
+% \end{verbatim}
+parser_f_too_complex_proc=03202_F_Zbyt rozbudowana procedura, spróbuj rozbiæ j± na mniejsze
+% Your procedure body is too long for the compiler. You should split the
+% procedure into multiple smaller procedures.
+parser_e_illegal_expression=03203_E_Nieprawid³owe wyra¿enie
+% This can occur under many circumstances. Mostly when trying to evaluate
+% constant expressions.
+parser_e_invalid_integer=03204_E_Nieprawid³owe wyra¿enie (powinno zwóciæ liczbê ca³kowit±)
+% You made an expression which isn't an integer, and the compiler expects the
+% result to be an integer.
+parser_e_invalid_qualifier=03205_E_Nieprawid³owy kwalifikator
+% One of the following is happening :
+% \begin{itemize}
+% \item You're trying to access a field of a variable that is not a record.
+% \item You're indexing a variable that is not an array.
+% \item You're dereferencing a variable that is not a pointer.
+% \end{itemize}
+parser_e_upper_lower_than_lower=03206_E_Górna granica zakresu jest mniejsza od dolnej
+% You are declaring a subrange, and the lower limit is higher than the high
+% limit of the range.
+parser_e_macpas_exit_wrong_param=03207_E_Parametr funkcji EXIT musi byæ nazw± procedury, w której jej u¿yto
+% Non local exit is not allowed. This error occurs only in mode MacPas.
+parser_e_illegal_assignment_to_count_var=03208_E_Nieprawid³owe przypisanie do licznika pêtli "$1"
+% The type of a \var{for} loop variable must be an ordinal type.
+% Loop variables cannot be reals or strings.
+parser_e_no_local_var_external=03209_E_Lokalne zmienne nie mog± byæ zadeklarowane jako EXTERNAL
+% Declaring local variables as external is not allowed. Only global variables can reference
+% to external variables.
+parser_e_proc_already_external=03210_E_Procedura ju¿ zadeklarowana jako EXTERNAL
+% The procedure is already declared with the EXTERNAL directive in an interface or
+% forward declaration.
+parser_w_implicit_uses_of_variants_unit=03211_W_Dopisanie modu³u Variants do sekcji uses
+% The Variant type is used in the unit without any used unit using the Variants unit. The
+% compiler has implicitly added the Variants unit to the uses list. To remove this warning
+% the Variants unit needs to be added to the uses statement.
+parser_e_no_static_method_in_interfaces=03212_E_Metody statyczne nie mog± byæ u¿yte w interfejsach
+% The specifier \var{class} and directive \var{static} can't be used in interfaces
+% because all methods of an interfaces must be public.
+parser_e_arithmetic_operation_overflow=03213_E_Wyst±pi³o przepe³nienie w operacji arytmetycznej
+% An operation on two integers values produced an overflow
+parser_e_protected_or_private_expected=03214_E_Oczekiwano "protected" albo "private"
+% \var{strict} can be only used together with \var{protected} or \var{private}.
+% \end{description}
+#
+# Type Checking
+#
+# 04049 is the last one used
+#
+% \section{Type checking errors}
+% This section lists all errors that can occur when type checking is
+% performed.
+% \begin{description}
+type_e_mismatch=04000_E_Nieprawid³owy typ
+% This can happen in many cases:
+% \begin{itemize}
+% \item The variable you're assigning to is of a different type than the
+% expression in the assignment.
+% \item You are calling a function or procedure with parameters that are
+% incompatible with the parameters in the function or procedure definition.
+% \end{itemize}
+type_e_incompatible_types=04001_E_Niezgodno¶æ typów: otrzymano "$1" oczekiwano "$2"
+% There is no conversion possible between the two types
+% Another possiblity is that they are declared in different
+% declarations:
+% \begin{verbatim}
+% Var
+% A1 : Array[1..10] Of Integer;
+% A2 : Array[1..10] Of Integer;
+%
+% Begin
+% A1:=A2; { This statement gives also this error, it
+% is due the strict type checking of pascal }
+% End.
+% \end{verbatim}
+type_e_not_equal_types=04002_E_Niezgodno¶æ typów pomiêdzy $1 i $2
+% The types are not equal
+type_e_type_id_expected=04003_E_Oczekiwano identyfikatora typu
+% The identifier is not a type, or you forgot to supply a type identifier.
+type_e_variable_id_expected=04004_E_Oczekiwano identyfikatora zmiennej
+% This happens when you pass a constant to a routine (such as \var{Inc} var or \var{Dec})
+% when it expects a variable. You can only pass variables as arguments to these functions.
+type_e_integer_expr_expected=04005_E_Oczekiwano wyra¿enia ca³kowitego, ale otrzymano "$1"
+% The compiler expects an expression of type integer, but gets a different
+% type.
+type_e_boolean_expr_expected=04006_E_Oczekiwano wyra¿enia logicznego, ale otrzymano "$1"
+% The expression must be a boolean type, it should be return true or
+% false.
+type_e_ordinal_expr_expected=04007_E_Oczekiwano wyra¿enia porz±dkowego
+% The expression must be of ordinal type, i.e., maximum a \var{Longint}.
+% This happens, for instance, when you specify a second argument
+% to \var{Inc} or \var{Dec} that doesn't evaluate to an ordinal value.
+type_e_pointer_type_expected=04008_E_Oczekiwano wska¼nika, ale otrzymano "$1"
+% The variable or expression isn't of the type \var{pointer}. This
+% happens when you pass a variable that isn't a pointer to \var{New}
+% or \var{Dispose}.
+type_e_class_type_expected=04009_E_Oczekiwano klasy, ale otrzymano "$1"
+% The variable of expression isn't of the type \var{class}. This happens
+% typically when
+% \begin{enumerate}
+% \item The parent class in a class declaration isn't a class.
+% \item An exception handler (\var{On}) contains a type identifier that
+% isn't a class.
+% \end{enumerate}
+type_e_cant_eval_constant_expr=04011_E_Nie mo¿na obliczyæ warto¶ci wyra¿enia
+% This error can occur when the bounds of an array you declared does
+% not evaluate to ordinal constants
+type_e_set_element_are_not_comp=04012_E_Niekompatybilne elementy zbioru
+% You are trying to make an operation on two sets, when the set element types
+% are not the same. The base type of a set must be the same when taking the
+% union
+type_e_set_operation_unknown=04013_E_Operacja niezaimplementowana dla zbioru
+% several binary operations are not defined for sets
+% like div mod ** (also >= <= for now)
+type_w_convert_real_2_comp=04014_W_Konwersja typu zmiennoprzecinkowego do ca³kowitego typu COMP
+% An implicit type conversion from a real type to a \var{comp} is
+% encountered. Since \var{Comp} is a 64 bit integer type, this may indicate
+% an error.
+type_h_use_div_for_int=04015_H_U¿yj DIV zamiast '/' aby wynik by³ ca³kowity
+% When hints are on, then an integer division with the '/' operator will
+% procuce this message, because the result will then be of type real
+type_e_strict_var_string_violation=04016_E_Typy stringów nie pasuj± z powodu trybu $V+
+% When compiling in \var{\{\$V+\}} mode, the string you pass as a parameter
+% should be of the exact same type as the declared parameter of the procedure.
+type_e_succ_and_pred_enums_with_assign_not_possible=04017_E_Succ i Pred nie dzia³aj± dla wyliczeñ z przypisaniami
+% When you declared an enumeration type which has assignments in it, as in C,
+% like in the following:
+% \begin{verbatim}
+% Tenum = (a,b,e:=5);
+% \end{verbatim}
+% you cannot use the \var{Succ} or \var{Pred} functions on them.
+type_e_cant_read_write_type=04018_E_Nie mo¿na zapisaæ lub odczytaæ zmiennych tego typu
+% You are trying to \var{read} or \var{write} a variable from or to a
+% file of type text, which doesn't support that. Only integer types,
+% reals, pchars and strings can be read from/written to a text file.
+% Booleans can only be written to text files.
+type_e_no_readln_writeln_for_typed_file=04019_E_Nie mo¿na u¿yæ readln ani writeln na pliku tego typu
+% \var{readln} and \var{writeln} are only allowed for text files.
+type_e_no_read_write_for_untyped_file=04020_E_Nie mo¿na u¿yæ readln ani writeln na nietypowanym pliku
+% \var{read} and \var{write} are only allowed for text or typed files.
+type_e_typeconflict_in_set=04021_E_Konflikt typów pomiêdzy elementami zbioru
+% There is at least one set element which is of the wrong type, i.e. not of
+% the set type.
+type_w_maybe_wrong_hi_lo=04022_W_lo/hi(dword/qword) zwraca starsze/m³odsze s³owo/podwójne s³owo
+% \fpc supports an overloaded version of \var{lo/hi} for \var{longint/dword/int64/qword}
+% which returns the lower/upper word/dword of the argument. TP always uses
+% a 16 bit \var{lo/hi} which returns always bits 0..7 for \var{lo} and the
+% bits 8..15 for \var{hi}. If you want the TP behavior you have
+% to type cast the argument to \var{word/integer}
+type_e_integer_or_real_expr_expected=04023_E_Oczekiwano wyra¿enia ca³kowitego lub zmiennoprzecinkowego
+% The first argument to \var{str} must a real or integer type.
+type_e_wrong_type_in_array_constructor=04024_E_Nieprawid³owy typ $1 w konstruktorze tablicy
+% You are trying to use a type in an array constructor which is not
+% allowed.
+type_e_wrong_parameter_type=04025_E_Nieprawid³owy typ parametru nr $1: Otrzymano $2, a oczekiwano $3
+% You are trying to pass an invalid type for the specified parameter.
+type_e_no_method_and_procedure_not_compatible=04026_E_Metoda i Procedura nie s± zgodne (jako zmienne)
+% You can't assign a method to a procedure variable or a procedure to a
+% method pointer.
+type_e_wrong_math_argument=04027_E_Nieprawid³owa sta³a przekazana do wbudowanej funkcji matematycznej
+% The constant argument passed to a ln or sqrt function is out of
+% the definition range of these functions.
+type_e_no_addr_of_constant=04028_E_Nie mo¿na pobraæ adresu sta³ej
+% It's not possible to get the address of a constant, because they
+% aren't stored in memory, you can try making it a typed constant.
+type_e_argument_cant_be_assigned=04029_E_Ten argument nie mo¿e byæ przekazany przez referencjê
+% Only expressions which can be on the left side of an
+% assignment can be passed as call by reference argument
+% Remark: Properties can be only
+% used on the left side of an assignment, but they can't be used as arguments
+type_e_cannot_local_proc_to_procvar=04030_E_Nie mo¿na przypisaæ lokalnej procedury/funkcji do zmiennej proceduralnej
+% It's not allowed to assign a local procedure/function to a
+% procedure variable, because the calling of local procedure/function is
+% different. You can only assign local procedure/function to a void pointer.
+type_e_no_assign_to_addr=04031_E_Nie mo¿na przypisaæ warto¶ci adresowi
+% It is not allowed to assign a value to an address of a variable, constant,
+% procedure or function. You can try compiling with -So if the identifier
+% is a procedure variable.
+type_e_no_assign_to_const=04032_E_Nie mo¿na sta³ej przypisaæ warto¶ci
+% It's not allowed to assign a value to a variable which is declared
+% as a const. This is normally a parameter declared as const, to allow
+% changing the value make the parameter as a value parameter or a var.
+type_e_array_required=04033_E_Dozwolone tylko dla tablic
+% If you are accessing a variable using an index '[<x>]' then
+% the type must be an array. In FPC mode also a pointer is allowed.
+type_e_interface_type_expected=04034_E_Oczekiwano interfejsu ale otrzymano "$1"
+type_w_mixed_signed_unsigned=04035_W_U¿ywanie zmiennych typu Cardinal w wyra¿eniach ze znakiem daje 64bitowy wynik
+% If you divide (or calculate the modulus of) a signed expression by a longword (or vice versa),
+% or if you have overflow and/or range checking turned on and use an arithmetical
+% expression (+, -, *, div, mod) in which both signed numbers and longwords appear,
+% then everything has to be evaluated in 64bit which is slower than normal
+% 32bit arithmetic. You can avoid this by typecasting one operand so it
+% matches the result type of the other one.
+type_w_mixed_signed_unsigned2=04036_W_U¿ywanie zmiennych typu Cardinal w wyra¿eniach ze znakiem mo¿e spowodowaæ b³±d zakresu w tym miejscu
+% If you use a binary operator (and, or, xor) and one of
+% the operands is a cardinal while the other one is a signed expression, then,
+% if range checking is turned on, you may get a range check error because in
+% such a case both operands are converted to cardinal before the operation is
+% carried out. You can avoid this by typecasting one operand so it
+% matches the result type of the other one.
+type_e_typecast_wrong_size_for_assignment=04037_E_Rzutowanie typów ró¿nych rozmiarów ($1 -> $2) w przypisaniu
+% Type casting to a type with a different size is not allowed when the variable is
+% used for assigning.
+type_e_array_index_enums_with_assign_not_possible=04038_E_Typ wyliczeniowy z przypisanymi warto¶ciami nie moze byæ u¿yty do ideksowania tablicy
+% When you declared an enumeration type which has assignments in it, as in C,
+% like in the following:
+% \begin{verbatim}
+% Tenum = (a,b,e:=5);
+% \end{verbatim}
+% you cannot use it as index of an array.
+type_e_classes_not_related=04039_E_Typy obiektowe "$1" i "$2" nie s± pokrewne
+% There is a typecast from one class or object to another while the class/object
+% are not related. This will probably lead to errors
+type_w_classes_not_related=04040_W_Typy obiektowe "$1" i "$2" nie s± pokrewne
+% There is a typecast from one class or object to another while the class/object
+% are not related. This will probably lead to errors
+type_e_class_or_interface_type_expected=04041_E_Oczekiwano klasy lub interfejsu ale otrzymano "$1"
+type_e_type_is_not_completly_defined=04042_E_Typ "$1" nie jest kompletnie zdefiniowany
+type_w_string_too_long=04043_W_Przekroczona maksymalna d³ugo¶æ ³añcucha
+% The size of the constant string, which is assigned to a shortstring,
+% is longer than the maximum size of the shortstring
+type_w_signed_unsigned_always_false=04044_W_To porównanie zawsze zwraca fa³sz z powodu zakresów warto¶ci zmiennych
+% There is a comparison between an unsigned value and a signed constant which is
+% less than zero. Because of type promotion, the statement will always evaluate to
+% false. Exlicitly typecast the constant to the correct range to avoid this problem.
+type_w_signed_unsigned_always_true=04045_W_To porównanie zawsze zwraca fa³sz z powodu zakresów warto¶ci zmiennych
+% There is a comparison between an unsigned value and a signed constant which is
+% less than zero. Because of type promotion, the statement will always evaluate to
+% true. Exlicitly typecast the constant to the correct range to avoid this problem.
+type_w_instance_with_abstract=04046_W_Tworzenie klasy "$1" posiadaj±cej metody abstrakcyjne
+% An instance of a class is created which contains non-implemented abstract
+% methods. This will probably lead to a runtime error 211 in the code if that
+% routine is ever called. All abstract methods should be overridden.
+type_h_in_range_check=04047_H_Lewy operand operatora IN powinien byæ wielko¶ci jednego bajta
+% The left operand of the \var{in} operator is not an ordinal or enumeration which fits
+% within 8-bits, this may lead to range check errors. The \var{in} operator
+% currently only supports a left operand which fits within a byte. In the case of
+% enumerations, the size of an element of an enumeration can be controlled with
+% the \var{\{\$PACKENUM\}} or \var{\{\$Zn\}} switches.
+type_w_smaller_possible_range_check=04048_W_Typy ró¿nej wielko¶ci - mo¿liwa utrata danych lub b³±d zakresu
+% There is an assignment to a smaller type than the source type. This means that
+% this may cause a range-check error, or may lead to possible loss of data.
+type_h_smaller_possible_range_check=04049_H_Typy ró¿nej wielko¶ci - mo¿liwa utrata danych lub b³±d zakresu
+% There is an assignment to a smaller type than the source type. This means that
+% this may cause a range-check error, or may lead to possible loss of data.
+type_e_cant_take_address_of_abstract_method=04050_E_Nie mo¿na uzyskaæ adresu metody abstrakcyjnej
+% An abstract method has no body, so the address of an abstract method can't be taken.
+type_e_operator_not_allowed=04051_E_Operator nie pasuje do operandu
+% You are trying an operator that is not available for the type of the
+% operands
+type_e_constant_expr_expected=04052_E_Oczekiwano sta³ego wyra¿enia
+% The compiler expects an constant expression, but gets a variable expression.
+type_e_operator_not_supported_for_types=04053_E_Operacja "$1" niedozwolona dla typów "$2" i "$3"
+% The operation is not allowed for the supplied types
+type_e_illegal_type_conversion=04054_E_Nieprawid³owa konwersja typów: "$1" do "$2"
+% When doing a type-cast, you must take care that the sizes of the variable and
+% the destination type are the same.
+type_h_pointer_to_longint_conv_not_portable=04055_H_Konwersja pomiêdzy typami ca³kowitymi i wska¼nikami jest nieprzeno¶na
+% If you typecast a pointer to a longint (or vice-versa), this code will not compile
+% on a machine using 64-bit for pointer storage.
+type_w_pointer_to_longint_conv_not_portable=04056_W_Konwersja pomiêdzy typami ca³kowitymi i wska¼nikami jest nieprzeno¶na
+% If you typecast a pointer to a ordinal type of a different size (or vice-versa), this can
+% cause problems. This is a warning to help finding the 32bit specific code where cardinal/longint is used
+% to typecast pointers to ordinals. A solution is to use the ptrint/ptruint types instead.
+type_e_cant_choose_overload_function=04057_E_Nie mo¿na okre¶liæ, któr± z przeci±¿onych funkcji wywo³aæ
+% You're calling overloaded functions with a parameter that doesn't correspond
+% to any of the declared function parameter lists. e.g. when you have declared
+% a function with parameters \var{word} and \var{longint}, and then you call
+% it with a parameter which is of type \var{integer}.
+type_e_illegal_count_var=04058_E_Nieprawid³owy typ licznika pêtli
+% The type of a \var{for} loop variable must be an ordinal type.
+% Loop variables cannot be reals or strings.
+% \end{description}
+#
+# Symtable
+#
+# 05055 is the last one used
+#
+% \section{Symbol handling}
+% This section lists all the messages that concern the handling of symbols.
+% This means all things that have to do with procedure and variable names.
+% \begin{description}
+sym_e_id_not_found=05000_E_Nie odnaleziono identyfikatora $1
+% The compiler doesn't know this symbol. Usually happens when you misspel
+% the name of a variable or procedure, or when you forgot to declare a
+% variable.
+sym_f_internal_error_in_symtablestack=05001_F_B³±d wewnêtrzny w SymTableStack()
+% An internal error occurred in the compiler; If you encounter such an error,
+% please contact the developers and try to provide an exact description of
+% the circumstances in which the error occurs.
+sym_e_duplicate_id=05002_E_Zduplikowany identyfikator $1
+% The identifier was already declared in the current scope.
+sym_h_duplicate_id_where=05003_H_Identyfikator ju¿ zdefiniowany w $1 w lini $2
+% The identifier was already declared in a previous scope.
+sym_e_unknown_id=05004_E_Nieznany identyfikator $1
+% The identifier encountered has not been declared, or is used outside the
+% scope where it is defined.
+sym_e_forward_not_resolved=05005_E_Deklaracaja naprzód nie rozwi±zana $1
+% This can happen in two cases:
+% \begin{itemize}
+% \item This happens when you declare a function (in the \var{interface} part, or
+% with a \var{forward} directive, but do not implement it.
+% \item You reference a type which isn't declared in the current \var{type}
+% block.
+% \end{itemize}
+sym_e_error_in_type_def=05007_E_B³±d w definicji typu
+% There is an error in your definition of a new array type:
+% \item One of the range delimiters in an array declaration is erroneous.
+% For example, \var{Array [1..1.25]} will trigger this error.
+sym_e_forward_type_not_resolved=05009_E_Brak definicji typu $1
+% A symbol was forward defined, but no declaration was encountered.
+sym_e_only_static_in_static=05010_E_Tylko zmienne statyczne mog± byæ u¿ywane w metodach statycznych
+% A static method of an object can only access static variables.
+sym_f_type_must_be_rec_or_class=05012_F_Oczekiwano rekordu lub klasy
+% The variable or expression isn't of the type \var{record} or \var{class}.
+sym_e_no_instance_of_abstract_object=05013_E_Instancje klas i obiektów z metodami abstrakcyjnymi niedozwolone
+% You are trying to generate an instance of a class which has an abstract
+% method that wasn't overridden.
+sym_w_label_not_defined=05014_W_Etykieta nie zosta³a zdefiniowana $1
+% A label was declared, but not defined.
+sym_e_label_used_and_not_defined=05015_E_Etykieta niezdefiniowana przed u¿yciem $1
+% A label was declared and used, but not defined.
+sym_e_ill_label_decl=05016_E_Nieprawid³owa deklaracja etykiety
+% This error should never happen; it occurs if a label is defined outside a
+% procedure or function.
+sym_e_goto_and_label_not_supported=05017_E_GOTO i LABEL nieobs³ugiwane (u¿yj opcji -Sg)
+% You must compile a program which has \var{label}s and \var{goto} statements
+% with the \var{-Sg} switch. By default, \var{label} and \var{goto} aren't
+% supported.
+sym_e_label_not_found=05018_E_Nie odnaleziono etykiety
+% A \var{goto label} was encountered, but the label isn't declared.
+sym_e_id_is_no_label_id=05019_E_Identyfikator nie jest etykiet±
+% The identifier specified after the \var{goto} isn't of type label.
+sym_e_label_already_defined=05020_E_Powtórna definicja etykiety
+% You are defining a label twice. You can define a label only once.
+sym_e_ill_type_decl_set=05021_E_Nieprawid³owa deklaracja typu zbiorowego
+% The declaration of a set contains an invalid type definition.
+sym_e_class_forward_not_resolved=05022_E_Brak implementacji klasy $1
+% You declared a class, but you didn't implement it.
+sym_n_unit_not_used=05023_H_Modu³ $1 nieu¿ywany w $2
+% The unit referenced in the \var{uses} clause is not used.
+sym_h_para_identifier_not_used=05024_H_Parametr $1 nieu¿ywany
+% The identifier was declared (locally or globally) but
+% was not used (locally or globally).
+sym_n_local_identifier_not_used=05025_N_Lokalna zmienna $1 nieu¿ywana
+% You have declared, but not used a variable in a procedure or function
+% implementation.
+sym_h_para_identifier_only_set=05026_H_Warto¶c przypisana do $1 nie jest nigdzie u¿yta
+% The identifier was declared (locally or globally)
+% set but not used (locally or globally).
+sym_n_local_identifier_only_set=05027_N_Warto¶c przypisana do $1 nie jest nigdzie u¿yta
+% The variable in a procedure or function
+% implementation is declared, set but never used.
+sym_h_local_symbol_not_used=05028_H_Lokalna(y) $1 $2 nie zosta³(a) u¿yta(y)
+% A local symbol is never used.
+sym_n_private_identifier_not_used=05029_N_Prywatne pole $1.$2 nieu¿ywane
+sym_n_private_identifier_only_set=05030_N_Warto¶c przypisana do lokalnego pola $1.$2 nie jest nigdzie u¿yta
+sym_n_private_method_not_used=05031_N_Metoda prywatna $1.$2 nieu¿ywana
+sym_e_set_expected=05032_E_Oczekiwano typu zbiorowego
+% The variable or expression is not of type \var{set}. This happens in an
+% \var{in} statement.
+sym_w_function_result_not_set=05033_W_Nie wygl±da na to, ¿eby warto¶æ zwracana przez funkcjê by³a ustawiona
+% You can get this warning if the compiler thinks that a function return
+% value is not set. This will not be displayed for assembler procedures,
+% or procedures that contain assembler blocks.
+sym_w_wrong_C_pack=05034_W_Typ $1 jest ¼le wyrównany dla C w bie¿±cym rekordzie
+% Arrays with sizes not multiples of 4 will be wrongly aligned
+% for C structures.
+sym_e_illegal_field=05035_E_Nieznany identyfikator pola rekordu $1
+% The field doesn't exist in the record definition.
+sym_n_uninitialized_local_variable=05036_W_Nie wygl±da na to, ¿eby lokalna zmienna $1 by³a zainicjowana
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_n_uninitialized_variable=05037_W_Nie wygl±da na to, ¿eby zmienna $1 by³a zainicjowana
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_e_id_no_member=05038_E_Identyfikator nie wskazuje ¿adnej metody ani pola $1
+% This error is generated when an identifier of a record,
+% field, or method is accessed while it is not defined.
+sym_h_param_list=05039_H_Znaleziono deklaracjê: $1
+% You get this when you use the \var{-vb} switch. In case an overloaded
+% procedure is not found, then all candidate overloaded procedures are
+% listed, with their parameter lists.
+sym_e_segment_too_large=05040_E_Element jest zbyt du¿y
+% You get this when you declare a data element whose size exceeds the
+% prescribed limit (2 Gb on 80386+/68020+ processors)
+sym_e_no_matching_implementation_found=05042_E_Nie znaleziono implementacji metody interfejsu "$1"
+% There was no matching method found which could implement the interface
+% method. Check argument types and result type of the methods.
+sym_w_deprecated_symbol=05043_W_Symbol "$1" jest przestarza³y
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{deprecated} is used. Deprecated symbols may no longer
+% be available in newer versions of the unit / library. Usage of this symbol
+% should be avoided as much as possible.
+sym_w_non_portable_symbol=05044_W_Symbolu "$1" nie da siê przenie¶æ na inne platformy
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{platform} is used. This symbol's value, usage
+% and availability is platform specific and should not be used
+% if the source code must be portable.
+sym_w_non_implemented_symbol=05055_W_Symbol "$1" nie jest zaimplementowany
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{unimplemented} is used. This symbol is defined,
+% but is not yet implemented on this specific platform.
+sym_e_cant_create_unique_type=05056_E_Nie mo¿na utworzyæ unikalnego typu z tego typu
+% Only simple types like ordinal, float and string types are supported when
+% redefining a type with \var{type newtype = type oldtype;}.
+sym_h_uninitialized_local_variable=05057_H_Zmienna lokalna "$1" mo¿e nie byæ zainicjalizowana
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_h_uninitialized_variable=05058_H_Zmienna "$1" mo¿e nie byæ zainicjalizowana
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+% \end{description}
+#
+# Codegenerator
+#
+# 06040 is the last used one
+#
+% \section{Code generator messages}
+% This section lists all messages that can be displayed if the code
+% generator encounters an error condition.
+% \begin{description}
+cg_e_parasize_too_big=06009_E_Rozmiar listy parametrów przekracza 65535 bajtów
+% The I386 processor limits the parameter list to 65535 bytes (the \var{RET}
+% instruction causes this)
+cg_e_file_must_call_by_reference=06012_E_Zmienne plikowe musz± byæ przekazywane przez referencje
+% You cannot specify files as value parameters, i.e. they must always be
+% declared \var{var} parameters.
+cg_e_cant_use_far_pointer_there=06013_E_U¿ycie wska¼nika far niedozwolone w tym miejscu
+% Free Pascal doesn't support far pointers, so you cannot take the address of
+% an expression which has a far reference as a result. The \var{mem} construct
+% has a far reference as a result, so the following code will produce this
+% error:
+% \begin{verbatim}
+% var p : pointer;
+% ...
+% p:=@mem[a000:000];
+% \end{verbatim}
+cg_e_dont_call_exported_direct=06015_E_EXPORT declared functions can't be called
+% No longer in use.
+cg_w_member_cd_call_from_method=06016_W_Mo¿liwe nieprawid³owe wywo³anie konstruktora/destruktora
+% The compiler detected that a constructor or destructor is called within a
+% a method. This will probably lead to problems, since constructors / destructors
+% require parameters on entry.
+cg_n_inefficient_code=06017_N_Niewydajny kod
+% Your statement seems dubious to the compiler.
+cg_w_unreachable_code=06018_W_Kod nie zostanie nigdy wykonany
+% You specified a construct which will never be executed. Example:
+% \begin{verbatim}
+% while false do
+% begin
+% {.. code ...}
+% end;
+% \end{verbatim}
+cg_e_cant_call_abstract_method=06020_E_Nie mo¿na bezpo¶rednio wywo³aæ metod abstrakcyjnych
+% You cannot call an abstract method directy, instead you must call a
+% overriding child method, because an abstract method isn't implemented.
+cg_d_register_weight=06027_DL_Rejestr $1 waga $2 $3
+% Debugging message. Shown when the compiler considers a variable for
+% keeping in the registers.
+cg_d_stackframe_omited=06029_DL_Pominiêto ramkê stosu
+% Some procedure/functions do not need a complete stack-frame, so it is omitted.
+% This message will be displayed when the {-vd} switch is used.
+cg_e_unable_inline_object_methods=06031_E_Metody obiektów i klas nie mog± byæ inline
+% You cannot have inlined object methods.
+cg_e_unable_inline_procvar=06032_E_Wywo³ania procedur ze zmiennych proceduralnych nie mog± byæ inline
+% A procedure with a procedural variable call cannot be inlined.
+cg_e_no_code_for_inline_stored=06033_E_Brak kodu dla procedury inline
+% The compiler couldn't store code for the inline procedure.
+cg_e_can_access_element_zero=06035_E_Brak dostêpu do zerowego elementu ansi/wide- lub longstringa, u¿yj (set)length
+% You should use \var{setlength} to set the length of an ansi/wide/longstring
+% and \var{length} to get the length of such kinf of string
+cg_e_cannot_call_cons_dest_inside_with=06037_E_Konstruktory i destruktory nie mog± byæ wywo³ywane w klauzuli 'with'
+% Inside a \var{with} clause you cannot call a constructor or destructor for the
+% object you have in the \var{with} clause.
+cg_e_cannot_call_message_direct=06038_E_Nie mo¿na wywo³aæ bezpo¶rednio metody obs³uguj±cej komunikaty
+% A message method handler method cannot be called directly if it contains an
+% explicit self argument
+cg_e_goto_inout_of_exception_block=06039_E_Skok do bloku lub poza blok exception
+% It is not allowed to jump in or outside of an exception block like \var{try..finally..end;}:
+% \begin{verbatim}
+% label 1;
+%
+% ...
+%
+% try
+% if not(final) then
+% goto 1; // this line will cause an error
+% finally
+% ...
+% end;
+% 1:
+% ...
+% \end{verbatim}
+cg_e_control_flow_outside_finally=06040_E_Break, Continue i Exit nie s± dozwolone w bloku finally
+% It isn't allowed to use the control flow statements \var{break},
+% \var{continue} and \var{exit}
+% inside a finally statement. The following example shows the problem:
+% \begin{verbatim}
+% ...
+% try
+% p;
+% finally
+% ...
+% exit; // This exit ISN'T allowed
+% end;
+% ...
+%
+% \end{verbatim}
+% If the procedure \var{p} raises an exception the finally block is
+% executed. If the execution reaches the exit, it's unclear what to do:
+% exiting the procedure or searching for another exception handler
+cg_w_parasize_too_big=06041_W_Rozmiar parametrów przekroczy³ limit dla niektórych procesorów
+% This indicates that you are declaring more than 64K of parameters, which
+% might not be supported on other processor targets.
+cg_w_localsize_too_big=06042_W_Rozmiar zmiennych lokalnych przekroczy³ limit dla dla niektórych procesorów
+% This indicates that you are declaring more than 32K of lcoal variables, which
+% might not be supported on other processor targets.
+cg_e_localsize_too_big=06043_E_Rozmiar zmiennych lokalnych przekroczy³ dopuszczalny limit
+% This indicates that you are declaring more than 32K of lcoal variables, which
+% is not supported by this processor.
+cg_e_break_not_allowed=06044_E_BREAK mo¿na u¿yæ tylko wewn±trz pêtli
+% You're trying to use \var{break} outside a loop construction.
+cg_e_continue_not_allowed=06045_E_CONTINUE mo¿na u¿yæ tylko wewn±trz pêtli
+% You're trying to use \var{continue} outside a loop construction.
+% \end{description}
+# EndOfTeX
+
+#
+# Assembler reader
+#
+# 07097 is the last used one
+#
+asmr_d_start_reading=07000_DL_Rozpoczêcie parsowania bloku asemblera w stylu $1
+% This informs you that an assembler block is being parsed
+asmr_d_finish_reading=07001_DL_Zakoñczenie parsowania bloku asemblera w stylu $1
+% This informs you that an assembler block has finished.
+asmr_e_none_label_contain_at=07002_E_¯aden identyfikator (poza etykietami) nie mo¿e zawieraæ @
+% A identifier which isn't a label can't contain a @.
+asmr_e_building_record_offset=07004_E_B³±d tworzenia offsetu rekordu
+% There has an error occured while building the offset of a record/object
+% structure, this can happend when there is no field specified at all or
+% an unknown field identifier is used.
+asmr_e_offset_without_identifier=07005_E_OFFSET u¿yty bez identyfikatora
+% You can only use OFFSET with an identifier. Other syntaxes aren't
+% supported
+asmr_e_type_without_identifier=07006_E_TYPE u¿yte bez identyfikatora
+% You can only use TYPE with an identifier. Other syntaxes aren't
+% supported
+asmr_e_no_local_or_para_allowed=07007_E_Nie mo¿na u¿ywaæ lokalnych zmiennych i parametrów w tym miejscu
+% You can't use a local variable or parameter here, mostly because the
+% addressing of locals and parameters is done using the frame pointer register so the
+% address can't be obtained directly.
+asmr_e_need_offset=07008_E_Nale¿y tu u¿yæ OFFSET
+% You need to use OFFSET <id> here to get the address of the identifier.
+asmr_e_need_dollar=07009_E_Nale¿y u¿yæ tu $
+% You need to use $<id> here to get the address of the identifier.
+asmr_e_cant_have_multiple_relocatable_symbols=07010_E_Mo¿na u¿yæ tylko jednego symbolu relokacyjnego
+% You can't have more than one relocatable symbol (variable/typed constant)
+% in one argument.
+asmr_e_only_add_relocatable_symbol=07011_E_Symbole relokacyjne mog± byæ tylko dodane
+% Relocatable symbols (variable/typed constant) can't be used with other
+% operators. Only addition is allowed.
+asmr_e_invalid_constant_expression=07012_E_Nieprawid³owe sta³e wyra¿enie
+% There is an error in the constant expression.
+asmr_e_relocatable_symbol_not_allowed=07013_E_Nie mo¿na u¿yæ symbolu relokacyjnego w tym miejscu
+% You can't use a relocatable symbol (variable/typed constant) here.
+asmr_e_invalid_reference_syntax=07014_E_Nieprawid³owa sk³adnia referencji
+% There is an error in the reference.
+asmr_e_local_para_unreachable=07015_E_Nie mo¿na osi±gn±æ $1 z tego kodu
+% You can not read directly the value of local or para
+% of a higher level in assembler code (except for
+% local assembler code without parameter nor locals).
+asmr_e_local_label_not_allowed_as_ref=07016_E_Lokalne symbole/etykiety nie s± dozwolone jako referencje
+% You can't use local symbols/labels as references
+asmr_e_wrong_base_index=07017_E_Nieprawid³owe u¿ycie rejestru indeksu i bazy
+% There is an error with the base and index register, they are
+% probably incorrect
+asmr_w_possible_object_field_bug=07018_W_Mo¿liwy b³±d w obs³ugiwaniu pola obiektu
+% Fields of objects or classes can be reached directly in normal or objfpc
+% modes but TP and Delphi modes treat the field name as a simple offset.
+asmr_e_wrong_scale_factor=07019_E_Nieprawid³owa skala
+% The scale factor given is wrong, only 1,2,4 and 8 are allowed
+asmr_e_multiple_index=07020_E_U¿ycie wielu rejestrów indeksu
+% You are trying to use more than one index register
+asmr_e_invalid_operand_type=07021_E_Nieprawid³owy typ operandu
+% The operand type doesn't match with the opcode used
+asmr_e_invalid_string_as_opcode_operand=07022_E_Nieprawid³owy string jako operand: $1
+% The string specified as operand is not correct with this opcode
+asmr_w_CODE_and_DATA_not_supported=07023_W_@CODE i @DATA nieobs³ugiwane
+% @CODE and @DATA are unsupported and are ignored.
+asmr_e_null_label_ref_not_allowed=07024_E_Puste etykiety referencji s± niedozwolone
+asmr_e_expr_zero_divide=07025_E_Dzielenie przez zero
+% There is a division by zero in a constant expression
+asmr_e_expr_illegal=07026_E_Nieprawid³owe wyra¿enie
+% There is an illegal expression in a constant expression
+asmr_e_escape_seq_ignored=07027_E_Sekwencja zignorowana: $1
+% There is a C-styled string, but the escape sequence in the string
+% is unknown, and is therefore ignored
+asmr_e_invalid_symbol_ref=07028_E_Nieprawid³owa referencja symbolu
+asmr_w_fwait_emu_prob=07029_W_Fwait mo¿e powodowaæ problemy emulacji z emu387
+asmr_w_fadd_to_faddp=07030_W_$1 bez operandu przet³umaczone na $1P
+asmr_w_enter_not_supported_by_linux=07031_W_Instrukcja ENTER nie jest obs³ugiwana przez j±dro Linuksa
+% ENTER instruction can generate a stack page fault that is not
+% caught correctly by the i386 Linux page handler.
+asmr_w_calling_overload_func=07032_W_Wywo³anie przeci±¿onej funkcji z poziomu asemblera
+% There is a call to an overloaded method in the assembler block,
+% this might be the sign there is a problem
+asmr_e_unsupported_symbol_type=07033_E_Nieobs³ugiwany typ symbolu dla operandu
+asmr_e_constant_out_of_bounds=07034_E_Warto¶æ sta³a przekracza zakres
+asmr_e_error_converting_decimal=07035_E_B³±d konwersji liczby dziesiêtnej $1
+% A constant decimal value does not have the correct syntax
+asmr_e_error_converting_octal=07036_E_B³±d konwersji liczby ósemkowej $1
+% A constant octal value does not have the correct syntax
+asmr_e_error_converting_binary=07037_E_B³±d konwersji liczby dwójkowej $1
+% A constant binary value does not have the correct syntax
+asmr_e_error_converting_hexadecimal=07038_E_B³±d konwersji liczby szesnastkowej $1
+% A constant hexadecimal value does not have the correct syntax
+asmr_h_direct_global_to_mangled=07039_H_$1 przet³umaczone na $2
+asmr_w_direct_global_is_overloaded_func=07040_W_$1 jest przypisane do przeci±¿onej funkcji
+asmr_e_cannot_use_SELF_outside_a_method=07041_E_Nie mo¿na u¿yæ SELF poza metod±
+% There is a reference to the \var{self} symbol while it is not
+% allowed. \var{self} can only be referenced inside methods
+asmr_e_cannot_use_OLDEBP_outside_nested_procedure=07042_E_Nie mo¿na u¿yæ OLDEBP poza zagnie¿d¿on± procedur±
+% There is a reference to the \var{oldebp} symbol while it is not
+% allowed. \var{oldebp} can only be referenced inside nested routines
+asmr_e_void_function=07043_W_Procedury nie mog± zwracaæ warto¶ci w kodzie asemblera
+% Trying to return a value while in a procedure. A procedure
+% does not have any return value
+asmr_e_SEG_not_supported=07044_E_SEG nie obs³ugiwane
+asmr_e_size_suffix_and_dest_dont_match=07045_E_Przyrostek okre¶laj±cy rozmiar nie pasuje do ¼ród³a lub celu
+% The register size and the opcode size suffix don't match. This is
+% probably an error in the assembler statement
+asmr_w_size_suffix_and_dest_dont_match=07046_W_Przyrostek okre¶laj±cy rozmiar nie pasuje do ¼ród³a lub celu
+% The register size and the opcode size suffix don't match. This is
+% probably an error in the assembler statement
+asmr_e_syntax_error=07047_E_B³±d sk³adni asemblera
+% There is an assembler syntax error
+asmr_e_invalid_opcode_and_operand=07048_E_Nieprawid³owa kombinacja opkodu i operandu
+% The opcode cannot be used with this type of operand
+asmr_e_syn_operand=07049_E_B³±d sk³adni asemblera w operandzie
+asmr_e_syn_constant=07050_E_B³±d sk³adni asemblera w sta³ej
+asmr_e_invalid_string_expression=07051_E_Nieprawid³owe wyra¿enie ze stringiem
+asmr_w_const32bit_for_address=07052_W_Sta³a $1 prawdopodobnie nie powinna byæ wska¼nikiem
+% A constant expression represents an address which does not fit
+% into a pointer. The address is probably incorrect
+asmr_e_unknown_opcode=07053_E_Nieznany opkod $1
+% This opcode is not known
+asmr_e_invalid_or_missing_opcode=07054_E_Nieprawid³owy opkod lub brak opkodu
+asmr_e_invalid_prefix_and_opcode=07055_E_Nieprawid³owa kombinacja prefiksu i opkodu: $1
+asmr_e_invalid_override_and_opcode=07056_E_Nieprawid³owa kombinacja override i opkodu: $1
+asmr_e_too_many_operands=07057_E_Zbyt du¿o operandów
+% There are too many operands for this opcode. Check your
+% assembler syntax
+asmr_w_near_ignored=07058_W_NEAR zignorowane
+asmr_w_far_ignored=07059_W_FAR zignorowane
+asmr_e_dup_local_sym=07060_E_Zduplikowany symbol lokalny $1
+asmr_e_unknown_local_sym=07061_E_Niezdefiniowany symbol lokalny $1
+asmr_e_unknown_label_identifier=07062_E_Nieznana etykieta $1
+asmr_e_invalid_register=07063_E_Nieprawid³owa nazwa rejestru
+% There is an unknown register name used as operand.
+asmr_e_invalid_fpu_register=07064_E_Nieprawid³owa nazwa rejestru zmiennoprzecinkowego
+% There is an unknown register name used as operand.
+asmr_w_modulo_not_supported=07066_W_Modulo nieobs³ugiwane
+asmr_e_invalid_float_const=07067_E_Nieprawid³owa sta³a zmiennoprzecinkowa $1
+% The floating point constant declared in an assembler block is
+% invalid.
+asmr_e_invalid_float_expr=07068_E_Nieprawid³owe wyra¿enie zmiennoprzecinkowe
+% The floating point expression declared in an assembler block is
+% invalid.
+asmr_e_wrong_sym_type=07069_E_Nieprawid³owy typ symbolu
+asmr_e_cannot_index_relative_var=07070_E_Nie mo¿na ideksowaæ rejestrem zmiennej lokalnej/parametru
+% Trying to index using a base register a symbol which is already relative
+% to a register. This is not possible, and will probably lead to crashes.
+asmr_e_invalid_seg_override=07071_E_Invalid segment override expression
+asmr_w_id_supposed_external=07072_W_Identifier $1 supposed external
+% There is a reference to an undefined symbol. This will not result
+% in an error, since the symbol might be external, but may cause
+% problems at link time if the symbol is not defined anywhere.
+asmr_e_string_not_allowed_as_const=07073_E_Stringi nie mog± byæ sta³ymi
+% Character strings are not allowed as constants.
+asmr_e_no_var_type_specified=07074_Nie okre¶lono typu zmiennej
+% The syntax expects a type idenfitifer after the dot, but
+% none was found.
+asmr_w_assembler_code_not_returned_to_text=07075_E_brak powrotu do sekcji text w kodzie asemblera
+% There was a directive in the assembler block to change sections,
+% but there is a missing return to the text section at the end
+% of the assembler block. This might cause errors during link time.
+asmr_e_not_directive_or_local_symbol=07076_E_To nie jest ani dyrektywa, ani symbol lokalny: $1
+% This symbol is unknown.
+asmr_w_using_defined_as_local=07077_E_U¿ycie zdefiniowanej nazwy jako lokalnej etykiety
+asmr_e_dollar_without_identifier=07078_E_Brak identyfikatora przy znaku dolara
+% A constant expression has an identifier which does not start with
+% the $ symbol.
+asmr_w_32bit_const_for_address=07079_W_32bitowa sta³a u¿yta jako adres
+% A constant was used as an address. This is probably an error,
+% since using absolute addresses will probably not work.
+asmr_n_align_is_target_specific=07080_N_.align nie jest przeno¶ne miêdzy platformami, u¿yj .balign lub .p2align
+% Using the .align directive is platform specific, and its meaning will vary
+% from one platform to another.
+asmr_e_cannot_access_field_directly_for_parameters=07081_E_Nie mo¿na odwo³ywaæ siê bezpo¶rednio do pól parametrów
+% You should load the parameter first into a register and then access the
+% fields using that register.
+asmr_e_cannot_access_object_field_directly=07082_E_Nie mo¿na odwo³ywaæ siê bezpo¶rednio do pól obiektów/klas
+% You should load the self pointer first into a register and then access the
+% fields using the register as base. By default the self pointer is available
+% in the esi register on i386.
+asmr_e_unable_to_determine_reference_size=07083_E_Nie okre¶lono rozmiaru operandu
+% You should specify explicitly a size for the reference, because
+% the compiler is unable to determine what size (byte,word,dword,etc.) it
+% should use for the reference.
+asmr_e_cannot_use_RESULT_here=07084_E_Nie mo¿na u¿yæ RESULT w tej funkcji
+% Some functions which return complex types cannot use the \var{result}
+% keyword.
+asmr_w_adding_explicit_args_fXX=07086_W_"$1" bez operandu przet³umaczone na "$1 %st,%st(1)"
+asmr_w_adding_explicit_first_arg_fXX=07087_W_"$1 %st(n)" przet³umaczone na "$1 %st,%st(n)"
+asmr_w_adding_explicit_second_arg_fXX=07088_W_"$1 %st(n)" przet³umaczone na "$1 %st(n),%st"
+asmr_e_invalid_char_smaller=07089_E_Znak < niedozwolony w tym miejscu
+% The shift operator requires the << characters. Only one
+% of those characters was found.
+asmr_e_invalid_char_greater=07090_E_Znak > niedozwolony w tym miejscu
+% The shift operator requires the >> characters. Only one
+% of those characters was found.
+asmr_w_align_not_supported=07093_W_ALIGN nieobs³ugiwane
+asmr_e_no_inc_and_dec_together=07094_E_Inc i Dec nie mog± wystêpowaæ razem
+% Trying to use an increment and a decrement within the same
+% opcode on the 680x0. This is impossible.
+asmr_e_invalid_reg_list_in_movem=07095_E_Nieprawid³owa lista rejestrów dla movem
+% Trying to use the \var{movem} opcode with invalid registers
+% to save or restore.
+asmr_e_invalid_reg_list_for_opcode=07096_E_Nieprawid³owa lista rejestrów dla opkodu
+asmr_e_higher_cpu_mode_required=07097_E_Ta instrukcja wymaga wy¿szego typu procesora ($1)
+% Trying to use an instruction which is not supported in the current
+% cpu mode. Use a higher cpu generation to be able to use this
+% opcode in your assembler block
+asmr_w_unable_to_determine_reference_size_using_dword=07098_W_Nie okre¶lono rozmiaru operandów, domy¶lne u¿ycie DWORD
+% You should specify explicitly a size for the reference, because
+% the compiler is unable to determine what size (byte,word,dword,etc.) it
+% should use for the reference. This warning is only used in Delphi mode where
+% it falls back to use DWORD as default.
+asmr_e_illegal_shifterop_syntax=07099_E_B³±d sk³adni przy operandzie shifter
+% ARM only; ARM assembler supports a so called shifter operand. The used syntax isn't
+% a valid shifter operand. Example for an operation with shifter operand:
+% \begin{verbatim}
+% asm
+% orr r2,r2,r2,lsl #8
+% end;
+% \end{verbatim}
+#
+# Assembler/binary writers
+#
+# 08018 is the last used one
+#
+asmw_f_too_many_asm_files=08000_F_Zbyt du¿o plików asemblera
+% With smartlinking enabled, there are too many assembler
+% files generated. Disable smartlinking.
+asmw_f_assembler_output_not_supported=08001_F_Wybrany typ wyj¶ciowy asemblera nieobs³ugiwany
+asmw_f_comp_not_supported=08002_F_Comp nieobs³ugiwany
+asmw_f_direct_not_supported=08003_F_Direct nieobs³ugiwane przy zapisywaniu bezpo¶rednim
+% Direct assembler mode is not supported for binary writers.
+asmw_e_alloc_data_only_in_bss=08004_E_Alokacja danych jest dozwolona tylko w sekcji bss
+asmw_f_no_binary_writer_selected=08005_F_Nie wybrano sposobu zapisywania binariów
+asmw_e_opcode_not_in_table=08006_E_Asm: Brak opkodu $1 w tablicy
+asmw_e_invalid_opcode_and_operands=08007_E_Asm: $1 nieprawid³owa kombinacja opkodu i operandów
+asmw_e_16bit_not_supported=08008_E_Asm: 16bitowe referencje nieobs³ugiwane
+asmw_e_invalid_effective_address=08009_E_Asm: Nieprawid³owy adres efektywny
+asmw_e_immediate_or_reference_expected=08010_E_Asm: Immediate or reference expected
+asmw_e_value_exceeds_bounds=08011_E_Asm: $1 warto¶æ przekracza zakres $2
+asmw_e_short_jmp_out_of_range=08012_E_Asm: Krótki skok poza zasiêg $1
+asmw_e_undefined_label=08013_E_Asm: Nieznana etykieta $1
+asmw_e_comp_not_supported=08014_E_Asm: Typ Comp nieobs³ugiwany dla tego celu
+asmw_e_extended_not_supported=08015_E_Asm: Typ Extended nieobs³ugiwany dla tego celu
+asmw_e_duplicate_label=08016_E_Asm: Zduplikowana etykieta $1
+asmw_e_redefined_label=08017_E_Asm: Etykieta powtórnie zdefiniowana $1
+asmw_e_first_defined_label=08018_E_Asm: Najpierw zdefiniowana tutaj
+asmw_e_invalid_register=08019_E_Asm: Nieprawid³owy rejestr $1
+
+#
+# Executing linker/assembler
+#
+# 09034 is the last used one
+#
+# BeginOfTeX
+%
+% \section{Errors of assembling/linking stage}
+% This section lists errors that occur when the compiler is processing the
+% command line or handling the configuration files.
+% \begin{description}
+exec_w_source_os_redefined=09000_W_Zmieniono ¼ród³owy system operacyjny
+exec_i_assembling_pipe=09001_I_Asemblowanie (potok) $1
+exec_d_cant_create_asmfile=09002_E_Nie mo¿na utworzyæ plików asemblera: $1
+% The mentioned file can't be created. Check if you have got
+% access permissions to create this file
+exec_e_cant_create_objectfile=09003_E_Nie mo¿na utworzyæ pliku: $1
+% The mentioned file can't be created. Check if you've
+% got access permissions to create this file
+exec_e_cant_create_archivefile=09004_E_Nie mo¿na utworzyæ pliku: $1
+% The mentioned file can't be created. Check if you've
+% access permissions to create this file
+exec_e_assembler_not_found=09005_E_Assembler $1 nie znaleziony, prze³±czenie na zewnêtrzn± asemblacjê
+exec_t_using_assembler=09006_T_U¿ywanie assemblera: $1
+exec_e_error_while_assembling=09007_E_B³±d asemblera, kod wyj¶cia $1
+% There was an error while assembling the file using an external assembler.
+% Consult the documentation of the assembler tool to find out more information
+% on this error.
+exec_e_cant_call_assembler=09008_E_Nie mo¿na wywo³aæ asemblera, b³±d $1 prze³±czenie na zewnêtrzn± asemblacjê
+exec_i_assembling=09009_I_Asemblowanie $1
+exec_i_assembling_smart=09010_I_Asemblowanie do linkowania smart $1
+exec_w_objfile_not_found=09011_W_Obiekt $1 nieodnaleziony, linkowanie mo¿e siê nie powie¶æ!
+% One of the object file is missing, and linking will probably fail.
+% Check your paths.
+exec_w_libfile_not_found=09012_W_Biblioteka $1 nieodnaleziona, Linkowanie mo¿e siê nie powie¶æ!
+% One of the library file is missing, and linking will probably fail.
+% Check your paths.
+exec_e_error_while_linking=09013_E_B³±d podczas linkowania
+% Generic error while linking.
+exec_e_cant_call_linker=09014_E_Nie mo¿na wywo³aæ linkera, prze³±czenie na zewnêtrzne linkowanie
+exec_i_linking=09015_I_Linkowanie $1
+exec_e_util_not_found=09016_E_Narzêdzie $1 nieodnalezione, prze³±czenie na zewnêtrzne linkowanie
+exec_t_using_util=09017_T_Uruchamianie $1
+exec_e_exe_not_supported=09018_E_Tworzenie plików wykonywalnych nieobs³ugiwane
+exec_e_dll_not_supported=09019_E_Tworzenie bibliotek dynamicznych/wspó³dzielonych nieobs³ugiwane
+exec_i_closing_script=09020_I_Zamykanie skryptu $1
+exec_e_res_not_found=09021_E_Kompilator zasobów nieodnaleziony, prze³±czenie na tryb zewnêtrzny
+exec_i_compilingresource=09022_I_Kompilacja zasobu $1
+exec_t_unit_not_static_linkable_switch_to_smart=09023_T_Modu³ $1 nie mo¿e byæ linkowany statycznie, prze³±czenie na linkowanie smart
+exec_t_unit_not_smart_linkable_switch_to_static=09024_T_Modu³ $1 nie moze byæ linkowany smart, prze³±czenie na linkowanie statyczne
+exec_t_unit_not_shared_linkable_switch_to_static=09025_T_Modu³ $1 nie mo¿e byæ linkowany dynamicznie, prze³±czenie na linkowanie statyczne
+exec_e_unit_not_smart_or_static_linkable=09026_E_Modu³ $1 nie mo¿e byæ linkowany statycznie ani smart
+exec_e_unit_not_shared_or_static_linkable=09027_E_Modu³ $1 nie mo¿e byæ linkowany statycznie ani dynamicznie
+%\end{description}
+# EndOfTeX
+
+#
+# Executable information
+#
+execinfo_f_cant_process_executable=09128_F_Nie mo¿na przetwarzaæ pliku $1
+execinfo_f_cant_open_executable=09129_F_Nie mo¿na otworzyæ pliku wykonywalnego $1
+execinfo_x_codesize=09130_X_Rozmiar kodu: $1 bajtów
+execinfo_x_initdatasize=09131_X_Rozmiar zainicjowanych danych: $1 bajtów
+execinfo_x_uninitdatasize=09132_X_Rozmiar niezainicjowanych danych: $1 bajtów
+execinfo_x_stackreserve=09133_X_Zarezerwowany rozmiar stosu: $1 bajtów
+execinfo_x_stackcommit=09134_X_Aktywny rozmiar stosu: $1 bajtów
+
+#
+# Unit loading
+#
+# 10041 is the last used one
+#
+# BeginOfTeX
+% \section{Unit loading messages.}
+% This section lists all messages that can occur when the compiler is
+% loading a unit from disk into memory. Many of these mesages are
+% informational messages.
+% \begin{description}
+unit_t_unitsearch=10000_T_Poszukiwanie modu³u: $1
+% When you use the \var{-vt}, the compiler tells you where it tries to find
+% unit files.
+unit_t_ppu_loading=10001_T_Otwieranie PPU $1
+% When the \var{-vt} switch is used, the compiler tells you
+% what units it loads.
+unit_u_ppu_name=10002_U_Nazwa PPU: $1
+% When you use the \var{-vu} flag, the unit name is shown.
+unit_u_ppu_flags=10003_U_Flagi PPU: $1
+% When you use the \var{-vu} flag, the unit flags are shown.
+unit_u_ppu_crc=10004_U_Crc PPU: $1
+% When you use the \var{-vu} flag, the unit CRC check is shown.
+unit_u_ppu_time=10005_U_Czas PPU: $1
+% When you use the \var{-vu} flag, the time the unit was compiled is shown.
+unit_u_ppu_file_too_short=10006_U_Plik PPU zbyt krótki
+% The ppufile is too short, not all declarations are present.
+unit_u_ppu_invalid_header=10007_U_Nieprawid³owy nag³ówek PPU (brak PPU na pocz±tku)
+% A unit file contains as the first three bytes the ascii codes of \var{PPU}
+unit_u_ppu_invalid_version=10008_U_Nieprawid³owa wersja PPU $1
+% This unit file was compiled with a different version of the compiler, and
+% cannot be read.
+unit_u_ppu_invalid_processor=10009_U_PPU jest skompilowany dla innego procesora
+% This unit file was compiled for a different processor type, and
+% cannot be read
+unit_u_ppu_invalid_target=10010_U_PPU skompilowany dla innej platformy docelowej
+% This unit file was compiled for a different target, and
+% cannot be read
+unit_u_ppu_source=10011_U_¬ród³o PPU: $1
+% When you use the \var{-vu} flag, the unit CRC check is shown.
+unit_u_ppu_write=10012_U_Zapisywanie $1
+% When you specify the \var{-vu} switch, the compiler will tell you where it
+% writes the unit file.
+unit_f_ppu_cannot_write=10013_F_Nie mo¿na zapisaæ pliku PPU
+% An error occurred when writing the unit file.
+unit_f_ppu_read_error=10014_F_B³±d podczas czytania pliku PPU
+% This means that the unit file was corrupted, and contains invalid
+% information. Recompilation will be necessary.
+unit_f_ppu_read_unexpected_end=10015_F_Nieoczekiwane zakoñczenie pliku PPU
+% Unexpected end of file. This may mean that the PPU file is
+% corrupted.
+unit_f_ppu_invalid_entry=10016_F_Nieprawid³owy plik PPU: $1
+% The unit the compiler is trying to read is corrupted, or generated with a
+% newer version of the compiler.
+unit_f_ppu_dbx_count_problem=10017_F_B³±d podczas liczenia PPU Dbx
+% There is an inconsistency in the debugging information of the unit.
+unit_e_illegal_unit_name=10018_E_Nieprawid³owa nazwa modu³u: $1
+% The name of the unit does not match the file name.
+unit_f_too_much_units=10019_F_Zbyt du¿o modu³ów
+% \fpc has a limit of 1024 units in a program. You can change this behavior
+% by changing the \var{maxunits} constant in the \file{files.pas} file of the
+% compiler, and recompiling the compiler.
+unit_f_circular_unit_reference=10020_F_Zapêtlone nawi±zanie pomiêdzy modu³ami $1 i $2
+% Two units are using each other in the interface part. This is only allowed
+% in the \var{implementation} part. At least one unit must contain the other one
+% in the \var{implementation} section.
+unit_f_cant_compile_unit=10021_F_Nie mo¿na skompilowaæ modu³u $1, brak ¼róde³
+% A unit was found that needs to be recompiled, but no sources are
+% available.
+unit_f_cant_find_ppu=10022_F_Nie mo¿na znale¼æ modu³u $1
+% You tried to use a unit of which the PPU file isn't found by the
+% compiler. Check your config files for the unit pathes
+unit_w_unit_name_error=10023_W_Nie znaleziono modu³u $1 ale istnieje $2
+unit_f_unit_name_error=10024_F_Szukano modu³u $1 ale znaleziono tylko $2
+% Dos truncation of 8 letters for unit PPU files
+% may lead to problems when unit name is longer than 8 letters.
+unit_w_switch_us_missed=10025_W_Kompilowanie modu³u System wymaga u¿ycia prze³±cznika -Us
+% When recompiling the system unit (it needs special treatment), the
+% \var{-Us} must be specified.
+unit_f_errors_in_unit=10026_F_Napotkano $1 b³êdów podczas kompilacji modu³u, zatrzymanie
+% When the compiler encounters a fatal error or too many errors in a module
+% then it stops with this message.
+unit_u_load_unit=10027_U_£adowanie z $1 ($2) modu³u $3
+% When you use the \var{-vu} flag, which unit is loaded from which unit is
+% shown.
+unit_u_recompile_crc_change=10028_U_Rekompilacja $1, suma kontrolna zmieniona dla $2
+unit_u_recompile_source_found_alone=10029_U_Rekompilacja $1, znaleziono tylko ¼ród³o
+% When you use the \var{-vu} flag, these messages tell you why the current
+% unit is recompiled.
+unit_u_recompile_staticlib_is_older=10030_U_Rekompilacja modu³u, biblioteka statyczna jest starsza ni¿ plik ppu
+% When you use the \var{-vu} flag, the compiler warns if the static library
+% of the unit are older than the unit file itself.
+unit_u_recompile_sharedlib_is_older=10031_U_Rekompilacja modu³u, biblioteka wspó³dzielona jest starsza ni¿ plik ppu
+% When you use the \var{-vu} flag, the compiler warns if the shared library
+% of the unit are older than the unit file itself.
+unit_u_recompile_obj_and_asm_older=10032_U_Rekompilacja modu³u, obj i asm s± starsze ni¿ plik ppu
+% When you use the \var{-vu} flag, the compiler warns if the assembler or
+% object file of the unit are older than the unit file itself.
+unit_u_recompile_obj_older_than_asm=10033_U_Rekompilacja modu³u, obj jest starszy ni¿ asm
+% When you use the \var{-vu} flag, the compiler warns if the assembler
+% file of the unit is older than the object file of the unit.
+unit_u_parsing_interface=10034_U_Parsowanie czê¶ci interface modu³u $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% parsing the interface part of the unit
+unit_u_parsing_implementation=10035_U_Parsowanie czê¶ci implementation modu³u $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% parsing the implementation part of the unit
+unit_u_second_load_unit=10036_U_Drugie za³adowanie pliku $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% recompiling a unit for the second time. This can happend with interdepend
+% units.
+unit_u_check_time=10037_U_Sprawdzanie pliku PPU: $1 czas: $2
+% When you use the \var{-vu} flag, the compiler show the filename and
+% date and time of the file which a recompile depends on
+### The following two error msgs is currently disabled.
+#unit_h_cond_not_set_in_last_compile=10038_H_Warunek $1 nie by³ ustawiony na pocz±tku ostatniej kompilacji modu³u $2
+#% when recompilation of an unit is required the compiler will check that
+#% the same conditionals are set for the recompiliation. The compiler has
+#% found a conditional that currently is defined, but was not used the last
+#% time the unit was compiled.
+#unit_h_cond_set_in_last_compile=10039_H_Warunek $1 nie by³ ustawiony na pocz±tku ostatniej kompilacji modu³u $2
+#% when recompilation of an unit is required the compiler will check that
+#% the same conditionals are set for the recompiliation. The compiler has
+#% found a conditional that was used the last time the unit was compiled, but
+#% the conditional is currently not defined.
+unit_w_cant_compile_unit_with_changed_incfile=10040_W_Nie mo¿na skompilowaæ modu³u $1, znaleziono zmodyfikowane pliki include
+% A unit was found to have modified include files, but
+% some source files were not found, so recompilation is impossible.
+unit_h_source_modified=10041_H_Plik $1 jest nowszy ni¿ plik $2
+% A modified source file for a unit was found that was compiled with the
+% release flag (-Ur). The unit will not implicitly be recompiled because
+% this release flag is set.
+unit_u_ppu_invalid_fpumode=10042_U_U¿ycie modu³u skompilowanego z innym formatem zapisu liczb zmiennoprzecinkowych
+% Trying to compile code while using units which were not compiled with
+% the same floating point format mode. Either all code should be compiled
+% with FPU emulation on, or with FPU emulation off.
+unit_u_loading_interface_units=10043_U_£adowanie modu³ów z czê¼ci interface modu³u $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% loading the units defined in the interface part of the unit.
+unit_u_loading_implementation_units=10044_U_£adowanie modu³ów z czê¼ci implementation modu³u $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% loading the units defined in the implementation part of the unit.
+unit_u_interface_crc_changed=10045_U_Zmieniona suma CRC sekcji interface modu³u $1
+% When you use the \var{-vu} flag, the compiler warns that it the
+% CRC calculated for the interface has been changed after the implementation
+% has been parsed.
+unit_u_implementation_crc_changed=10046_U_Zmieniona suma CRC sekcji implementation modu³u $1
+% When you use the \var{-vu} flag, the compiler warns that it the
+% CRC calculated has been changed after the implementation
+% has been parsed.
+unit_u_finished_compiling=10047_U_Zakoñczono kompilacjê modu³u $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has finished compiling the unit.
+unit_u_add_depend_to=10048_U_Dodanie zale¿no¶ci $1 do $2
+% When you use the \var{-vu} flag, the compiler warns that it
+% has added a dependency between the two units.
+unit_u_no_reload_is_caller=10049_U_Ominiêcie prze³adowania modu³u, to ten sam modu³: $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has will not reload the unit because it is the unit that wants
+% to load this unit
+unit_u_no_reload_in_second_compile=10050_U_Ominiêcie prze³adowania modu³u, trwa druga kompilacaja: $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has will not reload the unit because it is already in a second recompile
+unit_u_flag_for_reload=10051_U_Flaga do prze³adowania: $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has to reload the unit
+unit_u_forced_reload=10052_U_Wymuszone prze³adowanie modu³u
+% When you use the \var{-vu} flag, the compiler warns that it
+% has is reloading the unit because it was required
+unit_u_previous_state=10053_U_Poprzedni stan modu³u $1: $2
+% When you use the \var{-vu} flag, the compiler shows the
+% previous state of the unit
+unit_u_second_compile_unit=10054_U_Ju¿ kompilowane $1, ustawienie drugiej kompilacji
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% recompiling a unit for the second time. This can happend with interdepend
+% units.
+unit_u_loading_unit=10055_U_£adowanie modu³u $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% loading the unit.
+unit_u_finished_loading_unit=10056_U_Zakoñczenie ³adowania modu³u $1
+% When you use the \var{-vu} flag, the compiler warns that it finished
+% loading the unit.
+unit_u_registering_new_unit=10057_U_Rejestrowanie nowego modu³u $1
+% When you use the \var{-vu} flag, the compiler warns that it has
+% found a new unit and registers it in the internal lists.
+unit_u_reresolving_unit=10058_U_Powtórne odnajdowanie modu³u $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has to recalculate the internal data of the unit
+unit_u_skipping_reresolving_unit=10059_U_Ominiêcie powtórnego odnajdowania modu³u $1, ci±gle ³aduje u¿ywane modu³y
+% When you use the \var{-vu} flag, the compiler warns that it
+% skips to recalculate the internal data of the unit because there
+% is no data to recalculate
+% \end{description}
+# EndOfTeX
+
+#
+# Options
+#
+# 11039 is the last used one
+#
+option_usage=11000_O_$1 [opcje] <nazwapliku> [opcje]
+# BeginOfTeX
+%
+% \section{Command-line handling errors}
+% This section lists errors that occur when the compiler is processing the
+% command line or handling the configuration files.
+% \begin{description}
+option_only_one_source_support=11001_W_Obs³ugiwany tylko jeden plik ¼ród³owy
+% You can specify only one source file on the command line. The first
+% one will be compiled, others will be ignored. This may indicate that
+% you forgot a \var{'-'} sign.
+option_def_only_for_os2=11002_W_Plik DEF mo¿e byæ stworzony tylko pod OS/2
+% This option can only be specified when you're compiling for OS/2
+option_no_nested_response_file=11003_E_Zagnie¿d¿enia plików nieobs³ugiwane
+% you cannot nest response files with the \var{@file} command-line option.
+option_no_source_found=11004_F_Brak nazwy pliku w lini poleceñ
+% The compiler expects a source file name on the command line.
+option_no_option_found=11005_N_Brak opcji w pliku konfiguracyjnym $1
+% The compiler didn't find any option in that config file.
+option_illegal_para=11006_E_Nieprawid³owy parametr: $1
+% You specified an unknown option.
+option_help_pages_para=11007_H_-? wy¶wietla pomoc
+% When an unknown option is given, this message is diplayed.
+option_too_many_cfg_files=11008_F_Za du¿o zagnie¿d¿onych plików konfiguracyjnych
+% You can only nest up to 16 config files.
+option_unable_open_file=11009_F_Nie mo¿na otworzyæ pliku konfiguracyjnego $1
+% The option file cannot be found.
+option_reading_further_from=11010_D_Czytanie dalszych opcji z $1
+% Displayed when you have notes turned on, and the compiler switches
+% to another options file.
+option_target_is_already_set=11011_W_Cel jest ju¿ ustawiony na: $1
+% Displayed if more than one \var{-T} option is specified.
+option_no_shared_lib_under_dos=11012_W_Biblioteki wspó³dzielone nie s± obs³ugiwane w DOSie, reverting to static
+% If you specify \var{-CD} for the \dos platform, this message is displayed.
+% The compiler supports only static libraries under \dos
+option_too_many_ifdef=11013_F_Za du¿o IF(N)DEF
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_too_many_endif=11014_F_Za du¿o ENDIF
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_too_less_endif=11015_F_Warunek wci±¿ otwarty na koñcu pliku
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_no_debug_support=11016_W_Generowanie informacji do debugowania nieobs³ugiwane przez t± wersjê kompilatora
+% It is possible to have a compiler executable that doesn't support
+% the generation of debugging info. If you use such an executable with the
+% \var{-g} switch, this warning will be displayed.
+option_no_debug_support_recompile_fpc=11017_H_Spróbuj przekompilowaæ z -dGDB
+% It is possible to have a compiler executable that doesn't support
+% the generation of debugging info. If you use such an executable with the
+% \var{-g} switch, this warning will be displayed.
+option_obsolete_switch=11018_E_U¿ycie przedawnionego prze³±cznika $1
+% this warns you when you use a switch that is not needed/supported anymore.
+% It is recommended that you remove the switch to overcome problems in the
+% future, when the switch meaning may change.
+option_obsolete_switch_use_new=11019_E_U¿ycie przedawnionego prze³±cznika $1, proszê u¿yæ $2
+% this warns you when you use a switch that is not supported anymore. You
+% must now use the second switch instead.
+% It is recommended that you change the switch to overcome problems in the
+% future, when the switch meaning may change.
+option_switch_bin_to_src_assembler=11020_N_Prze³±czenie na domy¶lny zapis asemblera
+% this notifies you that the assembler has been changed because you used the
+% -a switch which can't be used with a binary assembler writer.
+option_incompatible_asm=11021_W_Wybrane wyj¶cie asemblera "$1" nie jest zgodne z "$2"
+option_asm_forced=11022_W_Wymuszenie u¿ycia asemblera "$1"
+% The assembler output selected can not generate
+% object files with the correct format. Therefore, the
+% default assembler for this target is used instead.
+option_using_file=11026_T_Czytanie opcji z pliku $1
+% Options are also read from this file
+option_using_env=11027_T_Czytanie opcji ze zmiennej ¶rodowiskowej $1
+% Options are also read from this environment string
+option_handling_option=11028_D_Obs³ugiwanie opcji "$1"
+% Debug info that an option is found and will be handled
+option_help_press_enter=11029__*** naci¶nij enter ***
+option_start_reading_configfile=11030_H_Rozpoczêto czytanie pliku konfiguracyjnego $1
+% Starting of config file parsing.
+option_end_reading_configfile=11031_H_Zakoñczono czytanie pliku konfiguracyjnego $1
+% End of config file parsing.
+option_interpreting_option=11032_D_Interpretowanie opcji "$1"
+option_interpreting_firstpass_option=11036_D_Interpretowanie opcji "$1"
+option_interpreting_file_option=11033_D_Interpretowanie opcji plikowej "$1"
+option_read_config_file=11034_D_Czytanie pliku konfiguracyjnego "$1"
+option_found_file=11035_D_Znaleziono nazwê pliku ¼ród³owego "$1"
+% Additional infos about options, displayed
+% when you have debug option turned on.
+option_code_page_not_available=11039_E_Nieznana strona kodowa
+%\end{description}
+# EndOfTeX
+
+#
+# Logo (option -l)
+#
+option_logo=11023_[
+Free Pascal Compiler wersja $FPCFULLVERSION [$FPCDATE] dla $FPCCPU
+Copyright (c) 1993-2011 by Florian Klaempfl
+]
+
+#
+# Info (option -i)
+#
+option_info=11024_[
+Free Pascal Compiler wersja $FPCVERSION
+
+Data kompilatora : $FPCDATE
+Platforma docelowa: $FPCCPU
+
+Wspierane platformy:
+ $OSTARGETS
+
+Wspierane instrukcje CPU:
+ $INSTRUCTIONSETS
+
+Wspierane instrukcje FPU:
+ $FPUINSTRUCTIONSETS
+
+Ten program jest oparty na GNU General Public Licence
+Przeczytaj COPYING.FPC aby dowiedzieæ siê wiêcej
+
+Zg³aszanie b³êdów, sugestii itp.
+ http://bugs.freepascal.org
+lub
+ bugs@freepascal.org
+]
+
+#
+# Help pages (option -? and -h)
+#
+# The first character on the line indicates who will display this
+# line, the current possibilities are :
+# * = every target
+# 3 = 80x86 targets
+# 6 = 680x0 targets
+# e = in extended debug mode only
+# P = PowerPC targets
+# S = Sparc targets
+# V = Virtual machine targets
+# The second character also indicates who will display this line,
+# (if the above character was TRUE) the current possibilities are :
+# * = everyone
+# g = with GDB info supported by the compiler
+# O = OS/2
+# L = UNIX systems
+# The third character represents the indentation level.
+#
+option_help_pages=11025_[
+**0*_wpisz + po prze³±czniku aby go aktywowaæ, - aby dezaktywowaæ
+**1a_kompilator nie usuwa wygenerowanego pliku asemblera
+**2al_wypisuje numery linii do pliku asemblera
+**2an_wypisuje informacje o wêz³ach do pliku asemblera
+*L2ap_u¿ycie potoków zamiast tymczasowych plików asemblera
+**2ar_wypisuje alokacje/zwalnianie rejestrów do pliku asemblera
+**2at_wypisuje tymczasowe alokacje/zwalnianie do pliku asemblera
+**1A<x>_format wyj¶ciowy:
+**2Adefault_u¿ycie domy¶lnego asemblera
+3*2Aas_asemblacja przy u¿yciu GNU AS
+3*2Anasmcoff_plik coff (Go32v2) przy u¿yciu Nasm
+3*2Anasmelf_plik elf32 (Linux) przy u¿yciu Nasm
+3*2Anasmwin32_plik obj (Win32) przy u¿yciu Nasm
+3*2Anasmwdosx_plik obj (Win32/WDOSX) przy u¿yciu Nasm
+3*2Awasm_plik obj przy u¿yciu Wasm (Watcom)
+3*2Anasmobj_plik obj przy u¿yciu Nasm
+3*2Amasm_plik obj przy u¿yciu Masm (Microsoft)
+3*2Atasm_plik obj przy u¿yciu Tasm (Borland)
+3*2Aelf_bezpo¶redni zapis do pliku elf32 (Linux)
+3*2Acoff_bezpo¶redni zapis do pliku coff (Go32v2)
+3*2Apecoff_bezpo¶redni zapis do pliku pecoff (Win32)
+4*2Aas_asemblacja przy u¿yciu GNU AS
+6*2Aas_o-file (Unix) przy u¿yciu GNU AS
+6*2Agas_asembler GNU Motorola
+6*2Amit_sk³adnia MIT (dawniej GAS)
+6*2Amot_standardowy asembler Motorola
+A*2Aas_asemblacja przy u¿yciu GNU AS
+P*2Aas_asemblacja przy u¿yciu GNU AS
+S*2Aas_asemblacja przy u¿yciu GNU AS
+**1b_generuje informacje przegl±darki
+**2bl_generuje informacje o lokalnych symbolach
+**1B_budowanie wszystkich modu³ów
+**1C<x>_opcje generacji kodu:
+**2Cc<x>_ustawia domy¶lny sposób wywo³ania funkcji/procedur na <x>
+**2CD_tworzenie tak¿e bibliotek dynamicznych (niedostêpne)
+**2Ce_kompilacja z emulowanymi opkodami zmiennoprzecinkowymi
+**2Cf<x>_ustawia u¿ywany zbiór instrukcji FPU na <x> (u¿yj "fpc -i", aby zobaczyæ mo¿liwe warto¶ci)
+**2Cg_generowanie kodu PIC
+**2Ch<n>_rozmiar sterty w bajtach (pomiêdzy 1023 i 67107840)
+**2Ci_sprawdzanie operacji wej¶cia/wyj¶cia
+**2Cn_pominiêcie etapu linkowania
+**2Co_sprawdzanie przepe³nienia liczb ca³kowitych
+**2Cp<x>_ustawia u¿ywany zbiór instrukcji na <x> (u¿yj "fpc -i", aby zobaczyæ mo¿liwe warto¶ci)
+**2Cr_sprawdzanie zakresu
+**2CR_sprawdzanie poprawno¶ci wywo³ywania metod obiektów
+**2Cs<n>_ustawienie rozmiar stosu na <n>
+**2Ct_sprawdzanie stosu
+**2CX_tworzenie bibliotek smartlinked
+**1d<x>_zdefiniowanie symbolu <x>
+*O1D_generacja pliku DEF
+*O2Dd<x>_ustawienie opisu na <x>
+**2Dv<x>_ustawienie wersji DLL na <x>
+*O2Dw_aplikacja PM
+**1e<x>_ustawienie ¶cie¿ki do asemblera i linkera
+**1E_to samo co -Cn
+**1F<x>_ustawianie nazw i ¶cie¿ek:
+**2Fa<x>[,y]_wczytuje <x> (i [y]) zanim zostani± wczytane modu³y z sekcji USES
+**2Fc<x>_ustawienie strony kodowej ¼róde³ na <x>
+**2FD<x>_ustawienie katalogu z narzêdziami kompilatora
+**2Fe<x>_przekierowanie komunikatów o b³êdach do pliku <x>
+**2FE<x>_ustawienie katalogu dla skompilowanych programów/modu³ów na <x>
+**2Fi<x>_dodanie <x> do ¶cie¿ki include'ów
+**2Fl<x>_dodanie <x> do ¶cie¿ki bibliotek
+**2FL<x>_u¿ycie <x> jako dynamicznego linkera
+**2Fo<x>_dodanie <x> do ¶cie¿ki obiektów
+**2Fr<x>_³adowanie pliku <x> z komunikatami b³êdów
+**2Fu<x>_dodanie <x> do ¶cie¿ki modu³ów
+**2FU<x>_ustawienie katalogu dla skompilowanych modu³ów, uniewa¿nia -FE
+*g1g_generacja informacji debuggera:
+*g2gc_generacja kodu sprawdzaj±cego wska¼niki
+*g2gd_u¿ycie dbx
+*g2gg_u¿ycie gsym
+*g2gh_u¿ycie modu³u ¶ledzenia sterty(do wykrywania wycieków pamiêci)
+*g2gl_u¿ycie modu³u z informacjami o numerach linii programu
+*g2gv_generacja kodu mo¿liwego do ¶ledzenia przy pomocy valgrind
+*g2gw_generacja informacji debuggera dwarf
+**1i_informacje
+**2iD_zwraca datê kompilatora
+**2iV_zwraca wersjê kompilatora
+**2iSO_zwraca OS kompilatora
+**2iSP_zwraca typ procesora kompilatora
+**2iTO_zwraca docelowy OS
+**2iTP_zwraca docelowy typ kompilatora
+**1I<x>_dodanie <x> do ¶cie¿ki include'ów
+**1k<x>_podanie <x> do linkera
+**1l_wypisanie logo
+**1M<x>_ustawia tryb jêzyka na <x>
+**2Mfpc_dialekt free pascala (domy¶lny)
+**2Mobjfpc_w³±czenie niektórych rozszerzeñ Delphi 2
+**2Mdelphi_kompatybilno¶æ z Delphi
+**2Mtp_kompatybilno¶æ z TP/BP 7.0
+**2Mgpc_kompatybilno¶æ z gpc
+**2Mmac_kompatybilno¶æ z dialektami pascala na Macintosha
+**1n_zignorowanie standardowego pliku konfiguracyjnego
+**1N<x>optymalizacje wêz³ów drzewa
+**2Nu_rozwijanie pêtli
+**1o<x>_zmiana nazwy skompilowanego programu na <x>
+3*1O<x>_optymalizacje:
+3*2Og_generacja mniejszego kodu
+3*2OG_generacja szybszego kodu (domy¶lne)
+3*2Or_trzymanie niektórych zmiennych w rejestrach
+3*2Ou_w³±czenie niepewnych optymalizacji (zobacz w dokumentacji)
+3*2O1_optymalizacje pierwszego stopnia (szybkie)
+3*2O2_optymalizacje drugiego stopnia (-O1 + wolniejsze)
+3*2O3_optymalizacje trzeciego stopnia (powtarzane maksymalnie 5 razy -02)
+3*2Op<x>_procesor docelowy:
+3*3Op1_ustawienie procesora docelowego na 386/486
+3*3Op2_ustawienie procesora docelowego na Pentium/PentiumMMX (tm)
+3*3Op3_ustawienie procesora docelowego na PPro/PII/c6x86/K6 (tm)
+6*2Og_generacja mniejszego kodu
+6*2OG_generacja szybszego kodu (domy¶lne)
+6*2Ox_maksymalne optymalizacje (ci±gle zawieraj± B£ÊDY!!!)
+6*2O0_ustawia docelowy procesor na MC68000
+6*2O2_ustawia docelowy procesor na MC68020+ (domy¶lne)
+**1pg_generacja kodu do profilowania przy pomocy gprof (definiuje FPC_PROFILE)
+**1R<x>_styl asemblera u¿ywanego w ¼ród³ach:
+**2Rdefault_u¿ycie domy¶lnego asemblera
+3*2Ratt_styl AT&T
+3*2Rintel_styl Intel
+6*2RMOT_styl Motorola
+**1S<x>_opcje sk³adni:
+**2S2_to samo co -Mobjfpc
+**2Sc_wspieranie operatorów C (*=,+=,/= oraz -=)
+**2Sa_do³±czanie kodu asercji
+**2Sd_to samo co -Mdelphi
+**2Se<x>_opcje b³êdów. <x> jest kombinacj±:
+**3*_<n> : kompilator zatrzymuje siê po <x> b³êdach (domy¶lnie 1)
+**3*_w : kompilator zatrzymuje siê tak¿e na ostrze¿eniach
+**3*_n : kompilator zatrzymuje siê tak¿e na notkach
+**3*_h : kompilator zatrzymuje siê tak¿e na podpowiedziach
+**2Sg_zezwolenie na LABEL i GOTO
+**2Sh_u¿ycie ansistringów
+**2Si_wspieranie INLINE w stylu C++
+**2SI<x>_ustawia styl interfejsów na <x>
+**3SIcom_interfejsy kompatybilne z COM (domy¶lne)
+**3SIcorba_interfejsy kompatybilne z CORBA
+**2Sm_wspieranie makr jak w C (opcja globalna)
+**2So_to samo co -Mtp
+**2Sp_to samo co -Mgpc
+**2Ss_konstruktory musz± mieæ nazwê init (destruktory - done)
+**1s_pominiêcie wywo³ania asemblera i linkera
+**2sh_generacja skryptu do linkowania na ho¶cie
+**2st_generacja skryptu do linkowania na celu
+**2sr_ominiêcie fazy alokowania rejestrów (u¿ywaj z -alr)
+**1T<x>_docelowy system operacyjny:
+3*2Temx_OS/2 na EMX (wliczaj±c EMX/RSX extender)
+3*2Tfreebsd_FreeBSD
+3*2Tgo32v2_DJ Delorie DOS extender - wersja 2
+3*2Tlinux_Linux
+3*2Tnetbsd_NetBSD
+3*2Tnetware_Novell Netware Module (clib)
+3*2Tnetwlibc_Novell Netware Module (libc)
+3*2Topenbsd_OpenBSD
+3*2Tos2_OS/2 / eComStation
+3*2Tsunos_SunOS/Solaris
+3*2Twatcom_DOS extendery zgodne z Watcomem
+3*2Twdosx_WDOSX DOS extender
+3*2Twin32_32-bitowy Windows
+4*2Tlinux_Linux
+6*2Tamiga_Commodore Amiga
+6*2Tatari_Atari ST/STe/TT
+6*2Tlinux_Linux-68k
+6*2Tmacos_Macintosh m68k (nie wspierane)
+6*2Tpalmos_PalmOS
+A*2Tlinux_Linux
+P*2Tdarwin_Darwin i MacOS X na PowerPC
+P*2Tlinux_Linux na PowerPC
+P*2Tmacos_MacOS (klasyczny) na PowerPC
+P*2Tmorphos_MorphOS
+S*2Tlinux_Linux
+**1u<x>_usuniêcie symbolu <x>
+**1U_opcje modu³ów:
+**2Un_pominiêcie sprawdzania nazwy modu³u
+**2Ur_generacja modu³u do wydania (release)
+**2Us_kompilacja modu³u system
+**1v<x>_obszerne opisy. <x> jest kombinacj± nastêpuj±cych liter i cyfr:
+**2*_e : pokazuje b³êdy (domy¶lne) 0 : nic nie pokazuje (oprócz b³êdów)
+**2*_w : pokazuje ostrze¿enia u : pokazuje informacje o modu³ach
+**2*_n : pokazuje notki t : pokazuje próbowane/u¿yte pliki
+**2*_h : pokazuje podpowiedzi c : pokazuje warunki
+**2*_i : pokazuje ogólne informacje d : pokazuje informacje debugowania
+**2*_l : pokazuje numery lini r : tryb kompatybilno¶ci z Rhide/GCC
+**2*_a : pokazuje wszystko x : informacje o pliku exe (tylko Win32)
+**2*_v : zapisuje plik fpcdebug.txt p : zapisuje tree.log z drzewem
+**2*_ z du¿± ilo¶ci± informacji parsowania
+3*1W<x>_opcje dla Win32 i podobnych
+3*2WB_tworzenie relokacyjnego obrazu
+3*2WB<x>_ustawienie bazy obrazu na szesnastkow± warto¶æ <x>
+3*2WC_aplikacja konsolowa
+3*2WD_u¿ycie DEFFILE do eksportu funkcji z DLLa lub EXE
+3*2WF_aplikacja pe³noekranowa (tylko OS/2)
+3*2WG_aplikacja graficzna
+3*2WN_nie generuje kodu relokacji (potrzebne do debugowania)
+3*2WR_generuje kod relokacji
+P*2WC_aplikacja konsolowa (tylko MacOS)
+P*2WG_aplikacja graficzna (tylko MacOS)
+P*2WT_aplikacja narzêdziowa (narzêdzie MPW, tylko MacOS)
+**1X_opcje plików wykonywalnych:
+**2Xc_podaje --shared do linkera (tylko Unix)
+**2Xd_nie u¿ywa standardowej ¶cie¿ki bibliotek (potrzebne do cross-kompilacji)
+**2XD_linkowanie dynamiczne (definiuje FPC_LINK_DYNAMIC)
+**2Xm_generuje link map
+**2XM<x>_ustawia nazwê g³ównego bloku programu (domy¶lnie 'main')
+**2XP<x>_poprzedza nazwê binutils tekstem <x>
+**2Xr<x>_ustawia ¶cie¿kê bibliotek na <x> (potrzebne do cross-kompilacji)
+**2Xs_wyciêcie wszystkich symboli z pliku
+**2XS_linkowanie statycznie (domy¶lne)(definiuje FPC_LINK_STATIC)
+**2Xt_linkuje z bibliotekami statycznymi (podaje -static do linkera)
+**2XX_linkowanie smart (definiuje FPC_LINK_SMART)
+**1*_
+**1?_pokazanie pomocy
+**1h_pokazanie pomocy bez zatrzymywania
+]
+
+#
+# The End...
diff --git a/closures/compiler/msg/errorpt.msg b/closures/compiler/msg/errorpt.msg
new file mode 100644
index 0000000000..76abb6d4ed
--- /dev/null
+++ b/closures/compiler/msg/errorpt.msg
@@ -0,0 +1,3447 @@
+#
+# This file is part of the Free Pascal Compiler
+# Copyright (c) 1999-2009 by the Free Pascal Development team
+#
+# Portuguese (CP850) language file for Free Pascal Compiler
+# Contributed by Marcelo B Paula, based on errore.msg SVN Rev.19883
+# Former translator: Ari Ricardo Ody <ary.odi at japinfo.com.br>
+#
+# See the file COPYING.FPC, included in this distribution,
+# for details about the copyright.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#
+#
+# The constants are build in the following order:
+# <part>_<type>_<txtidentifier>
+#
+# <part> is the part of the compiler the message is used
+# asmr_ assembler parsing
+# asmw_ assembler writing/binary writers
+# unit_ unit handling
+# scan_ scanner
+# parser_ parser
+# type_ type checking
+# general_ general info
+# exec_ calls to assembler, external linker, binder
+# link_ internal linker
+#
+# <type> the type of the message it should normally used for
+# f_ fatal error
+# e_ error
+# w_ warning
+# n_ note
+# h_ hint
+# i_ info
+# l_ add linenumber
+# u_ used
+# t_ tried
+# c_ conditional
+# d_ debug message
+# x_ executable informations
+# o_ normal (e.g., "press enter to continue")
+#
+# <type> can contain a minus sign at the beginning to mark that
+# the message is off by default. Look at type_w_explicit_string_cast
+# for example.
+
+#
+# General
+#
+# 01023 is the last used one
+#
+# BeginOfTeX
+% \section{General compiler messages}
+% This section gives the compiler messages which are not fatal, but which
+% display useful information. The number of such messages can be
+% controlled with the various verbosity level \var{-v} switches.
+% \begin{description}
+general_t_compilername=01000_T_Compilador: $1
+% When the \var{-vt} switch is used, this line tells you what compiler
+% is used.
+general_d_sourceos=01001_D_SO Compilador: $1
+% When the \var{-vd} switch is used, this line tells you what the source
+% operating system is.
+general_i_targetos=01002_I_SO Alvo: $1
+% When the \var{-vd} switch is used, this line tells you what the target
+% operating system is.
+general_t_exepath=01003_T_Usando caminho execut vel: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for its binaries.
+general_t_unitpath=01004_T_Usando caminho unidade: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for compiled units. You can set this path with the \var{-Fu} option.
+general_t_includepath=01005_T_Usando caminho inclusäes: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for its include files (files used in \var{\{\$I xxx\}} statements).
+% You can set this path with the \var{-Fi} option.
+general_t_librarypath=01006_T_Usando caminho biblioteca: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for the libraries. You can set this path with the \var{-Fl} option.
+general_t_objectpath=01007_T_Usando caminho objeto: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for object files you link in (files used in \var{\{\$L xxx\}} statements).
+% You can set this path with the \var{-Fo} option.
+general_i_abslines_compiled=01008_I_$1 linhas compiladas, $2 seg$3
+% When the \var{-vi} switch is used, the compiler reports the number
+% of lines compiled, and the time it took to compile them (real time,
+% not program time).
+general_f_no_memory_left=01009_F_Mem¢ria insuficiente
+% The compiler doesn't have enough memory to compile your program. There are
+% several remedies for this:
+% \begin{itemize}
+% \item If you're using the build option of the compiler, try compiling the
+% different units manually.
+% \item If you're compiling a huge program, split it up into units, and compile
+% these separately.
+% \item If the previous two don't work, recompile the compiler with a bigger
+% heap. (You can use the \var{-Ch} option for this, \seeo{Ch}.)
+% \end{itemize}
+general_i_writingresourcefile=01010_I_Gravando arquivo Tabela Recursos 'String': $1
+% This message is shown when the compiler writes the Resource String Table
+% file containing all the resource strings for a program.
+general_e_errorwritingresourcefile=01011_E_Gravando arquivo Tabela Recursos 'String': $1
+% This message is shown when the compiler encounters an error when writing
+% the Resource String Table file.
+general_i_fatal=01012_I_Fatal:
+% Prefix for Fatal Errors.
+general_i_error=01013_I_Erro:
+% Prefix for Errors.
+general_i_warning=01014_I_Aviso:
+% Prefix for Warnings.
+general_i_note=01015_I_Nota:
+% Prefix for Notes.
+general_i_hint=01016_I_Dica:
+% Prefix for Hints.
+general_e_path_does_not_exist=01017_E_Caminho "$1" nÆo existe
+% The specified path does not exist.
+general_f_compilation_aborted=01018_F_Compila‡Æo abortada
+% Compilation was aborted.
+general_text_bytes_code=01019_bytes (c¢digo gerado)
+% The size of the generated executable code, in bytes.
+general_text_bytes_data=01020_bytes (dados gerados)
+% The size of the generated program data, in bytes.
+general_i_number_of_warnings=01021_I_$1 aviso(s) emitido(s)
+% Total number of warnings issued during compilation.
+general_i_number_of_hints=01022_I_$1 dica(s) emitida(s)
+% Total number of hints issued during compilation.
+general_i_number_of_notes=01023_I_$1 nota(s) emitida(s)
+% Total number of notes issued during compilation.
+general_f_ioerror=01024_F_Erro E/S: $1
+% During compilation an I/O error happened which allows no further compilation.
+general_f_oserror=01025_F_Erro do sistema operacional: $1
+% During compilation an operanting system error happened which allows no further compilation.
+% \end{description}
+#
+# Scanner
+#
+# 02087 is the last used one
+#
+% \section{Scanner messages.}
+% This section lists the messages that the scanner emits. The scanner takes
+% care of the lexical structure of the pascal file, i.e. it tries to find
+% reserved words, strings, etc. It also takes care of directives and
+% conditional compilation handling.
+% \begin{description}
+scan_f_end_of_file=02000_F_Fim de arquivo inesperado
+% This typically happens in one of the following cases:
+% \begin{itemize}
+% \item The source file ends before the final \var{end.} statement. This
+% happens mostly when the \var{begin} and \var{end} statements aren't
+% balanced;
+% \item An include file ends in the middle of a statement.
+% \item A comment was not closed.
+% \end{itemize}
+scan_f_string_exceeds_line=02001_F_'String' excendo linha
+% There is a missing closing ' in a string, so it occupies
+% multiple lines.
+scan_f_illegal_char=02002_F_caractere ilegal "$1" ($2)
+% An illegal character was encountered in the input file.
+scan_f_syn_expected=02003_F_Erro sintaxe, "$1" esperado, mas "$2" encontrado
+% This indicates that the compiler expected a different token than
+% the one you typed. It can occur almost anywhere it is possible to make an error
+% against the Pascal language.
+scan_t_start_include_file=02004_TL_Iniciando leitura arquivo de inclusäes $1
+% When you provide the \var{-vt} switch, the compiler tells you
+% when it starts reading an included file.
+scan_w_comment_level=02005_W_N¡vel coment rio $1 encontrado
+% When the \var{-vw} switch is used, then the compiler warns you if
+% it finds nested comments. Nested comments are not allowed in Turbo Pascal
+% and Delphi, and can be a possible source of errors.
+scan_n_ignored_switch=02008_N_Ignorar chave compilador "$1"
+% With \var{-vn} on, the compiler warns if it ignores a switch.
+scan_w_illegal_switch=02009_W_Chave ilegal compilador "$1"
+% You included a compiler switch (i.e. \var{\{\$... \}}) which the compiler
+% does not recognise.
+scan_w_switch_is_global=02010_W_Chave global compilador fora de lugar
+% The compiler switch is misplaced, and should be located at
+% the start of the unit or program.
+scan_e_illegal_char_const=02011_E_Constante caractere ilegal
+% This happens when you specify a character with its ASCII code, as in
+% \var{\#96}, but the number is either illegal, or out of range.
+scan_f_cannot_open_input=02012_F_Imposs¡vel abrir arquivo "$1"
+% \fpc cannot find the program or unit source file you specified on the
+% command line.
+scan_f_cannot_open_includefile=02013_F_Imposs¡vel abrir arquivo de inclusäes "$1"
+% \fpc cannot find the source file you specified in a \var{\{\$include ..\}}
+% statement.
+scan_e_illegal_pack_records=02015_E_Especificador alinhamento registro ilegal "$1"
+% You are specifying \var{\{\$PACKRECORDS n\} } or \var{\{\$ALIGN n\} }
+% with an illegal value for \var{n}. For \$PACKRECORDS valid alignments are 1, 2, 4, 8, 16, 32, C,
+% NORMAL, DEFAULT, and for \$ALIGN valid alignments are 1, 2, 4, 8, 16, 32, ON,
+% OFF. Under mode MacPas \$ALIGN also supports MAC68K, POWER and RESET.
+scan_e_illegal_pack_enum=02016_E_Especificador tamanho-m¡nimo enumera‡Æo ilegal "$1"
+% You are specifying the \var{\{\$PACKENUM n\}} with an illegal value for
+% \var{n}. Only 1,2,4, NORMAL or DEFAULT is valid here.
+scan_e_endif_expected=02017_E_$ENDIF esperado para $1 $2 definido em $3 linha $4
+% Your conditional compilation statements are unbalanced.
+scan_e_preproc_syntax_error=02018_E_Erro sintaxe enquanto analisando uma expressÆo compila‡Æo condicional
+% There is an error in the expression following the \var{\{\$if ..\}}, \var{\{\$ifc \}}
+% or \var{\{\$setc \}} compiler directives.
+scan_e_error_in_preproc_expr=02019_E_Avaliando uma expressÆo compila‡Æo condicional
+% There is an error in the expression following the \var{\{\$if ..\}}, $ifc or $setc compiler
+% directives.
+scan_w_macro_cut_after_255_chars=02020_W_Conte£do macro limitada ao tamanho de 255 caracteres
+% The contents of macros cannot be longer than 255 characters.
+scan_e_endif_without_if=02021_E_ENDIF sem IF(N)DEF
+% Your \var{\{\$IFDEF ..\}} and {\{\$ENDIF\}} statements aren't balanced.
+scan_f_user_defined=02022_F_Definido pelo usu rio: $1
+% A user defined fatal error occurred. See also the \progref.
+scan_e_user_defined=02023_E_Definido pelo usu rio: $1
+% A user defined error occurred. See also the \progref.
+scan_w_user_defined=02024_W_Definido pelo usu rio: $1
+% A user defined warning occurred. See also the \progref.
+scan_n_user_defined=02025_N_Definido pelo usu rio: $1
+% A user defined note was encountered. See also the \progref.
+scan_h_user_defined=02026_H_Definido pelo usu rio: $1
+% A user defined hint was encountered. See also the \progref.
+scan_i_user_defined=02027_I_Definido pelo usu rio: $1
+% User defined information was encountered. See also the \progref.
+scan_e_keyword_cant_be_a_macro=02028_E_Palavra-chave redefinida como macro nÆo tem efeito
+% You cannot redefine keywords with macros.
+scan_f_macro_buffer_overflow=02029_F_Transbordamento "buffer" macro durante leitura ou expansÆo de uma macro
+% Your macro or its result was too long for the compiler.
+scan_w_macro_too_deep=02030_W_ExpansÆo de macros excede profundidade de 16.
+% When expanding a macro, macros have been nested to a level of 16.
+% The compiler will expand no further, since this may be a sign that
+% recursion is used.
+scan_w_wrong_styled_switch=02031_W_chaves compilador nÆo sÆo suportadas no estilo de coment rio //
+% Compiler switches should be in normal Pascal style comments.
+scan_d_handling_switch=02032_DL_Chave manipula‡Æo "$1"
+% When you set debugging info on (\var{-vd}) the compiler tells you when it
+% is evaluating conditional compile statements.
+scan_c_endif_found=02033_CL_ENDIF $1 encontrado
+% When you turn on conditional messages (\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifdef_found=02034_CL_IFDEF $1 encontrado, $2
+% When you turn on conditional messages (\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifopt_found=02035_CL_IFOPT $1 encontrado, $2
+% When you turn on conditional messages (\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_if_found=02036_CL_IF $1 encontrado, $2
+% When you turn on conditional messages (\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifndef_found=02037_CL_IFNDEF $1 encontrado, $2
+% When you turn on conditional messages (\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_else_found=02038_CL_ELSE $1 encontrado, $2
+% When you turn on conditional messages (\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_skipping_until=02039_CL_Pulando at‚...
+% When you turn on conditional messages (\var{-vc}), the compiler tells you
+% where it encounters conditional statements, and whether it is skipping or
+% compiling parts.
+scan_i_press_enter=02040_I_Tecle <return> para continuar
+% When the \var{-vi} switch is used, the compiler stops compilation
+% and waits for the \var{Enter} key to be pressed when it encounters
+% a \var{\{\$STOP\}} directive.
+scan_w_unsupported_switch=02041_W_Chave nÆo suportada "$1"
+% When warnings are turned on (\var{-vw}), the compiler warns you about
+% unsupported switches. This means that the switch is used in Delphi or
+% Turbo Pascal, but not in \fpc.
+scan_w_illegal_directive=02042_W_Diretiva compilador ilegal "$1"
+% When warnings are turned on (\var{-vw}), the compiler warns you about
+% unrecognised switches. For a list of recognised switches, see the \progref.
+scan_t_back_in=02043_TL_De volta $1
+% When you use the \var{-vt} switch, the compiler tells you when it has finished
+% reading an include file.
+scan_w_unsupported_app_type=02044_W_Tipo aplica‡Æo nÆo suportada: "$1"
+% You get this warning if you specify an unknown application type
+% with the directive \var{\{\$APPTYPE\}}.
+scan_w_app_type_not_support=02045_W_APPTYPE nÆo ‚ suportado pelo SO alvo
+% The \var{\{\$APPTYPE\}} directive is supported by certain operating systems only.
+scan_w_description_not_support=02046_W_DESCRIPTION nÆo ‚ suportado pelo SO alvo
+% The \var{\{\$DESCRIPTION\}} directive is not supported on this target OS.
+scan_n_version_not_support=02047_N_VERSION nÆo ‚ suportado pelo SO alvo
+% The \var{\{\$VERSION\}} directive is not supported on this target OS.
+scan_n_only_exe_version=02048_N_VERSION apenas para EXEs ou DLLs
+% The \var{\{\$VERSION\}} directive is only used for executable or DLL sources.
+scan_w_wrong_version_ignored=02049_W_Formato incorreto para a diretiva VERSION "$1"
+% The \var{\{\$VERSION\}} directive format is majorversion.minorversion
+% where majorversion and minorversion are words.
+scan_e_illegal_asmmode_specifier=02050_E_Estilo especificado assembler ilegal "$1"
+% When you specify an assembler mode with the \var{\{\$ASMMODE xxx\}} directive,
+% the compiler didn't recognize the mode you specified.
+scan_w_no_asm_reader_switch_inside_asm=02051_W_ASM reader switch is not possible inside asm statement, "$1" will be effective only for next
+% It is not possible to switch from one assembler reader to another
+% inside an assembler block. The new reader will be used for next
+% assembler statements only.
+scan_e_wrong_switch_toggle=02052_E_Chave alternƒncia incorreta, usar ON/OFF ou +/-
+% You need to use ON or OFF or a + or - to toggle the switch.
+scan_e_resourcefiles_not_supported=02053_E_Arquivo recursos nÆo suportado para este alvo
+% The target you are compiling for doesn't support resource files.
+scan_w_include_env_not_found=02054_W_Vari vel inclusÆo ambiente "$1" nÆo encontrado no ambiente
+% The included environment variable can't be found in the environment; it will
+% be replaced by an empty string instead.
+scan_e_invalid_maxfpureg_value=02055_E_Valor ilegal para o registrador limite UPF
+% Valid values for this directive are 0..8 and NORMAL/DEFAULT.
+scan_w_only_one_resourcefile_supported=02056_W_Apenas um arquivo de recursos ‚ suportado para este alvo
+% The target you are compiling for supports only one resource file.
+% The first resource file found is used, the others are discarded.
+scan_w_macro_support_turned_off=02057_W_Suporte Macro foi desativado
+% A macro declaration has been found, but macro support is currently off,
+% so the declaration will be ignored. To turn macro support on compile with
+% -Sm on the command line or add \{\$MACRO ON\} in the source.
+scan_e_invalid_interface_type=02058_E_Tipo ilegal de interface especificado. SÆo v lidos COM, CORBA ou DEFAULT.
+% The interface type that was specified is not supported.
+scan_w_appid_not_support=02059_W_APPID ‚ suportado apenas para PalmOS
+% The \var{\{\$APPID\}} directive is only supported for the PalmOS target.
+scan_w_appname_not_support=02060_W_APPNAME ‚ suportado apenas para PalmOS
+% The \var{\{\$APPNAME\}} directive is only supported for the PalmOS target.
+scan_e_string_exceeds_255_chars=02061_E_Constante 'String' nÆo pode ser maior que 255 caracteres
+% A single string constant can contain at most 255 chars. Try splitting up the
+% string into multiple smaller parts and concatenate them with a + operator.
+scan_f_include_deep_ten=02062_F_Incluindo arquivos inclusÆo excede um n¡vel de 16.
+% When including include files the files have been nested to a level of 16.
+% The compiler will expand no further, since this may be a sign that
+% recursion is used.
+scan_e_too_many_push=02063_F_Muitos n¡veis de PUSH. Max. 20
+% A maximum of 20 levels is allowed. This error occurs only in mode MacPas.
+scan_e_too_many_pop=02064_E_Um POP sem um PUSH anterior
+% This error occurs only in mode MacPas.
+scan_e_error_macro_lacks_value=02065_E_Macro ou vari vel tempo compila‡Æo "$1" sem nenhum valor
+% Thus the conditional compile time expression cannot be evaluated.
+scan_e_wrong_switch_toggle_default=02066_E_Chave alternƒncia incorreta, usar ON/OFF/DEFAULT ou +/-/*
+% You need to use ON or OFF or DEFAULT or a + or - or * to toggle the switch.
+scan_e_mode_switch_not_allowed=02067_E_Chave modo "$1" nÆo permitida aqui
+% A mode switch has already been encountered, or, in the case of option -Mmacpas,
+% a mode switch occurs after UNIT.
+scan_e_error_macro_undefined=02068_E_Vari vel tempo compila‡Æo ou macro "$1" nÆo definida.
+% Thus the conditional compile time expression cannot be evaluated. Only in mode MacPas.
+scan_e_utf8_bigger_than_65535=02069_E_C¢digo UTF-8 maior que 65535 encontrado
+% \fpc handles UTF-8 strings internally as widestrings, i.e. the char codes are limited to 65535.
+scan_e_utf8_malformed=02070_E_'String' UTF-8 mal-formada
+% The given string isn't a valid UTF-8 string.
+scan_c_switching_to_utf8=02071_C_Assinatura UTF-8 encontrada, usando codifica‡Æo UTF-8
+% The compiler found a UTF-8 encoding signature (\$ef, \$bb, \$bf) at the beginning of a file,
+% so it interprets it as a UTF-8 file.
+scan_e_compile_time_typeerror=02072_E_ExpressÆo tempo compila‡Æo: Procurado $1 mas obtido $2 na $3
+% The type-check of a compile time expression failed.
+scan_n_app_type_not_support=02073_N_APPTYPE nÆo ‚ suportado pelo SO alvo
+% The \var{\{\$APPTYPE\}} directive is supported by certain operating systems only.
+scan_e_illegal_optimization_specifier=02074_E_Otimiza‡Æo especificada ilegal "$1"
+% You specified an optimization with the \var{\{\$OPTIMIZATION xxx\}} directive,
+% and the compiler didn't recognize the optimization you specified.
+scan_w_setpeflags_not_support=02075_W_SETPEFLAGS nÆo ‚ suportado pelo SO alvo
+% The \var{\{\$SETPEFLAGS\}} directive is not supported by the target OS.
+scan_w_imagebase_not_support=02076_W_IMAGEBASE nÆo ‚ suportado pelo SO alvo
+% The \var{\{\$IMAGEBASE\}} directive is not supported by the target OS.
+scan_w_minstacksize_not_support=02077_W_MINSTACKSIZE nÆo ‚ suportado pelo SO alvo
+% The \var{\{\$MINSTACKSIZE\}} directive is not supported by the target OS.
+scan_w_maxstacksize_not_support=02078_W_MAXSTACKSIZE nÆo ‚ suportado pelo SO alvo
+% The \var{\{\$MAXSTACKSIZE\}} directive is not supported by the target OS.
+scanner_e_illegal_warn_state=02079_E_Estado "$1" ilegal para a diretiva $WARN
+% Only ON and OFF can be used as state with a \var{\{\$WARN\}} compiler directive.
+scan_e_only_packset=02080_E_Valor ilegal para conjunto empacotamento
+% Only 0, 1, 2, 4, 8, DEFAULT and NORMAL are allowed as packset parameters.
+scan_w_pic_ignored=02081_W_Diretiva PIC ou chave ignorada
+% Several targets, such as \windows, do not support nor need PIC,
+% so the PIC directive and switch are ignored.
+scan_w_unsupported_switch_by_target=02082_W_A chave "$1" nÆo ‚ suportada pelo alvo selecionado atualmente
+% Some compiler switches like \$E are not supported by all targets.
+scan_w_frameworks_darwin_only=02084_W_Op‡äes relacionadas a "Framework" sÆo apenas suportadas para Darwin/Mac OS X
+% Frameworks are not a known concept, or at least not supported by FPC,
+% on operating systems other than Darwin/Mac OS X.
+scan_e_illegal_minfpconstprec=02085_E_Constante precisÆo m¡nima ponto flutuante ilegal "$1"
+% Valid minimal precisions for floating point constants are default, 32 and 64,
+% which mean respectively minimal (usually 32 bit), 32 bit and 64 bit precision.
+scan_w_multiple_main_name_overrides=02086_W_Sobrescrevendo nome do procedimento "main" m£ltiplas vezes, foi previamente ajustado para "$1"
+% The name for the main entry procedure is specified more than once. Only the last
+% name will be used.
+scanner_w_illegal_warn_identifier=02087_W_Identificador "$1" ilegal para a diretiva $WARN
+% Identifier is not known by a \var{\{\$WARN\}} compiler directive.
+scanner_e_illegal_alignment_directive=02088_E_Diretiva de alinhamento ilegal
+% The alignment directive is not valid. Either the alignment type is not known or the alignment
+% value is not a power of two.
+% \end{description}
+#
+# Parser
+#
+# 03314 is the last used one
+#
+% \section{Parser messages}
+% This section lists all parser messages. The parser takes care of the
+% semantics of you language, i.e. it determines if your Pascal constructs
+% are correct.
+% \begin{description}
+parser_e_syntax_error=03000_E_Analizador - Erro sintaxe
+% An error against the Turbo Pascal language was encountered. This typically
+% happens when an illegal character is found in the source file.
+parser_e_dont_nest_interrupt=03004_E_Procedimento INTERRUPT nÆo pode ser aninhado
+% An \var{INTERRUPT} procedure must be global.
+parser_w_proc_directive_ignored=03005_W_Tipo procedimento "$1" ignorado
+% The specified procedure directive is ignored by FPC programs.
+parser_e_no_overload_for_all_procs=03006_E_Nem todas as declara‡äes de "$1" estÆo declaradas com OVERLOAD
+% When you want to use overloading using the \var{OVERLOAD} directive, then
+% all declarations need to have \var{OVERLOAD} specified.
+parser_e_export_name_double=03008_E_Nome fun‡Æo exportada duplicada "$1"
+% Exported function names inside a specific DLL must all be different.
+parser_e_export_ordinal_double=03009_E_Öndice fun‡Æo exportada duplicada $1
+% Exported function indexes inside a specific DLL must all be different.
+parser_e_export_invalid_index=03010_E_¡ndice inv lido para fun‡Æo exportada
+% DLL function index must be in the range \var{1..\$FFFF}.
+parser_w_parser_reloc_no_debug=03011_W_Informa‡Æo depura‡Æo DLL reloc vel ou execut vel $1 nÆo funciona, desabilitado.
+% It is currently not possible to include debug information in a relocatable DLL.
+parser_w_parser_win32_debug_needs_WN=03012_W_Para permitir depura‡Æo para c¢digo win32 vocˆ necessita desabilitar reloca‡Æo com op‡Æo -WN
+% Stabs debug info is wrong for relocatable DLL or EXES. Use -WN
+% if you want to debug win32 executables.
+parser_e_constructorname_must_be_init=03013_E_Nome Construtor deve ser INIT
+% You are declaring an object constructor with a name which is not \var{init}, and the
+% \var{-Ss} switch is in effect. See the switch \seeo{Ss}.
+parser_e_destructorname_must_be_done=03014_E_Nome Destruidor deve ser DONE
+% You are declaring an object destructor with a name which is not \var{done}, and the
+% \var{-Ss} switch is in effect. See the switch \seeo{Ss}.
+parser_e_proc_inline_not_supported=03016_E_Tipo procedimento INLINE nÆo suportado
+% You tried to compile a program with C++ style inlining, and forgot to
+% specify the \var{-Si} option (\seeo{Si}). The compiler doesn't support C++
+% styled inlining by default.
+parser_w_constructor_should_be_public=03018_W_Construtor deve ser p£blico
+% Constructors must be in the 'public' part of an object (class) declaration.
+parser_w_destructor_should_be_public=03019_W_Destruidor deve ser p£blico
+% Destructors must be in the 'public' part of an object (class) declaration.
+parser_n_only_one_destructor=03020_N_Classe deve ter apenas um destruidor
+% You can declare only one destructor for a class.
+parser_e_no_local_objects=03021_E_Defini‡äes classe local nÆo permitidas
+% Classes must be defined globally. They cannot be defined inside a
+% procedure or function.
+parser_f_no_anonym_objects=03022_F_Defini‡äes classe an“nima nÆo permitidas
+% An invalid object (class) declaration was encountered, i.e. an
+% object or class without methods that isn't derived from another object or
+% class. For example:
+% \begin{verbatim}
+% Type o = object
+% a : longint;
+% end;
+% \end{verbatim}
+% will trigger this error.
+parser_n_object_has_no_vmt=03023_N_O objeto "$1" nÆo tem VMT
+% This is a note indicating that the declared object has no
+% virtual method table.
+parser_e_illegal_parameter_list=03024_E_Lista parƒmetros ilegal
+% You are calling a function with parameters that are of a different type than
+% the declared parameters of the function.
+parser_e_wrong_parameter_size=03026_E_N£mero incorreto de parƒmetros especificado para chamada de "$1"
+% There is an error in the parameter list of the function or procedure --
+% the number of parameters is not correct.
+parser_e_overloaded_no_procedure=03027_E_Identificador sobrecarregado "$1" nÆo ‚ uma fun‡Æo
+% The compiler encountered a symbol with the same name as an overloaded
+% function, but it is not a function it can overload.
+parser_e_overloaded_have_same_parameters=03028_E_Fun‡äes sobrecarregadas tˆm a mesma lista de parƒmetros
+% You're declaring overloaded functions, but with the same parameter list.
+% Overloaded function must have at least 1 different parameter in their
+% declaration.
+parser_e_header_dont_match_forward=03029_E_Cabe‡alho da fun‡Æo nÆo coincide com a declara‡Æo anterior de "$1"
+% You declared a function with the same parameters but
+% different result type or function modifiers.
+parser_e_header_different_var_names=03030_E_Cabe‡alho fun‡Æo "$1" nÆo coincide com posterior : nome var modifica $2 => $3
+% You declared the function in the \var{interface} part, or with the
+% \var{forward} directive, but defined it with a different parameter list.
+parser_n_duplicate_enum=03031_N_Valores tipo enumera‡Æo tˆm que ser ascendentes
+% \fpc allows enumeration constructions as in C. Examine the following
+% two declarations:
+% \begin{verbatim}
+% type a = (A_A,A_B,A_E:=6,A_UAS:=200);
+% type a = (A_A,A_B,A_E:=6,A_UAS:=4);
+% \end{verbatim}
+% The second declaration would produce an error. \var{A\_UAS} needs to have a
+% value higher than \var{A\_E}, i.e. at least 7.
+parser_e_no_with_for_variable_in_other_segments=03033_E_With nÆo pode ser usado para vari veis em segmentos diferentes
+% With stores a variable locally on the stack,
+% but this is not possible if the variable belongs to another segment.
+parser_e_too_much_lexlevel=03034_E_Aninhamento fun‡Æo > 31
+% You can nest function definitions only 31 levels deep.
+parser_e_range_check_error=03035_E_Erro verifica‡Æo de faixa enquanto avaliando constantes
+% The constants are out of their allowed range.
+parser_w_range_check_error=03036_W_Erro verifica‡Æo de faixa enquanto avaliando constantes
+% The constants are out of their allowed range.
+parser_e_double_caselabel=03037_E_R¢tulo duplicado declara‡Æo "case"
+% You are specifying the same label 2 times in a \var{case} statement.
+parser_e_case_lower_less_than_upper_bound=03038_E_Limite superior da faixa declara‡Æo "case" ‚ menor que o limite inferior
+% The upper bound of a \var{case} label is less than the lower bound and this
+% is useless.
+parser_e_type_const_not_possible=03039_E_Constantes tipadas de classes ou interfaces nÆo sÆo permitidas
+% You cannot declare a constant of type class or object.
+parser_e_no_overloaded_procvars=03040_E_Vari veis fun‡Æo de fun‡äes sobrecarregadas nÆo sÆo permitidas
+% You are trying to assign an overloaded function to a procedural variable.
+% This is not allowed.
+parser_e_invalid_string_size=03041_E_Comprimento 'String' deve ter valor entre 1 … 255
+% The length of a shortstring in Pascal is limited to 255 characters. You are
+% trying to declare a string with length less than 1 or greater than 255.
+parser_w_use_extended_syntax_for_objects=03042_W_Use sintaxe extendida de NEW e DISPOSE para instanciar objetos
+% If you have a pointer \var{a} to an object type, then the statement
+% \var{new(a)} will not initialize the object (i.e. the constructor isn't
+% called), although space will be allocated. You should issue the
+% \var{new(a,init)} statement. This will allocate space, and call the
+% constructor of the object.
+parser_w_no_new_dispose_on_void_pointers=03043_W_Uso de NEW ou DISPOSE para ponteiros nÆo tipados nÆo tem sentido
+parser_e_no_new_dispose_on_void_pointers=03044_E_Uso de NEW ou DISPOSE nÆo ‚ poss¡vel para ponteiros nÆo tipados
+% You cannot use \var{new(p)} or \var{dispose(p)} if \var{p} is an untyped pointer
+% because no size is associated to an untyped pointer.
+% It is accepted for compatibility in \var{TP} and \var{DELPHI} modes, but the
+% compiler will still warn you if it finds such a construct.
+parser_e_class_id_expected=03045_E_Identificador de classe esperado
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., an object or class method, but the type in front of the dot is not
+% a known type.
+parser_e_no_type_not_allowed_here=03046_E_Identificador tipo nÆo permitido aqui
+% You cannot use a type inside an expression.
+parser_e_methode_id_expected=03047_E_Identificador de m‚todo esperado
+% This identifier is not a method.
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., an object or class method, but the procedure name is not a
+% procedure of this type.
+parser_e_header_dont_match_any_member=03048_E_Cabe‡alho fun‡Æo nÆo coincide com qualquer m‚todo desta classe "$1"
+% This identifier is not a method.
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., an object or class method, but the procedure name is not a
+% procedure of this type.
+parser_d_procedure_start=03049_DL_Procedimento/fun‡Æo $1
+% When using the \var{-vd} switch, the compiler tells you when it starts
+% processing a procedure or function implementation.
+parser_e_error_in_real=03050_E_Constante ponto flutuante ilegal
+% The compiler expects a floating point expression, and gets something else.
+parser_e_fail_only_in_constructor=03051_E_FAIL s¢ pode ser usado em contrutores
+% You are using the \var{fail} keyword outside a constructor method.
+parser_e_no_paras_for_destructor=03052_E_Destruidores nÆo podem ter parƒmetros
+% You are declaring a destructor with a parameter list. Destructor methods
+% cannot have parameters.
+parser_e_only_class_members_via_class_ref=03053_E_Apenas m‚todos, propriedades e vari veis de classe podem ser referenciadas por referˆncias classe
+% This error occurs in a situation like the following:
+% \begin{verbatim}
+% Type :
+% Tclass = Class of Tobject;
+%
+% Var C : TClass;
+%
+% begin
+% ...
+% C.free
+% \end{verbatim}
+% \var{Free} is not a class method and hence cannot be called with a class
+% reference.
+parser_e_only_class_members=03054_E_Apenas m‚todos, propriedades e vari veis de classe podem ser acessadas em m‚todos de classe
+% This is related to the previous error. You cannot call a method of an object
+% from inside a class method. The following code would produce this error:
+% \begin{verbatim}
+% class procedure tobject.x;
+%
+% begin
+% free
+% \end{verbatim}
+% Because free is a normal method of a class it cannot be called from a class
+% method.
+parser_e_case_mismatch=03055_E_Constante e tipo CASE incompat¡veis
+% One of the labels is not of the same type as the case variable.
+parser_e_illegal_symbol_exported=03056_E_S¡mbolos s¢ podem ser exportados em uma biblioteca
+% You can only export procedures and functions when you write a library. You
+% cannot export variables or constants.
+parser_w_should_use_override=03057_W_Um m‚todo herdado ‚ ocultado por "$1"
+% A method that is declared \var{virtual} in a parent class, should be
+% overridden in the descendant class with the \var{override} directive. If you
+% don't specify the \var{override} directive, you will hide the parent method;
+% you will not override it.
+parser_e_nothing_to_be_overridden=03058_E_NÆo h  m‚todo na classe ancestral para ser sobreposto: "$1"
+% You are trying to \var{override} a virtual method of a parent class that does
+% not exist.
+parser_e_no_procedure_to_access_property=03059_E_Nenhum membro foi provido para acessar a propriedade
+% You specified no \var{read} directive for a property.
+parser_w_stored_not_implemented=03060_W_Diretiva propriedade armazenamento ainda nÆo foi implementada
+% This message is no longer used, as the \var{stored} directive has been implemented.
+parser_e_ill_property_access_sym=03061_E_S¡mbolo ilegal para acesso propriedade
+% There is an error in the \var{read} or \var{write} directives for an array
+% property. When you declare an array property, you can only access it with
+% procedures and functions. The following code would cause such an error.
+% \begin{verbatim}
+% tmyobject = class
+% i : integer;
+% property x [i : integer]: integer read I write i;
+% \end{verbatim}
+%
+parser_e_cant_access_protected_member=03062_E_NÆo ‚ poss¡vel acessar um campo protegido de um objeto aqui
+% Fields that are declared in a \var{protected} section of an object or class
+% declaration cannot be accessed outside the module where the object is
+% defined, or outside descendent object methods.
+parser_e_cant_access_private_member=03063_E_NÆo ‚ poss¡vel acessar um campo privado de um objeto aqui
+% Fields that are declared in a \var{private} section of an object or class
+% declaration cannot be accessed outside the module where the class is
+% defined.
+parser_e_overridden_methods_not_same_ret=03066_E_M‚todos sobrepostos devem ter o mesmo tipo de retorno: "$2" ‚ sobreposto por "$1" que possui outro tipo retorno
+% If you declare overridden methods in a class definition, they must
+% have the same return type.
+parser_e_dont_nest_export=03067_E_Fun‡äes EXPORT declaradas nÆo podem estar aninhadas
+% You cannot declare a function or procedure within a function or procedure
+% that was declared as an export procedure.
+parser_e_methods_dont_be_export=03068_E_M‚todos nÆo podem ser EXPORTados
+% You cannot declare a procedure that is a method for an object as
+% \var{export}ed.
+parser_e_call_by_ref_without_typeconv=03069_E_Chamada por var. para arg. no. $1 tem que coincidir exatamente: Obtido "$2" esperado "$3"
+% When calling a function declared with \var{var} parameters, the variables in
+% the function call must be of exactly the same type. There is no automatic
+% type conversion.
+parser_e_no_super_class=03070_E_Classe nÆo ‚ uma classe pai da classe atual
+% When calling inherited methods, you are trying to call a method of a non-related
+% class. You can only call an inherited method of a parent class.
+parser_e_self_not_in_method=03071_E_SELF ‚ permitido apenas em m‚todos
+% You are trying to use the \var{self} parameter outside an object's method.
+% Only methods get passed the \var{self} parameters.
+parser_e_generic_methods_only_in_methods=03072_E_M‚todos s¢ podem estar em outros m‚todos se chamados diretamente com o identificador de tipo da classe
+% A construction like \var{sometype.somemethod} is only allowed in a method.
+parser_e_illegal_colon_qualifier=03073_E_Uso ilegal de ':'
+% You are using the format \var{:} (colon) 2 times on an expression that
+% is not a real expression.
+parser_e_illegal_set_expr=03074_E_Erro verifica‡Æo de faixa em conjunto construtor ou elemento conjunto duplicado
+% The declaration of a set contains an error. Either one of the elements is
+% outside the range of the set type, or two of the elements are in fact
+% the same.
+parser_e_pointer_to_class_expected=03075_E_Ponteiro para objeto esperado
+% You specified an illegal type in a \var{new} statement.
+% The extended syntax of \var{new} needs an object as a parameter.
+parser_e_expr_have_to_be_constructor_call=03076_E_ExpressÆo deve ser chamada ao construtor
+% When using the extended syntax of \var{new}, you must specify the constructor
+% method of the object you are trying to create. The procedure you specified
+% is not a constructor.
+parser_e_expr_have_to_be_destructor_call=03077_E_ExpressÆo deve ser chamada ao destruidor
+% When using the extended syntax of \var{dispose}, you must specify the
+% destructor method of the object you are trying to dispose of.
+% The procedure you specified is not a destructor.
+parser_e_invalid_record_const=03078_E_Ordem ilegal dos elementos do registro
+% When declaring a constant record, you specified the fields in the wrong
+% order.
+parser_e_false_with_expr=03079_E_Tipo expressÆo deve ser classe ou tipo registro
+% A \var{with} statement needs an argument that is of the type \var{record}
+% or \var{class}. You are using \var{with} on an expression that is not of
+% this type.
+parser_e_void_function=03080_E_Procedimentos nÆo podem retornar um valor
+% In \fpc, you can specify a return value for a function when using
+% the \var{exit} statement. This error occurs when you try to do this with a
+% procedure. Procedures cannot return a value.
+parser_e_constructors_always_objects=03081_E_Construtores, destruidores e operadores de classe devem ser m‚todos
+% You're declaring a procedure as destructor, constructor or class operator, when the
+% procedure isn't a class method.
+parser_e_operator_not_overloaded=03082_E_Operador nÆo ‚ sobrecarregado
+% You're trying to use an overloaded operator when it is not overloaded for
+% this type.
+parser_e_no_such_assignment=03083_E_Imposs¡vel sobrecarregar atribui‡äes para tipos iguais
+% You cannot overload assignment for types
+% that the compiler considers as equal.
+parser_e_overload_impossible=03084_E_Operador sobrecarga imposs¡vel
+% The combination of operator, arguments and return type are
+% incompatible.
+parser_e_no_reraise_possible=03085_E_Re-elevar nÆo ‚ poss¡vel l 
+% You are trying to re-raise an exception where it is not allowed. You can only
+% re-raise exceptions in an \var{except} block.
+parser_e_no_new_or_dispose_for_classes=03086_E_A sintaxe estendida para new ou dispose nÆo ‚ permitida para uma classe
+% You cannot generate an instance of a class with the extended syntax of
+% \var{new}. The constructor must be used for that. For the same reason, you
+% cannot call \var{dispose} to de-allocate an instance of a class, the
+% destructor must be used for that.
+parser_e_procedure_overloading_is_off=03088_E_Sobrecarga de procimento est  desativada
+% When using the \var{-So} switch, procedure overloading is switched off.
+% Turbo Pascal does not support function overloading.
+parser_e_overload_operator_failed=03089_E_NÆo ‚ poss¡vel sobrecarregar este operador. Operadores relacionados poss¡veis de sobrecarga (se algum) sÆo: $1
+% You are trying to overload an operator which cannot be overloaded.
+% The following operators can be overloaded :
+% \begin{verbatim}
+% +, -, *, /, =, >, <, <=, >=, is, as, in, **, :=
+% \end{verbatim}
+parser_e_comparative_operator_return_boolean=03090_E_Operador de compara‡Æo deve retornar um valor booleano
+% When overloading the \var{=} operator, the function must return a boolean
+% value.
+parser_e_only_virtual_methods_abstract=03091_E_Apenas m‚todos virtuais podem ser abstratos
+% You are declaring a method as abstract, when it is not declared to be
+% virtual.
+parser_f_unsupported_feature=03092_F_Uso de caracter¡stica nÆo suportada!
+% You're trying to force the compiler into doing something it cannot do yet.
+parser_e_mix_of_classes_and_objects=03093_E_A mistura de diferentes esp‚cies de objetos (class, object, interface, etc) nÆo ‚ permitida
+% You cannot derive \var{objects}, \var{classes}, \var{cppclasses} and \var{interfaces} intertwined. E.g.
+% a class cannot have an object as parent and vice versa.
+parser_w_unknown_proc_directive_ignored=03094_W_Diretiva desconhecida de procedimento teve que ser ignorada: "$1"
+% The procedure directive you specified is unknown.
+parser_e_absolute_only_one_var=03095_E_Absolute s¢ pode estar associada a uma vari vel
+% You cannot specify more than one variable before the \var{absolute} directive.
+% Thus, the following construct will provide this error:
+% \begin{verbatim}
+% Var Z : Longint;
+% X,Y : Longint absolute Z;
+% \end{verbatim}
+parser_e_absolute_only_to_var_or_const=03096_E_Absolute s¢ pode estar associada com uma vari vel ou constante
+% The address of an \var{absolute} directive can only point to a variable or
+% constant. Therefore, the following code will produce this error:
+% \begin{verbatim}
+% Procedure X;
+%
+% var p : longint absolute x;
+% \end{verbatim}
+parser_e_initialized_only_one_var=03097_E_Apenas uma vari vel pode ser inicializada
+% You cannot specify more than one variable with a initial value in Delphi mode.
+parser_e_abstract_no_definition=03098_E_M‚todos abstratos nÆo devem ter qualquer defini‡Æo (com corpo fun‡Æo)
+% Abstract methods can only be declared, you cannot implement them. They
+% should be overridden by a descendant class.
+parser_e_overloaded_must_be_all_global=03099_E_Esta fun‡Æo sobrecarregada nÆo pode ser local (deve ser exportada)
+% You are defining an overloaded function in the implementation part of a unit,
+% but there is no corresponding declaration in the interface part of the unit.
+parser_w_virtual_without_constructor=03100_W_M‚todos virtuais sÆo usados sem um construtor em "$1"
+% If you declare objects or classes that contain virtual methods, you need
+% to have a constructor and destructor to initialize them. The compiler
+% encountered an object or class with virtual methods that doesn't have
+% a constructor/destructor pair.
+parser_c_macro_defined=03101_CL_Macro definida: $1
+% When \var{-vc} is used, the compiler tells you when it defines macros.
+parser_c_macro_undefined=03102_CL_Macro indefinida: $1
+% When \var{-vc} is used, the compiler tells you when it undefines macros.
+parser_c_macro_set_to=03103_CL_Macro $1 ajustada para $2
+% When \var{-vc} is used, the compiler tells you what values macros get.
+parser_i_compiling=03104_I_Compilando $1
+% When you turn on information messages (\var{-vi}), the compiler tells you
+% what units it is recompiling.
+parser_u_parsing_interface=03105_UL_Analisando interface da unidade $1
+% This tells you that the reading of the interface
+% of the current unit has started
+parser_u_parsing_implementation=03106_UL_Analisando implementa‡Æo de $1
+% This tells you that the code reading of the implementation
+% of the current unit, library or program starts
+parser_d_compiling_second_time=03107_DL_Compilando $1 uma segunda vez
+% When you request debug messages (\var{-vd}) the compiler tells you what
+% units it recompiles for the second time.
+parser_e_no_property_found_to_override=03109_E_Nenhuma propriedade encontrada para sobrepor
+% You want to override a property of a parent class, when there is, in fact,
+% no such property in the parent class.
+parser_e_only_one_default_property=03110_E_Apenas uma propriedade padrÆo ‚ permitida
+% You specified a property as \var{Default}, but the class already has a
+% default property, and a class can have only one default property.
+parser_e_property_need_paras=03111_E_A propriedade padrÆo deve ser uma propriedade matriz
+% Only array properties of classes can be made \var{default} properties.
+parser_e_constructor_cannot_be_not_virtual=03112_E_Construtores virtuais sÆo suportados apenas modelo objeto classe
+% You cannot have virtual constructors in objects. You can only have them
+% in classes.
+parser_e_no_default_property_available=03113_E_Nenhuma propriedade padrÆo dispon¡vel
+% You are trying to access a default property of a class, but this class (or one of
+% its ancestors) doesn't have a default property.
+parser_e_cant_have_published=03114_E_A classe nÆo pode ter uma se‡Æo PUBLISHED, use a chave {$M+}
+% If you want a \var{published} section in a class definition, you must
+% use the \var{\{\$M+\}} switch, which turns on generation of type
+% information.
+parser_e_forward_declaration_must_be_resolved=03115_E_Declara‡Æo posterior da classe "$1" deve ser resolvida aqui para usar a classe como ancestral
+% To be able to use an object as an ancestor object, it must be defined
+% first. This error occurs in the following situation:
+% \begin{verbatim}
+% Type ParentClas = Class;
+% ChildClass = Class(ParentClass)
+% ...
+% end;
+% \end{verbatim}
+% where \var{ParentClass} is declared but not defined.
+parser_e_no_local_operator=03116_E_Operadores locais nÆo suportados
+% You cannot overload locally, i.e. inside procedures or function
+% definitions.
+parser_e_proc_dir_not_allowed_in_interface=03117_E_Diretiva procedimento "$1" nÆo permitida na se‡Æo interface
+% This procedure directive is not allowed in the \var{interface} section of
+% a unit. You can only use it in the \var{implementation} section.
+parser_e_proc_dir_not_allowed_in_implementation=03118_E_Diretiva procedimento "$1" nÆo permitida na se‡Æo implementa‡Æo
+% This procedure directive is not allowed in the \var{implementation} section of
+% a unit. You can only use it in the \var{interface} section.
+parser_e_proc_dir_not_allowed_in_procvar=03119_E_Diretiva procedimento "$1" nÆo permitida na declara‡Æo procvar
+% This procedure directive cannot be part of a procedural or function
+% type declaration.
+parser_e_function_already_declared_public_forward=03120_E_Fun‡Æo j  declarada como P£blica/Posterior "$1"
+% You will get this error if a function is defined as \var{forward} twice.
+% Or if it occurs in the \var{interface} section, and again as a \var{forward}
+% declaration in the \var{implementation} section.
+parser_e_not_external_and_export=03121_E_Imposs¡vel usar ambos EXPORT e EXTERNAL
+% These two procedure directives are mutually exclusive.
+parser_w_not_supported_for_inline=03123_W_"$1" nÆo suportado ainda dentro procedimento/fun‡Æo em linha
+% Inline procedures don't support this declaration.
+parser_w_inlining_disabled=03124_W_Procedimentos em linha desabilitados
+% Inlining of procedures is disabled.
+parser_i_writing_browser_log=03125_I_Gravando hist¢rio Navegador $1
+% When information messages are on, the compiler warns you when it
+% writes the browser log (generated with the \var{\{\$Y+ \}} switch).
+parser_h_maybe_deref_caret_missing=03126_H_Talvez desreferˆncia de ponteiro esteja faltando
+% The compiler thinks that a pointer may need a dereference.
+parser_f_assembler_reader_not_supported=03127_F_Leitor assembler selecionado nÆo suportado
+% The selected assembler reader (with \var{\{\$ASMMODE xxx\}} is not
+% supported. The compiler can be compiled with or without support for a
+% particular assembler reader.
+parser_e_proc_dir_conflict=03128_E_Diretiva procedimento "$1" tem conflitos com outras diretivas
+% You specified a procedure directive that conflicts with other directives.
+% For instance \var{cdecl} and \var{pascal} are mutually exclusive.
+parser_e_call_convention_dont_match_forward=03129_E_Conven‡Æo de chamada nÆo coincide com declara‡Æo posterior
+% This error happens when you declare a function or procedure with
+% e.g. \var{cdecl;} but omit this directive in the implementation, or vice
+% versa. The calling convention is part of the function declaration, and
+% must be repeated in the function definition.
+parser_e_property_cant_have_a_default_value=03131_E_Propriedade nÆo pode ter um valor padrÆo
+% Set properties or indexed properties cannot have a default value.
+parser_e_property_default_value_must_const=03132_E_O valor padrÆo de um propriedade deve ser uma constante
+% The value of a \var{default} declared property must be known at compile
+% time. The value you specified is only known at run time. This happens
+% e.g. if you specify a variable name as a default value.
+parser_e_cant_publish_that=03133_E_S¡mbolo nÆo pode ser PUBLISHED, pode ser apenas uma classe
+% Only class type variables can be in a \var{published} section of a class
+% if they are not declared as a property.
+parser_e_cant_publish_that_property=03134_E_Este tipo de propriedade nÆo pode ser PUBLISHED
+% Properties in a \var{published} section cannot be array properties.
+% They must be moved to public sections. Properties in a \var{published}
+% section must be an ordinal type, a real type, strings or sets.
+parser_e_empty_import_name=03136_E_Um nome importa‡Æo ‚ requerido
+% Some targets need a name for the imported procedure or a \var{cdecl} specifier.
+parser_e_division_by_zero=03138_E_DivisÆo por zero
+% A division by zero was encounted.
+parser_e_invalid_float_operation=03139_E_Opera‡Æo ponto flutuante inv lida
+% An operation on two real type values produced an overflow or a division
+% by zero.
+parser_e_array_lower_less_than_upper_bound=03140_E_Limite superior da faixa ‚ menor que o limite inferior
+% The upper bound of an array declaration is less than the lower bound and this
+% is not possible.
+parser_w_string_too_long=03141_W_'String' "$1" ‚ maior que "$2"
+% The size of the constant string is larger than the size you specified in
+% string type definition.
+parser_e_string_larger_array=03142_E_Comprimento 'String' ‚ maior que o comprimento da matriz de caractere
+% The size of the constant string is larger than the size you specified in
+% the \var{Array[x..y] of char} definition.
+parser_e_ill_msg_expr=03143_E_ExpressÆo ilegal ap¢s diretiva mensagem
+% \fpc supports only integer or string values as message constants.
+parser_e_ill_msg_param=03144_E_Manipuladores mensagens podem ter apenas uma chamada por parƒmetro referˆncia
+% A method declared with the \var{message} directive as message handler
+% can take only one parameter which must be declared as call by reference.
+% Parameters are declared as call by reference using the \var{var}-directive.
+parser_e_duplicate_message_label=03145_E_R¢tulo mensagem duplicado: "$1"
+% A label for a message is used twice in one object/class.
+parser_e_self_in_non_message_handler=03146_E_Self pode ser um parƒmetro expl¡cito apenas em m‚todos que sÆo manipuladores de mensagens
+% The \var{Self} parameter can only be passed explicitly to a method which
+% is declared as message handler.
+parser_e_threadvars_only_sg=03147_E_Threadvars podem ser apenas est ticas ou globais
+% Threadvars must be static or global; you can't declare a thread
+% local to a procedure. Local variables are always local to a thread,
+% because every thread has its own stack and local variables
+% are stored on the stack.
+parser_f_direct_assembler_not_allowed=03148_F_Assembler direto nÆo suportado para formato de sa¡da bin rio
+% You can't use direct assembler when using a binary writer. Choose an
+% other output format or use another assembler reader.
+parser_w_no_objpas_use_mode=03149_W_NÆo carregue a unidade OBJPAS manualmente, use \{\$mode objfpc\} ou \{\$mode delphi\}
+% You are trying to load the \file{ObjPas} unit manually from a \var{uses} clause.
+% This is not a good idea. Use the \var{\{\$MODE OBJFPC\}} or
+% \var{\{\$mode delphi\}} directives which load the unit automatically.
+parser_e_no_object_override=03150_E_OVERRIDE nÆo pode ser usado em objetos
+% \var{Override} is not supported for objects, use \var{virtual} instead to override
+% a method of a parent object.
+parser_e_cant_use_inittable_here=03151_E_Tipos de dados que requerem inicializa‡Æo/finaliza‡Æo nÆo podem ser usados em registros variant
+% Some data types (e.g. \var{ansistring}) need initialization/finalization
+% code which is implicitly generated by the compiler. Such data types
+% can't be used in the variant part of a record.
+parser_e_resourcestring_only_sg=03152_E_Recursos 'String' podem ser apenas est ticos ou globais
+% Resourcestring cannot be declared local, only global or using the static
+% directive.
+parser_e_exit_with_argument_not__possible=03153_E_EXIT com argumentos nÆo pode ser usado aqui
+% An exit statement with an argument for the return value can't be used here. This
+% can happen for example in \var{try..except} or \var{try..finally} blocks.
+parser_e_stored_property_must_be_boolean=03154_E_O tipo do s¡mbolo de armazenamento deve ser booleano
+% If you specify a storage symbol in a property declaration, it must be a
+% boolean type.
+parser_e_ill_property_storage_sym=03155_E_Este s¡mbolo nÆo ‚ permitido como s¡mbolo de armazenamento
+% You can't use this type of symbol as storage specifier in property
+% declaration. You can use only methods with the result type boolean,
+% boolean class fields or boolean constants.
+parser_e_only_publishable_classes_can_be_published=03156_E_Apenas classes que sÆo compiladas no modo $M+ podem ser PUBLISHED
+% A class-typed field in the published section of a class can only be a class which was
+% compiled in \var{\{\$M+\}} or which is derived from such a class. Normally
+% such a class should be derived from \var{TPersistent}.
+parser_e_proc_directive_expected=03157_E_Diretiva procedimento esperada
+% This error is triggered when you have a \var{\{\$Calling\}} directive without
+% a calling convention specified.
+% It also happens when declaring a procedure in a const block and you
+% used a ; after a procedure declaration which must be followed by a
+% procedure directive.
+% Correct declarations are:
+% \begin{verbatim}
+% const
+% p : procedure;stdcall=nil;
+% p : procedure stdcall=nil;
+% \end{verbatim}
+parser_e_invalid_property_index_value=03158_E_O valor de um ¡ndice de propriedade deve ser do tipo ordinal
+% The value you use to index a property must be of an ordinal type, for
+% example an integer or enumerated type.
+parser_e_procname_to_short_for_export=03159_E_Nome procedimento muito curto para ser exportado
+% The length of the procedure/function name must be at least 2 characters
+% long. This is because of a bug in dlltool which doesn't parse the .def
+% file correctly with a name of length 1.
+parser_e_dlltool_unit_var_problem=03160_E_Nenhuma entrada DEFFILE pode ser gerada para vars. globais unidade
+parser_e_dlltool_unit_var_problem2=03161_E_Compile sem a op‡Æo -WD
+% You need to compile this file without the -WD switch on the
+% command line.
+parser_f_need_objfpc_or_delphi_mode=03162_F_Vocˆ precisa do modo ObjFpc (-S2) ou Delphi (-Sd) para compilar este m¢dulo
+% You need to use \var{\{\$MODE OBJFPC\}} or \var{\{\$MODE DELPHI\}} to compile this file.
+% Or use the corresponding command line switch, either \var{-Mobjfpc} or \var{-MDelphi.}
+parser_e_no_export_with_index_for_target=03163_E_Imposs¡vel exportar com ¡ndice sob $1
+% Exporting of functions or procedures with a specified index is not
+% supported on this target.
+parser_e_no_export_of_variables_for_target=03164_E_Exporta‡Æo de vari veis nÆo ‚ suportada sob $1
+% Exporting of variables is not supported on this target.
+parser_e_improper_guid_syntax=03165_E_Sintaxe GUID impr¢pria
+% The GUID indication does not have the proper syntax. It should be of the form
+% \begin{verbatim}
+% {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}
+% \end{verbatim}
+% Where each \var{X} represents a hexadecimal digit.
+parser_w_interface_mapping_notfound=03168_W_Procedimento chamado "$1" que fosse adequado … implementa‡Æo de $2.$3 nÆo encontrado
+% The compiler cannot find a suitable procedure which implements the given method of an interface.
+% A procedure with the same name is found, but the arguments do not match.
+parser_e_interface_id_expected=03169_E_Identificador interface esperado
+% This happens when the compiler scans a \var{class} declaration that contains
+% \var{interface} function name mapping code like this:
+% \begin{verbatim}
+% type
+% TMyObject = class(TObject, IDispatch)
+% function IUnknown.QueryInterface=MyQueryInterface;
+% ....
+% \end{verbatim}
+% and the \var{interface} before the dot is not listed in the inheritance list.
+parser_e_type_cant_be_used_in_array_index=03170_E_Tipo "$1" nÆo pode ser usado como tipo ¡ndice matriz
+% Types like \var{qword} or \var{int64} aren't allowed as array index type.
+parser_e_no_con_des_in_interfaces=03171_E_Construtor e destruidor nÆo permitidos em interfaces
+% Constructor and destructor declarations aren't allowed in interfaces.
+% In the most cases method \var{QueryInterface} of \var{IUnknown} can
+% be used to create a new interface.
+parser_e_no_access_specifier_in_interfaces=03172_E_Especificadores de acesso nÆo podem ser usados em INTERFACEs e OBJCPROTOCOLs
+% The access specifiers \var{public}, \var{private}, \var{protected} and
+% \var{published} can't be used in interfaces, Objective-C protocols and categories because all methods
+% of an interface/protocol/category must be public.
+parser_e_no_vars_in_interfaces=03173_E_Uma interface, auxiliar ou protocolo Objective-C ou categoria nÆo pode conter campos
+% Declarations of fields are not allowed in interfaces, helpers and Objective-C protocols and categories.
+% An interface/protocol/category can contain only methods and properties with method read/write specifiers.
+parser_e_no_local_proc_external=03174_E_Imposs¡ve declarar procedimento local como EXTERNAL
+% Declaring local procedures as external is not possible. Local procedures
+% get hidden parameters that will make the chance of errors very high.
+parser_w_skipped_fields_before=03175_W_Alguns campos que vˆm antes de "$1" nÆo foram inicializados
+% In Delphi mode, not all fields of a typed constant record have to be
+% initialized, but the compiler warns you when it detects such situations.
+parser_e_skipped_fields_before=03176_E_Alguns campos que vˆm antes de "$1" nÆo foram inicializados
+% In all syntax modes but Delphi mode, you can't leave some fields uninitialized
+% in the middle of a typed constant record.
+parser_w_skipped_fields_after=03177_W_Alguns campos que vˆm depois de "$1" nÆo foram inicializados
+% You can leave some fields at the end of a type constant record uninitialized
+% (The compiler will initialize them to zero automatically). This may be the cause
+% of subtle problems.
+parser_e_varargs_need_cdecl_and_external=03178_E_Diretiva VarArgs (ou '...' em MacPas) sem CDecl/CPPDecl/MWPascal e External
+% The varargs directive (or the ``...'' varargs parameter in MacPas mode) can only be
+% used with procedures or functions that are declared with \var{external} and one of
+% \var{cdecl}, \var{cppdecl} and \var{mwpascal}. This functionality
+% is only supported to provide a compatible interface to C functions like printf.
+parser_e_self_call_by_value=03179_E_Self deve ser um parƒmetro normal (chamada-por-valor)
+% You can't declare \var{Self} as a const or var parameter, it must always be
+% a call-by-value parameter.
+parser_e_interface_has_no_guid=03180_E_Interface "$1" nÆo tem identifica‡Æo de interface
+% When you want to assign an interface to a constant, then the interface
+% must have a GUID value set.
+parser_e_illegal_field_or_method=03181_E_Campo classe ou identificador m‚todo "$1" desconhecido
+% Properties must refer to a field or method in the same class.
+parser_w_proc_overriding_calling=03182_W_Conven‡Æo chamada sobreposi‡Æo "$1" com "$2"
+% There are two directives in the procedure declaration that specify a calling
+% convention. Only the last directive will be used.
+parser_e_no_procvarobj_const=03183_E_Constantes tipadas do tipo "procedimento de objeto" podem ser apenas inicializadas com NIL
+% You cannot assign the address of a method to a typed constant which has a
+% 'procedure of object' type, because such a constant requires two addresses:
+% that of the method (which is known at compile time) and that of the object or
+% class instance it operates on (which cannot be known at compile time).
+parser_e_default_value_only_one_para=03184_E_Valor padrÆo pode ser atribu¡do apenas … um parƒmetro
+% It is not possible to specify a default value for several parameters at once.
+% The following is invalid:
+% \begin{verbatim}
+% Procedure MyProcedure (A,B : Integer = 0);
+% \end{verbatim}
+% Instead, this should be declared as
+% \begin{verbatim}
+% Procedure MyProcedure (A : Integer = 0; B : Integer = 0);
+% \end{verbatim}
+parser_e_default_value_expected_for_para=03185_E_Parƒmetro padrÆo requerido para "$1"
+% The specified parameter requires a default value.
+parser_w_unsupported_feature=03186_W_Uso de caracter¡stica nÆo suportada!
+% You're trying to force the compiler into doing something it cannot do yet.
+parser_h_c_arrays_are_references=03187_H_Matrizes C sÆo passadas por referˆncia
+% Any array passed to a C function is passed
+% by a pointer (i.e. by reference).
+parser_e_C_array_of_const_must_be_last=03188_E_Matrizes de constantes C devem ser o £ltimo argumento
+% You cannot add any other argument after an \var{array of const} for
+% \var{cdecl} functions, as the size pushed on stack for this argument is
+% not known.
+parser_h_type_redef=03189_H_Redefini‡Æo do tipo "$1"
+% This is an indicator that a previously declared type is
+% being redefined as something else. This may, or may not
+% be, a potential source of errors.
+parser_w_cdecl_has_no_high=03190_W_Fun‡äes declaradas com cdecl nÆo tem um parƒmetro impl¡cito extra
+% Functions declared with the \var{cdecl} modifier do not pass an extra implicit parameter.
+parser_w_cdecl_no_openstring=03191_W_Fun‡äes declaradas com cdecl nÆo suportam 'String' aberta
+% Openstring is not supported for functions that have the \var{cdecl} modifier.
+parser_e_initialized_not_for_threadvar=03192_E_Imposs¡vel inicializar vari veis declaradas como threadvar
+% Variables declared as threadvar cannot be initialized with a default value.
+% The variables will always be filled with zero at the start of a new thread.
+parser_e_msg_only_for_classes=03193_E_Diretiva mensagem ‚ permitida apenas em Classes
+% The message directive is only supported for Class types.
+parser_e_procedure_or_function_expected=03194_E_Procedimento ou Fun‡Æo esperados
+% A class method can only be specified for procedures and functions.
+parser_e_illegal_calling_convention=03195_W_Diretiva conven‡Æo de chamada ignorada: "$1"
+% Some calling conventions are supported only by certain CPUs. I.e. most non-i386 ports support
+% only the standard ABI calling convention of the CPU.
+parser_e_no_object_reintroduce=03196_E_REINTRODUCE nÆo pode ser usado em objetos
+% \var{reintroduce} is not supported for objects, Objective-C classes and Objective-C protocols.
+parser_e_paraloc_only_one_para=03197_E_Cada argumento deve ter sua pr¢pria localiza‡Æo
+% If locations for arguments are specified explicitly as it is required by
+% some syscall conventions, each argument must have its own location. Things
+% like
+% \begin{verbatim}
+% procedure p(i,j : longint 'r1');
+% \end{verbatim}
+% aren't allowed.
+parser_e_paraloc_all_paras=03198_E_Cada argumento deve ter uma localiza‡Æo expl¡cita
+% If one argument has an explicit argument location, all arguments of a procedure
+% must have one.
+parser_e_illegal_explicit_paraloc=03199_E_Localiza‡Æo argumento desconhecida
+% The location specified for an argument isn't recognized by the compiler.
+parser_e_32bitint_or_pointer_variable_expected=03200_E_Inteiro 32-Bit ou vari vel ponteiro esperados
+% The libbase for MorphOS/AmigaOS can be given only as \var{longint}, \var{dword} or any pointer variable.
+parser_e_goto_outside_proc=03201_E_Declara‡Æo Goto nÆo permitida entre procedimentos diferentes
+% It isn't allowed to use \var{goto} statements referencing labels outside the
+% current procedure. The following example shows the problem:
+% \begin{verbatim}
+% ...
+% procedure p1;
+% label
+% l1;
+%
+% procedure p2;
+% begin
+% goto l1; // This goto ISN'T allowed
+% end;
+%
+% begin
+% p2
+% l1:
+% end;
+% ...
+%
+% \end{verbatim}
+parser_f_too_complex_proc=03202_F_Procedimento muito complexo, ele requer muitos registradores
+% Your procedure body is too long for the compiler. You should split the
+% procedure into multiple smaller procedures.
+parser_e_illegal_expression=03203_E_ExpressÆo ilegal
+% This can occur under many circumstances. Usually when trying to evaluate
+% constant expressions.
+parser_e_invalid_integer=03204_E_ExpressÆo inteira inv lida
+% You made an expression which isn't an integer, and the compiler expects the
+% result to be an integer.
+parser_e_invalid_qualifier=03205_E_Qualifiador ilegal
+% One of the following is happening :
+% \begin{itemize}
+% \item You're trying to access a field of a variable that is not a record.
+% \item You're indexing a variable that is not an array.
+% \item You're dereferencing a variable that is not a pointer.
+% \end{itemize}
+parser_e_upper_lower_than_lower=03206_E_Limite de faixa alta < limite de faixa baixa
+% You are declaring a subrange, and the high limit is less than the low limit of
+% the range.
+parser_e_macpas_exit_wrong_param=03207_E_Parƒmetro de sa¡da deve ser o nome do procedimento em que ele ‚ usado
+% Non local exit is not allowed. This error occurs only in mode MacPas.
+parser_e_illegal_assignment_to_count_var=03208_E_Atribui‡Æo ilegal para a vari vel for-loop "$1"
+% The type of a \var{for} loop variable must be an ordinal type.
+% Loop variables cannot be reals or strings. You also cannot assign values to
+% loop variables inside the loop (Except in Delphi and TP modes). Use a while or
+% repeat loop instead if you need to do something like that, since those
+% constructs were built for that.
+parser_e_no_local_var_external=03209_E_Imposs¡vel declarar vari vel local como EXTERNAL
+% Declaring local variables as external is not allowed. Only global variables can reference
+% external variables.
+parser_e_proc_already_external=03210_E_Procedimento j  foi declarado como EXTERNAL
+% The procedure is already declared with the EXTERNAL directive in an interface or
+% forward declaration.
+parser_w_implicit_uses_of_variants_unit=03211_W_Uso impl¡cito da unidade Variants
+% The Variant type is used in the unit without any used unit using the Variants unit. The
+% compiler has implicitly added the Variants unit to the uses list. To remove this warning
+% the Variants unit needs to be added to the uses statement.
+parser_e_no_static_method_in_interfaces=03212_E_Classe e m‚todos est ticos nÆo podem ser usados em INTERFACES
+% The specifier \var{class} and directive \var{static} can't be used in interfaces
+% because all methods of an interface must be public.
+parser_e_arithmetic_operation_overflow=03213_E_Transbordamento em opera‡Æo aritim‚tica
+% An operation on two integer values produced an overflow.
+parser_e_protected_or_private_expected=03214_E_Protected ou private esperados
+% \var{strict} can be only used together with \var{protected} or \var{private}.
+parser_e_illegal_slice=03215_E_SLICE nÆo pode ser usado fora da lista de parƒmetros
+% \var{slice} can be used only for arguments accepting an open array parameter.
+parser_e_dispinterface_cant_have_parent=03216_E_Uma DISPINTERFACE nÆo pode ter uma classe pai
+% A DISPINTERFACE is a special type of interface which can't have a parent class. Dispinterface always derive from IDispatch type.
+parser_e_dispinterface_needs_a_guid=03217_E_Uma DISPINTERFACE necessita de um GUID
+% A DISPINTERFACE always needs an interface identification (a GUID).
+parser_w_overridden_methods_not_same_ret=03218_W_M‚todos susbtitu¡dos devem ter um tipo de retorno relacionados. Este c¢digo pode travar, ele depende de uma falha do analizador Delphi ("$2" ‚ sobreposto por "$1" que possue outro tipo de retorno)
+% If you declare overridden methods in a class definition, they must
+% have the same return type. Some versions of Delphi allow you to change the
+% return type of interface methods, and even to change procedures into
+% functions, but the resulting code may crash depending on the types used
+% and the way the methods are called.
+parser_e_dispid_must_be_ord_const=03219_E_IDs despacho devem ser constantes ordinais
+% The \var{dispid} keyword must be followed by an ordinal constant (the dispid index).
+parser_e_array_range_out_of_bounds=03220_E_A faixa da matriz ‚ demasiada grande
+% Regardless of the size taken up by its elements, an array cannot have more
+% than high(ptrint) elements. Additionally, the range type must be a subrange
+% of ptrint.
+parser_e_packed_element_no_var_addr=03221_E_O endere‡o nÆo pode ser obtido de elementos de matriz de bits compactados ou campos de registro
+% If you declare an array or record as \var{packed} in Mac Pascal mode
+% (or as \var{packed} in any mode with \var{\{\$bitpacking on\}}), it will
+% be packed at the bit level. This means it becomes impossible to take addresses
+% of individual array elements or record fields. The only exception to this rule
+% is in the case of packed arrays elements whose packed size is a multple of 8 bits.
+parser_e_packed_dynamic_open_array=03222_E_Matrizes dinƒmicas nÆo podem ser compactadas
+% Only regular (and possibly in the future also open) arrays can be packed.
+parser_e_packed_element_no_loop=03223_E_Elementos de matrizes de bits compactados ou campos de registro nÆo podem ser usadas como vari veis de la‡os
+% If you declare an array or record as \var{packed} in Mac Pascal mode
+% (or as \var{packed} in any mode with \var{\{\$bitpacking on\}}), it will
+% be packed at the bit level. For performance reasons, they cannot be
+% used as loop variables.
+parser_e_type_var_const_only_in_records_and_classes=03224_E_VAR, TYPE e CONST sÆo permitidos apenas em registros, objetos e classes
+% The usage of VAR, TYPE and CONST to declare new types inside an object is allowed only inside
+% records, objects and classes.
+parser_e_cant_create_generics_of_this_type=03225_E_Este tipo nÆo pode ser um gen‚rico
+% Only Classes, Objects, Interfaces and Records are allowed to be used as generic.
+parser_w_no_lineinfo_use_switch=03226_W_NÆo caregue a unidade LINEINFO manualmente, Em vez disso utilize a chave de compilador -gl
+% Do not use the \file{lineinfo} unit directly, Use the \var{-gl} switch which
+% automatically adds the correct unit for reading the selected type of debugging
+% information. The unit that needs to be used depends on the type of
+% debug information used when compiling the binary.
+parser_e_no_funcret_specified=03227_E_Nenhum tipo de retorno de fun‡Æo especificado para a fun‡Æo "$1"
+% The first time you declare a function you have to declare it completely,
+% including all parameters and the result type.
+parser_e_special_onlygenerics=03228_E_Especializa‡Æo ‚ suportado apenas por tipos gen‚ricos
+% Types which are not generics can't be specialized.
+parser_e_no_generics_as_params=03229_E_Gen‚ricos nÆo podem ser usados como parƒmetros quando especializando gen‚ricos
+% When specializing a generic, only non-generic types can be used as parameters.
+parser_e_type_object_constants=03230_E_Constantes de objetos contendo uma VMT nÆo sÆo permitidas
+% If an object requires a VMT either because it contains a constructor or virtual methods,
+% it's not allowed to create constants of it. In TP and Delphi mode this is allowed
+% for compatibility reasons.
+parser_e_label_outside_proc=03231_E_Obter o endere‡o de r¢tulos definidos fora do escopo atual nÆo ‚ permitido
+% It isn't allowed to take the address of labels outside the
+% current procedure.
+parser_e_initialized_not_for_external=03233_E_Imposs¡vel inicializar vari veis declaradas como externas
+% Variables declared as external cannot be initialized with a default value.
+parser_e_illegal_function_result=03234_E_Tipo de retorno de fun‡Æo ilegal
+% Some types like file types cannot be used as function result.
+parser_e_no_common_type=03235_E_Nenhum tipo comum entre "$1" e "$2"
+% To perform an operation on integers, the compiler converts both operands
+% to their common type, which appears to be an invalid type. To determine the
+% common type of the operands, the compiler takes the minimum of the minimal values
+% of both types, and the maximum of the maximal values of both types. The common
+% type is then minimum..maximum.
+parser_e_no_generics_as_types=03236_E_Gen‚ricos sem especializa‡Æo nÆo podem ser usadas como um tipo para uma vari vel
+% Generics must be always specialized before being used as variable type.
+parser_w_register_list_ignored=03237_W_Lista registros ‚ ignorada para rotinas assembler puras
+% When using pure assembler routines, the list with modified registers is ignored.
+parser_e_implements_must_be_class_or_interface=03238_E_Propriedade 'Implements' deve ter tipo classe ou interface
+% A property which implements an interface must be of type class or interface.
+parser_e_implements_must_have_correct_type=03239_E_Propriedade 'Implements' deve implementar interface de tipo correto, encontrado "$1" esperado "$2"
+% A property which implements an interface actually implements a different interface.
+parser_e_implements_must_read_specifier=03240_E_Propriedade 'Implements' deve ter especificador de leitura
+% A property which implements an interface must have at least a read specifier.
+parser_e_implements_must_not_have_write_specifier=03241_E_Propriedade 'Implements' nÆo deve ter especificador de escrita
+% A property which implements an interface may not have a write specifier.
+parser_e_implements_must_not_have_stored_specifier=03242_E_Propriedade 'Implements' nÆo deve ter especificador de armazenagem
+% A property which implements an interface may not have a stored specifier.
+parser_e_implements_uses_non_implemented_interface=03243_E_Propriedade 'Implements' usada em interface nÆo implementada: "$1"
+% The interface which is implemented by a property is not an interface implemented by the class.
+parser_e_unsupported_real=03244_E_Ponto flutuante nÆo suportado para este alvo
+% The compiler parsed a floating point expression, but it is not supported.
+parser_e_class_doesnt_implement_interface=03245_E_Classe "$1" nÆo implementa interface "$2"
+% The delegated interface is not implemented by the class given in the implements clause.
+parser_e_class_implements_must_be_interface=03246_E_Tipo usado por implementa‡Æo deve ser uma interface
+% The \var{implements} keyword must be followed by an interface type.
+parser_e_cant_export_var_different_name=03247_E_Vari veis nÆo podem ser exportadas com um nome diferente neste alvo, adicione o nome na declara‡Æo usando a diretiva "export" (nome vari vel: $1, nome exporta‡Æo declarado: $2)
+% On most targets it is not possible to change the name under which a variable
+% is exported inside the \var{exports} statement of a library.
+% In that case, you have to specify the export name at the point where the
+% variable is declared, using the \var{export} and \var{alias} directives.
+parser_e_weak_external_not_supported=03248_E_S¡mbolos externos fracos nÆo sÆo suportados para o atual alvo
+% A "weak external" symbol is a symbol which may or may not exist at (either static
+% or dynamic) link time. This concept may not be available (or implemented yet)
+% on the current cpu/OS target.
+parser_e_forward_mismatch=03249_E_Defini‡Æo posterior tipo incompat¡vel
+% Classes and interfaces being defined forward must have the same type
+% when being implemented. A forward interface cannot be changed into a class.
+parser_n_ignore_lower_visibility=03250_N_M‚todo virtual "$1" tem baixa visibilidade ($2) que a classe pai $3 ($4)
+% The virtual method overrides an method that is declared with a higher visibility. This might give
+% unexpected results. In case the new visibility is private than it might be that a call to inherited in a
+% new child class will call the higher visible method in a parent class and ignores the private method.
+parser_e_field_not_allowed_here=03251_E_Campos nÆo podem aparecer depois dem um m‚todo ou defini‡Æo propriedade, inicie uma nova se‡Æo de visibilidade primeiro
+% Once a method or property has been defined in a class or object, you cannot define any fields afterwards
+% without starting a new visibility section (such as \var{public}, \var{private}, etc.). The reason is
+% that otherwise the source code can appear ambiguous to the compiler, since it is possible to use modifiers
+% such as \var{default} and \var{register} also as field names.
+parser_e_no_local_para_def=03252_E_Parƒmetros ou tipos resultado nÆo podem conter defini‡äes locais de tipo. Use uma defini‡Æo de tipo separada em um bloco de tipos
+% In Pascal, types are not considered to be identical simply because they are semantically equivalent.
+% Two variables or parameters are only considered to be of the same type if they refer to the
+% same type definition.
+% As a result, it is not allowed to define new types inside parameter lists, because then it is impossible to
+% refer to the same type definition in the procedure headers of the interface and implementation of a unit
+% (both procedure headers would define a separate type). Keep in mind that expressions such as
+% ``file of byte'' or ``string[50]'' also define a new type.
+parser_e_abstract_and_sealed_conflict=03253_E_Conflito ABSTRACT e SEALED
+% ABSTRACT and SEALED cannot be used together in one declaration
+parser_e_sealed_descendant=03254_E_Imposs¡vel criar um descendente da classe selada "$1"
+% Sealed means that class cannot be derived by another class.
+parser_e_sealed_class_cannot_have_abstract_methods=03255_E_Classe selada nÆo pode ter um m‚todo abstrato
+% Sealed means that class cannot be derived. Therefore no one class is able to override an abstract method in a sealed class.
+parser_e_only_virtual_methods_final=03256_E_Apenas m‚todos virtuais podem ser finais
+% You are declaring a method as final, when it is not declared to be
+% virtual.
+parser_e_final_can_no_be_overridden=03257_E_M‚todo final nÆo pode ser sobreposto: "$1"
+% You are trying to \var{override} a virtual method of a parent class that does
+% not exist.
+parser_e_multiple_messages=03258_E_Apenas uma mensagem pode ser usada por m‚todo.
+% It is not possible to associate multiple messages with a single method.
+parser_e_invalid_enumerator_identifier=03259_E_Identificador enumerador inv lido: "$1"
+% Only "MoveNext" and "Current" enumerator identifiers are supported.
+parser_e_enumerator_identifier_required=03260_E_Identificador enumerador requerido
+% "MoveNext" or "Current" identifier must follow the \var{enumerator} modifier.
+parser_e_enumerator_movenext_is_not_valid=03261_E_M‚todo enumerador 'MoveNext' padrÆo inv lido. M‚todo deve ser uma fun‡Æo com tipo de retorno booleano e sem argumentos requeridos.
+% "MoveNext" enumerator pattern method must be a function with Boolean return type and no required arguments
+parser_e_enumerator_current_is_not_valid=03262_E_Propriedade enumerador 'Current' padrÆo inv lido. Propriedade deve ter um 'getter'.
+% "Current" enumerator pattern property must have a getter
+parser_e_only_one_enumerator_movenext=03263_E_Apenas um m‚todo enumerador 'MoveNext' ‚ permitido por classe/objeto
+% Class or Object can have only one enumerator MoveNext declaration.
+parser_e_only_one_enumerator_current=03264_E_Apenas uma propriedade enumerador 'Current' ‚ permitida por classe/objeto
+% Class or Object can have only one enumerator Current declaration.
+parser_e_for_in_loop_cannot_be_used_for_the_type=03265_E_La‡o 'for in' nÆo pode ser usado para o tipo "$1"
+% For in loop can be used not for all types. For example it cannot be used for the enumerations with jumps.
+parser_e_objc_requires_msgstr=03266_E_Mensagens Objective-C requerem que seu nome seletor Objective-C seja especificado usando a diretiva "message".
+% Objective-C messages require their Objective-C name (selector name) to be specified using the \var{message `someName:'} procedure directive.
+% While bindings to other languages automatically generate such names based on the identifier you use (by replacing
+% all underscores with colons), this is unsafe since nothing prevents an Objective-C method name to contain actual
+% colons.
+parser_e_objc_no_constructor_destructor=03267_E_Objective-C nÆo tem construtores nem destruidores formais. Use as mensagens 'alloc', 'initXXX' e 'dealloc'.
+% The Objective-C language does not have any constructors or destructors. While there are some messages with a similar
+% purpose (such as \var{init} and \var{dealloc}), these cannot be identified using automatic parsers and do not
+% guarantee anything like Pascal constructors/destructors (e.g., you have to take care of only calling ``designated''
+% inherited ``constructors''). For these reasons, we have opted to follow the standard Objective-C patterns for
+% instance creation/destruction.
+parser_e_message_string_too_long=03268_E_Nome mensagem ‚ muito longo (max. 255 caracteres)
+% Due to compiler implementation reasons, message names are currently limited to 255 characters.
+parser_e_objc_message_name_too_long=03269_E_Nome s¡mbolo mensagem Objective-C para "$1" ‚ muito longo
+% Due to compiler implementation reasons, mangled message names (i.e., the symbol names used in the assembler
+% code) are currently limited to 255 characters.
+parser_h_no_objc_parent=03270_H_Definindo uma nova classe raiz Objective-C. Para derivar de outra classe raiz (ex., NSObject), especifique-a como pai da classe
+% If no parent class is specified for an Object Pascal class, then it automatically derives from TObject.
+% Objective-C classes however do not automatically derive from NSObject, because one can have multiple
+% root classes in Objective-C. For example, in the Cocoa framework both NSObject and NSProxy are root classes.
+% Therefore, you have to explicitly define a parent class (such as NSObject) if you want to derive your
+% Objective-C class from it.
+parser_e_no_objc_published=03271_E_Classes Objective-C nÆo podem ter se‡äes PUBLISHED
+% In Object Pascal, ``published'' determines whether or not RTTI is generated. Since the Objective-C runtime always needs
+% RTTI for everything, this specified does not make sense for Objective-C classes.
+parser_f_need_objc=03272_F_Este m¢dulo requer que seja especificado uma chave de modo Objective-C para ser compilado
+% This error indicates the use of Objective-C language features without an Objective-C mode switch
+% active. Enable one via the -M command line switch, or the {\$modeswitch x} directive.
+parser_e_must_use_override_objc=03273_E_M‚todos herdados podem apenas ser sobrepostos em Objective-C, adicione "OVERRIDE" (m‚todo herdado definido em $1)
+parser_h_should_use_override_objc=03274_H_M‚todos herdados podem apenas ser sobrepostos em Objective-C, adicione "OVERRIDE" (m‚todo herdado definido em $1).
+% It is not possible to \var{reintroduce} methods in Objective-C like in Object Pascal. Methods with the same
+% name always map to the same virtual method entry. In order to make this clear in the source code,
+% the compiler always requires the \var{override} directive to be specified when implementing overriding
+% Objective-C methods in Pascal. If the implementation is external, this rule is relaxed because Objective-C
+% does not have any \var{override}-style keyword (since it's the default and only behaviour in that language),
+% which makes it hard for automated header conversion tools to include it everywhere.
+% The type in which the inherited method is defined is explicitly mentioned, because this may either
+% be an objcclass or an objccategory.
+parser_e_objc_message_name_changed=03275_E_Nome mensagem "$1" na classe herdada ‚ diferente do nome mensagem "$2" na classe atual.
+% An overriding Objective-C method cannot have a different message name than an inherited method. The reason
+% is that these message names uniquely define the message to the Objective-C runtime, which means that
+% giving them a different message name breaks the ``override'' semantics.
+parser_e_no_objc_unique=03276_E_Ainda nÆo ‚ poss¡vel fazer c¢pias £nicas de tipos Objective-C
+% Duplicating an Objective-C type using \var{type x = type y;} is not yet supported. You may be able to
+% obtain the desired effect using \var{type x = objcclass(y) end;} instead.
+parser_e_no_category_as_types=03277_E_Categorias Objective-C e classes auxiliares Object Pascal nÆo podem ser usadas como tipos
+% It is not possible to declare a variable as an instance of an Objective-C
+% category or an Object Pascal class helper. A category/class helper adds
+% methods to the scope of an existing class, but does not define a type by
+% itself. An exception of this rule is when inheriting an Object Pascal class
+% helper from another class helper.
+parser_e_no_category_override=03278_E_Categorias nÆo sobrepäem, mas substituem m‚todos. Use "REINTRODUCE".
+parser_e_must_use_reintroduce_objc=03279_E_M‚todos substitu¡dos podem apenas ser reintroduzidos em Objective-C, adicione "REINTRODUCE" (m‚todo substitu¡do definido em $1).
+parser_h_should_use_reintroduce_objc=03280_H_M‚todos substitu¡dos podem apenas ser reintroduzidos em Objective-C, adicione "REINTRODUCE" (m‚todo substitu¡do definido em $1).
+% A category replaces an existing method in an Objective-C class, rather than that it overrides it.
+% Calling an inherited method from an category method will call that method in
+% the extended class' parent, not in the extended class itself. The
+% replaced method in the original class is basically lost, and can no longer be
+% called or referred to. This behaviour corresponds somewhat more closely to
+% \var{reintroduce} than to \var{override} (although in case of \var{reintroduce}
+% in Object Pascal, hidden methods are still reachable via inherited).
+% The type in which the inherited method is defined is explicitly mentioned, because this may either
+% be an objcclass or an objccategory.
+parser_e_implements_getter_not_default_cc=03281_E_'Getter' para implementa‡Æo interface deve usar a conven‡Æo de chamada padrÆo do alvo.
+% Interface getters are called via a helper in the run time library, and hence
+% have to use the default calling convention for the target (\var{register} on
+% i386 and x86\_64, \var{stdcall} on other architectures).
+parser_e_no_refcounted_typed_file=03282_E_Arquivos tipados nÆo podem conter tipos referˆncia-contados.
+% The data in a typed file cannot be of a reference counted type (such as
+% \var{ansistring} or a record containing a field that is reference counted).
+parser_e_operator_not_overloaded_2=03283_E_Operador nÆo est  sobrecarregado: $2 "$1"
+% You are trying to use an overloaded operator when it is not overloaded for
+% this type.
+parser_e_operator_not_overloaded_3=03284_E_Operador nÆo est  sobrecarregado: "$1" $2 "$3"
+% You are trying to use an overloaded operator when it is not overloaded for
+% this type.
+parser_e_more_array_elements_expected=03285_E_Esperados outros $1 elementos matriz
+% When declaring a typed constant array, you provided to few elements to initialize the array
+parser_e_string_const_too_long=03286_E_Constante 'String' muito longa, enquanto 'ansistrings' estÆo desabilitadas
+% Only when a piece of code is compiled with ansistrings enabled (\var{\{\$H+\}}), string constants
+% longer than 255 characters are allowed.
+parser_e_invalid_univ_para=03287_E_Tipo nÆo pode ser usado como parƒmetro 'univ' porque seu tamanho ‚ desconhecido em tempo compila‡Æo: "$1"
+% \var{univ} parameters are compatible with all values of the same size, but this
+% cannot be checked in case a parameter's size is unknown at compile time.
+parser_e_only_one_class_constructor_allowed=03288_E_Apenas um construtor de classe pode ser definido na classe: "$1"
+% You are trying to declare more than one class constructor but only one class constructor can be declared.
+parser_e_only_one_class_destructor_allowed=03289_E_Apenas um destruidor de classe pode ser definido na classe: "$1"
+% You are trying to declare more than one class destructor but only one class destructor can be declared.
+parser_e_no_paras_for_class_constructor=03290_E_Construtores de classe nÆo podem ter parƒmetros
+% You are declaring a class constructor with a parameter list. Class constructor methods
+% cannot have parameters.
+parser_e_no_paras_for_class_destructor=03291_E_Destruidores de classe nÆo podem ter parƒmetros
+% You are declaring a class destructor with a parameter list. Class destructor methods
+% cannot have parameters.
+parser_f_modeswitch_objc_required=03292_F_Esta constru‡Æo requer que chave de modo \{\$modeswitch objectivec1\} esteja ativa
+% Objective-Pascal constructs are not supported when \{\$modeswitch ObjectiveC1\}
+% is not active.
+parser_e_widestring_to_ansi_compile_time=03293_E_Constantes caracteres/unicode nÆo podem ser convertidas em "ansi/shortstring" em tempo de compila‡Æo
+% It is not possible to use unicodechar and unicodestring constants in
+% constant expressions that have to be converted into an ansistring or shortstring
+% at compile time, for example inside typed constants. The reason is that the
+% compiler cannot know what the actual ansi encoding will be at run time.
+parser_e_objc_enumerator_2_0=03294_E_La‡os "For-in Objective-Pascal" requerem que a chave \{\$modeswitch ObjectiveC2\} esteja ativa
+% Objective-C ``fast enumeration'' support was added in Objective-C 2.0, and
+% hence the appropriate modeswitch has to be activated to expose this feature.
+% Note that Objective-C 2.0 programs require Mac OS X 10.5 or later.
+parser_e_objc_missing_enumeration_defs=03295_E_O compilador nÆo encontrou os tipos "NSFastEnumerationProtocol" ou "NSFastEnumerationState" na unidade "CocoaAll"
+% Objective-C for-in loops (fast enumeration) require that the compiler can
+% find a unit called CocoaAll that contains definitions for the
+% NSFastEnumerationProtocol and NSFastEnumerationState types. If you get this
+% error, most likely the compiler is finding and loading an alternate CocoaAll
+% unit.
+parser_e_no_procvarnested_const=03296_E_Constantes tipadas do tipo 'procedimento ‚ aninhado' s¢ podem ser inicializadas com NIL e procedimentos/fun‡äes globais
+% A nested procedural variable consists of two components: the address of the
+% procedure/function to call (which is always known at compile time), and also
+% a parent frame pointer (which is never known at compile time) in case the
+% procedural variable contains a reference to a nested procedure/function.
+% Therefore such typed constants can only be initialized with global
+% functions/procedures since these do not require a parent frame pointer.
+parser_f_no_generic_inside_generic=03297_F_Declara‡Æo de classe gen‚rica dentro de outra classe gen‚rica nÆo ‚ permitido
+% At the moment, scanner supports recording of only one token buffer at the time
+% (guarded by internal error 200511173 in tscannerfile.startrecordtokens).
+% Since generics are implemented by recording tokens, it is not possible to
+% have declaration of generic class inside another generic class.
+parser_e_forward_protocol_declaration_must_be_resolved=03298_E_Declara‡Æo posterior de objcprotocl "$1" deve ser resolvida antes de uma objcclass possa conform -la
+% An objcprotocol must be fully defined before classes can conform to it.
+% This error occurs in the following situation:
+% \begin{verbatim}
+% Type MyProtocol = objcprotoocl;
+% ChildClass = Class(NSObject,MyProtocol)
+% ...
+% end;
+% \end{verbatim}
+% where \var{MyProtocol} is declared but not defined.
+parser_e_no_record_published=03299_E_Tipos registro nÆo podem ter se‡äes publicadas
+% Published sections can be used only inside classes.
+parser_e_no_destructor_in_records=03300_E_Destruidores nÆo sÆo permitidos em registros ou auxiliares
+% Destructor declarations aren't allowed in records or helpers.
+parser_e_class_methods_only_static_in_records=03301_E_M‚todos de classe devem ser est ticos em registros
+% Class methods declarations aren't allowed in records without static modifier.
+% Records have no inheritance and therefore non static class methods have no sence for them.
+parser_e_no_constructor_in_records=03302_E_Construtores nÆo sÆo permitidos em registros ou auxiliares de registro
+% Constructor declarations aren't allowed in records or record helpers.
+parser_e_at_least_one_argument_must_be_of_type=03303_E_Tanto o resultado ou ao menos um parƒmetro deve ser do tipo "$1"
+% It is required that either the result of the routine or at least one of its parameters be of the specified type.
+% For example class operators either take an instance of the structured type in which they are defined, or they return one.
+parser_e_cant_use_type_parameters_here=03304_E_Parƒmetros de tipo podem requerer inicializa‡Æo/finaliza‡Æo - nÆo podem ser usados em registros variant
+% Type parameters may be specialized with types which (e.g. \var{ansistring}) need initialization/finalization
+% code which is implicitly generated by the compiler.
+parser_e_externals_no_section=03305_E_Vari veis sendo declaradas como externas nÆo podem estar em uma se‡Æo customizada
+% A section directive is not valid for variables being declared as external.
+parser_e_section_no_locals=03306_E_Vari veis nÆo-est ticas e nÆo-globais nÆo podem ter uma diretiva de se‡Æo
+% A variable placed in a custom section is always statically allocated so it must be either a static or global variable.
+parser_e_not_allowed_in_helper=03307_E_"$1" nÆo ‚ permitido em tipos auxiliares
+% Some directives and specifiers like "virtual", "dynamic", "override" aren't
+% allowed inside helper types in mode ObjFPC (they are ignored in mode Delphi),
+% because they have no meaning within helpers. Also "abstract" isn't allowed in
+% either mode.
+parser_e_no_class_constructor_in_helpers=03308_E_Construtores de classe nÆo sÆo permitidos em auxiliares
+% Class constructor declarations aren't allowed in helpers.
+parser_e_inherited_not_in_record=03309_E_O uso de "inherited" nÆo ‚ permitido em um registro
+% As records don't suppport inheritance the use of "inherited" is prohibited for
+% these as well as for record helpers (in mode "Delphi" only).
+parser_e_no_types_in_local_anonymous_records=03310_E_Declara‡äes de tipo nÆo sÆo permitidas em registros locais ou an“nimos
+% Records with types must be defined globally. Types cannot be defined inside records which are defined in a
+% procedure or function or in anonymous records.
+parser_e_duplicate_implements_clause=03311_E_Cl usula "implements" duplicada para a interface "$1"
+% A class may delegate an interface using the "implements" clause only to a single property. Delegating it multiple times
+% is a error.
+parser_e_mapping_no_implements=03312_E_Interface "$1" nÆo pode ser delegada por "$2", j  possui resolu‡Æo de m‚todos
+% Method resolution clause maps a method of an interface to a method of the current class. Therefore the current class
+% has to implement the interface directly. Delegation is not possible.
+parser_e_implements_no_mapping=03313_E_Interface "$1" nÆo pode ter resolu‡Æo de m‚todo, "$2" j  a delega
+% Method resoulution is only possible for interfaces that are implemented directly, not by delegation.
+parser_e_invalid_codepage=03314_E_Codepage inv lido
+% When declaring a string with a given codepage, the range of valid codepages values is limited
+% to 0 to 65535.
+% \end{description}
+# Type Checking
+#
+# 04108 is the last used one
+#
+% \section{Type checking errors}
+% This section lists all errors that can occur when type checking is
+% performed.
+% \begin{description}
+type_e_mismatch=04000_E_Tipo incompat¡vel
+% This can happen in many cases:
+% \begin{itemize}
+% \item The variable you're assigning to is of a different type than the
+% expression in the assignment.
+% \item You are calling a function or procedure with parameters that are
+% incompatible with the parameters in the function or procedure definition.
+% \end{itemize}
+type_e_incompatible_types=04001_E_Tipos incompat¡veis: obtido "$1" esperado "$2"
+% There is no conversion possible between the two types.
+% Another possiblity is that they are declared in different
+% declarations:
+% \begin{verbatim}
+% Var
+% A1 : Array[1..10] Of Integer;
+% A2 : Array[1..10] Of Integer;
+%
+% Begin
+% A1:=A2; { This statement also gives this error. It
+% is due to the strict type checking of Pascal }
+% End.
+% \end{verbatim}
+type_e_not_equal_types=04002_E_Tipos incompat¡veis entre "$1" e "$2"
+% The types are not equal.
+type_e_type_id_expected=04003_E_Identificador de tipo esperado
+% The identifier is not a type, or you forgot to supply a type identifier.
+type_e_variable_id_expected=04004_E_Identificador de vari vel esperado
+% This happens when you pass a constant to a routine (such as \var{Inc} var or \var{Dec})
+% when it expects a variable. You can only pass variables as arguments to these functions.
+type_e_integer_expr_expected=04005_E_ExpressÆo inteira esperada, mas obtido "$1"
+% The compiler expects an expression of type integer, but gets a different
+% type.
+type_e_boolean_expr_expected=04006_E_ExpressÆo booleana esperada, mas obtido "$1"
+% The expression must be a boolean type. It should be return \var{True} or
+% \var{False}.
+type_e_ordinal_expr_expected=04007_E_ExpressÆo ordinal esperada
+% The expression must be of ordinal type, i.e., maximum a \var{Longint}.
+% This happens, for instance, when you specify a second argument
+% to \var{Inc} or \var{Dec} that doesn't evaluate to an ordinal value.
+type_e_pointer_type_expected=04008_E_Tipo ponteiro esperado, mas obtido "$1"
+% The variable or expression isn't of the type \var{pointer}. This
+% happens when you pass a variable that isn't a pointer to \var{New}
+% or \var{Dispose}.
+type_e_class_type_expected=04009_E_Tipo classe esperado, mas obtido "$1"
+% The variable or expression isn't of the type \var{class}. This happens
+% typically when
+% \begin{enumerate}
+% \item The parent class in a class declaration isn't a class.
+% \item An exception handler (\var{On}) contains a type identifier that
+% isn't a class.
+% \end{enumerate}
+type_e_cant_eval_constant_expr=04011_E_Imposs¡vel avaliar expressÆo constante
+% This error can occur when the bounds of an array you declared do
+% not evaluate to ordinal constants.
+type_e_set_element_are_not_comp=04012_E_Elementos conjunto nÆo sÆo compat¡veis
+% You are trying to perform an operation on two sets, when the set element types
+% are not the same. The base type of a set must be the same when taking the
+% union.
+type_e_set_operation_unknown=04013_E_Opera‡Æo nÆo implementada para conjuntos
+% several binary operations are not defined for sets.
+% These include: \var{div}, \var{mod}, \var{**}, \var{>=} and \var{<=}.
+% The last two may be defined for sets in the future.
+type_w_convert_real_2_comp=04014_W_ConversÆo autom tica de tipo de ponto flutuante para COMP que ‚ um inteiro
+% An implicit type conversion from a real type to a \var{comp} is
+% encountered. Since \var{comp} is a 64 bit integer type, this may indicate
+% an error.
+type_h_use_div_for_int=04015_H_Use DIV como alternativa para obter um resultado inteiro
+% When hints are on, then an integer division with the '/' operator will
+% produce this message, because the result will then be of type real.
+type_e_strict_var_string_violation=04016_E_Tipos 'String' devem coincidir exatamente no modo $V+
+% When compiling in \var{\{\$V+\}} mode, the string you pass as a parameter
+% should be of the exact same type as the declared parameter of the procedure.
+type_e_succ_and_pred_enums_with_assign_not_possible=04017_E_'SUCC' ou 'PRED' nÆo ‚ poss¡vel em enumera‡äes com atribui‡äes
+% If you declare an enumeration type which has C-like assignments
+% in it, such as in the following:
+% \begin{verbatim}
+% Tenum = (a,b,e:=5);
+% \end{verbatim}
+% then you cannot use the \var{Succ} or \var{Pred} functions with this enumeration.
+type_e_cant_read_write_type=04018_E_Imposs¡vel ler ou gravar vari veis deste tipo
+% You are trying to \var{read} or \var{write} a variable from or to a
+% file of type text, which doesn't support that variable's type.
+% Only integer types, reals, pchars and strings can be read from or
+% written to a text file. Booleans can only be written to text files.
+type_e_no_readln_writeln_for_typed_file=04019_E_Imposs¡vel usar 'readln' ou 'writeln' em arquivos tipados
+% \var{readln} and \var{writeln} are only allowed for text files.
+type_e_no_read_write_for_untyped_file=04020_E_Impossivel usar 'read' ou 'write' em arquivos nÆo tipados.
+% \var{read} and \var{write} are only allowed for text or typed files.
+type_e_typeconflict_in_set=04021_E_Conflito de tipos entre elementos de conjunto
+% There is at least one set element which is of the wrong type, i.e. not of
+% the set type.
+type_w_maybe_wrong_hi_lo=04022_W_lo/hi(dword/qword) retorna 'upper/lower word/dword'
+% \fpc supports an overloaded version of \var{lo/hi} for \var{longint/dword/int64/qword}
+% which returns the lower/upper word/dword of the argument. \tp always uses
+% a 16 bit \var{lo/hi} which always returns bits 0..7 for \var{lo} and the
+% bits 8..15 for \var{hi}. If you want the \tp behavior you have
+% to type cast the argument to a \var{word} or \var{integer}.
+type_e_integer_or_real_expr_expected=04023_E_ExpressÆo inteira ou real esperada
+% The first argument to \var{str} must be a real or integer type.
+type_e_wrong_type_in_array_constructor=04024_E_Tipo incorreto "$1" no construtor matriz
+% You are trying to use a type in an array constructor which is not
+% allowed.
+type_e_wrong_parameter_type=04025_E_Tipos incompat¡veis para o arg. no. $1: Obtido "$2", esperado "$3"
+% You are trying to pass an invalid type for the specified parameter.
+type_e_no_method_and_procedure_not_compatible=04026_E_M‚todo (vari vel) e Procedimento (vari vel) nÆo sÆo compat¡veis
+% You can't assign a method to a procedure variable or a procedure to a
+% method pointer.
+type_e_wrong_math_argument=04027_E_Constante ilegal passada para fun‡Æo matem tica interna
+% The constant argument passed to a \var{ln} or \var{sqrt} function is out of
+% the definition range of these functions.
+type_e_no_addr_of_constant=04028_E_Imposs¡vel obter o endere‡o de expressäes constantes
+% It is not possible to get the address of a constant expression, because they
+% aren't stored in memory. You can try making it a typed constant. This error
+% can also be displayed if you try to pass a property to a var parameter.
+type_e_argument_cant_be_assigned=04029_E_Argumento nÆo pode ser atribu¡do
+% Only expressions which can be on the left side of an
+% assignment can be passed as call by reference arguments.
+%
+% Remark: Properties can be used on the left side of an assignment,
+% nevertheless they cannot be used as arguments.
+type_e_cannot_local_proc_to_procvar=04030_E_Imposs¡vel atribuir procedimento/fun‡Æo local a vari vel procedimento
+% It's not allowed to assign a local procedure/function to a
+% procedure variable, because the calling convention of a local procedure/function is
+% different. You can only assign local procedure/function to a void pointer.
+type_e_no_assign_to_addr=04031_E_Imposs¡vel atribuir valores a um endere‡o
+% It is not allowed to assign a value to an address of a variable, constant,
+% procedure or function. You can try compiling with -So if the identifier
+% is a procedure variable.
+type_e_no_assign_to_const=04032_E_Imposs¡vel atribuir valors a uma vari vel constante
+% It's not allowed to assign a value to a variable which is declared
+% as a const. This is normally a parameter declared as const. To allow
+% changing the value, pass the parameter by value, or a parameter by reference
+% (using var).
+type_e_array_required=04033_E_Tipo matriz requerido
+% If you are accessing a variable using an index '[<x>]' then
+% the type must be an array. In FPC mode a pointer is also allowed.
+type_e_interface_type_expected=04034_E_Tipo interface esperado, mas obtido "$1"
+% The compiler expected to encounter an interface type name, but got something else.
+% The following code would produce this error:
+% \begin{verbatim}
+% Type
+% TMyStream = Class(TStream,Integer)
+% \end{verbatim}
+type_h_mixed_signed_unsigned=04035_H_Misturando expressäes assinadas e 'longwords' obtem-se um resultado de 64bits
+% If you divide (or calculate the modulus of) a signed expression by a longword (or vice versa),
+% or if you have overflow and/or range checking turned on and use an arithmetic
+% expression (+, -, *, div, mod) in which both signed numbers and longwords appear,
+% then everything has to be evaluated in 64-bit arithmetic which is slower than normal
+% 32-bit arithmetic. You can avoid this by typecasting one operand so it
+% matches the result type of the other one.
+type_w_mixed_signed_unsigned2=04036_W_Misturando expressäes assinadas e cardinais pode causar um erro de verifica‡Æo de faixa
+% If you use a binary operator (and, or, xor) and one of
+% the operands is a longword while the other one is a signed expression, then,
+% if range checking is turned on, you may get a range check error because in
+% such a case both operands are converted to longword before the operation is
+% carried out. You can avoid this by typecasting one operand so it
+% matches the result type of the other one.
+type_e_typecast_wrong_size_for_assignment=04037_E_ConversÆo de tipo tem tamanhos diferentes ($1 -> $2) na atribui‡Æo
+% Type casting to a type with a different size is not allowed when the variable is
+% used in an assignment.
+type_e_array_index_enums_with_assign_not_possible=04038_E_Enumera‡äes com atribui‡äes nÆo podem ser usadas como ¡ndice de matrizes
+% When you declared an enumeration type which has C-like
+% assignments, such as in the following:
+% \begin{verbatim}
+% Tenum = (a,b,e:=5);
+% \end{verbatim}
+% you cannot use it as the index of an array.
+type_e_classes_not_related=04039_E_Tipos Classe ou Objeto "$1" e "$2" nÆo estÆo relacionados
+% There is a typecast from one class or object to another while the class/object
+% are not related. This will probably lead to errors.
+type_w_classes_not_related=04040_W_Tipos Classe "$1" e "$2" nÆo estÆo relacionados
+% There is a typecast from one class to another while the classes
+% are not related. This will probably lead to errors.
+type_e_class_or_interface_type_expected=04041_E_Tipo classe ou interface esperado, mas obtido "$1"
+% The compiler expected a class or interface name, but got another type or identifier.
+type_e_type_is_not_completly_defined=04042_E_Tipo "$1" nÆo est  completamente definido
+% This error occurs when a type is not complete: i.e. a pointer type which points to
+% an undefined type.
+type_w_string_too_long=04043_W_Literal 'String' tem mais caracteres que comprimento 'string' curta
+% The size of the constant string, which is assigned to a shortstring,
+% is longer than the maximum size of the shortstring (255 characters).
+type_w_signed_unsigned_always_false=04044_W_Compara‡Æo pode ser sempre falsa devido a faixa da constante e expressÆo
+% There is a comparison between a constant and an expression where the constant is out of the
+% valid range of values of the expression. Because of type promotion, the statement will always evaluate to
+% false. Explicitly typecast the constant or the expression to the correct range to avoid this warning
+% if you think the code is correct.
+type_w_signed_unsigned_always_true=04045_W_Compara‡Æo pode ser sempre verdadeira devido a faixa da constante e expressÆo
+% There is a comparison between a constant and an expression where the constant is out of the
+% valid range of values of the expression. Because of type promotion, the statement will always evaluate to
+% true. Explicitly typecast the constant or the expression to the correct range to avoid this warning
+% if you think the code is correct.
+type_w_instance_with_abstract=04046_W_Construindo uma classe "$1" com m‚todo abstrato "$2"
+% An instance of a class is created which contains non-implemented abstract
+% methods. This will probably lead to a runtime error 211 in the code if that
+% routine is ever called. All abstract methods should be overridden.
+type_h_in_range_check=04047_H_O operador esquerdo em um operador 'IN' deve ser tamanho byte
+% The left operand of the \var{in} operator is not an ordinal or enumeration which fits
+% within 8 bits. This may lead to range check errors. The \var{in} operator
+% currently only supports a left operand which fits within a byte. In the case of
+% enumerations, the size of an element of an enumeration can be controlled with
+% the \var{\{\$PACKENUM\}} or \var{\{\$Zn\}} switches.
+type_w_smaller_possible_range_check=04048_W_Tamanho tipo incompat¡vel, poss¡vel perda de dados / erro verifica‡Æo faixa
+% There is an assignment to a smaller type than the source type. This means that
+% this may cause a range-check error, or may lead to possible loss of data.
+type_h_smaller_possible_range_check=04049_H_Tamanho tipo incompat¡vel, poss¡vel perda de dados / erro verifica‡Æo faixa
+% There is an assignment to a smaller type than the source type. This means that
+% this may cause a range-check error, or may lead to possible loss of data.
+type_e_cant_take_address_of_abstract_method=04050_E_O endere‡o de um m‚todo abstrato nÆo pode ser obtido
+% An abstract method has no body, so the address of an abstract method can't be taken.
+type_e_assignment_not_allowed=04051_E_Atribui‡äes … parƒmetros formais e matrizes abertas nÆo sÆo poss¡veis
+% You are trying to assign a value to a formal (untyped var, const or out)
+% parameter, or to an open array.
+type_e_constant_expr_expected=04052_E_ExpressÆo constante esperada
+% The compiler expects an constant expression, but gets a variable expression.
+type_e_operator_not_supported_for_types=04053_E_Opera‡Æo "$1" nÆo ‚ suportada para os tipos "$2" e "$3"
+% The operation is not allowed for the supplied types.
+type_e_illegal_type_conversion=04054_E_ConversÆo de tipo ilegal: "$1" para "$2"
+% When doing a type-cast, you must take care that the sizes of the variable and
+% the destination type are the same.
+type_h_pointer_to_longint_conv_not_portable=04055_H_ConversÆo entre ordinais e ponteiros nÆo ‚ port vel
+% If you typecast a pointer to a longint (or vice-versa), this code will not compile
+% on a machine using 64 bits addressing.
+type_w_pointer_to_longint_conv_not_portable=04056_W_ConversÆo entre ordinais e ponteiros nÆo ‚ port vel
+% If you typecast a pointer to an ordinal type of a different size (or vice-versa), this can
+% cause problems. This is a warning to help in finding the 32-bit specific code where cardinal/longint is used
+% to typecast pointers to ordinals. A solution is to use the ptrint/ptruint types instead.
+type_e_cant_choose_overload_function=04057_E_Imposs¡vel determinar qual fun‡Æo sobrecarregada chamar
+% You're calling overloaded functions with a parameter that doesn't correspond
+% to any of the declared function parameter lists. e.g. when you have declared
+% a function with parameters \var{word} and \var{longint}, and then you call
+% it with a parameter which is of type \var{integer}.
+type_e_illegal_count_var=04058_E_Vari vel contador ilegal
+% The type of a \var{for} loop variable must be an ordinal type.
+% Loop variables cannot be reals or strings.
+type_w_double_c_varargs=04059_W_Convertendo constante valor real para 'double' para vari vel argumento C, adicione conversÆo de tipo expl¡cita para evitar isso.
+% In C, constant real values are double by default. For this reason, if you
+% pass a constant real value to a variable argument part of a C function, FPC
+% by default converts this constant to double as well. If you want to prevent
+% this from happening, add an explicit typecast around the constant.
+type_e_class_or_cominterface_type_expected=04060_E_Tipo Classe ou interface COM esperado, mas obtido "$1"
+% Some operators, such as the AS operator, are only applicable to classes or COM interfaces.
+type_e_no_const_packed_array=04061_E_Matrizes constantes compactadas nÆo sÆo suportadas ainda
+% You cannot declare a (bit)packed array as a typed constant.
+type_e_got_expected_packed_array=04062_E_Tipos incompat¡veis para arg. no. $1: Obtido "$2" esperado "Matriz compactada (Bits)"
+% The compiler expects a (bit)packed array as the specified parameter.
+type_e_got_expected_unpacked_array=04063_E_Tipos incompat¡veis para arg. no. $1: Obtido "$2" esperado "Matriz (nÆo compactada)"
+% The compiler expects a regular (i.e., not packed) array as the specified parameter.
+type_e_no_packed_inittable=04064_E_Elementos de matrizes compactadas nÆo podem ser de um tipo que necessita ser inicializado
+% Support for packed arrays of types that need initialization
+% (such as ansistrings, or records which contain ansistrings) is not yet implemented.
+type_e_no_const_packed_record=04065_E_Registros constantes compactadas e objetos nÆo sÆo suportados ainda
+% You cannot declare a (bit)packed array as a typed constant at this time.
+type_w_untyped_arithmetic_unportable=04066_W_Aritm‚tica "$1" em ponteiros nÆo tipados nÆo ‚ port vel {$T+}, sugere-se conversÆo de tipo
+% Addition/subtraction from an untyped pointer may work differently in \var{\{\$T+\}}.
+% Use a typecast to a typed pointer.
+type_e_cant_take_address_of_local_subroutine=04076_E_Imposs¡vel obter endere‡o de uma subrotina marcada como local
+% The address of a subroutine marked as local can't be taken.
+type_e_cant_export_local=04077_E_Imposs¡vel exportar subrotina marcada como local de uma unidade
+% A subroutine marked as local can't be exported from a unit.
+type_e_not_automatable=04078_E_Tipo nÆo ‚ automatiz vel: "$1"
+% Only byte, integer, longint, smallint, currency, single, double, ansistring,
+% widestring, tdatetime, variant, olevariant, wordbool and all interfaces are automatable.
+type_h_convert_add_operands_to_prevent_overflow=04079_H_Convertendo os operandos para "$1" antes de realizar a soma pode prevenir erros de transbordamento.
+% Adding two types can cause overflow errors. Since you are converting the result to a larger type, you
+% could prevent such errors by converting the operands to this type before doing the addition.
+type_h_convert_sub_operands_to_prevent_overflow=04080_H_Convertendo os operandos para "$1" antes de realizar a subtra‡Æo pode prevenir erros de transbordamento.
+% Subtracting two types can cause overflow errors. Since you are converting the result to a larger type, you
+% could prevent such errors by converting the operands to this type before doing the subtraction.
+type_h_convert_mul_operands_to_prevent_overflow=04081_H_Convertendo os operados para "$1" antes de realizar a multiplica‡Æo pode prevenir erros de transbordamento.
+% Multiplying two types can cause overflow errors. Since you are converting the result to a larger type, you
+% could prevent such errors by converting the operands to this type before doing the multiplication.
+type_w_pointer_to_signed=04082_W_Convertendo ponteiros para inteiros assinados pode resultar em compara‡äes de resultados incorretas e erros de faixa. Ao inv‚s disso, use tipos nÆo assinados.
+% The virtual address space on 32-bit machines runs from \$00000000 to \$ffffffff.
+% Many operating systems allow you to allocate memory above \$80000000.
+% For example both \windows and \linux allow pointers in the range \$0000000 to \$bfffffff.
+% If you convert pointers to signed types, this can cause overflow and range check errors,
+% but also \$80000000 < \$7fffffff. This can cause random errors in code like "if p>q".
+type_e_interface_has_no_guid=04083_E_Tipo interface $1 nÆo tem um GUID v lido
+% When applying the as-operator to an interface or class, the desired interface (i.e. the right operand of the
+% as-operator) must have a valid GUID.
+type_e_invalid_objc_selector_name=04084_E_Nome seletor inv lido "$1"
+% An Objective-C selector cannot be empty, must be a valid identifier or a single colon,
+% and if it contains at least one colon it must also end in one.
+type_e_expected_objc_method_but_got=04085_E_M‚todo Objective-C esperado, mas obtido $1
+% A selector can only be created for Objective-C methods, not for any other kind
+% of procedure/function/method.
+type_e_expected_objc_method=04086_E_M‚todo Objective-C ou nome m‚todo constante esperados
+% A selector can only be created for Objective-C methods, either by specifying
+% the name using a string constant, or by using an Objective-C method identifier
+% that is visible in the current scope.
+type_e_no_type_info=04087_E_Nenhuma informa‡Æo de tipo dispon¡vel para este tipo
+% Type information is not generated for some types, such as enumerations with gaps
+% in their value range (this includes enumerations whose lower bound is different
+% from zero).
+type_e_ordinal_or_string_expr_expected=04088_E_Ordinal ou expressÆo 'string' esperados
+% The expression must be an ordinal or string type.
+type_e_string_expr_expected=04089_E_ExpressÆo 'string' esperada
+% The expression must be a string type.
+type_w_zero_to_nil=04090_W_Convertendo 0 para NIL
+% Use NIL rather than 0 when initialising a pointer.
+type_e_protocol_type_expected=04091_E_Tipo protocolo Objective-C esperado, mas obtido "$1"
+% The compiler expected a protocol type name, but found something else.
+type_e_objc_type_unsupported=04092_E_O tipo "$1" nÆo ‚ suportado para intera‡Æo com c¢digo Objective-C de tempo execu‡Æo.
+% Objective-C makes extensive use of run time type information (RTTI). This format
+% is defined by the maintainers of the run time and can therefore not be adapted
+% to all possible Object Pascal types. In particular, types that depend on
+% reference counting by the compiler (such as ansistrings and certain kinds of
+% interfaces) cannot be used as fields of Objective-C classes, cannot be
+% directly passed to Objective-C methods, and cannot be encoded using \var{objc\_encode}.
+type_e_class_or_objcclass_type_expected=04093_E_Tipo classe ou 'objcclass' esperados, mas obtido "$1"
+% It is only possible to create class reference types of \var{class} and \var{objcclass}
+type_e_objcclass_type_expected=04094_E_Tipo 'Objcclass' esperado
+% The compiler expected an \var{objcclass} type
+type_w_procvar_univ_conflicting_para=04095_W_Tipo parƒmetro 'univ' for‡ado em vari vel procedimental pode causar travamento ou corrup‡Æo de mem¢ria: $1 para $2
+% \var{univ} parameters are implicitly compatible with all types of the same size,
+% also in procedural variable definitions. That means that the following code is
+% legal, because \var{single} and \var{longint} have the same size:
+% \begin{verbatim}
+% {$mode macpas}
+% Type
+% TIntProc = procedure (l: univ longint);
+%
+% procedure test(s: single);
+% begin
+% writeln(s);
+% end;
+%
+% var
+% p: TIntProc;
+% begin
+% p:=test;
+% p(4);
+% end.
+% \end{verbatim}
+% This code may however crash on platforms that pass integers in registers and
+% floating point values on the stack, because then the stack will be unbalanced.
+% Note that this warning will not flagg all potentially dangerous situations.
+% when \var{test} returns.
+type_e_generics_cannot_reference_itself=04096_E_Parƒmetros de tipo de especializa‡äes de gen‚ricos nÆo podem referenciar o tipo especializado atual
+% Recursive specializations of generics like \var{Type MyType = specialize MyGeneric<MyType>;} are not possible.
+type_e_type_parameters_are_not_allowed_here=04097_E_Parƒmetros de tipo nÆo sÆo permitidos em procedimentos ou fun‡äes de classe/registro/objeto nÆo-gen‚rico
+% Type parameters are only allowed for methods of generic classes, records or objects
+type_e_generic_declaration_does_not_match=04098_E_Declara‡Æo gen‚rica de "$1" difere da declara‡Æo anterior
+% Generic declaration does not match the previous declaration
+type_e_helper_type_expected=04099_E_Tipo auxiliar esperado
+% The compiler expected a \var{class helper} type.
+type_e_record_type_expected=04100_E_Tipo registro esperado
+% The compiler expected a \var{record} type.
+type_e_class_helper_must_extend_subclass=04101_E_Classe auxiliar derivada deve extender a subclasse de "$1" ou a pr¢pria classe
+% If a class helper inherits from another class helper the extended class must
+% extend either the same class as the parent class helper or a subclass of it
+type_e_record_helper_must_extend_same_record=04102_E_Registro auxiliar derivado deve extender "$1"
+% If a record helper inherits from another record helper it must extend the same
+% record that the parent record helper extended.
+type_e_procedures_return_no_value=04103_E_Atribui‡Æo inv lida, procedimento nÆo retorna valor
+% This error occurs when one tries to assign the result of a procedure or destructor call.
+% A procedure or destructor returns no value so this is not
+% possible.
+type_w_implicit_string_cast=04104_W_ConversÆo de tipo 'string' impl¡cita de "$1" para "$2"
+% An implicit type conversion from an ansi string type to an unicode string type is
+% encountered. To avoid this warning perform an explicit type conversion.
+type_w_implicit_string_cast_loss=04105_W_ConversÆo de tipo 'string' impl¡cita com potencial de perda de dados de "$1" para "$2"
+% An implicit type conversion from an unicode string type to an ansi string type is
+% encountered. This conversion can lose data since not all unicode characters may be represented in the codepage of
+% destination string type.
+type_w_explicit_string_cast=04106_-W_ConversÆo de tipo 'string' expl¡cita de "$1" para "$2"
+% An explicit typecast from an ansi string type to an unicode string type is
+% encountered. This warning is off by default. You can turn it on to see all suspicious string conversions.
+type_w_explicit_string_cast_loss=04107_-W_ConversÆo de tipo 'string' expl¡cita com potencial de perda de dados de "$1" para "$2"
+% An explicit typecast from an unicode string type to an ansi string type is
+% encountered. This conversion can lose data since not all unicode characters may be represented in the codepage of
+% destination string type. This warning is off by default. You can turn it on to see all the places with lossy string
+% conversions.
+type_w_unicode_data_loss=04108_W_ConversÆo de constante Unicode com potencial de perda de dados
+% Conversion from a WideChar to AnsiChar can lose data since now all unicode characters may be represented in the current
+% system codepage
+% \end{description}
+#
+# Symtable
+#
+# 05084 is the last used one
+#
+% \section{Symbol handling}
+% This section lists all the messages that concern the handling of symbols.
+% This means all things that have to do with procedure and variable names.
+% \begin{description}
+sym_e_id_not_found=05000_E_Identificador nÆo encontrado "$1"
+% The compiler doesn't know this symbol. Usually happens when you misspell
+% the name of a variable or procedure, or when you forget to declare a
+% variable.
+sym_f_internal_error_in_symtablestack=05001_F_Erro interno em SymTableStack()
+% An internal error occurred in the compiler; If you encounter such an error,
+% please contact the developers and try to provide an exact description of
+% the circumstances in which the error occurs.
+sym_e_duplicate_id=05002_E_Identificador duplicado "$1"
+% The identifier was already declared in the current scope.
+sym_h_duplicate_id_where=05003_H_Identificador j  definido em $1 na linha $2
+% The identifier was already declared in a previous scope.
+sym_e_unknown_id=05004_E_Identificador desconhecido "$1"
+% The identifier encountered has not been declared, or is used outside the
+% scope where it is defined.
+sym_e_forward_not_resolved=05005_E_Declara‡Æo posterior nÆo resolvida "$1"
+% This can happen in two cases:
+% \begin{itemize}
+% \item You declare a function in the \var{interface} part, or
+% with a \var{forward} directive, but do not implement it.
+% \item You reference a type which isn't declared in the current \var{type}
+% block.
+% \end{itemize}
+sym_e_error_in_type_def=05007_E_Erro na defini‡Æo de tipo
+% There is an error in your definition of a new array type.
+% One of the range delimiters in an array declaration is erroneous.
+% For example, \var{Array [1..1.25]} will trigger this error.
+sym_e_forward_type_not_resolved=05009_E_Tipo posterior nÆo resolvido "$1"
+% A symbol was forward defined, but no declaration was encountered.
+sym_e_only_static_in_static=05010_E_Apenas vari veis est ticas podem ser usadas em m‚todos est ticos ou m‚todos externos
+% A static method of an object can only access static variables.
+sym_f_type_must_be_rec_or_class=05012_F_Tipo registro ou classe esperados
+% The variable or expression isn't of the type \var{record} or \var{class}.
+sym_e_no_instance_of_abstract_object=05013_E_Instƒncias de classes ou objetos com m‚todos abstratos nÆo sÆo permitidas
+% You are trying to generate an instance of a class which has an abstract
+% method that wasn't overridden.
+sym_w_label_not_defined=05014_W_R¢tulo nÆo definido "$1"
+% A label was declared, but not defined.
+sym_e_label_used_and_not_defined=05015_E_R¢tulo usado mas nÆo definido "$1"
+% A label was declared and used, but not defined.
+sym_e_ill_label_decl=05016_E_Declara‡Æo r¢tulo ilegal
+% This error should never happen; it occurs if a label is defined outside a
+% procedure or function.
+sym_e_goto_and_label_not_supported=05017_E_GOTO e LABEL nÆo sÆo suportados (use a chave -Sg)
+% You must use the -Sg switch to compile a program which has \var{label}s
+% and \var{goto} statements. By default, \var{label} and \var{goto} aren't
+% supported.
+sym_e_label_not_found=05018_E_R¢tulo nÆo encontrado
+% A \var{goto label} was encountered, but the label wasn't declared.
+sym_e_id_is_no_label_id=05019_E_Identificador nÆo ‚ um r¢tulo
+% The identifier specified after the \var{goto} isn't of type label.
+sym_e_label_already_defined=05020_E_R¢tulo j  definido
+% You are defining a label twice. You can define a label only once.
+sym_e_ill_type_decl_set=05021_E_Declara‡Æo de tipo de conjunto de elementos ilegal
+% The declaration of a set contains an invalid type definition.
+sym_e_class_forward_not_resolved=05022_E_Declara‡Æo posterior de classe nÆo resolvida "$1"
+% You declared a class, but you did not implement it.
+sym_n_unit_not_used=05023_H_Unidade "$1" nÆo usada em $2
+% The unit referenced in the \var{uses} clause is not used.
+sym_h_para_identifier_not_used=05024_H_Parƒmetro "$1" nÆo usado
+% The identifier was declared (locally or globally) but
+% was not used (locally or globally).
+sym_n_local_identifier_not_used=05025_N_Vari vel local "$1" nÆo usada
+% You have declared, but not used, a variable in a procedure or function
+% implementation.
+sym_h_para_identifier_only_set=05026_H_Valor parƒmetro "$1" ‚ atribu¡do mas nunca usado
+% The identifier was declared (locally or globally) and
+% assigned to, but is not used (locally or globally) after the assignment.
+sym_n_local_identifier_only_set=05027_N_Vari vel local "$1" ‚ atribu¡da mas nunca usada
+% The variable in a procedure or function implementation is declared and
+% assigned to, but is not used after the assignment.
+sym_h_local_symbol_not_used=05028_H_Local $1 "$2" nÆo ‚ usado
+% A local symbol is never used.
+sym_n_private_identifier_not_used=05029_N_Campo privado "$1.$2" nunca usado
+% The indicated private field is defined, but is never used in the code.
+sym_n_private_identifier_only_set=05030_N_Campo privado "$1.$2" ‚ atribu¡do mas nunca usado
+% The indicated private field is declared and assigned to, but never read.
+sym_n_private_method_not_used=05031_N_M‚todo privado "$1.$2" nunca usado
+% The indicated private method is declared but is never used in the code.
+sym_e_set_expected=05032_E_Tipo conjunto esperado
+% The variable or expression is not of type \var{set}. This happens in an
+% \var{in} statement.
+sym_w_function_result_not_set=05033_W_Retorno da fun‡Æo parece nÆo ter sido ajustado
+% You can get this warning if the compiler thinks that a function return
+% value is not set. This will not be displayed for assembler procedures,
+% or procedures that contain assembler blocks.
+sym_w_wrong_C_pack=05034_W_Tipo "$1" nÆo est  alinhado corretamente no atual registro para C
+% Arrays with sizes not multiples of 4 will be wrongly aligned
+% for C structures.
+sym_e_illegal_field=05035_E_Identificador de campo de registro desconhecido "$1"
+% The field doesn't exist in the record/object definition.
+sym_w_uninitialized_local_variable=05036_W_Vari vel local "$1" nÆo parece ter sido inicializada
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. it appears in the right-hand side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assignment).
+sym_w_uninitialized_variable=05037_W_Vari vel "$1" parece nÆo ter sido inicializada
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. it appears in the right-hand side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assignment).
+sym_e_id_no_member=05038_E_Identificador nÆo identifica nenhum membro "$1"
+% This error is generated when an identifier of a record,
+% field or method is accessed while it is not defined.
+sym_h_param_list=05039_H_Declara‡Æo encontrada: $1
+% You get this when you use the \var{-vh} switch.In the case of an overloaded procedure
+% not being found. Then all candidate overloaded procedures are
+% listed, with their parameter lists.
+sym_e_segment_too_large=05040_E_Elemento de dados muito grande
+% You get this when you declare a data element whose size exceeds the
+% prescribed limit (2 Gb on 80386+/68020+ processors).
+sym_e_no_matching_implementation_found=05042_E_Nenhuma implementa‡Æo coincidente para m‚todo interface "$1" encontrada
+% There was no matching method found which could implement the interface
+% method. Check argument types and result type of the methods.
+sym_w_deprecated_symbol=05043_W_S¡mbolo "$1" est  depreciado
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{deprecated} is used. Deprecated symbols may no longer
+% be available in newer versions of the unit / library. Use of this symbol
+% should be avoided as much as possible.
+sym_w_non_portable_symbol=05044_W_S¡mbolo "$1" nÆo ‚ port vel
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{platform} is used. This symbol's value, use
+% and availability is platform specific and should not be used
+% if the source code must be portable.
+sym_w_non_implemented_symbol=05055_W_S¡mbolo "$1" nÆo est  implementado
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{unimplemented} is used. This symbol is defined,
+% but is not yet implemented on this specific platform.
+sym_e_cant_create_unique_type=05056_E_Imposs¡vel criar tipo £nico para este tipo
+% Only simple types like ordinal, float and string types are supported when
+% redefining a type with \var{type newtype = type oldtype;}.
+sym_h_uninitialized_local_variable=05057_H_Vari vel local "$1" parece nÆo ter sido inicializada
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. it appears in the right-hand side of an expression) when it
+% was not initialized first (i.e. it did not appear in the left-hand side of an
+% assignment).
+sym_h_uninitialized_variable=05058_H_Vari vel "$1" parece nÆo ter sido inicializada
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. it appears in the right-hand side of an expression) when it
+% was not initialized first (i.e. t did not appear in the left-hand side of an
+% assignment).
+sym_w_function_result_uninitialized=05059_W_Vari vel de retorno da fun‡Æo parece nÆo ter sido inicializada
+% This message is displayed if the compiler thinks that the function result
+% variable will be used (i.e. it appears in the right-hand side of an expression)
+% before it is initialized (i.e. before it appeared in the left-hand side of an
+% assignment).
+sym_h_function_result_uninitialized=05060_H_Vari vel de retorno da fun‡Æo parece nÆo ter sido inicializada
+% This message is displayed if the compiler thinks that the function result
+% variable will be used (i.e. it appears in the right-hand side of an expression)
+% before it is initialized (i.e. it appears in the left-hand side of an
+% assignment)
+sym_w_identifier_only_read=05061_W_Vari vel "$1" lida mas nÆo atribu¡da em lugar algum
+% You have read the value of a variable, but nowhere assigned a value to
+% it.
+sym_h_abstract_method_list=05062_H_M‚todo abstrato encontrado: $1
+% When getting a warning about constructing a class/object with abstract methods
+% you get this hint to assist you in finding the affected method.
+sym_w_experimental_symbol=05063_W_S¡mbolo "$1" ‚ experimental
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{experimental} is used. Experimental symbols
+% might disappear or change semantics in future versions. Usage of this symbol
+% should be avoided as much as possible.
+sym_w_forward_not_resolved=05064_W_Declara‡Æo posterior "$1" nÆo resolvida, assumida como externa
+% This happens if you declare a function in the \var{interface} of a unit in macpas mode,
+% but do not implement it.
+sym_w_library_symbol=05065_W_S¡mbolo "$1" pertence a uma biblioteca
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{library} is used. Library symbols may not be
+% available in other libraries.
+sym_w_deprecated_symbol_with_msg=05066_W_S¡mbolo "$1" est  depreciado: "$2"
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{deprecated} is used. Deprecated symbols may no longer
+% be available in newer versions of the unit / library. Use of this symbol
+% should be avoided as much as possible.
+sym_e_no_enumerator=05067_E_Imposs¡vel encontrar um enumerador para o tipo "$1"
+% This means that compiler cannot find an apropriate enumerator to use in the for-in loop.
+% To create an enumerator you need to defind an operator enumerator or add a public or published
+% GetEnumerator method to the class or object definition.
+sym_e_no_enumerator_move=05068_E_Imposs¡vel encontrar um m‚todo "MoveNext" no enumerador "$1"
+% This means that compiler cannot find a public MoveNext method with the Boolean return type in
+% the enumerator class or object definition.
+sym_e_no_enumerator_current=05069_E_Imposs¡vel encontrar uma propriedade "Current" no enumerador "$1"
+% This means that compiler cannot find a public Current property in the enumerator class or object
+% definition.
+sym_e_objc_para_mismatch=05070_E_Incompatibilidade entre n£mero de parƒmetros declarados e n£mero de dois pontos (:) na 'string' mensagem.
+% In Objective-C, a message name automatically contains as many colons as parameters.
+% In order to prevent mistakes when specifying the message name in FPC, the compiler
+% checks whether this is also the case here. Note that in case of messages taking a
+% variable number of arguments translated to FPC via an \var{array of const} parameter,
+% this final \var{array of const} parameter is not counted. Neither are the hidden
+% \var{self} and \var{\_cmd} parameters.
+sym_n_private_type_not_used=05071_N_Tipo privado "$1.$2" nunca usado
+% The indicated private type is declared but is never used in the code.
+sym_n_private_const_not_used=05072_N_Constante privada "$1.$2" nunca usada
+% The indicated private const is declared but is never used in the code.
+sym_n_private_property_not_used=05073_N_Propriedade privada "$1.$2" nunca usada
+% The indicated private property is declared but is never used in the code.
+sym_w_deprecated_unit=05074_W_Unidade "$1" est  depreciada
+% This means that a unit which is
+% declared as \var{deprecated} is used. Deprecated units may no longer
+% be available in newer versions of the library. Use of this unit
+% should be avoided as much as possible.
+sym_w_deprecated_unit_with_msg=05075_W_Unidade "$1" est  depreciada: "$2"
+% This means that a unit which is
+% declared as \var{deprecated} is used. Deprecated units may no longer
+% be available in newer versions of the library. Use of this unit
+% should be avoided as much as possible.
+sym_w_non_portable_unit=05076_W_Unidade "$1" nÆo ‚ port vel
+% This means that a unit which is
+% declared as \var{platform} is used. This unit use
+% and availability is platform specific and should not be used
+% if the source code must be portable.
+sym_w_library_unit=05077_W_Unidade "$1" pertence a uma biblioteca
+% This means that a unit which is
+% declared as \var{library} is used. Library units may not be
+% available in other libraries.
+sym_w_non_implemented_unit=05078_W_Unidade "$1" nÆo est  implementada
+% This means that a unit which is
+% declared as \var{unimplemented} is used. This unit is defined,
+% but is not yet implemented on this specific platform.
+sym_w_experimental_unit=05079_W_Unidade "$1" ‚ experimental
+% This means that a unit which is
+% declared as \var{experimental} is used. Experimental units
+% might disappear or change semantics in future versions. Usage of this unit
+% should be avoided as much as possible.
+sym_e_objc_formal_class_not_resolved=05080_E_Nenhuma defini‡Æo completa da classe objeto formalmente declarada "$1" est  no escopo
+% Objecive-C classes can be imported formally, without using the the unit in which it is fully declared.
+% This enables making forward references to such classes and breaking circular dependencies amongst units.
+% However, as soon as you wish to actually do something with an entity of this class type (such as
+% access one of its fields, send a message to it, or use it to inherit from), the compiler requires the full definition
+% of the class to be in scope.
+sym_e_interprocgoto_into_init_final_code_not_allowed=05081_E_Gotos dentro de blocos de inicializa‡Æo ou finaliza‡Æo de unidades nÆo sÆo permitidos
+% Gotos into initialization or finalization blockse of units are not allowed.
+sym_e_external_class_name_mismatch1=05082_E_Nome externo inv lido "$1" para classe formal "$2"
+sym_e_external_class_name_mismatch2=05083_E_Complete a defini‡Æo de classe com nome externo "$1" aqui
+% When a class is declared using a formal external definition, the actual external
+% definition (if any) must specify the same external name as the formal definition
+% (since both definitions refer to the same actual class type).
+sym_w_library_overload=05084_W_Poss¡vel conflito em biblioteca: s¡mbolo "$1" da biblioteca "$2" tamb‚m encontrado na biblioteca "$3"
+% Some OS do not have library specific namespaces, for those
+% OS, the function declared as "external 'libname' name 'funcname'",
+% the 'libname' part is only a hint, funcname might also be loaded
+% by another library. This warning appears if 'funcname' is used twice
+% with two different library names.
+%
+% \end{description}
+#
+# Codegenerator
+#
+# 06049 is the last used one
+#
+% \section{Code generator messages}
+% This section lists all messages that can be displayed if the code
+% generator encounters an error condition.
+% \begin{description}
+cg_e_parasize_too_big=06009_E_Tamanho da lista de parƒmetros excede 65535 bytes
+% The I386 processor limits the parameter list to 65535 bytes. (The \var{RET}
+% instruction causes this.)
+cg_e_file_must_call_by_reference=06012_E_Tipos Arquivos devem ser parƒmetros var.
+% You cannot specify files as value parameters, i.e., they must always be
+% declared \var{var} parameters.
+cg_e_cant_use_far_pointer_there=06013_E_O uso de ponteiro distante nÆo ‚ permitido l 
+% Free Pascal doesn't support far pointers, so you cannot take the address of
+% an expression which has a far reference as a result. The \var{mem} construct
+% has a far reference as a result, so the following code will produce this
+% error:
+% \begin{verbatim}
+% var p : pointer;
+% ...
+% p:=@mem[a000:000];
+% \end{verbatim}
+cg_e_dont_call_exported_direct=06015_E_Fun‡äes 'EXPORT' declaradas nÆo podem ser chamadas
+% No longer in use.
+cg_w_member_cd_call_from_method=06016_W_Poss¡vel chamada ilegal de construtor ou destruidor
+% The compiler detected that a constructor or destructor is called within a
+% a method. This will probably lead to problems, since constructors / destructors
+% require parameters on entry.
+cg_n_inefficient_code=06017_N_C¢dio ineficiente
+% Your statement seems dubious to the compiler.
+cg_w_unreachable_code=06018_W_C¢digo inacess¡vel
+% You specified a construct which will never be executed. Example:
+% \begin{verbatim}
+% while false do
+% begin
+% {.. code ...}
+% end;
+% \end{verbatim}
+cg_e_cant_call_abstract_method=06020_E_M‚todos abstratos nÆo podem ser chamados diretamente
+% You cannot call an abstract method directly. Instead, you must call an
+% overriding child method, because an abstract method isn't implemented.
+cg_d_register_weight=06027_DL_Registro $1 peso $2 $3
+% Debugging message. Shown when the compiler considers a variable for
+% keeping in the registers.
+cg_d_stackframe_omited=06029_DL_Quadro da pilha ‚ omitido
+% Some procedure/functions do not need a complete stack-frame, so it is omitted.
+% This message will be displayed when the {-vd} switch is used.
+cg_e_unable_inline_object_methods=06031_E_Objeto ou m‚todos classe nÆo podem ser 'em linha'.
+% You cannot have inlined object methods.
+cg_e_unable_inline_procvar=06032_E_Chamadas 'Procvar' nÆo podem ser 'em linha'.
+% A procedure with a procedural variable call cannot be inlined.
+cg_e_no_code_for_inline_stored=06033_E_Nenhum c¢digo para procedimento 'em linha' armazenado
+% The compiler couldn't store code for the inline procedure.
+cg_e_can_access_element_zero=06035_E_Elemento zero de uma 'ansi/wide-' ou stringlonga pode ser acessado, usar '(set)length'
+% You should use \var{setlength} to set the length of an ansi/wide/longstring
+% and \var{length} to get the length of such string type.
+cg_e_cannot_call_cons_dest_inside_with=06037_E_Construtores ou destruidores nÆo podem ser chamados de dentro de uma cl usula 'with'
+% Inside a \var{with} clause you cannot call a constructor or destructor for the
+% object you have in the \var{with} clause.
+cg_e_cannot_call_message_direct=06038_E_Imposs¡vel chamar m‚todos manipuladores de mensagem diretamente
+% A message method handler method cannot be called directly if it contains an
+% explicit \var{Self} argument.
+cg_e_goto_inout_of_exception_block=06039_E_Salto interno ou externo a um bloco de exce‡Æo
+% It is not allowed to jump in or outside of an exception block like \var{try..finally..end;}.
+% For example, the following code will produce this error:
+
+% \begin{verbatim}
+% label 1;
+%
+% ...
+%
+% try
+% if not(final) then
+% goto 1; // this line will cause an error
+% finally
+% ...
+% end;
+% 1:
+% ...
+% \end{verbatim}
+cg_e_control_flow_outside_finally=06040_E_Instru‡äes de controle de fluxo nÆo sÆo permitidos em um bloco 'finally'
+% It isn't allowed to use the control flow statements \var{break},
+% \var{continue} and \var{exit}
+% inside a finally statement. The following example shows the problem:
+% \begin{verbatim}
+% ...
+% try
+% p;
+% finally
+% ...
+% exit; // This exit ISN'T allowed
+% end;
+% ...
+%
+% \end{verbatim}
+% If the procedure \var{p} raises an exception the finally block is
+% executed. If the execution reaches the exit, it's unclear what to do:
+% exit the procedure or search for another exception handler.
+cg_w_parasize_too_big=06041_W_Tamanho parƒmetros excede limite para certas CPU's
+% This indicates that you are declaring more than 64K of parameters, which
+% might not be supported on other processor targets.
+cg_w_localsize_too_big=06042_W_Tamanho vari vel local excede limite para certas CPU's
+% This indicates that you are declaring more than 32K of local variables, which
+% might not be supported on other processor targets.
+cg_e_localsize_too_big=06043_E_Tamanho vari veis locais excedem limites suportados
+% This indicates that you are declaring more than 32K of local variables, which
+% is not supported by this processor.
+cg_e_break_not_allowed=06044_E_BREAK nÆo permitido
+% You're trying to use \var{break} outside a loop construction.
+cg_e_continue_not_allowed=06045_E_CONTINUE nÆo permitido
+% You're trying to use \var{continue} outside a loop construction.
+cg_f_unknown_compilerproc=06046_F_'Compilerproc' desconhecido "$1". Verifique se vocˆ usa a biblioteca de tempo de execu‡Æo correta
+% The compiler expects that the runtime library contains certain subroutines. If you see this error
+% and you didn't change the runtime library code, it's very likely that the runtime library
+% you're using doesn't match the compiler in use. If you changed the runtime library this error means
+% that you removed a subroutine which the compiler needs for internal use.
+cg_f_unknown_system_type=06047_F_Imposs¡vel encontrar tipo sistema "$1". Verifique se vocˆ usa a biblioteca de tempo de execu‡Æo correta
+% The compiler expects that the runtime library contains certain type definitions. If you see this error
+% and you didn't change the runtime library code, it's very likely that the runtime library
+% you're using doesn't match the compiler in use. If you changed the runtime library this error means
+% that you removed a type which the compiler needs for internal use.
+cg_h_inherited_ignored=06048_H_Chamada herdada para m‚todo abstrato ignorada
+% This message appears only in Delphi mode when you call an abstract method
+% of a parent class via \var{inherited;}. The call is then ignored.
+cg_e_goto_label_not_found=06049_E_R¢tulo 'Goto' "$1" nÆo definido ou eliminado pela otimiza‡Æo
+% The label used in the goto definition is not defined or optimized away by the
+% unreachable code elemination.
+cg_f_unknown_type_in_unit=06050_F_Imposs¡vel encontrar o tipo "$1" na unidade "$2". Verifique se vocˆ usa a biblioteca de tempo de execu‡Æo correta.
+% The compiler expects that the runtime library contains certain type definitions. If you see this error
+% and you didn't change the runtime library code, it's very likely that the runtime library
+% you're using doesn't match the compiler in use. If you changed the runtime library this error means
+% that you removed a type which the compiler needs for internal use.
+cg_e_interprocedural_goto_only_to_outer_scope_allowed=06051_E_Gotos interprocedimentos sÆo permitidos apenas para subrotinas externas
+% Gotos between subroutines are only allowed if the goto jumps from an inner to an outer subroutine or
+% from a subroutine to the main program
+cg_e_labels_cannot_defined_outside_declaration_scope=06052_E_R¢tulo deve ser definido no mesmo escopo em que ‚ declarado
+% In ISO mode, labels must be defined in the same scope as they are declared.
+cg_e_goto_across_procedures_with_exceptions_not_allowed=06053_E_Deixar procedimentos contendo quadros de exce‡äes expl¡citas ou impl¡citas usando 'goto' nÆo ‚ permitido
+% Non-local gotos might not be used to leave procedures using exceptions either implicitly or explicitly. Procedures
+% which use automated types like ansistrings or class constructurs are affected by this too.
+cg_e_mod_only_defined_for_pos_quotient=06054_E_No modo ISO, o operador 'mod' ‚ definido apenas para quociente positivo
+% In ISO pascal, only positive values are allowed for the quotient: \var{n mod m} is only valid if \var{m>0}.
+% \end{description}
+# EndOfTeX
+
+#
+# Assembler reader
+#
+# 07110 is the last used one
+#
+asmr_d_start_reading=07000_DL_Iniciando $1 an lise estilo assembler
+% This informs you that an assembler block is being parsed
+asmr_d_finish_reading=07001_DL_Finalizada $1 an lise estilo assembler
+% This informs you that an assembler block has finished.
+asmr_e_none_label_contain_at=07002_E_PadrÆo nÆo-r¢tulo contˆm @
+% A identifier which isn't a label can't contain a @.
+asmr_e_building_record_offset=07004_E_Erro construindo deslocamento registro
+% There has an error occured while building the offset of a record/object
+% structure, this can happend when there is no field specified at all or
+% an unknown field identifier is used.
+asmr_e_offset_without_identifier=07005_E_'OFFSET' usado sem identificador
+% You can only use OFFSET with an identifier. Other syntaxes aren't
+% supported
+asmr_e_type_without_identifier=07006_E_'TYPE' usado sem identificador
+% You can only use TYPE with an identifier. Other syntaxes aren't
+% supported
+asmr_e_no_local_or_para_allowed=07007_E_Imposs¡vel usar vari vel local ou parƒmetro aqui
+% You can't use a local variable or parameter here, mostly because the
+% addressing of locals and parameters is done using the frame pointer register so the
+% address can't be obtained directly.
+asmr_e_need_offset=07008_E_Necess rio usar 'OFFSET' aqui
+% You need to use OFFSET <id> here to get the address of the identifier.
+asmr_e_need_dollar=07009_E_Necess rio usar $ aqui
+% You need to use $<id> here to get the address of the identifier.
+asmr_e_cant_have_multiple_relocatable_symbols=07010_E_Imposs¡vel usar m£ltiplos s¡mbolos reloc veis
+% You can't have more than one relocatable symbol (variable/typed constant)
+% in one argument.
+asmr_e_only_add_relocatable_symbol=07011_E_S¡mbolo reloc vel pode apenas ser adicionado
+% Relocatable symbols (variable/typed constant) can't be used with other
+% operators. Only addition is allowed.
+asmr_e_invalid_constant_expression=07012_E_ExpressÆo constante inv lida
+% There is an error in the constant expression.
+asmr_e_relocatable_symbol_not_allowed=07013_E_S¡mbolo reloc vel nÆo ‚ permitido
+% You can't use a relocatable symbol (variable/typed constant) here.
+asmr_e_invalid_reference_syntax=07014_E_Sintaxe referˆncia inv lida
+% There is an error in the reference.
+asmr_e_local_para_unreachable=07015_E_Vocˆ nÆo pode atingir $1 a partir desse c¢digo
+% You cannot read directly the value of a local variable or parameter
+% of a higher level procedure in assembler code (except for
+% local assembler code without parameter nor locals).
+asmr_e_local_label_not_allowed_as_ref=07016_E_S¡mbolos locais/r¢tulos nÆo sÆo permitidos como referˆncias
+% You can't use local symbols/labels as references
+asmr_e_wrong_base_index=07017_E_Uso registro base e ¡ndice inv lido
+% There is an error with the base and index register, they are
+% probably incorrect
+asmr_w_possible_object_field_bug=07018_W_Poss¡vel erro na manipula‡Æo de campo de objeto
+% Fields of objects or classes can be reached directly in normal or objfpc
+% modes but TP and Delphi modes treat the field name as a simple offset.
+asmr_e_wrong_scale_factor=07019_E_Fator incorreto de escala especificado
+% The scale factor given is wrong, only 1,2,4 and 8 are allowed
+asmr_e_multiple_index=07020_E_Uso m£ltiplo registro ¡ndice
+% You are trying to use more than one index register
+asmr_e_invalid_operand_type=07021_E_Tipo operando inv lido
+% The operand type doesn't match with the opcode used
+asmr_e_invalid_string_as_opcode_operand=07022_E_'String' inv lido como operando 'opcode': $1
+% The string specified as operand is not correct with this opcode
+asmr_w_CODE_and_DATA_not_supported=07023_W_@CODE e @DATA nÆo suportados
+% @CODE and @DATA are unsupported and are ignored.
+asmr_e_null_label_ref_not_allowed=07024_E_Referˆncias nulas de r¢tulos nÆo sÆo permitidas
+asmr_e_expr_zero_divide=07025_E_DivisÆo por zero em avaliador asm
+% There is a division by zero in a constant expression
+asmr_e_expr_illegal=07026_E_Expressao ilegal
+% There is an illegal expression in a constant expression
+asmr_e_escape_seq_ignored=07027_E_Sequˆncia de escape ignorada: $1
+% There is a C-styled string, but the escape sequence in the string
+% is unknown, and is therefore ignored
+asmr_e_invalid_symbol_ref=07028_E_Referˆncia s¡mbolo inv lida
+asmr_w_fwait_emu_prob=07029_W_Fwait pode causar problemas de emula‡Æo com emu387
+asmr_w_fadd_to_faddp=07030_W_$1 sem operando traduzido em $1P
+asmr_w_enter_not_supported_by_linux=07031_W_Instru‡Æo 'ENTER' nÆo suportada pelo kernel Linux
+% ENTER instruction can generate a stack page fault that is not
+% caught correctly by the i386 Linux page handler.
+asmr_w_calling_overload_func=07032_W_Chamando uma fun‡Æo sobrecarregada em assembler
+% There is a call to an overloaded method in the assembler block,
+% this might be the sign there is a problem
+asmr_e_unsupported_symbol_type=07033_E_Tipo s¡mbolo nÆo suportado para operando
+asmr_e_constant_out_of_bounds=07034_E_Valor constante fora de faixa
+asmr_e_error_converting_decimal=07035_E_Erro convertendo decimal $1
+% A constant decimal value does not have the correct syntax
+asmr_e_error_converting_octal=07036_E_Erro convertendo octal $1
+% A constant octal value does not have the correct syntax
+asmr_e_error_converting_binary=07037_E_Erro convertendo bin rio $1
+% A constant binary value does not have the correct syntax
+asmr_e_error_converting_hexadecimal=07038_E_Erro convertendo hexadecimal $1
+% A constant hexadecimal value does not have the correct syntax
+asmr_h_direct_global_to_mangled=07039_H_$1 traduzido para $2
+asmr_w_direct_global_is_overloaded_func=07040_W_$1 est  associado a uma fun‡Æo sobrecarregada
+asmr_e_cannot_use_SELF_outside_a_method=07041_E_Imposs¡vel usar 'SELF' fora de um m‚todo
+% There is a reference to the \var{self} symbol while it is not
+% allowed. \var{self} can only be referenced inside methods
+asmr_e_cannot_use_OLDEBP_outside_nested_procedure=07042_E_Imposs¡vel usar 'OLDEBP' fora de um procedimento aninhado
+% There is a reference to the \var{oldebp} symbol while it is not
+% allowed. \var{oldebp} can only be referenced inside nested routines
+asmr_e_void_function=07043_W_Procedimentos nÆo podem retornar qualquer valor em c¢digo asm
+% Trying to return a value while in a procedure. A procedure
+% does not have any return value
+asmr_e_SEG_not_supported=07044_E_SEG nÆo suportado
+asmr_e_size_suffix_and_dest_dont_match=07045_E_Tamanho sufixo e tamanho destino ou fonte nÆo coincidem
+% The register size and the opcode size suffix don't match. This is
+% probably an error in the assembler statement
+asmr_w_size_suffix_and_dest_dont_match=07046_W_Tamanho sufixo e tamanho destino ou fonte nÆo coincidem
+% The register size and the opcode size suffix don't match. This is
+% probably an error in the assembler statement
+asmr_e_syntax_error=07047_E_Erro de sintaxe assembler
+% There is an assembler syntax error
+asmr_e_invalid_opcode_and_operand=07048_E_Combina‡Æo inv lida de 'opcode' e operandos
+% The opcode cannot be used with this type of operand
+asmr_e_syn_operand=07049_E_Erro de sintaxe assembler em operando
+asmr_e_syn_constant=07050_E_Erro de sintaxe assembler em constante
+asmr_e_invalid_string_expression=07051_E_ExpressÆo 'String' inv lida
+asmr_w_const32bit_for_address=07052_W_Constante com s¡mbolo $1 para endere‡o que nÆo est  em um ponteiro
+% A constant expression represents an address which does not fit
+% into a pointer. The address is probably incorrect
+asmr_e_unknown_opcode=07053_E_'Opcode' desconhecido $1
+% This opcode is not known
+asmr_e_invalid_or_missing_opcode=07054_E_'Opcode' inv lido ou faltando
+asmr_e_invalid_prefix_and_opcode=07055_E_Combina‡Æo inv lida de prefixo e 'opcode': $1
+asmr_e_invalid_override_and_opcode=07056_E_Combina‡Æo inv lida de 'override' e 'opcode': $1
+asmr_e_too_many_operands=07057_E_Muitos operandos na linha
+% There are too many operands for this opcode. Check your
+% assembler syntax
+asmr_w_near_ignored=07058_W_NEAR ignorado
+asmr_w_far_ignored=07059_W_FAR ignorado
+asmr_e_dup_local_sym=07060_E_S¡mbolo local duplicado $1
+asmr_e_unknown_local_sym=07061_E_S¡mbolo local indefinido $1
+asmr_e_unknown_label_identifier=07062_E_Identificador r¢tulo desconhecido $1
+asmr_e_invalid_register=07063_E_Nome registro inv lido
+% There is an unknown register name used as operand.
+asmr_e_invalid_fpu_register=07064_E_Nome registro ponto flutuante inv lido
+% There is an unknown register name used as operand.
+asmr_w_modulo_not_supported=07066_W_M¢dulo nÆo suportado
+asmr_e_invalid_float_const=07067_E_Constante ponto flutuante inv lida $1
+% The floating point constant declared in an assembler block is
+% invalid.
+asmr_e_invalid_float_expr=07068_E_ExpressÆo ponto flutuante inv lida
+% The floating point expression declared in an assembler block is
+% invalid.
+asmr_e_wrong_sym_type=07069_E_Tipo s¡mbolo incorreto
+asmr_e_cannot_index_relative_var=07070_E_Imposs¡vel indexar uma var. local ou parƒmetro com um registro
+% Trying to index using a base register a symbol which is already relative
+% to a register. This is not possible, and will probably lead to crashes.
+asmr_e_invalid_seg_override=07071_E_ExpressÆo sobreposi‡Æo segmento inv lida
+asmr_w_id_supposed_external=07072_W_Identificador $1 supostamente externo
+% There is a reference to an undefined symbol. This will not result
+% in an error, since the symbol might be external, but may cause
+% problems at link time if the symbol is not defined anywhere.
+asmr_e_string_not_allowed_as_const=07073_E_'Strings' nÆo permitidas como constantes
+% Character strings are not allowed as constants.
+asmr_e_no_var_type_specified=07074_E_Nenhum tipo de vari vel especificado
+% The syntax expects a type idenfitifer after the dot, but
+% none was found.
+asmr_w_assembler_code_not_returned_to_text=07075_E_C¢digo assembler nÆo retornou a se‡Æo texto
+% There was a directive in the assembler block to change sections,
+% but there is a missing return to the text section at the end
+% of the assembler block. This might cause errors during link time.
+asmr_e_not_directive_or_local_symbol=07076_E_NÆo ‚ uma diretiva ou s¡mbolo local $1
+% This symbol is unknown.
+asmr_w_using_defined_as_local=07077_E_Usando um nome definido como um r¢tulo local
+asmr_e_dollar_without_identifier=07078_E_Caracter D¢lar ‚ usado sem um identificador
+% A constant expression has an identifier which does not start with
+% the $ symbol.
+asmr_w_32bit_const_for_address=07079_W_Constante 32bit criada para endere‡o
+% A constant was used as an address. This is probably an error,
+% since using absolute addresses will probably not work.
+asmr_n_align_is_target_specific=07080_N_'.align' ‚ espec¡fico de alvo, use '.balign' ou '.p2align'
+% Using the .align directive is platform specific, and its meaning will vary
+% from one platform to another.
+asmr_e_cannot_access_field_directly_for_parameters=07081_E_Imposs¡vel acessar campos diretamente para parƒmetros
+% You should load the parameter first into a register and then access the
+% fields using that register.
+asmr_e_cannot_access_object_field_directly=07082_E_Imposs¡vel acessar campos de objetos/classes diretamente
+% You should load the self pointer first into a register and then access the
+% fields using the register as base. By default the self pointer is available
+% in the esi register on i386.
+asmr_e_unable_to_determine_reference_size=07083_E_Tamanho nÆo especificado e incapaz de determinar o tamanho dos operandos
+% You should specify explicitly a size for the reference, because
+% the compiler is unable to determine what size (byte,word,dword,etc.) it
+% should use for the reference.
+asmr_e_cannot_use_RESULT_here=07084_E_Imposs¡vel usar 'RESULT' nesta fun‡Æo
+% Some functions which return complex types cannot use the \var{result}
+% keyword.
+asmr_w_adding_explicit_args_fXX=07086_W_"$1" sem operando traduzido em "$1 %st,%st(1)"
+asmr_w_adding_explicit_first_arg_fXX=07087_W_"$1 %st(n)" traduzido em "$1 %st,%st(n)"
+asmr_w_adding_explicit_second_arg_fXX=07088_W_"$1 %st(n)" translated em "$1 %st(n),%st"
+asmr_e_invalid_char_smaller=07089_E_Caracter < nÆo permitido aqui
+% The shift operator requires the << characters. Only one
+% of those characters was found.
+asmr_e_invalid_char_greater=07090_E_Caracter > nÆo permitido aqui
+% The shift operator requires the >> characters. Only one
+% of those characters was found.
+asmr_w_align_not_supported=07093_W_ALIGN nÆo suportado
+asmr_e_no_inc_and_dec_together=07094_E_'Inc' e 'Dec' nÆo podem estar juntos
+% Trying to use an increment and a decrement within the same
+% opcode on the 680x0. This is impossible.
+asmr_e_invalid_reg_list_in_movem=07095_E_'Reglist' para 'movem' inv lido
+% Trying to use the \var{movem} opcode with invalid registers
+% to save or restore.
+asmr_e_invalid_reg_list_for_opcode=07096_E_'Reglist' inv lido para 'opcode'
+asmr_e_higher_cpu_mode_required=07097_E_Modo CPU maior requerido ($1)
+% Trying to use an instruction which is not supported in the current
+% cpu mode. Use a higher cpu generation to be able to use this
+% opcode in your assembler block
+asmr_w_unable_to_determine_reference_size_using_dword=07098_W_Nenhum tamanho especificado e incapaz de determinar o tamanho dos operandos, usando DWORD como padrÆo
+% You should specify explicitly a size for the reference, because
+% the compiler is unable to determine what size (byte,word,dword,etc.) it
+% should use for the reference. This warning is only used in Delphi mode where
+% it falls back to use DWORD as default.
+asmr_e_illegal_shifterop_syntax=07099_E_Erro de sintaxe tentando analisar um operando deslocamento
+% ARM only; ARM assembler supports a so called shifter operand. The used syntax isn't
+% a valid shifter operand. Example for an operation with shifter operand:
+% \begin{verbatim}
+% asm
+% orr r2,r2,r2,lsl #8
+% end;
+% \end{verbatim}
+asmr_e_packed_element=07100_E_Endere‡o de componente compactado nÆo est  no limite byte
+% Packed components (record fields and array elements) may start at an arbitrary
+% bit inside a byte. On CPU which do not support bit-addressable memory (which
+% includes all currently supported CPUs by FPC) you will therefore get an error
+% message when trying to index arrays with elements whose size is not a multiple
+% of 8 bits. The same goes for accessing record fields with such an address.
+% multiple of 8 bits.
+asmr_w_unable_to_determine_reference_size_using_byte=07101_W_Nenhum tamanho especificado e incapaz de determinar o tamanho dos operandos, usando BYTE como padrÆo
+% You should specify explicitly a size for the reference, because
+% the compiler is unable to determine what size (byte,word,dword,etc.) it
+% should use for the reference. This warning is only used in Delphi mode where
+% it falls back to use BYTE as default.
+asmr_w_no_direct_ebp_for_parameter=07102_W_Uso de '+offset(%ebp)' para parƒmetros inv lido aqui
+% Using direct 8(%ebp) reference for function/procedure parameters is invalid
+% if parameters are in registers.
+asmr_w_direct_ebp_for_parameter_regcall=07103_W_Uso de '+offset(%ebp)' nÆo ‚ compat¡vel com a conven‡Æo 'regcall'
+% Using direct 8(%ebp) reference for function/procedure parameters is invalid
+% if parameters are in registers.
+asmr_w_direct_ebp_neg_offset=07104_W_Uso de '-offset(%ebp)' nÆo ‚ recomendada para acesso a vari vel local
+% Using -8(%ebp) to access a local variable is not recommended
+asmr_w_direct_esp_neg_offset=07105_W_Uso de '-offset(%esp)', acesso pode causar travamento ou valor pode ser perdido
+% Using -8(%esp) to access a local stack is not recommended, as
+% this stack portion can be overwritten by any function calls or interrupts.
+asmr_e_no_vmtoffset_possible=07106_E_'VMTOffset' deve ser usado em combina‡Æo com um m‚todo virtual, e "$1" nÆo ‚ virtual
+% Only virtual methods have VMT offsets
+asmr_e_need_pic_ref=07107_E_Gerando PIC, mas referˆncia nÆo ‚ segura (PIC-safe)
+% The compiler has been configured to generate position-independent code
+% (PIC), but there are position-dependent references in the current
+% handwritten assembler instruction.
+asmr_e_mixing_regtypes=07108_E_Todos os registros em um conjunto de registros devem ser do mesmo tipo e largura
+% Instructions on the ARM architecture that take a register set as argument require that all registers
+% in this set are of the same kind (e.g., integer, vfp) and width (e.g., single precision, double precision).
+asmr_e_empty_regset=07109_E_Um conjunto de registros nÆo pode estar vazio
+% Instructions on the ARM architecture that take a register set as argument require that such a set
+% contains at least one register.
+
+asmr_w_useless_got_for_local=07110_W_@GOTPCREL ‚ in£til e potencialmente perigoso para s¡mbolos locais
+% The use of @GOTPCREL supposes an extra indirection that is
+% not present if the symbol is local, which might lead to wrong asembler code
+asmr_w_general_segment_with_constant=07111_W_Constante com registro de segmento de prop¢sito geral
+% General purpose register should not have constant offsets
+% as OS memory allocation might not be compatible with that.
+asmr_e_bad_seh_directive_offset=07112_E_Valor de deslocamento inv lido para $1
+% Win64 SEH directives have certain restrictions on possible offset values, e.g. they should
+% be positive and have 3 or 4 low bits clear.
+asmr_e_bad_seh_directive_register=07113_E_Registro inv lido para $1
+% Win64 SEH directives accept only 64-bit integer registers or XMM registers.
+asmr_e_seh_in_pure_asm_only=07114_E_Diretivas SEH sÆo permitidas apenas em procedimentos assembler puros
+% Win64 SEH directives are allowed only in pure assembler procedures, not in assembler
+% blocks of regular procedures.
+asmr_e_unsupported_directive=07115_E_Diretiva "$1" nÆo ‚ suportada pelo alvo atual
+
+
+#
+# Assembler/binary writers
+#
+# 08022 is the last used one
+#
+asmw_f_too_many_asm_files=08000_F_Muitos arquivos assembler
+% With smartlinking enabled, there are too many assembler
+% files generated. Disable smartlinking.
+asmw_f_assembler_output_not_supported=08001_F_Sa¡da assembler selecionada nÆo suportada
+asmw_f_comp_not_supported=08002_F_'Comp' nÆo suportado
+asmw_f_direct_not_supported=08003_F_Modo direto nÆo suportado por gravadores bin rios
+% Direct assembler mode is not supported for binary writers.
+asmw_e_alloc_data_only_in_bss=08004_E_Alocamento de dados somente permitida na se‡Æo 'bss'
+asmw_f_no_binary_writer_selected=08005_F_Nenhum gravador bin rio selecionado
+asmw_e_opcode_not_in_table=08006_E_Asm: Opcode $1 nÆo est  na tabela
+asmw_e_invalid_opcode_and_operands=08007_E_Asm: $1 combina‡Æo inv lida de 'opcode' e operandos
+asmw_e_16bit_not_supported=08008_E_Asm: referˆncias 16 Bits nÆo suportadas
+asmw_e_invalid_effective_address=08009_E_Asm: Endere‡o efetivo inv lido
+asmw_e_immediate_or_reference_expected=08010_E_Asm: Esperados 'Immediate' ou referˆncia
+asmw_e_value_exceeds_bounds=08011_E_Asm: $1 valor excede limites $2
+asmw_e_short_jmp_out_of_range=08012_E_Asm: Salto curto fora de faixa $1
+asmw_e_undefined_label=08013_E_Asm: R¢tulo indefinido $1
+asmw_e_comp_not_supported=08014_E_Asm: Tipo 'Comp' nÆo suportado por este alvo
+asmw_e_extended_not_supported=08015_E_Asm: Tipo extendido nÆo suportado por este alvo
+asmw_e_duplicate_label=08016_E_Asm: R¢tulo duplicado $1
+asmw_e_redefined_label=08017_E_Asm: R¢tulo redefinido $1
+asmw_e_first_defined_label=08018_E_Asm: Primeiramente definido aqui
+asmw_e_invalid_register=08019_E_Asm: Registro inv lido $1
+asmw_e_16bit_32bit_not_supported=08020_E_Asm: Referˆncias 16 ou 32 Bits nÆo suportadas
+asmw_e_64bit_not_supported=08021_E_Asm: Operandos 64 Bits nÆo suportados
+asmw_e_bad_reg_with_rex=08022_E_Asm: AH,BH,CH ou DH nÆo podem ser usados em uma instru‡Æo que requer o prefixo REX
+% x86_64 only: instruction encoding of this platform does not allow using
+% 8086 high byte registers (AH,BH,CH or DH) together with REX prefix in a single instruction.
+% The REX prefix is required whenever the instruction operand size is 64 bits, or
+% when it uses one of extended x86_64 registers (R8-R15 or XMM8-XMM15).
+asmw_e_missing_endprologue=08023_E_Diretiva .seh_endprologue faltando
+% x86_64-win64 only: Normally, SEH directives are handled internally by compiler.
+% However, in pure assembler procedures .seh_endprologue directive is required
+% if other SEH directives are present.
+asmw_e_prologue_too_large=08024_E_Pr¢logo da fun‡Æo excede 255 bytes
+% x86_64-win64: .seh_prologue directive must be placed within 255 bytes from function start.
+asmw_e_handlerdata_no_handler=08025_E_Diretiva .seh_handlerdata sem .seh_handler precedente
+% x86_64-win64: If .seh_handlerdata directive is used, then a .seh_handler directive must be
+% present earlier in the same function.
+
+#
+# Executing linker/assembler
+#
+# 09033 is the last used one
+#
+# BeginOfTeX
+%
+% \section{Errors of assembling/linking stage}
+% This section lists errors that occur when the compiler is processing the
+% command line or handling the configuration files.
+% \begin{description}
+exec_w_source_os_redefined=09000_W_Sistema operacional fonte redefinido
+% The source operating system is redefined.
+exec_i_assembling_pipe=09001_I_Montando (pipe) $1
+% Assembling using a pipe to an external assembler.
+exec_d_cant_create_asmfile=09002_E_Imposs¡vel criar arquivo assembler: $1
+% The mentioned file can't be created. Check if you have
+% access permissions to create this file.
+exec_e_cant_create_objectfile=09003_E_Imposs¡vel criar arquivo objeto: $1
+% The mentioned file can't be created. Check if you have
+% got access permissions to create this file.
+exec_e_cant_create_archivefile=09004_E_Imposs¡vel criar arquivo: $1
+% The mentioned file can't be created. Check if you have
+% access permissions to create this file.
+exec_e_assembler_not_found=09005_E_Montador $1 nÆo encontrado, mudando para montador externo
+% The assembler program was not found. The compiler will produce a script that
+% can be used to assemble and link the program.
+exec_t_using_assembler=09006_T_Usando montador: $1
+% An informational message saying which assembler is being used.
+exec_e_error_while_assembling=09007_E_Erro ao montar c¢digo sa¡da $1
+% There was an error while assembling the file using an external assembler.
+% Consult the documentation of the assembler tool to find out more information
+% on this error.
+exec_e_cant_call_assembler=09008_E_Imposs¡vel chamar montador, erro $1 mudando para montador externo
+% An error occurred when calling an external assembler. The compiler will produce a script that
+% can be used to assemble and link the program.
+exec_i_assembling=09009_I_Montando $1
+% An informational message stating which file is being assembled.
+exec_i_assembling_smart=09010_I_Montando com vincula‡Æo inteligente $1
+% An informational message stating which file is being assembled using smartlinking.
+exec_w_objfile_not_found=09011_W_Objeto $1 nÆo encontrado, Vincula‡Æo pode falhar !
+% One of the object files is missing, and linking will probably fail.
+% Check your paths.
+exec_w_libfile_not_found=09012_W_Biblioteca $1 nÆo encontrada, Vincula‡Æo pode falhar !
+% One of the library files is missing, and linking will probably fail.
+% Check your paths.
+exec_e_error_while_linking=09013_E_Erro durante vincula‡Æo
+% Generic error while linking.
+exec_e_cant_call_linker=09014_E_Imposs¡vel chamar vinculador, mudando para vincula‡Æo externa
+% An error occurred when calling an external linker. The compiler will produce a script that
+% can be used to assemble and link the program.
+exec_i_linking=09015_I_Vinculando $1
+% An informational message, showing which program or library is being linked.
+exec_e_util_not_found=09016_E_Utilit rio $1 nÆo encontrado, mudando para vincula‡Æo externa
+% An external tool was not found. The compiler will produce a script that
+% can be used to assemble and link or postprocess the program.
+exec_t_using_util=09017_T_Usando utilit rio $1
+% An informational message, showing which external program (usually a postprocessor) is being used.
+exec_e_exe_not_supported=09018_E_Cria‡Æo de Execut veis nÆo suportada
+% Creating executable programs is not supported for this platform, because it was
+% not yet implemented in the compiler.
+exec_e_dll_not_supported=09019_E_Cria‡Æo de bibliotecas Dinƒmicas/Compartilhadas nÆo suportada
+% Creating dynamically loadable libraries is not supported for this platform, because it was
+% not yet implemented in the compiler.
+exec_i_closing_script=09020_I_Fechando roteiro $1
+% Informational message showing when writing of the external assembling and linking script is finished.
+exec_e_res_not_found=09021_E_Compilador recursos "$1" nÆo encontrado, mudando para modo externo
+% An external resource compiler was not found. The compiler will produce a script that
+% can be used to assemble, compile resources and link or postprocess the program.
+exec_i_compilingresource=09022_I_Compilando recursos $1
+% An informational message, showing which resource is being compiled.
+exec_t_unit_not_static_linkable_switch_to_smart=09023_T_Unidade $1 nÆo pode ser vinculada estaticamente, mudando para vincula‡Æo inteligente
+% Static linking was requested, but a unit which is not statically linkable was used.
+exec_t_unit_not_smart_linkable_switch_to_static=09024_T_Unidade $1 nÆo pode ser vinculada inteligentemente, mudando para vincula‡Æo est tica
+% Smart linking was requested, but a unit which is not smart-linkable was used.
+exec_t_unit_not_shared_linkable_switch_to_static=09025_T_Unidade $1 nÆo pode ser vinculada compartilhadamente, mudando para vincula‡Æo est tica
+% Shared linking was requested, but a unit which is not shared-linkable was used.
+exec_e_unit_not_smart_or_static_linkable=09026_E_Unidade $1 nÆo pode ser vinculada inteligentemente ou estaticamente
+% Smart or static linking was requested, but a unit which cannot be used for either was used.
+exec_e_unit_not_shared_or_static_linkable=09027_E_Unidade $1 nÆo pode ser vinculada compartilhadamente ou estaticamente
+% Shared or static linking was requested, but a unit which cannot be used for either was used.
+exec_d_resbin_params=09028_D_Chamando compilador recursos "$1" com "$2" como linha comando
+% An informational message showing which command line is used for the resource compiler.
+exec_e_error_while_compiling_resources=09029_E_Erro ao compilar recursos
+% The resource compiler or converter returned an error.
+exec_e_cant_call_resource_compiler=09030_E_Imposs¡vel chamar o compilador recursos "$1", mudando para modo externo
+% An error occurred when calling a resource compiler. The compiler will produce
+% a script that can be used to assemble, compile resources and link or
+% postprocess the program.
+exec_e_cant_open_resource_file=09031_E_Imposs¡vel abrir arquivo recursos "$1"
+% An error occurred resource file cannot be opened.
+exec_e_cant_write_resource_file=09032_E_Imposs¡vel gravar arquivo recursos "$1"
+% An error occurred resource file cannot be written.
+exec_n_backquote_cat_file_not_found=09033_N_Arquivo "$1" nÆo encontrado para comando 'cat' entre aspas
+% The compiler did not find the file that should be expanded into linker parameters
+%\end{description}
+# EndOfTeX
+
+#
+# Executable information
+#
+# 09134 is the last used one
+#
+# BeginOfTeX
+% \section{Executable information messages.}
+% This section lists all messages that the compiler emits when an executable program is produced,
+% and only when the internal linker is used.
+% \begin{description}
+execinfo_f_cant_process_executable=09128_F_Imposs¡vel p¢s-processar execut vel $1
+% Fatal error when the compiler is unable to post-process an executable.
+execinfo_f_cant_open_executable=09129_F_Imposs¡vel abrir execut vel $1
+% Fatal error when the compiler cannot open the file for the executable.
+execinfo_x_codesize=09130_X_Tamanho do C¢digo: $1 bytes
+% Informational message showing the size of the produced code section.
+execinfo_x_initdatasize=09131_X_Tamanho dos dados inicializados: $1 bytes
+% Informational message showing the size of the initialized data section.
+execinfo_x_uninitdatasize=09132_X_Tamanho dos dados nÆo inicializados: $1 bytes
+% Informational message showing the size of the uninitialized data section.
+execinfo_x_stackreserve=09133_X_Espa‡o da Pilha reservado: $1 bytes
+% Informational message showing the stack size that the compiler reserved for the executable.
+execinfo_x_stackcommit=09134_X_Espa‡o da Pilha confirmado: $1 bytes
+% Informational message showing the stack size that the compiler committed for the executable.
+%\end{description}
+# EndOfTeX
+
+#
+# Internal linker messages
+#
+# 09200 is the last used one
+#
+# BeginOfTeX
+% \section{Linker messages}
+% This section lists messages produced by internal linker.
+% \begin{description}
+link_f_executable_too_big=09200_F_Tamanho imagem execut vel ‚ muito grande para alvo $1.
+% Fatal error when resulting executable is too big.
+link_w_32bit_absolute_reloc=09201_W_Arquivo objeto "$1" contˆm reloca‡Æo absoluta de 32-bits para s¡mbolo "$2".
+% Warning when 64-bit object file contains 32-bit absolute relocations.
+% In such case an executable image can be loaded into lower 4Gb of
+% address space only.
+%\end{description}
+# EndOfTeX
+
+#
+# Unit loading
+#
+# 10062 is the last used one
+#
+# BeginOfTeX
+% \section{Unit loading messages.}
+% This section lists all messages that can occur when the compiler is
+% loading a unit from disk into memory. Many of these messages are
+% informational messages.
+% \begin{description}
+unit_t_unitsearch=10000_T_Busca Unidade: $1
+% When you use the \var{-vt} option, the compiler tells you where it tries to find
+% unit files.
+unit_t_ppu_loading=10001_T_Carregando PPU $1
+% When the \var{-vt} switch is used, the compiler tells you
+% what units it loads.
+unit_u_ppu_name=10002_U_Nome PPU: $1
+% When you use the \var{-vu} flag, the unit name is shown.
+unit_u_ppu_flags=10003_U_PPU 'Flags': $1
+% When you use the \var{-vu} flag, the unit flags are shown.
+unit_u_ppu_crc=10004_U_PPU 'Crc': $1
+% When you use the \var{-vu} flag, the unit CRC check is shown.
+unit_u_ppu_time=10005_U_Hora PPU: $1
+% When you use the \var{-vu} flag, the time the unit was compiled is shown.
+unit_u_ppu_file_too_short=10006_U_Arquivo PPU muito pequeno
+% The ppufile is too short, not all declarations are present.
+unit_u_ppu_invalid_header=10007_U_Cabe‡alho PPU inv lido (sem PPU no come‡o)
+% A unit file contains as the first three bytes the ASCII codes of the characters \var{PPU}.
+unit_u_ppu_invalid_version=10008_U_VersÆo PPU inv lida $1
+% This unit file was compiled with a different version of the compiler, and
+% cannot be read.
+unit_u_ppu_invalid_processor=10009_U_PPU foi compilado para outro processador
+% This unit file was compiled for a different processor type, and
+% cannot be read.
+unit_u_ppu_invalid_target=10010_U_PPU foi compilado para outro alvo
+% This unit file was compiled for a different target, and
+% cannot be read.
+unit_u_ppu_source=10011_U_Fonte PPU: $1
+% When you use the \var{-vu} flag, the unit source file name is shown.
+unit_u_ppu_write=10012_U_Gravando $1
+% When you specify the \var{-vu} switch, the compiler will tell you where it
+% writes the unit file.
+unit_f_ppu_cannot_write=10013_F_Imposs¡vel gravar arquivo PPU
+% An error occurred when writing the unit file.
+unit_f_ppu_read_error=10014_F_Erro ao ler arquivo PPU
+% This means that the unit file was corrupted, and contains invalid
+% information. Recompilation will be necessary.
+unit_f_ppu_read_unexpected_end=10015_F_Fim de arquivo PPU inesperado
+% Unexpected end of file. This may mean that the PPU file is
+% corrupted.
+unit_f_ppu_invalid_entry=10016_F_Entrada inv lida arquivo PPU: $1
+% The unit the compiler is trying to read is corrupted, or generated with a
+% newer version of the compiler.
+unit_f_ppu_dbx_count_problem=10017_F_Problema contagem Dbx PPU
+% There is an inconsistency in the debugging information of the unit.
+unit_e_illegal_unit_name=10018_E_Nome unidade ilegal: $1
+% The name of the unit does not match the file name.
+unit_f_too_much_units=10019_F_Muitas unidades
+% \fpc has a limit of 1024 units in a program. You can change this behavior
+% by changing the \var{maxunits} constant in the \file{fmodule.pas} file of the
+% compiler, and recompiling the compiler.
+unit_f_circular_unit_reference=10020_F_Referˆncia circular em unidade entre $1 e $2
+% Two units are using each other in the interface part. This is only allowed
+% in the \var{implementation} part. At least one unit must contain the other one
+% in the \var{implementation} section.
+unit_f_cant_compile_unit=10021_F_Imposs¡vel compilar unidade $1, nenhum fonte dispon¡vel
+% A unit was found that needs to be recompiled, but no sources are
+% available.
+unit_f_cant_find_ppu=10022_F_Imposs¡vel localizar unidade $1 usada por $2
+% You tried to use a unit of which the PPU file isn't found by the
+% compiler. Check your configuration file for the unit paths.
+unit_w_unit_name_error=10023_W_Unidade $1 nÆo foi encontrada mas $2 existe
+% This error message is no longer used.
+unit_f_unit_name_error=10024_F_Unidade $1 foi procurada mas $2 encontrada
+% \dos truncation of 8 letters for unit PPU files
+% may lead to problems when unit name is longer than 8 letters.
+unit_w_switch_us_missed=10025_W_Compilar a unidade 'system' requer a chave -Us
+% When recompiling the system unit (it needs special treatment), the
+% \var{-Us} switch must be specified.
+unit_f_errors_in_unit=10026_F_Houveram $1 erros ao compilar m¢dulo, parando
+% When the compiler encounters a fatal error or too many errors in a module
+% then it stops with this message.
+unit_u_load_unit=10027_U_Carregar de $1 ($2) unidade $3
+% When you use the \var{-vu} flag, which unit is loaded from which unit is
+% shown.
+unit_u_recompile_crc_change=10028_U_Recompilando $1, 'checksum' alterado para $2
+% The unit is recompiled because the checksum of a unit it depends on has
+% changed.
+unit_u_recompile_source_found_alone=10029_U_Recompilando $1, apenas fonte encontrado
+% When you use the \var{-vu} flag, these messages tell you why the current
+% unit is recompiled.
+unit_u_recompile_staticlib_is_older=10030_U_Recompilando unidade, bib est tica ‚ mais antiga que o arquivo ppu
+% When you use the \var{-vu} flag, the compiler warns if the static library
+% of the unit is older than the unit file itself.
+unit_u_recompile_sharedlib_is_older=10031_U_Recompilando unidade, bib compartilhada ‚ mais antiga que o arquivo ppu
+% When you use the \var{-vu} flag, the compiler warns if the shared library
+% of the unit is older than the unit file itself.
+unit_u_recompile_obj_and_asm_older=10032_U_Recompilando unidade, 'obj' e 'asm' sÆo mais antigos que o arquivo ppu
+% When you use the \var{-vu} flag, the compiler warns if the assembler or
+% object file of the unit is older than the unit file itself.
+unit_u_recompile_obj_older_than_asm=10033_U_Recompilando unidade, 'obj' ‚ mais antigo que 'asm'
+% When you use the \var{-vu} flag, the compiler warns if the assembler
+% file of the unit is older than the object file of the unit.
+unit_u_parsing_interface=10034_U_Analisando 'interface' de $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% parsing the interface part of the unit.
+unit_u_parsing_implementation=10035_U_Analisando 'implementation' de $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% parsing the implementation part of the unit.
+unit_u_second_load_unit=10036_U_Segundo carregamento para a unidade $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% recompiling a unit for the second time. This can happen with
+% interdependent units.
+unit_u_check_time=10037_U_PPU Verifique arquivo $1 hora $2
+% When you use the \var{-vu} flag, the compiler shows the filename and
+% date and time of the file on which a recompile depends.
+### The following two error msgs is currently disabled.
+#unit_h_cond_not_set_in_last_compile=10038_H_Conditional $1 was not set at startup in last compilation of $2
+#% when recompilation of an unit is required the compiler will check that
+#% the same conditionals are set for the recompiliation. The compiler has
+#% found a conditional that currently is defined, but was not used the last
+#% time the unit was compiled.
+#unit_h_cond_set_in_last_compile=10039_H_Conditional $1 was set at startup in last compilation of $2
+#% when recompilation of an unit is required the compiler will check that
+#% the same conditionals are set for the recompiliation. The compiler has
+#% found a conditional that was used the last time the unit was compiled, but
+#% the conditional is currently not defined.
+unit_w_cant_compile_unit_with_changed_incfile=10040_W_Imposs¡vel recompilar unidade $1, mas encontrados arquivos de inclusÆo modificados
+% A unit was found to have modified include files, but
+% some source files were not found, so recompilation is impossible.
+unit_u_source_modified=10041_U_Arquivo $1 ‚ mais novo que o usado para criar o arquivo PPU $2
+% A modified source file for a compiler unit was found.
+unit_u_ppu_invalid_fpumode=10042_U_Tentando usar uma unidade que foi compilada com um modo diferente de FPU
+% Trying to compile code while using units which were not compiled with
+% the same floating point format mode. Either all code should be compiled
+% with FPU emulation on, or with FPU emulation off.
+unit_u_loading_interface_units=10043_U_Carregando unidades 'interface' de $1
+% When you use the \var{-vu} flag, the compiler warns that it is starting
+% to load the units defined in the interface part of the unit.
+unit_u_loading_implementation_units=10044_U_Carregando unidades 'implementation' de $1
+% When you use the \var{-vu} flag, the compiler warns that it is starting
+% to load the units defined in the implementation part of the unit.
+unit_u_interface_crc_changed=10045_U_Interface CRC alterado para a unidade $1
+% When you use the \var{-vu} flag, the compiler warns that the
+% CRC calculated for the interface has been changed after the implementation
+% has been parsed.
+unit_u_implementation_crc_changed=10046_U_Implementation CRC alterado para a unidade $1
+% When you use the \var{-vu} flag, the compiler warns that the
+% CRC calculated has been changed after the implementation
+% has been parsed.
+unit_u_finished_compiling=10047_U_Terminada a compila‡Æo da unidade $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has finished compiling the unit.
+unit_u_add_depend_to=10048_U_Adi‡Æo dependˆncia: $1 depende de $2
+% When you use the \var{-vu} flag, the compiler warns that it
+% has added a dependency between the two units.
+unit_u_no_reload_is_caller=10049_U_Nenhum recarregamento, ‚ o chamador: $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% will not reload the unit because it is the unit that wants
+% to load this unit.
+unit_u_no_reload_in_second_compile=10050_U_Nenhum recarregamento, j  em segunda compila‡Æo: $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% will not reload the unit because it is already in a second recompile.
+unit_u_flag_for_reload=10051_U_'Flag' para recarregamento: $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has to reload the unit.
+unit_u_forced_reload=10052_U_Recarregamento for‡ado
+% When you use the \var{-vu} flag, the compiler warns that it
+% is reloading the unit because it was required.
+unit_u_previous_state=10053_U_Estado anterior de $1: $2
+% When you use the \var{-vu} flag, the compiler shows the
+% previous state of the unit.
+unit_u_second_compile_unit=10054_U_J  compilando $1, ajustando segunda compila‡Æo
+% When you use the \var{-vu} flag, the compiler warns that it is starting
+% to recompile a unit for the second time. This can happen with interdependent
+% units.
+unit_u_loading_unit=10055_U_Carregando unidade $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% loading the unit.
+unit_u_finished_loading_unit=10056_U_Terminado carregamento unidade $1
+% When you use the \var{-vu} flag, the compiler warns that it finished
+% loading the unit.
+unit_u_registering_new_unit=10057_U_Registrando nova unidade $1
+% When you use the \var{-vu} flag, the compiler warns that it has
+% found a new unit and is registering it in the internal lists.
+unit_u_reresolving_unit=10058_U_Re-solucionando unidade $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has to recalculate the internal data of the unit.
+unit_u_skipping_reresolving_unit=10059_U_Pulando re-solu‡Æo unidade $1, ainda carregando unidades usadas
+% When you use the \var{-vu} flag, the compiler warns that it is
+% skipping the recalculation of the internal data of the unit
+% because there is no data to recalculate.
+unit_u_unload_resunit=10060_U_Descarregando unidade recursos $1 (nÆo necess ria)
+% When you use the \var{-vu} flag, the compiler warns that it is unloading the
+% resource handling unit, since no resources are used.
+unit_e_different_wpo_file=10061_E_Unidade $1 foi compilada usando uma entrada de retorno inteiramente diferente de otimiza‡Æo de programa ($2, $3); recompile-a sem 'wpo' ou use o mesmo arquivo de retorno de entrada 'wpo' para esta compila‡Æo
+% When a unit has been compiled using a particular whole program optimization (wpo) feedback file (\var{-FW<x>} \var{-OW<x>}),
+% this compiled version of the unit is specialised for that particular compilation scenario and cannot be used in
+% any other context. It has to be recompiled before you can use it in another program or with another wpo feedback input file.
+unit_u_indirect_crc_changed=10062_U_CRC interface indireta (objetos/classes) alterado para a unidade $1
+% When you use the \var{-vu} flag, the compiler warns that the
+% indirect CRC calculated for the unit (this is the CRC of all classes/objects/interfaces/$\ldots$
+% in the interfaces of units directly or indirectly used by this unit in the interface) has been changed after the
+% implementation has been parsed.
+% \end{description}
+# EndOfTeX
+
+#
+# Options
+#
+# 11049 is the last used one
+#
+option_usage=11000_O_$1 [options] <inputfile> [options]
+# BeginOfTeX
+%
+% \section{Command line handling errors}
+% This section lists errors that occur when the compiler is processing the
+% command line or handling the configuration files.
+% \begin{description}
+option_only_one_source_support=11001_W_Apenas uma arquivo fonte suportado, alterando arquivo fonte … compilar de "$1" para "$2"
+% You can specify only one source file on the command line. The last
+% one will be compiled, others will be ignored. This may indicate that
+% you forgot a \var{'-'} sign.
+option_def_only_for_os2=11002_W_Arquivo DEF pode ser criado apenas para OS/2
+% This option can only be specified when you're compiling for OS/2.
+option_no_nested_response_file=11003_E_Arquivos respostas aninhados nÆo sÆo suportados
+% You cannot nest response files with the \var{@file} command line option.
+option_no_source_found=11004_F_Nenhm nome arquivo fonte na linha de comando
+% The compiler expects a source file name on the command line.
+option_no_option_found=11005_N_Nenhuma op‡Æo dentro do arquivo de configura‡äes $1
+% The compiler didn't find any option in that config file.
+option_illegal_para=11006_E_Parƒmetro ilegal: $1
+% You specified an unknown option.
+option_help_pages_para=11007_H_-? lista p ginas ajuda
+% When an unknown option is given, this message is diplayed.
+option_too_many_cfg_files=11008_F_Muitos arquivos de configura‡äes aninhados
+% You can only nest up to 16 config files.
+option_unable_open_file=11009_F_Incapaz de abrir arquivo $1
+% The option file cannot be found.
+option_reading_further_from=11010_D_Lendo demais op‡äes de $1
+% Displayed when you have notes turned on, and the compiler switches
+% to another options file.
+option_target_is_already_set=11011_W_Alvo j  est  ajustado para: $1
+% Displayed if more than one \var{-T} option is specified.
+option_no_shared_lib_under_dos=11012_W_Bibs compartilhadas nÆo sÆo suportadas pela plataforma DOS, revertendo para est tica
+% If you specify \var{-CD} for the \dos platform, this message is displayed.
+% The compiler supports only static libraries under \dos.
+option_too_many_ifdef=11013_F_No arquivo op‡äes $1 na linha $2 muitos \var{\#IF(N)DEFs} encontrados
+% The \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_too_many_endif=11014_F_No arquivo op‡äes $1 na linha $2 encontrados \var{\#ENDIFs} inesperados
+% The \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_too_less_endif=11015_F_Condicional aberta no final do arquivo de op‡äes
+% The \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_no_debug_support=11016_W_Gera‡Æo de informa‡äes depura‡Æo nÆo ‚ suportada por este execut vel
+% It is possible to have a compiler executable that doesn't support
+% the generation of debugging info. If you use such an executable with the
+% \var{-g} switch, this warning will be displayed.
+option_no_debug_support_recompile_fpc=11017_H_Tente recompilar com -dGDB
+% It is possible to have a compiler executable that doesn't support
+% the generation of debugging info. If you use such an executable with the
+% \var{-g} switch, this warning will be displayed.
+option_obsolete_switch=11018_W_Vocˆ esta usando uma chave obsoleta $1
+% This warns you when you use a switch that is not needed/supported anymore.
+% It is recommended that you remove the switch to overcome problems in the
+% future, when the meaning of the switch may change.
+option_obsolete_switch_use_new=11019_W_Vocˆ esta usando uma chave obsoleta $1, favor usar $2
+% This warns you when you use a switch that is not supported anymore. You
+% must now use the second switch instead.
+% It is recommended that you change the switch to overcome problems in the
+% future, when the meaning of the switch may change.
+option_switch_bin_to_src_assembler=11020_N_Mudando montador assembler para o padrÆo escrita de fontes
+% This notifies you that the assembler has been changed because you used the
+% -a switch, which can't be used with a binary assembler writer.
+option_incompatible_asm=11021_W_Sa¡da Assembler selecionado "$1" incompat¡vel com "$2"
+option_asm_forced=11022_W_"$1" uso for‡ado montador assembler
+% The assembler output selected cannot generate
+% object files with the correct format. Therefore, the
+% default assembler for this target is used instead.
+option_using_file=11026_T_Lendo op‡äes do arquivo $1
+% Options are also read from this file.
+option_using_env=11027_T_Lendo op‡äes do ambiente $1
+% Options are also read from this environment string.
+option_handling_option=11028_D_Manipulando op‡Æo "$1"
+% Debug info that an option is found and will be handled.
+option_help_press_enter=11029_O_*** pressione <enter> ***
+% Message shown when help is shown page per page. When pressing the ENTER
+% Key, the next page of help is shown. If you press q and then ENTER, the
+% compiler exits.
+option_start_reading_configfile=11030_H_In¡cio leitura do arquivo configura‡Æo $1
+% Start of configuration file parsing.
+option_end_reading_configfile=11031_H_Final leitura do arquivo configura‡Æo $1
+% End of configuration file parsing.
+option_interpreting_option=11032_D_Interpretando op‡Æo "$1"
+% The compiler is interpreting an option
+option_interpreting_firstpass_option=11036_D_Interpretando primeiro passo op‡Æo "$1"
+% The compiler is interpreting an option for the first time.
+option_interpreting_file_option=11033_D_Interpretando op‡Æo arquivo "$1"
+% The compiler is interpreting an option which it read from the configuration file.
+option_read_config_file=11034_D_Lendo arquivo configura‡Æo "$1"
+% The compiler is starting to read the configuration file.
+option_found_file=11035_D_Nome arquivo fonte encontrado "$1"
+% Additional information about options.
+% Displayed when you have the debug option turned on.
+option_code_page_not_available=11039_E_Codepage desconhecido
+% An unknown codepage for the source files was requested.
+% The compiler is compiled with support for several codepages built-in.
+% The requested codepage is not in that list. You will need to recompile
+% the compiler with support for the codepage you need.
+option_config_is_dir=11040_F_Arquivo configura‡Æo $1 ‚ um diret¢rio
+% Directories cannot be used as configuration files.
+option_confict_asm_debug=11041_W_Sa¡da montador Assembler selecionado "$1" nÆo pode gerar informa‡äes depura‡Æo, depura‡Æo desabilitada
+% The selected assembler output cannot generate
+% debugging information, debugging option is therefore disabled.
+option_ppc386_deprecated=11042_W_Uso de 'ppc386.cfg' est  depreciado, favor usar 'fpc.cfg'
+% Using ppc386.cfg is still supported for historical reasons, however, for a multiplatform
+% system the naming makes no sense anymore. Please continue to use fpc.cfg instead.
+option_else_without_if=11043_F_No arquivo op‡äes $1 na linha $2 diretiva \var{\#ELSE} sem \var{\#IF(N)DEF} encontrada
+% An \var{\#ELSE} statement was found in the options file without a matching \var{\#IF(N)DEF} statement.
+option_unsupported_target=11044_F_Op‡Æo "$1" nÆo ‚, ou ainda nÆo ‚, suportada pela plataforma alvo atual
+% Not all options are supported or implemented for all target platforms. This message informs you that a chosen
+% option is incompatible with the currently selected target platform.
+option_unsupported_target_for_feature=11045_F_A caracter¡stica "$1" nÆo ‚, ou ainda nÆo ‚, suportada pela plataforma alvo selecionada
+% Not all features are supported or implemented for all target platforms. This message informs you that a chosen
+% feature is incompatible with the currently selected target platform.
+option_dwarf_smart_linking=11046_N_Informa‡Æo de depura‡Æo DWARF nÆo pode ser usada com vincula‡Æo inteligente neste alvo, mudando para vincula‡Æo est tica
+% Smart linking is currently incompatble with DWARF debug information on most
+% platforms, so smart linking is disabled in such cases.
+option_ignored_target=11047_W_Op‡Æo "$1" ignorada pela plataforma alvo atual
+% Not all options are supported or implemented for all target platforms. This message informs you that a chosen
+% option is ignored for the currently selected target platform.
+option_debug_external_unsupported=11048_W_Desabilitando informa‡Æo externa depura‡Æo porque nÆo ‚ suportada pela combina‡Æo formato alvo/depura‡Æo selecionado.
+% Not all debug formats can be stored in an external file on all platforms. In particular, on
+% Mac OS X only DWARF debug information can be stored externally.
+option_dwarf_smartlink_creation=11049_N_Informa‡Æo de depura‡Æo DWARF nÆo pode ser usada com vincula‡Æo inteligente com assembler externo, desabilitando cria‡Æo de biblioteca est tica.
+% Smart linking is currently incompatble with DWARF debug information on most
+% platforms, so smart linking is disabled in such cases.
+%\end{description}
+# EndOfTeX
+
+#
+# Whole program optimization
+#
+# 12019 is the last used one
+#
+# BeginOfTeX
+%
+% \section{Whole program optimization messages}
+% This section lists errors that occur when the compiler is performing
+% whole program optimization.
+% \begin{description}
+wpo_cant_find_file=12000_F_Imposs¡vel abrir arquivo de retorno de otimiza‡Æo completa de programa "$1"
+% The compiler cannot open the specified feedback file with whole program optimization information.
+wpo_begin_processing=12001_D_Processando informa‡äes de otimiza‡Æo completa de programa no arquivo retorno 'wpo' "$1"
+% The compiler starts processing whole program optimization information found in the named file.
+wpo_end_processing=12002_D_Terminado processamento de otimiza‡Æo completea de programa no arquivo retorno 'wpo' "$1"
+% The compiler has finished processing the whole program optimization information found in the named file.
+wpo_expected_section=12003_E_Se‡Æo cabe‡alho esperada, mas obtido "$2" na linhae $1 do arquivo retorno 'wpo'
+% The compiler expected a section header in the whole program optimization file (starting with \%),
+% but did not find it.
+wpo_no_section_handler=12004_W_Nenhum manipulador registrado para se‡Æo otimiza‡Æo completa de programa "$2" na linha $1 do arquivo de retorno 'wpo', ignorando
+% The compiler has no handler to deal with the mentioned whole program optimization information
+% section, and will therefore ignore it and skip to the next section.
+wpo_found_section=12005_D_Encontrada se‡Æo otimiza‡Æo completa de programa "$1" com informa‡äes sobre "$2"
+% The compiler encountered a section with whole program optimization information, and according
+% to its handler this section contains information usable for the mentioned purpose.
+wpo_no_input_specified=12006_F_As otimiza‡äes completas de programa selecionadas requerem um arquivo de retorno previamente gerado (use -Fw para especificar)
+% The compiler needs information gathered during a previous compilation run to perform the selected
+% whole program optimizations. You can specify the location of the feedback file containing this
+% information using the -Fw switch.
+wpo_not_enough_info=12007_E_Nenhuma informa‡Æo coletada necess ria para realizar "$1" otimiza‡Æo completa programa foi encontrada
+% While you pointed the compiler to a file containing whole program optimization feedback, it
+% did not contain the information necessary to perform the selected optimizations. You most likely
+% have to recompile the program using the appropate -OWxxx switch.
+wpo_no_output_specified=12008_F_Especifique um arquivo de retorno de otimiza‡Æo completa programa para armazenar as informa‡äes geradas (usando -FW)
+% You have to specify the feedback file in which the compiler has to store the whole program optimization
+% feedback that is generated during the compilation run. This can be done using the -FW switch.
+wpo_output_without_info_gen=12009_E_NÆo gerando qualquer informa‡Æo otimiza‡Æo completa programa, assim mesmo um arquivo de retorno foi especificado (usando -FW)
+% The compiler was instructed to store whole program optimization feedback into a file specified using -FW,
+% but not to actually generated any whole program optimization feedback. The classes of to be
+% generated information can be speciied using -OWxxx.
+wpo_input_without_info_use=12010_E_NÆo realizando qualquer otimiza‡Æo completa programa, assim mesmo um arquivo de retorno foi especificado (usando -Fw)
+% The compiler was not instructed to perform any whole program optimizations (no -Owxxx parameters),
+% but nevertheless an input file with such feedback was specified (using -Fwyyy). Since this can
+% indicate that you forgot to specify an -Owxxx parameter, the compiler generates an error in this case.
+wpo_skipping_unnecessary_section=12011_D_Pulando se‡Æo otimiza‡Æo completa programa "$1", porque nÆo ‚ necess ria pelas otimiza‡äes solicitadas
+% The whole program optimization feedback file contains a section with information that is not
+% required by the selected whole program optimizations.
+wpo_duplicate_wpotype=12012_W_Sobrepondo informa‡äes previamente lidas para "$1" do arquivo entrada retorno usando informa‡äes na se‡Æo "$2"
+% The feedback file contains multiple sections that provide the same class of information (e.g.,
+% information about which virtual methods can be devirtualized). In this case, the information in last encountered
+% section is used. Turn on debugging output (-vd) to see which class of information is provided by each section.
+wpo_cannot_extract_live_symbol_info_strip=12013_E_Imposs¡vel extrair informa‡äes de vida de s¡mbolos do programa durante elimina‡Æo s¡mbolos, use -Xs-
+% Certain symbol liveness collectors extract the symbol information from the linked program. If the symbol information
+% is stripped (option -Xs), this is not possible.
+wpo_cannot_extract_live_symbol_info_no_link=12014_E_Imposs¡vel extrair informa‡äes de vida de s¡mbolos do programa quando nÆo vinculando
+% Certain symbol liveness collectors extract the symbol information from the linked program. If the program is not
+% linked by the compiler, this is not possible.
+wpo_cannot_find_symbol_progs=12015_F_Imposs¡vel encontrar "$1" ou "$2" para extrair informa‡äes de vida de s¡mbolos do programa vinculado
+% Certain symbol liveness collectors need a helper program to extract the symbol information from the linked program.
+% This helper program is normally 'nm', which is part of the GNU binutils.
+wpo_error_reading_symbol_file=12016_E_Erro durante leitura das informa‡äes de v¡da de s¡mbolos produzidas por "$1"
+% An error occurred during the reading of the symbol liveness file that was generated using the 'nm' or 'objdump' program. The reason
+% can be that it was shorter than expected, or that its format was not understood.
+wpo_error_executing_symbol_prog=12017_F_Erro executando "$1" (c¢digo sa¡da: $2) para extrair informa‡äes de s¡mbolos do programa vinculado
+% Certain symbol liveness collectors need a helper program to extract the symbol information from the linked program.
+% The helper program produced the reported error code when it was run on the linked program.
+wpo_symbol_live_info_needs_smart_linking=12018_E_Cole‡Æo de informa‡äes de vida de s¡mbolos pode ajudar apenas quando usando vincula‡Æo inteligente, use -CX -XX
+% Whether or not a symbol is live is determined by looking whether it exists in the final linked program.
+% Without smart linking/dead code stripping, all symbols are always included, regardless of whether they are
+% actually used or not. So in that case all symbols will be seen as live, which makes this optimization ineffective.
+wpo_cant_create_feedback_file=12019_E_Imposs¡vel criar arquivo retorno otimiza‡äes completas de programa especificado "$1"
+% The compiler is unable to create the file specified using the -FW parameter to store the whole program optimisation information.
+%\end{description}
+# EndOfTeX
+
+
+#
+# Logo (option -l)
+#
+option_logo=11023_[
+Compilador Free Pascal versÆo $FPCFULLVERSION [$FPCDATE] para $FPCCPU
+Copyright (c) 1993-2011 by Florian Klaempfl
+]
+
+#
+# Info (option -i)
+#
+option_info=11024_[
+Compilador Free Pascal versÆo $FPCVERSION
+
+Data Compilador : $FPCDATE
+CPU Alvo Copilador : $FPCCPU
+
+Alvos suportados:
+ $OSTARGETS
+
+Conjunto de instru‡äes CPU suportados:
+ $INSTRUCTIONSETS
+
+Conjunto de instru‡äes FPU suportados:
+ $FPUINSTRUCTIONSETS
+
+Alvos ABI suportados:
+ $ABITARGETS
+
+Otimiza‡äes suportadas:
+ $OPTIMIZATIONS
+
+Otimiza‡äs Completas Programa suportadas:
+ Todas
+ $WPOPTIMIZATIONS
+
+Tipos Microcontroladores suportados:
+ $CONTROLLERTYPES
+
+Este programa ‚ oferecido sob a Licen‡a Geral P£blica GNU
+Para maiores informa‡äes leia COPYING.FPC
+
+Reportar falhas, sugestäes, etc. para:
+ http://bugs.freepascal.org
+ou
+ bugs@freepascal.org
+]
+
+#
+# Help pages (option -? and -h)
+#
+# The first character on the line indicates who will display this
+# line, the current possibilities are :
+# * = every target
+# 3 = 80x86 targets
+# 4 = x86_64
+# 6 = 680x0 targets
+# A = ARM
+# e = in extended debug mode only
+# P = PowerPC targets
+# S = Sparc targets
+# V = Virtual machine targets
+# The second character also indicates who will display this line,
+# (if the above character was TRUE) the current possibilities are :
+# * = everyone
+# g = with GDB info supported by the compiler
+# O = OS/2
+# L = UNIX systems
+# The third character represents the indentation level.
+#
+option_help_pages=11025_[
+**0*_Ponha + ap¢s uma chave de op‡Æo booleana para habilit -la, - para desabilit -la
+**1a_O compilador nÆo elimina o arquivo gerado do montador assembler
+**2al_Lista linhas do c¢digo fonte no arquivo assembler
+**2an_Lista informa‡äes n¢ no arquivo assembler
+*L2ap_Usa encadeadores (pipes) em vez de criar arquivos tempor rios assembler
+**2ar_Lista informa‡äes aloca‡Æo/libera‡Æo registros no arquivo assembler
+**2at_Lista informa‡äes tempor rias aloca‡Æo/libera‡Æo no arquivo assembler
+**1A<x>_Formato sa¡da:
+**2Adefault_Usa montador assembler padrÆo
+3*2Aas_Monta usando o GNU AS
+3*2Amacho_Mach-O (Darwin, Intel 32 bit) usando gravador interno
+3*2Anasmcoff_Arquivo COFF (Go32v2) usando Nasm
+3*2Anasmelf_Arquivo ELF32 (Linux) usando Nasm
+3*2Anasmwin32_Arquivo objeto Win32 usando Nasm
+3*2Anasmwdosx_Arquivo objeto Win32/WDOSX usando Nasm
+3*2Awasm_Arquivo Obj usando Wasm (Watcom)
+3*2Anasmobj_Arquivo Obj usando Nasm
+3*2Amasm_Arquivo Obj usando Masm (Microsoft)
+3*2Atasm_Arquivo Obj usando Tasm (Borland)
+3*2Aelf_ELF (Linux) usando gravador interno
+3*2Acoff_COFF (Go32v2) usando gravador interno
+3*2Apecoff_PE-COFF (Win32) usando gravador interno
+4*2Aas_Monta usando o GNU AS
+4*2Agas_Monta usando o GNU GAS
+4*2Agas-darwin_Monta darwin Mach-O64 usando GNU GAS
+4*2Amasm_Win64 arquivo objeto usando ml64 (Microsoft)
+4*2Apecoff_PE-COFF (Win64) usando escritor interno
+4*2Aelf_ELF (Linux-64bit) usando escritor interno
+6*2Aas_Arquivo Unix .o usando o GNU AS
+6*2Agas_Montador assembler GNU Motorola
+6*2Amit_Sintaxe MIT (antigo GAS)
+6*2Amot_Montador assembler Motorola padrÆo
+A*2Aas_Monta usando o GNU AS
+P*2Aas_Monta usando o GNU AS
+S*2Aas_Monta usando o GNU AS
+**1b_Gera informa‡äes navegador
+**2bl_Gera informa‡äes s¡mbolos locais
+**1B_Constr¢i todos os m¢dulos
+**1C<x>_Op‡äes gera‡Æo de c¢digo:
+**2C3<x>_Ligar verifica‡Æo de erro ieee para constantes
+**2Ca<x>_Seleciona ABI, veja fpc -i para poss¡veis valores
+**2Cb_Gera c¢digo 'big-endian'
+**2Cc<x>_Ajusta conven‡Æo de chamada para <x>
+**2CD_Cria tamb‚m biblioteca dinƒmica (nÆo suportado)
+**2Ce_Compila‡Æo com opcodes de ponto flutuante emulados
+**2Cf<x>_Seleciona conjunto de instru‡äes fpu a usar, veja fpc -i para poss¡veis valores
+**2CF<x>_PrecisÆo m¡nima constante ponto flutuante (padrÆo, 32, 64)
+**2Cg_Gera c¢digo PIC
+**2Ch<n>_<n> bytes heap (entre 1023 e 67107840)
+**2Ci_Verifica‡Æo E/S
+**2Cn_Omite est gio vincula‡Æo
+**2Co_Verifica transbordamento de opera‡äes inteiras
+**2CO_Verifica poss¡vel transbordamento de opera‡äes inteiras
+**2Cp<x>_Seleciona conjunto de instru‡äes, veja fpc -i para poss¡ves valores
+**2CP<x>=<y>_ Ajustes compacta‡Æo
+**3CPPACKSET=<y>_ <y> conjunto aloca‡Æo: 0, 1 ou DEFAULT ou NORMAL, 2, 4 e 8
+**2Cr_Verifica‡Æo de faixa
+**2CR_Verifica validade de chamada de m‚todo de objeto
+**2Cs<n>_Ajusta verifica‡Æo tamanho da Pilha para <n>
+**2Ct_Verifica‡Æo Pilha (apenas para testes, veja manual)
+**2CX_Cria tamb‚m biblioteca inteligentemente vinculada
+**1d<x>_Define o s¡mbolo <x>
+**1D_Gera um arquivo DEF
+**2Dd<x>_Ajusta descri‡Æo para <x>
+**2Dv<x>_Ajusta versÆo DLL para <x>
+*O2Dw_Aplica‡Æo PM
+**1e<x>_Ajusta caminho para execut vel
+**1E_Mesmo que -Cn
+**1fPIC_Mesmo que -Cg
+**1F<x>_Ajusta nomes de arquivo e caminhos:
+**2Fa<x>[,y]_(para um programa) carregar unidades <x> e [y] antes de analisar cl usula 'uses'
+**2Fc<x>_Ajusta entrada p gina de c¢digo para <x>
+**2FC<x>_Ajusta nome do compilador RC bin rio para <x>
+**2Fd_Disabilita o cache de diret¢rios interno do compilador
+**2FD<x>_Ajusta o diret¢rio onde procurar por utilit rios para o compilador
+**2Fe<x>_Redireciona sa¡da erros para <x>
+**2Ff<x>_Adiciona <x> ao caminho framework (apenas Darwin)
+**2FE<x>_Ajusta caminho sa¡da exe/unidade para <x>
+**2Fi<x>_Adiciona <x> ao caminho inclusäes
+**2Fl<x>_Adiciona <x> ao caminho bibliotecas
+**2FL<x>_Use <x> como vinculador dinƒmico
+**2Fm<x>_Carrega tabela conversÆo unicode de <x>.txt no dir. do compilador
+**2Fo<x>_Adiciona <x> ao caminho objetos
+**2Fr<x>_Carrega o arquivo mensagens erro <x>
+**2FR<x>_Ajusta vinculador recursos (.res) para <x>
+**2Fu<x>_Adiciona <x> ao caminho unidades
+**2FU<x>_Ajusta caminho sa¡da unidade para <x>, sobrepäe -FE
+**2FW<x>_Armazena retorno otimiza‡Æo completa programa gerada em <x>
+**2Fw<x>_Carrega retorno otimiza‡Æo completa programa previamente armazenada de <x>
+*g1g_Gerar informa‡äes depura‡Æo (formato padrÆo para o alvo)
+*g2gc_Gerar verifica‡äes para ponteiros
+*g2gh_Usa unidade heaptrace (para depura‡Æo vazamentos/corrup‡Æo mem¢ria)
+*g2gl_Usa unidade informa‡äes linha (mostra mais info. com backtraces)
+*g2go<x>_Ajusta op‡äes informa‡äes depura‡Æo
+*g3godwarfsets_ Habilita 'conjunto' info. depura‡Æo DWARF (falhas gdb < 6.5)
+*g3gostabsabsincludes_ Armazena caminhos absolutos/completos arquivos inclusäes em 'Stabs'
+*g3godwarfmethodclassprefix_ Prefixa nomes m‚todos com nome classe em DWARF
+*g2gp_Preserva caixa nomes s¡mbolos em 'stabs'
+*g2gs_Gera informa‡äes depura‡Æo 'Stabs'
+*g2gt_Inutiliza vari veis locais (para detetar utiliza‡Æo de nÆo-inicilizadas)
+*g2gv_Gera programas rastre veis com 'Valgrind'
+*g2gw_Gera informa‡äes depura‡Æo DWARFv2 (mesmo que -gw2)
+*g2gw2_Gera informa‡äes depura‡Æo DWARFv2
+*g2gw3_Gera informa‡äes depura‡Æo DWARFv3
+*g2gw4_Gera informa‡äes depura‡Æo DWARFv4 (experimental)
+**1i_Informa‡äes
+**2iD_Retorna data compilador
+**2iV_Retorna versÆo compilador curta
+**2iW_Retorna versÆo compilador completa
+**2iSO_Retorna SO compilador
+**2iSP_Retorna processador servidor compilador
+**2iTO_Retorna SO alvo
+**2iTP_Retorna processador alvo
+**1I<x>_Adiciona <x> ao caminho inclusäes
+**1k<x>_Passa <x> ao vinculador
+**1l_Grava logo
+**1M<x>_Ajusta modo linguagem para <x>
+**2Mfpc_Dialeto Free Pascal (padrÆo)
+**2Mobjfpc_Modo FPC com suporte ao Object Pascal
+**2Mdelphi_Modo compatibilidade Delphi 7
+**2Mtp_Modo compatibilidade TP/BP 7.0
+**2Mmacpas_Modo compatibilidade dialetos Macintosh Pascal
+**1n_NÆo ler os arquivos de configura‡äes padrÆo
+**1N<x>_Otimiza‡äes n¢s  rvore
+**2Nu_Desdobra la‡os
+**1o<x>_Altera o nome do execut vel produzido para <x>
+**1O<x>_Otimiza‡äes:
+**2O-_Disabilita otimiza‡äes
+**2O1_N¡vel 1 otimiza‡äes (r pida e amig vel depurador)
+**2O2_N¡vel 2 otimiza‡äes (-O1 + otimiza‡äes r pidas)
+**2O3_N¡vel 3 otimiza‡äes (-O2 + otimiza‡äes lentas)
+**2Oa<x>=<y>_Ajusta alinhamento
+**2Oo[NO]<x>_Habilita ou desabilita otimiza‡äes, veja fpc -i para poss¡veis valores
+**2Op<x>_Ajusta cpu alvo para otimiza‡äes, veja fpc -i para poss¡veis valores
+**2OW<x>_Gera retorno otimiza‡Æo completa programa para otimiza‡äes <x>, veja fpc -i para poss¡veis valores
+**2Ow<x>_Realiza otimiza‡Æo completa programa <x>, veja fpc -i para poss¡veis valores
+**2Os_Otimiza tamanho ao inv‚s de velocidade
+**1pg_Gera perfil c¢digo para 'gprof' (define FPC_PROFILE)
+**1R<x>_Estilo leitura Assembler:
+**2Rdefault_Use assembler padrÆo para alvo
+3*2Ratt_Leia assembler estilo AT&T
+3*2Rintel_Leia assembler estilo Intel
+6*2RMOT_Leia assembler estilo motorola
+**1S<x>_Op‡äes sintaxe:
+**2S2_Mesmo que -Mobjfpc
+**2Sc_Suporte operadores similares C (*=,+=,/= and -=)
+**2Sa_Liga asser‡äes
+**2Sd_Mesmo que -Mdelphi
+**2Se<x>_Op‡äes erros. <x> ‚ uma combina‡Æo do seguinte:
+**3*_<n> : Compilador para depois de <n> erros (padrÆo ‚ 1)
+**3*_w : Compilador tamb‚m para ap¢s avisos
+**3*_n : Compilador tamb‚m para ap¢s notas
+**3*_h : Compilador tamb‚m para ap¢s dicas
+**2Sg_Habilita LABEL e GOTO (padrÆo em -Mtp e -Mdelphi)
+**2Sh_Use 'ansistrings' por padrÆo ao inv‚s de 'shortstrings'
+**2Si_Liga 'inlining' de procedimentos/fun‡äes declaradas como "em-linha" (inline)
+**2Sk_Carrega unidade 'fpcylix'
+**2SI<x>_Ajusta estilo interface para <x>
+**3SIcom_COM interface compat¡vel (padrÆo)
+**3SIcorba_CORBA interface compat¡vel
+**2Sm_Suporta macros semelhantes C (global)
+**2So_Mesmo que -Mtp
+**2Ss_Nome construtor deve ser 'init' (destruidor deve ser 'done')
+**2Sx_Habilita palavras-chave exce‡äes (padrÆo nos modos Delphi/ObjFPC)
+**2Sy_@<ponteiro> retorna um ponteiro tipado, mesmo que $T+
+**1s_NÆo chama o montador assembler e o vinculador
+**2sh_Gera roteiro para vincular no servidor
+**2st_Gera roteiro para vincular no alvo
+**2sr_Pula fase aloca‡Æo registro (use com -alr)
+**1T<x>_Sistema operacional alvo:
+3*2Tdarwin_Darwin/Mac OS X
+3*2Temx_OS/2 via EMX (incluidos extensor EMX/RSX)
+3*2Tfreebsd_FreeBSD
+3*2Tgo32v2_VersÆo 2 do extensor DOS DJ Delorie
+3*2Tiphonesim_ iPhoneSimulator do iOS SDK 3.2+ (versäes antigas: -Tdarwin)
+3*2Tlinux_Linux
+3*2Tnetbsd_NetBSD
+3*2Tnetware_M¢dulo Novell Netware (clib)
+3*2Tnetwlibc_M¢dulo Novell Netware (libc)
+3*2Topenbsd_OpenBSD
+3*2Tos2_OS/2 / eComStation
+3*2Tsunos_SunOS/Solaris
+3*2Tsymbian_Symbian OS
+3*2Tsolaris_Solaris
+3*2Twatcom_Watcom compatible DOS extender
+3*2Twdosx_WDOSX DOS extender
+3*2Twin32_Windows 32 Bit
+3*2Twince_Windows CE
+4*2Tdarwin_Darwin/Mac OS X
+4*2Tlinux_Linux
+4*2Twin64_Win64 (sistemas Windows 64 bit)
+6*2Tamiga_Commodore Amiga
+6*2Tatari_Atari ST/STe/TT
+6*2Tlinux_Linux
+6*2Tpalmos_PalmOS
+A*2Tdarwin_Darwin/iPhoneOS/iOS
+A*2Tlinux_Linux
+A*2Twince_Windows CE
+P*2Tamiga_AmigaOS
+P*2Tdarwin_Darwin/Mac OS X
+P*2Tlinux_Linux
+P*2Tmacos_Mac OS (cl ssico)
+P*2Tmorphos_MorphOS
+S*2Tsolaris_Solaris
+S*2Tlinux_Linux
+**1u<x>_Indefine o s¡mbolo <x>
+**1U_Op‡äes unidades:
+**2Un_NÆo verifica onde o nome unidade coincide com o nome arquivo
+**2Ur_Gera arquivos lan‡amento unidades (nunca automaticamente recompilado)
+**2Us_Compilar uma unidade sistema
+**1v<x>_Ser detalhado. <x> ‚ uma combina‡Æo das seguintes letras:
+**2*_e : Mostra erros (padrÆo) 0 : Nada mostra (exceto erros)
+**2*_w : Mostra avisos u : Mostra info. unidade
+**2*_n : Mostra notas t : Mostra arquivos tentados/usados
+**2*_h : Mostra dicas c : Mostra condicionais
+**2*_i : Mostra info. geral d : Mostra info. depura‡Æo
+**2*_l : Mostra n£meros linhas r : Modo compatibilidade Rhide/GCC
+**2*_s : Mostra Data/Hora q : Mostra n£meros mensagens
+**2*_a : Mostra tudo x : Info. execut vel (apenas Win32)
+**2*_b : Grava mensagens nome arqs. p : Grava tree.log com  rvore an lise
+**2*_ com caminho completo v : Grava fpcdebug.txt com muitas
+**2*_ informa‡äes de depura‡Æo
+**2*_m<x>,<y> : NÆo mostra mensagens numeradas <x> e <y>
+**1W<x>_Op‡äes espec¡ficas do alvo (alvos)
+3*2WA_Especifica aplica‡Æo do tipo nativo (Windows)
+4*2WA_Especifica aplica‡Æo do tipo nativo (Windows)
+A*2WA_Especifica aplica‡Æo do tipo nativo (Windows)
+3*2Wb_Cria um encarte ao inv‚s de uma biblioteca (Darwin)
+P*2Wb_Cria um encarte ao inv‚s de uma biblioteca (Darwin)
+p*2Wb_Cria um encarte ao inv‚s de uma biblioteca (Darwin)
+A*2Wb_Cria um encarte ao inv‚s de uma biblioteca (Darwin)
+4*2Wb_Cria um encarte ao inv‚s de uma biblioteca (Darwin)
+3*2WB_Cria uma imagem reloc vel (Windows, Symbian)
+3*2WBxxxx_Define base da imagem para xxxx (Windows, Symbian)
+4*2WB_Cria uma imagem reloc vel (Windows)
+4*2WBxxxx_Define base da imagem para xxxx (Windows)
+A*2WB_Cria uma imagem reloc vel (Windows, Symbian)
+A*2WBxxxx_Define base da imagem para xxxx (Windows, Symbian)
+3*2WC_Especifica aplica‡Æo do tipo console (EMX, OS/2, Windows)
+4*2WC_Especifica aplica‡Æo do tipo console (EMX, OS/2, Windows)
+A*2WC_Especifica aplica‡Æo do tipo console (Windows)
+P*2WC_Especifica aplica‡Æo do tipo console (Classic Mac OS)
+3*2WD_Usa DEFFILE para exportar fun‡äes de DLL ou EXE (Windows)
+4*2WD_Usa DEFFILE para exportar fun‡äes de DLL ou EXE (Windows)
+A*2WD_Usa DEFFILE para exportar fun‡äes de DLL ou EXE (Windows)
+3*2We_Usa recursos externos (Darwin)
+4*2We_Usa recursos externos (Darwin)
+A*2We_Usa recursos externos (Darwin)
+P*2We_Usa recursos externos (Darwin)
+p*2We_Usa recursos externos (Darwin)
+3*2WF_Especifica aplica‡Æo do tipo tela-cheia (EMX, OS/2)
+3*2WG_Especifica aplica‡Æo do tipo gr fica (EMX, OS/2, Windows)
+4*2WG_Especifica aplica‡Æo do tipo gr fica (EMX, OS/2, Windows)
+A*2WG_Especifica aplica‡Æo do tipo gr fica (Windows)
+P*2WG_Especifica aplica‡Æo do tipo gr fica (Classic Mac OS)
+3*2Wi_Usa recursos internos (Darwin)
+4*2Wi_Usa recursos internos (Darwin)
+A*2Wi_Usa recursos internos (Darwin)
+P*2Wi_Usa recursos internos (Darwin)
+p*2Wi_Usa recursos internos (Darwin)
+3*2WI_Liga/desliga o uso de se‡äes de importa‡Æo (Windows)
+4*2WI_Liga/desliga o uso de se‡äes de importa‡Æo (Windows)
+A*2WI_Liga/desliga o uso de se‡äes de importa‡Æo (Windows)
+3*2WN_NÆo gera c¢digo de reloca‡Æo, necess rio para depura‡Æo (Windows)
+4*2WN_NÆo gera c¢digo de reloca‡Æo, necess rio para depura‡Æo (Windows)
+A*2WN_NÆo gera c¢digo de reloca‡Æo, necess rio para depura‡Æo (Windows)
+A*2Wpxxxx_Especifica o tipo de controlador, veja fpc -i para valores poss¡veis
+V*2Wpxxxx_Especifica o tipo de controlador, veja fpc -i para valores poss¡veis
+3*2WR_Gera c¢digo de reloca‡Æo (Windows)
+4*2WR_Gera c¢digo de reloca‡Æo (Windows)
+A*2WR_Gera c¢digo de reloca‡Æo (Windows)
+P*2WT_Especifica aplica‡Æo do tipo ferramenta MPW (Classic Mac OS)
+**2WX_Habilita pilha execut vel (Linux)
+**1X_Op‡äes do execut vel:
+**2Xc_Passar --shared/-dynamic para o vinculador (BeOS, Darwin, FreeBSD, Linux)
+**2Xd_NÆo usar caminho padrÆo de busca de biblioteca (necess rio para compila‡Æo cross)
+**2Xe_Usar vinculador externo
+**2Xg_Cria informa‡Æo de depura‡Æo em um arquivo separado e adiciona uma se‡Æo de v¡nculo de depura‡Æo ao execut vel
+**2XD_Tenta vincular unidades dinamicamente (define FPC_LINK_DYNAMIC)
+**2Xi_Usa vinculador interno
+**2Xm_Gera mapa de vincula‡Æo
+**2XM<x>_Define o nome da rotina 'main' do programa (padrÆo ‚ 'main')
+**2XP<x>_Apensa os nomes 'binutils' com o prefixo <x>
+**2Xr<x>_Define o caminho-rlink do vinculador para <x> (necess rio para compila‡Æo 'cross', veja o manual do 'ld' para maiores informa‡äes) (BeOS, Linux)
+**2XR<x>_Apensa todos os caminhos de busca do vinculador com <x> (BeOS, Darwin, FreeBSD, Linux, Mac OS, Solaris)
+**2Xs_Remove todos os s¡mbolos do execut vel
+**2XS_Tenta vincular unidades estaticamente (padrÆo, define FPC_LINK_STATIC)
+**2Xt_Vincula com bibliotecas est ticas (-static ‚ passado ao vinculador)
+**2XX_Tenta a vincula‡Æo inteligente de unidades (define FPC_LINK_SMART)
+**1*_
+**1?_Exibe esta ajuda
+**1h_Exibe esta ajuda sem espera
+]
+
+#
+# The End...
diff --git a/closures/compiler/msg/errorptu.msg b/closures/compiler/msg/errorptu.msg
new file mode 100644
index 0000000000..186279067f
--- /dev/null
+++ b/closures/compiler/msg/errorptu.msg
@@ -0,0 +1,3447 @@
+#
+# This file is part of the Free Pascal Compiler
+# Copyright (c) 1999-2009 by the Free Pascal Development team
+#
+# Portuguese (UTF-8) language file for Free Pascal Compiler
+# Contributed by Marcelo B Paula, based on errore.msg SVN Rev.19883
+# Former translator: Ari Ricardo Ody <ary.odi at japinfo.com.br>
+#
+# See the file COPYING.FPC, included in this distribution,
+# for details about the copyright.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#
+#
+# The constants are build in the following order:
+# <part>_<type>_<txtidentifier>
+#
+# <part> is the part of the compiler the message is used
+# asmr_ assembler parsing
+# asmw_ assembler writing/binary writers
+# unit_ unit handling
+# scan_ scanner
+# parser_ parser
+# type_ type checking
+# general_ general info
+# exec_ calls to assembler, external linker, binder
+# link_ internal linker
+#
+# <type> the type of the message it should normally used for
+# f_ fatal error
+# e_ error
+# w_ warning
+# n_ note
+# h_ hint
+# i_ info
+# l_ add linenumber
+# u_ used
+# t_ tried
+# c_ conditional
+# d_ debug message
+# x_ executable informations
+# o_ normal (e.g., "press enter to continue")
+#
+# <type> can contain a minus sign at the beginning to mark that
+# the message is off by default. Look at type_w_explicit_string_cast
+# for example.
+
+#
+# General
+#
+# 01023 is the last used one
+#
+# BeginOfTeX
+% \section{General compiler messages}
+% This section gives the compiler messages which are not fatal, but which
+% display useful information. The number of such messages can be
+% controlled with the various verbosity level \var{-v} switches.
+% \begin{description}
+general_t_compilername=01000_T_Compilador: $1
+% When the \var{-vt} switch is used, this line tells you what compiler
+% is used.
+general_d_sourceos=01001_D_SO Compilador: $1
+% When the \var{-vd} switch is used, this line tells you what the source
+% operating system is.
+general_i_targetos=01002_I_SO Alvo: $1
+% When the \var{-vd} switch is used, this line tells you what the target
+% operating system is.
+general_t_exepath=01003_T_Usando caminho executável: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for its binaries.
+general_t_unitpath=01004_T_Usando caminho unidade: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for compiled units. You can set this path with the \var{-Fu} option.
+general_t_includepath=01005_T_Usando caminho inclusões: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for its include files (files used in \var{\{\$I xxx\}} statements).
+% You can set this path with the \var{-Fi} option.
+general_t_librarypath=01006_T_Usando caminho biblioteca: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for the libraries. You can set this path with the \var{-Fl} option.
+general_t_objectpath=01007_T_Usando caminho objeto: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for object files you link in (files used in \var{\{\$L xxx\}} statements).
+% You can set this path with the \var{-Fo} option.
+general_i_abslines_compiled=01008_I_$1 linhas compiladas, $2 seg$3
+% When the \var{-vi} switch is used, the compiler reports the number
+% of lines compiled, and the time it took to compile them (real time,
+% not program time).
+general_f_no_memory_left=01009_F_Memória insuficiente
+% The compiler doesn't have enough memory to compile your program. There are
+% several remedies for this:
+% \begin{itemize}
+% \item If you're using the build option of the compiler, try compiling the
+% different units manually.
+% \item If you're compiling a huge program, split it up into units, and compile
+% these separately.
+% \item If the previous two don't work, recompile the compiler with a bigger
+% heap. (You can use the \var{-Ch} option for this, \seeo{Ch}.)
+% \end{itemize}
+general_i_writingresourcefile=01010_I_Gravando arquivo Tabela Recursos 'String': $1
+% This message is shown when the compiler writes the Resource String Table
+% file containing all the resource strings for a program.
+general_e_errorwritingresourcefile=01011_E_Gravando arquivo Tabela Recursos 'String': $1
+% This message is shown when the compiler encounters an error when writing
+% the Resource String Table file.
+general_i_fatal=01012_I_Fatal:
+% Prefix for Fatal Errors.
+general_i_error=01013_I_Erro:
+% Prefix for Errors.
+general_i_warning=01014_I_Aviso:
+% Prefix for Warnings.
+general_i_note=01015_I_Nota:
+% Prefix for Notes.
+general_i_hint=01016_I_Dica:
+% Prefix for Hints.
+general_e_path_does_not_exist=01017_E_Caminho "$1" não existe
+% The specified path does not exist.
+general_f_compilation_aborted=01018_F_Compilação abortada
+% Compilation was aborted.
+general_text_bytes_code=01019_bytes (código gerado)
+% The size of the generated executable code, in bytes.
+general_text_bytes_data=01020_bytes (dados gerados)
+% The size of the generated program data, in bytes.
+general_i_number_of_warnings=01021_I_$1 aviso(s) emitido(s)
+% Total number of warnings issued during compilation.
+general_i_number_of_hints=01022_I_$1 dica(s) emitida(s)
+% Total number of hints issued during compilation.
+general_i_number_of_notes=01023_I_$1 nota(s) emitida(s)
+% Total number of notes issued during compilation.
+general_f_ioerror=01024_F_Erro E/S: $1
+% During compilation an I/O error happened which allows no further compilation.
+general_f_oserror=01025_F_Erro do sistema operacional: $1
+% During compilation an operanting system error happened which allows no further compilation.
+% \end{description}
+#
+# Scanner
+#
+# 02087 is the last used one
+#
+% \section{Scanner messages.}
+% This section lists the messages that the scanner emits. The scanner takes
+% care of the lexical structure of the pascal file, i.e. it tries to find
+% reserved words, strings, etc. It also takes care of directives and
+% conditional compilation handling.
+% \begin{description}
+scan_f_end_of_file=02000_F_Fim de arquivo inesperado
+% This typically happens in one of the following cases:
+% \begin{itemize}
+% \item The source file ends before the final \var{end.} statement. This
+% happens mostly when the \var{begin} and \var{end} statements aren't
+% balanced;
+% \item An include file ends in the middle of a statement.
+% \item A comment was not closed.
+% \end{itemize}
+scan_f_string_exceeds_line=02001_F_'String' excendo linha
+% There is a missing closing ' in a string, so it occupies
+% multiple lines.
+scan_f_illegal_char=02002_F_caractere ilegal "$1" ($2)
+% An illegal character was encountered in the input file.
+scan_f_syn_expected=02003_F_Erro sintaxe, "$1" esperado, mas "$2" encontrado
+% This indicates that the compiler expected a different token than
+% the one you typed. It can occur almost anywhere it is possible to make an error
+% against the Pascal language.
+scan_t_start_include_file=02004_TL_Iniciando leitura arquivo de inclusões $1
+% When you provide the \var{-vt} switch, the compiler tells you
+% when it starts reading an included file.
+scan_w_comment_level=02005_W_Nível comentário $1 encontrado
+% When the \var{-vw} switch is used, then the compiler warns you if
+% it finds nested comments. Nested comments are not allowed in Turbo Pascal
+% and Delphi, and can be a possible source of errors.
+scan_n_ignored_switch=02008_N_Ignorar chave compilador "$1"
+% With \var{-vn} on, the compiler warns if it ignores a switch.
+scan_w_illegal_switch=02009_W_Chave ilegal compilador "$1"
+% You included a compiler switch (i.e. \var{\{\$... \}}) which the compiler
+% does not recognise.
+scan_w_switch_is_global=02010_W_Chave global compilador fora de lugar
+% The compiler switch is misplaced, and should be located at
+% the start of the unit or program.
+scan_e_illegal_char_const=02011_E_Constante caractere ilegal
+% This happens when you specify a character with its ASCII code, as in
+% \var{\#96}, but the number is either illegal, or out of range.
+scan_f_cannot_open_input=02012_F_Impossível abrir arquivo "$1"
+% \fpc cannot find the program or unit source file you specified on the
+% command line.
+scan_f_cannot_open_includefile=02013_F_Impossível abrir arquivo de inclusões "$1"
+% \fpc cannot find the source file you specified in a \var{\{\$include ..\}}
+% statement.
+scan_e_illegal_pack_records=02015_E_Especificador alinhamento registro ilegal "$1"
+% You are specifying \var{\{\$PACKRECORDS n\} } or \var{\{\$ALIGN n\} }
+% with an illegal value for \var{n}. For \$PACKRECORDS valid alignments are 1, 2, 4, 8, 16, 32, C,
+% NORMAL, DEFAULT, and for \$ALIGN valid alignments are 1, 2, 4, 8, 16, 32, ON,
+% OFF. Under mode MacPas \$ALIGN also supports MAC68K, POWER and RESET.
+scan_e_illegal_pack_enum=02016_E_Especificador tamanho-mínimo enumeração ilegal "$1"
+% You are specifying the \var{\{\$PACKENUM n\}} with an illegal value for
+% \var{n}. Only 1,2,4, NORMAL or DEFAULT is valid here.
+scan_e_endif_expected=02017_E_$ENDIF esperado para $1 $2 definido em $3 linha $4
+% Your conditional compilation statements are unbalanced.
+scan_e_preproc_syntax_error=02018_E_Erro sintaxe enquanto analisando uma expressão compilação condicional
+% There is an error in the expression following the \var{\{\$if ..\}}, \var{\{\$ifc \}}
+% or \var{\{\$setc \}} compiler directives.
+scan_e_error_in_preproc_expr=02019_E_Avaliando uma expressão compilação condicional
+% There is an error in the expression following the \var{\{\$if ..\}}, $ifc or $setc compiler
+% directives.
+scan_w_macro_cut_after_255_chars=02020_W_Conteúdo macro limitada ao tamanho de 255 caracteres
+% The contents of macros cannot be longer than 255 characters.
+scan_e_endif_without_if=02021_E_ENDIF sem IF(N)DEF
+% Your \var{\{\$IFDEF ..\}} and {\{\$ENDIF\}} statements aren't balanced.
+scan_f_user_defined=02022_F_Definido pelo usuário: $1
+% A user defined fatal error occurred. See also the \progref.
+scan_e_user_defined=02023_E_Definido pelo usuário: $1
+% A user defined error occurred. See also the \progref.
+scan_w_user_defined=02024_W_Definido pelo usuário: $1
+% A user defined warning occurred. See also the \progref.
+scan_n_user_defined=02025_N_Definido pelo usuário: $1
+% A user defined note was encountered. See also the \progref.
+scan_h_user_defined=02026_H_Definido pelo usuário: $1
+% A user defined hint was encountered. See also the \progref.
+scan_i_user_defined=02027_I_Definido pelo usuário: $1
+% User defined information was encountered. See also the \progref.
+scan_e_keyword_cant_be_a_macro=02028_E_Palavra-chave redefinida como macro não tem efeito
+% You cannot redefine keywords with macros.
+scan_f_macro_buffer_overflow=02029_F_Transbordamento "buffer" macro durante leitura ou expansão de uma macro
+% Your macro or its result was too long for the compiler.
+scan_w_macro_too_deep=02030_W_Expansão de macros excede profundidade de 16.
+% When expanding a macro, macros have been nested to a level of 16.
+% The compiler will expand no further, since this may be a sign that
+% recursion is used.
+scan_w_wrong_styled_switch=02031_W_chaves compilador não são suportadas no estilo de comentário //
+% Compiler switches should be in normal Pascal style comments.
+scan_d_handling_switch=02032_DL_Chave manipulação "$1"
+% When you set debugging info on (\var{-vd}) the compiler tells you when it
+% is evaluating conditional compile statements.
+scan_c_endif_found=02033_CL_ENDIF $1 encontrado
+% When you turn on conditional messages (\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifdef_found=02034_CL_IFDEF $1 encontrado, $2
+% When you turn on conditional messages (\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifopt_found=02035_CL_IFOPT $1 encontrado, $2
+% When you turn on conditional messages (\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_if_found=02036_CL_IF $1 encontrado, $2
+% When you turn on conditional messages (\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifndef_found=02037_CL_IFNDEF $1 encontrado, $2
+% When you turn on conditional messages (\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_else_found=02038_CL_ELSE $1 encontrado, $2
+% When you turn on conditional messages (\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_skipping_until=02039_CL_Pulando até...
+% When you turn on conditional messages (\var{-vc}), the compiler tells you
+% where it encounters conditional statements, and whether it is skipping or
+% compiling parts.
+scan_i_press_enter=02040_I_Tecle <return> para continuar
+% When the \var{-vi} switch is used, the compiler stops compilation
+% and waits for the \var{Enter} key to be pressed when it encounters
+% a \var{\{\$STOP\}} directive.
+scan_w_unsupported_switch=02041_W_Chave não suportada "$1"
+% When warnings are turned on (\var{-vw}), the compiler warns you about
+% unsupported switches. This means that the switch is used in Delphi or
+% Turbo Pascal, but not in \fpc.
+scan_w_illegal_directive=02042_W_Diretiva compilador ilegal "$1"
+% When warnings are turned on (\var{-vw}), the compiler warns you about
+% unrecognised switches. For a list of recognised switches, see the \progref.
+scan_t_back_in=02043_TL_De volta $1
+% When you use the \var{-vt} switch, the compiler tells you when it has finished
+% reading an include file.
+scan_w_unsupported_app_type=02044_W_Tipo aplicação não suportada: "$1"
+% You get this warning if you specify an unknown application type
+% with the directive \var{\{\$APPTYPE\}}.
+scan_w_app_type_not_support=02045_W_APPTYPE não é suportado pelo SO alvo
+% The \var{\{\$APPTYPE\}} directive is supported by certain operating systems only.
+scan_w_description_not_support=02046_W_DESCRIPTION não é suportado pelo SO alvo
+% The \var{\{\$DESCRIPTION\}} directive is not supported on this target OS.
+scan_n_version_not_support=02047_N_VERSION não é suportado pelo SO alvo
+% The \var{\{\$VERSION\}} directive is not supported on this target OS.
+scan_n_only_exe_version=02048_N_VERSION apenas para EXEs ou DLLs
+% The \var{\{\$VERSION\}} directive is only used for executable or DLL sources.
+scan_w_wrong_version_ignored=02049_W_Formato incorreto para a diretiva VERSION "$1"
+% The \var{\{\$VERSION\}} directive format is majorversion.minorversion
+% where majorversion and minorversion are words.
+scan_e_illegal_asmmode_specifier=02050_E_Estilo especificado assembler ilegal "$1"
+% When you specify an assembler mode with the \var{\{\$ASMMODE xxx\}} directive,
+% the compiler didn't recognize the mode you specified.
+scan_w_no_asm_reader_switch_inside_asm=02051_W_ASM reader switch is not possible inside asm statement, "$1" will be effective only for next
+% It is not possible to switch from one assembler reader to another
+% inside an assembler block. The new reader will be used for next
+% assembler statements only.
+scan_e_wrong_switch_toggle=02052_E_Chave alternância incorreta, usar ON/OFF ou +/-
+% You need to use ON or OFF or a + or - to toggle the switch.
+scan_e_resourcefiles_not_supported=02053_E_Arquivo recursos não suportado para este alvo
+% The target you are compiling for doesn't support resource files.
+scan_w_include_env_not_found=02054_W_Variável inclusão ambiente "$1" não encontrado no ambiente
+% The included environment variable can't be found in the environment; it will
+% be replaced by an empty string instead.
+scan_e_invalid_maxfpureg_value=02055_E_Valor ilegal para o registrador limite UPF
+% Valid values for this directive are 0..8 and NORMAL/DEFAULT.
+scan_w_only_one_resourcefile_supported=02056_W_Apenas um arquivo de recursos é suportado para este alvo
+% The target you are compiling for supports only one resource file.
+% The first resource file found is used, the others are discarded.
+scan_w_macro_support_turned_off=02057_W_Suporte Macro foi desativado
+% A macro declaration has been found, but macro support is currently off,
+% so the declaration will be ignored. To turn macro support on compile with
+% -Sm on the command line or add \{\$MACRO ON\} in the source.
+scan_e_invalid_interface_type=02058_E_Tipo ilegal de interface especificado. São válidos COM, CORBA ou DEFAULT.
+% The interface type that was specified is not supported.
+scan_w_appid_not_support=02059_W_APPID é suportado apenas para PalmOS
+% The \var{\{\$APPID\}} directive is only supported for the PalmOS target.
+scan_w_appname_not_support=02060_W_APPNAME é suportado apenas para PalmOS
+% The \var{\{\$APPNAME\}} directive is only supported for the PalmOS target.
+scan_e_string_exceeds_255_chars=02061_E_Constante 'String' não pode ser maior que 255 caracteres
+% A single string constant can contain at most 255 chars. Try splitting up the
+% string into multiple smaller parts and concatenate them with a + operator.
+scan_f_include_deep_ten=02062_F_Incluindo arquivos inclusão excede um nível de 16.
+% When including include files the files have been nested to a level of 16.
+% The compiler will expand no further, since this may be a sign that
+% recursion is used.
+scan_e_too_many_push=02063_F_Muitos níveis de PUSH. Max. 20
+% A maximum of 20 levels is allowed. This error occurs only in mode MacPas.
+scan_e_too_many_pop=02064_E_Um POP sem um PUSH anterior
+% This error occurs only in mode MacPas.
+scan_e_error_macro_lacks_value=02065_E_Macro ou variável tempo compilação "$1" sem nenhum valor
+% Thus the conditional compile time expression cannot be evaluated.
+scan_e_wrong_switch_toggle_default=02066_E_Chave alternância incorreta, usar ON/OFF/DEFAULT ou +/-/*
+% You need to use ON or OFF or DEFAULT or a + or - or * to toggle the switch.
+scan_e_mode_switch_not_allowed=02067_E_Chave modo "$1" não permitida aqui
+% A mode switch has already been encountered, or, in the case of option -Mmacpas,
+% a mode switch occurs after UNIT.
+scan_e_error_macro_undefined=02068_E_Variável tempo compilação ou macro "$1" não definida.
+% Thus the conditional compile time expression cannot be evaluated. Only in mode MacPas.
+scan_e_utf8_bigger_than_65535=02069_E_Código UTF-8 maior que 65535 encontrado
+% \fpc handles UTF-8 strings internally as widestrings, i.e. the char codes are limited to 65535.
+scan_e_utf8_malformed=02070_E_'String' UTF-8 mal-formada
+% The given string isn't a valid UTF-8 string.
+scan_c_switching_to_utf8=02071_C_Assinatura UTF-8 encontrada, usando codificação UTF-8
+% The compiler found a UTF-8 encoding signature (\$ef, \$bb, \$bf) at the beginning of a file,
+% so it interprets it as a UTF-8 file.
+scan_e_compile_time_typeerror=02072_E_Expressão tempo compilação: Procurado $1 mas obtido $2 na $3
+% The type-check of a compile time expression failed.
+scan_n_app_type_not_support=02073_N_APPTYPE não é suportado pelo SO alvo
+% The \var{\{\$APPTYPE\}} directive is supported by certain operating systems only.
+scan_e_illegal_optimization_specifier=02074_E_Otimização especificada ilegal "$1"
+% You specified an optimization with the \var{\{\$OPTIMIZATION xxx\}} directive,
+% and the compiler didn't recognize the optimization you specified.
+scan_w_setpeflags_not_support=02075_W_SETPEFLAGS não é suportado pelo SO alvo
+% The \var{\{\$SETPEFLAGS\}} directive is not supported by the target OS.
+scan_w_imagebase_not_support=02076_W_IMAGEBASE não é suportado pelo SO alvo
+% The \var{\{\$IMAGEBASE\}} directive is not supported by the target OS.
+scan_w_minstacksize_not_support=02077_W_MINSTACKSIZE não é suportado pelo SO alvo
+% The \var{\{\$MINSTACKSIZE\}} directive is not supported by the target OS.
+scan_w_maxstacksize_not_support=02078_W_MAXSTACKSIZE não é suportado pelo SO alvo
+% The \var{\{\$MAXSTACKSIZE\}} directive is not supported by the target OS.
+scanner_e_illegal_warn_state=02079_E_Estado "$1" ilegal para a diretiva $WARN
+% Only ON and OFF can be used as state with a \var{\{\$WARN\}} compiler directive.
+scan_e_only_packset=02080_E_Valor ilegal para conjunto empacotamento
+% Only 0, 1, 2, 4, 8, DEFAULT and NORMAL are allowed as packset parameters.
+scan_w_pic_ignored=02081_W_Diretiva PIC ou chave ignorada
+% Several targets, such as \windows, do not support nor need PIC,
+% so the PIC directive and switch are ignored.
+scan_w_unsupported_switch_by_target=02082_W_A chave "$1" não é suportada pelo alvo selecionado atualmente
+% Some compiler switches like \$E are not supported by all targets.
+scan_w_frameworks_darwin_only=02084_W_Opções relacionadas a "Framework" são apenas suportadas para Darwin/Mac OS X
+% Frameworks are not a known concept, or at least not supported by FPC,
+% on operating systems other than Darwin/Mac OS X.
+scan_e_illegal_minfpconstprec=02085_E_Constante precisão mínima ponto flutuante ilegal "$1"
+% Valid minimal precisions for floating point constants are default, 32 and 64,
+% which mean respectively minimal (usually 32 bit), 32 bit and 64 bit precision.
+scan_w_multiple_main_name_overrides=02086_W_Sobrescrevendo nome do procedimento "main" múltiplas vezes, foi previamente ajustado para "$1"
+% The name for the main entry procedure is specified more than once. Only the last
+% name will be used.
+scanner_w_illegal_warn_identifier=02087_W_Identificador "$1" ilegal para a diretiva $WARN
+% Identifier is not known by a \var{\{\$WARN\}} compiler directive.
+scanner_e_illegal_alignment_directive=02088_E_Diretiva de alinhamento ilegal
+% The alignment directive is not valid. Either the alignment type is not known or the alignment
+% value is not a power of two.
+% \end{description}
+#
+# Parser
+#
+# 03314 is the last used one
+#
+% \section{Parser messages}
+% This section lists all parser messages. The parser takes care of the
+% semantics of you language, i.e. it determines if your Pascal constructs
+% are correct.
+% \begin{description}
+parser_e_syntax_error=03000_E_Analizador - Erro sintaxe
+% An error against the Turbo Pascal language was encountered. This typically
+% happens when an illegal character is found in the source file.
+parser_e_dont_nest_interrupt=03004_E_Procedimento INTERRUPT não pode ser aninhado
+% An \var{INTERRUPT} procedure must be global.
+parser_w_proc_directive_ignored=03005_W_Tipo procedimento "$1" ignorado
+% The specified procedure directive is ignored by FPC programs.
+parser_e_no_overload_for_all_procs=03006_E_Nem todas as declarações de "$1" estão declaradas com OVERLOAD
+% When you want to use overloading using the \var{OVERLOAD} directive, then
+% all declarations need to have \var{OVERLOAD} specified.
+parser_e_export_name_double=03008_E_Nome função exportada duplicada "$1"
+% Exported function names inside a specific DLL must all be different.
+parser_e_export_ordinal_double=03009_E_Ãndice função exportada duplicada $1
+% Exported function indexes inside a specific DLL must all be different.
+parser_e_export_invalid_index=03010_E_índice inválido para função exportada
+% DLL function index must be in the range \var{1..\$FFFF}.
+parser_w_parser_reloc_no_debug=03011_W_Informação depuração DLL relocável ou executável $1 não funciona, desabilitado.
+% It is currently not possible to include debug information in a relocatable DLL.
+parser_w_parser_win32_debug_needs_WN=03012_W_Para permitir depuração para código win32 você necessita desabilitar relocação com opção -WN
+% Stabs debug info is wrong for relocatable DLL or EXES. Use -WN
+% if you want to debug win32 executables.
+parser_e_constructorname_must_be_init=03013_E_Nome Construtor deve ser INIT
+% You are declaring an object constructor with a name which is not \var{init}, and the
+% \var{-Ss} switch is in effect. See the switch \seeo{Ss}.
+parser_e_destructorname_must_be_done=03014_E_Nome Destruidor deve ser DONE
+% You are declaring an object destructor with a name which is not \var{done}, and the
+% \var{-Ss} switch is in effect. See the switch \seeo{Ss}.
+parser_e_proc_inline_not_supported=03016_E_Tipo procedimento INLINE não suportado
+% You tried to compile a program with C++ style inlining, and forgot to
+% specify the \var{-Si} option (\seeo{Si}). The compiler doesn't support C++
+% styled inlining by default.
+parser_w_constructor_should_be_public=03018_W_Construtor deve ser público
+% Constructors must be in the 'public' part of an object (class) declaration.
+parser_w_destructor_should_be_public=03019_W_Destruidor deve ser público
+% Destructors must be in the 'public' part of an object (class) declaration.
+parser_n_only_one_destructor=03020_N_Classe deve ter apenas um destruidor
+% You can declare only one destructor for a class.
+parser_e_no_local_objects=03021_E_Definições classe local não permitidas
+% Classes must be defined globally. They cannot be defined inside a
+% procedure or function.
+parser_f_no_anonym_objects=03022_F_Definições classe anônima não permitidas
+% An invalid object (class) declaration was encountered, i.e. an
+% object or class without methods that isn't derived from another object or
+% class. For example:
+% \begin{verbatim}
+% Type o = object
+% a : longint;
+% end;
+% \end{verbatim}
+% will trigger this error.
+parser_n_object_has_no_vmt=03023_N_O objeto "$1" não tem VMT
+% This is a note indicating that the declared object has no
+% virtual method table.
+parser_e_illegal_parameter_list=03024_E_Lista parâmetros ilegal
+% You are calling a function with parameters that are of a different type than
+% the declared parameters of the function.
+parser_e_wrong_parameter_size=03026_E_Número incorreto de parâmetros especificado para chamada de "$1"
+% There is an error in the parameter list of the function or procedure --
+% the number of parameters is not correct.
+parser_e_overloaded_no_procedure=03027_E_Identificador sobrecarregado "$1" não é uma função
+% The compiler encountered a symbol with the same name as an overloaded
+% function, but it is not a function it can overload.
+parser_e_overloaded_have_same_parameters=03028_E_Funções sobrecarregadas têm a mesma lista de parâmetros
+% You're declaring overloaded functions, but with the same parameter list.
+% Overloaded function must have at least 1 different parameter in their
+% declaration.
+parser_e_header_dont_match_forward=03029_E_Cabeçalho da função não coincide com a declaração anterior de "$1"
+% You declared a function with the same parameters but
+% different result type or function modifiers.
+parser_e_header_different_var_names=03030_E_Cabeçalho função "$1" não coincide com posterior : nome var modifica $2 => $3
+% You declared the function in the \var{interface} part, or with the
+% \var{forward} directive, but defined it with a different parameter list.
+parser_n_duplicate_enum=03031_N_Valores tipo enumeração têm que ser ascendentes
+% \fpc allows enumeration constructions as in C. Examine the following
+% two declarations:
+% \begin{verbatim}
+% type a = (A_A,A_B,A_E:=6,A_UAS:=200);
+% type a = (A_A,A_B,A_E:=6,A_UAS:=4);
+% \end{verbatim}
+% The second declaration would produce an error. \var{A\_UAS} needs to have a
+% value higher than \var{A\_E}, i.e. at least 7.
+parser_e_no_with_for_variable_in_other_segments=03033_E_With não pode ser usado para variáveis em segmentos diferentes
+% With stores a variable locally on the stack,
+% but this is not possible if the variable belongs to another segment.
+parser_e_too_much_lexlevel=03034_E_Aninhamento função > 31
+% You can nest function definitions only 31 levels deep.
+parser_e_range_check_error=03035_E_Erro verificação de faixa enquanto avaliando constantes
+% The constants are out of their allowed range.
+parser_w_range_check_error=03036_W_Erro verificação de faixa enquanto avaliando constantes
+% The constants are out of their allowed range.
+parser_e_double_caselabel=03037_E_Rótulo duplicado declaração "case"
+% You are specifying the same label 2 times in a \var{case} statement.
+parser_e_case_lower_less_than_upper_bound=03038_E_Limite superior da faixa declaração "case" é menor que o limite inferior
+% The upper bound of a \var{case} label is less than the lower bound and this
+% is useless.
+parser_e_type_const_not_possible=03039_E_Constantes tipadas de classes ou interfaces não são permitidas
+% You cannot declare a constant of type class or object.
+parser_e_no_overloaded_procvars=03040_E_Variáveis função de funções sobrecarregadas não são permitidas
+% You are trying to assign an overloaded function to a procedural variable.
+% This is not allowed.
+parser_e_invalid_string_size=03041_E_Comprimento 'String' deve ter valor entre 1 à 255
+% The length of a shortstring in Pascal is limited to 255 characters. You are
+% trying to declare a string with length less than 1 or greater than 255.
+parser_w_use_extended_syntax_for_objects=03042_W_Use sintaxe extendida de NEW e DISPOSE para instanciar objetos
+% If you have a pointer \var{a} to an object type, then the statement
+% \var{new(a)} will not initialize the object (i.e. the constructor isn't
+% called), although space will be allocated. You should issue the
+% \var{new(a,init)} statement. This will allocate space, and call the
+% constructor of the object.
+parser_w_no_new_dispose_on_void_pointers=03043_W_Uso de NEW ou DISPOSE para ponteiros não tipados não tem sentido
+parser_e_no_new_dispose_on_void_pointers=03044_E_Uso de NEW ou DISPOSE não é possível para ponteiros não tipados
+% You cannot use \var{new(p)} or \var{dispose(p)} if \var{p} is an untyped pointer
+% because no size is associated to an untyped pointer.
+% It is accepted for compatibility in \var{TP} and \var{DELPHI} modes, but the
+% compiler will still warn you if it finds such a construct.
+parser_e_class_id_expected=03045_E_Identificador de classe esperado
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., an object or class method, but the type in front of the dot is not
+% a known type.
+parser_e_no_type_not_allowed_here=03046_E_Identificador tipo não permitido aqui
+% You cannot use a type inside an expression.
+parser_e_methode_id_expected=03047_E_Identificador de método esperado
+% This identifier is not a method.
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., an object or class method, but the procedure name is not a
+% procedure of this type.
+parser_e_header_dont_match_any_member=03048_E_Cabeçalho função não coincide com qualquer método desta classe "$1"
+% This identifier is not a method.
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., an object or class method, but the procedure name is not a
+% procedure of this type.
+parser_d_procedure_start=03049_DL_Procedimento/função $1
+% When using the \var{-vd} switch, the compiler tells you when it starts
+% processing a procedure or function implementation.
+parser_e_error_in_real=03050_E_Constante ponto flutuante ilegal
+% The compiler expects a floating point expression, and gets something else.
+parser_e_fail_only_in_constructor=03051_E_FAIL só pode ser usado em contrutores
+% You are using the \var{fail} keyword outside a constructor method.
+parser_e_no_paras_for_destructor=03052_E_Destruidores não podem ter parâmetros
+% You are declaring a destructor with a parameter list. Destructor methods
+% cannot have parameters.
+parser_e_only_class_members_via_class_ref=03053_E_Apenas métodos, propriedades e variáveis de classe podem ser referenciadas por referências classe
+% This error occurs in a situation like the following:
+% \begin{verbatim}
+% Type :
+% Tclass = Class of Tobject;
+%
+% Var C : TClass;
+%
+% begin
+% ...
+% C.free
+% \end{verbatim}
+% \var{Free} is not a class method and hence cannot be called with a class
+% reference.
+parser_e_only_class_members=03054_E_Apenas métodos, propriedades e variáveis de classe podem ser acessadas em métodos de classe
+% This is related to the previous error. You cannot call a method of an object
+% from inside a class method. The following code would produce this error:
+% \begin{verbatim}
+% class procedure tobject.x;
+%
+% begin
+% free
+% \end{verbatim}
+% Because free is a normal method of a class it cannot be called from a class
+% method.
+parser_e_case_mismatch=03055_E_Constante e tipo CASE incompatíveis
+% One of the labels is not of the same type as the case variable.
+parser_e_illegal_symbol_exported=03056_E_Símbolos só podem ser exportados em uma biblioteca
+% You can only export procedures and functions when you write a library. You
+% cannot export variables or constants.
+parser_w_should_use_override=03057_W_Um método herdado é ocultado por "$1"
+% A method that is declared \var{virtual} in a parent class, should be
+% overridden in the descendant class with the \var{override} directive. If you
+% don't specify the \var{override} directive, you will hide the parent method;
+% you will not override it.
+parser_e_nothing_to_be_overridden=03058_E_Não há método na classe ancestral para ser sobreposto: "$1"
+% You are trying to \var{override} a virtual method of a parent class that does
+% not exist.
+parser_e_no_procedure_to_access_property=03059_E_Nenhum membro foi provido para acessar a propriedade
+% You specified no \var{read} directive for a property.
+parser_w_stored_not_implemented=03060_W_Diretiva propriedade armazenamento ainda não foi implementada
+% This message is no longer used, as the \var{stored} directive has been implemented.
+parser_e_ill_property_access_sym=03061_E_Símbolo ilegal para acesso propriedade
+% There is an error in the \var{read} or \var{write} directives for an array
+% property. When you declare an array property, you can only access it with
+% procedures and functions. The following code would cause such an error.
+% \begin{verbatim}
+% tmyobject = class
+% i : integer;
+% property x [i : integer]: integer read I write i;
+% \end{verbatim}
+%
+parser_e_cant_access_protected_member=03062_E_Não é possível acessar um campo protegido de um objeto aqui
+% Fields that are declared in a \var{protected} section of an object or class
+% declaration cannot be accessed outside the module where the object is
+% defined, or outside descendent object methods.
+parser_e_cant_access_private_member=03063_E_Não é possível acessar um campo privado de um objeto aqui
+% Fields that are declared in a \var{private} section of an object or class
+% declaration cannot be accessed outside the module where the class is
+% defined.
+parser_e_overridden_methods_not_same_ret=03066_E_Métodos sobrepostos devem ter o mesmo tipo de retorno: "$2" é sobreposto por "$1" que possui outro tipo retorno
+% If you declare overridden methods in a class definition, they must
+% have the same return type.
+parser_e_dont_nest_export=03067_E_Funções EXPORT declaradas não podem estar aninhadas
+% You cannot declare a function or procedure within a function or procedure
+% that was declared as an export procedure.
+parser_e_methods_dont_be_export=03068_E_Métodos não podem ser EXPORTados
+% You cannot declare a procedure that is a method for an object as
+% \var{export}ed.
+parser_e_call_by_ref_without_typeconv=03069_E_Chamada por var. para arg. no. $1 tem que coincidir exatamente: Obtido "$2" esperado "$3"
+% When calling a function declared with \var{var} parameters, the variables in
+% the function call must be of exactly the same type. There is no automatic
+% type conversion.
+parser_e_no_super_class=03070_E_Classe não é uma classe pai da classe atual
+% When calling inherited methods, you are trying to call a method of a non-related
+% class. You can only call an inherited method of a parent class.
+parser_e_self_not_in_method=03071_E_SELF é permitido apenas em métodos
+% You are trying to use the \var{self} parameter outside an object's method.
+% Only methods get passed the \var{self} parameters.
+parser_e_generic_methods_only_in_methods=03072_E_Métodos só podem estar em outros métodos se chamados diretamente com o identificador de tipo da classe
+% A construction like \var{sometype.somemethod} is only allowed in a method.
+parser_e_illegal_colon_qualifier=03073_E_Uso ilegal de ':'
+% You are using the format \var{:} (colon) 2 times on an expression that
+% is not a real expression.
+parser_e_illegal_set_expr=03074_E_Erro verificação de faixa em conjunto construtor ou elemento conjunto duplicado
+% The declaration of a set contains an error. Either one of the elements is
+% outside the range of the set type, or two of the elements are in fact
+% the same.
+parser_e_pointer_to_class_expected=03075_E_Ponteiro para objeto esperado
+% You specified an illegal type in a \var{new} statement.
+% The extended syntax of \var{new} needs an object as a parameter.
+parser_e_expr_have_to_be_constructor_call=03076_E_Expressão deve ser chamada ao construtor
+% When using the extended syntax of \var{new}, you must specify the constructor
+% method of the object you are trying to create. The procedure you specified
+% is not a constructor.
+parser_e_expr_have_to_be_destructor_call=03077_E_Expressão deve ser chamada ao destruidor
+% When using the extended syntax of \var{dispose}, you must specify the
+% destructor method of the object you are trying to dispose of.
+% The procedure you specified is not a destructor.
+parser_e_invalid_record_const=03078_E_Ordem ilegal dos elementos do registro
+% When declaring a constant record, you specified the fields in the wrong
+% order.
+parser_e_false_with_expr=03079_E_Tipo expressão deve ser classe ou tipo registro
+% A \var{with} statement needs an argument that is of the type \var{record}
+% or \var{class}. You are using \var{with} on an expression that is not of
+% this type.
+parser_e_void_function=03080_E_Procedimentos não podem retornar um valor
+% In \fpc, you can specify a return value for a function when using
+% the \var{exit} statement. This error occurs when you try to do this with a
+% procedure. Procedures cannot return a value.
+parser_e_constructors_always_objects=03081_E_Construtores, destruidores e operadores de classe devem ser métodos
+% You're declaring a procedure as destructor, constructor or class operator, when the
+% procedure isn't a class method.
+parser_e_operator_not_overloaded=03082_E_Operador não é sobrecarregado
+% You're trying to use an overloaded operator when it is not overloaded for
+% this type.
+parser_e_no_such_assignment=03083_E_Impossível sobrecarregar atribuições para tipos iguais
+% You cannot overload assignment for types
+% that the compiler considers as equal.
+parser_e_overload_impossible=03084_E_Operador sobrecarga impossível
+% The combination of operator, arguments and return type are
+% incompatible.
+parser_e_no_reraise_possible=03085_E_Re-elevar não é possível lá
+% You are trying to re-raise an exception where it is not allowed. You can only
+% re-raise exceptions in an \var{except} block.
+parser_e_no_new_or_dispose_for_classes=03086_E_A sintaxe estendida para new ou dispose não é permitida para uma classe
+% You cannot generate an instance of a class with the extended syntax of
+% \var{new}. The constructor must be used for that. For the same reason, you
+% cannot call \var{dispose} to de-allocate an instance of a class, the
+% destructor must be used for that.
+parser_e_procedure_overloading_is_off=03088_E_Sobrecarga de procimento está desativada
+% When using the \var{-So} switch, procedure overloading is switched off.
+% Turbo Pascal does not support function overloading.
+parser_e_overload_operator_failed=03089_E_Não é possível sobrecarregar este operador. Operadores relacionados possíveis de sobrecarga (se algum) são: $1
+% You are trying to overload an operator which cannot be overloaded.
+% The following operators can be overloaded :
+% \begin{verbatim}
+% +, -, *, /, =, >, <, <=, >=, is, as, in, **, :=
+% \end{verbatim}
+parser_e_comparative_operator_return_boolean=03090_E_Operador de comparação deve retornar um valor booleano
+% When overloading the \var{=} operator, the function must return a boolean
+% value.
+parser_e_only_virtual_methods_abstract=03091_E_Apenas métodos virtuais podem ser abstratos
+% You are declaring a method as abstract, when it is not declared to be
+% virtual.
+parser_f_unsupported_feature=03092_F_Uso de característica não suportada!
+% You're trying to force the compiler into doing something it cannot do yet.
+parser_e_mix_of_classes_and_objects=03093_E_A mistura de diferentes espécies de objetos (class, object, interface, etc) não é permitida
+% You cannot derive \var{objects}, \var{classes}, \var{cppclasses} and \var{interfaces} intertwined. E.g.
+% a class cannot have an object as parent and vice versa.
+parser_w_unknown_proc_directive_ignored=03094_W_Diretiva desconhecida de procedimento teve que ser ignorada: "$1"
+% The procedure directive you specified is unknown.
+parser_e_absolute_only_one_var=03095_E_Absolute só pode estar associada a uma variável
+% You cannot specify more than one variable before the \var{absolute} directive.
+% Thus, the following construct will provide this error:
+% \begin{verbatim}
+% Var Z : Longint;
+% X,Y : Longint absolute Z;
+% \end{verbatim}
+parser_e_absolute_only_to_var_or_const=03096_E_Absolute só pode estar associada com uma variável ou constante
+% The address of an \var{absolute} directive can only point to a variable or
+% constant. Therefore, the following code will produce this error:
+% \begin{verbatim}
+% Procedure X;
+%
+% var p : longint absolute x;
+% \end{verbatim}
+parser_e_initialized_only_one_var=03097_E_Apenas uma variável pode ser inicializada
+% You cannot specify more than one variable with a initial value in Delphi mode.
+parser_e_abstract_no_definition=03098_E_Métodos abstratos não devem ter qualquer definição (com corpo função)
+% Abstract methods can only be declared, you cannot implement them. They
+% should be overridden by a descendant class.
+parser_e_overloaded_must_be_all_global=03099_E_Esta função sobrecarregada não pode ser local (deve ser exportada)
+% You are defining an overloaded function in the implementation part of a unit,
+% but there is no corresponding declaration in the interface part of the unit.
+parser_w_virtual_without_constructor=03100_W_Métodos virtuais são usados sem um construtor em "$1"
+% If you declare objects or classes that contain virtual methods, you need
+% to have a constructor and destructor to initialize them. The compiler
+% encountered an object or class with virtual methods that doesn't have
+% a constructor/destructor pair.
+parser_c_macro_defined=03101_CL_Macro definida: $1
+% When \var{-vc} is used, the compiler tells you when it defines macros.
+parser_c_macro_undefined=03102_CL_Macro indefinida: $1
+% When \var{-vc} is used, the compiler tells you when it undefines macros.
+parser_c_macro_set_to=03103_CL_Macro $1 ajustada para $2
+% When \var{-vc} is used, the compiler tells you what values macros get.
+parser_i_compiling=03104_I_Compilando $1
+% When you turn on information messages (\var{-vi}), the compiler tells you
+% what units it is recompiling.
+parser_u_parsing_interface=03105_UL_Analisando interface da unidade $1
+% This tells you that the reading of the interface
+% of the current unit has started
+parser_u_parsing_implementation=03106_UL_Analisando implementação de $1
+% This tells you that the code reading of the implementation
+% of the current unit, library or program starts
+parser_d_compiling_second_time=03107_DL_Compilando $1 uma segunda vez
+% When you request debug messages (\var{-vd}) the compiler tells you what
+% units it recompiles for the second time.
+parser_e_no_property_found_to_override=03109_E_Nenhuma propriedade encontrada para sobrepor
+% You want to override a property of a parent class, when there is, in fact,
+% no such property in the parent class.
+parser_e_only_one_default_property=03110_E_Apenas uma propriedade padrão é permitida
+% You specified a property as \var{Default}, but the class already has a
+% default property, and a class can have only one default property.
+parser_e_property_need_paras=03111_E_A propriedade padrão deve ser uma propriedade matriz
+% Only array properties of classes can be made \var{default} properties.
+parser_e_constructor_cannot_be_not_virtual=03112_E_Construtores virtuais são suportados apenas modelo objeto classe
+% You cannot have virtual constructors in objects. You can only have them
+% in classes.
+parser_e_no_default_property_available=03113_E_Nenhuma propriedade padrão disponível
+% You are trying to access a default property of a class, but this class (or one of
+% its ancestors) doesn't have a default property.
+parser_e_cant_have_published=03114_E_A classe não pode ter uma seção PUBLISHED, use a chave {$M+}
+% If you want a \var{published} section in a class definition, you must
+% use the \var{\{\$M+\}} switch, which turns on generation of type
+% information.
+parser_e_forward_declaration_must_be_resolved=03115_E_Declaração posterior da classe "$1" deve ser resolvida aqui para usar a classe como ancestral
+% To be able to use an object as an ancestor object, it must be defined
+% first. This error occurs in the following situation:
+% \begin{verbatim}
+% Type ParentClas = Class;
+% ChildClass = Class(ParentClass)
+% ...
+% end;
+% \end{verbatim}
+% where \var{ParentClass} is declared but not defined.
+parser_e_no_local_operator=03116_E_Operadores locais não suportados
+% You cannot overload locally, i.e. inside procedures or function
+% definitions.
+parser_e_proc_dir_not_allowed_in_interface=03117_E_Diretiva procedimento "$1" não permitida na seção interface
+% This procedure directive is not allowed in the \var{interface} section of
+% a unit. You can only use it in the \var{implementation} section.
+parser_e_proc_dir_not_allowed_in_implementation=03118_E_Diretiva procedimento "$1" não permitida na seção implementação
+% This procedure directive is not allowed in the \var{implementation} section of
+% a unit. You can only use it in the \var{interface} section.
+parser_e_proc_dir_not_allowed_in_procvar=03119_E_Diretiva procedimento "$1" não permitida na declaração procvar
+% This procedure directive cannot be part of a procedural or function
+% type declaration.
+parser_e_function_already_declared_public_forward=03120_E_Função já declarada como Pública/Posterior "$1"
+% You will get this error if a function is defined as \var{forward} twice.
+% Or if it occurs in the \var{interface} section, and again as a \var{forward}
+% declaration in the \var{implementation} section.
+parser_e_not_external_and_export=03121_E_Impossível usar ambos EXPORT e EXTERNAL
+% These two procedure directives are mutually exclusive.
+parser_w_not_supported_for_inline=03123_W_"$1" não suportado ainda dentro procedimento/função em linha
+% Inline procedures don't support this declaration.
+parser_w_inlining_disabled=03124_W_Procedimentos em linha desabilitados
+% Inlining of procedures is disabled.
+parser_i_writing_browser_log=03125_I_Gravando histório Navegador $1
+% When information messages are on, the compiler warns you when it
+% writes the browser log (generated with the \var{\{\$Y+ \}} switch).
+parser_h_maybe_deref_caret_missing=03126_H_Talvez desreferência de ponteiro esteja faltando
+% The compiler thinks that a pointer may need a dereference.
+parser_f_assembler_reader_not_supported=03127_F_Leitor assembler selecionado não suportado
+% The selected assembler reader (with \var{\{\$ASMMODE xxx\}} is not
+% supported. The compiler can be compiled with or without support for a
+% particular assembler reader.
+parser_e_proc_dir_conflict=03128_E_Diretiva procedimento "$1" tem conflitos com outras diretivas
+% You specified a procedure directive that conflicts with other directives.
+% For instance \var{cdecl} and \var{pascal} are mutually exclusive.
+parser_e_call_convention_dont_match_forward=03129_E_Convenção de chamada não coincide com declaração posterior
+% This error happens when you declare a function or procedure with
+% e.g. \var{cdecl;} but omit this directive in the implementation, or vice
+% versa. The calling convention is part of the function declaration, and
+% must be repeated in the function definition.
+parser_e_property_cant_have_a_default_value=03131_E_Propriedade não pode ter um valor padrão
+% Set properties or indexed properties cannot have a default value.
+parser_e_property_default_value_must_const=03132_E_O valor padrão de um propriedade deve ser uma constante
+% The value of a \var{default} declared property must be known at compile
+% time. The value you specified is only known at run time. This happens
+% e.g. if you specify a variable name as a default value.
+parser_e_cant_publish_that=03133_E_Símbolo não pode ser PUBLISHED, pode ser apenas uma classe
+% Only class type variables can be in a \var{published} section of a class
+% if they are not declared as a property.
+parser_e_cant_publish_that_property=03134_E_Este tipo de propriedade não pode ser PUBLISHED
+% Properties in a \var{published} section cannot be array properties.
+% They must be moved to public sections. Properties in a \var{published}
+% section must be an ordinal type, a real type, strings or sets.
+parser_e_empty_import_name=03136_E_Um nome importação é requerido
+% Some targets need a name for the imported procedure or a \var{cdecl} specifier.
+parser_e_division_by_zero=03138_E_Divisão por zero
+% A division by zero was encounted.
+parser_e_invalid_float_operation=03139_E_Operação ponto flutuante inválida
+% An operation on two real type values produced an overflow or a division
+% by zero.
+parser_e_array_lower_less_than_upper_bound=03140_E_Limite superior da faixa é menor que o limite inferior
+% The upper bound of an array declaration is less than the lower bound and this
+% is not possible.
+parser_w_string_too_long=03141_W_'String' "$1" é maior que "$2"
+% The size of the constant string is larger than the size you specified in
+% string type definition.
+parser_e_string_larger_array=03142_E_Comprimento 'String' é maior que o comprimento da matriz de caractere
+% The size of the constant string is larger than the size you specified in
+% the \var{Array[x..y] of char} definition.
+parser_e_ill_msg_expr=03143_E_Expressão ilegal após diretiva mensagem
+% \fpc supports only integer or string values as message constants.
+parser_e_ill_msg_param=03144_E_Manipuladores mensagens podem ter apenas uma chamada por parâmetro referência
+% A method declared with the \var{message} directive as message handler
+% can take only one parameter which must be declared as call by reference.
+% Parameters are declared as call by reference using the \var{var}-directive.
+parser_e_duplicate_message_label=03145_E_Rótulo mensagem duplicado: "$1"
+% A label for a message is used twice in one object/class.
+parser_e_self_in_non_message_handler=03146_E_Self pode ser um parâmetro explícito apenas em métodos que são manipuladores de mensagens
+% The \var{Self} parameter can only be passed explicitly to a method which
+% is declared as message handler.
+parser_e_threadvars_only_sg=03147_E_Threadvars podem ser apenas estáticas ou globais
+% Threadvars must be static or global; you can't declare a thread
+% local to a procedure. Local variables are always local to a thread,
+% because every thread has its own stack and local variables
+% are stored on the stack.
+parser_f_direct_assembler_not_allowed=03148_F_Assembler direto não suportado para formato de saída binário
+% You can't use direct assembler when using a binary writer. Choose an
+% other output format or use another assembler reader.
+parser_w_no_objpas_use_mode=03149_W_Não carregue a unidade OBJPAS manualmente, use \{\$mode objfpc\} ou \{\$mode delphi\}
+% You are trying to load the \file{ObjPas} unit manually from a \var{uses} clause.
+% This is not a good idea. Use the \var{\{\$MODE OBJFPC\}} or
+% \var{\{\$mode delphi\}} directives which load the unit automatically.
+parser_e_no_object_override=03150_E_OVERRIDE não pode ser usado em objetos
+% \var{Override} is not supported for objects, use \var{virtual} instead to override
+% a method of a parent object.
+parser_e_cant_use_inittable_here=03151_E_Tipos de dados que requerem inicialização/finalização não podem ser usados em registros variant
+% Some data types (e.g. \var{ansistring}) need initialization/finalization
+% code which is implicitly generated by the compiler. Such data types
+% can't be used in the variant part of a record.
+parser_e_resourcestring_only_sg=03152_E_Recursos 'String' podem ser apenas estáticos ou globais
+% Resourcestring cannot be declared local, only global or using the static
+% directive.
+parser_e_exit_with_argument_not__possible=03153_E_EXIT com argumentos não pode ser usado aqui
+% An exit statement with an argument for the return value can't be used here. This
+% can happen for example in \var{try..except} or \var{try..finally} blocks.
+parser_e_stored_property_must_be_boolean=03154_E_O tipo do símbolo de armazenamento deve ser booleano
+% If you specify a storage symbol in a property declaration, it must be a
+% boolean type.
+parser_e_ill_property_storage_sym=03155_E_Este símbolo não é permitido como símbolo de armazenamento
+% You can't use this type of symbol as storage specifier in property
+% declaration. You can use only methods with the result type boolean,
+% boolean class fields or boolean constants.
+parser_e_only_publishable_classes_can_be_published=03156_E_Apenas classes que são compiladas no modo $M+ podem ser PUBLISHED
+% A class-typed field in the published section of a class can only be a class which was
+% compiled in \var{\{\$M+\}} or which is derived from such a class. Normally
+% such a class should be derived from \var{TPersistent}.
+parser_e_proc_directive_expected=03157_E_Diretiva procedimento esperada
+% This error is triggered when you have a \var{\{\$Calling\}} directive without
+% a calling convention specified.
+% It also happens when declaring a procedure in a const block and you
+% used a ; after a procedure declaration which must be followed by a
+% procedure directive.
+% Correct declarations are:
+% \begin{verbatim}
+% const
+% p : procedure;stdcall=nil;
+% p : procedure stdcall=nil;
+% \end{verbatim}
+parser_e_invalid_property_index_value=03158_E_O valor de um índice de propriedade deve ser do tipo ordinal
+% The value you use to index a property must be of an ordinal type, for
+% example an integer or enumerated type.
+parser_e_procname_to_short_for_export=03159_E_Nome procedimento muito curto para ser exportado
+% The length of the procedure/function name must be at least 2 characters
+% long. This is because of a bug in dlltool which doesn't parse the .def
+% file correctly with a name of length 1.
+parser_e_dlltool_unit_var_problem=03160_E_Nenhuma entrada DEFFILE pode ser gerada para vars. globais unidade
+parser_e_dlltool_unit_var_problem2=03161_E_Compile sem a opção -WD
+% You need to compile this file without the -WD switch on the
+% command line.
+parser_f_need_objfpc_or_delphi_mode=03162_F_Você precisa do modo ObjFpc (-S2) ou Delphi (-Sd) para compilar este módulo
+% You need to use \var{\{\$MODE OBJFPC\}} or \var{\{\$MODE DELPHI\}} to compile this file.
+% Or use the corresponding command line switch, either \var{-Mobjfpc} or \var{-MDelphi.}
+parser_e_no_export_with_index_for_target=03163_E_Impossível exportar com índice sob $1
+% Exporting of functions or procedures with a specified index is not
+% supported on this target.
+parser_e_no_export_of_variables_for_target=03164_E_Exportação de variáveis não é suportada sob $1
+% Exporting of variables is not supported on this target.
+parser_e_improper_guid_syntax=03165_E_Sintaxe GUID imprópria
+% The GUID indication does not have the proper syntax. It should be of the form
+% \begin{verbatim}
+% {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}
+% \end{verbatim}
+% Where each \var{X} represents a hexadecimal digit.
+parser_w_interface_mapping_notfound=03168_W_Procedimento chamado "$1" que fosse adequado à implementação de $2.$3 não encontrado
+% The compiler cannot find a suitable procedure which implements the given method of an interface.
+% A procedure with the same name is found, but the arguments do not match.
+parser_e_interface_id_expected=03169_E_Identificador interface esperado
+% This happens when the compiler scans a \var{class} declaration that contains
+% \var{interface} function name mapping code like this:
+% \begin{verbatim}
+% type
+% TMyObject = class(TObject, IDispatch)
+% function IUnknown.QueryInterface=MyQueryInterface;
+% ....
+% \end{verbatim}
+% and the \var{interface} before the dot is not listed in the inheritance list.
+parser_e_type_cant_be_used_in_array_index=03170_E_Tipo "$1" não pode ser usado como tipo índice matriz
+% Types like \var{qword} or \var{int64} aren't allowed as array index type.
+parser_e_no_con_des_in_interfaces=03171_E_Construtor e destruidor não permitidos em interfaces
+% Constructor and destructor declarations aren't allowed in interfaces.
+% In the most cases method \var{QueryInterface} of \var{IUnknown} can
+% be used to create a new interface.
+parser_e_no_access_specifier_in_interfaces=03172_E_Especificadores de acesso não podem ser usados em INTERFACEs e OBJCPROTOCOLs
+% The access specifiers \var{public}, \var{private}, \var{protected} and
+% \var{published} can't be used in interfaces, Objective-C protocols and categories because all methods
+% of an interface/protocol/category must be public.
+parser_e_no_vars_in_interfaces=03173_E_Uma interface, auxiliar ou protocolo Objective-C ou categoria não pode conter campos
+% Declarations of fields are not allowed in interfaces, helpers and Objective-C protocols and categories.
+% An interface/protocol/category can contain only methods and properties with method read/write specifiers.
+parser_e_no_local_proc_external=03174_E_Impossíve declarar procedimento local como EXTERNAL
+% Declaring local procedures as external is not possible. Local procedures
+% get hidden parameters that will make the chance of errors very high.
+parser_w_skipped_fields_before=03175_W_Alguns campos que vêm antes de "$1" não foram inicializados
+% In Delphi mode, not all fields of a typed constant record have to be
+% initialized, but the compiler warns you when it detects such situations.
+parser_e_skipped_fields_before=03176_E_Alguns campos que vêm antes de "$1" não foram inicializados
+% In all syntax modes but Delphi mode, you can't leave some fields uninitialized
+% in the middle of a typed constant record.
+parser_w_skipped_fields_after=03177_W_Alguns campos que vêm depois de "$1" não foram inicializados
+% You can leave some fields at the end of a type constant record uninitialized
+% (The compiler will initialize them to zero automatically). This may be the cause
+% of subtle problems.
+parser_e_varargs_need_cdecl_and_external=03178_E_Diretiva VarArgs (ou '...' em MacPas) sem CDecl/CPPDecl/MWPascal e External
+% The varargs directive (or the ``...'' varargs parameter in MacPas mode) can only be
+% used with procedures or functions that are declared with \var{external} and one of
+% \var{cdecl}, \var{cppdecl} and \var{mwpascal}. This functionality
+% is only supported to provide a compatible interface to C functions like printf.
+parser_e_self_call_by_value=03179_E_Self deve ser um parâmetro normal (chamada-por-valor)
+% You can't declare \var{Self} as a const or var parameter, it must always be
+% a call-by-value parameter.
+parser_e_interface_has_no_guid=03180_E_Interface "$1" não tem identificação de interface
+% When you want to assign an interface to a constant, then the interface
+% must have a GUID value set.
+parser_e_illegal_field_or_method=03181_E_Campo classe ou identificador método "$1" desconhecido
+% Properties must refer to a field or method in the same class.
+parser_w_proc_overriding_calling=03182_W_Convenção chamada sobreposição "$1" com "$2"
+% There are two directives in the procedure declaration that specify a calling
+% convention. Only the last directive will be used.
+parser_e_no_procvarobj_const=03183_E_Constantes tipadas do tipo "procedimento de objeto" podem ser apenas inicializadas com NIL
+% You cannot assign the address of a method to a typed constant which has a
+% 'procedure of object' type, because such a constant requires two addresses:
+% that of the method (which is known at compile time) and that of the object or
+% class instance it operates on (which cannot be known at compile time).
+parser_e_default_value_only_one_para=03184_E_Valor padrão pode ser atribuído apenas à um parâmetro
+% It is not possible to specify a default value for several parameters at once.
+% The following is invalid:
+% \begin{verbatim}
+% Procedure MyProcedure (A,B : Integer = 0);
+% \end{verbatim}
+% Instead, this should be declared as
+% \begin{verbatim}
+% Procedure MyProcedure (A : Integer = 0; B : Integer = 0);
+% \end{verbatim}
+parser_e_default_value_expected_for_para=03185_E_Parâmetro padrão requerido para "$1"
+% The specified parameter requires a default value.
+parser_w_unsupported_feature=03186_W_Uso de característica não suportada!
+% You're trying to force the compiler into doing something it cannot do yet.
+parser_h_c_arrays_are_references=03187_H_Matrizes C são passadas por referência
+% Any array passed to a C function is passed
+% by a pointer (i.e. by reference).
+parser_e_C_array_of_const_must_be_last=03188_E_Matrizes de constantes C devem ser o último argumento
+% You cannot add any other argument after an \var{array of const} for
+% \var{cdecl} functions, as the size pushed on stack for this argument is
+% not known.
+parser_h_type_redef=03189_H_Redefinição do tipo "$1"
+% This is an indicator that a previously declared type is
+% being redefined as something else. This may, or may not
+% be, a potential source of errors.
+parser_w_cdecl_has_no_high=03190_W_Funções declaradas com cdecl não tem um parâmetro implícito extra
+% Functions declared with the \var{cdecl} modifier do not pass an extra implicit parameter.
+parser_w_cdecl_no_openstring=03191_W_Funções declaradas com cdecl não suportam 'String' aberta
+% Openstring is not supported for functions that have the \var{cdecl} modifier.
+parser_e_initialized_not_for_threadvar=03192_E_Impossível inicializar variáveis declaradas como threadvar
+% Variables declared as threadvar cannot be initialized with a default value.
+% The variables will always be filled with zero at the start of a new thread.
+parser_e_msg_only_for_classes=03193_E_Diretiva mensagem é permitida apenas em Classes
+% The message directive is only supported for Class types.
+parser_e_procedure_or_function_expected=03194_E_Procedimento ou Função esperados
+% A class method can only be specified for procedures and functions.
+parser_e_illegal_calling_convention=03195_W_Diretiva convenção de chamada ignorada: "$1"
+% Some calling conventions are supported only by certain CPUs. I.e. most non-i386 ports support
+% only the standard ABI calling convention of the CPU.
+parser_e_no_object_reintroduce=03196_E_REINTRODUCE não pode ser usado em objetos
+% \var{reintroduce} is not supported for objects, Objective-C classes and Objective-C protocols.
+parser_e_paraloc_only_one_para=03197_E_Cada argumento deve ter sua própria localização
+% If locations for arguments are specified explicitly as it is required by
+% some syscall conventions, each argument must have its own location. Things
+% like
+% \begin{verbatim}
+% procedure p(i,j : longint 'r1');
+% \end{verbatim}
+% aren't allowed.
+parser_e_paraloc_all_paras=03198_E_Cada argumento deve ter uma localização explícita
+% If one argument has an explicit argument location, all arguments of a procedure
+% must have one.
+parser_e_illegal_explicit_paraloc=03199_E_Localização argumento desconhecida
+% The location specified for an argument isn't recognized by the compiler.
+parser_e_32bitint_or_pointer_variable_expected=03200_E_Inteiro 32-Bit ou variável ponteiro esperados
+% The libbase for MorphOS/AmigaOS can be given only as \var{longint}, \var{dword} or any pointer variable.
+parser_e_goto_outside_proc=03201_E_Declaração Goto não permitida entre procedimentos diferentes
+% It isn't allowed to use \var{goto} statements referencing labels outside the
+% current procedure. The following example shows the problem:
+% \begin{verbatim}
+% ...
+% procedure p1;
+% label
+% l1;
+%
+% procedure p2;
+% begin
+% goto l1; // This goto ISN'T allowed
+% end;
+%
+% begin
+% p2
+% l1:
+% end;
+% ...
+%
+% \end{verbatim}
+parser_f_too_complex_proc=03202_F_Procedimento muito complexo, ele requer muitos registradores
+% Your procedure body is too long for the compiler. You should split the
+% procedure into multiple smaller procedures.
+parser_e_illegal_expression=03203_E_Expressão ilegal
+% This can occur under many circumstances. Usually when trying to evaluate
+% constant expressions.
+parser_e_invalid_integer=03204_E_Expressão inteira inválida
+% You made an expression which isn't an integer, and the compiler expects the
+% result to be an integer.
+parser_e_invalid_qualifier=03205_E_Qualifiador ilegal
+% One of the following is happening :
+% \begin{itemize}
+% \item You're trying to access a field of a variable that is not a record.
+% \item You're indexing a variable that is not an array.
+% \item You're dereferencing a variable that is not a pointer.
+% \end{itemize}
+parser_e_upper_lower_than_lower=03206_E_Limite de faixa alta < limite de faixa baixa
+% You are declaring a subrange, and the high limit is less than the low limit of
+% the range.
+parser_e_macpas_exit_wrong_param=03207_E_Parâmetro de saída deve ser o nome do procedimento em que ele é usado
+% Non local exit is not allowed. This error occurs only in mode MacPas.
+parser_e_illegal_assignment_to_count_var=03208_E_Atribuição ilegal para a variável for-loop "$1"
+% The type of a \var{for} loop variable must be an ordinal type.
+% Loop variables cannot be reals or strings. You also cannot assign values to
+% loop variables inside the loop (Except in Delphi and TP modes). Use a while or
+% repeat loop instead if you need to do something like that, since those
+% constructs were built for that.
+parser_e_no_local_var_external=03209_E_Impossível declarar variável local como EXTERNAL
+% Declaring local variables as external is not allowed. Only global variables can reference
+% external variables.
+parser_e_proc_already_external=03210_E_Procedimento já foi declarado como EXTERNAL
+% The procedure is already declared with the EXTERNAL directive in an interface or
+% forward declaration.
+parser_w_implicit_uses_of_variants_unit=03211_W_Uso implícito da unidade Variants
+% The Variant type is used in the unit without any used unit using the Variants unit. The
+% compiler has implicitly added the Variants unit to the uses list. To remove this warning
+% the Variants unit needs to be added to the uses statement.
+parser_e_no_static_method_in_interfaces=03212_E_Classe e métodos estáticos não podem ser usados em INTERFACES
+% The specifier \var{class} and directive \var{static} can't be used in interfaces
+% because all methods of an interface must be public.
+parser_e_arithmetic_operation_overflow=03213_E_Transbordamento em operação aritimética
+% An operation on two integer values produced an overflow.
+parser_e_protected_or_private_expected=03214_E_Protected ou private esperados
+% \var{strict} can be only used together with \var{protected} or \var{private}.
+parser_e_illegal_slice=03215_E_SLICE não pode ser usado fora da lista de parâmetros
+% \var{slice} can be used only for arguments accepting an open array parameter.
+parser_e_dispinterface_cant_have_parent=03216_E_Uma DISPINTERFACE não pode ter uma classe pai
+% A DISPINTERFACE is a special type of interface which can't have a parent class. Dispinterface always derive from IDispatch type.
+parser_e_dispinterface_needs_a_guid=03217_E_Uma DISPINTERFACE necessita de um GUID
+% A DISPINTERFACE always needs an interface identification (a GUID).
+parser_w_overridden_methods_not_same_ret=03218_W_Métodos susbtituídos devem ter um tipo de retorno relacionados. Este código pode travar, ele depende de uma falha do analizador Delphi ("$2" é sobreposto por "$1" que possue outro tipo de retorno)
+% If you declare overridden methods in a class definition, they must
+% have the same return type. Some versions of Delphi allow you to change the
+% return type of interface methods, and even to change procedures into
+% functions, but the resulting code may crash depending on the types used
+% and the way the methods are called.
+parser_e_dispid_must_be_ord_const=03219_E_IDs despacho devem ser constantes ordinais
+% The \var{dispid} keyword must be followed by an ordinal constant (the dispid index).
+parser_e_array_range_out_of_bounds=03220_E_A faixa da matriz é demasiada grande
+% Regardless of the size taken up by its elements, an array cannot have more
+% than high(ptrint) elements. Additionally, the range type must be a subrange
+% of ptrint.
+parser_e_packed_element_no_var_addr=03221_E_O endereço não pode ser obtido de elementos de matriz de bits compactados ou campos de registro
+% If you declare an array or record as \var{packed} in Mac Pascal mode
+% (or as \var{packed} in any mode with \var{\{\$bitpacking on\}}), it will
+% be packed at the bit level. This means it becomes impossible to take addresses
+% of individual array elements or record fields. The only exception to this rule
+% is in the case of packed arrays elements whose packed size is a multple of 8 bits.
+parser_e_packed_dynamic_open_array=03222_E_Matrizes dinâmicas não podem ser compactadas
+% Only regular (and possibly in the future also open) arrays can be packed.
+parser_e_packed_element_no_loop=03223_E_Elementos de matrizes de bits compactados ou campos de registro não podem ser usadas como variáveis de laços
+% If you declare an array or record as \var{packed} in Mac Pascal mode
+% (or as \var{packed} in any mode with \var{\{\$bitpacking on\}}), it will
+% be packed at the bit level. For performance reasons, they cannot be
+% used as loop variables.
+parser_e_type_var_const_only_in_records_and_classes=03224_E_VAR, TYPE e CONST são permitidos apenas em registros, objetos e classes
+% The usage of VAR, TYPE and CONST to declare new types inside an object is allowed only inside
+% records, objects and classes.
+parser_e_cant_create_generics_of_this_type=03225_E_Este tipo não pode ser um genérico
+% Only Classes, Objects, Interfaces and Records are allowed to be used as generic.
+parser_w_no_lineinfo_use_switch=03226_W_Não caregue a unidade LINEINFO manualmente, Em vez disso utilize a chave de compilador -gl
+% Do not use the \file{lineinfo} unit directly, Use the \var{-gl} switch which
+% automatically adds the correct unit for reading the selected type of debugging
+% information. The unit that needs to be used depends on the type of
+% debug information used when compiling the binary.
+parser_e_no_funcret_specified=03227_E_Nenhum tipo de retorno de função especificado para a função "$1"
+% The first time you declare a function you have to declare it completely,
+% including all parameters and the result type.
+parser_e_special_onlygenerics=03228_E_Especialização é suportado apenas por tipos genéricos
+% Types which are not generics can't be specialized.
+parser_e_no_generics_as_params=03229_E_Genéricos não podem ser usados como parâmetros quando especializando genéricos
+% When specializing a generic, only non-generic types can be used as parameters.
+parser_e_type_object_constants=03230_E_Constantes de objetos contendo uma VMT não são permitidas
+% If an object requires a VMT either because it contains a constructor or virtual methods,
+% it's not allowed to create constants of it. In TP and Delphi mode this is allowed
+% for compatibility reasons.
+parser_e_label_outside_proc=03231_E_Obter o endereço de rótulos definidos fora do escopo atual não é permitido
+% It isn't allowed to take the address of labels outside the
+% current procedure.
+parser_e_initialized_not_for_external=03233_E_Impossível inicializar variáveis declaradas como externas
+% Variables declared as external cannot be initialized with a default value.
+parser_e_illegal_function_result=03234_E_Tipo de retorno de função ilegal
+% Some types like file types cannot be used as function result.
+parser_e_no_common_type=03235_E_Nenhum tipo comum entre "$1" e "$2"
+% To perform an operation on integers, the compiler converts both operands
+% to their common type, which appears to be an invalid type. To determine the
+% common type of the operands, the compiler takes the minimum of the minimal values
+% of both types, and the maximum of the maximal values of both types. The common
+% type is then minimum..maximum.
+parser_e_no_generics_as_types=03236_E_Genéricos sem especialização não podem ser usadas como um tipo para uma variável
+% Generics must be always specialized before being used as variable type.
+parser_w_register_list_ignored=03237_W_Lista registros é ignorada para rotinas assembler puras
+% When using pure assembler routines, the list with modified registers is ignored.
+parser_e_implements_must_be_class_or_interface=03238_E_Propriedade 'Implements' deve ter tipo classe ou interface
+% A property which implements an interface must be of type class or interface.
+parser_e_implements_must_have_correct_type=03239_E_Propriedade 'Implements' deve implementar interface de tipo correto, encontrado "$1" esperado "$2"
+% A property which implements an interface actually implements a different interface.
+parser_e_implements_must_read_specifier=03240_E_Propriedade 'Implements' deve ter especificador de leitura
+% A property which implements an interface must have at least a read specifier.
+parser_e_implements_must_not_have_write_specifier=03241_E_Propriedade 'Implements' não deve ter especificador de escrita
+% A property which implements an interface may not have a write specifier.
+parser_e_implements_must_not_have_stored_specifier=03242_E_Propriedade 'Implements' não deve ter especificador de armazenagem
+% A property which implements an interface may not have a stored specifier.
+parser_e_implements_uses_non_implemented_interface=03243_E_Propriedade 'Implements' usada em interface não implementada: "$1"
+% The interface which is implemented by a property is not an interface implemented by the class.
+parser_e_unsupported_real=03244_E_Ponto flutuante não suportado para este alvo
+% The compiler parsed a floating point expression, but it is not supported.
+parser_e_class_doesnt_implement_interface=03245_E_Classe "$1" não implementa interface "$2"
+% The delegated interface is not implemented by the class given in the implements clause.
+parser_e_class_implements_must_be_interface=03246_E_Tipo usado por implementação deve ser uma interface
+% The \var{implements} keyword must be followed by an interface type.
+parser_e_cant_export_var_different_name=03247_E_Variáveis não podem ser exportadas com um nome diferente neste alvo, adicione o nome na declaração usando a diretiva "export" (nome variável: $1, nome exportação declarado: $2)
+% On most targets it is not possible to change the name under which a variable
+% is exported inside the \var{exports} statement of a library.
+% In that case, you have to specify the export name at the point where the
+% variable is declared, using the \var{export} and \var{alias} directives.
+parser_e_weak_external_not_supported=03248_E_Símbolos externos fracos não são suportados para o atual alvo
+% A "weak external" symbol is a symbol which may or may not exist at (either static
+% or dynamic) link time. This concept may not be available (or implemented yet)
+% on the current cpu/OS target.
+parser_e_forward_mismatch=03249_E_Definição posterior tipo incompatível
+% Classes and interfaces being defined forward must have the same type
+% when being implemented. A forward interface cannot be changed into a class.
+parser_n_ignore_lower_visibility=03250_N_Método virtual "$1" tem baixa visibilidade ($2) que a classe pai $3 ($4)
+% The virtual method overrides an method that is declared with a higher visibility. This might give
+% unexpected results. In case the new visibility is private than it might be that a call to inherited in a
+% new child class will call the higher visible method in a parent class and ignores the private method.
+parser_e_field_not_allowed_here=03251_E_Campos não podem aparecer depois dem um método ou definição propriedade, inicie uma nova seção de visibilidade primeiro
+% Once a method or property has been defined in a class or object, you cannot define any fields afterwards
+% without starting a new visibility section (such as \var{public}, \var{private}, etc.). The reason is
+% that otherwise the source code can appear ambiguous to the compiler, since it is possible to use modifiers
+% such as \var{default} and \var{register} also as field names.
+parser_e_no_local_para_def=03252_E_Parâmetros ou tipos resultado não podem conter definições locais de tipo. Use uma definição de tipo separada em um bloco de tipos
+% In Pascal, types are not considered to be identical simply because they are semantically equivalent.
+% Two variables or parameters are only considered to be of the same type if they refer to the
+% same type definition.
+% As a result, it is not allowed to define new types inside parameter lists, because then it is impossible to
+% refer to the same type definition in the procedure headers of the interface and implementation of a unit
+% (both procedure headers would define a separate type). Keep in mind that expressions such as
+% ``file of byte'' or ``string[50]'' also define a new type.
+parser_e_abstract_and_sealed_conflict=03253_E_Conflito ABSTRACT e SEALED
+% ABSTRACT and SEALED cannot be used together in one declaration
+parser_e_sealed_descendant=03254_E_Impossível criar um descendente da classe selada "$1"
+% Sealed means that class cannot be derived by another class.
+parser_e_sealed_class_cannot_have_abstract_methods=03255_E_Classe selada não pode ter um método abstrato
+% Sealed means that class cannot be derived. Therefore no one class is able to override an abstract method in a sealed class.
+parser_e_only_virtual_methods_final=03256_E_Apenas métodos virtuais podem ser finais
+% You are declaring a method as final, when it is not declared to be
+% virtual.
+parser_e_final_can_no_be_overridden=03257_E_Método final não pode ser sobreposto: "$1"
+% You are trying to \var{override} a virtual method of a parent class that does
+% not exist.
+parser_e_multiple_messages=03258_E_Apenas uma mensagem pode ser usada por método.
+% It is not possible to associate multiple messages with a single method.
+parser_e_invalid_enumerator_identifier=03259_E_Identificador enumerador inválido: "$1"
+% Only "MoveNext" and "Current" enumerator identifiers are supported.
+parser_e_enumerator_identifier_required=03260_E_Identificador enumerador requerido
+% "MoveNext" or "Current" identifier must follow the \var{enumerator} modifier.
+parser_e_enumerator_movenext_is_not_valid=03261_E_Método enumerador 'MoveNext' padrão inválido. Método deve ser uma função com tipo de retorno booleano e sem argumentos requeridos.
+% "MoveNext" enumerator pattern method must be a function with Boolean return type and no required arguments
+parser_e_enumerator_current_is_not_valid=03262_E_Propriedade enumerador 'Current' padrão inválido. Propriedade deve ter um 'getter'.
+% "Current" enumerator pattern property must have a getter
+parser_e_only_one_enumerator_movenext=03263_E_Apenas um método enumerador 'MoveNext' é permitido por classe/objeto
+% Class or Object can have only one enumerator MoveNext declaration.
+parser_e_only_one_enumerator_current=03264_E_Apenas uma propriedade enumerador 'Current' é permitida por classe/objeto
+% Class or Object can have only one enumerator Current declaration.
+parser_e_for_in_loop_cannot_be_used_for_the_type=03265_E_Laço 'for in' não pode ser usado para o tipo "$1"
+% For in loop can be used not for all types. For example it cannot be used for the enumerations with jumps.
+parser_e_objc_requires_msgstr=03266_E_Mensagens Objective-C requerem que seu nome seletor Objective-C seja especificado usando a diretiva "message".
+% Objective-C messages require their Objective-C name (selector name) to be specified using the \var{message `someName:'} procedure directive.
+% While bindings to other languages automatically generate such names based on the identifier you use (by replacing
+% all underscores with colons), this is unsafe since nothing prevents an Objective-C method name to contain actual
+% colons.
+parser_e_objc_no_constructor_destructor=03267_E_Objective-C não tem construtores nem destruidores formais. Use as mensagens 'alloc', 'initXXX' e 'dealloc'.
+% The Objective-C language does not have any constructors or destructors. While there are some messages with a similar
+% purpose (such as \var{init} and \var{dealloc}), these cannot be identified using automatic parsers and do not
+% guarantee anything like Pascal constructors/destructors (e.g., you have to take care of only calling ``designated''
+% inherited ``constructors''). For these reasons, we have opted to follow the standard Objective-C patterns for
+% instance creation/destruction.
+parser_e_message_string_too_long=03268_E_Nome mensagem é muito longo (max. 255 caracteres)
+% Due to compiler implementation reasons, message names are currently limited to 255 characters.
+parser_e_objc_message_name_too_long=03269_E_Nome símbolo mensagem Objective-C para "$1" é muito longo
+% Due to compiler implementation reasons, mangled message names (i.e., the symbol names used in the assembler
+% code) are currently limited to 255 characters.
+parser_h_no_objc_parent=03270_H_Definindo uma nova classe raiz Objective-C. Para derivar de outra classe raiz (ex., NSObject), especifique-a como pai da classe
+% If no parent class is specified for an Object Pascal class, then it automatically derives from TObject.
+% Objective-C classes however do not automatically derive from NSObject, because one can have multiple
+% root classes in Objective-C. For example, in the Cocoa framework both NSObject and NSProxy are root classes.
+% Therefore, you have to explicitly define a parent class (such as NSObject) if you want to derive your
+% Objective-C class from it.
+parser_e_no_objc_published=03271_E_Classes Objective-C não podem ter seções PUBLISHED
+% In Object Pascal, ``published'' determines whether or not RTTI is generated. Since the Objective-C runtime always needs
+% RTTI for everything, this specified does not make sense for Objective-C classes.
+parser_f_need_objc=03272_F_Este módulo requer que seja especificado uma chave de modo Objective-C para ser compilado
+% This error indicates the use of Objective-C language features without an Objective-C mode switch
+% active. Enable one via the -M command line switch, or the {\$modeswitch x} directive.
+parser_e_must_use_override_objc=03273_E_Métodos herdados podem apenas ser sobrepostos em Objective-C, adicione "OVERRIDE" (método herdado definido em $1)
+parser_h_should_use_override_objc=03274_H_Métodos herdados podem apenas ser sobrepostos em Objective-C, adicione "OVERRIDE" (método herdado definido em $1).
+% It is not possible to \var{reintroduce} methods in Objective-C like in Object Pascal. Methods with the same
+% name always map to the same virtual method entry. In order to make this clear in the source code,
+% the compiler always requires the \var{override} directive to be specified when implementing overriding
+% Objective-C methods in Pascal. If the implementation is external, this rule is relaxed because Objective-C
+% does not have any \var{override}-style keyword (since it's the default and only behaviour in that language),
+% which makes it hard for automated header conversion tools to include it everywhere.
+% The type in which the inherited method is defined is explicitly mentioned, because this may either
+% be an objcclass or an objccategory.
+parser_e_objc_message_name_changed=03275_E_Nome mensagem "$1" na classe herdada é diferente do nome mensagem "$2" na classe atual.
+% An overriding Objective-C method cannot have a different message name than an inherited method. The reason
+% is that these message names uniquely define the message to the Objective-C runtime, which means that
+% giving them a different message name breaks the ``override'' semantics.
+parser_e_no_objc_unique=03276_E_Ainda não é possível fazer cópias únicas de tipos Objective-C
+% Duplicating an Objective-C type using \var{type x = type y;} is not yet supported. You may be able to
+% obtain the desired effect using \var{type x = objcclass(y) end;} instead.
+parser_e_no_category_as_types=03277_E_Categorias Objective-C e classes auxiliares Object Pascal não podem ser usadas como tipos
+% It is not possible to declare a variable as an instance of an Objective-C
+% category or an Object Pascal class helper. A category/class helper adds
+% methods to the scope of an existing class, but does not define a type by
+% itself. An exception of this rule is when inheriting an Object Pascal class
+% helper from another class helper.
+parser_e_no_category_override=03278_E_Categorias não sobrepõem, mas substituem métodos. Use "REINTRODUCE".
+parser_e_must_use_reintroduce_objc=03279_E_Métodos substituídos podem apenas ser reintroduzidos em Objective-C, adicione "REINTRODUCE" (método substituído definido em $1).
+parser_h_should_use_reintroduce_objc=03280_H_Métodos substituídos podem apenas ser reintroduzidos em Objective-C, adicione "REINTRODUCE" (método substituído definido em $1).
+% A category replaces an existing method in an Objective-C class, rather than that it overrides it.
+% Calling an inherited method from an category method will call that method in
+% the extended class' parent, not in the extended class itself. The
+% replaced method in the original class is basically lost, and can no longer be
+% called or referred to. This behaviour corresponds somewhat more closely to
+% \var{reintroduce} than to \var{override} (although in case of \var{reintroduce}
+% in Object Pascal, hidden methods are still reachable via inherited).
+% The type in which the inherited method is defined is explicitly mentioned, because this may either
+% be an objcclass or an objccategory.
+parser_e_implements_getter_not_default_cc=03281_E_'Getter' para implementação interface deve usar a convenção de chamada padrão do alvo.
+% Interface getters are called via a helper in the run time library, and hence
+% have to use the default calling convention for the target (\var{register} on
+% i386 and x86\_64, \var{stdcall} on other architectures).
+parser_e_no_refcounted_typed_file=03282_E_Arquivos tipados não podem conter tipos referência-contados.
+% The data in a typed file cannot be of a reference counted type (such as
+% \var{ansistring} or a record containing a field that is reference counted).
+parser_e_operator_not_overloaded_2=03283_E_Operador não está sobrecarregado: $2 "$1"
+% You are trying to use an overloaded operator when it is not overloaded for
+% this type.
+parser_e_operator_not_overloaded_3=03284_E_Operador não está sobrecarregado: "$1" $2 "$3"
+% You are trying to use an overloaded operator when it is not overloaded for
+% this type.
+parser_e_more_array_elements_expected=03285_E_Esperados outros $1 elementos matriz
+% When declaring a typed constant array, you provided to few elements to initialize the array
+parser_e_string_const_too_long=03286_E_Constante 'String' muito longa, enquanto 'ansistrings' estão desabilitadas
+% Only when a piece of code is compiled with ansistrings enabled (\var{\{\$H+\}}), string constants
+% longer than 255 characters are allowed.
+parser_e_invalid_univ_para=03287_E_Tipo não pode ser usado como parâmetro 'univ' porque seu tamanho é desconhecido em tempo compilação: "$1"
+% \var{univ} parameters are compatible with all values of the same size, but this
+% cannot be checked in case a parameter's size is unknown at compile time.
+parser_e_only_one_class_constructor_allowed=03288_E_Apenas um construtor de classe pode ser definido na classe: "$1"
+% You are trying to declare more than one class constructor but only one class constructor can be declared.
+parser_e_only_one_class_destructor_allowed=03289_E_Apenas um destruidor de classe pode ser definido na classe: "$1"
+% You are trying to declare more than one class destructor but only one class destructor can be declared.
+parser_e_no_paras_for_class_constructor=03290_E_Construtores de classe não podem ter parâmetros
+% You are declaring a class constructor with a parameter list. Class constructor methods
+% cannot have parameters.
+parser_e_no_paras_for_class_destructor=03291_E_Destruidores de classe não podem ter parâmetros
+% You are declaring a class destructor with a parameter list. Class destructor methods
+% cannot have parameters.
+parser_f_modeswitch_objc_required=03292_F_Esta construção requer que chave de modo \{\$modeswitch objectivec1\} esteja ativa
+% Objective-Pascal constructs are not supported when \{\$modeswitch ObjectiveC1\}
+% is not active.
+parser_e_widestring_to_ansi_compile_time=03293_E_Constantes caracteres/unicode não podem ser convertidas em "ansi/shortstring" em tempo de compilação
+% It is not possible to use unicodechar and unicodestring constants in
+% constant expressions that have to be converted into an ansistring or shortstring
+% at compile time, for example inside typed constants. The reason is that the
+% compiler cannot know what the actual ansi encoding will be at run time.
+parser_e_objc_enumerator_2_0=03294_E_Laços "For-in Objective-Pascal" requerem que a chave \{\$modeswitch ObjectiveC2\} esteja ativa
+% Objective-C ``fast enumeration'' support was added in Objective-C 2.0, and
+% hence the appropriate modeswitch has to be activated to expose this feature.
+% Note that Objective-C 2.0 programs require Mac OS X 10.5 or later.
+parser_e_objc_missing_enumeration_defs=03295_E_O compilador não encontrou os tipos "NSFastEnumerationProtocol" ou "NSFastEnumerationState" na unidade "CocoaAll"
+% Objective-C for-in loops (fast enumeration) require that the compiler can
+% find a unit called CocoaAll that contains definitions for the
+% NSFastEnumerationProtocol and NSFastEnumerationState types. If you get this
+% error, most likely the compiler is finding and loading an alternate CocoaAll
+% unit.
+parser_e_no_procvarnested_const=03296_E_Constantes tipadas do tipo 'procedimento é aninhado' só podem ser inicializadas com NIL e procedimentos/funções globais
+% A nested procedural variable consists of two components: the address of the
+% procedure/function to call (which is always known at compile time), and also
+% a parent frame pointer (which is never known at compile time) in case the
+% procedural variable contains a reference to a nested procedure/function.
+% Therefore such typed constants can only be initialized with global
+% functions/procedures since these do not require a parent frame pointer.
+parser_f_no_generic_inside_generic=03297_F_Declaração de classe genérica dentro de outra classe genérica não é permitido
+% At the moment, scanner supports recording of only one token buffer at the time
+% (guarded by internal error 200511173 in tscannerfile.startrecordtokens).
+% Since generics are implemented by recording tokens, it is not possible to
+% have declaration of generic class inside another generic class.
+parser_e_forward_protocol_declaration_must_be_resolved=03298_E_Declaração posterior de objcprotocl "$1" deve ser resolvida antes de uma objcclass possa conformá-la
+% An objcprotocol must be fully defined before classes can conform to it.
+% This error occurs in the following situation:
+% \begin{verbatim}
+% Type MyProtocol = objcprotoocl;
+% ChildClass = Class(NSObject,MyProtocol)
+% ...
+% end;
+% \end{verbatim}
+% where \var{MyProtocol} is declared but not defined.
+parser_e_no_record_published=03299_E_Tipos registro não podem ter seções publicadas
+% Published sections can be used only inside classes.
+parser_e_no_destructor_in_records=03300_E_Destruidores não são permitidos em registros ou auxiliares
+% Destructor declarations aren't allowed in records or helpers.
+parser_e_class_methods_only_static_in_records=03301_E_Métodos de classe devem ser estáticos em registros
+% Class methods declarations aren't allowed in records without static modifier.
+% Records have no inheritance and therefore non static class methods have no sence for them.
+parser_e_no_constructor_in_records=03302_E_Construtores não são permitidos em registros ou auxiliares de registro
+% Constructor declarations aren't allowed in records or record helpers.
+parser_e_at_least_one_argument_must_be_of_type=03303_E_Tanto o resultado ou ao menos um parâmetro deve ser do tipo "$1"
+% It is required that either the result of the routine or at least one of its parameters be of the specified type.
+% For example class operators either take an instance of the structured type in which they are defined, or they return one.
+parser_e_cant_use_type_parameters_here=03304_E_Parâmetros de tipo podem requerer inicialização/finalização - não podem ser usados em registros variant
+% Type parameters may be specialized with types which (e.g. \var{ansistring}) need initialization/finalization
+% code which is implicitly generated by the compiler.
+parser_e_externals_no_section=03305_E_Variáveis sendo declaradas como externas não podem estar em uma seção customizada
+% A section directive is not valid for variables being declared as external.
+parser_e_section_no_locals=03306_E_Variáveis não-estáticas e não-globais não podem ter uma diretiva de seção
+% A variable placed in a custom section is always statically allocated so it must be either a static or global variable.
+parser_e_not_allowed_in_helper=03307_E_"$1" não é permitido em tipos auxiliares
+% Some directives and specifiers like "virtual", "dynamic", "override" aren't
+% allowed inside helper types in mode ObjFPC (they are ignored in mode Delphi),
+% because they have no meaning within helpers. Also "abstract" isn't allowed in
+% either mode.
+parser_e_no_class_constructor_in_helpers=03308_E_Construtores de classe não são permitidos em auxiliares
+% Class constructor declarations aren't allowed in helpers.
+parser_e_inherited_not_in_record=03309_E_O uso de "inherited" não é permitido em um registro
+% As records don't suppport inheritance the use of "inherited" is prohibited for
+% these as well as for record helpers (in mode "Delphi" only).
+parser_e_no_types_in_local_anonymous_records=03310_E_Declarações de tipo não são permitidas em registros locais ou anônimos
+% Records with types must be defined globally. Types cannot be defined inside records which are defined in a
+% procedure or function or in anonymous records.
+parser_e_duplicate_implements_clause=03311_E_Cláusula "implements" duplicada para a interface "$1"
+% A class may delegate an interface using the "implements" clause only to a single property. Delegating it multiple times
+% is a error.
+parser_e_mapping_no_implements=03312_E_Interface "$1" não pode ser delegada por "$2", já possui resolução de métodos
+% Method resolution clause maps a method of an interface to a method of the current class. Therefore the current class
+% has to implement the interface directly. Delegation is not possible.
+parser_e_implements_no_mapping=03313_E_Interface "$1" não pode ter resolução de método, "$2" já a delega
+% Method resoulution is only possible for interfaces that are implemented directly, not by delegation.
+parser_e_invalid_codepage=03314_E_Codepage inválido
+% When declaring a string with a given codepage, the range of valid codepages values is limited
+% to 0 to 65535.
+% \end{description}
+# Type Checking
+#
+# 04108 is the last used one
+#
+% \section{Type checking errors}
+% This section lists all errors that can occur when type checking is
+% performed.
+% \begin{description}
+type_e_mismatch=04000_E_Tipo incompatível
+% This can happen in many cases:
+% \begin{itemize}
+% \item The variable you're assigning to is of a different type than the
+% expression in the assignment.
+% \item You are calling a function or procedure with parameters that are
+% incompatible with the parameters in the function or procedure definition.
+% \end{itemize}
+type_e_incompatible_types=04001_E_Tipos incompatíveis: obtido "$1" esperado "$2"
+% There is no conversion possible between the two types.
+% Another possiblity is that they are declared in different
+% declarations:
+% \begin{verbatim}
+% Var
+% A1 : Array[1..10] Of Integer;
+% A2 : Array[1..10] Of Integer;
+%
+% Begin
+% A1:=A2; { This statement also gives this error. It
+% is due to the strict type checking of Pascal }
+% End.
+% \end{verbatim}
+type_e_not_equal_types=04002_E_Tipos incompatíveis entre "$1" e "$2"
+% The types are not equal.
+type_e_type_id_expected=04003_E_Identificador de tipo esperado
+% The identifier is not a type, or you forgot to supply a type identifier.
+type_e_variable_id_expected=04004_E_Identificador de variável esperado
+% This happens when you pass a constant to a routine (such as \var{Inc} var or \var{Dec})
+% when it expects a variable. You can only pass variables as arguments to these functions.
+type_e_integer_expr_expected=04005_E_Expressão inteira esperada, mas obtido "$1"
+% The compiler expects an expression of type integer, but gets a different
+% type.
+type_e_boolean_expr_expected=04006_E_Expressão booleana esperada, mas obtido "$1"
+% The expression must be a boolean type. It should be return \var{True} or
+% \var{False}.
+type_e_ordinal_expr_expected=04007_E_Expressão ordinal esperada
+% The expression must be of ordinal type, i.e., maximum a \var{Longint}.
+% This happens, for instance, when you specify a second argument
+% to \var{Inc} or \var{Dec} that doesn't evaluate to an ordinal value.
+type_e_pointer_type_expected=04008_E_Tipo ponteiro esperado, mas obtido "$1"
+% The variable or expression isn't of the type \var{pointer}. This
+% happens when you pass a variable that isn't a pointer to \var{New}
+% or \var{Dispose}.
+type_e_class_type_expected=04009_E_Tipo classe esperado, mas obtido "$1"
+% The variable or expression isn't of the type \var{class}. This happens
+% typically when
+% \begin{enumerate}
+% \item The parent class in a class declaration isn't a class.
+% \item An exception handler (\var{On}) contains a type identifier that
+% isn't a class.
+% \end{enumerate}
+type_e_cant_eval_constant_expr=04011_E_Impossível avaliar expressão constante
+% This error can occur when the bounds of an array you declared do
+% not evaluate to ordinal constants.
+type_e_set_element_are_not_comp=04012_E_Elementos conjunto não são compatíveis
+% You are trying to perform an operation on two sets, when the set element types
+% are not the same. The base type of a set must be the same when taking the
+% union.
+type_e_set_operation_unknown=04013_E_Operação não implementada para conjuntos
+% several binary operations are not defined for sets.
+% These include: \var{div}, \var{mod}, \var{**}, \var{>=} and \var{<=}.
+% The last two may be defined for sets in the future.
+type_w_convert_real_2_comp=04014_W_Conversão automática de tipo de ponto flutuante para COMP que é um inteiro
+% An implicit type conversion from a real type to a \var{comp} is
+% encountered. Since \var{comp} is a 64 bit integer type, this may indicate
+% an error.
+type_h_use_div_for_int=04015_H_Use DIV como alternativa para obter um resultado inteiro
+% When hints are on, then an integer division with the '/' operator will
+% produce this message, because the result will then be of type real.
+type_e_strict_var_string_violation=04016_E_Tipos 'String' devem coincidir exatamente no modo $V+
+% When compiling in \var{\{\$V+\}} mode, the string you pass as a parameter
+% should be of the exact same type as the declared parameter of the procedure.
+type_e_succ_and_pred_enums_with_assign_not_possible=04017_E_'SUCC' ou 'PRED' não é possível em enumerações com atribuições
+% If you declare an enumeration type which has C-like assignments
+% in it, such as in the following:
+% \begin{verbatim}
+% Tenum = (a,b,e:=5);
+% \end{verbatim}
+% then you cannot use the \var{Succ} or \var{Pred} functions with this enumeration.
+type_e_cant_read_write_type=04018_E_Impossível ler ou gravar variáveis deste tipo
+% You are trying to \var{read} or \var{write} a variable from or to a
+% file of type text, which doesn't support that variable's type.
+% Only integer types, reals, pchars and strings can be read from or
+% written to a text file. Booleans can only be written to text files.
+type_e_no_readln_writeln_for_typed_file=04019_E_Impossível usar 'readln' ou 'writeln' em arquivos tipados
+% \var{readln} and \var{writeln} are only allowed for text files.
+type_e_no_read_write_for_untyped_file=04020_E_Impossivel usar 'read' ou 'write' em arquivos não tipados.
+% \var{read} and \var{write} are only allowed for text or typed files.
+type_e_typeconflict_in_set=04021_E_Conflito de tipos entre elementos de conjunto
+% There is at least one set element which is of the wrong type, i.e. not of
+% the set type.
+type_w_maybe_wrong_hi_lo=04022_W_lo/hi(dword/qword) retorna 'upper/lower word/dword'
+% \fpc supports an overloaded version of \var{lo/hi} for \var{longint/dword/int64/qword}
+% which returns the lower/upper word/dword of the argument. \tp always uses
+% a 16 bit \var{lo/hi} which always returns bits 0..7 for \var{lo} and the
+% bits 8..15 for \var{hi}. If you want the \tp behavior you have
+% to type cast the argument to a \var{word} or \var{integer}.
+type_e_integer_or_real_expr_expected=04023_E_Expressão inteira ou real esperada
+% The first argument to \var{str} must be a real or integer type.
+type_e_wrong_type_in_array_constructor=04024_E_Tipo incorreto "$1" no construtor matriz
+% You are trying to use a type in an array constructor which is not
+% allowed.
+type_e_wrong_parameter_type=04025_E_Tipos incompatíveis para o arg. no. $1: Obtido "$2", esperado "$3"
+% You are trying to pass an invalid type for the specified parameter.
+type_e_no_method_and_procedure_not_compatible=04026_E_Método (variável) e Procedimento (variável) não são compatíveis
+% You can't assign a method to a procedure variable or a procedure to a
+% method pointer.
+type_e_wrong_math_argument=04027_E_Constante ilegal passada para função matemática interna
+% The constant argument passed to a \var{ln} or \var{sqrt} function is out of
+% the definition range of these functions.
+type_e_no_addr_of_constant=04028_E_Impossível obter o endereço de expressões constantes
+% It is not possible to get the address of a constant expression, because they
+% aren't stored in memory. You can try making it a typed constant. This error
+% can also be displayed if you try to pass a property to a var parameter.
+type_e_argument_cant_be_assigned=04029_E_Argumento não pode ser atribuído
+% Only expressions which can be on the left side of an
+% assignment can be passed as call by reference arguments.
+%
+% Remark: Properties can be used on the left side of an assignment,
+% nevertheless they cannot be used as arguments.
+type_e_cannot_local_proc_to_procvar=04030_E_Impossível atribuir procedimento/função local a variável procedimento
+% It's not allowed to assign a local procedure/function to a
+% procedure variable, because the calling convention of a local procedure/function is
+% different. You can only assign local procedure/function to a void pointer.
+type_e_no_assign_to_addr=04031_E_Impossível atribuir valores a um endereço
+% It is not allowed to assign a value to an address of a variable, constant,
+% procedure or function. You can try compiling with -So if the identifier
+% is a procedure variable.
+type_e_no_assign_to_const=04032_E_Impossível atribuir valors a uma variável constante
+% It's not allowed to assign a value to a variable which is declared
+% as a const. This is normally a parameter declared as const. To allow
+% changing the value, pass the parameter by value, or a parameter by reference
+% (using var).
+type_e_array_required=04033_E_Tipo matriz requerido
+% If you are accessing a variable using an index '[<x>]' then
+% the type must be an array. In FPC mode a pointer is also allowed.
+type_e_interface_type_expected=04034_E_Tipo interface esperado, mas obtido "$1"
+% The compiler expected to encounter an interface type name, but got something else.
+% The following code would produce this error:
+% \begin{verbatim}
+% Type
+% TMyStream = Class(TStream,Integer)
+% \end{verbatim}
+type_h_mixed_signed_unsigned=04035_H_Misturando expressões assinadas e 'longwords' obtem-se um resultado de 64bits
+% If you divide (or calculate the modulus of) a signed expression by a longword (or vice versa),
+% or if you have overflow and/or range checking turned on and use an arithmetic
+% expression (+, -, *, div, mod) in which both signed numbers and longwords appear,
+% then everything has to be evaluated in 64-bit arithmetic which is slower than normal
+% 32-bit arithmetic. You can avoid this by typecasting one operand so it
+% matches the result type of the other one.
+type_w_mixed_signed_unsigned2=04036_W_Misturando expressões assinadas e cardinais pode causar um erro de verificação de faixa
+% If you use a binary operator (and, or, xor) and one of
+% the operands is a longword while the other one is a signed expression, then,
+% if range checking is turned on, you may get a range check error because in
+% such a case both operands are converted to longword before the operation is
+% carried out. You can avoid this by typecasting one operand so it
+% matches the result type of the other one.
+type_e_typecast_wrong_size_for_assignment=04037_E_Conversão de tipo tem tamanhos diferentes ($1 -> $2) na atribuição
+% Type casting to a type with a different size is not allowed when the variable is
+% used in an assignment.
+type_e_array_index_enums_with_assign_not_possible=04038_E_Enumerações com atribuições não podem ser usadas como índice de matrizes
+% When you declared an enumeration type which has C-like
+% assignments, such as in the following:
+% \begin{verbatim}
+% Tenum = (a,b,e:=5);
+% \end{verbatim}
+% you cannot use it as the index of an array.
+type_e_classes_not_related=04039_E_Tipos Classe ou Objeto "$1" e "$2" não estão relacionados
+% There is a typecast from one class or object to another while the class/object
+% are not related. This will probably lead to errors.
+type_w_classes_not_related=04040_W_Tipos Classe "$1" e "$2" não estão relacionados
+% There is a typecast from one class to another while the classes
+% are not related. This will probably lead to errors.
+type_e_class_or_interface_type_expected=04041_E_Tipo classe ou interface esperado, mas obtido "$1"
+% The compiler expected a class or interface name, but got another type or identifier.
+type_e_type_is_not_completly_defined=04042_E_Tipo "$1" não está completamente definido
+% This error occurs when a type is not complete: i.e. a pointer type which points to
+% an undefined type.
+type_w_string_too_long=04043_W_Literal 'String' tem mais caracteres que comprimento 'string' curta
+% The size of the constant string, which is assigned to a shortstring,
+% is longer than the maximum size of the shortstring (255 characters).
+type_w_signed_unsigned_always_false=04044_W_Comparação pode ser sempre falsa devido a faixa da constante e expressão
+% There is a comparison between a constant and an expression where the constant is out of the
+% valid range of values of the expression. Because of type promotion, the statement will always evaluate to
+% false. Explicitly typecast the constant or the expression to the correct range to avoid this warning
+% if you think the code is correct.
+type_w_signed_unsigned_always_true=04045_W_Comparação pode ser sempre verdadeira devido a faixa da constante e expressão
+% There is a comparison between a constant and an expression where the constant is out of the
+% valid range of values of the expression. Because of type promotion, the statement will always evaluate to
+% true. Explicitly typecast the constant or the expression to the correct range to avoid this warning
+% if you think the code is correct.
+type_w_instance_with_abstract=04046_W_Construindo uma classe "$1" com método abstrato "$2"
+% An instance of a class is created which contains non-implemented abstract
+% methods. This will probably lead to a runtime error 211 in the code if that
+% routine is ever called. All abstract methods should be overridden.
+type_h_in_range_check=04047_H_O operador esquerdo em um operador 'IN' deve ser tamanho byte
+% The left operand of the \var{in} operator is not an ordinal or enumeration which fits
+% within 8 bits. This may lead to range check errors. The \var{in} operator
+% currently only supports a left operand which fits within a byte. In the case of
+% enumerations, the size of an element of an enumeration can be controlled with
+% the \var{\{\$PACKENUM\}} or \var{\{\$Zn\}} switches.
+type_w_smaller_possible_range_check=04048_W_Tamanho tipo incompatível, possível perda de dados / erro verificação faixa
+% There is an assignment to a smaller type than the source type. This means that
+% this may cause a range-check error, or may lead to possible loss of data.
+type_h_smaller_possible_range_check=04049_H_Tamanho tipo incompatível, possível perda de dados / erro verificação faixa
+% There is an assignment to a smaller type than the source type. This means that
+% this may cause a range-check error, or may lead to possible loss of data.
+type_e_cant_take_address_of_abstract_method=04050_E_O endereço de um método abstrato não pode ser obtido
+% An abstract method has no body, so the address of an abstract method can't be taken.
+type_e_assignment_not_allowed=04051_E_Atribuições à parâmetros formais e matrizes abertas não são possíveis
+% You are trying to assign a value to a formal (untyped var, const or out)
+% parameter, or to an open array.
+type_e_constant_expr_expected=04052_E_Expressão constante esperada
+% The compiler expects an constant expression, but gets a variable expression.
+type_e_operator_not_supported_for_types=04053_E_Operação "$1" não é suportada para os tipos "$2" e "$3"
+% The operation is not allowed for the supplied types.
+type_e_illegal_type_conversion=04054_E_Conversão de tipo ilegal: "$1" para "$2"
+% When doing a type-cast, you must take care that the sizes of the variable and
+% the destination type are the same.
+type_h_pointer_to_longint_conv_not_portable=04055_H_Conversão entre ordinais e ponteiros não é portável
+% If you typecast a pointer to a longint (or vice-versa), this code will not compile
+% on a machine using 64 bits addressing.
+type_w_pointer_to_longint_conv_not_portable=04056_W_Conversão entre ordinais e ponteiros não é portável
+% If you typecast a pointer to an ordinal type of a different size (or vice-versa), this can
+% cause problems. This is a warning to help in finding the 32-bit specific code where cardinal/longint is used
+% to typecast pointers to ordinals. A solution is to use the ptrint/ptruint types instead.
+type_e_cant_choose_overload_function=04057_E_Impossível determinar qual função sobrecarregada chamar
+% You're calling overloaded functions with a parameter that doesn't correspond
+% to any of the declared function parameter lists. e.g. when you have declared
+% a function with parameters \var{word} and \var{longint}, and then you call
+% it with a parameter which is of type \var{integer}.
+type_e_illegal_count_var=04058_E_Variável contador ilegal
+% The type of a \var{for} loop variable must be an ordinal type.
+% Loop variables cannot be reals or strings.
+type_w_double_c_varargs=04059_W_Convertendo constante valor real para 'double' para variável argumento C, adicione conversão de tipo explícita para evitar isso.
+% In C, constant real values are double by default. For this reason, if you
+% pass a constant real value to a variable argument part of a C function, FPC
+% by default converts this constant to double as well. If you want to prevent
+% this from happening, add an explicit typecast around the constant.
+type_e_class_or_cominterface_type_expected=04060_E_Tipo Classe ou interface COM esperado, mas obtido "$1"
+% Some operators, such as the AS operator, are only applicable to classes or COM interfaces.
+type_e_no_const_packed_array=04061_E_Matrizes constantes compactadas não são suportadas ainda
+% You cannot declare a (bit)packed array as a typed constant.
+type_e_got_expected_packed_array=04062_E_Tipos incompatíveis para arg. no. $1: Obtido "$2" esperado "Matriz compactada (Bits)"
+% The compiler expects a (bit)packed array as the specified parameter.
+type_e_got_expected_unpacked_array=04063_E_Tipos incompatíveis para arg. no. $1: Obtido "$2" esperado "Matriz (não compactada)"
+% The compiler expects a regular (i.e., not packed) array as the specified parameter.
+type_e_no_packed_inittable=04064_E_Elementos de matrizes compactadas não podem ser de um tipo que necessita ser inicializado
+% Support for packed arrays of types that need initialization
+% (such as ansistrings, or records which contain ansistrings) is not yet implemented.
+type_e_no_const_packed_record=04065_E_Registros constantes compactadas e objetos não são suportados ainda
+% You cannot declare a (bit)packed array as a typed constant at this time.
+type_w_untyped_arithmetic_unportable=04066_W_Aritmética "$1" em ponteiros não tipados não é portável {$T+}, sugere-se conversão de tipo
+% Addition/subtraction from an untyped pointer may work differently in \var{\{\$T+\}}.
+% Use a typecast to a typed pointer.
+type_e_cant_take_address_of_local_subroutine=04076_E_Impossível obter endereço de uma subrotina marcada como local
+% The address of a subroutine marked as local can't be taken.
+type_e_cant_export_local=04077_E_Impossível exportar subrotina marcada como local de uma unidade
+% A subroutine marked as local can't be exported from a unit.
+type_e_not_automatable=04078_E_Tipo não é automatizável: "$1"
+% Only byte, integer, longint, smallint, currency, single, double, ansistring,
+% widestring, tdatetime, variant, olevariant, wordbool and all interfaces are automatable.
+type_h_convert_add_operands_to_prevent_overflow=04079_H_Convertendo os operandos para "$1" antes de realizar a soma pode prevenir erros de transbordamento.
+% Adding two types can cause overflow errors. Since you are converting the result to a larger type, you
+% could prevent such errors by converting the operands to this type before doing the addition.
+type_h_convert_sub_operands_to_prevent_overflow=04080_H_Convertendo os operandos para "$1" antes de realizar a subtração pode prevenir erros de transbordamento.
+% Subtracting two types can cause overflow errors. Since you are converting the result to a larger type, you
+% could prevent such errors by converting the operands to this type before doing the subtraction.
+type_h_convert_mul_operands_to_prevent_overflow=04081_H_Convertendo os operados para "$1" antes de realizar a multiplicação pode prevenir erros de transbordamento.
+% Multiplying two types can cause overflow errors. Since you are converting the result to a larger type, you
+% could prevent such errors by converting the operands to this type before doing the multiplication.
+type_w_pointer_to_signed=04082_W_Convertendo ponteiros para inteiros assinados pode resultar em comparações de resultados incorretas e erros de faixa. Ao invés disso, use tipos não assinados.
+% The virtual address space on 32-bit machines runs from \$00000000 to \$ffffffff.
+% Many operating systems allow you to allocate memory above \$80000000.
+% For example both \windows and \linux allow pointers in the range \$0000000 to \$bfffffff.
+% If you convert pointers to signed types, this can cause overflow and range check errors,
+% but also \$80000000 < \$7fffffff. This can cause random errors in code like "if p>q".
+type_e_interface_has_no_guid=04083_E_Tipo interface $1 não tem um GUID válido
+% When applying the as-operator to an interface or class, the desired interface (i.e. the right operand of the
+% as-operator) must have a valid GUID.
+type_e_invalid_objc_selector_name=04084_E_Nome seletor inválido "$1"
+% An Objective-C selector cannot be empty, must be a valid identifier or a single colon,
+% and if it contains at least one colon it must also end in one.
+type_e_expected_objc_method_but_got=04085_E_Método Objective-C esperado, mas obtido $1
+% A selector can only be created for Objective-C methods, not for any other kind
+% of procedure/function/method.
+type_e_expected_objc_method=04086_E_Método Objective-C ou nome método constante esperados
+% A selector can only be created for Objective-C methods, either by specifying
+% the name using a string constant, or by using an Objective-C method identifier
+% that is visible in the current scope.
+type_e_no_type_info=04087_E_Nenhuma informação de tipo disponível para este tipo
+% Type information is not generated for some types, such as enumerations with gaps
+% in their value range (this includes enumerations whose lower bound is different
+% from zero).
+type_e_ordinal_or_string_expr_expected=04088_E_Ordinal ou expressão 'string' esperados
+% The expression must be an ordinal or string type.
+type_e_string_expr_expected=04089_E_Expressão 'string' esperada
+% The expression must be a string type.
+type_w_zero_to_nil=04090_W_Convertendo 0 para NIL
+% Use NIL rather than 0 when initialising a pointer.
+type_e_protocol_type_expected=04091_E_Tipo protocolo Objective-C esperado, mas obtido "$1"
+% The compiler expected a protocol type name, but found something else.
+type_e_objc_type_unsupported=04092_E_O tipo "$1" não é suportado para interação com código Objective-C de tempo execução.
+% Objective-C makes extensive use of run time type information (RTTI). This format
+% is defined by the maintainers of the run time and can therefore not be adapted
+% to all possible Object Pascal types. In particular, types that depend on
+% reference counting by the compiler (such as ansistrings and certain kinds of
+% interfaces) cannot be used as fields of Objective-C classes, cannot be
+% directly passed to Objective-C methods, and cannot be encoded using \var{objc\_encode}.
+type_e_class_or_objcclass_type_expected=04093_E_Tipo classe ou 'objcclass' esperados, mas obtido "$1"
+% It is only possible to create class reference types of \var{class} and \var{objcclass}
+type_e_objcclass_type_expected=04094_E_Tipo 'Objcclass' esperado
+% The compiler expected an \var{objcclass} type
+type_w_procvar_univ_conflicting_para=04095_W_Tipo parâmetro 'univ' forçado em variável procedimental pode causar travamento ou corrupção de memória: $1 para $2
+% \var{univ} parameters are implicitly compatible with all types of the same size,
+% also in procedural variable definitions. That means that the following code is
+% legal, because \var{single} and \var{longint} have the same size:
+% \begin{verbatim}
+% {$mode macpas}
+% Type
+% TIntProc = procedure (l: univ longint);
+%
+% procedure test(s: single);
+% begin
+% writeln(s);
+% end;
+%
+% var
+% p: TIntProc;
+% begin
+% p:=test;
+% p(4);
+% end.
+% \end{verbatim}
+% This code may however crash on platforms that pass integers in registers and
+% floating point values on the stack, because then the stack will be unbalanced.
+% Note that this warning will not flagg all potentially dangerous situations.
+% when \var{test} returns.
+type_e_generics_cannot_reference_itself=04096_E_Parâmetros de tipo de especializações de genéricos não podem referenciar o tipo especializado atual
+% Recursive specializations of generics like \var{Type MyType = specialize MyGeneric<MyType>;} are not possible.
+type_e_type_parameters_are_not_allowed_here=04097_E_Parâmetros de tipo não são permitidos em procedimentos ou funções de classe/registro/objeto não-genérico
+% Type parameters are only allowed for methods of generic classes, records or objects
+type_e_generic_declaration_does_not_match=04098_E_Declaração genérica de "$1" difere da declaração anterior
+% Generic declaration does not match the previous declaration
+type_e_helper_type_expected=04099_E_Tipo auxiliar esperado
+% The compiler expected a \var{class helper} type.
+type_e_record_type_expected=04100_E_Tipo registro esperado
+% The compiler expected a \var{record} type.
+type_e_class_helper_must_extend_subclass=04101_E_Classe auxiliar derivada deve extender a subclasse de "$1" ou a própria classe
+% If a class helper inherits from another class helper the extended class must
+% extend either the same class as the parent class helper or a subclass of it
+type_e_record_helper_must_extend_same_record=04102_E_Registro auxiliar derivado deve extender "$1"
+% If a record helper inherits from another record helper it must extend the same
+% record that the parent record helper extended.
+type_e_procedures_return_no_value=04103_E_Atribuição inválida, procedimento não retorna valor
+% This error occurs when one tries to assign the result of a procedure or destructor call.
+% A procedure or destructor returns no value so this is not
+% possible.
+type_w_implicit_string_cast=04104_W_Conversão de tipo 'string' implícita de "$1" para "$2"
+% An implicit type conversion from an ansi string type to an unicode string type is
+% encountered. To avoid this warning perform an explicit type conversion.
+type_w_implicit_string_cast_loss=04105_W_Conversão de tipo 'string' implícita com potencial de perda de dados de "$1" para "$2"
+% An implicit type conversion from an unicode string type to an ansi string type is
+% encountered. This conversion can lose data since not all unicode characters may be represented in the codepage of
+% destination string type.
+type_w_explicit_string_cast=04106_-W_Conversão de tipo 'string' explícita de "$1" para "$2"
+% An explicit typecast from an ansi string type to an unicode string type is
+% encountered. This warning is off by default. You can turn it on to see all suspicious string conversions.
+type_w_explicit_string_cast_loss=04107_-W_Conversão de tipo 'string' explícita com potencial de perda de dados de "$1" para "$2"
+% An explicit typecast from an unicode string type to an ansi string type is
+% encountered. This conversion can lose data since not all unicode characters may be represented in the codepage of
+% destination string type. This warning is off by default. You can turn it on to see all the places with lossy string
+% conversions.
+type_w_unicode_data_loss=04108_W_Conversão de constante Unicode com potencial de perda de dados
+% Conversion from a WideChar to AnsiChar can lose data since now all unicode characters may be represented in the current
+% system codepage
+% \end{description}
+#
+# Symtable
+#
+# 05084 is the last used one
+#
+% \section{Symbol handling}
+% This section lists all the messages that concern the handling of symbols.
+% This means all things that have to do with procedure and variable names.
+% \begin{description}
+sym_e_id_not_found=05000_E_Identificador não encontrado "$1"
+% The compiler doesn't know this symbol. Usually happens when you misspell
+% the name of a variable or procedure, or when you forget to declare a
+% variable.
+sym_f_internal_error_in_symtablestack=05001_F_Erro interno em SymTableStack()
+% An internal error occurred in the compiler; If you encounter such an error,
+% please contact the developers and try to provide an exact description of
+% the circumstances in which the error occurs.
+sym_e_duplicate_id=05002_E_Identificador duplicado "$1"
+% The identifier was already declared in the current scope.
+sym_h_duplicate_id_where=05003_H_Identificador já definido em $1 na linha $2
+% The identifier was already declared in a previous scope.
+sym_e_unknown_id=05004_E_Identificador desconhecido "$1"
+% The identifier encountered has not been declared, or is used outside the
+% scope where it is defined.
+sym_e_forward_not_resolved=05005_E_Declaração posterior não resolvida "$1"
+% This can happen in two cases:
+% \begin{itemize}
+% \item You declare a function in the \var{interface} part, or
+% with a \var{forward} directive, but do not implement it.
+% \item You reference a type which isn't declared in the current \var{type}
+% block.
+% \end{itemize}
+sym_e_error_in_type_def=05007_E_Erro na definição de tipo
+% There is an error in your definition of a new array type.
+% One of the range delimiters in an array declaration is erroneous.
+% For example, \var{Array [1..1.25]} will trigger this error.
+sym_e_forward_type_not_resolved=05009_E_Tipo posterior não resolvido "$1"
+% A symbol was forward defined, but no declaration was encountered.
+sym_e_only_static_in_static=05010_E_Apenas variáveis estáticas podem ser usadas em métodos estáticos ou métodos externos
+% A static method of an object can only access static variables.
+sym_f_type_must_be_rec_or_class=05012_F_Tipo registro ou classe esperados
+% The variable or expression isn't of the type \var{record} or \var{class}.
+sym_e_no_instance_of_abstract_object=05013_E_Instâncias de classes ou objetos com métodos abstratos não são permitidas
+% You are trying to generate an instance of a class which has an abstract
+% method that wasn't overridden.
+sym_w_label_not_defined=05014_W_Rótulo não definido "$1"
+% A label was declared, but not defined.
+sym_e_label_used_and_not_defined=05015_E_Rótulo usado mas não definido "$1"
+% A label was declared and used, but not defined.
+sym_e_ill_label_decl=05016_E_Declaração rótulo ilegal
+% This error should never happen; it occurs if a label is defined outside a
+% procedure or function.
+sym_e_goto_and_label_not_supported=05017_E_GOTO e LABEL não são suportados (use a chave -Sg)
+% You must use the -Sg switch to compile a program which has \var{label}s
+% and \var{goto} statements. By default, \var{label} and \var{goto} aren't
+% supported.
+sym_e_label_not_found=05018_E_Rótulo não encontrado
+% A \var{goto label} was encountered, but the label wasn't declared.
+sym_e_id_is_no_label_id=05019_E_Identificador não é um rótulo
+% The identifier specified after the \var{goto} isn't of type label.
+sym_e_label_already_defined=05020_E_Rótulo já definido
+% You are defining a label twice. You can define a label only once.
+sym_e_ill_type_decl_set=05021_E_Declaração de tipo de conjunto de elementos ilegal
+% The declaration of a set contains an invalid type definition.
+sym_e_class_forward_not_resolved=05022_E_Declaração posterior de classe não resolvida "$1"
+% You declared a class, but you did not implement it.
+sym_n_unit_not_used=05023_H_Unidade "$1" não usada em $2
+% The unit referenced in the \var{uses} clause is not used.
+sym_h_para_identifier_not_used=05024_H_Parâmetro "$1" não usado
+% The identifier was declared (locally or globally) but
+% was not used (locally or globally).
+sym_n_local_identifier_not_used=05025_N_Variável local "$1" não usada
+% You have declared, but not used, a variable in a procedure or function
+% implementation.
+sym_h_para_identifier_only_set=05026_H_Valor parâmetro "$1" é atribuído mas nunca usado
+% The identifier was declared (locally or globally) and
+% assigned to, but is not used (locally or globally) after the assignment.
+sym_n_local_identifier_only_set=05027_N_Variável local "$1" é atribuída mas nunca usada
+% The variable in a procedure or function implementation is declared and
+% assigned to, but is not used after the assignment.
+sym_h_local_symbol_not_used=05028_H_Local $1 "$2" não é usado
+% A local symbol is never used.
+sym_n_private_identifier_not_used=05029_N_Campo privado "$1.$2" nunca usado
+% The indicated private field is defined, but is never used in the code.
+sym_n_private_identifier_only_set=05030_N_Campo privado "$1.$2" é atribuído mas nunca usado
+% The indicated private field is declared and assigned to, but never read.
+sym_n_private_method_not_used=05031_N_Método privado "$1.$2" nunca usado
+% The indicated private method is declared but is never used in the code.
+sym_e_set_expected=05032_E_Tipo conjunto esperado
+% The variable or expression is not of type \var{set}. This happens in an
+% \var{in} statement.
+sym_w_function_result_not_set=05033_W_Retorno da função parece não ter sido ajustado
+% You can get this warning if the compiler thinks that a function return
+% value is not set. This will not be displayed for assembler procedures,
+% or procedures that contain assembler blocks.
+sym_w_wrong_C_pack=05034_W_Tipo "$1" não está alinhado corretamente no atual registro para C
+% Arrays with sizes not multiples of 4 will be wrongly aligned
+% for C structures.
+sym_e_illegal_field=05035_E_Identificador de campo de registro desconhecido "$1"
+% The field doesn't exist in the record/object definition.
+sym_w_uninitialized_local_variable=05036_W_Variável local "$1" não parece ter sido inicializada
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. it appears in the right-hand side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assignment).
+sym_w_uninitialized_variable=05037_W_Variável "$1" parece não ter sido inicializada
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. it appears in the right-hand side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assignment).
+sym_e_id_no_member=05038_E_Identificador não identifica nenhum membro "$1"
+% This error is generated when an identifier of a record,
+% field or method is accessed while it is not defined.
+sym_h_param_list=05039_H_Declaração encontrada: $1
+% You get this when you use the \var{-vh} switch.In the case of an overloaded procedure
+% not being found. Then all candidate overloaded procedures are
+% listed, with their parameter lists.
+sym_e_segment_too_large=05040_E_Elemento de dados muito grande
+% You get this when you declare a data element whose size exceeds the
+% prescribed limit (2 Gb on 80386+/68020+ processors).
+sym_e_no_matching_implementation_found=05042_E_Nenhuma implementação coincidente para método interface "$1" encontrada
+% There was no matching method found which could implement the interface
+% method. Check argument types and result type of the methods.
+sym_w_deprecated_symbol=05043_W_Símbolo "$1" está depreciado
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{deprecated} is used. Deprecated symbols may no longer
+% be available in newer versions of the unit / library. Use of this symbol
+% should be avoided as much as possible.
+sym_w_non_portable_symbol=05044_W_Símbolo "$1" não é portável
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{platform} is used. This symbol's value, use
+% and availability is platform specific and should not be used
+% if the source code must be portable.
+sym_w_non_implemented_symbol=05055_W_Símbolo "$1" não está implementado
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{unimplemented} is used. This symbol is defined,
+% but is not yet implemented on this specific platform.
+sym_e_cant_create_unique_type=05056_E_Impossível criar tipo único para este tipo
+% Only simple types like ordinal, float and string types are supported when
+% redefining a type with \var{type newtype = type oldtype;}.
+sym_h_uninitialized_local_variable=05057_H_Variável local "$1" parece não ter sido inicializada
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. it appears in the right-hand side of an expression) when it
+% was not initialized first (i.e. it did not appear in the left-hand side of an
+% assignment).
+sym_h_uninitialized_variable=05058_H_Variável "$1" parece não ter sido inicializada
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. it appears in the right-hand side of an expression) when it
+% was not initialized first (i.e. t did not appear in the left-hand side of an
+% assignment).
+sym_w_function_result_uninitialized=05059_W_Variável de retorno da função parece não ter sido inicializada
+% This message is displayed if the compiler thinks that the function result
+% variable will be used (i.e. it appears in the right-hand side of an expression)
+% before it is initialized (i.e. before it appeared in the left-hand side of an
+% assignment).
+sym_h_function_result_uninitialized=05060_H_Variável de retorno da função parece não ter sido inicializada
+% This message is displayed if the compiler thinks that the function result
+% variable will be used (i.e. it appears in the right-hand side of an expression)
+% before it is initialized (i.e. it appears in the left-hand side of an
+% assignment)
+sym_w_identifier_only_read=05061_W_Variável "$1" lida mas não atribuída em lugar algum
+% You have read the value of a variable, but nowhere assigned a value to
+% it.
+sym_h_abstract_method_list=05062_H_Método abstrato encontrado: $1
+% When getting a warning about constructing a class/object with abstract methods
+% you get this hint to assist you in finding the affected method.
+sym_w_experimental_symbol=05063_W_Símbolo "$1" é experimental
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{experimental} is used. Experimental symbols
+% might disappear or change semantics in future versions. Usage of this symbol
+% should be avoided as much as possible.
+sym_w_forward_not_resolved=05064_W_Declaração posterior "$1" não resolvida, assumida como externa
+% This happens if you declare a function in the \var{interface} of a unit in macpas mode,
+% but do not implement it.
+sym_w_library_symbol=05065_W_Símbolo "$1" pertence a uma biblioteca
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{library} is used. Library symbols may not be
+% available in other libraries.
+sym_w_deprecated_symbol_with_msg=05066_W_Símbolo "$1" está depreciado: "$2"
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{deprecated} is used. Deprecated symbols may no longer
+% be available in newer versions of the unit / library. Use of this symbol
+% should be avoided as much as possible.
+sym_e_no_enumerator=05067_E_Impossível encontrar um enumerador para o tipo "$1"
+% This means that compiler cannot find an apropriate enumerator to use in the for-in loop.
+% To create an enumerator you need to defind an operator enumerator or add a public or published
+% GetEnumerator method to the class or object definition.
+sym_e_no_enumerator_move=05068_E_Impossível encontrar um método "MoveNext" no enumerador "$1"
+% This means that compiler cannot find a public MoveNext method with the Boolean return type in
+% the enumerator class or object definition.
+sym_e_no_enumerator_current=05069_E_Impossível encontrar uma propriedade "Current" no enumerador "$1"
+% This means that compiler cannot find a public Current property in the enumerator class or object
+% definition.
+sym_e_objc_para_mismatch=05070_E_Incompatibilidade entre número de parâmetros declarados e número de dois pontos (:) na 'string' mensagem.
+% In Objective-C, a message name automatically contains as many colons as parameters.
+% In order to prevent mistakes when specifying the message name in FPC, the compiler
+% checks whether this is also the case here. Note that in case of messages taking a
+% variable number of arguments translated to FPC via an \var{array of const} parameter,
+% this final \var{array of const} parameter is not counted. Neither are the hidden
+% \var{self} and \var{\_cmd} parameters.
+sym_n_private_type_not_used=05071_N_Tipo privado "$1.$2" nunca usado
+% The indicated private type is declared but is never used in the code.
+sym_n_private_const_not_used=05072_N_Constante privada "$1.$2" nunca usada
+% The indicated private const is declared but is never used in the code.
+sym_n_private_property_not_used=05073_N_Propriedade privada "$1.$2" nunca usada
+% The indicated private property is declared but is never used in the code.
+sym_w_deprecated_unit=05074_W_Unidade "$1" está depreciada
+% This means that a unit which is
+% declared as \var{deprecated} is used. Deprecated units may no longer
+% be available in newer versions of the library. Use of this unit
+% should be avoided as much as possible.
+sym_w_deprecated_unit_with_msg=05075_W_Unidade "$1" está depreciada: "$2"
+% This means that a unit which is
+% declared as \var{deprecated} is used. Deprecated units may no longer
+% be available in newer versions of the library. Use of this unit
+% should be avoided as much as possible.
+sym_w_non_portable_unit=05076_W_Unidade "$1" não é portável
+% This means that a unit which is
+% declared as \var{platform} is used. This unit use
+% and availability is platform specific and should not be used
+% if the source code must be portable.
+sym_w_library_unit=05077_W_Unidade "$1" pertence a uma biblioteca
+% This means that a unit which is
+% declared as \var{library} is used. Library units may not be
+% available in other libraries.
+sym_w_non_implemented_unit=05078_W_Unidade "$1" não está implementada
+% This means that a unit which is
+% declared as \var{unimplemented} is used. This unit is defined,
+% but is not yet implemented on this specific platform.
+sym_w_experimental_unit=05079_W_Unidade "$1" é experimental
+% This means that a unit which is
+% declared as \var{experimental} is used. Experimental units
+% might disappear or change semantics in future versions. Usage of this unit
+% should be avoided as much as possible.
+sym_e_objc_formal_class_not_resolved=05080_E_Nenhuma definição completa da classe objeto formalmente declarada "$1" está no escopo
+% Objecive-C classes can be imported formally, without using the the unit in which it is fully declared.
+% This enables making forward references to such classes and breaking circular dependencies amongst units.
+% However, as soon as you wish to actually do something with an entity of this class type (such as
+% access one of its fields, send a message to it, or use it to inherit from), the compiler requires the full definition
+% of the class to be in scope.
+sym_e_interprocgoto_into_init_final_code_not_allowed=05081_E_Gotos dentro de blocos de inicialização ou finalização de unidades não são permitidos
+% Gotos into initialization or finalization blockse of units are not allowed.
+sym_e_external_class_name_mismatch1=05082_E_Nome externo inválido "$1" para classe formal "$2"
+sym_e_external_class_name_mismatch2=05083_E_Complete a definição de classe com nome externo "$1" aqui
+% When a class is declared using a formal external definition, the actual external
+% definition (if any) must specify the same external name as the formal definition
+% (since both definitions refer to the same actual class type).
+sym_w_library_overload=05084_W_Possível conflito em biblioteca: símbolo "$1" da biblioteca "$2" também encontrado na biblioteca "$3"
+% Some OS do not have library specific namespaces, for those
+% OS, the function declared as "external 'libname' name 'funcname'",
+% the 'libname' part is only a hint, funcname might also be loaded
+% by another library. This warning appears if 'funcname' is used twice
+% with two different library names.
+%
+% \end{description}
+#
+# Codegenerator
+#
+# 06049 is the last used one
+#
+% \section{Code generator messages}
+% This section lists all messages that can be displayed if the code
+% generator encounters an error condition.
+% \begin{description}
+cg_e_parasize_too_big=06009_E_Tamanho da lista de parâmetros excede 65535 bytes
+% The I386 processor limits the parameter list to 65535 bytes. (The \var{RET}
+% instruction causes this.)
+cg_e_file_must_call_by_reference=06012_E_Tipos Arquivos devem ser parâmetros var.
+% You cannot specify files as value parameters, i.e., they must always be
+% declared \var{var} parameters.
+cg_e_cant_use_far_pointer_there=06013_E_O uso de ponteiro distante não é permitido lá
+% Free Pascal doesn't support far pointers, so you cannot take the address of
+% an expression which has a far reference as a result. The \var{mem} construct
+% has a far reference as a result, so the following code will produce this
+% error:
+% \begin{verbatim}
+% var p : pointer;
+% ...
+% p:=@mem[a000:000];
+% \end{verbatim}
+cg_e_dont_call_exported_direct=06015_E_Funções 'EXPORT' declaradas não podem ser chamadas
+% No longer in use.
+cg_w_member_cd_call_from_method=06016_W_Possível chamada ilegal de construtor ou destruidor
+% The compiler detected that a constructor or destructor is called within a
+% a method. This will probably lead to problems, since constructors / destructors
+% require parameters on entry.
+cg_n_inefficient_code=06017_N_Códio ineficiente
+% Your statement seems dubious to the compiler.
+cg_w_unreachable_code=06018_W_Código inacessível
+% You specified a construct which will never be executed. Example:
+% \begin{verbatim}
+% while false do
+% begin
+% {.. code ...}
+% end;
+% \end{verbatim}
+cg_e_cant_call_abstract_method=06020_E_Métodos abstratos não podem ser chamados diretamente
+% You cannot call an abstract method directly. Instead, you must call an
+% overriding child method, because an abstract method isn't implemented.
+cg_d_register_weight=06027_DL_Registro $1 peso $2 $3
+% Debugging message. Shown when the compiler considers a variable for
+% keeping in the registers.
+cg_d_stackframe_omited=06029_DL_Quadro da pilha é omitido
+% Some procedure/functions do not need a complete stack-frame, so it is omitted.
+% This message will be displayed when the {-vd} switch is used.
+cg_e_unable_inline_object_methods=06031_E_Objeto ou métodos classe não podem ser 'em linha'.
+% You cannot have inlined object methods.
+cg_e_unable_inline_procvar=06032_E_Chamadas 'Procvar' não podem ser 'em linha'.
+% A procedure with a procedural variable call cannot be inlined.
+cg_e_no_code_for_inline_stored=06033_E_Nenhum código para procedimento 'em linha' armazenado
+% The compiler couldn't store code for the inline procedure.
+cg_e_can_access_element_zero=06035_E_Elemento zero de uma 'ansi/wide-' ou stringlonga pode ser acessado, usar '(set)length'
+% You should use \var{setlength} to set the length of an ansi/wide/longstring
+% and \var{length} to get the length of such string type.
+cg_e_cannot_call_cons_dest_inside_with=06037_E_Construtores ou destruidores não podem ser chamados de dentro de uma cláusula 'with'
+% Inside a \var{with} clause you cannot call a constructor or destructor for the
+% object you have in the \var{with} clause.
+cg_e_cannot_call_message_direct=06038_E_Impossível chamar métodos manipuladores de mensagem diretamente
+% A message method handler method cannot be called directly if it contains an
+% explicit \var{Self} argument.
+cg_e_goto_inout_of_exception_block=06039_E_Salto interno ou externo a um bloco de exceção
+% It is not allowed to jump in or outside of an exception block like \var{try..finally..end;}.
+% For example, the following code will produce this error:
+
+% \begin{verbatim}
+% label 1;
+%
+% ...
+%
+% try
+% if not(final) then
+% goto 1; // this line will cause an error
+% finally
+% ...
+% end;
+% 1:
+% ...
+% \end{verbatim}
+cg_e_control_flow_outside_finally=06040_E_Instruções de controle de fluxo não são permitidos em um bloco 'finally'
+% It isn't allowed to use the control flow statements \var{break},
+% \var{continue} and \var{exit}
+% inside a finally statement. The following example shows the problem:
+% \begin{verbatim}
+% ...
+% try
+% p;
+% finally
+% ...
+% exit; // This exit ISN'T allowed
+% end;
+% ...
+%
+% \end{verbatim}
+% If the procedure \var{p} raises an exception the finally block is
+% executed. If the execution reaches the exit, it's unclear what to do:
+% exit the procedure or search for another exception handler.
+cg_w_parasize_too_big=06041_W_Tamanho parâmetros excede limite para certas CPU's
+% This indicates that you are declaring more than 64K of parameters, which
+% might not be supported on other processor targets.
+cg_w_localsize_too_big=06042_W_Tamanho variável local excede limite para certas CPU's
+% This indicates that you are declaring more than 32K of local variables, which
+% might not be supported on other processor targets.
+cg_e_localsize_too_big=06043_E_Tamanho variáveis locais excedem limites suportados
+% This indicates that you are declaring more than 32K of local variables, which
+% is not supported by this processor.
+cg_e_break_not_allowed=06044_E_BREAK não permitido
+% You're trying to use \var{break} outside a loop construction.
+cg_e_continue_not_allowed=06045_E_CONTINUE não permitido
+% You're trying to use \var{continue} outside a loop construction.
+cg_f_unknown_compilerproc=06046_F_'Compilerproc' desconhecido "$1". Verifique se você usa a biblioteca de tempo de execução correta
+% The compiler expects that the runtime library contains certain subroutines. If you see this error
+% and you didn't change the runtime library code, it's very likely that the runtime library
+% you're using doesn't match the compiler in use. If you changed the runtime library this error means
+% that you removed a subroutine which the compiler needs for internal use.
+cg_f_unknown_system_type=06047_F_Impossível encontrar tipo sistema "$1". Verifique se você usa a biblioteca de tempo de execução correta
+% The compiler expects that the runtime library contains certain type definitions. If you see this error
+% and you didn't change the runtime library code, it's very likely that the runtime library
+% you're using doesn't match the compiler in use. If you changed the runtime library this error means
+% that you removed a type which the compiler needs for internal use.
+cg_h_inherited_ignored=06048_H_Chamada herdada para método abstrato ignorada
+% This message appears only in Delphi mode when you call an abstract method
+% of a parent class via \var{inherited;}. The call is then ignored.
+cg_e_goto_label_not_found=06049_E_Rótulo 'Goto' "$1" não definido ou eliminado pela otimização
+% The label used in the goto definition is not defined or optimized away by the
+% unreachable code elemination.
+cg_f_unknown_type_in_unit=06050_F_Impossível encontrar o tipo "$1" na unidade "$2". Verifique se você usa a biblioteca de tempo de execução correta.
+% The compiler expects that the runtime library contains certain type definitions. If you see this error
+% and you didn't change the runtime library code, it's very likely that the runtime library
+% you're using doesn't match the compiler in use. If you changed the runtime library this error means
+% that you removed a type which the compiler needs for internal use.
+cg_e_interprocedural_goto_only_to_outer_scope_allowed=06051_E_Gotos interprocedimentos são permitidos apenas para subrotinas externas
+% Gotos between subroutines are only allowed if the goto jumps from an inner to an outer subroutine or
+% from a subroutine to the main program
+cg_e_labels_cannot_defined_outside_declaration_scope=06052_E_Rótulo deve ser definido no mesmo escopo em que é declarado
+% In ISO mode, labels must be defined in the same scope as they are declared.
+cg_e_goto_across_procedures_with_exceptions_not_allowed=06053_E_Deixar procedimentos contendo quadros de exceções explícitas ou implícitas usando 'goto' não é permitido
+% Non-local gotos might not be used to leave procedures using exceptions either implicitly or explicitly. Procedures
+% which use automated types like ansistrings or class constructurs are affected by this too.
+cg_e_mod_only_defined_for_pos_quotient=06054_E_No modo ISO, o operador 'mod' é definido apenas para quociente positivo
+% In ISO pascal, only positive values are allowed for the quotient: \var{n mod m} is only valid if \var{m>0}.
+% \end{description}
+# EndOfTeX
+
+#
+# Assembler reader
+#
+# 07110 is the last used one
+#
+asmr_d_start_reading=07000_DL_Iniciando $1 análise estilo assembler
+% This informs you that an assembler block is being parsed
+asmr_d_finish_reading=07001_DL_Finalizada $1 análise estilo assembler
+% This informs you that an assembler block has finished.
+asmr_e_none_label_contain_at=07002_E_Padrão não-rótulo contêm @
+% A identifier which isn't a label can't contain a @.
+asmr_e_building_record_offset=07004_E_Erro construindo deslocamento registro
+% There has an error occured while building the offset of a record/object
+% structure, this can happend when there is no field specified at all or
+% an unknown field identifier is used.
+asmr_e_offset_without_identifier=07005_E_'OFFSET' usado sem identificador
+% You can only use OFFSET with an identifier. Other syntaxes aren't
+% supported
+asmr_e_type_without_identifier=07006_E_'TYPE' usado sem identificador
+% You can only use TYPE with an identifier. Other syntaxes aren't
+% supported
+asmr_e_no_local_or_para_allowed=07007_E_Impossível usar variável local ou parâmetro aqui
+% You can't use a local variable or parameter here, mostly because the
+% addressing of locals and parameters is done using the frame pointer register so the
+% address can't be obtained directly.
+asmr_e_need_offset=07008_E_Necessário usar 'OFFSET' aqui
+% You need to use OFFSET <id> here to get the address of the identifier.
+asmr_e_need_dollar=07009_E_Necessário usar $ aqui
+% You need to use $<id> here to get the address of the identifier.
+asmr_e_cant_have_multiple_relocatable_symbols=07010_E_Impossível usar múltiplos símbolos relocáveis
+% You can't have more than one relocatable symbol (variable/typed constant)
+% in one argument.
+asmr_e_only_add_relocatable_symbol=07011_E_Símbolo relocável pode apenas ser adicionado
+% Relocatable symbols (variable/typed constant) can't be used with other
+% operators. Only addition is allowed.
+asmr_e_invalid_constant_expression=07012_E_Expressão constante inválida
+% There is an error in the constant expression.
+asmr_e_relocatable_symbol_not_allowed=07013_E_Símbolo relocável não é permitido
+% You can't use a relocatable symbol (variable/typed constant) here.
+asmr_e_invalid_reference_syntax=07014_E_Sintaxe referência inválida
+% There is an error in the reference.
+asmr_e_local_para_unreachable=07015_E_Você não pode atingir $1 a partir desse código
+% You cannot read directly the value of a local variable or parameter
+% of a higher level procedure in assembler code (except for
+% local assembler code without parameter nor locals).
+asmr_e_local_label_not_allowed_as_ref=07016_E_Símbolos locais/rótulos não são permitidos como referências
+% You can't use local symbols/labels as references
+asmr_e_wrong_base_index=07017_E_Uso registro base e índice inválido
+% There is an error with the base and index register, they are
+% probably incorrect
+asmr_w_possible_object_field_bug=07018_W_Possível erro na manipulação de campo de objeto
+% Fields of objects or classes can be reached directly in normal or objfpc
+% modes but TP and Delphi modes treat the field name as a simple offset.
+asmr_e_wrong_scale_factor=07019_E_Fator incorreto de escala especificado
+% The scale factor given is wrong, only 1,2,4 and 8 are allowed
+asmr_e_multiple_index=07020_E_Uso múltiplo registro índice
+% You are trying to use more than one index register
+asmr_e_invalid_operand_type=07021_E_Tipo operando inválido
+% The operand type doesn't match with the opcode used
+asmr_e_invalid_string_as_opcode_operand=07022_E_'String' inválido como operando 'opcode': $1
+% The string specified as operand is not correct with this opcode
+asmr_w_CODE_and_DATA_not_supported=07023_W_@CODE e @DATA não suportados
+% @CODE and @DATA are unsupported and are ignored.
+asmr_e_null_label_ref_not_allowed=07024_E_Referências nulas de rótulos não são permitidas
+asmr_e_expr_zero_divide=07025_E_Divisão por zero em avaliador asm
+% There is a division by zero in a constant expression
+asmr_e_expr_illegal=07026_E_Expressao ilegal
+% There is an illegal expression in a constant expression
+asmr_e_escape_seq_ignored=07027_E_Sequência de escape ignorada: $1
+% There is a C-styled string, but the escape sequence in the string
+% is unknown, and is therefore ignored
+asmr_e_invalid_symbol_ref=07028_E_Referência símbolo inválida
+asmr_w_fwait_emu_prob=07029_W_Fwait pode causar problemas de emulação com emu387
+asmr_w_fadd_to_faddp=07030_W_$1 sem operando traduzido em $1P
+asmr_w_enter_not_supported_by_linux=07031_W_Instrução 'ENTER' não suportada pelo kernel Linux
+% ENTER instruction can generate a stack page fault that is not
+% caught correctly by the i386 Linux page handler.
+asmr_w_calling_overload_func=07032_W_Chamando uma função sobrecarregada em assembler
+% There is a call to an overloaded method in the assembler block,
+% this might be the sign there is a problem
+asmr_e_unsupported_symbol_type=07033_E_Tipo símbolo não suportado para operando
+asmr_e_constant_out_of_bounds=07034_E_Valor constante fora de faixa
+asmr_e_error_converting_decimal=07035_E_Erro convertendo decimal $1
+% A constant decimal value does not have the correct syntax
+asmr_e_error_converting_octal=07036_E_Erro convertendo octal $1
+% A constant octal value does not have the correct syntax
+asmr_e_error_converting_binary=07037_E_Erro convertendo binário $1
+% A constant binary value does not have the correct syntax
+asmr_e_error_converting_hexadecimal=07038_E_Erro convertendo hexadecimal $1
+% A constant hexadecimal value does not have the correct syntax
+asmr_h_direct_global_to_mangled=07039_H_$1 traduzido para $2
+asmr_w_direct_global_is_overloaded_func=07040_W_$1 está associado a uma função sobrecarregada
+asmr_e_cannot_use_SELF_outside_a_method=07041_E_Impossível usar 'SELF' fora de um método
+% There is a reference to the \var{self} symbol while it is not
+% allowed. \var{self} can only be referenced inside methods
+asmr_e_cannot_use_OLDEBP_outside_nested_procedure=07042_E_Impossível usar 'OLDEBP' fora de um procedimento aninhado
+% There is a reference to the \var{oldebp} symbol while it is not
+% allowed. \var{oldebp} can only be referenced inside nested routines
+asmr_e_void_function=07043_W_Procedimentos não podem retornar qualquer valor em código asm
+% Trying to return a value while in a procedure. A procedure
+% does not have any return value
+asmr_e_SEG_not_supported=07044_E_SEG não suportado
+asmr_e_size_suffix_and_dest_dont_match=07045_E_Tamanho sufixo e tamanho destino ou fonte não coincidem
+% The register size and the opcode size suffix don't match. This is
+% probably an error in the assembler statement
+asmr_w_size_suffix_and_dest_dont_match=07046_W_Tamanho sufixo e tamanho destino ou fonte não coincidem
+% The register size and the opcode size suffix don't match. This is
+% probably an error in the assembler statement
+asmr_e_syntax_error=07047_E_Erro de sintaxe assembler
+% There is an assembler syntax error
+asmr_e_invalid_opcode_and_operand=07048_E_Combinação inválida de 'opcode' e operandos
+% The opcode cannot be used with this type of operand
+asmr_e_syn_operand=07049_E_Erro de sintaxe assembler em operando
+asmr_e_syn_constant=07050_E_Erro de sintaxe assembler em constante
+asmr_e_invalid_string_expression=07051_E_Expressão 'String' inválida
+asmr_w_const32bit_for_address=07052_W_Constante com símbolo $1 para endereço que não está em um ponteiro
+% A constant expression represents an address which does not fit
+% into a pointer. The address is probably incorrect
+asmr_e_unknown_opcode=07053_E_'Opcode' desconhecido $1
+% This opcode is not known
+asmr_e_invalid_or_missing_opcode=07054_E_'Opcode' inválido ou faltando
+asmr_e_invalid_prefix_and_opcode=07055_E_Combinação inválida de prefixo e 'opcode': $1
+asmr_e_invalid_override_and_opcode=07056_E_Combinação inválida de 'override' e 'opcode': $1
+asmr_e_too_many_operands=07057_E_Muitos operandos na linha
+% There are too many operands for this opcode. Check your
+% assembler syntax
+asmr_w_near_ignored=07058_W_NEAR ignorado
+asmr_w_far_ignored=07059_W_FAR ignorado
+asmr_e_dup_local_sym=07060_E_Símbolo local duplicado $1
+asmr_e_unknown_local_sym=07061_E_Símbolo local indefinido $1
+asmr_e_unknown_label_identifier=07062_E_Identificador rótulo desconhecido $1
+asmr_e_invalid_register=07063_E_Nome registro inválido
+% There is an unknown register name used as operand.
+asmr_e_invalid_fpu_register=07064_E_Nome registro ponto flutuante inválido
+% There is an unknown register name used as operand.
+asmr_w_modulo_not_supported=07066_W_Módulo não suportado
+asmr_e_invalid_float_const=07067_E_Constante ponto flutuante inválida $1
+% The floating point constant declared in an assembler block is
+% invalid.
+asmr_e_invalid_float_expr=07068_E_Expressão ponto flutuante inválida
+% The floating point expression declared in an assembler block is
+% invalid.
+asmr_e_wrong_sym_type=07069_E_Tipo símbolo incorreto
+asmr_e_cannot_index_relative_var=07070_E_Impossível indexar uma var. local ou parâmetro com um registro
+% Trying to index using a base register a symbol which is already relative
+% to a register. This is not possible, and will probably lead to crashes.
+asmr_e_invalid_seg_override=07071_E_Expressão sobreposição segmento inválida
+asmr_w_id_supposed_external=07072_W_Identificador $1 supostamente externo
+% There is a reference to an undefined symbol. This will not result
+% in an error, since the symbol might be external, but may cause
+% problems at link time if the symbol is not defined anywhere.
+asmr_e_string_not_allowed_as_const=07073_E_'Strings' não permitidas como constantes
+% Character strings are not allowed as constants.
+asmr_e_no_var_type_specified=07074_E_Nenhum tipo de variável especificado
+% The syntax expects a type idenfitifer after the dot, but
+% none was found.
+asmr_w_assembler_code_not_returned_to_text=07075_E_Código assembler não retornou a seção texto
+% There was a directive in the assembler block to change sections,
+% but there is a missing return to the text section at the end
+% of the assembler block. This might cause errors during link time.
+asmr_e_not_directive_or_local_symbol=07076_E_Não é uma diretiva ou símbolo local $1
+% This symbol is unknown.
+asmr_w_using_defined_as_local=07077_E_Usando um nome definido como um rótulo local
+asmr_e_dollar_without_identifier=07078_E_Caracter Dólar é usado sem um identificador
+% A constant expression has an identifier which does not start with
+% the $ symbol.
+asmr_w_32bit_const_for_address=07079_W_Constante 32bit criada para endereço
+% A constant was used as an address. This is probably an error,
+% since using absolute addresses will probably not work.
+asmr_n_align_is_target_specific=07080_N_'.align' é específico de alvo, use '.balign' ou '.p2align'
+% Using the .align directive is platform specific, and its meaning will vary
+% from one platform to another.
+asmr_e_cannot_access_field_directly_for_parameters=07081_E_Impossível acessar campos diretamente para parâmetros
+% You should load the parameter first into a register and then access the
+% fields using that register.
+asmr_e_cannot_access_object_field_directly=07082_E_Impossível acessar campos de objetos/classes diretamente
+% You should load the self pointer first into a register and then access the
+% fields using the register as base. By default the self pointer is available
+% in the esi register on i386.
+asmr_e_unable_to_determine_reference_size=07083_E_Tamanho não especificado e incapaz de determinar o tamanho dos operandos
+% You should specify explicitly a size for the reference, because
+% the compiler is unable to determine what size (byte,word,dword,etc.) it
+% should use for the reference.
+asmr_e_cannot_use_RESULT_here=07084_E_Impossível usar 'RESULT' nesta função
+% Some functions which return complex types cannot use the \var{result}
+% keyword.
+asmr_w_adding_explicit_args_fXX=07086_W_"$1" sem operando traduzido em "$1 %st,%st(1)"
+asmr_w_adding_explicit_first_arg_fXX=07087_W_"$1 %st(n)" traduzido em "$1 %st,%st(n)"
+asmr_w_adding_explicit_second_arg_fXX=07088_W_"$1 %st(n)" translated em "$1 %st(n),%st"
+asmr_e_invalid_char_smaller=07089_E_Caracter < não permitido aqui
+% The shift operator requires the << characters. Only one
+% of those characters was found.
+asmr_e_invalid_char_greater=07090_E_Caracter > não permitido aqui
+% The shift operator requires the >> characters. Only one
+% of those characters was found.
+asmr_w_align_not_supported=07093_W_ALIGN não suportado
+asmr_e_no_inc_and_dec_together=07094_E_'Inc' e 'Dec' não podem estar juntos
+% Trying to use an increment and a decrement within the same
+% opcode on the 680x0. This is impossible.
+asmr_e_invalid_reg_list_in_movem=07095_E_'Reglist' para 'movem' inválido
+% Trying to use the \var{movem} opcode with invalid registers
+% to save or restore.
+asmr_e_invalid_reg_list_for_opcode=07096_E_'Reglist' inválido para 'opcode'
+asmr_e_higher_cpu_mode_required=07097_E_Modo CPU maior requerido ($1)
+% Trying to use an instruction which is not supported in the current
+% cpu mode. Use a higher cpu generation to be able to use this
+% opcode in your assembler block
+asmr_w_unable_to_determine_reference_size_using_dword=07098_W_Nenhum tamanho especificado e incapaz de determinar o tamanho dos operandos, usando DWORD como padrão
+% You should specify explicitly a size for the reference, because
+% the compiler is unable to determine what size (byte,word,dword,etc.) it
+% should use for the reference. This warning is only used in Delphi mode where
+% it falls back to use DWORD as default.
+asmr_e_illegal_shifterop_syntax=07099_E_Erro de sintaxe tentando analisar um operando deslocamento
+% ARM only; ARM assembler supports a so called shifter operand. The used syntax isn't
+% a valid shifter operand. Example for an operation with shifter operand:
+% \begin{verbatim}
+% asm
+% orr r2,r2,r2,lsl #8
+% end;
+% \end{verbatim}
+asmr_e_packed_element=07100_E_Endereço de componente compactado não está no limite byte
+% Packed components (record fields and array elements) may start at an arbitrary
+% bit inside a byte. On CPU which do not support bit-addressable memory (which
+% includes all currently supported CPUs by FPC) you will therefore get an error
+% message when trying to index arrays with elements whose size is not a multiple
+% of 8 bits. The same goes for accessing record fields with such an address.
+% multiple of 8 bits.
+asmr_w_unable_to_determine_reference_size_using_byte=07101_W_Nenhum tamanho especificado e incapaz de determinar o tamanho dos operandos, usando BYTE como padrão
+% You should specify explicitly a size for the reference, because
+% the compiler is unable to determine what size (byte,word,dword,etc.) it
+% should use for the reference. This warning is only used in Delphi mode where
+% it falls back to use BYTE as default.
+asmr_w_no_direct_ebp_for_parameter=07102_W_Uso de '+offset(%ebp)' para parâmetros inválido aqui
+% Using direct 8(%ebp) reference for function/procedure parameters is invalid
+% if parameters are in registers.
+asmr_w_direct_ebp_for_parameter_regcall=07103_W_Uso de '+offset(%ebp)' não é compatível com a convenção 'regcall'
+% Using direct 8(%ebp) reference for function/procedure parameters is invalid
+% if parameters are in registers.
+asmr_w_direct_ebp_neg_offset=07104_W_Uso de '-offset(%ebp)' não é recomendada para acesso a variável local
+% Using -8(%ebp) to access a local variable is not recommended
+asmr_w_direct_esp_neg_offset=07105_W_Uso de '-offset(%esp)', acesso pode causar travamento ou valor pode ser perdido
+% Using -8(%esp) to access a local stack is not recommended, as
+% this stack portion can be overwritten by any function calls or interrupts.
+asmr_e_no_vmtoffset_possible=07106_E_'VMTOffset' deve ser usado em combinação com um método virtual, e "$1" não é virtual
+% Only virtual methods have VMT offsets
+asmr_e_need_pic_ref=07107_E_Gerando PIC, mas referência não é segura (PIC-safe)
+% The compiler has been configured to generate position-independent code
+% (PIC), but there are position-dependent references in the current
+% handwritten assembler instruction.
+asmr_e_mixing_regtypes=07108_E_Todos os registros em um conjunto de registros devem ser do mesmo tipo e largura
+% Instructions on the ARM architecture that take a register set as argument require that all registers
+% in this set are of the same kind (e.g., integer, vfp) and width (e.g., single precision, double precision).
+asmr_e_empty_regset=07109_E_Um conjunto de registros não pode estar vazio
+% Instructions on the ARM architecture that take a register set as argument require that such a set
+% contains at least one register.
+
+asmr_w_useless_got_for_local=07110_W_@GOTPCREL é inútil e potencialmente perigoso para símbolos locais
+% The use of @GOTPCREL supposes an extra indirection that is
+% not present if the symbol is local, which might lead to wrong asembler code
+asmr_w_general_segment_with_constant=07111_W_Constante com registro de segmento de propósito geral
+% General purpose register should not have constant offsets
+% as OS memory allocation might not be compatible with that.
+asmr_e_bad_seh_directive_offset=07112_E_Valor de deslocamento inválido para $1
+% Win64 SEH directives have certain restrictions on possible offset values, e.g. they should
+% be positive and have 3 or 4 low bits clear.
+asmr_e_bad_seh_directive_register=07113_E_Registro inválido para $1
+% Win64 SEH directives accept only 64-bit integer registers or XMM registers.
+asmr_e_seh_in_pure_asm_only=07114_E_Diretivas SEH são permitidas apenas em procedimentos assembler puros
+% Win64 SEH directives are allowed only in pure assembler procedures, not in assembler
+% blocks of regular procedures.
+asmr_e_unsupported_directive=07115_E_Diretiva "$1" não é suportada pelo alvo atual
+
+
+#
+# Assembler/binary writers
+#
+# 08022 is the last used one
+#
+asmw_f_too_many_asm_files=08000_F_Muitos arquivos assembler
+% With smartlinking enabled, there are too many assembler
+% files generated. Disable smartlinking.
+asmw_f_assembler_output_not_supported=08001_F_Saída assembler selecionada não suportada
+asmw_f_comp_not_supported=08002_F_'Comp' não suportado
+asmw_f_direct_not_supported=08003_F_Modo direto não suportado por gravadores binários
+% Direct assembler mode is not supported for binary writers.
+asmw_e_alloc_data_only_in_bss=08004_E_Alocamento de dados somente permitida na seção 'bss'
+asmw_f_no_binary_writer_selected=08005_F_Nenhum gravador binário selecionado
+asmw_e_opcode_not_in_table=08006_E_Asm: Opcode $1 não está na tabela
+asmw_e_invalid_opcode_and_operands=08007_E_Asm: $1 combinação inválida de 'opcode' e operandos
+asmw_e_16bit_not_supported=08008_E_Asm: referências 16 Bits não suportadas
+asmw_e_invalid_effective_address=08009_E_Asm: Endereço efetivo inválido
+asmw_e_immediate_or_reference_expected=08010_E_Asm: Esperados 'Immediate' ou referência
+asmw_e_value_exceeds_bounds=08011_E_Asm: $1 valor excede limites $2
+asmw_e_short_jmp_out_of_range=08012_E_Asm: Salto curto fora de faixa $1
+asmw_e_undefined_label=08013_E_Asm: Rótulo indefinido $1
+asmw_e_comp_not_supported=08014_E_Asm: Tipo 'Comp' não suportado por este alvo
+asmw_e_extended_not_supported=08015_E_Asm: Tipo extendido não suportado por este alvo
+asmw_e_duplicate_label=08016_E_Asm: Rótulo duplicado $1
+asmw_e_redefined_label=08017_E_Asm: Rótulo redefinido $1
+asmw_e_first_defined_label=08018_E_Asm: Primeiramente definido aqui
+asmw_e_invalid_register=08019_E_Asm: Registro inválido $1
+asmw_e_16bit_32bit_not_supported=08020_E_Asm: Referências 16 ou 32 Bits não suportadas
+asmw_e_64bit_not_supported=08021_E_Asm: Operandos 64 Bits não suportados
+asmw_e_bad_reg_with_rex=08022_E_Asm: AH,BH,CH ou DH não podem ser usados em uma instrução que requer o prefixo REX
+% x86_64 only: instruction encoding of this platform does not allow using
+% 8086 high byte registers (AH,BH,CH or DH) together with REX prefix in a single instruction.
+% The REX prefix is required whenever the instruction operand size is 64 bits, or
+% when it uses one of extended x86_64 registers (R8-R15 or XMM8-XMM15).
+asmw_e_missing_endprologue=08023_E_Diretiva .seh_endprologue faltando
+% x86_64-win64 only: Normally, SEH directives are handled internally by compiler.
+% However, in pure assembler procedures .seh_endprologue directive is required
+% if other SEH directives are present.
+asmw_e_prologue_too_large=08024_E_Prólogo da função excede 255 bytes
+% x86_64-win64: .seh_prologue directive must be placed within 255 bytes from function start.
+asmw_e_handlerdata_no_handler=08025_E_Diretiva .seh_handlerdata sem .seh_handler precedente
+% x86_64-win64: If .seh_handlerdata directive is used, then a .seh_handler directive must be
+% present earlier in the same function.
+
+#
+# Executing linker/assembler
+#
+# 09033 is the last used one
+#
+# BeginOfTeX
+%
+% \section{Errors of assembling/linking stage}
+% This section lists errors that occur when the compiler is processing the
+% command line or handling the configuration files.
+% \begin{description}
+exec_w_source_os_redefined=09000_W_Sistema operacional fonte redefinido
+% The source operating system is redefined.
+exec_i_assembling_pipe=09001_I_Montando (pipe) $1
+% Assembling using a pipe to an external assembler.
+exec_d_cant_create_asmfile=09002_E_Impossível criar arquivo assembler: $1
+% The mentioned file can't be created. Check if you have
+% access permissions to create this file.
+exec_e_cant_create_objectfile=09003_E_Impossível criar arquivo objeto: $1
+% The mentioned file can't be created. Check if you have
+% got access permissions to create this file.
+exec_e_cant_create_archivefile=09004_E_Impossível criar arquivo: $1
+% The mentioned file can't be created. Check if you have
+% access permissions to create this file.
+exec_e_assembler_not_found=09005_E_Montador $1 não encontrado, mudando para montador externo
+% The assembler program was not found. The compiler will produce a script that
+% can be used to assemble and link the program.
+exec_t_using_assembler=09006_T_Usando montador: $1
+% An informational message saying which assembler is being used.
+exec_e_error_while_assembling=09007_E_Erro ao montar código saída $1
+% There was an error while assembling the file using an external assembler.
+% Consult the documentation of the assembler tool to find out more information
+% on this error.
+exec_e_cant_call_assembler=09008_E_Impossível chamar montador, erro $1 mudando para montador externo
+% An error occurred when calling an external assembler. The compiler will produce a script that
+% can be used to assemble and link the program.
+exec_i_assembling=09009_I_Montando $1
+% An informational message stating which file is being assembled.
+exec_i_assembling_smart=09010_I_Montando com vinculação inteligente $1
+% An informational message stating which file is being assembled using smartlinking.
+exec_w_objfile_not_found=09011_W_Objeto $1 não encontrado, Vinculação pode falhar !
+% One of the object files is missing, and linking will probably fail.
+% Check your paths.
+exec_w_libfile_not_found=09012_W_Biblioteca $1 não encontrada, Vinculação pode falhar !
+% One of the library files is missing, and linking will probably fail.
+% Check your paths.
+exec_e_error_while_linking=09013_E_Erro durante vinculação
+% Generic error while linking.
+exec_e_cant_call_linker=09014_E_Impossível chamar vinculador, mudando para vinculação externa
+% An error occurred when calling an external linker. The compiler will produce a script that
+% can be used to assemble and link the program.
+exec_i_linking=09015_I_Vinculando $1
+% An informational message, showing which program or library is being linked.
+exec_e_util_not_found=09016_E_Utilitário $1 não encontrado, mudando para vinculação externa
+% An external tool was not found. The compiler will produce a script that
+% can be used to assemble and link or postprocess the program.
+exec_t_using_util=09017_T_Usando utilitário $1
+% An informational message, showing which external program (usually a postprocessor) is being used.
+exec_e_exe_not_supported=09018_E_Criação de Executáveis não suportada
+% Creating executable programs is not supported for this platform, because it was
+% not yet implemented in the compiler.
+exec_e_dll_not_supported=09019_E_Criação de bibliotecas Dinâmicas/Compartilhadas não suportada
+% Creating dynamically loadable libraries is not supported for this platform, because it was
+% not yet implemented in the compiler.
+exec_i_closing_script=09020_I_Fechando roteiro $1
+% Informational message showing when writing of the external assembling and linking script is finished.
+exec_e_res_not_found=09021_E_Compilador recursos "$1" não encontrado, mudando para modo externo
+% An external resource compiler was not found. The compiler will produce a script that
+% can be used to assemble, compile resources and link or postprocess the program.
+exec_i_compilingresource=09022_I_Compilando recursos $1
+% An informational message, showing which resource is being compiled.
+exec_t_unit_not_static_linkable_switch_to_smart=09023_T_Unidade $1 não pode ser vinculada estaticamente, mudando para vinculação inteligente
+% Static linking was requested, but a unit which is not statically linkable was used.
+exec_t_unit_not_smart_linkable_switch_to_static=09024_T_Unidade $1 não pode ser vinculada inteligentemente, mudando para vinculação estática
+% Smart linking was requested, but a unit which is not smart-linkable was used.
+exec_t_unit_not_shared_linkable_switch_to_static=09025_T_Unidade $1 não pode ser vinculada compartilhadamente, mudando para vinculação estática
+% Shared linking was requested, but a unit which is not shared-linkable was used.
+exec_e_unit_not_smart_or_static_linkable=09026_E_Unidade $1 não pode ser vinculada inteligentemente ou estaticamente
+% Smart or static linking was requested, but a unit which cannot be used for either was used.
+exec_e_unit_not_shared_or_static_linkable=09027_E_Unidade $1 não pode ser vinculada compartilhadamente ou estaticamente
+% Shared or static linking was requested, but a unit which cannot be used for either was used.
+exec_d_resbin_params=09028_D_Chamando compilador recursos "$1" com "$2" como linha comando
+% An informational message showing which command line is used for the resource compiler.
+exec_e_error_while_compiling_resources=09029_E_Erro ao compilar recursos
+% The resource compiler or converter returned an error.
+exec_e_cant_call_resource_compiler=09030_E_Impossível chamar o compilador recursos "$1", mudando para modo externo
+% An error occurred when calling a resource compiler. The compiler will produce
+% a script that can be used to assemble, compile resources and link or
+% postprocess the program.
+exec_e_cant_open_resource_file=09031_E_Impossível abrir arquivo recursos "$1"
+% An error occurred resource file cannot be opened.
+exec_e_cant_write_resource_file=09032_E_Impossível gravar arquivo recursos "$1"
+% An error occurred resource file cannot be written.
+exec_n_backquote_cat_file_not_found=09033_N_Arquivo "$1" não encontrado para comando 'cat' entre aspas
+% The compiler did not find the file that should be expanded into linker parameters
+%\end{description}
+# EndOfTeX
+
+#
+# Executable information
+#
+# 09134 is the last used one
+#
+# BeginOfTeX
+% \section{Executable information messages.}
+% This section lists all messages that the compiler emits when an executable program is produced,
+% and only when the internal linker is used.
+% \begin{description}
+execinfo_f_cant_process_executable=09128_F_Impossível pós-processar executável $1
+% Fatal error when the compiler is unable to post-process an executable.
+execinfo_f_cant_open_executable=09129_F_Impossível abrir executável $1
+% Fatal error when the compiler cannot open the file for the executable.
+execinfo_x_codesize=09130_X_Tamanho do Código: $1 bytes
+% Informational message showing the size of the produced code section.
+execinfo_x_initdatasize=09131_X_Tamanho dos dados inicializados: $1 bytes
+% Informational message showing the size of the initialized data section.
+execinfo_x_uninitdatasize=09132_X_Tamanho dos dados não inicializados: $1 bytes
+% Informational message showing the size of the uninitialized data section.
+execinfo_x_stackreserve=09133_X_Espaço da Pilha reservado: $1 bytes
+% Informational message showing the stack size that the compiler reserved for the executable.
+execinfo_x_stackcommit=09134_X_Espaço da Pilha confirmado: $1 bytes
+% Informational message showing the stack size that the compiler committed for the executable.
+%\end{description}
+# EndOfTeX
+
+#
+# Internal linker messages
+#
+# 09200 is the last used one
+#
+# BeginOfTeX
+% \section{Linker messages}
+% This section lists messages produced by internal linker.
+% \begin{description}
+link_f_executable_too_big=09200_F_Tamanho imagem executável é muito grande para alvo $1.
+% Fatal error when resulting executable is too big.
+link_w_32bit_absolute_reloc=09201_W_Arquivo objeto "$1" contêm relocação absoluta de 32-bits para símbolo "$2".
+% Warning when 64-bit object file contains 32-bit absolute relocations.
+% In such case an executable image can be loaded into lower 4Gb of
+% address space only.
+%\end{description}
+# EndOfTeX
+
+#
+# Unit loading
+#
+# 10062 is the last used one
+#
+# BeginOfTeX
+% \section{Unit loading messages.}
+% This section lists all messages that can occur when the compiler is
+% loading a unit from disk into memory. Many of these messages are
+% informational messages.
+% \begin{description}
+unit_t_unitsearch=10000_T_Busca Unidade: $1
+% When you use the \var{-vt} option, the compiler tells you where it tries to find
+% unit files.
+unit_t_ppu_loading=10001_T_Carregando PPU $1
+% When the \var{-vt} switch is used, the compiler tells you
+% what units it loads.
+unit_u_ppu_name=10002_U_Nome PPU: $1
+% When you use the \var{-vu} flag, the unit name is shown.
+unit_u_ppu_flags=10003_U_PPU 'Flags': $1
+% When you use the \var{-vu} flag, the unit flags are shown.
+unit_u_ppu_crc=10004_U_PPU 'Crc': $1
+% When you use the \var{-vu} flag, the unit CRC check is shown.
+unit_u_ppu_time=10005_U_Hora PPU: $1
+% When you use the \var{-vu} flag, the time the unit was compiled is shown.
+unit_u_ppu_file_too_short=10006_U_Arquivo PPU muito pequeno
+% The ppufile is too short, not all declarations are present.
+unit_u_ppu_invalid_header=10007_U_Cabeçalho PPU inválido (sem PPU no começo)
+% A unit file contains as the first three bytes the ASCII codes of the characters \var{PPU}.
+unit_u_ppu_invalid_version=10008_U_Versão PPU inválida $1
+% This unit file was compiled with a different version of the compiler, and
+% cannot be read.
+unit_u_ppu_invalid_processor=10009_U_PPU foi compilado para outro processador
+% This unit file was compiled for a different processor type, and
+% cannot be read.
+unit_u_ppu_invalid_target=10010_U_PPU foi compilado para outro alvo
+% This unit file was compiled for a different target, and
+% cannot be read.
+unit_u_ppu_source=10011_U_Fonte PPU: $1
+% When you use the \var{-vu} flag, the unit source file name is shown.
+unit_u_ppu_write=10012_U_Gravando $1
+% When you specify the \var{-vu} switch, the compiler will tell you where it
+% writes the unit file.
+unit_f_ppu_cannot_write=10013_F_Impossível gravar arquivo PPU
+% An error occurred when writing the unit file.
+unit_f_ppu_read_error=10014_F_Erro ao ler arquivo PPU
+% This means that the unit file was corrupted, and contains invalid
+% information. Recompilation will be necessary.
+unit_f_ppu_read_unexpected_end=10015_F_Fim de arquivo PPU inesperado
+% Unexpected end of file. This may mean that the PPU file is
+% corrupted.
+unit_f_ppu_invalid_entry=10016_F_Entrada inválida arquivo PPU: $1
+% The unit the compiler is trying to read is corrupted, or generated with a
+% newer version of the compiler.
+unit_f_ppu_dbx_count_problem=10017_F_Problema contagem Dbx PPU
+% There is an inconsistency in the debugging information of the unit.
+unit_e_illegal_unit_name=10018_E_Nome unidade ilegal: $1
+% The name of the unit does not match the file name.
+unit_f_too_much_units=10019_F_Muitas unidades
+% \fpc has a limit of 1024 units in a program. You can change this behavior
+% by changing the \var{maxunits} constant in the \file{fmodule.pas} file of the
+% compiler, and recompiling the compiler.
+unit_f_circular_unit_reference=10020_F_Referência circular em unidade entre $1 e $2
+% Two units are using each other in the interface part. This is only allowed
+% in the \var{implementation} part. At least one unit must contain the other one
+% in the \var{implementation} section.
+unit_f_cant_compile_unit=10021_F_Impossível compilar unidade $1, nenhum fonte disponível
+% A unit was found that needs to be recompiled, but no sources are
+% available.
+unit_f_cant_find_ppu=10022_F_Impossível localizar unidade $1 usada por $2
+% You tried to use a unit of which the PPU file isn't found by the
+% compiler. Check your configuration file for the unit paths.
+unit_w_unit_name_error=10023_W_Unidade $1 não foi encontrada mas $2 existe
+% This error message is no longer used.
+unit_f_unit_name_error=10024_F_Unidade $1 foi procurada mas $2 encontrada
+% \dos truncation of 8 letters for unit PPU files
+% may lead to problems when unit name is longer than 8 letters.
+unit_w_switch_us_missed=10025_W_Compilar a unidade 'system' requer a chave -Us
+% When recompiling the system unit (it needs special treatment), the
+% \var{-Us} switch must be specified.
+unit_f_errors_in_unit=10026_F_Houveram $1 erros ao compilar módulo, parando
+% When the compiler encounters a fatal error or too many errors in a module
+% then it stops with this message.
+unit_u_load_unit=10027_U_Carregar de $1 ($2) unidade $3
+% When you use the \var{-vu} flag, which unit is loaded from which unit is
+% shown.
+unit_u_recompile_crc_change=10028_U_Recompilando $1, 'checksum' alterado para $2
+% The unit is recompiled because the checksum of a unit it depends on has
+% changed.
+unit_u_recompile_source_found_alone=10029_U_Recompilando $1, apenas fonte encontrado
+% When you use the \var{-vu} flag, these messages tell you why the current
+% unit is recompiled.
+unit_u_recompile_staticlib_is_older=10030_U_Recompilando unidade, bib estática é mais antiga que o arquivo ppu
+% When you use the \var{-vu} flag, the compiler warns if the static library
+% of the unit is older than the unit file itself.
+unit_u_recompile_sharedlib_is_older=10031_U_Recompilando unidade, bib compartilhada é mais antiga que o arquivo ppu
+% When you use the \var{-vu} flag, the compiler warns if the shared library
+% of the unit is older than the unit file itself.
+unit_u_recompile_obj_and_asm_older=10032_U_Recompilando unidade, 'obj' e 'asm' são mais antigos que o arquivo ppu
+% When you use the \var{-vu} flag, the compiler warns if the assembler or
+% object file of the unit is older than the unit file itself.
+unit_u_recompile_obj_older_than_asm=10033_U_Recompilando unidade, 'obj' é mais antigo que 'asm'
+% When you use the \var{-vu} flag, the compiler warns if the assembler
+% file of the unit is older than the object file of the unit.
+unit_u_parsing_interface=10034_U_Analisando 'interface' de $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% parsing the interface part of the unit.
+unit_u_parsing_implementation=10035_U_Analisando 'implementation' de $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% parsing the implementation part of the unit.
+unit_u_second_load_unit=10036_U_Segundo carregamento para a unidade $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% recompiling a unit for the second time. This can happen with
+% interdependent units.
+unit_u_check_time=10037_U_PPU Verifique arquivo $1 hora $2
+% When you use the \var{-vu} flag, the compiler shows the filename and
+% date and time of the file on which a recompile depends.
+### The following two error msgs is currently disabled.
+#unit_h_cond_not_set_in_last_compile=10038_H_Conditional $1 was not set at startup in last compilation of $2
+#% when recompilation of an unit is required the compiler will check that
+#% the same conditionals are set for the recompiliation. The compiler has
+#% found a conditional that currently is defined, but was not used the last
+#% time the unit was compiled.
+#unit_h_cond_set_in_last_compile=10039_H_Conditional $1 was set at startup in last compilation of $2
+#% when recompilation of an unit is required the compiler will check that
+#% the same conditionals are set for the recompiliation. The compiler has
+#% found a conditional that was used the last time the unit was compiled, but
+#% the conditional is currently not defined.
+unit_w_cant_compile_unit_with_changed_incfile=10040_W_Impossível recompilar unidade $1, mas encontrados arquivos de inclusão modificados
+% A unit was found to have modified include files, but
+% some source files were not found, so recompilation is impossible.
+unit_u_source_modified=10041_U_Arquivo $1 é mais novo que o usado para criar o arquivo PPU $2
+% A modified source file for a compiler unit was found.
+unit_u_ppu_invalid_fpumode=10042_U_Tentando usar uma unidade que foi compilada com um modo diferente de FPU
+% Trying to compile code while using units which were not compiled with
+% the same floating point format mode. Either all code should be compiled
+% with FPU emulation on, or with FPU emulation off.
+unit_u_loading_interface_units=10043_U_Carregando unidades 'interface' de $1
+% When you use the \var{-vu} flag, the compiler warns that it is starting
+% to load the units defined in the interface part of the unit.
+unit_u_loading_implementation_units=10044_U_Carregando unidades 'implementation' de $1
+% When you use the \var{-vu} flag, the compiler warns that it is starting
+% to load the units defined in the implementation part of the unit.
+unit_u_interface_crc_changed=10045_U_Interface CRC alterado para a unidade $1
+% When you use the \var{-vu} flag, the compiler warns that the
+% CRC calculated for the interface has been changed after the implementation
+% has been parsed.
+unit_u_implementation_crc_changed=10046_U_Implementation CRC alterado para a unidade $1
+% When you use the \var{-vu} flag, the compiler warns that the
+% CRC calculated has been changed after the implementation
+% has been parsed.
+unit_u_finished_compiling=10047_U_Terminada a compilação da unidade $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has finished compiling the unit.
+unit_u_add_depend_to=10048_U_Adição dependência: $1 depende de $2
+% When you use the \var{-vu} flag, the compiler warns that it
+% has added a dependency between the two units.
+unit_u_no_reload_is_caller=10049_U_Nenhum recarregamento, é o chamador: $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% will not reload the unit because it is the unit that wants
+% to load this unit.
+unit_u_no_reload_in_second_compile=10050_U_Nenhum recarregamento, já em segunda compilação: $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% will not reload the unit because it is already in a second recompile.
+unit_u_flag_for_reload=10051_U_'Flag' para recarregamento: $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has to reload the unit.
+unit_u_forced_reload=10052_U_Recarregamento forçado
+% When you use the \var{-vu} flag, the compiler warns that it
+% is reloading the unit because it was required.
+unit_u_previous_state=10053_U_Estado anterior de $1: $2
+% When you use the \var{-vu} flag, the compiler shows the
+% previous state of the unit.
+unit_u_second_compile_unit=10054_U_Já compilando $1, ajustando segunda compilação
+% When you use the \var{-vu} flag, the compiler warns that it is starting
+% to recompile a unit for the second time. This can happen with interdependent
+% units.
+unit_u_loading_unit=10055_U_Carregando unidade $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% loading the unit.
+unit_u_finished_loading_unit=10056_U_Terminado carregamento unidade $1
+% When you use the \var{-vu} flag, the compiler warns that it finished
+% loading the unit.
+unit_u_registering_new_unit=10057_U_Registrando nova unidade $1
+% When you use the \var{-vu} flag, the compiler warns that it has
+% found a new unit and is registering it in the internal lists.
+unit_u_reresolving_unit=10058_U_Re-solucionando unidade $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has to recalculate the internal data of the unit.
+unit_u_skipping_reresolving_unit=10059_U_Pulando re-solução unidade $1, ainda carregando unidades usadas
+% When you use the \var{-vu} flag, the compiler warns that it is
+% skipping the recalculation of the internal data of the unit
+% because there is no data to recalculate.
+unit_u_unload_resunit=10060_U_Descarregando unidade recursos $1 (não necessária)
+% When you use the \var{-vu} flag, the compiler warns that it is unloading the
+% resource handling unit, since no resources are used.
+unit_e_different_wpo_file=10061_E_Unidade $1 foi compilada usando uma entrada de retorno inteiramente diferente de otimização de programa ($2, $3); recompile-a sem 'wpo' ou use o mesmo arquivo de retorno de entrada 'wpo' para esta compilação
+% When a unit has been compiled using a particular whole program optimization (wpo) feedback file (\var{-FW<x>} \var{-OW<x>}),
+% this compiled version of the unit is specialised for that particular compilation scenario and cannot be used in
+% any other context. It has to be recompiled before you can use it in another program or with another wpo feedback input file.
+unit_u_indirect_crc_changed=10062_U_CRC interface indireta (objetos/classes) alterado para a unidade $1
+% When you use the \var{-vu} flag, the compiler warns that the
+% indirect CRC calculated for the unit (this is the CRC of all classes/objects/interfaces/$\ldots$
+% in the interfaces of units directly or indirectly used by this unit in the interface) has been changed after the
+% implementation has been parsed.
+% \end{description}
+# EndOfTeX
+
+#
+# Options
+#
+# 11049 is the last used one
+#
+option_usage=11000_O_$1 [options] <inputfile> [options]
+# BeginOfTeX
+%
+% \section{Command line handling errors}
+% This section lists errors that occur when the compiler is processing the
+% command line or handling the configuration files.
+% \begin{description}
+option_only_one_source_support=11001_W_Apenas uma arquivo fonte suportado, alterando arquivo fonte à compilar de "$1" para "$2"
+% You can specify only one source file on the command line. The last
+% one will be compiled, others will be ignored. This may indicate that
+% you forgot a \var{'-'} sign.
+option_def_only_for_os2=11002_W_Arquivo DEF pode ser criado apenas para OS/2
+% This option can only be specified when you're compiling for OS/2.
+option_no_nested_response_file=11003_E_Arquivos respostas aninhados não são suportados
+% You cannot nest response files with the \var{@file} command line option.
+option_no_source_found=11004_F_Nenhm nome arquivo fonte na linha de comando
+% The compiler expects a source file name on the command line.
+option_no_option_found=11005_N_Nenhuma opção dentro do arquivo de configurações $1
+% The compiler didn't find any option in that config file.
+option_illegal_para=11006_E_Parâmetro ilegal: $1
+% You specified an unknown option.
+option_help_pages_para=11007_H_-? lista páginas ajuda
+% When an unknown option is given, this message is diplayed.
+option_too_many_cfg_files=11008_F_Muitos arquivos de configurações aninhados
+% You can only nest up to 16 config files.
+option_unable_open_file=11009_F_Incapaz de abrir arquivo $1
+% The option file cannot be found.
+option_reading_further_from=11010_D_Lendo demais opções de $1
+% Displayed when you have notes turned on, and the compiler switches
+% to another options file.
+option_target_is_already_set=11011_W_Alvo já está ajustado para: $1
+% Displayed if more than one \var{-T} option is specified.
+option_no_shared_lib_under_dos=11012_W_Bibs compartilhadas não são suportadas pela plataforma DOS, revertendo para estática
+% If you specify \var{-CD} for the \dos platform, this message is displayed.
+% The compiler supports only static libraries under \dos.
+option_too_many_ifdef=11013_F_No arquivo opções $1 na linha $2 muitos \var{\#IF(N)DEFs} encontrados
+% The \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_too_many_endif=11014_F_No arquivo opções $1 na linha $2 encontrados \var{\#ENDIFs} inesperados
+% The \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_too_less_endif=11015_F_Condicional aberta no final do arquivo de opções
+% The \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_no_debug_support=11016_W_Geração de informações depuração não é suportada por este executável
+% It is possible to have a compiler executable that doesn't support
+% the generation of debugging info. If you use such an executable with the
+% \var{-g} switch, this warning will be displayed.
+option_no_debug_support_recompile_fpc=11017_H_Tente recompilar com -dGDB
+% It is possible to have a compiler executable that doesn't support
+% the generation of debugging info. If you use such an executable with the
+% \var{-g} switch, this warning will be displayed.
+option_obsolete_switch=11018_W_Você esta usando uma chave obsoleta $1
+% This warns you when you use a switch that is not needed/supported anymore.
+% It is recommended that you remove the switch to overcome problems in the
+% future, when the meaning of the switch may change.
+option_obsolete_switch_use_new=11019_W_Você esta usando uma chave obsoleta $1, favor usar $2
+% This warns you when you use a switch that is not supported anymore. You
+% must now use the second switch instead.
+% It is recommended that you change the switch to overcome problems in the
+% future, when the meaning of the switch may change.
+option_switch_bin_to_src_assembler=11020_N_Mudando montador assembler para o padrão escrita de fontes
+% This notifies you that the assembler has been changed because you used the
+% -a switch, which can't be used with a binary assembler writer.
+option_incompatible_asm=11021_W_Saída Assembler selecionado "$1" incompatível com "$2"
+option_asm_forced=11022_W_"$1" uso forçado montador assembler
+% The assembler output selected cannot generate
+% object files with the correct format. Therefore, the
+% default assembler for this target is used instead.
+option_using_file=11026_T_Lendo opções do arquivo $1
+% Options are also read from this file.
+option_using_env=11027_T_Lendo opções do ambiente $1
+% Options are also read from this environment string.
+option_handling_option=11028_D_Manipulando opção "$1"
+% Debug info that an option is found and will be handled.
+option_help_press_enter=11029_O_*** pressione <enter> ***
+% Message shown when help is shown page per page. When pressing the ENTER
+% Key, the next page of help is shown. If you press q and then ENTER, the
+% compiler exits.
+option_start_reading_configfile=11030_H_Início leitura do arquivo configuração $1
+% Start of configuration file parsing.
+option_end_reading_configfile=11031_H_Final leitura do arquivo configuração $1
+% End of configuration file parsing.
+option_interpreting_option=11032_D_Interpretando opção "$1"
+% The compiler is interpreting an option
+option_interpreting_firstpass_option=11036_D_Interpretando primeiro passo opção "$1"
+% The compiler is interpreting an option for the first time.
+option_interpreting_file_option=11033_D_Interpretando opção arquivo "$1"
+% The compiler is interpreting an option which it read from the configuration file.
+option_read_config_file=11034_D_Lendo arquivo configuração "$1"
+% The compiler is starting to read the configuration file.
+option_found_file=11035_D_Nome arquivo fonte encontrado "$1"
+% Additional information about options.
+% Displayed when you have the debug option turned on.
+option_code_page_not_available=11039_E_Codepage desconhecido
+% An unknown codepage for the source files was requested.
+% The compiler is compiled with support for several codepages built-in.
+% The requested codepage is not in that list. You will need to recompile
+% the compiler with support for the codepage you need.
+option_config_is_dir=11040_F_Arquivo configuração $1 é um diretório
+% Directories cannot be used as configuration files.
+option_confict_asm_debug=11041_W_Saída montador Assembler selecionado "$1" não pode gerar informações depuração, depuração desabilitada
+% The selected assembler output cannot generate
+% debugging information, debugging option is therefore disabled.
+option_ppc386_deprecated=11042_W_Uso de 'ppc386.cfg' está depreciado, favor usar 'fpc.cfg'
+% Using ppc386.cfg is still supported for historical reasons, however, for a multiplatform
+% system the naming makes no sense anymore. Please continue to use fpc.cfg instead.
+option_else_without_if=11043_F_No arquivo opções $1 na linha $2 diretiva \var{\#ELSE} sem \var{\#IF(N)DEF} encontrada
+% An \var{\#ELSE} statement was found in the options file without a matching \var{\#IF(N)DEF} statement.
+option_unsupported_target=11044_F_Opção "$1" não é, ou ainda não é, suportada pela plataforma alvo atual
+% Not all options are supported or implemented for all target platforms. This message informs you that a chosen
+% option is incompatible with the currently selected target platform.
+option_unsupported_target_for_feature=11045_F_A característica "$1" não é, ou ainda não é, suportada pela plataforma alvo selecionada
+% Not all features are supported or implemented for all target platforms. This message informs you that a chosen
+% feature is incompatible with the currently selected target platform.
+option_dwarf_smart_linking=11046_N_Informação de depuração DWARF não pode ser usada com vinculação inteligente neste alvo, mudando para vinculação estática
+% Smart linking is currently incompatble with DWARF debug information on most
+% platforms, so smart linking is disabled in such cases.
+option_ignored_target=11047_W_Opção "$1" ignorada pela plataforma alvo atual
+% Not all options are supported or implemented for all target platforms. This message informs you that a chosen
+% option is ignored for the currently selected target platform.
+option_debug_external_unsupported=11048_W_Desabilitando informação externa depuração porque não é suportada pela combinação formato alvo/depuração selecionado.
+% Not all debug formats can be stored in an external file on all platforms. In particular, on
+% Mac OS X only DWARF debug information can be stored externally.
+option_dwarf_smartlink_creation=11049_N_Informação de depuração DWARF não pode ser usada com vinculação inteligente com assembler externo, desabilitando criação de biblioteca estática.
+% Smart linking is currently incompatble with DWARF debug information on most
+% platforms, so smart linking is disabled in such cases.
+%\end{description}
+# EndOfTeX
+
+#
+# Whole program optimization
+#
+# 12019 is the last used one
+#
+# BeginOfTeX
+%
+% \section{Whole program optimization messages}
+% This section lists errors that occur when the compiler is performing
+% whole program optimization.
+% \begin{description}
+wpo_cant_find_file=12000_F_Impossível abrir arquivo de retorno de otimização completa de programa "$1"
+% The compiler cannot open the specified feedback file with whole program optimization information.
+wpo_begin_processing=12001_D_Processando informações de otimização completa de programa no arquivo retorno 'wpo' "$1"
+% The compiler starts processing whole program optimization information found in the named file.
+wpo_end_processing=12002_D_Terminado processamento de otimização completea de programa no arquivo retorno 'wpo' "$1"
+% The compiler has finished processing the whole program optimization information found in the named file.
+wpo_expected_section=12003_E_Seção cabeçalho esperada, mas obtido "$2" na linhae $1 do arquivo retorno 'wpo'
+% The compiler expected a section header in the whole program optimization file (starting with \%),
+% but did not find it.
+wpo_no_section_handler=12004_W_Nenhum manipulador registrado para seção otimização completa de programa "$2" na linha $1 do arquivo de retorno 'wpo', ignorando
+% The compiler has no handler to deal with the mentioned whole program optimization information
+% section, and will therefore ignore it and skip to the next section.
+wpo_found_section=12005_D_Encontrada seção otimização completa de programa "$1" com informações sobre "$2"
+% The compiler encountered a section with whole program optimization information, and according
+% to its handler this section contains information usable for the mentioned purpose.
+wpo_no_input_specified=12006_F_As otimizações completas de programa selecionadas requerem um arquivo de retorno previamente gerado (use -Fw para especificar)
+% The compiler needs information gathered during a previous compilation run to perform the selected
+% whole program optimizations. You can specify the location of the feedback file containing this
+% information using the -Fw switch.
+wpo_not_enough_info=12007_E_Nenhuma informação coletada necessária para realizar "$1" otimização completa programa foi encontrada
+% While you pointed the compiler to a file containing whole program optimization feedback, it
+% did not contain the information necessary to perform the selected optimizations. You most likely
+% have to recompile the program using the appropate -OWxxx switch.
+wpo_no_output_specified=12008_F_Especifique um arquivo de retorno de otimização completa programa para armazenar as informações geradas (usando -FW)
+% You have to specify the feedback file in which the compiler has to store the whole program optimization
+% feedback that is generated during the compilation run. This can be done using the -FW switch.
+wpo_output_without_info_gen=12009_E_Não gerando qualquer informação otimização completa programa, assim mesmo um arquivo de retorno foi especificado (usando -FW)
+% The compiler was instructed to store whole program optimization feedback into a file specified using -FW,
+% but not to actually generated any whole program optimization feedback. The classes of to be
+% generated information can be speciied using -OWxxx.
+wpo_input_without_info_use=12010_E_Não realizando qualquer otimização completa programa, assim mesmo um arquivo de retorno foi especificado (usando -Fw)
+% The compiler was not instructed to perform any whole program optimizations (no -Owxxx parameters),
+% but nevertheless an input file with such feedback was specified (using -Fwyyy). Since this can
+% indicate that you forgot to specify an -Owxxx parameter, the compiler generates an error in this case.
+wpo_skipping_unnecessary_section=12011_D_Pulando seção otimização completa programa "$1", porque não é necessária pelas otimizações solicitadas
+% The whole program optimization feedback file contains a section with information that is not
+% required by the selected whole program optimizations.
+wpo_duplicate_wpotype=12012_W_Sobrepondo informações previamente lidas para "$1" do arquivo entrada retorno usando informações na seção "$2"
+% The feedback file contains multiple sections that provide the same class of information (e.g.,
+% information about which virtual methods can be devirtualized). In this case, the information in last encountered
+% section is used. Turn on debugging output (-vd) to see which class of information is provided by each section.
+wpo_cannot_extract_live_symbol_info_strip=12013_E_Impossível extrair informações de vida de símbolos do programa durante eliminação símbolos, use -Xs-
+% Certain symbol liveness collectors extract the symbol information from the linked program. If the symbol information
+% is stripped (option -Xs), this is not possible.
+wpo_cannot_extract_live_symbol_info_no_link=12014_E_Impossível extrair informações de vida de símbolos do programa quando não vinculando
+% Certain symbol liveness collectors extract the symbol information from the linked program. If the program is not
+% linked by the compiler, this is not possible.
+wpo_cannot_find_symbol_progs=12015_F_Impossível encontrar "$1" ou "$2" para extrair informações de vida de símbolos do programa vinculado
+% Certain symbol liveness collectors need a helper program to extract the symbol information from the linked program.
+% This helper program is normally 'nm', which is part of the GNU binutils.
+wpo_error_reading_symbol_file=12016_E_Erro durante leitura das informações de vída de símbolos produzidas por "$1"
+% An error occurred during the reading of the symbol liveness file that was generated using the 'nm' or 'objdump' program. The reason
+% can be that it was shorter than expected, or that its format was not understood.
+wpo_error_executing_symbol_prog=12017_F_Erro executando "$1" (código saída: $2) para extrair informações de símbolos do programa vinculado
+% Certain symbol liveness collectors need a helper program to extract the symbol information from the linked program.
+% The helper program produced the reported error code when it was run on the linked program.
+wpo_symbol_live_info_needs_smart_linking=12018_E_Coleção de informações de vida de símbolos pode ajudar apenas quando usando vinculação inteligente, use -CX -XX
+% Whether or not a symbol is live is determined by looking whether it exists in the final linked program.
+% Without smart linking/dead code stripping, all symbols are always included, regardless of whether they are
+% actually used or not. So in that case all symbols will be seen as live, which makes this optimization ineffective.
+wpo_cant_create_feedback_file=12019_E_Impossível criar arquivo retorno otimizações completas de programa especificado "$1"
+% The compiler is unable to create the file specified using the -FW parameter to store the whole program optimisation information.
+%\end{description}
+# EndOfTeX
+
+
+#
+# Logo (option -l)
+#
+option_logo=11023_[
+Compilador Free Pascal versão $FPCFULLVERSION [$FPCDATE] para $FPCCPU
+Copyright (c) 1993-2011 by Florian Klaempfl
+]
+
+#
+# Info (option -i)
+#
+option_info=11024_[
+Compilador Free Pascal versão $FPCVERSION
+
+Data Compilador : $FPCDATE
+CPU Alvo Copilador : $FPCCPU
+
+Alvos suportados:
+ $OSTARGETS
+
+Conjunto de instruções CPU suportados:
+ $INSTRUCTIONSETS
+
+Conjunto de instruções FPU suportados:
+ $FPUINSTRUCTIONSETS
+
+Alvos ABI suportados:
+ $ABITARGETS
+
+Otimizações suportadas:
+ $OPTIMIZATIONS
+
+Otimizaçõs Completas Programa suportadas:
+ Todas
+ $WPOPTIMIZATIONS
+
+Tipos Microcontroladores suportados:
+ $CONTROLLERTYPES
+
+Este programa é oferecido sob a Licença Geral Pública GNU
+Para maiores informações leia COPYING.FPC
+
+Reportar falhas, sugestões, etc. para:
+ http://bugs.freepascal.org
+ou
+ bugs@freepascal.org
+]
+
+#
+# Help pages (option -? and -h)
+#
+# The first character on the line indicates who will display this
+# line, the current possibilities are :
+# * = every target
+# 3 = 80x86 targets
+# 4 = x86_64
+# 6 = 680x0 targets
+# A = ARM
+# e = in extended debug mode only
+# P = PowerPC targets
+# S = Sparc targets
+# V = Virtual machine targets
+# The second character also indicates who will display this line,
+# (if the above character was TRUE) the current possibilities are :
+# * = everyone
+# g = with GDB info supported by the compiler
+# O = OS/2
+# L = UNIX systems
+# The third character represents the indentation level.
+#
+option_help_pages=11025_[
+**0*_Ponha + após uma chave de opção booleana para habilitá-la, - para desabilitá-la
+**1a_O compilador não elimina o arquivo gerado do montador assembler
+**2al_Lista linhas do código fonte no arquivo assembler
+**2an_Lista informações nó no arquivo assembler
+*L2ap_Usa encadeadores (pipes) em vez de criar arquivos temporários assembler
+**2ar_Lista informações alocação/liberação registros no arquivo assembler
+**2at_Lista informações temporárias alocação/liberação no arquivo assembler
+**1A<x>_Formato saída:
+**2Adefault_Usa montador assembler padrão
+3*2Aas_Monta usando o GNU AS
+3*2Amacho_Mach-O (Darwin, Intel 32 bit) usando gravador interno
+3*2Anasmcoff_Arquivo COFF (Go32v2) usando Nasm
+3*2Anasmelf_Arquivo ELF32 (Linux) usando Nasm
+3*2Anasmwin32_Arquivo objeto Win32 usando Nasm
+3*2Anasmwdosx_Arquivo objeto Win32/WDOSX usando Nasm
+3*2Awasm_Arquivo Obj usando Wasm (Watcom)
+3*2Anasmobj_Arquivo Obj usando Nasm
+3*2Amasm_Arquivo Obj usando Masm (Microsoft)
+3*2Atasm_Arquivo Obj usando Tasm (Borland)
+3*2Aelf_ELF (Linux) usando gravador interno
+3*2Acoff_COFF (Go32v2) usando gravador interno
+3*2Apecoff_PE-COFF (Win32) usando gravador interno
+4*2Aas_Monta usando o GNU AS
+4*2Agas_Monta usando o GNU GAS
+4*2Agas-darwin_Monta darwin Mach-O64 usando GNU GAS
+4*2Amasm_Win64 arquivo objeto usando ml64 (Microsoft)
+4*2Apecoff_PE-COFF (Win64) usando escritor interno
+4*2Aelf_ELF (Linux-64bit) usando escritor interno
+6*2Aas_Arquivo Unix .o usando o GNU AS
+6*2Agas_Montador assembler GNU Motorola
+6*2Amit_Sintaxe MIT (antigo GAS)
+6*2Amot_Montador assembler Motorola padrão
+A*2Aas_Monta usando o GNU AS
+P*2Aas_Monta usando o GNU AS
+S*2Aas_Monta usando o GNU AS
+**1b_Gera informações navegador
+**2bl_Gera informações símbolos locais
+**1B_Constrói todos os módulos
+**1C<x>_Opções geração de código:
+**2C3<x>_Ligar verificação de erro ieee para constantes
+**2Ca<x>_Seleciona ABI, veja fpc -i para possíveis valores
+**2Cb_Gera código 'big-endian'
+**2Cc<x>_Ajusta convenção de chamada para <x>
+**2CD_Cria também biblioteca dinâmica (não suportado)
+**2Ce_Compilação com opcodes de ponto flutuante emulados
+**2Cf<x>_Seleciona conjunto de instruções fpu a usar, veja fpc -i para possíveis valores
+**2CF<x>_Precisão mínima constante ponto flutuante (padrão, 32, 64)
+**2Cg_Gera código PIC
+**2Ch<n>_<n> bytes heap (entre 1023 e 67107840)
+**2Ci_Verificação E/S
+**2Cn_Omite estágio vinculação
+**2Co_Verifica transbordamento de operações inteiras
+**2CO_Verifica possível transbordamento de operações inteiras
+**2Cp<x>_Seleciona conjunto de instruções, veja fpc -i para possíves valores
+**2CP<x>=<y>_ Ajustes compactação
+**3CPPACKSET=<y>_ <y> conjunto alocação: 0, 1 ou DEFAULT ou NORMAL, 2, 4 e 8
+**2Cr_Verificação de faixa
+**2CR_Verifica validade de chamada de método de objeto
+**2Cs<n>_Ajusta verificação tamanho da Pilha para <n>
+**2Ct_Verificação Pilha (apenas para testes, veja manual)
+**2CX_Cria também biblioteca inteligentemente vinculada
+**1d<x>_Define o símbolo <x>
+**1D_Gera um arquivo DEF
+**2Dd<x>_Ajusta descrição para <x>
+**2Dv<x>_Ajusta versão DLL para <x>
+*O2Dw_Aplicação PM
+**1e<x>_Ajusta caminho para executável
+**1E_Mesmo que -Cn
+**1fPIC_Mesmo que -Cg
+**1F<x>_Ajusta nomes de arquivo e caminhos:
+**2Fa<x>[,y]_(para um programa) carregar unidades <x> e [y] antes de analisar cláusula 'uses'
+**2Fc<x>_Ajusta entrada página de código para <x>
+**2FC<x>_Ajusta nome do compilador RC binário para <x>
+**2Fd_Disabilita o cache de diretórios interno do compilador
+**2FD<x>_Ajusta o diretório onde procurar por utilitários para o compilador
+**2Fe<x>_Redireciona saída erros para <x>
+**2Ff<x>_Adiciona <x> ao caminho framework (apenas Darwin)
+**2FE<x>_Ajusta caminho saída exe/unidade para <x>
+**2Fi<x>_Adiciona <x> ao caminho inclusões
+**2Fl<x>_Adiciona <x> ao caminho bibliotecas
+**2FL<x>_Use <x> como vinculador dinâmico
+**2Fm<x>_Carrega tabela conversão unicode de <x>.txt no dir. do compilador
+**2Fo<x>_Adiciona <x> ao caminho objetos
+**2Fr<x>_Carrega o arquivo mensagens erro <x>
+**2FR<x>_Ajusta vinculador recursos (.res) para <x>
+**2Fu<x>_Adiciona <x> ao caminho unidades
+**2FU<x>_Ajusta caminho saída unidade para <x>, sobrepõe -FE
+**2FW<x>_Armazena retorno otimização completa programa gerada em <x>
+**2Fw<x>_Carrega retorno otimização completa programa previamente armazenada de <x>
+*g1g_Gerar informações depuração (formato padrão para o alvo)
+*g2gc_Gerar verificações para ponteiros
+*g2gh_Usa unidade heaptrace (para depuração vazamentos/corrupção memória)
+*g2gl_Usa unidade informações linha (mostra mais info. com backtraces)
+*g2go<x>_Ajusta opções informações depuração
+*g3godwarfsets_ Habilita 'conjunto' info. depuração DWARF (falhas gdb < 6.5)
+*g3gostabsabsincludes_ Armazena caminhos absolutos/completos arquivos inclusões em 'Stabs'
+*g3godwarfmethodclassprefix_ Prefixa nomes métodos com nome classe em DWARF
+*g2gp_Preserva caixa nomes símbolos em 'stabs'
+*g2gs_Gera informações depuração 'Stabs'
+*g2gt_Inutiliza variáveis locais (para detetar utilização de não-inicilizadas)
+*g2gv_Gera programas rastreáveis com 'Valgrind'
+*g2gw_Gera informações depuração DWARFv2 (mesmo que -gw2)
+*g2gw2_Gera informações depuração DWARFv2
+*g2gw3_Gera informações depuração DWARFv3
+*g2gw4_Gera informações depuração DWARFv4 (experimental)
+**1i_Informações
+**2iD_Retorna data compilador
+**2iV_Retorna versão compilador curta
+**2iW_Retorna versão compilador completa
+**2iSO_Retorna SO compilador
+**2iSP_Retorna processador servidor compilador
+**2iTO_Retorna SO alvo
+**2iTP_Retorna processador alvo
+**1I<x>_Adiciona <x> ao caminho inclusões
+**1k<x>_Passa <x> ao vinculador
+**1l_Grava logo
+**1M<x>_Ajusta modo linguagem para <x>
+**2Mfpc_Dialeto Free Pascal (padrão)
+**2Mobjfpc_Modo FPC com suporte ao Object Pascal
+**2Mdelphi_Modo compatibilidade Delphi 7
+**2Mtp_Modo compatibilidade TP/BP 7.0
+**2Mmacpas_Modo compatibilidade dialetos Macintosh Pascal
+**1n_Não ler os arquivos de configurações padrão
+**1N<x>_Otimizações nós árvore
+**2Nu_Desdobra laços
+**1o<x>_Altera o nome do executável produzido para <x>
+**1O<x>_Otimizações:
+**2O-_Disabilita otimizações
+**2O1_Nível 1 otimizações (rápida e amigável depurador)
+**2O2_Nível 2 otimizações (-O1 + otimizações rápidas)
+**2O3_Nível 3 otimizações (-O2 + otimizações lentas)
+**2Oa<x>=<y>_Ajusta alinhamento
+**2Oo[NO]<x>_Habilita ou desabilita otimizações, veja fpc -i para possíveis valores
+**2Op<x>_Ajusta cpu alvo para otimizações, veja fpc -i para possíveis valores
+**2OW<x>_Gera retorno otimização completa programa para otimizações <x>, veja fpc -i para possíveis valores
+**2Ow<x>_Realiza otimização completa programa <x>, veja fpc -i para possíveis valores
+**2Os_Otimiza tamanho ao invés de velocidade
+**1pg_Gera perfil código para 'gprof' (define FPC_PROFILE)
+**1R<x>_Estilo leitura Assembler:
+**2Rdefault_Use assembler padrão para alvo
+3*2Ratt_Leia assembler estilo AT&T
+3*2Rintel_Leia assembler estilo Intel
+6*2RMOT_Leia assembler estilo motorola
+**1S<x>_Opções sintaxe:
+**2S2_Mesmo que -Mobjfpc
+**2Sc_Suporte operadores similares C (*=,+=,/= and -=)
+**2Sa_Liga asserções
+**2Sd_Mesmo que -Mdelphi
+**2Se<x>_Opções erros. <x> é uma combinação do seguinte:
+**3*_<n> : Compilador para depois de <n> erros (padrão é 1)
+**3*_w : Compilador também para após avisos
+**3*_n : Compilador também para após notas
+**3*_h : Compilador também para após dicas
+**2Sg_Habilita LABEL e GOTO (padrão em -Mtp e -Mdelphi)
+**2Sh_Use 'ansistrings' por padrão ao invés de 'shortstrings'
+**2Si_Liga 'inlining' de procedimentos/funções declaradas como "em-linha" (inline)
+**2Sk_Carrega unidade 'fpcylix'
+**2SI<x>_Ajusta estilo interface para <x>
+**3SIcom_COM interface compatível (padrão)
+**3SIcorba_CORBA interface compatível
+**2Sm_Suporta macros semelhantes C (global)
+**2So_Mesmo que -Mtp
+**2Ss_Nome construtor deve ser 'init' (destruidor deve ser 'done')
+**2Sx_Habilita palavras-chave exceções (padrão nos modos Delphi/ObjFPC)
+**2Sy_@<ponteiro> retorna um ponteiro tipado, mesmo que $T+
+**1s_Não chama o montador assembler e o vinculador
+**2sh_Gera roteiro para vincular no servidor
+**2st_Gera roteiro para vincular no alvo
+**2sr_Pula fase alocação registro (use com -alr)
+**1T<x>_Sistema operacional alvo:
+3*2Tdarwin_Darwin/Mac OS X
+3*2Temx_OS/2 via EMX (incluidos extensor EMX/RSX)
+3*2Tfreebsd_FreeBSD
+3*2Tgo32v2_Versão 2 do extensor DOS DJ Delorie
+3*2Tiphonesim_ iPhoneSimulator do iOS SDK 3.2+ (versões antigas: -Tdarwin)
+3*2Tlinux_Linux
+3*2Tnetbsd_NetBSD
+3*2Tnetware_Módulo Novell Netware (clib)
+3*2Tnetwlibc_Módulo Novell Netware (libc)
+3*2Topenbsd_OpenBSD
+3*2Tos2_OS/2 / eComStation
+3*2Tsunos_SunOS/Solaris
+3*2Tsymbian_Symbian OS
+3*2Tsolaris_Solaris
+3*2Twatcom_Watcom compatible DOS extender
+3*2Twdosx_WDOSX DOS extender
+3*2Twin32_Windows 32 Bit
+3*2Twince_Windows CE
+4*2Tdarwin_Darwin/Mac OS X
+4*2Tlinux_Linux
+4*2Twin64_Win64 (sistemas Windows 64 bit)
+6*2Tamiga_Commodore Amiga
+6*2Tatari_Atari ST/STe/TT
+6*2Tlinux_Linux
+6*2Tpalmos_PalmOS
+A*2Tdarwin_Darwin/iPhoneOS/iOS
+A*2Tlinux_Linux
+A*2Twince_Windows CE
+P*2Tamiga_AmigaOS
+P*2Tdarwin_Darwin/Mac OS X
+P*2Tlinux_Linux
+P*2Tmacos_Mac OS (clássico)
+P*2Tmorphos_MorphOS
+S*2Tsolaris_Solaris
+S*2Tlinux_Linux
+**1u<x>_Indefine o símbolo <x>
+**1U_Opções unidades:
+**2Un_Não verifica onde o nome unidade coincide com o nome arquivo
+**2Ur_Gera arquivos lançamento unidades (nunca automaticamente recompilado)
+**2Us_Compilar uma unidade sistema
+**1v<x>_Ser detalhado. <x> é uma combinação das seguintes letras:
+**2*_e : Mostra erros (padrão) 0 : Nada mostra (exceto erros)
+**2*_w : Mostra avisos u : Mostra info. unidade
+**2*_n : Mostra notas t : Mostra arquivos tentados/usados
+**2*_h : Mostra dicas c : Mostra condicionais
+**2*_i : Mostra info. geral d : Mostra info. depuração
+**2*_l : Mostra números linhas r : Modo compatibilidade Rhide/GCC
+**2*_s : Mostra Data/Hora q : Mostra números mensagens
+**2*_a : Mostra tudo x : Info. executável (apenas Win32)
+**2*_b : Grava mensagens nome arqs. p : Grava tree.log com árvore análise
+**2*_ com caminho completo v : Grava fpcdebug.txt com muitas
+**2*_ informações de depuração
+**2*_m<x>,<y> : Não mostra mensagens numeradas <x> e <y>
+**1W<x>_Opções específicas do alvo (alvos)
+3*2WA_Especifica aplicação do tipo nativo (Windows)
+4*2WA_Especifica aplicação do tipo nativo (Windows)
+A*2WA_Especifica aplicação do tipo nativo (Windows)
+3*2Wb_Cria um encarte ao invés de uma biblioteca (Darwin)
+P*2Wb_Cria um encarte ao invés de uma biblioteca (Darwin)
+p*2Wb_Cria um encarte ao invés de uma biblioteca (Darwin)
+A*2Wb_Cria um encarte ao invés de uma biblioteca (Darwin)
+4*2Wb_Cria um encarte ao invés de uma biblioteca (Darwin)
+3*2WB_Cria uma imagem relocável (Windows, Symbian)
+3*2WBxxxx_Define base da imagem para xxxx (Windows, Symbian)
+4*2WB_Cria uma imagem relocável (Windows)
+4*2WBxxxx_Define base da imagem para xxxx (Windows)
+A*2WB_Cria uma imagem relocável (Windows, Symbian)
+A*2WBxxxx_Define base da imagem para xxxx (Windows, Symbian)
+3*2WC_Especifica aplicação do tipo console (EMX, OS/2, Windows)
+4*2WC_Especifica aplicação do tipo console (EMX, OS/2, Windows)
+A*2WC_Especifica aplicação do tipo console (Windows)
+P*2WC_Especifica aplicação do tipo console (Classic Mac OS)
+3*2WD_Usa DEFFILE para exportar funções de DLL ou EXE (Windows)
+4*2WD_Usa DEFFILE para exportar funções de DLL ou EXE (Windows)
+A*2WD_Usa DEFFILE para exportar funções de DLL ou EXE (Windows)
+3*2We_Usa recursos externos (Darwin)
+4*2We_Usa recursos externos (Darwin)
+A*2We_Usa recursos externos (Darwin)
+P*2We_Usa recursos externos (Darwin)
+p*2We_Usa recursos externos (Darwin)
+3*2WF_Especifica aplicação do tipo tela-cheia (EMX, OS/2)
+3*2WG_Especifica aplicação do tipo gráfica (EMX, OS/2, Windows)
+4*2WG_Especifica aplicação do tipo gráfica (EMX, OS/2, Windows)
+A*2WG_Especifica aplicação do tipo gráfica (Windows)
+P*2WG_Especifica aplicação do tipo gráfica (Classic Mac OS)
+3*2Wi_Usa recursos internos (Darwin)
+4*2Wi_Usa recursos internos (Darwin)
+A*2Wi_Usa recursos internos (Darwin)
+P*2Wi_Usa recursos internos (Darwin)
+p*2Wi_Usa recursos internos (Darwin)
+3*2WI_Liga/desliga o uso de seções de importação (Windows)
+4*2WI_Liga/desliga o uso de seções de importação (Windows)
+A*2WI_Liga/desliga o uso de seções de importação (Windows)
+3*2WN_Não gera código de relocação, necessário para depuração (Windows)
+4*2WN_Não gera código de relocação, necessário para depuração (Windows)
+A*2WN_Não gera código de relocação, necessário para depuração (Windows)
+A*2Wpxxxx_Especifica o tipo de controlador, veja fpc -i para valores possíveis
+V*2Wpxxxx_Especifica o tipo de controlador, veja fpc -i para valores possíveis
+3*2WR_Gera código de relocação (Windows)
+4*2WR_Gera código de relocação (Windows)
+A*2WR_Gera código de relocação (Windows)
+P*2WT_Especifica aplicação do tipo ferramenta MPW (Classic Mac OS)
+**2WX_Habilita pilha executável (Linux)
+**1X_Opções do executável:
+**2Xc_Passar --shared/-dynamic para o vinculador (BeOS, Darwin, FreeBSD, Linux)
+**2Xd_Não usar caminho padrão de busca de biblioteca (necessário para compilação cross)
+**2Xe_Usar vinculador externo
+**2Xg_Cria informação de depuração em um arquivo separado e adiciona uma seção de vínculo de depuração ao executável
+**2XD_Tenta vincular unidades dinamicamente (define FPC_LINK_DYNAMIC)
+**2Xi_Usa vinculador interno
+**2Xm_Gera mapa de vinculação
+**2XM<x>_Define o nome da rotina 'main' do programa (padrão é 'main')
+**2XP<x>_Apensa os nomes 'binutils' com o prefixo <x>
+**2Xr<x>_Define o caminho-rlink do vinculador para <x> (necessário para compilação 'cross', veja o manual do 'ld' para maiores informações) (BeOS, Linux)
+**2XR<x>_Apensa todos os caminhos de busca do vinculador com <x> (BeOS, Darwin, FreeBSD, Linux, Mac OS, Solaris)
+**2Xs_Remove todos os símbolos do executável
+**2XS_Tenta vincular unidades estaticamente (padrão, define FPC_LINK_STATIC)
+**2Xt_Vincula com bibliotecas estáticas (-static é passado ao vinculador)
+**2XX_Tenta a vinculação inteligente de unidades (define FPC_LINK_SMART)
+**1*_
+**1?_Exibe esta ajuda
+**1h_Exibe esta ajuda sem espera
+]
+
+#
+# The End...
diff --git a/closures/compiler/msg/errorr.msg b/closures/compiler/msg/errorr.msg
new file mode 100644
index 0000000000..9982500555
--- /dev/null
+++ b/closures/compiler/msg/errorr.msg
@@ -0,0 +1,2832 @@
+#
+# This file is part of the Free Pascal Compiler
+# Copyright (c) 1999-2009 by the Free Pascal Development team
+#
+# Russian (utf-8) Language File for Free Pascal
+#
+# This file corresponds to SVN revision 13665 of errore.msg
+# Translated by Sergei Gorelkin <sergei_gorelkin at mail.ru>
+#
+# See the file COPYING.FPC, included in this distribution,
+# for details about the copyright.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#
+#
+# Š®­áâ ­âë § ¯¨á뢠îâáï ¢ á«¥¤yî饬 ¢¨¤¥:
+# <part>_<type>_<txtidentifier>
+#
+# <part> - ç áâì ª®¬¯¨«ïâ®à , ¢ ª®â®à®© ¨á¯®«ì§ã¥âáï á®®¡é¥­¨¥:
+# asmr_ ç⥭¨¥  áᥬ¡«¥à 
+# asmw_ § ¯¨áì  áᥬ¡«¥à /®¡ì¥ªâ­ëå ä ©«®¢
+# unit_ ®¡à ¡®âª  ¬®¤ã«¥©
+# scan_ ᪠­¥à
+# parser_ ᥬ ­â¨ç¥áª¨©  ­ «¨§ â®à
+# type_ ª®­â஫ì ᮮ⢥âá⢨ï ⨯®¢
+# general_ ®¡é ï ¨­ä®à¬ æ¨ï
+# exec_ ¢ë§®¢ë ¢­¥è­¨å ¯à®£à ¬¬ ( áᥬ¡«¥à , ª®¬¯®­®¢é¨ª  ¨ â.¤.)
+# link_ ¢­ãâ७­¨© ª®¬¯®­®¢é¨ª
+#
+# <type> ⨯ á®®¡é¥­¨ï:
+# f_ ä â «ì­ ï ®è¨¡ª 
+# e_ ®è¨¡ª 
+# w_ ¯à¥¤ã¯à¥¦¤¥­¨¥
+# n_ ¯à¨¬¥ç ­¨¥
+# h_ ¯®¤áª §ª 
+# i_ ¨­ä®à¬ æ¨ï
+# l_ ¤®¡ ¢«ï¥âáï ­®¬¥p áâp®ª¨
+# u_ ¨á¯®«ì§®¢ ­¨¥
+# t_ ¯®¯ë⪠ ¨á¯®«ì§®¢ âì
+# c_ ãá«®¢­®¥ ¢ëà ¦¥­¨¥
+# d_ ®â« ¤®ç­®¥ á®®¡é¥­¨¥
+# x_ ¨­ä®à¬ æ¨ï ® ¨á¯®«­ï¥¬ëå ä ©« å
+# o_ ®¡ëç­ë¥ ("­ ¦¬¨â¥ «î¡ãî ª« ¢¨èã")
+#
+
+#
+# General
+#
+# 01023 is the last used one
+#
+# BeginOfTeX
+% \section{Ž¡é¨¥ á®®¡é¥­¨ï ª®¬¯¨«ïâ®à }
+% â®â à §¤¥« ᮤ¥à¦¨â á®®¡é¥­¨ï ¨­ä®à¬ æ¨®­­®£® ­ §­ ç¥­¨ï.
+% Š®«¨ç¥á⢮ â ª¨å á®®¡é¥­¨© ã¯à ¢«ï¥âáï
+% à §«¨ç­ë¬¨ ­ áâp®©ª ¬¨ yp®¢­ï ¯®¤à®¡­®á⨠\var{-v}.
+% \begin{description}
+general_t_compilername=01000_T_Š®¬¯¨«ïâ®p: $1
+% ਠ¨á¯®«ì§®¢ ­¨¨ ª«îç  \var{-vt} íâ  áâப  á®®¡é ¥â ¢ ¬, ª ª®©
+% ª®¬¯¨«ïâ®à ¨á¯®«ì§ã¥âáï.
+general_d_sourceos=01001_D_Ž‘ ª®¬¯¨«ïâ®à : $1
+% ਠ¨á¯®«ì§®¢ ­¨¨ ª«îç  \var{-vd} íâ  áâப  á®®¡é ¥â ­ §¢ ­¨¥
+% ®¯¥à æ¨®­­®© á¨á⥬ë, ¢ ª®â®à®© ¯à®¨á室¨â ª®¬¯¨«ïæ¨ï.
+general_i_targetos=01002_I_–¥«¥¢ ï Ž‘: $1
+% ਠ¨á¯®«ì§®¢ ­¨¨ ª«îç  \var{-vd} íâ  áâப  á®®¡é ¥â ­ §¢ ­¨¥
+% ®¯¥à æ¨®­­®© á¨á⥬ë, ¤«ï ª®â®à®© ᮧ¤ ¥âáï ä ©«.
+general_t_exepath=01003_T_yâì ¨á¯®«­ï¥¬ëå ä ©«®¢: $1
+% ਠ¨á¯®«ì§®¢ ­¨¨ ª«îç  \var{-vt} íâ  áâப  á®®¡é ¥â ¯ãâì,
+% ¯® ª®â®à®¬ã ª®¬¯¨«ïâ®à ¨é¥â ¨á¯®«­ï¥¬ë¥ ä ©«ë.
+general_t_unitpath=01004_T_ãâì ¬®¤ã«¥©: $1
+% ਠ¨á¯®«ì§®¢ ­¨¨ ª«îç  \var{-vt} íâ  áâப  á®®¡é ¥â ¯ãâì,
+% ¯® ª®â®à®¬ã ª®¬¯¨«ïâ®à ¨é¥â ª®¬¯¨«¨àã¥¬ë¥ ¬®¤ã«¨. â®â ¯ãâì
+% ¬®¦¥â ¡ëâì ¨§¬¥­¥­ á ¯®¬®éìî ª«îç  \var{-Fu}.
+general_t_includepath=01005_T_yâì ¢ª«îç ¥¬ëå ä ©«®¢: $1
+% ਠ¨á¯®«ì§®¢ ­¨¨ ª«îç  \var{-vt} íâ  áâப  á®®¡é ¥â ¯ãâì,
+% ¯® ª®â®à®¬ã ª®¬¯¨«ïâ®à ¨é¥â ¢ª«îç ¥¬ë¥ ä ©«ë (ä ©«ë, ¨á¯®«ì§ã¥¬ë¥ ¢ ¤¨à¥ªâ¨¢ å
+% \var{\{\$I xxx\}}). â®â ¯ãâì ¬®¦¥â ¡ëâì ¨§¬¥­¥­ á ¯®¬®éìî ª«îç  \var{-I}.
+general_t_librarypath=01006_T_yâì ¡¨¡«¨®â¥ª: $1
+% ਠ¨á¯®«ì§®¢ ­¨¨ ª«îç  \var{-vt} íâ  áâப  á®®¡é ¥â ¯ãâì,
+% ¯® ª®â®à®¬ã ª®¬¯¨«ïâ®à ¨é¥â ¡¨¡«¨®â¥ª¨. â®â ¯ãâì ¬®¦¥â ¡ëâì ¨§¬¥­¥­
+% á ¯®¬®éìî ª«îç  \var{-Fl}.
+general_t_objectpath=01007_T_yâì ®¡ê¥ªâ­ëå ä ©«®¢: $1
+% ਠ¨á¯®«ì§®¢ ­¨¨ ª«îç  \var{-vt} íâ  áâப  á®®¡é ¥â ¯ãâì, ¯® ª®â®à®¬ã
+% ª®¬¯¨«ïâ®à ¨é¥â ®¡ê¥ªâ­ë¥ ä ©«ë (ä ©«ë, ¨á¯®«ì§ã¥¬ë¥ ¢ ¤¨à¥ªâ¨¢ å
+% \var{\{\$L xxx \}}). â®â ¯ãâì ¬®¦¥â ¡ëâì ¨§¬¥­¥­ á ¯®¬®éìî ª«îç  \var{-Fo}.
+general_i_abslines_compiled=01008_I_$1 áâப ᪮¬¯¨«¨p®¢ ­®, $2 ᥪ.$3
+% ਠ¨á¯®«ì§®¢ ­¨¨ ª«îç  \var{-vi} ª®¬¯¨«ïâ®à á®®¡é ¥â ç¨á«®
+% ᪮¬¯¨«¨p®¢ ­­ëå áâப, ¨ ¢à¥¬ï, ª®â®à®¥ ¯®âp¥¡®¢ «®áì ¤«ï í⮣®.
+% (ॠ«ì­®¥, ­¥ ¯à®£à ¬¬­®¥ ¢à¥¬ï).
+general_f_no_memory_left=01009_F_H¥¤®áâ â®ç­® ¯ ¬ïâ¨
+% Š®¬¯¨«ïâ®àã ­¥ 墠⨫® ¯ ¬ï⨠¤«ï ª®¬¯¨«ï樨 ¢ è¥© ¯à®£à ¬¬ë.
+% ˆ¬¥¥âáï ­¥áª®«ìª® p¥ª®¬¥­¤ æ¨© ¤«ï p¥è¥­¨ï í⮣® ¢®¯p®á :
+% \begin{itemize}
+% \item ‚¬¥áâ® ¯®«­®© ᡮન ¯à®¥ªâ , ¯®¯à®¡ã©â¥ ª®¬¯¨«¨à®¢ âì
+% ®â¤¥«ì­ë¥ ¬®¤ã«¨ ¢àãç­ãî.
+% \item …᫨ à §¬¥à ¯à®£à ¬¬ë ¡®«ì让, à §¡¥©â¥ ¥¥ ­  ¬®¤ã«¨, ¨
+% ª®¬¯¨«¨àã©â¥ ¨å ®â¤¥«ì­®.
+% \item …᫨ ¯à¥¤ë¤ã騥 ४®¬¥­¤ æ¨¨ ­¥ à ¡®â îâ, ¯¥à¥á®¡¥à¨â¥ ª®¬¯¨«ïâ®à
+% á ¡®«ì訬 p §¬¥p®¬ ªyç¨ (¤«ï í⮣® ¨á¯®«ì§ã¥âáï ª«îç \var{-Ch}, \seeo{Ch})
+% \end{itemize}
+general_i_writingresourcefile=01010_I_‡ ¯¨áì ä ©«  â ¡«¨æë áâp®ª®¢ëå p¥áypᮢ: $1
+% ‘®®¡é¥­¨¥ ®§­ ç ¥â, çâ® ª®¬¯¨«ïâ®à ᮧ¤ ¥â ä ©«, ᮤ¥à¦ é¨© ¢á¥ à¥áãàá­ë¥ áâப¨ ¯à®£à ¬¬ë
+% (â ¡«¨æã áâப®¢ëå à¥áãàᮢ).
+general_e_errorwritingresourcefile=01011_E_Žè¨¡ª  § ¯¨á¨ ä ©«  â ¡«¨æë áâp®ª®¢ëå p¥áypᮢ: $1
+% ‘®®¡é¥­¨¥ ®§­ ç ¥â, çâ® ¢ ¯à®æ¥áᥠ§ ¯¨á¨ ä ©«  áâப®¢ëå à¥áãàᮢ
+% ¯à®¨§®è«  ®è¨¡ª .
+general_i_fatal=01012_I_” â «ì­®:
+% à¥ä¨ªá ¤«ï ä â «ì­ëå ®è¨¡®ª
+general_i_error=01013_I_Žè¨¡ª :
+% à¥ä¨ªá ¤«ï ®è¨¡®ª
+general_i_warning=01014_I_‚­¨¬ ­¨¥:
+% à¥ä¨ªá ¤«ï ¯à¥¤ã¯à¥¦¤¥­¨© (!! "।ã¯à¥¦¤¥­¨¥:" ®¡à¥§ ¥âáï, ¯® ªà ©­¥© ¬¥à¥ ¢ utf-8 !!)
+general_i_note=01015_I_‡ ¬¥âª :
+% à¥ä¨ªá ¤«ï § ¬¥â®ª
+general_i_hint=01016_I_®¤áª §ª :
+% à¥ä¨ªá ¤«ï ¯®¤áª §®ª
+general_e_path_does_not_exist=01017_E_ãâì "$1" ­¥ áãé¥áâ¢ã¥â
+% “ª § ­­ë© ¯ãâì ­¥ áãé¥áâ¢ã¥â.
+general_f_compilation_aborted=01018_F_Š®¬¯¨«ïæ¨ï ¯à¥à¢ ­ 
+% Š®¬¯¨«ïæ¨ï ¡ë«  ¯à¥à¢ ­ .
+general_text_bytes_code=01019_¡ ©â ª®¤ 
+%  §¬¥à ᣥ­¥à¨à®¢ ­­®£® ª®¤ , ¢ ¡ ©â å.
+general_text_bytes_data=01020_¡ ©â ¤ ­­ëå
+%  §¬¥à ᣥ­¥à¨à®¢ ­­ëå ¤ ­­ëå ¯à®£à ¬¬ë, ¢ ¡ ©â å
+general_i_number_of_warnings=01021_I_$1 ¯à¥¤ã¯à¥¦¤¥­¨©
+% Ž¡é¥¥ ç¨á«® ¯à¥¤ã¯à¥¦¤¥­¨©, ¢ë¤ ­­ëå ¢ ¯à®æ¥áᥠª®¬¯¨«ï樨.
+general_i_number_of_hints=01022_I_$1 ¯®¤áª §®ª
+% Ž¡é¥¥ ç¨á«® ¯®¤áª §®ª, ¢ë¤ ­­ëå ¢ ¯à®æ¥áᥠª®¬¯¨«ï樨.
+general_i_number_of_notes=01023_I_$1 § ¬¥â®ª
+% Ž¡é¥¥ ç¨á«® § ¬¥â®ª, ¢ë¤ ­­ëå ¢ ¯à®æ¥áᥠª®¬¯¨«ï樨.
+% \end{description}
+#
+# Scanner
+#
+# 02086 is the last used one
+#
+% \section {‘®®¡é¥­¨ï ᪠­¥à .}
+% â®â à §¤¥« ¯¥à¥ç¨á«ï¥â á®®¡é¥­¨ï, ª®â®pë¥ ¢ë¤ ¥â ᪠­¥à. ‘ª ­¥à ®áãé¥á⢫ï¥â
+% «¥ªá¨ç¥áª¨©  ­ «¨§ áâàãªâãàë ¨á室­®£® ä ©« , â.¥. ­ å®¤¨â
+% § à¥§¥à¢¨à®¢ ­­ë¥ á«®¢ , áâப¨, ¨ â.¤. ‘ª ­¥à â ª¦¥ ®¡à ¡ â뢠¥â ¤¨à¥ªâ¨¢ë ¨
+% ¢ëà ¦¥­¨ï ãá«®¢­®© ª®¬¯¨«ï樨.
+% \begin{description}
+scan_f_end_of_file=02000_F_H¥®¦¨¤ ­­ë© ª®­¥æ ä ©« 
+% â® ®¡ëç­® ¯à®¨á室¨â ¢ á«¥¤ãîé¨å á«ãç ïå:
+% \begin{itemize}
+% \item ˆá室­ë© ä ©« § ª ­ç¨¢ ¥âáï ¤® ¯®á«¥¤­¥£® ¢ëà ¦¥­¨ï \var{end}.
+% — é¥ ¢á¥£® ¯à®¨á室¨â, ¥á«¨ ¢ëà ¦¥­¨ï \var{begin} ¨ \var{end} ­¥
+% á¡ « ­á¨à®¢ ­ë (¨å ª®«¨ç¥á⢮ ­¥ ᮢ¯ ¤ ¥â);
+% \item ‚ª«îç ¥¬ë© ä ©« § ª ­ç¨¢ ¥âáï ¢ á¥à¥¤¨­¥ ¢ëp ¦¥­¨ï.
+% \item ¥ ¡ë« § ªàëâ ª®¬¬¥­â à¨©.
+% \end{itemize}
+scan_f_string_exceeds_line=02001_F_¥ § ªàëâ  áâப®¢ ï ª®­áâ ­â 
+% Žâáãâáâ¢ã¥â § ªà뢠î騩 ᨬ¢®« ' áâப®¢®£® ª®­áâ ­âë, â ª çâ® ª®­áâ ­â  § ­¨¬ ¥â
+% ­¥áª®«ìª® áâப ä ©« .
+scan_f_illegal_char=02002_F_‡ ¯p¥é¥­­ë© ᨬ¢®« "$1" ($2)
+% ‚ ¨á室­®¬ ä ©«¥ ®¡­ à㦥­ § ¯à¥é¥­­ë© ᨬ¢®«.
+scan_f_syn_expected=02003_F_‘¨­â ªá¨ç¥áª ï ®è¨¡ª , ®¦¨¤ ¥âáï "$1", ­® ®¡­ à㦥­® "$2"
+% Š®¬¯¨«ïâ®à ®¦¨¤ « ­¥ â®â ⮪¥­, ª®â®àë© ¥¬ã ¢áâà¥â¨«áï. â® ¬®¦¥â
+% ¯à®¨á室¨âì ¢¥§¤¥, £¤¥ ⮫쪮 ¢®§¬®¦­® ­ àãè¨âì ¯à ¢¨« 
+% ï§ëª   áª «ì.
+scan_t_start_include_file=02004_TL_H ç «® ç⥭¨ï ¢ª«îç ¥¬®£® ä ©«  $1
+% ਠ¨á¯®«ì§®¢ ­¨¨ ª«îç  \var{-vt} ª®¬¯¨«ïâ®à á®®¡é ¥â,
+% ª®£¤  ®­ ­ ç¨­ ¥â ç¨â âì ¢ª«îç ¥¬ë© ä ©«.
+scan_w_comment_level=02005_W_H ©¤¥­ ª®¬¬¥­â à¨© $1 yp®¢­ï
+% ਠ¨á¯®«ì§®¢ ­¨¨ ª«îç  \var{-vw} ª®¬¯¨«ïâ®à ¯à¥¤ã¯à¥¦¤ ¥â ® ⮬,
+% çâ® ®­ ®¡­ à㦨« ¢«®¦¥­­ë© ª®¬¬¥­â à¨©. ‚«®¦¥­­ë¥ ª®¬¬¥­â à¨¨ ­¥ à §à¥è¥­ë ¢
+% Turbo Pascal ¨ ¬®£ãâ ¡ëâì ¢®§¬®¦­ë¬ ¨áâ®ç­¨ª®¬ ®è¨¡®ª.
+scan_n_ignored_switch=02008_N_„¨à¥ªâ¨¢  ª®¬¯¨«ïâ®à  $1 ¨£­®à¨à®¢ ­ 
+% ਠ¨á¯®«ì§®¢ ­¨¨ ª«îç  \var{-vn} ª®¬¯¨«ïâ®à ¯à¥¤ã¯à¥¦¤ ¥â ® ⮬, çâ® ®­ ¨£­®à¨àã¥â ¤¨à¥ªâ¨¢ã.
+scan_w_illegal_switch=02009_W_H¥¨§¢¥áâ­ ï ¤¨à¥ªâ¨¢  ª®¬¯¨«ïâ®p  $1
+% ë«  ¨á¯®«ì§®¢ ­  ¤¨à¥ªâ¨¢  ª®¬¯¨«ïâ®à  (â® ¥áâì \var{\{\$... \}}), ª®â®à ï
+% ª®¬¯¨«ïâ®àã ­¥ ¨§¢¥áâ­ .
+scan_w_switch_is_global=02010_W_ƒ«®¡ «ì­ ï ¤¨à¥ªâ¨¢  ­¥ ­  ᢮¥¬ ¬¥áâ¥
+% ƒ«®¡ «ì­ë¥ ¤¨à¥ªâ¨¢ë ¤®«¦­ë ­ å®¤¨âìáï ¢ ­ ç «¥ ¯à®£à ¬¬ë ¨«¨ ¬®¤ã«ï.
+scan_e_illegal_char_const=02011_E_H¥¢¥à­® § ¤ ­ ᨬ¢®«
+% â® á«ãç ¥âáï ¯à¨ ®¯à¥¤¥«¥­¨¨ ᨬ¢®«  á ¯®¬®éìî ASCII-ª®¤ , ­ ¯à¨¬¥à,
+% \var{\#96}, ­® ç¨á«® «¨¡® ï¥âáï ­¥¢¥à­ë¬, «¨¡® ¢­¥ ¤®¯ãá⨬®£® ¤¨ ¯ §®­ .
+scan_f_cannot_open_input=02012_F_H¥¢®§¬®¦­® ®âªpëâì ä ©« "$1"
+% \fpc ­¥ ¬®¦¥â ­ ©â¨ ¨á室­ë© ä ©« ¯à®£à ¬¬ë ¨«¨ ¬®¤ã«ï, 㪠§ ­­ë©
+% ¢ ª®¬ ­¤­®© áâப¥.
+scan_f_cannot_open_includefile=02013_F_H¥¢®§¬®¦­® ®âªpëâì ¢ª«îç ¥¬ë© ä ©« "$1"
+% \fpc ­¥ ¬®¦¥â ­ ©â¨ ¨á室­ë© ä ©«, 㪠§ ­­ë© ¢ ¤¨à¥ªâ¨¢¥ \var{\{\$include \}}.
+scan_e_illegal_pack_records=02015_E_¥¢¥à­®¥ 㪠§ ­¨¥ ¢ëà ¢­¨¢ ­¨ï § ¯¨á¨ "$1"
+% ‚ ¤¨à¥ªâ¨¢¥ \var{\{\$PACKRECORDS n\} } ¨«¨ \var{\{\$ALIGN n\} } ¨á¯®«ì§ã¥âáï ­¥¢¥à­®¥ §­ ç¥­¨¥
+% \var{n}. „«ï \$PACKRECORDS ¤®¯ãá⨬ë ⮫쪮 1, 2, 4, 8, 16, 32, C,
+% NORMAL, DEFAULT,   ¤«ï \$ALIGN ¤®¯ãáâ¨¬ë §­ ç¥­¨ï 1, 2, 4, 8, 16, 32, ON,
+% OFF. ‚ ०¨¬¥ MacPas \$ALIGN â ª¦¥ ¯®¤¤¥à¦¨¢ ¥â MAC68K, POWER ¨ RESET.
+scan_e_illegal_pack_enum=02016_E_¥¢¥à­®¥ 㪠§ ­¨¥ ¬¨­¨¬ «ì­®£® à §¬¥à  ¯¥à¥ç¨á«¥­¨ï "$1"
+% ‚ ¤¨à¥ªâ¨¢¥ \var{\{\$PACKENUM n \}} ¨á¯®«ì§ã¥âáï ­¥¢¥à­®¥ §­ ç¥­¨¥
+% \var {n}. „®¯ãá⨬묨 ïîâáï §­ ç¥­¨ï 1,2,4, NORMAL ¨ DEFAULT.
+scan_e_endif_expected=02017_E_Ž¦¨¤ ¥âáï $ENDIF ¤«ï $1 $2, ®¯à¥¤¥«¥­­®£® ¢ $3 áâப  $4
+% „¨à¥ªâ¨¢ë ãá«®¢­®© ª®¬¯¨«ï樨 ­¥ á¡ « ­á¨à®¢ ­ë.
+scan_e_preproc_syntax_error=02018_E_‘¨­â ªá¨ç¥áª ï ®è¨¡ª  ¢ ¢ëà ¦¥­¨¨ ãá«®¢­®© ª®¬¯¨«ï樨
+% ‚ ¢ëà ¦¥­¨¨, á«¥¤ãî饬 ¯®á«¥ ¤¨à¥ªâ¨¢ë \var{\{\$if \}}, $ifc ¨«¨ $setc, ¤®¯ã饭  ®è¨¡ª .
+scan_e_error_in_preproc_expr=02019_E_Žè¨¡ª  ¯à¨ ¢ëç¨á«¥­¨¨ ¢ëà ¦¥­¨ï ãá«®¢­®© ª®¬¯¨«ï樨
+% ‚ ¢ëà ¦¥­¨¨, á«¥¤ãî饬 ¯®á«¥ ¤¨à¥ªâ¨¢ë \var{\{\$if \}}, $ifc ¨«¨ $setc, ¤®¯ã饭  ®è¨¡ª .
+scan_w_macro_cut_after_255_chars=02020_W_„«¨­  ¬ ªp®á  ®£à ­¨ç¥­  255 ᨬ¢®« ¬¨
+% „«¨­  ¬ ªà®ª®¬ ­¤ë ­¥ ¬®¦¥â ¯à¥¢ëè âì 255 ᨬ¢®«®¢.
+scan_e_endif_without_if=02021_E_ENDIF ¡¥§ IF(N)DEF
+% „¨à¥ªâ¨¢ë \var{\{\$IFDEF.. \}} ¨ {\ {\$ENDIF \}} ­¥ á¡ « ­á¨à®¢ ­ë.
+scan_f_user_defined=02022_F_‡ ¤ ­® ¯®«ì§®¢ â¥«¥¬: $1
+% p®¨§®è«  ä â «ì­ ï ®è¨¡ª , § ¤ ­­ ï ¯®«ì§®¢ â¥«¥¬. ‘¬. â ª¦¥ \progref
+scan_e_user_defined=02023_E_‡ ¤ ­® ¯®«ì§®¢ â¥«¥¬: $1
+% p®¨§®è«  ®è¨¡ª , § ¤ ­­ ï ¯®«ì§®¢ â¥«¥¬. ‘¬. â ª¦¥ \progref
+scan_w_user_defined=02024_W_‡ ¤ ­® ¯®«ì§®¢ â¥«¥¬: $1
+% p¥¤ã¯à¥¦¤¥­¨¥, § ¤ ­­®¥ ¯®«ì§®¢ â¥«¥¬. ‘¬. â ª¦¥ \progref
+scan_n_user_defined=02025_N_‡ ¤ ­® ¯®«ì§®¢ â¥«¥¬: $1
+% ‡ ¬¥âª , § ¤ ­­ ï ¯®«ì§®¢ â¥«¥¬. ‘¬. â ª¦¥ \progref
+scan_h_user_defined=02026_H_‡ ¤ ­® ¯®«ì§®¢ â¥«¥¬: $1
+% ®¤áª §ª , § ¤ ­­ ï ¯®«ì§®¢ â¥«¥¬. ‘¬. â ª¦¥ \progref
+scan_i_user_defined=02027_I_‡ ¤ ­® ¯®«ì§®¢ â¥«¥¬: $1
+% ˆ­ä®à¬ æ¨ï, § ¤ ­­ ï ¯®«ì§®¢ â¥«¥¬. ‘¬. â ª¦¥ \progref
+scan_e_keyword_cant_be_a_macro=02028_E_Š«î祢®¥ á«®¢®, ¯¥à¥®¯à¥¤¥«¥­­®¥ ª ª ¬ ªà®á, ­¥ ¨¬¥¥â íä䥪â 
+% Š«îç¥¢ë¥ á«®¢  ­¥ ¬®£ãâ ¡ëâì ¯¥à¥®¯à¥¤¥«¥­ë á ¯®¬®éìî ¬ ªà®ª®¬ ­¤.
+scan_f_macro_buffer_overflow=02029_F_¥à¥¯®«­¥­¨¥ ¡yä¥p  ¬ ªp®á®¢ ¯à¨ ç⥭¨¨ ¨«¨ à áè¨à¥­¨¨ ¬ ªà®ª®¬ ­¤ë
+% „«¨­  ¬ ªp®ª®¬ ­¤ë ¨«¨ ¥¥ १ã«ìâ â  ᫨誮¬ ¢¥«¨ª .
+scan_w_macro_too_deep=02030_W_—¨á«® ã஢­¥© à áè¨p¥­¨ï ¬ ªà®ª®¬ ­¤ë ¯à¥¢ëè ¥â 16.
+% ਠà áè¨à¥­¨¨ ¬ ªà®ª®¬ ­¤ë ¡ë«® ¨á¯®«ì§®¢ ­® ¡®«¥¥ 16 yp®¢­¥© ¢«®¦¥­­®áâ¨.
+% Š®¬¯¨«ïâ®à ­¥ ¡ã¤¥â p áè¨pïâì ¤ «ìè¥, â ª ª ª íâ® ¬®¦¥â ¡ëâì ¯à¨§­ ª®¬ ¨á¯®«ì§®¢ ­¨ï ४ãàᨨ.
+scan_w_wrong_styled_switch=02031_W_„¨à¥ªâ¨¢ë ª®¬¯¨«ïâ®p  ¢ ª®¬¬¥­â à¨ïå á⨫ï // ­¥ ¯®¤¤¥à¦¨¢ îâáï.
+% „¨à¥ªâ¨¢ë ª®¬¯¨«ïâ®à  ¤®«¦­ë ¡ëâì ¢ ª®¬¬¥­â à¨ïå áâ¨«ï  áª «ì.
+scan_d_handling_switch=02032_DL_Ž¡à ¡®âª  ¤¨à¥ªâ¨¢ë "$1"
+% ਠ¢ª«î祭¨¨ ®â« ¤®ç­®© ¨­ä®à¬ æ¨¨ (\var{-vd}), ª®¬¯¨«ïâ®à á®®¡é ¥â
+% ® ⮬, çâ® ®­ ¢ëç¨á«ï¥â ¢ëà ¦¥­¨¥ ãá«®¢­®© ª®¬¯¨«ï樨.
+scan_c_endif_found=02033_CL_ENDIF $1 ­ ©¤¥­®
+% ਠ¢ª«î祭¨¨ á®®¡é¥­¨© ®¡ ãá«®¢­ëå ¢ëà ¦¥­¨ïå (\var{-vc}), ª®¬¯¨«ïâ®à á®®¡é ¥â
+% ® ⮬, £¤¥ ®­ ®¡à ¡ â뢠¥â ¢ëà ¦¥­¨ï ãá«®¢­®© ª®¬¯¨«ï樨.
+scan_c_ifdef_found=02034_CL_IFDEF $1 ­ ©¤¥­®, $2
+% ਠ¢ª«î祭¨¨ á®®¡é¥­¨© ®¡ ãá«®¢­ëå ¢ëà ¦¥­¨ïå (\var{-vc}), ª®¬¯¨«ïâ®à á®®¡é ¥â
+% ® ⮬, £¤¥ ®­ ®¡à ¡ â뢠¥â ¢ëà ¦¥­¨ï ãá«®¢­®© ª®¬¯¨«ï樨.
+scan_c_ifopt_found=02035_CL_IFOPT $1 ­ ©¤¥­®, $2
+% ਠ¢ª«î祭¨¨ á®®¡é¥­¨© ®¡ ãá«®¢­ëå ¢ëà ¦¥­¨ïå (\var{-vc}), ª®¬¯¨«ïâ®à á®®¡é ¥â
+% ® ⮬, £¤¥ ®­ ®¡à ¡ â뢠¥â ¢ëà ¦¥­¨ï ãá«®¢­®© ª®¬¯¨«ï樨.
+scan_c_if_found=02036_CL_IF $1 ­ ©¤¥­®, $2
+% ਠ¢ª«î祭¨¨ á®®¡é¥­¨© ®¡ ãá«®¢­ëå ¢ëà ¦¥­¨ïå (\var{-vc}), ª®¬¯¨«ïâ®à á®®¡é ¥â
+% ® ⮬, £¤¥ ®­ ®¡à ¡ â뢠¥â ¢ëà ¦¥­¨ï ãá«®¢­®© ª®¬¯¨«ï樨.
+scan_c_ifndef_found=02037_CL_IFNDEF $1 ­ ©¤¥­®, $2
+% ਠ¢ª«î祭¨¨ á®®¡é¥­¨© ®¡ ãá«®¢­ëå ¢ëà ¦¥­¨ïå (\var{-vc}), ª®¬¯¨«ïâ®à á®®¡é ¥â
+% ® ⮬, £¤¥ ®­ ®¡à ¡ â뢠¥â ¢ëà ¦¥­¨ï ãá«®¢­®© ª®¬¯¨«ï樨.
+scan_c_else_found=02038_CL_ELSE $1 ­ ©¤¥­®, $2
+% ਠ¢ª«î祭¨¨ á®®¡é¥­¨© ®¡ ãá«®¢­ëå ¢ëà ¦¥­¨ïå (\var{-vc}), ª®¬¯¨«ïâ®à á®®¡é ¥â
+% ® ⮬, £¤¥ ®­ ®¡à ¡ â뢠¥â ¢ëà ¦¥­¨ï ãá«®¢­®© ª®¬¯¨«ï樨.
+scan_c_skipping_until=02039_CL_p®¯y᪠¥¬ ¤® ...
+% ਠ¢ª«î祭¨¨ á®®¡é¥­¨© ®¡ ãá«®¢­ëå ¢ëà ¦¥­¨ïå (\var{-vc}), ª®¬¯¨«ïâ®à á®®¡é ¥â
+% ® ⮬, çâ® ®­ ¯à®¯ã᪠¥â ç áâì ãá«®¢­®£® ¢ëà ¦¥­¨ï, ­¥ 㤮¢«¥â¢®àïîéãî ãá«®¢¨î.
+scan_i_press_enter=02040_I_H ¦¬¨â¥ <ENTER> ¤«ï ¯à®¤®«¦¥­¨ï
+% ਠ¨á¯®«ì§®¢ ­¨¨ ª«îç  \var{-vi} ª®¬¯¨«ïâ®à ®áâ ­ ¢«¨¢ ¥âáï
+% ¨ ¦¤¥â ­ ¦ â¨ï ­  ª« ¢¨èã \var{enter}, ¥á«¨ ¢ ¨á室­®¬ ä ©«¥
+% ¢áâà¥ç ¥âáï ¤¨p¥ªâ¨¢  \var {\{\$STOP\}}.
+scan_w_unsupported_switch=02041_W_„¨à¥ªâ¨¢  "$1" ­¥ ¯®¤¤¥à¦¨¢ ¥âáï
+% ਠ¢ª«î祭­ëå ¯à¥¤ã¯à¥¦¤¥­¨ïå (\var{-vw}), ª®¬¯¨«ïâ®à ¯à¥¤ã¯à¥¦¤ ¥â
+% ® ­¥¯®¤¤¥à¦¨¢ ¥¬ëå ¤¨à¥ªâ¨¢ å. â® ®§­ ç ¥â, çâ® ¤¨à¥ªâ¨¢  ¨á¯®«ì§ã¥âáï
+% ¢ Delphi ¨«¨ Turbo Pascal, ­® ­¥ ¢ \fpc
+scan_w_illegal_directive=02042_W_H¥¢¥à­ ï ¤¨à¥ªâ¨¢  ª®¬¯¨«ïâ®à  "$1"
+% ਠ¢ª«î祭­ëå ¯p¥¤y¯p¥¦¤¥­¨ïå (\var{-vw}), ª®¬¯¨«ïâ®à ¯à¥¤ã¯à¥¦¤ ¥â
+% ® ­¥¢¥à­ëå ¤¨p¥ªâ¨¢ å. ‘¯¨á®ª à á¯®§­ ¢ ¥¬ëå ¤¨p¥ªâ¨¢ á¬. ¢ \progref
+scan_t_back_in=02043_TL_‚®§¢p â ¢ $1
+% ਠ¨á¯®«ì§®¢ ­¨¨ ª«îç  (\var{-vt}) ª®¬¯¨«ïâ®à á®®¡é ¥â ®¡ ®ª®­ç ­¨¨
+% ç⥭¨ï ¢ª«îç ¥¬®£® ä ©« .
+scan_w_unsupported_app_type=02044_W_’¨¯ ¯p¨«®¦¥­¨ï "$1" ­¥ ¯®¤¤¥à¦¨¢ ¥âáï
+% â® ¯à¥¤ã¯à¥¦¤¥­¨¥ ¢ë¤ ¥âáï ¯à¨ ¨á¯®«ì§®¢ ­¨¨ ­¥¨§¢¥áâ­®£® ⨯ 
+% ¯à¨«®¦¥­¨ï ¢ ¤¨à¥ªâ¨¢¥ \var{\{\$APPTYPE\}}
+scan_w_app_type_not_support=02045_W_APPTYPE ­¥ ¯®¤¤¥à¦¨¢ ¥âáï 楫¥¢®© Ž‘
+% „¨à¥ªâ¨¢  \var{\{\$APPTYPE\}} ¯®¤¤¥à¦¨¢ ¥âáï ⮫쪮 ­¥ª®â®à묨 ®¯¥à æ¨®­­ë¬¨ á¨á⥬ ¬¨.
+scan_w_description_not_support=02046_W_DESCRIPTION ­¥ ¯®¤¤¥à¦¨¢ ¥âáï 楫¥¢®© Ž‘
+% „¨à¥ªâ¨¢  \var{\{\$DESCRIPTION\}} ­¥ ¯®¤¤¥à¦¨¢ ¥âáï ­  ¤ ­­®© 楫¥¢®© Ž‘.
+scan_n_version_not_support=02047_N_VERSION ­¥ ¯®¤¤¥à¦¨¢ ¥âáï 楫¥¢®© Ž‘
+% „¨à¥ªâ¨¢  \var{\{\$VERSION\}} ­¥ ¯®¤¤¥à¦¨¢ ¥âáï ­  ¤ ­­®© 楫¥¢®© Ž‘.
+scan_n_only_exe_version=02048_N_VERSION ¨á¯®«ì§ã¥âáï ⮫쪮 ¤«ï .EXE ¨ .DLL ¨á室­¨ª®¢
+% „¨à¥ªâ¨¢  \var{\{\$VERSION\}} ¨á¯®«ì§ã¥âáï ⮫쪮 ¤«ï .EXE ¨ .DLL ¨á室­¨ª®¢.
+scan_w_wrong_version_ignored=02049_W_¥¢¥à­ë© ä®à¬ â VERSION ¤«ï ¤¨à¥ªâ¨¢ë "$1"
+% ”®à¬ â ¤¨à¥ªâ¨¢ë \var{\{\$VERSION\}} - major_version.minor_version
+% £¤¥ major_version ¨ minor_version ïîâáï á«®¢ ¬¨.
+scan_e_illegal_asmmode_specifier=02050_E_H¥¢¥à­ë© áâ¨«ì  áᥬ¡«¥p : "$1"
+% ਠ®¯à¥¤¥«¥­¨¨ ०¨¬   áᥬ¡«¥à  ¤¨à¥ªâ¨¢®© \var{\{\$ASMMODE xxx\}}
+% 㪠§ ­ ­¥¢¥à­ë© ०¨¬.
+scan_w_no_asm_reader_switch_inside_asm=02051_W_‘¬¥­  ⨯   áᥬ¡«¥p  ­¥¢®§¬®¦­  ¢­ãâਠ¡«®ª , "$1" ¡y¤¥â ¤¥©á⢮¢ âì ⮫쪮 ¤«ï á«¥¤yî饣® ¡«®ª 
+% ‚­ãâਠ áᥬ¡«¥à­®£® ¡«®ª  ­¥¢®§¬®¦­® ¯¥à¥ª«î祭¨¥  áᥬ¡«¥à  á ®¤­®£® ⨯  ­  ¤à㣮©.
+% “ª § ­­ë© ०¨¬ ­ ç­¥â ¤¥©á⢮¢ âì ⮫쪮 ¤«ï á«¥¤ãî饣®  áᥬ¡«¥à­®£® ¡«®ª .
+scan_e_wrong_switch_toggle=02052_E_H¥¢¥p­®¥ ¯¥à¥ª«î祭¨¥ ०¨¬ , ¨á¯®«ì§ã©â¥ ON/OFF ¨«¨ +/-
+% „«ï ¯¥à¥ª«î祭¨ï ०¨¬®¢ á«¥¤ã¥â ¨á¯®«ì§®¢ âì ON ¨«¨ OFF, «¨¡® + ¨«¨ -
+scan_e_resourcefiles_not_supported=02053_E_” ©«ë p¥áypᮢ ­¥ ¯®¤¤¥à¦¨¢ îâáï 楫¥¢®© Ž‘
+% Ž¯¥à æ¨®­­ ï á¨á⥬ , ¤«ï ª®â®à®© ¯à®¨á室¨â ª®¬¯¨«ïæ¨ï, ­¥ ¯®¤¤¥à¦¨¢ ¥â ä ©«ë à¥áãàᮢ.
+scan_w_include_env_not_found=02054_W_‚ª«îç ¥¬ ï ¯¥p¥¬¥­­ ï ®ªpy¦¥­¨ï "$1" ­¥ ­ ©¤¥­ 
+% “ª § ­­ ï ¯¥à¥¬¥­­ ï ®ªà㦥­¨ï ­¥ ­ ©¤¥­ , ¢¬¥áâ® ­¥¥ ¡ã¤¥â ¯®¤áâ ¢«¥­  ¯ãáâ ï áâப .
+scan_e_invalid_maxfpureg_value=02055_E_¥¢¥à­®¥ §­ ç¥­¨¥ ¤«ï ¬ ªá¨¬ «ì­®£® ç¨á«  ॣ¨áâ஢ ᮯà®æ¥áá®à 
+% „®¯ãá⨬묨 §­ ç¥­¨ï¬¨ ¤«ï í⮩ ¤¨à¥ªâ¨¢ë ïîâáï 0..8 ¨ NORMAL/DEFAULT
+scan_w_only_one_resourcefile_supported=02056_W_„«ï í⮩ á¨áâ¥¬ë ¯®¤¤¥à¦¨¢ ¥âáï ⮫쪮 ®¤¨­ ä ©« à¥áãàᮢ
+% „«ï ®¯¥à æ¨®­­®© á¨áâ¥¬ë ­ §­ ç¥­¨ï ¯®¤¤¥à¦¨¢ ¥âáï ⮫쪮 ®¤¨­ ä ©« à¥áãàᮢ.
+% 㤥⠨ᯮ«ì§®¢ ­ ¯¥à¢ë© ­ ©¤¥­­ë© ä ©«, ®áâ «ì­ë¥ ¡ã¤ãâ ¨£­®à¨à®¢ ­ë.
+scan_w_macro_support_turned_off=02057_W_®¤¤¥p¦ª  ¬ ªp®á®¢ ®âª«î祭 
+% Ž¡­ à㦥­® ®¡ê¥­¨¥ ¬ ªà®á , ­® ०¨¬ ¯®¤¤¥à¦ª¨ ¬ ªà®á®¢ ®âª«î祭,
+% ¯®í⮬㠮¡ê¥­¨¥ ¡ã¤¥â ¨£­®à¨à®¢ ­®. „«ï ¢ª«î祭¨ï ¯®¤¤¥à¦ª¨ ¬ ªà®á®¢ ¨á¯®«ì§ã©â¥
+% -Sm ¢ ª®¬ ­¤­®© áâப¥ ¨«¨ ¤®¡ ¢ì⥠{$MACRO ON} ¢ ¨á室­ë© ä ©«.
+scan_e_invalid_interface_type=02058_E_¥¢¥à­ë© ⨯ interface. „®¯ãá⨬ë ⮫쪮 COM, COBRA ¨«¨ DEFAULT
+% “ª § ­­ë© ⨯ ¨­â¥àä¥©á  ­¥ ¯®¤¤¥à¦¨¢ ¥âáï.
+scan_w_appid_not_support=02059_W_APPID ¯®¤¤¥à¦¨¢ ¥âáï ⮫쪮 ¤«ï PalmOS
+% „¨à¥ªâ¨¢  \var{\{\$APPID\}} ¯®¤¤¥à¦¨¢ ¥âáï ⮫쪮 ¯à¨ ª®¬¯¨«ï樨 ¤«ï PalmOS.
+scan_w_appname_not_support=02060_W_APPNAME ¯®¤¤¥à¦¨¢ ¥âáï ⮫쪮 ¤«ï PalmOS
+% „¨à¥ªâ¨¢  \var{\{\$APPNAME\}} ¯®¤¤¥à¦¨¢ ¥âáï ⮫쪮 ¯à¨ ª®¬¯¨«ï樨 ¤«ï PalmOS.
+scan_e_string_exceeds_255_chars=02061_E_‘âப®¢ ï ª®­áâ ­â  ­¥ ¬®¦¥â ¡ëâì ¤«¨­­¥¥ 255 ᨬ¢®«®¢
+% Ž¤­  áâப®¢ ï ª®­áâ ­â  ¬®¦¥â ᮤ¥à¦ âì 255 ᨬ¢®«®¢ ¬ ªá¨¬ã¬. ®«¥¥ ¤«¨­­ãî
+% áâபã á«¥¤ã¥â à §¡¨âì ­  ç á⨠¨ ᮥ¤¨­¨âì ¨å ®¯¥à â®à®¬ +.
+scan_f_include_deep_ten=02062_F_“஢¥­ì ¢«®¦¥­¨ï ¢ª«îç ¥¬ëå ä ©«®¢ ¯à¥¢®á室¨â 16.
+% ਠç⥭¨¨ ¢ª«îç ¥¬ëå ä ©«®¢ ¤®á⨣­ãâ ã஢¥­ì ¢«®¦¥­­®á⨠16.
+% Š®¬¯¨«ïâ®à ¯à¥ªà é ¥â à ¡®âã, â.ª. íâ® ¬®¦¥â ïâìáï ¯à¨§­ ª®¬ ४ãàᨨ.
+scan_e_too_many_push=02063_F_‘«¨èª®¬ ¬­®£® ã஢­¥© PUSH
+% „®¯ãáâ¨¬ë© ¬ ªá¨¬ã¬ á®áâ ¢«ï¥â 20. â  ®è¨¡ª  ¢®§­¨ª ¥â ⮫쪮 ¢ ०¨¬¥ MacPas.
+scan_e_too_many_pop=02064_E_„¨à¥ªâ¨¢  POP ¡¥§ ¯à¥¤è¥áâ¢ãî饩 PUSH
+% â  ®è¨¡ª  ¢®§­¨ª ¥â ⮫쪮 ¢ ०¨¬¥ MacPas.
+scan_e_error_macro_lacks_value=02065_E_Œ ªà®á ¨«¨ ¯¥à¥¬¥­­ ï ¢à¥¬¥­¨ ª®¬¯¨«ï樨 "$1" ­¥ ¨¬¥¥â ¯à¨á¢®¥­­®£® §­ ç¥­¨ï
+% ˆ§-§  í⮣® ¢ëà ¦¥­¨¥ ¢à¥¬¥­¨ ª®¬¯¨«ï樨 ­¥ ¬®¦¥â ¡ëâì ¢ëç¨á«¥­®.
+scan_e_wrong_switch_toggle_default=02066_E_¥¢¥à­®¥ ¯¥à¥ª«î祭¨¥ ०¨¬ , ¨á¯®«ì§ã©â¥ ON/OFF/DEFAULT ¨«¨ +/-/*
+% ‘«¥¤ã¥â ¯¥à¥ª«îç âì ०¨¬, ¨á¯®«ì§ãï ON ¨«¨ OFF ¨«¨ DEFAULT, «¨¡® + ¨«¨ - ¨«¨ *
+scan_e_mode_switch_not_allowed=02067_E_„¨à¥ªâ¨¢  ०¨¬  "$1" §¤¥áì ­¥ ¤®¯ãá⨬ 
+% „¨à¥ªâ¨¢  ०¨¬  ª®¬¯¨«ï樨 㦥 ¡ë«  ®¡à ¡®â ­ , ¨«¨, ¢ á«ãç ¥ ०¨¬  -Mmacpas,
+% ¯¥à¥ª«î祭¨¥ ०¨¬  ¯à®¨á室¨â ¯®á«¥ UNIT.
+scan_e_error_macro_undefined=02068_E_¥à¥¬¥­­ ï ¢à¥¬¥­¨ ª®¬¯¨«ï樨 ¨«¨ ¬ ªà®á "$1" ­¥ ®¯à¥¤¥«¥­.
+% ˆ§-§  í⮣® ¢ëà ¦¥­¨¥ ¢à¥¬¥­¨ ª®¬¯¨«ï樨 ­¥ ¬®¦¥â ¡ëâì ¢ëç¨á«¥­®. ’®«ìª® ¤«ï ०¨¬  MacPas.
+scan_e_utf8_bigger_than_65535=02069_E_Ž¡­ à㦥­ ª®¤ UTF-8, ¯à¥¢ëè î騩 65535
+% \fpc ®¡à ¡ â뢠¥â áâப¨ utf-8 ª ª widestring, â.¥. ª®¤ë ᨬ¢®«®¢ ®£à ­¨ç¥­ë 65535
+scan_e_utf8_malformed=02070_E_¥¢¥à­ ï UTF-8 áâப 
+% „ ­­ ï áâப  ­¥ ï¥âáï ¤®¯ãá⨬®© ¢ ª®¤¨à®¢ª¥ UTF-8
+scan_c_switching_to_utf8=02071_C_ ©¤¥­  ᨣ­ âãà  UTF-8, ¨á¯®«ì§ãî ª®¤¨à®¢ªã UTF-8
+% Š®¬¯¨«ïâ®à ®¡­ à㦨« ᨣ­ âãàã UTF-8 (\$ef, \$bb, \$bf) ¢ ­ ç «¥ ä ©« ,
+% ¯®í⮬㠮­ ¡ã¤¥â ®¡à ¡ â뢠âì ä ©« ª ª UTF-8
+scan_e_compile_time_typeerror=02072_E_‚ëà ¦¥­¨¥ ¢à¥¬¥­¨ ª®¬¯¨«ï樨: Ž¦¨¤ «®áì $1, ­® ¯®«ã祭® $2 ¢ $3
+% Žè¨¡ª  ⨯®¢ ¢ ¢ëà ¦¥­¨¨ ¢à¥¬¥­¨ ª®¬¯¨«ï樨.
+scan_n_app_type_not_support=02073_N_APPTYPE ­¥ ¯®¤¤¥à¦¨¢ ¥âáï 楫¥¢®© Ž‘
+% „¨à¥ªâ¨¢  \var{\{\$APPTYPE\}} ¯®¤¤¥à¦¨¢ ¥âáï ⮫쪮 ¤«ï ­¥ª®â®àëå ®¯¥à æ¨®­­ëå á¨á⥬.
+scan_e_illegal_optimization_specifier=02074_E_¥¢¥à­ë© ⨯ ®¯â¨¬¨§ æ¨¨ "$1"
+% ‚ ¤¨à¥ªâ¨¢¥ \var{\{\$OPTIMIZATION xxx\}} 㪠§ ­® ­¥¢¥à­®¥ §­ ç¥­¨¥.
+scan_w_setpeflags_not_support=02075_W_SETPEFLAGS ­¥ ¯®¤¤¥à¦¨¢ ¥âáï 楫¥¢®© Ž‘
+% „¨à¥ªâ¨¢  \var{\{\$SETPEFLAGS\}} ­¥ ¯®¤¤¥à¦¨¢ ¥âáï ®¯¥à æ¨®­­®© á¨á⥬®© ­ §­ ç¥­¨ï.
+scan_w_imagebase_not_support=02076_W_IMAGEBASE ­¥ ¯®¤¤¥à¦¨¢ ¥âáï Ž‘ ­ § ­ ç¥­¨ï
+% „¨à¥ªâ¨¢  \var{\{\$IMAGEBASE\}} ­¥ ¯®¤¤¥à¦¨¢ ¥âáï ®¯¥à æ¨®­­®© á¨á⥬®© ­ §­ ç¥­¨ï.
+scan_w_minstacksize_not_support=02077_W_MINSTACKSIZE ­¥ ¯®¤¤¥à¦¨¢ ¥âáï Ž‘ ­ § ­ ç¥­¨ï
+% „¨à¥ªâ¨¢  \var{\{\$MINSTACKSIZE\}} ­¥ ¯®¤¤¥à¦¨¢ ¥âáï ®¯¥à æ¨®­­®© á¨á⥬®© ­ §­ ç¥­¨ï.
+scan_w_maxstacksize_not_support=02078_W_MAXSTACKSIZE ­¥ ¯®¤¤¥à¦¨¢ ¥âáï Ž‘ ­ § ­ ç¥­¨ï
+% „¨à¥ªâ¨¢  \var{\{\$MAXSTACKSIZE\}} ­¥ ¯®¤¤¥à¦¨¢ ¥âáï ®¯¥à æ¨®­­®© á¨á⥬®© ­ §­ ç¥­¨ï.
+scanner_e_illegal_warn_state=02079_E_¥¢¥à­ë© ०¨¬ ¤¨à¥ªâ¨¢ë $WARN
+% „¨à¥ªâ¨¢  \$warn ¤®¯ã᪠¥â ⮫쪮 ON ¨ OFF ¤«ï 㪠§ ­¨ï ०¨¬ 
+scan_e_only_packset=02080_E_¥¢¥à­®¥ §­ ç¥­¨¥ 㯠ª®¢ª¨ ¬­®¦¥áâ¢
+% „®¯ãá⨬묨 §­ ç¥­¨ï¬¨ ïîâáï 0, 1, 2, 4, 8, DEFAULT ¨ NORMAL
+scan_w_pic_ignored=02081_W_„¨à¥ªâ¨¢  ¨«¨ ª«îç PIC ¨£­®à¨à®¢ ­ë
+% ¥ª®â®àë¥ ¯« âä®à¬ë, ­ ¯à¨¬¥à, Windows, ­¥ ¯®¤¤¥à¦¨¢ îâ ¨ ­¥ âॡãîâ ¯®§¨æ¨®­­®-­¥§ ¢¨á¨¬ë© ª®¤ (PIC),
+% ¯®í⮬ã ᮮ⢥âáâ¢ãî騥 ¤¨àª¥ªâ¨¢ë ¨ ª«îç¨ ª®¬ ­¤­®© áâப¨ ¤«ï ­¨å ¨£­®à¨àãîâáï.
+scan_w_unsupported_switch_by_target=02082_W_„¨à¥ªâ¨¢  "$1" ­¥ ¯®¤¤¥à¦¨¢ ¥âáï ¤«ï ⥪ã饩 ¯« âä®à¬ë ­ §­ ç¥­¨ï
+% ¥ª®â®àë¥ ¤¨à¥ªâ¨¢ë, ­ ¯à¨¬¥à, \$E, ¯®¤¤¥à¦¨¢ îâáï ­¥ ¤«ï ¢á¥å ¯« âä®à¬.
+scan_w_frameworks_darwin_only=02084_W_„¨à¥ªâ¨¢ë ¤«ï Framework ¯®¤¤¥à¦¨¢ îâáï ⮫쪮 ¤«ï Darwin/Mac OS X
+% Š®­æ¥¯æ¨ï ä३¬¢®àª®¢ ­¥ ¯®¤¤¥à¦¨¢ ¥âáï FPC ¤«ï ®¯¥à æ¨®­­ëå á¨á⥬, ®â«¨ç­ëå ®â Darwin/Mac OS X.
+scan_e_illegal_minfpconstprec=02085_E_¥¢¥à­®¥ 㪠§ ­¨¥ ¬¨­¨¬ «ì­®© â®ç­®á⨠ª®­áâ ­â á ¯« ¢ î饩 § ¯ï⮩ "$1"
+% „®¯ãá⨬묨 §­ ç¥­¨ï¬¨ ïîâáï default, 32 ¨ 64, ª®â®àë¥ ®§­ ç îâ ᮮ⢥âá⢥­­® ¬¨­¨¬ «ì­ãî (®¡ëç­® 32 ¡¨â ), 32 ¡¨â ¨ 64 ¡¨â â®ç­®áâì.
+scan_w_multiple_main_name_overrides=02086_W_Œ­®£®ªà â­®¥ 㪠§ ­¨¥ ¨¬¥­¨ ¯à®æ¥¤ãàë "main", ¯¥à¢®­ ç «ì­® ¡ë«® "$1"
+% ˆ¬ï ®á­®¢­®© â®çª¨ ¢å®¤  㪠§ ­® ¡®«¥¥ ®¤­®£® à § . 㤥⠨ᯮ«ì§®¢ ­® ⮫쪮 ¯®á«¥¤­¥¥ ¨¬ï.
+% \end{description}
+#
+# Parser
+#
+# 03252 is the last used one
+#
+% \section {á®®¡é¥­¨ï ᨭ⠪á¨ç¥áª®£®  ­ «¨§ â®à }
+% â®â à §¤¥« ¯¥à¥ç¨á«ï¥â ¢á¥ á®®¡é¥­¨ï ᨭ⠪á¨ç¥áª®£®  ­ «¨§ â®à .
+% ‘¨­â ªá¨ç¥áª¨©  ­ «¨§ â®à ®áãé¥á⢫ï¥â ᥬ ­â¨ç¥áª¨©  ­ «¨§, â.¥.
+% ®¯à¥¤¥«ï¥â ¯à ¢¨«ì­®áâì ¢ëà ¦¥­¨©  áª «ï.
+% \begin{description}
+parser_e_syntax_error=03000_E_‘¨­â ªá¨ç¥áª ï ®è¨¡ª  ¢  ­ «¨§ â®à¥
+% Ž¡­ à㦥­  ®è¨¡ª  ᨭ⠪á¨á  ï§ëª . Ž¡ëç­® ¯à®¨á室¨â, ª®£¤  ¢ ¨á室­®¬ ä ©«¥
+% ¢áâà¥ç ¥âáï ­¥¤®¯ãáâ¨¬ë© á¨¬¢®«.
+parser_e_dont_nest_interrupt=03004_E_INTERRUPT ¯à®æ¥¤ãà  ­¥ ¬®¦¥â ¡ëâì ¢«®¦¥­­®©
+% à®æ¥¤ãà  â¨¯  \VAR{INTERRUPT} ¤®«¦­  ¡ëâì £«®¡ «ì­®©.
+parser_w_proc_directive_ignored=03005_W_„¨à¥ªâ¨¢  ¯à®æ¥¤ãàë "$1" ¨£­®à¨à®¢ ­ 
+% “ª § ­­ë© ¬®¤¨ä¨ªâ®à ⨯  ¯à®æ¥¤ãàë ¨£­®à¨à®¢ ­ ª®¬¯¨«ïâ®à®¬.
+parser_e_no_overload_for_all_procs=03006_E_¥ ¢á¥ ®¡ê¥­¨ï "$1" ¯¥à¥£à㦥­ë (®¯à¥¤¥«¥­ë ª ª OVERLOAD)
+% ਠ¯¥à¥£à㧪¥ ¯à®æ¥¤ãà á ¯®¬®éìî ¤¨à¥ªâ¨¢ë \var{OVERLOAD}, ¥¥ á«¥¤ã¥â
+% 㪠§ë¢ âì ¤«ï ¢á¥å ®¡ê¥­¨© ¯¥à¥£à㦥­­®© ¯à®æ¥¤ãàë.
+parser_e_export_name_double=03008_E_ˆ¬ï äy­ªæ¨¨ "$1" íªá¯®àâ¨àã¥âáï ¤¢ ¦¤ë
+% ‚ᥠä㭪樨, íªá¯®àâ¨àã¥¬ë¥ ¨§ ®¤­®© DLL, ¤®«¦­ë ¨¬¥âì à §«¨ç­ë¥ ¨¬¥­ .
+parser_e_export_ordinal_double=03009_E_ˆ­¤¥ªá ä㭪樨 $1 íªá¯®àâ¨àã¥âáï ¤¢ ¦¤ë
+% ‚ᥠä㭪樨, íªá¯®àâ¨àã¥¬ë¥ ¨§ ®¤­®© DLL, ¤®«¦­ë ¨¬¥âì à §«¨ç­ë¥ ¨­¤¥ªáë.
+parser_e_export_invalid_index=03010_E_H¥¢¥p­ë© ¨­¤¥ªá íªá¯®pâ¨py¥¬®© äy­ªæ¨¨
+% ˆ­¤¥ªá íªá¯®àâ¨à㥬®© ä㭪樨 ¤®«¦¥­ ¡ëâì ¢ ¤¨ ¯ §®­¥ \var{1..\$FFFF}
+parser_w_parser_reloc_no_debug=03011_W_Žâ« ¤®ç­ ï ¨­ä®à¬ æ¨ï ¢ ¯¥à¥¬¥é ¥¬®¬ DLL/EXE ä ©«¥ $1 ­¥ à ¡®â®á¯®á®¡­ , ®âª«î祭 .
+% ‚ ­ áâ®ï饥 ¢à¥¬ï ¢ª«î祭¨¥ ®â« ¤®ç­®© ¨­ä®à¬ æ¨¨ ¢ ¯¥à¥¬¥é ¥¬ãî DLL ­¥¢®§¬®¦­®.
+parser_w_parser_win32_debug_needs_WN=03012_W_„«ï ®â« ¤ª¨ win32-ª®¤ , á«¥¤ã¥â ®âª«îç¨âì ¯¥à¥¬¥é¥­¨¥ ª«î箬 -WN
+% Žâ« ¤®ç­ ï ¨­ä®à¬ æ¨ï Stabs ­¥ à ¡®â ¥â ¢ ¯¥à¥¬¥é ¥¬ëå DLL ¨«¨ EXE ä ©« å, ¨á¯®«ì§ã©â¥ -WN
+% ¥á«¨ âॡã¥âáï ®â« ¤ª .
+parser_e_constructorname_must_be_init=03013_E_Š®­áâpyªâ®p ¤®«¦¥­ ¨¬¥âì ¨¬ï INIT
+% Š®­áâàãªâ®à ®¡ê¥­ á ¨¬¥­¥¬, ®â«¨ç­ë¬ ®â \var{init}, ¨ ¤¥©áâ¢ã¥â ª«îç
+% \var{-Ss}. ‘¬. ®¯¨á ­¨¥ ¤¥©áâ¢¨ï ª«îç  \var{-Ss} (\seeo{Ss}).
+parser_e_destructorname_must_be_done=03014_E_„¥áâpyªâ®p ¤®«¦¥­ ¨¬¥âì ¨¬ï DONE
+% „¥áâàãªâ®à ®¡ê¥­ á ¨¬¥­¥¬, ®â«¨ç­ë¬ ®â \var{done}, ¨ ¤¥©áâ¢ã¥â ª«îç
+% \var{-Ss}. ‘¬. ®¯¨á ­¨¥ ¤¥©áâ¢¨ï ª«îç  \var{-Ss} (\seeo{Ss}).
+parser_e_proc_inline_not_supported=03016_E_„¨à¥ªâ¨¢  INLINE ­¥ ¯®¤¤¥p¦¨¢ ¥âáï
+% ਠª®¬¯¨«ï樨 ¯à®£à ¬¬ë á inlining ¢ á⨫¥ C++ ­¥ ¡ë« ¨á¯®«ì§®¢ ­ ª«îç
+% \var{-Si} (\seeo{Si}). ® 㬮«ç ­¨î ª®¬¯¨«ïâ®à ­¥ ¯®¤¤¥à¦¨¢ ¥â inlining ¢ á⨫¥ C++.
+parser_w_constructor_should_be_public=03018_W_Š®­áâpyªâ®p ¤®«¦¥­ ¡ëâì public
+% Š®­áâàãªâ®àë ¤®«¦­ë ¡ëâì ¢ 'public' ᥪ樨 ®¡ê¥­¨ï ®¡ê¥ªâ  (ª« áá ).
+parser_w_destructor_should_be_public=03019_W_„¥áâpyªâ®p ¤®«¦¥­ ¡ëâì public
+% „¥áâàãªâ®àë ¤®«¦­ë ¡ëâì ¢ 'public' ᥪ樨 ®¡ê¥­¨ï ®¡ê¥ªâ  (ª« áá ).
+parser_n_only_one_destructor=03020_N_Š« áá ¬®¦¥â ¨¬¥âì ⮫쪮 ®¤¨­ ¤¥áâpyªâ®p
+% „«ï ª« áá  ¬®¦­® ®¯à¥¤¥«¨âì ⮫쪮 ®¤¨­ ¤¥áâàãªâ®à.
+parser_e_no_local_objects=03021_E_‹®ª «ì­ë¥ ®¡ê¥­¨ï ª« áᮢ ­¥ ¯®¤¤¥p¦¨¢ îâáï
+% Š« ááë ¤®«¦­ë ¡ëâì ®¡ê¥­ë £«®¡ «ì­®. Ž­¨ ­¥ ¬®£ãâ ¡ëâì ®¡ê¥­ë ¢­ãâà¨
+% ¯à®æ¥¤ãàë ¨«¨ ä㭪樨.
+parser_f_no_anonym_objects=03022_F_€­®­¨¬­ë¥ ®¡ê¥­¨ï ª« áᮢ ­¥ ¯®¤¤¥p¦¨¢ ¥âáï
+% ‚áâà¥ç¥­® ­¥¤®¯ãá⨬®¥ ®¡ê¥­¨¥ ®¡ê¥ªâ  (ª« áá ), â.¥. ®¡ê¥ªâ ¨«¨ ª« áá,
+% ­¥ ¨¬¥î騩 ¬¥â®¤®¢ ¨ ­¥ ã­ á«¥¤®¢ ­­ë© ®â ¤à㣮£® ®¡ê¥ªâ  (ª« áá ).
+%  ¯à¨¬¥à, ®¡ê¥­¨¥:
+% \begin{verbatim}
+% Type o = object
+% a : longint;
+% end;
+% \end{verbatim}
+% ¢ë§®¢¥â íâ㠮訡ªã.
+parser_n_object_has_no_vmt=03023_N_Ž¡ê¥ªâ "$1" ­¥ ¨¬¥¥â â ¡«¨æë VMT
+% â® § ¬¥âª  ® ⮬, çâ® ®¡ê¥­­ë© ®¡ê¥ªâ ­¥ ¨¬¥¥â â ¡«¨æë ¢¨àâã «ì­ëå ¬¥â®¤®¢ (VMT).
+parser_e_illegal_parameter_list=03024_E_H¥¢¥p­ë© ᯨ᮪ ¯ p ¬¥âp®¢
+% ”ã­ªæ¨ï ¢ë§ë¢ ¥âáï á ¯ à ¬¥âà ¬¨, ⨯ ª®â®àëå ®â«¨ç ¥âáï ®â ⨯®¢ ¯ à ¬¥â஢, ¨á¯®«ì§®¢ ­­ëå
+% ¯à¨ ®¡ê¥­¨¨ ä㭪樨.
+parser_e_wrong_parameter_size=03026_E_¥¢¥à­®¥ ª®«¨ç¥á⢮ ¯ p ¬¥âp®¢ ¯à¨ ¢ë§®¢¥ "$1"
+% Žè¨¡ª  ¢ ᯨ᪥ ¯ à ¬¥â஢ ¢ë§ë¢ ¥¬®© ¯à®æ¥¤ãàë ¨«¨ ä㭪樨, ª®«¨ç¥á⢮ ¯ à ¬¥â஢ ­¥¢¥à­®.
+parser_e_overloaded_no_procedure=03027_E_¥à¥£à㦥­­ë© ¨¤¥­â¨ä¨ª â®p "$1" ­¥ ï¥âáï äy­ªæ¨¥©
+% Š®¬¯¨«ïâ®à ®¡­ à㦨« ᨬ¢®« á ⥬ ¦¥ ¨¬¥­¥¬, çâ® ¨ ¯¥à¥£à㦥­­ ï äã­ªæ¨ï, ­® ­¥ ïî騩áï ä㭪樥©.
+parser_e_overloaded_have_same_parameters=03028_E_¥à¥£à㦥­­ë¥ äy­ªæ¨¨ ¨¬¥îâ ®¤¨­ ª®¢ë© ᯨ᮪ ¯ p ¬¥âp®¢
+% ®¯ë⪠ ®¡ê¥­¨ï ¯¥à¥£à㦥­­ëå ä㭪権 á ®¤­¨¬ ¨ ⥬ ¦¥ ᯨ᪮¬ ¯ à ¬¥â஢.
+% —â®¡ë ¯¥à¥£à㧪  ¡ë«  ¢®§¬®¦­ , ¯® ªà ©­¥© ¬¥à¥ ®¤¨­ ¨§ ¯ à ¬¥â஢ ¤®«¦¥­ ®â«¨ç âìáï.
+parser_e_header_dont_match_forward=03029_E_‡ £®«®¢®ª äy­ªæ¨¨ ­¥ ᮮ⢥âáâ¢y¥â ¯p¥¤ë¤y饬y ®¡ê¥­¨î "$1"
+% Ž¡ê¥­  äã­ªæ¨ï á ⥬ ¦¥ ᯨ᪮¬ ¯ à ¬¥â஬, ­® ®â«¨ç î騬áï ⨯®¬ १ã«ìâ â  «¨¡® ¬®¤¨ä¨ª â®à®¬.
+parser_e_header_different_var_names=03030_E_‡ £®«®¢®ª äy­ªæ¨¨ "$1" ­¥ ᮮ⢥âáâ¢y¥â ¯p¥¤ë¤y饬y ®¯p¥¤¥«¥­¨î ¢ forward : ¨§¬¥­ï¥âáï ¨¬ï ¯¥à¥¬¥­­®© $2 => $3
+% ”ã­ªæ¨ï ®¡ê¥­  ¢ ᥪ樨 \var{interface} «¨¡® á ¤¨à¥ªâ¨¢®©
+% \var{forward},   § â¥¬ ®¯à¥¤¥«¥­  á ®â«¨ç î騬áï ᯨ᪮¬ ¯ à ¬¥â஢.
+parser_n_duplicate_enum=03031_N_‡­ ç¥­¨ï ¢ ¯¥à¥ç¨á«ï¥¬ëå ⨯ å ¤®«¦­ë ¡ëâì ¢®§à áâ î騬¨
+% \fpc ¤®¯ã᪠¥â ®¡ê¥­¨¥ ¯¥à¥ç¨á«¥­¨© ª ª ¢ C. ˆ§ á«¥¤ãîé¨å ¤¢ãå ®¡ê¥­¨©:
+% \begin{verbatim}
+% type a = (A_A,A_B,A_E:=6,A_UAS:=200);
+% type a = (A_A,A_B,A_E:=6,A_UAS:=4);
+% \end{verbatim}
+% ‚â®à®¥ ®¡ê¥­¨¥ ¢ë§®¢¥â íâ® á®®¡é¥­¨¥. ‡­ ç¥­¨¥ \var{A\_UAS} ¤®«¦­® ¡ëâì ¡®«ìè¥,
+% 祬 §­ ç¥­¨¥ \var{A\_E}, â.¥. ¯® ªà ©­¥© ¬¥à¥ 7.
+parser_e_no_with_for_variable_in_other_segments=03033_E_With ­¥ ¬®¦¥â ¡ëâì ¨á¯®«ì§®¢ ­ ¤«ï ¯¥p¥¬¥­­ëå ¨§ ¤à㣮£® ᥣ¬¥­â 
+% With á®åà ­ï¥â ¯¥à¥¬¥­­ãî «®ª «ì­® ­  á⥪¥,
+% ­® íâ® ­¥¢®§¬®¦­®, ¥á«¨ ¯¥à¥¬¥­­ ï ­ å®¤¨âáï ¢ ¤à㣮¬ ᥣ¬¥­â¥.
+parser_e_too_much_lexlevel=03034_E_“஢¥­ì ¢«®¦¥­¨ï äy­ªæ¨© ¯à¥¢ëè ¥â 31
+% Š®«¨ç¥á⢮ ã஢­¥© ¢«®¦¥­¨ï ä㭪権 ®£à ­¨ç¥­® 31.
+parser_e_range_check_error=03035_E_Žè¨¡ª  ¯à®¢¥àª¨ ¤¨ ¯ §®­  ¯p¨ ¢ëç¨á«¥­¨¨ ª®­áâ ­â
+% ‡­ ç¥­¨¥ ª®­áâ ­â ­ å®¤¨âáï ¢­¥ ¤®¯ãá⨬®£® ¤«ï ­¨å ¤¨ ¯ §®­ .
+parser_w_range_check_error=03036_W_Žè¨¡ª  ¯à®¢¥àª¨ ¤¨ ¯ §®­  ¯p¨ ¢ëç¨á«¥­¨¨ ª®­áâ ­â
+% ‡­ ç¥­¨¥ ª®­áâ ­â ­ å®¤¨âáï ¢­¥ ¤®¯ãá⨬®£® ¤«ï ­¨å ¤¨ ¯ §®­ .
+parser_e_double_caselabel=03037_E_®¢â®pïîé ïáï ¬¥âª  CASE
+% Ž¤­  ¨ â  ¦¥ ¬¥âª  㪠§ ­  2 à §  ¢ ®¤­®¬ ¢ëà ¦¥­¨¨ \var{case}.
+parser_e_case_lower_less_than_upper_bound=03038_E_‚¥på­ïï £p ­¨æ  ¤¨ ¯ §®­  case ¬¥­ìè¥, 祬 ­¨¦­ïï
+% ‚¥àå­ïï £à ­¨æ  ¬¥âª¨ \var{case} ¬¥­ìè¥ ­¨¦­¥© £à ­¨æë, ¯®í⮬㠬¥âª  ­¥ ¨¬¥¥â á¬ëá« .
+parser_e_type_const_not_possible=03039_E_’¨¯¨§¨p®¢ ­­ë¥ ª®­áâ ­âë ª« áᮢ ¨ ¨­â¥à䥩ᮢ ­¥ ¯®¤¤¥p¦¨¢ îâáï
+% Ž¡ê¥­¨ï ª®­áâ ­â, ¨¬¥îé¨å ⨯ ª« áá  «¨¡® ¨­â¥à䥩á , ­¥ ¤®¯ã᪠¥âáï.
+parser_e_no_overloaded_procvars=03040_E_¥à¥¬¥­­ë¥ ¯¥à¥£à㦥­­ëå ä㭪権 ­¥ ¯®¤¤¥p¦¨¢ îâáï
+% ¥¤®¯ãá⨬ ï ¯®¯ë⪠ ¯à¨á¢®¥­¨ï ¯¥à¥£à㦥­­®© ä㭪樨 ¯à®æ¥¤ãà­®© ¯¥à¥¬¥­­®©.
+parser_e_invalid_string_size=03041_E_„«¨­  áâp®ª¨ ¤®«¦­  ¡ëâì ¢ ¤¨ ¯ §®­¥ 1 .. 255
+% „«¨­  áâப¨ ⨯  shortstring ®£à ­¨ç¥­  255 ᨬ¢®« ¬¨. ®¯ë⪠ ®¡êâì áâபã
+% á ¤«¨­®© ¬¥­¥¥ 1 ¨«¨ ¡®«¥¥ 255.
+parser_w_use_extended_syntax_for_objects=03042_W_ˆá¯®«ì§ã©â¥ p áè¨p¥­­ë© ᨭ⠪á¨á NEW ¨ DISPOSE ¤«ï ᮧ¤ ­¨ï íª§¥¬¯«ï஢ ®¡ê¥ªâ®¢
+% ਠ­ «¨ç¨¨ 㪠§ â¥«ï \var{a} ­  ⨯ ª« áá , ¢ë§®¢
+% \var{new(a)} ­¥ ¯à®¨­¨æ¨ «¨§¨àã¥â ª« áá (â.¥. ª®­áâàãªâ®à ­¥ ¡ã¤¥â
+% ¢ë§¢ ­), å®âï ¯ ¬ïâì ¡ã¤¥â ¢ë¤¥«¥­ . ‘«¥¤ã¥â ¨á¯®«ì§®¢ âì ¢ë§®¢
+% \var{new(a,init)}, ª®â®àë© ¢ë¤¥«¨â ¯ ¬ïâì ¨ ¢ë§®¢¥â ª®­áâàãªâ®à ª« áá .
+parser_w_no_new_dispose_on_void_pointers=03043_W_ˆá¯®«ì§®¢ ­¨¥ NEW ¨ DISPOSE ¤«ï ­¥â¨¯¨§¨p®¢ ­­ëå yª § â¥«¥© ¡¥áá¬ëá«¥­­®
+parser_e_no_new_dispose_on_void_pointers=03044_E_ˆá¯®«ì§®¢ ­¨¥ NEW ¨ DISPOSE ¤«ï ­¥â¨¯¨§¨p®¢ ­­ëå yª § â¥«¥© ­¥¢®§¬®¦­®
+% ‚맮¢ë \var{new(p)} ¨«¨ \var{dispose(p)} ­¥¢®§¬®¦­ë, ¥á«¨ \var{p} ï¥âáï ­¥â¨¯¨§¨à®¢ ­­ë¬ 㪠§ â¥«¥¬,
+% â.ª. ¯à¨ í⮬ ®âáãâáâ¢ã¥â ¨­ä®à¬ æ¨ï ® à §¬¥à¥ ¢ë¤¥«ï¥¬®© ¯ ¬ïâ¨.
+% ਭ¨¬ ¥âáï ¤«ï ᮢ¬¥á⨬®á⨠¢ ०¨¬ å \var{tp} ¨ \var{delphi}.
+parser_e_class_id_expected=03045_E_Ž¦¨¤ ¥âáï ¨¤¥­â¨ä¨ª â®p ª« áá 
+% நá室¨â ¯à¨ ᪠­¨à®¢ ­¨¨ ¨¬¥­¨ ¯à®æ¥¤ãàë, ᮤ¥à¦ é¥£® â®çªã, â.¥. ¬¥â®¤ 
+% ª« áá  ¨«¨ ®¡ê¥ªâ , ­® ⨯ ¯¥à¥¤ â®çª®© ­¥¨§¢¥á⥭.
+parser_e_no_type_not_allowed_here=03046_E_ˆ¤¥­â¨ä¨ª â®p ⨯  §¤¥áì ­¥¤®¯ãá⨬
+% ˆ¤¥­â¨ä¨ª â®à ⨯  ­¥ ¬®¦¥â ¡ëâì ¨á¯®«ì§®¢ ­ ¢ ¢ëà ¦¥­¨¨.
+parser_e_methode_id_expected=03047_E_Ž¦¨¤ ¥âáï ¨¤¥­â¨ä¨ª â®p ¬¥â®¤ 
+% ˆ¤¥­â¨ä¨ª â®à ­¥ ï¥âáï ¬¥â®¤®¬.
+% நá室¨â ¯à¨ ᪠­¨à®¢ ­¨¨ ¨¬¥­¨ ¯à®æ¥¤ãàë, ᮤ¥à¦ é¥£® â®çªã, â.¥. ¬¥â®¤ 
+% ª« áá  ¨«¨ ®¡ê¥ªâ , ­® ¨¬ï ¯à®æ¥¤ãàë ®âáãâáâ¢ã¥â ¢ ®¡ê¥­¨¨ ª« áá .
+parser_e_header_dont_match_any_member=03048_E_‡ £®«®¢®ª äy­ªæ¨¨ ­¥ ᮮ⢥âáâ¢ã¥â ­¨ ®¤­®¬ã ¨§ ¬¥â®¤®¢ ª« áá  "$1"
+% ˆ¤¥­â¨ä¨ª â®à ­¥ ï¥âáï ¬¥â®¤®¬.
+% நá室¨â ¯à¨ ᪠­¨à®¢ ­¨¨ ¨¬¥­¨ ¯à®æ¥¤ãàë, ᮤ¥à¦ é¥£® â®çªã, â.¥. ¬¥â®¤ 
+% ª« áá  ¨«¨ ®¡ê¥ªâ , ­® ¨¬ï ¯à®æ¥¤ãàë ®âáãâáâ¢ã¥â ¢ ®¡ê¥­¨¨ ª« áá .
+parser_d_procedure_start=03049_DL_p®æ¥¤yp /”y­ªæ¨ï $1
+% ਠ¨á¯®«ì§®¢ ­¨¨ ª«îç  \var{-vd} ª®¬¯¨«ïâ®à á®®¡é ¥â ® ­ ç «¥ ®¡à ¡®âª¨
+% ⥫  ¯à®æ¥¤ãàë ¨«¨ ä㭪樨.
+parser_e_error_in_real=03050_E_H¥¢¥p­ ï ª®­áâ ­â  á ¯« ¢ î饩 § ¯ï⮩
+% Š®¬¯¨«ïâ®à ®¦¨¤ ¥â ¢ëà ¦¥­¨¥ ¢¥é¥á⢥­­®£® ⨯ , ­® ¯®«ãç ¥â çâ®-â® ¤à㣮¥.
+parser_e_fail_only_in_constructor=03051_E_FAIL ¤®¯ãá⨬ ⮫쪮 ¢ ª®­áâpyªâ®p å
+% ˆ­áâàãªæ¨ï \var{FAIL} ¨á¯®«ì§®¢ ­  ¢­¥ ¬¥â®¤  ª®­áâàãªâ®à .
+parser_e_no_paras_for_destructor=03052_E_„¥áâpyªâ®pë ­¥ ¬®£yâ ¨¬¥âì ¯ p ¬¥âp®¢
+% „¥áâàãªâ®à ®¡ê¥­ ᮠᯨ᪮¬ ¯ à ¬¥â஢. Œ¥â®¤ë ¤¥áâàãªâ®à®¢ ­¥ ¬®£ãâ ¨¬¥âì ¯ à ¬¥â஢.
+% cannot have parameters.
+parser_e_only_class_methods_via_class_ref=03053_E_® áá뫪¥ ­  ª« áá ¬®£ãâ ¡ëâì ¢ë§¢ ­ë ⮫쪮 ª« áá-¬¥â®¤ë
+% Žè¨¡ª  ¢®§­¨ª ¥â ¢ á«¥¤ãî饩 á¨âã æ¨¨:
+% \begin{verbatim}
+% Type :
+% Tclass = Class of Tobject;
+%
+% Var C : TClass;
+%
+% begin
+% ...
+% C.free
+% \end{verbatim}
+% \var{Free} ­¥ ï¥âáï ª« áá-¬¥â®¤®¬ ¨ ¯®í⮬㠭¥ ¬®¦¥â ¡ëâì ¢ë§¢ ­ ¯® áá뫪¥ ­  ª« áá.
+parser_e_only_class_methods=03054_E_‚ ª« áá-¬¥â®¤ å ¤®áâ㯭ë ⮫쪮 ¤à㣨¥ ª« áá-¬¥â®¤ë
+% ˆ¬¥¥â ®â­®è¥­¨¥ ª ¯à¥¤ë¤ã饩 ®è¨¡ª¥. ˆ§ ª« áá-¬¥â®¤  ­¥«ì§ï ¢ë§¢ âì ®¡ëç­ë© ¬¥â®¤ ®¡ê¥ªâ .
+% ‘«¥¤ãî騩 ª®¤ ¯à¨¢¥¤¥â ª í⮩ ®è¨¡ª¥:
+% \begin{verbatim}
+% class procedure tobject.x;
+%
+% begin
+% free
+% \end{verbatim}
+% ®áª®«ìªã free ï¥âáï ®¡ëç­ë¬ ¬¥â®¤®¬, ¥£® ­¥«ì§ï ¢ë§¢ âì ¨§ ª« áá-¬¥â®¤ .
+parser_e_case_mismatch=03055_E_’¨¯ ª®­áâ ­âë ­¥ ᮢ¯ ¤ ¥â á ⨯®¬ ¢ëp ¦¥­¨ï CASE
+% Ž¤­  ¨§ ¬¥â®ª ¨¬¥¥â ⨯, ®â«¨ç­ë© ®â ⨯  ¢ëà ¦¥­¨ï case.
+parser_e_illegal_symbol_exported=03056_E_‘¨¬¢®« ­¥ ¬®¦¥â ¡ëâì íªá¯®àâ¨à®¢ ­ ¨§ ¡¨¡«¨®â¥ª¨
+% ਠ­ ¯¨á ­¨¨ ¡¨¡«¨®â¥ª¨ ¬®¦­® íªá¯®àâ¨à®¢ âì ⮫쪮 ¯à®æ¥¤ãàë ¨ ä㭪樨. ’ ª¨¥ ⨯ë,
+% ª ª ¯¥à¥¬¥­­ë¥ ¨ ª®­áâ ­âë, íªá¯®àâ¨à®¢ âì ­¥«ì§ï.
+parser_w_should_use_override=03057_W_“­ á«¥¤®¢ ­­ë© ¬¥â®¤ "$1" áªàëâ, ¨á¯®«ì§ã©â¥ override
+% Œ¥â®¤, ®¡ê¥­­ë© ¢ த¨â¥«ì᪮¬ ª« áᥠª ª \var{virtual}, ¤®«¦¥­ ¡ëâì
+% ¯¥à¥ªàëâ ¢ ª« áá¥-­ á«¥¤­¨ª¥ ¤¨à¥ªâ¨¢®© \var{override}. …᫨ ¤¨à¥ªâ¨¢ 
+% \var{override} ­¥ 㪠§ ­ , ã­ á«¥¤®¢ ­­ë© ¬¥â®¤ ¡ã¤¥â áªàëâ,   ­¥ ¯¥à¥ªàëâ.
+parser_e_nothing_to_be_overridden=03058_E_‚ த¨â¥«ì᪮¬ ª« áᥠ­¥â ¬¥â®¤  ¤«ï ¯¥p¥ªàëâ¨ï: "$1"
+% ®¯ë⪠ ¯¥à¥ªàëâì \var{override} ¢¨àâã «ì­ë© ¬¥â®¤, ®âáãâáâ¢ãî騩 ¢ த¨â¥«ì᪮¬ ª« áá¥î.
+parser_e_no_procedure_to_access_property=03059_E_¥ 㪠§ ­ ᯮᮡ ¤®áâ㯠 ª ᢮©áâ¢ã
+% „«ï ᢮©á⢠ ­¥ 㪠§ ­  ¤¨à¥ªâ¨¢  \var{read}.
+parser_w_stored_not_implemented=03060_W_„¨à¥ªâ¨¢  stored ¤«ï ᢮©á⢠¥é¥ ­¥ p¥ «¨§®¢ ­ 
+% „¨à¥ªâ¨¢  \var{stored} ¥é¥ ­¥ ॠ«¨§®¢ ­ 
+parser_e_ill_property_access_sym=03061_E_H¥¢¥p­ë© ᨬ¢®« ¤«ï ¤®áâ㯠 ª ᢮©áâ¢y
+% Žè¨¡ª  ¢ ¤¨à¥ªâ¨¢¥ \var{read} ¨«¨ \var{write} ¤«ï ᢮©á⢠ ⨯  ¬ áᨢ.
+% „®áâ㯠ª ᢮©áâ¢ã ⨯  ¬ áᨢ ¢®§¬®¦¥­ ⮫쪮 á ¯®¬®éìî ¯à®æ¥¤ãà ¨ ä㭪権.
+% ‘«¥¤ãî騩 ª®¤ ¢ë§®¢¥â ®è¨¡ªã:
+% \begin{verbatim}
+% tmyobject = class
+% i : integer;
+% property x [i : integer]: integer read I write i;
+% \end{verbatim}
+%
+parser_e_cant_access_protected_member=03062_E_„®áâ㯠ª protected ¯®«î ®¡ê¥ªâ  §¤¥áì ­¥¢®§¬®¦¥­
+% ®«ï, ®¯à¥¤¥«¥­­ë¥ ¢ ᥪ樨 \var{protected} ®¡ê¥­¨ï ª« áá ,
+% ­¥¤®áâã¯­ë ¢­¥ ¬®¤ã«ï, ¢ ª®â®à®¬ ®¡ê¥­ ª« áá, ¨ ¢­¥ ¬¥â®¤®¢ ®¡ê¥ªâ®¢-­ á«¥¤­¨ª®¢.
+parser_e_cant_access_private_member=03063_E_„®áâ㯠ª private ¯®«î ®¡ê¥ªâ  §¤¥áì ­¥¢®§¬®¦¥­
+% ®«ï, ®¯à¥¤¥«¥­­ë¥ ¢ ᥪ樨 \var{private} ®¡ê¥­¨ï ª« áá ,
+% ­¥¤®áâã¯­ë ¢­¥ ¬®¤ã«ï, ¢ ª®â®à®¬ ®¡ê¥­ ª« áá.
+parser_e_overridden_methods_not_same_ret=03066_E_¥à¥ªàëâë¥ ¬¥â®¤ë ¤®«¦­ë ¨¬¥âì ®¤¨­ ª®¢ë© ⨯ १ã«ìâ â : "$2" ¯¥à¥ªàëâ "$1", ª®â®àë© ¢®§¢à é ¥â ¤à㣮© ⨯
+% ¥à¥ªàëâë¥ ¬¥â®¤ë ¤®«¦­ë ¢®§¢à é âì १ã«ìâ â ®¤¨­ ª®¢®£® ⨯ .
+parser_e_dont_nest_export=03067_E_ªá¯®àâ¨àã¥¬ë¥ äy­ªæ¨¨ ­¥ ¬®£yâ ¡ëâì ¢«®¦¥­­ë¬¨
+% ¥«ì§ï ®¡êâì ¯à®æ¥¤ãàã ¨«¨ äã­ªæ¨î, ¢«®¦¥­­ãî ¢ ¯à®æ¥¤ãàã ¨«¨ äã­ªæ¨î, ®¡ê¥­­ãî ª ª íªá¯®àâ¨à㥬 ï.
+parser_e_methods_dont_be_export=03068_E_Œ¥â®¤ë ­¥ ¬®£yâ íªá¯®pâ¨p®¢ âìáï
+% Œ¥â®¤ ª« áá  ¨«¨ ®¡ê¥ªâ  ­¥ ¬®¦¥â ¡ëâì ®¡ê¥­ ª ª
+% \var{export}.
+parser_e_call_by_ref_without_typeconv=03069_E_’¨¯ ¯ à ¬¥âà  no. $1 ¯à¨ ¯¥à¥¤ ç¥ ¯® áá뫪¥ ¤®«¦¥­ ᮢ¯ ¤ âì: ¯®«ã祭® "$2", ®¦¨¤ «®áì "$3"
+% ਠ¢ë§®¢¥ ä㭪樨, ¨¬¥î饩 ¯ à ¬¥âàë ¯® áá뫪¥ (\var{var}), ⨯ ¯ à ¬¥âà 
+% ¤®«¦¥­ áâண® ᮢ¯ ¤ âì á ®¡ê¥­­ë¬. €¢â®¬ â¨ç¥áª®¥ ¯à¥®¡à §®¢ ­¨¥ ⨯®¢
+% ¢ í⮬ á«ãç ¥ ®âáãâáâ¢ã¥â.
+parser_e_no_super_class=03070_E_Š« áá ­¥ ï¥âáï த¨â¥«ì᪨¬ ¤«ï ⥪ã饣® ª« áá 
+% ਠ¢ë§®¢¥ ã­ á«¥¤®¢ ­­®£® ¬¥â®¤  㪠§ ­ ª« áá, ®â«¨ç­ë© ®â த¨â¥«ì᪮£®.
+% “­ á«¥¤®¢ ­­ë© ¬¥â®¤ ¬®¦­® ¢ë§ë¢ âì ⮫쪮 ã த¨â¥«ì᪮£® ª« áá .
+parser_e_self_not_in_method=03071_E_SELF ¤®¯ãá⨬ ⮫쪮 ¢ ¬¥â®¤ å
+% ®¯ë⪠ ¨á¯®«ì§®¢ ­¨ï ¯ à ¬¥âà  \var{self} ¢­¥ ¬¥â®¤  ®¡ê¥ªâ .
+%  à ¬¥âà \var{self} ¯¥à¥¤ ¥âáï ⮫쪮 ¢ ¬¥â®¤ë.
+parser_e_generic_methods_only_in_methods=03072_E_‚맮¢ ¬¥â®¤®¢ á ¨¤¥­â¨ä¨ª â®à®¬ ⨯  ª« áá  ¢®§¬®¦¥­ ⮫쪮 ¨§ ¤àã£¨å ¬¥â®¤®¢
+% Š®­áâàãªæ¨ï ¢¨¤  \var{sometype.somemethod} ¤®¯ãá⨬  ⮫쪮 ¢­ãâਠ¬¥â®¤®¢.
+parser_e_illegal_colon_qualifier=03073_E_H¥¢¥à­®¥ ¨á¯®«ì§®¢ ­¨¥ ':'
+% ”®à¬ â \var{:} (¤¢®¥â®ç¨¥) 2 à §  ¨á¯®«ì§ã¥âáï ­  ¢ëà ¦¥­¨¨, ª®â®à®¥ ­¥ ï¥âáï ¢¥é¥á⢥­­ë¬.
+parser_e_illegal_set_expr=03074_E_Žè¨¡ª  ¯à®¢¥àª¨ ¤¨ ¯ §®­  ¢ ª®­áâàãªâ®à¥ ¬­®¦¥á⢠ ¨«¨ ¯®¢â®àïî騩áï í«¥¬¥­â ¬­®¦¥á⢠
+% Žè¨¡ª  ¢ ®¡ê¥­¨¨ ¬­®¦¥á⢠. ‹¨¡® ®¤¨­ ¨§ í«¥¬¥­â®¢ ¢ë室¨â §  ¤®¯ãáâ¨¬ë© ¤¨ ¯ §®­,
+% «¨¡® ª ª¨¥-«¨¡® ¤¢  í«¥¬¥­â  ¨¬¥îâ ®¤­® ¨ â® ¦¥ §­ ç¥­¨¥.
+parser_e_pointer_to_class_expected=03075_E_Ž¦¨¤ ¥âáï yª § â¥«ì ­  ®¡ê¥ªâ
+% ˆá¯®«ì§®¢ ­ ­¥¢¥à­ë© ⨯ ¢ ¢ëà ¦¥­¨¨ \var{New}.
+%  áè¨à¥­­ë© ᨭ⠪á¨á \var{New} âॡã¥â ¯ à ¬¥âà  â¨¯  ®¡ê¥ªâ.
+parser_e_expr_have_to_be_constructor_call=03076_E_‚ëp ¦¥­¨¥ ¤®«¦­® ¢ë§ë¢ âì ª®­áâpyªâ®p
+% ਠ¨á¯®«ì§®¢ ­¨¨ à áè¨à¥­­®£® ᨭ⠪á¨á  \var{new} ­ã¦­® 㪠§ë¢ âì ª®­áâàãªâ®à ®¡ê¥ªâ .
+% “ª § ­­ ï ¯à®æ¥¤ãà  ­¥ ï¥âáï ª®­áâàãªâ®à®¬.
+parser_e_expr_have_to_be_destructor_call=03077_E_‚ëp ¦¥­¨¥ ¤®«¦­® ¢ë§ë¢ âì ¤¥áâpyªâ®p
+% ਠ¨á¯®«ì§®¢ ­¨¨ à áè¨à¥­­®£® ᨭ⠪á¨á  \var{dispose} ­ã¦­® 㪠§ë¢ âì ¤¥áâàãªâ®à ®¡ê¥ªâ .
+% “ª § ­­ ï ¯à®æ¥¤ãà  ­¥ ï¥âáï ¤¥áâàãªâ®à®¬.
+parser_e_invalid_record_const=03078_E_H¥¢¥p­ë© ¯®p冷ª í«¥¬¥­â®¢ § ¯¨á¨
+% ਠ®¡ê¥­¨¨ ª®­áâ ­âë ⨯  § ¯¨áì, ¯®«ï 㪠§ ­ë ¢ ­¥¢¥à­®¬ ¯®à浪¥.
+parser_e_false_with_expr=03079_E_’¨¯ ¢ëp ¦¥­¨ï ¤®«¦¥­ ¡ëâì CLASS ¨«¨ RECORD
+% €à£ã¬¥­â ¢ëà ¦¥­¨ï \var{with} ¤®«¦¥­ ¡ëâì ⨯  \var{record} ¨«¨
+% \var{class}. ˆá¯®«ì§®¢ ­  à£ã¬¥­â á ⨯®¬, ®â«¨ç­ë¬ ®â 㪠§ ­­ëå.
+parser_e_void_function=03080_E_p®æ¥¤yp  ­¥ ¬®¦¥â ¢®§¢p é âì §­ ç¥­¨¥
+% \fpc ¯®§¢®«ï¥â 㪠§ âì ¢®§¢à é ¥¬®¥ §­ ç¥­¨¥ ¤«ï ä㭪樨 ¯à¨ ¨á¯®«ì§®¢ ­¨¨
+% ¢ëà ¦¥­¨ï \var{exit}. Žè¨¡ª  ¢®§­¨ª ¥â ¯à¨ ¯®¯ë⪥ ᤥ« âì íâ® ¢ ¯à®æ¥¤ãà¥.
+% à®æ¥¤ãà  ­¥ ¬®¦¥â ¢®§¢à é âì §­ ç¥­¨¥.
+parser_e_only_methods_allowed=03081_E_Š®­áâpyªâ®pë, ¤¥áâpyªâ®pë ¨ ®¯¥à â®àë ª« áá  ¤®«¦­ë ¡ëâì ¬¥â®¤ ¬¨
+% ®¯ë⪠ ®¯à¥¤¥«¨âì ¯à®æ¥¤ãàã, ­¥ ïîéãîáï ¬¥â®¤®¬ ª« áá , ª ª ª®­áâàãªâ®à, ¤¥áâàãªâ®à ¨«¨ ®¯¥à â®à ª« áá .
+parser_e_operator_not_overloaded=03082_E_Ž¯¥p â®p ­¥ ¯¥p¥£py¦¥­
+% ®¯ë⪠ ¨á¯®«ì§®¢ âì ¯¥à¥£à㦥­­ë© ®¯¥à â®à, ª®£¤  ®­ ­¥ ¯¥à¥£à㦥­ ¤«ï ¤ ­­®£® ⨯ .
+parser_e_no_such_assignment=03083_E_¥¢®§¬®¦­® ¯¥à¥£à㧨âì ¯à¨á¢®¥­¨¥ ¤«ï ®¤¨­ ª®¢ëå ⨯®¢
+% ¥à¥£à㦥­­®¥ ¯à¨á¢®¥­¨¥ ­¥¢®§¬®¦­® ¤«ï ⨯®¢, ª®â®àë¥ ª®¬¯¨«ïâ®à áç¨â ¥â ®¤¨­ ª®¢ë¬¨.
+parser_e_overload_impossible=03084_E_¥à¥£à㧪  ®¯¥à â®à  ­¥¢®§¬®¦­ 
+% ‘®ç¥â ­¨¥ ®¯¥à â®à ,  à£ã¬¥­â®¢ ¨ ¢®§¢à é ¥¬®£® §­ ç¥­¨ï ï¥âáï ­¥á®¢¬¥á⨬ë¬.
+parser_e_no_reraise_possible=03085_E_®¢â®à­®¥ ¡à®á ­¨¥ ¨áª«î祭¨ï §¤¥áì ­¥¢®§¬®¦­®
+% ®¯ë⪠ ¯®¢â®à­®£® ¡à®á ­¨ï ¨áª«î祭¨ï ¢ ­¥¤®¯ãá⨬®¬ ¬¥áâ¥. â® à §à¥è¥­® ¤¥« âì ⮫쪮
+% ¢ ¡«®ª¥ \var{except}.
+parser_e_no_new_or_dispose_for_classes=03086_E_ áè¨p¥­­ë© ᨭ⠪á¨á NEW ¨ DISPOSE ­¥ à §à¥è¥­ ¤«ï ª« áᮢ
+% ª§¥¬¯«ïà ª« áá  ­¥ ¬®¦¥â ¡ëâì ᮧ¤ ­ á ¯®¬®éìî à áè¨à¥­­®£® ᨭ⠪á¨á 
+% \var{new}, ¤«ï í⮣® á«¥¤ã¥â ¨á¯®«ì§®¢ âì ª®­áâàãªâ®à. €­ «®£¨ç­®, ¤«ï
+% 㤠«¥­¨ï íª§¥¬¯«ïà  ª« áá  á«¥¤ã¥â ¨á¯®«ì§®¢ âì ­¥ \var{Dispose},   ¤¥áâàãªâ®à.
+parser_e_procedure_overloading_is_off=03088_E_¥à¥£à㧪  ¯p®æ¥¤yp ®âª«î祭 
+% ਠ¨á¯®«ì§®¢ ­¨¨ ª«îç  \var{-So} ¯¥à¥£à㧪  ¯à®æ¥¤ãà ®âª«î祭 .
+% Turbo Pascal ­¥ ¯®¤¤¥à¦¨¢ ¥â ¯¥à¥£à㧪ã.
+parser_e_overload_operator_failed=03089_E_¥à¥£à㧪  í⮣® ®¯¥à â®à  ­¥¢®§¬®¦­ . ¥à¥£à㦠¥¬ë¥ ®¯¥à â®àë (¥á«¨ ¥áâì): $1
+% ®¯ë⪠ ¯¥à¥£à㧨âì ®¯¥à â®à, ª®â®àë© ­¥ ¬®¦¥â ¡ëâì ¯¥à¥£à㦥­.
+% ‘«¥¤ãî騥 ®¯¥à â®àë ¬®£ãâ ¡ëâì ¯¥à¥£à㦥­ë:
+% \begin{verbatim}
+% +, -, *, /, =, >, <, <=, >=, is, as, in, **, :=
+% \end{verbatim}
+parser_e_comparative_operator_return_boolean=03090_E_Ž¯¥à â®à áà ¢­¥­¨ï ¤®«¦¥­ ¢®§¢à é âì §­ ç¥­¨¥ ⨯  boolean
+% ਠ¯¥à¥£à㧪¥ ®¯¥à â®à  áà ¢­¥­¨ï \var{=}, äã­ªæ¨ï ¤®«¦­  ¢®§¢à é âì §­ ç¥­¨¥ ⨯  boolean.
+parser_e_only_virtual_methods_abstract=03091_E_’®«ìª® ¢¨àâã «ì­ë¥ ¬¥â®¤ë ¬®£ãâ ¡ëâì  ¡áâà ªâ­ë¬¨
+% ®¯ë⪠ ®¯à¥¤¥«¨âì  ¡áâà ªâ­ë© ¬¥â®¤, ­¥ ïî騩áï ¯à¨ í⮬ ¢¨àâã «ì­ë¬.
+parser_f_unsupported_feature=03092_F_ˆá¯®«ì§®¢ ­¨¥ ¯®ª  ­¥¯®¤¤¥à¦¨¢ ¥¬®© ®á®¡¥­­®á⨠ª®¬¯¨«ïâ®à !
+% ®¯ë⪠ § áâ ¢¨âì ª®¬¯¨«ïâ®à ᤥ« âì ­¥çâ®, 祣® ®­ ¯®ª  ¥é¥ ­¥ 㬥¥â.
+parser_e_mix_of_classes_and_objects=03093_E_‘¬¥è¨¢ ­¨¥ à §«¨ç­ëå ⨯®¢ ®¡ê¥ªâ®¢ (class, object, interface) ­¥ ¤®¯ã᪠¥âáï
+% ˆ§¬¥­¥­¨¥ ¡ §®¢®£® ⨯  ¯à¨ ­ á«¥¤®¢ ­¨¨ ­¥ ¤®¯ã᪠¥âáï. â®, ¢ ç áâ­®áâ¨, ®§­ ç ¥â, çâ®
+% class ­¥ ¬®¦¥â ¡ëâì ¯®à®¦¤¥­ ®â object, ¨ ­ ®¡®à®â.
+parser_w_unknown_proc_directive_ignored=03094_W_¥¨§¢¥áâ­ ï ¤¨à¥ªâ¨¢  ¯à®æ¥¤ãàë: "$1", ¨£­®à¨à®¢ ­®
+% “ª § ­­ ï ¤¨à¥ªâ¨¢  ¯à®æ¥¤ãàë ­¥¨§¢¥áâ­  ª®¬¯¨«ïâ®àã.
+parser_e_absolute_only_one_var=03095_E_ABSOLUTE ¬®¦¥â ¡ëâì 㪠§ ­® ⮫쪮 ¤«ï ®¤­®© ¯¥p¥¬¥­­®©
+% ¥«ì§ï 㪠§ë¢ âì ¡®«¥¥ ®¤­®© ¯¥à¥¬¥­­®© ¯¥à¥¤ ¤¨à¥ªâ¨¢®© \var{absolute}.
+% ‘«¥¤ãîé ï ª®­áâàãªæ¨ï ¯à¨¢¥¤¥â ª ®è¨¡ª¥:
+% \begin{verbatim}
+% Var Z : Longint;
+% X,Y : Longint absolute Z;
+% \end{verbatim}
+parser_e_absolute_only_to_var_or_const=03096_E_ABSOLUTE ¬®¦¥â ¡ëâì á¢ï§ ­  ⮫쪮 á ¯¥p¥¬¥­­®© ¨«¨ ª®­á⠭⮩
+% €¤à¥á ¤¨à¥ªâ¨¢ë \var{absolute} ¬®¦¥â 㪠§ë¢ âì ⮫쪮 ­  ¯¥à¥¬¥­­ãî ¨«¨
+% ª®­áâ ­âã. ‘«¥¤ãî騩 ª®¤ ¯à¨¢¥¤¥â ª ®è¨¡ª¥:
+% \begin{verbatim}
+% Procedure X;
+%
+% var p : longint absolute x;
+% \end{verbatim}
+%
+parser_e_initialized_only_one_var=03097_E_ˆ­¨æ¨ «¨§ æ¨ï ¤®¯ãá⨬  ⮫쪮 ¤«ï ®¤­®© ¯¥à¥¬¥­­®©
+% ¥¤®¯ãá⨬® 㪠§ ­¨¥ ­ ç «ì­®£® §­ ç¥­¨ï ¡®«¥¥ 祬 ¤«ï ®¤­®© ¯¥à¥¬¥­­®© ¢
+% ᨭ⠪á¨á¥ Delphi.
+parser_e_abstract_no_definition=03098_E_€¡áâà ªâ­ë¥ ¬¥â®¤ë ­¥ ¬®£ãâ ¨¬¥âì ॠ«¨§ æ¨î (⥫®)
+% €¡áâà ªâ­ë¥ ¬¥â®¤ë ¬®£ãâ ¨¬¥âì ⮫쪮 ®¡ê¥­¨¥, ॠ«¨§ æ¨ï ¤«ï ­¨å ­¥¤®¯ãá⨬ . Ž­¨
+% ¤®«¦­ë ¡ëâì ¯¥à¥ªàëâë ¢ ã­ á«¥¤®¢ ­­ëå ª« áá å.
+parser_e_overloaded_must_be_all_global=03099_E_â  ¯¥à¥£à㦥­­ ï äã­ªæ¨ï ­¥ ¬®¦¥â ¡ëâì «®ª «ì­®© (¤®«¦­  íªá¯®àâ¨à®¢ âìáï)
+% ®¯ë⪠ ®¯à¥¤¥«¨âì ¯¥à¥£à㦥­­ãî äã­ªæ¨î ¢ ᥪ樨 implementation ¬®¤ã«ï,
+% ¤«ï ª®â®à®© ®âáãâáâ¢ã¥â ®¡ê¥­¨¥ ¢ ᥪ樨 interface.
+parser_w_virtual_without_constructor=03100_W_‚¨àâã «ì­ë¥ ¬¥â®¤ë ¨á¯®«ì§ãîâáï ¡¥§ ª®­áâàãªâ®à  ¢ "$1"
+% ਠ®¡ê¥­¨¨ ®¡ê¥ªâ  ¨«¨ ª« áá , ᮤ¥à¦ é¥£® ¢¨àâã «ì­ë¥ ¬¥â®¤ë, ¤«ï
+% ¨å ª®à४⭮© ¨­¨æ¨ «¨§ æ¨¨ âॡã¥âáï ª®­áâàãªâ®à. Š®¬¯¨«ïâ®à ¢áâà¥â¨« ®¡ê¥­¨¥
+% ª« áá  ¨«¨ ®¡ê¥ªâ  á ¢¨àâã «ì­ë¬¨ ¬¥â®¤ ¬¨, ­® ¡¥§ ¯ àë ª®­áâàãªâ®à/¤¥áâàãªâ®à.
+parser_c_macro_defined=03101_CL_Ž¯p¥¤¥«¥­ ¬ ªp®á: $1
+% ਠ¨á¯®«ì§®¢ ­¨¨ \var{-vc} ª®¬¯¨«ïâ®à á®®¡é ¥â ®¡ ®¯à¥¤¥«¥­¨¨ ¬ ªà®á®¢.
+parser_c_macro_undefined=03102_CL_“¤ «¥­® ®¯à¥¤¥«¥­¨¥ ¬ ªà®á : $1
+% ਠ¨á¯®«ì§®¢ ­¨¨ \var{-vc} ª®¬¯¨«ïâ®à á®®¡é ¥â ® ⮬, çâ® ¬ ªà®á ¡®«ìè¥ ­¥ ®¯à¥¤¥«¥­.
+parser_c_macro_set_to=03103_CL_Œ ªp®á $1 yáâ ­®¢«¥­ ¢ $2
+% ਠ¨á¯®«ì§®¢ ­¨¨ \var{-vc} ª®¬¯¨«ïâ®à á®®¡é ¥â ®¡ ¨§¬¥­¥­¨¨ §­ ç¥­¨ï ¬ ªà®á .
+parser_i_compiling=03104_I_Š®¬¯¨«ïæ¨ï $1
+% ਠ¢ª«î祭¨¨ ¨­ä®à¬ æ¨®­­ëå á®®¡é¥­¨© (\var{-vi}), ª®¬¯¨«ïâ®à á®®¡é ¥â ® ⮬,
+% ª ª¨¥ ¬®¤ã«¨ ®­ ª®¬¯¨«¨àã¥â.
+parser_u_parsing_interface=03105_UL_€­ «¨§ ¨­â¥àä¥©á  ¬®¤y«ï $1
+% ‘®®¡é ¥â ® ­ ç «¥ à §¡®à  ¨­â¥à䥩᭮© ç á⨠⥪ã饣® ¬®¤ã«ï.
+parser_u_parsing_implementation=03106_UL_€­ «¨§ ॠ«¨§ æ¨¨ ¬®¤y«ï $1
+% ‘®®¡é ¥â ® ­ ç «¥ à §¡®à  ॠ«¨§ æ¨¨ ⥪ã饣® ¬®¤ã«ï, ¯à®£à ¬¬ë ¨«¨ ¡¨¡«¨®â¥ª¨.
+parser_d_compiling_second_time=03107_DL_®¢â®à­ ï ª®¬¯¨«ïæ¨ï $1
+% ਠ¢ª«î祭¨¨ ®â« ¤®ç­ëå á®®¡é¥­¨© (\var{-vd}) ª®¬¯¨«ïâ®à á®®¡é ¥â ® ⮬,
+% ª ª¨¥ ¬®¤ã«¨ ®­ ª®¬¯¨«¨àã¥â ¯®¢â®à­®.
+parser_e_no_property_found_to_override=03109_E_Žâáãâáâ¢ã¥â ᢮©á⢮ ¤«ï ¯¥p¥®¯p¥¤¥«¥­¨ï
+% ®¯ë⪠ ¯¥à¥®¯à¥¤¥«¨âì ᢮©á⢮ த¨â¥«ì᪮£® ª« áá , ¯à¨ ®âáãâá⢨¨ â ª®¢®£® ¢ த¨â¥«ì᪮¬ ª« áá¥.
+parser_e_only_one_default_property=03110_E_„®¯ãá⨬® ⮫쪮 ®¤­® ᢮©á⢮ ¯® 㬮«ç ­¨î
+% ‘¢®©á⢮ ®¯à¥¤¥«¥­® ª ª \var{Default}, ­® த¨â¥«ì᪨© ª« áá 㦥 ¨¬¥¥â ®¯à¥¤¥«¥­­®¥ â ª¨¬ ¦¥ ®¡à §®¬
+% ᢮©á⢮.
+parser_e_property_need_paras=03111_E_‘¢®©á⢮ ¯® 㬮«ç ­¨î ¤®«¦­® ¨¬¥âì ⨯ ¬ áᨢ 
+% ’®«ìª® ᢮©á⢠ ⨯  ¬ áᨢ ¬®£ãâ ¡ëâì ®¡ê¥­ë ª ª \var{default}.
+parser_e_constructor_cannot_be_not_virtual=03112_E_‚¨pây «ì­ë¥ ª®­áâpyªâ®pë ¤®¯ãá⨬ë ⮫쪮 ¢ ª« áá å
+% ‚¨àâã «ì­ë¥ ª®­áâàãªâ®àë ¤®¯ãá⨬ë ⮫쪮 ¢ ª« áá å, ¨å ­¥«ì§ï
+% ®¡êïâì ¢ ®¡ê¥ªâ å.
+parser_e_no_default_property_available=03113_E_Žâáãâáâ¢ã¥â ᢮©á⢮ ¯® 㬮«ç ­¨î
+% ®¯ë⪠ ¤®áâ㯠 ª ᢮©áâ¢ã ¯® 㬮«ç ­¨î ª« áá , ª®â®àë© ­¥ ¨¬¥¥â â ª®£® ᢮©á⢠.
+parser_e_cant_have_published=03114_E_Š« áá ­¥ ¬®¦¥â ¨¬¥âì PUBLISHED à §¤¥«, ¨á¯®«ì§y©â¥ ª«îç {$M+}
+% …᫨ âॡã¥âáï à §¤¥« \var{published} ¢ ®¡ê¥­¨¨ ª« áá , á«¥¤ã¥â
+% ¨á¯®«ì§®¢ âì ª«îç \var{\{\$M+\}}, ª®â®àë© ¢ª«î砥⠣¥­¥à æ¨î ¨­ä®à¬ æ¨¨ ® ⨯ å.
+parser_e_forward_declaration_must_be_resolved=03115_E_ ­­¥¥ ®¯p¥¤¥«¥­¨¥ ª« áá  "$1" ¤®«¦­® ¡ëâì à §à¥è¥­® §¤¥áì, çâ®¡ë ¨á¯®«ì§®¢ âì ¥£® ª ª ¯à¥¤®ª
+% —â®¡ë ª« áá ¬®¦­® ¡ë«® ¨á¯®«ì§®¢ âì ª ª ¯à¥¤®ª, ®­ ¤®«¦¥­ ¡ëâì á­ ç «  ®¯à¥¤¥«¥­.
+% Žè¨¡ª  ¢®§­¨ª ¥â ¢ á«¥¤ãî饩 á¨âã æ¨¨:
+% \begin{verbatim}
+% Type ParentClas = Class;
+% ChildClass = Class(ParentClass)
+% ...
+% end;
+% \end{verbatim}
+% ƒ¤¥ \var{ParentClass} ®¡ê¥­, ­® ­¥ ®¯à¥¤¥«¥­.
+parser_e_no_local_operator=03116_E_‹®ª «ì­ë¥ ®¯¥p â®pë ­¥ ¯®¤¤¥p¦¨¢ îâáï
+% Ž¯¥à â®à ­¥«ì§ï ¯¥à¥£à㧨âì «®ª «ì­®, â.¥. ¢­ãâਠ®¯à¥¤¥«¥­¨ï ¯à®æ¥¤ãàë ¨«¨
+% ä㭪樨.
+parser_e_proc_dir_not_allowed_in_interface=03117_E_„¨p¥ªâ¨¢  ¯à®æ¥¤ãàë "$1" ­¥¤®¯ãá⨬  ¢ ¨­â¥à䥩᭮© ç á⨠¬®¤ã«ï
+% „ ­­ ï ¤¨à¥ªâ¨¢  ­¥ ¤®¯ãá⨬  ¢ ᥪ樨 \var{interface} ¬®¤ã«ï.
+% …¥ ¬®¦­® ¨á¯®«ì§®¢ âì ⮫쪮 ¢ ᥪ樨 \var{implementation}.
+parser_e_proc_dir_not_allowed_in_implementation=03118_E_„¨p¥ªâ¨¢  ¯à®æ¥¤ãàë "$1" ­¥¤®¯ãá⨬  ¢ ॠ«¨§ æ¨®­­®© ç á⨠¬®¤ã«ï
+% „ ­­ ï ¤¨à¥ªâ¨¢  ­¥ ¤®¯ãá⨬  ¢ ᥪ樨 \var{implementation} ¬®¤ã«ï.
+% …¥ ¬®¦­® ¨á¯®«ì§®¢ âì ⮫쪮 ¢ ᥪ樨 \var{interface}.
+parser_e_proc_dir_not_allowed_in_procvar=03119_E_„¨p¥ªâ¨¢  ¯à®æ¥¤ãàë "$1" ­¥¤®¯ãá⨬  ¢ ®¡ê¥­¨¨ ¯à®æ¥¤ãà­®© ¯¥à¥¬¥­­®©
+% „ ­­ ï ¤¨à¥ªâ¨¢  ­¥ ¬®¦¥â ¡ëâì ç áâìî ®¡ê¥­¨ï ⨯  ¯à®æ¥¤ãàë ¨«¨ ä㭪樨.
+parser_e_function_already_declared_public_forward=03120_E_”ã­ªæ¨ï "$1" 㦥 ®¡ê¥­  ª ª PUBLIC ¨«¨ FORWARD
+% Žè¨¡ª  ¢®§­¨ª ¥â ¯à¨ ¤¢ãªà â­®¬ ®¡ê¥­¨¨ ä㭪樨 ª ª \var{forward}.
+% ˆ«¨ ¯à¨ ®¡ê¥­¨¨ ¥¥ ¢ ᥪ樨 \var{interface} ¨ ¯®á«¥¤ãî饬 ®¤­®ªà â­®¬ ®¡ê¥­¨¨ ª ª \var{forward}
+% ¢ ᥪ樨 \var{implmentation}.
+parser_e_not_external_and_export=03121_E_H¥«ì§ï ¨á¯®«ì§®¢ âì EXPORT ᮢ¬¥áâ­® á EXTERNAL
+% ⨠¤¢¥ ¤¨à¥ªâ¨¢ë ïîâáï ¢§ ¨¬®¨áª«îç î騬¨
+parser_w_not_supported_for_inline=03123_W_"$1" ­¥ ¯®¤¤¥p¦¨¢ ¥âáï ¢­yâp¨ INLINE ¯p®æ¥¤ypë/äy­ªæ¨¨
+% ‚áâà ¨¢ ¥¬ë¥ ¯à®æ¥¤ãàë ­¥ ¯®¤¤¥à¦¨¢ îâ íâ®â ⨯ ®¡ê¥­¨ï.
+parser_w_inlining_disabled=03124_W_‚áâà ¨¢ ­¨¥ (INLINE) ®âª«î祭®
+% ‚áâà ¨¢ ­¨¥ ¯à®æ¥¤ãà ®âª«î祭®.
+parser_i_writing_browser_log=03125_I_‡ ¯¨á뢠¥¬ «®£ ¡p y§¥p  $1
+% Š®£¤  ¢ª«îç¥­ë ¨­ä®à¬ æ¨®­­ë¥ á®®¡é¥­¨ï, ª®¬¯¨«ïâ®à á®®¡é ¥â
+% ® § ¯¨á¨ ¤ ­­ëå ¤«ï ¡à ã§¥à  (¢ª«îç ¥¬®£® ¤¨à¥ªâ¨¢®© \var{\{\$Y+ \}}).
+parser_h_maybe_deref_caret_missing=03126_H_‚®§¬®¦­®, ¯à®¯ã饭® p §ë¬¥­®¢ ­¨¥ yª § â¥«ï
+% Š®¬¯¨«ïâ®à áç¨â ¥â, ç⮠㪠§ â¥«ì ¬®¦¥â âॡ®¢ âì ࠧ묥­®¢ ­¨ï.
+parser_f_assembler_reader_not_supported=03127_F_‚ë¡p ­­ë© ⨯  áᥬ¡«¥p  ­¥ ¯®¤¤¥p¦¨¢ ¥âáï
+% ‚ë¡à ­­ë© ⨯  áᥬ¡«¥à  (á ¯®¬®éìî \var{\{\$ASMMODE xxx\}}) ­¥ ¯®¤¤¥à¦¨¢ ¥âáï.
+% ®¤¤¥à¦ª  ⮣® ¨«¨ ¨­®£®  áᥬ¡«¥à  ¬®¦¥â ¡ëâì ¯®¤ª«î祭  ¯à¨ ᡮથ ª®¬¯¨«ïâ®à .
+parser_e_proc_dir_conflict=03128_E_„¨p¥ªâ¨¢  ¯à®æ¥¤ãàë "$1" ­¥á®¢¬¥á⨬  á ¤py£¨¬¨ ¤¨p¥ªâ¨¢ ¬¨
+% “ª § ­­ ï ¤¨à¥ªâ¨¢  ­¥á®¢¬¥á⨬  á ¤à㣨¬¨ ¤¨à¥ªâ¨¢ ¬¨.
+%  ¯à¨¬¥à, \var{cdecl} ¨ \var{pascal} ¨áª«îç îâ ¤à㣠¤à㣠.
+parser_e_call_convention_dont_match_forward=03129_E_’¨¯ ¢ë§®¢  ¯p®æ¥¤ypë/äy­ªæ¨¨ ­¥ ᮮ⢥âáâ¢ã¥â yª § ­­®¬y à ­¥¥
+% Žè¨¡ª  ¯à®¨á室¨â ¯à¨ ®¡ê¥­¨¨ ¯à®æ¥¤ãàë ¨«¨ ä㭪樨, ­ ¯à¨¬¥à,
+% ª ª \var{cdecl;} ¨ ¯à®¯ã᪮¬ í⮩ ¤¨à¥ªâ¨¢ë ¯à¨ ®¯à¥¤¥«¥­¨¨, ¨«¨ ­ ®¡®à®â.
+% ’¨¯ ¢ë§®¢  ï¥âáï ç áâìî ®¡ê¥­¨ï ¯à®æ¥¤ãàë ¨ ¤®«¦¥­ ¯®¢â®àïâìáï
+% ¯à¨ ¥¥ ®¯à¥¤¥«¥­¨¨.
+parser_e_property_cant_have_a_default_value=03131_E_‘¢®©á⢮ ­¥ ¬®¦¥â ¨¬¥âì §­ ç¥­¨¥ ¯® y¬®«ç ­¨î
+% ‘¢®©á⢠ ⨯  ¬­®¦¥á⢮ ¨«¨ ¨­¤¥ªá¨à®¢ ­­ë¥ ᢮©á⢠ ­¥ ¬®£ãâ ¨¬¥âì §­ ç¥­¨¥ ¯® 㬮«ç ­¨î.
+parser_e_property_default_value_must_const=03132_E_‡­ ç¥­¨¥ ᢮©á⢠ ¯® y¬®«ç ­¨î ¤®«¦­® ¡ëâì ª®­á⠭⮩
+% ‡­ ç¥­¨¥ ᢮©á⢠, ®¡ê¥­­®¥ ª ª \var{default}, ¤®«¦­® ¡ëâì ¨§¢¥áâ­® ¢® ¢à¥¬ï ª®¬¯¨«ï樨.
+% Žè¨¡ª  ¯à®¨á室¨â, ¥á«¨ 㪠§ ­® §­ ç¥­¨¥, ¨§¢¥áâ­®¥ ⮫쪮 ¢® ¢à¥¬ï ¢ë¯®«­¥­¨ï, ­ ¯à¨¬¥à, ¨¬ï ¯¥à¥¬¥­­®©.
+parser_e_cant_publish_that=03133_E_‘¨¬¢®« ­¥ ¬®¦¥â ¡ëâì PUBLISHED, §¤¥áì ¤®¯ãá⨬ ⮫쪮 ª« áá
+% ’®«ìª® ¯¥à¥¬¥­­ë¥ ⨯  ª« áá  ¬®£ãâ ¡ëâì ¢ \var{published} ᥪ樨 ®¡ê¥­¨ï ª« áá ,
+% ¥á«¨ ®­¨ ­¥ ®¡ê¥­ë ª ª ᢮©á⢮.
+parser_e_cant_publish_that_property=03134_E_‘¢®©á⢮ í⮣® ⨯  ­¥ ¬®¦¥â ¡ëâì PUBLISHED
+% ‘¢®©á⢠ ¢ \var{published} ᥪ樨 ­¥ ¬®£ãâ ¡ëâì ⨯  ¬ áᨢ, ®­¨
+% ¤®«¦­ë ¡ëâì ¯¥à¥­¥á¥­ë ¢ ᥪæ¨î public. ‘¢®©á⢠ ¢ ᥪ樨 \var{published}
+% ¬®£ãâ ¡ëâì ¯¥à¥ç¨á«ï¥¬®£®, ¢¥é¥á⢥­­®£®, áâப®¢®£® ⨯  «¨¡® ¬­®¦¥á⢠¬¨.
+parser_e_empty_import_name=03136_E_’ॡã¥âáï ¨¬ï ¨¬¯®àâ 
+% „«ï ­¥ª®â®àëå ¯« âä®à¬ âॡã¥âáï ¨¬ï ¨¬¯®àâ¨à㥬®© ¯à®æ¥¤ãàë ¨«¨ 㪠§ â¥«ï cdecl
+parser_e_division_by_zero=03138_E_„¥«¥­¨¥ ­  ­®«ì
+% ந§®è«® ¤¥«¥­¨¥ ­  ­®«ì.
+parser_e_invalid_float_operation=03139_E_H¥¯p ¢¨«ì­ ï ®¯¥p æ¨ï á ¯« ¢ î饩 § ¯ï⮩
+% Ž¯¥à æ¨ï ­ ¤ ¤¢ã¬ï ¢¥é¥á⢥­­ë¬¨ ç¨á« ¬¨ ¢ë§¢ «  ¯¥à¥¯®«­¥­¨¥ ¨«¨ ¤¥«¥­¨¥ ­  ­®«ì.
+parser_e_array_lower_less_than_upper_bound=03140_E_‚¥på­ïï £p ­¨æ  ¤¨ ¯ §®­  ¬¥­ìè¥, 祬 ­¨¦­ïï
+% ‚¥àå­ïï £à ­¨æ  ¢ ®¡ê¥­¨¨ ¬ áᨢ  ¬¥­ìè¥ ­¨¦­¥© £à ­¨æë, çâ® ­¥¤®¯ãá⨬®.
+parser_w_string_too_long=03141_W_‘âப  "$1" ¤«¨­­¥¥, 祬 "$2"
+% „«¨­  áâப®¢®© ª®­áâ ­âë ¯à¥¢ë蠥⠤«¨­ã, 㪠§ ­­ãî ¢ ®¡ê¥­¨¨ ⨯  áâப¨.
+parser_e_string_larger_array=03142_E_„«¨­  áâப¨ ¯à¥¢ë蠥⠤«¨­ã ¬ áᨢ  ᨬ¢®«®¢
+% „«¨­  áâப®¢®© ª®­áâ ­âë ¯à¥¢ëè ¥â à §¬¥à, 㪠§ ­­ë© ¢ ®¡ê¥­¨¨ ¬ áᨢ 
+% array[x..y] of char.
+parser_e_ill_msg_expr=03143_E_H¥¢¥p­®¥ ¢ëp ¦¥­¨¥ ¯®á«¥ ¤¨p¥ªâ¨¢ë message
+% \fpc ¯®¤¤¥à¦¨¢ ¥â ⮫쪮 楫®ç¨á«¥­­ë¥ ¨ áâப®¢ë¥ ¢ëà ¦¥­¨ï ª ª ¨¤¥­â¨ä¨ª â®àë á®®¡é¥­¨©.
+parser_e_ill_msg_param=03144_E_Ž¡p ¡®â稪¨ á®®¡é¥­¨© ¯à¨­¨¬ îâ ⮫쪮 ®¤¨­ ¯ à ¬¥âà ¯® áá뫪¥
+% Œ¥â®¤, ®¡ê¥­­ë© á ¤¨à¥ªâ¨¢®© \var{message} ª ª ®¡à ¡®â稪 á®®¡é¥­¨©,
+% ¬®¦¥â ¯à¨­¨¬ âì ⮫쪮 ®¤¨­ ¯ à ¬¥âà, ª®â®àë© ¤®«¦¥­ ¯¥à¥¤ ¢ âìáï ¯® áá뫪¥.
+%  à ¬¥âà ¯¥à¥¤ ¥âáï ¯® áá뫪¥ ¯®á।á⢮¬ ¤¨à¥ªâ¨¢ë \var{var}.
+parser_e_duplicate_message_label=03145_E_®¢â®p­ ï ¬¥âª  á®®¡é¥­¨ï: "$1"
+% Ž¤­  ¨ â  ¦¥ ¬¥âª  á®®¡é¥­¨ï ¨á¯®«ì§®¢ ­  ¤¢ ¦¤ë ¢ ®¤­®¬ ®¡ê¥ªâ¥/ª« áá¥.
+parser_e_self_in_non_message_handler=03146_E_SELF ¬®¦¥â ¡ëâì ⮫쪮 ª ª ï¢­ë© ¯ à ¬¥âà ¢ ®¡à ¡®â稪 å á®®¡é¥­¨ï
+%  à ¬¥âà self ¬®¦¥â ¡ëâì ⮫쪮 ® ¯¥à¥¤ ­ ¢ ¬¥â®¤, ®¡ê¥­­ë© ª ª ®¡à ¡®â稪 á®®¡é¥­¨©.
+parser_e_threadvars_only_sg=03147_E_¥p¥¬¥­­ë¥ threadvar ¬®£yâ ¡ëâì ⮫쪮 áâ â¨ç¥áª¨¬¨ ¨«¨ £«®¡ «ì­ë¬¨
+% ¥à¥¬¥­­ë¥ threadvar ¤®«¦­ë ¡ëâì áâ â¨ç¥áª¨¬¨ ¨«¨ £«®¡ «ì­ë¬¨, ¨å ­¥«ì§ï ®¡êïâì «®ª «ì­®
+% ¢ ¯à®æ¥¤ãà¥. ‹®ª «ì­ë¥ ¯¥à¥¬¥­­ë¥ ¯à®æ¥¤ãàë ¢á¥£¤  ïîâáï «®ª «ì­ë¬¨ ¤«ï ¯®â®ª ,
+% ¯®â®¬ã çâ® ª ¦¤ë© ¯®â®ª ¨¬¥¥â ᮡá⢥­­ë© á⥪,   «®ª «ì­ë¥ ¯¥à¥¬¥­­ë¥ åà ­ïâáï ­  á⥪¥.
+parser_f_direct_assembler_not_allowed=03148_F_’¨¯  áᥬ¡«¥p  direct ­¥ ¯®¤¤¥p¦¨¢ ¥âáï ¯à¨ ¤¢®¨ç­®¬ ä®p¬ â¥ ¢ë室­®£® ä ©« 
+% ’¨¯  áᥬ¡«¥à  direct ­¥ ¬®¦¥â ¡ëâì ¨á¯®«ì§®¢ ­ ᮢ¬¥áâ­® á ¤¢®¨ç­ë¬ ä®à¬ â®¬ ¢ë室­ëå ä ©«®¢,
+% ¨á¯®«ì§ã©â¥ ¤à㣮© ¢ë室­®© ä®à¬ â ¨«¨ ¤à㣮©  áᥬ¡«¥à.
+parser_w_no_objpas_use_mode=03149_W_H¥ § £py¦ ©â¥ ¬®¤ã«ì OBJPAS ¢àãç­ãî, ¨á¯®«ì§y©â¥ {$mode objfpc} ¨«¨ {$mode delphi}
+% ®¯ë⪠ § £à㧨âì ¬®¤ã«ì ObjPas ¢àãç­ãî ¢ ᥪ樨 uses. â®â ¬®¤ã«ì ¯à¥¤­ §­ ç¥­ ¤«ï
+%  ¢â®¬ â¨ç¥áª®© § £à㧪¨ á ¯®¬®éìî ¤¨à¥ªâ¨¢ \var{\{\$mode objfpc\}} ¨«¨
+% \var{\{\$mode delphi\}}.
+parser_e_no_object_override=03150_E_OVERRIDE ­¥ ¬®¦¥â ¡ëâì ¨á¯®«ì§®¢ ­® ¢ ®¡ê¥ªâ å
+% „¨à¥ªâ¨¢  override ­¥ ¯®¤¤¥à¦¨¢ ¥âáï ¤«ï ®¡ê¥ªâ®¢, ¤«ï ¯¥à¥ªàëâ¨ï ¬¥â®¤®¢ த¨â¥«ì᪮£®
+% ®¡ê¥ªâ  á«¥¤ã¥â ¨á¯®«ì§®¢ âì \var{virtual}.
+parser_e_cant_use_inittable_here=03151_E_’¨¯ ¤ ­­ëå, âp¥¡ãî騩 ¨­¨æ¨ «¨§ æ¨¨/䨭 «¨§ æ¨¨, ­¥«ì§ï ¨á¯®«ì§®¢ âì ¢ ¢ à¨ ­â­ëå § ¯¨áïå
+% ¥ª®â®àë¥ â¨¯ë ¤ ­­ëå (­ ¯à¨¬¥à, \var{ansistring}) âॡãîâ ª®¤ ¨­¨æ¨ «¨§ æ¨¨/䨭 «¨§ æ¨¨,
+% ª®â®àë© ­¥ï¢­® £¥­¥à¨àã¥âáï ª®¬¨¯¨«ïâ®à®¬. ’ ª¨¥ â¨¯ë ¤ ­­ëå ­¥ ¬®£ãâ ¡ëâì ¨á¯®«ì§®¢ ­ë
+% ¢ ¢ à¨ ­â­®© ç á⨠§ ¯¨á¥©.
+parser_e_resourcestring_only_sg=03152_E_‘âப¨ à¥áãàᮢ ¬®£ãâ ¡ëâì ⮫쪮 áâ â¨ç¥áª¨¬¨ ¨«¨ £«®¡ «ì­ë¬¨
+% ‘âப¨ à¥áãàᮢ ­¥ ¬®£ãâ ¡ëâì ®¡ê¥­ë ­  «®ª «ì­®¬ ã஢­¥, ⮫쪮 ­  ã஢­¥ ¬®¤ã«ï.
+parser_e_exit_with_argument_not__possible=03153_E_à®æ¥¤ãà  Exit á  à£ã¬¥­â®¬ §¤¥áì ­¥¤®¯ãá⨬ 
+% ‚맮¢ exit á  à£ã¬¥­â®¬ ¤«ï ¢®§¢à é ¥¬®£® §­ ç¥­¨ï ­¥ ¬®¦¥â ¡ëâì ¨á¯®«ì§®¢ ­ ¢ í⮬ ¬¥áâ¥,
+% ¢ ç áâ­®áâ¨, ¢ ¡«®ª å \var{try..except} ¨«¨ \var{try..finally}.
+parser_e_stored_property_must_be_boolean=03154_E_’¨¯ ᨬ¢®«  stored ¤®«¦¥­ ¡ëâì boolean
+% …᫨ ¢ ®¡ê¥­¨¨ ᢮©á⢠ ¨á¯®«ì§ã¥âáï ᨬ¢®« stored, ®­ ¤®«¦¥­ ¨¬¥âì ⨯ boolean.
+parser_e_ill_property_storage_sym=03155_E_â®â ᨬ¢®« ­¥¤®¯ãá⨬ ¢ ª ç¥á⢥ stored
+% „ ­­ë© ⨯ ᨬ¢®«  ­¥ ¬®¦¥â ¡ëâì ¨á¯®«ì§®¢ ­ ¤«ï 㪠§ ­¨ï ¯à¨§­ ª  á®åà ­¥­¨ï ᢮©áâ¢.
+% „®¯ãá⨬® ¨á¯®«ì§®¢ âì ¬¥â®¤ë, ¢®§¢à é î騥 boolean, ¯®«ï ⨯  boolean,
+% «¨¡® ª®­áâ ­âë í⮣® ⨯ .
+parser_e_only_publishable_classes_can_be_published=03156_E_’®«ìª® ª« ááë, ᪮¬¯¨«¨p®¢ ­­ë¥ ¢ ०¨¬¥ $M+, ¬®£ãâ ¡ëâì published
+% ‚ ᥪ樨 published ®¡ê¥­¨ï ª« áá  ¬®£ã⠨ᯮ«ì§®¢ âìáï ¯®«ï ⮫쪮 ⨯  ª« áá ,
+% ª®â®àë© ª®¬¯¨«¨àã¥âáï ¢ ०¨¬¥ $M+ ¨«¨ ã­ á«¥¤®¢ ­­ë© ®â â ª®£® ª« áá . Ž¡ëç­®
+% ¨á¯®«ì§ãîâáï ­ á«¥¤­¨ª¨ TPersitent.
+parser_e_proc_directive_expected=03157_E_Ž¦¨¤ ¥âáï ¯p®æ¥¤yp­ ï ¤¨p¥ªâ¨¢ 
+% Žè¨¡ª  ¯à®¨á室¨â, ¥á«¨ ¢ ¤¨à¥ªâ¨¢¥ \var{\{\$Calling\}} ­¥ 㪠§ ­ ⨯ ¢ë§®¢ .
+% ’ ª¦¥ ¯à®¨á室¨â, ¥á«¨ ¯à¨ ®¡ê¥­¨¨ ¯à®æ¥¤ãà ¢ ¡«®ª¥ ª®­á⠭⠨ᯮ«ì§ã¥âáï ; ¯®á«¥
+% ®¡ê¥­¨ï ¯à®æ¥¤ãàë, ¯®á«¥ 祣® ¤®«¦­  á«¥¤®¢ âì ¯à®æ¥¤ãà­ ï ¤¨à¥ªâ¨¢ .
+% ਬ¥àë ¯à ¢¨«ì­ëå ®¡ê¥­¨©:
+% \begin{verbatim}
+% const
+% p : procedure;stdcall=nil;
+% p : procedure stdcall=nil;
+% \end{verbatim}
+parser_e_invalid_property_index_value=03158_E_‡­ ç¥­¨¥ ¨­¤¥ªá  ᢮©á⢠ ¤®«¦­® ¡ëâì ¯®à浪®¢®£® ⨯ 
+% ‡­ ç¥­¨¥, ¨á¯®«ì㧥¬®¥ ª ª ¨­¤¥ªá ᢮©á⢠, ¤®«¦­® ¡ëâì ¯®à浪®¢®£® ⨯ , ­ ¯à¨¬¥à,
+% æ¥«ë¬ ç¨á«®¬ ¨«¨ ¯¥à¥ç¨á«¥­¨¥¬.
+parser_e_procname_to_short_for_export=03159_E_ˆ¬ï ¯p®æ¥¤ypë ᫨誮¬ ª®p®âª®¥ ¤«ï íªá¯®pâ 
+% „«¨­  íªá¯®àâ­®£® ¨¬¥­¨ ¯à®æ¥¤ãàë/ä㭪樨 ¤®«¦­  á®áâ ¢«ïâì ¯® ªà ©­¥© ¬¥à¥ 2 ᨬ¢®« .
+% â® ®¡ãá«®¢«¥­® ®è¨¡ª®© ¢ ã⨫¨â¥ dlltool, ª®â®à ï ­¥ ¬®¦¥â ª®à४⭮ ¯à®ç¨â âì .def ä ©«
+% á ¤«¨­®© ¨¬¥­, à ¢­®© 1.
+parser_e_dlltool_unit_var_problem=03160_E_¥¢®§¬®¦­® ᮧ¤ âì § ¯¨áì DEFFILE ¤«ï £«®¡ «ì­ëå ¯¥à¥¬¥­­ëå ¬®¤ã«ï
+parser_e_dlltool_unit_var_problem2=03161_E_Š®¬¯¨«¨àã©â¥ ¡¥§ ª«îç  -WD
+% â®â ä ©« ­¥®¡å®¤¨¬® ª®¬¯¨«¨à®¢ âì ¡¥§ 㪠§ ­¨ï ª«îç  -WD ¢ ª®¬ ­¤­®© áâப¥.
+parser_f_need_objfpc_or_delphi_mode=03162_F_„«ï í⮣® ¬®¤ã«ï ­¥®¡å®¤¨¬ ०¨¬ ObjFpc (-S2) ¨«¨ Delphi (-Sd)
+% „«ï ª®¬¯¨«ï樨 ¤ ­­®£® ¬®¤ã«ï âॡã¥âáï {$mode objfpc} or {$mode delphi},
+% «¨¡® ¨á¯®«ì§®¢ ­¨¥  ­ «®£¨ç­ëå ª«î祩 ª®¬ ­¤­®© áâப¨ -S2 ¨«¨ -Sd.
+parser_e_no_export_with_index_for_target=03163_E_ªá¯®pâ ¯® ¨­¤¥ªáã ­¥¢®§¬®¦¥­ ¯®¤ $1
+% ªá¯®àâ ¯à®æ¥¤ãà/ä㭪権 á 㪠§ ­¨¥¬ ¨­¤¥ªá  ­¥ ¯®¤¤¥à¦¨¢ ¥âáï ¤«ï ¯« âä®à¬ë ­ §­ ç¥­¨ï.
+parser_e_no_export_of_variables_for_target=03164_E_ªá¯®pâ ¯¥p¥¬¥­­ëå ­¥ ¯®¤¤¥p¦¨¢ ¥âáï ¯®¤ $1
+% ªá¯®àâ ¯¥à¥¬¥­­ëå ­¥ ¯®¤¤¥à¦¨¢ ¥âáï ¤«ï ¯« âä®à¬ë ­ §­ ç¥­¨ï.
+parser_e_improper_guid_syntax=03165_E_¥¢¥à­ë© ᨭ⠪á¨á GUID
+% Žè¨¡ª  ¢ ᨭ⠪á¨á¥ GUID. Š®à४â­ë© GUID ¤®«¦¥­ ¡ëâì ¢ ä®à¬¥
+% \begin{verbatim}
+% {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}
+% \end{verbatim}
+% ƒ¤¥ ª ¦¤ë© \var{X} ¯à¥¤áâ ¢«ï¥â ᮡ®© è¥áâ­ ¤æ â¥à¨ç­ãî æ¨äàã.
+parser_w_interface_mapping_notfound=03168_W_¥ ­ ©¤¥­  ¯à®æ¥¤ãà  á ¨¬¥­¥¬ "$1", ¯®¤å®¤ïé ï ¤«ï ॠ«¨§ æ¨¨ $2.$3
+% Š®¬¯¨«ïâ®à ­¥ ¬®¦¥â ­ ©â¨ ¯à®æ¥¤ãàã, ¯®¤å®¤ïéãî ¤«ï ॠ«¨§ æ¨¨ 㪠§ ­­®£® ¬¥â®¤  ¨­â¥à䥩á .
+% à®æ¥¤ãà  á ᮢ¯ ¤ î騬 ¨¬¥­¥¬ ­ ©¤¥­ , ­® ­¥ ᮢ¯ ¤ ¥â ᯨ᮪ ¯ à ¬¥â஢.
+parser_e_interface_id_expected=03169_E_Ž¦¨¤ ¥âáï ¨¤¥­â¨ä¨ª â®à ¨­â¥à䥩á 
+% நá室¨â ¯à¨  ­ «¨§¥ ®¡ê¥­¨ï \var{class}, ª®â®à®¥ ᮤ¥à¦¨â
+% ®¯¨á ­¨¥ ᮮ⢥âáâ¢¨ï ¬¥â®¤®¢ \var{interface} ¯® ¨¬¥­¨, ­ ¯à¨¬¥à:
+% \begin{verbatim}
+% type
+% TMyObject = class(TObject, IDispatch)
+% function IUnknown.QueryInterface=MyQueryInterface;
+% ....
+% \end{verbatim}
+% ¨ ¨¬ï \var{interface} ¯¥à¥¤ â®çª®© ­¥ ¯¥à¥ç¨á«¥­® ¢ ᯨ᪥ ­ á«¥¤®¢ ­¨ï.
+parser_e_type_cant_be_used_in_array_index=03170_E_’¨¯ "$1" ­¥ ¬®¦¥â ¨á¯®«ì§®¢ âìáï ª ª ¨­¤¥ªá ¬ áᨢ 
+% ’ ª¨¥ ⨯ë, ª ª \var{qword} ¨«¨ \var{int64}, ­¥¤®¯ãáâ¨¬ë ¢ ª ç¥á⢥ ¨­¤¥ªá®¢ ¬ áᨢ 
+parser_e_no_con_des_in_interfaces=03171_E_Constructor ¨ destructor ­¥¤®¯ãáâ¨¬ë ¢ interface
+% ˆá¯®«ì§®¢ ­¨¥ ª®­áâàãªâ®à®¢ ¨ ¤¥áâàãªâ®à®¢ ¢ ¨­â¥à䥩á å ­¥ à §à¥è ¥âáï.
+% ‚ ¡®«ì設á⢥ á«ãç ¥¢ ¤«ï ᮧ¤ ­¨ï íª§¥¬¯«ï஢ ¨­â¥àä¥©á  ¬®¦¥â ¡ëâì ¨á¯®«ì§®¢ ­ ¬¥â®¤
+% \var{QueryInterface} ¨­â¥àä¥©á  \var{IUnknown}.
+parser_e_no_access_specifier_in_interfaces=03172_E_“ª § ­¨¥ ⨯  ¤®áâ㯠 ­¥¤®¯ãá⨬® ¢ interface
+% ’¨¯ ¤®áâ㯠 \var{public}, \var{private}, \var{protected} ¨
+% \var{pusblished} ­¥ ¬®¦¥â ¡ëâì 㪠§ ­ ¤«ï ¬¥â®¤®¢ ¨­â¥à䥩á .
+% ‚ᥠ¬¥â®¤ë ¨­âä¥àä¥©á  ï¢«ïîâáï ®¡é¥¤®áâ㯭묨 (public).
+parser_e_no_vars_in_interfaces=03173_E_Interface ­¥ ¬®¦¥â ᮤ¥à¦ âì ¯®«ï
+% Ž¡ê¥­¨¥ ¯®«¥© ¢ ¨­â¥à䥩ᥠ­¥ ¤®¯ã᪠¥âáï. ˆ­â¥àä¥©á ¬®¦¥â
+% ᮤ¥à¦ âì ⮫쪮 ¬¥â®¤ë.
+parser_e_no_local_proc_external=03174_E_‹®ª «ì­ ï ¯à®æ¥¤ãà  ­¥ ¬®¦¥â ¡ëâì EXTERNAL
+% Ž¡ê¥­¨¥ «®ª «ì­ëå ¯à®æ¥¤ãà ª ª external ­¥¢®§¬®¦­®. ‹®ª «ì­ë¥ ¯à®æ¥¤ãàë
+% ¯®«ãç îâ áªàëâë¥ ¯ à ¬¥âàë, çâ® ¤¥« ¥â ¢¥à®ïâ­®áâì ®è¨¡®ª ®ç¥­ì ¢ë᮪®©.
+parser_w_skipped_fields_before=03175_W_¥ª®â®àë¥ ¯®«ï ¯¥à¥¤ "$1" ­¥ ¡ë«¨ ¨­¨æ¨ «¨§¨à®¢ ­ë
+% ‚ ०¨¬¥ Delphi, ¨­¨æ¨ «¨§ æ¨ï ­¥ª®â®àëå ¯®«¥© ª®­áâ ­â ⨯  § ¯¨áì ¬®¦¥â ¡ëâì ¯à®¯ã饭 ,
+% ­® ª®¬¯¨«ïâ®à ¯à¥¤ã¯à¥¦¤ ¥â ® ­ «¨ç¨¨ â ª®© á¨âã æ¨¨.
+parser_e_skipped_fields_before=03176_E_¥ª®â®àë¥ ¯®«ï ¯¥à¥¤ "$1" ­¥ ¡ë«¨ ¨­¨æ¨ «¨§¨à®¢ ­ë
+% ‚ ०¨¬ å, ®â«¨ç­ëå ®â Delphi, ­¥ ¤®¯ã᪠¥âáï ®áâ ¢«ïâì ­¥¨­¨æ¨ «¨§¨à®¢ ­­ë¥ ¯®«ï
+% ¢ á¥à¥¤¨­¥ ª®­áâ ­âë ⨯  § ¯¨áì.
+parser_w_skipped_fields_after=03177_W_¥ª®â®àë¥ ¯®«ï ¯®á«¥ "$1" ­¥ ¡ë«¨ ¨­¨æ¨ «¨§¨à®¢ ­ë
+% ®«ï ¢ ª®­æ¥ ª®­áâ ­âë ⨯  § ¯¨áì ¬®£ãâ ¡ëâì ®áâ ¢«¥­ë ¡¥§ ¨­¨æ¨ «¨§ æ¨¨
+% (ª®¬¯¨«ïâ®à  ¢â®¬ â¨ç¥áª¨ ¨­¨æ¨ «¨§¨àã¥â ¨å ­ã«¥¢ë¬¨ §­ ç¥­¨ï¬¨). â®
+% ¬®¦¥â ïâìáï ¯à¨ç¨­®© ­¥ª®â®àëå ¯à®¡«¥¬.
+parser_e_varargs_need_cdecl_and_external=03178_E_„¨à¥ªâ¨¢  VarArgs (¨«¨ '...' ¢ MacPas) ¡¥§ CDecl/CPPDecl/MWPascal ¨ External
+% „¨à¥ªâ¨¢  varargs (¨«¨ ¯ à ¬¥âà ``...'' ¢ ०¨¬¥ MacPas) ¬®¦¥â ¡ëâì ¨á¯®«ì§®¢ ­  ⮫쪮 á
+% ¯à®æ¥¤ãà ¬¨/äã­ªæ¨ï¬¨, ®¡ê¥­­ë¬¨ á ¤¨à¥ªâ¨¢ ¬¨ \var{external} ¨ ®¤­®© ¨§ \var{cdecl},
+% \var{cppdecl} ¨«¨ \var{mwpascal}. â  ä㭪樮­ «ì­®áâì ¯®¤¤¥à¦¨¢ ¥âáï ⮫쪮 ¤«ï
+% ᮢ¬¥á⨬®á⨠á äã­ªæ¨ï¬¨ ï§ëª  C ⨯  printf.
+parser_e_self_call_by_value=03179_E_Self ¤®«¦¥­ ¡ëâì ¯ à ¬¥â஬ á ¯¥à¥¤ ç¥© ¯® §­ ç¥­¨î
+%  à ¬¥âà Self ­¥ ¬®¦¥â ¡ëâì ¯¥à¥¤ ­ ¯® áá뫪¥ (á var ¨«¨ const), ¥£® ­ã¦­® ¯¥à¥¤ ¢ âì ¯®
+% §­ ç¥­¨î
+parser_e_interface_has_no_guid=03180_E_ˆ­â¥à䥩á "$1" ­¥ ¨¬¥¥â ¨¤¥­â¨ä¨ª â®à 
+% ਠ¯à¨á¢®¥­¨¨ ¨­â¥àä¥©á  ª®­áâ ­â¥, ¨­â¥àä¥©á ¤®«¦¥­ ¨¬¥âì §­ ç¥­¨¥ GUID.
+parser_e_illegal_field_or_method=03181_E_¥¨§¢¥áâ­ë© ¨¤¥­â¨ä¨ª â®à ¯®«ï ¨«¨ ¬¥â®¤  "$1"
+% ‘¢®©á⢠ ¤®«¦­ë ááë« âìáï ­  ¯®«ï ¨ ¬¥â®¤ë ⮣® ¦¥ ª« áá , ¢ ª®â®à®¬ ®¡ê¥­ë.
+parser_w_proc_overriding_calling=03182_W_’¨¯ ¢ë§®¢  "$2" ¯¥à¥ªà뢠¥â "$1"
+% ‚ ®¡ê¥­¨¨ ¯à®æ¥¤ãàë ¯à¨áãâáâ¢ãîâ ¤¢¥ ¤¨à¥ªâ¨¢ë, ®¯à¥¤¥«ïî騥 ⨯ ¢ë§®¢ .
+% 㤥⠨ᯮ«ì§®¢ ­  ¯®á«¥¤­ïï ¤¨à¥ªâ¨¢ .
+parser_e_no_procvarobj_const=03183_E_Š®­áâ ­â  â¨¯  "procedure of object" ¬®¦¥â ¡ëâì ¨­¨æ¨ «¨§¨à®¢ ­  ⮫쪮 §­ ç¥­¨¥¬ NIL
+% €¤à¥á ¬¥â®¤  ­¥ ¬®¦¥â ¡ëâì ¨á¯®«ì§®¢ ­ ¤«ï ¨­¨æ¨ «¨§ æ¨¨ ⨯¨§¨à®¢ ­­®© ª®­áâ ­âë ⨯ 
+% 'procedure of object', ¯®â®¬ã çâ® â ª ï ª®­áâ ­â  á®á⮨⠨§ ¤¢ãå  ¤à¥á®¢:
+%  ¤à¥á ¬¥â®¤  (¨§¢¥áâ­ë© ¢® ¢à¥¬ï ª®¬¯¨«ï樨) ¨  ¤à¥á íª§¥¬¯«ïà  ®¡ê¥ªâ  ¨«¨
+% ª« áá  (­¥ ¬®¦¥â ¡ëâì ®¯à¥¤¥«¥­ ¯à¨ ª®¬¯¨«ï樨).
+parser_e_default_value_only_one_para=03184_E_‡­ ç¥­¨¥ ¯® 㬮«ç ­¨î ¬®¦¥â ¡ëâì ¯à¨á¢®¥­® ⮫쪮 ®¤­®¬ã ¯ à ¬¥âàã
+% ¥¢®§¬®¦­® ¯à¨á¢®¨âì §­ ç¥­¨¥ ¯® 㬮«ç ­¨î áࠧ㠭¥áª®«ìª¨¬ ¯ à ¬¥âà ¬.
+% ‘«¥¤ãî騩 ª®¤ ­¥¢¥à¥­:
+% \begin{verbatim}
+% Procedure MyProcedure (A,B : Integer = 0);
+% \end{verbatim}
+% ‚¬¥áâ® íâ® á«¥¤ã¥â ®¡êâì ¯à®æ¥¤ãàã ª ª:
+% \begin{verbatim}
+% Procedure MyProcedure (A : Integer = 0; B : Integer = 0);
+% \end{verbatim}
+parser_e_default_value_expected_for_para=03185_E_„«ï "$1" âॡã¥âáï §­ ç¥­¨¥ ¯® 㬮«ç ­¨î
+% “ª § ­­ë© ¯ à ¬¥âà âॡã¥â §­ ç¥­¨¥ ¯® 㬮«ç ­¨î.
+parser_w_unsupported_feature=03186_W_ˆá¯®«ì§®¢ ­¨¥ ¯®ª  ­¥¯®¤¤¥à¦¨¢ ¥¬®© ®á®¡¥­­®á⨠ª®¬¯¨«ïâ®à !
+% ®¯ë⪠ § áâ ¢¨âì ª®¬¯¨«ïâ®à ᤥ« âì ­¥çâ®, 祣® ®­ ¯®ª  ¥é¥ ­¥ 㬥¥â.
+parser_h_c_arrays_are_references=03187_H_Œ áᨢë C ¯¥à¥¤ îâáï ¯® áá뫪¥
+% ¥à¥¤ ç  ¬ áᨢ®¢ ¢ ä㭪樨 ­  ï§ëª¥ C ¢á¥£¤ 
+% ®áãé¥á⢫ï¥âáï ¯®á।á⢮¬ 㪠§ â¥«ï (â.¥. ¯® áá뫪¥).
+parser_e_C_array_of_const_must_be_last=03188_E_Œ áᨢ ª®­áâ ­â ¢ C ¤®«¦¥­ ¡ëâì ¯®á«¥¤­¨¬ ¯ à ¬¥â஬
+% ¥«ì§ï ¤®¡ ¢«ïâì ¤à㣨¥ ¯ à ¬¥âàë ¯®á«¥ ¯ à ¬¥âà  â¨¯  \var{array of const},
+% ¯¥à¥¤ ¢ ¥¬®£® ¢ äã­ªæ¨î, ®¡ê¥­­ãî ª ª \var{cdecl}, ¯®â®¬ã çâ® ¤«ï ­¥£®
+% § à ­¥¥ ­¥ ¨§¢¥á⥭ à §¬¥à ¤ ­­ëå, ¯®¬¥é ¥¬ëå ­  á⥪.
+parser_h_type_redef=03189_H_®¢â®à­®¥ ®¡ê¥­¨¥ ⨯  "$1"
+% ‘®®¡é ¥â ® ⮬, çâ® ¤«ï à ­¥¥ ®¯à¥¤¥«¥­­®£® ⨯  ¢áâà¥â¨«®áì
+% ¯®¢â®à­®¥ ®â«¨ç î饥áï ®¡ê¥­¨¥. â® ¬®¦¥â ¡ëâì (  ¬®¦¥â ¨ ­¥ ¡ëâì)
+% ¯à¨ç¨­®© ®è¨¡®ª.
+parser_w_cdecl_has_no_high=03190_W_”㭪樨 cdecl ­¥ ¨¬¥îâ ¯ à ¬¥âà  high
+% ‚ ä㭪樨, ®¡ê¥­­ë¥ ª ª cdecl, ­¥ ¯¥à¥¤ ¥âáï áªàëâë© ¯ à ¬¥âà high.
+parser_w_cdecl_no_openstring=03191_W_”㭪樨 cdecl ­¥ ¯®¤¤¥à¦¨¢ îâ ®âªàëâë¥ áâப¨
+% ‘âப¨ ⨯  openstring ­¥ ¯®¤¤¥à¦¨¢ îâáï ¢ cdecl äã­ªæ¨ïå.
+parser_e_initialized_not_for_threadvar=03192_E_ˆ­¨æ¨ «¨§ æ¨ï ¯¥à¥¬¥­­®© ⨯  threadvar ­¥¢®§¬®¦­ 
+% ¥à¥¬¥­­ë¥, ®¡ê¥­­ë¥ ª ª threadvar, ­¥ ¬®£ãâ ¨¬¥âì ­ ç «ì­®£® §­ ç¥­¨ï.
+% Ž­¨ ¢á¥£¤  ¯®«ãç îâ ­ã«¥¢®¥ §­ ç¥­¨¥ ¯à¨ áâ à⥠­®¢®£® ¯®â®ª .
+parser_e_msg_only_for_classes=03193_E_„¨à¥ªâ¨¢  message à §à¥è¥­  ⮫쪮 ¤«ï ª« áᮢ
+% „¨à¥ªâ¨¢  message ¯®¤¤¥à¦¨¢ ¥âáï ⮫쪮 ¤«ï ⨯®¢ Class.
+parser_e_procedure_or_function_expected=03194_E_Ž¦¨¤ ¥âáï "procedure" ¨«¨ "function"
+% Š« áá-¬¥â®¤ ¬¨ ¬®£ãâ ¡ëâì ⮫쪮 ¯à®æ¥¤ãàë ¨ ä㭪樨.
+parser_e_illegal_calling_convention=03195_W_’¨¯ ¢ë§®¢  ¨£­®à¨à®¢ ­: "$1"
+% ¥ª®â®àë¥ â¨¯ë ¢ë§®¢®¢ ¯®¤¤¥à¦¨¢ îâáï ⮫쪮 ­  ®¯à¥¤¥«¥­­ëå ¯à®æ¥áá®à å. ’ ª, ¤«ï ¡®«ì設á⢠
+% ­¥-i386 ¯®¤¤¥à¦¨¢ îâáï ⮫쪮 â¨¯ë ¢ë§®¢  áâ ­¤ àâ­®£® ABI.
+parser_e_no_object_reintroduce=03196_E_REINTRODUCE ­¥«ì§ï ¨á¯®«ì§®¢ âì ¤«ï ®¡ê¥ªâ®¢
+% „¨à¥ªâ¨¢  \var{reintroduce} ­¥ ¯®¤¤¥à¦¨¢ ¥âáï ¤«ï ®¡ê¥ªâ®¢.
+parser_e_paraloc_only_one_para=03197_E_ á¯®«®¦¥­¨¥  à£ã¬¥­â®¢ ­¥ ¬®¦¥â ᮢ¯ ¤ âì
+% …᫨ à á¯®«®¦¥­¨¥  à£ã¬¥­â®¢ 㪠§ë¢ îâáï ®, ª ª ⮣® âॡãîâ ­¥ª®â®àë¥
+% â¨¯ë ¢ë§®¢®¢ syscall, à á¯®«®¦¥­¨¥ ª ¦¤®£® ¨§  à£ã¬¥­â®¢ ¤®«¦­® ¡ëâì ã­¨ª «ì­ë¬,
+% ª®­áâàãªæ¨¨ ¢¨¤  \var{procedure p(i,j : longint 'r1');} ­¥ ¤®¯ã᪠îâáï.
+parser_e_paraloc_all_paras=03198_E_㦭® 㪠§ âì à á¯®«®¦¥­¨¥ ¤«ï ¢á¥å  à£ã¬¥­â®¢
+% …᫨ à á¯®«®¦¥­¨¥ 㪠§ ­® ¤«ï ®¤­®£®  à£ã¬¥­â®¢, ¥£® ­ã¦­® 㪠§ âì ¨ ¤«ï ¢á¥å
+% ®áâ «ì­ëå.
+parser_e_illegal_explicit_paraloc=03199_E_¥¨§¢¥áâ­®¥ à á¯®«®¦¥­¨¥  à£ã¬¥­â 
+% “ª § ­­®¥ à á¯®«®¦¥­¨¥ ­¥ ï¥âáï ¤®¯ãáâ¨¬ë¬ á â®çª¨ §à¥­¨ï ª®¬¯¨«ïâ®à .
+parser_e_32bitint_or_pointer_variable_expected=03200_E_Ž¦¨¤ ¥âáï 32-¡¨â­®¥ 楫®¥ «¨¡® 㪠§ â¥«ì
+% libbase ¤«ï MorphOS/AmigaOS ¬®¦­® § ¤ ¢ âì ⮫쪮 ª ª \var{longint}, \var{dword}, «¨¡® 㪠§ â¥«ì
+% «î¡®£® ⨯ .
+parser_e_goto_outside_proc=03201_E_¥ ¤®¯ã᪠¥âáï goto ¬¥¦¤ã à §«¨ç­ë¬¨ ¯à®æ¥¤ãà ¬¨
+% ¥ ¤®¯ã᪠¥âáï ¨á¯®«ì§®¢ ­¨¥ \var{goto} ¤«ï ¯¥à¥å®¤  ­  ¬¥âªã, ®¯à¥¤¥«¥­­ãî ¢­¥
+% ⥪ã饩 ¯à®æ¥¤ãàë. ‘«¥¤ãî騩 ¯à¨¬¥à ¤¥¬®­áâà¨àã¥â ¯à®¡«¥¬ã:
+% \begin{verbatim}
+% ...
+% procedure p1;
+% label
+% l1;
+%
+% procedure p2;
+% begin
+% goto l1; // â  ¨­áâàãªæ¨ï goto ­¥ à §à¥è ¥âáï
+% end;
+%
+% begin
+% p2
+% l1:
+% end;
+% ...
+%
+% \end{verbatim}
+parser_f_too_complex_proc=03202_F_‘«¨èª®¬ á«®¦­ ï ¯à®æ¥¤ãà , ­¥ 墠⠥â ॣ¨áâ஢
+% ’¥«® ¯à®æ¥¤ãàë ï¥âáï ᫨誮¬ á«®¦­ë¬ ¤«ï ª®¬¯¨«ï樨. ‘«¥¤ã¥â à §¡¨âì ¥¥
+% ­  ­¥áª®«ìª® ¡®«¥¥ ¯à®áâëå ¯à®æ¥¤ãà.
+parser_e_illegal_expression=03203_E_¥¤®¯ãá⨬®¥ ¢ëà ¦¥­¨¥
+% Œ®¦¥â ¢®§­¨ª âì ¯® à §­ë¬ ¯à¨ç¨­ ¬.  ¨¡®«¥¥ ç áâ® - ¯à¨ ¢ëç¨á«¥­¨¨
+% ª®­áâ ­â­ëå ¢ëà ¦¥­¨©.
+parser_e_invalid_integer=03204_E_¥¢¥à­®¥ 楫®ç¨á«¥­­®¥ ¢ëà ¦¥­¨¥
+% ‚ëà ¦¥­¨¥ ­¥ ï¥âáï æ¥«ë¬ ç¨á«®¬, ¢ â® ¢à¥¬ï ª ª ª®¬¯¨«ïâ®à ®¦¨¤ ¥â
+% ¨¬¥­­® 楫®ç¨á«¥­­ë© १ã«ìâ â.
+parser_e_invalid_qualifier=03205_E_¥¢¥à­ë© ª¢ «¨ä¨ª â®à
+% நá室¨â ¯® ®¤­®© ¨§ á«¥¤ãîé¨å ¯à¨ç¨­:
+% \begin{itemize}
+% \item ®¯ë⪠ ¤®áâ㯠 ª ¯®«î ¯¥à¥¬¥­­®©, ª®â®à ï ­¥ ï¥âáï § ¯¨áìî.
+% \item “ª § ­¨¥ ¨­¤¥ªá  ¤«ï ¯¥à¥¬¥­­®©, ­¥ ïî饩áï ¬ áᨢ®¬.
+% \item  §ë¬¥­®¢ ­¨¥ ¯¥à¥¬¥­­®©, ­¥ ïî饩áï 㪠§ â¥«¥¬.
+% \end{itemize}
+parser_e_upper_lower_than_lower=03206_E_‚¥àå­¨© ¯à¥¤¥« ¤¨ ¯ §®­  < ­¨¦­¥£®
+% ਠ®¡ê¥­¨¨ ¯®¤¤¨ ¯ §®­ , ­¨¦­¨© ¯à¥¤¥« ®ª § «áï ¡®«ìè¥
+% ¢¥àå­¥£®.
+parser_e_macpas_exit_wrong_param=03207_E_ à ¬¥âà Exit ¤®«¦¥­ ¡ëâì ¨¬¥­¥¬ ⥪ã饩 ¯à®æ¥¤ãàë
+% ¥-«®ª «ì­ë© exit ­¥ ¤®¯ã᪠¥âáï. â  ®è¨¡ª  ¢®§­¨ª ¥â ⮫쪮 ¢ ०¨¬¥ MacPas.
+parser_e_illegal_assignment_to_count_var=03208_E_¥¢¥à­®¥ ¯à¨á¢®¥­¨¥ ¯¥à¥¬¥­­®© for-横«  "$1"
+% ’¨¯ ¯¥à¥¬¥­­®© ¤«ï 横«  \var{for} ¤®«¦¥­ ¡ëâì ¯®à浪®¢ë¬.
+% ‚¥é¥á⢥­­ë¥ ¨ áâப®¢ë¥ â¨¯ë ­¥ ¤®¯ã᪠îâáï. Šà®¬¥ ⮣®, ­¥ ¤®¯ã᪠¥âáï ¯à¨á¢®¥­¨¥
+% ã¯à ¢«ïî饩 ¯¥à¥¬¥­­®© ¢­ãâਠ横«  (ªà®¬¥ ०¨¬®¢ Delphi ¨ TP). …᫨ âॡã¥âáï
+% ¯à¨á¢®¥­¨¥, ¢¬¥á⮠横«  for á«¥¤ã¥â ¨á¯®«ì§®¢ âì ¯à¥¤­ §­ ç¥­­ë¥ ¤«ï í⮣®
+% 横«ë while ¨«¨ repeat.
+parser_e_no_local_var_external=03209_E_‹®ª «ì­ ï ¯¥à¥¬¥­­ ï ­¥ ¬®¦¥â ¡ëâì EXTERNAL
+% Ž¡ê¥­¨¥ «®ª «ì­ëå ¯¥à¥¬¥­­ëå ª ª ¢­¥è­¨å ­¥ ¤®¯ã᪠¥âáï. ‚­¥è­¨¬¨ ¬®£ãâ ¡ëâì
+% ⮫쪮 £«®¡ «ì­ë¥ ¯¥à¥¬¥­­ë¥.
+parser_e_proc_already_external=03210_E_à®æ¥¤ãà  ã¦¥ ®¡ê¥­  ª ª EXTERNAL
+% à®æ¥¤ãà  ã¦¥ ®¡ê¥­  á ¤¨à¥ªâ¨¢®© EXTERNAL ¢ ¨­â¥à䥩ᥠ¬®¤ã«ï ¨«¨
+% ¢ à ­­¥¬ ®¡ê¥­¨¨.
+parser_w_implicit_uses_of_variants_unit=03211_W_¥ï¢­®¥ ¨á¯®«ì§®¢ ­¨¥ ¬®¤ã«ï Variants
+% ‚ ¬®¤ã«¥ ¨á¯®«ì§ã¥âáï ⨯ Variant, ­® ¬®¤ã«ì Variants ­¥ ¯®¤ª«î祭 ­¨ ª ®¤­®¬ã ¨§ ¨á¯®«ì§ã¥¬ëå
+% ¬®¤ã«¥©. Š®¬¯¨«ïâ®à ­¥ï¢­® ¤®¡ ¢«ï¥â Variants ¢ ᯨ᮪ ¨á¯®«ì§ã¥¬ëå ¬®¤ã«¥©.
+% —â®¡ë ¨§¡ ¢¨âìáï ®â ¯à¥¤ã¯à¥¦¤¥­¨ï, ¤®¡ ¢ì⥠Variants ¢ ᯨ᮪ uses.
+parser_e_no_static_method_in_interfaces=03212_E_Œ¥â®¤ë class and static ­¥ ¤®¯ã᪠îâáï ¢ INTERFACE
+% ‘¯¥æ¨ä¨ª â®à \var{class} ¨ ¤¨à¥ªâ¨¢  \var{static} ­¥ ¯à¨¬¥­¨¬ë ¢ ¨­â¥à䥩á å,
+% â.ª. ¢á¥ ¬¥â®¤ë ¨­â¥àä¥©á  ¤®«¦­ë ¡ëâì ¯ã¡«¨ç­ë¬¨.
+parser_e_arithmetic_operation_overflow=03213_E_¥à¥¯®«­¥­¨¥ ¢  à¨ä¬¥â¨ç¥áª®© ®¯¥à æ¨¨
+% Ž¯¥à æ¨ï ­ ¤ 楫묨 ç¨á« ¬¨ ¯à¨¢¥«  ª ¯¥à¥¯®«­¥­¨î
+parser_e_protected_or_private_expected=03214_E_Ž¦¨¤ ¥âáï "protected" ¨«¨ "private"
+% \var{strict} ¬®¦¥â ¨á¯®«ì§®¢ âìáï ⮫쪮 ¢ á®ç¥â ­¨¨ á \var{protected} ¨«¨ \var{private}.
+parser_e_illegal_slice=03215_E_SLICE ­¥«ì§ï ¨á¯®«ì§®¢ âì ¢­¥ ᯨ᪠ ¯ à ¬¥â஢
+% \var{slice} ¬®¦­® ¨á¯®«ì§®¢ âì ⮫쪮 ¤«ï  à£ã¬¥­â®¢, ¯à¨­¨¬ îé¨å ⨯ ®âªàë⮣® ¬ áᨢ 
+parser_e_dispinterface_cant_have_parent=03216_E_DISPINTERFACE ­¥ ¬®¦¥â ¨¬¥âì த¨â¥«ï
+% DISPINTERFACE ï¥âáï ®á®¡ë¬ â¨¯®¬ ¨­â¥àä¥©á  ¨ ­¥ ¬®¦¥â ¨¬¥âì த¨â¥«ì᪨© ª« áá
+parser_e_dispinterface_needs_a_guid=03217_E_„«ï DISPINTERFACE âॡã¥âáï GUID
+% DISPINTERFACE ¢á¥£¤  âॡã¥â ¨¤¥­â¨ä¨ª æ¨¨ á ¯®¬®éìî GUID
+parser_w_overridden_methods_not_same_ret=03218_W_¥à¥ªàëâë¥ ¬¥â®¤ë ¤®«¦­ë ¨¬¥âì ®¤¨­ ª®¢ë© ⨯ १ã«ìâ â . â®â ª®¤ ¨á¯®«ì§ã¥â ®è¨¡ªã ¢ ¯ àá¥à¥ Delphi ¨ ¡ã¤¥â à ¡®â âì ­¥¯à¥¤áª §ã¥¬® ("$2" ¯¥à¥ªàëâ® "$1", ¨¬¥î騬 ¤à㣮© ⨯ १ã«ìâ â )
+% ¥à¥ªàëâë¥ ¬¥â®¤ë ¤®«¦­ë ¢®§¢à é âì ®¤¨­ ¨ â®â ¦¥ ⨯ १ã«ìâ â .
+% ¥ª®â®àë¥ ¢¥àᨨ Delphi ¯®§¢®«ïîâ ¨§¬¥­ïâì ⨯ë १ã«ìâ â  ¨ ¤ ¦¥ ¯à¥¢à é âì
+% ¯à®æ¥¤ãàë ¢ ä㭪樨, ­® à ¡®â®á¯®á®¡­®áâì ¯®«ã祭­®£® ª®¤  § ¢¨á¨â ®â
+% ¨á¯®«ì§®¢ ­­ëå ⨯®¢ ¨ ᯮᮡ  ¢ë§®¢  ¬¥â®¤®¢.
+parser_e_dispid_must_be_ord_const=03219_E_Dispatch ID ¤®«¦­ë ¡ëâì ¯®à浪®¢ë¬¨ ª®­áâ ­â ¬¨
+% ‡  ª«îç¥¢ë¬ á«®¢®¬ \var{dispid} ¤®«¦­  á«¥¤®¢ âì ¯®à浪®¢ ï ª®­áâ ­â  (¨­¤¥ªá).
+parser_e_array_range_out_of_bounds=03220_E_„¨ ¯ §®­ ¬ áᨢ  ᫨誮¬ ¢¥«¨ª
+% ¥§ ¢¨á¨¬® ®â ª®«¨ç¥á⢠ ¯ ¬ïâ¨, § ­¨¬ ¥¬®© í«¥¬¥­â ¬¨, ¬ áá¨¢ë ­¥ ¬®£ãâ ᮤ¥à¦ âì
+% ¡®«ìè¥ ç¥¬ high(ptrint) í«¥¬¥­â®¢. Šà®¬¥ ⮣®, ⨯ ¤¨ ¯ §®­  ¤®«¦¥­ ¡ëâì ¯®¤¤¨ ¯ §®­®¬
+% ⨯  ptrint.
+parser_e_packed_element_no_var_addr=03221_E_¥«ì§ï ¢§ïâì  ¤à¥á í«¥¬¥­â®¢/¯®«¥© ¯®¡¨â­®-㯠ª®¢ ­­ëå ¬ áᨢ®¢/§ ¯¨á¥©
+% ®«ï § ¯¨á¨ ¨«¨ í«¥¬¥­âë ¬ áᨢ , ®¡ê¥­­ëå ª ª \var{packed} ¢ ०¨¬¥ Mac Pascal («¨¡® ª ª
+% \var{packed} ¢ «î¡®¬ ०¨¬¥ ¯à¨ ãá«®¢¨¨ \var{\{\$bitpacking on\}}), ¡ã¤ãâ 㯠ª®¢ ­ë ­  ã஢­¥
+% ¡¨â. â® ®§­ ç ¥â ­¥¢®§¬®¦­®áâì ¯®«ã祭¨ï  ¤à¥á®¢ ®â¤¥«ì­ëå í«¥¬¥­â®¢ ¬ áᨢ  ¨«¨ ¯®«¥© § ¯¨á¨.
+% ˆáª«î祭¨¥¬ ¨§ í⮣® ¯à ¢¨«  ïîâáï 㯠ª®¢ ­­ë¥ ¬ áᨢë, à §¬¥à í«¥¬¥­â®¢ ª®â®àëå ªà â¥­ 8 ¡¨â ¬.
+parser_e_packed_dynamic_open_array=03222_E_„¨­ ¬¨ç¥áª¨¥ ¬ áá¨¢ë ­¥ ¬®£ãâ ¡ëâì 㯠ª®¢ ­­ë¬¨
+% “¯ ª®¢ ­­ë¬¨ ¬®£ãâ ¡ëâì ⮫쪮 ®¡ëç­ë¥ (¨, ¢®§¬®¦­®, ¢ ¡ã¤ã饬 â ª¦¥ ®âªàëâë¥) ¬ áᨢë.
+parser_e_packed_element_no_loop=03223_E_«¥¬¥­âë/¯®«ï ¯®¡¨â­®-㯠ª®¢ ­­ëå ¬ áᨢ®¢/§ ¯¨á¥© ­¥«ì§ï ¨á¯®«ì§®¢ âì ª ª ¯¥à¥¬¥­­ë¥ 横«  for
+% ®«ï § ¯¨á¨ ¨«¨ í«¥¬¥­âë ¬ áᨢ , ®¡ê¥­­ëå ª ª \var{packed} ¢ ०¨¬¥ Mac Pascal («¨¡® ª ª
+% \var{packed} ¢ «î¡®¬ ०¨¬¥ ¯à¨ ãá«®¢¨¨ \var{\{\$bitpacking on\}}), ¡ã¤ãâ 㯠ª®¢ ­ë ­  ã஢­¥
+% ¡¨â. ® ¯à¨ç¨­ ¬ ¡ëáâத¥©áâ¢¨ï ¨å ­¥«ì§ï ¨á¯®«ì§®¢ âì ª ª ¯¥à¥¬¥­­ë¥ ¤«ï for-横« .
+parser_e_type_and_var_only_in_generics=03224_E_VAR ¨ TYPE ¤®¯ãá⨬ë ⮫쪮 ¢ ®¡®¡é¥­¨ïå (generic)
+% ˆá¯®«ì§®¢ ­¨¥ VAR ¨ TYPE ¤«ï ®¡ê¥­¨ï ­®¢ëå ⨯®¢ ¢­ãâਠ®¡ê¥ªâ  à §à¥è ¥âáï ⮫쪮 ¤«ï
+% ®¡®¡é¥­¨©.
+parser_e_cant_create_generics_of_this_type=03225_E_â®â ⨯ ­¥ ¬®¦¥â ¡ëâì ®¡®¡é¥­¨¥¬
+% Ž¡®¡é¥­¨ï ¤®¯ã᪠îâáï ⮫쪮 ¤«ï ª« áᮢ, ®¡ê¥ªâ®¢, ¨­â¥à䥩ᮢ ¨ § ¯¨á¥©.
+parser_w_no_lineinfo_use_switch=03226_W_¥ ¯®¤ª«î砩⥠¬®¤ã«ì LINEINFO ¢àãç­ãî, ¨á¯®«ì§ã©â¥ ¤«ï í⮣® ª«îç -gl
+% ¥ ¯®¤ª«î砩⥠¬®¤ã«ì LINEINFO ¢àãç­ãî, ¨á¯®«ì§®¢ ­¨¥ ª«îç  \var{-gl}  ¢â®¬ â¨ç¥áª¨ ¯®¤ª«îç ¥â
+% à §«¨ç­ë¥ ¬®¤ã«¨ ¢ § ¢¨á¨¬®á⨠®â ⨯  £¥­¥à¨à㥬®© ®â« ¤®ç­®© ¨­ä®à¬ æ¨¨.
+parser_e_no_funcret_specified=03227_E_„«ï ä㭪樨 "$1" ­¥ 㪠§ ­ ⨯ १ã«ìâ â 
+% ¥à¢®¥ ®¡ê¥­¨¥ ä㭪樨 ¤®«¦­® ¡ëâì ¯®«­ë¬, ¢ª«îç ï ¢á¥ ¯ à ¬¥âàë ¨ ⨯ १ã«ìâ â .
+parser_e_special_onlygenerics=03228_E_‘¯¥æ¨ «¨§ æ¨ï ¢®§¬®¦­  ⮫쪮 ¤«ï ®¡®¡é¥­­ëå ⨯®¢.
+% ’¨¯ë, ­¥ ïî騥áï ®¡®¡é¥­¨ï¬¨, ­¥ ¬®£ãâ ¡ëâì ᯥ樠«¨§¨à®¢ ­ë.
+parser_e_no_generics_as_params=03229_E_Ž¡®¡é¥­¨ï ­¥«ì§ï ¨á¯®«ì§®¢ âì ª ª ¯ à ¬¥âàë ᯥ樠«¨§ æ¨¨ ¤àã£¨å ®¡®¡é¥­¨©
+% ਠᯥ樠«¨§ æ¨¨ ®¡®¡é¥­¨ï, ¢ ª ç¥á⢥ ¯ à ¬¥â஢ ¬®¦­® ¨á¯®«ì§®¢ âì ⮫쪮 ®¡ëç­ë¥ ⨯ë.
+parser_e_type_object_constants=03230_E_Š®­áâ ­â­ë¥ ®¡ê¥ªâë, ᮤ¥à¦ é¨¥ VMT, ­¥ ¤®¯ã᪠îâáï
+% …᫨ ®¡ê¥ªâ âॡã¥â VMT ¨§-§  ­ «¨ç¨ï ª®­áâàãªâ®à  «¨¡® ¢¨àâã «ì­ëå ¬¥â®¤®¢,
+% ᮧ¤ ­¨¥ ª®­áâ ­â ¥£® ⨯  ­¥ ¤®¯ã᪠¥âáï. ‚ ०¨¬ å TP ¨ Delphi, ⥬ ­¥ ¬¥­¥¥,
+% íâ® à §à¥è¥­® ¢ 楫ïå ᮢ¬¥á⨬®áâ¨.
+parser_e_label_outside_proc=03231_E_¥ ¤®¯ã᪠¥âáï ¢§ï⨥  ¤à¥á®¢ ¬¥â®ª, ®¯à¥¤¥«¥­­ëå ¢­¥ ⥪ã饩 ®¡« á⨠¢¨¤¨¬®áâ¨
+% ¥ à §à¥è ¥âáï ¯®«ã祭¨¥  ¤à¥á®¢ ¬¥â®ª, ­ å®¤ïé¨åáï ¢­¥ ⥪ã饩 ¯à®æ¥¤ãàë.
+parser_e_initialized_not_for_external=03233_E_¥ ¤®¯ã᪠¥âáï ¨­¨æ¨ «¨§ æ¨ï ¯¥à¥¬¥­­ëå, ®¡ê¥­­ëå ª ª external
+% ¥à¥¬¥­­ë¥, ®¡ê¥­­ë¥ ª ª external, ­¥ ¬®£ãâ ¨¬¥âì §­ ç¥­¨¥ ¯® 㬮«ç ­¨î.
+parser_e_illegal_function_result=03234_E_¥¢¥à­ë© ⨯ ¢®§¢à é ¥¬®£® §­ ç¥­¨ï
+% ¥ª®â®àë¥ â¨¯ë, â ª¨¥ ª ª ä ©«ë, ­¥ ¬®£ãâ ¡ëâì ¨á¯®«ì§®¢ ­ë ¢ ª ç¥á⢥ १ã«ìâ â  ä㭪樨.
+parser_e_no_common_type=03235_E_Žâáãâáâ¢ã¥â ®¡é¨© ⨯ ¤«ï "$1" ¨ "$2"
+% —â®¡ë ¢ë¯®«­¨âì ®¯¥à æ¨î ­ ¤ 楫묨 ç¨á« ¬¨, ª®¬¯¨«ïâ®à ¯à¨¢®¤¨â ¨å ª ®¡é¥¬ã ⨯ã,
+% 祣® ¥¬ã ¢ ¤ ­­®¬ á«ãç ¥ ­¥ 㤠¥âáï. „«ï ®¯à¥¤¥«¥­¨ï ®¡é¥£® ⨯  ®¯¥à ­¤®¢
+% ª®¬¯¨«ïâ®à ¡¥à¥â ¬¥­ì襥 ¨§ ¬¨­¨¬ «ì­ëå §­ ç¥­¨© ®¡®¨å ⨯®¢ ¨ ¡®«ì襥 ¨§ ¬ ªá¨¬ «ì­ëå
+% §­ ç¥­¨©. Ž¡é¨© ⨯ ¡ã¤¥â ¨¬¥âì ¤¨ ¯ §®­ ¬¨­¨¬ã¬..¬ ªá¨¬ã¬.
+parser_e_no_generics_as_types=03236_E_Ž¡®¡é¥­¨ï ¡¥§ ᯥ樠«¨§ æ¨¨ ­¥ ¬®£ãâ ¡ëâì ¨á¯®«ì§®¢ ­ë ª ª ⨯ ¯¥à¥¬¥­­®©
+% Ž¡®¡é¥­¨ï ¢á¥£¤  ¤®«¦­ë ¡ëâì ᯥ樠«¨§¨à®¢ ­ë ¯¥à¥¤ ¨á¯®«ì§®¢ ­¨¥¬ ¢ ª ç¥á⢥ ⨯  ¤«ï ¯¥à¥¬¥­­ëå.
+parser_w_register_list_ignored=03237_W_¥à¥ç¥­ì ॣ¨áâ஢ ¤«ï ¯à®æ¥¤ãà ¯®«­®áâìî ­   áᥬ¡«¥à¥ ¨£­®à¨à®¢ ­
+% ‚ ¯à®æ¥¤ãà å, ­ ¯¨á ­­ëå ¯®«­®áâìî ­   áᥬ¡«¥à¥, ¯¥à¥ç¥­ì ¨§¬¥­¥­­ëå ॣ¨áâ஢ ¨£­®à¨àã¥âáï.
+parser_e_implements_must_be_class_or_interface=03238_E_‘¢®©á⢮ implements ¤®«¦­® ¡ëâì ⨯  ª« áá ¨«¨ ¨­â¥à䥩á
+% ‘¢®©á⢮, ॠ«¨§ãî饥 ¨­â¥à䥩á, ¤®«¦­® ¨¬¥âì ⨯ ª« áá  ¨«¨ ¨­â¥à䥩á .
+parser_e_implements_must_have_correct_type=03239_E_‘¢®©á⢮ implements ¤®«¦­® ॠ«¨§®¢ë¢ âì ¨­â¥à䥩á 㪠§ ­­®£® ⨯ , ­ ©¤¥­® "$1" ®¦¨¤ «®áì "$2"
+% ‘¢®©á⢮, ॠ«¨§ãî饥 ¨­â¥à䥩á, ॠ«¨§ã¥â ­¥ â®â ⨯ ¨­â¥à䥩á .
+parser_e_implements_must_read_specifier=03240_E_‘¢®©á⢮ implements ¤®«¦­® ¡ëâì ¤®áâã¯­ë¬ ¤«ï ç⥭¨ï
+% ‘¢®©á⢮, ॠ«¨§ãî饥 ¨­â¥à䥩á, ¤®«¦­® ¨¬¥âì ᯥæ¨ä¨ª â®à read.
+parser_e_implements_must_not_have_write_specifier=03241_E_‘¢®©á⢮ implements ­¥ ¤®«¦­® ¡ëâì ¤®áâã¯­ë¬ ¤«ï § ¯¨á¨
+% ‘¢®©á⢮, ॠ«¨§ãî饥 ¨­â¥à䥩á, ­¥ ¬®¦¥â ¨¬¥âì ᯥæ¨ä¨ª â®à write.
+parser_e_implements_must_not_have_stored_specifier=03242_E_‘¢®©á⢮ implements ­¥ ¬®¦¥â ¡ëâì stored
+% ‘¢®©á⢮, ॠ«¨§ãî饥 ¨­â¥à䥩á, ­¥ ¬®¦¥â ¨¬¥âì ᯥæ¨ä¨ª â®à stored.
+parser_e_implements_uses_non_implemented_interface=03243_E_‘¢®©á⢮ implements ¨á¯®«ì§®¢ ­® ¤«ï ­¥à¥ «¨§®¢ ­­®£® ¨­â¥à䥩á : "$1"
+% ˆ­â¥à䥩á, ॠ«¨§ã¥¬ë© ᢮©á⢮¬, ¤®«¦¥­ ¡ëâì ¢ ᯨ᪥ ¨­â¥à䥩ᮢ, ॠ«¨§ã¥¬ëå ª« áᮬ.
+parser_e_unsupported_real=03244_E_‚ëç¨á«¥­¨ï á ¯« ¢ î饩 § ¯ï⮩ ­¥ ¤®áâã¯­ë ¤«ï 楫¥¢®© ¯« âä®à¬ë
+% ‚áâà¥â¨«®áì ¢¥é¥á⢥­­®¥ ¢ëà ¦¥­¨¥, ­® ­  楫¥¢®© ¯« âä®à¬¥ ®­¨ ­¥ ¯®¤¤¥à¦¨¢ îâáï
+parser_e_class_doesnt_implement_interface=03245_E_Š« áá "$1" ­¥ ॠ«¨§ã¥â ¨­â¥à䥩á "$2"
+% „¥«¥£¨à®¢ ­­ë© ¨­â¥àä¥©á ­¥ ॠ«¨§®¢ ­ ª« áᮬ, 㪠§ ­­ë¬ ¢ ¢ëà ¦¥­¨¨ implements.
+parser_e_class_implements_must_be_interface=03246_E_’¨¯, ¨á¯®«ì§ã¥¬ë© implements, ¤®«¦¥­ ¡ëâì ¨­â¥à䥩ᮬ
+% ‡  ª«îç¥¢ë¬ á«®¢®¬ \var{implements} ¤®«¦­® á«¥¤®¢ âì ¨¬ï ⨯  ¨­â¥à䥩á .
+parser_e_cant_export_var_different_name=03247_E_  í⮩ ¯« âä®à¬¥ ¯¥à¥¬¥­­ë¥ ­¥«ì§ï íªá¯®àâ¨à®¢ âì á ¤à㣨¬ ¨¬¥­¥¬, ¤®¡ ¢ì⥠¨¬ï ª ®¡ê¥­¨î á ¯®¬®éìî ¤¨à¥ªâ¨¢ë "export" (¨¬ï ¯¥à¥¬¥­­®©: $1, ®¡ê¥­­®¥ ¨¬ï íªá¯®àâ : $2)
+% On most targets it is not possible to change the name under which a variable
+% is exported inside the \var{exports} statement of a library.
+% In that case, you have to specify the export name at the point where the
+% variable is declared, using the \var{export} and \var{alias} directives.
+parser_e_weak_external_not_supported=03248_E_‘¨¬¢®«ë "weak external" ­¥ ¯®¤¤¥à¦¨¢ îâáï ­  楫¥¢®© ¯« âä®à¬¥
+% A "weak external" symbol is a symbol which may or may not exist at (either static
+% or dynamic) link time. This concept may not be available (or implemented yet)
+% on the current cpu/OS target.
+parser_e_forward_mismatch=03249_E_’¨¯ ­¥ ᮮ⢥âáâ¢ã¥â à ­­¥¬ã ®¡ê¥­¨î
+% ਠ࠭­¥¬ ®¡ê¥­¨¨ ª« áᮢ ¨ ¨­â¥à䥩ᮢ ⨯ë à ­­¥£® ¨ ä ªâ¨ç¥áª®£® ®¡ê¥­¨©
+% ¤®«¦­ë ᮢ¯ ¤ âì.  ­¥¥ ®¡ê¥­­ë© ¨­â¥àä¥©á ­¥ ¬®¦¥â ¡ëâì ¯à¥¢à é¥­ ¢ ª« áá.
+parser_n_ignore_lower_visibility=03250_N_‚¨àâã «ì­ë© ¬¥â®¤ "$1" ¨¬¥¥â ¬¥­ìèãî ¢¨¤¨¬®áâì ($2), 祬 ¢ த¨â¥«ì᪮¬ ª« áᥠ$3 ($4)
+% ¥à¥ªà뢠î騩 ¢¨àâã «ì­ë© ¬¥â®¤ ¢¨¤¨¬®áâì ¬¥­ìè¥, 祬 ¯¥à¥ªà뢠¥¬ë©. â® ¬®¦¥â ¯à¨¢®¤¨âì ª
+% ­¥®¦¨¤ ­­ë¬ १ã«ìâ â ¬. …᫨ ­®¢ ï ¢¨¤¨¬®áâì - private, â® ¢ë§®¢ inherited ¢ ­®¢®¬ ª« áá¥
+% ¯®â®¬ª  ¬®¦¥â ¢ë§ë¢ âì ¬¥â®¤ á ¡®«ì襩 ¢¨¤¨¬®áâìî ¢ த¨â¥«ì᪮¬ ª« áá¥, ¨£­®à¨àãï private ¬¥â®¤.
+parser_e_field_not_allowed_here=03251_E_®«ï ­¥«ì§ï ®¡êïâì ¯®á«¥ ¬¥â®¤®¢ ¨«¨ ᢮©áâ¢, á­ ç «  ­ ç­¨â¥ ­®¢ãî ᥪæ¨î ¢¨¤¨¬®áâ¨
+% ®á«¥ ®¡ê¥­¨ï ¬¥â®¤  ¨«¨ ᢮©á⢠ ¢ ª« áᥠ¨«¨ ®¡ê¥ªâ¥, ¤ «ì­¥©è¥¥ ®¡ê¥­¨¥ ¯®«¥© ¢®§¬®¦­®
+% ⮫쪮 ¢ ­®¢®© ᥪ樨 ®¡« á⨠¢¨¤¨¬®á⨠(\var{public}, \var{private} ¨ â.¤.). â® ­¥®¡å®¤¨¬®
+% ¤«ï ®¤­®§­ ç­®£® ¯®­¨¬ ­¨ï ª®¤  ª®¬¯¨«ïâ®à®¬, ¯®áª®«ìªã ¬®¤¨ä¨ª â®àë ¬¥â®¤®¢,
+% â ª¨¥ ª ª \var{default} ¨ \var{register} ¬®£ãâ â ª¦¥ ¨á¯®«ì§®¢ âìáï ª ª ¨¬¥­  ¯®«¥©.
+parser_e_no_local_para_def=03252_E_ à ¬¥âàë ­¥ ¬®£ãâ ᮤ¥à¦ âì «®ª «ì­ë¥ ®¡ê¥­¨ï ⨯®¢. ˆá¯®«ì§ã©â¥ ®â¤¥«ì­®¥ ®¡ê¥­¨¥ ⨯  ¢ ¡«®ª¥ type.
+% ‚  áª «¥ ᥬ ­â¨ç¥áª¨ à ¢­®§­ ç­ë¥ â¨¯ë ­¥ áç¨â îâáï ¨¤¥­â¨ç­ë¬¨.
+% ¥à¥¬¥­­ë¥ ¨«¨ ¯ à ¬¥âàë áç¨â îâáï ®¤­®â¨¯­ë¬¨ ⮫쪮 ¢ ⮬ á«ãç ¥, ¥á«¨ ®­¨ ááë« îâáï ­  ®¤­® ¨ â® ¦¥
+% ®¡ê¥­¨¥ ⨯ .
+% Š ª á«¥¤á⢨¥, ®¡ê¥­¨¥ ⨯®¢ ¢ ᯨ᪥ ¯ à ¬¥â஢ ­¥ ¤®¯ã᪠¥âáï, â.ª. ­  «®ª «ì­®¥ ®¡ê¥­¨¥ ­¥¢®§¬®¦­®
+% á®á« âìáï ¨§¢­¥, ¨ ¤¢  § £®«®¢ª  ¯à®æ¥¤ãàë ¢ ¨­â¥à䥩᭮© ¨ ॠ«¨§ æ¨®­­®© ç á⨠¬®¤ã«ï ®¡ê﫨 ¡ë
+% ¤¢  à §«¨ç­ëå ⨯ . ˆ¬¥©â¥ ¢ ¢¨¤ã, çâ® ¢ëà ¦¥­¨ï ¢¨¤  ``file of byte'' ¨«¨ ``string[50]'' â ª¦¥ ®¯à¥¤¥«ïîâ
+% ­®¢ë© ⨯.
+% \end{description}
+#
+# Type Checking
+#
+# 04087 is the last used one
+#
+% \section{Žè¨¡ª¨ ¯à®¢¥àª¨ ⨯®¢}
+% ‚ à §¤¥«¥ ¯¥à¥ç¨á«¥­ë ¢á¥ ®è¨¡ª¨, ª®â®àë¥ ¬®£ãâ ¢®§­¨ª âì ¢ ¯à®æ¥áá¥
+% ¯à®¢¥àª¨ ⨯®¢.
+% \begin{description}
+type_e_mismatch=04000_E_’¨¯ ­¥ ᮢ¯ ¤ ¥â
+% Œ®¦¥â ¨¬¥âì ¬¥áâ® ¢® ¬­®£¨å á«ãç ïå:
+% \begin{itemize}
+% \item à¨á¢ ¨¢ ¥¬ ï ¯¥à¥¬¥­­ ï ¨¬¥¥â ⨯, ®â«¨ç­ë© ®â ¯à¨á¢ ¨¢ ¥¬®£® ¢ëà ¦¥­¨ï.
+% \item ‚맮¢ ä㭪樨 ¨«¨ ¯à®æ¥¤ãàë á ¯ à ¬¥âà ¬¨, ­¥á®¢¬¥á⨬묨
+% á ⥬¨, ª®â®àë¥ ¡ë«¨ ¨á¯®«ì§®¢ ­ë ¯à¨ ®¡ê¥­¨¨ ä㭪樨.
+% \end{itemize}
+type_e_incompatible_types=04001_E_H¥á®¢¬¥áâ¨¬ë¥ â¨¯ë: ¯®«y祭® "$1", ®¦¨¤ «®áì "$2"
+% ८¡à §®¢ ­¨¥ ¨§ ®¤­®£® ⨯  ¢ ¤à㣮© ­¥¢®§¬®¦­®.
+% ’ ª¦¥ ¢®§¬®¦­®, çâ® â¨¯ë ®¡ê¥­ë ¢ à §«¨ç­ëå ®¡ê¥­¨ïå:
+% \begin{verbatim}
+% Var
+% A1 : Array[1..10] Of Integer;
+% A2 : Array[1..10] Of Integer;
+%
+% Begin
+% A1:=A2; { ਢ¥¤¥â ª ®è¨¡ª¥ ¨§-§  âॡ®¢ ­¨ï
+% áâண®£® ᮮ⢥âá⢨ï ⨯®¢ ¢  áª «¥ }
+% End.
+% \end{verbatim}
+type_e_not_equal_types=04002_E_H¥á®¢¯ ¤¥­¨¥ ⨯®¢ ¬¥¦¤y "$1" ¨ "$2"
+% ’¨¯ë ­¥ à ¢­ë
+type_e_type_id_expected=04003_E_Ž¦¨¤ ¥âáï ¨¤¥­â䨪 â®à ⨯ 
+% ˆ¤¥­â¨ä¨ª â®à ­¥ ï¥âáï ⨯®¬, «¨¡® ¨¤¥­â¨ä¨ª â®à ⨯  ¯à®¯ã饭.
+type_e_variable_id_expected=04004_E_Ž¦¨¤ ¥âáï ¨¤¥­â¨ä¨ª â®à ¯¥à¥¬¥­­®©
+% நá室¨â ¯à¨ ¯®¯ë⪥ ¯¥à¥¤ ç¨ ª®­áâ ­âë ¢ ¯à®æ¥¤ãàã \var{Inc} ¨«¨ \var{Dec}.
+% ˆ¬ ¬®¦­® ¯¥à¥¤ ¢ âì ⮫쪮 ¯¥à¥¬¥­­ë¥.
+type_e_integer_expr_expected=04005_E_Ž¦¨¤ ¥âáï ¢ëp ¦¥­¨¥ ⨯  INTEGER, ­® ¯®«ã祭® "$1"
+% Š®¬¯¨«ïâ®à ®¦¨¤ ¥â ¢ëà ¦¥­¨¥ ⨯  integer, ­® ¯®«ã砥⠭¥çâ® ¨­®¥.
+type_e_boolean_expr_expected=04006_E_Ž¦¨¤ ¥âáï ¢ëà ¦¥­¨¥ ⨯  BOOLEAN, ­® ¯®«ã祭® "$1"
+% ‚ëà ¦¥­¨¥ ¤®«¦­® ¡ëâì ¡ã«¥¢®£® ⨯ , ¤®«¦­® ¡ëâì ¢®§¢à é¥­® true ¨«¨
+% false.
+type_e_ordinal_expr_expected=04007_E_Ž¦¨¤ ¥âáï ¢ëp ¦¥­¨¥ ¯®à浪®¢®£® ⨯ 
+% ’¨¯ ¢ëà ¦¥­¨ï ¤®«¦¥­ ¡ëâì ¯®à浪®¢ë¬, â.¥., ¬ ªá¨¬ã¬ \var{Longint}.
+% நá室¨â, ­ ¯à¨¬¥à, ¥á«¨ ¢â®à®©  à£ã¬¥­â
+% \var{Inc} ¨«¨ \var{Dec} ­¥ ¢ëç¨á«ï¥âáï ª ª ¯®à浪®¢ë© ⨯.
+type_e_pointer_type_expected=04008_E_Ž¦¨¤ ¥âáï ⨯ POINTER, ­® ¯®«ã祭® "$1"
+% ¥à¥¬¥­­ ï ¨«¨ ¢ëà ¦¥­¨¥ ¨¬¥¥â ⨯, ®â«¨ç­ë© ®â \var{pointer}. நá室¨â,
+% ­ ¯à¨¬¥à, ¯à¨ ¯¥à¥¤ ç¥ 楫®© ¯¥à¥¬¥­­®© ¢ ª ç¥á⢥  à£ã¬¥­â  \var{New}
+% ¨«¨ \var{Dispose}.
+type_e_class_type_expected=04009_E_Ž¦¨¤ ¥âáï ⨯ CLASS, ­® ¯®«ã祭® "$1"
+% ¥à¥¬¥­­ ï ¨«¨ ¢ëà ¦¥­¨¥ ¨¬¥¥â ⨯, ®â«¨ç­ë© ®â \var{class}. Ž¡ëç­®
+% á«ãç ¥âáï, ¥á«¨
+% \begin{enumerate}
+% \item ®¤¨â¥«ì᪨© ª« áá ¢ ®¡ê¥­¨¨ ª« áá  ­¥ ï¥âáï ª« áᮬ.
+% \item Ž¡à ¡®â稪 ¨áª«î祭¨© (\var{On}) ᮤ¥à¦¨â ¨¤¥­â¨ä¨ª â®à ⨯ ,
+% ­¥ ïî騩áï ª« áᮬ.
+% \end{enumerate}
+type_e_cant_eval_constant_expr=04011_E_H¥¢®§¬®¦­® ¢ëç¨á«¨âì ª®­áâ ­â­®¥ ¢ëà ¦¥­¨¥
+% நá室¨â, ¥á«¨ £à ­¨æë ®¡ê¥­­®£® ¬ áᨢ  ­¥ ¢ëç¨á«ïîâáï ª ª ¯®à浪®¢ë¥ ª®­áâ ­âë.
+type_e_set_element_are_not_comp=04012_E_«¥¬¥­âë ¬­®¦¥á⢠ ­¥ ᮢ¬¥á⨬ë
+% ‚®§­¨ª ¥â ¯à¨ ®¯¥à æ¨¨ ­ ¤ ¤¢ã¬ï ¬­®¦¥á⢠¬¨, ¨¬¥î騬¨ à §«¨ç­ë© ⨯ í«¥¬¥­â®¢.
+% „«ï ®¡ê¥¤¨­¥­¨ï ¬­®¦¥á⢠®­¨ ¤®«¦­ë ¨¬¥âì ®¤¨­ ª®¢ë© ¡ §®¢ë© ⨯.
+type_e_set_operation_unknown=04013_E_Ž¯¥p æ¨ï ­¥ p¥ «¨§®¢ ­  ¤«ï ¬­®¦¥áâ¢
+% ¥ª®â®àë¥ ¯ à­ë¥ ®¯¥à æ¨¨ ­¥ ®¯à¥¤¥«¥­ë ¤«ï ¬­®¦¥áâ¢,
+% ­ ¯à¨¬¥à, div mod ** (â ª¦¥, ¢ ­ áâ®ï饥 ¢à¥¬ï, >= <=).
+type_w_convert_real_2_comp=04014_W_€¢â®¬ â¨ç¥áª®¥ ¯p¥®¡p §®¢ ­¨¥ ¨§ ¢¥é¥á⢥­­®£® ⨯  ¢ COMP, ª®â®pë© ï¢«ï¥âáï 楫®ç¨á«¥­­ë¬
+% ‚áâà¥â¨«®áì ­¥ï¢­®¥ ¯à¥®¡à §®¢ ­¨¥ ¢¥é¥á⢥­­®£® ⨯  ¢ \var{comp}.
+% ®áª®«ìªã \var{Comp} ï¥âáï 64-¡¨â­ë¬ 楫ë¬, íâ® ¬®¦¥â ᢨ¤¥â¥«ìá⢮¢ âì ®¡ ®è¨¡ª¥.
+type_h_use_div_for_int=04015_H_„«ï ¯®«y祭¨ï 楫®ç¨á«¥­­®£® p¥§y«ìâ â  ¨á¯®«ì§y©â¥ DIV
+% ਠ¢ª«î祭­ëå ¯®¤áª §ª å, á®®¡é¥­¨¥ ¡ã¤¥â ¢ë¤ ¢ âìáï ¯à¨ æ¥«®ç¨á«¥­­®¬ ¤¥«¥­¨¨
+% á ¯®¬®éìî '/', ¯®áª®«ìªã १ã«ìâ â ¢ í⮬ á«ãç ¥ ¡ã¤¥â ¢¥é¥á⢥­­ë¬.
+type_e_strict_var_string_violation=04016_E_’¨¯ë áâப ­¥ ᮢ¯ ¤ îâ ¨§-§  ०¨¬  $V+
+% ਠª®¬¯¨«ï樨 ¢ ०¨¬¥ \var{\{\$V+\}}, ⨯ áâப, ¯¥à¥¤ ¢ ¥¬ëå ª ª ¯ à ¬¥âàë,
+% ¤®«¦¥­ ¢ â®ç­®á⨠ᮢ¯ ¤ âì á ⨯®¬ ¢ ®¡ê¥­¨¨ ä㭪樨.
+type_e_succ_and_pred_enums_with_assign_not_possible=04017_E_SUCC ¨«¨ PRED ­¥¢®§¬®¦­ë ­  ¯¥p¥ç¨á«¥­¨ïå á ¯à¨á¢®¥­¨ï¬¨
+% …᫨ ¯¥à¥ç¨á«ï¥¬ë© ⨯ ᮤ¥à¦¨â ¯à¨á¢®¥­¨ï, ª ª ¢ ï§ëª¥ C,
+% ­ ¯à¨¬¥à:
+% \begin{verbatim}
+% Tenum = (a,b,e:=5);
+% \end{verbatim}
+% â® ¤«ï ­¥£® ­¥«ì§ï ¨á¯®«ì§®¢ âì ä㭪樨 \var{Succ} ¨«¨ \var{Pred}.
+type_e_cant_read_write_type=04018_E_—⥭¨¥ ¨ § ¯¨áì ¯¥p¥¬¥­­ëå í⮣® ⨯  ­¥¢®§¬®¦­ 
+% ®¯ë⪠ ç⥭¨ï (\var{read}) ¨«¨ § ¯¨á¨ (\var{write}) ¯¥à¥¬¥­­®©, ⨯ ª®â®à®© ­¥
+% ¯®¤¤¥à¦¨¢ ¥âáï, ¢ ä ©« ⨯  ⥪áâ. ®¤¤¥à¦¨¢ îâáï ⮫쪮 楫ë¥,
+% ¡ã«¥¢ë, ¢¥é¥á⢥­­ë¥ ¯¥à¥¬¥­­ë¥, ¯¥à¥¬¥­­ë¥ ⨯  pchar ¨ áâப¨.
+type_e_no_readln_writeln_for_typed_file=04019_E_Readln ¨«¨ Writeln ­¥¤®¯ãáâ¨¬ë ­  ⨯¨§¨à®¢ ­­®¬ ä ©«¥
+% \var{readln} ¨ \var{writeln} ¤®¯ã᪠îâáï ⮫쪮 ¤«ï ⥪á⮢ëå ä ©«®¢.
+type_e_no_read_write_for_untyped_file=04020_E_Read ¨«¨ Write ­¥¤®¯ãáâ¨¬ë ­  ­¥â¨¯¨§¨à®¢ ­­®¬ ä ©«¥
+% \var{read} ¨ \var{write} ¤®¯ã᪠îâáï ⮫쪮 ¤«ï ⥪á⮢ëå ¨ ⨯¨§¨à®¢ ­­ëå ä ©«®¢.
+type_e_typeconflict_in_set=04021_E_Š®­ä«¨ªâ ⨯®¢ ¬¥¦¤y í«¥¬¥­â ¬¨ ¬­®¦¥á⢠
+% ’¨¯ ¯® ªà ©­¥© ¬¥à¥ ®¤­®£® í«¥¬¥­â  ­¥ ᮢ¯ ¤ ¥â á ¡ §®¢ë¬ ⨯®¬ ¬­®¦¥á⢠.
+type_w_maybe_wrong_hi_lo=04022_W_Lo/Hi(dword/qword) ¢®§¢p é îâ ¬« ¤è¥¥/áâ à襥 word/dword
+% \fpc ¯®¤¤¥à¦¨¢ ¥â ¯¥à¥£à㦥­­ë¥ ¢ à¨ ­âë \var{lo/hi} ¤«ï \var{longint/dword/int64/qword},
+% ª®â®àë¥ ¢®§¢à é îâ ¬« ¤èãî/áâ àèãî ¯®«®¢¨­ã  à£ã¬¥­â  (⨯  word/dword). TP ¢á¥£¤  ¨á¯®«ì§ã¥â
+% 16-¡¨â­ë¥ \var{lo/hi}, ª®â®àë¥ ¢á¥£¤  ¢®§¢à é îâ ¡¨âë 0..7 ¤«ï \var{lo} ¨
+% ¡¨âë 8..15 ¤«ï \var{hi}. …᫨ âॡã¥âáï ¯®¢¥¤¥­¨¥ TP, ­ã¦­® ¯à¨¢¥á⨠ à£ã¬¥­â
+% ª \var{word/integer}.
+type_e_integer_or_real_expr_expected=04023_E_Ž¦¨¤ ¥âáï ¢ëp ¦¥­¨¥ 楫®£® ¨«¨ ¢¥é¥á⢥­­®£® ⨯ 
+% ¥à¢ë©  à£ã¬¥­â \var{str} ¤®«¦¥­ ¨¬¥âì æ¥«ë© «¨¡® ¢¥é¥á⢥­­ë© ⨯.
+type_e_wrong_type_in_array_constructor=04024_E_H¥¢¥p­ë© ⨯ "$1" ¢ ª®­áâpyªâ®p¥ ¬ áᨢ 
+% ®¯ë⪠ ¨á¯®«ì§®¢ ­¨ï ­¥¤®¯ãá⨬®£® ⨯  ¢ ª®­áâàãªâ®à¥ ¬ áᨢ .
+type_e_wrong_parameter_type=04025_E_H¥á®¢¯ ¤¥­¨¥ ⨯   p£y¬¥­â  # $1: ¯®«ã祭® "$2", ®¦¨¤ «®áì "$3"
+% ®¯ë⪠ ¯¥à¥¤ âì ­¥¢¥à­ë© ⨯ ¤«ï 㪠§ ­­®£® ¯ à ¬¥âà .
+type_e_no_method_and_procedure_not_compatible=04026_E_Œ¥â®¤ (¯¥p¥¬¥­­ ï) ¨ ¯p®æ¥¤yp  (¯¥p¥¬¥­­ ï) ­¥ ᮢ¬¥á⨬ë
+% ¥«ì§ï ¯à¨á¢®¨âì ¬¥â®¤ ¯¥à¥¬¥­­®© ⨯  ¯à®æ¥¤ãà , ¨«¨ ¯à®æ¥¤ãàã ¯¥à¥¬¥­­®© ⨯ 
+% ¬¥â®¤.
+type_e_wrong_math_argument=04027_E_¥¢¥à­ ï ª®­áâ ­â  ¯¥p¥¤ ­  ¢áâ஥­­®© ¬ â¥¬ â¨ç¥áª®© äy­ªæ¨¨
+% Š®­áâ ­â­ë©  à£ã¬¥­â ä㭪樨 ln ¨«¨ sqrt ­ å®¤¨âáï ¢­¥ ®¯à¥¤¥«¥­­®£® ¤«ï ­¨å
+% ¤¨ ¯ §®­ .
+type_e_no_addr_of_constant=04028_E_H¥«ì§ï ¢§ïâì  ¤à¥á ª®­áâ ­â­®£® ¢ëà ¦¥­¨ï
+% ‚§ïâì  ¤à¥á ª®­áâ ­â­®£® ¢ëà ¦¥­¨ï ­¥¢®§¬®¦­®, ¯®â®¬ã çâ® ª®­áâ ­âë ­¥
+% åà ­ïâáï ¢ ¯ ¬ïâ¨. Œ®¦­® ¯®¯à®¡®¢ âì ®¡êâì ⨯¨§¨à®¢ ­­ãî ª®­áâ ­âã.
+type_e_argument_cant_be_assigned=04029_E_€à£ã¬¥­âã ­¥¢®§¬®¦­® ¯à¨á¢®¨âì §­ ç¥­¨¥
+% ‚ ª ç¥á⢥ ¯ à ¬¥âà  ¯® áá뫪¥ ¬®£ãâ ¡ëâì ¯¥à¥¤ ­ë ⮫쪮 ⥠¢ëà ¦¥­¨ï,
+% ª®â®àë¥ ¬®¦­® ¨á¯®«ì§®¢ âì á «¥¢®© áâ®à®­ë ®¯¥à â®à  ¯à¨á¢ ¨¢ ­¨ï.
+% ‡ ¬¥ç ­¨ï: ‘¢®©á⢠ ¬®¦­® ¨á¯®«ì§®¢ âì á «¥¢®© áâ®à®­ë ¯à¨á¢ ¨¢ ­¨ï, ­®
+% ­¥«ì§ï ¯¥à¥¤ ¢ âì ¯® áá뫪¥.
+type_e_cannot_local_proc_to_procvar=04030_E_‹®ª «ì­ ï ¯à®æ¥¤ãà  ­¥ ¬®¦¥â ¡ëâì ¯à¨á¢®¥­  ¯¥à¥¬¥­­®© ¯à®æ¥¤ãà­®£® ⨯ 
+% à¨á¢®¥­¨¥ «®ª «ì­ëå ¯à®æ¥¤ãà/ä㭪権 ¯à®æ¥¤ãà­ë¬ ¯¥à¥¬¥­­ë¬ ­¥ ¤®¯ã᪠¥âáï,
+% â.ª. ã ­¨å ¤à㣮© ᯮᮡ ¢ë§®¢ . ‹®ª «ì­ë¥ ¯à®æ¥¤ãàë/ä㭪樨
+% ¬®¦­® ¯à¨á¢®¨âì ⮫쪮 ­¥â¨¯¨§¨à®¢ ­­®¬ã 㪠§ â¥«î.
+type_e_no_assign_to_addr=04031_E_H¥«ì§ï ¯à¨á¢®¨âì §­ ç¥­¨¥  ¤p¥áy
+% ¥ ¤®¯ã᪠¥âáï ¯à¨á¢®¥­¨¥ §­ ç¥­¨©  ¤à¥á ¬ ¯¥à¥¬¥­­ëå, ª®­áâ ­â, ¯à®æ¥¤ãà
+% ¨ ä㭪権. …᫨ ¨¤¥­â¨ä¨ª â®à ï¥âáï ¯à®æ¥¤ãà­®© ¯¥à¥¬¥­­®©, ¬®¦­® ¯®¯à®¡®¢ âì
+% ª®¬¯¨«ïæ¨î á ª«î箬 -So.
+type_e_no_assign_to_const=04032_E_H¥«ì§ï ¯à¨á¢®¨âì §­ ç¥­¨¥ ª®­áâ ­â¥
+% ¥ ¤®¯ã᪠¥âáï ¯à¨á¢®¥­¨¥ §­ ç¥­¨© ¯¥à¥¬¥­­ë¬, ®¡ê¥­­ë¬ ª ª ª®­áâ ­â­ë¥.
+% Š ª ¯à ¢¨«®, íâ® ¯ à ¬¥âàë, ®¡ê¥­­ë¥ ª ª const. —â®¡ë ¨å ¬®¦­® ¡ë«®
+% ¯à¨á¢ ¨¢ âì, ¯®¬¥­ï©â¥ ¨å ­  var ¨«¨ ­  ¯ à ¬¥âà-§­ ç¥­¨¥.
+type_e_array_required=04033_E_’p¥¡y¥âáï ⨯ ¬ áᨢ 
+% ਠ¤®áâ㯥 ª ¯¥à¥¬¥­­®© ¯® ¨­¤¥ªáã '[<x>]' ⨯ í⮩ ¯¥à¥¬¥­­®© ¤®«¦­  ¡ëâì
+% ¬ áᨢ®¬. ‚ ०¨¬¥ FPC â ª¦¥ ¤®¯ã᪠îâáï 㪠§ â¥«¨.
+type_e_interface_type_expected=04034_E_’ॡã¥âáï ⨯ ¨­â¥à䥩á , ­® ¯®«ã祭® "$1"
+% Š®¬¯¨«ïâ®à ®¦¨¤ « ¢áâà¥â¨âì ¨¬ï ⨯  ¨­â¥à䥩á , ­® ¢áâà¥â¨« çâ®-â® ¤à㣮¥.
+% Žè¨¡ª  ¬®¦¥â ¡ëâì ¢ë§¢ ­  á«¥¤ãî騬 ª®¤®¬:
+% \begin{verbatim}
+% Type
+% TMyStream = Class(TStream,Integer)
+% \end{verbatim}
+type_h_mixed_signed_unsigned=04035_H_‘¬¥è¨¢ ­¨¥ §­ ª®¢ëå ¨ ¡¥§§­ ª®¢ëå ¢ëà ¦¥­¨© ¤ ¥â 64-¡¨â­ë© १ã«ìâ â
+% ਠ¤¥«¥­¨¨ (¨«¨ ¢ëç¨á«¥­¨¨ ®áâ âª ) §­ ª®¢®£® ¢ëà ¦¥­¨ï ­  ¡¥§§­ ª®¢®¥ (¨«¨ ­ ®¡®à®â),
+% ¨«¨ ¦¥ ¢ª«î祭  ¯à®¢¥àª  ¯¥à¥¯®«­¥­¨© ¨/¨«¨ ¤¨ ¯ §®­®¢ ¨ ¨á¯®«ì§ã¥âáï  à¨ä¬¥â¨ç¥áª®¥
+% ¢ëà ¦¥­¨¥ (+, -, *, div, mod), ¢ ª®â®à®¬ ¢áâà¥ç îâáï ª ª §­ ª®¢ë¥, â ª ¨ ¡¥§§­ ª®¢ë¥ §­ ç¥­¨ï,
+% ¢ëç¨á«¥­¨¥ ¡ã¤¥â ¯à®¨§¢®¤¨âìáï ¢ 64-¡¨â­®¬ ०¨¬¥, ª®â®àë© ¬¥¤«¥­­¥¥ ®¡ëç­®©
+% 32-¡¨â­®©  à¨ä¬¥â¨ª¨. ⮣® ¬®¦­® ¨§¡¥¦ âì, ¯à¨¢¥¤ï ⨯ ®¤­®£® ¨§ ®¯¥à ­¤®¢ ª ⨯ã
+% ¤à㣮£®.
+type_w_mixed_signed_unsigned2=04036_W_‘¬¥è¨¢ ­¨¥ §­ ª®¢ëå ¨ ¡¥§§­ ª®¢ëå ¢ëà ¦¥­¨© ⨯  ¬®¦¥â ¢ë§¢ âì ®è¨¡ªã ¢ë室  §  ¤¨ ¯ §®­
+% ਠ¨á¯®«ì§®¢ ­¨¨ ¤¢®¨ç­ëå ®¯¥à æ¨© (and, or, xor), ®¤¨­ ¨§ ®¯¥à ­¤®¢ ª®â®àëå
+% ï¥âáï ¡¥§§­ ª®¢ë¬ ¢ëà ¦¥­¨¥¬,   ¤à㣮© - ¢ëà ¦¥­¨¥¬ á® §­ ª®¬, ¨ ¢ª«î祭 
+% ¯à®¢¥àª  ¤¨ ¯ §®­®¢, ¬®¦¥â ¢®§­¨ª­ãâì ®è¨¡ª , â.ª. ¢ í⮬ á«ãç ¥ ®¡  ®¯¥à ­¤ 
+% ¡ã¤ã⠯८¡à §®¢ ­ë ¢ ¡¥§§­ ª®¢ë© cardinal. ⮣® ¬®¦­® ¨§¡¥¦ âì, ¯à¨¢¥¤ï ⨯
+% ®¤­®£® ¨§ ®¯¥à ­¤®¢ ª ⨯㠤à㣮£®.
+type_e_typecast_wrong_size_for_assignment=04037_E_ਢ¥¤¥­¨¥ ⨯®¢ à §­®£® à §¬¥à  ($1 -> $2) ¢ ¯à¨á¢ ¨¢ ­¨¨
+% ਢ¥¤¥­¨¥ ⨯  ª ⨯㠤à㣮£® à §¬¥à  ­¥¢®§¬®¦­®, ¥á«¨ ¯¥à¥¬¥­­ ï ¨á¯®«ì§ã¥âáï
+% ¢ ¯à¨á¢ ¨¢ ­¨¨.
+type_e_array_index_enums_with_assign_not_possible=04038_E_¥à¥ç¨á«¥­¨ï á ¯à¨á¢®¥­¨ï¬¨ ­¥«ì§ï ¨á¯®«ì§®¢ âì ª ª ¨­¤¥ªá ¬ áᨢ 
+% «¥¬¥­âë ¯¥à¥ç¨á«ï¥¬®£® ⨯ , ®¡ê¥­­®£® á ¯à¨á¢®¥­¨ï¬¨, ª ª ¢ ï§ëª¥ C,
+% ­ ¯à¨¬¥à:
+% \begin{verbatim}
+% Tenum = (a,b,e:=5);
+% \end{verbatim}
+% ­¥«ì§ï ¨á¯®«ì§®¢ âì ª ª ¨­¤¥ªáë ¬ áᨢ®¢.
+type_e_classes_not_related=04039_E_’¨¯ë ª« áᮢ ¨«¨ ®¡ê¥ªâ®¢ "$1" ¨ "$2" ­¥ ᮮ⭮áïâáï
+% ਢ¥¤¥­¨¥ ⨯  ®¤­®£® ª« áá  ¨«¨ ®¡ê¥ªâ  ª ¤à㣮¬ã, ­¥ ¨¬¥î饣® ª ­¥¬ã ®â­®è¥­¨ï.
+% â® ­ ¢¥à­ïª  ¯à¨¢¥¤¥â ª ®è¨¡ª ¬.
+type_w_classes_not_related=04040_W_’¨¯ë ª« áᮢ "$1" ¨ "$2" ­¥ ᮮ⭮áïâáï
+% ਢ¥¤¥­¨¥ ⨯  ®¤­®£® ª« áá  ¨«¨ ®¡ê¥ªâ  ª ¤à㣮¬ã, ­¥ ¨¬¥î饣® ª ­¥¬ã ®â­®è¥­¨ï.
+% â® ­ ¢¥à­ïª  ¯à¨¢¥¤¥â ª ®è¨¡ª ¬.
+type_e_class_or_interface_type_expected=04041_E_Ž¦¨¤ ¥âáï ⨯ ª« áá  ¨«¨ ¨­â¥à䥩á , ­® ¯®«ã祭® "$1"
+% Š®¬¯¨«ïâ®à ®¦¨¤ « ¢áâà¥â¨âì ¨¬ï ª« áá  ¨«¨ ¨­â¥à䥩á , ­® ¢áâà¥â¨« çâ®-â® ¤à㣮¥.
+type_e_type_is_not_completly_defined=04042_E_’¨¯ "$1" ­¥ ®¯à¥¤¥«¥­ ¯®«­®áâìî
+% ந室¨â, ¥á«¨ ⨯ ­¥ ®¯à¥¤¥«¥­ ¯®«­®áâìî, ­ ¯à¨¬¥à, í⮠⨯ 㪠§ â¥«ï, ª®â®àë© ãª §ë¢ ¥â
+% ­  ­¥®¯à¥¤¥«¥­­ë© ⨯.
+type_w_string_too_long=04043_W_‘âப®¢ë© «¨â¥à « ᮤ¥à¦¨â ¡®«ìè¥ á¨¬¢®«®¢, 祬 ¬®¦¥â ¢¬¥áâ¨âì shortstring
+% ®¯ë⪠ ¯à¨á¢®¨âì ª®à®âª®© áâப¥ ª®­áâ ­â­®¥ §­ ç¥­¨¥, ª®â®à®¥ ᮤ¥à¦¨â ¡®«ìè¥ á¨¬¢®«®¢,
+% 祬 ¬ ªá¨¬ «ì­ ï ¤«¨­  áâப¨.
+type_w_signed_unsigned_always_false=04044_W_‘à ¢­¥­¨¥ ¢á¥£¤  «®¦­® ¨§-§  ¤¨ ¯ §®­®¢ §­ ç¥­¨©
+% ‘à ¢­¥­¨¥ ¡¥§§­ ª®¢®£® §­ ç¥­¨ï á® §­ ª®¢®© ª®­á⠭⮩, ¬¥­ì襩 ­ã«ï. ¥§ã«ìâ â â ª®£® ¢ëà ¦¥­¨ï
+% ¡ã¤¥â ¢á¥£¤  «®¦­ë¬. ‘«¥¤ã¥â ® ¯à¨¢¥á⨠⨯ ª®­áâ ­âë ª ­ã¦­®¬ã ¤¨ ¯ §®­ã.
+type_w_signed_unsigned_always_true=04045_W_‘à ¢­¥­¨¥ ¢á¥£¤  ¨á⨭­® ¨§-§  ¤¨ ¯ §®­®¢ §­ ç¥­¨©
+% ‘à ¢­¥­¨¥ ¡¥§§­ ª®¢®£® §­ ç¥­¨ï á® §­ ª®¢®© ª®­á⠭⮩, ¬¥­ì襩 ­ã«ï. ¥§ã«ìâ â â ª®£® ¢ëà ¦¥­¨ï
+% ¡ã¤¥â ¢á¥£¤  ¨á⨭­ë¬. ‘«¥¤ã¥â ® ¯à¨¢¥á⨠⨯ ª®­áâ ­âë ª ­ã¦­®¬ã ¤¨ ¯ §®­ã.
+type_w_instance_with_abstract=04046_W_‘®§¤ ­¨¥ ª« áá  "$1" á  ¡áâà ªâ­ë¬ ¬¥â®¤®¬ "$2"
+% ‘®§¤ ¥âáï íª§¥¬¯«ïà ª« áá , ᮤ¥à¦ é¥£® ­¥¯¥à¥ªàëâë©  ¡áâà ªâ­ë© ¬¥â®¤.
+% ‚맮¢ â ª®£® ¬¥â®¤  ¢® ¢à¥¬ï ¢ë¯®«­¥­¨ï ¯à®£à ¬¬ë ¯à¨¢¥¤¥â ª ®è¨¡ª¥ 211.
+% ‚ᥠ ¡áâà ªâ­ë¥ ¬¥â®¤ë ¤®«¦­ë ¡ëâì ¯¥à¥ªàëâë.
+type_h_in_range_check=04047_H_‹¥¢ë© ®¯¥à ­¤ ®¯¥à â®à  IN ¤®«¦¥­ ¨¬¥âì à §¬¥à ¡ ©â 
+% ‹¥¢ë© ®¯¥à ­¤ ®¯¥à â®à  \var{in} ­¥ ï¥âáï ¯®à浪®¢ë¬ ¨«¨ ¯¥à¥ç¨á«ï¥¬ë¬ §­ ç¥­¨¥¬,
+% ¯®¬¥é î騬áï ¢ 8 ¡¨â, íâ® ¬®¦¥â ¯à¨¢®¤¨âì ª ®è¨¡ª ¬ ¯à®¢¥àª¨ ¤¨ ¯ §®­ . Ž¯¥à â®à \var{in}
+% ¢ ­ áâ®ï饥 ¢à¥¬ï ¯®¤¤¥à¦¨¢ ¥â «¥¢ë© ®¯¥à ­¤ ⮫쪮 ¡ ©â®¢®£® ¤¨ ¯ §®­ . ‚ á«ãç ¥
+% ¯¥à¥ç¨á«¥­¨©, à §¬¥à®¬ í«¥¬¥­â®¢ ¯¥à¥ç¨á«¥­¨ï ¬®¦­® ã¯à ¢«ïâì á ¯®¬®éìî
+% ª«î祩 \var{\{\$PACKENUM\}} ¨«¨ \var{\{\$Zn\}}.
+type_w_smaller_possible_range_check=04048_W_¥á®¢¯ ¤¥­¨¥ à §¬¥à®¢ ⨯®¢, ¢®§¬®¦­  ¯®â¥àï ¤ ­­ëå / ®è¨¡ª¨ ¤¨ ¯ §®­ 
+% à¨á¢®¥­¨¥ ⨯㠬¥­ì襣® à §¬¥à , 祬 ¨á室­ë© ⨯. â® ¬®¦¥â ¯à¨¢®¤¨âì ª ®è¨¡ª ¬ ¯à®¢¥àª¨
+% ¤¨ ¯ §®­ , ¨«¨ ç áâ¨ç­®© ¯®â¥à¥ ¤ ­­ëå.
+type_h_smaller_possible_range_check=04049_H_¥á®¢¯ ¤¥­¨¥ à §¬¥à®¢ ⨯®¢, ¢®§¬®¦­  ¯®â¥àï ¤ ­­ëå / ®è¨¡ª¨ ¤¨ ¯ §®­ 
+% à¨á¢®¥­¨¥ ⨯㠬¥­ì襣® à §¬¥à , 祬 ¨á室­ë© ⨯. â® ¬®¦¥â ¯à¨¢®¤¨âì ª ®è¨¡ª ¬ ¯à®¢¥àª¨
+% ¤¨ ¯ §®­ , ¨«¨ ç áâ¨ç­®© ¯®â¥à¥ ¤ ­­ëå.
+type_e_cant_take_address_of_abstract_method=04050_E_‚§ï⨥  ¤à¥á   ¡áâࠪ⭮£® ¬¥â®¤  ­¥¢®§¬®¦­®
+% €¡áâà ªâ­ë© ¬¥â®¤ ­¥ ¨¬¥¥â ⥫ , ¯®íâ®¬ã  ¤à¥á ¡à âì ­¥ ®â 祣®.
+type_e_assignment_not_allowed=04051_E_¥¢®§¬®¦­® ¯à¨á¢®¥­¨¥ ä®à¬ «ì­ëå ¯ à ¬¥â஢ ¨ ®âªàëâëå ¬ áᨢ®¢
+% ®¯ë⪠ ¯à¨á¢®¨âì §­ ç¥­¨¥ ä®à¬ «ì­®¬ã (­¥â¨¯¨§¨à®¢ ­­®¬ã var, const ¨«¨ out)
+% ¯ à ¬¥âàã, «¨¡® ®âªàë⮬㠬 áᨢã.
+type_e_constant_expr_expected=04052_E_Ž¦¨¤ ¥âáï ª®­áâ ­â­®¥ ¢ëà ¦¥­¨¥
+% Š®¬¯¨«ïâ®à ®¦¨¤ ¥â ª®­áâ ­â­®¥ ¢ëà ¦¥­¨¥, ­® ¯®«ã砥⠯¥à¥¬¥­­®¥.
+type_e_operator_not_supported_for_types=04053_E_Ž¯¥à æ¨ï "$1" ­¥ ¯®¤¤¥à¦¨¢ ¥âáï ¤«ï ⨯®¢ "$2" ¨ "$3"
+% “ª § ­­ ï ®¯¥à æ¨ï ­¥¤®¯ãá⨬  ¤«ï 㪠§ ­­ëå ⨯®¢.
+type_e_illegal_type_conversion=04054_E_¥¤®¯ãá⨬®¥ ¯à¨¢¥¤¥­¨¥ ⨯®¢: "$1" ª "$2"
+% ਠ¯à¨¢¥¤¥­¨¨ ⨯®¢ á«¥¤ã¥â ᮡ«î¤ âì à ¢¥­á⢮ à §¬¥à®¢ ¨áâ®ç­¨ª  ¨ ¯®«ãç â¥«ï.
+type_h_pointer_to_longint_conv_not_portable=04055_H_८¡à §®¢ ­¨¥ ¬¥¦¤ã ¯®à浪®¢ë¬¨ ⨯ ¬¨ ¨ 㪠§ â¥«ï¬¨ ï¥âáï ­¥¯®àâ¨à㥬ë¬
+% Š®¤, ¢ ª®â®à®¬ 㪠§ â¥«¨ ¯à¨¢®¤ïâáï ª longint (¨«¨ ­ ®¡®à®â), ­¥ ¡ã¤¥â à ¡®â âì
+% ­  ¯« âä®à¬ å, ã ª®â®àëå à §¬¥à 㪠§ â¥«ï à ¢¥­ 64 ¡¨â ¬.
+type_w_pointer_to_longint_conv_not_portable=04056_W_८¡à §®¢ ­¨¥ ¬¥¦¤ã ¯®à浪®¢ë¬¨ ⨯ ¬¨ ¨ 㪠§ â¥«ï¬¨ ï¥âáï ­¥¯®àâ¨à㥬ë¬
+% ਢ¥¤¥­¨¥ 㪠§ â¥«¥© ª ¯®à浪®¢ë¬ ⨯ ¬ ¤à㣮£® à §¬¥à  (¨«¨ ­ ®¡®à®â), ¬®¦¥â
+% ¢ë§ë¢ âì ¯à®¡«¥¬ë. â® ¯à¥¤ã¯à¥¦¤¥­¨¥ ¯®¬®£ ¥â ­ å®¤¨âì ᯥæ¨ä¨ç­ë© 32-¡¨â­ë© ª®¤, ¢ ª®â®à®¬
+% ⨯ longint/cardinal ¨á¯®«ì§ã¥âáï ¢§ ¨¬®§ ¬¥­ï¥¬® á 㪠§ â¥«ï¬¨. ¥è¥­¨¥ § ª«îç ¥âáï ¢ ¨á¯®«ì§®¢ ­¨¨
+% ⨯®¢ ptrint/ptruint.
+type_e_cant_choose_overload_function=04057_E_¥¢®§¬®¦­® ®¯à¥¤¥«¨âì, ª®â®àãî ¨§ ¯¥à¥£à㦥­­ëå ä㭪樨 ¢ë§ë¢ âì
+% ‚맮¢ ¯¥à¥£à㦥­­®© ä㭪樨 ᮠᯨ᪮¬ ¯ à ¬¥â஢, ª®â®àë© ­¥ ᮮ⢥âáâ¢ã¥â ­¨
+% ®¤­®© ¨§ ®¡ê¥­­ëå ä㭪権.  ¯à¨¬¥à, ¥á«¨ ®¡ê¥­ë ä㭪樨 á ¯ à ¬¥âà ¬¨
+% ⨯  \var{word} ¨ \var{longint},   ¢ë§®¢ ¯à®¨§¢®¤¨âáï á ¯ à ¬¥â஬ ⨯ 
+% \var{integer}.
+type_e_illegal_count_var=04058_E_¥¢¥à­ ï ¯¥à¥¬¥­­ ï áç¥â稪 
+% ’¨¯ ¯¥à¥¬¥­­®© ¤«ï 横«  \var{for} ¤®«¦¥­ ¡ëâì ¯®à浪®¢ë¬.
+% ‚¥é¥á⢥­­ë¥ ¨ áâப®¢ë¥ â¨¯ë ­¥ ¤®¯ã᪠îâáï.
+type_w_double_c_varargs=04059_W_‚¥é¥á⢥­­ ï ª®­áâ ­â  ¯à¥®¡à §®¢ ­  ¢ double ¤«ï ä-樨 C á ¯¥à¥¬¥­­ë¬ ç¨á«®¬ ¯ à ¬¥â஢
+% ‚ ï§ëª¥ C ¢¥é¥á⢥­­ë¥ ª®­áâ ­âë ¯® 㬮«ç ­¨î ¨¬¥îâ ⨯ double. ®í⮬㠯ਠ¯¥à¥¤ ç¥
+% ¢¥é¥á⢥­­®© ª®­áâ ­âë ¢ äã­ªæ¨î ­  C á ¯¥à¥¬¥­­ë¬ ç¨á«®¬  à£ã¬¥­â®¢ FPC
+% ¯® 㬮«ç ­¨î ¯à¥®¡à §ã¥â ¥¥ ¢ double. …᫨ íâ® ¯®¢¥¤¥­¨¥ ­¥¦¥« â¥«ì­®,
+% ¯à¨¢¥¤¨â¥ ª®­áâ ­âã ª ­ã¦­®¬ã ⨯ã ®.
+type_e_class_or_cominterface_type_expected=04060_E_Ž¦¨¤ ¥âáï ⨯ ª« áá  ¨«¨ COM-¨­â¥à䥩á , ­® ¯®«ã祭® "$1"
+% ¥ª®â®àë¥ ®¯¥à â®àë, â ª¨¥ ª ª AS, ¯à¨¬¥­¨¬ë ⮫쪮 ª ª« áá ¬ ¨«¨ COM-¨­â¥à䥩ᠬ.
+type_e_no_const_packed_array=04061_E_Š®­áâ ­â­ë¥ 㯠ª®¢ ­­ë¥ ¬ áá¨¢ë ¯®ª  ­¥ ¯®¤¤¥à¦¨¢ îâáï
+% ¥«ì§ï ®¡êâì ª®­áâ ­âã ⨯  (¯®¡¨â­®)㯠ª®¢ ­­ë© ¬ áᨢ.
+type_e_got_expected_packed_array=04062_E_¥á®¢¯ ¤¥­¨¥ ⨯   à£ã¬¥­â  no. $1: ®«ã祭® "$2" ®¦¨¤ «®áì "(Bit)Packed Array"
+% Š®¬¯¨«ïâ®à ®¦¨¤ ¥â (¯®¡¨â­®)㯠ª®¢ ­­ë© ¬ áᨢ ¢ ª ç¥á⢥ 㪠§ ­­®£® ¯ à ¬¥âà .
+type_e_got_expected_unpacked_array=04063_E_¥á®¢¯ ¤¥­¨¥ ⨯   à£ã¬¥­â  no. $1: ®«ã祭® "$2" ®¦¨¤ «®áì "(not packed) Array"
+% Š®¬¯¨«ïâ®à ®¦¨¤ ¥â ®¡ëç­ë© (­¥ã¯ ª®¢ ­­ë©) ¬ áᨢ ¢ ª ç¥á⢥ 㪠§ ­­®£® ¯ à ¬¥âà .
+type_e_no_packed_inittable=04064_E_«¥¬¥­âë 㯠ª®¢ ­­®£® ¬ áᨢ  ­¥ ¬®£ãâ ¨¬¥âì ⨯, âॡãî騩 ¨­¨æ¨ «¨§ æ¨¨
+% “¯ ª®¢ ­­ë¥ ¬ áᨢë á ⨯ ¬¨, âॡãî騬¨ ¨­¨æ¨ «¨§ æ¨î (â ª¨¬¨ ª ª ansistring, ¨«¨ § ¯¨á¨, ᮤ¥à¦ é¨¥
+% ansistring), ¯®ª  ­¥ ¯®¤¤¥à¦¨¢ îâáï.
+type_e_no_const_packed_record=04065_E_Š®­áâ ­â­ë¥ 㯠ª®¢ ­­ë¥ § ¯¨á¨ ¨ ®¡ê¥ªâë ¯®ª  ­¥ ¯®¤¤¥à¦¨¢ îâáï
+% ‚ ­ áâ®ï饥 ¢à¥¬ï ­¥«ì§ï ®¡êâì ª®­áâ ­âã ⨯  (¯®¡¨â­®)㯠ª®¢ ­­ ï § ¯¨áì/®¡ê¥ªâ.
+type_w_untyped_arithmetic_unportable=04066_W_€à¨ä¬¥â¨ª  "$1" ­¥â¨¯¨§¨à®¢ ­­ëå 㪠§ â¥«¥© ­¥á®¢¬¥á⨬  á ०¨¬®¬ {$T+}, ¯à¥¤« £ ¥âáï ¯à¨¢¥¤¥­¨¥ ⨯ 
+% ‘«®¦¥­¨¥/¢ëç¨â ­¨¥ ­¥â¨¯¨§¨à®¢ ­­ëå 㪠§ â¥«¥© ¬®¦¥â à ¡®â âì ¯®-¤à㣮¬ã ¢ ०¨¬¥ \var{\{\$T+\}},
+% ¯à¨¢¥¤¨â¥ ⨯ ª ⨯¨§¨à®¢ ­­®¬ã 㪠§ â¥«î.
+type_e_cant_take_address_of_local_subroutine=04076_E_¥«ì§ï ¢§ïâì  ¤à¥á ¯à®æ¥¤ãàë, ¯®¬¥ç¥­­®© ª ª «®ª «ì­ ï
+% ‚§ï⨥  ¤à¥á  ¯à®æ¥¤ãàë, ¯®¬¥ç¥­­®© ª ª «®ª «ì­ ï, ­¥¢®§¬®¦­®.
+type_e_cant_export_local=04077_E_à®æ¥¤ãà , ®â¬¥ç¥­­ ï ª ª «®ª «ì­ ï, ­¥ ¬®¦¥â ¡ëâì íªá¯®àâ¨à®¢ ­  ¨§ ¬®¤ã«ï
+% à®æ¥¤ãà , ®â¬¥ç¥­­ ï ª ª «®ª «ì­ ï, ­¥ ¬®¦¥â ¡ëâì íªá¯®àâ¨à®¢ ­  ¨§ ¬®¤ã«ï.
+type_e_not_automatable=04078_E_’¨¯ ­¥  ¢â®¬ â¨§¨à㥬ë©: "$1"
+% ‚ ª ç¥á⢥  ¢â®¬ â¨§¨à®¢ ­­ëå ¤®¯ã᪠îâáï byte, integer, longint, smallint, currency, single, double,
+% ansistring, widestring, tdatetime, variant, olevariant, wordbool ¨ ¢á¥ ¨­â¥à䥩á­ë¥ ⨯ë.
+type_h_convert_add_operands_to_prevent_overflow=04079_H_ਢ¥¤¥­¨¥ ®¯¥à ­¤®¢ ª "$1" ¯¥à¥¤ á«®¦¥­¨¥¬ ¯à¥¤®â¢à â¨â ®è¨¡ª¨ ¯¥à¥¯®«­¥­¨ï.
+% ‘«®¦¥­¨¥ ¬®¦¥â ¢ë§ë¢ âì ¯¥à¥¯®«­¥­¨¥. ’.ª. १ã«ìâ â ¯à¥®¡à §ã¥âáï ¢ ⨯ ¡®«ì襣® à §¬¥à ,
+% ¯¥à¥¯®«­¥­¨ï ¬®¦­® ¨§¡¥¦ âì, ¯à¨¢¥¤ï ®¯¥à ­¤ë ª ⨯ã १ã«ìâ â  ¯¥à¥¤ á«®¦¥­¨¥¬.
+type_h_convert_sub_operands_to_prevent_overflow=04080_H_ਢ¥¤¥­¨¥ ®¯¥à ­¤®¢ ª "$1" ¯¥à¥¤ ¢ëç¨â ­¨¥¬ ¯à¥¤®â¢à â¨â ®è¨¡ª¨ ¯¥à¥¯®«­¥­¨ï.
+% ‚ëç¨â ­¨¥ ¬®¦¥â ¢ë§ë¢ âì ¯¥à¥¯®«­¥­¨¥. ’.ª. १ã«ìâ â ¯à¥®¡à §ã¥âáï ¢ ⨯ ¡®«ì襣® à §¬¥à ,
+% ¯¥à¥¯®«­¥­¨ï ¬®¦­® ¨§¡¥¦ âì, ¯à¨¢¥¤ï ®¯¥à ­¤ë ª ⨯ã १ã«ìâ â  ¯¥à¥¤ ¢ëç¨â ­¨¥¬.
+type_h_convert_mul_operands_to_prevent_overflow=04081_H_ਢ¥¤¥­¨¥ ®¯¥à ­¤®¢ ª "$1" ¯¥à¥¤ 㬭®¦¥­¨¥¬ ¯à¥¤®â¢à â¨â ®è¨¡ª¨ ¯¥à¥¯®«­¥­¨ï.
+% “¬­®¦¥­¨¥ ¬®¦¥â ¢ë§ë¢ âì ¯¥à¥¯®«­¥­¨¥. ’.ª. १ã«ìâ â ¯à¥®¡à §ã¥âáï ¢ ⨯ ¡®«ì襣® à §¬¥à ,
+% ¯¥à¥¯®«­¥­¨ï ¬®¦­® ¨§¡¥¦ âì, ¯à¨¢¥¤ï ®¯¥à ­¤ë ª ⨯ã १ã«ìâ â  ¯¥à¥¤ 㬭®¦¥­¨¥¬.
+type_w_pointer_to_signed=04082_W_ਢ¥¤¥­¨¥ 㪠§ â¥«¥© ª æ¥«ë¬ á® §­ ª®¬ ¬®¦¥â ¯à¨¢®¤¨âì ª ®è¨¡ª ¬ áà ¢­¥­¨ï ¨ ¢ë室㠧  ¤¨ ¯ §®­, ¨á¯®«ì§ã©â¥ ¡¥§§­ ª®¢ë© ⨯.
+% ‚¨àâã «ì­®¥  ¤à¥á­®¥ ¯à®áâà ­á⢮ ­  32-¡¨â­ëå á¨á⥬ å ¨¬¥¥â ¤¨ ¯ §®­ ®â \$00000000 ¤® \$ffffffff.
+% Œ­®£¨¥ ®¯¥à æ¨®­­ë¥ á¨áâ¥¬ë ¯®§¢®«ïî⠢뤥«ïâì ¯ ¬ïâì á¢ëè¥ \$80000000, ­ ¯à¨¬¥à, Windows ¨ Linux
+% ¤®¯ã᪠îâ 㪠§ â¥«¨ ¢ ¤¨ ¯ §®­¥ ®â \$0000000 ¤® \$bfffffff. …᫨ ¯à¨¢®¤¨âì 㪠§ â¥«¨ ª §­ ª®¢ë¬ ⨯ ¬,
+% ¬®£ãâ ¢®§­¨ª âì ®è¨¡ª¨ ¯¥à¥¯®«­¥­¨ï ¨ ¤¨ ¯ §®­ , ªà®¬¥ ⮣®, \$80000000 < \$7fffffff.
+% â® ¬®¦¥â ¢ë§ë¢ âì á«ãç ©­ë¥ ®è¨¡ª¨ ¢ ª®¤¥ ­ ¯®¤®¡¨¥ "if p>q".
+type_interface_has_no_guid=04083_E_’¨¯ ¨­â¥àä¥©á  $1 ­¥ ¨¬¥¥â GUID
+% ਠ¨á¯®«ì§®¢ ­¨¨ ®¯¥à â®à  as ­ã¦­ë© ¨­â¥à䥩á, â.¥ ¯à ¢ë© ®¯¥à ­¤ ®¯¥à â®à  as,
+% ¤®«¦¥­ ¨¬¥âì ¯à ¢¨«ì­ë© GUID.
+type_e_invalid_objc_selector_name=04084_E_¥¢¥à­®¥ ¨¬ï ᥫ¥ªâ®à 
+% ‘¥«¥ªâ®à Objective-C ­¥ ¬®¦¥â ¡ëâì ¯ãáâë¬, ®­ ¤®«¦¥­ ¡ëâì ¨¤¥­â¨ä¨ª â®à®¬ «¨¡® ®¤¨­®ç­ë¬ ¤¢®¥â®ç¨¥¬,
+% ¨, ¥á«¨ ®­ ᮤ¥à¦¨â ¤¢®¥â®ç¨¥, â® ¤®«¦¥­ ¤¢®¥â®ç¨¥¬ ¨ § ª ­ç¨¢ âìáï.
+type_e_expected_objc_method_but_got=04085_E_Ž¦¨¤ ¥âáï ¬¥â®¤ Objective-C, ­® ¯®«ã祭® $1
+% ‘¥«¥ªâ®à ¬®¦¥â ¡ëâì ᮧ¤ ­ ⮫쪮 ¤«ï ¬¥â®¤®¢ Objective-C, ­¨ª ª®© ¤à㣮© ⨯
+% ¯à®æ¥¤ãà/ä㭪権/¬¥â®¤®¢ ­¥ ¤®¯ãá⨬.
+type_e_expected_objc_method=04086_E_Ž¦¨¤ ¥âáï ¬¥â®¤ Objective-C ¨«¨ ª®­áâ ­â­®¥ ¨¬ï ¬¥â®¤ 
+% ‘¥«¥ªâ®à ¬®¦¥â ¡ëâì ᮧ¤ ­ ⮫쪮 ¤«ï ¬¥â®¤®¢ Objective-C, «¨¡® ¯ã⥬ 㪠§ ­¨ï ¨¬¥­¨
+% ¢ ¢¨¤¥ áâப®¢®© ª®­áâ ­âë, «¨¡® á ¨á¯®«ì§®¢ ­¨ï ¨¤¥­â¨ä¨ª â®à  ¬¥â®¤  Objective-C,
+% ¤¥©á⢨⥫쭮£® ¢ ⥪ã饩 ®¡« á⨠¢¨¤¨¬®áâ¨.
+type_e_no_type_info=04087_E_ˆ­ä®à¬ æ¨ï ® ⨯¥ ­¥¤®áâ㯭  ¤«ï í⮣® ⨯ 
+% ˆ­ä®à¬ æ¨ï ® ⨯¥ ­¥ £¥­¥à¨àã¥âáï ¤«ï ­¥ª®â®àëå ⨯®¢, â ª¨å ª ª ¯¥à¥ç¨á«¥­¨ï á à §à뢠¬¨
+% ¢ ¤¨ ¯ §®­¥ §­ ç¥­¨© (¢ª«îç ï ¯¥à¥ç¨á«¥­¨ï, ã ª®â®àëå ­¨¦­ïï £à ­¨æ  ¤¨ ¯ §®­  ®â«¨ç ¥âáï ®â
+% ­ã«ï).
+type_e_ordinal_or_string_expr_expected=04088_E_’ॡã¥âáï ¢ëà ¦¥­¨¥ ¯®à浪®¢®£® ¨«¨ áâப®¢®£® ⨯ 
+% ‚ëà ¦¥­¨¥ ¤®«¦­® ¨¬¥âì ¯®à浪®¢ë© ¨«¨ áâப®¢ë© ⨯.
+type_e_string_expr_expected=04089_E_’ॡã¥âáï áâப®¢®¥ ¢ëà ¦¥­¨¥
+% ‚ëà ¦¥­¨¥ ¤®«¦­® ¨¬¥âì áâப®¢ë© ⨯.
+% \end{description}
+#
+# Symtable
+#
+# 05064 is the last used one
+#
+% \section{Symbol handling}
+% „ ­­ë© à §¤¥« ᮤ¥à¦¨â á®®¡é¥­¨ï, ®â­®áï騥áï ª ®¡à ¡®âª¥ ᨬ¢®«®¢,
+% â.¥. ¢á¥£®, çâ® á¢ï§ ­® á ¨¬¥­ ¬¨ ¯à®æ¥¤ãà ¨ ¯¥à¥¬¥­­ëå.
+% \begin{description}
+sym_e_id_not_found=05000_E_ˆ¤¥­â¨ä¨ª â®p "$1" ­¥ ­ ©¤¥­
+% „ ­­ë© ᨬ¢®« ­¥¨§¢¥á⥭ ª®¬¯¨«ïâ®àã. Ž¡ëç­® ¯à®¨á室¨â ¯à¨ ®è¨¡ª å ­ ¯¨á ­¨ï
+% ¨¬¥­¨ ¯¥à¥¬¥­­®© ¨«¨ ¯à®æ¥¤ãàë, ¨«¨ ¥á«¨ ¢ë § ¡ë«¨ ®¡êâì
+% ¯¥à¥¬¥­­ãî.
+sym_f_internal_error_in_symtablestack=05001_F_‚­yâp¥­­ïï ®è¨¡ª  ¢ SymTableStack()
+% An internal error occurred in the compiler; If you encounter such an error,
+% please contact the developers and try to provide an exact description of
+% the circumstances in which the error occurs.
+sym_e_duplicate_id=05002_E_ˆ¤¥­â¨ä¨ª â®p "$1" ¯®¢â®àï¥âáï
+% “ª § ­­ë© ¨¤¥­â¨ä¨ª â®à 㦥 ¡ë« ®¡ê¥­ ¢ ⥪ã饩 ®¡« áâ¨.
+sym_h_duplicate_id_where=05003_H_ˆ¤¥­â¨ä¨ª â®p y¦¥ ®¯p¥¤¥«¥­ ¢ $1 (áâp®ª  $2)
+% ˆ¤¥­â¨ä¨ª â®à 㦥 ¡ë« ®¡ê¥­ ¢ 㪠§ ­­®© ®¡« áâ¨.
+sym_e_unknown_id=05004_E_H¥¨§¢¥áâ­ë© ¨¤¥­â¨ä¨ª â®p "$1"
+% “ª § ­­ë© ¨¤¥­â¨ä¨ª â®à ­¥ ¡ë« ®¡ê¥­, «¨¡® ¨á¯®«ì§ã¥âáï §  ¯à¥¤¥« ¬¨
+% ®¡« áâ¨, ¤«ï ª®â®à®© ®­ ¡ë« ®¯à¥¤¥«¥­.
+sym_e_forward_not_resolved=05005_E_Žâáãâáâ¢ã¥â ॠ«¨§ æ¨ï ¯à®æ¥¤ãàë ¨«¨ ¬¥â®¤  "$1"
+% Œ®¦¥â ¯à®¨á室¨âì ¢ ¤¢ãå á«ãç ïå:
+% \begin{itemize}
+% \item …᫨ äã­ªæ¨ï ®¡ê¥­  (¢ ᥪ樨 \var{interface}, «¨¡®
+% á ¤¨à¥ªâ¨¢®© \var{forward}, ­® ­¥ ॠ«¨§®¢ ­ .
+% \item ਠáá뫪¥ ­  ⨯, ª®â®àë© ­¥ ®¡ê¥­ ¢ ⥪ã饬 ¡«®ª¥ \var{type}.
+% \end{itemize}
+sym_e_error_in_type_def=05007_E_Žè¨¡ª  ¢ ®¯p¥¤¥«¥­¨¨ ⨯ 
+% Žè¨¡ª  ¯à¨ ®¯à¥¤¥«¥­¨¨ ­®¢®£® ⨯  ¬ áᨢ :
+% \item Ž¤­  ¨§ £à ­¨æ ¤¨ ¯ §®­  ï¥âáï ®è¨¡®ç­®©.
+%  ¯à¨¬¥à, \var{Array [1..1.25]} ¢ë§®¢¥â ¤ ­­ãî ®è¨¡ªã.
+sym_e_forward_type_not_resolved=05009_E_ ­­¥¥ ®¡ê¥­¨¥ ⨯  "$1" ­¥ à¥è¥­®
+% ‘¨¬¢®« ¡ë« ®¡ê¥­ § à ­¥¥, ­® ®¯à¥¤¥«¥­¨¥ ¤«ï ­¥£® ­¥ ¡ë«® ®¡­ à㦥­®.
+sym_e_only_static_in_static=05010_E_’®«ìª® áâ â¨ç¥áª¨¥ ¯¥à¥¬¥­­ë¥ ¬®£ã⠨ᯮ«ì§®¢ âìáï ¢ áâ â¨ç¥áª¨å ¬¥â®¤ å ¨«¨ ¢­¥ ¬¥â®¤®¢
+% ‘â â¨ç¥áª¨© ¬¥â®¤ ®¡ê¥ªâ  ¨¬¥¥â ¤®áâ㯠⮫쪮 ª áâ â¨ç¥áª¨¬ ¯¥à¥¬¥­­ë¬.
+sym_f_type_must_be_rec_or_class=05012_F_Ž¦¨¤ ¥âáï ⨯ record ¨«¨ class
+% ¥à¥¬¥­­ ï ¨«¨ ¢ëà ¦¥­¨¥ ¨¬¥¥â ⨯, ®â«¨ç­ë© ®â \var{record} ¨«¨ \var{class}.
+sym_e_no_instance_of_abstract_object=05013_E_ª§¥¬¯«ïàë ª« áᮢ ¨«¨ ®¡ê¥ªâ®¢ á  ¡áâp ªâ­ë¬ ¬¥â®¤®¬ ­¥ ¤®¯ã᪠îâáï
+% ®¯ë⪠ ᮧ¤ âì íª§¥¬¯«ïà ª« áá  á  ¡áâà ªâ­ë¬ ¬¥â®¤®¬, ª®â®àë© ­¥ ¡ë« ¯¥à¥ªàëâ.
+sym_w_label_not_defined=05014_W_Œ¥âª  "$1" ­¥ ®¯p¥¤¥«¥­ 
+% Œ¥âª  ¡ë«  ®¡ê¥­ , ­® ­¥ ¡ë«  ®¯à¥¤¥«¥­ .
+sym_e_label_used_and_not_defined=05015_E_Œ¥âª  "$1" ¨á¯®«ì§ã¥âáï, ­® ­¥ ®¯à¥¤¥«¥­ 
+% Œ¥âª  ¡ë«  ®¡ê¥­  ¨ ¨á¯®«ì§®¢ ­ , ­® ­¥ ¡ë«  ®¯à¥¤¥«¥­ .
+sym_e_ill_label_decl=05016_E_H¥¢¥p­®¥ ®¡ê¥­¨¥ ¬¥âª¨
+% நá室¨â, ¥á«¨ ¬¥âª  ®¡ê¥­  ¢­¥ ¯à®æ¥¤ãàë ¨«¨ ä㭪樨; í⮣® ­¨ª®£¤ 
+% ­¥ ¤®«¦­® á«ãç âìáï.
+sym_e_goto_and_label_not_supported=05017_E_GOTO ¨ LABEL ­¥ ¯®¤¤¥p¦¨¢ îâáï (¨á¯®«ì§y©â¥ ª«îç -Sg)
+% ணࠬ¬ã, ᮤ¥à¦ éãî ¬¥âª¨ ¨ ¯¥à¥å®¤ë \var{goto}, ­¥®¡å®¤¨¬® ª®¬¯¨«¨à®¢ âì
+% á ª«î箬 \var{-Sg}. ® 㬮«ç ­¨î, ¬¥âª¨ ¨ ¯¥à¥å®¤ë ­¥ ¯®¤¤¥à¦¨¢ îâáï.
+sym_e_label_not_found=05018_E_Œ¥âª  ­¥ ­ ©¤¥­ 
+% ‚áâà¥â¨«®áì \var{goto label}, ­® ¬¥âª  ­¥ ¡ë«  ®¡ê¥­ .
+sym_e_id_is_no_label_id=05019_E_ˆ¤¥­â¨ä¨ª â®p ­¥ ï¥âáï ¬¥âª®©
+% ˆ¤¥­â¨ä¨ª â®à, á«¥¤ãî騩 §  \var{goto}, ­¥ ¨¬¥¥â ⨯ ¬¥âª¨.
+sym_e_label_already_defined=05020_E_®¢â®p­®¥ ®¯p¥¤¥«¥­¨¥ ¬¥âª¨
+% ®¯ë⪠ ®¯à¥¤¥«¨âì ¬¥âªã ¤¢ ¦¤ë. Œ¥âª  ¬®¦¥â ¡ëâì ®¯à¥¤¥«¥­  ⮫쪮 ®¤¨­ à §.
+sym_e_ill_type_decl_set=05021_E_¥¢¥p­®¥ ®¡ê¥­¨¥ ⨯  í«¥¬¥­â®¢ ¬­®¦¥á⢠
+% Ž¡ê¥­¨¥ ¬­®¦¥á⢠ ᮤ¥à¦¨â ­¥¤®¯ãá⨬®¥ ®¯à¥¤¥«¥­¨¥ ⨯ .
+sym_e_class_forward_not_resolved=05022_E_ ­¥¥ ®¡ê¥­¨¥ ª« áá  "$1" ­¥ à¥è¥­®
+% Š« áá ¡ë« ®¡ê¥­, ­® ­¥ ¡ë« ॠ«¨§®¢ ­.
+sym_n_unit_not_used=05023_H_Œ®¤ã«ì "$1" ­¥ ¨á¯®«ì§ã¥âáï ¢ $2
+% Œ®¤ã«ì, 㪠§ ­­ë© ¢ ᥪ樨 \var{uses}, ­¥ ¨á¯®«ì§ã¥âáï.
+sym_h_para_identifier_not_used=05024_H_ p ¬¥âp "$1" ­¥ ¨á¯®«ì§y¥âáï
+% ˆ¤¥­â¨ä¨ª â®à ¡ë« ®¡ê¥­ («®ª «ì­® ¨«¨ £«®¡ «ì­®), ­®
+% ­¥ ¡ë« ¨á¯®«ì§®¢ ­.
+sym_n_local_identifier_not_used=05025_N_‹®ª «ì­ ï ¯¥p¥¬¥­­ ï "$1" ­¥ ¨á¯®«ì§y¥âáï
+% ¥à¥¬¥­­ ï ®¡ê¥­ , ­® ­¥ ¨á¯®«ì§®¢ ­  ¢ ॠ«¨§ æ¨¨ ¯à®æ¥¤ãàë
+% ¨«¨ ä㭪樨.
+sym_h_para_identifier_only_set=05026_H_ à ¬¥âà-§­ ç¥­¨¥ "$1" ¯à¨á¢®¥­, ­® ­¥ ¨á¯®«ì§®¢ ­
+%  à ¬¥âàã ¯à¨á¢®¥­® §­ ç¥­¨¥, ª®â®à®¥ ¢ ¤ «ì­¥©è¥¬ ­¨£¤¥ ­¥ ¨á¯®«ì§ã¥âáï.
+sym_n_local_identifier_only_set=05027_N_‹®ª «ì­ ï ¯¥à¥¬¥­­ ï "$1" ¯à¨á¢®¥­ , ­® ­¥ ¨á¯®«ì§®¢ ­ 
+% ‹®ª «ì­®© ¯¥à¥¬¥­­®© ¯à¨á¢®¥­® §­ ç¥­¨¥, ª®â®à®¥ ¢ ¤ «ì­¥©è¥¬ ­¨£¤¥ ­¥ ¨á¯®«ì§ã¥âáï.
+sym_h_local_symbol_not_used=05028_H_‹®ª «ì­ë© ᨬ¢®« $1 "$2" ­¥ ¨á¯®«ì§ã¥âáï
+% ‹®ª «ì­ë© ᨬ¢®« ­¥ ¨á¯®«ì§ã¥âáï.
+sym_n_private_identifier_not_used=05029_N_Private ¯®«¥ "$1.$2" ­¥ ¨á¯®«ì§ã¥âáï
+% “ª § ­­®¥ private ¯®«¥ ®¯à¥¤¥«¥­®, ­® ­¥ ¨á¯®«ì§ã¥âáï ­¨£¤¥ ¢ ª®¤¥.
+sym_n_private_identifier_only_set=05030_N_Private ¯®«¥ "$1.$2" ¯à¨á¢®¥­®, ­® ­¥ ¨á¯®«ì§®¢ ­®
+% “ª § ­­®¥ private ¯®«¥ ®¯à¥¤¥«¥­® ¨ ¥¬ã ¯à¨á¢®¥­® §­ ç¥­¨¥, ª®â®à®¥ ­¨£¤¥ ­¥ ç¨â ¥âáï.
+sym_n_private_method_not_used=05031_N_Private ¬¥â®¤ "$1.$2" ­¥ ¨á¯®«ì§ã¥âáï
+% “ª § ­­ë© private ¬¥â®¤ ®¯à¥¤¥«¥­, ­® ­¥ ¨á¯®«ì§ã¥âáï ­¨£¤¥ ¢ ª®¤¥.
+sym_e_set_expected=05032_E_Ž¦¨¤ ¥âáï ⨯ ¬­®¦¥á⢠
+% ¥à¥¬¥­­ ï ¨«¨ ¢ëà ¦¥­¨¥ ¨¬¥¥â ⨯, ®â«¨ç­ë© ®â \var{set}. â® á«ãç ¥âáï ¢
+% ¢ëà ¦¥­¨ïå \var{in}.
+sym_w_function_result_not_set=05033_W_¥§y«ìâ â äy­ªæ¨¨, ¢®§¬®¦­®, ­¥ ¯à¨á¢®¥­
+% ।ã¯à¥¦¤¥­¨¥ ¢ë¤ ¥âáï, ¥á«¨ ª®¬¯¨«ïâ®à ¯®« £ ¥â, ç⮠१ã«ìâ â, ¢®§¢à é ¥¬ë© ä㭪樥©,
+% ­¥ ¯à¨á¢®¥­. …᫨ äã­ªæ¨ï ­ ¯¨á ­  ­   áᥬ¡«¥à¥, ¨«¨ ᮤ¥à¦¨â  áᥬ¡«¥à­ë© ¡«®ª,
+% ¯à¥¤ã¯à¥¦¤¥­¨¥ ­¥ ¢ë¤ ¥âáï.
+sym_w_wrong_C_pack=05034_W_’¨¯ "$1" ­¥ª®à४⭮ ¢ë஢­¥­ ¢ ⥪ã饩 § ¯¨á¨ ¤«ï ï§ëª  C
+% Œ áᨢë á à §¬¥à ¬¨, ­¥ ªà â­ë¬¨ 4, ¡ã¤ãâ ­¥¢¥à­® ¢ë஢­¥­ë ¢ áâàãªâãà å ï§ëª  C.
+sym_e_illegal_field=05035_E_H¥¨§¢¥áâ­®¥ ¯®«¥ § ¯¨á¨ "$1"
+% “ª § ­­®¥ ¯®«¥ ®âáãâáâ¢ã¥â ¢ ®¯à¥¤¥«¥­¨¨ § ¯¨á¨.
+sym_w_uninitialized_local_variable=05036_W_‹®ª «ì­ ï ¯¥p¥¬¥­­ ï "$1" ­¥ ¨­¨æ¨ «¨§¨p®¢ ­ 
+% ‘®®¡é¥­¨¥ ¢ë¤ ¥âáï, ª®£¤  ª®¬¯¨«ïâ®à áç¨â ¥â, çâ® «®ª «ì­ ï ¯¥à¥¬¥­­ ï ¡ã¤¥â
+% ¨á¯®«ì§®¢ ­  (â.¥. ¢áâà¥â¨« áì ¢ ¯à ¢®© ç á⨠¢ëà ¦¥­¨ï), ­® ­¥ ¡ë« 
+% ¨­¨æ¨ «¨§¨à®¢ ­  (â.¥. ­¥ ¯®ï¢«ï« áì à ­¥¥ ¢ «¥¢®© ç á⨠¯à¨á¢ ¨¢ ­¨ï).
+sym_w_uninitialized_variable=05037_W_¥p¥¬¥­­ ï "$1" ­¥ ¨­¨æ¨ «¨§¨p®¢ ­ 
+% ‘®®¡é¥­¨¥ ¢ë¤ ¥âáï, ª®£¤  ª®¬¯¨«ïâ®à áç¨â ¥â, çâ® ¯¥à¥¬¥­­ ï ¡ã¤¥â ¨á¯®«ì§®¢ ­ 
+% (â.¥. ¢áâà¥â¨« áì ¢ ¯à ¢®© ç á⨠¢ëà ¦¥­¨ï), ­® ­¥ ¡ë«  ¨­¨æ¨ «¨§¨à®¢ ­  (â.¥.
+% ­¥ ¯®ï¢«ï« áì à ­¥¥ ¢ «¥¢®© ç á⨠¯à¨á¢ ¨¢ ­¨ï).
+sym_e_id_no_member=05038_E_ˆ¤¥­â¨ä¨ª â®p ­¥ ®¯à¥¤¥«ï¥â í«¥¬¥­â "$1"
+% ‘®®¡é¥­¨¥ ¢ë¤ ¥âáï ¯à¨ ¯®¯ë⪥ ¤®áâ㯠 ª ­¥®¯à¥¤¥«¥­­®¬ã ¯®«î § ¯¨á¨
+% ¨«¨ ®¡ê¥ªâ , «¨¡® ¬¥â®¤ã.
+sym_h_param_list=05039_H_H ©¤¥­® ®¯p¥¤¥«¥­¨¥: $1
+% ਠ¨á¯®«ì§®¢ ­¨¨ ª«îç  \var{-vh}, ¥á«¨ ­¥ ­ ©¤¥­  ¯¥à¥£à㦥­­ ï ¯à®æ¥¤ãà ,
+% ¯¥à¥ç¨á«ïîâáï ¢á¥ ¯®¤å®¤ï騥 ¯¥à¥£à㦥­­ë¥ ¯à®æ¥¤ãàë ¨ ᯨ᪨ ¨å
+% ¯ à ¬¥â஢.
+sym_e_segment_too_large=05040_E_‘«¨èª®¬ ¡®«ì让 í«¥¬¥­â ¤ ­­ëå
+% ‚뤠¥âáï ¯à¨ ¯®¯ë⪥ ®¡êâì í«¥¬¥­â ¤ ­­ëå, à §¬¥à ª®â®à®£® ¯à¥¢ëè ¥â
+% ãáâ ­®¢«¥­­ë© ¯à¥¤¥« (2 ƒ ¤«ï ¯à®æ¥áá®à®¢ 80386+/68020+)
+sym_e_no_matching_implementation_found=05042_E_¥ ­ ©¤¥­  ¯®¤å®¤ïé ï ॠ«¨§ æ¨ï ¬¥â®¤  ¨­â¥àä¥©á  "$1"
+% ¥ ­ ©¤¥­ ¬¥â®¤, ª®â®àë© ¬®£ ¡ë ॠ«¨§®¢ âì 㪠§ ­­ë© ¬¥â®¤ ¨­â¥à䥩á .
+% ஢¥àìâ¥ â¨¯ë  à£ã¬¥­â®¢ ¨ â¨¯ë ¢®§¢à é ¥¬ëå §­ ç¥­¨©.
+sym_w_deprecated_symbol=05043_W_‘¨¬¢®« "$1" ãáâ à¥«
+% ˆá¯®«ì§®¢ ­ ᨬ¢®« (¯¥à¥¬¥­­ ï, ¯à®æ¥¤ãà  ¨ â.¯.), ª®â®àë© ¡ë«
+% ®¡ê¥­ ª ª \var{deprecated}. ’ ª®© ãáâ à¥¢è¨© ᨬ¢®« ¬®¦¥â ¡ëâì
+% ­¥¤®áâ㯥­ ¢ ­®¢ëå ¢¥àá¨ïå ¬®¤ã«ï / ¡¨¡«¨®â¥ª¨. ® ¢®§¬®¦­®áâ¨,
+% ­ã¦­® ¨§¡¥£ âì ¨á¯®«ì§®¢ ­¨ï ãáâ à¥¢è¨å ᨬ¢®«®¢.
+sym_w_non_portable_symbol=05044_W_‘¨¬¢®« "$1" ­¥ ¯®àâ ¡¥«¥­
+% ˆá¯®«ì§®¢ ­ ᨬ¢®« (¯¥à¥¬¥­­ ï, ¯à®æ¥¤ãà  ¨ â.¯.), ª®â®àë© ¡ë«
+% ®¡ê¥­ ª ª \var{platform}. ‡­ ç¥­¨¥, ¨á¯®«ì§®¢ ­¨¥ ¨ ¤®áâ㯭®áâì
+% â ª®£® ᨬ¢®«  § ¢¨á¨â ®â ¯« âä®à¬ë. …᫨ ¨á室­ë© ª®¤ ¤®«¦¥­ ¡ëâì
+% ¯®àâ¨à㥬ë¬, ¨á¯®«ì§®¢ âì â ª¨¥ ᨬ¢®«ë ­¥ á«¥¤ã¥â.
+sym_w_non_implemented_symbol=05055_W_‘¨¬¢®« "$1" ­¥ ॠ«¨§®¢ ­
+% ˆá¯®«ì§®¢ ­ ᨬ¢®« (¯¥à¥¬¥­­ ï, ¯à®æ¥¤ãà  ¨ â.¯.), ª®â®àë© ¡ë«
+% ®¡ê¥­ ª ª \var{unimplemented}. â®â ᨬ¢®« ®¯à¥¤¥«¥­,
+% ­® ¥é¥ ­¥ ॠ«¨§®¢ ­ ¤«ï ¤ ­­®© ¯« âä®à¬ë.
+sym_e_cant_create_unique_type=05056_E_â®â ⨯ ­¥«ì§ï ¨á¯®«ì§®¢ âì ¤«ï ®¡ê¥­¨ï ã­¨ª «ì­®£® ⨯ 
+% ਠ®¡ê¥­¨¨ ã­¨ª «ì­®£® ⨯  á ¯®¬®éìî ¢ëà ¦¥­¨ï \var{type newtype = type oldtype;}
+% ¬®¦­® ¨á¯®«ì§®¢ âì ⮫쪮 ¯à®áâë¥ â¨¯ë (¯®à浪®¢ë¥, ¢¥é¥á⢥­­ë¥ ¨ áâப®¢ë¥).
+sym_h_uninitialized_local_variable=05057_H_‹®ª «ì­ ï ¯¥à¥¬¥­­ ï "$1" ­¥ ¨­¨æ¨ «¨§¨à®¢ ­ 
+% ‘®®¡é¥­¨¥ ¢ë¤ ¥âáï, ª®£¤  ª®¬¯¨«ïâ®à áç¨â ¥â, çâ® «®ª «ì­ ï ¯¥à¥¬¥­­ ï ¡ã¤¥â
+% ¨á¯®«ì§®¢ ­  (â.¥. ¢áâà¥â¨« áì ¢ ¯à ¢®© ç á⨠¢ëà ¦¥­¨ï), ­® ­¥ ¡ë« 
+% ¨­¨æ¨ «¨§¨à®¢ ­  (â.¥. ­¥ ¯®ï¢«ï« áì à ­¥¥ ¢ «¥¢®© ç á⨠¯à¨á¢ ¨¢ ­¨ï).
+sym_h_uninitialized_variable=05058_H_¥à¥¬¥­­ ï "$1" ­¥ ¨­¨æ¨ «¨§¨à®¢ ­ 
+% ‘®®¡é¥­¨¥ ¢ë¤ ¥âáï, ª®£¤  ª®¬¯¨«ïâ®à áç¨â ¥â, çâ® ¯¥à¥¬¥­­ ï ¡ã¤¥â
+% ¨á¯®«ì§®¢ ­  (â.¥. ¢áâà¥â¨« áì ¢ ¯à ¢®© ç á⨠¢ëà ¦¥­¨ï), ­® ­¥ ¡ë« 
+% ¨­¨æ¨ «¨§¨à®¢ ­  (â.¥. ­¥ ¯®ï¢«ï« áì à ­¥¥ ¢ «¥¢®© ç á⨠¯à¨á¢ ¨¢ ­¨ï).
+sym_w_function_result_uninitialized=05059_W_¥à¥¬¥­­ ï १ã«ìâ â  ä㭪樨 ­¥ ¨­¨æ¨ «¨§¨à®¢ ­ 
+% ‘®®¡é¥­¨¥ ¢ë¤ ¥âáï, ª®£¤  ª®¬¯¨«ïâ®à áç¨â ¥â, çâ® ¯¥à¥¬¥­­ ï १ã«ìâ â 
+% ä㭪樨 ¡ã¤¥â ¨á¯®«ì§®¢ ­  (â.¥. ¢áâà¥â¨« áì ¢ ¯à ¢®© ç á⨠¢ëà ¦¥­¨ï),
+% ­® ­¥ ¡ë«  ¨­¨æ¨ «¨§¨à®¢ ­  (â.¥. ­¥ ¯®ï¢«ï« áì à ­¥¥ ¢ «¥¢®© ç áâ¨
+% ¯à¨á¢ ¨¢ ­¨ï).
+sym_h_function_result_uninitialized=05060_H_¥à¥¬¥­­ ï १ã«ìâ â  ä㭪樨 ­¥ ¨­¨æ¨ «¨§¨à®¢ ­ 
+% ‘®®¡é¥­¨¥ ¢ë¤ ¥âáï, ª®£¤  ª®¬¯¨«ïâ®à áç¨â ¥â, çâ® ¯¥à¥¬¥­­ ï १ã«ìâ â 
+% ä㭪樨 ¡ã¤¥â ¨á¯®«ì§®¢ ­  (â.¥. ¢áâà¥â¨« áì ¢ ¯à ¢®© ç á⨠¢ëà ¦¥­¨ï),
+% ­® ­¥ ¡ë«  ¨­¨æ¨ «¨§¨à®¢ ­  (â.¥. ­¥ ¯®ï¢«ï« áì à ­¥¥ ¢ «¥¢®© ç áâ¨
+% ¯à¨á¢ ¨¢ ­¨ï).
+sym_w_identifier_only_read=05061_W_¥à¥¬¥­­ ï "$1" ç¨â ¥âáï, ­® ­¥ ¯à¨á¢®¥­ 
+% ‡­ ç¥­¨¥ ¯¥à¥¬¥­­®© áç¨â뢠¥âáï, ­® ­¨£¤¥ ­¥ ¯à¨á¢ ¨¢ ¥âáï.
+sym_h_abstract_method_list=05062_H_ ©¤¥­  ¡áâà ªâ­ë© ¬¥â®¤: $1
+% ਠ¢ë¤ ç¥ ¯à¥¤ã¯à¥¦¤¥­¨ï ® ᮧ¤ ­¨¨ ª« áá /®¡ê¥ªâ  á  ¡áâà ªâ­ë¬¨ ¬¥â®¤ ¬¨
+% íâ  ¯®¤áª §ª  ®¡«¥£ç ¥â ¯®¨áª ¯à®¡«¥¬­®£® ¬¥â®¤ .
+sym_w_experimental_symbol=05063_W_‘¨¬¢®« "$1" ï¥âáï íªá¯¥à¨¬¥­â «ì­ë¬
+% ˆá¯®«ì§®¢ ­ ᨬ¢®« (¯¥à¥¬¥­­ ï, ¯à®æ¥¤ãà  ¨ â.¯.), ª®â®àë© ¡ë«
+% ®¡ê¥­ ª ª \var{experimental}. ªá¯¥à¨¬¥­â «ì­ë¥ ᨬ¢®«ë ¬®£ãâ
+% ¨á祧­ãâì ¨«¨ ¨§¬¥­¨âì ¯®¢¥¤¥­¨¥ ¢ ¡ã¤ã饩 ¢¥àᨨ. ˆá¯®«ì§®¢ ­¨ï
+% â ª¨å ᨬ¢®«®¢ á«¥¤ã¥â ¯® ¢®§¬®¦­®á⨠¨§¡¥£ âì.
+sym_w_forward_not_resolved=05064_W_ ­¥¥ ®¡ê¥­¨¥ "$1" ­¥ à §à¥è¨«®áì, ¯à¥¤¯®« £ ¥âáï external
+% நá室¨â, ¥á«¨ äã­ªæ¨ï ¡ë«  ®¡ê¥­  ¢ ᥪ樨 \var{interface} ¬®¤ã«ï ¢ ०¨¬¥ macpas,
+% ­® ­¥ ¡ë«  ॠ«¨§®¢ ­ .
+% \end{description}
+
+#
+# Š®¤®£¥­¥à â®à
+#
+# 06049 ­®¬¥à ¯®á«¥¤­¥£® á®®¡é¥­¨ï
+#
+% \section{Code generator messages}
+%  §¤¥« ᮤ¥à¦¨â á®®¡é¥­¨ï, ª®â®àë¥ ¬®£ãâ ¡ëâì ¢ë¤ ­ë ¯à¨ ®è¨¡ª å
+% ª®¤®£¥­¥à æ¨¨.
+% \begin{description}
+cg_e_parasize_too_big=06009_E_ §¬¥p ᯨ᪠ ¯ p ¬¥âp®¢ ¯p¥¢ëè ¥â 65535 ¡ ©â
+% à®æ¥áá®à I386 ®£à ­¨ç¨¢ ¥â ᯨ᮪ ¯ à ¬¥â஢ ¤® 65535 ¡ ©â (¨§-§  ®á®¡¥­­®áâ¨
+% ¨­áâàãªæ¨¨ \var{RET})
+cg_e_file_must_call_by_reference=06012_E_” ©«®¢ë¥ ⨯ë á«¥¤ã¥â ¯¥à¥¤ ¢ âì ¯® áá뫪¥
+% ” ©«ë ­¥«ì§ï ¯¥à¥¤ ¢ âì ¯® §­ ç¥­¨î, â.¥. ®­¨ ¢á¥£¤  ¤®«¦­ë ¡ëâì ®¡ê¥­ë
+% ª ª \var{var} ¯ à ¬¥âàë.
+cg_e_cant_use_far_pointer_there=06013_E_ˆá¯®«ì§®¢ ­¨¥ FAR yª § â¥«ï §¤¥áì ­¥¤®¯ãá⨬®
+% Free Pascal ­¥ ¯®¤¤¥à¦¨¢ ¥â ¤ «ì­¨¥ 㪠§ â¥«¨, ¯®í⮬㠭¥¢®§¬®¦­® ¢§ïâì  ¤à¥á
+% ¢ëà ¦¥­¨ï, ¢ १ã«ìâ â¥ ª®â®à®£® ¯®«ãç¨âáï ¤ «ì­¨© 㪠§ â¥«ì. Š®­áâàãªæ¨ï \var{mem}
+% ï¥âáï ¯à¨¬¥à®¬ â ª®£® ¢ëà ¦¥­¨ï, ¯®í⮬ã á«¥¤ãî騩 ª®¤ ¢ë§®¢¥â ¤ ­­ãî ®è¨¡ªã:
+% \begin{verbatim}
+% var p : pointer;
+% ...
+% p:=@mem[a000:000];
+% \end{verbatim}
+cg_e_dont_call_exported_direct=06015_E_‚맮¢ EXPORT ä㭪樨 ­¥¢®§¬®¦¥­
+% ®«ìè¥ ­¥ ¨á¯®«ì§ã¥âáï.
+cg_w_member_cd_call_from_method=06016_W_‚®§¬®¦­®, ­¥¢¥à­ë© ¢ë§®¢ ª®­áâpyªâ®p  ¨«¨ ¤¥áâpyªâ®p 
+% Ž¡­ à㦥­ ¢ë§®¢ ª®­áâàãªâ®à  ¨«¨ ¤¥áâàãªâ®à  ¨§ ¬¥â®¤ . â®, ᪮॥ ¢á¥£®, ¯à¨¢¥¤¥â ª
+% ¯à®¡«¥¬ ¬, â.ª. ¤«ï ª®­áâàãªâ®à®¢/¤¥áâàãªâ®à®¢ âॡãîâáï ®á®¡ë¥ ¯ à ¬¥âàë.
+cg_n_inefficient_code=06017_N_H¥íä䥪⨢­ë© ª®¤
+%  ¯¨á ­­ ï ¢ ¬¨ ª®­áâàãªæ¨ï ª ¦¥âáï ª®¬¯¨«ïâ®à㠮祭ì ᮬ­¨â¥«ì­®©.
+cg_w_unreachable_code=06018_W_H¥¤®á⨦¨¬ë© ª®¤
+%  ¯¨á ­­ ï ª®­áâàãªæ¨ï ­¨ª®£¤  ­¥ ¡ã¤¥â ¢ë¯®«­¥­ . ਬ¥à:
+% \begin{verbatim}
+% while false do
+% begin
+% {.. code ...}
+% end;
+% \end{verbatim}
+cg_e_cant_call_abstract_method=06020_E_€¡áâp ªâ­ë¥ ¬¥â®¤ë ­¥«ì§ï ¢ë§ë¢ âì ­ ¯pï¬yî
+% €¡áâà ªâ­ë© ¬¥â®¤ ­¥«ì§ï ¢ë§¢ âì ­¥¯®á।á⢥­­®, ¢¬¥áâ® ­¥£® á«¥¤ã¥â ¢ë§ë¢ âì
+% ¯¥à¥ªà뢠î騩 ¬¥â®¤ ¯®â®¬ª , ¯®â®¬ã çâ®  ¡áâà ªâ­ë© ¬¥â®¤ ­¥ ¨¬¥¥â ॠ«¨§ æ¨¨.
+cg_d_register_weight=06027_DL_¥£¨áâp $1 ¢¥á $2 $3
+% Žâ« ¤®ç­®¥ á®®¡é¥­¨¥. ‚뢮¤¨âáï, ª®£¤  ª®¬¯¨«ïâ®à à áᬠâਢ ¥â ¢®§¬®¦­®áâì
+% à §¬¥é¥­¨ï ¯¥à¥¬¥­­ëå ¢ ॣ¨áâà å.
+cg_d_stackframe_omited=06029_DL_Š ¤à á⥪  ­¥ ᮧ¤ ­ (­¥ âॡã¥âáï)
+% ¥ª®â®àë¬ ¯à®æ¥¤ãà ¬/äã­ªæ¨ï¬ ­¥ âॡã¥âáï ¯®«­ë© ª ¤à á⥪ , ¨ ¥£® ¬®¦­® ®¯ãáâ¨âì.
+% ‘®®¡é¥­¨¥ ¢ë¢®¤¨âáï ¯à¨ ¨á¯®«ì§®¢ ­¨¨ ª«îç  \var{-vd}.
+cg_e_unable_inline_object_methods=06031_E_Œ¥â®¤ë ®¡ê¥ªâ å ¨«¨ ª« áᮢ ­¥ ¬®£ãâ ¡ëâì ¢áâà ¨¢ ¥¬ë¬¨ (inline)
+% Œ¥â®¤ë ®¡ê¥ªâ  ­¥«ì§ï ¢áâà ¨¢ âì.
+cg_e_unable_inline_procvar=06032_E_‚맮¢ë ¯à®æ¥¤ãà­ëå ¯¥à¥¬¥­­ëå ­¥ ¬®£ã£ ¡ëâì ¢áâà ¨¢ ¥¬ë¬¨ (inline)
+% ‚맮¢ ¯à®æ¥¤ãà­®© ¯¥à¥¬¥­­®© ­¥ ¬®¦¥â ¡ëâì ¢áâ஥­.
+cg_e_no_code_for_inline_stored=06033_E_H¥â ª®¤  ¤«ï inline
+% Š®¬¯¨«ïâ®à ­¥ ᬮ£ á®åà ­¨âì ª®¤ ¤«ï ¢áâà ¨¢ ¥¬®© ¯à®æ¥¤ãàë.
+cg_e_can_access_element_zero=06035_E_Hy«¥¢®© í«¥¬¥­â ansi/wide- áâp®ª¨ ­¥¤®áây¯¥­, ¨á¯®«ì§y©â¥ (set)length
+% „«ï ¨§¬¥­¥­¨ï ¤«¨­ë áâப¨ ⨯  ansi/wide/longstring á«¥¤ã¥â ¨á¯®«ì§®¢ âì
+% ¯à®æ¥¤ãàã \var{setlength},   ¤«ï ¯®«ã祭¨ï - äã­ªæ¨î \var{length}.
+cg_e_cannot_call_cons_dest_inside_with=06037_E_Š®­áâpyªâ®p ¨«¨ ¤¥áâpyªâ®p ­¥«ì§ï ¢ë§ë¢ âì ¢­yâp¨ ¢ëà ¦¥­¨© 'WITH'
+% ‚­ãâਠª®­áâàãªæ¨¨ \var{With} ¢ë§®¢ ª®­áâàãªâ®à  ¨«¨ ¤¥áâàãªâ®à  ¤«ï ®¡ê¥ªâ - à£ã¬¥­â 
+% \var{with} ­¥¢®§¬®¦¥­.
+cg_e_cannot_call_message_direct=06038_E_H¥¯®á।á⢥­­ë© ¢ë§®¢ ¬¥â®¤ -®¡p ¡®â稪  ᮡë⨩ ­¥¢®§¬®¦¥­
+% A message method handler method can't be called directly if it contains an
+% explicit self argument
+cg_e_goto_inout_of_exception_block=06039_E_¥à¥å®¤ ç¥à¥§ £à ­¨æã ¡«®ª  ¨áª«î祭¨©
+% ¥à¥å®¤ ¢­ãâàì ¡«®ª  ®¡à ¡®âª¨ ¨áª«î祭¨© \var{try..finally..end;} ¨«¨ ¨§ ­¥£® ­¥ ¤®¯ã᪠¥âáï:
+% \begin{verbatim}
+% label 1;
+%
+% ...
+%
+% try
+% if not(final) then
+% goto 1; // ¢ í⮩ áâப¥ ¡ã¤¥â ®è¨¡ª 
+% finally
+% ...
+% end;
+% 1:
+% ...
+% \end{verbatim}
+cg_e_control_flow_outside_finally=06040_E_“¯à ¢«ïî騥 ¢ëà ¦¥­¨ï (break, continue ¨ exit) ­¥¤®¯ãáâ¨¬ë ¢ ¡«®ª¥ finally
+% ˆá¯®«ì§®¢ ­¨¥ ¢ëà ¦¥­¨©, ¨§¬¥­ïîé¨å 室 ¢ë¯®«­¥­¨ï (\var{break},
+% \var{continue} ¨ \var{exit}), ­¥ ¤®¯ã᪠¥âáï
+% ¢­ãâਠ¡«®ª  finally. ‘«¥¤ãî騩 ª®¤ ¢ë§®¢¥â ®è¨¡ªã:
+% \begin{verbatim}
+% ...
+% try
+% p;
+% finally
+% ...
+% exit; // â®â exit ­¥¤®¯ãá⨬
+% end;
+% ...
+%
+% \end{verbatim}
+% …᫨ ¯à¨ ¢ë¯®«­¥­¨¨ ¯à®æ¥¤ãà  \var{p} ¯à®¨á室¨â ¨áª«î祭¨¥, ¢ë¯®«­ï¥âáï ¡«®ª
+% finally. …᫨ ¢ë¯®«­¥­¨¥ ¤®å®¤¨â ¤® exit, ­¥¯®­ïâ­® çâ® ¤¥« âì:
+% ¢ë室¨âì ¨§ ¯à®æ¥¤ãਠ¨«¨ ¨áª âì ¤à㣮© ®¡à ¡®â稪 ¨áª«î祭¨©.
+cg_w_parasize_too_big=06041_W_ §¬¥à ¯ à ¬¥â஢ ¯à¥¢ë蠥⠯।¥« ¤«ï ­¥ª®â®àëå ¯à®æ¥áá®à®¢
+% Ž§­ ç ¥â, çâ® ¡ë«® ®¡ê¥­® ¡®«¥¥ 64 ª ©â ¯ à ¬¥â஢, çâ®
+% ¬®¦¥â ­¥ ¯®¤¤¥à¦¨¢ âìáï ¯à¨ ª®¬¯¨«ï樨 ¤«ï ¤àã£¨å ¯« âä®à¬.
+cg_w_localsize_too_big=06042_W_ §¬¥à «®ª «ì­ëå ¯¥à¥¬¥­­ëå ¯à¥¢ë蠥⠯।¥« ¤«ï ­¥ª®â®àëå ¯à®æ¥áá®à®¢
+% Ž§­ ç ¥â, çâ® ¡ë«® ®¡ê¥­® ¡®«¥¥ 32 ª ©â «®ª «ì­ëå ¯¥à¥¬¥­­ëå, çâ®
+% ¬®¦¥â ­¥ ¯®¤¤¥à¦¨¢ âìáï ¯à¨ ª®¬¯¨«ï樨 ¤«ï ¤àã£¨å ¯« âä®à¬.
+cg_e_localsize_too_big=06043_E_ §¬¥à «®ª «ì­ëå ¯¥à¥¬¥­­ëå ¯à¥¢ë蠥⠤®¯ãáâ¨¬ë© ¯à¥¤¥«
+% Ž§­ ç ¥â, çâ® ®¡ê¥­® ¡®«¥¥ 32 ª ©â «®ª «ì­ëå ¯¥à¥¬¥­­ëå, çâ®
+% ­¥ ¯®¤¤¥à¦¨¢ ¥âáï ¤«ï ¤ ­­®£® ¯à®æ¥áá®à .
+cg_e_break_not_allowed=06044_E_BREAK ­¥¤®¯ãá⨬®
+% ®¯ë⪠ ¨á¯®«ì§®¢ ­¨ï \var{break} ¢­¥ ª®­áâàãªæ¨¨ 横« .
+cg_e_continue_not_allowed=06045_E_CONTINUE ­¥¤®¯ãá⨬®
+% ®¯ë⪠ ¨á¯®«ì§®¢ ­¨ï \var{continue} ¢­¥ ª®­áâàãªæ¨¨ 横« .
+cg_f_unknown_compilerproc=06046_F_¥¨§¢¥áâ­ ï ¢­ãâ७­ïï ¯à®æ¥¤ãà  "$1". ஢¥àì⥠¢¥àá¨î ¡¨¡«¨®â¥ª¨ RTL.
+% Š®¬¯¨«ïâ®à ®¦¨¤ ¥â, çâ® ¡¨¡«¨®â¥ª  ¢à¥¬¥­¨ ¢ë¯®«­¥­¨ï (RTL) ᮤ¥à¦¨â ®¯à¥¤¥«¥­­ë¥ ¯à®æ¥¤ãàë. …᫨
+% ¢ë ¢¨¤¨â¥ íâ® á®®¡é¥­¨¥, ­¥ § ­¨¬ ïáì á ¬®áâ®ï⥫쭮© ¬®¤¨ä¨ª æ¨¥© ª®¤  ¡¨¡«¨®â¥ª¨ RTL, â®, ᪮॥
+% ¢á¥£®, ¨á¯®«ì§ã¥¬ ï ¡¨¡«¨®â¥ª  RTL ­¥ ᮮ⢥âáâ¢ã¥â ª®¬¯¨«ïâ®àã. …᫨ ¦¥ ¢ë ¬®¤¨ä¨æ¨à®¢ «¨ RTL, §­ ç¨â,
+% ¢ë 㤠«¨«¨ ¯à®æ¥¤ãàã, ª®â®à ï ­ã¦­  ª®¬¯¨«ïâ®àã ¤«ï ¢­ãâ७­¥£® ¨á¯®«ì§®¢ ­¨ï.
+cg_f_unknown_system_type=06047_F_¥ ­ ©¤¥­ á¨á⥬­ë© ⨯ "$1". ஢¥àì⥠¢¥àá¨î ¡¨¡«¨®â¥ª¨ RTL.
+% Š®¬¯¨«ïâ®à ®¦¨¤ ¥â, çâ® ¡¨¡«¨®â¥ª  ¢à¥¬¥­¨ ¢ë¯®«­¥­¨ï (RTL) ᮤ¥à¦¨â ®¯à¥¤¥«¥­­ë¥ ®¡ê¥­¨ï
+% ⨯®¢. …᫨ ¢ë ¢¨¤¨â¥ íâ® á®®¡é¥­¨¥, ­¥ § ­¨¬ ïáì á ¬®áâ®ï⥫쭮© ¬®¤¨ä¨ª æ¨¥© ª®¤  ¡¨¡«¨®â¥ª¨ RTL, â®,
+% ᪮॥ ¢á¥£®, ¨á¯®«ì§ã¥¬ ï ¡¨¡«¨®â¥ª  RTL ­¥ ᮮ⢥âáâ¢ã¥â ª®¬¯¨«ïâ®àã. …᫨ ¦¥ ¢ë ¬®¤¨ä¨æ¨à®¢ «¨ RTL,
+% §­ ç¨â, ¢ë 㤠«¨«¨ ⨯, ­ã¦­ë© ª®¬¯¨«ïâ®àã ¤«ï ¢­ãâ७­¥£® ¨á¯®«ì§®¢ ­¨ï.
+cg_h_inherited_ignored=06048_H_‚맮¢  ¡áâࠪ⭮£® ¬¥â®¤  ¯®á।á⢮¬ inherited ¨£­®à¨à®¢ ­
+% ‘®®¡é¥­¨¥ ¢ë¤ ¥âáï ⮫쪮 ¢ ०¨¬¥ Delphi, ¯à¨ ¯®¯ë⪥ ¢ë§¢ âì  ¡áâà ªâ­ë© ¬¥â®¤
+% த¨â¥«ì᪮£® ª« áá  á ¯®¬®éìî \var{inherited;}. ’ ª®© ¢ë§®¢ ¨£­®à¨àã¥âáï.
+cg_e_goto_label_not_found=06049_E_Œ¥âª  "$1" ­¥ ®¯à¥¤¥«¥­  ¨«¨ 㤠«¥­  ®¯â¨¬¨§ æ¨¥©
+% Œ¥âª , ¨á¯®«ì§®¢ ­­ ï ¢ goto, ­¥ ®¯à¥¤¥«¥­  «¨¡® ¡ë«  㤠«¥­  ¯à¨ 㤠«¥­¨¨
+% ­¥¤®áâ㯭®£® ª®¤ .
+% \end{description}
+# EndOfTeX
+
+#
+# Assembler reader
+#
+# 07107 is the last used one
+#
+asmr_d_start_reading=07000_DL_H ç «® ç⥭¨ï  áᥬ¡«¥p  ⨯  $1
+% ˆ­ä®à¬¨àã¥â ® ­ ç «¥ ç⥭¨ï  áᥬ¡«¥à­®£® ¡«®ª .
+asmr_d_finish_reading=07001_DL_Š®­¥æ ç⥭¨ï  áᥬ¡«¥p  ⨯  $1
+% ˆ­ä®à¬¨àã¥â ® § ¢¥à襭¨¨ ç⥭¨ï  áᥬ¡«¥à­®£® ¡«®ª .
+asmr_e_none_label_contain_at=07002_E_’®ª¥­, ­¥ ïî騩áï ¬¥âª®©, ᮤ¥p¦¨â @
+% ˆ¤¥­â¨ä¨ª â®à, ­¥ ïî騩áï ¬¥âª®©, ­¥ ¬®¦¥â ᮤ¥à¦ âì ᨬ¢®« @.
+asmr_e_building_record_offset=07004_E_Žè¨¡ª  ¯®áâp®¥­¨ï ᬥ饭¨ï ¢ § ¯¨á¨
+% Žè¨¡ª  ¢ëç¨á«¥­¨ï ᬥ饭¨ï ¢ § ¯¨á¨/®¡ê¥ªâ¥, ¬®¦¥â ¯à®¨á室¨âì, ¥á«¨
+% ¯®«¥ ­¥ 㪠§ ­® ¢®®¡é¥ ¨«¨ ¨á¯®«ì§®¢ ­ ­¥¨§¢¥áâ­ë© ¨¤¥­â¨ä¨ª â®à ¯®«ï.
+asmr_e_offset_without_identifier=07005_E_ˆá¯®«ì§®¢ ­¨¥ OFFSET ¡¥§ ¨¤¥­â¨ä¨ª â®p 
+% Š«î祢®¥ á«®¢® OFFSET ¬®¦­® ¨á¯®«ì§®¢ âì ⮫쪮 ᮢ¬¥áâ­® á ¨¤¥­â¨ä¨ª â®à®¬.
+% „à㣨¥ ᨭ⠪á¨áë ­¥ ¯®¤¤¥à¦¨¢ îâáï.
+asmr_e_type_without_identifier=07006_E_ˆá¯®«ì§®¢ ­¨¥ TYPE ¡¥§ ¨¤¥­â¨ä¨ª â®p 
+% Š«î祢®¥ á«®¢® TYPE ¬®¦­® ¨á¯®«ì§®¢ âì ⮫쪮 ᮢ¬¥áâ­® á ¨¤¥­â¨ä¨ª â®à®¬.
+% „à㣨¥ ᨭ⠪á¨áë ­¥ ¯®¤¤¥à¦¨¢ îâáï.
+asmr_e_no_local_or_para_allowed=07007_E_‡¤¥áì ­¥«ì§ï ¨á¯®«ì§®¢ âì «®ª «ì­ë¥ ¯¥p¥¬¥­­ë¥ ¨«¨ ¯ p ¬¥âpë
+% ‹®ª «ì­ë¥ ¯¥à¥¬¥­­ë¥ ¨ ¯ à ¬¥âàë ®¡ëç­®  ¤à¥áãîâáï ª ª ᬥ饭¨¥ ®â ॣ¨áâà 
+% %ebp, ¯®íâ®¬ã ¨å  ¤à¥á ­¥ ¬®¦¥â ¡ëâì ¯®«ã祭 ­¥¯®á।á⢥­­®.
+asmr_e_need_offset=07008_E_‡¤¥áì ­¥®¡å®¤¨¬® ¨á¯®«ì§®¢ âì OFFSET
+% „«ï ¯®«ã祭¨ï  ¤à¥á  ¤ ­­®£® ¨¤¥­â¨ä¨ª â®à  ­¥®¡å®¤¨¬® ¨á¯®«ì§®¢ âì OFFSET <id>.
+asmr_e_need_dollar=07009_E_‡¤¥áì ­¥®¡å®¤¨¬® ¨á¯®«ì§®¢ âì §­ ª ¤®«« à  ('$')
+% „«ï ¯®«ã祭¨ï  ¤à¥á  ¤ ­­®£® ¨¤¥­¨ä¨ª â®à  ­¥®¡å®¤¨¬® ¨á¯®«ì§®¢ âì $<id>.
+asmr_e_cant_have_multiple_relocatable_symbols=07010_E_H¥ ¤®¯ã᪠îâáï ¬­®¦¥á⢥­­ë¥ ¯¥p¥¬¥é ¥¬ë¥ ᨬ¢®«ë
+% ¥ ¤®¯ã᪠¥âáï ¡®«¥¥ ®¤­®£® ¯¥à¥¬¥é ¥¬®£® ᨬ¢®«  (¯¥à¥¬¥­­ ï/⨯¨§¨à®¢ ­­ ï ª®­áâ ­â )
+% ¢ ®¤­®¬  à£ã¬¥­â¥.
+asmr_e_only_add_relocatable_symbol=07011_E_¥p¥¬¥é ¥¬ë© ᨬ¢®« ¤®¯ã᪠¥â ⮫쪮 á«®¦¥­¨¥
+% ¥à¥¬¥é ¥¬ë¥ ᨬ¢®«ë (¯¥à¥¬¥­­ë¥/⨯¨§¨à®¢ ­­ë¥ ª®­áâ ­âë) ­¥ ¬®£ãâ ¡ëâì ¨á¯®«ì§®¢ ­ë á ¤à㣨¬¨
+% ®¯¥à â®à ¬¨. „®¯ã᪠¥âáï ⮫쪮 á«®¦¥­¨¥.
+asmr_e_invalid_constant_expression=07012_E_H¥¢¥à­®¥ ª®­áâ ­â­®¥ ¢ëp ¦¥­¨¥
+% Žè¨¡ª  ¢ ª®­áâ ­â­®¬ ¢ëà ¦¥­¨¨.
+asmr_e_relocatable_symbol_not_allowed=07013_E_¥p¥¬¥é ¥¬ë© ᨬ¢®« §¤¥áì ­¥ p §p¥è¥­
+% ‚ ¤ ­­®¬ ¬¥á⥠­¥ ¬®¦¥â ¡ëâì ¨á¯®«ì§®¢ ­ ¯¥à¥¬¥é ¥¬ë© ᨬ¢®« (¯¥à¥¬¥­­ ï/⨯¨§¨à®¢ ­­ ï ª®­áâ ­â ).
+asmr_e_invalid_reference_syntax=07014_E_H¥¢¥p­ë© ᨭ⠪á¨á áá뫪¨
+% ‘¨­â ªá¨ç¥áª ï ®è¨¡ª  ¢ § ¯¨á¨ áá뫪¨.
+asmr_e_local_para_unreachable=07015_E_$1 ­¥¤®áâ㯭® ¨§ í⮣® ª®¤ 
+% ‚® ¢«®¦¥­­®© ¯à®æ¥¤ãॠ­¥¢®§¬®¦¥­ ¯àאַ© ¤®áâ㯠ª §­ ç¥­ï¬ «®ª «ì­ëå ¯¥à¥¬¥­­ëå ¨«¨ ¯ à ¬¥â஢
+% ¢­¥è­¥© ¯à®æ¥¤ãàë (ªà®¬¥ á«ãç ï, ª®£¤  ¢«®¦¥­­ ï ¯à®æ¥¤ãà  á ¬  ­¥ ¨¬¥¥â ¯ à ¬¥â஢ ¨ «®ª «ì­ëå
+% ¯¥à¥¬¥­­ëå).
+asmr_e_local_label_not_allowed_as_ref=07016_E_‹®ª «ì­ë¥ ᨬ¢®«ë ¨«¨ ¬¥âª¨ ­¥«ì§ï ¨á¯®«ì§®¢ âì ª ª áá뫪¨
+% ‚ë ­¥ ¬®¦¥â¥ ¨á¯®«ì§®¢ âì «®ª «ì­ë¥ ᨬ¢®«ë ¨«¨ ¬¥âª¨ ª ª áá뫪¨
+asmr_e_wrong_base_index=07017_E_H¥¢¥p­®¥ ¨á¯®«ì§®¢ ­¨¥ ॣ¨áâ஢ ¡ §ë ¨ ¨­¤¥ªá 
+% Žè¨¡ª  ¯à¨ ¨á¯®«ì§®¢ ­¨¨ ॣ¨áâ஢ ¡ §ë ¨ ¨­¤¥ªá 
+asmr_w_possible_object_field_bug=07018_W_‚®§¬®¦­ ï ®è¨¡ª  ¢ ®¡à ¡®âª¥ ¯®«ï ®¡ê¥ªâ 
+% ®«ï ª« áᮢ/®¡ê¥ªâ®¢ ­¥¤®áâã¯­ë ­ ¯àï¬ãî ¢ ०¨¬ å fpc ¨ objfpc,
+% ­® ¢ ०¨¬ å TP ¨ Delphi ¨¬¥­  ¯®«¥© ®¡à ¡ â뢠îâáï ª ª ®¡ëç­ë¥ ᬥ饭¨ï.
+asmr_e_wrong_scale_factor=07019_E_H¥¢¥p­ë© ¬­®¦¨â¥«ì
+% “ª § ­ ­¥¢¥à­ë© ¬­®¦¨â¥«ì, à §à¥è¥­ë ⮫쪮 §­ ç¥­¨ï 1,2,4 ¨ 8
+asmr_e_multiple_index=07020_E_Œ­®¦¥á⢥­­®¥ ¨á¯®«ì§®¢ ­¨¥ ¨­¤¥ªá­®£® p¥£¨áâp 
+% ®¯ë⪠ ¨á¯®«ì§®¢ ­¨ï ¡®«¥¥ 祬 ®¤­®£® ¨­¤¥ªá­®£® ॣ¨áâà .
+asmr_e_invalid_operand_type=07021_E_H¥¢¥p­ë© ⨯ ®¯¥p ­¤ 
+% ’¨¯ ®¯¥à ­¤  ­¥ ᮮ⢥âáâ¢ã¥â ª®¤ã ª®¬ ­¤ë.
+asmr_e_invalid_string_as_opcode_operand=07022_E_‘âp®ª  ­¥¯à¨£®¤­  ¢ ª ç¥á⢥ ®¯¥p ­¤  ¨­áâàãªæ¨¨: $1
+% ‘âப , 㪠§ ­­ ï ª ª ®¯¥à ­¤, ­¥ª®à४⭠ ¤«ï ¤ ­­®© ª®¬ ­¤ë.
+asmr_w_CODE_and_DATA_not_supported=07023_W_@CODE ¨ @DATA ­¥ ¯®¤¤¥p¦¨¢ îâáï
+% @CODE ¨ @DATA ­¥ ¯®¤¤¥à¦¨¢ îâáï ¨ ¨£­®à¨àãîâáï.
+asmr_e_null_label_ref_not_allowed=07024_E_‘á뫪¨ ­  ¡¥§ë¬ï­­ë¥ ¬¥âª¨ ­¥ ¤®¯ã᪠îâáï
+asmr_e_expr_zero_divide=07025_E_„¥«¥­¨¥ ­  ­®«ì ¢ ¢ëà ¦¥­¨¨  áᥬ¡«¥à 
+% ‚ ª®­áâ ­â­®¬ ¢ëà ¦¥­¨¨ ᮤ¥à¦¨âáï ¤¥«¥­¨¥ ­  ­®«ì
+asmr_e_expr_illegal=07026_E_¥¢¥à­®¥ ¢ëà ¦¥­¨¥
+% Š®­áâ ­â­®¥ ¢ëà ¦¥­¨¥ ­¥¢¥à­®
+asmr_e_escape_seq_ignored=07027_E_Escape-¯®á«¥¤®¢ â¥«ì­®áâì ¨£­®p¨p®¢ ­ : $1
+% ‚ áâப¥ á⨫ï ï§ëª  C ᮤ¥à¦¨âáï ­¥¨§¢¥áâ­ ï escape-¯®á«¥¤®¢ â¥«ì­®áâì,
+% ª®â®à ï ¨£­®à¨àã¥âáï.
+asmr_e_invalid_symbol_ref=07028_E_H¥¢¥p­ ï áá뫪  ­  ᨬ¢®«
+asmr_w_fwait_emu_prob=07029_W_FWAIT ¬®¦¥â ¢ë§¢ âì ¯p®¡«¥¬ë í¬y«ï樨 á EMU387
+asmr_w_fadd_to_faddp=07030_W_$1 ¡¥§ ®¯¥à ­¤  â࠭᫨àã¥âáï ¢ $1P
+asmr_w_enter_not_supported_by_linux=07031_W_ˆ­áâàãªæ¨ï ENTER ­¥ ¯®¤¤¥à¦¨¢ ¥âáï ï¤à®¬ Linux
+% ˆ­áâàãªæ¨ï ENTER ¬®¦¥â ¯à¨¢¥á⨠ª ®è¨¡ª¥ § é¨âë áâà ­¨æë á⥪ , ª®â®à ï ­¥ª®à४⭮
+% "«®¢¨âáï" ®¡à ¡®â稪®¬ ¢ i386 Linux.
+asmr_w_calling_overload_func=07032_W_‚맮¢ ¯¥p¥£py¦¥­­®© äy­ªæ¨¨ ¢  áᥬ¡«¥p¥
+% ‚맮¢ ¯¥à¥£à㦥­­®© ä㭪樨 ¨§  áᥬ¡«¥à­®£® ¡«®ª ,
+% ª ª ¯à ¢¨«®, ï¥âáï ¯à¨§­ ª®¬ ¯à®¡«¥¬ë.
+asmr_e_unsupported_symbol_type=07033_E_H¥ ¯®¤¤¥p¦¨¢ ¥¬ë© ⨯ ᨬ¢®«  ¤«ï ®¯¥p ­¤ 
+asmr_e_constant_out_of_bounds=07034_E_‡­ ç¥­¨¥ ª®­áâ ­âë ¢­¥ ¤¨ ¯ §®­ 
+asmr_e_error_converting_decimal=07035_E_"$1" ­¥ ï¥âáï ¤¥áïâ¨ç­ë¬ ç¨á«®¬
+% ¥¢¥à­ë© ᨭ⠪á¨á ¤¥áïâ¨ç­®£® ç¨á« .
+asmr_e_error_converting_octal=07036_E_"$1" ­¥ ï¥âáï ¢®á쬥p¨ç­ë¬ ç¨á«®¬
+% ¥¢¥à­ë© ᨭ⠪á¨á ¢®á쬥à¨ç­®£® ç¨á« .
+asmr_e_error_converting_binary=07037_E_"$1" ­¥ ï¥âáï ¤¢®¨ç­ë¬ ç¨á«®¬
+% ¥¢¥à­ë© ᨭ⠪á¨á ¤¢®¨ç­®£® ç¨á« .
+asmr_e_error_converting_hexadecimal=07038_E_"$1" ­¥ ï¥âáï è¥áâ­ ¤æ â¥p¨ç­ë¬ ç¨á«®¬
+% ¥¢¥à­ë© ᨭ⠪á¨á è¥áâ­ ¤æ â¥à¨ç­®£® ç¨á« .
+asmr_h_direct_global_to_mangled=07039_H_$1 ¯p¥®¡p §®¢ ­® ¢ $2
+asmr_w_direct_global_is_overloaded_func=07040_W_$1 á¢ï§ ­® á ¯¥p¥£py¦¥­­®© äy­ªæ¨¥©
+asmr_e_cannot_use_SELF_outside_a_method=07041_E_H¥ ¤®¯ã᪠¥âáï ¨á¯®«ì§®¢ ­¨¥ SELF ¢­¥ ¬¥â®¤ 
+% ¥¤®¯ãá⨬ ï áá뫪  ­  ᨬ¢®« \var{self}.
+%   \var{self} ¬®¦­® ááë« âìáï ⮫쪮 ¢ ¬¥â®¤ å.
+asmr_e_cannot_use_OLDEBP_outside_nested_procedure=07042_E_H¥ ¤®¯ã᪠¥âáï ¨á¯®«ì§®¢ ­¨¥ OLDEBP ¢­¥ ¢«®¦¥­­®© ¯p®æ¥¤ypë
+% ¥¤®¯ãá⨬ ï áá뫪  ­  ᨬ¢®« \var{oldebp}.
+%   \var{oldebp} ¬®¦­® ááë« âìáï ⮫쪮 ¢® ¢«®¦¥­­ëå ¯à®æ¥¤ãà å.
+asmr_e_void_function=07043_W_஥楤ãàë ­¥ ¬®£ãâ ¢®§¢p é âì §­ ç¥­¨ï ¨§  áᥬ¡«¥à­®£® ª®¤ 
+% ®¯ë⪠ ¢¥à­ãâì §­ ç¥­¨¥ ¨§ ¯à®æ¥¤ãàë. à®æ¥¤ãà  ­¥ ¬®¦¥â ¢®§¢à é âì §­ ç¥­¨ï.
+asmr_e_SEG_not_supported=07044_E_SEG ­¥ ¯®¤¤¥p¦¨¢ ¥âáï
+asmr_e_size_suffix_and_dest_dont_match=07045_E_‘yä䨪á p §¬¥p  ­¥ ᮮ⢥âáâ¢ã¥â à §¬¥àã ®¯¥à ­¤®¢
+%  §¬¥à ॣ¨áâà  ¨ áãä䨪á à §¬¥à  ¢ ª®¤¥ ª®¬ ­¤ë ­¥ ᮮ⢥âá¢ãîâ. ‘ª®à¥¥ ¢á¥£®,
+% ª®¬ ­¤   áᥬ¡«¥à  § ¯¨á ­  á ®è¨¡ª®©.
+asmr_w_size_suffix_and_dest_dont_match=07046_W_‘yä䨪á p §¬¥p  ­¥ ᮮ⢥âáâ¢ã¥â à §¬¥àã ®¯¥à ­¤®¢
+%  §¬¥à ॣ¨áâà  ¨ áãä䨪á à §¬¥à  ¢ ª®¤¥ ª®¬ ­¤ë ­¥ ᮮ⢥âá¢ãîâ. ‘ª®à¥¥ ¢á¥£®,
+% ª®¬ ­¤   áᥬ¡«¥à  § ¯¨á ­  á ®è¨¡ª®©.
+asmr_e_syntax_error=07047_E_‘¨­â ªá¨ç¥áª ï ®è¨¡ª   áᥬ¡«¥à 
+% ‘¨­â ªá¨ç¥áª ï ®è¨¡ª   áᥬ¡«¥à 
+asmr_e_invalid_opcode_and_operand=07048_E_H¥¢¥p­ ï ª®¬¡¨­ æ¨ï ª®¬ ­¤ë ¨ ®¯¥p ­¤®¢
+% „ ­­ ï ª®¬ ­¤  ­¥ ¬®¦¥â ¨¬¥âì ®¯¥à ­¤ë ¤ ­­®£® ⨯ .
+asmr_e_syn_operand=07049_E_‘¨­â ªá¨ç¥áª ï ®è¨¡ª   áᥬ¡«¥à  ¢ ®¯¥p ­¤¥
+asmr_e_syn_constant=07050_E_‘¨­â ªá¨ç¥áª ï ®è¨¡ª   áᥬ¡«¥à  ¢ ª®­áâ ­â¥
+asmr_e_invalid_string_expression=07051_E_H¥¢¥p­®¥ áâp®ª®¢®¥ ¢ëp ¦¥­¨¥
+asmr_w_const32bit_for_address=07052_W_ª®­áâ ­â  á ᨬ¢®«®¬ $1 ¤«ï  ¤à¥á , à §¬¥à ª®â®à®£® ®â«¨ç ¥âáï ®â 㪠§ â¥«ï
+% Š®­áâ ­â­®¥ ¢ëà ¦¥­¨¥, ¯à¥¤áâ ¢«ïî饥  ¤à¥á, ­¥ 㬥頥âáï ¢ ¤¨ ¯ §®­ 㪠§ â¥«ï.
+% €¤à¥á, ᪮॥ ¢á¥£®, ­¥¢¥à¥­.
+asmr_e_unknown_opcode=07053_E_¥¨§¢¥áâ­ë© ª®¤ ®¯¥à æ¨¨ $1
+% ¥¨§¢¥áâ­ ï ª®¬ ­¤   áᥬ¡«¥à 
+asmr_e_invalid_or_missing_opcode=07054_E_H¥¢¥p­ ï ¨«¨ ¯p®¯y饭­ ï ®¯¥à æ¨ï
+asmr_e_invalid_prefix_and_opcode=07055_E_H¥¢¥p­ ï ª®¬¡¨­ æ¨ï ¯p¥ä¨ªá  ¨ ®¯¥à æ¨¨: $1
+asmr_e_invalid_override_and_opcode=07056_E_H¥¢¥p­ ï ª®¬¡¨­ æ¨ï ¯¥p¥®¯p¥¤¥«¥­¨ï ¨ ®¯¥à æ¨¨: $1
+asmr_e_too_many_operands=07057_E_‘«¨èª®¬ ¬­®£® ®¯¥p ­¤®¢ ¢ áâp®ª¥
+% ‘«¨èª®¬ ¬­®£® ®¯¥à ­¤®¢ ¤«ï ¤ ­­®© ª®¬ ­¤ë. ஢¥àì⥠ᨭ⠪á¨á.
+asmr_w_near_ignored=07058_W_„¨à¥ªâ¨¢  NEAR ¨£­®p¨p®¢ ­ 
+asmr_w_far_ignored=07059_W_„¨à¥ªâ¨¢  FAR ¨£­®p¨p®¢ ­ 
+asmr_e_dup_local_sym=07060_E_®¢â®p­®¥ ®¯p¥¤¥«¥­¨¥ «®ª «ì­®£® ᨬ¢®«  $1
+asmr_e_unknown_local_sym=07061_E_H¥¨§¢¥áâ­ë© «®ª «ì­ë© ᨬ¢®« $1
+asmr_e_unknown_label_identifier=07062_E_H¥¨§¢¥áâ­ ï ¬¥âª  $1
+asmr_e_invalid_register=07063_E_¥¢¥à­®¥ ¨¬ï ॣ¨áâà 
+% There is an unknown register name used as operand.
+asmr_e_invalid_fpu_register=07064_E_H¥¢¥à­®¥ ¨¬ï p¥£¨áâp  ¤«ï ®¯¥p æ¨¨ á ¯« ¢ î饩 § ¯ï⮩
+% ë«® ¨á¯®«ì§®¢ ­® ­¥¨§¢¥áâ­®¥ ¨¬ï ॣ¨áâà .
+asmr_w_modulo_not_supported=07066_W_MODULO ­¥ ¯®¤¤¥p¦¨¢ ¥âáï
+asmr_e_invalid_float_const=07067_E_H¥¢¥p­ ï ¢¥é¥á⢥­­ ï ª®­áâ ­â  $1
+% Š®­áâ ­â  á ¯« ¢ î饩 § ¯ï⮩, ®¡ê¥­­ ï ¢  áᥬ¡«¥à­®¬ ¡«®ª¥, ­¥¢¥à­ .
+asmr_e_invalid_float_expr=07068_E_H¥¢¥p­®¥ ¢¥é¥á⢥­­®¥ ¢ëp ¦¥­¨¥
+% ‚ëà ¦¥­¨¥ á ¯« ¢ î饩 § ¯ï⮩, ®¡ê¥­­®¥ ¢  áᥬ¡«¥à­®¬ ¡«®ª¥, ­¥¢¥à­®.
+asmr_e_wrong_sym_type=07069_E_H¥¢¥p­ë© ⨯ ᨬ¢®« 
+asmr_e_cannot_index_relative_var=07070_E_H¥«ì§ï ¨­¤¥ªá¨p®¢ âì «®ª «ì­yî ¯¥p¥¬¥­­yî ¨«¨ ¯ p ¬¥âp á ¯®¬®éìî p¥£¨áâp 
+%  §®¢ë© ॣ¨áâà ¨á¯®«ì§ã¥âáï ¤«ï ¨­¤¥ªá æ¨¨ ᨬ¢®« , ª®â®àë© ã¦¥ ï¥âáï ®â­®á¨â¥«ì­ë¬
+% ¯® ®â­®è¥­¨î ª ॣ¨áâàã. â® ­¥¢®§¬®¦­®, ¨ ­ ¢¥à­ïª  ¯à¨¢¥¤¥â ª ®è¨¡ª¥ ¯à¨ ¢ë¯®«­¥­¨¨.
+asmr_e_invalid_seg_override=07071_E_H¥¢¥p­®¥ ¢ëp ¦¥­¨¥ ¯¥p¥®¯p¥¤¥«¥­¨ï ᥣ¬¥­â 
+asmr_w_id_supposed_external=07072_W_ˆ¤¥­â¨ä¨ª â®p $1, ¯p¥¤¯®«®¦¨â¥«ì­®, ¢­¥è­¨©
+% ‘á뫪  ­¥ ­¥®¯à¥¤¥«¥­­ë© ᨬ¢®«.â® ­¥ ï¥âáï ®è¨¡ª®©,
+% â.ª. ᨬ¢®« ¬®¦¥â ¨¬¥âì ¢­¥è­¥¥ ®¯à¥¤¥«¥­¨¥, ­® ¬®¦¥â ¯à¨¢¥á⨠ª ¯à®¡«¥¬ ¬
+% ¯à¨ ª®¬¯®­®¢ª¥, ¥á«¨ ᨬ¢®« ­¥ ¡ë« ®¯à¥¤¥«¥­ £¤¥-­¨¡ã¤ì ¥é¥.
+asmr_e_string_not_allowed_as_const=07073_E_H¥«ì§ï ¨á¯®«ì§®¢ âì áâp®ª¨ ª ª ª®­áâ ­âë
+% ‘âப¨ ᨬ¢®«®¢ ­¥«ì§ï ¨á¯®«ì§®¢ âì ¢ ª ç¥á⢥ ª®­áâ ­â.
+asmr_e_no_var_type_specified=07074_¥ 㪠§ ­ ⨯ ¯¥p¥¬¥­­®©
+% ‘¨­â ªá¨á ¯à¥¤¯®« £ ¥â ¨¬ï ⨯  ¯®á«¥ â®çª¨, ­® ®­® ­¥ ¡ë«® ®¡­ à㦥­®.
+asmr_w_assembler_code_not_returned_to_text=07075_E_€áᥬ¡«¥p­ë© ª®¤ ­¥ ¢®§¢p é ¥âáï ¢ ᥣ¬¥­â TEXT
+% ‚  áᥬ¡«¥à­®¬ ¡«®ª¥ ¡ë«  ¤¨à¥ªâ¨¢  ᬥ­ë ᥪ権, ­® ¢ ª®­æ¥ ¡«®ª  ®âáãâáâ¢ã¥â ¤¨à¥ªâ¨¢ 
+% ¢®§¢à â  ¢ ᥣ¬¥­â ⥪áâ . Œ®¦¥â ¡ëâì ¯à¨ç¨­®© ®è¨¡®ª ¯à¨ ª®¬¯®­®¢ª¥.
+asmr_e_not_directive_or_local_symbol=07076_E_$1 ­¥ ï¥âáï ¤¨p¥ªâ¨¢®© ¨«¨ «®ª «ì­ë¬ ᨬ¢®«®¬
+% “ª § ­­ë© ᨬ¢®« ­¥¨§¢¥á⥭.
+asmr_w_using_defined_as_local=07077_E_ˆá¯®«ì§®¢ ­¨¥ ®¯p¥¤¥«¥­­®£® ¨¬¥­¨ ¢ ª ç¥á⢥ «®ª «ì­®© ¬¥âª¨
+asmr_e_dollar_without_identifier=07078_E_‘¨¬¢®« '$' ¨á¯®«ì§y¥âáï ¡¥§ ¨¤¥­â¨ä¨ª â®p 
+% ‚ ª®­áâ ­â­®¬ ¢ëà ¦¥­¨¨ ¢áâà¥â¨«áï ¨¤¥­â¨ä¨ª â®à, ­¥ ­ ç¨­ î騩áï á ᨬ¢®«  $.
+asmr_w_32bit_const_for_address=07079_W_32-¡¨â­ ï ª®­áâ ­â  ¨á¯®«ì§®¢ ­  ¤«ï  ¤p¥á 
+% Š®­áâ ­â  ¨á¯®«ì§®¢ ­  ¢ ª ç¥á⢥  ¤à¥á . ⮠ï¥âáï ¯à¨§­ ª®¬ ®è¨¡ª¨,
+% ¯®áª®«ìªã  ¡á®«îâ­ ï  ¤à¥á æ¨ï ®¡ëç­® ­¥ à ¡®â ¥â.
+asmr_n_align_is_target_specific=07080_N_.ALIGN ï¥âáï ¯« âä®à¬¥­­®-§ ¢¨á¨¬®©, ¨á¯®«ì§y©â¥ .BALIGN ¨«¨ .P2ALIGN
+% „¥©á⢨¥ ¨ §­ ç¥­¨¥ ¤¨à¥ªâ¨¢ë .align ¬®¦¥â ¨§¬¥­ïâìáï ¢ § ¢¨á¨¬®á⨠®â
+% 楫¥¢®© ¯« âä®à¬ë.
+asmr_e_cannot_access_field_directly_for_parameters=07081_E_®«ï ¯ p ¬¥âp  ­¥¤®áâã¯­ë ­ ¯pï¬yî, ¨á¯®«ì§y©â¥ p¥£¨áâpë
+%  à ¬¥âà á«¥¤ã¥â § £à㧨âì ¢ ॣ¨áâà ¨ § â¥¬  ¤à¥á®¢ âì ¯®«ï ¯ à ¬¥âà  ®â­®á¨â¥«ì­®
+% í⮣® ॣ¨áâà .
+asmr_e_cannot_access_object_field_directly=07082_E_®«ï ®¡ê¥ªâ®¢/ª« áᮢ ­¥¤®áâã¯­ë ­ ¯pï¬yî, ¨á¯®«ì§y©â¥ p¥£¨áâpë
+% ‘«¥¤ã¥â § £à㧨âì 㪠§ â¥«ì ­  self ¢ ॣ¨áâà ¨ § â¥¬  ¤à¥á®¢ âì ¯®«ï, ¨á¯®«ì§ãï ॣ¨áâà
+% ¢ ª ç¥á⢥ ¡ §ë. ® 㬮«ç ­¨î 㪠§ â¥«ì ­  self ¤®áâ㯥­
+% ¢ ॣ¨áâॠesi ­  i386.
+asmr_e_unable_to_determine_reference_size=07083_E_ §¬¥p ®¯¥à ­¤®¢ ­¥ 㪠§ ­ ¨ ¥£® ®¯à¥¤¥«¥­¨¥ ­¥¢®§¬®¦­®
+%  §¬¥à áá뫪¨ á«¥¤ã¥â 㪠§ âì ®, â.ª. ª®¬¯¨«ïâ®à ­¥ ¬®¦¥â
+% ®¯à¥¤¥«¨âì, ª ª®© à §¬¥à (byte,word,dword ¨ â.¤.) ®­
+% ¤®«¦¥­ ¨á¯®«ì§®¢ âì.
+asmr_e_cannot_use_RESULT_here=07084_E_‚ í⮩ ä㭪樨 ¨á¯®«ì§®¢ âì RESULT ­¥«ì§ï
+% ¥ª®â®àë¥ ä㭪樨, ¢®§¢à é î騥 १ã«ìâ â á«®¦­®£® ⨯ , ­¥ ¬®£ã⠨ᯮ«ì§®¢ âì ¯¥à¥¬¥­­ãî
+% \var{result}.
+asmr_w_adding_explicit_args_fXX=07086_W_"$1" ¡¥§ ®¯¥à ­¤  â࠭᫨àã¥âáï ¢ "$1 %st,%st(1)"
+asmr_w_adding_explicit_first_arg_fXX=07087_W_"$1 %st(n)" â࠭᫨àã¥âáï ¢ "$1 %st,%st(n)"
+asmr_w_adding_explicit_second_arg_fXX=07088_W_"$1 %st(n)" â࠭᫨àã¥âáï ¢ "$1 %st(n),%st"
+asmr_e_invalid_char_smaller=07089_E_‘¨¬¢®« < §¤¥áì ­¥ à §à¥è¥­
+% Ž¯¥à â®à ᤢ¨£  âॡã¥â ᨬ¢®«®¢ <<. ë« ®¡­ à㦥­ ⮫쪮 ®¤¨­ ¨§ ­¨å.
+asmr_e_invalid_char_greater=07090_E_‘¨¬¢®« > §¤¥áì ­¥ à §à¥è¥­
+% Ž¯¥à â®à ᤢ¨£  âॡã¥â ᨬ¢®«®¢ >>. ë« ®¡­ à㦥­ ⮫쪮 ®¤¨­ ¨§ ­¨å.
+asmr_w_align_not_supported=07093_W_ALIGN ­¥ ¯®¤¤¥à¦¨¢ ¥âáï
+asmr_e_no_inc_and_dec_together=07094_E_Inc ¨ Dec ­¥ ¬®£ã⠨ᯮ«ì§®¢ âìáï ®¤­®¢à¥¬¥­­®
+% Ž¤­®¢à¥¬¥­­®¥ ¨á¯®«ì§®¢ ­¨¥ ¨­ªà¥¬¥­â  ¨ ¤¥ªà¥¬¥­â  ¢ ®¤­®¬ ®¯¥à ­¤¥
+% ­  680x0. â® ­¥¤®¯ãá⨬®.
+asmr_e_invalid_reg_list_in_movem=07095_E_¥¢¥à­ë© ᯨ᮪ ॣ¨áâ஢ ¤«ï movem
+% ˆá¯®«ì§®¢ ­¨¥ ¨­áâàãªæ¨¨ \var{movem} á ­¥¢¥à­ë¬¨ ॣ¨áâà ¬¨ ¤«ï á®åà ­¥­¨ï/¢®ááâ ­®¢«¥­¨ï.
+asmr_e_invalid_reg_list_for_opcode=07096_E_¥¢¥à­ë© ᯨ᮪ ॣ¨áâ஢ ¤«ï ª®¬ ­¤ë
+asmr_e_higher_cpu_mode_required=07097_E_’ॡã¥âáï ०¨¬ ¡®«¥¥ ᮢ६¥­­®£® ¯à®æ¥áá®à  ($1)
+% ˆá¯®«ì§®¢ ­¨¥ ¨­áâàãªæ¨¨, ª®â®à ï ­¥ ¯®¤¤¥à¦¨¢ ¥âáï ¢ ⥪ã饬 ०¨¬¥ ¯à®æ¥áá®à .
+% ˆá¯®«ì§ã©â¥ ०¨¬ ¤«ï á«¥¤ãîé¨å ¯®ª®«¥­¨© ¯à®æ¥áá®à®¢.
+asmr_w_unable_to_determine_reference_size_using_dword=07098_W_ §¬¥à ®¯¥à ­¤®¢ ­¥ 㪠§ ­ ¨ ¥£® ­¥ 㤠¥âáï ®¯à¥¤¥«¨âì, ¨á¯®«ì§ã¥âáï DWORD ¯® 㬮«ç ­¨î
+%  §¬¥à áá뫪¨ á«¥¤ã¥â 㪠§ âì ®, â.ª. ª®¬¯¨«ïâ®à ­¥ ¬®¦¥â
+% ®¯à¥¤¥«¨âì, ª ª®© à §¬¥à (byte,word,dword ¨ â.¤.) ®­
+% ¤®«¦¥­ ¨á¯®«ì§®¢ âì. ‚뤠¥âáï ⮫쪮 ¢ ०¨¬¥ Delphi, ª®£¤ 
+% ¯® 㬮«ç ­¨î ¨á¯®«ì§ã¥âáï à §¬¥à DWORD.
+asmr_e_illegal_shifterop_syntax=07099_E_‘¨­â ªá¨ç¥áª ï ®è¨¡ª  ¢ ®¯¥à ­¤¥ ᤢ¨£ 
+% ’®«ìª® ARM;  áᥬ¡«¥à ARM ¯®¤¤¥à¦¨¢ ¥â â.­. ®¯¥à ­¤ ᤢ¨£ . ˆá¯®«ì§®¢ ­­ë© ¤«ï ­¥£® ᨭ⠪á¨á
+% ­¥¢¥à¥­. ਬ¥à ¨­áâàãªæ¨¨ á ®¯¥à ­¤®¬ ᤢ¨£ :
+% \begin{verbatim}
+% asm
+% orr r2,r2,r2,lsl #8
+% end;
+% \end{verbatim}
+asmr_e_packed_element=07100_E_€¤à¥á 㯠ª®¢ ­­®£® ª®¬¯®­¥­â  ­¥ ᮢ¯ ¤ ¥â á £à ­¨æ¥© ¡ ©â 
+% “¯ ª®¢ ­­ë¥ ª®¬¯®­¥­âë (¯®«ï § ¯¨á¥© ¨ í«¥¬¥­âë ¬ áᨢ®¢) ¬®£ãâ ­ ç¨­ âìáï
+% á ¯à®¨§¢®«ì­®£® ¡¨â  ¢ ¡ ©â¥. ‘«¥¤®¢ â¥«ì­®, ­  ¯à®æ¥áá®à¥, ­¥ ¯®¤¤¥à¦¨¢ î饣®
+% ¡¨â®¢ãî  ¤à¥á æ¨î ¯ ¬ï⨠(  ¢á¥ ¯®¤¤¥à¦¨¢ ¥¬ë¥ FPC ¯à®æ¥áá®àë ïîâáï ¨¬¥­­® â ª¨¬¨),
+% ¡ã¤¥â ¢ë¤ ­  ®è¨¡ª  ¯à¨ ¯®¯ë⪥ ¤®áâ㯠 ¯® ¨­¤¥ªáã ª ¬ áᨢ ¬, à §¬¥à í«¥¬¥­â  ª®â®àëå
+% ­¥ ªà â¥­ 8 ¡¨â ¬. â® á¯à ¢¥¤«¨¢® ¨ ¤«ï ¯®«¥© § ¯¨á¥© á â ª¨¬¨  ¤à¥á ¬¨.
+asmr_w_unable_to_determine_reference_size_using_byte=07101_W_ §¬¥à ®¯¥à ­¤®¢ ­¥ 㪠§ ­ ¨ ¥£® ­¥ 㤠¥âáï ®¯à¥¤¥«¨âì, ¨á¯®«ì§ã¥âáï BYTE ¯® 㬮«ç ­¨î
+%  §¬¥à áá뫪¨ á«¥¤ã¥â 㪠§ âì ®, â.ª. ª®¬¯¨«ïâ®à ­¥ ¬®¦¥â
+% ®¯à¥¤¥«¨âì, ª ª®© à §¬¥à (byte,word,dword ¨ â.¤.) ®­
+% ¤®«¦¥­ ¨á¯®«ì§®¢ âì. ‚뤠¥âáï ⮫쪮 ¢ ०¨¬¥ Delphi, ª®£¤ 
+% ¯® 㬮«ç ­¨î ¨á¯®«ì§ã¥âáï à §¬¥à BYTE.
+asmr_w_no_direct_ebp_for_parameter=07102_W_‡¤¥áì ­¥«ì§ï ¨á¯®«ì§®¢ âì +offset(%ebp) ¤«ï ¯ à ¬¥â஢
+% ˆá¯®«ì§®¢ ­¨¥ ¯àאַ© áá뫪¨ ¢¨¤  8(%ebp) ¤«ï ¯ à ¬¥â஢ ¯à®æ¥¤ãàë/ä㭪樨 ­¥¢¥à­®, ¥á«¨
+% ¯ à ¬¥âàë ­ å®¤ïâáï ¢ ॣ¨áâà å.
+asmr_w_direct_ebp_for_parameter_regcall=07103_W_ˆá¯®«ì§®¢ ­¨¥ +offset(%ebp) ­¥á®¢¬¥á⨬® á ⨯®¬ ¢ë§®¢  regcall
+% ˆá¯®«ì§®¢ ­¨¥ ¯àאַ© áá뫪¨ ¢¨¤  8(%ebp) ¤«ï ¯ à ¬¥â஢ ¯à®æ¥¤ãàë/ä㭪樨 ­¥¢¥à­®, ¥á«¨
+% ¯ à ¬¥âàë ­ å®¤ïâáï ¢ ॣ¨áâà å.
+asmr_w_direct_ebp_neg_offset=07104_W_ˆá¯®«ì§®¢ ­¨¥ -offset(%ebp) ¤«ï «®ª «ì­ëå ¯¥à¥¬¥­­ëå ­¥ ४®¬¥­¤ã¥âáï
+% ˆá¯®«ì§®¢ ­¨¥ ááë«®ª ¢¨¤  -8(%ebp) ¤«ï ¤®áâ㯠 ª «®ª «ì­ë¬ ¯¥à¥¬¥­­ë¬ ­¥ ४®¬¥­¤ã¥âáï.
+asmr_w_direct_esp_neg_offset=07105_W_ˆá¯®«ì§®¢ ­¨¥ -offset(%esp), ¢®§¬®¦¥­ á¡®© ¯à¨ ¤®áâ㯥 ¨«¨ ¯®â¥àï §­ ç¥­¨ï
+% ˆá¯®«ì§®¢ ­¨¥ ááë«®ª ¢¨¤  -8(%esp) ¤«ï ¤®áâ㯠 ª «®ª «ì­®¬ã á⥪㠭¥ ४®¬¥­¤ã¥âáï,
+% ¯®â®¬ã çâ® íâ  ç áâì á⥪  ¬®¦¥â ¡ëâì § â¥àâ  ¯à¨ ¢ë§®¢¥ «î¡®© ä㭪樨 ¨«¨ ¯à¨ ¯à¥à뢠­¨¨.
+asmr_e_no_vmtoffset_possible=07106_E_VMTOffset á«¥¤ã¥â ¨á¯®«ì§®¢ âì ¢ ª®¬¡¨­ æ¨¨ á ¢¨àâã «ì­ë¬ ¬¥â®¤®¬, "$1" ­¥ ï¥âáï ¢¨àâã «ì­ë¬
+% ’®«ìª® ¢¨àâã «ì­ë¥ ¬¥â®¤ë ¨¬¥îâ ᬥ饭¨¥ ¢ VMT.
+asmr_e_need_pic_ref=07107_E_‚ ०¨¬¥ ¯®§¨æ¨®­­®-­¥§ ¢¨á¨¬®£® ª®¤  ­ ©¤¥­  ¯®§¨æ¨®­­®-§ ¢¨á¨¬ ï áá뫪 
+% ¥¦¨¬ ª®¬¯¨«ï樨 ¯à¥¤ãᬠâਢ ¥â £¥­¥à æ¨î ¯®§¨æ¨®­­®-­¥§ ¢¨á¨¬®£® ª®¤ 
+% (PIC), ­® ¢ ¤ ­­®© ­ ¯¨á ­­®© ¢àãç­ãî  áᥬ¡«¥à­®© ¨­áâàãªæ¨¨ ᮤ¥à¦¨âáï
+% ¯®§¨æ¨®­­®-§ ¢¨á¨¬ ï áá뫪 .
+#
+# Assembler/binary writers
+#
+# 08020 is the last used one
+#
+asmw_f_too_many_asm_files=08000_F_‘«¨èª®¬ ¬­®£®  áᥬ¡«¥à­ëå ä ©«®¢
+% "“¬­ ï" ª®¬¯®­®¢ª  ¯à¨¢®¤¨â ª ¯®«ã祭¨î ᫨誮¬ ¡®«ì讣® ª®«¨ç¥á⢠
+%  áᥬ¡«¥à­ëå ä ©«®¢. Žâª«îç¨â¥ ¥¥.
+asmw_f_assembler_output_not_supported=08001_F_‚ë¡p ­­ë© ¢ë室­®© ä®à¬ â  áᥬ¡«¥p  ­¥ ¯®¤¤¥p¦¨¢ ¥âáï
+asmw_f_comp_not_supported=08002_F_COMP ­¥ ¯®¤¤¥p¦¨¢ ¥âáï
+asmw_f_direct_not_supported=08003_F_’¨¯  áᥬ¡«¥p  direct ­¥ ¯®¤¤¥p¦¨¢ ¥âáï á ¤¢®¨ç­ë¬ ¢ë室­ë¬ ä®à¬ â®¬
+% ’¨¯  áᥬ¡«¥à  direct ¯à¥¤¯®« £ ¥â § ¯¨áì ¯à®ç¨â ­­®£®  áᥬ¡«¥à­®£® ⥪áâ  ­ ¯àï¬ãî ¢ ¢ë室­®© ä ©«,
+% ¯à¨ í⮬ ¢ë室­®© ä ©« ­¥ ¬®¦¥â ¡ëâì ¤¢®¨ç­ë¬. ‚ë¡¥à¨â¥ ⥪áâ®¢ë© ä®à¬ â ¢ë室­ëå ä ©«®¢.
+asmw_e_alloc_data_only_in_bss=08004_E_‚뤥«¥­¨¥ ¯ ¬ï⨠¤«ï ¤ ­­ëå à §à¥è¥­® ⮫쪮 ¢ ᥪ樨 BSS
+asmw_f_no_binary_writer_selected=08005_F_¥ ¢ë¡à ­ ¤¢®¨ç­ë© ¢ë室­®© ä®à¬ â
+asmw_e_opcode_not_in_table=08006_E_Asm: Š®¤  ª®¬ ­¤ë $1 ­¥â ¢ ᯨ᪥
+asmw_e_invalid_opcode_and_operands=08007_E_Asm: $1 ­¥¢¥p­®¥ á®ç¥â ­¨¥ ª®¬ ­¤ë ¨ ®¯¥p ­¤®¢
+asmw_e_16bit_not_supported=08008_E_Asm: 16-¡¨â­ë¥ áá뫪¨ ­¥ ¯®¤¤¥p¦¨¢ îâáï
+asmw_e_invalid_effective_address=08009_E_Asm: H¥¢¥p­ë© íä䥪⨢­ë©  ¤p¥á
+asmw_e_immediate_or_reference_expected=08010_E_Asm: Ž¦¨¤ ¥âáï IMMEDIATE ¨«¨ áá뫪 
+asmw_e_value_exceeds_bounds=08011_E_Asm: §­ ç¥­¨¥ $1 ¢ë室¨â §  £p ­¨æë $2
+asmw_e_short_jmp_out_of_range=08012_E_Asm: Š®à®âª¨© ¯¥à¥å®¤ ¢ë室¨â §  £p ­¨æë $1
+asmw_e_undefined_label=08013_E_Asm: Œ¥âª  $1 ­¥ ®¯à¥¤¥«¥­ 
+asmw_e_comp_not_supported=08014_E_Asm: ’¨¯ comp ­¥ ¯®¤¤¥à¦¨¢ ¥âáï ¤«ï í⮩ ¯« âä®à¬ë
+asmw_e_extended_not_supported=08015_E_Asm: ’¨¯ extended ­¥ ¯®¤¤¥à¦¨¢ ¥âáï ¤«ï í⮩ ¯« âä®à¬ë
+asmw_e_duplicate_label=08016_E_Asm: ®¢â®àïîé ïáï ¬¥âª  $1
+asmw_e_redefined_label=08017_E_Asm: ®¢â®à­®¥ ®¯à¥¤¥«¥­¨¥ ¬¥âª¨ $1
+asmw_e_first_defined_label=08018_E_Asm: ¥à¢®­ ç «ì­® ®¯à¥¤¥«ï¥âáï §¤¥áì
+asmw_e_invalid_register=08019_E_Asm: ¥¢¥à­ë© ॣ¨áâà $1
+asmw_e_16bit_32bit_not_supported=08020_E_Asm: 16- ¨ 32-¡¨â­ë¥ áá뫪¨ ­¥ ¯®¤¤¥à¦¨¢ îâáï
+asmw_e_64bit_not_supported=08021_E_Asm: 64-¡¨â­ë¥ ®¯¥à ­¤ë ­¥ ¯®¤¤¥à¦¨¢ îâáï
+
+#
+# Executing linker/assembler
+#
+# 09032 is the last used one
+#
+# BeginOfTeX
+%
+% \section{Žè¨¡ª¨ áâ ¤¨¨  áᥬ¡«¨à®¢ ­¨ï/ª®¬¯®­®¢ª¨}
+% ¥à¥ç¨á«ïîâáï ®è¨¡ª¨, ª®â®àë¥ ¬®£ãâ ¨¬¥âì ¬¥áâ® ¢® ¢à¥¬ï ®¡à ¡®âª¨
+% ª®¬ ­¤­®© áâப¨ ¨ ä ©«®¢ ª®­ä¨£ãà æ¨¨.
+% \begin{description}
+exec_w_source_os_redefined=09000_W_ˆá室­ ï ®¯¥p æ¨®­­ ï á¨á⥬  ¯¥p¥®¯p¥¤¥«¥­ 
+% ˆá室­ ï ®¯¥à æ¨®­­ ï á¨áâ¥¬ë ¯¥à¥®¯à¥¤¥«¥­ .
+exec_i_assembling_pipe=09001_I_€áᥬ¡«¨py¥âáï (pipe) $1
+% €áᥬ¡«¨à®¢ ­¨¥ á ¨á¯®«ì§®¢ ­¨¥¬ ª ­ «  (pipe) ¤«ï ®¡¬¥­  ¤ ­­ë¬¨ á ¢­¥è­¨¬  áᥬ¡«¥à®¬.
+exec_d_cant_create_asmfile=09002_E_H¥¢®§¬®¦­® ᮧ¤ âì  áᬥ¡«¥p­ë© ä ©«: $1
+% “ª § ­­ë© ä ©« ­¥ ¬®¦¥â ¡ëâì ᮧ¤ ­. ஢¥àìâ¥, ¥á«¨ «¨
+% à §à¥è¥­¨¥ ­  ᮧ¤ ­¨¥ ä ©« .
+exec_e_cant_create_objectfile=09003_E_¥¢®§¬®¦­® ᮧ¤ âì ®¡ê¥ªâ­ë© ä ©«: $1
+% “ª § ­­ë© ä ©« ­¥ ¬®¦¥â ¡ëâì ᮧ¤ ­. ஢¥àìâ¥, ¥á«¨ «¨
+% à §à¥è¥­¨¥ ­  ᮧ¤ ­¨¥ ä ©« .
+exec_e_cant_create_archivefile=09004_E_¥¢®§¬®¦­® ᮧ¤ âì ä ©«  à娢 : $1
+% “ª § ­­ë© ä ©« ­¥ ¬®¦¥â ¡ëâì ᮧ¤ ­. ஢¥àìâ¥, ¥á«¨ «¨
+% à §à¥è¥­¨¥ ­  ᮧ¤ ­¨¥ ä ©« .
+exec_e_assembler_not_found=09005_E_€áᥬ¡«¥p $1 ­¥ ­ ©¤¥­, ¯¥à¥å®¤ ­  ¢­¥è­îî á¡®àªã
+% ணࠬ¬   áᥬ¡«¥à  ­¥ ­ ©¤¥­ . Š®¬¯¨«ïâ®à ᮧ¤ áâ áªà¨¯â,
+% ¯®§¢®«ïî騩  áᥬ¡«¨à®¢ âì ¨ ᪮¬¯®­®¢ âì ¯à®£à ¬¬ã ¯®§¤­¥¥.
+exec_t_using_assembler=09006_T_ˆá¯®«ì§y¥âáï  áᥬ¡«¥p: $1
+% ˆ­ä®à¬ æ¨ï ® ⮬, ª ª®© ¨¬¥­­®  áᥬ¡«¥à ¨á¯®«ì§ã¥âáï.
+exec_e_error_while_assembling=09007_E_Žè¨¡ª   áᥬ¡«¨p®¢ ­¨ï, ª®¤ ¢®§¢à â  $1
+% ਠ®¡à ¡®âª¥ ä ©«  ¢­¥è­¨¬  áᥬ¡«¥à®¬ ¯à®¨§®è«  ®è¨¡ª . ®¤à®¡­®áâ¨
+% ¬®¦­® ­ ©â¨ ¢ à㪮¢®¤á⢥ ª ¨á¯®«ì§ã¥¬®© ¯à®£à ¬¬¥  áᥬ¡«¥à .
+exec_e_cant_call_assembler=09008_E_Žè¨¡ª  $1 ¯à¨ § ¯ã᪥  áᥬ¡«¥à , ¯¥à¥å®¤ ­  ¢­¥è­îî á¡®àªã
+% Žè¨¡ª  ¯à¨ § ¯ã᪥ ¢­¥è­¥£®  áᥬ¡«¥à . Š®¬¯¨«ïâ®à ᮧ¤ áâ áªà¨¯â,
+% ¯®§¢®«ïî騩  áᥬ¡«¨à®¢ âì ¨ ᪮¬¯®­®¢ âì ¯à®£à ¬¬ã ¯®§¤­¥¥.
+exec_i_assembling=09009_I_€áᥬ¡«¨pã¥âáï $1
+% ˆ­ä®à¬ æ¨ï ® ⮬, ª ª®© ä ©«  áᥬ¡«¨àã¥âáï.
+exec_i_assembling_smart=09010_I_€áᥬ¡«¨pã¥âáï á "㬭®©" ᡮમ© $1
+% ˆ­ä®à¬ æ¨ï ® ⮬, ª ª®© ä ©«  áᥬ¡«¨àã¥âáï á ¯®¤¤¥à¦ª®© "㬭®©" ᡮન.
+exec_w_objfile_not_found=09011_W_Ž¡ê¥ªâ­ë© ä ©« $1 ­¥ ­ ©¤¥­, ª®¬¯®­®¢ª  ¬®¦¥â ­¥ y¤ âìáï!
+% Ž¤¨­ ¨§ ®¡ê¥ªâ­ëå ä ©«®¢ ­¥ ­ ©¤¥­, ¨ ª®¬¯®­®¢ª , ᪮॥ ¢á¥£®, ­¥ 㤠áâáï.
+% ஢¥àì⥠¯ãâ¨.
+exec_w_libfile_not_found=09012_W_¨¡«¨®â¥ª  $1 ­¥ ­ ©¤¥­ , ª®¬¯®­®¢ª  ¬®¦¥â ­¥ y¤ âìáï!
+% Ž¤¨­ ¨§ ä ©«®¢ ¡¨¡«¨®â¥ª ­¥ ­ ©¤¥­, ¨ ª®¬¯®­®¢ª , ᪮॥ ¢á¥£®, ­¥ 㤠áâáï.
+% ஢¥àì⥠¯ãâ¨.
+exec_e_error_while_linking=09013_E_Žè¨¡ª  ¯p¨ ª®¬¯®­®¢ª¥
+% Ž¡é ï ®è¨¡ª  ¯à¨ ª®¬¯®­®¢ª¥.
+exec_e_cant_call_linker=09014_E_H¥ 㤠¥âáï ¢ë§¢ âì ª®¬¯®­®¢é¨ª, ¯¥à¥å®¤ ­  ¢­¥è­îî ª®¬¯®­®¢ªã
+% Žè¨¡ª  ¯à¨ § ¯ã᪥ ¢­¥è­¥£® ª®¬¯®­®¢é¨ª . Š®¬¯¨«ïâ®à ᮧ¤ áâ áªà¨¯â,
+% ¯®§¢®«ïî騩  áᥬ¡«¨à®¢ âì ¨ ᪮¬¯®­®¢ âì ¯à®£à ¬¬ã ¯®§¤­¥¥.
+exec_i_linking=09015_I_Š®¬¯®­®¢ª  $1
+% ˆ­ä®à¬ æ¨ï ® ⮬, ª ª ï ¯à®£à ¬¬  ¨«¨ ¡¨¡«¨®â¥ª  ª®¬¯®­ã¥âáï.
+exec_e_util_not_found=09016_E_“⨫¨â  $1 ­¥ ­ ©¤¥­ , ¯¥p¥å®¤ ­  ¢­¥è­îî ª®¬¯®­®¢ªã
+% ‚­¥è­ïï ã⨫¨â  ­¥ ­ ©¤¥­ . Š®¬¯¨«ïâ®à ᮧ¤ áâ áªà¨¯â,
+% ¯®§¢®«ïî騩 ¯à®¨§¢¥á⨠­¥ã¤ ¢è¨¥áï ¤¥©áâ¢¨ï ¯®§¤­¥¥.
+exec_t_using_util=09017_T_ˆá¯®«ì§ã¥âáï ã⨫¨â  $1
+% ˆ­ä®à¬ æ¨®­­®¥ á®®¡é¥­¨¥ ® ⮬, ª ª ï ã⨫¨â  ¨á¯®«ì§ã¥âáï (®¡ëç­® íâ® ¯®áâ-¯à®æ¥áá®à).
+exec_e_exe_not_supported=09018_E_‘®§¤ ­¨¥ ¨á¯®«­ï¥¬ëå ä ©«®¢ ­¥ ¯®¤¤¥p¦¨¢ ¥âáï
+% ‘®§¤ ­¨¥ ¨á¯®«­ï¥¬ëå ä ©«®¢ ¤«ï í⮩ ¯« âä®à¬ë ¥é¥ ­¥ ॠ«¨§®¢ ­® ¢ ª®¬¯¨«ïâ®à¥
+% ¨ ¯®â®¬ã ­¥¢®§¬®¦­®.
+exec_e_dll_not_supported=09019_E_‘®§¤ ­¨¥ ¤¨­ ¬¨ç¥áª¨å ¡¨¡«¨®â¥ª (DLL) ­¥ ¯®¤¤¥p¦¨¢ îâáï
+% ‘®§¤ ­¨¥ ¤¨­ ¬¨ç¥áª¨ § £à㦠¥¬ëå ¡¨¡«¨®â¥ª ¤«ï í⮩ ¯« âä®à¬ë ¥é¥ ­¥ ॠ«¨§®¢ ­® ¢ ª®¬¯¨«ïâ®à¥
+% ¨ ¯®â®¬ã ­¥¢®§¬®¦­®.
+exec_i_closing_script=09020_I_‘®§¤ ­ áªp¨¯â $1
+% ˆ­ä®à¬ æ¨ï ®¡ ®ª®­ç ­¨¨ § ¯¨á¨ áªà¨¯â  ¤«ï ¢­¥è­¥£®  áᥬ¡«¨à®¢ ­¨ï/ª®¬¯®­®¢ª¨.
+exec_e_res_not_found=09021_E_Š®¬¯¨«ïâ®p p¥áypᮢ "$1" ­¥ ­ ©¤¥­, ¯¥p¥å®¤ ¢® ¢­¥è­¨© ०¨¬
+% Žè¨¡ª  ¯à¨ § ¯ã᪥ ¢­¥è­¥£® ª®¬¯¨«ïâ®à  à¥áãàᮢ. Š®¬¯¨«ïâ®à ᮧ¤ áâ áªà¨¯â,
+% ¯®§¢®«ïî騩 ¢ë¯®«­¨âì ­¥ã¤ ¢è¨¥áï ¤¥©áâ¢¨ï ¨ § ¢¥àè¨âì ᮧ¤ ­¨¥ ¯à®£à ¬¬ë ¯®§¤­¥¥.
+exec_i_compilingresource=09022_I_Š®¬¯¨«ïæ¨ï p¥áypá  $1
+% ˆ­ä®à¬ æ¨ï ® ⮬, ª ª®© ä ©« à¥áãàᮢ ª®¬¯¨«¨àã¥âáï.
+exec_t_unit_not_static_linkable_switch_to_smart=09023_T_¬®¤y«ì $1 ­¥ ¬®¦¥â ¡ëâì ᪮¬¯®­®¢ ­ áâ â¨ç¥áª¨, ¯¥à¥å®¤ ­  "㬭ãî" ª®¬¯®­®¢ªã
+% ‡ ¯à®è¥­  áâ â¨ç¥áª ï ª®¬¯®­®¢ª , ­® ¨á¯®«ì§®¢ ­­ë© ¬®¤ã«ì ­¥ ¤®¯ã᪠¥â íâ®â ०¨¬.
+exec_t_unit_not_smart_linkable_switch_to_static=09024_T_¬®¤y«ì $1 ­¥ ¬®¦¥â ¡ëâì ᪮¬¯®­®¢ ­ ¢ "㬭®¬" p¥¦¨¬¥, ¯¥à¥å®¤ ­  áâ â¨ç¥áªãî ª®¬¯®­®¢ªã
+% ‡ ¯à®è¥­  "㬭 ï" ª®¬¯®­®¢ª , ­® ¨á¯®«ì§®¢ ­­ë© ¬®¤ã«ì ­¥ ¤®¯ã᪠¥â íâ®â ०¨¬.
+exec_t_unit_not_shared_linkable_switch_to_static=09025_T_¬®¤y«ì $1 ­¥ ¬®¦¥â ¡ëâì ᪮¬¯®­®¢ ­ ¢ p¥¦¨¬¥ shared, ¯¥à¥å®¤ ­  áâ â¨ç¥áªãî ª®¬¯®­®¢ªã
+% ‡ ¯à®è¥­  à §¤¥«ï¥¬ ï ª®¬¯®­®¢ª , ­® ¨á¯®«ì§®¢ ­­ë© ¬®¤ã«ì ­¥ ¤®¯ã᪠¥â íâ®â ०¨¬.
+exec_e_unit_not_smart_or_static_linkable=09026_E_¬®¤y«ì $1 ­¥ ¬®¦¥â ¡ëâì ᪮¬¯®­®¢ ­ ¢ p¥¦¨¬ å smart ¨«¨ static
+% ‡ ¯à®è¥­  "㬭 ï" ¨«¨ áâ â¨ç¥áª ï ª®¬¯®­®¢ª , ­® ¨á¯®«ì§®¢ ­­ë© ¬®¤ã«ì ­¥ ¤®¯ã᪠¥â ­¨ ®¤¨­ ¨§ íâ¨å ०¨¬®¢.
+exec_e_unit_not_shared_or_static_linkable=09027_E_¬®¤y«ì $1 ­¥ ¬®¦¥â ¡ëâì ᮡp ­ ¢ p¥¦¨¬ å shared ¨«¨ static
+% ‡ ¯à®è¥­  à §¤¥«ï¥¬ ï ¨«¨ áâ â¨ç¥áª ï ª®¬¯®­®¢ª , ­® ¨á¯®«ì§®¢ ­­ë© ¬®¤ã«ì ­¥ ¤®¯ã᪠¥â ­¨ ®¤¨­ ¨§ íâ¨å ०¨¬®¢.
+exec_d_resbin_params=09028_D_‚맮¢ ª®¬¯¨«ïâ®à  à¥áãàᮢ "$1" á ª®¬ ­¤­®© áâப®© "$2"
+% ˆ­ä®à¬ æ¨ï ®¡ ¨á¯®«ì§ã¥¬®¬ ª®¬¯¨«ïâ®à¥ à¥áãàᮢ ¨ ¥£® ª®¬ ­¤­®© áâப¥.
+exec_e_error_while_compiling_resources=09029_E_Žè¨¡ª  ¯à¨ ª®¬¯¨«ï樨 à¥áãàᮢ
+% Š®¬¯¨«ïâ®à ¨«¨ ª®­¢¥àâ®à à¥áãàᮢ § ¢¥à訫áï á ®è¨¡ª®©.
+exec_e_cant_call_resource_compiler=09030_E_‚맮¢ ª®¬¯¨«ïâ®à  à¥áãàᮢ "$1" ­¥¢®§¬®¦¥­, ¯¥à¥å®¤ ¢® ¢­¥è­¨© ०¨¬
+% Žè¨¡ª  ¯à¨ ¢ë§®¢¥ ª®¬¯¨«ïâ®à  à¥áãàᮢ. Š®¬¯¨«ïâ®à ᮧ¤ áâ áªà¨¯â,
+% ¯®§¢®«ïî騩 ¯®¢â®à¨âì ­¥ã¤ ¢è¨¥áï ¤¥©áâ¢¨ï ¨ § ¢¥àè¨âì ᮧ¤ ­¨¥ ¯à®£à ¬¬ë
+% ¯®§¤­¥¥.
+exec_e_cant_open_resource_file=09031_E_¥¢®§¬®¦­® ®âªàëâì ä ©« à¥áãàᮢ "$1"
+% Žè¨¡ª  ¯à¨ ®âªàë⨨ 㪠§ ­­®£® ä ©«  à¥áãàᮢ.
+exec_e_cant_write_resource_file=09032_E_Žè¨¡ª  § ¯¨á¨ ä ©«  à¥áãàᮢ "$1"
+% Žè¨¡ª  ¯à¨ § ¯¨á¨ 㪠§ ­­®£® ä ©«  à¥áãàᮢ.
+%\end{description}
+# EndOfTeX
+
+#
+# Executable information
+#
+# 09134 is the last used one
+#
+# BeginOfTeX
+% \section{ˆ­ä®à¬ æ¨ï ®¡ ¨á¯®«­ï¥¬ëå ä ©« å.}
+% ‘®¤¥à¦¨â á®®¡é¥­¨ï, ¢ë¤ ¢ ¥¬ë¥ ¯à¨ ᮧ¤ ­¨¨ ¨á¯®«­ï¥¬®£® ä ©« 
+% á ¨á¯®«ì§®¢ ­¨¥¬ ¢­ãâ७­¥£® ª®¬¯®­®¢é¨ª .
+% \begin{description}
+execinfo_f_cant_process_executable=09128_F_®áâ-®¡à ¡®âª  ¨á¯®«­ï¥¬®£® ä ©«  $1 ­¥¢®§¬®¦­ 
+% ” â «ì­ ï ®è¨¡ª  ¯à¨ ­¥¢®§¬®¦­®á⨠¯®áâ-®¡à ¡®âª¨ ¨á¯®«­ï¥¬®£® ä ©« .
+execinfo_f_cant_open_executable=09129_F_¥¢®§¬®¦­® ®âªàëâì ¨á¯®«­ï¥¬ë© ä ©« $1
+% ” â «ì­ ï ®è¨¡ª  ¯à¨ ­¥¢®§¬®¦­®á⨠®âªàëâì ¨á¯®«­ï¥¬ë© ä ©«.
+execinfo_x_codesize=09130_X_ §¬¥à ª®¤ : $1 ¡ ©â
+% ˆ­ä®à¬ æ¨ï ® à §¬¥à¥ ᮧ¤ ­­®© ᥪ樨 ª®¤ .
+execinfo_x_initdatasize=09131_X_ §¬¥à ¨­¨æ¨ «¨§¨à®¢ ­­ëå ¤ ­­ëå: $1 ¡ ©â
+% ˆ­ä®à¬ æ¨ï ® à §¬¥à¥ ᮧ¤ ­­®© ᥪ樨 ¨­¨æ¨ «¨§¨à®¢ ­­ëå ¤ ­­ëå.
+execinfo_x_uninitdatasize=09132_X_ §¬¥à ­¥¨­¨æ¨ «¨§¨à®¢ ­­ëå ¤ ­­ëå: $1 bytes
+% ˆ­ä®à¬ æ¨ï ® à §¬¥à¥ ᥪ樨 ­¥¨­¨æ¨ «¨§¨à®¢ ­­ëå ¤ ­­ëå.
+execinfo_x_stackreserve=09133_X_ §¬¥à á⥪  (§ à¥§¥à¢¨à®¢ ­­ë©): $1 bytes
+% ˆ­ä®à¬ æ¨ï ® § à¥§¥à¢¨à®¢ ­­®¬ à §¬¥à¥ á⥪  ¨á¯®«­ï¥¬®£® ä ©« .
+execinfo_x_stackcommit=09134_X_ §¬¥à á⥪  (¯®¤ª«î祭­ë©): $1 bytes
+% ˆ­ä®à¬ æ¨ï ® ¯®¤ª«î祭­®¬ à §¬¥à¥ á⥪  ¨á¯®«­ï¥¬®£® ä ©« .
+%\end{description}
+# EndOfTeX
+
+#
+# Internal linker messages
+#
+# 09200 is the last used one
+#
+# BeginOfTeX
+% \section{‘®®¡é¥­¨ï ª®¬¯®­®¢é¨ª }
+% ‘®®¡é¥­¨ï, ¢ë¤ ¢ ¥¬ë¥ ¢­ãâ७­¨¬ ª®¬¯®­®¢é¨ª®¬.
+% \begin{description}
+link_f_executable_too_big=09200_F_ §¬¥à ¨á¯®«­ï¥¬®£® ®¡à §  ᫨誮¬ ¢¥«¨ª ¤«ï ¯« âä®à¬ë $1.
+% ” â «ì­ ï ®è¨¡ª , ¢®§­¨ª îé ï ¢ á«ãç ¥, ¥á«¨ ᮧ¤ ­­ë© ¨á¯®«­ï¥¬ë© ä ©« ᫨誮¬ ¢¥«¨ª.
+link_w_32bit_absolute_reloc=09201_W_Ž¡ê¥ªâ­ë© ä ©« "$1" ᮤ¥à¦¨â 32-¡¨â­®¥  ¡á®«îâ­®¥ ¯¥à¥¬¥é¥­¨¥ ¤«ï ᨬ¢®«  "$2".
+% ‚ á«ãç ¥, ª®£¤  64-¡¨â­ë© ®¡ê¥ªâ­ë© ä ©« ᮤ¥à¦¨â 32-¡¨â­ë¥  ¡á®«îâ­ë¥ ¯¥à¥¬¥é¥­¨ï,
+% ¯®«ã祭­ë© ¨á¯®«­ï¥¬ë© ®¡à § ¬®¦¥â ¡ëâì § £à㦥­ ⮫쪮 ¢ ­¨¦­¨¥ 4 ƒ  ¤à¥á­®£®
+% ¯à®áâà ­á⢠.
+%\end{description}
+# EndOfTeX
+
+#
+# Unit loading
+#
+# 10061 is the last used one
+#
+# BeginOfTeX
+% \section{‘®®¡é¥­¨ï § £à㧪¨ ¬®¤ã«¥©.}
+% ‘®®¡é¥­¨ï, ¢ë¤ ¢ ¥¬ë¥ ¯à¨ § £à㧪¥ ¬®¤ã«¥© á ¤¨áª  ¢ ¯ ¬ïâì.
+% Œ­®£¨¥ ¨§ ­¨å ­®áïâ ¨­ä®à¬ æ¨®­­ë© å à ªâ¥à.
+% \begin{description}
+unit_t_unitsearch=10000_T_®¨áª ¬®¤y«ï: $1
+% ਠ¨á¯®«ì§®¢ ­¨¨ ª«îç  \var{-vt} á®®¡é ¥â ® ⮬, £¤¥ ª®¬¯¨«ïâ®à ¨é¥â
+% ä ©«ë ¬®¤ã«¥©.
+unit_t_ppu_loading=10001_T_‡ £py§ª  PPU $1
+% ਠ¨á¯®«ì§®¢ ­¨¨ ª«îç  \var{-vt} á®®¡é ¥â ¨¬ï ä ©«  § £à㦠¥¬®£® ¬®¤ã«ï.
+unit_u_ppu_name=10002_U_ˆ¬ï PPU: $1
+% ਠ¨á¯®«ì§®¢ ­¨¨ ª«îç  \var{-vu} á®®¡é ¥â ¨¬ï ¬®¤ã«ï.
+unit_u_ppu_flags=10003_U_”« £¨ PPU: $1
+% ਠ¨á¯®«ì§®¢ ­¨¨ ª«îç  \var{-vu} ¯®ª §ë¢ ¥â ä« £¨ ¬®¤ã«ï.
+unit_u_ppu_crc=10004_U_CRC PPU: $1
+% ਠ¨á¯®«ì§®¢ ­¨¨ ª«îç  \var{-vu} ¯®ª §ë¢ ¥â ª®­â஫ì­ãî á㬬㠬®¤ã«ï.
+unit_u_ppu_time=10005_U_∴• PPU: $1
+% ਠ¨á¯®«ì§®¢ ­¨¨ ª«îç  \var{-vu} ¯®ª §ë¢ ¥â ¢à¥¬ï, ª®£¤  ¬®¤ã«ì ¡ë« ᪮¬¯¨«¨à®¢ ­.
+unit_u_ppu_file_too_short=10006_U_PPU ä ©« ᫨誮¬ ª®p®âª¨©
+% ” ©« ¬®¤ã«ï ᫨誮¬ ª®à®âª¨©, ¢ ­¥¬ ᮤ¥à¦ âáï ­¥ ¢á¥ ®¡ê¥­¨ï.
+unit_u_ppu_invalid_header=10007_U_H¥¢¥p­ë© § £®«®¢®ª PPU (­¥â ᨣ­ âãàë PPU ¢ ­ ç «¥)
+% ¥à¢ë¬¨ âà¥¬ï ¡ ©â ¬¨ ä ©«  PPU ¤®«¦­ë ¡ëâì ª®¤ë ᨬ¢®«®¢ \var{PPU}
+unit_u_ppu_invalid_version=10008_U_H¥¢¥p­ ï ¢¥pá¨ï PPU ä ©«  $1
+% “ª § ­­ë© ä ©« ¬®¤ã«ï ¡ë« ᮧ¤ ­ ¤à㣮© ¢¥àᨥ© ª®¬¯¨«ïâ®à , ¨ ¯®í⮬㠭¥ ¬®¦¥â ¡ëâì
+% ¯à®ç¨â ­.
+unit_u_ppu_invalid_processor=10009_U_PPU ä ©« ᮧ¤ ­ ¤«ï ¤py£®£® ¯p®æ¥áá®p 
+% â®â ¬®¤ã«ì ¡ë« ᪮¬¯¨«¨à®¢ ­ ¤«ï ¤à㣮£® ⨯  ¯à®æ¥áá®à , ¨ ¯®í⮬㠭¥ ¬®¦¥â
+% ¡ëâì ¯à®ç¨â ­.
+unit_u_ppu_invalid_target=10010_U_PPU ä ©« ᮧ¤ ­ ¤«ï ¤py£®© Ž‘
+% â®â ¬®¤ã«ì ¡ë« ᪮¬¯¨«¨à®¢ ­ ¤«ï ¤à㣮© ®¯¥à æ¨®­­®© á¨á⥬ë, ¨ ¯®í⮬㠭¥ ¬®¦¥â
+% ¡ëâì ¯à®ç¨â ­.
+unit_u_ppu_source=10011_U_ˆá室­ë© ä ©« PPU: $1
+% ਠ¨á¯®«ì§®¢ ­¨¨ ª«îç  \var{-vu} ¯®ª §ë¢ ¥â ¨¬ï ¨á室­®£® ä ©«  ¬®¤ã«ï.
+unit_u_ppu_write=10012_U_‡ ¯¨áì $1
+% ਠ¨á¯®«ì§®¢ ­¨¨ ª«îç  \var{-vu} á®®¡é ¥â, ªã¤  ª®¬¯¨«ïâ®à § ¯¨á뢠¥â
+% ä ©« ¬®¤ã«ï.
+unit_f_ppu_cannot_write=10013_F_H¥¢®§¬®¦­® § ¯¨á âì PPU-ä ©«
+% ਠ§ ¯¨á¨ ä ©«  ¬®¤ã«ï ¯à®¨§®è«  ®è¨¡ª .
+unit_f_ppu_read_error=10014_F_Žè¨¡ª  ç⥭¨ï PPU-ä ©« 
+% ” ©« ¬®¤ã«ï ¯®¢à¥¦¤¥­ ¨ ᮤ¥à¦¨â ­¥¢¥à­ãî
+% ¨­ä®à¬ æ¨î. ®âॡã¥âáï ४®¬¯¨«ïæ¨ï.
+unit_f_ppu_read_unexpected_end=10015_F_¥®¦¨¤ ­­ë© ª®­¥æ PPU-ä ©« 
+% ¥®¦¨¤ ­­ë© ª®­¥æ ä ©« .
+unit_f_ppu_invalid_entry=10016_F_H¥¢¥à­ ï § ¯¨áì PPU-ä ©« : $1
+% ” ©« ¬®¤ã«ï ¯®¢à¥¦¤¥­, ¨«¨ ¡ë« ᮧ¤ ­ ¡®«¥¥ ­®¢®© ¢¥àᨥ© ª®¬¯¨«ïâ®à .
+unit_f_ppu_dbx_count_problem=10017_F_Žè¨¡ª  PPU DBX count
+% ¥áâ몮¢ª¨ ¢ ®â« ¤®ç­®© ¨­ä®à¬ æ¨¨ ¬®¤ã«ï.
+unit_e_illegal_unit_name=10018_E_H¥¢¥p­®¥ ¨¬ï ¬®¤y«ï: $1
+% ˆ¬ï ¬®¤ã«ï ­¥ ᮢ¯ ¤ ¥â á ¨¬¥­¥¬ ä ©«  ¬®¤ã«ï.
+unit_f_too_much_units=10019_F_‘«¨èª®¬ ¬­®£® ¬®¤y«¥©
+% Š®¬¯¨«ïâ®à ¨¬¥¥â ¯à¥¤¥« 1024 ¬®¤ã«ï ¢ ¯à®£à ¬¬¥. …£® ¬®¦­® 㢥«¨ç¨âì,
+% ¨§¬¥­¨¢ §­ ç¥­¨¥ ª®­áâ ­âë \var{maxunits} ¢ ä ©«¥ \file{files.pas} ª®¬¯¨«ïâ®à ,
+% ¨ ¯¥à¥ª®¬¯¨«¨à®¢ ¢ ª®¬¯¨«ïâ®à.
+unit_f_circular_unit_reference=10020_F_Š®«ì楢 ï áá뫪  ¬¥¦¤y ¬®¤ã«ï¬¨ $1 ¨ $2
+% „¢  ¬®¤ã«ï ¨á¯®«ì§ãîâ ¤à㣠¤à㣠 ¢ ¨­â¥à䥩᭮© ᥪ樨. â® à §à¥è¥­® ⮫쪮 ¢
+% ᥪ樨 \var{implementation}. ® ªà ©­¥© ¬¥à¥ ®¤¨­ ¨§ ¬®¤ã«¥© ¤®«¦¥­ ᮤ¥à¦ âì
+% áá뫪㠭  ¤à㣮© ¢ ᥪ樨 \var{implementation}.
+unit_f_cant_compile_unit=10021_F_Š®¬¯¨«ïæ¨ï ¬®¤y«ï $1 ­¥¢®§¬®¦­ , ®âáãâáâ¢ãîâ ¨á室­¨ª¨.
+%  ©¤¥­ ¬®¤ã«ì, âॡãî騩 ¯¥à¥ª®¬¯¨«ï樨, ­® ¨á室­ë¥ ä ©«ë ¤«ï ­¥£® ®âáãâáâ¢ãîâ.
+unit_f_cant_find_ppu=10022_F_H¥ ­ ©¤¥­ ¬®¤ã«ì $1, ¨á¯®«ì§ã¥¬ë© $2
+% ®¯ë⪠ ¨á¯®«ì§®¢ ­¨ï ¬®¤ã«ï, ¤«ï ª®â®à®£® ­¥ ­ ©¤¥­ ä ©« PPU.
+% ஢¥àì⥠¯ã⨠¬®¤ã«¥© ¢ ä ©«¥ ª®­ä¨£ãà æ¨¨.
+unit_w_unit_name_error=10023_W_Œ®¤ã«ì $1 ­¥ ­ ©¤¥­, ­® $2 áãé¥áâ¢ã¥â
+% ®«ìè¥ ­¥ ¨á¯®«ì§ã¥âáï.
+unit_f_unit_name_error=10024_F_ਠ¯®¨áª¥ ¬®¤ã«ï $1 ¡ë« ­ ©¤¥­ $2
+% Ž£à ­¨ç¥­¨¥ DOS ­  ¤«¨­ã ¨¬¥­ ä ©«®¢ ¢ 8 ᨬ¢®«®¢ ¬®¦¥â ¢ë§ë¢ âì
+% ¯à®¡«¥¬ë, ¥á«¨ ¨¬ï ¬®¤ã«ï ¨¬¥¥â ¡®«ìèãî ¤«¨­ã.
+unit_w_switch_us_missed=10025_W_„«ï ª®¬¯¨«ï樨 ¬®¤ã«ï system âॡã¥âáï ª«îç -Us
+% ਠª®¬¯¨«ï樨 ¬®¤ã«ï system (âॡãî饣® ®á®¡®© ®¡à ¡®âª¨), á«¥¤ã¥â
+% 㪠§ë¢ âì ª«îç \var{-Us}.
+unit_f_errors_in_unit=10026_F_p¨ ª®¬¯¨«ï樨 ¬®¤y«ï ¯à®¨§®è«® $1 ®è¨¡®ª, à ¡®â  ¯à¥à¢ ­ 
+% Š®¬¯¨«ïâ®à ¯à¥ªà é ¥â à ¡®âã á í⨬ á®®¡é¥­¨¥¬ ¯à¨ ¢®§­¨ª­®¢¥­¨¨ ä â «ì­®© ®è¨¡ª¨,
+% ¨«¨ ¯à¨ ¯à¥¢ë襭¨¨ ¯à¥¤¥«ì­®£® ª®«¨ç¥á⢠ ®è¨¡®ª.
+unit_u_load_unit=10027_U_‡ £py§ª  ¨§ $1 ($2) ¬®¤y«ì $3
+% ਠ¨á¯®«ì§®¢ ­¨¨ ª«îç  \var{-vu} á®®¡é ¥â, ª®â®àë© ¬®¤ã«ì ®âªã¤  § £à㦠¥âáï.
+% shown.
+unit_u_recompile_crc_change=10028_U_¥p¥ª®¬¯¨«ïæ¨ï $1, ¨§¬¥­¨« áì ª®­âp®«ì­ ï áy¬¬  $2
+% Œ®¤ã«ì ¯¥à¥ª®¬¯¨«¨àã¥âáï, ¯®â®¬ã çâ® ¨§¬¥­¨« áì ª®­â஫쭠ï á㬬  ¬®¤ã«ï, ®â ª®â®à®£®
+% ®­ § ¢¨á¨â.
+unit_u_recompile_source_found_alone=10029_U_¥p¥ª®¬¯¨«ïæ¨ï $1, ­ ©¤¥­ë ⮫쪮 ¨á室­ë¥ ä ©«ë
+% ਠ¨á¯®«ì§®¢ ­¨¨ ª«îç  \var{-vu} á®®¡é ¥â ¯à¨ç¨­ã ¯¥à¥ª®¬¯¨«ï樨 㪠§ ­­®£® ¬®¤ã«ï.
+unit_u_recompile_staticlib_is_older=10030_U_¥p¥ª®¬¯¨«ïæ¨ï ¬®¤y«ï, áâ â¨ç¥áª ï ¡¨¡«¨®â¥ª  áâ pè¥ ç¥¬ ppu-ä ©«
+% ਠ¨á¯®«ì§®¢ ­¨¨ ª«îç  \var{-vu} á®®¡é ¥â ® ⮬, çâ® áâ â¨ç¥áª ï ¡¨¡«¨®â¥ª  ¬®¤ã«ï
+% áâ àè¥, 祬 ppu-ä ©« ¬®¤ã«ï.
+unit_u_recompile_sharedlib_is_older=10031_U_¥p¥ª®¬¯¨«ïæ¨ï ¬®¤y«ï, à §¤¥«ï¥¬ ï ¡¨¡«¨®â¥ª  áâ pè¥ ç¥¬ ppu-ä ©«
+% ਠ¨á¯®«ì§®¢ ­¨¨ ª«îç  \var{-vu} á®®¡é ¥â ® ⮬, çâ® à §¤¥«ï¥¬ ï ¡¨¡«¨®â¥ª  ¬®¤ã«ï
+% áâ àè¥, 祬 ppu-ä ©« ¬®¤ã«ï.
+unit_u_recompile_obj_and_asm_older=10032_U_¥p¥ª®¬¯¨«ïæ¨ï ¬®¤y«ï, .as ¨ .obj ä ©«ë áâ pè¥ ç¥¬ ppu-ä ©«
+% ਠ¨á¯®«ì§®¢ ­¨¨ ª«îç  \var{-vu} á®®¡é ¥â ® ⮬, çâ®  áᥬ¡«¥à­ë© ¨«¨ ®¡ê¥ªâ­ë© ä ©« ¬®¤ã«ï
+% áâ àè¥, 祬 ppu-ä ©« ¬®¤ã«ï.
+unit_u_recompile_obj_older_than_asm=10033_U_¥p¥ª®¬¯¨«ïæ¨ï ¬®¤y«ï, .obj ä ©« áâ pè¥ ç¥¬ .as ä ©«
+% ਠ¨á¯®«ì§®¢ ­¨¨ ª«îç  \var{-vu} á®®¡é ¥â ® ⮬, çâ® ®¡ê¥ªâ­ë© ä ©« ¬®¤ã«ï
+% áâ àè¥, 祬 ¥£®  áᥬ¡«¥à­ë© ä ©«.
+unit_u_parsing_interface=10034_U_€­ «¨§ ¨­â¥pä¥©á  $1
+% ਠ¨á¯®«ì§®¢ ­¨¨ ª«îç  \var{-vu} á®®¡é ¥â ® ­ ç «¥  ­ «¨§ 
+% ¨­â¥à䥩᭮© ç á⨠¬®¤ã«ï.
+unit_u_parsing_implementation=10035_U_€­ «¨§ p¥ «¨§ æ¨¨ $1
+% ਠ¨á¯®«ì§®¢ ­¨¨ ª«îç  \var{-vu} á®®¡é ¥â ® ­ ç «¥  ­ «¨§ 
+% ॠ«¨§ æ¨®­­®© ç á⨠¬®¤ã«ï.
+unit_u_second_load_unit=10036_U_®¢â®à­ ï § £py§ª  ¬®¤y«ï $1
+% ਠ¨á¯®«ì§®¢ ­¨¨ ª«îç  \var{-vu} á®®¡é ¥â ® ­ ç «¥ ¯®¢â®à­®© ª®¬¯¨«ï樨
+% ¬®¤ã«ç. â® ¬®¦¥â ¯à®¨á室¨âì ¯à¨ ­ «¨ç¨¨ ¢§ ¨¬®§ ¢¨á¨¬ëå ¬®¤ã«¥©.
+unit_u_check_time=10037_U_஢¥àª  PPU ä ©«  $1 ¢p¥¬ï $2
+% ਠ¨á¯®«ì§®¢ ­¨¨ ª«îç  \var{-vu} ¯®ª §¢ ¥â ¨¬ï ¨ ¤ âã/¢à¥¬ï ä ©« ,
+% ®â ª®â®à®£® § ¢¨á¨â ४®¬¯¨«ïæ¨ï.
+### The following two error msgs is currently disabled.
+#unit_h_cond_not_set_in_last_compile=10038_H_“á«®¢­®¥ ¢ëp ¦¥­¨¥ $1 ­¥ ¡ë«® yáâ ­®¢«¥­® ¯p¨ ¯®á«¥¤­¥© ª®¬¯¨«ï樨 $2
+#% when recompilation of an unit is required the compiler will check that
+#% the same conditionals are set for the recompiliation. The compiler has
+#% found a conditional that currently is defined, but was not used the last
+#% time the unit was compiled.
+#unit_h_cond_set_in_last_compile=10039_H_“á«®¢­®¥ ¢ëp ¦¥­¨¥ $1 ¡ë«® yáâ ­®¢«¥­® ¯p¨ ¯®á«¥¤­¥© ª®¬¯¨«ï樨 $2
+#% when recompilation of an unit is required the compiler will check that
+#% the same conditionals are set for the recompiliation. The compiler has
+#% found a conditional that was used the last time the unit was compiled, but
+#% the conditional is currently not defined.
+unit_w_cant_compile_unit_with_changed_incfile=10040_W_ ©¤¥­ë ¨§¬¥­¥­­ë¥ ¢ª«îç ¥¬ë¥ ä ©«ë, ­® ª®¬¯¨«ïæ¨ï $1 ­¥¢®§¬®¦­ 
+% Ž¡­ à㦥­® ¨§¬¥­¥­¨¥ ¢ª«îç ¥¬ëå ä ©«®¢ ¬®¤ã«ï, ­® ­¥ª®â®àë¥ ¨á室­ë¥ ä ©«ë
+% ­¥ ­ ©¤¥­ë, ¯®í⮬ã ४®¬¯¨«ïæ¨ï ­¥¢®§¬®¦­ .
+unit_u_source_modified=10041_U_” ©« $1 ­®¢¥¥, 祬 $2
+%  ©¤¥­ ¨§¬¥­¥­­ë© ¨á室­ë© ä ©« ¬®¤ã«ï.
+unit_u_ppu_invalid_fpumode=10042_U_®¯ë⪠ ¨á¯®«ì§®¢ ­¨ï ¬®¤ã«ï, ᪮¬¯¨«¨à®¢ ­­®£® á ¤à㣨¬ ०¨¬®¬ ᮯà®æ¥áá®à 
+% ®¯ë⪠ ¨á¯®«ì§®¢ ­¨ï ¬®¤ã«¥©, ª®â®àë¥ ¡ë«¨ ᪮¬¯¨«¨à®¢ ­ë á ®â«¨ç î騬áï ०¨¬®¬
+% ä®à¬ â  ¯« ¢ î饩 § ¯ï⮩. ‚ᥠ¬®¤ã«¨ ¤®«¦­ë ¡ëâì ᪮¬¯¨«¨à®¢ ­ë «¨¡® á ¢ª«î祭­®©
+% í¬ã«ï樥© ᮯà®æ¥áá®à , «¨¡® á ®âª«î祭­®©, ­® ­¥ ¢¯¥à¥¬¥èªã.
+unit_u_loading_interface_units=10043_U_‡ £à㧪  ¬®¤ã«¥© ¨§ ¨­â¥à䥩᭮© ç á⨠$1
+% ਠ¨á¯®«ì§®¢ ­¨¨ ª«îç  \var{-vu} á®®¡é ¥â ® ­ ç «¥ § £à㧪¨ ¬®¤ã«¥©,
+% ¨á¯®«ì§ã¥¬ëå ¢ ¨­â¥à䥩᭮© ç á⨠㪠§ ­­®£® ¬®¤ã«ï.
+unit_u_loading_implementation_units=10044_U_‡ £à㧪  ¬®¤ã«¥© ¨§ ॠ«¨§ æ¨®­­®© ç á⨠$1
+% ਠ¨á¯®«ì§®¢ ­¨¨ ª«îç  \var{-vu} á®®¡é ¥â ® ­ ç «¥ § £à㧪¨ ¬®¤ã«¥©,
+% ¨á¯®«ì§ã¥¬ëå ¢ ॠ«¨§ æ¨®­­®© ç á⨠㪠§ ­­®£® ¬®¤ã«ï.
+unit_u_interface_crc_changed=10045_U_“ ¬®¤ã«ï $1 ¨§¬¥­¨« áì ª®­â஫쭠ï á㬬  ¨­â¥à䥩á 
+% ਠ¨á¯®«ì§®¢ ­¨¨ ª«îç  \var{-vu} á®®¡é ¥â ® ⮬, çâ® ª®­â஫쭠ï á㬬 ,
+% ¢ëç¨á«¥­­ ï ¤«ï ¨­â¥à䥩᭮© ç á⨠¬®¤ã«ï, ¨§¬¥­¨« áì ¯®á«¥ à §¡®à  ¥£® ॠ«¨§ æ¨®­­®©
+% ç áâ¨.
+unit_u_implementation_crc_changed=10046_U_“ ¬®¤ã«ï $1 ¨§¬¥­¨« áì ª®­â஫쭠ï á㬬  ॠ«¨§ æ¨¨
+% ਠ¨á¯®«ì§®¢ ­¨¨ ª«îç  \var{-vu} á®®¡é ¥â, çâ® ª®­â஫쭠ï á㬬  ¬®¤ã«ï
+% ¨§¬¥­¨« áì ¯®á«¥ à §¡®à  ¥£® ॠ«¨§ æ¨®­­®© ç áâ¨.
+unit_u_finished_compiling=10047_U_‡ ¢¥à襭  ª®¬¯¨«ïæ¨ï ¬®¤ã«ï $1
+% ਠ¨á¯®«ì§®¢ ­¨¨ ª«îç  \var{-vu} á®®¡é ¥â ® § ¢¥à襭¨ ª®¬¯¨«ï樨 ¬®¤ã«ï.
+unit_u_add_depend_to=10048_U_„®¡ ¢«¥­  § ¢¨á¨¬®áâì $1 ®â $2
+% ਠ¨á¯®«ì§®¢ ­¨¨ ª«îç  \var{-vu} á®®¡é ¥â ® ⮬, çâ® ¡ë«  ¤®¡ ¢«¥­ 
+% § ¢¨á¨¬®áâì ¬¥¦¤ã ¤¢ã¬ï ¬®¤ã«ï¬¨.
+unit_u_no_reload_is_caller=10049_U_¥§ ¯¥à¥§ £à㧪¨, íâ® ¨­¨æ¨ â®à: $1
+% ਠ¨á¯®«ì§®¢ ­¨¨ ª«îç  \var{-vu} ¯à¥¤ã¯à¥¦¤ ¥â ® ⮬, çâ®
+% ¬®¤ã«ì ­¥ ¡ã¤¥â ¯¥à¥§ £à㦥­, ¯®â®¬ã çâ® ®­ á ¬ ï¥âáï ¨­¨æ¨ â®à®¬ ᢮¥©
+% ¯¥à¥§ £à㧪¨.
+unit_u_no_reload_in_second_compile=10050_U_¥§ ¯¥à¥§ £à㧪¨, 㦥 ¯®¢â®à­ ï ª®¬¯¨«ïæ¨ï: $1
+% ਠ¨á¯®«ì§®¢ ­¨¨ ª«îç  \var{-vu} ¯à¥¤ã¯à¥¦¤ ¥â, çâ® ¬®¤ã«ì
+% ­¥ ¡ã¤¥â ¯¥à¥§ £à㦥­, â.ª. ®­ 㦥 ¡ë« ¯¥à¥§ £à㦥­ ¨ ª®¬¯¨«¨àã¥âáï ¢® ¢â®à®© à §.
+unit_u_flag_for_reload=10051_U_®¬¥ç¥­® ¤«ï ¯¥à¥§ £à㧪¨: $1
+% ਠ¨á¯®«ì§®¢ ­¨¨ ª«îç  \var{-vu} á®®¡é ¥â ® ⮬, çâ® ¬®¤ã«ì ¡ã¤¥â ¯¥à¥§ £à㦥­.
+unit_u_forced_reload=10052_U_‚ë­ã¦¤¥­­ ï ¯¥à¥§ £à㧪 
+% ਠ¨á¯®«ì§®¢ ­¨¨ ª«îç  \var{-vu} á®®¡é ¥â ® ⮬, çâ® ¬®¤ã«ì ¯à¨è«®áì ¯¥à¥§ £à㧨âì.
+unit_u_previous_state=10053_U_०­¨© áâ âãá $1: $2
+% ਠ¨á¯®«ì§®¢ ­¨¨ ª«îç  \var{-vu} ¯®ª §ë¢ ¥â ¯à¥¤ë¤ã騩 áâ âãá ¬®¤ã«ï.
+unit_u_second_compile_unit=10054_U_$1 㦥 ª®¬¯¨«¨àã¥âáï, ¯¥à¥å®¤ ª ¯®¢â®à­®© ª®¬¯¨«ï樨
+% ਠ¨á¯®«ì§®¢ ­¨¨ ª«îç  \var{-vu} ¯à¥¤ã¯à¥¦¤ ¥â ® ­ ç «¥ ¯¥à¥ª®¬¯¨«ï樨 ¬®¤ã«ï
+% ¢® ¢â®à®© à §. â® ¬®¦¥â ¯à®¨á室¨âì á® ¢§ ¨¬®§ ¢¨á¨¬ë¬¨ ¬®¤ã«ï¬¨.
+unit_u_loading_unit=10055_U_‡ £à㧪  ¬®¤ã«ï $1
+% ਠ¨á¯®«ì§®¢ ­¨¨ ª«îç  \var{-vu} á®®¡é ¥â ® ­ ç «¥ § £à㧪¨ ¬®¤ã«ï.
+unit_u_finished_loading_unit=10056_U_‡ £à㧪  ¬®¤ã«ï $1 § ¢¥à襭 
+% ਠ¨á¯®«ì§®¢ ­¨¨ ª«îç  \var{-vu} á®®¡é ¥â ® § ¢¥à襭¨¨ § £à㧪¨ ¬®¤ã«ï.
+unit_u_registering_new_unit=10057_U_¥£¨áâà æ¨ï ­®¢®£® ¬®¤ã«ï $1
+% ਠ¨á¯®«ì§®¢ ­¨¨ ª«îç  \var{-vu} á®®¡é ¥â ® ⮬, çâ® ª®¬¯¨«ïâ®à ¢áâà¥â¨« ­®¢ë© ¬®¤ã«ì
+% ¨ § à¥£¨áâà¨à®¢ « ¥£® ¢® ¢­ãâ७­¨å ᯨ᪠å.
+unit_u_reresolving_unit=10058_U_®¢â®à­®¥ à §à¥è¥­¨¥ § ¢¨á¨¬®á⥩ ¬®¤ã«ï $1
+% ਠ¨á¯®«ì§®¢ ­¨¨ ª«îç  \var{-vu} ¯à¥¤ã¯à¥¦¤ ¥â ® ⮬, çâ® ª®¬¯¨«ïâ®àã ¯à¨è«®áì
+% ¯®¢â®à­® ¢ëç¨á«¨âì ¢­ãâ७­¨¥ ¤ ­­ë¥ 㪠§ ­­®£® ¬®¤ã«ï.
+unit_u_skipping_reresolving_unit=10059_U_யã᪠¯®¢â®à­®£® à §à¥è¥­¨ï ¬®¤ã«ï $1, § £à㧪  ¨á¯®«ì§ã¥¬ëå ¬®¤ã«¥© ¯à®¤®«¦ ¥âáï
+% ਠ¨á¯®«ì§®¢ ­¨¨ ª«îç  \var{-vu} á®®¡é ¥â ® ⮬, çâ® ¯®¢â®à­®¥ ¢ëç¨á«¥­¨¥ ¤ ­­ëå
+% ¬®¤ã«ï ¯à®¯ã饭®, ¯®â®¬ã çâ® ¢ëç¨á«ïâì ¯®ª  ­¥ç¥£®.
+unit_u_unload_resunit=10060_U_‚ë£à㧪  ¬®¤ã«ï ®¡à ¡®âª¨ à¥áãàᮢ $1 (­¥ ­ã¦¥­)
+% ਠ¨á¯®«ì§®¢ ­¨¨ ª«îç  \var{-vu} á®®¡é ¥â ® ⮬, çâ® ¬®¤ã«ì ®¡à ¡®âª¨ à¥áãàᮢ
+% ¢ë£à㦠¥âáï, â.ª. à¥áãàáë ­¥ ¨á¯®«ì§ãîâáï ¯à®£à ¬¬®©.
+unit_e_different_wpo_file=10061_E_Œ®¤ã«ì $1 ᪮¬¯¨«¨à®¢ ­ á ¨á¯®«ì§®¢ ­¨¥¬ ®â«¨ç îé¨åáï ­ áâ஥ª ®¯â¨¬¨§ æ¨¨ ¢á¥© ¯à®£à ¬¬ë (wpo) ($2, $3); ¯¥à¥ª®¬¯¨«¨àã©â¥ ¥£® ¡¥§ wpo ¨«¨ á ⥬ ¦¥ ä ©«®¬ ®¡à â­®© á¢ï§¨
+% Š®£¤  ¬®¤ã«ì ¡ë« ᪮¬¯¨«¨à®¢ ­ á ®¯à¥¤¥«¥­­ë¬ ä ©«®¬ ®¡à â­®© á¢ï§¨ ®¯â¨¬¨§ æ¨¨ ¢á¥© ¯à®£à ¬¬ë (wpo) (\var{-FW<x>} \var{-OW<x>}),
+% ¥£® ᪮¬¯¨«¨à®¢ ­­ ï ¢¥àá¨ï ᯥ樠«¨§¨à®¢ ­  ¯®¤ ¤ ­­ë© á業 à¨© ª®¬¯¨«ï樨 ¨ ­¥ ¬®¦¥â ¡ëâì ¨á¯®«ì§®¢ ­ 
+% ¯® ¤à㣮¬ã ­ §­ ç¥­¨î. „«ï ¨á¯®«ì§®¢ ­¨ï ¬®¤ã«ï ¢ ¤à㣮© ¯à®£à ¬¬¥ ¨«¨ á ¤à㣨¬¨ ­ áâனª ¬¨ wpo
+% ¥£® ­¥®¡å®¤¨¬® ¯¥à¥ª®¬¯¨«¨à®¢ âì.
+% \end{description}
+# EndOfTeX
+
+#
+# Options
+#
+# 11047 is the last used one
+#
+option_usage=11000_O_$1 [®¯æ¨¨] <ä ©«> [®¯æ¨¨]
+# BeginOfTeX
+%
+% \section{Žè¨¡ª¨ ®¡à ¡®âª¨ ª®¬ ­¤­®© áâப¨}
+% Žè¨¡ª¨, ª®â®àë¥ ¬®£ãâ ¢®§­¨ª âì ¢® ¢à¥¬ï ®¡à ¡®âª¨ ª®¬ ­¤­®© áâப¨
+% ¨«¨ ä ©«®¢ ª®­ä¨£ãà æ¨¨.
+% \begin{description}
+option_only_one_source_support=11001_W_®¤¤¥p¦¨¢ ¥âáï ⮫쪮 ®¤¨­ ¨á室­ë© ä ©«, ¢¬¥áâ® $1 ¡ã¤¥â ᪮¬¯¨«¨à®¢ ­ $2
+% ‚ ª®¬ ­¤­®© áâப¥ ¬®¦­® 㪠§ë¢ âì ⮫쪮 ®¤¨­ ä ©«. ¥à¢ë© ®¡­ à㦥­­ë© ä ©« ¡ã¤¥â
+% ᪮¬¯¨«¨à®¢ ­, ®áâ «ì­ë¥ ¨£­®à¨àãîâáï. Œ®¦¥â ¡ëâì ¯à¨§­ ª®¬ ⮣®, çâ®
+% ¯¥à¥¤ ®¯æ¨¥© § ¡ëâ §­ ª \var{'-'}.
+option_def_only_for_os2=11002_W_DEF ä ©« ¬®¦­® ᮧ¤ ¢ âì ⮫쪮 ¤«ï OS/2
+% This option can only be specified when you're compiling for OS/2
+option_no_nested_response_file=11003_E_‚«®¦¥­­ë¥ ä ©«ë ®â¢¥â  ­¥ ¯®¤¤¥p¦¨¢ îâáï
+% Ž¯æ¨ï ª®¬ ­¤­®© áâப¨ \var{@file} ­¥ ¯®§¢®«ï¥â ¨á¯®«ì§®¢ âì ¢«®¦¥­­ë¥ ä ©«ë ®â¢¥â .
+option_no_source_found=11004_F_‚ ª®¬ ­¤­®© áâப¥ ®âáãâáâ¢ã¥â ¨¬ï ¨á室­®£® ä ©« 
+% ‚ ª®¬ ­¤­®© áâப¥ ¤®«¦­® ¯à¨áãâá⢮¢ âì ¨¬ï ¨á室­®£® ä ©« .
+option_no_option_found=11005_N_” ©« ª®­ä¨£ãà æ¨¨ $1 ­¥ ᮤ¥à¦¨â ®¯æ¨© ª®¬¯¨«ïâ®à 
+% ‚ 㪠§ ­­®¬ ä ©«¥ ª®­ä¨£ãà æ¨¨ ­¥ ®¡­ à㦥­® ­¨ ®¤­®© ®¯æ¨¨.
+option_illegal_para=11006_E_H¥¢¥p­ë© ¯ p ¬¥âp: $1
+% “ª § ­  ­¥¨§¢¥áâ­ ï ®¯æ¨ï.
+option_help_pages_para=11007_H_-? ¢ë¢®¤¨â áâp ­¨æë á¯à ¢ª¨
+% â® á®®¡é¥­¨¥ ¢ë¢®¤¨âáï, ¥á«¨ 㪠§ ­  ­¥¨§¢¥áâ­ ï ®¯æ¨ï.
+option_too_many_cfg_files=11008_F_‘«¨èª®¬ ¬­®£® ¢«®¦¥­­ëå ä ©«®¢ ª®­ä¨£ãà æ¨¨
+% “஢¥­ì ¢«®¦¥­¨ï ä ©«®¢ ª®­ä¨£ãà æ¨¨ ®£à ­¨ç¥­ ç¨á«®¬ 16.
+option_unable_open_file=11009_F_H¥¢®§¬®¦­® ®âªpëâì $1
+% Žè¨¡ª  ¯à¨ ®âªàë⨨ ä ©«  ª®­ä¨£ãà æ¨¨.
+option_reading_further_from=11010_D_த®«¦ ¥âáï ç⥭¨¥ ¯ p ¬¥âp®¢ ¨§ $1
+% ‚뤠¥âáï, ¥á«¨ ¢ª«î祭 ¢ë¢®¤ § ¬¥â®ª, ¨ ª®¬¯¨«ïâ®à ¯¥à¥ª«îç ¥âáï ­ 
+% ¤à㣮© ä ©« ª®­ä¨£ãà æ¨¨.
+option_target_is_already_set=11011_W_–¥«¥¢ ï ¯« âä®à¬  㦥 yáâ ­®¢«¥­  ¢: $1
+% “ª § ­® ¡®«¥¥ ®¤­®© ®¯æ¨¨ \var{-T}, ®¯à¥¤¥«ïî饩 楫¥¢ãî ¯« âä®à¬ã.
+option_no_shared_lib_under_dos=11012_W_ §¤¥«ï¥¬ë¥ ¡¨¡«¨®â¥ª¨ ­¥ ¯®¤¤¥p¦¨¢ îâáï ¤«ï DOS, ¡ã¤ãâ áâ â¨ç¥áª¨¬¨
+% If you specify \var{-CD} for the \dos platform, this message is displayed.
+% The compiler supports only static libraries under \dos
+option_too_many_ifdef=11013_F_‘«¨èª®¬ ¬­®£® $IFDEF ¨«¨ $IFNDEF ¢ ä ©«¥ ®¯æ¨© $1 áâப  $2
+% Š®«¨ç¥á⢮ ¤¨à¥ªâ¨¢ \var{\#IF(N)DEF} ¢ ä ©«¥ ª®­ä¨£ãà æ¨¨ ­¥ ᮢ¯ ¤ ¥â á ª®«¨ç¥á⢮¬
+% ¤¨à¥ªâ¨¢ \var{\#ENDIF}.
+option_too_many_endif=11014_F_¥®¦¨¤ ­­ë© $ENDIF ¢ ä ©«¥ ®¯æ¨© $1 áâப  $2
+% Š®«¨ç¥á⢮ ¤¨à¥ªâ¨¢ \var{\#IF(N)DEF} ¢ ä ©«¥ ª®­ä¨£ãà æ¨¨ ­¥ ᮢ¯ ¤ ¥â á ª®«¨ç¥á⢮¬
+% ¤¨à¥ªâ¨¢ \var{\#ENDIF}.
+option_too_less_endif=11015_F_¥§ ªàë⮥ yá«®¢­®¥ ¢ëp ¦¥­¨¥ ¢ ª®­æ¥ ä ©«  ®¯æ¨©
+% Š®«¨ç¥á⢮ ¤¨à¥ªâ¨¢ \var{\#IF(N)DEF} ¢ ä ©«¥ ª®­ä¨£ãà æ¨¨ ­¥ ᮢ¯ ¤ ¥â á ª®«¨ç¥á⢮¬
+% ¤¨à¥ªâ¨¢ \var{\#ENDIF}.
+option_no_debug_support=11016_W_â®â íª§¥¬¯«ïà ª®¬¯¨«ïâ®à  ­¥ ¯®¤¤¥à¦¨¢ ¥â £¥­¥p æ¨î ®â« ¤®ç­®© ¨­ä®p¬ æ¨¨
+% It is possible to have a compiler executable that doesn't support
+% the generation of debugging info. If you use such an executable with the
+% \var{-g} switch, this warning will be displayed.
+option_no_debug_support_recompile_fpc=11017_H_®¯p®¡y©â¥ ᮡà âì á ®¯æ¨¥© -dGDB
+% It is possible to have a compiler executable that doesn't support
+% the generation of debugging info. If you use such an executable with the
+% \var{-g} switch, this warning will be displayed.
+option_obsolete_switch=11018_W_ˆá¯®«ì§y¥âáï yáâ p¥¢è¨© ª«îç $1
+% ।ã¯à¥¦¤ ¥â, ç⮠㪠§ ­­ ï ®¯æ¨ï ¡®«ìè¥ ­¥ ­ã¦­ /­¥ ¯®¤¤¥à¦¨¢ ¥âáï.
+% …¥ ४®¬¥­¤ã¥âáï 㤠«¨âì, çâ®¡ë ¨§¡¥¦ âì ¯à®¡«¥¬ ¢ á«ãç ¥, ¥á«¨
+% ¢ ¡ã¤ã饬 §­ ç¥­¨¥ ®¯æ¨¨ ¨§¬¥­¨âáï.
+option_obsolete_switch_use_new=11019_W_ˆá¯®«ì§y¥âáï yáâ p¥¢è¨© ª«îç $1, ¨á¯®«ì§y©â¥ ¢¬¥áâ® ­¥£® ª«îç $2
+% ।ã¯à¥¦¤ ¥â, ç⮠㪠§ ­­ ï ®¯æ¨ï ¡®«ìè¥ ­¥ ¯®¤¤¥à¦¨¢ ¥âáï ¨ ¢¬¥áâ® ­¥¥ á«¥¤ã¥â ¨á¯®«ì§®¢ âì ¤àã£ãî.
+% ¥ª®¬¥­¤ã¥âáï § ¬¥­¨âì ª«îç, çâ®¡ë ¨§¡¥¦ âì ¯à®¡«¥¬ ¢ á«ãç ¥, ¥á«¨
+% ¢ ¡ã¤ã饬 ¥£® §­ ç¥­¨¥ ¨§¬¥­¨âáï.
+option_switch_bin_to_src_assembler=11020_N_¥p¥ª«î祭¨¥ ­   áᥬ¡«¥p, £¥­¥à¨àãî騩 ⥪áâ
+% €áᥬ¡«¥à (á ¤¢®¨ç­ë¬ ä®à¬ â®¬ ¢ë室­ëå ä ©«®¢) ¡ë« ¨§¬¥­¥­, ¯®â®¬ã çâ® ¡ë« ¨á¯®«ì§®¢ ­ ª«îç -a,
+% ª®â®àë© ®§­ ç ¥â ᮧ¤ ­¨¥  áᥬ¡«¥à­ëå ä ©«®¢ ¢ ⥪á⮢®¬ ä®à¬ â¥.
+option_incompatible_asm=11021_W_‚ë¡à ­­ë©  áᥬ¡«¥à "$1" ­¥ ᮢ¬¥á⨬ á "$2"
+option_asm_forced=11022_W_‚ë­ã¦¤¥­­® ¨á¯®«ì§¥âáï  áᥬ¡«¥à "$1"
+% ‡ ¤ ­­ë© ⨯  áᥬ¡«¥à  ­¥ ¯®§¢®«ï¥â ᮧ¤ ¢ âì ®¡ê¥ªâ­ë¥ ä ©«ë
+% ¢ ¯à ¢¨«ì­®¬ ä®à¬ â¥. ‚¬¥áâ® ­¥£® ¡ã¤¥â ¨á¯®«ì§®¢ ­  áᥬ¡«¥à ¯® 㬮«ç ­¨î
+% ¤«ï ¢ë¡à ­­®© ¯« âä®à¬ë.
+option_using_file=11026_T_—⥭¨¥ ®¯æ¨© ¨§ ä ©«  $1
+% Ž¯æ¨¨ ç¨â îâáï â ª¦¥ ¨§ 㪠§ ­­®£® ä ©« .
+option_using_env=11027_T_—⥭¨¥ ®¯æ¨© ¨§ ¯¥à¥¬¥­­®© ®ªà㦥­¨ï $1
+% Ž¯æ¨¨ ç¨â îâáï â ª¦¥ ¨§ 㪠§ ­­®© ¯¥à¥¬¥­­®© ®ªà㦥­¨ï.
+option_handling_option=11028_D_Ž¡à ¡®âª  ®¯æ¨¨ "$1"
+% Žâ« ¤®ç­®¥ á®®¡é¥­¨¥ ® ⮬, çâ® ®¯æ¨ï ­ ©¤¥­  ¨ ¡ã¤¥â ®¡à ¡®â ­ .
+option_help_press_enter=11029_O_*** ­ ¦¬¨â¥ enter ***
+% ‘®®¡é¥­¨ ¢ë¤ ¥âáï ¯à¨ ¯®áâà ­¨ç­®¬ ¢ë¢®¤¥ á¯à ¢ª¨.  ¦ â¨¥ ª« ¢¨è¨ ENTER
+% ¢ë§ë¢ ¥â ¯®ª § á«¥¤ãî饩 áâà ­¨æë. …᫨ ­ ¦ âì q ¨ § â¥¬ ENTER, ª®¬¯¨«ïâ®à
+% § ¢¥àè ¥â à ¡®âã.
+option_start_reading_configfile=11030_H_ ç «® ç⥭¨ï ä ©«  ª®­ä¨£ãà æ¨¨ $1
+%  ç «® ç⥭¨ï ä ©«  ª®­ä¨£ãà æ¨¨.
+option_end_reading_configfile=11031_H_Š®­¥æ ç⥭¨ï ä ©«  ª®­ä¨£ãà æ¨¨ $1
+% Žª®­ç ­¨¥ ç⥭¨ï ä ©«  ª®­ä¨£ãà æ¨¨.
+option_interpreting_option=11032_D_¨­â¥à¯à¥â æ¨ï ®¯æ¨¨ "$1"
+% Š®¬¯¨«ïâ®à ¨­â¥à¯à¥â¨àã¥â ®¯æ¨î.
+option_interpreting_firstpass_option=11036_D_¨­â¥à¯à¥â æ¨ï ®¯æ¨¨ ¯¥à¢®£® ¯à®å®¤  "$1"
+% Š®¬¯¨«ïâ®à ¨­â¥à¯à¥â¨àã¥â ®¯æ¨î ¢ ¯¥à¢ë© à §.
+option_interpreting_file_option=11033_D_¨­â¥à¯à¥â æ¨ï ®¯æ¨¨ ¨§ ä ©«  "$1"
+% Š®¬¯¨«ïâ®à ¨­â¥à¯à¥â¨àã¥â ®¯æ¨î, ¯à®ç¨â ­­ãî ¨§ ä ©«  ª®­ä¨£ãà æ¨¨.
+option_read_config_file=11034_D_—⥭¨¥ ä ©«  ª®­ä¨£ãà æ¨¨ "$1"
+%  ç «® ç⥭¨ï 㪠§ ­­®£® ä ©«  ª®­ä¨£ãà æ¨¨ (®â« ¤®ç­®¥ á®®¡é¥­¨¥).
+option_found_file=11035_D_­ ©¤¥­® ¨¬ï ¨á室­®£® ä ©«  "$1"
+% „®¯®«­¨â¥«ì­ ï ¨­ä®à¬ æ¨ï ®¡ ®¯æ¨ïå, ¢ë¢®¤¨âáï ¯à¨
+% ¢ª«î祭­ëå ®â« ¤®ç­ëå á®®¡é¥­¨ïå.
+option_code_page_not_available=11039_E_¥¨§¢¥áâ­ ï ª®¤®¢ ï áâà ­¨æ 
+% “ª § ­  ­¥¨§¢¥áâ­ ï ª®¤®¢ ï áâà ­¨æ  ¤«ï ¨á室­ëå ä ©«®¢.
+% Š®¬¯¨«ïâ®à ¨¬¥¥â ¢áâ஥­­ãî ¯®¤¤¥à¦ªã ­¥áª®«ìª¨å ª®¤®¢ëå áâà ­¨æ.
+% ‡ ¯à®è¥­­ ï ª®¤®¢ ï áâà ­¨æ  ¢ ¨å ç¨á«® ­¥ ¢å®¤¨â. „«ï ¤®¡ ¢«¥­¨ï
+% ¯®¤¤¥à¦ª¨ ¯®âॡã¥âáï ¯¥à¥á¡®àª  ª®¬¯¨«ïâ®à .
+option_config_is_dir=11040_F_” ©« ª®­ä¨£ãà æ¨¨ $1 - ¤¨à¥ªâ®à¨ï
+% „¨à¥ªâ®à¨¨ ­¥«ì§ï ¨á¯®«ì§®¢ âì ¢ ª ç¥á⢥ ä ©«®¢ ª®­ä¨£ãà æ¨¨.
+option_confict_asm_debug=11041_W_‚ë¡à ­­ë© ⨯  áᥬ¡«¥à  "$1" ­¥ ¯®¤¤¥à¦¨¢ ¥â ®â« ¤®ç­ãî ¨­ä®à¬ æ¨î, ®â« ¤ª  ®âª«î祭 
+% ‚ë¡à ­­ë©  áᥬ¡«¥à ­¥ ¯®¤¤¥à¦¨¢ ¥â £¥­¥à æ¨î ®â« ¤®ç­®© ¨­ä®à¬ æ¨¨,
+% ¯®í⮬㠢®§¬®¦­®áâì ®â« ¤ª¨ ®âª«î祭 .
+option_ppc386_deprecated=11042_W_ˆá¯®«ì§®¢ ­¨¥ ppc386.cfg ï¥âáï ãáâ à¥¢è¨¬, ¢¬¥áâ® ­¥£® á«¥¤ã¥â ¨á¯®«ì§®¢ âì fpc.cfg
+% Using ppc386.cfg is still supported for historical reasons, however, for a multiplatform
+% system the naming makes no sense anymore. Please continue to use fpc.cfg instead.
+option_else_without_if=11043_F_‚ ä ©«¥ ®¯æ¨© $1 áâப  $2 ®¡­ à㦥­  ¤¨à¥ªâ¨¢  \var{\#ELSE} ¡¥§ ¯à¥¤¢ à¨â¥«ì­®© \var{\#IF(N)DEF}
+% ‚ ä ©«¥ ª®­ä¨£ãà æ¨¨ ®¡­ à㦥­  ¤¨à¥ªâ¨¢  \var{\#ELSE} ¡¥§ ¯à¥¤¢ à¨â¥«ì­®© ¤¨à¥ªâ¨¢ë \var{\#IF(N)DEF}.
+option_unsupported_target=11044_F_Ž¯æ¨ï "$1" ­¥ ¯®¤¤¥à¦¨¢ ¥âáï (¨«¨ ¯®ª  ­¥ ¯®¤¤¥à¦¨¢ ¥âáï) ¤«ï 楫¥¢®© ¯« âä®à¬ë
+% ¥ ¢á¥ ®¯æ¨¨ ¯®¤¤¥à¦¨¢ îâáï ¨«¨ ॠ«¨§®¢ ­ë ¤«ï ¢á¥å ¯« âä®à¬. â® á®®¡é¥­¨¥ ® ⮬,
+% çâ® ¢ë¡à ­­ ï ®¯æ¨ï ­¥á®¢¬¥á⨬  á ⥪ã饩 ¯« âä®à¬®©.
+option_unsupported_target_for_feature=11045_F_Žá®¡¥­­®áâì "$1" ­¥ ¯®¤¤¥à¦¨¢ ¥âáï (¨«¨ ¯®ª  ­¥ ¯®¤¤¥à¦¨¢ ¥âáï) ¤«ï ¢ë¡à ­­®© 楫¥¢®© ¯« âä®à¬ë
+% ¥ ¢á¥ ®¯æ¨¨ ¯®¤¤¥à¦¨¢ îâáï ¨«¨ ॠ«¨§®¢ ­ë ¤«ï ¢á¥å ¯« âä®à¬. â® á®®¡é¥­¨¥ ® ⮬,
+% çâ® ¢ë¡à ­­ ï ®¯æ¨ï ­¥á®¢¬¥á⨬  á ⥪ã饩 ¯« âä®à¬®©.
+option_dwarf_smart_linking=11046_N_  ¢ë¡à ­­®© ¯« âä®à¬¥ ­¥«ì§ï ¨á¯®«ì§®¢ âì ®â« ¤®ç­ãî ¨­ä®à¬ æ¨î ⨯  DWARF ᮢ¬¥áâ­® á "㬭®©" ª®¬¯®­®¢ª®©, ¯¥à¥ª«î祭¨¥ ­  áâ â¨ç¥áªãî ª®¬¯®­®¢ªã
+% "“¬­ ï" ª®¬¯®­®¢ª  ¢ ­ áâ®ï饥 ¢à¥¬ï ­¥á®¢¬¥á⨬  á ®â« ¤®ç­®© ¨­ä®à¬ æ¨¥© ⨯  DWARF ­  ¡®«ì設á⢥
+% ¯« âä®à¬, ¯®í⮬㠯ਠ¢ë¡®à¥ ä®à¬ â  DWARF "㬭 ï" ª®¬¯®­®¢ª  ®âª«îç ¥âáï.
+option_ignored_target=11047_W_Ž¯æ¨ï "$1" ¨£­®à¨àã¥âáï ¤«ï ¢ë¡à ­­®© 楫¥¢®© ¯« âä®à¬ë.
+% ¥ ¢á¥ ®¯æ¨¨ ¯®¤¤¥à¦¨¢ îâáï ¨«¨ ॠ«¨§®¢ ­ë ¤«ï ¢á¥å ¯« âä®à¬. â® á®®¡é¥­¨¥ ® ⮬,
+% çâ® ¢ë¡à ­­ ï ®¯æ¨ï ¨£­®à¨àã¥âáï ¤«ï ⥪ã饩 ¯« âä®à¬ë.
+% \end{description}
+# EndOfTeX
+
+#
+# Whole program optimization
+#
+# 12019 is the last used one
+#
+# BeginOfTeX
+%
+% \section{‘®®¡é¥­¨ï ®¯â¨¬¨§ æ¨¨ ¢á¥© ¯à®£à ¬¬ë}
+%  §¤¥« ᮤ¥à¦¨â á®®¡é¥­¨ï ®¡ ®è¨¡ª å, ª®â®àë¥ ¬®£ãâ ¢®§­¨ª âì
+% ¢ ¯à®æ¥áᥠ®¯â¨¬¨§ æ¨¨ ¢á¥© ¯à®£à ¬¬ë (wpo).
+% \begin{description}
+wpo_cant_find_file=12000_F_¥¢®§¬®¦­® ®âªàëâì ä ©« ¤ ­­ëå WPO "$1"
+% Š®¬¯¨«ïâ®à ­¥ ¬®¦¥â ®âªàëâì 㪠§ ­­ë© ä ©« á ¤ ­­ë¬¨ ®¯â¨¬¨§ æ¨¨ ¢á¥© ¯à®£à ¬¬ë.
+wpo_begin_processing=12001_D_Ž¡à ¡®âª  ¨­ä®à¬ æ¨¨ WPO ¢ ä ©«¥ "$1"
+% Š®¬¯¨«ïâ®à ­ ç¨­ ¥â ®¡à ¡®âªã ¤ ­­ëå ¤«ï ®¯â¨¬¨§ æ¨¨ ¢á¥© ¯à®£à ¬¬ë ¢ 㪠§ ­­®¬ ä ©«¥.
+wpo_end_processing=12002_D_‡ ª®­ç¥­  ®¡à ¡®âª  ¨­ä®à¬ æ¨¨ WPO ¢ ä ©«¥ "$1"
+% Š®¬¯¨«ïâ®à § ª®­ç¨« ®¡à ¡®âªã ¤ ­­ëå ¤«ï ®¯â¨¬¨§ æ¨¨ ¢á¥© ¯à®£à ¬¬ë ¢ 㪠§ ­­®¬ ä ©«¥.
+wpo_expected_section=12003_E_Ž¦¨¤ «áï § £®«®¢®ª ᥪ樨, ­® ¯®«ã祭® "$2" ¢ áâப¥ $1 ä ©«  WPO-¨­ä®à¬ æ¨¨
+% ਠ®¡à ¡®âª¥ ä ©«  ®¯â¨¬¨§ æ¨¨ ¢á¥© ¯à®£à ¬¬ë ª®¬¯¨«ïâ®à ®¦¨¤ « § £®«®¢®ª ᥪ樨 (­ ç¨­ ¥âáï á \%),
+% ­® ­¥ ­ è¥« ¥£®.
+wpo_no_section_handler=12004_W_¥ § à¥£¨áâà¨à®¢ ­ ®¡à ¡®â稪 ¤«ï ᥪ樨 "$2" ¢ áâப¥ $1 ä ©«  WPO, ¨£­®à¨àã¥âáï
+% Š®¬¯¨«ïâ®à ­¥ ¨¬¥¥â ®¡à ¡®â稪  ¤«ï 㯮¬ï­ã⮩ ᥪ樨 ä ©«  WPO-¨­ä®à¬ æ¨¨,
+% ¯®í⮬㠮­ ¯à®¯ã᪠¥â íâã ᥪæ¨î ¨ ¯¥à¥å®¤¨â ª á«¥¤ãî饩.
+wpo_found_section=12005_D_ ©¤¥­  ᥪæ¨ï "$1" á ¨­ä®à¬ æ¨¥© ® "$2"
+% Š®¬¯¨«ïâ®à ®¡­ à㦨« ¢ ä ©«¥ WPO ᥪæ¨î á ¨­ä®à¬ æ¨¥©, ª®â®àãî ®­ ¬®¦¥â ®¡à ¡®â âì.
+wpo_no_input_specified=12006_F_‚ë¡à ­­ë¥ ०¨¬ë ®¯â¨¬¨§ æ¨¨ ¢á¥© ¯à®£à ¬¬ë âॡãî⠯।¢ à¨â¥«ì­® ᮧ¤ ­­®£® ä ©«  ®¡à â­®© á¢ï§¨ (㪠¦¨â¥ á ¯®¬®éìî -Fw)
+% —â®¡ë ¢ë¯®«­¨âì ¢ë¡à ­­ãî ®¯â¨¬¨§ æ¨î ¢á¥© ¯à®£à ¬¬ë, ª®¬¯¨«ïâ®àã âॡã¥âáï ¨­ä®à¬ æ¨ï,
+% ᮡ࠭­ ï ¢ ¯à®æ¥áᥠ¯à¥¤ë¤ã饩 ª®¬¯¨«ï樨. ” ©«, ᮤ¥à¦ é¨© íâã ¨­ä®à¬ æ¨î, ¤®«¦¥­ ¡ëâì 㪠§ ­
+% á ¯®¬®éìî ª«îç  -Fw.
+wpo_not_enough_info=12007_E_” ©« ®¡à â­®© á¢ï§¨ ­¥ ᮤ¥à¦¨â ¨­ä®à¬ æ¨¨, ­¥®¡å®¤¨¬®© ¤«ï ¯à®¢¥¤¥­¨ï ®¯â¨¬¨§ æ¨¨ "$1"
+% “ª § ­­ë© ä ©« ®¡à â­®© á¢ï§¨ ­¥ ᮤ¥à¦¨â ¨­ä®à¬ æ¨î, ª®â®à® ï ­ã¦­  ¤«ï ¯à®¢¥¤¥­¨ï âॡ㥬®£® ¢¨¤ 
+% ®¯â¨¬¨§ æ¨¨. ‘ª®à¥¥ ¢á¥£®, ­ã¦­® ¯¥à¥ª®¬¯¨«¨à®¢ âì ¯à®£à ¬¬ã, 㪠§ ¢ ¯®¤å®¤ï騩 ª«îç -OWxxx.
+wpo_no_output_specified=12008_F_“ª ¦¨â¥ ä ©« ®¡à â­®© á¢ï§¨ ¤«ï § ¯¨á¨ ᮡ࠭­®© ¨­ä®à¬ æ¨¨ (á ¯®¬®éìî -FW)
+% ¥®¡å®¤¨¬® 㪠§ âì ä ©«, ¢ ª®â®àë© ª®¬¯¨«ïâ®à § ¯¨è¥â ᮡ࠭­ë¥ ¢® ¢à¥¬ï ª®¬¯¨«ï樨
+% ¤ ­­ë¥ ¤«ï ®¯â¨¬¨§ æ¨¨ ¢á¥© ¯à®£à ¬¬ë. â® ¤¥« ¥âáï á ¯®¬®éìî ª«îç  -FW.
+wpo_output_without_info_gen=12009_E_” ©« ®¡à â­®© á¢ï§¨ 㪠§ ­ (á ¯®¬®éìî -FW), ­® ­¥ 㪠§ ­ âà¥¡ã¥¬ë© â¨¯ ᮡ¨à ¥¬®© ¨­ä®à¬ æ¨¨
+% ®¬¨¬® 㪠§ ­¨ï ¨¬¥­¨ ä ©«  ®¡à â­®© á¢ï§¨ wpo á ¯®¬®éìî -FW, á«¥¤ã¥â 㪠§ë¢ âì
+% âà¥¡ã¥¬ë¥ ¢¨¤ë ®¯â¨¬¨§ æ¨¨ á ¯®¬®éìî -OWxxx, ¨­ ç¥ ¯®«¥§­ ï ¨­ä®à¬ æ¨ï ¢ ä ©« § ¯¨á ­ 
+% ­¥ ¡ã¤¥â.
+wpo_input_without_info_use=12010_E_” ©« ®¡à â­®© á¢ï§¨ 㪠§ ­ (á ¯®¬®éìî -Fw), ­® ­¥ 㪠§ ­ ⨯ ®¯â¨¬¨§ æ¨¨, ª®â®àë© á«¥¤ã¥â ¢ë¯®«­¨âì
+% …᫨ 㪠§ ­ ä ©« ®¡à â­®© á¢ï§¨ wpo á ¯®¬®éìî -Fw, ­® ­¥ § ¤ ­ë ¢¨¤ë ®¯â¨¬¨§ æ¨¨ á ¯®¬®éìî -Owxxx,
+% ¡ã¤¥â ¢ë¤ ­  ¤ ­­ ï ®è¨¡ª . “ª § ­­ë¥ ª«îç¨ á«¥¤ã¥â ¨á¯®«ì§®¢ âì ᮢ¬¥áâ­®.
+wpo_skipping_unnecessary_section=12011_D_‘¥ªæ¨ï wpo ¯à®¯ã饭  "$1", ¯®áª®«ìªã ­¥ âॡã¥âáï ¤«ï § ¯à®è¥­­ëå ®¯â¨¬¨§ æ¨©
+% ” ©« ®¡à â­®© á¢ï§¨ wpo ᮤ¥à¦¨â ᥪæ¨î á ¨­ä®à¬ æ¨¥©, ª®â®à ï ­¥ âॡã¥âáï
+% ¤«ï ¯à®¢¥¤¥­¨ï ¢ë¡à ­­ëå ⨯®¢ ®¯â¨¬¨§ æ¨¨.
+wpo_duplicate_wpotype=12012_W_ˆ­ä®à¬ æ¨ï, à ­¥¥ ¯à®ç¨â ­­ ï ¨§ ä ©«  ®¡à â­®© á¢ï§¨ ¤«ï "$1", ¯¥à¥ªà뢠¥âáï ¨­ä®à¬ æ¨¥© ¨§ ᥪ樨 "$2"
+% ” ©« ®¡à â­®© á¢ï§¨ wpo ᮤ¥à¦¨â ­¥áª®«ìª® ᥪ権 á ®¤­®â¨¯­®© ¨­ä®à¬ æ¨¥© (­ ¯à¨¬¥à,
+% ® ⮬, ª ª¨¥ ¢¨àâã «ì­ë¥ ¬¥â®¤ë ¬®£ãâ ¡ëâì ¤¥-¢¨àâã «¨§¨à®¢ ­ë). ‚ í⮬ á«ãç ¥ ¨á¯®«ì§ã¥âáï ¨­ä®à¬ æ¨ï
+% ¨§ ¯®á«¥¤­¥© ᥪ樨. ‚ª«îç¨â¥ ®â« ¤®ç­ë¥ á®®¡é¥­¨ï (-vd), ç⮡ë 㢨¤¥âì, ª ª¨¥ ª« ááë ¨­ä®à¬ æ¨¨ ᮤ¥à¦ âáï
+% ¢ ª ¦¤®© ¨§ ᥪ権.
+wpo_cannot_extract_live_symbol_info_strip=12013_E_ˆ­ä®à¬ æ¨ï ® ¦¨¢ãç¥á⨠ᨬ¢®«®¢ ­¥ ¬®¦¥â ¡ëâì ¯®«ã祭  ¨§ ¯à®£à ¬¬ë ¡¥§ ®â« ¤®ç­®© ¨­ä®à¬ æ¨¨, ¨á¯®«ì§ã©â¥ -Xs-
+% ¥ª®â®àë¥ á¯®á®¡ë á¡®à  ¨­ä®à¬ æ¨¨ ® ¦¨¢ãç¥á⨠ᨬ¢®«®¢ ¯à¥¤¯®« £ îâ  ­ «¨§ ᨬ¢®«ì­®© ¨­ä®à¬ æ¨¨
+% £®â®¢®© ¯à®£à ¬¬ë. …᫨ íâ  ¨­ä®à¬ æ¨ï 㤠«¥­  (®¯æ¨ï -Xs), â ª®©  ­ «¨§ ­¥¢®§¬®¦¥­.
+wpo_cannot_extract_live_symbol_info_no_link=12014_E_ˆ­ä®à¬ æ¨ï ® ¦¨¢ãç¥á⨠ᨬ¢®«®¢ ­¥ ¬®¦¥â ¡ëâì ¯®«ã祭  ¡¥§ ᪮¬¯®­®¢ ­­®© ¯à®£à ¬¬ë
+% ¥ª®â®àë¥ á¯®á®¡ë á¡®à  ¨­ä®à¬ æ¨¨ ® ¦¨¢ãç¥á⨠ᨬ¢®«®¢ ¯à¥¤¯®« £ îâ  ­ «¨§ ᨬ¢®«ì­®© ¨­ä®à¬ æ¨¨
+% £®â®¢®© ¯à®£à ¬¬ë. …᫨ ¯à®£à ¬¬  ­¥ ᪮¬¯®­®¢ ­ , â ª®©  ­ «¨§ ­¥¢®§¬®¦¥­.
+wpo_cannot_find_symbol_progs=12015_F_¥ ­ ©¤¥­ë "$1" ¨«¨ "$2" ¤«ï ¨§¢«¥ç¥­¨ï ¨­ä®à¬ æ¨¨ ® ᨬ¢®« å ¨§ ᪮¬¯®­®¢ ­­®© ¯à®£à ¬¬ë
+% ¥ª®â®àë¥ á¯®á®¡ë á¡®à  ¨­ä®à¬ æ¨¨ ® ¦¨¢ãç¥á⨠ᨬ¢®«®¢ ¨á¯®«ì§ãî⠢ᯮ¬®£ â¥«ì­ë¥ ¯à®£à ¬¬ë
+% ¤«ï ¯®«ã祭¨ï ¨­ä®à¬ æ¨¨ ® ᨬ¢®« å ¯à®£à ¬¬ë. Ž¡ëç­® íâ® ¯à®£à ¬¬  'nm', ¢å®¤ïé ï ¢ á®áâ ¢ GNU binutils.
+wpo_error_reading_symbol_file=12016_E_Žè¨¡ª  ç⥭¨ï ¨­ä®à¬ æ¨¨ ® ¦¨¢ãç¥á⨠ᨬ¢®«®¢, ¯®«ã祭­®© ®â "$1"
+% ਠ¯®«ã祭¨¨ ¨­ä®à¬ æ¨¨ ® ᨬ¢®« å á ¯®¬®éìî ¢á¯®¬®£ â¥«ì­®© ¯à®£à ¬¬ë ('nm' ¨«¨ 'objdump') ¯à®¨§®è« 
+% ®è¨¡ª . ‚뢮¤ ¢á¯®¬®£ â¥«ì­®© ¯à®£à ¬¬ë ®ª § «áï ª®à®ç¥ ®¦¨¤ ¥¬®£®, ¨«¨ ¨¬¥¥â ­¥¢¥à­ë© ä®à¬ â.
+wpo_error_executing_symbol_prog=12017_F_Žè¨¡ª  ¢ë¯®«­¥­¨ï "$1" (ª®¤ ¢ë室 : $2) ¯à¨ ¨§¢«¥ç¥­¨¨ ¨­ä®à¬ æ¨¨ ® ᨬ¢®« å
+% ਠ¯®«ã祭¨¨ ¨­ä®à¬ æ¨¨ ® ᨬ¢®« å á ¯®¬®éìî ¢á¯®¬®£ â¥«ì­®© ¯à®£à ¬¬ë ('nm' ¨«¨ 'objdump') ¯à®¨§®è« 
+% ®è¨¡ª . ‚ᯮ¬®£ â¥«ì­ ï ¯à®£à ¬¬  ¢¥à­ã«  㪠§ ­­ë© ª®¤ ®è¨¡ª¨.
+wpo_symbol_live_info_needs_smart_linking=12018_E_‘¡®à ¨­ä®à¬ æ¨¨ ® ¦¨¢ãç¥á⨠ᨬ¢®«®¢ ¯®«¥§¥­ ⮫쪮 ¯à¨ "㬭®©" ª®¬¯®­®¢ª¥, ¨á¯®«ì§ã©â¥ -CX -XX
+% †¨¢ãç¥áâì ᨬ¢®«  ®¯à¥¤¥«ï¥âáï 䠪⮬ ¥£® ­ «¨ç¨ï ¢ £®â®¢®© ᪮¬¯®­®¢ ­­®© ¯à®£à ¬¬¥. …᫨ ®âª«î祭 
+% "㬭 ï" ª®¬¯®­®¢ª , ¢á¥ ᨬ¢®«ë ¢ªîç îâáï ¢ ¯à®£à ¬¬ã ­¥§ ¢¨á¨¬® ®â ⮣®, ¨á¯®«ì§ãîâáï ®­¨ ¨«¨ ­¥â.
+% â® ¤¥« ¥â á¡®à ¨­ä®à¬ æ¨¨ ® ¦¨¢ãç¥á⨠ᨬ¢®«®¢ ¡¥áá¬ëá«¥­­ë¬.
+wpo_cant_create_feedback_file=12019_E_¥¢®§¬®¦­® ᮧ¤ âì ä ©« ®¡à â­®© á¢ï§¨ "$1"
+% ” ©« ®¡à â­®© á¢ï§¨ wpo, 㪠§ ­­ë© á ¯®¬®éìî ª«îç  -FW, ­¥ ¬®¦¥â ¡ëâì ᮧ¤ ­.
+%\end{description}
+# EndOfTeX
+
+
+#
+# Logo (option -l)
+#
+option_logo=11023_[
+Š®¬¯¨«ïâ®à Free Pascal ¢¥àᨨ $FPCFULLVERSION [$FPCDATE] ¤«ï $FPCCPU
+Copyright (c) 1993-2011 by Florian Klaempfl
+]
+
+#
+# Info (option -i)
+#
+option_info=11024_[
+Free Pascal Compiler version $FPCVERSION
+
+Compiler Date : $FPCDATE
+Compiler CPU Target: $FPCCPU
+
+®¤¤¥à¦¨¢ ¥¬ë¥ ¯« âä®à¬ë:
+ $OSTARGETS
+
+®¤¤¥à¦¨¢ ¥¬ë¥ ­ ¡®àë ª®¬ ­¤ CPU:
+ $INSTRUCTIONSETS
+
+®¤¤¥à¦¨¢ ¥¬ë¥ ­ ¡®àë ª®¬ ­¤ FPU:
+ $FPUINSTRUCTIONSETS
+
+®¤¤¥à¦¨¢ ¥¬ë¥ ABI:
+ $ABITARGETS
+
+®¤¤¥à¦¨¢ ¥¬ë¥ ®¯â¨¬¨§ æ¨¨:
+ $OPTIMIZATIONS
+
+®¤¤¥à¦¨¢ ¥¬ë¥ ®¯â¨¬¨§ æ¨¨ ¢á¥© ¯à®£à ¬¬ë:
+ All
+ $WPOPTIMIZATIONS
+
+®¤¤¥à¦¨¢ ¥¬ë¥ â¨¯ë ¬¨ªà®ª®­â஫«¥à®¢:
+ $CONTROLLERTYPES
+
+This program comes under the GNU General Public Licence
+For more information read COPYING.FPC
+
+Report bugs, suggestions, etc. to:
+ http://bugs.freepascal.org
+or
+ bugs@freepascal.org
+]
+
+#
+# Help pages (option -? and -h)
+#
+# The first character on the line indicates who will display this
+# line, the current possibilities are :
+# * = every target
+# 3 = 80x86 targets
+# 6 = 680x0 targets
+# e = in extended debug mode only
+# P = PowerPC targets
+# S = Sparc targets
+# V = Virtual machine targets
+# The second character also indicates who will display this line,
+# (if the above character was TRUE) the current possibilities are :
+# * = everyone
+# g = with GDB info supported by the compiler
+# O = OS/2
+# L = UNIX systems
+# The third character represents the indentation level.
+#
+option_help_pages=11025_[
+**0*_„®¡ ¢ì⥠'+' ¯®á«¥ ®¯æ¨¨ ¡ã«¥¢  ª«îç  ¤«ï ¥£® ¢ª«î祭¨ï ¨ '-' ¤«ï ®âª«î祭¨ï
+**1a_Š®¬¯¨«ïâ®à ­¥ 㤠«ï¥â ᮧ¤ ­­ë©  áᥬ¡«¥à­ë© ä ©«
+**2al_‚뢮¤ ­®¬¥p®¢ áâப ¢  áᥬ¡«¥à­ë© ä ©«
+**2an_‚뢮¤ ¨­ä®à¬ æ¨¨ ®¡ 㧫 å £à ä  ¢  áᥬ¡«¥à­ë© ä ©«
+*L2ap_ˆá¯®«ì§®¢ âì ¯ ©¯ë ¢¬¥áâ® ¢à¥¬¥­­ëå  áᥬ¡«¥à­ë© ä ©«®¢
+**2ar_¥à¥ç¨á«ïâì ¢ë¤¥«¥­¨ï/®á¢®¡®¦¤¥­¨ï p¥£¨áâp®¢ ¢  áᥬ¡«¥p­®¬ ä ©«¥
+**2at_¥à¥ç¨á«ïâì ¢ë¤¥«¥­¨ï/®á¢®¡®¦¤¥­¨ï ¢p¥¬¥­­ëå ¯¥p¥¬¥­­ëå ¢  áᥬ¡«¥p­®¬ ä ©«¥
+**1A<x>_”®à¬ â ¢ë¢®¤ :
+**2Adefault_€áᥬ¡«¥à ¯® 㬮«ç ­¨î
+3*2Aas_€áᥬ¡«¥à GNU AS
+3*2Anasmcoff_COFF ä ©« (Go32v2), ¨á¯®«ì§ãï Nasm
+3*2Anasmelf_ELF32 ä ©« (Linux), ¨á¯®«ì§ãï Nasm
+3*2Anasmwin32_Win32 ®¡ê¥ªâ­ë© ä ©«, ¨á¯®«ì§ãï Nasm
+3*2Anasmwdosx_Win32/WDOSX ®¡ê¥ªâ­ë© ä ©«, ¨á¯®«ì§ãï Nasm
+3*2Awasm_Obj ä ©«, ¨á¯®«ì§ãï Wasm (Watcom)
+3*2Anasmobj_Obj ä ©«, ¨á¯®«ì§ãï Nasm
+3*2Amasm_Obj ä ©«, ¨á¯®«ì§ãï Masm (Microsoft)
+3*2Atasm_Obj ä ©«, ¨á¯®«ì§ãï Tasm (Borland)
+3*2Aelf_ELF (Linux) ¨á¯®«ì§ãï ¢­ãâ७­¨© £¥­¥à â®à
+3*2Acoff_COFF (Go32v2) ¨á¯®«ì§ãï ¢­ãâ७­¨© £¥­¥à â®à
+3*2Apecoff_PE-COFF (Win32) ¨á¯®«ì§ãï ¢­ãâ७­¨© £¥­¥à â®à
+4*2Aas_€áᥬ¡«¥à GNU AS
+6*2Aas_Unix o-ä ©«, ¨á¯®«ì§ãï GNU AS
+6*2Agas_GNU Motorola  áᥬ¡«¥à
+6*2Amit_‘¨­â ªá¨á MIT (áâ àë© GAS)
+6*2Amot_‘â ­¤ àâ­ë©  áᥬ¡«¥à Motorola
+A*2Aas_€áᥬ¡«¥à GNU AS
+P*2Aas_€áᥬ¡«¥à GNU AS
+S*2Aas_€áᥬ¡«¥à GNU AS
+**1b_ƒ¥­¥p¨p®¢ âì ¨­ä®p¬ æ¨î ¤«ï ¡p y§¥p  (IDE)
+**2bl_ƒ¥­¥p¨p®¢ âì â ª¦¥ ¨­ä®p¬ æ¨î ® «®ª «ì­ëå ᨬ¢®« å
+**1B_¥p¥á¡®àª  ¢á¥å ¬®¤y«¥©
+**1C<x>_Ž¯æ¨¨ £¥­¥p â®à  ª®¤ :
+**2Ca<x>_‚ë¡®à ABI, á¬. fpc -i ¤«ï ¢®§¬®¦­ëå §­ ç¥­¨©
+**2Cb_ƒ¥­¥à¨à®¢ âì big-endian ª®¤
+**2Cc<x>_“áâ ­®¢¨âì ⨯ ¢ë§®¢  ¯® 㬮«ç ­¨î ¢ <x>
+**2CD_‘®§¤ âì â ª¦¥ ¤¨­ ¬¨ç¥áªyî ¡¨¡«¨®â¥ªy (­¥ ¯®¤¤¥p¦¨¢ ¥âáï)
+**2Ce_Š®¬¯¨«¨à®¢ âì á í¬ã«¨à®¢ ­­ë¬¨ ¨­áâàãªæ¨ï¬¨ á ¯« ¢ î饩 § ¯ï⮩
+**2Cf<x>_‚ë¡®à ­ ¡®à  ª®¬ ­¤ ᮯà®æ¥áá®à , á¬. fpc -i ¤«ï ¢®§¬®¦­ëå §­ ç¥­¨©
+**2CF<x>_Œ¨­¨¬ «ì­ ï â®ç­®áâì ª®­áâ ­â á ¯« ¢ î饩 § ¯ï⮩ (default, 32, 64)
+**2Cg_ƒ¥­¥à¨à®¢ âì ¯®§¨æ¨®­­®-­¥§ ¢¨á¨¬ë© ª®¤ (PIC)
+**2Ch<n>_<n> ¡ ©â ªyç¨ (®â 1023 ¤® 67107840)
+**2Ci_p®¢¥pª  ¢¢®¤ -¢ë¢®¤ 
+**2Cn_p®¯yáâ¨âì áâ ¤¨î ª®¬¯®­®¢ª¨
+**2Co_p®¢¥pª  ¯¥à¥¯®«­¥­¨ï 楫®ç¨á«¥­­ëå ®¯¥à æ¨©
+**2CO_஢¥àª  ¢®§¬®¦­®£® ¯¥à¥¯®«­¥­¨ï 楫®ç¨á«¥­­ëå ®¯¥à æ¨©
+**2Cp<x>_‚ë¡®à ­ ¡®à  ª®¬ ­¤, á¬. fpc -i ¤«ï ¢®§¬®¦­ëå §­ ç¥­¨©
+**2CP<x>=<y>_ ­ áâனª¨ 㯠ª®¢ª¨
+**3CPPACKSET=<y>_ <y> 㯠ª®¢ª  ¬­®¦¥áâ¢: 0, 1 ¨«¨ DEFAULT ¨«¨ NORMAL, 2, 4 ¨ 8
+**2Cr_p®¢¥pª  ¤¨ ¯ §®­®¢
+**2CR_஢¥àª  ¯à ¢¨«ì­®á⨠¢ë§®¢  ¬¥â®¤®¢ ®¡ê¥ªâ®¢
+**2Cs<n>_“áâ ­®¢¨âì p §¬¥p á⥪  ¢ <n>
+**2Ct_஢¥àª  á⥪  (⮫쪮 â¥áâ¨à®¢ ­¨¥, á¬. à㪮¢®¤á⢮)
+**2CX_‘®§¤ âì â ª¦¥ smartlink-¡¨¡«¨®â¥ªã
+**1d<x>_Ž¯p¥¤¥«¨âì ᨬ¢®« <x>
+**1D_‘®§¤ âì DEF-ä ©«
+**2Dd<x>_“áâ ­®¢¨âì ®¯¨á ­¨¥ ¢ <x>
+**2Dv<x>_“áâ ­®¢¨âì ¢¥àá¨î DLL ¢ <x>
+*O2Dw_ਫ®¦¥­¨¥ PM
+**1e<x>_“áâ ­®¢¨âì ¯yâì ¤«ï ¨á¯®«­ï¥¬ëå ä ©«®¢
+**1E_’® ¦¥, çâ® ¨ -Cn
+**1fPIC_’® ¦¥, çâ® ¨ -Cg
+**1F<x>_“áâ ­®¢ª  ¨¬¥­ ¨ ¯ã⥩ ä ©«®¢
+**2Fa<x>[,y]_(¤«ï ¯à®£à ¬¬ë) § £à㧨âì ¬®¤ã«¨ <x> ¨ [y] ¯¥à¥¤ ç⥭¨¥¬ ᥪ樨 uses
+**2Fc<x>_“áâ ­®¢¨âì ª®¤®¢ãî áâà ­¨æã ¨á室­®£® ä ©«  ¢ <x>
+**2FC<x>_“áâ ­®¢¨âì ¨¬ï ª®¬¯¨«ïâ®à  à¥áãàᮢ (.rc) ¢ <x>
+**2Fd_Žâª«îç¨âì ¢­ãâ७­¨© ªíè ¤¨à¥ªâ®à¨© ª®¬¯¨«ïâ®à 
+**2FD<x>_“áâ ­®¢¨âì ¯yâì ¯®¨áª  ã⨫¨â ª®¬¯¨«ïâ®à 
+**2Fe<x>_¥p¥­ ¯p ¢¨âì ¢ë¢®¤ ®è¨¡®ª ¢ <x>
+**2Ff<x>_„®¡ ¢¨âì <x> ª ¯ã⨠ä३¬¢®àª  (⮫쪮 Darwin)
+**2FE<x>_“áâ ­®¢¨âì ¯ãâì ¢ë¢®¤  exe/¬®¤ã«¥© ¢ <x>
+**2Fi<x>_„®¡ ¢¨âì <x> ª ¯yâï¬ ¢ª«îç ¥¬ëå ä ©«®¢
+**2Fl<x>_„®¡ ¢¨âì <x> ª ¯yâï¬ ¡¨¡«¨®â¥ª
+**2FL<x>_ˆá¯®«ì§®¢ âì <x> ª ª ¤¨­ ¬¨ç¥áª¨© ª®¬¯®­®¢é¨ª
+**2Fm<x>_‡ £à㧨âì â ¡«¨æ㠯८¡à §®¢ ­¨ï unicode ¨§ <x>.txt ¢ ¤¨à¥ªâ®à¨¨ ª®¬¯¨«ïâ®à 
+**2Fo<x>_„®¡ ¢¨âì <x> ª ¯yâï¬ ®¡ê¥ªâ­ëå ä ©«®¢
+**2Fr<x>_‡ £py§¨âì ä ©« á®®¡é¥­¨© ®¡ ®è¨¡ª å <x>
+**2FR<x>_“áâ ­®¢¨âì ¨¬ï ª®¬¯®­®¢é¨ª  à¥áãàᮢ (.res) ¢ <x>
+**2Fu<x>_„®¡ ¢¨âì <x> ª ¯ãâï¬ ¬®¤ã«¥©
+**2FU<x>_“áâ ­®¢¨âì ¯yâì ¢ë¢®¤  ¬®¤y«¥© ¢ <x>, ®â¬¥­ï¥â -FE
+**2FW<x>_‡ ¯¨á âì ä ©« ®¡à â­®© á¢ï§¨ ®¯â¨¬¨§ æ¨¨ ¢á¥© ¯à®£à ¬¬ë ¢ <x>
+**2Fw<x>_‡ £à㧨âì à ­¥¥ ᮧ¤ ­­ë© ä ©« ®¡à â­®© á¢ï§¨ ¨§ <x>
+*g1g_‘®§¤ ¢ âì ®â« ¤®ç­ãî ¨­ä®à¬ æ¨î (ä®à¬ â¥ ¯® 㬮«ç ­¨î ¤«ï 楫¥¢®© ¯« âä®à¬ë)
+*g2gc_‘®§¤ ¢ âì ¯à®¢¥àª¨ 㪠§ â¥«¥©
+*g2gh_ˆá¯®«ì§®¢ âì ¬®¤y«ì heaptrc (¤«ï ®â« ¤ª¨ yâ¥ç¥ª/¯®¢à¥¦¤¥­¨© ¯ ¬ïâ¨)
+*g2gl_ˆá¯®«ì§®¢ âì ¬®¤ã«ì lineinfo (¡®«ìè¥ ¨­ä®à¬ æ¨¨ ® á⥪¥ ¢ë§®¢®¢)
+*g2go<x>_Ž¯æ¨¨ ®â« ¤®ç­®© ¨­ä®à¬ æ¨¨
+*g3godwarfsets_ ‚ª«îç¨âì ¨­ä®à¬ æ¨î ® ¬­®¦¥á⢠å DWARF («®¬ ¥â gdb < 6.5)
+*g3gostabsabsincludes_ ‘®åà ­ïâì  ¡á®«îâ­ë¥/¯®«­ë¥ ¯ã⨠¢ª«îç ¥¬ëå ä ©«®¢ ¢ Stabs
+*g2gp_‘®åà ­ïâì ॣ¨áâà ¢ ¨¬¥­ å ᨬ¢®«®¢ stabs
+*g2gs_Žâ« ¤®ç­ ï ¨­ä®à¬ æ¨ï ¢ ä®à¬ â¥ Stabs
+*g2gt_‡ â¨à âì «®ª «ì­ë¥ ¯¥à¥¬¥­­ë¥ (¢ë¥­¨¥ ¨á¯®«ì§®¢ ­¨ï ¡¥§ ¨­¨æ¨ «¨§ æ¨¨)
+*g2gv_®¤¤¥à¦ª  âà áá¨à®¢ª¨ á ¯®¬®éìî Valgrind
+*g2gw_Žâ« ¤®ç­ ï ¨­ä®à¬ æ¨ï ¢ ä®à¬ â¥ DWARFv2 (â® ¦¥, çâ® ¨ -gw2)
+*g2gw2_Žâ« ¤®ç­ ï ¨­ä®à¬ æ¨ï ¢ ä®à¬ â¥ DWARFv2
+*g2gw3_Žâ« ¤®ç­ ï ¨­ä®à¬ æ¨ï ¢ ä®à¬ â¥ DWARFv3
+**1i_ˆ­ä®p¬ æ¨ï
+**2iD_‚¥à­ãâì ¤ ây ª®¬¯¨«ïâ®p 
+**2iV_‚¥à­ãâì ª®à®âªãî ¢¥pá¨î ª®¬¯¨«ïâ®à 
+**2iW_‚¥à­ãâì ¯®«­ãî ¢¥àá¨î ª®¬¯¨«ïâ®à 
+**2iSO_‚¥à­ãâì ⨯ Ž‘ ª®¬¯¨«ïâ®à 
+**2iSP_‚¥à­ãâì ⨯ ¯p®æ¥áá®p  ª®¬¯¨«ïâ®à 
+**2iTO_‚¥à­ãâì ⨯ 楫¥¢®© Ž‘
+**2iTP_‚¥à­ãâì ⨯ 楫¥¢®£® ¯p®æ¥áá®p 
+**1I<x>_„®¡ ¢¨âì <x> ª ¯y⨠¤® ¢ª«îç ¥¬ëå ä ©«®¢
+**1k<x>_¥à¥¤ âì <x> ª®¬¯®­®¢é¨ªy
+**1l_‚뢥á⨠«®£®â¨¯
+**1M<x>_“áâ ­®¢¨âì ०¨¬ ï§ëª  ¢ <x>
+**2Mfpc_„¨ «¥ªâ Free Pascal (¯® 㬮«ç ­¨î)
+**2Mobjfpc_¥¦¨¬ FPC á ¯®¤¤¥à¦ª®© Object Pascal
+**2Mdelphi_¥¦¨¬ ᮢ¬¥á⨬®á⨠á Delphi 7
+**2Mtp_¥¦¨¬ ᮢ¬¥á⨬®á⨠á TP/BP 7.0
+**2Mmacpas_¥¦¨¬ ᮢ¬¥á⨬®áâ¨ á ¤¨ «¥ªâ ¬¨ Macintosh Pascal
+**1n_¥ ç¨â âì áâ ­¤ pâ­ë¥ ä ©«ë ª®­ä¨£ãà æ¨¨
+**1N<x>_Ž¯â¨¬¨§ æ¨ï £à ä 
+**2Nu_ §¢®à ç¨¢ âì 横«ë
+**1o<x>_ˆ§¬¥­¨âì ¨¬ï ¯®«ãç ¥¬®£® ¨á¯®«­ï¥¬®£® ä ©«  ­  <x>
+**1O<x>_Ž¯â¨¬¨§ æ¨¨:
+**2O-_Žâª«îç¨âì ®¯â¨¬¨§ æ¨¨
+**2O1_Ž¯â¨¬¨§ æ¨¨ ã஢­ï 1 (¡ëáâà® ¨ ᮢ¬¥á⨬® á ®â« ¤ç¨ª®¬)
+**2O2_Ž¯â¨¬¨§ æ¨¨ ã஢­ï 2 (-O1 + ¡ëáâàë¥ ®¯â¨¬¨§ æ¨¨)
+**2O3_Ž¯â¨¬¨§ æ¨¨ ã஢­ï 3 (-O2 + ¬¥¤«¥­­ë¥ ®¯â¨¬¨§ æ¨¨)
+**2Oa<x>=<y>_“áâ ­®¢¨âì ¢ëà ¢­¨¢ ­¨¥
+**2Oo[NO]<x>_‚ª«îç¨âì ¨«¨ ®âª«îç¨âì ®â¤¥«ì­ë¥ ®¯â¨¬¨§ æ¨¨, á¬. fpc -i ¤«ï ¢®§¬®¦­ëå §­ ç¥­¨©
+**2Op<x>_‡ ¤ âì ¯à®æ¥áá®à ¤«ï ®¯â¨¬¨§ æ¨¨, á¬. fpc -i ¤«ï ¢®§¬®¦­ëå §­ ç¥­¨©
+**2OW<x>_ƒ¥­¥à æ¨ï ä ©«  ®¡à â­®© á¢ï§¨ wpo ¤«ï ®¯â¨¬¨§ æ¨¨ <x>, á¬. fpc -i ¤«ï ¢®§¬®¦­ëå §­ ç¥­¨©
+**2Ow<x>_‚믮«­¨âì ®¯â¨¬¨§ æ¨î <x> ¢á¥© ¯à®£à ¬¬ë, á¬. fpc -i ¤«ï ¢®§¬®¦­ëå §­ ç¥­¨©
+**2Os_Ž¯â¨¬¨§ æ¨ï ¯® à §¬¥àã ¢¬¥á⮠᪮à®áâ¨
+**1pg_ƒ¥­¥p æ¨ï ª®¤  ¤«ï ¯à®ä¨«¨à®¢ ­¨ï á ¯®¬®éìî gprof (®¯p¥¤¥«ï¥â ᨬ¢®« FPC_PROFILE)
+**1R<x>_‘⨫ì ç⥭¨ï  áᥬ¡«¥à :
+**2Rdefault_€áᥬ¡«¥à ¯® 㬮«ç ­¨î ¤«ï 楫¥¢®© ¯« âä®à¬ë
+3*2Ratt_—⥭¨¥  áᥬ¡«¥à  ¢ á⨫¥ AT&T
+3*2Rintel_—⥭¨¥  áᥬ¡«¥à  ¢ á⨫¥ Intel
+6*2RMOT_—⥭¨¥  áᥬ¡«¥à  ¢ á⨫¥ Motorola
+**1S<x>_Ž¯æ¨¨ ᨭ⠪á¨á :
+**2S2_’® ¦¥, çâ® ¨ -Mobjfpc
+**2Sc_®¤¤¥p¦ª  ®¯¥à â®à®¢ ª ª ¢ C (*=,+=,/= ¨ -=)
+**2sa_‚ª«îç¨âì ¯à®¢¥àª¨ Assert
+**2Sd_’® ¦¥, çâ® ¨ -Mdelphi
+**2Se<x>_Ž¯æ¨¨ ®è¨¡®ª. <x> - ª®¬¡¨­ æ¨ï á«¥¤ãîé¨å ᨬ¢®«®¢:
+**3*_<n> : Žáâ ­®¢ª  ª®¬¯¨«ï樨 ¯®á«¥ <n> ®è¨¡®ª (¯® 㬮«ç ­¨î 1)
+**3*_w : Š®¬¯¨«ïâ®à â ª¦¥ ®áâ ­ ¢«¨¢ ¥âáï ¯®á«¥ ¯à¥¤ã¯à¥¦¤¥­¨©
+**3*_n : Š®¬¯¨«ïâ®à â ª¦¥ ®áâ ­ ¢«¨¢ ¥âáï ¯®á«¥ § ¬¥â®ª
+**3*_h : Š®¬¯¨«ïâ®à â ª¦¥ ®áâ ­ ¢«¨¢ ¥âáï ¯®á«¥ ¯®¤áª §®ª
+**2Sg_ §à¥è¨âì LABEL ¨ GOTO (¯® 㬮«ç ­¨î ¢ -Mtp ¨ -Mdelphi)
+**2Sh_ˆá¯®«ì§®¢ âì áâp®ª¨ ansistring ¯® 㬮«ç ­¨î ¢¬¥áâ® shortstring
+**2Si_‚ª«îç¨âì ¢áâà ¨¢ ­¨¥ ¯à®æ¥¤ãà/ä㭪権, ®¡ê¥­­ëå ª ª "inline"
+**2Sk_‡ £à㧨âì ¬®¤ã«ì fpcylix
+**2SI<x>_“áâ ­®¢¨âì áâ¨«ì ¨­â¥à䥩ᮢ ¢ <x>
+**3SIcom_COM-ᮢ¬¥áâ¨¬ë¥ ¨­â¥à䥩áë (¯® 㬮«ç ­¨î)
+**3SIcorba_CORBA-ᮢ¬¥áâ¨¬ë¥ ¨­â¥à䥩áë
+**2Sm_®¤¤¥p¦ª  ¬ ªà®ª®¬ ­¤ ª ª ¢ C (£«®¡ «ì­®)
+**2So_’® ¦¥, çâ® ¨ -Mtp
+**2Ss_ˆ¬¥­  ª®­áâàãªâ®à®¢/¤¥áâàãªâ®à®¢ ¤®«¦­ë ¡ëâì init/done
+**2Sx_®¤¤¥à¦ª  ª«î祢ëå á«®¢ ¨áª«î祭¨© (¯® 㬮«ç ­¨î ¢ ०¨¬ å Delphi/ObjFPC)
+**1s_¥ ¢ë§ë¢ âì  áᥬ¡«¥à ¨ ª®¬¯®­®¢é¨ª
+**2sh_‘®§¤ âì áªà¨¯â ¤«ï ª®¬¯®­®¢ª¨ ­  å®áâ¥
+**2st_‘®§¤ âì áªà¨¯â ¤«ï ª®¬¯®­®¢ª¨ ­  ¯« âä®à¬¥ ­ §­ ç¥­¨ï
+**2sr_யãáâ¨âì ä §ã à á¯à¥¤¥«¥­¨ï ॣ¨áâ஢ (¨á¯®«ì§ã¥âáï á -alr)
+**1T<x>_Ž¯¥à æ¨®­­ ï á¨á⥬  ­ §­ ç¥­¨ï:
+3*2Temx_OS/2 ç¥à¥§ EMX (¢ª«îç ï à áè¨à¨â¥«ì EMX/RSX)
+3*2Tfreebsd_FreeBSD
+3*2Tgo32v2_‚¥àá¨ï 2 à áè¨à¨â¥«ï DOS DJ Delorie
+3*2Tlinux_Linux
+3*2Tnetbsd_NetBSD
+3*2Tnetware_Œ®¤ã«ì Novell Netware (clib)
+3*2Tnetwlibc_Œ®¤ã«ì Novell Netware (libc)
+3*2Topenbsd_OpenBSD
+3*2Tos2_OS/2 / eComStation
+3*2Tsunos_SunOS/Solaris
+3*2Tsymbian_Symbian OS
+3*2Twatcom_Watcom-ᮢ¬¥áâ¨¬ë© à áè¨à¨â¥«ì DOS
+3*2Twdosx_ áè¨à¨â¥«ì DOS WDOSX
+3*2Twin32_Windows 32 ¡¨â 
+3*2Twince_Windows CE
+4*2Tlinux_Linux
+6*2Tamiga_Commodore Amiga
+6*2Tatari_Atari ST/STe/TT
+6*2Tlinux_Linux/m68k
+6*2Tmacos_Macintosh m68k (­¥ ¯®¤¤¥à¦¨¢ ¥âáï)
+6*2Tpalmos_PalmOS
+A*2Tlinux_Linux
+A*2Twince_Windows CE
+P*2Tamiga_AmigaOS ­  PowerPC
+P*2Tdarwin_Darwin ¨ Mac OS X ­  PowerPC
+P*2Tlinux_Linux ­  PowerPC
+P*2Tmacos_Mac OS (classic) ­  PowerPC
+P*2Tmorphos_MorphOS
+S*2Tlinux_Linux
+**1u<x>_y¤ «ï¥â ®¯p¥¤¥«¥­¨¥ ᨬ¢®«  <x>
+**1U_Ž¯æ¨¨ ¬®¤y«¥©:
+**2Un_¥ ¯p®¢¥pïâì ᮮ⢥âá⢨¥ ¨¬¥­¨ ¬®¤y«ï ¨ ¨¬¥­¨ ä ©« 
+**2Ur_ƒ¥­¥à¨à®¢ âì ५¨§­ë¥ ä ©«ë ¬®¤ã«¥© (­¥ ¯¥à¥ª®¬¯¨«¨àãîâáï  ¢â®¬ â¨ç¥áª¨)
+**2Us_Š®¬¯¨«¨p®¢ âì ¬®¤y«ì system
+**1v<x>_“஢¥­ì ¯®¤p®¡­®áâ¨. <x> - ª®¬¡¨­ æ¨ï á«¥¤yîé¨å ᨬ¢®«®¢:
+**2*_e : Žè¨¡ª¨ (¯® 㬮«ç ­¨î) 0 : ¨ç¥£® (ªà®¬¥ ®è¨¡®ª)
+**2*_w : ।ã¯à¥¦¤¥­¨ï u : ˆ­ä®à¬ æ¨ï ® ¬®¤ã«ïå
+**2*_n : ਬ¥ç ­¨ï t : ®¯à®¡®¢ ­­ë¥/¨á¯®«ì§®¢ ­­ë¥ ä ©«ë
+**2*_h : ®¤áª §ª¨ c : “á«®¢­ë¥ ¢ëà ¦¥­¨ï
+**2*_i : Ž¡é ï ¨­ä®à¬ æ¨ï d : Žâ« ¤®ç­ë¥ á®®¡é¥­¨ï
+**2*_l : H®¬¥p  áâப c : ¥¦¨¬ ᮢ¬¥á⨬®á⨠á Rhide/GCC
+**2*_s : Žâ¬¥âª¨ ¢à¥¬¥­¨ q : ®¬¥à  á®®¡é¥­¨©
+**2*_a : ®ª §ë¢ âì ¢á¥ x : ˆ­ä®à¬ æ¨ï ® ¨á¯®«­ï¥¬®¬ ä ©«¥ (⮫쪮 Win32)
+**2*_b : ‘®®¡é¥­¨ï ® ä ©« å p : ‡ ¯¨áì tree.log á £à ä®¬ à §¡®à 
+**2*_ á ¯®«­ë¬¨ ¯ãâﬨ x : ‡ ¯¨áì fpcdebug.txt á ¯®¤à®¡­®©
+**2*_ ¨¬¥­­® ¢ ­¥© ®â« ¤®ç­®© ¨­ä®à¬ æ¨¥©
+**2*_m<x>,<y> : ¥ ¯®ª §ë¢ âì á®®¡é¥­¨ï á ­®¬¥à ¬¨ <x> ¨ <y>
+3*1W<x>_« âä®à¬¥­­®-ᯥæ¨ä¨ç­ë¥ ®¯æ¨¨ (¯« âä®à¬ë)
+A*1W<x>_« âä®à¬¥­­®-ᯥæ¨ä¨ç­ë¥ ®¯æ¨¨ (¯« âä®à¬ë)
+P*1W<x>_« âä®à¬¥­­®-ᯥæ¨ä¨ç­ë¥ ®¯æ¨¨ (¯« âä®à¬ë)
+p*1W<x>_« âä®à¬¥­­®-ᯥæ¨ä¨ç­ë¥ ®¯æ¨¨ (¯« âä®à¬ë)
+3*2Wb_‘®§¤ ¢ âì bundle ¢¬¥áâ® ¡¨¡«¨®â¥ª¨ (Darwin)
+P*2Wb_‘®§¤ ¢ âì bundle ¢¬¥áâ® ¡¨¡«¨®â¥ª¨ (Darwin)
+p*2Wb_‘®§¤ ¢ âì bundle ¢¬¥áâ® ¡¨¡«¨®â¥ª¨ (Darwin)
+3*2WB_‘®§¤ ¢ âì ¯¥à¥¬¥é ¥¬ë© ®¡à § (Windows)
+A*2WB_‘®§¤ ¢ âì ¯¥à¥¬¥é ¥¬ë© ®¡à § (Windows, Symbian)
+3*2WC_“ª § âì ª®­á®«ì­ë© ⨯ ¯à¨«®¦¥­¨ï (EMX, OS/2, Windows)
+A*2WC_“ª § âì ª®­á®«ì­ë© ⨯ ¯à¨«®¦¥­¨ï (Windows)
+P*2WC_“ª § âì ª®­á®«ì­ë© ⨯ ¯à¨«®¦¥­¨ï (Classic Mac OS)
+3*2WD_ˆá¯®«ì§®¢ âì DEFFILE ¤«ï íªá¯®àâ  ä㭪樨 DLL ¨«¨ EXE (Windows)
+A*2WD_ˆá¯®«ì§®¢ âì DEFFILE ¤«ï íªá¯®àâ  ä㭪樨 DLL ¨«¨ EXE (Windows)
+3*2We_ˆá¯®«ì§®¢ âì ¢­¥è­¨¥ à¥áãàáë (Darwin)
+P*2We_ˆá¯®«ì§®¢ âì ¢­¥è­¨¥ à¥áãàáë (Darwin)
+p*2We_ˆá¯®«ì§®¢ âì ¢­¥è­¨¥ à¥áãàáë (Darwin)
+3*2WF_“ª § âì ¯®«­®íªà ­­ë© ⨯ ¯à¨«®¦¥­¨ï (EMX, OS/2)
+3*2WG_“ª § âì £à ä¨ç¥áª¨© ⨯ ¯à¨«®¦¥­¨ï (EMX, OS/2, Windows)
+A*2WG_“ª § âì £à ä¨ç¥áª¨© ⨯ ¯à¨«®¦¥­¨ï (Windows)
+P*2WG_“ª § âì £à ä¨ç¥áª¨© ⨯ ¯à¨«®¦¥­¨ï (Classic Mac OS)
+3*2Wi_ˆá¯®«ì§®¢ âì ¢­ãâ७­¨¥ à¥áãàáë (Darwin)
+P*2Wi_ˆá¯®«ì§®¢ âì ¢­ãâ७­¨¥ à¥áãàáë (Darwin)
+p*2Wi_ˆá¯®«ì§®¢ âì ¢­ãâ७­¨¥ à¥áãàáë (Darwin)
+3*2WN_¥ £¥­¥à¨à®¢ âì ª®¤ ¯¥à¥¬¥é¥­¨ï, ­ã¦­® ¤«ï ®â« ¤ª¨ (Windows)
+A*2WN_¥ £¥­¥à¨à®¢ âì ª®¤ ¯¥à¥¬¥é¥­¨ï, ­ã¦­® ¤«ï ®â« ¤ª¨ (Windows)
+3*2WR_ƒ¥­¥à¨à®¢ âì ª®¤ ¯¥à¥¬¥é¥­¨ï (Windows)
+A*2WR_ƒ¥­¥à¨à®¢ âì ª®¤ ¯¥à¥¬¥é¥­¨ï (Windows)
+P*2WT_“ª § âì ⨯ ¯à¨«®¦¥­¨ï MPW tool (Classic Mac OS)
+3*2WX_ §à¥è¨âì ¨á¯®«­ï¥¬ë© á⥪ (Linux)
+A*2WX_ §à¥è¨âì ¨á¯®«­ï¥¬ë© á⥪ (Linux)
+p*2WX_ §à¥è¨âì ¨á¯®«­ï¥¬ë© á⥪ (Linux)
+P*2WX_ §à¥è¨âì ¨á¯®«­ï¥¬ë© á⥪ (Linux)
+**1X_®¯æ¨¨ ¢ë¯®«­¥­¨ï
+**2Xc_¥à¥¤ âì ª®¬¯®­®¢é¨ªã --shared/-dynamic (BeOS, Darwin, FreeBSD, Linux)
+**2Xd_¥ ¨á¯®«ì§®¢ âì áâ ­¤ àâ­ë© ¯ãâì ¯®¨áª  ¡¨¡«¨®â¥ª (­ã¦­® ¤«ï ªà®á᪮¬¯¨«ï樨)
+**2Xe_ˆá¯®«ì§®¢ âì ¢­¥è­¨© ª®¬¯®­®¢é¨ª
+**2Xg_‘®§¤ âì ®â« ¤®ç­ãî ¨­ä®à¬ æ¨î ¢ ®â¤¥«ì­®¬ ä ©«¥ ¨ ¤®¡ ¢¨âì ᥪæ¨î debuglink ¢ ¨á¯®«­ï¥¬ë© ä ©«
+**2XD_®¯à®¡®¢ âì ᪮¬¯®­®¢ âì ¤¨­ ¬¨ç¥áª¨ (®¯à¥¤¥«ï¥â ᨬ¢®« FPC_LINK_DYNAMIC)
+**2Xi_ˆá¯®«ì§®¢ âì ¢­ãâ७­¨© ª®¬¯®­®¢é¨ª
+**2Xm_‘®§¤ âì ª àâã ª®¬¯®­®¢ª¨
+**2XM<x>_‡ ¤ âì ¨¬ï ®á­®¢­®© â®çª¨ ¢å®¤  'main' (¯® 㬮«ç ­¨î 'main')
+**2XP<x>_„®¡ ¢¨âì ª ¨¬¥­ ¬ binutils ¯à¥ä¨ªá <x>
+**2Xr<x>_“áâ ­®¢¨âì rlink-path ª®¬¯®­®¢é¨ª  ¢ <x> (­ã¦­® ¤«ï ªà®á᪮¬¯¨«ï樨, á¬. à㪮¢®¤á⢮ ld) (BeOS, Linux)
+**2XR<x>_„®¡ ¢¨â ¯à¥ä¨ªá <x> ª® ¢á¥¬ ¯ãâï¬ ¯®¨áª  ª®¬¯®­®¢é¨ª  (BeOS, Darwin, FreeBSD, Linux, Mac OS, Solaris)
+**2Xs_“¡à âì ¢á¥ á¨¬¢®«ë ¨§ ¨á¯®«­ï¥¬®£® ä ©« 
+**2XS_®¯à®¡®¢ âì ᪮¬¯®­®¢ âì áâ â¨ç¥áª¨ (¯® 㬮«ç ­¨î, ®¯à¥¤¥«ï¥â ᨬ¢®« FPC_LINK_STATIC)
+**2Xt_Š®¬¯®­®¢ª  á® áâ â¨ç¥áª¨¬¨ ¡¨¡«¨®â¥ª ¬¨ (ª®¬¯®­®¢é¨ªã ¯¥à¥¤ ¥âáï -static)
+**2XX_®¯à®¡®¢ âì "㬭ãî" ª®¬¯®­®¢ªã (®¯à¥¤¥«ï¥â ᨬ¢®« FPC_LINK_SMART)
+**1*_
+**1?_¯®ª § âì íây á¯à ¢ªy
+**1h_¯®ª § âì íây á¯à ¢ªy ¡¥§ ®¦¨¤ ­¨ï
+]
+
+#
+# The End...
diff --git a/closures/compiler/msg/errorru.msg b/closures/compiler/msg/errorru.msg
new file mode 100644
index 0000000000..4efaf6146b
--- /dev/null
+++ b/closures/compiler/msg/errorru.msg
@@ -0,0 +1,2832 @@
+#
+# This file is part of the Free Pascal Compiler
+# Copyright (c) 1999-2009 by the Free Pascal Development team
+#
+# Russian (utf-8) Language File for Free Pascal
+#
+# This file corresponds to SVN revision 13665 of errore.msg
+# Translated by Sergei Gorelkin <sergei_gorelkin at mail.ru>
+#
+# See the file COPYING.FPC, included in this distribution,
+# for details about the copyright.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#
+#
+# КонÑтанты запиÑываютÑÑ Ð² Ñледyющем виде:
+# <part>_<type>_<txtidentifier>
+#
+# <part> - чаÑÑ‚ÑŒ компилÑтора, в которой иÑпользуетÑÑ Ñообщение:
+# asmr_ чтение аÑÑемблера
+# asmw_ запиÑÑŒ аÑÑемблера/обьектных файлов
+# unit_ обработка модулей
+# scan_ Ñканер
+# parser_ ÑемантичеÑкий анализатор
+# type_ контроль ÑоответÑÑ‚Ð²Ð¸Ñ Ñ‚Ð¸Ð¿Ð¾Ð²
+# general_ Ð¾Ð±Ñ‰Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ
+# exec_ вызовы внешних программ (аÑÑемблера, компоновщика и Ñ‚.д.)
+# link_ внутренний компоновщик
+#
+# <type> тип ÑообщениÑ:
+# f_ Ñ„Ð°Ñ‚Ð°Ð»ÑŒÐ½Ð°Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ°
+# e_ ошибка
+# w_ предупреждение
+# n_ примечание
+# h_ подÑказка
+# i_ информациÑ
+# l_ добавлÑетÑÑ Ð½Ð¾Ð¼Ðµp ÑÑ‚pоки
+# u_ иÑпользование
+# t_ попытка иÑпользовать
+# c_ уÑловное выражение
+# d_ отладочное Ñообщение
+# x_ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ иÑполнÑемых файлах
+# o_ обычные ("нажмите любую клавишу")
+#
+
+#
+# General
+#
+# 01023 is the last used one
+#
+# BeginOfTeX
+% \section{Общие ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ ÐºÐ¾Ð¼Ð¿Ð¸Ð»Ñтора}
+% Этот раздел Ñодержит ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ð¾Ð½Ð½Ð¾Ð³Ð¾ назначениÑ.
+% КоличеÑтво таких Ñообщений управлÑетÑÑ
+% различными наÑÑ‚pойками ypÐ¾Ð²Ð½Ñ Ð¿Ð¾Ð´Ñ€Ð¾Ð±Ð½Ð¾Ñти \var{-v}.
+% \begin{description}
+general_t_compilername=01000_T_КомпилÑтоp: $1
+% При иÑпользовании ключа \var{-vt} Ñта Ñтрока Ñообщает вам, какой
+% компилÑтор иÑпользуетÑÑ.
+general_d_sourceos=01001_D_ОС компилÑтора: $1
+% При иÑпользовании ключа \var{-vd} Ñта Ñтрока Ñообщает название
+% операционной ÑиÑтемы, в которой проиÑходит компилÑциÑ.
+general_i_targetos=01002_I_Ð¦ÐµÐ»ÐµÐ²Ð°Ñ ÐžÐ¡: $1
+% При иÑпользовании ключа \var{-vd} Ñта Ñтрока Ñообщает название
+% операционной ÑиÑтемы, Ð´Ð»Ñ ÐºÐ¾Ñ‚Ð¾Ñ€Ð¾Ð¹ ÑоздаетÑÑ Ñ„Ð°Ð¹Ð».
+general_t_exepath=01003_T_ПyÑ‚ÑŒ иÑполнÑемых файлов: $1
+% При иÑпользовании ключа \var{-vt} Ñта Ñтрока Ñообщает путь,
+% по которому компилÑтор ищет иÑполнÑемые файлы.
+general_t_unitpath=01004_T_Путь модулей: $1
+% При иÑпользовании ключа \var{-vt} Ñта Ñтрока Ñообщает путь,
+% по которому компилÑтор ищет компилируемые модули. Этот путь
+% может быть изменен Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ ключа \var{-Fu}.
+general_t_includepath=01005_T_Пyть включаемых файлов: $1
+% При иÑпользовании ключа \var{-vt} Ñта Ñтрока Ñообщает путь,
+% по которому компилÑтор ищет включаемые файлы (файлы, иÑпользуемые в директивах
+% \var{\{\$I xxx\}}). Этот путь может быть изменен Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ ключа \var{-I}.
+general_t_librarypath=01006_T_Пyть библиотек: $1
+% При иÑпользовании ключа \var{-vt} Ñта Ñтрока Ñообщает путь,
+% по которому компилÑтор ищет библиотеки. Этот путь может быть изменен
+% Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ ключа \var{-Fl}.
+general_t_objectpath=01007_T_Пyть объектных файлов: $1
+% При иÑпользовании ключа \var{-vt} Ñта Ñтрока Ñообщает путь, по которому
+% компилÑтор ищет объектные файлы (файлы, иÑпользуемые в директивах
+% \var{\{\$L xxx \}}). Этот путь может быть изменен Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ ключа \var{-Fo}.
+general_i_abslines_compiled=01008_I_$1 Ñтрок Ñкомпилиpовано, $2 Ñек.$3
+% При иÑпользовании ключа \var{-vi} компилÑтор Ñообщает чиÑло
+% Ñкомпилиpованных Ñтрок, и времÑ, которое потpебовалоÑÑŒ Ð´Ð»Ñ Ñтого.
+% (реальное, не программное времÑ).
+general_f_no_memory_left=01009_F_HедоÑтаточно памÑти
+% КомпилÑтору не хватило памÑти Ð´Ð»Ñ ÐºÐ¾Ð¼Ð¿Ð¸Ð»Ñции вашей программы.
+% ИмеетÑÑ Ð½ÐµÑколько pекомендаций Ð´Ð»Ñ pÐµÑˆÐµÐ½Ð¸Ñ Ñтого вопpоÑа:
+% \begin{itemize}
+% \item ВмеÑто полной Ñборки проекта, попробуйте компилировать
+% отдельные модули вручную.
+% \item ЕÑли размер программы большой, разбейте ее на модули, и
+% компилируйте их отдельно.
+% \item ЕÑли предыдущие рекомендации не работают, переÑоберите компилÑтор
+% Ñ Ð±Ð¾Ð»ÑŒÑˆÐ¸Ð¼ pазмеpом кyчи (Ð´Ð»Ñ Ñтого иÑпользуетÑÑ ÐºÐ»ÑŽÑ‡ \var{-Ch}, \seeo{Ch})
+% \end{itemize}
+general_i_writingresourcefile=01010_I_ЗапиÑÑŒ файла таблицы ÑÑ‚pоковых pеÑypÑов: $1
+% Сообщение означает, что компилÑтор Ñоздает файл, Ñодержащий вÑе реÑурÑные Ñтроки программы
+% (таблицу Ñтроковых реÑурÑов).
+general_e_errorwritingresourcefile=01011_E_Ошибка запиÑи файла таблицы ÑÑ‚pоковых pеÑypÑов: $1
+% Сообщение означает, что в процеÑÑе запиÑи файла Ñтроковых реÑурÑов
+% произошла ошибка.
+general_i_fatal=01012_I_Фатально:
+% ÐŸÑ€ÐµÑ„Ð¸ÐºÑ Ð´Ð»Ñ Ñ„Ð°Ñ‚Ð°Ð»ÑŒÐ½Ñ‹Ñ… ошибок
+general_i_error=01013_I_Ошибка:
+% ÐŸÑ€ÐµÑ„Ð¸ÐºÑ Ð´Ð»Ñ Ð¾ÑˆÐ¸Ð±Ð¾Ðº
+general_i_warning=01014_I_Внимание:
+% ÐŸÑ€ÐµÑ„Ð¸ÐºÑ Ð´Ð»Ñ Ð¿Ñ€ÐµÐ´ÑƒÐ¿Ñ€ÐµÐ¶Ð´ÐµÐ½Ð¸Ð¹ (!! "Предупреждение:" обрезаетÑÑ, по крайней мере в utf-8 !!)
+general_i_note=01015_I_Заметка:
+% ÐŸÑ€ÐµÑ„Ð¸ÐºÑ Ð´Ð»Ñ Ð·Ð°Ð¼ÐµÑ‚Ð¾Ðº
+general_i_hint=01016_I_ПодÑказка:
+% ÐŸÑ€ÐµÑ„Ð¸ÐºÑ Ð´Ð»Ñ Ð¿Ð¾Ð´Ñказок
+general_e_path_does_not_exist=01017_E_Путь "$1" не ÑущеÑтвует
+% Указанный путь не ÑущеÑтвует.
+general_f_compilation_aborted=01018_F_КомпилÑÑ†Ð¸Ñ Ð¿Ñ€ÐµÑ€Ð²Ð°Ð½Ð°
+% КомпилÑÑ†Ð¸Ñ Ð±Ñ‹Ð»Ð° прервана.
+general_text_bytes_code=01019_байт кода
+% Размер Ñгенерированного кода, в байтах.
+general_text_bytes_data=01020_байт данных
+% Размер Ñгенерированных данных программы, в байтах
+general_i_number_of_warnings=01021_I_$1 предупреждений
+% Общее чиÑло предупреждений, выданных в процеÑÑе компилÑции.
+general_i_number_of_hints=01022_I_$1 подÑказок
+% Общее чиÑло подÑказок, выданных в процеÑÑе компилÑции.
+general_i_number_of_notes=01023_I_$1 заметок
+% Общее чиÑло заметок, выданных в процеÑÑе компилÑции.
+% \end{description}
+#
+# Scanner
+#
+# 02086 is the last used one
+#
+% \section {Ð¡Ð¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ñканера.}
+% Этот раздел перечиÑлÑет ÑообщениÑ, котоpые выдает Ñканер. Сканер оÑущеÑтвлÑет
+% лекÑичеÑкий анализ Ñтруктуры иÑходного файла, Ñ‚.е. находит
+% зарезервированные Ñлова, Ñтроки, и Ñ‚.д. Сканер также обрабатывает директивы и
+% Ð²Ñ‹Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ ÑƒÑловной компилÑции.
+% \begin{description}
+scan_f_end_of_file=02000_F_Hеожиданный конец файла
+% Это обычно проиÑходит в Ñледующих ÑлучаÑÑ…:
+% \begin{itemize}
+% \item ИÑходный файл заканчиваетÑÑ Ð´Ð¾ поÑледнего Ð²Ñ‹Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ \var{end}.
+% Чаще вÑего проиÑходит, еÑли Ð²Ñ‹Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ \var{begin} и \var{end} не
+% ÑбаланÑированы (их количеÑтво не Ñовпадает);
+% \item Включаемый файл заканчиваетÑÑ Ð² Ñередине выpажениÑ.
+% \item Ðе был закрыт комментарий.
+% \end{itemize}
+scan_f_string_exceeds_line=02001_F_Ðе закрыта ÑÑ‚Ñ€Ð¾ÐºÐ¾Ð²Ð°Ñ ÐºÐ¾Ð½Ñтанта
+% ОтÑутÑтвует закрывающий Ñимвол ' Ñтрокового конÑтанты, так что конÑтанта занимает
+% неÑколько Ñтрок файла.
+scan_f_illegal_char=02002_F_Запpещенный Ñимвол "$1" ($2)
+% Ð’ иÑходном файле обнаружен запрещенный Ñимвол.
+scan_f_syn_expected=02003_F_СинтакÑичеÑÐºÐ°Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ°, ожидаетÑÑ "$1", но обнаружено "$2"
+% КомпилÑтор ожидал не тот токен, который ему вÑтретилÑÑ. Это может
+% проиÑходить везде, где только возможно нарушить правила
+% Ñзыка ПаÑкаль.
+scan_t_start_include_file=02004_TL_Hачало Ñ‡Ñ‚ÐµÐ½Ð¸Ñ Ð²ÐºÐ»ÑŽÑ‡Ð°ÐµÐ¼Ð¾Ð³Ð¾ файла $1
+% При иÑпользовании ключа \var{-vt} компилÑтор Ñообщает,
+% когда он начинает читать включаемый файл.
+scan_w_comment_level=02005_W_Hайден комментарий $1 ypовнÑ
+% При иÑпользовании ключа \var{-vw} компилÑтор предупреждает о том,
+% что он обнаружил вложенный комментарий. Вложенные комментарии не разрешены в
+% Turbo Pascal и могут быть возможным иÑточником ошибок.
+scan_n_ignored_switch=02008_N_Директива компилÑтора $1 игнорирована
+% При иÑпользовании ключа \var{-vn} компилÑтор предупреждает о том, что он игнорирует директиву.
+scan_w_illegal_switch=02009_W_HеизвеÑÑ‚Ð½Ð°Ñ Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¸Ð²Ð° компилÑтоpа $1
+% Была иÑпользована директива компилÑтора (то еÑÑ‚ÑŒ \var{\{\$... \}}), котораÑ
+% компилÑтору не извеÑтна.
+scan_w_switch_is_global=02010_W_Ð“Ð»Ð¾Ð±Ð°Ð»ÑŒÐ½Ð°Ñ Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¸Ð²Ð° не на Ñвоем меÑте
+% Глобальные директивы должны находитьÑÑ Ð² начале программы или модулÑ.
+scan_e_illegal_char_const=02011_E_Hеверно задан Ñимвол
+% Это ÑлучаетÑÑ Ð¿Ñ€Ð¸ определении Ñимвола Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ ASCII-кода, например,
+% \var{\#96}, но чиÑло либо ÑвлÑетÑÑ Ð½ÐµÐ²ÐµÑ€Ð½Ñ‹Ð¼, либо вне допуÑтимого диапазона.
+scan_f_cannot_open_input=02012_F_Hевозможно откpыть файл "$1"
+% \fpc не может найти иÑходный файл программы или модулÑ, указанный
+% в командной Ñтроке.
+scan_f_cannot_open_includefile=02013_F_Hевозможно откpыть включаемый файл "$1"
+% \fpc не может найти иÑходный файл, указанный в директиве \var{\{\$include \}}.
+scan_e_illegal_pack_records=02015_E_Ðеверное указание Ð²Ñ‹Ñ€Ð°Ð²Ð½Ð¸Ð²Ð°Ð½Ð¸Ñ Ð·Ð°Ð¿Ð¸Ñи "$1"
+% Ð’ директиве \var{\{\$PACKRECORDS n\} } или \var{\{\$ALIGN n\} } иÑпользуетÑÑ Ð½ÐµÐ²ÐµÑ€Ð½Ð¾Ðµ значение
+% \var{n}. Ð”Ð»Ñ \$PACKRECORDS допуÑтимы только 1, 2, 4, 8, 16, 32, C,
+% NORMAL, DEFAULT, а Ð´Ð»Ñ \$ALIGN допуÑтимы Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ 1, 2, 4, 8, 16, 32, ON,
+% OFF. В режиме MacPas \$ALIGN также поддерживает MAC68K, POWER и RESET.
+scan_e_illegal_pack_enum=02016_E_Ðеверное указание минимального размера перечиÑÐ»ÐµÐ½Ð¸Ñ "$1"
+% Ð’ директиве \var{\{\$PACKENUM n \}} иÑпользуетÑÑ Ð½ÐµÐ²ÐµÑ€Ð½Ð¾Ðµ значение
+% \var {n}. ДопуÑтимыми ÑвлÑÑŽÑ‚ÑÑ Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ 1,2,4, NORMAL и DEFAULT.
+scan_e_endif_expected=02017_E_ОжидаетÑÑ $ENDIF Ð´Ð»Ñ $1 $2, определенного в $3 Ñтрока $4
+% Директивы уÑловной компилÑции не ÑбаланÑированы.
+scan_e_preproc_syntax_error=02018_E_СинтакÑичеÑÐºÐ°Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ° в выражении уÑловной компилÑции
+% Ð’ выражении, Ñледующем поÑле директивы \var{\{\$if \}}, $ifc или $setc, допущена ошибка.
+scan_e_error_in_preproc_expr=02019_E_Ошибка при вычиÑлении Ð²Ñ‹Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ ÑƒÑловной компилÑции
+% Ð’ выражении, Ñледующем поÑле директивы \var{\{\$if \}}, $ifc или $setc, допущена ошибка.
+scan_w_macro_cut_after_255_chars=02020_W_Длина макpоÑа ограничена 255 Ñимволами
+% Длина макрокоманды не может превышать 255 Ñимволов.
+scan_e_endif_without_if=02021_E_ENDIF без IF(N)DEF
+% Директивы \var{\{\$IFDEF.. \}} и {\ {\$ENDIF \}} не ÑбаланÑированы.
+scan_f_user_defined=02022_F_Задано пользователем: $1
+% Пpоизошла Ñ„Ð°Ñ‚Ð°Ð»ÑŒÐ½Ð°Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ°, Ð·Ð°Ð´Ð°Ð½Ð½Ð°Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»ÐµÐ¼. См. также \progref
+scan_e_user_defined=02023_E_Задано пользователем: $1
+% Пpоизошла ошибка, Ð·Ð°Ð´Ð°Ð½Ð½Ð°Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»ÐµÐ¼. См. также \progref
+scan_w_user_defined=02024_W_Задано пользователем: $1
+% Пpедупреждение, заданное пользователем. См. также \progref
+scan_n_user_defined=02025_N_Задано пользователем: $1
+% Заметка, Ð·Ð°Ð´Ð°Ð½Ð½Ð°Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»ÐµÐ¼. См. также \progref
+scan_h_user_defined=02026_H_Задано пользователем: $1
+% ПодÑказка, Ð·Ð°Ð´Ð°Ð½Ð½Ð°Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»ÐµÐ¼. См. также \progref
+scan_i_user_defined=02027_I_Задано пользователем: $1
+% ИнформациÑ, Ð·Ð°Ð´Ð°Ð½Ð½Ð°Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»ÐµÐ¼. См. также \progref
+scan_e_keyword_cant_be_a_macro=02028_E_Ключевое Ñлово, переопределенное как макроÑ, не имеет Ñффекта
+% Ключевые Ñлова не могут быть переопределены Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ макрокоманд.
+scan_f_macro_buffer_overflow=02029_F_Переполнение бyфеpа макpоÑов при чтении или раÑширении макрокоманды
+% Длина макpокоманды или ее результата Ñлишком велика.
+scan_w_macro_too_deep=02030_W_ЧиÑло уровней раÑшиpÐµÐ½Ð¸Ñ Ð¼Ð°ÐºÑ€Ð¾ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ‹ превышает 16.
+% При раÑширении макрокоманды было иÑпользовано более 16 ypовней вложенноÑти.
+% КомпилÑтор не будет pаÑшиpÑÑ‚ÑŒ дальше, так как Ñто может быть признаком иÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ñ€ÐµÐºÑƒÑ€Ñии.
+scan_w_wrong_styled_switch=02031_W_Директивы компилÑтоpа в комментариÑÑ… ÑÑ‚Ð¸Ð»Ñ // не поддерживаютÑÑ.
+% Директивы компилÑтора должны быть в комментариÑÑ… ÑÑ‚Ð¸Ð»Ñ ÐŸÐ°Ñкаль.
+scan_d_handling_switch=02032_DL_Обработка директивы "$1"
+% При включении отладочной информации (\var{-vd}), компилÑтор Ñообщает
+% о том, что он вычиÑлÑет выражение уÑловной компилÑции.
+scan_c_endif_found=02033_CL_ENDIF $1 найдено
+% При включении Ñообщений об уÑловных выражениÑÑ… (\var{-vc}), компилÑтор Ñообщает
+% о том, где он обрабатывает Ð²Ñ‹Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ ÑƒÑловной компилÑции.
+scan_c_ifdef_found=02034_CL_IFDEF $1 найдено, $2
+% При включении Ñообщений об уÑловных выражениÑÑ… (\var{-vc}), компилÑтор Ñообщает
+% о том, где он обрабатывает Ð²Ñ‹Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ ÑƒÑловной компилÑции.
+scan_c_ifopt_found=02035_CL_IFOPT $1 найдено, $2
+% При включении Ñообщений об уÑловных выражениÑÑ… (\var{-vc}), компилÑтор Ñообщает
+% о том, где он обрабатывает Ð²Ñ‹Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ ÑƒÑловной компилÑции.
+scan_c_if_found=02036_CL_IF $1 найдено, $2
+% При включении Ñообщений об уÑловных выражениÑÑ… (\var{-vc}), компилÑтор Ñообщает
+% о том, где он обрабатывает Ð²Ñ‹Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ ÑƒÑловной компилÑции.
+scan_c_ifndef_found=02037_CL_IFNDEF $1 найдено, $2
+% При включении Ñообщений об уÑловных выражениÑÑ… (\var{-vc}), компилÑтор Ñообщает
+% о том, где он обрабатывает Ð²Ñ‹Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ ÑƒÑловной компилÑции.
+scan_c_else_found=02038_CL_ELSE $1 найдено, $2
+% При включении Ñообщений об уÑловных выражениÑÑ… (\var{-vc}), компилÑтор Ñообщает
+% о том, где он обрабатывает Ð²Ñ‹Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ ÑƒÑловной компилÑции.
+scan_c_skipping_until=02039_CL_ПpопyÑкаем до ...
+% При включении Ñообщений об уÑловных выражениÑÑ… (\var{-vc}), компилÑтор Ñообщает
+% о том, что он пропуÑкает чаÑÑ‚ÑŒ уÑловного выражениÑ, не удовлетворÑющую уÑловию.
+scan_i_press_enter=02040_I_Hажмите <ENTER> Ð´Ð»Ñ Ð¿Ñ€Ð¾Ð´Ð¾Ð»Ð¶ÐµÐ½Ð¸Ñ
+% При иÑпользовании ключа \var{-vi} компилÑтор оÑтанавливаетÑÑ
+% и ждет Ð½Ð°Ð¶Ð°Ñ‚Ð¸Ñ Ð½Ð° клавишу \var{enter}, еÑли в иÑходном файле
+% вÑтречаетÑÑ Ð´Ð¸pектива \var {\{\$STOP\}}.
+scan_w_unsupported_switch=02041_W_Директива "$1" не поддерживаетÑÑ
+% При включенных предупреждениÑÑ… (\var{-vw}), компилÑтор предупреждает
+% о неподдерживаемых директивах. Это означает, что директива иÑпользуетÑÑ
+% в Delphi или Turbo Pascal, но не в \fpc
+scan_w_illegal_directive=02042_W_HÐµÐ²ÐµÑ€Ð½Ð°Ñ Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¸Ð²Ð° компилÑтора "$1"
+% При включенных пpедyпpеждениÑÑ… (\var{-vw}), компилÑтор предупреждает
+% о неверных диpективах. СпиÑок раÑпознаваемых диpектив Ñм. в \progref
+scan_t_back_in=02043_TL_Возвpат в $1
+% При иÑпользовании ключа (\var{-vt}) компилÑтор Ñообщает об окончании
+% Ñ‡Ñ‚ÐµÐ½Ð¸Ñ Ð²ÐºÐ»ÑŽÑ‡Ð°ÐµÐ¼Ð¾Ð³Ð¾ файла.
+scan_w_unsupported_app_type=02044_W_Тип пpÐ¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ "$1" не поддерживаетÑÑ
+% Это предупреждение выдаетÑÑ Ð¿Ñ€Ð¸ иÑпользовании неизвеÑтного типа
+% Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð² директиве \var{\{\$APPTYPE\}}
+scan_w_app_type_not_support=02045_W_APPTYPE не поддерживаетÑÑ Ñ†ÐµÐ»ÐµÐ²Ð¾Ð¹ ОС
+% Директива \var{\{\$APPTYPE\}} поддерживаетÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ некоторыми операционными ÑиÑтемами.
+scan_w_description_not_support=02046_W_DESCRIPTION не поддерживаетÑÑ Ñ†ÐµÐ»ÐµÐ²Ð¾Ð¹ ОС
+% Директива \var{\{\$DESCRIPTION\}} не поддерживаетÑÑ Ð½Ð° данной целевой ОС.
+scan_n_version_not_support=02047_N_VERSION не поддерживаетÑÑ Ñ†ÐµÐ»ÐµÐ²Ð¾Ð¹ ОС
+% Директива \var{\{\$VERSION\}} не поддерживаетÑÑ Ð½Ð° данной целевой ОС.
+scan_n_only_exe_version=02048_N_VERSION иÑпользуетÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ Ð´Ð»Ñ .EXE и .DLL иÑходников
+% Директива \var{\{\$VERSION\}} иÑпользуетÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ Ð´Ð»Ñ .EXE и .DLL иÑходников.
+scan_w_wrong_version_ignored=02049_W_Ðеверный формат VERSION Ð´Ð»Ñ Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¸Ð²Ñ‹ "$1"
+% Формат директивы \var{\{\$VERSION\}} - major_version.minor_version
+% где major_version и minor_version ÑвлÑÑŽÑ‚ÑÑ Ñловами.
+scan_e_illegal_asmmode_specifier=02050_E_Hеверный Ñтиль аÑÑемблеpа: "$1"
+% При определении режима аÑÑемблера директивой \var{\{\$ASMMODE xxx\}}
+% указан неверный режим.
+scan_w_no_asm_reader_switch_inside_asm=02051_W_Смена типа аÑÑемблеpа невозможна внутри блока, "$1" бyдет дейÑтвовать только Ð´Ð»Ñ Ñледyющего блока
+% Внутри аÑÑемблерного блока невозможно переключение аÑÑемблера Ñ Ð¾Ð´Ð½Ð¾Ð³Ð¾ типа на другой.
+% Указанный режим начнет дейÑтвовать только Ð´Ð»Ñ Ñледующего аÑÑемблерного блока.
+scan_e_wrong_switch_toggle=02052_E_Hевеpное переключение режима, иÑпользуйте ON/OFF или +/-
+% Ð”Ð»Ñ Ð¿ÐµÑ€ÐµÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ñ€ÐµÐ¶Ð¸Ð¼Ð¾Ð² Ñледует иÑпользовать ON или OFF, либо + или -
+scan_e_resourcefiles_not_supported=02053_E_Файлы pеÑypÑов не поддерживаютÑÑ Ñ†ÐµÐ»ÐµÐ²Ð¾Ð¹ ОС
+% ÐžÐ¿ÐµÑ€Ð°Ñ†Ð¸Ð¾Ð½Ð½Ð°Ñ ÑиÑтема, Ð´Ð»Ñ ÐºÐ¾Ñ‚Ð¾Ñ€Ð¾Ð¹ проиÑходит компилÑциÑ, не поддерживает файлы реÑурÑов.
+scan_w_include_env_not_found=02054_W_Ð’ÐºÐ»ÑŽÑ‡Ð°ÐµÐ¼Ð°Ñ Ð¿ÐµpÐµÐ¼ÐµÐ½Ð½Ð°Ñ Ð¾ÐºpyÐ¶ÐµÐ½Ð¸Ñ "$1" не найдена
+% Ð£ÐºÐ°Ð·Ð°Ð½Ð½Ð°Ñ Ð¿ÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ð°Ñ Ð¾ÐºÑ€ÑƒÐ¶ÐµÐ½Ð¸Ñ Ð½Ðµ найдена, вмеÑто нее будет подÑтавлена пуÑÑ‚Ð°Ñ Ñтрока.
+scan_e_invalid_maxfpureg_value=02055_E_Ðеверное значение Ð´Ð»Ñ Ð¼Ð°ÐºÑимального чиÑла региÑтров ÑопроцеÑÑора
+% ДопуÑтимыми значениÑми Ð´Ð»Ñ Ñтой директивы ÑвлÑÑŽÑ‚ÑÑ 0..8 и NORMAL/DEFAULT
+scan_w_only_one_resourcefile_supported=02056_W_Ð”Ð»Ñ Ñтой ÑиÑтемы поддерживаетÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ один файл реÑурÑов
+% Ð”Ð»Ñ Ð¾Ð¿ÐµÑ€Ð°Ñ†Ð¸Ð¾Ð½Ð½Ð¾Ð¹ ÑиÑтемы Ð½Ð°Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð´Ð´ÐµÑ€Ð¶Ð¸Ð²Ð°ÐµÑ‚ÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ один файл реÑурÑов.
+% Будет иÑпользован первый найденный файл, оÑтальные будут игнорированы.
+scan_w_macro_support_turned_off=02057_W_Поддеpжка макpоÑов отключена
+% Обнаружено объÑвление макроÑа, но режим поддержки макроÑов отключен,
+% поÑтому объÑвление будет игнорировано. Ð”Ð»Ñ Ð²ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð´Ð´ÐµÑ€Ð¶ÐºÐ¸ макроÑов иÑпользуйте
+% -Sm в командной Ñтроке или добавьте {$MACRO ON} в иÑходный файл.
+scan_e_invalid_interface_type=02058_E_Ðеверный тип interface. ДопуÑтимы только COM, COBRA или DEFAULT
+% Указанный тип интерфейÑа не поддерживаетÑÑ.
+scan_w_appid_not_support=02059_W_APPID поддерживаетÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ Ð´Ð»Ñ PalmOS
+% Директива \var{\{\$APPID\}} поддерживаетÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ при компилÑции Ð´Ð»Ñ PalmOS.
+scan_w_appname_not_support=02060_W_APPNAME поддерживаетÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ Ð´Ð»Ñ PalmOS
+% Директива \var{\{\$APPNAME\}} поддерживаетÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ при компилÑции Ð´Ð»Ñ PalmOS.
+scan_e_string_exceeds_255_chars=02061_E_Ð¡Ñ‚Ñ€Ð¾ÐºÐ¾Ð²Ð°Ñ ÐºÐ¾Ð½Ñтанта не может быть длиннее 255 Ñимволов
+% Одна ÑÑ‚Ñ€Ð¾ÐºÐ¾Ð²Ð°Ñ ÐºÐ¾Ð½Ñтанта может Ñодержать 255 Ñимволов макÑимум. Более длинную
+% Ñтроку Ñледует разбить на чаÑти и Ñоединить их оператором +.
+scan_f_include_deep_ten=02062_F_Уровень Ð²Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð²ÐºÐ»ÑŽÑ‡Ð°ÐµÐ¼Ñ‹Ñ… файлов превоÑходит 16.
+% При чтении включаемых файлов доÑтигнут уровень вложенноÑти 16.
+% КомпилÑтор прекращает работу, Ñ‚.к. Ñто может ÑвлÑÑ‚ÑŒÑÑ Ð¿Ñ€Ð¸Ð·Ð½Ð°ÐºÐ¾Ð¼ рекурÑии.
+scan_e_too_many_push=02063_F_Слишком много уровней PUSH
+% ДопуÑтимый макÑимум ÑоÑтавлÑет 20. Эта ошибка возникает только в режиме MacPas.
+scan_e_too_many_pop=02064_E_Директива POP без предшеÑтвующей PUSH
+% Эта ошибка возникает только в режиме MacPas.
+scan_e_error_macro_lacks_value=02065_E_ÐœÐ°ÐºÑ€Ð¾Ñ Ð¸Ð»Ð¸ Ð¿ÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ð°Ñ Ð²Ñ€ÐµÐ¼ÐµÐ½Ð¸ компилÑции "$1" не имеет приÑвоенного значениÑ
+% Из-за Ñтого выражение времени компилÑции не может быть вычиÑлено.
+scan_e_wrong_switch_toggle_default=02066_E_Ðеверное переключение режима, иÑпользуйте ON/OFF/DEFAULT или +/-/*
+% Следует переключать режим, иÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ ON или OFF или DEFAULT, либо + или - или *
+scan_e_mode_switch_not_allowed=02067_E_Директива режима "$1" здеÑÑŒ не допуÑтима
+% Директива режима компилÑции уже была обработана, или, в Ñлучае режима -Mmacpas,
+% переключение режима проиÑходит поÑле UNIT.
+scan_e_error_macro_undefined=02068_E_ÐŸÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ð°Ñ Ð²Ñ€ÐµÐ¼ÐµÐ½Ð¸ компилÑции или Ð¼Ð°ÐºÑ€Ð¾Ñ "$1" не определен.
+% Из-за Ñтого выражение времени компилÑции не может быть вычиÑлено. Только Ð´Ð»Ñ Ñ€ÐµÐ¶Ð¸Ð¼Ð° MacPas.
+scan_e_utf8_bigger_than_65535=02069_E_Обнаружен код UTF-8, превышающий 65535
+% \fpc обрабатывает Ñтроки utf-8 как widestring, Ñ‚.е. коды Ñимволов ограничены 65535
+scan_e_utf8_malformed=02070_E_ÐÐµÐ²ÐµÑ€Ð½Ð°Ñ UTF-8 Ñтрока
+% Ð”Ð°Ð½Ð½Ð°Ñ Ñтрока не ÑвлÑетÑÑ Ð´Ð¾Ð¿ÑƒÑтимой в кодировке UTF-8
+scan_c_switching_to_utf8=02071_C_Ðайдена Ñигнатура UTF-8, иÑпользую кодировку UTF-8
+% КомпилÑтор обнаружил Ñигнатуру UTF-8 (\$ef, \$bb, \$bf) в начале файла,
+% поÑтому он будет обрабатывать файл как UTF-8
+scan_e_compile_time_typeerror=02072_E_Выражение времени компилÑции: ОжидалоÑÑŒ $1, но получено $2 в $3
+% Ошибка типов в выражении времени компилÑции.
+scan_n_app_type_not_support=02073_N_APPTYPE не поддерживаетÑÑ Ñ†ÐµÐ»ÐµÐ²Ð¾Ð¹ ОС
+% Директива \var{\{\$APPTYPE\}} поддерживаетÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ Ð´Ð»Ñ Ð½ÐµÐºÐ¾Ñ‚Ð¾Ñ€Ñ‹Ñ… операционных ÑиÑтем.
+scan_e_illegal_optimization_specifier=02074_E_Ðеверный тип оптимизации "$1"
+% В директиве \var{\{\$OPTIMIZATION xxx\}} указано неверное значение.
+scan_w_setpeflags_not_support=02075_W_SETPEFLAGS не поддерживаетÑÑ Ñ†ÐµÐ»ÐµÐ²Ð¾Ð¹ ОС
+% Директива \var{\{\$SETPEFLAGS\}} не поддерживаетÑÑ Ð¾Ð¿ÐµÑ€Ð°Ñ†Ð¸Ð¾Ð½Ð½Ð¾Ð¹ ÑиÑтемой назначениÑ.
+scan_w_imagebase_not_support=02076_W_IMAGEBASE не поддерживаетÑÑ ÐžÐ¡ назаначениÑ
+% Директива \var{\{\$IMAGEBASE\}} не поддерживаетÑÑ Ð¾Ð¿ÐµÑ€Ð°Ñ†Ð¸Ð¾Ð½Ð½Ð¾Ð¹ ÑиÑтемой назначениÑ.
+scan_w_minstacksize_not_support=02077_W_MINSTACKSIZE не поддерживаетÑÑ ÐžÐ¡ назаначениÑ
+% Директива \var{\{\$MINSTACKSIZE\}} не поддерживаетÑÑ Ð¾Ð¿ÐµÑ€Ð°Ñ†Ð¸Ð¾Ð½Ð½Ð¾Ð¹ ÑиÑтемой назначениÑ.
+scan_w_maxstacksize_not_support=02078_W_MAXSTACKSIZE не поддерживаетÑÑ ÐžÐ¡ назаначениÑ
+% Директива \var{\{\$MAXSTACKSIZE\}} не поддерживаетÑÑ Ð¾Ð¿ÐµÑ€Ð°Ñ†Ð¸Ð¾Ð½Ð½Ð¾Ð¹ ÑиÑтемой назначениÑ.
+scanner_e_illegal_warn_state=02079_E_Ðеверный режим директивы $WARN
+% Директива \$warn допуÑкает только ON и OFF Ð´Ð»Ñ ÑƒÐºÐ°Ð·Ð°Ð½Ð¸Ñ Ñ€ÐµÐ¶Ð¸Ð¼Ð°
+scan_e_only_packset=02080_E_Ðеверное значение упаковки множеÑтв
+% ДопуÑтимыми значениÑми ÑвлÑÑŽÑ‚ÑÑ 0, 1, 2, 4, 8, DEFAULT и NORMAL
+scan_w_pic_ignored=02081_W_Директива или ключ PIC игнорированы
+% Ðекоторые платформы, например, Windows, не поддерживают и не требуют позиционно-незавиÑимый код (PIC),
+% поÑтому ÑоответÑтвующие диркективы и ключи командной Ñтроки Ð´Ð»Ñ Ð½Ð¸Ñ… игнорируютÑÑ.
+scan_w_unsupported_switch_by_target=02082_W_Директива "$1" не поддерживаетÑÑ Ð´Ð»Ñ Ñ‚ÐµÐºÑƒÑ‰ÐµÐ¹ платформы назначениÑ
+% Ðекоторые директивы, например, \$E, поддерживаютÑÑ Ð½Ðµ Ð´Ð»Ñ Ð²Ñех платформ.
+scan_w_frameworks_darwin_only=02084_W_Директивы Ð´Ð»Ñ Framework поддерживаютÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ Ð´Ð»Ñ Darwin/Mac OS X
+% ÐšÐ¾Ð½Ñ†ÐµÐ¿Ñ†Ð¸Ñ Ñ„Ñ€ÐµÐ¹Ð¼Ð²Ð¾Ñ€ÐºÐ¾Ð² не поддерживаетÑÑ FPC Ð´Ð»Ñ Ð¾Ð¿ÐµÑ€Ð°Ñ†Ð¸Ð¾Ð½Ð½Ñ‹Ñ… ÑиÑтем, отличных от Darwin/Mac OS X.
+scan_e_illegal_minfpconstprec=02085_E_Ðеверное указание минимальной точноÑти конÑтант Ñ Ð¿Ð»Ð°Ð²Ð°ÑŽÑ‰ÐµÐ¹ запÑтой "$1"
+% ДопуÑтимыми значениÑми ÑвлÑÑŽÑ‚ÑÑ default, 32 и 64, которые означают ÑоответÑтвенно минимальную (обычно 32 бита), 32 бит и 64 бит точноÑÑ‚ÑŒ.
+scan_w_multiple_main_name_overrides=02086_W_Многократное указание имени процедуры "main", первоначально было "$1"
+% Ð˜Ð¼Ñ Ð¾Ñновной точки входа указано более одного раза. Будет иÑпользовано только поÑледнее имÑ.
+% \end{description}
+#
+# Parser
+#
+# 03252 is the last used one
+#
+% \section {ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ ÑинтакÑичеÑкого анализатора}
+% Этот раздел перечиÑлÑет вÑе ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ ÑинтакÑичеÑкого анализатора.
+% СинтакÑичеÑкий анализатор оÑущеÑтвлÑет ÑемантичеÑкий анализ, Ñ‚.е.
+% определÑет правильноÑÑ‚ÑŒ выражений ПаÑкалÑ.
+% \begin{description}
+parser_e_syntax_error=03000_E_СинтакÑичеÑÐºÐ°Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ° в анализаторе
+% Обнаружена ошибка ÑинтакÑиÑа Ñзыка. Обычно проиÑходит, когда в иÑходном файле
+% вÑтречаетÑÑ Ð½ÐµÐ´Ð¾Ð¿ÑƒÑтимый Ñимвол.
+parser_e_dont_nest_interrupt=03004_E_INTERRUPT процедура не может быть вложенной
+% Процедура типа \VAR{INTERRUPT} должна быть глобальной.
+parser_w_proc_directive_ignored=03005_W_Директива процедуры "$1" игнорирована
+% Указанный модификтор типа процедуры игнорирован компилÑтором.
+parser_e_no_overload_for_all_procs=03006_E_Ðе вÑе объÑÐ²Ð»ÐµÐ½Ð¸Ñ "$1" перегружены (определены как OVERLOAD)
+% При перегрузке процедур Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ директивы \var{OVERLOAD}, ее Ñледует
+% указывать Ð´Ð»Ñ Ð²Ñех объÑвлений перегруженной процедуры.
+parser_e_export_name_double=03008_E_Ð˜Ð¼Ñ Ñ„yнкции "$1" ÑкÑпортируетÑÑ Ð´Ð²Ð°Ð¶Ð´Ñ‹
+% Ð’Ñе функции, ÑкÑпортируемые из одной DLL, должны иметь различные имена.
+parser_e_export_ordinal_double=03009_E_Ð˜Ð½Ð´ÐµÐºÑ Ñ„ÑƒÐ½ÐºÑ†Ð¸Ð¸ $1 ÑкÑпортируетÑÑ Ð´Ð²Ð°Ð¶Ð´Ñ‹
+% Ð’Ñе функции, ÑкÑпортируемые из одной DLL, должны иметь различные индекÑÑ‹.
+parser_e_export_invalid_index=03010_E_Hевеpный Ð¸Ð½Ð´ÐµÐºÑ ÑкÑпоpтиpyемой Ñ„yнкции
+% Ð˜Ð½Ð´ÐµÐºÑ ÑкÑпортируемой функции должен быть в диапазоне \var{1..\$FFFF}
+parser_w_parser_reloc_no_debug=03011_W_ÐžÑ‚Ð»Ð°Ð´Ð¾Ñ‡Ð½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð² перемещаемом DLL/EXE файле $1 не работоÑпоÑобна, отключена.
+% Ð’ наÑтоÑщее Ð²Ñ€ÐµÐ¼Ñ Ð²ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ðµ отладочной информации в перемещаемую DLL невозможно.
+parser_w_parser_win32_debug_needs_WN=03012_W_Ð”Ð»Ñ Ð¾Ñ‚Ð»Ð°Ð´ÐºÐ¸ win32-кода, Ñледует отключить перемещение ключом -WN
+% ÐžÑ‚Ð»Ð°Ð´Ð¾Ñ‡Ð½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Stabs не работает в перемещаемых DLL или EXE файлах, иÑпользуйте -WN
+% еÑли требуетÑÑ Ð¾Ñ‚Ð»Ð°Ð´ÐºÐ°.
+parser_e_constructorname_must_be_init=03013_E_КонÑÑ‚pyктоp должен иметь Ð¸Ð¼Ñ INIT
+% КонÑтруктор объÑвлен Ñ Ð¸Ð¼ÐµÐ½ÐµÐ¼, отличным от \var{init}, и дейÑтвует ключ
+% \var{-Ss}. См. опиÑание дейÑÑ‚Ð²Ð¸Ñ ÐºÐ»ÑŽÑ‡Ð° \var{-Ss} (\seeo{Ss}).
+parser_e_destructorname_must_be_done=03014_E_ДеÑÑ‚pyктоp должен иметь Ð¸Ð¼Ñ DONE
+% ДеÑтруктор объÑвлен Ñ Ð¸Ð¼ÐµÐ½ÐµÐ¼, отличным от \var{done}, и дейÑтвует ключ
+% \var{-Ss}. См. опиÑание дейÑÑ‚Ð²Ð¸Ñ ÐºÐ»ÑŽÑ‡Ð° \var{-Ss} (\seeo{Ss}).
+parser_e_proc_inline_not_supported=03016_E_Директива INLINE не поддеpживаетÑÑ
+% При компилÑции программы Ñ inlining в Ñтиле C++ не был иÑпользован ключ
+% \var{-Si} (\seeo{Si}). По умолчанию компилÑтор не поддерживает inlining в Ñтиле C++.
+parser_w_constructor_should_be_public=03018_W_КонÑÑ‚pyктоp должен быть public
+% КонÑтрукторы должны быть в 'public' Ñекции объÑÐ²Ð»ÐµÐ½Ð¸Ñ Ð¾Ð±ÑŠÐµÐºÑ‚Ð° (клаÑÑа).
+parser_w_destructor_should_be_public=03019_W_ДеÑÑ‚pyктоp должен быть public
+% ДеÑтрукторы должны быть в 'public' Ñекции объÑÐ²Ð»ÐµÐ½Ð¸Ñ Ð¾Ð±ÑŠÐµÐºÑ‚Ð° (клаÑÑа).
+parser_n_only_one_destructor=03020_N_КлаÑÑ Ð¼Ð¾Ð¶ÐµÑ‚ иметь только один деÑÑ‚pyктоp
+% Ð”Ð»Ñ ÐºÐ»Ð°ÑÑа можно определить только один деÑтруктор.
+parser_e_no_local_objects=03021_E_Локальные объÑÐ²Ð»ÐµÐ½Ð¸Ñ ÐºÐ»Ð°ÑÑов не поддеpживаютÑÑ
+% КлаÑÑÑ‹ должны быть объÑвлены глобально. Они не могут быть объÑвлены внутри
+% процедуры или функции.
+parser_f_no_anonym_objects=03022_F_Ðнонимные объÑÐ²Ð»ÐµÐ½Ð¸Ñ ÐºÐ»Ð°ÑÑов не поддеpживаетÑÑ
+% Ð’Ñтречено недопуÑтимое объÑвление объекта (клаÑÑа), Ñ‚.е. объект или клаÑÑ,
+% не имеющий методов и не унаÑледованный от другого объекта (клаÑÑа).
+% Ðапример, объÑвление:
+% \begin{verbatim}
+% Type o = object
+% a : longint;
+% end;
+% \end{verbatim}
+% вызовет Ñту ошибку.
+parser_n_object_has_no_vmt=03023_N_Объект "$1" не имеет таблицы VMT
+% Это заметка о том, что объÑвленный объект не имеет таблицы виртуальных методов (VMT).
+parser_e_illegal_parameter_list=03024_E_Hевеpный ÑпиÑок паpаметpов
+% Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ Ð²Ñ‹Ð·Ñ‹Ð²Ð°ÐµÑ‚ÑÑ Ñ Ð¿Ð°Ñ€Ð°Ð¼ÐµÑ‚Ñ€Ð°Ð¼Ð¸, тип которых отличаетÑÑ Ð¾Ñ‚ типов параметров, иÑпользованных
+% при объÑвлении функции.
+parser_e_wrong_parameter_size=03026_E_Ðеверное количеÑтво паpаметpов при вызове "$1"
+% Ошибка в ÑпиÑке параметров вызываемой процедуры или функции, количеÑтво параметров неверно.
+parser_e_overloaded_no_procedure=03027_E_Перегруженный идентификатоp "$1" не ÑвлÑетÑÑ Ñ„yнкцией
+% КомпилÑтор обнаружил Ñимвол Ñ Ñ‚ÐµÐ¼ же именем, что и Ð¿ÐµÑ€ÐµÐ³Ñ€ÑƒÐ¶ÐµÐ½Ð½Ð°Ñ Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ, но не ÑвлÑющийÑÑ Ñ„ÑƒÐ½ÐºÑ†Ð¸ÐµÐ¹.
+parser_e_overloaded_have_same_parameters=03028_E_Перегруженные Ñ„yнкции имеют одинаковый ÑпиÑок паpаметpов
+% Попытка объÑÐ²Ð»ÐµÐ½Ð¸Ñ Ð¿ÐµÑ€ÐµÐ³Ñ€ÑƒÐ¶ÐµÐ½Ð½Ñ‹Ñ… функций Ñ Ð¾Ð´Ð½Ð¸Ð¼ и тем же ÑпиÑком параметров.
+% Чтобы перегрузка была возможна, по крайней мере один из параметров должен отличатьÑÑ.
+parser_e_header_dont_match_forward=03029_E_Заголовок Ñ„yнкции не ÑоответÑтвyет пpедыдyщемy объÑвлению "$1"
+% ОбъÑвлена Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ Ñ Ñ‚ÐµÐ¼ же ÑпиÑком параметром, но отличающимÑÑ Ñ‚Ð¸Ð¿Ð¾Ð¼ результата либо модификатором.
+parser_e_header_different_var_names=03030_E_Заголовок Ñ„yнкции "$1" не ÑоответÑтвyет пpедыдyщемy опpеделению в forward : изменÑетÑÑ Ð¸Ð¼Ñ Ð¿ÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ð¾Ð¹ $2 => $3
+% Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ Ð¾Ð±ÑŠÑвлена в Ñекции \var{interface} либо Ñ Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¸Ð²Ð¾Ð¹
+% \var{forward}, а затем определена Ñ Ð¾Ñ‚Ð»Ð¸Ñ‡Ð°ÑŽÑ‰Ð¸Ð¼ÑÑ ÑпиÑком параметров.
+parser_n_duplicate_enum=03031_N_Ð—Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð² перечиÑлÑемых типах должны быть возраÑтающими
+% \fpc допуÑкает объÑвление перечиÑлений как в C. Из Ñледующих двух объÑвлений:
+% \begin{verbatim}
+% type a = (A_A,A_B,A_E:=6,A_UAS:=200);
+% type a = (A_A,A_B,A_E:=6,A_UAS:=4);
+% \end{verbatim}
+% Второе объÑвление вызовет Ñто Ñообщение. Значение \var{A\_UAS} должно быть больше,
+% чем значение \var{A\_E}, т.е. по крайней мере 7.
+parser_e_no_with_for_variable_in_other_segments=03033_E_With не может быть иÑпользован Ð´Ð»Ñ Ð¿Ðµpеменных из другого Ñегмента
+% With ÑохранÑет переменную локально на Ñтеке,
+% но Ñто невозможно, еÑли Ð¿ÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ð°Ñ Ð½Ð°Ñ…Ð¾Ð´Ð¸Ñ‚ÑÑ Ð² другом Ñегменте.
+parser_e_too_much_lexlevel=03034_E_Уровень Ð²Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ñ„yнкций превышает 31
+% КоличеÑтво уровней Ð²Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ñ„ÑƒÐ½ÐºÑ†Ð¸Ð¹ ограничено 31.
+parser_e_range_check_error=03035_E_Ошибка проверки диапазона пpи вычиÑлении конÑтант
+% Значение конÑтант находитÑÑ Ð²Ð½Ðµ допуÑтимого Ð´Ð»Ñ Ð½Ð¸Ñ… диапазона.
+parser_w_range_check_error=03036_W_Ошибка проверки диапазона пpи вычиÑлении конÑтант
+% Значение конÑтант находитÑÑ Ð²Ð½Ðµ допуÑтимого Ð´Ð»Ñ Ð½Ð¸Ñ… диапазона.
+parser_e_double_caselabel=03037_E_ПовтоpÑющаÑÑÑ Ð¼ÐµÑ‚ÐºÐ° CASE
+% Одна и та же метка указана 2 раза в одном выражении \var{case}.
+parser_e_case_lower_less_than_upper_bound=03038_E_ВеpхнÑÑ Ð³pаница диапазона case меньше, чем нижнÑÑ
+% ВерхнÑÑ Ð³Ñ€Ð°Ð½Ð¸Ñ†Ð° метки \var{case} меньше нижней границы, поÑтому метка не имеет ÑмыÑла.
+parser_e_type_const_not_possible=03039_E_Типизиpованные конÑтанты клаÑÑов и интерфейÑов не поддеpживаютÑÑ
+% ОбъÑÐ²Ð»ÐµÐ½Ð¸Ñ ÐºÐ¾Ð½Ñтант, имеющих тип клаÑÑа либо интерфейÑа, не допуÑкаетÑÑ.
+parser_e_no_overloaded_procvars=03040_E_Переменные перегруженных функций не поддеpживаютÑÑ
+% ÐедопуÑÑ‚Ð¸Ð¼Ð°Ñ Ð¿Ð¾Ð¿Ñ‹Ñ‚ÐºÐ° приÑÐ²Ð¾ÐµÐ½Ð¸Ñ Ð¿ÐµÑ€ÐµÐ³Ñ€ÑƒÐ¶ÐµÐ½Ð½Ð¾Ð¹ функции процедурной переменной.
+parser_e_invalid_string_size=03041_E_Длина ÑÑ‚pоки должна быть в диапазоне 1 .. 255
+% Длина Ñтроки типа shortstring ограничена 255 Ñимволами. Попытка объÑвить Ñтроку
+% Ñ Ð´Ð»Ð¸Ð½Ð¾Ð¹ менее 1 или более 255.
+parser_w_use_extended_syntax_for_objects=03042_W_ИÑпользуйте pаÑшиpенный ÑинтакÑÐ¸Ñ NEW и DISPOSE Ð´Ð»Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ ÑкземплÑров объектов
+% При наличии ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ»Ñ \var{a} на тип клаÑÑа, вызов
+% \var{new(a)} не проинициализирует клаÑÑ (Ñ‚.е. конÑтруктор не будет
+% вызван), Ñ…Ð¾Ñ‚Ñ Ð¿Ð°Ð¼ÑÑ‚ÑŒ будет выделена. Следует иÑпользовать вызов
+% \var{new(a,init)}, который выделит памÑÑ‚ÑŒ и вызовет конÑтруктор клаÑÑа.
+parser_w_no_new_dispose_on_void_pointers=03043_W_ИÑпользование NEW и DISPOSE Ð´Ð»Ñ Ð½ÐµÑ‚Ð¸Ð¿Ð¸Ð·Ð¸pованных yказателей беÑÑмыÑленно
+parser_e_no_new_dispose_on_void_pointers=03044_E_ИÑпользование NEW и DISPOSE Ð´Ð»Ñ Ð½ÐµÑ‚Ð¸Ð¿Ð¸Ð·Ð¸pованных yказателей невозможно
+% Вызовы \var{new(p)} или \var{dispose(p)} невозможны, еÑли \var{p} ÑвлÑетÑÑ Ð½ÐµÑ‚Ð¸Ð¿Ð¸Ð·Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð½Ñ‹Ð¼ указателем,
+% Ñ‚.к. при Ñтом отÑутÑтвует Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ размере выделÑемой памÑти.
+% ПринимаетÑÑ Ð´Ð»Ñ ÑовмеÑтимоÑти в режимах \var{tp} и \var{delphi}.
+parser_e_class_id_expected=03045_E_ОжидаетÑÑ Ð¸Ð´ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ‚Ð¾p клаÑÑа
+% ПроиÑходит при Ñканировании имени процедуры, Ñодержащего точку, Ñ‚.е. метода
+% клаÑÑа или объекта, но тип перед точкой неизвеÑтен.
+parser_e_no_type_not_allowed_here=03046_E_Идентификатоp типа здеÑÑŒ недопуÑтим
+% Идентификатор типа не может быть иÑпользован в выражении.
+parser_e_methode_id_expected=03047_E_ОжидаетÑÑ Ð¸Ð´ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ‚Ð¾p метода
+% Идентификатор не ÑвлÑетÑÑ Ð¼ÐµÑ‚Ð¾Ð´Ð¾Ð¼.
+% ПроиÑходит при Ñканировании имени процедуры, Ñодержащего точку, Ñ‚.е. метода
+% клаÑÑа или объекта, но Ð¸Ð¼Ñ Ð¿Ñ€Ð¾Ñ†ÐµÐ´ÑƒÑ€Ñ‹ отÑутÑтвует в объÑвлении клаÑÑа.
+parser_e_header_dont_match_any_member=03048_E_Заголовок Ñ„yнкции не ÑоответÑтвует ни одному из методов клаÑÑа "$1"
+% Идентификатор не ÑвлÑетÑÑ Ð¼ÐµÑ‚Ð¾Ð´Ð¾Ð¼.
+% ПроиÑходит при Ñканировании имени процедуры, Ñодержащего точку, Ñ‚.е. метода
+% клаÑÑа или объекта, но Ð¸Ð¼Ñ Ð¿Ñ€Ð¾Ñ†ÐµÐ´ÑƒÑ€Ñ‹ отÑутÑтвует в объÑвлении клаÑÑа.
+parser_d_procedure_start=03049_DL_Пpоцедypа/ФyÐ½ÐºÑ†Ð¸Ñ $1
+% При иÑпользовании ключа \var{-vd} компилÑтор Ñообщает о начале обработки
+% тела процедуры или функции.
+parser_e_error_in_real=03050_E_HевеpÐ½Ð°Ñ ÐºÐ¾Ð½Ñтанта Ñ Ð¿Ð»Ð°Ð²Ð°ÑŽÑ‰ÐµÐ¹ запÑтой
+% КомпилÑтор ожидает выражение вещеÑтвенного типа, но получает что-то другое.
+parser_e_fail_only_in_constructor=03051_E_FAIL допуÑтим только в конÑÑ‚pyктоpах
+% ИнÑÑ‚Ñ€ÑƒÐºÑ†Ð¸Ñ \var{FAIL} иÑпользована вне метода конÑтруктора.
+parser_e_no_paras_for_destructor=03052_E_ДеÑÑ‚pyктоpÑ‹ не могyÑ‚ иметь паpаметpов
+% ДеÑтруктор объÑвлен Ñо ÑпиÑком параметров. Методы деÑтрукторов не могут иметь параметров.
+% cannot have parameters.
+parser_e_only_class_methods_via_class_ref=03053_E_По ÑÑылке на клаÑÑ Ð¼Ð¾Ð³ÑƒÑ‚ быть вызваны только клаÑÑ-методы
+% Ошибка возникает в Ñледующей Ñитуации:
+% \begin{verbatim}
+% Type :
+% Tclass = Class of Tobject;
+%
+% Var C : TClass;
+%
+% begin
+% ...
+% C.free
+% \end{verbatim}
+% \var{Free} не ÑвлÑетÑÑ ÐºÐ»Ð°ÑÑ-методом и поÑтому не может быть вызван по ÑÑылке на клаÑÑ.
+parser_e_only_class_methods=03054_E_Ð’ клаÑÑ-методах доÑтупны только другие клаÑÑ-методы
+% Имеет отношение к предыдущей ошибке. Из клаÑÑ-метода Ð½ÐµÐ»ÑŒÐ·Ñ Ð²Ñ‹Ð·Ð²Ð°Ñ‚ÑŒ обычный метод объекта.
+% Следующий код приведет к Ñтой ошибке:
+% \begin{verbatim}
+% class procedure tobject.x;
+%
+% begin
+% free
+% \end{verbatim}
+% ПоÑкольку free ÑвлÑетÑÑ Ð¾Ð±Ñ‹Ñ‡Ð½Ñ‹Ð¼ методом, его Ð½ÐµÐ»ÑŒÐ·Ñ Ð²Ñ‹Ð·Ð²Ð°Ñ‚ÑŒ из клаÑÑ-метода.
+parser_e_case_mismatch=03055_E_Тип конÑтанты не Ñовпадает Ñ Ñ‚Ð¸Ð¿Ð¾Ð¼ выpÐ°Ð¶ÐµÐ½Ð¸Ñ CASE
+% Одна из меток имеет тип, отличный от типа Ð²Ñ‹Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ case.
+parser_e_illegal_symbol_exported=03056_E_Символ не может быть ÑкÑпортирован из библиотеки
+% При напиÑании библиотеки можно ÑкÑпортировать только процедуры и функции. Такие типы,
+% как переменные и конÑтанты, ÑкÑпортировать нельзÑ.
+parser_w_should_use_override=03057_W_УнаÑледованный метод "$1" Ñкрыт, иÑпользуйте override
+% Метод, объÑвленный в родительÑком клаÑÑе как \var{virtual}, должен быть
+% перекрыт в клаÑÑе-наÑледнике директивой \var{override}. ЕÑли директива
+% \var{override} не указана, унаÑледованный метод будет Ñкрыт, а не перекрыт.
+parser_e_nothing_to_be_overridden=03058_E_Ð’ родительÑком клаÑÑе нет метода Ð´Ð»Ñ Ð¿ÐµpекрытиÑ: "$1"
+% Попытка перекрыть \var{override} виртуальный метод, отÑутÑтвующий в родительÑком клаÑÑею.
+parser_e_no_procedure_to_access_property=03059_E_Ðе указан ÑпоÑоб доÑтупа к ÑвойÑтву
+% Ð”Ð»Ñ ÑвойÑтва не указана директива \var{read}.
+parser_w_stored_not_implemented=03060_W_Директива stored Ð´Ð»Ñ ÑвойÑтв еще не pеализована
+% Директива \var{stored} еще не реализована
+parser_e_ill_property_access_sym=03061_E_Hевеpный Ñимвол Ð´Ð»Ñ Ð´Ð¾Ñтупа к ÑвойÑтвy
+% Ошибка в директиве \var{read} или \var{write} Ð´Ð»Ñ ÑвойÑтва типа маÑÑив.
+% ДоÑтуп к ÑвойÑтву типа маÑÑив возможен только Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ процедур и функций.
+% Следующий код вызовет ошибку:
+% \begin{verbatim}
+% tmyobject = class
+% i : integer;
+% property x [i : integer]: integer read I write i;
+% \end{verbatim}
+%
+parser_e_cant_access_protected_member=03062_E_ДоÑтуп к protected полю объекта здеÑÑŒ невозможен
+% ПолÑ, определенные в Ñекции \var{protected} объÑÐ²Ð»ÐµÐ½Ð¸Ñ ÐºÐ»Ð°ÑÑа,
+% недоÑтупны вне модулÑ, в котором объÑвлен клаÑÑ, и вне методов объектов-наÑледников.
+parser_e_cant_access_private_member=03063_E_ДоÑтуп к private полю объекта здеÑÑŒ невозможен
+% ПолÑ, определенные в Ñекции \var{private} объÑÐ²Ð»ÐµÐ½Ð¸Ñ ÐºÐ»Ð°ÑÑа,
+% недоÑтупны вне модулÑ, в котором объÑвлен клаÑÑ.
+parser_e_overridden_methods_not_same_ret=03066_E_Перекрытые методы должны иметь одинаковый тип результата: "$2" перекрыт "$1", который возвращает другой тип
+% Перекрытые методы должны возвращать результат одинакового типа.
+parser_e_dont_nest_export=03067_E_ЭкÑпортируемые Ñ„yнкции не могyÑ‚ быть вложенными
+% ÐÐµÐ»ÑŒÐ·Ñ Ð¾Ð±ÑŠÑвить процедуру или функцию, вложенную в процедуру или функцию, объÑвленную как ÑкÑпортируемаÑ.
+parser_e_methods_dont_be_export=03068_E_Методы не могyÑ‚ ÑкÑпоpтиpоватьÑÑ
+% Метод клаÑÑа или объекта не может быть объÑвлен как
+% \var{export}.
+parser_e_call_by_ref_without_typeconv=03069_E_Тип параметра no. $1 при передаче по ÑÑылке должен Ñовпадать: получено "$2", ожидалоÑÑŒ "$3"
+% При вызове функции, имеющей параметры по ÑÑылке (\var{var}), тип параметра
+% должен Ñтрого Ñовпадать Ñ Ð¾Ð±ÑŠÑвленным. ÐвтоматичеÑкое преобразование типов
+% в Ñтом Ñлучае отÑутÑтвует.
+parser_e_no_super_class=03070_E_КлаÑÑ Ð½Ðµ ÑвлÑетÑÑ Ñ€Ð¾Ð´Ð¸Ñ‚ÐµÐ»ÑŒÑким Ð´Ð»Ñ Ñ‚ÐµÐºÑƒÑ‰ÐµÐ³Ð¾ клаÑÑа
+% При вызове унаÑледованного метода указан клаÑÑ, отличный от родительÑкого.
+% УнаÑледованный метод можно вызывать только у родительÑкого клаÑÑа.
+parser_e_self_not_in_method=03071_E_SELF допуÑтим только в методах
+% Попытка иÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¿Ð°Ñ€Ð°Ð¼ÐµÑ‚Ñ€Ð° \var{self} вне метода объекта.
+% Параметр \var{self} передаетÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ в методы.
+parser_e_generic_methods_only_in_methods=03072_E_Вызов методов Ñ Ð¸Ð´ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ‚Ð¾Ñ€Ð¾Ð¼ типа клаÑÑа возможен только из других методов
+% КонÑÑ‚Ñ€ÑƒÐºÑ†Ð¸Ñ Ð²Ð¸Ð´Ð° \var{sometype.somemethod} допуÑтима только внутри методов.
+parser_e_illegal_colon_qualifier=03073_E_Hеверное иÑпользование ':'
+% Формат \var{:} (двоеточие) 2 раза иÑпользуетÑÑ Ð½Ð° выражении, которое не ÑвлÑетÑÑ Ð²ÐµÑ‰ÐµÑтвенным.
+parser_e_illegal_set_expr=03074_E_Ошибка проверки диапазона в конÑтрукторе множеÑтва или повторÑющийÑÑ Ñлемент множеÑтва
+% Ошибка в объÑвлении множеÑтва. Либо один из Ñлементов выходит за допуÑтимый диапазон,
+% либо какие-либо два Ñлемента имеют одно и то же значение.
+parser_e_pointer_to_class_expected=03075_E_ОжидаетÑÑ yказатель на объект
+% ИÑпользован неверный тип в выражении \var{New}.
+% РаÑширенный ÑинтакÑÐ¸Ñ \var{New} требует параметра типа объект.
+parser_e_expr_have_to_be_constructor_call=03076_E_Ð’Ñ‹pажение должно вызывать конÑÑ‚pyктоp
+% При иÑпользовании раÑширенного ÑинтакÑиÑа \var{new} нужно указывать конÑтруктор объекта.
+% Ð£ÐºÐ°Ð·Ð°Ð½Ð½Ð°Ñ Ð¿Ñ€Ð¾Ñ†ÐµÐ´ÑƒÑ€Ð° не ÑвлÑетÑÑ ÐºÐ¾Ð½Ñтруктором.
+parser_e_expr_have_to_be_destructor_call=03077_E_Ð’Ñ‹pажение должно вызывать деÑÑ‚pyктоp
+% При иÑпользовании раÑширенного ÑинтакÑиÑа \var{dispose} нужно указывать деÑтруктор объекта.
+% Ð£ÐºÐ°Ð·Ð°Ð½Ð½Ð°Ñ Ð¿Ñ€Ð¾Ñ†ÐµÐ´ÑƒÑ€Ð° не ÑвлÑетÑÑ Ð´ÐµÑтруктором.
+parser_e_invalid_record_const=03078_E_Hевеpный поpÑдок Ñлементов запиÑи
+% При объÑвлении конÑтанты типа запиÑÑŒ, Ð¿Ð¾Ð»Ñ ÑƒÐºÐ°Ð·Ð°Ð½Ñ‹ в неверном порÑдке.
+parser_e_false_with_expr=03079_E_Тип выpÐ°Ð¶ÐµÐ½Ð¸Ñ Ð´Ð¾Ð»Ð¶ÐµÐ½ быть CLASS или RECORD
+% Ðргумент Ð²Ñ‹Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ \var{with} должен быть типа \var{record} или
+% \var{class}. ИÑпользован аргумент Ñ Ñ‚Ð¸Ð¿Ð¾Ð¼, отличным от указанных.
+parser_e_void_function=03080_E_Пpоцедypа не может возвpащать значение
+% \fpc позволÑет указать возвращаемое значение Ð´Ð»Ñ Ñ„ÑƒÐ½ÐºÑ†Ð¸Ð¸ при иÑпользовании
+% Ð²Ñ‹Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ \var{exit}. Ошибка возникает при попытке Ñделать Ñто в процедуре.
+% Процедура не может возвращать значение.
+parser_e_only_methods_allowed=03081_E_КонÑÑ‚pyктоpÑ‹, деÑÑ‚pyктоpÑ‹ и операторы клаÑÑа должны быть методами
+% Попытка определить процедуру, не ÑвлÑющуюÑÑ Ð¼ÐµÑ‚Ð¾Ð´Ð¾Ð¼ клаÑÑа, как конÑтруктор, деÑтруктор или оператор клаÑÑа.
+parser_e_operator_not_overloaded=03082_E_Опеpатоp не пеpегpyжен
+% Попытка иÑпользовать перегруженный оператор, когда он не перегружен Ð´Ð»Ñ Ð´Ð°Ð½Ð½Ð¾Ð³Ð¾ типа.
+parser_e_no_such_assignment=03083_E_Ðевозможно перегрузить приÑвоение Ð´Ð»Ñ Ð¾Ð´Ð¸Ð½Ð°ÐºÐ¾Ð²Ñ‹Ñ… типов
+% Перегруженное приÑвоение невозможно Ð´Ð»Ñ Ñ‚Ð¸Ð¿Ð¾Ð², которые компилÑтор Ñчитает одинаковыми.
+parser_e_overload_impossible=03084_E_Перегрузка оператора невозможна
+% Сочетание оператора, аргументов и возвращаемого Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ ÑвлÑетÑÑ Ð½ÐµÑовмеÑтимым.
+parser_e_no_reraise_possible=03085_E_Повторное броÑание иÑÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ð·Ð´ÐµÑÑŒ невозможно
+% Попытка повторного броÑÐ°Ð½Ð¸Ñ Ð¸ÑÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ð² недопуÑтимом меÑте. Это разрешено делать только
+% в блоке \var{except}.
+parser_e_no_new_or_dispose_for_classes=03086_E_РаÑшиpенный ÑинтакÑÐ¸Ñ NEW и DISPOSE не разрешен Ð´Ð»Ñ ÐºÐ»Ð°ÑÑов
+% ЭкземплÑÑ€ клаÑÑа не может быть Ñоздан Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ раÑширенного ÑинтакÑиÑа
+% \var{new}, Ð´Ð»Ñ Ñтого Ñледует иÑпользовать конÑтруктор. Ðналогично, длÑ
+% ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ ÑкземплÑра клаÑÑа Ñледует иÑпользовать не \var{Dispose}, а деÑтруктор.
+parser_e_procedure_overloading_is_off=03088_E_Перегрузка пpоцедyp отключена
+% При иÑпользовании ключа \var{-So} перегрузка процедур отключена.
+% Turbo Pascal не поддерживает перегрузку.
+parser_e_overload_operator_failed=03089_E_Перегрузка Ñтого оператора невозможна. Перегружаемые операторы (еÑли еÑÑ‚ÑŒ): $1
+% Попытка перегрузить оператор, который не может быть перегружен.
+% Следующие операторы могут быть перегружены:
+% \begin{verbatim}
+% +, -, *, /, =, >, <, <=, >=, is, as, in, **, :=
+% \end{verbatim}
+parser_e_comparative_operator_return_boolean=03090_E_Оператор ÑÑ€Ð°Ð²Ð½ÐµÐ½Ð¸Ñ Ð´Ð¾Ð»Ð¶ÐµÐ½ возвращать значение типа boolean
+% При перегрузке оператора ÑÑ€Ð°Ð²Ð½ÐµÐ½Ð¸Ñ \var{=}, Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ Ð´Ð¾Ð»Ð¶Ð½Ð° возвращать значение типа boolean.
+parser_e_only_virtual_methods_abstract=03091_E_Только виртуальные методы могут быть абÑтрактными
+% Попытка определить абÑтрактный метод, не ÑвлÑющийÑÑ Ð¿Ñ€Ð¸ Ñтом виртуальным.
+parser_f_unsupported_feature=03092_F_ИÑпользование пока неподдерживаемой оÑобенноÑти компилÑтора!
+% Попытка заÑтавить компилÑтор Ñделать нечто, чего он пока еще не умеет.
+parser_e_mix_of_classes_and_objects=03093_E_Смешивание различных типов объектов (class, object, interface) не допуÑкаетÑÑ
+% Изменение базового типа при наÑледовании не допуÑкаетÑÑ. Это, в чаÑтноÑти, означает, что
+% class не может быть порожден от object, и наоборот.
+parser_w_unknown_proc_directive_ignored=03094_W_ÐеизвеÑÑ‚Ð½Ð°Ñ Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¸Ð²Ð° процедуры: "$1", игнорировано
+% Ð£ÐºÐ°Ð·Ð°Ð½Ð½Ð°Ñ Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¸Ð²Ð° процедуры неизвеÑтна компилÑтору.
+parser_e_absolute_only_one_var=03095_E_ABSOLUTE может быть указано только Ð´Ð»Ñ Ð¾Ð´Ð½Ð¾Ð¹ пеpеменной
+% ÐÐµÐ»ÑŒÐ·Ñ ÑƒÐºÐ°Ð·Ñ‹Ð²Ð°Ñ‚ÑŒ более одной переменной перед директивой \var{absolute}.
+% Ð¡Ð»ÐµÐ´ÑƒÑŽÑ‰Ð°Ñ ÐºÐ¾Ð½ÑÑ‚Ñ€ÑƒÐºÑ†Ð¸Ñ Ð¿Ñ€Ð¸Ð²ÐµÐ´ÐµÑ‚ к ошибке:
+% \begin{verbatim}
+% Var Z : Longint;
+% X,Y : Longint absolute Z;
+% \end{verbatim}
+parser_e_absolute_only_to_var_or_const=03096_E_ABSOLUTE может быть ÑвÑзана только Ñ Ð¿Ðµpеменной или конÑтантой
+% ÐÐ´Ñ€ÐµÑ Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¸Ð²Ñ‹ \var{absolute} может указывать только на переменную или
+% конÑтанту. Следующий код приведет к ошибке:
+% \begin{verbatim}
+% Procedure X;
+%
+% var p : longint absolute x;
+% \end{verbatim}
+%
+parser_e_initialized_only_one_var=03097_E_Ð˜Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð´Ð¾Ð¿ÑƒÑтима только Ð´Ð»Ñ Ð¾Ð´Ð½Ð¾Ð¹ переменной
+% ÐедопуÑтимо указание начального Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð±Ð¾Ð»ÐµÐµ чем Ð´Ð»Ñ Ð¾Ð´Ð½Ð¾Ð¹ переменной в
+% ÑинтакÑиÑе Delphi.
+parser_e_abstract_no_definition=03098_E_ÐбÑтрактные методы не могут иметь реализацию (тело)
+% ÐбÑтрактные методы могут иметь только объÑвление, Ñ€ÐµÐ°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð´Ð»Ñ Ð½Ð¸Ñ… недопуÑтима. Они
+% должны быть перекрыты в унаÑледованных клаÑÑах.
+parser_e_overloaded_must_be_all_global=03099_E_Эта Ð¿ÐµÑ€ÐµÐ³Ñ€ÑƒÐ¶ÐµÐ½Ð½Ð°Ñ Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ Ð½Ðµ может быть локальной (должна ÑкÑпортироватьÑÑ)
+% Попытка определить перегруженную функцию в Ñекции implementation модулÑ,
+% Ð´Ð»Ñ ÐºÐ¾Ñ‚Ð¾Ñ€Ð¾Ð¹ отÑутÑтвует объÑвление в Ñекции interface.
+parser_w_virtual_without_constructor=03100_W_Виртуальные методы иÑпользуютÑÑ Ð±ÐµÐ· конÑтруктора в "$1"
+% При объÑвлении объекта или клаÑÑа, Ñодержащего виртуальные методы, длÑ
+% их корректной инициализации требуетÑÑ ÐºÐ¾Ð½Ñтруктор. КомпилÑтор вÑтретил объÑвление
+% клаÑÑа или объекта Ñ Ð²Ð¸Ñ€Ñ‚ÑƒÐ°Ð»ÑŒÐ½Ñ‹Ð¼Ð¸ методами, но без пары конÑтруктор/деÑтруктор.
+parser_c_macro_defined=03101_CL_Опpеделен макpоÑ: $1
+% При иÑпользовании \var{-vc} компилÑтор Ñообщает об определении макроÑов.
+parser_c_macro_undefined=03102_CL_Удалено определение макроÑа: $1
+% При иÑпользовании \var{-vc} компилÑтор Ñообщает о том, что Ð¼Ð°ÐºÑ€Ð¾Ñ Ð±Ð¾Ð»ÑŒÑˆÐµ не определен.
+parser_c_macro_set_to=03103_CL_МакpÐ¾Ñ $1 yÑтановлен в $2
+% При иÑпользовании \var{-vc} компилÑтор Ñообщает об изменении Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð¼Ð°ÐºÑ€Ð¾Ñа.
+parser_i_compiling=03104_I_КомпилÑÑ†Ð¸Ñ $1
+% При включении информационных Ñообщений (\var{-vi}), компилÑтор Ñообщает о том,
+% какие модули он компилирует.
+parser_u_parsing_interface=03105_UL_Ðнализ интерфейÑа модyÐ»Ñ $1
+% Сообщает о начале разбора интерфейÑной чаÑти текущего модулÑ.
+parser_u_parsing_implementation=03106_UL_Ðнализ реализации модyÐ»Ñ $1
+% Сообщает о начале разбора реализации текущего модулÑ, программы или библиотеки.
+parser_d_compiling_second_time=03107_DL_ÐŸÐ¾Ð²Ñ‚Ð¾Ñ€Ð½Ð°Ñ ÐºÐ¾Ð¼Ð¿Ð¸Ð»ÑÑ†Ð¸Ñ $1
+% При включении отладочных Ñообщений (\var{-vd}) компилÑтор Ñообщает о том,
+% какие модули он компилирует повторно.
+parser_e_no_property_found_to_override=03109_E_ОтÑутÑтвует ÑвойÑтво Ð´Ð»Ñ Ð¿ÐµpеопpеделениÑ
+% Попытка переопределить ÑвойÑтво родительÑкого клаÑÑа, при отÑутÑтвии такового в родительÑком клаÑÑе.
+parser_e_only_one_default_property=03110_E_ДопуÑтимо только одно ÑвойÑтво по умолчанию
+% СвойÑтво определено как \var{Default}, но родительÑкий клаÑÑ ÑƒÐ¶Ðµ имеет определенное таким же образом
+% ÑвойÑтво.
+parser_e_property_need_paras=03111_E_СвойÑтво по умолчанию должно иметь тип маÑÑива
+% Только ÑвойÑтва типа маÑÑив могут быть объÑвлены как \var{default}.
+parser_e_constructor_cannot_be_not_virtual=03112_E_ВиpÑ‚yальные конÑÑ‚pyктоpÑ‹ допуÑтимы только в клаÑÑах
+% Виртуальные конÑтрукторы допуÑтимы только в клаÑÑах, их нельзÑ
+% объÑвлÑÑ‚ÑŒ в объектах.
+parser_e_no_default_property_available=03113_E_ОтÑутÑтвует ÑвойÑтво по умолчанию
+% Попытка доÑтупа к ÑвойÑтву по умолчанию клаÑÑа, который не имеет такого ÑвойÑтва.
+parser_e_cant_have_published=03114_E_КлаÑÑ Ð½Ðµ может иметь PUBLISHED раздел, иÑпользyйте ключ {$M+}
+% ЕÑли требуетÑÑ Ñ€Ð°Ð·Ð´ÐµÐ» \var{published} в объÑвлении клаÑÑа, Ñледует
+% иÑпользовать ключ \var{\{\$M+\}}, который включает генерацию информации о типах.
+parser_e_forward_declaration_must_be_resolved=03115_E_Раннее опpеделение клаÑÑа "$1" должно быть разрешено здеÑÑŒ, чтобы иÑпользовать его как предок
+% Чтобы клаÑÑ Ð¼Ð¾Ð¶Ð½Ð¾ было иÑпользовать как предок, он должен быть Ñначала определен.
+% Ошибка возникает в Ñледующей Ñитуации:
+% \begin{verbatim}
+% Type ParentClas = Class;
+% ChildClass = Class(ParentClass)
+% ...
+% end;
+% \end{verbatim}
+% Где \var{ParentClass} объÑвлен, но не определен.
+parser_e_no_local_operator=03116_E_Локальные опеpатоpÑ‹ не поддеpживаютÑÑ
+% Оператор Ð½ÐµÐ»ÑŒÐ·Ñ Ð¿ÐµÑ€ÐµÐ³Ñ€ÑƒÐ·Ð¸Ñ‚ÑŒ локально, Ñ‚.е. внутри Ð¾Ð¿Ñ€ÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¾Ñ†ÐµÐ´ÑƒÑ€Ñ‹ или
+% функции.
+parser_e_proc_dir_not_allowed_in_interface=03117_E_Диpектива процедуры "$1" недопуÑтима в интерфейÑной чаÑти модулÑ
+% Ð”Ð°Ð½Ð½Ð°Ñ Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¸Ð²Ð° не допуÑтима в Ñекции \var{interface} модулÑ.
+% Ее можно иÑпользовать только в Ñекции \var{implementation}.
+parser_e_proc_dir_not_allowed_in_implementation=03118_E_Диpектива процедуры "$1" недопуÑтима в реализационной чаÑти модулÑ
+% Ð”Ð°Ð½Ð½Ð°Ñ Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¸Ð²Ð° не допуÑтима в Ñекции \var{implementation} модулÑ.
+% Ее можно иÑпользовать только в Ñекции \var{interface}.
+parser_e_proc_dir_not_allowed_in_procvar=03119_E_Диpектива процедуры "$1" недопуÑтима в объÑвлении процедурной переменной
+% Ð”Ð°Ð½Ð½Ð°Ñ Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¸Ð²Ð° не может быть чаÑтью объÑÐ²Ð»ÐµÐ½Ð¸Ñ Ñ‚Ð¸Ð¿Ð° процедуры или функции.
+parser_e_function_already_declared_public_forward=03120_E_Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ "$1" уже объÑвлена как PUBLIC или FORWARD
+% Ошибка возникает при двукратном объÑвлении функции как \var{forward}.
+% Или при объÑвлении ее в Ñекции \var{interface} и поÑледующем однократном объÑвлении как \var{forward}
+% в Ñекции \var{implmentation}.
+parser_e_not_external_and_export=03121_E_HÐµÐ»ÑŒÐ·Ñ Ð¸Ñпользовать EXPORT ÑовмеÑтно Ñ EXTERNAL
+% Эти две директивы ÑвлÑÑŽÑ‚ÑÑ Ð²Ð·Ð°Ð¸Ð¼Ð¾Ð¸Ñключающими
+parser_w_not_supported_for_inline=03123_W_"$1" не поддеpживаетÑÑ Ð²Ð½yÑ‚pи INLINE пpоцедypÑ‹/Ñ„yнкции
+% Ð’Ñтраиваемые процедуры не поддерживают Ñтот тип объÑвлениÑ.
+parser_w_inlining_disabled=03124_W_Ð’Ñтраивание (INLINE) отключено
+% Ð’Ñтраивание процедур отключено.
+parser_i_writing_browser_log=03125_I_ЗапиÑываем лог бpаyзеpа $1
+% Когда включены информационные ÑообщениÑ, компилÑтор Ñообщает
+% о запиÑи данных Ð´Ð»Ñ Ð±Ñ€Ð°ÑƒÐ·ÐµÑ€Ð° (включаемого директивой \var{\{\$Y+ \}}).
+parser_h_maybe_deref_caret_missing=03126_H_Возможно, пропущено pазыменование yказателÑ
+% КомпилÑтор Ñчитает, что указатель может требовать разыменованиÑ.
+parser_f_assembler_reader_not_supported=03127_F_Выбpанный тип аÑÑемблеpа не поддеpживаетÑÑ
+% Выбранный тип аÑÑемблера (Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ \var{\{\$ASMMODE xxx\}}) не поддерживаетÑÑ.
+% Поддержка того или иного аÑÑемблера может быть подключена при Ñборке компилÑтора.
+parser_e_proc_dir_conflict=03128_E_Диpектива процедуры "$1" неÑовмеÑтима Ñ Ð´pyгими диpективами
+% Ð£ÐºÐ°Ð·Ð°Ð½Ð½Ð°Ñ Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¸Ð²Ð° неÑовмеÑтима Ñ Ð´Ñ€ÑƒÐ³Ð¸Ð¼Ð¸ директивами.
+% Ðапример, \var{cdecl} и \var{pascal} иÑключают друг друга.
+parser_e_call_convention_dont_match_forward=03129_E_Тип вызова пpоцедypÑ‹/Ñ„yнкции не ÑоответÑтвует yказанномy ранее
+% Ошибка проиÑходит при объÑвлении процедуры или функции, например,
+% как \var{cdecl;} и пропуÑком Ñтой директивы при определении, или наоборот.
+% Тип вызова ÑвлÑетÑÑ Ñ‡Ð°Ñтью объÑÐ²Ð»ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¾Ñ†ÐµÐ´ÑƒÑ€Ñ‹ и должен повторÑÑ‚ÑŒÑÑ
+% при ее определении.
+parser_e_property_cant_have_a_default_value=03131_E_СвойÑтво не может иметь значение по yмолчанию
+% СвойÑтва типа множеÑтво или индекÑированные ÑвойÑтва не могут иметь значение по умолчанию.
+parser_e_property_default_value_must_const=03132_E_Значение ÑвойÑтва по yмолчанию должно быть конÑтантой
+% Значение ÑвойÑтва, объÑвленное как \var{default}, должно быть извеÑтно во Ð²Ñ€ÐµÐ¼Ñ ÐºÐ¾Ð¼Ð¿Ð¸Ð»Ñции.
+% Ошибка проиÑходит, еÑли указано значение, извеÑтное только во Ð²Ñ€ÐµÐ¼Ñ Ð²Ñ‹Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ, например, Ð¸Ð¼Ñ Ð¿ÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ð¾Ð¹.
+parser_e_cant_publish_that=03133_E_Символ не может быть PUBLISHED, здеÑÑŒ допуÑтим только клаÑÑ
+% Только переменные типа клаÑÑа могут быть в \var{published} Ñекции объÑÐ²Ð»ÐµÐ½Ð¸Ñ ÐºÐ»Ð°ÑÑа,
+% еÑли они не объÑвлены как ÑвойÑтво.
+parser_e_cant_publish_that_property=03134_E_СвойÑтво Ñтого типа не может быть PUBLISHED
+% СвойÑтва в \var{published} Ñекции не могут быть типа маÑÑив, они
+% должны быть перенеÑены в Ñекцию public. СвойÑтва в Ñекции \var{published}
+% могут быть перечиÑлÑемого, вещеÑтвенного, Ñтрокового типа либо множеÑтвами.
+parser_e_empty_import_name=03136_E_ТребуетÑÑ Ð¸Ð¼Ñ Ð¸Ð¼Ð¿Ð¾Ñ€Ñ‚Ð°
+% Ð”Ð»Ñ Ð½ÐµÐºÐ¾Ñ‚Ð¾Ñ€Ñ‹Ñ… платформ требуетÑÑ Ð¸Ð¼Ñ Ð¸Ð¼Ð¿Ð¾Ñ€Ñ‚Ð¸Ñ€ÑƒÐµÐ¼Ð¾Ð¹ процедуры или ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ»Ñ cdecl
+parser_e_division_by_zero=03138_E_Деление на ноль
+% Произошло деление на ноль.
+parser_e_invalid_float_operation=03139_E_HепpÐ°Ð²Ð¸Ð»ÑŒÐ½Ð°Ñ Ð¾Ð¿ÐµpÐ°Ñ†Ð¸Ñ Ñ Ð¿Ð»Ð°Ð²Ð°ÑŽÑ‰ÐµÐ¹ запÑтой
+% ÐžÐ¿ÐµÑ€Ð°Ñ†Ð¸Ñ Ð½Ð°Ð´ Ð´Ð²ÑƒÐ¼Ñ Ð²ÐµÑ‰ÐµÑтвенными чиÑлами вызвала переполнение или деление на ноль.
+parser_e_array_lower_less_than_upper_bound=03140_E_ВеpхнÑÑ Ð³pаница диапазона меньше, чем нижнÑÑ
+% ВерхнÑÑ Ð³Ñ€Ð°Ð½Ð¸Ñ†Ð° в объÑвлении маÑÑива меньше нижней границы, что недопуÑтимо.
+parser_w_string_too_long=03141_W_Строка "$1" длиннее, чем "$2"
+% Длина Ñтроковой конÑтанты превышает длину, указанную в объÑвлении типа Ñтроки.
+parser_e_string_larger_array=03142_E_Длина Ñтроки превышает длину маÑÑива Ñимволов
+% Длина Ñтроковой конÑтанты превышает размер, указанный в объÑвлении маÑÑива
+% array[x..y] of char.
+parser_e_ill_msg_expr=03143_E_Hевеpное выpажение поÑле диpективы message
+% \fpc поддерживает только целочиÑленные и Ñтроковые Ð²Ñ‹Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ ÐºÐ°Ðº идентификаторы Ñообщений.
+parser_e_ill_msg_param=03144_E_Обpаботчики Ñообщений принимают только один параметр по ÑÑылке
+% Метод, объÑвленный Ñ Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¸Ð²Ð¾Ð¹ \var{message} как обработчик Ñообщений,
+% может принимать только один параметр, который должен передаватьÑÑ Ð¿Ð¾ ÑÑылке.
+% Параметр передаетÑÑ Ð¿Ð¾ ÑÑылке поÑредÑтвом директивы \var{var}.
+parser_e_duplicate_message_label=03145_E_ПовтоpÐ½Ð°Ñ Ð¼ÐµÑ‚ÐºÐ° ÑообщениÑ: "$1"
+% Одна и та же метка ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð¸Ñпользована дважды в одном объекте/клаÑÑе.
+parser_e_self_in_non_message_handler=03146_E_SELF может быть только как Ñвный параметр в обработчиках ÑообщениÑ
+% Параметр self может быть только Ñвно передан в метод, объÑвленный как обработчик Ñообщений.
+parser_e_threadvars_only_sg=03147_E_Пеpеменные threadvar могyÑ‚ быть только ÑтатичеÑкими или глобальными
+% Переменные threadvar должны быть ÑтатичеÑкими или глобальными, их Ð½ÐµÐ»ÑŒÐ·Ñ Ð¾Ð±ÑŠÑвлÑÑ‚ÑŒ локально
+% в процедуре. Локальные переменные процедуры вÑегда ÑвлÑÑŽÑ‚ÑÑ Ð»Ð¾ÐºÐ°Ð»ÑŒÐ½Ñ‹Ð¼Ð¸ Ð´Ð»Ñ Ð¿Ð¾Ñ‚Ð¾ÐºÐ°,
+% потому что каждый поток имеет ÑобÑтвенный Ñтек, а локальные переменные хранÑÑ‚ÑÑ Ð½Ð° Ñтеке.
+parser_f_direct_assembler_not_allowed=03148_F_Тип аÑÑемблеpа direct не поддеpживаетÑÑ Ð¿Ñ€Ð¸ двоичном фоpмате выходного файла
+% Тип аÑÑемблера direct не может быть иÑпользован ÑовмеÑтно Ñ Ð´Ð²Ð¾Ð¸Ñ‡Ð½Ñ‹Ð¼ форматом выходных файлов,
+% иÑпользуйте другой выходной формат или другой аÑÑемблер.
+parser_w_no_objpas_use_mode=03149_W_Hе загpyжайте модуль OBJPAS вручную, иÑпользyйте {$mode objfpc} или {$mode delphi}
+% Попытка загрузить модуль ObjPas вручную в Ñекции uses. Этот модуль предназначен длÑ
+% автоматичеÑкой загрузки Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ директив \var{\{\$mode objfpc\}} или
+% \var{\{\$mode delphi\}}.
+parser_e_no_object_override=03150_E_OVERRIDE не может быть иÑпользовано в объектах
+% Директива override не поддерживаетÑÑ Ð´Ð»Ñ Ð¾Ð±ÑŠÐµÐºÑ‚Ð¾Ð², Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐºÑ€Ñ‹Ñ‚Ð¸Ñ Ð¼ÐµÑ‚Ð¾Ð´Ð¾Ð² родительÑкого
+% объекта Ñледует иÑпользовать \var{virtual}.
+parser_e_cant_use_inittable_here=03151_E_Тип данных, Ñ‚pебующий инициализации/финализации, Ð½ÐµÐ»ÑŒÐ·Ñ Ð¸Ñпользовать в вариантных запиÑÑÑ…
+% Ðекоторые типы данных (например, \var{ansistring}) требуют код инициализации/финализации,
+% который неÑвно генерируетÑÑ ÐºÐ¾Ð¼Ð¸Ð¿Ð¸Ð»Ñтором. Такие типы данных не могут быть иÑпользованы
+% в вариантной чаÑти запиÑей.
+parser_e_resourcestring_only_sg=03152_E_Строки реÑурÑов могут быть только ÑтатичеÑкими или глобальными
+% Строки реÑурÑов не могут быть объÑвлены на локальном уровне, только на уровне модулÑ.
+parser_e_exit_with_argument_not__possible=03153_E_Процедура Exit Ñ Ð°Ñ€Ð³ÑƒÐ¼ÐµÐ½Ñ‚Ð¾Ð¼ здеÑÑŒ недопуÑтима
+% Вызов exit Ñ Ð°Ñ€Ð³ÑƒÐ¼ÐµÐ½Ñ‚Ð¾Ð¼ Ð´Ð»Ñ Ð²Ð¾Ð·Ð²Ñ€Ð°Ñ‰Ð°ÐµÐ¼Ð¾Ð³Ð¾ Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð½Ðµ может быть иÑпользован в Ñтом меÑте,
+% в чаÑтноÑти, в блоках \var{try..except} или \var{try..finally}.
+parser_e_stored_property_must_be_boolean=03154_E_Тип Ñимвола stored должен быть boolean
+% ЕÑли в объÑвлении ÑвойÑтва иÑпользуетÑÑ Ñимвол stored, он должен иметь тип boolean.
+parser_e_ill_property_storage_sym=03155_E_Этот Ñимвол недопуÑтим в качеÑтве stored
+% Данный тип Ñимвола не может быть иÑпользован Ð´Ð»Ñ ÑƒÐºÐ°Ð·Ð°Ð½Ð¸Ñ Ð¿Ñ€Ð¸Ð·Ð½Ð°ÐºÐ° ÑÐ¾Ñ…Ñ€Ð°Ð½ÐµÐ½Ð¸Ñ ÑвойÑтв.
+% ДопуÑтимо иÑпользовать методы, возвращающие boolean, Ð¿Ð¾Ð»Ñ Ñ‚Ð¸Ð¿Ð° boolean,
+% либо конÑтанты Ñтого типа.
+parser_e_only_publishable_classes_can_be_published=03156_E_Только клаÑÑÑ‹, Ñкомпилиpованные в режиме $M+, могут быть published
+% Ð’ Ñекции published объÑÐ²Ð»ÐµÐ½Ð¸Ñ ÐºÐ»Ð°ÑÑа могут иÑпользоватьÑÑ Ð¿Ð¾Ð»Ñ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ типа клаÑÑа,
+% который компилируетÑÑ Ð² режиме $M+ или унаÑледованный от такого клаÑÑа. Обычно
+% иÑпользуютÑÑ Ð½Ð°Ñледники TPersitent.
+parser_e_proc_directive_expected=03157_E_ОжидаетÑÑ Ð¿pоцедypÐ½Ð°Ñ Ð´Ð¸pектива
+% Ошибка проиÑходит, еÑли в директиве \var{\{\$Calling\}} не указан тип вызова.
+% Также проиÑходит, еÑли при объÑвлении процедур в блоке конÑтант иÑпользуетÑÑ ; поÑле
+% объÑÐ²Ð»ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¾Ñ†ÐµÐ´ÑƒÑ€Ñ‹, поÑле чего должна Ñледовать Ð¿Ñ€Ð¾Ñ†ÐµÐ´ÑƒÑ€Ð½Ð°Ñ Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¸Ð²Ð°.
+% Примеры правильных объÑвлений:
+% \begin{verbatim}
+% const
+% p : procedure;stdcall=nil;
+% p : procedure stdcall=nil;
+% \end{verbatim}
+parser_e_invalid_property_index_value=03158_E_Значение индекÑа ÑвойÑтва должно быть порÑдкового типа
+% Значение, иÑпольуземое как Ð¸Ð½Ð´ÐµÐºÑ ÑвойÑтва, должно быть порÑдкового типа, например,
+% целым чиÑлом или перечиÑлением.
+parser_e_procname_to_short_for_export=03159_E_Ð˜Ð¼Ñ Ð¿pоцедypÑ‹ Ñлишком коpоткое Ð´Ð»Ñ ÑкÑпоpта
+% Длина ÑкÑпортного имени процедуры/функции должна ÑоÑтавлÑÑ‚ÑŒ по крайней мере 2 Ñимвола.
+% Это обуÑловлено ошибкой в утилите dlltool, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð½Ðµ может корректно прочитать .def файл
+% Ñ Ð´Ð»Ð¸Ð½Ð¾Ð¹ имен, равной 1.
+parser_e_dlltool_unit_var_problem=03160_E_Ðевозможно Ñоздать запиÑÑŒ DEFFILE Ð´Ð»Ñ Ð³Ð»Ð¾Ð±Ð°Ð»ÑŒÐ½Ñ‹Ñ… переменных модулÑ
+parser_e_dlltool_unit_var_problem2=03161_E_Компилируйте без ключа -WD
+% Этот файл необходимо компилировать без ÑƒÐºÐ°Ð·Ð°Ð½Ð¸Ñ ÐºÐ»ÑŽÑ‡Ð° -WD в командной Ñтроке.
+parser_f_need_objfpc_or_delphi_mode=03162_F_Ð”Ð»Ñ Ñтого Ð¼Ð¾Ð´ÑƒÐ»Ñ Ð½ÐµÐ¾Ð±Ñ…Ð¾Ð´Ð¸Ð¼ режим ObjFpc (-S2) или Delphi (-Sd)
+% Ð”Ð»Ñ ÐºÐ¾Ð¼Ð¿Ð¸Ð»Ñции данного Ð¼Ð¾Ð´ÑƒÐ»Ñ Ñ‚Ñ€ÐµÐ±ÑƒÐµÑ‚ÑÑ {$mode objfpc} or {$mode delphi},
+% либо иÑпользование аналогичных ключей командной Ñтроки -S2 или -Sd.
+parser_e_no_export_with_index_for_target=03163_E_ЭкÑпоpÑ‚ по индекÑу невозможен под $1
+% ЭкÑпорт процедур/функций Ñ ÑƒÐºÐ°Ð·Ð°Ð½Ð¸ÐµÐ¼ индекÑа не поддерживаетÑÑ Ð´Ð»Ñ Ð¿Ð»Ð°Ñ‚Ñ„Ð¾Ñ€Ð¼Ñ‹ назначениÑ.
+parser_e_no_export_of_variables_for_target=03164_E_ЭкÑпоpÑ‚ пеpеменных не поддеpживаетÑÑ Ð¿Ð¾Ð´ $1
+% ЭкÑпорт переменных не поддерживаетÑÑ Ð´Ð»Ñ Ð¿Ð»Ð°Ñ‚Ñ„Ð¾Ñ€Ð¼Ñ‹ назначениÑ.
+parser_e_improper_guid_syntax=03165_E_Ðеверный ÑинтакÑÐ¸Ñ GUID
+% Ошибка в ÑинтакÑиÑе GUID. Корректный GUID должен быть в форме
+% \begin{verbatim}
+% {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}
+% \end{verbatim}
+% Где каждый \var{X} предÑтавлÑет Ñобой шеÑтнадцатеричную цифру.
+parser_w_interface_mapping_notfound=03168_W_Ðе найдена процедура Ñ Ð¸Ð¼ÐµÐ½ÐµÐ¼ "$1", подходÑÑ‰Ð°Ñ Ð´Ð»Ñ Ñ€ÐµÐ°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ð¸ $2.$3
+% КомпилÑтор не может найти процедуру, подходÑщую Ð´Ð»Ñ Ñ€ÐµÐ°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ð¸ указанного метода интерфейÑа.
+% Процедура Ñ Ñовпадающим именем найдена, но не Ñовпадает ÑпиÑок параметров.
+parser_e_interface_id_expected=03169_E_ОжидаетÑÑ Ð¸Ð´ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ‚Ð¾Ñ€ интерфейÑа
+% ПроиÑходит при анализе объÑÐ²Ð»ÐµÐ½Ð¸Ñ \var{class}, которое Ñодержит
+% опиÑание ÑоответÑÑ‚Ð²Ð¸Ñ Ð¼ÐµÑ‚Ð¾Ð´Ð¾Ð² \var{interface} по имени, например:
+% \begin{verbatim}
+% type
+% TMyObject = class(TObject, IDispatch)
+% function IUnknown.QueryInterface=MyQueryInterface;
+% ....
+% \end{verbatim}
+% и Ð¸Ð¼Ñ \var{interface} перед точкой не перечиÑлено в ÑпиÑке наÑледованиÑ.
+parser_e_type_cant_be_used_in_array_index=03170_E_Тип "$1" не может иÑпользоватьÑÑ ÐºÐ°Ðº Ð¸Ð½Ð´ÐµÐºÑ Ð¼Ð°ÑÑива
+% Такие типы, как \var{qword} или \var{int64}, недопуÑтимы в качеÑтве индекÑов маÑÑива
+parser_e_no_con_des_in_interfaces=03171_E_Constructor и destructor недопуÑтимы в interface
+% ИÑпользование конÑтрукторов и деÑтрукторов в интерфейÑах не разрешаетÑÑ.
+% Ð’ большинÑтве Ñлучаев Ð´Ð»Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ ÑкземплÑров интерфейÑа может быть иÑпользован метод
+% \var{QueryInterface} интерфейÑа \var{IUnknown}.
+parser_e_no_access_specifier_in_interfaces=03172_E_Указание типа доÑтупа недопуÑтимо в interface
+% Тип доÑтупа \var{public}, \var{private}, \var{protected} и
+% \var{pusblished} не может быть указан Ð´Ð»Ñ Ð¼ÐµÑ‚Ð¾Ð´Ð¾Ð² интерфейÑа.
+% Ð’Ñе методы интферфейÑа ÑвлÑÑŽÑ‚ÑÑ Ð¾Ð±Ñ‰ÐµÐ´Ð¾Ñтупными (public).
+parser_e_no_vars_in_interfaces=03173_E_Interface не может Ñодержать полÑ
+% ОбъÑвление полей в интерфейÑе не допуÑкаетÑÑ. Ð˜Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ Ð¼Ð¾Ð¶ÐµÑ‚
+% Ñодержать только методы.
+parser_e_no_local_proc_external=03174_E_Ð›Ð¾ÐºÐ°Ð»ÑŒÐ½Ð°Ñ Ð¿Ñ€Ð¾Ñ†ÐµÐ´ÑƒÑ€Ð° не может быть EXTERNAL
+% ОбъÑвление локальных процедур как external невозможно. Локальные процедуры
+% получают Ñкрытые параметры, что делает вероÑтноÑÑ‚ÑŒ ошибок очень выÑокой.
+parser_w_skipped_fields_before=03175_W_Ðекоторые Ð¿Ð¾Ð»Ñ Ð¿ÐµÑ€ÐµÐ´ "$1" не были инициализированы
+% Ð’ режиме Delphi, Ð¸Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð½ÐµÐºÐ¾Ñ‚Ð¾Ñ€Ñ‹Ñ… полей конÑтант типа запиÑÑŒ может быть пропущена,
+% но компилÑтор предупреждает о наличии такой Ñитуации.
+parser_e_skipped_fields_before=03176_E_Ðекоторые Ð¿Ð¾Ð»Ñ Ð¿ÐµÑ€ÐµÐ´ "$1" не были инициализированы
+% Ð’ режимах, отличных от Delphi, не допуÑкаетÑÑ Ð¾ÑтавлÑÑ‚ÑŒ неинициализированные полÑ
+% в Ñередине конÑтанты типа запиÑÑŒ.
+parser_w_skipped_fields_after=03177_W_Ðекоторые Ð¿Ð¾Ð»Ñ Ð¿Ð¾Ñле "$1" не были инициализированы
+% ÐŸÐ¾Ð»Ñ Ð² конце конÑтанты типа запиÑÑŒ могут быть оÑтавлены без инициализации
+% (компилÑтор автоматичеÑки инициализирует их нулевыми значениÑми). Это
+% может ÑвлÑÑ‚ÑŒÑÑ Ð¿Ñ€Ð¸Ñ‡Ð¸Ð½Ð¾Ð¹ некоторых проблем.
+parser_e_varargs_need_cdecl_and_external=03178_E_Директива VarArgs (или '...' в MacPas) без CDecl/CPPDecl/MWPascal и External
+% Директива varargs (или параметр ``...'' в режиме MacPas) может быть иÑпользована только Ñ
+% процедурами/функциÑми, объÑвленными Ñ Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¸Ð²Ð°Ð¼Ð¸ \var{external} и одной из \var{cdecl},
+% \var{cppdecl} или \var{mwpascal}. Эта функциональноÑÑ‚ÑŒ поддерживаетÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ длÑ
+% ÑовмеÑтимоÑти Ñ Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñми Ñзыка C типа printf.
+parser_e_self_call_by_value=03179_E_Self должен быть параметром Ñ Ð¿ÐµÑ€ÐµÐ´Ð°Ñ‡ÐµÐ¹ по значению
+% Параметр Self не может быть передан по ÑÑылке (Ñ var или const), его нужно передавать по
+% значению
+parser_e_interface_has_no_guid=03180_E_Ð˜Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ "$1" не имеет идентификатора
+% При приÑвоении интерфейÑа конÑтанте, Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ Ð´Ð¾Ð»Ð¶ÐµÐ½ иметь значение GUID.
+parser_e_illegal_field_or_method=03181_E_ÐеизвеÑтный идентификатор Ð¿Ð¾Ð»Ñ Ð¸Ð»Ð¸ метода "$1"
+% СвойÑтва должны ÑÑылатьÑÑ Ð½Ð° Ð¿Ð¾Ð»Ñ Ð¸ методы того же клаÑÑа, в котором объÑвлены.
+parser_w_proc_overriding_calling=03182_W_Тип вызова "$2" перекрывает "$1"
+% Ð’ объÑвлении процедуры приÑутÑтвуют две директивы, определÑющие тип вызова.
+% Будет иÑпользована поÑледнÑÑ Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¸Ð²Ð°.
+parser_e_no_procvarobj_const=03183_E_КонÑтанта типа "procedure of object" может быть инициализирована только значением NIL
+% ÐÐ´Ñ€ÐµÑ Ð¼ÐµÑ‚Ð¾Ð´Ð° не может быть иÑпользован Ð´Ð»Ñ Ð¸Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ð¸ типизированной конÑтанты типа
+% 'procedure of object', потому что Ñ‚Ð°ÐºÐ°Ñ ÐºÐ¾Ð½Ñтанта ÑоÑтоит из двух адреÑов:
+% Ð°Ð´Ñ€ÐµÑ Ð¼ÐµÑ‚Ð¾Ð´Ð° (извеÑтный во Ð²Ñ€ÐµÐ¼Ñ ÐºÐ¾Ð¼Ð¿Ð¸Ð»Ñции) и Ð°Ð´Ñ€ÐµÑ ÑкземплÑра объекта или
+% клаÑÑа (не может быть определен при компилÑции).
+parser_e_default_value_only_one_para=03184_E_Значение по умолчанию может быть приÑвоено только одному параметру
+% Ðевозможно приÑвоить значение по умолчанию Ñразу неÑкольким параметрам.
+% Следующий код неверен:
+% \begin{verbatim}
+% Procedure MyProcedure (A,B : Integer = 0);
+% \end{verbatim}
+% ВмеÑто Ñто Ñледует объÑвить процедуру как:
+% \begin{verbatim}
+% Procedure MyProcedure (A : Integer = 0; B : Integer = 0);
+% \end{verbatim}
+parser_e_default_value_expected_for_para=03185_E_Ð”Ð»Ñ "$1" требуетÑÑ Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ðµ по умолчанию
+% Указанный параметр требует значение по умолчанию.
+parser_w_unsupported_feature=03186_W_ИÑпользование пока неподдерживаемой оÑобенноÑти компилÑтора!
+% Попытка заÑтавить компилÑтор Ñделать нечто, чего он пока еще не умеет.
+parser_h_c_arrays_are_references=03187_H_МаÑÑивы C передаютÑÑ Ð¿Ð¾ ÑÑылке
+% Передача маÑÑивов в функции на Ñзыке C вÑегда
+% оÑущеÑтвлÑетÑÑ Ð¿Ð¾ÑредÑтвом ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ»Ñ (Ñ‚.е. по ÑÑылке).
+parser_e_C_array_of_const_must_be_last=03188_E_МаÑÑив конÑтант в C должен быть поÑледним параметром
+% ÐÐµÐ»ÑŒÐ·Ñ Ð´Ð¾Ð±Ð°Ð²Ð»ÑÑ‚ÑŒ другие параметры поÑле параметра типа \var{array of const},
+% передаваемого в функцию, объÑвленную как \var{cdecl}, потому что Ð´Ð»Ñ Ð½ÐµÐ³Ð¾
+% заранее не извеÑтен размер данных, помещаемых на Ñтек.
+parser_h_type_redef=03189_H_Повторное объÑвление типа "$1"
+% Сообщает о том, что Ð´Ð»Ñ Ñ€Ð°Ð½ÐµÐµ определенного типа вÑтретилоÑÑŒ
+% повторное отличающееÑÑ Ð¾Ð±ÑŠÑвление. Это может быть (а может и не быть)
+% причиной ошибок.
+parser_w_cdecl_has_no_high=03190_W_Функции cdecl не имеют параметра high
+% Ð’ функции, объÑвленные как cdecl, не передаетÑÑ Ñкрытый параметр high.
+parser_w_cdecl_no_openstring=03191_W_Функции cdecl не поддерживают открытые Ñтроки
+% Строки типа openstring не поддерживаютÑÑ Ð² cdecl функциÑÑ….
+parser_e_initialized_not_for_threadvar=03192_E_Ð˜Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð¿ÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ð¾Ð¹ типа threadvar невозможна
+% Переменные, объÑвленные как threadvar, не могут иметь начального значениÑ.
+% Они вÑегда получают нулевое значение при Ñтарте нового потока.
+parser_e_msg_only_for_classes=03193_E_Директива message разрешена только Ð´Ð»Ñ ÐºÐ»Ð°ÑÑов
+% Директива message поддерживаетÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ Ð´Ð»Ñ Ñ‚Ð¸Ð¿Ð¾Ð² Class.
+parser_e_procedure_or_function_expected=03194_E_ОжидаетÑÑ "procedure" или "function"
+% КлаÑÑ-методами могут быть только процедуры и функции.
+parser_e_illegal_calling_convention=03195_W_Тип вызова игнорирован: "$1"
+% Ðекоторые типы вызовов поддерживаютÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ на определенных процеÑÑорах. Так, Ð´Ð»Ñ Ð±Ð¾Ð»ÑŒÑˆÐ¸Ð½Ñтва
+% не-i386 поддерживаютÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ типы вызова Ñтандартного ABI.
+parser_e_no_object_reintroduce=03196_E_REINTRODUCE Ð½ÐµÐ»ÑŒÐ·Ñ Ð¸Ñпользовать Ð´Ð»Ñ Ð¾Ð±ÑŠÐµÐºÑ‚Ð¾Ð²
+% Директива \var{reintroduce} не поддерживаетÑÑ Ð´Ð»Ñ Ð¾Ð±ÑŠÐµÐºÑ‚Ð¾Ð².
+parser_e_paraloc_only_one_para=03197_E_РаÑположение аргументов не может Ñовпадать
+% ЕÑли раÑположение аргументов указываютÑÑ Ñвно, как того требуют некоторые
+% типы вызовов syscall, раÑположение каждого из аргументов должно быть уникальным,
+% конÑтрукции вида \var{procedure p(i,j : longint 'r1');} не допуÑкаютÑÑ.
+parser_e_paraloc_all_paras=03198_E_Ðужно указать раÑположение Ð´Ð»Ñ Ð²Ñех аргументов
+% ЕÑли раÑположение указано Ð´Ð»Ñ Ð¾Ð´Ð½Ð¾Ð³Ð¾ аргументов, его нужно указать и Ð´Ð»Ñ Ð²Ñех
+% оÑтальных.
+parser_e_illegal_explicit_paraloc=03199_E_ÐеизвеÑтное раÑположение аргумента
+% Указанное раÑположение не ÑвлÑетÑÑ Ð´Ð¾Ð¿ÑƒÑтимым Ñ Ñ‚Ð¾Ñ‡ÐºÐ¸ Ð·Ñ€ÐµÐ½Ð¸Ñ ÐºÐ¾Ð¼Ð¿Ð¸Ð»Ñтора.
+parser_e_32bitint_or_pointer_variable_expected=03200_E_ОжидаетÑÑ 32-битное целое либо указатель
+% libbase Ð´Ð»Ñ MorphOS/AmigaOS можно задавать только как \var{longint}, \var{dword}, либо указатель
+% любого типа.
+parser_e_goto_outside_proc=03201_E_Ðе допуÑкаетÑÑ goto между различными процедурами
+% Ðе допуÑкаетÑÑ Ð¸Ñпользование \var{goto} Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÑ…Ð¾Ð´Ð° на метку, определенную вне
+% текущей процедуры. Следующий пример демонÑтрирует проблему:
+% \begin{verbatim}
+% ...
+% procedure p1;
+% label
+% l1;
+%
+% procedure p2;
+% begin
+% goto l1; // Эта инÑÑ‚Ñ€ÑƒÐºÑ†Ð¸Ñ goto не разрешаетÑÑ
+% end;
+%
+% begin
+% p2
+% l1:
+% end;
+% ...
+%
+% \end{verbatim}
+parser_f_too_complex_proc=03202_F_Слишком ÑÐ»Ð¾Ð¶Ð½Ð°Ñ Ð¿Ñ€Ð¾Ñ†ÐµÐ´ÑƒÑ€Ð°, не хватает региÑтров
+% Тело процедуры ÑвлÑетÑÑ Ñлишком Ñложным Ð´Ð»Ñ ÐºÐ¾Ð¼Ð¿Ð¸Ð»Ñции. Следует разбить ее
+% на неÑколько более проÑÑ‚Ñ‹Ñ… процедур.
+parser_e_illegal_expression=03203_E_ÐедопуÑтимое выражение
+% Может возникать по разным причинам. Ðаиболее чаÑто - при вычиÑлении
+% конÑтантных выражений.
+parser_e_invalid_integer=03204_E_Ðеверное целочиÑленное выражение
+% Выражение не ÑвлÑетÑÑ Ñ†ÐµÐ»Ñ‹Ð¼ чиÑлом, в то Ð²Ñ€ÐµÐ¼Ñ ÐºÐ°Ðº компилÑтор ожидает
+% именно целочиÑленный результат.
+parser_e_invalid_qualifier=03205_E_Ðеверный квалификатор
+% ПроиÑходит по одной из Ñледующих причин:
+% \begin{itemize}
+% \item Попытка доÑтупа к полю переменной, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð½Ðµ ÑвлÑетÑÑ Ð·Ð°Ð¿Ð¸Ñью.
+% \item Указание индекÑа Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ð¾Ð¹, не ÑвлÑющейÑÑ Ð¼Ð°ÑÑивом.
+% \item Разыменование переменной, не ÑвлÑющейÑÑ ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ»ÐµÐ¼.
+% \end{itemize}
+parser_e_upper_lower_than_lower=03206_E_Верхний предел диапазона < нижнего
+% При объÑвлении поддиапазона, нижний предел оказалÑÑ Ð±Ð¾Ð»ÑŒÑˆÐµ
+% верхнего.
+parser_e_macpas_exit_wrong_param=03207_E_Параметр Exit должен быть именем текущей процедуры
+% Ðе-локальный exit не допуÑкаетÑÑ. Эта ошибка возникает только в режиме MacPas.
+parser_e_illegal_assignment_to_count_var=03208_E_Ðеверное приÑвоение переменной for-цикла "$1"
+% Тип переменной Ð´Ð»Ñ Ñ†Ð¸ÐºÐ»Ð° \var{for} должен быть порÑдковым.
+% ВещеÑтвенные и Ñтроковые типы не допуÑкаютÑÑ. Кроме того, не допуÑкаетÑÑ Ð¿Ñ€Ð¸Ñвоение
+% управлÑющей переменной внутри цикла (кроме режимов Delphi и TP). ЕÑли требуетÑÑ
+% приÑвоение, вмеÑто цикла for Ñледует иÑпользовать предназначенные Ð´Ð»Ñ Ñтого
+% циклы while или repeat.
+parser_e_no_local_var_external=03209_E_Ð›Ð¾ÐºÐ°Ð»ÑŒÐ½Ð°Ñ Ð¿ÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ð°Ñ Ð½Ðµ может быть EXTERNAL
+% ОбъÑвление локальных переменных как внешних не допуÑкаетÑÑ. Внешними могут быть
+% только глобальные переменные.
+parser_e_proc_already_external=03210_E_Процедура уже объÑвлена как EXTERNAL
+% Процедура уже объÑвлена Ñ Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¸Ð²Ð¾Ð¹ EXTERNAL в интерфейÑе Ð¼Ð¾Ð´ÑƒÐ»Ñ Ð¸Ð»Ð¸
+% в раннем объÑвлении.
+parser_w_implicit_uses_of_variants_unit=03211_W_ÐеÑвное иÑпользование Ð¼Ð¾Ð´ÑƒÐ»Ñ Variants
+% Ð’ модуле иÑпользуетÑÑ Ñ‚Ð¸Ð¿ Variant, но модуль Variants не подключен ни к одному из иÑпользуемых
+% модулей. КомпилÑтор неÑвно добавлÑет Variants в ÑпиÑок иÑпользуемых модулей.
+% Чтобы избавитьÑÑ Ð¾Ñ‚ предупреждениÑ, добавьте Variants в ÑпиÑок uses.
+parser_e_no_static_method_in_interfaces=03212_E_Методы class and static не допуÑкаютÑÑ Ð² INTERFACE
+% Спецификатор \var{class} и директива \var{static} не применимы в интерфейÑах,
+% Ñ‚.к. вÑе методы интерфейÑа должны быть публичными.
+parser_e_arithmetic_operation_overflow=03213_E_Переполнение в арифметичеÑкой операции
+% ÐžÐ¿ÐµÑ€Ð°Ñ†Ð¸Ñ Ð½Ð°Ð´ целыми чиÑлами привела к переполнению
+parser_e_protected_or_private_expected=03214_E_ОжидаетÑÑ "protected" или "private"
+% \var{strict} может иÑпользоватьÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ в Ñочетании Ñ \var{protected} или \var{private}.
+parser_e_illegal_slice=03215_E_SLICE Ð½ÐµÐ»ÑŒÐ·Ñ Ð¸Ñпользовать вне ÑпиÑка параметров
+% \var{slice} можно иÑпользовать только Ð´Ð»Ñ Ð°Ñ€Ð³ÑƒÐ¼ÐµÐ½Ñ‚Ð¾Ð², принимающих тип открытого маÑÑива
+parser_e_dispinterface_cant_have_parent=03216_E_DISPINTERFACE не может иметь родителÑ
+% DISPINTERFACE ÑвлÑетÑÑ Ð¾Ñобым типом интерфейÑа и не может иметь родительÑкий клаÑÑ
+parser_e_dispinterface_needs_a_guid=03217_E_Ð”Ð»Ñ DISPINTERFACE требуетÑÑ GUID
+% DISPINTERFACE вÑегда требует идентификации Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ GUID
+parser_w_overridden_methods_not_same_ret=03218_W_Перекрытые методы должны иметь одинаковый тип результата. Этот код иÑпользует ошибку в парÑере Delphi и будет работать непредÑказуемо ("$2" перекрыто "$1", имеющим другой тип результата)
+% Перекрытые методы должны возвращать один и тот же тип результата.
+% Ðекоторые верÑии Delphi позволÑÑŽÑ‚ изменÑÑ‚ÑŒ типы результата и даже превращать
+% процедуры в функции, но работоÑпоÑобноÑÑ‚ÑŒ полученного кода завиÑит от
+% иÑпользованных типов и ÑпоÑоба вызова методов.
+parser_e_dispid_must_be_ord_const=03219_E_Dispatch ID должны быть порÑдковыми конÑтантами
+% За ключевым Ñловом \var{dispid} должна Ñледовать порÑÐ´ÐºÐ¾Ð²Ð°Ñ ÐºÐ¾Ð½Ñтанта (индекÑ).
+parser_e_array_range_out_of_bounds=03220_E_Диапазон маÑÑива Ñлишком велик
+% ÐезавиÑимо от количеÑтва памÑти, занимаемой Ñлементами, маÑÑивы не могут Ñодержать
+% больше чем high(ptrint) Ñлементов. Кроме того, тип диапазона должен быть поддиапазоном
+% типа ptrint.
+parser_e_packed_element_no_var_addr=03221_E_ÐÐµÐ»ÑŒÐ·Ñ Ð²Ð·ÑÑ‚ÑŒ Ð°Ð´Ñ€ÐµÑ Ñлементов/полей побитно-упакованных маÑÑивов/запиÑей
+% ÐŸÐ¾Ð»Ñ Ð·Ð°Ð¿Ð¸Ñи или Ñлементы маÑÑива, объÑвленных как \var{packed} в режиме Mac Pascal (либо как
+% \var{packed} в любом режиме при уÑловии \var{\{\$bitpacking on\}}), будут упакованы на уровне
+% бит. Это означает невозможноÑÑ‚ÑŒ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð°Ð´Ñ€ÐµÑов отдельных Ñлементов маÑÑива или полей запиÑи.
+% ИÑключением из Ñтого правила ÑвлÑÑŽÑ‚ÑÑ ÑƒÐ¿Ð°ÐºÐ¾Ð²Ð°Ð½Ð½Ñ‹Ðµ маÑÑивы, размер Ñлементов которых кратен 8 битам.
+parser_e_packed_dynamic_open_array=03222_E_ДинамичеÑкие маÑÑивы не могут быть упакованными
+% Упакованными могут быть только обычные (и, возможно, в будущем также открытые) маÑÑивы.
+parser_e_packed_element_no_loop=03223_E_Элементы/Ð¿Ð¾Ð»Ñ Ð¿Ð¾Ð±Ð¸Ñ‚Ð½Ð¾-упакованных маÑÑивов/запиÑей Ð½ÐµÐ»ÑŒÐ·Ñ Ð¸Ñпользовать как переменные цикла for
+% ÐŸÐ¾Ð»Ñ Ð·Ð°Ð¿Ð¸Ñи или Ñлементы маÑÑива, объÑвленных как \var{packed} в режиме Mac Pascal (либо как
+% \var{packed} в любом режиме при уÑловии \var{\{\$bitpacking on\}}), будут упакованы на уровне
+% бит. По причинам быÑтродейÑÑ‚Ð²Ð¸Ñ Ð¸Ñ… Ð½ÐµÐ»ÑŒÐ·Ñ Ð¸Ñпользовать как переменные Ð´Ð»Ñ for-цикла.
+parser_e_type_and_var_only_in_generics=03224_E_VAR и TYPE допуÑтимы только в обобщениÑÑ… (generic)
+% ИÑпользование VAR и TYPE Ð´Ð»Ñ Ð¾Ð±ÑŠÑÐ²Ð»ÐµÐ½Ð¸Ñ Ð½Ð¾Ð²Ñ‹Ñ… типов внутри объекта разрешаетÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ длÑ
+% обобщений.
+parser_e_cant_create_generics_of_this_type=03225_E_Этот тип не может быть обобщением
+% ÐžÐ±Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð´Ð¾Ð¿ÑƒÑкаютÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ Ð´Ð»Ñ ÐºÐ»Ð°ÑÑов, объектов, интерфейÑов и запиÑей.
+parser_w_no_lineinfo_use_switch=03226_W_Ðе подключайте модуль LINEINFO вручную, иÑпользуйте Ð´Ð»Ñ Ñтого ключ -gl
+% Ðе подключайте модуль LINEINFO вручную, иÑпользование ключа \var{-gl} автоматичеÑки подключает
+% различные модули в завиÑимоÑти от типа генерируемой отладочной информации.
+parser_e_no_funcret_specified=03227_E_Ð”Ð»Ñ Ñ„ÑƒÐ½ÐºÑ†Ð¸Ð¸ "$1" не указан тип результата
+% Первое объÑвление функции должно быть полным, Ð²ÐºÐ»ÑŽÑ‡Ð°Ñ Ð²Ñе параметры и тип результата.
+parser_e_special_onlygenerics=03228_E_Ð¡Ð¿ÐµÑ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð²Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ð° только Ð´Ð»Ñ Ð¾Ð±Ð¾Ð±Ñ‰ÐµÐ½Ð½Ñ‹Ñ… типов.
+% Типы, не ÑвлÑющиеÑÑ Ð¾Ð±Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñми, не могут быть Ñпециализированы.
+parser_e_no_generics_as_params=03229_E_ÐžÐ±Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð½ÐµÐ»ÑŒÐ·Ñ Ð¸Ñпользовать как параметры Ñпециализации других обобщений
+% При Ñпециализации обобщениÑ, в качеÑтве параметров можно иÑпользовать только обычные типы.
+parser_e_type_object_constants=03230_E_КонÑтантные объекты, Ñодержащие VMT, не допуÑкаютÑÑ
+% ЕÑли объект требует VMT из-за Ð½Ð°Ð»Ð¸Ñ‡Ð¸Ñ ÐºÐ¾Ð½Ñтруктора либо виртуальных методов,
+% Ñоздание конÑтант его типа не допуÑкаетÑÑ. Ð’ режимах TP и Delphi, тем не менее,
+% Ñто разрешено в целÑÑ… ÑовмеÑтимоÑти.
+parser_e_label_outside_proc=03231_E_Ðе допуÑкаетÑÑ Ð²Ð·Ñтие адреÑов меток, определенных вне текущей облаÑти видимоÑти
+% Ðе разрешаетÑÑ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ðµ адреÑов меток, находÑщихÑÑ Ð²Ð½Ðµ текущей процедуры.
+parser_e_initialized_not_for_external=03233_E_Ðе допуÑкаетÑÑ Ð¸Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð¿ÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ñ‹Ñ…, объÑвленных как external
+% Переменные, объÑвленные как external, не могут иметь значение по умолчанию.
+parser_e_illegal_function_result=03234_E_Ðеверный тип возвращаемого значениÑ
+% Ðекоторые типы, такие как файлы, не могут быть иÑпользованы в качеÑтве результата функции.
+parser_e_no_common_type=03235_E_ОтÑутÑтвует общий тип Ð´Ð»Ñ "$1" и "$2"
+% Чтобы выполнить операцию над целыми чиÑлами, компилÑтор приводит их к общему типу,
+% чего ему в данном Ñлучае не удаетÑÑ. Ð”Ð»Ñ Ð¾Ð¿Ñ€ÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ Ð¾Ð±Ñ‰ÐµÐ³Ð¾ типа операндов
+% компилÑтор берет меньшее из минимальных значений обоих типов и большее из макÑимальных
+% значений. Общий тип будет иметь диапазон минимум..макÑимум.
+parser_e_no_generics_as_types=03236_E_ÐžÐ±Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð±ÐµÐ· Ñпециализации не могут быть иÑпользованы как тип переменной
+% ÐžÐ±Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð²Ñегда должны быть Ñпециализированы перед иÑпользованием в качеÑтве типа Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ñ‹Ñ….
+parser_w_register_list_ignored=03237_W_Перечень региÑтров Ð´Ð»Ñ Ð¿Ñ€Ð¾Ñ†ÐµÐ´ÑƒÑ€ полноÑтью на аÑÑемблере игнорирован
+% Ð’ процедурах, напиÑанных полноÑтью на аÑÑемблере, перечень измененных региÑтров игнорируетÑÑ.
+parser_e_implements_must_be_class_or_interface=03238_E_СвойÑтво implements должно быть типа клаÑÑ Ð¸Ð»Ð¸ интерфейÑ
+% СвойÑтво, реализующее интерфейÑ, должно иметь тип клаÑÑа или интерфейÑа.
+parser_e_implements_must_have_correct_type=03239_E_СвойÑтво implements должно реализовывать Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ ÑƒÐºÐ°Ð·Ð°Ð½Ð½Ð¾Ð³Ð¾ типа, найдено "$1" ожидалоÑÑŒ "$2"
+% СвойÑтво, реализующее интерфейÑ, реализует не тот тип интерфейÑа.
+parser_e_implements_must_read_specifier=03240_E_СвойÑтво implements должно быть доÑтупным Ð´Ð»Ñ Ñ‡Ñ‚ÐµÐ½Ð¸Ñ
+% СвойÑтво, реализующее интерфейÑ, должно иметь Ñпецификатор read.
+parser_e_implements_must_not_have_write_specifier=03241_E_СвойÑтво implements не должно быть доÑтупным Ð´Ð»Ñ Ð·Ð°Ð¿Ð¸Ñи
+% СвойÑтво, реализующее интерфейÑ, не может иметь Ñпецификатор write.
+parser_e_implements_must_not_have_stored_specifier=03242_E_СвойÑтво implements не может быть stored
+% СвойÑтво, реализующее интерфейÑ, не может иметь Ñпецификатор stored.
+parser_e_implements_uses_non_implemented_interface=03243_E_СвойÑтво implements иÑпользовано Ð´Ð»Ñ Ð½ÐµÑ€ÐµÐ°Ð»Ð¸Ð·Ð¾Ð²Ð°Ð½Ð½Ð¾Ð³Ð¾ интерфейÑа: "$1"
+% ИнтерфейÑ, реализуемый ÑвойÑтвом, должен быть в ÑпиÑке интерфейÑов, реализуемых клаÑÑом.
+parser_e_unsupported_real=03244_E_ВычиÑÐ»ÐµÐ½Ð¸Ñ Ñ Ð¿Ð»Ð°Ð²Ð°ÑŽÑ‰ÐµÐ¹ запÑтой не доÑтупны Ð´Ð»Ñ Ñ†ÐµÐ»ÐµÐ²Ð¾Ð¹ платформы
+% Ð’ÑтретилоÑÑŒ вещеÑтвенное выражение, но на целевой платформе они не поддерживаютÑÑ
+parser_e_class_doesnt_implement_interface=03245_E_КлаÑÑ "$1" не реализует Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ "$2"
+% Делегированный Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ Ð½Ðµ реализован клаÑÑом, указанным в выражении implements.
+parser_e_class_implements_must_be_interface=03246_E_Тип, иÑпользуемый implements, должен быть интерфейÑом
+% За ключевым Ñловом \var{implements} должно Ñледовать Ð¸Ð¼Ñ Ñ‚Ð¸Ð¿Ð° интерфейÑа.
+parser_e_cant_export_var_different_name=03247_E_Ðа Ñтой платформе переменные Ð½ÐµÐ»ÑŒÐ·Ñ ÑкÑпортировать Ñ Ð´Ñ€ÑƒÐ³Ð¸Ð¼ именем, добавьте Ð¸Ð¼Ñ Ðº объÑвлению Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ директивы "export" (Ð¸Ð¼Ñ Ð¿ÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ð¾Ð¹: $1, объÑвленное Ð¸Ð¼Ñ ÑкÑпорта: $2)
+% On most targets it is not possible to change the name under which a variable
+% is exported inside the \var{exports} statement of a library.
+% In that case, you have to specify the export name at the point where the
+% variable is declared, using the \var{export} and \var{alias} directives.
+parser_e_weak_external_not_supported=03248_E_Символы "weak external" не поддерживаютÑÑ Ð½Ð° целевой платформе
+% A "weak external" symbol is a symbol which may or may not exist at (either static
+% or dynamic) link time. This concept may not be available (or implemented yet)
+% on the current cpu/OS target.
+parser_e_forward_mismatch=03249_E_Тип не ÑоответÑтвует раннему объÑвлению
+% При раннем объÑвлении клаÑÑов и интерфейÑов типы раннего и фактичеÑкого объÑвлений
+% должны Ñовпадать. Ранее объÑвленный Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ Ð½Ðµ может быть превращен в клаÑÑ.
+parser_n_ignore_lower_visibility=03250_N_Виртуальный метод "$1" имеет меньшую видимоÑÑ‚ÑŒ ($2), чем в родительÑком клаÑÑе $3 ($4)
+% Перекрывающий виртуальный метод видимоÑÑ‚ÑŒ меньше, чем перекрываемый. Это может приводить к
+% неожиданным результатам. ЕÑли Ð½Ð¾Ð²Ð°Ñ Ð²Ð¸Ð´Ð¸Ð¼Ð¾ÑÑ‚ÑŒ - private, то вызов inherited в новом клаÑÑе
+% потомка может вызывать метод Ñ Ð±Ð¾Ð»ÑŒÑˆÐµÐ¹ видимоÑтью в родительÑком клаÑÑе, Ð¸Ð³Ð½Ð¾Ñ€Ð¸Ñ€ÑƒÑ private метод.
+parser_e_field_not_allowed_here=03251_E_ÐŸÐ¾Ð»Ñ Ð½ÐµÐ»ÑŒÐ·Ñ Ð¾Ð±ÑŠÑвлÑÑ‚ÑŒ поÑле методов или ÑвойÑтв, Ñначала начните новую Ñекцию видимоÑти
+% ПоÑле объÑÐ²Ð»ÐµÐ½Ð¸Ñ Ð¼ÐµÑ‚Ð¾Ð´Ð° или ÑвойÑтва в клаÑÑе или объекте, дальнейшее объÑвление полей возможно
+% только в новой Ñекции облаÑти видимоÑти (\var{public}, \var{private} и Ñ‚.д.). Это необходимо
+% Ð´Ð»Ñ Ð¾Ð´Ð½Ð¾Ð·Ð½Ð°Ñ‡Ð½Ð¾Ð³Ð¾ Ð¿Ð¾Ð½Ð¸Ð¼Ð°Ð½Ð¸Ñ ÐºÐ¾Ð´Ð° компилÑтором, поÑкольку модификаторы методов,
+% такие как \var{default} и \var{register} могут также иÑпользоватьÑÑ ÐºÐ°Ðº имена полей.
+parser_e_no_local_para_def=03252_E_Параметры не могут Ñодержать локальные объÑÐ²Ð»ÐµÐ½Ð¸Ñ Ñ‚Ð¸Ð¿Ð¾Ð². ИÑпользуйте отдельное объÑвление типа в блоке type.
+% Ð’ ПаÑкале ÑемантичеÑки равнозначные типы не ÑчитаютÑÑ Ð¸Ð´ÐµÐ½Ñ‚Ð¸Ñ‡Ð½Ñ‹Ð¼Ð¸.
+% Переменные или параметры ÑчитаютÑÑ Ð¾Ð´Ð½Ð¾Ñ‚Ð¸Ð¿Ð½Ñ‹Ð¼Ð¸ только в том Ñлучае, еÑли они ÑÑылаютÑÑ Ð½Ð° одно и то же
+% объÑвление типа.
+% Как ÑледÑтвие, объÑвление типов в ÑпиÑке параметров не допуÑкаетÑÑ, Ñ‚.к. на локальное объÑвление невозможно
+% ÑоÑлатьÑÑ Ð¸Ð·Ð²Ð½Ðµ, и два заголовка процедуры в интерфейÑной и реализационной чаÑти Ð¼Ð¾Ð´ÑƒÐ»Ñ Ð¾Ð±ÑŠÑвлÑли бы
+% два различных типа. Имейте в виду, что Ð²Ñ‹Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ð²Ð¸Ð´Ð° ``file of byte'' или ``string[50]'' также определÑÑŽÑ‚
+% новый тип.
+% \end{description}
+#
+# Type Checking
+#
+# 04087 is the last used one
+#
+% \section{Ошибки проверки типов}
+% Ð’ разделе перечиÑлены вÑе ошибки, которые могут возникать в процеÑÑе
+% проверки типов.
+% \begin{description}
+type_e_mismatch=04000_E_Тип не Ñовпадает
+% Может иметь меÑто во многих ÑлучаÑÑ…:
+% \begin{itemize}
+% \item ПриÑÐ²Ð°Ð¸Ð²Ð°ÐµÐ¼Ð°Ñ Ð¿ÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ð°Ñ Ð¸Ð¼ÐµÐµÑ‚ тип, отличный от приÑваиваемого выражениÑ.
+% \item Вызов функции или процедуры Ñ Ð¿Ð°Ñ€Ð°Ð¼ÐµÑ‚Ñ€Ð°Ð¼Ð¸, неÑовмеÑтимыми
+% Ñ Ñ‚ÐµÐ¼Ð¸, которые были иÑпользованы при объÑвлении функции.
+% \end{itemize}
+type_e_incompatible_types=04001_E_HеÑовмеÑтимые типы: полyчено "$1", ожидалоÑÑŒ "$2"
+% Преобразование из одного типа в другой невозможно.
+% Также возможно, что типы объÑвлены в различных объÑвлениÑÑ…:
+% \begin{verbatim}
+% Var
+% A1 : Array[1..10] Of Integer;
+% A2 : Array[1..10] Of Integer;
+%
+% Begin
+% A1:=A2; { Приведет к ошибке из-за требованиÑ
+% Ñтрогого ÑоответÑÑ‚Ð²Ð¸Ñ Ñ‚Ð¸Ð¿Ð¾Ð² в ПаÑкале }
+% End.
+% \end{verbatim}
+type_e_not_equal_types=04002_E_HеÑовпадение типов междy "$1" и "$2"
+% Типы не равны
+type_e_type_id_expected=04003_E_ОжидаетÑÑ Ð¸Ð´ÐµÐ½Ñ‚Ñ„Ð¸ÐºÐ°Ñ‚Ð¾Ñ€ типа
+% Идентификатор не ÑвлÑетÑÑ Ñ‚Ð¸Ð¿Ð¾Ð¼, либо идентификатор типа пропущен.
+type_e_variable_id_expected=04004_E_ОжидаетÑÑ Ð¸Ð´ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ‚Ð¾Ñ€ переменной
+% ПроиÑходит при попытке передачи конÑтанты в процедуру \var{Inc} или \var{Dec}.
+% Им можно передавать только переменные.
+type_e_integer_expr_expected=04005_E_ОжидаетÑÑ Ð²Ñ‹pажение типа INTEGER, но получено "$1"
+% КомпилÑтор ожидает выражение типа integer, но получает нечто иное.
+type_e_boolean_expr_expected=04006_E_ОжидаетÑÑ Ð²Ñ‹Ñ€Ð°Ð¶ÐµÐ½Ð¸Ðµ типа BOOLEAN, но получено "$1"
+% Выражение должно быть булевого типа, должно быть возвращено true или
+% false.
+type_e_ordinal_expr_expected=04007_E_ОжидаетÑÑ Ð²Ñ‹pажение порÑдкового типа
+% Тип Ð²Ñ‹Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ð´Ð¾Ð»Ð¶ÐµÐ½ быть порÑдковым, Ñ‚.е., макÑимум \var{Longint}.
+% ПроиÑходит, например, еÑли второй аргумент
+% \var{Inc} или \var{Dec} не вычиÑлÑетÑÑ ÐºÐ°Ðº порÑдковый тип.
+type_e_pointer_type_expected=04008_E_ОжидаетÑÑ Ñ‚Ð¸Ð¿ POINTER, но получено "$1"
+% ÐŸÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ð°Ñ Ð¸Ð»Ð¸ выражение имеет тип, отличный от \var{pointer}. ПроиÑходит,
+% например, при передаче целой переменной в качеÑтве аргумента \var{New}
+% или \var{Dispose}.
+type_e_class_type_expected=04009_E_ОжидаетÑÑ Ñ‚Ð¸Ð¿ CLASS, но получено "$1"
+% ÐŸÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ð°Ñ Ð¸Ð»Ð¸ выражение имеет тип, отличный от \var{class}. Обычно
+% ÑлучаетÑÑ, еÑли
+% \begin{enumerate}
+% \item РодительÑкий клаÑÑ Ð² объÑвлении клаÑÑа не ÑвлÑетÑÑ ÐºÐ»Ð°ÑÑом.
+% \item Обработчик иÑключений (\var{On}) Ñодержит идентификатор типа,
+% не ÑвлÑющийÑÑ ÐºÐ»Ð°ÑÑом.
+% \end{enumerate}
+type_e_cant_eval_constant_expr=04011_E_Hевозможно вычиÑлить конÑтантное выражение
+% ПроиÑходит, еÑли границы объÑвленного маÑÑива не вычиÑлÑÑŽÑ‚ÑÑ ÐºÐ°Ðº порÑдковые конÑтанты.
+type_e_set_element_are_not_comp=04012_E_Элементы множеÑтва не ÑовмеÑтимы
+% Возникает при операции над Ð´Ð²ÑƒÐ¼Ñ Ð¼Ð½Ð¾Ð¶ÐµÑтвами, имеющими различный тип Ñлементов.
+% Ð”Ð»Ñ Ð¾Ð±ÑŠÐµÐ´Ð¸Ð½ÐµÐ½Ð¸Ñ Ð¼Ð½Ð¾Ð¶ÐµÑтв они должны иметь одинаковый базовый тип.
+type_e_set_operation_unknown=04013_E_ОпеpÐ°Ñ†Ð¸Ñ Ð½Ðµ pеализована Ð´Ð»Ñ Ð¼Ð½Ð¾Ð¶ÐµÑтв
+% Ðекоторые парные операции не определены Ð´Ð»Ñ Ð¼Ð½Ð¾Ð¶ÐµÑтв,
+% например, div mod ** (также, в наÑтоÑщее времÑ, >= <=).
+type_w_convert_real_2_comp=04014_W_ÐвтоматичеÑкое пpеобpазование из вещеÑтвенного типа в COMP, котоpый ÑвлÑетÑÑ Ñ†ÐµÐ»Ð¾Ñ‡Ð¸Ñленным
+% Ð’ÑтретилоÑÑŒ неÑвное преобразование вещеÑтвенного типа в \var{comp}.
+% ПоÑкольку \var{Comp} ÑвлÑетÑÑ 64-битным целым, Ñто может ÑвидетельÑтвовать об ошибке.
+type_h_use_div_for_int=04015_H_Ð”Ð»Ñ Ð¿Ð¾Ð»yÑ‡ÐµÐ½Ð¸Ñ Ñ†ÐµÐ»Ð¾Ñ‡Ð¸Ñленного pезyльтата иÑпользyйте DIV
+% При включенных подÑказках, Ñообщение будет выдаватьÑÑ Ð¿Ñ€Ð¸ целочиÑленном делении
+% Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ '/', поÑкольку результат в Ñтом Ñлучае будет вещеÑтвенным.
+type_e_strict_var_string_violation=04016_E_Типы Ñтрок не Ñовпадают из-за режима $V+
+% При компилÑции в режиме \var{\{\$V+\}}, тип Ñтрок, передаваемых как параметры,
+% должен в точноÑти Ñовпадать Ñ Ñ‚Ð¸Ð¿Ð¾Ð¼ в объÑвлении функции.
+type_e_succ_and_pred_enums_with_assign_not_possible=04017_E_SUCC или PRED невозможны на пеpечиÑлениÑÑ… Ñ Ð¿Ñ€Ð¸ÑвоениÑми
+% ЕÑли перечиÑлÑемый тип Ñодержит приÑвоениÑ, как в Ñзыке C,
+% например:
+% \begin{verbatim}
+% Tenum = (a,b,e:=5);
+% \end{verbatim}
+% то Ð´Ð»Ñ Ð½ÐµÐ³Ð¾ Ð½ÐµÐ»ÑŒÐ·Ñ Ð¸Ñпользовать функции \var{Succ} или \var{Pred}.
+type_e_cant_read_write_type=04018_E_Чтение и запиÑÑŒ пеpеменных Ñтого типа невозможна
+% Попытка Ñ‡Ñ‚ÐµÐ½Ð¸Ñ (\var{read}) или запиÑи (\var{write}) переменной, тип которой не
+% поддерживаетÑÑ, в файл типа текÑÑ‚. ПоддерживаютÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ целые,
+% булевы, вещеÑтвенные переменные, переменные типа pchar и Ñтроки.
+type_e_no_readln_writeln_for_typed_file=04019_E_Readln или Writeln недопуÑтимы на типизированном файле
+% \var{readln} и \var{writeln} допуÑкаютÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ Ð´Ð»Ñ Ñ‚ÐµÐºÑтовых файлов.
+type_e_no_read_write_for_untyped_file=04020_E_Read или Write недопуÑтимы на нетипизированном файле
+% \var{read} и \var{write} допуÑкаютÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ Ð´Ð»Ñ Ñ‚ÐµÐºÑтовых и типизированных файлов.
+type_e_typeconflict_in_set=04021_E_Конфликт типов междy Ñлементами множеÑтва
+% Тип по крайней мере одного Ñлемента не Ñовпадает Ñ Ð±Ð°Ð·Ð¾Ð²Ñ‹Ð¼ типом множеÑтва.
+type_w_maybe_wrong_hi_lo=04022_W_Lo/Hi(dword/qword) возвpащают младшее/Ñтаршее word/dword
+% \fpc поддерживает перегруженные варианты \var{lo/hi} Ð´Ð»Ñ \var{longint/dword/int64/qword},
+% которые возвращают младшую/Ñтаршую половину аргумента (типа word/dword). TP вÑегда иÑпользует
+% 16-битные \var{lo/hi}, которые вÑегда возвращают биты 0..7 Ð´Ð»Ñ \var{lo} и
+% биты 8..15 Ð´Ð»Ñ \var{hi}. ЕÑли требуетÑÑ Ð¿Ð¾Ð²ÐµÐ´ÐµÐ½Ð¸Ðµ TP, нужно привеÑти аргумент
+% к \var{word/integer}.
+type_e_integer_or_real_expr_expected=04023_E_ОжидаетÑÑ Ð²Ñ‹pажение целого или вещеÑтвенного типа
+% Первый аргумент \var{str} должен иметь целый либо вещеÑтвенный тип.
+type_e_wrong_type_in_array_constructor=04024_E_Hевеpный тип "$1" в конÑÑ‚pyктоpе маÑÑива
+% Попытка иÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð½ÐµÐ´Ð¾Ð¿ÑƒÑтимого типа в конÑтрукторе маÑÑива.
+type_e_wrong_parameter_type=04025_E_HеÑовпадение типа аpгyмента # $1: получено "$2", ожидалоÑÑŒ "$3"
+% Попытка передать неверный тип Ð´Ð»Ñ ÑƒÐºÐ°Ð·Ð°Ð½Ð½Ð¾Ð³Ð¾ параметра.
+type_e_no_method_and_procedure_not_compatible=04026_E_Метод (пеpеменнаÑ) и пpоцедypа (пеpеменнаÑ) не ÑовмеÑтимы
+% ÐÐµÐ»ÑŒÐ·Ñ Ð¿Ñ€Ð¸Ñвоить метод переменной типа процедура, или процедуру переменной типа
+% метод.
+type_e_wrong_math_argument=04027_E_ÐÐµÐ²ÐµÑ€Ð½Ð°Ñ ÐºÐ¾Ð½Ñтанта пеpедана вÑтроенной математичеÑкой Ñ„yнкции
+% КонÑтантный аргумент функции ln или sqrt находитÑÑ Ð²Ð½Ðµ определенного Ð´Ð»Ñ Ð½Ð¸Ñ…
+% диапазона.
+type_e_no_addr_of_constant=04028_E_HÐµÐ»ÑŒÐ·Ñ Ð²Ð·ÑÑ‚ÑŒ Ð°Ð´Ñ€ÐµÑ ÐºÐ¾Ð½Ñтантного выражениÑ
+% ВзÑÑ‚ÑŒ Ð°Ð´Ñ€ÐµÑ ÐºÐ¾Ð½Ñтантного Ð²Ñ‹Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ð½ÐµÐ²Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ð¾, потому что конÑтанты не
+% хранÑÑ‚ÑÑ Ð² памÑти. Можно попробовать объÑвить типизированную конÑтанту.
+type_e_argument_cant_be_assigned=04029_E_Ðргументу невозможно приÑвоить значение
+% Ð’ качеÑтве параметра по ÑÑылке могут быть переданы только те выражениÑ,
+% которые можно иÑпользовать Ñ Ð»ÐµÐ²Ð¾Ð¹ Ñтороны оператора приÑваиваниÑ.
+% ЗамечаниÑ: СвойÑтва можно иÑпользовать Ñ Ð»ÐµÐ²Ð¾Ð¹ Ñтороны приÑваиваниÑ, но
+% Ð½ÐµÐ»ÑŒÐ·Ñ Ð¿ÐµÑ€ÐµÐ´Ð°Ð²Ð°Ñ‚ÑŒ по ÑÑылке.
+type_e_cannot_local_proc_to_procvar=04030_E_Ð›Ð¾ÐºÐ°Ð»ÑŒÐ½Ð°Ñ Ð¿Ñ€Ð¾Ñ†ÐµÐ´ÑƒÑ€Ð° не может быть приÑвоена переменной процедурного типа
+% ПриÑвоение локальных процедур/функций процедурным переменным не допуÑкаетÑÑ,
+% Ñ‚.к. у них другой ÑпоÑоб вызова. Локальные процедуры/функции
+% можно приÑвоить только нетипизированному указателю.
+type_e_no_assign_to_addr=04031_E_HÐµÐ»ÑŒÐ·Ñ Ð¿Ñ€Ð¸Ñвоить значение адpеÑy
+% Ðе допуÑкаетÑÑ Ð¿Ñ€Ð¸Ñвоение значений адреÑам переменных, конÑтант, процедур
+% и функций. ЕÑли идентификатор ÑвлÑетÑÑ Ð¿Ñ€Ð¾Ñ†ÐµÐ´ÑƒÑ€Ð½Ð¾Ð¹ переменной, можно попробовать
+% компилÑцию Ñ ÐºÐ»ÑŽÑ‡Ð¾Ð¼ -So.
+type_e_no_assign_to_const=04032_E_HÐµÐ»ÑŒÐ·Ñ Ð¿Ñ€Ð¸Ñвоить значение конÑтанте
+% Ðе допуÑкаетÑÑ Ð¿Ñ€Ð¸Ñвоение значений переменным, объÑвленным как конÑтантные.
+% Как правило, Ñто параметры, объÑвленные как const. Чтобы их можно было
+% приÑваивать, поменÑйте их на var или на параметр-значение.
+type_e_array_required=04033_E_ТpебyетÑÑ Ñ‚Ð¸Ð¿ маÑÑива
+% При доÑтупе к переменной по индекÑу '[<x>]' тип Ñтой переменной должна быть
+% маÑÑивом. Ð’ режиме FPC также допуÑкаютÑÑ ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ»Ð¸.
+type_e_interface_type_expected=04034_E_ТребуетÑÑ Ñ‚Ð¸Ð¿ интерфейÑа, но получено "$1"
+% КомпилÑтор ожидал вÑтретить Ð¸Ð¼Ñ Ñ‚Ð¸Ð¿Ð° интерфейÑа, но вÑтретил что-то другое.
+% Ошибка может быть вызвана Ñледующим кодом:
+% \begin{verbatim}
+% Type
+% TMyStream = Class(TStream,Integer)
+% \end{verbatim}
+type_h_mixed_signed_unsigned=04035_H_Смешивание знаковых и беззнаковых выражений дает 64-битный результат
+% При делении (или вычиÑлении оÑтатка) знакового Ð²Ñ‹Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ð½Ð° беззнаковое (или наоборот),
+% или же включена проверка переполнений и/или диапазонов и иÑпользуетÑÑ Ð°Ñ€Ð¸Ñ„Ð¼ÐµÑ‚Ð¸Ñ‡ÐµÑкое
+% выражение (+, -, *, div, mod), в котором вÑтречаютÑÑ ÐºÐ°Ðº знаковые, так и беззнаковые значениÑ,
+% вычиÑление будет производитьÑÑ Ð² 64-битном режиме, который медленнее обычной
+% 32-битной арифметики. Этого можно избежать, Ð¿Ñ€Ð¸Ð²ÐµÐ´Ñ Ñ‚Ð¸Ð¿ одного из операндов к типу
+% другого.
+type_w_mixed_signed_unsigned2=04036_W_Смешивание знаковых и беззнаковых выражений типа может вызвать ошибку выхода за диапазон
+% При иÑпользовании двоичных операций (and, or, xor), один из операндов которых
+% ÑвлÑетÑÑ Ð±ÐµÐ·Ð·Ð½Ð°ÐºÐ¾Ð²Ñ‹Ð¼ выражением, а другой - выражением Ñо знаком, и включена
+% проверка диапазонов, может возникнуть ошибка, Ñ‚.к. в Ñтом Ñлучае оба операнда
+% будут преобразованы в беззнаковый cardinal. Этого можно избежать, Ð¿Ñ€Ð¸Ð²ÐµÐ´Ñ Ñ‚Ð¸Ð¿
+% одного из операндов к типу другого.
+type_e_typecast_wrong_size_for_assignment=04037_E_Приведение типов разного размера ($1 -> $2) в приÑваивании
+% Приведение типа к типу другого размера невозможно, еÑли Ð¿ÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ð°Ñ Ð¸ÑпользуетÑÑ
+% в приÑваивании.
+type_e_array_index_enums_with_assign_not_possible=04038_E_ПеречиÑÐ»ÐµÐ½Ð¸Ñ Ñ Ð¿Ñ€Ð¸ÑвоениÑми Ð½ÐµÐ»ÑŒÐ·Ñ Ð¸Ñпользовать как Ð¸Ð½Ð´ÐµÐºÑ Ð¼Ð°ÑÑива
+% Элементы перечиÑлÑемого типа, объÑвленного Ñ Ð¿Ñ€Ð¸ÑвоениÑми, как в Ñзыке C,
+% например:
+% \begin{verbatim}
+% Tenum = (a,b,e:=5);
+% \end{verbatim}
+% Ð½ÐµÐ»ÑŒÐ·Ñ Ð¸Ñпользовать как индекÑÑ‹ маÑÑивов.
+type_e_classes_not_related=04039_E_Типы клаÑÑов или объектов "$1" и "$2" не ÑоотноÑÑÑ‚ÑÑ
+% Приведение типа одного клаÑÑа или объекта к другому, не имеющего к нему отношениÑ.
+% Это навернÑка приведет к ошибкам.
+type_w_classes_not_related=04040_W_Типы клаÑÑов "$1" и "$2" не ÑоотноÑÑÑ‚ÑÑ
+% Приведение типа одного клаÑÑа или объекта к другому, не имеющего к нему отношениÑ.
+% Это навернÑка приведет к ошибкам.
+type_e_class_or_interface_type_expected=04041_E_ОжидаетÑÑ Ñ‚Ð¸Ð¿ клаÑÑа или интерфейÑа, но получено "$1"
+% КомпилÑтор ожидал вÑтретить Ð¸Ð¼Ñ ÐºÐ»Ð°ÑÑа или интерфейÑа, но вÑтретил что-то другое.
+type_e_type_is_not_completly_defined=04042_E_Тип "$1" не определен полноÑтью
+% Проиходит, еÑли тип не определен полноÑтью, например, Ñто тип указателÑ, который указывает
+% на неопределенный тип.
+type_w_string_too_long=04043_W_Строковый литерал Ñодержит больше Ñимволов, чем может вмеÑтить shortstring
+% Попытка приÑвоить короткой Ñтроке конÑтантное значение, которое Ñодержит больше Ñимволов,
+% чем макÑÐ¸Ð¼Ð°Ð»ÑŒÐ½Ð°Ñ Ð´Ð»Ð¸Ð½Ð° Ñтроки.
+type_w_signed_unsigned_always_false=04044_W_Сравнение вÑегда ложно из-за диапазонов значений
+% Сравнение беззнакового Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ñо знаковой конÑтантой, меньшей нулÑ. Результат такого выражениÑ
+% будет вÑегда ложным. Следует Ñвно привеÑти тип конÑтанты к нужному диапазону.
+type_w_signed_unsigned_always_true=04045_W_Сравнение вÑегда иÑтинно из-за диапазонов значений
+% Сравнение беззнакового Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ñо знаковой конÑтантой, меньшей нулÑ. Результат такого выражениÑ
+% будет вÑегда иÑтинным. Следует Ñвно привеÑти тип конÑтанты к нужному диапазону.
+type_w_instance_with_abstract=04046_W_Создание клаÑÑа "$1" Ñ Ð°Ð±Ñтрактным методом "$2"
+% СоздаетÑÑ ÑкземплÑÑ€ клаÑÑа, Ñодержащего неперекрытый абÑтрактный метод.
+% Вызов такого метода во Ð²Ñ€ÐµÐ¼Ñ Ð²Ñ‹Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð¼Ñ‹ приведет к ошибке 211.
+% Ð’Ñе абÑтрактные методы должны быть перекрыты.
+type_h_in_range_check=04047_H_Левый операнд оператора IN должен иметь размер байта
+% Левый операнд оператора \var{in} не ÑвлÑетÑÑ Ð¿Ð¾Ñ€Ñдковым или перечиÑлÑемым значением,
+% помещающимÑÑ Ð² 8 бит, Ñто может приводить к ошибкам проверки диапазона. Оператор \var{in}
+% в наÑтоÑщее Ð²Ñ€ÐµÐ¼Ñ Ð¿Ð¾Ð´Ð´ÐµÑ€Ð¶Ð¸Ð²Ð°ÐµÑ‚ левый операнд только байтового диапазона. Ð’ Ñлучае
+% перечиÑлений, размером Ñлементов перечиÑÐ»ÐµÐ½Ð¸Ñ Ð¼Ð¾Ð¶Ð½Ð¾ управлÑÑ‚ÑŒ Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ
+% ключей \var{\{\$PACKENUM\}} или \var{\{\$Zn\}}.
+type_w_smaller_possible_range_check=04048_W_ÐеÑовпадение размеров типов, возможна Ð¿Ð¾Ñ‚ÐµÑ€Ñ Ð´Ð°Ð½Ð½Ñ‹Ñ… / ошибки диапазона
+% ПриÑвоение типу меньшего размера, чем иÑходный тип. Это может приводить к ошибкам проверки
+% диапазона, или чаÑтичной потере данных.
+type_h_smaller_possible_range_check=04049_H_ÐеÑовпадение размеров типов, возможна Ð¿Ð¾Ñ‚ÐµÑ€Ñ Ð´Ð°Ð½Ð½Ñ‹Ñ… / ошибки диапазона
+% ПриÑвоение типу меньшего размера, чем иÑходный тип. Это может приводить к ошибкам проверки
+% диапазона, или чаÑтичной потере данных.
+type_e_cant_take_address_of_abstract_method=04050_E_ВзÑтие адреÑа абÑтрактного метода невозможно
+% ÐбÑтрактный метод не имеет тела, поÑтому Ð°Ð´Ñ€ÐµÑ Ð±Ñ€Ð°Ñ‚ÑŒ не от чего.
+type_e_assignment_not_allowed=04051_E_Ðевозможно приÑвоение формальных параметров и открытых маÑÑивов
+% Попытка приÑвоить значение формальному (нетипизированному var, const или out)
+% параметру, либо открытому маÑÑиву.
+type_e_constant_expr_expected=04052_E_ОжидаетÑÑ ÐºÐ¾Ð½Ñтантное выражение
+% КомпилÑтор ожидает конÑтантное выражение, но получает переменное.
+type_e_operator_not_supported_for_types=04053_E_ÐžÐ¿ÐµÑ€Ð°Ñ†Ð¸Ñ "$1" не поддерживаетÑÑ Ð´Ð»Ñ Ñ‚Ð¸Ð¿Ð¾Ð² "$2" и "$3"
+% Ð£ÐºÐ°Ð·Ð°Ð½Ð½Ð°Ñ Ð¾Ð¿ÐµÑ€Ð°Ñ†Ð¸Ñ Ð½ÐµÐ´Ð¾Ð¿ÑƒÑтима Ð´Ð»Ñ ÑƒÐºÐ°Ð·Ð°Ð½Ð½Ñ‹Ñ… типов.
+type_e_illegal_type_conversion=04054_E_ÐедопуÑтимое приведение типов: "$1" к "$2"
+% При приведении типов Ñледует Ñоблюдать равенÑтво размеров иÑточника и получателÑ.
+type_h_pointer_to_longint_conv_not_portable=04055_H_Преобразование между порÑдковыми типами и указателÑми ÑвлÑетÑÑ Ð½ÐµÐ¿Ð¾Ñ€Ñ‚Ð¸Ñ€ÑƒÐµÐ¼Ñ‹Ð¼
+% Код, в котором указатели приводÑÑ‚ÑÑ Ðº longint (или наоборот), не будет работать
+% на платформах, у которых размер ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ»Ñ Ñ€Ð°Ð²ÐµÐ½ 64 битам.
+type_w_pointer_to_longint_conv_not_portable=04056_W_Преобразование между порÑдковыми типами и указателÑми ÑвлÑетÑÑ Ð½ÐµÐ¿Ð¾Ñ€Ñ‚Ð¸Ñ€ÑƒÐµÐ¼Ñ‹Ð¼
+% Приведение указателей к порÑдковым типам другого размера (или наоборот), может
+% вызывать проблемы. Это предупреждение помогает находить Ñпецифичный 32-битный код, в котором
+% тип longint/cardinal иÑпользуетÑÑ Ð²Ð·Ð°Ð¸Ð¼Ð¾Ð·Ð°Ð¼ÐµÐ½Ñемо Ñ ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ»Ñми. Решение заключаетÑÑ Ð² иÑпользовании
+% типов ptrint/ptruint.
+type_e_cant_choose_overload_function=04057_E_Ðевозможно определить, которую из перегруженных функции вызывать
+% Вызов перегруженной функции Ñо ÑпиÑком параметров, который не ÑоответÑтвует ни
+% одной из объÑвленных функций. Ðапример, еÑли объÑвлены функции Ñ Ð¿Ð°Ñ€Ð°Ð¼ÐµÑ‚Ñ€Ð°Ð¼Ð¸
+% типа \var{word} и \var{longint}, а вызов производитÑÑ Ñ Ð¿Ð°Ñ€Ð°Ð¼ÐµÑ‚Ñ€Ð¾Ð¼ типа
+% \var{integer}.
+type_e_illegal_count_var=04058_E_ÐÐµÐ²ÐµÑ€Ð½Ð°Ñ Ð¿ÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ð°Ñ Ñчетчика
+% Тип переменной Ð´Ð»Ñ Ñ†Ð¸ÐºÐ»Ð° \var{for} должен быть порÑдковым.
+% ВещеÑтвенные и Ñтроковые типы не допуÑкаютÑÑ.
+type_w_double_c_varargs=04059_W_ВещеÑÑ‚Ð²ÐµÐ½Ð½Ð°Ñ ÐºÐ¾Ð½Ñтанта преобразована в double Ð´Ð»Ñ Ñ„-ции C Ñ Ð¿ÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ñ‹Ð¼ чиÑлом параметров
+% Ð’ Ñзыке C вещеÑтвенные конÑтанты по умолчанию имеют тип double. ПоÑтому при передаче
+% вещеÑтвенной конÑтанты в функцию на C Ñ Ð¿ÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ñ‹Ð¼ чиÑлом аргументов FPC
+% по умолчанию преобразует ее в double. ЕÑли Ñто поведение нежелательно,
+% приведите конÑтанту к нужному типу Ñвно.
+type_e_class_or_cominterface_type_expected=04060_E_ОжидаетÑÑ Ñ‚Ð¸Ð¿ клаÑÑа или COM-интерфейÑа, но получено "$1"
+% Ðекоторые операторы, такие как AS, применимы только к клаÑÑам или COM-интерфейÑам.
+type_e_no_const_packed_array=04061_E_КонÑтантные упакованные маÑÑивы пока не поддерживаютÑÑ
+% ÐÐµÐ»ÑŒÐ·Ñ Ð¾Ð±ÑŠÑвить конÑтанту типа (побитно)упакованный маÑÑив.
+type_e_got_expected_packed_array=04062_E_ÐеÑовпадение типа аргумента no. $1: Получено "$2" ожидалоÑÑŒ "(Bit)Packed Array"
+% КомпилÑтор ожидает (побитно)упакованный маÑÑив в качеÑтве указанного параметра.
+type_e_got_expected_unpacked_array=04063_E_ÐеÑовпадение типа аргумента no. $1: Получено "$2" ожидалоÑÑŒ "(not packed) Array"
+% КомпилÑтор ожидает обычный (неупакованный) маÑÑив в качеÑтве указанного параметра.
+type_e_no_packed_inittable=04064_E_Элементы упакованного маÑÑива не могут иметь тип, требующий инициализации
+% Упакованные маÑÑивы Ñ Ñ‚Ð¸Ð¿Ð°Ð¼Ð¸, требующими инициализацию (такими как ansistring, или запиÑи, Ñодержащие
+% ansistring), пока не поддерживаютÑÑ.
+type_e_no_const_packed_record=04065_E_КонÑтантные упакованные запиÑи и объекты пока не поддерживаютÑÑ
+% Ð’ наÑтоÑщее Ð²Ñ€ÐµÐ¼Ñ Ð½ÐµÐ»ÑŒÐ·Ñ Ð¾Ð±ÑŠÑвить конÑтанту типа (побитно)ÑƒÐ¿Ð°ÐºÐ¾Ð²Ð°Ð½Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ/объект.
+type_w_untyped_arithmetic_unportable=04066_W_Ðрифметика "$1" нетипизированных указателей неÑовмеÑтима Ñ Ñ€ÐµÐ¶Ð¸Ð¼Ð¾Ð¼ {$T+}, предлагаетÑÑ Ð¿Ñ€Ð¸Ð²ÐµÐ´ÐµÐ½Ð¸Ðµ типа
+% Сложение/вычитание нетипизированных указателей может работать по-другому в режиме \var{\{\$T+\}},
+% приведите тип к типизированному указателю.
+type_e_cant_take_address_of_local_subroutine=04076_E_ÐÐµÐ»ÑŒÐ·Ñ Ð²Ð·ÑÑ‚ÑŒ Ð°Ð´Ñ€ÐµÑ Ð¿Ñ€Ð¾Ñ†ÐµÐ´ÑƒÑ€Ñ‹, помеченной как локальнаÑ
+% ВзÑтие адреÑа процедуры, помеченной как локальнаÑ, невозможно.
+type_e_cant_export_local=04077_E_Процедура, Ð¾Ñ‚Ð¼ÐµÑ‡ÐµÐ½Ð½Ð°Ñ ÐºÐ°Ðº локальнаÑ, не может быть ÑкÑпортирована из модулÑ
+% Процедура, Ð¾Ñ‚Ð¼ÐµÑ‡ÐµÐ½Ð½Ð°Ñ ÐºÐ°Ðº локальнаÑ, не может быть ÑкÑпортирована из модулÑ.
+type_e_not_automatable=04078_E_Тип не автоматизируемый: "$1"
+% Ð’ качеÑтве автоматизированных допуÑкаютÑÑ byte, integer, longint, smallint, currency, single, double,
+% ansistring, widestring, tdatetime, variant, olevariant, wordbool и вÑе интерфейÑные типы.
+type_h_convert_add_operands_to_prevent_overflow=04079_H_Приведение операндов к "$1" перед Ñложением предотвратит ошибки переполнениÑ.
+% Сложение может вызывать переполнение. Т.к. результат преобразуетÑÑ Ð² тип большего размера,
+% Ð¿ÐµÑ€ÐµÐ¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð¼Ð¾Ð¶Ð½Ð¾ избежать, Ð¿Ñ€Ð¸Ð²ÐµÐ´Ñ Ð¾Ð¿ÐµÑ€Ð°Ð½Ð´Ñ‹ к типу результата перед Ñложением.
+type_h_convert_sub_operands_to_prevent_overflow=04080_H_Приведение операндов к "$1" перед вычитанием предотвратит ошибки переполнениÑ.
+% Вычитание может вызывать переполнение. Т.к. результат преобразуетÑÑ Ð² тип большего размера,
+% Ð¿ÐµÑ€ÐµÐ¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð¼Ð¾Ð¶Ð½Ð¾ избежать, Ð¿Ñ€Ð¸Ð²ÐµÐ´Ñ Ð¾Ð¿ÐµÑ€Ð°Ð½Ð´Ñ‹ к типу результата перед вычитанием.
+type_h_convert_mul_operands_to_prevent_overflow=04081_H_Приведение операндов к "$1" перед умножением предотвратит ошибки переполнениÑ.
+% Умножение может вызывать переполнение. Т.к. результат преобразуетÑÑ Ð² тип большего размера,
+% Ð¿ÐµÑ€ÐµÐ¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð¼Ð¾Ð¶Ð½Ð¾ избежать, Ð¿Ñ€Ð¸Ð²ÐµÐ´Ñ Ð¾Ð¿ÐµÑ€Ð°Ð½Ð´Ñ‹ к типу результата перед умножением.
+type_w_pointer_to_signed=04082_W_Приведение указателей к целым Ñо знаком может приводить к ошибкам ÑÑ€Ð°Ð²Ð½ÐµÐ½Ð¸Ñ Ð¸ выходу за диапазон, иÑпользуйте беззнаковый тип.
+% Виртуальное адреÑное проÑтранÑтво на 32-битных ÑиÑтемах имеет диапазон от \$00000000 до \$ffffffff.
+% Многие операционные ÑиÑтемы позволÑÑŽÑ‚ выделÑÑ‚ÑŒ памÑÑ‚ÑŒ Ñвыше \$80000000, например, Windows и Linux
+% допуÑкают указатели в диапазоне от \$0000000 до \$bfffffff. ЕÑли приводить указатели к знаковым типам,
+% могут возникать ошибки Ð¿ÐµÑ€ÐµÐ¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð¸ диапазона, кроме того, \$80000000 < \$7fffffff.
+% Это может вызывать Ñлучайные ошибки в коде наподобие "if p>q".
+type_interface_has_no_guid=04083_E_Тип интерфейÑа $1 не имеет GUID
+% При иÑпользовании оператора as нужный интерфейÑ, Ñ‚.е правый операнд оператора as,
+% должен иметь правильный GUID.
+type_e_invalid_objc_selector_name=04084_E_Ðеверное Ð¸Ð¼Ñ Ñелектора
+% Селектор Objective-C не может быть пуÑтым, он должен быть идентификатором либо одиночным двоеточием,
+% и, еÑли он Ñодержит двоеточие, то должен двоеточием и заканчиватьÑÑ.
+type_e_expected_objc_method_but_got=04085_E_ОжидаетÑÑ Ð¼ÐµÑ‚Ð¾Ð´ Objective-C, но получено $1
+% Селектор может быть Ñоздан только Ð´Ð»Ñ Ð¼ÐµÑ‚Ð¾Ð´Ð¾Ð² Objective-C, никакой другой тип
+% процедур/функций/методов не допуÑтим.
+type_e_expected_objc_method=04086_E_ОжидаетÑÑ Ð¼ÐµÑ‚Ð¾Ð´ Objective-C или конÑтантное Ð¸Ð¼Ñ Ð¼ÐµÑ‚Ð¾Ð´Ð°
+% Селектор может быть Ñоздан только Ð´Ð»Ñ Ð¼ÐµÑ‚Ð¾Ð´Ð¾Ð² Objective-C, либо путем ÑƒÐºÐ°Ð·Ð°Ð½Ð¸Ñ Ð¸Ð¼ÐµÐ½Ð¸
+% в виде Ñтроковой конÑтанты, либо Ñ Ð¸ÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¸Ð´ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ‚Ð¾Ñ€Ð° метода Objective-C,
+% дейÑтвительного в текущей облаÑти видимоÑти.
+type_e_no_type_info=04087_E_Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ типе недоÑтупна Ð´Ð»Ñ Ñтого типа
+% Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ типе не генерируетÑÑ Ð´Ð»Ñ Ð½ÐµÐºÐ¾Ñ‚Ð¾Ñ€Ñ‹Ñ… типов, таких как перечиÑÐ»ÐµÐ½Ð¸Ñ Ñ Ñ€Ð°Ð·Ñ€Ñ‹Ð²Ð°Ð¼Ð¸
+% в диапазоне значений (Ð²ÐºÐ»ÑŽÑ‡Ð°Ñ Ð¿ÐµÑ€ÐµÑ‡Ð¸ÑлениÑ, у которых нижнÑÑ Ð³Ñ€Ð°Ð½Ð¸Ñ†Ð° диапазона отличаетÑÑ Ð¾Ñ‚
+% нулÑ).
+type_e_ordinal_or_string_expr_expected=04088_E_ТребуетÑÑ Ð²Ñ‹Ñ€Ð°Ð¶ÐµÐ½Ð¸Ðµ порÑдкового или Ñтрокового типа
+% Выражение должно иметь порÑдковый или Ñтроковый тип.
+type_e_string_expr_expected=04089_E_ТребуетÑÑ Ñтроковое выражение
+% Выражение должно иметь Ñтроковый тип.
+% \end{description}
+#
+# Symtable
+#
+# 05064 is the last used one
+#
+% \section{Symbol handling}
+% Данный раздел Ñодержит ÑообщениÑ, отноÑÑщиеÑÑ Ðº обработке Ñимволов,
+% Ñ‚.е. вÑего, что ÑвÑзано Ñ Ð¸Ð¼ÐµÐ½Ð°Ð¼Ð¸ процедур и переменных.
+% \begin{description}
+sym_e_id_not_found=05000_E_Идентификатоp "$1" не найден
+% Данный Ñимвол неизвеÑтен компилÑтору. Обычно проиÑходит при ошибках напиÑаниÑ
+% имени переменной или процедуры, или еÑли вы забыли объÑвить
+% переменную.
+sym_f_internal_error_in_symtablestack=05001_F_ВнyÑ‚pеннÑÑ Ð¾ÑˆÐ¸Ð±ÐºÐ° в SymTableStack()
+% An internal error occurred in the compiler; If you encounter such an error,
+% please contact the developers and try to provide an exact description of
+% the circumstances in which the error occurs.
+sym_e_duplicate_id=05002_E_Идентификатоp "$1" повторÑетÑÑ
+% Указанный идентификатор уже был объÑвлен в текущей облаÑти.
+sym_h_duplicate_id_where=05003_H_Идентификатоp yже опpеделен в $1 (ÑÑ‚pока $2)
+% Идентификатор уже был объÑвлен в указанной облаÑти.
+sym_e_unknown_id=05004_E_HеизвеÑтный идентификатоp "$1"
+% Указанный идентификатор не был объÑвлен, либо иÑпользуетÑÑ Ð·Ð° пределами
+% облаÑти, Ð´Ð»Ñ ÐºÐ¾Ñ‚Ð¾Ñ€Ð¾Ð¹ он был определен.
+sym_e_forward_not_resolved=05005_E_ОтÑутÑтвует Ñ€ÐµÐ°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð¿Ñ€Ð¾Ñ†ÐµÐ´ÑƒÑ€Ñ‹ или метода "$1"
+% Может проиÑходить в двух ÑлучаÑÑ…:
+% \begin{itemize}
+% \item ЕÑли Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ Ð¾Ð±ÑŠÑвлена (в Ñекции \var{interface}, либо
+% Ñ Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¸Ð²Ð¾Ð¹ \var{forward}, но не реализована.
+% \item При ÑÑылке на тип, который не объÑвлен в текущем блоке \var{type}.
+% \end{itemize}
+sym_e_error_in_type_def=05007_E_Ошибка в опpеделении типа
+% Ошибка при определении нового типа маÑÑива:
+% \item Одна из границ диапазона ÑвлÑетÑÑ Ð¾ÑˆÐ¸Ð±Ð¾Ñ‡Ð½Ð¾Ð¹.
+% Ðапример, \var{Array [1..1.25]} вызовет данную ошибку.
+sym_e_forward_type_not_resolved=05009_E_Раннее объÑвление типа "$1" не решено
+% Символ был объÑвлен заранее, но определение Ð´Ð»Ñ Ð½ÐµÐ³Ð¾ не было обнаружено.
+sym_e_only_static_in_static=05010_E_Только ÑтатичеÑкие переменные могут иÑпользоватьÑÑ Ð² ÑтатичеÑких методах или вне методов
+% СтатичеÑкий метод объекта имеет доÑтуп только к ÑтатичеÑким переменным.
+sym_f_type_must_be_rec_or_class=05012_F_ОжидаетÑÑ Ñ‚Ð¸Ð¿ record или class
+% ÐŸÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ð°Ñ Ð¸Ð»Ð¸ выражение имеет тип, отличный от \var{record} или \var{class}.
+sym_e_no_instance_of_abstract_object=05013_E_ЭкземплÑры клаÑÑов или объектов Ñ Ð°Ð±ÑÑ‚pактным методом не допуÑкаютÑÑ
+% Попытка Ñоздать ÑкземплÑÑ€ клаÑÑа Ñ Ð°Ð±Ñтрактным методом, который не был перекрыт.
+sym_w_label_not_defined=05014_W_Метка "$1" не опpеделена
+% Метка была объÑвлена, но не была определена.
+sym_e_label_used_and_not_defined=05015_E_Метка "$1" иÑпользуетÑÑ, но не определена
+% Метка была объÑвлена и иÑпользована, но не была определена.
+sym_e_ill_label_decl=05016_E_Hевеpное объÑвление метки
+% ПроиÑходит, еÑли метка объÑвлена вне процедуры или функции; Ñтого никогда
+% не должно ÑлучатьÑÑ.
+sym_e_goto_and_label_not_supported=05017_E_GOTO и LABEL не поддеpживаютÑÑ (иÑпользyйте ключ -Sg)
+% Программу, Ñодержащую метки и переходы \var{goto}, необходимо компилировать
+% Ñ ÐºÐ»ÑŽÑ‡Ð¾Ð¼ \var{-Sg}. По умолчанию, метки и переходы не поддерживаютÑÑ.
+sym_e_label_not_found=05018_E_Метка не найдена
+% Ð’ÑтретилоÑÑŒ \var{goto label}, но метка не была объÑвлена.
+sym_e_id_is_no_label_id=05019_E_Идентификатоp не ÑвлÑетÑÑ Ð¼ÐµÑ‚ÐºÐ¾Ð¹
+% Идентификатор, Ñледующий за \var{goto}, не имеет тип метки.
+sym_e_label_already_defined=05020_E_Повтоpное опpеделение метки
+% Попытка определить метку дважды. Метка может быть определена только один раз.
+sym_e_ill_type_decl_set=05021_E_Ðевеpное объÑвление типа Ñлементов множеÑтва
+% ОбъÑвление множеÑтва Ñодержит недопуÑтимое определение типа.
+sym_e_class_forward_not_resolved=05022_E_Ранее объÑвление клаÑÑа "$1" не решено
+% КлаÑÑ Ð±Ñ‹Ð» объÑвлен, но не был реализован.
+sym_n_unit_not_used=05023_H_Модуль "$1" не иÑпользуетÑÑ Ð² $2
+% Модуль, указанный в Ñекции \var{uses}, не иÑпользуетÑÑ.
+sym_h_para_identifier_not_used=05024_H_Паpаметp "$1" не иÑпользyетÑÑ
+% Идентификатор был объÑвлен (локально или глобально), но
+% не был иÑпользован.
+sym_n_local_identifier_not_used=05025_N_Ð›Ð¾ÐºÐ°Ð»ÑŒÐ½Ð°Ñ Ð¿ÐµpÐµÐ¼ÐµÐ½Ð½Ð°Ñ "$1" не иÑпользyетÑÑ
+% ÐŸÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ð°Ñ Ð¾Ð±ÑŠÑвлена, но не иÑпользована в реализации процедуры
+% или функции.
+sym_h_para_identifier_only_set=05026_H_Параметр-значение "$1" приÑвоен, но не иÑпользован
+% Параметру приÑвоено значение, которое в дальнейшем нигде не иÑпользуетÑÑ.
+sym_n_local_identifier_only_set=05027_N_Ð›Ð¾ÐºÐ°Ð»ÑŒÐ½Ð°Ñ Ð¿ÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ð°Ñ "$1" приÑвоена, но не иÑпользована
+% Локальной переменной приÑвоено значение, которое в дальнейшем нигде не иÑпользуетÑÑ.
+sym_h_local_symbol_not_used=05028_H_Локальный Ñимвол $1 "$2" не иÑпользуетÑÑ
+% Локальный Ñимвол не иÑпользуетÑÑ.
+sym_n_private_identifier_not_used=05029_N_Private поле "$1.$2" не иÑпользуетÑÑ
+% Указанное private поле определено, но не иÑпользуетÑÑ Ð½Ð¸Ð³Ð´Ðµ в коде.
+sym_n_private_identifier_only_set=05030_N_Private поле "$1.$2" приÑвоено, но не иÑпользовано
+% Указанное private поле определено и ему приÑвоено значение, которое нигде не читаетÑÑ.
+sym_n_private_method_not_used=05031_N_Private метод "$1.$2" не иÑпользуетÑÑ
+% Указанный private метод определен, но не иÑпользуетÑÑ Ð½Ð¸Ð³Ð´Ðµ в коде.
+sym_e_set_expected=05032_E_ОжидаетÑÑ Ñ‚Ð¸Ð¿ множеÑтва
+% ÐŸÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ð°Ñ Ð¸Ð»Ð¸ выражение имеет тип, отличный от \var{set}. Это ÑлучаетÑÑ Ð²
+% выражениÑÑ… \var{in}.
+sym_w_function_result_not_set=05033_W_Резyльтат Ñ„yнкции, возможно, не приÑвоен
+% Предупреждение выдаетÑÑ, еÑли компилÑтор полагает, что результат, возвращаемый функцией,
+% не приÑвоен. ЕÑли Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ Ð½Ð°Ð¿Ð¸Ñана на аÑÑемблере, или Ñодержит аÑÑемблерный блок,
+% предупреждение не выдаетÑÑ.
+sym_w_wrong_C_pack=05034_W_Тип "$1" некорректно выровнен в текущей запиÑи Ð´Ð»Ñ Ñзыка C
+% МаÑÑивы Ñ Ñ€Ð°Ð·Ð¼ÐµÑ€Ð°Ð¼Ð¸, не кратными 4, будут неверно выровнены в Ñтруктурах Ñзыка C.
+sym_e_illegal_field=05035_E_HеизвеÑтное поле запиÑи "$1"
+% Указанное поле отÑутÑтвует в определении запиÑи.
+sym_w_uninitialized_local_variable=05036_W_Ð›Ð¾ÐºÐ°Ð»ÑŒÐ½Ð°Ñ Ð¿ÐµpÐµÐ¼ÐµÐ½Ð½Ð°Ñ "$1" не инициализиpована
+% Сообщение выдаетÑÑ, когда компилÑтор Ñчитает, что Ð»Ð¾ÐºÐ°Ð»ÑŒÐ½Ð°Ñ Ð¿ÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ð°Ñ Ð±ÑƒÐ´ÐµÑ‚
+% иÑпользована (Ñ‚.е. вÑтретилаÑÑŒ в правой чаÑти выражениÑ), но не была
+% инициализирована (Ñ‚.е. не поÑвлÑлаÑÑŒ ранее в левой чаÑти приÑваиваниÑ).
+sym_w_uninitialized_variable=05037_W_ПеpÐµÐ¼ÐµÐ½Ð½Ð°Ñ "$1" не инициализиpована
+% Сообщение выдаетÑÑ, когда компилÑтор Ñчитает, что Ð¿ÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ð°Ñ Ð±ÑƒÐ´ÐµÑ‚ иÑпользована
+% (Ñ‚.е. вÑтретилаÑÑŒ в правой чаÑти выражениÑ), но не была инициализирована (Ñ‚.е.
+% не поÑвлÑлаÑÑŒ ранее в левой чаÑти приÑваиваниÑ).
+sym_e_id_no_member=05038_E_Идентификатоp не определÑет Ñлемент "$1"
+% Сообщение выдаетÑÑ Ð¿Ñ€Ð¸ попытке доÑтупа к неопределенному полю запиÑи
+% или объекта, либо методу.
+sym_h_param_list=05039_H_Hайдено опpеделение: $1
+% При иÑпользовании ключа \var{-vh}, еÑли не найдена Ð¿ÐµÑ€ÐµÐ³Ñ€ÑƒÐ¶ÐµÐ½Ð½Ð°Ñ Ð¿Ñ€Ð¾Ñ†ÐµÐ´ÑƒÑ€Ð°,
+% перечиÑлÑÑŽÑ‚ÑÑ Ð²Ñе подходÑщие перегруженные процедуры и ÑпиÑки их
+% параметров.
+sym_e_segment_too_large=05040_E_Слишком большой Ñлемент данных
+% ВыдаетÑÑ Ð¿Ñ€Ð¸ попытке объÑвить Ñлемент данных, размер которого превышает
+% уÑтановленный предел (2 ГБ Ð´Ð»Ñ Ð¿Ñ€Ð¾Ñ†ÐµÑÑоров 80386+/68020+)
+sym_e_no_matching_implementation_found=05042_E_Ðе найдена подходÑÑ‰Ð°Ñ Ñ€ÐµÐ°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð¼ÐµÑ‚Ð¾Ð´Ð° интерфейÑа "$1"
+% Ðе найден метод, который мог бы реализовать указанный метод интерфейÑа.
+% Проверьте типы аргументов и типы возвращаемых значений.
+sym_w_deprecated_symbol=05043_W_Символ "$1" уÑтарел
+% ИÑпользован Ñимвол (переменнаÑ, процедура и Ñ‚.п.), который был
+% объÑвлен как \var{deprecated}. Такой уÑтаревший Ñимвол может быть
+% недоÑтупен в новых верÑиÑÑ… Ð¼Ð¾Ð´ÑƒÐ»Ñ / библиотеки. По возможноÑти,
+% нужно избегать иÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ ÑƒÑтаревших Ñимволов.
+sym_w_non_portable_symbol=05044_W_Символ "$1" не портабелен
+% ИÑпользован Ñимвол (переменнаÑ, процедура и Ñ‚.п.), который был
+% объÑвлен как \var{platform}. Значение, иÑпользование и доÑтупноÑÑ‚ÑŒ
+% такого Ñимвола завиÑит от платформы. ЕÑли иÑходный код должен быть
+% портируемым, иÑпользовать такие Ñимволы не Ñледует.
+sym_w_non_implemented_symbol=05055_W_Символ "$1" не реализован
+% ИÑпользован Ñимвол (переменнаÑ, процедура и Ñ‚.п.), который был
+% объÑвлен как \var{unimplemented}. Этот Ñимвол определен,
+% но еще не реализован Ð´Ð»Ñ Ð´Ð°Ð½Ð½Ð¾Ð¹ платформы.
+sym_e_cant_create_unique_type=05056_E_Этот тип Ð½ÐµÐ»ÑŒÐ·Ñ Ð¸Ñпользовать Ð´Ð»Ñ Ð¾Ð±ÑŠÑÐ²Ð»ÐµÐ½Ð¸Ñ ÑƒÐ½Ð¸ÐºÐ°Ð»ÑŒÐ½Ð¾Ð³Ð¾ типа
+% При объÑвлении уникального типа Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ Ð²Ñ‹Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ \var{type newtype = type oldtype;}
+% можно иÑпользовать только проÑтые типы (порÑдковые, вещеÑтвенные и Ñтроковые).
+sym_h_uninitialized_local_variable=05057_H_Ð›Ð¾ÐºÐ°Ð»ÑŒÐ½Ð°Ñ Ð¿ÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ð°Ñ "$1" не инициализирована
+% Сообщение выдаетÑÑ, когда компилÑтор Ñчитает, что Ð»Ð¾ÐºÐ°Ð»ÑŒÐ½Ð°Ñ Ð¿ÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ð°Ñ Ð±ÑƒÐ´ÐµÑ‚
+% иÑпользована (Ñ‚.е. вÑтретилаÑÑŒ в правой чаÑти выражениÑ), но не была
+% инициализирована (Ñ‚.е. не поÑвлÑлаÑÑŒ ранее в левой чаÑти приÑваиваниÑ).
+sym_h_uninitialized_variable=05058_H_ÐŸÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ð°Ñ "$1" не инициализирована
+% Сообщение выдаетÑÑ, когда компилÑтор Ñчитает, что Ð¿ÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ð°Ñ Ð±ÑƒÐ´ÐµÑ‚
+% иÑпользована (Ñ‚.е. вÑтретилаÑÑŒ в правой чаÑти выражениÑ), но не была
+% инициализирована (Ñ‚.е. не поÑвлÑлаÑÑŒ ранее в левой чаÑти приÑваиваниÑ).
+sym_w_function_result_uninitialized=05059_W_ÐŸÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ð°Ñ Ñ€ÐµÐ·ÑƒÐ»ÑŒÑ‚Ð°Ñ‚Ð° функции не инициализирована
+% Сообщение выдаетÑÑ, когда компилÑтор Ñчитает, что Ð¿ÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ð°Ñ Ñ€ÐµÐ·ÑƒÐ»ÑŒÑ‚Ð°Ñ‚Ð°
+% функции будет иÑпользована (Ñ‚.е. вÑтретилаÑÑŒ в правой чаÑти выражениÑ),
+% но не была инициализирована (Ñ‚.е. не поÑвлÑлаÑÑŒ ранее в левой чаÑти
+% приÑваиваниÑ).
+sym_h_function_result_uninitialized=05060_H_ÐŸÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ð°Ñ Ñ€ÐµÐ·ÑƒÐ»ÑŒÑ‚Ð°Ñ‚Ð° функции не инициализирована
+% Сообщение выдаетÑÑ, когда компилÑтор Ñчитает, что Ð¿ÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ð°Ñ Ñ€ÐµÐ·ÑƒÐ»ÑŒÑ‚Ð°Ñ‚Ð°
+% функции будет иÑпользована (Ñ‚.е. вÑтретилаÑÑŒ в правой чаÑти выражениÑ),
+% но не была инициализирована (Ñ‚.е. не поÑвлÑлаÑÑŒ ранее в левой чаÑти
+% приÑваиваниÑ).
+sym_w_identifier_only_read=05061_W_ÐŸÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ð°Ñ "$1" читаетÑÑ, но не приÑвоена
+% Значение переменной ÑчитываетÑÑ, но нигде не приÑваиваетÑÑ.
+sym_h_abstract_method_list=05062_H_Ðайден абÑтрактный метод: $1
+% При выдаче Ð¿Ñ€ÐµÐ´ÑƒÐ¿Ñ€ÐµÐ¶Ð´ÐµÐ½Ð¸Ñ Ð¾ Ñоздании клаÑÑа/объекта Ñ Ð°Ð±Ñтрактными методами
+% Ñта подÑказка облегчает поиÑк проблемного метода.
+sym_w_experimental_symbol=05063_W_Символ "$1" ÑвлÑетÑÑ ÑкÑпериментальным
+% ИÑпользован Ñимвол (переменнаÑ, процедура и Ñ‚.п.), который был
+% объÑвлен как \var{experimental}. ЭкÑпериментальные Ñимволы могут
+% иÑчезнуть или изменить поведение в будущей верÑии. ИÑпользованиÑ
+% таких Ñимволов Ñледует по возможноÑти избегать.
+sym_w_forward_not_resolved=05064_W_Ранее объÑвление "$1" не разрешилоÑÑŒ, предполагаетÑÑ external
+% ПроиÑходит, еÑли Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ Ð±Ñ‹Ð»Ð° объÑвлена в Ñекции \var{interface} Ð¼Ð¾Ð´ÑƒÐ»Ñ Ð² режиме macpas,
+% но не была реализована.
+% \end{description}
+
+#
+# Кодогенератор
+#
+# 06049 номер поÑледнего ÑообщениÑ
+#
+% \section{Code generator messages}
+% Раздел Ñодержит ÑообщениÑ, которые могут быть выданы при ошибках
+% кодогенерации.
+% \begin{description}
+cg_e_parasize_too_big=06009_E_Размеp ÑпиÑка паpаметpов пpевышает 65535 байт
+% ПроцеÑÑор I386 ограничивает ÑпиÑок параметров до 65535 байт (из-за оÑобенноÑти
+% инÑтрукции \var{RET})
+cg_e_file_must_call_by_reference=06012_E_Файловые типы Ñледует передавать по ÑÑылке
+% Файлы Ð½ÐµÐ»ÑŒÐ·Ñ Ð¿ÐµÑ€ÐµÐ´Ð°Ð²Ð°Ñ‚ÑŒ по значению, Ñ‚.е. они вÑегда должны быть объÑвлены
+% как \var{var} параметры.
+cg_e_cant_use_far_pointer_there=06013_E_ИÑпользование FAR yÐºÐ°Ð·Ð°Ñ‚ÐµÐ»Ñ Ð·Ð´ÐµÑÑŒ недопуÑтимо
+% Free Pascal не поддерживает дальние указатели, поÑтому невозможно взÑÑ‚ÑŒ адреÑ
+% выражениÑ, в результате которого получитÑÑ Ð´Ð°Ð»ÑŒÐ½Ð¸Ð¹ указатель. КонÑÑ‚Ñ€ÑƒÐºÑ†Ð¸Ñ \var{mem}
+% ÑвлÑетÑÑ Ð¿Ñ€Ð¸Ð¼ÐµÑ€Ð¾Ð¼ такого выражениÑ, поÑтому Ñледующий код вызовет данную ошибку:
+% \begin{verbatim}
+% var p : pointer;
+% ...
+% p:=@mem[a000:000];
+% \end{verbatim}
+cg_e_dont_call_exported_direct=06015_E_Вызов EXPORT функции невозможен
+% Больше не иÑпользуетÑÑ.
+cg_w_member_cd_call_from_method=06016_W_Возможно, неверный вызов конÑÑ‚pyктоpа или деÑÑ‚pyктоpа
+% Обнаружен вызов конÑтруктора или деÑтруктора из метода. Это, Ñкорее вÑего, приведет к
+% проблемам, Ñ‚.к. Ð´Ð»Ñ ÐºÐ¾Ð½Ñтрукторов/деÑтрукторов требуютÑÑ Ð¾Ñобые параметры.
+cg_n_inefficient_code=06017_N_HеÑффективный код
+% ÐапиÑÐ°Ð½Ð½Ð°Ñ Ð²Ð°Ð¼Ð¸ конÑÑ‚Ñ€ÑƒÐºÑ†Ð¸Ñ ÐºÐ°Ð¶ÐµÑ‚ÑÑ ÐºÐ¾Ð¼Ð¿Ð¸Ð»Ñтору очень Ñомнительной.
+cg_w_unreachable_code=06018_W_HедоÑтижимый код
+% ÐапиÑÐ°Ð½Ð½Ð°Ñ ÐºÐ¾Ð½ÑÑ‚Ñ€ÑƒÐºÑ†Ð¸Ñ Ð½Ð¸ÐºÐ¾Ð³Ð´Ð° не будет выполнена. Пример:
+% \begin{verbatim}
+% while false do
+% begin
+% {.. code ...}
+% end;
+% \end{verbatim}
+cg_e_cant_call_abstract_method=06020_E_ÐбÑÑ‚pактные методы Ð½ÐµÐ»ÑŒÐ·Ñ Ð²Ñ‹Ð·Ñ‹Ð²Ð°Ñ‚ÑŒ напpÑмyÑŽ
+% ÐбÑтрактный метод Ð½ÐµÐ»ÑŒÐ·Ñ Ð²Ñ‹Ð·Ð²Ð°Ñ‚ÑŒ непоÑредÑтвенно, вмеÑто него Ñледует вызывать
+% перекрывающий метод потомка, потому что абÑтрактный метод не имеет реализации.
+cg_d_register_weight=06027_DL_РегиÑÑ‚p $1 Ð²ÐµÑ $2 $3
+% Отладочное Ñообщение. ВыводитÑÑ, когда компилÑтор раÑÑматривает возможноÑÑ‚ÑŒ
+% Ñ€Ð°Ð·Ð¼ÐµÑ‰ÐµÐ½Ð¸Ñ Ð¿ÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ñ‹Ñ… в региÑтрах.
+cg_d_stackframe_omited=06029_DL_Кадр Ñтека не Ñоздан (не требуетÑÑ)
+% Ðекоторым процедурам/функциÑм не требуетÑÑ Ð¿Ð¾Ð»Ð½Ñ‹Ð¹ кадр Ñтека, и его можно опуÑтить.
+% Сообщение выводитÑÑ Ð¿Ñ€Ð¸ иÑпользовании ключа \var{-vd}.
+cg_e_unable_inline_object_methods=06031_E_Методы объектах или клаÑÑов не могут быть вÑтраиваемыми (inline)
+% Методы объекта Ð½ÐµÐ»ÑŒÐ·Ñ Ð²Ñтраивать.
+cg_e_unable_inline_procvar=06032_E_Вызовы процедурных переменных не могуг быть вÑтраиваемыми (inline)
+% Вызов процедурной переменной не может быть вÑтроен.
+cg_e_no_code_for_inline_stored=06033_E_Hет кода Ð´Ð»Ñ inline
+% КомпилÑтор не Ñмог Ñохранить код Ð´Ð»Ñ Ð²Ñтраиваемой процедуры.
+cg_e_can_access_element_zero=06035_E_Hyлевой Ñлемент ansi/wide- ÑÑ‚pоки недоÑÑ‚yпен, иÑпользyйте (set)length
+% Ð”Ð»Ñ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð´Ð»Ð¸Ð½Ñ‹ Ñтроки типа ansi/wide/longstring Ñледует иÑпользовать
+% процедуру \var{setlength}, а Ð´Ð»Ñ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ - функцию \var{length}.
+cg_e_cannot_call_cons_dest_inside_with=06037_E_КонÑÑ‚pyктоp или деÑÑ‚pyктоp Ð½ÐµÐ»ÑŒÐ·Ñ Ð²Ñ‹Ð·Ñ‹Ð²Ð°Ñ‚ÑŒ внyÑ‚pи выражений 'WITH'
+% Внутри конÑтрукции \var{With} вызов конÑтруктора или деÑтруктора Ð´Ð»Ñ Ð¾Ð±ÑŠÐµÐºÑ‚Ð°-аргумента
+% \var{with} невозможен.
+cg_e_cannot_call_message_direct=06038_E_HепоÑредÑтвенный вызов метода-обpаботчика Ñобытий невозможен
+% A message method handler method can't be called directly if it contains an
+% explicit self argument
+cg_e_goto_inout_of_exception_block=06039_E_Переход через границу блока иÑключений
+% Переход внутрь блока обработки иÑключений \var{try..finally..end;} или из него не допуÑкаетÑÑ:
+% \begin{verbatim}
+% label 1;
+%
+% ...
+%
+% try
+% if not(final) then
+% goto 1; // в Ñтой Ñтроке будет ошибка
+% finally
+% ...
+% end;
+% 1:
+% ...
+% \end{verbatim}
+cg_e_control_flow_outside_finally=06040_E_УправлÑющие Ð²Ñ‹Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ (break, continue и exit) недопуÑтимы в блоке finally
+% ИÑпользование выражений, изменÑющих ход Ð²Ñ‹Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ (\var{break},
+% \var{continue} и \var{exit}), не допуÑкаетÑÑ
+% внутри блока finally. Следующий код вызовет ошибку:
+% \begin{verbatim}
+% ...
+% try
+% p;
+% finally
+% ...
+% exit; // Этот exit недопуÑтим
+% end;
+% ...
+%
+% \end{verbatim}
+% ЕÑли при выполнении процедура \var{p} проиÑходит иÑключение, выполнÑетÑÑ Ð±Ð»Ð¾Ðº
+% finally. ЕÑли выполнение доходит до exit, непонÑтно что делать:
+% выходить из процедури или иÑкать другой обработчик иÑключений.
+cg_w_parasize_too_big=06041_W_Размер параметров превышает предел Ð´Ð»Ñ Ð½ÐµÐºÐ¾Ñ‚Ð¾Ñ€Ñ‹Ñ… процеÑÑоров
+% Означает, что было объÑвлено более 64 кБайт параметров, что
+% может не поддерживатьÑÑ Ð¿Ñ€Ð¸ компилÑции Ð´Ð»Ñ Ð´Ñ€ÑƒÐ³Ð¸Ñ… платформ.
+cg_w_localsize_too_big=06042_W_Размер локальных переменных превышает предел Ð´Ð»Ñ Ð½ÐµÐºÐ¾Ñ‚Ð¾Ñ€Ñ‹Ñ… процеÑÑоров
+% Означает, что было объÑвлено более 32 кБайт локальных переменных, что
+% может не поддерживатьÑÑ Ð¿Ñ€Ð¸ компилÑции Ð´Ð»Ñ Ð´Ñ€ÑƒÐ³Ð¸Ñ… платформ.
+cg_e_localsize_too_big=06043_E_Размер локальных переменных превышает допуÑтимый предел
+% Означает, что объÑвлено более 32 кБайт локальных переменных, что
+% не поддерживаетÑÑ Ð´Ð»Ñ Ð´Ð°Ð½Ð½Ð¾Ð³Ð¾ процеÑÑора.
+cg_e_break_not_allowed=06044_E_BREAK недопуÑтимо
+% Попытка иÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ \var{break} вне конÑтрукции цикла.
+cg_e_continue_not_allowed=06045_E_CONTINUE недопуÑтимо
+% Попытка иÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ \var{continue} вне конÑтрукции цикла.
+cg_f_unknown_compilerproc=06046_F_ÐеизвеÑÑ‚Ð½Ð°Ñ Ð²Ð½ÑƒÑ‚Ñ€ÐµÐ½Ð½ÑÑ Ð¿Ñ€Ð¾Ñ†ÐµÐ´ÑƒÑ€Ð° "$1". Проверьте верÑию библиотеки RTL.
+% КомпилÑтор ожидает, что библиотека времени Ð²Ñ‹Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ (RTL) Ñодержит определенные процедуры. ЕÑли
+% вы видите Ñто Ñообщение, не занимаÑÑÑŒ ÑамоÑтоÑтельной модификацией кода библиотеки RTL, то, Ñкорее
+% вÑего, иÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÐµÐ¼Ð°Ñ Ð±Ð¸Ð±Ð»Ð¸Ð¾Ñ‚ÐµÐºÐ° RTL не ÑоответÑтвует компилÑтору. ЕÑли же вы модифицировали RTL, значит,
+% вы удалили процедуру, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð½ÑƒÐ¶Ð½Ð° компилÑтору Ð´Ð»Ñ Ð²Ð½ÑƒÑ‚Ñ€ÐµÐ½Ð½ÐµÐ³Ð¾ иÑпользованиÑ.
+cg_f_unknown_system_type=06047_F_Ðе найден ÑиÑтемный тип "$1". Проверьте верÑию библиотеки RTL.
+% КомпилÑтор ожидает, что библиотека времени Ð²Ñ‹Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ (RTL) Ñодержит определенные объÑвлениÑ
+% типов. ЕÑли вы видите Ñто Ñообщение, не занимаÑÑÑŒ ÑамоÑтоÑтельной модификацией кода библиотеки RTL, то,
+% Ñкорее вÑего, иÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÐµÐ¼Ð°Ñ Ð±Ð¸Ð±Ð»Ð¸Ð¾Ñ‚ÐµÐºÐ° RTL не ÑоответÑтвует компилÑтору. ЕÑли же вы модифицировали RTL,
+% значит, вы удалили тип, нужный компилÑтору Ð´Ð»Ñ Ð²Ð½ÑƒÑ‚Ñ€ÐµÐ½Ð½ÐµÐ³Ð¾ иÑпользованиÑ.
+cg_h_inherited_ignored=06048_H_Вызов абÑтрактного метода поÑредÑтвом inherited игнорирован
+% Сообщение выдаетÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ в режиме Delphi, при попытке вызвать абÑтрактный метод
+% родительÑкого клаÑÑа Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ \var{inherited;}. Такой вызов игнорируетÑÑ.
+cg_e_goto_label_not_found=06049_E_Метка "$1" не определена или удалена оптимизацией
+% Метка, иÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð½Ð°Ñ Ð² goto, не определена либо была удалена при удалении
+% недоÑтупного кода.
+% \end{description}
+# EndOfTeX
+
+#
+# Assembler reader
+#
+# 07107 is the last used one
+#
+asmr_d_start_reading=07000_DL_Hачало Ñ‡Ñ‚ÐµÐ½Ð¸Ñ Ð°ÑÑемблеpа типа $1
+% Информирует о начале Ñ‡Ñ‚ÐµÐ½Ð¸Ñ Ð°ÑÑемблерного блока.
+asmr_d_finish_reading=07001_DL_Конец Ñ‡Ñ‚ÐµÐ½Ð¸Ñ Ð°ÑÑемблеpа типа $1
+% Информирует о завершении Ñ‡Ñ‚ÐµÐ½Ð¸Ñ Ð°ÑÑемблерного блока.
+asmr_e_none_label_contain_at=07002_E_Токен, не ÑвлÑющийÑÑ Ð¼ÐµÑ‚ÐºÐ¾Ð¹, Ñодеpжит @
+% Идентификатор, не ÑвлÑющийÑÑ Ð¼ÐµÑ‚ÐºÐ¾Ð¹, не может Ñодержать Ñимвол @.
+asmr_e_building_record_offset=07004_E_Ошибка поÑÑ‚pÐ¾ÐµÐ½Ð¸Ñ ÑÐ¼ÐµÑ‰ÐµÐ½Ð¸Ñ Ð² запиÑи
+% Ошибка вычиÑÐ»ÐµÐ½Ð¸Ñ ÑÐ¼ÐµÑ‰ÐµÐ½Ð¸Ñ Ð² запиÑи/объекте, может проиÑходить, еÑли
+% поле не указано вообще или иÑпользован неизвеÑтный идентификатор полÑ.
+asmr_e_offset_without_identifier=07005_E_ИÑпользование OFFSET без идентификатоpа
+% Ключевое Ñлово OFFSET можно иÑпользовать только ÑовмеÑтно Ñ Ð¸Ð´ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ‚Ð¾Ñ€Ð¾Ð¼.
+% Другие ÑинтакÑиÑÑ‹ не поддерживаютÑÑ.
+asmr_e_type_without_identifier=07006_E_ИÑпользование TYPE без идентификатоpа
+% Ключевое Ñлово TYPE можно иÑпользовать только ÑовмеÑтно Ñ Ð¸Ð´ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ‚Ð¾Ñ€Ð¾Ð¼.
+% Другие ÑинтакÑиÑÑ‹ не поддерживаютÑÑ.
+asmr_e_no_local_or_para_allowed=07007_E_ЗдеÑÑŒ Ð½ÐµÐ»ÑŒÐ·Ñ Ð¸Ñпользовать локальные пеpеменные или паpаметpÑ‹
+% Локальные переменные и параметры обычно адреÑуютÑÑ ÐºÐ°Ðº Ñмещение от региÑтра
+% %ebp, поÑтому их Ð°Ð´Ñ€ÐµÑ Ð½Ðµ может быть получен непоÑредÑтвенно.
+asmr_e_need_offset=07008_E_ЗдеÑÑŒ необходимо иÑпользовать OFFSET
+% Ð”Ð»Ñ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð°Ð´Ñ€ÐµÑа данного идентификатора необходимо иÑпользовать OFFSET <id>.
+asmr_e_need_dollar=07009_E_ЗдеÑÑŒ необходимо иÑпользовать знак доллара ('$')
+% Ð”Ð»Ñ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð°Ð´Ñ€ÐµÑа данного иденификатора необходимо иÑпользовать $<id>.
+asmr_e_cant_have_multiple_relocatable_symbols=07010_E_Hе допуÑкаютÑÑ Ð¼Ð½Ð¾Ð¶ÐµÑтвенные пеpемещаемые Ñимволы
+% Ðе допуÑкаетÑÑ Ð±Ð¾Ð»ÐµÐµ одного перемещаемого Ñимвола (переменнаÑ/Ñ‚Ð¸Ð¿Ð¸Ð·Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð½Ð°Ñ ÐºÐ¾Ð½Ñтанта)
+% в одном аргументе.
+asmr_e_only_add_relocatable_symbol=07011_E_Пеpемещаемый Ñимвол допуÑкает только Ñложение
+% Перемещаемые Ñимволы (переменные/типизированные конÑтанты) не могут быть иÑпользованы Ñ Ð´Ñ€ÑƒÐ³Ð¸Ð¼Ð¸
+% операторами. ДопуÑкаетÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ Ñложение.
+asmr_e_invalid_constant_expression=07012_E_Hеверное конÑтантное выpажение
+% Ошибка в конÑтантном выражении.
+asmr_e_relocatable_symbol_not_allowed=07013_E_Пеpемещаемый Ñимвол здеÑÑŒ не pазpешен
+% Ð’ данном меÑте не может быть иÑпользован перемещаемый Ñимвол (переменнаÑ/Ñ‚Ð¸Ð¿Ð¸Ð·Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð½Ð°Ñ ÐºÐ¾Ð½Ñтанта).
+asmr_e_invalid_reference_syntax=07014_E_Hевеpный ÑинтакÑÐ¸Ñ ÑÑылки
+% СинтакÑичеÑÐºÐ°Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ° в запиÑи ÑÑылки.
+asmr_e_local_para_unreachable=07015_E_$1 недоÑтупно из Ñтого кода
+% Во вложенной процедуре невозможен прÑмой доÑтуп к значенÑм локальных переменных или параметров
+% внешней процедуры (кроме ÑлучаÑ, когда Ð²Ð»Ð¾Ð¶ÐµÐ½Ð½Ð°Ñ Ð¿Ñ€Ð¾Ñ†ÐµÐ´ÑƒÑ€Ð° Ñама не имеет параметров и локальных
+% переменных).
+asmr_e_local_label_not_allowed_as_ref=07016_E_Локальные Ñимволы или метки Ð½ÐµÐ»ÑŒÐ·Ñ Ð¸Ñпользовать как ÑÑылки
+% Ð’Ñ‹ не можете иÑпользовать локальные Ñимволы или метки как ÑÑылки
+asmr_e_wrong_base_index=07017_E_Hевеpное иÑпользование региÑтров базы и индекÑа
+% Ошибка при иÑпользовании региÑтров базы и индекÑа
+asmr_w_possible_object_field_bug=07018_W_Ð’Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ð°Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ° в обработке Ð¿Ð¾Ð»Ñ Ð¾Ð±ÑŠÐµÐºÑ‚Ð°
+% ÐŸÐ¾Ð»Ñ ÐºÐ»Ð°ÑÑов/объектов недоÑтупны напрÑмую в режимах fpc и objfpc,
+% но в режимах TP и Delphi имена полей обрабатываютÑÑ ÐºÐ°Ðº обычные ÑмещениÑ.
+asmr_e_wrong_scale_factor=07019_E_Hевеpный множитель
+% Указан неверный множитель, разрешены только Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ 1,2,4 и 8
+asmr_e_multiple_index=07020_E_МножеÑтвенное иÑпользование индекÑного pегиÑÑ‚pа
+% Попытка иÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð±Ð¾Ð»ÐµÐµ чем одного индекÑного региÑтра.
+asmr_e_invalid_operand_type=07021_E_Hевеpный тип опеpанда
+% Тип операнда не ÑоответÑтвует коду команды.
+asmr_e_invalid_string_as_opcode_operand=07022_E_Стpока непригодна в качеÑтве опеpанда инÑтрукции: $1
+% Строка, ÑƒÐºÐ°Ð·Ð°Ð½Ð½Ð°Ñ ÐºÐ°Ðº операнд, некорректна Ð´Ð»Ñ Ð´Ð°Ð½Ð½Ð¾Ð¹ команды.
+asmr_w_CODE_and_DATA_not_supported=07023_W_@CODE и @DATA не поддеpживаютÑÑ
+% @CODE и @DATA не поддерживаютÑÑ Ð¸ игнорируютÑÑ.
+asmr_e_null_label_ref_not_allowed=07024_E_СÑылки на безымÑнные метки не допуÑкаютÑÑ
+asmr_e_expr_zero_divide=07025_E_Деление на ноль в выражении аÑÑемблера
+% Ð’ конÑтантном выражении ÑодержитÑÑ Ð´ÐµÐ»ÐµÐ½Ð¸Ðµ на ноль
+asmr_e_expr_illegal=07026_E_Ðеверное выражение
+% КонÑтантное выражение неверно
+asmr_e_escape_seq_ignored=07027_E_Escape-поÑледовательноÑÑ‚ÑŒ игноpиpована: $1
+% Ð’ Ñтроке ÑÑ‚Ð¸Ð»Ñ Ñзыка C ÑодержитÑÑ Ð½ÐµÐ¸Ð·Ð²ÐµÑÑ‚Ð½Ð°Ñ escape-поÑледовательноÑÑ‚ÑŒ,
+% ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð¸Ð³Ð½Ð¾Ñ€Ð¸Ñ€ÑƒÐµÑ‚ÑÑ.
+asmr_e_invalid_symbol_ref=07028_E_HевеpÐ½Ð°Ñ ÑÑылка на Ñимвол
+asmr_w_fwait_emu_prob=07029_W_FWAIT может вызвать пpоблемы ÑмyлÑции Ñ EMU387
+asmr_w_fadd_to_faddp=07030_W_$1 без операнда транÑлируетÑÑ Ð² $1P
+asmr_w_enter_not_supported_by_linux=07031_W_ИнÑÑ‚Ñ€ÑƒÐºÑ†Ð¸Ñ ENTER не поддерживаетÑÑ Ñдром Linux
+% ИнÑÑ‚Ñ€ÑƒÐºÑ†Ð¸Ñ ENTER может привеÑти к ошибке защиты Ñтраницы Ñтека, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð½ÐµÐºÐ¾Ñ€Ñ€ÐµÐºÑ‚Ð½Ð¾
+% "ловитÑÑ" обработчиком в i386 Linux.
+asmr_w_calling_overload_func=07032_W_Вызов пеpегpyженной Ñ„yнкции в аÑÑемблеpе
+% Вызов перегруженной функции из аÑÑемблерного блока,
+% как правило, ÑвлÑетÑÑ Ð¿Ñ€Ð¸Ð·Ð½Ð°ÐºÐ¾Ð¼ проблемы.
+asmr_e_unsupported_symbol_type=07033_E_Hе поддеpживаемый тип Ñимвола Ð´Ð»Ñ Ð¾Ð¿Ðµpанда
+asmr_e_constant_out_of_bounds=07034_E_Значение конÑтанты вне диапазона
+asmr_e_error_converting_decimal=07035_E_"$1" не ÑвлÑетÑÑ Ð´ÐµÑÑтичным чиÑлом
+% Ðеверный ÑинтакÑÐ¸Ñ Ð´ÐµÑÑтичного чиÑла.
+asmr_e_error_converting_octal=07036_E_"$1" не ÑвлÑетÑÑ Ð²Ð¾Ñьмеpичным чиÑлом
+% Ðеверный ÑинтакÑÐ¸Ñ Ð²Ð¾Ñьмеричного чиÑла.
+asmr_e_error_converting_binary=07037_E_"$1" не ÑвлÑетÑÑ Ð´Ð²Ð¾Ð¸Ñ‡Ð½Ñ‹Ð¼ чиÑлом
+% Ðеверный ÑинтакÑÐ¸Ñ Ð´Ð²Ð¾Ð¸Ñ‡Ð½Ð¾Ð³Ð¾ чиÑла.
+asmr_e_error_converting_hexadecimal=07038_E_"$1" не ÑвлÑетÑÑ ÑˆÐµÑтнадцатеpичным чиÑлом
+% Ðеверный ÑинтакÑÐ¸Ñ ÑˆÐµÑтнадцатеричного чиÑла.
+asmr_h_direct_global_to_mangled=07039_H_$1 пpеобpазовано в $2
+asmr_w_direct_global_is_overloaded_func=07040_W_$1 ÑвÑзано Ñ Ð¿Ðµpегpyженной Ñ„yнкцией
+asmr_e_cannot_use_SELF_outside_a_method=07041_E_Hе допуÑкаетÑÑ Ð¸Ñпользование SELF вне метода
+% ÐедопуÑÑ‚Ð¸Ð¼Ð°Ñ ÑÑылка на Ñимвол \var{self}.
+% Ðа \var{self} можно ÑÑылатьÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ в методах.
+asmr_e_cannot_use_OLDEBP_outside_nested_procedure=07042_E_Hе допуÑкаетÑÑ Ð¸Ñпользование OLDEBP вне вложенной пpоцедypÑ‹
+% ÐедопуÑÑ‚Ð¸Ð¼Ð°Ñ ÑÑылка на Ñимвол \var{oldebp}.
+% Ðа \var{oldebp} можно ÑÑылатьÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ во вложенных процедурах.
+asmr_e_void_function=07043_W_Проецедуры не могут возвpащать Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð¸Ð· аÑÑемблерного кода
+% Попытка вернуть значение из процедуры. Процедура не может возвращать значениÑ.
+asmr_e_SEG_not_supported=07044_E_SEG не поддеpживаетÑÑ
+asmr_e_size_suffix_and_dest_dont_match=07045_E_СyÑ„Ñ„Ð¸ÐºÑ pазмеpа не ÑоответÑтвует размеру операндов
+% Размер региÑтра и ÑÑƒÑ„Ñ„Ð¸ÐºÑ Ñ€Ð°Ð·Ð¼ÐµÑ€Ð° в коде команды не ÑоответÑвуют. Скорее вÑего,
+% команда аÑÑемблера запиÑана Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ¾Ð¹.
+asmr_w_size_suffix_and_dest_dont_match=07046_W_СyÑ„Ñ„Ð¸ÐºÑ pазмеpа не ÑоответÑтвует размеру операндов
+% Размер региÑтра и ÑÑƒÑ„Ñ„Ð¸ÐºÑ Ñ€Ð°Ð·Ð¼ÐµÑ€Ð° в коде команды не ÑоответÑвуют. Скорее вÑего,
+% команда аÑÑемблера запиÑана Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ¾Ð¹.
+asmr_e_syntax_error=07047_E_СинтакÑичеÑÐºÐ°Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ° аÑÑемблера
+% СинтакÑичеÑÐºÐ°Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ° аÑÑемблера
+asmr_e_invalid_opcode_and_operand=07048_E_HевеpÐ½Ð°Ñ ÐºÐ¾Ð¼Ð±Ð¸Ð½Ð°Ñ†Ð¸Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ‹ и опеpандов
+% Ð”Ð°Ð½Ð½Ð°Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ð° не может иметь операнды данного типа.
+asmr_e_syn_operand=07049_E_СинтакÑичеÑÐºÐ°Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ° аÑÑемблера в опеpанде
+asmr_e_syn_constant=07050_E_СинтакÑичеÑÐºÐ°Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ° аÑÑемблера в конÑтанте
+asmr_e_invalid_string_expression=07051_E_Hевеpное ÑÑ‚pоковое выpажение
+asmr_w_const32bit_for_address=07052_W_конÑтанта Ñ Ñимволом $1 Ð´Ð»Ñ Ð°Ð´Ñ€ÐµÑа, размер которого отличаетÑÑ Ð¾Ñ‚ указателÑ
+% КонÑтантное выражение, предÑтавлÑющее адреÑ, не умещаетÑÑ Ð² диапазон указателÑ.
+% ÐдреÑ, Ñкорее вÑего, неверен.
+asmr_e_unknown_opcode=07053_E_ÐеизвеÑтный код операции $1
+% ÐеизвеÑÑ‚Ð½Ð°Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ð° аÑÑемблера
+asmr_e_invalid_or_missing_opcode=07054_E_HевеpÐ½Ð°Ñ Ð¸Ð»Ð¸ пpопyÑ‰ÐµÐ½Ð½Ð°Ñ Ð¾Ð¿ÐµÑ€Ð°Ñ†Ð¸Ñ
+asmr_e_invalid_prefix_and_opcode=07055_E_HевеpÐ½Ð°Ñ ÐºÐ¾Ð¼Ð±Ð¸Ð½Ð°Ñ†Ð¸Ñ Ð¿pефикÑа и операции: $1
+asmr_e_invalid_override_and_opcode=07056_E_HевеpÐ½Ð°Ñ ÐºÐ¾Ð¼Ð±Ð¸Ð½Ð°Ñ†Ð¸Ñ Ð¿ÐµpеопpÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ Ð¸ операции: $1
+asmr_e_too_many_operands=07057_E_Слишком много опеpандов в ÑÑ‚pоке
+% Слишком много операндов Ð´Ð»Ñ Ð´Ð°Ð½Ð½Ð¾Ð¹ команды. Проверьте ÑинтакÑиÑ.
+asmr_w_near_ignored=07058_W_Директива NEAR игноpиpована
+asmr_w_far_ignored=07059_W_Директива FAR игноpиpована
+asmr_e_dup_local_sym=07060_E_Повтоpное опpеделение локального Ñимвола $1
+asmr_e_unknown_local_sym=07061_E_HеизвеÑтный локальный Ñимвол $1
+asmr_e_unknown_label_identifier=07062_E_HеизвеÑÑ‚Ð½Ð°Ñ Ð¼ÐµÑ‚ÐºÐ° $1
+asmr_e_invalid_register=07063_E_Ðеверное Ð¸Ð¼Ñ Ñ€ÐµÐ³Ð¸Ñтра
+% There is an unknown register name used as operand.
+asmr_e_invalid_fpu_register=07064_E_Hеверное Ð¸Ð¼Ñ pегиÑÑ‚pа Ð´Ð»Ñ Ð¾Ð¿Ðµpации Ñ Ð¿Ð»Ð°Ð²Ð°ÑŽÑ‰ÐµÐ¹ запÑтой
+% Было иÑпользовано неизвеÑтное Ð¸Ð¼Ñ Ñ€ÐµÐ³Ð¸Ñтра.
+asmr_w_modulo_not_supported=07066_W_MODULO не поддеpживаетÑÑ
+asmr_e_invalid_float_const=07067_E_HевеpÐ½Ð°Ñ Ð²ÐµÑ‰ÐµÑÑ‚Ð²ÐµÐ½Ð½Ð°Ñ ÐºÐ¾Ð½Ñтанта $1
+% КонÑтанта Ñ Ð¿Ð»Ð°Ð²Ð°ÑŽÑ‰ÐµÐ¹ запÑтой, объÑÐ²Ð»ÐµÐ½Ð½Ð°Ñ Ð² аÑÑемблерном блоке, неверна.
+asmr_e_invalid_float_expr=07068_E_Hевеpное вещеÑтвенное выpажение
+% Выражение Ñ Ð¿Ð»Ð°Ð²Ð°ÑŽÑ‰ÐµÐ¹ запÑтой, объÑвленное в аÑÑемблерном блоке, неверно.
+asmr_e_wrong_sym_type=07069_E_Hевеpный тип Ñимвола
+asmr_e_cannot_index_relative_var=07070_E_HÐµÐ»ÑŒÐ·Ñ Ð¸Ð½Ð´ÐµÐºÑиpовать локальнyÑŽ пеpеменнyÑŽ или паpаметp Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ pегиÑÑ‚pа
+% Базовый региÑÑ‚Ñ€ иÑпользуетÑÑ Ð´Ð»Ñ Ð¸Ð½Ð´ÐµÐºÑации Ñимвола, который уже ÑвлÑетÑÑ Ð¾Ñ‚Ð½Ð¾Ñительным
+% по отношению к региÑтру. Это невозможно, и навернÑка приведет к ошибке при выполнении.
+asmr_e_invalid_seg_override=07071_E_Hевеpное выpажение пеpеопpÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ Ñегмента
+asmr_w_id_supposed_external=07072_W_Идентификатоp $1, пpедположительно, внешний
+% СÑылка не неопределенный Ñимвол.Это не ÑвлÑетÑÑ Ð¾ÑˆÐ¸Ð±ÐºÐ¾Ð¹,
+% Ñ‚.к. Ñимвол может иметь внешнее определение, но может привеÑти к проблемам
+% при компоновке, еÑли Ñимвол не был определен где-нибудь еще.
+asmr_e_string_not_allowed_as_const=07073_E_HÐµÐ»ÑŒÐ·Ñ Ð¸Ñпользовать ÑÑ‚pоки как конÑтанты
+% Строки Ñимволов Ð½ÐµÐ»ÑŒÐ·Ñ Ð¸Ñпользовать в качеÑтве конÑтант.
+asmr_e_no_var_type_specified=07074_Ðе указан тип пеpеменной
+% СинтакÑÐ¸Ñ Ð¿Ñ€ÐµÐ´Ð¿Ð¾Ð»Ð°Ð³Ð°ÐµÑ‚ Ð¸Ð¼Ñ Ñ‚Ð¸Ð¿Ð° поÑле точки, но оно не было обнаружено.
+asmr_w_assembler_code_not_returned_to_text=07075_E_ÐÑÑемблеpный код не возвpащаетÑÑ Ð² Ñегмент TEXT
+% Ð’ аÑÑемблерном блоке была директива Ñмены Ñекций, но в конце блока отÑутÑтвует директива
+% возврата в Ñегмент текÑта. Может быть причиной ошибок при компоновке.
+asmr_e_not_directive_or_local_symbol=07076_E_$1 не ÑвлÑетÑÑ Ð´Ð¸pективой или локальным Ñимволом
+% Указанный Ñимвол неизвеÑтен.
+asmr_w_using_defined_as_local=07077_E_ИÑпользование опpеделенного имени в качеÑтве локальной метки
+asmr_e_dollar_without_identifier=07078_E_Символ '$' иÑпользyетÑÑ Ð±ÐµÐ· идентификатоpа
+% Ð’ конÑтантном выражении вÑтретилÑÑ Ð¸Ð´ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ‚Ð¾Ñ€, не начинающийÑÑ Ñ Ñимвола $.
+asmr_w_32bit_const_for_address=07079_W_32-Ð±Ð¸Ñ‚Ð½Ð°Ñ ÐºÐ¾Ð½Ñтанта иÑпользована Ð´Ð»Ñ Ð°Ð´pеÑа
+% КонÑтанта иÑпользована в качеÑтве адреÑа. Это ÑвлÑетÑÑ Ð¿Ñ€Ð¸Ð·Ð½Ð°ÐºÐ¾Ð¼ ошибки,
+% поÑкольку абÑÐ¾Ð»ÑŽÑ‚Ð½Ð°Ñ Ð°Ð´Ñ€ÐµÑÐ°Ñ†Ð¸Ñ Ð¾Ð±Ñ‹Ñ‡Ð½Ð¾ не работает.
+asmr_n_align_is_target_specific=07080_N_.ALIGN ÑвлÑетÑÑ Ð¿Ð»Ð°Ñ‚Ñ„Ð¾Ñ€Ð¼ÐµÐ½Ð½Ð¾-завиÑимой, иÑпользyйте .BALIGN или .P2ALIGN
+% ДейÑтвие и значение директивы .align может изменÑÑ‚ÑŒÑÑ Ð² завиÑимоÑти от
+% целевой платформы.
+asmr_e_cannot_access_field_directly_for_parameters=07081_E_ÐŸÐ¾Ð»Ñ Ð¿Ð°pаметpа недоÑтупны напpÑмyÑŽ, иÑпользyйте pегиÑÑ‚pÑ‹
+% Параметр Ñледует загрузить в региÑÑ‚Ñ€ и затем адреÑовать Ð¿Ð¾Ð»Ñ Ð¿Ð°Ñ€Ð°Ð¼ÐµÑ‚Ñ€Ð° отноÑительно
+% Ñтого региÑтра.
+asmr_e_cannot_access_object_field_directly=07082_E_ÐŸÐ¾Ð»Ñ Ð¾Ð±ÑŠÐµÐºÑ‚Ð¾Ð²/клаÑÑов недоÑтупны напpÑмyÑŽ, иÑпользyйте pегиÑÑ‚pÑ‹
+% Следует загрузить указатель на self в региÑÑ‚Ñ€ и затем адреÑовать полÑ, иÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ Ñ€ÐµÐ³Ð¸ÑÑ‚Ñ€
+% в качеÑтве базы. По умолчанию указатель на self доÑтупен
+% в региÑтре esi на i386.
+asmr_e_unable_to_determine_reference_size=07083_E_Размеp операндов не указан и его определение невозможно
+% Размер ÑÑылки Ñледует указать Ñвно, Ñ‚.к. компилÑтор не может
+% определить, какой размер (byte,word,dword и т.д.) он
+% должен иÑпользовать.
+asmr_e_cannot_use_RESULT_here=07084_E_Ð’ Ñтой функции иÑпользовать RESULT нельзÑ
+% Ðекоторые функции, возвращающие результат Ñложного типа, не могут иÑпользовать переменную
+% \var{result}.
+asmr_w_adding_explicit_args_fXX=07086_W_"$1" без операнда транÑлируетÑÑ Ð² "$1 %st,%st(1)"
+asmr_w_adding_explicit_first_arg_fXX=07087_W_"$1 %st(n)" транÑлируетÑÑ Ð² "$1 %st,%st(n)"
+asmr_w_adding_explicit_second_arg_fXX=07088_W_"$1 %st(n)" транÑлируетÑÑ Ð² "$1 %st(n),%st"
+asmr_e_invalid_char_smaller=07089_E_Символ < здеÑÑŒ не разрешен
+% Оператор Ñдвига требует Ñимволов <<. Был обнаружен только один из них.
+asmr_e_invalid_char_greater=07090_E_Символ > здеÑÑŒ не разрешен
+% Оператор Ñдвига требует Ñимволов >>. Был обнаружен только один из них.
+asmr_w_align_not_supported=07093_W_ALIGN не поддерживаетÑÑ
+asmr_e_no_inc_and_dec_together=07094_E_Inc и Dec не могут иÑпользоватьÑÑ Ð¾Ð´Ð½Ð¾Ð²Ñ€ÐµÐ¼ÐµÐ½Ð½Ð¾
+% Одновременное иÑпользование инкремента и декремента в одном операнде
+% на 680x0. Это недопуÑтимо.
+asmr_e_invalid_reg_list_in_movem=07095_E_Ðеверный ÑпиÑок региÑтров Ð´Ð»Ñ movem
+% ИÑпользование инÑтрукции \var{movem} Ñ Ð½ÐµÐ²ÐµÑ€Ð½Ñ‹Ð¼Ð¸ региÑтрами Ð´Ð»Ñ ÑохранениÑ/воÑÑтановлениÑ.
+asmr_e_invalid_reg_list_for_opcode=07096_E_Ðеверный ÑпиÑок региÑтров Ð´Ð»Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ‹
+asmr_e_higher_cpu_mode_required=07097_E_ТребуетÑÑ Ñ€ÐµÐ¶Ð¸Ð¼ более Ñовременного процеÑÑора ($1)
+% ИÑпользование инÑтрукции, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð½Ðµ поддерживаетÑÑ Ð² текущем режиме процеÑÑора.
+% ИÑпользуйте режим Ð´Ð»Ñ Ñледующих поколений процеÑÑоров.
+asmr_w_unable_to_determine_reference_size_using_dword=07098_W_Размер операндов не указан и его не удаетÑÑ Ð¾Ð¿Ñ€ÐµÐ´ÐµÐ»Ð¸Ñ‚ÑŒ, иÑпользуетÑÑ DWORD по умолчанию
+% Размер ÑÑылки Ñледует указать Ñвно, Ñ‚.к. компилÑтор не может
+% определить, какой размер (byte,word,dword и т.д.) он
+% должен иÑпользовать. ВыдаетÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ в режиме Delphi, когда
+% по умолчанию иÑпользуетÑÑ Ñ€Ð°Ð·Ð¼ÐµÑ€ DWORD.
+asmr_e_illegal_shifterop_syntax=07099_E_СинтакÑичеÑÐºÐ°Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ° в операнде Ñдвига
+% Только ARM; аÑÑемблер ARM поддерживает Ñ‚.н. операнд Ñдвига. ИÑпользованный Ð´Ð»Ñ Ð½ÐµÐ³Ð¾ ÑинтакÑиÑ
+% неверен. Пример инÑтрукции Ñ Ð¾Ð¿ÐµÑ€Ð°Ð½Ð´Ð¾Ð¼ Ñдвига:
+% \begin{verbatim}
+% asm
+% orr r2,r2,r2,lsl #8
+% end;
+% \end{verbatim}
+asmr_e_packed_element=07100_E_ÐÐ´Ñ€ÐµÑ ÑƒÐ¿Ð°ÐºÐ¾Ð²Ð°Ð½Ð½Ð¾Ð³Ð¾ компонента не Ñовпадает Ñ Ð³Ñ€Ð°Ð½Ð¸Ñ†ÐµÐ¹ байта
+% Упакованные компоненты (Ð¿Ð¾Ð»Ñ Ð·Ð°Ð¿Ð¸Ñей и Ñлементы маÑÑивов) могут начинатьÑÑ
+% Ñ Ð¿Ñ€Ð¾Ð¸Ð·Ð²Ð¾Ð»ÑŒÐ½Ð¾Ð³Ð¾ бита в байте. Следовательно, на процеÑÑоре, не поддерживающего
+% битовую адреÑацию памÑти (а вÑе поддерживаемые FPC процеÑÑоры ÑвлÑÑŽÑ‚ÑÑ Ð¸Ð¼ÐµÐ½Ð½Ð¾ такими),
+% будет выдана ошибка при попытке доÑтупа по индекÑу к маÑÑивам, размер Ñлемента которых
+% не кратен 8 битам. Это Ñправедливо и Ð´Ð»Ñ Ð¿Ð¾Ð»ÐµÐ¹ запиÑей Ñ Ñ‚Ð°ÐºÐ¸Ð¼Ð¸ адреÑами.
+asmr_w_unable_to_determine_reference_size_using_byte=07101_W_Размер операндов не указан и его не удаетÑÑ Ð¾Ð¿Ñ€ÐµÐ´ÐµÐ»Ð¸Ñ‚ÑŒ, иÑпользуетÑÑ BYTE по умолчанию
+% Размер ÑÑылки Ñледует указать Ñвно, Ñ‚.к. компилÑтор не может
+% определить, какой размер (byte,word,dword и т.д.) он
+% должен иÑпользовать. ВыдаетÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ в режиме Delphi, когда
+% по умолчанию иÑпользуетÑÑ Ñ€Ð°Ð·Ð¼ÐµÑ€ BYTE.
+asmr_w_no_direct_ebp_for_parameter=07102_W_ЗдеÑÑŒ Ð½ÐµÐ»ÑŒÐ·Ñ Ð¸Ñпользовать +offset(%ebp) Ð´Ð»Ñ Ð¿Ð°Ñ€Ð°Ð¼ÐµÑ‚Ñ€Ð¾Ð²
+% ИÑпользование прÑмой ÑÑылки вида 8(%ebp) Ð´Ð»Ñ Ð¿Ð°Ñ€Ð°Ð¼ÐµÑ‚Ñ€Ð¾Ð² процедуры/функции неверно, еÑли
+% параметры находÑÑ‚ÑÑ Ð² региÑтрах.
+asmr_w_direct_ebp_for_parameter_regcall=07103_W_ИÑпользование +offset(%ebp) неÑовмеÑтимо Ñ Ñ‚Ð¸Ð¿Ð¾Ð¼ вызова regcall
+% ИÑпользование прÑмой ÑÑылки вида 8(%ebp) Ð´Ð»Ñ Ð¿Ð°Ñ€Ð°Ð¼ÐµÑ‚Ñ€Ð¾Ð² процедуры/функции неверно, еÑли
+% параметры находÑÑ‚ÑÑ Ð² региÑтрах.
+asmr_w_direct_ebp_neg_offset=07104_W_ИÑпользование -offset(%ebp) Ð´Ð»Ñ Ð»Ð¾ÐºÐ°Ð»ÑŒÐ½Ñ‹Ñ… переменных не рекомендуетÑÑ
+% ИÑпользование ÑÑылок вида -8(%ebp) Ð´Ð»Ñ Ð´Ð¾Ñтупа к локальным переменным не рекомендуетÑÑ.
+asmr_w_direct_esp_neg_offset=07105_W_ИÑпользование -offset(%esp), возможен Ñбой при доÑтупе или Ð¿Ð¾Ñ‚ÐµÑ€Ñ Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ
+% ИÑпользование ÑÑылок вида -8(%esp) Ð´Ð»Ñ Ð´Ð¾Ñтупа к локальному Ñтеку не рекомендуетÑÑ,
+% потому что Ñта чаÑÑ‚ÑŒ Ñтека может быть затерта при вызове любой функции или при прерывании.
+asmr_e_no_vmtoffset_possible=07106_E_VMTOffset Ñледует иÑпользовать в комбинации Ñ Ð²Ð¸Ñ€Ñ‚ÑƒÐ°Ð»ÑŒÐ½Ñ‹Ð¼ методом, "$1" не ÑвлÑетÑÑ Ð²Ð¸Ñ€Ñ‚ÑƒÐ°Ð»ÑŒÐ½Ñ‹Ð¼
+% Только виртуальные методы имеют Ñмещение в VMT.
+asmr_e_need_pic_ref=07107_E_Ð’ режиме позиционно-незавиÑимого кода найдена позиционно-завиÑÐ¸Ð¼Ð°Ñ ÑÑылка
+% Режим компилÑции предуÑматривает генерацию позиционно-незавиÑимого кода
+% (PIC), но в данной напиÑанной вручную аÑÑемблерной инÑтрукции ÑодержитÑÑ
+% позиционно-завиÑÐ¸Ð¼Ð°Ñ ÑÑылка.
+#
+# Assembler/binary writers
+#
+# 08020 is the last used one
+#
+asmw_f_too_many_asm_files=08000_F_Слишком много аÑÑемблерных файлов
+% "УмнаÑ" компоновка приводит к получению Ñлишком большого количеÑтва
+% аÑÑемблерных файлов. Отключите ее.
+asmw_f_assembler_output_not_supported=08001_F_Выбpанный выходной формат аÑÑемблеpа не поддеpживаетÑÑ
+asmw_f_comp_not_supported=08002_F_COMP не поддеpживаетÑÑ
+asmw_f_direct_not_supported=08003_F_Тип аÑÑемблеpа direct не поддеpживаетÑÑ Ñ Ð´Ð²Ð¾Ð¸Ñ‡Ð½Ñ‹Ð¼ выходным форматом
+% Тип аÑÑемблера direct предполагает запиÑÑŒ прочитанного аÑÑемблерного текÑта напрÑмую в выходной файл,
+% при Ñтом выходной файл не может быть двоичным. Выберите текÑтовый формат выходных файлов.
+asmw_e_alloc_data_only_in_bss=08004_E_Выделение памÑти Ð´Ð»Ñ Ð´Ð°Ð½Ð½Ñ‹Ñ… разрешено только в Ñекции BSS
+asmw_f_no_binary_writer_selected=08005_F_Ðе выбран двоичный выходной формат
+asmw_e_opcode_not_in_table=08006_E_Asm: Кода команды $1 нет в ÑпиÑке
+asmw_e_invalid_opcode_and_operands=08007_E_Asm: $1 невеpное Ñочетание команды и опеpандов
+asmw_e_16bit_not_supported=08008_E_Asm: 16-битные ÑÑылки не поддеpживаютÑÑ
+asmw_e_invalid_effective_address=08009_E_Asm: Hевеpный Ñффективный адpеÑ
+asmw_e_immediate_or_reference_expected=08010_E_Asm: ОжидаетÑÑ IMMEDIATE или ÑÑылка
+asmw_e_value_exceeds_bounds=08011_E_Asm: значение $1 выходит за гpаницы $2
+asmw_e_short_jmp_out_of_range=08012_E_Asm: Короткий переход выходит за гpаницы $1
+asmw_e_undefined_label=08013_E_Asm: Метка $1 не определена
+asmw_e_comp_not_supported=08014_E_Asm: Тип comp не поддерживаетÑÑ Ð´Ð»Ñ Ñтой платформы
+asmw_e_extended_not_supported=08015_E_Asm: Тип extended не поддерживаетÑÑ Ð´Ð»Ñ Ñтой платформы
+asmw_e_duplicate_label=08016_E_Asm: ПовторÑющаÑÑÑ Ð¼ÐµÑ‚ÐºÐ° $1
+asmw_e_redefined_label=08017_E_Asm: Повторное определение метки $1
+asmw_e_first_defined_label=08018_E_Asm: Первоначально определÑетÑÑ Ð·Ð´ÐµÑÑŒ
+asmw_e_invalid_register=08019_E_Asm: Ðеверный региÑÑ‚Ñ€ $1
+asmw_e_16bit_32bit_not_supported=08020_E_Asm: 16- и 32-битные ÑÑылки не поддерживаютÑÑ
+asmw_e_64bit_not_supported=08021_E_Asm: 64-битные операнды не поддерживаютÑÑ
+
+#
+# Executing linker/assembler
+#
+# 09032 is the last used one
+#
+# BeginOfTeX
+%
+% \section{Ошибки Ñтадии аÑÑемблированиÑ/компоновки}
+% ПеречиÑлÑÑŽÑ‚ÑÑ Ð¾ÑˆÐ¸Ð±ÐºÐ¸, которые могут иметь меÑто во Ð²Ñ€ÐµÐ¼Ñ Ð¾Ð±Ñ€Ð°Ð±Ð¾Ñ‚ÐºÐ¸
+% командной Ñтроки и файлов конфигурации.
+% \begin{description}
+exec_w_source_os_redefined=09000_W_ИÑÑ…Ð¾Ð´Ð½Ð°Ñ Ð¾Ð¿ÐµpÐ°Ñ†Ð¸Ð¾Ð½Ð½Ð°Ñ ÑиÑтема пеpеопpеделена
+% ИÑÑ…Ð¾Ð´Ð½Ð°Ñ Ð¾Ð¿ÐµÑ€Ð°Ñ†Ð¸Ð¾Ð½Ð½Ð°Ñ ÑиÑтемы переопределена.
+exec_i_assembling_pipe=09001_I_ÐÑÑемблиpyетÑÑ (pipe) $1
+% ÐÑÑемблирование Ñ Ð¸Ñпользованием канала (pipe) Ð´Ð»Ñ Ð¾Ð±Ð¼ÐµÐ½Ð° данными Ñ Ð²Ð½ÐµÑˆÐ½Ð¸Ð¼ аÑÑемблером.
+exec_d_cant_create_asmfile=09002_E_Hевозможно Ñоздать аÑÑмеблеpный файл: $1
+% Указанный файл не может быть Ñоздан. Проверьте, еÑли ли
+% разрешение на Ñоздание файла.
+exec_e_cant_create_objectfile=09003_E_Ðевозможно Ñоздать объектный файл: $1
+% Указанный файл не может быть Ñоздан. Проверьте, еÑли ли
+% разрешение на Ñоздание файла.
+exec_e_cant_create_archivefile=09004_E_Ðевозможно Ñоздать файл архива: $1
+% Указанный файл не может быть Ñоздан. Проверьте, еÑли ли
+% разрешение на Ñоздание файла.
+exec_e_assembler_not_found=09005_E_ÐÑÑемблеp $1 не найден, переход на внешнюю Ñборку
+% Программа аÑÑемблера не найдена. КомпилÑтор ÑоздаÑÑ‚ Ñкрипт,
+% позволÑющий аÑÑемблировать и Ñкомпоновать программу позднее.
+exec_t_using_assembler=09006_T_ИÑпользyетÑÑ Ð°ÑÑемблеp: $1
+% Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ том, какой именно аÑÑемблер иÑпользуетÑÑ.
+exec_e_error_while_assembling=09007_E_Ошибка аÑÑемблиpованиÑ, код возврата $1
+% При обработке файла внешним аÑÑемблером произошла ошибка. ПодробноÑти
+% можно найти в руководÑтве к иÑпользуемой программе аÑÑемблера.
+exec_e_cant_call_assembler=09008_E_Ошибка $1 при запуÑке аÑÑемблера, переход на внешнюю Ñборку
+% Ошибка при запуÑке внешнего аÑÑемблера. КомпилÑтор ÑоздаÑÑ‚ Ñкрипт,
+% позволÑющий аÑÑемблировать и Ñкомпоновать программу позднее.
+exec_i_assembling=09009_I_ÐÑÑемблиpуетÑÑ $1
+% Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ том, какой файл аÑÑемблируетÑÑ.
+exec_i_assembling_smart=09010_I_ÐÑÑемблиpуетÑÑ Ñ "умной" Ñборкой $1
+% Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ том, какой файл аÑÑемблируетÑÑ Ñ Ð¿Ð¾Ð´Ð´ÐµÑ€Ð¶ÐºÐ¾Ð¹ "умной" Ñборки.
+exec_w_objfile_not_found=09011_W_Объектный файл $1 не найден, компоновка может не yдатьÑÑ!
+% Один из объектных файлов не найден, и компоновка, Ñкорее вÑего, не удаÑÑ‚ÑÑ.
+% Проверьте пути.
+exec_w_libfile_not_found=09012_W_Библиотека $1 не найдена, компоновка может не yдатьÑÑ!
+% Один из файлов библиотек не найден, и компоновка, Ñкорее вÑего, не удаÑÑ‚ÑÑ.
+% Проверьте пути.
+exec_e_error_while_linking=09013_E_Ошибка пpи компоновке
+% ÐžÐ±Ñ‰Ð°Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ° при компоновке.
+exec_e_cant_call_linker=09014_E_Hе удаетÑÑ Ð²Ñ‹Ð·Ð²Ð°Ñ‚ÑŒ компоновщик, переход на внешнюю компоновку
+% Ошибка при запуÑке внешнего компоновщика. КомпилÑтор ÑоздаÑÑ‚ Ñкрипт,
+% позволÑющий аÑÑемблировать и Ñкомпоновать программу позднее.
+exec_i_linking=09015_I_Компоновка $1
+% Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ том, ÐºÐ°ÐºÐ°Ñ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð¼Ð° или библиотека компонуетÑÑ.
+exec_e_util_not_found=09016_E_Утилита $1 не найдена, пеpеход на внешнюю компоновку
+% ВнешнÑÑ ÑƒÑ‚Ð¸Ð»Ð¸Ñ‚Ð° не найдена. КомпилÑтор ÑоздаÑÑ‚ Ñкрипт,
+% позволÑющий произвеÑти неудавшиеÑÑ Ð´ÐµÐ¹ÑÑ‚Ð²Ð¸Ñ Ð¿Ð¾Ð·Ð´Ð½ÐµÐµ.
+exec_t_using_util=09017_T_ИÑпользуетÑÑ ÑƒÑ‚Ð¸Ð»Ð¸Ñ‚Ð° $1
+% Информационное Ñообщение о том, ÐºÐ°ÐºÐ°Ñ ÑƒÑ‚Ð¸Ð»Ð¸Ñ‚Ð° иÑпользуетÑÑ (обычно Ñто поÑÑ‚-процеÑÑор).
+exec_e_exe_not_supported=09018_E_Создание иÑполнÑемых файлов не поддеpживаетÑÑ
+% Создание иÑполнÑемых файлов Ð´Ð»Ñ Ñтой платформы еще не реализовано в компилÑторе
+% и потому невозможно.
+exec_e_dll_not_supported=09019_E_Создание динамичеÑких библиотек (DLL) не поддеpживаютÑÑ
+% Создание динамичеÑки загружаемых библиотек Ð´Ð»Ñ Ñтой платформы еще не реализовано в компилÑторе
+% и потому невозможно.
+exec_i_closing_script=09020_I_Создан Ñкpипт $1
+% Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾Ð± окончании запиÑи Ñкрипта Ð´Ð»Ñ Ð²Ð½ÐµÑˆÐ½ÐµÐ³Ð¾ аÑÑемблированиÑ/компоновки.
+exec_e_res_not_found=09021_E_КомпилÑтоp pеÑypÑов "$1" не найден, пеpеход во внешний режим
+% Ошибка при запуÑке внешнего компилÑтора реÑурÑов. КомпилÑтор ÑоздаÑÑ‚ Ñкрипт,
+% позволÑющий выполнить неудавшиеÑÑ Ð´ÐµÐ¹ÑÑ‚Ð²Ð¸Ñ Ð¸ завершить Ñоздание программы позднее.
+exec_i_compilingresource=09022_I_КомпилÑÑ†Ð¸Ñ pеÑypÑа $1
+% Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ том, какой файл реÑурÑов компилируетÑÑ.
+exec_t_unit_not_static_linkable_switch_to_smart=09023_T_модyль $1 не может быть Ñкомпонован ÑтатичеÑки, переход на "умную" компоновку
+% Запрошена ÑтатичеÑÐºÐ°Ñ ÐºÐ¾Ð¼Ð¿Ð¾Ð½Ð¾Ð²ÐºÐ°, но иÑпользованный модуль не допуÑкает Ñтот режим.
+exec_t_unit_not_smart_linkable_switch_to_static=09024_T_модyль $1 не может быть Ñкомпонован в "умном" pежиме, переход на ÑтатичеÑкую компоновку
+% Запрошена "умнаÑ" компоновка, но иÑпользованный модуль не допуÑкает Ñтот режим.
+exec_t_unit_not_shared_linkable_switch_to_static=09025_T_модyль $1 не может быть Ñкомпонован в pежиме shared, переход на ÑтатичеÑкую компоновку
+% Запрошена разделÑÐµÐ¼Ð°Ñ ÐºÐ¾Ð¼Ð¿Ð¾Ð½Ð¾Ð²ÐºÐ°, но иÑпользованный модуль не допуÑкает Ñтот режим.
+exec_e_unit_not_smart_or_static_linkable=09026_E_модyль $1 не может быть Ñкомпонован в pежимах smart или static
+% Запрошена "умнаÑ" или ÑтатичеÑÐºÐ°Ñ ÐºÐ¾Ð¼Ð¿Ð¾Ð½Ð¾Ð²ÐºÐ°, но иÑпользованный модуль не допуÑкает ни один из Ñтих режимов.
+exec_e_unit_not_shared_or_static_linkable=09027_E_модyль $1 не может быть Ñобpан в pежимах shared или static
+% Запрошена разделÑÐµÐ¼Ð°Ñ Ð¸Ð»Ð¸ ÑтатичеÑÐºÐ°Ñ ÐºÐ¾Ð¼Ð¿Ð¾Ð½Ð¾Ð²ÐºÐ°, но иÑпользованный модуль не допуÑкает ни один из Ñтих режимов.
+exec_d_resbin_params=09028_D_Вызов компилÑтора реÑурÑов "$1" Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ð½Ð¾Ð¹ Ñтрокой "$2"
+% Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾Ð± иÑпользуемом компилÑторе реÑурÑов и его командной Ñтроке.
+exec_e_error_while_compiling_resources=09029_E_Ошибка при компилÑции реÑурÑов
+% КомпилÑтор или конвертор реÑурÑов завершилÑÑ Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ¾Ð¹.
+exec_e_cant_call_resource_compiler=09030_E_Вызов компилÑтора реÑурÑов "$1" невозможен, переход во внешний режим
+% Ошибка при вызове компилÑтора реÑурÑов. КомпилÑтор ÑоздаÑÑ‚ Ñкрипт,
+% позволÑющий повторить неудавшиеÑÑ Ð´ÐµÐ¹ÑÑ‚Ð²Ð¸Ñ Ð¸ завершить Ñоздание программы
+% позднее.
+exec_e_cant_open_resource_file=09031_E_Ðевозможно открыть файл реÑурÑов "$1"
+% Ошибка при открытии указанного файла реÑурÑов.
+exec_e_cant_write_resource_file=09032_E_Ошибка запиÑи файла реÑурÑов "$1"
+% Ошибка при запиÑи указанного файла реÑурÑов.
+%\end{description}
+# EndOfTeX
+
+#
+# Executable information
+#
+# 09134 is the last used one
+#
+# BeginOfTeX
+% \section{Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾Ð± иÑполнÑемых файлах.}
+% Содержит ÑообщениÑ, выдаваемые при Ñоздании иÑполнÑемого файла
+% Ñ Ð¸Ñпользованием внутреннего компоновщика.
+% \begin{description}
+execinfo_f_cant_process_executable=09128_F_ПоÑÑ‚-обработка иÑполнÑемого файла $1 невозможна
+% Ð¤Ð°Ñ‚Ð°Ð»ÑŒÐ½Ð°Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ° при невозможноÑти поÑÑ‚-обработки иÑполнÑемого файла.
+execinfo_f_cant_open_executable=09129_F_Ðевозможно открыть иÑполнÑемый файл $1
+% Ð¤Ð°Ñ‚Ð°Ð»ÑŒÐ½Ð°Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ° при невозможноÑти открыть иÑполнÑемый файл.
+execinfo_x_codesize=09130_X_Размер кода: $1 байт
+% Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ размере Ñозданной Ñекции кода.
+execinfo_x_initdatasize=09131_X_Размер инициализированных данных: $1 байт
+% Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ размере Ñозданной Ñекции инициализированных данных.
+execinfo_x_uninitdatasize=09132_X_Размер неинициализированных данных: $1 bytes
+% Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ размере Ñекции неинициализированных данных.
+execinfo_x_stackreserve=09133_X_Размер Ñтека (зарезервированный): $1 bytes
+% Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ зарезервированном размере Ñтека иÑполнÑемого файла.
+execinfo_x_stackcommit=09134_X_Размер Ñтека (подключенный): $1 bytes
+% Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ подключенном размере Ñтека иÑполнÑемого файла.
+%\end{description}
+# EndOfTeX
+
+#
+# Internal linker messages
+#
+# 09200 is the last used one
+#
+# BeginOfTeX
+% \section{Ð¡Ð¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ ÐºÐ¾Ð¼Ð¿Ð¾Ð½Ð¾Ð²Ñ‰Ð¸ÐºÐ°}
+% СообщениÑ, выдаваемые внутренним компоновщиком.
+% \begin{description}
+link_f_executable_too_big=09200_F_Размер иÑполнÑемого образа Ñлишком велик Ð´Ð»Ñ Ð¿Ð»Ð°Ñ‚Ñ„Ð¾Ñ€Ð¼Ñ‹ $1.
+% Ð¤Ð°Ñ‚Ð°Ð»ÑŒÐ½Ð°Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ°, Ð²Ð¾Ð·Ð½Ð¸ÐºÐ°ÑŽÑ‰Ð°Ñ Ð² Ñлучае, еÑли Ñозданный иÑполнÑемый файл Ñлишком велик.
+link_w_32bit_absolute_reloc=09201_W_Объектный файл "$1" Ñодержит 32-битное абÑолютное перемещение Ð´Ð»Ñ Ñимвола "$2".
+% Ð’ Ñлучае, когда 64-битный объектный файл Ñодержит 32-битные абÑолютные перемещениÑ,
+% полученный иÑполнÑемый образ может быть загружен только в нижние 4 ГБ адреÑного
+% проÑтранÑтва.
+%\end{description}
+# EndOfTeX
+
+#
+# Unit loading
+#
+# 10061 is the last used one
+#
+# BeginOfTeX
+% \section{Ð¡Ð¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ¸ модулей.}
+% СообщениÑ, выдаваемые при загрузке модулей Ñ Ð´Ð¸Ñка в памÑÑ‚ÑŒ.
+% Многие из них ноÑÑÑ‚ информационный характер.
+% \begin{description}
+unit_t_unitsearch=10000_T_ПоиÑк модyлÑ: $1
+% При иÑпользовании ключа \var{-vt} Ñообщает о том, где компилÑтор ищет
+% файлы модулей.
+unit_t_ppu_loading=10001_T_Загpyзка PPU $1
+% При иÑпользовании ключа \var{-vt} Ñообщает Ð¸Ð¼Ñ Ñ„Ð°Ð¹Ð»Ð° загружаемого модулÑ.
+unit_u_ppu_name=10002_U_Ð˜Ð¼Ñ PPU: $1
+% При иÑпользовании ключа \var{-vu} Ñообщает Ð¸Ð¼Ñ Ð¼Ð¾Ð´ÑƒÐ»Ñ.
+unit_u_ppu_flags=10003_U_Флаги PPU: $1
+% При иÑпользовании ключа \var{-vu} показывает флаги модулÑ.
+unit_u_ppu_crc=10004_U_CRC PPU: $1
+% При иÑпользовании ключа \var{-vu} показывает контрольную Ñумму модулÑ.
+unit_u_ppu_time=10005_U_Ð’Ñ€ÐµÐ¼Ñ PPU: $1
+% При иÑпользовании ключа \var{-vu} показывает времÑ, когда модуль был Ñкомпилирован.
+unit_u_ppu_file_too_short=10006_U_PPU файл Ñлишком коpоткий
+% Файл Ð¼Ð¾Ð´ÑƒÐ»Ñ Ñлишком короткий, в нем ÑодержатÑÑ Ð½Ðµ вÑе объÑвлениÑ.
+unit_u_ppu_invalid_header=10007_U_Hевеpный заголовок PPU (нет Ñигнатуры PPU в начале)
+% Первыми Ñ‚Ñ€ÐµÐ¼Ñ Ð±Ð°Ð¹Ñ‚Ð°Ð¼Ð¸ файла PPU должны быть коды Ñимволов \var{PPU}
+unit_u_ppu_invalid_version=10008_U_HевеpÐ½Ð°Ñ Ð²ÐµpÑÐ¸Ñ PPU файла $1
+% Указанный файл Ð¼Ð¾Ð´ÑƒÐ»Ñ Ð±Ñ‹Ð» Ñоздан другой верÑией компилÑтора, и поÑтому не может быть
+% прочитан.
+unit_u_ppu_invalid_processor=10009_U_PPU файл Ñоздан Ð´Ð»Ñ Ð´pyгого пpоцеÑÑоpа
+% Этот модуль был Ñкомпилирован Ð´Ð»Ñ Ð´Ñ€ÑƒÐ³Ð¾Ð³Ð¾ типа процеÑÑора, и поÑтому не может
+% быть прочитан.
+unit_u_ppu_invalid_target=10010_U_PPU файл Ñоздан Ð´Ð»Ñ Ð´pyгой ОС
+% Этот модуль был Ñкомпилирован Ð´Ð»Ñ Ð´Ñ€ÑƒÐ³Ð¾Ð¹ операционной ÑиÑтемы, и поÑтому не может
+% быть прочитан.
+unit_u_ppu_source=10011_U_ИÑходный файл PPU: $1
+% При иÑпользовании ключа \var{-vu} показывает Ð¸Ð¼Ñ Ð¸Ñходного файла модулÑ.
+unit_u_ppu_write=10012_U_ЗапиÑÑŒ $1
+% При иÑпользовании ключа \var{-vu} Ñообщает, куда компилÑтор запиÑывает
+% файл модулÑ.
+unit_f_ppu_cannot_write=10013_F_Hевозможно запиÑать PPU-файл
+% При запиÑи файла Ð¼Ð¾Ð´ÑƒÐ»Ñ Ð¿Ñ€Ð¾Ð¸Ð·Ð¾ÑˆÐ»Ð° ошибка.
+unit_f_ppu_read_error=10014_F_Ошибка Ñ‡Ñ‚ÐµÐ½Ð¸Ñ PPU-файла
+% Файл Ð¼Ð¾Ð´ÑƒÐ»Ñ Ð¿Ð¾Ð²Ñ€ÐµÐ¶Ð´ÐµÐ½ и Ñодержит неверную
+% информацию. ПотребуетÑÑ Ñ€ÐµÐºÐ¾Ð¼Ð¿Ð¸Ð»ÑциÑ.
+unit_f_ppu_read_unexpected_end=10015_F_Ðеожиданный конец PPU-файла
+% Ðеожиданный конец файла.
+unit_f_ppu_invalid_entry=10016_F_HÐµÐ²ÐµÑ€Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ PPU-файла: $1
+% Файл Ð¼Ð¾Ð´ÑƒÐ»Ñ Ð¿Ð¾Ð²Ñ€ÐµÐ¶Ð´ÐµÐ½, или был Ñоздан более новой верÑией компилÑтора.
+unit_f_ppu_dbx_count_problem=10017_F_Ошибка PPU DBX count
+% ÐеÑтыковки в отладочной информации модулÑ.
+unit_e_illegal_unit_name=10018_E_Hевеpное Ð¸Ð¼Ñ Ð¼Ð¾Ð´yлÑ: $1
+% Ð˜Ð¼Ñ Ð¼Ð¾Ð´ÑƒÐ»Ñ Ð½Ðµ Ñовпадает Ñ Ð¸Ð¼ÐµÐ½ÐµÐ¼ файла модулÑ.
+unit_f_too_much_units=10019_F_Слишком много модyлей
+% КомпилÑтор имеет предел 1024 Ð¼Ð¾Ð´ÑƒÐ»Ñ Ð² программе. Его можно увеличить,
+% изменив значение конÑтанты \var{maxunits} в файле \file{files.pas} компилÑтора,
+% и перекомпилировав компилÑтор.
+unit_f_circular_unit_reference=10020_F_ÐšÐ¾Ð»ÑŒÑ†ÐµÐ²Ð°Ñ ÑÑылка междy модулÑми $1 и $2
+% Два Ð¼Ð¾Ð´ÑƒÐ»Ñ Ð¸Ñпользуют друг друга в интерфейÑной Ñекции. Это разрешено только в
+% Ñекции \var{implementation}. По крайней мере один из модулей должен Ñодержать
+% ÑÑылку на другой в Ñекции \var{implementation}.
+unit_f_cant_compile_unit=10021_F_КомпилÑÑ†Ð¸Ñ Ð¼Ð¾Ð´yÐ»Ñ $1 невозможна, отÑутÑтвуют иÑходники.
+% Ðайден модуль, требующий перекомпилÑции, но иÑходные файлы Ð´Ð»Ñ Ð½ÐµÐ³Ð¾ отÑутÑтвуют.
+unit_f_cant_find_ppu=10022_F_Hе найден модуль $1, иÑпользуемый $2
+% Попытка иÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¼Ð¾Ð´ÑƒÐ»Ñ, Ð´Ð»Ñ ÐºÐ¾Ñ‚Ð¾Ñ€Ð¾Ð³Ð¾ не найден файл PPU.
+% Проверьте пути модулей в файле конфигурации.
+unit_w_unit_name_error=10023_W_Модуль $1 не найден, но $2 ÑущеÑтвует
+% Больше не иÑпользуетÑÑ.
+unit_f_unit_name_error=10024_F_При поиÑке Ð¼Ð¾Ð´ÑƒÐ»Ñ $1 был найден $2
+% Ограничение DOS на длину имен файлов в 8 Ñимволов может вызывать
+% проблемы, еÑли Ð¸Ð¼Ñ Ð¼Ð¾Ð´ÑƒÐ»Ñ Ð¸Ð¼ÐµÐµÑ‚ большую длину.
+unit_w_switch_us_missed=10025_W_Ð”Ð»Ñ ÐºÐ¾Ð¼Ð¿Ð¸Ð»Ñции Ð¼Ð¾Ð´ÑƒÐ»Ñ system требуетÑÑ ÐºÐ»ÑŽÑ‡ -Us
+% При компилÑции Ð¼Ð¾Ð´ÑƒÐ»Ñ system (требующего оÑобой обработки), Ñледует
+% указывать ключ \var{-Us}.
+unit_f_errors_in_unit=10026_F_Пpи компилÑции модyÐ»Ñ Ð¿Ñ€Ð¾Ð¸Ð·Ð¾ÑˆÐ»Ð¾ $1 ошибок, работа прервана
+% КомпилÑтор прекращает работу Ñ Ñтим Ñообщением при возникновении фатальной ошибки,
+% или при превышении предельного количеÑтва ошибок.
+unit_u_load_unit=10027_U_Загpyзка из $1 ($2) модyль $3
+% При иÑпользовании ключа \var{-vu} Ñообщает, который модуль откуда загружаетÑÑ.
+% shown.
+unit_u_recompile_crc_change=10028_U_ПеpекомпилÑÑ†Ð¸Ñ $1, изменилаÑÑŒ контpÐ¾Ð»ÑŒÐ½Ð°Ñ Ñyмма $2
+% Модуль перекомпилируетÑÑ, потому что изменилаÑÑŒ ÐºÐ¾Ð½Ñ‚Ñ€Ð¾Ð»ÑŒÐ½Ð°Ñ Ñумма модулÑ, от которого
+% он завиÑит.
+unit_u_recompile_source_found_alone=10029_U_ПеpекомпилÑÑ†Ð¸Ñ $1, найдены только иÑходные файлы
+% При иÑпользовании ключа \var{-vu} Ñообщает причину перекомпилÑции указанного модулÑ.
+unit_u_recompile_staticlib_is_older=10030_U_ПеpекомпилÑÑ†Ð¸Ñ Ð¼Ð¾Ð´yлÑ, ÑтатичеÑÐºÐ°Ñ Ð±Ð¸Ð±Ð»Ð¸Ð¾Ñ‚ÐµÐºÐ° Ñтаpше чем ppu-файл
+% При иÑпользовании ключа \var{-vu} Ñообщает о том, что ÑтатичеÑÐºÐ°Ñ Ð±Ð¸Ð±Ð»Ð¸Ð¾Ñ‚ÐµÐºÐ° модулÑ
+% Ñтарше, чем ppu-файл модулÑ.
+unit_u_recompile_sharedlib_is_older=10031_U_ПеpекомпилÑÑ†Ð¸Ñ Ð¼Ð¾Ð´yлÑ, разделÑÐµÐ¼Ð°Ñ Ð±Ð¸Ð±Ð»Ð¸Ð¾Ñ‚ÐµÐºÐ° Ñтаpше чем ppu-файл
+% При иÑпользовании ключа \var{-vu} Ñообщает о том, что разделÑÐµÐ¼Ð°Ñ Ð±Ð¸Ð±Ð»Ð¸Ð¾Ñ‚ÐµÐºÐ° модулÑ
+% Ñтарше, чем ppu-файл модулÑ.
+unit_u_recompile_obj_and_asm_older=10032_U_ПеpекомпилÑÑ†Ð¸Ñ Ð¼Ð¾Ð´yлÑ, .as и .obj файлы Ñтаpше чем ppu-файл
+% При иÑпользовании ключа \var{-vu} Ñообщает о том, что аÑÑемблерный или объектный файл модулÑ
+% Ñтарше, чем ppu-файл модулÑ.
+unit_u_recompile_obj_older_than_asm=10033_U_ПеpекомпилÑÑ†Ð¸Ñ Ð¼Ð¾Ð´yлÑ, .obj файл Ñтаpше чем .as файл
+% При иÑпользовании ключа \var{-vu} Ñообщает о том, что объектный файл модулÑ
+% Ñтарше, чем его аÑÑемблерный файл.
+unit_u_parsing_interface=10034_U_Ðнализ интеpфейÑа $1
+% При иÑпользовании ключа \var{-vu} Ñообщает о начале анализа
+% интерфейÑной чаÑти модулÑ.
+unit_u_parsing_implementation=10035_U_Ðнализ pеализации $1
+% При иÑпользовании ключа \var{-vu} Ñообщает о начале анализа
+% реализационной чаÑти модулÑ.
+unit_u_second_load_unit=10036_U_ÐŸÐ¾Ð²Ñ‚Ð¾Ñ€Ð½Ð°Ñ Ð·Ð°Ð³pyзка модyÐ»Ñ $1
+% При иÑпользовании ключа \var{-vu} Ñообщает о начале повторной компилÑции
+% модулч. Это может проиÑходить при наличии взаимозавиÑимых модулей.
+unit_u_check_time=10037_U_Проверка PPU файла $1 вpÐµÐ¼Ñ $2
+% При иÑпользовании ключа \var{-vu} показвает Ð¸Ð¼Ñ Ð¸ дату/Ð²Ñ€ÐµÐ¼Ñ Ñ„Ð°Ð¹Ð»Ð°,
+% от которого завиÑит рекомпилÑциÑ.
+### The following two error msgs is currently disabled.
+#unit_h_cond_not_set_in_last_compile=10038_H_УÑловное выpажение $1 не было yÑтановлено пpи поÑледней компилÑции $2
+#% when recompilation of an unit is required the compiler will check that
+#% the same conditionals are set for the recompiliation. The compiler has
+#% found a conditional that currently is defined, but was not used the last
+#% time the unit was compiled.
+#unit_h_cond_set_in_last_compile=10039_H_УÑловное выpажение $1 было yÑтановлено пpи поÑледней компилÑции $2
+#% when recompilation of an unit is required the compiler will check that
+#% the same conditionals are set for the recompiliation. The compiler has
+#% found a conditional that was used the last time the unit was compiled, but
+#% the conditional is currently not defined.
+unit_w_cant_compile_unit_with_changed_incfile=10040_W_Ðайдены измененные включаемые файлы, но компилÑÑ†Ð¸Ñ $1 невозможна
+% Обнаружено изменение включаемых файлов модулÑ, но некоторые иÑходные файлы
+% не найдены, поÑтому рекомпилÑÑ†Ð¸Ñ Ð½ÐµÐ²Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ð°.
+unit_u_source_modified=10041_U_Файл $1 новее, чем $2
+% Ðайден измененный иÑходный файл модулÑ.
+unit_u_ppu_invalid_fpumode=10042_U_Попытка иÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¼Ð¾Ð´ÑƒÐ»Ñ, Ñкомпилированного Ñ Ð´Ñ€ÑƒÐ³Ð¸Ð¼ режимом ÑопроцеÑÑора
+% Попытка иÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¼Ð¾Ð´ÑƒÐ»ÐµÐ¹, которые были Ñкомпилированы Ñ Ð¾Ñ‚Ð»Ð¸Ñ‡Ð°ÑŽÑ‰Ð¸Ð¼ÑÑ Ñ€ÐµÐ¶Ð¸Ð¼Ð¾Ð¼
+% формата плавающей запÑтой. Ð’Ñе модули должны быть Ñкомпилированы либо Ñ Ð²ÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ð¾Ð¹
+% ÑмулÑцией ÑопроцеÑÑора, либо Ñ Ð¾Ñ‚ÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ð¾Ð¹, но не вперемешку.
+unit_u_loading_interface_units=10043_U_Загрузка модулей из интерфейÑной чаÑти $1
+% При иÑпользовании ключа \var{-vu} Ñообщает о начале загрузки модулей,
+% иÑпользуемых в интерфейÑной чаÑти указанного модулÑ.
+unit_u_loading_implementation_units=10044_U_Загрузка модулей из реализационной чаÑти $1
+% При иÑпользовании ключа \var{-vu} Ñообщает о начале загрузки модулей,
+% иÑпользуемых в реализационной чаÑти указанного модулÑ.
+unit_u_interface_crc_changed=10045_U_У Ð¼Ð¾Ð´ÑƒÐ»Ñ $1 изменилаÑÑŒ ÐºÐ¾Ð½Ñ‚Ñ€Ð¾Ð»ÑŒÐ½Ð°Ñ Ñумма интерфейÑа
+% При иÑпользовании ключа \var{-vu} Ñообщает о том, что ÐºÐ¾Ð½Ñ‚Ñ€Ð¾Ð»ÑŒÐ½Ð°Ñ Ñумма,
+% вычиÑÐ»ÐµÐ½Ð½Ð°Ñ Ð´Ð»Ñ Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñной чаÑти модулÑ, изменилаÑÑŒ поÑле разбора его реализационной
+% чаÑти.
+unit_u_implementation_crc_changed=10046_U_У Ð¼Ð¾Ð´ÑƒÐ»Ñ $1 изменилаÑÑŒ ÐºÐ¾Ð½Ñ‚Ñ€Ð¾Ð»ÑŒÐ½Ð°Ñ Ñумма реализации
+% При иÑпользовании ключа \var{-vu} Ñообщает, что ÐºÐ¾Ð½Ñ‚Ñ€Ð¾Ð»ÑŒÐ½Ð°Ñ Ñумма модулÑ
+% изменилаÑÑŒ поÑле разбора его реализационной чаÑти.
+unit_u_finished_compiling=10047_U_Завершена компилÑÑ†Ð¸Ñ Ð¼Ð¾Ð´ÑƒÐ»Ñ $1
+% При иÑпользовании ключа \var{-vu} Ñообщает о завершени компилÑции модулÑ.
+unit_u_add_depend_to=10048_U_Добавлена завиÑимоÑÑ‚ÑŒ $1 от $2
+% При иÑпользовании ключа \var{-vu} Ñообщает о том, что была добавлена
+% завиÑимоÑÑ‚ÑŒ между Ð´Ð²ÑƒÐ¼Ñ Ð¼Ð¾Ð´ÑƒÐ»Ñми.
+unit_u_no_reload_is_caller=10049_U_Без перезагрузки, Ñто инициатор: $1
+% При иÑпользовании ключа \var{-vu} предупреждает о том, что
+% модуль не будет перезагружен, потому что он Ñам ÑвлÑетÑÑ Ð¸Ð½Ð¸Ñ†Ð¸Ð°Ñ‚Ð¾Ñ€Ð¾Ð¼ Ñвоей
+% перезагрузки.
+unit_u_no_reload_in_second_compile=10050_U_Без перезагрузки, уже Ð¿Ð¾Ð²Ñ‚Ð¾Ñ€Ð½Ð°Ñ ÐºÐ¾Ð¼Ð¿Ð¸Ð»ÑциÑ: $1
+% При иÑпользовании ключа \var{-vu} предупреждает, что модуль
+% не будет перезагружен, Ñ‚.к. он уже был перезагружен и компилируетÑÑ Ð²Ð¾ второй раз.
+unit_u_flag_for_reload=10051_U_Помечено Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ¸: $1
+% При иÑпользовании ключа \var{-vu} Ñообщает о том, что модуль будет перезагружен.
+unit_u_forced_reload=10052_U_Ð’Ñ‹Ð½ÑƒÐ¶Ð´ÐµÐ½Ð½Ð°Ñ Ð¿ÐµÑ€ÐµÐ·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ°
+% При иÑпользовании ключа \var{-vu} Ñообщает о том, что модуль пришлоÑÑŒ перезагрузить.
+unit_u_previous_state=10053_U_Прежний ÑÑ‚Ð°Ñ‚ÑƒÑ $1: $2
+% При иÑпользовании ключа \var{-vu} показывает предыдущий ÑÑ‚Ð°Ñ‚ÑƒÑ Ð¼Ð¾Ð´ÑƒÐ»Ñ.
+unit_u_second_compile_unit=10054_U_$1 уже компилируетÑÑ, переход к повторной компилÑции
+% При иÑпользовании ключа \var{-vu} предупреждает о начале перекомпилÑции модулÑ
+% во второй раз. Это может проиÑходить Ñо взаимозавиÑимыми модулÑми.
+unit_u_loading_unit=10055_U_Загрузка Ð¼Ð¾Ð´ÑƒÐ»Ñ $1
+% При иÑпользовании ключа \var{-vu} Ñообщает о начале загрузки модулÑ.
+unit_u_finished_loading_unit=10056_U_Загрузка Ð¼Ð¾Ð´ÑƒÐ»Ñ $1 завершена
+% При иÑпользовании ключа \var{-vu} Ñообщает о завершении загрузки модулÑ.
+unit_u_registering_new_unit=10057_U_РегиÑÑ‚Ñ€Ð°Ñ†Ð¸Ñ Ð½Ð¾Ð²Ð¾Ð³Ð¾ Ð¼Ð¾Ð´ÑƒÐ»Ñ $1
+% При иÑпользовании ключа \var{-vu} Ñообщает о том, что компилÑтор вÑтретил новый модуль
+% и зарегиÑтрировал его во внутренних ÑпиÑках.
+unit_u_reresolving_unit=10058_U_Повторное разрешение завиÑимоÑтей Ð¼Ð¾Ð´ÑƒÐ»Ñ $1
+% При иÑпользовании ключа \var{-vu} предупреждает о том, что компилÑтору пришлоÑÑŒ
+% повторно вычиÑлить внутренние данные указанного модулÑ.
+unit_u_skipping_reresolving_unit=10059_U_ПропуÑк повторного Ñ€Ð°Ð·Ñ€ÐµÑˆÐµÐ½Ð¸Ñ Ð¼Ð¾Ð´ÑƒÐ»Ñ $1, загрузка иÑпользуемых модулей продолжаетÑÑ
+% При иÑпользовании ключа \var{-vu} Ñообщает о том, что повторное вычиÑление данных
+% Ð¼Ð¾Ð´ÑƒÐ»Ñ Ð¿Ñ€Ð¾Ð¿ÑƒÑ‰ÐµÐ½Ð¾, потому что вычиÑлÑÑ‚ÑŒ пока нечего.
+unit_u_unload_resunit=10060_U_Выгрузка Ð¼Ð¾Ð´ÑƒÐ»Ñ Ð¾Ð±Ñ€Ð°Ð±Ð¾Ñ‚ÐºÐ¸ реÑурÑов $1 (не нужен)
+% При иÑпользовании ключа \var{-vu} Ñообщает о том, что модуль обработки реÑурÑов
+% выгружаетÑÑ, Ñ‚.к. реÑурÑÑ‹ не иÑпользуютÑÑ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð¼Ð¾Ð¹.
+unit_e_different_wpo_file=10061_E_Модуль $1 Ñкомпилирован Ñ Ð¸Ñпользованием отличающихÑÑ Ð½Ð°Ñтроек оптимизации вÑей программы (wpo) ($2, $3); перекомпилируйте его без wpo или Ñ Ñ‚ÐµÐ¼ же файлом обратной ÑвÑзи
+% Когда модуль был Ñкомпилирован Ñ Ð¾Ð¿Ñ€ÐµÐ´ÐµÐ»ÐµÐ½Ð½Ñ‹Ð¼ файлом обратной ÑвÑзи оптимизации вÑей программы (wpo) (\var{-FW<x>} \var{-OW<x>}),
+% его ÑÐºÐ¾Ð¼Ð¿Ð¸Ð»Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð½Ð°Ñ Ð²ÐµÑ€ÑÐ¸Ñ Ñпециализирована под данный Ñценарий компилÑции и не может быть иÑпользована
+% по другому назначению. Ð”Ð»Ñ Ð¸ÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¼Ð¾Ð´ÑƒÐ»Ñ Ð² другой программе или Ñ Ð´Ñ€ÑƒÐ³Ð¸Ð¼Ð¸ наÑтройками wpo
+% его необходимо перекомпилировать.
+% \end{description}
+# EndOfTeX
+
+#
+# Options
+#
+# 11047 is the last used one
+#
+option_usage=11000_O_$1 [опции] <файл> [опции]
+# BeginOfTeX
+%
+% \section{Ошибки обработки командной Ñтроки}
+% Ошибки, которые могут возникать во Ð²Ñ€ÐµÐ¼Ñ Ð¾Ð±Ñ€Ð°Ð±Ð¾Ñ‚ÐºÐ¸ командной Ñтроки
+% или файлов конфигурации.
+% \begin{description}
+option_only_one_source_support=11001_W_ПоддеpживаетÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ один иÑходный файл, вмеÑто $1 будет Ñкомпилирован $2
+% Ð’ командной Ñтроке можно указывать только один файл. Первый обнаруженный файл будет
+% Ñкомпилирован, оÑтальные игнорируютÑÑ. Может быть признаком того, что
+% перед опцией забыт знак \var{'-'}.
+option_def_only_for_os2=11002_W_DEF файл можно Ñоздавать только Ð´Ð»Ñ OS/2
+% This option can only be specified when you're compiling for OS/2
+option_no_nested_response_file=11003_E_Вложенные файлы ответа не поддеpживаютÑÑ
+% ÐžÐ¿Ñ†Ð¸Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ð½Ð¾Ð¹ Ñтроки \var{@file} не позволÑет иÑпользовать вложенные файлы ответа.
+option_no_source_found=11004_F_Ð’ командной Ñтроке отÑутÑтвует Ð¸Ð¼Ñ Ð¸Ñходного файла
+% Ð’ командной Ñтроке должно приÑутÑтвовать Ð¸Ð¼Ñ Ð¸Ñходного файла.
+option_no_option_found=11005_N_Файл конфигурации $1 не Ñодержит опций компилÑтора
+% В указанном файле конфигурации не обнаружено ни одной опции.
+option_illegal_para=11006_E_Hевеpный паpаметp: $1
+% Указана неизвеÑÑ‚Ð½Ð°Ñ Ð¾Ð¿Ñ†Ð¸Ñ.
+option_help_pages_para=11007_H_-? выводит ÑÑ‚pаницы Ñправки
+% Это Ñообщение выводитÑÑ, еÑли указана неизвеÑÑ‚Ð½Ð°Ñ Ð¾Ð¿Ñ†Ð¸Ñ.
+option_too_many_cfg_files=11008_F_Слишком много вложенных файлов конфигурации
+% Уровень Ð²Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ñ„Ð°Ð¹Ð»Ð¾Ð² конфигурации ограничен чиÑлом 16.
+option_unable_open_file=11009_F_Hевозможно откpыть $1
+% Ошибка при открытии файла конфигурации.
+option_reading_further_from=11010_D_ПродолжаетÑÑ Ñ‡Ñ‚ÐµÐ½Ð¸Ðµ паpаметpов из $1
+% ВыдаетÑÑ, еÑли включен вывод заметок, и компилÑтор переключаетÑÑ Ð½Ð°
+% другой файл конфигурации.
+option_target_is_already_set=11011_W_Ð¦ÐµÐ»ÐµÐ²Ð°Ñ Ð¿Ð»Ð°Ñ‚Ñ„Ð¾Ñ€Ð¼Ð° уже yÑтановлена в: $1
+% Указано более одной опции \var{-T}, определÑющей целевую платформу.
+option_no_shared_lib_under_dos=11012_W_РазделÑемые библиотеки не поддеpживаютÑÑ Ð´Ð»Ñ DOS, будут ÑтатичеÑкими
+% If you specify \var{-CD} for the \dos platform, this message is displayed.
+% The compiler supports only static libraries under \dos
+option_too_many_ifdef=11013_F_Слишком много $IFDEF или $IFNDEF в файле опций $1 Ñтрока $2
+% КоличеÑтво директив \var{\#IF(N)DEF} в файле конфигурации не Ñовпадает Ñ ÐºÐ¾Ð»Ð¸Ñ‡ÐµÑтвом
+% директив \var{\#ENDIF}.
+option_too_many_endif=11014_F_Ðеожиданный $ENDIF в файле опций $1 Ñтрока $2
+% КоличеÑтво директив \var{\#IF(N)DEF} в файле конфигурации не Ñовпадает Ñ ÐºÐ¾Ð»Ð¸Ñ‡ÐµÑтвом
+% директив \var{\#ENDIF}.
+option_too_less_endif=11015_F_Ðезакрытое yÑловное выpажение в конце файла опций
+% КоличеÑтво директив \var{\#IF(N)DEF} в файле конфигурации не Ñовпадает Ñ ÐºÐ¾Ð»Ð¸Ñ‡ÐµÑтвом
+% директив \var{\#ENDIF}.
+option_no_debug_support=11016_W_Этот ÑкземплÑÑ€ компилÑтора не поддерживает генеpацию отладочной инфоpмации
+% It is possible to have a compiler executable that doesn't support
+% the generation of debugging info. If you use such an executable with the
+% \var{-g} switch, this warning will be displayed.
+option_no_debug_support_recompile_fpc=11017_H_Попpобyйте Ñобрать Ñ Ð¾Ð¿Ñ†Ð¸ÐµÐ¹ -dGDB
+% It is possible to have a compiler executable that doesn't support
+% the generation of debugging info. If you use such an executable with the
+% \var{-g} switch, this warning will be displayed.
+option_obsolete_switch=11018_W_ИÑпользyетÑÑ yÑтаpевший ключ $1
+% Предупреждает, что ÑƒÐºÐ°Ð·Ð°Ð½Ð½Ð°Ñ Ð¾Ð¿Ñ†Ð¸Ñ Ð±Ð¾Ð»ÑŒÑˆÐµ не нужна/не поддерживаетÑÑ.
+% Ее рекомендуетÑÑ ÑƒÐ´Ð°Ð»Ð¸Ñ‚ÑŒ, чтобы избежать проблем в Ñлучае, еÑли
+% в будущем значение опции изменитÑÑ.
+option_obsolete_switch_use_new=11019_W_ИÑпользyетÑÑ yÑтаpевший ключ $1, иÑпользyйте вмеÑто него ключ $2
+% Предупреждает, что ÑƒÐºÐ°Ð·Ð°Ð½Ð½Ð°Ñ Ð¾Ð¿Ñ†Ð¸Ñ Ð±Ð¾Ð»ÑŒÑˆÐµ не поддерживаетÑÑ Ð¸ вмеÑто нее Ñледует иÑпользовать другую.
+% РекомендуетÑÑ Ð·Ð°Ð¼ÐµÐ½Ð¸Ñ‚ÑŒ ключ, чтобы избежать проблем в Ñлучае, еÑли
+% в будущем его значение изменитÑÑ.
+option_switch_bin_to_src_assembler=11020_N_Пеpеключение на аÑÑемблеp, генерирующий текÑÑ‚
+% ÐÑÑемблер (Ñ Ð´Ð²Ð¾Ð¸Ñ‡Ð½Ñ‹Ð¼ форматом выходных файлов) был изменен, потому что был иÑпользован ключ -a,
+% который означает Ñоздание аÑÑемблерных файлов в текÑтовом формате.
+option_incompatible_asm=11021_W_Выбранный аÑÑемблер "$1" не ÑовмеÑтим Ñ "$2"
+option_asm_forced=11022_W_Вынужденно иÑпользетÑÑ Ð°ÑÑемблер "$1"
+% Заданный тип аÑÑемблера не позволÑет Ñоздавать объектные файлы
+% в правильном формате. ВмеÑто него будет иÑпользован аÑÑемблер по умолчанию
+% Ð´Ð»Ñ Ð²Ñ‹Ð±Ñ€Ð°Ð½Ð½Ð¾Ð¹ платформы.
+option_using_file=11026_T_Чтение опций из файла $1
+% Опции читаютÑÑ Ñ‚Ð°ÐºÐ¶Ðµ из указанного файла.
+option_using_env=11027_T_Чтение опций из переменной Ð¾ÐºÑ€ÑƒÐ¶ÐµÐ½Ð¸Ñ $1
+% Опции читаютÑÑ Ñ‚Ð°ÐºÐ¶Ðµ из указанной переменной окружениÑ.
+option_handling_option=11028_D_Обработка опции "$1"
+% Отладочное Ñообщение о том, что Ð¾Ð¿Ñ†Ð¸Ñ Ð½Ð°Ð¹Ð´ÐµÐ½Ð° и будет обработана.
+option_help_press_enter=11029_O_*** нажмите enter ***
+% Сообщени выдаетÑÑ Ð¿Ñ€Ð¸ поÑтраничном выводе Ñправки. Ðажатие клавиши ENTER
+% вызывает показ Ñледующей Ñтраницы. ЕÑли нажать q и затем ENTER, компилÑтор
+% завершает работу.
+option_start_reading_configfile=11030_H_Ðачало Ñ‡Ñ‚ÐµÐ½Ð¸Ñ Ñ„Ð°Ð¹Ð»Ð° конфигурации $1
+% Ðачало Ñ‡Ñ‚ÐµÐ½Ð¸Ñ Ñ„Ð°Ð¹Ð»Ð° конфигурации.
+option_end_reading_configfile=11031_H_Конец Ñ‡Ñ‚ÐµÐ½Ð¸Ñ Ñ„Ð°Ð¹Ð»Ð° конфигурации $1
+% Окончание Ñ‡Ñ‚ÐµÐ½Ð¸Ñ Ñ„Ð°Ð¹Ð»Ð° конфигурации.
+option_interpreting_option=11032_D_Ð¸Ð½Ñ‚ÐµÑ€Ð¿Ñ€ÐµÑ‚Ð°Ñ†Ð¸Ñ Ð¾Ð¿Ñ†Ð¸Ð¸ "$1"
+% КомпилÑтор интерпретирует опцию.
+option_interpreting_firstpass_option=11036_D_Ð¸Ð½Ñ‚ÐµÑ€Ð¿Ñ€ÐµÑ‚Ð°Ñ†Ð¸Ñ Ð¾Ð¿Ñ†Ð¸Ð¸ первого прохода "$1"
+% КомпилÑтор интерпретирует опцию в первый раз.
+option_interpreting_file_option=11033_D_Ð¸Ð½Ñ‚ÐµÑ€Ð¿Ñ€ÐµÑ‚Ð°Ñ†Ð¸Ñ Ð¾Ð¿Ñ†Ð¸Ð¸ из файла "$1"
+% КомпилÑтор интерпретирует опцию, прочитанную из файла конфигурации.
+option_read_config_file=11034_D_Чтение файла конфигурации "$1"
+% Ðачало Ñ‡Ñ‚ÐµÐ½Ð¸Ñ ÑƒÐºÐ°Ð·Ð°Ð½Ð½Ð¾Ð³Ð¾ файла конфигурации (отладочное Ñообщение).
+option_found_file=11035_D_найдено Ð¸Ð¼Ñ Ð¸Ñходного файла "$1"
+% Ð”Ð¾Ð¿Ð¾Ð»Ð½Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾Ð± опциÑÑ…, выводитÑÑ Ð¿Ñ€Ð¸
+% включенных отладочных ÑообщениÑÑ….
+option_code_page_not_available=11039_E_ÐеизвеÑÑ‚Ð½Ð°Ñ ÐºÐ¾Ð´Ð¾Ð²Ð°Ñ Ñтраница
+% Указана неизвеÑÑ‚Ð½Ð°Ñ ÐºÐ¾Ð´Ð¾Ð²Ð°Ñ Ñтраница Ð´Ð»Ñ Ð¸Ñходных файлов.
+% КомпилÑтор имеет вÑтроенную поддержку неÑкольких кодовых Ñтраниц.
+% Ð—Ð°Ð¿Ñ€Ð¾ÑˆÐµÐ½Ð½Ð°Ñ ÐºÐ¾Ð´Ð¾Ð²Ð°Ñ Ñтраница в их чиÑло не входит. Ð”Ð»Ñ Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ
+% поддержки потребуетÑÑ Ð¿ÐµÑ€ÐµÑборка компилÑтора.
+option_config_is_dir=11040_F_Файл конфигурации $1 - директориÑ
+% Директории Ð½ÐµÐ»ÑŒÐ·Ñ Ð¸Ñпользовать в качеÑтве файлов конфигурации.
+option_confict_asm_debug=11041_W_Выбранный тип аÑÑемблера "$1" не поддерживает отладочную информацию, отладка отключена
+% Выбранный аÑÑемблер не поддерживает генерацию отладочной информации,
+% поÑтому возможноÑÑ‚ÑŒ отладки отключена.
+option_ppc386_deprecated=11042_W_ИÑпользование ppc386.cfg ÑвлÑетÑÑ ÑƒÑтаревшим, вмеÑто него Ñледует иÑпользовать fpc.cfg
+% Using ppc386.cfg is still supported for historical reasons, however, for a multiplatform
+% system the naming makes no sense anymore. Please continue to use fpc.cfg instead.
+option_else_without_if=11043_F_Ð’ файле опций $1 Ñтрока $2 обнаружена директива \var{\#ELSE} без предварительной \var{\#IF(N)DEF}
+% В файле конфигурации обнаружена директива \var{\#ELSE} без предварительной директивы \var{\#IF(N)DEF}.
+option_unsupported_target=11044_F_ÐžÐ¿Ñ†Ð¸Ñ "$1" не поддерживаетÑÑ (или пока не поддерживаетÑÑ) Ð´Ð»Ñ Ñ†ÐµÐ»ÐµÐ²Ð¾Ð¹ платформы
+% Ðе вÑе опции поддерживаютÑÑ Ð¸Ð»Ð¸ реализованы Ð´Ð»Ñ Ð²Ñех платформ. Это Ñообщение о том,
+% что Ð²Ñ‹Ð±Ñ€Ð°Ð½Ð½Ð°Ñ Ð¾Ð¿Ñ†Ð¸Ñ Ð½ÐµÑовмеÑтима Ñ Ñ‚ÐµÐºÑƒÑ‰ÐµÐ¹ платформой.
+option_unsupported_target_for_feature=11045_F_ОÑобенноÑÑ‚ÑŒ "$1" не поддерживаетÑÑ (или пока не поддерживаетÑÑ) Ð´Ð»Ñ Ð²Ñ‹Ð±Ñ€Ð°Ð½Ð½Ð¾Ð¹ целевой платформы
+% Ðе вÑе опции поддерживаютÑÑ Ð¸Ð»Ð¸ реализованы Ð´Ð»Ñ Ð²Ñех платформ. Это Ñообщение о том,
+% что Ð²Ñ‹Ð±Ñ€Ð°Ð½Ð½Ð°Ñ Ð¾Ð¿Ñ†Ð¸Ñ Ð½ÐµÑовмеÑтима Ñ Ñ‚ÐµÐºÑƒÑ‰ÐµÐ¹ платформой.
+option_dwarf_smart_linking=11046_N_Ðа выбранной платформе Ð½ÐµÐ»ÑŒÐ·Ñ Ð¸Ñпользовать отладочную информацию типа DWARF ÑовмеÑтно Ñ "умной" компоновкой, переключение на ÑтатичеÑкую компоновку
+% "УмнаÑ" компоновка в наÑтоÑщее Ð²Ñ€ÐµÐ¼Ñ Ð½ÐµÑовмеÑтима Ñ Ð¾Ñ‚Ð»Ð°Ð´Ð¾Ñ‡Ð½Ð¾Ð¹ информацией типа DWARF на большинÑтве
+% платформ, поÑтому при выборе формата DWARF "умнаÑ" компоновка отключаетÑÑ.
+option_ignored_target=11047_W_ÐžÐ¿Ñ†Ð¸Ñ "$1" игнорируетÑÑ Ð´Ð»Ñ Ð²Ñ‹Ð±Ñ€Ð°Ð½Ð½Ð¾Ð¹ целевой платформы.
+% Ðе вÑе опции поддерживаютÑÑ Ð¸Ð»Ð¸ реализованы Ð´Ð»Ñ Ð²Ñех платформ. Это Ñообщение о том,
+% что Ð²Ñ‹Ð±Ñ€Ð°Ð½Ð½Ð°Ñ Ð¾Ð¿Ñ†Ð¸Ñ Ð¸Ð³Ð½Ð¾Ñ€Ð¸Ñ€ÑƒÐµÑ‚ÑÑ Ð´Ð»Ñ Ñ‚ÐµÐºÑƒÑ‰ÐµÐ¹ платформы.
+% \end{description}
+# EndOfTeX
+
+#
+# Whole program optimization
+#
+# 12019 is the last used one
+#
+# BeginOfTeX
+%
+% \section{Ð¡Ð¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð¾Ð¿Ñ‚Ð¸Ð¼Ð¸Ð·Ð°Ñ†Ð¸Ð¸ вÑей программы}
+% Раздел Ñодержит ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð¾Ð± ошибках, которые могут возникать
+% в процеÑÑе оптимизации вÑей программы (wpo).
+% \begin{description}
+wpo_cant_find_file=12000_F_Ðевозможно открыть файл данных WPO "$1"
+% КомпилÑтор не может открыть указанный файл Ñ Ð´Ð°Ð½Ð½Ñ‹Ð¼Ð¸ оптимизации вÑей программы.
+wpo_begin_processing=12001_D_Обработка информации WPO в файле "$1"
+% КомпилÑтор начинает обработку данных Ð´Ð»Ñ Ð¾Ð¿Ñ‚Ð¸Ð¼Ð¸Ð·Ð°Ñ†Ð¸Ð¸ вÑей программы в указанном файле.
+wpo_end_processing=12002_D_Закончена обработка информации WPO в файле "$1"
+% КомпилÑтор закончил обработку данных Ð´Ð»Ñ Ð¾Ð¿Ñ‚Ð¸Ð¼Ð¸Ð·Ð°Ñ†Ð¸Ð¸ вÑей программы в указанном файле.
+wpo_expected_section=12003_E_ОжидалÑÑ Ð·Ð°Ð³Ð¾Ð»Ð¾Ð²Ð¾Ðº Ñекции, но получено "$2" в Ñтроке $1 файла WPO-информации
+% При обработке файла оптимизации вÑей программы компилÑтор ожидал заголовок Ñекции (начинаетÑÑ Ñ \%),
+% но не нашел его.
+wpo_no_section_handler=12004_W_Ðе зарегиÑтрирован обработчик Ð´Ð»Ñ Ñекции "$2" в Ñтроке $1 файла WPO, игнорируетÑÑ
+% КомпилÑтор не имеет обработчика Ð´Ð»Ñ ÑƒÐ¿Ð¾Ð¼Ñнутой Ñекции файла WPO-информации,
+% поÑтому он пропуÑкает Ñту Ñекцию и переходит к Ñледующей.
+wpo_found_section=12005_D_Ðайдена ÑÐµÐºÑ†Ð¸Ñ "$1" Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸ÐµÐ¹ о "$2"
+% КомпилÑтор обнаружил в файле WPO Ñекцию Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸ÐµÐ¹, которую он может обработать.
+wpo_no_input_specified=12006_F_Выбранные режимы оптимизации вÑей программы требуют предварительно Ñозданного файла обратной ÑвÑзи (укажите Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ -Fw)
+% Чтобы выполнить выбранную оптимизацию вÑей программы, компилÑтору требуетÑÑ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ,
+% ÑÐ¾Ð±Ñ€Ð°Ð½Ð½Ð°Ñ Ð² процеÑÑе предыдущей компилÑции. Файл, Ñодержащий Ñту информацию, должен быть указан
+% Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ ключа -Fw.
+wpo_not_enough_info=12007_E_Файл обратной ÑвÑзи не Ñодержит информации, необходимой Ð´Ð»Ñ Ð¿Ñ€Ð¾Ð²ÐµÐ´ÐµÐ½Ð¸Ñ Ð¾Ð¿Ñ‚Ð¸Ð¼Ð¸Ð·Ð°Ñ†Ð¸Ð¸ "$1"
+% Указанный файл обратной ÑвÑзи не Ñодержит информацию, ÐºÐ¾Ñ‚Ð¾Ñ€Ð¾Ð°Ñ Ð½ÑƒÐ¶Ð½Ð° Ð´Ð»Ñ Ð¿Ñ€Ð¾Ð²ÐµÐ´ÐµÐ½Ð¸Ñ Ñ‚Ñ€ÐµÐ±ÑƒÐµÐ¼Ð¾Ð³Ð¾ вида
+% оптимизации. Скорее вÑего, нужно перекомпилировать программу, указав подходÑщий ключ -OWxxx.
+wpo_no_output_specified=12008_F_Укажите файл обратной ÑвÑзи Ð´Ð»Ñ Ð·Ð°Ð¿Ð¸Ñи Ñобранной информации (Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ -FW)
+% Ðеобходимо указать файл, в который компилÑтор запишет Ñобранные во Ð²Ñ€ÐµÐ¼Ñ ÐºÐ¾Ð¼Ð¿Ð¸Ð»Ñции
+% данные Ð´Ð»Ñ Ð¾Ð¿Ñ‚Ð¸Ð¼Ð¸Ð·Ð°Ñ†Ð¸Ð¸ вÑей программы. Это делаетÑÑ Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ ключа -FW.
+wpo_output_without_info_gen=12009_E_Файл обратной ÑвÑзи указан (Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ -FW), но не указан требуемый тип Ñобираемой информации
+% Помимо ÑƒÐºÐ°Ð·Ð°Ð½Ð¸Ñ Ð¸Ð¼ÐµÐ½Ð¸ файла обратной ÑвÑзи wpo Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ -FW, Ñледует указывать
+% требуемые виды оптимизации Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ -OWxxx, иначе Ð¿Ð¾Ð»ÐµÐ·Ð½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð² файл запиÑана
+% не будет.
+wpo_input_without_info_use=12010_E_Файл обратной ÑвÑзи указан (Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ -Fw), но не указан тип оптимизации, который Ñледует выполнить
+% ЕÑли указан файл обратной ÑвÑзи wpo Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ -Fw, но не заданы виды оптимизации Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ -Owxxx,
+% будет выдана Ð´Ð°Ð½Ð½Ð°Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ°. Указанные ключи Ñледует иÑпользовать ÑовмеÑтно.
+wpo_skipping_unnecessary_section=12011_D_Ð¡ÐµÐºÑ†Ð¸Ñ wpo пропущена "$1", поÑкольку не требуетÑÑ Ð´Ð»Ñ Ð·Ð°Ð¿Ñ€Ð¾ÑˆÐµÐ½Ð½Ñ‹Ñ… оптимизаций
+% Файл обратной ÑвÑзи wpo Ñодержит Ñекцию Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸ÐµÐ¹, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð½Ðµ требуетÑÑ
+% Ð´Ð»Ñ Ð¿Ñ€Ð¾Ð²ÐµÐ´ÐµÐ½Ð¸Ñ Ð²Ñ‹Ð±Ñ€Ð°Ð½Ð½Ñ‹Ñ… типов оптимизации.
+wpo_duplicate_wpotype=12012_W_ИнформациÑ, ранее Ð¿Ñ€Ð¾Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ð°Ñ Ð¸Ð· файла обратной ÑвÑзи Ð´Ð»Ñ "$1", перекрываетÑÑ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸ÐµÐ¹ из Ñекции "$2"
+% Файл обратной ÑвÑзи wpo Ñодержит неÑколько Ñекций Ñ Ð¾Ð´Ð½Ð¾Ñ‚Ð¸Ð¿Ð½Ð¾Ð¹ информацией (например,
+% о том, какие виртуальные методы могут быть де-виртуализированы). Ð’ Ñтом Ñлучае иÑпользуетÑÑ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ
+% из поÑледней Ñекции. Включите отладочные ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ (-vd), чтобы увидеть, какие клаÑÑÑ‹ информации ÑодержатÑÑ
+% в каждой из Ñекций.
+wpo_cannot_extract_live_symbol_info_strip=12013_E_Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ живучеÑти Ñимволов не может быть получена из программы без отладочной информации, иÑпользуйте -Xs-
+% Ðекоторые ÑпоÑобы Ñбора информации о живучеÑти Ñимволов предполагают анализ Ñимвольной информации
+% готовой программы. ЕÑли Ñта Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ ÑƒÐ´Ð°Ð»ÐµÐ½Ð° (Ð¾Ð¿Ñ†Ð¸Ñ -Xs), такой анализ невозможен.
+wpo_cannot_extract_live_symbol_info_no_link=12014_E_Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ живучеÑти Ñимволов не может быть получена без Ñкомпонованной программы
+% Ðекоторые ÑпоÑобы Ñбора информации о живучеÑти Ñимволов предполагают анализ Ñимвольной информации
+% готовой программы. ЕÑли программа не Ñкомпонована, такой анализ невозможен.
+wpo_cannot_find_symbol_progs=12015_F_Ðе найдены "$1" или "$2" Ð´Ð»Ñ Ð¸Ð·Ð²Ð»ÐµÑ‡ÐµÐ½Ð¸Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ð¸ о Ñимволах из Ñкомпонованной программы
+% Ðекоторые ÑпоÑобы Ñбора информации о живучеÑти Ñимволов иÑпользуют вÑпомогательные программы
+% Ð´Ð»Ñ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ð¸ о Ñимволах программы. Обычно Ñто программа 'nm', входÑÑ‰Ð°Ñ Ð² ÑоÑтав GNU binutils.
+wpo_error_reading_symbol_file=12016_E_Ошибка Ñ‡Ñ‚ÐµÐ½Ð¸Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ð¸ о живучеÑти Ñимволов, полученной от "$1"
+% При получении информации о Ñимволах Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ вÑпомогательной программы ('nm' или 'objdump') произошла
+% ошибка. Вывод вÑпомогательной программы оказалÑÑ ÐºÐ¾Ñ€Ð¾Ñ‡Ðµ ожидаемого, или имеет неверный формат.
+wpo_error_executing_symbol_prog=12017_F_Ошибка Ð²Ñ‹Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ "$1" (код выхода: $2) при извлечении информации о Ñимволах
+% При получении информации о Ñимволах Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ вÑпомогательной программы ('nm' или 'objdump') произошла
+% ошибка. Ð’ÑÐ¿Ð¾Ð¼Ð¾Ð³Ð°Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð¼Ð° вернула указанный код ошибки.
+wpo_symbol_live_info_needs_smart_linking=12018_E_Сбор информации о живучеÑти Ñимволов полезен только при "умной" компоновке, иÑпользуйте -CX -XX
+% ЖивучеÑÑ‚ÑŒ Ñимвола определÑетÑÑ Ñ„Ð°ÐºÑ‚Ð¾Ð¼ его Ð½Ð°Ð»Ð¸Ñ‡Ð¸Ñ Ð² готовой Ñкомпонованной программе. ЕÑли отключена
+% "умнаÑ" компоновка, вÑе Ñимволы вкючаютÑÑ Ð² программу незавиÑимо от того, иÑпользуютÑÑ Ð¾Ð½Ð¸ или нет.
+% Это делает Ñбор информации о живучеÑти Ñимволов беÑÑмыÑленным.
+wpo_cant_create_feedback_file=12019_E_Ðевозможно Ñоздать файл обратной ÑвÑзи "$1"
+% Файл обратной ÑвÑзи wpo, указанный Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ ключа -FW, не может быть Ñоздан.
+%\end{description}
+# EndOfTeX
+
+
+#
+# Logo (option -l)
+#
+option_logo=11023_[
+КомпилÑтор Free Pascal верÑии $FPCFULLVERSION [$FPCDATE] Ð´Ð»Ñ $FPCCPU
+Copyright (c) 1993-2011 by Florian Klaempfl
+]
+
+#
+# Info (option -i)
+#
+option_info=11024_[
+Free Pascal Compiler version $FPCVERSION
+
+Compiler Date : $FPCDATE
+Compiler CPU Target: $FPCCPU
+
+Поддерживаемые платформы:
+ $OSTARGETS
+
+Поддерживаемые наборы команд CPU:
+ $INSTRUCTIONSETS
+
+Поддерживаемые наборы команд FPU:
+ $FPUINSTRUCTIONSETS
+
+Поддерживаемые ABI:
+ $ABITARGETS
+
+Поддерживаемые оптимизации:
+ $OPTIMIZATIONS
+
+Поддерживаемые оптимизации вÑей программы:
+ All
+ $WPOPTIMIZATIONS
+
+Поддерживаемые типы микроконтроллеров:
+ $CONTROLLERTYPES
+
+This program comes under the GNU General Public Licence
+For more information read COPYING.FPC
+
+Report bugs, suggestions, etc. to:
+ http://bugs.freepascal.org
+or
+ bugs@freepascal.org
+]
+
+#
+# Help pages (option -? and -h)
+#
+# The first character on the line indicates who will display this
+# line, the current possibilities are :
+# * = every target
+# 3 = 80x86 targets
+# 6 = 680x0 targets
+# e = in extended debug mode only
+# P = PowerPC targets
+# S = Sparc targets
+# V = Virtual machine targets
+# The second character also indicates who will display this line,
+# (if the above character was TRUE) the current possibilities are :
+# * = everyone
+# g = with GDB info supported by the compiler
+# O = OS/2
+# L = UNIX systems
+# The third character represents the indentation level.
+#
+option_help_pages=11025_[
+**0*_Добавьте '+' поÑле опции булева ключа Ð´Ð»Ñ ÐµÐ³Ð¾ Ð²ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ð¸ '-' Ð´Ð»Ñ Ð¾Ñ‚ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ
+**1a_КомпилÑтор не удалÑет Ñозданный аÑÑемблерный файл
+**2al_Вывод номеpов Ñтрок в аÑÑемблерный файл
+**2an_Вывод информации об узлах графа в аÑÑемблерный файл
+*L2ap_ИÑпользовать пайпы вмеÑто временных аÑÑемблерный файлов
+**2ar_ПеречиÑлÑÑ‚ÑŒ выделениÑ/оÑÐ²Ð¾Ð±Ð¾Ð¶Ð´ÐµÐ½Ð¸Ñ pегиÑÑ‚pов в аÑÑемблеpном файле
+**2at_ПеречиÑлÑÑ‚ÑŒ выделениÑ/оÑÐ²Ð¾Ð±Ð¾Ð¶Ð´ÐµÐ½Ð¸Ñ Ð²pеменных пеpеменных в аÑÑемблеpном файле
+**1A<x>_Формат вывода:
+**2Adefault_ÐÑÑемблер по умолчанию
+3*2Aas_ÐÑÑемблер GNU AS
+3*2Anasmcoff_COFF файл (Go32v2), иÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ Nasm
+3*2Anasmelf_ELF32 файл (Linux), иÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ Nasm
+3*2Anasmwin32_Win32 объектный файл, иÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ Nasm
+3*2Anasmwdosx_Win32/WDOSX объектный файл, иÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ Nasm
+3*2Awasm_Obj файл, иÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ Wasm (Watcom)
+3*2Anasmobj_Obj файл, иÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ Nasm
+3*2Amasm_Obj файл, иÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ Masm (Microsoft)
+3*2Atasm_Obj файл, иÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ Tasm (Borland)
+3*2Aelf_ELF (Linux) иÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ Ð²Ð½ÑƒÑ‚Ñ€ÐµÐ½Ð½Ð¸Ð¹ генератор
+3*2Acoff_COFF (Go32v2) иÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ Ð²Ð½ÑƒÑ‚Ñ€ÐµÐ½Ð½Ð¸Ð¹ генератор
+3*2Apecoff_PE-COFF (Win32) иÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ Ð²Ð½ÑƒÑ‚Ñ€ÐµÐ½Ð½Ð¸Ð¹ генератор
+4*2Aas_ÐÑÑемблер GNU AS
+6*2Aas_Unix o-файл, иÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ GNU AS
+6*2Agas_GNU Motorola аÑÑемблер
+6*2Amit_СинтакÑÐ¸Ñ MIT (Ñтарый GAS)
+6*2Amot_Стандартный аÑÑемблер Motorola
+A*2Aas_ÐÑÑемблер GNU AS
+P*2Aas_ÐÑÑемблер GNU AS
+S*2Aas_ÐÑÑемблер GNU AS
+**1b_Генеpиpовать инфоpмацию Ð´Ð»Ñ Ð±pаyзеpа (IDE)
+**2bl_Генеpиpовать также инфоpмацию о локальных Ñимволах
+**1B_ПеpеÑборка вÑех модyлей
+**1C<x>_Опции генеpатора кода:
+**2Ca<x>_Выбор ABI, Ñм. fpc -i Ð´Ð»Ñ Ð²Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ñ‹Ñ… значений
+**2Cb_Генерировать big-endian код
+**2Cc<x>_УÑтановить тип вызова по умолчанию в <x>
+**2CD_Создать также динамичеÑкyÑŽ библиотекy (не поддеpживаетÑÑ)
+**2Ce_Компилировать Ñ Ñмулированными инÑтрукциÑми Ñ Ð¿Ð»Ð°Ð²Ð°ÑŽÑ‰ÐµÐ¹ запÑтой
+**2Cf<x>_Выбор набора команд ÑопроцеÑÑора, Ñм. fpc -i Ð´Ð»Ñ Ð²Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ñ‹Ñ… значений
+**2CF<x>_ÐœÐ¸Ð½Ð¸Ð¼Ð°Ð»ÑŒÐ½Ð°Ñ Ñ‚Ð¾Ñ‡Ð½Ð¾ÑÑ‚ÑŒ конÑтант Ñ Ð¿Ð»Ð°Ð²Ð°ÑŽÑ‰ÐµÐ¹ запÑтой (default, 32, 64)
+**2Cg_Генерировать позиционно-незавиÑимый код (PIC)
+**2Ch<n>_<n> байт кyчи (от 1023 до 67107840)
+**2Ci_Пpовеpка ввода-вывода
+**2Cn_ПpопyÑтить Ñтадию компоновки
+**2Co_Пpовеpка Ð¿ÐµÑ€ÐµÐ¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ñ†ÐµÐ»Ð¾Ñ‡Ð¸Ñленных операций
+**2CO_Проверка возможного Ð¿ÐµÑ€ÐµÐ¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ñ†ÐµÐ»Ð¾Ñ‡Ð¸Ñленных операций
+**2Cp<x>_Выбор набора команд, Ñм. fpc -i Ð´Ð»Ñ Ð²Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ñ‹Ñ… значений
+**2CP<x>=<y>_ наÑтройки упаковки
+**3CPPACKSET=<y>_ <y> упаковка множеÑтв: 0, 1 или DEFAULT или NORMAL, 2, 4 и 8
+**2Cr_Пpовеpка диапазонов
+**2CR_Проверка правильноÑти вызова методов объектов
+**2Cs<n>_УÑтановить pазмеp Ñтека в <n>
+**2Ct_Проверка Ñтека (только теÑтирование, Ñм. руководÑтво)
+**2CX_Создать также smartlink-библиотеку
+**1d<x>_Опpеделить Ñимвол <x>
+**1D_Создать DEF-файл
+**2Dd<x>_УÑтановить опиÑание в <x>
+**2Dv<x>_УÑтановить верÑию DLL в <x>
+*O2Dw_Приложение PM
+**1e<x>_УÑтановить пyÑ‚ÑŒ Ð´Ð»Ñ Ð¸ÑполнÑемых файлов
+**1E_То же, что и -Cn
+**1fPIC_То же, что и -Cg
+**1F<x>_УÑтановка имен и путей файлов
+**2Fa<x>[,y]_(Ð´Ð»Ñ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð¼Ñ‹) загрузить модули <x> и [y] перед чтением Ñекции uses
+**2Fc<x>_УÑтановить кодовую Ñтраницу иÑходного файла в <x>
+**2FC<x>_УÑтановить Ð¸Ð¼Ñ ÐºÐ¾Ð¼Ð¿Ð¸Ð»Ñтора реÑурÑов (.rc) в <x>
+**2Fd_Отключить внутренний кÑш директорий компилÑтора
+**2FD<x>_УÑтановить пyÑ‚ÑŒ поиÑка утилит компилÑтора
+**2Fe<x>_Пеpенапpавить вывод ошибок в <x>
+**2Ff<x>_Добавить <x> к пути фреймворка (только Darwin)
+**2FE<x>_УÑтановить путь вывода exe/модулей в <x>
+**2Fi<x>_Добавить <x> к пyÑ‚Ñм включаемых файлов
+**2Fl<x>_Добавить <x> к пyÑ‚Ñм библиотек
+**2FL<x>_ИÑпользовать <x> как динамичеÑкий компоновщик
+**2Fm<x>_Загрузить таблицу Ð¿Ñ€ÐµÐ¾Ð±Ñ€Ð°Ð·Ð¾Ð²Ð°Ð½Ð¸Ñ unicode из <x>.txt в директории компилÑтора
+**2Fo<x>_Добавить <x> к пyÑ‚Ñм объектных файлов
+**2Fr<x>_Загpyзить файл Ñообщений об ошибках <x>
+**2FR<x>_УÑтановить Ð¸Ð¼Ñ ÐºÐ¾Ð¼Ð¿Ð¾Ð½Ð¾Ð²Ñ‰Ð¸ÐºÐ° реÑурÑов (.res) в <x>
+**2Fu<x>_Добавить <x> к путÑм модулей
+**2FU<x>_УÑтановить пyÑ‚ÑŒ вывода модyлей в <x>, отменÑет -FE
+**2FW<x>_ЗапиÑать файл обратной ÑвÑзи оптимизации вÑей программы в <x>
+**2Fw<x>_Загрузить ранее Ñозданный файл обратной ÑвÑзи из <x>
+*g1g_Создавать отладочную информацию (формате по умолчанию Ð´Ð»Ñ Ñ†ÐµÐ»ÐµÐ²Ð¾Ð¹ платформы)
+*g2gc_Создавать проверки указателей
+*g2gh_ИÑпользовать модyль heaptrc (Ð´Ð»Ñ Ð¾Ñ‚Ð»Ð°Ð´ÐºÐ¸ yтечек/повреждений памÑти)
+*g2gl_ИÑпользовать модуль lineinfo (больше информации о Ñтеке вызовов)
+*g2go<x>_Опции отладочной информации
+*g3godwarfsets_ Включить информацию о множеÑтвах DWARF (ломает gdb < 6.5)
+*g3gostabsabsincludes_ СохранÑÑ‚ÑŒ абÑолютные/полные пути включаемых файлов в Stabs
+*g2gp_СохранÑÑ‚ÑŒ региÑÑ‚Ñ€ в именах Ñимволов stabs
+*g2gs_ÐžÑ‚Ð»Ð°Ð´Ð¾Ñ‡Ð½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð² формате Stabs
+*g2gt_Затирать локальные переменные (выÑвление иÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð±ÐµÐ· инициализации)
+*g2gv_Поддержка траÑÑировки Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ Valgrind
+*g2gw_ÐžÑ‚Ð»Ð°Ð´Ð¾Ñ‡Ð½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð² формате DWARFv2 (то же, что и -gw2)
+*g2gw2_ÐžÑ‚Ð»Ð°Ð´Ð¾Ñ‡Ð½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð² формате DWARFv2
+*g2gw3_ÐžÑ‚Ð»Ð°Ð´Ð¾Ñ‡Ð½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð² формате DWARFv3
+**1i_ИнфоpмациÑ
+**2iD_Вернуть датy компилÑтоpа
+**2iV_Вернуть короткую веpÑию компилÑтора
+**2iW_Вернуть полную верÑию компилÑтора
+**2iSO_Вернуть тип ОС компилÑтора
+**2iSP_Вернуть тип пpоцеÑÑоpа компилÑтора
+**2iTO_Вернуть тип целевой ОС
+**2iTP_Вернуть тип целевого пpоцеÑÑоpа
+**1I<x>_Добавить <x> к пyти до включаемых файлов
+**1k<x>_Передать <x> компоновщикy
+**1l_ВывеÑти логотип
+**1M<x>_УÑтановить режим Ñзыка в <x>
+**2Mfpc_Диалект Free Pascal (по умолчанию)
+**2Mobjfpc_Режим FPC Ñ Ð¿Ð¾Ð´Ð´ÐµÑ€Ð¶ÐºÐ¾Ð¹ Object Pascal
+**2Mdelphi_Режим ÑовмеÑтимоÑти Ñ Delphi 7
+**2Mtp_Режим ÑовмеÑтимоÑти Ñ TP/BP 7.0
+**2Mmacpas_Режим ÑовмеÑтимоÑти Ñ Ð´Ð¸Ð°Ð»ÐµÐºÑ‚Ð°Ð¼Ð¸ Macintosh Pascal
+**1n_Ðе читать Ñтандаpтные файлы конфигурации
+**1N<x>_ÐžÐ¿Ñ‚Ð¸Ð¼Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð³Ñ€Ð°Ñ„Ð°
+**2Nu_Разворачивать циклы
+**1o<x>_Изменить Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑƒÑ‡Ð°ÐµÐ¼Ð¾Ð³Ð¾ иÑполнÑемого файла на <x>
+**1O<x>_Оптимизации:
+**2O-_Отключить оптимизации
+**2O1_Оптимизации ÑƒÑ€Ð¾Ð²Ð½Ñ 1 (быÑтро и ÑовмеÑтимо Ñ Ð¾Ñ‚Ð»Ð°Ð´Ñ‡Ð¸ÐºÐ¾Ð¼)
+**2O2_Оптимизации ÑƒÑ€Ð¾Ð²Ð½Ñ 2 (-O1 + быÑтрые оптимизации)
+**2O3_Оптимизации ÑƒÑ€Ð¾Ð²Ð½Ñ 3 (-O2 + медленные оптимизации)
+**2Oa<x>=<y>_УÑтановить выравнивание
+**2Oo[NO]<x>_Включить или отключить отдельные оптимизации, Ñм. fpc -i Ð´Ð»Ñ Ð²Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ñ‹Ñ… значений
+**2Op<x>_Задать процеÑÑор Ð´Ð»Ñ Ð¾Ð¿Ñ‚Ð¸Ð¼Ð¸Ð·Ð°Ñ†Ð¸Ð¸, Ñм. fpc -i Ð´Ð»Ñ Ð²Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ñ‹Ñ… значений
+**2OW<x>_Ð“ÐµÐ½ÐµÑ€Ð°Ñ†Ð¸Ñ Ñ„Ð°Ð¹Ð»Ð° обратной ÑвÑзи wpo Ð´Ð»Ñ Ð¾Ð¿Ñ‚Ð¸Ð¼Ð¸Ð·Ð°Ñ†Ð¸Ð¸ <x>, Ñм. fpc -i Ð´Ð»Ñ Ð²Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ñ‹Ñ… значений
+**2Ow<x>_Выполнить оптимизацию <x> вÑей программы, Ñм. fpc -i Ð´Ð»Ñ Ð²Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ñ‹Ñ… значений
+**2Os_ÐžÐ¿Ñ‚Ð¸Ð¼Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð¿Ð¾ размеру вмеÑто ÑкороÑти
+**1pg_ГенеpÐ°Ñ†Ð¸Ñ ÐºÐ¾Ð´Ð° Ð´Ð»Ñ Ð¿Ñ€Ð¾Ñ„Ð¸Ð»Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ gprof (опpеделÑет Ñимвол FPC_PROFILE)
+**1R<x>_Стиль Ñ‡Ñ‚ÐµÐ½Ð¸Ñ Ð°ÑÑемблера:
+**2Rdefault_ÐÑÑемблер по умолчанию Ð´Ð»Ñ Ñ†ÐµÐ»ÐµÐ²Ð¾Ð¹ платформы
+3*2Ratt_Чтение аÑÑемблера в Ñтиле AT&T
+3*2Rintel_Чтение аÑÑемблера в Ñтиле Intel
+6*2RMOT_Чтение аÑÑемблера в Ñтиле Motorola
+**1S<x>_Опции ÑинтакÑиÑа:
+**2S2_То же, что и -Mobjfpc
+**2Sc_Поддеpжка операторов как в C (*=,+=,/= и -=)
+**2sa_Включить проверки Assert
+**2Sd_То же, что и -Mdelphi
+**2Se<x>_Опции ошибок. <x> - ÐºÐ¾Ð¼Ð±Ð¸Ð½Ð°Ñ†Ð¸Ñ Ñледующих Ñимволов:
+**3*_<n> : ОÑтановка компилÑции поÑле <n> ошибок (по умолчанию 1)
+**3*_w : КомпилÑтор также оÑтанавливаетÑÑ Ð¿Ð¾Ñле предупреждений
+**3*_n : КомпилÑтор также оÑтанавливаетÑÑ Ð¿Ð¾Ñле заметок
+**3*_h : КомпилÑтор также оÑтанавливаетÑÑ Ð¿Ð¾Ñле подÑказок
+**2Sg_Разрешить LABEL и GOTO (по умолчанию в -Mtp и -Mdelphi)
+**2Sh_ИÑпользовать ÑÑ‚pоки ansistring по умолчанию вмеÑто shortstring
+**2Si_Включить вÑтраивание процедур/функций, объÑвленных как "inline"
+**2Sk_Загрузить модуль fpcylix
+**2SI<x>_УÑтановить Ñтиль интерфейÑов в <x>
+**3SIcom_COM-ÑовмеÑтимые интерфейÑÑ‹ (по умолчанию)
+**3SIcorba_CORBA-ÑовмеÑтимые интерфейÑÑ‹
+**2Sm_Поддеpжка макрокоманд как в C (глобально)
+**2So_То же, что и -Mtp
+**2Ss_Имена конÑтрукторов/деÑтрукторов должны быть init/done
+**2Sx_Поддержка ключевых Ñлов иÑключений (по умолчанию в режимах Delphi/ObjFPC)
+**1s_Ðе вызывать аÑÑемблер и компоновщик
+**2sh_Создать Ñкрипт Ð´Ð»Ñ ÐºÐ¾Ð¼Ð¿Ð¾Ð½Ð¾Ð²ÐºÐ¸ на хоÑте
+**2st_Создать Ñкрипт Ð´Ð»Ñ ÐºÐ¾Ð¼Ð¿Ð¾Ð½Ð¾Ð²ÐºÐ¸ на платформе назначениÑ
+**2sr_ПропуÑтить фазу раÑÐ¿Ñ€ÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ Ñ€ÐµÐ³Ð¸Ñтров (иÑпользуетÑÑ Ñ -alr)
+**1T<x>_ÐžÐ¿ÐµÑ€Ð°Ñ†Ð¸Ð¾Ð½Ð½Ð°Ñ ÑиÑтема назначениÑ:
+3*2Temx_OS/2 через EMX (Ð²ÐºÐ»ÑŽÑ‡Ð°Ñ Ñ€Ð°Ñширитель EMX/RSX)
+3*2Tfreebsd_FreeBSD
+3*2Tgo32v2_ВерÑÐ¸Ñ 2 раÑÑˆÐ¸Ñ€Ð¸Ñ‚ÐµÐ»Ñ DOS DJ Delorie
+3*2Tlinux_Linux
+3*2Tnetbsd_NetBSD
+3*2Tnetware_Модуль Novell Netware (clib)
+3*2Tnetwlibc_Модуль Novell Netware (libc)
+3*2Topenbsd_OpenBSD
+3*2Tos2_OS/2 / eComStation
+3*2Tsunos_SunOS/Solaris
+3*2Tsymbian_Symbian OS
+3*2Twatcom_Watcom-ÑовмеÑтимый раÑширитель DOS
+3*2Twdosx_РаÑширитель DOS WDOSX
+3*2Twin32_Windows 32 бита
+3*2Twince_Windows CE
+4*2Tlinux_Linux
+6*2Tamiga_Commodore Amiga
+6*2Tatari_Atari ST/STe/TT
+6*2Tlinux_Linux/m68k
+6*2Tmacos_Macintosh m68k (не поддерживаетÑÑ)
+6*2Tpalmos_PalmOS
+A*2Tlinux_Linux
+A*2Twince_Windows CE
+P*2Tamiga_AmigaOS на PowerPC
+P*2Tdarwin_Darwin и Mac OS X на PowerPC
+P*2Tlinux_Linux на PowerPC
+P*2Tmacos_Mac OS (classic) на PowerPC
+P*2Tmorphos_MorphOS
+S*2Tlinux_Linux
+**1u<x>_yдалÑет опpеделение Ñимвола <x>
+**1U_Опции модyлей:
+**2Un_Ðе пpовеpÑÑ‚ÑŒ ÑоответÑтвие имени модyÐ»Ñ Ð¸ имени файла
+**2Ur_Генерировать релизные файлы модулей (не перекомпилируютÑÑ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡ÐµÑки)
+**2Us_Компилиpовать модyль system
+**1v<x>_Уровень подpобноÑти. <x> - ÐºÐ¾Ð¼Ð±Ð¸Ð½Ð°Ñ†Ð¸Ñ Ñледyющих Ñимволов:
+**2*_e : Ошибки (по умолчанию) 0 : Ðичего (кроме ошибок)
+**2*_w : ÐŸÑ€ÐµÐ´ÑƒÐ¿Ñ€ÐµÐ¶Ð´ÐµÐ½Ð¸Ñ u : Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ модулÑÑ…
+**2*_n : ÐŸÑ€Ð¸Ð¼ÐµÑ‡Ð°Ð½Ð¸Ñ t : Попробованные/иÑпользованные файлы
+**2*_h : ПодÑказки c : УÑловные выражениÑ
+**2*_i : ÐžÐ±Ñ‰Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ d : Отладочные ÑообщениÑ
+**2*_l : Hомеpа Ñтрок c : Режим ÑовмеÑтимоÑти Ñ Rhide/GCC
+**2*_s : Отметки времени q : Ðомера Ñообщений
+**2*_a : Показывать вÑе x : Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ иÑполнÑемом файле (только Win32)
+**2*_b : Ð¡Ð¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð¾ файлах p : ЗапиÑÑŒ tree.log Ñ Ð³Ñ€Ð°Ñ„Ð¾Ð¼ разбора
+**2*_ Ñ Ð¿Ð¾Ð»Ð½Ñ‹Ð¼Ð¸ путÑми x : ЗапиÑÑŒ fpcdebug.txt Ñ Ð¿Ð¾Ð´Ñ€Ð¾Ð±Ð½Ð¾Ð¹
+**2*_ именно в ней отладочной информацией
+**2*_m<x>,<y> : Ðе показывать ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ñ Ð½Ð¾Ð¼ÐµÑ€Ð°Ð¼Ð¸ <x> и <y>
+3*1W<x>_Платформенно-Ñпецифичные опции (платформы)
+A*1W<x>_Платформенно-Ñпецифичные опции (платформы)
+P*1W<x>_Платформенно-Ñпецифичные опции (платформы)
+p*1W<x>_Платформенно-Ñпецифичные опции (платформы)
+3*2Wb_Создавать bundle вмеÑто библиотеки (Darwin)
+P*2Wb_Создавать bundle вмеÑто библиотеки (Darwin)
+p*2Wb_Создавать bundle вмеÑто библиотеки (Darwin)
+3*2WB_Создавать перемещаемый образ (Windows)
+A*2WB_Создавать перемещаемый образ (Windows, Symbian)
+3*2WC_Указать конÑольный тип Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ (EMX, OS/2, Windows)
+A*2WC_Указать конÑольный тип Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ (Windows)
+P*2WC_Указать конÑольный тип Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ (Classic Mac OS)
+3*2WD_ИÑпользовать DEFFILE Ð´Ð»Ñ ÑкÑпорта функции DLL или EXE (Windows)
+A*2WD_ИÑпользовать DEFFILE Ð´Ð»Ñ ÑкÑпорта функции DLL или EXE (Windows)
+3*2We_ИÑпользовать внешние реÑурÑÑ‹ (Darwin)
+P*2We_ИÑпользовать внешние реÑурÑÑ‹ (Darwin)
+p*2We_ИÑпользовать внешние реÑурÑÑ‹ (Darwin)
+3*2WF_Указать полноÑкранный тип Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ (EMX, OS/2)
+3*2WG_Указать графичеÑкий тип Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ (EMX, OS/2, Windows)
+A*2WG_Указать графичеÑкий тип Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ (Windows)
+P*2WG_Указать графичеÑкий тип Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ (Classic Mac OS)
+3*2Wi_ИÑпользовать внутренние реÑурÑÑ‹ (Darwin)
+P*2Wi_ИÑпользовать внутренние реÑурÑÑ‹ (Darwin)
+p*2Wi_ИÑпользовать внутренние реÑурÑÑ‹ (Darwin)
+3*2WN_Ðе генерировать код перемещениÑ, нужно Ð´Ð»Ñ Ð¾Ñ‚Ð»Ð°Ð´ÐºÐ¸ (Windows)
+A*2WN_Ðе генерировать код перемещениÑ, нужно Ð´Ð»Ñ Ð¾Ñ‚Ð»Ð°Ð´ÐºÐ¸ (Windows)
+3*2WR_Генерировать код Ð¿ÐµÑ€ÐµÐ¼ÐµÑ‰ÐµÐ½Ð¸Ñ (Windows)
+A*2WR_Генерировать код Ð¿ÐµÑ€ÐµÐ¼ÐµÑ‰ÐµÐ½Ð¸Ñ (Windows)
+P*2WT_Указать тип Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ MPW tool (Classic Mac OS)
+3*2WX_Разрешить иÑполнÑемый Ñтек (Linux)
+A*2WX_Разрешить иÑполнÑемый Ñтек (Linux)
+p*2WX_Разрешить иÑполнÑемый Ñтек (Linux)
+P*2WX_Разрешить иÑполнÑемый Ñтек (Linux)
+**1X_опции выполнениÑ
+**2Xc_Передать компоновщику --shared/-dynamic (BeOS, Darwin, FreeBSD, Linux)
+**2Xd_Ðе иÑпользовать Ñтандартный путь поиÑка библиотек (нужно Ð´Ð»Ñ ÐºÑ€Ð¾ÑÑкомпилÑции)
+**2Xe_ИÑпользовать внешний компоновщик
+**2Xg_Создать отладочную информацию в отдельном файле и добавить Ñекцию debuglink в иÑполнÑемый файл
+**2XD_Попробовать Ñкомпоновать динамичеÑки (определÑет Ñимвол FPC_LINK_DYNAMIC)
+**2Xi_ИÑпользовать внутренний компоновщик
+**2Xm_Создать карту компоновки
+**2XM<x>_Задать Ð¸Ð¼Ñ Ð¾Ñновной точки входа 'main' (по умолчанию 'main')
+**2XP<x>_Добавить к именам binutils Ð¿Ñ€ÐµÑ„Ð¸ÐºÑ <x>
+**2Xr<x>_УÑтановить rlink-path компоновщика в <x> (нужно Ð´Ð»Ñ ÐºÑ€Ð¾ÑÑкомпилÑции, Ñм. руководÑтво ld) (BeOS, Linux)
+**2XR<x>_Добавит Ð¿Ñ€ÐµÑ„Ð¸ÐºÑ <x> ко вÑем путÑм поиÑка компоновщика (BeOS, Darwin, FreeBSD, Linux, Mac OS, Solaris)
+**2Xs_Убрать вÑе Ñимволы из иÑполнÑемого файла
+**2XS_Попробовать Ñкомпоновать ÑтатичеÑки (по умолчанию, определÑет Ñимвол FPC_LINK_STATIC)
+**2Xt_Компоновка Ñо ÑтатичеÑкими библиотеками (компоновщику передаетÑÑ -static)
+**2XX_Попробовать "умную" компоновку (определÑет Ñимвол FPC_LINK_SMART)
+**1*_
+**1?_показать ÑÑ‚y Ñправкy
+**1h_показать ÑÑ‚y Ñправкy без ожиданиÑ
+]
+
+#
+# The End...
diff --git a/closures/compiler/msg/errorues.msg b/closures/compiler/msg/errorues.msg
new file mode 100644
index 0000000000..64ebb12297
--- /dev/null
+++ b/closures/compiler/msg/errorues.msg
@@ -0,0 +1,2369 @@
+#
+# This file is part of the Free Pascal Compiler
+# Copyright (c) 1999-2000 by the Free Pascal Development team
+#
+# Spanish Language File for Free Pascal
+#
+# See the file COPYING.FPC, included in this distribution,
+# for details about the copyright.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#
+#
+# The constants are build in the following order:
+# <part>_<type>_<txtidentifier>
+#
+# <part> is the part of the compiler the message is used
+# asmr_ assembler parsing
+# asmw_ assembler writing/binary writers
+
+# unit_ unit handling
+# scan_ scanner
+# parser_ parser
+# type_ type checking
+# general_ general info
+# exec_ calls to assembler, linker, binder
+#
+# <type> the type of the message it should normally used for
+# f_ fatal error
+# e_ error
+# w_ warning
+# n_ note
+# h_ hint
+# i_ info
+# l_ add linenumber
+# u_ used
+# t_ tried
+# c_ conditional
+# d_ debug message
+# x_ executable informations
+#
+
+#
+# General
+#
+# 01016 is the last used one
+#
+# BeginOfTeX
+% \section{General compiler messages}
+% This section gives the compiler messages which are not fatal, but which
+% display useful information. The number of such messages can be
+% controlled with the various verbosity level \var{-v} switches.
+% \begin{description}
+general_t_compilername=01000_T_Compilador: $1
+% When the \var{-vt} switch is used, this line tells you what compiler
+% is used.
+general_d_sourceos=01001_D_SO del host: $1
+% When the \var{-vd} switch is used, this line tells you what the source
+% operating system is.
+general_i_targetos=01002_I_SO de destino: $1
+% When the \var{-vd} switch is used, this line tells you what the target
+% operating system is.
+general_t_exepath=01003_T_Usando la ruta para ejecutables: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for its binaries.
+general_t_unitpath=01004_T_Usando la ruta para unidades: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for compiled units. You can set this path with the \var{-Fu}
+general_t_includepath=01005_T_Usando la ruta para inclusiones: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for its include files (files used in \var{\{\$I xxx\}} statements).
+% You can set this path with the \var{-I} option.
+general_t_librarypath=01006_T_Usando la ruta para bibliotecas: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for the libraries. You can set this path with the \var{-Fl} option.
+general_t_objectpath=01007_T_Usando la ruta para objetos: $1
+% When the \var{-vt} switch is used, this line tells you where the compiler
+% looks for object files you link in (files used in \var{\{\$L xxx\}} statements).
+% You can set this path with the \var{-Fo} option.
+general_i_abslines_compiled=01008_I_$1 Líneas compiladas, $2 seg
+% When the \var{-vi} switch is used, the compiler reports the number
+% of lines compiled, and the time it took to compile them (real time,
+% not program time).
+general_f_no_memory_left=01009_F_No queda suficiente memoria disponible
+% The compiler doesn't have enough memory to compile your program. There are
+% several remedies for this:
+% \begin{itemize}
+% \item If you're using the build option of the compiler, try compiling the
+% different units manually.
+% \item If you're compiling a huge program, split it up in units, and compile
+% these separately.
+% \item If the previous two don't work, recompile the compiler with a bigger
+% heap (you can use the \var{-Ch} option for this, \seeo{Ch})
+% \end{itemize}
+general_i_writingresourcefile=01010_I_Escribiendo archivo de recursos de tabla de cadenas: $1
+% This message is shown when the compiler writes the Resource String Table
+% file containing all the resource strings for a program.
+general_e_errorwritingresourcefile=01011_E_Escribiendo archivo de recursos de tabla de cadenas: $1
+% This message is shown when the compiler encountered an error when writing
+% the Resource String Table file
+general_i_fatal=01012_I_Fatal:
+% Prefix for Fatal Errors
+general_i_error=01013_I_Error:
+% Prefix for Errors
+general_i_warning=01014_I_Aviso:
+% Prefix for Warnings
+general_i_note=01015_I_Nota:
+% Prefix for Notes
+general_i_hint=01016_I_Consejo:
+% Prefix for Hints
+general_e_path_does_not_exist=01017_E_La ruta "$1" no existe
+% The specified path does not exist.
+general_e_compilation_aborted=01018_E_Compilación abortada
+% \end{description}
+#
+# Scanner
+#
+# 02063 is the last used one
+#
+% \section{Scanner messages.}
+% This section lists the messages that the scanner emits. The scanner takes
+% care of the lexical structure of the pascal file, i.e. it tries to find
+% reserved words, strings, etc. It also takes care of directives and
+% conditional compiling handling.
+% \begin{description}
+scan_f_end_of_file=02000_F_Final de fichero inesperado
+% this typically happens in one of the following cases :
+% \begin{itemize}
+% \item The source file ends before the final \var{end.} statement. This
+% happens mostly when the \var{begin} and \var{end} statements aren't
+% balanced;
+% \item An include file ends in the middle of a statement.
+% \item A comment was not closed
+% \end{itemize}
+scan_f_string_exceeds_line=02001_F_La cadena excede la línea
+% There is a missing closing ' in a string, so it occupies
+% multiple lines.
+scan_f_illegal_char=02002_F_Caracter inválido
+% An illegal character was encountered in the input file.
+scan_f_syn_expected=02003_F_Error de sintaxis, se esperaba "$1" pero se encontró "$2"
+% This indicates that the compiler expected a different token than
+% the one you typed. It can occur almost everywhere where you make a
+% mistake against the pascal language.
+scan_t_start_include_file=02004_TL_Empezando a leer el fichero incluido $1
+% When you provide the \var{-vt} switch, the compiler tells you
+% when it starts reading an included file.
+scan_w_comment_level=02005_W_Nivel de comentario anidado $1 encontrado
+% When the \var{-vw} switch is used, then the compiler warns you if
+% it finds nested comments. Nested comments are not allowed in Turbo Pascal
+% and can be a possible source of errors.
+scan_n_ignored_switch=02008_N_Directiva de compilación $1 ignorado
+% With \var{-vn} on, the compiler warns if it ignores a switch
+scan_w_illegal_switch=02009_W_Directiva de compilación $i inválida
+% You included a compiler switch (i.e. \var{\{\$... \}}) which the compiler
+% does not recognise
+scan_w_switch_is_global=02010_W_Esta opción de compilacion tiene un efecto global
+% The compiler switch is misplaced, and should be located at
+% the start of the unit or program.
+scan_e_illegal_char_const=02011_E_Constante de caracter inválido
+% This happens when you specify a character with its ASCII code, as in
+% \var{\#96}, but the number is either illegal, or out of range.
+scan_f_cannot_open_input=02012_F_No se puede abrir el fichero "$1"
+% \fpc cannot find the program or unit source file you specified on the
+% command line.
+scan_f_cannot_open_includefile=02013_F_No se puede abrir el fichero de inclusion "$1"
+% \fpc cannot find the source file you specified in a \var{\{\$include ..\}}
+% statement.
+scan_w_only_pack_records=02015_W_Los campos de los registros pueden ser alineados solo a 1, 2, 4 o 16 bytes
+% You are specifying the \var{\{\$PACKRECORDS n\} } with an illegal value for
+% \var{n}. Only 1, 2, 4, 8, 16 and 32 are valid in this case.
+scan_w_only_pack_enum=02016_W_Los tipos enumerados solo pueden ser almacenados en 1, 2 o 4 bytes
+% You are specifying the \var{\{\$PACKENUM n\}} with an illegal value for
+% \var{n}. Only 1,2 or 4 are valid in this case.
+scan_e_endif_expected=02017_E_$1 esperado para $2 definido en la línea $3
+% Your conditional compilation statements are unbalanced.
+scan_e_preproc_syntax_error=02018_E_Error de sintaxis mientras se procesaba una expresión de compilación condicional
+% There is an error in the expression following the \var{\{\$if ..\}}, $ifc or $setc compiler
+% directives.
+scan_e_error_in_preproc_expr=02019_E_Evaluando una expresión de compilación condicional
+% There is an error in the expression following the \var{\{\$if ..\}}, $ifc or $setc compiler
+% directives.
+scan_w_macro_cut_after_255_chars=02020_W_El contenido de las macros esta limitado a 255 caracteres de longitud
+% The contents of macros cannot be longer than 255 characters.
+scan_e_endif_without_if=02021_E_ENDIF sin IF(N)DEF
+% Your \var{\{\$IFDEF ..\}} and {\{\$ENDIF\}} statements aren't balanced.
+scan_f_user_defined=02022_F_Error de usuario: $1
+% A user defined fatal error occurred. see also the \progref
+scan_e_user_defined=02023_E_Error de usuario: $1
+% A user defined error occurred. see also the \progref
+scan_w_user_defined=02024_W_Aviso de usuario: $1
+% A user defined warning occurred. see also the \progref
+scan_n_user_defined=02025_N_Nota de usuario: $1
+% A user defined note was encountered. see also the \progref
+scan_h_user_defined=02026_H_Consejo de usuario: $1
+% A user defined hint was encountered. see also the \progref
+scan_i_user_defined=02027_I_Informacion de usuario: $1
+% User defined information was encountered. see also the \progref
+scan_e_keyword_cant_be_a_macro=02028_E_Palabra clave redefinida como macro no tiene efecto
+% You cannot redefine keywords with macros.
+scan_f_macro_buffer_overflow=02029_F_Desbordamiento del buffer de macro durante la lextura o expansión
+% Your macro or its result was too long for the compiler.
+can_w_macro_too_deep=02030_W_La expansión de macros excede una profundidad de 16.
+% When expanding a macro, macros have been nested to a level of 16.
+% The compiler will expand no further, since this may be a sign that
+% recursion is used.
+scan_w_wrong_styled_switch=02031_W_Las directivas de compilacióon no estan soportadas en comentarios estilo //
+% Compiler switches should be in normal pascal style comments.
+scan_d_handling_switch=02032_DL_Manejando la directiva "$1"
+% When you set debugging info on (\var{-vd}) the compiler tells you when it
+% is evaluating conditional compile statements.
+scan_c_endif_found=02033_CL_ENDIF $1 encontrado
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifdef_found=02034_CL_IFDEF $1 encontrado, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifopt_found=02035_CL_IFOPT $1 encontrado, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_if_found=02036_CL_IF $1 encontrado, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_ifndef_found=02037_CL_IFNDEF $1 encontrado, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_else_found=02038_CL_ELSE $1 encontrado, $2
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements.
+scan_c_skipping_until=02039_CL_Omitiendo hasta...
+% When you turn on conditional messages(\var{-vc}), the compiler tells you
+% where it encounters conditional statements, and whether it is skipping or
+% compiling parts.
+scan_i_press_enter=02040_I_Presione <retorno> para continuar
+% When the \var{-vi} switch is used, the compiler stops compilation
+% and waits for the \var{Enter} key to be pressed when it encounters
+% a \var{\{\$STOP\}} directive.
+scan_w_unsupported_switch=02041_W_Conmutador "$1" no soportado
+% When warnings are turned on (\var{-vw}) the compiler warns you about
+% unsupported switches. This means that the switch is used in Delphi or
+% Turbo Pascal, but not in \fpc
+scan_w_illegal_directive=02042_W_Directiva de compilación "$1" inválida
+% When warings are turned on (\var{-vw}) the compiler warns you about
+% unrecognised switches. For a list of recognised switches, \progref
+scan_t_back_in=02043_TL_Vuelve en $1
+% When you use (\var{-vt}) the compiler tells you when it has finished
+% reading an include file.
+scan_w_unsupported_app_type=02044_W_Tipo de aplicación no soportada: "$1"
+% You get this warning, if you specify an unknown application type
+% with the directive \var{\{\$APPTYPE\}}
+scan_w_app_type_not_support=02045_W_APPTYPE no es soportado por el SO de destino
+% The \var{\{\$APPTYPE\}} directive is supported by certain operating systems only.
+scan_w_description_not_support=02046_W_DESCRIPTION no es soportado por el SO de destino
+% The \var{\{\$DESCRIPTION\}} directive is not supported on this target OS
+scan_n_version_not_support=02047_N_VERSION no es soportado por el SO de destino
+% The \var{\{\$VERSION\}} directive is not supported on this target OS
+scan_n_only_exe_version=02048_N_VERSION sólo para EXEs o DLLs
+% The \var{\{\$VERSION\}} directive is only used for executable or DLL sources.
+scan_w_wrong_version_ignored=02049_W_Formato erroneo para la directiva VERSION: "$1"
+% The \var{\{\$VERSION\}} directive format is majorversion.minorversion
+% where majorversion and minorversion are words.
+scan_e_illegal_asmmode_specifier=02050_E_Estilo de ensamblador inváalido especificado: "$1"
+% When you specify an assembler mode with the \var{\{\$ASMMODE xxx\}}
+% the compiler didn't recognize the mode you specified.
+scan_w_no_asm_reader_switch_inside_asm=02051_W_No es posible cambiar el lector dentro de una sentencia asm. "$1" solo sera efectivo en los siguientes
+% It is not possible to switch from one assembler reader to another
+% inside an assmebler block. The new reader will be used for next
+% assembler statements only.
+scan_e_wrong_switch_toggle=02052_E_Modificador de conmutador erróneo, use ON/OFF o +/-
+% You need to use ON or OFF or a + or - to toggle the switch
+scan_e_resourcefiles_not_supported=02053_E_Los ficheros de recursos no son soportados por la plataforma de destino
+% The target you are compiling for doesn't support resource files.
+scan_w_include_env_not_found=02054_W_Variable de entorno incluida "$1" no encontrada.
+% The included environment variable can't be found in the environment, it will
+% be replaced by an empty string instead.
+scan_e_invalid_maxfpureg_value=02055_E_Valor inválido para el registro de la FPU
+% Valid values for this directive are 0..8 and NORMAL/DEFAULT
+scan_w_only_one_resourcefile_supported=02056_W_La plataforma de destino solo soporta un archivo de recursos
+% The target you are compiling for supports only one resource file.
+% The first resource file found is used, the others are discarded.
+scan_w_macro_support_turned_off=02057_W_El soporte para macros ha sido deshabilitado
+% A macro declaration has been found, but macro support is currently off,
+% so the declaration will be ignored. To turn macro support on compile with
+% -Sm on the commandline or add \{\$MACRO ON\} in the source
+scan_e_invalid_interface_type=02058_E_El tipo de interfaz especificado es inválido. Debe ser COM, CORBA o DEFAULT
+% The interface type that was specified is not supported
+scan_w_appid_not_support=02059_W_APPID solo esta soportado para PalmOS
+% The \var{\{\$APPID\}} directive is only supported for the PalmOS target.
+scan_w_appname_not_support=02060_W_APPNAME solo esta soportado para PalmOS
+% The \var{\{\$APPNAME\}} directive is only supported for the PalmOS target.
+scan_e_string_exceeds_255_chars=02061_E_Las constantes de cadena no pueden ser de mas de 255 caracteres de longitud
+% A single string constant can contain at most 255 chars. Try splitting up the
+% string in multiple smaller parts and concatenate them with a + operator.
+scan_f_include_deep_ten=02062_F_La inclusion de archivos no puede exceder 16 niveles
+% When including include files the files have been nested to a level of 16.
+% The compiler will expand no further, since this may be a sign that
+% recursion is used.
+scan_e_too_many_push=02063_F_Demasiados niveles de PUSH
+% A maximum of 20 levels is allowed. This error occurs only in mode MacPas.
+scan_e_too_many_pop=02064_E_A POP sin un PUSH previo
+% This error occurs only in mode MacPas.
+scan_e_error_macro_lacks_value=02065_E_Macro o variable de compilación "$1" no tiene ningún valor
+% Thus the conditional compiling expression cannot be evaluated.
+scan_e_wrong_switch_toggle_default=02066_E_Valor invalido para el conmutado, use ON/OFF/DEFAULT o +/-/*
+% You need to use ON or OFF or DEFAULT or a + or - or * to toggle the switch
+scan_e_mode_switch_not_allowed=02067_E_No esta permitido cambiar de modo a "$1" aqui
+% A mode switch has already been encountered, or, in case of option -Mmacpas,
+% a mode switch occur after UNIT.
+scan_e_error_macro_undefined=02068_E_Variable en tiempo de compilación "$1" no ha sido definida.
+% Thus the conditional compile time expression cannot be evaluated.
+% \end{description}
+#
+# Parser
+#
+# 03192 is the last used one
+#
+% \section{Parser messages}
+% This section lists all parser messages. The parser takes care of the
+% semantics of you language, i.e. it determines if your pascal constructs
+% are correct.
+% \begin{description}
+parser_e_syntax_error=03000_E_Analizador - Error de sintaxis
+% An error against the Turbo Pascal language was encountered. This happens
+% typically when an illegal character is found in the sources file.
+parser_e_dont_nest_interrupt=03004_E_Los procedimientos INTERRUPT no pueden ser anidados
+% An \var{INTERRUPT} procedure must be global.
+parser_w_proc_directive_ignored=03005_W_Tipo de procedimiento "$1" ignorado
+% The specified is ignored by FPC programs.
+parser_e_no_overload_for_all_procs=03006_E_No todas las declaraciones de "$1" llevan OVERLOAD
+% When you want to use overloading using the \var{OVERLOAD} directive, then
+% all declarations need to have \var{OVERLOAD} specified.
+parser_e_export_name_double=03008_E_Nombre de funcion exportada "$1" duplicado
+% Exported function names inside a specific DLL must all be different
+parser_e_export_ordinal_double=03009_E_Indice de funcion exportada "$1" duplicado
+% Exported function names inside a specific DLL must all be different
+parser_e_export_invalid_index=03010_E_Indice de funcion exportada inválido
+% DLL function index must be in the range \var{1..\$FFFF}
+parser_w_parser_reloc_no_debug=03011_W_La informacion de depurado $1 para ejecutables o DLLs reubicables no funciona. Desactivado.
+parser_w_parser_win32_debug_needs_WN=03012_W_Para permitir el depurado en win32 las reubicaciones deben ser desactivadas con la opcion -WN
+% Stabs info is wrong for relocatable DLL or EXES use -WN
+% if you want to debug win32 executables.
+parser_e_constructorname_must_be_init=03013_E_El nombre del constructor debe ser INIT
+% You are declaring an object constructor with a name which is not \var{init}, and the
+% \var{-Ss} switch is in effect. See the \var{-Ss} switch (\seeo{Ss}).
+parser_e_destructorname_must_be_done=03014_E_El nombre del destructor debe ser DONE
+% You are declaring an object destructor with a name which is not \var{done}, and the
+% \var{-Ss} switch is in effect. See the \var{-Ss} switch (\seeo{Ss}).
+parser_e_proc_inline_not_supported=03016_E_Procedimientos tipo INLINE no soportados
+% You tried to compile a program with C++ style inlining, and forgot to
+% specify the \var{-Si} option (\seeo{Si}). The compiler doesn't support C++
+% styled inlining by default.
+parser_w_constructor_should_be_public=03018_W_El constructor debería ser público
+% Constructors must be in the 'public' part of an object (class) declaration.
+parser_w_destructor_should_be_public=03019_W_El destructor debería ser público
+% Destructors must be in the 'public' part of an object (class) declaration.
+parser_n_only_one_destructor=03020_N_Una clase debería tener solo un destructor
+% You can declare only one destructor for a class.
+parser_e_no_local_objects=03021_E_Las definiciones de clases locales no están permitidas
+% Classes must be defined globally. They cannot be defined inside a
+% procedure or function
+parser_f_no_anonym_objects=03022_F_Las definiciones de clases anónimas no están permitidas
+% An invalid object (class) declaration was encountered, i.e. an
+% object or class without methods that isn't derived from another object or
+% class. For example:
+% \begin{verbatim}
+% Type o = object
+% a : longint;
+% end;
+% \end{verbatim}
+% will trigger this error.
+parser_n_object_has_no_vmt=03023_N_El objeto "$1" no tiene VMT
+% This is a note indicating that the declared object has no
+% virtual method table.
+parser_e_illegal_parameter_list=03024_E_Lista de parámetros inválida
+% You are calling a function with parameters that are of a different type than
+% the declared parameters of the function.
+parser_e_wrong_parameter_size=03026_E_Numero de parámetros incorrecto
+% There is an error in the parameter list of the function or procedure,
+% the number of parameters is not correct.
+parser_e_overloaded_no_procedure=03027_E_el identificador sobrecargado "$1" no es una función
+% The compiler encountered a symbol with the same name as an overloaded
+% function, but it is not a function it can overload.
+parser_e_overloaded_have_same_parameters=03028_E_funciones sobrecargadas tienen los mismos par metros
+% You're declaring overloaded functions, but with the same parameter list.
+% Overloaded function must have at least 1 different parameter in their
+% declaration.
+parser_e_header_dont_match_forward=03029_E_la cabecera de la función no concuerda con la declaración posterior "$1"
+% You declared a function with same parameters but
+% different result type or function modifiers.
+parser_e_header_different_var_names=03030_E_la cabecera de la funcion "$1" no concuerda con la posterior declaración : el nombre de la variable cambia $2 => $3
+% You declared the function in the \var{interface} part, or with the
+% \var{forward} directive, but define it with a different parameter list.
+parser_n_duplicate_enum=03031_N_el orden de los valores en una enumeracion debe ser ascendente
+% \fpc allows enumeration constructions as in C. Given the following
+% declaration two declarations:
+% \begin{verbatim}
+% type a = (A_A,A_B,A_E:=6,A_UAS:=200);
+% type a = (A_A,A_B,A_E:=6,A_UAS:=4);
+% \end{verbatim}
+% The second declaration would produce an error. \var{A\_UAS} needs to have a
+% value higher than \var{A\_E}, i.e. at least 7.
+parser_e_no_with_for_variable_in_other_segments=03033_E_With no puede ser usado con variables en segmentos diferentes
+% With stores a variable locally on the stack,
+% but this is not possible if the variable belongs to another segment.
+parser_e_too_much_lexlevel=03034_E_Anidado de funciones > 31
+% You can nest function definitions only 31 times.
+parser_e_range_check_error=03035_E_error en la comprobación de rangos mientras se evaluaban constantes
+% The constants are out of their allowed range.
+parser_w_range_check_error=03036_W_error en la comprobacion de rangos mientras se evaluaban constantes
+% The constants are out of their allowed range.
+parser_e_double_caselabel=03037_E_etiqueta de caso duplicada
+% You are specifying the same label 2 times in a \var{case} statement.
+parser_e_case_lower_less_than_upper_bound=03038_E_El líimite superior del caso es menor que el inferior
+% The upper bound of a \var{case} label is less than the lower bound and this
+% is useless
+parser_e_type_const_not_possible=03039_E_no se permiten constantes con tipo de clases
+% You cannot declare a constant of type class or object.
+parser_e_no_overloaded_procvars=03040_E_no se permite asignar a variables de funcion funciones sobrecargadas
+% You are trying to assign an overloaded function to a procedural variable.
+% This is not allowed
+parser_e_invalid_string_size=03041_E_la longitud de una cadena tiene que ser un valor entre 1 y 255
+% The length of a shortstring in Pascal is limited to 255 characters. You are
+% trying to declare a string with length lower than 1 or greater than 255
+parser_w_use_extended_syntax_for_objects=03042_W_use la sintaxis estendida de DISPOSE y NEW para instancias de objetos
+% If you have a pointer \var{a} to a class type, then the statement
+% \var{new(a)} will not initialize the class (i.e. the constructor isn't
+% called), although space will be allocated. you should issue the
+% \var{new(a,init)} statement. This will allocate space, and call the
+% constructor of the object
+parser_w_no_new_dispose_on_void_pointers=03043_W_el uso de NEW o DISPOSE para punteros sin tipo no tiene sentido
+parser_e_no_new_dispose_on_void_pointers=03044_E_el uso de NEW o DISPOSE no es posible con punteros sin tipo
+% You cannot use \var{new(p)} or \var{dispose(p)} if \var{p} is an untyped pointer
+% because no size is associated to an untyped pointer.
+% Accepted for compatibility in \var{tp} and \var{delphi} modes.
+parser_e_class_id_expected=03045_E_identificador de clase esperado
+% This happens when the compiler scans a procedure declaration that contains
+% a dot,
+% i.e., a object or class method, but the type in front of the dot is not
+% a known type.
+parser_e_no_type_not_allowed_here=03046_E_identificador de tipo no permitido aquí
+% You cannot use a type inside an expression.
+parser_e_methode_id_expected=03047_E_identificador de método esperado
+% This identifier is not a method.
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., a object or class method, but the procedure name is not a
+% procedure of this type.
+parser_e_header_dont_match_any_member=03048_E_la cabecera de la funcion no concuerda con ningún método de esta clase "$1"
+% This identifier is not a method.
+% This happens when the compiler scans a procedure declaration that contains
+% a dot, i.e., a object or class method, but the procedure name is not a
+% procedure of this type.
+parser_d_procedure_start=03049_DL_proceduimiento/función $1
+% When using the \var{-vd} switch, the compiler tells you when it starts
+% processing a procedure or function implementation.
+parser_e_error_in_real=03050_E_Constante de punto flotante inválida
+% The compiler expects a floating point expression, and gets something else.
+parser_e_fail_only_in_constructor=03051_E_FAIL solo puede ser usado en constructores
+% You are using the \var{fail} keyword outside a constructor method.
+parser_e_no_paras_for_destructor=03052_E_Los destructores no pueden tener parámetros
+% You are declaring a destructor with a parameter list. Destructor methods
+% cannot have parameters.
+parser_e_only_class_methods_via_class_ref=03053_E_Solo los métodos de clases pueden ser referidos con referencias de clase
+% This error occurs in a situation like the following:
+% \begin{verbatim}
+% Type :
+% Tclass = Class of Tobject;
+%
+% Var C : TClass;
+%
+% begin
+% ...
+% C.free
+% \end{verbatim}
+% \var{Free} is not a class method and hence cannot be called with a class
+% reference.
+parser_e_only_class_methods=03054_E_Los métodos de clase solo pueden ser acceder a otros métodos de clase
+% This is related to the previous error. You cannot call a method of an object
+% from a inside a class method. The following code would produce this error:
+% \begin{verbatim}
+% class procedure tobject.x;
+%
+% begin
+% free
+% \end{verbatim}
+% Because free is a normal method of a class it cannot be called from a class
+% method.
+parser_e_case_mismatch=03055_E_Los tipos de la constante y del CASE no concuerdan
+% One of the labels is not of the same type as the case variable.
+parser_e_illegal_symbol_exported=03056_E_El símbolo no puede ser exportado de una librería
+% You can only export procedures and functions when you write a library. You
+% cannot export variables or constants.
+parser_w_should_use_override=03057_W_Un método heredado ha sido ocultado por "$1"
+% A method that is declared \var{virtual} in a parent class, should be
+% overridden in the descendent class with the \var{override} directive. If you
+% don't specify the \var{override} directive, you will hide the parent method;
+% you will not override it.
+parser_e_nothing_to_be_overridden=03058_E_No hay un método en una clase antepasada para ser substituido: "$1"
+% You are trying to \var{override} a virtual method of a parent class that does
+% not exist.
+parser_e_no_procedure_to_access_property=03059_E_No se suministro un miembro para acceder a propiedad
+% You specified no \var{read} directive for a property.
+parser_w_stored_not_implemented=03060_W_La directiva de propiedad Stored no esta implementada aún
+% The \var{stored} directive is not yet implemented
+parser_e_ill_property_access_sym=03061_E_símbolo inváalido para el acceso a la propiedad
+% There is an error in the \var{read} or \var{write} directives for an array
+% property. When you declare an array property, you can only access it with
+% procedures and functions. The following code woud cause such an error.
+% \begin{verbatim}
+% tmyobject = class
+% i : integer;
+% property x [i : integer]: integer read I write i;
+% \end{verbatim}
+%
+parser_e_cant_access_protected_member=03062_E_No se puede acceder a un campo protegido de un objeto aquí
+% Fields that are declared in a \var{protected} section of an object or class
+% declaration cannot be accessed outside the module wher the object is
+% defined, or outside descendent object methods.
+parser_e_cant_access_private_member=03063_E_No se puede acceder a un campo privado de un objeto aquí
+% Fields that are declared in a \var{private} section of an object or class
+% declaration cannot be accessed outside the module where the class is
+% defined.
+parser_e_overridden_methods_not_same_ret=03066_E_los métodos reemplazados deben tener el mismo tipo de dato devuelto: "$2" es reemplazado por "$1" que devuelve otro tipo
+% If you declare overridden methods in a class definition, they must
+% have the same return type.
+parser_e_dont_nest_export=03067_E_Las funciones declarados como EXPORT no pueden estar anidados
+% You cannot declare a function or procedure within a function or procedure
+% that was declared as an export procedure.
+parser_e_methods_dont_be_export=03068_E_los métodos no pueden ser EXPORTados
+% You cannot declare a procedure that is a method for an object as
+% \var{export}ed.
+parser_e_call_by_ref_without_typeconv=03069_E_en llamadas con parámetros VAR los tipos deben coincidir exactamente. Se recibio "$1" cuando se esperaba "$2"
+% When calling a function declared with \var{var} parameters, the variables in
+% the function call must be of exactly the same type. There is no automatic
+% type conversion.
+parser_e_no_super_class=03070_E_La clase no es un ancestor de la clase actual
+% When calling inherited methods, you are trying to call a method of a non-related
+% class. You can only call an inherited method of a parent class.
+parser_e_self_not_in_method=03071_E_SELF solo está permitido en métodos
+% You are trying to use the \var{self} parameter outside an object's method.
+% Only methods get passed the \var{self} parameters.
+parser_e_generic_methods_only_in_methods=03072_E_los métodos solo pueden estar en otros métodos llamados directamente con el tipo identificador de la clase
+% A construction like \var{sometype.somemethod} is only allowed in a method.
+parser_e_illegal_colon_qualifier=03073_E_Uso inválido de ':'
+% You are using the format \var{:} (colon) 2 times on an expression that
+% is not a real expression.
+parser_e_illegal_set_expr=03074_E_Error en la comprobación de rangos en el constructor del set, o elemento duplicado en el set
+% The declaration of a set contains an error. Either one of the elements is
+% outside the range of the set type, either two of the elements are in fact
+% the same.
+parser_e_pointer_to_class_expected=03075_E_Se esperaba un puntero a objeto
+% You specified an illegal type in a \var{new} statement.
+% The extended syntax of \var{new} needs an object as a parameter.
+parser_e_expr_have_to_be_constructor_call=03076_E_La expresión tiene que ser una llamada al constructor
+% When using the extended syntax of \var{new}, you must specify the constructor
+% method of the object you are trying to create. The procedure you specified
+% is not a constructor.
+parser_e_expr_have_to_be_destructor_call=03077_E_La expresión tiene que ser una llamada al destructor
+% When using the extended syntax of \var{dispose}, you must specify the
+% destructor method of the object you are trying to dispose of.
+% The procedure you specified is not a destructor.
+parser_e_invalid_record_const=03078_E_Orden de los campos del registro incorrecto
+% When declaring a constant record, you specified the fields in the wrong
+% order.
+parser_e_false_with_expr=03079_E_El tipo de la expresión tiene que ser class o record
+% A \var{with} statement needs an argument that is of the type \var{record}
+% or \var{class}. You are using \var{with} on an expression that is not of
+% this type.
+parser_e_void_function=03080_E_Los procedimientos no pueden devolver ningún valor
+% In \fpc, you can specify a return value for a function when using
+% the \var{exit} statement. This error occurs when you try to do this with a
+% procedure. Procedures cannot return a value.
+parser_e_only_methods_allowed=03081_E_constructores, destructores y class operators deben ser métodos
+% You're declaring a procedure as destructor, constructor or class operator, when the
+% procedure isn't a class method.
+parser_e_operator_not_overloaded=03082_E_El operador no esta sobrecargado
+% You're trying to use an overloaded operator when it is not overloaded for
+% this type.
+parser_e_no_such_assignment=03083_E_Imposible sobrecargar operador de asignacion para tipos iguales
+% You can not overload assignment for types
+% that the compiler considers as equal.
+parser_e_overload_impossible=03084_E_Sobrecarga de operador imposible
+% The combination of operator, arguments and return type are
+% incompatible.
+parser_e_no_reraise_possible=03085_E_Re-lanzamiento de la excepcion no es posible aquí
+% You are trying to raise an exception where it is not allowed. You can only
+% raise exceptions in an \var{except} block.
+parser_e_no_new_or_dispose_for_classes=03086_E_La sintaxis extendida de new o dispose no está permitida para una clase
+% You cannot generate an instance of a class with the extended syntax of
+% \var{new}. The constructor must be used for that. For the same reason, you
+% cannot call \var{dispose} to de-allocate an instance of a class, the
+% destructor must be used for that.
+parser_e_procedure_overloading_is_off=03088_E_La sobrecarga de funciones no esta activada
+% When using the \var{-So} switch, procedure overloading is switched off.
+% Turbo Pascal does not support function overloading.
+parser_e_overload_operator_failed=03089_E_No es posible sobrecargar este operador (sobrecarge en cambio "=" )
+% You are trying to overload an operator which cannot be overloaded.
+% The following operators can be overloaded :
+% \begin{verbatim}
+% +, -, *, /, =, >, <, <=, >=, is, as, in, **, :=
+% \end{verbatim}
+parser_e_comparative_operator_return_boolean=03090_E_Operador comparativo tiene que devolver un valor booleano
+% When overloading the \var{=} operator, the function must return a boolean
+% value.
+parser_e_only_virtual_methods_abstract=03091_E_Solo los métodos virtuales pueden ser abstractos
+% You are declaring a method as abstract, when it is not declared to be
+% virtual.
+parser_f_unsupported_feature=03092_F_Uso de característica no soportada!
+% You're trying to force the compiler into doing something it cannot do yet.
+parser_e_mix_of_classes_and_objects=03093_E_No se permite la mezcla de objetos de diferentes tipos (class, object, interface, etc)
+% You cannot derive \var{objects}, \var{classes}, \var{cppclasses} and \var{interfaces} interttwined . E.g.
+% a class cannot have an object as parent and vice versa.
+parser_w_unknown_proc_directive_ignored=03094_W_Directiva de procedimiento desconocida fue ignorada: "$1"
+% The procedure directive you specified is unknown.
+parser_e_absolute_only_one_var=03095_E_absolute solo puede estar asociado a una variable
+% You cannot specify more than one variable before the \var{absolute} directive.
+% Thus, the following construct will provide this error:
+% \begin{verbatim}
+% Var Z : Longint;
+% X,Y : Longint absolute Z;
+% \end{verbatim}
+% \item [ absolute can only be associated a var or const ]
+% The address of a \var{absolute} directive can only point to a variable or a
+% typed constant. Therefore, the following code will produce this error:
+% \begin{verbatim}
+% Procedure X;
+%
+% var p : longint absolute x;
+% \end{verbatim}
+%
+parser_e_absolute_only_to_var_or_const=03096_E_absolute solo puede ser asociado con var o const
+% The address of a \var{absolute} directive can only point to a variable or
+% constant. Therefore, the following code will produce this error:
+% \begin{verbatim}
+% Procedure X;
+%
+% var p : longint absolute x;
+% \end{verbatim}
+%
+parser_e_initialized_only_one_var=03097_E_Solo una variable puede ser inicializada
+% You cannot specify more than one variable with a initial value
+% in Delphi mode.
+parser_e_abstract_no_definition=03098_E_Métodos abstractos no deberían tener ninguna definición (con el cuerpo de la función)
+% Abstract methods can only be declared, you cannot implement them. They
+% should be overridden by a descendant class.
+parser_e_overloaded_must_be_all_global=03099_E_Esta función sobrecargada no puede ser local (debe ser exportada)
+% You are defining a overloaded function in the implementation part of a unit,
+% but there is no corresponding declaration in the interface part of the unit.
+parser_w_virtual_without_constructor=03100_W_Métodos virtuales están siendo usados sin un constructor en "$1"
+% If you declare objects or classes that contain virtual methods, you need
+% to have a constructor and destructor to initialize them. The compiler
+% encountered an object or class with virtual methods that doesn't have
+% a constructor/destructor pair.
+parser_c_macro_defined=03101_CL_Macro definido: $1
+% When \var{-vc} is used, the compiler tells you when it defines macros.
+parser_c_macro_undefined=03102_CL_Macro indefinido: $1
+% When \var{-vc} is used, the compiler tells you when it undefines macros.
+parser_c_macro_set_to=03103_CL_Macro $1 asignado a $2
+% When \var{-vc} is used, the compiler tells you what values macros get.
+parser_i_compiling=03104_I_Compilando $1
+% When you turn on information messages (\var{-vi}), the compiler tells you
+% what units it is recompiling.
+parser_u_parsing_interface=03105_UL_Interpretando interfaz de la unidad $1
+% This tells you that the reading of the interface
+% of the current unit starts
+parser_u_parsing_implementation=03106_UL_Interpretando implementacion de la unidad $1
+% This tells you that the code reading of the implementation
+% of the current unit, library or program starts
+parser_d_compiling_second_time=03107_DL_Compilando $1 por segunda vez
+% When you request debug messages (\var{-vd}) the compiler tells you what
+% units it recompiles for the second time.
+parser_e_no_property_found_to_override=03109_E_No se encontro la propiedad a reemplazar
+% You want to overrride a property of a parent class, when there is, in fact,
+% no such property in the parent class.
+parser_e_only_one_default_property=03110_E_Sólo se permite una única propiedad por defecto
+% You specified a property as \var{Default}, but the class already has a
+% default property, and a class can have only one default property.
+parser_e_property_need_paras=03111_E_La propiedad por defecto tiene que ser un array
+% Only array properties of classes can be made \var{default} properties.
+parser_e_constructor_cannot_be_not_virtual=03112_E_Solo las clases soportan constructores virtuales
+% You cannot have virtual constructors in objects. You can only have them
+% in classes.
+parser_e_no_default_property_available=03113_E_No hay propiedad por defecto disponible
+% You are trying to access a default property of a class, but this class (or one of
+% its ancestors) doesn't have a default property.
+parser_e_cant_have_published=03114_E_La clase no puede tener una sección published, use el conmutador {$M+}
+% If you want a \var{published} section in a class definition, you must
+% use the \var{\{\$M+\}} switch, whch turns on generation of type
+% information.
+parser_e_forward_declaration_must_be_resolved=03115_E_Declaración posterior de la clase "$1" tiene que ser resuelta aquí para usar la clase como antepasado
+% To be able to use an object as an ancestor object, it must be defined
+% first. This error occurs in the following situation:
+% \begin{verbatim}
+% Type ParentClas = Class;
+% ChildClass = Class(ParentClass)
+% ...
+% end;
+% \end{verbatim}
+% Where \var{ParentClass} is declared but not defined.
+parser_e_no_local_operator=03116_E_Operadores locales no soportados
+% You cannot overload locally, i.e. inside procedures or function
+% definitions.
+parser_e_proc_dir_not_allowed_in_interface=03117_E_Directiva de procedimiento "$1" no permitida en la sección de interfaz
+% This procedure directive is not allowed in the \var{interface} section of
+% a unit. You can only use it in the \var{implementation} section.
+parser_e_proc_dir_not_allowed_in_implementation=03118_E_Directiva de procedimiento "$1" no permitida en la sección de implementacion
+% This procedure directive is not defined in the \var{implementation} section of
+% a unit. You can only use it in the \var{interface} section.
+parser_e_proc_dir_not_allowed_in_procvar=03119_E_Directiva de procedimiento "$1" no permitida en la declaración de tipo
+% This procedure directive cannot be part of a procedural or function
+% type declaration.
+parser_e_function_already_declared_public_forward=03120_E_La función esta actualmente declarada como Public/Forward "$1"
+% You will get this error if a function is defined as \var{forward} twice.
+% Or it is once in the \var{interface} section, and once as a \var{forward}
+% declaration in the \var{implmentation} section.
+parser_e_not_external_and_export=03121_E_No se pueden usar ambos EXPORT y EXTERNAL
+% These two procedure directives are mutually exclusive
+parser_w_not_supported_for_inline=03123_W_"$1" aún no soportado en procedimientos/funciones inline
+% Inline procedures don't support this declaration.
+parser_w_inlining_disabled=03124_W_Inlining deshabilitado
+% Inlining of procedures is disabled.
+parser_i_writing_browser_log=03125_I_Escribiendo Browser log $1
+% When information messages are on, the compiler warns you when it
+% writes the browser log (generated with the \var{\{\$Y+ \}} switch).
+parser_h_maybe_deref_caret_missing=03126_H_podría ser que falte la de-referencia del puntero
+% The compiler thinks that a pointer may need a dereference.
+parser_f_assembler_reader_not_supported=03127_F_Lector del ensamblador seleccionado no soportado
+% The selected assembler reader (with \var{\{\$ASMMODE xxx\}} is not
+% supported. The compiler can be compiled with or without support for a
+% particular assembler reader.
+parser_e_proc_dir_conflict=03128_E_Directiva de procedimiento "$1" causa conflicto con otras directivas
+% You specified a procedure directive that conflicts with other directives.
+% for instance \var{cdecl} and \var{pascal} are mutually exclusive.
+parser_e_call_convention_dont_match_forward=03129_E_La convencion de llamada actual no concuerda con la definida anteriormente
+% This error happens when you declare a function or procedure with
+% e.g. \var{cdecl;} but omit this directive in the implementation, or vice
+% versa. The calling convention is part of the function declaration, and
+% must be repeated in the function definition.
+parser_e_property_cant_have_a_default_value=03131_E_La propiedad no puede tener un valor por defecto
+% Set properties or indexed properties cannot have a default value.
+parser_e_property_default_value_must_const=03132_E_El valor por defecto de una propiedad tiene que ser constante
+% The value of a \var{default} declared property must be known at compile
+% time. The value you specified is only known at run time. This happens
+% .e.g. if you specify a variable name as a default value.
+parser_e_cant_publish_that=03133_E_El símbolo no puede ser published, solo puede ser una clase
+% Only class type variables can be in a \var{published} section of a class
+% if they are not declared as a property.
+parser_e_cant_publish_that_property=03134_E_Este tipo de propiedad no puede ser published
+% Properties in a \var{published} section cannot be array properties.
+% they must be moved to public sections. Properties in a \var{published}
+% section must be an ordinal type, a real type, strings or sets.
+parser_e_empty_import_name=03136_E_Se requiere un nombre de importación
+% Some targets need a name for the imported procedure or a \var{cdecl} specifier
+parser_e_division_by_zero=03138_E_Division por cero
+% There is a divsion by zero encounted
+parser_e_invalid_float_operation=03139_E_Operacion de punto flotante no válida
+% An operation on two real type values produced an overflow or a division
+% by zero.
+parser_e_array_lower_less_than_upper_bound=03140_E_Límite superior del rango es menor que el límite inferior
+% The upper bound of a an array declaration is less than the lower bound and this
+% is not possible
+parser_w_string_too_long=03141_W_La cadena "$1" es mas larga que $2
+% The size of the constant string is larger than the size you specified in
+% string type definition
+parser_e_string_larger_array=03142_E_La longitud de la cadena es mayor que el tamaño array de carácteres
+% The size of the constant string is larger than the size you specified in
+% the array[x..y] of char definition
+parser_e_ill_msg_expr=03143_E_Expresión inválida tras la directiva de mensaje
+% \fpc supports only integer or string values as message constants
+parser_e_ill_msg_param=03144_E_Los méetodos de manejo de mensajes deben tener un único parámetro por referencia
+% A method declared with the \var{message}-directive as message handler
+% can take only one parameter which must be declared as call by reference
+% Parameters are declared as call by reference using the \var{var}-directive
+parser_e_duplicate_message_label=03145_E_Etiqueta de mensaje duplicada: "$1"
+% A label for a message is used twice in one object/class
+parser_e_self_in_non_message_handler=03146_E_Self solo puede ser un parámetro explícito en manejadores de mensajes
+% The self parameter can only be passed explicitly to a method which
+% is declared as message handler.
+parser_e_threadvars_only_sg=03147_E_Threadvars sólo pueden ser globales o estáticos
+% Threadvars must be static or global, you can't declare a thread
+% local to a procedure. Local variables are always local to a thread,
+% because every thread has its own stack and local variables
+% are stored on the stack
+parser_f_direct_assembler_not_allowed=03148_F_Ensamblador directo no soportado para formato binario de salida
+% You can't use direct assembler when using a binary writer, choose an
+% other outputformat or use another assembler reader
+parser_w_no_objpas_use_mode=03149_W_No carges manuamente la unidad OBJPAS, usa \{\$mode objfpc\} o \{\$mode delphi\}
+% You are trying to load the ObjPas unit manually from a uses clause. This is
+% not a good idea. Use the \var{\{\$mode objfpc\}} or
+% \var{\{\$mode delphi\}}
+% directives which load the unit automatically
+parser_e_no_object_override=03150_E_OVERRIDE no puede ser usado en objetos
+% Override is not supported for objects, use \var{virtual} instead to override
+% a method of a parent object
+parser_e_cant_use_inittable_here=03151_E_Tipos de datos que requieran inicializacion/finalizacion no pueden ser usados en registros variables
+% Some data type (e.g. \var{ansistring}) needs initialization/finalization
+% code which is implicitly generated by the compiler. Such data types
+% can't be used in the variant part of a record.
+parser_e_resourcestring_only_sg=03152_E_Resourcestrings solo pueden ser globales o estáaticos
+% Resourcestring can not be declared local, only global or using the static
+% directive.
+parser_e_exit_with_argument_not__possible=03153_E_Exit con parámetro no puede ser usado aquí
+% an exit statement with an argument for the return value can't be used here, this
+% can happen e.g. in \var{try..except} or \var{try..finally} blocks
+parser_e_stored_property_must_be_boolean=03154_E_El tipo del símbolo en stored debe ser de tipo booleano
+% If you specify a storage symbol in a property declaration, it must be of
+% the type boolean
+parser_e_ill_property_storage_sym=03155_E_Este símbolo no puede ser usado en storage para una propiedad
+% You can't use this type of symbol as storage specifier in property
+% declaration. You can use only methods with the result type boolean,
+% boolean class fields or boolean constants
+parser_e_only_publishable_classes_can__be_published=03156_E_Solo clases compiladas en $M+ pueden ser publicadas
+% In the published section of a class can be only class as fields used which
+% are compiled in \var{\{\$M+\}} or which are derived from such a class. Normally
+% such a class should be derived from TPersitent
+parser_e_proc_directive_expected=03157_E_Directiva de procedimiento esperada
+% When declaring a procedure in a const block you used a ; after the
+% procedure declaration after which a procedure directive must follow.
+% Correct declarations are:
+% \begin{verbatim}
+% const
+% p : procedure;stdcall=nil;
+% p : procedure stdcall=nil;
+% \end{verbatim}
+parser_e_invalid_property_index_value=03158_E_El valor para el índice de una propiedad debe ser de tipo ordinal
+% The value you use to index a property must be of an ordinal type, for
+% example an integer or enumerated type.
+parser_e_procname_to_short_for_export=03159_E_Nombre del procedimiento demasiado corto para ser exportado
+% The length of the procedure/function name must be at least 2 characters
+% long. This is because of a bug in dlltool which doesn't parse the .def
+% file correct with a name of length 1.
+parser_e_dlltool_unit_var_problem=03160_E_No se puede generar una entrada DEFFILE para las variables globales de la unidad
+parser_e_dlltool_unit_var_problem2=03161_E_Compile sin la opcion -WD
+% You need to compile this file without the -WD switch on the
+% commandline
+parser_f_need_objfpc_or_delphi_mode=03162_F_Se requiere el modo ObjFpc (-S2) o Delphi (-Sd) para compilar este módulo
+% You need to use \{\$mode objfpc\} or \{\$mode delphi\} to compile this file.
+% Or use the equivalent commandline switches -S2 or -Sd.
+parser_e_no_export_with_index_for_target=03163_E_No se pueden exportar funciones o procedimientos por indice en $1
+% Exporting of functions or procedures with a specified index is not
+% supported on this target.
+parser_e_no_export_of_variables_for_target=03164_E_Exportar variables no esta soportado en $1
+% Exporting of variables is not supported on this target.
+parser_e_improper_guid_syntax=03165_E_Sintaxis de GUID incorrecta
+parser_w_interface_mapping_notfound=03168_W_No se encontro el procedimiento de nombre "$1" apropiado para implementar $2.$3
+parser_e_interface_id_expected=03169_E_identificador de interfaz esperado
+% This happens when the compiler scans a \var{class} declaration that contains
+% \var{interface} function name mapping code like this:
+% \begin{verbatim}
+% type
+% TMyObject = class(TObject, IDispatch)
+% function IUnknown.QueryInterface=MyQueryInterface;
+% ....
+% \end{verbatim}
+% and the \var{interface} before the dot not listed in the inheritance list.
+parser_e_type_cant_be_used_in_array_index=03170_E_El tipo "$1" no puede ser usado como indice en arrays
+% Types like \var{qword} or \var{int64} aren't allowed as array index type
+parser_e_no_con_des_in_interfaces=03171_E_No se permiten constructores/destructores en interfaces
+% Constructor and destructor declarations aren't allowed in interface
+% In the most cases the method \var{QueryInterface} of \var{IUnknown} can
+% be used to create a new interface.
+parser_e_no_access_specifier_in_interfaces=03172_E_No se permiten especificadores de acceso en interfaces
+% The access specifiers \var{public}, \var{private}, \var{protected} and
+% \var{pusblished} can't be used in interfaces because all methods
+% of an interfaces must be public.
+parser_e_no_vars_in_interfaces=03173_E_Una interfaz no puede contener campos
+% Declarations of fields aren't allowed in interfaces. An interface
+% can contain only methods
+parser_e_no_local_proc_external=03174_E_No se puede declarar un procedimiento local como externo
+% Declaring local procedures as external is not possible. Local procedures
+% get hidden parameters that will make the chance of errors very high
+parser_w_skipped_fields_before=03175_W_Algunos campos anteriores a "$1" no fueron inicializados
+% In Delphi mode, not all fields of a typed constant record have to be
+% initialized, but the compiler warns you when it detects such situations.
+parser_e_skipped_fields_before=03176_E_Algunos campos anteriores a "$1" no fueron inicializados
+% In all syntax modes but Delphi mode, you can't leave some fields uninitialized
+% in the middle of a typed constant record
+parser_w_skipped_fields_after=03177_W_Algunos campos tras "$1" no fueron inicializados
+% You can leave some fields at the end of a type constant record uninitialized
+% (the compiler will initialize them to zero automatically). This may be the cause
+% of subtle problems.
+parser_e_varargs_need_cdecl_and_external=03178_E_Directiva VarArgs sólo es válida con CDecl o External
+% The varargs directive can only be used with procedures or functions
+% that are declared with \var{cdecl} and \var{external} directives. The varargs directive
+% is only meant to provide a compatible interface to C functions like printf.
+parser_e_self_call_by_value=03179_E_Self debe ser un parámetro normal por valor
+% You can't declare self as a const or var parameter, it must always be
+% a call-by-value parameter
+parser_e_interface_has_no_guid=03180_E_La interfaz "$1" no tiene identificacion
+% When you want to assign an interface to a constant, then the interface
+% must have a GUID value set.
+parser_e_illegal_field_or_method=03181_E_Campo de la clase o método desconocido "$1"
+% Properties must refer to a field or method in the same class.
+parser_w_proc_overriding_calling=03182_W_Varias convenciones de llamada especificadas, "$1" ignorado al especificar "$2"
+% There are two directives in the procedure declaration that specify a calling
+% convention. Only the last directive will be used
+parser_e_no_procvarobj_const=03183_E_constantes con tipo de tipo Procedure/Function (...) of Object solo pueden ser inicializados a NIL
+% You can't assign the address of a method to a typed constant which has a
+% 'procedure of object' type, because such a constant requires two addresses:
+% that of the method (which is known at compile time) and that of the object or
+% class instance it operates on (which can not be known at compile time).
+parser_e_default_value_only_one_para=03184_E_Sólo se puede asignar valor por defecto a un parámetro
+parser_e_default_value_expected_for_para=03185_E_Parámetro por defecto requerido para "$1"
+parser_w_unsupported_feature=03186_W_¡Uso de una caracteristica no soportada!
+% You're trying to force the compiler into doing something it cannot do yet.
+parser_h_c_arrays_are_references=03187_H_Arrays tipo C son pasados por referencia
+% Any array passed to a C functions is passed
+% by a pointer (i.e. by reference).
+parser_e_C_array_of_const_must_be_last=03188_E_Array tipo C de const debe ser el ultimo parámetro
+% You can not add any other argument after an \var{array of const} for
+% \var{cdecl} functions, as the size pushed on stack for this argument is
+% not known.
+parser_h_type_redef=03189_H_Redefinición del tipo "$1"
+% This is an indicator that a previously declared type is
+% being redefined as something else. This may, or may not
+% be, a cause for errors.
+parser_w_cdecl_has_no_high=03190_W_Procedimientos y funciones declarados como cdecl no reciben de parámetro el límite superior
+% Functions declared with cdecl modifier do not pass an extra implicit parameter.
+parser_w_cdecl_no_openstring=03191_W_open strings no son soportados en funciones cdecl
+% Openstring is not supported for cdecl'ared functions.
+parser_e_initialized_not_for_threadvar=03192_E_No se pueden inicializar variables declaradas como threadvar
+% Variables declared as threadvar can not be initialized with a default value.
+% The variables will always be filled with zero at the start of a new thread.
+parser_e_msg_only_for_classes=03193_E_La directiva Message sólo es valida en clases
+% The message directive is only supported for Class types.
+parser_e_procedure_or_function_expected=03194_E_Se esperaba un procedimiento o funcion
+% A class method can only be specified for procedures and functions.
+parser_e_illegal_calling_convention=03195_W_Directiva de convención de llama "$1" ignorada
+% Some calling conventions are supported only by certain CPUs. I.e. most non-i386 ports support
+% only the standard ABI calling convention of the CPU.
+parser_e_no_object_reintroduce=03196_E_REINTRODUCE no puede ser utilizado en objetos
+% \var{reintroduce} is not supported for objects.
+parser_e_paraloc_only_one_para=03197_E_Cada parámetro debe tener su propia posición
+% If locations for arguments are specified explicitly as it is required by
+% some syscall conventions, each argument must have it's only location, things
+% like \var{procedure p(i,j : longint 'r1');} aren't allowed
+parser_e_paraloc_all_paras=03198_E_Cada parámetro debe tener su propia posición
+% If one argument has an explicit argument location, all arguments of a procedure
+% must have one.
+parser_e_illegal_explicit_paraloc=03199_E_Localizacón en el segmento desconocida
+% The location specified for an argument isn't recognized by the compiler
+parser_e_32bitint_or_pointer_variable_expected=03200_E_Se esperaba una variable entera de 32 bits o un puntero
+% The libbase for MorphOS/AmigaOS can be give only as \var{longint}, \var{dword} or any pointer variable.
+parser_e_goto_outside_proc=03201_E_No se puede usar Goto para saltar a otro procedimiento
+% It isn't allowed to use the \var{goto} statements referencing labels outside the
+% current procedure. The following example shows the problem:
+% \begin{verbatim}
+% ...
+% procedure p1;
+% label
+% l1;
+%
+% procedure p2;
+% begin
+% goto l1; // This goto ISN'T allowed
+% end;
+%
+% begin
+% p2
+% l1:
+% end;
+% ...
+%
+% \end{verbatim}
+parser_f_too_complex_proc=03202_F_Procedimiento demasiado complejo. Se requieren demasiados registros
+% Your procedure body is too long for the compiler. You should split the
+% procedure into multiple smaller procedures.
+parser_e_illegal_expression=03203_E_Expresión inválida
+% This can occur under many circumstances. Mostly when trying to evaluate
+% constant expressions.
+parser_e_invalid_integer=03204_E_La expresión no evalua un número entero
+% You made an expression which isn't an integer, and the compiler expects the
+% result to be an integer.
+parser_e_invalid_qualifier=03205_E_calificador inválido
+% One of the following is happening :
+% \begin{itemize}
+% \item You're trying to access a field of a variable that is not a record.
+% \item You're indexing a variable that is not an array.
+% \item You're dereferencing a variable that is not a pointer.
+% \end{itemize}
+parser_e_upper_lower_than_lower=03206_E_El limite superior especificado es menor que el inferior
+% You are declaring a subrange, and the lower limit is higher than the high
+% limit of the range.
+parser_e_macpas_exit_wrong_param=03207_E_El parámetro de Exit debe ser el nombre del mismo procedimiento en el que está
+% Non local exit is not allowed. This error occurs only in mode MacPas.
+parser_e_illegal_assignment_to_count_var=03208_E_Asignación inválida a la variable de bucle "$1"
+% The type of a \var{for} loop variable must be an ordinal type.
+% Loop variables cannot be reals or strings.
+parser_e_no_local_var_external=03209_E_No se puede declarar una variable local como externa
+% Declaring local variables as external is not allowed. Only global variables can reference
+% to external variables.
+parser_e_proc_already_external=03210_E_El procedimiento ya ha sido declarado como externo con anterioridad
+% The procedure is already declared with the EXTERNAL directive in an interface or
+% forward declaration.
+parser_w_implicit_uses_of_variants_unit=03211_W_Uso implícito de la unidad Variants
+% The Variant type is used in the unit without any used unit using the Variants unit. The
+% compiler has implicitly added the Variants unit to the uses list. To remove this warning
+% the Variants unit needs to be added to the uses statement.
+parser_e_no_static_method_in_interfaces=03212_E_Clases y métodos estáticos no pueden ser utilizados en interfaces
+% The specifier \var{class} and directive \var{static} can't be used in interfaces
+% because all methods of an interfaces must be public.
+parser_e_arithmetic_operation_overflow=03213_E_Desbordamiento en la operación aritmética
+% An operation on two integers values produced an overflow
+% \end{description}
+#
+# Type Checking
+#
+# 04049 is the last used one
+#
+% \section{Type checking errors}
+% This section lists all errors that can occur when type checking is
+% performed.
+% \begin{description}
+type_e_mismatch=04000_E_Los tipos no concuerdan
+% This can happen in many cases:
+% \begin{itemize}
+% \item The variable you're assigning to is of a different type than the
+% expression in the assignment.
+% \item You are calling a function or procedure with parameters that are
+% incompatible with the parameters in the function or procedure definition.
+% \end{itemize}
+type_e_incompatible_types=04001_E_Tipos incompatibles: se encontró "$1" esperado "$2"
+% There is no conversion possible between the two types
+% Another possiblity is that they are declared in different
+% declarations:
+% \begin{verbatim}
+% Var
+% A1 : Array[1..10] Of Integer;
+% A2 : Array[1..10] Of Integer;
+%
+% Begin
+% A1:=A2; { This statement gives also this error, it
+% is due the strict type checking of pascal }
+% End.
+% \end{verbatim}
+type_e_not_equal_types=04002_E_Los tipos $1 y $2 no concuerdan
+% The types are not equal
+type_e_type_id_expected=04003_E_Identificador de tipo esperado
+% The identifier is not a type, or you forgot to supply a type identifier.
+type_e_variable_id_expected=04004_E_Identificador de variable esperado
+% This happens when you pass a constant to a routine (such as \var{Inc} var or \var{Dec})
+% when it expects a variable. You can only pass variables as arguments to these functions.
+type_e_integer_expr_expected=04005_E_expression entera esperada, pero se encontró "$1"
+% The compiler expects an expression of type integer, but gets a different
+% type.
+type_e_boolean_expr_expected=04006_E_Expresion booleana esperada, pero se encontró "$1"
+% The expression must be a boolean type, it should be return true or
+% false.
+type_e_ordinal_expr_expected=04007_E_Espresión ordinal esperada
+% The expression must be of ordinal type, i.e., maximum a \var{Longint}.
+% This happens, for instance, when you specify a second argument
+% to \var{Inc} or \var{Dec} that doesn't evaluate to an ordinal value.
+type_e_pointer_type_expected=04008_E_Se esperaba un tipo puntero, pero se encontró "$1"
+% The variable or expression isn't of the type \var{pointer}. This
+% happens when you pass a variable that isn't a pointer to \var{New}
+% or \var{Dispose}.
+type_e_class_type_expected=04009_E_Se esperaba un tipo de clase, pero se encontró "$1"
+% The variable of expression isn't of the type \var{class}. This happens
+% typically when
+% \begin{enumerate}
+% \item The parent class in a class declaration isn't a class.
+% \item An exception handler (\var{On}) contains a type identifier that
+% isn't a class.
+% \end{enumerate}
+type_e_cant_eval_constant_expr=04011_E_No se puede evaluar la espresión constante
+% This error can occur when the bounds of an array you declared does
+% not evaluate to ordinal constants
+type_e_set_element_are_not_comp=04012_E_Elementos de sets incompatibles
+% You are trying to make an operation on two sets, when the set element types
+% are not the same. The base type of a set must be the same when taking the
+% union
+type_e_set_operation_unknown=04013_E_Operación no implementada para sets
+% several binary operations are not defined for sets
+% like div mod ** (also >= <= for now)
+type_w_convert_real_2_comp=04014_W_Conversion automática de tipo de punto flotante a COMP el cual es un tipo entero
+% An implicit type conversion from a real type to a \var{comp} is
+% encountered. Since \var{comp} is a 64 bit integer type, this may indicate
+% an error.
+type_h_use_div_for_int=04015_H_usa DIV para tener un resultado entero
+% When hints are on, then an integer division with the '/' operator will
+% procuce this message, because the result will then be of type real
+type_e_strict_var_string_violation=04016_E_Tipos de cadena no concuerdan por la presencia de la opción $V+
+% When compiling in \var{\{\$V+\}} mode, the string you pass as a parameter
+% should be of the exact same type as the declared parameter of the procedure.
+type_e_succ_and_pred_enums_with_assign_not_possible=04017_E_No se permite el uso de Succ o Pred en enumeraciones que tienen valores asignados explícitamente
+% When you declared an enumeration type which has assignments in it, as in C,
+% like in the following:
+% \begin{verbatim}
+% Tenum = (a,b,e:=5);
+% \end{verbatim}
+% you cannot use the \var{Succ} or \var{Pred} functions on them.
+type_e_cant_read_write_type=04018_E_No se puede leer o escribir variables de este tipo
+% You are trying to \var{read} or \var{write} a variable from or to a
+% file of type text, which doesn't support that. Only integer types,
+% reals, pchars and strings can be read from/written to a text file.
+% Booleans can only be written to text files.
+type_e_no_readln_writeln_for_typed_file=04019_E_No se puede utilizar readln o writeln en ficheros con tipo
+% \var{readln} and \var{writeln} are only allowed for text files.
+type_e_no_read_write_for_untyped_file=04020_E_No se pueden usar read o write en ficheros sin tipo
+% \var{read} and \var{write} are only allowed for text or typed files.
+type_e_typeconflict_in_set=04021_E_El set contiene un elemento que no es de tipo compatible
+% There is at least one set element which is of the wrong type, i.e. not of
+% the set type.
+type_w_maybe_wrong_hi_lo=04022_W_lo/hi(longint/dword) devuelve la parte superior/inferior de tipo word
+% \fpc supports an overloaded version of \var{lo/hi} for \var{longint/dword/int64/qword}
+% which returns the lower/upper word/dword of the argument. TP always uses
+% a 16 bit \var{lo/hi} which returns always bits 0..7 for \var{lo} and the
+% bits 8..15 for \var{hi}. If you want the TP behavior you have
+% to type cast the argument to \var{word/integer}
+type_e_integer_or_real_expr_expected=04023_E_Espresión entera o real esperada
+% The first argument to \var{str} must a real or integer type.
+type_e_wrong_type_in_array_constructor=04024_E_Tipo "$1" erróneo en el constructor del array
+% You are trying to use a type in an array constructor which is not
+% allowed.
+type_e_wrong_parameter_type=04025_E_Tipo incompatible para el parámetro número $1: Se recibió "$2", cuando se esperaba "$3"
+% You are trying to pass an invalid type for the specified parameter.
+type_e_no_method_and_procedure_not_compatible=04026_E_Variables de tipo método y procedimiento no son compatibles entre si
+% You can't assign a method to a procedure variable or a procedure to a
+% method pointer.
+type_e_wrong_math_argument=04027_E_Constante pasada a la función matematica interna no válida
+% The constant argument passed to a ln or sqrt function is out of
+% the definition range of these functions.
+type_e_no_addr_of_constant=04028_E_No se puede obtener una dirección de una constante
+% It is not possible to get the address of a constant, because they
+% aren't stored in memory, you can try making it a typed constant.
+type_e_argument_cant_be_assigned=04029_E_No se puede asignar un valor al parámetro
+% Only expressions which can be on the left side of an
+% assignment can be passed as call by reference argument
+% Remark: Properties can be only
+% used on the left side of an assignment, but they cannot be used as arguments
+type_e_cannot_local_proc_to_procvar=04030_E_No se puede asignar un prodecimiento o funcion local a una variable
+% It's not allowed to assign a local procedure/function to a
+% procedure variable, because the calling of local procedure/function is
+% different. You can only assign local procedure/function to a void pointer.
+type_e_no_assign_to_addr=04031_E_No se puede asignar un valor a una dirección
+% It is not allowed to assign a value to an address of a variable,constant,
+% procedure or function. You can try compiling with -So if the identifier
+% is a procedure variable.
+type_e_no_assign_to_const=04032_E_No se pueden asignar valores a variables constantes
+% It's not allowed to assign a value to a variable which is declared
+% as a const. This is normally a parameter declared as const, to allow
+% changing the value make the parameter as a value parameter or a var.
+type_e_array_required=04033_E_Se requiere un array para usar [ ]
+% If you are accessing a variable using an index '[<x>]' then
+% the type must be an array. In FPC mode also a pointer is allowed.
+type_e_interface_type_expected=04034_E_Se esperaba "interface" pero se encontró "$1"
+type_w_mixed_signed_unsigned=04035_W_Operaciones mezclando enteros de 32 bits con signo son convertidas a 64 bits
+% If you divide (or calculate the modulus of) a signed expression by a longword (or vice versa),
+% or if you have overflow and/or range checking turned on and use an arithmetic
+% expression (+, -, *, div, mod) in which both signed numbers and longwords appear,
+% then everything has to be evaluated in 64bit which is slower than normal
+% 32bit arithmetic. You can avoid this by typecasting one operand so it
+% matches the result type of the other one.
+type_w_mixed_signed_unsigned2=04036_W_Mezclar operando con signo y sin signo aqui puede causar errores de comprobación de rango
+% If you use a binary operator (and, or, xor) and one of
+% the operands is a longword while the other one is a signed expression, then,
+% if range checking is turned on, you may get a range check error because in
+% such a case both operands are converted to longword before the operation is
+% carried out. You can avoid this by typecasting one operand so it
+% matches the result type of the other one.
+type_e_typecast_wrong_size_for_assignment=04037_E_La conversión de tipos ($1 -> $2) en la asignación tiene diferentes tamaños
+% Type casting to a type with a different size is not allowed when the variable is
+% used for assigning.
+type_e_array_index_enums_with_assign_not_possible=04038_E_No se pueden usar enums con asignaciones como indices de arrays
+% When you declared an enumeration type which has assignments in it, as in C,
+% like in the following:
+% \begin{verbatim}
+% Tenum = (a,b,e:=5);
+% \end{verbatim}
+% you cannot use it as index of an array.
+type_e_classes_not_related=04039_E_Las clases u objetos "$1" y "$2" no están relacionados
+% There is a typecast from one class or object to another while the class/object
+% are not related. This will probably lead to errors
+type_w_classes_not_related=04040_W_Los tipos de clases "$1" y "$2" no están relacionados
+% There is a typecast from one class or object to another while the class/object
+% are not related. This will probably lead to errors
+type_e_class_or_interface_type_expected=04041_E_Se esperaba una clase o interfaz, pero se encotró "$1"
+type_e_type_is_not_completly_defined=04042_E_El tipo "$1" no esta definido completamente aún
+type_w_string_too_long=04043_W_La cadena contiene mas caracteres que los admitidos por una cadena corta
+% The size of the constant string, which is assigned to a shortstring,
+% is longer than the maximum size of the shortstring
+type_w_signed_unsigned_always_false=04044_W_La comparación es siempre falsa debido a los rangos de los valores
+% There is a comparison between an unsigned value and a signed constant which is
+% less than zero. Because of type promotion, the statement will always evaluate to
+% false. Exlicitly typecast the constant to the correct range to avoid this problem.
+type_w_signed_unsigned_always_true=04045_W_La comparación es siempre verdadera debido a los rangos de los valores
+% There is a comparison between an unsigned value and a signed constant which is
+% less than zero. Because of type promotion, the statement will always evaluate to
+% true. Exlicitly typecast the constant to the correct range to avoid this problem.
+type_w_instance_with_abstract=04046_W_Constuyendo un objeto de clase "$1" que contiene métodos abstractos
+% An instance of a class is created which contains non-implemented abstract
+% methods. This will probably lead to a runtime error 211 in the code if that
+% routine is ever called. All abstract methods should be overridden.
+type_h_in_range_check=04047_H_El operando a la izquierda de IN debe ser de tamaño un byte
+% The left operand of the \var{in} operator is not an ordinal or enumeration which fits
+% within 8-bits, this may lead to range check errors. The \var{in} operator
+% currently only supports a left operand which fits within a byte. In the case of
+% enumerations, the size of an element of an enumeration can be controlled with
+% the \var{\{\$PACKENUM\}} or \var{\{\$Zn\}} switches.
+type_w_smaller_possible_range_check=04048_W_Diferencia del tamaño de los tipos puede causar pérdida de datos o errores de comprobación de rango
+% There is an assignment to a smaller type than the source type. This means that
+% this may cause a range-check error, or may lead to possible loss of data.
+type_h_smaller_possible_range_check=04049_H_Diferencia del tamaño de los tipos puede causar pérdida de datos o errores de comprobación de rango
+% There is an assignment to a smaller type than the source type. This means that
+% this may cause a range-check error, or may lead to possible loss of data.
+type_e_cant_take_address_of_abstract_method=04050_E_No se puede obtener la dirección de un método abstracto
+% An abstract method has no body, so the address of an abstract method can't be taken.
+type_e_operator_not_allowed=04051_E_El operador no es aplicable con los operandos especificados
+% You are trying an operator that is not available for the type of the
+% operands
+type_e_constant_expr_expected=04052_E_Se esperaba una expresió constante
+% The compiler expects an constant expression, but gets a variable expression.
+type_e_operator_not_supported_for_types=04053_E_La operacion "$1" no está soportada para los tipos "$2" y "$3"
+% The operation is not allowed for the supplied types
+type_e_illegal_type_conversion=04054_E_No es posible realizar una conversión de "$1" a "$2"
+% When doing a type-cast, you must take care that the sizes of the variable and
+% the destination type are the same.
+type_h_pointer_to_longint_conv_not_portable=04055_H_La conversion entre punteros y ordinales no es portable
+% If you typecast a pointer to a longint (or vice-versa), this code will not compile
+% on a machine using 64-bit for pointer storage.
+type_w_pointer_to_longint_conv_not_portable=04056_W_La conversion entre punteros y ordinales no es portable
+% If you typecast a pointer to a ordinal type of a different size (or vice-versa), this can
+% cause problems. This is a warning to help finding the 32bit specific code where cardinal/longint is used
+% to typecast pointers to ordinals. A solution is to use the ptrint/ptruint types instead.
+type_e_cant_choose_overload_function=04057_E_No se pudo determinar que funcion sobrecargada llamar
+% You're calling overloaded functions with a parameter that doesn't correspond
+% to any of the declared function parameter lists. e.g. when you have declared
+% a function with parameters \var{word} and \var{longint}, and then you call
+% it with a parameter which is of type \var{integer}.
+type_e_illegal_count_var=04058_E_Variable de contador inválida
+% The type of a \var{for} loop variable must be an ordinal type.
+% Loop variables cannot be reals or strings.
+% \end{description}
+#
+# Symtable
+#
+# 05055 is the last used one
+#
+% \section{Symbol handling}
+% This section lists all the messages that concern the handling of symbols.
+% This means all things that have to do with procedure and variable names.
+% \begin{description}
+sym_e_id_not_found=05000_E_Identificador no encontrado "$1"
+% The compiler doesn't know this symbol. Usually happens when you misspel
+% the name of a variable or procedure, or when you forgot to declare a
+% variable.
+sym_f_internal_error_in_symtablestack=05001_F_Error interno en SymTableStack()
+% An internal error occurred in the compiler; If you encounter such an error,
+% please contact the developers and try to provide an exact description of
+% the circumstances in which the error occurs.
+sym_e_duplicate_id=05002_E_Identificador duplicado "$1"
+% The identifier was already declared in the current scope.
+sym_h_duplicate_id_where=05003_H_El identificador ya está definido en $1 en la línea $2
+% The identifier was already declared in a previous scope.
+sym_e_unknown_id=05004_E_Identificador desconocido "$1"
+% The identifier encountered has not been declared, or is used outside the
+% scope where it is defined.
+sym_e_forward_not_resolved=05005_E_Declaración posterior no solucionada "$1"
+% This can happen in two cases:
+% \begin{itemize}
+% \item This happens when you declare a function (in the \var{interface} part, or
+% with a \var{forward} directive, but do not implement it.
+% \item You reference a type which isn't declared in the current \var{type}
+% block.
+% \end{itemize}
+sym_e_error_in_type_def=05007_E_Error en definición de tipo
+% There is an error in your definition of a new array type:
+% \item One of the range delimiters in an array declaration is erroneous.
+% For example, \var{Array [1..1.25]} will trigger this error.
+sym_e_forward_type_not_resolved=05009_E_Tipo posterior no resuelto "$1"
+% A symbol was forward defined, but no declaration was encountered.
+sym_e_only_static_in_static=05010_E_Solo las variables estáticas pueden ser usadas en métodos estáticos o fuera de métodos
+% A static method of an object can only access static variables.
+sym_f_type_must_be_rec_or_class=05012_F_tipo record o class esperado
+% The variable or expression isn't of the type \var{record} or \var{class}.
+sym_e_no_instance_of_abstract_object=05013_E_No se permiten instancias de clases u objetos con un métodos abstractos
+% You are trying to generate an instance of a class which has an abstract
+% method that wasn't overridden.
+sym_w_label_not_defined=05014_W_Etiqueta no definida "$1"
+% A label was declared, but not defined.
+sym_e_label_used_and_not_defined=05015_E_Etiqueta "$1" usada pero no definida
+% A label was declared and used, but not defined.
+sym_e_ill_label_decl=05016_E_Declaración inválida de la etiqueta
+% This error should never happen; it occurs if a label is defined outside a
+% procedure or function.
+sym_e_goto_and_label_not_supported=05017_E_GOTO y LABEL no son soportados (debe ser habilitado con -Sg)
+% You must compile a program which has \var{label}s and \var{goto} statements
+% with the \var{-Sg} switch. By default, \var{label} and \var{goto} aren't
+% supported.
+sym_e_label_not_found=05018_E_Etiqueta no encontrada
+% A \var{goto label} was encountered, but the label isn't declared.
+sym_e_id_is_no_label_id=05019_E_el identificador no es una etiqueta
+% The identifier specified after the \var{goto} isn't of type label.
+sym_e_label_already_defined=05020_E_Etiqueta ya definida
+% You are defining a label twice. You can define a label only once.
+sym_e_ill_type_decl_set=05021_E_Definicion de tipo set inválida
+% The declaration of a set contains an invalid type definition.
+sym_e_class_forward_not_resolved=05022_E_Definición posterior de la clase "$1" no resuelta
+% You declared a class, but you did not implement it.
+sym_n_unit_not_used=05023_H_Unidad "$1" no utilizada en $2
+% The unit referenced in the \var{uses} clause is not used.
+sym_h_para_identifier_not_used=05024_H_Parámetro "$1" no usado
+% The identifier was declared (locally or globally) but
+% was not used (locally or globally).
+sym_n_local_identifier_not_used=05025_N_Variable local no usada "$1"
+% You have declared, but not used a variable in a procedure or function
+% implementation.
+sym_h_para_identifier_only_set=05026_H_Valor asignado a "$1" pero no utilizado
+% The identifier was declared (locally or globally)
+% set but not used (locally or globally).
+sym_n_local_identifier_only_set=05027_N_Valor asignado a la variable local "$1" no utilizado
+% The variable in a procedure or function
+% implementation is declared, set but never used.
+sym_h_local_symbol_not_used=05028_H_Símbolo local $1 "$2" no utilizado
+% A local symbol is never used.
+sym_n_private_identifier_not_used=05029_N_Campo privado $1.$2 no utilizado
+sym_n_private_identifier_only_set=05030_N_Valor asignado al campo privado $1.$2 pero nunca es utilizado
+sym_n_private_method_not_used=05031_N_Método privado $1.$2 no utilizado
+sym_e_set_expected=05032_E_Tipo set esperado
+% The variable or expression is not of type \var{set}. This happens in an
+% \var{in} statement.
+sym_w_function_result_not_set=05033_W_El resultado de la función puede no haber sido asignado
+% You can get this warning if the compiler thinks that a function return
+% value is not set. This will not be displayed for assembler procedures,
+% or procedures that contain assembler blocks.
+sym_w_wrong_C_pack=05034_W_El tipo "$1" no esta correctamente alineado para C
+% Arrays with sizes not multiples of 4 will be wrongly aligned
+% for C structures.
+sym_e_illegal_field=05035_E_Identificador de campo de registro desconocido: "$1"
+% The field doesn't exist in the record/object definition.
+sym_w_uninitialized_local_variable=05036_W_La variable local "$1" no parace haber sido inicializada
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_w_uninitialized_variable=05037_W_La variable "$1" no parece haber sido inicializada
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_e_id_no_member=05038_E_El identificador "$1" no identifica ningún miembro
+% This error is generated when an identifier of a record,
+% field, or method is accessed while it is not defined.
+sym_h_param_list=05039_H_Declaracion encontrada: $1
+% You get this when you use the \var{-vh} switch. In case an overloaded
+% procedure is not found, then all candidate overloaded procedures are
+% listed, with their parameter lists.
+sym_e_segment_too_large=05040_E_Segmento de datos demasiado grande
+% You get this when you declare a data element whose size exceeds the
+% prescribed limit (2 Gb on 80386+/68020+ processors)
+sym_e_no_matching_implementation_found=05042_E_No se encontro una implementación para el método "$1" de la interfaz
+% There was no matching method found which could implement the interface
+% method. Check argument types and result type of the methods.
+sym_w_deprecated_symbol=05043_W_Símbolo "$1" desaconsejado
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{deprecated} is used. Deprecated symbols may no longer
+% be available in newer versions of the unit / library. Usage of this symbol
+% should be avoided as much as possible.
+sym_w_non_portable_symbol=05044_W_El símbolo "$1" no es portable
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{platform} is used. This symbol's value, usage
+% and availability is platform specific and should not be used
+% if the source code must be portable.
+sym_w_non_implemented_symbol=05055_W_El símbolo "$1" no está implementado
+% This means that a symbol (a variable, routine, etc...) which is
+% declared as \var{unimplemented} is used. This symbol is defined,
+% but is not yet implemented on this specific platform.
+sym_e_cant_create_unique_type=05056_E_No se puede crear un tipo único a partir de este tipo
+% Only simple types like ordinal, float and string types are supported when
+% redefining a type with \var{type newtype = type oldtype;}.
+sym_h_uninitialized_local_variable=05057_H_La variable local "$1" no parece haber sido inicializada
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+sym_h_uninitialized_variable=05058_H_La variable "$1" no parece haber sido inicializada
+% This message is displayed if the compiler thinks that a variable will
+% be used (i.e. appears in the right-hand-side of an expression) when it
+% was not initialized first (i.e. appeared in the left-hand side of an
+% assigment)
+% \end{description}
+#
+# Codegenerator
+#
+# 06040 is the last used one
+#
+% \section{Code generator messages}
+% This section lists all messages that can be displayed if the code
+% generator encounters an error condition.
+% \begin{description}
+cg_e_parasize_too_big=06009_E_El tamaño de la lista de par metros excede 65535 bytes
+% The I386 processor limits the parameter list to 65535 bytes (the \var{RET}
+% instruction causes this)
+cg_e_file_must_call_by_reference=06012_E_Los tipos File deben ser pasados por referencia
+% You cannot specify files as value parameters, i.e. they must always be
+% declared \var{var} parameters.
+cg_e_cant_use_far_pointer_there=06013_E_El uso de punteros "far" no esta permitido aqií
+% Free Pascal doesn't support far pointers, so you cannot take the address of
+% an expression which has a far reference as a result. The \var{mem} construct
+% has a far reference as a result, so the following code will produce this
+% error:
+% \begin{verbatim}
+% var p : pointer;
+% ...
+% p:=@mem[a000:000];
+% \end{verbatim}
+cg_e_dont_call_exported_direct=06015_E_las funciones declaradas como EXPORT no pueden ser llamadas
+% No longer in use.
+cg_w_member_cd_call_from_method=06016_W_Posible llamada inválida de un constructor o destructor
+% The compiler detected that a constructor or destructor is called within a
+% a method. This will probably lead to problems, since constructors / destructors
+% require parameters on entry.
+cg_n_inefficient_code=06017_N_código ineficiente
+% Your statement seems dubious to the compiler.
+cg_w_unreachable_code=06018_W_El código no será ejecutado nunca
+% You specified a construct which will never be executed. Example:
+% \begin{verbatim}
+% while false do
+% begin
+% {.. code ...}
+% end;
+% \end{verbatim}
+cg_e_cant_call_abstract_method=06020_E_Los métodos abstractos no pueden ser llamados directamente
+% You cannot call an abstract method directy, instead you must call a
+% overriding child method, because an abstract method isn't implemented.
+cg_d_register_weight=06027_DL_Registro $1 peso $2 $3
+% Debugging message. Shown when the compiler considers a variable for
+% keeping in the registers.
+cg_d_stackframe_omited=06029_DL_Se omite generar stack frame
+% Some procedure/functions do not need a complete stack-frame, so it is omitted.
+% This message will be displayed when the {-vd} switch is used.
+cg_e_unable_inline_object_methods=06031_E_Métodos de objetos o clases no pueden ser inline
+% You cannot have inlined object methods.
+cg_e_unable_inline_procvar=06032_E_Variables de procedimiento o función no pueden ser inline
+% A procedure with a procedural variable call cannot be inlined.
+cg_e_no_code_for_inline_stored=06033_E_No hay código almacenado para procedimientos inline
+% The compiler couldn't store code for the inline procedure.
+cg_e_can_access_element_zero=06035_E_No se puede acceder al elemento 0 de cadenas largas, use SetLength/Length
+% You should use \var{setlength} to set the length of an ansi/wide/longstring
+% and \var{length} to get the length of such a string types
+cg_e_cannot_call_cons_dest_inside_with=06037_E_No se pueden llamar a constructores o destructores en with
+% Inside a \var{with} clause you cannot call a constructor or destructor for the
+% object you have in the \var{with} clause.
+cg_e_cannot_call_message_direct=06038_E_No se pueden llamar a métodos manejadores de mensajes directamente
+% A message method handler method cannot be called directly if it contains an
+% explicit self argument
+cg_e_goto_inout_of_exception_block=06039_E_Salto fuera de un bloque de excepción
+% It is not allowed to jump in or outside of an exception block like \var{try..finally..end;}:
+% \begin{verbatim}
+% label 1;
+%
+% ...
+%
+% try
+% if not(final) then
+% goto 1; // this line will cause an error
+% finally
+% ...
+% end;
+% 1:
+% ...
+% \end{verbatim}
+cg_e_control_flow_outside_finally=06040_E_No se admiten instrucciones de control de flujo en un bloque finally
+% It isn't allowed to use the control flow statements \var{break},
+% \var{continue} and \var{exit}
+% inside a finally statement. The following example shows the problem:
+% \begin{verbatim}
+% ...
+% try
+% p;
+% finally
+% ...
+% exit; // This exit ISN'T allowed
+% end;
+% ...
+%
+% \end{verbatim}
+% If the procedure \var{p} raises an exception the finally block is
+% executed. If the execution reaches the exit, it's unclear what to do:
+% exiting the procedure or searching for another exception handler
+cg_w_parasize_too_big=06041_W_El tamaño del parámetro excede el límite de algunas CPU
+% This indicates that you are declaring more than 64K of parameters, which
+% might not be supported on other processor targets.
+cg_w_localsize_too_big=06042_W_El tamaño de las variables locales excede el límite de algunas CPU
+% This indicates that you are declaring more than 32K of lcoal variables, which
+% might not be supported on other processor targets.
+cg_e_localsize_too_big=06043_E_El tamaño de las variables locales excede el límite de la CPU de destino
+% This indicates that you are declaring more than 32K of lcoal variables, which
+% is not supported by this processor.
+cg_e_break_not_allowed=06044_E_BREAK no permitido aquí
+% You're trying to use \var{break} outside a loop construction.
+cg_e_continue_not_allowed=06045_E_CONTINUE no permitido aquí
+% You're trying to use \var{continue} outside a loop construction.
+% \end{description}
+# EndOfTeX
+
+#
+# Assembler reader
+#
+# 07097 is the last used one
+#
+asmr_d_start_reading=07000_DL_Iniciando interpretado de ensamblador de estilo $1
+% This informs you that an assembler block is being parsed
+asmr_d_finish_reading=07001_DL_Finalizado interpretado de ensamblador de estilo $1
+% This informs you that an assembler block has finished.
+asmr_e_none_label_contain_at=07002_E_Una patrón que no es una etiqueta contiene @
+% A identifier which isn't a label can't contain a @.
+asmr_e_building_record_offset=07004_E_Error construyendo desplazamiento de registro (record)
+% There has an error occured while building the offset of a record/object
+% structure, this can happend when there is no field specified at all or
+% an unknown field identifier is used.
+asmr_e_offset_without_identifier=07005_E_OFFSET usado sin identificador
+% You can only use OFFSET with an identifier. Other syntaxes aren't
+% supported
+asmr_e_type_without_identifier=07006_E_TYPE usado sin identificador
+% You can only use TYPE with an identifier. Other syntaxes aren't
+% supported
+asmr_e_no_local_or_para_allowed=07007_E_No es posible usar una variable local o parámetro aquí
+% You can't use a local variable or parameter here, mostly because the
+% addressing of locals and parameters is done using the frame pointer register so the
+% address can't be obtained directly.
+asmr_e_need_offset=07008_E_Es necesario el uso de OFFSET aquí
+% You need to use OFFSET <id> here to get the address of the identifier.
+asmr_e_need_dollar=07009_E_Es necesario el uso de $ auqí
+% You need to use $<id> here to get the address of the identifier.
+asmr_e_cant_have_multiple_relocatable_symbols=07010_E_No es posible utilizar varios símbolos reubicables
+% You can't have more than one relocatable symbol (variable/typed constant)
+% in one argument.
+asmr_e_only_add_relocatable_symbol=07011_E_Símbolos reubicables solo pueden ser añadidos
+% Relocatable symbols (variable/typed constant) can't be used with other
+% operators. Only addition is allowed.
+asmr_e_invalid_constant_expression=07012_E_Espresió constante inválida
+% There is an error in the constant expression.
+asmr_e_relocatable_symbol_not_allowed=07013_E_Símbolo reubicable no permitido
+% You can't use a relocatable symbol (variable/typed constant) here.
+asmr_e_invalid_reference_syntax=07014_E_Sintaxis de referencia inválida
+% There is an error in the reference.
+asmr_e_local_para_unreachable=07015_E_No se puede llegar a $1 desde este código
+% You can not read directly the value of local or para
+% of a higher level in assembler code (except for
+% local assembler code without parameter nor locals).
+asmr_e_local_label_not_allowed_as_ref=07016_E_No está permitido el uso símbolos locales o etiquetas como referencias
+% You can't use local symbols/labels as references
+asmr_e_wrong_base_index=07017_E_Uso inválido de registros indice y base
+% There is an error with the base and index register, they are
+% probably incorrect
+asmr_w_possible_object_field_bug=07018_W_Posible error en el manejo de campos de objetos
+% Fields of objects or classes can be reached directly in normal or objfpc
+% modes but TP and Delphi modes treat the field name as a simple offset.
+asmr_e_wrong_scale_factor=07019_E_Factor de escala erróneo
+% The scale factor given is wrong, only 1,2,4 and 8 are allowed
+asmr_e_multiple_index=07020_E_Uso de multiples registros índice
+% You are trying to use more than one index register
+asmr_e_invalid_operand_type=07021_E_Tipo del operando no válido
+% The operand type doesn't match with the opcode used
+asmr_e_invalid_string_as_opcode_operand=07022_E_Cadena no vólida como operando de esta instrucción: $1
+% The string specified as operand is not correct with this opcode
+asmr_w_CODE_and_DATA_not_supported=07023_W_@CODE y @DATA no son soportados
+% @CODE and @DATA are unsupported and are ignored.
+asmr_e_null_label_ref_not_allowed=07024_E_Referencias a etiqueta nula no permitida
+asmr_e_expr_zero_divide=07025_E_Division entre cero en el evaluador de ensamblador
+% There is a division by zero in a constant expression
+asmr_e_expr_illegal=07026_E_Expresión inválida
+% There is an illegal expression in a constant expression
+asmr_e_escape_seq_ignored=07027_E_Sequencia de escape ignorada: $1
+% There is a C-styled string, but the escape sequence in the string
+% is unknown, and is therefore ignored
+asmr_e_invalid_symbol_ref=07028_E_Referencia a símbolo inválida
+asmr_w_fwait_emu_prob=07029_W_Fwait puede causar problemas de emulación con emu387
+asmr_w_fadd_to_faddp=07030_W_$1 sin operando interpretado como $1P
+asmr_w_enter_not_supported_by_linux=07031_W_La instruccion ENTER no está soportada por el kernel de Linux
+% ENTER instruction can generate a stack page fault that is not
+% caught correctly by the i386 Linux page handler.
+asmr_w_calling_overload_func=07032_W_Llamando a una funcion sobrecargada desde ensamblador
+% There is a call to an overloaded method in the assembler block,
+% this might be the sign there is a problem
+asmr_e_unsupported_symbol_type=07033_E_Tipo de símbolo no soportado para el operando
+asmr_e_constant_out_of_bounds=07034_E_Valor de la constante fuera de rango
+asmr_e_error_converting_decimal=07035_E_Error convirtiendo decimal $1
+% A constant decimal value does not have the correct syntax
+asmr_e_error_converting_octal=07036_E_Error convirtiendo octal $1
+% A constant octal value does not have the correct syntax
+asmr_e_error_converting_binary=07037_E_Error convirtiendo binario $1
+% A constant binary value does not have the correct syntax
+asmr_e_error_converting_hexadecimal=07038_E_Error convirtiendo hexadecimal $1
+% A constant hexadecimal value does not have the correct syntax
+asmr_h_direct_global_to_mangled=07039_H_$1 traducido a $2
+asmr_w_direct_global_is_overloaded_func=07040_W_$1 esta asociado a una función sobrecargada
+asmr_e_cannot_use_SELF_outside_a_method=07041_E_No se puede usar SELF fuera de un método
+% There is a reference to the \var{self} symbol while it is not
+% allowed. \var{self} can only be referenced inside methods
+asmr_e_cannot_use_OLDEBP_outside_nested_procedure=07042_E_No se puede usar OLDEBP fuera de un procedimiento anidado
+% There is a reference to the \var{oldebp} symbol while it is not
+% allowed. \var{oldebp} can only be referenced inside nested routines
+asmr_e_void_function=07043_W_No es posible devolver un valor en procedimientos desde código asm
+% Trying to return a value while in a procedure. A procedure
+% does not have any return value
+asmr_e_SEG_not_supported=07044_E_SEG no soportado
+asmr_e_size_suffix_and_dest_dont_match=07045_E_No concuerdan el tamaño del prefijo y el del origen o destino
+% The register size and the opcode size suffix don't match. This is
+% probably an error in the assembler statement
+asmr_w_size_suffix_and_dest_dont_match=07046_W_No concuerdan el tamaño del prefijo y el del origen o destino
+% The register size and the opcode size suffix don't match. This is
+% probably an error in the assembler statement
+asmr_e_syntax_error=07047_E_Error de sintaxis de ensamblador
+% There is an assembler syntax error
+asmr_e_invalid_opcode_and_operand=07048_E_Combinación inválida de operacion y operandos
+% The opcode cannot be used with this type of operand
+asmr_e_syn_operand=07049_E_Error de sintaxis de ensamblador en operando
+asmr_e_syn_constant=07050_E_Error de sintaxis de ensamblador en constante
+asmr_e_invalid_string_expression=07051_E_Espresión de cadena noáv lida
+asmr_w_const32bit_for_address=07052_W_constante con la direccion del símbolo $1 que no es un puntero
+% A constant expression represents an address which does not fit
+% into a pointer. The address is probably incorrect
+asmr_e_unknown_opcode=07053_E_Instrucción $1 no reconocida
+% This opcode is not known
+asmr_e_invalid_or_missing_opcode=07054_E_Falta la instrucción o no es válida
+asmr_e_invalid_prefix_and_opcode=07055_E_Combinación de prefijo y operación inválidos: $1
+asmr_e_invalid_override_and_opcode=07056_E_Combinación de sobrecarga y operación inválidos: $1
+asmr_e_too_many_operands=07057_E_Demasiados operandos en la línea
+% There are too many operands for this opcode. Check your
+% assembler syntax
+asmr_w_near_ignored=07058_W_NEAR ignorado
+asmr_w_far_ignored=07059_W_FAR ignorado
+asmr_e_dup_local_sym=07060_E_Símbolo local duplicado $1
+asmr_e_unknown_local_sym=07061_E_Símbolo local indefinido $1
+asmr_e_unknown_label_identifier=07062_E_Identificador de etiqueta desconocido $1
+asmr_e_invalid_register=07063_E_Nombre de registro incorrecto
+% There is an unknown register name used as operand.
+asmr_e_invalid_fpu_register=07064_E_Nombre de registro de punto flotante no válido
+% There is an unknown register name used as operand.
+asmr_w_modulo_not_supported=07066_W_Modulo no soportado
+asmr_e_invalid_float_const=07067_E_Constante de punto flotante no válida $1
+% The floating point constant declared in an assembler block is
+% invalid.
+asmr_e_invalid_float_expr=07068_E_Espresión de punto flotante no válida
+% The floating point expression declared in an assembler block is
+% invalid.
+asmr_e_wrong_sym_type=07069_E_Tipo de símbolo erróneo
+asmr_e_cannot_index_relative_var=07070_E_No se puede indexar una var. local o un parámetro con un registro
+% Trying to index using a base register a symbol which is already relative
+% to a register. This is not possible, and will probably lead to crashes.
+asmr_e_invalid_seg_override=07071_E_Espresión reemplazo de segmento inválida
+asmr_w_id_supposed_external=07072_W_Identificador $1 se supone externo
+% There is a reference to an undefined symbol. This will not result
+% in an error, since the symbol might be external, but may cause
+% problems at link time if the symbol is not defined anywhere.
+asmr_e_string_not_allowed_as_const=07073_E_Cadenas no permitidas como constantes
+% Character strings are not allowed as constants.
+asmr_e_no_var_type_specified=07074_E_No hay tipo de variable especificado
+% The syntax expects a type idenfitifer after the dot, but
+% none was found.
+asmr_w_assembler_code_not_returned_to_text=07075_E_Código ensamblador no devuelto a sección de texto
+% There was a directive in the assembler block to change sections,
+% but there is a missing return to the text section at the end
+% of the assembler block. This might cause errors during link time.
+asmr_e_not_directive_or_local_symbol=07076_E_No es una directiva o un símbolo local $1
+% This symbol is unknown.
+asmr_w_using_defined_as_local=07077_E_Usando un nombre definido como una etiqueta local
+asmr_e_dollar_without_identifier=07078_E_Tóken de dólar usado sin identificador
+% A constant expression has an identifier which does not start with
+% the $ symbol.
+asmr_w_32bit_const_for_address=07079_W_Constante de 32 bits creada para la dirección
+% A constant was used as an address. This is probably an error,
+% since using absolute addresses will probably not work.
+asmr_n_align_is_target_specific=07080_N_.align es dependiente de la plataforma, use .balign o .p2align
+% Using the .align directive is platform specific, and its meaning will vary
+% from one platform to another.
+asmr_e_cannot_access_field_directly_for_parameters=07081_E_No se puede acceder directamente a los campos de los parámetros
+% You should load the parameter first into a register and then access the
+% fields using that register.
+asmr_e_cannot_access_object_field_directly=07082_E_No se puede acceder directamente a los campos de objetos o clases
+% You should load the self pointer first into a register and then access the
+% fields using the register as base. By default the self pointer is available
+% in the esi register on i386.
+asmr_e_unable_to_determine_reference_size=07083_E_No se especificó un tamaño y no es posible determinar el tamaño del operando
+% You should specify explicitly a size for the reference, because
+% the compiler is unable to determine what size (byte,word,dword,etc.) it
+% should use for the reference.
+asmr_e_cannot_use_RESULT_here=07084_E_No se puede utilizar RESULT en esta función
+% Some functions which return complex types cannot use the \var{result}
+% keyword.
+asmr_w_adding_explicit_args_fXX=07086_W_"$1" sin operando traducido como "$1 %st,%st(1)"
+asmr_w_adding_explicit_first_arg_fXX=07087_W_"$1 %st(n)" traducido como "$1 %st,%st(n)"
+asmr_w_adding_explicit_second_arg_fXX=07088_W_"$1 %st(n)" traducido como "$1 %st(n),%st"
+asmr_e_invalid_char_smaller=07089_E_El carácter < no está permitido aquí
+% The shift operator requires the << characters. Only one
+% of those characters was found.
+asmr_e_invalid_char_greater=07090_E_El carácter > no está permitido aqui
+% The shift operator requires the >> characters. Only one
+% of those characters was found.
+asmr_w_align_not_supported=07093_W_ALIGN no es soportado
+asmr_e_no_inc_and_dec_together=07094_E_Inc y Dec no pueden estar juntos en la misma instrucción
+% Trying to use an increment and a decrement within the same
+% opcode on the 680x0. This is impossible.
+asmr_e_invalid_reg_list_in_movem=07095_E_Lista de registros inválida para movem
+% Trying to use the \var{movem} opcode with invalid registers
+% to save or restore.
+asmr_e_invalid_reg_list_for_opcode=07096_E_Lista de registros inválida para la instrucción
+asmr_e_higher_cpu_mode_required=07097_E_Se requiere un modo de CPU superior ($1)
+% Trying to use an instruction which is not supported in the current
+% cpu mode. Use a higher cpu generation to be able to use this
+% opcode in your assembler block
+asmr_w_unable_to_determine_reference_size_using_dword=07098_W_No se especificó el tamaño del operando y no pudo ser determinado. Se utilizará DWORD por defecto
+% You should specify explicitly a size for the reference, because
+% the compiler is unable to determine what size (byte,word,dword,etc.) it
+% should use for the reference. This warning is only used in Delphi mode where
+% it falls back to use DWORD as default.
+asmr_e_illegal_shifterop_syntax=07099_E_Error de sintaxis tratando de interpretar un operando de desplazamiento
+% ARM only; ARM assembler supports a so called shifter operand. The used syntax isn't
+% a valid shifter operand. Example for an operation with shifter operand:
+% \begin{verbatim}
+% asm
+% orr r2,r2,r2,lsl #8
+% end;
+% \end{verbatim}
+#
+# Assembler/binary writers
+#
+# 08018 is the last used one
+#
+asmw_f_too_many_asm_files=08000_F_Demasiados archivos de ensamblador abiertos
+% With smartlinking enabled, there are too many assembler
+% files generated. Disable smartlinking.
+asmw_f_assembler_output_not_supported=08001_F_Salida a ensamblador seleccionada no soportada
+asmw_f_comp_not_supported=08002_F_Comp no soportado
+asmw_f_direct_not_supported=08003_F_Direct no soportado por escritores binarios
+% Direct assembler mode is not supported for binary writers.
+asmw_e_alloc_data_only_in_bss=08004_E_Sólo esta permitido alojar datos en la seccion bss
+asmw_f_no_binary_writer_selected=08005_F_No hay seleccionado un escritor binario
+asmw_e_opcode_not_in_table=08006_E_Asm: Opcode $1 no está en la tabla
+asmw_e_invalid_opcode_and_operands=08007_E_Asm: $1 combinacion inválida de opcode y operandos
+asmw_e_16bit_not_supported=08008_E_Asm: Referencias de 16 Bit no soportadas
+asmw_e_invalid_effective_address=08009_E_Asm: Dirección efectiva no válida
+asmw_e_immediate_or_reference_expected=08010_E_Asm: Inmediato o referencia esperado
+asmw_e_value_exceeds_bounds=08011_E_Asm: $1 valor excede los límites $2
+asmw_e_short_jmp_out_of_range=08012_E_Asm: Salto corto es fuera de rango $1
+asmw_e_undefined_label=08013_E_Asm: Etiqueta no definida $1
+asmw_e_comp_not_supported=08014_E_Asm: El tipo Comp no está soportado en esta plataforma
+asmw_e_extended_not_supported=08015_E_Asm: El tipo Extended no está soportado en esta plataforma
+asmw_e_duplicate_label=08016_E_Asm: Etiquita $1 duplicada
+asmw_e_redefined_label=08017_E_Asm: Etiqueta $1 redefinida
+asmw_e_first_defined_label=08018_E_Asm: Se definió por primera vez aquí
+asmw_e_invalid_register=08019_E_Asm: Registro $1 inválido
+
+#
+# Executing linker/assembler
+#
+# 09034 is the last used one
+#
+# BeginOfTeX
+%
+% \section{Errors of assembling/linking stage}
+% This section lists errors that occur when the compiler is processing the
+% command line or handling the configuration files.
+% \begin{description}
+exec_w_source_os_redefined=09000_W_Sistema operativo de origen redefinido
+exec_i_assembling_pipe=09001_I_Ensamblando (pipe) $1
+exec_d_cant_create_asmfile=09002_E_No se puede crear fichero ensamblador $1
+% The mentioned file can't be created. Check if you have got
+% access permissions to create this file
+exec_e_cant_create_objectfile=09003_E_No se puede crear fichero objeto: $1
+% The mentioned file can't be created. Check if you've
+% got access permissions to create this file
+exec_e_cant_create_archivefile=09004_E_No se puede crear fichero de archivado: $1
+% The mentioned file can't be created. Check if you've
+% access permissions to create this file
+exec_e_assembler_not_found=09005_E_Ensamblador $1 no encontrado, cambiando a ensamblado externo
+exec_t_using_assembler=09006_T_Usando ensamblador: $1
+exec_e_error_while_assembling=09007_E_Error mientras se ensamblaba, codigo de terminación $1
+% There was an error while assembling the file using an external assembler.
+% Consult the documentation of the assembler tool to find out more information
+% on this error.
+exec_e_cant_call_assembler=09008_E_No se pudo llamar al ensamblador, error $1. Cambiando a ensamblador externo
+exec_i_assembling=09009_I_Ensamblando $1
+exec_i_assembling_smart=09010_I_Assembling con enlazado inteligente $1
+exec_w_objfile_not_found=09011_W_Objeto $1 no encontrado, el enlazado podria fallar!
+% One of the object file is missing, and linking will probably fail.
+% Check your paths.
+exec_w_libfile_not_found=09012_W_Librería $1 no encontrada, el enlazado podria fallar!
+% One of the library file is missing, and linking will probably fail.
+% Check your paths.
+exec_e_error_while_linking=09013_E_Error durante el enlazado
+% Generic error while linking.
+exec_e_cant_call_linker=09014_E_No se puede llamar al enlazador, cambiando a enlazado externo
+exec_i_linking=09015_I_Enlazando $1
+exec_e_util_not_found=09016_E_Utilidad $1 no encontrada, cambiando a enlazado externo
+exec_t_using_util=09017_T_Utilizando utilidad $1
+exec_e_exe_not_supported=09018_E_Creacion de ejecutables no soportado
+exec_e_dll_not_supported=09019_E_Creacion de librerías dinámicas/compartidas no soportado
+exec_i_closing_script=09020_I_Cerrando script $1
+exec_e_res_not_found=09021_E_Compilador de recursos no encontrado, cambiando a modo externo
+exec_i_compilingresource=09022_I_Compilando resource $1
+exec_t_unit_not_static_linkable_switch_to_smart=09023_T_La unidad $1 no puede ser enlazada estáticamente, cambiando a enlazado inteligente
+exec_t_unit_not_smart_linkable_switch_to_static=09024_T_La unidad $1 no puede ser enlazada inteligentemente, cambiando a enlazado estático
+exec_t_unit_not_shared_linkable_switch_to_static=09025_T_La unidad $1 no admite enlazado compartido, cambiando a enlazado estático
+exec_e_unit_not_smart_or_static_linkable=09026_E_La unidad $1 no puede ser enlazada estática o inteligentemente
+exec_e_unit_not_shared_or_static_linkable=09027_E_La unidad $1 no admite enlazado compartido o estático
+%\end{description}
+# EndOfTeX
+
+#
+# Executable information
+#
+execinfo_f_cant_process_executable=09128_F_No se puede post-procesar el ejecutable $1
+execinfo_f_cant_open_executable=09129_F_No se puede abrir el ejecutable $1
+execinfo_x_codesize=09130_X_Tamaño de Código: $1 bytes
+execinfo_x_initdatasize=09131_X_Tamaño de datos inicializados: $1 bytes
+execinfo_x_uninitdatasize=09132_X_Tamaño de datos sin inicializar: $1 bytes
+execinfo_x_stackreserve=09133_X_Espacio reservado para la pila: $1 bytes
+execinfo_x_stackcommit=09134_X_Stack space commited: $1 bytes
+
+#
+# Unit loading
+#
+# 10041 is the last used one
+#
+# BeginOfTeX
+% \section{Unit loading messages.}
+% This section lists all messages that can occur when the compiler is
+% loading a unit from disk into memory. Many of these messages are
+% informational messages.
+% \begin{description}
+unit_t_unitsearch=10000_T_Buscando unidad: $1
+% When you use the \var{-vt}, the compiler tells you where it tries to find
+% unit files.
+unit_t_ppu_loading=10001_T_Cargando PPU $1
+% When the \var{-vt} switch is used, the compiler tells you
+% what units it loads.
+unit_u_ppu_name=10002_U_PPU Nombre: $1
+% When you use the \var{-vu} flag, the unit name is shown.
+unit_u_ppu_flags=10003_U_PPU Banderas: $1
+% When you use the \var{-vu} flag, the unit flags are shown.
+unit_u_ppu_crc=10004_U_PPU CRC: $1
+% When you use the \var{-vu} flag, the unit CRC check is shown.
+unit_u_ppu_time=10005_U_PPU Fecha: $1
+% When you use the \var{-vu} flag, the time the unit was compiled is shown.
+unit_u_ppu_file_too_short=10006_U_Fichero PPU demasiado corto
+% The ppufile is too short, not all declarations are present.
+unit_u_ppu_invalid_header=10007_U_Cabecera PPU inválida (no comienza por PPU)
+% A unit file contains as the first three bytes the ascii codes of \var{PPU}
+unit_u_ppu_invalid_version=10008_U_Versión $1 inválida
+% This unit file was compiled with a different version of the compiler, and
+% cannot be read.
+unit_u_ppu_invalid_processor=10009_U_PPU está compilada para otro procesador
+% This unit file was compiled for a different processor type, and
+% cannot be read
+unit_u_ppu_invalid_target=10010_U_PPU está compilada para otra plataforma
+% This unit file was compiled for a different target, and
+% cannot be read
+unit_u_ppu_source=10011_U_Origen PPU: $1
+% When you use the \var{-vu} flag, the unit CRC check is shown.
+unit_u_ppu_write=10012_U_Escribiendo $1
+% When you specify the \var{-vu} switch, the compiler will tell you where it
+% writes the unit file.
+unit_f_ppu_cannot_write=10013_F_No se puede escribir el fichero PPU
+% An error occurred when writing the unit file.
+unit_f_ppu_read_error=10014_F_Error leyendo fichero PPU
+% This means that the unit file was corrupted, and contains invalid
+% information. Recompilation will be necessary.
+unit_f_ppu_read_unexpected_end=10015_F_Fin de fichero inesperado
+% Unexpected end of file. This may mean that the PPU file is
+% corrupted.
+unit_f_ppu_invalid_entry=10016_F_Entrada inválida en fichero PPU: $1
+% The unit the compiler is trying to read is corrupted, or generated with a
+% newer version of the compiler.
+unit_f_ppu_dbx_count_problem=10017_F_Problema en el contador PPU Dbx
+% There is an inconsistency in the debugging information of the unit.
+unit_e_illegal_unit_name=10018_E_Nombre de unidad inválido: $1
+% The name of the unit does not match the file name.
+unit_f_too_much_units=10019_F_Demasiades unidades
+% \fpc has a limit of 1024 units in a program. You can change this behavior
+% by changing the \var{maxunits} constant in the \file{fmodule.pas} file of the
+% compiler, and recompiling the compiler.
+unit_f_circular_unit_reference=10020_F_Referencia circular entre unidades $1 y $2
+% Two units are using each other in the interface part. This is only allowed
+% in the \var{implementation} part. At least one unit must contain the other one
+% in the \var{implementation} section.
+unit_f_cant_compile_unit=10021_F_No se puede compilar la unidad $1, no hay código fuente disponible
+% A unit was found that needs to be recompiled, but no sources are
+% available.
+unit_f_cant_find_ppu=10022_F_No se puede encontrar la unidad $1
+% You tried to use a unit of which the PPU file isn't found by the
+% compiler. Check your configuration file for the unit paths
+unit_w_unit_name_error=10023_W_La unidad $1 no pudo ser encontrada, pero $2 existe
+unit_f_unit_name_error=10024_F_Se buscó la unidad $1 pero se encontró $2
+% Dos truncation of 8 letters for unit PPU files
+% may lead to problems when unit name is longer than 8 letters.
+unit_w_switch_us_missed=10025_W_Compilar la unidad System requiere el conmutador -Us
+% When recompiling the system unit (it needs special treatment), the
+% \var{-Us} must be specified.
+unit_f_errors_in_unit=10026_F_Hubo $1 errores compilando el modulo, parando
+% When the compiler encounters a fatal error or too many errors in a module
+% then it stops with this message.
+unit_u_load_unit=10027_U_Cargado de $1 ($2) unidad $3
+% When you use the \var{-vu} flag, which unit is loaded from which unit is
+% shown.
+unit_u_recompile_crc_change=10028_U_Recompilando $1, checksum cambiado por $2
+unit_u_recompile_source_found_alone=10029_U_Recompilando $1, solo se encontró el código fuente
+% When you use the \var{-vu} flag, these messages tell you why the current
+% unit is recompiled.
+unit_u_recompile_staticlib_is_older=10030_U_Recompilando unidad, la lib estática es más antigua que la ppu
+% When you use the \var{-vu} flag, the compiler warns if the static library
+% of the unit are older than the unit file itself.
+unit_u_recompile_sharedlib_is_older=10031_U_Recompilando unidad, la lib compartida es más antigua que la ppu
+% When you use the \var{-vu} flag, the compiler warns if the shared library
+% of the unit are older than the unit file itself.
+unit_u_recompile_obj_and_asm_older=10032_U_Recompilando unidad, obj y asm son más antiguos que ppu
+% When you use the \var{-vu} flag, the compiler warns if the assembler or
+% object file of the unit are older than the unit file itself.
+unit_u_recompile_obj_older_than_asm=10033_U_Recompilando unidad, obj es más antiguo que asm
+% When you use the \var{-vu} flag, the compiler warns if the assembler
+% file of the unit is older than the object file of the unit.
+unit_u_parsing_interface=10034_U_Interpretando interfaz de $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% parsing the interface part of the unit
+unit_u_parsing_implementation=10035_U_Interpretando implementacion de $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% parsing the implementation part of the unit
+unit_u_second_load_unit=10036_U_Segunda carga para la unidad $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% recompiling a unit for the second time. This can happend with interdepend
+% units.
+unit_u_check_time=10037_U_Chequeo de fichero PPU $1 fecha $2
+% When you use the \var{-vu} flag, the compiler show the filename and
+% date and time of the file which a recompile depends on
+### The following two error msgs is currently disabled.
+#unit_h_cond_not_set_in_last_compile=10038_H_Conditional $1 was not set at startup in last compilation of $2
+#% when recompilation of an unit is required the compiler will check that
+#% the same conditionals are set for the recompiliation. The compiler has
+#% found a conditional that currently is defined, but was not used the last
+#% time the unit was compiled.
+#unit_h_cond_set_in_last_compile=10039_H_Conditional $1 was set at startup in last compilation of $2
+#% when recompilation of an unit is required the compiler will check that
+#% the same conditionals are set for the recompiliation. The compiler has
+#% found a conditional that was used the last time the unit was compiled, but
+#% the conditional is currently not defined.
+unit_w_cant_compile_unit_with_changed_incfile=10040_W_No se pudo recompilar la unida $1, pero se encontraron ficheros de inclusió modificados
+% A unit was found to have modified include files, but
+% some source files were not found, so recompilation is impossible.
+unit_h_source_modified=10041_H_El fichero $1 es mas moderno que la versión Release del archivo PPU $2
+% A modified source file for a unit was found that was compiled with the
+% release flag (-Ur). The unit will not implicitly be recompiled because
+% this release flag is set.
+unit_u_ppu_invalid_fpumode=10042_U_Se esta utilizando una unidad que no fue compilada con el modo de FPU correcto
+% Trying to compile code while using units which were not compiled with
+% the same floating point format mode. Either all code should be compiled
+% with FPU emulation on, or with FPU emulation off.
+unit_u_loading_interface_units=10043_U_Cargando unidades de interfaz de $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% loading the units defined in the interface part of the unit.
+unit_u_loading_implementation_units=10044_U_Cargando unidades de implementación de $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% loading the units defined in the implementation part of the unit.
+unit_u_interface_crc_changed=10045_U_CRC de la interfaz de la unidad $1 cambiado
+% When you use the \var{-vu} flag, the compiler warns that it the
+% CRC calculated for the interface has been changed after the implementation
+% has been parsed.
+unit_u_implementation_crc_changed=10046_U_CRC de la implementacion de la unidad $1 cambiado
+% When you use the \var{-vu} flag, the compiler warns that it the
+% CRC calculated has been changed after the implementation
+% has been parsed.
+unit_u_finished_compiling=10047_U_Finalizando compilado de la unidad $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has finished compiling the unit.
+unit_u_add_depend_to=10048_U_Añadida dependencia de $1 a $2
+% When you use the \var{-vu} flag, the compiler warns that it
+% has added a dependency between the two units.
+unit_u_no_reload_is_caller=10049_U_No hay recarga, es llamada de: $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has will not reload the unit because it is the unit that wants
+% to load this unit
+unit_u_no_reload_in_second_compile=10050_U_No hay recarga, ya se esta en la segunda compilación de: $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has will not reload the unit because it is already in a second recompile
+unit_u_flag_for_reload=10051_U_Marcado para recarga: $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has to reload the unit
+unit_u_forced_reload=10052_U_Recarga forzada
+% When you use the \var{-vu} flag, the compiler warns that it
+% has is reloading the unit because it was required
+unit_u_previous_state=10053_U_Estado anterior de $1: $2
+% When you use the \var{-vu} flag, the compiler shows the
+% previous state of the unit
+unit_u_second_compile_unit=10054_U_Ya se está compilando $1, estableciendo segunda compilación
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% recompiling a unit for the second time. This can happend with interdepend
+% units.
+unit_u_loading_unit=10055_U_Cargando unidad $1
+% When you use the \var{-vu} flag, the compiler warns that it starts
+% loading the unit.
+unit_u_finished_loading_unit=10056_U_Carga de la unidad $1 completada
+% When you use the \var{-vu} flag, the compiler warns that it finished
+% loading the unit.
+unit_u_registering_new_unit=10057_U_Registrando nueva unidad $1
+% When you use the \var{-vu} flag, the compiler warns that it has
+% found a new unit and registers it in the internal lists.
+unit_u_reresolving_unit=10058_U_Re-resolviendo unidad $1
+% When you use the \var{-vu} flag, the compiler warns that it
+% has to recalculate the internal data of the unit
+unit_u_skipping_reresolving_unit=10059_U_Saltando re-resolución de $1, aún se estan cargando las unidades utilizadas
+% When you use the \var{-vu} flag, the compiler warns that it
+% skips to recalculate the internal data of the unit because there
+% is no data to recalculate
+% \end{description}
+# EndOfTeX
+
+#
+# Options
+#
+# 11039 is the last used one
+#
+option_usage=11000_O_$1 [opciones] <fichero_entrada> [opciones]
+# BeginOfTeX
+%
+% \section{Command-line handling errors}
+% This section lists errors that occur when the compiler is processing the
+% command line or handling the configuration files.
+% \begin{description}
+option_only_one_source_support=11001_W_Solo es soportado un fichero fuente
+% You can specify only one source file on the command line. The first
+% one will be compiled, others will be ignored. This may indicate that
+% you forgot a \var{'-'} sign.
+option_def_only_for_os2=11002_W_Fichero DEF solo puede ser creado para OS/2
+% This option can only be specified when you're compiling for OS/2
+option_no_nested_response_file=11003_E_Ficheros de respuesta anidados no son soportados
+% you cannot nest response files with the \var{@file} command-line option.
+option_no_source_found=11004_F_No hay fichero fuente en la línea de comandos
+% The compiler expects a source file name on the command line.
+option_no_option_found=11005_N_No hay opciones en el archivo de configuración $1
+% The compiler didn't find any option in that config file.
+option_illegal_para=11006_E_Parámetro incorrecto: $1
+% You specified an unknown option.
+option_help_pages_para=11007_H_-? escribe las páginas de ayuda
+% When an unknown option is given, this message is diplayed.
+option_too_many_cfg_files=11008_F_Demasiados ficheros de configuración anidados
+% You can only nest up to 16 config files.
+option_unable_open_file=11009_F_Imposible abrir fichero $1
+% The option file cannot be found.
+option_reading_further_from=11010_D_Leyendo opciones adicionales de $1
+% Displayed when you have notes turned on, and the compiler switches
+% to another options file.
+option_target_is_already_set=11011_W_Destino está ya puesto a: $1
+% Displayed if more than one \var{-T} option is specified.
+option_no_shared_lib_under_dos=11012_W_Librerías compartidas no soportadas en la plataforma DOS, regresando a estáticas
+% If you specify \var{-CD} for the \dos platform, this message is displayed.
+% The compiler supports only static libraries under \dos
+option_too_many_ifdef=11013_F_demasiados IF(N)DEFs
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_too_many_endif=11014_F_demasiados ENDIFs
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_too_less_endif=11015_F_condicional abierto al final del fichero
+% the \var{\#IF(N)DEF} statements in the options file are not balanced with
+% the \var{\#ENDIF} statements.
+option_no_debug_support=11016_W_La generación de información de depuración no es soportada por este ejecutable
+% It is possible to have a compiler executable that doesn't support
+% the generation of debugging info. If you use such an executable with the
+% \var{-g} switch, this warning will be displayed.
+option_no_debug_support_recompile_fpc=11017_H_Prueba recompilando con -dGDB
+% It is possible to have a compiler executable that doesn't support
+% the generation of debugging info. If you use such an executable with the
+% \var{-g} switch, this warning will be displayed.
+option_obsolete_switch=11018_E_Estas usando el conmutador obsoleto $1
+% this warns you when you use a switch that is not needed/supported anymore.
+% It is recommended that you remove the switch to overcome problems in the
+% future, when the switch meaning may change.
+option_obsolete_switch_use_new=11019_E_Estás usando el conmutador obsoleto $1, porfavor usa $2
+% this warns you when you use a switch that is not supported anymore. You
+% must now use the second switch instead.
+% It is recommended that you change the switch to overcome problems in the
+% future, when the switch meaning may change.
+option_switch_bin_to_src_assembler=11020_N_Cambiando a ensamblador de escritura de código fuente por defecto
+% this notifies you that the assembler has been changed because you used the
+% -a switch which can't be used with a binary assembler writer.
+option_incompatible_asm=11021_W_La salida de ensamblador "$1" no es compatible con "$2"
+option_asm_forced=11022_W_Forzado el uso de ensamblador "$1"
+% The assembler output selected can not generate
+% object files with the correct format. Therefore, the
+% default assembler for this target is used instead.
+option_using_file=11026_T_Leyendo opciones del fichero $1
+% Options are also read from this file
+option_using_env=11027_T_Leyendo opciones del entorno $1
+% Options are also read from this environment string
+option_handling_option=11028_D_Procesando pción "$1"
+% Debug info that an option is found and will be handled
+option_help_press_enter=11029__*** presione retorno ***
+option_start_reading_configfile=11030_H_Inicio de lectura del archivo de configuración $1
+% Starting of config file parsing.
+option_end_reading_configfile=11031_H_Fin de lectura del archivo de configuración $1
+% End of config file parsing.
+option_interpreting_option=11032_D_Interpretando opción "$1"
+option_interpreting_firstpass_option=11036_D_Interpretando primera pasada de la opción "$1"
+option_interpreting_file_option=11033_D_Interpretando opción de archivo "$1"
+option_read_config_file=11034_D_Leyendo archivo de configuración "$1"
+option_found_file=11035_D_encontrado nombre del archivo fuente "$1"
+% Additional infos about options, displayed
+% when you have debug option turned on.
+option_code_page_not_available=11039_E_Código de página desconocido
+%\end{description}
+# EndOfTeX
+
+#
+# Logo (option -l)
+#
+option_logo=11023_[
+Free Pascal Compiler version $FPCFULLVERSION [$FPCDATE] for $FPCCPU
+Copyright (c) 1993-2011 by Florian Klaempfl
+]
+
+#
+# Info (option -i)
+#
+option_info=11024_[
+Free Pascal Compiler versión $FPCVERSION
+
+Fecha del Compilador : $FPCDATE
+CPU de destino : $FPCCPU
+
+Plataformas soportadas:
+ $OSTARGETS
+
+Sets de instrucciones de la CPU soportados:
+ $INSTRUCTIONSETS
+
+Sets de instrucciones de la FPU soportados:
+ $FPUINSTRUCTIONSETS
+
+Este programa esta bajo la licencia GNU General Public Licence
+Para mas informació lea COPYING.FPC
+
+Para informar de errores, sugerencias, etc:
+ http://bugs.freepascal.org
+o
+ bugs@freepascal.org
+]
+
+#
+# Help pages (option -? and -h)
+#
+# The first character on the line indicates who will display this
+# line, the current possibilities are :
+# * = every target
+# 3 = 80x86 targets
+# 6 = 680x0 targets
+# e = in extended debug mode only
+# P = PowerPC targets
+# S = Sparc targets
+# V = Virtual machine targets
+# The second character also indicates who will display this line,
+# (if the above character was TRUE) the current possibilities are :
+# * = everyone
+# g = with GDB info supported by the compiler
+# O = OS/2
+# L = UNIX systems
+# The third character represents the indentation level.
+#
+option_help_pages=11025_[
+**0*_ponga + tras un conmutador booleano para activarlo, - para desactivarlo
+**1a_el compilador no borra los ficheros de ensamblador generados
+**2al_incluir los números de línea del codigo fuente en el archivo ensamblador
+**2an_incluir la informacion de nodos en el archivo ensamblador generado
+*L2ap_usar tuberías (pipes) en lugar de crear archivos de ensamblado temporales
+**2ar_incluir reserva y liberació de registros en el archivo ensamblador
+**2at_incluir informacion de reserva y liberación temporales en el archivo ensamblador
+**1A<x>_formato de salida:
+**2Adefault_usar ensamblador por defecto
+3*2Aas_ensamblar usando GNU AS
+3*2Anasmcoff_coff (Go32v2) usando Nasm
+3*2Anasmelf_elf32 (Linux) usando Nasm
+3*2Anasmwin32_objeto Win32 usando Nasm
+3*2Anasmwdosx_objeto Win32/WDOSX usando Nasm
+3*2Awasm_fichero obj usando Wasm (Watcom)
+3*2Anasmobj_fichero obj usando Nasm
+3*2Amasm_fichero obj usando Masm (Microsoft)
+3*2Atasm_fichero obj usando Tasm (Borland)
+3*2Aelf_elf32 (Linux) usando escritor interno
+3*2Acoff_coff (Go32v2) usando escritor interno
+3*2Apecoff_pecoff (Win32) usando escritor interno
+4*2Aas_ensamblar usando GNU AS
+6*2Aas_archivo o de Unix usando GNU AS
+6*2Agas_ensamblador GNU Motorola
+6*2Amit_Sintaxis MIT (GAS antiguo)
+6*2Amot_Ensamblador Motorola estándar
+A*2Aas_ensamblar usando GNU AS
+P*2Aas_ensamblar usando GNU AS
+S*2Aas_ensamblar usando GNU AS
+**1b_generar informacion de navegado
+**2bl_generar informació de símbolos locales
+**1B_construir(build) todos los modulos
+**1C<x>_opciones de generado de código:
+**2Cc<x>_cambiar la convencion de llamada por defecto a <x>
+**2CD_crear adicionalmente una librería dinámica (no soportado)
+**2Ce_Compilar con opcodes de punto flotante emulados
+**2Cf<x>_Cambiar el set de instrucciones de la FPU usado, fpc -i para posibles valores<x>
+**2Cg_Generar código PIC
+**2Ch<n>_<n> bytes heap (entre 1023 y 67107840)
+**2Ci_Comprobación de E/S
+**2Cn_omitir etapa de enlazado
+**2Co_comprobar desbordamiento en operaciones de enteros
+**2Cp<x>_Cambiar el set de instrucciones usado, fpc -i para posibles valores
+**2Cr_comprobación de rango
+**2CR_verificar validez de objetos de llamada
+**2Cs<n>_definir el tamaño de la pila a <n>
+**2Ct_comprobación de pila
+**2CX_crear adicionalmente una librerí con enlazado inteligente
+**1d<x>_define el símbol <x>
+**1D_generar fichero DEF
+**2Dd<x>_establece la descripción a <x>
+**2Dv<x>_establece la version de la DLL a <x>
+*O2Dw_Aplicación PM
+**1e<x>_establecer ruta al ejecutable
+**1E_igual que -Cn
+**1F<x>_establecer ficheros y rutas:
+**2Fa<x>[,y]_para hacer que el programa cargue las unidades <x> e [y] antes de procesar su uses
+**2Fc<x>_establece el código de pagina de la entrada a <x>
+**2FD<x>_establece la ruta donde buscar las utilidades del compilador
+**2Fe<x>_redirige la salida de errores a <x>
+**2FE<x>_establece la ruta de destino de exe/unidades a <x>
+**2Fi<x>_añade <x> a las rutas de inclusión
+**2Fl<x>_añade <x> a las rutas de librerías
+**2FL<x>_usa <x> como enlazador dinámico
+**2Fo<x>_añade <x> a las rutas de objetos
+**2Fr<x>_load error message file <x>
+**2Fu<x>_adds <x> a las rutas de unidades
+**2FU<x>_establece la ruta de salida de unidades a <x>, reemplaza -FE anteriores
+*g1g_generar información de depurado:
+*g2gc_generar comprobación de punteros
+*g2gd_usar dbx
+*g2gg_usar gsym
+*g2gh_usar unidad de trazado de memoria (para depurar pérdidas de memoria)
+*g2gl_usar informacion de líneas de las unidades para la traza de ejecución (backtrace)
+*g2gv_genera programas trazables con valgrind
+*g2gw_generar información de depurado dwarf
+**1i_información
+**2iD_devuelve la fecha del compilador
+**2iV_devuelve la versión del compilador
+**2iSO_devuelve el SO del compilador
+**2iSP_devuelve el procesador del compilador
+**2iTO_devuelve el SO de destino
+**2iTP_devuelve el procesador de destino
+**1I<x>_añade <x> a las rutas de iclusión
+**1k<x>_Pasar <x> al enlazador
+**1l_mostrar logo
+**1M<x>_establecer modo del lenguaje a <x>
+**2Mfpc_dialecto de free pascal(default)
+**2Mobjfpc_activar algunas extensiones de Delphi 2
+**2Mdelphi_tratar de ser compatible con Delphi
+**2Mtp_tratar de ser compatible con TP/BP 7.0
+**2Mgpc_tratar de ser compatible con gpc
+**2Mmacpas_tratar de ser compatible con dialectos de macintosh pascal
+**1n_no leer la configuración por defecto
+**1o<x>_cambiar el nombre del ejecutable producido a <x>
+**1O<x>_optimizaciones:
+3*2Og_generar código más pequeño
+3*2OG_generar código más rápido (defecto)
+**2Or_mantener algunas variables en registros
+3*2Ou_activar optimizaciones inseguras (ver docs)
+3*2O1_optimizaciones nivel 1 (optimizaciones rápidas)
+3*2O2_optimizaciones nivel 2 (-O1 + optimizaciones más lentas)
+3*2O3_optimizaciones nivel 3 (-O2 repetidamente, max 5 veces)
+3*2Op<x>_procesador de destino:
+3*3Op1_establecer procesador de destino a 386/486
+3*3Op2_establecer procesador de destino a Pentium/PentiumMMX (tm)
+3*3Op3_establecer procesador de destino a PPro/PII/c6x86/K6 (tm)
+6*2Og_generar código más pequeño
+6*2OG_generatr código más rápido (defecto)
+6*2Ox_optimizar al máximo (AUN CON ERRORES!!!)
+6*2O0_establecer procesador de destino a MC68000
+6*2O2_establecer procesador de destino a MC68020+ (defecto)
+**1pg_generar código de perfilado gprof (define FPC_PROFILE)
+**1R<x>_estilo de lectura de ensamblador:
+**2Rdefault_usar ensamblador por defecto
+3*2Ratt_leer ensamblador estilo AT&T
+3*2Rintel_leer ensamblador estilo Intel
+6*2RMOT_leer ensamblador estilo motorola
+**1S<x>_opciones de sintaxis:
+**2S2_igual que -Mobjfpc
+**2Sc_soportar operadores estilo C (*=,+=,/= and -=)
+**2Sa_incluir código de aserción.
+**2Sd_igual que -Mdelphi
+**2Se<x>_opciones de error. <x> es una combinación de los siguientes:
+**3*_<n> : detener el compilador tras <n> errores (por defecto 1)
+**3*_w : detener también tras avisos
+**3*_n : detener también tras notas
+**3*_h : detener también tras consejos
+**2Sg_permitir LABEL y GOTO
+**2Sh_Usar cadenas largas (ansistrings)
+**2Si_soportar INLINE estilo C++
+**2SI<x>_establecer estilo de interfaz a <x>
+**3SIcom_interfaces compatibles COM (defecto)
+**3SIcorba_interfaces compatibles CORBA
+**2Sm_soportar macros tipo C (global)
+**2So_igual que -Mtp
+**2Sp_igual que -Mgpc
+**2Ss_el nombre del constructor debe ser init (el destructor debe ser done)
+**1s_no llamar al ensamblador ni enlazador
+**2sh_Generar script para enlazar en host
+**2st_Generar script para enlazar en destino
+**2sr_Saltar fase de reserva de registros (usar con -alr)
+**1T<x>_Sistema operativo de destino:
+3*2Temx_OS/2 usando EMX (incluyendo extensor EMX/RSX)
+3*2Tfreebsd_FreeBSD
+3*2Tgo32v2_Version 2 de DJ Delorie DOS extender
+3*2Tlinux_Linux
+3*2Tnetbsd_NetBSD
+3*2Tnetware_Novell Netware Module (clib)
+3*2Tnetwlibc_Novell Netware Module (libc)
+3*2Topenbsd_OpenBSD
+3*2Tos2_OS/2 / eComStation
+3*2Tsunos_SunOS/Solaris
+3*2Twatcom_extensor DOS compatible Watcom
+3*2Twdosx_extensor WDOSX DOS
+3*2Twin32_Windows 32 Bit
+4*2Tlinux_Linux
+6*2Tamiga_Commodore Amiga
+6*2Tatari_Atari ST/STe/TT
+6*2Tlinux_Linux-68k
+6*2Tmacos_Macintosh m68k (no soportado)
+6*2Tpalmos_PalmOS
+A*2Tlinux_Linux
+P*2Tdarwin_Darwin y MacOS X en PowerPC
+P*2Tlinux_Linux en PowerPC
+P*2Tmacos_MacOS (clásico) en PowerPC
+P*2Tmorphos_MorphOS
+S*2Tlinux_Linux
+**1u<x>_elimina la definición del símbolo <x>
+**1U_opciones de unidad:
+**2Un_no comprobar el nombre de la unidad
+**2Ur_generar unidades para distribución (release)
+**2Us_compilar la unidad System
+**1v<x>_Mostrar detalles. <x> es una combinación de las siguientes letras:
+**2*_e : Mostrar errores (defecto) 0 : No mostrar nada (excepto errores)
+**2*_w : Mostrar avisos u : Mostrar info. de la unidad
+**2*_n : Mostrar notas t : Mostrar archivos usados / intentados
+**2*_h : Mostrar consejos c : Mostrar condicionales
+**2*_i : Mostrar info. general d : Mostrar info. de depurado
+**2*_l : Mostrar num de lineas r : Modo compatible con Rhide/GCC
+**2*_a : Mostrar todo x : Info. del ejecutable (Win32 solo)
+**2*_v : escribe fpcdebug.txt con p : Escribir el árbol de parser en tree.log
+**2*_ mucha informacón de depurado
+3*1W<x>_opciones de Win32 o similares
+3*2WB<x>_Establece la dirección hex de base a <x>
+3*2WC_Especifica que la aplicación es de consola
+3*2WD_Usa DEFFILE para exportar funciones de la DLL o EXE
+3*2WF_Especifica aplicación de pantalla completa (OS/2 sólo)
+3*2WG_Especifica que la aplicación es para entorno gráfico
+3*2WN_No generar código de reubicación (necesario para depurar)
+3*2WR_Generar código de reubicación
+P*2WC_Especifica aplicación de colnsola (MacOS sólo)
+P*2WG_Especifica aplicación gráfica (MacOS sólo)
+P*2WT_Especifica aplicación de tipo herramienta (herramienta MPW, MacOS sólo)
+**1X_opciones de ejecutable:
+**2Xc_pasar --shared al enlazador (Unix sólo)
+**2Xd_no utilizar la ruta de librería por defecto (necesario para compilación cruzada)
+**2XD_tratar de enlazar dinámicamente (define FPC_LINK_DYNAMIC)
+**2XP<x>_pone <x> delante de los nombres de binutils
+**2Xr<x>_establece la ruta de librerías a <x> (necesario para compilación cruzada)
+**2Xs_eliminar todos los símbolos del ejecutable
+**2XS_tratar de enlazar estáticamente (defecto) (define FPC_LINK_STATIC)
+**2Xt_enlazar con librerias estáticas (-static es pasado al enlazador)
+**2XX_tratar de enlazar inteligentemente (define FPC_LINK_SMART)
+**1*_
+**1?_muestra esta ayuda
+**1h_muestra esta ayuda sin esperas
+]
+
+#
+# The End...
diff --git a/closures/compiler/msgidx.inc b/closures/compiler/msgidx.inc
new file mode 100644
index 0000000000..f83c84d146
--- /dev/null
+++ b/closures/compiler/msgidx.inc
@@ -0,0 +1,926 @@
+const
+ general_t_compilername=01000;
+ general_d_sourceos=01001;
+ general_i_targetos=01002;
+ general_t_exepath=01003;
+ general_t_unitpath=01004;
+ general_t_includepath=01005;
+ general_t_librarypath=01006;
+ general_t_objectpath=01007;
+ general_i_abslines_compiled=01008;
+ general_f_no_memory_left=01009;
+ general_i_writingresourcefile=01010;
+ general_e_errorwritingresourcefile=01011;
+ general_i_fatal=01012;
+ general_i_error=01013;
+ general_i_warning=01014;
+ general_i_note=01015;
+ general_i_hint=01016;
+ general_e_path_does_not_exist=01017;
+ general_f_compilation_aborted=01018;
+ general_text_bytes_code=01019;
+ general_text_bytes_data=01020;
+ general_i_number_of_warnings=01021;
+ general_i_number_of_hints=01022;
+ general_i_number_of_notes=01023;
+ general_f_ioerror=01024;
+ general_f_oserror=01025;
+ scan_f_end_of_file=02000;
+ scan_f_string_exceeds_line=02001;
+ scan_f_illegal_char=02002;
+ scan_f_syn_expected=02003;
+ scan_t_start_include_file=02004;
+ scan_w_comment_level=02005;
+ scan_n_ignored_switch=02008;
+ scan_w_illegal_switch=02009;
+ scan_w_switch_is_global=02010;
+ scan_e_illegal_char_const=02011;
+ scan_f_cannot_open_input=02012;
+ scan_f_cannot_open_includefile=02013;
+ scan_e_illegal_pack_records=02015;
+ scan_e_illegal_pack_enum=02016;
+ scan_e_endif_expected=02017;
+ scan_e_preproc_syntax_error=02018;
+ scan_e_error_in_preproc_expr=02019;
+ scan_w_macro_cut_after_255_chars=02020;
+ scan_e_endif_without_if=02021;
+ scan_f_user_defined=02022;
+ scan_e_user_defined=02023;
+ scan_w_user_defined=02024;
+ scan_n_user_defined=02025;
+ scan_h_user_defined=02026;
+ scan_i_user_defined=02027;
+ scan_e_keyword_cant_be_a_macro=02028;
+ scan_f_macro_buffer_overflow=02029;
+ scan_w_macro_too_deep=02030;
+ scan_w_wrong_styled_switch=02031;
+ scan_d_handling_switch=02032;
+ scan_c_endif_found=02033;
+ scan_c_ifdef_found=02034;
+ scan_c_ifopt_found=02035;
+ scan_c_if_found=02036;
+ scan_c_ifndef_found=02037;
+ scan_c_else_found=02038;
+ scan_c_skipping_until=02039;
+ scan_i_press_enter=02040;
+ scan_w_unsupported_switch=02041;
+ scan_w_illegal_directive=02042;
+ scan_t_back_in=02043;
+ scan_w_unsupported_app_type=02044;
+ scan_w_app_type_not_support=02045;
+ scan_w_description_not_support=02046;
+ scan_n_version_not_support=02047;
+ scan_n_only_exe_version=02048;
+ scan_w_wrong_version_ignored=02049;
+ scan_e_illegal_asmmode_specifier=02050;
+ scan_w_no_asm_reader_switch_inside_asm=02051;
+ scan_e_wrong_switch_toggle=02052;
+ scan_e_resourcefiles_not_supported=02053;
+ scan_w_include_env_not_found=02054;
+ scan_e_invalid_maxfpureg_value=02055;
+ scan_w_only_one_resourcefile_supported=02056;
+ scan_w_macro_support_turned_off=02057;
+ scan_e_invalid_interface_type=02058;
+ scan_w_appid_not_support=02059;
+ scan_w_appname_not_support=02060;
+ scan_e_string_exceeds_255_chars=02061;
+ scan_f_include_deep_ten=02062;
+ scan_e_too_many_push=02063;
+ scan_e_too_many_pop=02064;
+ scan_e_error_macro_lacks_value=02065;
+ scan_e_wrong_switch_toggle_default=02066;
+ scan_e_mode_switch_not_allowed=02067;
+ scan_e_error_macro_undefined=02068;
+ scan_e_utf8_bigger_than_65535=02069;
+ scan_e_utf8_malformed=02070;
+ scan_c_switching_to_utf8=02071;
+ scan_e_compile_time_typeerror=02072;
+ scan_n_app_type_not_support=02073;
+ scan_e_illegal_optimization_specifier=02074;
+ scan_w_setpeflags_not_support=02075;
+ scan_w_imagebase_not_support=02076;
+ scan_w_minstacksize_not_support=02077;
+ scan_w_maxstacksize_not_support=02078;
+ scanner_e_illegal_warn_state=02079;
+ scan_e_only_packset=02080;
+ scan_w_pic_ignored=02081;
+ scan_w_unsupported_switch_by_target=02082;
+ scan_w_frameworks_darwin_only=02084;
+ scan_e_illegal_minfpconstprec=02085;
+ scan_w_multiple_main_name_overrides=02086;
+ scanner_w_illegal_warn_identifier=02087;
+ scanner_e_illegal_alignment_directive=02088;
+ parser_e_syntax_error=03000;
+ parser_e_dont_nest_interrupt=03004;
+ parser_w_proc_directive_ignored=03005;
+ parser_e_no_overload_for_all_procs=03006;
+ parser_e_export_name_double=03008;
+ parser_e_export_ordinal_double=03009;
+ parser_e_export_invalid_index=03010;
+ parser_w_parser_reloc_no_debug=03011;
+ parser_w_parser_win32_debug_needs_WN=03012;
+ parser_e_constructorname_must_be_init=03013;
+ parser_e_destructorname_must_be_done=03014;
+ parser_e_proc_inline_not_supported=03016;
+ parser_w_constructor_should_be_public=03018;
+ parser_w_destructor_should_be_public=03019;
+ parser_n_only_one_destructor=03020;
+ parser_e_no_local_objects=03021;
+ parser_f_no_anonym_objects=03022;
+ parser_n_object_has_no_vmt=03023;
+ parser_e_illegal_parameter_list=03024;
+ parser_e_wrong_parameter_size=03026;
+ parser_e_overloaded_no_procedure=03027;
+ parser_e_overloaded_have_same_parameters=03028;
+ parser_e_header_dont_match_forward=03029;
+ parser_e_header_different_var_names=03030;
+ parser_n_duplicate_enum=03031;
+ parser_e_no_with_for_variable_in_other_segments=03033;
+ parser_e_too_much_lexlevel=03034;
+ parser_e_range_check_error=03035;
+ parser_w_range_check_error=03036;
+ parser_e_double_caselabel=03037;
+ parser_e_case_lower_less_than_upper_bound=03038;
+ parser_e_type_const_not_possible=03039;
+ parser_e_no_overloaded_procvars=03040;
+ parser_e_invalid_string_size=03041;
+ parser_w_use_extended_syntax_for_objects=03042;
+ parser_w_no_new_dispose_on_void_pointers=03043;
+ parser_e_no_new_dispose_on_void_pointers=03044;
+ parser_e_class_id_expected=03045;
+ parser_e_no_type_not_allowed_here=03046;
+ parser_e_methode_id_expected=03047;
+ parser_e_header_dont_match_any_member=03048;
+ parser_d_procedure_start=03049;
+ parser_e_error_in_real=03050;
+ parser_e_fail_only_in_constructor=03051;
+ parser_e_no_paras_for_destructor=03052;
+ parser_e_only_class_members_via_class_ref=03053;
+ parser_e_only_class_members=03054;
+ parser_e_case_mismatch=03055;
+ parser_e_illegal_symbol_exported=03056;
+ parser_w_should_use_override=03057;
+ parser_e_nothing_to_be_overridden=03058;
+ parser_e_no_procedure_to_access_property=03059;
+ parser_w_stored_not_implemented=03060;
+ parser_e_ill_property_access_sym=03061;
+ parser_e_cant_access_protected_member=03062;
+ parser_e_cant_access_private_member=03063;
+ parser_e_overridden_methods_not_same_ret=03066;
+ parser_e_dont_nest_export=03067;
+ parser_e_methods_dont_be_export=03068;
+ parser_e_call_by_ref_without_typeconv=03069;
+ parser_e_no_super_class=03070;
+ parser_e_self_not_in_method=03071;
+ parser_e_generic_methods_only_in_methods=03072;
+ parser_e_illegal_colon_qualifier=03073;
+ parser_e_illegal_set_expr=03074;
+ parser_e_pointer_to_class_expected=03075;
+ parser_e_expr_have_to_be_constructor_call=03076;
+ parser_e_expr_have_to_be_destructor_call=03077;
+ parser_e_invalid_record_const=03078;
+ parser_e_false_with_expr=03079;
+ parser_e_void_function=03080;
+ parser_e_only_methods_allowed=03081;
+ parser_e_operator_not_overloaded=03082;
+ parser_e_no_such_assignment=03083;
+ parser_e_overload_impossible=03084;
+ parser_e_no_reraise_possible=03085;
+ parser_e_no_new_or_dispose_for_classes=03086;
+ parser_e_procedure_overloading_is_off=03088;
+ parser_e_overload_operator_failed=03089;
+ parser_e_comparative_operator_return_boolean=03090;
+ parser_e_only_virtual_methods_abstract=03091;
+ parser_f_unsupported_feature=03092;
+ parser_e_mix_of_classes_and_objects=03093;
+ parser_w_unknown_proc_directive_ignored=03094;
+ parser_e_absolute_only_one_var=03095;
+ parser_e_absolute_only_to_var_or_const=03096;
+ parser_e_initialized_only_one_var=03097;
+ parser_e_abstract_no_definition=03098;
+ parser_e_overloaded_must_be_all_global=03099;
+ parser_w_virtual_without_constructor=03100;
+ parser_c_macro_defined=03101;
+ parser_c_macro_undefined=03102;
+ parser_c_macro_set_to=03103;
+ parser_i_compiling=03104;
+ parser_u_parsing_interface=03105;
+ parser_u_parsing_implementation=03106;
+ parser_d_compiling_second_time=03107;
+ parser_e_no_property_found_to_override=03109;
+ parser_e_only_one_default_property=03110;
+ parser_e_property_need_paras=03111;
+ parser_e_constructor_cannot_be_not_virtual=03112;
+ parser_e_no_default_property_available=03113;
+ parser_e_cant_have_published=03114;
+ parser_e_forward_declaration_must_be_resolved=03115;
+ parser_e_no_local_operator=03116;
+ parser_e_proc_dir_not_allowed_in_interface=03117;
+ parser_e_proc_dir_not_allowed_in_implementation=03118;
+ parser_e_proc_dir_not_allowed_in_procvar=03119;
+ parser_e_function_already_declared_public_forward=03120;
+ parser_e_not_external_and_export=03121;
+ parser_w_not_supported_for_inline=03123;
+ parser_w_inlining_disabled=03124;
+ parser_i_writing_browser_log=03125;
+ parser_h_maybe_deref_caret_missing=03126;
+ parser_f_assembler_reader_not_supported=03127;
+ parser_e_proc_dir_conflict=03128;
+ parser_e_call_convention_dont_match_forward=03129;
+ parser_e_property_cant_have_a_default_value=03131;
+ parser_e_property_default_value_must_const=03132;
+ parser_e_cant_publish_that=03133;
+ parser_e_cant_publish_that_property=03134;
+ parser_e_empty_import_name=03136;
+ parser_e_division_by_zero=03138;
+ parser_e_invalid_float_operation=03139;
+ parser_e_array_lower_less_than_upper_bound=03140;
+ parser_w_string_too_long=03141;
+ parser_e_string_larger_array=03142;
+ parser_e_ill_msg_expr=03143;
+ parser_e_ill_msg_param=03144;
+ parser_e_duplicate_message_label=03145;
+ parser_e_self_in_non_message_handler=03146;
+ parser_e_threadvars_only_sg=03147;
+ parser_f_direct_assembler_not_allowed=03148;
+ parser_w_no_objpas_use_mode=03149;
+ parser_e_no_object_override=03150;
+ parser_e_cant_use_inittable_here=03151;
+ parser_e_resourcestring_only_sg=03152;
+ parser_e_exit_with_argument_not__possible=03153;
+ parser_e_stored_property_must_be_boolean=03154;
+ parser_e_ill_property_storage_sym=03155;
+ parser_e_only_publishable_classes_can_be_published=03156;
+ parser_e_proc_directive_expected=03157;
+ parser_e_invalid_property_index_value=03158;
+ parser_e_procname_to_short_for_export=03159;
+ parser_e_dlltool_unit_var_problem=03160;
+ parser_e_dlltool_unit_var_problem2=03161;
+ parser_f_need_objfpc_or_delphi_mode=03162;
+ parser_e_no_export_with_index_for_target=03163;
+ parser_e_no_export_of_variables_for_target=03164;
+ parser_e_improper_guid_syntax=03165;
+ parser_w_interface_mapping_notfound=03168;
+ parser_e_interface_id_expected=03169;
+ parser_e_type_cant_be_used_in_array_index=03170;
+ parser_e_no_con_des_in_interfaces=03171;
+ parser_e_no_access_specifier_in_interfaces=03172;
+ parser_e_no_vars_in_interfaces=03173;
+ parser_e_no_local_proc_external=03174;
+ parser_w_skipped_fields_before=03175;
+ parser_e_skipped_fields_before=03176;
+ parser_w_skipped_fields_after=03177;
+ parser_e_varargs_need_cdecl_and_external=03178;
+ parser_e_self_call_by_value=03179;
+ parser_e_interface_has_no_guid=03180;
+ parser_e_illegal_field_or_method=03181;
+ parser_w_proc_overriding_calling=03182;
+ parser_e_no_procvarobj_const=03183;
+ parser_e_default_value_only_one_para=03184;
+ parser_e_default_value_expected_for_para=03185;
+ parser_w_unsupported_feature=03186;
+ parser_h_c_arrays_are_references=03187;
+ parser_e_C_array_of_const_must_be_last=03188;
+ parser_h_type_redef=03189;
+ parser_w_cdecl_has_no_high=03190;
+ parser_w_cdecl_no_openstring=03191;
+ parser_e_initialized_not_for_threadvar=03192;
+ parser_e_msg_only_for_classes=03193;
+ parser_e_procedure_or_function_expected=03194;
+ parser_e_illegal_calling_convention=03195;
+ parser_e_no_object_reintroduce=03196;
+ parser_e_paraloc_only_one_para=03197;
+ parser_e_paraloc_all_paras=03198;
+ parser_e_illegal_explicit_paraloc=03199;
+ parser_e_32bitint_or_pointer_variable_expected=03200;
+ parser_e_goto_outside_proc=03201;
+ parser_f_too_complex_proc=03202;
+ parser_e_illegal_expression=03203;
+ parser_e_invalid_integer=03204;
+ parser_e_invalid_qualifier=03205;
+ parser_e_upper_lower_than_lower=03206;
+ parser_e_macpas_exit_wrong_param=03207;
+ parser_e_illegal_assignment_to_count_var=03208;
+ parser_e_no_local_var_external=03209;
+ parser_e_proc_already_external=03210;
+ parser_w_implicit_uses_of_variants_unit=03211;
+ parser_e_no_static_method_in_interfaces=03212;
+ parser_e_arithmetic_operation_overflow=03213;
+ parser_e_protected_or_private_expected=03214;
+ parser_e_illegal_slice=03215;
+ parser_e_dispinterface_cant_have_parent=03216;
+ parser_e_dispinterface_needs_a_guid=03217;
+ parser_w_overridden_methods_not_same_ret=03218;
+ parser_e_dispid_must_be_ord_const=03219;
+ parser_e_array_range_out_of_bounds=03220;
+ parser_e_packed_element_no_var_addr=03221;
+ parser_e_packed_dynamic_open_array=03222;
+ parser_e_packed_element_no_loop=03223;
+ parser_e_type_var_const_only_in_records_and_classes=03224;
+ parser_e_cant_create_generics_of_this_type=03225;
+ parser_w_no_lineinfo_use_switch=03226;
+ parser_e_no_funcret_specified=03227;
+ parser_e_special_onlygenerics=03228;
+ parser_e_no_generics_as_params=03229;
+ parser_e_type_object_constants=03230;
+ parser_e_label_outside_proc=03231;
+ parser_e_initialized_not_for_external=03233;
+ parser_e_illegal_function_result=03234;
+ parser_e_no_common_type=03235;
+ parser_e_no_generics_as_types=03236;
+ parser_w_register_list_ignored=03237;
+ parser_e_implements_must_be_class_or_interface=03238;
+ parser_e_implements_must_have_correct_type=03239;
+ parser_e_implements_must_read_specifier=03240;
+ parser_e_implements_must_not_have_write_specifier=03241;
+ parser_e_implements_must_not_have_stored_specifier=03242;
+ parser_e_implements_uses_non_implemented_interface=03243;
+ parser_e_unsupported_real=03244;
+ parser_e_class_doesnt_implement_interface=03245;
+ parser_e_class_implements_must_be_interface=03246;
+ parser_e_cant_export_var_different_name=03247;
+ parser_e_weak_external_not_supported=03248;
+ parser_e_forward_mismatch=03249;
+ parser_n_ignore_lower_visibility=03250;
+ parser_e_field_not_allowed_here=03251;
+ parser_e_no_local_para_def=03252;
+ parser_e_abstract_and_sealed_conflict=03253;
+ parser_e_sealed_descendant=03254;
+ parser_e_sealed_class_cannot_have_abstract_methods=03255;
+ parser_e_only_virtual_methods_final=03256;
+ parser_e_final_can_no_be_overridden=03257;
+ parser_e_multiple_messages=03258;
+ parser_e_invalid_enumerator_identifier=03259;
+ parser_e_enumerator_identifier_required=03260;
+ parser_e_enumerator_movenext_is_not_valid=03261;
+ parser_e_enumerator_current_is_not_valid=03262;
+ parser_e_only_one_enumerator_movenext=03263;
+ parser_e_only_one_enumerator_current=03264;
+ parser_e_for_in_loop_cannot_be_used_for_the_type=03265;
+ parser_e_objc_requires_msgstr=03266;
+ parser_e_objc_no_constructor_destructor=03267;
+ parser_e_message_string_too_long=03268;
+ parser_e_objc_message_name_too_long=03269;
+ parser_h_no_objc_parent=03270;
+ parser_e_no_objc_published=03271;
+ parser_f_need_objc=03272;
+ parser_e_must_use_override_objc=03273;
+ parser_h_should_use_override_objc=03274;
+ parser_e_objc_message_name_changed=03275;
+ parser_e_no_objc_unique=03276;
+ parser_e_no_category_as_types=03277;
+ parser_e_no_category_override=03278;
+ parser_e_must_use_reintroduce_objc=03279;
+ parser_h_should_use_reintroduce_objc=03280;
+ parser_e_implements_getter_not_default_cc=03281;
+ parser_e_no_refcounted_typed_file=03282;
+ parser_e_operator_not_overloaded_2=03283;
+ parser_e_operator_not_overloaded_3=03284;
+ parser_e_more_array_elements_expected=03285;
+ parser_e_string_const_too_long=03286;
+ parser_e_invalid_univ_para=03287;
+ parser_e_only_one_class_constructor_allowed=03288;
+ parser_e_only_one_class_destructor_allowed=03289;
+ parser_e_no_paras_for_class_constructor=03290;
+ parser_e_no_paras_for_class_destructor=03291;
+ parser_f_modeswitch_objc_required=03292;
+ parser_e_widestring_to_ansi_compile_time=03293;
+ parser_e_objc_enumerator_2_0=03294;
+ parser_e_objc_missing_enumeration_defs=03295;
+ parser_e_no_procvarnested_const=03296;
+ parser_f_no_generic_inside_generic=03297;
+ parser_e_forward_protocol_declaration_must_be_resolved=03298;
+ parser_e_no_record_published=03299;
+ parser_e_no_destructor_in_records=03300;
+ parser_e_class_methods_only_static_in_records=03301;
+ parser_e_no_constructor_in_records=03302;
+ parser_e_at_least_one_argument_must_be_of_type=03303;
+ parser_e_cant_use_type_parameters_here=03304;
+ parser_e_externals_no_section=03305;
+ parser_e_section_no_locals=03306;
+ parser_e_not_allowed_in_helper=03307;
+ parser_e_no_class_constructor_in_helpers=03308;
+ parser_e_inherited_not_in_record=03309;
+ parser_e_no_types_in_local_anonymous_records=03310;
+ parser_e_duplicate_implements_clause=03311;
+ parser_e_mapping_no_implements=03312;
+ parser_e_implements_no_mapping=03313;
+ parser_e_invalid_codepage=03314;
+ type_e_mismatch=04000;
+ type_e_incompatible_types=04001;
+ type_e_not_equal_types=04002;
+ type_e_type_id_expected=04003;
+ type_e_variable_id_expected=04004;
+ type_e_integer_expr_expected=04005;
+ type_e_boolean_expr_expected=04006;
+ type_e_ordinal_expr_expected=04007;
+ type_e_pointer_type_expected=04008;
+ type_e_class_type_expected=04009;
+ type_e_cant_eval_constant_expr=04011;
+ type_e_set_element_are_not_comp=04012;
+ type_e_set_operation_unknown=04013;
+ type_w_convert_real_2_comp=04014;
+ type_h_use_div_for_int=04015;
+ type_e_strict_var_string_violation=04016;
+ type_e_succ_and_pred_enums_with_assign_not_possible=04017;
+ type_e_cant_read_write_type=04018;
+ type_e_no_readln_writeln_for_typed_file=04019;
+ type_e_no_read_write_for_untyped_file=04020;
+ type_e_typeconflict_in_set=04021;
+ type_w_maybe_wrong_hi_lo=04022;
+ type_e_integer_or_real_expr_expected=04023;
+ type_e_wrong_type_in_array_constructor=04024;
+ type_e_wrong_parameter_type=04025;
+ type_e_no_method_and_procedure_not_compatible=04026;
+ type_e_wrong_math_argument=04027;
+ type_e_no_addr_of_constant=04028;
+ type_e_argument_cant_be_assigned=04029;
+ type_e_cannot_local_proc_to_procvar=04030;
+ type_e_no_assign_to_addr=04031;
+ type_e_no_assign_to_const=04032;
+ type_e_array_required=04033;
+ type_e_interface_type_expected=04034;
+ type_h_mixed_signed_unsigned=04035;
+ type_w_mixed_signed_unsigned2=04036;
+ type_e_typecast_wrong_size_for_assignment=04037;
+ type_e_array_index_enums_with_assign_not_possible=04038;
+ type_e_classes_not_related=04039;
+ type_w_classes_not_related=04040;
+ type_e_class_or_interface_type_expected=04041;
+ type_e_type_is_not_completly_defined=04042;
+ type_w_string_too_long=04043;
+ type_w_comparison_always_false=04044;
+ type_w_comparison_always_true=04045;
+ type_w_instance_with_abstract=04046;
+ type_h_in_range_check=04047;
+ type_w_smaller_possible_range_check=04048;
+ type_h_smaller_possible_range_check=04049;
+ type_e_cant_take_address_of_abstract_method=04050;
+ type_e_assignment_not_allowed=04051;
+ type_e_constant_expr_expected=04052;
+ type_e_operator_not_supported_for_types=04053;
+ type_e_illegal_type_conversion=04054;
+ type_h_pointer_to_longint_conv_not_portable=04055;
+ type_w_pointer_to_longint_conv_not_portable=04056;
+ type_e_cant_choose_overload_function=04057;
+ type_e_illegal_count_var=04058;
+ type_w_double_c_varargs=04059;
+ type_e_class_or_cominterface_type_expected=04060;
+ type_e_no_const_packed_array=04061;
+ type_e_got_expected_packed_array=04062;
+ type_e_got_expected_unpacked_array=04063;
+ type_e_no_packed_inittable=04064;
+ type_e_no_const_packed_record=04065;
+ type_w_untyped_arithmetic_unportable=04066;
+ type_e_cant_take_address_of_local_subroutine=04076;
+ type_e_cant_export_local=04077;
+ type_e_not_automatable=04078;
+ type_h_convert_add_operands_to_prevent_overflow=04079;
+ type_h_convert_sub_operands_to_prevent_overflow=04080;
+ type_h_convert_mul_operands_to_prevent_overflow=04081;
+ type_w_pointer_to_signed=04082;
+ type_e_interface_has_no_guid=04083;
+ type_e_invalid_objc_selector_name=04084;
+ type_e_expected_objc_method_but_got=04085;
+ type_e_expected_objc_method=04086;
+ type_e_no_type_info=04087;
+ type_e_ordinal_or_string_expr_expected=04088;
+ type_e_string_expr_expected=04089;
+ type_w_zero_to_nil=04090;
+ type_e_protocol_type_expected=04091;
+ type_e_objc_type_unsupported=04092;
+ type_e_class_or_objcclass_type_expected=04093;
+ type_e_objcclass_type_expected=04094;
+ type_w_procvar_univ_conflicting_para=04095;
+ type_e_generics_cannot_reference_itself=04096;
+ type_e_type_parameters_are_not_allowed_here=04097;
+ type_e_generic_declaration_does_not_match=04098;
+ type_e_helper_type_expected=04099;
+ type_e_record_type_expected=04100;
+ type_e_class_helper_must_extend_subclass=04101;
+ type_e_record_helper_must_extend_same_record=04102;
+ type_e_procedures_return_no_value=04103;
+ type_w_implicit_string_cast=04104;
+ type_w_implicit_string_cast_loss=04105;
+ type_w_explicit_string_cast=04106;
+ type_w_explicit_string_cast_loss=04107;
+ type_w_unicode_data_loss=04108;
+ sym_e_id_not_found=05000;
+ sym_f_internal_error_in_symtablestack=05001;
+ sym_e_duplicate_id=05002;
+ sym_h_duplicate_id_where=05003;
+ sym_e_unknown_id=05004;
+ sym_e_forward_not_resolved=05005;
+ sym_e_error_in_type_def=05007;
+ sym_e_forward_type_not_resolved=05009;
+ sym_e_only_static_in_static=05010;
+ sym_f_type_must_be_rec_or_class=05012;
+ sym_e_no_instance_of_abstract_object=05013;
+ sym_w_label_not_defined=05014;
+ sym_e_label_used_and_not_defined=05015;
+ sym_e_ill_label_decl=05016;
+ sym_e_goto_and_label_not_supported=05017;
+ sym_e_label_not_found=05018;
+ sym_e_id_is_no_label_id=05019;
+ sym_e_label_already_defined=05020;
+ sym_e_ill_type_decl_set=05021;
+ sym_e_class_forward_not_resolved=05022;
+ sym_n_unit_not_used=05023;
+ sym_h_para_identifier_not_used=05024;
+ sym_n_local_identifier_not_used=05025;
+ sym_h_para_identifier_only_set=05026;
+ sym_n_local_identifier_only_set=05027;
+ sym_h_local_symbol_not_used=05028;
+ sym_n_private_identifier_not_used=05029;
+ sym_n_private_identifier_only_set=05030;
+ sym_n_private_method_not_used=05031;
+ sym_e_set_expected=05032;
+ sym_w_function_result_not_set=05033;
+ sym_w_wrong_C_pack=05034;
+ sym_e_illegal_field=05035;
+ sym_w_uninitialized_local_variable=05036;
+ sym_w_uninitialized_variable=05037;
+ sym_e_id_no_member=05038;
+ sym_h_param_list=05039;
+ sym_e_segment_too_large=05040;
+ sym_e_no_matching_implementation_found=05042;
+ sym_w_deprecated_symbol=05043;
+ sym_w_non_portable_symbol=05044;
+ sym_w_non_implemented_symbol=05055;
+ sym_e_cant_create_unique_type=05056;
+ sym_h_uninitialized_local_variable=05057;
+ sym_h_uninitialized_variable=05058;
+ sym_w_function_result_uninitialized=05059;
+ sym_h_function_result_uninitialized=05060;
+ sym_w_identifier_only_read=05061;
+ sym_h_abstract_method_list=05062;
+ sym_w_experimental_symbol=05063;
+ sym_w_forward_not_resolved=05064;
+ sym_w_library_symbol=05065;
+ sym_w_deprecated_symbol_with_msg=05066;
+ sym_e_no_enumerator=05067;
+ sym_e_no_enumerator_move=05068;
+ sym_e_no_enumerator_current=05069;
+ sym_e_objc_para_mismatch=05070;
+ sym_n_private_type_not_used=05071;
+ sym_n_private_const_not_used=05072;
+ sym_n_private_property_not_used=05073;
+ sym_w_deprecated_unit=05074;
+ sym_w_deprecated_unit_with_msg=05075;
+ sym_w_non_portable_unit=05076;
+ sym_w_library_unit=05077;
+ sym_w_non_implemented_unit=05078;
+ sym_w_experimental_unit=05079;
+ sym_e_objc_formal_class_not_resolved=05080;
+ sym_e_interprocgoto_into_init_final_code_not_allowed=05081;
+ sym_e_external_class_name_mismatch1=05082;
+ sym_e_external_class_name_mismatch2=05083;
+ sym_w_library_overload=05084;
+ cg_e_parasize_too_big=06009;
+ cg_e_file_must_call_by_reference=06012;
+ cg_e_cant_use_far_pointer_there=06013;
+ cg_e_dont_call_exported_direct=06015;
+ cg_w_member_cd_call_from_method=06016;
+ cg_n_inefficient_code=06017;
+ cg_w_unreachable_code=06018;
+ cg_e_cant_call_abstract_method=06020;
+ cg_d_register_weight=06027;
+ cg_d_stackframe_omited=06029;
+ cg_e_unable_inline_object_methods=06031;
+ cg_e_unable_inline_procvar=06032;
+ cg_e_no_code_for_inline_stored=06033;
+ cg_e_can_access_element_zero=06035;
+ cg_e_cannot_call_cons_dest_inside_with=06037;
+ cg_e_cannot_call_message_direct=06038;
+ cg_e_goto_inout_of_exception_block=06039;
+ cg_e_control_flow_outside_finally=06040;
+ cg_w_parasize_too_big=06041;
+ cg_w_localsize_too_big=06042;
+ cg_e_localsize_too_big=06043;
+ cg_e_break_not_allowed=06044;
+ cg_e_continue_not_allowed=06045;
+ cg_f_unknown_compilerproc=06046;
+ cg_f_unknown_system_type=06047;
+ cg_h_inherited_ignored=06048;
+ cg_e_goto_label_not_found=06049;
+ cg_f_unknown_type_in_unit=06050;
+ cg_e_interprocedural_goto_only_to_outer_scope_allowed=06051;
+ cg_e_labels_cannot_defined_outside_declaration_scope=06052;
+ cg_e_goto_across_procedures_with_exceptions_not_allowed=06053;
+ cg_e_mod_only_defined_for_pos_quotient=06054;
+ asmr_d_start_reading=07000;
+ asmr_d_finish_reading=07001;
+ asmr_e_none_label_contain_at=07002;
+ asmr_e_building_record_offset=07004;
+ asmr_e_offset_without_identifier=07005;
+ asmr_e_type_without_identifier=07006;
+ asmr_e_no_local_or_para_allowed=07007;
+ asmr_e_need_offset=07008;
+ asmr_e_need_dollar=07009;
+ asmr_e_cant_have_multiple_relocatable_symbols=07010;
+ asmr_e_only_add_relocatable_symbol=07011;
+ asmr_e_invalid_constant_expression=07012;
+ asmr_e_relocatable_symbol_not_allowed=07013;
+ asmr_e_invalid_reference_syntax=07014;
+ asmr_e_local_para_unreachable=07015;
+ asmr_e_local_label_not_allowed_as_ref=07016;
+ asmr_e_wrong_base_index=07017;
+ asmr_w_possible_object_field_bug=07018;
+ asmr_e_wrong_scale_factor=07019;
+ asmr_e_multiple_index=07020;
+ asmr_e_invalid_operand_type=07021;
+ asmr_e_invalid_string_as_opcode_operand=07022;
+ asmr_w_CODE_and_DATA_not_supported=07023;
+ asmr_e_null_label_ref_not_allowed=07024;
+ asmr_e_expr_zero_divide=07025;
+ asmr_e_expr_illegal=07026;
+ asmr_e_escape_seq_ignored=07027;
+ asmr_e_invalid_symbol_ref=07028;
+ asmr_w_fwait_emu_prob=07029;
+ asmr_w_fadd_to_faddp=07030;
+ asmr_w_enter_not_supported_by_linux=07031;
+ asmr_w_calling_overload_func=07032;
+ asmr_e_unsupported_symbol_type=07033;
+ asmr_e_constant_out_of_bounds=07034;
+ asmr_e_error_converting_decimal=07035;
+ asmr_e_error_converting_octal=07036;
+ asmr_e_error_converting_binary=07037;
+ asmr_e_error_converting_hexadecimal=07038;
+ asmr_h_direct_global_to_mangled=07039;
+ asmr_w_direct_global_is_overloaded_func=07040;
+ asmr_e_cannot_use_SELF_outside_a_method=07041;
+ asmr_e_cannot_use_OLDEBP_outside_nested_procedure=07042;
+ asmr_e_void_function=07043;
+ asmr_e_SEG_not_supported=07044;
+ asmr_e_size_suffix_and_dest_dont_match=07045;
+ asmr_w_size_suffix_and_dest_dont_match=07046;
+ asmr_e_syntax_error=07047;
+ asmr_e_invalid_opcode_and_operand=07048;
+ asmr_e_syn_operand=07049;
+ asmr_e_syn_constant=07050;
+ asmr_e_invalid_string_expression=07051;
+ asmr_w_const32bit_for_address=07052;
+ asmr_e_unknown_opcode=07053;
+ asmr_e_invalid_or_missing_opcode=07054;
+ asmr_e_invalid_prefix_and_opcode=07055;
+ asmr_e_invalid_override_and_opcode=07056;
+ asmr_e_too_many_operands=07057;
+ asmr_w_near_ignored=07058;
+ asmr_w_far_ignored=07059;
+ asmr_e_dup_local_sym=07060;
+ asmr_e_unknown_local_sym=07061;
+ asmr_e_unknown_label_identifier=07062;
+ asmr_e_invalid_register=07063;
+ asmr_e_invalid_fpu_register=07064;
+ asmr_w_modulo_not_supported=07066;
+ asmr_e_invalid_float_const=07067;
+ asmr_e_invalid_float_expr=07068;
+ asmr_e_wrong_sym_type=07069;
+ asmr_e_cannot_index_relative_var=07070;
+ asmr_e_invalid_seg_override=07071;
+ asmr_w_id_supposed_external=07072;
+ asmr_e_string_not_allowed_as_const=07073;
+ asmr_e_no_var_type_specified=07074;
+ asmr_w_assembler_code_not_returned_to_text=07075;
+ asmr_e_not_directive_or_local_symbol=07076;
+ asmr_w_using_defined_as_local=07077;
+ asmr_e_dollar_without_identifier=07078;
+ asmr_w_32bit_const_for_address=07079;
+ asmr_n_align_is_target_specific=07080;
+ asmr_e_cannot_access_field_directly_for_parameters=07081;
+ asmr_e_cannot_access_object_field_directly=07082;
+ asmr_e_unable_to_determine_reference_size=07083;
+ asmr_e_cannot_use_RESULT_here=07084;
+ asmr_w_adding_explicit_args_fXX=07086;
+ asmr_w_adding_explicit_first_arg_fXX=07087;
+ asmr_w_adding_explicit_second_arg_fXX=07088;
+ asmr_e_invalid_char_smaller=07089;
+ asmr_e_invalid_char_greater=07090;
+ asmr_w_align_not_supported=07093;
+ asmr_e_no_inc_and_dec_together=07094;
+ asmr_e_invalid_reg_list_in_movem=07095;
+ asmr_e_invalid_reg_list_for_opcode=07096;
+ asmr_e_higher_cpu_mode_required=07097;
+ asmr_w_unable_to_determine_reference_size_using_dword=07098;
+ asmr_e_illegal_shifterop_syntax=07099;
+ asmr_e_packed_element=07100;
+ asmr_w_unable_to_determine_reference_size_using_byte=07101;
+ asmr_w_no_direct_ebp_for_parameter=07102;
+ asmr_w_direct_ebp_for_parameter_regcall=07103;
+ asmr_w_direct_ebp_neg_offset=07104;
+ asmr_w_direct_esp_neg_offset=07105;
+ asmr_e_no_vmtoffset_possible=07106;
+ asmr_e_need_pic_ref=07107;
+ asmr_e_mixing_regtypes=07108;
+ asmr_e_empty_regset=07109;
+ asmr_w_useless_got_for_local=07110;
+ asmr_w_general_segment_with_constant=07111;
+ asmr_e_bad_seh_directive_offset=07112;
+ asmr_e_bad_seh_directive_register=07113;
+ asmr_e_seh_in_pure_asm_only=07114;
+ asmr_e_unsupported_directive=07115;
+ asmw_f_too_many_asm_files=08000;
+ asmw_f_assembler_output_not_supported=08001;
+ asmw_f_comp_not_supported=08002;
+ asmw_f_direct_not_supported=08003;
+ asmw_e_alloc_data_only_in_bss=08004;
+ asmw_f_no_binary_writer_selected=08005;
+ asmw_e_opcode_not_in_table=08006;
+ asmw_e_invalid_opcode_and_operands=08007;
+ asmw_e_16bit_not_supported=08008;
+ asmw_e_invalid_effective_address=08009;
+ asmw_e_immediate_or_reference_expected=08010;
+ asmw_e_value_exceeds_bounds=08011;
+ asmw_e_short_jmp_out_of_range=08012;
+ asmw_e_undefined_label=08013;
+ asmw_e_comp_not_supported=08014;
+ asmw_e_extended_not_supported=08015;
+ asmw_e_duplicate_label=08016;
+ asmw_e_redefined_label=08017;
+ asmw_e_first_defined_label=08018;
+ asmw_e_invalid_register=08019;
+ asmw_e_16bit_32bit_not_supported=08020;
+ asmw_e_64bit_not_supported=08021;
+ asmw_e_bad_reg_with_rex=08022;
+ asmw_e_missing_endprologue=08023;
+ asmw_e_prologue_too_large=08024;
+ asmw_e_handlerdata_no_handler=08025;
+ exec_w_source_os_redefined=09000;
+ exec_i_assembling_pipe=09001;
+ exec_d_cant_create_asmfile=09002;
+ exec_e_cant_create_objectfile=09003;
+ exec_e_cant_create_archivefile=09004;
+ exec_e_assembler_not_found=09005;
+ exec_t_using_assembler=09006;
+ exec_e_error_while_assembling=09007;
+ exec_e_cant_call_assembler=09008;
+ exec_i_assembling=09009;
+ exec_i_assembling_smart=09010;
+ exec_w_objfile_not_found=09011;
+ exec_w_libfile_not_found=09012;
+ exec_e_error_while_linking=09013;
+ exec_e_cant_call_linker=09014;
+ exec_i_linking=09015;
+ exec_e_util_not_found=09016;
+ exec_t_using_util=09017;
+ exec_e_exe_not_supported=09018;
+ exec_e_dll_not_supported=09019;
+ exec_i_closing_script=09020;
+ exec_e_res_not_found=09021;
+ exec_i_compilingresource=09022;
+ exec_t_unit_not_static_linkable_switch_to_smart=09023;
+ exec_t_unit_not_smart_linkable_switch_to_static=09024;
+ exec_t_unit_not_shared_linkable_switch_to_static=09025;
+ exec_e_unit_not_smart_or_static_linkable=09026;
+ exec_e_unit_not_shared_or_static_linkable=09027;
+ exec_d_resbin_params=09028;
+ exec_e_error_while_compiling_resources=09029;
+ exec_e_cant_call_resource_compiler=09030;
+ exec_e_cant_open_resource_file=09031;
+ exec_e_cant_write_resource_file=09032;
+ exec_n_backquote_cat_file_not_found=09033;
+ execinfo_f_cant_process_executable=09128;
+ execinfo_f_cant_open_executable=09129;
+ execinfo_x_codesize=09130;
+ execinfo_x_initdatasize=09131;
+ execinfo_x_uninitdatasize=09132;
+ execinfo_x_stackreserve=09133;
+ execinfo_x_stackcommit=09134;
+ link_f_executable_too_big=09200;
+ link_w_32bit_absolute_reloc=09201;
+ unit_t_unitsearch=10000;
+ unit_t_ppu_loading=10001;
+ unit_u_ppu_name=10002;
+ unit_u_ppu_flags=10003;
+ unit_u_ppu_crc=10004;
+ unit_u_ppu_time=10005;
+ unit_u_ppu_file_too_short=10006;
+ unit_u_ppu_invalid_header=10007;
+ unit_u_ppu_invalid_version=10008;
+ unit_u_ppu_invalid_processor=10009;
+ unit_u_ppu_invalid_target=10010;
+ unit_u_ppu_source=10011;
+ unit_u_ppu_write=10012;
+ unit_f_ppu_cannot_write=10013;
+ unit_f_ppu_read_error=10014;
+ unit_f_ppu_read_unexpected_end=10015;
+ unit_f_ppu_invalid_entry=10016;
+ unit_f_ppu_dbx_count_problem=10017;
+ unit_e_illegal_unit_name=10018;
+ unit_f_too_much_units=10019;
+ unit_f_circular_unit_reference=10020;
+ unit_f_cant_compile_unit=10021;
+ unit_f_cant_find_ppu=10022;
+ unit_w_unit_name_error=10023;
+ unit_f_unit_name_error=10024;
+ unit_w_switch_us_missed=10025;
+ unit_f_errors_in_unit=10026;
+ unit_u_load_unit=10027;
+ unit_u_recompile_crc_change=10028;
+ unit_u_recompile_source_found_alone=10029;
+ unit_u_recompile_staticlib_is_older=10030;
+ unit_u_recompile_sharedlib_is_older=10031;
+ unit_u_recompile_obj_and_asm_older=10032;
+ unit_u_recompile_obj_older_than_asm=10033;
+ unit_u_parsing_interface=10034;
+ unit_u_parsing_implementation=10035;
+ unit_u_second_load_unit=10036;
+ unit_u_check_time=10037;
+ unit_w_cant_compile_unit_with_changed_incfile=10040;
+ unit_u_source_modified=10041;
+ unit_u_ppu_invalid_fpumode=10042;
+ unit_u_loading_interface_units=10043;
+ unit_u_loading_implementation_units=10044;
+ unit_u_interface_crc_changed=10045;
+ unit_u_implementation_crc_changed=10046;
+ unit_u_finished_compiling=10047;
+ unit_u_add_depend_to=10048;
+ unit_u_no_reload_is_caller=10049;
+ unit_u_no_reload_in_second_compile=10050;
+ unit_u_flag_for_reload=10051;
+ unit_u_forced_reload=10052;
+ unit_u_previous_state=10053;
+ unit_u_second_compile_unit=10054;
+ unit_u_loading_unit=10055;
+ unit_u_finished_loading_unit=10056;
+ unit_u_registering_new_unit=10057;
+ unit_u_reresolving_unit=10058;
+ unit_u_skipping_reresolving_unit=10059;
+ unit_u_unload_resunit=10060;
+ unit_e_different_wpo_file=10061;
+ unit_u_indirect_crc_changed=10062;
+ option_usage=11000;
+ option_only_one_source_support=11001;
+ option_def_only_for_os2=11002;
+ option_no_nested_response_file=11003;
+ option_no_source_found=11004;
+ option_no_option_found=11005;
+ option_illegal_para=11006;
+ option_help_pages_para=11007;
+ option_too_many_cfg_files=11008;
+ option_unable_open_file=11009;
+ option_reading_further_from=11010;
+ option_target_is_already_set=11011;
+ option_no_shared_lib_under_dos=11012;
+ option_too_many_ifdef=11013;
+ option_too_many_endif=11014;
+ option_too_less_endif=11015;
+ option_no_debug_support=11016;
+ option_no_debug_support_recompile_fpc=11017;
+ option_obsolete_switch=11018;
+ option_obsolete_switch_use_new=11019;
+ option_switch_bin_to_src_assembler=11020;
+ option_incompatible_asm=11021;
+ option_asm_forced=11022;
+ option_using_file=11026;
+ option_using_env=11027;
+ option_handling_option=11028;
+ option_help_press_enter=11029;
+ option_start_reading_configfile=11030;
+ option_end_reading_configfile=11031;
+ option_interpreting_option=11032;
+ option_interpreting_firstpass_option=11036;
+ option_interpreting_file_option=11033;
+ option_read_config_file=11034;
+ option_found_file=11035;
+ option_code_page_not_available=11039;
+ option_config_is_dir=11040;
+ option_confict_asm_debug=11041;
+ option_ppc386_deprecated=11042;
+ option_else_without_if=11043;
+ option_unsupported_target=11044;
+ option_unsupported_target_for_feature=11045;
+ option_dwarf_smart_linking=11046;
+ option_ignored_target=11047;
+ option_debug_external_unsupported=11048;
+ option_dwarf_smartlink_creation=11049;
+ wpo_cant_find_file=12000;
+ wpo_begin_processing=12001;
+ wpo_end_processing=12002;
+ wpo_expected_section=12003;
+ wpo_no_section_handler=12004;
+ wpo_found_section=12005;
+ wpo_no_input_specified=12006;
+ wpo_not_enough_info=12007;
+ wpo_no_output_specified=12008;
+ wpo_output_without_info_gen=12009;
+ wpo_input_without_info_use=12010;
+ wpo_skipping_unnecessary_section=12011;
+ wpo_duplicate_wpotype=12012;
+ wpo_cannot_extract_live_symbol_info_strip=12013;
+ wpo_cannot_extract_live_symbol_info_no_link=12014;
+ wpo_cannot_find_symbol_progs=12015;
+ wpo_error_reading_symbol_file=12016;
+ wpo_error_executing_symbol_prog=12017;
+ wpo_symbol_live_info_needs_smart_linking=12018;
+ wpo_cant_create_feedback_file=12019;
+ option_logo=11023;
+ option_info=11024;
+ option_help_pages=11025;
+
+ MsgTxtSize = 62116;
+
+ MsgIdxMax : array[1..20] of longint=(
+ 26,89,315,109,85,55,116,26,202,63,
+ 50,20,1,1,1,1,1,1,1,1
+ );
diff --git a/closures/compiler/msgtxt.inc b/closures/compiler/msgtxt.inc
new file mode 100644
index 0000000000..6f0ef14f37
--- /dev/null
+++ b/closures/compiler/msgtxt.inc
@@ -0,0 +1,1453 @@
+{$ifdef Delphi}
+const msgtxt : array[0..000258] of string[240]=(
+{$else Delphi}
+const msgtxt : array[0..000258,1..240] of char=(
+{$endif Delphi}
+ '01000_T_Compiler: $1'#000+
+ '01001_D_Compiler OS: $1'#000+
+ '01002_I_Target OS: $1'#000+
+ '01003_T_Using executable path: $1'#000+
+ '01004_T_Using unit path: $1'#000+
+ '01005_T_Using include path: $1'#000+
+ '01006_T_Using library path: $1'#000+
+ '01007_T_Using object path: $1'#000+
+ '01008_I_$1 lines co','mpiled, $2 sec$3'#000+
+ '01009_F_No memory left'#000+
+ '01010_I_Writing Resource String Table file: $1'#000+
+ '01011_E_Writing Resource String Table file: $1'#000+
+ '01012_I_Fatal:'#000+
+ '01013_I_Error:'#000+
+ '01014_I_Warning:'#000+
+ '01015_I_Note:'#000+
+ '01016_I_Hint:'#000+
+ '01017_E_Path "$1" does not exis','t'#000+
+ '01018_F_Compilation aborted'#000+
+ '01019_bytes code'#000+
+ '01020_bytes data'#000+
+ '01021_I_$1 warning(s) issued'#000+
+ '01022_I_$1 hint(s) issued'#000+
+ '01023_I_$1 note(s) issued'#000+
+ '01024_F_I/O error: $1'#000+
+ '01025_F_Operating system error: $1'#000+
+ '02000_F_Unexpected end of file'#000+
+ '02001_F','_String exceeds line'#000+
+ '02002_F_illegal character "$1" ($2)'#000+
+ '02003_F_Syntax error, "$1" expected but "$2" found'#000+
+ '02004_TL_Start reading includefile $1'#000+
+ '02005_W_Comment level $1 found'#000+
+ '02008_N_Ignored compiler switch "$1"'#000+
+ '02009_W_Illegal compiler s','witch "$1"'#000+
+ '02010_W_Misplaced global compiler switch'#000+
+ '02011_E_Illegal char constant'#000+
+ '02012_F_Can'#039't open file "$1"'#000+
+ '02013_F_Can'#039't open include file "$1"'#000+
+ '02015_E_Illegal record alignment specifier "$1"'#000+
+ '02016_E_Illegal enum minimum-size specifier ','"$1"'#000+
+ '02017_E_$ENDIF expected for $1 $2 defined in $3 line $4'#000+
+ '02018_E_Syntax error while parsing a conditional compiling expression'#000+
+ '02019_E_Evaluating a conditional compiling expression'#000+
+ '02020_W_Macro contents are limited to 255 characters in',' length'#000+
+ '02021_E_ENDIF without IF(N)DEF'#000+
+ '02022_F_User defined: $1'#000+
+ '02023_E_User defined: $1'#000+
+ '02024_W_User defined: $1'#000+
+ '02025_N_User defined: $1'#000+
+ '02026_H_User defined: $1'#000+
+ '02027_I_User defined: $1'#000+
+ '02028_E_Keyword redefined as macro has no effect'#000+
+ '02','029_F_Macro buffer overflow while reading or expanding a macro'#000+
+ '02030_W_Expanding of macros exceeds a depth of 16.'#000+
+ '02031_W_compiler switches aren'#039't supported in // styled comments'#000+
+ '02032_DL_Handling switch "$1"'#000+
+ '02033_CL_ENDIF $1 found'#000+
+ '02034_C','L_IFDEF $1 found, $2'#000+
+ '02035_CL_IFOPT $1 found, $2'#000+
+ '02036_CL_IF $1 found, $2'#000+
+ '02037_CL_IFNDEF $1 found, $2'#000+
+ '02038_CL_ELSE $1 found, $2'#000+
+ '02039_CL_Skipping until...'#000+
+ '02040_I_Press <return> to continue'#000+
+ '02041_W_Unsupported switch "$1"'#000+
+ '02042_W_Illegal ','compiler directive "$1"'#000+
+ '02043_TL_Back in $1'#000+
+ '02044_W_Unsupported application type: "$1"'#000+
+ '02045_W_APPTYPE is not supported by the target OS'#000+
+ '02046_W_DESCRIPTION is not supported by the target OS'#000+
+ '02047_N_VERSION is not supported by target OS'#000+
+ '020','48_N_VERSION only for exes or DLLs'#000+
+ '02049_W_Wrong format for VERSION directive "$1"'#000+
+ '02050_E_Illegal assembler style specified "$1"'#000+
+ '02051_W_ASM reader switch is not possible inside asm statement, "$1" w'+
+ 'ill be effective only for next'#000+
+ '02052_E_W','rong switch toggle, use ON/OFF or +/-'#000+
+ '02053_E_Resource files are not supported for this target'#000+
+ '02054_W_Include environment "$1" not found in environment'#000+
+ '02055_E_Illegal value for FPU register limit'#000+
+ '02056_W_Only one resource file is supporte','d for this target'#000+
+ '02057_W_Macro support has been turned off'#000+
+ '02058_E_Illegal interface type specified. Valids are COM, CORBA or DEF'+
+ 'AULT.'#000+
+ '02059_W_APPID is only supported for PalmOS'#000+
+ '02060_W_APPNAME is only supported for PalmOS'#000+
+ '02061_E_Constant',' strings can'#039't be longer than 255 chars'#000+
+ '02062_F_Including include files exceeds a depth of 16.'#000+
+ '02063_F_Too many levels of PUSH'#000+
+ '02064_E_A POP without a preceding PUSH'#000+
+ '02065_E_Macro or compile time variable "$1" does not have any value'#000+
+ '02066_','E_Wrong switch toggle, use ON/OFF/DEFAULT or +/-/*'#000+
+ '02067_E_Mode switch "$1" not allowed here'#000+
+ '02068_E_Compile time variable or macro "$1" is not defined.'#000+
+ '02069_E_UTF-8 code greater than 65535 found'#000+
+ '02070_E_Malformed UTF-8 string'#000+
+ '02071_C_UTF-','8 signature found, using UTF-8 encoding'#000+
+ '02072_E_Compile time expression: Wanted $1 but got $2 at $3'#000+
+ '02073_N_APPTYPE is not supported by the target OS'#000+
+ '02074_E_Illegal optimization specified "$1"'#000+
+ '02075_W_SETPEFLAGS is not supported by the tar','get OS'#000+
+ '02076_W_IMAGEBASE is not supported by the target OS'#000+
+ '02077_W_MINSTACKSIZE is not supported by the target OS'#000+
+ '02078_W_MAXSTACKSIZE is not supported by the target OS'#000+
+ '02079_E_Illegal state "$1" for $WARN directive'#000+
+ '02080_E_Illegal set pack','ing value'#000+
+ '02081_W_PIC directive or switch ignored'#000+
+ '02082_W_The switch "$1" is not supported by the currently selected tar'+
+ 'get'#000+
+ '02084_W_Framework-related options are only supported for Darwin/Mac OS'+
+ ' X'#000+
+ '02085_E_Illegal minimal floating point cons','tant precision "$1"'#000+
+ '02086_W_Overriding name of "main" procedure multiple times, was previo'+
+ 'usly set to "$1"'#000+
+ '02087_W_Illegal identifier "$1" for $WARN directive'#000+
+ '02088_E_Illegal alignment directive'#000+
+ '03000_E_Parser - Syntax Error'#000+
+ '03004_E_INTERRU','PT procedure can'#039't be nested'#000+
+ '03005_W_Procedure type "$1" ignored'#000+
+ '03006_E_Not all declarations of "$1" are declared with OVERLOAD'#000+
+ '03008_E_Duplicate exported function name "$1"'#000+
+ '03009_E_Duplicate exported function index $1'#000+
+ '03010_E_Invalid inde','x for exported function'#000+
+ '03011_W_Relocatable DLL or executable $1 debug info does not work, dis'+
+ 'abled.'#000+
+ '03012_W_To allow debugging for win32 code you need to disable relocati'+
+ 'on with -WN option'#000+
+ '03013_E_Constructor name must be INIT'#000+
+ '03014_E_Dest','ructor name must be DONE'#000+
+ '03016_E_Procedure type INLINE not supported'#000+
+ '03018_W_Constructor should be public'#000+
+ '03019_W_Destructor should be public'#000+
+ '03020_N_Class should have one destructor only'#000+
+ '03021_E_Local class definitions are not allowed'#000+
+ '0302','2_F_Anonymous class definitions are not allowed'#000+
+ '03023_N_The object "$1" has no VMT'#000+
+ '03024_E_Illegal parameter list'#000+
+ '03026_E_Wrong number of parameters specified for call to "$1"'#000+
+ '03027_E_overloaded identifier "$1" isn'#039't a function'#000+
+ '03028_E_over','loaded functions have the same parameter list'#000+
+ '03029_E_function header doesn'#039't match the previous declaration "$1'+
+ '"'#000+
+ '03030_E_function header "$1" doesn'#039't match forward : var name chan'+
+ 'ges $2 => $3'#000+
+ '03031_N_Values in enumeration types have to be ','ascending'#000+
+ '03033_E_With cannot be used for variables in a different segment'#000+
+ '03034_E_function nesting > 31'#000+
+ '03035_E_range check error while evaluating constants'#000+
+ '03036_W_range check error while evaluating constants'#000+
+ '03037_E_duplicate case label'#000,
+ '03038_E_Upper bound of case range is less than lower bound'#000+
+ '03039_E_typed constants of classes or interfaces are not allowed'#000+
+ '03040_E_functions variables of overloaded functions are not allowed'#000+
+ '03041_E_string length must be a value from 1 to ','255'#000+
+ '03042_W_use extended syntax of NEW and DISPOSE for instances of object'+
+ 's'#000+
+ '03043_W_use of NEW or DISPOSE for untyped pointers is meaningless'#000+
+ '03044_E_use of NEW or DISPOSE is not possible for untyped pointers'#000+
+ '03045_E_class identifier expect','ed'#000+
+ '03046_E_type identifier not allowed here'#000+
+ '03047_E_method identifier expected'#000+
+ '03048_E_function header doesn'#039't match any method of this class "$1'+
+ '"'#000+
+ '03049_DL_procedure/function $1'#000+
+ '03050_E_Illegal floating point constant'#000+
+ '03051_E_FAIL can be us','ed in constructors only'#000+
+ '03052_E_Destructors can'#039't have parameters'#000+
+ '03053_E_Only class methods, class properties and class variables can b'+
+ 'e referred with class references'#000+
+ '03054_E_Only class methods, class properties and class variables can b'+
+ 'e',' accessed in class methods'#000+
+ '03055_E_Constant and CASE types do not match'#000+
+ '03056_E_The symbol can'#039't be exported from a library'#000+
+ '03057_W_An inherited method is hidden by "$1"'#000+
+ '03058_E_There is no method in an ancestor class to be overridden: "$1"',
+ #000+
+ '03059_E_No member is provided to access property'#000+
+ '03060_W_Stored property directive is not yet implemented'#000+
+ '03061_E_Illegal symbol for property access'#000+
+ '03062_E_Cannot access a protected field of an object here'#000+
+ '03063_E_Cannot access a private ','field of an object here'#000+
+ '03066_E_Overridden methods must have the same return type: "$2" is ove'+
+ 'rridden by "$1" which has another return type'#000+
+ '03067_E_EXPORT declared functions can'#039't be nested'#000+
+ '03068_E_Methods can'#039't be EXPORTed'#000+
+ '03069_E_Call by ','var for arg no. $1 has to match exactly: Got "$2" ex'+
+ 'pected "$3"'#000+
+ '03070_E_Class isn'#039't a parent class of the current class'#000+
+ '03071_E_SELF is only allowed in methods'#000+
+ '03072_E_Methods can be only in other methods called direct with type i'+
+ 'dentifier ','of the class'#000+
+ '03073_E_Illegal use of '#039':'#039#000+
+ '03074_E_range check error in set constructor or duplicate set element'#000+
+ '03075_E_Pointer to object expected'#000+
+ '03076_E_Expression must be constructor call'#000+
+ '03077_E_Expression must be destructor call'#000+
+ '03078_E_','Illegal order of record elements'#000+
+ '03079_E_Expression type must be class or record type'#000+
+ '03080_E_Procedures can'#039't return a value'#000+
+ '03081_E_constructors, destructors and class operators must be methods'#000+
+ '03082_E_Operator is not overloaded'#000+
+ '03083_E_I','mpossible to overload assignment for equal types'#000+
+ '03084_E_Impossible operator overload'#000+
+ '03085_E_Re-raise isn'#039't possible there'#000+
+ '03086_E_The extended syntax of new or dispose isn'#039't allowed for a '+
+ 'class'#000+
+ '03088_E_Procedure overloading is switched of','f'#000+
+ '03089_E_It is not possible to overload this operator. Related overload'+
+ 'able operators (if any) are: $1'#000+
+ '03090_E_Comparative operator must return a boolean value'#000+
+ '03091_E_Only virtual methods can be abstract'#000+
+ '03092_F_Use of unsupported feature','!'#000+
+ '03093_E_The mix of different kind of objects (class, object, interface'+
+ ', etc) isn'#039't allowed'#000+
+ '03094_W_Unknown procedure directive had to be ignored: "$1"'#000+
+ '03095_E_absolute can only be associated to one variable'#000+
+ '03096_E_absolute can only be as','sociated with a var or const'#000+
+ '03097_E_Only one variable can be initialized'#000+
+ '03098_E_Abstract methods shouldn'#039't have any definition (with funct'+
+ 'ion body)'#000+
+ '03099_E_This overloaded function can'#039't be local (must be exported)'+
+ #000+
+ '03100_W_Virtual methods',' are used without a constructor in "$1"'#000+
+ '03101_CL_Macro defined: $1'#000+
+ '03102_CL_Macro undefined: $1'#000+
+ '03103_CL_Macro $1 set to $2'#000+
+ '03104_I_Compiling $1'#000+
+ '03105_UL_Parsing interface of unit $1'#000+
+ '03106_UL_Parsing implementation of $1'#000+
+ '03107_DL_Compiling ','$1 for the second time'#000+
+ '03109_E_No property found to override'#000+
+ '03110_E_Only one default property is allowed'#000+
+ '03111_E_The default property must be an array property'#000+
+ '03112_E_Virtual constructors are only supported in class object model'#000+
+ '03113_E_N','o default property available'#000+
+ '03114_E_The class can'#039't have a published section, use the {$M+} sw'+
+ 'itch'#000+
+ '03115_E_Forward declaration of class "$1" must be resolved here to use'+
+ ' the class as ancestor'#000+
+ '03116_E_Local operators not supported'#000+
+ '03117_E_P','rocedure directive "$1" not allowed in interface section'#000+
+ '03118_E_Procedure directive "$1" not allowed in implementation section'+
+ #000+
+ '03119_E_Procedure directive "$1" not allowed in procvar declaration'#000+
+ '03120_E_Function is already declared Public/','Forward "$1"'#000+
+ '03121_E_Can'#039't use both EXPORT and EXTERNAL'#000+
+ '03123_W_"$1" not yet supported inside inline procedure/function'#000+
+ '03124_W_Inlining disabled'#000+
+ '03125_I_Writing Browser log $1'#000+
+ '03126_H_may be pointer dereference is missing'#000+
+ '03127_F_Selected ','assembler reader not supported'#000+
+ '03128_E_Procedure directive "$1" has conflicts with other directives'#000+
+ '03129_E_Calling convention doesn'#039't match forward'#000+
+ '03131_E_Property can'#039't have a default value'#000+
+ '03132_E_The default value of a property must be',' constant'#000+
+ '03133_E_Symbol can'#039't be published, can be only a class'#000+
+ '03134_E_This kind of property can'#039't be published'#000+
+ '03136_E_An import name is required'#000+
+ '03138_E_Division by zero'#000+
+ '03139_E_Invalid floating point operation'#000+
+ '03140_E_Upper bound of ra','nge is less than lower bound'#000+
+ '03141_W_string "$1" is longer than "$2"'#000+
+ '03142_E_string length is larger than array of char length'#000+
+ '03143_E_Illegal expression after message directive'#000+
+ '03144_E_Message handlers can take only one call by ref. parame','ter'#000+
+ '03145_E_Duplicate message label: "$1"'#000+
+ '03146_E_Self can only be an explicit parameter in methods which are me'+
+ 'ssage handlers'#000+
+ '03147_E_Threadvars can be only static or global'#000+
+ '03148_F_Direct assembler not supported for binary output format'#000+
+ '0','3149_W_Don'#039't load OBJPAS unit manually, use \{\$mode objfpc\} o'+
+ 'r \{\$mode delphi\} instead'#000+
+ '03150_E_OVERRIDE can'#039't be used in objects'#000+
+ '03151_E_Data types which require initialization/finalization can'#039't'+
+ ' be used in variant records'#000+
+ '03152_E_Resou','rcestrings can be only static or global'#000+
+ '03153_E_Exit with argument can'#039't be used here'#000+
+ '03154_E_The type of the storage symbol must be boolean'#000+
+ '03155_E_This symbol isn'#039't allowed as storage symbol'#000+
+ '03156_E_Only classes which are compiled in $M+ ','mode can be published'+
+ #000+
+ '03157_E_Procedure directive expected'#000+
+ '03158_E_The value for a property index must be of an ordinal type'#000+
+ '03159_E_Procedure name too short to be exported'#000+
+ '03160_E_No DEFFILE entry can be generated for unit global vars'#000+
+ '0316','1_E_Compile without -WD option'#000+
+ '03162_F_You need ObjFpc (-S2) or Delphi (-Sd) mode to compile this mod'+
+ 'ule'#000+
+ '03163_E_Can'#039't export with index under $1'#000+
+ '03164_E_Exporting of variables is not supported under $1'#000+
+ '03165_E_Improper GUID syntax'#000+
+ '03168_W_','Procedure named "$1" not found that is suitable for implemen'+
+ 'ting the $2.$3'#000+
+ '03169_E_interface identifier expected'#000+
+ '03170_E_Type "$1" can'#039't be used as array index type'#000+
+ '03171_E_Con- and destructors aren'#039't allowed in interfaces'#000+
+ '03172_E_Access sp','ecifiers can'#039't be used in INTERFACEs and OBJCPR'+
+ 'OTOCOLs'#000+
+ '03173_E_An interface, helper or Objective-C protocol or category canno'+
+ 't contain fields'#000+
+ '03174_E_Can'#039't declare local procedure as EXTERNAL'#000+
+ '03175_W_Some fields coming before "$1" weren'#039't i','nitialized'#000+
+ '03176_E_Some fields coming before "$1" weren'#039't initialized'#000+
+ '03177_W_Some fields coming after "$1" weren'#039't initialized'#000+
+ '03178_E_VarArgs directive (or '#039'...'#039' in MacPas) without CDecl/C'+
+ 'PPDecl/MWPascal and External'#000+
+ '03179_E_Self must be ','a normal (call-by-value) parameter'#000+
+ '03180_E_Interface "$1" has no interface identification'#000+
+ '03181_E_Unknown class field or method identifier "$1"'#000+
+ '03182_W_Overriding calling convention "$1" with "$2"'#000+
+ '03183_E_Typed constants of the type "proced','ure of object" can only b'+
+ 'e initialized with NIL'#000+
+ '03184_E_Default value can only be assigned to one parameter'#000+
+ '03185_E_Default parameter required for "$1"'#000+
+ '03186_W_Use of unsupported feature!'#000+
+ '03187_H_C arrays are passed by reference'#000+
+ '03188_E_C a','rray of const must be the last argument'#000+
+ '03189_H_Type "$1" redefinition'#000+
+ '03190_W_cdecl'#039'ared functions have no high parameter'#000+
+ '03191_W_cdecl'#039'ared functions do not support open strings'#000+
+ '03192_E_Cannot initialize variables declared as threadvar'#000+
+ '03','193_E_Message directive is only allowed in Classes'#000+
+ '03194_E_Procedure or Function expected'#000+
+ '03195_W_Calling convention directive ignored: "$1"'#000+
+ '03196_E_REINTRODUCE can'#039't be used in objects'#000+
+ '03197_E_Each argument must have its own location'#000+
+ '03198','_E_Each argument must have an explicit location'#000+
+ '03199_E_Unknown argument location'#000+
+ '03200_E_32 Bit-Integer or pointer variable expected'#000+
+ '03201_E_Goto statements aren'#039't allowed between different procedure'+
+ 's'#000+
+ '03202_F_Procedure too complex, it requ','ires too many registers'#000+
+ '03203_E_Illegal expression'#000+
+ '03204_E_Invalid integer expression'#000+
+ '03205_E_Illegal qualifier'#000+
+ '03206_E_High range limit < low range limit'#000+
+ '03207_E_Exit'#039's parameter must be the name of the procedure it is u'+
+ 'sed in'#000+
+ '03208_E_Ille','gal assignment to for-loop variable "$1"'#000+
+ '03209_E_Can'#039't declare local variable as EXTERNAL'#000+
+ '03210_E_Procedure is already declared EXTERNAL'#000+
+ '03211_W_Implicit uses of Variants unit'#000+
+ '03212_E_Class and static methods can'#039't be used in INTERFACES'#000+
+ '032','13_E_Overflow in arithmetic operation'#000+
+ '03214_E_Protected or private expected'#000+
+ '03215_E_SLICE can'#039't be used outside of parameter list'#000+
+ '03216_E_A DISPINTERFACE can'#039't have a parent class'#000+
+ '03217_E_A DISPINTERFACE needs a guid'#000+
+ '03218_W_Overridden meth','ods must have a related return type. This cod'+
+ 'e may crash, it depends on a Delphi parser bug ("$2" is overridden by '+
+ '"$1" which has another return type)'#000+
+ '03219_E_Dispatch IDs must be ordinal constants'#000+
+ '03220_E_The range of the array is too larg','e'#000+
+ '03221_E_The address cannot be taken of bit packed array elements and r'+
+ 'ecord fields'#000+
+ '03222_E_Dynamic arrays cannot be packed'#000+
+ '03223_E_Bit packed array elements and record fields cannot be used as '+
+ 'loop variables'#000+
+ '03224_E_VAR, TYPE and CONST ar','e allowed only in records, objects and'+
+ ' classes'#000+
+ '03225_E_This type can'#039't be a generic'#000+
+ '03226_W_Don'#039't load LINEINFO unit manually, Use the -gl compiler sw'+
+ 'itch instead'#000+
+ '03227_E_No function result type specified for function "$1"'#000+
+ '03228_E_Specializ','ation is only supported for generic types'#000+
+ '03229_E_Generics can'#039't be used as parameters when specializing gen'+
+ 'erics'#000+
+ '03230_E_Constants of objects containing a VMT aren'#039't allowed'#000+
+ '03231_E_Taking the address of labels defined outside the current ','sco'+
+ 'pe isn'#039't allowed'#000+
+ '03233_E_Cannot initialize variables declared as external'#000+
+ '03234_E_Illegal function result type'#000+
+ '03235_E_No common type possible between "$1" and "$2"'#000+
+ '03236_E_Generics without specialization cannot be used as a type for a'+
+ ' v','ariable'#000+
+ '03237_W_Register list is ignored for pure assembler routines'#000+
+ '03238_E_Implements property must have class or interface type'#000+
+ '03239_E_Implements-property must implement interface of correct type, '+
+ 'found "$1" expected "$2"'#000+
+ '03240_E_Implem','ents-property must have read specifier'#000+
+ '03241_E_Implements-property must not have write-specifier'#000+
+ '03242_E_Implements-property must not have stored-specifier'#000+
+ '03243_E_Implements-property used on unimplemented interface: "$1"'#000+
+ '03244_E_Floating p','oint not supported for this target'#000+
+ '03245_E_Class "$1" does not implement interface "$2"'#000+
+ '03246_E_Type used by implements must be an interface'#000+
+ '03247_E_Variables cannot be exported with a different name on this tar'+
+ 'get, add the name to the decl','aration using the "export" directive (v'+
+ 'ariable name: $1, declared export name: $2)'#000+
+ '03248_E_Weak external symbols are not supported for the current target'+
+ #000+
+ '03249_E_Forward type definition does not match'#000+
+ '03250_N_Virtual method "$1" has a lower',' visibility ($2) than parent '+
+ 'class $3 ($4)'#000+
+ '03251_E_Fields cannot appear after a method or property definition, st'+
+ 'art a new visibility section first'#000+
+ '03252_E_Parameters or result types cannot contain local type definitio'+
+ 'ns. Use a separate typ','e definition in a type block.'#000+
+ '03253_E_ABSTRACT and SEALED conflict'#000+
+ '03254_E_Cannot create a descendant of the sealed class "$1"'#000+
+ '03255_E_SEALED class cannot have an ABSTRACT method'#000+
+ '03256_E_Only virtual methods can be final'#000+
+ '03257_E_Final metho','d cannot be overridden: "$1"'#000+
+ '03258_E_Only one message can be used per method.'#000+
+ '03259_E_Invalid enumerator identifier: "$1"'#000+
+ '03260_E_Enumerator identifier required'#000+
+ '03261_E_Enumerator MoveNext pattern method is not valid. Method must b'+
+ 'e a funct','ion with the Boolean return type and no required arguments.'+
+ #000+
+ '03262_E_Enumerator Current pattern property is not valid. Property mus'+
+ 't have a getter.'#000+
+ '03263_E_Only one enumerator MoveNext method is allowed per class/objec'+
+ 't'#000+
+ '03264_E_Only one enum','erator Current property is allowed per class/ob'+
+ 'ject'#000+
+ '03265_E_For in loop cannot be used for the type "$1"'#000+
+ '03266_E_Objective-C messages require their Objective-C selector name t'+
+ 'o be specified using the "message" directive.'#000+
+ '03267_E_Objective-C',' does not have formal constructors nor destructor'+
+ 's. Use the alloc, initXXX and dealloc messages.'#000+
+ '03268_E_Message name is too long (max. 255 characters)'#000+
+ '03269_E_Objective-C message symbol name for "$1" is too long'#000+
+ '03270_H_Defining a new Obje','ctive-C root class. To derive from anothe'+
+ 'r root class (e.g., NSObject), specify it as the parent class.'#000+
+ '03271_E_Objective-C classes cannot have published sections.'#000+
+ '03272_F_This module requires an Objective-C mode switch to be compiled'+
+ #000+
+ '03273','_E_Inherited methods can only be overridden in Objective-C, add'+
+ ' "override" (inherited method defined in $1)'#000+
+ '03274_H_Inherited methods can only be overridden in Objective-C, add "'+
+ 'override" (inherited method defined in $1).'#000+
+ '03275_E_Message na','me "$1" in inherited class is different from messa'+
+ 'ge name "$2" in current class.'#000+
+ '03276_E_It is not yet possible to make unique copies of Objective-C ty'+
+ 'pes'#000+
+ '03277_E_Objective-C categories and Object Pascal class helpers cannot '+
+ 'be used as type','s'#000+
+ '03278_E_Categories do not override, but replace methods. Use "reintrod'+
+ 'uce" instead.'#000+
+ '03279_E_Replaced methods can only be reintroduced in Objective-C, add '+
+ '"reintroduce" (replaced method defined in $1).'#000+
+ '03280_H_Replaced methods can only be ','reintroduced in Objective-C, ad'+
+ 'd "reintroduce" (replaced method defined in $1).'#000+
+ '03281_E_Getter for implements interface must use the target'#039's defa'+
+ 'ult calling convention.'#000+
+ '03282_E_Typed files cannot contain reference-counted types.'#000+
+ '03283_E_Op','erator is not overloaded: $2 "$1"'#000+
+ '03284_E_Operator is not overloaded: "$1" $2 "$3"'#000+
+ '03285_E_Expected another $1 array elements'#000+
+ '03286_E_String constant too long while ansistrings are disabled'#000+
+ '03287_E_Type cannot be used as univ parameter beca','use its size is un'+
+ 'known at compile time: "$1"'#000+
+ '03288_E_Only one class constructor can be declared in class: "$1"'#000+
+ '03289_E_Only one class destructor can be declared in class: "$1"'#000+
+ '03290_E_Class constructors can'#039't have parameters'#000+
+ '03291_E_Class ','destructors can'#039't have parameters'#000+
+ '03292_F_This construct requires the \{\$modeswitch objectivec1\} mode '+
+ 'switch to be active'#000+
+ '03293_E_Unicodechar/string constants cannot be converted to ansi/short'+
+ 'string at compile-time'#000+
+ '03294_E_For-in Objectiv','e-Pascal loops require \{\$modeswitch Objecti'+
+ 'veC2\} to be active'#000+
+ '03295_E_The compiler cannot find the NSFastEnumerationProtocol or NSFa'+
+ 'stEnumerationState type in the CocoaAll unit'#000+
+ '03296_E_Typed constants of the type '#039'procedure is nested'#039' ca','n'+
+ ' only be initialized with NIL and global procedures/functions'#000+
+ '03297_F_Declaration of generic class inside another generic class is n'+
+ 'ot allowed'#000+
+ '03298_E_Forward declaration of objcprotocol "$1" must be resolved befo'+
+ 're an objcclass can confor','m to it'#000+
+ '03299_E_Record types cannot have published sections'#000+
+ '03300_E_Destructors aren'#039't allowed in records or helpers'#000+
+ '03301_E_Class methods must be static in records'#000+
+ '03302_E_Constructors aren'#039't allowed in records or record helpers'#000+
+ '03303_E_Ei','ther the result or at least one parameter must be of type '+
+ '"$1"'#000+
+ '03304_E_Type parameters may require initialization/finalization - can'#039+
+ 't be used in variant records'#000+
+ '03305_E_Variables being declared as external cannot be in a custom sec'+
+ 'tion'#000+
+ '033','06_E_Non-static and non-global variables cannot have a section di'+
+ 'rective'#000+
+ '03307_E_"$1" is not allowed in helper types'#000+
+ '03308_E_Class constructors aren'#039't allowed in helpers'#000+
+ '03309_E_The use of "inherited" is not allowed in a record'#000+
+ '03310_E_Type',' declarations are not allowed in local or anonymous reco'+
+ 'rds'#000+
+ '03311_E_Duplicate implements clause for interface "$1"'#000+
+ '03312_E_Interface "$1" can'#039't be delegated by "$2", it already has '+
+ 'method resolutions'#000+
+ '03313_E_Interface "$1" can'#039't have method',' resolutions, "$2" alrea'+
+ 'dy delegates it'#000+
+ '03314_E_Invalid codepage'#000+
+ '04000_E_Type mismatch'#000+
+ '04001_E_Incompatible types: got "$1" expected "$2"'#000+
+ '04002_E_Type mismatch between "$1" and "$2"'#000+
+ '04003_E_Type identifier expected'#000+
+ '04004_E_Variable identifi','er expected'#000+
+ '04005_E_Integer expression expected, but got "$1"'#000+
+ '04006_E_Boolean expression expected, but got "$1"'#000+
+ '04007_E_Ordinal expression expected'#000+
+ '04008_E_pointer type expected, but got "$1"'#000+
+ '04009_E_class type expected, but got "$1"'#000+
+ '04011_','E_Can'#039't evaluate constant expression'#000+
+ '04012_E_Set elements are not compatible'#000+
+ '04013_E_Operation not implemented for sets'#000+
+ '04014_W_Automatic type conversion from floating type to COMP which is '+
+ 'an integer type'#000+
+ '04015_H_use DIV instead to get an ','integer result'#000+
+ '04016_E_String types have to match exactly in $V+ mode'#000+
+ '04017_E_succ or pred on enums with assignments not possible'#000+
+ '04018_E_Can'#039't read or write variables of this type'#000+
+ '04019_E_Can'#039't use readln or writeln on typed file'#000+
+ '04020_E_C','an'#039't use read or write on untyped file.'#000+
+ '04021_E_Type conflict between set elements'#000+
+ '04022_W_lo/hi(dword/qword) returns the upper/lower word/dword'#000+
+ '04023_E_Integer or real expression expected'#000+
+ '04024_E_Wrong type "$1" in array constructor'#000+
+ '04025_','E_Incompatible type for arg no. $1: Got "$2", expected "$3"'#000+
+ '04026_E_Method (variable) and Procedure (variable) are not compatible'#000+
+ '04027_E_Illegal constant passed to internal math function'#000+
+ '04028_E_Can'#039't take the address of constant expressio','ns'#000+
+ '04029_E_Argument can'#039't be assigned to'#000+
+ '04030_E_Can'#039't assign local procedure/function to procedure variabl'+
+ 'e'#000+
+ '04031_E_Can'#039't assign values to an address'#000+
+ '04032_E_Can'#039't assign values to const variable'#000+
+ '04033_E_Array type required'#000+
+ '04034_E_interfa','ce type expected, but got "$1"'#000+
+ '04035_H_Mixing signed expressions and longwords gives a 64bit result'#000+
+ '04036_W_Mixing signed expressions and cardinals here may cause a range'+
+ ' check error'#000+
+ '04037_E_Typecast has different size ($1 -> $2) in assignm','ent'#000+
+ '04038_E_enums with assignments can'#039't be used as array index'#000+
+ '04039_E_Class or Object types "$1" and "$2" are not related'#000+
+ '04040_W_Class types "$1" and "$2" are not related'#000+
+ '04041_E_Class or interface type expected, but got "$1"'#000+
+ '04042_E_Typ','e "$1" is not completely defined'#000+
+ '04043_W_String literal has more characters than short string length'#000+
+ '04044_W_Comparison might be always false due to range of constant and '+
+ 'expression'#000+
+ '04045_W_Comparison might be always true due to range of co','nstant and'+
+ ' expression'#000+
+ '04046_W_Constructing a class "$1" with abstract method "$2"'#000+
+ '04047_H_The left operand of the IN operator should be byte sized'#000+
+ '04048_W_Type size mismatch, possible loss of data / range check error'#000+
+ '04049_H_Type size misma','tch, possible loss of data / range check erro'+
+ 'r'#000+
+ '04050_E_The address of an abstract method can'#039't be taken'#000+
+ '04051_E_Assignments to formal parameters and open arrays are not possi'+
+ 'ble'#000+
+ '04052_E_Constant Expression expected'#000+
+ '04053_E_Operation "$1" no','t supported for types "$2" and "$3"'#000+
+ '04054_E_Illegal type conversion: "$1" to "$2"'#000+
+ '04055_H_Conversion between ordinals and pointers is not portable'#000+
+ '04056_W_Conversion between ordinals and pointers is not portable'#000+
+ '04057_E_Can'#039't determine whic','h overloaded function to call'#000+
+ '04058_E_Illegal counter variable'#000+
+ '04059_W_Converting constant real value to double for C variable argume'+
+ 'nt, add explicit typecast to prevent this.'#000+
+ '04060_E_Class or COM interface type expected, but got "$1"'#000+
+ '04061','_E_Constant packed arrays are not yet supported'#000+
+ '04062_E_Incompatible type for arg no. $1: Got "$2" expected "(Bit)Pack'+
+ 'ed Array"'#000+
+ '04063_E_Incompatible type for arg no. $1: Got "$2" expected "(not pack'+
+ 'ed) Array"'#000+
+ '04064_E_Elements of packed arra','ys cannot be of a type which need to '+
+ 'be initialised'#000+
+ '04065_E_Constant packed records and objects are not yet supported'#000+
+ '04066_W_Arithmetic "$1" on untyped pointer is unportable to {$T+}, sug'+
+ 'gest typecast'#000+
+ '04076_E_Can'#039't take address of a subrou','tine marked as local'#000+
+ '04077_E_Can'#039't export subroutine marked as local from a unit'#000+
+ '04078_E_Type is not automatable: "$1"'#000+
+ '04079_H_Converting the operands to "$1" before doing the add could pre'+
+ 'vent overflow errors.'#000+
+ '04080_H_Converting the operan','ds to "$1" before doing the subtract co'+
+ 'uld prevent overflow errors.'#000+
+ '04081_H_Converting the operands to "$1" before doing the multiply coul'+
+ 'd prevent overflow errors.'#000+
+ '04082_W_Converting pointers to signed integers may result in wrong com'+
+ 'paris','on results and range errors, use an unsigned type instead.'#000+
+ '04083_E_Interface type $1 has no valid GUID'#000+
+ '04084_E_Invalid selector name "$1"'#000+
+ '04085_E_Expected Objective-C method, but got $1'#000+
+ '04086_E_Expected Objective-C method or constant method',' name'#000+
+ '04087_E_No type info available for this type'#000+
+ '04088_E_Ordinal or string expression expected'#000+
+ '04089_E_String expression expected'#000+
+ '04090_W_Converting 0 to NIL'#000+
+ '04091_E_Objective-C protocol type expected, but got "$1"'#000+
+ '04092_E_The type "$1" i','s not supported for interaction with the Obje'+
+ 'ctive-C runtime.'#000+
+ '04093_E_Class or objcclass type expected, but got "$1"'#000+
+ '04094_E_Objcclass type expected'#000+
+ '04095_W_Coerced univ parameter type in procedural variable may cause c'+
+ 'rash or memory corrup','tion: $1 to $2'#000+
+ '04096_E_Type parameters of specializations of generics cannot referenc'+
+ 'e the currently specialized type'#000+
+ '04097_E_Type parameters are not allowed on non-generic class/record/ob'+
+ 'ject procedure or function'#000+
+ '04098_E_Generic declarati','on of "$1" differs from previous declaratio'+
+ 'n'#000+
+ '04099_E_Helper type expected'#000+
+ '04100_E_Record type expected'#000+
+ '04101_E_Derived class helper must extend a subclass of "$1" or the cla'+
+ 'ss itself'#000+
+ '04102_E_Derived record helper must extend "$1"'#000+
+ '04103_E_In','valid assignment, procedures return no value'#000+
+ '04104_W_Implicit string type conversion from "$1" to "$2"'#000+
+ '04105_W_Implicit string type conversion with potential data loss from '+
+ '"$1" to "$2"'#000+
+ '04106_-W_Explicit string typecast from "$1" to "$2"'#000+
+ '04','107_-W_Explicit string typecast with potential data loss from "$1"'+
+ ' to "$2"'#000+
+ '04108_W_Unicode constant cast with potential data loss'#000+
+ '05000_E_Identifier not found "$1"'#000+
+ '05001_F_Internal Error in SymTableStack()'#000+
+ '05002_E_Duplicate identifier "$1"'#000,
+ '05003_H_Identifier already defined in $1 at line $2'#000+
+ '05004_E_Unknown identifier "$1"'#000+
+ '05005_E_Forward declaration not solved "$1"'#000+
+ '05007_E_Error in type definition'#000+
+ '05009_E_Forward type not resolved "$1"'#000+
+ '05010_E_Only static variables can be use','d in static methods or outsi'+
+ 'de methods'#000+
+ '05012_F_record or class type expected'#000+
+ '05013_E_Instances of classes or objects with an abstract method are no'+
+ 't allowed'#000+
+ '05014_W_Label not defined "$1"'#000+
+ '05015_E_Label used but not defined "$1"'#000+
+ '05016_E_Ille','gal label declaration'#000+
+ '05017_E_GOTO and LABEL are not supported (use switch -Sg)'#000+
+ '05018_E_Label not found'#000+
+ '05019_E_identifier isn'#039't a label'#000+
+ '05020_E_label already defined'#000+
+ '05021_E_illegal type declaration of set elements'#000+
+ '05022_E_Forward class de','finition not resolved "$1"'#000+
+ '05023_H_Unit "$1" not used in $2'#000+
+ '05024_H_Parameter "$1" not used'#000+
+ '05025_N_Local variable "$1" not used'#000+
+ '05026_H_Value parameter "$1" is assigned but never used'#000+
+ '05027_N_Local variable "$1" is assigned but never used'#000,
+ '05028_H_Local $1 "$2" is not used'#000+
+ '05029_N_Private field "$1.$2" is never used'#000+
+ '05030_N_Private field "$1.$2" is assigned but never used'#000+
+ '05031_N_Private method "$1.$2" never used'#000+
+ '05032_E_Set type expected'#000+
+ '05033_W_Function result does not seem',' to be set'#000+
+ '05034_W_Type "$1" is not aligned correctly in current record for C'#000+
+ '05035_E_Unknown record field identifier "$1"'#000+
+ '05036_W_Local variable "$1" does not seem to be initialized'#000+
+ '05037_W_Variable "$1" does not seem to be initialized'#000+
+ '050','38_E_identifier idents no member "$1"'#000+
+ '05039_H_Found declaration: $1'#000+
+ '05040_E_Data element too large'#000+
+ '05042_E_No matching implementation for interface method "$1" found'#000+
+ '05043_W_Symbol "$1" is deprecated'#000+
+ '05044_W_Symbol "$1" is not portable'#000+
+ '0505','5_W_Symbol "$1" is not implemented'#000+
+ '05056_E_Can'#039't create unique type from this type'#000+
+ '05057_H_Local variable "$1" does not seem to be initialized'#000+
+ '05058_H_Variable "$1" does not seem to be initialized'#000+
+ '05059_W_Function result variable does not s','eem to initialized'#000+
+ '05060_H_Function result variable does not seem to be initialized'#000+
+ '05061_W_Variable "$1" read but nowhere assigned'#000+
+ '05062_H_Found abstract method: $1'#000+
+ '05063_W_Symbol "$1" is experimental'#000+
+ '05064_W_Forward declaration "$1" not r','esolved, assumed external'#000+
+ '05065_W_Symbol "$1" is belongs to a library'#000+
+ '05066_W_Symbol "$1" is deprecated: "$2"'#000+
+ '05067_E_Cannot find an enumerator for the type "$1"'#000+
+ '05068_E_Cannot find a "MoveNext" method in enumerator "$1"'#000+
+ '05069_E_Cannot find',' a "Current" property in enumerator "$1"'#000+
+ '05070_E_Mismatch between number of declared parameters and number of c'+
+ 'olons in message string.'#000+
+ '05071_N_Private type "$1.$2" never used'#000+
+ '05072_N_Private const "$1.$2" never used'#000+
+ '05073_N_Private propert','y "$1.$2" never used'#000+
+ '05074_W_Unit "$1" is deprecated'#000+
+ '05075_W_Unit "$1" is deprecated: "$2"'#000+
+ '05076_W_Unit "$1" is not portable'#000+
+ '05077_W_Unit "$1" is belongs to a library'#000+
+ '05078_W_Unit "$1" is not implemented'#000+
+ '05079_W_Unit "$1" is experimental'#000+
+ '05','080_E_No complete definition of the formally declared objcclass "$'+
+ '1" is in scope'#000+
+ '05081_E_Gotos into initialization or finalization blocks of units are '+
+ 'not allowed'#000+
+ '05082_E_Invalid external name "$1" for formal class "$2"'#000+
+ '05083_E_Complete cla','ss definition with external name "$1" here'#000+
+ '05084_W_Possible library conflict: symbol "$1" from library "$2" also '+
+ 'found in library "$3"'#000+
+ '06009_E_Parameter list size exceeds 65535 bytes'#000+
+ '06012_E_File types must be var parameters'#000+
+ '06013_E_The use',' of a far pointer isn'#039't allowed there'#000+
+ '06015_E_EXPORT declared functions can'#039't be called'#000+
+ '06016_W_Possible illegal call of constructor or destructor'#000+
+ '06017_N_Inefficient code'#000+
+ '06018_W_unreachable code'#000+
+ '06020_E_Abstract methods can'#039't be called di','rectly'#000+
+ '06027_DL_Register $1 weight $2 $3'#000+
+ '06029_DL_Stack frame is omitted'#000+
+ '06031_E_Object or class methods can'#039't be inline.'#000+
+ '06032_E_Procvar calls cannot be inline.'#000+
+ '06033_E_No code for inline procedure stored'#000+
+ '06035_E_Element zero of an ansi/wi','de- or longstring can'#039't be acc'+
+ 'essed, use (set)length instead'#000+
+ '06037_E_Constructors or destructors cannot be called inside a '#039'wit'+
+ 'h'#039' clause'#000+
+ '06038_E_Cannot call message handler methods directly'#000+
+ '06039_E_Jump in or outside of an exception block'#000+
+ '0','6040_E_Control flow statements aren'#039't allowed in a finally bloc'+
+ 'k'#000+
+ '06041_W_Parameters size exceeds limit for certain cpu'#039's'#000+
+ '06042_W_Local variable size exceed limit for certain cpu'#039's'#000+
+ '06043_E_Local variables size exceeds supported limit'#000+
+ '06044_E','_BREAK not allowed'#000+
+ '06045_E_CONTINUE not allowed'#000+
+ '06046_F_Unknown compilerproc "$1". Check if you use the correct run ti'+
+ 'me library.'#000+
+ '06047_F_Cannot find system type "$1". Check if you use the correct run'+
+ ' time library.'#000+
+ '06048_H_Inherited call to',' abstract method ignored'#000+
+ '06049_E_Goto label "$1" not defined or optimized away'#000+
+ '06050_F_Cannot find type "$1" in unit "$2". Check if you use the corre'+
+ 'ct run time library.'#000+
+ '06051_E_Interprocedural gotos are allowed only to outer subroutines'#000+
+ '06','052_E_Label must be defined in the same scope as it is declared'#000+
+ '06053_E_Leaving procedures containing explicit or implicit exceptions '+
+ 'frames using goto is not allowed'#000+
+ '06054_E_In ISO mode, the mod operator is defined only for positive quo'+
+ 'tie','nt'#000+
+ '07000_DL_Starting $1 styled assembler parsing'#000+
+ '07001_DL_Finished $1 styled assembler parsing'#000+
+ '07002_E_Non-label pattern contains @'#000+
+ '07004_E_Error building record offset'#000+
+ '07005_E_OFFSET used without identifier'#000+
+ '07006_E_TYPE used without identi','fier'#000+
+ '07007_E_Cannot use local variable or parameters here'#000+
+ '07008_E_need to use OFFSET here'#000+
+ '07009_E_need to use $ here'#000+
+ '07010_E_Cannot use multiple relocatable symbols'#000+
+ '07011_E_Relocatable symbol can only be added'#000+
+ '07012_E_Invalid constant expre','ssion'#000+
+ '07013_E_Relocatable symbol is not allowed'#000+
+ '07014_E_Invalid reference syntax'#000+
+ '07015_E_You cannot reach $1 from that code'#000+
+ '07016_E_Local symbols/labels aren'#039't allowed as references'#000+
+ '07017_E_Invalid base and index register usage'#000+
+ '07018_W_Poss','ible error in object field handling'#000+
+ '07019_E_Wrong scale factor specified'#000+
+ '07020_E_Multiple index register usage'#000+
+ '07021_E_Invalid operand type'#000+
+ '07022_E_Invalid string as opcode operand: $1'#000+
+ '07023_W_@CODE and @DATA not supported'#000+
+ '07024_E_Null labe','l references are not allowed'#000+
+ '07025_E_Divide by zero in asm evaluator'#000+
+ '07026_E_Illegal expression'#000+
+ '07027_E_escape sequence ignored: $1'#000+
+ '07028_E_Invalid symbol reference'#000+
+ '07029_W_Fwait can cause emulation problems with emu387'#000+
+ '07030_W_$1 without o','perand translated into $1P'#000+
+ '07031_W_ENTER instruction is not supported by Linux kernel'#000+
+ '07032_W_Calling an overload function in assembler'#000+
+ '07033_E_Unsupported symbol type for operand'#000+
+ '07034_E_Constant value out of bounds'#000+
+ '07035_E_Error convertin','g decimal $1'#000+
+ '07036_E_Error converting octal $1'#000+
+ '07037_E_Error converting binary $1'#000+
+ '07038_E_Error converting hexadecimal $1'#000+
+ '07039_H_$1 translated to $2'#000+
+ '07040_W_$1 is associated to an overloaded function'#000+
+ '07041_E_Cannot use SELF outside a metho','d'#000+
+ '07042_E_Cannot use OLDEBP outside a nested procedure'#000+
+ '07043_W_Procedures can'#039't return any value in asm code'#000+
+ '07044_E_SEG not supported'#000+
+ '07045_E_Size suffix and destination or source size do not match'#000+
+ '07046_W_Size suffix and destination or so','urce size do not match'#000+
+ '07047_E_Assembler syntax error'#000+
+ '07048_E_Invalid combination of opcode and operands'#000+
+ '07049_E_Assembler syntax error in operand'#000+
+ '07050_E_Assembler syntax error in constant'#000+
+ '07051_E_Invalid String expression'#000+
+ '07052_W_constant',' with symbol $1 for address which is not on a pointe'+
+ 'r'#000+
+ '07053_E_Unrecognized opcode $1'#000+
+ '07054_E_Invalid or missing opcode'#000+
+ '07055_E_Invalid combination of prefix and opcode: $1'#000+
+ '07056_E_Invalid combination of override and opcode: $1'#000+
+ '07057_E_Too m','any operands on line'#000+
+ '07058_W_NEAR ignored'#000+
+ '07059_W_FAR ignored'#000+
+ '07060_E_Duplicate local symbol $1'#000+
+ '07061_E_Undefined local symbol $1'#000+
+ '07062_E_Unknown label identifier $1'#000+
+ '07063_E_Invalid register name'#000+
+ '07064_E_Invalid floating point register name',#000+
+ '07066_W_Modulo not supported'#000+
+ '07067_E_Invalid floating point constant $1'#000+
+ '07068_E_Invalid floating point expression'#000+
+ '07069_E_Wrong symbol type'#000+
+ '07070_E_Cannot index a local var or parameter with a register'#000+
+ '07071_E_Invalid segment override expr','ession'#000+
+ '07072_W_Identifier $1 supposed external'#000+
+ '07073_E_Strings not allowed as constants'#000+
+ '07074_E_No type of variable specified'#000+
+ '07075_E_assembler code not returned to text section'#000+
+ '07076_E_Not a directive or local symbol $1'#000+
+ '07077_E_Using a def','ined name as a local label'#000+
+ '07078_E_Dollar token is used without an identifier'#000+
+ '07079_W_32bit constant created for address'#000+
+ '07080_N_.align is target specific, use .balign or .p2align'#000+
+ '07081_E_Can'#039't access fields directly for parameters'#000+
+ '07082_E_','Can'#039't access fields of objects/classes directly'#000+
+ '07083_E_No size specified and unable to determine the size of the oper'+
+ 'ands'#000+
+ '07084_E_Cannot use RESULT in this function'#000+
+ '07086_W_"$1" without operand translated into "$1 %st,%st(1)"'#000+
+ '07087_W_"$1 %','st(n)" translated into "$1 %st,%st(n)"'#000+
+ '07088_W_"$1 %st(n)" translated into "$1 %st(n),%st"'#000+
+ '07089_E_Char < not allowed here'#000+
+ '07090_E_Char > not allowed here'#000+
+ '07093_W_ALIGN not supported'#000+
+ '07094_E_Inc and Dec cannot be together'#000+
+ '07095_E_Invalid re','glist for movem'#000+
+ '07096_E_Reglist invalid for opcode'#000+
+ '07097_E_Higher cpu mode required ($1)'#000+
+ '07098_W_No size specified and unable to determine the size of the oper'+
+ 'ands, using DWORD as default'#000+
+ '07099_E_Syntax error while trying to parse a shifter',' operand'#000+
+ '07100_E_Address of packed component is not at a byte boundary'#000+
+ '07101_W_No size specified and unable to determine the size of the oper'+
+ 'ands, using BYTE as default'#000+
+ '07102_W_Use of +offset(%ebp) for parameters invalid here'#000+
+ '07103_W_Use of',' +offset(%ebp) is not compatible with regcall conventi'+
+ 'on'#000+
+ '07104_W_Use of -offset(%ebp) is not recommended for local variable acc'+
+ 'ess'#000+
+ '07105_W_Use of -offset(%esp), access may cause a crash or value may be'+
+ ' lost'#000+
+ '07106_E_VMTOffset must be used in',' combination with a virtual method,'+
+ ' and "$1" is not virtual'#000+
+ '07107_E_Generating PIC, but reference is not PIC-safe'#000+
+ '07108_E_All registers in a register set must be of the same kind and w'+
+ 'idth'#000+
+ '07109_E_A register set cannot be empty'#000+
+ '07110_W_@GOT','PCREL is useless and potentially dangereous for local sy'+
+ 'mbols'#000+
+ '07111_W_Constant with general purpose segment register'#000+
+ '07112_E_Invalid offset value for $1'#000+
+ '07113_E_Invalid register for $1'#000+
+ '07114_E_SEH directives are allowed only in pure assembl','er procedures'+
+ #000+
+ '07115_E_Directive "$1" is not supported for the current target'#000+
+ '08000_F_Too many assembler files'#000+
+ '08001_F_Selected assembler output not supported'#000+
+ '08002_F_Comp not supported'#000+
+ '08003_F_Direct not support for binary writers'#000+
+ '08004_E_A','llocating of data is only allowed in bss section'#000+
+ '08005_F_No binary writer selected'#000+
+ '08006_E_Asm: Opcode $1 not in table'#000+
+ '08007_E_Asm: $1 invalid combination of opcode and operands'#000+
+ '08008_E_Asm: 16 Bit references not supported'#000+
+ '08009_E_Asm: Inva','lid effective address'#000+
+ '08010_E_Asm: Immediate or reference expected'#000+
+ '08011_E_Asm: $1 value exceeds bounds $2'#000+
+ '08012_E_Asm: Short jump is out of range $1'#000+
+ '08013_E_Asm: Undefined label $1'#000+
+ '08014_E_Asm: Comp type not supported for this target'#000+
+ '08015','_E_Asm: Extended type not supported for this target'#000+
+ '08016_E_Asm: Duplicate label $1'#000+
+ '08017_E_Asm: Redefined label $1'#000+
+ '08018_E_Asm: First defined here'#000+
+ '08019_E_Asm: Invalid register $1'#000+
+ '08020_E_Asm: 16 or 32 Bit references not supported'#000+
+ '08021_E_','Asm: 64 Bit operands not supported'#000+
+ '08022_E_Asm: AH,BH,CH or DH cannot be used in an instruction requiring'+
+ ' REX prefix'#000+
+ '08023_E_Missing .seh_endprologue directive'#000+
+ '08024_E_Function prologue exceeds 255 bytes'#000+
+ '08025_E_.seh_handlerdata directive w','ithout preceding .seh_handler'#000+
+ '09000_W_Source operating system redefined'#000+
+ '09001_I_Assembling (pipe) $1'#000+
+ '09002_E_Can'#039't create assembler file: $1'#000+
+ '09003_E_Can'#039't create object file: $1 (error code: $2)'#000+
+ '09004_E_Can'#039't create archive file: $1'#000+
+ '09005_E','_Assembler $1 not found, switching to external assembling'#000+
+ '09006_T_Using assembler: $1'#000+
+ '09007_E_Error while assembling exitcode $1'#000+
+ '09008_E_Can'#039't call the assembler, error $1 switching to external a'+
+ 'ssembling'#000+
+ '09009_I_Assembling $1'#000+
+ '09010_I_Assem','bling with smartlinking $1'#000+
+ '09011_W_Object $1 not found, Linking may fail !'#000+
+ '09012_W_Library $1 not found, Linking may fail !'#000+
+ '09013_E_Error while linking'#000+
+ '09014_E_Can'#039't call the linker, switching to external linking'#000+
+ '09015_I_Linking $1'#000+
+ '09016_E_','Util $1 not found, switching to external linking'#000+
+ '09017_T_Using util $1'#000+
+ '09018_E_Creation of Executables not supported'#000+
+ '09019_E_Creation of Dynamic/Shared Libraries not supported'#000+
+ '09020_I_Closing script $1'#000+
+ '09021_E_resource compiler "$1" not fou','nd, switching to external mode'+
+ #000+
+ '09022_I_Compiling resource $1'#000+
+ '09023_T_unit $1 can'#039't be statically linked, switching to smart lin'+
+ 'king'#000+
+ '09024_T_unit $1 can'#039't be smart linked, switching to static linking'+
+ #000+
+ '09025_T_unit $1 can'#039't be shared linked, s','witching to static link'+
+ 'ing'#000+
+ '09026_E_unit $1 can'#039't be smart or static linked'#000+
+ '09027_E_unit $1 can'#039't be shared or static linked'#000+
+ '09028_D_Calling resource compiler "$1" with "$2" as command line'#000+
+ '09029_E_Error while compiling resources'#000+
+ '09030_E_Can',#039't call the resource compiler "$1", switching to extern'+
+ 'al mode'#000+
+ '09031_E_Can'#039't open resource file "$1"'#000+
+ '09032_E_Can'#039't write resource file "$1"'#000+
+ '09033_N_File "$1" not found for backquoted cat command'#000+
+ '09128_F_Can'#039't post process executable $1'#000+
+ '0912','9_F_Can'#039't open executable $1'#000+
+ '09130_X_Size of Code: $1 bytes'#000+
+ '09131_X_Size of initialized data: $1 bytes'#000+
+ '09132_X_Size of uninitialized data: $1 bytes'#000+
+ '09133_X_Stack space reserved: $1 bytes'#000+
+ '09134_X_Stack space committed: $1 bytes'#000+
+ '09200_F_Execu','table image size is too big for $1 target.'#000+
+ '09201_W_Object file "$1" contains 32-bit absolute relocation to symbol'+
+ ' "$2".'#000+
+ '10000_T_Unitsearch: $1'#000+
+ '10001_T_PPU Loading $1'#000+
+ '10002_U_PPU Name: $1'#000+
+ '10003_U_PPU Flags: $1'#000+
+ '10004_U_PPU Crc: $1'#000+
+ '10005_U_PPU',' Time: $1'#000+
+ '10006_U_PPU File too short'#000+
+ '10007_U_PPU Invalid Header (no PPU at the begin)'#000+
+ '10008_U_PPU Invalid Version $1'#000+
+ '10009_U_PPU is compiled for another processor'#000+
+ '10010_U_PPU is compiled for another target'#000+
+ '10011_U_PPU Source: $1'#000+
+ '10012_U_Wri','ting $1'#000+
+ '10013_F_Can'#039't Write PPU-File'#000+
+ '10014_F_Error reading PPU-File'#000+
+ '10015_F_unexpected end of PPU-File'#000+
+ '10016_F_Invalid PPU-File entry: $1'#000+
+ '10017_F_PPU Dbx count problem'#000+
+ '10018_E_Illegal unit name: $1'#000+
+ '10019_F_Too much units'#000+
+ '10020_F_Circular un','it reference between $1 and $2'#000+
+ '10021_F_Can'#039't compile unit $1, no sources available'#000+
+ '10022_F_Can'#039't find unit $1 used by $2'#000+
+ '10023_W_Unit $1 was not found but $2 exists'#000+
+ '10024_F_Unit $1 searched but $2 found'#000+
+ '10025_W_Compiling the system unit req','uires the -Us switch'#000+
+ '10026_F_There were $1 errors compiling module, stopping'#000+
+ '10027_U_Load from $1 ($2) unit $3'#000+
+ '10028_U_Recompiling $1, checksum changed for $2'#000+
+ '10029_U_Recompiling $1, source found only'#000+
+ '10030_U_Recompiling unit, static lib is',' older than ppufile'#000+
+ '10031_U_Recompiling unit, shared lib is older than ppufile'#000+
+ '10032_U_Recompiling unit, obj and asm are older than ppufile'#000+
+ '10033_U_Recompiling unit, obj is older than asm'#000+
+ '10034_U_Parsing interface of $1'#000+
+ '10035_U_Parsing impl','ementation of $1'#000+
+ '10036_U_Second load for unit $1'#000+
+ '10037_U_PPU Check file $1 time $2'#000+
+ '10040_W_Can'#039't recompile unit $1, but found modifed include files'#000+
+ '10041_U_File $1 is newer than the one used for creating PPU file $2'#000+
+ '10042_U_Trying to use a ','unit which was compiled with a different FPU'+
+ ' mode'#000+
+ '10043_U_Loading interface units from $1'#000+
+ '10044_U_Loading implementation units from $1'#000+
+ '10045_U_Interface CRC changed for unit $1'#000+
+ '10046_U_Implementation CRC changed for unit $1'#000+
+ '10047_U_Finished',' compiling unit $1'#000+
+ '10048_U_Adding dependency: $1 depends on $2'#000+
+ '10049_U_No reload, is caller: $1'#000+
+ '10050_U_No reload, already in second compile: $1'#000+
+ '10051_U_Flag for reload: $1'#000+
+ '10052_U_Forced reloading'#000+
+ '10053_U_Previous state of $1: $2'#000+
+ '10054_U_A','lready compiling $1, setting second compile'#000+
+ '10055_U_Loading unit $1'#000+
+ '10056_U_Finished loading unit $1'#000+
+ '10057_U_Registering new unit $1'#000+
+ '10058_U_Re-resolving unit $1'#000+
+ '10059_U_Skipping re-resolving unit $1, still loading used units'#000+
+ '10060_U_Unload','ing resource unit $1 (not needed)'#000+
+ '10061_E_Unit $1 was compiled using a different whole program optimizat'+
+ 'ion feedback input ($2, $3); recompile it without wpo or use the same '+
+ 'wpo feedback input file for this compilation invocation'#000+
+ '10062_U_In','direct interface (objects/classes) CRC changed for unit $1'+
+ #000+
+ '11000_O_$1 [options] <inputfile> [options]'#000+
+ '11001_W_Only one source file supported, changing source file to compil'+
+ 'e from "$1" into "$2"'#000+
+ '11002_W_DEF file can be created only for OS/2'#000,
+ '11003_E_nested response files are not supported'#000+
+ '11004_F_No source file name in command line'#000+
+ '11005_N_No option inside $1 config file'#000+
+ '11006_E_Illegal parameter: $1'#000+
+ '11007_H_-? writes help pages'#000+
+ '11008_F_Too many config files nested'#000+
+ '11009_F_Unab','le to open file $1'#000+
+ '11010_D_Reading further options from $1'#000+
+ '11011_W_Target is already set to: $1'#000+
+ '11012_W_Shared libs not supported on DOS platform, reverting to static'+
+ #000+
+ '11013_F_In options file $1 at line $2 too many \var{\#IF(N)DEFs} encou'+
+ 'nte','red'#000+
+ '11014_F_In options file $1 at line $2 unexpected \var{\#ENDIFs} encoun'+
+ 'tered'#000+
+ '11015_F_Open conditional at the end of the options file'#000+
+ '11016_W_Debug information generation is not supported by this executab'+
+ 'le'#000+
+ '11017_H_Try recompiling with -d','GDB'#000+
+ '11018_W_You are using the obsolete switch $1'#000+
+ '11019_W_You are using the obsolete switch $1, please use $2'#000+
+ '11020_N_Switching assembler to default source writing assembler'#000+
+ '11021_W_Assembler output selected "$1" is not compatible with "$2"'#000,
+ '11022_W_"$1" assembler use forced'#000+
+ '11026_T_Reading options from file $1'#000+
+ '11027_T_Reading options from environment $1'#000+
+ '11028_D_Handling option "$1"'#000+
+ '11029_O_*** press enter ***'#000+
+ '11030_H_Start of reading config file $1'#000+
+ '11031_H_End of reading confi','g file $1'#000+
+ '11032_D_interpreting option "$1"'#000+
+ '11036_D_interpreting firstpass option "$1"'#000+
+ '11033_D_interpreting file option "$1"'#000+
+ '11034_D_Reading config file "$1"'#000+
+ '11035_D_found source file name "$1"'#000+
+ '11039_E_Unknown codepage'#000+
+ '11040_F_Config file $1',' is a directory'#000+
+ '11041_W_Assembler output selected "$1" cannot generate debug info, deb'+
+ 'ugging disabled'#000+
+ '11042_W_Use of ppc386.cfg is deprecated, please use fpc.cfg instead'#000+
+ '11043_F_In options file $1 at line $2 \var{\#ELSE} directive without \',
+ 'var{\#IF(N)DEF} found'#000+
+ '11044_F_Option "$1" is not, or not yet, supported on the current targe'+
+ 't platform'#000+
+ '11045_F_The feature "$1" is not, or not yet, supported on the selected'+
+ ' target platform'#000+
+ '11046_N_DWARF debug information cannot be used wit','h smart linking on'+
+ ' this target, switching to static linking'#000+
+ '11047_W_Option "$1" is ignored for the current target platform.'#000+
+ '11048_W_Disabling external debug information because it is unsupported'+
+ ' for the selected target/debug format combinat','ion.'#000+
+ '11049_N_DWARF debug information cannot be used with smart linking with'+
+ ' external assembler, disabling static library creation.'#000+
+ '12000_F_Cannot open whole program optimization feedback file "$1"'#000+
+ '12001_D_Processing whole program optimizati','on information in wpo fee'+
+ 'dback file "$1"'#000+
+ '12002_D_Finished processing the whole program optimization information'+
+ ' in wpo feedback file "$1"'#000+
+ '12003_E_Expected section header, but got "$2" at line $1 of wpo feedba'+
+ 'ck file'#000+
+ '12004_W_No handler regis','tered for whole program optimization section'+
+ ' "$2" at line $1 of wpo feedback file, ignoring'#000+
+ '12005_D_Found whole program optimization section "$1" with information'+
+ ' about "$2"'#000+
+ '12006_F_The selected whole program optimizations require a previou','sl'+
+ 'y generated feedback file (use -Fw to specify)'#000+
+ '12007_E_No collected information necessary to perform "$1" whole progr'+
+ 'am optimization found'#000+
+ '12008_F_Specify a whole program optimization feedback file to store th'+
+ 'e generated info in (using -F','W)'#000+
+ '12009_E_Not generating any whole program optimization information, yet'+
+ ' a feedback file was specified (using -FW)'#000+
+ '12010_E_Not performing any whole program optimizations, yet an input f'+
+ 'eedback file was specified (using -Fw)'#000+
+ '12011_D_Skippin','g whole program optimization section "$1", because no'+
+ 't needed by the requested optimizations'#000+
+ '12012_W_Overriding previously read information for "$1" from feedback '+
+ 'input file using information in section "$2"'#000+
+ '12013_E_Cannot extract symbol li','veness information from program when'+
+ ' stripping symbols, use -Xs-'#000+
+ '12014_E_Cannot extract symbol liveness information from program when w'+
+ 'hen not linking'#000+
+ '12015_F_Cannot find "$1" or "$2" to extract symbol liveness informatio'+
+ 'n from linked progr','am'#000+
+ '12016_E_Error during reading symbol liveness information produced by "'+
+ '$1"'#000+
+ '12017_F_Error executing "$1" (exitcode: $2) to extract symbol informat'+
+ 'ion from linked program'#000+
+ '12018_E_Collection of symbol liveness information can only help when ',
+ 'using smart linking, use -CX -XX'#000+
+ '12019_E_Cannot create specified whole program optimisation feedback fi'+
+ 'le "$1"'#000+
+ '11023_Free Pascal Compiler version $FPCFULLVERSION [$FPCDATE] for $FPC'+
+ 'CPU'#010+
+ 'Copyright (c) 1993-2011 by Florian Klaempfl and others'#000,
+ '11024_Free Pascal Compiler version $FPCVERSION'#010+
+ #010+
+ 'Compiler Date : $FPCDATE'#010+
+ 'Compiler CPU Target: $FPCCPU'#010+
+ #010+
+ 'Supported targets:'#010+
+ ' $OSTARGETS'#010+
+ #010+
+ 'Supported CPU instruction sets:'#010+
+ ' $INSTRUCTIONSETS'#010+
+ #010+
+ 'Supported FPU instruction sets:'#010+
+ ' $FPUINSTRUCTI','ONSETS'#010+
+ #010+
+ 'Supported ABI targets:'#010+
+ ' $ABITARGETS'#010+
+ #010+
+ 'Supported Optimizations:'#010+
+ ' $OPTIMIZATIONS'#010+
+ #010+
+ 'Supported Whole Program Optimizations:'#010+
+ ' All'#010+
+ ' $WPOPTIMIZATIONS'#010+
+ #010+
+ 'Supported Microcontroller types:'#010+
+ ' $CONTROLLERTYPES'#010+
+ #010+
+ 'This program comes under the GNU ','General Public Licence'#010+
+ 'For more information read COPYING.FPC'#010+
+ #010+
+ 'Report bugs, suggestions, etc. to:'#010+
+ ' http://bugs.freepascal.org'#010+
+ 'or'#010+
+ ' bugs@freepascal.org'#000+
+ '11025_**0*_Put + after a boolean switch option to enable it',', - to di'+
+ 'sable it'#010+
+ '**1a_The compiler doesn'#039't delete the generated assembler file'#010+
+ '**2al_List sourcecode lines in assembler file'#010+
+ '**2an_List node info in assembler file'#010+
+ '*L2ap_Use pipes instead of creating temporary assembler files'#010+
+ '**2ar_List re','gister allocation/release info in assembler file'#010+
+ '**2at_List temp allocation/release info in assembler file'#010+
+ '**1A<x>_Output format:'#010+
+ '**2Adefault_Use default assembler'#010+
+ '3*2Aas_Assemble using GNU AS'#010+
+ '3*2Amacho_Mach-O (Darwin, Intel 32 bit) using i','nternal writer'#010+
+ '3*2Anasmcoff_COFF (Go32v2) file using Nasm'#010+
+ '3*2Anasmelf_ELF32 (Linux) file using Nasm'#010+
+ '3*2Anasmwin32_Win32 object file using Nasm'#010+
+ '3*2Anasmwdosx_Win32/WDOSX object file using Nasm'#010+
+ '3*2Awasm_Obj file using Wasm (Watcom)'#010+
+ '3*2Anasmob','j_Obj file using Nasm'#010+
+ '3*2Amasm_Obj file using Masm (Microsoft)'#010+
+ '3*2Atasm_Obj file using Tasm (Borland)'#010+
+ '3*2Aelf_ELF (Linux) using internal writer'#010+
+ '3*2Acoff_COFF (Go32v2) using internal writer'#010+
+ '3*2Apecoff_PE-COFF (Win32) using internal writer'#010+
+ '4*','2Aas_Assemble using GNU AS'#010+
+ '4*2Agas_Assemble using GNU GAS'#010+
+ '4*2Agas-darwin_Assemble darwin Mach-O64 using GNU GAS'#010+
+ '4*2Amasm_Win64 object file using ml64 (Microsoft)'#010+
+ '4*2Apecoff_PE-COFF (Win64) using internal writer'#010+
+ '4*2Aelf_ELF (Linux-64bit) usi','ng internal writer'#010+
+ '6*2Aas_Unix o-file using GNU AS'#010+
+ '6*2Agas_GNU Motorola assembler'#010+
+ '6*2Amit_MIT Syntax (old GAS)'#010+
+ '6*2Amot_Standard Motorola assembler'#010+
+ 'A*2Aas_Assemble using GNU AS'#010+
+ 'P*2Aas_Assemble using GNU AS'#010+
+ 'S*2Aas_Assemble using GNU AS'#010+
+ '**1b_G','enerate browser info'#010+
+ '**2bl_Generate local symbol info'#010+
+ '**1B_Build all modules'#010+
+ '**1C<x>_Code generation options:'#010+
+ '**2C3<x>_Turn on ieee error checking for constants'#010+
+ '**2Ca<x>_Select ABI, see fpc -i for possible values'#010+
+ '**2Cb_Generate big-endian c','ode'#010+
+ '**2Cc<x>_Set default calling convention to <x>'#010+
+ '**2CD_Create also dynamic library (not supported)'#010+
+ '**2Ce_Compilation with emulated floating point opcodes'#010+
+ '**2Cf<x>_Select fpu instruction set to use, see fpc -i for possible va'+
+ 'lues'#010+
+ '**2CF<x>_','Minimal floating point constant precision (default, 32, 64)'+
+ #010+
+ '**2Cg_Generate PIC code'#010+
+ '**2Ch<n>_<n> bytes heap (between 1023 and 67107840)'#010+
+ '**2Ci_IO-checking'#010+
+ '**2Cn_Omit linking stage'#010+
+ '**2Co_Check overflow of integer operations'#010+
+ '**2CO_Check for po','ssible overflow of integer operations'#010+
+ '**2Cp<x>_Select instruction set, see fpc -i for possible values'#010+
+ '**2CP<x>=<y>_ packing settings'#010+
+ '**3CPPACKSET=<y>_ <y> set allocation: 0, 1 or DEFAULT or NORMAL, 2, 4 '+
+ 'and 8'#010+
+ '**2Cr_Range checking'#010+
+ '**2CR_Veri','fy object method call validity'#010+
+ '**2Cs<n>_Set stack checking size to <n>'#010+
+ '**2Ct_Stack checking (for testing only, see manual)'#010+
+ '**2CX_Create also smartlinked library'#010+
+ '**1d<x>_Defines the symbol <x>'#010+
+ '**1D_Generate a DEF file'#010+
+ '**2Dd<x>_Set descriptio','n to <x>'#010+
+ '**2Dv<x>_Set DLL version to <x>'#010+
+ '*O2Dw_PM application'#010+
+ '**1e<x>_Set path to executable'#010+
+ '**1E_Same as -Cn'#010+
+ '**1fPIC_Same as -Cg'#010+
+ '**1F<x>_Set file names and paths:'#010+
+ '**2Fa<x>[,y]_(for a program) load units <x> and [y] before uses is par'+
+ 'sed'#010+
+ '**','2Fc<x>_Set input codepage to <x>'#010+
+ '**2FC<x>_Set RC compiler binary name to <x>'#010+
+ '**2Fd_Disable the compiler'#039's internal directory cache'#010+
+ '**2FD<x>_Set the directory where to search for compiler utilities'#010+
+ '**2Fe<x>_Redirect error output to <x>'#010+
+ '**2Ff','<x>_Add <x> to framework path (Darwin only)'#010+
+ '**2FE<x>_Set exe/unit output path to <x>'#010+
+ '**2Fi<x>_Add <x> to include path'#010+
+ '**2Fl<x>_Add <x> to library path'#010+
+ '**2FL<x>_Use <x> as dynamic linker'#010+
+ '**2Fm<x>_Load unicode conversion table from <x>.txt in',' the compiler '+
+ 'dir'#010+
+ '**2Fo<x>_Add <x> to object path'#010+
+ '**2Fr<x>_Load error message file <x>'#010+
+ '**2FR<x>_Set resource (.res) linker to <x>'#010+
+ '**2Fu<x>_Add <x> to unit path'#010+
+ '**2FU<x>_Set unit output path to <x>, overrides -FE'#010+
+ '**2FW<x>_Store generated who','le-program optimization feedback in <x>'#010+
+ '**2Fw<x>_Load previously stored whole-program optimization feedback fr'+
+ 'om <x>'#010+
+ '*g1g_Generate debug information (default format for target)'#010+
+ '*g2gc_Generate checks for pointers'#010+
+ '*g2gh_Use heaptrace unit (fo','r memory leak/corruption debugging)'#010+
+ '*g2gl_Use line info unit (show more info with backtraces)'#010+
+ '*g2go<x>_Set debug information options'#010+
+ '*g3godwarfsets_ Enable DWARF '#039'set'#039' type debug information (bre'+
+ 'aks gdb < 6.5)'#010+
+ '*g3gostabsabsincludes_ Store a','bsolute/full include file paths in Sta'+
+ 'bs'#010+
+ '*g3godwarfmethodclassprefix_ Prefix method names in DWARF with class n'+
+ 'ame'#010+
+ '*g2gp_Preserve case in stabs symbol names'#010+
+ '*g2gs_Generate Stabs debug information'#010+
+ '*g2gt_Trash local variables (to detect unini','tialized uses)'#010+
+ '*g2gv_Generates programs traceable with Valgrind'#010+
+ '*g2gw_Generate DWARFv2 debug information (same as -gw2)'#010+
+ '*g2gw2_Generate DWARFv2 debug information'#010+
+ '*g2gw3_Generate DWARFv3 debug information'#010+
+ '*g2gw4_Generate DWARFv4 debug inform','ation (experimental)'#010+
+ '**1i_Information'#010+
+ '**2iD_Return compiler date'#010+
+ '**2iV_Return short compiler version'#010+
+ '**2iW_Return full compiler version'#010+
+ '**2iSO_Return compiler OS'#010+
+ '**2iSP_Return compiler host processor'#010+
+ '**2iTO_Return target OS'#010+
+ '**2iTP_Return ta','rget processor'#010+
+ '**1I<x>_Add <x> to include path'#010+
+ '**1k<x>_Pass <x> to the linker'#010+
+ '**1l_Write logo'#010+
+ '**1M<x>_Set language mode to <x>'#010+
+ '**2Mfpc_Free Pascal dialect (default)'#010+
+ '**2Mobjfpc_FPC mode with Object Pascal support'#010+
+ '**2Mdelphi_Delphi 7 compatib','ility mode'#010+
+ '**2Mtp_TP/BP 7.0 compatibility mode'#010+
+ '**2Mmacpas_Macintosh Pascal dialects compatibility mode'#010+
+ '**1n_Do not read the default config files'#010+
+ '**1N<x>_Node tree optimizations'#010+
+ '**2Nu_Unroll loops'#010+
+ '**1o<x>_Change the name of the executable pr','oduced to <x>'#010+
+ '**1O<x>_Optimizations:'#010+
+ '**2O-_Disable optimizations'#010+
+ '**2O1_Level 1 optimizations (quick and debugger friendly)'#010+
+ '**2O2_Level 2 optimizations (-O1 + quick optimizations)'#010+
+ '**2O3_Level 3 optimizations (-O2 + slow optimizations)'#010+
+ '**2Oa<','x>=<y>_Set alignment'#010+
+ '**2Oo[NO]<x>_Enable or disable optimizations, see fpc -i for possible '+
+ 'values'#010+
+ '**2Op<x>_Set target cpu for optimizing, see fpc -i for possible values'+
+ #010+
+ '**2OW<x>_Generate whole-program optimization feedback for optimization'+
+ ' ','<x>, see fpc -i for possible values'#010+
+ '**2Ow<x>_Perform whole-program optimization <x>, see fpc -i for possib'+
+ 'le values'#010+
+ '**2Os_Optimize for size rather than speed'#010+
+ '**1pg_Generate profile code for gprof (defines FPC_PROFILE)'#010+
+ '**1R<x>_Assembler read','ing style:'#010+
+ '**2Rdefault_Use default assembler for target'#010+
+ '3*2Ratt_Read AT&T style assembler'#010+
+ '3*2Rintel_Read Intel style assembler'#010+
+ '6*2RMOT_Read motorola style assembler'#010+
+ '**1S<x>_Syntax options:'#010+
+ '**2S2_Same as -Mobjfpc'#010+
+ '**2Sc_Support operators like',' C (*=,+=,/= and -=)'#010+
+ '**2Sa_Turn on assertions'#010+
+ '**2Sd_Same as -Mdelphi'#010+
+ '**2Se<x>_Error options. <x> is a combination of the following:'#010+
+ '**3*_<n> : Compiler halts after the <n> errors (default is 1)'#010+
+ '**3*_w : Compiler also halts after warnings'#010+
+ '**','3*_n : Compiler also halts after notes'#010+
+ '**3*_h : Compiler also halts after hints'#010+
+ '**2Sg_Enable LABEL and GOTO (default in -Mtp and -Mdelphi)'#010+
+ '**2Sh_Use ansistrings by default instead of shortstrings'#010+
+ '**2Si_Turn on inlining of procedures/functio','ns declared as "inline"'#010+
+ '**2Sk_Load fpcylix unit'#010+
+ '**2SI<x>_Set interface style to <x>'#010+
+ '**3SIcom_COM compatible interface (default)'#010+
+ '**3SIcorba_CORBA compatible interface'#010+
+ '**2Sm_Support macros like C (global)'#010+
+ '**2So_Same as -Mtp'#010+
+ '**2Ss_Constructor ','name must be init (destructor must be done)'#010+
+ '**2Sx_Enable exception keywords (default in Delphi/ObjFPC modes)'#010+
+ '**2Sy_@<pointer> returns a typed pointer, same as $T+'#010+
+ '**1s_Do not call assembler and linker'#010+
+ '**2sh_Generate script to link on host'#010+
+ '*','*2st_Generate script to link on target'#010+
+ '**2sr_Skip register allocation phase (use with -alr)'#010+
+ '**1T<x>_Target operating system:'#010+
+ '3*2Tdarwin_Darwin/Mac OS X'#010+
+ '3*2Temx_OS/2 via EMX (including EMX/RSX extender)'#010+
+ '3*2Tfreebsd_FreeBSD'#010+
+ '3*2Tgo32v2_Version',' 2 of DJ Delorie DOS extender'#010+
+ '3*2Tiphonesim_ iPhoneSimulator from iOS SDK 3.2+ (older versions: -Tda'+
+ 'rwin)'#010+
+ '3*2Tlinux_Linux'#010+
+ '3*2Tnetbsd_NetBSD'#010+
+ '3*2Tnetware_Novell Netware Module (clib)'#010+
+ '3*2Tnetwlibc_Novell Netware Module (libc)'#010+
+ '3*2Topenbsd_OpenB','SD'#010+
+ '3*2Tos2_OS/2 / eComStation'#010+
+ '3*2Tsunos_SunOS/Solaris'#010+
+ '3*2Tsymbian_Symbian OS'#010+
+ '3*2Tsolaris_Solaris'#010+
+ '3*2Twatcom_Watcom compatible DOS extender'#010+
+ '3*2Twdosx_WDOSX DOS extender'#010+
+ '3*2Twin32_Windows 32 Bit'#010+
+ '3*2Twince_Windows CE'#010+
+ '4*2Tdarwin_Darwin/Mac OS X',#010+
+ '4*2Tlinux_Linux'#010+
+ '4*2Twin64_Win64 (64 bit Windows systems)'#010+
+ '6*2Tamiga_Commodore Amiga'#010+
+ '6*2Tatari_Atari ST/STe/TT'#010+
+ '6*2Tlinux_Linux'#010+
+ '6*2Tpalmos_PalmOS'#010+
+ 'A*2Tdarwin_Darwin/iPhoneOS/iOS'#010+
+ 'A*2Tlinux_Linux'#010+
+ 'A*2Twince_Windows CE'#010+
+ 'P*2Tamiga_AmigaOS'#010+
+ 'P*2Tdarwin','_Darwin/Mac OS X'#010+
+ 'P*2Tlinux_Linux'#010+
+ 'P*2Tmacos_Mac OS (classic)'#010+
+ 'P*2Tmorphos_MorphOS'#010+
+ 'S*2Tsolaris_Solaris'#010+
+ 'S*2Tlinux_Linux'#010+
+ '**1u<x>_Undefines the symbol <x>'#010+
+ '**1U_Unit options:'#010+
+ '**2Un_Do not check where the unit name matches the file name'#010+
+ '**2Ur_Gener','ate release unit files (never automatically recompiled)'#010+
+ '**2Us_Compile a system unit'#010+
+ '**1v<x>_Be verbose. <x> is a combination of the following letters:'#010+
+ '**2*_e : Show errors (default) 0 : Show nothing (except errors)'#010+
+ '**2*_w : Show warni','ngs u : Show unit info'#010+
+ '**2*_n : Show notes t : Show tried/used files'#010+
+ '**2*_h : Show hints c : Show conditionals'#010+
+ '**2*_i : Show general info d : Show debug info'#010+
+ '**2*_l : Show linenumber','s r : Rhide/GCC compatibility mod'+
+ 'e'#010+
+ '**2*_s : Show time stamps q : Show message numbers'#010+
+ '**2*_a : Show everything x : Executable info (Win32 only)'#010+
+ '**2*_b : Write file names messages p : Write tree.log with p','arse t'+
+ 'ree'#010+
+ '**2*_ with full path v : Write fpcdebug.txt with'#010+
+ '**2*_ lots of debugging info'#010+
+ '**2*_m<x>,<y> : Don'#039't show messages numbered <x> and <y>'#010+
+ '**1W<x>_Target-specific options (targets)'#010+
+ '3*','2WA_Specify native type application (Windows)'#010+
+ '4*2WA_Specify native type application (Windows)'#010+
+ 'A*2WA_Specify native type application (Windows)'#010+
+ '3*2Wb_Create a bundle instead of a library (Darwin)'#010+
+ 'P*2Wb_Create a bundle instead of a library (Da','rwin)'#010+
+ 'p*2Wb_Create a bundle instead of a library (Darwin)'#010+
+ 'A*2Wb_Create a bundle instead of a library (Darwin)'#010+
+ '4*2Wb_Create a bundle instead of a library (Darwin)'#010+
+ '3*2WB_Create a relocatable image (Windows, Symbian)'#010+
+ '3*2WBxxxx_Set image base t','o xxxx (Windows, Symbian)'#010+
+ '4*2WB_Create a relocatable image (Windows)'#010+
+ '4*2WBxxxx_Set image base to xxxx (Windows)'#010+
+ 'A*2WB_Create a relocatable image (Windows, Symbian)'#010+
+ 'A*2WBxxxx_Set image base to xxxx (Windows, Symbian)'#010+
+ '3*2WC_Specify console ty','pe application (EMX, OS/2, Windows)'#010+
+ '4*2WC_Specify console type application (EMX, OS/2, Windows)'#010+
+ 'A*2WC_Specify console type application (Windows)'#010+
+ 'P*2WC_Specify console type application (Classic Mac OS)'#010+
+ '3*2WD_Use DEFFILE to export functions o','f DLL or EXE (Windows)'#010+
+ '4*2WD_Use DEFFILE to export functions of DLL or EXE (Windows)'#010+
+ 'A*2WD_Use DEFFILE to export functions of DLL or EXE (Windows)'#010+
+ '3*2We_Use external resources (Darwin)'#010+
+ '4*2We_Use external resources (Darwin)'#010+
+ 'A*2We_Use externa','l resources (Darwin)'#010+
+ 'P*2We_Use external resources (Darwin)'#010+
+ 'p*2We_Use external resources (Darwin)'#010+
+ '3*2WF_Specify full-screen type application (EMX, OS/2)'#010+
+ '3*2WG_Specify graphic type application (EMX, OS/2, Windows)'#010+
+ '4*2WG_Specify graphic type a','pplication (EMX, OS/2, Windows)'#010+
+ 'A*2WG_Specify graphic type application (Windows)'#010+
+ 'P*2WG_Specify graphic type application (Classic Mac OS)'#010+
+ '3*2Wi_Use internal resources (Darwin)'#010+
+ '4*2Wi_Use internal resources (Darwin)'#010+
+ 'A*2Wi_Use internal resource','s (Darwin)'#010+
+ 'P*2Wi_Use internal resources (Darwin)'#010+
+ 'p*2Wi_Use internal resources (Darwin)'#010+
+ '3*2WI_Turn on/off the usage of import sections (Windows)'#010+
+ '4*2WI_Turn on/off the usage of import sections (Windows)'#010+
+ 'A*2WI_Turn on/off the usage of import s','ections (Windows)'#010+
+ '3*2WN_Do not generate relocation code, needed for debugging (Windows)'#010+
+ '4*2WN_Do not generate relocation code, needed for debugging (Windows)'#010+
+ 'A*2WN_Do not generate relocation code, needed for debugging (Windows)'#010+
+ 'A*2Wpxxxx_Sp','ecify the controller type, see fpc -i for possible value'+
+ 's'#010+
+ 'V*2Wpxxxx_Specify the controller type, see fpc -i for possible values'#010+
+ '3*2WR_Generate relocation code (Windows)'#010+
+ '4*2WR_Generate relocation code (Windows)'#010+
+ 'A*2WR_Generate relocation code',' (Windows)'#010+
+ 'P*2WT_Specify MPW tool type application (Classic Mac OS)'#010+
+ '**2WX_Enable executable stack (Linux)'#010+
+ '**1X_Executable options:'#010+
+ '**2Xc_Pass --shared/-dynamic to the linker (BeOS, Darwin, FreeBSD, Lin'+
+ 'ux)'#010+
+ '**2Xd_Do not use standard library s','earch path (needed for cross comp'+
+ 'ile)'#010+
+ '**2Xe_Use external linker'#010+
+ '**2Xg_Create debuginfo in a separate file and add a debuglink section '+
+ 'to executable'#010+
+ '**2XD_Try to link units dynamically (defines FPC_LINK_DYNAMIC)'#010+
+ '**2Xi_Use internal linke','r'#010+
+ '**2Xm_Generate link map'#010+
+ '**2XM<x>_Set the name of the '#039'main'#039' program routine (default i'+
+ 's '#039'main'#039')'#010+
+ '**2XP<x>_Prepend the binutils names with the prefix <x>'#010+
+ '**2Xr<x>_Set the linker'#039's rlink-path to <x> (needed for cross comp'+
+ 'ile, see the ld manu','al for more information) (BeOS, Linux)'#010+
+ '**2XR<x>_Prepend <x> to all linker search paths (BeOS, Darwin, FreeBSD'+
+ ', Linux, Mac OS, Solaris)'#010+
+ '**2Xs_Strip all symbols from executable'#010+
+ '**2XS_Try to link units statically (default, defines FPC_LINK_STA','TIC'+
+ ')'#010+
+ '**2Xt_Link with static libraries (-static is passed to linker)'#010+
+ '**2XX_Try to smartlink units (defines FPC_LINK_SMART)'#010+
+ '**1*_'#010+
+ '**1?_Show this help'#010+
+ '**1h_Shows this help without waiting'
+);
diff --git a/closures/compiler/nadd.pas b/closures/compiler/nadd.pas
new file mode 100644
index 0000000000..28666600c8
--- /dev/null
+++ b/closures/compiler/nadd.pas
@@ -0,0 +1,3070 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Type checking and simplification for add nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit nadd;
+
+{$i fpcdefs.inc}
+
+{ define addstringopt}
+
+interface
+
+ uses
+ node,symtype;
+
+ type
+ taddnode = class(tbinopnode)
+ private
+ resultrealdefderef: tderef;
+ function pass_typecheck_internal:tnode;
+ public
+ resultrealdef : tdef;
+ constructor create(tt : tnodetype;l,r : tnode);override;
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderefimpl;override;
+ procedure derefimpl;override;
+ function pass_1 : tnode;override;
+ function pass_typecheck:tnode;override;
+ function simplify(forinline: boolean) : tnode;override;
+ function dogetcopy : tnode;override;
+ function docompare(p: tnode): boolean; override;
+ {$ifdef state_tracking}
+ function track_state_pass(exec_known:boolean):boolean;override;
+ {$endif}
+ protected
+ { override the following if you want to implement }
+ { parts explicitely in the code generator (JM) }
+ function first_addstring: tnode; virtual;
+ function first_addset: tnode; virtual;
+ { only implements "muln" nodes, the rest always has to be done in }
+ { the code generator for performance reasons (JM) }
+ function first_add64bitint: tnode; virtual;
+
+ { override and return false if you can handle 32x32->64 }
+ { bit multiplies directly in your code generator. If }
+ { this function is overridden to return false, you can }
+ { get multiplies with left/right both s32bit or u32bit, }
+ { and resultdef of the muln s64bit or u64bit }
+ function use_generic_mul32to64: boolean; virtual;
+
+ { This routine calls internal runtime library helpers
+ for all floating point arithmetic in the case
+ where the emulation switches is on. Otherwise
+ returns nil, and everything must be done in
+ the code generation phase.
+ }
+ function first_addfloat : tnode; virtual;
+ private
+ { checks whether a muln can be calculated as a 32bit }
+ { * 32bit -> 64 bit }
+ function try_make_mul32to64: boolean;
+ { Match against the ranges, i.e.:
+ var a:1..10;
+ begin
+ if a>0 then
+ ...
+ always evaluates to true. (DM)
+ }
+ function cmp_of_disjunct_ranges(var res : boolean) : boolean;
+ end;
+ taddnodeclass = class of taddnode;
+
+ var
+ { caddnode is used to create nodes of the add type }
+ { the virtual constructor allows to assign }
+ { another class type to caddnode => processor }
+ { specific node types can be created }
+ caddnode : taddnodeclass = taddnode;
+
+implementation
+
+ uses
+{$IFNDEF USE_FAKE_SYSUTILS}
+ sysutils,
+{$ELSE}
+ fksysutl,
+{$ENDIF}
+ globtype,systems,constexp,
+ cutils,verbose,globals,widestr,
+ symconst,symdef,symsym,symtable,defutil,defcmp,
+ cgbase,
+ htypechk,pass_1,
+ nld,nbas,nmat,ncnv,ncon,nset,nopt,ncal,ninl,nmem,nutils,
+ {$ifdef state_tracking}
+ nstate,
+ {$endif}
+ cpuinfo,procinfo;
+
+
+{*****************************************************************************
+ TADDNODE
+*****************************************************************************}
+
+{$maxfpuregisters 0}
+
+ function getbestreal(t1,t2 : tdef) : tdef;
+ const
+ floatweight : array[tfloattype] of byte =
+ (2,3,4,5,0,1,6);
+ begin
+ if t1.typ=floatdef then
+ begin
+ result:=t1;
+ if t2.typ=floatdef then
+ begin
+ { when a comp or currency is used, use always the
+ best float type to calculate the result }
+ if (tfloatdef(t2).floattype in [s64comp,s64currency]) or
+ (tfloatdef(t2).floattype in [s64comp,s64currency]) then
+ result:=pbestrealtype^
+ else
+ if floatweight[tfloatdef(t2).floattype]>floatweight[tfloatdef(t1).floattype] then
+ result:=t2;
+ end;
+ end
+ else if t2.typ=floatdef then
+ result:=t2
+ else internalerror(200508061);
+ end;
+
+
+ constructor taddnode.create(tt : tnodetype;l,r : tnode);
+ begin
+ inherited create(tt,l,r);
+ end;
+
+
+ constructor taddnode.ppuload(t: tnodetype; ppufile: tcompilerppufile);
+ begin
+ inherited ppuload(t, ppufile);
+ ppufile.getderef(resultrealdefderef);
+ end;
+
+
+ procedure taddnode.ppuwrite(ppufile: tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putderef(resultrealdefderef);
+ end;
+
+
+ procedure taddnode.buildderefimpl;
+ begin
+ inherited buildderefimpl;
+ resultrealdefderef.build(resultrealdef);
+ end;
+
+
+ procedure taddnode.derefimpl;
+ begin
+ inherited derefimpl;
+ resultrealdef:=tdef(resultrealdefderef.resolve);
+ end;
+
+
+ function taddnode.cmp_of_disjunct_ranges(var res : boolean) : boolean;
+ var
+ hp : tnode;
+ realdef : tdef;
+ v : tconstexprint;
+ begin
+ result:=false;
+ { check for comparision with known result because the ranges of the operands don't overlap }
+ if (is_constintnode(right) and (left.resultdef.typ=orddef) and
+ { don't ignore type checks }
+ is_subequal(right.resultdef,left.resultdef)) or
+ (is_constintnode(left) and (right.resultdef.typ=orddef) and
+ { don't ignore type checks }
+ is_subequal(left.resultdef,right.resultdef)) then
+ begin
+ if is_constintnode(right) then
+ begin
+ hp:=left;
+ v:=Tordconstnode(right).value;
+ end
+ else
+ begin
+ hp:=right;
+ v:=Tordconstnode(left).value;
+ end;
+
+ realdef:=hp.resultdef;
+ { stop with finding the real def when we either encounter
+ a) an explicit type conversion (then the value has to be
+ re-interpreted)
+ b) an "absolute" type conversion (also requires
+ re-interpretation)
+ }
+ while (hp.nodetype=typeconvn) and
+ ([nf_internal,nf_explicit,nf_absolute] * hp.flags = []) do
+ begin
+ hp:=ttypeconvnode(hp).left;
+ realdef:=hp.resultdef;
+ end;
+ if is_constintnode(left) then
+ with torddef(realdef) do
+ case nodetype of
+ ltn:
+ if v<low then
+ begin
+ result:=true;
+ res:=true;
+ end
+ else if v>=high then
+ begin
+ result:=true;
+ res:=false;
+ end;
+ lten:
+ if v<=low then
+ begin
+ result:=true;
+ res:=true;
+ end
+ else if v>high then
+ begin
+ result:=true;
+ res:=false;
+ end;
+ gtn:
+ if v<=low then
+ begin
+ result:=true;
+ res:=false;
+ end
+ else if v>high then
+ begin
+ result:=true;
+ res:=true;
+ end;
+ gten :
+ if v<low then
+ begin
+ result:=true;
+ res:=false;
+ end
+ else if v>=high then
+ begin
+ result:=true;
+ res:=true;
+ end;
+ equaln:
+ if (v<low) or (v>high) then
+ begin
+ result:=true;
+ res:=false;
+ end;
+ unequaln:
+ if (v<low) or (v>high) then
+ begin
+ result:=true;
+ res:=true;
+ end;
+ end
+ else
+ with torddef(realdef) do
+ case nodetype of
+ ltn:
+ if high<v then
+ begin
+ result:=true;
+ res:=true;
+ end
+ else if low>=v then
+ begin
+ result:=true;
+ res:=false;
+ end;
+ lten:
+ if high<=v then
+ begin
+ result:=true;
+ res:=true;
+ end
+ else if low>v then
+ begin
+ result:=true;
+ res:=false;
+ end;
+ gtn:
+ if high<=v then
+ begin
+ result:=true;
+ res:=false;
+ end
+ else if low>v then
+ begin
+ result:=true;
+ res:=true;
+ end;
+ gten:
+ if high<v then
+ begin
+ result:=true;
+ res:=false;
+ end
+ else if low>=v then
+ begin
+ result:=true;
+ res:=true;
+ end;
+ equaln:
+ if (v<low) or (v>high) then
+ begin
+ result:=true;
+ res:=false;
+ end;
+ unequaln:
+ if (v<low) or (v>high) then
+ begin
+ result:=true;
+ res:=true;
+ end;
+ end;
+ end;
+ end;
+
+
+ function taddnode.simplify(forinline : boolean) : tnode;
+ var
+ t : tnode;
+ lt,rt : tnodetype;
+ rd,ld : tdef;
+ rv,lv,v : tconstexprint;
+ rvd,lvd : bestreal;
+ ws1,ws2 : pcompilerwidestring;
+ concatstrings : boolean;
+ c1,c2 : array[0..1] of char;
+ s1,s2 : pchar;
+ l1,l2 : longint;
+ resultset : Tconstset;
+ res,
+ b : boolean;
+ begin
+ result:=nil;
+
+ { load easier access variables }
+ rd:=right.resultdef;
+ ld:=left.resultdef;
+ rt:=right.nodetype;
+ lt:=left.nodetype;
+
+ if (nodetype = slashn) and
+ (((rt = ordconstn) and
+ (tordconstnode(right).value = 0)) or
+ ((rt = realconstn) and
+ (trealconstnode(right).value_real = 0.0))) then
+ begin
+ if floating_point_range_check_error then
+ begin
+ result:=crealconstnode.create(1,pbestrealtype^);
+ Message(parser_e_division_by_zero);
+ exit;
+ end;
+ end;
+
+ { both are int constants }
+ if (
+ (
+ is_constintnode(left) and
+ is_constintnode(right)
+ ) or
+ (
+ is_constboolnode(left) and
+ is_constboolnode(right) and
+ (nodetype in [slashn,ltn,lten,gtn,gten,equaln,unequaln,andn,xorn,orn])
+ ) or
+ (
+ is_constenumnode(left) and
+ is_constenumnode(right) and
+ allowenumop(nodetype))
+ ) or
+ (
+ (lt = pointerconstn) and
+ is_constintnode(right) and
+ (nodetype in [addn,subn])
+ ) or
+ (
+ (lt in [pointerconstn,niln]) and
+ (rt in [pointerconstn,niln]) and
+ (nodetype in [ltn,lten,gtn,gten,equaln,unequaln,subn])
+ ) then
+ begin
+ t:=nil;
+
+ { load values }
+ case lt of
+ ordconstn:
+ lv:=tordconstnode(left).value;
+ pointerconstn:
+ lv:=tpointerconstnode(left).value;
+ niln:
+ lv:=0;
+ else
+ internalerror(2002080202);
+ end;
+ case rt of
+ ordconstn:
+ rv:=tordconstnode(right).value;
+ pointerconstn:
+ rv:=tpointerconstnode(right).value;
+ niln:
+ rv:=0;
+ else
+ internalerror(2002080203);
+ end;
+ { type checking already took care of multiplying }
+ { integer constants with pointeddef.size if necessary }
+ case nodetype of
+ addn :
+ begin
+ v:=lv+rv;
+ if v.overflow then
+ begin
+ Message(parser_e_arithmetic_operation_overflow);
+ { Recover }
+ t:=genintconstnode(0)
+ end
+ else if (lt=pointerconstn) then
+ t := cpointerconstnode.create(qword(v),resultdef)
+ else
+ if is_integer(ld) then
+ t := create_simplified_ord_const(v,resultdef,forinline)
+ else
+ t := cordconstnode.create(v,resultdef,(ld.typ<>enumdef));
+ end;
+ subn :
+ begin
+ v:=lv-rv;
+ if v.overflow then
+ begin
+ Message(parser_e_arithmetic_operation_overflow);
+ { Recover }
+ t:=genintconstnode(0)
+ end
+ else if (lt=pointerconstn) then
+ { pointer-pointer results in an integer }
+ if (rt=pointerconstn) then
+ begin
+ if not(nf_has_pointerdiv in flags) then
+ internalerror(2008030101);
+ t := cpointerconstnode.create(qword(v),resultdef)
+ end
+ else
+ t := cpointerconstnode.create(qword(v),resultdef)
+ else
+ if is_integer(ld) then
+ t := create_simplified_ord_const(v,resultdef,forinline)
+ else
+ t:=cordconstnode.create(v,resultdef,(ld.typ<>enumdef));
+ end;
+ muln :
+ begin
+ v:=lv*rv;
+ if v.overflow then
+ begin
+ message(parser_e_arithmetic_operation_overflow);
+ { Recover }
+ t:=genintconstnode(0)
+ end
+ else
+ t := create_simplified_ord_const(v,resultdef,forinline)
+ end;
+ xorn :
+ if is_integer(ld) then
+ t := create_simplified_ord_const(lv xor rv,resultdef,forinline)
+ else
+ t:=cordconstnode.create(lv xor rv,resultdef,true);
+ orn :
+ if is_integer(ld) then
+ t:=create_simplified_ord_const(lv or rv,resultdef,forinline)
+ else
+ t:=cordconstnode.create(lv or rv,resultdef,true);
+ andn :
+ if is_integer(ld) then
+ t:=create_simplified_ord_const(lv and rv,resultdef,forinline)
+ else
+ t:=cordconstnode.create(lv and rv,resultdef,true);
+ ltn :
+ t:=cordconstnode.create(ord(lv<rv),pasbool8type,true);
+ lten :
+ t:=cordconstnode.create(ord(lv<=rv),pasbool8type,true);
+ gtn :
+ t:=cordconstnode.create(ord(lv>rv),pasbool8type,true);
+ gten :
+ t:=cordconstnode.create(ord(lv>=rv),pasbool8type,true);
+ equaln :
+ t:=cordconstnode.create(ord(lv=rv),pasbool8type,true);
+ unequaln :
+ t:=cordconstnode.create(ord(lv<>rv),pasbool8type,true);
+ slashn :
+ begin
+ { int/int becomes a real }
+ rvd:=rv;
+ lvd:=lv;
+ t:=crealconstnode.create(lvd/rvd,resultrealdef);
+ end;
+ else
+ internalerror(2008022101);
+ end;
+ result:=t;
+ exit;
+ end
+ else if cmp_of_disjunct_ranges(res) then
+ begin
+ if res then
+ t:=Cordconstnode.create(1,pasbool8type,true)
+ else
+ t:=Cordconstnode.create(0,pasbool8type,true);
+ { don't do this optimization, if the variable expression might
+ have a side effect }
+ if (is_constintnode(left) and might_have_sideeffects(right)) or
+ (is_constintnode(right) and might_have_sideeffects(left)) then
+ t.free
+ else
+ result:=t;
+ exit;
+ end;
+
+ { Add,Sub,Mul with constant 0, 1 or -1? }
+ if is_constintnode(right) and is_integer(left.resultdef) then
+ begin
+ if tordconstnode(right).value = 0 then
+ begin
+ case nodetype of
+ addn,subn:
+ result := left.getcopy;
+ muln:
+ result:=cordconstnode.create(0,resultdef,true);
+ end;
+ end
+ else if tordconstnode(right).value = 1 then
+ begin
+ case nodetype of
+ muln:
+ result := left.getcopy;
+ end;
+ end
+{$ifdef VER2_2}
+ else if (tordconstnode(right).value.svalue = -1) and (tordconstnode(right).value.signed) then
+{$else}
+ else if tordconstnode(right).value = -1 then
+{$endif}
+ begin
+ case nodetype of
+ muln:
+ result := cunaryminusnode.create(left.getcopy);
+ end;
+ end;
+ if assigned(result) then
+ exit;
+ end;
+ if is_constintnode(left) and is_integer(right.resultdef) then
+ begin
+ if tordconstnode(left).value = 0 then
+ begin
+ case nodetype of
+ addn:
+ result := right.getcopy;
+ subn:
+ result := cunaryminusnode.create(right.getcopy);
+ muln:
+ result:=cordconstnode.create(0,right.resultdef,true);
+ end;
+ end
+ else if tordconstnode(left).value = 1 then
+ begin
+ case nodetype of
+ muln:
+ result := right.getcopy;
+ end;
+ end
+{$ifdef VER2_2}
+ else if (tordconstnode(left).value.svalue = -1) and (tordconstnode(left).value.signed) then
+{$else}
+ else if tordconstnode(left).value = -1 then
+{$endif}
+ begin
+ case nodetype of
+ muln:
+ result := cunaryminusnode.create(right.getcopy);
+ end;
+ end;
+ if assigned(result) then
+ exit;
+ end;
+
+ { both real constants ? }
+ if (lt=realconstn) and (rt=realconstn) then
+ begin
+ lvd:=trealconstnode(left).value_real;
+ rvd:=trealconstnode(right).value_real;
+ case nodetype of
+ addn :
+ t:=crealconstnode.create(lvd+rvd,resultrealdef);
+ subn :
+ t:=crealconstnode.create(lvd-rvd,resultrealdef);
+ muln :
+ t:=crealconstnode.create(lvd*rvd,resultrealdef);
+ starstarn:
+ begin
+ if lvd<0 then
+ begin
+ Message(parser_e_invalid_float_operation);
+ t:=crealconstnode.create(0,resultrealdef);
+ end
+ else if lvd=0 then
+ t:=crealconstnode.create(1.0,resultrealdef)
+ else
+ t:=crealconstnode.create(exp(ln(lvd)*rvd),resultrealdef);
+ end;
+ slashn :
+ t:=crealconstnode.create(lvd/rvd,resultrealdef);
+ ltn :
+ t:=cordconstnode.create(ord(lvd<rvd),pasbool8type,true);
+ lten :
+ t:=cordconstnode.create(ord(lvd<=rvd),pasbool8type,true);
+ gtn :
+ t:=cordconstnode.create(ord(lvd>rvd),pasbool8type,true);
+ gten :
+ t:=cordconstnode.create(ord(lvd>=rvd),pasbool8type,true);
+ equaln :
+ t:=cordconstnode.create(ord(lvd=rvd),pasbool8type,true);
+ unequaln :
+ t:=cordconstnode.create(ord(lvd<>rvd),pasbool8type,true);
+ else
+ internalerror(2008022102);
+ end;
+ result:=t;
+ exit;
+ end;
+
+ { first, we handle widestrings, so we can check later for }
+ { stringconstn only }
+
+ { widechars are converted above to widestrings too }
+ { this isn't ver y efficient, but I don't think }
+ { that it does matter that much (FK) }
+ if (lt=stringconstn) and (rt=stringconstn) and
+ (tstringconstnode(left).cst_type in [cst_widestring,cst_unicodestring]) and
+ (tstringconstnode(right).cst_type in [cst_widestring,cst_unicodestring]) then
+ begin
+ initwidestring(ws1);
+ initwidestring(ws2);
+ copywidestring(pcompilerwidestring(tstringconstnode(left).value_str),ws1);
+ copywidestring(pcompilerwidestring(tstringconstnode(right).value_str),ws2);
+ case nodetype of
+ addn :
+ begin
+ concatwidestrings(ws1,ws2);
+ t:=cstringconstnode.createwstr(ws1);
+ end;
+ ltn :
+ t:=cordconstnode.create(byte(comparewidestrings(ws1,ws2)<0),pasbool8type,true);
+ lten :
+ t:=cordconstnode.create(byte(comparewidestrings(ws1,ws2)<=0),pasbool8type,true);
+ gtn :
+ t:=cordconstnode.create(byte(comparewidestrings(ws1,ws2)>0),pasbool8type,true);
+ gten :
+ t:=cordconstnode.create(byte(comparewidestrings(ws1,ws2)>=0),pasbool8type,true);
+ equaln :
+ t:=cordconstnode.create(byte(comparewidestrings(ws1,ws2)=0),pasbool8type,true);
+ unequaln :
+ t:=cordconstnode.create(byte(comparewidestrings(ws1,ws2)<>0),pasbool8type,true);
+ else
+ internalerror(2008022103);
+ end;
+ donewidestring(ws1);
+ donewidestring(ws2);
+ result:=t;
+ exit;
+ end;
+
+ { concating strings ? }
+ concatstrings:=false;
+
+ if (lt=ordconstn) and (rt=ordconstn) and
+ is_char(ld) and is_char(rd) then
+ begin
+ c1[0]:=char(int64(tordconstnode(left).value));
+ c1[1]:=#0;
+ l1:=1;
+ c2[0]:=char(int64(tordconstnode(right).value));
+ c2[1]:=#0;
+ l2:=1;
+ s1:=@c1[0];
+ s2:=@c2[0];
+ concatstrings:=true;
+ end
+ else if (lt=stringconstn) and (rt=ordconstn) and is_char(rd) then
+ begin
+ s1:=tstringconstnode(left).value_str;
+ l1:=tstringconstnode(left).len;
+ c2[0]:=char(int64(tordconstnode(right).value));
+ c2[1]:=#0;
+ s2:=@c2[0];
+ l2:=1;
+ concatstrings:=true;
+ end
+ else if (lt=ordconstn) and (rt=stringconstn) and is_char(ld) then
+ begin
+ c1[0]:=char(int64(tordconstnode(left).value));
+ c1[1]:=#0;
+ l1:=1;
+ s1:=@c1[0];
+ s2:=tstringconstnode(right).value_str;
+ l2:=tstringconstnode(right).len;
+ concatstrings:=true;
+ end
+ else if (lt=stringconstn) and (rt=stringconstn) then
+ begin
+ s1:=tstringconstnode(left).value_str;
+ l1:=tstringconstnode(left).len;
+ s2:=tstringconstnode(right).value_str;
+ l2:=tstringconstnode(right).len;
+ concatstrings:=true;
+ end;
+ if concatstrings then
+ begin
+ case nodetype of
+ addn :
+ begin
+ t:=cstringconstnode.createpchar(concatansistrings(s1,s2,l1,l2),l1+l2);
+ typecheckpass(t);
+ tstringconstnode(t).changestringtype(resultdef);
+ end;
+ ltn :
+ t:=cordconstnode.create(byte(compareansistrings(s1,s2,l1,l2)<0),pasbool8type,true);
+ lten :
+ t:=cordconstnode.create(byte(compareansistrings(s1,s2,l1,l2)<=0),pasbool8type,true);
+ gtn :
+ t:=cordconstnode.create(byte(compareansistrings(s1,s2,l1,l2)>0),pasbool8type,true);
+ gten :
+ t:=cordconstnode.create(byte(compareansistrings(s1,s2,l1,l2)>=0),pasbool8type,true);
+ equaln :
+ t:=cordconstnode.create(byte(compareansistrings(s1,s2,l1,l2)=0),pasbool8type,true);
+ unequaln :
+ t:=cordconstnode.create(byte(compareansistrings(s1,s2,l1,l2)<>0),pasbool8type,true);
+ else
+ internalerror(2008022104);
+ end;
+ result:=t;
+ exit;
+ end;
+
+ { set constant evaluation }
+ if (right.nodetype=setconstn) and
+ not assigned(tsetconstnode(right).left) and
+ (left.nodetype=setconstn) and
+ not assigned(tsetconstnode(left).left) then
+ begin
+ case nodetype of
+ addn :
+ begin
+ resultset:=tsetconstnode(right).value_set^ + tsetconstnode(left).value_set^;
+ t:=csetconstnode.create(@resultset,resultdef);
+ end;
+ muln :
+ begin
+ resultset:=tsetconstnode(right).value_set^ * tsetconstnode(left).value_set^;
+ t:=csetconstnode.create(@resultset,resultdef);
+ end;
+ subn :
+ begin
+ resultset:=tsetconstnode(left).value_set^ - tsetconstnode(right).value_set^;
+ t:=csetconstnode.create(@resultset,resultdef);
+ end;
+ symdifn :
+ begin
+ resultset:=tsetconstnode(right).value_set^ >< tsetconstnode(left).value_set^;
+ t:=csetconstnode.create(@resultset,resultdef);
+ end;
+ unequaln :
+ begin
+ b:=tsetconstnode(right).value_set^ <> tsetconstnode(left).value_set^;
+ t:=cordconstnode.create(byte(b),pasbool8type,true);
+ end;
+ equaln :
+ begin
+ b:=tsetconstnode(right).value_set^ = tsetconstnode(left).value_set^;
+ t:=cordconstnode.create(byte(b),pasbool8type,true);
+ end;
+ lten :
+ begin
+ b:=tsetconstnode(left).value_set^ <= tsetconstnode(right).value_set^;
+ t:=cordconstnode.create(byte(b),pasbool8type,true);
+ end;
+ gten :
+ begin
+ b:=tsetconstnode(left).value_set^ >= tsetconstnode(right).value_set^;
+ t:=cordconstnode.create(byte(b),pasbool8type,true);
+ end;
+ else
+ internalerror(2008022105);
+ end;
+ result:=t;
+ exit;
+ end;
+
+ { slow simplifications }
+ if (cs_opt_level2 in current_settings.optimizerswitches) then
+ begin
+ { the comparison is might be expensive and the nodes are usually only
+ equal if some previous optimizations were done so don't check
+ this simplification always
+ }
+ if is_boolean(left.resultdef) and is_boolean(right.resultdef) and
+ { since the expressions might have sideeffects, we may only remove them
+ if short boolean evaluation is turned on }
+ (nf_short_bool in flags) then
+ begin
+ if left.isequal(right) then
+ begin
+ case nodetype of
+ andn,orn:
+ begin
+ result:=left;
+ left:=nil;
+ exit;
+ end;
+ {
+ xorn:
+ begin
+ result:=cordconstnode.create(0,resultdef,true);
+ exit;
+ end;
+ }
+ end;
+ end;
+ end;
+
+ { using sqr(x) for reals instead of x*x might reduces register pressure and/or
+ memory accesses while sqr(<real>) has no drawback }
+ if
+{$ifdef cpufpemu}
+ (current_settings.fputype<>fpu_soft) and
+ not(cs_fp_emulation in current_settings.moduleswitches) and
+{$endif cpufpemu}
+ (nodetype=muln) and
+ is_real(left.resultdef) and is_real(right.resultdef) and
+ left.isequal(right) and
+ not(might_have_sideeffects(left)) then
+ begin
+ result:=cinlinenode.create(in_sqr_real,false,left);
+ left:=nil;
+ exit;
+ end;
+{$ifdef cpurox}
+ { optimize (i shl x) or (i shr (bitsizeof(i)-x)) into rol(x,i) (and different flavours with shl/shr swapped etc.) }
+ if (nodetype=orn)
+{$ifndef cpu64bitalu}
+ and (left.resultdef.typ=orddef) and
+ not(torddef(left.resultdef).ordtype in [s64bit,u64bit,scurrency])
+{$endif cpu64bitalu}
+ then
+ begin
+ if (left.nodetype=shrn) and (right.nodetype=shln) and
+ is_constintnode(tshlshrnode(left).right) and
+ is_constintnode(tshlshrnode(right).right) and
+ (tordconstnode(tshlshrnode(right).right).value>0) and
+ (tordconstnode(tshlshrnode(left).right).value>0) and
+ tshlshrnode(left).left.isequal(tshlshrnode(right).left) and
+ not(might_have_sideeffects(tshlshrnode(left).left)) then
+ begin
+ if tordconstnode(tshlshrnode(left).right).value=
+ tshlshrnode(left).left.resultdef.size*8-tordconstnode(tshlshrnode(right).right).value then
+ begin
+ result:=cinlinenode.create(in_ror_x_y,false,
+ ccallparanode.create(tshlshrnode(left).right,
+ ccallparanode.create(tshlshrnode(left).left,nil)));
+ tshlshrnode(left).left:=nil;
+ tshlshrnode(left).right:=nil;
+ exit;
+ end
+ else if tordconstnode(tshlshrnode(right).right).value=
+ tshlshrnode(left).left.resultdef.size*8-tordconstnode(tshlshrnode(left).right).value then
+ begin
+ result:=cinlinenode.create(in_rol_x_y,false,
+ ccallparanode.create(tshlshrnode(right).right,
+ ccallparanode.create(tshlshrnode(left).left,nil)));
+ tshlshrnode(left).left:=nil;
+ tshlshrnode(right).right:=nil;
+ exit;
+ end;
+ end;
+ if (left.nodetype=shln) and (right.nodetype=shrn) and
+ is_constintnode(tshlshrnode(left).right) and
+ is_constintnode(tshlshrnode(right).right) and
+ (tordconstnode(tshlshrnode(right).right).value>0) and
+ (tordconstnode(tshlshrnode(left).right).value>0) and
+ tshlshrnode(left).left.isequal(tshlshrnode(right).left) and
+ not(might_have_sideeffects(tshlshrnode(left).left)) then
+ begin
+ if tordconstnode(tshlshrnode(left).right).value=
+ tshlshrnode(left).left.resultdef.size*8-tordconstnode(tshlshrnode(right).right).value then
+ begin
+ result:=cinlinenode.create(in_rol_x_y,false,
+ ccallparanode.create(tshlshrnode(left).right,
+ ccallparanode.create(tshlshrnode(left).left,nil)));
+ tshlshrnode(left).left:=nil;
+ tshlshrnode(left).right:=nil;
+ exit;
+ end
+ else if tordconstnode(tshlshrnode(right).right).value=
+ tshlshrnode(left).left.resultdef.size*8-tordconstnode(tshlshrnode(left).right).value then
+ begin
+ result:=cinlinenode.create(in_ror_x_y,false,
+ ccallparanode.create(tshlshrnode(right).right,
+ ccallparanode.create(tshlshrnode(left).left,nil)));
+ tshlshrnode(left).left:=nil;
+ tshlshrnode(right).right:=nil;
+ exit;
+ end;
+ end;
+ end;
+{$endif cpurox}
+ end;
+ end;
+
+
+ function taddnode.dogetcopy: tnode;
+ var
+ n: taddnode;
+ begin
+ n:=taddnode(inherited dogetcopy);
+ n.resultrealdef:=resultrealdef;
+ result:=n;
+ end;
+
+
+ function taddnode.docompare(p: tnode): boolean;
+ begin
+ result:=
+ inherited docompare(p) and
+ equal_defs(taddnode(p).resultrealdef,resultrealdef);
+ end;
+
+
+ function taddnode.pass_typecheck:tnode;
+ begin
+ { This function is small to keep the stack small for recursive of
+ large + operations }
+ typecheckpass(left);
+ typecheckpass(right);
+ result:=pass_typecheck_internal;
+ end;
+
+
+ function taddnode.pass_typecheck_internal:tnode;
+ var
+ hp : tnode;
+ rd,ld,nd : tdef;
+ hsym : tfieldvarsym;
+ llow,lhigh,
+ rlow,rhigh : tconstexprint;
+ strtype : tstringtype;
+ res,
+ b : boolean;
+ lt,rt : tnodetype;
+ ot : tnodetype;
+{$ifdef state_tracking}
+ factval : Tnode;
+ change : boolean;
+{$endif}
+
+ begin
+ result:=nil;
+ { avoid any problems with type parameters later on }
+ if is_typeparam(left.resultdef) or is_typeparam(right.resultdef) then
+ begin
+ resultdef:=cundefinedtype;
+ exit;
+ end;
+
+ { both left and right need to be valid }
+ set_varstate(left,vs_read,[vsf_must_be_valid]);
+ set_varstate(right,vs_read,[vsf_must_be_valid]);
+ if codegenerror then
+ exit;
+
+ { tp procvar support }
+ maybe_call_procvar(left,true);
+ maybe_call_procvar(right,true);
+
+ { convert array constructors to sets, because there is no other operator
+ possible for array constructors }
+ if is_array_constructor(left.resultdef) then
+ begin
+ arrayconstructor_to_set(left);
+ typecheckpass(left);
+ end;
+ if is_array_constructor(right.resultdef) then
+ begin
+ arrayconstructor_to_set(right);
+ typecheckpass(right);
+ end;
+
+ { allow operator overloading }
+ hp:=self;
+ if isbinaryoverloaded(hp) then
+ begin
+ result:=hp;
+ exit;
+ end;
+ { Stop checking when an error was found in the operator checking }
+ if codegenerror then
+ begin
+ result:=cerrornode.create;
+ exit;
+ end;
+
+
+ { Kylix allows enum+ordconstn in an enum type declaration, we need to do
+ the conversion here before the constant folding }
+ if (m_delphi in current_settings.modeswitches) and
+ (blocktype in [bt_type,bt_const_type,bt_var_type]) then
+ begin
+ if (left.resultdef.typ=enumdef) and
+ (right.resultdef.typ=orddef) then
+ begin
+ { insert explicit typecast to default signed int }
+ left:=ctypeconvnode.create_internal(left,sinttype);
+ typecheckpass(left);
+ end
+ else
+ if (left.resultdef.typ=orddef) and
+ (right.resultdef.typ=enumdef) then
+ begin
+ { insert explicit typecast to default signed int }
+ right:=ctypeconvnode.create_internal(right,sinttype);
+ typecheckpass(right);
+ end;
+ end;
+
+ { is one a real float, then both need to be floats, this
+ need to be done before the constant folding so constant
+ operation on a float and int are also handled }
+{$ifdef x86}
+ { use extended as default real type only when the x87 fpu is used }
+ {$ifdef i386}
+ if not(current_settings.fputype=fpu_x87) then
+ resultrealdef:=s64floattype
+ else
+ resultrealdef:=pbestrealtype^;
+ {$endif i386}
+ {$ifdef x86_64}
+ { x86-64 has no x87 only mode, so use always double as default }
+ resultrealdef:=s64floattype;
+ {$endif x86_6}
+{$else not x86}
+ resultrealdef:=pbestrealtype^;
+{$endif not x86}
+
+ if (right.resultdef.typ=floatdef) or (left.resultdef.typ=floatdef) then
+ begin
+ { when both floattypes are already equal then use that
+ floattype for results }
+ if (right.resultdef.typ=floatdef) and
+ (left.resultdef.typ=floatdef) and
+ (tfloatdef(left.resultdef).floattype=tfloatdef(right.resultdef).floattype) then
+ resultrealdef:=left.resultdef
+ { when there is a currency type then use currency, but
+ only when currency is defined as float }
+ else
+ if (is_currency(right.resultdef) or
+ is_currency(left.resultdef)) and
+ ((s64currencytype.typ = floatdef) or
+ (nodetype <> slashn)) then
+ begin
+ resultrealdef:=s64currencytype;
+ inserttypeconv(right,resultrealdef);
+ inserttypeconv(left,resultrealdef);
+ end
+ else
+ begin
+ resultrealdef:=getbestreal(left.resultdef,right.resultdef);
+ inserttypeconv(right,resultrealdef);
+ inserttypeconv(left,resultrealdef);
+ end;
+ end;
+
+ { If both operands are constant and there is a unicodestring
+ or unicodestring then convert everything to unicodestring }
+ if is_constnode(right) and is_constnode(left) and
+ (is_unicodestring(right.resultdef) or
+ is_unicodestring(left.resultdef)) then
+ begin
+ inserttypeconv(right,cunicodestringtype);
+ inserttypeconv(left,cunicodestringtype);
+ end;
+
+ { If both operands are constant and there is a widechar
+ or widestring then convert everything to widestring. This
+ allows constant folding like char+widechar }
+ if is_constnode(right) and is_constnode(left) and
+ (is_widestring(right.resultdef) or
+ is_widestring(left.resultdef) or
+ is_widechar(right.resultdef) or
+ is_widechar(left.resultdef)) then
+ begin
+ inserttypeconv(right,cwidestringtype);
+ inserttypeconv(left,cwidestringtype);
+ end;
+
+ { load easier access variables }
+ rd:=right.resultdef;
+ ld:=left.resultdef;
+ rt:=right.nodetype;
+ lt:=left.nodetype;
+
+ { 4 character constant strings are compatible with orddef }
+ { in macpas mode (become cardinals) }
+ if (m_mac in current_settings.modeswitches) and
+ { only allow for comparisons, additions etc are }
+ { normally program errors }
+ (nodetype in [ltn,lten,gtn,gten,unequaln,equaln]) and
+ (((lt=stringconstn) and
+ (tstringconstnode(left).len=4) and
+ (rd.typ=orddef)) or
+ ((rt=stringconstn) and
+ (tstringconstnode(right).len=4) and
+ (ld.typ=orddef))) then
+ begin
+ if (rt=stringconstn) then
+ begin
+ inserttypeconv(right,u32inttype);
+ rt:=right.nodetype;
+ rd:=right.resultdef;
+ end
+ else
+ begin
+ inserttypeconv(left,u32inttype);
+ lt:=left.nodetype;
+ ld:=left.resultdef;
+ end;
+ end;
+
+ { but an int/int gives real/real! }
+ if (nodetype=slashn) and not(is_vector(left.resultdef)) and not(is_vector(right.resultdef)) then
+ begin
+ if is_currency(left.resultdef) and
+ is_currency(right.resultdef) then
+ { In case of currency, converting to float means dividing by 10000 }
+ { However, since this is already a division, both divisions by }
+ { 10000 are eliminated when we divide the results -> we can skip }
+ { them. }
+ if s64currencytype.typ = floatdef then
+ begin
+ { there's no s64comptype or so, how do we avoid the type conversion?
+ left.resultdef := s64comptype;
+ right.resultdef := s64comptype; }
+ end
+ else
+ begin
+ left.resultdef := s64inttype;
+ right.resultdef := s64inttype;
+ end;
+ inserttypeconv(right,resultrealdef);
+ inserttypeconv(left,resultrealdef);
+ end
+
+ { if both are orddefs then check sub types }
+ else if (ld.typ=orddef) and (rd.typ=orddef) then
+ begin
+ { set for & and | operations in macpas mode: they only work on }
+ { booleans, and always short circuit evaluation }
+ if (nf_short_bool in flags) then
+ begin
+ if not is_boolean(ld) then
+ begin
+ inserttypeconv(left,pasbool8type);
+ ld := left.resultdef;
+ end;
+ if not is_boolean(rd) then
+ begin
+ inserttypeconv(right,pasbool8type);
+ rd := right.resultdef;
+ end;
+ end;
+
+ { 2 booleans? Make them equal to the largest boolean }
+ if (is_boolean(ld) and is_boolean(rd)) then
+ begin
+ if (torddef(left.resultdef).size>torddef(right.resultdef).size) or
+ (is_cbool(left.resultdef) and not is_cbool(right.resultdef)) then
+ begin
+ right:=ctypeconvnode.create_internal(right,left.resultdef);
+ ttypeconvnode(right).convtype:=tc_bool_2_bool;
+ typecheckpass(right);
+ end
+ else if (torddef(left.resultdef).size<torddef(right.resultdef).size) or
+ (not is_cbool(left.resultdef) and is_cbool(right.resultdef)) then
+ begin
+ left:=ctypeconvnode.create_internal(left,right.resultdef);
+ ttypeconvnode(left).convtype:=tc_bool_2_bool;
+ typecheckpass(left);
+ end;
+ case nodetype of
+ xorn,
+ andn,
+ orn:
+ begin
+ end;
+ ltn,
+ lten,
+ gtn,
+ gten:
+ begin
+ { convert both to pasbool to perform the comparison (so
+ that longbool(4) = longbool(2), since both represent
+ "true" }
+ inserttypeconv(left,pasbool8type);
+ inserttypeconv(right,pasbool8type);
+ end;
+ unequaln,
+ equaln:
+ begin
+ if not(cs_full_boolean_eval in current_settings.localswitches) or
+ (nf_short_bool in flags) then
+ begin
+ { Remove any compares with constants }
+ if (left.nodetype=ordconstn) then
+ begin
+ hp:=right;
+ b:=(tordconstnode(left).value<>0);
+ ot:=nodetype;
+ left.free;
+ left:=nil;
+ right:=nil;
+ if (not(b) and (ot=equaln)) or
+ (b and (ot=unequaln)) then
+ begin
+ hp:=cnotnode.create(hp);
+ end;
+ result:=hp;
+ exit;
+ end;
+ if (right.nodetype=ordconstn) then
+ begin
+ hp:=left;
+ b:=(tordconstnode(right).value<>0);
+ ot:=nodetype;
+ right.free;
+ right:=nil;
+ left:=nil;
+ if (not(b) and (ot=equaln)) or
+ (b and (ot=unequaln)) then
+ begin
+ hp:=cnotnode.create(hp);
+ end;
+ result:=hp;
+ exit;
+ end;
+ end;
+ { Delphi-compatibility: convert both to pasbool to
+ perform the equality comparison }
+ inserttypeconv(left,pasbool8type);
+ inserttypeconv(right,pasbool8type);
+ end;
+ else
+ begin
+ CGMessage3(type_e_operator_not_supported_for_types,node2opstr(nodetype),ld.typename,rd.typename);
+ result:=cnothingnode.create;
+ exit;
+ end;
+ end;
+ end
+ { Both are chars? }
+ else if is_char(rd) and is_char(ld) then
+ begin
+ if nodetype=addn then
+ begin
+ resultdef:=cshortstringtype;
+ if not(is_constcharnode(left) and is_constcharnode(right)) then
+ begin
+ inserttypeconv(left,cshortstringtype);
+{$ifdef addstringopt}
+ hp := genaddsstringcharoptnode(self);
+ result := hp;
+ exit;
+{$endif addstringopt}
+ end
+ end
+ else if not(nodetype in [ltn,lten,gtn,gten,unequaln,equaln]) then
+ begin
+ CGMessage3(type_e_operator_not_supported_for_types,node2opstr(nodetype),ld.typename,rd.typename);
+ result:=cnothingnode.create;
+ exit;
+ end;
+ end
+ { There is a widechar? }
+ else if is_widechar(rd) or is_widechar(ld) then
+ begin
+ { widechar+widechar gives widestring }
+ if nodetype=addn then
+ begin
+ inserttypeconv(left,cwidestringtype);
+ if (torddef(rd).ordtype<>uwidechar) then
+ inserttypeconv(right,cwidechartype);
+ resultdef:=cwidestringtype;
+ end
+ else
+ begin
+ if (torddef(ld).ordtype<>uwidechar) then
+ inserttypeconv(left,cwidechartype);
+ if (torddef(rd).ordtype<>uwidechar) then
+ inserttypeconv(right,cwidechartype);
+ end;
+ end
+ { is there a currency type ? }
+ else if ((torddef(rd).ordtype=scurrency) or (torddef(ld).ordtype=scurrency)) then
+ begin
+ if (torddef(ld).ordtype<>scurrency) then
+ inserttypeconv(left,s64currencytype);
+ if (torddef(rd).ordtype<>scurrency) then
+ inserttypeconv(right,s64currencytype);
+ end
+ { "and" does't care about the sign of integers }
+ { "xor", "or" and compares don't need extension to native int }
+ { size either as long as both values are signed or unsigned }
+ { "xor" and "or" also don't care about the sign if the values }
+ { occupy an entire register }
+ { don't do it if either type is 64 bit, since in that case we }
+ { can't safely find a "common" type }
+ else if is_integer(ld) and is_integer(rd) and
+ not is_64bitint(ld) and not is_64bitint(rd) and
+ ((nodetype=andn) or
+ ((nodetype in [orn,xorn,equaln,unequaln,gtn,gten,ltn,lten]) and
+ not(is_signed(ld) xor is_signed(rd)))) then
+ begin
+ if (rd.size>ld.size) or
+ { Delphi-compatible: prefer unsigned type for "and" with equal size }
+ ((rd.size=ld.size) and
+ not is_signed(rd)) then
+ begin
+ if (rd.size=ld.size) and
+ is_signed(ld) then
+ inserttypeconv_internal(left,rd)
+ else
+ begin
+ { not to left right.resultdef, because that may
+ cause a range error if left and right's def don't
+ completely overlap }
+ nd:=get_common_intdef(torddef(ld),torddef(rd),true);
+ inserttypeconv(left,nd);
+ inserttypeconv(right,nd);
+ end;
+ end
+ else
+ begin
+ if (rd.size=ld.size) and
+ is_signed(rd) then
+ inserttypeconv_internal(right,ld)
+ else
+ begin
+ nd:=get_common_intdef(torddef(ld),torddef(rd),true);
+ inserttypeconv(left,nd);
+ inserttypeconv(right,nd);
+ end;
+ end
+ end
+ { is there a signed 64 bit type ? }
+ else if ((torddef(rd).ordtype=s64bit) or (torddef(ld).ordtype=s64bit)) then
+ begin
+ if (torddef(ld).ordtype<>s64bit) then
+ inserttypeconv(left,s64inttype);
+ if (torddef(rd).ordtype<>s64bit) then
+ inserttypeconv(right,s64inttype);
+ end
+ { is there a unsigned 64 bit type ? }
+ else if ((torddef(rd).ordtype=u64bit) or (torddef(ld).ordtype=u64bit)) then
+ begin
+ if (torddef(ld).ordtype<>u64bit) then
+ inserttypeconv(left,u64inttype);
+ if (torddef(rd).ordtype<>u64bit) then
+ inserttypeconv(right,u64inttype);
+ end
+ { 64 bit cpus do calculations always in 64 bit }
+{$ifndef cpu64bitaddr}
+ { is there a cardinal? }
+ else if ((torddef(rd).ordtype=u32bit) or (torddef(ld).ordtype=u32bit)) then
+ begin
+ { convert positive constants to u32bit }
+ if (torddef(ld).ordtype<>u32bit) and
+ is_constintnode(left) and
+ (tordconstnode(left).value >= 0) then
+ inserttypeconv(left,u32inttype);
+ if (torddef(rd).ordtype<>u32bit) and
+ is_constintnode(right) and
+ (tordconstnode(right).value >= 0) then
+ inserttypeconv(right,u32inttype);
+ { when one of the operand is signed or the operation is subn then perform
+ the operation in 64bit, can't use rd/ld here because there
+ could be already typeconvs inserted.
+ This is compatible with the code below for other unsigned types (PFV) }
+ if is_signed(left.resultdef) or
+ is_signed(right.resultdef) or
+ (nodetype=subn) then
+ begin
+ if nodetype<>subn then
+ CGMessage(type_h_mixed_signed_unsigned);
+ { mark as internal in case added for a subn, so }
+ { ttypeconvnode.simplify can remove the 64 bit }
+ { typecast again if semantically correct. Even }
+ { if we could detect that here already, we }
+ { mustn't do it here because that would change }
+ { overload choosing behaviour etc. The code in }
+ { ncnv.pas is run after that is already decided }
+ if (not is_signed(left.resultdef) and
+ not is_signed(right.resultdef)) or
+ (nodetype in [orn,xorn]) then
+ include(flags,nf_internal);
+ inserttypeconv(left,s64inttype);
+ inserttypeconv(right,s64inttype);
+ end
+ else
+ begin
+ if (torddef(left.resultdef).ordtype<>u32bit) then
+ inserttypeconv(left,u32inttype);
+ if (torddef(right.resultdef).ordtype<>u32bit) then
+ inserttypeconv(right,u32inttype);
+ end;
+ end
+{$endif cpu64bitaddr}
+ { generic ord conversion is sinttype }
+ else
+ begin
+ { When there is a signed type or there is a minus operation
+ we convert to signed int. Otherwise (both are unsigned) we keep
+ the result also unsigned. This is compatible with Delphi (PFV) }
+ if is_signed(ld) or
+ is_signed(rd) or
+ (nodetype=subn) then
+ begin
+{$ifdef cpunodefaultint}
+ { for small cpus we use the smallest common type }
+ nd:=get_common_intdef(torddef(ld),torddef(rd),false);
+ inserttypeconv(right,nd);
+ inserttypeconv(left,nd);
+{$else cpunodefaultint}
+ inserttypeconv(right,sinttype);
+ inserttypeconv(left,sinttype);
+{$endif cpunodefaultint}
+ end
+ else
+ begin
+ inserttypeconv(right,uinttype);
+ inserttypeconv(left,uinttype);
+ end;
+ end;
+ end
+
+ { if both are floatdefs, conversion is already done before constant folding }
+ else if (ld.typ=floatdef) then
+ begin
+ if not(nodetype in [addn,subn,muln,slashn,equaln,unequaln,ltn,lten,gtn,gten]) then
+ CGMessage3(type_e_operator_not_supported_for_types,node2opstr(nodetype),ld.typename,rd.typename);
+ end
+
+ { left side a setdef, must be before string processing,
+ else array constructor can be seen as array of char (PFV) }
+ else if (ld.typ=setdef) then
+ begin
+ if not(nodetype in [addn,subn,symdifn,muln,equaln,unequaln,lten,gten]) then
+ CGMessage(type_e_set_operation_unknown);
+ { right must either be a set or a set element }
+ if (rd.typ<>setdef) and
+ (rt<>setelementn) then
+ CGMessage(type_e_mismatch)
+ { Make operands the same setdef. If one's elementtype fits }
+ { entirely inside the other's, pick the one with the largest }
+ { range. Otherwise create a new setdef with a range which }
+ { can contain both. }
+ else if not(equal_defs(ld,rd)) then
+ begin
+ { note: ld cannot be an empty set with elementdef=nil in }
+ { case right is not a set, arrayconstructor_to_set takes }
+ { care of that }
+
+ { 1: rd is a set with an assigned elementdef, and ld is }
+ { either an empty set without elementdef or a set whose }
+ { elementdef fits in rd's elementdef -> convert to rd }
+ if ((rd.typ=setdef) and
+ assigned(tsetdef(rd).elementdef) and
+ (not assigned(tsetdef(ld).elementdef) or
+ is_in_limit(ld,rd))) then
+ inserttypeconv(left,rd)
+ { 2: rd is either an empty set without elementdef or a set }
+ { whose elementdef fits in ld's elementdef, or a set }
+ { element whose def fits in ld's elementdef -> convert }
+ { to ld. ld's elementdef can't be nil here, is caught }
+ { previous case and "note:" above }
+ else if ((rd.typ=setdef) and
+ (not assigned(tsetdef(rd).elementdef) or
+ is_in_limit(rd,ld))) or
+ ((rd.typ<>setdef) and
+ is_in_limit(rd,tsetdef(ld).elementdef)) then
+ if (rd.typ=setdef) then
+ inserttypeconv(right,ld)
+ else
+ inserttypeconv(right,tsetdef(ld).elementdef)
+ { 3: otherwise create setdef which encompasses both, taking }
+ { into account empty sets without elementdef }
+ else
+ begin
+ if assigned(tsetdef(ld).elementdef) then
+ begin
+ llow:=tsetdef(ld).setbase;
+ lhigh:=tsetdef(ld).setmax;
+ end;
+ if (rd.typ=setdef) then
+ if assigned(tsetdef(rd).elementdef) then
+ begin
+ rlow:=tsetdef(rd).setbase;
+ rhigh:=tsetdef(rd).setmax;
+ end
+ else
+ begin
+ { ld's elementdef must have been valid }
+ rlow:=llow;
+ rhigh:=lhigh;
+ end
+ else
+ getrange(rd,rlow,rhigh);
+ if not assigned(tsetdef(ld).elementdef) then
+ begin
+ llow:=rlow;
+ lhigh:=rhigh;
+ end;
+ nd:=tsetdef.create(tsetdef(ld).elementdef,min(llow,rlow),max(lhigh,rhigh));
+ inserttypeconv(left,nd);
+ if (rd.typ=setdef) then
+ inserttypeconv(right,nd)
+ else
+ inserttypeconv(right,tsetdef(nd).elementdef);
+ end;
+ end;
+ end
+ { pointer comparision and subtraction }
+ else if (
+ (rd.typ=pointerdef) and (ld.typ=pointerdef)
+ ) or
+ { compare/add pchar to variable (not stringconst) char arrays
+ by addresses like BP/Delphi }
+ (
+ (nodetype in [equaln,unequaln,subn,addn]) and
+ (
+ ((is_pchar(ld) or (lt=niln)) and is_chararray(rd) and (rt<>stringconstn)) or
+ ((is_pchar(rd) or (rt=niln)) and is_chararray(ld) and (lt<>stringconstn))
+ )
+ ) then
+ begin
+ { convert char array to pointer }
+ if is_chararray(rd) then
+ begin
+ inserttypeconv(right,charpointertype);
+ rd:=right.resultdef;
+ end
+ else if is_chararray(ld) then
+ begin
+ inserttypeconv(left,charpointertype);
+ ld:=left.resultdef;
+ end;
+
+ case nodetype of
+ equaln,unequaln :
+ begin
+ if is_voidpointer(right.resultdef) then
+ inserttypeconv(right,left.resultdef)
+ else if is_voidpointer(left.resultdef) then
+ inserttypeconv(left,right.resultdef)
+ else if not(equal_defs(ld,rd)) then
+ IncompatibleTypes(ld,rd);
+ { now that the type checking is done, convert both to charpointer, }
+ { because methodpointers are 8 bytes even though only the first 4 }
+ { bytes must be compared. This can happen here if we are in }
+ { TP/Delphi mode, because there @methodpointer = voidpointer (but }
+ { a voidpointer of 8 bytes). A conversion to voidpointer would be }
+ { optimized away, since the result already was a voidpointer, so }
+ { use a charpointer instead (JM) }
+ inserttypeconv_internal(left,charpointertype);
+ inserttypeconv_internal(right,charpointertype);
+ end;
+ ltn,lten,gtn,gten:
+ begin
+ if (cs_extsyntax in current_settings.moduleswitches) then
+ begin
+ if is_voidpointer(right.resultdef) then
+ inserttypeconv(right,left.resultdef)
+ else if is_voidpointer(left.resultdef) then
+ inserttypeconv(left,right.resultdef)
+ else if not(equal_defs(ld,rd)) then
+ IncompatibleTypes(ld,rd);
+ end
+ else
+ CGMessage3(type_e_operator_not_supported_for_types,node2opstr(nodetype),ld.typename,rd.typename);
+ end;
+ subn:
+ begin
+ if (cs_extsyntax in current_settings.moduleswitches) then
+ begin
+ if is_voidpointer(right.resultdef) then
+ begin
+ if is_big_untyped_addrnode(right) then
+ CGMessage1(type_w_untyped_arithmetic_unportable,node2opstr(nodetype));
+ inserttypeconv(right,left.resultdef)
+ end
+ else if is_voidpointer(left.resultdef) then
+ inserttypeconv(left,right.resultdef)
+ else if not(equal_defs(ld,rd)) then
+ IncompatibleTypes(ld,rd);
+ end
+ else
+ CGMessage3(type_e_operator_not_supported_for_types,node2opstr(nodetype),ld.typename,rd.typename);
+
+ if not(nf_has_pointerdiv in flags) and
+ (tpointerdef(rd).pointeddef.size>1) then
+ begin
+ hp:=getcopy;
+ include(hp.flags,nf_has_pointerdiv);
+ result:=cmoddivnode.create(divn,hp,cordconstnode.create(tpointerdef(rd).pointeddef.size,sinttype,false));
+ end;
+ resultdef:=sinttype;
+ exit;
+ end;
+ else
+ CGMessage3(type_e_operator_not_supported_for_types,node2opstr(nodetype),ld.typename,rd.typename);
+ end;
+ end
+
+ { is one of the operands a string?,
+ chararrays are also handled as strings (after conversion), also take
+ care of chararray+chararray and chararray+char.
+ Note: Must be done after pointerdef+pointerdef has been checked, else
+ pchar is converted to string }
+ else if (rd.typ=stringdef) or
+ (ld.typ=stringdef) or
+ { stringconstn's can be arraydefs }
+ (lt=stringconstn) or
+ (rt=stringconstn) or
+ ((is_pchar(rd) or is_chararray(rd) or is_char(rd) or is_open_chararray(rd) or
+ is_pwidechar(rd) or is_widechararray(rd) or is_widechar(rd) or is_open_widechararray(rd)) and
+ (is_pchar(ld) or is_chararray(ld) or is_char(ld) or is_open_chararray(ld) or
+ is_pwidechar(ld) or is_widechararray(ld) or is_widechar(ld) or is_open_widechararray(ld))) then
+ begin
+ if (nodetype in [addn,equaln,unequaln,lten,gten,ltn,gtn]) then
+ begin
+ { Is there a unicodestring? }
+ if is_unicodestring(rd) or is_unicodestring(ld) then
+ strtype:=st_unicodestring
+ else
+ { Is there a widestring? }
+ if is_widestring(rd) or is_widestring(ld) or
+ is_pwidechar(rd) or is_widechararray(rd) or is_widechar(rd) or is_open_widechararray(rd) or
+ is_pwidechar(ld) or is_widechararray(ld) or is_widechar(ld) or is_open_widechararray(ld) then
+ strtype:=st_widestring
+ else
+ if is_ansistring(rd) or is_ansistring(ld) or
+ ((cs_ansistrings in current_settings.localswitches) and
+ //todo: Move some of this to longstring's then they are implemented?
+ (
+ is_pchar(rd) or (is_chararray(rd) and (rd.size > 255)) or is_open_chararray(rd) or (lt = stringconstn) or
+ is_pchar(ld) or (is_chararray(ld) and (ld.size > 255)) or is_open_chararray(ld) or (rt = stringconstn)
+ )
+ ) then
+ strtype:=st_ansistring
+ else
+ if is_longstring(rd) or is_longstring(ld) then
+ strtype:=st_longstring
+ else
+ begin
+ { TODO: todo: add a warning/hint here if one converting a too large array}
+ { nodes is PChar, array [with size > 255] or OpenArrayOfChar.
+ Note: Delphi halts with error if "array [0..xx] of char"
+ is assigned to ShortString and string length is less
+ then array size }
+ strtype:= st_shortstring;
+ end;
+
+ // Now convert nodes to common string type
+ case strtype of
+ st_widestring :
+ begin
+ if not(is_widestring(rd)) then
+ inserttypeconv(right,cwidestringtype);
+ if not(is_widestring(ld)) then
+ inserttypeconv(left,cwidestringtype);
+ end;
+ st_unicodestring :
+ begin
+ if not(is_unicodestring(rd)) then
+ inserttypeconv(right,cunicodestringtype);
+ if not(is_unicodestring(ld)) then
+ inserttypeconv(left,cunicodestringtype);
+ end;
+ st_ansistring :
+ begin
+ { use same code page if possible (don't force same code
+ page in case both are ansistrings with code page <>
+ CP_NONE, since then data loss can occur (the ansistring
+ helpers will convert them at run time to an encoding
+ that can represent both encodings) }
+ if is_ansistring(ld) and
+ (tstringdef(ld).encoding<>0) and
+ (tstringdef(ld).encoding<>globals.CP_NONE) and
+ (not is_ansistring(rd) or
+ (tstringdef(rd).encoding=0) or
+ (tstringdef(rd).encoding=globals.CP_NONE)) then
+ inserttypeconv(right,ld)
+ else if is_ansistring(rd) and
+ (tstringdef(rd).encoding<>0) and
+ (tstringdef(rd).encoding<>globals.CP_NONE) and
+ (not is_ansistring(ld) or
+ (tstringdef(ld).encoding=0) or
+ (tstringdef(ld).encoding=globals.CP_NONE)) then
+ inserttypeconv(left,rd)
+ else
+ begin
+ if not is_ansistring(ld) then
+ inserttypeconv(left,getansistringdef);
+ if not is_ansistring(rd) then
+ inserttypeconv(right,getansistringdef);
+ end;
+ end;
+ st_longstring :
+ begin
+ if not(is_longstring(rd)) then
+ inserttypeconv(right,clongstringtype);
+ if not(is_longstring(ld)) then
+ inserttypeconv(left,clongstringtype);
+ end;
+ st_shortstring :
+ begin
+ if not(is_shortstring(ld)) then
+ inserttypeconv(left,cshortstringtype);
+ { don't convert char, that can be handled by the optimized node }
+ if not(is_shortstring(rd) or is_char(rd)) then
+ inserttypeconv(right,cshortstringtype);
+ end;
+ else
+ internalerror(2005101);
+ end;
+ end
+ else
+ CGMessage3(type_e_operator_not_supported_for_types,node2opstr(nodetype),ld.typename,rd.typename);
+ end
+
+ { implicit pointer object type comparison }
+ else if is_implicit_pointer_object_type(rd) or is_implicit_pointer_object_type(ld) then
+ begin
+ if (nodetype in [equaln,unequaln]) then
+ begin
+ if is_implicit_pointer_object_type(rd) and is_implicit_pointer_object_type(ld) then
+ begin
+ if tobjectdef(rd).is_related(tobjectdef(ld)) then
+ inserttypeconv(right,left.resultdef)
+ else
+ inserttypeconv(left,right.resultdef);
+ end
+ else if is_implicit_pointer_object_type(rd) then
+ inserttypeconv(left,right.resultdef)
+ else
+ inserttypeconv(right,left.resultdef);
+ end
+ else
+ CGMessage3(type_e_operator_not_supported_for_types,node2opstr(nodetype),ld.typename,rd.typename);
+ end
+
+ else if (rd.typ=classrefdef) and (ld.typ=classrefdef) then
+ begin
+ if (nodetype in [equaln,unequaln]) then
+ begin
+ if tobjectdef(tclassrefdef(rd).pointeddef).is_related(
+ tobjectdef(tclassrefdef(ld).pointeddef)) then
+ inserttypeconv(right,left.resultdef)
+ else
+ inserttypeconv(left,right.resultdef);
+ end
+ else
+ CGMessage3(type_e_operator_not_supported_for_types,node2opstr(nodetype),ld.typename,rd.typename);
+ end
+
+ { allow comparison with nil pointer }
+ else if is_implicit_pointer_object_type(rd) or (rd.typ=classrefdef) then
+ begin
+ if (nodetype in [equaln,unequaln]) then
+ inserttypeconv(left,right.resultdef)
+ else
+ CGMessage3(type_e_operator_not_supported_for_types,node2opstr(nodetype),ld.typename,rd.typename);
+ end
+
+ else if is_implicit_pointer_object_type(ld) or (ld.typ=classrefdef) then
+ begin
+ if (nodetype in [equaln,unequaln]) then
+ inserttypeconv(right,left.resultdef)
+ else
+ CGMessage3(type_e_operator_not_supported_for_types,node2opstr(nodetype),ld.typename,rd.typename);
+ end
+
+ { support procvar=nil,procvar<>nil }
+ else if ((ld.typ=procvardef) and (rt=niln)) or
+ ((rd.typ=procvardef) and (lt=niln)) then
+ begin
+ if not(nodetype in [equaln,unequaln]) then
+ CGMessage3(type_e_operator_not_supported_for_types,node2opstr(nodetype),ld.typename,rd.typename);
+ { find proc field in methodpointer record }
+ hsym:=tfieldvarsym(trecorddef(methodpointertype).symtable.Find('proc'));
+ if not assigned(hsym) then
+ internalerror(200412043);
+ { For methodpointers compare only tmethodpointer.proc }
+ if (rd.typ=procvardef) and
+ (not tprocvardef(rd).is_addressonly) then
+ begin
+ right:=csubscriptnode.create(
+ hsym,
+ ctypeconvnode.create_internal(right,methodpointertype));
+ typecheckpass(right);
+ end;
+ if (ld.typ=procvardef) and
+ (not tprocvardef(ld).is_addressonly) then
+ begin
+ left:=csubscriptnode.create(
+ hsym,
+ ctypeconvnode.create_internal(left,methodpointertype));
+ typecheckpass(left);
+ end;
+ end
+
+ { support dynamicarray=nil,dynamicarray<>nil }
+ else if (is_dynamic_array(ld) and (rt=niln)) or
+ (is_dynamic_array(rd) and (lt=niln)) or
+ (is_dynamic_array(ld) and is_dynamic_array(rd)) then
+ begin
+ if not(nodetype in [equaln,unequaln]) then
+ CGMessage3(type_e_operator_not_supported_for_types,node2opstr(nodetype),ld.typename,rd.typename);
+ end
+
+{$ifdef SUPPORT_MMX}
+ { mmx support, this must be before the zero based array
+ check }
+ else if (cs_mmx in current_settings.localswitches) and
+ is_mmx_able_array(ld) and
+ is_mmx_able_array(rd) and
+ equal_defs(ld,rd) then
+ begin
+ case nodetype of
+ addn,subn,xorn,orn,andn:
+ ;
+ { mul is a little bit restricted }
+ muln:
+ if not(mmx_type(ld) in [mmxu16bit,mmxs16bit,mmxfixed16]) then
+ CGMessage3(type_e_operator_not_supported_for_types,node2opstr(nodetype),ld.typename,rd.typename);
+ else
+ CGMessage3(type_e_operator_not_supported_for_types,node2opstr(nodetype),ld.typename,rd.typename);
+ end;
+ end
+{$endif SUPPORT_MMX}
+ { vector support, this must be before the zero based array
+ check }
+ else if (cs_support_vectors in current_settings.globalswitches) and
+ is_vector(ld) and
+ is_vector(rd) and
+ equal_defs(ld,rd) then
+ begin
+ if not(nodetype in [addn,subn,xorn,orn,andn,muln,slashn]) then
+ CGMessage3(type_e_operator_not_supported_for_types,node2opstr(nodetype),ld.typename,rd.typename);
+ { both defs must be equal, so taking left or right as resultdef doesn't matter }
+ resultdef:=left.resultdef;
+ end
+
+ { this is a little bit dangerous, also the left type }
+ { pointer to should be checked! This broke the mmx support }
+ else if (rd.typ=pointerdef) or
+ (is_zero_based_array(rd) and (rt<>stringconstn)) then
+ begin
+ if is_zero_based_array(rd) then
+ begin
+ resultdef:=tpointerdef.create(tarraydef(rd).elementdef);
+ inserttypeconv(right,resultdef);
+ end
+ else
+ resultdef:=right.resultdef;
+ inserttypeconv(left,sinttype);
+ if nodetype=addn then
+ begin
+ if not(cs_extsyntax in current_settings.moduleswitches) or
+ (not (is_pchar(ld) or is_chararray(ld) or is_open_chararray(ld) or is_widechar(ld) or is_widechararray(ld) or is_open_widechararray(ld)) and
+ not(cs_pointermath in current_settings.localswitches) and
+ not((ld.typ=pointerdef) and tpointerdef(ld).has_pointer_math)) then
+ CGMessage3(type_e_operator_not_supported_for_types,node2opstr(nodetype),ld.typename,rd.typename);
+ if (rd.typ=pointerdef) and
+ (tpointerdef(rd).pointeddef.size>1) then
+ begin
+ left:=caddnode.create(muln,left,
+ cordconstnode.create(tpointerdef(rd).pointeddef.size,sinttype,true));
+ typecheckpass(left);
+ end;
+ end
+ else
+ CGMessage3(type_e_operator_not_supported_for_types,node2opstr(nodetype),ld.typename,rd.typename);
+ end
+
+ else if (ld.typ=pointerdef) or
+ (is_zero_based_array(ld) and (lt<>stringconstn)) then
+ begin
+ if is_zero_based_array(ld) then
+ begin
+ resultdef:=tpointerdef.create(tarraydef(ld).elementdef);
+ inserttypeconv(left,resultdef);
+ end
+ else
+ resultdef:=left.resultdef;
+
+ inserttypeconv(right,sinttype);
+ if nodetype in [addn,subn] then
+ begin
+ if (lt=niln) then
+ CGMessage3(type_e_operator_not_supported_for_types,node2opstr(nodetype),'NIL',rd.typename);
+ if not(cs_extsyntax in current_settings.moduleswitches) or
+ (not (is_pchar(ld) or is_chararray(ld) or is_open_chararray(ld) or is_widechar(ld) or is_widechararray(ld) or is_open_widechararray(ld)) and
+ not(cs_pointermath in current_settings.localswitches) and
+ not((ld.typ=pointerdef) and tpointerdef(ld).has_pointer_math)) then
+ CGMessage3(type_e_operator_not_supported_for_types,node2opstr(nodetype),ld.typename,rd.typename);
+ if (ld.typ=pointerdef) then
+ begin
+ if is_big_untyped_addrnode(left) then
+ CGMessage1(type_w_untyped_arithmetic_unportable,node2opstr(nodetype));
+ if (tpointerdef(ld).pointeddef.size>1) then
+ begin
+ right:=caddnode.create(muln,right,
+ cordconstnode.create(tpointerdef(ld).pointeddef.size,sinttype,true));
+ typecheckpass(right);
+ end
+ end else
+ if is_zero_based_array(ld) and
+ (tarraydef(ld).elementdef.size>1) then
+ begin
+ right:=caddnode.create(muln,right,
+ cordconstnode.create(tarraydef(ld).elementdef.size,sinttype,true));
+ typecheckpass(right);
+ end;
+ end
+ else
+ CGMessage3(type_e_operator_not_supported_for_types,node2opstr(nodetype),ld.typename,rd.typename);
+ end
+
+ else if (rd.typ=procvardef) and
+ (ld.typ=procvardef) and
+ equal_defs(rd,ld) then
+ begin
+ if (nodetype in [equaln,unequaln]) then
+ begin
+ if tprocvardef(rd).is_addressonly then
+ begin
+ inserttypeconv_internal(right,voidpointertype);
+ inserttypeconv_internal(left,voidpointertype);
+ end
+ else
+ begin
+ { find proc field in methodpointer record }
+ hsym:=tfieldvarsym(trecorddef(methodpointertype).symtable.Find('proc'));
+ if not assigned(hsym) then
+ internalerror(200412043);
+ { Compare tmehodpointer(left).proc }
+ right:=csubscriptnode.create(
+ hsym,
+ ctypeconvnode.create_internal(right,methodpointertype));
+ typecheckpass(right);
+ left:=csubscriptnode.create(
+ hsym,
+ ctypeconvnode.create_internal(left,methodpointertype));
+ typecheckpass(left);
+ end;
+ end
+ else
+ CGMessage3(type_e_operator_not_supported_for_types,node2opstr(nodetype),ld.typename,rd.typename);
+ end
+
+ { enums }
+ else if (ld.typ=enumdef) and (rd.typ=enumdef) then
+ begin
+ if allowenumop(nodetype) then
+ inserttypeconv(right,left.resultdef)
+ else
+ CGMessage3(type_e_operator_not_supported_for_types,node2opstr(nodetype),ld.typename,rd.typename);
+ end
+
+ { generic conversion, this is for error recovery }
+ else
+ begin
+ inserttypeconv(left,sinttype);
+ inserttypeconv(right,sinttype);
+ end;
+
+ if cmp_of_disjunct_ranges(res) then
+ begin
+ if res then
+ CGMessage(type_w_comparison_always_true)
+ else
+ CGMessage(type_w_comparison_always_false);
+ end;
+
+ { set resultdef if not already done }
+ if not assigned(resultdef) then
+ begin
+ case nodetype of
+ ltn,lten,gtn,gten,equaln,unequaln :
+ resultdef:=pasbool8type;
+ slashn :
+ resultdef:=resultrealdef;
+ addn:
+ begin
+ { for strings, return is always a 255 char string }
+ if is_shortstring(left.resultdef) then
+ resultdef:=cshortstringtype
+ else
+ { for ansistrings set resultdef to assignment left node
+ if it is an assignment and left node expects ansistring }
+ if is_ansistring(left.resultdef) and
+ assigned(aktassignmentnode) and
+ (aktassignmentnode.right=self) and
+ is_ansistring(aktassignmentnode.left.resultdef) then
+ resultdef:=aktassignmentnode.left.resultdef
+ else
+ resultdef:=left.resultdef;
+ end;
+ else
+ resultdef:=left.resultdef;
+ end;
+ end;
+
+ { when the result is currency we need some extra code for
+ multiplication and division. this should not be done when
+ the muln or slashn node is created internally }
+ if not(nf_is_currency in flags) and
+ is_currency(resultdef) then
+ begin
+ case nodetype of
+ slashn :
+ begin
+ { slashn will only work with floats }
+ hp:=caddnode.create(muln,getcopy,crealconstnode.create(10000.0,s64currencytype));
+ include(hp.flags,nf_is_currency);
+ result:=hp;
+ end;
+ muln :
+ begin
+ if s64currencytype.typ=floatdef then
+ hp:=caddnode.create(slashn,getcopy,crealconstnode.create(10000.0,s64currencytype))
+ else
+ hp:=cmoddivnode.create(divn,getcopy,cordconstnode.create(10000,s64currencytype,false));
+ include(hp.flags,nf_is_currency);
+ result:=hp
+ end;
+ end;
+ end;
+
+ if not codegenerror and
+ not assigned(result) then
+ result:=simplify(false);
+ end;
+
+
+ function taddnode.first_addstring: tnode;
+ const
+ swap_relation: array [ltn..unequaln] of Tnodetype=(gtn, gten, ltn, lten, equaln, unequaln);
+ var
+ p: tnode;
+ newstatement : tstatementnode;
+ tempnode (*,tempnode2*) : ttempcreatenode;
+ cmpfuncname: string;
+ para: tcallparanode;
+ begin
+ { when we get here, we are sure that both the left and the right }
+ { node are both strings of the same stringtype (JM) }
+ case nodetype of
+ addn:
+ begin
+ if (left.nodetype=stringconstn) and (tstringconstnode(left).len=0) then
+ begin
+ result:=right;
+ left.free;
+ left:=nil;
+ right:=nil;
+ exit;
+ end;
+ if (right.nodetype=stringconstn) and (tstringconstnode(right).len=0) then
+ begin
+ result:=left;
+ left:=nil;
+ right.free;
+ right:=nil;
+ exit;
+ end;
+ { create the call to the concat routine both strings as arguments }
+ if assigned(aktassignmentnode) and
+ (aktassignmentnode.right=self) and
+ (aktassignmentnode.left.resultdef=resultdef) and
+ valid_for_var(aktassignmentnode.left,false) then
+ begin
+ para:=ccallparanode.create(
+ right,
+ ccallparanode.create(
+ left,
+ ccallparanode.create(aktassignmentnode.left.getcopy,nil)
+ )
+ );
+ if is_ansistring(resultdef) then
+ para:=ccallparanode.create(
+ cordconstnode.create(
+ getparaencoding(resultdef),
+ u16inttype,
+ true
+ ),
+ para
+ );
+ result:=ccallnode.createintern(
+ 'fpc_'+tstringdef(resultdef).stringtypname+'_concat',
+ para
+ );
+ include(aktassignmentnode.flags,nf_assign_done_in_right);
+ firstpass(result);
+ end
+ else
+ begin
+ result:=internalstatements(newstatement);
+ tempnode:=ctempcreatenode.create(resultdef,resultdef.size,tt_persistent,true);
+ addstatement(newstatement,tempnode);
+ para:=ccallparanode.create(
+ right,
+ ccallparanode.create(
+ left,
+ ccallparanode.create(ctemprefnode.create(tempnode),nil)
+ )
+ );
+ if is_ansistring(resultdef) then
+ para:=ccallparanode.create(
+ cordconstnode.create(
+ getparaencoding(resultdef),
+ u16inttype,
+ true
+ ),
+ para
+ );
+ addstatement(
+ newstatement,
+ ccallnode.createintern(
+ 'fpc_'+tstringdef(resultdef).stringtypname+'_concat',
+ para
+ )
+ );
+ addstatement(newstatement,ctempdeletenode.create_normal_temp(tempnode));
+ addstatement(newstatement,ctemprefnode.create(tempnode));
+ end;
+ { we reused the arguments }
+ left := nil;
+ right := nil;
+ end;
+ ltn,lten,gtn,gten,equaln,unequaln :
+ begin
+ { generate better code for comparison with empty string, we
+ only need to compare the length with 0 }
+ if (nodetype in [equaln,unequaln,gtn,gten,ltn,lten]) and
+ { windows widestrings are too complicated to be handled optimized }
+ not(is_widestring(left.resultdef) and (target_info.system in systems_windows)) and
+ (((left.nodetype=stringconstn) and (tstringconstnode(left).len=0)) or
+ ((right.nodetype=stringconstn) and (tstringconstnode(right).len=0))) then
+ begin
+ { switch so that the constant is always on the right }
+ if left.nodetype = stringconstn then
+ begin
+ p := left;
+ left := right;
+ right := p;
+ nodetype:=swap_relation[nodetype];
+ end;
+ if is_shortstring(left.resultdef) or
+ (nodetype in [gtn,gten,ltn,lten]) then
+ { compare the length with 0 }
+ result := caddnode.create(nodetype,
+ cinlinenode.create(in_length_x,false,left),
+ cordconstnode.create(0,s32inttype,false))
+ else
+ begin
+ (*
+ if is_widestring(left.resultdef) and
+ (target_info.system in system_windows) then
+ begin
+ { windows like widestrings requires that we also check the length }
+ result:=internalstatements(newstatement);
+ tempnode:=ctempcreatenode.create(voidpointertype,voidpointertype.size,tt_persistent,true);
+ tempnode2:=ctempcreatenode.create(resultdef,resultdef.size,tt_persistent,true);
+ addstatement(newstatement,tempnode);
+ addstatement(newstatement,tempnode2);
+ { poor man's cse }
+ addstatement(newstatement,cassignmentnode.create(ctemprefnode.create(tempnode),
+ ctypeconvnode.create_internal(left,voidpointertype))
+ );
+ addstatement(newstatement,cassignmentnode.create(ctemprefnode.create(tempnode2),
+ caddnode.create(orn,
+ caddnode.create(nodetype,
+ ctemprefnode.create(tempnode),
+ cpointerconstnode.create(0,voidpointertype)
+ ),
+ caddnode.create(nodetype,
+ ctypeconvnode.create_internal(cderefnode.create(ctemprefnode.create(tempnode)),s32inttype),
+ cordconstnode.create(0,s32inttype,false)
+ )
+ )
+ ));
+ addstatement(newstatement,ctempdeletenode.create_normal_temp(tempnode));
+ addstatement(newstatement,ctempdeletenode.create_normal_temp(tempnode2));
+ addstatement(newstatement,ctemprefnode.create(tempnode2));
+ end
+ else
+ *)
+ begin
+ { compare the pointer with nil (for ansistrings etc), }
+ { faster than getting the length (JM) }
+ result:= caddnode.create(nodetype,
+ ctypeconvnode.create_internal(left,voidpointertype),
+ cpointerconstnode.create(0,voidpointertype));
+ end;
+ end;
+ { left is reused }
+ left := nil;
+ { right isn't }
+ right.free;
+ right := nil;
+ exit;
+ end;
+ { no string constant -> call compare routine }
+ cmpfuncname := 'fpc_'+tstringdef(left.resultdef).stringtypname+'_compare';
+ { for equality checks use optimized version }
+ if nodetype in [equaln,unequaln] then
+ cmpfuncname := cmpfuncname + '_equal';
+
+ result := ccallnode.createintern(cmpfuncname,
+ ccallparanode.create(right,ccallparanode.create(left,nil)));
+ { and compare its result with 0 according to the original operator }
+ result := caddnode.create(nodetype,result,
+ cordconstnode.create(0,s32inttype,false));
+ left := nil;
+ right := nil;
+ end;
+ end;
+ end;
+
+
+ function taddnode.first_addset : tnode;
+
+ procedure call_varset_helper(const n : string);
+ var
+ newstatement : tstatementnode;
+ temp : ttempcreatenode;
+ begin
+ { add two var sets }
+ result:=internalstatements(newstatement);
+
+ { create temp for result }
+ temp:=ctempcreatenode.create(resultdef,resultdef.size,tt_persistent,true);
+ addstatement(newstatement,temp);
+
+ addstatement(newstatement,ccallnode.createintern(n,
+ ccallparanode.create(cordconstnode.create(resultdef.size,sinttype,false),
+ ccallparanode.create(ctemprefnode.create(temp),
+ ccallparanode.create(right,
+ ccallparanode.create(left,nil)))))
+ );
+
+ { remove reused parts from original node }
+ left:=nil;
+ right:=nil;
+ { the last statement should return the value as
+ location and type, this is done be referencing the
+ temp and converting it first from a persistent temp to
+ normal temp }
+ addstatement(newstatement,ctempdeletenode.create_normal_temp(temp));
+ addstatement(newstatement,ctemprefnode.create(temp));
+ end;
+
+ var
+ procname: string[31];
+ tempn: tnode;
+ newstatement : tstatementnode;
+ temp : ttempcreatenode;
+ begin
+ result:=nil;
+ case nodetype of
+ equaln,unequaln,lten,gten:
+ begin
+ case nodetype of
+ equaln,unequaln:
+ procname := 'fpc_varset_comp_sets';
+ lten,gten:
+ begin
+ procname := 'fpc_varset_contains_sets';
+ { (left >= right) = (right <= left) }
+ if nodetype = gten then
+ begin
+ tempn := left;
+ left := right;
+ right := tempn;
+ end;
+ end;
+ end;
+ result := ccallnode.createinternres(procname,
+ ccallparanode.create(cordconstnode.create(left.resultdef.size,sinttype,false),
+ ccallparanode.create(right,
+ ccallparanode.create(left,nil))),resultdef);
+ { left and right are reused as parameters }
+ left := nil;
+ right := nil;
+ { for an unequaln, we have to negate the result of comp_sets }
+ if nodetype = unequaln then
+ result := cnotnode.create(result);
+ end;
+ addn:
+ begin
+ { optimize first loading of a set }
+ if (right.nodetype=setelementn) and
+ not(assigned(tsetelementnode(right).right)) and
+ is_emptyset(left) then
+ begin
+ result:=internalstatements(newstatement);
+
+ { create temp for result }
+ temp:=ctempcreatenode.create(resultdef,resultdef.size,tt_persistent,true);
+ addstatement(newstatement,temp);
+
+ { adjust for set base }
+ tsetelementnode(right).left:=caddnode.create(subn,
+ ctypeconvnode.create_internal(tsetelementnode(right).left,sinttype),
+ cordconstnode.create(tsetdef(resultdef).setbase,sinttype,false));
+
+ addstatement(newstatement,ccallnode.createintern('fpc_varset_create_element',
+ ccallparanode.create(ctemprefnode.create(temp),
+ ccallparanode.create(cordconstnode.create(resultdef.size,sinttype,false),
+ ccallparanode.create(tsetelementnode(right).left,nil))))
+ );
+
+ { the last statement should return the value as
+ location and type, this is done be referencing the
+ temp and converting it first from a persistent temp to
+ normal temp }
+ addstatement(newstatement,ctempdeletenode.create_normal_temp(temp));
+ addstatement(newstatement,ctemprefnode.create(temp));
+
+ tsetelementnode(right).left := nil;
+ end
+ else
+ begin
+ if right.nodetype=setelementn then
+ begin
+ result:=internalstatements(newstatement);
+
+ { create temp for result }
+ temp:=ctempcreatenode.create(resultdef,resultdef.size,tt_persistent,true);
+ addstatement(newstatement,temp);
+
+ { adjust for set base }
+ tsetelementnode(right).left:=caddnode.create(subn,
+ ctypeconvnode.create_internal(tsetelementnode(right).left,sinttype),
+ cordconstnode.create(tsetdef(resultdef).setbase,sinttype,false));
+
+ { add a range or a single element? }
+ if assigned(tsetelementnode(right).right) then
+ begin
+ { adjust for set base }
+ tsetelementnode(right).right:=caddnode.create(subn,
+ ctypeconvnode.create_internal(tsetelementnode(right).right,sinttype),
+ cordconstnode.create(tsetdef(resultdef).setbase,sinttype,false));
+ addstatement(newstatement,ccallnode.createintern('fpc_varset_set_range',
+ ccallparanode.create(cordconstnode.create(resultdef.size,sinttype,false),
+ ccallparanode.create(tsetelementnode(right).right,
+ ccallparanode.create(tsetelementnode(right).left,
+ ccallparanode.create(ctemprefnode.create(temp),
+ ccallparanode.create(left,nil))))))
+ );
+ end
+ else
+ addstatement(newstatement,ccallnode.createintern('fpc_varset_set',
+ ccallparanode.create(cordconstnode.create(resultdef.size,sinttype,false),
+ ccallparanode.create(ctypeconvnode.create_internal(tsetelementnode(right).left,sinttype),
+ ccallparanode.create(ctemprefnode.create(temp),
+ ccallparanode.create(left,nil)))))
+ );
+ { remove reused parts from original node }
+ tsetelementnode(right).right:=nil;
+ tsetelementnode(right).left:=nil;
+ left:=nil;
+ { the last statement should return the value as
+ location and type, this is done be referencing the
+ temp and converting it first from a persistent temp to
+ normal temp }
+ addstatement(newstatement,ctempdeletenode.create_normal_temp(temp));
+ addstatement(newstatement,ctemprefnode.create(temp));
+ end
+ else
+ call_varset_helper('fpc_varset_add_sets');
+ end
+ end;
+ subn:
+ call_varset_helper('fpc_varset_sub_sets');
+ symdifn:
+ call_varset_helper('fpc_varset_symdif_sets');
+ muln:
+ call_varset_helper('fpc_varset_mul_sets');
+ else
+ internalerror(200609241);
+ end;
+ end;
+
+
+ function taddnode.use_generic_mul32to64: boolean;
+ begin
+ result := true;
+ end;
+
+
+ function taddnode.try_make_mul32to64: boolean;
+
+ function canbe32bitint(v: tconstexprint): boolean;
+ begin
+ result := ((v >= int64(low(longint))) and (v <= int64(high(longint)))) or
+ ((v >= qword(low(cardinal))) and (v <= qword(high(cardinal))))
+ end;
+
+ var
+ temp: tnode;
+ begin
+ result := false;
+ if ((left.nodetype = typeconvn) and
+ is_integer(ttypeconvnode(left).left.resultdef) and
+ (not(torddef(ttypeconvnode(left).left.resultdef).ordtype in [u64bit,s64bit])) and
+ (((right.nodetype = ordconstn) and canbe32bitint(tordconstnode(right).value)) or
+ ((right.nodetype = typeconvn) and
+ is_integer(ttypeconvnode(right).left.resultdef) and
+ not(torddef(ttypeconvnode(right).left.resultdef).ordtype in [u64bit,s64bit])) and
+ ((is_signed(ttypeconvnode(left).left.resultdef) =
+ is_signed(ttypeconvnode(right).left.resultdef)) or
+ (is_signed(ttypeconvnode(left).left.resultdef) and
+ (torddef(ttypeconvnode(right).left.resultdef).ordtype in [u8bit,u16bit]))))) then
+ begin
+ temp := ttypeconvnode(left).left;
+ ttypeconvnode(left).left := nil;
+ left.free;
+ left := temp;
+ if (right.nodetype = typeconvn) then
+ begin
+ temp := ttypeconvnode(right).left;
+ ttypeconvnode(right).left := nil;
+ right.free;
+ right := temp;
+ end;
+ if (is_signed(left.resultdef)) then
+ begin
+ inserttypeconv(left,s32inttype);
+ inserttypeconv(right,s32inttype);
+ end
+ else
+ begin
+ inserttypeconv(left,u32inttype);
+ inserttypeconv(right,u32inttype);
+ end;
+ firstpass(left);
+ firstpass(right);
+ result := true;
+ end;
+ end;
+
+
+ function taddnode.first_add64bitint: tnode;
+ var
+ procname: string[31];
+ temp: tnode;
+ power: longint;
+ begin
+ result := nil;
+ { create helper calls mul }
+ if nodetype <> muln then
+ exit;
+
+ { make sure that if there is a constant, that it's on the right }
+ if left.nodetype = ordconstn then
+ begin
+ temp := right;
+ right := left;
+ left := temp;
+ end;
+
+ { can we use a shift instead of a mul? }
+ if not (cs_check_overflow in current_settings.localswitches) and
+ (right.nodetype = ordconstn) and
+ ispowerof2(tordconstnode(right).value,power) then
+ begin
+ tordconstnode(right).value := power;
+ result := cshlshrnode.create(shln,left,right);
+ { left and right are reused }
+ left := nil;
+ right := nil;
+ { return firstpassed new node }
+ exit;
+ end;
+
+ if not(use_generic_mul32to64) and
+ try_make_mul32to64 then
+ exit;
+
+ { when currency is used set the result of the
+ parameters to s64bit, so they are not converted }
+ if is_currency(resultdef) then
+ begin
+ left.resultdef:=s64inttype;
+ right.resultdef:=s64inttype;
+ end;
+
+ { otherwise, create the parameters for the helper }
+ right := ccallparanode.create(
+ cordconstnode.create(ord(cs_check_overflow in current_settings.localswitches),pasbool8type,true),
+ ccallparanode.create(right,ccallparanode.create(left,nil)));
+ left := nil;
+ { only qword needs the unsigned code, the
+ signed code is also used for currency }
+ if is_signed(resultdef) then
+ procname := 'fpc_mul_int64'
+ else
+ procname := 'fpc_mul_qword';
+ result := ccallnode.createintern(procname,right);
+ right := nil;
+ end;
+
+
+ function taddnode.first_addfloat : tnode;
+ var
+ procname: string[31];
+ { do we need to reverse the result ? }
+ notnode : boolean;
+ fdef : tdef;
+ begin
+ result := nil;
+ notnode := false;
+ { In non-emulation mode, real opcodes are
+ emitted for floating point values.
+ }
+ if not (cs_fp_emulation in current_settings.moduleswitches) then
+ exit;
+
+ if not(target_info.system in systems_wince) then
+ begin
+ case tfloatdef(left.resultdef).floattype of
+ s32real:
+ begin
+ fdef:=search_system_type('FLOAT32REC').typedef;
+ procname:='float32';
+ end;
+ s64real:
+ begin
+ fdef:=search_system_type('FLOAT64').typedef;
+ procname:='float64';
+ end;
+ {!!! not yet implemented
+ s128real:
+ }
+ else
+ internalerror(2005082601);
+ end;
+
+ case nodetype of
+ addn:
+ procname:=procname+'_add';
+ muln:
+ procname:=procname+'_mul';
+ subn:
+ procname:=procname+'_sub';
+ slashn:
+ procname:=procname+'_div';
+ ltn:
+ procname:=procname+'_lt';
+ lten:
+ procname:=procname+'_le';
+ gtn:
+ begin
+ procname:=procname+'_le';
+ notnode:=true;
+ end;
+ gten:
+ begin
+ procname:=procname+'_lt';
+ notnode:=true;
+ end;
+ equaln:
+ procname:=procname+'_eq';
+ unequaln:
+ begin
+ procname:=procname+'_eq';
+ notnode:=true;
+ end;
+ else
+ CGMessage3(type_e_operator_not_supported_for_types,node2opstr(nodetype),left.resultdef.typename,right.resultdef.typename);
+ end;
+ end
+ else
+ begin
+ case nodetype of
+ addn:
+ procname:='ADD';
+ muln:
+ procname:='MUL';
+ subn:
+ procname:='SUB';
+ slashn:
+ procname:='DIV';
+ ltn:
+ procname:='LT';
+ lten:
+ procname:='LE';
+ gtn:
+ procname:='GT';
+ gten:
+ procname:='GE';
+ equaln:
+ procname:='EQ';
+ unequaln:
+ procname:='NE';
+ else
+ CGMessage3(type_e_operator_not_supported_for_types,node2opstr(nodetype),left.resultdef.typename,right.resultdef.typename);
+ end;
+ case tfloatdef(left.resultdef).floattype of
+ s32real:
+ begin
+ procname:=procname+'S';
+ if nodetype in [addn,muln,subn,slashn] then
+ procname:=lower(procname);
+ end;
+ s64real:
+ procname:=procname+'D';
+ {!!! not yet implemented
+ s128real:
+ }
+ else
+ internalerror(2005082602);
+ end;
+
+ end;
+ { cast softfpu result? }
+ if not(target_info.system in systems_wince) then
+ begin
+ if nodetype in [ltn,lten,gtn,gten,equaln,unequaln] then
+ resultdef:=pasbool8type;
+ result:=ctypeconvnode.create_internal(ccallnode.createintern(procname,ccallparanode.create(
+ ctypeconvnode.create_internal(right,fdef),
+ ccallparanode.create(
+ ctypeconvnode.create_internal(left,fdef),nil))),resultdef);
+ end
+ else
+ result:=ccallnode.createintern(procname,ccallparanode.create(right,
+ ccallparanode.create(left,nil)));
+ left:=nil;
+ right:=nil;
+
+ { do we need to reverse the result }
+ if notnode then
+ result:=cnotnode.create(result);
+ end;
+
+
+ function taddnode.pass_1 : tnode;
+ var
+{$ifdef addstringopt}
+ hp : tnode;
+{$endif addstringopt}
+ rd,ld : tdef;
+ i : longint;
+ lt,rt : tnodetype;
+{$ifdef cpuneedsmulhelper}
+ procname : string[32];
+{$endif cpuneedsmulhelper}
+ begin
+ result:=nil;
+
+ { Can we optimize multiple string additions into a single call?
+ This need to be done on a complete tree to detect the multiple
+ add nodes and is therefor done before the subtrees are processed }
+ if canbemultistringadd(self) then
+ begin
+ result := genmultistringadd(self);
+ exit;
+ end;
+
+ { first do the two subtrees }
+ firstpass(left);
+ firstpass(right);
+
+ if codegenerror then
+ exit;
+
+ { load easier access variables }
+ rd:=right.resultdef;
+ ld:=left.resultdef;
+ rt:=right.nodetype;
+ lt:=left.nodetype;
+
+ { int/int gives real/real! }
+ if nodetype=slashn then
+ begin
+{$ifdef cpufpemu}
+ if (current_settings.fputype=fpu_soft) or (cs_fp_emulation in current_settings.moduleswitches) then
+ begin
+ result:=first_addfloat;
+ if assigned(result) then
+ exit;
+ end;
+{$endif cpufpemu}
+ expectloc:=LOC_FPUREGISTER;
+ end
+
+ { if both are orddefs then check sub types }
+ else if (ld.typ=orddef) and (rd.typ=orddef) then
+ begin
+ { optimize multiplacation by a power of 2 }
+ if not(cs_check_overflow in current_settings.localswitches) and
+ (nodetype = muln) and
+ (((left.nodetype = ordconstn) and
+ ispowerof2(tordconstnode(left).value,i)) or
+ ((right.nodetype = ordconstn) and
+ ispowerof2(tordconstnode(right).value,i))) then
+ begin
+ if left.nodetype = ordconstn then
+ begin
+ tordconstnode(left).value := i;
+ result := cshlshrnode.create(shln,right,left);
+ end
+ else
+ begin
+ tordconstnode(right).value := i;
+ result := cshlshrnode.create(shln,left,right);
+ end;
+ left := nil;
+ right := nil;
+ exit;
+ end;
+
+ { 2 booleans ? }
+ if is_boolean(ld) and is_boolean(rd) then
+ begin
+ if (not(cs_full_boolean_eval in current_settings.localswitches) or
+ (nf_short_bool in flags)) and
+ (nodetype in [andn,orn]) then
+ expectloc:=LOC_JUMP
+ else
+ begin
+ if nodetype in [ltn,lten,gtn,gten,equaln,unequaln] then
+ expectloc:=LOC_FLAGS
+ else
+ expectloc:=LOC_REGISTER;
+ end;
+ end
+ else
+ { Both are chars? only convert to shortstrings for addn }
+ if is_char(ld) then
+ begin
+ if nodetype=addn then
+ internalerror(200103291);
+ expectloc:=LOC_FLAGS;
+ end
+{$ifndef cpu64bitaddr}
+ { is there a 64 bit type ? }
+ else if (torddef(ld).ordtype in [s64bit,u64bit,scurrency]) then
+ begin
+ result := first_add64bitint;
+ if assigned(result) then
+ exit;
+ if nodetype in [addn,subn,muln,andn,orn,xorn] then
+ expectloc:=LOC_REGISTER
+ else
+ expectloc:=LOC_JUMP;
+ end
+{$endif cpu64bitaddr}
+{$ifndef cpuneedsmulhelper}
+ { is there a cardinal? }
+ else if (torddef(ld).ordtype=u32bit) then
+ begin
+ if nodetype in [addn,subn,muln,andn,orn,xorn] then
+ expectloc:=LOC_REGISTER
+ else
+ expectloc:=LOC_FLAGS;
+ end
+{$endif cpuneedsmulhelper}
+ { generic s32bit conversion }
+ else
+ begin
+{$ifdef cpuneedsmulhelper}
+ if (nodetype=muln) and not(torddef(resultdef).ordtype in [u8bit,s8bit]) then
+ begin
+ result := nil;
+
+ case torddef(resultdef).ordtype of
+ s16bit:
+ procname := 'fpc_mul_integer';
+ u16bit:
+ procname := 'fpc_mul_word';
+ s32bit:
+ procname := 'fpc_mul_longint';
+ u32bit:
+ procname := 'fpc_mul_dword';
+ else
+ internalerror(2011022301);
+ end;
+ result := ccallnode.createintern(procname,
+ ccallparanode.create(cordconstnode.create(0,pasbool8type,false),
+ ccallparanode.create(right,
+ ccallparanode.create(left,nil))));
+ left := nil;
+ right := nil;
+ firstpass(result);
+ exit;
+ end;
+{$endif cpuneedsmulhelper}
+ if nodetype in [addn,subn,muln,andn,orn,xorn] then
+ expectloc:=LOC_REGISTER
+ else
+ expectloc:=LOC_FLAGS;
+ end;
+ end
+
+ { left side a setdef, must be before string processing,
+ else array constructor can be seen as array of char (PFV) }
+ else if (ld.typ=setdef) then
+ begin
+ { small sets are handled inline by the compiler.
+ small set doesn't have support for adding ranges }
+ if is_smallset(ld) and
+ not(
+ (right.nodetype=setelementn) and
+ assigned(tsetelementnode(right).right)
+ ) then
+ begin
+ if nodetype in [ltn,lten,gtn,gten,equaln,unequaln] then
+ expectloc:=LOC_FLAGS
+ else
+ expectloc:=LOC_REGISTER;
+ end
+ else
+ begin
+ result := first_addset;
+ if assigned(result) then
+ exit;
+ expectloc:=LOC_CREFERENCE;
+ end;
+ end
+
+ { compare pchar by addresses like BP/Delphi }
+ else if is_pchar(ld) then
+ begin
+ if nodetype in [addn,subn,muln,andn,orn,xorn] then
+ expectloc:=LOC_REGISTER
+ else
+ expectloc:=LOC_FLAGS;
+ end
+
+ { is one of the operands a string }
+ else if (ld.typ=stringdef) then
+ begin
+ if is_widestring(ld) then
+ begin
+ { this is only for add, the comparisaion is handled later }
+ expectloc:=LOC_REGISTER;
+ end
+ else if is_unicodestring(ld) then
+ begin
+ { this is only for add, the comparisaion is handled later }
+ expectloc:=LOC_REGISTER;
+ end
+ else if is_ansistring(ld) then
+ begin
+ { this is only for add, the comparisaion is handled later }
+ expectloc:=LOC_REGISTER;
+ end
+ else if is_longstring(ld) then
+ begin
+ { this is only for add, the comparisaion is handled later }
+ expectloc:=LOC_REFERENCE;
+ end
+ else
+ begin
+{$ifdef addstringopt}
+ { can create a call which isn't handled by callparatemp }
+ if canbeaddsstringcharoptnode(self) then
+ begin
+ hp := genaddsstringcharoptnode(self);
+ pass_1 := hp;
+ exit;
+ end
+ else
+{$endif addstringopt}
+ begin
+ { Fix right to be shortstring }
+ if is_char(right.resultdef) then
+ begin
+ inserttypeconv(right,cshortstringtype);
+ firstpass(right);
+ end;
+ end;
+{$ifdef addstringopt}
+ { can create a call which isn't handled by callparatemp }
+ if canbeaddsstringcsstringoptnode(self) then
+ begin
+ hp := genaddsstringcsstringoptnode(self);
+ pass_1 := hp;
+ exit;
+ end;
+{$endif addstringopt}
+ end;
+ { otherwise, let addstring convert everything }
+ result := first_addstring;
+ exit;
+ end
+
+ { is one a real float ? }
+ else if (rd.typ=floatdef) or (ld.typ=floatdef) then
+ begin
+{$ifdef cpufpemu}
+ if (current_settings.fputype=fpu_soft) or (cs_fp_emulation in current_settings.moduleswitches) then
+ begin
+ result:=first_addfloat;
+ if assigned(result) then
+ exit;
+ end;
+{$endif cpufpemu}
+ if nodetype in [addn,subn,muln,andn,orn,xorn] then
+ expectloc:=LOC_FPUREGISTER
+ else
+ expectloc:=LOC_FLAGS;
+ end
+
+ { pointer comperation and subtraction }
+ else if (ld.typ=pointerdef) then
+ begin
+ if nodetype in [addn,subn,muln,andn,orn,xorn] then
+ expectloc:=LOC_REGISTER
+ else
+ expectloc:=LOC_FLAGS;
+ end
+
+ else if is_implicit_pointer_object_type(ld) then
+ begin
+ expectloc:=LOC_FLAGS;
+ end
+
+ else if (ld.typ=classrefdef) then
+ begin
+ expectloc:=LOC_FLAGS;
+ end
+
+ { support procvar=nil,procvar<>nil }
+ else if ((ld.typ=procvardef) and (rt=niln)) or
+ ((rd.typ=procvardef) and (lt=niln)) then
+ begin
+ expectloc:=LOC_FLAGS;
+ end
+
+{$ifdef SUPPORT_MMX}
+ { mmx support, this must be before the zero based array
+ check }
+ else if (cs_mmx in current_settings.localswitches) and is_mmx_able_array(ld) and
+ is_mmx_able_array(rd) then
+ begin
+ expectloc:=LOC_MMXREGISTER;
+ end
+{$endif SUPPORT_MMX}
+
+ else if (rd.typ=pointerdef) or (ld.typ=pointerdef) then
+ begin
+ expectloc:=LOC_REGISTER;
+ end
+
+ else if (rd.typ=procvardef) and
+ (ld.typ=procvardef) and
+ equal_defs(rd,ld) then
+ begin
+ expectloc:=LOC_FLAGS;
+ end
+
+ else if (ld.typ=enumdef) then
+ begin
+ expectloc:=LOC_FLAGS;
+ end
+
+{$ifdef SUPPORT_MMX}
+ else if (cs_mmx in current_settings.localswitches) and
+ is_mmx_able_array(ld) and
+ is_mmx_able_array(rd) then
+ begin
+ expectloc:=LOC_MMXREGISTER;
+ end
+{$endif SUPPORT_MMX}
+
+ { the general solution is to convert to 32 bit int }
+ else
+ begin
+ expectloc:=LOC_REGISTER;
+ end;
+ end;
+
+{$ifdef state_tracking}
+ function Taddnode.track_state_pass(exec_known:boolean):boolean;
+
+ var factval:Tnode;
+
+ begin
+ track_state_pass:=false;
+ if left.track_state_pass(exec_known) then
+ begin
+ track_state_pass:=true;
+ left.resultdef:=nil;
+ do_typecheckpass(left);
+ end;
+ factval:=aktstate.find_fact(left);
+ if factval<>nil then
+ begin
+ track_state_pass:=true;
+ left.destroy;
+ left:=factval.getcopy;
+ end;
+ if right.track_state_pass(exec_known) then
+ begin
+ track_state_pass:=true;
+ right.resultdef:=nil;
+ do_typecheckpass(right);
+ end;
+ factval:=aktstate.find_fact(right);
+ if factval<>nil then
+ begin
+ track_state_pass:=true;
+ right.destroy;
+ right:=factval.getcopy;
+ end;
+ end;
+{$endif}
+
+end.
diff --git a/closures/compiler/nbas.pas b/closures/compiler/nbas.pas
new file mode 100644
index 0000000000..78b741fcf8
--- /dev/null
+++ b/closures/compiler/nbas.pas
@@ -0,0 +1,1130 @@
+{
+ Copyright (c) 2000-2002 by Florian Klaempfl
+
+ This unit implements some basic nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit nbas;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ globtype,
+ cpuinfo,cpubase,cgbase,cgutils,
+ aasmbase,aasmtai,aasmdata,aasmcpu,
+ node,
+ symtype;
+
+ type
+ tnothingnode = class(tnode)
+ constructor create;virtual;
+ function pass_1 : tnode;override;
+ function pass_typecheck:tnode;override;
+ end;
+ tnothingnodeclass = class of tnothingnode;
+
+ terrornode = class(tnode)
+ constructor create;virtual;
+ function pass_1 : tnode;override;
+ function pass_typecheck:tnode;override;
+ procedure mark_write;override;
+ end;
+ terrornodeclass = class of terrornode;
+
+ tasmnode = class(tnode)
+ p_asm : TAsmList;
+ currenttai : tai;
+ { Used registers in assembler block }
+ used_regs_int,
+ used_regs_fpu : tcpuregisterset;
+ constructor create(p : TAsmList);virtual;
+ constructor create_get_position;
+ destructor destroy;override;
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderefimpl;override;
+ procedure derefimpl;override;
+ function dogetcopy : tnode;override;
+ function pass_1 : tnode;override;
+ function pass_typecheck:tnode;override;
+ function docompare(p: tnode): boolean; override;
+ end;
+ tasmnodeclass = class of tasmnode;
+
+ tstatementnode = class(tbinarynode)
+ constructor create(l,r : tnode);virtual;
+ function simplify(forinline : boolean) : tnode; override;
+ function pass_1 : tnode;override;
+ function pass_typecheck:tnode;override;
+ procedure printnodetree(var t:text);override;
+ property statement : tnode read left write left;
+ property next : tnode read right write right;
+ end;
+ tstatementnodeclass = class of tstatementnode;
+
+ tblocknode = class(tunarynode)
+ constructor create(l : tnode);virtual;
+ destructor destroy; override;
+ function simplify(forinline : boolean) : tnode; override;
+ function pass_1 : tnode;override;
+ function pass_typecheck:tnode;override;
+{$ifdef state_tracking}
+ function track_state_pass(exec_known:boolean):boolean;override;
+{$endif state_tracking}
+ property statements : tnode read left write left;
+ end;
+ tblocknodeclass = class of tblocknode;
+
+ ttempcreatenode = class;
+
+ ttempinfoflag = (ti_may_be_in_reg,ti_valid,ti_nextref_set_hookoncopy_nil,
+ ti_addr_taken,ti_executeinitialisation);
+ ttempinfoflags = set of ttempinfoflag;
+
+ const
+ tempinfostoreflags = [ti_may_be_in_reg,ti_addr_taken];
+
+ type
+ { to allow access to the location by temp references even after the temp has }
+ { already been disposed and to make sure the coherency between temps and }
+ { temp references is kept after a getcopy }
+ ptempinfo = ^ttempinfo;
+ ttempinfo = record
+ { set to the copy of a tempcreate pnode (if it gets copied) so that the }
+ { refs and deletenode can hook to this copy once they get copied too }
+ hookoncopy : ptempinfo;
+ typedef : tdef;
+ typedefderef : tderef;
+ temptype : ttemptype;
+ owner : ttempcreatenode;
+ withnode : tnode;
+ location : tlocation;
+ flags : ttempinfoflags;
+ tempinitcode : tnode;
+ end;
+
+ { a node which will create a (non)persistent temp of a given type with a given }
+ { size (the size is separate to allow creating "void" temps with a custom size) }
+ ttempcreatenode = class(tnode)
+ size: tcgint;
+ tempinfo: ptempinfo;
+ ftemplvalue : tnode;
+ { * persistent temps are used in manually written code where the temp }
+ { be usable among different statements and where you can manually say }
+ { when the temp has to be freed (using a ttempdeletenode) }
+ { * non-persistent temps are mostly used in typeconversion helpers, }
+ { where the node that receives the temp becomes responsible for }
+ { freeing it. In this last case, you must use only one reference }
+ { to it and *not* generate a ttempdeletenode }
+ constructor create(_typedef: tdef; _size: tcgint; _temptype: ttemptype;allowreg:boolean); virtual;
+ constructor create_withnode(_typedef: tdef; _size: tcgint; _temptype: ttemptype; allowreg:boolean; withnode: tnode); virtual;
+ constructor create_value(_typedef:tdef; _size: tcgint; _temptype: ttemptype;allowreg:boolean; templvalue: tnode);
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderefimpl;override;
+ procedure derefimpl;override;
+ function dogetcopy: tnode; override;
+ function pass_1 : tnode; override;
+ function pass_typecheck: tnode; override;
+ function docompare(p: tnode): boolean; override;
+ procedure printnodedata(var t:text);override;
+ end;
+ ttempcreatenodeclass = class of ttempcreatenode;
+
+ { a node which is a reference to a certain temp }
+ ttemprefnode = class(tnode)
+ tempinfo: ptempinfo;
+
+ constructor create(const temp: ttempcreatenode); virtual;
+ constructor create_offset(const temp: ttempcreatenode;aoffset:longint);
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure resolveppuidx;override;
+ function dogetcopy: tnode; override;
+ function pass_1 : tnode; override;
+ function pass_typecheck : tnode; override;
+ procedure mark_write;override;
+ function docompare(p: tnode): boolean; override;
+ procedure printnodedata(var t:text);override;
+ protected
+ offset : longint;
+ private
+ tempidx : longint;
+ end;
+ ttemprefnodeclass = class of ttemprefnode;
+
+ { a node which removes a temp }
+ ttempdeletenode = class(tnode)
+ tempinfo: ptempinfo;
+ constructor create(const temp: ttempcreatenode); virtual;
+ { this will convert the persistant temp to a normal temp
+ for returning to the other nodes }
+ constructor create_normal_temp(const temp: ttempcreatenode);
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure resolveppuidx;override;
+ function dogetcopy: tnode; override;
+ function pass_1: tnode; override;
+ function pass_typecheck: tnode; override;
+ function docompare(p: tnode): boolean; override;
+ destructor destroy; override;
+ procedure printnodedata(var t:text);override;
+ protected
+ release_to_normal : boolean;
+ private
+ tempidx : longint;
+ end;
+ ttempdeletenodeclass = class of ttempdeletenode;
+
+ var
+ cnothingnode : tnothingnodeclass = tnothingnode;
+ cerrornode : terrornodeclass = terrornode;
+ casmnode : tasmnodeclass = tasmnode;
+ cstatementnode : tstatementnodeclass = tstatementnode;
+ cblocknode : tblocknodeclass = tblocknode;
+ ctempcreatenode : ttempcreatenodeclass = ttempcreatenode;
+ ctemprefnode : ttemprefnodeclass = ttemprefnode;
+ ctempdeletenode : ttempdeletenodeclass = ttempdeletenode;
+
+ { Create a blocknode and statement node for multiple statements
+ generated internally by the parser }
+ function internalstatements(var laststatement:tstatementnode):tblocknode;
+ function laststatement(block:tblocknode):tstatementnode;
+ procedure addstatement(var laststatement:tstatementnode;n:tnode);
+
+
+implementation
+
+ uses
+ cutils,
+ verbose,globals,systems,
+ symconst,symdef,defutil,defcmp,
+ pass_1,
+ nutils,nld,ncal,nflw,
+ procinfo
+ ;
+
+
+{*****************************************************************************
+ Helpers
+*****************************************************************************}
+
+ function internalstatements(var laststatement:tstatementnode):tblocknode;
+ begin
+ { create dummy initial statement }
+ laststatement := cstatementnode.create(cnothingnode.create,nil);
+ internalstatements := cblocknode.create(laststatement);
+ end;
+
+
+ function laststatement(block:tblocknode):tstatementnode;
+ begin
+ result:=tstatementnode(block.left);
+ while assigned(result) and assigned(result.right) do
+ result:=tstatementnode(result.right);
+ end;
+
+
+ procedure addstatement(var laststatement:tstatementnode;n:tnode);
+ begin
+ if assigned(laststatement.right) then
+ internalerror(200204201);
+ laststatement.right:=cstatementnode.create(n,nil);
+ laststatement:=tstatementnode(laststatement.right);
+ end;
+
+
+{*****************************************************************************
+ TFIRSTNOTHING
+*****************************************************************************}
+
+ constructor tnothingnode.create;
+ begin
+ inherited create(nothingn);
+ end;
+
+
+ function tnothingnode.pass_typecheck:tnode;
+ begin
+ result:=nil;
+ resultdef:=voidtype;
+ end;
+
+
+ function tnothingnode.pass_1 : tnode;
+ begin
+ result:=nil;
+ expectloc:=LOC_VOID;
+ end;
+
+
+{*****************************************************************************
+ TFIRSTERROR
+*****************************************************************************}
+
+ constructor terrornode.create;
+
+ begin
+ inherited create(errorn);
+ end;
+
+
+ function terrornode.pass_typecheck:tnode;
+ begin
+ result:=nil;
+ include(flags,nf_error);
+ codegenerror:=true;
+ resultdef:=generrordef;
+ end;
+
+
+ function terrornode.pass_1 : tnode;
+ begin
+ result:=nil;
+ expectloc:=LOC_VOID;
+ codegenerror:=true;
+ end;
+
+
+ procedure terrornode.mark_write;
+ begin
+ end;
+
+{*****************************************************************************
+ TSTATEMENTNODE
+*****************************************************************************}
+
+ constructor tstatementnode.create(l,r : tnode);
+
+ begin
+ inherited create(statementn,l,r);
+ end;
+
+
+ function is_exit_statement(var n: tnode; arg: pointer): foreachnoderesult;
+ begin
+ if (n.nodetype<>exitn) then
+ result:=fen_false
+ else
+ result:=fen_norecurse_true;
+ end;
+
+
+ function no_exit_statement_in_block(n: tnode): boolean;
+ begin
+ result:=not foreachnodestatic(n,@is_exit_statement,nil);
+ end;
+
+
+ function tstatementnode.simplify(forinline: boolean) : tnode;
+ begin
+ result:=nil;
+ { these "optimizations" are only to make it more easy to recognise }
+ { blocknodes which at the end of inlining only contain one single }
+ { statement. Simplifying inside blocknode.simplify could be dangerous }
+ { because if the main blocknode which makes up a procedure/function }
+ { body were replaced with a statementn/nothingn, this could cause }
+ { problems elsewhere in the compiler which expects a blocknode }
+
+ { remove next statement if it's a nothing-statement (since if it's }
+ { the last, it won't remove itself -- see next simplification) }
+ while assigned(right) and
+ (tstatementnode(right).left.nodetype = nothingn) do
+ begin
+ result:=tstatementnode(right).right;
+ tstatementnode(right).right:=nil;
+ right.free;
+ right:=result;
+ result:=nil;
+ end;
+
+ { Remove initial nothingn if there are other statements. If there }
+ { are no other statements, returning nil doesn't help (will be }
+ { interpreted as "can't be simplified") and replacing the }
+ { statementnode with a nothingnode cannot be done (because it's }
+ { possible this statementnode is a child of a blocknode, and }
+ { blocknodes are expected to only contain statementnodes) }
+ if (left.nodetype = nothingn) and
+ assigned(right) then
+ begin
+ result:=right;
+ right:=nil;
+ exit;
+ end;
+
+ { if the current statement contains a block with one statement, }
+ { replace the current statement with that block's statement }
+ { (but only if the block does not have nf_block_with_exit set }
+ { or has no exit statement, because otherwise it needs an own }
+ { exit label, see tests/test/tinline10) }
+ if (left.nodetype = blockn) and
+ (not(nf_block_with_exit in left.flags) or
+ no_exit_statement_in_block(left)) and
+ assigned(tblocknode(left).left) and
+ not assigned(tstatementnode(tblocknode(left).left).right) then
+ begin
+ result:=tblocknode(left).left;
+ tstatementnode(result).right:=right;
+ right:=nil;
+ tblocknode(left).left:=nil;
+ exit;
+ end;
+ end;
+
+
+ function tstatementnode.pass_typecheck:tnode;
+ begin
+ result:=nil;
+ resultdef:=voidtype;
+
+ { left is the statement itself calln assignn or a complex one }
+ typecheckpass(left);
+ if codegenerror then
+ exit;
+
+ { right is the next statement in the list }
+ if assigned(right) then
+ typecheckpass(right);
+ if codegenerror then
+ exit;
+ end;
+
+
+ function tstatementnode.pass_1 : tnode;
+ begin
+ result:=nil;
+ { left is the statement itself calln assignn or a complex one }
+ firstpass(left);
+ if codegenerror then
+ exit;
+ expectloc:=left.expectloc;
+ { right is the next in the list }
+ if assigned(right) then
+ firstpass(right);
+ if codegenerror then
+ exit;
+ end;
+
+
+ procedure tstatementnode.printnodetree(var t:text);
+ begin
+ printnodelist(t);
+ end;
+
+{*****************************************************************************
+ TBLOCKNODE
+*****************************************************************************}
+
+ constructor tblocknode.create(l : tnode);
+
+ begin
+ inherited create(blockn,l);
+ end;
+
+ destructor tblocknode.destroy;
+
+ var
+ hp, next: tstatementnode;
+ begin
+ hp := tstatementnode(left);
+ left := nil;
+ while assigned(hp) do
+ begin
+ next := tstatementnode(hp.right);
+ hp.right := nil;
+ hp.free;
+ hp := next;
+ end;
+ inherited destroy;
+ end;
+
+
+ function tblocknode.simplify(forinline : boolean): tnode;
+ begin
+ result := nil;
+ { Warning: never replace a blocknode with another node type, }
+ { since the block may be the main block of a procedure/function/ }
+ { main program body, and those nodes should always be blocknodes }
+ { since that's what the compiler expects elsewhere. }
+
+ { if the current block contains only one statement, and }
+ { this one statement only contains another block, replace }
+ { this block with that other block. }
+ if assigned(left) and
+ not assigned(tstatementnode(left).right) and
+ (tstatementnode(left).left.nodetype = blockn) then
+ begin
+ result:=tstatementnode(left).left;
+ tstatementnode(left).left:=nil;
+ { make sure the nf_block_with_exit flag is safeguarded }
+ result.flags:=result.flags+(flags * [nf_block_with_exit]);
+ exit;
+ end;
+ end;
+
+
+ function tblocknode.pass_typecheck:tnode;
+ var
+ hp : tstatementnode;
+ begin
+ result:=nil;
+ resultdef:=voidtype;
+
+ hp:=tstatementnode(left);
+ while assigned(hp) do
+ begin
+ if assigned(hp.left) then
+ begin
+ codegenerror:=false;
+ typecheckpass(hp.left);
+ { the resultdef of the block is the last type that is
+ returned. Normally this is a voidtype. But when the
+ compiler inserts a block of multiple statements then the
+ last entry can return a value }
+ resultdef:=hp.left.resultdef;
+ end;
+ hp:=tstatementnode(hp.right);
+ end;
+ end;
+
+
+ function tblocknode.pass_1 : tnode;
+ var
+ hp : tstatementnode;
+ //count : longint;
+ begin
+ result:=nil;
+ expectloc:=LOC_VOID;
+ //count:=0;
+ hp:=tstatementnode(left);
+ while assigned(hp) do
+ begin
+ if assigned(hp.left) then
+ begin
+ codegenerror:=false;
+ firstpass(hp.left);
+ hp.expectloc:=hp.left.expectloc;
+ end;
+ expectloc:=hp.expectloc;
+ //inc(count);
+ hp:=tstatementnode(hp.right);
+ end;
+ end;
+
+{$ifdef state_tracking}
+ function Tblocknode.track_state_pass(exec_known:boolean):boolean;
+
+ var hp:Tstatementnode;
+
+ begin
+ track_state_pass:=false;
+ hp:=Tstatementnode(left);
+ while assigned(hp) do
+ begin
+ if hp.left.track_state_pass(exec_known) then
+ track_state_pass:=true;
+ hp:=Tstatementnode(hp.right);
+ end;
+ end;
+{$endif state_tracking}
+
+{*****************************************************************************
+ TASMNODE
+*****************************************************************************}
+
+ constructor tasmnode.create(p : TAsmList);
+ begin
+ inherited create(asmn);
+ p_asm:=p;
+ currenttai:=nil;
+ used_regs_int:=[];
+ used_regs_fpu:=[];
+ end;
+
+
+ constructor tasmnode.create_get_position;
+ begin
+ inherited create(asmn);
+ p_asm:=nil;
+ include(flags,nf_get_asm_position);
+ currenttai:=nil;
+ end;
+
+
+ destructor tasmnode.destroy;
+ begin
+ if assigned(p_asm) then
+ p_asm.free;
+ inherited destroy;
+ end;
+
+
+ constructor tasmnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+ var
+ hp : tai;
+ begin
+ inherited ppuload(t,ppufile);
+ if not(nf_get_asm_position in flags) then
+ begin
+ p_asm:=TAsmList.create;
+ repeat
+ hp:=ppuloadai(ppufile);
+ if hp=nil then
+ break;
+ p_asm.concat(hp);
+ until false;
+ end
+ else
+ p_asm:=nil;
+ currenttai:=nil;
+ end;
+
+
+ procedure tasmnode.ppuwrite(ppufile:tcompilerppufile);
+ var
+ hp : tai;
+ begin
+ inherited ppuwrite(ppufile);
+{ TODO: FIXME Add saving of register sets}
+ if not(nf_get_asm_position in flags) then
+ begin
+ hp:=tai(p_asm.first);
+ while assigned(hp) do
+ begin
+ ppuwriteai(ppufile,hp);
+ hp:=tai(hp.next);
+ end;
+ { end is marked by a nil }
+ ppuwriteai(ppufile,nil);
+ end;
+ end;
+
+
+ procedure tasmnode.buildderefimpl;
+ var
+ hp : tai;
+ begin
+ inherited buildderefimpl;
+ if not(nf_get_asm_position in flags) then
+ begin
+ hp:=tai(p_asm.first);
+ while assigned(hp) do
+ begin
+ hp.buildderefimpl;
+ hp:=tai(hp.next);
+ end;
+ end;
+ end;
+
+
+ procedure tasmnode.derefimpl;
+ var
+ hp : tai;
+ begin
+ inherited derefimpl;
+ if not(nf_get_asm_position in flags) then
+ begin
+ hp:=tai(p_asm.first);
+ while assigned(hp) do
+ begin
+ hp.derefimpl;
+ hp:=tai(hp.next);
+ end;
+ end;
+ end;
+
+
+ function tasmnode.dogetcopy: tnode;
+ var
+ n: tasmnode;
+ begin
+ n := tasmnode(inherited dogetcopy);
+ if assigned(p_asm) then
+ begin
+ n.p_asm:=TAsmList.create;
+ n.p_asm.concatlistcopy(p_asm);
+ end
+ else n.p_asm := nil;
+ n.currenttai:=currenttai;
+ result:=n;
+ end;
+
+
+ function tasmnode.pass_typecheck:tnode;
+ begin
+ result:=nil;
+ resultdef:=voidtype;
+ if not(nf_get_asm_position in flags) then
+ include(current_procinfo.flags,pi_has_assembler_block);
+ end;
+
+
+ function tasmnode.pass_1 : tnode;
+ begin
+ result:=nil;
+ expectloc:=LOC_VOID;
+ end;
+
+
+ function tasmnode.docompare(p: tnode): boolean;
+ begin
+ { comparing of asmlists is not implemented (JM) }
+ docompare := false;
+ end;
+
+
+{*****************************************************************************
+ TEMPCREATENODE
+*****************************************************************************}
+
+ constructor ttempcreatenode.create(_typedef:tdef; _size: tcgint; _temptype: ttemptype;allowreg:boolean);
+ begin
+ inherited create(tempcreaten);
+ size := _size;
+ new(tempinfo);
+ fillchar(tempinfo^,sizeof(tempinfo^),0);
+ tempinfo^.typedef := _typedef;
+ tempinfo^.temptype := _temptype;
+ tempinfo^.owner := self;
+ tempinfo^.withnode := nil;
+ if allowreg and
+ { temp must fit a single register }
+ (tstoreddef(_typedef).is_fpuregable or
+ (tstoreddef(_typedef).is_intregable and
+ (_size<=TCGSize2Size[OS_64]))) and
+ { size of register operations must be known }
+ (def_cgsize(_typedef)<>OS_NO) and
+ { no init/final needed }
+ not is_managed_type(_typedef) then
+ include(tempinfo^.flags,ti_may_be_in_reg);
+ end;
+
+
+ constructor ttempcreatenode.create_withnode(_typedef: tdef; _size: tcgint; _temptype: ttemptype; allowreg:boolean; withnode: tnode);
+ begin
+ self.create(_typedef,_size,_temptype,allowreg);
+ tempinfo^.withnode:=withnode.getcopy;
+ end;
+
+
+ constructor ttempcreatenode.create_value(_typedef:tdef; _size: tcgint; _temptype: ttemptype;allowreg:boolean; templvalue: tnode);
+ begin
+ self.create(_typedef,_size,_temptype,allowreg);
+ // store in ppuwrite
+ ftemplvalue:=templvalue;
+ // create from stored ftemplvalue in ppuload
+ tempinfo^.tempinitcode:=cassignmentnode.create(ctemprefnode.create(self),ftemplvalue);
+ end;
+
+
+ function ttempcreatenode.dogetcopy: tnode;
+ var
+ n: ttempcreatenode;
+ begin
+ n := ttempcreatenode(inherited dogetcopy);
+ n.size := size;
+
+ new(n.tempinfo);
+ fillchar(n.tempinfo^,sizeof(n.tempinfo^),0);
+ n.tempinfo^.owner:=n;
+ n.tempinfo^.typedef := tempinfo^.typedef;
+ n.tempinfo^.temptype := tempinfo^.temptype;
+ n.tempinfo^.flags := tempinfo^.flags * tempinfostoreflags;
+
+ { when the tempinfo has already a hookoncopy then it is not
+ reset by a tempdeletenode }
+ if assigned(tempinfo^.hookoncopy) then
+ internalerror(200211262);
+ { signal the temprefs that the temp they point to has been copied, }
+ { so that if the refs get copied as well, they can hook themselves }
+ { to the copy of the temp }
+ tempinfo^.hookoncopy := n.tempinfo;
+ exclude(tempinfo^.flags,ti_nextref_set_hookoncopy_nil);
+
+ if assigned(tempinfo^.withnode) then
+ n.tempinfo^.withnode := tempinfo^.withnode.getcopy
+ else
+ n.tempinfo^.withnode := nil;
+
+ if assigned(tempinfo^.tempinitcode) then
+ n.tempinfo^.tempinitcode := tempinfo^.tempinitcode.getcopy
+ else
+ n.tempinfo^.tempinitcode := nil;
+
+ result := n;
+ end;
+
+
+ constructor ttempcreatenode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+
+ size:=ppufile.getlongint;
+ new(tempinfo);
+ fillchar(tempinfo^,sizeof(tempinfo^),0);
+ ppufile.getsmallset(tempinfo^.flags);
+ ppufile.getderef(tempinfo^.typedefderef);
+ tempinfo^.temptype := ttemptype(ppufile.getbyte);
+ tempinfo^.owner:=self;
+ tempinfo^.withnode:=ppuloadnode(ppufile);
+ ftemplvalue:=ppuloadnode(ppufile);
+ end;
+
+
+ procedure ttempcreatenode.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putlongint(size);
+ ppufile.putsmallset(tempinfo^.flags);
+ ppufile.putderef(tempinfo^.typedefderef);
+ ppufile.putbyte(byte(tempinfo^.temptype));
+ ppuwritenode(ppufile,tempinfo^.withnode);
+ ppuwritenode(ppufile,ftemplvalue);
+ end;
+
+
+ procedure ttempcreatenode.buildderefimpl;
+ begin
+ inherited buildderefimpl;
+ tempinfo^.typedefderef.build(tempinfo^.typedef);
+ if assigned(tempinfo^.withnode) then
+ tempinfo^.withnode.buildderefimpl;
+ if assigned(ftemplvalue) then
+ ftemplvalue.buildderefimpl;
+ end;
+
+
+ procedure ttempcreatenode.derefimpl;
+ begin
+ inherited derefimpl;
+ tempinfo^.typedef:=tdef(tempinfo^.typedefderef.resolve);
+ if assigned(tempinfo^.withnode) then
+ tempinfo^.withnode.derefimpl;
+ if assigned(ftemplvalue) then
+ begin
+ ftemplvalue.derefimpl;
+ tempinfo^.tempinitcode:=cassignmentnode.create(ctemprefnode.create(self),ftemplvalue);
+ end;
+ end;
+
+
+ function ttempcreatenode.pass_1 : tnode;
+ begin
+ result := nil;
+ expectloc:=LOC_VOID;
+ if (tempinfo^.typedef.needs_inittable) then
+ include(current_procinfo.flags,pi_needs_implicit_finally);
+ if assigned(tempinfo^.withnode) then
+ firstpass(tempinfo^.withnode);
+ if assigned(tempinfo^.tempinitcode) then
+ firstpass(tempinfo^.tempinitcode);
+ end;
+
+
+ function ttempcreatenode.pass_typecheck: tnode;
+ begin
+ result := nil;
+ { a tempcreatenode doesn't have a resultdef, only temprefnodes do }
+ resultdef := voidtype;
+ if assigned(tempinfo^.withnode) then
+ typecheckpass(tempinfo^.withnode);
+ if assigned(tempinfo^.tempinitcode) then
+ typecheckpass(tempinfo^.tempinitcode);
+ end;
+
+
+ function ttempcreatenode.docompare(p: tnode): boolean;
+ begin
+ result :=
+ inherited docompare(p) and
+ (ttempcreatenode(p).size = size) and
+ (ttempcreatenode(p).tempinfo^.flags*tempinfostoreflags=tempinfo^.flags*tempinfostoreflags) and
+ equal_defs(ttempcreatenode(p).tempinfo^.typedef,tempinfo^.typedef) and
+ (ttempcreatenode(p).tempinfo^.withnode.isequal(tempinfo^.withnode)) and
+ (ttempcreatenode(p).tempinfo^.tempinitcode.isequal(tempinfo^.tempinitcode));
+ end;
+
+
+ procedure ttempcreatenode.printnodedata(var t:text);
+ begin
+ inherited printnodedata(t);
+ writeln(t,printnodeindention,'size = ',size,', temptypedef = ',tempinfo^.typedef.typesymbolprettyname,' = "',
+ tempinfo^.typedef.GetTypeName,'", tempinfo = $',hexstr(ptrint(tempinfo),sizeof(ptrint)*2));
+ end;
+
+{*****************************************************************************
+ TEMPREFNODE
+*****************************************************************************}
+
+ constructor ttemprefnode.create(const temp: ttempcreatenode);
+ begin
+ inherited create(temprefn);
+ tempinfo := temp.tempinfo;
+ offset:=0;
+ end;
+
+
+ constructor ttemprefnode.create_offset(const temp: ttempcreatenode;aoffset:longint);
+ begin
+ self.create(temp);
+ offset := aoffset;
+ end;
+
+
+ function ttemprefnode.dogetcopy: tnode;
+ var
+ n: ttemprefnode;
+ begin
+ n := ttemprefnode(inherited dogetcopy);
+ n.offset := offset;
+
+ if assigned(tempinfo^.hookoncopy) then
+ { if the temp has been copied, assume it becomes a new }
+ { temp which has to be hooked by the copied reference }
+ begin
+ { hook the ref to the copied temp }
+ n.tempinfo := tempinfo^.hookoncopy;
+ { if we passed a ttempdeletenode that changed the temp }
+ { from a persistent one into a normal one, we must be }
+ { the last reference (since our parent should free the }
+ { temp (JM) }
+ if (ti_nextref_set_hookoncopy_nil in tempinfo^.flags) then
+ tempinfo^.hookoncopy := nil;
+ end
+ else
+ { if the temp we refer to hasn't been copied, assume }
+ { we're just a new reference to that temp }
+ begin
+ n.tempinfo := tempinfo;
+ end;
+
+ if not assigned(n.tempinfo) then
+ internalerror(2005071901);
+
+ result := n;
+ end;
+
+
+ constructor ttemprefnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ tempidx:=ppufile.getlongint;
+ offset:=ppufile.getlongint;
+ end;
+
+
+ procedure ttemprefnode.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putlongint(tempinfo^.owner.ppuidx);
+ ppufile.putlongint(offset);
+ end;
+
+
+ procedure ttemprefnode.resolveppuidx;
+ var
+ temp : ttempcreatenode;
+ begin
+ temp:=ttempcreatenode(nodeppuidxget(tempidx));
+ if temp.nodetype<>tempcreaten then
+ internalerror(200311075);
+ tempinfo:=temp.tempinfo;
+ end;
+
+
+ function ttemprefnode.pass_1 : tnode;
+ begin
+ expectloc := LOC_REFERENCE;
+ if not tempinfo^.typedef.needs_inittable and
+ (ti_may_be_in_reg in tempinfo^.flags) then
+ begin
+ if tempinfo^.typedef.typ=floatdef then
+ begin
+ if not use_vectorfpu(tempinfo^.typedef) then
+ if (tempinfo^.temptype = tt_persistent) then
+ expectloc := LOC_CFPUREGISTER
+ else
+ expectloc := LOC_FPUREGISTER
+ else
+ if (tempinfo^.temptype = tt_persistent) then
+ expectloc := LOC_CMMREGISTER
+ else
+ expectloc := LOC_MMREGISTER
+ end
+ else
+ begin
+ if (tempinfo^.temptype = tt_persistent) then
+ expectloc := LOC_CREGISTER
+ else
+ expectloc := LOC_REGISTER;
+ end;
+ end;
+ result := nil;
+ end;
+
+
+ function ttemprefnode.pass_typecheck: tnode;
+ begin
+ { check if the temp is already resultdef passed }
+ if not assigned(tempinfo^.typedef) then
+ internalerror(200108233);
+ result := nil;
+ resultdef := tempinfo^.typedef;
+ end;
+
+
+ function ttemprefnode.docompare(p: tnode): boolean;
+ begin
+ result :=
+ inherited docompare(p) and
+ (ttemprefnode(p).tempinfo = tempinfo) and
+ (ttemprefnode(p).offset = offset);
+ end;
+
+
+ procedure ttemprefnode.mark_write;
+
+ begin
+ include(flags,nf_write);
+ end;
+
+ procedure ttemprefnode.printnodedata(var t:text);
+ begin
+ inherited printnodedata(t);
+ writeln(t,printnodeindention,'temptypedef = ',tempinfo^.typedef.typesymbolprettyname,' = "',
+ tempinfo^.typedef.GetTypeName,'", tempinfo = $',hexstr(ptrint(tempinfo),sizeof(ptrint)*2));
+ end;
+
+
+{*****************************************************************************
+ TEMPDELETENODE
+*****************************************************************************}
+
+ constructor ttempdeletenode.create(const temp: ttempcreatenode);
+ begin
+ inherited create(tempdeleten);
+ tempinfo := temp.tempinfo;
+ release_to_normal := false;
+ end;
+
+
+ constructor ttempdeletenode.create_normal_temp(const temp: ttempcreatenode);
+ begin
+ inherited create(tempdeleten);
+ tempinfo := temp.tempinfo;
+ release_to_normal := true;
+ if tempinfo^.temptype <> tt_persistent then
+ internalerror(200204211);
+ end;
+
+
+ function ttempdeletenode.dogetcopy: tnode;
+ var
+ n: ttempdeletenode;
+ begin
+ n:=ttempdeletenode(inherited dogetcopy);
+ n.release_to_normal:=release_to_normal;
+
+ if assigned(tempinfo^.hookoncopy) then
+ { if the temp has been copied, assume it becomes a new }
+ { temp which has to be hooked by the copied deletenode }
+ begin
+ { hook the tempdeletenode to the copied temp }
+ n.tempinfo:=tempinfo^.hookoncopy;
+ { the temp shall not be used, reset hookoncopy }
+ { Only if release_to_normal is false, otherwise }
+ { the temp can still be referenced once more (JM) }
+ if (not release_to_normal) then
+ tempinfo^.hookoncopy:=nil
+ else
+ include(tempinfo^.flags,ti_nextref_set_hookoncopy_nil);
+ end
+ else
+ { if the temp we refer to hasn't been copied, we have a }
+ { problem since that means we now have two delete nodes }
+ { for one temp }
+ internalerror(200108234);
+ result:=n;
+ end;
+
+
+ constructor ttempdeletenode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ tempidx:=ppufile.getlongint;
+ release_to_normal:=(ppufile.getbyte<>0);
+ end;
+
+
+ procedure ttempdeletenode.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putlongint(tempinfo^.owner.ppuidx);
+ ppufile.putbyte(byte(release_to_normal));
+ end;
+
+
+ procedure ttempdeletenode.resolveppuidx;
+ var
+ temp : ttempcreatenode;
+ begin
+ temp:=ttempcreatenode(nodeppuidxget(tempidx));
+ if temp.nodetype<>tempcreaten then
+ internalerror(200311075);
+ tempinfo:=temp.tempinfo;
+ end;
+
+
+ function ttempdeletenode.pass_1 : tnode;
+ begin
+ expectloc:=LOC_VOID;
+ result := nil;
+ end;
+
+ function ttempdeletenode.pass_typecheck: tnode;
+ begin
+ result := nil;
+ resultdef := voidtype;
+ end;
+
+ function ttempdeletenode.docompare(p: tnode): boolean;
+ begin
+ result :=
+ inherited docompare(p) and
+ (ttemprefnode(p).tempinfo = tempinfo);
+ end;
+
+ destructor ttempdeletenode.destroy;
+ begin
+ if assigned(tempinfo^.withnode) then
+ begin
+ tempinfo^.withnode.free;
+ end;
+ dispose(tempinfo);
+ end;
+
+ procedure ttempdeletenode.printnodedata(var t:text);
+ begin
+ inherited printnodedata(t);
+ writeln(t,printnodeindention,'release_to_normal: ',release_to_normal,', temptypedef = ',tempinfo^.typedef.typesymbolprettyname,' = "',
+ tempinfo^.typedef.GetTypeName,'", tempinfo = $',hexstr(ptrint(tempinfo),sizeof(ptrint)*2));
+ end;
+
+end.
diff --git a/closures/compiler/ncal.pas b/closures/compiler/ncal.pas
new file mode 100644
index 0000000000..eeb6e26865
--- /dev/null
+++ b/closures/compiler/ncal.pas
@@ -0,0 +1,3888 @@
+{
+ This file implements the node for sub procedure calling.
+
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit ncal;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cutils,cclasses,
+ globtype,constexp,
+ paramgr,parabase,cgbase,
+ node,nbas,nutils,
+ {$ifdef state_tracking}
+ nstate,
+ {$endif state_tracking}
+ symbase,symtype,symsym,symdef,symtable;
+
+ type
+ tcallnodeflag = (
+ cnf_typedefset,
+ cnf_return_value_used,
+ cnf_do_inline,
+ cnf_inherited,
+ cnf_anon_inherited,
+ cnf_new_call,
+ cnf_dispose_call,
+ cnf_member_call, { called with implicit methodpointer tree }
+ cnf_uses_varargs, { varargs are used in the declaration }
+ cnf_create_failed, { exception thrown in constructor -> don't call beforedestruction }
+ cnf_objc_processed, { the procedure name has been set to the appropriate objc_msgSend* variant -> don't process again }
+ cnf_objc_id_call, { the procedure is a member call via id -> any ObjC method of any ObjC type in scope is fair game }
+ cnf_unit_specified { the unit in which the procedure has to be searched has been specified }
+ );
+ tcallnodeflags = set of tcallnodeflag;
+
+ tcallparanode = class;
+
+ tcallnode = class(tbinarynode)
+ private
+ { number of parameters passed from the source, this does not include the hidden parameters }
+ paralength : smallint;
+ function is_simple_para_load(p:tnode; may_be_in_reg: boolean):boolean;
+ procedure maybe_load_in_temp(var p:tnode);
+ function gen_high_tree(var p:tnode;paradef:tdef):tnode;
+ function gen_procvar_context_tree:tnode;
+ function gen_self_tree:tnode;
+ function gen_vmt_tree:tnode;
+ procedure gen_hidden_parameters;
+ function funcret_can_be_reused:boolean;
+ procedure maybe_create_funcret_node;
+ procedure bind_parasym;
+ procedure add_init_statement(n:tnode);
+ procedure add_done_statement(n:tnode);
+ procedure convert_carg_array_of_const;
+ procedure order_parameters;
+ procedure check_inlining;
+ function pass1_normal:tnode;
+ procedure register_created_object_types;
+ function get_expect_loc: tcgloc;
+ protected
+ procedure objc_convert_to_message_send;virtual;
+
+ private
+ { inlining support }
+ inlinelocals : TFPObjectList;
+ inlineinitstatement,
+ inlinecleanupstatement : tstatementnode;
+ procedure createinlineparas;
+ function replaceparaload(var n: tnode; arg: pointer): foreachnoderesult;
+ procedure createlocaltemps(p:TObject;arg:pointer);
+ function optimize_funcret_assignment(inlineblock: tblocknode): tnode;
+ function pass1_inline:tnode;
+ protected
+ pushedparasize : longint;
+ { Objective-C support: force the call node to call the routine with
+ this name rather than the name of symtableprocentry (don't store
+ to ppu, is set while processing the node) }
+ fobjcforcedprocname: pshortstring;
+ public
+ { the symbol containing the definition of the procedure }
+ { to call }
+ symtableprocentry : tprocsym;
+ symtableprocentryderef : tderef;
+ { symtable where the entry was found, needed for with support }
+ symtableproc : TSymtable;
+ { the definition of the procedure to call }
+ procdefinition : tabstractprocdef;
+ procdefinitionderef : tderef;
+ { tree that contains the pointer to the object for this method }
+ methodpointer : tnode;
+ { initialize/finalization of temps }
+ callinitblock,
+ callcleanupblock : tblocknode;
+ { function return node for initialized types or supplied return variable.
+ When the result is passed in a parameter then it is set to nil }
+ funcretnode : tnode;
+ { varargs parasyms }
+ varargsparas : tvarargsparalist;
+
+ { separately specified resultdef for some compilerprocs (e.g. }
+ { you can't have a function with an "array of char" resultdef }
+ { the RTL) (JM) }
+ typedef: tdef;
+ callnodeflags : tcallnodeflags;
+
+ { only the processor specific nodes need to override this }
+ { constructor }
+ constructor create(l:tnode; v : tprocsym;st : TSymtable; mp: tnode; callflags:tcallnodeflags);virtual;
+ constructor create_procvar(l,r:tnode);
+ constructor createintern(const name: string; params: tnode);
+ constructor createinternfromunit(const fromunit, procname: string; params: tnode);
+ constructor createinternres(const name: string; params: tnode; res:tdef);
+ constructor createinternresfromunit(const fromunit, procname: string; params: tnode; res:tdef);
+ constructor createinternreturn(const name: string; params: tnode; returnnode : tnode);
+ destructor destroy;override;
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderefimpl;override;
+ procedure derefimpl;override;
+ function dogetcopy : tnode;override;
+ { Goes through all symbols in a class and subclasses and calls
+ verify abstract for each .
+ }
+ procedure verifyabstractcalls;
+ { called for each definition in a class and verifies if a method
+ is abstract or not, if it is abstract, give out a warning
+ }
+ procedure verifyabstract(sym:TObject;arg:pointer);
+ procedure insertintolist(l : tnodelist);override;
+ function pass_1 : tnode;override;
+ function pass_typecheck:tnode;override;
+ {$ifdef state_tracking}
+ function track_state_pass(exec_known:boolean):boolean;override;
+ {$endif state_tracking}
+ function docompare(p: tnode): boolean; override;
+ procedure printnodedata(var t:text);override;
+ function para_count:longint;
+ function required_para_count:longint;
+ { checks if there are any parameters which end up at the stack, i.e.
+ which have LOC_REFERENCE and set pi_has_stackparameter if this applies }
+ procedure check_stack_parameters;
+ { force the name of the to-be-called routine to a particular string,
+ used for Objective-C message sending. }
+ property parameters : tnode read left write left;
+ property pushed_parasize: longint read pushedparasize;
+ private
+ AbstractMethodsList : TFPHashList;
+ end;
+ tcallnodeclass = class of tcallnode;
+
+ tcallparaflag = (
+ cpf_is_colon_para,
+ cpf_varargs_para { belongs this para to varargs }
+ );
+ tcallparaflags = set of tcallparaflag;
+
+ tcallparanode = class(ttertiarynode)
+ private
+ fcontains_stack_tainting_call_cached,
+ ffollowed_by_stack_tainting_call_cached : boolean;
+ public
+ callparaflags : tcallparaflags;
+ parasym : tparavarsym;
+ { only the processor specific nodes need to override this }
+ { constructor }
+ constructor create(expr,next : tnode);virtual;
+ destructor destroy;override;
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ function dogetcopy : tnode;override;
+ procedure insertintolist(l : tnodelist);override;
+ function pass_typecheck : tnode;override;
+ function pass_1 : tnode;override;
+ procedure get_paratype;
+ procedure firstcallparan;
+ procedure insert_typeconv;
+ procedure secondcallparan;virtual;abstract;
+ function docompare(p: tnode): boolean; override;
+ procedure printnodetree(var t:text);override;
+ { returns whether a parameter contains a type conversion from }
+ { a refcounted into a non-refcounted type }
+ function can_be_inlined: boolean;
+
+ property nextpara : tnode read right write right;
+ { third is reused to store the parameter name (only while parsing
+ vardispatch calls, never in real node tree) and copy of 'high'
+ parameter tree when the parameter is an open array of managed type }
+ property parametername : tnode read third write third;
+
+ { returns whether the evaluation of this parameter involves a
+ stack tainting call }
+ function contains_stack_tainting_call: boolean;
+ { initialises the fcontains_stack_tainting_call_cached field with the
+ result of contains_stack_tainting_call so that it can be quickly
+ accessed via the contains_stack_tainting_call_cached property }
+ procedure init_contains_stack_tainting_call_cache;
+ { returns result of contains_stack_tainting_call cached during last
+ call to init_contains_stack_tainting_call_cache }
+ property contains_stack_tainting_call_cached: boolean read fcontains_stack_tainting_call_cached;
+ { returns whether this parameter is followed by at least one other
+ parameter whose evaluation involves a stack tainting parameter
+ (result is only valid after order_parameters has been called) }
+ property followed_by_stack_tainting_call_cached: boolean read ffollowed_by_stack_tainting_call_cached;
+ end;
+ tcallparanodeclass = class of tcallparanode;
+
+ tdispcalltype = (
+ dct_method,
+ dct_propget,
+ dct_propput
+ );
+
+ function reverseparameters(p: tcallparanode): tcallparanode;
+ function translate_disp_call(selfnode,parametersnode: tnode; calltype: tdispcalltype; const methodname : ansistring;
+ dispid : longint;resultdef : tdef) : tnode;
+
+ var
+ ccallnode : tcallnodeclass = tcallnode;
+ ccallparanode : tcallparanodeclass = tcallparanode;
+
+ { Current callnode, this is needed for having a link
+ between the callparanodes and the callnode they belong to }
+ aktcallnode : tcallnode;
+
+
+implementation
+
+ uses
+ systems,
+ verbose,globals,
+ symconst,defutil,defcmp,
+ htypechk,pass_1,
+ ncnv,nld,ninl,nadd,ncon,nmem,nset,nobjc,
+ objcutil,
+ procinfo,cpuinfo,
+ wpobase
+ ;
+
+ type
+ tobjectinfoitem = class(tlinkedlistitem)
+ objinfo : tobjectdef;
+ constructor create(def : tobjectdef);
+ end;
+
+
+{****************************************************************************
+ HELPERS
+ ****************************************************************************}
+
+ function reverseparameters(p: tcallparanode): tcallparanode;
+ var
+ hp1, hp2: tcallparanode;
+ begin
+ hp1:=nil;
+ while assigned(p) do
+ begin
+ { pull out }
+ hp2:=p;
+ p:=tcallparanode(p.right);
+ { pull in }
+ hp2.right:=hp1;
+ hp1:=hp2;
+ end;
+ reverseparameters:=hp1;
+ end;
+
+ function translate_disp_call(selfnode,parametersnode: tnode; calltype: tdispcalltype; const methodname : ansistring;
+ dispid : longint;resultdef : tdef) : tnode;
+ const
+ DISPATCH_METHOD = $1;
+ DISPATCH_PROPERTYGET = $2;
+ DISPATCH_PROPERTYPUT = $4;
+ DISPATCH_PROPERTYPUTREF = $8;
+ DISPATCH_CONSTRUCT = $4000;
+
+ calltypes: array[tdispcalltype] of byte = (
+ DISPATCH_METHOD, DISPATCH_PROPERTYGET, DISPATCH_PROPERTYPUT
+ );
+ var
+ statements : tstatementnode;
+ result_data,
+ params : ttempcreatenode;
+ paramssize : cardinal;
+ calldescnode : tdataconstnode;
+ resultvalue : tnode;
+ para : tcallparanode;
+ namedparacount,
+ paracount : longint;
+ assignmenttype,
+ vardatadef,
+ pvardatadef : tdef;
+ useresult: boolean;
+ restype: byte;
+
+ names : ansistring;
+ variantdispatch : boolean;
+
+ function is_byref_para(out assign_type: tdef): boolean;
+ begin
+ result:=(assigned(para.parasym) and (para.parasym.varspez in [vs_var,vs_out,vs_constref])) or
+ (variantdispatch and valid_for_var(para.left,false));
+
+ if result or (para.left.resultdef.typ in [variantdef]) then
+ assign_type:=voidpointertype
+ else
+ case para.left.resultdef.size of
+ 1..4:
+ assign_type:=u32inttype;
+ 8:
+ assign_type:=u64inttype;
+ else
+ internalerror(2007042801);
+ end;
+ end;
+
+ function getvardef(sourcedef: TDef): longint;
+ begin
+ if is_ansistring(sourcedef) then
+ result:=varStrArg
+ else
+ if is_unicodestring(sourcedef) then
+ result:=varUStrArg
+ else
+ if is_interfacecom_or_dispinterface(sourcedef) then
+ begin
+ { distinct IDispatch and IUnknown interfaces }
+ if tobjectdef(sourcedef).is_related(tobjectdef(search_system_type('IDISPATCH').typedef)) then
+ result:=vardispatch
+ else
+ result:=varunknown;
+ end
+ else
+ result:=sourcedef.getvardef;
+ end;
+
+ begin
+ variantdispatch:=selfnode.resultdef.typ=variantdef;
+ result:=internalstatements(statements);
+
+ useresult := assigned(resultdef) and not is_void(resultdef);
+ if useresult then
+ begin
+ { get temp for the result }
+ result_data:=ctempcreatenode.create(colevarianttype,colevarianttype.size,tt_persistent,true);
+ addstatement(statements,result_data);
+ end;
+
+ { first, count and check parameters }
+ para:=tcallparanode(parametersnode);
+ paracount:=0;
+ namedparacount:=0;
+ while assigned(para) do
+ begin
+ typecheckpass(para.left);
+
+ { skip hidden dispinterface parameters like $self, $result,
+ but count skipped variantdispatch parameters. }
+ if (not variantdispatch) and (para.left.nodetype=nothingn) then
+ begin
+ para:=tcallparanode(para.nextpara);
+ continue;
+ end;
+ inc(paracount);
+ if assigned(para.parametername) then
+ inc(namedparacount);
+
+ { insert some extra casts }
+ if para.left.nodetype=stringconstn then
+ inserttypeconv_internal(para.left,cwidestringtype)
+
+ { force automatable boolean type }
+ else if is_boolean(para.left.resultdef) then
+ inserttypeconv_internal(para.left,bool16type)
+
+ { force automatable float type }
+ else if is_extended(para.left.resultdef)
+ and (current_settings.fputype<>fpu_none) then
+ inserttypeconv_internal(para.left,s64floattype)
+
+ else if is_shortstring(para.left.resultdef) then
+ inserttypeconv_internal(para.left,cwidestringtype)
+
+ { skip this check if we've already typecasted to automatable type }
+ else if (para.left.nodetype<>nothingn) and (not is_automatable(para.left.resultdef)) then
+ CGMessagePos1(para.left.fileinfo,type_e_not_automatable,para.left.resultdef.typename);
+
+ para:=tcallparanode(para.nextpara);
+ end;
+
+ { create a temp to store parameter values }
+ params:=ctempcreatenode.create(voidtype,0,tt_persistent,true);
+ addstatement(statements,params);
+
+ calldescnode:=cdataconstnode.create;
+
+ if not variantdispatch then { generate a tdispdesc record }
+ begin
+ { dispid }
+ calldescnode.append(dispid,sizeof(dispid));
+ { restype }
+ if useresult then
+ restype:=getvardef(resultdef)
+ else
+ restype:=0;
+ calldescnode.appendbyte(restype);
+ end;
+
+ calldescnode.appendbyte(calltypes[calltype]);
+ calldescnode.appendbyte(paracount);
+ calldescnode.appendbyte(namedparacount);
+
+ { build up parameters and description }
+ para:=tcallparanode(parametersnode);
+ paramssize:=0;
+ names := '';
+ while assigned(para) do
+ begin
+ { Skipped parameters are actually (varType=varError, vError=DISP_E_PARAMNOTFOUND).
+ Generate only varType here, the value will be added by RTL. }
+ if para.left.nodetype=nothingn then
+ begin
+ if variantdispatch then
+ calldescnode.appendbyte(varError);
+ para:=tcallparanode(para.nextpara);
+ continue;
+ end;
+
+ if assigned(para.parametername) then
+ begin
+ if para.parametername.nodetype=stringconstn then
+ names:=names+tstringconstnode(para.parametername).value_str+#0
+ else
+ internalerror(200611041);
+ end;
+
+ restype:=getvardef(para.left.resultdef);
+ if is_byref_para(assignmenttype) then
+ restype:=restype or $80;
+
+ { assign the argument/parameter to the temporary location }
+ { for Variants, we always pass a pointer, RTL helpers must handle it
+ depending on byref bit }
+
+ if assignmenttype=voidpointertype then
+ begin
+ addstatement(statements,cassignmentnode.create(
+ ctypeconvnode.create_internal(cderefnode.create(caddnode.create(addn,
+ caddrnode.create(ctemprefnode.create(params)),
+ cordconstnode.create(qword(paramssize),ptruinttype,false)
+ )),voidpointertype),
+ ctypeconvnode.create_internal(caddrnode.create_internal(para.left),voidpointertype)));
+ end
+ else
+ addstatement(statements,cassignmentnode.create(
+ ctypeconvnode.create_internal(cderefnode.create(caddnode.create(addn,
+ caddrnode.create(ctemprefnode.create(params)),
+ cordconstnode.create(paramssize,ptruinttype,false)
+ )),assignmenttype),
+ ctypeconvnode.create_internal(para.left,assignmenttype)));
+
+ inc(paramssize,max(voidpointertype.size,assignmenttype.size));
+ calldescnode.appendbyte(restype);
+
+ para.left:=nil;
+ para:=tcallparanode(para.nextpara);
+ end;
+
+ { Set final size for parameter block }
+ params.size:=paramssize;
+
+ { old argument list skeleton isn't needed anymore }
+ parametersnode.free;
+
+ pvardatadef:=tpointerdef(search_system_type('PVARDATA').typedef);
+
+ if useresult then
+ resultvalue:=caddrnode.create(ctemprefnode.create(result_data))
+ else
+ resultvalue:=cpointerconstnode.create(0,voidpointertype);
+
+ if variantdispatch then
+ begin
+ calldescnode.append(pointer(methodname)^,length(methodname));
+ calldescnode.appendbyte(0);
+ calldescnode.append(pointer(names)^,length(names));
+
+ { actual call }
+ vardatadef:=trecorddef(search_system_type('TVARDATA').typedef);
+
+ addstatement(statements,ccallnode.createintern('fpc_dispinvoke_variant',
+ { parameters are passed always reverted, i.e. the last comes first }
+ ccallparanode.create(caddrnode.create(ctemprefnode.create(params)),
+ ccallparanode.create(caddrnode.create(calldescnode),
+ ccallparanode.create(ctypeconvnode.create_internal(selfnode,vardatadef),
+ ccallparanode.create(ctypeconvnode.create_internal(resultvalue,pvardatadef),nil)))))
+ );
+ end
+ else
+ begin
+ addstatement(statements,ccallnode.createintern('fpc_dispatch_by_id',
+ { parameters are passed always reverted, i.e. the last comes first }
+ ccallparanode.create(caddrnode.create(ctemprefnode.create(params)),
+ ccallparanode.create(caddrnode.create(calldescnode),
+ ccallparanode.create(ctypeconvnode.create_internal(selfnode,voidpointertype),
+ ccallparanode.create(ctypeconvnode.create_internal(resultvalue,pvardatadef),nil)))))
+ );
+ end;
+ addstatement(statements,ctempdeletenode.create(params));
+ if useresult then
+ begin
+ { clean up }
+ addstatement(statements,ctempdeletenode.create_normal_temp(result_data));
+ addstatement(statements,ctemprefnode.create(result_data));
+ end;
+ end;
+
+
+{****************************************************************************
+ TOBJECTINFOITEM
+ ****************************************************************************}
+
+ constructor tobjectinfoitem.create(def : tobjectdef);
+ begin
+ inherited create;
+ objinfo := def;
+ end;
+
+
+{****************************************************************************
+ TCALLPARANODE
+ ****************************************************************************}
+
+ constructor tcallparanode.create(expr,next : tnode);
+
+ begin
+ inherited create(callparan,expr,next,nil);
+ if not assigned(expr) then
+ internalerror(200305091);
+ expr.fileinfo:=fileinfo;
+ callparaflags:=[];
+ if expr.nodetype = typeconvn then
+ ttypeconvnode(expr).warn_pointer_to_signed:=false;
+ end;
+
+ destructor tcallparanode.destroy;
+
+ begin
+ inherited destroy;
+ end;
+
+
+ constructor tcallparanode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ ppufile.getsmallset(callparaflags);
+ end;
+
+
+ procedure tcallparanode.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putsmallset(callparaflags);
+ end;
+
+
+ function tcallparanode.dogetcopy : tnode;
+
+ var
+ n : tcallparanode;
+
+ begin
+ n:=tcallparanode(inherited dogetcopy);
+ n.callparaflags:=callparaflags;
+ n.parasym:=parasym;
+ result:=n;
+ end;
+
+
+ procedure tcallparanode.insertintolist(l : tnodelist);
+ begin
+ end;
+
+
+ function tcallparanode.pass_typecheck : tnode;
+ begin
+ { need to use get_paratype }
+ internalerror(200709251);
+ result:=nil;
+ end;
+
+
+ function tcallparanode.pass_1 : tnode;
+ begin
+ { need to use firstcallparan }
+ internalerror(200709252);
+ result:=nil;
+ end;
+
+
+ procedure tcallparanode.get_paratype;
+ var
+ old_array_constructor : boolean;
+ begin
+ if assigned(right) then
+ tcallparanode(right).get_paratype;
+ old_array_constructor:=allow_array_constructor;
+ allow_array_constructor:=true;
+ typecheckpass(left);
+ if assigned(third) then
+ typecheckpass(third);
+ allow_array_constructor:=old_array_constructor;
+ if codegenerror then
+ resultdef:=generrordef
+ else
+ resultdef:=left.resultdef;
+ end;
+
+
+ procedure tcallparanode.firstcallparan;
+ begin
+ if assigned(right) then
+ tcallparanode(right).firstcallparan;
+ if not assigned(left.resultdef) then
+ get_paratype;
+ firstpass(left);
+ if assigned(third) then
+ firstpass(third);
+ expectloc:=left.expectloc;
+ end;
+
+
+ procedure tcallparanode.insert_typeconv;
+ var
+ olddef : tdef;
+ hp : tnode;
+ block : tblocknode;
+ statements : tstatementnode;
+ temp : ttempcreatenode;
+ owningprocdef: tprocdef;
+ begin
+ { Be sure to have the resultdef }
+ if not assigned(left.resultdef) then
+ typecheckpass(left);
+
+ if (left.nodetype<>nothingn) then
+ begin
+ { convert loads of the function result variable into procvars
+ representing the current function in case the formal parameter is
+ a procvar (CodeWarrior Pascal contains the same kind of
+ automatic disambiguation; you can use the function name in both
+ meanings, so we cannot statically pick either the function result
+ or the function definition in pexpr) }
+ if (m_mac in current_settings.modeswitches) and
+ (parasym.vardef.typ=procvardef) and
+ is_ambiguous_funcret_load(left,owningprocdef) then
+ begin
+ hp:=cloadnode.create_procvar(owningprocdef.procsym,owningprocdef,owningprocdef.procsym.owner);
+ typecheckpass(hp);
+ left.free;
+ left:=hp;
+ end;
+
+ { Convert tp procvars, this is needs to be done
+ here to make the change permanent. in the overload
+ choosing the changes are only made temporarily }
+ if (left.resultdef.typ=procvardef) and
+ not(parasym.vardef.typ in [procvardef,formaldef]) then
+ begin
+ if maybe_call_procvar(left,true) then
+ resultdef:=left.resultdef
+ end;
+
+ { Remove implicitly inserted typecast to pointer for
+ @procvar in macpas }
+ if (m_mac_procvar in current_settings.modeswitches) and
+ (parasym.vardef.typ=procvardef) and
+ (left.nodetype=typeconvn) and
+ is_voidpointer(left.resultdef) and
+ (ttypeconvnode(left).left.nodetype=typeconvn) and
+ (ttypeconvnode(ttypeconvnode(left).left).convtype=tc_proc_2_procvar) then
+ begin
+ hp:=left;
+ left:=ttypeconvnode(left).left;
+ ttypeconvnode(hp).left:=nil;
+ hp.free;
+ end;
+ maybe_global_proc_to_nested(left,parasym.vardef);
+
+ { Handle varargs and hidden paras directly, no typeconvs or }
+ { pass_typechecking needed }
+ if (cpf_varargs_para in callparaflags) then
+ begin
+ { this should only happen vor C varargs }
+ { the necessary conversions have already been performed in }
+ { tarrayconstructornode.insert_typeconvs }
+ set_varstate(left,vs_read,[vsf_must_be_valid]);
+ insert_varargstypeconv(left,true);
+ resultdef:=left.resultdef;
+ { also update parasym type to get the correct parameter location
+ for the new types }
+ parasym.vardef:=left.resultdef;
+ end
+ else
+ if (vo_is_hidden_para in parasym.varoptions) then
+ begin
+ set_varstate(left,vs_read,[vsf_must_be_valid]);
+ resultdef:=left.resultdef;
+ end
+ else
+ begin
+
+ { Do we need arrayconstructor -> set conversion, then insert
+ it here before the arrayconstructor node breaks the tree
+ with its conversions of enum->ord }
+ if (left.nodetype=arrayconstructorn) and
+ (parasym.vardef.typ=setdef) then
+ inserttypeconv(left,parasym.vardef);
+
+ { set some settings needed for arrayconstructor }
+ if is_array_constructor(left.resultdef) then
+ begin
+ if left.nodetype<>arrayconstructorn then
+ internalerror(200504041);
+ if is_array_of_const(parasym.vardef) then
+ begin
+ { force variant array }
+ include(left.flags,nf_forcevaria);
+ end
+ else
+ begin
+ include(left.flags,nf_novariaallowed);
+ { now that the resultting type is know we can insert the required
+ typeconvs for the array constructor }
+ if parasym.vardef.typ=arraydef then
+ tarrayconstructornode(left).force_type(tarraydef(parasym.vardef).elementdef);
+ end;
+ end;
+
+ { check if local proc/func is assigned to procvar }
+ if left.resultdef.typ=procvardef then
+ test_local_to_procvar(tprocvardef(left.resultdef),parasym.vardef);
+
+ { test conversions }
+ if not(is_shortstring(left.resultdef) and
+ is_shortstring(parasym.vardef)) and
+ (parasym.vardef.typ<>formaldef) and
+ not(parasym.univpara) then
+ begin
+ { Process open parameters }
+ if paramanager.push_high_param(parasym.varspez,parasym.vardef,aktcallnode.procdefinition.proccalloption) then
+ begin
+ { insert type conv but hold the ranges of the array }
+ olddef:=left.resultdef;
+ inserttypeconv(left,parasym.vardef);
+ left.resultdef:=olddef;
+ end
+ else
+ begin
+ check_ranges(left.fileinfo,left,parasym.vardef);
+ inserttypeconv(left,parasym.vardef);
+ end;
+ if codegenerror then
+ exit;
+ end;
+
+ { truncate shortstring value parameters at the caller side if }
+ { they are passed by value (if passed by reference, then the }
+ { callee will truncate when copying in the string) }
+ { This happens e.g. on x86_64 for small strings }
+ if is_shortstring(left.resultdef) and
+ is_shortstring(parasym.vardef) and
+ (parasym.varspez=vs_value) and
+ not paramanager.push_addr_param(parasym.varspez,parasym.vardef,
+ aktcallnode.procdefinition.proccalloption) and
+ ((is_open_string(left.resultdef) and
+ (tstringdef(parasym.vardef).len < 255)) or
+ (not is_open_string(left.resultdef) and
+ { when a stringconstn is typeconverted, then only its }
+ { def is modified, not the contents (needed because in }
+ { Delphi/TP, if you pass a longer string to a const }
+ { parameter, then the callee has to see this longer }
+ { string) }
+ (((left.nodetype<>stringconstn) and
+ (tstringdef(parasym.vardef).len<tstringdef(left.resultdef).len)) or
+ ((left.nodetype=stringconstn) and
+ (tstringdef(parasym.vardef).len<tstringconstnode(left).len))))) then
+ begin
+ block:=internalstatements(statements);
+ { temp for the new string }
+ temp:=ctempcreatenode.create(parasym.vardef,parasym.vardef.size,
+ tt_persistent,true);
+ addstatement(statements,temp);
+ { assign parameter to temp }
+ addstatement(statements,cassignmentnode.create(ctemprefnode.create(temp),left));
+ left:=nil;
+ { release temp after next use }
+ addstatement(statements,ctempdeletenode.create_normal_temp(temp));
+ addstatement(statements,ctemprefnode.create(temp));
+ typecheckpass(tnode(block));
+ left:=block;
+ end;
+
+ { check var strings }
+ if (cs_strict_var_strings in current_settings.localswitches) and
+ is_shortstring(left.resultdef) and
+ is_shortstring(parasym.vardef) and
+ (parasym.varspez in [vs_out,vs_var,vs_constref]) and
+ not(is_open_string(parasym.vardef)) and
+ not(equal_defs(left.resultdef,parasym.vardef)) then
+ begin
+ CGMessagePos(left.fileinfo,type_e_strict_var_string_violation);
+ end;
+
+ { passing a value to an "univ" parameter implies an explicit
+ typecast to the parameter type. Must be done before the
+ valid_for_var() check, since the typecast can result in
+ an invalid lvalue in case of var/out parameters. }
+ if (parasym.univpara) then
+ begin
+ { load procvar if a procedure is passed }
+ if ((m_tp_procvar in current_settings.modeswitches) or
+ (m_mac_procvar in current_settings.modeswitches)) and
+ (left.nodetype=calln) and
+ (is_void(left.resultdef)) then
+ begin
+ load_procvar_from_calln(left);
+ { load_procvar_from_calln() creates a loadn for a
+ a procedure, which means that the type conversion
+ below will type convert the first instruction
+ bytes of the procedure -> convert to a procvar }
+ left:=ctypeconvnode.create_proc_to_procvar(left);
+ typecheckpass(left);
+ end;
+ inserttypeconv_explicit(left,parasym.vardef);
+ end;
+
+ { Handle formal parameters separate }
+ if (parasym.vardef.typ=formaldef) then
+ begin
+ { load procvar if a procedure is passed }
+ if ((m_tp_procvar in current_settings.modeswitches) or
+ (m_mac_procvar in current_settings.modeswitches)) and
+ (left.nodetype=calln) and
+ (is_void(left.resultdef)) then
+ load_procvar_from_calln(left);
+
+ case parasym.varspez of
+ vs_var,
+ vs_constref,
+ vs_out :
+ begin
+ if not valid_for_formal_var(left,true) then
+ CGMessagePos(left.fileinfo,parser_e_illegal_parameter_list);
+ end;
+ vs_const :
+ begin
+ if not valid_for_formal_const(left,true) then
+ CGMessagePos(left.fileinfo,parser_e_illegal_parameter_list);
+ end;
+ end;
+ end
+ else
+ begin
+ { check if the argument is allowed }
+ if (parasym.varspez in [vs_out,vs_var]) then
+ valid_for_var(left,true);
+ end;
+
+ if parasym.varspez in [vs_var,vs_out,vs_constref] then
+ set_unique(left);
+
+ { When the address needs to be pushed then the register is
+ not regable. Exception is when the location is also a var
+ parameter and we can pass the address transparently (but
+ that is handled by make_not_regable if ra_addr_regable is
+ passed, and make_not_regable always needs to called for
+ the ra_addr_taken info for non-invisble parameters) }
+ if (
+ not(
+ (vo_is_hidden_para in parasym.varoptions) and
+ (left.resultdef.typ in [pointerdef,classrefdef])
+ ) and
+ paramanager.push_addr_param(parasym.varspez,parasym.vardef,
+ aktcallnode.procdefinition.proccalloption)
+ ) then
+ { pushing the address of a variable to take the place of a temp }
+ { as the complex function result of a function does not make its }
+ { address escape the current block, as the "address of the }
+ { function result" is not something which can be stored }
+ { persistently by the callee (it becomes invalid when the callee }
+ { returns) }
+ if not(vo_is_funcret in parasym.varoptions) then
+ make_not_regable(left,[ra_addr_regable,ra_addr_taken])
+ else
+ make_not_regable(left,[ra_addr_regable]);
+
+ case parasym.varspez of
+ vs_out :
+ begin
+ { first set written separately to avoid false }
+ { uninitialized warnings (tbs/tb0542) }
+ set_varstate(left,vs_written,[]);
+ set_varstate(left,vs_readwritten,[]);
+ end;
+ vs_var,
+ vs_constref:
+ set_varstate(left,vs_readwritten,[vsf_must_be_valid,vsf_use_hints]);
+ else
+ set_varstate(left,vs_read,[vsf_must_be_valid]);
+ end;
+ { must only be done after typeconv PM }
+ resultdef:=parasym.vardef;
+ end;
+ end;
+
+ { process next node }
+ if assigned(right) then
+ tcallparanode(right).insert_typeconv;
+ end;
+
+
+ function tcallparanode.can_be_inlined: boolean;
+ var
+ n: tnode;
+ begin
+ n:=left;
+ result:=false;
+ while assigned(n) and
+ (n.nodetype=typeconvn) do
+ begin
+ { look for type conversion nodes which convert a }
+ { refcounted type into a non-refcounted type }
+ if not is_managed_type(n.resultdef) and
+ is_managed_type(ttypeconvnode(n).left.resultdef) then
+ exit;
+ n:=ttypeconvnode(n).left;
+ end;
+ { also check for dereferencing constant pointers, like }
+ { tsomerecord(nil^) passed to a const r: tsomerecord }
+ { parameter }
+ if (n.nodetype=derefn) then
+ begin
+ repeat
+ n:=tunarynode(n).left;
+ until (n.nodetype<>typeconvn);
+ if (n.nodetype in [niln,pointerconstn]) then
+ exit
+ end;
+ result:=true;
+ end;
+
+
+ function check_contains_stack_tainting_call(var n: tnode; arg: pointer): foreachnoderesult;
+ begin
+ if (n.nodetype=calln) and
+ tcallnode(n).procdefinition.stack_tainting_parameter(callerside) then
+ result:=fen_norecurse_true
+ else
+ result:=fen_false;
+ end;
+
+
+ function tcallparanode.contains_stack_tainting_call: boolean;
+ begin
+ result:=foreachnodestatic(pm_postprocess,left,@check_contains_stack_tainting_call,nil);
+ end;
+
+
+ procedure tcallparanode.init_contains_stack_tainting_call_cache;
+ begin
+ fcontains_stack_tainting_call_cached:=contains_stack_tainting_call;
+ end;
+
+
+ function tcallparanode.docompare(p: tnode): boolean;
+ begin
+ docompare :=
+ inherited docompare(p) and
+ (callparaflags = tcallparanode(p).callparaflags)
+ ;
+ end;
+
+
+ procedure tcallparanode.printnodetree(var t:text);
+ begin
+ printnodelist(t);
+ end;
+
+
+{****************************************************************************
+ TCALLNODE
+ ****************************************************************************}
+
+ constructor tcallnode.create(l:tnode;v : tprocsym;st : TSymtable; mp: tnode; callflags:tcallnodeflags);
+ begin
+ inherited create(calln,l,nil);
+ symtableprocentry:=v;
+ symtableproc:=st;
+ callnodeflags:=callflags+[cnf_return_value_used];
+ methodpointer:=mp;
+ callinitblock:=nil;
+ callcleanupblock:=nil;
+ procdefinition:=nil;
+ funcretnode:=nil;
+ paralength:=-1;
+ varargsparas:=nil;
+ end;
+
+
+ constructor tcallnode.create_procvar(l,r:tnode);
+ begin
+ inherited create(calln,l,r);
+ symtableprocentry:=nil;
+ symtableproc:=nil;
+ methodpointer:=nil;
+ callinitblock:=nil;
+ callcleanupblock:=nil;
+ procdefinition:=nil;
+ callnodeflags:=[cnf_return_value_used];
+ funcretnode:=nil;
+ paralength:=-1;
+ varargsparas:=nil;
+ end;
+
+
+ constructor tcallnode.createintern(const name: string; params: tnode);
+ var
+ srsym: tsym;
+ begin
+ srsym := tsym(systemunit.Find(name));
+ if not assigned(srsym) and
+ (cs_compilesystem in current_settings.moduleswitches) then
+ srsym := tsym(systemunit.Find(upper(name)));
+ if not assigned(srsym) or
+ (srsym.typ<>procsym) then
+ Message1(cg_f_unknown_compilerproc,name);
+ create(params,tprocsym(srsym),srsym.owner,nil,[]);
+ end;
+
+
+ constructor tcallnode.createinternfromunit(const fromunit, procname: string; params: tnode);
+ var
+ srsym: tsym;
+ srsymtable: tsymtable;
+ begin
+ if not searchsym_in_named_module(fromunit,procname,srsym,srsymtable) or
+ (srsym.typ<>procsym) then
+ Message1(cg_f_unknown_compilerproc,fromunit+'.'+procname);
+ create(params,tprocsym(srsym),srsymtable,nil,[]);
+ end;
+
+
+ constructor tcallnode.createinternres(const name: string; params: tnode; res:tdef);
+ var
+ pd : tprocdef;
+ begin
+ createintern(name,params);
+ typedef:=res;
+ include(callnodeflags,cnf_typedefset);
+ pd:=tprocdef(symtableprocentry.ProcdefList[0]);
+ { both the normal and specified resultdef either have to be returned via a }
+ { parameter or not, but no mixing (JM) }
+ if paramanager.ret_in_param(typedef,pd.proccalloption) xor
+ paramanager.ret_in_param(pd.returndef,pd.proccalloption) then
+ internalerror(2001082911);
+ end;
+
+
+ constructor tcallnode.createinternresfromunit(const fromunit, procname: string; params: tnode; res:tdef);
+ var
+ pd : tprocdef;
+ begin
+ createinternfromunit(fromunit,procname,params);
+ typedef:=res;
+ include(callnodeflags,cnf_typedefset);
+ pd:=tprocdef(symtableprocentry.ProcdefList[0]);
+ { both the normal and specified resultdef either have to be returned via a }
+ { parameter or not, but no mixing (JM) }
+ if paramanager.ret_in_param(typedef,pd.proccalloption) xor
+ paramanager.ret_in_param(pd.returndef,pd.proccalloption) then
+ internalerror(200108291);
+ end;
+
+
+ constructor tcallnode.createinternreturn(const name: string; params: tnode; returnnode : tnode);
+ begin
+ createintern(name,params);
+ funcretnode:=returnnode;
+ end;
+
+
+ destructor tcallnode.destroy;
+ begin
+ methodpointer.free;
+ callinitblock.free;
+ callcleanupblock.free;
+ funcretnode.free;
+ if assigned(varargsparas) then
+ varargsparas.free;
+ stringdispose(fobjcforcedprocname);
+ inherited destroy;
+ end;
+
+
+ constructor tcallnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+ begin
+ callinitblock:=tblocknode(ppuloadnode(ppufile));
+ methodpointer:=ppuloadnode(ppufile);
+ callcleanupblock:=tblocknode(ppuloadnode(ppufile));
+ funcretnode:=ppuloadnode(ppufile);
+ inherited ppuload(t,ppufile);
+ ppufile.getderef(symtableprocentryderef);
+{ TODO: FIXME: No withsymtable support}
+ symtableproc:=nil;
+ ppufile.getderef(procdefinitionderef);
+ ppufile.getsmallset(callnodeflags);
+ end;
+
+
+ procedure tcallnode.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ ppuwritenode(ppufile,callinitblock);
+ ppuwritenode(ppufile,methodpointer);
+ ppuwritenode(ppufile,callcleanupblock);
+ ppuwritenode(ppufile,funcretnode);
+ inherited ppuwrite(ppufile);
+ ppufile.putderef(symtableprocentryderef);
+ ppufile.putderef(procdefinitionderef);
+ ppufile.putsmallset(callnodeflags);
+ end;
+
+
+ procedure tcallnode.buildderefimpl;
+ begin
+ inherited buildderefimpl;
+ symtableprocentryderef.build(symtableprocentry);
+ procdefinitionderef.build(procdefinition);
+ if assigned(methodpointer) then
+ methodpointer.buildderefimpl;
+ if assigned(callinitblock) then
+ callinitblock.buildderefimpl;
+ if assigned(callcleanupblock) then
+ callcleanupblock.buildderefimpl;
+ if assigned(funcretnode) then
+ funcretnode.buildderefimpl;
+ end;
+
+
+ procedure tcallnode.derefimpl;
+ var
+ pt : tcallparanode;
+ i : integer;
+ begin
+ inherited derefimpl;
+ symtableprocentry:=tprocsym(symtableprocentryderef.resolve);
+ if assigned(symtableprocentry) then
+ symtableproc:=symtableprocentry.owner;
+ procdefinition:=tabstractprocdef(procdefinitionderef.resolve);
+ if assigned(methodpointer) then
+ methodpointer.derefimpl;
+ if assigned(callinitblock) then
+ callinitblock.derefimpl;
+ if assigned(callcleanupblock) then
+ callcleanupblock.derefimpl;
+ if assigned(funcretnode) then
+ funcretnode.derefimpl;
+ { generic method has no procdefinition }
+ if assigned(procdefinition) then
+ begin
+ { Connect parasyms }
+ pt:=tcallparanode(left);
+ while assigned(pt) and
+ (cpf_varargs_para in pt.callparaflags) do
+ pt:=tcallparanode(pt.right);
+ for i:=procdefinition.paras.count-1 downto 0 do
+ begin
+ if not assigned(pt) then
+ internalerror(200311077);
+ pt.parasym:=tparavarsym(procdefinition.paras[i]);
+ pt:=tcallparanode(pt.right);
+ end;
+ if assigned(pt) then
+ internalerror(200311078);
+ end;
+ end;
+
+
+ function tcallnode.dogetcopy : tnode;
+ var
+ n : tcallnode;
+ i : integer;
+ hp,hpn : tparavarsym;
+ oldleft : tnode;
+ begin
+ { Need to use a hack here to prevent the parameters from being copied.
+ The parameters must be copied between callinitblock/callcleanupblock because
+ they can reference methodpointer }
+ oldleft:=left;
+ left:=nil;
+ n:=tcallnode(inherited dogetcopy);
+ left:=oldleft;
+ n.symtableprocentry:=symtableprocentry;
+ n.symtableproc:=symtableproc;
+ n.procdefinition:=procdefinition;
+ n.typedef := typedef;
+ n.callnodeflags := callnodeflags;
+ if assigned(callinitblock) then
+ n.callinitblock:=tblocknode(callinitblock.dogetcopy)
+ else
+ n.callinitblock:=nil;
+ { callinitblock is copied, now references to the temp will also be copied
+ correctly. We can now copy the parameters, funcret and methodpointer }
+ if assigned(left) then
+ n.left:=left.dogetcopy
+ else
+ n.left:=nil;
+ if assigned(methodpointer) then
+ n.methodpointer:=methodpointer.dogetcopy
+ else
+ n.methodpointer:=nil;
+ if assigned(funcretnode) then
+ n.funcretnode:=funcretnode.dogetcopy
+ else
+ n.funcretnode:=nil;
+ if assigned(callcleanupblock) then
+ n.callcleanupblock:=tblocknode(callcleanupblock.dogetcopy)
+ else
+ n.callcleanupblock:=nil;
+ if assigned(varargsparas) then
+ begin
+ n.varargsparas:=tvarargsparalist.create(true);
+ for i:=0 to varargsparas.count-1 do
+ begin
+ hp:=tparavarsym(varargsparas[i]);
+ hpn:=tparavarsym.create(hp.realname,hp.paranr,hp.varspez,hp.vardef,[]);
+ n.varargsparas.add(hpn);
+ end;
+ end
+ else
+ n.varargsparas:=nil;
+ result:=n;
+ end;
+
+
+ function tcallnode.docompare(p: tnode): boolean;
+ begin
+ docompare :=
+ inherited docompare(p) and
+ (symtableprocentry = tcallnode(p).symtableprocentry) and
+ (procdefinition = tcallnode(p).procdefinition) and
+ (methodpointer.isequal(tcallnode(p).methodpointer)) and
+ (((cnf_typedefset in callnodeflags) and (cnf_typedefset in tcallnode(p).callnodeflags) and
+ (equal_defs(typedef,tcallnode(p).typedef))) or
+ (not(cnf_typedefset in callnodeflags) and not(cnf_typedefset in tcallnode(p).callnodeflags)));
+ end;
+
+
+ procedure tcallnode.printnodedata(var t:text);
+ begin
+ if assigned(procdefinition) and
+ (procdefinition.typ=procdef) then
+ writeln(t,printnodeindention,'proc = ',tprocdef(procdefinition).fullprocname(true))
+ else
+ begin
+ if assigned(symtableprocentry) then
+ writeln(t,printnodeindention,'proc = ',symtableprocentry.name)
+ else
+ writeln(t,printnodeindention,'proc = <nil>');
+ end;
+
+ if assigned(methodpointer) then
+ begin
+ writeln(t,printnodeindention,'methodpointer =');
+ printnode(t,methodpointer);
+ end;
+
+ if assigned(callinitblock) then
+ begin
+ writeln(t,printnodeindention,'callinitblock =');
+ printnode(t,callinitblock);
+ end;
+
+ if assigned(callcleanupblock) then
+ begin
+ writeln(t,printnodeindention,'callcleanupblock =');
+ printnode(t,callcleanupblock);
+ end;
+
+ if assigned(right) then
+ begin
+ writeln(t,printnodeindention,'right =');
+ printnode(t,right);
+ end;
+
+ if assigned(left) then
+ begin
+ writeln(t,printnodeindention,'left =');
+ printnode(t,left);
+ end;
+ end;
+
+
+ procedure tcallnode.insertintolist(l : tnodelist);
+ begin
+ end;
+
+
+ procedure tcallnode.add_init_statement(n:tnode);
+ var
+ lastinitstatement : tstatementnode;
+ begin
+ if not assigned(callinitblock) then
+ callinitblock:=internalstatements(lastinitstatement)
+ else
+ lastinitstatement:=laststatement(callinitblock);
+ { all these nodes must be immediately typechecked, because this routine }
+ { can be called from pass_1 (i.e., after typecheck has already run) and }
+ { moreover, the entire blocks themselves are also only typechecked in }
+ { pass_1, while the the typeinfo is already required after the }
+ { typecheck pass for simplify purposes (not yet perfect, because the }
+ { statementnodes themselves are not typechecked this way) }
+ typecheckpass(n);
+ addstatement(lastinitstatement,n);
+ end;
+
+
+ procedure tcallnode.add_done_statement(n:tnode);
+ var
+ lastdonestatement : tstatementnode;
+ begin
+ if not assigned(callcleanupblock) then
+ callcleanupblock:=internalstatements(lastdonestatement)
+ else
+ lastdonestatement:=laststatement(callcleanupblock);
+ { see comments in add_init_statement }
+ typecheckpass(n);
+ addstatement(lastdonestatement,n);
+ end;
+
+
+ function tcallnode.para_count:longint;
+ var
+ ppn : tcallparanode;
+ begin
+ result:=0;
+ ppn:=tcallparanode(left);
+ while assigned(ppn) do
+ begin
+ if not(assigned(ppn.parasym) and
+ (vo_is_hidden_para in ppn.parasym.varoptions)) then
+ inc(result);
+ ppn:=tcallparanode(ppn.right);
+ end;
+ end;
+
+
+ function tcallnode.required_para_count: longint;
+ var
+ ppn : tcallparanode;
+ begin
+ result:=0;
+ ppn:=tcallparanode(left);
+ while assigned(ppn) do
+ begin
+ if not(assigned(ppn.parasym) and
+ ((vo_is_hidden_para in ppn.parasym.varoptions) or
+ assigned(ppn.parasym.defaultconstsym))) then
+ inc(result);
+ ppn:=tcallparanode(ppn.right);
+ end;
+ end;
+
+
+ function tcallnode.is_simple_para_load(p:tnode; may_be_in_reg: boolean):boolean;
+ var
+ hp : tnode;
+ begin
+ hp:=p;
+ while assigned(hp) and
+ (hp.nodetype=typeconvn) and
+ (ttypeconvnode(hp).convtype=tc_equal) do
+ hp:=tunarynode(hp).left;
+ result:=(hp.nodetype in [typen,loadvmtaddrn,loadn,temprefn,arrayconstructorn,addrn]);
+ if result and
+ not(may_be_in_reg) then
+ case hp.nodetype of
+ loadn:
+ result:=(tabstractvarsym(tloadnode(hp).symtableentry).varregable in [vr_none,vr_addr]);
+ temprefn:
+ result:=not(ti_may_be_in_reg in ttemprefnode(hp).tempinfo^.flags);
+ end;
+ end;
+
+ function look_for_call(var n: tnode; arg: pointer): foreachnoderesult;
+ begin
+ case n.nodetype of
+ calln:
+ result := fen_norecurse_true;
+ typen,loadvmtaddrn,loadn,temprefn,arrayconstructorn:
+ result := fen_norecurse_false;
+ else
+ result := fen_false;
+ end;
+ end;
+
+ procedure tcallnode.maybe_load_in_temp(var p:tnode);
+ var
+ loadp,
+ refp : tnode;
+ hdef : tdef;
+ ptemp : ttempcreatenode;
+ usederef : boolean;
+ begin
+ { Load all complex loads into a temp to prevent
+ double calls to a function. We can't simply check for a hp.nodetype=calln }
+ if assigned(p) and
+ foreachnodestatic(p,@look_for_call,nil) then
+ begin
+ { temp create }
+ usederef:=(p.resultdef.typ in [arraydef,recorddef]) or
+ is_shortstring(p.resultdef) or
+ is_object(p.resultdef);
+
+ if usederef then
+ hdef:=tpointerdef.create(p.resultdef)
+ else
+ hdef:=p.resultdef;
+
+ ptemp:=ctempcreatenode.create(hdef,hdef.size,tt_persistent,true);
+ if usederef then
+ begin
+ loadp:=caddrnode.create_internal(p);
+ refp:=cderefnode.create(ctemprefnode.create(ptemp));
+ end
+ else
+ begin
+ loadp:=p;
+ refp:=ctemprefnode.create(ptemp)
+ end;
+ add_init_statement(ptemp);
+ add_init_statement(cassignmentnode.create(
+ ctemprefnode.create(ptemp),
+ loadp));
+ add_done_statement(ctempdeletenode.create(ptemp));
+ { new tree is only a temp reference }
+ p:=refp;
+ typecheckpass(p);
+ end;
+ end;
+
+
+ function tcallnode.gen_high_tree(var p:tnode;paradef:tdef):tnode;
+ { When passing an array to an open array, or a string to an open string,
+ some code is needed that generates the high bound of the array. This
+ function returns a tree containing the nodes for it. }
+ var
+ temp: tnode;
+ len : integer;
+ loadconst : boolean;
+ hightree,l,r : tnode;
+ defkind: tdeftyp;
+ begin
+ len:=-1;
+ loadconst:=true;
+ hightree:=nil;
+ { constant strings are internally stored as array of char, but if the
+ parameter is a string also treat it like one }
+ defkind:=p.resultdef.typ;
+ if (p.nodetype=stringconstn) and
+ (paradef.typ=stringdef) then
+ defkind:=stringdef;
+ case defkind of
+ arraydef :
+ begin
+ if (paradef.typ<>arraydef) then
+ internalerror(200405241);
+ { passing a string to an array of char }
+ if (p.nodetype=stringconstn) and
+ is_char(tarraydef(paradef).elementdef) then
+ begin
+ len:=tstringconstnode(p).len;
+ if len>0 then
+ dec(len);
+ end
+ else
+ { handle special case of passing an single array to an array of array }
+ if compare_defs(tarraydef(paradef).elementdef,p.resultdef,nothingn)>=te_equal then
+ len:=0
+ else
+ begin
+ { handle via a normal inline in_high_x node }
+ loadconst:=false;
+ { slice? }
+ if (p.nodetype=inlinen) and (tinlinenode(p).inlinenumber=in_slice_x) then
+ with Tcallparanode(Tinlinenode(p).left) do
+ begin
+ {Array slice using slice builtin function.}
+ l:=Tcallparanode(right).left;
+ hightree:=caddnode.create(subn,l,genintconstnode(1));
+ Tcallparanode(right).left:=nil;
+
+ {Remove the inline node.}
+ temp:=p;
+ p:=left;
+ Tcallparanode(tinlinenode(temp).left).left:=nil;
+ temp.free;
+
+ typecheckpass(hightree);
+ end
+ else if (p.nodetype=vecn) and (Tvecnode(p).right.nodetype=rangen) then
+ begin
+ {Array slice using .. operator.}
+ with Trangenode(Tvecnode(p).right) do
+ begin
+ l:=left; {Get lower bound.}
+ r:=right; {Get upper bound.}
+ end;
+ {In the procedure the array range is 0..(upper_bound-lower_bound).}
+ hightree:=caddnode.create(subn,r,l);
+
+ {Replace the rangnode in the tree by its lower_bound, and
+ dispose the rangenode.}
+ temp:=Tvecnode(p).right;
+ Tvecnode(p).right:=l.getcopy;
+
+ {Typecheckpass can only be performed *after* the l.getcopy since it
+ can modify the tree, and l is in the hightree.}
+ typecheckpass(hightree);
+
+ with Trangenode(temp) do
+ begin
+ left:=nil;
+ right:=nil;
+ end;
+ temp.free;
+
+ {Tree changed from p[l..h] to p[l], recalculate resultdef.}
+ p.resultdef:=nil;
+ typecheckpass(p);
+ end
+ else
+ begin
+ maybe_load_in_temp(p);
+ hightree:=geninlinenode(in_high_x,false,p.getcopy);
+ typecheckpass(hightree);
+ { only substract low(array) if it's <> 0 }
+ temp:=geninlinenode(in_low_x,false,p.getcopy);
+ typecheckpass(temp);
+ if (temp.nodetype <> ordconstn) or
+ (tordconstnode(temp).value <> 0) then
+ hightree := caddnode.create(subn,hightree,temp)
+ else
+ temp.free;
+ end;
+ end;
+ end;
+ stringdef :
+ begin
+ if is_open_string(paradef) then
+ begin
+ { a stringconstn is not a simple parameter and hence would be
+ loaded in a temp, but in that case the high() node
+ a) goes wrong (it cannot deal with a temp node)
+ b) would give a generic result instead of one specific to
+ this constant string
+ }
+ if p.nodetype<>stringconstn then
+ maybe_load_in_temp(p);
+ { handle via a normal inline in_high_x node }
+ loadconst := false;
+ hightree := geninlinenode(in_high_x,false,p.getcopy);
+ end
+ else
+ { handle special case of passing an single string to an array of string }
+ if compare_defs(tarraydef(paradef).elementdef,p.resultdef,nothingn)>=te_equal then
+ len:=0
+ else
+ { passing a string to an array of char }
+ if (p.nodetype=stringconstn) and
+ is_char(tarraydef(paradef).elementdef) then
+ begin
+ len:=tstringconstnode(p).len;
+ if len>0 then
+ dec(len);
+ end
+ else
+ begin
+ maybe_load_in_temp(p);
+ hightree:=caddnode.create(subn,geninlinenode(in_length_x,false,p.getcopy),
+ cordconstnode.create(1,sinttype,false));
+ loadconst:=false;
+ end;
+ end;
+ else
+ len:=0;
+ end;
+ if loadconst then
+ hightree:=cordconstnode.create(len,sinttype,true)
+ else
+ begin
+ if not assigned(hightree) then
+ internalerror(200304071);
+ { Need to use explicit, because it can also be a enum }
+ hightree:=ctypeconvnode.create_internal(hightree,sinttype);
+ end;
+ result:=hightree;
+ end;
+
+
+ function tcallnode.gen_procvar_context_tree:tnode;
+ begin
+ { Load tmehodpointer(right).self (either self or parentfp) }
+ result:=genloadfield(ctypeconvnode.create_internal(
+ right.getcopy,methodpointertype),
+ 'self');
+ end;
+
+
+ function tcallnode.gen_self_tree:tnode;
+ var
+ selftree : tnode;
+ selfdef : tdef;
+ begin
+ selftree:=nil;
+
+ { When methodpointer was a callnode we must load it first into a
+ temp to prevent processing the callnode twice }
+ if (methodpointer.nodetype=calln) then
+ internalerror(200405121);
+
+ { Objective-C: objc_convert_to_message_send() already did all necessary
+ transformation on the methodpointer }
+ if (procdefinition.typ=procdef) and
+ (po_objc in tprocdef(procdefinition).procoptions) then
+ selftree:=methodpointer.getcopy
+ { inherited }
+ else if (cnf_inherited in callnodeflags) then
+ begin
+ selftree:=load_self_node;
+ { we can call an inherited class static/method from a regular method
+ -> self node must change from instance pointer to vmt pointer)
+ }
+ if (procdefinition.procoptions*[po_classmethod,po_staticmethod] <> []) and
+ (selftree.resultdef.typ<>classrefdef) then
+ selftree:=cloadvmtaddrnode.create(selftree);
+ end
+ else
+ { constructors }
+ if (procdefinition.proctypeoption=potype_constructor) then
+ begin
+ { push 0 as self when allocation is needed }
+ if (methodpointer.resultdef.typ=classrefdef) or
+ (cnf_new_call in callnodeflags) then
+ selftree:=cpointerconstnode.create(0,voidpointertype)
+ else
+ begin
+ if methodpointer.nodetype=typen then
+ selftree:=load_self_node
+ else
+ selftree:=methodpointer.getcopy;
+ end;
+ end
+ else
+ { Calling a static/class method }
+ if (po_classmethod in procdefinition.procoptions) or
+ (po_staticmethod in procdefinition.procoptions) then
+ begin
+ if (procdefinition.typ<>procdef) then
+ internalerror(200305062);
+ { if the method belongs to a helper then we need to use the
+ extended type for references to Self }
+ if is_objectpascal_helper(tprocdef(procdefinition).struct) then
+ selfdef:=tobjectdef(tprocdef(procdefinition).struct).extendeddef
+ else
+ selfdef:=tprocdef(procdefinition).struct;
+ if (selfdef.typ in [recorddef,objectdef]) and
+ (oo_has_vmt in tabstractrecorddef(selfdef).objectoptions) then
+ begin
+ { we only need the vmt, loading self is not required and there is no
+ need to check for typen, because that will always get the
+ loadvmtaddrnode added }
+ selftree:=methodpointer.getcopy;
+ if (methodpointer.resultdef.typ<>classrefdef) or
+ (methodpointer.nodetype = typen) then
+ selftree:=cloadvmtaddrnode.create(selftree);
+ end
+ else
+ selftree:=cpointerconstnode.create(0,voidpointertype);
+ end
+ else
+ begin
+ if methodpointer.nodetype=typen then
+ selftree:=load_self_node
+ else
+ selftree:=methodpointer.getcopy;
+ end;
+ result:=selftree;
+ end;
+
+
+ procedure tcallnode.register_created_object_types;
+
+ function checklive(def: tdef): boolean;
+ begin
+ if assigned(current_procinfo) and
+ not(po_inline in current_procinfo.procdef.procoptions) and
+ not wpoinfomanager.symbol_live(current_procinfo.procdef.mangledname) then
+ begin
+{$ifdef debug_deadcode}
+ writeln(' NOT adding creadion of ',def.typename,' because performed in dead stripped proc: ',current_procinfo.procdef.typename);
+{$endif debug_deadcode}
+ result:=false;
+ end
+ else
+ result:=true;
+ end;
+
+ var
+ crefdef,
+ systobjectdef : tdef;
+ begin
+ { only makes sense for methods }
+ if not assigned(methodpointer) then
+ exit;
+ if (methodpointer.resultdef.typ=classrefdef) then
+ begin
+ { constructor call via classreference => allocate memory }
+ if (procdefinition.proctypeoption=potype_constructor) then
+ begin
+ { Only a typenode can be passed when it is called with <class of xx>.create }
+ if (methodpointer.nodetype=typen) then
+ begin
+ if checklive(methodpointer.resultdef) then
+ { we know the exact class type being created }
+ tclassrefdef(methodpointer.resultdef).pointeddef.register_created_object_type
+ end
+ else
+ begin
+ { the loadvmtaddrnode is already created in case of classtype.create }
+ if (methodpointer.nodetype=loadvmtaddrn) and
+ (tloadvmtaddrnode(methodpointer).left.nodetype=typen) then
+ begin
+ if checklive(methodpointer.resultdef) then
+ tclassrefdef(methodpointer.resultdef).pointeddef.register_created_object_type
+ end
+ else
+ begin
+ if checklive(methodpointer.resultdef) then
+ begin
+ { special case: if the classref comes from x.classtype (with classtype,
+ being tobject.classtype) then the created instance is x or a descendant
+ of x (rather than tobject or a descendant of tobject)
+ }
+ systobjectdef:=search_system_type('TOBJECT').typedef;
+ if (methodpointer.nodetype=calln) and
+ { not a procvar call }
+ not assigned(right) and
+ { procdef is owned by system.tobject }
+ (tprocdef(tcallnode(methodpointer).procdefinition).owner.defowner=systobjectdef) and
+ { we're calling system.tobject.classtype }
+ (tcallnode(methodpointer).symtableprocentry.name='CLASSTYPE') and
+ { could again be a classrefdef, but unlikely }
+ (tcallnode(methodpointer).methodpointer.resultdef.typ=objectdef) and
+ { don't go through this trouble if it was already a tobject }
+ (tcallnode(methodpointer).methodpointer.resultdef<>systobjectdef) then
+ begin
+ { register this object type as classref, so all descendents will also
+ be marked as instantiatable (only the pointeddef will actually be
+ recorded, so it's no problem that the clasrefdef is only temporary)
+ }
+ crefdef:=tclassrefdef.create(tcallnode(methodpointer).methodpointer.resultdef);
+ { and register it }
+ crefdef.register_created_object_type;
+ end
+ else
+ { the created class can be any child class as well -> register classrefdef }
+ methodpointer.resultdef.register_created_object_type;
+ end;
+ end;
+ end;
+ end
+ end
+ else
+ { Old style object }
+ if is_object(methodpointer.resultdef) then
+ begin
+ { constructor with extended syntax called from new }
+ if (cnf_new_call in callnodeflags) then
+ begin
+ if checklive(methodpointer.resultdef) then
+ methodpointer.resultdef.register_created_object_type;
+ end
+ else
+ { normal object call like obj.proc }
+ if not(cnf_dispose_call in callnodeflags) and
+ not(cnf_inherited in callnodeflags) and
+ not(cnf_member_call in callnodeflags) then
+ begin
+ if (procdefinition.proctypeoption=potype_constructor) then
+ begin
+ if (methodpointer.nodetype<>typen) and
+ checklive(methodpointer.resultdef) then
+ methodpointer.resultdef.register_created_object_type;
+ end
+ end;
+ end;
+ end;
+
+
+ function tcallnode.get_expect_loc: tcgloc;
+ var
+ realresdef: tstoreddef;
+ begin
+ if not assigned(typedef) then
+ realresdef:=tstoreddef(resultdef)
+ else
+ realresdef:=tstoreddef(typedef);
+ if realresdef.is_intregable then
+ result:=LOC_REGISTER
+ else if (realresdef.typ=floatdef) and
+ not(cs_fp_emulation in current_settings.moduleswitches) then
+ if use_vectorfpu(realresdef) then
+ result:=LOC_MMREGISTER
+ else
+ result:=LOC_FPUREGISTER
+ else
+ result:=LOC_REFERENCE
+ end;
+
+
+ procedure tcallnode.objc_convert_to_message_send;
+ var
+ block,
+ selftree : tnode;
+ statements : tstatementnode;
+ field : tfieldvarsym;
+ temp : ttempcreatenode;
+ selfrestype,
+ objcsupertype : tdef;
+ srsym : tsym;
+ srsymtable : tsymtable;
+ msgsendname : string;
+ begin
+ if not(m_objectivec1 in current_settings.modeswitches) then
+ Message(parser_f_modeswitch_objc_required);
+ { typecheck pass must already have run on the call node,
+ because pass1 calls this method
+ }
+
+ { default behaviour: call objc_msgSend and friends;
+ 64 bit targets for Mac OS X can override this as they
+ can call messages via an indirect function call similar to
+ dynamically linked functions, ARM maybe as well (not checked)
+
+ Which variant of objc_msgSend is used depends on the
+ result type, and on whether or not it's an inherited call.
+ }
+
+ { make sure we don't perform this transformation twice in case
+ firstpass would be called multiple times }
+ include(callnodeflags,cnf_objc_processed);
+
+ { make sure the methodpointer doesn't get translated into a call
+ as well (endless loop) }
+ if methodpointer.nodetype=loadvmtaddrn then
+ tloadvmtaddrnode(methodpointer).forcall:=true;
+
+ { A) set the appropriate objc_msgSend* variant to call }
+
+ { record returned via implicit pointer }
+ if paramanager.ret_in_param(resultdef,procdefinition.proccalloption) then
+ begin
+ if not(cnf_inherited in callnodeflags) then
+ msgsendname:='OBJC_MSGSEND_STRET'
+{$if defined(onlymacosx10_6) or defined(arm) }
+ else if (target_info.system in systems_objc_nfabi) then
+ msgsendname:='OBJC_MSGSENDSUPER2_STRET'
+{$endif onlymacosx10_6 or arm}
+ else
+ msgsendname:='OBJC_MSGSENDSUPER_STRET'
+ end
+{$ifdef i386}
+ { special case for fpu results on i386 for non-inherited calls }
+ { TODO: also for x86_64 "extended" results }
+ else if (resultdef.typ=floatdef) and
+ not(cnf_inherited in callnodeflags) then
+ msgsendname:='OBJC_MSGSEND_FPRET'
+{$endif}
+ { default }
+ else if not(cnf_inherited in callnodeflags) then
+ msgsendname:='OBJC_MSGSEND'
+{$if defined(onlymacosx10_6) or defined(arm) }
+ else if (target_info.system in systems_objc_nfabi) then
+ msgsendname:='OBJC_MSGSENDSUPER2'
+{$endif onlymacosx10_6 or arm}
+ else
+ msgsendname:='OBJC_MSGSENDSUPER';
+
+ { get the mangled name }
+ if not searchsym_in_named_module('OBJC',msgsendname,srsym,srsymtable) or
+ (srsym.typ<>procsym) or
+ (tprocsym(srsym).ProcdefList.count<>1) then
+ Message1(cg_f_unknown_compilerproc,'objc.'+msgsendname);
+ fobjcforcedprocname:=stringdup(tprocdef(tprocsym(srsym).ProcdefList[0]).mangledname);
+
+ { B) Handle self }
+ { 1) in case of sending a message to a superclass, self is a pointer to
+ an objc_super record
+ }
+ if (cnf_inherited in callnodeflags) then
+ begin
+ block:=internalstatements(statements);
+ objcsupertype:=search_named_unit_globaltype('OBJC','OBJC_SUPER',true).typedef;
+ if (objcsupertype.typ<>recorddef) then
+ internalerror(2009032901);
+ { temp for the for the objc_super record }
+ temp:=ctempcreatenode.create(objcsupertype,objcsupertype.size,tt_persistent,false);
+ addstatement(statements,temp);
+ { initialize objc_super record }
+ selftree:=load_self_node;
+
+ { we can call an inherited class static/method from a regular method
+ -> self node must change from instance pointer to vmt pointer)
+ }
+ if (po_classmethod in procdefinition.procoptions) and
+ (selftree.resultdef.typ<>classrefdef) then
+ begin
+ selftree:=cloadvmtaddrnode.create(selftree);
+ { since we're in a class method of the current class, its
+ information has already been initialized (and that of all of
+ its parent classes too) }
+ tloadvmtaddrnode(selftree).forcall:=true;
+ typecheckpass(selftree);
+ end;
+ selfrestype:=selftree.resultdef;
+ field:=tfieldvarsym(trecorddef(objcsupertype).symtable.find('RECEIVER'));
+ if not assigned(field) then
+ internalerror(2009032902);
+ { first the destination object/class instance }
+ addstatement(statements,
+ cassignmentnode.create(
+ csubscriptnode.create(field,ctemprefnode.create(temp)),
+ selftree
+ )
+ );
+ { and secondly, the class type in which the selector must be looked
+ up (the parent class in case of an instance method, the parent's
+ metaclass in case of a class method) }
+ field:=tfieldvarsym(trecorddef(objcsupertype).symtable.find('_CLASS'));
+ if not assigned(field) then
+ internalerror(2009032903);
+ addstatement(statements,
+ cassignmentnode.create(
+ csubscriptnode.create(field,ctemprefnode.create(temp)),
+ objcsuperclassnode(selftree.resultdef)
+ )
+ );
+ { result of this block is the address of this temp }
+ addstatement(statements,ctypeconvnode.create_internal(
+ caddrnode.create_internal(ctemprefnode.create(temp)),selfrestype)
+ );
+ { replace the method pointer with the address of this temp }
+ methodpointer.free;
+ methodpointer:=block;
+ typecheckpass(block);
+ end
+ else
+ { 2) regular call (not inherited) }
+ begin
+ { a) If we're calling a class method, use a class ref. }
+ if (po_classmethod in procdefinition.procoptions) and
+ ((methodpointer.nodetype=typen) or
+ (methodpointer.resultdef.typ<>classrefdef)) then
+ begin
+ methodpointer:=cloadvmtaddrnode.create(methodpointer);
+ { no need to obtain the class ref by calling class(), sending
+ this message will initialize it if necessary }
+ tloadvmtaddrnode(methodpointer).forcall:=true;
+ firstpass(methodpointer);
+ end;
+ end;
+ end;
+
+
+ function tcallnode.gen_vmt_tree:tnode;
+ var
+ vmttree : tnode;
+ begin
+ vmttree:=nil;
+ if not(procdefinition.proctypeoption in [potype_constructor,potype_destructor]) then
+ internalerror(200305051);
+
+ { When methodpointer was a callnode we must load it first into a
+ temp to prevent the processing callnode twice }
+ if (methodpointer.nodetype=calln) then
+ internalerror(200405122);
+
+ { Handle classes and legacy objects separate to make it
+ more maintainable }
+ if (methodpointer.resultdef.typ=classrefdef) then
+ begin
+ if not is_class(tclassrefdef(methodpointer.resultdef).pointeddef) then
+ internalerror(200501041);
+
+ { constructor call via classreference => allocate memory }
+ if (procdefinition.proctypeoption=potype_constructor) then
+ begin
+ vmttree:=methodpointer.getcopy;
+ { Only a typenode can be passed when it is called with <class of xx>.create }
+ if vmttree.nodetype=typen then
+ begin
+ vmttree:=cloadvmtaddrnode.create(vmttree);
+ tloadvmtaddrnode(vmttree).forcall:=true;
+ end;
+ end
+ else
+ begin
+ { Call afterconstruction }
+ vmttree:=cpointerconstnode.create(1,voidpointertype);
+ end;
+ end
+ else
+ { Class style objects }
+ if is_class(methodpointer.resultdef) then
+ begin
+ { inherited call, no create/destroy }
+ if (cnf_inherited in callnodeflags) then
+ vmttree:=cpointerconstnode.create(0,voidpointertype)
+ else
+ { do not create/destroy when called from member function
+ without specifying self explicit }
+ if (cnf_member_call in callnodeflags) then
+ begin
+ { destructor (in the same class, since cnf_member_call):
+ if not called from a destructor then
+ call beforedestruction and release instance, vmt=1
+ else
+ don't release instance, vmt=0
+ constructor (in the same class, since cnf_member_call):
+ if called from a constructor then
+ don't call afterconstruction, vmt=0
+ else
+ call afterconstrution, vmt=1 }
+ if (procdefinition.proctypeoption=potype_destructor) then
+ if (current_procinfo.procdef.proctypeoption<>potype_constructor) then
+ vmttree:=cpointerconstnode.create(1,voidpointertype)
+ else
+ vmttree:=cpointerconstnode.create(0,voidpointertype)
+ else if (current_procinfo.procdef.proctypeoption=potype_constructor) and
+ (procdefinition.proctypeoption=potype_constructor) then
+ vmttree:=cpointerconstnode.create(0,voidpointertype)
+ else
+ vmttree:=cpointerconstnode.create(1,voidpointertype);
+ end
+ else
+ { normal call to method like cl1.proc }
+ begin
+ { destructor:
+ if not called from exception block in constructor
+ call beforedestruction and release instance, vmt=1
+ else
+ don't call beforedestruction and release instance, vmt=-1
+ constructor:
+ if called from a constructor in the same class using self.create then
+ don't call afterconstruction, vmt=0
+ else
+ call afterconstruction, vmt=1 }
+ if (procdefinition.proctypeoption=potype_destructor) then
+ if not(cnf_create_failed in callnodeflags) then
+ vmttree:=cpointerconstnode.create(1,voidpointertype)
+ else
+ vmttree:=cpointerconstnode.create(TConstPtrUInt(-1),voidpointertype)
+ else
+ begin
+ if (current_procinfo.procdef.proctypeoption=potype_constructor) and
+ (procdefinition.proctypeoption=potype_constructor) and
+ (methodpointer.nodetype=loadn) and
+ (loadnf_is_self in tloadnode(methodpointer).loadnodeflags) then
+ vmttree:=cpointerconstnode.create(0,voidpointertype)
+ else
+ vmttree:=cpointerconstnode.create(1,voidpointertype);
+ end;
+ end;
+ end
+ else
+ { Old style object }
+ begin
+ { constructor with extended syntax called from new }
+ if (cnf_new_call in callnodeflags) then
+ vmttree:=cloadvmtaddrnode.create(ctypenode.create(methodpointer.resultdef))
+ else
+ { destructor with extended syntax called from dispose }
+ if (cnf_dispose_call in callnodeflags) then
+ vmttree:=cloadvmtaddrnode.create(methodpointer.getcopy)
+ else
+ { inherited call, no create/destroy }
+ if (cnf_inherited in callnodeflags) then
+ vmttree:=cpointerconstnode.create(0,voidpointertype)
+ else
+ { do not create/destroy when called from member function
+ without specifying self explicit }
+ if (cnf_member_call in callnodeflags) then
+ begin
+ { destructor: don't release instance, vmt=0
+ constructor: don't initialize instance, vmt=0 }
+ vmttree:=cpointerconstnode.create(0,voidpointertype)
+ end
+ else
+ { normal object call like obj.proc }
+ begin
+ { destructor: direct call, no dispose, vmt=0
+ constructor: initialize object, load vmt }
+ if (procdefinition.proctypeoption=potype_constructor) then
+ begin
+ { old styled inherited call? }
+ if (methodpointer.nodetype=typen) then
+ vmttree:=cpointerconstnode.create(0,voidpointertype)
+ else
+ vmttree:=cloadvmtaddrnode.create(ctypenode.create(methodpointer.resultdef))
+ end
+ else
+ vmttree:=cpointerconstnode.create(0,voidpointertype);
+ end;
+ end;
+ result:=vmttree;
+ end;
+
+
+
+ function check_funcret_used_as_para(var n: tnode; arg: pointer): foreachnoderesult;
+ var
+ destsym : tsym absolute arg;
+ begin
+ result := fen_false;
+ if (n.nodetype=loadn) and
+ (tloadnode(n).symtableentry = destsym) then
+ result := fen_norecurse_true;
+ end;
+
+
+ function tcallnode.funcret_can_be_reused:boolean;
+ var
+ realassignmenttarget: tnode;
+ alignment: longint;
+ begin
+ result:=false;
+
+ { we are processing an assignment node? }
+ if not(assigned(aktassignmentnode) and
+ (aktassignmentnode.right=self) and
+ (aktassignmentnode.left.resultdef=resultdef)) then
+ exit;
+
+ { destination must be able to be passed as var parameter }
+ if not valid_for_var(aktassignmentnode.left,false) then
+ exit;
+
+ { destination must be a simple load so it doesn't need a temp when
+ it is evaluated }
+ if not is_simple_para_load(aktassignmentnode.left,false) then
+ exit;
+
+ { remove possible typecasts }
+ realassignmenttarget:=aktassignmentnode.left.actualtargetnode;
+
+ { when it is not passed in a parameter it will only be used after the
+ function call }
+ if not paramanager.ret_in_param(resultdef,procdefinition.proccalloption) then
+ begin
+ result:=true;
+ exit;
+ end;
+
+ { if the result is the same as the self parameter (in case of objects),
+ we can't optimise. We have to check this explicitly becaise
+ hidden parameters such as self have not yet been inserted at this
+ point
+ }
+ if assigned(methodpointer) and
+ realassignmenttarget.isequal(methodpointer.actualtargetnode) then
+ exit;
+
+ { when we substitute a function result inside an inlined function,
+ we may take the address of this function result. Therefore the
+ substituted function result may not be in a register, as we cannot
+ take its address in that case }
+ if (realassignmenttarget.nodetype=temprefn) and
+ not(ti_addr_taken in ttemprefnode(realassignmenttarget).tempinfo^.flags) and
+ not(ti_may_be_in_reg in ttemprefnode(realassignmenttarget).tempinfo^.flags) then
+ begin
+ result:=true;
+ exit;
+ end;
+
+ if (realassignmenttarget.nodetype=loadn) and
+ { nested procedures may access the current procedure's locals }
+ (procdefinition.parast.symtablelevel=normal_function_level) and
+ { must be a local variable, a value para or a hidden function result }
+ { parameter (which can be passed by address, but in that case it got }
+ { through these same checks at the caller side and is thus safe }
+ (
+ (tloadnode(realassignmenttarget).symtableentry.typ=localvarsym) or
+ (
+ (tloadnode(realassignmenttarget).symtableentry.typ=paravarsym) and
+ ((tparavarsym(tloadnode(realassignmenttarget).symtableentry).varspez = vs_value) or
+ (vo_is_funcret in tparavarsym(tloadnode(realassignmenttarget).symtableentry).varoptions))
+ )
+ ) and
+ { the address may not have been taken of the variable/parameter, because }
+ { otherwise it's possible that the called function can access it via a }
+ { global variable or other stored state }
+ (
+ not(tabstractvarsym(tloadnode(realassignmenttarget).symtableentry).addr_taken) and
+ (tabstractvarsym(tloadnode(realassignmenttarget).symtableentry).varregable in [vr_none,vr_addr])
+ ) then
+ begin
+ { If the funcret is also used as a parameter we can't optimize because the funcret
+ and the parameter will point to the same address. That means that a change of the result variable
+ will result also in a change of the parameter value }
+ result:=not foreachnodestatic(left,@check_funcret_used_as_para,tloadnode(realassignmenttarget).symtableentry);
+ { ensure that it is aligned using the default alignment }
+ alignment:=tabstractvarsym(tloadnode(realassignmenttarget).symtableentry).vardef.alignment;
+ if (used_align(alignment,target_info.alignment.localalignmin,target_info.alignment.localalignmax)<>
+ used_align(alignment,current_settings.alignment.localalignmin,current_settings.alignment.localalignmax)) then
+ result:=false;
+ exit;
+ end;
+ end;
+
+
+ procedure tcallnode.maybe_create_funcret_node;
+ var
+ temp : ttempcreatenode;
+ begin
+ { For the function result we need to create a temp node for:
+ - Inlined functions
+ - Types requiring initialization/finalization
+ - Types passed in parameters }
+ if not is_void(resultdef) and
+ not assigned(funcretnode) and
+ (
+ (cnf_do_inline in callnodeflags) or
+ is_managed_type(resultdef) or
+ paramanager.ret_in_param(resultdef,procdefinition.proccalloption)
+ ) then
+ begin
+ { Optimize calls like x:=f() where we can use x directly as
+ result instead of using a temp. Condition is that x cannot be accessed from f().
+ This implies that x is a local variable or value parameter of the current block
+ and its address is not passed to f. One problem: what if someone takes the
+ address of x, puts it in a pointer variable/field and then accesses it that way
+ from within the function? This is solved (in a conservative way) using the
+ ti_addr_taken flag.
+
+ When the result is not not passed in a parameter there are no problem because
+ then it means only reference counted types (eg. ansistrings) that need a decr
+ of the refcount before being assigned. This is all done after the call so there
+ is no issue with exceptions and possible use of the old value in the called
+ function }
+ if funcret_can_be_reused then
+ begin
+ funcretnode:=aktassignmentnode.left.getcopy;
+ include(funcretnode.flags,nf_is_funcret);
+ { notify the assignment node that the assignment can be removed }
+ include(aktassignmentnode.flags,nf_assign_done_in_right);
+ end
+ else
+ begin
+ temp:=ctempcreatenode.create(resultdef,resultdef.size,tt_persistent,
+ (cnf_do_inline in callnodeflags) and
+ not(tabstractvarsym(tprocdef(procdefinition).funcretsym).varregable in [vr_none,vr_addr]));
+ include(temp.flags,nf_is_funcret);
+ add_init_statement(temp);
+ { When the function result is not used in an inlined function
+ we need to delete the temp. This can currently only be done by
+ a tempdeletenode and not after converting it to a normal temp }
+ if not(cnf_return_value_used in callnodeflags) and
+ (cnf_do_inline in callnodeflags) then
+ add_done_statement(ctempdeletenode.create(temp))
+ else
+ add_done_statement(ctempdeletenode.create_normal_temp(temp));
+ funcretnode:=ctemprefnode.create(temp);
+ include(funcretnode.flags,nf_is_funcret);
+ end;
+ end;
+ end;
+
+
+ procedure tcallnode.gen_hidden_parameters;
+ var
+ para : tcallparanode;
+ begin
+ para:=tcallparanode(left);
+ while assigned(para) do
+ begin
+ { The processing of high() and typeinfo() is already
+ done in the typecheckpass. We only need to process the
+ nodes that still have a nothingn }
+ if (vo_is_hidden_para in para.parasym.varoptions) and
+ (para.left.nodetype=nothingn) then
+ begin
+ { remove dummy nothingn }
+ para.left.free;
+ para.left:=nil;
+ { generate the corresponding nodes for the hidden parameter type }
+ if (vo_is_funcret in para.parasym.varoptions) then
+ begin
+ if not assigned(funcretnode) then
+ internalerror(200709083);
+ para.left:=funcretnode;
+ funcretnode:=nil;
+ end
+ else
+ if vo_is_self in para.parasym.varoptions then
+ begin
+ if assigned(right) then
+ para.left:=gen_procvar_context_tree
+ else
+ para.left:=gen_self_tree;
+ end
+ else
+ if vo_is_vmt in para.parasym.varoptions then
+ begin
+ para.left:=gen_vmt_tree;
+ end
+{$if defined(powerpc) or defined(m68k)}
+ else
+ if vo_is_syscall_lib in para.parasym.varoptions then
+ begin
+ { lib parameter has no special type but proccalloptions must be a syscall }
+ para.left:=cloadnode.create(tprocdef(procdefinition).libsym,tprocdef(procdefinition).libsym.owner);
+ end
+{$endif powerpc or m68k}
+ else
+ if vo_is_parentfp in para.parasym.varoptions then
+ begin
+ if not assigned(right) then
+ begin
+ if assigned(procdefinition.owner.defowner) then
+ para.left:=cloadparentfpnode.create(tprocdef(procdefinition.owner.defowner))
+ { exceptfilters called from main level are not owned }
+ else if procdefinition.proctypeoption=potype_exceptfilter then
+ para.left:=cloadparentfpnode.create(current_procinfo.procdef)
+ else
+ internalerror(200309287);
+ end
+ else
+ para.left:=gen_procvar_context_tree;
+ end
+ else
+ if vo_is_range_check in para.parasym.varoptions then
+ begin
+ para.left:=cordconstnode.create(Ord(cs_check_range in current_settings.localswitches),pasbool8type,false);
+ end
+ else
+ if vo_is_overflow_check in para.parasym.varoptions then
+ begin
+ para.left:=cordconstnode.create(Ord(cs_check_overflow in current_settings.localswitches),pasbool8type,false);
+ end
+ else
+ if vo_is_msgsel in para.parasym.varoptions then
+ begin
+ para.left:=cobjcselectornode.create(cstringconstnode.createstr(tprocdef(procdefinition).messageinf.str^));
+ end;
+ end;
+ if not assigned(para.left) then
+ internalerror(200709084);
+ para:=tcallparanode(para.right);
+ end;
+ end;
+
+
+ procedure tcallnode.verifyabstract(sym:TObject;arg:pointer);
+ var
+ pd : tprocdef;
+ i : longint;
+ j : integer;
+ hs : string;
+ begin
+ if (tsym(sym).typ<>procsym) then
+ exit;
+ for i:=0 to tprocsym(sym).ProcdefList.Count-1 do
+ begin
+ pd:=tprocdef(tprocsym(sym).ProcdefList[i]);
+ hs:=pd.procsym.name+pd.typename_paras(false);
+ j:=AbstractMethodsList.FindIndexOf(hs);
+ if j<>-1 then
+ AbstractMethodsList[j]:=pd
+ else
+ AbstractMethodsList.Add(hs,pd);
+ end;
+ end;
+
+
+ procedure tcallnode.verifyabstractcalls;
+ var
+ objectdf : tobjectdef;
+ parents : tlinkedlist;
+ objectinfo : tobjectinfoitem;
+ pd : tprocdef;
+ i : integer;
+ begin
+ objectdf := nil;
+ { verify if trying to create an instance of a class which contains
+ non-implemented abstract methods }
+
+ { first verify this class type, no class than exit }
+ { also, this checking can only be done if the constructor is directly
+ called, indirect constructor calls cannot be checked.
+ }
+ if assigned(methodpointer) and
+ not((methodpointer.nodetype=loadn) and
+ (loadnf_is_self in tloadnode(methodpointer).loadnodeflags)) then
+ begin
+ if (methodpointer.resultdef.typ = objectdef) then
+ objectdf:=tobjectdef(methodpointer.resultdef)
+ else
+ if (methodpointer.resultdef.typ = classrefdef) and
+ (tclassrefdef(methodpointer.resultdef).pointeddef.typ = objectdef) and
+ (methodpointer.nodetype in [typen,loadvmtaddrn]) then
+ objectdf:=tobjectdef(tclassrefdef(methodpointer.resultdef).pointeddef);
+ end;
+ if not assigned(objectdf) then
+ exit;
+
+ parents := tlinkedlist.create;
+ AbstractMethodsList := TFPHashList.create;
+
+ { insert all parents in this class : the first item in the
+ list will be the base parent of the class .
+ }
+ while assigned(objectdf) do
+ begin
+ objectinfo:=tobjectinfoitem.create(objectdf);
+ parents.insert(objectinfo);
+ objectdf := objectdf.childof;
+ end;
+ { now all parents are in the correct order
+ insert all abstract methods in the list, and remove
+ those which are overridden by parent classes.
+ }
+ objectinfo:=tobjectinfoitem(parents.first);
+ while assigned(objectinfo) do
+ begin
+ objectdf := objectinfo.objinfo;
+ if assigned(objectdf.symtable) then
+ objectdf.symtable.SymList.ForEachCall(@verifyabstract,nil);
+ objectinfo:=tobjectinfoitem(objectinfo.next);
+ end;
+ if assigned(parents) then
+ parents.free;
+ { Finally give out a warning for each abstract method still in the list }
+ for i:=0 to AbstractMethodsList.Count-1 do
+ begin
+ pd:=tprocdef(AbstractMethodsList[i]);
+ if po_abstractmethod in pd.procoptions then
+ begin
+ Message2(type_w_instance_with_abstract,objectdf.objrealname^,pd.procsym.RealName);
+ MessagePos1(pd.fileinfo,sym_h_abstract_method_list,pd.fullprocname(true));
+ end;
+ end;
+ if assigned(AbstractMethodsList) then
+ AbstractMethodsList.Free;
+ end;
+
+
+ procedure tcallnode.convert_carg_array_of_const;
+ var
+ hp : tarrayconstructornode;
+ oldleft : tcallparanode;
+ begin
+ oldleft:=tcallparanode(left);
+ if oldleft.left.nodetype<>arrayconstructorn then
+ begin
+ CGMessage1(type_e_wrong_type_in_array_constructor,oldleft.left.resultdef.typename);
+ exit;
+ end;
+ include(callnodeflags,cnf_uses_varargs);
+ { Get arrayconstructor node and insert typeconvs }
+ hp:=tarrayconstructornode(oldleft.left);
+ { Add c args parameters }
+ { It could be an empty set }
+ if assigned(hp) and
+ assigned(hp.left) then
+ begin
+ while assigned(hp) do
+ begin
+ left:=ccallparanode.create(hp.left,left);
+ { set callparanode resultdef and flags }
+ left.resultdef:=hp.left.resultdef;
+ include(tcallparanode(left).callparaflags,cpf_varargs_para);
+ hp.left:=nil;
+ hp:=tarrayconstructornode(hp.right);
+ end;
+ end;
+ { Remove value of old array of const parameter, but keep it
+ in the list because it is required for bind_parasym.
+ Generate a nothign to keep callparanoed.left valid }
+ oldleft.left.free;
+ oldleft.left:=cnothingnode.create;
+ end;
+
+
+ procedure tcallnode.bind_parasym;
+ type
+ pcallparanode = ^tcallparanode;
+ var
+ i : integer;
+ pt : tcallparanode;
+ oldppt : pcallparanode;
+ varargspara,
+ currpara : tparavarsym;
+ hiddentree : tnode;
+ paradef : tdef;
+ begin
+ pt:=tcallparanode(left);
+ oldppt:=pcallparanode(@left);
+
+ { flag all callparanodes that belong to the varargs }
+ i:=paralength;
+ while (i>procdefinition.maxparacount) do
+ begin
+ include(pt.callparaflags,cpf_varargs_para);
+ oldppt:=pcallparanode(@pt.right);
+ pt:=tcallparanode(pt.right);
+ dec(i);
+ end;
+
+ { skip varargs that are inserted by array of const }
+ while assigned(pt) and
+ (cpf_varargs_para in pt.callparaflags) do
+ pt:=tcallparanode(pt.right);
+
+ { process normal parameters and insert hidden parameter nodes, the content
+ of the hidden parameters will be updated in pass1 }
+ for i:=procdefinition.paras.count-1 downto 0 do
+ begin
+ currpara:=tparavarsym(procdefinition.paras[i]);
+ if vo_is_hidden_para in currpara.varoptions then
+ begin
+ { Here we handle only the parameters that depend on
+ the types of the previous parameter. The typeconversion
+ can change the type in the next step. For example passing
+ an array can be change to a pointer and a deref }
+ if vo_is_high_para in currpara.varoptions then
+ begin
+ if not assigned(pt) or (i=0) then
+ internalerror(200304081);
+ { we need the information of the previous parameter }
+ paradef:=tparavarsym(procdefinition.paras[i-1]).vardef;
+ hiddentree:=gen_high_tree(pt.left,paradef);
+ { for open array of managed type, a copy of high parameter is
+ necessary to properly initialize before the call }
+ if is_open_array(paradef) and
+ (tparavarsym(procdefinition.paras[i-1]).varspez=vs_out) and
+ is_managed_type(tarraydef(paradef).elementdef) then
+ begin
+ typecheckpass(hiddentree);
+ {this eliminates double call to fpc_dynarray_high, if any}
+ maybe_load_in_temp(hiddentree);
+ oldppt^.third:=hiddentree.getcopy;
+ end;
+ end
+ else
+ if vo_is_typinfo_para in currpara.varoptions then
+ begin
+ if not assigned(pt) or (i=0) then
+ internalerror(200304082);
+ hiddentree:=caddrnode.create_internal(
+ crttinode.create(Tstoreddef(pt.resultdef),fullrtti,rdt_normal)
+ );
+ end
+ else
+ hiddentree:=cnothingnode.create;
+ pt:=ccallparanode.create(hiddentree,oldppt^);
+ oldppt^:=pt;
+ end;
+ if not assigned(pt) then
+ internalerror(200310052);
+ pt.parasym:=currpara;
+ oldppt:=pcallparanode(@pt.right);
+ pt:=tcallparanode(pt.right);
+ end;
+
+ { Create parasyms for varargs, first count the number of varargs paras,
+ then insert the parameters with numbering in reverse order. The SortParas
+ will set the correct order at the end}
+ pt:=tcallparanode(left);
+ i:=0;
+ while assigned(pt) do
+ begin
+ if cpf_varargs_para in pt.callparaflags then
+ inc(i);
+ pt:=tcallparanode(pt.right);
+ end;
+ if (i>0) then
+ begin
+ varargsparas:=tvarargsparalist.create;
+ pt:=tcallparanode(left);
+ while assigned(pt) do
+ begin
+ if cpf_varargs_para in pt.callparaflags then
+ begin
+ varargspara:=tparavarsym.create('va'+tostr(i),i,vs_value,pt.resultdef,[]);
+ dec(i);
+ { varargspara is left-right, use insert
+ instead of concat }
+ varargsparas.add(varargspara);
+ pt.parasym:=varargspara;
+ end;
+ pt:=tcallparanode(pt.right);
+ end;
+ varargsparas.sortparas;
+ end;
+ end;
+
+
+ function tcallnode.pass_typecheck:tnode;
+ var
+ candidates : tcallcandidates;
+ oldcallnode : tcallnode;
+ hpt : tnode;
+ pt : tcallparanode;
+ lastpara : longint;
+ paraidx,
+ cand_cnt : integer;
+ i : longint;
+ ignorevisibility,
+ is_const : boolean;
+ statements : tstatementnode;
+ converted_result_data : ttempcreatenode;
+ calltype: tdispcalltype;
+ label
+ errorexit;
+ begin
+ result:=nil;
+ candidates:=nil;
+
+ oldcallnode:=aktcallnode;
+ aktcallnode:=self;
+
+ { determine length of parameter list }
+ pt:=tcallparanode(left);
+ paralength:=0;
+ while assigned(pt) do
+ begin
+ inc(paralength);
+ pt:=tcallparanode(pt.right);
+ end;
+
+ { determine the type of the parameters }
+ if assigned(left) then
+ begin
+ tcallparanode(left).get_paratype;
+ if codegenerror then
+ goto errorexit;
+ end;
+
+ if assigned(methodpointer) then
+ typecheckpass(methodpointer);
+
+ { procedure variable ? }
+ if assigned(right) then
+ begin
+ set_varstate(right,vs_read,[vsf_must_be_valid]);
+ typecheckpass(right);
+ if codegenerror then
+ exit;
+
+ procdefinition:=tabstractprocdef(right.resultdef);
+
+ { Compare parameters from right to left }
+ paraidx:=procdefinition.Paras.count-1;
+ { Skip default parameters }
+ if not(po_varargs in procdefinition.procoptions) then
+ begin
+ { ignore hidden parameters }
+ while (paraidx>=0) and (vo_is_hidden_para in tparavarsym(procdefinition.paras[paraidx]).varoptions) do
+ dec(paraidx);
+ for i:=1 to procdefinition.maxparacount-paralength do
+ begin
+ if paraidx<0 then
+ internalerror(200402261);
+ if not assigned(tparavarsym(procdefinition.paras[paraidx]).defaultconstsym) then
+ begin
+ CGMessage1(parser_e_wrong_parameter_size,'<Procedure Variable>');
+ goto errorexit;
+ end;
+ dec(paraidx);
+ end;
+ end;
+ while (paraidx>=0) and (vo_is_hidden_para in tparavarsym(procdefinition.paras[paraidx]).varoptions) do
+ dec(paraidx);
+ pt:=tcallparanode(left);
+ lastpara:=paralength;
+ while (paraidx>=0) and assigned(pt) do
+ begin
+ { only goto next para if we're out of the varargs }
+ if not(po_varargs in procdefinition.procoptions) or
+ (lastpara<=procdefinition.maxparacount) then
+ begin
+ repeat
+ dec(paraidx);
+ until (paraidx<0) or not(vo_is_hidden_para in tparavarsym(procdefinition.paras[paraidx]).varoptions);
+ end;
+ pt:=tcallparanode(pt.right);
+ dec(lastpara);
+ end;
+ if assigned(pt) or
+ ((paraidx>=0) and
+ not assigned(tparavarsym(procdefinition.paras[paraidx]).defaultconstsym)) then
+ begin
+ if assigned(pt) then
+ current_filepos:=pt.fileinfo;
+ CGMessage1(parser_e_wrong_parameter_size,'<Procedure Variable>');
+ goto errorexit;
+ end;
+ end
+ else
+ { not a procedure variable }
+ begin
+ { do we know the procedure to call ? }
+ if not(assigned(procdefinition)) then
+ begin
+ { ignore possible private for properties or in delphi mode for anon. inherited (FK) }
+ ignorevisibility:=(nf_isproperty in flags) or
+ ((m_delphi in current_settings.modeswitches) and (cnf_anon_inherited in callnodeflags));
+ candidates:=tcallcandidates.create(symtableprocentry,symtableproc,left,ignorevisibility,
+ not(nf_isproperty in flags),cnf_objc_id_call in callnodeflags,cnf_unit_specified in callnodeflags,
+ callnodeflags*[cnf_anon_inherited,cnf_inherited]=[],cnf_anon_inherited in callnodeflags);
+
+ { no procedures found? then there is something wrong
+ with the parameter size or the procedures are
+ not accessible }
+ if candidates.count=0 then
+ begin
+ { when it's an auto inherited call and there
+ is no procedure found, but the procedures
+ were defined with overload directive and at
+ least two procedures are defined then we ignore
+ this inherited by inserting a nothingn. Only
+ do this ugly hack in Delphi mode as it looks more
+ like a bug. It's also not documented }
+ if (m_delphi in current_settings.modeswitches) and
+ (cnf_anon_inherited in callnodeflags) and
+ (symtableprocentry.owner.symtabletype=ObjectSymtable) and
+ (po_overload in tprocdef(symtableprocentry.ProcdefList[0]).procoptions) and
+ (symtableprocentry.ProcdefList.Count>=2) then
+ result:=cnothingnode.create
+ else
+ begin
+ { in tp mode we can try to convert to procvar if
+ there are no parameters specified }
+ if not(assigned(left)) and
+ not(cnf_inherited in callnodeflags) and
+ ((m_tp_procvar in current_settings.modeswitches) or
+ (m_mac_procvar in current_settings.modeswitches)) and
+ (not assigned(methodpointer) or
+ (methodpointer.nodetype <> typen)) then
+ begin
+ hpt:=cloadnode.create(tprocsym(symtableprocentry),symtableproc);
+ if assigned(methodpointer) then
+ tloadnode(hpt).set_mp(methodpointer.getcopy);
+ typecheckpass(hpt);
+ result:=hpt;
+ end
+ else
+ begin
+ CGMessagePos1(fileinfo,parser_e_wrong_parameter_size,symtableprocentry.realname);
+ symtableprocentry.write_parameter_lists(nil);
+ end;
+ end;
+ candidates.free;
+ goto errorexit;
+ end;
+
+ { Retrieve information about the candidates }
+ candidates.get_information;
+{$ifdef EXTDEBUG}
+ { Display info when multiple candidates are found }
+ if candidates.count>1 then
+ candidates.dump_info(V_Debug);
+{$endif EXTDEBUG}
+
+ { Choose the best candidate and count the number of
+ candidates left }
+ cand_cnt:=candidates.choose_best(procdefinition,
+ assigned(left) and
+ not assigned(tcallparanode(left).right) and
+ (tcallparanode(left).left.resultdef.typ=variantdef));
+
+ { All parameters are checked, check if there are any
+ procedures left }
+ if cand_cnt>0 then
+ begin
+ { Multiple candidates left? }
+ if cand_cnt>1 then
+ begin
+ CGMessage(type_e_cant_choose_overload_function);
+{$ifdef EXTDEBUG}
+ candidates.dump_info(V_Hint);
+{$else EXTDEBUG}
+ candidates.list(false);
+{$endif EXTDEBUG}
+ { we'll just use the first candidate to make the
+ call }
+ end;
+
+ { assign procdefinition }
+ if symtableproc=nil then
+ symtableproc:=procdefinition.owner;
+ end
+ else
+ begin
+ { No candidates left, this must be a type error,
+ because wrong size is already checked. procdefinition
+ is filled with the first (random) definition that is
+ found. We use this definition to display a nice error
+ message that the wrong type is passed }
+ candidates.find_wrong_para;
+ candidates.list(true);
+{$ifdef EXTDEBUG}
+ candidates.dump_info(V_Hint);
+{$endif EXTDEBUG}
+
+ { We can not proceed, release all procs and exit }
+ candidates.free;
+ goto errorexit;
+ end;
+
+ candidates.free;
+ end; { end of procedure to call determination }
+ end;
+
+ { check for hints (deprecated etc) }
+ if (procdefinition.typ = procdef) then
+ check_hints(tprocdef(procdefinition).procsym,tprocdef(procdefinition).symoptions,tprocdef(procdefinition).deprecatedmsg);
+
+ { add needed default parameters }
+ if assigned(procdefinition) and
+ (paralength<procdefinition.maxparacount) then
+ begin
+ paraidx:=0;
+ i:=0;
+ while (i<paralength) do
+ begin
+ if paraidx>=procdefinition.Paras.count then
+ internalerror(200306181);
+ if not(vo_is_hidden_para in tparavarsym(procdefinition.paras[paraidx]).varoptions) then
+ inc(i);
+ inc(paraidx);
+ end;
+ while (paraidx<procdefinition.paras.count) and (vo_is_hidden_para in tparavarsym(procdefinition.paras[paraidx]).varoptions) do
+ inc(paraidx);
+ while (paraidx<procdefinition.paras.count) do
+ begin
+ if not assigned(tparavarsym(procdefinition.paras[paraidx]).defaultconstsym) then
+ internalerror(200212142);
+ left:=ccallparanode.create(genconstsymtree(
+ tconstsym(tparavarsym(procdefinition.paras[paraidx]).defaultconstsym)),left);
+ { Ignore vs_hidden parameters }
+ repeat
+ inc(paraidx);
+ until (paraidx>=procdefinition.paras.count) or
+ not(vo_is_hidden_para in tparavarsym(procdefinition.paras[paraidx]).varoptions);
+ end;
+ end;
+
+ { recursive call? }
+ if assigned(current_procinfo) and
+ (procdefinition=current_procinfo.procdef) then
+ include(current_procinfo.flags,pi_is_recursive);
+
+ { handle predefined procedures }
+ is_const:=(po_internconst in procdefinition.procoptions) and
+ ((block_type in [bt_const,bt_type,bt_const_type,bt_var_type]) or
+ (assigned(left) and (tcallparanode(left).left.nodetype in [realconstn,ordconstn])));
+ if (procdefinition.proccalloption=pocall_internproc) or is_const then
+ begin
+ if assigned(left) then
+ begin
+ { convert types to those of the prototype, this is required by functions like ror, rol, sar
+ some use however a dummy type (Typedfile) so this would break them }
+ if not(tprocdef(procdefinition).extnumber in [fpc_in_Reset_TypedFile,fpc_in_Rewrite_TypedFile]) then
+ begin
+ { bind parasyms to the callparanodes and insert hidden parameters }
+ bind_parasym;
+
+ { insert type conversions for parameters }
+ if assigned(left) then
+ tcallparanode(left).insert_typeconv;
+ end;
+
+ { ptr and settextbuf need two args }
+ if assigned(tcallparanode(left).right) then
+ begin
+ hpt:=geninlinenode(tprocdef(procdefinition).extnumber,is_const,left);
+ left:=nil;
+ end
+ else
+ begin
+ hpt:=geninlinenode(tprocdef(procdefinition).extnumber,is_const,tcallparanode(left).left);
+ tcallparanode(left).left:=nil;
+ end;
+ end
+ else
+ hpt:=geninlinenode(tprocdef(procdefinition).extnumber,is_const,nil);
+ result:=hpt;
+ goto errorexit;
+ end;
+
+ { ensure that the result type is set }
+ if not(cnf_typedefset in callnodeflags) then
+ begin
+ { constructors return their current class type, not the type where the
+ constructor is declared, this can be different because of inheritance }
+ if (procdefinition.proctypeoption=potype_constructor) and
+ assigned(methodpointer) and
+ assigned(methodpointer.resultdef) and
+ (methodpointer.resultdef.typ=classrefdef) then
+ resultdef:=tclassrefdef(methodpointer.resultdef).pointeddef
+ else
+ { Member call to a (inherited) constructor from the class, the return
+ value is always self, so we change it to voidtype to generate an
+ error and to prevent users from generating non-working code
+ when they expect to clone the current instance, see bug 3662 (PFV) }
+ if (procdefinition.proctypeoption=potype_constructor) and
+ is_class(tprocdef(procdefinition).struct) and
+ assigned(methodpointer) and
+ (methodpointer.nodetype=loadn) and
+ (loadnf_is_self in tloadnode(methodpointer).loadnodeflags) then
+ resultdef:=voidtype
+ else
+ resultdef:=procdefinition.returndef;
+ end
+ else
+ resultdef:=typedef;
+
+ { Check object/class for methods }
+ if assigned(methodpointer) then
+ begin
+ { direct call to inherited abstract method, then we
+ can already give a error in the compiler instead
+ of a runtime error }
+ if (cnf_inherited in callnodeflags) and
+ (po_abstractmethod in procdefinition.procoptions) then
+ begin
+ if (m_delphi in current_settings.modeswitches) and
+ (cnf_anon_inherited in callnodeflags) then
+ begin
+ CGMessage(cg_h_inherited_ignored);
+ result:=cnothingnode.create;
+ exit;
+ end
+ else
+ CGMessage(cg_e_cant_call_abstract_method);
+ end;
+
+ { directly calling an interface/protocol/category/class helper
+ method via its type is not possible (always must be called via
+ the actual instance) }
+ if (methodpointer.nodetype=typen) and
+ (is_interface(methodpointer.resultdef) or
+ is_objc_protocol_or_category(methodpointer.resultdef)) then
+ CGMessage1(type_e_class_type_expected,methodpointer.resultdef.typename);
+
+ { if an inherited con- or destructor should be }
+ { called in a con- or destructor then a warning }
+ { will be made }
+ { con- and destructors need a pointer to the vmt }
+ if (cnf_inherited in callnodeflags) and
+ (procdefinition.proctypeoption in [potype_constructor,potype_destructor]) and
+ is_object(methodpointer.resultdef) and
+ not(current_procinfo.procdef.proctypeoption in [potype_constructor,potype_destructor]) then
+ CGMessage(cg_w_member_cd_call_from_method);
+
+ if methodpointer.nodetype<>typen then
+ begin
+ { Remove all postfix operators }
+ hpt:=methodpointer;
+ while assigned(hpt) and (hpt.nodetype in [subscriptn,vecn]) do
+ hpt:=tunarynode(hpt).left;
+
+ if ((hpt.nodetype=loadvmtaddrn) or
+ ((hpt.nodetype=loadn) and assigned(tloadnode(hpt).resultdef) and (tloadnode(hpt).resultdef.typ=classrefdef))) and
+ not (procdefinition.proctypeoption=potype_constructor) and
+ not (po_classmethod in procdefinition.procoptions) and
+ not (po_staticmethod in procdefinition.procoptions) then
+ { error: we are calling instance method from the class method/static method }
+ CGMessage(parser_e_only_class_members);
+
+ if (procdefinition.proctypeoption=potype_constructor) and
+ assigned(symtableproc) and
+ (symtableproc.symtabletype=withsymtable) and
+ (tnode(twithsymtable(symtableproc).withrefnode).nodetype=temprefn) then
+ CGmessage(cg_e_cannot_call_cons_dest_inside_with);
+
+ { R.Init then R will be initialized by the constructor,
+ Also allow it for simple loads }
+ if (procdefinition.proctypeoption=potype_constructor) or
+ ((hpt.nodetype=loadn) and
+ (methodpointer.resultdef.typ=objectdef) and
+ not(oo_has_virtual in tobjectdef(methodpointer.resultdef).objectoptions)
+ ) then
+ { a constructor will and a method may write something to }
+ { the fields }
+ set_varstate(methodpointer,vs_readwritten,[])
+ else
+ set_varstate(methodpointer,vs_read,[vsf_must_be_valid]);
+ end;
+
+ { if we are calling the constructor check for abstract
+ methods. Ignore inherited and member calls, because the
+ class is then already created }
+ if (procdefinition.proctypeoption=potype_constructor) and
+ not(cnf_inherited in callnodeflags) and
+ not(cnf_member_call in callnodeflags) then
+ verifyabstractcalls;
+ end
+ else
+ begin
+ { When this is method the methodpointer must be available }
+ if (right=nil) and
+ (procdefinition.owner.symtabletype in [ObjectSymtable,recordsymtable]) and
+ not procdefinition.no_self_node then
+ internalerror(200305061);
+ end;
+
+ { Set flag that the procedure uses varargs, also if they are not passed it is still
+ needed for x86_64 to pass the number of SSE registers used }
+ if po_varargs in procdefinition.procoptions then
+ include(callnodeflags,cnf_uses_varargs);
+
+ { Change loading of array of const to varargs }
+ if assigned(left) and
+ is_array_of_const(tparavarsym(procdefinition.paras[procdefinition.paras.count-1]).vardef) and
+ (procdefinition.proccalloption in cdecl_pocalls) then
+ convert_carg_array_of_const;
+
+ { bind parasyms to the callparanodes and insert hidden parameters }
+ bind_parasym;
+
+ { insert type conversions for parameters }
+ if assigned(left) then
+ tcallparanode(left).insert_typeconv;
+
+ { dispinterface methode invoke? }
+ if assigned(methodpointer) and is_dispinterface(methodpointer.resultdef) then
+ begin
+ case procdefinition.proctypeoption of
+ potype_propgetter: calltype:=dct_propget;
+ potype_propsetter: calltype:=dct_propput;
+ else
+ calltype:=dct_method;
+ end;
+ { if the result is used, we've to insert a call to convert the type to be on the "safe side" }
+ if (cnf_return_value_used in callnodeflags) and not is_void(procdefinition.returndef) then
+ begin
+ result:=internalstatements(statements);
+ converted_result_data:=ctempcreatenode.create(procdefinition.returndef,sizeof(procdefinition.returndef),
+ tt_persistent,true);
+ addstatement(statements,converted_result_data);
+ addstatement(statements,cassignmentnode.create(ctemprefnode.create(converted_result_data),
+ ctypeconvnode.create_internal(
+ translate_disp_call(methodpointer,parameters,calltype,'',tprocdef(procdefinition).dispid,procdefinition.returndef),
+ procdefinition.returndef)));
+ addstatement(statements,ctempdeletenode.create_normal_temp(converted_result_data));
+ addstatement(statements,ctemprefnode.create(converted_result_data));
+ end
+ else
+ result:=translate_disp_call(methodpointer,parameters,calltype,'',tprocdef(procdefinition).dispid,voidtype);
+
+ { don't free reused nodes }
+ methodpointer:=nil;
+ parameters:=nil;
+ end;
+
+ errorexit:
+ aktcallnode:=oldcallnode;
+ end;
+
+
+ procedure tcallnode.order_parameters;
+ var
+ hp,hpcurr,hpnext,hpfirst,hpprev : tcallparanode;
+ currloc : tcgloc;
+ begin
+ hpfirst:=nil;
+ hpcurr:=tcallparanode(left);
+ { cache all info about parameters containing stack tainting calls,
+ since we will need it a lot below and calculting it can be expensive }
+ while assigned(hpcurr) do
+ begin
+ hpcurr.init_contains_stack_tainting_call_cache;
+ hpcurr:=tcallparanode(hpcurr.right);
+ end;
+ hpcurr:=tcallparanode(left);
+ while assigned(hpcurr) do
+ begin
+ { pull out }
+ hpnext:=tcallparanode(hpcurr.right);
+ { pull in at the correct place.
+ Used order:
+ 1. LOC_REFERENCE with smallest offset (i386 only)
+ 2. LOC_REFERENCE with least complexity (non-i386 only)
+ 3. LOC_REFERENCE with most complexity (non-i386 only)
+ 4. LOC_REGISTER with most complexity
+ 5. LOC_REGISTER with least complexity
+ For the moment we only look at the first parameter field. Combining it
+ with multiple parameter fields will make things a lot complexer (PFV)
+
+ The reason for the difference regarding complexity ordering
+ between LOC_REFERENCE and LOC_REGISTER is mainly for calls:
+ we first want to treat the LOC_REFERENCE destinations whose
+ calculation does not require a call, because their location
+ may contain registers which might otherwise have to be saved
+ if a call has to be evaluated first. The calculated value is
+ stored on the stack and will thus no longer occupy any
+ register.
+
+ Similarly, for the register parameters we first want to
+ evaluate the calls, because otherwise the already loaded
+ register parameters will have to be saved so the intermediate
+ call can be evaluated (JM) }
+ if not assigned(hpcurr.parasym.paraloc[callerside].location) then
+ internalerror(200412152);
+ currloc:=hpcurr.parasym.paraloc[callerside].location^.loc;
+ hpprev:=nil;
+ hp:=hpfirst;
+ { on fixed_stack targets, always evaluate parameters containing
+ a call with stack parameters before all other parameters,
+ because they will prevent any other parameters from being put
+ in their final place; if both the current and the next para
+ contain a stack tainting call, don't do anything to prevent
+ them from keeping on chasing eachother's tail }
+ while assigned(hp) do
+ begin
+ if paramanager.use_fixed_stack and
+ hpcurr.contains_stack_tainting_call_cached then
+ break;
+ case currloc of
+ LOC_REFERENCE :
+ begin
+ case hp.parasym.paraloc[callerside].location^.loc of
+ LOC_REFERENCE :
+ begin
+ { Offset is calculated like:
+ sub esp,12
+ mov [esp+8],para3
+ mov [esp+4],para2
+ mov [esp],para1
+ call function
+ That means the for pushes the para with the
+ highest offset (see para3) needs to be pushed first
+ }
+{$ifdef i386}
+ { the i386 code generator expects all reference }
+ { parameter to be in this order so it can use }
+ { pushes in case of no fixed stack }
+ if (not paramanager.use_fixed_stack and
+ (hpcurr.parasym.paraloc[callerside].location^.reference.offset>
+ hp.parasym.paraloc[callerside].location^.reference.offset)) or
+ (paramanager.use_fixed_stack and
+ (node_complexity(hpcurr)<node_complexity(hp))) then
+{$else i386}
+ if (node_complexity(hpcurr)<node_complexity(hp)) then
+{$endif i386}
+ break;
+ end;
+ LOC_MMREGISTER,
+ LOC_REGISTER,
+ LOC_FPUREGISTER :
+ break;
+ end;
+ end;
+ LOC_MMREGISTER,
+ LOC_FPUREGISTER,
+ LOC_REGISTER :
+ begin
+ if (hp.parasym.paraloc[callerside].location^.loc<>LOC_REFERENCE) and
+ (node_complexity(hpcurr)>node_complexity(hp)) then
+ break;
+ end;
+ end;
+ hpprev:=hp;
+ hp:=tcallparanode(hp.right);
+ end;
+ hpcurr.right:=hp;
+ if assigned(hpprev) then
+ hpprev.right:=hpcurr
+ else
+ hpfirst:=hpcurr;
+ { next }
+ hpcurr:=hpnext;
+ end;
+ left:=hpfirst;
+ { now mark each parameter that is followed by a stack-tainting call,
+ to determine on use_fixed_stack targets which ones can immediately be
+ put in their final destination. Unforunately we can never put register
+ parameters immediately in their final destination (even on register-
+ rich architectures such as the PowerPC), because the code generator
+ can still insert extra calls that only make use of register
+ parameters (fpc_move() etc. }
+ hpcurr:=hpfirst;
+ while assigned(hpcurr) do
+ begin
+ if hpcurr.contains_stack_tainting_call_cached then
+ begin
+ { all parameters before this one are followed by a stack
+ tainting call }
+ hp:=hpfirst;
+ while hp<>hpcurr do
+ begin
+ hp.ffollowed_by_stack_tainting_call_cached:=true;
+ hp:=tcallparanode(hp.right);
+ end;
+ hpfirst:=hpcurr;
+ end;
+ hpcurr:=tcallparanode(hpcurr.right);
+ end;
+ end;
+
+
+ procedure tcallnode.check_stack_parameters;
+ var
+ hp : tcallparanode;
+ begin
+ hp:=tcallparanode(left);
+ while assigned(hp) do
+ begin
+ if assigned(hp.parasym) and
+ assigned(hp.parasym.paraloc[callerside].location) and
+ (hp.parasym.paraloc[callerside].location^.loc=LOC_REFERENCE) then
+ include(current_procinfo.flags,pi_has_stackparameter);
+ hp:=tcallparanode(hp.right);
+ end;
+ end;
+
+
+ procedure tcallnode.check_inlining;
+ var
+ st : tsymtable;
+ para : tcallparanode;
+ begin
+ { Can we inline the procedure? }
+ if ([po_inline,po_has_inlininginfo] <= procdefinition.procoptions) then
+ begin
+ include(callnodeflags,cnf_do_inline);
+ { Check if we can inline the procedure when it references proc/var that
+ are not in the globally available }
+ st:=procdefinition.owner;
+ if (st.symtabletype=ObjectSymtable) then
+ st:=st.defowner.owner;
+ if (pi_uses_static_symtable in tprocdef(procdefinition).inlininginfo^.flags) and
+ (st.symtabletype=globalsymtable) and
+ (not st.iscurrentunit) then
+ begin
+ Comment(V_lineinfo+V_Debug,'Not inlining "'+tprocdef(procdefinition).procsym.realname+'", references static symtable');
+ exclude(callnodeflags,cnf_do_inline);
+ end;
+ para:=tcallparanode(parameters);
+ while assigned(para) do
+ begin
+ if not para.can_be_inlined then
+ begin
+ Comment(V_lineinfo+V_Debug,'Not inlining "'+tprocdef(procdefinition).procsym.realname+
+ '", invocation parameter contains an unsafe/unsupported construct');
+ exclude(callnodeflags,cnf_do_inline);
+ break;
+ end;
+ para:=tcallparanode(para.nextpara);
+ end;
+ end;
+ end;
+
+
+ function tcallnode.pass_1 : tnode;
+ begin
+ result:=nil;
+
+ { as pass_1 is never called on the methodpointer node, we must check
+ here that it's not a helper type }
+ if assigned(methodpointer) and
+ (methodpointer.nodetype=typen) and
+ is_objectpascal_helper(ttypenode(methodpointer).typedef) and
+ not ttypenode(methodpointer).helperallowed then
+ Message(parser_e_no_category_as_types);
+
+ { convert Objective-C calls into a message call }
+ if (procdefinition.typ=procdef) and
+ (po_objc in tprocdef(procdefinition).procoptions) then
+ begin
+ if not(cnf_objc_processed in callnodeflags) then
+ objc_convert_to_message_send;
+ end
+ else
+ begin
+ { The following don't apply to obj-c: obj-c methods can never be
+ inlined because they're always virtual and the destination can
+ change at run, and for the same reason we also can't perform
+ WPO on them (+ they have no constructors) }
+
+ { Check if the call can be inlined, sets the cnf_do_inline flag }
+ check_inlining;
+
+ { must be called before maybe_load_in_temp(methodpointer), because
+ it converts the methodpointer into a temp in case it's a call
+ (and we want to know the original call)
+ }
+ register_created_object_types;
+ end;
+
+ { Maybe optimize the loading of the methodpointer using a temp. When the methodpointer
+ is a calln this is even required to not execute the calln twice.
+ This needs to be done after the resulttype pass, because in the resulttype we can still convert the
+ calln to a loadn (PFV) }
+ if assigned(methodpointer) then
+ maybe_load_in_temp(methodpointer);
+
+ { Create destination (temp or assignment-variable reuse) for function result if it not yet set }
+ maybe_create_funcret_node;
+
+ { Insert the self,vmt,function result in the parameters }
+ gen_hidden_parameters;
+
+ { Remove useless nodes from init/final blocks }
+ { (simplify depends on typecheck info) }
+ if assigned(callinitblock) then
+ begin
+ typecheckpass(tnode(callinitblock));
+ doinlinesimplify(tnode(callinitblock));
+ end;
+ if assigned(callcleanupblock) then
+ begin
+ typecheckpass(tnode(callcleanupblock));
+ doinlinesimplify(tnode(callcleanupblock));
+ end;
+
+ { Continue with checking a normal call or generate the inlined code }
+ if cnf_do_inline in callnodeflags then
+ result:=pass1_inline
+ else
+ result:=pass1_normal;
+ end;
+
+
+ function tcallnode.pass1_normal : tnode;
+ begin
+ result:=nil;
+
+ { calculate the parameter info for the procdef }
+ procdefinition.init_paraloc_info(callerside);
+
+ { calculate the parameter size needed for this call include varargs if they are available }
+ if assigned(varargsparas) then
+ pushedparasize:=paramanager.create_varargs_paraloc_info(procdefinition,varargsparas)
+ else
+ pushedparasize:=procdefinition.callerargareasize;
+
+ { record maximum parameter size used in this proc }
+ current_procinfo.allocate_push_parasize(pushedparasize);
+
+ { check for stacked parameters }
+ if assigned(left) and
+ (current_settings.optimizerswitches*[cs_opt_stackframe,cs_opt_level1]<>[]) then
+ check_stack_parameters;
+
+ if assigned(callinitblock) then
+ firstpass(tnode(callinitblock));
+
+ { function result node (tempref or simple load) }
+ if assigned(funcretnode) then
+ firstpass(funcretnode);
+
+ { parameters }
+ if assigned(left) then
+ tcallparanode(left).firstcallparan;
+
+ { procedure variable ? }
+ if assigned(right) then
+ firstpass(right);
+
+ if assigned(methodpointer) and
+ (methodpointer.nodetype<>typen) then
+ firstpass(methodpointer);
+
+ if assigned(callcleanupblock) then
+ firstpass(tnode(callcleanupblock));
+
+ if not (block_type in [bt_const,bt_type,bt_const_type,bt_var_type]) then
+ include(current_procinfo.flags,pi_do_call);
+
+ { order parameters }
+ order_parameters;
+
+ { get a register for the return value }
+ if (not is_void(resultdef)) then
+ begin
+ if paramanager.ret_in_param(resultdef,procdefinition.proccalloption) then
+ begin
+ expectloc:=LOC_REFERENCE;
+ end
+ else
+ { ansi/widestrings must be registered, so we can dispose them }
+ if is_ansistring(resultdef) or
+ is_widestring(resultdef) or
+ is_unicodestring(resultdef) then
+ begin
+ expectloc:=LOC_REFERENCE;
+ end
+ else
+ { we have only to handle the result if it is used }
+ if (cnf_return_value_used in callnodeflags) then
+ expectloc:=get_expect_loc
+ else
+ expectloc:=LOC_VOID;
+ end
+ else
+ expectloc:=LOC_VOID;
+ end;
+
+{$ifdef state_tracking}
+ function Tcallnode.track_state_pass(exec_known:boolean):boolean;
+
+ var hp:Tcallparanode;
+ value:Tnode;
+
+ begin
+ track_state_pass:=false;
+ hp:=Tcallparanode(left);
+ while assigned(hp) do
+ begin
+ if left.track_state_pass(exec_known) then
+ begin
+ left.resultdef:=nil;
+ do_typecheckpass(left);
+ end;
+ value:=aktstate.find_fact(hp.left);
+ if value<>nil then
+ begin
+ track_state_pass:=true;
+ hp.left.destroy;
+ hp.left:=value.getcopy;
+ do_typecheckpass(hp.left);
+ end;
+ hp:=Tcallparanode(hp.right);
+ end;
+ end;
+{$endif}
+
+
+{**************************************************************************
+ INLINING SUPPORT
+**************************************************************************}
+
+ function tcallnode.replaceparaload(var n: tnode; arg: pointer): foreachnoderesult;
+ var
+ paras: tcallparanode;
+ temp: tnode;
+ indexnr : integer;
+ begin
+ result := fen_false;
+ n.fileinfo := pfileposinfo(arg)^;
+ if (n.nodetype = loadn) then
+ begin
+ case tloadnode(n).symtableentry.typ of
+ paravarsym :
+ begin
+ paras := tcallparanode(left);
+ while assigned(paras) and
+ (paras.parasym <> tloadnode(n).symtableentry) do
+ paras := tcallparanode(paras.right);
+ if assigned(paras) then
+ begin
+ n.free;
+ n := paras.left.getcopy;
+ typecheckpass(n);
+ result := fen_true;
+ end;
+ end;
+ localvarsym :
+ begin
+ { local? }
+ if (tloadnode(n).symtableentry.owner <> tprocdef(procdefinition).localst) then
+ exit;
+ indexnr:=tloadnode(n).symtableentry.owner.SymList.IndexOf(tloadnode(n).symtableentry);
+ if (indexnr >= inlinelocals.count) or
+ not assigned(inlinelocals[indexnr]) then
+ internalerror(20040720);
+ temp := tnode(inlinelocals[indexnr]).getcopy;
+ n.free;
+ n := temp;
+ typecheckpass(n);
+ result := fen_true;
+ end;
+ end;
+ end;
+ end;
+
+
+ procedure tcallnode.createlocaltemps(p:TObject;arg:pointer);
+ var
+ tempnode: ttempcreatenode;
+ indexnr : integer;
+ begin
+ if (TSym(p).typ <> localvarsym) then
+ exit;
+ indexnr:=TSym(p).Owner.SymList.IndexOf(p);
+ if (indexnr >= inlinelocals.count) then
+ inlinelocals.count:=indexnr+10;
+ if (vo_is_funcret in tabstractvarsym(p).varoptions) then
+ begin
+ if not assigned(funcretnode) then
+ internalerror(200709081);
+ inlinelocals[indexnr] := funcretnode.getcopy
+ end
+ else
+ begin
+ tempnode :=ctempcreatenode.create(tabstractvarsym(p).vardef,
+ tabstractvarsym(p).vardef.size,tt_persistent,tabstractvarsym(p).is_regvar(false));
+ addstatement(inlineinitstatement,tempnode);
+ addstatement(inlinecleanupstatement,ctempdeletenode.create(tempnode));
+ { inherit addr_taken flag }
+ if (tabstractvarsym(p).addr_taken) then
+ include(tempnode.tempinfo^.flags,ti_addr_taken);
+ inlinelocals[indexnr] := ctemprefnode.create(tempnode);
+ end;
+ end;
+
+
+ function nonlocalvars(var n: tnode; arg: pointer): foreachnoderesult;
+ begin
+ result := fen_false;
+ { this is just to play it safe, there are more safe situations }
+ if (n.nodetype = derefn) or
+ ((n.nodetype = loadn) and
+ { globals and fields of (possibly global) objects could always be changed in the callee }
+ ((tloadnode(n).symtable.symtabletype in [globalsymtable,ObjectSymtable]) or
+ { statics can only be modified by functions in the same unit }
+ ((tloadnode(n).symtable.symtabletype = staticsymtable) and
+ (tloadnode(n).symtable = TSymtable(arg))))) or
+ ((n.nodetype = subscriptn) and
+ (tsubscriptnode(n).vs.owner.symtabletype = ObjectSymtable)) then
+ result := fen_norecurse_true;
+ end;
+
+
+ procedure tcallnode.createinlineparas;
+ var
+ para: tcallparanode;
+ tempnode: ttempcreatenode;
+ n: tnode;
+ paraaddr: taddrnode;
+ ptrtype: tpointerdef;
+ paracomplexity: longint;
+ begin
+ { parameters }
+ para := tcallparanode(left);
+ while assigned(para) do
+ begin
+ if (para.parasym.typ = paravarsym) then
+ begin
+ { must take copy of para.left, because if it contains a }
+ { temprefn pointing to a copied temp (e.g. methodpointer), }
+ { then this parameter must be changed to point to the copy of }
+ { that temp (JM) }
+ n := para.left.getcopy;
+ para.left.free;
+ para.left := n;
+
+ firstpass(para.left);
+
+ { create temps for value parameters, function result and also for }
+ { const parameters which are passed by value instead of by reference }
+ { we need to take care that we use the type of the defined parameter and not of the
+ passed parameter, because these can be different in case of a formaldef (PFV) }
+ paracomplexity := node_complexity(para.left);
+ { check if we have to create a temp, assign the parameter's }
+ { contents to that temp and then substitute the paramter }
+ { with the temp everywhere in the function }
+ if
+ ((tparavarsym(para.parasym).varregable in [vr_none,vr_addr]) and
+ not(para.left.expectloc in [LOC_REFERENCE,LOC_CREFERENCE])) or
+ { we can't assign to formaldef temps }
+ ((para.parasym.vardef.typ<>formaldef) and
+ (
+ { if paracomplexity > 1, we normally take the address of }
+ { the parameter expression, store it in a temp and }
+ { substitute the dereferenced temp in the inlined function }
+ { We can't do this if we can't take the address of the }
+ { parameter expression, so in that case assign to a temp }
+ not(para.left.expectloc in [LOC_REFERENCE,LOC_CREFERENCE,LOC_CONSTANT]) or
+ ((paracomplexity > 1) and
+ (not valid_for_addr(para.left,false) or
+ (para.left.nodetype = calln) or
+ is_constnode(para.left))) or
+ { we do not need to create a temp for value parameters }
+ { which are not modified in the inlined function }
+ { const parameters can get vs_readwritten if their }
+ { address is taken }
+ ((((para.parasym.varspez = vs_value) and
+ (para.parasym.varstate in [vs_initialised,vs_declared,vs_read])) or
+ { in case of const, this is only necessary if the }
+ { variable would be passed by value normally, or if }
+ { there is such a variable somewhere in an expression }
+ ((para.parasym.varspez = vs_const) and
+ (not paramanager.push_addr_param(vs_const,para.parasym.vardef,procdefinition.proccalloption) or
+ (paracomplexity > 1)))) and
+ { however, if we pass a global variable, an object field or}
+ { an expression containing a pointer dereference as }
+ { parameter, this value could be modified in other ways as }
+ { well and in such cases create a temp to be on the safe }
+ { side }
+ foreachnodestatic(para.left,@nonlocalvars,pointer(symtableproc))) or
+ { value parameters of which we know they are modified by }
+ { definition have to be copied to a temp }
+ { the same goes for cases of "x:=f(x)" where x is passed }
+ { as value parameter to f(), at least if we optimized }
+ { invocation by setting the funcretnode to x to avoid }
+ { assignment afterwards (since x may be read inside the }
+ { function after it modified result==x) }
+ ((para.parasym.varspez = vs_value) and
+ (not(para.parasym.varstate in [vs_initialised,vs_declared,vs_read]) or
+ (assigned(aktassignmentnode) and
+ (aktassignmentnode.right=self) and
+ (nf_assign_done_in_right in aktassignmentnode.flags) and
+ aktassignmentnode.left.isequal(para.left)))) or
+ { the compiler expects that it can take the address of parameters passed by reference in
+ the case of const so we can't replace the node simply by a constant node
+ When playing with this code, ensure that
+ function f(const a,b : longint) : longint;inline;
+ begin
+ result:=a*b;
+ end;
+
+ [...]
+ ...:=f(10,20));
+ [...]
+
+ is still folded. (FK)
+ }
+ ((para.parasym.varspez = vs_const) and
+ { const para's can get vs_readwritten if their address }
+ { is taken }
+ ((para.parasym.varstate = vs_readwritten) or
+ { call-by-reference const's may need to be passed by }
+ { reference to function called in the inlined code }
+ (paramanager.push_addr_param(vs_const,para.parasym.vardef,procdefinition.proccalloption) and
+ not valid_for_addr(para.left,false))
+ ))
+ )
+ ) then
+ begin
+ { don't create a new temp unnecessarily, but make sure we
+ do create a new one if the old one could be a regvar and
+ the new one cannot be one }
+ if (para.left.nodetype<>temprefn) or
+ (((tparavarsym(para.parasym).varregable in [vr_none,vr_addr])) and
+ (ti_may_be_in_reg in ttemprefnode(para.left).tempinfo^.flags)) then
+ begin
+ tempnode := ctempcreatenode.create(para.parasym.vardef,para.parasym.vardef.size,
+ tt_persistent,tparavarsym(para.parasym).is_regvar(false));
+ addstatement(inlineinitstatement,tempnode);
+ addstatement(inlinecleanupstatement,ctempdeletenode.create(tempnode));
+ addstatement(inlineinitstatement,cassignmentnode.create(ctemprefnode.create(tempnode),
+ para.left));
+ para.left := ctemprefnode.create(tempnode);
+ { inherit addr_taken flag }
+ if (tabstractvarsym(para.parasym).addr_taken) then
+ include(tempnode.tempinfo^.flags,ti_addr_taken);
+ end;
+ end
+ { otherwise if the parameter is "complex", take the address }
+ { of the parameter expression, store it in a temp and replace }
+ { occurrences of the parameter with dereferencings of this }
+ { temp }
+ else if (paracomplexity > 1) then
+ begin
+ ptrtype:=tpointerdef.create(para.left.resultdef);
+ tempnode := ctempcreatenode.create(ptrtype,ptrtype.size,tt_persistent,tparavarsym(para.parasym).is_regvar(true));
+ addstatement(inlineinitstatement,tempnode);
+ addstatement(inlinecleanupstatement,ctempdeletenode.create(tempnode));
+ { inherit addr_taken flag }
+ if (tabstractvarsym(para.parasym).addr_taken) then
+ include(tempnode.tempinfo^.flags,ti_addr_taken);
+ paraaddr:=caddrnode.create_internal(para.left);
+ include(paraaddr.flags,nf_typedaddr);
+ addstatement(inlineinitstatement,cassignmentnode.create(ctemprefnode.create(tempnode),
+ paraaddr));
+ para.left:=cderefnode.create(ctemprefnode.create(tempnode));
+ end;
+ end;
+ para := tcallparanode(para.right);
+ end;
+ { local variables }
+ if not assigned(tprocdef(procdefinition).localst) or
+ (tprocdef(procdefinition).localst.SymList.count = 0) then
+ exit;
+ inlinelocals.count:=tprocdef(procdefinition).localst.SymList.count;
+ tprocdef(procdefinition).localst.SymList.ForEachCall(@createlocaltemps,nil);
+ end;
+
+
+ function tcallnode.optimize_funcret_assignment(inlineblock: tblocknode): tnode;
+ var
+ hp : tstatementnode;
+ hp2 : tnode;
+ resassign : tassignmentnode;
+ begin
+ result:=nil;
+ if not assigned(funcretnode) or
+ not(cnf_return_value_used in callnodeflags) then
+ exit;
+
+ { tempcreatenode for the function result }
+ hp:=tstatementnode(inlineblock.left);
+ if not(assigned(hp)) or
+ (hp.left.nodetype <> tempcreaten) or
+ not(nf_is_funcret in hp.left.flags) then
+ exit;
+
+ { constant assignment? right must be a constant (mainly to avoid trying
+ to reuse local temps which may already be freed afterwards once these
+ checks are made looser) }
+ hp:=tstatementnode(hp.right);
+ if not(assigned(hp)) or
+ (hp.left.nodetype<>assignn) or
+ not is_constnode(tassignmentnode(hp.left).right) then
+ exit;
+
+ { left must be function result }
+ resassign:=tassignmentnode(hp.left);
+ hp2:=resassign.left;
+ { can have extra type conversion due to absolute mapping
+ of <fucntionname> on function result var }
+ if (hp2.nodetype=typeconvn) and (ttypeconvnode(hp2).convtype=tc_equal) then
+ hp2:=ttypeconvnode(hp2).left;
+ if (hp2.nodetype<>temprefn) or
+ not(nf_is_funcret in hp2.flags) then
+ exit;
+
+ { tempdelete to normal of the function result }
+ hp:=tstatementnode(hp.right);
+ if not(assigned(hp)) or
+ (hp.left.nodetype <> tempdeleten) then
+ exit;
+
+ { the function result once more }
+ hp:=tstatementnode(hp.right);
+ if not(assigned(hp)) or
+ (hp.left.nodetype<>temprefn) or
+ not(nf_is_funcret in hp.left.flags) then
+ exit;
+
+ { should be the end }
+ if assigned(hp.right) then
+ exit;
+
+ { we made it! }
+ result:=tassignmentnode(resassign).right.getcopy;
+ firstpass(result);
+ end;
+
+
+ function tcallnode.pass1_inline:tnode;
+ var
+ n,
+ body : tnode;
+ para : tcallparanode;
+ inlineblock,
+ inlinecleanupblock : tblocknode;
+ begin
+ result:=nil;
+ if not(assigned(tprocdef(procdefinition).inlininginfo) and
+ assigned(tprocdef(procdefinition).inlininginfo^.code)) then
+ internalerror(200412021);
+
+ inlinelocals:=TFPObjectList.create(true);
+
+ { inherit flags }
+ current_procinfo.flags:=current_procinfo.flags+
+ ((procdefinition as tprocdef).inlininginfo^.flags*inherited_inlining_flags);
+
+ { Create new code block for inlining }
+ inlineblock:=internalstatements(inlineinitstatement);
+ inlinecleanupblock:=internalstatements(inlinecleanupstatement);
+
+ if assigned(callinitblock) then
+ addstatement(inlineinitstatement,callinitblock.getcopy);
+
+ { replace complex parameters with temps }
+ createinlineparas;
+
+ { create a copy of the body and replace parameter loads with the parameter values }
+ body:=tprocdef(procdefinition).inlininginfo^.code.getcopy;
+ foreachnode(pm_preprocess,body,@replaceparaload,@fileinfo);
+
+ { Concat the body and finalization parts }
+ addstatement(inlineinitstatement,body);
+ addstatement(inlineinitstatement,inlinecleanupblock);
+ inlinecleanupblock:=nil;
+
+ if assigned(callcleanupblock) then
+ addstatement(inlineinitstatement,callcleanupblock.getcopy);
+
+ { the last statement of the new inline block must return the
+ location and type of the function result.
+ This is not needed when the result is not used, also the tempnode is then
+ already destroyed by a tempdelete in the callcleanupblock tree }
+ if not is_void(resultdef) and
+ (cnf_return_value_used in callnodeflags) then
+ begin
+ if assigned(funcretnode) then
+ addstatement(inlineinitstatement,funcretnode.getcopy)
+ else
+ begin
+ para:=tcallparanode(left);
+ while assigned(para) do
+ begin
+ if (vo_is_hidden_para in para.parasym.varoptions) and
+ (vo_is_funcret in para.parasym.varoptions) then
+ begin
+ addstatement(inlineinitstatement,para.left.getcopy);
+ break;
+ end;
+ para:=tcallparanode(para.right);
+ end;
+ end;
+ end;
+
+ { consider it must not be inlined if called
+ again inside the args or itself }
+ exclude(procdefinition.procoptions,po_inline);
+ typecheckpass(tnode(inlineblock));
+ doinlinesimplify(tnode(inlineblock));
+ firstpass(tnode(inlineblock));
+ include(procdefinition.procoptions,po_inline);
+ result:=inlineblock;
+
+ { if the function result is used then verify that the blocknode
+ returns the same result type as the original callnode }
+ if (cnf_return_value_used in callnodeflags) and
+ (result.resultdef<>resultdef) then
+ internalerror(200709171);
+
+ { free the temps for the locals }
+ inlinelocals.free;
+ inlinelocals:=nil;
+ inlineinitstatement:=nil;
+ inlinecleanupstatement:=nil;
+
+ { if all that's left of the inlined function is an constant assignment
+ to the result, replace the whole block with the constant only }
+ n:=optimize_funcret_assignment(inlineblock);
+ if assigned(n) then
+ begin
+ inlineblock.free;
+ result:=n;
+ end;
+
+{$ifdef DEBUGINLINE}
+ writeln;
+ writeln('**************************',tprocdef(procdefinition).mangledname);
+ printnode(output,result);
+{$endif DEBUGINLINE}
+ end;
+
+end.
diff --git a/closures/compiler/ncgadd.pas b/closures/compiler/ncgadd.pas
new file mode 100644
index 0000000000..45b6a9af25
--- /dev/null
+++ b/closures/compiler/ncgadd.pas
@@ -0,0 +1,854 @@
+{
+ Copyright (c) 2000-2002 by the FPC development team
+
+ Code generation for add nodes (generic version)
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit ncgadd;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,nadd,cpubase;
+
+ type
+ tcgaddnode = class(taddnode)
+{ function pass_1: tnode; override;}
+ procedure pass_generate_code;override;
+ protected
+ { call secondpass for both left and right }
+ procedure pass_left_right;
+ { set the register of the result location }
+ procedure set_result_location_reg;
+ { load left and right nodes into registers }
+ procedure force_reg_left_right(allow_swap,allow_constant:boolean);
+
+ procedure second_opfloat;
+ procedure second_opboolean;
+ procedure second_opsmallset;
+ procedure second_op64bit;
+ procedure second_opordinal;
+
+ procedure second_addstring;virtual;
+ procedure second_addfloat;virtual;abstract;
+ procedure second_addboolean;virtual;
+ procedure second_addsmallset;virtual;
+ procedure second_addsmallsetelement;virtual;
+{$ifdef x86}
+{$ifdef SUPPORT_MMX}
+ procedure second_opmmx;virtual;abstract;
+{$endif SUPPORT_MMX}
+{$endif x86}
+ procedure second_opvector;virtual;abstract;
+ procedure second_add64bit;virtual;
+ procedure second_addordinal;virtual;
+ procedure second_cmpfloat;virtual;abstract;
+ procedure second_cmpboolean;virtual;
+ procedure second_cmpsmallset;virtual;abstract;
+ procedure second_cmp64bit;virtual;abstract;
+ procedure second_cmpordinal;virtual;abstract;
+ end;
+
+ implementation
+
+ uses
+ globtype,systems,
+ cutils,verbose,globals,
+ symconst,symdef,paramgr,
+ aasmbase,aasmtai,aasmdata,defutil,
+ cgbase,procinfo,pass_2,tgobj,
+ nutils,ncon,nset,ncgutil,cgobj,cgutils
+ ;
+
+
+{*****************************************************************************
+ Helpers
+*****************************************************************************}
+
+ procedure tcgaddnode.pass_left_right;
+ var
+ tmpreg : tregister;
+{$ifdef x86}
+ pushedfpu,
+{$endif x86}
+ isjump : boolean;
+ otl,ofl : tasmlabel;
+ begin
+ { calculate the operator which is more difficult }
+ firstcomplex(self);
+
+ { in case of constant put it to the left }
+ if (left.nodetype=ordconstn) then
+ swapleftright;
+
+ isjump:=(left.expectloc=LOC_JUMP);
+ if isjump then
+ begin
+ otl:=current_procinfo.CurrTrueLabel;
+ current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
+ ofl:=current_procinfo.CurrFalseLabel;
+ current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel);
+ end;
+ secondpass(left);
+ if left.location.loc in [LOC_FLAGS,LOC_JUMP] then
+ location_force_reg(current_asmdata.CurrAsmList,left.location,def_cgsize(resultdef),false);
+ if isjump then
+ begin
+ current_procinfo.CurrTrueLabel:=otl;
+ current_procinfo.CurrFalseLabel:=ofl;
+ end;
+
+{$ifdef x86}
+ { are too few registers free? }
+ pushedfpu:=false;
+ if (left.location.loc=LOC_FPUREGISTER) and
+ (node_resources_fpu(right)>=maxfpuregs) then
+ begin
+ location_force_mem(current_asmdata.CurrAsmList,left.location);
+ pushedfpu:=true;
+ end;
+{$endif x86}
+
+ isjump:=(right.expectloc=LOC_JUMP);
+ if isjump then
+ begin
+ otl:=current_procinfo.CurrTrueLabel;
+ current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
+ ofl:=current_procinfo.CurrFalseLabel;
+ current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel);
+ end;
+ secondpass(right);
+ if right.location.loc in [LOC_FLAGS,LOC_JUMP] then
+ location_force_reg(current_asmdata.CurrAsmList,right.location,def_cgsize(resultdef),false);
+ if isjump then
+ begin
+ current_procinfo.CurrTrueLabel:=otl;
+ current_procinfo.CurrFalseLabel:=ofl;
+ end;
+{$ifdef x86}
+ if pushedfpu then
+ begin
+ if use_vectorfpu(left.resultdef) then
+ begin
+ tmpreg := cg.getmmregister(current_asmdata.CurrAsmList,left.location.size);
+ cg.a_loadmm_loc_reg(current_asmdata.CurrAsmList,left.location.size,left.location,tmpreg,mms_movescalar);
+ location_freetemp(current_asmdata.CurrAsmList,left.location);
+ location_reset(left.location,LOC_MMREGISTER,left.location.size);
+ left.location.register:=tmpreg;
+ end
+ else
+ begin
+ tmpreg := cg.getfpuregister(current_asmdata.CurrAsmList,left.location.size);
+ cg.a_loadfpu_loc_reg(current_asmdata.CurrAsmList,left.location.size,left.location,tmpreg);
+ location_freetemp(current_asmdata.CurrAsmList,left.location);
+ location_reset(left.location,LOC_FPUREGISTER,left.location.size);
+ left.location.register := tmpreg;
+ { left operand is now on top of the stack, instead of the right one! }
+ if (right.location.loc=LOC_FPUREGISTER) then
+ toggleflag(nf_swapped);
+ end;
+ end;
+{$endif x86}
+ end;
+
+
+ procedure tcgaddnode.set_result_location_reg;
+ begin
+ location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
+{$ifdef x86}
+ if left.location.loc=LOC_REGISTER then
+ begin
+ if TCGSize2Size[left.location.size]<>TCGSize2Size[location.size] then
+ internalerror(200307041);
+{$ifndef cpu64bitalu}
+ if location.size in [OS_64,OS_S64] then
+ begin
+ location.register64.reglo := left.location.register64.reglo;
+ location.register64.reghi := left.location.register64.reghi;
+ end
+ else
+{$endif}
+ location.register := left.location.register;
+ end
+ else
+ if right.location.loc=LOC_REGISTER then
+ begin
+ if TCGSize2Size[right.location.size]<>TCGSize2Size[location.size] then
+ internalerror(200307042);
+{$ifndef cpu64bitalu}
+ if location.size in [OS_64,OS_S64] then
+ begin
+ location.register64.reglo := right.location.register64.reglo;
+ location.register64.reghi := right.location.register64.reghi;
+ end
+ else
+{$endif}
+ location.register := right.location.register;
+ end
+ else
+{$endif}
+ begin
+{$ifndef cpu64bitalu}
+ if location.size in [OS_64,OS_S64] then
+ begin
+ location.register64.reglo := cg.getintregister(current_asmdata.CurrAsmList,OS_32);
+ location.register64.reghi := cg.getintregister(current_asmdata.CurrAsmList,OS_32);
+ end
+ else
+{$endif}
+ location.register := cg.getintregister(current_asmdata.CurrAsmList,location.size);
+ end;
+ end;
+
+
+ procedure tcgaddnode.force_reg_left_right(allow_swap,allow_constant:boolean);
+ begin
+ if (left.location.loc<>LOC_REGISTER) and
+ not(
+ allow_constant and
+ (left.location.loc in [LOC_CONSTANT,LOC_CREGISTER])
+ ) then
+ location_force_reg(current_asmdata.CurrAsmList,left.location,left.location.size,false);
+ if (right.location.loc<>LOC_REGISTER) and
+ not(
+ allow_constant and
+ (right.location.loc in [LOC_CONSTANT,LOC_CREGISTER]) and
+ (left.location.loc<>LOC_CONSTANT)
+ ) then
+ location_force_reg(current_asmdata.CurrAsmList,right.location,right.location.size,false);
+
+ { Left is always a register, right can be register or constant }
+ if left.location.loc=LOC_CONSTANT then
+ begin
+ { when it is not allowed to swap we have a constant on
+ left, that will give problems }
+ if not allow_swap then
+ internalerror(200307043);
+ swapleftright;
+ end;
+ end;
+
+
+{*****************************************************************************
+ Smallsets
+*****************************************************************************}
+
+ procedure tcgaddnode.second_opsmallset;
+ begin
+ { when a setdef is passed, it has to be a smallset }
+ if not(
+ ((left.nodetype=setelementn) or is_smallset(left.resultdef)) and
+ ((right.nodetype=setelementn) or is_smallset(right.resultdef))
+ ) then
+ internalerror(200203302);
+ if (left.nodetype=setelementn) or (right.nodetype=setelementn) then
+ second_addsmallsetelement
+ else if nodetype in [equaln,unequaln,gtn,gten,lten,ltn] then
+ second_cmpsmallset
+ else
+ second_addsmallset;
+ end;
+
+
+ procedure tcgaddnode.second_addsmallset;
+ var
+ cgop : TOpCg;
+ opdone : boolean;
+ begin
+ opdone := false;
+ pass_left_right;
+ force_reg_left_right(true,true);
+ set_result_location_reg;
+ case nodetype of
+ addn :
+ cgop:=OP_OR;
+ symdifn :
+ cgop:=OP_XOR;
+ muln :
+ cgop:=OP_AND;
+ subn :
+ begin
+ cgop:=OP_AND;
+ if (not(nf_swapped in flags)) then
+ if (right.location.loc=LOC_CONSTANT) then
+ right.location.value := not(right.location.value)
+ else
+ opdone := true
+ else if (left.location.loc=LOC_CONSTANT) then
+ left.location.value := not(left.location.value)
+ else
+ begin
+ swapleftright;
+ opdone := true;
+ end;
+ if opdone then
+ begin
+ if (right.location.size<>left.location.size) or
+ (location.size<>left.location.size) then
+ internalerror(2010123001);
+ { make sure that location.register is different from
+ left.location.register, since right will overwrite it
+ and we'll use left afterwards }
+ if (right.location.loc=LOC_REGISTER) then
+ location.register:=right.location.register
+ else
+ location.register:=cg.getintregister(current_asmdata.CurrAsmList,location.size);
+ { make sure we don't modify left/right.location, because we told
+ force_reg_left_right above that they can be constant }
+ cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_NOT,location.size,right.location.register,location.register);
+ if left.location.loc = LOC_CONSTANT then
+ cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_AND,location.size,left.location.value,location.register)
+ else
+ cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_AND,location.size,left.location.register,location.register);
+ end;
+ end;
+ else
+ internalerror(2002072701);
+ end;
+
+ if not opdone then
+ begin
+ // these are all commutative operations
+ if (left.location.loc = LOC_CONSTANT) then
+ swapleftright;
+ if (right.location.loc = LOC_CONSTANT) then
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,cgop,location.size,
+ right.location.value,left.location.register,
+ location.register)
+ else
+ cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,cgop,location.size,
+ right.location.register,left.location.register,
+ location.register);
+ end;
+ end;
+
+
+ procedure tcgaddnode.second_addsmallsetelement;
+ var
+ tmpreg : tregister;
+ mask,
+ setbase : aint;
+ cgop : TOpCg;
+ begin
+ if nodetype<>addn then
+ internalerror(20080302);
+ { no range support for smallsets }
+ if assigned(tsetelementnode(right).right) then
+ internalerror(20080303);
+ pass_left_right;
+ { setelementn is a special case, it must be on right }
+ if (nf_swapped in flags) and
+ (left.nodetype=setelementn) then
+ swapleftright;
+ force_reg_left_right(false,false);
+ set_result_location_reg;
+ setbase:=tsetdef(left.resultdef).setbase;
+ if (right.location.loc = LOC_CONSTANT) then
+ begin
+ if (target_info.endian=endian_big) then
+ mask:=aint((aword(1) shl (resultdef.size*8-1)) shr aword(right.location.value-setbase))
+ else
+ mask:=aint(1 shl (right.location.value-setbase));
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_OR,location.size,
+ mask,left.location.register,location.register);
+ end
+ else
+ begin
+ if (target_info.endian=endian_big) then
+ begin
+ mask:=aint((aword(1) shl (resultdef.size*8-1)));
+ cgop:=OP_SHR
+ end
+ else
+ begin
+ mask:=1;
+ cgop:=OP_SHL
+ end;
+ tmpreg := cg.getintregister(current_asmdata.CurrAsmList,location.size);
+ cg.a_load_const_reg(current_asmdata.CurrAsmList,location.size,mask,tmpreg);
+ location_force_reg(current_asmdata.CurrAsmList,right.location,location.size,true);
+ register_maybe_adjust_setbase(current_asmdata.CurrAsmList,right.location,setbase);
+ cg.a_op_reg_reg(current_asmdata.CurrAsmList,cgop,location.size,
+ right.location.register,tmpreg);
+ if left.location.loc <> LOC_CONSTANT then
+ cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,OP_OR,location.size,tmpreg,
+ left.location.register,location.register)
+ else
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_OR,location.size,
+ left.location.value,tmpreg,location.register);
+ end;
+ end;
+
+
+{*****************************************************************************
+ Boolean
+*****************************************************************************}
+
+ procedure tcgaddnode.second_opboolean;
+ begin
+ if nodetype in [ltn,lten,gtn,gten,equaln,unequaln] then
+ second_cmpboolean
+ else
+ second_addboolean;
+ end;
+
+
+ procedure tcgaddnode.second_addboolean;
+ var
+ cgop : TOpCg;
+ otl,ofl : tasmlabel;
+ oldflowcontrol : tflowcontrol;
+ begin
+ { And,Or will only evaluate from left to right only the
+ needed nodes unless full boolean evaluation is enabled }
+ if (nodetype in [orn,andn]) and
+ (not(cs_full_boolean_eval in current_settings.localswitches) or
+ (nf_short_bool in flags)) then
+ begin
+ location_reset(location,LOC_JUMP,OS_NO);
+ case nodetype of
+ andn :
+ begin
+ otl:=current_procinfo.CurrTrueLabel;
+ current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
+ secondpass(left);
+ maketojumpbool(current_asmdata.CurrAsmList,left,lr_load_regvars);
+ cg.a_label(current_asmdata.CurrAsmList,current_procinfo.CurrTrueLabel);
+ current_procinfo.CurrTrueLabel:=otl;
+ end;
+ orn :
+ begin
+ ofl:=current_procinfo.CurrFalseLabel;
+ current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel);
+ secondpass(left);
+ maketojumpbool(current_asmdata.CurrAsmList,left,lr_load_regvars);
+ cg.a_label(current_asmdata.CurrAsmList,current_procinfo.CurrFalseLabel);
+ current_procinfo.CurrFalseLabel:=ofl;
+ end;
+ else
+ internalerror(200307044);
+ end;
+ { these jumps mean we're now in a flow control construct }
+ oldflowcontrol:=flowcontrol;
+ include(flowcontrol,fc_inflowcontrol);
+
+ secondpass(right);
+ maketojumpbool(current_asmdata.CurrAsmList,right,lr_load_regvars);
+
+ flowcontrol:=oldflowcontrol+(flowcontrol-[fc_inflowcontrol]);
+ end
+ else
+ begin
+ pass_left_right;
+ force_reg_left_right(false,true);
+ set_result_location_reg;
+
+ case nodetype of
+ xorn :
+ cgop:=OP_XOR;
+ orn :
+ cgop:=OP_OR;
+ andn :
+ cgop:=OP_AND;
+ else
+ internalerror(200203247);
+ end;
+{$ifndef cpu64bitalu}
+ if right.location.size in [OS_64,OS_S64] then
+ begin
+ if right.location.loc <> LOC_CONSTANT then
+ cg64.a_op64_reg_reg_reg(current_asmdata.CurrAsmList,cgop,location.size,
+ left.location.register64,right.location.register64,
+ location.register64)
+ else
+ cg64.a_op64_const_reg_reg(current_asmdata.CurrAsmList,cgop,location.size,
+ right.location.value,left.location.register64,
+ location.register64);
+ end
+ else
+{$endif cpu64bitalu}
+ begin
+ if right.location.loc <> LOC_CONSTANT then
+ cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,cgop,location.size,
+ left.location.register,right.location.register,
+ location.register)
+ else
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,cgop,location.size,
+ right.location.value,left.location.register,
+ location.register);
+ end;
+ end;
+ end;
+
+
+{*****************************************************************************
+ 64-bit
+*****************************************************************************}
+
+ procedure tcgaddnode.second_op64bit;
+ begin
+ if nodetype in [ltn,lten,gtn,gten,equaln,unequaln] then
+ second_cmp64bit
+ else
+ second_add64bit;
+ end;
+
+
+ procedure tcgaddnode.second_add64bit;
+ var
+ op : TOpCG;
+ checkoverflow : boolean;
+ ovloc : tlocation;
+ begin
+ ovloc.loc:=LOC_VOID;
+
+ pass_left_right;
+ force_reg_left_right(false,true);
+ set_result_location_reg;
+
+ { assume no overflow checking is required }
+ checkoverflow := false;
+ case nodetype of
+ addn :
+ begin
+ op:=OP_ADD;
+ checkoverflow:=true;
+ end;
+ subn :
+ begin
+ op:=OP_SUB;
+ checkoverflow:=true;
+ end;
+ xorn:
+ op:=OP_XOR;
+ orn:
+ op:=OP_OR;
+ andn:
+ op:=OP_AND;
+ muln:
+ begin
+ { should be handled in pass_1 (JM) }
+ internalerror(200109051);
+ end;
+ else
+ internalerror(2002072705);
+ end;
+
+ checkoverflow:=
+ checkoverflow and
+ (left.resultdef.typ<>pointerdef) and
+ (right.resultdef.typ<>pointerdef);
+
+{$ifdef cpu64bitalu}
+ case nodetype of
+ xorn,orn,andn,addn:
+ begin
+ if (right.location.loc = LOC_CONSTANT) then
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,op,location.size,right.location.value,
+ left.location.register,location.register)
+ else
+ cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,op,location.size,right.location.register,
+ left.location.register,location.register);
+ end;
+ subn:
+ begin
+ if (nf_swapped in flags) then
+ swapleftright;
+
+ if left.location.loc <> LOC_CONSTANT then
+ begin
+ if right.location.loc <> LOC_CONSTANT then
+ // reg64 - reg64
+ cg.a_op_reg_reg_reg_checkoverflow(current_asmdata.CurrAsmList,OP_SUB,location.size,
+ right.location.register,left.location.register,location.register,
+ checkoverflow and (cs_check_overflow in current_settings.localswitches),ovloc)
+ else
+ // reg64 - const64
+ cg.a_op_const_reg_reg_checkoverflow(current_asmdata.CurrAsmList,OP_SUB,location.size,
+ right.location.value,left.location.register,location.register,
+ checkoverflow and (cs_check_overflow in current_settings.localswitches),ovloc);
+ end
+ else
+ begin
+ // const64 - reg64
+ location_force_reg(current_asmdata.CurrAsmList,left.location,left.location.size,true);
+ cg.a_op_reg_reg_reg_checkoverflow(current_asmdata.CurrAsmList,OP_SUB,location.size,
+ right.location.register,left.location.register,location.register,
+ checkoverflow and (cs_check_overflow in current_settings.localswitches),ovloc);
+ end;
+ end;
+ else
+ internalerror(2002072803);
+ end;
+{$else cpu64bitalu}
+ case nodetype of
+ xorn,orn,andn,addn:
+ begin
+ if (right.location.loc = LOC_CONSTANT) then
+ cg64.a_op64_const_reg_reg_checkoverflow(current_asmdata.CurrAsmList,op,location.size,right.location.value64,
+ left.location.register64,location.register64,
+ checkoverflow and (cs_check_overflow in current_settings.localswitches),ovloc)
+ else
+ cg64.a_op64_reg_reg_reg_checkoverflow(current_asmdata.CurrAsmList,op,location.size,right.location.register64,
+ left.location.register64,location.register64,
+ checkoverflow and (cs_check_overflow in current_settings.localswitches),ovloc);
+ end;
+ subn:
+ begin
+ if (nf_swapped in flags) then
+ swapleftright;
+
+ if left.location.loc <> LOC_CONSTANT then
+ begin
+ if right.location.loc <> LOC_CONSTANT then
+ // reg64 - reg64
+ cg64.a_op64_reg_reg_reg_checkoverflow(current_asmdata.CurrAsmList,OP_SUB,location.size,
+ right.location.register64,left.location.register64,
+ location.register64,
+ checkoverflow and (cs_check_overflow in current_settings.localswitches),ovloc)
+ else
+ // reg64 - const64
+ cg64.a_op64_const_reg_reg_checkoverflow(current_asmdata.CurrAsmList,OP_SUB,location.size,
+ right.location.value64,left.location.register64,
+ location.register64,
+ checkoverflow and (cs_check_overflow in current_settings.localswitches),ovloc)
+ end
+ else
+ begin
+ // const64 - reg64
+ location_force_reg(current_asmdata.CurrAsmList,left.location,left.location.size,true);
+ cg64.a_op64_reg_reg_reg_checkoverflow(current_asmdata.CurrAsmList,OP_SUB,location.size,
+ right.location.register64,left.location.register64,
+ location.register64,
+ checkoverflow and (cs_check_overflow in current_settings.localswitches),ovloc);
+ end;
+ end;
+ else
+ internalerror(2002072803);
+ end;
+{$endif cpu64bitalu}
+
+ { emit overflow check if enabled }
+ if checkoverflow then
+ cg.g_overflowcheck_loc(current_asmdata.CurrAsmList,Location,resultdef,ovloc);
+ end;
+
+
+{*****************************************************************************
+ Strings
+*****************************************************************************}
+
+ procedure tcgaddnode.second_addstring;
+ begin
+ { this should already be handled in pass1 }
+ internalerror(2002072402);
+ end;
+
+
+{*****************************************************************************
+ Floats
+*****************************************************************************}
+
+ procedure tcgaddnode.second_opfloat;
+ begin
+ if nodetype in [ltn,lten,gtn,gten,equaln,unequaln] then
+ second_cmpfloat
+ else
+ second_addfloat;
+ end;
+
+
+{*****************************************************************************
+ Ordinals
+*****************************************************************************}
+
+ procedure tcgaddnode.second_opordinal;
+ begin
+ if (nodetype in [ltn,lten,gtn,gten,equaln,unequaln]) then
+ second_cmpordinal
+ else
+ second_addordinal;
+ end;
+
+
+ procedure tcgaddnode.second_addordinal;
+ var
+ unsigned,
+ checkoverflow : boolean;
+ cgop : topcg;
+ tmpreg : tregister;
+ ovloc : tlocation;
+ begin
+ ovloc.loc:=LOC_VOID;
+
+ pass_left_right;
+ force_reg_left_right(false,true);
+ set_result_location_reg;
+
+ { determine if the comparison will be unsigned }
+ unsigned:=not(is_signed(left.resultdef)) or
+ not(is_signed(right.resultdef));
+
+ { assume no overflow checking is require }
+ checkoverflow := false;
+
+ case nodetype of
+ addn:
+ begin
+ cgop:=OP_ADD;
+ checkoverflow:=true;
+ end;
+ xorn :
+ begin
+ cgop:=OP_XOR;
+ end;
+ orn :
+ begin
+ cgop:=OP_OR;
+ end;
+ andn:
+ begin
+ cgop:=OP_AND;
+ end;
+ muln:
+ begin
+ checkoverflow:=true;
+ if unsigned then
+ cgop:=OP_MUL
+ else
+ cgop:=OP_IMUL;
+ end;
+ subn :
+ begin
+ checkoverflow:=true;
+ cgop:=OP_SUB;
+ end;
+ end;
+
+ checkoverflow:=
+ checkoverflow and
+ (left.resultdef.typ<>pointerdef) and
+ (right.resultdef.typ<>pointerdef);
+
+ if nodetype<>subn then
+ begin
+ if (right.location.loc<>LOC_CONSTANT) then
+ cg.a_op_reg_reg_reg_checkoverflow(current_asmdata.CurrAsmList,cgop,location.size,
+ left.location.register,right.location.register,
+ location.register,checkoverflow and (cs_check_overflow in current_settings.localswitches),ovloc)
+ else
+ cg.a_op_const_reg_reg_checkoverflow(current_asmdata.CurrAsmList,cgop,location.size,
+ right.location.value,left.location.register,
+ location.register,checkoverflow and (cs_check_overflow in current_settings.localswitches),ovloc);
+ end
+ else { subtract is a special case since its not commutative }
+ begin
+ if (nf_swapped in flags) then
+ swapleftright;
+ if left.location.loc<>LOC_CONSTANT then
+ begin
+ if right.location.loc<>LOC_CONSTANT then
+ cg.a_op_reg_reg_reg_checkoverflow(current_asmdata.CurrAsmList,OP_SUB,location.size,
+ right.location.register,left.location.register,
+ location.register,checkoverflow and (cs_check_overflow in current_settings.localswitches),ovloc)
+ else
+ cg.a_op_const_reg_reg_checkoverflow(current_asmdata.CurrAsmList,OP_SUB,location.size,
+ right.location.value,left.location.register,
+ location.register,checkoverflow and (cs_check_overflow in current_settings.localswitches),ovloc);
+ end
+ else
+ begin
+ tmpreg:=cg.getintregister(current_asmdata.CurrAsmList,location.size);
+ cg.a_load_const_reg(current_asmdata.CurrAsmList,location.size,
+ left.location.value,tmpreg);
+ cg.a_op_reg_reg_reg_checkoverflow(current_asmdata.CurrAsmList,OP_SUB,location.size,
+ right.location.register,tmpreg,location.register,checkoverflow and (cs_check_overflow in current_settings.localswitches),ovloc);
+ end;
+ end;
+
+ { emit overflow check if required }
+ if checkoverflow then
+ cg.g_overflowcheck_loc(current_asmdata.CurrAsmList,Location,resultdef,ovloc);
+ end;
+
+
+ procedure tcgaddnode.second_cmpboolean;
+ begin
+ second_cmpordinal;
+ end;
+
+
+{*****************************************************************************
+ pass_generate_code;
+*****************************************************************************}
+
+ procedure tcgaddnode.pass_generate_code;
+ begin
+ case left.resultdef.typ of
+ orddef :
+ begin
+ { handling boolean expressions }
+ if is_boolean(left.resultdef) and
+ is_boolean(right.resultdef) then
+ second_opboolean
+ { 64bit operations }
+ else if is_64bit(left.resultdef) then
+ second_op64bit
+ else
+ second_opordinal;
+ end;
+ stringdef :
+ begin
+ second_addstring;
+ end;
+ setdef :
+ begin
+ if is_smallset(tsetdef(left.resultdef)) then
+ second_opsmallset
+ else
+ internalerror(200109041);
+ end;
+ arraydef :
+ begin
+ { support dynarr=nil }
+ if is_dynamic_array(left.resultdef) then
+ second_opordinal
+ else
+ if (cs_support_vectors in current_settings.globalswitches) and
+ is_vector(left.resultdef) then
+ second_opvector
+{$ifdef SUPPORT_MMX}
+ else
+ if is_mmx_able_array(left.resultdef) then
+ second_opmmx
+{$endif SUPPORT_MMX}
+ else
+ internalerror(200306016);
+ end;
+ floatdef :
+ second_opfloat;
+ else
+ second_opordinal;
+ end;
+ end;
+
+begin
+ caddnode:=tcgaddnode;
+end.
diff --git a/closures/compiler/ncgbas.pas b/closures/compiler/ncgbas.pas
new file mode 100644
index 0000000000..a8625aa749
--- /dev/null
+++ b/closures/compiler/ncgbas.pas
@@ -0,0 +1,558 @@
+{
+ Copyright (c) 2000-2002 by Florian Klaempfl
+
+ This unit implements some basic nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit ncgbas;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cpubase,cgutils,
+ node,nbas;
+
+ type
+ tcgnothingnode = class(tnothingnode)
+ procedure pass_generate_code;override;
+ end;
+
+ tcgasmnode = class(tasmnode)
+ procedure pass_generate_code;override;
+ end;
+
+ tcgstatementnode = class(tstatementnode)
+ procedure pass_generate_code;override;
+ end;
+
+ tcgblocknode = class(tblocknode)
+ procedure pass_generate_code;override;
+ end;
+
+ tcgtempcreatenode = class(ttempcreatenode)
+ procedure pass_generate_code;override;
+ end;
+
+ tcgtemprefnode = class(ttemprefnode)
+ procedure pass_generate_code;override;
+ { Changes the location of this temp to ref. Useful when assigning }
+ { another temp to this one. The current location will be freed. }
+ { Can only be called in pass 2 (since earlier, the temp location }
+ { isn't known yet) }
+ procedure changelocation(const ref: treference);
+ end;
+
+ tcgtempdeletenode = class(ttempdeletenode)
+ procedure pass_generate_code;override;
+ end;
+
+ implementation
+
+ uses
+ globtype,globals,systems,
+ cutils,verbose,
+ aasmbase,aasmtai,aasmdata,aasmcpu,
+ symsym,symconst,symdef,defutil,
+ nflw,pass_2,ncgutil,
+ cgbase,cgobj,
+ procinfo,
+ tgobj
+ ;
+
+{*****************************************************************************
+ TNOTHING
+*****************************************************************************}
+
+ procedure tcgnothingnode.pass_generate_code;
+ begin
+ location_reset(location,LOC_VOID,OS_NO);
+
+ { avoid an abstract rte }
+ end;
+
+
+{*****************************************************************************
+ TSTATEMENTNODE
+*****************************************************************************}
+
+ procedure tcgstatementnode.pass_generate_code;
+ var
+ hp : tstatementnode;
+ begin
+ location_reset(location,LOC_VOID,OS_NO);
+
+ hp:=self;
+ while assigned(hp) do
+ begin
+ if assigned(hp.left) then
+ begin
+ secondpass(hp.left);
+ { Compiler inserted blocks can return values }
+ location_copy(hp.location,hp.left.location);
+ end;
+ hp:=tstatementnode(hp.right);
+ end;
+ end;
+
+
+{*****************************************************************************
+ TASMNODE
+*****************************************************************************}
+
+ procedure tcgasmnode.pass_generate_code;
+
+ procedure ReLabel(var p:tasmsymbol);
+ begin
+ { Only relabel local tasmlabels }
+ if (p.bind = AB_LOCAL) and
+ (p is tasmlabel) then
+ begin
+ if not assigned(p.altsymbol) then
+ current_asmdata.GenerateAltSymbol(p);
+ p:=p.altsymbol;
+ p.increfs;
+ end;
+ end;
+
+ procedure ResolveRef(var op:toper);
+ var
+ sym : tabstractnormalvarsym;
+{$ifdef x86}
+ scale : byte;
+{$endif x86}
+ forceref,
+ getoffset : boolean;
+ indexreg : tregister;
+ sofs : longint;
+ begin
+ if (op.typ=top_local) then
+ begin
+ sofs:=op.localoper^.localsymofs;
+ indexreg:=op.localoper^.localindexreg;
+{$ifdef x86}
+ scale:=op.localoper^.localscale;
+{$endif x86}
+ getoffset:=op.localoper^.localgetoffset;
+ forceref:=op.localoper^.localforceref;
+ sym:=tabstractnormalvarsym(pointer(op.localoper^.localsym));
+ dispose(op.localoper);
+ case sym.localloc.loc of
+ LOC_REFERENCE :
+ begin
+ if getoffset then
+ begin
+ if indexreg=NR_NO then
+ begin
+ op.typ:=top_const;
+ op.val:=sym.localloc.reference.offset+sofs;
+ end
+ else
+ begin
+ op.typ:=top_ref;
+ new(op.ref);
+ reference_reset_base(op.ref^,indexreg,sym.localloc.reference.offset+sofs,
+ newalignment(sym.localloc.reference.alignment,sofs));
+ end;
+ end
+ else
+ begin
+ op.typ:=top_ref;
+ new(op.ref);
+ reference_reset_base(op.ref^,sym.localloc.reference.base,sym.localloc.reference.offset+sofs,
+ newalignment(sym.localloc.reference.alignment,sofs));
+ op.ref^.index:=indexreg;
+{$ifdef x86}
+ op.ref^.scalefactor:=scale;
+{$endif x86}
+ end;
+ end;
+ LOC_REGISTER :
+ begin
+ if getoffset then
+ Message(asmr_e_invalid_reference_syntax);
+ { Subscribed access }
+ if forceref or
+ (sofs<>0) then
+ begin
+ op.typ:=top_ref;
+ new(op.ref);
+ { no idea about the actual alignment }
+ reference_reset_base(op.ref^,sym.localloc.register,sofs,1);
+ op.ref^.index:=indexreg;
+{$ifdef x86}
+ op.ref^.scalefactor:=scale;
+{$endif x86}
+ end
+ else
+ begin
+ op.typ:=top_reg;
+ op.reg:=sym.localloc.register;
+ end;
+ end;
+ LOC_MMREGISTER :
+ begin
+ if getoffset then
+ Message(asmr_e_invalid_reference_syntax);
+ { Subscribed access }
+ if forceref or (sofs<>0) then
+ internalerror(201001032)
+ else
+ begin
+ op.typ:=top_reg;
+ op.reg:=sym.localloc.register;
+ end;
+ end;
+ else
+ internalerror(201001031);
+ end;
+ end;
+ end;
+
+ var
+ hp,hp2 : tai;
+ i : longint;
+ begin
+ location_reset(location,LOC_VOID,OS_NO);
+
+ if (nf_get_asm_position in flags) then
+ begin
+ { Add a marker, to be sure the list is not empty }
+ current_asmdata.CurrAsmList.concat(tai_marker.create(mark_Position));
+ currenttai:=tai(current_asmdata.CurrAsmList.last);
+ exit;
+ end;
+
+ { Allocate registers used in the assembler block }
+ cg.alloccpuregisters(current_asmdata.CurrAsmList,R_INTREGISTER,used_regs_int);
+
+ if (po_inline in current_procinfo.procdef.procoptions) then
+ begin
+ hp:=tai(p_asm.first);
+ while assigned(hp) do
+ begin
+ hp2:=tai(hp.getcopy);
+ case hp2.typ of
+ ait_label :
+ ReLabel(tasmsymbol(tai_label(hp2).labsym));
+ ait_const :
+ begin
+ if assigned(tai_const(hp2).sym) then
+ ReLabel(tai_const(hp2).sym);
+ if assigned(tai_const(hp2).endsym) then
+ ReLabel(tai_const(hp2).endsym);
+ end;
+ ait_instruction :
+ begin
+ { remove cached insentry, because the new code can
+ require another less optimized instruction }
+{$ifdef i386}
+{$ifndef NOAG386BIN}
+ taicpu(hp2).ResetPass1;
+{$endif}
+{$endif}
+ { fixup the references }
+ for i:=1 to taicpu(hp2).ops do
+ begin
+ ResolveRef(taicpu(hp2).oper[i-1]^);
+ with taicpu(hp2).oper[i-1]^ do
+ begin
+ case typ of
+ top_ref :
+ begin
+ if assigned(ref^.symbol) then
+ ReLabel(ref^.symbol);
+ if assigned(ref^.relsymbol) then
+ ReLabel(ref^.relsymbol);
+ end;
+ end;
+ end;
+ end;
+{$ifdef x86}
+ { can only be checked now that all local operands }
+ { have been resolved }
+ taicpu(hp2).CheckIfValid;
+{$endif x86}
+ end;
+ end;
+ current_asmdata.CurrAsmList.concat(hp2);
+ hp:=tai(hp.next);
+ end;
+ { restore used symbols }
+ current_asmdata.ResetAltSymbols;
+ end
+ else
+ begin
+ hp:=tai(p_asm.first);
+ while assigned(hp) do
+ begin
+ case hp.typ of
+ ait_instruction :
+ begin
+ { remove cached insentry, because the new code can
+ require another less optimized instruction }
+{$ifdef i386}
+{$ifndef NOAG386BIN}
+ taicpu(hp).ResetPass1;
+{$endif}
+{$endif}
+ { fixup the references }
+ for i:=1 to taicpu(hp).ops do
+ ResolveRef(taicpu(hp).oper[i-1]^);
+{$ifdef x86}
+ { can only be checked now that all local operands }
+ { have been resolved }
+ taicpu(hp).CheckIfValid;
+{$endif x86}
+ end;
+ end;
+ hp:=tai(hp.next);
+ end;
+ { insert the list }
+ current_asmdata.CurrAsmList.concatlist(p_asm);
+ end;
+
+ { Release register used in the assembler block }
+ cg.dealloccpuregisters(current_asmdata.CurrAsmList,R_INTREGISTER,used_regs_int);
+ end;
+
+
+{*****************************************************************************
+ TBLOCKNODE
+*****************************************************************************}
+
+ procedure tcgblocknode.pass_generate_code;
+ var
+ hp : tstatementnode;
+ oldexitlabel : tasmlabel;
+ oldflowcontrol : tflowcontrol;
+ begin
+ location_reset(location,LOC_VOID,OS_NO);
+
+ { replace exitlabel? }
+ if nf_block_with_exit in flags then
+ begin
+ oldexitlabel:=current_procinfo.CurrExitLabel;
+ current_asmdata.getjumplabel(current_procinfo.CurrExitLabel);
+ oldflowcontrol:=flowcontrol;
+ { the nested block will not span an exit statement of the parent }
+ exclude(flowcontrol,fc_exit);
+ end;
+
+ { do second pass on left node }
+ if assigned(left) then
+ begin
+ hp:=tstatementnode(left);
+ while assigned(hp) do
+ begin
+ if assigned(hp.left) then
+ begin
+ secondpass(hp.left);
+ location_copy(hp.location,hp.left.location);
+ end;
+ location_copy(location,hp.location);
+ hp:=tstatementnode(hp.right);
+ end;
+ end;
+
+ { write exitlabel }
+ if nf_block_with_exit in flags then
+ begin
+ cg.a_label(current_asmdata.CurrAsmList,current_procinfo.CurrExitLabel);
+ current_procinfo.CurrExitLabel:=oldexitlabel;
+ { the exit statements inside this block are not exit statements }
+ { out of the parent }
+ flowcontrol:=oldflowcontrol+(flowcontrol - [fc_exit]);
+ end;
+ end;
+
+
+{*****************************************************************************
+ TTEMPCREATENODE
+*****************************************************************************}
+
+ procedure tcgtempcreatenode.pass_generate_code;
+ begin
+ location_reset(location,LOC_VOID,OS_NO);
+
+ { if we're secondpassing the same tcgtempcreatenode twice, we have a bug }
+ if (ti_valid in tempinfo^.flags) then
+ internalerror(200108222);
+
+ { get a (persistent) temp }
+ if is_managed_type(tempinfo^.typedef) then
+ begin
+ location_reset_ref(tempinfo^.location,LOC_REFERENCE,def_cgsize(tempinfo^.typedef),0);
+ tg.GetTempTyped(current_asmdata.CurrAsmList,tempinfo^.typedef,tempinfo^.temptype,tempinfo^.location.reference);
+ { the temp could have been used previously either because the memory location was reused or
+ because we're in a loop }
+ cg.g_finalize(current_asmdata.CurrAsmList,tempinfo^.typedef,tempinfo^.location.reference);
+ end
+ else if (ti_may_be_in_reg in tempinfo^.flags) then
+ begin
+ location_allocate_register(current_asmdata.CurrAsmList,tempinfo^.location,tempinfo^.typedef,tempinfo^.temptype = tt_persistent);
+ end
+ else
+ begin
+ location_reset_ref(tempinfo^.location,LOC_REFERENCE,def_cgsize(tempinfo^.typedef),0);
+ tg.GetTemp(current_asmdata.CurrAsmList,size,tempinfo^.typedef.alignment,tempinfo^.temptype,tempinfo^.location.reference);
+ end;
+ include(tempinfo^.flags,ti_valid);
+ if assigned(tempinfo^.tempinitcode) then
+ include(tempinfo^.flags,ti_executeinitialisation);
+ end;
+
+
+{*****************************************************************************
+ TTEMPREFNODE
+*****************************************************************************}
+
+ procedure tcgtemprefnode.pass_generate_code;
+ begin
+ if ti_executeinitialisation in tempinfo^.flags then
+ begin
+ { avoid recursion }
+ exclude(tempinfo^.flags, ti_executeinitialisation);
+ secondpass(tempinfo^.tempinitcode);
+ end;
+ { check if the temp is valid }
+ if not(ti_valid in tempinfo^.flags) then
+ internalerror(200108231);
+ location:=tempinfo^.location;
+ case tempinfo^.location.loc of
+ LOC_REFERENCE:
+ begin
+ inc(location.reference.offset,offset);
+ location.reference.alignment:=newalignment(location.reference.alignment,offset);
+ { ti_valid should be excluded if it's a normal temp }
+ end;
+ LOC_REGISTER,
+ LOC_FPUREGISTER,
+ LOC_MMREGISTER :
+ exclude(tempinfo^.flags,ti_valid);
+ end;
+ end;
+
+
+ procedure tcgtemprefnode.changelocation(const ref: treference);
+ begin
+ { check if the temp is valid }
+ if not(ti_valid in tempinfo^.flags) then
+ internalerror(200306081);
+ if (tempinfo^.location.loc<>LOC_REFERENCE) then
+ internalerror(2004020203);
+ if (tempinfo^.temptype = tt_persistent) then
+ tg.ChangeTempType(current_asmdata.CurrAsmList,tempinfo^.location.reference,tt_normal);
+ tg.ungettemp(current_asmdata.CurrAsmList,tempinfo^.location.reference);
+ tempinfo^.location.reference := ref;
+ tg.ChangeTempType(current_asmdata.CurrAsmList,tempinfo^.location.reference,tempinfo^.temptype);
+ { adapt location }
+ location.reference := ref;
+ inc(location.reference.offset,offset);
+ location.reference.alignment:=newalignment(location.reference.alignment,offset);
+ end;
+
+
+{*****************************************************************************
+ TTEMPDELETENODE
+*****************************************************************************}
+
+ procedure tcgtempdeletenode.pass_generate_code;
+ begin
+ location_reset(location,LOC_VOID,OS_NO);
+
+ case tempinfo^.location.loc of
+ LOC_REFERENCE:
+ begin
+ if release_to_normal then
+ tg.ChangeTempType(current_asmdata.CurrAsmList,tempinfo^.location.reference,tt_normal)
+ else
+ begin
+ tg.UnGetTemp(current_asmdata.CurrAsmList,tempinfo^.location.reference);
+ exclude(tempinfo^.flags,ti_valid);
+ end;
+ end;
+ LOC_CREGISTER,
+ LOC_REGISTER:
+ begin
+ if not(cs_opt_regvar in current_settings.optimizerswitches) or
+ (pi_has_label in current_procinfo.flags) then
+ begin
+ { make sure the register allocator doesn't reuse the }
+ { register e.g. in the middle of a loop }
+{$ifndef cpu64bitalu}
+ if tempinfo^.location.size in [OS_64,OS_S64] then
+ begin
+ cg.a_reg_sync(current_asmdata.CurrAsmList,tempinfo^.location.register64.reghi);
+ cg.a_reg_sync(current_asmdata.CurrAsmList,tempinfo^.location.register64.reglo);
+ end
+ else
+{$endif not cpu64bitalu}
+ cg.a_reg_sync(current_asmdata.CurrAsmList,tempinfo^.location.register);
+ end;
+ if release_to_normal then
+ tempinfo^.location.loc := LOC_REGISTER
+ else
+ exclude(tempinfo^.flags,ti_valid);
+ end;
+ LOC_CFPUREGISTER,
+ LOC_FPUREGISTER:
+ begin
+ if not(cs_opt_regvar in current_settings.optimizerswitches) or
+ (pi_has_label in current_procinfo.flags) then
+ begin
+ { make sure the register allocator doesn't reuse the }
+ { register e.g. in the middle of a loop }
+ cg.a_reg_sync(current_asmdata.CurrAsmList,tempinfo^.location.register);
+ end;
+ if release_to_normal then
+ tempinfo^.location.loc := LOC_FPUREGISTER
+ else
+ exclude(tempinfo^.flags,ti_valid);
+ end;
+ LOC_CMMREGISTER,
+ LOC_MMREGISTER:
+ begin
+ if not(cs_opt_regvar in current_settings.optimizerswitches) or
+ (pi_has_label in current_procinfo.flags) then
+ begin
+ { make sure the register allocator doesn't reuse the }
+ { register e.g. in the middle of a loop }
+ cg.a_reg_sync(current_asmdata.CurrAsmList,tempinfo^.location.register);
+ end;
+ if release_to_normal then
+ tempinfo^.location.loc := LOC_MMREGISTER
+ else
+ exclude(tempinfo^.flags,ti_valid);
+ end;
+ else
+ internalerror(200507161);
+ end;
+ end;
+
+
+begin
+ cnothingnode:=tcgnothingnode;
+ casmnode:=tcgasmnode;
+ cstatementnode:=tcgstatementnode;
+ cblocknode:=tcgblocknode;
+ ctempcreatenode:=tcgtempcreatenode;
+ ctemprefnode:=tcgtemprefnode;
+ ctempdeletenode:=tcgtempdeletenode;
+end.
diff --git a/closures/compiler/ncgcal.pas b/closures/compiler/ncgcal.pas
new file mode 100644
index 0000000000..46cf0fb1ea
--- /dev/null
+++ b/closures/compiler/ncgcal.pas
@@ -0,0 +1,976 @@
+ {
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate assembler for call nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit ncgcal;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cpubase,
+ globtype,
+ parabase,cgutils,
+ symdef,node,ncal;
+
+ type
+ tcgcallparanode = class(tcallparanode)
+ private
+ tempcgpara : tcgpara;
+ procedure push_addr_para;
+ procedure push_value_para;
+ public
+ constructor create(expr,next : tnode);override;
+ destructor destroy;override;
+ procedure secondcallparan;override;
+ end;
+
+ tcgcallnode = class(tcallnode)
+ private
+
+ procedure handle_return_value;
+ procedure release_unused_return_value;
+ procedure release_para_temps;
+ procedure pushparas;
+ procedure freeparas;
+ protected
+ retloc: tcgpara;
+
+ framepointer_paraloc : tcgpara;
+ {# This routine is used to push the current frame pointer
+ on the stack. This is used in nested routines where the
+ value of the frame pointer is always pushed as an extra
+ parameter.
+
+ The default handling is the standard handling used on
+ most stack based machines, where the frame pointer is
+ the first invisible parameter.
+ }
+ procedure pop_parasize(pop_size:longint);virtual;
+ procedure extra_interrupt_code;virtual;
+ procedure extra_call_code;virtual;
+ procedure extra_post_call_code;virtual;
+ procedure do_syscall;virtual;abstract;
+
+ { The function result is returned in a tcgpara. This tcgpara has to
+ be translated into a tlocation so the rest of the code generator
+ can work with it. This routine decides what the most appropriate
+ tlocation is and sets self.location based on that. }
+ procedure set_result_location(realresdef: tstoreddef);virtual;
+ public
+ procedure pass_generate_code;override;
+ destructor destroy;override;
+ end;
+
+
+implementation
+
+ uses
+ systems,
+ cutils,verbose,globals,
+ cpuinfo,
+ symconst,symtable,defutil,paramgr,
+ cgbase,pass_2,
+ aasmbase,aasmtai,aasmdata,
+ nbas,nmem,nld,ncnv,nutils,
+{$ifdef x86}
+ cga,cgx86,aasmcpu,
+{$endif x86}
+ ncgutil,
+ cgobj,tgobj,
+ procinfo,
+ wpobase;
+
+
+{*****************************************************************************
+ TCGCALLPARANODE
+*****************************************************************************}
+
+ constructor tcgcallparanode.create(expr,next : tnode);
+ begin
+ inherited create(expr,next);
+ tempcgpara.init;
+ end;
+
+
+ destructor tcgcallparanode.destroy;
+ begin
+ tempcgpara.done;
+ inherited destroy;
+ end;
+
+
+ procedure tcgcallparanode.push_addr_para;
+ begin
+ if not(left.location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) then
+ internalerror(200304235);
+ cg.a_loadaddr_ref_cgpara(current_asmdata.CurrAsmList,left.location.reference,tempcgpara);
+ end;
+
+
+ procedure tcgcallparanode.push_value_para;
+ begin
+ { we've nothing to push when the size of the parameter is 0 }
+ if left.resultdef.size=0 then
+ exit;
+
+ { Move flags and jump in register to make it less complex }
+ if left.location.loc in [LOC_FLAGS,LOC_JUMP,LOC_SUBSETREG,LOC_CSUBSETREG,LOC_SUBSETREF,LOC_CSUBSETREF] then
+ location_force_reg(current_asmdata.CurrAsmList,left.location,def_cgsize(left.resultdef),false);
+
+ { load the parameter's tlocation into its cgpara }
+ gen_load_loc_cgpara(current_asmdata.CurrAsmList,left.resultdef,left.location,tempcgpara)
+ end;
+
+
+ procedure tcgcallparanode.secondcallparan;
+ var
+ href : treference;
+ otlabel,
+ oflabel : tasmlabel;
+ begin
+ if not(assigned(parasym)) then
+ internalerror(200304242);
+
+ { Skip nothingn nodes which are used after disabling
+ a parameter }
+ if (left.nodetype<>nothingn) then
+ begin
+ otlabel:=current_procinfo.CurrTrueLabel;
+ oflabel:=current_procinfo.CurrFalseLabel;
+ current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
+ current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel);
+ secondpass(left);
+
+ maybechangeloadnodereg(current_asmdata.CurrAsmList,left,true);
+
+ { release memory for refcnt out parameters }
+ if (parasym.varspez=vs_out) and
+ is_managed_type(left.resultdef) then
+ begin
+ location_get_data_ref(current_asmdata.CurrAsmList,left.location,href,false,sizeof(pint));
+ if is_open_array(resultdef) then
+ begin
+ { if elementdef is not managed, omit fpc_decref_array
+ because it won't do anything anyway }
+ if is_managed_type(tarraydef(resultdef).elementdef) then
+ begin
+ if third=nil then
+ InternalError(201103063);
+ secondpass(third);
+ cg.g_array_rtti_helper(current_asmdata.CurrAsmList,tarraydef(resultdef).elementdef,
+ href,third.location,'FPC_FINALIZE_ARRAY');
+ end;
+ end
+ else
+ cg.g_finalize(current_asmdata.CurrAsmList,left.resultdef,href)
+ end;
+
+ paramanager.createtempparaloc(current_asmdata.CurrAsmList,aktcallnode.procdefinition.proccalloption,parasym,not followed_by_stack_tainting_call_cached,tempcgpara);
+
+ { handle varargs first, because parasym is not valid }
+ if (cpf_varargs_para in callparaflags) then
+ begin
+ if paramanager.push_addr_param(vs_value,left.resultdef,
+ aktcallnode.procdefinition.proccalloption) then
+ push_addr_para
+ else
+ push_value_para;
+ end
+ { hidden parameters }
+ else if (vo_is_hidden_para in parasym.varoptions) then
+ begin
+ { don't push a node that already generated a pointer type
+ by address for implicit hidden parameters }
+ if (vo_is_funcret in parasym.varoptions) or
+ { pass "this" in C++ classes explicitly as pointer
+ because push_addr_param might not be true for them }
+ (is_cppclass(parasym.vardef) and (vo_is_self in parasym.varoptions)) or
+ (not(left.resultdef.typ in [pointerdef,classrefdef]) and
+ paramanager.push_addr_param(parasym.varspez,parasym.vardef,
+ aktcallnode.procdefinition.proccalloption)) then
+ push_addr_para
+ else
+ push_value_para;
+ end
+ { formal def }
+ else if (parasym.vardef.typ=formaldef) then
+ begin
+ { allow passing of a constant to a const formaldef }
+ if (parasym.varspez=vs_const) and
+ (left.location.loc in [LOC_CONSTANT,LOC_REGISTER]) then
+ location_force_mem(current_asmdata.CurrAsmList,left.location);
+ push_addr_para;
+ end
+ { Normal parameter }
+ else
+ begin
+ { don't push a node that already generated a pointer type
+ by address for implicit hidden parameters }
+ if (not(
+ (vo_is_hidden_para in parasym.varoptions) and
+ (left.resultdef.typ in [pointerdef,classrefdef])
+ ) and
+ paramanager.push_addr_param(parasym.varspez,parasym.vardef,
+ aktcallnode.procdefinition.proccalloption)) and
+ { dyn. arrays passed to an array of const must be passed by value, see tests/webtbs/tw4219.pp }
+ not(
+ is_array_of_const(parasym.vardef) and
+ is_dynamic_array(left.resultdef)
+ ) then
+ begin
+ { Passing a var parameter to a var parameter, we can
+ just push the address transparently }
+ if (left.nodetype=loadn) and
+ (tloadnode(left).is_addr_param_load) then
+ begin
+ if (left.location.reference.index<>NR_NO) or
+ (left.location.reference.offset<>0) then
+ internalerror(200410107);
+ cg.a_load_reg_cgpara(current_asmdata.CurrAsmList,OS_ADDR,left.location.reference.base,tempcgpara)
+ end
+ else
+ begin
+ { Force to be in memory }
+ if not(left.location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) then
+ location_force_mem(current_asmdata.CurrAsmList,left.location);
+ push_addr_para;
+ end;
+ end
+ else
+ push_value_para;
+ end;
+ current_procinfo.CurrTrueLabel:=otlabel;
+ current_procinfo.CurrFalseLabel:=oflabel;
+
+ { update return location in callnode when this is the function
+ result }
+ if assigned(parasym) and
+ (vo_is_funcret in parasym.varoptions) then
+ location_copy(aktcallnode.location,left.location);
+ end;
+
+ { next parameter }
+ if assigned(right) then
+ tcallparanode(right).secondcallparan;
+ end;
+
+
+{*****************************************************************************
+ TCGCALLNODE
+*****************************************************************************}
+
+{$if first_mm_imreg = 0}
+ {$WARN 4044 OFF} { Comparison might be always false ... }
+{$endif}
+
+ procedure tcgcallnode.extra_interrupt_code;
+ begin
+ end;
+
+
+ procedure tcgcallnode.extra_call_code;
+ begin
+ end;
+
+
+ procedure tcgcallnode.extra_post_call_code;
+ begin
+ end;
+
+
+ procedure tcgcallnode.set_result_location(realresdef: tstoreddef);
+ begin
+ if realresdef.is_intregable or
+ realresdef.is_fpuregable or
+ { avoid temporarily storing pointer-sized entities that can't be
+ regvars, such as reference-counted pointers, to memory --
+ no exception can occur right now (except in case of existing
+ memory corruption), and we'd store them to a regular temp
+ anyway and that is not safer than keeping them in a register }
+ ((realresdef.size=sizeof(aint)) and
+ (retloc.location^.loc=LOC_REGISTER) and
+ not assigned(retloc.location^.next)) then
+ location_allocate_register(current_asmdata.CurrAsmList,location,realresdef,false)
+ else
+ begin
+ location_reset_ref(location,LOC_REFERENCE,def_cgsize(realresdef),0);
+ tg.GetTemp(current_asmdata.CurrAsmList,retloc.intsize,retloc.Alignment,tt_normal,location.reference);
+ end;
+ end;
+
+
+ procedure tcgcallnode.pop_parasize(pop_size:longint);
+ begin
+ end;
+
+
+ procedure tcgcallnode.handle_return_value;
+ var
+ realresdef: tstoreddef;
+ begin
+ { Check that the return location is set when the result is passed in
+ a parameter }
+ if (procdefinition.proctypeoption<>potype_constructor) and
+ paramanager.ret_in_param(resultdef,procdefinition.proccalloption) then
+ begin
+ { self.location is set near the end of secondcallparan so it
+ refers to the implicit result parameter }
+ if location.loc<>LOC_REFERENCE then
+ internalerror(200304241);
+ exit;
+ end;
+
+ if not assigned(typedef) then
+ realresdef:=tstoreddef(resultdef)
+ else
+ realresdef:=tstoreddef(typedef);
+
+{$ifdef x86}
+ if (retloc.location^.loc=LOC_FPUREGISTER) then
+ begin
+ tcgx86(cg).inc_fpu_stack;
+ location_reset(location,LOC_FPUREGISTER,retloc.location^.size);
+ location.register:=retloc.location^.register;
+ end
+ else
+{$endif x86}
+ begin
+ { get a tlocation that can hold the return value that's currently in
+ the the return value's tcgpara }
+ set_result_location(realresdef);
+
+ { Do not move the physical register to a virtual one in case
+ the return value is not used, because if the virtual one is
+ then mapped to the same register as the physical one, we will
+ end up with two deallocs of this register (one inserted here,
+ one inserted by the register allocator), which unbalances the
+ register allocation information. The return register(s) will
+ be freed by location_free() in release_unused_return_value
+ (mantis #13536). }
+ if (cnf_return_value_used in callnodeflags) or
+ assigned(funcretnode) then
+ begin
+ gen_load_cgpara_loc(current_asmdata.CurrAsmList,realresdef,retloc,location,false);
+{$ifdef arm}
+ if (resultdef.typ=floatdef) and
+ (location.loc=LOC_REGISTER) and
+ (current_settings.fputype in [fpu_fpa,fpu_fpa10,fpu_fpa11]) then
+ begin
+ location_force_mem(current_asmdata.CurrAsmList,location);
+ end;
+{$endif arm}
+ end;
+ end;
+
+ { copy value to the final location if this was already provided to the
+ callnode. This must be done after the call node, because the location can
+ also be used as parameter and may not be finalized yet }
+ if assigned(funcretnode) then
+ begin
+ funcretnode.pass_generate_code;
+ { Decrease refcount for refcounted types, this can be skipped when
+ we have used a temp, because then it is already done from tempcreatenode.
+ Also no finalize is needed, because there is no risk of exceptions from the
+ function since this is code is only executed after the function call has returned }
+ if is_managed_type(funcretnode.resultdef) and
+ (funcretnode.nodetype<>temprefn) then
+ cg.g_finalize(current_asmdata.CurrAsmList,funcretnode.resultdef,funcretnode.location.reference);
+
+ case location.loc of
+ LOC_REGISTER :
+ begin
+{$ifndef cpu64bitalu}
+ if location.size in [OS_64,OS_S64] then
+ cg64.a_load64_reg_loc(current_asmdata.CurrAsmList,location.register64,funcretnode.location)
+ else
+{$endif}
+ cg.a_load_reg_loc(current_asmdata.CurrAsmList,location.size,location.register,funcretnode.location);
+ location_free(current_asmdata.CurrAsmList,location);
+ end;
+ LOC_REFERENCE:
+ begin
+ case funcretnode.location.loc of
+ LOC_REGISTER:
+ cg.a_load_ref_reg(current_asmdata.CurrAsmList,location.size,location.size,location.reference,funcretnode.location.register);
+ LOC_REFERENCE:
+ cg.g_concatcopy(current_asmdata.CurrAsmList,location.reference,funcretnode.location.reference,resultdef.size);
+ else
+ internalerror(200802121);
+ end;
+ location_freetemp(current_asmdata.CurrAsmList,location);
+ end;
+ else
+ internalerror(200709085);
+ end;
+ location := funcretnode.location;
+ end;
+ end;
+
+
+ procedure tcgcallnode.release_unused_return_value;
+ begin
+ { When the result is not used we need to finalize the result and
+ can release the temp. This need to be after the callcleanupblock
+ tree is generated, because that converts the temp from persistent to normal }
+ if not(cnf_return_value_used in callnodeflags) then
+ begin
+ case location.loc of
+ LOC_REFERENCE :
+ begin
+ if is_managed_type(resultdef) then
+ cg.g_finalize(current_asmdata.CurrAsmList,resultdef,location.reference);
+ tg.ungetiftemp(current_asmdata.CurrAsmList,location.reference);
+ end;
+{$ifdef x86}
+ LOC_FPUREGISTER :
+ begin
+ { release FPU stack }
+ emit_reg(A_FSTP,S_NO,NR_FPU_RESULT_REG);
+ tcgx86(cg).dec_fpu_stack;
+ end;
+{$endif x86}
+ end;
+ if (retloc.intsize<>0) then
+ paramanager.freecgpara(current_asmdata.CurrAsmList,retloc);
+ location_reset(location,LOC_VOID,OS_NO);
+ end;
+ end;
+
+
+ procedure tcgcallnode.release_para_temps;
+ var
+ hp,
+ hp2 : tnode;
+ ppn : tcallparanode;
+ begin
+ { Release temps from parameters }
+ ppn:=tcallparanode(left);
+ while assigned(ppn) do
+ begin
+ if assigned(ppn.left) then
+ begin
+ { don't release the funcret temp }
+ if not(assigned(ppn.parasym)) or
+ not(vo_is_funcret in ppn.parasym.varoptions) then
+ location_freetemp(current_asmdata.CurrAsmList,ppn.left.location);
+ { process also all nodes of an array of const }
+ hp:=ppn.left;
+ while (hp.nodetype=typeconvn) do
+ hp:=ttypeconvnode(hp).left;
+ if (hp.nodetype=arrayconstructorn) and
+ assigned(tarrayconstructornode(hp).left) then
+ begin
+ while assigned(hp) do
+ begin
+ hp2:=tarrayconstructornode(hp).left;
+ { ignore typeconvs and addrn inserted by arrayconstructn for
+ passing a shortstring }
+ if (hp2.nodetype=typeconvn) and
+ (tunarynode(hp2).left.nodetype=addrn) then
+ hp2:=tunarynode(tunarynode(hp2).left).left;
+ location_freetemp(current_asmdata.CurrAsmList,hp2.location);
+ hp:=tarrayconstructornode(hp).right;
+ end;
+ end;
+ end;
+ ppn:=tcallparanode(ppn.right);
+ end;
+ end;
+
+
+ procedure tcgcallnode.pushparas;
+ var
+ ppn : tcgcallparanode;
+ callerparaloc,
+ tmpparaloc : pcgparalocation;
+ sizeleft: aint;
+ htempref,
+ href : treference;
+ calleralignment,
+ tmpalignment: longint;
+ skipiffinalloc: boolean;
+ begin
+ { copy all resources to the allocated registers }
+ ppn:=tcgcallparanode(left);
+ while assigned(ppn) do
+ begin
+ if (ppn.left.nodetype<>nothingn) then
+ begin
+ { better check for the real location of the parameter here, when stack passed parameters
+ are saved temporary in registers, checking for the tmpparaloc.loc is wrong
+ }
+ paramanager.freecgpara(current_asmdata.CurrAsmList,ppn.tempcgpara);
+ tmpparaloc:=ppn.tempcgpara.location;
+ sizeleft:=ppn.tempcgpara.intsize;
+ calleralignment:=ppn.parasym.paraloc[callerside].alignment;
+ tmpalignment:=ppn.tempcgpara.alignment;
+ if (tmpalignment=0) or
+ (calleralignment=0) then
+ internalerror(2009020701);
+ callerparaloc:=ppn.parasym.paraloc[callerside].location;
+ skipiffinalloc:=
+ not paramanager.use_fixed_stack or
+ not(ppn.followed_by_stack_tainting_call_cached);
+ while assigned(callerparaloc) do
+ begin
+ { Every paraloc must have a matching tmpparaloc }
+ if not assigned(tmpparaloc) then
+ internalerror(200408224);
+ if callerparaloc^.size<>tmpparaloc^.size then
+ internalerror(200408225);
+ case callerparaloc^.loc of
+ LOC_REGISTER:
+ begin
+ if tmpparaloc^.loc<>LOC_REGISTER then
+ internalerror(200408221);
+ if getsupreg(callerparaloc^.register)<first_int_imreg then
+ cg.getcpuregister(current_asmdata.CurrAsmList,callerparaloc^.register);
+ cg.a_load_reg_reg(current_asmdata.CurrAsmList,tmpparaloc^.size,tmpparaloc^.size,
+ tmpparaloc^.register,callerparaloc^.register);
+ end;
+ LOC_FPUREGISTER:
+ begin
+ if tmpparaloc^.loc<>LOC_FPUREGISTER then
+ internalerror(200408222);
+ if getsupreg(callerparaloc^.register)<first_fpu_imreg then
+ cg.getcpuregister(current_asmdata.CurrAsmList,callerparaloc^.register);
+ cg.a_loadfpu_reg_reg(current_asmdata.CurrAsmList,tmpparaloc^.size,ppn.tempcgpara.size,tmpparaloc^.register,callerparaloc^.register);
+ end;
+ LOC_MMREGISTER:
+ begin
+ if tmpparaloc^.loc<>LOC_MMREGISTER then
+ internalerror(200408223);
+ if getsupreg(callerparaloc^.register)<first_mm_imreg then
+ cg.getcpuregister(current_asmdata.CurrAsmList,callerparaloc^.register);
+ cg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,tmpparaloc^.size,tmpparaloc^.size,
+ tmpparaloc^.register,callerparaloc^.register,mms_movescalar);
+ end;
+ LOC_REFERENCE:
+ begin
+ if not(skipiffinalloc and
+ paramanager.is_stack_paraloc(callerparaloc)) then
+ begin
+ { Can't have a data copied to the stack, every location
+ must contain a valid size field }
+
+ if (tmpparaloc^.size=OS_NO) and
+ ((tmpparaloc^.loc<>LOC_REFERENCE) or
+ assigned(tmpparaloc^.next)) then
+ internalerror(200501281);
+ reference_reset_base(href,callerparaloc^.reference.index,callerparaloc^.reference.offset,calleralignment);
+ { copy parameters in case they were moved to a temp. location because we've a fixed stack }
+ case tmpparaloc^.loc of
+ LOC_REFERENCE:
+ begin
+ reference_reset_base(htempref,tmpparaloc^.reference.index,tmpparaloc^.reference.offset,tmpalignment);
+ { use concatcopy, because it can also be a float which fails when
+ load_ref_ref is used }
+ if (ppn.tempcgpara.size <> OS_NO) then
+ cg.g_concatcopy(current_asmdata.CurrAsmList,htempref,href,tcgsize2size[tmpparaloc^.size])
+ else
+ cg.g_concatcopy(current_asmdata.CurrAsmList,htempref,href,sizeleft)
+ end;
+ LOC_REGISTER:
+ cg.a_load_reg_ref(current_asmdata.CurrAsmList,tmpparaloc^.size,tmpparaloc^.size,tmpparaloc^.register,href);
+ LOC_FPUREGISTER:
+ cg.a_loadfpu_reg_ref(current_asmdata.CurrAsmList,tmpparaloc^.size,tmpparaloc^.size,tmpparaloc^.register,href);
+ LOC_MMREGISTER:
+ cg.a_loadmm_reg_ref(current_asmdata.CurrAsmList,tmpparaloc^.size,tmpparaloc^.size,tmpparaloc^.register,href,mms_movescalar);
+ else
+ internalerror(200402081);
+ end;
+ end;
+ end;
+ end;
+ dec(sizeleft,tcgsize2size[tmpparaloc^.size]);
+ callerparaloc:=callerparaloc^.next;
+ tmpparaloc:=tmpparaloc^.next;
+ end;
+ end;
+ ppn:=tcgcallparanode(ppn.right);
+ end;
+ end;
+
+
+ procedure tcgcallnode.freeparas;
+ var
+ ppn : tcgcallparanode;
+ begin
+ { free the resources allocated for the parameters }
+ ppn:=tcgcallparanode(left);
+ while assigned(ppn) do
+ begin
+ if (ppn.left.nodetype<>nothingn) then
+ begin
+ if (ppn.parasym.paraloc[callerside].location^.loc <> LOC_REFERENCE) then
+ paramanager.freecgpara(current_asmdata.CurrAsmList,ppn.parasym.paraloc[callerside]);
+ end;
+ ppn:=tcgcallparanode(ppn.right);
+ end;
+ end;
+
+
+
+ procedure tcgcallnode.pass_generate_code;
+ var
+ name_to_call: shortstring;
+ regs_to_save_int,
+ regs_to_save_fpu,
+ regs_to_save_mm : Tcpuregisterset;
+ href : treference;
+ pop_size : longint;
+ vmtoffset : aint;
+ pvreg,
+ vmtreg : tregister;
+ oldaktcallnode : tcallnode;
+ retlocitem: pcgparalocation;
+{$ifdef vtentry}
+ sym : tasmsymbol;
+{$endif vtentry}
+{$ifdef x86_64}
+ cgpara : tcgpara;
+{$endif x86_64}
+ begin
+ if not assigned(procdefinition) or
+ not(procdefinition.has_paraloc_info in [callerside,callbothsides]) then
+ internalerror(200305264);
+
+ if assigned(callinitblock) then
+ secondpass(tnode(callinitblock));
+
+ regs_to_save_int:=paramanager.get_volatile_registers_int(procdefinition.proccalloption);
+ regs_to_save_fpu:=paramanager.get_volatile_registers_fpu(procdefinition.proccalloption);
+ regs_to_save_mm:=paramanager.get_volatile_registers_mm(procdefinition.proccalloption);
+
+ { Include Function result registers }
+ if (not is_void(resultdef)) then
+ begin
+ { The forced returntype may have a different size than the one
+ declared for the procdef }
+ if not assigned(typedef) then
+ retloc:=procdefinition.funcretloc[callerside]
+ else
+ retloc:=paramanager.get_funcretloc(procdefinition,callerside,typedef);
+ retlocitem:=retloc.location;
+ while assigned(retlocitem) do
+ begin
+ case retlocitem^.loc of
+ LOC_REGISTER:
+ include(regs_to_save_int,getsupreg(retlocitem^.register));
+ LOC_FPUREGISTER:
+ include(regs_to_save_fpu,getsupreg(retlocitem^.register));
+ LOC_MMREGISTER:
+ include(regs_to_save_mm,getsupreg(retlocitem^.register));
+ LOC_REFERENCE,
+ LOC_VOID:
+ ;
+ else
+ internalerror(2004110213);
+ end;
+ retlocitem:=retlocitem^.next;
+ end;
+ end;
+
+ { Process parameters, register parameters will be loaded
+ in imaginary registers. The actual load to the correct
+ register is done just before the call }
+ oldaktcallnode:=aktcallnode;
+ aktcallnode:=self;
+ if assigned(left) then
+ tcallparanode(left).secondcallparan;
+ aktcallnode:=oldaktcallnode;
+
+ { procedure variable or normal function call ? }
+ if (right=nil) then
+ begin
+ { register call for WPO (must be done before wpo test below,
+ otherwise optimised called methods are no longer registered)
+ }
+ if (po_virtualmethod in procdefinition.procoptions) and
+ not is_objectpascal_helper(tprocdef(procdefinition).struct) and
+ assigned(methodpointer) and
+ (methodpointer.nodetype<>typen) and
+ (not assigned(current_procinfo) or
+ wpoinfomanager.symbol_live(current_procinfo.procdef.mangledname)) then
+ tobjectdef(tprocdef(procdefinition).struct).register_vmt_call(tprocdef(procdefinition).extnumber);
+{$ifdef vtentry}
+ if not is_interface(tprocdef(procdefinition)._class) then
+ begin
+ inc(current_asmdata.NextVTEntryNr);
+ current_asmdata.CurrAsmList.Concat(tai_symbol.CreateName('VTREF'+tostr(current_asmdata.NextVTEntryNr)+'_'+tprocdef(procdefinition).struct.vmt_mangledname+'$$'+tostr(vmtoffset div sizeof(pint)),AT_FUNCTION,0));
+ end;
+{$endif vtentry}
+
+ name_to_call:='';
+ if assigned(fobjcforcedprocname) then
+ name_to_call:=fobjcforcedprocname^;
+ { When methodpointer is typen we don't need (and can't) load
+ a pointer. We can directly call the correct procdef (PFV) }
+ if (name_to_call='') and
+ (po_virtualmethod in procdefinition.procoptions) and
+ not is_objectpascal_helper(tprocdef(procdefinition).struct) and
+ assigned(methodpointer) and
+ (methodpointer.nodetype<>typen) and
+ not wpoinfomanager.can_be_devirtualized(methodpointer.resultdef,procdefinition,name_to_call) then
+ begin
+ { virtual methods require an index }
+ if tprocdef(procdefinition).extnumber=$ffff then
+ internalerror(200304021);
+
+ secondpass(methodpointer);
+
+ { Load VMT from self }
+ if methodpointer.resultdef.typ=objectdef then
+ gen_load_vmt_register(current_asmdata.CurrAsmList,tobjectdef(methodpointer.resultdef),methodpointer.location,vmtreg)
+ else
+ begin
+ { Load VMT value in register }
+ location_force_reg(current_asmdata.CurrAsmList,methodpointer.location,OS_ADDR,false);
+ vmtreg:=methodpointer.location.register;
+ end;
+
+ { test validity of VMT }
+ if not(is_interface(tprocdef(procdefinition).struct)) and
+ not(is_cppclass(tprocdef(procdefinition).struct)) then
+ cg.g_maybe_testvmt(current_asmdata.CurrAsmList,vmtreg,tobjectdef(tprocdef(procdefinition).struct));
+
+ { Call through VMT, generate a VTREF symbol to notify the linker }
+ vmtoffset:=tobjectdef(tprocdef(procdefinition).struct).vmtmethodoffset(tprocdef(procdefinition).extnumber);
+ { register call for WPO }
+ if (not assigned(current_procinfo) or
+ wpoinfomanager.symbol_live(current_procinfo.procdef.mangledname)) then
+ tobjectdef(tprocdef(procdefinition).struct).register_vmt_call(tprocdef(procdefinition).extnumber);
+{$ifndef x86}
+ pvreg:=cg.getintregister(current_asmdata.CurrAsmList,OS_ADDR);
+{$endif not x86}
+ reference_reset_base(href,vmtreg,vmtoffset,sizeof(pint));
+{$ifndef x86}
+ cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,href,pvreg);
+{$endif not x86}
+
+ { Load parameters that are in temporary registers in the
+ correct parameter register }
+ if assigned(left) then
+ begin
+ pushparas;
+ { free the resources allocated for the parameters }
+ freeparas;
+ end;
+
+ cg.alloccpuregisters(current_asmdata.CurrAsmList,R_INTREGISTER,regs_to_save_int);
+ if cg.uses_registers(R_FPUREGISTER) then
+ cg.alloccpuregisters(current_asmdata.CurrAsmList,R_FPUREGISTER,regs_to_save_fpu);
+ if cg.uses_registers(R_MMREGISTER) then
+ cg.alloccpuregisters(current_asmdata.CurrAsmList,R_MMREGISTER,regs_to_save_mm);
+
+ { call method }
+ extra_call_code;
+{$ifdef x86}
+ cg.a_call_ref(current_asmdata.CurrAsmList,href);
+{$else x86}
+ cg.a_call_reg(current_asmdata.CurrAsmList,pvreg);
+{$endif x86}
+ extra_post_call_code;
+ end
+ else
+ begin
+ { Load parameters that are in temporary registers in the
+ correct parameter register }
+ if assigned(left) then
+ begin
+ pushparas;
+ { free the resources allocated for the parameters }
+ freeparas;
+ end;
+
+ cg.alloccpuregisters(current_asmdata.CurrAsmList,R_INTREGISTER,regs_to_save_int);
+ if cg.uses_registers(R_FPUREGISTER) then
+ cg.alloccpuregisters(current_asmdata.CurrAsmList,R_FPUREGISTER,regs_to_save_fpu);
+ if cg.uses_registers(R_MMREGISTER) then
+ cg.alloccpuregisters(current_asmdata.CurrAsmList,R_MMREGISTER,regs_to_save_mm);
+
+ if procdefinition.proccalloption=pocall_syscall then
+ do_syscall
+ else
+ begin
+ { Calling interrupt from the same code requires some
+ extra code }
+ if (po_interrupt in procdefinition.procoptions) then
+ extra_interrupt_code;
+ extra_call_code;
+ if (name_to_call='') then
+ cg.a_call_name(current_asmdata.CurrAsmList,tprocdef(procdefinition).mangledname,po_weakexternal in procdefinition.procoptions)
+ else
+ cg.a_call_name(current_asmdata.CurrAsmList,name_to_call,po_weakexternal in procdefinition.procoptions);
+ extra_post_call_code;
+ end;
+ end;
+ end
+ else
+ { now procedure variable case }
+ begin
+ secondpass(right);
+
+ pvreg:=cg.getintregister(current_asmdata.CurrAsmList,OS_ADDR);
+ { Only load OS_ADDR from the reference }
+ if right.location.loc in [LOC_REFERENCE,LOC_CREFERENCE] then
+ cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,right.location.reference,pvreg)
+ else
+ cg.a_load_loc_reg(current_asmdata.CurrAsmList,OS_ADDR,right.location,pvreg);
+ location_freetemp(current_asmdata.CurrAsmList,right.location);
+
+ { Load parameters that are in temporary registers in the
+ correct parameter register }
+ if assigned(left) then
+ begin
+ pushparas;
+ { free the resources allocated for the parameters }
+ freeparas;
+ end;
+
+ cg.alloccpuregisters(current_asmdata.CurrAsmList,R_INTREGISTER,regs_to_save_int);
+ if cg.uses_registers(R_FPUREGISTER) then
+ cg.alloccpuregisters(current_asmdata.CurrAsmList,R_FPUREGISTER,regs_to_save_fpu);
+ if cg.uses_registers(R_MMREGISTER) then
+ cg.alloccpuregisters(current_asmdata.CurrAsmList,R_MMREGISTER,regs_to_save_mm);
+
+ { Calling interrupt from the same code requires some
+ extra code }
+ if (po_interrupt in procdefinition.procoptions) then
+ extra_interrupt_code;
+ extra_call_code;
+ cg.a_call_reg(current_asmdata.CurrAsmList,pvreg);
+ extra_post_call_code;
+ end;
+
+ { Need to remove the parameters from the stack? }
+ if (procdefinition.proccalloption in clearstack_pocalls) then
+ begin
+ pop_size:=pushedparasize;
+ { for Cdecl functions we don't need to pop the funcret when it
+ was pushed by para. Except for safecall functions with
+ safecall-exceptions enabled. In that case the funcret is always
+ returned as a para which is considered a normal para on the
+ c-side, so the funcret has to be pop'ed normally. }
+ if not ((procdefinition.proccalloption=pocall_safecall) and
+ (tf_safecall_exceptions in target_info.flags)) and
+ paramanager.ret_in_param(procdefinition.returndef,procdefinition.proccalloption) then
+ dec(pop_size,sizeof(pint));
+ { Remove parameters/alignment from the stack }
+ pop_parasize(pop_size);
+ end
+ { frame pointer parameter is popped by the caller when it's passed the
+ Delphi way }
+ else if (po_delphi_nested_cc in procdefinition.procoptions) and
+ not paramanager.use_fixed_stack then
+ pop_parasize(sizeof(pint));
+ { Release registers, but not the registers that contain the
+ function result }
+ if (not is_void(resultdef)) then
+ begin
+ retlocitem:=retloc.location;
+ while assigned(retlocitem) do
+ begin
+ case retlocitem^.loc of
+ LOC_REGISTER:
+ exclude(regs_to_save_int,getsupreg(retlocitem^.register));
+ LOC_FPUREGISTER:
+ exclude(regs_to_save_fpu,getsupreg(retlocitem^.register));
+ LOC_MMREGISTER:
+ exclude(regs_to_save_mm,getsupreg(retlocitem^.register));
+ LOC_REFERENCE,
+ LOC_VOID:
+ ;
+ else
+ internalerror(2004110214);
+ end;
+ retlocitem:=retlocitem^.next;
+ end;
+ end;
+
+{$if defined(x86) or defined(arm)}
+ if (procdefinition.proccalloption=pocall_safecall) and
+ (tf_safecall_exceptions in target_info.flags) then
+ begin
+{$ifdef x86_64}
+ cgpara.init;
+ paramanager.getintparaloc(pocall_default,1,cgpara);
+ cg.a_load_reg_cgpara(current_asmdata.CurrAsmList,OS_ADDR,NR_RAX,cgpara);
+ cgpara.done;
+{$endif x86_64}
+ cg.allocallcpuregisters(current_asmdata.CurrAsmList);
+ cg.a_call_name(current_asmdata.CurrAsmList,'FPC_SAFECALLCHECK',false);
+ cg.deallocallcpuregisters(current_asmdata.CurrAsmList);
+ end;
+{$endif}
+
+ if cg.uses_registers(R_MMREGISTER) then
+ cg.dealloccpuregisters(current_asmdata.CurrAsmList,R_MMREGISTER,regs_to_save_mm);
+ if cg.uses_registers(R_FPUREGISTER) then
+ cg.dealloccpuregisters(current_asmdata.CurrAsmList,R_FPUREGISTER,regs_to_save_fpu);
+ cg.dealloccpuregisters(current_asmdata.CurrAsmList,R_INTREGISTER,regs_to_save_int);
+
+ { handle function results }
+ if (not is_void(resultdef)) then
+ handle_return_value
+ else
+ location_reset(location,LOC_VOID,OS_NO);
+
+ { convert persistent temps for parameters and function result to normal temps }
+ if assigned(callcleanupblock) then
+ secondpass(tnode(callcleanupblock));
+
+ { release temps and finalize unused return values, must be
+ after the callcleanupblock because that converts temps
+ from persistent to normal }
+ release_unused_return_value;
+
+ { release temps of paras }
+ release_para_temps;
+
+ { perhaps i/o check ? }
+ if (cs_check_io in current_settings.localswitches) and
+ (po_iocheck in procdefinition.procoptions) and
+ not(po_iocheck in current_procinfo.procdef.procoptions) and
+ { no IO check for methods and procedure variables }
+ (right=nil) and
+ not(po_virtualmethod in procdefinition.procoptions) then
+ begin
+ cg.allocallcpuregisters(current_asmdata.CurrAsmList);
+ cg.a_call_name(current_asmdata.CurrAsmList,'FPC_IOCHECK',false);
+ cg.deallocallcpuregisters(current_asmdata.CurrAsmList);
+ end;
+ end;
+
+
+ destructor tcgcallnode.destroy;
+ begin
+ if assigned(typedef) then
+ retloc.done;
+ inherited destroy;
+ end;
+
+
+begin
+ ccallparanode:=tcgcallparanode;
+ ccallnode:=tcgcallnode;
+end.
diff --git a/closures/compiler/ncgcnv.pas b/closures/compiler/ncgcnv.pas
new file mode 100644
index 0000000000..ad20c667a1
--- /dev/null
+++ b/closures/compiler/ncgcnv.pas
@@ -0,0 +1,760 @@
+{
+ Copyright (c) 2000-2002 by Florian Klaempfl
+
+ Generate assembler for nodes that handle type conversions which are
+ the same for all (most) processors
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit ncgcnv;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,ncnv,defutil,defcmp;
+
+ type
+
+ { tcgtypeconvnode }
+
+ tcgtypeconvnode = class(ttypeconvnode)
+ protected
+{$ifdef cpuflags}
+ { CPUs without flags need a specific implementation of int -> bool }
+ procedure second_int_to_bool;override;
+{$endif cpuflags}
+ procedure second_int_to_int;override;
+ procedure second_cstring_to_pchar;override;
+ procedure second_cstring_to_int;override;
+ procedure second_string_to_chararray;override;
+ procedure second_array_to_pointer;override;
+ procedure second_pointer_to_array;override;
+ procedure second_char_to_string;override;
+ procedure second_real_to_real;override;
+ procedure second_cord_to_pointer;override;
+ procedure second_proc_to_procvar;override;
+ procedure second_nil_to_methodprocvar;override;
+ procedure second_bool_to_int;override;
+ procedure second_bool_to_bool;override;
+ procedure second_ansistring_to_pchar;override;
+ procedure second_class_to_intf;override;
+ procedure second_char_to_char;override;
+ procedure second_nothing;override;
+ public
+ procedure pass_generate_code;override;
+ end;
+
+ tcgasnode = class(tasnode)
+ procedure pass_generate_code;override;
+ end;
+
+ implementation
+
+ uses
+ cutils,verbose,globtype,globals,
+ aasmbase,aasmtai,aasmdata,aasmcpu,symconst,symdef,paramgr,
+ nutils,ncon,ncal,
+ cpubase,systems,
+ procinfo,pass_2,
+ cgbase,
+ cgutils,cgobj,
+ ncgutil,
+ tgobj
+ ;
+
+
+ procedure tcgtypeconvnode.second_int_to_int;
+ var
+ orgsize,
+ newsize : tcgsize;
+ ressize,
+ leftsize : longint;
+ begin
+ newsize:=def_cgsize(resultdef);
+
+ { insert range check if not explicit conversion }
+ if not(nf_explicit in flags) then
+ cg.g_rangecheck(current_asmdata.CurrAsmList,left.location,left.resultdef,resultdef);
+
+ { is the result size smaller? when typecasting from void
+ we always reuse the current location, because there is
+ nothing that we can load in a register }
+ ressize := resultdef.size;
+ leftsize := left.resultdef.size;
+ if ((ressize<>leftsize) or
+ is_bitpacked_access(left)) and
+ not is_void(left.resultdef) then
+ begin
+ location_copy(location,left.location);
+ { reuse a loc_reference when the newsize is smaller than
+ than the original, else load it to a register }
+ if (location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) and
+ (ressize<leftsize) then
+ begin
+ location.size:=newsize;
+ if (target_info.endian = ENDIAN_BIG) then
+ begin
+ inc(location.reference.offset,leftsize-ressize);
+ location.reference.alignment:=newalignment(location.reference.alignment,leftsize-ressize);
+ end;
+ end
+ else
+ location_force_reg(current_asmdata.CurrAsmList,location,newsize,false);
+ end
+ else
+ begin
+ { no special loading is required, reuse current location }
+
+ { that's not true, if you go from signed to unsiged or }
+ { vice versa, you need sign extension/removal if the }
+ { value is already in a register (at least for archs }
+ { which don't have 8bit register components etc) (JM) }
+ location_copy(location,left.location);
+ location.size:=newsize;
+ orgsize := def_cgsize(left.resultdef);
+ if (ressize < sizeof(aint)) and
+ (location.loc in [LOC_REGISTER,LOC_CREGISTER]) and
+ (orgsize <> newsize) then
+ begin
+ location.register := cg.getintregister(current_asmdata.CurrAsmList,newsize);
+ location.loc := LOC_REGISTER;
+ cg.a_load_reg_reg(current_asmdata.CurrAsmList,orgsize,newsize,left.location.register,location.register);
+ end;
+ end;
+ end;
+
+
+{$ifdef cpuflags}
+ procedure tcgtypeconvnode.second_int_to_bool;
+ var
+ hregister : tregister;
+ href : treference;
+ resflags : tresflags;
+ hlabel,oldTrueLabel,oldFalseLabel : tasmlabel;
+ newsize : tcgsize;
+ begin
+ oldTrueLabel:=current_procinfo.CurrTrueLabel;
+ oldFalseLabel:=current_procinfo.CurrFalseLabel;
+ current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
+ current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel);
+ secondpass(left);
+ if codegenerror then
+ exit;
+
+ { Explicit typecasts from any ordinal type to a boolean type }
+ { must not change the ordinal value }
+ if (nf_explicit in flags) and
+ not(left.location.loc in [LOC_FLAGS,LOC_JUMP]) then
+ begin
+ location_copy(location,left.location);
+ newsize:=def_cgsize(resultdef);
+ { change of size? change sign only if location is LOC_(C)REGISTER? Then we have to sign/zero-extend }
+ if (tcgsize2size[newsize]<>tcgsize2size[left.location.size]) or
+ ((newsize<>left.location.size) and (location.loc in [LOC_REGISTER,LOC_CREGISTER])) then
+ location_force_reg(current_asmdata.CurrAsmList,location,newsize,true)
+ else
+ location.size:=newsize;
+ current_procinfo.CurrTrueLabel:=oldTrueLabel;
+ current_procinfo.CurrFalseLabel:=oldFalseLabel;
+ exit;
+ end;
+ { though ppc/ppc64 doesn't use the generic code, we need to ifdef here
+ because the code is included into the powerpc compilers }
+{$if defined(POWERPC) or defined(POWERPC64)}
+ resflags.cr := RS_CR0;
+ resflags.flag:=F_NE;
+{$else defined(POWERPC) or defined(POWERPC64)}
+ { Load left node into flag F_NE/F_E }
+ resflags:=F_NE;
+{$endif defined(POWERPC) or defined(POWERPC64)}
+ case left.location.loc of
+ LOC_CREFERENCE,
+ LOC_REFERENCE :
+ begin
+ if left.location.size in [OS_64,OS_S64] then
+ begin
+ hregister:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
+ cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_32,OS_32,left.location.reference,hregister);
+ href:=left.location.reference;
+ inc(href.offset,4);
+ cg.a_op_ref_reg(current_asmdata.CurrAsmList,OP_OR,OS_32,href,hregister);
+ end
+ else
+ begin
+ location_force_reg(current_asmdata.CurrAsmList,left.location,left.location.size,true);
+ cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_OR,left.location.size,left.location.register,left.location.register);
+ end;
+ end;
+ LOC_FLAGS :
+ begin
+ resflags:=left.location.resflags;
+ end;
+ LOC_REGISTER,LOC_CREGISTER :
+ begin
+{$ifndef cpu64bitalu}
+ if left.location.size in [OS_64,OS_S64] then
+ begin
+ hregister:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
+ cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_32,OS_32,left.location.register64.reglo,hregister);
+ cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_OR,OS_32,left.location.register64.reghi,hregister);
+ end
+ else
+{$endif cpu64bitalu}
+ begin
+ cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_OR,left.location.size,left.location.register,left.location.register);
+ end;
+ end;
+ LOC_JUMP :
+ begin
+ hregister:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+ current_asmdata.getjumplabel(hlabel);
+ cg.a_label(current_asmdata.CurrAsmList,current_procinfo.CurrTrueLabel);
+ cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_INT,1,hregister);
+ cg.a_jmp_always(current_asmdata.CurrAsmList,hlabel);
+ cg.a_label(current_asmdata.CurrAsmList,current_procinfo.CurrFalseLabel);
+ cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_INT,0,hregister);
+ cg.a_label(current_asmdata.CurrAsmList,hlabel);
+ cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_OR,OS_INT,hregister,hregister);
+ end;
+ else
+ internalerror(200311301);
+ end;
+ { load flags to register }
+ location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
+ location.register:=cg.getintregister(current_asmdata.CurrAsmList,location.size);
+ cg.g_flags2reg(current_asmdata.CurrAsmList,location.size,resflags,location.register);
+ if (is_cbool(resultdef)) then
+ cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_NEG,location.size,location.register,location.register);
+ current_procinfo.CurrTrueLabel:=oldTrueLabel;
+ current_procinfo.CurrFalseLabel:=oldFalseLabel;
+ end;
+{$endif cpuflags}
+
+
+ procedure tcgtypeconvnode.second_cstring_to_pchar;
+
+ var
+ hr : treference;
+
+ begin
+ if left.nodetype<>stringconstn then
+ internalerror(200601131);
+ location_reset(location,LOC_REGISTER,OS_ADDR);
+ case tstringconstnode(left).cst_type of
+ cst_conststring :
+ begin
+ location.register:=cg.getaddressregister(current_asmdata.CurrAsmList);
+ cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,left.location.reference,location.register);
+ end;
+ cst_shortstring :
+ begin
+ inc(left.location.reference.offset);
+ location.reference.alignment:=1;
+ location.register:=cg.getaddressregister(current_asmdata.CurrAsmList);
+ cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,left.location.reference,location.register);
+ end;
+ cst_widestring,
+ cst_unicodestring,
+ cst_ansistring :
+ begin
+ if tstringconstnode(left).len=0 then
+ begin
+ { FPC_EMPTYCHAR is a widechar -> 2 bytes }
+ reference_reset(hr,2);
+ hr.symbol:=current_asmdata.RefAsmSymbol('FPC_EMPTYCHAR');
+ location.register:=cg.getaddressregister(current_asmdata.CurrAsmList);
+ cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,hr,location.register);
+ end
+ else
+ begin
+ location_copy(location,left.location);
+ end;
+ end;
+ cst_longstring:
+ begin
+ {!!!!!!!}
+ internalerror(8888);
+ end;
+ else
+ internalerror(200808241);
+ end;
+ end;
+
+
+ procedure tcgtypeconvnode.second_cstring_to_int;
+ begin
+ { this can't happen because constants are already processed in
+ pass 1 }
+ internalerror(200510013);
+ end;
+
+
+ procedure tcgtypeconvnode.second_string_to_chararray;
+ begin
+ if is_chararray(left.resultdef) then
+ begin
+ location_copy(location,left.location);
+ exit;
+ end;
+ { should be handled already in resultdef pass (JM) }
+ internalerror(200108292);
+ end;
+
+
+ procedure tcgtypeconvnode.second_array_to_pointer;
+
+ begin
+ location_reset(location,LOC_REGISTER,OS_ADDR);
+ location.register:=cg.getaddressregister(current_asmdata.CurrAsmList);
+ cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,left.location.reference,location.register);
+ end;
+
+
+ procedure tcgtypeconvnode.second_pointer_to_array;
+
+ begin
+ { assume natural alignment }
+ location_reset_ref(location,LOC_REFERENCE,OS_NO,resultdef.alignment);
+ case left.location.loc of
+ LOC_CREGISTER,
+ LOC_REGISTER :
+ begin
+ {$ifdef cpu_uses_separate_address_registers}
+ if getregtype(left.location.register)<>R_ADDRESSREGISTER then
+ begin
+ location.reference.base:=rg.getaddressregister(current_asmdata.CurrAsmList);
+ cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,
+ left.location.register,location.reference.base);
+ end
+ else
+ {$endif}
+ location.reference.base := left.location.register;
+ end;
+ LOC_REFERENCE,
+ LOC_CREFERENCE :
+ begin
+ location.reference.base:=cg.getaddressregister(current_asmdata.CurrAsmList);
+ cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,left.location.reference,
+ location.reference.base);
+ location_freetemp(current_asmdata.CurrAsmList,left.location);
+ end;
+ else
+ internalerror(2002032216);
+ end;
+ end;
+
+
+ procedure tcgtypeconvnode.second_char_to_string;
+ begin
+ location_reset_ref(location,LOC_REFERENCE,OS_NO,2);
+ case tstringdef(resultdef).stringtype of
+ st_shortstring :
+ begin
+ tg.GetTemp(current_asmdata.CurrAsmList,256,2,tt_normal,location.reference);
+ cg.a_load_loc_ref(current_asmdata.CurrAsmList,left.location.size,left.location,
+ location.reference);
+ location_freetemp(current_asmdata.CurrAsmList,left.location);
+ end;
+ { the rest is removed in the resultdef pass and converted to compilerprocs }
+ else
+ internalerror(4179);
+ end;
+ end;
+
+
+ procedure tcgtypeconvnode.second_real_to_real;
+{$ifdef x86}
+ var
+ tr: treference;
+{$endif x86}
+ begin
+ location_reset(location,expectloc,def_cgsize(resultdef));
+{$ifdef x86}
+ { extended types in memory which should be loaded into the sse unit
+ must be converted by the fpu first, so force them to be loaded into
+ the fpu }
+ if (expectloc=LOC_MMREGISTER) and
+ (left.location.size in [OS_F80,OS_C64]) then
+ begin
+ if (left.location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) then
+ location_force_fpureg(current_asmdata.CurrAsmList,left.location,false);
+ { round them down to the proper precision }
+ tg.gettemp(current_asmdata.currasmlist,resultdef.size,resultdef.alignment,tt_normal,tr);
+ cg.a_loadfpu_reg_ref(current_asmdata.CurrAsmList,left.location.size,location.size,left.location.register,tr);
+ location_reset_ref(left.location,LOC_REFERENCE,location.size,tr.alignment);
+ left.location.reference:=tr;
+ end;
+{$endif x86}
+ { ARM VFP values are in integer registers when they are function results }
+ if (left.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
+ location_force_mmregscalar(current_asmdata.CurrAsmList,left.location,false);
+ case left.location.loc of
+ LOC_FPUREGISTER,
+ LOC_CFPUREGISTER:
+ begin
+ case expectloc of
+ LOC_FPUREGISTER:
+ begin
+ { on sparc a move from double -> single means from two to one register. }
+ { On all other platforms it also needs rounding to avoid that }
+ { single(double_regvar) = double_regvar is true in all cases }
+ location.register:=cg.getfpuregister(current_asmdata.CurrAsmList,location.size);
+ cg.a_loadfpu_reg_reg(current_asmdata.CurrAsmList,left.location.size,location.size,left.location.register,location.register);
+ end;
+ LOC_MMREGISTER:
+ begin
+ location_force_mmregscalar(current_asmdata.CurrAsmList,left.location,false);
+ location.register:=cg.getmmregister(current_asmdata.CurrAsmList,location.size);
+ cg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,left.location.size,location.size,left.location.register,location.register,mms_movescalar);
+ end
+ else
+ internalerror(2003012262);
+ end;
+ exit
+ end;
+ LOC_CREFERENCE,
+ LOC_REFERENCE:
+ begin
+ if expectloc=LOC_MMREGISTER then
+ begin
+ location.register:=cg.getmmregister(current_asmdata.CurrAsmList,location.size);
+ cg.a_loadmm_loc_reg(current_asmdata.CurrAsmList,location.size,left.location,location.register,mms_movescalar)
+ end
+ else
+ begin
+ location_force_fpureg(current_asmdata.CurrAsmList,left.location,false);
+ location.register:=cg.getfpuregister(current_asmdata.CurrAsmList,location.size);
+ cg.a_loadfpu_reg_reg(current_asmdata.CurrAsmList,left.location.size,location.size,left.location.register,location.register);
+ end;
+ location_freetemp(current_asmdata.CurrAsmList,left.location);
+ end;
+ LOC_MMREGISTER,
+ LOC_CMMREGISTER:
+ begin
+ case expectloc of
+ LOC_FPUREGISTER:
+ begin
+ location_force_fpureg(current_asmdata.CurrAsmList,left.location,false);
+ location.register:=cg.getfpuregister(current_asmdata.CurrAsmList,location.size);
+ cg.a_loadfpu_reg_reg(current_asmdata.CurrAsmList,left.location.size,location.size,left.location.register,location.register);
+ end;
+ LOC_MMREGISTER:
+ begin
+ location.register:=cg.getmmregister(current_asmdata.CurrAsmList,location.size);
+ cg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,left.location.size,location.size,left.location.register,location.register,mms_movescalar);
+ end;
+ else
+ internalerror(2003012261);
+ end;
+ end;
+ else
+ internalerror(2002032215);
+ end;
+ end;
+
+
+ procedure tcgtypeconvnode.second_cord_to_pointer;
+ begin
+ { this can't happen because constants are already processed in
+ pass 1 }
+ internalerror(47423985);
+ end;
+
+
+ procedure tcgtypeconvnode.second_proc_to_procvar;
+ var
+ tmpreg: tregister;
+ begin
+ if tabstractprocdef(resultdef).is_addressonly then
+ begin
+ location_reset(location,LOC_REGISTER,OS_ADDR);
+ location.register:=cg.getaddressregister(current_asmdata.CurrAsmList);
+ cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,left.location.reference,location.register);
+ end
+ else
+ begin
+ if not tabstractprocdef(left.resultdef).is_addressonly then
+ location_copy(location,left.location)
+ else
+ begin
+ { assigning a global function to a nested procvar -> create
+ tmethodpointer record and set the "frame pointer" to nil }
+ location_reset_ref(location,LOC_REFERENCE,int_cgsize(sizeof(pint)*2),sizeof(pint));
+ tg.gettemp(current_asmdata.CurrAsmList,resultdef.size,sizeof(pint),tt_normal,location.reference);
+ tmpreg:=cg.getaddressregister(current_asmdata.CurrAsmList);
+ cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,left.location.reference,tmpreg);
+ cg.a_load_reg_ref(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,tmpreg,location.reference);
+ { setting the frame pointer to nil is not strictly necessary
+ since the global procedure won't use it, but it can help with
+ debugging }
+ inc(location.reference.offset,sizeof(pint));
+ cg.a_load_const_ref(current_asmdata.CurrAsmList,OS_ADDR,0,location.reference);
+ dec(location.reference.offset,sizeof(pint));
+ end;
+ end;
+ end;
+
+ procedure Tcgtypeconvnode.second_nil_to_methodprocvar;
+
+ var r:Treference;
+
+ begin
+ tg.gettemp(current_asmdata.currasmlist,2*sizeof(puint),sizeof(puint),tt_normal,r);
+ location_reset_ref(location,LOC_REFERENCE,def_cgsize(resultdef),0);
+ location.reference:=r;
+ cg.a_load_const_ref(current_asmdata.currasmlist,OS_ADDR,0,r);
+ inc(r.offset,sizeof(puint));
+ cg.a_load_const_ref(current_asmdata.currasmlist,OS_ADDR,0,r);
+ end;
+
+ procedure tcgtypeconvnode.second_bool_to_int;
+ var
+ newsize: tcgsize;
+ oldTrueLabel,oldFalseLabel : tasmlabel;
+ begin
+ oldTrueLabel:=current_procinfo.CurrTrueLabel;
+ oldFalseLabel:=current_procinfo.CurrFalseLabel;
+ current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
+ current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel);
+ secondpass(left);
+ location_copy(location,left.location);
+ newsize:=def_cgsize(resultdef);
+ { byte(bytebool) or word(wordbool) or longint(longbool) must be }
+ { accepted for var parameters and assignments, and must not }
+ { change the ordinal value or value location. }
+ { htypechk.valid_for_assign ensures that such locations with a }
+ { size<sizeof(register) cannot be LOC_CREGISTER (they otherwise }
+ { could be in case of a plain assignment), and LOC_REGISTER can }
+ { never be an assignment target. The remaining LOC_REGISTER/ }
+ { LOC_CREGISTER locations do have to be sign/zero-extended. }
+ if not(nf_explicit in flags) or
+ (location.loc in [LOC_FLAGS,LOC_JUMP]) or
+ { change of size/signedness? Then we have to sign/ }
+ { zero-extend in case of a loc_(c)register }
+ ((newsize<>left.location.size) and
+ ((left.resultdef.size<>resultdef.size) or
+ not(location.loc in [LOC_REFERENCE,LOC_CREFERENCE]))) then
+ location_force_reg(current_asmdata.CurrAsmList,location,newsize,true)
+ else
+ { may differ in sign, e.g. bytebool -> byte }
+ location.size:=newsize;
+ current_procinfo.CurrTrueLabel:=oldTrueLabel;
+ current_procinfo.CurrFalseLabel:=oldFalseLabel;
+ end;
+
+
+ procedure tcgtypeconvnode.second_bool_to_bool;
+ begin
+ { we can reuse the conversion already available
+ in bool_to_int to resize the value. But when the
+ size of the new boolean is smaller we need to calculate
+ the value as is done in int_to_bool. This is needed because
+ the bits that define the true status can be outside the limits
+ of the new size and truncating the register can result in a 0
+ value }
+ if (left.expectloc in [LOC_FLAGS,LOC_JUMP]) and
+ { a cbool must be converted to -1/0 }
+ not is_cbool(resultdef) then
+ begin
+ secondpass(left);
+ if (left.location.loc <> left.expectloc) then
+ internalerror(2010081601);
+ location_copy(location,left.location);
+ end
+ else if (resultdef.size=left.resultdef.size) and
+ (is_cbool(resultdef)=is_cbool(left.resultdef)) then
+ second_bool_to_int
+ else
+ begin
+ if (resultdef.size<>left.resultdef.size) then
+ { remove nf_explicit to perform full conversion if boolean sizes are different }
+ exclude(flags, nf_explicit);
+ second_int_to_bool;
+ end;
+ end;
+
+
+ procedure tcgtypeconvnode.second_ansistring_to_pchar;
+ var
+ l1 : tasmlabel;
+ hr : treference;
+ begin
+ location_reset(location,LOC_REGISTER,OS_ADDR);
+ current_asmdata.getjumplabel(l1);
+ case left.location.loc of
+ LOC_CREGISTER,LOC_REGISTER:
+ begin
+ {$ifdef cpu_uses_separate_address_registers}
+ if getregtype(left.location.register)<>R_ADDRESSREGISTER then
+ begin
+ location.register:=cg.getaddressregister(current_asmdata.CurrAsmList);
+ cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,
+ left.location.register,location.register);
+ end
+ else
+ {$endif}
+ location.register := left.location.register;
+ end;
+ LOC_CREFERENCE,LOC_REFERENCE:
+ begin
+ location.register:=cg.getaddressregister(current_asmdata.CurrAsmList);
+ cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,left.location.reference,location.register);
+ end;
+ else
+ internalerror(2002032214);
+ end;
+ cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,OS_ADDR,OC_NE,0,location.register,l1);
+ { FPC_EMPTYCHAR is a widechar -> 2 bytes }
+ reference_reset(hr,2);
+ hr.symbol:=current_asmdata.RefAsmSymbol('FPC_EMPTYCHAR');
+ cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,hr,location.register);
+ cg.a_label(current_asmdata.CurrAsmList,l1);
+ end;
+
+
+ procedure tcgtypeconvnode.second_class_to_intf;
+ var
+ l1 : tasmlabel;
+ hd : tobjectdef;
+ ImplIntf : TImplementedInterface;
+ begin
+ location_reset(location,LOC_REGISTER,OS_ADDR);
+ case left.location.loc of
+ LOC_CREFERENCE,
+ LOC_REFERENCE:
+ begin
+ location.register:=cg.getaddressregister(current_asmdata.CurrAsmList);
+ cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,left.location.reference,location.register);
+ location_freetemp(current_asmdata.CurrAsmList,left.location);
+ end;
+ LOC_CREGISTER:
+ begin
+ location.register:=cg.getaddressregister(current_asmdata.CurrAsmList);
+ cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,left.location.register,location.register);
+ end;
+ LOC_REGISTER:
+ location.register:=left.location.register;
+ else
+ internalerror(121120001);
+ end;
+ hd:=tobjectdef(left.resultdef);
+ while assigned(hd) do
+ begin
+ ImplIntf:=hd.find_implemented_interface(tobjectdef(resultdef));
+ if assigned(ImplIntf) then
+ begin
+ case ImplIntf.IType of
+ etStandard:
+ begin
+ current_asmdata.getjumplabel(l1);
+ cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,OS_ADDR,OC_EQ,0,location.register,l1);
+ cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_ADD,OS_ADDR,ImplIntf.ioffset,location.register);
+ break;
+ end;
+ else
+ internalerror(200802163);
+ end;
+ end;
+ hd:=hd.childof;
+ end;
+ if hd=nil then
+ internalerror(2002081301);
+ cg.a_label(current_asmdata.CurrAsmList,l1);
+ end;
+
+
+ procedure tcgtypeconvnode.second_char_to_char;
+ begin
+ internalerror(2007081202);
+ end;
+
+
+ procedure tcgtypeconvnode.second_nothing;
+ var
+ newsize : tcgsize;
+ begin
+ { we reuse the old value }
+ location_copy(location,left.location);
+
+ { Floats should never be returned as LOC_CONSTANT, do the
+ moving to memory before the new size is set.
+ Also when converting from a float to a non-float
+ or the other way round, move to memory first to prevent
+ invalid LOC_FPUREGISTER locations }
+ if (
+ (resultdef.typ=floatdef) and
+ (location.loc=LOC_CONSTANT)
+ ) or
+ (
+ (left.resultdef.typ=floatdef) xor
+ (resultdef.typ=floatdef)
+ ) then
+ location_force_mem(current_asmdata.CurrAsmList,location);
+
+ { but use the new size, but we don't know the size of all arrays }
+ newsize:=def_cgsize(resultdef);
+ location.size:=newsize;
+ end;
+
+
+{$ifdef TESTOBJEXT2}
+ procedure tcgtypeconvnode.checkobject;
+ begin
+ { no checking by default }
+ end;
+{$endif TESTOBJEXT2}
+
+
+ procedure tcgtypeconvnode.pass_generate_code;
+ begin
+ { the boolean routines can be called with LOC_JUMP and
+ call secondpass themselves in the helper }
+ if not(convtype in [tc_bool_2_int,tc_bool_2_bool,tc_int_2_bool]) then
+ begin
+ secondpass(left);
+ if codegenerror then
+ exit;
+ end;
+
+ second_call_helper(convtype);
+
+{$ifdef TESTOBJEXT2}
+ { Check explicit conversions to objects pointers !! }
+ if p^.explizit and
+ (p^.resultdef.typ=pointerdef) and
+ (tpointerdef(p^.resultdef).definition.typ=objectdef) and not
+ (tobjectdef(tpointerdef(p^.resultdef).definition).isclass) and
+ ((tobjectdef(tpointerdef(p^.resultdef).definition).options and oo_hasvmt)<>0) and
+ (cs_check_range in current_settings.localswitches) then
+ checkobject;
+{$endif TESTOBJEXT2}
+ end;
+
+
+ procedure tcgasnode.pass_generate_code;
+ begin
+ secondpass(call);
+ location_copy(location,call.location);
+ end;
+
+
+begin
+ ctypeconvnode := tcgtypeconvnode;
+ casnode := tcgasnode;
+end.
diff --git a/closures/compiler/ncgcon.pas b/closures/compiler/ncgcon.pas
new file mode 100644
index 0000000000..b64d25ed00
--- /dev/null
+++ b/closures/compiler/ncgcon.pas
@@ -0,0 +1,493 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate assembler for constant nodes which are the same for
+ all (most) processors
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit ncgcon;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,ncon;
+
+ type
+ tcgdataconstnode = class(tdataconstnode)
+ procedure pass_generate_code;override;
+ end;
+
+ tcgrealconstnode = class(trealconstnode)
+ procedure pass_generate_code;override;
+ end;
+
+ tcgordconstnode = class(tordconstnode)
+ procedure pass_generate_code;override;
+ end;
+
+ tcgpointerconstnode = class(tpointerconstnode)
+ procedure pass_generate_code;override;
+ end;
+
+ tcgstringconstnode = class(tstringconstnode)
+ procedure pass_generate_code;override;
+ end;
+
+ tcgsetconstnode = class(tsetconstnode)
+ procedure pass_generate_code;override;
+ end;
+
+ tcgnilnode = class(tnilnode)
+ procedure pass_generate_code;override;
+ end;
+
+ tcgguidconstnode = class(tguidconstnode)
+ procedure pass_generate_code;override;
+ end;
+
+
+implementation
+
+ uses
+ globtype,widestr,systems,
+ verbose,globals,cutils,
+ symconst,symdef,aasmbase,aasmtai,aasmdata,aasmcpu,defutil,
+ cpuinfo,cpubase,
+ cgbase,cgobj,cgutils,
+ ncgutil, cclasses,asmutils
+ ;
+
+
+{*****************************************************************************
+ TCGREALCONSTNODE
+*****************************************************************************}
+
+ procedure tcgdataconstnode.pass_generate_code;
+ var
+ l : tasmlabel;
+ i : longint;
+ b : byte;
+ begin
+ location_reset_ref(location,LOC_CREFERENCE,OS_NO,const_align(maxalign));
+ current_asmdata.getdatalabel(l);
+ maybe_new_object_file(current_asmdata.asmlists[al_typedconsts]);
+ new_section(current_asmdata.asmlists[al_typedconsts],sec_rodata,l.name,const_align(maxalign));
+ current_asmdata.asmlists[al_typedconsts].concat(Tai_label.Create(l));
+ data.seek(0);
+ for i:=0 to data.size-1 do
+ begin
+ data.read(b,1);
+ current_asmdata.asmlists[al_typedconsts].concat(Tai_const.Create_8bit(b));
+ end;
+ location.reference.symbol:=l;
+ end;
+
+{*****************************************************************************
+ TCGREALCONSTNODE
+*****************************************************************************}
+
+ procedure tcgrealconstnode.pass_generate_code;
+ { I suppose the parser/pass_1 must make sure the generated real }
+ { constants are actually supported by the target processor? (JM) }
+ const
+ floattype2ait:array[tfloattype] of taitype=
+ (ait_real_32bit,ait_real_64bit,ait_real_80bit,ait_real_80bit,ait_comp_64bit,ait_comp_64bit,ait_real_128bit);
+
+ { Since the value is stored always as bestreal, we share a single pool
+ between all float types. This requires type and hiloswapped flag to
+ be matched along with the value }
+ type
+ tfloatkey = record
+ value: bestreal;
+ typ: tfloattype;
+ swapped: boolean;
+ end;
+
+ var
+ lastlabel : tasmlabel;
+ realait : taitype;
+ entry : PHashSetItem;
+ key: tfloatkey;
+{$ifdef ARM}
+ hiloswapped : boolean;
+{$endif ARM}
+
+ begin
+ location_reset_ref(location,LOC_CREFERENCE,def_cgsize(resultdef),const_align(resultdef.alignment));
+ lastlabel:=nil;
+ realait:=floattype2ait[tfloatdef(resultdef).floattype];
+{$ifdef ARM}
+ hiloswapped:=is_double_hilo_swapped;
+{$endif ARM}
+ { const already used ? }
+ if not assigned(lab_real) then
+ begin
+ { there may be gap between record fields, zero it out }
+ fillchar(key,sizeof(key),0);
+ key.value:=value_real;
+ key.typ:=tfloatdef(resultdef).floattype;
+{$ifdef ARM}
+ key.swapped:=hiloswapped;
+{$endif ARM}
+ entry := current_asmdata.ConstPools[sp_floats].FindOrAdd(@key, sizeof(key));
+
+ lab_real := TAsmLabel(entry^.Data); // is it needed anymore?
+
+ { :-(, we must generate a new entry }
+ if not assigned(lab_real) then
+ begin
+ current_asmdata.getdatalabel(lastlabel);
+ entry^.Data:=lastlabel;
+ lab_real:=lastlabel;
+ maybe_new_object_file(current_asmdata.asmlists[al_typedconsts]);
+ new_section(current_asmdata.asmlists[al_typedconsts],sec_rodata_norel,lastlabel.name,const_align(resultdef.alignment));
+ current_asmdata.asmlists[al_typedconsts].concat(Tai_label.Create(lastlabel));
+ case realait of
+ ait_real_32bit :
+ begin
+ current_asmdata.asmlists[al_typedconsts].concat(Tai_real_32bit.Create(ts32real(value_real)));
+ { range checking? }
+ if floating_point_range_check_error and
+ (tai_real_32bit(current_asmdata.asmlists[al_typedconsts].last).value=MathInf.Value) then
+ Message(parser_e_range_check_error);
+ end;
+
+ ait_real_64bit :
+ begin
+{$ifdef ARM}
+ if hiloswapped then
+ current_asmdata.asmlists[al_typedconsts].concat(Tai_real_64bit.Create_hiloswapped(ts64real(value_real)))
+ else
+{$endif ARM}
+ current_asmdata.asmlists[al_typedconsts].concat(Tai_real_64bit.Create(ts64real(value_real)));
+
+ { range checking? }
+ if floating_point_range_check_error and
+ (tai_real_64bit(current_asmdata.asmlists[al_typedconsts].last).value=MathInf.Value) then
+ Message(parser_e_range_check_error);
+ end;
+
+ ait_real_80bit :
+ begin
+ current_asmdata.asmlists[al_typedconsts].concat(Tai_real_80bit.Create(value_real,resultdef.size));
+
+ { range checking? }
+ if floating_point_range_check_error and
+ (tai_real_80bit(current_asmdata.asmlists[al_typedconsts].last).value=MathInf.Value) then
+ Message(parser_e_range_check_error);
+ end;
+{$ifdef cpufloat128}
+ ait_real_128bit :
+ begin
+ current_asmdata.asmlists[al_typedconsts].concat(Tai_real_128bit.Create(value_real));
+
+ { range checking? }
+ if floating_point_range_check_error and
+ (tai_real_128bit(current_asmdata.asmlists[al_typedconsts].last).value=MathInf.Value) then
+ Message(parser_e_range_check_error);
+ end;
+{$endif cpufloat128}
+
+ { the round is necessary for native compilers where comp isn't a float }
+ ait_comp_64bit :
+ if (value_real>9223372036854775807.0) or (value_real<-9223372036854775808.0) then
+ message(parser_e_range_check_error)
+ else
+ current_asmdata.asmlists[al_typedconsts].concat(Tai_comp_64bit.Create(round(value_real)));
+ else
+ internalerror(10120);
+ end;
+ end;
+ end;
+ location.reference.symbol:=lab_real;
+ end;
+
+{*****************************************************************************
+ TCGORDCONSTNODE
+*****************************************************************************}
+
+ procedure tcgordconstnode.pass_generate_code;
+ begin
+ location_reset(location,LOC_CONSTANT,def_cgsize(resultdef));
+{$ifdef cpu64bitalu}
+ location.value:=value.svalue;
+{$else cpu64bitalu}
+ location.value64:=value.svalue;
+{$endif cpu64bitalu}
+ end;
+
+
+{*****************************************************************************
+ TCGPOINTERCONSTNODE
+*****************************************************************************}
+
+ procedure tcgpointerconstnode.pass_generate_code;
+ begin
+ { an integer const. behaves as a memory reference }
+ location_reset(location,LOC_CONSTANT,OS_ADDR);
+ location.value:=aint(value);
+ end;
+
+
+{*****************************************************************************
+ TCGSTRINGCONSTNODE
+*****************************************************************************}
+
+ procedure tcgstringconstnode.pass_generate_code;
+ var
+ lastlabel: tasmlabel;
+ pc: pchar;
+ l: longint;
+ href: treference;
+ pool: THashSet;
+ entry: PHashSetItem;
+
+ const
+ PoolMap: array[tconststringtype] of TConstPoolType = (
+ sp_conststr,
+ sp_shortstr,
+ sp_longstr,
+ sp_ansistr,
+ sp_widestr,
+ sp_unicodestr
+ );
+ begin
+ { for empty ansistrings we could return a constant 0 }
+ if (cst_type in [cst_ansistring,cst_widestring,cst_unicodestring]) and (len=0) then
+ begin
+ location_reset(location,LOC_CONSTANT,OS_ADDR);
+ location.value:=0;
+ exit;
+ end;
+ { const already used ? }
+ if not assigned(lab_str) then
+ begin
+ pool := current_asmdata.ConstPools[PoolMap[cst_type]];
+
+ if cst_type in [cst_widestring, cst_unicodestring] then
+ entry := pool.FindOrAdd(pcompilerwidestring(value_str)^.data,len*cwidechartype.size)
+ else
+ if cst_type = cst_ansistring then
+ entry := PHashSetItem(TTagHashSet(pool).FindOrAdd(value_str,len,tstringdef(resultdef).encoding))
+ else
+ entry := pool.FindOrAdd(value_str,len);
+
+ lab_str := TAsmLabel(entry^.Data); // is it needed anymore?
+
+ { :-(, we must generate a new entry }
+ if not assigned(entry^.Data) then
+ begin
+ case cst_type of
+ cst_ansistring:
+ begin
+ if len=0 then
+ InternalError(2008032301) { empty string should be handled above }
+ else
+ lastlabel:=emit_ansistring_const(current_asmdata.AsmLists[al_typedconsts],value_str,len,tstringdef(resultdef).encoding);
+ end;
+ cst_unicodestring,
+ cst_widestring:
+ begin
+ if len=0 then
+ InternalError(2008032302) { empty string should be handled above }
+ else
+ lastlabel := emit_unicodestring_const(current_asmdata.AsmLists[al_typedconsts],
+ value_str,
+ tstringdef(resultdef).encoding,
+ (cst_type=cst_widestring) and (tf_winlikewidestring in target_info.flags));
+ end;
+ cst_shortstring:
+ begin
+ current_asmdata.getdatalabel(lastlabel);
+ maybe_new_object_file(current_asmdata.asmlists[al_typedconsts]);
+ new_section(current_asmdata.asmlists[al_typedconsts],sec_rodata_norel,lastlabel.name,const_align(sizeof(pint)));
+
+ current_asmdata.asmlists[al_typedconsts].concat(Tai_label.Create(lastlabel));
+ { truncate strings larger than 255 chars }
+ if len>255 then
+ l:=255
+ else
+ l:=len;
+ { include length and terminating zero for quick conversion to pchar }
+ getmem(pc,l+2);
+ move(value_str^,pc[1],l);
+ pc[0]:=chr(l);
+ pc[l+1]:=#0;
+ current_asmdata.asmlists[al_typedconsts].concat(Tai_string.Create_pchar(pc,l+2));
+ end;
+ cst_conststring:
+ begin
+ current_asmdata.getdatalabel(lastlabel);
+ maybe_new_object_file(current_asmdata.asmlists[al_typedconsts]);
+ new_section(current_asmdata.asmlists[al_typedconsts],sec_rodata_norel,lastlabel.name,const_align(sizeof(pint)));
+
+ current_asmdata.asmlists[al_typedconsts].concat(Tai_label.Create(lastlabel));
+ { include terminating zero }
+ getmem(pc,len+1);
+ move(value_str^,pc[0],len);
+ pc[len]:=#0;
+ current_asmdata.asmlists[al_typedconsts].concat(Tai_string.Create_pchar(pc,len+1));
+ end;
+ end;
+ lab_str:=lastlabel;
+ entry^.Data:=lastlabel;
+ end;
+ end;
+ if cst_type in [cst_ansistring, cst_widestring, cst_unicodestring] then
+ begin
+ location_reset(location, LOC_REGISTER, OS_ADDR);
+ reference_reset_symbol(href, lab_str, 0, const_align(sizeof(pint)));
+ location.register:=cg.getaddressregister(current_asmdata.CurrAsmList);
+ cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,href,location.register);
+ end
+ else
+ begin
+ location_reset_ref(location, LOC_CREFERENCE, def_cgsize(resultdef), const_align(sizeof(pint)));
+ location.reference.symbol:=lab_str;
+ end;
+ end;
+
+
+{*****************************************************************************
+ TCGSETCONSTNODE
+*****************************************************************************}
+
+ procedure tcgsetconstnode.pass_generate_code;
+
+ type
+ setbytes=array[0..31] of byte;
+ Psetbytes=^setbytes;
+
+ procedure smallsetconst;
+ begin
+ location_reset(location,LOC_CONSTANT,int_cgsize(resultdef.size));
+ if (source_info.endian=target_info.endian) then
+ begin
+ { not plongint, because that will "sign extend" the set on 64 bit platforms }
+ { if changed to "paword", please also modify "32-resultdef.size*8" and }
+ { cross-endian code below }
+ { Extra aint type cast to avoid range errors }
+ location.value:=aint(pCardinal(value_set)^)
+ end
+ else
+ begin
+ location.value:=swapendian(Pcardinal(value_set)^);
+ location.value:=aint(
+ reverse_byte (location.value and $ff) or
+ (reverse_byte((location.value shr 8) and $ff) shl 8) or
+ (reverse_byte((location.value shr 16) and $ff) shl 16) or
+ (reverse_byte((location.value shr 24) and $ff) shl 24)
+ );
+ end;
+ if (target_info.endian=endian_big) then
+ location.value:=location.value shr (32-resultdef.size*8);
+ end;
+
+ procedure varsetconst;
+ var
+ lastlabel : tasmlabel;
+ i : longint;
+ entry : PHashSetItem;
+ begin
+ location_reset_ref(location,LOC_CREFERENCE,OS_NO,const_align(8));
+ lastlabel:=nil;
+ { const already used ? }
+ if not assigned(lab_set) then
+ begin
+ entry := current_asmdata.ConstPools[sp_varsets].FindOrAdd(value_set, 32);
+
+ lab_set := TAsmLabel(entry^.Data); // is it needed anymore?
+
+ { :-(, we must generate a new entry }
+ if not assigned(entry^.Data) then
+ begin
+ current_asmdata.getdatalabel(lastlabel);
+ lab_set:=lastlabel;
+ entry^.Data:=lastlabel;
+ maybe_new_object_file(current_asmdata.asmlists[al_typedconsts]);
+ new_section(current_asmdata.asmlists[al_typedconsts],sec_rodata_norel,lastlabel.name,const_align(8));
+ current_asmdata.asmlists[al_typedconsts].concat(Tai_label.Create(lastlabel));
+ if (source_info.endian=target_info.endian) then
+ for i:=0 to 31 do
+ current_asmdata.asmlists[al_typedconsts].concat(Tai_const.Create_8bit(Psetbytes(value_set)^[i]))
+ else
+ for i:=0 to 31 do
+ current_asmdata.asmlists[al_typedconsts].concat(Tai_const.Create_8bit(reverse_byte(Psetbytes(value_set)^[i])));
+ end;
+ end;
+ location.reference.symbol:=lab_set;
+ end;
+
+ begin
+ adjustforsetbase;
+
+ { small sets are loaded as constants }
+ if is_smallset(resultdef) then
+ smallsetconst
+ else
+ varsetconst;
+ end;
+
+
+{*****************************************************************************
+ TCGNILNODE
+*****************************************************************************}
+
+ procedure tcgnilnode.pass_generate_code;
+ begin
+ location_reset(location,LOC_CONSTANT,OS_ADDR);
+ location.value:=0;
+ end;
+
+
+{*****************************************************************************
+ TCGGUIDCONSTNODE
+*****************************************************************************}
+
+ procedure tcgguidconstnode.pass_generate_code;
+ var
+ tmplabel : TAsmLabel;
+ i : integer;
+ begin
+ location_reset_ref(location,LOC_CREFERENCE,OS_NO,const_align(16));
+ { label for GUID }
+ current_asmdata.getdatalabel(tmplabel);
+ maybe_new_object_file(current_asmdata.asmlists[al_typedconsts]);
+ new_section(current_asmdata.asmlists[al_typedconsts],sec_rodata_norel,tmplabel.name,const_align(16));
+ current_asmdata.asmlists[al_typedconsts].concat(Tai_label.Create(tmplabel));
+ current_asmdata.asmlists[al_typedconsts].concat(Tai_const.Create_32bit(longint(value.D1)));
+ current_asmdata.asmlists[al_typedconsts].concat(Tai_const.Create_16bit(value.D2));
+ current_asmdata.asmlists[al_typedconsts].concat(Tai_const.Create_16bit(value.D3));
+ for i:=low(value.D4) to high(value.D4) do
+ current_asmdata.asmlists[al_typedconsts].concat(Tai_const.Create_8bit(value.D4[i]));
+ location.reference.symbol:=tmplabel;
+ end;
+
+
+begin
+ cdataconstnode:=tcgdataconstnode;
+ crealconstnode:=tcgrealconstnode;
+ cordconstnode:=tcgordconstnode;
+ cpointerconstnode:=tcgpointerconstnode;
+ cstringconstnode:=tcgstringconstnode;
+ csetconstnode:=tcgsetconstnode;
+ cnilnode:=tcgnilnode;
+ cguidconstnode:=tcgguidconstnode;
+end.
diff --git a/closures/compiler/ncgflw.pas b/closures/compiler/ncgflw.pas
new file mode 100644
index 0000000000..3ff66ee81f
--- /dev/null
+++ b/closures/compiler/ncgflw.pas
@@ -0,0 +1,1662 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate assembler for nodes that influence the flow which are
+ the same for all (most?) processors
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit ncgflw;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ aasmbase,node,nflw,ncgutil;
+
+ type
+ tcgwhilerepeatnode = class(twhilerepeatnode)
+ usedregvars: tusedregvars;
+
+ procedure pass_generate_code;override;
+ procedure sync_regvars(checkusedregvars: boolean);
+ end;
+
+ tcgifnode = class(tifnode)
+ procedure pass_generate_code;override;
+ end;
+
+ tcgfornode = class(tfornode)
+ usedregvars: tusedregvars;
+
+ procedure pass_generate_code;override;
+ procedure sync_regvars(checkusedregvars: boolean);
+ end;
+
+ tcgexitnode = class(texitnode)
+ procedure pass_generate_code;override;
+ end;
+
+ tcgbreaknode = class(tbreaknode)
+ procedure pass_generate_code;override;
+ end;
+
+ tcgcontinuenode = class(tcontinuenode)
+ procedure pass_generate_code;override;
+ end;
+
+ tcggotonode = class(tgotonode)
+ procedure pass_generate_code;override;
+ end;
+
+ tcglabelnode = class(tlabelnode)
+ private
+ asmlabel : tasmlabel;
+ public
+ function getasmlabel : tasmlabel;
+ procedure pass_generate_code;override;
+ end;
+
+ tcgraisenode = class(traisenode)
+ procedure pass_generate_code;override;
+ end;
+
+ tcgtryexceptnode = class(ttryexceptnode)
+ procedure pass_generate_code;override;
+ end;
+
+ tcgtryfinallynode = class(ttryfinallynode)
+ procedure handle_safecall_exception;
+ procedure pass_generate_code;override;
+ end;
+
+ tcgonnode = class(tonnode)
+ procedure pass_generate_code;override;
+ end;
+
+implementation
+
+ uses
+ verbose,globals,systems,globtype,constexp,
+ symconst,symdef,symsym,aasmtai,aasmdata,aasmcpu,defutil,
+ procinfo,cgbase,pass_2,parabase,
+ cpubase,cpuinfo,
+ nld,ncon,
+ tgobj,paramgr,
+ regvars,
+ cgutils,cgobj,nutils
+ ;
+
+{*****************************************************************************
+ Second_While_RepeatN
+*****************************************************************************}
+
+ procedure tcgwhilerepeatnode.sync_regvars(checkusedregvars: boolean);
+ begin
+ if (cs_opt_regvar in current_settings.optimizerswitches) and
+ not(pi_has_label in current_procinfo.flags) then
+ begin
+ if checkusedregvars then
+ begin
+ usedregvars.intregvars.init;
+ usedregvars.fpuregvars.init;
+ usedregvars.mmregvars.init;
+
+ { we have to synchronise both the regvars used in the loop }
+ { and the ones in the while/until condition }
+ get_used_regvars(self,usedregvars);
+ gen_sync_regvars(current_asmdata.CurrAsmList,usedregvars);
+ end
+ else
+ begin
+ gen_sync_regvars(current_asmdata.CurrAsmList,usedregvars);
+ usedregvars.intregvars.done;
+ usedregvars.fpuregvars.done;
+ usedregvars.mmregvars.done;
+ end;
+ end;
+ end;
+
+
+ procedure tcgwhilerepeatnode.pass_generate_code;
+ var
+ lcont,lbreak,lloop,
+ oldclabel,oldblabel : tasmlabel;
+ otlabel,oflabel : tasmlabel;
+ oldflowcontrol : tflowcontrol;
+ oldexecutionweight : longint;
+ begin
+ location_reset(location,LOC_VOID,OS_NO);
+
+ current_asmdata.getjumplabel(lloop);
+ current_asmdata.getjumplabel(lcont);
+ current_asmdata.getjumplabel(lbreak);
+ { arrange continue and breaklabels: }
+ oldflowcontrol:=flowcontrol;
+ oldclabel:=current_procinfo.CurrContinueLabel;
+ oldblabel:=current_procinfo.CurrBreakLabel;
+ include(flowcontrol,fc_inflowcontrol);
+
+ sync_regvars(true);
+{$ifdef OLDREGVARS}
+ load_all_regvars(current_asmdata.CurrAsmList);
+{$endif OLDREGVARS}
+ { handling code at the end as it is much more efficient, and makes
+ while equal to repeat loop, only the end true/false is swapped (PFV) }
+ if lnf_testatbegin in loopflags then
+ cg.a_jmp_always(current_asmdata.CurrAsmList,lcont);
+
+ if not(cs_opt_size in current_settings.optimizerswitches) then
+ { align loop target }
+ current_asmdata.CurrAsmList.concat(Tai_align.Create(current_settings.alignment.loopalign));
+
+ cg.a_label(current_asmdata.CurrAsmList,lloop);
+
+ current_procinfo.CurrContinueLabel:=lcont;
+ current_procinfo.CurrBreakLabel:=lbreak;
+
+ if assigned(right) then
+ begin
+ { calc register weight }
+ oldexecutionweight:=cg.executionweight;
+ cg.executionweight:=cg.executionweight*8;
+ secondpass(right);
+ cg.executionweight:=oldexecutionweight;
+ end;
+
+{$ifdef OLDREGVARS}
+ load_all_regvars(current_asmdata.CurrAsmList);
+{$endif OLDREGVARS}
+
+ cg.a_label(current_asmdata.CurrAsmList,lcont);
+ otlabel:=current_procinfo.CurrTrueLabel;
+ oflabel:=current_procinfo.CurrFalseLabel;
+ if lnf_checknegate in loopflags then
+ begin
+ current_procinfo.CurrTrueLabel:=lbreak;
+ current_procinfo.CurrFalseLabel:=lloop;
+ end
+ else
+ begin
+ current_procinfo.CurrTrueLabel:=lloop;
+ current_procinfo.CurrFalseLabel:=lbreak;
+ end;
+ secondpass(left);
+
+ maketojumpbool(current_asmdata.CurrAsmList,left,lr_load_regvars);
+ cg.a_label(current_asmdata.CurrAsmList,lbreak);
+
+ sync_regvars(false);
+
+ current_procinfo.CurrTrueLabel:=otlabel;
+ current_procinfo.CurrFalseLabel:=oflabel;
+
+ current_procinfo.CurrContinueLabel:=oldclabel;
+ current_procinfo.CurrBreakLabel:=oldblabel;
+ { a break/continue in a while/repeat block can't be seen outside }
+ flowcontrol:=oldflowcontrol+(flowcontrol-[fc_break,fc_continue,fc_inflowcontrol]);
+ end;
+
+
+{*****************************************************************************
+ tcgIFNODE
+*****************************************************************************}
+
+ procedure tcgifnode.pass_generate_code;
+
+ var
+ hl,otlabel,oflabel : tasmlabel;
+ oldflowcontrol: tflowcontrol;
+ oldexecutionweight : longint;
+(*
+ org_regvar_loaded_other,
+ then_regvar_loaded_other,
+ else_regvar_loaded_other : regvarother_booleanarray;
+ org_regvar_loaded_int,
+ then_regvar_loaded_int,
+ else_regvar_loaded_int : Tsuperregisterset;
+ org_list,
+ then_list,
+ else_list : TAsmList;
+*)
+
+ begin
+ location_reset(location,LOC_VOID,OS_NO);
+
+ oldflowcontrol := flowcontrol;
+ include(flowcontrol,fc_inflowcontrol);
+ otlabel:=current_procinfo.CurrTrueLabel;
+ oflabel:=current_procinfo.CurrFalseLabel;
+ current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
+ current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel);
+ secondpass(left);
+
+(*
+ { save regvars loaded in the beginning so that we can restore them }
+ { when processing the else-block }
+ if cs_opt_regvar in current_settings.optimizerswitches then
+ begin
+ org_list := current_asmdata.CurrAsmList;
+ current_asmdata.CurrAsmList := TAsmList.create;
+ end;
+*)
+ maketojumpbool(current_asmdata.CurrAsmList,left,lr_dont_load_regvars);
+
+(*
+ if cs_opt_regvar in current_settings.optimizerswitches then
+ begin
+ org_regvar_loaded_int := rg.regvar_loaded_int;
+ org_regvar_loaded_other := rg.regvar_loaded_other;
+ end;
+*)
+ { determines registers weigths }
+ oldexecutionweight:=cg.executionweight;
+ cg.executionweight:=cg.executionweight div 2;
+ if cg.executionweight<1 then
+ cg.executionweight:=1;
+
+ if assigned(right) then
+ begin
+ cg.a_label(current_asmdata.CurrAsmList,current_procinfo.CurrTrueLabel);
+ secondpass(right);
+ end;
+
+ { save current asmlist (previous instructions + then-block) and }
+ { loaded regvar state and create new clean ones }
+{
+ if cs_opt_regvar in current_settings.optimizerswitches then
+ begin
+ then_regvar_loaded_int := rg.regvar_loaded_int;
+ then_regvar_loaded_other := rg.regvar_loaded_other;
+ rg.regvar_loaded_int := org_regvar_loaded_int;
+ rg.regvar_loaded_other := org_regvar_loaded_other;
+ then_list := current_asmdata.CurrAsmList;
+ current_asmdata.CurrAsmList := TAsmList.create;
+ end;
+}
+
+ if assigned(t1) then
+ begin
+ if assigned(right) then
+ begin
+ current_asmdata.getjumplabel(hl);
+ { do go back to if line !! }
+(*
+ if not(cs_opt_regvar in current_settings.optimizerswitches) then
+*)
+ current_filepos:=current_asmdata.CurrAsmList.getlasttaifilepos^
+(*
+ else
+ current_filepos:=then_list.getlasttaifilepos^
+*)
+ ;
+ cg.a_jmp_always(current_asmdata.CurrAsmList,hl);
+ end;
+ cg.a_label(current_asmdata.CurrAsmList,current_procinfo.CurrFalseLabel);
+ secondpass(t1);
+(*
+ { save current asmlist (previous instructions + else-block) }
+ { and loaded regvar state and create a new clean list }
+ if cs_opt_regvar in current_settings.optimizerswitches then
+ begin
+{ else_regvar_loaded_int := rg.regvar_loaded_int;
+ else_regvar_loaded_other := rg.regvar_loaded_other;}
+ else_list := current_asmdata.CurrAsmList;
+ current_asmdata.CurrAsmList := TAsmList.create;
+ end;
+*)
+ if assigned(right) then
+ cg.a_label(current_asmdata.CurrAsmList,hl);
+ end
+ else
+ begin
+(*
+ if cs_opt_regvar in current_settings.optimizerswitches then
+ begin
+{ else_regvar_loaded_int := rg.regvar_loaded_int;
+ else_regvar_loaded_other := rg.regvar_loaded_other;}
+ else_list := current_asmdata.CurrAsmList;
+ current_asmdata.CurrAsmList := TAsmList.create;
+ end;
+*)
+ cg.a_label(current_asmdata.CurrAsmList,current_procinfo.CurrFalseLabel);
+ end;
+ if not(assigned(right)) then
+ begin
+ cg.a_label(current_asmdata.CurrAsmList,current_procinfo.CurrTrueLabel);
+ end;
+
+(*
+ if cs_opt_regvar in current_settings.optimizerswitches then
+ begin
+ { add loads of regvars at the end of the then- and else-blocks }
+ { so that at the end of both blocks the same regvars are loaded }
+
+ { no else block? }
+ if not assigned(t1) then
+ begin
+ sync_regvars_int(org_list,then_list,org_regvar_loaded_int,then_regvar_loaded_int);
+ sync_regvars_other(org_list,then_list,org_regvar_loaded_other,then_regvar_loaded_other);
+ end
+ { no then block? }
+ else if not assigned(right) then
+ begin
+ sync_regvars_int(org_list,else_list,org_regvar_loaded_int,else_regvar_loaded_int);
+ sync_regvars_other(org_list,else_list,org_regvar_loaded_other,else_regvar_loaded_other);
+ end
+ { both else and then blocks }
+ else
+ begin
+ sync_regvars_int(then_list,else_list,then_regvar_loaded_int,else_regvar_loaded_int);
+ sync_regvars_other(then_list,else_list,then_regvar_loaded_other,else_regvar_loaded_other);
+ end;
+ { add all lists together }
+ org_list.concatlist(then_list);
+ then_list.free;
+ org_list.concatlist(else_list);
+ else_list.free;
+ org_list.concatlist(current_asmdata.CurrAsmList);
+ current_asmdata.CurrAsmList.free;
+ current_asmdata.CurrAsmList := org_list;
+ end;
+*)
+
+ cg.executionweight:=oldexecutionweight;
+
+ current_procinfo.CurrTrueLabel:=otlabel;
+ current_procinfo.CurrFalseLabel:=oflabel;
+ flowcontrol := oldflowcontrol + (flowcontrol - [fc_inflowcontrol]);
+ end;
+
+
+{*****************************************************************************
+ SecondFor
+*****************************************************************************}
+
+ procedure tcgfornode.sync_regvars(checkusedregvars: boolean);
+ begin
+ if (cs_opt_regvar in current_settings.optimizerswitches) and
+ not(pi_has_label in current_procinfo.flags) then
+ begin
+ if checkusedregvars then
+ begin
+ usedregvars.intregvars.init;
+ usedregvars.fpuregvars.init;
+ usedregvars.mmregvars.init;
+
+ { We have to synchronise the loop variable and loop body. }
+ { The loop end is not necessary, unless it's a register }
+ { variable. The start value also doesn't matter. }
+
+ { loop var }
+ get_used_regvars(right,usedregvars);
+ { loop body }
+ get_used_regvars(t2,usedregvars);
+ { end value (t1) is not necessary (it cannot be a regvar, }
+ { see webtbs/tw8883) }
+
+ gen_sync_regvars(current_asmdata.CurrAsmList,usedregvars);
+ end
+ else
+ begin
+ gen_sync_regvars(current_asmdata.CurrAsmList,usedregvars);
+ usedregvars.intregvars.done;
+ usedregvars.fpuregvars.done;
+ usedregvars.mmregvars.done;
+ end;
+ end;
+ end;
+
+
+ procedure tcgfornode.pass_generate_code;
+ var
+ l3,oldclabel,oldblabel,
+ otl, ofl : tasmlabel;
+ temptovalue : boolean;
+ hop : topcg;
+ hcond : topcmp;
+ opsize : tcgsize;
+ count_var_is_signed,do_loopvar_at_end : boolean;
+ cmp_const:Tconstexprint;
+ oldflowcontrol : tflowcontrol;
+ oldexecutionweight : longint;
+ isjump: boolean;
+ begin
+ location_reset(location,LOC_VOID,OS_NO);
+ oldclabel:=current_procinfo.CurrContinueLabel;
+ oldblabel:=current_procinfo.CurrBreakLabel;
+ current_asmdata.getjumplabel(current_procinfo.CurrContinueLabel);
+ current_asmdata.getjumplabel(current_procinfo.CurrBreakLabel);
+ current_asmdata.getjumplabel(l3);
+
+ { only calculate reference }
+ opsize := def_cgsize(left.resultdef);
+ count_var_is_signed:=is_signed(left.resultdef);
+
+ { first set the to value
+ because the count var can be in the expression ! }
+ do_loopvar_at_end:=(lnf_dont_mind_loopvar_on_exit in loopflags)
+ { if the loop is unrolled and there is a jump into the loop,
+ then we can't do the trick with incrementing the loop var only at the
+ end
+ }
+ and not(assigned(entrylabel));
+
+ isjump:=(t1.expectloc=LOC_JUMP);
+ if isjump then
+ begin
+ otl:=current_procinfo.CurrTrueLabel;
+ current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
+ ofl:=current_procinfo.CurrFalseLabel;
+ current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel);
+ end;
+ secondpass(t1);
+ if t1.location.loc in [LOC_FLAGS,LOC_JUMP] then
+ location_force_reg(current_asmdata.CurrAsmList,t1.location,def_cgsize(t1.resultdef),false);
+ if isjump then
+ begin
+ current_procinfo.CurrTrueLabel:=otl;
+ current_procinfo.CurrFalseLabel:=ofl;
+ end;
+ { calculate pointer value and check if changeable and if so }
+ { load into temporary variable }
+ if t1.nodetype<>ordconstn then
+ begin
+ do_loopvar_at_end:=false;
+ location_force_reg(current_asmdata.CurrAsmList,t1.location,t1.location.size,false);
+ temptovalue:=true;
+ end
+ else
+ temptovalue:=false;
+
+ { load loopvar, prefer loopvar being a register variable }
+ oldexecutionweight:=cg.executionweight;
+ inc(cg.executionweight,8);
+ secondpass(left);
+ cg.executionweight:=oldexecutionweight;
+
+ { load from value }
+ isjump:=(right.expectloc=LOC_JUMP);
+ if isjump then
+ begin
+ otl:=current_procinfo.CurrTrueLabel;
+ current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
+ ofl:=current_procinfo.CurrFalseLabel;
+ current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel);
+ end;
+ secondpass(right);
+ if right.location.loc in [LOC_FLAGS,LOC_JUMP] then
+ location_force_reg(current_asmdata.CurrAsmList,right.location,def_cgsize(right.resultdef),false);
+ if isjump then
+ begin
+ current_procinfo.CurrTrueLabel:=otl;
+ current_procinfo.CurrFalseLabel:=ofl;
+ end;
+
+ maybechangeloadnodereg(current_asmdata.CurrAsmList,left,false);
+ oldflowcontrol:=flowcontrol;
+ include(flowcontrol,fc_inflowcontrol);
+ { produce start assignment }
+ case left.location.loc of
+ LOC_REFERENCE,
+ LOC_CREFERENCE :
+ cg.a_load_loc_ref(current_asmdata.CurrAsmList,left.location.size,right.location,left.location.reference);
+ LOC_REGISTER,
+ LOC_CREGISTER:
+ cg.a_load_loc_reg(current_asmdata.CurrAsmList,left.location.size,right.location,left.location.register);
+ LOC_SUBSETREG,
+ LOC_CSUBSETREG :
+ cg.a_load_loc_subsetreg(current_asmdata.CurrAsmList,left.location.size,right.location,left.location.sreg);
+ else
+ internalerror(200501311);
+ end;
+
+ if lnf_backward in loopflags then
+ if count_var_is_signed then
+ hcond:=OC_LT
+ else
+ hcond:=OC_B
+ else
+ if count_var_is_signed then
+ hcond:=OC_GT
+ else
+ hcond:=OC_A;
+
+ sync_regvars(true);
+{$ifdef OLDREGVARS}
+ load_all_regvars(current_asmdata.CurrAsmList);
+{$endif OLDREGVARS}
+
+ if temptovalue then
+ begin
+ cg.a_cmp_reg_loc_label(current_asmdata.CurrAsmList,opsize,hcond,
+ t1.location.register,left.location,current_procinfo.CurrBreakLabel);
+ end
+ else
+ begin
+ if lnf_testatbegin in loopflags then
+ begin
+ cg.a_cmp_const_loc_label(current_asmdata.CurrAsmList,opsize,hcond,
+ tordconstnode(t1).value.svalue,
+ left.location,current_procinfo.CurrBreakLabel);
+ end;
+ end;
+
+ {If the loopvar doesn't mind on exit, we avoid this ugly
+ dec instruction and do the loopvar inc/dec after the loop
+ body.}
+ if not do_loopvar_at_end then
+ begin
+ if lnf_backward in loopflags then
+ hop:=OP_ADD
+ else
+ hop:=OP_SUB;
+ cg.a_op_const_loc(current_asmdata.CurrAsmList,hop,1,left.location);
+ end;
+
+ if assigned(entrylabel) then
+ cg.a_jmp_always(current_asmdata.CurrAsmList,tcglabelnode(entrylabel).getasmlabel);
+
+ { align loop target }
+ if not(cs_opt_size in current_settings.optimizerswitches) then
+ current_asmdata.CurrAsmList.concat(Tai_align.Create(current_settings.alignment.loopalign));
+ cg.a_label(current_asmdata.CurrAsmList,l3);
+
+ {If the loopvar doesn't mind on exit, we avoid the loopvar inc/dec
+ after the loop body instead of here.}
+ if not do_loopvar_at_end then
+ begin
+ { according to count direction DEC or INC... }
+ if lnf_backward in loopflags then
+ hop:=OP_SUB
+ else
+ hop:=OP_ADD;
+ cg.a_op_const_loc(current_asmdata.CurrAsmList,hop,1,left.location);
+ end;
+
+ if assigned(t2) then
+ begin
+ { Calc register weight }
+ oldexecutionweight:=cg.executionweight;
+ cg.executionweight:=cg.executionweight*8;
+ secondpass(t2);
+ cg.executionweight:=oldexecutionweight;
+{$ifdef OLDREGVARS}
+ load_all_regvars(current_asmdata.CurrAsmList);
+{$endif OLDREGVARS}
+ end;
+
+ {If the loopvar doesn't mind on exit, we do the loopvar inc/dec
+ after the loop body instead of here.}
+ if do_loopvar_at_end then
+ begin
+ { according to count direction DEC or INC... }
+ if lnf_backward in loopflags then
+ hop:=OP_SUB
+ else
+ hop:=OP_ADD;
+ cg.a_op_const_loc(current_asmdata.CurrAsmList,hop,1,left.location);
+ end;
+
+ cg.a_label(current_asmdata.CurrAsmList,current_procinfo.CurrContinueLabel);
+
+ if do_loopvar_at_end then
+ if lnf_backward in loopflags then
+ if count_var_is_signed then
+ hcond:=OC_GTE
+ else
+ hcond:=OC_AE
+ else
+ if count_var_is_signed then
+ hcond:=OC_LTE
+ else
+ hcond:=OC_BE
+ else
+ if lnf_backward in loopflags then
+ if count_var_is_signed then
+ hcond:=OC_GT
+ else
+ hcond:=OC_A
+ else
+ if count_var_is_signed then
+ hcond:=OC_LT
+ else
+ hcond:=OC_B;
+{$ifdef OLDREGVARS}
+ load_all_regvars(current_asmdata.CurrAsmList);
+{$endif OLDREGVARS}
+
+ { produce comparison and the corresponding }
+ { jump }
+ if temptovalue then
+ begin
+ cg.a_cmp_reg_loc_label(current_asmdata.CurrAsmList,opsize,hcond,t1.location.register,
+ left.location,l3);
+ end
+ else
+ begin
+ cmp_const:=Tordconstnode(t1).value;
+ if do_loopvar_at_end then
+ begin
+ {Watch out for wrap around 255 -> 0.}
+ {Ugly: This code is way to long... Use tables?}
+ case opsize of
+ OS_8:
+ begin
+ if lnf_backward in loopflags then
+ begin
+ if byte(cmp_const.svalue)=low(byte) then
+ begin
+ hcond:=OC_NE;
+ cmp_const:=high(byte);
+ end
+ end
+ else
+ begin
+ if byte(cmp_const.svalue)=high(byte) then
+ begin
+ hcond:=OC_NE;
+ cmp_const:=low(byte);
+ end
+ end
+ end;
+ OS_16:
+ begin
+ if lnf_backward in loopflags then
+ begin
+ if word(cmp_const.svalue)=high(word) then
+ begin
+ hcond:=OC_NE;
+ cmp_const:=low(word);
+ end
+ end
+ else
+ begin
+ if word(cmp_const.svalue)=low(word) then
+ begin
+ hcond:=OC_NE;
+ cmp_const:=high(word);
+ end
+ end
+ end;
+ OS_32:
+ begin
+ if lnf_backward in loopflags then
+ begin
+ if cardinal(cmp_const.svalue)=high(cardinal) then
+ begin
+ hcond:=OC_NE;
+ cmp_const:=low(cardinal);
+ end
+ end
+ else
+ begin
+ if cardinal(cmp_const.svalue)=low(cardinal) then
+ begin
+ hcond:=OC_NE;
+ cmp_const:=high(cardinal);
+ end
+ end
+ end;
+ OS_64:
+ begin
+ if lnf_backward in loopflags then
+ begin
+ if qword(cmp_const.uvalue)=high(qword) then
+ begin
+ hcond:=OC_NE;
+ cmp_const:=low(qword);
+ end
+ end
+ else
+ begin
+ if qword(cmp_const.uvalue)=low(qword) then
+ begin
+ hcond:=OC_NE;
+ cmp_const:=high(qword);
+ end
+ end
+ end;
+ OS_S8:
+ begin
+ if lnf_backward in loopflags then
+ begin
+ if shortint(cmp_const.svalue)=low(shortint) then
+ begin
+ hcond:=OC_NE;
+ cmp_const:=high(shortint);
+ end
+ end
+ else
+ begin
+ if shortint(cmp_const.svalue)=high(shortint) then
+ begin
+ hcond:=OC_NE;
+ cmp_const:=int64(low(shortint));
+ end
+ end
+ end;
+ OS_S16:
+ begin
+ if lnf_backward in loopflags then
+ begin
+ if integer(cmp_const.svalue)=high(smallint) then
+ begin
+ hcond:=OC_NE;
+ cmp_const:=int64(low(smallint));
+ end
+ end
+ else
+ begin
+ if integer(cmp_const.svalue)=low(smallint) then
+ begin
+ hcond:=OC_NE;
+ cmp_const:=int64(high(smallint));
+ end
+ end
+ end;
+ OS_S32:
+ begin
+ if lnf_backward in loopflags then
+ begin
+ if longint(cmp_const.svalue)=high(longint) then
+ begin
+ hcond:=OC_NE;
+ cmp_const:=int64(low(longint));
+ end
+ end
+ else
+ begin
+ if longint(cmp_const.svalue)=low(longint) then
+ begin
+ hcond:=OC_NE;
+ cmp_const:=int64(high(longint));
+ end
+ end
+ end;
+ OS_S64:
+ begin
+ if lnf_backward in loopflags then
+ begin
+ if int64(cmp_const.svalue)=high(int64) then
+ begin
+ hcond:=OC_NE;
+ cmp_const:=low(int64);
+ end
+ end
+ else
+ begin
+ if int64(cmp_const.svalue)=low(int64) then
+ begin
+ hcond:=OC_NE;
+ cmp_const:=high(int64);
+ end
+ end
+ end;
+ else
+ internalerror(200201021);
+ end;
+ end;
+
+ cg.a_cmp_const_loc_label(current_asmdata.CurrAsmList,opsize,hcond,
+ aint(cmp_const.svalue),left.location,l3);
+ end;
+
+ { this is the break label: }
+ cg.a_label(current_asmdata.CurrAsmList,current_procinfo.CurrBreakLabel);
+
+ sync_regvars(false);
+
+ current_procinfo.CurrContinueLabel:=oldclabel;
+ current_procinfo.CurrBreakLabel:=oldblabel;
+ { a break/continue in a while/repeat block can't be seen outside }
+ flowcontrol:=oldflowcontrol+(flowcontrol-[fc_break,fc_continue,fc_inflowcontrol]);
+ end;
+
+
+{*****************************************************************************
+ SecondExitN
+*****************************************************************************}
+
+ procedure tcgexitnode.pass_generate_code;
+ begin
+ location_reset(location,LOC_VOID,OS_NO);
+
+ include(flowcontrol,fc_exit);
+ if assigned(left) then
+ secondpass(left);
+ if (fc_unwind in flowcontrol) then
+ cg.g_local_unwind(current_asmdata.CurrAsmList,current_procinfo.CurrExitLabel)
+ else
+ cg.a_jmp_always(current_asmdata.CurrAsmList,current_procinfo.CurrExitLabel);
+ end;
+
+
+{*****************************************************************************
+ SecondBreakN
+*****************************************************************************}
+
+ procedure tcgbreaknode.pass_generate_code;
+ begin
+ location_reset(location,LOC_VOID,OS_NO);
+
+ include(flowcontrol,fc_break);
+ if current_procinfo.CurrBreakLabel<>nil then
+ begin
+{$ifdef OLDREGVARS}
+ load_all_regvars(current_asmdata.CurrAsmList);
+{$endif OLDREGVARS}
+ if (fc_unwind in flowcontrol) then
+ cg.g_local_unwind(current_asmdata.CurrAsmList,current_procinfo.CurrBreakLabel)
+ else
+ cg.a_jmp_always(current_asmdata.CurrAsmList,current_procinfo.CurrBreakLabel)
+ end
+ else
+ CGMessage(cg_e_break_not_allowed);
+ end;
+
+
+{*****************************************************************************
+ SecondContinueN
+*****************************************************************************}
+
+ procedure tcgcontinuenode.pass_generate_code;
+ begin
+ location_reset(location,LOC_VOID,OS_NO);
+
+ include(flowcontrol,fc_continue);
+ if current_procinfo.CurrContinueLabel<>nil then
+ begin
+{$ifdef OLDREGVARS}
+ load_all_regvars(current_asmdata.CurrAsmList);
+{$endif OLDREGVARS}
+ if (fc_unwind in flowcontrol) then
+ cg.g_local_unwind(current_asmdata.CurrAsmList,current_procinfo.CurrContinueLabel)
+ else
+ cg.a_jmp_always(current_asmdata.CurrAsmList,current_procinfo.CurrContinueLabel)
+ end
+ else
+ CGMessage(cg_e_continue_not_allowed);
+ end;
+
+
+{*****************************************************************************
+ SecondGoto
+*****************************************************************************}
+
+ procedure tcggotonode.pass_generate_code;
+
+ begin
+ location_reset(location,LOC_VOID,OS_NO);
+
+ include(flowcontrol,fc_gotolabel);
+{$ifdef OLDREGVARS}
+ load_all_regvars(current_asmdata.CurrAsmList);
+{$endif OLDREGVARS}
+ cg.a_jmp_always(current_asmdata.CurrAsmList,tcglabelnode(labelnode).getasmlabel)
+ end;
+
+
+{*****************************************************************************
+ SecondLabel
+*****************************************************************************}
+
+ function tcglabelnode.getasmlabel : tasmlabel;
+ begin
+ if not(assigned(asmlabel)) then
+ { labsym is not set in inlined procedures, but since assembler }
+ { routines can't be inlined, that shouldn't matter }
+ if assigned(labsym) and
+ labsym.nonlocal then
+ current_asmdata.getglobaljumplabel(asmlabel)
+ else
+ current_asmdata.getjumplabel(asmlabel);
+ result:=asmlabel
+ end;
+
+
+ procedure tcglabelnode.pass_generate_code;
+ begin
+ location_reset(location,LOC_VOID,OS_NO);
+
+ include(flowcontrol,fc_gotolabel);
+{$ifdef OLDREGVARS}
+ load_all_regvars(current_asmdata.CurrAsmList);
+{$endif OLDREGVARS}
+ cg.a_label(current_asmdata.CurrAsmList,getasmlabel);
+
+ { Write also extra label if this label was referenced from
+ assembler block }
+ if assigned(labsym) and
+ assigned(labsym.asmblocklabel) then
+ cg.a_label(current_asmdata.CurrAsmList,labsym.asmblocklabel);
+
+ secondpass(left);
+ end;
+
+
+{*****************************************************************************
+ SecondRaise
+*****************************************************************************}
+
+ procedure tcgraisenode.pass_generate_code;
+
+ var
+ a : tasmlabel;
+ href2: treference;
+ paraloc1,paraloc2,paraloc3 : tcgpara;
+ begin
+ paraloc1.init;
+ paraloc2.init;
+ paraloc3.init;
+ paramanager.getintparaloc(pocall_default,1,paraloc1);
+ paramanager.getintparaloc(pocall_default,2,paraloc2);
+ paramanager.getintparaloc(pocall_default,3,paraloc3);
+ location_reset(location,LOC_VOID,OS_NO);
+
+ if assigned(left) then
+ begin
+ { multiple parameters? }
+ if assigned(right) then
+ begin
+ { frame tree }
+ if assigned(third) then
+ secondpass(third);
+ secondpass(right);
+ end;
+ secondpass(left);
+ if codegenerror then
+ exit;
+
+ { Push parameters }
+ if assigned(right) then
+ begin
+ { frame tree }
+ if assigned(third) then
+ cg.a_load_loc_cgpara(current_asmdata.CurrAsmList,third.location,paraloc3)
+ else
+ cg.a_load_const_cgpara(current_asmdata.CurrAsmList,OS_INT,0,paraloc3);
+ { push address }
+ cg.a_load_loc_cgpara(current_asmdata.CurrAsmList,right.location,paraloc2);
+ end
+ else
+ begin
+ { get current address }
+ current_asmdata.getaddrlabel(a);
+ cg.a_label(current_asmdata.CurrAsmList,a);
+ reference_reset_symbol(href2,a,0,1);
+ { push current frame }
+ cg.a_load_reg_cgpara(current_asmdata.CurrAsmList,OS_ADDR,NR_FRAME_POINTER_REG,paraloc3);
+ { push current address }
+ if target_info.system <> system_powerpc_macos then
+ cg.a_loadaddr_ref_cgpara(current_asmdata.CurrAsmList,href2,paraloc2)
+ else
+ cg.a_load_const_cgpara(current_asmdata.CurrAsmList,OS_INT,0,paraloc2);
+ end;
+ cg.a_load_loc_cgpara(current_asmdata.CurrAsmList,left.location,paraloc1);
+ paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc1);
+ paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc2);
+ paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc3);
+ cg.allocallcpuregisters(current_asmdata.CurrAsmList);
+ cg.a_call_name(current_asmdata.CurrAsmList,'FPC_RAISEEXCEPTION',false);
+ cg.deallocallcpuregisters(current_asmdata.CurrAsmList);
+ end
+ else
+ begin
+ cg.allocallcpuregisters(current_asmdata.CurrAsmList);
+ cg.a_call_name(current_asmdata.CurrAsmList,'FPC_POPADDRSTACK',false);
+ cg.a_call_name(current_asmdata.CurrAsmList,'FPC_RERAISE',false);
+ cg.deallocallcpuregisters(current_asmdata.CurrAsmList);
+ end;
+ paraloc1.done;
+ paraloc2.done;
+ paraloc3.done;
+ end;
+
+
+{*****************************************************************************
+ SecondTryExcept
+*****************************************************************************}
+
+ var
+ endexceptlabel : tasmlabel;
+
+
+ { does the necessary things to clean up the object stack }
+ { in the except block }
+ procedure cleanupobjectstack;
+ begin
+ cg.g_call(current_asmdata.CurrAsmList,'FPC_DONEEXCEPTION');
+ end;
+
+ { generates code to be executed when another exeception is raised while
+ control is inside except block }
+ procedure handle_nested_exception(list:TAsmList;const t:texceptiontemps;entrylabel:TAsmLabel);
+ var
+ exitlabel: tasmlabel;
+ begin
+ { don't generate line info for internal cleanup }
+ list.concat(tai_marker.create(mark_NoLineInfoStart));
+ current_asmdata.getjumplabel(exitlabel);
+ cg.a_label(list,entrylabel);
+ free_exception(list,t,0,exitlabel,false);
+ { we don't need to save/restore registers here because reraise never }
+ { returns }
+ cg.a_call_name(list,'FPC_RAISE_NESTED',false);
+ cg.a_label(list,exitlabel);
+ cleanupobjectstack;
+ end;
+
+
+ procedure tcgtryexceptnode.pass_generate_code;
+
+ var
+ exceptlabel,doexceptlabel,oldendexceptlabel,
+ lastonlabel,
+ exitexceptlabel,
+ continueexceptlabel,
+ breakexceptlabel,
+ exittrylabel,
+ continuetrylabel,
+ breaktrylabel,
+ doobjectdestroyandreraise,
+ oldCurrExitLabel,
+ oldContinueLabel,
+ oldBreakLabel : tasmlabel;
+ oldflowcontrol,tryflowcontrol,
+ exceptflowcontrol : tflowcontrol;
+ destroytemps,
+ excepttemps : texceptiontemps;
+ label
+ errorexit;
+ begin
+ location_reset(location,LOC_VOID,OS_NO);
+
+ oldflowcontrol:=flowcontrol;
+ flowcontrol:=[fc_inflowcontrol];
+ { this can be called recursivly }
+ oldBreakLabel:=nil;
+ oldContinueLabel:=nil;
+ oldendexceptlabel:=endexceptlabel;
+
+ { save the old labels for control flow statements }
+ oldCurrExitLabel:=current_procinfo.CurrExitLabel;
+ if assigned(current_procinfo.CurrBreakLabel) then
+ begin
+ oldContinueLabel:=current_procinfo.CurrContinueLabel;
+ oldBreakLabel:=current_procinfo.CurrBreakLabel;
+ end;
+
+ { get new labels for the control flow statements }
+ current_asmdata.getjumplabel(exittrylabel);
+ current_asmdata.getjumplabel(exitexceptlabel);
+ if assigned(current_procinfo.CurrBreakLabel) then
+ begin
+ current_asmdata.getjumplabel(breaktrylabel);
+ current_asmdata.getjumplabel(continuetrylabel);
+ current_asmdata.getjumplabel(breakexceptlabel);
+ current_asmdata.getjumplabel(continueexceptlabel);
+ end;
+
+ current_asmdata.getjumplabel(exceptlabel);
+ current_asmdata.getjumplabel(doexceptlabel);
+ current_asmdata.getjumplabel(endexceptlabel);
+ current_asmdata.getjumplabel(lastonlabel);
+
+ get_exception_temps(current_asmdata.CurrAsmList,excepttemps);
+ new_exception(current_asmdata.CurrAsmList,excepttemps,exceptlabel);
+
+ { try block }
+ { set control flow labels for the try block }
+ current_procinfo.CurrExitLabel:=exittrylabel;
+ if assigned(oldBreakLabel) then
+ begin
+ current_procinfo.CurrContinueLabel:=continuetrylabel;
+ current_procinfo.CurrBreakLabel:=breaktrylabel;
+ end;
+
+ flowcontrol:=[fc_inflowcontrol];
+ secondpass(left);
+ tryflowcontrol:=flowcontrol;
+ if codegenerror then
+ goto errorexit;
+
+ { don't generate line info for internal cleanup }
+ current_asmdata.CurrAsmList.concat(tai_marker.create(mark_NoLineInfoStart));
+
+ cg.a_label(current_asmdata.CurrAsmList,exceptlabel);
+
+ free_exception(current_asmdata.CurrAsmList, excepttemps, 0, endexceptlabel, false);
+
+ cg.a_label(current_asmdata.CurrAsmList,doexceptlabel);
+
+ { end cleanup }
+ current_asmdata.CurrAsmList.concat(tai_marker.create(mark_NoLineInfoEnd));
+
+ { set control flow labels for the except block }
+ { and the on statements }
+ current_procinfo.CurrExitLabel:=exitexceptlabel;
+ if assigned(oldBreakLabel) then
+ begin
+ current_procinfo.CurrContinueLabel:=continueexceptlabel;
+ current_procinfo.CurrBreakLabel:=breakexceptlabel;
+ end;
+
+ flowcontrol:=[fc_inflowcontrol];
+ { on statements }
+ if assigned(right) then
+ secondpass(right);
+
+ { don't generate line info for internal cleanup }
+ current_asmdata.CurrAsmList.concat(tai_marker.create(mark_NoLineInfoStart));
+
+ cg.a_label(current_asmdata.CurrAsmList,lastonlabel);
+ { default handling except handling }
+ if assigned(t1) then
+ begin
+ { FPC_CATCHES with 'default handler' flag (=-1) need no longer be called,
+ it doesn't change any state and its return value is ignored (Sergei)
+ }
+
+ { the destruction of the exception object must be also }
+ { guarded by an exception frame, but it can be omitted }
+ { if there's no user code in 'except' block }
+
+ if not (has_no_code(t1)) then
+ begin
+ current_asmdata.getjumplabel(doobjectdestroyandreraise);
+
+ get_exception_temps(current_asmdata.CurrAsmList,destroytemps);
+ new_exception(current_asmdata.CurrAsmList,destroytemps,doobjectdestroyandreraise);
+
+ { except block needs line info }
+ current_asmdata.CurrAsmList.concat(tai_marker.create(mark_NoLineInfoEnd));
+
+ { here we don't have to reset flowcontrol }
+ { the default and on flowcontrols are handled equal }
+ secondpass(t1);
+ exceptflowcontrol:=flowcontrol;
+
+ handle_nested_exception(current_asmdata.CurrAsmList,destroytemps,doobjectdestroyandreraise);
+
+ unget_exception_temps(current_asmdata.CurrAsmList,destroytemps);
+ cg.a_jmp_always(current_asmdata.CurrAsmList,endexceptlabel);
+ end
+ else
+ begin
+ exceptflowcontrol:=flowcontrol;
+ cleanupobjectstack;
+ cg.a_jmp_always(current_asmdata.CurrAsmList,endexceptlabel);
+ end;
+ end
+ else
+ begin
+ cg.a_call_name(current_asmdata.CurrAsmList,'FPC_RERAISE',false);
+ exceptflowcontrol:=flowcontrol;
+ end;
+
+ if fc_exit in exceptflowcontrol then
+ begin
+ { do some magic for exit in the try block }
+ cg.a_label(current_asmdata.CurrAsmList,exitexceptlabel);
+ { we must also destroy the address frame which guards }
+ { exception object }
+ cg.g_call(current_asmdata.CurrAsmList,'FPC_POPADDRSTACK');
+ cg.g_exception_reason_load(current_asmdata.CurrAsmList,excepttemps.reasonbuf);
+ cleanupobjectstack;
+ cg.a_jmp_always(current_asmdata.CurrAsmList,oldCurrExitLabel);
+ { from g_exception_reason_load }
+ cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_FUNCTION_RESULT_REG);
+ end;
+
+ if fc_break in exceptflowcontrol then
+ begin
+ cg.a_label(current_asmdata.CurrAsmList,breakexceptlabel);
+ { we must also destroy the address frame which guards }
+ { exception object }
+ cg.g_call(current_asmdata.CurrAsmList,'FPC_POPADDRSTACK');
+ cg.g_exception_reason_load(current_asmdata.CurrAsmList,excepttemps.reasonbuf);
+ cleanupobjectstack;
+ cg.a_jmp_always(current_asmdata.CurrAsmList,oldBreakLabel);
+ { from g_exception_reason_load }
+ cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_FUNCTION_RESULT_REG);
+ end;
+
+ if fc_continue in exceptflowcontrol then
+ begin
+ cg.a_label(current_asmdata.CurrAsmList,continueexceptlabel);
+ { we must also destroy the address frame which guards }
+ { exception object }
+ cg.g_call(current_asmdata.CurrAsmList,'FPC_POPADDRSTACK');
+ cg.g_exception_reason_load(current_asmdata.CurrAsmList,excepttemps.reasonbuf);
+ cleanupobjectstack;
+ cg.a_jmp_always(current_asmdata.CurrAsmList,oldContinueLabel);
+ { from g_exception_reason_load }
+ cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_FUNCTION_RESULT_REG);
+ end;
+
+ if fc_exit in tryflowcontrol then
+ begin
+ { do some magic for exit in the try block }
+ cg.a_label(current_asmdata.CurrAsmList,exittrylabel);
+ cg.g_call(current_asmdata.CurrAsmList,'FPC_POPADDRSTACK');
+ cg.g_exception_reason_load(current_asmdata.CurrAsmList,excepttemps.reasonbuf);
+ cg.a_jmp_always(current_asmdata.CurrAsmList,oldCurrExitLabel);
+ { from g_exception_reason_load }
+ cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_FUNCTION_RESULT_REG);
+ end;
+
+ if fc_break in tryflowcontrol then
+ begin
+ cg.a_label(current_asmdata.CurrAsmList,breaktrylabel);
+ cg.g_call(current_asmdata.CurrAsmList,'FPC_POPADDRSTACK');
+ cg.g_exception_reason_load(current_asmdata.CurrAsmList,excepttemps.reasonbuf);
+ cg.a_jmp_always(current_asmdata.CurrAsmList,oldBreakLabel);
+ { from g_exception_reason_load }
+ cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_FUNCTION_RESULT_REG);
+ end;
+
+ if fc_continue in tryflowcontrol then
+ begin
+ cg.a_label(current_asmdata.CurrAsmList,continuetrylabel);
+ cg.g_call(current_asmdata.CurrAsmList,'FPC_POPADDRSTACK');
+ cg.g_exception_reason_load(current_asmdata.CurrAsmList,excepttemps.reasonbuf);
+ cg.a_jmp_always(current_asmdata.CurrAsmList,oldContinueLabel);
+ { from g_exception_reason_load }
+ cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_FUNCTION_RESULT_REG);
+ end;
+ unget_exception_temps(current_asmdata.CurrAsmList,excepttemps);
+ cg.a_label(current_asmdata.CurrAsmList,endexceptlabel);
+
+ { end cleanup }
+ current_asmdata.CurrAsmList.concat(tai_marker.create(mark_NoLineInfoEnd));
+
+ errorexit:
+ { restore all saved labels }
+ endexceptlabel:=oldendexceptlabel;
+
+ { restore the control flow labels }
+ current_procinfo.CurrExitLabel:=oldCurrExitLabel;
+ if assigned(oldBreakLabel) then
+ begin
+ current_procinfo.CurrContinueLabel:=oldContinueLabel;
+ current_procinfo.CurrBreakLabel:=oldBreakLabel;
+ end;
+
+ { return all used control flow statements }
+ flowcontrol:=oldflowcontrol+(exceptflowcontrol +
+ tryflowcontrol - [fc_inflowcontrol]);
+ end;
+
+
+ procedure tcgonnode.pass_generate_code;
+ var
+ nextonlabel,
+ exitonlabel,
+ continueonlabel,
+ breakonlabel,
+ oldCurrExitLabel,
+ oldContinueLabel,
+ doobjectdestroyandreraise,
+ oldBreakLabel : tasmlabel;
+ oldflowcontrol : tflowcontrol;
+ excepttemps : texceptiontemps;
+ href2: treference;
+ paraloc1 : tcgpara;
+ exceptvarsym : tlocalvarsym;
+ begin
+ paraloc1.init;
+ location_reset(location,LOC_VOID,OS_NO);
+
+ oldflowcontrol:=flowcontrol;
+ flowcontrol:=[fc_inflowcontrol];
+ current_asmdata.getjumplabel(nextonlabel);
+
+ { send the vmt parameter }
+ reference_reset_symbol(href2,current_asmdata.RefAsmSymbol(excepttype.vmt_mangledname),0,sizeof(pint));
+ paramanager.getintparaloc(pocall_default,1,paraloc1);
+ cg.a_loadaddr_ref_cgpara(current_asmdata.CurrAsmList,href2,paraloc1);
+ paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc1);
+ cg.g_call(current_asmdata.CurrAsmList,'FPC_CATCHES');
+
+ cg.a_reg_alloc(current_asmdata.CurrAsmList,NR_FUNCTION_RESULT_REG);
+ { is it this catch? No. go to next onlabel }
+ cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,OS_ADDR,OC_EQ,0,NR_FUNCTION_RESULT_REG,nextonlabel);
+
+ { Retrieve exception variable }
+ if assigned(excepTSymtable) then
+ exceptvarsym:=tlocalvarsym(excepTSymtable.SymList[0])
+ else
+ exceptvarsym:=nil;
+
+ if assigned(exceptvarsym) then
+ begin
+ exceptvarsym.localloc.loc:=LOC_REFERENCE;
+ exceptvarsym.localloc.size:=OS_ADDR;
+ tg.GetLocal(current_asmdata.CurrAsmList,sizeof(pint),voidpointertype,exceptvarsym.localloc.reference);
+ cg.a_load_reg_ref(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,NR_FUNCTION_RESULT_REG,exceptvarsym.localloc.reference);
+ end;
+ cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_FUNCTION_RESULT_REG);
+
+ { in the case that another exception is risen
+ we've to destroy the old one }
+ current_asmdata.getjumplabel(doobjectdestroyandreraise);
+
+ { call setjmp, and jump to finally label on non-zero result }
+ get_exception_temps(current_asmdata.CurrAsmList,excepttemps);
+ new_exception(current_asmdata.CurrAsmList,excepttemps,doobjectdestroyandreraise);
+
+ oldBreakLabel:=nil;
+ oldContinueLabel:=nil;
+ if assigned(right) then
+ begin
+ oldCurrExitLabel:=current_procinfo.CurrExitLabel;
+ current_asmdata.getjumplabel(exitonlabel);
+ current_procinfo.CurrExitLabel:=exitonlabel;
+ if assigned(current_procinfo.CurrBreakLabel) then
+ begin
+ oldContinueLabel:=current_procinfo.CurrContinueLabel;
+ oldBreakLabel:=current_procinfo.CurrBreakLabel;
+ current_asmdata.getjumplabel(breakonlabel);
+ current_asmdata.getjumplabel(continueonlabel);
+ current_procinfo.CurrContinueLabel:=continueonlabel;
+ current_procinfo.CurrBreakLabel:=breakonlabel;
+ end;
+
+ secondpass(right);
+ end;
+
+ handle_nested_exception(current_asmdata.CurrAsmList,excepttemps,doobjectdestroyandreraise);
+
+ { clear some stuff }
+ if assigned(exceptvarsym) then
+ begin
+ tg.UngetLocal(current_asmdata.CurrAsmList,exceptvarsym.localloc.reference);
+ exceptvarsym.localloc.loc:=LOC_INVALID;
+ end;
+ cg.a_jmp_always(current_asmdata.CurrAsmList,endexceptlabel);
+
+ if assigned(right) then
+ begin
+ { special handling for control flow instructions }
+ if fc_exit in flowcontrol then
+ begin
+ { the address and object pop does secondtryexcept }
+ cg.a_label(current_asmdata.CurrAsmList,exitonlabel);
+ cg.a_jmp_always(current_asmdata.CurrAsmList,oldCurrExitLabel);
+ end;
+
+ if fc_break in flowcontrol then
+ begin
+ { the address and object pop does secondtryexcept }
+ cg.a_label(current_asmdata.CurrAsmList,breakonlabel);
+ cg.a_jmp_always(current_asmdata.CurrAsmList,oldBreakLabel);
+ end;
+
+ if fc_continue in flowcontrol then
+ begin
+ { the address and object pop does secondtryexcept }
+ cg.a_label(current_asmdata.CurrAsmList,continueonlabel);
+ cg.a_jmp_always(current_asmdata.CurrAsmList,oldContinueLabel);
+ end;
+
+ current_procinfo.CurrExitLabel:=oldCurrExitLabel;
+ if assigned(oldBreakLabel) then
+ begin
+ current_procinfo.CurrContinueLabel:=oldContinueLabel;
+ current_procinfo.CurrBreakLabel:=oldBreakLabel;
+ end;
+ end;
+
+ unget_exception_temps(current_asmdata.CurrAsmList,excepttemps);
+ cg.a_label(current_asmdata.CurrAsmList,nextonlabel);
+ flowcontrol:=oldflowcontrol+(flowcontrol-[fc_inflowcontrol]);
+ paraloc1.done;
+ current_asmdata.CurrAsmList.concat(tai_marker.create(mark_NoLineInfoEnd));
+
+ { next on node }
+ if assigned(left) then
+ secondpass(left);
+ end;
+
+{*****************************************************************************
+ SecondTryFinally
+*****************************************************************************}
+
+ procedure tcgtryfinallynode.handle_safecall_exception;
+ var
+ cgpara: tcgpara;
+ selfsym: tparavarsym;
+ begin
+ { call fpc_safecallhandler, passing self for methods of classes,
+ nil otherwise. }
+ cgpara.init;
+ paramanager.getintparaloc(pocall_default,1,cgpara);
+ if is_class(current_procinfo.procdef.struct) then
+ begin
+ selfsym:=tparavarsym(current_procinfo.procdef.parast.Find('self'));
+ if (selfsym=nil) or (selfsym.typ<>paravarsym) then
+ InternalError(2011123101);
+ cg.a_load_loc_cgpara(current_asmdata.CurrAsmList,selfsym.localloc,cgpara);
+ end
+ else
+ cg.a_load_const_cgpara(current_asmdata.CurrAsmList,OS_ADDR,0,cgpara);
+ paramanager.freecgpara(current_asmdata.CurrAsmList,cgpara);
+ cgpara.done;
+ cg.g_call(current_asmdata.CurrAsmList,'FPC_SAFECALLHANDLER');
+ end;
+
+ procedure tcgtryfinallynode.pass_generate_code;
+ var
+ reraiselabel,
+ finallylabel,
+ endfinallylabel,
+ exitfinallylabel,
+ continuefinallylabel,
+ breakfinallylabel,
+ oldCurrExitLabel,
+ oldContinueLabel,
+ oldBreakLabel : tasmlabel;
+ oldflowcontrol,tryflowcontrol : tflowcontrol;
+ decconst : longint;
+ excepttemps : texceptiontemps;
+ begin
+ location_reset(location,LOC_VOID,OS_NO);
+
+ { check if child nodes do a break/continue/exit }
+ oldflowcontrol:=flowcontrol;
+ flowcontrol:=[fc_inflowcontrol];
+ current_asmdata.getjumplabel(finallylabel);
+ current_asmdata.getjumplabel(endfinallylabel);
+ current_asmdata.getjumplabel(reraiselabel);
+
+ { the finally block must catch break, continue and exit }
+ { statements }
+ oldCurrExitLabel:=current_procinfo.CurrExitLabel;
+ if implicitframe then
+ exitfinallylabel:=finallylabel
+ else
+ current_asmdata.getjumplabel(exitfinallylabel);
+ current_procinfo.CurrExitLabel:=exitfinallylabel;
+ if assigned(current_procinfo.CurrBreakLabel) then
+ begin
+ oldContinueLabel:=current_procinfo.CurrContinueLabel;
+ oldBreakLabel:=current_procinfo.CurrBreakLabel;
+ if implicitframe then
+ begin
+ breakfinallylabel:=finallylabel;
+ continuefinallylabel:=finallylabel;
+ end
+ else
+ begin
+ current_asmdata.getjumplabel(breakfinallylabel);
+ current_asmdata.getjumplabel(continuefinallylabel);
+ end;
+ current_procinfo.CurrContinueLabel:=continuefinallylabel;
+ current_procinfo.CurrBreakLabel:=breakfinallylabel;
+ end;
+
+ { call setjmp, and jump to finally label on non-zero result }
+ get_exception_temps(current_asmdata.CurrAsmList,excepttemps);
+ new_exception(current_asmdata.CurrAsmList,excepttemps,finallylabel);
+
+ { try code }
+ if assigned(left) then
+ begin
+ secondpass(left);
+ tryflowcontrol:=flowcontrol;
+ if codegenerror then
+ exit;
+ end;
+
+ { don't generate line info for internal cleanup }
+ current_asmdata.CurrAsmList.concat(tai_marker.create(mark_NoLineInfoStart));
+
+ cg.a_label(current_asmdata.CurrAsmList,finallylabel);
+ { just free the frame information }
+ free_exception(current_asmdata.CurrAsmList,excepttemps,1,finallylabel,true);
+
+ { end cleanup }
+ current_asmdata.CurrAsmList.concat(tai_marker.create(mark_NoLineInfoEnd));
+
+ { finally code }
+ flowcontrol:=[fc_inflowcontrol];
+ secondpass(right);
+ { goto is allowed if it stays inside the finally block,
+ this is checked using the exception block number }
+ if (flowcontrol-[fc_gotolabel])<>[fc_inflowcontrol] then
+ CGMessage(cg_e_control_flow_outside_finally);
+ if codegenerror then
+ exit;
+
+ { don't generate line info for internal cleanup }
+ current_asmdata.CurrAsmList.concat(tai_marker.create(mark_NoLineInfoStart));
+
+ { the value should now be in the exception handler }
+ cg.g_exception_reason_load(current_asmdata.CurrAsmList,excepttemps.reasonbuf);
+ if implicitframe then
+ begin
+ cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,OS_INT,OC_EQ,0,NR_FUNCTION_RESULT_REG,endfinallylabel);
+ { from g_exception_reason_load }
+ cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_FUNCTION_RESULT_REG);
+ { finally code only needed to be executed on exception }
+ flowcontrol:=[fc_inflowcontrol];
+ secondpass(t1);
+ if flowcontrol<>[fc_inflowcontrol] then
+ CGMessage(cg_e_control_flow_outside_finally);
+ if codegenerror then
+ exit;
+{$if defined(x86) or defined(arm)}
+ if (tf_safecall_exceptions in target_info.flags) and
+ (current_procinfo.procdef.proccalloption=pocall_safecall) then
+ handle_safecall_exception
+ else
+{$endif}
+ cg.a_call_name(current_asmdata.CurrAsmList,'FPC_RERAISE',false);
+ end
+ else
+ begin
+ cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,OS_INT,OC_EQ,0,NR_FUNCTION_RESULT_REG,endfinallylabel);
+ if (tryflowcontrol*[fc_exit,fc_break,fc_continue]<>[]) then
+ begin
+ cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_SUB,OS_INT,1,NR_FUNCTION_RESULT_REG);
+ cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,OS_INT,OC_EQ,0,NR_FUNCTION_RESULT_REG,reraiselabel);
+ if fc_exit in tryflowcontrol then
+ begin
+ cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_SUB,OS_INT,1,NR_FUNCTION_RESULT_REG);
+ cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,OS_INT,OC_EQ,0,NR_FUNCTION_RESULT_REG,oldCurrExitLabel);
+ decconst:=1;
+ end
+ else
+ decconst:=2;
+ if fc_break in tryflowcontrol then
+ begin
+ cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_SUB,OS_INT,decconst,NR_FUNCTION_RESULT_REG);
+ cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,OS_INT,OC_EQ,0,NR_FUNCTION_RESULT_REG,oldBreakLabel);
+ decconst:=1;
+ end
+ else
+ inc(decconst);
+ if fc_continue in tryflowcontrol then
+ begin
+ cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_SUB,OS_INT,decconst,NR_FUNCTION_RESULT_REG);
+ cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,OS_INT,OC_EQ,0,NR_FUNCTION_RESULT_REG,oldContinueLabel);
+ end;
+ end;
+ cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_FUNCTION_RESULT_REG);
+ cg.a_label(current_asmdata.CurrAsmList,reraiselabel);
+ cg.a_call_name(current_asmdata.CurrAsmList,'FPC_RERAISE',false);
+ { do some magic for exit,break,continue in the try block }
+ if fc_exit in tryflowcontrol then
+ begin
+ cg.a_label(current_asmdata.CurrAsmList,exitfinallylabel);
+ cg.g_exception_reason_load(current_asmdata.CurrAsmList,excepttemps.reasonbuf);
+ cg.g_exception_reason_save_const(current_asmdata.CurrAsmList,excepttemps.reasonbuf,2);
+ cg.a_jmp_always(current_asmdata.CurrAsmList,finallylabel);
+ { from g_exception_reason_load }
+ cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_FUNCTION_RESULT_REG);
+ end;
+ if fc_break in tryflowcontrol then
+ begin
+ cg.a_label(current_asmdata.CurrAsmList,breakfinallylabel);
+ cg.g_exception_reason_load(current_asmdata.CurrAsmList,excepttemps.reasonbuf);
+ cg.g_exception_reason_save_const(current_asmdata.CurrAsmList,excepttemps.reasonbuf,3);
+ cg.a_jmp_always(current_asmdata.CurrAsmList,finallylabel);
+ { from g_exception_reason_load }
+ cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_FUNCTION_RESULT_REG);
+ end;
+ if fc_continue in tryflowcontrol then
+ begin
+ cg.a_label(current_asmdata.CurrAsmList,continuefinallylabel);
+ cg.g_exception_reason_load(current_asmdata.CurrAsmList,excepttemps.reasonbuf);
+ cg.g_exception_reason_save_const(current_asmdata.CurrAsmList,excepttemps.reasonbuf,4);
+ cg.a_jmp_always(current_asmdata.CurrAsmList,finallylabel);
+ { from g_exception_reason_load }
+ cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_FUNCTION_RESULT_REG);
+ end;
+ end;
+ unget_exception_temps(current_asmdata.CurrAsmList,excepttemps);
+ cg.a_label(current_asmdata.CurrAsmList,endfinallylabel);
+
+ { end cleanup }
+ current_asmdata.CurrAsmList.concat(tai_marker.create(mark_NoLineInfoEnd));
+
+ current_procinfo.CurrExitLabel:=oldCurrExitLabel;
+ if assigned(current_procinfo.CurrBreakLabel) then
+ begin
+ current_procinfo.CurrContinueLabel:=oldContinueLabel;
+ current_procinfo.CurrBreakLabel:=oldBreakLabel;
+ end;
+ flowcontrol:=oldflowcontrol+(tryflowcontrol-[fc_inflowcontrol]);
+ end;
+
+
+begin
+ cwhilerepeatnode:=tcgwhilerepeatnode;
+ cifnode:=tcgifnode;
+ cfornode:=tcgfornode;
+ cexitnode:=tcgexitnode;
+ cbreaknode:=tcgbreaknode;
+ ccontinuenode:=tcgcontinuenode;
+ cgotonode:=tcggotonode;
+ clabelnode:=tcglabelnode;
+ craisenode:=tcgraisenode;
+ ctryexceptnode:=tcgtryexceptnode;
+ ctryfinallynode:=tcgtryfinallynode;
+ connode:=tcgonnode;
+end.
diff --git a/closures/compiler/ncginl.pas b/closures/compiler/ncginl.pas
new file mode 100644
index 0000000000..d2b8d84a8f
--- /dev/null
+++ b/closures/compiler/ncginl.pas
@@ -0,0 +1,835 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl and Carl Eric Codere
+
+ Generate generic inline nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit ncginl;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,ninl;
+
+ type
+ tcginlinenode = class(tinlinenode)
+ procedure pass_generate_code;override;
+ procedure second_assert;virtual;
+ procedure second_sizeoftypeof;virtual;
+ procedure second_length;virtual;
+ procedure second_predsucc;virtual;
+ procedure second_incdec;virtual;
+ procedure second_typeinfo;virtual;
+ procedure second_includeexclude;virtual;
+ procedure second_pi; virtual;
+ procedure second_arctan_real; virtual;
+ procedure second_abs_real; virtual;
+ procedure second_sqr_real; virtual;
+ procedure second_sqrt_real; virtual;
+ procedure second_ln_real; virtual;
+ procedure second_cos_real; virtual;
+ procedure second_sin_real; virtual;
+ procedure second_assigned; virtual;
+ procedure second_get_frame;virtual;
+ procedure second_get_caller_frame;virtual;
+ procedure second_get_caller_addr;virtual;
+ procedure second_prefetch; virtual;
+ procedure second_round_real; virtual;
+ procedure second_trunc_real; virtual;
+ procedure second_abs_long; virtual;
+ procedure second_rox; virtual;
+ procedure second_sar; virtual;
+ procedure second_bsfbsr; virtual;
+ end;
+
+implementation
+
+ uses
+ globtype,systems,constexp,
+ cutils,verbose,globals,fmodule,
+ symconst,symdef,defutil,symsym,
+ aasmbase,aasmtai,aasmdata,aasmcpu,parabase,
+ cgbase,pass_1,pass_2,
+ cpuinfo,cpubase,paramgr,procinfo,
+ nbas,ncon,ncal,ncnv,nld,ncgrtti,
+ tgobj,ncgutil,
+ cgutils,cgobj
+{$ifndef cpu64bitalu}
+ ,cg64f32
+{$endif not cpu64bitalu}
+ ;
+
+
+{*****************************************************************************
+ TCGINLINENODE
+*****************************************************************************}
+
+
+ procedure tcginlinenode.pass_generate_code;
+ begin
+ location_reset(location,LOC_VOID,OS_NO);
+
+ case inlinenumber of
+ in_assert_x_y:
+ second_Assert;
+ in_sizeof_x,
+ in_typeof_x :
+ second_SizeofTypeOf;
+ in_length_x :
+ second_Length;
+ in_pred_x,
+ in_succ_x:
+ second_PredSucc;
+ in_dec_x,
+ in_inc_x :
+ second_IncDec;
+ in_typeinfo_x:
+ second_TypeInfo;
+ in_include_x_y,
+ in_exclude_x_y:
+ second_IncludeExclude;
+ in_pi_real:
+ second_pi;
+ in_sin_real:
+ second_sin_real;
+ in_arctan_real:
+ second_arctan_real;
+ in_abs_real:
+ second_abs_real;
+ in_abs_long:
+ second_abs_long;
+ in_round_real:
+ second_round_real;
+ in_trunc_real:
+ second_trunc_real;
+ in_sqr_real:
+ second_sqr_real;
+ in_sqrt_real:
+ second_sqrt_real;
+ in_ln_real:
+ second_ln_real;
+ in_cos_real:
+ second_cos_real;
+ in_prefetch_var:
+ second_prefetch;
+ in_assigned_x:
+ second_assigned;
+ in_get_frame:
+ second_get_frame;
+ in_get_caller_frame:
+ second_get_caller_frame;
+ in_get_caller_addr:
+ second_get_caller_addr;
+ in_unaligned_x:
+ begin
+ secondpass(tcallparanode(left).left);
+ location:=tcallparanode(left).left.location;
+ if location.loc in [LOC_CREFERENCE,LOC_REFERENCE] then
+ location.reference.alignment:=1;
+ end;
+{$ifdef SUPPORT_MMX}
+ in_mmx_pcmpeqb..in_mmx_pcmpgtw:
+ begin
+ location_reset(location,LOC_MMXREGISTER,OS_NO);
+ if left.location.loc=LOC_REGISTER then
+ begin
+ {!!!!!!!}
+ end
+ else if tcallparanode(left).left.location.loc=LOC_REGISTER then
+ begin
+ {!!!!!!!}
+ end
+ else
+ begin
+ {!!!!!!!}
+ end;
+ end;
+{$endif SUPPORT_MMX}
+ in_rol_x,
+ in_rol_x_y,
+ in_ror_x,
+ in_ror_x_y:
+ second_rox;
+ in_sar_x,
+ in_sar_x_y:
+ second_sar;
+ in_bsf_x,
+ in_bsr_x:
+ second_BsfBsr;
+ else internalerror(9);
+ end;
+ end;
+
+
+{*****************************************************************************
+ ASSERT GENERIC HANDLING
+*****************************************************************************}
+ procedure tcginlinenode.second_Assert;
+ var
+ hp2,hp3 : tnode;
+ otlabel,oflabel : tasmlabel;
+ paraloc1,paraloc2,
+ paraloc3,paraloc4 : tcgpara;
+ begin
+ { the node should be removed in the firstpass }
+ if not (cs_do_assertion in current_settings.localswitches) then
+ internalerror(7123458);
+ paraloc1.init;
+ paraloc2.init;
+ paraloc3.init;
+ paraloc4.init;
+ paramanager.getintparaloc(pocall_default,1,paraloc1);
+ paramanager.getintparaloc(pocall_default,2,paraloc2);
+ paramanager.getintparaloc(pocall_default,3,paraloc3);
+ paramanager.getintparaloc(pocall_default,4,paraloc4);
+ otlabel:=current_procinfo.CurrTrueLabel;
+ oflabel:=current_procinfo.CurrFalseLabel;
+ current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
+ current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel);
+ secondpass(tcallparanode(left).left);
+ maketojumpbool(current_asmdata.CurrAsmList,tcallparanode(left).left,lr_load_regvars);
+ cg.a_label(current_asmdata.CurrAsmList,current_procinfo.CurrFalseLabel);
+ { First call secondpass() before we can push the parameters, otherwise
+ parameters allocated in the registers can be destroyed }
+ { generate filename string parameter }
+ hp2:=ctypeconvnode.create(cstringconstnode.createstr(current_module.sourcefiles.get_file_name(current_filepos.fileindex)),cshortstringtype);
+ firstpass(hp2);
+ secondpass(hp2);
+ if codegenerror then
+ exit;
+ { message parameter }
+ hp3:=tcallparanode(tcallparanode(left).right).left;
+ secondpass(hp3);
+ if codegenerror then
+ exit;
+ { push erroraddr }
+ cg.a_load_reg_cgpara(current_asmdata.CurrAsmList,OS_ADDR,NR_FRAME_POINTER_REG,paraloc4);
+ { push lineno }
+ cg.a_load_const_cgpara(current_asmdata.CurrAsmList,OS_INT,current_filepos.line,paraloc3);
+ { push filename }
+ cg.a_loadaddr_ref_cgpara(current_asmdata.CurrAsmList,hp2.location.reference,paraloc2);
+ { push msg }
+ cg.a_loadaddr_ref_cgpara(current_asmdata.CurrAsmList,hp3.location.reference,paraloc1);
+ { call }
+ paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc1);
+ paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc2);
+ paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc3);
+ paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc4);
+ cg.allocallcpuregisters(current_asmdata.CurrAsmList);
+ cg.a_call_name(current_asmdata.CurrAsmList,'FPC_ASSERT',false);
+ cg.deallocallcpuregisters(current_asmdata.CurrAsmList);
+ location_freetemp(current_asmdata.CurrAsmList,hp3.location);
+ location_freetemp(current_asmdata.CurrAsmList,hp2.location);
+ cg.a_label(current_asmdata.CurrAsmList,current_procinfo.CurrTrueLabel);
+ current_procinfo.CurrTrueLabel:=otlabel;
+ current_procinfo.CurrFalseLabel:=oflabel;
+ paraloc1.done;
+ paraloc2.done;
+ paraloc3.done;
+ paraloc4.done;
+ hp2.free;
+ end;
+
+
+{*****************************************************************************
+ SIZEOF / TYPEOF GENERIC HANDLING
+*****************************************************************************}
+
+ { second_handle_ the sizeof and typeof routines }
+ procedure tcginlinenode.second_SizeOfTypeOf;
+ var
+ href,
+ hrefvmt : treference;
+ hregister : tregister;
+ begin
+ if inlinenumber=in_sizeof_x then
+ location_reset(location,LOC_REGISTER,def_cgsize(resultdef))
+ else
+ location_reset(location,LOC_REGISTER,OS_ADDR);
+ { for both cases load vmt }
+ if left.nodetype=typen then
+ begin
+ hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
+ reference_reset_symbol(href,current_asmdata.RefAsmSymbol(tobjectdef(left.resultdef).vmt_mangledname),0,sizeof(pint));
+ cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,href,hregister);
+ end
+ else
+ begin
+ secondpass(left);
+ hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
+
+ { handle self inside a method of a class }
+ case left.location.loc of
+ LOC_CREGISTER,
+ LOC_REGISTER :
+ begin
+ if (left.resultdef.typ=classrefdef) or
+ (po_staticmethod in current_procinfo.procdef.procoptions) then
+ cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,left.location.register,hregister)
+ else
+ begin
+ { load VMT pointer }
+ reference_reset_base(hrefvmt,left.location.register,tobjectdef(left.resultdef).vmt_offset,sizeof(pint));
+ cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,hrefvmt,hregister);
+ end
+ end;
+ LOC_REFERENCE,
+ LOC_CREFERENCE :
+ begin
+ if is_class(left.resultdef) then
+ begin
+ { deref class }
+ cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,left.location.reference,hregister);
+ cg.g_maybe_testself(current_asmdata.CurrAsmList,hregister);
+ { load VMT pointer }
+ reference_reset_base(hrefvmt,hregister,tobjectdef(left.resultdef).vmt_offset,sizeof(pint));
+ cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,hrefvmt,hregister);
+ end
+ else
+ begin
+ { load VMT pointer, but not for classrefdefs }
+ if (left.resultdef.typ=objectdef) then
+ begin
+ inc(left.location.reference.offset,tobjectdef(left.resultdef).vmt_offset);
+ left.location.reference.alignment:=newalignment(left.location.reference.alignment,tobjectdef(left.resultdef).vmt_offset);
+ end;
+ cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,left.location.reference,hregister);
+ end;
+ end;
+ else
+ internalerror(200301301);
+ end;
+ end;
+ { in sizeof load size }
+ if inlinenumber=in_sizeof_x then
+ begin
+ reference_reset_base(href,hregister,0,sizeof(pint));
+ hregister:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+ cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_INT,OS_INT,href,hregister);
+ end;
+ location.register:=hregister;
+ end;
+
+
+{*****************************************************************************
+ LENGTH GENERIC HANDLING
+*****************************************************************************}
+
+ procedure tcginlinenode.second_Length;
+ var
+ lengthlab : tasmlabel;
+ hregister : tregister;
+ href : treference;
+ begin
+ secondpass(left);
+ if is_shortstring(left.resultdef) then
+ begin
+ location_copy(location,left.location);
+ location.size:=OS_8;
+ end
+ else
+ begin
+ { length in ansi/wide strings is at offset -sizeof(pint) }
+ location_force_reg(current_asmdata.CurrAsmList,left.location,OS_ADDR,false);
+ current_asmdata.getjumplabel(lengthlab);
+ cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,OS_ADDR,OC_EQ,0,left.location.register,lengthlab);
+ if is_widestring(left.resultdef) and (tf_winlikewidestring in target_info.flags) then
+ begin
+ reference_reset_base(href,left.location.register,-sizeof(dword),sizeof(dword));
+ hregister:=cg.makeregsize(current_asmdata.CurrAsmList,left.location.register,OS_INT);
+ cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_32,OS_INT,href,hregister);
+ end
+ else
+ begin
+ reference_reset_base(href,left.location.register,-sizeof(pint),sizeof(pint));
+ hregister:=cg.makeregsize(current_asmdata.CurrAsmList,left.location.register,OS_INT);
+ cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_INT,OS_INT,href,hregister);
+ end;
+ if is_widestring(left.resultdef) then
+ cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_SHR,OS_INT,1,hregister);
+ cg.a_label(current_asmdata.CurrAsmList,lengthlab);
+ location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
+ location.register:=hregister;
+ end;
+ end;
+
+
+{*****************************************************************************
+ PRED/SUCC GENERIC HANDLING
+*****************************************************************************}
+
+ procedure tcginlinenode.second_PredSucc;
+ var
+ cgsize : TCGSize;
+ cgop : topcg;
+ begin
+ secondpass(left);
+ if inlinenumber=in_pred_x then
+ cgop:=OP_SUB
+ else
+ cgop:=OP_ADD;
+ cgsize:=def_cgsize(resultdef);
+
+ { we need a value in a register }
+ location_copy(location,left.location);
+ location_force_reg(current_asmdata.CurrAsmList,location,cgsize,false);
+
+{$ifndef cpu64bitalu}
+ if cgsize in [OS_64,OS_S64] then
+ cg64.a_op64_const_reg(current_asmdata.CurrAsmList,cgop,cgsize,1,location.register64)
+ else
+{$endif not cpu64bitalu}
+ cg.a_op_const_reg(current_asmdata.CurrAsmList,cgop,location.size,1,location.register);
+ end;
+
+
+{*****************************************************************************
+ INC/DEC GENERIC HANDLING
+*****************************************************************************}
+ procedure tcginlinenode.second_IncDec;
+ const
+ addsubop:array[in_inc_x..in_dec_x] of TOpCG=(OP_ADD,OP_SUB);
+ var
+ addvalue : TConstExprInt;
+ addconstant : boolean;
+{$ifndef cpu64bitalu}
+ hregisterhi,
+{$endif not cpu64bitalu}
+ hregister : tregister;
+ cgsize : tcgsize;
+ begin
+ { set defaults }
+ addconstant:=true;
+ { first secondpass second argument, because if the first arg }
+ { is used in that expression then SSL may move it to another }
+ { register }
+ if assigned(tcallparanode(left).right) then
+ secondpass(tcallparanode(tcallparanode(left).right).left);
+ { load first parameter, must be a reference }
+ secondpass(tcallparanode(left).left);
+ cgsize:=def_cgsize(tcallparanode(left).left.resultdef);
+ { get addvalue }
+ case tcallparanode(left).left.resultdef.typ of
+ orddef,
+ enumdef :
+ addvalue:=1;
+ pointerdef :
+ begin
+ if is_void(tpointerdef(tcallparanode(left).left.resultdef).pointeddef) then
+ addvalue:=1
+ else
+ addvalue:=tpointerdef(tcallparanode(left).left.resultdef).pointeddef.size;
+ end;
+ else
+ internalerror(10081);
+ end;
+ { second_ argument specified?, must be a s32bit in register }
+ if assigned(tcallparanode(left).right) then
+ begin
+ { when constant, just multiply the addvalue }
+ if is_constintnode(tcallparanode(tcallparanode(left).right).left) then
+ addvalue:=addvalue*get_ordinal_value(tcallparanode(tcallparanode(left).right).left)
+ else if is_constpointernode(tcallparanode(tcallparanode(left).right).left) then
+ addvalue:=addvalue*tpointerconstnode(tcallparanode(tcallparanode(left).right).left).value
+ else
+ begin
+ location_force_reg(current_asmdata.CurrAsmList,tcallparanode(tcallparanode(left).right).left.location,cgsize,addvalue<=1);
+ hregister:=tcallparanode(tcallparanode(left).right).left.location.register;
+{$ifndef cpu64bitalu}
+ hregisterhi:=tcallparanode(tcallparanode(left).right).left.location.register64.reghi;
+{$endif not cpu64bitalu}
+ { insert multiply with addvalue if its >1 }
+ if addvalue>1 then
+ cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_IMUL,cgsize,addvalue.svalue,hregister);
+ addconstant:=false;
+ end;
+ end;
+ { write the add instruction }
+ if addconstant then
+ begin
+{$ifndef cpu64bitalu}
+ if cgsize in [OS_64,OS_S64] then
+ cg64.a_op64_const_loc(current_asmdata.CurrAsmList,addsubop[inlinenumber],cgsize,addvalue,tcallparanode(left).left.location)
+ else
+{$endif not cpu64bitalu}
+ cg.a_op_const_loc(current_asmdata.CurrAsmList,addsubop[inlinenumber],
+ aint(addvalue.svalue),tcallparanode(left).left.location);
+ end
+ else
+ begin
+{$ifndef cpu64bitalu}
+ if cgsize in [OS_64,OS_S64] then
+ cg64.a_op64_reg_loc(current_asmdata.CurrAsmList,addsubop[inlinenumber],cgsize,
+ joinreg64(hregister,hregisterhi),tcallparanode(left).left.location)
+ else
+{$endif not cpu64bitalu}
+ cg.a_op_reg_loc(current_asmdata.CurrAsmList,addsubop[inlinenumber],
+ hregister,tcallparanode(left).left.location);
+ end;
+ { no overflow checking for pointers (see ninl), and range checking }
+ { is not applicable for them }
+ if (tcallparanode(left).left.resultdef.typ <> pointerdef) then
+ begin
+ { things which can overflow must NOT pass via here, but have to be }
+ { handled via a regular add node (conversion in tinlinenode.pass_1) }
+ { Or someone has to rewrite the above to use a_op_const_reg_reg_ov }
+ { and friends in case of overflow checking, and ask everyone to }
+ { implement these methods since they don't exist for all cpus (JM) }
+ { Similarly, range checking also has to be handled separately, }
+ { see mantis #14841 (JM) }
+ if ([cs_check_overflow,cs_check_range] * current_settings.localswitches <> []) then
+ internalerror(2006111010);
+// cg.g_overflowcheck(current_asmdata.CurrAsmList,tcallparanode(left).left.location,tcallparanode(left).resultdef);
+// cg.g_rangecheck(current_asmdata.CurrAsmList,tcallparanode(left).left.location,tcallparanode(left).left.resultdef,
+// tcallparanode(left).left.resultdef);
+ end;
+ end;
+
+
+{*****************************************************************************
+ TYPEINFO GENERIC HANDLING
+*****************************************************************************}
+ procedure tcginlinenode.second_typeinfo;
+ var
+ href : treference;
+ begin
+ location_reset(location,LOC_REGISTER,OS_ADDR);
+ location.register:=cg.getaddressregister(current_asmdata.CurrAsmList);
+ reference_reset_symbol(href,RTTIWriter.get_rtti_label(left.resultdef,fullrtti),0,sizeof(pint));
+ cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,href,location.register);
+ end;
+
+
+{*****************************************************************************
+ INCLUDE/EXCLUDE GENERIC HANDLING
+*****************************************************************************}
+
+ procedure tcginlinenode.second_IncludeExclude;
+ var
+ setpara, elepara: tnode;
+ begin
+ { the set }
+ secondpass(tcallparanode(left).left);
+ { the element to set }
+ secondpass(tcallparanode(tcallparanode(left).right).left);
+
+ setpara:=tcallparanode(left).left;
+ elepara:=tcallparanode(tcallparanode(left).right).left;
+
+ if elepara.location.loc=LOC_CONSTANT then
+ begin
+ cg.a_bit_set_const_loc(current_asmdata.CurrAsmList,(inlinenumber=in_include_x_y),
+ elepara.location.value-tsetdef(setpara.resultdef).setbase,setpara.location);
+ end
+ else
+ begin
+ location_force_reg(current_asmdata.CurrAsmList,elepara.location,OS_INT,true);
+ register_maybe_adjust_setbase(current_asmdata.CurrAsmList,elepara.location,tsetdef(setpara.resultdef).setbase);
+ cg.a_bit_set_reg_loc(current_asmdata.CurrAsmList,(inlinenumber=in_include_x_y),
+ elepara.location.size,elepara.location.register,setpara.location);
+ end;
+ end;
+
+
+{*****************************************************************************
+ FLOAT GENERIC HANDLING
+*****************************************************************************}
+
+{
+ These routines all call internal RTL routines, so if they are
+ called here, they give an internal error
+}
+ procedure tcginlinenode.second_pi;
+ begin
+ internalerror(20020718);
+ end;
+
+ procedure tcginlinenode.second_arctan_real;
+ begin
+ internalerror(20020718);
+ end;
+
+ procedure tcginlinenode.second_abs_real;
+ begin
+ internalerror(20020718);
+ end;
+
+ procedure tcginlinenode.second_round_real;
+ begin
+ internalerror(20020718);
+ end;
+
+ procedure tcginlinenode.second_trunc_real;
+ begin
+ internalerror(20020718);
+ end;
+
+ procedure tcginlinenode.second_sqr_real;
+ begin
+ internalerror(20020718);
+ end;
+
+ procedure tcginlinenode.second_sqrt_real;
+ begin
+ internalerror(20020718);
+ end;
+
+ procedure tcginlinenode.second_ln_real;
+ begin
+ internalerror(20020718);
+ end;
+
+ procedure tcginlinenode.second_cos_real;
+ begin
+ internalerror(20020718);
+ end;
+
+ procedure tcginlinenode.second_sin_real;
+ begin
+ internalerror(20020718);
+ end;
+
+
+ procedure tcginlinenode.second_prefetch;
+ begin
+ end;
+
+ procedure tcginlinenode.second_abs_long;
+ var
+ opsize : tcgsize;
+ tempreg1, tempreg2 : tregister;
+ begin
+ opsize := def_cgsize(left.resultdef);
+
+ secondpass(left);
+ location_force_reg(current_asmdata.CurrAsmList, left.location, opsize, false);
+ location := left.location;
+ location.register := cg.getintregister(current_asmdata.CurrAsmList, opsize);
+
+ tempreg1 := cg.getintregister(current_asmdata.CurrAsmList, opsize);
+ tempreg2 := cg.getintregister(current_asmdata.CurrAsmList, opsize);
+
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_SAR, OS_INT, tcgsize2size[opsize]*8-1, left.location.register, tempreg1);
+ cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList, OP_XOR, OS_INT, left.location.register, tempreg1, tempreg2);
+ cg.a_op_reg_reg_reg(current_asmdata.CurrAsmlist, OP_SUB, OS_INT, tempreg1, tempreg2, location.register);
+ end;
+
+
+{*****************************************************************************
+ ASSIGNED GENERIC HANDLING
+*****************************************************************************}
+
+ procedure tcginlinenode.second_assigned;
+ begin
+ secondpass(tcallparanode(left).left);
+ cg.a_cmp_const_loc_label(current_asmdata.CurrAsmList,def_cgsize(left.resultdef),OC_NE,0,tcallparanode(left).left.location,current_procinfo.CurrTrueLabel);
+ cg.a_jmp_always(current_asmdata.CurrAsmList,current_procinfo.CurrFalseLabel);
+ location_reset(location,LOC_JUMP,OS_NO);
+ end;
+
+ procedure Tcginlinenode.second_get_frame;
+
+ begin
+{$if defined(x86) or defined(arm)}
+ if current_procinfo.framepointer=NR_STACK_POINTER_REG then
+ begin
+ location_reset(location,LOC_CONSTANT,OS_ADDR);
+ location.value:=0;
+ end
+ else
+{$endif defined(x86) or defined(arm)}
+ begin
+ location_reset(location,LOC_CREGISTER,OS_ADDR);
+ location.register:=current_procinfo.framepointer;
+ end;
+ end;
+
+ procedure Tcginlinenode.second_get_caller_frame;
+
+ var
+ frame_reg:Tregister;
+ use_frame_pointer:boolean;
+
+ begin
+ if left<>nil then
+ begin
+ secondpass(left);
+ if left.location.loc=LOC_CONSTANT then
+ use_frame_pointer:=true
+ else
+ begin
+ location_force_reg(current_asmdata.currasmlist,left.location,OS_ADDR,false);
+ frame_reg:=left.location.register;
+ use_frame_pointer:=false;
+ end
+ end
+ else
+ begin
+ use_frame_pointer:=current_procinfo.framepointer=NR_STACK_POINTER_REG;
+ frame_reg:=current_procinfo.framepointer;
+ end;
+
+ if use_frame_pointer then
+ begin
+ location_reset(location,LOC_CREGISTER,OS_ADDR);
+ location.register:=NR_FRAME_POINTER_REG;
+ end
+ else
+ begin
+ location_reset_ref(location,LOC_REFERENCE,OS_ADDR,sizeof(pint));
+ location.reference.base:=frame_reg;
+ end;
+ end;
+
+ procedure Tcginlinenode.second_get_caller_addr;
+ var
+ frame_ref:Treference;
+ begin
+ if current_procinfo.framepointer=NR_STACK_POINTER_REG then
+ begin
+ location_reset(location,LOC_REGISTER,OS_ADDR);
+ location.register:=cg.getaddressregister(current_asmdata.currasmlist);
+ reference_reset_base(frame_ref,NR_STACK_POINTER_REG,{current_procinfo.calc_stackframe_size}tg.lasttemp,sizeof(pint));
+ cg.a_load_ref_reg(current_asmdata.currasmlist,OS_ADDR,OS_ADDR,frame_ref,location.register);
+ end
+ else
+ begin
+ location_reset(location,LOC_REGISTER,OS_ADDR);
+ location.register:=cg.getaddressregister(current_asmdata.currasmlist);
+ reference_reset_base(frame_ref,current_procinfo.framepointer,sizeof(pint),sizeof(pint));
+ cg.a_load_ref_reg(current_asmdata.currasmlist,OS_ADDR,OS_ADDR,frame_ref,location.register);
+ end;
+ end;
+
+
+ procedure tcginlinenode.second_rox;
+ var
+ op : topcg;
+ {hcountreg : tregister;}
+ op1,op2 : tnode;
+ begin
+ { one or two parameters? }
+ if (left.nodetype=callparan) and
+ assigned(tcallparanode(left).right) then
+ begin
+ op1:=tcallparanode(tcallparanode(left).right).left;
+ op2:=tcallparanode(left).left;
+ end
+ else
+ op1:=left;
+
+ secondpass(op1);
+ { load left operator in a register }
+ location_copy(location,op1.location);
+ case inlinenumber of
+ in_ror_x,
+ in_ror_x_y:
+ op:=OP_ROR;
+ in_rol_x,
+ in_rol_x_y:
+ op:=OP_ROL;
+ end;
+ location_force_reg(current_asmdata.CurrAsmList,location,location.size,false);
+
+ if (left.nodetype=callparan) and
+ assigned(tcallparanode(left).right) then
+ begin
+ secondpass(op2);
+ { rotating by a constant directly coded: }
+ if op2.nodetype=ordconstn then
+ cg.a_op_const_reg(current_asmdata.CurrAsmList,op,location.size,
+ tordconstnode(op2).value.uvalue and (resultdef.size*8-1),location.register)
+ else
+ begin
+ location_force_reg(current_asmdata.CurrAsmList,op2.location,location.size,false);
+ { do modulo 2 operation }
+ cg.a_op_reg_reg(current_asmdata.CurrAsmList,op,location.size,op2.location.register,location.register);
+ end;
+ end
+ else
+ cg.a_op_const_reg(current_asmdata.CurrAsmList,op,location.size,1,location.register);
+ end;
+
+
+ procedure tcginlinenode.second_sar;
+ var
+ {hcountreg : tregister;}
+ op1,op2 : tnode;
+ begin
+ if (left.nodetype=callparan) and
+ assigned(tcallparanode(left).right) then
+ begin
+ op1:=tcallparanode(tcallparanode(left).right).left;
+ op2:=tcallparanode(left).left;
+ end
+ else
+ begin
+ op1:=left;
+ op2:=nil;
+ end;
+ secondpass(op1);
+ { load left operator in a register }
+ location_copy(location,op1.location);
+
+ location_force_reg(current_asmdata.CurrAsmList,location,location.size,false);
+
+ if not(assigned(op2)) then
+ cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_SAR,location.size,1,location.register)
+ else
+ begin
+ secondpass(op2);
+ { shifting by a constant directly coded: }
+ if op2.nodetype=ordconstn then
+ cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_SAR,location.size,
+ tordconstnode(op2).value.uvalue and (resultdef.size*8-1),location.register)
+ else
+ begin
+ location_force_reg(current_asmdata.CurrAsmList,op2.location,location.size,false);
+ cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_SAR,location.size,op2.location.register,location.register);
+ end;
+ end;
+ end;
+
+
+ procedure tcginlinenode.second_BsfBsr;
+ var
+ reverse: boolean;
+ opsize: tcgsize;
+ begin
+ reverse:=(inlinenumber = in_bsr_x);
+ secondpass(left);
+
+ opsize:=tcgsize2unsigned[left.location.size];
+ if opsize < OS_32 then
+ opsize:=OS_32;
+
+ if (left.location.loc <> LOC_REGISTER) or
+ (left.location.size <> opsize) then
+ location_force_reg(current_asmdata.CurrAsmList,left.location,opsize,true);
+
+ location_reset(location,LOC_REGISTER,opsize);
+ location.register := cg.getintregister(current_asmdata.CurrAsmList,opsize);
+ cg.a_bit_scan_reg_reg(current_asmdata.CurrAsmList,reverse,opsize,left.location.register,location.register);
+ end;
+
+
+begin
+ cinlinenode:=tcginlinenode;
+end.
diff --git a/closures/compiler/ncgld.pas b/closures/compiler/ncgld.pas
new file mode 100644
index 0000000000..789b065e8c
--- /dev/null
+++ b/closures/compiler/ncgld.pas
@@ -0,0 +1,1286 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate assembler for nodes that handle loads and assignments which
+ are the same for all (most) processors
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit ncgld;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,nld,cgutils;
+
+ type
+ tcgloadnode = class(tloadnode)
+ procedure pass_generate_code;override;
+ procedure generate_picvaraccess;virtual;
+ procedure changereflocation(const ref: treference);
+ end;
+
+ tcgassignmentnode = class(tassignmentnode)
+ procedure pass_generate_code;override;
+ end;
+
+ tcgarrayconstructornode = class(tarrayconstructornode)
+ procedure pass_generate_code;override;
+ end;
+
+ tcgrttinode = class(trttinode)
+ procedure pass_generate_code;override;
+ end;
+
+
+implementation
+
+ uses
+ cutils,
+ systems,
+ verbose,globtype,globals,constexp,
+ nutils,
+ symtable,symconst,symtype,symdef,symsym,defutil,paramgr,
+ ncnv,ncon,nmem,nbas,ncgrtti,
+ aasmbase,aasmtai,aasmdata,aasmcpu,
+ cgbase,pass_2,
+ procinfo,
+ cpubase,parabase,
+ tgobj,ncgutil,
+ cgobj,
+ ncgbas,ncgflw,
+ wpobase;
+
+{*****************************************************************************
+ SSA (for memory temps) support
+*****************************************************************************}
+
+ type
+ preplacerefrec = ^treplacerefrec;
+ treplacerefrec = record
+ old, new: preference;
+ ressym: tsym;
+ end;
+
+ function doreplaceref(var n: tnode; para: pointer): foreachnoderesult;
+ var
+ rr: preplacerefrec absolute para;
+ begin
+ result := fen_false;
+ case n.nodetype of
+ loadn:
+ begin
+ { regular variable }
+ if (tabstractvarsym(tloadnode(n).symtableentry).varoptions * [vo_is_dll_var, vo_is_thread_var] = []) and
+ not assigned(tloadnode(n).left) and
+ { not function result, or no exit in function }
+ (((tloadnode(n).symtableentry <> rr^.ressym) and
+ not(vo_is_funcret in tabstractvarsym(tloadnode(n).symtableentry).varoptions)) or
+ not(fc_exit in flowcontrol)) and
+ { stored in memory... }
+ (tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.loc in [LOC_REFERENCE]) and
+ { ... at the place we are looking for }
+ references_equal(tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.reference,rr^.old^) and
+ { its address cannot have escaped the current routine }
+ not(tabstractvarsym(tloadnode(n).symtableentry).addr_taken) then
+ begin
+ { relocate variable }
+ tcgloadnode(n).changereflocation(rr^.new^);
+ result := fen_norecurse_true;
+ end;
+ end;
+ temprefn:
+ begin
+ if (ti_valid in ttemprefnode(n).tempinfo^.flags) and
+ { memory temp... }
+ (ttemprefnode(n).tempinfo^.location.loc in [LOC_REFERENCE]) and
+ { ... at the place we are looking for }
+ references_equal(ttemprefnode(n).tempinfo^.location.reference,rr^.old^) and
+ { its address cannot have escaped the current routine }
+ not(ti_addr_taken in ttemprefnode(n).tempinfo^.flags) then
+ begin
+ { relocate the temp }
+ tcgtemprefnode(n).changelocation(rr^.new^);
+ result := fen_norecurse_true;
+ end;
+ end;
+ { Subscriptn must be rejected, otherwise we may replace an
+ an entire record with a temp for its first field, mantis #13948)
+ Exception: the field's size is the same as the entire record
+
+ The same goes for array indexing
+ }
+ subscriptn,
+ vecn:
+ if not(tunarynode(n).left.resultdef.typ in [recorddef,objectdef,arraydef,stringdef]) or
+ { make sure we don't try to call resultdef.size for types that
+ don't have a compile-time size such as open arrays }
+ is_special_array(tunarynode(n).left.resultdef) or
+ (tsubscriptnode(n).left.resultdef.size <> tunarynode(n).resultdef.size) then
+ result := fen_norecurse_false;
+
+ { optimize the searching a bit }
+ derefn,addrn,
+ calln,inlinen,casen,
+ addn,subn,muln,
+ andn,orn,xorn,
+ ltn,lten,gtn,gten,equaln,unequaln,
+ slashn,divn,shrn,shln,notn,
+ inn,
+ asn,isn:
+ result := fen_norecurse_false;
+ end;
+ end;
+
+
+ function maybechangetemp(list: TAsmList; var n: tnode; const newref: treference): boolean;
+ var
+ rr: treplacerefrec;
+ begin
+ result := false;
+
+ { only do for -O2 or higher (breaks debugging since }
+ { variables move to different memory locations) }
+ if not(cs_opt_level2 in current_settings.optimizerswitches) or
+ { must be a copy to a memory location ... }
+ (n.location.loc <> LOC_REFERENCE) or
+ { not inside a control flow statement and no goto's in sight }
+ ([fc_inflowcontrol,fc_gotolabel] * flowcontrol <> []) or
+ { not for refcounted types, because those locations are }
+ { still used later on in initialisation/finalisation code }
+ is_managed_type(n.resultdef) or
+ { source and destination are temps (= not global variables) }
+ not tg.istemp(n.location.reference) or
+ not tg.istemp(newref) or
+ { and both point to the start of a temp, and the source is a }
+ { non-persistent temp (otherwise we need some kind of copy- }
+ { on-write support in case later on both are still used) }
+ (tg.gettypeoftemp(newref) <> tt_normal) or
+ not (tg.gettypeoftemp(n.location.reference) in [tt_normal,tt_persistent]) or
+ { and both have the same size }
+ (tg.sizeoftemp(current_asmdata.CurrAsmList,newref) <> tg.sizeoftemp(current_asmdata.CurrAsmList,n.location.reference)) then
+ exit;
+
+ { find the source of the old reference (loadnode or tempnode) }
+ { and replace it with the new reference }
+ rr.old := @n.location.reference;
+ rr.new := @newref;
+ rr.ressym := nil;
+
+ if assigned(current_procinfo.procdef.funcretsym) and
+ (tabstractvarsym(current_procinfo.procdef.funcretsym).refs <> 0) then
+ if (current_procinfo.procdef.proctypeoption=potype_constructor) then
+ rr.ressym:=tsym(current_procinfo.procdef.parast.Find('self'))
+ else
+ rr.ressym:=current_procinfo.procdef.funcretsym;
+
+ { if source not found, don't do anything }
+ if not foreachnodestatic(n,@doreplaceref,@rr) then
+ exit;
+
+ n.location.reference := newref;
+ result:=true;
+ end;
+
+{*****************************************************************************
+ SecondLoad
+*****************************************************************************}
+
+ procedure tcgloadnode.generate_picvaraccess;
+ begin
+{$ifndef sparc}
+ location.reference.base:=current_procinfo.got;
+ location.reference.symbol:=current_asmdata.RefAsmSymbol(tstaticvarsym(symtableentry).mangledname+'@GOT');
+{$endif sparc}
+ end;
+
+
+ procedure tcgloadnode.changereflocation(const ref: treference);
+ var
+ oldtemptype: ttemptype;
+ begin
+ if (location.loc<>LOC_REFERENCE) then
+ internalerror(2007020812);
+ if not tg.istemp(location.reference) then
+ internalerror(2007020813);
+ oldtemptype:=tg.gettypeoftemp(location.reference);
+ if (oldtemptype = tt_persistent) then
+ tg.ChangeTempType(current_asmdata.CurrAsmList,location.reference,tt_normal);
+ tg.ungettemp(current_asmdata.CurrAsmList,location.reference);
+ location.reference:=ref;
+ tg.ChangeTempType(current_asmdata.CurrAsmList,location.reference,oldtemptype);
+ tabstractnormalvarsym(symtableentry).localloc:=location;
+ end;
+
+
+ procedure tcgloadnode.pass_generate_code;
+ var
+ hregister : tregister;
+ vs : tabstractnormalvarsym;
+ gvs : tstaticvarsym;
+ pd : tprocdef;
+ href : treference;
+ newsize : tcgsize;
+ endrelocatelab,
+ norelocatelab : tasmlabel;
+ paraloc1 : tcgpara;
+ begin
+ { we don't know the size of all arrays }
+ newsize:=def_cgsize(resultdef);
+ { alignment is overridden per case below }
+ location_reset_ref(location,LOC_REFERENCE,newsize,resultdef.alignment);
+ case symtableentry.typ of
+ absolutevarsym :
+ begin
+ { this is only for toasm and toaddr }
+ case tabsolutevarsym(symtableentry).abstyp of
+ toaddr :
+ begin
+{$ifdef i386}
+ if tabsolutevarsym(symtableentry).absseg then
+ location.reference.segment:=NR_FS;
+{$endif i386}
+ location.reference.offset:=aint(tabsolutevarsym(symtableentry).addroffset);
+ end;
+ toasm :
+ location.reference.symbol:=current_asmdata.RefAsmSymbol(tabsolutevarsym(symtableentry).mangledname);
+ else
+ internalerror(200310283);
+ end;
+ end;
+ constsym:
+ begin
+ if tconstsym(symtableentry).consttyp=constresourcestring then
+ begin
+ location_reset_ref(location,LOC_CREFERENCE,OS_ADDR,sizeof(pint));
+ location.reference.symbol:=current_asmdata.RefAsmSymbol(make_mangledname('RESSTR',symtableentry.owner,symtableentry.name));
+ { Resourcestring layout:
+ TResourceStringRecord = Packed Record
+ Name,
+ CurrentValue,
+ DefaultValue : AnsiString;
+ HashValue : LongWord;
+ end;
+ }
+ location.reference.offset:=sizeof(pint);
+ end
+ else
+ internalerror(22798);
+ end;
+ staticvarsym :
+ begin
+ gvs:=tstaticvarsym(symtableentry);
+ if ([vo_is_dll_var,vo_is_external] * gvs.varoptions <> []) then
+ begin
+ { assume external variables use the default alignment }
+ location.reference.alignment:=gvs.vardef.alignment;
+ location.reference.base := cg.g_indirect_sym_load(current_asmdata.CurrAsmList,tstaticvarsym(symtableentry).mangledname,
+ vo_is_weak_external in gvs.varoptions);
+ if (location.reference.base <> NR_NO) then
+ exit;
+ end
+ else
+ begin
+ location.reference.alignment:=var_align(gvs.vardef.alignment);
+ end;
+
+
+ if (vo_is_dll_var in gvs.varoptions) then
+ { DLL variable }
+ begin
+ hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
+ if not(vo_is_weak_external in gvs.varoptions) then
+ location.reference.symbol:=current_asmdata.RefAsmSymbol(tstaticvarsym(symtableentry).mangledname)
+ else
+ location.reference.symbol:=current_asmdata.WeakRefAsmSymbol(tstaticvarsym(symtableentry).mangledname);
+ cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,location.reference,hregister);
+ reference_reset_base(location.reference,hregister,0,location.reference.alignment);
+ end
+ { Thread variable }
+ else if (vo_is_thread_var in gvs.varoptions) and
+ not(tf_section_threadvars in target_info.flags) then
+ begin
+ if (tf_section_threadvars in target_info.flags) then
+ begin
+ if gvs.localloc.loc=LOC_INVALID then
+ if not(vo_is_weak_external in gvs.varoptions) then
+ reference_reset_symbol(location.reference,current_asmdata.RefAsmSymbol(gvs.mangledname),0,location.reference.alignment)
+ else
+ reference_reset_symbol(location.reference,current_asmdata.WeakRefAsmSymbol(gvs.mangledname),0,location.reference.alignment)
+ else
+ location:=gvs.localloc;
+{$ifdef i386}
+ case target_info.system of
+ system_i386_linux:
+ location.reference.segment:=NR_GS;
+ system_i386_win32:
+ location.reference.segment:=NR_FS;
+ end;
+{$endif i386}
+ end
+ else
+ begin
+ {
+ Thread var loading is optimized to first check if
+ a relocate function is available. When the function
+ is available it is called to retrieve the address.
+ Otherwise the address is loaded with the symbol
+
+ The code needs to be in the order to first handle the
+ call and then the address load to be sure that the
+ register that is used for returning is the same (PFV)
+ }
+ current_asmdata.getjumplabel(norelocatelab);
+ current_asmdata.getjumplabel(endrelocatelab);
+ { make sure hregister can't allocate the register necessary for the parameter }
+ paraloc1.init;
+ paramanager.getintparaloc(pocall_default,1,paraloc1);
+ hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
+ reference_reset_symbol(href,current_asmdata.RefAsmSymbol('FPC_THREADVAR_RELOCATE'),0,sizeof(pint));
+ cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,href,hregister);
+ cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,OS_ADDR,OC_EQ,0,hregister,norelocatelab);
+ { don't save the allocated register else the result will be destroyed later }
+ if not(vo_is_weak_external in gvs.varoptions) then
+ reference_reset_symbol(href,current_asmdata.RefAsmSymbol(gvs.mangledname),0,sizeof(pint))
+ else
+ reference_reset_symbol(href,current_asmdata.WeakRefAsmSymbol(gvs.mangledname),0,sizeof(pint));
+ cg.a_load_ref_cgpara(current_asmdata.CurrAsmList,OS_32,href,paraloc1);
+ paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc1);
+ paraloc1.done;
+ cg.allocallcpuregisters(current_asmdata.CurrAsmList);
+ cg.a_call_reg(current_asmdata.CurrAsmList,hregister);
+ cg.deallocallcpuregisters(current_asmdata.CurrAsmList);
+ cg.getcpuregister(current_asmdata.CurrAsmList,NR_FUNCTION_RESULT_REG);
+ cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_FUNCTION_RESULT_REG);
+ hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
+ cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_INT,OS_ADDR,NR_FUNCTION_RESULT_REG,hregister);
+ cg.a_jmp_always(current_asmdata.CurrAsmList,endrelocatelab);
+ cg.a_label(current_asmdata.CurrAsmList,norelocatelab);
+ { no relocation needed, load the address of the variable only, the
+ layout of a threadvar is (4 bytes pointer):
+ 0 - Threadvar index
+ 4 - Threadvar value in single threading }
+ if not(vo_is_weak_external in gvs.varoptions) then
+ reference_reset_symbol(href,current_asmdata.RefAsmSymbol(gvs.mangledname),sizeof(pint),sizeof(pint))
+ else
+ reference_reset_symbol(href,current_asmdata.WeakRefAsmSymbol(gvs.mangledname),sizeof(pint),sizeof(pint));
+ cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,href,hregister);
+ cg.a_label(current_asmdata.CurrAsmList,endrelocatelab);
+ location.reference.base:=hregister;
+ end;
+ end
+ { Normal (or external) variable }
+ else
+ begin
+ if gvs.localloc.loc=LOC_INVALID then
+ if not(vo_is_weak_external in gvs.varoptions) then
+ reference_reset_symbol(location.reference,current_asmdata.RefAsmSymbol(gvs.mangledname),0,location.reference.alignment)
+ else
+ reference_reset_symbol(location.reference,current_asmdata.WeakRefAsmSymbol(gvs.mangledname),0,location.reference.alignment)
+ else
+ location:=gvs.localloc;
+ end;
+
+ { make const a LOC_CREFERENCE }
+ if (gvs.varspez=vs_const) and
+ (location.loc=LOC_REFERENCE) then
+ location.loc:=LOC_CREFERENCE;
+ end;
+ paravarsym,
+ localvarsym :
+ begin
+ vs:=tabstractnormalvarsym(symtableentry);
+ { Nested variable }
+ if assigned(left) then
+ begin
+ secondpass(left);
+ if not(left.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
+ internalerror(200309286);
+ if vs.localloc.loc<>LOC_REFERENCE then
+ internalerror(200409241);
+ reference_reset_base(location.reference,left.location.register,vs.localloc.reference.offset,vs.localloc.reference.alignment);
+ end
+ else
+ location:=vs.localloc;
+
+ { handle call by reference variables when they are not
+ already copied to local copies. Also ignore the reference
+ when we need to load the self pointer for objects }
+ if is_addr_param_load then
+ begin
+ if (location.loc in [LOC_CREGISTER,LOC_REGISTER]) then
+ hregister:=location.register
+ else
+ begin
+ hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
+ { we need to load only an address }
+ location.size:=OS_ADDR;
+ cg.a_load_loc_reg(current_asmdata.CurrAsmList,location.size,location,hregister);
+ end;
+ { assume packed records may always be unaligned }
+ if not(resultdef.typ in [recorddef,objectdef]) or
+ (tabstractrecordsymtable(tabstractrecorddef(resultdef).symtable).usefieldalignment<>1) then
+ location_reset_ref(location,LOC_REFERENCE,newsize,resultdef.alignment)
+ else
+ location_reset_ref(location,LOC_REFERENCE,newsize,1);
+ location.reference.base:=hregister;
+ end;
+
+ { make const a LOC_CREFERENCE }
+ if (vs.varspez=vs_const) and
+ (location.loc=LOC_REFERENCE) then
+ location.loc:=LOC_CREFERENCE;
+ end;
+ procsym:
+ begin
+ if not assigned(procdef) then
+ internalerror(200312011);
+ if assigned(left) then
+ begin
+ {$if sizeof(pint) = 4}
+ location_reset_ref(location,LOC_CREFERENCE,OS_64,sizeof(pint));
+ {$else} {$if sizeof(pint) = 8}
+ location_reset_ref(location,LOC_CREFERENCE,OS_128,sizeof(pint));
+ {$else}
+ internalerror(20020520);
+ {$endif} {$endif}
+ tg.GetTemp(current_asmdata.CurrAsmList,2*sizeof(pint),sizeof(pint),tt_normal,location.reference);
+ secondpass(left);
+
+ { load class instance/classrefdef address }
+ if left.location.loc=LOC_CONSTANT then
+ location_force_reg(current_asmdata.CurrAsmList,left.location,OS_ADDR,false);
+ case left.location.loc of
+ LOC_CREGISTER,
+ LOC_REGISTER:
+ begin
+ { this is not possible for objects }
+ if is_object(left.resultdef) then
+ internalerror(200304234);
+ hregister:=left.location.register;
+ end;
+ LOC_CREFERENCE,
+ LOC_REFERENCE:
+ begin
+ hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
+ if not is_object(left.resultdef) then
+ cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,left.location.reference,hregister)
+ else
+ cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,left.location.reference,hregister);
+ location_freetemp(current_asmdata.CurrAsmList,left.location);
+ end;
+ else
+ internalerror(200610311);
+ end;
+
+ { store the class instance or classredef address }
+ href:=location.reference;
+ inc(href.offset,sizeof(pint));
+ cg.a_load_reg_ref(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,hregister,href);
+
+ { virtual method ? }
+ if (po_virtualmethod in procdef.procoptions) and
+ not(loadnf_inherited in loadnodeflags) and
+ not is_objectpascal_helper(procdef.struct) then
+ begin
+ if (not assigned(current_procinfo) or
+ wpoinfomanager.symbol_live(current_procinfo.procdef.mangledname)) then
+ tobjectdef(procdef.struct).register_vmt_call(procdef.extnumber);
+ {$ifdef vtentry}
+ if not is_interface(procdef.struct) then
+ begin
+ inc(current_asmdata.NextVTEntryNr);
+ current_asmdata.CurrAsmList.Concat(tai_symbol.CreateName('VTREF'+tostr(current_asmdata.NextVTEntryNr)+'_'+procdef._class.vmt_mangledname+'$$'+tostr(vmtoffset div sizeof(pint)),AT_FUNCTION,0));
+ end;
+ {$endif vtentry}
+ { a classrefdef already points to the VMT }
+ if (left.resultdef.typ<>classrefdef) then
+ begin
+ { load vmt pointer }
+ reference_reset_base(href,hregister,tobjectdef(left.resultdef).vmt_offset,sizeof(pint));
+ hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
+ cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,href,hregister);
+ end;
+ { load method address }
+ reference_reset_base(href,hregister,tobjectdef(procdef.struct).vmtmethodoffset(procdef.extnumber),sizeof(pint));
+ hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
+ cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,href,hregister);
+ { ... and store it }
+ cg.a_load_reg_ref(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,hregister,location.reference);
+ end
+ else
+ begin
+ { load address of the function }
+ reference_reset_symbol(href,current_asmdata.RefAsmSymbol(procdef.mangledname),0,sizeof(pint));
+ hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
+ cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,href,hregister);
+ cg.a_load_reg_ref(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,hregister,location.reference);
+ end;
+ end
+ else
+ begin
+ pd:=tprocdef(tprocsym(symtableentry).ProcdefList[0]);
+ if (po_external in pd.procoptions) then
+ location.reference.base :=
+ cg.g_indirect_sym_load(current_asmdata.CurrAsmList,pd.mangledname,
+ po_weakexternal in pd.procoptions);
+ {!!!!! Be aware, work on virtual methods too }
+ if (location.reference.base = NR_NO) then
+ if not(po_weakexternal in pd.procoptions) then
+ location.reference.symbol:=current_asmdata.RefAsmSymbol(procdef.mangledname)
+ else
+ location.reference.symbol:=current_asmdata.WeakRefAsmSymbol(procdef.mangledname);
+ end;
+ end;
+ labelsym :
+ if assigned(tlabelsym(symtableentry).asmblocklabel) then
+ location.reference.symbol:=tlabelsym(symtableentry).asmblocklabel
+ else
+ location.reference.symbol:=tcglabelnode((tlabelsym(symtableentry).code)).getasmlabel;
+ else internalerror(200510032);
+ end;
+ end;
+
+
+{*****************************************************************************
+ SecondAssignment
+*****************************************************************************}
+
+ procedure tcgassignmentnode.pass_generate_code;
+ var
+ otlabel,hlabel,oflabel : tasmlabel;
+ href : treference;
+ releaseright : boolean;
+ alignmentrequirement,
+ len : aint;
+ r : tregister;
+ r64 : tregister64;
+ oldflowcontrol : tflowcontrol;
+ begin
+ location_reset(location,LOC_VOID,OS_NO);
+ { managed types should be handled in firstpass }
+ if is_managed_type(left.resultdef) or is_managed_type(right.resultdef) then
+ InternalError(2012011901);
+
+ otlabel:=current_procinfo.CurrTrueLabel;
+ oflabel:=current_procinfo.CurrFalseLabel;
+ current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
+ current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel);
+
+ {
+ in most cases we can process first the right node which contains
+ the most complex code. Exceptions for this are:
+ - result is in flags, loading left will then destroy the flags
+ - result is a jump, loading left must be already done before the jump is made
+ - result need reference count, when left points to a value used in
+ right then decreasing the refcnt on left can possibly release
+ the memory before right increased the refcnt, result is that an
+ empty value is assigned
+
+ But not when the result is in the flags, then
+ loading the left node afterwards can destroy the flags.
+ }
+ if not(right.expectloc in [LOC_FLAGS,LOC_JUMP]) and
+ (node_complexity(right)>node_complexity(left)) then
+ begin
+ secondpass(right);
+ if codegenerror then
+ exit;
+
+ secondpass(left);
+ if codegenerror then
+ exit;
+ end
+ else
+ begin
+ { calculate left sides }
+ secondpass(left);
+ if codegenerror then
+ exit;
+
+ { tell the SSA/SSL code that the left side was handled first so
+ ni SSL is done
+ }
+ oldflowcontrol:=flowcontrol;
+ include(flowcontrol,fc_lefthandled);
+
+ secondpass(right);
+ flowcontrol:=oldflowcontrol;
+
+ if codegenerror then
+ exit;
+ end;
+
+ releaseright:=true;
+
+ { shortstring assignments are handled separately }
+ if is_shortstring(left.resultdef) then
+ begin
+ {
+ we can get here only in the following situations
+ for the right node:
+ - empty constant string
+ - char
+ }
+
+ { The addn is replaced by a blockn or calln that already returns
+ a shortstring }
+ if is_shortstring(right.resultdef) and
+ (right.nodetype in [blockn,calln]) then
+ begin
+ { nothing to do }
+ end
+ { empty constant string }
+ else if (right.nodetype=stringconstn) and
+ (tstringconstnode(right).len=0) then
+ begin
+ cg.a_load_const_ref(current_asmdata.CurrAsmList,OS_8,0,left.location.reference);
+ end
+ { char loading }
+ else if is_char(right.resultdef) then
+ begin
+ if right.nodetype=ordconstn then
+ begin
+ if (target_info.endian = endian_little) then
+ cg.a_load_const_ref(current_asmdata.CurrAsmList,OS_16,(tordconstnode(right).value.svalue shl 8) or 1,
+ setalignment(left.location.reference,1))
+ else
+ cg.a_load_const_ref(current_asmdata.CurrAsmList,OS_16,tordconstnode(right).value.svalue or (1 shl 8),
+ setalignment(left.location.reference,1));
+ end
+ else
+ begin
+ href:=left.location.reference;
+ cg.a_load_const_ref(current_asmdata.CurrAsmList,OS_8,1,href);
+ inc(href.offset,1);
+ case right.location.loc of
+ LOC_REGISTER,
+ LOC_CREGISTER :
+ begin
+ r:=cg.makeregsize(current_asmdata.CurrAsmList,right.location.register,OS_8);
+ cg.a_load_reg_ref(current_asmdata.CurrAsmList,OS_8,OS_8,r,href);
+ end;
+ LOC_REFERENCE,
+ LOC_CREFERENCE :
+ cg.a_load_ref_ref(current_asmdata.CurrAsmList,OS_8,OS_8,right.location.reference,href);
+ else
+ internalerror(200205111);
+ end;
+ end;
+ end
+ else
+ internalerror(2002042410);
+ end
+ { try to reuse memory locations instead of copying }
+ { copy to a memory location ... }
+ else if (right.location.loc = LOC_REFERENCE) and
+ maybechangetemp(current_asmdata.CurrAsmList,left,right.location.reference) then
+ begin
+ { if it worked, we're done }
+ end
+ else
+ begin
+ { SSA support }
+ maybechangeloadnodereg(current_asmdata.CurrAsmList,left,false);
+ maybechangeloadnodereg(current_asmdata.CurrAsmList,right,true);
+ case right.location.loc of
+ LOC_CONSTANT :
+ begin
+{$ifndef cpu64bitalu}
+ if (left.location.size in [OS_64,OS_S64]) or (right.location.size in [OS_64,OS_S64]) then
+ cg64.a_load64_const_loc(current_asmdata.CurrAsmList,right.location.value64,left.location)
+ else
+{$endif not cpu64bitalu}
+ cg.a_load_const_loc(current_asmdata.CurrAsmList,right.location.value,left.location);
+ end;
+ LOC_REFERENCE,
+ LOC_CREFERENCE :
+ begin
+ case left.location.loc of
+ LOC_REGISTER,
+ LOC_CREGISTER :
+ begin
+{$ifndef cpu64bitalu}
+ if left.location.size in [OS_64,OS_S64] then
+ cg64.a_load64_ref_reg(current_asmdata.CurrAsmList,right.location.reference,left.location.register64)
+ else
+{$endif not cpu64bitalu}
+ cg.a_load_ref_reg(current_asmdata.CurrAsmList,right.location.size,left.location.size,right.location.reference,left.location.register);
+ end;
+ LOC_FPUREGISTER,
+ LOC_CFPUREGISTER :
+ begin
+ cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,
+ right.location.size,left.location.size,
+ right.location.reference,
+ left.location.register);
+ end;
+ LOC_REFERENCE,
+ LOC_CREFERENCE :
+ begin
+ if (left.resultdef.typ=floatdef) and
+ (right.resultdef.typ=floatdef) and
+ (left.location.size<>right.location.size) then
+ begin
+ cg.a_loadfpu_ref_ref(current_asmdata.CurrAsmList,
+ right.location.size,left.location.size,
+ right.location.reference,left.location.reference)
+ end
+ else
+ begin
+{ TODO: HACK: unaligned test, maybe remove all unaligned locations (array of char) from the compiler}
+ { Use unaligned copy when the offset is not aligned }
+ len:=left.resultdef.size;
+
+ { data smaller than an aint has less alignment requirements }
+ { max(1,...) avoids div by zero in case of an empty record }
+ alignmentrequirement:=min(max(1,len),sizeof(aint));
+
+ if (right.location.reference.offset mod alignmentrequirement<>0) or
+ (left.location.reference.offset mod alignmentrequirement<>0) or
+ (right.resultdef.alignment<alignmentrequirement) or
+ ((right.location.reference.alignment<>0) and
+ (right.location.reference.alignment<alignmentrequirement)) or
+ ((left.location.reference.alignment<>0) and
+ (left.location.reference.alignment<alignmentrequirement)) then
+ cg.g_concatcopy_unaligned(current_asmdata.CurrAsmList,right.location.reference,left.location.reference,len)
+ else
+ cg.g_concatcopy(current_asmdata.CurrAsmList,right.location.reference,left.location.reference,len);
+ end;
+ end;
+ LOC_MMREGISTER,
+ LOC_CMMREGISTER:
+ begin
+{$ifdef x86}
+ if (right.resultdef.typ=floatdef) and
+ not use_vectorfpu(right.resultdef) then
+ begin
+ { perform size conversion if needed (the mm-code cannot }
+ { convert an extended into a double/single, since sse }
+ { doesn't support extended) }
+ r:=cg.getfpuregister(current_asmdata.CurrAsmList,right.location.size);
+ tg.gettemp(current_asmdata.CurrAsmList,left.resultdef.size,left.resultdef.alignment,tt_normal,href);
+ cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,right.location.size,right.location.size,right.location.reference,r);
+ cg.a_loadfpu_reg_ref(current_asmdata.CurrAsmList,right.location.size,left.location.size,r,href);
+ if releaseright then
+ location_freetemp(current_asmdata.CurrAsmList,right.location);
+ releaseright:=true;
+ location_reset_ref(right.location,LOC_REFERENCE,left.location.size,0);
+ right.location.reference:=href;
+ end;
+{$endif}
+ cg.a_loadmm_ref_reg(current_asmdata.CurrAsmList,
+ right.location.size,
+ left.location.size,
+ right.location.reference,
+ left.location.register,mms_movescalar);
+ end;
+ LOC_SUBSETREG,
+ LOC_CSUBSETREG:
+ cg.a_load_ref_subsetreg(current_asmdata.CurrAsmList,right.location.size,left.location.size,right.location.reference,left.location.sreg);
+ LOC_SUBSETREF,
+ LOC_CSUBSETREF:
+{$ifndef cpu64bitalu}
+ if right.location.size in [OS_64,OS_S64] then
+ cg64.a_load64_ref_subsetref(current_asmdata.CurrAsmList,right.location.reference,left.location.sref)
+ else
+{$endif not cpu64bitalu}
+ cg.a_load_ref_subsetref(current_asmdata.CurrAsmList,right.location.size,left.location.size,right.location.reference,left.location.sref);
+ else
+ internalerror(200203284);
+ end;
+ end;
+{$ifdef SUPPORT_MMX}
+ LOC_CMMXREGISTER,
+ LOC_MMXREGISTER:
+ begin
+ if left.location.loc=LOC_CMMXREGISTER then
+ cg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,OS_M64,OS_M64,right.location.register,left.location.register,nil)
+ else
+ cg.a_loadmm_reg_ref(current_asmdata.CurrAsmList,OS_M64,OS_M64,right.location.register,left.location.reference,nil);
+ end;
+{$endif SUPPORT_MMX}
+ LOC_MMREGISTER,
+ LOC_CMMREGISTER:
+ begin
+ if left.resultdef.typ=arraydef then
+ begin
+ end
+ else
+ begin
+ case left.location.loc of
+ LOC_CMMREGISTER,
+ LOC_MMREGISTER:
+ cg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,right.location.size,left.location.size,right.location.register,left.location.register,mms_movescalar);
+ LOC_REFERENCE,
+ LOC_CREFERENCE:
+ cg.a_loadmm_reg_ref(current_asmdata.CurrAsmList,right.location.size,left.location.size,right.location.register,left.location.reference,mms_movescalar);
+ else
+ internalerror(2009112601);
+ end;
+ end;
+ end;
+ LOC_REGISTER,
+ LOC_CREGISTER :
+ begin
+{$ifndef cpu64bitalu}
+ { also OS_F64 in case of mmreg -> intreg }
+ if left.location.size in [OS_64,OS_S64,OS_F64] then
+ cg64.a_load64_reg_loc(current_asmdata.CurrAsmList,
+ right.location.register64,left.location)
+ else
+{$endif not cpu64bitalu}
+ cg.a_load_reg_loc(current_asmdata.CurrAsmList,right.location.size,right.location.register,left.location);
+ end;
+ LOC_FPUREGISTER,
+ LOC_CFPUREGISTER :
+ begin
+ { we can't do direct moves between fpu and mm registers }
+ if left.location.loc in [LOC_MMREGISTER,LOC_CMMREGISTER] then
+ begin
+{$ifdef x86}
+ if not use_vectorfpu(right.resultdef) then
+ begin
+ { perform size conversion if needed (the mm-code cannot convert an }
+ { extended into a double/single, since sse doesn't support extended) }
+ tg.gettemp(current_asmdata.CurrAsmList,left.resultdef.size,left.resultdef.alignment,tt_normal,href);
+ cg.a_loadfpu_reg_ref(current_asmdata.CurrAsmList,right.location.size,left.location.size,right.location.register,href);
+ location_reset_ref(right.location,LOC_REFERENCE,left.location.size,0);
+ right.location.reference:=href;
+ end;
+{$endif}
+ location_force_mmregscalar(current_asmdata.CurrAsmList,right.location,false);
+ cg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,
+ right.location.size,left.location.size,
+ right.location.register,left.location.register,mms_movescalar);
+ end
+ else
+ cg.a_loadfpu_reg_loc(current_asmdata.CurrAsmList,
+ right.location.size,
+ right.location.register,left.location);
+ end;
+ LOC_SUBSETREG,
+ LOC_CSUBSETREG:
+ begin
+ cg.a_load_subsetreg_loc(current_asmdata.CurrAsmList,
+ right.location.size,right.location.sreg,left.location);
+ end;
+ LOC_SUBSETREF,
+ LOC_CSUBSETREF:
+ begin
+{$ifndef cpu64bitalu}
+ if right.location.size in [OS_64,OS_S64] then
+ cg64.a_load64_subsetref_loc(current_asmdata.CurrAsmList,right.location.sref,left.location)
+ else
+{$endif not cpu64bitalu}
+ cg.a_load_subsetref_loc(current_asmdata.CurrAsmList,
+ right.location.size,right.location.sref,left.location);
+ end;
+ LOC_JUMP :
+ begin
+ current_asmdata.getjumplabel(hlabel);
+ cg.a_label(current_asmdata.CurrAsmList,current_procinfo.CurrTrueLabel);
+ if is_pasbool(left.resultdef) then
+ begin
+{$ifndef cpu64bitalu}
+ if left.location.size in [OS_64,OS_S64] then
+ cg64.a_load64_const_loc(current_asmdata.CurrAsmList,1,left.location)
+ else
+{$endif not cpu64bitalu}
+ cg.a_load_const_loc(current_asmdata.CurrAsmList,1,left.location)
+ end
+ else
+ begin
+{$ifndef cpu64bitalu}
+ if left.location.size in [OS_64,OS_S64] then
+ cg64.a_load64_const_loc(current_asmdata.CurrAsmList,-1,left.location)
+ else
+{$endif not cpu64bitalu}
+ cg.a_load_const_loc(current_asmdata.CurrAsmList,-1,left.location);
+ end;
+
+ cg.a_jmp_always(current_asmdata.CurrAsmList,hlabel);
+ cg.a_label(current_asmdata.CurrAsmList,current_procinfo.CurrFalseLabel);
+{$ifndef cpu64bitalu}
+ if left.location.size in [OS_64,OS_S64] then
+ cg64.a_load64_const_loc(current_asmdata.CurrAsmList,0,left.location)
+ else
+{$endif not cpu64bitalu}
+ cg.a_load_const_loc(current_asmdata.CurrAsmList,0,left.location);
+ cg.a_label(current_asmdata.CurrAsmList,hlabel);
+ end;
+{$ifdef cpuflags}
+ LOC_FLAGS :
+ begin
+ if is_pasbool(left.resultdef) then
+ begin
+ case left.location.loc of
+ LOC_REGISTER,LOC_CREGISTER:
+{$ifdef cpu32bitalu}
+ if left.location.size in [OS_S64,OS_64] then
+ begin
+ cg.g_flags2reg(current_asmdata.CurrAsmList,OS_32,right.location.resflags,left.location.register64.reglo);
+ cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_32,0,left.location.register64.reghi);
+ end
+ else
+{$endif cpu32bitalu}
+ cg.g_flags2reg(current_asmdata.CurrAsmList,left.location.size,right.location.resflags,left.location.register);
+ LOC_REFERENCE:
+ { i386 has a hack in its code generator so that it can
+ deal with 64 bit locations in this parcticular case }
+{$if defined(cpu32bitalu) and not defined(x86)}
+ if left.location.size in [OS_S64,OS_64] then
+ begin
+ r64.reglo:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
+ r64.reghi:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
+ cg.g_flags2reg(current_asmdata.CurrAsmList,OS_32,right.location.resflags,r64.reglo);
+ cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_32,0,r64.reghi);
+ cg64.a_load64_reg_ref(current_asmdata.CurrAsmList,r64,left.location.reference);
+ end
+ else
+{$endif cpu32bitalu}
+ cg.g_flags2ref(current_asmdata.CurrAsmList,left.location.size,right.location.resflags,left.location.reference);
+ LOC_SUBSETREG,LOC_SUBSETREF:
+ begin
+ r:=cg.getintregister(current_asmdata.CurrAsmList,left.location.size);
+ cg.g_flags2reg(current_asmdata.CurrAsmList,left.location.size,right.location.resflags,r);
+ cg.a_load_reg_loc(current_asmdata.CurrAsmList,left.location.size,r,left.location);
+ end;
+ else
+ internalerror(200203273);
+ end;
+ end
+ else
+ begin
+{$ifdef cpu32bitalu}
+ if left.location.size in [OS_S64,OS_64] then
+ begin
+ r64.reglo:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
+ r64.reghi:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
+ cg.g_flags2reg(current_asmdata.CurrAsmList,OS_32,right.location.resflags,r64.reglo);
+ cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_32,0,r64.reghi);
+ cg64.a_op64_reg_reg(current_asmdata.CurrAsmList,OP_NEG,OS_S64,
+ r64,r64);
+ cg64.a_load64_reg_loc(current_asmdata.CurrAsmList,r64,left.location);
+ end
+ else
+{$endif cpu32bitalu}
+ begin
+ r:=cg.getintregister(current_asmdata.CurrAsmList,left.location.size);
+ cg.g_flags2reg(current_asmdata.CurrAsmList,left.location.size,right.location.resflags,r);
+ cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_NEG,left.location.size,r,r);
+ cg.a_load_reg_loc(current_asmdata.CurrAsmList,left.location.size,r,left.location);
+ end
+ end;
+ end;
+{$endif cpuflags}
+ end;
+ end;
+
+ if releaseright then
+ location_freetemp(current_asmdata.CurrAsmList,right.location);
+
+ current_procinfo.CurrTrueLabel:=otlabel;
+ current_procinfo.CurrFalseLabel:=oflabel;
+ end;
+
+
+{*****************************************************************************
+ SecondArrayConstruct
+*****************************************************************************}
+
+ const
+ vtInteger = 0;
+ vtBoolean = 1;
+ vtChar = 2;
+ vtExtended = 3;
+ vtString = 4;
+ vtPointer = 5;
+ vtPChar = 6;
+ vtObject = 7;
+ vtClass = 8;
+ vtWideChar = 9;
+ vtPWideChar = 10;
+ vtAnsiString32 = 11;
+ vtCurrency = 12;
+ vtVariant = 13;
+ vtInterface = 14;
+ vtWideString = 15;
+ vtInt64 = 16;
+ vtQWord = 17;
+ vtUnicodeString = 18;
+ vtAnsiString16 = 19;
+ vtAnsiString64 = 20;
+
+ procedure tcgarrayconstructornode.pass_generate_code;
+ var
+ hp : tarrayconstructornode;
+ href : treference;
+ lt : tdef;
+ paraloc : tcgparalocation;
+ otlabel,
+ oflabel : tasmlabel;
+ vtype : longint;
+ elesize,
+ elealign : longint;
+ tmpreg : tregister;
+ vaddr : boolean;
+ freetemp,
+ dovariant : boolean;
+ begin
+ if is_packed_array(resultdef) then
+ internalerror(200608042);
+ dovariant:=(nf_forcevaria in flags) or is_variant_array(resultdef);
+ if dovariant then
+ begin
+ elesize:=sizeof(pint)+sizeof(pint);
+ elealign:=sizeof(pint);
+ end
+ else
+ begin
+ elesize:=tarraydef(resultdef).elesize;
+ elealign:=tarraydef(resultdef).elementdef.alignment;
+ end;
+ { alignment is filled in by tg.gettemp below }
+ location_reset_ref(location,LOC_CREFERENCE,OS_NO,0);
+ fillchar(paraloc,sizeof(paraloc),0);
+ { Allocate always a temp, also if no elements are required, to
+ be sure that location is valid (PFV) }
+ if tarraydef(resultdef).highrange=-1 then
+ tg.GetTemp(current_asmdata.CurrAsmList,elesize,elealign,tt_normal,location.reference)
+ else
+ tg.GetTemp(current_asmdata.CurrAsmList,(tarraydef(resultdef).highrange+1)*elesize,resultdef.alignment,tt_normal,location.reference);
+ href:=location.reference;
+ { Process nodes in array constructor }
+ hp:=self;
+ while assigned(hp) do
+ begin
+ if assigned(hp.left) then
+ begin
+ freetemp:=true;
+ if (hp.left.expectloc=LOC_JUMP) then
+ begin
+ otlabel:=current_procinfo.CurrTrueLabel;
+ oflabel:=current_procinfo.CurrFalseLabel;
+ current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
+ current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel);
+ end;
+ secondpass(hp.left);
+ { Move flags and jump in register }
+ if hp.left.location.loc in [LOC_FLAGS,LOC_JUMP] then
+ location_force_reg(current_asmdata.CurrAsmList,hp.left.location,def_cgsize(hp.left.resultdef),false);
+
+ if (hp.left.location.loc=LOC_JUMP) then
+ begin
+ if (hp.left.expectloc<>LOC_JUMP) then
+ internalerror(2007103101);
+ current_procinfo.CurrTrueLabel:=otlabel;
+ current_procinfo.CurrFalseLabel:=oflabel;
+ end;
+
+ if dovariant then
+ begin
+ { find the correct vtype value }
+ vtype:=$ff;
+ vaddr:=false;
+ lt:=hp.left.resultdef;
+ case lt.typ of
+ enumdef,
+ orddef :
+ begin
+ if is_64bit(lt) then
+ begin
+ case torddef(lt).ordtype of
+ scurrency:
+ vtype:=vtCurrency;
+ s64bit:
+ vtype:=vtInt64;
+ u64bit:
+ vtype:=vtQWord;
+ end;
+ freetemp:=false;
+ vaddr:=true;
+ end
+ else if (lt.typ=enumdef) or
+ is_integer(lt) then
+ vtype:=vtInteger
+ else
+ if is_boolean(lt) then
+ vtype:=vtBoolean
+ else
+ if (lt.typ=orddef) then
+ begin
+ case torddef(lt).ordtype of
+ uchar:
+ vtype:=vtChar;
+ uwidechar:
+ vtype:=vtWideChar;
+ end;
+ end;
+ end;
+ floatdef :
+ begin
+ if is_currency(lt) then
+ vtype:=vtCurrency
+ else
+ vtype:=vtExtended;
+ freetemp:=false;
+ vaddr:=true;
+ end;
+ procvardef,
+ pointerdef :
+ begin
+ if is_pchar(lt) then
+ vtype:=vtPChar
+ else if is_pwidechar(lt) then
+ vtype:=vtPWideChar
+ else
+ vtype:=vtPointer;
+ end;
+ variantdef :
+ begin
+ vtype:=vtVariant;
+ vaddr:=true;
+ freetemp:=false;
+ end;
+ classrefdef :
+ vtype:=vtClass;
+ objectdef :
+ if is_interface(lt) then
+ vtype:=vtInterface
+ { vtObject really means a class based on TObject }
+ else if is_class(lt) then
+ vtype:=vtObject
+ else
+ internalerror(200505171);
+ stringdef :
+ begin
+ if is_shortstring(lt) then
+ begin
+ vtype:=vtString;
+ vaddr:=true;
+ freetemp:=false;
+ end
+ else
+ if is_ansistring(lt) then
+ begin
+ vtype:=vtAnsiString;
+ freetemp:=false;
+ end
+ else
+ if is_widestring(lt) then
+ begin
+ vtype:=vtWideString;
+ freetemp:=false;
+ end
+ else
+ if is_unicodestring(lt) then
+ begin
+ vtype:=vtUnicodeString;
+ freetemp:=false;
+ end;
+ end;
+ end;
+ if vtype=$ff then
+ internalerror(14357);
+ { write changing field update href to the next element }
+ inc(href.offset,sizeof(pint));
+ if vaddr then
+ begin
+ location_force_mem(current_asmdata.CurrAsmList,hp.left.location);
+ tmpreg:=cg.getaddressregister(current_asmdata.CurrAsmList);
+ cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,hp.left.location.reference,tmpreg);
+ cg.a_load_reg_ref(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,tmpreg,href);
+ end
+ else
+ cg.a_load_loc_ref(current_asmdata.CurrAsmList,OS_ADDR,hp.left.location,href);
+ { update href to the vtype field and write it }
+ dec(href.offset,sizeof(pint));
+ cg.a_load_const_ref(current_asmdata.CurrAsmList, OS_INT,vtype,href);
+ { goto next array element }
+ inc(href.offset,sizeof(pint)*2);
+ end
+ else
+ { normal array constructor of the same type }
+ begin
+ if is_managed_type(resultdef) then
+ freetemp:=false;
+ case hp.left.location.loc of
+ LOC_MMREGISTER,
+ LOC_CMMREGISTER:
+ cg.a_loadmm_reg_ref(current_asmdata.CurrAsmList,hp.left.location.size,hp.left.location.size,
+ hp.left.location.register,href,mms_movescalar);
+ LOC_FPUREGISTER,
+ LOC_CFPUREGISTER :
+ cg.a_loadfpu_reg_ref(current_asmdata.CurrAsmList,hp.left.location.size,hp.left.location.size,hp.left.location.register,href);
+ LOC_REFERENCE,
+ LOC_CREFERENCE :
+ begin
+ if is_shortstring(hp.left.resultdef) then
+ cg.g_copyshortstring(current_asmdata.CurrAsmList,hp.left.location.reference,href,
+ Tstringdef(hp.left.resultdef).len)
+ else
+ cg.g_concatcopy(current_asmdata.CurrAsmList,hp.left.location.reference,href,elesize);
+ end;
+ else
+ begin
+{$ifndef cpu64bitalu}
+ if hp.left.location.size in [OS_64,OS_S64] then
+ cg64.a_load64_loc_ref(current_asmdata.CurrAsmList,hp.left.location,href)
+ else
+{$endif not cpu64bitalu}
+ cg.a_load_loc_ref(current_asmdata.CurrAsmList,hp.left.location.size,hp.left.location,href);
+ end;
+ end;
+ inc(href.offset,elesize);
+ end;
+ if freetemp then
+ location_freetemp(current_asmdata.CurrAsmList,hp.left.location);
+ end;
+ { load next entry }
+ hp:=tarrayconstructornode(hp.right);
+ end;
+ end;
+
+
+{*****************************************************************************
+ SecondRTTI
+*****************************************************************************}
+
+ procedure tcgrttinode.pass_generate_code;
+ begin
+ location_reset_ref(location,LOC_CREFERENCE,OS_NO,sizeof(pint));
+ case rttidatatype of
+ rdt_normal:
+ location.reference.symbol:=RTTIWriter.get_rtti_label(rttidef,rttitype);
+ rdt_ord2str:
+ location.reference.symbol:=RTTIWriter.get_rtti_label_ord2str(rttidef,rttitype);
+ rdt_str2ord:
+ location.reference.symbol:=RTTIWriter.get_rtti_label_str2ord(rttidef,rttitype);
+ end;
+ end;
+
+
+
+begin
+ cloadnode:=tcgloadnode;
+ cassignmentnode:=tcgassignmentnode;
+ carrayconstructornode:=tcgarrayconstructornode;
+ crttinode:=tcgrttinode;
+end.
diff --git a/closures/compiler/ncgmat.pas b/closures/compiler/ncgmat.pas
new file mode 100644
index 0000000000..2d47e78ec4
--- /dev/null
+++ b/closures/compiler/ncgmat.pas
@@ -0,0 +1,519 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate generic mathematical nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit ncgmat;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,nmat,cpubase,cgbase;
+
+ type
+ tcgunaryminusnode = class(tunaryminusnode)
+ protected
+ { This routine is called to change the sign of the
+ floating point value in the floating point
+ register r.
+
+ This routine should be overridden, since
+ the generic version is not optimal at all. The
+ generic version assumes that floating
+ point values are stored in the register
+ in IEEE-754 format.
+ }
+ procedure emit_float_sign_change(r: tregister; _size : tcgsize);virtual;
+{$ifdef SUPPORT_MMX}
+ procedure second_mmx;virtual;abstract;
+{$endif SUPPORT_MMX}
+{$ifndef cpu64bitalu}
+ procedure second_64bit;virtual;
+{$endif not cpu64bitalu}
+ procedure second_integer;virtual;
+ procedure second_float;virtual;
+ public
+ procedure pass_generate_code;override;
+ end;
+
+ tcgmoddivnode = class(tmoddivnode)
+ procedure pass_generate_code;override;
+ protected
+ { This routine must do an actual 32-bit division, be it
+ signed or unsigned. The result must set into the the
+ @var(num) register.
+
+ @param(signed Indicates if the division must be signed)
+ @param(denum Register containing the denominator
+ @param(num Register containing the numerator, will also receive result)
+
+ The actual optimizations regarding shifts have already
+ been done and emitted, so this should really a do a divide.
+ }
+ procedure emit_div_reg_reg(signed: boolean;denum,num : tregister);virtual;abstract;
+ { This routine must do an actual 32-bit modulo, be it
+ signed or unsigned. The result must set into the the
+ @var(num) register.
+
+ @param(signed Indicates if the modulo must be signed)
+ @param(denum Register containing the denominator
+ @param(num Register containing the numerator, will also receive result)
+
+ The actual optimizations regarding shifts have already
+ been done and emitted, so this should really a do a modulo.
+ }
+ procedure emit_mod_reg_reg(signed: boolean;denum,num : tregister);virtual;abstract;
+{$ifndef cpu64bitalu}
+ { This routine must do an actual 64-bit division, be it
+ signed or unsigned. The result must set into the the
+ @var(num) register.
+
+ @param(signed Indicates if the division must be signed)
+ @param(denum Register containing the denominator
+ @param(num Register containing the numerator, will also receive result)
+
+ The actual optimizations regarding shifts have already
+ been done and emitted, so this should really a do a divide.
+ Currently, this routine should only be implemented on
+ 64-bit systems, otherwise a helper is called in 1st pass.
+ }
+ procedure emit64_div_reg_reg(signed: boolean;denum,num : tregister64);virtual;
+{$endif not cpu64bitalu}
+ end;
+
+ tcgshlshrnode = class(tshlshrnode)
+{$ifndef cpu64bitalu}
+ procedure second_64bit;virtual;
+{$endif not cpu64bitalu}
+ procedure second_integer;virtual;
+ procedure pass_generate_code;override;
+ end;
+
+ tcgnotnode = class(tnotnode)
+ protected
+ procedure second_boolean;virtual;abstract;
+{$ifdef SUPPORT_MMX}
+ procedure second_mmx;virtual;abstract;
+{$endif SUPPORT_MMX}
+{$ifndef cpu64bitalu}
+ procedure second_64bit;virtual;
+{$endif not cpu64bitalu}
+ procedure second_integer;virtual;
+ public
+ procedure pass_generate_code;override;
+ end;
+
+
+implementation
+
+ uses
+ globtype,systems,
+ cutils,verbose,globals,
+ symconst,aasmbase,aasmtai,aasmdata,aasmcpu,defutil,
+ parabase,
+ pass_2,
+ ncon,
+ tgobj,ncgutil,cgobj,cgutils,paramgr
+{$ifndef cpu64bitalu}
+ ,cg64f32
+{$endif not cpu64bitalu}
+ ;
+
+{*****************************************************************************
+ TCGUNARYMINUSNODE
+*****************************************************************************}
+
+ procedure tcgunaryminusnode.emit_float_sign_change(r: tregister; _size : tcgsize);
+ var
+ href,
+ href2 : treference;
+ begin
+ { get a temporary memory reference to store the floating
+ point value
+ }
+ tg.gettemp(current_asmdata.CurrAsmList,tcgsize2size[_size],tcgsize2size[_size],tt_normal,href);
+ { store the floating point value in the temporary memory area }
+ cg.a_loadfpu_reg_ref(current_asmdata.CurrAsmList,_size,_size,r,href);
+ { only single and double ieee are supported, for little endian
+ the signed bit is in the second dword }
+ href2:=href;
+ case _size of
+ OS_F64 :
+ if target_info.endian = endian_little then
+ inc(href2.offset,4);
+ OS_F32 :
+ ;
+ else
+ internalerror(200406021);
+ end;
+ { flip sign-bit (bit 31/63) of single/double }
+ cg.a_op_const_ref(current_asmdata.CurrAsmList,OP_XOR,OS_32,aint($80000000),href2);
+ cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,_size,_size,href,r);
+ tg.ungetiftemp(current_asmdata.CurrAsmList,href);
+ end;
+
+
+{$ifndef cpu64bitalu}
+ procedure tcgunaryminusnode.second_64bit;
+ var
+ tr: tregister;
+ hl: tasmlabel;
+ begin
+ secondpass(left);
+ location_reset(location,LOC_REGISTER,left.location.size);
+ location.register64.reglo:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+ location.register64.reghi:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+ cg64.a_op64_loc_reg(current_asmdata.CurrAsmList,OP_NEG,OS_S64,
+ left.location,joinreg64(location.register64.reglo,location.register64.reghi));
+ { there's only overflow in case left was low(int64) -> -left = left }
+ if (cs_check_overflow in current_settings.localswitches) then
+ begin
+ tr:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_XOR,OS_INT,
+ aint($80000000),location.register64.reghi,tr);
+ cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_OR,OS_INT,
+ location.register64.reglo,tr);
+ current_asmdata.getjumplabel(hl);
+ cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,OS_INT,OC_NE,0,tr,hl);
+ cg.a_call_name(current_asmdata.CurrAsmList,'FPC_OVERFLOW',false);
+ cg.a_label(current_asmdata.CurrAsmList,hl);
+ end;
+ end;
+{$endif not cpu64bitalu}
+
+ procedure tcgunaryminusnode.second_float;
+ begin
+ secondpass(left);
+ location_reset(location,LOC_FPUREGISTER,def_cgsize(resultdef));
+ case left.location.loc of
+ LOC_REFERENCE,
+ LOC_CREFERENCE :
+ begin
+ location.register:=cg.getfpuregister(current_asmdata.CurrAsmList,location.size);
+ cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,
+ left.location.size,location.size,
+ left.location.reference,location.register);
+ emit_float_sign_change(location.register,def_cgsize(left.resultdef));
+ end;
+ LOC_FPUREGISTER:
+ begin
+ location.register:=left.location.register;
+ emit_float_sign_change(location.register,def_cgsize(left.resultdef));
+ end;
+ LOC_CFPUREGISTER:
+ begin
+ location.register:=cg.getfpuregister(current_asmdata.CurrAsmList,location.size);
+ cg.a_loadfpu_reg_reg(current_asmdata.CurrAsmList,left.location.size,location.size,left.location.register,location.register);
+ emit_float_sign_change(location.register,def_cgsize(left.resultdef));
+ end;
+ else
+ internalerror(200306021);
+ end;
+ end;
+
+
+ procedure tcgunaryminusnode.second_integer;
+ var
+ hl: tasmlabel;
+ begin
+ secondpass(left);
+ { load left operator in a register }
+ location_copy(location,left.location);
+ location_force_reg(current_asmdata.CurrAsmList,location,OS_SINT,false);
+ cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_NEG,OS_SINT,location.register,location.register);
+
+ if (cs_check_overflow in current_settings.localswitches) then
+ begin
+ current_asmdata.getjumplabel(hl);
+ cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,OS_SINT,OC_NE,low(aint),location.register,hl);
+ cg.a_call_name(current_asmdata.CurrAsmList,'FPC_OVERFLOW',false);
+ cg.a_label(current_asmdata.CurrAsmList,hl);
+ end;
+ end;
+
+
+ procedure tcgunaryminusnode.pass_generate_code;
+ begin
+{$ifndef cpu64bitalu}
+ if is_64bit(left.resultdef) then
+ second_64bit
+ else
+{$endif not cpu64bitalu}
+{$ifdef SUPPORT_MMX}
+ if (cs_mmx in current_settings.localswitches) and is_mmx_able_array(left.resultdef) then
+ second_mmx
+ else
+{$endif SUPPORT_MMX}
+ if (left.resultdef.typ=floatdef) then
+ second_float
+ else
+ second_integer;
+ end;
+
+
+{*****************************************************************************
+ TCGMODDIVNODE
+*****************************************************************************}
+
+{$ifndef cpu64bitalu}
+ procedure tcgmoddivnode.emit64_div_reg_reg(signed: boolean; denum,num:tregister64);
+ begin
+ { handled in pass_1 already, unless pass_1 is
+ overridden
+ }
+ { should be handled in pass_1 (JM) }
+ internalerror(200109052);
+ end;
+{$endif not cpu64bitalu}
+
+
+ procedure tcgmoddivnode.pass_generate_code;
+ var
+ hreg1 : tregister;
+ hdenom : tregister;
+ power : longint;
+ hl : tasmlabel;
+ paraloc1 : tcgpara;
+ opsize : tcgsize;
+ begin
+ secondpass(left);
+ if codegenerror then
+ exit;
+ secondpass(right);
+ if codegenerror then
+ exit;
+ location_copy(location,left.location);
+
+{$ifndef cpu64bitalu}
+ if is_64bit(resultdef) then
+ begin
+ if is_signed(left.resultdef) then
+ opsize:=OS_S64
+ else
+ opsize:=OS_64;
+
+ { this code valid for 64-bit cpu's only ,
+ otherwise helpers are called in pass_1
+ }
+ location_force_reg(current_asmdata.CurrAsmList,location,opsize,false);
+ location_copy(location,left.location);
+ location_force_reg(current_asmdata.CurrAsmList,right.location,opsize,false);
+ emit64_div_reg_reg(is_signed(left.resultdef),
+ joinreg64(right.location.register64.reglo,right.location.register64.reghi),
+ joinreg64(location.register64.reglo,location.register64.reghi));
+ end
+ else
+{$endif not cpu64bitalu}
+ begin
+ if is_signed(left.resultdef) then
+ opsize:=OS_SINT
+ else
+ opsize:=OS_INT;
+
+ { put numerator in register }
+ location_force_reg(current_asmdata.CurrAsmList,left.location,opsize,false);
+ hreg1:=left.location.register;
+
+ if (nodetype=divn) and
+ (right.nodetype=ordconstn) and
+ ispowerof2(tordconstnode(right).value.svalue,power) then
+ Begin
+ { for signed numbers, the numerator must be adjusted before the
+ shift instruction, but not wih unsigned numbers! Otherwise,
+ "Cardinal($ffffffff) div 16" overflows! (JM) }
+ If is_signed(left.resultdef) Then
+ Begin
+ current_asmdata.getjumplabel(hl);
+ cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,OS_INT,OC_GT,0,hreg1,hl);
+ if power=1 then
+ cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_ADD,OS_INT,1,hreg1)
+ else
+ cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_ADD,OS_INT,Tordconstnode(right).value.svalue-1,hreg1);
+ cg.a_label(current_asmdata.CurrAsmList,hl);
+ cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_SAR,OS_INT,power,hreg1);
+ End
+ Else { not signed }
+ cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_SHR,OS_INT,power,hreg1);
+ End
+ else
+ begin
+ { bring denominator to hdenom }
+ { hdenom is always free, it's }
+ { only used for temporary }
+ { purposes }
+ hdenom := cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+ cg.a_load_loc_reg(current_asmdata.CurrAsmList,right.location.size,right.location,hdenom);
+ { verify if the divisor is zero, if so return an error
+ immediately
+ }
+ current_asmdata.getjumplabel(hl);
+ cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,OS_INT,OC_NE,0,hdenom,hl);
+ paraloc1.init;
+ paramanager.getintparaloc(pocall_default,1,paraloc1);
+ cg.a_load_const_cgpara(current_asmdata.CurrAsmList,OS_S32,aint(200),paraloc1);
+ paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc1);
+ cg.a_call_name(current_asmdata.CurrAsmList,'FPC_HANDLEERROR',false);
+ paraloc1.done;
+ cg.a_label(current_asmdata.CurrAsmList,hl);
+ if nodetype = modn then
+ emit_mod_reg_reg(is_signed(left.resultdef),hdenom,hreg1)
+ else
+ emit_div_reg_reg(is_signed(left.resultdef),hdenom,hreg1);
+ end;
+ location_reset(location,LOC_REGISTER,opsize);
+ location.register:=hreg1;
+ end;
+ cg.g_overflowcheck(current_asmdata.CurrAsmList,location,resultdef);
+ end;
+
+
+{*****************************************************************************
+ TCGSHLRSHRNODE
+*****************************************************************************}
+
+
+{$ifndef cpu64bitalu}
+ procedure tcgshlshrnode.second_64bit;
+ begin
+ { already hanled in 1st pass }
+ internalerror(2002081501);
+ end;
+{$endif not cpu64bitalu}
+
+
+ procedure tcgshlshrnode.second_integer;
+ var
+ op : topcg;
+ hcountreg : tregister;
+ opsize : tcgsize;
+ begin
+ { determine operator }
+ case nodetype of
+ shln: op:=OP_SHL;
+ shrn: op:=OP_SHR;
+ end;
+{$ifdef cpunodefaultint}
+ opsize:=left.location.size;
+{$else cpunodefaultint}
+ { load left operators in a register }
+ if is_signed(left.resultdef) then
+ opsize:=OS_SINT
+ else
+ opsize:=OS_INT;
+{$endif cpunodefaultint}
+
+ location_force_reg(current_asmdata.CurrAsmList,left.location,opsize,true);
+ location_reset(location,LOC_REGISTER,opsize);
+ location.register:=cg.getintregister(current_asmdata.CurrAsmList,opsize);
+
+ { shifting by a constant directly coded: }
+ if (right.nodetype=ordconstn) then
+ begin
+ { l shl 32 should 0 imho, but neither TP nor Delphi do it in this way (FK)
+ if right.value<=31 then
+ }
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,op,location.size,
+ tordconstnode(right).value.uvalue and 31,left.location.register,location.register);
+ {
+ else
+ emit_reg_reg(A_XOR,S_L,hregister1,
+ hregister1);
+ }
+ end
+ else
+ begin
+ { load right operators in a register - this
+ is done since most target cpu which will use this
+ node do not support a shift count in a mem. location (cec)
+ }
+ if right.location.loc<>LOC_REGISTER then
+ begin
+ hcountreg:=cg.getintregister(current_asmdata.CurrAsmList,opsize);
+ cg.a_load_loc_reg(current_asmdata.CurrAsmList,right.location.size,right.location,hcountreg);
+ end
+ else
+ hcountreg:=right.location.register;
+ cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,op,opsize,hcountreg,left.location.register,location.register);
+ end;
+ end;
+
+
+ procedure tcgshlshrnode.pass_generate_code;
+ begin
+ secondpass(left);
+ secondpass(right);
+{$ifndef cpu64bitalu}
+ if is_64bit(left.resultdef) then
+ second_64bit
+ else
+{$endif not cpu64bitalu}
+ second_integer;
+ end;
+
+
+{*****************************************************************************
+ TCGNOTNODE
+*****************************************************************************}
+
+{$ifndef cpu64bitalu}
+ procedure tcgnotnode.second_64bit;
+ begin
+ secondpass(left);
+ location_force_reg(current_asmdata.CurrAsmList,left.location,def_cgsize(left.resultdef),false);
+ location_copy(location,left.location);
+ { perform the NOT operation }
+ cg64.a_op64_reg_reg(current_asmdata.CurrAsmList,OP_NOT,location.size,left.location.register64,location.register64);
+ end;
+{$endif not cpu64bitalu}
+
+
+ procedure tcgnotnode.second_integer;
+ begin
+ secondpass(left);
+ location_force_reg(current_asmdata.CurrAsmList,left.location,def_cgsize(left.resultdef),false);
+ location_copy(location,left.location);
+ { perform the NOT operation }
+ cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_NOT,location.size,location.register,location.register);
+ end;
+
+
+ procedure tcgnotnode.pass_generate_code;
+ begin
+ if is_boolean(resultdef) then
+ second_boolean
+{$ifdef SUPPORT_MMX}
+ else if (cs_mmx in current_settings.localswitches) and is_mmx_able_array(left.resultdef) then
+ second_mmx
+{$endif SUPPORT_MMX}
+{$ifndef cpu64bitalu}
+ else if is_64bit(left.resultdef) then
+ second_64bit
+{$endif not cpu64bitalu}
+ else
+ second_integer;
+ end;
+
+begin
+ cmoddivnode:=tcgmoddivnode;
+ cunaryminusnode:=tcgunaryminusnode;
+ cshlshrnode:=tcgshlshrnode;
+ cnotnode:=tcgnotnode;
+end.
diff --git a/closures/compiler/ncgmem.pas b/closures/compiler/ncgmem.pas
new file mode 100644
index 0000000000..3e77038df9
--- /dev/null
+++ b/closures/compiler/ncgmem.pas
@@ -0,0 +1,1005 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate assembler for memory related nodes which are
+ the same for all (most?) processors
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit ncgmem;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ globtype,cgbase,cpuinfo,cpubase,
+ node,nmem;
+
+ type
+ tcgloadvmtaddrnode = class(tloadvmtaddrnode)
+ procedure pass_generate_code;override;
+ end;
+
+ tcgloadparentfpnode = class(tloadparentfpnode)
+ procedure pass_generate_code;override;
+ end;
+
+ tcgaddrnode = class(taddrnode)
+ procedure pass_generate_code;override;
+ end;
+
+ tcgderefnode = class(tderefnode)
+ procedure pass_generate_code;override;
+ end;
+
+ tcgsubscriptnode = class(tsubscriptnode)
+ procedure pass_generate_code;override;
+ end;
+
+ tcgwithnode = class(twithnode)
+ procedure pass_generate_code;override;
+ end;
+
+ tcgvecnode = class(tvecnode)
+ function get_mul_size : aint;
+ private
+ procedure rangecheck_array;
+ procedure rangecheck_string;
+ protected
+ {# This routine is used to calculate the address of the reference.
+ On entry reg contains the index in the array,
+ and l contains the size of each element in the array.
+ This routine should update location.reference correctly,
+ so it points to the correct address.
+ }
+ procedure update_reference_reg_mul(maybe_const_reg:tregister;l:aint);virtual;
+ procedure update_reference_reg_packed(maybe_const_reg:tregister;l:aint);virtual;
+ procedure second_wideansistring;virtual;
+ procedure second_dynamicarray;virtual;
+ public
+ procedure pass_generate_code;override;
+ end;
+
+
+implementation
+
+ uses
+ systems,
+ cutils,cclasses,verbose,globals,constexp,
+ symconst,symdef,symsym,symtable,defutil,paramgr,
+ aasmbase,aasmtai,aasmdata,
+ procinfo,pass_2,parabase,
+ pass_1,nld,ncon,nadd,nutils,
+ cgutils,cgobj,
+ tgobj,ncgutil,objcgutl
+ ;
+
+
+{*****************************************************************************
+ TCGLOADVMTADDRNODE
+*****************************************************************************}
+
+ procedure tcgloadvmtaddrnode.pass_generate_code;
+ var
+ href : treference;
+ pool : THashSet;
+ entry : PHashSetItem;
+
+ begin
+ location_reset(location,LOC_REGISTER,OS_ADDR);
+ if (left.nodetype=typen) then
+ begin
+ location.register:=cg.getaddressregister(current_asmdata.CurrAsmList);
+ if not is_objcclass(left.resultdef) then
+ begin
+ reference_reset_symbol(href,
+ current_asmdata.RefAsmSymbol(tobjectdef(tclassrefdef(resultdef).pointeddef).vmt_mangledname),0,
+ sizeof(pint));
+ cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,href,location.register);
+ end
+ else
+ begin
+ pool:=current_asmdata.ConstPools[sp_objcclassnamerefs];
+ entry:=pool.FindOrAdd(@tobjectdef(left.resultdef).objextname^[1],length(tobjectdef(left.resultdef).objextname^));
+ if (target_info.system in systems_objc_nfabi) then
+ begin
+ { find/add necessary classref/classname pool entries }
+ objcfinishclassrefnfpoolentry(entry,tobjectdef(left.resultdef));
+ end
+ else
+ begin
+ { find/add necessary classref/classname pool entries }
+ objcfinishstringrefpoolentry(entry,sp_objcclassnames,sec_objc_cls_refs,sec_objc_class_names);
+ end;
+ reference_reset_symbol(href,tasmlabel(entry^.Data),0,sizeof(pint));
+ cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,href,location.register);
+ end;
+ end
+ else
+ begin
+ { left contains self, load vmt from self }
+ secondpass(left);
+ gen_load_vmt_register(current_asmdata.CurrAsmList,tobjectdef(left.resultdef),left.location,location.register);
+ end;
+ end;
+
+
+{*****************************************************************************
+ TCGLOADPARENTFPNODE
+*****************************************************************************}
+
+ procedure tcgloadparentfpnode.pass_generate_code;
+ var
+ currpi : tprocinfo;
+ hsym : tparavarsym;
+ href : treference;
+ begin
+ if (current_procinfo.procdef.parast.symtablelevel=parentpd.parast.symtablelevel) then
+ begin
+ location_reset(location,LOC_REGISTER,OS_ADDR);
+ location.register:=current_procinfo.framepointer;
+ end
+ else
+ begin
+ currpi:=current_procinfo;
+ location_reset(location,LOC_REGISTER,OS_ADDR);
+ location.register:=cg.getaddressregister(current_asmdata.CurrAsmList);
+ { load framepointer of current proc }
+ hsym:=tparavarsym(currpi.procdef.parast.Find('parentfp'));
+ if not assigned(hsym) then
+ internalerror(200309281);
+ cg.a_load_loc_reg(current_asmdata.CurrAsmList,OS_ADDR,hsym.localloc,location.register);
+ { walk parents }
+ while (currpi.procdef.owner.symtablelevel>parentpd.parast.symtablelevel) do
+ begin
+ currpi:=currpi.parent;
+ if not assigned(currpi) then
+ internalerror(200311201);
+ hsym:=tparavarsym(currpi.procdef.parast.Find('parentfp'));
+ if not assigned(hsym) then
+ internalerror(200309282);
+
+ if hsym.localloc.loc<>LOC_REFERENCE then
+ internalerror(200309283);
+
+ reference_reset_base(href,location.register,hsym.localloc.reference.offset,sizeof(pint));
+ cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,href,location.register);
+ end;
+ end;
+ end;
+
+
+{*****************************************************************************
+ TCGADDRNODE
+*****************************************************************************}
+
+ procedure tcgaddrnode.pass_generate_code;
+ begin
+ secondpass(left);
+
+ location_reset(location,LOC_REGISTER,OS_ADDR);
+ location.register:=cg.getaddressregister(current_asmdata.CurrAsmList);
+ if not(left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
+ { on x86_64-win64, array of chars can be returned in registers, however,
+ when passing these arrays to other functions, the compiler wants to take
+ the address of the array so when the addrnode has been created internally,
+ we have to force the data into memory, see also tw14388.pp
+ }
+ if nf_internal in flags then
+ location_force_mem(current_asmdata.CurrAsmList,left.location)
+ else
+ internalerror(2006111510);
+ cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,left.location.reference,location.register);
+ end;
+
+
+{*****************************************************************************
+ TCGDEREFNODE
+*****************************************************************************}
+
+ procedure tcgderefnode.pass_generate_code;
+ var
+ paraloc1 : tcgpara;
+ begin
+ secondpass(left);
+ { assume natural alignment, except for packed records }
+ if not(resultdef.typ in [recorddef,objectdef]) or
+ (tabstractrecordsymtable(tabstractrecorddef(resultdef).symtable).usefieldalignment<>1) then
+ location_reset_ref(location,LOC_REFERENCE,def_cgsize(resultdef),resultdef.alignment)
+ else
+ location_reset_ref(location,LOC_REFERENCE,def_cgsize(resultdef),1);
+ if not(left.location.loc in [LOC_CREGISTER,LOC_REGISTER,LOC_CREFERENCE,LOC_REFERENCE,LOC_CONSTANT]) then
+ location_force_reg(current_asmdata.CurrAsmList,left.location,OS_ADDR,true);
+ case left.location.loc of
+ LOC_CREGISTER,
+ LOC_REGISTER:
+ begin
+ maybechangeloadnodereg(current_asmdata.CurrAsmList,left,true);
+ {$ifdef cpu_uses_separate_address_registers}
+ if getregtype(left.location.register)<>R_ADDRESSREGISTER then
+ begin
+ location.reference.base := cg.getaddressregister(current_asmdata.CurrAsmList);
+ cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,left.location.register,
+ location.reference.base);
+ end
+ else
+ {$endif}
+ location.reference.base := left.location.register;
+ end;
+ LOC_CREFERENCE,
+ LOC_REFERENCE:
+ begin
+ location.reference.base:=cg.getaddressregister(current_asmdata.CurrAsmList);
+ cg.a_load_loc_reg(current_asmdata.CurrAsmList,OS_ADDR,left.location,location.reference.base);
+ end;
+ LOC_CONSTANT:
+ begin
+ location.reference.offset:=left.location.value;
+ end;
+ else
+ internalerror(200507031);
+ end;
+ if (cs_use_heaptrc in current_settings.globalswitches) and
+ (cs_checkpointer in current_settings.localswitches) and
+ not(cs_compilesystem in current_settings.moduleswitches) and
+ not(tpointerdef(left.resultdef).is_far) and
+ not(nf_no_checkpointer in flags) and
+ { can be NR_NO in case of LOC_CONSTANT }
+ (location.reference.base<>NR_NO) then
+ begin
+ paraloc1.init;
+ paramanager.getintparaloc(pocall_default,1,paraloc1);
+ cg.a_load_reg_cgpara(current_asmdata.CurrAsmList, OS_ADDR,location.reference.base,paraloc1);
+ paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc1);
+ paraloc1.done;
+ cg.allocallcpuregisters(current_asmdata.CurrAsmList);
+ cg.a_call_name(current_asmdata.CurrAsmList,'FPC_CHECKPOINTER',false);
+ cg.deallocallcpuregisters(current_asmdata.CurrAsmList);
+ end;
+ end;
+
+
+{*****************************************************************************
+ TCGSUBSCRIPTNODE
+*****************************************************************************}
+
+ procedure tcgsubscriptnode.pass_generate_code;
+ var
+ sym: tasmsymbol;
+ paraloc1 : tcgpara;
+ hreg : tregister;
+ tmpref: treference;
+ sref: tsubsetreference;
+ begin
+ secondpass(left);
+ if codegenerror then
+ exit;
+ paraloc1.init;
+ { several object types must be dereferenced implicitly }
+ if is_implicit_pointer_object_type(left.resultdef) then
+ begin
+ if not is_managed_type(left.resultdef) then
+ begin
+ { the contents of a class are aligned to a sizeof(pointer) }
+ location_reset_ref(location,LOC_REFERENCE,def_cgsize(resultdef),sizeof(pint));
+ case left.location.loc of
+ LOC_CREGISTER,
+ LOC_REGISTER:
+ begin
+ {$ifdef cpu_uses_separate_address_registers}
+ if getregtype(left.location.register)<>R_ADDRESSREGISTER then
+ begin
+ location.reference.base:=rg.getaddressregister(current_asmdata.CurrAsmList);
+ cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,
+ left.location.register,location.reference.base);
+ end
+ else
+ {$endif}
+ location.reference.base := left.location.register;
+ end;
+ LOC_CREFERENCE,
+ LOC_REFERENCE:
+ begin
+ location.reference.base:=cg.getaddressregister(current_asmdata.CurrAsmList);
+ cg.a_load_loc_reg(current_asmdata.CurrAsmList,OS_ADDR,left.location,location.reference.base);
+ end;
+ LOC_CONSTANT:
+ begin
+ { can happen with @classtype(pointerconst).field }
+ location.reference.offset:=left.location.value;
+ end;
+ else
+ internalerror(2009092401);
+ end;
+ { implicit deferencing }
+ if (cs_use_heaptrc in current_settings.globalswitches) and
+ (cs_checkpointer in current_settings.localswitches) and
+ not(cs_compilesystem in current_settings.moduleswitches) then
+ begin
+ paramanager.getintparaloc(pocall_default,1,paraloc1);
+ cg.a_load_reg_cgpara(current_asmdata.CurrAsmList, OS_ADDR,location.reference.base,paraloc1);
+ paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc1);
+ cg.allocallcpuregisters(current_asmdata.CurrAsmList);
+ cg.a_call_name(current_asmdata.CurrAsmList,'FPC_CHECKPOINTER',false);
+ cg.deallocallcpuregisters(current_asmdata.CurrAsmList);
+ end;
+ end
+ else
+ { reference-counted implicit pointer object types don't have
+ fields -> cannot be subscripted (calls are handled via call
+ nodes) }
+ internalerror(2011011901);
+ end
+ else
+ begin
+ location_copy(location,left.location);
+ { some abi's require that functions return (some) records in }
+ { registers }
+ case location.loc of
+ LOC_REFERENCE,
+ LOC_CREFERENCE:
+ ;
+ LOC_REGISTER,
+ LOC_CREGISTER,
+ LOC_MMREGISTER,
+ LOC_FPUREGISTER:
+ begin
+ // in case the result is not something that can be put
+ // into an integer register (e.g.
+ // function_returning_record().non_regable_field, or
+ // a function returning a value > sizeof(intreg))
+ // -> force to memory
+ if not tstoreddef(left.resultdef).is_intregable or
+ not tstoreddef(resultdef).is_intregable or
+ (location.loc in [LOC_MMREGISTER,LOC_FPUREGISTER]) then
+ location_force_mem(current_asmdata.CurrAsmList,location)
+ else
+ begin
+ if (left.location.loc = LOC_REGISTER) then
+ location.loc := LOC_SUBSETREG
+ else
+ location.loc := LOC_CSUBSETREG;
+ location.size:=def_cgsize(resultdef);
+ location.sreg.subsetreg := left.location.register;
+ location.sreg.subsetregsize := left.location.size;
+ if not is_packed_record_or_object(left.resultdef) then
+ begin
+ if (target_info.endian = ENDIAN_BIG) then
+ location.sreg.startbit := (tcgsize2size[location.sreg.subsetregsize] - tcgsize2size[location.size] - vs.fieldoffset) * 8
+ else
+ location.sreg.startbit := (vs.fieldoffset * 8);
+ location.sreg.bitlen := tcgsize2size[location.size] * 8;
+ end
+ else
+ begin
+ location.sreg.bitlen := resultdef.packedbitsize;
+ if (target_info.endian = ENDIAN_BIG) then
+ location.sreg.startbit := (tcgsize2size[location.sreg.subsetregsize]*8 - location.sreg.bitlen) - vs.fieldoffset
+ else
+ location.sreg.startbit := vs.fieldoffset;
+ end;
+ end;
+ end;
+ LOC_SUBSETREG,
+ LOC_CSUBSETREG:
+ begin
+ location.size:=def_cgsize(resultdef);
+ if not is_packed_record_or_object(left.resultdef) then
+ begin
+ if (target_info.endian = ENDIAN_BIG) then
+ inc(location.sreg.startbit, (left.resultdef.size - tcgsize2size[location.size] - vs.fieldoffset) * 8)
+ else
+ inc(location.sreg.startbit, vs.fieldoffset * 8);
+ location.sreg.bitlen := tcgsize2size[location.size] * 8;
+ end
+ else
+ begin
+ location.sreg.bitlen := resultdef.packedbitsize;
+ if (target_info.endian = ENDIAN_BIG) then
+ inc(location.sreg.startbit, left.location.sreg.bitlen - location.sreg.bitlen - vs.fieldoffset)
+ else
+ inc(location.sreg.startbit, vs.fieldoffset);
+ end;
+ end;
+ else
+ internalerror(2006031901);
+ end;
+ end;
+
+ if is_objc_class_or_protocol(left.resultdef) and
+ (target_info.system in systems_objc_nfabi) then
+ begin
+ if (location.loc<>LOC_REFERENCE) or
+ (location.reference.index<>NR_NO) then
+ internalerror(2009092402);
+ { the actual field offset is stored in memory (to solve the
+ "fragile base class" problem: this way the layout of base
+ classes can be changed without breaking programs compiled against
+ earlier versions)
+ }
+ hreg:=cg.g_indirect_sym_load(current_asmdata.CurrAsmList,vs.mangledname,false);
+ { TODO: clean up. g_indirect_sym_load cannot perform
+ a plain load for targets that don't need an indirect load
+ because it's also used in ncgld, but this is not very nice...
+ }
+ if (hreg=NR_NO) then
+ begin
+ sym:=current_asmdata.RefAsmSymbol(vs.mangledname);
+ reference_reset_symbol(tmpref,sym,0,sizeof(pint));
+ location.reference.index:=cg.getaddressregister(current_asmdata.CurrAsmList);
+ end
+ else
+ begin
+ reference_reset_base(tmpref,hreg,0,sizeof(pint));
+ location.reference.index:=hreg;
+ end;
+ cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,tmpref,location.reference.index);
+ { always packrecords C -> natural alignment }
+ location.reference.alignment:=vs.vardef.alignment;
+ end
+ else if (location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
+ begin
+ if not is_packed_record_or_object(left.resultdef) then
+ begin
+ inc(location.reference.offset,vs.fieldoffset);
+ location.reference.alignment:=newalignment(location.reference.alignment,vs.fieldoffset);
+ end
+ else if (vs.fieldoffset mod 8 = 0) and
+ (resultdef.packedbitsize mod 8 = 0) and
+ { is different in case of e.g. packenum 2 and an enum }
+ { which fits in 8 bits }
+ (resultdef.size*8 = resultdef.packedbitsize) then
+ begin
+ inc(location.reference.offset,vs.fieldoffset div 8);
+ location.reference.alignment:=newalignment(location.reference.alignment,vs.fieldoffset div 8);
+ end
+ else
+ begin
+ sref.ref:=location.reference;
+ sref.ref.alignment:=1;
+ sref.bitindexreg:=NR_NO;
+ inc(sref.ref.offset,vs.fieldoffset div 8);
+ sref.startbit:=vs.fieldoffset mod 8;
+ sref.bitlen:=resultdef.packedbitsize;
+ if (left.location.loc=LOC_REFERENCE) then
+ location.loc:=LOC_SUBSETREF
+ else
+ location.loc:=LOC_CSUBSETREF;
+ location.sref:=sref;
+ end;
+ { also update the size of the location }
+ location.size:=def_cgsize(resultdef);
+ end;
+ paraloc1.done;
+ end;
+
+
+{*****************************************************************************
+ TCGWITHNODE
+*****************************************************************************}
+
+ procedure tcgwithnode.pass_generate_code;
+ begin
+ location_reset(location,LOC_VOID,OS_NO);
+
+ if assigned(left) then
+ secondpass(left);
+ end;
+
+
+{*****************************************************************************
+ TCGVECNODE
+*****************************************************************************}
+
+ function tcgvecnode.get_mul_size : aint;
+ begin
+ if nf_memindex in flags then
+ get_mul_size:=1
+ else
+ begin
+ if (left.resultdef.typ=arraydef) then
+ if not is_packed_array(left.resultdef) then
+ get_mul_size:=tarraydef(left.resultdef).elesize
+ else
+ get_mul_size:=tarraydef(left.resultdef).elepackedbitsize
+ else
+ get_mul_size:=resultdef.size;
+ end
+ end;
+
+
+ { this routine must, like any other routine, not change the contents }
+ { of base/index registers of references, as these may be regvars. }
+ { The register allocator can coalesce one LOC_REGISTER being moved }
+ { into another (as their live ranges won't overlap), but not a }
+ { LOC_CREGISTER moved into a LOC_(C)REGISTER most of the time (as }
+ { the live range of the LOC_CREGISTER will most likely overlap the }
+ { the live range of the target LOC_(C)REGISTER) }
+ { The passed register may be a LOC_CREGISTER as well. }
+ procedure tcgvecnode.update_reference_reg_mul(maybe_const_reg:tregister;l:aint);
+ var
+ hreg: tregister;
+ begin
+ if l<>1 then
+ begin
+ hreg:=cg.getaddressregister(current_asmdata.CurrAsmList);
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_IMUL,OS_ADDR,l,maybe_const_reg,hreg);
+ maybe_const_reg:=hreg;
+ end;
+ if location.reference.base=NR_NO then
+ location.reference.base:=maybe_const_reg
+ else if location.reference.index=NR_NO then
+ location.reference.index:=maybe_const_reg
+ else
+ begin
+ hreg:=cg.getaddressregister(current_asmdata.CurrAsmList);
+ cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,location.reference,hreg);
+ reference_reset_base(location.reference,hreg,0,location.reference.alignment);
+ { insert new index register }
+ location.reference.index:=maybe_const_reg;
+ end;
+ { update alignment }
+ if (location.reference.alignment=0) then
+ internalerror(2009020704);
+ location.reference.alignment:=newalignment(location.reference.alignment,l);
+ end;
+
+
+ { see remarks for tcgvecnode.update_reference_reg_mul above }
+ procedure tcgvecnode.update_reference_reg_packed(maybe_const_reg:tregister;l:aint);
+ var
+ sref: tsubsetreference;
+ offsetreg, hreg: tregister;
+ alignpower: aint;
+ temp : longint;
+ begin
+ { only orddefs are bitpacked. Even then we only need special code in }
+ { case the bitpacked *byte size* is not a power of two, otherwise }
+ { everything can be handled using the the regular array code. }
+ if ((l mod 8) = 0) and
+ (ispowerof2(l div 8,temp) or
+ not is_ordinal(resultdef)
+{$ifndef cpu64bitalu}
+ or is_64bitint(resultdef)
+{$endif not cpu64bitalu}
+ ) then
+ begin
+ update_reference_reg_mul(maybe_const_reg,l div 8);
+ exit;
+ end;
+ if (l > 8*sizeof(aint)) then
+ internalerror(200608051);
+ sref.ref := location.reference;
+ hreg := cg.getaddressregister(current_asmdata.CurrAsmList);
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SUB,OS_INT,tarraydef(left.resultdef).lowrange,maybe_const_reg,hreg);
+ cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_IMUL,OS_INT,l,hreg);
+ { keep alignment for index }
+ sref.ref.alignment := left.resultdef.alignment;
+ if not ispowerof2(sref.ref.alignment,temp) then
+ internalerror(2006081201);
+ alignpower:=temp;
+ offsetreg := cg.getaddressregister(current_asmdata.CurrAsmList);
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SHR,OS_ADDR,3+alignpower,hreg,offsetreg);
+ cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_SHL,OS_ADDR,alignpower,offsetreg);
+ if (sref.ref.base = NR_NO) then
+ sref.ref.base := offsetreg
+ else if (sref.ref.index = NR_NO) then
+ sref.ref.index := offsetreg
+ else
+ begin
+ cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_ADD,OS_ADDR,sref.ref.base,offsetreg);
+ sref.ref.base := offsetreg;
+ end;
+ cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_AND,OS_INT,(1 shl (3+alignpower))-1,hreg);
+ sref.bitindexreg := hreg;
+ sref.startbit := 0;
+ sref.bitlen := resultdef.packedbitsize;
+ if (left.location.loc = LOC_REFERENCE) then
+ location.loc := LOC_SUBSETREF
+ else
+ location.loc := LOC_CSUBSETREF;
+ location.sref := sref;
+ end;
+
+
+ procedure tcgvecnode.second_wideansistring;
+ begin
+ end;
+
+ procedure tcgvecnode.second_dynamicarray;
+ begin
+ end;
+
+
+ procedure tcgvecnode.rangecheck_array;
+ var
+ hightree : tnode;
+ poslabel,
+ neglabel : tasmlabel;
+ hreg : tregister;
+ paraloc1,paraloc2 : tcgpara;
+ begin
+ { omit range checking when this is an array access to a pointer which has been
+ typecasted from an array }
+ if (ado_isconvertedpointer in tarraydef(left.resultdef).arrayoptions) then
+ exit;
+ paraloc1.init;
+ paraloc2.init;
+ if is_open_array(left.resultdef) or
+ is_array_of_const(left.resultdef) then
+ begin
+ { cdecl functions don't have high() so we can not check the range }
+ { (can't use current_procdef, since it may be a nested procedure) }
+ if not(tprocdef(tparasymtable(tparavarsym(tloadnode(left).symtableentry).owner).defowner).proccalloption in cdecl_pocalls) then
+ begin
+ { Get high value }
+ hightree:=load_high_value_node(tparavarsym(tloadnode(left).symtableentry));
+ { it must be available }
+ if not assigned(hightree) then
+ internalerror(200212201);
+ firstpass(hightree);
+ secondpass(hightree);
+ { generate compares }
+ if (right.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
+ hreg:=cg.makeregsize(current_asmdata.CurrAsmList,right.location.register,OS_INT)
+ else
+ begin
+ hreg:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+ cg.a_load_loc_reg(current_asmdata.CurrAsmList,OS_INT,right.location,hreg);
+ end;
+ current_asmdata.getjumplabel(neglabel);
+ current_asmdata.getjumplabel(poslabel);
+ cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,OS_INT,OC_LT,0,hreg,poslabel);
+ cg.a_cmp_loc_reg_label(current_asmdata.CurrAsmList,OS_INT,OC_BE,hightree.location,hreg,neglabel);
+ cg.a_label(current_asmdata.CurrAsmList,poslabel);
+ cg.a_call_name(current_asmdata.CurrAsmList,'FPC_RANGEERROR',false);
+ cg.a_label(current_asmdata.CurrAsmList,neglabel);
+ { release hightree }
+ hightree.free;
+ end;
+ end
+ else
+ if is_dynamic_array(left.resultdef) then
+ begin
+ paramanager.getintparaloc(pocall_default,1,paraloc1);
+ paramanager.getintparaloc(pocall_default,2,paraloc2);
+ cg.a_load_loc_cgpara(current_asmdata.CurrAsmList,right.location,paraloc2);
+ cg.a_load_loc_cgpara(current_asmdata.CurrAsmList,left.location,paraloc1);
+ paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc1);
+ paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc2);
+ cg.allocallcpuregisters(current_asmdata.CurrAsmList);
+ cg.a_call_name(current_asmdata.CurrAsmList,'FPC_DYNARRAY_RANGECHECK',false);
+ cg.deallocallcpuregisters(current_asmdata.CurrAsmList);
+ end;
+{ for regular arrays, we don't have to do anything because the index has been
+ type converted to the index type, which already inserted a range check if
+ necessary }
+ paraloc1.done;
+ paraloc2.done;
+ end;
+
+ procedure tcgvecnode.rangecheck_string;
+ var
+ paraloc1,
+ paraloc2: tcgpara;
+ begin
+ paraloc1.init;
+ paraloc2.init;
+ case tstringdef(left.resultdef).stringtype of
+ { it's the same for ansi- and wide strings }
+ st_unicodestring,
+ st_widestring,
+ st_ansistring:
+ begin
+ paramanager.getintparaloc(pocall_default,1,paraloc1);
+ paramanager.getintparaloc(pocall_default,2,paraloc2);
+ cg.a_load_loc_cgpara(current_asmdata.CurrAsmList,left.location,paraloc1);
+ cg.a_load_loc_cgpara(current_asmdata.CurrAsmList,right.location,paraloc2);
+
+ paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc1);
+ paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc2);
+ cg.allocallcpuregisters(current_asmdata.CurrAsmList);
+ cg.a_call_name(current_asmdata.CurrAsmList,'FPC_'+upper(tstringdef(left.resultdef).stringtypname)+'_RANGECHECK',false);
+ cg.deallocallcpuregisters(current_asmdata.CurrAsmList);
+ end;
+
+ st_shortstring:
+ begin
+ {!!!!!!!!!!!!!!!!!}
+ { if this one is implemented making use of the high parameter for openshortstrings, update ncgutils.do_get_used_regvars() too (JM) }
+ end;
+
+ st_longstring:
+ begin
+ {!!!!!!!!!!!!!!!!!}
+ end;
+ end;
+ paraloc1.done;
+ paraloc2.done;
+ end;
+
+ procedure tcgvecnode.pass_generate_code;
+
+ var
+ offsetdec,
+ extraoffset : aint;
+ t : tnode;
+ otl,ofl : tasmlabel;
+ newsize : tcgsize;
+ mulsize,
+ bytemulsize,
+ alignpow : aint;
+ isjump : boolean;
+ paraloc1,
+ paraloc2 : tcgpara;
+ subsetref : tsubsetreference;
+ temp : longint;
+ begin
+ paraloc1.init;
+ paraloc2.init;
+ mulsize:=get_mul_size;
+ if not is_packed_array(left.resultdef) then
+ bytemulsize:=mulsize
+ else
+ bytemulsize:=mulsize div 8;
+
+ newsize:=def_cgsize(resultdef);
+ secondpass(left);
+ if left.location.loc=LOC_CREFERENCE then
+ location_reset_ref(location,LOC_CREFERENCE,newsize,left.location.reference.alignment)
+ else
+ location_reset_ref(location,LOC_REFERENCE,newsize,left.location.reference.alignment);
+
+ { an ansistring needs to be dereferenced }
+ if is_ansistring(left.resultdef) or
+ is_wide_or_unicode_string(left.resultdef) then
+ begin
+ if nf_callunique in flags then
+ internalerror(200304236);
+
+ {DM!!!!!}
+ case left.location.loc of
+ LOC_REGISTER,
+ LOC_CREGISTER :
+ begin
+{$ifdef m68k}
+ location.reference.base:=cg.getaddressregister(current_asmdata.CurrAsmList);
+ cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,left.location.register,location.reference.base);
+{$else m68k}
+ location.reference.base:=left.location.register;
+{$endif m68k}
+ end;
+ LOC_CREFERENCE,
+ LOC_REFERENCE :
+ begin
+ location.reference.base:=cg.getaddressregister(current_asmdata.CurrAsmList);
+ cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,left.location.reference,location.reference.base);
+ end;
+ else
+ internalerror(2002032218);
+ end;
+
+ { in ansistrings/widestrings S[1] is p<w>char(S)[0] !! }
+ if is_ansistring(left.resultdef) then
+ offsetdec:=1
+ else
+ offsetdec:=2;
+ location.reference.alignment:=offsetdec;
+ dec(location.reference.offset,offsetdec);
+ end
+ else if is_dynamic_array(left.resultdef) then
+ begin
+ case left.location.loc of
+ LOC_REGISTER,
+ LOC_CREGISTER :
+ location.reference.base:=left.location.register;
+ LOC_REFERENCE,
+ LOC_CREFERENCE :
+ begin
+ location.reference.base:=cg.getaddressregister(current_asmdata.CurrAsmList);
+ cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,
+ left.location.reference,location.reference.base);
+ end;
+ else
+ internalerror(2002032219);
+ end;
+ { a dynarray points to the start of a memory block, which
+ we assume to be always aligned to a multiple of the
+ pointer size
+ }
+ location.reference.alignment:=sizeof(pint);
+ end
+ else
+ begin
+ { may happen in case of function results }
+ case left.location.loc of
+ LOC_REGISTER,
+ LOC_MMREGISTER:
+ location_force_mem(current_asmdata.CurrAsmList,left.location);
+ end;
+ location_copy(location,left.location);
+ end;
+
+ { location must be memory }
+ if not(location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
+ internalerror(200411013);
+
+ { offset can only differ from 0 if arraydef }
+ if (left.resultdef.typ=arraydef) and
+ not(is_dynamic_array(left.resultdef)) and
+ (not(is_packed_array(left.resultdef)) or
+ ((mulsize mod 8 = 0) and
+ ispowerof2(mulsize div 8,temp)) or
+ { only orddefs are bitpacked }
+ not is_ordinal(resultdef)
+{$ifndef cpu64bitalu}
+ or is_64bitint(resultdef)
+{$endif not cpu64bitalu}
+ ) then
+ dec(location.reference.offset,bytemulsize*tarraydef(left.resultdef).lowrange);
+
+ if right.nodetype=ordconstn then
+ begin
+ { offset can only differ from 0 if arraydef }
+ if cs_check_range in current_settings.localswitches then
+ begin
+ secondpass(right);
+ case left.resultdef.typ of
+ arraydef :
+ rangecheck_array;
+ stringdef :
+ rangecheck_string;
+ end;
+ end;
+ if not(is_packed_array(left.resultdef)) or
+ ((mulsize mod 8 = 0) and
+ (ispowerof2(mulsize div 8,temp) or
+ { only orddefs are bitpacked }
+ not is_ordinal(resultdef))) then
+ begin
+ extraoffset:=bytemulsize*tordconstnode(right).value.svalue;
+ inc(location.reference.offset,extraoffset);
+ { adjust alignment after to this change }
+ location.reference.alignment:=newalignment(location.reference.alignment,extraoffset);
+ { don't do this for floats etc.; needed to properly set the }
+ { size for bitpacked arrays (e.g. a bitpacked array of }
+ { enums who are size 2 but fit in one byte -> in the array }
+ { they will be one byte and have to be stored like that) }
+ if is_packed_array(left.resultdef) and
+ (tcgsize2size[newsize] <> bytemulsize) then
+ newsize:=int_cgsize(bytemulsize);
+ end
+ else
+ begin
+ subsetref.ref := location.reference;
+ subsetref.ref.alignment := left.resultdef.alignment;
+ if not ispowerof2(subsetref.ref.alignment,temp) then
+ internalerror(2006081212);
+ alignpow:=temp;
+ inc(subsetref.ref.offset,((mulsize * (tordconstnode(right).value.svalue-tarraydef(left.resultdef).lowrange)) shr (3+alignpow)) shl alignpow);
+ subsetref.bitindexreg := NR_NO;
+ subsetref.startbit := (mulsize * (tordconstnode(right).value.svalue-tarraydef(left.resultdef).lowrange)) and ((1 shl (3+alignpow))-1);
+ subsetref.bitlen := resultdef.packedbitsize;
+ if (left.location.loc = LOC_REFERENCE) then
+ location.loc := LOC_SUBSETREF
+ else
+ location.loc := LOC_CSUBSETREF;
+ location.sref := subsetref;
+ end;
+ end
+ else
+ { not nodetype=ordconstn }
+ begin
+ if (cs_opt_level1 in current_settings.optimizerswitches) and
+ { if we do range checking, we don't }
+ { need that fancy code (it would be }
+ { buggy) }
+ not(cs_check_range in current_settings.localswitches) and
+ (left.resultdef.typ=arraydef) and
+ not is_packed_array(left.resultdef) then
+ begin
+ extraoffset:=0;
+ if (right.nodetype=addn) then
+ begin
+ if taddnode(right).right.nodetype=ordconstn then
+ begin
+ extraoffset:=tordconstnode(taddnode(right).right).value.svalue;
+ t:=taddnode(right).left;
+ taddnode(right).left:=nil;
+ right.free;
+ right:=t;
+ end
+ else if taddnode(right).left.nodetype=ordconstn then
+ begin
+ extraoffset:=tordconstnode(taddnode(right).left).value.svalue;
+ t:=taddnode(right).right;
+ taddnode(right).right:=nil;
+ right.free;
+ right:=t;
+ end;
+ end
+ else if (right.nodetype=subn) then
+ begin
+ if taddnode(right).right.nodetype=ordconstn then
+ begin
+ extraoffset:=-tordconstnode(taddnode(right).right).value.svalue;
+ t:=taddnode(right).left;
+ taddnode(right).left:=nil;
+ right.free;
+ right:=t;
+ end;
+ end;
+ inc(location.reference.offset,
+ mulsize*extraoffset);
+ end;
+ { calculate from left to right }
+ if not(location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) then
+ internalerror(200304237);
+ isjump:=(right.expectloc=LOC_JUMP);
+ if isjump then
+ begin
+ otl:=current_procinfo.CurrTrueLabel;
+ current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
+ ofl:=current_procinfo.CurrFalseLabel;
+ current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel);
+ end;
+ secondpass(right);
+
+ { if mulsize = 1, we won't have to modify the index }
+ location_force_reg(current_asmdata.CurrAsmList,right.location,OS_ADDR,true);
+
+ if isjump then
+ begin
+ current_procinfo.CurrTrueLabel:=otl;
+ current_procinfo.CurrFalseLabel:=ofl;
+ end
+ else if (right.location.loc = LOC_JUMP) then
+ internalerror(2006010801);
+
+ { produce possible range check code: }
+ if cs_check_range in current_settings.localswitches then
+ begin
+ if left.resultdef.typ=arraydef then
+ rangecheck_array
+ else if (left.resultdef.typ=stringdef) then
+ rangecheck_string;
+ end;
+
+ { insert the register and the multiplication factor in the
+ reference }
+ if not is_packed_array(left.resultdef) then
+ update_reference_reg_mul(right.location.register,mulsize)
+ else
+ update_reference_reg_packed(right.location.register,mulsize);
+ end;
+
+ location.size:=newsize;
+ paraloc1.done;
+ paraloc2.done;
+ end;
+
+
+begin
+ cloadvmtaddrnode:=tcgloadvmtaddrnode;
+ cloadparentfpnode:=tcgloadparentfpnode;
+ caddrnode:=tcgaddrnode;
+ cderefnode:=tcgderefnode;
+ csubscriptnode:=tcgsubscriptnode;
+ cwithnode:=tcgwithnode;
+ cvecnode:=tcgvecnode;
+end.
diff --git a/closures/compiler/ncgobjc.pas b/closures/compiler/ncgobjc.pas
new file mode 100644
index 0000000000..39a063c86e
--- /dev/null
+++ b/closures/compiler/ncgobjc.pas
@@ -0,0 +1,102 @@
+{
+ Copyright (c) 2009 by Jonas Maebe
+
+ This unit implements code generator support for Objective-C nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+
+unit ncgobjc;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ nobjc;
+
+type
+ tcgobjcselectornode = class(tobjcselectornode)
+ procedure pass_generate_code; override;
+ end;
+
+ tcgobjcprotocolnode = class(tobjcprotocolnode)
+ procedure pass_generate_code; override;
+ end;
+
+implementation
+
+uses
+ globtype,cclasses,
+ aasmbase,aasmdata,aasmtai,
+ cgbase,cgutils,defutil,objcgutl,
+ symconst,symsym,symdef,
+ node,nld,ncon,
+ verbose;
+
+{*****************************************************************************
+ TCGOBJCSELECTORNODE
+*****************************************************************************}
+
+procedure tcgobjcselectornode.pass_generate_code;
+ var
+ pool : THashSet;
+ entry : PHashSetItem;
+ name : pshortstring;
+ begin
+ pool:=current_asmdata.ConstPools[sp_varnamerefs];
+
+ case left.nodetype of
+ loadn:
+ begin
+ if (tloadnode(left).symtableentry.typ<>procsym) then
+ internalerror(2009051602);
+ if (tprocsym(tloadnode(left).symtableentry).procdeflist.count<>1) then
+ internalerror(2009051701);
+ name:=tprocdef(tprocsym(tloadnode(left).symtableentry).procdeflist[0]).messageinf.str;
+ entry:=pool.FindOrAdd(@name^[1],length(name^))
+ end;
+ stringconstn:
+ begin
+ entry:=pool.FindOrAdd(tstringconstnode(left).value_str,tstringconstnode(left).len);
+ end;
+ else
+ internalerror(2009030701);
+ end;
+
+ objcfinishstringrefpoolentry(entry,sp_objcvarnames,sec_objc_message_refs,sec_objc_meth_var_names);
+
+ location_reset_ref(location,LOC_CREFERENCE,def_cgsize(resultdef),sizeof(pint));
+ location.reference.symbol:=tasmlabel(entry^.Data);
+ end;
+
+
+{*****************************************************************************
+ TCGOBJCPROTOCOLNODE
+*****************************************************************************}
+
+procedure tcgobjcprotocolnode.pass_generate_code;
+ begin
+ { first needs support for writing class definitions }
+ internalerror(2009072601);
+ end;
+
+
+begin
+ cobjcselectornode:=tcgobjcselectornode;
+ cobjcprotocolnode:=tcgobjcprotocolnode;
+end.
diff --git a/closures/compiler/ncgopt.pas b/closures/compiler/ncgopt.pas
new file mode 100644
index 0000000000..1393eaef9b
--- /dev/null
+++ b/closures/compiler/ncgopt.pas
@@ -0,0 +1,188 @@
+{
+ Copyright (c) 1998-2003 by Jonas Maebe
+
+ This unit implements the generic implementation of optimized nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit ncgopt;
+
+{$i fpcdefs.inc}
+
+interface
+uses node, nopt;
+
+type
+ tcgaddsstringcharoptnode = class(taddsstringcharoptnode)
+ function pass_typecheck: tnode; override;
+ function pass_1: tnode; override;
+ procedure pass_generate_code; override;
+ end;
+
+
+implementation
+
+uses
+ globtype,globals,
+ pass_1,defutil,htypechk,
+ symdef,paramgr,
+ aasmbase,aasmtai,aasmdata,
+ ncnv, ncon, pass_2,
+ cgbase, cpubase,
+ tgobj, cgobj, cgutils,ncgutil;
+
+
+{*****************************************************************************
+ TCGADDOPTNODE
+*****************************************************************************}
+
+function tcgaddsstringcharoptnode.pass_typecheck: tnode;
+begin
+ pass_typecheck := nil;
+ typecheckpass(left);
+ typecheckpass(right);
+ if codegenerror then
+ exit;
+ { update the curmaxlen field (before converting to a string!) }
+ updatecurmaxlen;
+ if not is_shortstring(left.resultdef) then
+ inserttypeconv(left,cshortstringtype);
+ resultdef:=left.resultdef;
+end;
+
+
+function tcgaddsstringcharoptnode.pass_1: tnode;
+begin
+ pass_1 := nil;
+ firstpass(left);
+ firstpass(right);
+ if codegenerror then
+ exit;
+ expectloc:=LOC_REFERENCE;
+end;
+
+
+procedure tcgaddsstringcharoptnode.pass_generate_code;
+var
+ l: tasmlabel;
+ href,href2 : treference;
+ hreg, lengthreg: tregister;
+ checklength: boolean;
+ len : integer;
+begin
+ { first, we have to more or less replicate some code from }
+ { ti386addnode.pass_generate_code }
+ secondpass(left);
+ if not(tg.istemp(left.location.reference) and
+ (tg.sizeoftemp(current_asmdata.CurrAsmList,left.location.reference) = 256)) then
+ begin
+ tg.Gettemp(current_asmdata.CurrAsmList,256,1,tt_normal,href);
+ cg.g_copyshortstring(current_asmdata.CurrAsmList,left.location.reference,href,255);
+ location_freetemp(current_asmdata.CurrAsmList,left.location);
+ { return temp reference }
+ location_reset_ref(left.location,LOC_REFERENCE,def_cgsize(resultdef),1);
+ left.location.reference:=href;
+ end;
+ secondpass(right);
+ { special case for string := string + char (JM) }
+ hreg:=NR_NO;
+
+ { we have to load the char before checking the length, because we }
+ { may need registers from the reference }
+
+ { is it a constant char? }
+ if not is_constcharnode(right) then
+ { no, make sure it is in a register }
+ if right.location.loc in [LOC_REFERENCE,LOC_CREFERENCE] then
+ begin
+ { get register for the char }
+ hreg := cg.getintregister(current_asmdata.CurrAsmList,OS_8);
+ cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_8,OS_8,right.location.reference,hreg);
+ { I don't think a temp char exists, but it won't hurt (JM) }
+ tg.ungetiftemp(current_asmdata.CurrAsmList,right.location.reference);
+ end
+ else hreg := right.location.register;
+
+ { load the current string length }
+ lengthreg := cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+ cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_8,OS_INT,left.location.reference,lengthreg);
+
+ { do we have to check the length ? }
+ if tg.istemp(left.location.reference) then
+ checklength := curmaxlen = 255
+ else
+ checklength := curmaxlen >= tstringdef(left.resultdef).len;
+ if checklength then
+ begin
+ { is it already maximal? }
+ current_asmdata.getjumplabel(l);
+ if tg.istemp(left.location.reference) then
+ len:=255
+ else
+ len:=tstringdef(left.resultdef).len;
+ cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,OS_INT,OC_EQ,len,lengthreg,l)
+ end;
+
+ { no, so increase the length and add the new character }
+ href2 := left.location.reference;
+
+ { we need a new reference to store the character }
+ { at the end of the string. Check if the base or }
+ { index register is still free }
+ if (href2.base <> NR_NO) and
+ (href2.index <> NR_NO) then
+ begin
+ { they're not free, so add the base reg to }
+ { the string length (since the index can }
+ { have a scalefactor) and use lengthreg as base }
+ cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_ADD,OS_INT,href2.base,lengthreg);
+ href2.base := lengthreg;
+ end
+ else
+ { at least one is still free, so put EDI there }
+ if href2.base = NR_NO then
+ href2.base := lengthreg
+ else
+ begin
+ href2.index := lengthreg;
+{$ifdef x86}
+ href2.scalefactor := 1;
+{$endif x86}
+ end;
+ { we need to be one position after the last char }
+ inc(href2.offset);
+ { store the character at the end of the string }
+ if (right.nodetype <> ordconstn) then
+ begin
+ { no new_reference(href2) because it's only }
+ { used once (JM) }
+ cg.a_load_reg_ref(current_asmdata.CurrAsmList,OS_8,OS_8,hreg,href2);
+ end
+ else
+ cg.a_load_const_ref(current_asmdata.CurrAsmList,OS_8,tordconstnode(right).value.svalue,href2);
+ lengthreg:=cg.makeregsize(current_asmdata.CurrAsmList,lengthreg,OS_8);
+ { increase the string length }
+ cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_ADD,OS_8,1,lengthreg);
+ cg.a_load_reg_ref(current_asmdata.CurrAsmList,OS_8,OS_8,lengthreg,left.location.reference);
+ if checklength then
+ cg.a_label(current_asmdata.CurrAsmList,l);
+ location_copy(location,left.location);
+end;
+
+begin
+ caddsstringcharoptnode := tcgaddsstringcharoptnode;
+end.
diff --git a/closures/compiler/ncgrtti.pas b/closures/compiler/ncgrtti.pas
new file mode 100644
index 0000000000..2d0e7df123
--- /dev/null
+++ b/closures/compiler/ncgrtti.pas
@@ -0,0 +1,1244 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Routines for the code generation of RTTI data structures
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit ncgrtti;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cclasses,constexp,
+ aasmbase,
+ symbase,symconst,symtype,symdef;
+
+ type
+
+ { TRTTIWriter }
+
+ TRTTIWriter=class
+ private
+ procedure fields_write_rtti(st:tsymtable;rt:trttitype);
+ procedure fields_write_rtti_data(def:tabstractrecorddef;rt:trttitype);
+ procedure write_rtti_extrasyms(def:Tdef;rt:Trttitype;mainrtti:Tasmsymbol);
+ procedure published_write_rtti(st:tsymtable;rt:trttitype);
+ function published_properties_count(st:tsymtable):longint;
+ procedure published_properties_write_rtti_data(propnamelist:TFPHashObjectList;st:tsymtable);
+ procedure collect_propnamelist(propnamelist:TFPHashObjectList;objdef:tobjectdef);
+ procedure write_rtti_name(def:tdef);
+ procedure write_rtti_data(def:tdef;rt:trttitype);
+ procedure write_child_rtti_data(def:tdef;rt:trttitype);
+ function ref_rtti(def:tdef;rt:trttitype):tasmsymbol;
+ procedure write_header(def: tdef; typekind: byte);
+ procedure write_string(const s: string);
+ procedure maybe_write_align;
+ public
+ procedure write_rtti(def:tdef;rt:trttitype);
+ function get_rtti_label(def:tdef;rt:trttitype):tasmsymbol;
+ function get_rtti_label_ord2str(def:tdef;rt:trttitype):tasmsymbol;
+ function get_rtti_label_str2ord(def:tdef;rt:trttitype):tasmsymbol;
+ end;
+
+ var
+ RTTIWriter : TRTTIWriter;
+
+
+implementation
+
+ uses
+ cutils,
+ globals,globtype,verbose,systems,
+ fmodule,
+ symsym,
+ aasmtai,aasmdata,
+ defutil,
+ wpobase
+ ;
+
+
+ const
+ rttidefstate : array[trttitype] of tdefstate =
+ (ds_rtti_table_written,ds_init_table_written,
+ { Objective-C related, does not pass here }
+ symconst.ds_none,symconst.ds_none,
+ symconst.ds_none,symconst.ds_none);
+
+ type
+ TPropNameListItem = class(TFPHashObject)
+ propindex : longint;
+ propowner : TSymtable;
+ end;
+
+
+{***************************************************************************
+ TRTTIWriter
+***************************************************************************}
+
+ procedure TRTTIWriter.maybe_write_align;
+ begin
+ if (tf_requires_proper_alignment in target_info.flags) then
+ current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
+ end;
+
+ procedure TRTTIWriter.write_string(const s: string);
+ begin
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(length(s)));
+ current_asmdata.asmlists[al_rtti].concat(Tai_string.Create(s));
+ end;
+
+ procedure TRTTIWriter.write_header(def: tdef; typekind: byte);
+ begin
+ if def.typ=arraydef then
+ InternalError(201012211);
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(typekind));
+ if assigned(def.typesym) then
+ write_string(ttypesym(def.typesym).realname)
+ else
+ current_asmdata.asmlists[al_rtti].concat(Tai_string.Create(#0));
+ end;
+
+ procedure TRTTIWriter.write_rtti_name(def:tdef);
+ var
+ hs : string;
+ begin
+ if is_open_array(def) then
+ { open arrays never have a typesym with a name, since you cannot
+ define an "open array type". Kylix prints the type of the
+ elements in the array in this case (so together with the pfArray
+ flag, you can reconstruct the full typename, I assume (JM))
+ }
+ def:=tarraydef(def).elementdef;
+ { name }
+ if assigned(def.typesym) then
+ begin
+ hs:=ttypesym(def.typesym).realname;
+ current_asmdata.asmlists[al_rtti].concat(Tai_string.Create(chr(length(hs))+hs));
+ end
+ else
+ current_asmdata.asmlists[al_rtti].concat(Tai_string.Create(#0));
+ end;
+
+ { writes a 32-bit count followed by array of field infos for given symtable }
+ procedure TRTTIWriter.fields_write_rtti_data(def:tabstractrecorddef;rt:trttitype);
+ var
+ i : longint;
+ sym : tsym;
+ fieldcnt: longint;
+ lastai: TLinkedListItem;
+ st: tsymtable;
+ begin
+ fieldcnt:=0;
+ { Count will be inserted at this location. It cannot be nil as we've just
+ written header for this symtable owner. But stay safe. }
+ lastai:=current_asmdata.asmlists[al_rtti].last;
+ if lastai=nil then
+ InternalError(201012212);
+
+ { For objects, treat parent (if any) as a field with offset 0. This
+ provides correct handling of entire instance with RTL rtti routines. }
+ if (def.typ=objectdef) and (tobjectdef(def).objecttype=odt_object) and
+ Assigned(tobjectdef(def).childof) and
+ ((rt=fullrtti) or (tobjectdef(def).childof.needs_inittable)) then
+ begin
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_sym(ref_rtti(tobjectdef(def).childof,rt)));
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_32bit(0));
+ inc(fieldcnt);
+ end;
+ st:=def.symtable;
+ for i:=0 to st.SymList.Count-1 do
+ begin
+ sym:=tsym(st.SymList[i]);
+ if (tsym(sym).typ=fieldvarsym) and
+ not(sp_static in tsym(sym).symoptions) and
+ (
+ (rt=fullrtti) or
+ tfieldvarsym(sym).vardef.needs_inittable
+ ) and
+ not is_objc_class_or_protocol(tfieldvarsym(sym).vardef) then
+ begin
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_sym(ref_rtti(tfieldvarsym(sym).vardef,rt)));
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_32bit(tfieldvarsym(sym).fieldoffset));
+ inc(fieldcnt);
+ end;
+ end;
+ { insert field count before data }
+ current_asmdata.asmlists[al_rtti].InsertAfter(Tai_const.Create_32bit(fieldcnt),lastai)
+ end;
+
+
+ procedure TRTTIWriter.fields_write_rtti(st:tsymtable;rt:trttitype);
+ var
+ i : longint;
+ sym : tsym;
+ begin
+ for i:=0 to st.SymList.Count-1 do
+ begin
+ sym:=tsym(st.SymList[i]);
+ if (tsym(sym).typ=fieldvarsym) and
+ not(sp_static in tsym(sym).symoptions) and
+ (
+ (rt=fullrtti) or
+ tfieldvarsym(sym).vardef.needs_inittable
+ ) then
+ write_rtti(tfieldvarsym(sym).vardef,rt);
+ end;
+ end;
+
+
+ procedure TRTTIWriter.published_write_rtti(st:tsymtable;rt:trttitype);
+ var
+ i : longint;
+ sym : tsym;
+ begin
+ for i:=0 to st.SymList.Count-1 do
+ begin
+ sym:=tsym(st.SymList[i]);
+ if (sym.visibility=vis_published) then
+ begin
+ case tsym(sym).typ of
+ propertysym:
+ write_rtti(tpropertysym(sym).propdef,rt);
+ fieldvarsym:
+ write_rtti(tfieldvarsym(sym).vardef,rt);
+ end;
+ end;
+ end;
+ end;
+
+
+ function TRTTIWriter.published_properties_count(st:tsymtable):longint;
+ var
+ i : longint;
+ sym : tsym;
+ begin
+ result:=0;
+ for i:=0 to st.SymList.Count-1 do
+ begin
+ sym:=tsym(st.SymList[i]);
+ if (tsym(sym).typ=propertysym) and
+ (sym.visibility=vis_published) then
+ inc(result);
+ end;
+ end;
+
+
+ procedure TRTTIWriter.collect_propnamelist(propnamelist:TFPHashObjectList;objdef:tobjectdef);
+ var
+ i : longint;
+ sym : tsym;
+ pn : tpropnamelistitem;
+ begin
+ if assigned(objdef.childof) then
+ collect_propnamelist(propnamelist,objdef.childof);
+ for i:=0 to objdef.symtable.SymList.Count-1 do
+ begin
+ sym:=tsym(objdef.symtable.SymList[i]);
+ if (tsym(sym).typ=propertysym) and
+ (sym.visibility=vis_published) then
+ begin
+ pn:=TPropNameListItem(propnamelist.Find(tsym(sym).name));
+ if not assigned(pn) then
+ begin
+ pn:=tpropnamelistitem.create(propnamelist,tsym(sym).name);
+ pn.propindex:=propnamelist.count-1;
+ pn.propowner:=tsym(sym).owner;
+ end;
+ end;
+ end;
+ end;
+
+
+ procedure TRTTIWriter.published_properties_write_rtti_data(propnamelist:TFPHashObjectList;st:tsymtable);
+ var
+ i : longint;
+ sym : tsym;
+ proctypesinfo : byte;
+ propnameitem : tpropnamelistitem;
+
+ procedure writeaccessproc(pap:tpropaccesslisttypes; shiftvalue : byte; unsetvalue: byte);
+ var
+ typvalue : byte;
+ hp : ppropaccesslistitem;
+ address,space : longint;
+ def : tdef;
+ hpropsym : tpropertysym;
+ propaccesslist : tpropaccesslist;
+ begin
+ hpropsym:=tpropertysym(sym);
+ repeat
+ propaccesslist:=hpropsym.propaccesslist[pap];
+ if not propaccesslist.empty then
+ break;
+ hpropsym:=hpropsym.overriddenpropsym;
+ until not assigned(hpropsym);
+ if not(assigned(propaccesslist) and assigned(propaccesslist.firstsym)) then
+ begin
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.create(aitconst_ptr,unsetvalue));
+ typvalue:=3;
+ end
+ else if propaccesslist.firstsym^.sym.typ=fieldvarsym then
+ begin
+ address:=0;
+ hp:=propaccesslist.firstsym;
+ def:=nil;
+ while assigned(hp) do
+ begin
+ case hp^.sltype of
+ sl_load :
+ begin
+ def:=tfieldvarsym(hp^.sym).vardef;
+ inc(address,tfieldvarsym(hp^.sym).fieldoffset);
+ end;
+ sl_subscript :
+ begin
+ if not(assigned(def) and
+ ((def.typ=recorddef) or
+ is_object(def))) then
+ internalerror(200402171);
+ inc(address,tfieldvarsym(hp^.sym).fieldoffset);
+ def:=tfieldvarsym(hp^.sym).vardef;
+ end;
+ sl_vec :
+ begin
+ if not(assigned(def) and (def.typ=arraydef)) then
+ internalerror(200402172);
+ def:=tarraydef(def).elementdef;
+ {Hp.value is a Tconstexprint, which can be rather large,
+ sanity check for longint overflow.}
+ space:=(high(address)-address) div def.size;
+ if int64(space)<hp^.value then
+ internalerror(200706101);
+ inc(address,int64(def.size*hp^.value));
+ end;
+ end;
+ hp:=hp^.next;
+ end;
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.create(aitconst_ptr,address));
+ typvalue:=0;
+ end
+ else
+ begin
+ { When there was an error then procdef is not assigned }
+ if not assigned(propaccesslist.procdef) then
+ exit;
+ if not(po_virtualmethod in tprocdef(propaccesslist.procdef).procoptions) or
+ is_objectpascal_helper(tprocdef(propaccesslist.procdef).struct) then
+ begin
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.createname(tprocdef(propaccesslist.procdef).mangledname,0));
+ typvalue:=1;
+ end
+ else
+ begin
+ { virtual method, write vmt offset }
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.create(aitconst_ptr,
+ tobjectdef(tprocdef(propaccesslist.procdef).struct).vmtmethodoffset(tprocdef(propaccesslist.procdef).extnumber)));
+ { register for wpo }
+ tobjectdef(tprocdef(propaccesslist.procdef).struct).register_vmt_call(tprocdef(propaccesslist.procdef).extnumber);
+ {$ifdef vtentry}
+ { not sure if we can insert those vtentry symbols safely here }
+ {$error register methods used for published properties}
+ {$endif vtentry}
+ typvalue:=2;
+ end;
+ end;
+ proctypesinfo:=proctypesinfo or (typvalue shl shiftvalue);
+ end;
+
+ begin
+ for i:=0 to st.SymList.Count-1 do
+ begin
+ sym:=tsym(st.SymList[i]);
+ if (sym.typ=propertysym) and
+ (sym.visibility=vis_published) then
+ begin
+ if ppo_indexed in tpropertysym(sym).propoptions then
+ proctypesinfo:=$40
+ else
+ proctypesinfo:=0;
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_sym(ref_rtti(tpropertysym(sym).propdef,fullrtti)));
+ writeaccessproc(palt_read,0,0);
+ writeaccessproc(palt_write,2,0);
+ { is it stored ? }
+ if not(ppo_stored in tpropertysym(sym).propoptions) then
+ begin
+ { no, so put a constant zero }
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.create(aitconst_ptr,0));
+ proctypesinfo:=proctypesinfo or (3 shl 4);
+ end
+ else
+ writeaccessproc(palt_stored,4,1); { maybe; if no procedure put a constant 1 (=true) }
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_32bit(tpropertysym(sym).index));
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_32bit(tpropertysym(sym).default));
+ propnameitem:=TPropNameListItem(propnamelist.Find(tpropertysym(sym).name));
+ if not assigned(propnameitem) then
+ internalerror(200512201);
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_16bit(propnameitem.propindex));
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(proctypesinfo));
+ write_string(tpropertysym(sym).realname);
+ maybe_write_align;
+ end;
+ end;
+ end;
+
+
+ procedure TRTTIWriter.write_rtti_data(def:tdef;rt:trttitype);
+
+ procedure unknown_rtti(def:tstoreddef);
+ begin
+ current_asmdata.asmlists[al_rtti].concat(tai_const.create_8bit(tkUnknown));
+ write_rtti_name(def);
+ end;
+
+ procedure variantdef_rtti(def:tvariantdef);
+ begin
+ write_header(def,tkVariant);
+ end;
+
+ procedure stringdef_rtti(def:tstringdef);
+ begin
+ case def.stringtype of
+ st_ansistring:
+ write_header(def,tkAString);
+
+ st_widestring:
+ write_header(def,tkWString);
+
+ st_unicodestring:
+ write_header(def,tkUString);
+
+ st_longstring:
+ write_header(def,tkLString);
+
+ st_shortstring:
+ begin
+ write_header(def,tkSString);
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(def.len));
+ maybe_write_align; // is align necessary here?
+ end;
+ end;
+ end;
+
+ procedure enumdef_rtti(def:tenumdef);
+ var
+ i : integer;
+ hp : tenumsym;
+ begin
+ write_header(def,tkEnumeration);
+ maybe_write_align;
+ case longint(def.size) of
+ 1 :
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(otUByte));
+ 2 :
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(otUWord));
+ 4 :
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(otULong));
+ end;
+ { we need to align by Tconstptruint here to satisfy the alignment rules set by
+ records: in the typinfo unit we overlay a TTypeData record on this data, which at
+ the innermost variant record needs an alignment of TConstPtrUint due to e.g.
+ the "CompType" member for tkSet (also the "BaseType" member for tkEnumeration).
+ We need to adhere to this, otherwise things will break.
+ Note that other code (e.g. enumdef_rtti_calcstringtablestart()) relies on the
+ exact sequence too. }
+ maybe_write_align;
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_32bit(def.min));
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_32bit(def.max));
+ maybe_write_align; // is align necessary here?
+ { write base type }
+ if assigned(def.basedef) then
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_sym(ref_rtti(def.basedef,rt)))
+ else
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.create_sym(nil));
+ for i := 0 to def.symtable.SymList.Count - 1 do
+ begin
+ hp:=tenumsym(def.symtable.SymList[i]);
+ if hp.value<def.minval then
+ continue
+ else
+ if hp.value>def.maxval then
+ break;
+ write_string(hp.realname);
+ end;
+ { write unit name }
+ write_string(current_module.realmodulename^);
+ { write zero which is required by RTL }
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(0));
+ end;
+
+ procedure orddef_rtti(def:torddef);
+
+ procedure dointeger(typekind: byte);
+ const
+ trans : array[tordtype] of byte =
+ (otUByte{otNone},
+ otUByte,otUWord,otULong,otUByte{otNone},
+ otSByte,otSWord,otSLong,otUByte{otNone},
+ otUByte,otUWord,otULong,otUByte,
+ otSByte,otSWord,otSLong,otSByte,
+ otUByte,otUWord,otUByte);
+ begin
+ write_header(def,typekind);
+ maybe_write_align;
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(byte(trans[def.ordtype])));
+ maybe_write_align;
+ {Convert to longint to smuggle values in high(longint)+1..high(cardinal) into asmlist.}
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_32bit(longint(def.low.svalue)));
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_32bit(longint(def.high.svalue)));
+ end;
+
+ begin
+ case def.ordtype of
+ s64bit :
+ begin
+ write_header(def,tkInt64);
+ maybe_write_align;
+ { low }
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_64bit(def.low.svalue));
+ { high }
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_64bit(def.high.svalue));
+ end;
+ u64bit :
+ begin
+ write_header(def,tkQWord);
+ maybe_write_align;
+ {use svalue because Create_64bit accepts int64, prevents range checks}
+ { low }
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_64bit(def.low.svalue));
+ { high }
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_64bit(def.high.svalue));
+ end;
+ pasbool8:
+ dointeger(tkBool);
+ uchar:
+ dointeger(tkChar);
+ uwidechar:
+ dointeger(tkWChar);
+ scurrency:
+ begin
+ write_header(def,tkFloat);
+ maybe_write_align;
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(ftCurr));
+ end;
+ else
+ dointeger(tkInteger);
+ end;
+ end;
+
+
+ procedure floatdef_rtti(def:tfloatdef);
+ const
+ {tfloattype = (s32real,s64real,s80real,sc80real,s64bit,s128bit);}
+ translate : array[tfloattype] of byte =
+ (ftSingle,ftDouble,ftExtended,ftExtended,ftComp,ftCurr,ftFloat128);
+ begin
+ write_header(def,tkFloat);
+ maybe_write_align;
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(translate[def.floattype]));
+ end;
+
+
+ procedure setdef_rtti(def:tsetdef);
+ begin
+ write_header(def,tkSet);
+ maybe_write_align;
+ case def.size of
+ 1:
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(otUByte));
+ 2:
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(otUWord));
+ 4:
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(otULong));
+ else
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(otUByte));
+ end;
+ maybe_write_align;
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_sym(ref_rtti(def.elementdef,rt)));
+ end;
+
+
+ procedure arraydef_rtti(def:tarraydef);
+ begin
+ if ado_IsDynamicArray in def.arrayoptions then
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkdynarray))
+ else
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkarray));
+ write_rtti_name(def);
+ maybe_write_align;
+ { size of elements }
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_pint(def.elesize));
+
+ if not(ado_IsDynamicArray in def.arrayoptions) then
+ begin
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_pint(pint(def.elecount)));
+ { element type }
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_sym(ref_rtti(def.elementdef,rt)));
+ end
+ else
+ { write a delphi almost compatible dyn. array entry:
+ there are two types, eltype and eltype2, the latter is nil if the element type needs
+ no finalization, the former is always valid, delphi has this swapped, but for
+ compatibility with older fpc versions we do it different, to be delphi compatible,
+ the names are swapped in typinfo.pp
+ }
+ begin
+ { element type }
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_sym(ref_rtti(def.elementdef,rt)));
+ end;
+ { variant type }
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_32bit(tstoreddef(def.elementdef).getvardef));
+ if ado_IsDynamicArray in def.arrayoptions then
+ begin
+ { element type }
+ if def.elementdef.needs_inittable then
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_sym(ref_rtti(def.elementdef,rt)))
+ else
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_pint(0));
+ { write unit name }
+ write_string(current_module.realmodulename^);
+ end;
+ end;
+
+ procedure recorddef_rtti(def:trecorddef);
+ begin
+ write_header(def,tkRecord);
+ maybe_write_align;
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_32bit(def.size));
+ fields_write_rtti_data(def,rt);
+ end;
+
+
+ procedure procvardef_rtti(def:tprocvardef);
+
+ const
+ ProcCallOptionToCallConv: array[tproccalloption] of byte = (
+ { pocall_none } 0,
+ { pocall_cdecl } 1,
+ { pocall_cppdecl } 5,
+ { pocall_far16 } 6,
+ { pocall_oldfpccall } 7,
+ { pocall_internproc } 8,
+ { pocall_syscall } 9,
+ { pocall_pascal } 2,
+ { pocall_register } 0,
+ { pocall_safecall } 4,
+ { pocall_stdcall } 3,
+ { pocall_softfloat } 10,
+ { pocall_mwpascal } 11,
+ { pocall_interrupt } 12
+ );
+
+ procedure write_para(parasym:tparavarsym);
+ var
+ paraspec : byte;
+ begin
+ { only store user visible parameters }
+ if not(vo_is_hidden_para in parasym.varoptions) then
+ begin
+ case parasym.varspez of
+ vs_value : paraspec := 0;
+ vs_const : paraspec := pfConst;
+ vs_var : paraspec := pfVar;
+ vs_out : paraspec := pfOut;
+ vs_constref: paraspec := pfConstRef;
+ end;
+ { Kylix also seems to always add both pfArray and pfReference
+ in this case
+ }
+ if is_open_array(parasym.vardef) then
+ paraspec:=paraspec or pfArray or pfReference;
+ { and these for classes and interfaces (maybe because they
+ are themselves addresses?)
+ }
+ if is_class_or_interface(parasym.vardef) then
+ paraspec:=paraspec or pfAddress;
+ { set bits run from the highest to the lowest bit on
+ big endian systems
+ }
+ if (target_info.endian = endian_big) then
+ paraspec:=reverse_byte(paraspec);
+ { write flags for current parameter }
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(paraspec));
+ { write name of current parameter }
+ write_string(parasym.realname);
+ { write name of type of current parameter }
+ write_rtti_name(parasym.vardef);
+ end;
+ end;
+
+ var
+ methodkind : byte;
+ i : integer;
+ begin
+ if po_methodpointer in def.procoptions then
+ begin
+ { write method id and name }
+ write_header(def,tkMethod);
+ maybe_write_align;
+
+ { write kind of method }
+ case def.proctypeoption of
+ potype_constructor: methodkind:=mkConstructor;
+ potype_destructor: methodkind:=mkDestructor;
+ potype_class_constructor: methodkind:=mkClassConstructor;
+ potype_class_destructor: methodkind:=mkClassDestructor;
+ potype_operator: methodkind:=mkOperatorOverload;
+ potype_procedure:
+ if po_classmethod in def.procoptions then
+ methodkind:=mkClassProcedure
+ else
+ methodkind:=mkProcedure;
+ potype_function:
+ if po_classmethod in def.procoptions then
+ methodkind:=mkClassFunction
+ else
+ methodkind:=mkFunction;
+ else
+ begin
+ if def.returndef = voidtype then
+ methodkind:=mkProcedure
+ else
+ methodkind:=mkFunction;
+ end;
+ end;
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(methodkind));
+
+ { write parameter info. The parameters must be written in reverse order
+ if this method uses right to left parameter pushing! }
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(def.maxparacount));
+
+ for i:=0 to def.paras.count-1 do
+ write_para(tparavarsym(def.paras[i]));
+
+ if (methodkind=mkFunction) or (methodkind=mkClassFunction) then
+ begin
+ { write name of result type }
+ write_rtti_name(def.returndef);
+ maybe_write_align;
+
+ { write result typeinfo }
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_sym(ref_rtti(def.returndef,fullrtti)))
+ end;
+
+ { write calling convention }
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(ProcCallOptionToCallConv[def.proccalloption]));
+ maybe_write_align;
+
+ { write params typeinfo }
+ for i:=0 to def.paras.count-1 do
+ if not(vo_is_hidden_para in tparavarsym(def.paras[i]).varoptions) then
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_sym(ref_rtti(tparavarsym(def.paras[i]).vardef,fullrtti)));
+ end
+ else
+ write_header(def,tkProcvar);
+ end;
+
+
+ procedure objectdef_rtti(def:tobjectdef);
+
+ procedure objectdef_rtti_fields(def:tobjectdef);
+ begin
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_32bit(def.size));
+ fields_write_rtti_data(def,rt);
+ end;
+
+ procedure objectdef_rtti_interface_init(def:tobjectdef);
+ begin
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_32bit(def.size));
+ end;
+
+ procedure objectdef_rtti_class_full(def:tobjectdef);
+ var
+ propnamelist : TFPHashObjectList;
+ begin
+ { Collect unique property names with nameindex }
+ propnamelist:=TFPHashObjectList.Create;
+ collect_propnamelist(propnamelist,def);
+
+ if not is_objectpascal_helper(def) then
+ if (oo_has_vmt in def.objectoptions) then
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Createname(def.vmt_mangledname,0))
+ else
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.create_sym(nil));
+
+ { write parent typeinfo }
+ if assigned(def.childof) then
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_sym(ref_rtti(def.childof,fullrtti)))
+ else
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.create_sym(nil));
+
+ { write typeinfo of extended type }
+ if is_objectpascal_helper(def) then
+ if assigned(def.extendeddef) then
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_sym(ref_rtti(def.extendeddef,fullrtti)))
+ else
+ InternalError(2011033001);
+
+ { total number of unique properties }
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_16bit(propnamelist.count));
+
+ { write unit name }
+ write_string(current_module.realmodulename^);
+ maybe_write_align;
+
+ { write published properties for this object }
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_16bit(published_properties_count(def.symtable)));
+ maybe_write_align;
+ published_properties_write_rtti_data(propnamelist,def.symtable);
+
+ propnamelist.free;
+ end;
+
+ procedure objectdef_rtti_interface_full(def:tobjectdef);
+ var
+ i : longint;
+ propnamelist : TFPHashObjectList;
+ { if changed to a set, make sure it's still a byte large, and
+ swap appropriately when cross-compiling
+ }
+ IntfFlags: byte;
+ begin
+ { Collect unique property names with nameindex }
+ propnamelist:=TFPHashObjectList.Create;
+ collect_propnamelist(propnamelist,def);
+
+ { write parent typeinfo }
+ if assigned(def.childof) then
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_sym(ref_rtti(def.childof,fullrtti)))
+ else
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.create_sym(nil));
+
+ { interface: write flags, iid and iidstr }
+ IntfFlags:=0;
+ if assigned(def.iidguid) then
+ IntfFlags:=IntfFlags or (1 shl ord(ifHasGuid));
+ if assigned(def.iidstr) then
+ IntfFlags:=IntfFlags or (1 shl ord(ifHasStrGUID));
+ if (def.objecttype=odt_dispinterface) then
+ IntfFlags:=IntfFlags or (1 shl ord(ifDispInterface));
+ if (target_info.endian=endian_big) then
+ IntfFlags:=reverse_byte(IntfFlags);
+ {
+ ifDispatch, }
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(IntfFlags));
+ maybe_write_align;
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_32bit(longint(def.iidguid^.D1)));
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_16bit(def.iidguid^.D2));
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_16bit(def.iidguid^.D3));
+ for i:=Low(def.iidguid^.D4) to High(def.iidguid^.D4) do
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(def.iidguid^.D4[i]));
+
+ { write unit name }
+ write_string(current_module.realmodulename^);
+ maybe_write_align;
+
+ { write iidstr }
+ if assigned(def.iidstr) then
+ write_string(def.iidstr^)
+ else
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(0));
+ maybe_write_align;
+
+ { write published properties for this object }
+ published_properties_write_rtti_data(propnamelist,def.symtable);
+
+ propnamelist.free;
+ end;
+
+ begin
+ case def.objecttype of
+ odt_class:
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkclass));
+ odt_object:
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkobject));
+ odt_dispinterface,
+ odt_interfacecom:
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkinterface));
+ odt_interfacecorba:
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkinterfaceCorba));
+ odt_helper:
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkhelper));
+ else
+ internalerror(200611034);
+ end;
+
+ { generate the name }
+ write_string(def.objrealname^);
+ maybe_write_align;
+
+ case rt of
+ initrtti :
+ begin
+ if def.objecttype in [odt_class,odt_object,odt_helper] then
+ objectdef_rtti_fields(def)
+ else
+ objectdef_rtti_interface_init(def);
+ end;
+ fullrtti :
+ begin
+ case def.objecttype of
+ odt_helper,
+ odt_class:
+ objectdef_rtti_class_full(def);
+ odt_object:
+ objectdef_rtti_fields(def);
+ else
+ objectdef_rtti_interface_full(def);
+ end;
+ end;
+ end;
+ end;
+
+ begin
+ case def.typ of
+ variantdef :
+ variantdef_rtti(tvariantdef(def));
+ stringdef :
+ stringdef_rtti(tstringdef(def));
+ enumdef :
+ enumdef_rtti(tenumdef(def));
+ orddef :
+ orddef_rtti(torddef(def));
+ floatdef :
+ floatdef_rtti(tfloatdef(def));
+ setdef :
+ setdef_rtti(tsetdef(def));
+ procvardef :
+ procvardef_rtti(tprocvardef(def));
+ arraydef :
+ begin
+ if ado_IsBitPacked in tarraydef(def).arrayoptions then
+ unknown_rtti(tstoreddef(def))
+ else
+ arraydef_rtti(tarraydef(def));
+ end;
+ recorddef :
+ begin
+ if trecorddef(def).is_packed then
+ unknown_rtti(tstoreddef(def))
+ else
+ recorddef_rtti(trecorddef(def));
+ end;
+ objectdef :
+ objectdef_rtti(tobjectdef(def));
+ else
+ unknown_rtti(tstoreddef(def));
+ end;
+ end;
+
+ procedure TRTTIWriter.write_rtti_extrasyms(def:Tdef;rt:Trttitype;mainrtti:Tasmsymbol);
+
+ type Penumsym = ^Tenumsym;
+
+ function enumdef_rtti_calcstringtablestart(const def : Tenumdef) : integer;
+ begin
+ { the alignment calls must correspond to the ones used during generating the
+ actual data structure created elsewhere in this file }
+ result:=1;
+ if assigned(def.typesym) then
+ inc(result,length(def.typesym.realname)+1)
+ else
+ inc(result);
+ if (tf_requires_proper_alignment in target_info.flags) then
+ result:=align(result,sizeof(Tconstptruint));
+ inc(result);
+ if (tf_requires_proper_alignment in target_info.flags) then
+ result:=align(result,sizeof(Tconstptruint));
+ inc(result, sizeof(longint) * 2);
+ if (tf_requires_proper_alignment in target_info.flags) then
+ result:=align(result,sizeof(Tconstptruint));
+ inc(result, sizeof(pint));
+ end;
+
+ { Writes a helper table for accelerated conversion of ordinal enum values to strings.
+ If you change something in this method, make sure to adapt the corresponding code
+ in sstrings.inc. }
+ procedure enumdef_rtti_ord2stringindex(const sym_count:longint; const offsets:plongint; const syms:Penumsym; const st:longint);
+
+ var rttilab:Tasmsymbol;
+ h,i,o:longint;
+ mode:(lookup,search); {Modify with care, ordinal value of enum is written.}
+ r:single; {Must be real type because of integer overflow risk.}
+
+ begin
+
+ {Decide wether a lookup array is size efficient.}
+ mode:=lookup;
+ if sym_count>0 then
+ begin
+ i:=1;
+ r:=0;
+ h:=syms[0].value; {Next expected enum value is min.}
+ while i<sym_count do
+ begin
+ {Calculate size of hole between values. Avoid integer overflows.}
+ r:=r+(single(syms[i].value)-single(h))-1;
+ h:=syms[i].value;
+ inc(i);
+ end;
+ if r>sym_count then
+ mode:=search; {Don't waste more than 50% space.}
+ end;
+ { write rtti data; make sure that the alignment matches the corresponding data structure
+ in the code that uses it (if alignment is required). }
+ with current_asmdata do
+ begin
+ rttilab:=defineasmsymbol(Tstoreddef(def).rtti_mangledname(rt)+'_o2s',AB_GLOBAL,AT_DATA);
+ maybe_new_object_file(asmlists[al_rtti]);
+ new_section(asmlists[al_rtti],sec_rodata,rttilab.name,const_align(sizeof(pint)));
+ asmlists[al_rtti].concat(Tai_symbol.create_global(rttilab,0));
+ asmlists[al_rtti].concat(Tai_const.create_32bit(longint(mode)));
+ if mode=lookup then
+ begin
+ maybe_write_align;
+ o:=syms[0].value; {Start with min value.}
+ for i:=0 to sym_count-1 do
+ begin
+ while o<syms[i].value do
+ begin
+ asmlists[al_rtti].concat(Tai_const.create_pint(0));
+ inc(o);
+ end;
+ inc(o);
+ asmlists[al_rtti].concat(Tai_const.create_sym_offset(mainrtti,st+offsets[i]));
+ end;
+ end
+ else
+ begin
+ maybe_write_align;
+ asmlists[al_rtti].concat(Tai_const.create_32bit(sym_count));
+ for i:=0 to sym_count-1 do
+ begin
+ maybe_write_align;
+ asmlists[al_rtti].concat(Tai_const.create_32bit(syms[i].value));
+ maybe_write_align;
+ asmlists[al_rtti].concat(Tai_const.create_sym_offset(mainrtti,st+offsets[i]));
+ end;
+ end;
+ asmlists[al_rtti].concat(Tai_symbol_end.create(rttilab));
+ end;
+ end;
+
+ { Writes a helper table for accelerated conversion of string to ordinal enum values.
+ If you change something in this method, make sure to adapt the corresponding code
+ in sstrings.inc. }
+ procedure enumdef_rtti_string2ordindex(const sym_count:longint; const offsets:plongint; const syms:Penumsym; const st:longint);
+
+ var rttilab:Tasmsymbol;
+ i:longint;
+
+ begin
+ { write rtti data }
+ with current_asmdata do
+ begin
+ rttilab:=defineasmsymbol(Tstoreddef(def).rtti_mangledname(rt)+'_s2o',AB_GLOBAL,AT_DATA);
+ maybe_new_object_file(asmlists[al_rtti]);
+ new_section(asmlists[al_rtti],sec_rodata,rttilab.name,const_align(sizeof(pint)));
+ asmlists[al_rtti].concat(Tai_symbol.create_global(rttilab,0));
+ asmlists[al_rtti].concat(Tai_const.create_32bit(sym_count));
+ { need to align the entry record according to the largest member }
+ maybe_write_align;
+ for i:=0 to sym_count-1 do
+ begin
+ if (tf_requires_proper_alignment in target_info.flags) then
+ current_asmdata.asmlists[al_rtti].concat(cai_align.Create(4)); // necessary?
+ asmlists[al_rtti].concat(Tai_const.create_32bit(syms[i].value));
+ maybe_write_align;
+ asmlists[al_rtti].concat(Tai_const.create_sym_offset(mainrtti,st+offsets[i]));
+ end;
+ asmlists[al_rtti].concat(Tai_symbol_end.create(rttilab));
+ end;
+ end;
+
+ procedure enumdef_rtti_extrasyms(def:Tenumdef);
+ var
+ t:Tenumsym;
+ syms:Penumsym;
+ sym_count,sym_alloc:sizeuint;
+ offsets:^longint;
+ h,i,p,o,st:longint;
+ begin
+ {Random access needed, put in array.}
+ getmem(syms,64*sizeof(Tenumsym));
+ getmem(offsets,64*sizeof(longint));
+ sym_count:=0;
+ sym_alloc:=64;
+ st:=0;
+ for i := 0 to def.symtable.SymList.Count - 1 do
+ begin
+ t:=tenumsym(def.symtable.SymList[i]);
+ if t.value<def.minval then
+ continue
+ else
+ if t.value>def.maxval then
+ break;
+ if sym_count>=sym_alloc then
+ begin
+ reallocmem(syms,2*sym_alloc*sizeof(Tenumsym));
+ reallocmem(offsets,2*sym_alloc*sizeof(longint));
+ sym_alloc:=sym_alloc*2;
+ end;
+ syms[sym_count]:=t;
+ offsets[sym_count]:=st;
+ inc(sym_count);
+ st:=st+length(t.realname)+1;
+ end;
+ {Sort the syms by enum name}
+ if sym_count>=2 then
+ begin
+ p:=1;
+ while 2*p<sym_count do
+ p:=2*p;
+ while p<>0 do
+ begin
+ for h:=p to sym_count-1 do
+ begin
+ i:=h;
+ t:=syms[i];
+ o:=offsets[i];
+ repeat
+ if syms[i-p].name<=t.name then
+ break;
+ syms[i]:=syms[i-p];
+ offsets[i]:=offsets[i-p];
+ dec(i,p);
+ until i<p;
+ syms[i]:=t;
+ offsets[i]:=o;
+ end;
+ p:=p shr 1;
+ end;
+ end;
+ st:=enumdef_rtti_calcstringtablestart(def);
+ enumdef_rtti_string2ordindex(sym_count,offsets,syms,st);
+ { Sort the syms by enum value }
+ if sym_count>=2 then
+ begin
+ p:=1;
+ while 2*p<sym_count do
+ p:=2*p;
+ while p<>0 do
+ begin
+ for h:=p to sym_count-1 do
+ begin
+ i:=h;
+ t:=syms[i];
+ o:=offsets[i];
+ repeat
+ if syms[i-p].value<=t.value then
+ break;
+ syms[i]:=syms[i-p];
+ offsets[i]:=offsets[i-p];
+ dec(i,p);
+ until i<p;
+ syms[i]:=t;
+ offsets[i]:=o;
+ end;
+ p:=p shr 1;
+ end;
+ end;
+ enumdef_rtti_ord2stringindex(sym_count,offsets,syms,st);
+ freemem(syms);
+ freemem(offsets);
+ end;
+
+
+ begin
+ case def.typ of
+ enumdef:
+ if rt=fullrtti then
+ begin
+ enumdef_rtti_extrasyms(Tenumdef(def));
+ end;
+ end;
+ end;
+
+ procedure TRTTIWriter.write_child_rtti_data(def:tdef;rt:trttitype);
+ begin
+ case def.typ of
+ enumdef :
+ if assigned(tenumdef(def).basedef) then
+ write_rtti(tenumdef(def).basedef,rt);
+ setdef :
+ write_rtti(tsetdef(def).elementdef,rt);
+ arraydef :
+ write_rtti(tarraydef(def).elementdef,rt);
+ recorddef :
+ fields_write_rtti(trecorddef(def).symtable,rt);
+ objectdef :
+ begin
+ if assigned(tobjectdef(def).childof) then
+ write_rtti(tobjectdef(def).childof,rt);
+ if (rt=initrtti) or (tobjectdef(def).objecttype=odt_object) then
+ fields_write_rtti(tobjectdef(def).symtable,rt)
+ else
+ published_write_rtti(tobjectdef(def).symtable,rt);
+ end;
+ end;
+ end;
+
+
+ function TRTTIWriter.ref_rtti(def:tdef;rt:trttitype):tasmsymbol;
+ begin
+ result:=current_asmdata.RefAsmSymbol(def.rtti_mangledname(rt));
+ end;
+
+
+ procedure TRTTIWriter.write_rtti(def:tdef;rt:trttitype);
+ var
+ rttilab : tasmsymbol;
+ begin
+ { only write rtti of definitions from the current module }
+ if not findunitsymtable(def.owner).iscurrentunit then
+ exit;
+ { prevent recursion }
+ if rttidefstate[rt] in def.defstates then
+ exit;
+ include(def.defstates,rttidefstate[rt]);
+ { write first all dependencies }
+ write_child_rtti_data(def,rt);
+ { write rtti data }
+ rttilab:=current_asmdata.DefineAsmSymbol(tstoreddef(def).rtti_mangledname(rt),AB_GLOBAL,AT_DATA);
+ maybe_new_object_file(current_asmdata.asmlists[al_rtti]);
+ new_section(current_asmdata.asmlists[al_rtti],sec_rodata,rttilab.name,const_align(sizeof(pint)));
+ current_asmdata.asmlists[al_rtti].concat(Tai_symbol.Create_global(rttilab,0));
+ write_rtti_data(def,rt);
+ current_asmdata.asmlists[al_rtti].concat(Tai_symbol_end.Create(rttilab));
+ write_rtti_extrasyms(def,rt,rttilab);
+ end;
+
+
+ function TRTTIWriter.get_rtti_label(def:tdef;rt:trttitype):tasmsymbol;
+ begin
+ result:=current_asmdata.RefAsmSymbol(def.rtti_mangledname(rt));
+ end;
+
+ function TRTTIWriter.get_rtti_label_ord2str(def:tdef;rt:trttitype):tasmsymbol;
+ begin
+ result:=current_asmdata.RefAsmSymbol(def.rtti_mangledname(rt)+'_o2s');
+ end;
+
+ function TRTTIWriter.get_rtti_label_str2ord(def:tdef;rt:trttitype):tasmsymbol;
+ begin
+ result:=current_asmdata.RefAsmSymbol(def.rtti_mangledname(rt)+'_s2o');
+ end;
+
+end.
+
diff --git a/closures/compiler/ncgset.pas b/closures/compiler/ncgset.pas
new file mode 100644
index 0000000000..c5491deeb8
--- /dev/null
+++ b/closures/compiler/ncgset.pas
@@ -0,0 +1,879 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl and Carl Eric Codere
+
+ Generate generic assembler for in set/case labels
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit ncgset;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ globtype,globals,constexp,
+ node,nset,cpubase,cgbase,cgutils,cgobj,aasmbase,aasmtai,aasmdata;
+
+ type
+ tcgsetelementnode = class(tsetelementnode)
+ procedure pass_generate_code;override;
+ end;
+
+
+ Tsetpart=record
+ range : boolean; {Part is a range.}
+ start,stop : byte; {Start/stop when range; Stop=element when an element.}
+ end;
+ Tsetparts=array[1..8] of Tsetpart;
+
+ tcginnode = class(tinnode)
+ function pass_1: tnode;override;
+ procedure pass_generate_code;override;
+ protected
+ function checkgenjumps(out setparts: Tsetparts; out numparts: byte; out use_small: boolean): boolean; virtual;
+ function analizeset(const Aset:Tconstset;out setparts: Tsetparts; out numparts: byte;is_small:boolean):boolean;virtual;
+ end;
+
+ tcgcasenode = class(tcasenode)
+ {
+ Emits the case node statement. Contrary to the intel
+ 80x86 version, this version does not emit jump tables,
+ because of portability problems.
+ }
+ procedure pass_generate_code;override;
+
+ protected
+ with_sign : boolean;
+ opsize : tcgsize;
+ jmp_gt,jmp_lt,jmp_le : topcmp;
+ { register with case expression }
+ hregister,hregister2 : tregister;
+ endlabel,elselabel : tasmlabel;
+
+ { true, if we can omit the range check of the jump table }
+ jumptable_no_range : boolean;
+ { has the implementation jumptable support }
+ min_label : tconstexprint;
+
+ function blocklabel(id:longint):tasmlabel;
+ procedure optimizevalues(var max_linear_list:aint;var max_dist:aword);virtual;
+ function has_jumptable : boolean;virtual;
+ procedure genjumptable(hp : pcaselabel;min_,max_ : aint); virtual;
+ procedure genlinearlist(hp : pcaselabel); virtual;
+ procedure genlinearcmplist(hp : pcaselabel); virtual;
+ end;
+
+
+implementation
+
+ uses
+ systems,
+ verbose,
+ symconst,symdef,defutil,
+ paramgr,
+ procinfo,pass_2,tgobj,
+ nbas,ncon,nflw,
+ ncgutil;
+
+
+{*****************************************************************************
+ TCGSETELEMENTNODE
+*****************************************************************************}
+
+ procedure tcgsetelementnode.pass_generate_code;
+ begin
+ { load first value in 32bit register }
+ secondpass(left);
+ if left.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
+ location_force_reg(current_asmdata.CurrAsmList,left.location,OS_32,false);
+
+ { also a second value ? }
+ if assigned(right) then
+ begin
+ secondpass(right);
+ if codegenerror then
+ exit;
+ if right.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
+ location_force_reg(current_asmdata.CurrAsmList,right.location,OS_32,false);
+ end;
+
+ { we doesn't modify the left side, we check only the type }
+ location_copy(location,left.location);
+ end;
+
+
+{*****************************************************************************
+*****************************************************************************}
+
+ function tcginnode.analizeset(const Aset:Tconstset; out setparts:tsetparts; out numparts: byte; is_small:boolean):boolean;
+ var
+ compares,maxcompares:word;
+ i:byte;
+ begin
+ analizeset:=false;
+ fillchar(setparts,sizeof(setparts),0);
+ numparts:=0;
+ compares:=0;
+ { Lots of comparisions take a lot of time, so do not allow
+ too much comparisions. 8 comparisions are, however, still
+ smalller than emitting the set }
+ if cs_opt_size in current_settings.optimizerswitches then
+ maxcompares:=8
+ else
+ maxcompares:=5;
+ { when smallset is possible allow only 3 compares the smallset
+ code is for littlesize also smaller when more compares are used }
+ if is_small then
+ maxcompares:=3;
+ for i:=0 to 255 do
+ if i in Aset then
+ begin
+ if (numparts=0) or (i<>setparts[numparts].stop+1) then
+ begin
+ {Set element is a separate element.}
+ inc(compares);
+ if compares>maxcompares then
+ exit;
+ inc(numparts);
+ setparts[numparts].range:=false;
+ setparts[numparts].stop:=i;
+ end
+ else
+ {Set element is part of a range.}
+ if not setparts[numparts].range then
+ begin
+ {Transform an element into a range.}
+ setparts[numparts].range:=true;
+ setparts[numparts].start:=setparts[numparts].stop;
+ setparts[numparts].stop:=i;
+ { there's only one compare per range anymore. Only a }
+ { sub is added, but that's much faster than a }
+ { cmp/jcc combo so neglect its effect }
+{ inc(compares);
+ if compares>maxcompares then
+ exit; }
+ end
+ else
+ begin
+ {Extend a range.}
+ setparts[numparts].stop:=i;
+ end;
+ end;
+ analizeset:=true;
+ end;
+
+
+ function tcginnode.checkgenjumps(out setparts: Tsetparts; out numparts: byte;out use_small: boolean): boolean;
+ begin
+ { check if we can use smallset operation using btl which is limited
+ to 32 bits, the left side may also not contain higher values !! }
+ use_small:=is_smallset(right.resultdef) and
+ not is_signed(left.resultdef) and
+ ((left.resultdef.typ=orddef) and (torddef(left.resultdef).high<32) or
+ (left.resultdef.typ=enumdef) and (tenumdef(left.resultdef).max<32));
+
+ { Can we generate jumps? Possible for all types of sets }
+ checkgenjumps:=(right.nodetype=setconstn) and
+ analizeset(Tsetconstnode(right).value_set^,setparts,numparts,use_small);
+ end;
+
+
+ function tcginnode.pass_1: tnode;
+ var
+ setparts: Tsetparts;
+ numparts: byte;
+ use_small: boolean;
+ begin
+ result := inherited pass_1;
+ if not(assigned(result)) and
+ checkgenjumps(setparts,numparts,use_small) then
+ expectloc := LOC_JUMP;
+ end;
+
+ procedure tcginnode.pass_generate_code;
+ var
+ adjustment,
+ setbase : aint;
+ l, l2 : tasmlabel;
+ otl, ofl : tasmlabel;
+ hr,
+ pleftreg : tregister;
+ setparts : Tsetparts;
+ opsize : tcgsize;
+ uopsize : tcgsize;
+ orgopsize : tcgsize;
+ genjumps,
+ use_small,
+ isjump : boolean;
+ i,numparts : byte;
+ needslabel : Boolean;
+ begin
+ { We check first if we can generate jumps, this can be done
+ because the resultdef is already set in firstpass }
+
+ genjumps := checkgenjumps(setparts,numparts,use_small);
+
+ orgopsize := def_cgsize(left.resultdef);
+ uopsize := OS_32;
+ if is_signed(left.resultdef) then
+ opsize := tcgsize(ord(uopsize)+(ord(OS_S8)-ord(OS_8)))
+ else
+ opsize := uopsize;
+ needslabel := false;
+
+ isjump:=false;
+ if (left.expectloc=LOC_JUMP) then
+ begin
+ otl:=current_procinfo.CurrTrueLabel;
+ current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
+ ofl:=current_procinfo.CurrFalseLabel;
+ current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel);
+ isjump:=true;
+ end
+ else if not genjumps then
+ { calculate both operators }
+ { the complex one first }
+ { only if left will not be a LOC_JUMP, to keep complexity in the }
+ { code generator down. This almost never happens anyway, only in }
+ { case like "if ((a in someset) in someboolset) then" etc }
+ { also not in case of genjumps, because then we don't secondpass }
+ { right at all (so we have to make sure that "right" really is }
+ { "right" and not "swapped left" in that case) }
+ firstcomplex(self);
+
+ secondpass(left);
+ if isjump then
+ begin
+ location_force_reg(current_asmdata.CurrAsmList,left.location,opsize,true);
+ current_procinfo.CurrTrueLabel:=otl;
+ current_procinfo.CurrFalseLabel:=ofl;
+ end
+ else if (left.location.loc=LOC_JUMP) then
+ internalerror(2007070101);
+
+ { Only process the right if we are not generating jumps }
+ if not genjumps then
+ secondpass(right);
+ if codegenerror then
+ exit;
+
+ { ofcourse not commutative }
+ if nf_swapped in flags then
+ swapleftright;
+
+ setbase:=tsetdef(right.resultdef).setbase;
+ if genjumps then
+ begin
+ { location is always LOC_JUMP }
+ location_reset(location,LOC_JUMP,OS_NO);
+
+ { If register is used, use only lower 8 bits }
+ location_force_reg(current_asmdata.CurrAsmList,left.location,opsize,false);
+ pleftreg := left.location.register;
+
+ { how much have we already substracted from the x in the }
+ { "x in [y..z]" expression }
+ adjustment := 0;
+ hr:=NR_NO;
+
+ for i:=1 to numparts do
+ if setparts[i].range then
+ { use fact that a <= x <= b <=> aword(x-a) <= aword(b-a) }
+ begin
+ { is the range different from all legal values? }
+ if (setparts[i].stop-setparts[i].start <> 255) or not (orgopsize = OS_8) then
+ begin
+ { yes, is the lower bound <> 0? }
+ if (setparts[i].start <> 0) then
+ { we're going to substract from the left register, }
+ { so in case of a LOC_CREGISTER first move the value }
+ { to edi (not done before because now we can do the }
+ { move and substract in one instruction with LEA) }
+ if (left.location.loc = LOC_CREGISTER) and
+ (hr<>pleftreg) then
+ begin
+ { don't change this back to a_op_const_reg/a_load_reg_reg, since pleftreg must not be modified }
+ hr:=cg.getintregister(current_asmdata.CurrAsmList,opsize);
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SUB,opsize,setparts[i].start,pleftreg,hr);
+ pleftreg:=hr;
+ end
+ else
+ begin
+ { otherwise, the value is already in a register }
+ { that can be modified }
+ cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_SUB,opsize,
+ setparts[i].start-adjustment,pleftreg)
+ end;
+ { new total value substracted from x: }
+ { adjustment + (setparts[i].start - adjustment) }
+ adjustment := setparts[i].start;
+
+ { check if result < b-a+1 (not "result <= b-a", since }
+ { we need a carry in case the element is in the range }
+ { (this will never overflow since we check at the }
+ { beginning whether stop-start <> 255) }
+ cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList, opsize, OC_B,
+ setparts[i].stop-setparts[i].start+1,pleftreg,current_procinfo.CurrTrueLabel);
+ end
+ else
+ { if setparts[i].start = 0 and setparts[i].stop = 255, }
+ { it's always true since "in" is only allowed for bytes }
+ begin
+ cg.a_jmp_always(current_asmdata.CurrAsmList,current_procinfo.CurrTrueLabel);
+ end;
+ end
+ else
+ begin
+ { Emit code to check if left is an element }
+ cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList, opsize, OC_EQ,
+ setparts[i].stop-adjustment,pleftreg,current_procinfo.CurrTrueLabel);
+ end;
+ { To compensate for not doing a second pass }
+ right.location.reference.symbol:=nil;
+ cg.a_jmp_always(current_asmdata.CurrAsmList,current_procinfo.CurrFalseLabel);
+ end
+ else
+ {*****************************************************************}
+ { NO JUMP TABLE GENERATION }
+ {*****************************************************************}
+ begin
+ { location is always LOC_REGISTER }
+ location_reset(location, LOC_REGISTER, uopsize{def_cgsize(resultdef)});
+ { allocate a register for the result }
+ location.register := cg.getintregister(current_asmdata.CurrAsmList, uopsize);
+
+ { We will now generated code to check the set itself, no jmps,
+ handle smallsets separate, because it allows faster checks }
+ if use_small then
+ begin
+ {**************************** SMALL SET **********************}
+ if left.location.loc=LOC_CONSTANT then
+ begin
+ cg.a_bit_test_const_loc_reg(current_asmdata.CurrAsmList,location.size,
+ left.location.value-setbase,right.location,
+ location.register);
+ end
+ else
+ begin
+ location_force_reg(current_asmdata.CurrAsmList,left.location,opsize,true);
+ register_maybe_adjust_setbase(current_asmdata.CurrAsmList,left.location,setbase);
+ cg.a_bit_test_reg_loc_reg(current_asmdata.CurrAsmList,left.location.size,
+ location.size,left.location.register,right.location,location.register);
+ end;
+ end
+ else
+ {************************** NOT SMALL SET ********************}
+ begin
+ if right.location.loc=LOC_CONSTANT then
+ begin
+ { can it actually occur currently? CEC }
+ { yes: "if bytevar in [1,3,5,7,9,11,13,15]" (JM) }
+
+ { note: this code assumes that left in [0..255], which is a valid }
+ { assumption (other cases will be caught by range checking) (JM) }
+
+ { load left in register }
+ location_force_reg(current_asmdata.CurrAsmList,left.location,location.size,true);
+ register_maybe_adjust_setbase(current_asmdata.CurrAsmList,left.location,setbase);
+ { emit bit test operation -- warning: do not use
+ location_force_reg() to force a set into a register, except
+ to a register of the same size as the set. The reason is
+ that on big endian systems, this would require moving the
+ set to the most significant part of the new register,
+ and location_force_register can't do that (it does not
+ know the type).
+
+ a_bit_test_reg_loc_reg() properly takes into account the
+ size of the set to adjust the register index to test }
+ cg.a_bit_test_reg_loc_reg(current_asmdata.CurrAsmList,
+ left.location.size,location.size,
+ left.location.register,right.location,location.register);
+
+ { now zero the result if left > nr_of_bits_in_right_register }
+ hr := cg.getintregister(current_asmdata.CurrAsmList,location.size);
+ { if left > tcgsize2size[opsize]*8 then hr := 0 else hr := $ffffffff }
+ { (left.location.size = location.size at this point) }
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_SUB, location.size, tcgsize2size[opsize]*8, left.location.register, hr);
+ cg.a_op_const_reg(current_asmdata.CurrAsmList, OP_SAR, location.size, (tcgsize2size[opsize]*8)-1, hr);
+
+ { if left > tcgsize2size[opsize]*8-1, then result := 0 else result := result of bit test }
+ cg.a_op_reg_reg(current_asmdata.CurrAsmList, OP_AND, location.size, hr, location.register);
+ end { of right.location.loc=LOC_CONSTANT }
+ { do search in a normal set which could have >32 elements
+ but also used if the left side contains higher values > 32 }
+ else if (left.location.loc=LOC_CONSTANT) then
+ begin
+ if (left.location.value < setbase) or (((left.location.value-setbase) shr 3) >= right.resultdef.size) then
+ {should be caught earlier }
+ internalerror(2007020402);
+
+ cg.a_bit_test_const_loc_reg(current_asmdata.CurrAsmList,location.size,left.location.value-setbase,
+ right.location,location.register);
+ end
+ else
+ begin
+ location_force_reg(current_asmdata.CurrAsmList, left.location, opsize, true);
+ register_maybe_adjust_setbase(current_asmdata.CurrAsmList,left.location,setbase);
+ pleftreg := left.location.register;
+
+ if (opsize >= OS_S8) or { = if signed }
+ ((left.resultdef.typ=orddef) and
+ ((torddef(left.resultdef).low < int64(tsetdef(right.resultdef).setbase)) or
+ (torddef(left.resultdef).high > int64(tsetdef(right.resultdef).setmax)))) or
+ ((left.resultdef.typ=enumdef) and
+ ((tenumdef(left.resultdef).min < aint(tsetdef(right.resultdef).setbase)) or
+ (tenumdef(left.resultdef).max > aint(tsetdef(right.resultdef).setmax)))) then
+ begin
+ current_asmdata.getjumplabel(l);
+ current_asmdata.getjumplabel(l2);
+ needslabel := True;
+
+ cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList, left.location.size, OC_BE, tsetdef(right.resultdef).setmax-tsetdef(right.resultdef).setbase, pleftreg, l);
+
+ cg.a_load_const_reg(current_asmdata.CurrAsmList, location.size, 0, location.register);
+ cg.a_jmp_always(current_asmdata.CurrAsmList, l2);
+
+ cg.a_label(current_asmdata.CurrAsmList, l);
+ end;
+
+ cg.a_bit_test_reg_loc_reg(current_asmdata.CurrAsmList,left.location.size,location.size,
+ pleftreg,right.location,location.register);
+
+ if needslabel then
+ cg.a_label(current_asmdata.CurrAsmList, l2);
+ end;
+ end;
+ end;
+ location_freetemp(current_asmdata.CurrAsmList, right.location);
+
+ location.size := def_cgsize(resultdef);
+ location.register := cg.makeregsize(current_asmdata.CurrAsmList, location.register, location.size);
+ end;
+
+{*****************************************************************************
+ TCGCASENODE
+*****************************************************************************}
+
+ function tcgcasenode.blocklabel(id:longint):tasmlabel;
+ begin
+ if not assigned(blocks[id]) then
+ internalerror(200411301);
+ result:=pcaseblock(blocks[id])^.blocklabel;
+ end;
+
+
+ procedure tcgcasenode.optimizevalues(var max_linear_list:aint;var max_dist:aword);
+ begin
+ { no changes by default }
+ end;
+
+
+ function tcgcasenode.has_jumptable : boolean;
+ begin
+ { No jumptable support in the default implementation }
+ has_jumptable:=false;
+ end;
+
+
+ procedure tcgcasenode.genjumptable(hp : pcaselabel;min_,max_ : aint);
+ begin
+ internalerror(200209161);
+ end;
+
+
+ procedure tcgcasenode.genlinearlist(hp : pcaselabel);
+
+ var
+ first : boolean;
+ last : TConstExprInt;
+ scratch_reg: tregister;
+
+ procedure genitem(t : pcaselabel);
+
+ procedure gensub(value:aint);
+ begin
+ { here, since the sub and cmp are separate we need
+ to move the result before subtract to help
+ the register allocator
+ }
+ cg.a_load_reg_reg(current_asmdata.CurrAsmList, opsize, opsize, hregister, scratch_reg);
+ cg.a_op_const_reg(current_asmdata.CurrAsmList, OP_SUB, opsize, value, hregister);
+ end;
+
+ begin
+ if assigned(t^.less) then
+ genitem(t^.less);
+ { do we need to test the first value? }
+ if first and (t^._low>get_min_value(left.resultdef)) then
+ cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,opsize,jmp_lt,aint(t^._low.svalue),hregister,elselabel);
+ if t^._low=t^._high then
+ begin
+ if t^._low-last=0 then
+ cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,opsize,OC_EQ,0,hregister,blocklabel(t^.blockid))
+ else
+ begin
+ gensub(aint(t^._low.svalue-last.svalue));
+ cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,opsize,
+ OC_EQ,aint(t^._low.svalue-last.svalue),scratch_reg,blocklabel(t^.blockid));
+ end;
+ last:=t^._low;
+ end
+ else
+ begin
+ { it begins with the smallest label, if the value }
+ { is even smaller then jump immediately to the }
+ { ELSE-label }
+ if first then
+ begin
+ { have we to ajust the first value ? }
+ if (t^._low>get_min_value(left.resultdef)) or (get_min_value(left.resultdef)<>0) then
+ gensub(aint(t^._low.svalue));
+ end
+ else
+ begin
+ { if there is no unused label between the last and the }
+ { present label then the lower limit can be checked }
+ { immediately. else check the range in between: }
+ gensub(aint(t^._low.svalue-last.svalue));
+ cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList, opsize,jmp_lt,aint(t^._low.svalue-last.svalue),scratch_reg,elselabel);
+ end;
+ gensub(aint(t^._high.svalue-t^._low.svalue));
+ cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,opsize,jmp_le,aint(t^._high.svalue-t^._low.svalue),scratch_reg,blocklabel(t^.blockid));
+ last:=t^._high;
+ end;
+ first:=false;
+ if assigned(t^.greater) then
+ genitem(t^.greater);
+ end;
+
+ begin
+ { do we need to generate cmps? }
+ if (with_sign and (min_label<0)) then
+ genlinearcmplist(hp)
+ else
+ begin
+ last:=0;
+ first:=true;
+ scratch_reg:=cg.getintregister(current_asmdata.CurrAsmList,opsize);
+ genitem(hp);
+ cg.a_jmp_always(current_asmdata.CurrAsmList,elselabel);
+ end;
+ end;
+
+
+ procedure tcgcasenode.genlinearcmplist(hp : pcaselabel);
+
+ var
+ last : TConstExprInt;
+ lastwasrange: boolean;
+
+ procedure genitem(t : pcaselabel);
+
+{$ifndef cpu64bitalu}
+ var
+ l1 : tasmlabel;
+{$endif not cpu64bitalu}
+
+ begin
+ if assigned(t^.less) then
+ genitem(t^.less);
+ if t^._low=t^._high then
+ begin
+{$ifndef cpu64bitalu}
+ if opsize in [OS_S64,OS_64] then
+ begin
+ current_asmdata.getjumplabel(l1);
+ cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList, OS_32, OC_NE, aint(hi(int64(t^._low.svalue))),hregister2,l1);
+ cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList, OS_32, OC_EQ, aint(lo(int64(t^._low.svalue))),hregister, blocklabel(t^.blockid));
+ cg.a_label(current_asmdata.CurrAsmList,l1);
+ end
+ else
+{$endif not cpu64bitalu}
+ begin
+ cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList, opsize, OC_EQ, aint(t^._low.svalue),hregister, blocklabel(t^.blockid));
+ end;
+ { Reset last here, because we've only checked for one value and need to compare
+ for the next range both the lower and upper bound }
+ lastwasrange := false;
+ end
+ else
+ begin
+ { it begins with the smallest label, if the value }
+ { is even smaller then jump immediately to the }
+ { ELSE-label }
+ if not lastwasrange or (t^._low-last>1) then
+ begin
+{$ifndef cpu64bitalu}
+ if opsize in [OS_64,OS_S64] then
+ begin
+ current_asmdata.getjumplabel(l1);
+ cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList, OS_32, jmp_lt, aint(hi(int64(t^._low.svalue))),
+ hregister2, elselabel);
+ cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList, OS_32, jmp_gt, aint(hi(int64(t^._low.svalue))),
+ hregister2, l1);
+ { the comparisation of the low dword must be always unsigned! }
+ cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList, OS_32, OC_B, aint(lo(int64(t^._low.svalue))), hregister, elselabel);
+ cg.a_label(current_asmdata.CurrAsmList,l1);
+ end
+ else
+{$endif not cpu64bitalu}
+ begin
+ cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList, opsize, jmp_lt, aint(t^._low.svalue), hregister,
+ elselabel);
+ end;
+ end;
+{$ifndef cpu64bitalu}
+ if opsize in [OS_S64,OS_64] then
+ begin
+ current_asmdata.getjumplabel(l1);
+ cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList, OS_32, jmp_lt, aint(hi(int64(t^._high.svalue))), hregister2,
+ blocklabel(t^.blockid));
+ cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList, OS_32, jmp_gt, aint(hi(int64(t^._high.svalue))), hregister2,
+ l1);
+ cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList, OS_32, OC_BE, aint(lo(int64(t^._high.svalue))), hregister, blocklabel(t^.blockid));
+ cg.a_label(current_asmdata.CurrAsmList,l1);
+ end
+ else
+{$endif not cpu64bitalu}
+ begin
+ cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList, opsize, jmp_le, aint(t^._high.svalue), hregister, blocklabel(t^.blockid));
+ end;
+
+ last:=t^._high;
+ lastwasrange := true;
+ end;
+ if assigned(t^.greater) then
+ genitem(t^.greater);
+ end;
+
+ begin
+ last:=0;
+ lastwasrange:=false;
+ genitem(hp);
+ cg.a_jmp_always(current_asmdata.CurrAsmList,elselabel);
+ end;
+
+
+ procedure tcgcasenode.pass_generate_code;
+ var
+ oldflowcontrol: tflowcontrol;
+ i : longint;
+ distv,
+ lv,hv,
+ max_label: tconstexprint;
+ labelcnt : aint;
+ max_linear_list : aint;
+ otl, ofl: tasmlabel;
+ isjump : boolean;
+ max_dist,
+ dist : aword;
+ oldexecutionweight : longint;
+ begin
+ location_reset(location,LOC_VOID,OS_NO);
+
+ oldflowcontrol := flowcontrol;
+ include(flowcontrol,fc_inflowcontrol);
+ { Allocate labels }
+ current_asmdata.getjumplabel(endlabel);
+ current_asmdata.getjumplabel(elselabel);
+ for i:=0 to blocks.count-1 do
+ current_asmdata.getjumplabel(pcaseblock(blocks[i])^.blocklabel);
+
+ with_sign:=is_signed(left.resultdef);
+ if with_sign then
+ begin
+ jmp_gt:=OC_GT;
+ jmp_lt:=OC_LT;
+ jmp_le:=OC_LTE;
+ end
+ else
+ begin
+ jmp_gt:=OC_A;
+ jmp_lt:=OC_B;
+ jmp_le:=OC_BE;
+ end;
+
+ { save current current_procinfo.CurrTrueLabel and current_procinfo.CurrFalseLabel }
+ isjump:=false;
+ if left.expectloc=LOC_JUMP then
+ begin
+ otl:=current_procinfo.CurrTrueLabel;
+ current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
+ ofl:=current_procinfo.CurrFalseLabel;
+ current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel);
+ isjump:=true;
+ end;
+ secondpass(left);
+ { determines the size of the operand }
+ opsize:=def_cgsize(left.resultdef);
+ { copy the case expression to a register }
+ location_force_reg(current_asmdata.CurrAsmList,left.location,opsize,false);
+{$ifndef cpu64bitalu}
+ if opsize in [OS_S64,OS_64] then
+ begin
+ hregister:=left.location.register64.reglo;
+ hregister2:=left.location.register64.reghi;
+ end
+ else
+{$endif not cpu64bitalu}
+ hregister:=left.location.register;
+ if isjump then
+ begin
+ current_procinfo.CurrTrueLabel:=otl;
+ current_procinfo.CurrFalseLabel:=ofl;
+ end
+ else
+ if (left.location.loc=LOC_JUMP) then
+ internalerror(2006050501);
+
+ { we need the min_label always to choose between }
+ { cmps and subs/decs }
+ min_label:=case_get_min(labels);
+
+ { Generate the jumps }
+{$ifdef OLDREGVARS}
+ load_all_regvars(current_asmdata.CurrAsmList);
+{$endif OLDREGVARS}
+{$ifndef cpu64bitalu}
+ if opsize in [OS_64,OS_S64] then
+ genlinearcmplist(labels)
+ else
+{$endif not cpu64bitalu}
+ begin
+ if cs_opt_level1 in current_settings.optimizerswitches then
+ begin
+ { procedures are empirically passed on }
+ { consumption can also be calculated }
+ { but does it pay on the different }
+ { processors? }
+ { moreover can the size only be appro- }
+ { ximated as it is not known if rel8, }
+ { rel16 or rel32 jumps are used }
+ max_label:=case_get_max(labels);
+ labelcnt:=case_count_labels(labels);
+ { can we omit the range check of the jump table ? }
+ getrange(left.resultdef,lv,hv);
+ jumptable_no_range:=(lv=min_label) and (hv=max_label);
+ { hack a little bit, because the range can be greater }
+ { than the positive range of a aint }
+
+ if (min_label<0) and (max_label>0) then
+ distv:=max_label+min_label
+ else
+ distv:=max_label-min_label;
+ if (distv>=0) then
+ dist:=distv.uvalue
+ else
+ dist:=-distv.svalue;
+
+ { optimize for size ? }
+ if cs_opt_size in current_settings.optimizerswitches then
+ begin
+ if has_jumptable and
+ (min_label>=int64(low(aint))) and
+ (max_label<=high(aint)) and
+ not((labelcnt<=2) or
+ ((max_label-min_label)<0) or
+ ((max_label-min_label)>3*labelcnt)) then
+ begin
+ { if the labels less or more a continuum then }
+ genjumptable(labels,min_label.svalue,max_label.svalue);
+ end
+ else
+ begin
+ { a linear list is always smaller than a jump tree }
+ genlinearlist(labels);
+ end;
+ end
+ else
+ begin
+ max_dist:=4*labelcnt;
+ if jumptable_no_range then
+ max_linear_list:=4
+ else
+ max_linear_list:=2;
+
+ { allow processor specific values }
+ optimizevalues(max_linear_list,max_dist);
+
+ if (labelcnt<=max_linear_list) then
+ genlinearlist(labels)
+ else
+ begin
+ if (has_jumptable) and
+ (dist<max_dist) and
+ (min_label>=int64(low(aint))) and
+ (max_label<=high(aint)) then
+ genjumptable(labels,min_label.svalue,max_label.svalue)
+ else
+ genlinearlist(labels);
+ end;
+ end;
+ end
+ else
+ { it's always not bad }
+ genlinearlist(labels);
+ end;
+
+ { estimates the repeat of each instruction }
+ oldexecutionweight:=cg.executionweight;
+ cg.executionweight:=cg.executionweight div case_count_labels(labels);
+ if cg.executionweight<1 then
+ cg.executionweight:=1;
+
+ { generate the instruction blocks }
+ for i:=0 to blocks.count-1 do
+ begin
+ current_asmdata.CurrAsmList.concat(cai_align.create(current_settings.alignment.jumpalign));
+ cg.a_label(current_asmdata.CurrAsmList,pcaseblock(blocks[i])^.blocklabel);
+ secondpass(pcaseblock(blocks[i])^.statement);
+ { don't come back to case line }
+ current_filepos:=current_asmdata.CurrAsmList.getlasttaifilepos^;
+{$ifdef OLDREGVARS}
+ load_all_regvars(current_asmdata.CurrAsmList);
+{$endif OLDREGVARS}
+ cg.a_jmp_always(current_asmdata.CurrAsmList,endlabel);
+ end;
+ current_asmdata.CurrAsmList.concat(cai_align.create(current_settings.alignment.jumpalign));
+ { ...and the else block }
+ cg.a_label(current_asmdata.CurrAsmList,elselabel);
+ if assigned(elseblock) then
+ begin
+ secondpass(elseblock);
+{$ifdef OLDREGVARS}
+ load_all_regvars(current_asmdata.CurrAsmList);
+{$endif OLDREGVARS}
+ end;
+
+ cg.executionweight:=oldexecutionweight;
+
+ current_asmdata.CurrAsmList.concat(cai_align.create(current_settings.alignment.jumpalign));
+ cg.a_label(current_asmdata.CurrAsmList,endlabel);
+
+ { Reset labels }
+ for i:=0 to blocks.count-1 do
+ pcaseblock(blocks[i])^.blocklabel:=nil;
+ flowcontrol := oldflowcontrol + (flowcontrol - [fc_inflowcontrol]);
+ end;
+
+
+begin
+ csetelementnode:=tcgsetelementnode;
+ cinnode:=tcginnode;
+ ccasenode:=tcgcasenode;
+end.
diff --git a/closures/compiler/ncgutil.pas b/closures/compiler/ncgutil.pas
new file mode 100644
index 0000000000..093708bf55
--- /dev/null
+++ b/closures/compiler/ncgutil.pas
@@ -0,0 +1,3252 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Helper routines for all code generators
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit ncgutil;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,cpuinfo,
+ globtype,
+ cpubase,cgbase,parabase,cgutils,
+ aasmbase,aasmtai,aasmdata,aasmcpu,
+ symconst,symbase,symdef,symsym,symtype,symtable
+{$ifndef cpu64bitalu}
+ ,cg64f32
+{$endif not cpu64bitalu}
+ ;
+
+ type
+ tloadregvars = (lr_dont_load_regvars, lr_load_regvars);
+
+ pusedregvars = ^tusedregvars;
+ tusedregvars = record
+ intregvars, fpuregvars, mmregvars: Tsuperregisterworklist;
+ end;
+
+{
+ Not used currently, implemented because I thought we had to
+ synchronise around if/then/else as well, but not needed. May
+ still be useful for SSA once we get around to implementing
+ that (JM)
+
+ pusedregvarscommon = ^tusedregvarscommon;
+ tusedregvarscommon = record
+ allregvars, commonregvars, myregvars: tusedregvars;
+ end;
+}
+
+ procedure firstcomplex(p : tbinarynode);
+ procedure maketojumpbool(list:TAsmList; p : tnode; loadregvars: tloadregvars);
+// procedure remove_non_regvars_from_loc(const t: tlocation; var regs:Tsuperregisterset);
+
+ procedure location_force_reg(list:TAsmList;var l:tlocation;dst_size:TCGSize;maybeconst:boolean);
+ procedure location_force_fpureg(list:TAsmList;var l: tlocation;maybeconst:boolean);
+ procedure location_force_mem(list:TAsmList;var l:tlocation);
+ procedure location_force_mmregscalar(list:TAsmList;var l: tlocation;maybeconst:boolean);
+ procedure location_force_mmreg(list:TAsmList;var l: tlocation;maybeconst:boolean);
+ procedure location_allocate_register(list:TAsmList;out l: tlocation;def: tdef;constant: boolean);
+
+ { load a tlocation into a cgpara }
+ procedure gen_load_loc_cgpara(list: TAsmList; vardef: tdef; const l: tlocation; const cgpara: tcgpara);
+ { loads a cgpara into a tlocation; assumes that loc.loc is already
+ initialised }
+ procedure gen_load_cgpara_loc(list: TAsmList; vardef: tdef; const para: TCGPara; var destloc: tlocation; reusepara: boolean);
+
+ { allocate registers for a tlocation; assumes that loc.loc is already
+ set to LOC_CREGISTER/LOC_CFPUREGISTER/... }
+ procedure gen_alloc_regloc(list:TAsmList;var loc: tlocation);
+
+ procedure register_maybe_adjust_setbase(list: TAsmList; var l: tlocation; setbase: aint);
+
+ { Retrieve the location of the data pointed to in location l, when the location is
+ a register it is expected to contain the address of the data }
+ procedure location_get_data_ref(list:TAsmList;const l:tlocation;var ref:treference;loadref:boolean; alignment: longint);
+
+ function has_alias_name(pd:tprocdef;const s:string):boolean;
+ procedure alloc_proc_symbol(pd: tprocdef);
+ procedure gen_proc_symbol(list:TAsmList);
+ procedure gen_proc_symbol_end(list:TAsmList);
+ procedure gen_proc_entry_code(list:TAsmList);
+ procedure gen_proc_exit_code(list:TAsmList);
+ procedure gen_stack_check_size_para(list:TAsmList);
+ procedure gen_stack_check_call(list:TAsmList);
+ procedure gen_save_used_regs(list:TAsmList);
+ procedure gen_restore_used_regs(list:TAsmList);
+ procedure gen_initialize_code(list:TAsmList);
+ procedure gen_finalize_code(list:TAsmList);
+ procedure gen_entry_code(list:TAsmList);
+ procedure gen_exit_code(list:TAsmList);
+ procedure gen_load_para_value(list:TAsmList);
+ procedure gen_load_return_value(list:TAsmList);
+
+ procedure gen_external_stub(list:TAsmList;pd:tprocdef;const externalname:string);
+ procedure gen_intf_wrappers(list:TAsmList;st:TSymtable;nested:boolean);
+ procedure gen_load_vmt_register(list:TAsmList;objdef:tobjectdef;selfloc:tlocation;var vmtreg:tregister);
+
+ procedure get_used_regvars(n: tnode; var rv: tusedregvars);
+ { adds the regvars used in n and its children to rv.allregvars,
+ those which were already in rv.allregvars to rv.commonregvars and
+ uses rv.myregvars as scratch (so that two uses of the same regvar
+ in a single tree to make it appear in commonregvars). Useful to
+ find out which regvars are used in two different node trees
+ (e.g. in the "else" and "then" path, or in various case blocks }
+// procedure get_used_regvars_common(n: tnode; var rv: tusedregvarscommon);
+ procedure gen_sync_regvars(list:TAsmList; var rv: tusedregvars);
+
+ { if the result of n is a LOC_C(..)REGISTER, try to find the corresponding }
+ { loadn and change its location to a new register (= SSA). In case reload }
+ { is true, transfer the old to the new register }
+ procedure maybechangeloadnodereg(list: TAsmList; var n: tnode; reload: boolean);
+
+ {#
+ Allocate the buffers for exception management and setjmp environment.
+ Return a pointer to these buffers, send them to the utility routine
+ so they are registered, and then call setjmp.
+
+ Then compare the result of setjmp with 0, and if not equal
+ to zero, then jump to exceptlabel.
+
+ Also store the result of setjmp to a temporary space by calling g_save_exception_reason
+
+ It is to note that this routine may be called *after* the stackframe of a
+ routine has been called, therefore on machines where the stack cannot
+ be modified, all temps should be allocated on the heap instead of the
+ stack.
+ }
+
+ const
+
+ EXCEPT_BUF_SIZE = 3*sizeof(pint);
+ type
+ texceptiontemps=record
+ jmpbuf,
+ envbuf,
+ reasonbuf : treference;
+ end;
+
+ procedure get_exception_temps(list:TAsmList;var t:texceptiontemps);
+ procedure unget_exception_temps(list:TAsmList;const t:texceptiontemps);
+ procedure new_exception(list:TAsmList;const t:texceptiontemps;exceptlabel:tasmlabel);
+ procedure free_exception(list:TAsmList;const t:texceptiontemps;a:aint;endexceptlabel:tasmlabel;onlyfree:boolean);
+
+ procedure insertbssdata(sym : tstaticvarsym);
+
+ procedure gen_alloc_symtable(list:TAsmList;st:TSymtable);
+ procedure gen_free_symtable(list:TAsmList;st:TSymtable);
+
+ procedure location_free(list: TAsmList; const location : TLocation);
+
+ function getprocalign : shortint;
+
+ procedure gen_fpc_dummy(list : TAsmList);
+
+ procedure InsertInterruptTable;
+
+implementation
+
+ uses
+ version,
+ cutils,cclasses,
+ globals,systems,verbose,export,
+ ppu,defutil,
+ procinfo,paramgr,fmodule,
+ regvars,dbgbase,
+ pass_1,pass_2,
+ nbas,ncon,nld,nmem,nutils,
+ tgobj,cgobj,cgcpu
+{$ifdef powerpc}
+ , cpupi
+{$endif}
+{$ifdef powerpc64}
+ , cpupi
+{$endif}
+{$ifdef SUPPORT_MMX}
+ , cgx86
+{$endif SUPPORT_MMX}
+;
+
+
+{*****************************************************************************
+ Misc Helpers
+*****************************************************************************}
+{$if first_mm_imreg = 0}
+ {$WARN 4044 OFF} { Comparison might be always false ... }
+{$endif}
+
+ procedure location_free(list: TAsmList; const location : TLocation);
+ begin
+ case location.loc of
+ LOC_VOID:
+ ;
+ LOC_REGISTER,
+ LOC_CREGISTER:
+ begin
+{$ifdef cpu64bitaddr}
+ { x86-64 system v abi:
+ structs with up to 16 bytes are returned in registers }
+ if location.size in [OS_128,OS_S128] then
+ begin
+ if getsupreg(location.register)<first_int_imreg then
+ cg.ungetcpuregister(list,location.register);
+ if getsupreg(location.registerhi)<first_int_imreg then
+ cg.ungetcpuregister(list,location.registerhi);
+ end
+{$else cpu64bitaddr}
+ if location.size in [OS_64,OS_S64] then
+ begin
+ if getsupreg(location.register64.reglo)<first_int_imreg then
+ cg.ungetcpuregister(list,location.register64.reglo);
+ if getsupreg(location.register64.reghi)<first_int_imreg then
+ cg.ungetcpuregister(list,location.register64.reghi);
+ end
+{$endif}
+ else
+ if getsupreg(location.register)<first_int_imreg then
+ cg.ungetcpuregister(list,location.register);
+ end;
+ LOC_FPUREGISTER,
+ LOC_CFPUREGISTER:
+ begin
+ if getsupreg(location.register)<first_fpu_imreg then
+ cg.ungetcpuregister(list,location.register);
+ end;
+ LOC_MMREGISTER,
+ LOC_CMMREGISTER :
+ begin
+ if getsupreg(location.register)<first_mm_imreg then
+ cg.ungetcpuregister(list,location.register);
+ end;
+ LOC_REFERENCE,
+ LOC_CREFERENCE :
+ begin
+ if paramanager.use_fixed_stack then
+ location_freetemp(list,location);
+ end;
+ else
+ internalerror(2004110211);
+ end;
+ end;
+
+
+ procedure firstcomplex(p : tbinarynode);
+ var
+ fcl, fcr: longint;
+ ncl, ncr: longint;
+ begin
+ { always calculate boolean AND and OR from left to right }
+ if (p.nodetype in [orn,andn]) and
+ is_boolean(p.left.resultdef) then
+ begin
+ if nf_swapped in p.flags then
+ internalerror(200709253);
+ end
+ else
+ begin
+ fcl:=node_resources_fpu(p.left);
+ fcr:=node_resources_fpu(p.right);
+ ncl:=node_complexity(p.left);
+ ncr:=node_complexity(p.right);
+ { We swap left and right if
+ a) right needs more floating point registers than left, and
+ left needs more than 0 floating point registers (if it
+ doesn't need any, swapping won't change the floating
+ point register pressure)
+ b) both left and right need an equal amount of floating
+ point registers or right needs no floating point registers,
+ and in addition right has a higher complexity than left
+ (+- needs more integer registers, but not necessarily)
+ }
+ if ((fcr>fcl) and
+ (fcl>0)) or
+ (((fcr=fcl) or
+ (fcr=0)) and
+ (ncr>ncl)) then
+ p.swapleftright
+ end;
+ end;
+
+
+ procedure maketojumpbool(list:TAsmList; p : tnode; loadregvars: tloadregvars);
+ {
+ produces jumps to true respectively false labels using boolean expressions
+
+ depending on whether the loading of regvars is currently being
+ synchronized manually (such as in an if-node) or automatically (most of
+ the other cases where this procedure is called), loadregvars can be
+ "lr_load_regvars" or "lr_dont_load_regvars"
+ }
+ var
+ opsize : tcgsize;
+ storepos : tfileposinfo;
+ tmpreg : tregister;
+ begin
+ if nf_error in p.flags then
+ exit;
+ storepos:=current_filepos;
+ current_filepos:=p.fileinfo;
+ if is_boolean(p.resultdef) then
+ begin
+{$ifdef OLDREGVARS}
+ if loadregvars = lr_load_regvars then
+ load_all_regvars(list);
+{$endif OLDREGVARS}
+ if is_constboolnode(p) then
+ begin
+ if Tordconstnode(p).value.uvalue<>0 then
+ cg.a_jmp_always(list,current_procinfo.CurrTrueLabel)
+ else
+ cg.a_jmp_always(list,current_procinfo.CurrFalseLabel)
+ end
+ else
+ begin
+ opsize:=def_cgsize(p.resultdef);
+ case p.location.loc of
+ LOC_SUBSETREG,LOC_CSUBSETREG,
+ LOC_SUBSETREF,LOC_CSUBSETREF:
+ begin
+ tmpreg := cg.getintregister(list,OS_INT);
+ cg.a_load_loc_reg(list,OS_INT,p.location,tmpreg);
+ cg.a_cmp_const_reg_label(list,OS_INT,OC_NE,0,tmpreg,current_procinfo.CurrTrueLabel);
+ cg.a_jmp_always(list,current_procinfo.CurrFalseLabel);
+ end;
+ LOC_CREGISTER,LOC_REGISTER,LOC_CREFERENCE,LOC_REFERENCE :
+ begin
+{$ifndef cpu64bitalu}
+ if opsize in [OS_64,OS_S64] then
+ begin
+ location_force_reg(list,p.location,opsize,true);
+ tmpreg:=cg.getintregister(list,OS_32);
+ cg.a_op_reg_reg_reg(list,OP_OR,OS_32,p.location.register64.reglo,p.location.register64.reghi,tmpreg);
+ location_reset(p.location,LOC_REGISTER,OS_32);
+ p.location.register:=tmpreg;
+ opsize:=OS_32;
+ end;
+{$endif not cpu64bitalu}
+ cg.a_cmp_const_loc_label(list,opsize,OC_NE,0,p.location,current_procinfo.CurrTrueLabel);
+ cg.a_jmp_always(list,current_procinfo.CurrFalseLabel);
+ end;
+ LOC_JUMP:
+ ;
+{$ifdef cpuflags}
+ LOC_FLAGS :
+ begin
+ cg.a_jmp_flags(list,p.location.resflags,current_procinfo.CurrTrueLabel);
+ cg.a_jmp_always(list,current_procinfo.CurrFalseLabel);
+ end;
+{$endif cpuflags}
+ else
+ begin
+ printnode(output,p);
+ internalerror(200308241);
+ end;
+ end;
+ end;
+ end
+ else
+ internalerror(200112305);
+ current_filepos:=storepos;
+ end;
+
+
+ (*
+ This code needs fixing. It is not safe to use rgint; on the m68000 it
+ would be rgaddr.
+
+ procedure remove_non_regvars_from_loc(const t: tlocation; var regs:Tsuperregisterset);
+ begin
+ case t.loc of
+ LOC_REGISTER:
+ begin
+ { can't be a regvar, since it would be LOC_CREGISTER then }
+ exclude(regs,getsupreg(t.register));
+ if t.register64.reghi<>NR_NO then
+ exclude(regs,getsupreg(t.register64.reghi));
+ end;
+ LOC_CREFERENCE,LOC_REFERENCE:
+ begin
+ if not(cs_opt_regvar in current_settings.optimizerswitches) or
+ (getsupreg(t.reference.base) in cg.rgint.usableregs) then
+ exclude(regs,getsupreg(t.reference.base));
+ if not(cs_opt_regvar in current_settings.optimizerswitches) or
+ (getsupreg(t.reference.index) in cg.rgint.usableregs) then
+ exclude(regs,getsupreg(t.reference.index));
+ end;
+ end;
+ end;
+ *)
+
+
+{*****************************************************************************
+ EXCEPTION MANAGEMENT
+*****************************************************************************}
+
+ procedure get_exception_temps(list:TAsmList;var t:texceptiontemps);
+ var
+ srsym : ttypesym;
+ begin
+ if jmp_buf_size=-1 then
+ begin
+ srsym:=search_system_type('JMP_BUF');
+ jmp_buf_size:=srsym.typedef.size;
+ jmp_buf_align:=srsym.typedef.alignment;
+ end;
+ tg.GetTemp(list,EXCEPT_BUF_SIZE,sizeof(pint),tt_persistent,t.envbuf);
+ tg.GetTemp(list,jmp_buf_size,jmp_buf_align,tt_persistent,t.jmpbuf);
+ tg.GetTemp(list,sizeof(pint),sizeof(pint),tt_persistent,t.reasonbuf);
+ end;
+
+
+ procedure unget_exception_temps(list:TAsmList;const t:texceptiontemps);
+ begin
+ tg.Ungettemp(list,t.jmpbuf);
+ tg.ungettemp(list,t.envbuf);
+ tg.ungettemp(list,t.reasonbuf);
+ end;
+
+
+ procedure new_exception(list:TAsmList;const t:texceptiontemps;exceptlabel:tasmlabel);
+ var
+ paraloc1,paraloc2,paraloc3 : tcgpara;
+ begin
+ paraloc1.init;
+ paraloc2.init;
+ paraloc3.init;
+ paramanager.getintparaloc(pocall_default,1,paraloc1);
+ paramanager.getintparaloc(pocall_default,2,paraloc2);
+ paramanager.getintparaloc(pocall_default,3,paraloc3);
+ cg.a_loadaddr_ref_cgpara(list,t.envbuf,paraloc3);
+ cg.a_loadaddr_ref_cgpara(list,t.jmpbuf,paraloc2);
+ { push type of exceptionframe }
+ cg.a_load_const_cgpara(list,OS_S32,1,paraloc1);
+ paramanager.freecgpara(list,paraloc3);
+ paramanager.freecgpara(list,paraloc2);
+ paramanager.freecgpara(list,paraloc1);
+ cg.allocallcpuregisters(list);
+ cg.a_call_name(list,'FPC_PUSHEXCEPTADDR',false);
+ cg.deallocallcpuregisters(list);
+
+ paramanager.getintparaloc(pocall_default,1,paraloc1);
+ cg.a_load_reg_cgpara(list,OS_ADDR,NR_FUNCTION_RESULT_REG,paraloc1);
+ paramanager.freecgpara(list,paraloc1);
+ cg.allocallcpuregisters(list);
+ cg.a_call_name(list,'FPC_SETJMP',false);
+ cg.deallocallcpuregisters(list);
+ cg.alloccpuregisters(list,R_INTREGISTER,[RS_FUNCTION_RESULT_REG]);
+
+ cg.g_exception_reason_save(list, t.reasonbuf);
+ cg.a_cmp_const_reg_label(list,OS_S32,OC_NE,0,cg.makeregsize(list,NR_FUNCTION_RESULT_REG,OS_S32),exceptlabel);
+ cg.dealloccpuregisters(list,R_INTREGISTER,[RS_FUNCTION_RESULT_REG]);
+ paraloc1.done;
+ paraloc2.done;
+ paraloc3.done;
+ end;
+
+
+ procedure free_exception(list:TAsmList;const t:texceptiontemps;a:aint;endexceptlabel:tasmlabel;onlyfree:boolean);
+ begin
+ cg.allocallcpuregisters(list);
+ cg.a_call_name(list,'FPC_POPADDRSTACK',false);
+ cg.deallocallcpuregisters(list);
+
+ if not onlyfree then
+ begin
+ { g_exception_reason_load already allocates NR_FUNCTION_RESULT_REG }
+ cg.g_exception_reason_load(list, t.reasonbuf);
+ cg.a_cmp_const_reg_label(list,OS_INT,OC_EQ,a,NR_FUNCTION_RESULT_REG,endexceptlabel);
+ cg.a_reg_dealloc(list,NR_FUNCTION_RESULT_REG);
+ end;
+ end;
+
+
+{*****************************************************************************
+ TLocation
+*****************************************************************************}
+
+{$ifndef cpu64bitalu}
+ { 32-bit version }
+ procedure location_force_reg(list:TAsmList;var l:tlocation;dst_size:TCGSize;maybeconst:boolean);
+ var
+ hregister,
+ hregisterhi : tregister;
+ hreg64 : tregister64;
+ hl : tasmlabel;
+ oldloc : tlocation;
+ const_location: boolean;
+ begin
+ oldloc:=l;
+ if dst_size=OS_NO then
+ internalerror(200309144);
+ { handle transformations to 64bit separate }
+ if dst_size in [OS_64,OS_S64] then
+ begin
+ if not (l.size in [OS_64,OS_S64]) then
+ begin
+ { load a smaller size to OS_64 }
+ if l.loc=LOC_REGISTER then
+ begin
+{$ifdef AVR}
+ { on avr, we cannot change the size of a register
+ due to the nature how register with size > OS8 are handled
+ }
+ hregister:=cg.getintregister(list,OS_32);
+{$else AVR}
+ hregister:=cg.makeregsize(list,l.register64.reglo,OS_32);
+{$endif AVR}
+ cg.a_load_reg_reg(list,l.size,OS_32,l.register64.reglo,hregister);
+ end
+ else
+ hregister:=cg.getintregister(list,OS_32);
+ { load value in low register }
+ case l.loc of
+{$ifdef cpuflags}
+ LOC_FLAGS :
+ cg.g_flags2reg(list,OS_INT,l.resflags,hregister);
+{$endif cpuflags}
+ LOC_JUMP :
+ begin
+ cg.a_label(list,current_procinfo.CurrTrueLabel);
+ cg.a_load_const_reg(list,OS_INT,1,hregister);
+ current_asmdata.getjumplabel(hl);
+ cg.a_jmp_always(list,hl);
+ cg.a_label(list,current_procinfo.CurrFalseLabel);
+ cg.a_load_const_reg(list,OS_INT,0,hregister);
+ cg.a_label(list,hl);
+ end;
+ else
+ cg.a_load_loc_reg(list,OS_INT,l,hregister);
+ end;
+ { reset hi part, take care of the signed bit of the current value }
+ hregisterhi:=cg.getintregister(list,OS_32);
+ if (l.size in [OS_S8,OS_S16,OS_S32]) then
+ begin
+ if l.loc=LOC_CONSTANT then
+ begin
+ if (longint(l.value)<0) then
+ cg.a_load_const_reg(list,OS_32,aint($ffffffff),hregisterhi)
+ else
+ cg.a_load_const_reg(list,OS_32,0,hregisterhi);
+ end
+ else
+ begin
+ cg.a_op_const_reg_reg(list,OP_SAR,OS_32,31,hregister,
+ hregisterhi);
+ end;
+ end
+ else
+ cg.a_load_const_reg(list,OS_32,0,hregisterhi);
+ location_reset(l,LOC_REGISTER,dst_size);
+ l.register64.reglo:=hregister;
+ l.register64.reghi:=hregisterhi;
+ end
+ else
+ begin
+ { 64bit to 64bit }
+ if ((l.loc=LOC_CREGISTER) and maybeconst) then
+ begin
+ hregister:=l.register64.reglo;
+ hregisterhi:=l.register64.reghi;
+ const_location := true;
+ end
+ else
+ begin
+ hregister:=cg.getintregister(list,OS_32);
+ hregisterhi:=cg.getintregister(list,OS_32);
+ const_location := false;
+ end;
+ hreg64.reglo:=hregister;
+ hreg64.reghi:=hregisterhi;
+ { load value in new register }
+ cg64.a_load64_loc_reg(list,l,hreg64);
+ if not const_location then
+ location_reset(l,LOC_REGISTER,dst_size)
+ else
+ location_reset(l,LOC_CREGISTER,dst_size);
+ l.register64.reglo:=hregister;
+ l.register64.reghi:=hregisterhi;
+ end;
+ end
+ else
+ begin
+ {Do not bother to recycle the existing register. The register
+ allocator eliminates unnecessary moves, so it's not needed
+ and trying to recycle registers can cause problems because
+ the registers changes size and may need aditional constraints.
+
+ Not if it's about LOC_CREGISTER's (JM)
+ }
+ const_location :=
+ (maybeconst) and
+ (l.loc = LOC_CREGISTER) and
+ (TCGSize2Size[l.size] = TCGSize2Size[dst_size]) and
+ ((l.size = dst_size) or
+ (TCGSize2Size[l.size] = sizeof(aint)));
+ if not const_location then
+ hregister:=cg.getintregister(list,dst_size)
+ else
+ hregister := l.register;
+ { load value in new register }
+ case l.loc of
+{$ifdef cpuflags}
+ LOC_FLAGS :
+ cg.g_flags2reg(list,dst_size,l.resflags,hregister);
+{$endif cpuflags}
+ LOC_JUMP :
+ begin
+ cg.a_label(list,current_procinfo.CurrTrueLabel);
+ cg.a_load_const_reg(list,dst_size,1,hregister);
+ current_asmdata.getjumplabel(hl);
+ cg.a_jmp_always(list,hl);
+ cg.a_label(list,current_procinfo.CurrFalseLabel);
+ cg.a_load_const_reg(list,dst_size,0,hregister);
+ cg.a_label(list,hl);
+ end;
+ else
+ begin
+ { load_loc_reg can only handle size >= l.size, when the
+ new size is smaller then we need to adjust the size
+ of the orignal and maybe recalculate l.register for i386 }
+ if (TCGSize2Size[dst_size]<TCGSize2Size[l.size]) then
+ begin
+ if (l.loc in [LOC_REGISTER,LOC_CREGISTER]) then
+ l.register:=cg.makeregsize(list,l.register,dst_size);
+ { for big endian systems, the reference's offset must }
+ { be increased in this case, since they have the }
+ { MSB first in memory and e.g. byte(word_var) should }
+ { return the second byte in this case (JM) }
+ if (target_info.endian = ENDIAN_BIG) and
+ (l.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
+ begin
+ inc(l.reference.offset,TCGSize2Size[l.size]-TCGSize2Size[dst_size]);
+ l.reference.alignment:=newalignment(l.reference.alignment,TCGSize2Size[l.size]-TCGSize2Size[dst_size]);
+ end;
+{$ifdef x86}
+ if not (l.loc in [LOC_SUBSETREG,LOC_CSUBSETREG]) then
+ l.size:=dst_size;
+{$endif x86}
+ end;
+ cg.a_load_loc_reg(list,dst_size,l,hregister);
+ if (TCGSize2Size[dst_size]<TCGSize2Size[l.size])
+{$ifdef x86}
+ and (l.loc in [LOC_SUBSETREG,LOC_CSUBSETREG])
+{$endif x86}
+ then
+ l.size:=dst_size;
+ end;
+ end;
+ if not const_location then
+ location_reset(l,LOC_REGISTER,dst_size)
+ else
+ location_reset(l,LOC_CREGISTER,dst_size);
+ l.register:=hregister;
+ end;
+ { Release temp when it was a reference }
+ if oldloc.loc=LOC_REFERENCE then
+ location_freetemp(list,oldloc);
+ end;
+
+{$else not cpu64bitalu}
+
+ { 64-bit version }
+ procedure location_force_reg(list:TAsmList;var l:tlocation;dst_size:TCGSize;maybeconst:boolean);
+ var
+ hregister : tregister;
+ hl : tasmlabel;
+ oldloc : tlocation;
+ begin
+ oldloc:=l;
+ hregister:=cg.getintregister(list,dst_size);
+ { load value in new register }
+ case l.loc of
+ LOC_FLAGS :
+ cg.g_flags2reg(list,dst_size,l.resflags,hregister);
+ LOC_JUMP :
+ begin
+ cg.a_label(list,current_procinfo.CurrTrueLabel);
+ cg.a_load_const_reg(list,dst_size,1,hregister);
+ current_asmdata.getjumplabel(hl);
+ cg.a_jmp_always(list,hl);
+ cg.a_label(list,current_procinfo.CurrFalseLabel);
+ cg.a_load_const_reg(list,dst_size,0,hregister);
+ cg.a_label(list,hl);
+ end;
+ else
+ begin
+ { load_loc_reg can only handle size >= l.size, when the
+ new size is smaller then we need to adjust the size
+ of the orignal and maybe recalculate l.register for i386 }
+ if (TCGSize2Size[dst_size]<TCGSize2Size[l.size]) then
+ begin
+ if (l.loc in [LOC_REGISTER,LOC_CREGISTER]) then
+ l.register:=cg.makeregsize(list,l.register,dst_size);
+ { for big endian systems, the reference's offset must }
+ { be increased in this case, since they have the }
+ { MSB first in memory and e.g. byte(word_var) should }
+ { return the second byte in this case (JM) }
+ if (target_info.endian = ENDIAN_BIG) and
+ (l.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
+ begin
+ inc(l.reference.offset,TCGSize2Size[l.size]-TCGSize2Size[dst_size]);
+ l.reference.alignment:=newalignment(l.reference.alignment,TCGSize2Size[l.size]-TCGSize2Size[dst_size]);
+ end;
+{$ifdef x86}
+ l.size:=dst_size;
+{$endif x86}
+ end;
+ cg.a_load_loc_reg(list,dst_size,l,hregister);
+{$ifndef x86}
+ if (TCGSize2Size[dst_size]<TCGSize2Size[l.size]) then
+ l.size:=dst_size;
+{$endif not x86}
+ end;
+ end;
+ if (l.loc <> LOC_CREGISTER) or
+ not maybeconst then
+ location_reset(l,LOC_REGISTER,dst_size)
+ else
+ location_reset(l,LOC_CREGISTER,dst_size);
+ l.register:=hregister;
+ { Release temp when it was a reference }
+ if oldloc.loc=LOC_REFERENCE then
+ location_freetemp(list,oldloc);
+ end;
+{$endif not cpu64bitalu}
+
+
+ procedure location_force_fpureg(list:TAsmList;var l: tlocation;maybeconst:boolean);
+ var
+ reg : tregister;
+ href : treference;
+ begin
+ if (l.loc<>LOC_FPUREGISTER) and
+ ((l.loc<>LOC_CFPUREGISTER) or (not maybeconst)) then
+ begin
+ { if it's in an mm register, store to memory first }
+ if (l.loc in [LOC_MMREGISTER,LOC_CMMREGISTER]) then
+ begin
+ tg.GetTemp(list,tcgsize2size[l.size],tcgsize2size[l.size],tt_normal,href);
+ cg.a_loadmm_reg_ref(list,l.size,l.size,l.register,href,mms_movescalar);
+ location_reset_ref(l,LOC_REFERENCE,l.size,0);
+ l.reference:=href;
+ end;
+ reg:=cg.getfpuregister(list,l.size);
+ cg.a_loadfpu_loc_reg(list,l.size,l,reg);
+ location_freetemp(list,l);
+ location_reset(l,LOC_FPUREGISTER,l.size);
+ l.register:=reg;
+ end;
+ end;
+
+
+ procedure location_force_mmregscalar(list:TAsmList;var l: tlocation;maybeconst:boolean);
+ var
+ reg : tregister;
+ href : treference;
+ newsize : tcgsize;
+ begin
+ if (l.loc<>LOC_MMREGISTER) and
+ ((l.loc<>LOC_CMMREGISTER) or (not maybeconst)) then
+ begin
+ { if it's in an fpu register, store to memory first }
+ if (l.loc in [LOC_FPUREGISTER,LOC_CFPUREGISTER]) then
+ begin
+ tg.GetTemp(list,tcgsize2size[l.size],tcgsize2size[l.size],tt_normal,href);
+ cg.a_loadfpu_reg_ref(list,l.size,l.size,l.register,href);
+ location_reset_ref(l,LOC_REFERENCE,l.size,0);
+ l.reference:=href;
+ end;
+{$ifndef cpu64bitalu}
+ if (l.loc in [LOC_REGISTER,LOC_CREGISTER]) and
+ (l.size in [OS_64,OS_S64]) then
+ begin
+ reg:=cg.getmmregister(list,OS_F64);
+ cg64.a_loadmm_intreg64_reg(list,OS_F64,l.register64,reg);
+ l.size:=OS_F64
+ end
+ else
+{$endif not cpu64bitalu}
+ begin
+ { on ARM, CFP values may be located in integer registers,
+ and its second_int_to_real() also uses this routine to
+ force integer (memory) values in an mmregister }
+ if (l.size in [OS_32,OS_S32]) then
+ newsize:=OS_F32
+ else if (l.size in [OS_64,OS_S64]) then
+ newsize:=OS_F64
+ else
+ newsize:=l.size;
+ reg:=cg.getmmregister(list,newsize);
+ cg.a_loadmm_loc_reg(list,newsize,l,reg,mms_movescalar);
+ l.size:=newsize;
+ end;
+ location_freetemp(list,l);
+ location_reset(l,LOC_MMREGISTER,l.size);
+ l.register:=reg;
+ end;
+ end;
+
+
+ procedure gen_loadfpu_loc_cgpara(list: TAsmList; const l: tlocation;const cgpara: tcgpara;locintsize: longint);
+ var
+{$ifdef i386}
+ href : treference;
+ size : longint;
+{$endif i386}
+ locsize : tcgsize;
+ tmploc : tlocation;
+ begin
+ if not(l.size in [OS_32,OS_S32,OS_64,OS_S64,OS_128,OS_S128]) then
+ locsize:=l.size
+ else
+ locsize:=int_float_cgsize(tcgsize2size[l.size]);
+{$ifdef i386}
+ case l.loc of
+ LOC_FPUREGISTER,
+ LOC_CFPUREGISTER:
+ begin
+ case cgpara.location^.loc of
+ LOC_REFERENCE:
+ begin
+ size:=align(locintsize,cgpara.alignment);
+ if (not paramanager.use_fixed_stack) and
+ (cgpara.location^.reference.index=NR_STACK_POINTER_REG) then
+ begin
+ cg.g_stackpointer_alloc(list,size);
+ reference_reset_base(href,NR_STACK_POINTER_REG,0,sizeof(pint));
+ end
+ else
+ reference_reset_base(href,cgpara.location^.reference.index,cgpara.location^.reference.offset,cgpara.alignment);
+ cg.a_loadfpu_reg_ref(list,locsize,locsize,l.register,href);
+ end;
+ LOC_FPUREGISTER:
+ begin
+ cg.a_loadfpu_reg_reg(list,locsize,cgpara.location^.size,l.register,cgpara.location^.register);
+ end;
+ { can happen if a record with only 1 "single field" is
+ returned in a floating point register and then is directly
+ passed to a regcall parameter }
+ LOC_REGISTER:
+ begin
+ tmploc:=l;
+ location_force_mem(list,tmploc);
+ case locsize of
+ OS_F32:
+ tmploc.size:=OS_32;
+ OS_F64:
+ tmploc.size:=OS_64;
+ else
+ internalerror(2010053116);
+ end;
+ cg.a_load_loc_cgpara(list,tmploc,cgpara);
+ location_freetemp(list,tmploc);
+ end
+ else
+ internalerror(2010053003);
+ end;
+ end;
+ LOC_MMREGISTER,
+ LOC_CMMREGISTER:
+ begin
+ case cgpara.location^.loc of
+ LOC_REFERENCE:
+ begin
+ { can't use TCGSize2Size[l.size], because the size of an
+ 80 bit extended parameter can be either 10 or 12 bytes }
+ size:=align(locintsize,cgpara.alignment);
+ if (not paramanager.use_fixed_stack) and
+ (cgpara.location^.reference.index=NR_STACK_POINTER_REG) then
+ begin
+ cg.g_stackpointer_alloc(list,size);
+ reference_reset_base(href,NR_STACK_POINTER_REG,0,sizeof(pint));
+ end
+ else
+ reference_reset_base(href,cgpara.location^.reference.index,cgpara.location^.reference.offset,cgpara.alignment);
+ cg.a_loadmm_reg_ref(list,locsize,locsize,l.register,href,mms_movescalar);
+ end;
+ LOC_FPUREGISTER:
+ begin
+ tmploc:=l;
+ location_force_mem(list,tmploc);
+ cg.a_loadfpu_ref_cgpara(list,tmploc.size,tmploc.reference,cgpara);
+ location_freetemp(list,tmploc);
+ end;
+ else
+ internalerror(2010053004);
+ end;
+ end;
+ LOC_REFERENCE,
+ LOC_CREFERENCE :
+ begin
+ case cgpara.location^.loc of
+ LOC_REFERENCE:
+ begin
+ size:=align(locintsize,cgpara.alignment);
+ if (not paramanager.use_fixed_stack) and
+ (cgpara.location^.reference.index=NR_STACK_POINTER_REG) then
+ cg.a_load_ref_cgpara(list,locsize,l.reference,cgpara)
+ else
+ begin
+ reference_reset_base(href,cgpara.location^.reference.index,cgpara.location^.reference.offset,cgpara.alignment);
+ cg.g_concatcopy(list,l.reference,href,size);
+ end;
+ end;
+ LOC_FPUREGISTER:
+ begin
+ cg.a_loadfpu_ref_cgpara(list,locsize,l.reference,cgpara);
+ end;
+ else
+ internalerror(2010053005);
+ end;
+ end;
+ else
+ internalerror(2002042430);
+ end;
+{$else i386}
+ case l.loc of
+ LOC_MMREGISTER,
+ LOC_CMMREGISTER:
+ case cgpara.location^.loc of
+ LOC_REFERENCE,
+ LOC_CREFERENCE,
+ LOC_MMREGISTER,
+ LOC_CMMREGISTER,
+ LOC_REGISTER,
+ LOC_CREGISTER :
+ cg.a_loadmm_reg_cgpara(list,locsize,l.register,cgpara,mms_movescalar);
+ LOC_FPUREGISTER,
+ LOC_CFPUREGISTER:
+ begin
+ tmploc:=l;
+ location_force_fpureg(list,tmploc,false);
+ cg.a_loadfpu_reg_cgpara(list,tmploc.size,tmploc.register,cgpara);
+ end;
+ else
+ internalerror(200204249);
+ end;
+ LOC_FPUREGISTER,
+ LOC_CFPUREGISTER:
+ case cgpara.location^.loc of
+ LOC_MMREGISTER,
+ LOC_CMMREGISTER:
+ begin
+ tmploc:=l;
+ location_force_mmregscalar(list,tmploc,false);
+ cg.a_loadmm_reg_cgpara(list,tmploc.size,tmploc.register,cgpara,mms_movescalar);
+ end;
+ { Some targets pass floats in normal registers }
+ LOC_REGISTER,
+ LOC_CREGISTER,
+ LOC_REFERENCE,
+ LOC_CREFERENCE,
+ LOC_FPUREGISTER,
+ LOC_CFPUREGISTER:
+ cg.a_loadfpu_reg_cgpara(list,locsize,l.register,cgpara);
+ else
+ internalerror(2002042433);
+ end;
+ LOC_REFERENCE,
+ LOC_CREFERENCE:
+ case cgpara.location^.loc of
+ LOC_MMREGISTER,
+ LOC_CMMREGISTER:
+ cg.a_loadmm_ref_cgpara(list,locsize,l.reference,cgpara,mms_movescalar);
+ { Some targets pass floats in normal registers }
+ LOC_REGISTER,
+ LOC_CREGISTER,
+ LOC_REFERENCE,
+ LOC_CREFERENCE,
+ LOC_FPUREGISTER,
+ LOC_CFPUREGISTER:
+ cg.a_loadfpu_ref_cgpara(list,locsize,l.reference,cgpara);
+ else
+ internalerror(2002042431);
+ end;
+ LOC_REGISTER,
+ LOC_CREGISTER :
+ begin
+{$ifndef cpu64bitalu}
+ { Only a_load_ref_cgpara supports multiple locations, when the
+ value is still a const or in a register then write it
+ to a reference first. This situation can be triggered
+ by typecasting an int64 constant to a record of 8 bytes }
+ if locsize = OS_F64 then
+ begin
+ tmploc:=l;
+ location_force_mem(list,tmploc);
+ cg.a_load_loc_cgpara(list,tmploc,cgpara);
+ location_freetemp(list,tmploc);
+ end
+ else
+{$endif not cpu64bitalu}
+ cg.a_load_loc_cgpara(list,l,cgpara);
+ end;
+ else
+ internalerror(2002042432);
+ end;
+{$endif i386}
+ end;
+
+
+ procedure gen_load_loc_cgpara(list: TAsmList; vardef: tdef; const l: tlocation; const cgpara: tcgpara);
+{$ifndef cpu64bitalu}
+ var
+ tmploc: tlocation;
+{$endif not cpu64bitalu}
+ begin
+ { Handle Floating point types differently
+
+ This doesn't depend on emulator settings, emulator settings should
+ be handled by cpupara }
+ if (vardef.typ=floatdef) or
+ { some ABIs return certain records in an fpu register }
+ (l.loc in [LOC_FPUREGISTER,LOC_CFPUREGISTER]) or
+ (assigned(cgpara.location) and
+ (cgpara.Location^.loc in [LOC_FPUREGISTER,LOC_CFPUREGISTER])) then
+ begin
+ gen_loadfpu_loc_cgpara(list,l,cgpara,vardef.size);
+ exit;
+ end;
+
+ case l.loc of
+ LOC_CONSTANT,
+ LOC_REGISTER,
+ LOC_CREGISTER,
+ LOC_REFERENCE,
+ LOC_CREFERENCE :
+ begin
+{$ifndef cpu64bitalu}
+ { use cg64 only for int64, not for 8 byte records }
+ if is_64bit(vardef) then
+ cg64.a_load64_loc_cgpara(list,l,cgpara)
+ else
+{$endif not cpu64bitalu}
+ begin
+{$ifndef cpu64bitalu}
+ { Only a_load_ref_cgpara supports multiple locations, when the
+ value is still a const or in a register then write it
+ to a reference first. This situation can be triggered
+ by typecasting an int64 constant to a record of 8 bytes }
+ if l.size in [OS_64,OS_S64] then
+ begin
+ tmploc:=l;
+ location_force_mem(list,tmploc);
+ cg.a_load_loc_cgpara(list,tmploc,cgpara);
+ { do not free the tmploc in case the original value was
+ already in memory, because the caller (ncgcal) will then
+ free it again later }
+ if not(l.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
+ location_freetemp(list,tmploc);
+ end
+ else
+{$endif not cpu64bitalu}
+ cg.a_load_loc_cgpara(list,l,cgpara);
+ end;
+ end;
+ LOC_MMREGISTER,
+ LOC_CMMREGISTER:
+ begin
+ case l.size of
+ OS_F32,
+ OS_F64:
+ cg.a_loadmm_loc_cgpara(list,l,cgpara,mms_movescalar);
+ else
+ cg.a_loadmm_loc_cgpara(list,l,cgpara,nil);
+ end;
+ end;
+{$ifdef SUPPORT_MMX}
+ LOC_MMXREGISTER,
+ LOC_CMMXREGISTER:
+ cg.a_loadmm_reg_cgpara(list,OS_M64,l.register,cgpara,nil);
+{$endif SUPPORT_MMX}
+ else
+ internalerror(200204241);
+ end;
+ end;
+
+
+ procedure register_maybe_adjust_setbase(list: TAsmList; var l: tlocation; setbase: aint);
+ var
+ tmpreg: tregister;
+ begin
+ if (setbase<>0) then
+ begin
+ if not(l.loc in [LOC_REGISTER,LOC_CREGISTER]) then
+ internalerror(2007091502);
+ { subtract the setbase }
+ case l.loc of
+ LOC_CREGISTER:
+ begin
+ tmpreg := cg.getintregister(list,l.size);
+ cg.a_op_const_reg_reg(list,OP_SUB,l.size,setbase,l.register,tmpreg);
+ l.loc:=LOC_REGISTER;
+ l.register:=tmpreg;
+ end;
+ LOC_REGISTER:
+ begin
+ cg.a_op_const_reg(list,OP_SUB,l.size,setbase,l.register);
+ end;
+ end;
+ end;
+ end;
+
+
+ procedure location_force_mmreg(list:TAsmList;var l: tlocation;maybeconst:boolean);
+ var
+ reg : tregister;
+ begin
+ if (l.loc<>LOC_MMREGISTER) and
+ ((l.loc<>LOC_CMMREGISTER) or (not maybeconst)) then
+ begin
+ reg:=cg.getmmregister(list,OS_VECTOR);
+ cg.a_loadmm_loc_reg(list,OS_VECTOR,l,reg,nil);
+ location_freetemp(list,l);
+ location_reset(l,LOC_MMREGISTER,OS_VECTOR);
+ l.register:=reg;
+ end;
+ end;
+
+
+ procedure location_allocate_register(list: TAsmList;out l: tlocation;def: tdef;constant: boolean);
+ begin
+ l.size:=def_cgsize(def);
+ if (def.typ=floatdef) and
+ not(cs_fp_emulation in current_settings.moduleswitches) then
+ begin
+ if use_vectorfpu(def) then
+ begin
+ if constant then
+ location_reset(l,LOC_CMMREGISTER,l.size)
+ else
+ location_reset(l,LOC_MMREGISTER,l.size);
+ l.register:=cg.getmmregister(list,l.size);
+ end
+ else
+ begin
+ if constant then
+ location_reset(l,LOC_CFPUREGISTER,l.size)
+ else
+ location_reset(l,LOC_FPUREGISTER,l.size);
+ l.register:=cg.getfpuregister(list,l.size);
+ end;
+ end
+ else
+ begin
+ if constant then
+ location_reset(l,LOC_CREGISTER,l.size)
+ else
+ location_reset(l,LOC_REGISTER,l.size);
+{$ifndef cpu64bitalu}
+ if l.size in [OS_64,OS_S64,OS_F64] then
+ begin
+ l.register64.reglo:=cg.getintregister(list,OS_32);
+ l.register64.reghi:=cg.getintregister(list,OS_32);
+ end
+ else
+{$endif not cpu64bitalu}
+ l.register:=cg.getintregister(list,l.size);
+ end;
+ end;
+
+
+ procedure location_force_mem(list:TAsmList;var l:tlocation);
+ var
+ r : treference;
+ begin
+ case l.loc of
+ LOC_FPUREGISTER,
+ LOC_CFPUREGISTER :
+ begin
+ tg.GetTemp(list,TCGSize2Size[l.size],TCGSize2Size[l.size],tt_normal,r);
+ cg.a_loadfpu_reg_ref(list,l.size,l.size,l.register,r);
+ location_reset_ref(l,LOC_REFERENCE,l.size,0);
+ l.reference:=r;
+ end;
+ LOC_MMREGISTER,
+ LOC_CMMREGISTER:
+ begin
+ tg.GetTemp(list,TCGSize2Size[l.size],TCGSize2Size[l.size],tt_normal,r);
+ cg.a_loadmm_reg_ref(list,l.size,l.size,l.register,r,mms_movescalar);
+ location_reset_ref(l,LOC_REFERENCE,l.size,0);
+ l.reference:=r;
+ end;
+ LOC_CONSTANT,
+ LOC_REGISTER,
+ LOC_CREGISTER :
+ begin
+ tg.GetTemp(list,TCGSize2Size[l.size],TCGSize2Size[l.size],tt_normal,r);
+{$ifndef cpu64bitalu}
+ if l.size in [OS_64,OS_S64] then
+ cg64.a_load64_loc_ref(list,l,r)
+ else
+{$endif not cpu64bitalu}
+ cg.a_load_loc_ref(list,l.size,l,r);
+ location_reset_ref(l,LOC_REFERENCE,l.size,0);
+ l.reference:=r;
+ end;
+ LOC_SUBSETREG,
+ LOC_CSUBSETREG,
+ LOC_SUBSETREF,
+ LOC_CSUBSETREF:
+ begin
+ tg.GetTemp(list,TCGSize2Size[l.size],TCGSize2Size[l.size],tt_normal,r);
+ cg.a_load_loc_ref(list,l.size,l,r);
+ location_reset_ref(l,LOC_REFERENCE,l.size,0);
+ l.reference:=r;
+ end;
+ LOC_CREFERENCE,
+ LOC_REFERENCE : ;
+ else
+ internalerror(200203219);
+ end;
+ end;
+
+
+ procedure location_get_data_ref(list:TAsmList;const l:tlocation;var ref:treference;loadref:boolean; alignment: longint);
+ begin
+ case l.loc of
+ LOC_REGISTER,
+ LOC_CREGISTER :
+ begin
+ if not loadref then
+ internalerror(200410231);
+ reference_reset_base(ref,l.register,0,alignment);
+ end;
+ LOC_REFERENCE,
+ LOC_CREFERENCE :
+ begin
+ if loadref then
+ begin
+ reference_reset_base(ref,cg.getaddressregister(list),0,alignment);
+ cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,l.reference,ref.base);
+ end
+ else
+ ref:=l.reference;
+ end;
+ else
+ internalerror(200309181);
+ end;
+ end;
+
+
+{****************************************************************************
+ Init/Finalize Code
+****************************************************************************}
+
+ procedure copyvalueparas(p:TObject;arg:pointer);
+ var
+ href : treference;
+ hreg : tregister;
+ list : TAsmList;
+ hsym : tparavarsym;
+ l : longint;
+ localcopyloc : tlocation;
+ begin
+ list:=TAsmList(arg);
+ if (tsym(p).typ=paravarsym) and
+ (tparavarsym(p).varspez=vs_value) and
+ (paramanager.push_addr_param(tparavarsym(p).varspez,tparavarsym(p).vardef,current_procinfo.procdef.proccalloption)) then
+ begin
+ { we have no idea about the alignment at the caller side }
+ location_get_data_ref(list,tparavarsym(p).initialloc,href,true,1);
+ if is_open_array(tparavarsym(p).vardef) or
+ is_array_of_const(tparavarsym(p).vardef) then
+ begin
+ { cdecl functions don't have a high pointer so it is not possible to generate
+ a local copy }
+ if not(current_procinfo.procdef.proccalloption in cdecl_pocalls) then
+ begin
+ hsym:=tparavarsym(get_high_value_sym(tparavarsym(p)));
+ if not assigned(hsym) then
+ internalerror(200306061);
+ hreg:=cg.getaddressregister(list);
+ if not is_packed_array(tparavarsym(p).vardef) then
+ cg.g_copyvaluepara_openarray(list,href,hsym.initialloc,tarraydef(tparavarsym(p).vardef).elesize,hreg)
+ else
+ internalerror(2006080401);
+// cg.g_copyvaluepara_packedopenarray(list,href,hsym.intialloc,tarraydef(tparavarsym(p).vardef).elepackedbitsize,hreg);
+ cg.a_load_reg_loc(list,OS_ADDR,hreg,tparavarsym(p).initialloc);
+ end;
+ end
+ else
+ begin
+ { Allocate space for the local copy }
+ l:=tparavarsym(p).getsize;
+ localcopyloc.loc:=LOC_REFERENCE;
+ localcopyloc.size:=int_cgsize(l);
+ tg.GetLocal(list,l,tparavarsym(p).vardef,localcopyloc.reference);
+ { Copy data }
+ if is_shortstring(tparavarsym(p).vardef) then
+ begin
+ { this code is only executed before the code for the body and the entry/exit code is generated
+ so we're allowed to include pi_do_call here; after pass1 is run, this isn't allowed anymore
+ }
+ include(current_procinfo.flags,pi_do_call);
+ cg.g_copyshortstring(list,href,localcopyloc.reference,tstringdef(tparavarsym(p).vardef).len)
+ end
+ else if tparavarsym(p).vardef.typ = variantdef then
+ begin
+ { this code is only executed before the code for the body and the entry/exit code is generated
+ so we're allowed to include pi_do_call here; after pass1 is run, this isn't allowed anymore
+ }
+ include(current_procinfo.flags,pi_do_call);
+ cg.g_copyvariant(list,href,localcopyloc.reference)
+ end
+ else
+ begin
+ { pass proper alignment info }
+ localcopyloc.reference.alignment:=tparavarsym(p).vardef.alignment;
+ cg.g_concatcopy(list,href,localcopyloc.reference,tparavarsym(p).vardef.size);
+ end;
+ { update localloc of varsym }
+ tg.Ungetlocal(list,tparavarsym(p).localloc.reference);
+ tparavarsym(p).localloc:=localcopyloc;
+ tparavarsym(p).initialloc:=localcopyloc;
+ end;
+ end;
+ end;
+
+
+ const
+{$ifdef cpu64bitalu}
+ trashintvalues: array[0..nroftrashvalues-1] of aint = ($5555555555555555,aint($AAAAAAAAAAAAAAAA),aint($EFEFEFEFEFEFEFEF),0);
+{$endif cpu64bitalu}
+{$ifdef cpu32bitalu}
+ trashintvalues: array[0..nroftrashvalues-1] of aint = ($55555555,aint($AAAAAAAA),aint($EFEFEFEF),0);
+{$endif cpu32bitalu}
+{$ifdef cpu8bitalu}
+ trashintvalues: array[0..nroftrashvalues-1] of aint = ($55,aint($AA),aint($EF),0);
+{$endif cpu8bitalu}
+
+ procedure trash_reference(list: TAsmList; const ref: treference; size: aint);
+ var
+ countreg, valuereg: tregister;
+ hl: tasmlabel;
+ trashintval: aint;
+ tmpref: treference;
+ begin
+ trashintval := trashintvalues[localvartrashing];
+ case size of
+ 0: ; { empty record }
+ 1: cg.a_load_const_ref(list,OS_8,byte(trashintval),ref);
+ 2: cg.a_load_const_ref(list,OS_16,word(trashintval),ref);
+ 4: cg.a_load_const_ref(list,OS_32,longint(trashintval),ref);
+ {$ifdef cpu64bitalu}
+ 8: cg.a_load_const_ref(list,OS_64,int64(trashintval),ref);
+ {$endif cpu64bitalu}
+ else
+ begin
+ countreg := cg.getintregister(list,OS_ADDR);
+ valuereg := cg.getintregister(list,OS_8);
+ cg.a_load_const_reg(list,OS_INT,size,countreg);
+ cg.a_load_const_reg(list,OS_8,byte(trashintval),valuereg);
+ current_asmdata.getjumplabel(hl);
+ tmpref := ref;
+ if (tmpref.index <> NR_NO) then
+ internalerror(200607201);
+ tmpref.index := countreg;
+ dec(tmpref.offset);
+ cg.a_label(list,hl);
+ cg.a_load_reg_ref(list,OS_8,OS_8,valuereg,tmpref);
+ cg.a_op_const_reg(list,OP_SUB,OS_INT,1,countreg);
+ cg.a_cmp_const_reg_label(list,OS_INT,OC_NE,0,countreg,hl);
+ cg.a_reg_sync(list,tmpref.base);
+ cg.a_reg_sync(list,valuereg);
+ end;
+ end;
+ end;
+
+
+ { trash contents of local variables or parameters (function result) }
+ procedure trash_variable(p:TObject;arg:pointer);
+ var
+ trashintval: aint;
+ list: TAsmList absolute arg;
+ begin
+ if ((tsym(p).typ=localvarsym) or
+ ((tsym(p).typ=paravarsym) and
+ (vo_is_funcret in tparavarsym(p).varoptions))) and
+ not(is_managed_type(tabstractnormalvarsym(p).vardef)) and
+ not(assigned(tabstractnormalvarsym(p).defaultconstsym)) then
+ begin
+ trashintval := trashintvalues[localvartrashing];
+ case tabstractnormalvarsym(p).initialloc.loc of
+ LOC_CREGISTER :
+{$push}
+{$q-}
+ begin
+ { avoid problems with broken x86 shifts }
+ case tcgsize2size[tabstractnormalvarsym(p).initialloc.size] of
+ 1: cg.a_load_const_reg(list,OS_8,byte(trashintval),tabstractnormalvarsym(p).initialloc.register);
+ 2: cg.a_load_const_reg(list,OS_16,word(trashintval),tabstractnormalvarsym(p).initialloc.register);
+ 4: cg.a_load_const_reg(list,OS_32,longint(trashintval),tabstractnormalvarsym(p).initialloc.register);
+ 8:
+ begin
+{$ifdef cpu64bitalu}
+ cg.a_load_const_reg(list,OS_64,aint(trashintval),tabstractnormalvarsym(p).initialloc.register);
+{$else}
+ cg64.a_load64_const_reg(list,int64(trashintval) shl 32 or int64(trashintval),tabstractnormalvarsym(p).initialloc.register64);
+{$endif}
+ end;
+ else
+ internalerror(2010060801);
+ end;
+ end;
+{$pop}
+ LOC_REFERENCE :
+ begin
+ if ((tsym(p).typ=localvarsym) and
+ not(vo_is_funcret in tabstractvarsym(p).varoptions)) or
+ not is_shortstring(tabstractnormalvarsym(p).vardef) then
+ trash_reference(list,tabstractnormalvarsym(p).initialloc.reference,
+ tlocalvarsym(p).getsize)
+ else
+ { may be an open string, even if is_open_string() returns }
+ { false (for some helpers in the system unit) }
+ { an open string has at least size 2 }
+ trash_reference(list,tabstractnormalvarsym(p).initialloc.reference,
+ 2);
+ end;
+ LOC_CMMREGISTER :
+ ;
+ LOC_CFPUREGISTER :
+ ;
+ else
+ internalerror(200410124);
+ end;
+ end;
+ end;
+
+
+ { initializes the regvars from staticsymtable with 0 }
+ procedure initialize_regvars(p:TObject;arg:pointer);
+ var
+ href : treference;
+ begin
+ if (tsym(p).typ=staticvarsym) then
+ begin
+ { Static variables can have the initialloc only set to LOC_CxREGISTER
+ or LOC_INVALID, for explaination see gen_alloc_symtable (PFV) }
+ case tstaticvarsym(p).initialloc.loc of
+ LOC_CREGISTER :
+ begin
+{$ifndef cpu64bitalu}
+ if (tstaticvarsym(p).initialloc.size in [OS_64,OS_S64]) then
+ cg64.a_load64_const_reg(TAsmList(arg),0,tstaticvarsym(p).initialloc.register64)
+ else
+{$endif not cpu64bitalu}
+ cg.a_load_const_reg(TAsmList(arg),reg_cgsize(tstaticvarsym(p).initialloc.register),0,
+ tstaticvarsym(p).initialloc.register);
+ end;
+ LOC_CMMREGISTER :
+ { clear the whole register }
+ cg.a_opmm_reg_reg(TAsmList(arg),OP_XOR,reg_cgsize(tstaticvarsym(p).initialloc.register),
+ tstaticvarsym(p).initialloc.register,
+ tstaticvarsym(p).initialloc.register,
+ nil);
+ LOC_CFPUREGISTER :
+ begin
+ { initialize fpu regvar by loading from memory }
+ reference_reset_symbol(href,
+ current_asmdata.RefAsmSymbol(tstaticvarsym(p).mangledname), 0,
+ var_align(tstaticvarsym(p).vardef.alignment));
+ cg.a_loadfpu_ref_reg(TAsmList(arg), tstaticvarsym(p).initialloc.size,
+ tstaticvarsym(p).initialloc.size, href, tstaticvarsym(p).initialloc.register);
+ end;
+ LOC_INVALID :
+ ;
+ else
+ internalerror(200410124);
+ end;
+ end;
+ end;
+
+
+ { generates the code for initialisation of local data }
+ procedure initialize_data(p:TObject;arg:pointer);
+ var
+ OldAsmList : TAsmList;
+ hp : tnode;
+ begin
+ if (tsym(p).typ = localvarsym) and
+ { local (procedure or unit) variables only need initialization if
+ they are used }
+ ((tabstractvarsym(p).refs>0) or
+ { managed return symbols must be inited }
+ ((tsym(p).typ=localvarsym) and (vo_is_funcret in tlocalvarsym(p).varoptions))
+ ) and
+ not(vo_is_typed_const in tabstractvarsym(p).varoptions) and
+ not(vo_is_external in tabstractvarsym(p).varoptions) and
+ (is_managed_type(tabstractvarsym(p).vardef) or
+ ((m_iso in current_settings.modeswitches) and (tabstractvarsym(p).vardef.typ=filedef))
+ ) then
+ begin
+ OldAsmList:=current_asmdata.CurrAsmList;
+ current_asmdata.CurrAsmList:=TAsmList(arg);
+ hp:=initialize_data_node(cloadnode.create(tsym(p),tsym(p).owner));
+ firstpass(hp);
+ secondpass(hp);
+ hp.free;
+ current_asmdata.CurrAsmList:=OldAsmList;
+ end;
+ end;
+
+
+ procedure finalize_sym(asmlist:TAsmList;sym:tsym);
+ var
+ hp : tnode;
+ OldAsmList : TAsmList;
+ begin
+ include(current_procinfo.flags,pi_needs_implicit_finally);
+ OldAsmList:=current_asmdata.CurrAsmList;
+ current_asmdata.CurrAsmList:=asmlist;
+ hp:=cloadnode.create(sym,sym.owner);
+ if (sym.typ=staticvarsym) and (vo_force_finalize in tstaticvarsym(sym).varoptions) then
+ include(tloadnode(hp).loadnodeflags,loadnf_isinternal_ignoreconst);
+ hp:=finalize_data_node(hp);
+ firstpass(hp);
+ secondpass(hp);
+ hp.free;
+ current_asmdata.CurrAsmList:=OldAsmList;
+ end;
+
+
+ { generates the code for finalisation of local variables }
+ procedure finalize_local_vars(p:TObject;arg:pointer);
+ begin
+ if (tsym(p).typ=localvarsym) and
+ (tlocalvarsym(p).refs>0) and
+ not(vo_is_external in tlocalvarsym(p).varoptions) and
+ not(vo_is_funcret in tlocalvarsym(p).varoptions) and
+ is_managed_type(tlocalvarsym(p).vardef) then
+ finalize_sym(TAsmList(arg),tsym(p));
+ end;
+
+
+ { generates the code for finalization of static symtable and
+ all local (static) typed consts }
+ procedure finalize_static_data(p:TObject;arg:pointer);
+ var
+ i : longint;
+ pd : tprocdef;
+ begin
+ case tsym(p).typ of
+ staticvarsym :
+ begin
+ { local (procedure or unit) variables only need finalization
+ if they are used
+ }
+ if ((tstaticvarsym(p).refs>0) or
+ { global (unit) variables always need finalization, since
+ they may also be used in another unit
+ }
+ (tstaticvarsym(p).owner.symtabletype=globalsymtable)) and
+ (
+ (tstaticvarsym(p).varspez<>vs_const) or
+ (vo_force_finalize in tstaticvarsym(p).varoptions)
+ ) and
+ not(vo_is_funcret in tstaticvarsym(p).varoptions) and
+ not(vo_is_external in tstaticvarsym(p).varoptions) and
+ is_managed_type(tstaticvarsym(p).vardef) then
+ finalize_sym(TAsmList(arg),tsym(p));
+ end;
+ procsym :
+ begin
+ for i:=0 to tprocsym(p).ProcdefList.Count-1 do
+ begin
+ pd:=tprocdef(tprocsym(p).ProcdefList[i]);
+ if assigned(pd.localst) and
+ (pd.procsym=tprocsym(p)) and
+ (pd.localst.symtabletype<>staticsymtable) then
+ pd.localst.SymList.ForEachCall(@finalize_static_data,arg);
+ end;
+ end;
+ end;
+ end;
+
+
+ { generates the code for incrementing the reference count of parameters and
+ initialize out parameters }
+ procedure init_paras(p:TObject;arg:pointer);
+ var
+ href : treference;
+ hsym : tparavarsym;
+ eldef : tdef;
+ tmpreg : tregister;
+ list : TAsmList;
+ needs_inittable,
+ do_trashing : boolean;
+ begin
+ list:=TAsmList(arg);
+ if (tsym(p).typ=paravarsym) then
+ begin
+ needs_inittable:=is_managed_type(tparavarsym(p).vardef);
+ do_trashing:=
+ (localvartrashing <> -1) and
+ (not assigned(tparavarsym(p).defaultconstsym)) and
+ not needs_inittable;
+ case tparavarsym(p).varspez of
+ vs_value :
+ if needs_inittable then
+ begin
+ { variants are already handled by the call to fpc_variant_copy_overwrite if
+ they are passed by reference }
+ if not((tparavarsym(p).vardef.typ=variantdef) and
+ paramanager.push_addr_param(tparavarsym(p).varspez,tparavarsym(p).vardef,current_procinfo.procdef.proccalloption)) then
+ begin
+ location_get_data_ref(list,tparavarsym(p).initialloc,href,is_open_array(tparavarsym(p).vardef),sizeof(pint));
+ if is_open_array(tparavarsym(p).vardef) then
+ begin
+ { open arrays do not contain correct element count in their rtti,
+ the actual count must be passed separately. }
+ hsym:=tparavarsym(get_high_value_sym(tparavarsym(p)));
+ eldef:=tarraydef(tparavarsym(p).vardef).elementdef;
+ if not assigned(hsym) then
+ internalerror(201003031);
+ cg.g_array_rtti_helper(list,eldef,href,hsym.initialloc,'FPC_ADDREF_ARRAY');
+ end
+ else
+ cg.g_incrrefcount(list,tparavarsym(p).vardef,href);
+ end;
+ end;
+ vs_out :
+ begin
+ if needs_inittable or
+ do_trashing then
+ begin
+ tmpreg:=cg.getaddressregister(list);
+ cg.a_load_loc_reg(list,OS_ADDR,tparavarsym(p).initialloc,tmpreg);
+ { we have no idea about the alignment at the callee side,
+ and the user also cannot specify "unaligned" here, so
+ assume worst case }
+ reference_reset_base(href,tmpreg,0,1);
+ if do_trashing and
+ { needs separate implementation to trash open arrays }
+ { since their size is only known at run time }
+ not is_special_array(tparavarsym(p).vardef) then
+ { may be an open string, even if is_open_string() returns }
+ { false (for some helpers in the system unit) }
+ if not is_shortstring(tparavarsym(p).vardef) then
+ trash_reference(list,href,tparavarsym(p).vardef.size)
+ else
+ trash_reference(list,href,2);
+ if needs_inittable then
+ begin
+ if is_open_array(tparavarsym(p).vardef) then
+ begin
+ hsym:=tparavarsym(get_high_value_sym(tparavarsym(p)));
+ eldef:=tarraydef(tparavarsym(p).vardef).elementdef;
+ if not assigned(hsym) then
+ internalerror(201103033);
+ cg.g_array_rtti_helper(list,eldef,href,hsym.initialloc,'FPC_INITIALIZE_ARRAY');
+ end
+ else
+ cg.g_initialize(list,tparavarsym(p).vardef,href);
+ end;
+ end;
+ end;
+ else if do_trashing and
+ ([vo_is_funcret,vo_is_hidden_para] * tparavarsym(p).varoptions = [vo_is_funcret,vo_is_hidden_para]) then
+ begin
+ tmpreg:=cg.getaddressregister(list);
+ cg.a_load_loc_reg(list,OS_ADDR,tparavarsym(p).initialloc,tmpreg);
+ { should always have standard alignment. If a function is assigned
+ to a non-aligned variable, the optimisation to pass this variable
+ directly as hidden function result must/cannot be performed
+ (see tcallnode.funcret_can_be_reused)
+ }
+ reference_reset_base(href,tmpreg,0,
+ used_align(tparavarsym(p).vardef.alignment,current_settings.alignment.localalignmin,current_settings.alignment.localalignmax));
+ { may be an open string, even if is_open_string() returns }
+ { false (for some helpers in the system unit) }
+ if not is_shortstring(tparavarsym(p).vardef) then
+ trash_reference(list,href,tparavarsym(p).vardef.size)
+ else
+ { an open string has at least size 2 }
+ trash_reference(list,href,2);
+ end
+ end;
+ end;
+ end;
+
+
+ { generates the code for decrementing the reference count of parameters }
+ procedure final_paras(p:TObject;arg:pointer);
+ var
+ list : TAsmList;
+ href : treference;
+ hsym : tparavarsym;
+ eldef : tdef;
+ begin
+ if not(tsym(p).typ=paravarsym) then
+ exit;
+ list:=TAsmList(arg);
+ if is_managed_type(tparavarsym(p).vardef) then
+ begin
+ if (tparavarsym(p).varspez=vs_value) then
+ begin
+ include(current_procinfo.flags,pi_needs_implicit_finally);
+ location_get_data_ref(list,tparavarsym(p).localloc,href,is_open_array(tparavarsym(p).vardef),sizeof(pint));
+ if is_open_array(tparavarsym(p).vardef) then
+ begin
+ hsym:=tparavarsym(get_high_value_sym(tparavarsym(p)));
+ eldef:=tarraydef(tparavarsym(p).vardef).elementdef;
+ if not assigned(hsym) then
+ internalerror(201003032);
+ cg.g_array_rtti_helper(list,eldef,href,hsym.initialloc,'FPC_FINALIZE_ARRAY');
+ end
+ else
+ cg.g_finalize(list,tparavarsym(p).vardef,href);
+ end;
+ end;
+ { open arrays can contain elements requiring init/final code, so the else has been removed here }
+ if (tparavarsym(p).varspez=vs_value) and
+ (is_open_array(tparavarsym(p).vardef) or
+ is_array_of_const(tparavarsym(p).vardef)) then
+ begin
+ { cdecl functions don't have a high pointer so it is not possible to generate
+ a local copy }
+ if not(current_procinfo.procdef.proccalloption in cdecl_pocalls) then
+ cg.g_releasevaluepara_openarray(list,tparavarsym(p).localloc);
+ end;
+ end;
+
+
+ { Initialize temp ansi/widestrings,interfaces }
+ procedure inittempvariables(list:TAsmList);
+ var
+ hp : ptemprecord;
+ href : treference;
+ begin
+ hp:=tg.templist;
+ while assigned(hp) do
+ begin
+ if assigned(hp^.def) and
+ is_managed_type(hp^.def) then
+ begin
+ reference_reset_base(href,current_procinfo.framepointer,hp^.pos,sizeof(pint));
+ cg.g_initialize(list,hp^.def,href);
+ end;
+ hp:=hp^.next;
+ end;
+ end;
+
+
+ procedure finalizetempvariables(list:TAsmList);
+ var
+ hp : ptemprecord;
+ href : treference;
+ begin
+ hp:=tg.templist;
+ while assigned(hp) do
+ begin
+ if assigned(hp^.def) and
+ is_managed_type(hp^.def) then
+ begin
+ include(current_procinfo.flags,pi_needs_implicit_finally);
+ reference_reset_base(href,current_procinfo.framepointer,hp^.pos,sizeof(pint));
+ cg.g_finalize(list,hp^.def,href);
+ end;
+ hp:=hp^.next;
+ end;
+ end;
+
+
+ procedure gen_load_return_value(list:TAsmList);
+ var
+ ressym : tabstractnormalvarsym;
+ funcretloc : TCGPara;
+ begin
+ { Is the loading needed? }
+ if is_void(current_procinfo.procdef.returndef) or
+ (
+ (po_assembler in current_procinfo.procdef.procoptions) and
+ (not(assigned(current_procinfo.procdef.funcretsym)) or
+ (tabstractvarsym(current_procinfo.procdef.funcretsym).refs=0))
+ ) then
+ exit;
+
+ funcretloc:=current_procinfo.procdef.funcretloc[calleeside];
+
+ { constructors return self }
+ if (current_procinfo.procdef.proctypeoption=potype_constructor) then
+ ressym:=tabstractnormalvarsym(current_procinfo.procdef.parast.Find('self'))
+ else
+ ressym:=tabstractnormalvarsym(current_procinfo.procdef.funcretsym);
+ if (ressym.refs>0) or
+ is_managed_type(ressym.vardef) then
+ begin
+ { was: don't do anything if funcretloc.loc in [LOC_INVALID,LOC_REFERENCE] }
+ if not paramanager.ret_in_param(current_procinfo.procdef.returndef,current_procinfo.procdef.proccalloption) then
+ gen_load_loc_cgpara(list,ressym.vardef,ressym.localloc,funcretloc);
+ end
+{$ifdef x86}
+ else
+ begin
+ { the caller will pop a value from the fpu stack }
+ if assigned(funcretloc.location) and
+ (funcretloc.location^.loc = LOC_FPUREGISTER) then
+ list.concat(taicpu.op_none(A_FLDZ));
+ end;
+{$endif x86}
+ end;
+
+
+ procedure gen_alloc_regloc(list:TAsmList;var loc: tlocation);
+ begin
+ case loc.loc of
+ LOC_CREGISTER:
+ begin
+{$ifndef cpu64bitalu}
+ if loc.size in [OS_64,OS_S64] then
+ begin
+ loc.register64.reglo:=cg.getintregister(list,OS_32);
+ loc.register64.reghi:=cg.getintregister(list,OS_32);
+ end
+ else
+{$endif cpu64bitalu}
+ loc.register:=cg.getintregister(list,loc.size);
+ end;
+ LOC_CFPUREGISTER:
+ begin
+ loc.register:=cg.getfpuregister(list,loc.size);
+ end;
+ LOC_CMMREGISTER:
+ begin
+ loc.register:=cg.getmmregister(list,loc.size);
+ end;
+ end;
+ end;
+
+
+ procedure gen_alloc_regvar(list:TAsmList;sym: tabstractnormalvarsym; allocreg: boolean);
+ begin
+ if allocreg then
+ gen_alloc_regloc(list,sym.initialloc);
+ if (pi_has_label in current_procinfo.flags) then
+ begin
+ { Allocate register already, to prevent first allocation to be
+ inside a loop }
+{$ifndef cpu64bitalu}
+ if sym.initialloc.size in [OS_64,OS_S64] then
+ begin
+ cg.a_reg_sync(list,sym.initialloc.register64.reglo);
+ cg.a_reg_sync(list,sym.initialloc.register64.reghi);
+ end
+ else
+{$endif not cpu64bitalu}
+ cg.a_reg_sync(list,sym.initialloc.register);
+ end;
+ sym.localloc:=sym.initialloc;
+ end;
+
+
+ procedure gen_load_cgpara_loc(list: TAsmList; vardef: tdef; const para: TCGPara; var destloc: tlocation; reusepara: boolean);
+
+ procedure unget_para(const paraloc:TCGParaLocation);
+ begin
+ case paraloc.loc of
+ LOC_REGISTER :
+ begin
+ if getsupreg(paraloc.register)<first_int_imreg then
+ cg.ungetcpuregister(list,paraloc.register);
+ end;
+ LOC_MMREGISTER :
+ begin
+ if getsupreg(paraloc.register)<first_mm_imreg then
+ cg.ungetcpuregister(list,paraloc.register);
+ end;
+ LOC_FPUREGISTER :
+ begin
+ if getsupreg(paraloc.register)<first_fpu_imreg then
+ cg.ungetcpuregister(list,paraloc.register);
+ end;
+ end;
+ end;
+
+ var
+ paraloc : pcgparalocation;
+ href : treference;
+ sizeleft : aint;
+{$if defined(sparc) or defined(arm)}
+ tempref : treference;
+{$endif sparc}
+{$ifndef cpu64bitalu}
+ reg64: tregister64;
+{$endif not cpu64bitalu}
+ begin
+ paraloc:=para.location;
+ if not assigned(paraloc) then
+ internalerror(200408203);
+ { skip e.g. empty records }
+ if (paraloc^.loc = LOC_VOID) then
+ exit;
+ case destloc.loc of
+ LOC_REFERENCE :
+ begin
+ { If the parameter location is reused we don't need to copy
+ anything }
+ if not reusepara then
+ begin
+ href:=destloc.reference;
+ sizeleft:=para.intsize;
+ while assigned(paraloc) do
+ begin
+ if (paraloc^.size=OS_NO) then
+ begin
+ { Can only be a reference that contains the rest
+ of the parameter }
+ if (paraloc^.loc<>LOC_REFERENCE) or
+ assigned(paraloc^.next) then
+ internalerror(2005013010);
+ cg.a_load_cgparaloc_ref(list,paraloc^,href,sizeleft,destloc.reference.alignment);
+ inc(href.offset,sizeleft);
+ sizeleft:=0;
+ end
+ else
+ begin
+ cg.a_load_cgparaloc_ref(list,paraloc^,href,tcgsize2size[paraloc^.size],destloc.reference.alignment);
+ inc(href.offset,TCGSize2Size[paraloc^.size]);
+ dec(sizeleft,TCGSize2Size[paraloc^.size]);
+ end;
+ unget_para(paraloc^);
+ paraloc:=paraloc^.next;
+ end;
+ end;
+ end;
+ LOC_REGISTER,
+ LOC_CREGISTER :
+ begin
+{$ifndef cpu64bitalu}
+ if (para.size in [OS_64,OS_S64,OS_F64]) and
+ (is_64bit(vardef) or
+ { in case of fpu emulation, or abi's that pass fpu values
+ via integer registers }
+ (vardef.typ=floatdef)) then
+ begin
+ case paraloc^.loc of
+ LOC_REGISTER:
+ begin
+ if not assigned(paraloc^.next) then
+ internalerror(200410104);
+ if (target_info.endian=ENDIAN_BIG) then
+ begin
+ { paraloc^ -> high
+ paraloc^.next -> low }
+ unget_para(paraloc^);
+ gen_alloc_regloc(list,destloc);
+ { reg->reg, alignment is irrelevant }
+ cg.a_load_cgparaloc_anyreg(list,OS_32,paraloc^,destloc.register64.reghi,4);
+ unget_para(paraloc^.next^);
+ cg.a_load_cgparaloc_anyreg(list,OS_32,paraloc^.next^,destloc.register64.reglo,4);
+ end
+ else
+ begin
+ { paraloc^ -> low
+ paraloc^.next -> high }
+ unget_para(paraloc^);
+ gen_alloc_regloc(list,destloc);
+ cg.a_load_cgparaloc_anyreg(list,OS_32,paraloc^,destloc.register64.reglo,4);
+ unget_para(paraloc^.next^);
+ cg.a_load_cgparaloc_anyreg(list,OS_32,paraloc^.next^,destloc.register64.reghi,4);
+ end;
+ end;
+ LOC_REFERENCE:
+ begin
+ gen_alloc_regloc(list,destloc);
+ reference_reset_base(href,paraloc^.reference.index,paraloc^.reference.offset,para.alignment);
+ cg64.a_load64_ref_reg(list,href,destloc.register64);
+ unget_para(paraloc^);
+ end;
+ else
+ internalerror(2005101501);
+ end
+ end
+ else
+{$endif not cpu64bitalu}
+ begin
+ if assigned(paraloc^.next) then
+ internalerror(200410105);
+ unget_para(paraloc^);
+ gen_alloc_regloc(list,destloc);
+ cg.a_load_cgparaloc_anyreg(list,destloc.size,paraloc^,destloc.register,sizeof(aint));
+ end;
+ end;
+ LOC_FPUREGISTER,
+ LOC_CFPUREGISTER :
+ begin
+{$if defined(sparc) or defined(arm)}
+ { Arm and Sparc passes floats in int registers, when loading to fpu register
+ we need a temp }
+ sizeleft := TCGSize2Size[destloc.size];
+ tg.GetTemp(list,sizeleft,sizeleft,tt_normal,tempref);
+ href:=tempref;
+ while assigned(paraloc) do
+ begin
+ unget_para(paraloc^);
+ cg.a_load_cgparaloc_ref(list,paraloc^,href,sizeleft,destloc.reference.alignment);
+ inc(href.offset,TCGSize2Size[paraloc^.size]);
+ dec(sizeleft,TCGSize2Size[paraloc^.size]);
+ paraloc:=paraloc^.next;
+ end;
+ gen_alloc_regloc(list,destloc);
+ cg.a_loadfpu_ref_reg(list,destloc.size,destloc.size,tempref,destloc.register);
+ tg.UnGetTemp(list,tempref);
+{$else sparc}
+ unget_para(paraloc^);
+ gen_alloc_regloc(list,destloc);
+ { from register to register -> alignment is irrelevant }
+ cg.a_load_cgparaloc_anyreg(list,destloc.size,paraloc^,destloc.register,0);
+ if assigned(paraloc^.next) then
+ internalerror(200410109);
+{$endif sparc}
+ end;
+ LOC_MMREGISTER,
+ LOC_CMMREGISTER :
+ begin
+{$ifndef cpu64bitalu}
+ { ARM vfp floats are passed in integer registers }
+ if (para.size=OS_F64) and
+ (paraloc^.size in [OS_32,OS_S32]) and
+ use_vectorfpu(vardef) then
+ begin
+ { we need 2x32bit reg }
+ if not assigned(paraloc^.next) or
+ assigned(paraloc^.next^.next) then
+ internalerror(2009112421);
+ unget_para(paraloc^);
+ unget_para(paraloc^.next^);
+ gen_alloc_regloc(list,destloc);
+ if (target_info.endian=endian_big) then
+ { paraloc^ -> high
+ paraloc^.next -> low }
+ reg64:=joinreg64(paraloc^.next^.register,paraloc^.register)
+ else
+ reg64:=joinreg64(paraloc^.register,paraloc^.next^.register);
+ cg64.a_loadmm_intreg64_reg(list,OS_F64,reg64,destloc.register);
+ end
+ else
+{$endif not cpu64bitalu}
+ begin
+ unget_para(paraloc^);
+ gen_alloc_regloc(list,destloc);
+ { from register to register -> alignment is irrelevant }
+ cg.a_load_cgparaloc_anyreg(list,destloc.size,paraloc^,destloc.register,0);
+ { data could come in two memory locations, for now
+ we simply ignore the sanity check (FK)
+ if assigned(paraloc^.next) then
+ internalerror(200410108);
+ }
+ end;
+ end;
+ else
+ internalerror(2010052903);
+ end;
+ end;
+
+
+ procedure gen_load_para_value(list:TAsmList);
+
+ procedure get_para(const paraloc:TCGParaLocation);
+ begin
+ case paraloc.loc of
+ LOC_REGISTER :
+ begin
+ if getsupreg(paraloc.register)<first_int_imreg then
+ cg.getcpuregister(list,paraloc.register);
+ end;
+ LOC_MMREGISTER :
+ begin
+ if getsupreg(paraloc.register)<first_mm_imreg then
+ cg.getcpuregister(list,paraloc.register);
+ end;
+ LOC_FPUREGISTER :
+ begin
+ if getsupreg(paraloc.register)<first_fpu_imreg then
+ cg.getcpuregister(list,paraloc.register);
+ end;
+ end;
+ end;
+
+
+ var
+ i : longint;
+ currpara : tparavarsym;
+ paraloc : pcgparalocation;
+ begin
+ if (po_assembler in current_procinfo.procdef.procoptions) or
+ { exceptfilters have a single hidden 'parentfp' parameter, which
+ is handled by tcg.g_proc_entry. }
+ (current_procinfo.procdef.proctypeoption=potype_exceptfilter) then
+ exit;
+
+ { Allocate registers used by parameters }
+ for i:=0 to current_procinfo.procdef.paras.count-1 do
+ begin
+ currpara:=tparavarsym(current_procinfo.procdef.paras[i]);
+ paraloc:=currpara.paraloc[calleeside].location;
+ while assigned(paraloc) do
+ begin
+ if paraloc^.loc in [LOC_REGISTER,LOC_FPUREGISTER,LOC_MMREGISTER] then
+ get_para(paraloc^);
+ paraloc:=paraloc^.next;
+ end;
+ end;
+
+ { Copy parameters to local references/registers }
+ for i:=0 to current_procinfo.procdef.paras.count-1 do
+ begin
+ currpara:=tparavarsym(current_procinfo.procdef.paras[i]);
+ gen_load_cgpara_loc(list,currpara.vardef,currpara.paraloc[calleeside],currpara.initialloc,paramanager.param_use_paraloc(currpara.paraloc[calleeside]));
+ { gen_load_cgpara_loc() already allocated the initialloc
+ -> don't allocate again }
+ if currpara.initialloc.loc in [LOC_CREGISTER,LOC_CFPUREGISTER,LOC_CMMREGISTER] then
+ gen_alloc_regvar(list,currpara,false);
+ end;
+
+ { generate copies of call by value parameters, must be done before
+ the initialization and body is parsed because the refcounts are
+ incremented using the local copies }
+ current_procinfo.procdef.parast.SymList.ForEachCall(@copyvalueparas,list);
+{$ifdef powerpc}
+ { unget the register that contains the stack pointer before the procedure entry, }
+ { which is used to access the parameters in their original callee-side location }
+ if (tppcprocinfo(current_procinfo).needs_frame_pointer) then
+ cg.a_reg_dealloc(list,NR_R12);
+{$endif powerpc}
+{$ifdef powerpc64}
+ { unget the register that contains the stack pointer before the procedure entry, }
+ { which is used to access the parameters in their original callee-side location }
+ if (tppcprocinfo(current_procinfo).needs_frame_pointer) then
+ cg.a_reg_dealloc(list, NR_OLD_STACK_POINTER_REG);
+{$endif powerpc64}
+ if not(po_assembler in current_procinfo.procdef.procoptions) then
+ begin
+ { has to be done here rather than in gen_initialize_code, because
+ the initialisation code is generated a) later and b) with
+ rad_backwards, so the register allocator would generate
+ information as if this code comes before loading the parameters
+ from their original registers to their local location }
+ if (localvartrashing <> -1) then
+ current_procinfo.procdef.localst.SymList.ForEachCall(@trash_variable,list);
+ { initialize refcounted paras, and trash others. Needed here
+ instead of in gen_initialize_code, because when a reference is
+ intialised or trashed while the pointer to that reference is kept
+ in a regvar, we add a register move and that one again has to
+ come after the parameter loading code as far as the register
+ allocator is concerned }
+ current_procinfo.procdef.parast.SymList.ForEachCall(@init_paras,list);
+ end;
+ end;
+
+
+ procedure gen_initialize_code(list:TAsmList);
+ begin
+ { initialize local data like ansistrings }
+ case current_procinfo.procdef.proctypeoption of
+ potype_unitinit:
+ begin
+ { this is also used for initialization of variables in a
+ program which does not have a globalsymtable }
+ if assigned(current_module.globalsymtable) then
+ TSymtable(current_module.globalsymtable).SymList.ForEachCall(@initialize_data,list);
+ TSymtable(current_module.localsymtable).SymList.ForEachCall(@initialize_data,list);
+ TSymtable(current_module.localsymtable).SymList.ForEachCall(@initialize_regvars,list);
+ end;
+ { units have seperate code for initilization and finalization }
+ potype_unitfinalize: ;
+ { program init/final is generated in separate procedure }
+ potype_proginit:
+ begin
+ TSymtable(current_module.localsymtable).SymList.ForEachCall(@initialize_regvars,list);
+ end;
+ else
+ current_procinfo.procdef.localst.SymList.ForEachCall(@initialize_data,list);
+ end;
+
+ { initialisizes temp. ansi/wide string data }
+ if (current_procinfo.procdef.proctypeoption<>potype_exceptfilter) then
+ inittempvariables(list);
+
+{$ifdef OLDREGVARS}
+ load_regvars(list,nil);
+{$endif OLDREGVARS}
+ end;
+
+
+ procedure gen_finalize_code(list:TAsmList);
+ var
+ old_current_procinfo: tprocinfo;
+ begin
+ old_current_procinfo:=current_procinfo;
+ if (current_procinfo.procdef.proctypeoption=potype_exceptfilter) then
+ begin
+ if (current_procinfo.parent.finalize_procinfo<>current_procinfo) then
+ exit;
+ current_procinfo:=current_procinfo.parent;
+ end;
+
+{$ifdef OLDREGVARS}
+ cleanup_regvars(list);
+{$endif OLDREGVARS}
+
+ { finalize temporary data }
+ finalizetempvariables(list);
+
+ { finalize local data like ansistrings}
+ case current_procinfo.procdef.proctypeoption of
+ potype_unitfinalize:
+ begin
+ { this is also used for initialization of variables in a
+ program which does not have a globalsymtable }
+ if assigned(current_module.globalsymtable) then
+ TSymtable(current_module.globalsymtable).SymList.ForEachCall(@finalize_static_data,list);
+ TSymtable(current_module.localsymtable).SymList.ForEachCall(@finalize_static_data,list);
+ end;
+ { units/progs have separate code for initialization and finalization }
+ potype_unitinit: ;
+ { program init/final is generated in separate procedure }
+ potype_proginit: ;
+ else
+ current_procinfo.procdef.localst.SymList.ForEachCall(@finalize_local_vars,list);
+ end;
+
+ { finalize paras data }
+ if assigned(current_procinfo.procdef.parast) and
+ not(po_assembler in current_procinfo.procdef.procoptions) then
+ current_procinfo.procdef.parast.SymList.ForEachCall(@final_paras,list);
+ current_procinfo:=old_current_procinfo;
+ end;
+
+
+ procedure gen_entry_code(list:TAsmList);
+ begin
+ { the actual profile code can clobber some registers,
+ therefore if the context must be saved, do it before
+ the actual call to the profile code
+ }
+ if (cs_profile in current_settings.moduleswitches) and
+ not(po_assembler in current_procinfo.procdef.procoptions) then
+ begin
+ { non-win32 can call mcout even in main }
+ if not (target_info.system in [system_i386_win32,system_i386_wdosx]) or
+ not (current_procinfo.procdef.proctypeoption=potype_proginit) then
+ begin
+ cg.g_profilecode(list);
+ end;
+ end;
+
+ { call startup helpers from main program }
+ if (current_procinfo.procdef.proctypeoption=potype_proginit) then
+ begin
+ { initialize units }
+ cg.allocallcpuregisters(list);
+ if not(current_module.islibrary) then
+ cg.a_call_name(list,'FPC_INITIALIZEUNITS',false)
+ else
+ cg.a_call_name(list,'FPC_LIBINITIALIZEUNITS',false);
+ cg.deallocallcpuregisters(list);
+ end;
+
+ list.concat(Tai_force_line.Create);
+
+{$ifdef OLDREGVARS}
+ load_regvars(list,nil);
+{$endif OLDREGVARS}
+ end;
+
+
+ procedure gen_exit_code(list:TAsmList);
+ begin
+ { call __EXIT for main program }
+ if (not DLLsource) and
+ (current_procinfo.procdef.proctypeoption=potype_proginit) then
+ cg.a_call_name(list,'FPC_DO_EXIT',false);
+ end;
+
+
+{****************************************************************************
+ Entry/Exit
+****************************************************************************}
+
+ function has_alias_name(pd:tprocdef;const s:string):boolean;
+ var
+ item : TCmdStrListItem;
+ begin
+ result:=true;
+ if pd.mangledname=s then
+ exit;
+ item := TCmdStrListItem(pd.aliasnames.first);
+ while assigned(item) do
+ begin
+ if item.str=s then
+ exit;
+ item := TCmdStrListItem(item.next);
+ end;
+ result:=false;
+ end;
+
+
+ procedure alloc_proc_symbol(pd: tprocdef);
+ var
+ item : TCmdStrListItem;
+ begin
+ item := TCmdStrListItem(pd.aliasnames.first);
+ while assigned(item) do
+ begin
+ current_asmdata.DefineAsmSymbol(item.str,AB_GLOBAL,AT_FUNCTION);
+ item := TCmdStrListItem(item.next);
+ end;
+ end;
+
+
+ procedure gen_proc_symbol(list:TAsmList);
+ var
+ item,
+ previtem : TCmdStrListItem;
+ begin
+ previtem:=nil;
+ item := TCmdStrListItem(current_procinfo.procdef.aliasnames.first);
+ while assigned(item) do
+ begin
+{$ifdef arm}
+ if current_settings.cputype in cpu_thumb2 then
+ list.concat(tai_thumb_func.create);
+{$endif arm}
+ { "double link" all procedure entry symbols via .reference }
+ { directives on darwin, because otherwise the linker }
+ { sometimes strips the procedure if only on of the symbols }
+ { is referenced }
+ if assigned(previtem) and
+ (target_info.system in systems_darwin) then
+ list.concat(tai_directive.create(asd_reference,item.str));
+ if (cs_profile in current_settings.moduleswitches) or
+ (po_global in current_procinfo.procdef.procoptions) then
+ list.concat(Tai_symbol.createname_global(item.str,AT_FUNCTION,0))
+ else
+ list.concat(Tai_symbol.createname(item.str,AT_FUNCTION,0));
+ if assigned(previtem) and
+ (target_info.system in systems_darwin) then
+ list.concat(tai_directive.create(asd_reference,previtem.str));
+ if not(af_stabs_use_function_absolute_addresses in target_asm.flags) then
+ list.concat(Tai_function_name.create(item.str));
+ previtem:=item;
+ item := TCmdStrListItem(item.next);
+ end;
+ current_procinfo.procdef.procstarttai:=tai(list.last);
+ end;
+
+
+
+ procedure gen_proc_symbol_end(list:TAsmList);
+ begin
+ list.concat(Tai_symbol_end.Createname(current_procinfo.procdef.mangledname));
+
+ current_procinfo.procdef.procendtai:=tai(list.last);
+
+ if (current_module.islibrary) then
+ if (current_procinfo.procdef.proctypeoption = potype_proginit) then
+ { setinitname may generate a new section -> don't add to the
+ current list, because we assume this remains a text section }
+ exportlib.setinitname(current_asmdata.AsmLists[al_exports],current_procinfo.procdef.mangledname);
+
+ if (current_procinfo.procdef.proctypeoption=potype_proginit) then
+ begin
+ if (target_info.system in (systems_darwin+[system_powerpc_macos])) and
+ not(current_module.islibrary) then
+ begin
+ new_section(list,sec_code,'',4);
+ list.concat(tai_symbol.createname_global(
+ target_info.cprefix+mainaliasname,AT_FUNCTION,0));
+ { keep argc, argv and envp properly on the stack }
+ cg.a_jmp_name(list,target_info.cprefix+'FPC_SYSTEMMAIN');
+ end;
+ end;
+ end;
+
+
+ procedure gen_proc_entry_code(list:TAsmList);
+ var
+ hitemp,
+ lotemp : longint;
+ begin
+ { generate call frame marker for dwarf call frame info }
+ current_asmdata.asmcfi.start_frame(list);
+
+ { All temps are know, write offsets used for information }
+ if (cs_asm_source in current_settings.globalswitches) then
+ begin
+ if tg.direction>0 then
+ begin
+ lotemp:=current_procinfo.tempstart;
+ hitemp:=tg.lasttemp;
+ end
+ else
+ begin
+ lotemp:=tg.lasttemp;
+ hitemp:=current_procinfo.tempstart;
+ end;
+ list.concat(Tai_comment.Create(strpnew('Temps allocated between '+std_regname(current_procinfo.framepointer)+
+ tostr_with_plus(lotemp)+' and '+std_regname(current_procinfo.framepointer)+tostr_with_plus(hitemp))));
+ end;
+
+ { generate target specific proc entry code }
+ cg.g_proc_entry(list,current_procinfo.calc_stackframe_size,(po_nostackframe in current_procinfo.procdef.procoptions));
+ end;
+
+
+ procedure gen_proc_exit_code(list:TAsmList);
+ var
+ parasize : longint;
+ begin
+ { c style clearstack does not need to remove parameters from the stack, only the
+ return value when it was pushed by arguments }
+ if current_procinfo.procdef.proccalloption in clearstack_pocalls then
+ begin
+ parasize:=0;
+ if paramanager.ret_in_param(current_procinfo.procdef.returndef,current_procinfo.procdef.proccalloption) then
+ inc(parasize,sizeof(pint));
+ end
+ else
+ begin
+ parasize:=current_procinfo.para_stack_size;
+ { the parent frame pointer para has to be removed by the caller in
+ case of Delphi-style parent frame pointer passing }
+ if not paramanager.use_fixed_stack and
+ (po_delphi_nested_cc in current_procinfo.procdef.procoptions) then
+ dec(parasize,sizeof(pint));
+ end;
+
+ { generate target specific proc exit code }
+ cg.g_proc_exit(list,parasize,(po_nostackframe in current_procinfo.procdef.procoptions));
+
+ { release return registers, needed for optimizer }
+ if not is_void(current_procinfo.procdef.returndef) then
+ paramanager.freecgpara(list,current_procinfo.procdef.funcretloc[calleeside]);
+
+ { end of frame marker for call frame info }
+ current_asmdata.asmcfi.end_frame(list);
+ end;
+
+
+ procedure gen_stack_check_size_para(list:TAsmList);
+ var
+ paraloc1 : tcgpara;
+ begin
+ paraloc1.init;
+ paramanager.getintparaloc(pocall_default,1,paraloc1);
+ cg.a_load_const_cgpara(list,OS_INT,current_procinfo.calc_stackframe_size,paraloc1);
+ paramanager.freecgpara(list,paraloc1);
+ paraloc1.done;
+ end;
+
+
+ procedure gen_stack_check_call(list:TAsmList);
+ var
+ paraloc1 : tcgpara;
+ begin
+ paraloc1.init;
+ { Also alloc the register needed for the parameter }
+ paramanager.getintparaloc(pocall_default,1,paraloc1);
+ paramanager.freecgpara(list,paraloc1);
+ { Call the helper }
+ cg.allocallcpuregisters(list);
+ cg.a_call_name(list,'FPC_STACKCHECK',false);
+ cg.deallocallcpuregisters(list);
+ paraloc1.done;
+ end;
+
+
+ procedure gen_save_used_regs(list:TAsmList);
+ begin
+ { Pure assembler routines need to save the registers themselves }
+ if (po_assembler in current_procinfo.procdef.procoptions) then
+ exit;
+
+ { oldfpccall expects all registers to be destroyed }
+ if current_procinfo.procdef.proccalloption<>pocall_oldfpccall then
+ cg.g_save_registers(list);
+ end;
+
+
+ procedure gen_restore_used_regs(list:TAsmList);
+ begin
+ { Pure assembler routines need to save the registers themselves }
+ if (po_assembler in current_procinfo.procdef.procoptions) then
+ exit;
+
+ { oldfpccall expects all registers to be destroyed }
+ if current_procinfo.procdef.proccalloption<>pocall_oldfpccall then
+ cg.g_restore_registers(list);
+ end;
+
+
+{****************************************************************************
+ External handling
+****************************************************************************}
+
+ procedure gen_external_stub(list:TAsmList;pd:tprocdef;const externalname:string);
+ begin
+ create_codegen;
+ { add the procedure to the al_procedures }
+ maybe_new_object_file(list);
+ new_section(list,sec_code,lower(pd.mangledname),current_settings.alignment.procalign);
+ list.concat(Tai_align.create(current_settings.alignment.procalign));
+ if (po_global in pd.procoptions) then
+ list.concat(Tai_symbol.createname_global(pd.mangledname,AT_FUNCTION,0))
+ else
+ list.concat(Tai_symbol.createname(pd.mangledname,AT_FUNCTION,0));
+
+ cg.g_external_wrapper(list,pd,externalname);
+ destroy_codegen;
+ end;
+
+{****************************************************************************
+ Const Data
+****************************************************************************}
+
+ procedure insertbssdata(sym : tstaticvarsym);
+ var
+ l : asizeint;
+ varalign : shortint;
+ storefilepos : tfileposinfo;
+ list : TAsmList;
+ sectype : TAsmSectiontype;
+ begin
+ storefilepos:=current_filepos;
+ current_filepos:=sym.fileinfo;
+ l:=sym.getsize;
+ varalign:=sym.vardef.alignment;
+ if (varalign=0) then
+ varalign:=var_align_size(l)
+ else
+ varalign:=var_align(varalign);
+ if tf_section_threadvars in target_info.flags then
+ begin
+ if (vo_is_thread_var in sym.varoptions) then
+ begin
+ list:=current_asmdata.asmlists[al_threadvars];
+ sectype:=sec_threadvar;
+ end
+ else
+ begin
+ list:=current_asmdata.asmlists[al_globals];
+ sectype:=sec_bss;
+ end;
+ end
+ else
+ begin
+ if (vo_is_thread_var in sym.varoptions) then
+ begin
+ inc(l,sizeof(pint));
+ { it doesn't help to set a higher alignment, as }
+ { the first sizeof(pint) bytes field will offset }
+ { everything anyway }
+ varalign:=sizeof(pint);
+ end;
+ list:=current_asmdata.asmlists[al_globals];
+ sectype:=sec_bss;
+ end;
+ maybe_new_object_file(list);
+ if vo_has_section in sym.varoptions then
+ new_section(list,sec_user,sym.section,varalign)
+ else
+ new_section(list,sectype,lower(sym.mangledname),varalign);
+ if (sym.owner.symtabletype=globalsymtable) or
+ create_smartlink or
+ DLLSource or
+ (assigned(current_procinfo) and
+ (po_inline in current_procinfo.procdef.procoptions)) or
+ (vo_is_public in sym.varoptions) then
+ list.concat(Tai_datablock.create_global(sym.mangledname,l))
+ else
+ list.concat(Tai_datablock.create(sym.mangledname,l));
+ current_filepos:=storefilepos;
+ end;
+
+
+ procedure gen_alloc_symtable(list:TAsmList;st:TSymtable);
+
+ procedure setlocalloc(vs:tabstractnormalvarsym);
+ begin
+ if cs_asm_source in current_settings.globalswitches then
+ begin
+ case vs.initialloc.loc of
+ LOC_REFERENCE :
+ begin
+ if not assigned(vs.initialloc.reference.symbol) then
+ list.concat(Tai_comment.Create(strpnew('Var '+vs.realname+' located at '+
+ std_regname(vs.initialloc.reference.base)+tostr_with_plus(vs.initialloc.reference.offset))));
+ end;
+ end;
+ end;
+ vs.localloc:=vs.initialloc;
+ end;
+
+ var
+ i : longint;
+ sym : tsym;
+ vs : tabstractnormalvarsym;
+ isaddr : boolean;
+ begin
+ for i:=0 to st.SymList.Count-1 do
+ begin
+ sym:=tsym(st.SymList[i]);
+ case sym.typ of
+ staticvarsym :
+ begin
+ vs:=tabstractnormalvarsym(sym);
+ { The code in loadnode.pass_generatecode will create the
+ LOC_REFERENCE instead for all none register variables. This is
+ required because we can't store an asmsymbol in the localloc because
+ the asmsymbol is invalid after an unit is compiled. This gives
+ problems when this procedure is inlined in another unit (PFV) }
+ if vs.is_regvar(false) then
+ begin
+ vs.initialloc.loc:=tvarregable2tcgloc[vs.varregable];
+ vs.initialloc.size:=def_cgsize(vs.vardef);
+ gen_alloc_regvar(list,vs,true);
+ setlocalloc(vs);
+ end;
+ end;
+ paravarsym :
+ begin
+ vs:=tabstractnormalvarsym(sym);
+ { Parameters passed to assembler procedures need to be kept
+ in the original location }
+ if (po_assembler in current_procinfo.procdef.procoptions) then
+ tparavarsym(vs).paraloc[calleeside].get_location(vs.initialloc)
+ { exception filters receive their frame pointer as a parameter }
+ else if (current_procinfo.procdef.proctypeoption=potype_exceptfilter) and
+ (vo_is_parentfp in vs.varoptions) then
+ begin
+ location_reset(vs.initialloc,LOC_REGISTER,OS_ADDR);
+ vs.initialloc.register:=NR_FRAME_POINTER_REG;
+ end
+ else
+ begin
+ isaddr:=paramanager.push_addr_param(vs.varspez,vs.vardef,current_procinfo.procdef.proccalloption);
+ if isaddr then
+ vs.initialloc.size:=OS_ADDR
+ else
+ vs.initialloc.size:=def_cgsize(vs.vardef);
+
+ if vs.is_regvar(isaddr) then
+ vs.initialloc.loc:=tvarregable2tcgloc[vs.varregable]
+ else
+ begin
+ vs.initialloc.loc:=LOC_REFERENCE;
+ { Reuse the parameter location for values to are at a single location on the stack }
+ if paramanager.param_use_paraloc(tparavarsym(sym).paraloc[calleeside]) then
+ begin
+ reference_reset_base(vs.initialloc.reference,tparavarsym(sym).paraloc[calleeside].location^.reference.index,
+ tparavarsym(sym).paraloc[calleeside].location^.reference.offset,tparavarsym(sym).paraloc[calleeside].alignment);
+ end
+ else
+ begin
+ if isaddr then
+ tg.GetLocal(list,sizeof(pint),voidpointertype,vs.initialloc.reference)
+ else
+ tg.GetLocal(list,vs.getsize,tparavarsym(sym).paraloc[calleeside].alignment,vs.vardef,vs.initialloc.reference);
+ end;
+ end;
+ end;
+ setlocalloc(vs);
+ end;
+ localvarsym :
+ begin
+ vs:=tabstractnormalvarsym(sym);
+ vs.initialloc.size:=def_cgsize(vs.vardef);
+ if (m_delphi in current_settings.modeswitches) and
+ (po_assembler in current_procinfo.procdef.procoptions) and
+ (vo_is_funcret in vs.varoptions) and
+ (vs.refs=0) then
+ begin
+ { not referenced, so don't allocate. Use dummy to }
+ { avoid ie's later on because of LOC_INVALID }
+ vs.initialloc.loc:=LOC_REGISTER;
+ vs.initialloc.size:=OS_INT;
+ vs.initialloc.register:=NR_FUNCTION_RESULT_REG;
+ end
+ else if vs.is_regvar(false) then
+ begin
+ vs.initialloc.loc:=tvarregable2tcgloc[vs.varregable];
+ gen_alloc_regvar(list,vs,true);
+ end
+ else
+ begin
+ vs.initialloc.loc:=LOC_REFERENCE;
+ tg.GetLocal(list,vs.getsize,vs.vardef,vs.initialloc.reference);
+ end;
+ setlocalloc(vs);
+ end;
+ end;
+ end;
+ end;
+
+
+ procedure add_regvars(var rv: tusedregvars; const location: tlocation);
+ begin
+ case location.loc of
+ LOC_CREGISTER:
+{$ifndef cpu64bitalu}
+ if location.size in [OS_64,OS_S64] then
+ begin
+ rv.intregvars.addnodup(getsupreg(location.register64.reglo));
+ rv.intregvars.addnodup(getsupreg(location.register64.reghi));
+ end
+ else
+{$endif not cpu64bitalu}
+ rv.intregvars.addnodup(getsupreg(location.register));
+ LOC_CFPUREGISTER:
+ rv.fpuregvars.addnodup(getsupreg(location.register));
+ LOC_CMMREGISTER:
+ rv.mmregvars.addnodup(getsupreg(location.register));
+ end;
+ end;
+
+
+ function do_get_used_regvars(var n: tnode; arg: pointer): foreachnoderesult;
+ var
+ rv: pusedregvars absolute arg;
+ begin
+ case (n.nodetype) of
+ temprefn:
+ { We only have to synchronise a tempnode before a loop if it is }
+ { not created inside the loop, and only synchronise after the }
+ { loop if it's not destroyed inside the loop. If it's created }
+ { before the loop and not yet destroyed, then before the loop }
+ { is secondpassed tempinfo^.valid will be true, and we get the }
+ { correct registers. If it's not destroyed inside the loop, }
+ { then after the loop has been secondpassed tempinfo^.valid }
+ { be true and we also get the right registers. In other cases, }
+ { tempinfo^.valid will be false and so we do not add }
+ { unnecessary registers. This way, we don't have to look at }
+ { tempcreate and tempdestroy nodes to get this info (JM) }
+ if (ti_valid in ttemprefnode(n).tempinfo^.flags) then
+ add_regvars(rv^,ttemprefnode(n).tempinfo^.location);
+ loadn:
+ if (tloadnode(n).symtableentry.typ in [staticvarsym,localvarsym,paravarsym]) then
+ add_regvars(rv^,tabstractnormalvarsym(tloadnode(n).symtableentry).localloc);
+ vecn:
+ { range checks sometimes need the high parameter }
+ if (cs_check_range in current_settings.localswitches) and
+ (is_open_array(tvecnode(n).left.resultdef) or
+ is_array_of_const(tvecnode(n).left.resultdef)) and
+ not(current_procinfo.procdef.proccalloption in cdecl_pocalls) then
+ add_regvars(rv^,tabstractnormalvarsym(get_high_value_sym(tparavarsym(tloadnode(tvecnode(n).left).symtableentry))).localloc)
+
+ end;
+ result := fen_true;
+ end;
+
+
+ procedure get_used_regvars(n: tnode; var rv: tusedregvars);
+ begin
+ foreachnodestatic(n,@do_get_used_regvars,@rv);
+ end;
+
+(*
+ See comments at declaration of pusedregvarscommon
+
+ function do_get_used_regvars_common(var n: tnode; arg: pointer): foreachnoderesult;
+ var
+ rv: pusedregvarscommon absolute arg;
+ begin
+ if (n.nodetype = loadn) and
+ (tloadnode(n).symtableentry.typ in [staticvarsym,localvarsym,paravarsym]) then
+ with tabstractnormalvarsym(tloadnode(n).symtableentry).localloc do
+ case loc of
+ LOC_CREGISTER:
+ { if not yet encountered in this node tree }
+ if (rv^.myregvars.intregvars.addnodup(getsupreg(register))) and
+ { but nevertheless already encountered somewhere }
+ not(rv^.allregvars.intregvars.addnodup(getsupreg(register))) then
+ { then it's a regvar used in two or more node trees }
+ rv^.commonregvars.intregvars.addnodup(getsupreg(register));
+ LOC_CFPUREGISTER:
+ if (rv^.myregvars.intregvars.addnodup(getsupreg(register))) and
+ not(rv^.allregvars.intregvars.addnodup(getsupreg(register))) then
+ rv^.commonregvars.intregvars.addnodup(getsupreg(register));
+ LOC_CMMREGISTER:
+ if (rv^.myregvars.intregvars.addnodup(getsupreg(register))) and
+ not(rv^.allregvars.intregvars.addnodup(getsupreg(register))) then
+ rv^.commonregvars.intregvars.addnodup(getsupreg(register));
+ end;
+ result := fen_true;
+ end;
+
+
+ procedure get_used_regvars_common(n: tnode; var rv: tusedregvarscommon);
+ begin
+ rv.myregvars.intregvars.clear;
+ rv.myregvars.fpuregvars.clear;
+ rv.myregvars.mmregvars.clear;
+ foreachnodestatic(n,@do_get_used_regvars_common,@rv);
+ end;
+*)
+
+ procedure gen_sync_regvars(list:TAsmList; var rv: tusedregvars);
+ var
+ count: longint;
+ begin
+ for count := 1 to rv.intregvars.length do
+ cg.a_reg_sync(list,newreg(R_INTREGISTER,rv.intregvars.readidx(count-1),R_SUBWHOLE));
+ for count := 1 to rv.fpuregvars.length do
+ cg.a_reg_sync(list,newreg(R_FPUREGISTER,rv.fpuregvars.readidx(count-1),R_SUBWHOLE));
+ for count := 1 to rv.mmregvars.length do
+ cg.a_reg_sync(list,newreg(R_MMREGISTER,rv.mmregvars.readidx(count-1),R_SUBWHOLE));
+ end;
+
+
+{*****************************************************************************
+ SSA support
+*****************************************************************************}
+
+ type
+ preplaceregrec = ^treplaceregrec;
+ treplaceregrec = record
+ old, new: tregister;
+{$ifndef cpu64bitalu}
+ oldhi, newhi: tregister;
+{$endif not cpu64bitalu}
+ ressym: tsym;
+ { moved sym }
+ sym : tsym;
+ end;
+
+
+ function doreplace(var n: tnode; para: pointer): foreachnoderesult;
+ var
+ rr: preplaceregrec absolute para;
+ begin
+ result := fen_false;
+ if (nf_is_funcret in n.flags) and (fc_exit in flowcontrol) then
+ exit;
+ case n.nodetype of
+ loadn:
+ begin
+ if (tabstractvarsym(tloadnode(n).symtableentry).varoptions * [vo_is_dll_var, vo_is_thread_var] = []) and
+ not assigned(tloadnode(n).left) and
+ ((tloadnode(n).symtableentry <> rr^.ressym) or
+ not(fc_exit in flowcontrol)
+ ) and
+ (tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.loc in [LOC_CREGISTER,LOC_CFPUREGISTER,LOC_CMMXREGISTER,LOC_CMMREGISTER]) and
+ (tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.register = rr^.old) then
+ begin
+{$ifndef cpu64bitalu}
+ { it's possible a 64 bit location was shifted and/xor typecasted }
+ { in a 32 bit value, so only 1 register was left in the location }
+ if (tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.size in [OS_64,OS_S64]) then
+ if (tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.register64.reghi = rr^.oldhi) then
+ tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.register64.reghi := rr^.newhi
+ else
+ exit;
+{$endif not cpu64bitalu}
+ tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.register := rr^.new;
+ rr^.sym := tabstractnormalvarsym(tloadnode(n).symtableentry);
+ result := fen_norecurse_true;
+ end;
+ end;
+ temprefn:
+ begin
+ if (ti_valid in ttemprefnode(n).tempinfo^.flags) and
+ (ttemprefnode(n).tempinfo^.location.loc in [LOC_CREGISTER,LOC_CFPUREGISTER,LOC_CMMXREGISTER,LOC_CMMREGISTER]) and
+ (ttemprefnode(n).tempinfo^.location.register = rr^.old) then
+ begin
+{$ifndef cpu64bitalu}
+ { it's possible a 64 bit location was shifted and/xor typecasted }
+ { in a 32 bit value, so only 1 register was left in the location }
+ if (ttemprefnode(n).tempinfo^.location.size in [OS_64,OS_S64]) then
+ if (ttemprefnode(n).tempinfo^.location.register64.reghi = rr^.oldhi) then
+ ttemprefnode(n).tempinfo^.location.register64.reghi := rr^.newhi
+ else
+ exit;
+{$endif not cpu64bitalu}
+ ttemprefnode(n).tempinfo^.location.register := rr^.new;
+ result := fen_norecurse_true;
+ end;
+ end;
+ { optimize the searching a bit }
+ derefn,addrn,
+ calln,inlinen,casen,
+ addn,subn,muln,
+ andn,orn,xorn,
+ ltn,lten,gtn,gten,equaln,unequaln,
+ slashn,divn,shrn,shln,notn,
+ inn,
+ asn,isn:
+ result := fen_norecurse_false;
+ end;
+ end;
+
+
+ procedure maybechangeloadnodereg(list: TAsmList; var n: tnode; reload: boolean);
+ var
+ rr: treplaceregrec;
+ begin
+ if not (n.location.loc in [LOC_CREGISTER,LOC_CFPUREGISTER,LOC_CMMXREGISTER,LOC_CMMREGISTER]) or
+ ([fc_inflowcontrol,fc_gotolabel,fc_lefthandled] * flowcontrol <> []) then
+ exit;
+ rr.old := n.location.register;
+ rr.ressym := nil;
+ rr.sym := nil;
+ {$ifndef cpu64bitalu}
+ rr.oldhi := NR_NO;
+ {$endif not cpu64bitalu}
+ case n.location.loc of
+ LOC_CREGISTER:
+ begin
+ {$ifndef cpu64bitalu}
+ if (n.location.size in [OS_64,OS_S64]) then
+ begin
+ rr.oldhi := n.location.register64.reghi;
+ rr.new := cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+ rr.newhi := cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+ end
+ else
+ {$endif not cpu64bitalu}
+ rr.new := cg.getintregister(current_asmdata.CurrAsmList,n.location.size);
+ end;
+ LOC_CFPUREGISTER:
+ rr.new := cg.getfpuregister(current_asmdata.CurrAsmList,n.location.size);
+ {$ifdef SUPPORT_MMX}
+ LOC_CMMXREGISTER:
+ rr.new := tcgx86(cg).getmmxregister(current_asmdata.CurrAsmList);
+ {$endif SUPPORT_MMX}
+ LOC_CMMREGISTER:
+ rr.new := cg.getmmregister(current_asmdata.CurrAsmList,n.location.size);
+ else
+ exit;
+ end;
+
+ if not is_void(current_procinfo.procdef.returndef) and
+ assigned(current_procinfo.procdef.funcretsym) and
+ (tabstractvarsym(current_procinfo.procdef.funcretsym).refs <> 0) then
+ if (current_procinfo.procdef.proctypeoption=potype_constructor) then
+ rr.ressym:=tsym(current_procinfo.procdef.parast.Find('self'))
+ else
+ rr.ressym:=current_procinfo.procdef.funcretsym;
+
+ if not foreachnodestatic(n,@doreplace,@rr) then
+ exit;
+
+ if reload then
+ case n.location.loc of
+ LOC_CREGISTER:
+ begin
+ {$ifndef cpu64bitalu}
+ if (n.location.size in [OS_64,OS_S64]) then
+ cg64.a_load64_reg_reg(list,n.location.register64,joinreg64(rr.new,rr.newhi))
+ else
+ {$endif not cpu64bitalu}
+ cg.a_load_reg_reg(list,n.location.size,n.location.size,n.location.register,rr.new);
+ end;
+ LOC_CFPUREGISTER:
+ cg.a_loadfpu_reg_reg(list,n.location.size,n.location.size,n.location.register,rr.new);
+ {$ifdef SUPPORT_MMX}
+ LOC_CMMXREGISTER:
+ cg.a_loadmm_reg_reg(list,OS_M64,OS_M64,n.location.register,rr.new,nil);
+ {$endif SUPPORT_MMX}
+ LOC_CMMREGISTER:
+ cg.a_loadmm_reg_reg(list,n.location.size,n.location.size,n.location.register,rr.new,nil);
+ else
+ internalerror(2006090920);
+ end;
+
+ { now that we've change the loadn/temp, also change the node result location }
+ {$ifndef cpu64bitalu}
+ if (n.location.size in [OS_64,OS_S64]) then
+ begin
+ n.location.register64.reglo := rr.new;
+ n.location.register64.reghi := rr.newhi;
+ if assigned(rr.sym) then
+ list.concat(tai_varloc.create64(rr.sym,rr.new,rr.newhi));
+ end
+ else
+ {$endif not cpu64bitalu}
+ begin
+ n.location.register := rr.new;
+ if assigned(rr.sym) then
+ list.concat(tai_varloc.create(rr.sym,rr.new));
+ end;
+ end;
+
+
+ procedure gen_free_symtable(list:TAsmList;st:TSymtable);
+ var
+ i : longint;
+ sym : tsym;
+ begin
+ for i:=0 to st.SymList.Count-1 do
+ begin
+ sym:=tsym(st.SymList[i]);
+ if (sym.typ in [staticvarsym,localvarsym,paravarsym]) then
+ begin
+ with tabstractnormalvarsym(sym) do
+ begin
+ { Note: We need to keep the data available in memory
+ for the sub procedures that can access local data
+ in the parent procedures }
+ case localloc.loc of
+ LOC_CREGISTER :
+ if (pi_has_label in current_procinfo.flags) then
+{$ifndef cpu64bitalu}
+ if def_cgsize(vardef) in [OS_64,OS_S64] then
+ begin
+ cg.a_reg_sync(list,localloc.register64.reglo);
+ cg.a_reg_sync(list,localloc.register64.reghi);
+ end
+ else
+{$endif not cpu64bitalu}
+ cg.a_reg_sync(list,localloc.register);
+ LOC_CFPUREGISTER,
+ LOC_CMMREGISTER:
+ if (pi_has_label in current_procinfo.flags) then
+ cg.a_reg_sync(list,localloc.register);
+ LOC_REFERENCE :
+ begin
+ if typ in [localvarsym,paravarsym] then
+ tg.Ungetlocal(list,localloc.reference);
+ end;
+ end;
+ end;
+ end;
+ end;
+ end;
+
+
+ procedure gen_intf_wrapper(list:TAsmList;_class:tobjectdef);
+ var
+ i,j : longint;
+ tmps : string;
+ pd : TProcdef;
+ ImplIntf : TImplementedInterface;
+ begin
+ for i:=0 to _class.ImplementedInterfaces.count-1 do
+ begin
+ ImplIntf:=TImplementedInterface(_class.ImplementedInterfaces[i]);
+ if (ImplIntf=ImplIntf.VtblImplIntf) and
+ assigned(ImplIntf.ProcDefs) then
+ begin
+ maybe_new_object_file(list);
+ for j:=0 to ImplIntf.ProcDefs.Count-1 do
+ begin
+ pd:=TProcdef(ImplIntf.ProcDefs[j]);
+ tmps:=make_mangledname('WRPR',_class.owner,_class.objname^+'_$_'+
+ ImplIntf.IntfDef.objname^+'_$_'+tostr(j)+'_$_'+pd.mangledname);
+ { create wrapper code }
+ new_section(list,sec_code,tmps,0);
+ cg.init_register_allocators;
+ cg.g_intf_wrapper(list,pd,tmps,ImplIntf.ioffset);
+ cg.done_register_allocators;
+ end;
+ end;
+ end;
+ end;
+
+
+ procedure gen_intf_wrappers(list:TAsmList;st:TSymtable;nested:boolean);
+ var
+ i : longint;
+ def : tdef;
+ begin
+ if not nested then
+ create_codegen;
+ for i:=0 to st.DefList.Count-1 do
+ begin
+ def:=tdef(st.DefList[i]);
+ { if def can contain nested types then handle it symtable }
+ if def.typ in [objectdef,recorddef] then
+ gen_intf_wrappers(list,tabstractrecorddef(def).symtable,true);
+ if is_class(def) then
+ gen_intf_wrapper(list,tobjectdef(def));
+ end;
+ if not nested then
+ destroy_codegen;
+ end;
+
+
+ procedure gen_load_vmt_register(list:TAsmList;objdef:tobjectdef;selfloc:tlocation;var vmtreg:tregister);
+ var
+ href : treference;
+ begin
+ if is_object(objdef) then
+ begin
+ case selfloc.loc of
+ LOC_CREFERENCE,
+ LOC_REFERENCE:
+ begin
+ reference_reset_base(href,cg.getaddressregister(list),objdef.vmt_offset,sizeof(pint));
+ cg.a_loadaddr_ref_reg(list,selfloc.reference,href.base);
+ end;
+ else
+ internalerror(200305056);
+ end;
+ end
+ else
+ { This is also valid for Objective-C classes: vmt_offset is 0 there,
+ and the first "field" of an Objective-C class instance is a pointer
+ to its "meta-class". }
+ begin
+ case selfloc.loc of
+ LOC_REGISTER:
+ begin
+{$ifdef cpu_uses_separate_address_registers}
+ if getregtype(left.location.register)<>R_ADDRESSREGISTER then
+ begin
+ reference_reset_base(href,cg.getaddressregister(list),objdef.vmt_offset,sizeof(pint));
+ cg.a_load_reg_reg(list,OS_ADDR,OS_ADDR,selfloc.register,href.base);
+ end
+ else
+{$endif cpu_uses_separate_address_registers}
+ reference_reset_base(href,selfloc.register,objdef.vmt_offset,sizeof(pint));
+ end;
+ LOC_CREGISTER,
+ LOC_CREFERENCE,
+ LOC_REFERENCE:
+ begin
+ reference_reset_base(href,cg.getaddressregister(list),objdef.vmt_offset,sizeof(pint));
+ cg.a_load_loc_reg(list,OS_ADDR,selfloc,href.base);
+ end;
+ else
+ internalerror(200305057);
+ end;
+ end;
+ vmtreg:=cg.getaddressregister(list);
+ cg.g_maybe_testself(list,href.base);
+ cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,vmtreg);
+
+ { test validity of VMT }
+ if not(is_interface(objdef)) and
+ not(is_cppclass(objdef)) and
+ not(is_objc_class_or_protocol(objdef)) then
+ cg.g_maybe_testvmt(list,vmtreg,objdef);
+ end;
+
+
+ function getprocalign : shortint;
+ begin
+ { gprof uses 16 byte granularity }
+ if (cs_profile in current_settings.moduleswitches) then
+ result:=16
+ else
+ result:=current_settings.alignment.procalign;
+ end;
+
+
+ procedure gen_fpc_dummy(list : TAsmList);
+ begin
+{$ifdef i386}
+ { fix me! }
+ list.concat(Taicpu.Op_const_reg(A_MOV,S_L,1,NR_EAX));
+ list.concat(Taicpu.Op_const(A_RET,S_W,12));
+{$endif i386}
+ end;
+
+
+ procedure InsertInterruptTable;
+
+ procedure WriteVector(const name: string);
+{$IFDEF arm}
+ var
+ ai: taicpu;
+{$ENDIF arm}
+ begin
+{$IFDEF arm}
+ if current_settings.cputype in [cpu_armv7m] then
+ current_asmdata.asmlists[al_globals].concat(tai_const.Createname(name,0))
+ else
+ begin
+ ai:=taicpu.op_sym(A_B,current_asmdata.RefAsmSymbol(name));
+ ai.is_jmp:=true;
+ current_asmdata.asmlists[al_globals].concat(ai);
+ end;
+{$ENDIF arm}
+ end;
+
+ function GetInterruptTableLength: longint;
+ begin
+{$if defined(ARM)}
+ result:=embedded_controllers[current_settings.controllertype].interruptvectors;
+{$else}
+ result:=0;
+{$endif}
+ end;
+
+ var
+ hp: tused_unit;
+ sym: tsym;
+ i, i2: longint;
+ interruptTable: array of tprocdef;
+ pd: tprocdef;
+ begin
+ SetLength(interruptTable, GetInterruptTableLength);
+ FillChar(interruptTable[0], length(interruptTable)*sizeof(pointer), 0);
+
+ hp:=tused_unit(usedunits.first);
+ while assigned(hp) do
+ begin
+ for i := 0 to hp.u.symlist.Count-1 do
+ begin
+ sym:=tsym(hp.u.symlist[i]);
+ if not assigned(sym) then
+ continue;
+ if sym.typ = procsym then
+ begin
+ for i2 := 0 to tprocsym(sym).ProcdefList.Count-1 do
+ begin
+ pd:=tprocdef(tprocsym(sym).ProcdefList[i2]);
+ if pd.interruptvector >= 0 then
+ begin
+ if pd.interruptvector > high(interruptTable) then
+ Internalerror(2011030602);
+ if interruptTable[pd.interruptvector] <> nil then
+ internalerror(2011030601);
+
+ interruptTable[pd.interruptvector]:=pd;
+ break;
+ end;
+ end;
+ end;
+ end;
+ hp:=tused_unit(hp.next);
+ end;
+
+ new_section(current_asmdata.asmlists[al_globals],sec_init,'VECTORS',sizeof(pint));
+ current_asmdata.asmlists[al_globals].concat(Tai_symbol.Createname_global('VECTORS',AT_DATA,0));
+{$IFDEF arm}
+ if current_settings.cputype in [cpu_armv7m] then
+ current_asmdata.asmlists[al_globals].concat(tai_const.Createname('_stack_top',0)); { ARMv7-M processors have the initial stack value at address 0 }
+{$ENDIF arm}
+
+ for i:=0 to high(interruptTable) do
+ begin
+ if interruptTable[i]<>nil then
+ writeVector(interruptTable[i].mangledname)
+ else
+ writeVector('DefaultHandler'); { Default handler name }
+ end;
+ end;
+
+
+end.
diff --git a/closures/compiler/ncnv.pas b/closures/compiler/ncnv.pas
new file mode 100644
index 0000000000..dd989610b4
--- /dev/null
+++ b/closures/compiler/ncnv.pas
@@ -0,0 +1,3703 @@
+{
+ Copyright (c) 2000-2002 by Florian Klaempfl
+
+ Type checking and register allocation for type converting nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit ncnv;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,
+ symtype,
+ defutil,defcmp,
+ nld
+ ;
+
+ type
+ ttypeconvnode = class(tunarynode)
+ totypedef : tdef;
+ totypedefderef : tderef;
+ convtype : tconverttype;
+ warn_pointer_to_signed: boolean;
+ constructor create(node : tnode;def:tdef);virtual;
+ constructor create_explicit(node : tnode;def:tdef);
+ constructor create_internal(node : tnode;def:tdef);
+ constructor create_proc_to_procvar(node : tnode);
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderefimpl;override;
+ procedure derefimpl;override;
+ function dogetcopy : tnode;override;
+ function actualtargetnode: tnode;override;
+ procedure printnodeinfo(var t : text);override;
+ function pass_1 : tnode;override;
+ function pass_typecheck:tnode;override;
+ function simplify(forinline : boolean):tnode; override;
+ procedure mark_write;override;
+ function docompare(p: tnode) : boolean; override;
+ function retains_value_location:boolean;
+ function assign_allowed:boolean;
+ procedure second_call_helper(c : tconverttype);
+ private
+ function typecheck_int_to_int : tnode;
+ function typecheck_cord_to_pointer : tnode;
+ function typecheck_chararray_to_string : tnode;
+ function typecheck_string_to_chararray : tnode;
+ function typecheck_string_to_string : tnode;
+ function typecheck_char_to_string : tnode;
+ function typecheck_char_to_chararray : tnode;
+ function typecheck_int_to_real : tnode;
+ function typecheck_real_to_real : tnode;
+ function typecheck_real_to_currency : tnode;
+ function typecheck_cchar_to_pchar : tnode;
+ function typecheck_cstring_to_pchar : tnode;
+ function typecheck_cstring_to_int : tnode;
+ function typecheck_char_to_char : tnode;
+ function typecheck_arrayconstructor_to_set : tnode;
+ function typecheck_set_to_set : tnode;
+ function typecheck_pchar_to_string : tnode;
+ function typecheck_interface_to_string : tnode;
+ function typecheck_interface_to_guid : tnode;
+ function typecheck_dynarray_to_openarray : tnode;
+ function typecheck_pwchar_to_string : tnode;
+ function typecheck_variant_to_dynarray : tnode;
+ function typecheck_dynarray_to_variant : tnode;
+ function typecheck_call_helper(c : tconverttype) : tnode;
+ function typecheck_variant_to_enum : tnode;
+ function typecheck_enum_to_variant : tnode;
+ function typecheck_proc_to_procvar : tnode;
+ function typecheck_variant_to_interface : tnode;
+ function typecheck_interface_to_variant : tnode;
+ function typecheck_array_2_dynarray : tnode;
+ protected
+ function first_int_to_int : tnode;virtual;
+ function first_cstring_to_pchar : tnode;virtual;
+ function first_cstring_to_int : tnode;virtual;
+ function first_string_to_chararray : tnode;virtual;
+ function first_char_to_string : tnode;virtual;
+ function first_nothing : tnode;virtual;
+ function first_array_to_pointer : tnode;virtual;
+ function first_int_to_real : tnode;virtual;
+ function first_real_to_real : tnode;virtual;
+ function first_pointer_to_array : tnode;virtual;
+ function first_cchar_to_pchar : tnode;virtual;
+ function first_bool_to_int : tnode;virtual;
+ function first_int_to_bool : tnode;virtual;
+ function first_bool_to_bool : tnode;virtual;
+ function first_proc_to_procvar : tnode;virtual;
+ function first_nil_to_methodprocvar : tnode;virtual;
+ function first_set_to_set : tnode;virtual;
+ function first_cord_to_pointer : tnode;virtual;
+ function first_ansistring_to_pchar : tnode;virtual;
+ function first_arrayconstructor_to_set : tnode;virtual;
+ function first_class_to_intf : tnode;virtual;
+ function first_char_to_char : tnode;virtual;
+ function first_string_to_string : tnode;virtual;
+ function first_call_helper(c : tconverttype) : tnode;
+
+ { these wrapper are necessary, because the first_* stuff is called }
+ { through a table. Without the wrappers override wouldn't have }
+ { any effect }
+ function _first_int_to_int : tnode;
+ function _first_cstring_to_pchar : tnode;
+ function _first_cstring_to_int : tnode;
+ function _first_string_to_chararray : tnode;
+ function _first_char_to_string : tnode;
+ function _first_nothing : tnode;
+ function _first_array_to_pointer : tnode;
+ function _first_int_to_real : tnode;
+ function _first_real_to_real: tnode;
+ function _first_pointer_to_array : tnode;
+ function _first_cchar_to_pchar : tnode;
+ function _first_bool_to_int : tnode;
+ function _first_int_to_bool : tnode;
+ function _first_bool_to_bool : tnode;
+ function _first_proc_to_procvar : tnode;
+ function _first_nil_to_methodprocvar : tnode;
+ function _first_cord_to_pointer : tnode;
+ function _first_ansistring_to_pchar : tnode;
+ function _first_arrayconstructor_to_set : tnode;
+ function _first_class_to_intf : tnode;
+ function _first_char_to_char : tnode;
+ function _first_set_to_set : tnode;
+ function _first_string_to_string : tnode;
+
+ procedure _second_int_to_int;virtual;
+ procedure _second_string_to_string;virtual;
+ procedure _second_cstring_to_pchar;virtual;
+ procedure _second_cstring_to_int;virtual;
+ procedure _second_string_to_chararray;virtual;
+ procedure _second_array_to_pointer;virtual;
+ procedure _second_pointer_to_array;virtual;
+ procedure _second_chararray_to_string;virtual;
+ procedure _second_char_to_string;virtual;
+ procedure _second_int_to_real;virtual;
+ procedure _second_real_to_real;virtual;
+ procedure _second_cord_to_pointer;virtual;
+ procedure _second_proc_to_procvar;virtual;
+ procedure _second_nil_to_methodprocvar;virtual;
+ procedure _second_bool_to_int;virtual;
+ procedure _second_int_to_bool;virtual;
+ procedure _second_bool_to_bool;virtual;
+ procedure _second_set_to_set;virtual;
+ procedure _second_ansistring_to_pchar;virtual;
+ procedure _second_class_to_intf;virtual;
+ procedure _second_char_to_char;virtual;
+ procedure _second_nothing; virtual;
+
+ procedure second_int_to_int;virtual;abstract;
+ procedure second_string_to_string;virtual;abstract;
+ procedure second_cstring_to_pchar;virtual;abstract;
+ procedure second_cstring_to_int;virtual;abstract;
+ procedure second_string_to_chararray;virtual;abstract;
+ procedure second_array_to_pointer;virtual;abstract;
+ procedure second_pointer_to_array;virtual;abstract;
+ procedure second_chararray_to_string;virtual;abstract;
+ procedure second_char_to_string;virtual;abstract;
+ procedure second_int_to_real;virtual;abstract;
+ procedure second_real_to_real;virtual;abstract;
+ procedure second_cord_to_pointer;virtual;abstract;
+ procedure second_proc_to_procvar;virtual;abstract;
+ procedure second_nil_to_methodprocvar;virtual;abstract;
+ procedure second_bool_to_int;virtual;abstract;
+ procedure second_int_to_bool;virtual;abstract;
+ procedure second_bool_to_bool;virtual;abstract;
+ procedure second_set_to_set;virtual;abstract;
+ procedure second_ansistring_to_pchar;virtual;abstract;
+ procedure second_class_to_intf;virtual;abstract;
+ procedure second_char_to_char;virtual;abstract;
+ procedure second_nothing; virtual;abstract;
+ end;
+ ttypeconvnodeclass = class of ttypeconvnode;
+
+ { common functionality of as-nodes and is-nodes }
+ tasisnode = class(tbinarynode)
+ public
+ function pass_typecheck:tnode;override;
+ end;
+
+ tasnode = class(tasisnode)
+ { as nodes cannot be translated directly into call nodes bcause:
+
+ When using -CR, explicit class typecasts are replaced with as-nodes to perform
+ class type checking. The problem is that if a typecasted class instance is
+ passed as a var-parameter, then you cannot replace it with a function call. So the as-node
+ a) call the as helper to perform the type checking
+ b) still pass the original instance as parameter to var-parameters
+ (and in general: to return it as the result of the as-node)
+
+ so the call field is required
+ }
+ call: tnode;
+ constructor create(l,r : tnode);virtual;
+ function pass_1 : tnode;override;
+ function dogetcopy: tnode;override;
+ function docompare(p: tnode): boolean; override;
+ destructor destroy; override;
+ end;
+ tasnodeclass = class of tasnode;
+
+ tisnode = class(tasisnode)
+ constructor create(l,r : tnode);virtual;
+ function pass_1 : tnode;override;
+ procedure pass_generate_code;override;
+ end;
+ tisnodeclass = class of tisnode;
+
+ var
+ ctypeconvnode : ttypeconvnodeclass = ttypeconvnode;
+ casnode : tasnodeclass = tasnode;
+ cisnode : tisnodeclass=tisnode;
+
+ procedure inserttypeconv(var p:tnode;def:tdef);
+ procedure inserttypeconv_explicit(var p:tnode;def:tdef);
+ procedure inserttypeconv_internal(var p:tnode;def:tdef);
+ procedure arrayconstructor_to_set(var p : tnode);
+ procedure insert_varargstypeconv(var p : tnode; iscvarargs: boolean);
+
+ function maybe_global_proc_to_nested(var fromnode: tnode; todef: tdef): boolean;
+
+
+implementation
+
+ uses
+ globtype,systems,constexp,
+ cutils,verbose,globals,widestr,
+ symconst,symdef,symsym,symbase,symtable,
+ ncon,ncal,nset,nadd,ninl,nmem,nmat,nbas,nutils,
+ cgbase,procinfo,
+ htypechk,pass_1,cpuinfo;
+
+
+{*****************************************************************************
+ Helpers
+*****************************************************************************}
+ type
+ ttypeconvnodetype = (tct_implicit,tct_explicit,tct_internal);
+
+ procedure do_inserttypeconv(var p: tnode;def: tdef; convtype: ttypeconvnodetype);
+
+ begin
+ if not assigned(p.resultdef) then
+ begin
+ typecheckpass(p);
+ if codegenerror then
+ exit;
+ end;
+
+ { don't insert superfluous type conversions, but
+ in case of bitpacked accesses, the original type must
+ remain too so that not too many/few bits are laoded }
+ if equal_defs(p.resultdef,def) and
+ not is_bitpacked_access(p) then
+ begin
+ { don't replace encoded string constants to rawbytestring encoding.
+ preserve the codepage }
+ if not (is_rawbytestring(def) and (p.nodetype=stringconstn)) then
+ p.resultdef:=def
+ end
+ else
+ begin
+ case convtype of
+ tct_implicit:
+ p:=ctypeconvnode.create(p,def);
+ tct_explicit:
+ p:=ctypeconvnode.create_explicit(p,def);
+ tct_internal:
+ p:=ctypeconvnode.create_internal(p,def);
+ end;
+ p.fileinfo:=ttypeconvnode(p).left.fileinfo;
+ typecheckpass(p);
+ end;
+ end;
+
+
+ procedure inserttypeconv(var p:tnode;def:tdef);
+
+ begin
+ do_inserttypeconv(p,def,tct_implicit);
+ end;
+
+
+ procedure inserttypeconv_explicit(var p: tnode; def: tdef);
+
+ begin
+ do_inserttypeconv(p,def,tct_explicit);
+ end;
+
+ procedure inserttypeconv_internal(var p:tnode;def:tdef);
+
+ begin
+ do_inserttypeconv(p,def,tct_internal);
+ end;
+
+
+{*****************************************************************************
+ Array constructor to Set Conversion
+*****************************************************************************}
+
+ procedure arrayconstructor_to_set(var p : tnode);
+
+ var
+ constp : tsetconstnode;
+ buildp,
+ p2,p3,p4 : tnode;
+ hdef : tdef;
+ constset : Pconstset;
+ constsetlo,
+ constsethi : TConstExprInt;
+
+ procedure update_constsethi(def:tdef; maybetruncenumrange: boolean);
+ begin
+ if (def.typ=orddef) and
+ ((torddef(def).high>=constsethi) or
+ (torddef(def).low <=constsetlo)) then
+ begin
+ if torddef(def).ordtype=uwidechar then
+ begin
+ constsethi:=255;
+ constsetlo:=0;
+ if hdef=nil then
+ hdef:=def;
+ end
+ else
+ begin
+ if (torddef(def).high>=constsethi) then
+ constsethi:=torddef(def).high;
+ if (torddef(def).low<=constsetlo) then
+ constsetlo:=torddef(def).low;
+ if hdef=nil then
+ begin
+ if (constsethi>255) or
+ (torddef(def).low<0) then
+ hdef:=u8inttype
+ else
+ hdef:=def;
+ end;
+ if constsethi>255 then
+ constsethi:=255;
+ if constsetlo<0 then
+ constsetlo:=0;
+ end;
+ end
+ else if (def.typ=enumdef) and
+ ((tenumdef(def).max>=constsethi) or
+ (tenumdef(def).min<=constsetlo)) then
+ begin
+ if hdef=nil then
+ hdef:=def;
+ if (tenumdef(def).max>=constsethi) then
+ constsethi:=tenumdef(def).max;
+ if (tenumdef(def).min<=constsetlo) then
+ constsetlo:=tenumdef(def).min;
+ { for constant set elements, delphi allows the usage of elements of enumerations which
+ have value>255 if there is no element with a value > 255 used }
+ if (maybetruncenumrange) then
+ begin
+ if constsethi>255 then
+ constsethi:=255;
+ if constsetlo<0 then
+ constsetlo:=0;
+ end;
+ end;
+ end;
+
+ procedure do_set(pos : longint);
+ begin
+ if (pos and not $ff)<>0 then
+ Message(parser_e_illegal_set_expr);
+ if pos>constsethi then
+ constsethi:=pos;
+ if pos<constsetlo then
+ constsetlo:=pos;
+ if pos in constset^ then
+ Message(parser_e_illegal_set_expr);
+ include(constset^,pos);
+ end;
+
+ var
+ l : Longint;
+ lr,hr : TConstExprInt;
+ hp : tarrayconstructornode;
+ oldfilepos: tfileposinfo;
+ begin
+ if p.nodetype<>arrayconstructorn then
+ internalerror(200205105);
+ new(constset);
+ constset^:=[];
+ hdef:=nil;
+ { make sure to set constsetlo correctly for empty sets }
+ if assigned(tarrayconstructornode(p).left) then
+ constsetlo:=high(aint)
+ else
+ constsetlo:=0;
+ constsethi:=0;
+ constp:=csetconstnode.create(nil,hdef);
+ constp.value_set:=constset;
+ buildp:=constp;
+ hp:=tarrayconstructornode(p);
+ if assigned(hp.left) then
+ begin
+ while assigned(hp) do
+ begin
+ p4:=nil; { will contain the tree to create the set }
+ {split a range into p2 and p3 }
+ if hp.left.nodetype=arrayconstructorrangen then
+ begin
+ p2:=tarrayconstructorrangenode(hp.left).left;
+ p3:=tarrayconstructorrangenode(hp.left).right;
+ tarrayconstructorrangenode(hp.left).left:=nil;
+ tarrayconstructorrangenode(hp.left).right:=nil;
+ end
+ else
+ begin
+ p2:=hp.left;
+ hp.left:=nil;
+ p3:=nil;
+ end;
+ typecheckpass(p2);
+ set_varstate(p2,vs_read,[vsf_must_be_valid]);
+ if assigned(p3) then
+ begin
+ typecheckpass(p3);
+ set_varstate(p3,vs_read,[vsf_must_be_valid]);
+ end;
+ if codegenerror then
+ break;
+ oldfilepos:=current_filepos;
+ current_filepos:=p2.fileinfo;
+ case p2.resultdef.typ of
+ enumdef,
+ orddef:
+ begin
+ { widechars are not yet supported }
+ if is_widechar(p2.resultdef) then
+ begin
+ inserttypeconv(p2,cchartype);
+ if (p2.nodetype<>ordconstn) then
+ incompatibletypes(cwidechartype,cchartype);
+ end;
+
+ getrange(p2.resultdef,lr,hr);
+ if assigned(p3) then
+ begin
+ if is_widechar(p3.resultdef) then
+ begin
+ inserttypeconv(p3,cchartype);
+ if (p3.nodetype<>ordconstn) then
+ begin
+ current_filepos:=p3.fileinfo;
+ incompatibletypes(cwidechartype,cchartype);
+ end;
+ end;
+ { this isn't good, you'll get problems with
+ type t010 = 0..10;
+ ts = set of t010;
+ var s : ts;b : t010
+ begin s:=[1,2,b]; end.
+ if is_integer(p3^.resultdef) then
+ begin
+ inserttypeconv(p3,u8bitdef);
+ end;
+ }
+ if assigned(hdef) and not(equal_defs(hdef,p3.resultdef)) then
+ begin
+ CGMessagePos(p3.fileinfo,type_e_typeconflict_in_set);
+ end
+ else
+ begin
+ if (p2.nodetype=ordconstn) and (p3.nodetype=ordconstn) then
+ begin
+ if not(is_integer(p3.resultdef)) then
+ hdef:=p3.resultdef
+ else
+ begin
+ inserttypeconv(p3,u8inttype);
+ inserttypeconv(p2,u8inttype);
+ end;
+
+ for l:=tordconstnode(p2).value.svalue to tordconstnode(p3).value.svalue do
+ do_set(l);
+ p2.free;
+ p3.free;
+ end
+ else
+ begin
+ update_constsethi(p2.resultdef,false);
+ inserttypeconv(p2,hdef);
+
+ update_constsethi(p3.resultdef,false);
+ inserttypeconv(p3,hdef);
+
+ if assigned(hdef) then
+ inserttypeconv(p3,hdef)
+ else
+ inserttypeconv(p3,u8inttype);
+ p4:=csetelementnode.create(p2,p3);
+ end;
+ end;
+ end
+ else
+ begin
+ { Single value }
+ if p2.nodetype=ordconstn then
+ begin
+ if not(is_integer(p2.resultdef)) then
+ update_constsethi(p2.resultdef,true);
+
+ if assigned(hdef) then
+ inserttypeconv(p2,hdef)
+ else
+ inserttypeconv(p2,u8inttype);
+
+ do_set(tordconstnode(p2).value.svalue);
+ p2.free;
+ end
+ else
+ begin
+ update_constsethi(p2.resultdef,false);
+
+ if assigned(hdef) then
+ inserttypeconv(p2,hdef)
+ else
+ inserttypeconv(p2,u8inttype);
+
+ p4:=csetelementnode.create(p2,nil);
+ end;
+ end;
+ end;
+
+ stringdef :
+ begin
+ if (p2.nodetype<>stringconstn) then
+ Message(parser_e_illegal_expression)
+ { if we've already set elements which are constants }
+ { throw an error }
+ else if ((hdef=nil) and assigned(buildp)) or
+ not(is_char(hdef)) then
+ CGMessage(type_e_typeconflict_in_set)
+ else
+ for l:=1 to length(pshortstring(tstringconstnode(p2).value_str)^) do
+ do_set(ord(pshortstring(tstringconstnode(p2).value_str)^[l]));
+ if hdef=nil then
+ hdef:=cchartype;
+ p2.free;
+ end;
+
+ else
+ CGMessage(type_e_ordinal_expr_expected);
+ end;
+ { insert the set creation tree }
+ if assigned(p4) then
+ buildp:=caddnode.create(addn,buildp,p4);
+ { load next and dispose current node }
+ p2:=hp;
+ hp:=tarrayconstructornode(tarrayconstructornode(p2).right);
+ tarrayconstructornode(p2).right:=nil;
+ p2.free;
+ current_filepos:=oldfilepos;
+ end;
+ if (hdef=nil) then
+ hdef:=u8inttype;
+ end
+ else
+ begin
+ { empty set [], only remove node }
+ p.free;
+ end;
+ { set the initial set type }
+ constp.resultdef:=tsetdef.create(hdef,constsetlo.svalue,constsethi.svalue);
+ { determine the resultdef for the tree }
+ typecheckpass(buildp);
+ { set the new tree }
+ p:=buildp;
+ end;
+
+
+ procedure insert_varargstypeconv(var p : tnode; iscvarargs: boolean);
+ begin
+ { procvars without arguments in variant arrays are always called by
+ Delphi }
+ if not(iscvarargs) then
+ maybe_call_procvar(p,true);
+ if not(iscvarargs) and
+ (p.nodetype=stringconstn) and
+ { don't cast to AnsiString if already casted to Wide/UnicodeString, issue #18266 }
+ (tstringconstnode(p).cst_type in [cst_conststring,cst_shortstring,cst_longstring]) then
+ p:=ctypeconvnode.create_internal(p,getansistringdef)
+ else
+ case p.resultdef.typ of
+ enumdef :
+ p:=ctypeconvnode.create_internal(p,s32inttype);
+ arraydef :
+ begin
+ if is_chararray(p.resultdef) then
+ p:=ctypeconvnode.create_internal(p,charpointertype)
+ else
+ if is_widechararray(p.resultdef) then
+ p:=ctypeconvnode.create_internal(p,widecharpointertype)
+ else
+ CGMessagePos1(p.fileinfo,type_e_wrong_type_in_array_constructor,p.resultdef.typename);
+ end;
+ orddef :
+ begin
+ if is_integer(p.resultdef) and
+ not(is_64bitint(p.resultdef)) then
+ if not(m_delphi in current_settings.modeswitches) then
+ p:=ctypeconvnode.create(p,s32inttype)
+ else
+ { delphi doesn't generate a range error when passing a
+ cardinal >= $80000000, but since these are seen as
+ longint on the callee side, this causes data loss;
+ as a result, we require an explicit longint()
+ typecast in FPC mode on the caller side if range
+ checking should be disabled, but not in Delphi mode }
+ p:=ctypeconvnode.create_internal(p,s32inttype)
+ else if is_void(p.resultdef) then
+ CGMessagePos1(p.fileinfo,type_e_wrong_type_in_array_constructor,p.resultdef.typename)
+ else if iscvarargs and is_currency(p.resultdef)
+ and (current_settings.fputype<>fpu_none) then
+ p:=ctypeconvnode.create(p,s64floattype);
+ end;
+ floatdef :
+ if not(iscvarargs) then
+ begin
+ if not(is_currency(p.resultdef)) then
+ p:=ctypeconvnode.create(p,pbestrealtype^);
+ end
+ else
+ begin
+ if is_constrealnode(p) and
+ not(nf_explicit in p.flags) then
+ MessagePos(p.fileinfo,type_w_double_c_varargs);
+ if (tfloatdef(p.resultdef).floattype in [s32real,s64currency]) or
+ (is_constrealnode(p) and
+ not(nf_explicit in p.flags)) then
+ p:=ctypeconvnode.create(p,s64floattype);
+ end;
+ procvardef :
+ p:=ctypeconvnode.create(p,voidpointertype);
+ stringdef:
+ if iscvarargs then
+ p:=ctypeconvnode.create(p,charpointertype);
+ variantdef:
+ if iscvarargs then
+ CGMessagePos1(p.fileinfo,type_e_wrong_type_in_array_constructor,p.resultdef.typename);
+ { maybe warn in case it's not using "packrecords c"? }
+ recorddef:
+ if not iscvarargs then
+ CGMessagePos1(p.fileinfo,type_e_wrong_type_in_array_constructor,p.resultdef.typename);
+ pointerdef:
+ ;
+ classrefdef:
+ if iscvarargs then
+ p:=ctypeconvnode.create(p,voidpointertype);
+ objectdef :
+ if (iscvarargs and
+ not is_objc_class_or_protocol(p.resultdef)) or
+ is_object(p.resultdef) then
+ CGMessagePos1(p.fileinfo,type_e_wrong_type_in_array_constructor,p.resultdef.typename);
+ else
+ CGMessagePos1(p.fileinfo,type_e_wrong_type_in_array_constructor,p.resultdef.typename);
+ end;
+ typecheckpass(p);
+ end;
+
+
+ { in FPC mode, @procname immediately has to be evaluated as a
+ procvar. If procname is global, then this will be a global
+ procvar. Since converting global procvars to local procvars is
+ not allowed (see point d in defcmp.proc_to_procvar_equal()),
+ this results in errors when passing global procedures to local
+ procvar parameters or assigning them to nested procvars. The
+ solution is to remove the (wrong) conversion to a global procvar,
+ and instead insert a conversion to the local procvar type. }
+ function maybe_global_proc_to_nested(var fromnode: tnode; todef: tdef): boolean;
+ var
+ hp: tnode;
+ begin
+ result:=false;
+ if (m_nested_procvars in current_settings.modeswitches) and
+ not(m_tp_procvar in current_settings.modeswitches) and
+ (todef.typ=procvardef) and
+ is_nested_pd(tprocvardef(todef)) and
+ (fromnode.nodetype=typeconvn) and
+ (ttypeconvnode(fromnode).convtype=tc_proc_2_procvar) and
+ not is_nested_pd(tprocvardef(fromnode.resultdef)) and
+ (proc_to_procvar_equal(tprocdef(ttypeconvnode(fromnode).left.resultdef),tprocvardef(todef),false)>=te_convert_l1) then
+ begin
+ hp:=fromnode;
+ fromnode:=ctypeconvnode.create_proc_to_procvar(ttypeconvnode(fromnode).left);
+ ttypeconvnode(fromnode).totypedef:=todef;
+ typecheckpass(fromnode);
+ ttypeconvnode(hp).left:=nil;
+ hp.free;
+ result:=true;
+ end;
+ end;
+
+{*****************************************************************************
+ TTYPECONVNODE
+*****************************************************************************}
+
+
+ constructor ttypeconvnode.create(node : tnode;def:tdef);
+
+ begin
+ inherited create(typeconvn,node);
+ convtype:=tc_none;
+ totypedef:=def;
+ if def=nil then
+ internalerror(200103281);
+ fileinfo:=node.fileinfo;
+ {An attempt to convert the result of a floating point division
+ (with the / operator) to an integer type will fail. Give a hint
+ to use the div operator.}
+ if (node.nodetype=slashn) and (def.typ=orddef) then
+ cgmessage(type_h_use_div_for_int);
+ {In expressions like int64:=longint+longint, an integer overflow could be avoided
+ by simply converting the operands to int64 first. Give a hint to do this.}
+ if (node.nodetype in [addn,subn,muln]) and
+ (def.typ=orddef) and (node.resultdef<>nil) and (node.resultdef.typ=orddef) and
+ ((Torddef(node.resultdef).low>=Torddef(def).low) and (Torddef(node.resultdef).high<=Torddef(def).high)) and
+ ((Torddef(node.resultdef).low>Torddef(def).low) or (Torddef(node.resultdef).high<Torddef(def).high)) then
+ case node.nodetype of
+ addn:
+ cgmessage1(type_h_convert_add_operands_to_prevent_overflow,def.typename);
+ subn:
+ cgmessage1(type_h_convert_sub_operands_to_prevent_overflow,def.typename);
+ muln:
+ cgmessage1(type_h_convert_mul_operands_to_prevent_overflow,def.typename);
+ end;
+ end;
+
+
+ constructor ttypeconvnode.create_explicit(node : tnode;def:tdef);
+
+ begin
+ self.create(node,def);
+ include(flags,nf_explicit);
+ end;
+
+
+ constructor ttypeconvnode.create_internal(node : tnode;def:tdef);
+
+ begin
+ self.create(node,def);
+ { handle like explicit conversions }
+ include(flags,nf_explicit);
+ include(flags,nf_internal);
+ end;
+
+
+ constructor ttypeconvnode.create_proc_to_procvar(node : tnode);
+
+ begin
+ self.create(node,voidtype);
+ convtype:=tc_proc_2_procvar;
+ end;
+
+
+ constructor ttypeconvnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ ppufile.getderef(totypedefderef);
+ convtype:=tconverttype(ppufile.getbyte);
+ end;
+
+
+ procedure ttypeconvnode.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putderef(totypedefderef);
+ ppufile.putbyte(byte(convtype));
+ end;
+
+
+ procedure ttypeconvnode.buildderefimpl;
+ begin
+ inherited buildderefimpl;
+ totypedefderef.build(totypedef);
+ end;
+
+
+ procedure ttypeconvnode.derefimpl;
+ begin
+ inherited derefimpl;
+ totypedef:=tdef(totypedefderef.resolve);
+ end;
+
+
+ function ttypeconvnode.dogetcopy : tnode;
+ var
+ n : ttypeconvnode;
+ begin
+ n:=ttypeconvnode(inherited dogetcopy);
+ n.convtype:=convtype;
+ n.totypedef:=totypedef;
+ dogetcopy:=n;
+ end;
+
+ procedure ttypeconvnode.printnodeinfo(var t : text);
+ const
+ convtyp2str : array[tconverttype] of pchar = (
+ 'tc_none',
+ 'tc_equal',
+ 'tc_not_possible',
+ 'tc_string_2_string',
+ 'tc_char_2_string',
+ 'tc_char_2_chararray',
+ 'tc_pchar_2_string',
+ 'tc_cchar_2_pchar',
+ 'tc_cstring_2_pchar',
+ 'tc_cstring_2_int',
+ 'tc_ansistring_2_pchar',
+ 'tc_string_2_chararray',
+ 'tc_chararray_2_string',
+ 'tc_array_2_pointer',
+ 'tc_pointer_2_array',
+ 'tc_int_2_int',
+ 'tc_int_2_bool',
+ 'tc_bool_2_bool',
+ 'tc_bool_2_int',
+ 'tc_real_2_real',
+ 'tc_int_2_real',
+ 'tc_real_2_currency',
+ 'tc_proc_2_procvar',
+ 'tc_nil_2_methodprocvar',
+ 'tc_arrayconstructor_2_set',
+ 'tc_set_2_set',
+ 'tc_cord_2_pointer',
+ 'tc_intf_2_string',
+ 'tc_intf_2_guid',
+ 'tc_class_2_intf',
+ 'tc_char_2_char',
+ 'tc_dynarray_2_openarray',
+ 'tc_pwchar_2_string',
+ 'tc_variant_2_dynarray',
+ 'tc_dynarray_2_variant',
+ 'tc_variant_2_enum',
+ 'tc_enum_2_variant',
+ 'tc_interface_2_variant',
+ 'tc_variant_2_interface',
+ 'tc_array_2_dynarray'
+ );
+ begin
+ inherited printnodeinfo(t);
+ write(t,', convtype = ',strpas(convtyp2str[convtype]));
+ end;
+
+
+ function ttypeconvnode.typecheck_cord_to_pointer : tnode;
+
+ begin
+ result:=nil;
+ if left.nodetype=ordconstn then
+ begin
+ { check if we have a valid pointer constant (JM) }
+ {$if sizeof(pointer) > sizeof(TConstPtrUInt)}
+ {$if sizeof(TConstPtrUInt) = 4}
+ if (tordconstnode(left).value < int64(low(longint))) or
+ (tordconstnode(left).value > int64(high(cardinal))) then
+ CGMessage(parser_e_range_check_error);
+ {$else} {$if sizeof(TConstPtrUInt) = 8}
+ if (tordconstnode(left).value < int64(low(int64))) or
+ (tordconstnode(left).value > int64(high(qword))) then
+ CGMessage(parser_e_range_check_error);
+ {$else}
+ internalerror(2001020801);
+ {$endif} {$endif}
+ {$endif}
+
+ if not(nf_explicit in flags) then
+ if (tordconstnode(left).value.svalue=0) then
+ CGMessage(type_w_zero_to_nil)
+ else
+ { in Delphi mode, these aren't caught in compare_defs_ext }
+ IncompatibleTypes(left.resultdef,resultdef);
+ result:=cpointerconstnode.create(TConstPtrUInt(tordconstnode(left).value.uvalue),resultdef);
+ end
+ else
+ internalerror(200104023);
+ end;
+
+
+ function ttypeconvnode.typecheck_chararray_to_string : tnode;
+ var
+ chartype : string[8];
+ newblock : tblocknode;
+ newstat : tstatementnode;
+ restemp : ttempcreatenode;
+ begin
+ if is_widechar(tarraydef(left.resultdef).elementdef) then
+ chartype:='widechar'
+ else
+ chartype:='char';
+ if tstringdef(resultdef).stringtype=st_shortstring then
+ begin
+ newblock:=internalstatements(newstat);
+ restemp:=ctempcreatenode.create(resultdef,resultdef.size,tt_persistent,false);
+ addstatement(newstat,restemp);
+ addstatement(newstat,ccallnode.createintern('fpc_'+chartype+'array_to_shortstr',
+ ccallparanode.create(cordconstnode.create(
+ ord(tarraydef(left.resultdef).lowrange=0),pasbool8type,false),
+ ccallparanode.create(left,ccallparanode.create(
+ ctemprefnode.create(restemp),nil)))));
+ addstatement(newstat,ctempdeletenode.create_normal_temp(restemp));
+ addstatement(newstat,ctemprefnode.create(restemp));
+ result:=newblock;
+ end
+ else if (tstringdef(resultdef).stringtype=st_ansistring) then
+ begin
+ result:=ccallnode.createinternres(
+ 'fpc_'+chartype+'array_to_'+tstringdef(resultdef).stringtypname,
+ ccallparanode.create(
+ cordconstnode.create(
+ ord(tarraydef(left.resultdef).lowrange=0),
+ pasbool8type,
+ false
+ ),
+ ccallparanode.create(
+ cordconstnode.create(
+ getparaencoding(resultdef),
+ u16inttype,
+ true
+ ),
+ ccallparanode.create(left,nil)
+ )
+ ),
+ resultdef
+ );
+ end
+ else
+ result:=ccallnode.createinternres(
+ 'fpc_'+chartype+'array_to_'+tstringdef(resultdef).stringtypname,
+ ccallparanode.create(cordconstnode.create(
+ ord(tarraydef(left.resultdef).lowrange=0),pasbool8type,false),
+ ccallparanode.create(left,nil)),resultdef);
+ left:=nil;
+ end;
+
+
+ function ttypeconvnode.typecheck_string_to_chararray : tnode;
+ var
+ newblock : tblocknode;
+ newstat : tstatementnode;
+ restemp : ttempcreatenode;
+ pchtemp : pchar;
+ arrsize : aint;
+ chartype : string[8];
+ begin
+ result := nil;
+ with tarraydef(resultdef) do
+ begin
+ if highrange<lowrange then
+ internalerror(200501051);
+ arrsize := highrange-lowrange+1;
+ end;
+ if (left.nodetype = stringconstn) and
+ (tstringconstnode(left).cst_type=cst_conststring) then
+ begin
+ { if the array of char is large enough we can use the string
+ constant directly. This is handled in ncgcnv }
+ if (arrsize>=tstringconstnode(left).len) and
+ is_char(tarraydef(resultdef).elementdef) then
+ begin
+ { pad the constant string with #0 to the array len }
+ { (2.0.x compatible) }
+ if (arrsize>tstringconstnode(left).len) then
+ begin
+ pchtemp:=concatansistrings(tstringconstnode(left).value_str,pchar(StringOfChar(#0,arrsize-tstringconstnode(left).len)),tstringconstnode(left).len,arrsize-tstringconstnode(left).len);
+ left.free;
+ left:=cstringconstnode.createpchar(pchtemp,arrsize);
+ typecheckpass(left);
+ end;
+ exit;
+ end;
+ { Convert to wide/short/ansistring and call default helper }
+ if is_widechar(tarraydef(resultdef).elementdef) then
+ inserttypeconv(left,cwidestringtype)
+ else
+ begin
+ if tstringconstnode(left).len>255 then
+ inserttypeconv(left,getansistringdef)
+ else
+ inserttypeconv(left,cshortstringtype);
+ end;
+ end;
+ if is_widechar(tarraydef(resultdef).elementdef) then
+ chartype:='widechar'
+ else
+ chartype:='char';
+ newblock:=internalstatements(newstat);
+ restemp:=ctempcreatenode.create(resultdef,resultdef.size,tt_persistent,false);
+ addstatement(newstat,restemp);
+ addstatement(newstat,ccallnode.createintern('fpc_'+tstringdef(left.resultdef).stringtypname+
+ '_to_'+chartype+'array',ccallparanode.create(left,ccallparanode.create(
+ ctemprefnode.create(restemp),nil))));
+ addstatement(newstat,ctempdeletenode.create_normal_temp(restemp));
+ addstatement(newstat,ctemprefnode.create(restemp));
+ result:=newblock;
+ left:=nil;
+ end;
+
+
+ function ttypeconvnode.typecheck_char_to_string : tnode;
+ var
+ procname: string[31];
+ para : tcallparanode;
+ hp : tstringconstnode;
+ ws : pcompilerwidestring;
+ newblock : tblocknode;
+ newstat : tstatementnode;
+ restemp : ttempcreatenode;
+ sa : ansistring;
+ cw : tcompilerwidechar;
+ l : SizeUInt;
+ begin
+ result:=nil;
+ if (left.nodetype=ordconstn) and
+ ((tstringdef(resultdef).stringtype in [st_widestring,st_unicodestring,st_ansistring]) or
+ (torddef(left.resultdef).ordtype in [uchar,uwidechar])) then
+ begin
+ if (tstringdef(resultdef).stringtype in [st_widestring,st_unicodestring]) then
+ begin
+ initwidestring(ws);
+ if torddef(left.resultdef).ordtype=uwidechar then
+ concatwidestringchar(ws,tcompilerwidechar(tordconstnode(left).value.uvalue))
+ else
+ concatwidestringchar(ws,asciichar2unicode(chr(tordconstnode(left).value.uvalue)));
+ hp:=cstringconstnode.createwstr(ws);
+ hp.changestringtype(resultdef);
+ donewidestring(ws);
+ end
+ else
+ begin
+ if (torddef(left.resultdef).ordtype=uwidechar) then
+ begin
+ if (current_settings.sourcecodepage<>CP_UTF8) then
+ begin
+ if tordconstnode(left).value.uvalue>127 then
+ Message(type_w_unicode_data_loss);
+ hp:=cstringconstnode.createstr(unicode2asciichar(tcompilerwidechar(tordconstnode(left).value.uvalue)));
+ end
+ else
+ begin
+ cw:=tcompilerwidechar(tordconstnode(left).value.uvalue);
+ SetLength(sa,5);
+ l:=UnicodeToUtf8(@(sa[1]),Length(sa),@cw,1);
+ SetLength(sa,l-1);
+ hp:=cstringconstnode.createstr(sa);
+ end
+ end
+ else
+ hp:=cstringconstnode.createstr(chr(tordconstnode(left).value.uvalue));
+ { output string consts in local ansistring encoding }
+ if is_ansistring(resultdef) and ((tstringdef(resultdef).encoding=0) or (tstringdef(resultdef).encoding=globals.CP_NONE)) then
+ tstringconstnode(hp).changestringtype(getansistringdef)
+ else
+ tstringconstnode(hp).changestringtype(resultdef);
+ end;
+ result:=hp;
+ end
+ else
+ { shortstrings are handled 'inline' (except for widechars) }
+ if (tstringdef(resultdef).stringtype<>st_shortstring) or
+ (torddef(left.resultdef).ordtype=uwidechar) then
+ begin
+ if (tstringdef(resultdef).stringtype<>st_shortstring) then
+ begin
+ { parameter }
+ para:=ccallparanode.create(left,nil);
+ { encoding required? }
+ if tstringdef(resultdef).stringtype=st_ansistring then
+ para:=ccallparanode.create(cordconstnode.create(getparaencoding(resultdef),u16inttype,true),para);
+
+ { create the procname }
+ if torddef(left.resultdef).ordtype<>uwidechar then
+ begin
+ procname:='fpc_char_to_';
+ if tstringdef(resultdef).stringtype in [st_widestring,st_unicodestring] then
+ if nf_explicit in flags then
+ Message2(type_w_explicit_string_cast,left.resultdef.typename,resultdef.typename)
+ else
+ Message2(type_w_implicit_string_cast,left.resultdef.typename,resultdef.typename);
+ end
+ else
+ begin
+ procname:='fpc_uchar_to_';
+ if not (tstringdef(resultdef).stringtype in [st_widestring,st_unicodestring]) then
+ if nf_explicit in flags then
+ Message2(type_w_explicit_string_cast_loss,left.resultdef.typename,resultdef.typename)
+ else
+ Message2(type_w_implicit_string_cast_loss,left.resultdef.typename,resultdef.typename);
+ end;
+ procname:=procname+tstringdef(resultdef).stringtypname;
+
+ { and finally the call }
+ result:=ccallnode.createinternres(procname,para,resultdef);
+ end
+ else
+ begin
+ if nf_explicit in flags then
+ Message2(type_w_explicit_string_cast_loss,left.resultdef.typename,resultdef.typename)
+ else
+ Message2(type_w_implicit_string_cast_loss,left.resultdef.typename,resultdef.typename);
+ newblock:=internalstatements(newstat);
+ restemp:=ctempcreatenode.create(resultdef,resultdef.size,tt_persistent,false);
+ addstatement(newstat,restemp);
+ addstatement(newstat,ccallnode.createintern('fpc_wchar_to_shortstr',ccallparanode.create(left,ccallparanode.create(
+ ctemprefnode.create(restemp),nil))));
+ addstatement(newstat,ctempdeletenode.create_normal_temp(restemp));
+ addstatement(newstat,ctemprefnode.create(restemp));
+ result:=newblock;
+ end;
+ left := nil;
+ end
+ else
+ begin
+ { create word(byte(char) shl 8 or 1) for litte endian machines }
+ { and word(byte(char) or 256) for big endian machines }
+ left := ctypeconvnode.create_internal(left,u8inttype);
+ if (target_info.endian = endian_little) then
+ left := caddnode.create(orn,
+ cshlshrnode.create(shln,left,cordconstnode.create(8,s32inttype,false)),
+ cordconstnode.create(1,s32inttype,false))
+ else
+ left := caddnode.create(orn,left,
+ cordconstnode.create(1 shl 8,s32inttype,false));
+ left := ctypeconvnode.create_internal(left,u16inttype);
+ typecheckpass(left);
+ end;
+ end;
+
+ function ttypeconvnode.typecheck_string_to_string : tnode;
+ begin
+ result:=nil;
+ if (left.nodetype=stringconstn) and
+ (((tstringdef(resultdef).stringtype=st_ansistring) and
+ (tstringdef(resultdef).encoding<>CP_NONE)
+ )
+ ) and
+ (tstringdef(left.resultdef).stringtype in [st_unicodestring,st_widestring]) then
+ begin
+ tstringconstnode(left).changestringtype(resultdef);
+ Result:=left;
+ left:=nil;
+ end
+ else if (tstringdef(resultdef).stringtype=st_ansistring) and
+ (tstringdef(left.resultdef).stringtype=st_ansistring) and
+ (tstringdef(resultdef).encoding<>tstringdef(left.resultdef).encoding) then
+ begin
+ result:=ccallnode.createinternres(
+ 'fpc_ansistr_to_ansistr',
+ ccallparanode.create(
+ cordconstnode.create(
+ tstringdef(resultdef).encoding,
+ u16inttype,
+ true
+ ),
+ ccallparanode.create(left,nil)
+ ),
+ resultdef
+ );
+ left:=nil;
+ end
+ else if (left.nodetype=stringconstn) and
+ (tstringdef(left.resultdef).stringtype in [st_unicodestring,st_widestring]) and
+ (tstringdef(resultdef).stringtype=st_shortstring) then
+ begin
+ if not hasnonasciichars(pcompilerwidestring(tstringconstnode(left).value_str)) then
+ begin
+ tstringconstnode(left).changestringtype(resultdef);
+ Result:=left;
+ left:=nil;
+ end;
+ end
+ else if (tstringdef(left.resultdef).stringtype in [st_unicodestring,st_widestring]) and
+ not (tstringdef(resultdef).stringtype in [st_unicodestring,st_widestring]) then
+ begin
+ if nf_explicit in flags then
+ Message2(type_w_explicit_string_cast_loss,left.resultdef.typename,resultdef.typename)
+ else
+ Message2(type_w_implicit_string_cast_loss,left.resultdef.typename,resultdef.typename);
+ end
+ else if not (tstringdef(left.resultdef).stringtype in [st_unicodestring,st_widestring]) and
+ (tstringdef(resultdef).stringtype in [st_unicodestring,st_widestring]) then
+ begin
+ if nf_explicit in flags then
+ Message2(type_w_explicit_string_cast,left.resultdef.typename,resultdef.typename)
+ else
+ Message2(type_w_implicit_string_cast,left.resultdef.typename,resultdef.typename);
+ end
+ end;
+
+ function ttypeconvnode.typecheck_char_to_chararray : tnode;
+ begin
+ if resultdef.size <> 1 then
+ begin
+ { convert first to string, then to chararray }
+ inserttypeconv(left,cshortstringtype);
+ inserttypeconv(left,resultdef);
+ result:=left;
+ left := nil;
+ exit;
+ end;
+ result := nil;
+ end;
+
+
+ function ttypeconvnode.typecheck_char_to_char : tnode;
+ var
+ hp : tordconstnode;
+ begin
+ result:=nil;
+ if (left.nodetype=ordconstn) and
+ ((torddef(resultdef).ordtype<>uchar) or
+ (torddef(left.resultdef).ordtype<>uwidechar) or
+ (current_settings.sourcecodepage<>CP_UTF8))
+ then
+ begin
+ if (torddef(resultdef).ordtype=uchar) and
+ (torddef(left.resultdef).ordtype=uwidechar) and
+ (current_settings.sourcecodepage<>CP_UTF8) then
+ begin
+ if tordconstnode(left).value.uvalue>127 then
+ Message(type_w_unicode_data_loss);
+ hp:=cordconstnode.create(
+ ord(unicode2asciichar(tcompilerwidechar(tordconstnode(left).value.uvalue))),
+ cchartype,true);
+ result:=hp;
+ end
+ else if (torddef(resultdef).ordtype=uwidechar) and
+ (torddef(left.resultdef).ordtype=uchar) then
+ begin
+ hp:=cordconstnode.create(
+ asciichar2unicode(chr(tordconstnode(left).value.uvalue)),
+ cwidechartype,true);
+ result:=hp;
+ end
+ else
+ internalerror(200105131);
+ exit;
+ end;
+ end;
+
+
+ function ttypeconvnode.typecheck_int_to_int : tnode;
+ var
+ v : TConstExprInt;
+ begin
+ result:=nil;
+ if left.nodetype=ordconstn then
+ begin
+ v:=tordconstnode(left).value;
+ if is_currency(resultdef) then
+ v:=v*10000;
+ if (resultdef.typ=pointerdef) then
+ result:=cpointerconstnode.create(TConstPtrUInt(v.uvalue),resultdef)
+ else
+ begin
+ if is_currency(left.resultdef) then
+ v:=v div 10000;
+ result:=cordconstnode.create(v,resultdef,false);
+ end;
+ end
+ else if left.nodetype=pointerconstn then
+ begin
+ v:=tpointerconstnode(left).value;
+ if (resultdef.typ=pointerdef) then
+ result:=cpointerconstnode.create(v.uvalue,resultdef)
+ else
+ begin
+ if is_currency(resultdef) then
+ v:=v*10000;
+ result:=cordconstnode.create(v,resultdef,false);
+ end;
+ end
+ else
+ begin
+ { multiply by 10000 for currency. We need to use getcopy to pass
+ the argument because the current node is always disposed. Only
+ inserting the multiply in the left node is not possible because
+ it'll get in an infinite loop to convert int->currency }
+ if is_currency(resultdef) then
+ begin
+ result:=caddnode.create(muln,getcopy,cordconstnode.create(10000,resultdef,false));
+ include(result.flags,nf_is_currency);
+ end
+ else if is_currency(left.resultdef) then
+ begin
+ result:=cmoddivnode.create(divn,getcopy,cordconstnode.create(10000,resultdef,false));
+ include(result.flags,nf_is_currency);
+ end;
+ end;
+ end;
+
+
+ function ttypeconvnode.typecheck_int_to_real : tnode;
+ var
+ rv : bestreal;
+ begin
+ result:=nil;
+ if left.nodetype=ordconstn then
+ begin
+ rv:=tordconstnode(left).value;
+ if is_currency(resultdef) then
+ rv:=rv*10000.0
+ else if is_currency(left.resultdef) then
+ rv:=rv/10000.0;
+ result:=crealconstnode.create(rv,resultdef);
+ end
+ else
+ begin
+ { multiply by 10000 for currency. We need to use getcopy to pass
+ the argument because the current node is always disposed. Only
+ inserting the multiply in the left node is not possible because
+ it'll get in an infinite loop to convert int->currency }
+ if is_currency(resultdef) then
+ begin
+ result:=caddnode.create(muln,getcopy,crealconstnode.create(10000.0,resultdef));
+ include(result.flags,nf_is_currency);
+ end
+ else if is_currency(left.resultdef) then
+ begin
+ result:=caddnode.create(slashn,getcopy,crealconstnode.create(10000.0,resultdef));
+ include(result.flags,nf_is_currency);
+ end;
+ end;
+ end;
+
+
+ function ttypeconvnode.typecheck_real_to_currency : tnode;
+ begin
+ if not is_currency(resultdef) then
+ internalerror(200304221);
+ result:=nil;
+ left:=caddnode.create(muln,left,crealconstnode.create(10000.0,left.resultdef));
+ include(left.flags,nf_is_currency);
+ typecheckpass(left);
+ { Convert constants directly, else call Round() }
+ if left.nodetype=realconstn then
+ result:=cordconstnode.create(round(trealconstnode(left).value_real),resultdef,false)
+ else
+ begin
+ result:=ccallnode.createinternres('fpc_round_real',
+ ccallparanode.create(left,nil),resultdef);
+ left:=nil;
+ end;
+ end;
+
+
+ function ttypeconvnode.typecheck_real_to_real : tnode;
+ begin
+ result:=nil;
+ if is_currency(left.resultdef) and not(is_currency(resultdef)) then
+ begin
+ left:=caddnode.create(slashn,left,crealconstnode.create(10000.0,left.resultdef));
+ include(left.flags,nf_is_currency);
+ typecheckpass(left);
+ end
+ else
+ if is_currency(resultdef) and not(is_currency(left.resultdef)) then
+ begin
+ left:=caddnode.create(muln,left,crealconstnode.create(10000.0,left.resultdef));
+ include(left.flags,nf_is_currency);
+ typecheckpass(left);
+ end;
+ end;
+
+
+ function ttypeconvnode.typecheck_cchar_to_pchar : tnode;
+
+ begin
+ result:=nil;
+ if is_pwidechar(resultdef) then
+ inserttypeconv(left,cwidestringtype)
+ else
+ inserttypeconv(left,cshortstringtype);
+ { evaluate again, reset resultdef so the convert_typ
+ will be calculated again and cstring_to_pchar will
+ be used for futher conversion }
+ convtype:=tc_none;
+ result:=pass_typecheck;
+ end;
+
+
+ function ttypeconvnode.typecheck_cstring_to_pchar : tnode;
+
+ begin
+ result:=nil;
+ if is_pwidechar(resultdef) then
+ inserttypeconv(left,cwidestringtype)
+ else
+ if is_pchar(resultdef) and
+ (is_widestring(left.resultdef) or
+ is_unicodestring(left.resultdef)) then
+ begin
+ inserttypeconv(left,getansistringdef);
+ { the second pass of second_cstring_to_pchar expects a }
+ { strinconstn, but this may become a call to the }
+ { widestring manager in case left contains "high ascii" }
+ if (left.nodetype<>stringconstn) then
+ begin
+ result:=left;
+ left:=nil;
+ end;
+ end;
+ end;
+
+
+ function ttypeconvnode.typecheck_cstring_to_int : tnode;
+ var
+ fcc : cardinal;
+ pb : pbyte;
+ begin
+ result:=nil;
+ if left.nodetype<>stringconstn then
+ internalerror(200510012);
+ if tstringconstnode(left).len=4 then
+ begin
+ pb:=pbyte(tstringconstnode(left).value_str);
+ fcc:=(pb[0] shl 24) or (pb[1] shl 16) or (pb[2] shl 8) or pb[3];
+ result:=cordconstnode.create(fcc,u32inttype,false);
+ end
+ else
+ CGMessage2(type_e_illegal_type_conversion,left.resultdef.typename,resultdef.typename);
+ end;
+
+
+ function ttypeconvnode.typecheck_arrayconstructor_to_set : tnode;
+ var
+ hp : tnode;
+ begin
+ result:=nil;
+ if left.nodetype<>arrayconstructorn then
+ internalerror(5546);
+ { remove typeconv node }
+ hp:=left;
+ left:=nil;
+ { create a set constructor tree }
+ arrayconstructor_to_set(hp);
+ result:=hp;
+ end;
+
+
+ function ttypeconvnode.typecheck_set_to_set : tnode;
+ begin
+ result:=nil;
+ { constant sets can be converted by changing the type only }
+ if (left.nodetype=setconstn) then
+ begin
+ left.resultdef:=resultdef;
+ result:=left;
+ left:=nil;
+ exit;
+ end;
+ end;
+
+
+ function ttypeconvnode.typecheck_pchar_to_string : tnode;
+ var
+ newblock : tblocknode;
+ newstat : tstatementnode;
+ restemp : ttempcreatenode;
+ begin
+ if tstringdef(resultdef).stringtype=st_shortstring then
+ begin
+ newblock:=internalstatements(newstat);
+ restemp:=ctempcreatenode.create(resultdef,resultdef.size,tt_persistent,false);
+ addstatement(newstat,restemp);
+ addstatement(newstat,ccallnode.createintern('fpc_pchar_to_shortstr',ccallparanode.create(left,ccallparanode.create(
+ ctemprefnode.create(restemp),nil))));
+ addstatement(newstat,ctempdeletenode.create_normal_temp(restemp));
+ addstatement(newstat,ctemprefnode.create(restemp));
+ result:=newblock;
+ end
+ else if tstringdef(resultdef).stringtype=st_ansistring then
+ result := ccallnode.createinternres(
+ 'fpc_pchar_to_'+tstringdef(resultdef).stringtypname,
+ ccallparanode.create(
+ cordconstnode.create(getparaencoding(resultdef),u16inttype,true),
+ ccallparanode.create(left,nil)
+ ),
+ resultdef
+ )
+ else
+ result := ccallnode.createinternres(
+ 'fpc_pchar_to_'+tstringdef(resultdef).stringtypname,
+ ccallparanode.create(left,nil),resultdef);
+ left:=nil;
+ end;
+
+
+ function ttypeconvnode.typecheck_interface_to_string : tnode;
+ begin
+ if assigned(tobjectdef(left.resultdef).iidstr) then
+ begin
+ if not(oo_has_valid_guid in tobjectdef(left.resultdef).objectoptions) then
+ CGMessage1(type_e_interface_has_no_guid,tobjectdef(left.resultdef).typename);
+ result:=cstringconstnode.createstr(tobjectdef(left.resultdef).iidstr^);
+ tstringconstnode(result).changestringtype(cshortstringtype);
+ end;
+ end;
+
+
+ function ttypeconvnode.typecheck_interface_to_guid : tnode;
+ begin
+ if assigned(tobjectdef(left.resultdef).iidguid) then
+ begin
+ if not(oo_has_valid_guid in tobjectdef(left.resultdef).objectoptions) then
+ CGMessage1(type_e_interface_has_no_guid,tobjectdef(left.resultdef).typename);
+ result:=cguidconstnode.create(tobjectdef(left.resultdef).iidguid^);
+ end;
+ end;
+
+
+ function ttypeconvnode.typecheck_dynarray_to_openarray : tnode;
+ begin
+ { a dynamic array is a pointer to an array, so to convert it to }
+ { an open array, we have to dereference it (JM) }
+ result := ctypeconvnode.create_internal(left,voidpointertype);
+ typecheckpass(result);
+ { left is reused }
+ left := nil;
+ result := cderefnode.create(result);
+ include(result.flags,nf_no_checkpointer);
+ result.resultdef := resultdef;
+ end;
+
+
+ function ttypeconvnode.typecheck_pwchar_to_string : tnode;
+ var
+ newblock : tblocknode;
+ newstat : tstatementnode;
+ restemp : ttempcreatenode;
+ begin
+ if tstringdef(resultdef).stringtype=st_shortstring then
+ begin
+ newblock:=internalstatements(newstat);
+ restemp:=ctempcreatenode.create(resultdef,resultdef.size,tt_persistent,false);
+ addstatement(newstat,restemp);
+ addstatement(newstat,ccallnode.createintern('fpc_pwidechar_to_shortstr',ccallparanode.create(left,ccallparanode.create(
+ ctemprefnode.create(restemp),nil))));
+ addstatement(newstat,ctempdeletenode.create_normal_temp(restemp));
+ addstatement(newstat,ctemprefnode.create(restemp));
+ result:=newblock;
+ end
+ else if tstringdef(resultdef).stringtype=st_ansistring then
+ begin
+ result:=ccallnode.createinternres(
+ 'fpc_pwidechar_to_'+tstringdef(resultdef).stringtypname,
+ ccallparanode.create(
+ cordconstnode.create(
+ getparaencoding(resultdef),
+ u16inttype,
+ true
+ ),
+ ccallparanode.create(left,nil)
+ ),
+ resultdef
+ );
+ end
+ else
+ result := ccallnode.createinternres(
+ 'fpc_pwidechar_to_'+tstringdef(resultdef).stringtypname,
+ ccallparanode.create(left,nil),resultdef);
+ left:=nil;
+ end;
+
+
+ function ttypeconvnode.typecheck_variant_to_dynarray : tnode;
+ begin
+ result := ccallnode.createinternres(
+ 'fpc_variant_to_dynarray',
+ ccallparanode.create(caddrnode.create_internal(crttinode.create(tstoreddef(resultdef),initrtti,rdt_normal)),
+ ccallparanode.create(left,nil)
+ ),resultdef);
+ typecheckpass(result);
+ left:=nil;
+ end;
+
+
+ function ttypeconvnode.typecheck_dynarray_to_variant : tnode;
+ begin
+ result := ccallnode.createinternres(
+ 'fpc_dynarray_to_variant',
+ ccallparanode.create(caddrnode.create_internal(crttinode.create(tstoreddef(left.resultdef),initrtti,rdt_normal)),
+ ccallparanode.create(ctypeconvnode.create_explicit(left,voidpointertype),nil)
+ ),resultdef);
+ typecheckpass(result);
+ left:=nil;
+ end;
+
+
+ function ttypeconvnode.typecheck_variant_to_interface : tnode;
+ begin
+ if tobjectdef(resultdef).is_related(tobjectdef(search_system_type('IDISPATCH').typedef)) then
+ result := ccallnode.createinternres(
+ 'fpc_variant_to_idispatch',
+ ccallparanode.create(left,nil)
+ ,resultdef)
+ else
+ result := ccallnode.createinternres(
+ 'fpc_variant_to_interface',
+ ccallparanode.create(left,nil)
+ ,resultdef);
+ typecheckpass(result);
+ left:=nil;
+ end;
+
+
+ function ttypeconvnode.typecheck_interface_to_variant : tnode;
+ begin
+ if tobjectdef(left.resultdef).is_related(tobjectdef(search_system_type('IDISPATCH').typedef)) then
+ result := ccallnode.createinternres(
+ 'fpc_idispatch_to_variant',
+ ccallparanode.create(left,nil)
+ ,resultdef)
+ else
+ result := ccallnode.createinternres(
+ 'fpc_interface_to_variant',
+ ccallparanode.create(left,nil)
+ ,resultdef);
+ typecheckpass(result);
+ left:=nil;
+ end;
+
+
+ function ttypeconvnode.typecheck_variant_to_enum : tnode;
+
+ begin
+ result := ctypeconvnode.create_internal(left,sinttype);
+ result := ctypeconvnode.create_internal(result,resultdef);
+ typecheckpass(result);
+ { left is reused }
+ left := nil;
+ end;
+
+
+ function ttypeconvnode.typecheck_enum_to_variant : tnode;
+
+ begin
+ result := ctypeconvnode.create_internal(left,sinttype);
+ result := ctypeconvnode.create_internal(result,cvarianttype);
+ typecheckpass(result);
+ { left is reused }
+ left := nil;
+ end;
+
+
+ function ttypeconvnode.typecheck_array_2_dynarray : tnode;
+ var
+ newstatement : tstatementnode;
+ temp : ttempcreatenode;
+ temp2 : ttempcreatenode;
+ begin
+ { create statements with call to getmem+initialize }
+ result:=internalstatements(newstatement);
+
+ { create temp for result }
+ temp:=ctempcreatenode.create(resultdef,resultdef.size,tt_persistent,true);
+ addstatement(newstatement,temp);
+
+ { get temp for array of lengths }
+ temp2:=ctempcreatenode.create(sinttype,sinttype.size,tt_persistent,false);
+ addstatement(newstatement,temp2);
+
+ { one dimensional }
+ addstatement(newstatement,cassignmentnode.create(
+ ctemprefnode.create_offset(temp2,0),
+ cordconstnode.create
+ (tarraydef(left.resultdef).highrange+1,s32inttype,true)));
+ { create call to fpc_dynarr_setlength }
+ addstatement(newstatement,ccallnode.createintern('fpc_dynarray_setlength',
+ ccallparanode.create(caddrnode.create_internal
+ (ctemprefnode.create(temp2)),
+ ccallparanode.create(cordconstnode.create
+ (1,s32inttype,true),
+ ccallparanode.create(caddrnode.create_internal
+ (crttinode.create(tstoreddef(resultdef),initrtti,rdt_normal)),
+ ccallparanode.create(
+ ctypeconvnode.create_internal(
+ ctemprefnode.create(temp),voidpointertype),
+ nil))))
+
+ ));
+ addstatement(newstatement,ctempdeletenode.create(temp2));
+
+ { copy ... }
+ addstatement(newstatement,cassignmentnode.create(
+ ctypeconvnode.create_internal(cderefnode.create(ctypeconvnode.create_internal(ctemprefnode.create(temp),voidpointertype)),left.resultdef),
+ left
+ ));
+ { left is reused }
+ left:=nil;
+ { the last statement should return the value as
+ location and type, this is done be referencing the
+ temp and converting it first from a persistent temp to
+ normal temp }
+ addstatement(newstatement,ctempdeletenode.create_normal_temp(temp));
+ addstatement(newstatement,ctemprefnode.create(temp));
+ end;
+
+
+ procedure copyparasym(p:TObject;arg:pointer);
+ var
+ newparast : TSymtable absolute arg;
+ vs : tparavarsym;
+ begin
+ if tsym(p).typ<>paravarsym then
+ exit;
+ with tparavarsym(p) do
+ begin
+ vs:=tparavarsym.create(realname,paranr,varspez,vardef,varoptions);
+ vs.defaultconstsym:=defaultconstsym;
+ newparast.insert(vs);
+ end;
+ end;
+
+
+ function ttypeconvnode.typecheck_proc_to_procvar : tnode;
+ var
+ pd : tabstractprocdef;
+ nestinglevel : byte;
+ begin
+ result:=nil;
+ pd:=tabstractprocdef(left.resultdef);
+
+ { create procvardef (default for create_proc_to_procvar is voiddef,
+ but if later a regular inserttypeconvnode() is used to insert a type
+ conversion to the actual procvardef, totypedef will be set to the
+ real procvartype that we are converting to) }
+ if assigned(totypedef) and
+ (totypedef.typ=procvardef) then
+ resultdef:=totypedef
+ else
+ begin
+ nestinglevel:=pd.parast.symtablelevel;
+ resultdef:=tprocvardef.create(nestinglevel);
+ tprocvardef(resultdef).proctypeoption:=pd.proctypeoption;
+ tprocvardef(resultdef).proccalloption:=pd.proccalloption;
+ tprocvardef(resultdef).procoptions:=pd.procoptions;
+ tprocvardef(resultdef).returndef:=pd.returndef;
+ { method ? then set the methodpointer flag }
+ if (pd.owner.symtabletype=ObjectSymtable) then
+ include(tprocvardef(resultdef).procoptions,po_methodpointer);
+ { only need the address of the method? this is needed
+ for @tobject.create. In this case there will be a loadn without
+ a methodpointer. }
+ if (left.nodetype=loadn) and
+ not assigned(tloadnode(left).left) and
+ (not(m_nested_procvars in current_settings.modeswitches) or
+ not is_nested_pd(tprocvardef(resultdef))) then
+ include(tprocvardef(resultdef).procoptions,po_addressonly);
+
+ { Add parameters use only references, we don't need to keep the
+ parast. We use the parast from the original function to calculate
+ our parameter data and reset it afterwards }
+ pd.parast.SymList.ForEachCall(@copyparasym,tprocvardef(resultdef).parast);
+ tprocvardef(resultdef).calcparas;
+ end;
+ end;
+
+
+ function ttypeconvnode.typecheck_call_helper(c : tconverttype) : tnode;
+ const
+ resultdefconvert : array[tconverttype] of pointer = (
+ {none} nil,
+ {equal} nil,
+ {not_possible} nil,
+ { string_2_string } @ttypeconvnode.typecheck_string_to_string,
+ { char_2_string } @ttypeconvnode.typecheck_char_to_string,
+ { char_2_chararray } @ttypeconvnode.typecheck_char_to_chararray,
+ { pchar_2_string } @ttypeconvnode.typecheck_pchar_to_string,
+ { cchar_2_pchar } @ttypeconvnode.typecheck_cchar_to_pchar,
+ { cstring_2_pchar } @ttypeconvnode.typecheck_cstring_to_pchar,
+ { cstring_2_int } @ttypeconvnode.typecheck_cstring_to_int,
+ { ansistring_2_pchar } nil,
+ { string_2_chararray } @ttypeconvnode.typecheck_string_to_chararray,
+ { chararray_2_string } @ttypeconvnode.typecheck_chararray_to_string,
+ { array_2_pointer } nil,
+ { pointer_2_array } nil,
+ { int_2_int } @ttypeconvnode.typecheck_int_to_int,
+ { int_2_bool } nil,
+ { bool_2_bool } nil,
+ { bool_2_int } nil,
+ { real_2_real } @ttypeconvnode.typecheck_real_to_real,
+ { int_2_real } @ttypeconvnode.typecheck_int_to_real,
+ { real_2_currency } @ttypeconvnode.typecheck_real_to_currency,
+ { proc_2_procvar } @ttypeconvnode.typecheck_proc_to_procvar,
+ { nil_2_methodprocvar } nil,
+ { arrayconstructor_2_set } @ttypeconvnode.typecheck_arrayconstructor_to_set,
+ { set_to_set } @ttypeconvnode.typecheck_set_to_set,
+ { cord_2_pointer } @ttypeconvnode.typecheck_cord_to_pointer,
+ { intf_2_string } @ttypeconvnode.typecheck_interface_to_string,
+ { intf_2_guid } @ttypeconvnode.typecheck_interface_to_guid,
+ { class_2_intf } nil,
+ { char_2_char } @ttypeconvnode.typecheck_char_to_char,
+ { dynarray_2_openarray} @ttypeconvnode.typecheck_dynarray_to_openarray,
+ { pwchar_2_string} @ttypeconvnode.typecheck_pwchar_to_string,
+ { variant_2_dynarray} @ttypeconvnode.typecheck_variant_to_dynarray,
+ { dynarray_2_variant} @ttypeconvnode.typecheck_dynarray_to_variant,
+ { variant_2_enum} @ttypeconvnode.typecheck_variant_to_enum,
+ { enum_2_variant} @ttypeconvnode.typecheck_enum_to_variant,
+ { variant_2_interface} @ttypeconvnode.typecheck_interface_to_variant,
+ { interface_2_variant} @ttypeconvnode.typecheck_variant_to_interface,
+ { array_2_dynarray} @ttypeconvnode.typecheck_array_2_dynarray
+ );
+ type
+ tprocedureofobject = function : tnode of object;
+ var
+ r : packed record
+ proc : pointer;
+ obj : pointer;
+ end;
+ begin
+ result:=nil;
+ { this is a little bit dirty but it works }
+ { and should be quite portable too }
+ r.proc:=resultdefconvert[c];
+ r.obj:=self;
+ if assigned(r.proc) then
+ result:=tprocedureofobject(r)();
+ end;
+
+
+ function ttypeconvnode.actualtargetnode: tnode;
+ begin
+ result:=self;
+ while (result.nodetype=typeconvn) and
+ ttypeconvnode(result).retains_value_location do
+ result:=ttypeconvnode(result).left;
+ end;
+
+
+ function ttypeconvnode.pass_typecheck:tnode;
+
+ var
+ hdef : tdef;
+ hp : tnode;
+ currprocdef : tabstractprocdef;
+ aprocdef : tprocdef;
+ eq : tequaltype;
+ cdoptions : tcompare_defs_options;
+ newblock: tblocknode;
+ newstatement: tstatementnode;
+ tempnode: ttempcreatenode;
+ begin
+ result:=nil;
+ resultdef:=totypedef;
+
+ typecheckpass(left);
+ if codegenerror then
+ exit;
+
+ { When absolute force tc_equal }
+ if (nf_absolute in flags) then
+ begin
+ convtype:=tc_equal;
+ if not(tstoreddef(resultdef).is_intregable) and
+ not(tstoreddef(resultdef).is_fpuregable) then
+ make_not_regable(left,[ra_addr_regable]);
+ exit;
+ end;
+
+ { tp procvar support. Skip typecasts to procvar, record or set. Those
+ convert on the procvar value. This is used to access the
+ fields of a methodpointer }
+ if not(nf_load_procvar in flags) and
+ not(resultdef.typ in [procvardef,recorddef,setdef]) then
+ maybe_call_procvar(left,true);
+
+ { convert array constructors to sets, because there is no conversion
+ possible for array constructors }
+ if (resultdef.typ<>arraydef) and
+ is_array_constructor(left.resultdef) then
+ begin
+ arrayconstructor_to_set(left);
+ typecheckpass(left);
+ end;
+
+ if convtype=tc_none then
+ begin
+ cdoptions:=[cdo_check_operator,cdo_allow_variant,cdo_warn_incompatible_univ];
+ if nf_explicit in flags then
+ include(cdoptions,cdo_explicit);
+ if nf_internal in flags then
+ include(cdoptions,cdo_internal);
+ eq:=compare_defs_ext(left.resultdef,resultdef,left.nodetype,convtype,aprocdef,cdoptions);
+ case eq of
+ te_exact,
+ te_equal :
+ begin
+ result := simplify(false);
+ if assigned(result) then
+ exit;
+
+ { in case of bitpacked accesses, the original type must
+ remain so that not too many/few bits are laoded }
+ if is_bitpacked_access(left) then
+ convtype:=tc_int_2_int;
+ { Only leave when there is no conversion to do.
+ We can still need to call a conversion routine,
+ like the routine to convert a stringconstnode }
+ if (convtype in [tc_equal,tc_not_possible]) and
+ { some conversions, like dynarray to pointer in Delphi
+ mode, must not be removed, because then we get memory
+ leaks due to missing temp finalization }
+ (not is_managed_type(left.resultdef) or
+ { different kinds of refcounted types may need calls
+ to different kinds of refcounting helpers }
+ (resultdef=left.resultdef)) then
+ begin
+ left.resultdef:=resultdef;
+ if (nf_explicit in flags) and (left.nodetype = addrn) then
+ include(left.flags, nf_typedaddr);
+ result:=left;
+ left:=nil;
+ exit;
+ end;
+ end;
+
+ te_convert_l1,
+ te_convert_l2,
+ te_convert_l3,
+ te_convert_l4,
+ te_convert_l5:
+ { nothing to do }
+ ;
+
+ te_convert_operator :
+ begin
+ include(current_procinfo.flags,pi_do_call);
+ addsymref(aprocdef.procsym);
+ hp:=ccallnode.create(ccallparanode.create(left,nil),Tprocsym(aprocdef.procsym),nil,nil,[]);
+ { tell explicitly which def we must use !! (PM) }
+ tcallnode(hp).procdefinition:=aprocdef;
+ left:=nil;
+ result:=hp;
+ exit;
+ end;
+
+ te_incompatible :
+ begin
+ { Procedures have a resultdef of voiddef and functions of their
+ own resultdef. They will therefore always be incompatible with
+ a procvar. Because isconvertable cannot check for procedures we
+ use an extra check for them.}
+ if (left.nodetype=calln) and
+ (tcallnode(left).required_para_count=0) and
+ (resultdef.typ=procvardef) and
+ (
+ (m_tp_procvar in current_settings.modeswitches) or
+ (m_mac_procvar in current_settings.modeswitches)
+ ) then
+ begin
+ if assigned(tcallnode(left).right) then
+ begin
+ { this is already a procvar, if it is really equal
+ is checked below }
+ convtype:=tc_equal;
+ hp:=tcallnode(left).right.getcopy;
+ currprocdef:=tabstractprocdef(hp.resultdef);
+ end
+ else
+ begin
+ convtype:=tc_proc_2_procvar;
+ currprocdef:=Tprocsym(Tcallnode(left).symtableprocentry).Find_procdef_byprocvardef(Tprocvardef(resultdef));
+ hp:=cloadnode.create_procvar(tprocsym(tcallnode(left).symtableprocentry),
+ tprocdef(currprocdef),tcallnode(left).symtableproc);
+ if (tcallnode(left).symtableprocentry.owner.symtabletype=ObjectSymtable) then
+ begin
+ if assigned(tcallnode(left).methodpointer) then
+ tloadnode(hp).set_mp(tcallnode(left).methodpointer.getcopy)
+ else
+ tloadnode(hp).set_mp(load_self_node);
+ end;
+ typecheckpass(hp);
+ end;
+ left.free;
+ left:=hp;
+ { Now check if the procedure we are going to assign to
+ the procvar, is compatible with the procvar's type }
+ if not(nf_explicit in flags) and
+ (proc_to_procvar_equal(currprocdef,tprocvardef(resultdef),false)=te_incompatible) then
+ IncompatibleTypes(left.resultdef,resultdef);
+ exit;
+ end
+ else if maybe_global_proc_to_nested(left,resultdef) then
+ begin
+ result:=left;
+ left:=nil;
+ exit;
+ end;
+
+ { Handle explicit type conversions }
+ if nf_explicit in flags then
+ begin
+ { do common tc_equal cast }
+ convtype:=tc_equal;
+
+ { ordinal constants can be resized to 1,2,4,8 bytes }
+ if (left.nodetype=ordconstn) then
+ begin
+ { Insert typeconv for ordinal to the correct size first on left, after
+ that the other conversion can be done }
+ hdef:=nil;
+ case longint(resultdef.size) of
+ 1 :
+ hdef:=s8inttype;
+ 2 :
+ hdef:=s16inttype;
+ 4 :
+ hdef:=s32inttype;
+ 8 :
+ hdef:=s64inttype;
+ end;
+ { we need explicit, because it can also be an enum }
+ if assigned(hdef) then
+ inserttypeconv_internal(left,hdef)
+ else
+ CGMessage2(type_e_illegal_type_conversion,left.resultdef.typename,resultdef.typename);
+ end;
+
+ { check if the result could be in a register }
+ if (not(tstoreddef(resultdef).is_intregable) and
+ not(tstoreddef(resultdef).is_fpuregable)) or
+ ((left.resultdef.typ = floatdef) and
+ (resultdef.typ <> floatdef)) then
+ make_not_regable(left,[ra_addr_regable]);
+
+ { class/interface to class/interface, with checkobject support }
+ if is_class_or_interface_or_objc(resultdef) and
+ is_class_or_interface_or_objc(left.resultdef) then
+ begin
+ { check if the types are related }
+ if not(nf_internal in flags) and
+ (not(tobjectdef(left.resultdef).is_related(tobjectdef(resultdef)))) and
+ (not(tobjectdef(resultdef).is_related(tobjectdef(left.resultdef)))) then
+ begin
+ { Give an error when typecasting class to interface, this is compatible
+ with delphi }
+ if is_interface(resultdef) and
+ not is_interface(left.resultdef) then
+ CGMessage2(type_e_classes_not_related,
+ FullTypeName(left.resultdef,resultdef),
+ FullTypeName(resultdef,left.resultdef))
+ else
+ CGMessage2(type_w_classes_not_related,
+ FullTypeName(left.resultdef,resultdef),
+ FullTypeName(resultdef,left.resultdef))
+ end;
+
+ { Add runtime check? }
+ if not is_objc_class_or_protocol(resultdef) and
+ not is_objc_class_or_protocol(left.resultdef) and
+ (cs_check_object in current_settings.localswitches) and
+ not(nf_internal in flags) then
+ begin
+ { we can translate the typeconvnode to 'as' when
+ typecasting to a class or interface }
+ { we need to make sure the result can still be
+ passed as a var parameter }
+ newblock:=internalstatements(newstatement);
+ if (valid_for_var(left,false)) then
+ begin
+ tempnode:=ctempcreatenode.create(voidpointertype,voidpointertype.size,tt_persistent,true);
+ addstatement(newstatement,tempnode);
+ addstatement(newstatement,cassignmentnode.create(
+ ctemprefnode.create(tempnode),
+ caddrnode.create_internal(left)));
+ left:=ctypeconvnode.create_internal(cderefnode.create(ctemprefnode.create(tempnode)),left.resultdef);
+ end
+ else
+ begin
+ tempnode:=ctempcreatenode.create(left.resultdef,left.resultdef.size,tt_persistent,true);
+ addstatement(newstatement,tempnode);
+ addstatement(newstatement,cassignmentnode.create(
+ ctemprefnode.create(tempnode),
+ left));
+ left:=ctemprefnode.create(tempnode);
+ end;
+ addstatement(newstatement,casnode.create(left.getcopy,cloadvmtaddrnode.create(ctypenode.create(resultdef))));
+ addstatement(newstatement,ctempdeletenode.create_normal_temp(tempnode));
+ addstatement(newstatement,ctypeconvnode.create_internal(left,resultdef));
+ left:=nil;
+ result:=newblock;
+ exit;
+ end;
+ end
+
+ else
+ begin
+ { only if the same size or formal def, and }
+ { don't allow type casting of constants to }
+ { structured types }
+ if not(
+ (left.resultdef.typ=formaldef) or
+ (
+ not(is_open_array(left.resultdef)) and
+ not(is_array_constructor(left.resultdef)) and
+ not(is_array_of_const(left.resultdef)) and
+ (left.resultdef.size=resultdef.size) and
+ { disallow casts of const nodes }
+ (not is_constnode(left) or
+ { however, there are some exceptions }
+ (not(resultdef.typ in [arraydef,recorddef,setdef,stringdef,
+ filedef,variantdef,objectdef]) or
+ is_class_or_interface_or_objc(resultdef) or
+ { the softfloat code generates casts <const. float> to record }
+ (nf_internal in flags)
+ ))
+ ) or
+ (
+ is_void(left.resultdef) and
+ (left.nodetype=derefn)
+ )
+ ) then
+ CGMessage2(type_e_illegal_type_conversion,left.resultdef.typename,resultdef.typename);
+ end;
+ end
+ else
+ IncompatibleTypes(left.resultdef,resultdef);
+ end;
+
+ else
+ internalerror(200211231);
+ end;
+ end;
+ { Give hint or warning for unportable code, exceptions are
+ - typecasts from constants
+ - void }
+ if not(nf_internal in flags) and
+ (left.nodetype<>ordconstn) and
+ not(is_void(left.resultdef)) and
+ (((left.resultdef.typ=orddef) and
+ (resultdef.typ in [pointerdef,procvardef,classrefdef])) or
+ ((resultdef.typ=orddef) and
+ (left.resultdef.typ in [pointerdef,procvardef,classrefdef]))) then
+ begin
+ {Converting pointers to signed integers is a bad idea. Warn.}
+ warn_pointer_to_signed:=(resultdef.typ=orddef) and (Torddef(resultdef).ordtype in [s8bit,s16bit,s32bit,s64bit]);
+ { Give a warning when sizes don't match, because then info will be lost }
+ if left.resultdef.size=resultdef.size then
+ CGMessage(type_h_pointer_to_longint_conv_not_portable)
+ else
+ CGMessage(type_w_pointer_to_longint_conv_not_portable);
+ end;
+
+ { tc_cord_2_pointer still requires a type check, which
+ simplify does not do }
+ if (convtype<>tc_cord_2_pointer) then
+ begin
+ result := simplify(false);
+ if assigned(result) then
+ exit;
+ end;
+
+ { now call the resultdef helper to do constant folding }
+ result:=typecheck_call_helper(convtype);
+ end;
+
+
+{$ifndef cpu64bitalu}
+
+ { checks whether we can safely remove 64 bit typeconversions }
+ { in case range and overflow checking are off, and in case }
+ { the result of this node tree is downcasted again to a }
+ { 8/16/32 bit value afterwards }
+ function checkremove64bittypeconvs(n: tnode; out gotsint: boolean): boolean;
+ var
+ gotmuldivmod: boolean;
+
+ { checks whether a node is either an u32bit, or originally }
+ { was one but was implicitly converted to s64bit }
+ function wasoriginallyint32(n: tnode): boolean;
+ begin
+ if (n.resultdef.typ<>orddef) then
+ exit(false);
+ if (torddef(n.resultdef).ordtype in [s32bit,u32bit]) then
+ begin
+ if (torddef(n.resultdef).ordtype=s32bit) then
+ gotsint:=true;
+ exit(true);
+ end;
+ if (torddef(n.resultdef).ordtype=s64bit) and
+ { nf_explicit is also set for explicitly typecasted }
+ { ordconstn's }
+ ([nf_internal,nf_explicit]*n.flags=[]) and
+ { either a typeconversion node coming from u32bit }
+ (((n.nodetype=typeconvn) and
+ (ttypeconvnode(n).left.resultdef.typ=orddef) and
+ (torddef(ttypeconvnode(n).left.resultdef).ordtype in [s32bit,u32bit])) or
+ { or an ordconstnode which was/is a valid cardinal }
+ ((n.nodetype=ordconstn) and
+ (tordconstnode(n).value>=int64(low(longint))) and
+ (tordconstnode(n).value<=high(cardinal)))) then
+ begin
+ if ((n.nodetype=typeconvn) and
+ (torddef(ttypeconvnode(n).left.resultdef).ordtype=s32bit)) or
+ ((n.nodetype=ordconstn) and
+ (tordconstnode(n).value<0)) then
+ gotsint:=true;
+ exit(true);
+ end;
+ result:=false;
+ end;
+
+
+ function docheckremove64bittypeconvs(n: tnode): boolean;
+ begin
+ result:=false;
+ if wasoriginallyint32(n) then
+ exit(true);
+ case n.nodetype of
+ subn,orn,xorn:
+ begin
+ { nf_internal is set by taddnode.typecheckpass in }
+ { case the arguments of this subn were u32bit, but }
+ { upcasted to s64bit for calculation correctness }
+ { (normally only needed when range checking, but }
+ { also done otherwise so there is no difference }
+ { in overload choosing etc between $r+ and $r-) }
+ if (nf_internal in n.flags) then
+ result:=true
+ else
+ result:=
+ docheckremove64bittypeconvs(tbinarynode(n).left) and
+ docheckremove64bittypeconvs(tbinarynode(n).right);
+ end;
+ addn,muln,divn,modn,andn:
+ begin
+ if n.nodetype in [muln,divn,modn] then
+ gotmuldivmod:=true;
+ result:=
+ docheckremove64bittypeconvs(tbinarynode(n).left) and
+ docheckremove64bittypeconvs(tbinarynode(n).right);
+ end;
+ end;
+ end;
+
+ begin { checkremove64bittypeconvs }
+ gotmuldivmod:=false;
+ gotsint:=false;
+ result:=
+ docheckremove64bittypeconvs(n) and
+ not(gotmuldivmod and gotsint);
+ end;
+
+
+ procedure doremove64bittypeconvs(var n: tnode; todef: tdef; forceunsigned: boolean);
+ begin
+ case n.nodetype of
+ subn,addn,muln,divn,modn,xorn,andn,orn:
+ begin
+ exclude(n.flags,nf_internal);
+ if not forceunsigned and
+ is_signed(n.resultdef) then
+ begin
+ doremove64bittypeconvs(tbinarynode(n).left,s32inttype,false);
+ doremove64bittypeconvs(tbinarynode(n).right,s32inttype,false);
+ n.resultdef:=s32inttype
+ end
+ else
+ begin
+ doremove64bittypeconvs(tbinarynode(n).left,u32inttype,forceunsigned);
+ doremove64bittypeconvs(tbinarynode(n).right,u32inttype,forceunsigned);
+ n.resultdef:=u32inttype
+ end;
+ end;
+ ordconstn:
+ inserttypeconv_internal(n,todef);
+ typeconvn:
+ begin
+ n.resultdef:=todef;
+ ttypeconvnode(n).totypedef:=todef;
+ end;
+ end;
+ end;
+{$endif not cpu64bitalu}
+
+
+ function ttypeconvnode.simplify(forinline : boolean): tnode;
+ var
+ hp: tnode;
+{$ifndef cpu64bitalu}
+ foundsint: boolean;
+{$endif not cpu64bitalu}
+ begin
+ result := nil;
+ { Constant folding and other node transitions to
+ remove the typeconv node }
+ case left.nodetype of
+ stringconstn :
+ if (convtype=tc_string_2_string) and
+ (
+ ((not is_widechararray(left.resultdef) and
+ not is_wide_or_unicode_string(left.resultdef)) or
+ (tstringdef(resultdef).stringtype in [st_widestring,st_unicodestring,st_ansistring])
+ )
+ ) then
+ begin
+ { output string consts in local ansistring encoding }
+ if is_ansistring(resultdef) and ((tstringdef(resultdef).encoding=0)or(tstringdef(resultdef).encoding=globals.CP_NONE)) then
+ tstringconstnode(left).changestringtype(getansistringdef)
+ else
+ tstringconstnode(left).changestringtype(resultdef);
+ result:=left;
+ resultdef:=left.resultdef;
+ left:=nil;
+ exit;
+ end;
+ realconstn :
+ begin
+ if (convtype = tc_real_2_currency) then
+ result := typecheck_real_to_currency
+ else if (convtype = tc_real_2_real) then
+ result := typecheck_real_to_real
+ else
+ exit;
+ if not(assigned(result)) then
+ begin
+ result := left;
+ left := nil;
+ end;
+ if (result.nodetype = realconstn) then
+ begin
+ hp:=result;
+ result:=crealconstnode.create(trealconstnode(hp).value_real,resultdef);
+ if ([nf_explicit,nf_internal] * flags <> []) then
+ include(result.flags, nf_explicit);
+ hp.free;
+ end;
+ end;
+ niln :
+ begin
+ { nil to ordinal node }
+ if (resultdef.typ=orddef) then
+ begin
+ hp:=cordconstnode.create(0,resultdef,true);
+ if ([nf_explicit,nf_internal] * flags <> []) then
+ include(hp.flags, nf_explicit);
+ result:=hp;
+ exit;
+ end
+ else
+ { fold nil to any pointer type }
+ if (resultdef.typ=pointerdef) then
+ begin
+ hp:=cnilnode.create;
+ hp.resultdef:=resultdef;
+ if ([nf_explicit,nf_internal] * flags <> []) then
+ include(hp.flags, nf_explicit);
+ result:=hp;
+ exit;
+ end
+ else
+ { remove typeconv after niln, but not when the result is a
+ methodpointer. The typeconv of the methodpointer will then
+ take care of updateing size of niln to OS_64 }
+ if not((resultdef.typ=procvardef) and
+ not(tprocvardef(resultdef).is_addressonly)) then
+ begin
+ left.resultdef:=resultdef;
+ if ([nf_explicit,nf_internal] * flags <> []) then
+ include(left.flags, nf_explicit);
+ result:=left;
+ left:=nil;
+ exit;
+ end;
+ end;
+
+ ordconstn :
+ begin
+ { ordinal contants can be directly converted }
+ { but not char to char because it is a widechar to char or via versa }
+ { which needs extra code to do the code page transistion }
+ { constant ordinal to pointer }
+ if (resultdef.typ=pointerdef) and
+ (convtype<>tc_cchar_2_pchar) then
+ begin
+ hp:=cpointerconstnode.create(TConstPtrUInt(tordconstnode(left).value.uvalue),resultdef);
+ if ([nf_explicit,nf_internal] * flags <> []) then
+ include(hp.flags, nf_explicit);
+ result:=hp;
+ exit;
+ end
+ else if is_ordinal(resultdef) and
+ not(convtype=tc_char_2_char) then
+ begin
+ { replace the resultdef and recheck the range }
+ if ([nf_explicit,nf_internal] * flags <> []) then
+ include(left.flags, nf_explicit)
+ else
+ { no longer an ordconst with an explicit typecast }
+ exclude(left.flags, nf_explicit);
+ { when converting from one boolean type to another, force }
+ { booleans to 0/1, and byte/word/long/qwordbool to 0/-1 }
+ { (Delphi-compatibile) }
+ if is_boolean(left.resultdef) and
+ is_boolean(resultdef) and
+ (is_cbool(left.resultdef) or
+ is_cbool(resultdef)) then
+ begin
+ if is_pasbool(resultdef) then
+ tordconstnode(left).value:=ord(tordconstnode(left).value<>0)
+ else
+{$ifdef VER2_2}
+ tordconstnode(left).value:=ord(tordconstnode(left).value<>0);
+ tordconstnode(left).value:=-tordconstnode(left).value;
+{$else}
+ tordconstnode(left).value:=-ord(tordconstnode(left).value<>0);
+{$endif VER2_2}
+ end
+ else
+ testrange(resultdef,tordconstnode(left).value,(nf_explicit in flags),false);
+ left.resultdef:=resultdef;
+ tordconstnode(left).typedef:=resultdef;
+ result:=left;
+ left:=nil;
+ exit;
+ end;
+ end;
+
+ pointerconstn :
+ begin
+ { pointerconstn to any pointer is folded too }
+ if (resultdef.typ=pointerdef) then
+ begin
+ left.resultdef:=resultdef;
+ if ([nf_explicit,nf_internal] * flags <> []) then
+ include(left.flags, nf_explicit)
+ else
+ { no longer an ordconst with an explicit typecast }
+ exclude(left.flags, nf_explicit);
+ result:=left;
+ left:=nil;
+ exit;
+ end
+ { constant pointer to ordinal }
+ else if is_ordinal(resultdef) then
+ begin
+ hp:=cordconstnode.create(TConstExprInt(tpointerconstnode(left).value),
+ resultdef,not(nf_explicit in flags));
+ if ([nf_explicit,nf_internal] * flags <> []) then
+ include(hp.flags, nf_explicit);
+ result:=hp;
+ exit;
+ end;
+ end;
+ end;
+
+{$ifndef cpu64bitalu}
+ { must be done before code below, because we need the
+ typeconversions for ordconstn's as well }
+ case convtype of
+ tc_int_2_int:
+ begin
+ if (localswitches * [cs_check_range,cs_check_overflow] = []) and
+ (resultdef.typ in [pointerdef,orddef,enumdef]) and
+ (resultdef.size <= 4) and
+ is_64bitint(left.resultdef) and
+ (left.nodetype in [subn,addn,muln,divn,modn,xorn,andn,orn]) and
+ checkremove64bittypeconvs(left,foundsint) then
+ begin
+ { avoid unnecessary widening of intermediary calculations }
+ { to 64 bit }
+ doremove64bittypeconvs(left,generrordef,not foundsint);
+ end;
+ end;
+ end;
+{$endif not cpu64bitalu}
+
+ end;
+
+
+ procedure Ttypeconvnode.mark_write;
+ begin
+ left.mark_write;
+ end;
+
+ function ttypeconvnode.first_cord_to_pointer : tnode;
+
+ begin
+ result:=nil;
+ internalerror(200104043);
+ end;
+
+
+ function ttypeconvnode.first_int_to_int : tnode;
+
+ begin
+ first_int_to_int:=nil;
+ expectloc:=left.expectloc;
+ if not is_void(left.resultdef) then
+ begin
+ if (left.expectloc<>LOC_REGISTER) and
+ ((resultdef.size>left.resultdef.size) or
+ (left.expectloc in [LOC_SUBSETREF,LOC_CSUBSETREF,LOC_SUBSETREG,LOC_CSUBSETREG])) then
+ expectloc:=LOC_REGISTER
+ else
+ if (left.expectloc=LOC_CREGISTER) and
+ (resultdef.size<left.resultdef.size) then
+ expectloc:=LOC_REGISTER;
+ end;
+ end;
+
+
+ function ttypeconvnode.first_cstring_to_pchar : tnode;
+
+ begin
+ result:=nil;
+ expectloc:=LOC_REGISTER;
+ end;
+
+
+ function ttypeconvnode.first_cstring_to_int : tnode;
+
+ begin
+ result:=nil;
+ internalerror(200510014);
+ end;
+
+
+ function ttypeconvnode.first_string_to_chararray : tnode;
+
+ begin
+ first_string_to_chararray:=nil;
+ expectloc:=left.expectloc;
+ end;
+
+
+ function ttypeconvnode.first_char_to_string : tnode;
+
+ begin
+ first_char_to_string:=nil;
+ expectloc:=LOC_REFERENCE;
+ end;
+
+
+ function ttypeconvnode.first_nothing : tnode;
+ begin
+ first_nothing:=nil;
+ end;
+
+
+ function ttypeconvnode.first_array_to_pointer : tnode;
+
+ begin
+ first_array_to_pointer:=nil;
+ expectloc:=LOC_REGISTER;
+ end;
+
+
+ function ttypeconvnode.first_int_to_real: tnode;
+ var
+ fname: string[32];
+ begin
+ if target_info.system in systems_wince then
+ begin
+ { converting a 64bit integer to a float requires a helper }
+ if is_64bitint(left.resultdef) or
+ is_currency(left.resultdef) then
+ begin
+ { hack to avoid double division by 10000, as it's
+ already done by typecheckpass.resultdef_int_to_real }
+ if is_currency(left.resultdef) then
+ left.resultdef := s64inttype;
+ if is_signed(left.resultdef) then
+ fname:='I64TO'
+ else
+ fname:='UI64TO';
+ end
+ else
+ { other integers are supposed to be 32 bit }
+ begin
+ if is_signed(left.resultdef) then
+ fname:='ITO'
+ else
+ fname:='UTO';
+ firstpass(left);
+ end;
+ if tfloatdef(resultdef).floattype=s64real then
+ fname:=fname+'D'
+ else
+ fname:=fname+'S';
+ result:=ccallnode.createintern(fname,ccallparanode.create(
+ left,nil));
+ left:=nil;
+ firstpass(result);
+ exit;
+ end
+ else
+ begin
+ { converting a 64bit integer to a float requires a helper }
+ if is_64bitint(left.resultdef) or
+ is_currency(left.resultdef) then
+ begin
+ { hack to avoid double division by 10000, as it's
+ already done by typecheckpass.resultdef_int_to_real }
+ if is_currency(left.resultdef) then
+ left.resultdef := s64inttype;
+ if is_signed(left.resultdef) then
+ fname:='int64_to_'
+ else
+ { we can't do better currently }
+ fname:='qword_to_';
+ end
+ else
+ { other integers are supposed to be 32 bit }
+ begin
+ if is_signed(left.resultdef) then
+ fname:='int32_to_'
+ else
+ fname:='int64_to_';
+ firstpass(left);
+ end;
+ if tfloatdef(resultdef).floattype=s64real then
+ fname:=fname+'float64'
+ else
+ fname:=fname+'float32';
+ result:=ctypeconvnode.create_internal(ccallnode.createintern(fname,ccallparanode.create(
+ left,nil)),resultdef);
+ left:=nil;
+ firstpass(result);
+ exit;
+ end;
+ end;
+
+
+ function ttypeconvnode.first_real_to_real : tnode;
+ begin
+{$ifdef cpufpemu}
+ if cs_fp_emulation in current_settings.moduleswitches then
+ begin
+ if target_info.system in systems_wince then
+ begin
+ case tfloatdef(left.resultdef).floattype of
+ s32real:
+ case tfloatdef(resultdef).floattype of
+ s64real:
+ result:=ccallnode.createintern('STOD',ccallparanode.create(left,nil));
+ s32real:
+ begin
+ result:=left;
+ left:=nil;
+ end;
+ else
+ internalerror(2005082704);
+ end;
+ s64real:
+ case tfloatdef(resultdef).floattype of
+ s32real:
+ result:=ccallnode.createintern('DTOS',ccallparanode.create(left,nil));
+ s64real:
+ begin
+ result:=left;
+ left:=nil;
+ end;
+ else
+ internalerror(2005082703);
+ end;
+ else
+ internalerror(2005082702);
+ end;
+ left:=nil;
+ firstpass(result);
+ exit;
+ end
+ else
+ begin
+ case tfloatdef(left.resultdef).floattype of
+ s32real:
+ case tfloatdef(resultdef).floattype of
+ s64real:
+ result:=ctypeconvnode.create_explicit(ccallnode.createintern('float32_to_float64',ccallparanode.create(
+ ctypeconvnode.create_internal(left,search_system_type('FLOAT32REC').typedef),nil)),resultdef);
+ s32real:
+ begin
+ result:=left;
+ left:=nil;
+ end;
+ else
+ internalerror(200610151);
+ end;
+ s64real:
+ case tfloatdef(resultdef).floattype of
+ s32real:
+ result:=ctypeconvnode.create_explicit(ccallnode.createintern('float64_to_float32',ccallparanode.create(
+ ctypeconvnode.create_internal(left,search_system_type('FLOAT64').typedef),nil)),resultdef);
+ s64real:
+ begin
+ result:=left;
+ left:=nil;
+ end;
+ else
+ internalerror(200610152);
+ end;
+ else
+ internalerror(200610153);
+ end;
+ left:=nil;
+ firstpass(result);
+ exit;
+ end;
+ end
+ else
+{$endif cpufpemu}
+ begin
+ first_real_to_real:=nil;
+ if not use_vectorfpu(resultdef) then
+ expectloc:=LOC_FPUREGISTER
+ else
+ expectloc:=LOC_MMREGISTER;
+ end;
+ end;
+
+
+ function ttypeconvnode.first_pointer_to_array : tnode;
+
+ begin
+ first_pointer_to_array:=nil;
+ expectloc:=LOC_REFERENCE;
+ end;
+
+
+ function ttypeconvnode.first_cchar_to_pchar : tnode;
+
+ begin
+ first_cchar_to_pchar:=nil;
+ internalerror(200104021);
+ end;
+
+
+ function ttypeconvnode.first_bool_to_int : tnode;
+
+ begin
+ first_bool_to_int:=nil;
+ { byte(boolean) or word(wordbool) or longint(longbool) must
+ be accepted for var parameters }
+ if (nf_explicit in flags) and
+ (left.resultdef.size=resultdef.size) and
+ (left.expectloc in [LOC_REFERENCE,LOC_CREFERENCE,LOC_CREGISTER]) then
+ exit;
+ { when converting to 64bit, first convert to a 32bit int and then }
+ { convert to a 64bit int (only necessary for 32bit processors) (JM) }
+ if resultdef.size > sizeof(aint) then
+ begin
+ result := ctypeconvnode.create_internal(left,s32inttype);
+ result := ctypeconvnode.create(result,resultdef);
+ left := nil;
+ firstpass(result);
+ exit;
+ end;
+ expectloc:=LOC_REGISTER;
+ end;
+
+
+ function ttypeconvnode.first_int_to_bool : tnode;
+
+ begin
+ first_int_to_bool:=nil;
+ { byte(boolean) or word(wordbool) or longint(longbool) must
+ be accepted for var parameters }
+ if (nf_explicit in flags) and
+ (left.resultdef.size=resultdef.size) and
+ (left.expectloc in [LOC_REFERENCE,LOC_CREFERENCE,LOC_CREGISTER]) then
+ exit;
+ { when converting 64bit int to C-ctyle boolean, first convert to an int32 and then }
+ { convert to a boolean (only necessary for 32bit processors) }
+ if (left.resultdef.size > sizeof(aint)) and (left.resultdef.size<>resultdef.size)
+ and is_cbool(resultdef) then
+ begin
+ left:=ctypeconvnode.create_internal(left,s32inttype);
+ firstpass(left);
+ exit;
+ end;
+ expectloc:=LOC_REGISTER;
+ end;
+
+
+ function ttypeconvnode.first_bool_to_bool : tnode;
+ begin
+ first_bool_to_bool:=nil;
+ if (left.expectloc in [LOC_FLAGS,LOC_JUMP]) then
+ expectloc := left.expectloc
+ else
+ expectloc:=LOC_REGISTER;
+ end;
+
+
+ function ttypeconvnode.first_char_to_char : tnode;
+ var
+ fname: string[18];
+ begin
+ if (torddef(resultdef).ordtype=uchar) and
+ (torddef(left.resultdef).ordtype=uwidechar) then
+ fname := 'fpc_uchar_to_char'
+ else if (torddef(resultdef).ordtype=uwidechar) and
+ (torddef(left.resultdef).ordtype=uchar) then
+ fname := 'fpc_char_to_uchar'
+ else
+ internalerror(2007081201);
+
+ result := ccallnode.createintern(fname,ccallparanode.create(left,nil));
+ left:=nil;
+ firstpass(result);
+ end;
+
+
+ function ttypeconvnode.first_proc_to_procvar : tnode;
+ begin
+ first_proc_to_procvar:=nil;
+ { if we take the address of a nested function, the current function/
+ procedure needs a stack frame since it's required to construct
+ the nested procvar }
+ if is_nested_pd(tprocvardef(resultdef)) then
+ include(current_procinfo.flags,pi_needs_stackframe);
+ if tabstractprocdef(resultdef).is_addressonly then
+ expectloc:=LOC_REGISTER
+ else
+ begin
+ if not(left.expectloc in [LOC_CREFERENCE,LOC_REFERENCE]) then
+ CGMessage(parser_e_illegal_expression);
+ expectloc:=left.expectloc;
+ end;
+ end;
+
+
+ function ttypeconvnode.first_nil_to_methodprocvar : tnode;
+ begin
+ first_nil_to_methodprocvar:=nil;
+ expectloc:=LOC_REFERENCE;
+ end;
+
+
+ function ttypeconvnode.first_set_to_set : tnode;
+ var
+ newstatement : tstatementnode;
+ temp : ttempcreatenode;
+ begin
+ { in theory, we should do range checking here,
+ but Delphi doesn't do it either (FK) }
+
+ if left.nodetype=setconstn then
+ begin
+ left.resultdef:=resultdef;
+ result:=left;
+ left:=nil;
+ end
+ { equal sets for the code generator? }
+ else if (left.resultdef.size=resultdef.size) and
+ (tsetdef(left.resultdef).setbase=tsetdef(resultdef).setbase) then
+ { TODO: This causes wrong (but Delphi-compatible) results for disjoint subsets}
+ { e.g., this prints true because of this:
+ var
+ sa: set of 1..2;
+ sb: set of 5..6;
+ b: byte;
+ begin
+ b:=1;
+ sa:=[1..2];
+ sb:=sa;
+ writeln(b in sb);
+ end.
+ }
+ begin
+ result:=left;
+ left:=nil;
+ end
+ else
+ begin
+ result:=internalstatements(newstatement);
+
+ { in case left is a smallset expression, it can be an addn or so. }
+ { fpc_varset_load expects a formal const parameter, which doesn't }
+ { accept set addn's -> assign to a temp first and pass the temp }
+ if not(left.expectloc in [LOC_REFERENCE,LOC_CREFERENCE]) then
+ begin
+ temp:=ctempcreatenode.create(left.resultdef,left.resultdef.size,tt_persistent,false);
+ addstatement(newstatement,temp);
+ { temp := left }
+ addstatement(newstatement,cassignmentnode.create(
+ ctemprefnode.create(temp),left));
+ addstatement(newstatement,ctempdeletenode.create_normal_temp(temp));
+ addstatement(newstatement,ctemprefnode.create(temp));
+ left:=result;
+ firstpass(left);
+ { recreate the result's internalstatements list }
+ result:=internalstatements(newstatement);
+ end;
+
+ { create temp for result }
+ temp:=ctempcreatenode.create(resultdef,resultdef.size,tt_persistent,true);
+ addstatement(newstatement,temp);
+
+ addstatement(newstatement,ccallnode.createintern('fpc_varset_load',
+ ccallparanode.create(cordconstnode.create(tsetdef(left.resultdef).setbase div 8 - tsetdef(resultdef).setbase div 8,sinttype,false),
+ ccallparanode.create(cordconstnode.create(resultdef.size,sinttype,false),
+ ccallparanode.create(ctemprefnode.create(temp),
+ ccallparanode.create(cordconstnode.create(left.resultdef.size,sinttype,false),
+ ccallparanode.create(left,nil))))))
+ );
+ addstatement(newstatement,ctempdeletenode.create_normal_temp(temp));
+ addstatement(newstatement,ctemprefnode.create(temp));
+ left:=nil;
+ end;
+ end;
+
+
+ function ttypeconvnode.first_ansistring_to_pchar : tnode;
+ begin
+ first_ansistring_to_pchar:=nil;
+ expectloc:=LOC_REGISTER;
+ end;
+
+
+ function ttypeconvnode.first_arrayconstructor_to_set : tnode;
+ begin
+ first_arrayconstructor_to_set:=nil;
+ internalerror(200104022);
+ end;
+
+
+ function ttypeconvnode.first_class_to_intf : tnode;
+ var
+ hd : tobjectdef;
+ ImplIntf : TImplementedInterface;
+ begin
+ result:=nil;
+ expectloc:=LOC_REGISTER;
+ hd:=tobjectdef(left.resultdef);
+ while assigned(hd) do
+ begin
+ ImplIntf:=hd.find_implemented_interface(tobjectdef(resultdef));
+ if assigned(ImplIntf) then
+ begin
+ case ImplIntf.IType of
+ etStandard:
+ { handle in pass 2 }
+ ;
+ etFieldValue, etFieldValueClass:
+ if is_interface(tobjectdef(resultdef)) then
+ begin
+ result:=left;
+ propaccesslist_to_node(result,tpropertysym(implintf.implementsgetter).owner,tpropertysym(implintf.implementsgetter).propaccesslist[palt_read]);
+ { this ensures proper refcounting when field is of class type }
+ if not is_interface(result.resultdef) then
+ inserttypeconv(result, resultdef);
+ left:=nil;
+ end
+ else
+ begin
+ internalerror(200802213);
+ end;
+ etStaticMethodResult, etStaticMethodClass,
+ etVirtualMethodResult, etVirtualMethodClass:
+ if is_interface(tobjectdef(resultdef)) then
+ begin
+ { TODO: generating a call to TObject.GetInterface instead could yield
+ smaller code size. OTOH, refcounting gotchas are possible that way. }
+ { constructor create(l:tnode; v : tprocsym;st : TSymtable; mp: tnode; callflags:tcallnodeflags); }
+ result:=ccallnode.create(nil,tprocsym(tpropertysym(implintf.implementsgetter).propaccesslist[palt_read].firstsym^.sym),
+ tprocsym(tpropertysym(implintf.implementsgetter).propaccesslist[palt_read].firstsym^.sym).owner,
+ left,[]);
+ addsymref(tpropertysym(implintf.implementsgetter).propaccesslist[palt_read].firstsym^.sym);
+ { if it is a class, process it further in a similar way }
+ if not is_interface(result.resultdef) then
+ inserttypeconv(result, resultdef);
+ left:=nil;
+ end
+ else if is_class(tobjectdef(resultdef)) then
+ begin
+ internalerror(200802211);
+ end
+ else
+ internalerror(200802231);
+ else
+ internalerror(200802165);
+ end;
+ break;
+ end;
+ hd:=hd.childof;
+ end;
+ if hd=nil then
+ internalerror(200802164);
+ end;
+
+
+ function ttypeconvnode.first_string_to_string : tnode;
+ var
+ procname: string[31];
+ newblock : tblocknode;
+ newstat : tstatementnode;
+ restemp : ttempcreatenode;
+ begin
+ { get the correct procedure name }
+ procname := 'fpc_'+tstringdef(left.resultdef).stringtypname+
+ '_to_'+tstringdef(resultdef).stringtypname;
+
+ if tstringdef(resultdef).stringtype=st_shortstring then
+ begin
+ newblock:=internalstatements(newstat);
+ restemp:=ctempcreatenode.create(resultdef,resultdef.size,tt_persistent,false);
+ addstatement(newstat,restemp);
+ addstatement(newstat,ccallnode.createintern(procname,ccallparanode.create(left,ccallparanode.create(
+ ctemprefnode.create(restemp),nil))));
+ addstatement(newstat,ctempdeletenode.create_normal_temp(restemp));
+ addstatement(newstat,ctemprefnode.create(restemp));
+ result:=newblock;
+ end
+ { encoding parameter required? }
+ else if (tstringdef(resultdef).stringtype=st_ansistring) and
+ (tstringdef(left.resultdef).stringtype in [st_widestring,st_unicodestring,st_shortstring,st_ansistring]) then
+ result:=ccallnode.createinternres(procname,
+ ccallparanode.create(cordconstnode.create(getparaencoding(resultdef),u16inttype,true),
+ ccallparanode.create(left,nil)),resultdef)
+ else
+ result:=ccallnode.createinternres(procname,ccallparanode.create(left,nil),resultdef);
+
+ left:=nil;
+ end;
+
+
+ function ttypeconvnode._first_int_to_int : tnode;
+ begin
+ result:=first_int_to_int;
+ end;
+
+ function ttypeconvnode._first_cstring_to_pchar : tnode;
+ begin
+ result:=first_cstring_to_pchar;
+ end;
+
+ function ttypeconvnode._first_cstring_to_int : tnode;
+ begin
+ result:=first_cstring_to_int;
+ end;
+
+ function ttypeconvnode._first_string_to_chararray : tnode;
+ begin
+ result:=first_string_to_chararray;
+ end;
+
+ function ttypeconvnode._first_char_to_string : tnode;
+ begin
+ result:=first_char_to_string;
+ end;
+
+ function ttypeconvnode._first_nothing : tnode;
+ begin
+ result:=first_nothing;
+ end;
+
+ function ttypeconvnode._first_array_to_pointer : tnode;
+ begin
+ result:=first_array_to_pointer;
+ end;
+
+ function ttypeconvnode._first_int_to_real : tnode;
+ begin
+ result:=first_int_to_real;
+ end;
+
+ function ttypeconvnode._first_real_to_real : tnode;
+ begin
+ result:=first_real_to_real;
+ end;
+
+ function ttypeconvnode._first_pointer_to_array : tnode;
+ begin
+ result:=first_pointer_to_array;
+ end;
+
+ function ttypeconvnode._first_cchar_to_pchar : tnode;
+ begin
+ result:=first_cchar_to_pchar;
+ end;
+
+ function ttypeconvnode._first_bool_to_int : tnode;
+ begin
+ result:=first_bool_to_int;
+ end;
+
+ function ttypeconvnode._first_int_to_bool : tnode;
+ begin
+ result:=first_int_to_bool;
+ end;
+
+ function ttypeconvnode._first_bool_to_bool : tnode;
+ begin
+ result:=first_bool_to_bool;
+ end;
+
+ function ttypeconvnode._first_proc_to_procvar : tnode;
+ begin
+ result:=first_proc_to_procvar;
+ end;
+
+ function ttypeconvnode._first_nil_to_methodprocvar : tnode;
+ begin
+ result:=first_nil_to_methodprocvar;
+ end;
+
+ function ttypeconvnode._first_set_to_set : tnode;
+ begin
+ result:=first_set_to_set;
+ end;
+
+ function ttypeconvnode._first_cord_to_pointer : tnode;
+ begin
+ result:=first_cord_to_pointer;
+ end;
+
+ function ttypeconvnode._first_ansistring_to_pchar : tnode;
+ begin
+ result:=first_ansistring_to_pchar;
+ end;
+
+ function ttypeconvnode._first_arrayconstructor_to_set : tnode;
+ begin
+ result:=first_arrayconstructor_to_set;
+ end;
+
+ function ttypeconvnode._first_class_to_intf : tnode;
+ begin
+ result:=first_class_to_intf;
+ end;
+
+ function ttypeconvnode._first_char_to_char : tnode;
+ begin
+ result:=first_char_to_char;
+ end;
+
+ function ttypeconvnode._first_string_to_string : tnode;
+ begin
+ result:=first_string_to_string;
+ end;
+
+ function ttypeconvnode.first_call_helper(c : tconverttype) : tnode;
+
+ const
+ firstconvert : array[tconverttype] of pointer = (
+ nil, { none }
+ @ttypeconvnode._first_nothing, {equal}
+ @ttypeconvnode._first_nothing, {not_possible}
+ @ttypeconvnode._first_string_to_string,
+ @ttypeconvnode._first_char_to_string,
+ @ttypeconvnode._first_nothing, { char_2_chararray, needs nothing extra }
+ nil, { removed in typecheck_chararray_to_string }
+ @ttypeconvnode._first_cchar_to_pchar,
+ @ttypeconvnode._first_cstring_to_pchar,
+ @ttypeconvnode._first_cstring_to_int,
+ @ttypeconvnode._first_ansistring_to_pchar,
+ @ttypeconvnode._first_string_to_chararray,
+ nil, { removed in typecheck_chararray_to_string }
+ @ttypeconvnode._first_array_to_pointer,
+ @ttypeconvnode._first_pointer_to_array,
+ @ttypeconvnode._first_int_to_int,
+ @ttypeconvnode._first_int_to_bool,
+ @ttypeconvnode._first_bool_to_bool,
+ @ttypeconvnode._first_bool_to_int,
+ @ttypeconvnode._first_real_to_real,
+ @ttypeconvnode._first_int_to_real,
+ nil, { removed in typecheck_real_to_currency }
+ @ttypeconvnode._first_proc_to_procvar,
+ @ttypeconvnode._first_nil_to_methodprocvar,
+ @ttypeconvnode._first_arrayconstructor_to_set,
+ @ttypeconvnode._first_set_to_set,
+ @ttypeconvnode._first_cord_to_pointer,
+ @ttypeconvnode._first_nothing,
+ @ttypeconvnode._first_nothing,
+ @ttypeconvnode._first_class_to_intf,
+ @ttypeconvnode._first_char_to_char,
+ @ttypeconvnode._first_nothing,
+ @ttypeconvnode._first_nothing,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil
+ );
+ type
+ tprocedureofobject = function : tnode of object;
+ var
+ r : packed record
+ proc : pointer;
+ obj : pointer;
+ end;
+ begin
+ { this is a little bit dirty but it works }
+ { and should be quite portable too }
+ r.proc:=firstconvert[c];
+ r.obj:=self;
+ if not assigned(r.proc) then
+ internalerror(200312081);
+ first_call_helper:=tprocedureofobject(r)()
+ end;
+
+
+ function ttypeconvnode.pass_1 : tnode;
+ begin
+ if warn_pointer_to_signed then
+ cgmessage(type_w_pointer_to_signed);
+ result:=nil;
+ firstpass(left);
+ if codegenerror then
+ exit;
+ expectloc:=left.expectloc;
+ result:=first_call_helper(convtype);
+ end;
+
+
+ function ttypeconvnode.retains_value_location:boolean;
+ begin
+ result:=(convtype=tc_equal) or
+ { typecasting from void is always allowed }
+ is_void(left.resultdef) or
+ (left.resultdef.typ=formaldef) or
+ { int 2 int with same size reuses same location, or for
+ tp7 mode also allow size < orignal size }
+ (
+ (convtype=tc_int_2_int) and
+ (
+ not is_bitpacked_access(left) and
+ (resultdef.size=left.resultdef.size) or
+ ((m_tp7 in current_settings.modeswitches) and
+ (resultdef.size<left.resultdef.size))
+ )
+ ) or
+ { int 2 bool/bool 2 int, explicit typecast, see also nx86cnv }
+ ((convtype in [tc_int_2_bool,tc_bool_2_int,tc_bool_2_bool]) and
+ (nf_explicit in flags) and
+ (resultdef.size=left.resultdef.size));
+ end;
+
+
+ function ttypeconvnode.assign_allowed:boolean;
+ begin
+ result:=retains_value_location;
+
+ { When using only a part of the value it can't be in a register since
+ that will load the value in a new register first }
+ { the same goes for changing the sign of equal-sized values which
+ are smaller than an entire register }
+ if result and
+ (resultdef.size<left.resultdef.size) or
+ ((resultdef.size=left.resultdef.size) and
+ (left.resultdef.size<sizeof(aint)) and
+ (is_signed(resultdef) xor is_signed(left.resultdef))) then
+ make_not_regable(left,[ra_addr_regable]);
+ end;
+
+
+ function ttypeconvnode.docompare(p: tnode) : boolean;
+ begin
+ docompare :=
+ inherited docompare(p) and
+ (convtype = ttypeconvnode(p).convtype) and
+ equal_defs(totypedef,ttypeconvnode(p).totypedef);
+ end;
+
+
+ procedure ttypeconvnode._second_int_to_int;
+ begin
+ second_int_to_int;
+ end;
+
+
+ procedure ttypeconvnode._second_string_to_string;
+ begin
+ second_string_to_string;
+ end;
+
+
+ procedure ttypeconvnode._second_cstring_to_pchar;
+ begin
+ second_cstring_to_pchar;
+ end;
+
+
+ procedure ttypeconvnode._second_cstring_to_int;
+ begin
+ second_cstring_to_int;
+ end;
+
+
+ procedure ttypeconvnode._second_string_to_chararray;
+ begin
+ second_string_to_chararray;
+ end;
+
+
+ procedure ttypeconvnode._second_array_to_pointer;
+ begin
+ second_array_to_pointer;
+ end;
+
+
+ procedure ttypeconvnode._second_pointer_to_array;
+ begin
+ second_pointer_to_array;
+ end;
+
+
+ procedure ttypeconvnode._second_chararray_to_string;
+ begin
+ second_chararray_to_string;
+ end;
+
+
+ procedure ttypeconvnode._second_char_to_string;
+ begin
+ second_char_to_string;
+ end;
+
+
+ procedure ttypeconvnode._second_int_to_real;
+ begin
+ second_int_to_real;
+ end;
+
+
+ procedure ttypeconvnode._second_real_to_real;
+ begin
+ second_real_to_real;
+ end;
+
+
+ procedure ttypeconvnode._second_cord_to_pointer;
+ begin
+ second_cord_to_pointer;
+ end;
+
+
+ procedure ttypeconvnode._second_proc_to_procvar;
+ begin
+ second_proc_to_procvar;
+ end;
+
+ procedure ttypeconvnode._second_nil_to_methodprocvar;
+ begin
+ second_nil_to_methodprocvar;
+ end;
+
+ procedure ttypeconvnode._second_bool_to_int;
+ begin
+ second_bool_to_int;
+ end;
+
+
+ procedure ttypeconvnode._second_int_to_bool;
+ begin
+ second_int_to_bool;
+ end;
+
+
+ procedure ttypeconvnode._second_bool_to_bool;
+ begin
+ second_bool_to_bool;
+ end;
+
+
+ procedure ttypeconvnode._second_set_to_set;
+ begin
+ second_set_to_set;
+ end;
+
+
+ procedure ttypeconvnode._second_ansistring_to_pchar;
+ begin
+ second_ansistring_to_pchar;
+ end;
+
+
+ procedure ttypeconvnode._second_class_to_intf;
+ begin
+ second_class_to_intf;
+ end;
+
+
+ procedure ttypeconvnode._second_char_to_char;
+ begin
+ second_char_to_char;
+ end;
+
+
+ procedure ttypeconvnode._second_nothing;
+ begin
+ second_nothing;
+ end;
+
+
+ procedure ttypeconvnode.second_call_helper(c : tconverttype);
+ const
+ secondconvert : array[tconverttype] of pointer = (
+ @ttypeconvnode._second_nothing, {none}
+ @ttypeconvnode._second_nothing, {equal}
+ @ttypeconvnode._second_nothing, {not_possible}
+ @ttypeconvnode._second_nothing, {second_string_to_string, handled in resultdef pass }
+ @ttypeconvnode._second_char_to_string,
+ @ttypeconvnode._second_nothing, {char_to_charray}
+ @ttypeconvnode._second_nothing, { pchar_to_string, handled in resultdef pass }
+ @ttypeconvnode._second_nothing, {cchar_to_pchar}
+ @ttypeconvnode._second_cstring_to_pchar,
+ @ttypeconvnode._second_cstring_to_int,
+ @ttypeconvnode._second_ansistring_to_pchar,
+ @ttypeconvnode._second_string_to_chararray,
+ @ttypeconvnode._second_nothing, { chararray_to_string, handled in resultdef pass }
+ @ttypeconvnode._second_array_to_pointer,
+ @ttypeconvnode._second_pointer_to_array,
+ @ttypeconvnode._second_int_to_int,
+ @ttypeconvnode._second_int_to_bool,
+ @ttypeconvnode._second_bool_to_bool,
+ @ttypeconvnode._second_bool_to_int,
+ @ttypeconvnode._second_real_to_real,
+ @ttypeconvnode._second_int_to_real,
+ @ttypeconvnode._second_nothing, { real_to_currency, handled in resultdef pass }
+ @ttypeconvnode._second_proc_to_procvar,
+ @ttypeconvnode._second_nil_to_methodprocvar,
+ @ttypeconvnode._second_nothing, { arrayconstructor_to_set }
+ @ttypeconvnode._second_nothing, { second_set_to_set, handled in first pass }
+ @ttypeconvnode._second_cord_to_pointer,
+ @ttypeconvnode._second_nothing, { interface 2 string }
+ @ttypeconvnode._second_nothing, { interface 2 guid }
+ @ttypeconvnode._second_class_to_intf,
+ @ttypeconvnode._second_char_to_char,
+ @ttypeconvnode._second_nothing, { dynarray_2_openarray }
+ @ttypeconvnode._second_nothing, { pwchar_2_string }
+ @ttypeconvnode._second_nothing, { variant_2_dynarray }
+ @ttypeconvnode._second_nothing, { dynarray_2_variant}
+ @ttypeconvnode._second_nothing, { variant_2_enum }
+ @ttypeconvnode._second_nothing, { enum_2_variant }
+ @ttypeconvnode._second_nothing, { variant_2_interface }
+ @ttypeconvnode._second_nothing, { interface_2_variant }
+ @ttypeconvnode._second_nothing { array_2_dynarray }
+ );
+ type
+ tprocedureofobject = procedure of object;
+
+ var
+ r : packed record
+ proc : pointer;
+ obj : pointer;
+ end;
+
+ begin
+ { this is a little bit dirty but it works }
+ { and should be quite portable too }
+ r.proc:=secondconvert[c];
+ r.obj:=self;
+ tprocedureofobject(r)();
+ end;
+
+{*****************************************************************************
+ TASNODE
+*****************************************************************************}
+
+ function tasisnode.pass_typecheck: tnode;
+ var
+ hp : tnode;
+ begin
+ result:=nil;
+ typecheckpass(right);
+ typecheckpass(left);
+
+ set_varstate(right,vs_read,[vsf_must_be_valid]);
+ set_varstate(left,vs_read,[vsf_must_be_valid]);
+
+ if codegenerror then
+ exit;
+
+ if (right.resultdef.typ=classrefdef) then
+ begin
+ { left maybe an interface reference }
+ if is_interfacecom(left.resultdef) then
+ begin
+ { relation checks are not possible }
+ end
+ { or left must be a class }
+ else if is_class(left.resultdef) then
+ begin
+ { the operands must be related }
+ if (not(tobjectdef(left.resultdef).is_related(
+ tobjectdef(tclassrefdef(right.resultdef).pointeddef)))) and
+ (not(tobjectdef(tclassrefdef(right.resultdef).pointeddef).is_related(
+ tobjectdef(left.resultdef)))) then
+ CGMessage2(type_e_classes_not_related,
+ FullTypeName(left.resultdef,tclassrefdef(right.resultdef).pointeddef),
+ FullTypeName(tclassrefdef(right.resultdef).pointeddef,left.resultdef));
+ end
+ else
+ CGMessage1(type_e_class_or_cominterface_type_expected,left.resultdef.typename);
+ case nodetype of
+ isn:
+ resultdef:=pasbool8type;
+ asn:
+ resultdef:=tclassrefdef(right.resultdef).pointeddef;
+ end;
+ end
+ else if is_interface(right.resultdef) or is_dispinterface(right.resultdef) then
+ begin
+ { left is a class }
+ if not(is_class(left.resultdef) or
+ is_interfacecom(left.resultdef)) then
+ CGMessage1(type_e_class_or_cominterface_type_expected,left.resultdef.typename);
+
+ case nodetype of
+ isn:
+ resultdef:=pasbool8type;
+ asn:
+ resultdef:=right.resultdef;
+ end;
+
+ { load the GUID of the interface }
+ if (right.nodetype=typen) then
+ begin
+ if tobjectdef(right.resultdef).objecttype=odt_interfacecorba then
+ begin
+ if assigned(tobjectdef(right.resultdef).iidstr) then
+ begin
+ hp:=cstringconstnode.createstr(tobjectdef(right.resultdef).iidstr^);
+ tstringconstnode(hp).changestringtype(cshortstringtype);
+ right.free;
+ right:=hp;
+ end
+ else
+ internalerror(201006131);
+ end
+ else
+ begin
+ if assigned(tobjectdef(right.resultdef).iidguid) then
+ begin
+ if not(oo_has_valid_guid in tobjectdef(right.resultdef).objectoptions) then
+ CGMessage1(type_e_interface_has_no_guid,tobjectdef(right.resultdef).typename);
+ hp:=cguidconstnode.create(tobjectdef(right.resultdef).iidguid^);
+ right.free;
+ right:=hp;
+ end
+ else
+ internalerror(201006132);
+ end;
+ typecheckpass(right);
+ end;
+ end
+ else
+ CGMessage1(type_e_class_or_interface_type_expected,right.resultdef.typename);
+ end;
+
+{*****************************************************************************
+ TISNODE
+*****************************************************************************}
+
+ constructor tisnode.create(l,r : tnode);
+
+ begin
+ inherited create(isn,l,r);
+ end;
+
+ function tisnode.pass_1 : tnode;
+ var
+ procname: string;
+ begin
+ result:=nil;
+ { Passing a class type to an "is" expression cannot result in a class
+ of that type to be constructed.
+ }
+ include(right.flags,nf_ignore_for_wpo);
+
+ if is_class(left.resultdef) and
+ (right.resultdef.typ=classrefdef) then
+ result := ccallnode.createinternres('fpc_do_is',
+ ccallparanode.create(left,ccallparanode.create(right,nil)),
+ resultdef)
+ else
+ begin
+ if is_class(left.resultdef) then
+ if is_shortstring(right.resultdef) then
+ procname := 'fpc_class_is_corbaintf'
+ else
+ procname := 'fpc_class_is_intf'
+ else
+ if right.resultdef.typ=classrefdef then
+ procname := 'fpc_intf_is_class'
+ else
+ procname := 'fpc_intf_is';
+ result := ctypeconvnode.create_internal(ccallnode.createintern(procname,
+ ccallparanode.create(right,ccallparanode.create(left,nil))),resultdef);
+ end;
+ left := nil;
+ right := nil;
+ //firstpass(call);
+ if codegenerror then
+ exit;
+ end;
+
+ { dummy pass_2, it will never be called, but we need one since }
+ { you can't instantiate an abstract class }
+ procedure tisnode.pass_generate_code;
+ begin
+ end;
+
+
+{*****************************************************************************
+ TASNODE
+*****************************************************************************}
+
+ constructor tasnode.create(l,r : tnode);
+
+ begin
+ inherited create(asn,l,r);
+ call := nil;
+ end;
+
+
+ destructor tasnode.destroy;
+
+ begin
+ call.free;
+ inherited destroy;
+ end;
+
+
+ function tasnode.dogetcopy: tnode;
+ begin
+ result := inherited dogetcopy;
+ if assigned(call) then
+ tasnode(result).call := call.getcopy
+ else
+ tasnode(result).call := nil;
+ end;
+
+
+ function tasnode.docompare(p: tnode): boolean;
+ begin
+ result:=
+ inherited docompare(p) and
+ tasnode(p).call.isequal(call);
+ end;
+
+
+ function tasnode.pass_1 : tnode;
+ var
+ procname: string;
+ begin
+ result:=nil;
+ { Passing a class type to an "as" expression cannot result in a class
+ of that type to be constructed.
+ }
+ include(right.flags,nf_ignore_for_wpo);
+ if not assigned(call) then
+ begin
+ if is_class(left.resultdef) and
+ (right.resultdef.typ=classrefdef) then
+ call := ccallnode.createinternres('fpc_do_as',
+ ccallparanode.create(left,ccallparanode.create(right,nil)),
+ resultdef)
+ else
+ begin
+ if is_class(left.resultdef) then
+ if is_shortstring(right.resultdef) then
+ procname := 'fpc_class_as_corbaintf'
+ else
+ procname := 'fpc_class_as_intf'
+ else
+ if right.resultdef.typ=classrefdef then
+ procname := 'fpc_intf_as_class'
+ else
+ procname := 'fpc_intf_as';
+ call := ctypeconvnode.create_internal(ccallnode.createintern(procname,
+ ccallparanode.create(right,ccallparanode.create(left,nil))),resultdef);
+ end;
+ left := nil;
+ right := nil;
+ firstpass(call);
+ if codegenerror then
+ exit;
+ expectloc:=call.expectloc;
+ end;
+ end;
+
+end.
diff --git a/closures/compiler/ncon.pas b/closures/compiler/ncon.pas
new file mode 100644
index 0000000000..60141f3b61
--- /dev/null
+++ b/closures/compiler/ncon.pas
@@ -0,0 +1,1314 @@
+{
+ Copyright (c) 2000-2002 by Florian Klaempfl
+
+ Type checking and register allocation for constants
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit ncon;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ globtype,widestr,constexp,
+ cclasses,
+ node,
+ aasmbase,aasmtai,aasmdata,cpuinfo,globals,
+ symconst,symtype,symdef,symsym;
+
+ type
+ tdataconstnode = class(tnode)
+ data : tdynamicarray;
+ maxalign : word;
+ constructor create;virtual;
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
+ destructor destroy;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ function dogetcopy : tnode;override;
+ function pass_1 : tnode;override;
+ function pass_typecheck:tnode;override;
+ function docompare(p: tnode) : boolean; override;
+ procedure printnodedata(var t:text);override;
+ procedure append(const d;len : aint);
+ procedure appendbyte(b : byte);
+ procedure align(value : word);
+ end;
+ tdataconstnodeclass = class of tdataconstnode;
+
+ trealconstnode = class(tnode)
+ typedef : tdef;
+ typedefderef : tderef;
+ value_real : bestreal;
+ value_currency : currency;
+ lab_real : tasmlabel;
+ constructor create(v : bestreal;def:tdef);virtual;
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderefimpl;override;
+ procedure derefimpl;override;
+ function dogetcopy : tnode;override;
+ function pass_1 : tnode;override;
+ function pass_typecheck:tnode;override;
+ function docompare(p: tnode) : boolean; override;
+ procedure printnodedata(var t:text);override;
+ end;
+ trealconstnodeclass = class of trealconstnode;
+
+ tordconstnode = class(tnode)
+ typedef : tdef;
+ typedefderef : tderef;
+ value : TConstExprInt;
+ rangecheck : boolean;
+ { create an ordinal constant node of the specified type and value.
+ _rangecheck determines if the value of the ordinal should be checked
+ against the ranges of the type definition.
+ }
+ constructor create(v : tconstexprint;def:tdef; _rangecheck : boolean);virtual;
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderefimpl;override;
+ procedure derefimpl;override;
+ function dogetcopy : tnode;override;
+ function pass_1 : tnode;override;
+ function pass_typecheck:tnode;override;
+ function docompare(p: tnode) : boolean; override;
+ procedure printnodedata(var t:text);override;
+ end;
+ tordconstnodeclass = class of tordconstnode;
+
+ tpointerconstnode = class(tnode)
+ typedef : tdef;
+ typedefderef : tderef;
+ value : TConstPtrUInt;
+ constructor create(v : TConstPtrUInt;def:tdef);virtual;
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderefimpl;override;
+ procedure derefimpl;override;
+ function dogetcopy : tnode;override;
+ function pass_1 : tnode;override;
+ function pass_typecheck:tnode;override;
+ function docompare(p: tnode) : boolean; override;
+ end;
+ tpointerconstnodeclass = class of tpointerconstnode;
+
+ tconststringtype = (
+ cst_conststring,
+ cst_shortstring,
+ cst_longstring,
+ cst_ansistring,
+ cst_widestring,
+ cst_unicodestring
+ );
+
+ tstringconstnode = class(tnode)
+ value_str : pchar;
+ len : longint;
+ lab_str : tasmlabel;
+ cst_type : tconststringtype;
+ constructor createstr(const s : string);virtual;
+ constructor createpchar(s : pchar;l : longint);virtual;
+ constructor createwstr(w : pcompilerwidestring);virtual;
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderefimpl;override;
+ procedure derefimpl;override;
+ destructor destroy;override;
+ function dogetcopy : tnode;override;
+ function pass_1 : tnode;override;
+ function pass_typecheck:tnode;override;
+ function getpcharcopy : pchar;
+ function docompare(p: tnode) : boolean; override;
+ procedure changestringtype(def:tdef);
+ function fullcompare(p: tstringconstnode): longint;
+ end;
+ tstringconstnodeclass = class of tstringconstnode;
+
+ tsetconstnode = class(tunarynode)
+ typedef : tdef;
+ typedefderef : tderef;
+ value_set : pconstset;
+ lab_set : tasmlabel;
+ constructor create(s : pconstset;def:tdef);virtual;
+ destructor destroy;override;
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderefimpl;override;
+ procedure derefimpl;override;
+ procedure adjustforsetbase;
+ function dogetcopy : tnode;override;
+ function pass_1 : tnode;override;
+ function pass_typecheck:tnode;override;
+ function docompare(p: tnode) : boolean; override;
+ end;
+ tsetconstnodeclass = class of tsetconstnode;
+
+ tnilnode = class(tnode)
+ constructor create;virtual;
+ function pass_1 : tnode;override;
+ function pass_typecheck:tnode;override;
+ end;
+ tnilnodeclass = class of tnilnode;
+
+ tguidconstnode = class(tnode)
+ value : tguid;
+ constructor create(const g:tguid);virtual;
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ function dogetcopy : tnode;override;
+ function pass_1 : tnode;override;
+ function pass_typecheck:tnode;override;
+ function docompare(p: tnode) : boolean; override;
+ end;
+ tguidconstnodeclass = class of tguidconstnode;
+
+ var
+ crealconstnode : trealconstnodeclass = trealconstnode;
+ cordconstnode : tordconstnodeclass = tordconstnode;
+ cpointerconstnode : tpointerconstnodeclass = tpointerconstnode;
+ cstringconstnode : tstringconstnodeclass = tstringconstnode;
+ csetconstnode : tsetconstnodeclass = tsetconstnode;
+ cguidconstnode : tguidconstnodeclass = tguidconstnode;
+ cnilnode : tnilnodeclass=tnilnode;
+ cdataconstnode : tdataconstnodeclass = tdataconstnode;
+
+ function genintconstnode(v : TConstExprInt) : tordconstnode;
+ function genenumnode(v : tenumsym) : tordconstnode;
+
+ { some helper routines }
+ function get_ordinal_value(p : tnode) : TConstExprInt;
+ function get_string_value(p : tnode; def: tstringdef) : tstringconstnode;
+ function is_constresourcestringnode(p : tnode) : boolean;
+ function is_emptyset(p : tnode):boolean;
+ function genconstsymtree(p : tconstsym) : tnode;
+
+implementation
+
+ uses
+ cutils,
+ verbose,systems,sysutils,
+ defutil,
+ cpubase,cgbase,
+ nld;
+
+ function genintconstnode(v : TConstExprInt) : tordconstnode;
+ var
+ htype : tdef;
+ begin
+ int_to_type(v,htype);
+ genintconstnode:=cordconstnode.create(v,htype,true);
+ end;
+
+
+ function genenumnode(v : tenumsym) : tordconstnode;
+ var
+ htype : tdef;
+ begin
+ htype:=v.definition;
+ genenumnode:=cordconstnode.create(int64(v.value),htype,true);
+ end;
+
+
+ function get_ordinal_value(p : tnode) : TConstExprInt;
+ begin
+ get_ordinal_value:=0;
+ if is_constnode(p) then
+ begin
+ if p.nodetype=ordconstn then
+ get_ordinal_value:=tordconstnode(p).value
+ else
+ Message(type_e_ordinal_expr_expected);
+ end
+ else
+ Message(type_e_constant_expr_expected);
+ end;
+
+ function get_string_value(p: tnode; def: tstringdef): tstringconstnode;
+ var
+ stringVal: string;
+ pWideStringVal: pcompilerwidestring;
+ begin
+ if is_constcharnode(p) then
+ begin
+ SetLength(stringVal,1);
+ stringVal[1]:=char(tordconstnode(p).value.uvalue);
+ result:=cstringconstnode.createstr(stringVal);
+ end
+ else if is_constwidecharnode(p) then
+ begin
+ initwidestring(pWideStringVal);
+ concatwidestringchar(pWideStringVal, tcompilerwidechar(tordconstnode(p).value.uvalue));
+ result:=cstringconstnode.createwstr(pWideStringVal);
+ end
+ else if is_conststringnode(p) then
+ result:=tstringconstnode(p.getcopy)
+ else
+ begin
+ Message(type_e_string_expr_expected);
+ stringVal:='';
+ result:=cstringconstnode.createstr(stringVal);
+ end;
+ result.changestringtype(def);
+ end;
+
+
+ function is_constresourcestringnode(p : tnode) : boolean;
+ begin
+ is_constresourcestringnode:=(p.nodetype=loadn) and
+ (tloadnode(p).symtableentry.typ=constsym) and
+ (tconstsym(tloadnode(p).symtableentry).consttyp=constresourcestring);
+ end;
+
+
+ function is_emptyset(p : tnode):boolean;
+ begin
+ is_emptyset:=(p.nodetype=setconstn) and
+ (Tsetconstnode(p).value_set^=[]);
+ end;
+
+
+ function genconstsymtree(p : tconstsym) : tnode;
+ var
+ p1 : tnode;
+ len : longint;
+ pc : pchar;
+ begin
+ p1:=nil;
+ case p.consttyp of
+ constord :
+ begin
+ if p.constdef=nil then
+ internalerror(200403232);
+ p1:=cordconstnode.create(p.value.valueord,p.constdef,true);
+ end;
+ conststring :
+ begin
+ len:=p.value.len;
+ if not(cs_ansistrings in current_settings.localswitches) and (len>255) then
+ begin
+ message(parser_e_string_const_too_long);
+ len:=255;
+ end;
+ getmem(pc,len+1);
+ move(pchar(p.value.valueptr)^,pc^,len);
+ pc[len]:=#0;
+ p1:=cstringconstnode.createpchar(pc,len);
+ end;
+ constwstring :
+ p1:=cstringconstnode.createwstr(pcompilerwidestring(p.value.valueptr));
+ constreal :
+ p1:=crealconstnode.create(pbestreal(p.value.valueptr)^,pbestrealtype^);
+ constset :
+ p1:=csetconstnode.create(pconstset(p.value.valueptr),p.constdef);
+ constpointer :
+ p1:=cpointerconstnode.create(p.value.valueordptr,p.constdef);
+ constnil :
+ p1:=cnilnode.create;
+ constguid :
+ p1:=cguidconstnode.create(pguid(p.value.valueptr)^);
+ else
+ internalerror(200205103);
+ end;
+ genconstsymtree:=p1;
+ end;
+
+
+{*****************************************************************************
+ TDATACONSTNODE
+*****************************************************************************}
+
+ constructor tdataconstnode.create;
+ begin
+ inherited create(dataconstn);
+ data:=tdynamicarray.create(128);
+ end;
+
+
+ constructor tdataconstnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+ var
+ len : tcgint;
+ buf : array[0..255] of byte;
+ begin
+ inherited ppuload(t,ppufile);
+ len:=ppufile.getaint;
+ if len<4096 then
+ data:=tdynamicarray.create(len)
+ else
+ data:=tdynamicarray.create(4096);
+ while len>0 do
+ begin
+ if len>sizeof(buf) then
+ begin
+ ppufile.getdata(buf,sizeof(buf));
+ data.write(buf,sizeof(buf));
+ dec(len,sizeof(buf));
+ end
+ else
+ begin
+ ppufile.getdata(buf,len);
+ data.write(buf,len);
+ len:=0;
+ end;
+ end;
+ end;
+
+
+ destructor tdataconstnode.destroy;
+ begin
+ data.free;
+ inherited destroy;
+ end;
+
+
+ procedure tdataconstnode.ppuwrite(ppufile:tcompilerppufile);
+ var
+ len : tcgint;
+ buf : array[0..255] of byte;
+ begin
+ inherited ppuwrite(ppufile);
+ len:=data.size;
+ ppufile.putaint(len);
+ data.seek(0);
+ while len>0 do
+ begin
+ if len>sizeof(buf) then
+ begin
+ data.read(buf,sizeof(buf));
+ ppufile.putdata(buf,sizeof(buf));
+ dec(len,sizeof(buf));
+ end
+ else
+ begin
+ data.read(buf,len);
+ ppufile.putdata(buf,len);
+ len:=0;
+ end;
+ end;
+ end;
+
+
+ function tdataconstnode.dogetcopy : tnode;
+ var
+ n : tdataconstnode;
+ len : tcgint;
+ buf : array[0..255] of byte;
+ begin
+ n:=tdataconstnode(inherited dogetcopy);
+ len:=data.size;
+ if len<4096 then
+ n.data:=tdynamicarray.create(len)
+ else
+ n.data:=tdynamicarray.create(4096);
+ data.seek(0);
+ while len>0 do
+ begin
+ if len>sizeof(buf) then
+ begin
+ data.read(buf,sizeof(buf));
+ n.data.write(buf,sizeof(buf));
+ dec(len,sizeof(buf));
+ end
+ else
+ begin
+ data.read(buf,len);
+ n.data.write(buf,len);
+ len:=0;
+ end;
+ end;
+ dogetcopy := n;
+ end;
+
+
+ function tdataconstnode.pass_1 : tnode;
+ begin
+ result:=nil;
+ expectloc:=LOC_CREFERENCE;
+ end;
+
+
+ function tdataconstnode.pass_typecheck:tnode;
+ begin
+ result:=nil;
+ resultdef:=voidpointertype;
+ end;
+
+
+ function tdataconstnode.docompare(p: tnode) : boolean;
+ var
+ b1,b2 : byte;
+ I : longint;
+ begin
+ docompare :=
+ inherited docompare(p) and (data.size=tdataconstnode(p).data.size);
+ if docompare then
+ begin
+ data.seek(0);
+ tdataconstnode(p).data.seek(0);
+ for i:=0 to data.size-1 do
+ begin
+ data.read(b1,1);
+ tdataconstnode(p).data.read(b2,1);
+ if b1<>b2 then
+ begin
+ docompare:=false;
+ exit;
+ end;
+ end;
+ end;
+ end;
+
+
+ procedure tdataconstnode.printnodedata(var t:text);
+ var
+ i : longint;
+ b : byte;
+ begin
+ inherited printnodedata(t);
+ write(t,printnodeindention,'data size = ',data.size,' data = ');
+ data.seek(0);
+ for i:=0 to data.size-1 do
+ begin
+ data.read(b,1);
+ if i=data.size-1 then
+ writeln(t,b)
+ else
+ write(t,b,',');
+ end;
+ end;
+
+
+ procedure tdataconstnode.append(const d;len : aint);
+ begin
+ data.seek(data.size);
+ data.write(d,len);
+ end;
+
+ procedure tdataconstnode.appendbyte(b : byte);
+ begin
+ data.seek(data.size);
+ data.write(b,1);
+ end;
+
+ procedure tdataconstnode.align(value : word);
+ begin
+ if value>maxalign then
+ maxalign:=value;
+ data.align(value);
+ end;
+
+{*****************************************************************************
+ TREALCONSTNODE
+*****************************************************************************}
+
+ { generic code }
+ { overridden by: }
+ { i386 }
+ constructor trealconstnode.create(v : bestreal;def:tdef);
+ begin
+ if current_settings.fputype=fpu_none then
+ internalerror(2008022401);
+ inherited create(realconstn);
+ typedef:=def;
+ value_real:=v;
+ value_currency:=v;
+ lab_real:=nil;
+ end;
+
+ constructor trealconstnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+ var
+ i : int64;
+ begin
+ inherited ppuload(t,ppufile);
+ ppufile.getderef(typedefderef);
+ value_real:=ppufile.getreal;
+ i:=ppufile.getint64;
+ value_currency:=PCurrency(@i)^;
+ lab_real:=tasmlabel(ppufile.getasmsymbol);
+ end;
+
+
+ procedure trealconstnode.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putderef(typedefderef);
+ ppufile.putreal(value_real);
+ ppufile.putint64(PInt64(@value_currency)^);
+ ppufile.putasmsymbol(lab_real);
+ end;
+
+
+ procedure trealconstnode.buildderefimpl;
+ begin
+ inherited buildderefimpl;
+ typedefderef.build(typedef);
+ end;
+
+
+ procedure trealconstnode.derefimpl;
+ begin
+ inherited derefimpl;
+ typedef:=tdef(typedefderef.resolve);
+ end;
+
+
+ function trealconstnode.dogetcopy : tnode;
+ var
+ n : trealconstnode;
+ begin
+ n:=trealconstnode(inherited dogetcopy);
+ n.value_real:=value_real;
+ n.value_currency:=value_currency;
+ n.lab_real:=lab_real;
+ dogetcopy:=n;
+ end;
+
+ function trealconstnode.pass_typecheck:tnode;
+ begin
+ result:=nil;
+ resultdef:=typedef;
+ end;
+
+ function trealconstnode.pass_1 : tnode;
+ begin
+ result:=nil;
+ expectloc:=LOC_CREFERENCE;
+ end;
+
+ function trealconstnode.docompare(p: tnode): boolean;
+ begin
+ docompare :=
+ inherited docompare(p) and
+ (value_real = trealconstnode(p).value_real) and
+ { floating point compares for non-numbers give strange results usually }
+ is_number_float(value_real) and
+ is_number_float(trealconstnode(p).value_real);
+ end;
+
+
+ procedure Trealconstnode.printnodedata(var t:text);
+ begin
+ inherited printnodedata(t);
+ writeln(t,printnodeindention,'value = ',value_real);
+ end;
+
+
+{*****************************************************************************
+ TORDCONSTNODE
+*****************************************************************************}
+
+ constructor tordconstnode.create(v : tconstexprint;def:tdef;_rangecheck : boolean);
+
+ begin
+ inherited create(ordconstn);
+ value:=v;
+ typedef:=def;
+ rangecheck := _rangecheck;
+ end;
+
+
+ constructor tordconstnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ ppufile.getderef(typedefderef);
+ value:=ppufile.getexprint;
+ { normally, the value is already compiled, so we don't need
+ to do once again a range check
+ }
+ rangecheck := false;
+ end;
+
+
+ procedure tordconstnode.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putderef(typedefderef);
+ ppufile.putexprint(value);
+ end;
+
+
+ procedure tordconstnode.buildderefimpl;
+ begin
+ inherited buildderefimpl;
+ typedefderef.build(typedef);
+ end;
+
+
+ procedure tordconstnode.derefimpl;
+ begin
+ inherited derefimpl;
+ typedef:=tdef(typedefderef.resolve);
+ end;
+
+
+ function tordconstnode.dogetcopy : tnode;
+
+ var
+ n : tordconstnode;
+
+ begin
+ n:=tordconstnode(inherited dogetcopy);
+ n.value:=value;
+ n.typedef := typedef;
+ dogetcopy:=n;
+ end;
+
+ function tordconstnode.pass_typecheck:tnode;
+ begin
+ result:=nil;
+ resultdef:=typedef;
+ { only do range checking when explicitly asked for it
+ and if the type can be range checked, see tests/tbs/tb0539.pp }
+ if (resultdef.typ in [orddef,enumdef]) then
+ testrange(resultdef,value,not rangecheck,false)
+ end;
+
+ function tordconstnode.pass_1 : tnode;
+ begin
+ result:=nil;
+ expectloc:=LOC_CONSTANT;
+ end;
+
+ function tordconstnode.docompare(p: tnode): boolean;
+ begin
+ docompare :=
+ inherited docompare(p) and
+ (value = tordconstnode(p).value);
+ end;
+
+
+ procedure Tordconstnode.printnodedata(var t:text);
+ begin
+ inherited printnodedata(t);
+ writeln(t,printnodeindention,'value = ',tostr(value));
+ end;
+
+
+{*****************************************************************************
+ TPOINTERCONSTNODE
+*****************************************************************************}
+
+ constructor tpointerconstnode.create(v : TConstPtrUInt;def:tdef);
+
+ begin
+ inherited create(pointerconstn);
+ value:=v;
+ typedef:=def;
+ end;
+
+
+ constructor tpointerconstnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ ppufile.getderef(typedefderef);
+ value:=ppufile.getptruint;
+ end;
+
+
+ procedure tpointerconstnode.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putderef(typedefderef);
+ ppufile.putptruint(value);
+ end;
+
+
+ procedure tpointerconstnode.buildderefimpl;
+ begin
+ inherited buildderefimpl;
+ typedefderef.build(typedef);
+ end;
+
+
+ procedure tpointerconstnode.derefimpl;
+ begin
+ inherited derefimpl;
+ typedef:=tdef(typedefderef.resolve);
+ end;
+
+
+ function tpointerconstnode.dogetcopy : tnode;
+
+ var
+ n : tpointerconstnode;
+
+ begin
+ n:=tpointerconstnode(inherited dogetcopy);
+ n.value:=value;
+ n.typedef := typedef;
+ dogetcopy:=n;
+ end;
+
+ function tpointerconstnode.pass_typecheck:tnode;
+ begin
+ result:=nil;
+ resultdef:=typedef;
+ end;
+
+ function tpointerconstnode.pass_1 : tnode;
+ begin
+ result:=nil;
+ expectloc:=LOC_CONSTANT;
+ end;
+
+ function tpointerconstnode.docompare(p: tnode): boolean;
+ begin
+ docompare :=
+ inherited docompare(p) and
+ (value = tpointerconstnode(p).value);
+ end;
+
+
+{*****************************************************************************
+ TSTRINGCONSTNODE
+*****************************************************************************}
+
+ constructor tstringconstnode.createstr(const s : string);
+ var
+ l : longint;
+ begin
+ inherited create(stringconstn);
+ l:=length(s);
+ len:=l;
+ { stringdup write even past a #0 }
+ getmem(value_str,l+1);
+ move(s[1],value_str^,l);
+ value_str[l]:=#0;
+ lab_str:=nil;
+ cst_type:=cst_conststring;
+ end;
+
+
+ constructor tstringconstnode.createwstr(w : pcompilerwidestring);
+ begin
+ inherited create(stringconstn);
+ len:=getlengthwidestring(w);
+ initwidestring(pcompilerwidestring(value_str));
+ copywidestring(w,pcompilerwidestring(value_str));
+ lab_str:=nil;
+ cst_type:=cst_widestring;
+ end;
+
+
+ constructor tstringconstnode.createpchar(s : pchar;l : longint);
+ begin
+ inherited create(stringconstn);
+ len:=l;
+ value_str:=s;
+ cst_type:=cst_conststring;
+ lab_str:=nil;
+ end;
+
+
+ destructor tstringconstnode.destroy;
+ begin
+ if cst_type in [cst_widestring,cst_unicodestring] then
+ donewidestring(pcompilerwidestring(value_str))
+ else
+ ansistringdispose(value_str,len);
+ inherited destroy;
+ end;
+
+
+ constructor tstringconstnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+ var
+ pw : pcompilerwidestring;
+ i : longint;
+ begin
+ inherited ppuload(t,ppufile);
+ cst_type:=tconststringtype(ppufile.getbyte);
+ len:=ppufile.getlongint;
+ if cst_type in [cst_widestring,cst_unicodestring] then
+ begin
+ initwidestring(pw);
+ setlengthwidestring(pw,len);
+ { don't use getdata, because the compilerwidechars may have to
+ be byteswapped
+ }
+{$if sizeof(tcompilerwidechar) = 2}
+ for i:=0 to pw^.len-1 do
+ pw^.data[i]:=ppufile.getword;
+{$elseif sizeof(tcompilerwidechar) = 4}
+ for i:=0 to pw^.len-1 do
+ pw^.data[i]:=cardinal(ppufile.getlongint);
+{$else}
+ {$error Unsupported tcompilerwidechar size}
+{$endif}
+ pcompilerwidestring(value_str):=pw
+ end
+ else
+ begin
+ getmem(value_str,len+1);
+ ppufile.getdata(value_str^,len);
+ value_str[len]:=#0;
+ end;
+ lab_str:=tasmlabel(ppufile.getasmsymbol);
+ end;
+
+
+ procedure tstringconstnode.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putbyte(byte(cst_type));
+ ppufile.putlongint(len);
+ if cst_type in [cst_widestring,cst_unicodestring] then
+ ppufile.putdata(pcompilerwidestring(value_str)^.data^,len*sizeof(tcompilerwidechar))
+ else
+ ppufile.putdata(value_str^,len);
+ ppufile.putasmsymbol(lab_str);
+ end;
+
+
+ procedure tstringconstnode.buildderefimpl;
+ begin
+ inherited buildderefimpl;
+ end;
+
+
+ procedure tstringconstnode.derefimpl;
+ begin
+ inherited derefimpl;
+ end;
+
+
+ function tstringconstnode.dogetcopy : tnode;
+
+ var
+ n : tstringconstnode;
+
+ begin
+ n:=tstringconstnode(inherited dogetcopy);
+ n.cst_type:=cst_type;
+ n.len:=len;
+ n.lab_str:=lab_str;
+ if cst_type in [cst_widestring,cst_unicodestring] then
+ begin
+ initwidestring(pcompilerwidestring(n.value_str));
+ copywidestring(pcompilerwidestring(value_str),pcompilerwidestring(n.value_str));
+ end
+ else
+ n.value_str:=getpcharcopy;
+ dogetcopy:=n;
+ end;
+
+ function tstringconstnode.pass_typecheck:tnode;
+ var
+ l : aint;
+ begin
+ result:=nil;
+ case cst_type of
+ cst_conststring :
+ begin
+ { handle and store as array[0..len-1] of char }
+ if len>0 then
+ l:=len-1
+ else
+ l:=0;
+ resultdef:=tarraydef.create(0,l,s32inttype);
+ tarraydef(resultdef).elementdef:=cchartype;
+ include(tarraydef(resultdef).arrayoptions,ado_IsConstString);
+ end;
+ cst_shortstring :
+ resultdef:=cshortstringtype;
+ cst_ansistring :
+ resultdef:=getansistringdef;
+ cst_unicodestring :
+ resultdef:=cunicodestringtype;
+ cst_widestring :
+ resultdef:=cwidestringtype;
+ cst_longstring :
+ resultdef:=clongstringtype;
+ end;
+ end;
+
+ function tstringconstnode.pass_1 : tnode;
+ begin
+ result:=nil;
+ if (cst_type in [cst_ansistring,cst_widestring,cst_unicodestring]) then
+ begin
+ if len=0 then
+ expectloc:=LOC_CONSTANT
+ else
+ expectloc:=LOC_REGISTER
+ end
+ else
+ expectloc:=LOC_CREFERENCE;
+ end;
+
+
+ function tstringconstnode.getpcharcopy : pchar;
+ var
+ pc : pchar;
+ begin
+ pc:=nil;
+ getmem(pc,len+1);
+ if pc=nil then
+ Message(general_f_no_memory_left);
+ move(value_str^,pc^,len+1);
+ getpcharcopy:=pc;
+ end;
+
+ function tstringconstnode.docompare(p: tnode): boolean;
+ begin
+ docompare :=
+ inherited docompare(p) and
+ (len = tstringconstnode(p).len) and
+ { Don't compare the pchars, since they may contain null chars }
+ { Since all equal constant strings are replaced by the same }
+ { label, the following compare should be enough (JM) }
+ (lab_str = tstringconstnode(p).lab_str);
+ end;
+
+
+ procedure tstringconstnode.changestringtype(def:tdef);
+ const
+ st2cst : array[tstringtype] of tconststringtype = (
+ cst_shortstring,cst_longstring,cst_ansistring,cst_widestring,cst_unicodestring);
+ var
+ pw : pcompilerwidestring;
+ pc : pchar;
+ cp1 : tstringencoding;
+ cp2 : tstringencoding;
+ l,l2 : longint;
+ begin
+ if def.typ<>stringdef then
+ internalerror(200510011);
+ { convert ascii 2 unicode }
+ if (tstringdef(def).stringtype in [st_widestring,st_unicodestring]) and
+ not(cst_type in [cst_widestring,cst_unicodestring]) then
+ begin
+ initwidestring(pw);
+ ascii2unicode(value_str,len,current_settings.sourcecodepage,pw);
+ ansistringdispose(value_str,len);
+ pcompilerwidestring(value_str):=pw;
+ end
+ else
+ { convert unicode 2 ascii }
+ if (cst_type in [cst_widestring,cst_unicodestring]) and
+ not(tstringdef(def).stringtype in [st_widestring,st_unicodestring]) then
+ begin
+ cp1:=tstringdef(def).encoding;
+ if (cp1=CP_NONE) or (cp1=0) then
+ cp1:=current_settings.sourcecodepage;
+ if (cp1=CP_UTF8) then
+ begin
+ pw:=pcompilerwidestring(value_str);
+ l2:=len;
+ l:=UnicodeToUtf8(nil,0,PUnicodeChar(pw^.data),l2);
+ getmem(pc,l);
+ UnicodeToUtf8(pc,l,PUnicodeChar(pw^.data),l2);
+ len:=l-1;
+ donewidestring(pw);
+ value_str:=pc;
+ end
+ else
+ begin
+ pw:=pcompilerwidestring(value_str);
+ getmem(pc,getlengthwidestring(pw)+1);
+ unicode2ascii(pw,pc,cp1);
+ donewidestring(pw);
+ value_str:=pc;
+ end;
+ end
+ else
+ if (tstringdef(def).stringtype = st_ansistring) and
+ not(cst_type in [cst_widestring,cst_unicodestring]) then
+ begin
+ cp1:=tstringdef(def).encoding;
+ if cp1=0 then
+ cp1:=current_settings.sourcecodepage;
+ if (cst_type = cst_ansistring) then
+ begin
+ cp2:=tstringdef(resultdef).encoding;
+ if cp2=0 then
+ cp2:=current_settings.sourcecodepage;
+ end
+ else if (cst_type in [cst_shortstring,cst_conststring,cst_longstring]) then
+ cp2:=current_settings.sourcecodepage;
+ { don't change string if codepages are equal or string length is 0 }
+ if (cp1<>cp2) and (len>0) then
+ begin
+ if cpavailable(cp1) and cpavailable(cp2) then
+ changecodepage(value_str,len,cp2,value_str,cp1)
+ else if (cp1 <> CP_NONE) and (cp2 <> CP_NONE) then
+ begin
+ { if source encoding is UTF8 convert using UTF8->UTF16->destination encoding }
+ if (cp2=CP_UTF8) then
+ begin
+ if not cpavailable(cp1) then
+ Message1(option_code_page_not_available,IntToStr(cp1));
+ initwidestring(pw);
+ setlengthwidestring(pw,len);
+ l:=Utf8ToUnicode(PUnicodeChar(pw^.data),len,value_str,len);
+ if (l<>getlengthwidestring(pw)) then
+ begin
+ setlengthwidestring(pw,l);
+ ReAllocMem(value_str,l);
+ end;
+ unicode2ascii(pw,value_str,cp1);
+ donewidestring(pw);
+ end
+ else
+ { if destination encoding is UTF8 convert using source encoding->UTF16->UTF8 }
+ if (cp1=CP_UTF8) then
+ begin
+ if not cpavailable(cp2) then
+ Message1(option_code_page_not_available,IntToStr(cp2));
+ initwidestring(pw);
+ setlengthwidestring(pw,len);
+ ascii2unicode(value_str,len,cp2,pw);
+ l:=UnicodeToUtf8(nil,0,PUnicodeChar(pw^.data),len);
+ if l<>len then
+ ReAllocMem(value_str,l);
+ len:=l-1;
+ UnicodeToUtf8(value_str,PUnicodeChar(pw^.data),l);
+ donewidestring(pw);
+ end
+ else
+ begin
+ { output error message that encoding is not available for the compiler }
+ if not cpavailable(cp1) then
+ Message1(option_code_page_not_available,IntToStr(cp1));
+ if not cpavailable(cp2) then
+ Message1(option_code_page_not_available,IntToStr(cp2));
+ end;
+ end;
+ end;
+ end;
+ cst_type:=st2cst[tstringdef(def).stringtype];
+ resultdef:=def;
+ end;
+
+ function tstringconstnode.fullcompare(p: tstringconstnode): longint;
+ begin
+ if cst_type<>p.cst_type then
+ InternalError(2009121701);
+ if cst_type in [cst_widestring,cst_unicodestring] then
+ result:=comparewidestrings(pcompilerwidestring(value_str),pcompilerwidestring(p.value_str))
+ else
+ result:=compareansistrings(value_str,p.value_str,len,p.len);
+ end;
+
+{*****************************************************************************
+ TSETCONSTNODE
+*****************************************************************************}
+
+ constructor tsetconstnode.create(s : pconstset;def:tdef);
+
+ begin
+ inherited create(setconstn,nil);
+ typedef:=def;
+ if assigned(s) then
+ begin
+ new(value_set);
+ value_set^:=s^;
+ end
+ else
+ value_set:=nil;
+ end;
+
+ destructor tsetconstnode.destroy;
+ begin
+ if assigned(value_set) then
+ dispose(value_set);
+ inherited destroy;
+ end;
+
+
+ constructor tsetconstnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ ppufile.getderef(typedefderef);
+ new(value_set);
+ ppufile.getnormalset(value_set^);
+ end;
+
+
+ procedure tsetconstnode.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putderef(typedefderef);
+ ppufile.putnormalset(value_set^);
+ end;
+
+
+ procedure tsetconstnode.buildderefimpl;
+ begin
+ inherited buildderefimpl;
+ typedefderef.build(typedef);
+ end;
+
+
+ procedure tsetconstnode.derefimpl;
+ begin
+ inherited derefimpl;
+ typedef:=tdef(typedefderef.resolve);
+ end;
+
+
+ procedure tsetconstnode.adjustforsetbase;
+ type
+ setbytes = array[0..31] of byte;
+ Psetbytes = ^setbytes;
+ var
+ i, diff: longint;
+ begin
+ { Internally, the compiler stores all sets with setbase 0, so we have }
+ { to convert the set to its actual format in case setbase<>0 when }
+ { writing it out }
+ if (tsetdef(resultdef).setbase<>0) then
+ begin
+ if (tsetdef(resultdef).setbase and 7)<>0 then
+ internalerror(2007091501);
+ diff:=tsetdef(resultdef).setbase div 8;
+ { This is endian-neutral in the new set format: in both cases, }
+ { the first byte contains the first elements of the set. }
+ { Since the compiler/base rtl cannot contain packed sets before }
+ { they work for big endian, it's no problem that the code below }
+ { is wrong for the old big endian set format (setbase cannot be }
+ { <>0 with non-packed sets). }
+ for i:=0 to tsetdef(resultdef).size-1 do
+ begin
+ Psetbytes(value_set)^[i]:=Psetbytes(value_set)^[i+diff];
+ Psetbytes(value_set)^[i+diff]:=0;
+ end;
+ end;
+ end;
+
+
+
+ function tsetconstnode.dogetcopy : tnode;
+
+ var
+ n : tsetconstnode;
+
+ begin
+ n:=tsetconstnode(inherited dogetcopy);
+ if assigned(value_set) then
+ begin
+ new(n.value_set);
+ n.value_set^:=value_set^
+ end
+ else
+ n.value_set:=nil;
+ n.typedef := typedef;
+ n.lab_set:=lab_set;
+ dogetcopy:=n;
+ end;
+
+ function tsetconstnode.pass_typecheck:tnode;
+ begin
+ result:=nil;
+ resultdef:=typedef;
+ end;
+
+ function tsetconstnode.pass_1 : tnode;
+ begin
+ result:=nil;
+ if is_smallset(resultdef) then
+ expectloc:=LOC_CONSTANT
+ else
+ expectloc:=LOC_CREFERENCE;
+ end;
+
+
+ function tsetconstnode.docompare(p: tnode): boolean;
+ begin
+ docompare:=(inherited docompare(p)) and
+ (value_set^=Tsetconstnode(p).value_set^);
+ end;
+
+
+{*****************************************************************************
+ TNILNODE
+*****************************************************************************}
+
+ constructor tnilnode.create;
+
+ begin
+ inherited create(niln);
+ end;
+
+ function tnilnode.pass_typecheck:tnode;
+ begin
+ result:=nil;
+ resultdef:=voidpointertype;
+ end;
+
+ function tnilnode.pass_1 : tnode;
+ begin
+ result:=nil;
+ expectloc:=LOC_CONSTANT;
+ end;
+
+{*****************************************************************************
+ TGUIDCONSTNODE
+*****************************************************************************}
+
+ constructor tguidconstnode.create(const g:tguid);
+
+ begin
+ inherited create(guidconstn);
+ value:=g;
+ end;
+
+ constructor tguidconstnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ ppufile.getguid(value);
+ end;
+
+
+ procedure tguidconstnode.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putguid(value);
+ end;
+
+
+ function tguidconstnode.dogetcopy : tnode;
+
+ var
+ n : tguidconstnode;
+
+ begin
+ n:=tguidconstnode(inherited dogetcopy);
+ n.value:=value;
+ dogetcopy:=n;
+ end;
+
+ function tguidconstnode.pass_typecheck:tnode;
+ begin
+ result:=nil;
+ resultdef:=rec_tguid;
+ end;
+
+ function tguidconstnode.pass_1 : tnode;
+ begin
+ result:=nil;
+ expectloc:=LOC_CREFERENCE;
+ end;
+
+ function tguidconstnode.docompare(p: tnode): boolean;
+ begin
+ docompare :=
+ inherited docompare(p) and
+ (guid2string(value) = guid2string(tguidconstnode(p).value));
+ end;
+
+end.
diff --git a/closures/compiler/nflw.pas b/closures/compiler/nflw.pas
new file mode 100644
index 0000000000..b8c058422c
--- /dev/null
+++ b/closures/compiler/nflw.pas
@@ -0,0 +1,2144 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Type checking and register allocation for nodes that influence
+ the flow
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit nflw;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cclasses,
+ node,cpubase,
+ symnot,
+ symtype,symbase,symdef,symsym,
+ optloop;
+
+ type
+ { flags used by loop nodes }
+ tloopflag = (
+ { set if it is a for ... downto ... do loop }
+ lnf_backward,
+ { Do we need to parse childs to set var state? }
+ lnf_varstate,
+ { Do a test at the begin of the loop?}
+ lnf_testatbegin,
+ { Negate the loop test? }
+ lnf_checknegate,
+ { Should the value of the loop variable on exit be correct. }
+ lnf_dont_mind_loopvar_on_exit,
+ { Loop simplify flag }
+ lnf_simplify_processing);
+ tloopflags = set of tloopflag;
+
+ const
+ { loop flags which must match to consider loop nodes equal regarding the flags }
+ loopflagsequal = [lnf_backward];
+
+ type
+ tlabelnode = class;
+
+ tloopnode = class(tbinarynode)
+ t1,t2 : tnode;
+ loopflags : tloopflags;
+ constructor create(tt : tnodetype;l,r,_t1,_t2 : tnode);virtual;
+ destructor destroy;override;
+ function dogetcopy : tnode;override;
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderefimpl;override;
+ procedure derefimpl;override;
+ procedure insertintolist(l : tnodelist);override;
+ procedure printnodetree(var t:text);override;
+ function docompare(p: tnode): boolean; override;
+ end;
+
+ twhilerepeatnode = class(tloopnode)
+ constructor create(l,r:Tnode;tab,cn:boolean);virtual;reintroduce;
+ function pass_typecheck:tnode;override;
+ function pass_1 : tnode;override;
+{$ifdef state_tracking}
+ function track_state_pass(exec_known:boolean):boolean;override;
+{$endif}
+ end;
+ twhilerepeatnodeclass = class of twhilerepeatnode;
+
+ tifnode = class(tloopnode)
+ constructor create(l,r,_t1 : tnode);virtual;reintroduce;
+ function pass_typecheck:tnode;override;
+ function pass_1 : tnode;override;
+ function simplify(forinline : boolean) : tnode;override;
+ private
+ function internalsimplify(warn: boolean) : tnode;
+ end;
+ tifnodeclass = class of tifnode;
+
+ tfornode = class(tloopnode)
+ { if count isn divisable by unrolls then
+ the for loop must jump to this label to get the correct
+ number of executions }
+ entrylabel : tnode;
+ loopvar_notid:cardinal;
+ constructor create(l,r,_t1,_t2 : tnode;back : boolean);virtual;reintroduce;
+ procedure loop_var_access(not_type:Tnotification_flag;symbol:Tsym);
+ function pass_typecheck:tnode;override;
+ function pass_1 : tnode;override;
+ function simplify(forinline : boolean) : tnode;override;
+ end;
+ tfornodeclass = class of tfornode;
+
+ texitnode = class(tunarynode)
+ constructor create(l:tnode);virtual;
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ function pass_typecheck:tnode;override;
+ function pass_1 : tnode;override;
+ end;
+ texitnodeclass = class of texitnode;
+
+ tbreaknode = class(tnode)
+ constructor create;virtual;
+ function pass_typecheck:tnode;override;
+ function pass_1 : tnode;override;
+ end;
+ tbreaknodeclass = class of tbreaknode;
+
+ tcontinuenode = class(tnode)
+ constructor create;virtual;
+ function pass_typecheck:tnode;override;
+ function pass_1 : tnode;override;
+ end;
+ tcontinuenodeclass = class of tcontinuenode;
+
+ tgotonode = class(tnode)
+ private
+ labelnodeidx : longint;
+ public
+ labelsym : tlabelsym;
+ labelnode : tlabelnode;
+ exceptionblock : integer;
+ constructor create(p : tlabelsym);virtual;
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderefimpl;override;
+ procedure derefimpl;override;
+ procedure resolveppuidx;override;
+ function dogetcopy : tnode;override;
+ function pass_typecheck:tnode;override;
+ function pass_1 : tnode;override;
+ function docompare(p: tnode): boolean; override;
+ end;
+ tgotonodeclass = class of tgotonode;
+
+ tlabelnode = class(tunarynode)
+ exceptionblock : integer;
+ { when copying trees, this points to the newly created copy of a label }
+ copiedto : tlabelnode;
+ labsym : tlabelsym;
+ constructor create(l:tnode;alabsym:tlabelsym);virtual;
+ destructor destroy;override;
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderefimpl;override;
+ procedure derefimpl;override;
+ function dogetcopy : tnode;override;
+ function pass_typecheck:tnode;override;
+ function pass_1 : tnode;override;
+ function docompare(p: tnode): boolean; override;
+ end;
+ tlabelnodeclass = class of tlabelnode;
+
+ traisenode = class(ttertiarynode)
+ constructor create(l,taddr,tframe:tnode);virtual;
+ function pass_typecheck:tnode;override;
+ function pass_1 : tnode;override;
+ end;
+ traisenodeclass = class of traisenode;
+
+ ttryexceptnode = class(tloopnode)
+ constructor create(l,r,_t1 : tnode);virtual;reintroduce;
+ function pass_typecheck:tnode;override;
+ function pass_1 : tnode;override;
+ end;
+ ttryexceptnodeclass = class of ttryexceptnode;
+
+ ttryfinallynode = class(tloopnode)
+ implicitframe : boolean;
+ constructor create(l,r:tnode);virtual;reintroduce;
+ constructor create_implicit(l,r,_t1:tnode);virtual;
+ function pass_typecheck:tnode;override;
+ function pass_1 : tnode;override;
+ function simplify(forinline:boolean): tnode;override;
+ end;
+ ttryfinallynodeclass = class of ttryfinallynode;
+
+ tonnode = class(tbinarynode)
+ excepTSymtable : TSymtable;
+ excepttype : tobjectdef;
+ constructor create(l,r:tnode);virtual;
+ destructor destroy;override;
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
+ function pass_typecheck:tnode;override;
+ function pass_1 : tnode;override;
+ function dogetcopy : tnode;override;
+ function docompare(p: tnode): boolean; override;
+ end;
+ tonnodeclass = class of tonnode;
+
+ var
+ cwhilerepeatnode : twhilerepeatnodeclass=twhilerepeatnode;
+ cifnode : tifnodeclass = tifnode;
+ cfornode : tfornodeclass = tfornode;
+ cexitnode : texitnodeclass = texitnode;
+ cgotonode : tgotonodeclass = tgotonode;
+ clabelnode : tlabelnodeclass = tlabelnode;
+ craisenode : traisenodeclass = traisenode;
+ ctryexceptnode : ttryexceptnodeclass = ttryexceptnode;
+ ctryfinallynode : ttryfinallynodeclass = ttryfinallynode;
+ connode : tonnodeclass = tonnode;
+ cbreaknode : tbreaknodeclass = tbreaknode;
+ ccontinuenode : tcontinuenodeclass = tcontinuenode;
+
+ // for-in loop helpers
+ function create_type_for_in_loop(hloopvar, hloopbody, expr: tnode): tnode;
+ function create_string_for_in_loop(hloopvar, hloopbody, expr: tnode): tnode;
+ function create_array_for_in_loop(hloopvar, hloopbody, expr: tnode): tnode;
+ function create_set_for_in_loop(hloopvar, hloopbody, expr: tnode): tnode;
+ function create_enumerator_for_in_loop(hloopvar, hloopbody, expr: tnode;
+ enumerator_get, enumerator_move: tprocdef; enumerator_current: tpropertysym): tnode;
+ function create_for_in_loop(hloopvar, hloopbody, expr: tnode): tnode;
+
+implementation
+
+ uses
+ globtype,systems,constexp,
+ cutils,verbose,globals,
+ symconst,symtable,paramgr,defcmp,defutil,htypechk,pass_1,
+ ncal,nadd,ncon,nmem,nld,ncnv,nbas,cgobj,nutils,ninl,nset,
+ {$ifdef state_tracking}
+ nstate,
+ {$endif}
+ cgbase,procinfo
+ ;
+
+
+ // for-in loop helpers
+
+ function create_type_for_in_loop(hloopvar, hloopbody, expr: tnode): tnode;
+ begin
+ result:=cfornode.create(hloopvar,
+ cinlinenode.create(in_low_x,false,expr.getcopy),
+ cinlinenode.create(in_high_x,false,expr.getcopy),
+ hloopbody,
+ false);
+ end;
+
+
+ function create_objc_for_in_loop(hloopvar, hloopbody, expr: tnode): tnode;
+ var
+ mainstatement, outerloopbodystatement, innerloopbodystatement, tempstatement: tstatementnode;
+ state, mutationcheck, currentamount, innerloopcounter, items, expressiontemp: ttempcreatenode;
+ outerloop, innerloop, hp: tnode;
+ itemsarraydef: tarraydef;
+ sym: tsym;
+ begin
+ { Objective-C enumerators require Objective-C 2.0 }
+ if not(m_objectivec2 in current_settings.modeswitches) then
+ begin
+ result:=cerrornode.create;
+ MessagePos(expr.fileinfo,parser_e_objc_enumerator_2_0);
+ exit;
+ end;
+ { Requires the NSFastEnumeration protocol and NSFastEnumerationState
+ record }
+ maybeloadcocoatypes;
+ if not assigned(objc_fastenumeration) or
+ not assigned(objc_fastenumerationstate) then
+ begin
+ result:=cerrornode.create;
+ MessagePos(expr.fileinfo,parser_e_objc_missing_enumeration_defs);
+ exit;
+ end;
+
+ (* Original code:
+ for hloopvar in expression do
+ <hloopbody>
+
+ Pascal code equivalent into which it has to be transformed
+ (sure would be nice if the compiler had some kind of templates ;) :
+ var
+ state: NSFastEnumerationState;
+ expressiontemp: NSFastEnumerationProtocol;
+ mutationcheck,
+ currentamount,
+ innerloopcounter: culong;
+ { size can be increased/decreased if desired }
+ items: array[1..16] of id;
+ begin
+ fillchar(state,sizeof(state),0);
+ expressiontemp:=expression;
+ repeat
+ currentamount:=expressiontemp.countByEnumeratingWithState_objects_count(@state,@items,length(items));
+ if currentamount=0 then
+ begin
+ { "The iterating variable is set to nil when the loop ends by
+ exhausting the source pool of objects" }
+ hloopvar:=nil;
+ break;
+ end;
+ mutationcheck:=state.mutationsptr^;
+ innerloopcounter:=culong(-1);
+ repeat
+ { at the start so that "continue" in <loopbody> works correctly }
+ { don't use for-loop, because then the value of the iteration
+ counter is undefined on exit and we have to check it in the
+ outer repeat/until condition }
+ {$push}
+ {$r-,q-}
+ inc(innerloopcounter);
+ {$pop}
+ if innerloopcounter=currentamount then
+ break;
+ if mutationcheck<>state.mutationsptr^ then
+ { raises Objective-C exception... }
+ objc_enumerationMutation(expressiontemp);
+ hloopvar:=state.itemsPtr[innerloopcounter];
+ { if continue in loopbody -> jumps to start, increases count and checks }
+ { if break in loopbody: goes to outer repeat/until and innerloopcount
+ will be < currentamount -> stops }
+ <hloopbody>
+ until false;
+ { if the inner loop terminated early, "break" was used and we have
+ to stop }
+ { "If the loop is terminated early, the iterating variable is left
+ pointing to the last iteration item." }
+ until innerloopcounter<currentamount;
+ end;
+ *)
+
+ result:=internalstatements(mainstatement);
+ { the fast enumeration state }
+ state:=ctempcreatenode.create(objc_fastenumerationstate,objc_fastenumerationstate.size,tt_persistent,false);
+ typecheckpass(tnode(state));
+ addstatement(mainstatement,state);
+ { the temporary items array }
+ itemsarraydef:=tarraydef.create(1,16,u32inttype);
+ itemsarraydef.elementdef:=objc_idtype;
+ items:=ctempcreatenode.create(itemsarraydef,itemsarraydef.size,tt_persistent,false);
+ addstatement(mainstatement,items);
+ typecheckpass(tnode(items));
+ { temp for the expression/collection through which we iterate }
+ expressiontemp:=ctempcreatenode.create(objc_fastenumeration,objc_fastenumeration.size,tt_persistent,true);
+ addstatement(mainstatement,expressiontemp);
+ { currentamount temp (not really clean: we use ptruint instead of
+ culong) }
+ currentamount:=ctempcreatenode.create(ptruinttype,ptruinttype.size,tt_persistent,true);
+ typecheckpass(tnode(currentamount));
+ addstatement(mainstatement,currentamount);
+ { mutationcheck temp (idem) }
+ mutationcheck:=ctempcreatenode.create(ptruinttype,ptruinttype.size,tt_persistent,true);
+ typecheckpass(tnode(mutationcheck));
+ addstatement(mainstatement,mutationcheck);
+ { innerloopcounter temp (idem) }
+ innerloopcounter:=ctempcreatenode.create(ptruinttype,ptruinttype.size,tt_persistent,true);
+ typecheckpass(tnode(innerloopcounter));
+ addstatement(mainstatement,innerloopcounter);
+ { initialise the state with 0 }
+ addstatement(mainstatement,ccallnode.createinternfromunit('SYSTEM','FILLCHAR',
+ ccallparanode.create(genintconstnode(0),
+ ccallparanode.create(genintconstnode(objc_fastenumerationstate.size),
+ ccallparanode.create(ctemprefnode.create(state),nil)
+ )
+ )
+ ));
+ { this will also check whether the expression (potentially) conforms
+ to the NSFastEnumeration protocol (use expr.getcopy, because the
+ caller will free expr) }
+ addstatement(mainstatement,cassignmentnode.create(ctemprefnode.create(expressiontemp),expr.getcopy));
+
+ { we add the "repeat..until" afterwards, now just create the body }
+ outerloop:=internalstatements(outerloopbodystatement);
+ { the countByEnumeratingWithState_objects_count call }
+ hp:=ccallparanode.create(cinlinenode.create(in_length_x,false,ctypenode.create(itemsarraydef)),
+ ccallparanode.create(caddrnode.create(ctemprefnode.create(items)),
+ ccallparanode.create(caddrnode.create(ctemprefnode.create(state)),nil)
+ )
+ );
+ sym:=search_struct_member(objc_fastenumeration,'COUNTBYENUMERATINGWITHSTATE_OBJECTS_COUNT');
+ if not assigned(sym) or
+ (sym.typ<>procsym) then
+ internalerror(2010061901);
+ hp:=ccallnode.create(hp,tprocsym(sym),sym.owner,ctemprefnode.create(expressiontemp),[]);
+ addstatement(outerloopbodystatement,cassignmentnode.create(
+ ctemprefnode.create(currentamount),hp));
+ { if currentamount = 0, bail out (use copy of hloopvar, because we
+ have to use it again below) }
+ hp:=internalstatements(tempstatement);
+ addstatement(tempstatement,cassignmentnode.create(
+ hloopvar.getcopy,cnilnode.create));
+ addstatement(tempstatement,cbreaknode.create);
+ addstatement(outerloopbodystatement,cifnode.create(
+ caddnode.create(equaln,ctemprefnode.create(currentamount),genintconstnode(0)),
+ hp,nil));
+ { initial value of mutationcheck }
+ hp:=ctemprefnode.create(state);
+ typecheckpass(hp);
+ hp:=cderefnode.create(genloadfield(hp,'MUTATIONSPTR'));
+ addstatement(outerloopbodystatement,cassignmentnode.create(
+ ctemprefnode.create(mutationcheck),hp));
+ { initialise innerloopcounter }
+ addstatement(outerloopbodystatement,cassignmentnode.create(
+ ctemprefnode.create(innerloopcounter),cordconstnode.create(-1,ptruinttype,false)));
+
+ { and now the inner loop, again adding the repeat/until afterwards }
+ innerloop:=internalstatements(innerloopbodystatement);
+ { inc(innerloopcounter) without range/overflowchecking (because
+ we go from culong(-1) to 0 during the first iteration }
+ hp:=cinlinenode.create(
+ in_inc_x,false,ccallparanode.create(
+ ctemprefnode.create(innerloopcounter),nil));
+ hp.localswitches:=hp.localswitches-[cs_check_range,cs_check_overflow];
+ addstatement(innerloopbodystatement,hp);
+ { if innerloopcounter=currentamount then break to the outer loop }
+ addstatement(innerloopbodystatement,cifnode.create(
+ caddnode.create(equaln,
+ ctemprefnode.create(innerloopcounter),
+ ctemprefnode.create(currentamount)),
+ cbreaknode.create,
+ nil));
+ { verify that the collection didn't change in the mean time }
+ hp:=ctemprefnode.create(state);
+ typecheckpass(hp);
+ addstatement(innerloopbodystatement,cifnode.create(
+ caddnode.create(unequaln,
+ ctemprefnode.create(mutationcheck),
+ cderefnode.create(genloadfield(hp,'MUTATIONSPTR'))
+ ),
+ ccallnode.createinternfromunit('OBJC','OBJC_ENUMERATIONMUTATION',
+ ccallparanode.create(ctemprefnode.create(expressiontemp),nil)),
+ nil));
+ { finally: actually get the next element }
+ hp:=ctemprefnode.create(state);
+ typecheckpass(hp);
+ hp:=genloadfield(hp,'ITEMSPTR');
+ typecheckpass(hp);
+ { don't simply use a vecn, because indexing a pointer won't work in
+ non-FPC modes }
+ if hp.resultdef.typ<>pointerdef then
+ internalerror(2010061904);
+ inserttypeconv(hp,
+ tarraydef.create_from_pointer(tpointerdef(hp.resultdef).pointeddef));
+ hp:=cvecnode.create(hp,ctemprefnode.create(innerloopcounter));
+ addstatement(innerloopbodystatement,
+ cassignmentnode.create(hloopvar,hp));
+ { the actual loop body! }
+ addstatement(innerloopbodystatement,hloopbody);
+
+ { create the inner repeat/until and add it to the body of the outer
+ one }
+ hp:=cwhilerepeatnode.create(
+ { repeat .. until false }
+ cordconstnode.create(0,pasbool8type,false),innerloop,false,true);
+ addstatement(outerloopbodystatement,hp);
+
+ { create the outer repeat/until and add it to the the main body }
+ hp:=cwhilerepeatnode.create(
+ { repeat .. until innerloopcounter<currentamount }
+ caddnode.create(ltn,
+ ctemprefnode.create(innerloopcounter),
+ ctemprefnode.create(currentamount)),
+ outerloop,false,true);
+ addstatement(mainstatement,hp);
+
+ { release the temps }
+ addstatement(mainstatement,ctempdeletenode.create(state));
+ addstatement(mainstatement,ctempdeletenode.create(mutationcheck));
+ addstatement(mainstatement,ctempdeletenode.create(currentamount));
+ addstatement(mainstatement,ctempdeletenode.create(innerloopcounter));
+ addstatement(mainstatement,ctempdeletenode.create(items));
+ addstatement(mainstatement,ctempdeletenode.create(expressiontemp));
+ end;
+
+
+ function create_string_for_in_loop(hloopvar, hloopbody, expr: tnode): tnode;
+ var
+ loopstatement, loopbodystatement: tstatementnode;
+ loopvar, stringvar: ttempcreatenode;
+ stringindex, loopbody, forloopnode: tnode;
+ begin
+ { result is a block of statements }
+ result:=internalstatements(loopstatement);
+
+ { create a temp variable for expression }
+ stringvar := ctempcreatenode.create(
+ expr.resultdef,
+ expr.resultdef.size,
+ tt_persistent,true);
+
+ addstatement(loopstatement,stringvar);
+ addstatement(loopstatement,cassignmentnode.create(ctemprefnode.create(stringvar),expr.getcopy));
+
+ { create a loop counter: signed integer with size of string length }
+ loopvar := ctempcreatenode.create(
+ sinttype,
+ sinttype.size,
+ tt_persistent,true);
+
+ addstatement(loopstatement,loopvar);
+
+ stringindex:=ctemprefnode.create(loopvar);
+
+ loopbody:=internalstatements(loopbodystatement);
+ // for-in loop variable := string_expression[index]
+ addstatement(loopbodystatement,
+ cassignmentnode.create(hloopvar, cvecnode.create(ctemprefnode.create(stringvar),stringindex)));
+
+ { add the actual statement to the loop }
+ addstatement(loopbodystatement,hloopbody);
+
+ forloopnode:=cfornode.create(ctemprefnode.create(loopvar),
+ genintconstnode(1),
+ cinlinenode.create(in_length_x,false,ctemprefnode.create(stringvar)),
+ loopbody,
+ false);
+
+ addstatement(loopstatement,forloopnode);
+ { free the loop counter }
+ addstatement(loopstatement,ctempdeletenode.create(loopvar));
+ { free the temp variable for expression }
+ addstatement(loopstatement,ctempdeletenode.create(stringvar));
+ end;
+
+
+ function create_array_for_in_loop(hloopvar, hloopbody, expr: tnode): tnode;
+ var
+ loopstatement, loopbodystatement: tstatementnode;
+ loopvar, arrayvar: ttempcreatenode;
+ arrayindex, lowbound, highbound, loopbody, forloopnode, expression: tnode;
+ is_string: boolean;
+ tmpdef, convertdef: tdef;
+ elementcount: aword;
+ begin
+ expression := expr;
+
+ { result is a block of statements }
+ result:=internalstatements(loopstatement);
+
+ is_string:=ado_IsConstString in tarraydef(expr.resultdef).arrayoptions;
+
+ // if array element type <> loovar type then create a conversion if possible
+ if compare_defs(tarraydef(expression.resultdef).elementdef,hloopvar.resultdef,nothingn)=te_incompatible then
+ begin
+ tmpdef:=expression.resultdef;
+ elementcount:=1;
+ while assigned(tmpdef) and (tmpdef.typ=arraydef) and
+ (tarraydef(tmpdef).arrayoptions = []) and
+ (compare_defs(tarraydef(tmpdef).elementdef,hloopvar.resultdef,nothingn)=te_incompatible) do
+ begin
+ elementcount:=elementcount*tarraydef(tmpdef).elecount;
+ tmpdef:=tarraydef(tmpdef).elementdef;
+ end;
+ if assigned(tmpdef) and (tmpdef.typ=arraydef) and (tarraydef(tmpdef).arrayoptions = []) then
+ begin
+ elementcount:=elementcount*tarraydef(tmpdef).elecount;
+ convertdef:=tarraydef.create(0,elementcount-1,s32inttype);
+ tarraydef(convertdef).elementdef:=tarraydef(tmpdef).elementdef;
+ expression:=expr.getcopy;
+ expression:=ctypeconvnode.create_internal(expression,convertdef);
+ typecheckpass(expression);
+ addstatement(loopstatement,expression);
+ end;
+ end;
+
+ if (node_complexity(expression) > 1) and not is_open_array(expression.resultdef) then
+ begin
+ { create a temp variable for expression }
+ arrayvar := ctempcreatenode.create(
+ expression.resultdef,
+ expression.resultdef.size,
+ tt_persistent,true);
+
+ if is_string then
+ begin
+ lowbound:=genintconstnode(1);
+ highbound:=cinlinenode.create(in_length_x,false,ctemprefnode.create(arrayvar))
+ end
+ else
+ begin
+ lowbound:=cinlinenode.create(in_low_x,false,ctemprefnode.create(arrayvar));
+ highbound:=cinlinenode.create(in_high_x,false,ctemprefnode.create(arrayvar));
+ end;
+
+ addstatement(loopstatement,arrayvar);
+ addstatement(loopstatement,cassignmentnode.create(ctemprefnode.create(arrayvar),expression.getcopy));
+ end
+ else
+ begin
+ arrayvar:=nil;
+ if is_string then
+ begin
+ lowbound:=genintconstnode(1);
+ highbound:=cinlinenode.create(in_length_x,false,expression.getcopy);
+ end
+ else
+ begin
+ lowbound:=cinlinenode.create(in_low_x,false,expression.getcopy);
+ highbound:=cinlinenode.create(in_high_x,false,expression.getcopy);
+ end;
+ end;
+
+ { create a loop counter }
+ loopvar := ctempcreatenode.create(
+ tarraydef(expression.resultdef).rangedef,
+ tarraydef(expression.resultdef).rangedef.size,
+ tt_persistent,true);
+
+ addstatement(loopstatement,loopvar);
+
+ arrayindex:=ctemprefnode.create(loopvar);
+
+ loopbody:=internalstatements(loopbodystatement);
+ // for-in loop variable := array_expression[index]
+ if assigned(arrayvar) then
+ addstatement(loopbodystatement,
+ cassignmentnode.create(hloopvar,cvecnode.create(ctemprefnode.create(arrayvar),arrayindex)))
+ else
+ addstatement(loopbodystatement,
+ cassignmentnode.create(hloopvar,cvecnode.create(expression.getcopy,arrayindex)));
+
+ { add the actual statement to the loop }
+ addstatement(loopbodystatement,hloopbody);
+
+ forloopnode:=cfornode.create(ctemprefnode.create(loopvar),
+ lowbound,
+ highbound,
+ loopbody,
+ false);
+
+ addstatement(loopstatement,forloopnode);
+ { free the loop counter }
+ addstatement(loopstatement,ctempdeletenode.create(loopvar));
+ { free the temp variable for expression if needed }
+ if arrayvar<>nil then
+ addstatement(loopstatement,ctempdeletenode.create(arrayvar));
+ end;
+
+
+ function create_set_for_in_loop(hloopvar, hloopbody, expr: tnode): tnode;
+ var
+ loopstatement, loopbodystatement: tstatementnode;
+ loopvar, setvar: ttempcreatenode;
+ loopbody, forloopnode: tnode;
+ begin
+ // first check is set is empty and if it so then skip other processing
+ if not Assigned(tsetdef(expr.resultdef).elementdef) then
+ begin
+ result:=cnothingnode.create;
+ // free unused nodes
+ hloopvar.free;
+ hloopbody.free;
+ exit;
+ end;
+ { result is a block of statements }
+ result:=internalstatements(loopstatement);
+
+ { create a temp variable for expression }
+ setvar := ctempcreatenode.create(
+ expr.resultdef,
+ expr.resultdef.size,
+ tt_persistent,true);
+
+ addstatement(loopstatement,setvar);
+ addstatement(loopstatement,cassignmentnode.create(ctemprefnode.create(setvar),expr.getcopy));
+
+ { create a loop counter }
+ loopvar := ctempcreatenode.create(
+ tsetdef(expr.resultdef).elementdef,
+ tsetdef(expr.resultdef).elementdef.size,
+ tt_persistent,true);
+
+ addstatement(loopstatement,loopvar);
+
+ // if loopvar in set then
+ // begin
+ // hloopvar := loopvar
+ // for-in loop body
+ // end
+
+ loopbody:=cifnode.create(
+ cinnode.create(ctemprefnode.create(loopvar),ctemprefnode.create(setvar)),
+ internalstatements(loopbodystatement),
+ nil);
+
+ addstatement(loopbodystatement,cassignmentnode.create(hloopvar,ctemprefnode.create(loopvar)));
+ { add the actual statement to the loop }
+ addstatement(loopbodystatement,hloopbody);
+
+ forloopnode:=cfornode.create(ctemprefnode.create(loopvar),
+ cinlinenode.create(in_low_x,false,ctemprefnode.create(setvar)),
+ cinlinenode.create(in_high_x,false,ctemprefnode.create(setvar)),
+ loopbody,
+ false);
+
+ addstatement(loopstatement,forloopnode);
+ { free the loop counter }
+ addstatement(loopstatement,ctempdeletenode.create(loopvar));
+ { free the temp variable for expression }
+ addstatement(loopstatement,ctempdeletenode.create(setvar));
+ end;
+
+
+ function create_enumerator_for_in_loop(hloopvar, hloopbody, expr: tnode;
+ enumerator_get, enumerator_move: tprocdef; enumerator_current: tpropertysym): tnode;
+ var
+ loopstatement, loopbodystatement: tstatementnode;
+ enumvar: ttempcreatenode;
+ loopbody, whileloopnode,
+ enum_get, enum_move, enum_current, enum_get_params: tnode;
+ propaccesslist: tpropaccesslist;
+ enumerator_is_class: boolean;
+ enumerator_destructor: tprocdef;
+ begin
+ { result is a block of statements }
+ result:=internalstatements(loopstatement);
+
+ enumerator_is_class := is_class(enumerator_get.returndef);
+
+ { create a temp variable for enumerator }
+ enumvar := ctempcreatenode.create(
+ enumerator_get.returndef,
+ enumerator_get.returndef.size,
+ tt_persistent,true);
+
+ addstatement(loopstatement,enumvar);
+
+ if enumerator_get.proctypeoption=potype_operator then
+ begin
+ enum_get_params:=ccallparanode.create(expr.getcopy,nil);
+ enum_get:=ccallnode.create(enum_get_params, tprocsym(enumerator_get.procsym), nil, nil, []);
+ tcallnode(enum_get).procdefinition:=enumerator_get;
+ addsymref(enumerator_get.procsym);
+ end
+ else
+ enum_get:=ccallnode.create(nil, tprocsym(enumerator_get.procsym), enumerator_get.owner, expr.getcopy, []);
+
+ addstatement(loopstatement,
+ cassignmentnode.create(
+ ctemprefnode.create(enumvar),
+ enum_get
+ ));
+
+ loopbody:=internalstatements(loopbodystatement);
+ { for-in loop variable := enumerator.current }
+ if getpropaccesslist(enumerator_current,palt_read,propaccesslist) then
+ begin
+ case propaccesslist.firstsym^.sym.typ of
+ fieldvarsym :
+ begin
+ { generate access code }
+ enum_current:=ctemprefnode.create(enumvar);
+ propaccesslist_to_node(enum_current,enumerator_current.owner,propaccesslist);
+ include(enum_current.flags,nf_isproperty);
+ end;
+ procsym :
+ begin
+ { generate the method call }
+ enum_current:=ccallnode.create(nil,tprocsym(propaccesslist.firstsym^.sym),enumerator_current.owner,ctemprefnode.create(enumvar),[]);
+ include(enum_current.flags,nf_isproperty);
+ end
+ else
+ begin
+ enum_current:=cerrornode.create;
+ Message(type_e_mismatch);
+ end;
+ end;
+ end
+ else
+ enum_current:=cerrornode.create;
+
+ addstatement(loopbodystatement,
+ cassignmentnode.create(hloopvar, enum_current));
+
+ { add the actual statement to the loop }
+ addstatement(loopbodystatement,hloopbody);
+
+ enum_move:=ccallnode.create(nil, tprocsym(enumerator_move.procsym), enumerator_move.owner, ctemprefnode.create(enumvar), []);
+ whileloopnode:=cwhilerepeatnode.create(enum_move,loopbody,true,false);
+
+ if enumerator_is_class then
+ begin
+ { insert a try-finally and call the destructor for the enumerator in the finally section }
+ enumerator_destructor:=tobjectdef(enumerator_get.returndef).find_destructor;
+ if assigned(enumerator_destructor) then
+ begin
+ whileloopnode:=ctryfinallynode.create(
+ whileloopnode, // try node
+ ccallnode.create(nil,tprocsym(enumerator_destructor.procsym), // finally node
+ enumerator_destructor.procsym.owner,ctemprefnode.create(enumvar),[]));
+ end;
+ { if getenumerator <> nil then do the loop }
+ whileloopnode:=cifnode.create(
+ caddnode.create(unequaln, ctemprefnode.create(enumvar), cnilnode.create),
+ whileloopnode,
+ nil);
+ end;
+
+ addstatement(loopstatement, whileloopnode);
+
+ if is_object(enumerator_get.returndef) then
+ begin
+ // call the object destructor too
+ enumerator_destructor:=tobjectdef(enumerator_get.returndef).find_destructor;
+ if assigned(enumerator_destructor) then
+ begin
+ addstatement(loopstatement,
+ ccallnode.create(nil,tprocsym(enumerator_destructor.procsym),
+ enumerator_destructor.procsym.owner,ctemprefnode.create(enumvar),[]));
+ end;
+ end;
+
+ { free the temp variable for enumerator }
+ addstatement(loopstatement,ctempdeletenode.create(enumvar));
+ end;
+
+
+ function create_for_in_loop(hloopvar, hloopbody, expr: tnode): tnode;
+ var
+ pd, movenext: tprocdef;
+ helperdef: tobjectdef;
+ current: tpropertysym;
+ storefilepos: tfileposinfo;
+ begin
+ storefilepos:=current_filepos;
+ current_filepos:=hloopvar.fileinfo;
+ if expr.nodetype=typen then
+ begin
+ if (expr.resultdef.typ=enumdef) and tenumdef(expr.resultdef).has_jumps then
+ begin
+ result:=cerrornode.create;
+ hloopvar.free;
+ hloopbody.free;
+ MessagePos1(expr.fileinfo,parser_e_for_in_loop_cannot_be_used_for_the_type,expr.resultdef.typename);
+ end
+ else
+ result:=create_type_for_in_loop(hloopvar, hloopbody, expr);
+ end
+ else
+ begin
+ { loop is made for an expression }
+ // Objective-C uses different conventions (and it's only supported for Objective-C 2.0)
+ if is_objc_class_or_protocol(hloopvar.resultdef) or
+ is_objc_class_or_protocol(expr.resultdef) then
+ begin
+ result:=create_objc_for_in_loop(hloopvar,hloopbody,expr);
+ if result.nodetype=errorn then
+ begin
+ hloopvar.free;
+ hloopbody.free;
+ end;
+ end
+ else
+ begin
+ // search for operator first
+ pd:=search_enumerator_operator(expr.resultdef, hloopvar.resultdef);
+ // if there is no operator then search for class/object enumerator method
+ if (pd=nil) and (expr.resultdef.typ in [objectdef,recorddef]) then
+ begin
+ { first search using the helper hierarchy }
+ if search_last_objectpascal_helper(tabstractrecorddef(expr.resultdef),nil,helperdef) then
+ repeat
+ pd:=helperdef.search_enumerator_get;
+ helperdef:=helperdef.childof;
+ until (pd<>nil) or (helperdef=nil);
+ { we didn't find an enumerator in a helper, so search in the
+ class/record/object itself }
+ if pd=nil then
+ pd:=tabstractrecorddef(expr.resultdef).search_enumerator_get;
+ end;
+ if pd<>nil then
+ begin
+ // seach movenext and current symbols
+ movenext:=tabstractrecorddef(pd.returndef).search_enumerator_move;
+ if movenext = nil then
+ begin
+ result:=cerrornode.create;
+ hloopvar.free;
+ hloopbody.free;
+ MessagePos1(expr.fileinfo,sym_e_no_enumerator_move,pd.returndef.typename);
+ end
+ else
+ begin
+ current:=tpropertysym(tabstractrecorddef(pd.returndef).search_enumerator_current);
+ if current = nil then
+ begin
+ result:=cerrornode.create;
+ hloopvar.free;
+ hloopbody.free;
+ MessagePos1(expr.fileinfo,sym_e_no_enumerator_current,pd.returndef.typename);
+ end
+ else
+ result:=create_enumerator_for_in_loop(hloopvar, hloopbody, expr, pd, movenext, current);
+ end;
+ end
+ else
+ begin
+ case expr.resultdef.typ of
+ stringdef: result:=create_string_for_in_loop(hloopvar, hloopbody, expr);
+ arraydef: result:=create_array_for_in_loop(hloopvar, hloopbody, expr);
+ setdef: result:=create_set_for_in_loop(hloopvar, hloopbody, expr);
+ else
+ begin
+ result:=cerrornode.create;
+ hloopvar.free;
+ hloopbody.free;
+ MessagePos1(expr.fileinfo,sym_e_no_enumerator,expr.resultdef.typename);
+ end;
+ end;
+ end;
+ end;
+ end;
+ current_filepos:=storefilepos;
+ end;
+
+{****************************************************************************
+ TLOOPNODE
+*****************************************************************************}
+
+ constructor tloopnode.create(tt : tnodetype;l,r,_t1,_t2 : tnode);
+
+ begin
+ inherited create(tt,l,r);
+ t1:=_t1;
+ t2:=_t2;
+ fileinfo:=l.fileinfo;
+ end;
+
+ destructor tloopnode.destroy;
+
+ begin
+ t1.free;
+ t2.free;
+ inherited destroy;
+ end;
+
+
+ constructor tloopnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ t1:=ppuloadnode(ppufile);
+ t2:=ppuloadnode(ppufile);
+ ppufile.getsmallset(loopflags);
+ end;
+
+
+ procedure tloopnode.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppuwritenode(ppufile,t1);
+ ppuwritenode(ppufile,t2);
+ ppufile.putsmallset(loopflags);
+ end;
+
+
+ procedure tloopnode.buildderefimpl;
+ begin
+ inherited buildderefimpl;
+ if assigned(t1) then
+ t1.buildderefimpl;
+ if assigned(t2) then
+ t2.buildderefimpl;
+ end;
+
+
+ procedure tloopnode.derefimpl;
+ begin
+ inherited derefimpl;
+ if assigned(t1) then
+ t1.derefimpl;
+ if assigned(t2) then
+ t2.derefimpl;
+ end;
+
+
+ function tloopnode.dogetcopy : tnode;
+
+ var
+ p : tloopnode;
+
+ begin
+ p:=tloopnode(inherited dogetcopy);
+ if assigned(t1) then
+ p.t1:=t1.dogetcopy
+ else
+ p.t1:=nil;
+ if assigned(t2) then
+ p.t2:=t2.dogetcopy
+ else
+ p.t2:=nil;
+ p.loopflags:=loopflags;
+ dogetcopy:=p;
+ end;
+
+ procedure tloopnode.insertintolist(l : tnodelist);
+
+ begin
+ end;
+
+
+ procedure tloopnode.printnodetree(var t:text);
+ begin
+ write(t,printnodeindention,'(');
+ printnodeindent;
+ printnodeinfo(t);
+ writeln(t);
+ printnode(t,left);
+ printnode(t,right);
+ printnode(t,t1);
+ printnode(t,t2);
+ printnodeunindent;
+ writeln(t,printnodeindention,')');
+ end;
+
+
+ function tloopnode.docompare(p: tnode): boolean;
+ begin
+ docompare :=
+ inherited docompare(p) and
+ (loopflags*loopflagsequal=tloopnode(p).loopflags*loopflagsequal) and
+ t1.isequal(tloopnode(p).t1) and
+ t2.isequal(tloopnode(p).t2);
+ end;
+
+{****************************************************************************
+ TWHILEREPEATNODE
+*****************************************************************************}
+
+ constructor Twhilerepeatnode.create(l,r:Tnode;tab,cn:boolean);
+ begin
+ inherited create(whilerepeatn,l,r,nil,nil);
+ if tab then
+ include(loopflags, lnf_testatbegin);
+ if cn then
+ include(loopflags,lnf_checknegate);
+ end;
+
+ function twhilerepeatnode.pass_typecheck:tnode;
+ var
+ t:Tunarynode;
+ begin
+ result:=nil;
+ resultdef:=voidtype;
+
+ typecheckpass(left);
+
+ { tp procvar support }
+ maybe_call_procvar(left,true);
+
+ {A not node can be removed.}
+ if left.nodetype=notn then
+ begin
+ t:=Tunarynode(left);
+ left:=Tunarynode(left).left;
+ t.left:=nil;
+ t.destroy;
+ {Symdif operator, in case you are wondering:}
+ loopflags:=loopflags >< [lnf_checknegate];
+ end;
+ { loop instruction }
+ if assigned(right) then
+ typecheckpass(right);
+ set_varstate(left,vs_read,[vsf_must_be_valid]);
+ if codegenerror then
+ exit;
+
+ if not(is_boolean(left.resultdef)) and
+ not(is_typeparam(left.resultdef)) then
+ begin
+ if left.resultdef.typ=variantdef then
+ inserttypeconv(left,pasbool8type)
+ else
+ CGMessage1(type_e_boolean_expr_expected,left.resultdef.typename);
+ end;
+
+ { Give warnings for code that will never be executed for
+ while false do }
+ if (lnf_testatbegin in loopflags) and
+ (left.nodetype=ordconstn) and
+ (tordconstnode(left).value.uvalue=0) and
+ assigned(right) then
+ CGMessagePos(right.fileinfo,cg_w_unreachable_code);
+ end;
+
+
+{$ifdef prefetchnext}
+ type
+ passignmentquery = ^tassignmentquery;
+ tassignmentquery = record
+ towhat: tnode;
+ source: tassignmentnode;
+ statementcount: cardinal;
+ end;
+
+ function checkassignment(var n: tnode; arg: pointer): foreachnoderesult;
+ var
+ query: passignmentquery absolute arg;
+ temp, prederef: tnode;
+ begin
+ result := fen_norecurse_false;
+ if (n.nodetype in [assignn,inlinen,forn,calln,whilerepeatn,casen,ifn]) then
+ inc(query^.statementcount);
+ { make sure there's something else in the loop besides going to the }
+ { next item }
+ if (query^.statementcount > 1) and
+ (n.nodetype = assignn) then
+ begin
+ { skip type conversions of assignment target }
+ temp := tassignmentnode(n).left;
+ while (temp.nodetype = typeconvn) do
+ temp := ttypeconvnode(temp).left;
+
+ { assignment to x of the while assigned(x) check? }
+ if not(temp.isequal(query^.towhat)) then
+ exit;
+
+ { right hand side of assignment dereferenced field of }
+ { x? (no derefn in case of class) }
+ temp := tassignmentnode(n).right;
+ while (temp.nodetype = typeconvn) do
+ temp := ttypeconvnode(temp).left;
+ if (temp.nodetype <> subscriptn) then
+ exit;
+
+ prederef := tsubscriptnode(temp).left;
+ temp := prederef;
+ while (temp.nodetype = typeconvn) do
+ temp := ttypeconvnode(temp).left;
+
+ { see tests/test/prefetch1.pp }
+ if (temp.nodetype = derefn) then
+ temp := tderefnode(temp).left
+ else
+ temp := prederef;
+
+ if temp.isequal(query^.towhat) then
+ begin
+ query^.source := tassignmentnode(n);
+ result := fen_norecurse_true;
+ end
+ end
+ { don't check nodes which can't contain an assignment or whose }
+ { final assignment can vary a lot }
+ else if not(n.nodetype in [calln,inlinen,casen,whilerepeatn,forn]) then
+ result := fen_false;
+ end;
+
+
+ function findassignment(where: tnode; towhat: tnode): tassignmentnode;
+ var
+ query: tassignmentquery;
+ begin
+ query.towhat := towhat;
+ query.source := nil;
+ query.statementcount := 0;
+ if foreachnodestatic(where,@checkassignment,@query) then
+ result := query.source
+ else
+ result := nil;
+ end;
+{$endif prefetchnext}
+
+
+ function twhilerepeatnode.pass_1 : tnode;
+{$ifdef prefetchnext}
+ var
+ runnernode, prefetchcode: tnode;
+ assignmentnode: tassignmentnode;
+ prefetchstatements: tstatementnode;
+{$endif prefetchnext}
+ begin
+ result:=nil;
+ expectloc:=LOC_VOID;
+
+ firstpass(left);
+ if codegenerror then
+ exit;
+
+ { loop instruction }
+ if assigned(right) then
+ begin
+ firstpass(right);
+ if codegenerror then
+ exit;
+ end;
+
+{$ifdef prefetchnext}
+ { do at the end so all complex typeconversions are already }
+ { converted to calln's }
+ if (cs_opt_level1 in current_settings.optimizerswitches) and
+ (lnf_testatbegin in loopflags) then
+ begin
+ { get first component of the while check }
+ runnernode := left;
+ while (runnernode.nodetype in [andn,orn,notn,xorn,typeconvn]) do
+ runnernode := tunarynode(runnernode).left;
+ { is it an assigned(x) check? }
+ if ((runnernode.nodetype = inlinen) and
+ (tinlinenode(runnernode).inlinenumber = in_assigned_x)) or
+ ((runnernode.nodetype = unequaln) and
+ (taddnode(runnernode).right.nodetype = niln)) then
+ begin
+ runnernode := tunarynode(runnernode).left;
+ { in case of in_assigned_x, there's a callparan in between }
+ if (runnernode.nodetype = callparan) then
+ runnernode := tcallparanode(runnernode).left;
+ while (runnernode.nodetype = typeconvn) do
+ runnernode := ttypeconvnode(runnernode).left;
+ { is there an "x := x(^).somefield"? }
+ assignmentnode := findassignment(right,runnernode);
+ if assigned(assignmentnode) then
+ begin
+ prefetchcode := internalstatements(prefetchstatements);
+ addstatement(prefetchstatements,geninlinenode(in_prefetch_var,false,
+ cderefnode.create(ctypeconvnode.create(assignmentnode.right.getcopy,voidpointertype))));
+ addstatement(prefetchstatements,right);
+ right := prefetchcode;
+ typecheckpass(right);
+ end;
+ end;
+ end;
+{$endif prefetchnext}
+ end;
+
+{$ifdef state_tracking}
+ function Twhilerepeatnode.track_state_pass(exec_known:boolean):boolean;
+
+ var condition:Tnode;
+ code:Tnode;
+ done:boolean;
+ value:boolean;
+ change:boolean;
+ firsttest:boolean;
+ factval:Tnode;
+
+ begin
+ track_state_pass:=false;
+ done:=false;
+ firsttest:=true;
+ {For repeat until statements, first do a pass through the code.}
+ if not(lnf_testatbegin in flags) then
+ begin
+ code:=right.getcopy;
+ if code.track_state_pass(exec_known) then
+ track_state_pass:=true;
+ code.destroy;
+ end;
+ repeat
+ condition:=left.getcopy;
+ code:=right.getcopy;
+ change:=condition.track_state_pass(exec_known);
+ factval:=aktstate.find_fact(left);
+ if factval<>nil then
+ begin
+ condition.destroy;
+ condition:=factval.getcopy;
+ change:=true;
+ end;
+ if change then
+ begin
+ track_state_pass:=true;
+ {Force new resultdef pass.}
+ condition.resultdef:=nil;
+ do_typecheckpass(condition);
+ end;
+ if is_constboolnode(condition) then
+ begin
+ {Try to turn a while loop into a repeat loop.}
+ if firsttest then
+ exclude(flags,testatbegin);
+ value:=(Tordconstnode(condition).value<>0) xor checknegate;
+ if value then
+ begin
+ if code.track_state_pass(exec_known) then
+ track_state_pass:=true;
+ end
+ else
+ done:=true;
+ end
+ else
+ begin
+ {Remove any modified variables from the state.}
+ code.track_state_pass(false);
+ done:=true;
+ end;
+ code.destroy;
+ condition.destroy;
+ firsttest:=false;
+ until done;
+ {The loop condition is also known, for example:
+ while i<10 do
+ begin
+ ...
+ end;
+
+ When the loop is done, we do know that i<10 = false.
+ }
+ condition:=left.getcopy;
+ if condition.track_state_pass(exec_known) then
+ begin
+ track_state_pass:=true;
+ {Force new resultdef pass.}
+ condition.resultdef:=nil;
+ do_typecheckpass(condition);
+ end;
+ if not is_constboolnode(condition) then
+ aktstate.store_fact(condition,
+ cordconstnode.create(byte(checknegate),pasbool8type,true))
+ else
+ condition.destroy;
+ end;
+{$endif}
+
+{*****************************************************************************
+ TIFNODE
+*****************************************************************************}
+
+ constructor tifnode.create(l,r,_t1 : tnode);
+ begin
+ inherited create(ifn,l,r,_t1,nil);
+ end;
+
+
+ function tifnode.internalsimplify(warn: boolean) : tnode;
+ begin
+ result:=nil;
+ { optimize constant expressions }
+ if (left.nodetype=ordconstn) then
+ begin
+ if tordconstnode(left).value.uvalue=1 then
+ begin
+ if assigned(right) then
+ result:=right
+ else
+ result:=cnothingnode.create;
+ right:=nil;
+ if warn and assigned(t1) then
+ CGMessagePos(t1.fileinfo,cg_w_unreachable_code);
+ end
+ else
+ begin
+ if assigned(t1) then
+ result:=t1
+ else
+ result:=cnothingnode.create;
+ t1:=nil;
+ if warn and assigned(right) then
+ CGMessagePos(right.fileinfo,cg_w_unreachable_code);
+ end;
+ end;
+ end;
+
+
+ function tifnode.simplify(forinline : boolean) : tnode;
+ begin
+ result:=internalsimplify(false);
+ end;
+
+
+ function tifnode.pass_typecheck:tnode;
+ begin
+ result:=nil;
+ resultdef:=voidtype;
+
+ typecheckpass(left);
+
+ { tp procvar support }
+ maybe_call_procvar(left,true);
+
+ { if path }
+ if assigned(right) then
+ typecheckpass(right);
+ { else path }
+ if assigned(t1) then
+ typecheckpass(t1);
+ set_varstate(left,vs_read,[vsf_must_be_valid]);
+ if codegenerror then
+ exit;
+
+ if not(is_boolean(left.resultdef)) and
+ not(is_typeparam(left.resultdef)) then
+ begin
+ if left.resultdef.typ=variantdef then
+ inserttypeconv(left,pasbool8type)
+ else
+ Message1(type_e_boolean_expr_expected,left.resultdef.typename);
+ end;
+ result:=internalsimplify(true);
+ end;
+
+
+ function tifnode.pass_1 : tnode;
+ begin
+ result:=nil;
+ expectloc:=LOC_VOID;
+ firstpass(left);
+
+ { if path }
+ if assigned(right) then
+ firstpass(right);
+
+ { else path }
+ if assigned(t1) then
+ firstpass(t1);
+
+ { leave if we've got an error in one of the paths }
+
+ if codegenerror then
+ exit;
+ end;
+
+
+{*****************************************************************************
+ TFORNODE
+*****************************************************************************}
+
+ constructor tfornode.create(l,r,_t1,_t2 : tnode;back : boolean);
+
+ begin
+ inherited create(forn,l,r,_t1,_t2);
+ if back then
+ include(loopflags,lnf_backward);
+ include(loopflags,lnf_testatbegin);
+ end;
+
+ procedure Tfornode.loop_var_access(not_type:Tnotification_flag;
+ symbol:Tsym);
+
+ begin
+ {If there is a read access, the value of the loop counter is important;
+ at the end of the loop the loop variable should contain the value it
+ had in the last iteration.}
+ if not_type=vn_onwrite then
+ begin
+ writeln('Loopvar does not matter on exit');
+ end
+ else
+ begin
+ exclude(loopflags,lnf_dont_mind_loopvar_on_exit);
+ writeln('Loopvar does matter on exit');
+ end;
+ Tabstractvarsym(symbol).unregister_notification(loopvar_notid);
+ end;
+
+
+ function tfornode.simplify(forinline : boolean) : tnode;
+ begin
+ result:=nil;
+ if (t1.nodetype=ordconstn) and
+ (right.nodetype=ordconstn) and
+ (
+ (
+ (lnf_backward in loopflags) and
+ (tordconstnode(right).value<tordconstnode(t1).value)
+ ) or
+ (
+ not(lnf_backward in loopflags) and
+ (tordconstnode(right).value>tordconstnode(t1).value)
+ )
+ ) then
+ result:=cnothingnode.create;
+ end;
+
+
+ function tfornode.pass_typecheck:tnode;
+ var
+ res : tnode;
+ begin
+ result:=nil;
+ resultdef:=voidtype;
+
+ { process the loopvar, from and to, varstates are already set }
+ typecheckpass(left);
+ typecheckpass(right);
+ typecheckpass(t1);
+
+ set_varstate(left,vs_written,[]);
+
+ { loop unrolling }
+ if cs_opt_loopunroll in current_settings.optimizerswitches then
+ begin
+ res:=unroll_loop(self);
+ if assigned(res) then
+ begin
+ typecheckpass(res);
+ result:=res;
+ exit;
+ end;
+ end;
+
+ { Can we spare the first comparision? }
+ if (t1.nodetype=ordconstn) and
+ (right.nodetype=ordconstn) and
+ (
+ (
+ (lnf_backward in loopflags) and
+ (Tordconstnode(right).value>=Tordconstnode(t1).value)
+ ) or
+ (
+ not(lnf_backward in loopflags) and
+ (Tordconstnode(right).value<=Tordconstnode(t1).value)
+ )
+ ) then
+ exclude(loopflags,lnf_testatbegin);
+
+ { Make sure that the loop var and the
+ from and to values are compatible types }
+ check_ranges(right.fileinfo,right,left.resultdef);
+ inserttypeconv(right,left.resultdef);
+
+ check_ranges(t1.fileinfo,t1,left.resultdef);
+ inserttypeconv(t1,left.resultdef);
+
+ if assigned(t2) then
+ typecheckpass(t2);
+ end;
+
+
+ function tfornode.pass_1 : tnode;
+ begin
+ result:=nil;
+ expectloc:=LOC_VOID;
+
+ firstpass(left);
+ firstpass(right);
+ firstpass(t1);
+
+ if assigned(t2) then
+ begin
+ firstpass(t2);
+ if codegenerror then
+ exit;
+ end;
+ end;
+
+
+{*****************************************************************************
+ TEXITNODE
+*****************************************************************************}
+
+ constructor texitnode.create(l:tnode);
+ begin
+ inherited create(exitn,l);
+ if assigned(left) then
+ begin
+ { add assignment to funcretsym }
+ left:=ctypeconvnode.create(left,current_procinfo.procdef.returndef);
+ left:=cassignmentnode.create(
+ cloadnode.create(current_procinfo.procdef.funcretsym,current_procinfo.procdef.funcretsym.owner),
+ left);
+ end;
+ end;
+
+
+ constructor texitnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ end;
+
+
+ procedure texitnode.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ end;
+
+
+ function texitnode.pass_typecheck:tnode;
+ var
+ newstatement : tstatementnode;
+ begin
+ result:=nil;
+ if assigned(left) then
+ begin
+ result:=internalstatements(newstatement);
+ addstatement(newstatement,left);
+ left:=nil;
+ addstatement(newstatement,self.getcopy);
+ end;
+ resultdef:=voidtype;
+ end;
+
+
+ function texitnode.pass_1 : tnode;
+ begin
+ result:=nil;
+ expectloc:=LOC_VOID;
+ if assigned(left) then
+ internalerror(2011052801);
+ end;
+
+
+{*****************************************************************************
+ TBREAKNODE
+*****************************************************************************}
+
+ constructor tbreaknode.create;
+
+ begin
+ inherited create(breakn);
+ end;
+
+
+ function tbreaknode.pass_typecheck:tnode;
+ begin
+ result:=nil;
+ resultdef:=voidtype;
+ end;
+
+
+ function tbreaknode.pass_1 : tnode;
+ begin
+ result:=nil;
+ expectloc:=LOC_VOID;
+ end;
+
+
+{*****************************************************************************
+ TCONTINUENODE
+*****************************************************************************}
+
+ constructor tcontinuenode.create;
+ begin
+ inherited create(continuen);
+ end;
+
+
+ function tcontinuenode.pass_typecheck:tnode;
+ begin
+ result:=nil;
+ resultdef:=voidtype;
+ end;
+
+
+ function tcontinuenode.pass_1 : tnode;
+ begin
+ result:=nil;
+ expectloc:=LOC_VOID;
+ end;
+
+
+{*****************************************************************************
+ TGOTONODE
+*****************************************************************************}
+
+ constructor tgotonode.create(p : tlabelsym);
+ begin
+ inherited create(goton);
+ exceptionblock:=current_exceptblock;
+ labelnode:=nil;
+ labelsym:=p;
+ end;
+
+
+ constructor tgotonode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ labelnodeidx:=ppufile.getlongint;
+ exceptionblock:=ppufile.getbyte;
+ end;
+
+
+ procedure tgotonode.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ labelnodeidx:=labelnode.ppuidx;
+ ppufile.putlongint(labelnodeidx);
+ ppufile.putbyte(exceptionblock);
+ end;
+
+
+ procedure tgotonode.buildderefimpl;
+ begin
+ inherited buildderefimpl;
+ end;
+
+
+ procedure tgotonode.derefimpl;
+ begin
+ inherited derefimpl;
+ end;
+
+
+ procedure tgotonode.resolveppuidx;
+ begin
+ labelnode:=tlabelnode(nodeppuidxget(labelnodeidx));
+ if labelnode.nodetype<>labeln then
+ internalerror(200809021);
+ end;
+
+
+ function tgotonode.pass_typecheck:tnode;
+ begin
+ result:=nil;
+ resultdef:=voidtype;
+ end;
+
+
+ function tgotonode.pass_1 : tnode;
+ var
+ p2 : tprocinfo;
+ begin
+ result:=nil;
+ expectloc:=LOC_VOID;
+
+ { The labelnode can already be set when
+ this node was copied }
+ if not(assigned(labelnode)) then
+ begin
+ { inner procedure goto? }
+ if assigned(labelsym.code) and
+ ((assigned(labelsym.owner) and (current_procinfo.procdef.parast.symtablelevel=labelsym.owner.symtablelevel)) or
+ { generated by the optimizer? }
+ not(assigned(labelsym.owner))) then
+ labelnode:=tlabelnode(labelsym.code)
+ else if (m_non_local_goto in current_settings.modeswitches) and
+ assigned(labelsym.owner) then
+ begin
+ if current_procinfo.procdef.parast.symtablelevel>labelsym.owner.symtablelevel then
+ begin
+ { don't mess with the exception blocks, global gotos in/out side exception blocks are not allowed }
+ if exceptionblock>0 then
+ CGMessage(cg_e_goto_inout_of_exception_block);
+
+ { goto across procedures using exception?
+ this is not allowed because we cannot
+ easily unwind the exception frame
+ stack
+ }
+ p2:=current_procinfo;
+ while true do
+ begin
+ if (p2.flags*[pi_needs_implicit_finally,pi_uses_exceptions,pi_has_implicit_finally])<>[] then
+ Message(cg_e_goto_across_procedures_with_exceptions_not_allowed);
+ if labelsym.owner=p2.procdef.localst then
+ break;
+ p2:=p2.parent
+ end;
+
+ if assigned(labelsym.jumpbuf) then
+ begin
+ labelsym.nonlocal:=true;
+ result:=ccallnode.createintern('fpc_longjmp',
+ ccallparanode.create(cordconstnode.create(1,sinttype,true),
+ ccallparanode.create(cloadnode.create(labelsym.jumpbuf,labelsym.jumpbuf.owner),
+ nil)));
+ end
+ else
+ CGMessage1(cg_e_goto_label_not_found,labelsym.realname);
+ end
+ else
+ CGMessage(cg_e_interprocedural_goto_only_to_outer_scope_allowed);
+ end
+ else
+ CGMessage1(cg_e_goto_label_not_found,labelsym.realname);
+ end;
+
+ { check if we don't mess with exception blocks }
+ if assigned(labelnode) and
+ (exceptionblock<>labelnode.exceptionblock) then
+ CGMessage(cg_e_goto_inout_of_exception_block);
+ end;
+
+
+ function tgotonode.dogetcopy : tnode;
+ var
+ p : tgotonode;
+ begin
+ p:=tgotonode(inherited dogetcopy);
+ p.exceptionblock:=exceptionblock;
+
+ { generate labelnode if not done yet }
+ if not(assigned(labelnode)) then
+ begin
+ if assigned(labelsym) and assigned(labelsym.code) then
+ labelnode:=tlabelnode(labelsym.code)
+ end;
+
+ p.labelsym:=labelsym;
+ if assigned(labelnode) then
+ p.labelnode:=tlabelnode(labelnode.dogetcopy)
+ else
+ begin
+ { don't trigger IE when there was already an error, i.e. the
+ label is not defined. See tw11763 (PFV) }
+ if errorcount=0 then
+ internalerror(200610291);
+ end;
+ result:=p;
+ end;
+
+
+ function tgotonode.docompare(p: tnode): boolean;
+ begin
+ docompare := false;
+ end;
+
+
+{*****************************************************************************
+ TLABELNODE
+*****************************************************************************}
+
+ constructor tlabelnode.create(l:tnode;alabsym:tlabelsym);
+ begin
+ inherited create(labeln,l);
+ exceptionblock:=current_exceptblock;
+ labsym:=alabsym;
+ { Register labelnode in labelsym }
+ labsym.code:=self;
+ end;
+
+
+ constructor tlabelnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ exceptionblock:=ppufile.getbyte;
+ end;
+
+
+ destructor tlabelnode.destroy;
+ begin
+ { Remove reference in labelsym, this is to prevent
+ goto's to this label }
+ if assigned(labsym) and (labsym.code=pointer(self)) then
+ labsym.code:=nil;
+ inherited destroy;
+ end;
+
+
+ procedure tlabelnode.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putbyte(exceptionblock);
+ end;
+
+
+ procedure tlabelnode.buildderefimpl;
+ begin
+ inherited buildderefimpl;
+ end;
+
+
+ procedure tlabelnode.derefimpl;
+ begin
+ inherited derefimpl;
+ end;
+
+
+ function tlabelnode.pass_typecheck:tnode;
+ begin
+ result:=nil;
+ { left could still be unassigned }
+ if assigned(left) then
+ typecheckpass(left);
+ resultdef:=voidtype;
+ end;
+
+
+ function tlabelnode.pass_1 : tnode;
+ begin
+ result:=nil;
+ expectloc:=LOC_VOID;
+
+ include(current_procinfo.flags,pi_has_label);
+
+ if assigned(labsym) and labsym.nonlocal then
+ include(current_procinfo.flags,pi_has_interproclabel);
+
+ if assigned(left) then
+ firstpass(left);
+ if (m_non_local_goto in current_settings.modeswitches) and
+ (current_procinfo.procdef.parast.symtablelevel<>labsym.owner.symtablelevel) then
+ CGMessage(cg_e_labels_cannot_defined_outside_declaration_scope)
+ end;
+
+
+ function tlabelnode.dogetcopy : tnode;
+ begin
+ if not(assigned(copiedto)) then
+ copiedto:=tlabelnode(inherited dogetcopy);
+ copiedto.exceptionblock:=exceptionblock;
+
+ result:=copiedto;
+ end;
+
+
+ function tlabelnode.docompare(p: tnode): boolean;
+ begin
+ docompare := false;
+ end;
+
+
+{*****************************************************************************
+ TRAISENODE
+*****************************************************************************}
+
+ constructor traisenode.create(l,taddr,tframe:tnode);
+ begin
+ inherited create(raisen,l,taddr,tframe);
+ end;
+
+
+ function traisenode.pass_typecheck:tnode;
+ begin
+ result:=nil;
+ resultdef:=voidtype;
+ if assigned(left) then
+ begin
+ { first para must be a _class_ }
+ typecheckpass(left);
+ set_varstate(left,vs_read,[vsf_must_be_valid]);
+ if codegenerror then
+ exit;
+ if not(is_class(left.resultdef)) then
+ CGMessage1(type_e_class_type_expected,left.resultdef.typename);
+ { insert needed typeconvs for addr,frame }
+ if assigned(right) then
+ begin
+ { addr }
+ typecheckpass(right);
+ inserttypeconv(right,voidpointertype);
+ { frame }
+ if assigned(third) then
+ begin
+ typecheckpass(third);
+ inserttypeconv(third,voidpointertype);
+ end;
+ end;
+ end;
+ end;
+
+
+ function traisenode.pass_1 : tnode;
+ begin
+ result:=nil;
+ include(current_procinfo.flags,pi_do_call);
+ expectloc:=LOC_VOID;
+ if assigned(left) then
+ begin
+ { first para must be a _class_ }
+ firstpass(left);
+ { insert needed typeconvs for addr,frame }
+ if assigned(right) then
+ begin
+ { addr }
+ firstpass(right);
+ { frame }
+ if assigned(third) then
+ firstpass(third);
+ end;
+ end;
+ end;
+
+
+{*****************************************************************************
+ TTRYEXCEPTNODE
+*****************************************************************************}
+
+ constructor ttryexceptnode.create(l,r,_t1 : tnode);
+ begin
+ inherited create(tryexceptn,l,r,_t1,nil);
+ end;
+
+
+ function ttryexceptnode.pass_typecheck:tnode;
+ begin
+ result:=nil;
+ typecheckpass(left);
+ { on statements }
+ if assigned(right) then
+ typecheckpass(right);
+ { else block }
+ if assigned(t1) then
+ typecheckpass(t1);
+ resultdef:=voidtype;
+ end;
+
+
+ function ttryexceptnode.pass_1 : tnode;
+ begin
+ result:=nil;
+ include(current_procinfo.flags,pi_do_call);
+ include(current_procinfo.flags,pi_uses_exceptions);
+ expectloc:=LOC_VOID;
+ firstpass(left);
+ { on statements }
+ if assigned(right) then
+ firstpass(right);
+ { else block }
+ if assigned(t1) then
+ firstpass(t1);
+ end;
+
+
+{*****************************************************************************
+ TTRYFINALLYNODE
+*****************************************************************************}
+
+ constructor ttryfinallynode.create(l,r:tnode);
+ begin
+ inherited create(tryfinallyn,l,r,nil,nil);
+ include(current_procinfo.flags,pi_uses_exceptions);
+ implicitframe:=false;
+ end;
+
+
+ constructor ttryfinallynode.create_implicit(l,r,_t1:tnode);
+ begin
+ inherited create(tryfinallyn,l,r,_t1,nil);
+ implicitframe:=true;
+ end;
+
+
+ function ttryfinallynode.pass_typecheck:tnode;
+ begin
+ result:=nil;
+ include(current_procinfo.flags,pi_do_call);
+ resultdef:=voidtype;
+
+ typecheckpass(left);
+ // "try block" is "used"? (JM)
+ set_varstate(left,vs_readwritten,[vsf_must_be_valid]);
+
+ typecheckpass(right);
+ // "except block" is "used"? (JM)
+ set_varstate(right,vs_readwritten,[vsf_must_be_valid]);
+
+ { special finally block only executed when there was an exception }
+ if assigned(t1) then
+ begin
+ typecheckpass(t1);
+ // "finally block" is "used"? (JM)
+ set_varstate(t1,vs_readwritten,[vsf_must_be_valid]);
+ end;
+ end;
+
+
+ function ttryfinallynode.pass_1 : tnode;
+ begin
+ result:=nil;
+ expectloc:=LOC_VOID;
+ firstpass(left);
+
+ firstpass(right);
+
+ if assigned(t1) then
+ firstpass(t1);
+ end;
+
+
+ function ttryfinallynode.simplify(forinline : boolean): tnode;
+ begin
+ result:=nil;
+ { if the try contains no code, we can kill
+ the try and except and return only the
+ finally part }
+ if has_no_code(left) then
+ begin
+ result:=right;
+ right:=nil;
+ end;
+ end;
+
+
+{*****************************************************************************
+ TONNODE
+*****************************************************************************}
+
+ constructor tonnode.create(l,r:tnode);
+ begin
+ inherited create(onn,l,r);
+ excepTSymtable:=nil;
+ excepttype:=nil;
+ end;
+
+
+ destructor tonnode.destroy;
+ begin
+ { copied nodes don't need to release the symtable }
+ if assigned(excepTSymtable) then
+ excepTSymtable.free;
+ inherited destroy;
+ end;
+
+
+ constructor tonnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ excepTSymtable:=nil;
+ excepttype:=nil;
+ end;
+
+
+ function tonnode.dogetcopy : tnode;
+ var
+ n : tonnode;
+ begin
+ n:=tonnode(inherited dogetcopy);
+ if assigned(exceptsymtable) then
+ n.exceptsymtable:=exceptsymtable.getcopy
+ else
+ n.exceptsymtable:=nil;
+ n.excepttype:=excepttype;
+ result:=n;
+ end;
+
+
+ function tonnode.pass_typecheck:tnode;
+ begin
+ result:=nil;
+ resultdef:=voidtype;
+ if not(is_class(excepttype)) then
+ CGMessage1(type_e_class_type_expected,excepttype.typename);
+ if assigned(left) then
+ typecheckpass(left);
+ if assigned(right) then
+ typecheckpass(right);
+ end;
+
+
+ function tonnode.pass_1 : tnode;
+ begin
+ result:=nil;
+ include(current_procinfo.flags,pi_do_call);
+ expectloc:=LOC_VOID;
+ if assigned(left) then
+ firstpass(left);
+
+ if assigned(right) then
+ firstpass(right);
+ end;
+
+
+ function tonnode.docompare(p: tnode): boolean;
+ begin
+ docompare := false;
+ end;
+
+end.
diff --git a/closures/compiler/ninl.pas b/closures/compiler/ninl.pas
new file mode 100644
index 0000000000..647978002c
--- /dev/null
+++ b/closures/compiler/ninl.pas
@@ -0,0 +1,3375 @@
+{
+ Copyright (c) 1998-2007 by Florian Klaempfl
+
+ Type checking and register allocation for inline nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit ninl;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,htypechk,cpuinfo,symtype;
+
+ {$i compinnr.inc}
+
+ type
+ tinlinenode = class(tunarynode)
+ inlinenumber : byte;
+ constructor create(number : byte;is_const:boolean;l : tnode);virtual;
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ function dogetcopy : tnode;override;
+ function pass_1 : tnode;override;
+ function pass_typecheck:tnode;override;
+ function simplify(forinline : boolean): tnode;override;
+ function docompare(p: tnode): boolean; override;
+
+ { pack and unpack are changed into for-loops by the compiler }
+ function first_pack_unpack: tnode; virtual;
+
+ { All the following routines currently
+ call compilerprocs, unless they are
+ overridden in which case, the code
+ generator handles them.
+ }
+ function first_pi: tnode ; virtual;
+ function first_arctan_real: tnode; virtual;
+ function first_abs_real: tnode; virtual;
+ function first_sqr_real: tnode; virtual;
+ function first_sqrt_real: tnode; virtual;
+ function first_ln_real: tnode; virtual;
+ function first_cos_real: tnode; virtual;
+ function first_sin_real: tnode; virtual;
+ function first_exp_real: tnode; virtual;
+ function first_frac_real: tnode; virtual;
+ function first_round_real: tnode; virtual;
+ function first_trunc_real: tnode; virtual;
+ function first_int_real: tnode; virtual;
+ function first_abs_long: tnode; virtual;
+ private
+ function handle_str: tnode;
+ function handle_reset_rewrite_typed: tnode;
+ function handle_text_read_write(filepara,params:Ttertiarynode;var newstatement:Tnode):boolean;
+ function handle_typed_read_write(filepara,params:Ttertiarynode;var newstatement:Tnode):boolean;
+ function handle_read_write: tnode;
+ function handle_val: tnode;
+ end;
+ tinlinenodeclass = class of tinlinenode;
+
+ var
+ cinlinenode : tinlinenodeclass = tinlinenode;
+
+ function geninlinenode(number : byte;is_const:boolean;l : tnode) : tinlinenode;
+
+implementation
+
+ uses
+ verbose,globals,systems,constexp,
+ globtype, cutils,
+ symconst,symdef,symsym,symtable,paramgr,defutil,
+ pass_1,
+ ncal,ncon,ncnv,nadd,nld,nbas,nflw,nmem,nmat,nutils,
+ nobjc,objcdef,
+ cgbase,procinfo
+ ;
+
+ function geninlinenode(number : byte;is_const:boolean;l : tnode) : tinlinenode;
+
+ begin
+ geninlinenode:=cinlinenode.create(number,is_const,l);
+ end;
+
+{*****************************************************************************
+ TINLINENODE
+*****************************************************************************}
+
+ constructor tinlinenode.create(number : byte;is_const:boolean;l : tnode);
+
+ begin
+ inherited create(inlinen,l);
+ if is_const then
+ include(flags,nf_inlineconst);
+ inlinenumber:=number;
+ end;
+
+
+ constructor tinlinenode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ inlinenumber:=ppufile.getbyte;
+ end;
+
+
+ procedure tinlinenode.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putbyte(inlinenumber);
+ end;
+
+
+ function tinlinenode.dogetcopy : tnode;
+ var
+ n : tinlinenode;
+ begin
+ n:=tinlinenode(inherited dogetcopy);
+ n.inlinenumber:=inlinenumber;
+ result:=n;
+ end;
+
+
+ function tinlinenode.handle_str : tnode;
+ var
+ lenpara,
+ fracpara,
+ newparas,
+ tmppara,
+ dest,
+ source : tcallparanode;
+ procname: string;
+ is_real,is_enum : boolean;
+ rt : aint;
+
+ begin
+ result := cerrornode.create;
+
+ { get destination string }
+ dest := tcallparanode(left);
+
+ { get source para (number) }
+ source := dest;
+ while assigned(source.right) do
+ source := tcallparanode(source.right);
+
+ { destination parameter must be a normal (not a colon) parameter, this
+ check is needed because str(v:len) also has 2 parameters }
+ if (source=dest) or
+ (cpf_is_colon_para in tcallparanode(dest).callparaflags) then
+ begin
+ CGMessage1(parser_e_wrong_parameter_size,'Str');
+ exit;
+ end;
+
+ { in case we are in a generic definition, we cannot
+ do all checks, the parameters might be type parameters }
+ if df_generic in current_procinfo.procdef.defoptions then
+ begin
+ result.Free;
+ result:=nil;
+ resultdef:=voidtype;
+ exit;
+ end;
+
+ is_real:=(source.resultdef.typ = floatdef) or is_currency(source.resultdef);
+ is_enum:=source.left.resultdef.typ=enumdef;
+
+ if ((dest.left.resultdef.typ<>stringdef) and
+ not(is_chararray(dest.left.resultdef))) or
+ not(is_real or is_enum or
+ (source.left.resultdef.typ=orddef)) then
+ begin
+ CGMessagePos(fileinfo,parser_e_illegal_expression);
+ exit;
+ end;
+
+ { get len/frac parameters }
+ lenpara := nil;
+ fracpara := nil;
+ if (cpf_is_colon_para in tcallparanode(dest.right).callparaflags) then
+ begin
+ lenpara := tcallparanode(dest.right);
+
+ { we can let the callnode do the type checking of these parameters too, }
+ { but then the error messages aren't as nice }
+ if not is_integer(lenpara.resultdef) then
+ begin
+ CGMessagePos1(lenpara.fileinfo,
+ type_e_integer_expr_expected,lenpara.resultdef.typename);
+ exit;
+ end;
+ if (cpf_is_colon_para in tcallparanode(lenpara.right).callparaflags) then
+ begin
+ { parameters are in reverse order! }
+ fracpara := lenpara;
+ lenpara := tcallparanode(lenpara.right);
+ if not is_real then
+ begin
+ CGMessagePos(lenpara.fileinfo,parser_e_illegal_colon_qualifier);
+ exit
+ end;
+ if not is_integer(lenpara.resultdef) then
+ begin
+ CGMessagePos1(lenpara.fileinfo,
+ type_e_integer_expr_expected,lenpara.resultdef.typename);
+ exit;
+ end;
+ end;
+ end;
+
+ { generate the parameter list for the compilerproc }
+ newparas := dest;
+
+ { if we have a float parameter, insert the realtype, len and fracpara parameters }
+ if is_real then
+ begin
+ { insert realtype parameter }
+ if not is_currency(source.resultdef) then
+ begin
+ rt:=ord(tfloatdef(source.left.resultdef).floattype);
+ newparas.right := ccallparanode.create(cordconstnode.create(
+ rt,s32inttype,true),newparas.right);
+ tmppara:=tcallparanode(newparas.right);
+ end
+ else
+ tmppara:=newparas;
+ { if necessary, insert a fraction parameter }
+ if not assigned(fracpara) then
+ begin
+ tmppara.right := ccallparanode.create(
+ cordconstnode.create(int64(-1),s32inttype,false),
+ tmppara.right);
+ fracpara := tcallparanode(tmppara.right);
+ end;
+ { if necessary, insert a length para }
+ if not assigned(lenpara) then
+ fracpara.right := ccallparanode.create(
+ cordconstnode.create(int64(-32767),s32inttype,false),
+ fracpara.right);
+ end
+ else if is_enum then
+ begin
+ {Insert a reference to the ord2string index.}
+ newparas.right:=Ccallparanode.create(
+ Caddrnode.create_internal(
+ Crttinode.create(Tenumdef(source.left.resultdef),fullrtti,rdt_normal)
+ ),
+ newparas.right);
+ {Insert a reference to the typinfo.}
+ newparas.right:=Ccallparanode.create(
+ Caddrnode.create_internal(
+ Crttinode.create(Tenumdef(source.left.resultdef),fullrtti,rdt_ord2str)
+ ),
+ newparas.right);
+ {Insert a type conversion from the enumeration to longint.}
+ source.left:=Ctypeconvnode.create_internal(source.left,s32inttype);
+ typecheckpass(source.left);
+
+ { if necessary, insert a length para }
+ if not assigned(lenpara) then
+ Tcallparanode(Tcallparanode(newparas.right).right).right:=
+ Ccallparanode.create(
+ cordconstnode.create(int64(-1),s32inttype,false),
+ Tcallparanode(Tcallparanode(newparas.right).right).right
+ );
+ end
+ else
+ { for a normal parameter, insert a only length parameter if one is missing }
+ if not assigned(lenpara) then
+ newparas.right := ccallparanode.create(cordconstnode.create(int64(-1),s32inttype,false),
+ newparas.right);
+
+ { remove the parameters from the original node so they won't get disposed, }
+ { since they're reused }
+ left := nil;
+
+ { create procedure name }
+ if is_chararray(dest.resultdef) then
+ procname:='fpc_chararray_'
+ else
+ procname := 'fpc_' + tstringdef(dest.resultdef).stringtypname+'_';
+ if is_real then
+ if is_currency(source.resultdef) then
+ procname := procname + 'currency'
+ else
+ procname := procname + 'float'
+ else if is_enum then
+ procname:=procname+'enum'
+ else
+ case torddef(source.resultdef).ordtype of
+{$ifdef cpu64bitaddr}
+ u64bit:
+ procname := procname + 'uint';
+{$else}
+ u32bit:
+ procname := procname + 'uint';
+ u64bit:
+ procname := procname + 'qword';
+ scurrency,
+ s64bit:
+ procname := procname + 'int64';
+ pasbool8,pasbool16,pasbool32,pasbool64,
+ bool8bit,bool16bit,bool32bit,bool64bit:
+ procname := procname + 'bool';
+{$endif}
+ else
+ procname := procname + 'sint';
+ end;
+
+ { for ansistrings insert the encoding argument }
+ if is_ansistring(dest.resultdef) then
+ newparas:=ccallparanode.create(cordconstnode.create(
+ getparaencoding(dest.resultdef),u16inttype,true),newparas);
+
+ { free the errornode we generated in the beginning }
+ result.free;
+ { create the call node, }
+ result := ccallnode.createintern(procname,newparas);
+ end;
+
+
+ function tinlinenode.handle_reset_rewrite_typed: tnode;
+ begin
+ { since this is a "in_xxxx_typedfile" node, we can be sure we have }
+ { a typed file as argument and we don't have to check it again (JM) }
+
+ { add the recsize parameter }
+ { note: for some reason, the parameter of intern procedures with only one }
+ { parameter is gets lifted out of its original tcallparanode (see round }
+ { line 1306 of ncal.pas), so recreate a tcallparanode here (JM) }
+ left := ccallparanode.create(cordconstnode.create(
+ tfiledef(left.resultdef).typedfiledef.size,s32inttype,true),
+ ccallparanode.create(left,nil));
+ { create the correct call }
+ if m_iso in current_settings.modeswitches then
+ begin
+ if inlinenumber=in_reset_typedfile then
+ result := ccallnode.createintern('fpc_reset_typed_iso',left)
+ else
+ result := ccallnode.createintern('fpc_rewrite_typed_iso',left);
+ end
+ else
+ begin
+ if inlinenumber=in_reset_typedfile then
+ result := ccallnode.createintern('fpc_reset_typed',left)
+ else
+ result := ccallnode.createintern('fpc_rewrite_typed',left);
+ end;
+
+ { make sure left doesn't get disposed, since we use it in the new call }
+ left := nil;
+ end;
+
+
+ procedure maybe_convert_to_string(var n: tnode);
+ begin
+ { stringconstnodes are arrays of char. It's much more }
+ { efficient to write a constant string, so convert }
+ { either to shortstring or ansistring depending on }
+ { length }
+ if (n.nodetype=stringconstn) then
+ if is_chararray(n.resultdef) then
+ if (tstringconstnode(n).len<=255) then
+ inserttypeconv(n,cshortstringtype)
+ else
+ inserttypeconv(n,getansistringdef)
+ else if is_widechararray(n.resultdef) then
+ inserttypeconv(n,cwidestringtype);
+ end;
+
+
+ function Tinlinenode.handle_text_read_write(filepara,params:Ttertiarynode;var newstatement:Tnode):boolean;
+
+ {Read(ln)/write(ln) for text files.}
+
+ const procprefixes:array[boolean] of string[15]=('fpc_write_text_','fpc_read_text_');
+
+ var error_para,is_real,special_handling,found_error,do_read:boolean;
+ p1:Tnode;
+ nextpara,
+ indexpara,
+ lenpara,
+ para,
+ fracpara:Tcallparanode;
+ temp:Ttempcreatenode;
+ readfunctype:Tdef;
+ name:string[63];
+
+ begin
+ para:=Tcallparanode(params);
+ found_error:=false;
+ do_read:=inlinenumber in [in_read_x,in_readln_x,in_readstr_x];
+ while assigned(para) do
+ begin
+ { is this parameter faulty? }
+ error_para:=false;
+ { is this parameter a real? }
+ is_real:=false;
+ { type used for the read(), this is used to check
+ whether a temp is needed for range checking }
+ readfunctype:=nil;
+
+ { can't read/write types }
+ if (para.left.nodetype=typen) and not(ttypenode(para.left).typedef.typ=undefineddef) then
+ begin
+ CGMessagePos(para.fileinfo,type_e_cant_read_write_type);
+ error_para := true;
+ end;
+
+ { support writeln(procvar) }
+ if para.left.resultdef.typ=procvardef then
+ begin
+ p1:=ccallnode.create_procvar(nil,para.left);
+ typecheckpass(p1);
+ para.left:=p1;
+ end;
+
+ if inlinenumber in [in_write_x,in_writeln_x] then
+ { prefer strings to chararrays }
+ maybe_convert_to_string(para.left);
+
+ case para.left.resultdef.typ of
+ stringdef :
+ name:=procprefixes[do_read]+tstringdef(para.left.resultdef).stringtypname;
+ pointerdef :
+ begin
+ if (not is_pchar(para.left.resultdef)) or do_read then
+ begin
+ CGMessagePos(para.fileinfo,type_e_cant_read_write_type);
+ error_para := true;
+ end
+ else
+ name:=procprefixes[do_read]+'pchar_as_pointer';
+ end;
+ floatdef :
+ begin
+ is_real:=true;
+ if Tfloatdef(para.left.resultdef).floattype=s64currency then
+ name := procprefixes[do_read]+'currency'
+ else
+ begin
+ name := procprefixes[do_read]+'float';
+ readfunctype:=pbestrealtype^;
+ end;
+ end;
+ enumdef:
+ begin
+ name:=procprefixes[do_read]+'enum';
+ readfunctype:=s32inttype;
+ end;
+ orddef :
+ begin
+ case Torddef(para.left.resultdef).ordtype of
+{$ifdef cpu64bitaddr}
+ s64bit,
+{$endif cpu64bitaddr}
+ s8bit,
+ s16bit,
+ s32bit :
+ begin
+ name := procprefixes[do_read]+'sint';
+ readfunctype:=sinttype;
+ end;
+{$ifdef cpu64bitaddr}
+ u64bit,
+{$endif cpu64bitaddr}
+ u8bit,
+ u16bit,
+ u32bit :
+ begin
+ name := procprefixes[do_read]+'uint';
+ readfunctype:=uinttype;
+ end;
+ uchar :
+ begin
+ name := procprefixes[do_read]+'char';
+ { iso pascal needs a different handler }
+ if (m_iso in current_settings.modeswitches) and do_read then
+ name:=name+'_iso';
+ readfunctype:=cchartype;
+ end;
+ uwidechar :
+ begin
+ name := procprefixes[do_read]+'widechar';
+ readfunctype:=cwidechartype;
+ end;
+{$ifndef cpu64bitaddr}
+ s64bit :
+ begin
+ name := procprefixes[do_read]+'int64';
+ readfunctype:=s64inttype;
+ end;
+ u64bit :
+ begin
+ name := procprefixes[do_read]+'qword';
+ readfunctype:=u64inttype;
+ end;
+{$endif not cpu64bitaddr}
+ scurrency:
+ begin
+ name := procprefixes[do_read]+'currency';
+ readfunctype:=s64currencytype;
+ is_real:=true;
+ end;
+ pasbool8,
+ pasbool16,
+ pasbool32,
+ pasbool64,
+ bool8bit,
+ bool16bit,
+ bool32bit,
+ bool64bit:
+ if do_read then
+ begin
+ CGMessagePos(para.fileinfo,type_e_cant_read_write_type);
+ error_para := true;
+ end
+ else
+ begin
+ name := procprefixes[do_read]+'boolean';
+ readfunctype:=pasbool8type;
+ end
+ else
+ begin
+ CGMessagePos(para.fileinfo,type_e_cant_read_write_type);
+ error_para := true;
+ end;
+ end;
+ end;
+ variantdef :
+ name:=procprefixes[do_read]+'variant';
+ arraydef :
+ begin
+ if is_chararray(para.left.resultdef) then
+ name := procprefixes[do_read]+'pchar_as_array'
+ else
+ begin
+ CGMessagePos(para.fileinfo,type_e_cant_read_write_type);
+ error_para := true;
+ end
+ end;
+ { generic parameter }
+ undefineddef:
+ { don't try to generate any code for a writeln on a generic parameter }
+ error_para:=true;
+ else
+ begin
+ CGMessagePos(para.fileinfo,type_e_cant_read_write_type);
+ error_para := true;
+ end;
+ end;
+
+ { iso pascal needs a different handler }
+ if (m_iso in current_settings.modeswitches) and not(do_read) then
+ name:=name+'_iso';
+
+ { check for length/fractional colon para's }
+ fracpara:=nil;
+ lenpara:=nil;
+ indexpara:=nil;
+ if assigned(para.right) and
+ (cpf_is_colon_para in tcallparanode(para.right).callparaflags) then
+ begin
+ lenpara := tcallparanode(para.right);
+ if assigned(lenpara.right) and
+ (cpf_is_colon_para in tcallparanode(lenpara.right).callparaflags) then
+ fracpara:=tcallparanode(lenpara.right);
+ end;
+ { get the next parameter now already, because we're going }
+ { to muck around with the pointers }
+ if assigned(fracpara) then
+ nextpara := tcallparanode(fracpara.right)
+ else if assigned(lenpara) then
+ nextpara := tcallparanode(lenpara.right)
+ else
+ nextpara := tcallparanode(para.right);
+
+ { check if a fracpara is allowed }
+ if assigned(fracpara) and not is_real then
+ begin
+ CGMessagePos(fracpara.fileinfo,parser_e_illegal_colon_qualifier);
+ error_para := true;
+ end
+ else if assigned(lenpara) and do_read then
+ begin
+ { I think this is already filtered out by parsing, but I'm not sure (JM) }
+ CGMessagePos(lenpara.fileinfo,parser_e_illegal_colon_qualifier);
+ error_para := true;
+ end;
+
+ { adjust found_error }
+ found_error := found_error or error_para;
+
+ if not error_para then
+ begin
+ special_handling:=false;
+ { create dummy frac/len para's if necessary }
+ if not do_read then
+ begin
+ { difference in default value for floats and the rest :( }
+ if not is_real then
+ begin
+ if not assigned(lenpara) then
+ begin
+ if m_iso in current_settings.modeswitches then
+ lenpara := ccallparanode.create(
+ cordconstnode.create(-1,s32inttype,false),nil)
+ else
+ lenpara := ccallparanode.create(
+ cordconstnode.create(0,s32inttype,false),nil);
+ end
+ else
+ { make sure we don't pass the successive }
+ { parameters too. We also already have a }
+ { reference to the next parameter in }
+ { nextpara }
+ lenpara.right := nil;
+ end
+ else
+ begin
+ if not assigned(lenpara) then
+ lenpara := ccallparanode.create(
+ cordconstnode.create(int64(-32767),s32inttype,false),nil);
+ { also create a default fracpara if necessary }
+ if not assigned(fracpara) then
+ fracpara := ccallparanode.create(
+ cordconstnode.create(int64(-1),s32inttype,false),nil);
+ { add it to the lenpara }
+ lenpara.right := fracpara;
+ if not is_currency(para.left.resultdef) then
+ begin
+ { and add the realtype para (this also removes the link }
+ { to any parameters coming after it) }
+ fracpara.right := ccallparanode.create(
+ cordconstnode.create(ord(tfloatdef(para.left.resultdef).floattype),
+ s32inttype,true),nil);
+ end
+ else
+ fracpara.right:=nil;
+ end;
+ if para.left.resultdef.typ=enumdef then
+ begin
+ {To write(ln) an enum we need a some extra parameters.}
+ {Insert a reference to the ord2string index.}
+ indexpara:=Ccallparanode.create(
+ Caddrnode.create_internal(
+ Crttinode.create(Tenumdef(para.left.resultdef),fullrtti,rdt_normal)
+ ),
+ nil);
+ {Insert a reference to the typinfo.}
+ indexpara:=Ccallparanode.create(
+ Caddrnode.create_internal(
+ Crttinode.create(Tenumdef(para.left.resultdef),fullrtti,rdt_ord2str)
+ ),
+ indexpara);
+ {Insert a type conversion to to convert the enum to longint.}
+ para.left:=Ctypeconvnode.create_internal(para.left,s32inttype);
+ typecheckpass(para.left);
+ end;
+ end
+ else
+ begin
+ {To read(ln) an enum we need a an extra parameter.}
+ if para.left.resultdef.typ=enumdef then
+ begin
+ {Insert a reference to the string2ord index.}
+ indexpara:=Ccallparanode.create(Caddrnode.create_internal(
+ Crttinode.create(Tenumdef(para.left.resultdef),fullrtti,rdt_str2ord)
+ ),nil);
+ {Insert a type conversion to to convert the enum to longint.}
+ para.left:=Ctypeconvnode.create_internal(para.left,s32inttype);
+ typecheckpass(para.left);
+ end;
+ { special handling of reading small numbers, because the helpers }
+ { expect a longint/card/bestreal var parameter. Use a temp. can't }
+ { use functions because then the call to FPC_IOCHECK destroys }
+ { their result before we can store it }
+ if (readfunctype<>nil) and (para.left.resultdef<>readfunctype) then
+ special_handling:=true;
+ end;
+ if special_handling then
+ begin
+ { since we're not going to pass the parameter as var-parameter }
+ { to the read function, manually check whether the parameter }
+ { can be used as var-parameter (e.g., whether it isn't a }
+ { property) }
+ valid_for_var(para.left,true);
+
+ { create the parameter list: the temp ... }
+ temp := ctempcreatenode.create(readfunctype,readfunctype.size,tt_persistent,false);
+ addstatement(Tstatementnode(newstatement),temp);
+
+ { ... and the file }
+ p1 := ccallparanode.create(ctemprefnode.create(temp),
+ filepara.getcopy);
+ Tcallparanode(Tcallparanode(p1).right).right:=indexpara;
+
+ { create the call to the helper }
+ addstatement(Tstatementnode(newstatement),
+ ccallnode.createintern(name,tcallparanode(p1)));
+
+ { assign the result to the original var (this automatically }
+ { takes care of range checking) }
+ addstatement(Tstatementnode(newstatement),
+ cassignmentnode.create(para.left,
+ ctemprefnode.create(temp)));
+
+ { release the temp location }
+ addstatement(Tstatementnode(newstatement),ctempdeletenode.create(temp));
+
+ { statement of para is used }
+ para.left := nil;
+
+ { free the enclosing tcallparanode, but not the }
+ { parameters coming after it }
+ para.right := nil;
+ para.free;
+ end
+ else
+ { read of non s/u-8/16bit, or a write }
+ begin
+ { add the filepara to the current parameter }
+ para.right := filepara.getcopy;
+ {Add the lenpara and the indexpara(s) (fracpara and realtype are
+ already linked with the lenpara if necessary).}
+ if indexpara=nil then
+ Tcallparanode(para.right).right:=lenpara
+ else
+ begin
+ if lenpara=nil then
+ Tcallparanode(para.right).right:=indexpara
+ else
+ begin
+ Tcallparanode(para.right).right:=lenpara;
+ lenpara.right:=indexpara;
+ end;
+{ indexpara.right:=lenpara;}
+ end;
+ { in case of writing a chararray, add whether it's zero-based }
+ if para.left.resultdef.typ=arraydef then
+ para := ccallparanode.create(cordconstnode.create(
+ ord(tarraydef(para.left.resultdef).lowrange=0),pasbool8type,false),para)
+ else
+ { in case of reading an ansistring pass a codepage argument }
+ if do_read and is_ansistring(para.left.resultdef) then
+ para:=ccallparanode.create(cordconstnode.create(
+ getparaencoding(para.left.resultdef),u16inttype,true),para);
+ { create the call statement }
+ addstatement(Tstatementnode(newstatement),
+ ccallnode.createintern(name,para));
+ end
+ end
+ else
+ { error_para = true }
+ begin
+ { free the parameter, since it isn't referenced anywhere anymore }
+ para.right := nil;
+ para.free;
+ if assigned(lenpara) then
+ begin
+ lenpara.right := nil;
+ lenpara.free;
+ end;
+ if assigned(fracpara) then
+ begin
+ fracpara.right := nil;
+ fracpara.free;
+ end;
+ end;
+
+ { process next parameter }
+ para := nextpara;
+ end;
+
+ { if no error, add the write(ln)/read(ln) end calls }
+ if not found_error then
+ begin
+ case inlinenumber of
+ in_read_x,
+ in_readstr_x:
+ name:='fpc_read_end';
+ in_write_x,
+ in_writestr_x:
+ name:='fpc_write_end';
+ in_readln_x:
+ begin
+ name:='fpc_readln_end';
+ if m_iso in current_settings.modeswitches then
+ name:=name+'_iso';
+ end;
+ in_writeln_x:
+ name:='fpc_writeln_end';
+ end;
+ addstatement(Tstatementnode(newstatement),ccallnode.createintern(name,filepara));
+ end;
+ handle_text_read_write:=found_error;
+ end;
+
+ function Tinlinenode.handle_typed_read_write(filepara,params:Ttertiarynode;var newstatement:Tnode):boolean;
+
+ {Read/write for typed files.}
+
+ const procprefixes:array[boolean] of string[15]=('fpc_typed_write','fpc_typed_read');
+ procnamesdisplay:array[boolean,boolean] of string[8] = (('Write','Read'),('WriteStr','ReadStr'));
+
+ var found_error,do_read,is_rwstr:boolean;
+ para,nextpara:Tcallparanode;
+ p1:Tnode;
+ temp:Ttempcreatenode;
+ begin
+ found_error:=false;
+ para:=Tcallparanode(params);
+ do_read:=inlinenumber in [in_read_x,in_readln_x,in_readstr_x];
+ is_rwstr := inlinenumber in [in_readstr_x,in_writestr_x];
+ { add the typesize to the filepara }
+ if filepara.resultdef.typ=filedef then
+ filepara.right := ccallparanode.create(cordconstnode.create(
+ tfiledef(filepara.resultdef).typedfiledef.size,s32inttype,true),nil);
+
+ { check for "no parameters" (you need at least one extra para for typed files) }
+ if not assigned(para) then
+ begin
+ CGMessage1(parser_e_wrong_parameter_size,procnamesdisplay[is_rwstr,do_read]);
+ found_error := true;
+ end;
+
+ { process all parameters }
+ while assigned(para) do
+ begin
+ { check if valid parameter }
+ if para.left.nodetype=typen then
+ begin
+ CGMessagePos(para.left.fileinfo,type_e_cant_read_write_type);
+ found_error := true;
+ end;
+
+ { support writeln(procvar) }
+ if (para.left.resultdef.typ=procvardef) then
+ begin
+ p1:=ccallnode.create_procvar(nil,para.left);
+ typecheckpass(p1);
+ para.left:=p1;
+ end;
+
+ if filepara.resultdef.typ=filedef then
+ inserttypeconv(para.left,tfiledef(filepara.resultdef).typedfiledef);
+
+ if assigned(para.right) and
+ (cpf_is_colon_para in tcallparanode(para.right).callparaflags) then
+ begin
+ CGMessagePos(para.right.fileinfo,parser_e_illegal_colon_qualifier);
+
+ { skip all colon para's }
+ nextpara := tcallparanode(tcallparanode(para.right).right);
+ while assigned(nextpara) and (cpf_is_colon_para in nextpara.callparaflags) do
+ nextpara := tcallparanode(nextpara.right);
+ found_error := true;
+ end
+ else
+ { get next parameter }
+ nextpara := tcallparanode(para.right);
+
+ { When we have a call, we have a problem: you can't pass the }
+ { result of a call as a formal const parameter. Solution: }
+ { assign the result to a temp and pass this temp as parameter }
+ { This is not very efficient, but write(typedfile,x) is }
+ { already slow by itself anyway (no buffering) (JM) }
+ { Actually, thge same goes for every non-simple expression }
+ { (such as an addition, ...) -> put everything but load nodes }
+ { into temps (JM) }
+ { of course, this must only be allowed for writes!!! (JM) }
+ if not(do_read) and (para.left.nodetype <> loadn) then
+ begin
+ { create temp for result }
+ temp := ctempcreatenode.create(para.left.resultdef,
+ para.left.resultdef.size,tt_persistent,false);
+ addstatement(Tstatementnode(newstatement),temp);
+ { assign result to temp }
+ addstatement(Tstatementnode(newstatement),
+ cassignmentnode.create(ctemprefnode.create(temp),
+ para.left));
+ { replace (reused) paranode with temp }
+ para.left := ctemprefnode.create(temp);
+ end;
+ { add fileparameter }
+ para.right := filepara.getcopy;
+
+ { create call statment }
+ { since the parameters are in the correct order, we have to insert }
+ { the statements always at the end of the current block }
+ addstatement(Tstatementnode(newstatement),
+ Ccallnode.createintern(procprefixes[do_read],para
+ ));
+
+ { if we used a temp, free it }
+ if para.left.nodetype = temprefn then
+ addstatement(Tstatementnode(newstatement),ctempdeletenode.create(temp));
+
+ { process next parameter }
+ para := nextpara;
+ end;
+
+ { free the file parameter }
+ filepara.free;
+ handle_typed_read_write:=found_error;
+ end;
+
+ function tinlinenode.handle_read_write: tnode;
+
+ var
+ filepara,
+ nextpara,
+ params : tcallparanode;
+ newstatement : tstatementnode;
+ newblock : tblocknode;
+ filetemp : Ttempcreatenode;
+ name : string[31];
+ textsym : ttypesym;
+ is_typed,
+ do_read,
+ is_rwstr,
+ found_error : boolean;
+ begin
+ filepara := nil;
+ is_typed := false;
+ filetemp := nil;
+ do_read := inlinenumber in [in_read_x,in_readln_x,in_readstr_x];
+ is_rwstr := inlinenumber in [in_readstr_x,in_writestr_x];
+
+ { if we fail, we can quickly exit this way. We must generate something }
+ { instead of the inline node, because firstpass will bomb with an }
+ { internalerror if it encounters a read/write }
+ result := cerrornode.create;
+
+ { reverse the parameters (needed to get the colon parameters in the }
+ { correct order when processing write(ln) }
+ left := reverseparameters(tcallparanode(left));
+
+ if is_rwstr then
+ begin
+ filepara := tcallparanode(left);
+ { needs at least two parameters: source/dest string + min. 1 value }
+ if not(assigned(filepara)) or
+ not(assigned(filepara.right)) then
+ begin
+ CGMessagePos1(fileinfo,parser_e_wrong_parameter_size,'ReadStr/WriteStr');
+ exit;
+ end
+ else if (filepara.resultdef.typ <> stringdef) then
+ begin
+ { convert chararray to string, or give an appropriate error message }
+ { (if you want to optimize to use shortstring, keep in mind that }
+ { readstr internally always uses ansistring, and to account for }
+ { chararrays with > 255 characters) }
+ inserttypeconv(filepara.left,getansistringdef);
+ filepara.resultdef:=filepara.left.resultdef;
+ if codegenerror then
+ exit;
+ end
+ end
+ else if assigned(left) then
+ begin
+ { check if we have a file parameter and if yes, what kind it is }
+ filepara := tcallparanode(left);
+
+ if (filepara.resultdef.typ=filedef) then
+ begin
+ if (tfiledef(filepara.resultdef).filetyp=ft_untyped) then
+ begin
+ CGMessagePos(fileinfo,type_e_no_read_write_for_untyped_file);
+ exit;
+ end
+ else
+ begin
+ if (tfiledef(filepara.resultdef).filetyp=ft_typed) then
+ begin
+ if (inlinenumber in [in_readln_x,in_writeln_x]) then
+ begin
+ CGMessagePos(fileinfo,type_e_no_readln_writeln_for_typed_file);
+ exit;
+ end;
+ is_typed := true;
+ end
+ end;
+ end
+ else
+ filepara := nil;
+ end;
+
+ { create a blocknode in which the successive write/read statements will be }
+ { put, since they belong together. Also create a dummy statement already to }
+ { make inserting of additional statements easier }
+ newblock:=internalstatements(newstatement);
+
+ { if we don't have a filepara, create one containing the default }
+ if not assigned(filepara) or
+ is_rwstr then
+ begin
+ { since the input/output variables are threadvars loading them into
+ a temp once is faster. Create a temp which will hold a pointer to the file }
+ filetemp := ctempcreatenode.create(voidpointertype,voidpointertype.size,tt_persistent,true);
+ addstatement(newstatement,filetemp);
+
+ { make sure the resultdef of the temp (and as such of the }
+ { temprefs coming after it) is set (necessary because the }
+ { temprefs will be part of the filepara, of which we need }
+ { the resultdef later on and temprefs can only be }
+ { typecheckpassed if the resultdef of the temp is known) }
+ typecheckpass(tnode(filetemp));
+
+ if not is_rwstr then
+ begin
+ { assign the address of the file to the temp }
+ if do_read then
+ name := 'input'
+ else
+ name := 'output';
+ addstatement(newstatement,
+ cassignmentnode.create(ctemprefnode.create(filetemp),
+ ccallnode.createintern('fpc_get_'+name,nil)));
+ end
+ else
+ begin
+ if (do_read) then
+ name := 'fpc_setupreadstr_'
+ else
+ name := 'fpc_setupwritestr_';
+ name:=name+tstringdef(filepara.resultdef).stringtypname;
+ { remove the source/destination string parameter from the }
+ { parameter chain }
+ left:=filepara.right;
+ filepara.right:=nil;
+ { pass the source/destination string to the setup routine, which }
+ { will store the string's address in the returned textrec }
+ addstatement(newstatement,
+ cassignmentnode.create(ctemprefnode.create(filetemp),
+ ccallnode.createintern(name,filepara)));
+ end;
+
+ { create a new fileparameter as follows: file_type(temp^) }
+ { (so that we pass the value and not the address of the temp }
+ { to the read/write routine) }
+ textsym:=search_system_type('TEXT');
+ filepara := ccallparanode.create(ctypeconvnode.create_internal(
+ cderefnode.create(ctemprefnode.create(filetemp)),textsym.typedef),nil);
+ end
+ else
+ { remove filepara from the parameter chain }
+ begin
+ left := filepara.right;
+ filepara.right := nil;
+ { the file para is a var parameter, but it must be valid already }
+ set_varstate(filepara.left,vs_readwritten,[vsf_must_be_valid]);
+ { check if we should make a temp to store the result of a complex }
+ { expression (better heuristics, anyone?) (JM) }
+ if (filepara.left.nodetype <> loadn) then
+ begin
+ { create a temp which will hold a pointer to the file }
+ filetemp := ctempcreatenode.create(voidpointertype,voidpointertype.size,tt_persistent,true);
+
+ { add it to the statements }
+ addstatement(newstatement,filetemp);
+
+ { make sure the resultdef of the temp (and as such of the }
+ { temprefs coming after it) is set (necessary because the }
+ { temprefs will be part of the filepara, of which we need }
+ { the resultdef later on and temprefs can only be }
+ { typecheckpassed if the resultdef of the temp is known) }
+ typecheckpass(tnode(filetemp));
+
+ { assign the address of the file to the temp }
+ addstatement(newstatement,
+ cassignmentnode.create(ctemprefnode.create(filetemp),
+ caddrnode.create_internal(filepara.left)));
+ typecheckpass(newstatement.left);
+ { create a new fileparameter as follows: file_type(temp^) }
+ { (so that we pass the value and not the address of the temp }
+ { to the read/write routine) }
+ nextpara := ccallparanode.create(ctypeconvnode.create_internal(
+ cderefnode.create(ctemprefnode.create(filetemp)),filepara.left.resultdef),nil);
+
+ { replace the old file para with the new one }
+ filepara.left := nil;
+ filepara.free;
+ filepara := nextpara;
+ end;
+ end;
+
+ { the resultdef of the filepara must be set since it's }
+ { used below }
+ filepara.get_paratype;
+
+ { now, filepara is nowhere referenced anymore, so we can safely dispose it }
+ { if something goes wrong or at the end of the procedure }
+
+ { we're going to reuse the paranodes, so make sure they don't get freed }
+ { twice }
+ params:=Tcallparanode(left);
+ left := nil;
+
+ if is_typed then
+ found_error:=handle_typed_read_write(filepara,Ttertiarynode(params),tnode(newstatement))
+ else
+ found_error:=handle_text_read_write(filepara,Ttertiarynode(params),tnode(newstatement));
+
+ { if we found an error, simply delete the generated blocknode }
+ if found_error then
+ newblock.free
+ else
+ begin
+ { deallocate the temp for the file para if we used one }
+ if assigned(filetemp) then
+ addstatement(newstatement,ctempdeletenode.create(filetemp));
+ { otherwise return the newly generated block of instructions, }
+ { but first free the errornode we generated at the beginning }
+ result.free;
+ result := newblock
+ end;
+ end;
+
+
+ function tinlinenode.handle_val: tnode;
+ var
+ procname,
+ suffix : string[31];
+ sourcepara,
+ destpara,
+ codepara,
+ sizepara,
+ newparas : tcallparanode;
+ orgcode,tc : tnode;
+ newstatement : tstatementnode;
+ newblock : tblocknode;
+ tempcode : ttempcreatenode;
+ begin
+ { for easy exiting if something goes wrong }
+ result := cerrornode.create;
+
+ { check the amount of parameters }
+ if not(assigned(left)) or
+ not(assigned(tcallparanode(left).right)) then
+ begin
+ CGMessage1(parser_e_wrong_parameter_size,'Val');
+ exit;
+ end;
+
+ { in case we are in a generic definition, we cannot
+ do all checks, the parameters might be type parameters }
+ if df_generic in current_procinfo.procdef.defoptions then
+ begin
+ result.Free;
+ result:=nil;
+ resultdef:=voidtype;
+ exit;
+ end;
+
+ { reverse parameters for easier processing }
+ left := reverseparameters(tcallparanode(left));
+
+ { get the parameters }
+ tempcode := nil;
+ orgcode := nil;
+ sizepara := nil;
+ sourcepara := tcallparanode(left);
+ destpara := tcallparanode(sourcepara.right);
+ codepara := tcallparanode(destpara.right);
+
+ { check if codepara is valid }
+ if assigned(codepara) and
+ (
+ not is_integer(codepara.resultdef)
+{$ifndef cpu64bitaddr}
+ or is_64bitint(codepara.resultdef)
+{$endif not cpu64bitaddr}
+ ) then
+ begin
+ CGMessagePos1(codepara.fileinfo,type_e_integer_expr_expected,codepara.resultdef.typename);
+ exit;
+ end;
+
+ { check if dest para is valid }
+ if not is_integer(destpara.resultdef) and
+ not is_currency(destpara.resultdef) and
+ not(destpara.resultdef.typ in [floatdef,enumdef]) then
+ begin
+ CGMessagePos(destpara.fileinfo,type_e_integer_or_real_expr_expected);
+ exit;
+ end;
+
+ { we're going to reuse the exisiting para's, so make sure they }
+ { won't be disposed }
+ left := nil;
+
+ { create the blocknode which will hold the generated statements + }
+ { an initial dummy statement }
+
+ newblock:=internalstatements(newstatement);
+
+ { do we need a temp for code? Yes, if no code specified, or if }
+ { code is not a 32bit parameter (we already checked whether the }
+ { the code para, if specified, was an orddef) }
+ if not assigned(codepara) or
+ (codepara.resultdef.size<>sinttype.size) then
+ begin
+ tempcode := ctempcreatenode.create(sinttype,sinttype.size,tt_persistent,false);
+ addstatement(newstatement,tempcode);
+ { set the resultdef of the temp (needed to be able to get }
+ { the resultdef of the tempref used in the new code para) }
+ typecheckpass(tnode(tempcode));
+ { create a temp codepara, but save the original code para to }
+ { assign the result to later on }
+ if assigned(codepara) then
+ begin
+ orgcode := codepara.left;
+ codepara.left := ctemprefnode.create(tempcode);
+ end
+ else
+ codepara := ccallparanode.create(ctemprefnode.create(tempcode),nil);
+ { we need its resultdef later on }
+ codepara.get_paratype;
+ end
+ else if (torddef(codepara.resultdef).ordtype = torddef(sinttype).ordtype) then
+ { because code is a var parameter, it must match types exactly }
+ { however, since it will return values in [0..255], both longints }
+ { and cardinals are fine. Since the formal code para type is }
+ { longint, insert a typecoversion to longint for cardinal para's }
+ begin
+ codepara.left := ctypeconvnode.create_internal(codepara.left,sinttype);
+ { make it explicit, oterwise you may get a nonsense range }
+ { check error if the cardinal already contained a value }
+ { > $7fffffff }
+ codepara.get_paratype;
+ end;
+
+ { create the procedure name }
+ procname := 'fpc_val_';
+
+ case destpara.resultdef.typ of
+ orddef:
+ begin
+ case torddef(destpara.resultdef).ordtype of
+{$ifdef cpu64bitaddr}
+ s64bit,
+{$endif cpu64bitaddr}
+ s8bit,
+ s16bit,
+ s32bit:
+ begin
+ suffix := 'sint_';
+ { we also need a destsize para in this case }
+ sizepara := ccallparanode.create(cordconstnode.create
+ (destpara.resultdef.size,s32inttype,true),nil);
+ end;
+{$ifdef cpu64bitaddr}
+ u64bit,
+{$endif cpu64bitaddr}
+ u8bit,
+ u16bit,
+ u32bit:
+ suffix := 'uint_';
+{$ifndef cpu64bitaddr}
+ s64bit: suffix := 'int64_';
+ u64bit: suffix := 'qword_';
+{$endif not cpu64bitaddr}
+ scurrency: suffix := 'currency_';
+ else
+ internalerror(200304225);
+ end;
+ end;
+ floatdef:
+ suffix:='real_';
+ enumdef:
+ begin
+ suffix:='enum_';
+ sizepara:=Ccallparanode.create(Caddrnode.create_internal(
+ Crttinode.create(Tenumdef(destpara.resultdef),fullrtti,rdt_str2ord)
+ ),nil);
+ end;
+ end;
+
+ procname := procname + suffix;
+
+ { play a trick to have tcallnode handle invalid source parameters: }
+ { the shortstring-longint val routine by default }
+ if (sourcepara.resultdef.typ = stringdef) then
+ procname := procname + tstringdef(sourcepara.resultdef).stringtypname
+ { zero-based arrays (of char) can be implicitely converted to ansistring }
+ else if is_zero_based_array(sourcepara.resultdef) then
+ procname := procname + 'ansistr'
+ else
+ procname := procname + 'shortstr';
+
+ { set up the correct parameters for the call: the code para... }
+ newparas := codepara;
+ { and the source para }
+ codepara.right := sourcepara;
+ { sizepara either contains nil if none is needed (which is ok, since }
+ { then the next statement severes any possible links with other paras }
+ { that sourcepara may have) or it contains the necessary size para and }
+ { its right field is nil }
+ sourcepara.right := sizepara;
+
+ { create the call and assign the result to dest (val helpers are functions).
+ Use a trick to prevent a type size mismatch warning to be generated by the
+ assignment node. First convert implicitly to the resultdef. This will insert
+ the range check. The Second conversion is done explicitly to hide the implicit conversion
+ for the assignment node and therefor preventing the warning (PFV)
+
+ The implicit conversion is avoided for enums because implicit conversion between
+ longint (which is what fpc_val_enum_shortstr returns) and enumerations is not
+ possible. (DM).
+
+ The implicit conversion is also avoided for COMP type if it is handled by FPU (x86)
+ to prevent warning about automatic type conversion. }
+ if (destpara.resultdef.typ=enumdef) or
+ ((destpara.resultdef.typ=floatdef) and (tfloatdef(destpara.resultdef).floattype=s64comp))
+ then
+ tc:=ccallnode.createintern(procname,newparas)
+ else
+ tc:=ctypeconvnode.create(ccallnode.createintern(procname,newparas),destpara.left.resultdef);
+ addstatement(newstatement,cassignmentnode.create(
+ destpara.left,ctypeconvnode.create_internal(tc,destpara.left.resultdef)));
+
+ { dispose of the enclosing paranode of the destination }
+ destpara.left := nil;
+ destpara.right := nil;
+ destpara.free;
+
+ { check if we used a temp for code and whether we have to store }
+ { it to the real code parameter }
+ if assigned(orgcode) then
+ addstatement(newstatement,cassignmentnode.create(
+ orgcode,
+ ctypeconvnode.create_internal(
+ ctemprefnode.create(tempcode),orgcode.resultdef)));
+
+ { release the temp if we allocated one }
+ if assigned(tempcode) then
+ addstatement(newstatement,ctempdeletenode.create(tempcode));
+
+ { free the errornode }
+ result.free;
+ { and return it }
+ result := newblock;
+ end;
+
+{$maxfpuregisters 0}
+
+ function getpi : bestreal;
+ begin
+ {$ifdef x86}
+ { x86 has pi in hardware }
+ result:=pi;
+ {$else x86}
+ {$ifdef cpuextended}
+ result:=MathPiExtended.Value;
+ {$else cpuextended}
+ result:=MathPi.Value;
+ {$endif cpuextended}
+ {$endif x86}
+ end;
+
+
+ function tinlinenode.simplify(forinline : boolean): tnode;
+
+ function do_lowhigh(def:tdef) : tnode;
+ var
+ v : tconstexprint;
+ enum : tenumsym;
+ hp : tnode;
+ i : integer;
+ begin
+ case def.typ of
+ orddef:
+ begin
+ set_varstate(left,vs_read,[]);
+ if inlinenumber=in_low_x then
+ v:=torddef(def).low
+ else
+ v:=torddef(def).high;
+ hp:=cordconstnode.create(v,def,true);
+ typecheckpass(hp);
+ do_lowhigh:=hp;
+ end;
+ enumdef:
+ begin
+ set_varstate(left,vs_read,[]);
+ if inlinenumber=in_high_x then
+ v:=tenumdef(def).maxval
+ else
+ v:=tenumdef(def).minval;
+ enum:=nil;
+ for i := 0 to tenumdef(def).symtable.SymList.Count - 1 do
+ if tenumsym(tenumdef(def).symtable.SymList[i]).value=v then
+ begin
+ enum:=tenumsym(tenumdef(def).symtable.SymList[i]);
+ break;
+ end;
+ if not assigned(enum) then
+ internalerror(309993)
+ else
+ hp:=genenumnode(enum);
+ do_lowhigh:=hp;
+ end;
+ else
+ internalerror(87);
+ end;
+ end;
+
+
+ function getconstrealvalue : bestreal;
+ begin
+ case left.nodetype of
+ ordconstn:
+ getconstrealvalue:=tordconstnode(left).value;
+ realconstn:
+ getconstrealvalue:=trealconstnode(left).value_real;
+ else
+ internalerror(309992);
+ end;
+ end;
+
+
+ procedure setconstrealvalue(r : bestreal);
+ begin
+ result:=crealconstnode.create(r,pbestrealtype^);
+ end;
+
+
+ function handle_ln_const(r : bestreal) : tnode;
+ begin
+ if r<=0.0 then
+ if floating_point_range_check_error then
+ begin
+ result:=crealconstnode.create(0,pbestrealtype^);
+ CGMessage(type_e_wrong_math_argument)
+ end
+ else
+ begin
+ if r=0.0 then
+ result:=crealconstnode.create(MathQNaN.Value,pbestrealtype^)
+ else
+ result:=crealconstnode.create(MathNegInf.Value,pbestrealtype^)
+ end
+ else
+ result:=crealconstnode.create(ln(r),pbestrealtype^)
+ end;
+
+
+ function handle_sqrt_const(r : bestreal) : tnode;
+ begin
+ if r<0.0 then
+ if floating_point_range_check_error then
+ begin
+ result:=crealconstnode.create(0,pbestrealtype^);
+ CGMessage(type_e_wrong_math_argument)
+ end
+ else
+ result:=crealconstnode.create(MathQNaN.Value,pbestrealtype^)
+ else
+ result:=crealconstnode.create(sqrt(r),pbestrealtype^)
+ end;
+
+
+ function handle_const_sar : tnode;
+ var
+ vl,vl2 : TConstExprInt;
+ bits,shift: integer;
+ mask : qword;
+ def : tdef;
+ begin
+ result:=nil;
+ if (left.nodetype=ordconstn) or ((left.nodetype=callparan) and (tcallparanode(left).left.nodetype=ordconstn)) then
+ begin
+ if (left.nodetype=callparan) and
+ assigned(tcallparanode(left).right) then
+ begin
+ if (tcallparanode(tcallparanode(left).right).left.nodetype=ordconstn) then
+ begin
+ def:=tcallparanode(tcallparanode(left).right).left.resultdef;
+ vl:=tordconstnode(tcallparanode(left).left).value;
+ vl2:=tordconstnode(tcallparanode(tcallparanode(left).right).left).value;
+ end
+ else
+ exit;
+ end
+ else
+ begin
+ def:=left.resultdef;
+ vl:=1;
+ vl2:=tordconstnode(left).value;
+ end;
+
+ bits:=def.size*8;
+ shift:=vl.svalue and (bits-1);
+ case bits of
+ 8:
+ mask:=$ff;
+ 16:
+ mask:=$ffff;
+ 32:
+ mask:=$ffffffff;
+ 64:
+ mask:=qword($ffffffffffffffff);
+ else
+ mask:=qword(1 shl bits)-1;
+ end;
+{$push}
+{$r-,q-}
+ if shift=0 then
+ result:=cordconstnode.create(vl2.svalue,def,false)
+ else if vl2.svalue<0 then
+ result:=cordconstnode.create(((vl2.svalue shr shift) or (mask shl (bits-shift))) and mask,def,false)
+ else
+ result:=cordconstnode.create((vl2.svalue shr shift) and mask,def,false);
+{$pop}
+ end
+ else
+ end;
+
+
+ function handle_const_rox : tnode;
+ var
+ vl,vl2 : TConstExprInt;
+ bits,shift: integer;
+ def : tdef;
+ begin
+ result:=nil;
+ if (left.nodetype=ordconstn) or ((left.nodetype=callparan) and (tcallparanode(left).left.nodetype=ordconstn)) then
+ begin
+ if (left.nodetype=callparan) and
+ assigned(tcallparanode(left).right) then
+ begin
+ if (tcallparanode(tcallparanode(left).right).left.nodetype=ordconstn) then
+ begin
+ def:=tcallparanode(tcallparanode(left).right).left.resultdef;
+ vl:=tordconstnode(tcallparanode(left).left).value;
+ vl2:=tordconstnode(tcallparanode(tcallparanode(left).right).left).value;
+ end
+ else
+ exit;
+ end
+ else
+ begin
+ def:=left.resultdef;
+ vl:=1;
+ vl2:=tordconstnode(left).value;
+ end;
+
+ bits:=def.size*8;
+ shift:=vl.svalue and (bits-1);
+{$push}
+{$r-,q-}
+ if shift=0 then
+ result:=cordconstnode.create(vl2.svalue,def,false)
+ else
+ case inlinenumber of
+ in_ror_x,in_ror_x_y:
+ case def.size of
+ 1:
+ result:=cordconstnode.create(RorByte(Byte(vl2.svalue),shift),def,false);
+ 2:
+ result:=cordconstnode.create(RorWord(Word(vl2.svalue),shift),def,false);
+ 4:
+ result:=cordconstnode.create(RorDWord(DWord(vl2.svalue),shift),def,false);
+ 8:
+ result:=cordconstnode.create(RorQWord(QWord(vl2.svalue),shift),def,false);
+ else
+ internalerror(2011061903);
+ end;
+ in_rol_x,in_rol_x_y:
+ case def.size of
+ 1:
+ result:=cordconstnode.create(RolByte(Byte(vl2.svalue),shift),def,false);
+ 2:
+ result:=cordconstnode.create(RolWord(Word(vl2.svalue),shift),def,false);
+ 4:
+ result:=cordconstnode.create(RolDWord(DWord(vl2.svalue),shift),def,false);
+ 8:
+ result:=cordconstnode.create(RolQWord(QWord(vl2.svalue),shift),def,false);
+ else
+ internalerror(2011061902);
+ end;
+ else
+ internalerror(2011061901);
+ end;
+ end;
+ end;
+
+ var
+ hp : tnode;
+ vl,vl2 : TConstExprInt;
+ vr : bestreal;
+
+ begin { simplify }
+ result:=nil;
+ { handle intern constant functions in separate case }
+ if nf_inlineconst in flags then
+ begin
+ { no parameters? }
+ if not assigned(left) then
+ internalerror(200501231)
+ else
+ begin
+ vl:=0;
+ vl2:=0; { second parameter Ex: ptr(vl,vl2) }
+ case left.nodetype of
+ realconstn :
+ begin
+ { Real functions are all handled with internproc below }
+ CGMessage1(type_e_integer_expr_expected,left.resultdef.typename)
+ end;
+ ordconstn :
+ vl:=tordconstnode(left).value;
+ callparan :
+ begin
+ { both exists, else it was not generated }
+ vl:=tordconstnode(tcallparanode(left).left).value;
+ vl2:=tordconstnode(tcallparanode(tcallparanode(left).right).left).value;
+ end;
+ else
+ CGMessage(parser_e_illegal_expression);
+ end;
+ case inlinenumber of
+ in_const_abs :
+ if vl.signed then
+ hp:=create_simplified_ord_const(abs(vl.svalue),resultdef,forinline)
+ else
+ hp:=create_simplified_ord_const(vl.uvalue,resultdef,forinline);
+ in_const_sqr:
+ if vl.signed then
+ hp:=create_simplified_ord_const(sqr(vl.svalue),resultdef,forinline)
+ else
+ hp:=create_simplified_ord_const(sqr(vl.uvalue),resultdef,forinline);
+ in_const_odd :
+ hp:=cordconstnode.create(qword(odd(int64(vl))),pasbool8type,true);
+ in_const_swap_word :
+ hp:=cordconstnode.create((vl and $ff) shl 8+(vl shr 8),left.resultdef,true);
+ in_const_swap_long :
+ hp:=cordconstnode.create((vl and $ffff) shl 16+(vl shr 16),left.resultdef,true);
+ in_const_swap_qword :
+ hp:=cordconstnode.create((vl and $ffff) shl 32+(vl shr 32),left.resultdef,true);
+ in_const_ptr:
+ begin
+ {Don't construct pointers from negative values.}
+ if (vl.signed and (vl.svalue<0)) or (vl2.signed and (vl2.svalue<0)) then
+ cgmessage(parser_e_range_check_error);
+ hp:=cpointerconstnode.create((vl2.uvalue shl 4)+vl.uvalue,voidfarpointertype);
+ end
+ else
+ internalerror(88);
+ end;
+ end;
+ if hp=nil then
+ hp:=cerrornode.create;
+ result:=hp;
+ end
+ else
+ begin
+ case inlinenumber of
+ in_lo_long,
+ in_hi_long,
+ in_lo_qword,
+ in_hi_qword,
+ in_lo_word,
+ in_hi_word :
+ begin
+ if left.nodetype=ordconstn then
+ begin
+ case inlinenumber of
+ in_lo_word :
+ result:=cordconstnode.create(tordconstnode(left).value and $ff,u8inttype,true);
+ in_hi_word :
+ result:=cordconstnode.create(tordconstnode(left).value shr 8,u8inttype,true);
+ in_lo_long :
+ result:=cordconstnode.create(tordconstnode(left).value and $ffff,u16inttype,true);
+ in_hi_long :
+ result:=cordconstnode.create(tordconstnode(left).value shr 16,u16inttype,true);
+ in_lo_qword :
+ result:=cordconstnode.create(tordconstnode(left).value and $ffffffff,u32inttype,true);
+ in_hi_qword :
+ result:=cordconstnode.create(tordconstnode(left).value shr 32,u32inttype,true);
+ end;
+ end;
+ end;
+ in_ord_x:
+ begin
+ case left.resultdef.typ of
+ orddef :
+ begin
+ case torddef(left.resultdef).ordtype of
+ pasbool8,
+ uchar:
+ begin
+ { change to byte() }
+ result:=ctypeconvnode.create_internal(left,u8inttype);
+ left:=nil;
+ end;
+ pasbool16,
+ uwidechar :
+ begin
+ { change to word() }
+ result:=ctypeconvnode.create_internal(left,u16inttype);
+ left:=nil;
+ end;
+ pasbool32 :
+ begin
+ { change to dword() }
+ result:=ctypeconvnode.create_internal(left,u32inttype);
+ left:=nil;
+ end;
+ pasbool64 :
+ begin
+ { change to qword() }
+ result:=ctypeconvnode.create_internal(left,u64inttype);
+ left:=nil;
+ end;
+ bool8bit:
+ begin
+ { change to shortint() }
+ result:=ctypeconvnode.create_internal(left,s8inttype);
+ left:=nil;
+ end;
+ bool16bit :
+ begin
+ { change to smallint() }
+ result:=ctypeconvnode.create_internal(left,s16inttype);
+ left:=nil;
+ end;
+ bool32bit :
+ begin
+ { change to longint() }
+ result:=ctypeconvnode.create_internal(left,s32inttype);
+ left:=nil;
+ end;
+ bool64bit :
+ begin
+ { change to int64() }
+ result:=ctypeconvnode.create_internal(left,s64inttype);
+ left:=nil;
+ end;
+ uvoid :
+ CGMessage1(type_e_ordinal_expr_expected,left.resultdef.typename);
+ else
+ begin
+ { all other orddef need no transformation }
+ result:=left;
+ left:=nil;
+ end;
+ end;
+ end;
+ enumdef :
+ begin
+ result:=ctypeconvnode.create_internal(left,s32inttype);
+ left:=nil;
+ end;
+ pointerdef :
+ begin
+ if m_mac in current_settings.modeswitches then
+ begin
+ result:=ctypeconvnode.create_internal(left,ptruinttype);
+ left:=nil;
+ end
+ end;
+ end;
+(*
+ if (left.nodetype=ordconstn) then
+ begin
+ result:=cordconstnode.create(
+ tordconstnode(left).value,sinttype,true);
+ end
+ else if (m_mac in current_settings.modeswitches) and
+ (left.ndoetype=pointerconstn) then
+ result:=cordconstnode.create(
+ tpointerconstnode(left).value,ptruinttype,true);
+*)
+ end;
+ in_chr_byte:
+ begin
+ { convert to explicit char() }
+ result:=ctypeconvnode.create_internal(left,cchartype);
+ left:=nil;
+ end;
+ in_length_x:
+ begin
+ case left.resultdef.typ of
+ stringdef :
+ begin
+ if (left.nodetype=stringconstn) then
+ begin
+ result:=cordconstnode.create(
+ tstringconstnode(left).len,sinttype,true);
+ end;
+ end;
+ orddef :
+ begin
+ { length of char is always one }
+ if is_char(left.resultdef) or
+ is_widechar(left.resultdef) then
+ begin
+ result:=cordconstnode.create(1,sinttype,false);
+ end
+ end;
+ arraydef :
+ begin
+ if (left.nodetype=stringconstn) then
+ begin
+ result:=cordconstnode.create(
+ tstringconstnode(left).len,sinttype,true);
+ end
+ else if not is_open_array(left.resultdef) and
+ not is_array_of_const(left.resultdef) and
+ not is_dynamic_array(left.resultdef) then
+ result:=cordconstnode.create(tarraydef(left.resultdef).highrange-
+ tarraydef(left.resultdef).lowrange+1,
+ sinttype,true);
+ end;
+ end;
+ end;
+ in_assigned_x:
+ begin
+ if is_constnode(tcallparanode(left).left) or
+ (tcallparanode(left).left.nodetype = pointerconstn) then
+ begin
+ { let an add node figure it out }
+ result:=caddnode.create(unequaln,tcallparanode(left).left,cnilnode.create);
+ tcallparanode(left).left := nil;
+ end;
+ end;
+ in_pred_x,
+ in_succ_x:
+ begin
+ if (left.nodetype=ordconstn) then
+ begin
+ if (inlinenumber=in_succ_x) then
+ vl:=tordconstnode(left).value+1
+ else
+ vl:=tordconstnode(left).value-1;
+ if is_integer(left.resultdef) then
+ { the type of the original integer constant is irrelevant,
+ it should be automatically adapted to the new value
+ (except when inlining) }
+ result:=create_simplified_ord_const(vl,resultdef,forinline)
+ else
+ { check the range for enums, chars, booleans }
+ result:=cordconstnode.create(vl,left.resultdef,true)
+ end
+ end;
+ in_low_x,
+ in_high_x:
+ begin
+ case left.resultdef.typ of
+ orddef,
+ enumdef:
+ begin
+ result:=do_lowhigh(left.resultdef);
+ end;
+ setdef:
+ begin
+ result:=do_lowhigh(tsetdef(left.resultdef).elementdef);
+ end;
+ arraydef:
+ begin
+ if (inlinenumber=in_low_x) then
+ begin
+ result:=cordconstnode.create(int64(tarraydef(
+ left.resultdef).lowrange),tarraydef(left.resultdef).rangedef,true);
+ end
+ else if not is_open_array(left.resultdef) and
+ not is_array_of_const(left.resultdef) and
+ not is_dynamic_array(left.resultdef) then
+ result:=cordconstnode.create(int64(tarraydef(left.resultdef).highrange),
+ tarraydef(left.resultdef).rangedef,true);
+ end;
+ stringdef:
+ begin
+ if inlinenumber=in_low_x then
+ begin
+ result:=cordconstnode.create(0,u8inttype,false);
+ end
+ else if not is_ansistring(left.resultdef) and
+ not is_wide_or_unicode_string(left.resultdef) then
+ result:=cordconstnode.create(tstringdef(left.resultdef).len,u8inttype,true)
+ end;
+ end;
+ end;
+ in_exp_real :
+ begin
+ if left.nodetype in [ordconstn,realconstn] then
+ begin
+ result:=crealconstnode.create(exp(getconstrealvalue),pbestrealtype^);
+ if (trealconstnode(result).value_real=MathInf.Value) and
+ floating_point_range_check_error then
+ begin
+ result:=crealconstnode.create(0,pbestrealtype^);
+ CGMessage(parser_e_range_check_error);
+ end;
+ end
+ end;
+ in_trunc_real :
+ begin
+ if left.nodetype in [ordconstn,realconstn] then
+ begin
+ vr:=getconstrealvalue;
+ if (vr>=9223372036854775807.5) or (vr<=-9223372036854775808.5) then
+ begin
+ CGMessage(parser_e_range_check_error);
+ result:=cordconstnode.create(1,s64inttype,false)
+ end
+ else
+ result:=cordconstnode.create(trunc(vr),s64inttype,true)
+ end
+ end;
+ in_round_real :
+ begin
+ { can't evaluate while inlining, may depend on fpu setting }
+ if (not forinline) and
+ (left.nodetype in [ordconstn,realconstn]) then
+ begin
+ vr:=getconstrealvalue;
+ if (vr>=9223372036854775807.5) or (vr<=-9223372036854775808.5) then
+ begin
+ CGMessage(parser_e_range_check_error);
+ result:=cordconstnode.create(1,s64inttype,false)
+ end
+ else
+ result:=cordconstnode.create(round(vr),s64inttype,true)
+ end
+ end;
+ in_frac_real :
+ begin
+ if left.nodetype in [ordconstn,realconstn] then
+ setconstrealvalue(frac(getconstrealvalue))
+ end;
+ in_int_real :
+ begin
+ if left.nodetype in [ordconstn,realconstn] then
+ setconstrealvalue(int(getconstrealvalue));
+ end;
+ in_pi_real :
+ begin
+ if block_type=bt_const then
+ setconstrealvalue(getpi)
+ end;
+ in_cos_real :
+ begin
+ if left.nodetype in [ordconstn,realconstn] then
+ setconstrealvalue(cos(getconstrealvalue))
+ end;
+ in_sin_real :
+ begin
+ if left.nodetype in [ordconstn,realconstn] then
+ setconstrealvalue(sin(getconstrealvalue))
+ end;
+ in_arctan_real :
+ begin
+ if left.nodetype in [ordconstn,realconstn] then
+ setconstrealvalue(arctan(getconstrealvalue))
+ end;
+ in_abs_real :
+ begin
+ if left.nodetype in [ordconstn,realconstn] then
+ setconstrealvalue(abs(getconstrealvalue))
+ end;
+ in_abs_long:
+ begin
+ if left.nodetype=ordconstn then
+ begin
+ if tordconstnode(left).value<0 then
+ result:=cordconstnode.create((-tordconstnode(left).value),s32inttype,false)
+ else
+ result:=cordconstnode.create((tordconstnode(left).value),s32inttype,false);
+ end
+ end;
+ in_sqr_real :
+ begin
+ if left.nodetype in [ordconstn,realconstn] then
+ setconstrealvalue(sqr(getconstrealvalue))
+ end;
+ in_sqrt_real :
+ begin
+ if left.nodetype in [ordconstn,realconstn] then
+ begin
+ vr:=getconstrealvalue;
+ if vr<0.0 then
+ result:=handle_sqrt_const(vr)
+ else
+ setconstrealvalue(sqrt(vr));
+ end
+ end;
+ in_ln_real :
+ begin
+ if left.nodetype in [ordconstn,realconstn] then
+ begin
+ vr:=getconstrealvalue;
+ if vr<=0.0 then
+ result:=handle_ln_const(vr)
+ else
+ setconstrealvalue(ln(vr));
+ end
+ end;
+ in_assert_x_y :
+ begin
+ if not(cs_do_assertion in current_settings.localswitches) then
+ { we need a valid node, so insert a nothingn }
+ result:=cnothingnode.create;
+ end;
+ in_sar_x,
+ in_sar_x_y :
+ begin
+ result:=handle_const_sar;
+ end;
+ in_rol_x,
+ in_rol_x_y,
+ in_ror_x,
+ in_ror_x_y :
+ result:=handle_const_rox;
+ end;
+ end;
+ end;
+
+
+
+ function tinlinenode.pass_typecheck:tnode;
+
+ procedure setfloatresultdef;
+ begin
+ if (left.resultdef.typ=floatdef) and
+ (tfloatdef(left.resultdef).floattype in [s32real,s64real,s80real,sc80real,s128real]) then
+ resultdef:=left.resultdef
+ else
+ begin
+ if (left.nodetype <> ordconstn) then
+ inserttypeconv(left,pbestrealtype^);
+ resultdef:=pbestrealtype^;
+ end;
+ end;
+
+
+ procedure handle_pack_unpack;
+ var
+ source, target, index: tcallparanode;
+ unpackedarraydef, packedarraydef: tarraydef;
+ tempindex: TConstExprInt;
+ begin
+ resultdef:=voidtype;
+
+ unpackedarraydef := nil;
+ packedarraydef := nil;
+ source := tcallparanode(left);
+ if (inlinenumber = in_unpack_x_y_z) then
+ begin
+ target := tcallparanode(source.right);
+ index := tcallparanode(target.right);
+
+ { source must be a packed array }
+ if not is_packed_array(source.left.resultdef) then
+ CGMessagePos2(source.left.fileinfo,type_e_got_expected_packed_array,'1',source.left.resultdef.typename)
+ else
+ packedarraydef := tarraydef(source.left.resultdef);
+ { target can be any kind of array, as long as it's not packed }
+ if (target.left.resultdef.typ <> arraydef) or
+ is_packed_array(target.left.resultdef) then
+ CGMessagePos2(target.left.fileinfo,type_e_got_expected_unpacked_array,'2',target.left.resultdef.typename)
+ else
+ unpackedarraydef := tarraydef(target.left.resultdef);
+ end
+ else
+ begin
+ index := tcallparanode(source.right);
+ target := tcallparanode(index.right);
+
+ { source can be any kind of array, as long as it's not packed }
+ if (source.left.resultdef.typ <> arraydef) or
+ is_packed_array(source.left.resultdef) then
+ CGMessagePos2(source.left.fileinfo,type_e_got_expected_unpacked_array,'1',source.left.resultdef.typename)
+ else
+ unpackedarraydef := tarraydef(source.left.resultdef);
+ { target must be a packed array }
+ if not is_packed_array(target.left.resultdef) then
+ CGMessagePos2(target.left.fileinfo,type_e_got_expected_packed_array,'3',target.left.resultdef.typename)
+ else
+ packedarraydef := tarraydef(target.left.resultdef);
+ end;
+
+ if assigned(unpackedarraydef) then
+ begin
+ { index must be compatible with the unpacked array's indextype }
+ inserttypeconv(index.left,unpackedarraydef.rangedef);
+
+ { range check at compile time if possible }
+ if assigned(packedarraydef) and
+ (index.left.nodetype = ordconstn) and
+ not is_special_array(unpackedarraydef) then
+ begin
+ testrange(unpackedarraydef,tordconstnode(index.left).value,false,false);
+ tempindex := tordconstnode(index.left).value + packedarraydef.highrange-packedarraydef.lowrange;
+ testrange(unpackedarraydef,tempindex,false,false);
+ end;
+ end;
+
+ { source array is read and must be valid }
+ set_varstate(source.left,vs_read,[vsf_must_be_valid]);
+ { target array is written }
+ valid_for_assignment(target.left,true);
+ set_varstate(target.left,vs_written,[]);
+ { index in the unpacked array is read and must be valid }
+ set_varstate(index.left,vs_read,[vsf_must_be_valid]);
+ { if the size of the arrays is 0 (array of empty records), }
+ { do nothing }
+ if (source.resultdef.size = 0) then
+ result:=cnothingnode.create;
+ end;
+
+
+ function handle_objc_encode: tnode;
+ var
+ encodedtype: ansistring;
+ errordef: tdef;
+ begin
+ encodedtype:='';
+ if not objctryencodetype(left.resultdef,encodedtype,errordef) then
+ Message1(type_e_objc_type_unsupported,errordef.typename);
+ result:=cstringconstnode.createpchar(ansistring2pchar(encodedtype),length(encodedtype));
+ end;
+
+
+ var
+ hightree,
+ hp : tnode;
+ begin
+ result:=nil;
+ { when handling writeln "left" contains no valid address }
+ if assigned(left) then
+ begin
+ if left.nodetype=callparan then
+ tcallparanode(left).get_paratype
+ else
+ typecheckpass(left);
+ end;
+
+ if not(nf_inlineconst in flags) then
+ begin
+ case inlinenumber of
+ in_lo_long,
+ in_hi_long,
+ in_lo_qword,
+ in_hi_qword,
+ in_lo_word,
+ in_hi_word :
+ begin
+ { give warning for incompatibility with tp and delphi }
+ if (inlinenumber in [in_lo_long,in_hi_long,in_lo_qword,in_hi_qword]) and
+ ((m_tp7 in current_settings.modeswitches) or
+ (m_delphi in current_settings.modeswitches)) then
+ CGMessage(type_w_maybe_wrong_hi_lo);
+ set_varstate(left,vs_read,[vsf_must_be_valid]);
+ if not is_integer(left.resultdef) then
+ CGMessage1(type_e_integer_expr_expected,left.resultdef.typename);
+ case inlinenumber of
+ in_lo_word,
+ in_hi_word :
+ resultdef:=u8inttype;
+ in_lo_long,
+ in_hi_long :
+ resultdef:=u16inttype;
+ in_lo_qword,
+ in_hi_qword :
+ resultdef:=u32inttype;
+ end;
+ end;
+
+ in_sizeof_x:
+ begin
+ { the constant evaluation of in_sizeof_x happens in pexpr where possible }
+ set_varstate(left,vs_read,[]);
+ if paramanager.push_high_param(vs_value,left.resultdef,current_procinfo.procdef.proccalloption) then
+ begin
+ hightree:=load_high_value_node(tparavarsym(tloadnode(left).symtableentry));
+ if assigned(hightree) then
+ begin
+ hp:=caddnode.create(addn,hightree,
+ cordconstnode.create(1,sinttype,false));
+ if (left.resultdef.typ=arraydef) then
+ if not is_packed_array(tarraydef(left.resultdef)) then
+ begin
+ if (tarraydef(left.resultdef).elesize<>1) then
+ hp:=caddnode.create(muln,hp,cordconstnode.create(tarraydef(
+ left.resultdef).elesize,sinttype,true));
+ end
+ else if (tarraydef(left.resultdef).elepackedbitsize <> 8) then
+ begin
+ { no packed open array support yet }
+ if (hp.nodetype <> ordconstn) then
+ internalerror(2006081511);
+ hp.free;
+ hp := cordconstnode.create(left.resultdef.size,sinttype,true);
+{
+ hp:=
+ ctypeconvnode.create_explicit(sinttype,
+ cmoddivnode.create(divn,
+ caddnode.create(addn,
+ caddnode.create(muln,hp,cordconstnode.create(tarraydef(
+ left.resultdef).elepackedbitsize,s64inttype,true)),
+ cordconstnode.create(a,s64inttype,true)),
+ cordconstnode.create(8,s64inttype,true)),
+ sinttype);
+}
+ end;
+ result:=hp;
+ end;
+ end
+ else
+ resultdef:=sinttype;
+ end;
+
+ in_typeof_x:
+ begin
+ set_varstate(left,vs_read,[]);
+ resultdef:=voidpointertype;
+ end;
+
+ in_ord_x:
+ begin
+ set_varstate(left,vs_read,[vsf_must_be_valid]);
+ case left.resultdef.typ of
+ orddef,
+ enumdef :
+ ;
+ pointerdef :
+ begin
+ if not(m_mac in current_settings.modeswitches) then
+ CGMessage1(type_e_ordinal_expr_expected,left.resultdef.typename);
+ end
+ else
+ CGMessage1(type_e_ordinal_expr_expected,left.resultdef.typename);
+ end;
+ end;
+
+ in_chr_byte:
+ begin
+ set_varstate(left,vs_read,[vsf_must_be_valid]);
+ end;
+
+ in_length_x:
+ begin
+ if ((left.resultdef.typ=arraydef) and
+ (not is_special_array(left.resultdef) or
+ is_open_array(left.resultdef))) or
+ (left.resultdef.typ=orddef) then
+ set_varstate(left,vs_read,[])
+ else
+ set_varstate(left,vs_read,[vsf_must_be_valid]);
+
+ case left.resultdef.typ of
+ variantdef:
+ begin
+ inserttypeconv(left,getansistringdef);
+ end;
+
+ stringdef :
+ begin
+ { we don't need string convertions here, }
+ { except if from widestring to ansistring }
+ { and vice versa (that can change the }
+ { length) }
+ if (left.nodetype=typeconvn) and
+ (ttypeconvnode(left).left.resultdef.typ=stringdef) and
+ not(is_wide_or_unicode_string(left.resultdef) xor
+ is_wide_or_unicode_string(ttypeconvnode(left).left.resultdef)) then
+ begin
+ hp:=ttypeconvnode(left).left;
+ ttypeconvnode(left).left:=nil;
+ left.free;
+ left:=hp;
+ end;
+ end;
+ orddef :
+ begin
+ { will be handled in simplify }
+ if not is_char(left.resultdef) and
+ not is_widechar(left.resultdef) then
+ CGMessage(type_e_mismatch);
+ end;
+ pointerdef :
+ begin
+ if is_pchar(left.resultdef) then
+ begin
+ hp := ccallparanode.create(left,nil);
+ result := ccallnode.createintern('fpc_pchar_length',hp);
+ { make sure the left node doesn't get disposed, since it's }
+ { reused in the new node (JM) }
+ left:=nil;
+ exit;
+ end
+ else if is_pwidechar(left.resultdef) then
+ begin
+ hp := ccallparanode.create(left,nil);
+ result := ccallnode.createintern('fpc_pwidechar_length',hp);
+ { make sure the left node doesn't get disposed, since it's }
+ { reused in the new node (JM) }
+ left:=nil;
+ exit;
+ end
+ else
+ CGMessage(type_e_mismatch);
+ end;
+ arraydef :
+ begin
+ if is_open_array(left.resultdef) or
+ is_array_of_const(left.resultdef) then
+ begin
+ hightree:=load_high_value_node(tparavarsym(tloadnode(left).symtableentry));
+ if assigned(hightree) then
+ result:=caddnode.create(addn,hightree,
+ cordconstnode.create(1,sinttype,false));
+ exit;
+ end
+ else if is_dynamic_array(left.resultdef) then
+ begin
+ hp := ccallparanode.create(ctypeconvnode.create_internal(left,voidpointertype),nil);
+ result := ccallnode.createintern('fpc_dynarray_length',hp);
+ { make sure the left node doesn't get disposed, since it's }
+ { reused in the new node (JM) }
+ left:=nil;
+ exit;
+ end
+ else
+ begin
+ { will be handled in simplify }
+ end;
+ end
+ else
+ CGMessage(type_e_mismatch);
+ end;
+
+ { shortstring return an 8 bit value as the length
+ is the first byte of the string }
+ if is_shortstring(left.resultdef) then
+ resultdef:=u8inttype
+ else
+ resultdef:=sinttype;
+ end;
+
+ in_typeinfo_x:
+ begin
+ if (left.resultdef.typ=enumdef) and
+ (tenumdef(left.resultdef).has_jumps) then
+ CGMessage(type_e_no_type_info);
+ set_varstate(left,vs_read,[vsf_must_be_valid]);
+ resultdef:=voidpointertype;
+ end;
+
+ in_assigned_x:
+ begin
+ { the parser has already made sure the expression is valid }
+
+ { in case of a complex procvar, only check the "code" pointer }
+ if (tcallparanode(left).left.resultdef.typ=procvardef) and
+ not tprocvardef(tcallparanode(left).left.resultdef).is_addressonly then
+ begin
+ inserttypeconv_explicit(tcallparanode(left).left,search_system_type('TMETHOD').typedef);
+ tcallparanode(left).left:=csubscriptnode.create(tsym(tabstractrecorddef(tcallparanode(left).left.resultdef).symtable.find('CODE')),tcallparanode(left).left);
+ tcallparanode(left).get_paratype;
+ end;
+
+ { converting to an add node is tricky because of differences
+ in procvar handling between FPC and Delphi handling, so
+ handle specially }
+ set_varstate(tcallparanode(left).left,vs_read,[vsf_must_be_valid]);
+ resultdef:=pasbool8type;
+ end;
+
+ in_ofs_x :
+ internalerror(2000101001);
+
+ in_seg_x :
+ begin
+ set_varstate(left,vs_read,[]);
+ result:=cordconstnode.create(0,s32inttype,false);
+ end;
+
+ in_pred_x,
+ in_succ_x:
+ begin
+ set_varstate(left,vs_read,[vsf_must_be_valid]);
+ resultdef:=left.resultdef;
+ if not is_ordinal(resultdef) then
+ CGMessage(type_e_ordinal_expr_expected)
+ else
+ begin
+ if (resultdef.typ=enumdef) and
+ (tenumdef(resultdef).has_jumps) and
+ not(m_delphi in current_settings.modeswitches) then
+ CGMessage(type_e_succ_and_pred_enums_with_assign_not_possible);
+ end;
+ end;
+
+ in_initialize_x,
+ in_finalize_x,
+ in_setlength_x:
+ begin
+ { inlined from pinline }
+ internalerror(200204231);
+ end;
+
+ in_inc_x,
+ in_dec_x:
+ begin
+ resultdef:=voidtype;
+ if assigned(left) then
+ begin
+ { first param must be var }
+ valid_for_var(tcallparanode(left).left,true);
+ set_varstate(tcallparanode(left).left,vs_readwritten,[vsf_must_be_valid]);
+
+ if (left.resultdef.typ in [enumdef,pointerdef]) or
+ is_ordinal(left.resultdef) or
+ is_currency(left.resultdef) then
+ begin
+ { value of left gets changed -> must be unique }
+ set_unique(tcallparanode(left).left);
+ { two paras ? }
+ if assigned(tcallparanode(left).right) then
+ begin
+ if is_integer(tcallparanode(left).right.resultdef) then
+ begin
+ set_varstate(tcallparanode(tcallparanode(left).right).left,vs_read,[vsf_must_be_valid]);
+ { when range/overflow checking is on, we
+ convert this to a regular add, and for proper
+ checking we need the original type }
+ if ([cs_check_range,cs_check_overflow]*current_settings.localswitches=[]) then
+ if (tcallparanode(left).left.resultdef.typ=pointerdef) then
+ begin
+ { don't convert values added to pointers into the pointer types themselves,
+ because that will turn signed values into unsigned ones, which then
+ goes wrong when they have to be multiplied with the size of the elements
+ to which the pointer points in ncginl (mantis #17342) }
+ if is_signed(tcallparanode(tcallparanode(left).right).left.resultdef) then
+ inserttypeconv(tcallparanode(tcallparanode(left).right).left,ptrsinttype)
+ else
+ inserttypeconv(tcallparanode(tcallparanode(left).right).left,ptruinttype)
+ end
+ else if is_integer(tcallparanode(left).left.resultdef) then
+ inserttypeconv(tcallparanode(tcallparanode(left).right).left,tcallparanode(left).left.resultdef)
+ else
+ inserttypeconv_internal(tcallparanode(tcallparanode(left).right).left,tcallparanode(left).left.resultdef);
+ if assigned(tcallparanode(tcallparanode(left).right).right) then
+ { should be handled in the parser (JM) }
+ internalerror(2006020901);
+ end
+ else
+ CGMessagePos(tcallparanode(left).right.fileinfo,type_e_ordinal_expr_expected);
+ end;
+ end
+ else
+ begin
+ hp:=self;
+ if isunaryoverloaded(hp) then
+ begin
+ { inc(rec) and dec(rec) assigns result value to argument }
+ result:=cassignmentnode.create(tcallparanode(left).left.getcopy,hp);
+ exit;
+ end
+ else
+ CGMessagePos(left.fileinfo,type_e_ordinal_expr_expected);
+ end;
+ end
+ else
+ CGMessagePos(fileinfo,type_e_mismatch);
+ end;
+
+ in_read_x,
+ in_readln_x,
+ in_readstr_x,
+ in_write_x,
+ in_writeln_x,
+ in_writestr_x :
+ begin
+ result := handle_read_write;
+ end;
+
+ in_settextbuf_file_x :
+ begin
+ resultdef:=voidtype;
+ { now we know the type of buffer }
+ hp:=ccallparanode.create(cordconstnode.create(
+ tcallparanode(left).left.resultdef.size,s32inttype,true),left);
+ result:=ccallnode.createintern('SETTEXTBUF',hp);
+ left:=nil;
+ end;
+
+ { the firstpass of the arg has been done in firstcalln ? }
+ in_reset_typedfile,
+ in_rewrite_typedfile :
+ begin
+ result := handle_reset_rewrite_typed;
+ end;
+
+ in_str_x_string :
+ begin
+ result:=handle_str;
+ end;
+
+ in_val_x :
+ begin
+ result:=handle_val;
+ end;
+
+ in_include_x_y,
+ in_exclude_x_y:
+ begin
+ resultdef:=voidtype;
+ { the parser already checks whether we have two (and exactly two) }
+ { parameters (JM) }
+ { first param must be var }
+ valid_for_var(tcallparanode(left).left,true);
+ set_varstate(tcallparanode(left).left,vs_readwritten,[vsf_must_be_valid]);
+ { check type }
+ if (left.resultdef.typ=setdef) then
+ begin
+ { insert a type conversion }
+ { to the type of the set elements }
+ set_varstate(tcallparanode(tcallparanode(left).right).left,vs_read,[vsf_must_be_valid]);
+ inserttypeconv(tcallparanode(tcallparanode(left).right).left,
+ tsetdef(left.resultdef).elementdef);
+ end
+ else
+ CGMessage(type_e_mismatch);
+ end;
+ in_pack_x_y_z,
+ in_unpack_x_y_z :
+ begin
+ handle_pack_unpack;
+ end;
+
+ in_slice_x:
+ begin
+ result:=nil;
+ resultdef:=tcallparanode(left).left.resultdef;
+ if (resultdef.typ <> arraydef) then
+ CGMessagePos(left.fileinfo,type_e_mismatch)
+ else if is_packed_array(resultdef) then
+ CGMessagePos2(left.fileinfo,type_e_got_expected_unpacked_array,'1',resultdef.typename);
+ if not(is_integer(tcallparanode(tcallparanode(left).right).left.resultdef)) then
+ CGMessagePos1(tcallparanode(left).right.fileinfo,
+ type_e_integer_expr_expected,
+ tcallparanode(tcallparanode(left).right).left.resultdef.typename);
+ end;
+
+ in_low_x,
+ in_high_x:
+ begin
+ case left.resultdef.typ of
+ orddef,
+ enumdef,
+ setdef:
+ ;
+ arraydef:
+ begin
+ if (inlinenumber=in_low_x) then
+ set_varstate(left,vs_read,[])
+ else
+ begin
+ if is_open_array(left.resultdef) or
+ is_array_of_const(left.resultdef) then
+ begin
+ set_varstate(left,vs_read,[]);
+ result:=load_high_value_node(tparavarsym(tloadnode(left).symtableentry));
+ end
+ else
+ if is_dynamic_array(left.resultdef) then
+ begin
+ set_varstate(left,vs_read,[vsf_must_be_valid]);
+ { can't use inserttypeconv because we need }
+ { an explicit type conversion (JM) }
+ hp := ccallparanode.create(ctypeconvnode.create_internal(left,voidpointertype),nil);
+ result := ccallnode.createintern('fpc_dynarray_high',hp);
+ { make sure the left node doesn't get disposed, since it's }
+ { reused in the new node (JM) }
+ left:=nil;
+ end
+ else
+ begin
+ set_varstate(left,vs_read,[]);
+ end;
+ end;
+ end;
+ stringdef:
+ begin
+ if inlinenumber=in_low_x then
+ begin
+ set_varstate(left,vs_read,[]);
+ end
+ else
+ begin
+ if is_open_string(left.resultdef) then
+ begin
+ set_varstate(left,vs_read,[]);
+ result:=load_high_value_node(tparavarsym(tloadnode(left).symtableentry))
+ end
+ else if is_ansistring(left.resultdef) or
+ is_wide_or_unicode_string(left.resultdef) then
+ CGMessage(type_e_mismatch)
+ end;
+ end;
+ else
+ CGMessage(type_e_mismatch);
+ end;
+ end;
+
+ in_exp_real,
+ in_frac_real,
+ in_int_real,
+ in_cos_real,
+ in_sin_real,
+ in_arctan_real,
+ in_abs_real,
+ in_ln_real :
+ begin
+ set_varstate(left,vs_read,[vsf_must_be_valid]);
+ { converting an int64 to double on platforms without }
+ { extended can cause precision loss }
+ if not(left.nodetype in [ordconstn,realconstn]) then
+ inserttypeconv(left,pbestrealtype^);
+ resultdef:=pbestrealtype^;
+ end;
+
+ in_trunc_real,
+ in_round_real :
+ begin
+ set_varstate(left,vs_read,[vsf_must_be_valid]);
+ { for direct float rounding, no best real type cast should be necessary }
+ if not((left.resultdef.typ=floatdef) and
+ (tfloatdef(left.resultdef).floattype in [s32real,s64real,s80real,sc80real,s128real])) and
+ { converting an int64 to double on platforms without }
+ { extended can cause precision loss }
+ not(left.nodetype in [ordconstn,realconstn]) then
+ inserttypeconv(left,pbestrealtype^);
+ resultdef:=s64inttype;
+ end;
+
+ in_pi_real :
+ begin
+ resultdef:=pbestrealtype^;
+ end;
+
+ in_abs_long:
+ begin
+ set_varstate(left,vs_read,[vsf_must_be_valid]);
+ inserttypeconv(left,s32inttype);
+ resultdef:=s32inttype;
+ end;
+
+ in_sqr_real,
+ in_sqrt_real :
+ begin
+ set_varstate(left,vs_read,[vsf_must_be_valid]);
+ setfloatresultdef;
+ end;
+
+{$ifdef SUPPORT_MMX}
+ in_mmx_pcmpeqb..in_mmx_pcmpgtw:
+ begin
+ end;
+{$endif SUPPORT_MMX}
+ in_unaligned_x:
+ begin
+ resultdef:=left.resultdef;
+ end;
+ in_assert_x_y :
+ begin
+ resultdef:=voidtype;
+ if assigned(left) then
+ begin
+ set_varstate(tcallparanode(left).left,vs_read,[vsf_must_be_valid]);
+ { check type }
+ if is_boolean(left.resultdef) then
+ begin
+ set_varstate(tcallparanode(tcallparanode(left).right).left,vs_read,[vsf_must_be_valid]);
+ { must always be a string }
+ inserttypeconv(tcallparanode(tcallparanode(left).right).left,cshortstringtype);
+ end
+ else
+ CGMessage1(type_e_boolean_expr_expected,left.resultdef.typename);
+ end
+ else
+ CGMessage(type_e_mismatch);
+
+ if (cs_do_assertion in current_settings.localswitches) then
+ include(current_procinfo.flags,pi_do_call);
+ end;
+ in_prefetch_var:
+ resultdef:=voidtype;
+ in_get_frame,
+ in_get_caller_frame,
+ in_get_caller_addr:
+ begin
+ resultdef:=voidpointertype;
+ end;
+ in_rol_x,
+ in_ror_x,
+ in_sar_x:
+ begin
+ set_varstate(left,vs_read,[vsf_must_be_valid]);
+ resultdef:=left.resultdef;
+ end;
+ in_rol_x_y,
+ in_ror_x_y,
+ in_sar_x_y:
+ begin
+ set_varstate(tcallparanode(left).left,vs_read,[vsf_must_be_valid]);
+ set_varstate(tcallparanode(tcallparanode(left).right).left,vs_read,[vsf_must_be_valid]);
+ resultdef:=tcallparanode(tcallparanode(left).right).left.resultdef;
+ end;
+ in_bsf_x,
+ in_bsr_x:
+ begin
+ set_varstate(left,vs_read,[vsf_must_be_valid]);
+ if not is_integer(left.resultdef) then
+ CGMessage1(type_e_integer_expr_expected,left.resultdef.typename);
+ if torddef(left.resultdef).ordtype in [u64bit, s64bit] then
+ resultdef:=u64inttype
+ else
+ resultdef:=u32inttype
+ end;
+
+ in_objc_selector_x:
+ begin
+ result:=cobjcselectornode.create(left);
+ { reused }
+ left:=nil;
+ end;
+ in_objc_protocol_x:
+ begin
+ result:=cobjcprotocolnode.create(left);
+ { reused }
+ left:=nil;
+ end;
+ in_objc_encode_x:
+ begin
+ result:=handle_objc_encode;
+ end;
+ else
+ internalerror(8);
+ end;
+ end;
+
+ if not assigned(result) and not
+ codegenerror then
+ result:=simplify(false);
+ end;
+
+
+ function tinlinenode.pass_1 : tnode;
+ var
+ hp,hpp,resultnode : tnode;
+ shiftconst: longint;
+ tempnode: ttempcreatenode;
+ newstatement: tstatementnode;
+ newblock: tblocknode;
+
+ begin
+ result:=nil;
+ { if we handle writeln; left contains no valid address }
+ if assigned(left) then
+ begin
+ if left.nodetype=callparan then
+ tcallparanode(left).firstcallparan
+ else
+ firstpass(left);
+ end;
+
+ { intern const should already be handled }
+ if nf_inlineconst in flags then
+ internalerror(200104044);
+ case inlinenumber of
+ in_lo_qword,
+ in_hi_qword,
+ in_lo_long,
+ in_hi_long,
+ in_lo_word,
+ in_hi_word:
+ begin
+ shiftconst := 0;
+ case inlinenumber of
+ in_hi_qword:
+ shiftconst := 32;
+ in_hi_long:
+ shiftconst := 16;
+ in_hi_word:
+ shiftconst := 8;
+ end;
+ if shiftconst <> 0 then
+ result := ctypeconvnode.create_internal(cshlshrnode.create(shrn,left,
+ cordconstnode.create(shiftconst,u32inttype,false)),resultdef)
+ else
+ result := ctypeconvnode.create_internal(left,resultdef);
+ left := nil;
+ firstpass(result);
+ end;
+
+ in_sizeof_x:
+ begin
+ expectloc:=LOC_REGISTER;
+ end;
+
+ in_typeof_x:
+ begin
+ expectloc:=LOC_REGISTER;
+ end;
+
+ in_length_x:
+ begin
+ if is_shortstring(left.resultdef) then
+ expectloc:=left.expectloc
+ else
+ begin
+ { ansi/wide string }
+ expectloc:=LOC_REGISTER;
+ end;
+ end;
+
+ in_typeinfo_x:
+ begin
+ expectloc:=LOC_REGISTER;
+ end;
+
+ in_assigned_x:
+ begin
+ expectloc := LOC_JUMP;
+ end;
+
+ in_pred_x,
+ in_succ_x:
+ begin
+ expectloc:=LOC_REGISTER;
+ { in case of range/overflow checking, use a regular addnode
+ because it's too complex to handle correctly otherwise }
+ if ([cs_check_overflow,cs_check_range]*current_settings.localswitches)<>[] then
+ begin
+ { create constant 1 }
+ hp:=cordconstnode.create(1,left.resultdef,false);
+ typecheckpass(hp);
+ if not is_integer(hp.resultdef) then
+ inserttypeconv_internal(hp,sinttype);
+
+ { avoid type errors from the addn/subn }
+ if not is_integer(left.resultdef) then
+ inserttypeconv_internal(left,sinttype);
+
+ { addition/substraction depending on succ/pred }
+ if inlinenumber=in_succ_x then
+ hp:=caddnode.create(addn,left,hp)
+ else
+ hp:=caddnode.create(subn,left,hp);
+ { assign result of addition }
+ if not(is_integer(resultdef)) then
+ inserttypeconv(hp,torddef.create(
+{$ifdef cpu64bitaddr}
+ s64bit,
+{$else cpu64bitaddr}
+ s32bit,
+{$endif cpu64bitaddr}
+ get_min_value(resultdef),
+ get_max_value(resultdef)))
+ else
+ inserttypeconv(hp,resultdef);
+
+ { avoid any possible errors/warnings }
+ inserttypeconv_internal(hp,resultdef);
+
+ { firstpass it }
+ firstpass(hp);
+
+ { left is reused }
+ left:=nil;
+
+ { return new node }
+ result:=hp;
+ end;
+ end;
+
+ in_setlength_x,
+ in_initialize_x,
+ in_finalize_x:
+ begin
+ expectloc:=LOC_VOID;
+ end;
+
+ in_inc_x,
+ in_dec_x:
+ begin
+ expectloc:=LOC_VOID;
+
+ { range/overflow checking doesn't work properly }
+ { with the inc/dec code that's generated (JM) }
+ if (current_settings.localswitches * [cs_check_overflow,cs_check_range] <> []) and
+ { No overflow check for pointer operations, because inc(pointer,-1) will always
+ trigger an overflow. For uint32 it works because then the operation is done
+ in 64bit. Range checking is not applicable to pointers either }
+ (tcallparanode(left).left.resultdef.typ<>pointerdef) then
+ { convert to simple add (JM) }
+ begin
+ newblock := internalstatements(newstatement);
+ { extra parameter? }
+ if assigned(tcallparanode(left).right) then
+ begin
+ { Yes, use for add node }
+ hpp := tcallparanode(tcallparanode(left).right).left;
+ tcallparanode(tcallparanode(left).right).left := nil;
+ if assigned(tcallparanode(tcallparanode(left).right).right) then
+ CGMessage(parser_e_illegal_expression);
+ end
+ else
+ begin
+ { no, create constant 1 }
+ hpp := cordconstnode.create(1,tcallparanode(left).left.resultdef,false);
+ end;
+ typecheckpass(hpp);
+
+ { make sure we don't call functions part of the left node twice (and generally }
+ { optimize the code generation) }
+ if node_complexity(tcallparanode(left).left) > 1 then
+ begin
+ tempnode := ctempcreatenode.create(voidpointertype,voidpointertype.size,tt_persistent,true);
+ addstatement(newstatement,tempnode);
+ addstatement(newstatement,cassignmentnode.create(ctemprefnode.create(tempnode),
+ caddrnode.create_internal(tcallparanode(left).left.getcopy)));
+ hp := cderefnode.create(ctemprefnode.create(tempnode));
+ inserttypeconv_internal(hp,tcallparanode(left).left.resultdef);
+ end
+ else
+ begin
+ hp := tcallparanode(left).left.getcopy;
+ tempnode := nil;
+ end;
+
+ resultnode := hp.getcopy;
+ { avoid type errors from the addn/subn }
+ if not is_integer(resultnode.resultdef) then
+ begin
+ inserttypeconv_internal(hp,sinttype);
+ inserttypeconv_internal(hpp,sinttype);
+ end;
+
+ { addition/substraction depending on inc/dec }
+ if inlinenumber = in_inc_x then
+ hpp := caddnode.create(addn,hp,hpp)
+ else
+ hpp := caddnode.create(subn,hp,hpp);
+ { assign result of addition }
+ if not(is_integer(resultnode.resultdef)) then
+ inserttypeconv(hpp,torddef.create(
+{$ifdef cpu64bitaddr}
+ s64bit,
+{$else cpu64bitaddr}
+ s32bit,
+{$endif cpu64bitaddr}
+ get_min_value(resultnode.resultdef),
+ get_max_value(resultnode.resultdef)))
+ else
+ inserttypeconv(hpp,resultnode.resultdef);
+ { avoid any possible warnings }
+ inserttypeconv_internal(hpp,resultnode.resultdef);
+
+ addstatement(newstatement,cassignmentnode.create(resultnode,hpp));
+ { deallocate the temp }
+ if assigned(tempnode) then
+ addstatement(newstatement,ctempdeletenode.create(tempnode));
+ { firstpass it }
+ firstpass(tnode(newblock));
+ { return new node }
+ result := newblock;
+ end;
+ end;
+
+ in_include_x_y,
+ in_exclude_x_y:
+ begin
+ expectloc:=LOC_VOID;
+ end;
+
+ in_pack_x_y_z,
+ in_unpack_x_y_z:
+ begin
+ result:=first_pack_unpack;
+ end;
+
+ in_exp_real:
+ begin
+ result:= first_exp_real;
+ end;
+
+ in_round_real:
+ begin
+ result:= first_round_real;
+ end;
+
+ in_trunc_real:
+ begin
+ result:= first_trunc_real;
+ end;
+
+ in_int_real:
+ begin
+ result:= first_int_real;
+ end;
+
+ in_frac_real:
+ begin
+ result:= first_frac_real;
+ end;
+
+ in_cos_real:
+ begin
+ result:= first_cos_real;
+ end;
+
+ in_sin_real:
+ begin
+ result := first_sin_real;
+ end;
+
+ in_arctan_real:
+ begin
+ result := first_arctan_real;
+ end;
+
+ in_pi_real :
+ begin
+ result := first_pi;
+ end;
+
+ in_abs_real:
+ begin
+ result := first_abs_real;
+ end;
+
+ in_abs_long:
+ begin
+ result := first_abs_long;
+ end;
+
+ in_sqr_real:
+ begin
+ result := first_sqr_real;
+ end;
+
+ in_sqrt_real:
+ begin
+ result := first_sqrt_real;
+ end;
+
+ in_ln_real:
+ begin
+ result := first_ln_real;
+ end;
+
+{$ifdef SUPPORT_MMX}
+ in_mmx_pcmpeqb..in_mmx_pcmpgtw:
+ begin
+ end;
+{$endif SUPPORT_MMX}
+
+ in_assert_x_y :
+ begin
+ expectloc:=LOC_VOID;
+ end;
+
+ in_low_x,
+ in_high_x:
+ internalerror(200104047);
+
+ in_slice_x:
+ internalerror(2005101501);
+
+ in_ord_x,
+ in_chr_byte:
+ begin
+ { should not happend as it's converted to typeconv }
+ internalerror(200104045);
+ end;
+
+ in_ofs_x :
+ internalerror(2000101001);
+
+ in_seg_x :
+ internalerror(200104046);
+
+ in_settextbuf_file_x,
+ in_reset_typedfile,
+ in_rewrite_typedfile,
+ in_str_x_string,
+ in_val_x,
+ in_read_x,
+ in_readln_x,
+ in_write_x,
+ in_writeln_x :
+ begin
+ { should be handled by pass_typecheck }
+ internalerror(200108234);
+ end;
+ in_get_frame:
+ begin
+ include(current_procinfo.flags,pi_needs_stackframe);
+ expectloc:=LOC_CREGISTER;
+ end;
+ in_get_caller_frame:
+ begin
+ expectloc:=LOC_REGISTER;
+ end;
+ in_get_caller_addr:
+ begin
+ expectloc:=LOC_REGISTER;
+ end;
+
+ in_prefetch_var:
+ begin
+ expectloc:=LOC_VOID;
+ end;
+ in_unaligned_x:
+ begin
+ expectloc:=tcallparanode(left).left.expectloc;
+ end;
+ in_rol_x,
+ in_rol_x_y,
+ in_ror_x,
+ in_ror_x_y,
+ in_sar_x,
+ in_sar_x_y,
+ in_bsf_x,
+ in_bsr_x:
+ expectloc:=LOC_REGISTER;
+ else
+ internalerror(89);
+ end;
+ end;
+{$maxfpuregisters default}
+
+ function tinlinenode.docompare(p: tnode): boolean;
+ begin
+ docompare :=
+ inherited docompare(p) and
+ (inlinenumber = tinlinenode(p).inlinenumber);
+ end;
+
+
+ function tinlinenode.first_pi : tnode;
+ begin
+ result:=crealconstnode.create(getpi,pbestrealtype^);
+ end;
+
+
+ function tinlinenode.first_arctan_real : tnode;
+ begin
+ { create the call to the helper }
+ { on entry left node contains the parameter }
+ first_arctan_real := ccallnode.createintern('fpc_arctan_real',
+ ccallparanode.create(left,nil));
+ left := nil;
+ end;
+
+ function tinlinenode.first_abs_real : tnode;
+ begin
+ { create the call to the helper }
+ { on entry left node contains the parameter }
+ first_abs_real := ccallnode.createintern('fpc_abs_real',
+ ccallparanode.create(left,nil));
+ left := nil;
+ end;
+
+ function tinlinenode.first_sqr_real : tnode;
+ begin
+{$ifndef cpufpemu}
+ { this procedure might be only used for cpus definining cpufpemu else
+ the optimizer might go into an endless loop when doing x*x -> changes }
+ internalerror(2011092401);
+{$endif cpufpemu}
+ { create the call to the helper }
+ { on entry left node contains the parameter }
+ first_sqr_real := ctypeconvnode.create(ccallnode.createintern('fpc_sqr_real',
+ ccallparanode.create(left,nil)),resultdef);
+ left := nil;
+ end;
+
+ function tinlinenode.first_sqrt_real : tnode;
+ begin
+ { create the call to the helper }
+ { on entry left node contains the parameter }
+ first_sqrt_real := ctypeconvnode.create(ccallnode.createintern('fpc_sqrt_real',
+ ccallparanode.create(left,nil)),resultdef);
+ left := nil;
+ end;
+
+ function tinlinenode.first_ln_real : tnode;
+ begin
+ { create the call to the helper }
+ { on entry left node contains the parameter }
+ first_ln_real := ccallnode.createintern('fpc_ln_real',
+ ccallparanode.create(left,nil));
+ left := nil;
+ end;
+
+ function tinlinenode.first_cos_real : tnode;
+ begin
+ { create the call to the helper }
+ { on entry left node contains the parameter }
+ first_cos_real := ccallnode.createintern('fpc_cos_real',
+ ccallparanode.create(left,nil));
+ left := nil;
+ end;
+
+ function tinlinenode.first_sin_real : tnode;
+ begin
+ { create the call to the helper }
+ { on entry left node contains the parameter }
+ first_sin_real := ccallnode.createintern('fpc_sin_real',
+ ccallparanode.create(left,nil));
+ left := nil;
+ end;
+
+ function tinlinenode.first_exp_real : tnode;
+ begin
+ { create the call to the helper }
+ { on entry left node contains the parameter }
+ result := ccallnode.createintern('fpc_exp_real',ccallparanode.create(left,nil));
+ left := nil;
+ end;
+
+ function tinlinenode.first_int_real : tnode;
+ begin
+ { create the call to the helper }
+ { on entry left node contains the parameter }
+ result := ccallnode.createintern('fpc_int_real',ccallparanode.create(left,nil));
+ left := nil;
+ end;
+
+ function tinlinenode.first_frac_real : tnode;
+ begin
+ { create the call to the helper }
+ { on entry left node contains the parameter }
+ result := ccallnode.createintern('fpc_frac_real',ccallparanode.create(left,nil));
+ left := nil;
+ end;
+
+ function tinlinenode.first_round_real : tnode;
+ begin
+ { create the call to the helper }
+ { on entry left node contains the parameter }
+ result := ccallnode.createintern('fpc_round_real',ccallparanode.create(left,nil));
+ left := nil;
+ end;
+
+ function tinlinenode.first_trunc_real : tnode;
+ begin
+ { create the call to the helper }
+ { on entry left node contains the parameter }
+ result := ccallnode.createintern('fpc_trunc_real',ccallparanode.create(left,nil));
+ left := nil;
+ end;
+
+ function tinlinenode.first_abs_long : tnode;
+ begin
+ expectloc:=LOC_REGISTER;
+ result:=nil;
+ end;
+
+ function tinlinenode.first_pack_unpack: tnode;
+ var
+ loopstatement : tstatementnode;
+ loop : tblocknode;
+ loopvar : ttempcreatenode;
+ tempnode,
+ source,
+ target,
+ index,
+ unpackednode,
+ packednode,
+ sourcevecindex,
+ targetvecindex,
+ loopbody : tnode;
+ temprangedef : tdef;
+ ulorange,
+ uhirange,
+ plorange,
+ phirange : TConstExprInt;
+ begin
+ { transform into a for loop which assigns the data of the (un)packed }
+ { array to the other one }
+ source := left;
+ if (inlinenumber = in_unpack_x_y_z) then
+ begin
+ target := tcallparanode(source).right;
+ index := tcallparanode(target).right;
+ packednode := tcallparanode(source).left;
+ unpackednode := tcallparanode(target).left;
+ end
+ else
+ begin
+ index := tcallparanode(source).right;
+ target := tcallparanode(index).right;
+ packednode := tcallparanode(target).left;
+ unpackednode := tcallparanode(source).left;
+ end;
+ source := tcallparanode(source).left;
+ target := tcallparanode(target).left;
+ index := tcallparanode(index).left;
+
+ loop := internalstatements(loopstatement);
+ loopvar := ctempcreatenode.create(
+ tarraydef(packednode.resultdef).rangedef,
+ tarraydef(packednode.resultdef).rangedef.size,
+ tt_persistent,true);
+ addstatement(loopstatement,loopvar);
+
+ { For range checking: we have to convert to an integer type (in case the index type }
+ { is an enum), add the index and loop variable together, convert the result }
+ { implicitly to an orddef with range equal to the rangedef to get range checking }
+ { and finally convert it explicitly back to the actual rangedef to avoid type }
+ { errors }
+ temprangedef:=nil;
+ getrange(unpackednode.resultdef,ulorange,uhirange);
+ getrange(packednode.resultdef,plorange,phirange);
+ temprangedef:=torddef.create(torddef(sinttype).ordtype,ulorange,uhirange);
+ sourcevecindex := ctemprefnode.create(loopvar);
+ targetvecindex := ctypeconvnode.create_internal(index.getcopy,sinttype);
+ targetvecindex := caddnode.create(subn,targetvecindex,cordconstnode.create(plorange,sinttype,true));
+ targetvecindex := caddnode.create(addn,targetvecindex,ctemprefnode.create(loopvar));
+ targetvecindex := ctypeconvnode.create(targetvecindex,temprangedef);
+ targetvecindex := ctypeconvnode.create_explicit(targetvecindex,tarraydef(unpackednode.resultdef).rangedef);
+
+ if (inlinenumber = in_pack_x_y_z) then
+ begin
+ { swap source and target vec indices }
+ tempnode := sourcevecindex;
+ sourcevecindex := targetvecindex;
+ targetvecindex := tempnode;
+ end;
+
+ { create the assignment in the loop body }
+ loopbody :=
+ cassignmentnode.create(
+ cvecnode.create(target.getcopy,targetvecindex),
+ cvecnode.create(source.getcopy,sourcevecindex)
+ );
+ { create the actual for loop }
+ tempnode := cfornode.create(
+ ctemprefnode.create(loopvar),
+ cinlinenode.create(in_low_x,false,packednode.getcopy),
+ cinlinenode.create(in_high_x,false,packednode.getcopy),
+ loopbody,
+ false);
+ addstatement(loopstatement,tempnode);
+ { free the loop counter }
+ addstatement(loopstatement,ctempdeletenode.create(loopvar));
+ result := loop;
+ end;
+
+end.
diff --git a/closures/compiler/nld.pas b/closures/compiler/nld.pas
new file mode 100644
index 0000000000..2f2dc872af
--- /dev/null
+++ b/closures/compiler/nld.pas
@@ -0,0 +1,1269 @@
+{
+ Copyright (c) 2000-2002 by Florian Klaempfl
+
+ Type checking and register allocation for load/assignment nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit nld;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,
+ {$ifdef state_tracking}
+ nstate,
+ {$endif}
+ symconst,symbase,symtype,symsym,symdef;
+
+ type
+ Trttidatatype = (rdt_normal,rdt_ord2str,rdt_str2ord);
+
+ tloadnodeflags = (
+ loadnf_is_self,
+ loadnf_load_self_pointer,
+ loadnf_inherited,
+ { the loadnode is generated internally and a varspez=vs_const should be ignore,
+ this requires that the parameter is actually passed by value
+ Be really carefull when using this flag! }
+ loadnf_isinternal_ignoreconst,
+
+ loadnf_only_uninitialized_hint
+ );
+
+ tloadnode = class(tunarynode)
+ protected
+ fprocdef : tprocdef;
+ fprocdefderef : tderef;
+ public
+ loadnodeflags : set of tloadnodeflags;
+ symtableentry : tsym;
+ symtableentryderef : tderef;
+ symtable : TSymtable;
+ constructor create(v : tsym;st : TSymtable);virtual;
+ constructor create_procvar(v : tsym;d:tprocdef;st : TSymtable);virtual;
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderefimpl;override;
+ procedure derefimpl;override;
+ procedure set_mp(p:tnode);
+ function is_addr_param_load:boolean;
+ function dogetcopy : tnode;override;
+ function pass_1 : tnode;override;
+ function pass_typecheck:tnode;override;
+ procedure mark_write;override;
+ function docompare(p: tnode): boolean; override;
+ procedure printnodedata(var t:text);override;
+ procedure setprocdef(p : tprocdef);
+ property procdef: tprocdef read fprocdef write setprocdef;
+ end;
+ tloadnodeclass = class of tloadnode;
+
+ { different assignment types }
+ tassigntype = (at_normal,at_plus,at_minus,at_star,at_slash);
+
+ tassignmentnode = class(tbinarynode)
+ assigntype : tassigntype;
+ constructor create(l,r : tnode);virtual;
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ function dogetcopy : tnode;override;
+ function pass_1 : tnode;override;
+ function pass_typecheck:tnode;override;
+ function simplify(forinline : boolean) : tnode;override;
+ {$ifdef state_tracking}
+ function track_state_pass(exec_known:boolean):boolean;override;
+ {$endif state_tracking}
+ function docompare(p: tnode): boolean; override;
+ end;
+ tassignmentnodeclass = class of tassignmentnode;
+
+ tarrayconstructorrangenode = class(tbinarynode)
+ constructor create(l,r : tnode);virtual;
+ function pass_1 : tnode;override;
+ function pass_typecheck:tnode;override;
+ end;
+ tarrayconstructorrangenodeclass = class of tarrayconstructorrangenode;
+
+ tarrayconstructornode = class(tbinarynode)
+ constructor create(l,r : tnode);virtual;
+ function dogetcopy : tnode;override;
+ function pass_1 : tnode;override;
+ function pass_typecheck:tnode;override;
+ function docompare(p: tnode): boolean; override;
+ procedure force_type(def:tdef);
+ procedure insert_typeconvs;
+ end;
+ tarrayconstructornodeclass = class of tarrayconstructornode;
+
+ ttypenode = class(tnode)
+ allowed : boolean;
+ helperallowed : boolean;
+ typedef : tdef;
+ typedefderef : tderef;
+ typesym : tsym;
+ typesymderef : tderef;
+ constructor create(def:tdef);virtual;
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderefimpl;override;
+ procedure derefimpl;override;
+ function pass_1 : tnode;override;
+ function pass_typecheck:tnode;override;
+ function dogetcopy : tnode;override;
+ function docompare(p: tnode): boolean; override;
+ end;
+ ttypenodeclass = class of ttypenode;
+
+ trttinode = class(tnode)
+ l1,l2 : longint;
+ rttitype : trttitype;
+ rttidef : tstoreddef;
+ rttidefderef : tderef;
+ rttidatatype : Trttidatatype;
+ constructor create(def:tstoreddef;rt:trttitype;dt:Trttidatatype);virtual;
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderefimpl;override;
+ procedure derefimpl;override;
+ function dogetcopy : tnode;override;
+ function pass_1 : tnode;override;
+ function pass_typecheck:tnode;override;
+ function docompare(p: tnode): boolean; override;
+ end;
+ trttinodeclass = class of trttinode;
+
+ var
+ cloadnode : tloadnodeclass = tloadnode;
+ cassignmentnode : tassignmentnodeclass = tassignmentnode;
+ carrayconstructorrangenode : tarrayconstructorrangenodeclass = tarrayconstructorrangenode;
+ carrayconstructornode : tarrayconstructornodeclass = tarrayconstructornode;
+ ctypenode : ttypenodeclass = ttypenode;
+ crttinode : trttinodeclass = trttinode;
+
+ { Current assignment node }
+ aktassignmentnode : tassignmentnode;
+
+
+implementation
+
+ uses
+ cutils,verbose,globtype,globals,systems,
+ symnot,symtable,
+ defutil,defcmp,
+ htypechk,pass_1,procinfo,paramgr,
+ cpuinfo,
+ ncon,ninl,ncnv,nmem,ncal,nutils,nbas,
+ cgobj,cgbase
+ ;
+
+{*****************************************************************************
+ TLOADNODE
+*****************************************************************************}
+
+ constructor tloadnode.create(v : tsym;st : TSymtable);
+ begin
+ inherited create(loadn,nil);
+ if not assigned(v) then
+ internalerror(200108121);
+ symtableentry:=v;
+ symtable:=st;
+ fprocdef:=nil;
+ end;
+
+
+ constructor tloadnode.create_procvar(v : tsym;d:tprocdef;st : TSymtable);
+ begin
+ inherited create(loadn,nil);
+ if not assigned(v) then
+ internalerror(200108122);
+ symtableentry:=v;
+ symtable:=st;
+ fprocdef:=d;
+ end;
+
+
+ constructor tloadnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ ppufile.getderef(symtableentryderef);
+ symtable:=nil;
+ ppufile.getderef(fprocdefderef);
+ ppufile.getsmallset(loadnodeflags);
+ end;
+
+
+ procedure tloadnode.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putderef(symtableentryderef);
+ ppufile.putderef(fprocdefderef);
+ ppufile.putsmallset(loadnodeflags);
+ end;
+
+
+ procedure tloadnode.buildderefimpl;
+ begin
+ inherited buildderefimpl;
+ symtableentryderef.build(symtableentry);
+ fprocdefderef.build(fprocdef);
+ end;
+
+
+ procedure tloadnode.derefimpl;
+ begin
+ inherited derefimpl;
+ symtableentry:=tsym(symtableentryderef.resolve);
+ symtable:=symtableentry.owner;
+ fprocdef:=tprocdef(fprocdefderef.resolve);
+ end;
+
+
+ procedure tloadnode.set_mp(p:tnode);
+ begin
+ { typen nodes should not be set }
+ if p.nodetype=typen then
+ internalerror(200301042);
+ left:=p;
+ end;
+
+
+ function tloadnode.dogetcopy : tnode;
+ var
+ n : tloadnode;
+
+ begin
+ n:=tloadnode(inherited dogetcopy);
+ n.symtable:=symtable;
+ n.symtableentry:=symtableentry;
+ n.fprocdef:=fprocdef;
+ result:=n;
+ end;
+
+
+ function tloadnode.is_addr_param_load:boolean;
+ begin
+ result:=(symtable.symtabletype=parasymtable) and
+ (symtableentry.typ=paravarsym) and
+ not(vo_has_local_copy in tparavarsym(symtableentry).varoptions) and
+ not(loadnf_load_self_pointer in loadnodeflags) and
+ paramanager.push_addr_param(tparavarsym(symtableentry).varspez,tparavarsym(symtableentry).vardef,tprocdef(symtable.defowner).proccalloption);
+ end;
+
+
+ function tloadnode.pass_typecheck:tnode;
+ begin
+ result:=nil;
+ case symtableentry.typ of
+ absolutevarsym :
+ resultdef:=tabsolutevarsym(symtableentry).vardef;
+ constsym:
+ begin
+ if tconstsym(symtableentry).consttyp=constresourcestring then
+ resultdef:=getansistringdef
+ else
+ internalerror(22799);
+ end;
+ staticvarsym :
+ begin
+ tabstractvarsym(symtableentry).IncRefCountBy(1);
+ { static variables referenced in procedures or from finalization,
+ variable needs to be in memory.
+ It is too hard and the benefit is too small to detect whether a
+ variable is only used in the finalization to add support for it (PFV) }
+ if assigned(current_procinfo) and
+ (symtable.symtabletype=staticsymtable) and
+ (
+ (symtable.symtablelevel<>current_procinfo.procdef.localst.symtablelevel) or
+ (current_procinfo.procdef.proctypeoption=potype_unitfinalize)
+ ) then
+ make_not_regable(self,[ra_addr_taken]);
+ resultdef:=tabstractvarsym(symtableentry).vardef;
+ end;
+ paravarsym,
+ localvarsym :
+ begin
+ tabstractvarsym(symtableentry).IncRefCountBy(1);
+ { Nested variable? The we need to load the framepointer of
+ the parent procedure }
+ if assigned(current_procinfo) and
+ (symtable.symtabletype in [localsymtable,parasymtable]) and
+ (symtable.symtablelevel<>current_procinfo.procdef.parast.symtablelevel) then
+ begin
+ if assigned(left) then
+ internalerror(200309289);
+ left:=cloadparentfpnode.create(tprocdef(symtable.defowner));
+ { we can't inline the referenced parent procedure }
+ exclude(tprocdef(symtable.defowner).procoptions,po_inline);
+ { reference in nested procedures, variable needs to be in memory }
+ { and behaves as if its address escapes its parent block }
+ make_not_regable(self,[ra_addr_taken]);
+ end;
+ { fix self type which is declared as voidpointer in the
+ definition }
+ if vo_is_self in tabstractvarsym(symtableentry).varoptions then
+ begin
+ resultdef:=tprocdef(symtableentry.owner.defowner).struct;
+ if is_objectpascal_helper(resultdef) then
+ resultdef:=tobjectdef(resultdef).extendeddef;
+ if (po_classmethod in tprocdef(symtableentry.owner.defowner).procoptions) or
+ (po_staticmethod in tprocdef(symtableentry.owner.defowner).procoptions) then
+ resultdef:=tclassrefdef.create(resultdef)
+ else if (is_object(resultdef) or is_record(resultdef)) and
+ (loadnf_load_self_pointer in loadnodeflags) then
+ resultdef:=tpointerdef.create(resultdef);
+ end
+ else if vo_is_vmt in tabstractvarsym(symtableentry).varoptions then
+ begin
+ resultdef:=tprocdef(symtableentry.owner.defowner).struct;
+ resultdef:=tclassrefdef.create(resultdef);
+ end
+ else
+ resultdef:=tabstractvarsym(symtableentry).vardef;
+ end;
+ procsym :
+ begin
+ { Return the first procdef. In case of overloaded
+ procdefs the matching procdef will be choosen
+ when the expected procvardef is known, see get_information
+ in htypechk.pas (PFV) }
+ if not assigned(fprocdef) then
+ fprocdef:=tprocdef(tprocsym(symtableentry).ProcdefList[0])
+ else if po_kylixlocal in fprocdef.procoptions then
+ CGMessage(type_e_cant_take_address_of_local_subroutine);
+
+ { the result is a fprocdef, addrn and proc_to_procvar
+ typeconvn need this as resultdef so they know
+ that the address needs to be returned }
+ resultdef:=fprocdef;
+
+ { process methodpointer/framepointer }
+ if assigned(left) then
+ typecheckpass(left);
+ end;
+ labelsym:
+ begin
+ tlabelsym(symtableentry).used:=true;
+ resultdef:=voidtype;
+ end;
+ else
+ internalerror(200104141);
+ end;
+ end;
+
+ procedure Tloadnode.mark_write;
+
+ begin
+ include(flags,nf_write);
+ end;
+
+ function tloadnode.pass_1 : tnode;
+ begin
+ result:=nil;
+ expectloc:=LOC_REFERENCE;
+ if (cs_create_pic in current_settings.moduleswitches) and
+ not(symtableentry.typ in [paravarsym,localvarsym]) then
+ include(current_procinfo.flags,pi_needs_got);
+
+ case symtableentry.typ of
+ absolutevarsym :
+ ;
+ constsym:
+ begin
+ if tconstsym(symtableentry).consttyp=constresourcestring then
+ expectloc:=LOC_CREFERENCE;
+ end;
+ staticvarsym,
+ localvarsym,
+ paravarsym :
+ begin
+ if assigned(left) then
+ firstpass(left);
+ if not is_addr_param_load and
+ tabstractvarsym(symtableentry).is_regvar(is_addr_param_load) then
+ expectloc:=tvarregable2tcgloc[tabstractvarsym(symtableentry).varregable]
+ else
+ if (tabstractvarsym(symtableentry).varspez=vs_const) then
+ expectloc:=LOC_CREFERENCE;
+ if (target_info.system=system_powerpc_darwin) and
+ ([vo_is_dll_var,vo_is_external] * tabstractvarsym(symtableentry).varoptions <> []) then
+ include(current_procinfo.flags,pi_needs_got);
+ { call to get address of threadvar }
+ if (vo_is_thread_var in tabstractvarsym(symtableentry).varoptions) then
+ include(current_procinfo.flags,pi_do_call);
+ if nf_write in flags then
+ Tabstractvarsym(symtableentry).trigger_notifications(vn_onwrite)
+ else
+ Tabstractvarsym(symtableentry).trigger_notifications(vn_onread);
+ end;
+ procsym :
+ begin
+ { initialise left for nested procs if necessary }
+ if (m_nested_procvars in current_settings.modeswitches) then
+ setprocdef(fprocdef);
+ { method pointer or nested proc ? }
+ if assigned(left) then
+ begin
+ expectloc:=LOC_CREFERENCE;
+ firstpass(left);
+ end;
+ end;
+ labelsym :
+ ;
+ else
+ internalerror(200104143);
+ end;
+ end;
+
+
+ function tloadnode.docompare(p: tnode): boolean;
+ begin
+ docompare :=
+ inherited docompare(p) and
+ (symtableentry = tloadnode(p).symtableentry) and
+ (fprocdef = tloadnode(p).fprocdef) and
+ (symtable = tloadnode(p).symtable);
+ end;
+
+
+ procedure tloadnode.printnodedata(var t:text);
+ begin
+ inherited printnodedata(t);
+ write(t,printnodeindention,'symbol = ',symtableentry.name);
+ if symtableentry.typ=procsym then
+ write(t,printnodeindention,'procdef = ',fprocdef.mangledname);
+ writeln(t,'');
+ end;
+
+
+ procedure tloadnode.setprocdef(p : tprocdef);
+ begin
+ fprocdef:=p;
+ resultdef:=p;
+ { nested procedure? }
+ if assigned(p) and
+ is_nested_pd(p) then
+ begin
+ if not(m_nested_procvars in current_settings.modeswitches) then
+ CGMessage(type_e_cant_take_address_of_local_subroutine)
+ else
+ begin
+ { parent frame pointer pointer as "self" }
+ left.free;
+ left:=cloadparentfpnode.create(tprocdef(p.owner.defowner));
+ end;
+ end
+ { we should never go from nested to non-nested }
+ else if assigned(left) and
+ (left.nodetype=loadparentfpn) then
+ internalerror(2010072201);
+ end;
+
+{*****************************************************************************
+ TASSIGNMENTNODE
+*****************************************************************************}
+
+ constructor tassignmentnode.create(l,r : tnode);
+
+ begin
+ inherited create(assignn,l,r);
+ l.mark_write;
+ assigntype:=at_normal;
+ if r.nodetype = typeconvn then
+ ttypeconvnode(r).warn_pointer_to_signed:=false;
+ end;
+
+
+ constructor tassignmentnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ assigntype:=tassigntype(ppufile.getbyte);
+ end;
+
+
+ procedure tassignmentnode.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putbyte(byte(assigntype));
+ end;
+
+
+ function tassignmentnode.dogetcopy : tnode;
+
+ var
+ n : tassignmentnode;
+
+ begin
+ n:=tassignmentnode(inherited dogetcopy);
+ n.assigntype:=assigntype;
+ result:=n;
+ end;
+
+
+ function tassignmentnode.simplify(forinline : boolean) : tnode;
+ begin
+ result:=nil;
+ { assignment nodes can perform several floating point }
+ { type conversions directly, so no typeconversions }
+ { are inserted in those cases. When inlining, a }
+ { variable may be replaced by a constant which can be }
+ { converted at compile time, so check for this case }
+ if is_real(left.resultdef) and
+ is_real(right.resultdef) and
+ is_constrealnode(right) and
+ not equal_defs(right.resultdef,left.resultdef) then
+ inserttypeconv(right,left.resultdef);
+ end;
+
+
+ function tassignmentnode.pass_typecheck:tnode;
+ var
+ hp : tnode;
+ useshelper : boolean;
+ oldassignmentnode : tassignmentnode;
+ begin
+ result:=nil;
+ resultdef:=voidtype;
+
+ { must be made unique }
+ set_unique(left);
+
+ typecheckpass(left);
+
+ { PI. This is needed to return correct resultdef of add nodes for ansistrings
+ rawbytestring return needs to be replaced by left.resultdef }
+ oldassignmentnode:=aktassignmentnode;
+ aktassignmentnode:=self;
+ typecheckpass(right);
+ aktassignmentnode:=oldassignmentnode;
+
+ set_varstate(right,vs_read,[vsf_must_be_valid]);
+ set_varstate(left,vs_written,[]);
+ if codegenerror then
+ exit;
+
+ { tp procvar support, when we don't expect a procvar
+ then we need to call the procvar }
+ if (left.resultdef.typ<>procvardef) then
+ maybe_call_procvar(right,true);
+
+ { assignments to formaldefs and open arrays aren't allowed }
+ if (left.resultdef.typ=formaldef) or
+ is_open_array(left.resultdef) then
+ CGMessage(type_e_assignment_not_allowed);
+
+ { test if node can be assigned, properties are allowed }
+ valid_for_assignment(left,true);
+
+ { assigning nil to a dynamic array clears the array }
+ if is_dynamic_array(left.resultdef) and
+ (right.nodetype=niln) then
+ begin
+ { remove property flag to avoid errors, see comments for }
+ { tf_winlikewidestring assignments below }
+ exclude(left.flags,nf_isproperty);
+ hp:=ccallparanode.create(caddrnode.create_internal
+ (crttinode.create(tstoreddef(left.resultdef),initrtti,rdt_normal)),
+ ccallparanode.create(ctypeconvnode.create_internal(left,voidpointertype),nil));
+ result := ccallnode.createintern('fpc_dynarray_clear',hp);
+ left:=nil;
+ exit;
+ end;
+
+ { shortstring helpers can do the conversion directly,
+ so treat them separatly }
+ if (is_shortstring(left.resultdef)) then
+ begin
+ { insert typeconv, except for chars that are handled in
+ secondpass and except for ansi/wide string that can
+ be converted immediatly }
+ if not(is_char(right.resultdef) or
+ (right.resultdef.typ=stringdef)) then
+ inserttypeconv(right,left.resultdef);
+ if right.resultdef.typ=stringdef then
+ begin
+ useshelper:=true;
+ { convert constant strings to shortstrings. But
+ skip empty constant strings, that will be handled
+ in secondpass }
+ if (right.nodetype=stringconstn) then
+ begin
+ { verify if range fits within shortstring }
+ { just emit a warning, delphi gives an }
+ { error, only if the type definition of }
+ { of the string is less < 255 characters }
+ if not is_open_string(left.resultdef) and
+ (tstringconstnode(right).len > tstringdef(left.resultdef).len) then
+ cgmessage(type_w_string_too_long);
+ inserttypeconv(right,left.resultdef);
+ if (right.nodetype=stringconstn) and
+ (tstringconstnode(right).len=0) then
+ useshelper:=false;
+ end
+ else if (tstringdef(right.resultdef).stringtype in [st_unicodestring,st_widestring]) then
+ Message2(type_w_implicit_string_cast_loss,right.resultdef.typename,left.resultdef.typename);
+ { rest is done in pass 1 (JM) }
+ if useshelper then
+ exit;
+ end
+ end
+ { floating point assignments can also perform the conversion directly }
+ else if is_real(left.resultdef) and is_real(right.resultdef) and
+ not is_constrealnode(right)
+{$ifdef cpufpemu}
+ { the emulator can't do this obviously }
+ and not(current_settings.fputype in [fpu_libgcc,fpu_soft])
+{$endif cpufpemu}
+
+{$ifdef x86}
+ { the assignment node code can't convert a double in an }
+ { sse register to an extended value in memory more }
+ { efficiently than a type conversion node, so don't }
+ { bother implementing support for that }
+ and (use_vectorfpu(left.resultdef) or not(use_vectorfpu(right.resultdef)))
+{$endif}
+
+{$ifdef arm}
+ { the assignment node code can't convert a single in
+ an interger register to a double in an mmregister or
+ vice versa }
+ and (use_vectorfpu(left.resultdef) and
+ use_vectorfpu(right.resultdef) and
+ (tfloatdef(left.resultdef).floattype=tfloatdef(right.resultdef).floattype))
+{$endif}
+ then
+ begin
+ check_ranges(fileinfo,right,left.resultdef);
+ end
+ else
+ begin
+ { check if the assignment may cause a range check error }
+ check_ranges(fileinfo,right,left.resultdef);
+
+ { beginners might be confused about an error message like
+ Incompatible types: got "untyped" expected "LongInt"
+ when trying to assign the result of a procedure, so give
+ a better error message, see also #19122 }
+ if (left.resultdef.typ<>procvardef) and
+ (right.nodetype=calln) and is_void(right.resultdef) then
+ CGMessage(type_e_procedures_return_no_value)
+ else
+ inserttypeconv(right,left.resultdef);
+ end;
+
+ { call helpers for interface }
+ if is_interfacecom_or_dispinterface(left.resultdef) then
+ begin
+ { Normal interface assignments are handled by the generic refcount incr/decr }
+ if not right.resultdef.is_related(left.resultdef) then
+ begin
+ { remove property flag to avoid errors, see comments for }
+ { tf_winlikewidestring assignments below }
+ exclude(left.flags,nf_isproperty);
+ hp:=
+ ccallparanode.create(
+ cguidconstnode.create(tobjectdef(left.resultdef).iidguid^),
+ ccallparanode.create(
+ ctypeconvnode.create_internal(right,voidpointertype),
+ ccallparanode.create(
+ ctypeconvnode.create_internal(left,voidpointertype),
+ nil)));
+ result:=ccallnode.createintern('fpc_intf_assign_by_iid',hp);
+ left:=nil;
+ right:=nil;
+ exit;
+ end;
+ end;
+
+ { check if local proc/func is assigned to procvar }
+ if right.resultdef.typ=procvardef then
+ test_local_to_procvar(tprocvardef(right.resultdef),left.resultdef);
+ end;
+
+
+ function tassignmentnode.pass_1 : tnode;
+ var
+ hp: tnode;
+ oldassignmentnode : tassignmentnode;
+ hdef: tdef;
+ hs: string;
+ needrtti: boolean;
+ begin
+ result:=nil;
+ expectloc:=LOC_VOID;
+
+ firstpass(left);
+
+ { Optimize the reuse of the destination of the assingment in left.
+ Allow the use of the left inside the tree generated on the right.
+ This is especially useful for string routines where the destination
+ is pushed as a parameter. Using the final destination of left directly
+ save a temp allocation and copy of data (PFV) }
+ oldassignmentnode:=aktassignmentnode;
+ aktassignmentnode:=self;
+ firstpass(right);
+ aktassignmentnode:=oldassignmentnode;
+ if nf_assign_done_in_right in flags then
+ begin
+ result:=right;
+ right:=nil;
+ exit;
+ end;
+
+ if codegenerror then
+ exit;
+
+ { assignment to refcounted variable -> inc/decref }
+ if is_managed_type(left.resultdef) then
+ include(current_procinfo.flags,pi_do_call);
+
+ needrtti:=false;
+
+ if (is_shortstring(left.resultdef)) then
+ begin
+ if right.resultdef.typ=stringdef then
+ begin
+ if (right.nodetype<>stringconstn) or
+ (tstringconstnode(right).len<>0) then
+ begin
+ { remove property flag to avoid errors, see comments for }
+ { tf_winlikewidestring assignments below }
+ exclude(left.flags, nf_isproperty);
+ hp:=ccallparanode.create
+ (right,
+ ccallparanode.create(left,nil));
+ result:=ccallnode.createintern('fpc_'+tstringdef(right.resultdef).stringtypname+'_to_shortstr',hp);
+ firstpass(result);
+ left:=nil;
+ right:=nil;
+ end;
+ end;
+ exit;
+ end
+ { call helpers for composite types containing automated types }
+ else if is_managed_type(left.resultdef) and
+ (left.resultdef.typ in [arraydef,objectdef,recorddef]) and
+ not is_interfacecom_or_dispinterface(left.resultdef) and
+ not is_dynamic_array(left.resultdef) then
+ begin
+ hp:=ccallparanode.create(caddrnode.create_internal(
+ crttinode.create(tstoreddef(left.resultdef),initrtti,rdt_normal)),
+ ccallparanode.create(ctypeconvnode.create_internal(
+ caddrnode.create_internal(left),voidpointertype),
+ ccallparanode.create(ctypeconvnode.create_internal(
+ caddrnode.create_internal(right),voidpointertype),
+ nil)));
+ result:=ccallnode.createintern('fpc_copy_proc',hp);
+ firstpass(result);
+ left:=nil;
+ right:=nil;
+ exit;
+ end
+ { call helpers for variant, they can contain non ref. counted types like
+ vararrays which must be really copied }
+ else if left.resultdef.typ=variantdef then
+ begin
+ { remove property flag to avoid errors, see comments for }
+ { tf_winlikewidestring assignments below }
+ exclude(left.flags,nf_isproperty);
+ hdef:=search_system_type('TVARDATA').typedef;
+ hp:=ccallparanode.create(ctypeconvnode.create_internal(
+ right,hdef),
+ ccallparanode.create(ctypeconvnode.create_internal(
+ left,hdef),
+ nil));
+ result:=ccallnode.createintern('fpc_variant_copy',hp);
+ firstpass(result);
+ left:=nil;
+ right:=nil;
+ exit;
+ end
+ { call helpers for pointer-sized managed types }
+ else if is_widestring(left.resultdef) then
+ hs:='fpc_widestr_assign'
+ else if is_ansistring(left.resultdef) then
+ hs:='fpc_ansistr_assign'
+ else if is_unicodestring(left.resultdef) then
+ hs:='fpc_unicodestr_assign'
+ else if is_interfacecom_or_dispinterface(left.resultdef) then
+ hs:='fpc_intf_assign'
+ else if is_dynamic_array(left.resultdef) then
+ begin
+ hs:='fpc_dynarray_assign';
+ needrtti:=true;
+ end
+ else
+ exit;
+
+ { The first argument of these procedures is a var parameter. Properties cannot }
+ { be passed to var or out parameters, because in that case setters/getters are not }
+ { used. Further, if we would allow it in case there are no getters or setters, you }
+ { would need source changes in case these are introduced later on, thus defeating }
+ { part of the transparency advantages of properties. In this particular case, }
+ { however: }
+ { a) if there is a setter, this code will not be used since then the assignment }
+ { will be converted to a procedure call }
+ { b) the getter is irrelevant, because fpc_widestr_assign must always decrease }
+ { the refcount of the field to which we are writing }
+ { c) source code changes are not required if a setter is added/removed, because }
+ { this transformation is handled at compile time }
+ { -> we can remove the nf_isproperty flag (if any) from left, so that in case it }
+ { is a property which refers to a field without a setter call, we will not get }
+ { an error about trying to pass a property as a var parameter }
+ exclude(left.flags,nf_isproperty);
+ hp:=ccallparanode.create(ctypeconvnode.create_internal(right,voidpointertype),
+ ccallparanode.create(ctypeconvnode.create_internal(left,voidpointertype),
+ nil));
+ if needrtti then
+ hp:=ccallparanode.create(
+ caddrnode.create_internal(
+ crttinode.create(tstoreddef(left.resultdef),initrtti,rdt_normal)),
+ hp);
+ result:=ccallnode.createintern(hs,hp);
+ firstpass(result);
+ left:=nil;
+ right:=nil;
+ end;
+
+
+ function tassignmentnode.docompare(p: tnode): boolean;
+ begin
+ docompare :=
+ inherited docompare(p) and
+ (assigntype = tassignmentnode(p).assigntype);
+ end;
+
+{$ifdef state_tracking}
+ function Tassignmentnode.track_state_pass(exec_known:boolean):boolean;
+
+ var se:Tstate_entry;
+
+ begin
+ track_state_pass:=false;
+ if exec_known then
+ begin
+ track_state_pass:=right.track_state_pass(exec_known);
+ {Force a new resultdef pass.}
+ right.resultdef:=nil;
+ do_typecheckpass(right);
+ typecheckpass(right);
+ aktstate.store_fact(left.getcopy,right.getcopy);
+ end
+ else
+ aktstate.delete_fact(left);
+ end;
+{$endif}
+
+
+{*****************************************************************************
+ TARRAYCONSTRUCTORRANGENODE
+*****************************************************************************}
+
+ constructor tarrayconstructorrangenode.create(l,r : tnode);
+
+ begin
+ inherited create(arrayconstructorrangen,l,r);
+ end;
+
+ function tarrayconstructorrangenode.pass_typecheck:tnode;
+ begin
+ result:=nil;
+ typecheckpass(left);
+ typecheckpass(right);
+ set_varstate(left,vs_read,[vsf_must_be_valid]);
+ set_varstate(right,vs_read,[vsf_must_be_valid]);
+ if codegenerror then
+ exit;
+ resultdef:=left.resultdef;
+ end;
+
+
+ function tarrayconstructorrangenode.pass_1 : tnode;
+ begin
+ result:=nil;
+ CGMessage(parser_e_illegal_expression);
+ end;
+
+
+{****************************************************************************
+ TARRAYCONSTRUCTORNODE
+*****************************************************************************}
+
+ constructor tarrayconstructornode.create(l,r : tnode);
+ begin
+ inherited create(arrayconstructorn,l,r);
+ end;
+
+
+ function tarrayconstructornode.dogetcopy : tnode;
+ var
+ n : tarrayconstructornode;
+ begin
+ n:=tarrayconstructornode(inherited dogetcopy);
+ result:=n;
+ end;
+
+
+ function tarrayconstructornode.pass_typecheck:tnode;
+ var
+ hdef : tdef;
+ hp : tarrayconstructornode;
+ len : longint;
+ varia : boolean;
+ eq : tequaltype;
+ hnodetype : tnodetype;
+ begin
+ result:=nil;
+
+ { are we allowing array constructor? Then convert it to a set.
+ Do this only if we didn't convert the arrayconstructor yet. This
+ is needed for the cases where the resultdef is forced for a second
+ run }
+ if not(allow_array_constructor) then
+ begin
+ hp:=tarrayconstructornode(getcopy);
+ arrayconstructor_to_set(tnode(hp));
+ result:=hp;
+ exit;
+ end;
+
+ { only pass left tree, right tree contains next construct if any }
+ hdef:=nil;
+ hnodetype:=errorn;
+ len:=0;
+ varia:=false;
+ if assigned(left) then
+ begin
+ hp:=self;
+ while assigned(hp) do
+ begin
+ typecheckpass(hp.left);
+ set_varstate(hp.left,vs_read,[vsf_must_be_valid]);
+ if (hdef=nil) then
+ begin
+ hdef:=hp.left.resultdef;
+ hnodetype:=hp.left.nodetype;
+ end
+ else
+ begin
+ { If we got a niln we don't know the type yet and need to take the
+ type of the next array element.
+ This is to handle things like [nil,tclass,tclass], see also tw8371 (PFV) }
+ if hnodetype=niln then
+ begin
+ eq:=compare_defs(hp.left.resultdef,hdef,hnodetype);
+ if eq>te_incompatible then
+ begin
+ hdef:=hp.left.resultdef;
+ hnodetype:=hp.left.nodetype;
+ end;
+ end
+ else
+ eq:=compare_defs(hdef,hp.left.resultdef,hp.left.nodetype);
+ if (not varia) and (eq<te_equal) then
+ begin
+ { If both are integers we need to take the type that can hold both
+ defs }
+ if is_integer(hdef) and is_integer(hp.left.resultdef) then
+ begin
+ if is_in_limit(hdef,hp.left.resultdef) then
+ hdef:=hp.left.resultdef;
+ end
+ else
+ if (nf_novariaallowed in flags) then
+ varia:=true;
+ end;
+ end;
+ inc(len);
+ hp:=tarrayconstructornode(hp.right);
+ end;
+ end;
+ { Set the type of empty or varia arrays to void. Also
+ do this if the type is array of const/open array
+ because those can't be used with setelementdef }
+ if not assigned(hdef) or
+ varia or
+ is_array_of_const(hdef) or
+ is_open_array(hdef) then
+ hdef:=voidtype;
+ resultdef:=tarraydef.create(0,len-1,s32inttype);
+ tarraydef(resultdef).elementdef:=hdef;
+ include(tarraydef(resultdef).arrayoptions,ado_IsConstructor);
+ if varia then
+ include(tarraydef(resultdef).arrayoptions,ado_IsVariant);
+ end;
+
+
+ procedure tarrayconstructornode.force_type(def:tdef);
+ var
+ hp : tarrayconstructornode;
+ begin
+ tarraydef(resultdef).elementdef:=def;
+ include(tarraydef(resultdef).arrayoptions,ado_IsConstructor);
+ exclude(tarraydef(resultdef).arrayoptions,ado_IsVariant);
+ if assigned(left) then
+ begin
+ hp:=self;
+ while assigned(hp) do
+ begin
+ inserttypeconv(hp.left,def);
+ hp:=tarrayconstructornode(hp.right);
+ end;
+ end;
+ end;
+
+
+ procedure tarrayconstructornode.insert_typeconvs;
+ var
+ hp : tarrayconstructornode;
+ dovariant : boolean;
+ begin
+ dovariant:=(nf_forcevaria in flags) or (ado_isvariant in tarraydef(resultdef).arrayoptions);
+ { only pass left tree, right tree contains next construct if any }
+ if assigned(left) then
+ begin
+ hp:=self;
+ while assigned(hp) do
+ begin
+ typecheckpass(hp.left);
+ { Insert typeconvs for array of const }
+ if dovariant then
+ { at this time C varargs are no longer an arrayconstructornode }
+ insert_varargstypeconv(hp.left,false);
+ hp:=tarrayconstructornode(hp.right);
+ end;
+ end;
+ end;
+
+
+ function tarrayconstructornode.pass_1 : tnode;
+ var
+ hp : tarrayconstructornode;
+ do_variant:boolean;
+ begin
+ do_variant:=(nf_forcevaria in flags) or (ado_isvariant in tarraydef(resultdef).arrayoptions);
+ result:=nil;
+ { Insert required type convs, this must be
+ done in pass 1, because the call must be
+ typecheckpassed already }
+ if assigned(left) then
+ begin
+ insert_typeconvs;
+ { call firstpass for all nodes }
+ hp:=self;
+ while assigned(hp) do
+ begin
+ if hp.left<>nil then
+ begin
+ {This check is pessimistic; a call will happen depending
+ on the location in which the elements will be found in
+ pass 2.}
+ if not do_variant then
+ include(current_procinfo.flags,pi_do_call);
+ firstpass(hp.left);
+ end;
+ hp:=tarrayconstructornode(hp.right);
+ end;
+ end;
+ expectloc:=LOC_CREFERENCE;
+ end;
+
+
+ function tarrayconstructornode.docompare(p: tnode): boolean;
+ begin
+ docompare:=inherited docompare(p);
+ end;
+
+
+{*****************************************************************************
+ TTYPENODE
+*****************************************************************************}
+
+ constructor ttypenode.create(def:tdef);
+ begin
+ inherited create(typen);
+ typedef:=def;
+ typesym:=def.typesym;
+ allowed:=false;
+ helperallowed:=false;
+ end;
+
+
+ constructor ttypenode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ ppufile.getderef(typedefderef);
+ ppufile.getderef(typesymderef);
+ allowed:=boolean(ppufile.getbyte);
+ helperallowed:=boolean(ppufile.getbyte);
+ end;
+
+
+ procedure ttypenode.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putderef(typedefderef);
+ ppufile.putderef(typesymderef);
+ ppufile.putbyte(byte(allowed));
+ ppufile.putbyte(byte(helperallowed));
+ end;
+
+
+ procedure ttypenode.buildderefimpl;
+ begin
+ inherited buildderefimpl;
+ typedefderef.build(typedef);
+ typesymderef.build(typesym);
+ end;
+
+
+ procedure ttypenode.derefimpl;
+ begin
+ inherited derefimpl;
+ typedef:=tdef(typedefderef.resolve);
+ typesym:=tsym(typesymderef.resolve);
+ end;
+
+
+ function ttypenode.pass_typecheck:tnode;
+ begin
+ result:=nil;
+ resultdef:=typedef;
+ { check if it's valid }
+ if typedef.typ = errordef then
+ CGMessage(parser_e_illegal_expression);
+ end;
+
+
+ function ttypenode.pass_1 : tnode;
+ begin
+ result:=nil;
+ expectloc:=LOC_VOID;
+ { a typenode can't generate code, so we give here
+ an error. Else it'll be an abstract error in pass_generate_code.
+ Only when the allowed flag is set we don't generate
+ an error }
+ if not allowed then
+ Message(parser_e_no_type_not_allowed_here);
+ if not helperallowed and is_objectpascal_helper(typedef) then
+ Message(parser_e_no_category_as_types);
+ end;
+
+
+ function ttypenode.dogetcopy : tnode;
+ var
+ n : ttypenode;
+ begin
+ n:=ttypenode(inherited dogetcopy);
+ n.allowed:=allowed;
+ n.typedef:=typedef;
+ n.helperallowed:=helperallowed;
+ result:=n;
+ end;
+
+
+ function ttypenode.docompare(p: tnode): boolean;
+ begin
+ docompare :=
+ inherited docompare(p);
+ end;
+
+
+{*****************************************************************************
+ TRTTINODE
+*****************************************************************************}
+
+
+ constructor trttinode.create(def:tstoreddef;rt:trttitype;dt:Trttidatatype);
+ begin
+ inherited create(rttin);
+ rttidef:=def;
+ rttitype:=rt;
+ rttidatatype:=dt;
+ end;
+
+
+ constructor trttinode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ ppufile.getderef(rttidefderef);
+ rttitype:=trttitype(ppufile.getbyte);
+ rttidatatype:=trttidatatype(ppufile.getbyte);
+ end;
+
+
+ procedure trttinode.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putderef(rttidefderef);
+ ppufile.putbyte(byte(rttitype));
+ ppufile.putbyte(byte(rttidatatype));
+ end;
+
+
+ procedure trttinode.buildderefimpl;
+ begin
+ inherited buildderefimpl;
+ rttidefderef.build(rttidef);
+ end;
+
+
+ procedure trttinode.derefimpl;
+ begin
+ inherited derefimpl;
+ rttidef:=tstoreddef(rttidefderef.resolve);
+ end;
+
+
+ function trttinode.dogetcopy : tnode;
+ var
+ n : trttinode;
+ begin
+ n:=trttinode(inherited dogetcopy);
+ n.rttidef:=rttidef;
+ n.rttitype:=rttitype;
+ n.rttidatatype:=rttidatatype;
+ result:=n;
+ end;
+
+
+ function trttinode.pass_typecheck:tnode;
+ begin
+ { rtti information will be returned as a void pointer }
+ result:=nil;
+ resultdef:=voidpointertype;
+ end;
+
+
+ function trttinode.pass_1 : tnode;
+ begin
+ result:=nil;
+ expectloc:=LOC_CREFERENCE;
+ end;
+
+
+ function trttinode.docompare(p: tnode): boolean;
+ begin
+ docompare :=
+ inherited docompare(p) and
+ (rttidef = trttinode(p).rttidef) and
+ (rttitype = trttinode(p).rttitype);
+ end;
+
+end.
diff --git a/closures/compiler/nmat.pas b/closures/compiler/nmat.pas
new file mode 100644
index 0000000000..2286a12598
--- /dev/null
+++ b/closures/compiler/nmat.pas
@@ -0,0 +1,1131 @@
+{
+ Copyright (c) 2000-2005 by Florian Klaempfl
+
+ Type checking and register allocation for math nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit nmat;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node;
+
+ type
+ tmoddivnode = class(tbinopnode)
+ function pass_1 : tnode;override;
+ function pass_typecheck:tnode;override;
+ function simplify(forinline : boolean) : tnode;override;
+ protected
+{$ifndef cpu64bitalu}
+ { override the following if you want to implement }
+ { parts explicitely in the code generator (JM) }
+ function first_moddiv64bitint: tnode; virtual;
+{$endif not cpu64bitalu}
+ function firstoptimize: tnode; virtual;
+ function first_moddivint: tnode; virtual;
+ end;
+ tmoddivnodeclass = class of tmoddivnode;
+
+ tshlshrnode = class(tbinopnode)
+ function pass_1 : tnode;override;
+ function pass_typecheck:tnode;override;
+ function simplify(forinline : boolean) : tnode;override;
+{$ifndef cpu64bitalu}
+ { override the following if you want to implement }
+ { parts explicitely in the code generator (CEC)
+ Should return nil, if everything will be handled
+ in the code generator
+ }
+ function first_shlshr64bitint: tnode; virtual;
+{$endif not cpu64bitalu}
+ end;
+ tshlshrnodeclass = class of tshlshrnode;
+
+ tunaryminusnode = class(tunarynode)
+ constructor create(expr : tnode);virtual;
+ function pass_1 : tnode;override;
+ function pass_typecheck:tnode;override;
+ function simplify(forinline : boolean) : tnode;override;
+ end;
+ tunaryminusnodeclass = class of tunaryminusnode;
+
+ tunaryplusnode = class(tunarynode)
+ constructor create(expr : tnode);virtual;
+ function pass_1 : tnode;override;
+ function pass_typecheck:tnode;override;
+ end;
+ tunaryplusnodeclass = class of tunaryplusnode;
+
+ tnotnode = class(tunarynode)
+ constructor create(expr : tnode);virtual;
+ function pass_1 : tnode;override;
+ function pass_typecheck:tnode;override;
+ function simplify(forinline : boolean) : tnode;override;
+ {$ifdef state_tracking}
+ function track_state_pass(exec_known:boolean):boolean;override;
+ {$endif}
+ end;
+ tnotnodeclass = class of tnotnode;
+
+ var
+ cmoddivnode : tmoddivnodeclass = tmoddivnode;
+ cshlshrnode : tshlshrnodeclass = tshlshrnode;
+ cunaryminusnode : tunaryminusnodeclass = tunaryminusnode;
+ cunaryplusnode : tunaryplusnodeclass = tunaryplusnode;
+ cnotnode : tnotnodeclass = tnotnode;
+
+implementation
+
+ uses
+ systems,
+ verbose,globals,cutils,
+ globtype,constexp,
+ symconst,symtype,symdef,symtable,
+ defutil,
+ htypechk,pass_1,
+ cgbase,
+ ncon,ncnv,ncal,nadd,nld,nbas,nflw,ninl,
+ nutils;
+
+{****************************************************************************
+ TMODDIVNODE
+ ****************************************************************************}
+
+ function tmoddivnode.simplify(forinline : boolean):tnode;
+ var
+ rv,lv : tconstexprint;
+ begin
+ result:=nil;
+
+ if is_constintnode(right) then
+ begin
+ rv:=tordconstnode(right).value;
+ if rv = 1 then
+ begin
+ case nodetype of
+ modn:
+ result := cordconstnode.create(0,left.resultdef,true);
+ divn:
+ result := left.getcopy;
+ end;
+ exit;
+ end;
+ if rv = 0 then
+ begin
+ Message(parser_e_division_by_zero);
+ { recover }
+ tordconstnode(right).value := 1;
+ end;
+ if (nf_isomod in flags) and
+ (rv<=0) then
+ begin
+ Message(cg_e_mod_only_defined_for_pos_quotient);
+ { recover }
+ tordconstnode(right).value := 1;
+ end;
+ end;
+
+ if is_constintnode(right) and is_constintnode(left) then
+ begin
+ rv:=tordconstnode(right).value;
+ lv:=tordconstnode(left).value;
+
+ case nodetype of
+ modn:
+ if nf_isomod in flags then
+ begin
+ if lv>=0 then
+ result:=create_simplified_ord_const(lv mod rv,resultdef,forinline)
+ else
+ if ((-lv) mod rv)=0 then
+ result:=create_simplified_ord_const((-lv) mod rv,resultdef,forinline)
+ else
+ result:=create_simplified_ord_const(rv-((-lv) mod rv),resultdef,forinline);
+ end
+ else
+ result:=create_simplified_ord_const(lv mod rv,resultdef,forinline);
+ divn:
+ result:=create_simplified_ord_const(lv div rv,resultdef,forinline);
+ end;
+ end;
+ end;
+
+
+ function tmoddivnode.pass_typecheck:tnode;
+ var
+ else_block,
+ hp,t : tnode;
+ rd,ld : torddef;
+ else_statements,
+ statements : tstatementnode;
+ result_data : ttempcreatenode;
+ begin
+ result:=nil;
+ typecheckpass(left);
+ typecheckpass(right);
+ set_varstate(left,vs_read,[vsf_must_be_valid]);
+ set_varstate(right,vs_read,[vsf_must_be_valid]);
+ if codegenerror then
+ exit;
+
+ { tp procvar support }
+ maybe_call_procvar(left,true);
+ maybe_call_procvar(right,true);
+
+ result:=simplify(false);
+ if assigned(result) then
+ exit;
+
+ { allow operator overloading }
+ t:=self;
+ if isbinaryoverloaded(t) then
+ begin
+ result:=t;
+ exit;
+ end;
+
+ { we need 2 orddefs always }
+ if (left.resultdef.typ<>orddef) then
+ inserttypeconv(right,sinttype);
+ if (right.resultdef.typ<>orddef) then
+ inserttypeconv(right,sinttype);
+ if codegenerror then
+ exit;
+
+ rd:=torddef(right.resultdef);
+ ld:=torddef(left.resultdef);
+
+ { if one operand is a cardinal and the other is a positive constant, convert the }
+ { constant to a cardinal as well so we don't have to do a 64bit division (JM) }
+ { Do the same for qwords and positive constants as well, otherwise things like }
+ { "qword mod 10" are evaluated with int64 as result, which is wrong if the }
+ { "qword" was > high(int64) (JM) }
+ { Additionally, do the same for cardinal/qwords and other positive types, but }
+ { always in a way that a smaller type is converted to a bigger type }
+ { (webtbs/tw8870) }
+ if (rd.ordtype in [u32bit,u64bit]) and
+ ((is_constintnode(left) and
+ (tordconstnode(left).value >= 0)) or
+ (not is_signed(ld) and
+ (rd.size >= ld.size))) then
+ begin
+ inserttypeconv(left,right.resultdef);
+ ld:=torddef(left.resultdef);
+ end;
+ if (ld.ordtype in [u32bit,u64bit]) and
+ ((is_constintnode(right) and
+ (tordconstnode(right).value >= 0)) or
+ (not is_signed(rd) and
+ (ld.size >= rd.size))) then
+ begin
+ inserttypeconv(right,left.resultdef);
+ rd:=torddef(right.resultdef);
+ end;
+
+ { when there is one currency value, everything is done
+ using currency }
+ if (ld.ordtype=scurrency) or
+ (rd.ordtype=scurrency) then
+ begin
+ if (ld.ordtype<>scurrency) then
+ inserttypeconv(left,s64currencytype);
+ if (rd.ordtype<>scurrency) then
+ inserttypeconv(right,s64currencytype);
+ resultdef:=left.resultdef;
+ end
+ else
+{$ifndef cpu64bitaddr}
+ { when there is one 64bit value, everything is done
+ in 64bit }
+ if (is_64bitint(left.resultdef) or
+ is_64bitint(right.resultdef)) then
+ begin
+ if is_signed(rd) or is_signed(ld) then
+ begin
+ if (ld.ordtype<>s64bit) then
+ inserttypeconv(left,s64inttype);
+ if (rd.ordtype<>s64bit) then
+ inserttypeconv(right,s64inttype);
+ end
+ else
+ begin
+ if (ld.ordtype<>u64bit) then
+ inserttypeconv(left,u64inttype);
+ if (rd.ordtype<>u64bit) then
+ inserttypeconv(right,u64inttype);
+ end;
+ resultdef:=left.resultdef;
+ end
+ else
+ { when mixing cardinals and signed numbers, convert everythign to 64bit (JM) }
+ if ((rd.ordtype = u32bit) and
+ is_signed(ld)) or
+ ((ld.ordtype = u32bit) and
+ is_signed(rd)) then
+ begin
+ CGMessage(type_h_mixed_signed_unsigned);
+ if (ld.ordtype<>s64bit) then
+ inserttypeconv(left,s64inttype);
+ if (rd.ordtype<>s64bit) then
+ inserttypeconv(right,s64inttype);
+ resultdef:=left.resultdef;
+ end
+ else
+{$endif not cpu64bitaddr}
+ begin
+ { Make everything always default singed int }
+ if not(rd.ordtype in [torddef(sinttype).ordtype,torddef(uinttype).ordtype]) then
+ inserttypeconv(right,sinttype);
+ if not(ld.ordtype in [torddef(sinttype).ordtype,torddef(uinttype).ordtype]) then
+ inserttypeconv(left,sinttype);
+ resultdef:=right.resultdef;
+ end;
+
+ { when the result is currency we need some extra code for
+ division. this should not be done when the divn node is
+ created internally }
+ if (nodetype=divn) and
+ not(nf_is_currency in flags) and
+ is_currency(resultdef) then
+ begin
+ hp:=caddnode.create(muln,getcopy,cordconstnode.create(10000,s64currencytype,false));
+ include(hp.flags,nf_is_currency);
+ result:=hp;
+ end;
+
+ if (nodetype=modn) and (nf_isomod in flags) then
+ begin
+ result:=internalstatements(statements);
+ else_block:=internalstatements(else_statements);
+ result_data:=ctempcreatenode.create(resultdef,resultdef.size,tt_persistent,true);
+
+ { right <=0? }
+ addstatement(statements,cifnode.create(caddnode.create(lten,right.getcopy,cordconstnode.create(0,resultdef,false)),
+ { then: result:=left mod right }
+ ccallnode.createintern('fpc_divbyzero',nil),
+ nil
+ ));
+
+ { prepare else block }
+ { result:=(-left) mod right }
+ addstatement(else_statements,cassignmentnode.create(ctemprefnode.create(result_data),cmoddivnode.create(modn,cunaryminusnode.create(left.getcopy),right.getcopy)));
+ { result<>0? }
+ addstatement(else_statements,cifnode.create(caddnode.create(unequaln,ctemprefnode.create(result_data),cordconstnode.create(0,resultdef,false)),
+ { then: result:=right-result }
+ cassignmentnode.create(ctemprefnode.create(result_data),caddnode.create(subn,right.getcopy,ctemprefnode.create(result_data))),
+ nil
+ ));
+
+ addstatement(statements,result_data);
+ { if left>=0 }
+ addstatement(statements,cifnode.create(caddnode.create(gten,left.getcopy,cordconstnode.create(0,resultdef,false)),
+ { then: result:=left mod right }
+ cassignmentnode.create(ctemprefnode.create(result_data),cmoddivnode.create(modn,left.getcopy,right.getcopy)),
+ { else block }
+ else_block
+ ));
+
+ addstatement(statements,ctempdeletenode.create_normal_temp(result_data));
+ addstatement(statements,ctemprefnode.create(result_data));
+ end;
+ end;
+
+
+ function tmoddivnode.first_moddivint: tnode;
+{$ifdef cpuneedsdiv32helper}
+ var
+ procname: string[31];
+ begin
+ result := nil;
+
+ { otherwise create a call to a helper }
+ if nodetype = divn then
+ procname := 'fpc_div_'
+ else
+ procname := 'fpc_mod_';
+ { only qword needs the unsigned code, the
+ signed code is also used for currency }
+ if is_signed(resultdef) then
+ procname := procname + 'longint'
+ else
+ procname := procname + 'dword';
+
+ result := ccallnode.createintern(procname,ccallparanode.create(left,
+ ccallparanode.create(right,nil)));
+ left := nil;
+ right := nil;
+ firstpass(result);
+ end;
+{$else cpuneedsdiv32helper}
+ begin
+ result:=nil;
+ end;
+{$endif cpuneedsdiv32helper}
+
+
+{$ifndef cpu64bitalu}
+ function tmoddivnode.first_moddiv64bitint: tnode;
+ var
+ procname: string[31];
+ begin
+ result := nil;
+
+ { when currency is used set the result of the
+ parameters to s64bit, so they are not converted }
+ if is_currency(resultdef) then
+ begin
+ left.resultdef:=s64inttype;
+ right.resultdef:=s64inttype;
+ end;
+
+ { otherwise create a call to a helper }
+ if nodetype = divn then
+ procname := 'fpc_div_'
+ else
+ procname := 'fpc_mod_';
+ { only qword needs the unsigned code, the
+ signed code is also used for currency }
+ if is_signed(resultdef) then
+ procname := procname + 'int64'
+ else
+ procname := procname + 'qword';
+
+ result := ccallnode.createintern(procname,ccallparanode.create(left,
+ ccallparanode.create(right,nil)));
+ left := nil;
+ right := nil;
+ firstpass(result);
+ end;
+{$endif not cpu64bitalu}
+
+
+ function tmoddivnode.firstoptimize: tnode;
+ var
+ power,shiftval : longint;
+ newtype: tnodetype;
+ statements : tstatementnode;
+ temp : ttempcreatenode;
+ begin
+ result := nil;
+ { divide/mod a number by a constant which is a power of 2? }
+ if (right.nodetype = ordconstn) and
+{$ifdef cpu64bitalu}
+ { for 64 bit, we leave the optimization to the cg }
+ (not is_signed(resultdef)) and
+{$else cpu64bitalu}
+ ((nodetype=divn) and (is_64bit(resultdef)) or
+ not is_signed(resultdef)) and
+{$endif cpu64bitalu}
+ ispowerof2(tordconstnode(right).value,power) then
+ begin
+ if nodetype=divn then
+ begin
+ if is_signed(resultdef) then
+ begin
+ if is_64bitint(left.resultdef) then
+ if not (cs_opt_size in current_settings.optimizerswitches) then
+ shiftval:=63
+ else
+ { the shift code is a lot bigger than the call to }
+ { the divide helper }
+ exit
+ else
+ shiftval:=31;
+
+ result:=internalstatements(statements);
+ temp:=ctempcreatenode.create(left.resultdef,left.resultdef.size,tt_persistent,true);
+ addstatement(statements,temp);
+ addstatement(statements,cassignmentnode.create(ctemprefnode.create(temp),
+ left));
+ left:=nil;
+
+ addstatement(statements,ccallnode.createintern('fpc_sarint64',
+ ccallparanode.create(cordconstnode.create(power,u8inttype,false),
+ ccallparanode.create(caddnode.create(addn,ctemprefnode.create(temp),
+ caddnode.create(andn,
+ ccallnode.createintern('fpc_sarint64',
+ ccallparanode.create(cordconstnode.create(shiftval,u8inttype,false),
+ ccallparanode.create(ctemprefnode.create(temp),nil))
+ ),
+ cordconstnode.create(tordconstnode(right).value-1,
+ right.resultdef,false)
+ )),nil
+ )))
+ );
+ end
+ else
+ begin
+ tordconstnode(right).value:=power;
+ result:=cshlshrnode.create(shrn,left,right)
+ end;
+ end
+ else
+ begin
+ dec(tordconstnode(right).value.uvalue);
+ result := caddnode.create(andn,left,right);
+ end;
+ { left and right are reused }
+ left := nil;
+ right := nil;
+ firstpass(result);
+ exit;
+ end;
+ end;
+
+
+ function tmoddivnode.pass_1 : tnode;
+ begin
+ result:=nil;
+ firstpass(left);
+ firstpass(right);
+ if codegenerror then
+ exit;
+
+ { Try to optimize mod/div }
+ result := firstoptimize;
+ if assigned(result) then
+ exit;
+
+{$ifndef cpu64bitalu}
+ { 64bit }
+ if (left.resultdef.typ=orddef) and
+ (right.resultdef.typ=orddef) and
+ (is_64bitint(left.resultdef) or is_64bitint(right.resultdef)) then
+ begin
+ result := first_moddiv64bitint;
+ if assigned(result) then
+ exit;
+ expectloc:=LOC_REGISTER;
+ end
+ else
+{$endif not cpu64bitalu}
+ begin
+ result := first_moddivint;
+ if assigned(result) then
+ exit;
+ end;
+ expectloc:=LOC_REGISTER;
+ end;
+
+
+
+{****************************************************************************
+ TSHLSHRNODE
+ ****************************************************************************}
+
+ function tshlshrnode.simplify(forinline : boolean):tnode;
+ begin
+ result:=nil;
+ { constant folding }
+ if is_constintnode(left) and is_constintnode(right) then
+ begin
+ case nodetype of
+ shrn:
+ result:=create_simplified_ord_const(tordconstnode(left).value shr tordconstnode(right).value,resultdef,forinline);
+ shln:
+ result:=create_simplified_ord_const(tordconstnode(left).value shl tordconstnode(right).value,resultdef,forinline);
+ end;
+ end;
+
+ end;
+
+
+ function tshlshrnode.pass_typecheck:tnode;
+ var
+ t : tnode;
+{$ifdef cpunodefaultint}
+ nd : tdef;
+{$endif cpunodefaultint}
+ begin
+ result:=nil;
+ typecheckpass(left);
+ typecheckpass(right);
+ set_varstate(right,vs_read,[vsf_must_be_valid]);
+ set_varstate(left,vs_read,[vsf_must_be_valid]);
+ if codegenerror then
+ exit;
+
+ { tp procvar support }
+ maybe_call_procvar(left,true);
+ maybe_call_procvar(right,true);
+
+ result:=simplify(false);
+ if assigned(result) then
+ exit;
+
+ { allow operator overloading }
+ t:=self;
+ if isbinaryoverloaded(t) then
+ begin
+ result:=t;
+ exit;
+ end;
+
+{$ifdef cpunodefaultint}
+ { for small cpus we use the smallest common type }
+ if (left.resultdef.typ=orddef) and (right.resultdef.typ=orddef) then
+ nd:=get_common_intdef(torddef(left.resultdef),torddef(right.resultdef),false)
+ else
+ nd:=s32inttype;
+{$endif cpunodefaultint}
+
+ { calculations for ordinals < 32 bit have to be done in
+ 32 bit for backwards compatibility. That way 'shl 33' is
+ the same as 'shl 1'. It's ugly but compatible with delphi/tp/gcc }
+ if (not is_64bit(left.resultdef)) and
+ (torddef(left.resultdef).ordtype<>u32bit) then
+ begin
+ { keep singness of orignal type }
+ if is_signed(left.resultdef) then
+{$ifdef cpunodefaultint}
+ inserttypeconv(left,nd)
+{$else cpunodefaultint}
+ inserttypeconv(left,s32inttype)
+{$endif cpunodefaultint}
+ else
+ begin
+{$ifdef cpunodefaultint}
+ inserttypeconv(left,nd)
+{$else cpunodefaultint}
+ inserttypeconv(left,u32inttype);
+{$endif cpunodefaultint}
+ end
+ end;
+
+{$ifdef cpunodefaultint}
+ inserttypeconv(right,nd);
+{$else cpunodefaultint}
+ inserttypeconv(right,sinttype);
+{$endif cpunodefaultint}
+
+ resultdef:=left.resultdef;
+ end;
+
+
+{$ifndef cpu64bitalu}
+ function tshlshrnode.first_shlshr64bitint: tnode;
+ var
+ procname: string[31];
+ begin
+ result := nil;
+ { Normally already done below, but called again,
+ just in case it is called directly }
+ firstpass(left);
+ { otherwise create a call to a helper }
+ if is_signed(left.resultdef) then
+ procname:='int64'
+ else
+ procname:='qword';
+ if nodetype = shln then
+ procname := 'fpc_shl_'+procname
+ else
+ procname := 'fpc_shr_'+procname;
+ { this order of parameters works at least for the arm,
+ however it should work for any calling conventions (FK) }
+ result := ccallnode.createintern(procname,ccallparanode.create(right,
+ ccallparanode.create(left,nil)));
+ left := nil;
+ right := nil;
+ firstpass(result);
+ end;
+{$endif not cpu64bitalu}
+
+
+ function tshlshrnode.pass_1 : tnode;
+ var
+ regs : longint;
+ begin
+ result:=nil;
+ firstpass(left);
+ firstpass(right);
+ if codegenerror then
+ exit;
+
+{$ifndef cpu64bitalu}
+ { 64 bit ints have their own shift handling }
+ if is_64bit(left.resultdef) then
+ begin
+ result := first_shlshr64bitint;
+ if assigned(result) then
+ exit;
+ regs:=2;
+ end
+ else
+{$endif not cpu64bitalu}
+ begin
+ regs:=1
+ end;
+
+ if (right.nodetype<>ordconstn) then
+ inc(regs);
+ expectloc:=LOC_REGISTER;
+ end;
+
+
+{****************************************************************************
+ TUNARYMINUSNODE
+ ****************************************************************************}
+
+ constructor tunaryminusnode.create(expr : tnode);
+ begin
+ inherited create(unaryminusn,expr);
+ end;
+
+
+ function tunaryminusnode.simplify(forinline : boolean):tnode;
+ begin
+ result:=nil;
+ { constant folding }
+ if is_constintnode(left) then
+ begin
+ result:=create_simplified_ord_const(-tordconstnode(left).value,resultdef,forinline);
+ exit;
+ end;
+ if is_constrealnode(left) then
+ begin
+ trealconstnode(left).value_real:=-trealconstnode(left).value_real;
+ trealconstnode(left).value_currency:=-trealconstnode(left).value_currency;
+ result:=left;
+ left:=nil;
+ exit;
+ end;
+ end;
+
+
+ function tunaryminusnode.pass_typecheck : tnode;
+ var
+ t : tnode;
+ begin
+ result:=nil;
+ typecheckpass(left);
+ set_varstate(left,vs_read,[vsf_must_be_valid]);
+ if codegenerror then
+ exit;
+
+ result:=simplify(false);
+ if assigned(result) then
+ exit;
+
+ resultdef:=left.resultdef;
+ if (left.resultdef.typ=floatdef) or
+ is_currency(left.resultdef) then
+ begin
+ end
+{$ifdef SUPPORT_MMX}
+ else if (cs_mmx in current_settings.localswitches) and
+ is_mmx_able_array(left.resultdef) then
+ begin
+ { if saturation is on, left.resultdef isn't
+ "mmx able" (FK)
+ if (cs_mmx_saturation in current_settings.localswitches^) and
+ (torddef(tarraydef(resultdef).definition).typ in
+ [s32bit,u32bit]) then
+ CGMessage(type_e_mismatch);
+ }
+ end
+{$endif SUPPORT_MMX}
+{$ifndef cpu64bitaddr}
+ else if is_64bit(left.resultdef) then
+ begin
+ inserttypeconv(left,s64inttype);
+ resultdef:=left.resultdef
+ end
+{$endif not cpu64bitaddr}
+ else if (left.resultdef.typ=orddef) then
+ begin
+ inserttypeconv(left,sinttype);
+ resultdef:=left.resultdef
+ end
+ else
+ begin
+ { allow operator overloading }
+ t:=self;
+ if isunaryoverloaded(t) then
+ begin
+ result:=t;
+ exit;
+ end;
+
+ CGMessage(type_e_mismatch);
+ end;
+ end;
+
+ { generic code }
+ { overridden by: }
+ { i386 }
+ function tunaryminusnode.pass_1 : tnode;
+ var
+ procname: string[31];
+ fdef : tdef;
+ begin
+ result:=nil;
+ firstpass(left);
+ if codegenerror then
+ exit;
+
+ if (cs_fp_emulation in current_settings.moduleswitches) and (left.resultdef.typ=floatdef) then
+ begin
+ if not(target_info.system in systems_wince) then
+ begin
+ case tfloatdef(resultdef).floattype of
+ s32real:
+ begin
+ procname:='float32_sub';
+ fdef:=search_system_type('FLOAT32REC').typedef;
+ end;
+ s64real:
+ begin
+ procname:='float64_sub';
+ fdef:=search_system_type('FLOAT64').typedef;
+ end;
+ {!!! not yet implemented
+ s128real:
+ }
+ else
+ internalerror(2005082801);
+ end;
+ result:=ctypeconvnode.create_internal(ccallnode.createintern(procname,ccallparanode.create(
+ ctypeconvnode.create_internal(left,fDef),
+ ccallparanode.create(ctypeconvnode.create_internal(crealconstnode.create(0,resultdef),fdef),nil))),resultdef);
+ end
+ else
+ begin
+ case tfloatdef(resultdef).floattype of
+ s32real:
+ procname:='NEGS';
+ s64real:
+ procname:='NEGD';
+ {!!! not yet implemented
+ s128real:
+ }
+ else
+ internalerror(2005082802);
+ end;
+ result:=ccallnode.createintern(procname,ccallparanode.create(left,nil));
+ end;
+
+ left:=nil;
+ end
+ else
+ begin
+ if (left.resultdef.typ=floatdef) then
+ expectloc:=LOC_FPUREGISTER
+{$ifdef SUPPORT_MMX}
+ else if (cs_mmx in current_settings.localswitches) and
+ is_mmx_able_array(left.resultdef) then
+ expectloc:=LOC_MMXREGISTER
+{$endif SUPPORT_MMX}
+ else if (left.resultdef.typ=orddef) then
+ expectloc:=LOC_REGISTER;
+ end;
+ end;
+
+{****************************************************************************
+ TUNARYPLUSNODE
+ ****************************************************************************}
+
+ constructor tunaryplusnode.create(expr: tnode);
+ begin
+ inherited create(unaryplusn,expr);
+ end;
+
+ function tunaryplusnode.pass_1: tnode;
+ begin
+ result:=nil;
+ { can never happen because all the conversions happen
+ in pass_typecheck }
+ internalerror(201012250);
+ end;
+
+ function tunaryplusnode.pass_typecheck: tnode;
+ var
+ t:tnode;
+ begin
+ result:=nil;
+ typecheckpass(left);
+ set_varstate(left,vs_read,[vsf_must_be_valid]);
+ if codegenerror then
+ exit;
+
+ if is_constintnode(left) or
+ is_constrealnode(left) or
+ (left.resultdef.typ=floatdef) or
+ is_currency(left.resultdef)
+{$ifdef SUPPORT_MMX}
+ or ((cs_mmx in current_settings.localswitches) and
+ is_mmx_able_array(left.resultdef))
+{$endif SUPPORT_MMX}
+ then
+ begin
+ result:=left;
+ left:=nil;
+ end
+{$ifndef cpu64bitaddr}
+ else if is_64bit(left.resultdef) then
+ begin
+ inserttypeconv(left,s64inttype);
+ result:=left;
+ left:=nil;
+ end
+{$endif not cpu64bitaddr}
+ else if (left.resultdef.typ=orddef) then
+ begin
+ inserttypeconv(left,sinttype);
+ result:=left;
+ left:=nil;
+ end
+ else
+ begin
+ { allow operator overloading }
+ t:=self;
+ if isunaryoverloaded(t) then
+ begin
+ result:=t;
+ exit;
+ end;
+
+ CGMessage(type_e_mismatch);
+ end;
+ end;
+
+
+{****************************************************************************
+ TNOTNODE
+ ****************************************************************************}
+
+ const
+ boolean_reverse:array[ltn..unequaln] of Tnodetype=(
+ gten,gtn,lten,ltn,unequaln,equaln
+ );
+
+ constructor tnotnode.create(expr : tnode);
+ begin
+ inherited create(notn,expr);
+ end;
+
+
+ function tnotnode.simplify(forinline : boolean):tnode;
+ var
+ v : tconstexprint;
+ t : tnode;
+ def : tdef;
+ begin
+ result:=nil;
+ { Try optmimizing ourself away }
+ if left.nodetype=notn then
+ begin
+ { Double not. Remove both }
+ result:=Tnotnode(left).left;
+ tnotnode(left).left:=nil;
+ exit;
+ end;
+
+ if (left.nodetype in [ltn,lten,equaln,unequaln,gtn,gten]) then
+ begin
+ { Not of boolean expression. Turn around the operator and remove
+ the not. This is not allowed for sets with the gten/lten,
+ because there is no ltn/gtn support }
+ if (taddnode(left).left.resultdef.typ<>setdef) or
+ (left.nodetype in [equaln,unequaln]) then
+ begin
+ result:=left;
+ left.nodetype:=boolean_reverse[left.nodetype];
+ left:=nil;
+ exit;
+ end;
+ end;
+
+ { constant folding }
+ if (left.nodetype=ordconstn) then
+ begin
+ v:=tordconstnode(left).value;
+ def:=left.resultdef;
+ case torddef(left.resultdef).ordtype of
+ pasbool8,
+ pasbool16,
+ pasbool32,
+ pasbool64,
+ bool8bit,
+ bool16bit,
+ bool32bit,
+ bool64bit:
+ begin
+ v:=byte(not(boolean(int64(v))));
+ if is_cbool(left.resultdef) then
+ v:=-v;
+ end;
+ uchar,
+ uwidechar,
+ u8bit,
+ s8bit,
+ u16bit,
+ s16bit,
+ s32bit,
+{$ifdef cpu64bitaddr}
+ u32bit,
+{$endif cpu64bitaddr}
+ s64bit:
+ begin
+ v:=int64(not int64(v));
+ if (torddef(left.resultdef).ordtype<>s64bit) then
+ def:=sinttype
+ else
+ def:=s64inttype;
+ end;
+{$ifndef cpu64bitaddr}
+ u32bit,
+{$endif not cpu64bitaddr}
+ u64bit :
+ begin
+ { Delphi-compatible: not dword = dword (not word = longint) }
+ { Extension: not qword = qword }
+ v:=qword(not qword(v));
+ { will be truncated by the ordconstnode for u32bit }
+ end;
+ else
+ CGMessage(type_e_mismatch);
+ end;
+ { not-nodes are not range checked by the code generator -> also
+ don't range check while inlining; the resultdef is a bit tricky
+ though: the node's resultdef gets changed in most cases compared
+ to left, but the not-operation itself is caried out in the code
+ generator using the size of left
+ }
+ if not(forinline) then
+ t:=cordconstnode.create(v,def,false)
+ else
+ begin
+ { cut off the value if necessary }
+ t:=cordconstnode.create(v,left.resultdef,false);
+ { now convert to node's resultdef }
+ inserttypeconv_explicit(t,def);
+ end;
+ result:=t;
+ exit;
+ end;
+ end;
+
+
+ function tnotnode.pass_typecheck : tnode;
+ var
+ t : tnode;
+ begin
+ result:=nil;
+ typecheckpass(left);
+ set_varstate(left,vs_read,[vsf_must_be_valid]);
+ if codegenerror then
+ exit;
+
+ { tp procvar support }
+ maybe_call_procvar(left,true);
+
+ resultdef:=left.resultdef;
+
+ result:=simplify(false);
+ if assigned(result) then
+ exit;
+
+ if is_boolean(resultdef) then
+ begin
+ end
+ else
+{$ifdef SUPPORT_MMX}
+ if (cs_mmx in current_settings.localswitches) and
+ is_mmx_able_array(left.resultdef) then
+ begin
+ end
+ else
+{$endif SUPPORT_MMX}
+{$ifndef cpu64bitaddr}
+ if is_64bitint(left.resultdef) then
+ begin
+ end
+ else
+{$endif not cpu64bitaddr}
+ if is_integer(left.resultdef) then
+ begin
+ end
+ else
+ begin
+ { allow operator overloading }
+ t:=self;
+ if isunaryoverloaded(t) then
+ begin
+ result:=t;
+ exit;
+ end;
+
+ CGMessage(type_e_mismatch);
+ end;
+ end;
+
+
+ function tnotnode.pass_1 : tnode;
+ begin
+ result:=nil;
+ firstpass(left);
+ if codegenerror then
+ exit;
+
+ expectloc:=left.expectloc;
+ if is_boolean(resultdef) then
+ begin
+ if (expectloc in [LOC_REFERENCE,LOC_CREFERENCE,LOC_CREGISTER]) then
+ expectloc:=LOC_REGISTER;
+ { before loading it into flags we need to load it into
+ a register thus 1 register is need PM }
+{$ifdef cpuflags}
+ if left.expectloc<>LOC_JUMP then
+ expectloc:=LOC_FLAGS;
+{$endif def cpuflags}
+ end
+ else
+{$ifdef SUPPORT_MMX}
+ if (cs_mmx in current_settings.localswitches) and
+ is_mmx_able_array(left.resultdef) then
+ expectloc:=LOC_MMXREGISTER
+ else
+{$endif SUPPORT_MMX}
+{$ifndef cpu64bitalu}
+ if is_64bit(left.resultdef) then
+ begin
+ if (expectloc in [LOC_REFERENCE,LOC_CREFERENCE,LOC_CREGISTER]) then
+ expectloc:=LOC_REGISTER;
+ end
+ else
+{$endif not cpu64bitalu}
+ if is_integer(left.resultdef) then
+ expectloc:=LOC_REGISTER;
+ end;
+
+{$ifdef state_tracking}
+ function Tnotnode.track_state_pass(exec_known:boolean):boolean;
+ begin
+ track_state_pass:=true;
+ if left.track_state_pass(exec_known) then
+ begin
+ left.resultdef:=nil;
+ do_typecheckpass(left);
+ end;
+ end;
+{$endif}
+
+end.
diff --git a/closures/compiler/nmem.pas b/closures/compiler/nmem.pas
new file mode 100644
index 0000000000..74a59544f1
--- /dev/null
+++ b/closures/compiler/nmem.pas
@@ -0,0 +1,1099 @@
+{
+ Copyright (c) 2000-2002 by Florian Klaempfl
+
+ Type checking and register allocation for memory related nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit nmem;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,
+ symdef,symsym,symtable,symtype;
+
+ type
+ tloadvmtaddrnode = class(tunarynode)
+ { unless this is for a call, we have to send the "class" message to
+ the objctype because the type information only gets initialized
+ after the first message has been sent -> crash if you pass an
+ uninitialized type to e.g. class_getInstanceSize() or so. No need
+ to save to/restore from ppu. }
+ forcall: boolean;
+ constructor create(l : tnode);virtual;
+ function pass_1 : tnode;override;
+ function pass_typecheck:tnode;override;
+ function docompare(p: tnode): boolean; override;
+ function dogetcopy: tnode; override;
+ end;
+ tloadvmtaddrnodeclass = class of tloadvmtaddrnode;
+
+ tloadparentfpnode = class(tunarynode)
+ parentpd : tprocdef;
+ parentpdderef : tderef;
+ constructor create(pd:tprocdef);virtual;
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderefimpl;override;
+ procedure derefimpl;override;
+ function pass_1 : tnode;override;
+ function pass_typecheck:tnode;override;
+ function docompare(p: tnode): boolean; override;
+ function dogetcopy : tnode;override;
+ end;
+ tloadparentfpnodeclass = class of tloadparentfpnode;
+
+ taddrnode = class(tunarynode)
+ getprocvardef : tprocvardef;
+ getprocvardefderef : tderef;
+ constructor create(l : tnode);virtual;
+ constructor create_internal(l : tnode); virtual;
+ constructor create_internal_nomark(l : tnode); virtual;
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure mark_write;override;
+ procedure buildderefimpl;override;
+ procedure derefimpl;override;
+ function docompare(p: tnode): boolean; override;
+ function dogetcopy : tnode;override;
+ function pass_1 : tnode;override;
+ function pass_typecheck:tnode;override;
+ private
+ mark_read_written: boolean;
+ end;
+ taddrnodeclass = class of taddrnode;
+
+ tderefnode = class(tunarynode)
+ constructor create(l : tnode);virtual;
+ function pass_1 : tnode;override;
+ function pass_typecheck:tnode;override;
+ procedure mark_write;override;
+ end;
+ tderefnodeclass = class of tderefnode;
+
+ tsubscriptnode = class(tunarynode)
+ vs : tfieldvarsym;
+ vsderef : tderef;
+ constructor create(varsym : tsym;l : tnode);virtual;
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderefimpl;override;
+ procedure derefimpl;override;
+ function dogetcopy : tnode;override;
+ function pass_1 : tnode;override;
+ function docompare(p: tnode): boolean; override;
+ function pass_typecheck:tnode;override;
+ procedure mark_write;override;
+ end;
+ tsubscriptnodeclass = class of tsubscriptnode;
+
+ tvecnode = class(tbinarynode)
+ constructor create(l,r : tnode);virtual;
+ function pass_1 : tnode;override;
+ function pass_typecheck:tnode;override;
+ procedure mark_write;override;
+ end;
+ tvecnodeclass = class of tvecnode;
+
+ twithnode = class(tunarynode)
+ constructor create(l:tnode);
+ destructor destroy;override;
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ function dogetcopy : tnode;override;
+ function pass_1 : tnode;override;
+ function docompare(p: tnode): boolean; override;
+ function pass_typecheck:tnode;override;
+ end;
+ twithnodeclass = class of twithnode;
+
+ var
+ cloadvmtaddrnode : tloadvmtaddrnodeclass= tloadvmtaddrnode;
+ caddrnode : taddrnodeclass= taddrnode;
+ cderefnode : tderefnodeclass= tderefnode;
+ csubscriptnode : tsubscriptnodeclass= tsubscriptnode;
+ cvecnode : tvecnodeclass= tvecnode;
+ cwithnode : twithnodeclass= twithnode;
+ cloadparentfpnode : tloadparentfpnodeclass = tloadparentfpnode;
+
+ function is_big_untyped_addrnode(p: tnode): boolean;
+
+implementation
+
+ uses
+ globtype,systems,constexp,
+ cutils,verbose,globals,
+ symconst,symbase,defutil,defcmp,
+ nbas,nutils,
+ wpobase,
+ htypechk,pass_1,ncal,nld,ncon,ncnv,cgbase,procinfo
+ ;
+
+{*****************************************************************************
+ TLOADVMTADDRNODE
+*****************************************************************************}
+
+ constructor tloadvmtaddrnode.create(l : tnode);
+ begin
+ inherited create(loadvmtaddrn,l);
+ end;
+
+
+ function tloadvmtaddrnode.pass_typecheck:tnode;
+ var
+ defaultresultdef : boolean;
+ begin
+ result:=nil;
+ typecheckpass(left);
+ if codegenerror then
+ exit;
+
+ case left.resultdef.typ of
+ classrefdef :
+ resultdef:=left.resultdef;
+ objectdef,
+ recorddef:
+ { access to the classtype while specializing? }
+ if (df_generic in left.resultdef.defoptions) then
+ begin
+ defaultresultdef:=true;
+ if assigned(current_structdef) then
+ begin
+ if assigned(current_structdef.genericdef) then
+ if current_structdef.genericdef=left.resultdef then
+ begin
+ resultdef:=tclassrefdef.create(current_structdef);
+ defaultresultdef:=false;
+ end
+ else
+ message(parser_e_cant_create_generics_of_this_type);
+ end
+ else
+ message(parser_e_cant_create_generics_of_this_type);
+ if defaultresultdef then
+ resultdef:=tclassrefdef.create(left.resultdef);
+ end
+ else
+ resultdef:=tclassrefdef.create(left.resultdef);
+ else
+ Message(parser_e_pointer_to_class_expected);
+ end;
+ end;
+
+
+ function tloadvmtaddrnode.docompare(p: tnode): boolean;
+ begin
+ result:=inherited docompare(p);
+ if result then
+ result:=forcall=tloadvmtaddrnode(p).forcall;
+ end;
+
+
+ function tloadvmtaddrnode.dogetcopy: tnode;
+ begin
+ result:=inherited dogetcopy;
+ tloadvmtaddrnode(result).forcall:=forcall;
+ end;
+
+
+ function tloadvmtaddrnode.pass_1 : tnode;
+ var
+ vs: tsym;
+ begin
+ result:=nil;
+ expectloc:=LOC_REGISTER;
+ if left.nodetype<>typen then
+ begin
+ { make sure that the isa field is loaded correctly in case
+ of the non-fragile ABI }
+ if is_objcclass(left.resultdef) and
+ (left.nodetype<>typen) then
+ begin
+ vs:=search_struct_member(tobjectdef(left.resultdef),'ISA');
+ if not assigned(vs) or
+ (tsym(vs).typ<>fieldvarsym) then
+ internalerror(2009092502);
+ result:=csubscriptnode.create(tfieldvarsym(vs),left);
+ inserttypeconv_internal(result,resultdef);
+ { reused }
+ left:=nil;
+ end
+ else
+ firstpass(left)
+ end
+ else if not is_objcclass(left.resultdef) and
+ not is_objcclassref(left.resultdef) then
+ begin
+ if not(nf_ignore_for_wpo in flags) and
+ (not assigned(current_procinfo) or
+ (po_inline in current_procinfo.procdef.procoptions) or
+ wpoinfomanager.symbol_live(current_procinfo.procdef.mangledname)) then
+ begin
+ { keep track of which classes might be instantiated via a classrefdef }
+ if (left.resultdef.typ=classrefdef) then
+ tobjectdef(tclassrefdef(left.resultdef).pointeddef).register_maybe_created_object_type
+ else if (left.resultdef.typ=objectdef) then
+ tobjectdef(left.resultdef).register_maybe_created_object_type
+ end
+ end
+ else if is_objcclass(left.resultdef) and
+ not(forcall) then
+ begin
+ { call "class" method (= "classclass" in FPC), because otherwise
+ we may use the class information before it has been
+ initialized }
+ vs:=search_struct_member(tobjectdef(left.resultdef),'CLASSCLASS');
+ if not assigned(vs) or
+ (vs.typ<>procsym) then
+ internalerror(2011080601);
+ { can't reuse "self", because it will be freed when we return }
+ result:=ccallnode.create(nil,tprocsym(vs),vs.owner,self.getcopy,[]);
+ end;
+ end;
+
+
+{*****************************************************************************
+ TLOADPARENTFPNODE
+*****************************************************************************}
+
+ constructor tloadparentfpnode.create(pd:tprocdef);
+ begin
+ inherited create(loadparentfpn,nil);
+ if not assigned(pd) then
+ internalerror(200309288);
+ if (pd.parast.symtablelevel>current_procinfo.procdef.parast.symtablelevel) then
+ internalerror(200309284);
+ parentpd:=pd;
+ end;
+
+
+ constructor tloadparentfpnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ ppufile.getderef(parentpdderef);
+ end;
+
+
+ procedure tloadparentfpnode.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putderef(parentpdderef);
+ end;
+
+
+ procedure tloadparentfpnode.buildderefimpl;
+ begin
+ inherited buildderefimpl;
+ parentpdderef.build(parentpd);
+ end;
+
+
+ procedure tloadparentfpnode.derefimpl;
+ begin
+ inherited derefimpl;
+ parentpd:=tprocdef(parentpdderef.resolve);
+ end;
+
+
+ function tloadparentfpnode.docompare(p: tnode): boolean;
+ begin
+ result:=
+ inherited docompare(p) and
+ (tloadparentfpnode(p).parentpd=parentpd);
+ end;
+
+
+ function tloadparentfpnode.dogetcopy : tnode;
+ var
+ p : tloadparentfpnode;
+ begin
+ p:=tloadparentfpnode(inherited dogetcopy);
+ p.parentpd:=parentpd;
+ dogetcopy:=p;
+ end;
+
+
+ function tloadparentfpnode.pass_typecheck:tnode;
+{$ifdef dummy}
+ var
+ currpi : tprocinfo;
+ hsym : tparavarsym;
+{$endif dummy}
+ begin
+ result:=nil;
+ resultdef:=voidpointertype;
+{$ifdef dummy}
+ { currently parentfps are never loaded in registers (FK) }
+ if (current_procinfo.procdef.parast.symtablelevel<>parentpd.parast.symtablelevel) then
+ begin
+ currpi:=current_procinfo;
+ { walk parents }
+ while (currpi.procdef.owner.symtablelevel>parentpd.parast.symtablelevel) do
+ begin
+ currpi:=currpi.parent;
+ if not assigned(currpi) then
+ internalerror(2005040602);
+ hsym:=tparavarsym(currpi.procdef.parast.Find('parentfp'));
+ if not assigned(hsym) then
+ internalerror(2005040601);
+ hsym.varregable:=vr_none;
+ end;
+ end;
+{$endif dummy}
+ end;
+
+
+ function tloadparentfpnode.pass_1 : tnode;
+ begin
+ result:=nil;
+ expectloc:=LOC_REGISTER;
+ end;
+
+
+{*****************************************************************************
+ TADDRNODE
+*****************************************************************************}
+
+ constructor taddrnode.create(l : tnode);
+
+ begin
+ inherited create(addrn,l);
+ getprocvardef:=nil;
+ mark_read_written := true;
+ end;
+
+
+ constructor taddrnode.create_internal(l : tnode);
+ begin
+ self.create(l);
+ include(flags,nf_internal);
+ end;
+
+
+ constructor taddrnode.create_internal_nomark(l : tnode);
+ begin
+ self.create_internal(l);
+ mark_read_written := false;
+ end;
+
+
+ constructor taddrnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ ppufile.getderef(getprocvardefderef);
+ end;
+
+
+ procedure taddrnode.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putderef(getprocvardefderef);
+ end;
+
+ procedure Taddrnode.mark_write;
+
+ begin
+ {@procvar:=nil is legal in Delphi mode.}
+ left.mark_write;
+ end;
+
+ procedure taddrnode.buildderefimpl;
+ begin
+ inherited buildderefimpl;
+ getprocvardefderef.build(getprocvardef);
+ end;
+
+
+ procedure taddrnode.derefimpl;
+ begin
+ inherited derefimpl;
+ getprocvardef:=tprocvardef(getprocvardefderef.resolve);
+ end;
+
+
+ function taddrnode.docompare(p: tnode): boolean;
+ begin
+ result:=
+ inherited docompare(p) and
+ (taddrnode(p).getprocvardef=getprocvardef);
+ end;
+
+
+ function taddrnode.dogetcopy : tnode;
+ var
+ p : taddrnode;
+ begin
+ p:=taddrnode(inherited dogetcopy);
+ p.getprocvardef:=getprocvardef;
+ dogetcopy:=p;
+ end;
+
+
+ function taddrnode.pass_typecheck:tnode;
+ var
+ hp : tnode;
+ hsym : tfieldvarsym;
+ isprocvar : boolean;
+ begin
+ result:=nil;
+ typecheckpass(left);
+ if codegenerror then
+ exit;
+
+ make_not_regable(left,[ra_addr_regable,ra_addr_taken]);
+
+ { don't allow constants, for internal use we also
+ allow taking the address of strings }
+ if is_constnode(left) and
+ not(
+ (nf_internal in flags) and
+ (left.nodetype in [stringconstn])
+ ) then
+ begin
+ CGMessagePos(left.fileinfo,type_e_no_addr_of_constant);
+ exit;
+ end;
+
+ { Handle @proc special, also @procvar in tp-mode needs
+ special handling }
+ if (left.resultdef.typ=procdef) or
+ (
+ (left.resultdef.typ=procvardef) and
+ ((m_tp_procvar in current_settings.modeswitches) or
+ (m_mac_procvar in current_settings.modeswitches))
+ ) then
+ begin
+ isprocvar:=(left.resultdef.typ=procvardef);
+
+ if not isprocvar then
+ begin
+ left:=ctypeconvnode.create_proc_to_procvar(left);
+ left.fileinfo:=fileinfo;
+ typecheckpass(left);
+ end;
+
+ { In tp procvar mode the result is always a voidpointer. Insert
+ a typeconversion to voidpointer. For methodpointers we need
+ to load the proc field }
+ if (m_tp_procvar in current_settings.modeswitches) or
+ (m_mac_procvar in current_settings.modeswitches) then
+ begin
+ if tabstractprocdef(left.resultdef).is_addressonly then
+ begin
+ result:=ctypeconvnode.create_internal(left,voidpointertype);
+ include(result.flags,nf_load_procvar);
+ left:=nil;
+ end
+ else
+ begin
+ { For procvars and for nested routines we need to return
+ the proc field of the methodpointer }
+ if isprocvar or
+ is_nested_pd(tabstractprocdef(left.resultdef)) then
+ begin
+ { find proc field in methodpointer record }
+ hsym:=tfieldvarsym(trecorddef(methodpointertype).symtable.Find('proc'));
+ if not assigned(hsym) then
+ internalerror(200412041);
+ { Load tmehodpointer(left).proc }
+ result:=csubscriptnode.create(
+ hsym,
+ ctypeconvnode.create_internal(left,methodpointertype));
+ left:=nil;
+ end
+ else
+ CGMessage(type_e_variable_id_expected);
+ end;
+ end
+ else
+ begin
+ { Return the typeconvn only }
+ result:=left;
+ left:=nil;
+ end;
+ end
+ else
+ begin
+ { what are we getting the address from an absolute sym? }
+ hp:=left;
+ while assigned(hp) and (hp.nodetype in [typeconvn,vecn,derefn,subscriptn]) do
+ hp:=tunarynode(hp).left;
+ if not assigned(hp) then
+ internalerror(200412042);
+{$ifdef i386}
+ if (hp.nodetype=loadn) and
+ ((tloadnode(hp).symtableentry.typ=absolutevarsym) and
+ tabsolutevarsym(tloadnode(hp).symtableentry).absseg) then
+ begin
+ if not(nf_typedaddr in flags) then
+ resultdef:=voidfarpointertype
+ else
+ resultdef:=tpointerdef.createfar(left.resultdef);
+ end
+ else
+{$endif i386}
+ if (hp.nodetype=loadn) and
+ (tloadnode(hp).symtableentry.typ=absolutevarsym) and
+{$ifdef i386}
+ not(tabsolutevarsym(tloadnode(hp).symtableentry).absseg) and
+{$endif i386}
+ (tabsolutevarsym(tloadnode(hp).symtableentry).abstyp=toaddr) then
+ begin
+ if nf_typedaddr in flags then
+ result:=cpointerconstnode.create(tabsolutevarsym(tloadnode(hp).symtableentry).addroffset,tpointerdef.create(left.resultdef))
+ else
+ result:=cpointerconstnode.create(tabsolutevarsym(tloadnode(hp).symtableentry).addroffset,voidpointertype);
+ exit;
+ end
+ else if (nf_internal in flags) or
+ valid_for_addr(left,true) then
+ begin
+ if not(nf_typedaddr in flags) then
+ resultdef:=voidpointertype
+ else
+ resultdef:=tpointerdef.create(left.resultdef);
+ end
+ else
+ CGMessage(type_e_variable_id_expected);
+ end;
+
+ if mark_read_written then
+ begin
+ { This is actually only "read", but treat it nevertheless as }
+ { modified due to the possible use of pointers }
+ { To avoid false positives regarding "uninitialised" }
+ { warnings when using arrays, perform it in two steps }
+ set_varstate(left,vs_written,[]);
+ { vsf_must_be_valid so it doesn't get changed into }
+ { vsf_referred_not_inited }
+ set_varstate(left,vs_read,[vsf_must_be_valid]);
+ end;
+ end;
+
+
+ function taddrnode.pass_1 : tnode;
+ begin
+ result:=nil;
+ firstpass(left);
+ if codegenerror then
+ exit;
+
+ { is this right for object of methods ?? }
+ expectloc:=LOC_REGISTER;
+ end;
+
+
+{*****************************************************************************
+ TDEREFNODE
+*****************************************************************************}
+
+ constructor tderefnode.create(l : tnode);
+
+ begin
+ inherited create(derefn,l);
+
+ end;
+
+ function tderefnode.pass_typecheck:tnode;
+ begin
+ result:=nil;
+ typecheckpass(left);
+ set_varstate(left,vs_read,[vsf_must_be_valid]);
+ if codegenerror then
+ exit;
+
+ { tp procvar support }
+ maybe_call_procvar(left,true);
+
+ if left.resultdef.typ=pointerdef then
+ resultdef:=tpointerdef(left.resultdef).pointeddef
+ else
+ CGMessage(parser_e_invalid_qualifier);
+ end;
+
+ procedure Tderefnode.mark_write;
+
+ begin
+ include(flags,nf_write);
+ end;
+
+ function tderefnode.pass_1 : tnode;
+ begin
+ result:=nil;
+ firstpass(left);
+ if codegenerror then
+ exit;
+
+ expectloc:=LOC_REFERENCE;
+ end;
+
+
+{*****************************************************************************
+ TSUBSCRIPTNODE
+*****************************************************************************}
+
+ constructor tsubscriptnode.create(varsym : tsym;l : tnode);
+
+ begin
+ inherited create(subscriptn,l);
+ { vs should be changed to tsym! }
+ vs:=tfieldvarsym(varsym);
+ end;
+
+ constructor tsubscriptnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ ppufile.getderef(vsderef);
+ end;
+
+
+ procedure tsubscriptnode.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putderef(vsderef);
+ end;
+
+
+ procedure tsubscriptnode.buildderefimpl;
+ begin
+ inherited buildderefimpl;
+ vsderef.build(vs);
+ end;
+
+
+ procedure tsubscriptnode.derefimpl;
+ begin
+ inherited derefimpl;
+ vs:=tfieldvarsym(vsderef.resolve);
+ end;
+
+
+ function tsubscriptnode.dogetcopy : tnode;
+ var
+ p : tsubscriptnode;
+ begin
+ p:=tsubscriptnode(inherited dogetcopy);
+ p.vs:=vs;
+ dogetcopy:=p;
+ end;
+
+
+ function tsubscriptnode.pass_typecheck:tnode;
+ begin
+ result:=nil;
+ typecheckpass(left);
+ { tp procvar support }
+ maybe_call_procvar(left,true);
+ resultdef:=vs.vardef;
+
+ // don't put records from which we load float fields
+ // in integer registers
+ if (left.resultdef.typ=recorddef) and
+ (resultdef.typ=floatdef) then
+ make_not_regable(left,[ra_addr_regable]);
+ end;
+
+ procedure Tsubscriptnode.mark_write;
+ begin
+ include(flags,nf_write);
+ end;
+
+
+ function tsubscriptnode.pass_1 : tnode;
+ begin
+ result:=nil;
+ firstpass(left);
+ if codegenerror then
+ exit;
+
+ { several object types must be dereferenced implicitly }
+ if is_implicit_pointer_object_type(left.resultdef) then
+ expectloc:=LOC_REFERENCE
+ else
+ begin
+ case left.expectloc of
+ LOC_REGISTER,
+ LOC_SUBSETREG:
+ // can happen for function results on win32 and darwin/x86
+ if (left.resultdef.size > sizeof(pint)) then
+ expectloc:=LOC_REFERENCE
+ else
+ expectloc:=LOC_SUBSETREG;
+ LOC_CREGISTER,
+ LOC_CSUBSETREG:
+ expectloc:=LOC_CSUBSETREG;
+ LOC_REFERENCE,
+ LOC_CREFERENCE:
+ expectloc:=left.expectloc;
+ else internalerror(20060521);
+ end;
+ end;
+ end;
+
+ function tsubscriptnode.docompare(p: tnode): boolean;
+ begin
+ docompare :=
+ inherited docompare(p) and
+ (vs = tsubscriptnode(p).vs);
+ end;
+
+
+{*****************************************************************************
+ TVECNODE
+*****************************************************************************}
+
+ constructor tvecnode.create(l,r : tnode);
+
+ begin
+ inherited create(vecn,l,r);
+ end;
+
+
+ function tvecnode.pass_typecheck:tnode;
+ var
+ hightree: tnode;
+ htype,elementdef : tdef;
+ newordtyp: tordtype;
+ valid : boolean;
+ begin
+ result:=nil;
+ typecheckpass(left);
+ typecheckpass(right);
+
+ { implicitly convert stringconstant to stringdef,
+ see tbs/tb0476.pp for a test }
+ if (left.nodetype=stringconstn) and
+ (tstringconstnode(left).cst_type=cst_conststring) then
+ begin
+ if tstringconstnode(left).len>255 then
+ inserttypeconv(left,getansistringdef)
+ else
+ inserttypeconv(left,cshortstringtype);
+ end;
+
+ { In p[1] p is always valid, it is not possible to
+ declared a shortstring or normal array that has
+ undefined number of elements. Dynamic array and
+ ansi/widestring needs to be valid }
+ valid:=is_dynamic_array(left.resultdef) or
+ is_ansistring(left.resultdef) or
+ is_wide_or_unicode_string(left.resultdef) or
+ { implicit pointer dereference -> pointer is read }
+ (left.resultdef.typ = pointerdef);
+ if valid then
+ set_varstate(left,vs_read,[vsf_must_be_valid]);
+{
+ A vecn is, just like a loadn, always part of an expression with its
+ own read/write and must_be_valid semantics. Therefore we don't have
+ to do anything else here, just like for loadn's
+}
+ set_varstate(right,vs_read,[vsf_must_be_valid]);
+ if codegenerror then
+ exit;
+
+ { maybe type conversion for the index value, but
+ do not convert range nodes }
+ if (right.nodetype<>rangen) then
+ case left.resultdef.typ of
+ arraydef:
+ begin
+ htype:=Tarraydef(left.resultdef).rangedef;
+ if ado_isvariant in Tarraydef(left.resultdef).arrayoptions then
+ {Variant arrays are a special array, can have negative indexes and would therefore
+ need s32bit. However, they should not appear in a vecn, as they are handled in
+ handle_variantarray in pexpr.pas. Therefore, encountering a variant array is an
+ internal error... }
+ internalerror(200707031)
+ else if is_special_array(left.resultdef) then
+ {Arrays without a high bound (dynamic arrays, open arrays) are zero based,
+ convert indexes into these arrays to aword.}
+ inserttypeconv(right,uinttype)
+ { note: <> rather than </>, because indexing e.g. an array 0..0
+ must not result in truncating the indexing value from 2/4/8
+ bytes to 1 byte (with range checking off, the full index
+ value must be used) }
+ else if (htype.typ=enumdef) and
+ (right.resultdef.typ=enumdef) and
+ (tenumdef(htype).basedef=tenumdef(right.resultdef).basedef) and
+ ((tarraydef(left.resultdef).lowrange<>tenumdef(htype).min) or
+ (tarraydef(left.resultdef).highrange<>tenumdef(htype).max)) then
+ {Convert array indexes to low_bound..high_bound.}
+ inserttypeconv(right,tenumdef.create_subrange(tenumdef(right.resultdef),
+ asizeint(Tarraydef(left.resultdef).lowrange),
+ asizeint(Tarraydef(left.resultdef).highrange)
+ ))
+ else if (htype.typ=orddef) and
+ { don't try to create boolean types with custom ranges }
+ not is_boolean(right.resultdef) and
+ { ordtype determines the size of the loaded value -> make
+ sure we don't truncate }
+ ((Torddef(right.resultdef).ordtype<>torddef(htype).ordtype) or
+ (tarraydef(left.resultdef).lowrange<>torddef(htype).low) or
+ (tarraydef(left.resultdef).highrange<>torddef(htype).high)) then
+ {Convert array indexes to low_bound..high_bound.}
+ begin
+ if right.resultdef.typ=orddef then
+ newordtyp:=Torddef(right.resultdef).ordtype
+ else
+ newordtyp:=torddef(ptrsinttype).ordtype;
+ inserttypeconv(right,Torddef.create(newordtyp,
+ int64(Tarraydef(left.resultdef).lowrange),
+ int64(Tarraydef(left.resultdef).highrange)
+ ))
+ end
+ else
+ inserttypeconv(right,htype)
+ end;
+ stringdef:
+ if is_open_string(left.resultdef) then
+ inserttypeconv(right,u8inttype)
+ else if is_shortstring(left.resultdef) then
+ {Convert shortstring indexes to 0..length.}
+ inserttypeconv(right,Torddef.create(u8bit,0,int64(Tstringdef(left.resultdef).len)))
+ else
+ {Convert indexes into dynamically allocated strings to aword.}
+ inserttypeconv(right,uinttype);
+ else
+ {Others, i.e. pointer indexes to aint.}
+ inserttypeconv(right,sinttype);
+ end;
+
+ { although we never put regular arrays or shortstrings in registers,
+ it's possible that another type was typecasted to a small record
+ that has a field of one of these types -> in that case the record
+ can't be a regvar either }
+ if ((left.resultdef.typ=arraydef) and
+ not is_special_array(left.resultdef)) or
+ ((left.resultdef.typ=stringdef) and
+ (tstringdef(left.resultdef).stringtype in [st_shortstring,st_longstring])) then
+ make_not_regable(left,[ra_addr_regable]);
+
+ case left.resultdef.typ of
+ arraydef :
+ begin
+ { check type of the index value }
+ if (compare_defs(right.resultdef,tarraydef(left.resultdef).rangedef,right.nodetype)=te_incompatible) then
+ IncompatibleTypes(right.resultdef,tarraydef(left.resultdef).rangedef);
+ if right.nodetype=rangen then
+ resultdef:=left.resultdef
+ else
+ resultdef:=Tarraydef(left.resultdef).elementdef;
+
+ { if we are range checking an open array or array of const, we }
+ { need to load the high parameter. If the current procedure is }
+ { nested inside the procedure to which the open array/of const }
+ { was passed, then the high parameter must not be a regvar. }
+ { So create a loadnode for the high parameter here and }
+ { typecheck it, then the loadnode will make the high parameter }
+ { not regable. Otherwise this would only happen inside pass_2, }
+ { which is too late since by then the regvars are already }
+ { assigned (pass_1 is also already too late, because then the }
+ { regvars of the parent are also already assigned). }
+ { webtbs/tw8975 }
+ if (cs_check_range in current_settings.localswitches) and
+ (is_open_array(left.resultdef) or
+ is_array_of_const(left.resultdef)) and
+ { cdecl functions don't have high() so we can not check the range }
+ { (can't use current_procdef, since it may be a nested procedure) }
+ not(tprocdef(tparasymtable(tparavarsym(tloadnode(left).symtableentry).owner).defowner).proccalloption in cdecl_pocalls) then
+ begin
+ { load_high_value_node already typechecks }
+ hightree:=load_high_value_node(tparavarsym(tloadnode(left).symtableentry));
+ hightree.free;
+ end;
+
+
+ end;
+ pointerdef :
+ begin
+ { are we accessing a pointer[], then convert the pointer to
+ an array first, in FPC this is allowed for all pointers
+ (except voidpointer) in delphi/tp7 it's only allowed for pchars. }
+ if not is_voidpointer(left.resultdef) and
+ (
+ (cs_pointermath in current_settings.localswitches) or
+ tpointerdef(left.resultdef).has_pointer_math or
+ is_pchar(left.resultdef) or
+ is_pwidechar(left.resultdef)
+ ) then
+ begin
+ { convert pointer to array }
+ htype:=tarraydef.create_from_pointer(tpointerdef(left.resultdef).pointeddef);
+ inserttypeconv(left,htype);
+ if right.nodetype=rangen then
+ resultdef:=htype
+ else
+ resultdef:=tarraydef(htype).elementdef;
+ end
+ else
+ CGMessage(type_e_array_required);
+ end;
+ stringdef :
+ begin
+ case tstringdef(left.resultdef).stringtype of
+ st_unicodestring,
+ st_widestring :
+ elementdef:=cwidechartype;
+ st_ansistring :
+ elementdef:=cchartype;
+ st_longstring :
+ elementdef:=cchartype;
+ st_shortstring :
+ elementdef:=cchartype;
+ end;
+ if right.nodetype=rangen then
+ begin
+ htype:=Tarraydef.create_from_pointer(elementdef);
+ resultdef:=htype;
+ end
+ else
+ begin
+ { indexed access to 0 element is only allowed for shortstrings }
+ if (right.nodetype=ordconstn) and
+ (Tordconstnode(right).value.svalue=0) and
+ not is_shortstring(left.resultdef) then
+ CGMessage(cg_e_can_access_element_zero);
+ resultdef:=elementdef;
+ end;
+ end;
+ variantdef :
+ resultdef:=cvarianttype;
+ else
+ CGMessage(type_e_array_required);
+ end;
+ end;
+
+ procedure Tvecnode.mark_write;
+
+ begin
+ include(flags,nf_write);
+ end;
+
+ function tvecnode.pass_1 : tnode;
+ begin
+ result:=nil;
+ firstpass(left);
+ firstpass(right);
+ if codegenerror then
+ exit;
+
+ if (nf_callunique in flags) and
+ (is_ansistring(left.resultdef) or
+ is_unicodestring(left.resultdef) or
+ (is_widestring(left.resultdef) and not(tf_winlikewidestring in target_info.flags))) then
+ begin
+ left := ctypeconvnode.create_internal(ccallnode.createintern('fpc_'+tstringdef(left.resultdef).stringtypname+'_unique',
+ ccallparanode.create(
+ ctypeconvnode.create_internal(left,voidpointertype),nil)),
+ left.resultdef);
+ firstpass(left);
+ { double resultdef passes somwhere else may cause this to be }
+ { reset though :/ }
+ exclude(flags,nf_callunique);
+ end
+ else if is_widestring(left.resultdef) and (tf_winlikewidestring in target_info.flags) then
+ exclude(flags,nf_callunique);
+
+ { a range node as array index can only appear in function calls, and
+ those convert the range node into something else in
+ tcallnode.gen_high_tree }
+ if (right.nodetype=rangen) then
+ CGMessagePos(right.fileinfo,parser_e_illegal_expression)
+ else if (not is_packed_array(left.resultdef)) or
+ ((tarraydef(left.resultdef).elepackedbitsize mod 8) = 0) then
+ if left.expectloc=LOC_CREFERENCE then
+ expectloc:=LOC_CREFERENCE
+ else
+ expectloc:=LOC_REFERENCE
+ else
+ if left.expectloc=LOC_CREFERENCE then
+ expectloc:=LOC_CSUBSETREF
+ else
+ expectloc:=LOC_SUBSETREF;
+ end;
+
+
+{*****************************************************************************
+ TWITHNODE
+*****************************************************************************}
+
+ constructor twithnode.create(l:tnode);
+ begin
+ inherited create(withn,l);
+ fileinfo:=l.fileinfo;
+ end;
+
+
+ destructor twithnode.destroy;
+ begin
+ inherited destroy;
+ end;
+
+
+ constructor twithnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ end;
+
+
+ procedure twithnode.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ end;
+
+
+ function twithnode.dogetcopy : tnode;
+ var
+ p : twithnode;
+ begin
+ p:=twithnode(inherited dogetcopy);
+ result:=p;
+ end;
+
+
+ function twithnode.pass_typecheck:tnode;
+ begin
+ result:=nil;
+ resultdef:=voidtype;
+ if assigned(left) then
+ typecheckpass(left);
+ end;
+
+
+ function twithnode.pass_1 : tnode;
+ begin
+ result:=nil;
+ expectloc:=LOC_VOID;
+ end;
+
+
+ function twithnode.docompare(p: tnode): boolean;
+ begin
+ docompare :=
+ inherited docompare(p);
+ end;
+
+ function is_big_untyped_addrnode(p: tnode): boolean;
+ begin
+ is_big_untyped_addrnode:=(p.nodetype=addrn) and
+ not (nf_typedaddr in p.flags) and (taddrnode(p).left.resultdef.size > 1);
+ end;
+
+end.
diff --git a/closures/compiler/nobj.pas b/closures/compiler/nobj.pas
new file mode 100644
index 0000000000..7ce974f2f7
--- /dev/null
+++ b/closures/compiler/nobj.pas
@@ -0,0 +1,1593 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Routines for the code generation of data structures
+ like VMT, Messages, VTables, Interfaces descs
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit nobj;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cutils,cclasses,
+ globtype,
+ symdef,symsym,
+ aasmbase,aasmtai,aasmdata
+ ;
+
+ type
+ TVMTBuilder=class
+ private
+ _Class : tobjectdef;
+ handledprotocols: tfpobjectlist;
+ function is_new_vmt_entry(pd:tprocdef; out overridesclasshelper: boolean):boolean;
+ procedure add_new_vmt_entry(pd:tprocdef; allowoverridingmethod: boolean);
+ function check_msg_str(vmtpd, pd: tprocdef):boolean;
+ function intf_search_procdef_by_name(proc: tprocdef;const name: string): tprocdef;
+ procedure intf_get_procdefs(ImplIntf:TImplementedInterface;IntfDef:TObjectDef);
+ procedure intf_get_procdefs_recursive(ImplIntf:TImplementedInterface;IntfDef:TObjectDef);
+ procedure prot_get_procdefs_recursive(ImplProt:TImplementedInterface;ProtDef:TObjectDef);
+ procedure intf_optimize_vtbls;
+ procedure intf_allocate_vtbls;
+ public
+ constructor create(c:tobjectdef);
+ destructor destroy;override;
+ procedure generate_vmt;
+ procedure build_interface_mappings;
+ end;
+
+ type
+ pprocdeftree = ^tprocdeftree;
+ tprocdeftree = record
+ data : tprocdef;
+ nl : tasmlabel;
+ l,r : pprocdeftree;
+ end;
+
+ TVMTWriter=class
+ private
+ _Class : tobjectdef;
+ { message tables }
+ root : pprocdeftree;
+ procedure disposeprocdeftree(p : pprocdeftree);
+ procedure insertmsgint(p:TObject;arg:pointer);
+ procedure insertmsgstr(p:TObject;arg:pointer);
+ procedure insertint(p : pprocdeftree;var at : pprocdeftree;var count:longint);
+ procedure insertstr(p : pprocdeftree;var at : pprocdeftree;var count:longint);
+ procedure writenames(p : pprocdeftree);
+ procedure writeintentry(p : pprocdeftree);
+ procedure writestrentry(p : pprocdeftree);
+{$ifdef WITHDMT}
+ { dmt }
+ procedure insertdmtentry(p:TObject;arg:pointer);
+ procedure writedmtindexentry(p : pprocdeftree);
+ procedure writedmtaddressentry(p : pprocdeftree);
+{$endif}
+ { published methods }
+ procedure do_count_published_methods(p:TObject;arg:pointer);
+ procedure do_gen_published_methods(p:TObject;arg:pointer);
+ { virtual methods }
+ procedure writevirtualmethods(List:TAsmList);
+ { interface tables }
+ function intf_get_vtbl_name(AImplIntf:TImplementedInterface): string;
+ procedure intf_create_vtbl(rawdata: TAsmList;AImplIntf:TImplementedInterface);
+ procedure intf_gen_intf_ref(rawdata: TAsmList;AImplIntf:TImplementedInterface);
+ function intf_write_table:TAsmLabel;
+ { generates the message tables for a class }
+ function genstrmsgtab : tasmlabel;
+ function genintmsgtab : tasmlabel;
+ function genpublishedmethodstable : tasmlabel;
+ function generate_field_table : tasmlabel;
+{$ifdef WITHDMT}
+ { generates a DMT for _class }
+ function gendmt : tasmlabel;
+{$endif WITHDMT}
+ public
+ constructor create(c:tobjectdef);
+ destructor destroy;override;
+ { write the VMT to al_globals }
+ procedure writevmt;
+ procedure writeinterfaceids;
+ end;
+
+implementation
+
+ uses
+ SysUtils,
+ globals,verbose,systems,
+ node,
+ symbase,symtable,symconst,symtype,defcmp,
+ dbgbase,
+ ncgrtti,
+ wpobase
+ ;
+
+
+{*****************************************************************************
+ TVMTBuilder
+*****************************************************************************}
+
+ constructor TVMTBuilder.create(c:tobjectdef);
+ begin
+ inherited Create;
+ _Class:=c;
+ end;
+
+
+ destructor TVMTBuilder.destroy;
+ begin
+ end;
+
+
+ procedure TVMTBuilder.add_new_vmt_entry(pd:tprocdef; allowoverridingmethod: boolean);
+ var
+ i : longint;
+ vmtentry : pvmtentry;
+ vmtpd : tprocdef;
+ begin
+ { new entry is needed, override was not possible }
+ { Allowed when overriding a category method for a parent class in a
+ descendent Objective-C class }
+ if not allowoverridingmethod and
+ (po_overridingmethod in pd.procoptions) then
+ MessagePos1(pd.fileinfo,parser_e_nothing_to_be_overridden,pd.fullprocname(false));
+
+ { check that all methods have overload directive }
+ if not(m_fpc in current_settings.modeswitches) then
+ begin
+ for i:=0 to _class.vmtentries.count-1 do
+ begin
+ vmtentry:=pvmtentry(_class.vmtentries[i]);
+ vmtpd:=tprocdef(vmtentry^.procdef);
+ if (vmtpd.procsym=pd.procsym) and
+ (not(po_overload in pd.procoptions) or
+ not(po_overload in vmtpd.procoptions)) then
+ begin
+ MessagePos1(pd.fileinfo,parser_e_no_overload_for_all_procs,pd.procsym.realname);
+ { recover }
+ include(vmtpd.procoptions,po_overload);
+ include(pd.procoptions,po_overload);
+ end;
+ end;
+ end;
+
+ { Register virtual method and give it a number }
+ if (po_virtualmethod in pd.procoptions) then
+ begin
+ { store vmt entry number in procdef }
+ if (pd.extnumber<>$ffff) and
+ (pd.extnumber<>_class.VMTEntries.Count) then
+ internalerror(200810283);
+ pd.extnumber:=_class.VMTEntries.Count;
+ new(vmtentry);
+ vmtentry^.procdef:=pd;
+ vmtentry^.procdefderef.reset;
+ vmtentry^.visibility:=pd.visibility;
+ _class.VMTEntries.Add(vmtentry);
+ end;
+ end;
+
+
+ function TVMTBuilder.check_msg_str(vmtpd, pd: tprocdef): boolean;
+ begin
+ result:=true;
+ if not(is_objc_class_or_protocol(_class)) then
+ begin
+ { the only requirement for normal methods is that both either
+ have a message string or not (the value is irrelevant) }
+ if ((pd.procoptions * [po_msgstr]) <> (vmtpd.procoptions * [po_msgstr])) then
+ begin
+ MessagePos1(pd.fileinfo,parser_e_header_dont_match_forward,pd.fullprocname(false));
+ tprocsym(vmtpd.procsym).write_parameter_lists(pd);
+ result:=false;
+ end
+ end
+ else
+ begin
+ { the compiler should have ensured that the protocol or parent
+ class method has a message name specified }
+ if not(po_msgstr in vmtpd.procoptions) then
+ internalerror(2009070601);
+ if not(po_msgstr in pd.procoptions) then
+ begin
+ { copy the protocol's/parent class' message name to the one in
+ the class if none has been specified there }
+ include(pd.procoptions,po_msgstr);
+ pd.messageinf.str:=stringdup(vmtpd.messageinf.str^);
+ end
+ else
+ begin
+ { if both have a message name, make sure they are equal }
+ if (vmtpd.messageinf.str^<>pd.messageinf.str^) then
+ begin
+ MessagePos2(pd.fileinfo,parser_e_objc_message_name_changed,vmtpd.messageinf.str^,pd.messageinf.str^);
+ result:=false;
+ end;
+ end;
+ end;
+ end;
+
+
+ function TVMTBuilder.is_new_vmt_entry(pd:tprocdef; out overridesclasshelper: boolean):boolean;
+ const
+ po_comp = [po_classmethod,po_virtualmethod,po_staticmethod,po_interrupt,po_iocheck,po_msgint,
+ po_exports,po_varargs,po_explicitparaloc,po_nostackframe];
+ var
+ i : longint;
+ hasequalpara,
+ hasoverloads,
+ pdoverload : boolean;
+ srsym : tsym;
+ st : tsymtable;
+
+ // returns true if we can stop checking, false if we have to continue
+ function found_entry(var vmtpd: tprocdef; var vmtentryvis: tvisibility; updatevalues: boolean): boolean;
+ begin
+ result:=false;
+
+ { ignore hidden entries (e.g. virtual overridden by a static) that are not visible anymore }
+ if vmtentryvis=vis_hidden then
+ exit;
+
+ { ignore different names }
+ if vmtpd.procsym.name<>pd.procsym.name then
+ exit;
+
+ { hide private methods that are not visible anymore. For this check we
+ must override the visibility with the highest value in the override chain.
+ This is required for case (see tw3292) with protected-private-protected where the
+ same vmtentry is used (PFV) }
+ if not is_visible_for_object(vmtpd.owner,vmtentryvis,_class) then
+ exit;
+
+ { inherit overload }
+ if (po_overload in vmtpd.procoptions) then
+ begin
+ include(pd.procoptions,po_overload);
+ pdoverload:=true;
+ end;
+
+ { compare parameter types only, no specifiers yet }
+ hasequalpara:=(compare_paras(vmtpd.paras,pd.paras,cp_none,[cpo_ignoreuniv,cpo_ignorehidden])>=te_equal);
+
+ { check that we are not trying to override a final method }
+ if (po_finalmethod in vmtpd.procoptions) and
+ hasequalpara and (po_overridingmethod in pd.procoptions) and
+ (is_class(_class) or is_objectpascal_helper(_class)) then
+ MessagePos1(pd.fileinfo,parser_e_final_can_no_be_overridden,pd.fullprocname(false))
+ else
+ { old definition has virtual
+ new definition has no virtual or override }
+ if (po_virtualmethod in vmtpd.procoptions) and
+ (
+ not(po_virtualmethod in pd.procoptions) or
+ (
+ { new one does not have reintroduce in case of an objccategory }
+ (is_objccategory(_class) and not(po_reintroduce in pd.procoptions)) or
+ { new one does not have override in case of objpas/objc class/helper/intf/proto }
+ (
+ (is_class_or_interface_or_objc(_class) or is_objectpascal_helper(_class)) and
+ not is_objccategory(_class) and not(po_overridingmethod in pd.procoptions)
+ )
+ )
+ ) then
+ begin
+ if (
+ not(pdoverload or hasoverloads) or
+ hasequalpara
+ ) then
+ begin
+ if not(po_reintroduce in pd.procoptions) then
+ if not(is_objc_class_or_protocol(_class)) then
+ MessagePos1(pd.fileinfo,parser_w_should_use_override,pd.fullprocname(false))
+ else
+ begin
+ { In Objective-C, you cannot create a new VMT entry to
+ start a new inheritance tree. We therefore give an
+ error when the class is implemented in Pascal, to
+ avoid confusion due to things working differently
+ with Object Pascal classes.
+
+ In case of external classes, we only give a hint,
+ because requiring override everywhere may make
+ automated header translation tools too complex. }
+ if not(oo_is_external in _class.objectoptions) then
+ if not is_objccategory(_class) then
+ MessagePos1(pd.fileinfo,parser_e_must_use_override_objc,FullTypeName(tdef(vmtpd.owner.defowner),nil))
+ else
+ MessagePos1(pd.fileinfo,parser_e_must_use_reintroduce_objc,FullTypeName(tdef(vmtpd.owner.defowner),nil))
+ { there may be a lot of these in auto-translated
+ heaeders, so only calculate the fulltypename if
+ the hint will be shown }
+ else if CheckVerbosity(V_Hint) then
+ if not is_objccategory(_class) then
+ MessagePos1(pd.fileinfo,parser_h_should_use_override_objc,FullTypeName(tdef(vmtpd.owner.defowner),nil))
+ else
+ MessagePos1(pd.fileinfo,parser_h_should_use_reintroduce_objc,FullTypeName(tdef(vmtpd.owner.defowner),nil));
+ { no new entry, but copy the message name if any from
+ the procdef in the parent class }
+ check_msg_str(vmtpd,pd);
+ result:=true;
+ exit;
+ end;
+ { disable/hide old VMT entry }
+ if updatevalues then
+ vmtentryvis:=vis_hidden;
+ end;
+ end
+ { both are virtual? }
+ else if (po_virtualmethod in pd.procoptions) and
+ (po_virtualmethod in vmtpd.procoptions) then
+ begin
+ { same parameter and return types (parameter specifiers will be checked below) }
+ if hasequalpara and
+ compatible_childmethod_resultdef(vmtpd.returndef,pd.returndef) then
+ begin
+ { inherite calling convention when it was explicit and the
+ current definition has none explicit set }
+ if (po_hascallingconvention in vmtpd.procoptions) and
+ not(po_hascallingconvention in pd.procoptions) then
+ begin
+ pd.proccalloption:=vmtpd.proccalloption;
+ include(pd.procoptions,po_hascallingconvention);
+ end;
+
+ { All parameter specifiers and some procedure the flags have to match
+ except abstract and override }
+ if (compare_paras(vmtpd.paras,pd.paras,cp_all,[cpo_ignoreuniv,cpo_ignorehidden])<te_equal) or
+ (vmtpd.proccalloption<>pd.proccalloption) or
+ (vmtpd.proctypeoption<>pd.proctypeoption) or
+ ((vmtpd.procoptions*po_comp)<>(pd.procoptions*po_comp)) then
+ begin
+ MessagePos1(pd.fileinfo,parser_e_header_dont_match_forward,pd.fullprocname(false));
+ tprocsym(vmtpd.procsym).write_parameter_lists(pd);
+ end;
+
+ check_msg_str(vmtpd,pd);
+
+ { Give a note if the new visibility is lower. For a higher
+ visibility update the vmt info }
+ if vmtentryvis>pd.visibility then
+ MessagePos4(pd.fileinfo,parser_n_ignore_lower_visibility,pd.fullprocname(false),
+ visibilityname[pd.visibility],tobjectdef(vmtpd.owner.defowner).objrealname^,visibilityname[vmtentryvis])
+ else if pd.visibility>vmtentryvis then
+ begin
+ if updatevalues then
+ vmtentryvis:=pd.visibility;
+ end;
+
+ { override old virtual method in VMT }
+ if updatevalues then
+ begin
+ if (vmtpd.extnumber<>i) then
+ internalerror(200611084);
+ pd.extnumber:=vmtpd.extnumber;
+ vmtpd:=pd;
+ end;
+ result:=true;
+ exit;
+ end
+ { different parameters }
+ else
+ begin
+ { when we got an override directive then can search futher for
+ the procedure to override.
+ If we are starting a new virtual tree then hide the old tree }
+ if not(po_overridingmethod in pd.procoptions) and
+ not(pdoverload or hasoverloads) then
+ begin
+ if not(po_reintroduce in pd.procoptions) then
+ begin
+ if not is_object(_class) and
+ not is_objc_class_or_protocol(_class) then
+ MessagePos1(pd.fileinfo,parser_w_should_use_override,pd.fullprocname(false))
+ else
+ { objects don't allow starting a new virtual tree
+ and neither does Objective-C }
+ MessagePos1(pd.fileinfo,parser_e_header_dont_match_forward,vmtpd.fullprocname(false));
+ end;
+ { disable/hide old VMT entry }
+ if updatevalues then
+ vmtentryvis:=vis_hidden;
+ end;
+ end;
+ end;
+ end;
+
+ function found_category_method(st: tsymtable): boolean;
+ var
+ entrycount: longint;
+ cat: tobjectdef;
+ vmtpd: tprocdef;
+ vmtvis: tvisibility;
+ begin
+ result:=false;
+ if is_objccategory(tdef(st.defowner)) then
+ begin
+ cat:=tobjectdef(st.defowner);
+ { go through all of the category's methods to find the
+ vmtentry corresponding to the procdef we are handling }
+ for entrycount:=0 to cat.vmtentries.Count-1 do
+ begin
+ vmtpd:=pvmtentry(cat.vmtentries[entrycount])^.procdef;
+ vmtvis:=pvmtentry(cat.vmtentries[entrycount])^.visibility;
+ { don't change the vmtentry of the category }
+ if found_entry(vmtpd,vmtvis,false) then
+ begin
+ result:=true;
+ exit;
+ end;
+ end;
+ end;
+ end;
+
+ begin
+ result:=false;
+ overridesclasshelper:=false;
+ { Load other values for easier readability }
+ hasoverloads:=(tprocsym(pd.procsym).ProcdefList.Count>1);
+ pdoverload:=(po_overload in pd.procoptions);
+
+ { compare with all stored definitions }
+ for i:=0 to _class.vmtentries.Count-1 do
+ begin
+ if found_entry(pvmtentry(_class.vmtentries[i])^.procdef, pvmtentry(_class.vmtentries[i])^.visibility,true) then
+ exit;
+ end;
+
+ { in case of Objective-C, also check the categories that apply to this
+ class' *parent* for methods to override (don't allow class X to
+ "override" a method added by a category to class X itself, since in
+ that case the category method will in fact replace class X'
+ "overriding" method }
+ if is_objcclass(_class) and
+ assigned(_class.childof) and
+ search_objc_helper(_class.childof,pd.procsym.name,srsym,st) then
+ begin
+ overridesclasshelper:=found_category_method(st);
+ end;
+
+ { No entry found, we need to create a new entry }
+ result:=true;
+ end;
+
+
+ function TVMTBuilder.intf_search_procdef_by_name(proc: tprocdef;const name: string): tprocdef;
+ const
+ po_comp = [po_classmethod,po_staticmethod,po_interrupt,po_iocheck,po_msgint,
+ po_exports,po_varargs,po_explicitparaloc,po_nostackframe];
+ var
+ implprocdef : Tprocdef;
+ i: cardinal;
+ hclass : tobjectdef;
+ hashedid : THashedIDString;
+ srsym : tsym;
+ begin
+ result:=nil;
+ hashedid.id:=name;
+ hclass:=_class;
+ while assigned(hclass) do
+ begin
+ srsym:=tsym(hclass.symtable.FindWithHash(hashedid));
+ if assigned(srsym) and
+ (srsym.typ=procsym) then
+ begin
+ for i:=0 to Tprocsym(srsym).ProcdefList.Count-1 do
+ begin
+ implprocdef:=tprocdef(tprocsym(srsym).ProcdefList[i]);
+ if (implprocdef.procsym=tprocsym(srsym)) and
+ (compare_paras(proc.paras,implprocdef.paras,cp_all,[cpo_ignorehidden,cpo_comparedefaultvalue,cpo_ignoreuniv])>=te_equal) and
+ (compare_defs(proc.returndef,implprocdef.returndef,nothingn)>=te_equal) and
+ (proc.proccalloption=implprocdef.proccalloption) and
+ (proc.proctypeoption=implprocdef.proctypeoption) and
+ ((proc.procoptions*po_comp)=((implprocdef.procoptions+[po_virtualmethod])*po_comp)) and
+ check_msg_str(proc,implprocdef) then
+ begin
+ result:=implprocdef;
+ exit;
+ end;
+ end;
+ end;
+ hclass:=hclass.childof;
+ end;
+ end;
+
+
+ procedure TVMTBuilder.intf_get_procdefs(ImplIntf:TImplementedInterface;IntfDef:TObjectDef);
+ var
+ i : longint;
+ def : tdef;
+ hs,
+ prefix,
+ mappedname: string;
+ implprocdef: tprocdef;
+ begin
+ prefix:=ImplIntf.IntfDef.symtable.name^+'.';
+ for i:=0 to IntfDef.symtable.DefList.Count-1 do
+ begin
+ def:=tdef(IntfDef.symtable.DefList[i]);
+ if assigned(def) and
+ (def.typ=procdef) then
+ begin
+ { Find implementing procdef
+ 1. Check for mapped name
+ 2. Use symbol name, but only if there's no mapping,
+ or we're processing ancestor of interface.
+ When modifying this code, ensure that webtbs/tw11862, webtbs/tw4950
+ and webtbf/tw19591 stay correct. }
+ implprocdef:=nil;
+ hs:=prefix+tprocdef(def).procsym.name;
+ mappedname:=ImplIntf.GetMapping(hs);
+ if mappedname<>'' then
+ implprocdef:=intf_search_procdef_by_name(tprocdef(def),mappedname);
+ if not assigned(implprocdef) then
+ if (mappedname='') or (ImplIntf.IntfDef<>IntfDef) then
+ implprocdef:=intf_search_procdef_by_name(tprocdef(def),tprocdef(def).procsym.name);
+
+ { Add procdef to the implemented interface }
+ if assigned(implprocdef) then
+ begin
+ if (tobjectdef(implprocdef.struct).objecttype<>odt_objcclass) then
+ ImplIntf.AddImplProc(implprocdef)
+ else
+ begin
+ { If no message name has been specified for the method
+ in the objcclass, copy it from the protocol
+ definition. }
+ if not(po_msgstr in tprocdef(def).procoptions) then
+ begin
+ include(tprocdef(def).procoptions,po_msgstr);
+ implprocdef.messageinf.str:=stringdup(tprocdef(def).messageinf.str^);
+ end
+ else
+ begin
+ { If a message name has been specified in the
+ objcclass, it has to match the message name in the
+ protocol definition. }
+ if (implprocdef.messageinf.str^<>tprocdef(def).messageinf.str^) then
+ MessagePos2(implprocdef.fileinfo,parser_e_objc_message_name_changed,tprocdef(def).messageinf.str^,implprocdef.messageinf.str^);
+ end;
+ end;
+ end
+ else
+ if (ImplIntf.IType=etStandard) and
+ not(po_optional in tprocdef(def).procoptions) then
+ MessagePos1(_Class.typesym.fileinfo,sym_e_no_matching_implementation_found,tprocdef(def).fullprocname(false));
+ end;
+ end;
+ end;
+
+
+ procedure TVMTBuilder.intf_get_procdefs_recursive(ImplIntf:TImplementedInterface;IntfDef:TObjectDef);
+ begin
+ if assigned(IntfDef.childof) then
+ intf_get_procdefs_recursive(ImplIntf,IntfDef.childof);
+ intf_get_procdefs(ImplIntf,IntfDef);
+ end;
+
+
+ procedure TVMTBuilder.prot_get_procdefs_recursive(ImplProt:TImplementedInterface;ProtDef:TObjectDef);
+ var
+ i: longint;
+ begin
+ { don't check the same protocol twice }
+ if handledprotocols.IndexOf(ProtDef)<>-1 then
+ exit;
+ handledprotocols.add(ProtDef);
+ for i:=0 to ProtDef.ImplementedInterfaces.count-1 do
+ prot_get_procdefs_recursive(ImplProt,TImplementedInterface(ProtDef.ImplementedInterfaces[i]).intfdef);
+ intf_get_procdefs(ImplProt,ProtDef);
+ end;
+
+
+ procedure TVMTBuilder.intf_optimize_vtbls;
+ type
+ tcompintfentry = record
+ weight: longint;
+ compintf: longint;
+ end;
+ { Max 1000 interface in the class header interfaces it's enough imho }
+ tcompintfs = array[0..1000] of tcompintfentry;
+ pcompintfs = ^tcompintfs;
+ tequals = array[0..1000] of longint;
+ pequals = ^tequals;
+ timpls = array[0..1000] of longint;
+ pimpls = ^timpls;
+ var
+ aequals: pequals;
+ compats: pcompintfs;
+ impls: pimpls;
+ ImplIntfCount,
+ w,i,j,k: longint;
+ ImplIntfI,
+ ImplIntfJ : TImplementedInterface;
+ cij: boolean;
+ cji: boolean;
+ begin
+ ImplIntfCount:=_class.ImplementedInterfaces.count;
+ if ImplIntfCount>=High(tequals) then
+ Internalerror(200006135);
+ getmem(compats,sizeof(tcompintfentry)*ImplIntfCount);
+ getmem(aequals,sizeof(longint)*ImplIntfCount);
+ getmem(impls,sizeof(longint)*ImplIntfCount);
+ filldword(compats^,(sizeof(tcompintfentry) div sizeof(dword))*ImplIntfCount,dword(-1));
+ filldword(aequals^,ImplIntfCount,dword(-1));
+ filldword(impls^,ImplIntfCount,dword(-1));
+ { ismergepossible is a containing relation
+ meaning of ismergepossible(a,b,w) =
+ if implementorfunction map of a is contained implementorfunction map of b
+ imp(a,b) and imp(b,c) => imp(a,c) ; imp(a,b) and imp(b,a) => a == b
+ }
+ { the order is very important for correct allocation }
+ for i:=0 to ImplIntfCount-1 do
+ begin
+ for j:=i+1 to ImplIntfCount-1 do
+ begin
+ ImplIntfI:=TImplementedInterface(_class.ImplementedInterfaces[i]);
+ ImplIntfJ:=TImplementedInterface(_class.ImplementedInterfaces[j]);
+ cij:=ImplIntfI.IsImplMergePossible(ImplIntfJ,w);
+ cji:=ImplIntfJ.IsImplMergePossible(ImplIntfI,w);
+ if cij and cji then { i equal j }
+ begin
+ { get minimum index of equal }
+ if aequals^[j]=-1 then
+ aequals^[j]:=i;
+ end
+ else if cij then
+ begin
+ { get minimum index of maximum weight }
+ if compats^[i].weight<w then
+ begin
+ compats^[i].weight:=w;
+ compats^[i].compintf:=j;
+ end;
+ end
+ else if cji then
+ begin
+ { get minimum index of maximum weight }
+ if (compats^[j].weight<w) then
+ begin
+ compats^[j].weight:=w;
+ compats^[j].compintf:=i;
+ end;
+ end;
+ end;
+ end;
+ { Reset, no replacements by default }
+ for i:=0 to ImplIntfCount-1 do
+ impls^[i]:=i;
+ { Replace vtbls when equal or compat, repeat
+ until there are no replacements possible anymore. This is
+ needed for the cases like:
+ First loop: 2->3, 3->1
+ Second loop: 2->1 (because 3 was replaced with 1)
+ }
+ repeat
+ k:=0;
+ for i:=0 to ImplIntfCount-1 do
+ begin
+ if compats^[impls^[i]].compintf<>-1 then
+ impls^[i]:=compats^[impls^[i]].compintf
+ else if aequals^[impls^[i]]<>-1 then
+ impls^[i]:=aequals^[impls^[i]]
+ else
+ inc(k);
+ end;
+ until k=ImplIntfCount;
+ { Update the VtblImplIntf }
+ for i:=0 to ImplIntfCount-1 do
+ begin
+ ImplIntfI:=TImplementedInterface(_class.ImplementedInterfaces[i]);
+ ImplIntfI.VtblImplIntf:=TImplementedInterface(_class.ImplementedInterfaces[impls^[i]]);
+ end;
+ freemem(compats);
+ freemem(aequals);
+ freemem(impls);
+ end;
+
+
+ procedure TVMTBuilder.intf_allocate_vtbls;
+ var
+ i : longint;
+ ImplIntf : TImplementedInterface;
+ begin
+ { Allocation vtbl space }
+ for i:=0 to _class.ImplementedInterfaces.count-1 do
+ begin
+ ImplIntf:=TImplementedInterface(_class.ImplementedInterfaces[i]);
+ { if it implements itself and if it's not implemented by delegation }
+ if (ImplIntf.VtblImplIntf=ImplIntf) and (ImplIntf.IType=etStandard) then
+ begin
+ { allocate a pointer in the object memory }
+ with tObjectSymtable(_class.symtable) do
+ begin
+ datasize:=align(datasize,sizeof(pint));
+ ImplIntf.Ioffset:=datasize;
+ datasize:=datasize+sizeof(pint);
+ end;
+ end;
+ end;
+ { Update ioffset of current interface with the ioffset from
+ the interface that is reused to implements this interface }
+ for i:=0 to _class.ImplementedInterfaces.count-1 do
+ begin
+ ImplIntf:=TImplementedInterface(_class.ImplementedInterfaces[i]);
+ if ImplIntf.VtblImplIntf<>ImplIntf then
+ ImplIntf.IOffset:=ImplIntf.VtblImplIntf.IOffset;
+ end;
+ end;
+
+
+ procedure TVMTBuilder.generate_vmt;
+ var
+ i : longint;
+ def : tdef;
+ old_current_structdef : tabstractrecorddef;
+ overridesclasshelper : boolean;
+ begin
+ old_current_structdef:=current_structdef;
+ current_structdef:=_class;
+
+ _class.resetvmtentries;
+
+ { inherit (copy) VMT from parent object }
+ if assigned(_class.childof) then
+ begin
+ if not assigned(_class.childof.vmtentries) then
+ internalerror(200810281);
+ _class.copyvmtentries(_class.childof);
+ end;
+
+ { process all procdefs, we must process the defs to
+ keep the same order as that is written in the source
+ to be compatible with the indexes in the interface vtable (PFV) }
+ for i:=0 to _class.symtable.DefList.Count-1 do
+ begin
+ def:=tdef(_class.symtable.DefList[i]);
+ if def.typ=procdef then
+ begin
+ { VMT entry }
+ if is_new_vmt_entry(tprocdef(def),overridesclasshelper) then
+ add_new_vmt_entry(tprocdef(def),overridesclasshelper);
+ end;
+ end;
+ build_interface_mappings;
+ if assigned(_class.ImplementedInterfaces) and
+ not(is_objc_class_or_protocol(_class)) then
+ begin
+ { Optimize interface tables to reuse wrappers }
+ intf_optimize_vtbls;
+ { Allocate interface tables }
+ intf_allocate_vtbls;
+ end;
+
+ current_structdef:=old_current_structdef;
+ end;
+
+
+ procedure TVMTBuilder.build_interface_mappings;
+ var
+ ImplIntf : TImplementedInterface;
+ i: longint;
+ begin
+ { Find Procdefs implementing the interfaces }
+ if assigned(_class.ImplementedInterfaces) and
+ (_class.objecttype<>odt_objcprotocol) then
+ begin
+ { Collect implementor functions into the tImplementedInterface.procdefs }
+ case _class.objecttype of
+ odt_class:
+ begin
+ for i:=0 to _class.ImplementedInterfaces.count-1 do
+ begin
+ ImplIntf:=TImplementedInterface(_class.ImplementedInterfaces[i]);
+ intf_get_procdefs_recursive(ImplIntf,ImplIntf.IntfDef)
+ end;
+ end;
+ odt_objcclass:
+ begin
+ { Object Pascal interfaces are afterwards optimized via the
+ intf_optimize_vtbls() method, but we can't do this for
+ protocols -> check for duplicates here already. }
+ handledprotocols:=tfpobjectlist.create(false);
+ for i:=0 to _class.ImplementedInterfaces.count-1 do
+ begin
+ ImplIntf:=TImplementedInterface(_class.ImplementedInterfaces[i]);
+ prot_get_procdefs_recursive(ImplIntf,ImplIntf.IntfDef);
+ end;
+ handledprotocols.free;
+ end
+ else
+ internalerror(2009091801);
+ end
+ end;
+ end;
+
+
+{*****************************************************************************
+ TVMTWriter
+*****************************************************************************}
+
+ constructor TVMTWriter.create(c:tobjectdef);
+ begin
+ inherited Create;
+ _Class:=c;
+ end;
+
+
+ destructor TVMTWriter.destroy;
+ begin
+ end;
+
+
+{**************************************
+ Message Tables
+**************************************}
+
+ procedure TVMTWriter.disposeprocdeftree(p : pprocdeftree);
+ begin
+ if assigned(p^.l) then
+ disposeprocdeftree(p^.l);
+ if assigned(p^.r) then
+ disposeprocdeftree(p^.r);
+ dispose(p);
+ end;
+
+
+ procedure TVMTWriter.insertint(p : pprocdeftree;var at : pprocdeftree;var count:longint);
+ begin
+ if at=nil then
+ begin
+ at:=p;
+ inc(count);
+ end
+ else
+ begin
+ if p^.data.messageinf.i<at^.data.messageinf.i then
+ insertint(p,at^.l,count)
+ else if p^.data.messageinf.i>at^.data.messageinf.i then
+ insertint(p,at^.r,count)
+ else
+ Message1(parser_e_duplicate_message_label,tostr(p^.data.messageinf.i));
+ end;
+ end;
+
+
+ procedure TVMTWriter.insertstr(p : pprocdeftree;var at : pprocdeftree;var count:longint);
+ var
+ i : integer;
+ begin
+ if at=nil then
+ begin
+ at:=p;
+ inc(count);
+ end
+ else
+ begin
+ i:=CompareStr(p^.data.messageinf.str^,at^.data.messageinf.str^);
+ if i<0 then
+ insertstr(p,at^.l,count)
+ else if i>0 then
+ insertstr(p,at^.r,count)
+ else
+ Message1(parser_e_duplicate_message_label,p^.data.messageinf.str^);
+ end;
+ end;
+
+
+ procedure TVMTWriter.insertmsgint(p:TObject;arg:pointer);
+ var
+ i : longint;
+ pd : Tprocdef;
+ pt : pprocdeftree;
+ begin
+ if tsym(p).typ<>procsym then
+ exit;
+ for i:=0 to Tprocsym(p).ProcdefList.Count-1 do
+ begin
+ pd:=tprocdef(Tprocsym(p).ProcdefList[i]);
+ if po_msgint in pd.procoptions then
+ begin
+ new(pt);
+ pt^.data:=pd;
+ pt^.l:=nil;
+ pt^.r:=nil;
+ insertint(pt,root,plongint(arg)^);
+ end;
+ end;
+ end;
+
+
+ procedure TVMTWriter.insertmsgstr(p:TObject;arg:pointer);
+ var
+ i : longint;
+ pd : Tprocdef;
+ pt : pprocdeftree;
+ begin
+ if tsym(p).typ<>procsym then
+ exit;
+ for i:=0 to Tprocsym(p).ProcdefList.Count-1 do
+ begin
+ pd:=tprocdef(Tprocsym(p).ProcdefList[i]);
+ if po_msgstr in pd.procoptions then
+ begin
+ new(pt);
+ pt^.data:=pd;
+ pt^.l:=nil;
+ pt^.r:=nil;
+ insertstr(pt,root,plongint(arg)^);
+ end;
+ end;
+ end;
+
+
+ procedure TVMTWriter.writenames(p : pprocdeftree);
+ var
+ ca : pchar;
+ len : byte;
+ begin
+ current_asmdata.getdatalabel(p^.nl);
+ if assigned(p^.l) then
+ writenames(p^.l);
+ current_asmdata.asmlists[al_globals].concat(cai_align.create(const_align(sizeof(pint))));
+ current_asmdata.asmlists[al_globals].concat(Tai_label.Create(p^.nl));
+ len:=length(p^.data.messageinf.str^);
+ current_asmdata.asmlists[al_globals].concat(tai_const.create_8bit(len));
+ getmem(ca,len+1);
+ move(p^.data.messageinf.str^[1],ca^,len);
+ ca[len]:=#0;
+ current_asmdata.asmlists[al_globals].concat(Tai_string.Create_pchar(ca,len));
+ if assigned(p^.r) then
+ writenames(p^.r);
+ end;
+
+ procedure TVMTWriter.writestrentry(p : pprocdeftree);
+
+ begin
+ if assigned(p^.l) then
+ writestrentry(p^.l);
+
+ { write name label }
+ current_asmdata.asmlists[al_globals].concat(cai_align.create(const_align(sizeof(pint))));
+ current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(p^.nl));
+ current_asmdata.asmlists[al_globals].concat(cai_align.create(const_align(sizeof(pint))));
+ current_asmdata.asmlists[al_globals].concat(Tai_const.Createname(p^.data.mangledname,0));
+
+ if assigned(p^.r) then
+ writestrentry(p^.r);
+ end;
+
+
+ function TVMTWriter.genstrmsgtab : tasmlabel;
+ var
+ count : longint;
+ begin
+ root:=nil;
+ count:=0;
+ { insert all message handlers into a tree, sorted by name }
+ _class.symtable.SymList.ForEachCall(@insertmsgstr,@count);
+
+ { write all names }
+ if assigned(root) then
+ writenames(root);
+
+ { now start writing of the message string table }
+ current_asmdata.getdatalabel(result);
+ current_asmdata.asmlists[al_globals].concat(cai_align.create(const_align(sizeof(pint))));
+ current_asmdata.asmlists[al_globals].concat(Tai_label.Create(result));
+ current_asmdata.asmlists[al_globals].concat(cai_align.create(const_align(sizeof(longint))));
+ current_asmdata.asmlists[al_globals].concat(Tai_const.Create_32bit(count));
+ current_asmdata.asmlists[al_globals].concat(cai_align.create(const_align(sizeof(pint))));
+ if assigned(root) then
+ begin
+ writestrentry(root);
+ disposeprocdeftree(root);
+ end;
+ end;
+
+
+ procedure TVMTWriter.writeintentry(p : pprocdeftree);
+ begin
+ if assigned(p^.l) then
+ writeintentry(p^.l);
+
+ { write name label }
+ current_asmdata.asmlists[al_globals].concat(cai_align.create(const_align(sizeof(longint))));
+ current_asmdata.asmlists[al_globals].concat(Tai_const.Create_32bit(p^.data.messageinf.i));
+ current_asmdata.asmlists[al_globals].concat(cai_align.create(const_align(sizeof(pint))));
+ current_asmdata.asmlists[al_globals].concat(Tai_const.Createname(p^.data.mangledname,0));
+
+ if assigned(p^.r) then
+ writeintentry(p^.r);
+ end;
+
+
+ function TVMTWriter.genintmsgtab : tasmlabel;
+ var
+ r : tasmlabel;
+ count : longint;
+ begin
+ root:=nil;
+ count:=0;
+ { insert all message handlers into a tree, sorted by name }
+ _class.symtable.SymList.ForEachCall(@insertmsgint,@count);
+
+ { now start writing of the message string table }
+ current_asmdata.getdatalabel(r);
+ current_asmdata.asmlists[al_globals].concat(cai_align.create(const_align(sizeof(pint))));
+ current_asmdata.asmlists[al_globals].concat(Tai_label.Create(r));
+ genintmsgtab:=r;
+ current_asmdata.asmlists[al_globals].concat(cai_align.create(const_align(sizeof(longint))));
+ current_asmdata.asmlists[al_globals].concat(Tai_const.Create_32bit(count));
+ current_asmdata.asmlists[al_globals].concat(cai_align.create(const_align(sizeof(pint))));
+ if assigned(root) then
+ begin
+ writeintentry(root);
+ disposeprocdeftree(root);
+ end;
+ end;
+
+{$ifdef WITHDMT}
+
+{**************************************
+ DMT
+**************************************}
+
+ procedure TVMTWriter.insertdmtentry(p:TObject;arg:pointer);
+
+ var
+ hp : tprocdef;
+ pt : pprocdeftree;
+
+ begin
+ if tsym(p).typ=procsym then
+ begin
+ hp:=tprocsym(p).definition;
+ while assigned(hp) do
+ begin
+ if (po_msgint in hp.procoptions) then
+ begin
+ new(pt);
+ pt^.p:=hp;
+ pt^.l:=nil;
+ pt^.r:=nil;
+ insertint(pt,root);
+ end;
+ hp:=hp.nextoverloaded;
+ end;
+ end;
+ end;
+
+ procedure TVMTWriter.writedmtindexentry(p : pprocdeftree);
+
+ begin
+ if assigned(p^.l) then
+ writedmtindexentry(p^.l);
+ al_globals.concat(Tai_const.Create_32bit(p^.data.messageinf.i));
+ if assigned(p^.r) then
+ writedmtindexentry(p^.r);
+ end;
+
+ procedure TVMTWriter.writedmtaddressentry(p : pprocdeftree);
+
+ begin
+ if assigned(p^.l) then
+ writedmtaddressentry(p^.l);
+ al_globals.concat(Tai_const_symbol.Createname(p^.data.mangledname,0));
+ if assigned(p^.r) then
+ writedmtaddressentry(p^.r);
+ end;
+
+ function TVMTWriter.gendmt : tasmlabel;
+
+ var
+ r : tasmlabel;
+
+ begin
+ root:=nil;
+ count:=0;
+ gendmt:=nil;
+ { insert all message handlers into a tree, sorted by number }
+ _class.symtable.SymList.ForEachCall(insertdmtentry);
+
+ if count>0 then
+ begin
+ current_asmdata.getdatalabel(r);
+ gendmt:=r;
+ al_globals.concat(cai_align.create(const_align(sizeof(pint))));
+ al_globals.concat(Tai_label.Create(r));
+ { entries for caching }
+ al_globals.concat(Tai_const.Create_ptr(0));
+ al_globals.concat(Tai_const.Create_ptr(0));
+
+ al_globals.concat(Tai_const.Create_32bit(count));
+ if assigned(root) then
+ begin
+ writedmtindexentry(root);
+ writedmtaddressentry(root);
+ disposeprocdeftree(root);
+ end;
+ end;
+ end;
+
+{$endif WITHDMT}
+
+{**************************************
+ Published Methods
+**************************************}
+
+ procedure TVMTWriter.do_count_published_methods(p:TObject;arg:pointer);
+ var
+ i : longint;
+ pd : tprocdef;
+ begin
+ if (tsym(p).typ<>procsym) then
+ exit;
+ for i:=0 to Tprocsym(p).ProcdefList.Count-1 do
+ begin
+ pd:=tprocdef(Tprocsym(p).ProcdefList[i]);
+ if (pd.procsym=tsym(p)) and
+ (pd.visibility=vis_published) then
+ inc(plongint(arg)^);
+ end;
+ end;
+
+
+ procedure TVMTWriter.do_gen_published_methods(p:TObject;arg:pointer);
+ var
+ i : longint;
+ l : tasmlabel;
+ pd : tprocdef;
+ begin
+ if (tsym(p).typ<>procsym) then
+ exit;
+ for i:=0 to Tprocsym(p).ProcdefList.Count-1 do
+ begin
+ pd:=tprocdef(Tprocsym(p).ProcdefList[i]);
+ if (pd.procsym=tsym(p)) and
+ (pd.visibility=vis_published) then
+ begin
+ current_asmdata.getdatalabel(l);
+ new_section(current_asmdata.asmlists[al_typedconsts],sec_rodata_norel,l.name,const_align(sizeof(pint)));
+ current_asmdata.asmlists[al_typedconsts].concat(Tai_label.Create(l));
+ current_asmdata.asmlists[al_typedconsts].concat(Tai_const.Create_8bit(length(tsym(p).realname)));
+ current_asmdata.asmlists[al_typedconsts].concat(Tai_string.Create(tsym(p).realname));
+
+ current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(l));
+ if po_abstractmethod in pd.procoptions then
+ current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(nil))
+ else
+ current_asmdata.asmlists[al_globals].concat(Tai_const.Createname(pd.mangledname,0));
+ end;
+ end;
+ end;
+
+
+ function TVMTWriter.genpublishedmethodstable : tasmlabel;
+
+ var
+ l : tasmlabel;
+ count : longint;
+
+ begin
+ count:=0;
+ _class.symtable.SymList.ForEachCall(@do_count_published_methods,@count);
+ if count>0 then
+ begin
+ current_asmdata.getdatalabel(l);
+ current_asmdata.asmlists[al_globals].concat(cai_align.create(const_align(sizeof(pint))));
+ current_asmdata.asmlists[al_globals].concat(Tai_label.Create(l));
+ current_asmdata.asmlists[al_globals].concat(Tai_const.Create_32bit(count));
+ _class.symtable.SymList.ForEachCall(@do_gen_published_methods,nil);
+ genpublishedmethodstable:=l;
+ end
+ else
+ genpublishedmethodstable:=nil;
+ end;
+
+
+ function TVMTWriter.generate_field_table : tasmlabel;
+ var
+ i : longint;
+ sym : tsym;
+ fieldtable,
+ classtable : tasmlabel;
+ classindex,
+ fieldcount : longint;
+ classtablelist : TFPList;
+ begin
+ classtablelist:=TFPList.Create;
+ current_asmdata.getdatalabel(fieldtable);
+ current_asmdata.getdatalabel(classtable);
+ maybe_new_object_file(current_asmdata.asmlists[al_rtti]);
+ new_section(current_asmdata.asmlists[al_rtti],sec_rodata,classtable.name,const_align(sizeof(pint)));
+
+ { retrieve field info fields }
+ fieldcount:=0;
+ for i:=0 to _class.symtable.SymList.Count-1 do
+ begin
+ sym:=tsym(_class.symtable.SymList[i]);
+ if (sym.typ=fieldvarsym) and
+ (sym.visibility=vis_published) then
+ begin
+ if tfieldvarsym(sym).vardef.typ<>objectdef then
+ internalerror(200611032);
+ classindex:=classtablelist.IndexOf(tfieldvarsym(sym).vardef);
+ if classindex=-1 then
+ classtablelist.Add(tfieldvarsym(sym).vardef);
+ inc(fieldcount);
+ end;
+ end;
+
+ { write fields }
+ current_asmdata.asmlists[al_rtti].concat(Tai_label.Create(fieldtable));
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_16bit(fieldcount));
+ if (tf_requires_proper_alignment in target_info.flags) then
+ current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_sym(classtable));
+ for i:=0 to _class.symtable.SymList.Count-1 do
+ begin
+ sym:=tsym(_class.symtable.SymList[i]);
+ if (sym.typ=fieldvarsym) and
+ (sym.visibility=vis_published) then
+ begin
+ if (tf_requires_proper_alignment in target_info.flags) then
+ current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(pint)));
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_pint(tfieldvarsym(sym).fieldoffset));
+ classindex:=classtablelist.IndexOf(tfieldvarsym(sym).vardef);
+ if classindex=-1 then
+ internalerror(200611033);
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_16bit(classindex+1));
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(length(tfieldvarsym(sym).realname)));
+ current_asmdata.asmlists[al_rtti].concat(Tai_string.Create(tfieldvarsym(sym).realname));
+ end;
+ end;
+
+ { generate the class table }
+ current_asmdata.asmlists[al_rtti].concat(cai_align.create(const_align(sizeof(pint))));
+ current_asmdata.asmlists[al_rtti].concat(Tai_label.Create(classtable));
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_16bit(classtablelist.count));
+ if (tf_requires_proper_alignment in target_info.flags) then
+ current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
+ for i:=0 to classtablelist.Count-1 do
+ current_asmdata.asmlists[al_rtti].concat(Tai_const.Createname(tobjectdef(classtablelist[i]).vmt_mangledname,0));
+
+ classtablelist.free;
+ result:=fieldtable;
+ end;
+
+
+{**************************************
+ Interface tables
+**************************************}
+
+ function TVMTWriter.intf_get_vtbl_name(AImplIntf:TImplementedInterface): string;
+ begin
+ result:=make_mangledname('VTBL',_class.owner,_class.objname^+'_$_'+AImplIntf.IntfDef.objname^);
+ end;
+
+
+ procedure TVMTWriter.intf_create_vtbl(rawdata: TAsmList;AImplIntf:TImplementedInterface);
+ var
+ pd : tprocdef;
+ vtblstr,
+ hs : string;
+ i : longint;
+ begin
+ vtblstr:=intf_get_vtbl_name(AImplIntf);
+ section_symbol_start(rawdata,vtblstr,AT_DATA,true,sec_data,const_align(sizeof(pint)));
+ if assigned(AImplIntf.procdefs) then
+ begin
+ for i:=0 to AImplIntf.procdefs.count-1 do
+ begin
+ pd:=tprocdef(AImplIntf.procdefs[i]);
+ hs:=make_mangledname('WRPR',_class.owner,_class.objname^+'_$_'+AImplIntf.IntfDef.objname^+'_$_'+
+ tostr(i)+'_$_'+pd.mangledname);
+ { create reference }
+ rawdata.concat(Tai_const.Createname(hs,0));
+ end;
+ end;
+ section_symbol_end(rawdata,vtblstr);
+ end;
+
+
+ procedure TVMTWriter.intf_gen_intf_ref(rawdata: TAsmList;AImplIntf:TImplementedInterface);
+ var
+ iidlabel,
+ guidlabel : tasmlabel;
+ i: longint;
+ pd: tprocdef;
+ begin
+ { GUID }
+ if AImplIntf.IntfDef.objecttype in [odt_interfacecom] then
+ begin
+ { label for GUID }
+ current_asmdata.getdatalabel(guidlabel);
+ rawdata.concat(cai_align.create(const_align(sizeof(pint))));
+ rawdata.concat(Tai_label.Create(guidlabel));
+ with AImplIntf.IntfDef.iidguid^ do
+ begin
+ rawdata.concat(Tai_const.Create_32bit(longint(D1)));
+ rawdata.concat(Tai_const.Create_16bit(D2));
+ rawdata.concat(Tai_const.Create_16bit(D3));
+ for i:=Low(D4) to High(D4) do
+ rawdata.concat(Tai_const.Create_8bit(D4[i]));
+ end;
+ current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(guidlabel));
+ end
+ else
+ begin
+ { nil for Corba interfaces }
+ current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(nil));
+ end;
+ { VTable }
+ current_asmdata.asmlists[al_globals].concat(Tai_const.Createname(intf_get_vtbl_name(AImplIntf.VtblImplIntf),0));
+ { IOffset field }
+ case AImplIntf.VtblImplIntf.IType of
+ etFieldValue, etFieldValueClass,
+ etStandard:
+ current_asmdata.asmlists[al_globals].concat(Tai_const.Create_pint(AImplIntf.VtblImplIntf.IOffset));
+ etStaticMethodResult, etStaticMethodClass:
+ current_asmdata.asmlists[al_globals].concat(Tai_const.Createname(
+ tprocdef(tpropertysym(AImplIntf.ImplementsGetter).propaccesslist[palt_read].procdef).mangledname,
+ 0
+ ));
+ etVirtualMethodResult, etVirtualMethodClass:
+ begin
+ pd := tprocdef(tpropertysym(AImplIntf.ImplementsGetter).propaccesslist[palt_read].procdef);
+ current_asmdata.asmlists[al_globals].concat(Tai_const.Create_pint(tobjectdef(pd.struct).vmtmethodoffset(pd.extnumber)));
+ end;
+ else
+ internalerror(200802162);
+ end;
+
+ { IIDStr }
+ current_asmdata.getdatalabel(iidlabel);
+ rawdata.concat(cai_align.create(const_align(sizeof(pint))));
+ rawdata.concat(Tai_label.Create(iidlabel));
+ rawdata.concat(Tai_const.Create_8bit(length(AImplIntf.IntfDef.iidstr^)));
+ if AImplIntf.IntfDef.objecttype=odt_interfacecom then
+ rawdata.concat(Tai_string.Create(upper(AImplIntf.IntfDef.iidstr^)))
+ else
+ rawdata.concat(Tai_string.Create(AImplIntf.IntfDef.iidstr^));
+ current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(iidlabel));
+ { IType }
+ current_asmdata.asmlists[al_globals].concat(Tai_const.Create_pint(aint(AImplIntf.VtblImplIntf.IType)));
+ end;
+
+
+ function TVMTWriter.intf_write_table:TAsmLabel;
+ var
+ rawdata : TAsmList;
+ i : longint;
+ ImplIntf : TImplementedInterface;
+ intftablelab : tasmlabel;
+ begin
+ current_asmdata.getdatalabel(intftablelab);
+ current_asmdata.asmlists[al_globals].concat(cai_align.create(const_align(sizeof(pint))));
+ current_asmdata.asmlists[al_globals].concat(Tai_label.Create(intftablelab));
+ current_asmdata.asmlists[al_globals].concat(Tai_const.Create_pint(_class.ImplementedInterfaces.count));
+ rawdata:=TAsmList.Create;
+ { Write vtbls }
+ for i:=0 to _class.ImplementedInterfaces.count-1 do
+ begin
+ ImplIntf:=TImplementedInterface(_class.ImplementedInterfaces[i]);
+ if ImplIntf.VtblImplIntf=ImplIntf then
+ intf_create_vtbl(rawdata,ImplIntf);
+ end;
+ { Write vtbl references }
+ for i:=0 to _class.ImplementedInterfaces.count-1 do
+ begin
+ ImplIntf:=TImplementedInterface(_class.ImplementedInterfaces[i]);
+ intf_gen_intf_ref(rawdata,ImplIntf);
+ end;
+ { Write interface table }
+ current_asmdata.asmlists[al_globals].concatlist(rawdata);
+ rawdata.free;
+ result:=intftablelab;
+ end;
+
+
+ { Write interface identifiers to the data section }
+ procedure TVMTWriter.writeinterfaceids;
+ var
+ i : longint;
+ s : string;
+ begin
+ if assigned(_class.iidguid) then
+ begin
+ s:=make_mangledname('IID',_class.owner,_class.objname^);
+ maybe_new_object_file(current_asmdata.asmlists[al_globals]);
+ new_section(current_asmdata.asmlists[al_globals],sec_rodata,s,const_align(sizeof(pint)));
+ current_asmdata.asmlists[al_globals].concat(Tai_symbol.Createname_global(s,AT_DATA,0));
+ current_asmdata.asmlists[al_globals].concat(Tai_const.Create_32bit(longint(_class.iidguid^.D1)));
+ current_asmdata.asmlists[al_globals].concat(Tai_const.Create_16bit(_class.iidguid^.D2));
+ current_asmdata.asmlists[al_globals].concat(Tai_const.Create_16bit(_class.iidguid^.D3));
+ for i:=Low(_class.iidguid^.D4) to High(_class.iidguid^.D4) do
+ current_asmdata.asmlists[al_globals].concat(Tai_const.Create_8bit(_class.iidguid^.D4[i]));
+ end;
+ maybe_new_object_file(current_asmdata.asmlists[al_globals]);
+ s:=make_mangledname('IIDSTR',_class.owner,_class.objname^);
+ new_section(current_asmdata.asmlists[al_globals],sec_rodata,s,0);
+ current_asmdata.asmlists[al_globals].concat(Tai_symbol.Createname_global(s,AT_DATA,0));
+ current_asmdata.asmlists[al_globals].concat(Tai_const.Create_8bit(length(_class.iidstr^)));
+ current_asmdata.asmlists[al_globals].concat(Tai_string.Create(_class.iidstr^));
+ end;
+
+
+ procedure TVMTWriter.writevirtualmethods(List:TAsmList);
+ var
+ vmtpd : tprocdef;
+ vmtentry : pvmtentry;
+ i : longint;
+ procname : string;
+{$ifdef vtentry}
+ hs : string;
+{$endif vtentry}
+ begin
+ if not assigned(_class.VMTEntries) then
+ exit;
+ for i:=0 to _class.VMTEntries.Count-1 do
+ begin
+ vmtentry:=pvmtentry(_class.vmtentries[i]);
+ vmtpd:=vmtentry^.procdef;
+ { safety checks }
+ if not(po_virtualmethod in vmtpd.procoptions) then
+ internalerror(200611082);
+ if vmtpd.extnumber<>i then
+ internalerror(200611083);
+ if (po_abstractmethod in vmtpd.procoptions) then
+ procname:='FPC_ABSTRACTERROR'
+ else if not wpoinfomanager.optimized_name_for_vmt(_class,vmtpd,procname) then
+ procname:=vmtpd.mangledname;
+ List.concat(Tai_const.createname(procname,0));
+{$ifdef vtentry}
+ hs:='VTENTRY'+'_'+_class.vmt_mangledname+'$$'+tostr(_class.vmtmethodoffset(i) div sizeof(pint));
+ current_asmdata.asmlists[al_globals].concat(tai_symbol.CreateName(hs,AT_DATA,0));
+{$endif vtentry}
+ end;
+ end;
+
+
+ procedure TVMTWriter.writevmt;
+ var
+ methodnametable,intmessagetable,
+ strmessagetable,classnamelabel,
+ fieldtablelabel : tasmlabel;
+ hs: string;
+{$ifdef WITHDMT}
+ dmtlabel : tasmlabel;
+{$endif WITHDMT}
+ interfacetable : tasmlabel;
+ begin
+{$ifdef WITHDMT}
+ dmtlabel:=gendmt;
+{$endif WITHDMT}
+
+ { write tables for classes, this must be done before the actual
+ class is written, because we need the labels defined }
+ if is_class(_class) then
+ begin
+ current_asmdata.getdatalabel(classnamelabel);
+ maybe_new_object_file(current_asmdata.asmlists[al_globals]);
+ new_section(current_asmdata.asmlists[al_globals],sec_rodata,classnamelabel.name,const_align(sizeof(pint)));
+
+ { interface table }
+ if _class.ImplementedInterfaces.count>0 then
+ interfacetable:=intf_write_table;
+
+ methodnametable:=genpublishedmethodstable;
+ fieldtablelabel:=generate_field_table;
+ { write class name }
+ current_asmdata.asmlists[al_globals].concat(Tai_label.Create(classnamelabel));
+ hs:=_class.RttiName;
+ current_asmdata.asmlists[al_globals].concat(Tai_const.Create_8bit(length(hs)));
+ current_asmdata.asmlists[al_globals].concat(Tai_string.Create(hs));
+
+ { generate message and dynamic tables }
+ if (oo_has_msgstr in _class.objectoptions) then
+ strmessagetable:=genstrmsgtab;
+ if (oo_has_msgint in _class.objectoptions) then
+ intmessagetable:=genintmsgtab;
+ end;
+
+ { write debug info }
+ maybe_new_object_file(current_asmdata.asmlists[al_globals]);
+ new_section(current_asmdata.asmlists[al_globals],sec_rodata,_class.vmt_mangledname,const_align(sizeof(pint)));
+ current_asmdata.asmlists[al_globals].concat(Tai_symbol.Createname_global(_class.vmt_mangledname,AT_DATA,0));
+
+ { determine the size with symtable.datasize, because }
+ { size gives back 4 for classes }
+ current_asmdata.asmlists[al_globals].concat(Tai_const.Create(aitconst_ptr,tObjectSymtable(_class.symtable).datasize));
+ current_asmdata.asmlists[al_globals].concat(Tai_const.Create(aitconst_ptr,-int64(tObjectSymtable(_class.symtable).datasize)));
+{$ifdef WITHDMT}
+ if _class.classtype=ct_object then
+ begin
+ if assigned(dmtlabel) then
+ current_asmdata.asmlists[al_globals].concat(Tai_const_symbol.Create(dmtlabel)))
+ else
+ current_asmdata.asmlists[al_globals].concat(Tai_const.Create_ptr(0));
+ end;
+{$endif WITHDMT}
+ { write pointer to parent VMT, this isn't implemented in TP }
+ { but this is not used in FPC ? (PM) }
+ { it's not used yet, but the delphi-operators as and is need it (FK) }
+ { it is not written for parents that don't have any vmt !! }
+ if assigned(_class.childof) and
+ (oo_has_vmt in _class.childof.objectoptions) then
+ current_asmdata.asmlists[al_globals].concat(Tai_const.Createname(_class.childof.vmt_mangledname,0))
+ else
+ current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(nil));
+
+ { write extended info for classes, for the order see rtl/inc/objpash.inc }
+ if is_class(_class) then
+ begin
+ { pointer to class name string }
+ current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(classnamelabel));
+ { pointer to dynamic table or nil }
+ if (oo_has_msgint in _class.objectoptions) then
+ current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(intmessagetable))
+ else
+ current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(nil));
+ { pointer to method table or nil }
+ current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(methodnametable));
+ { pointer to field table }
+ current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(fieldtablelabel));
+ { pointer to type info of published section }
+ current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(RTTIWriter.get_rtti_label(_class,fullrtti)));
+ { inittable for con-/destruction }
+ if _class.members_need_inittable then
+ current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(RTTIWriter.get_rtti_label(_class,initrtti)))
+ else
+ current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(nil));
+ { auto table }
+ current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(nil));
+ { interface table }
+ if _class.ImplementedInterfaces.count>0 then
+ current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(interfacetable))
+ else if _class.implements_any_interfaces then
+ current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(nil))
+ else
+ current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(current_asmdata.RefAsmSymbol('FPC_EMPTYINTF')));
+ { table for string messages }
+ if (oo_has_msgstr in _class.objectoptions) then
+ current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(strmessagetable))
+ else
+ current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(nil));
+ end;
+ { write virtual methods }
+ writevirtualmethods(current_asmdata.asmlists[al_globals]);
+ current_asmdata.asmlists[al_globals].concat(Tai_const.create(aitconst_ptr,0));
+ { write the size of the VMT }
+ current_asmdata.asmlists[al_globals].concat(Tai_symbol_end.Createname(_class.vmt_mangledname));
+{$ifdef vtentry}
+ { write vtinherit symbol to notify the linker of the class inheritance tree }
+ hs:='VTINHERIT'+'_'+_class.vmt_mangledname+'$$';
+ if assigned(_class.childof) then
+ hs:=hs+_class.childof.vmt_mangledname
+ else
+ hs:=hs+_class.vmt_mangledname;
+ current_asmdata.asmlists[al_globals].concat(tai_symbol.CreateName(hs,AT_DATA,0));
+{$endif vtentry}
+ end;
+
+
+end.
diff --git a/closures/compiler/nobjc.pas b/closures/compiler/nobjc.pas
new file mode 100644
index 0000000000..a10f13a83c
--- /dev/null
+++ b/closures/compiler/nobjc.pas
@@ -0,0 +1,169 @@
+{
+ Copyright (c) 2009 by Jonas Maebe
+
+ This unit implements Objective-C nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+{ @abstract(This unit implements Objective-C nodes)
+ This unit contains various nodes to implement Objective-Pascal and to
+ interface with the Objective-C runtime.
+}
+
+unit nobjc;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ node;
+
+type
+ tobjcselectornode = class(tunarynode)
+ public
+ constructor create(formethod: tnode);
+ function pass_typecheck: tnode;override;
+ function pass_1: tnode;override;
+ end;
+ tobjcselectornodeclass = class of tobjcselectornode;
+
+ tobjcprotocolnode = class(tunarynode)
+ public
+ constructor create(forprotocol: tnode);
+ function pass_typecheck: tnode;override;
+ function pass_1: tnode;override;
+ end;
+ tobjcprotocolnodeclass = class of tobjcprotocolnode;
+
+var
+ cobjcselectornode : tobjcselectornodeclass;
+ cobjcprotocolnode : tobjcprotocolnodeclass;
+
+implementation
+
+uses
+ sysutils,
+ globtype,globals,cclasses,systems,
+ verbose,pass_1,
+ defutil,
+ symtype,symtable,symdef,symconst,symsym,
+ paramgr,
+ nutils,
+ nbas,nld,ncnv,ncon,ncal,nmem,
+ objcutil,
+ cgbase;
+
+
+{*****************************************************************************
+ TOBJCSELECTORNODE
+*****************************************************************************}
+
+constructor tobjcselectornode.create(formethod: tnode);
+ begin
+ inherited create(objcselectorn,formethod);
+ end;
+
+
+function tobjcselectornode.pass_typecheck: tnode;
+ var
+ len: longint;
+ s: shortstring;
+ begin
+ if not(m_objectivec1 in current_settings.modeswitches) then
+ Message(parser_f_modeswitch_objc_required);
+ result:=nil;
+ typecheckpass(left);
+ { argument can be
+ a) an objc method
+ b) a pchar, zero-based chararray or ansistring
+ }
+ case left.nodetype of
+ loadn:
+ begin
+ if (left.resultdef.typ=procdef) and
+ (po_objc in tprocdef(left.resultdef).procoptions) then
+ begin
+ { ok }
+ end
+ else
+ CGMessage1(type_e_expected_objc_method_but_got,left.resultdef.typename);
+ end;
+ stringconstn:
+ begin
+ if not objcvalidselectorname(tstringconstnode(left).value_str,
+ tstringconstnode(left).len) then
+ begin
+ len:=tstringconstnode(left).len;
+ if (len>255) then
+ len:=255;
+ setlength(s,len);
+ move(tstringconstnode(left).value_str^,s[1],len);
+ CGMessage1(type_e_invalid_objc_selector_name,s);
+ exit;
+ end;
+ end
+ else
+ CGMessage(type_e_expected_objc_method);
+ end;
+ resultdef:=objc_seltype;
+ end;
+
+
+function tobjcselectornode.pass_1: tnode;
+ begin
+ result:=nil;
+ expectloc:=LOC_CREFERENCE;
+ end;
+
+
+{*****************************************************************************
+ TOBJPROTOCOLNODE
+*****************************************************************************}
+
+constructor tobjcprotocolnode.create(forprotocol: tnode);
+ begin
+ inherited create(objcprotocoln,forprotocol);
+ end;
+
+
+function tobjcprotocolnode.pass_typecheck: tnode;
+ begin
+ if not(m_objectivec1 in current_settings.modeswitches) then
+ Message(parser_f_modeswitch_objc_required);
+ result:=nil;
+ typecheckpass(left);
+ if (left.nodetype<>typen) then
+ MessagePos(left.fileinfo,type_e_type_id_expected)
+ else if not is_objcprotocol(left.resultdef) then
+ MessagePos2(left.fileinfo,type_e_incompatible_types,left.resultdef.typename,'ObjCProtocol');
+ resultdef:=objc_protocoltype;
+ end;
+
+
+function tobjcprotocolnode.pass_1: tnode;
+ begin
+ result:=ccallnode.createinternresfromunit('OBJC','OBJC_GETPROTOCOL',
+ ccallparanode.create(cstringconstnode.createstr(tobjectdef(left.resultdef).objextname^),nil),
+ resultdef
+ );
+ typecheckpass(result);
+ end;
+
+
+end.
+
diff --git a/closures/compiler/node.pas b/closures/compiler/node.pas
new file mode 100644
index 0000000000..5b92ee5427
--- /dev/null
+++ b/closures/compiler/node.pas
@@ -0,0 +1,1301 @@
+{
+ Copyright (c) 2000-2002 by Florian Klaempfl
+
+ Basic node handling
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit node;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cclasses,
+ globtype,globals,
+ cpubase,cgbase,cgutils,
+ aasmbase,
+ symtype,
+ optbase;
+
+ type
+ tnodetype = (
+ emptynode, {No node (returns nil when loading from ppu)}
+ addn, {Represents the + operator}
+ muln, {Represents the * operator}
+ subn, {Represents the - operator}
+ divn, {Represents the div operator}
+ symdifn, {Represents the >< operator}
+ modn, {Represents the mod operator}
+ assignn, {Represents an assignment}
+ loadn, {Represents the use of a variabele}
+ rangen, {Represents a range (i.e. 0..9)}
+ ltn, {Represents the < operator}
+ lten, {Represents the <= operator}
+ gtn, {Represents the > operator}
+ gten, {Represents the >= operator}
+ equaln, {Represents the = operator}
+ unequaln, {Represents the <> operator}
+ inn, {Represents the in operator}
+ orn, {Represents the or operator}
+ xorn, {Represents the xor operator}
+ shrn, {Represents the shr operator}
+ shln, {Represents the shl operator}
+ slashn, {Represents the / operator}
+ andn, {Represents the and operator}
+ subscriptn, {Field in a record/object}
+ derefn, {Dereferences a pointer}
+ addrn, {Represents the @ operator}
+ ordconstn, {Represents an ordinal value}
+ typeconvn, {Represents type-conversion/typecast}
+ calln, {Represents a call node}
+ callparan, {Represents a parameter}
+ realconstn, {Represents a real value}
+ unaryminusn, {Represents a sign change (i.e. -2)}
+ unaryplusn, {Represents a check for +Value}
+ asmn, {Represents an assembler node }
+ vecn, {Represents array indexing}
+ pointerconstn, {Represents a pointer constant}
+ stringconstn, {Represents a string constant}
+ notn, {Represents the not operator}
+ inlinen, {Internal procedures (i.e. writeln)}
+ niln, {Represents the nil pointer}
+ errorn, {This part of the tree could not be
+ parsed because of a compiler error}
+ typen, {A type name. Used for i.e. typeof(obj)}
+ setelementn, {A set element(s) (i.e. [a,b] and also [a..b])}
+ setconstn, {A set constant (i.e. [1,2])}
+ blockn, {A block of statements}
+ statementn, {One statement in a block of nodes}
+ ifn, {An if statement}
+ breakn, {A break statement}
+ continuen, {A continue statement}
+ whilerepeatn, {A while or repeat statement}
+ forn, {A for loop}
+ exitn, {An exit statement}
+ withn, {A with statement}
+ casen, {A case statement}
+ labeln, {A label}
+ goton, {A goto statement}
+ tryexceptn, {A try except block}
+ raisen, {A raise statement}
+ tryfinallyn, {A try finally statement}
+ onn, {For an on statement in exception code}
+ isn, {Represents the is operator}
+ asn, {Represents the as typecast}
+ starstarn, {Represents the ** operator exponentiation }
+ arrayconstructorn, {Construction node for [...] parsing}
+ arrayconstructorrangen, {Range element to allow sets in array construction tree}
+ tempcreaten, { for temps in the result/firstpass }
+ temprefn, { references to temps }
+ tempdeleten, { for temps in the result/firstpass }
+ addoptn, { added for optimizations where we cannot suppress }
+ nothingn, { NOP, Do nothing}
+ loadvmtaddrn, { Load the address of the VMT of a class/object}
+ guidconstn, { A GUID COM Interface constant }
+ rttin, { Rtti information so they can be accessed in result/firstpass}
+ loadparentfpn, { Load the framepointer of the parent for nested procedures }
+ dataconstn, { node storing some binary data }
+ objcselectorn, { node for an Objective-C message selector }
+ objcprotocoln { node for an Objective-C @protocol() expression (returns metaclass associated with protocol) }
+ );
+
+ tnodetypeset = set of tnodetype;
+ pnodetypeset = ^tnodetypeset;
+
+ const
+ nodetype2str : array[tnodetype] of string[24] = (
+ '<emptynode>',
+ 'addn',
+ 'muln',
+ 'subn',
+ 'divn',
+ 'symdifn',
+ 'modn',
+ 'assignn',
+ 'loadn',
+ 'rangen',
+ 'ltn',
+ 'lten',
+ 'gtn',
+ 'gten',
+ 'equaln',
+ 'unequaln',
+ 'inn',
+ 'orn',
+ 'xorn',
+ 'shrn',
+ 'shln',
+ 'slashn',
+ 'andn',
+ 'subscriptn',
+ 'derefn',
+ 'addrn',
+ 'ordconstn',
+ 'typeconvn',
+ 'calln',
+ 'callparan',
+ 'realconstn',
+ 'unaryminusn',
+ 'unaryplusn',
+ 'asmn',
+ 'vecn',
+ 'pointerconstn',
+ 'stringconstn',
+ 'notn',
+ 'inlinen',
+ 'niln',
+ 'errorn',
+ 'typen',
+ 'setelementn',
+ 'setconstn',
+ 'blockn',
+ 'statementn',
+ 'ifn',
+ 'breakn',
+ 'continuen',
+ 'whilerepeatn',
+ 'forn',
+ 'exitn',
+ 'withn',
+ 'casen',
+ 'labeln',
+ 'goton',
+ 'tryexceptn',
+ 'raisen',
+ 'tryfinallyn',
+ 'onn',
+ 'isn',
+ 'asn',
+ 'starstarn',
+ 'arrayconstructn',
+ 'arrayconstructrangen',
+ 'tempcreaten',
+ 'temprefn',
+ 'tempdeleten',
+ 'addoptn',
+ 'nothingn',
+ 'loadvmtaddrn',
+ 'guidconstn',
+ 'rttin',
+ 'loadparentfpn',
+ 'dataconstn',
+ 'objcselectorn',
+ 'objcprotocoln');
+
+ type
+ { all boolean field of ttree are now collected in flags }
+ tnodeflag = (
+ nf_swapable, { tbinop operands can be swaped }
+ nf_swapped, { tbinop operands are swaped }
+ nf_error,
+
+ { general }
+ nf_pass1_done,
+ nf_write, { Node is written to }
+ nf_modify, { Node is modified }
+ nf_is_funcret,
+ nf_isproperty,
+ nf_processing,
+
+ { taddrnode }
+ nf_typedaddr,
+
+ { tderefnode }
+ nf_no_checkpointer,
+
+ { tvecnode }
+ nf_memindex,
+ nf_memseg,
+ nf_callunique,
+
+ { tloadnode/ttypeconvnode }
+ nf_absolute,
+
+ { taddnode }
+ nf_is_currency,
+ nf_has_pointerdiv,
+ nf_short_bool,
+
+ { tmoddivnode }
+ nf_isomod,
+
+ { tassignmentnode }
+ nf_assign_done_in_right,
+
+ { tarrayconstructnode }
+ nf_forcevaria,
+ nf_novariaallowed,
+
+ { ttypeconvnode, and the first one also treal/ord/pointerconstn }
+ { second one also for subtractions of u32-u32 implicitly upcasted to s64 }
+ nf_explicit,
+ nf_internal, { no warnings/hints generated }
+ nf_load_procvar,
+
+ { tinlinenode }
+ nf_inlineconst,
+
+ { tasmnode }
+ nf_get_asm_position,
+
+ { tblocknode }
+ nf_block_with_exit,
+
+ { tloadvmtaddrnode }
+ nf_ignore_for_wpo { we know that this loadvmtaddrnode cannot be used to construct a class instance }
+
+ { WARNING: there are now 32 elements in this type, and a set of this
+ type is written to the PPU. So before adding any more elements,
+ either move some flags to specific nodes, or stream a normalset
+ to the ppu
+ }
+
+ );
+
+ tnodeflags = set of tnodeflag;
+
+ const
+ { contains the flags which must be equal for the equality }
+ { of nodes }
+ flagsequal : tnodeflags = [nf_error];
+
+ type
+ tnodelist = class
+ end;
+
+ pnode = ^tnode;
+ { basic class for the intermediated representation fpc uses }
+ tnode = class
+ private
+ fppuidx : longint;
+ function getppuidx:longint;
+ public
+ { type of this node }
+ nodetype : tnodetype;
+ { type of the current code block, general/const/type }
+ blocktype : tblock_type;
+ { expected location of the result of this node (pass1) }
+ expectloc : tcgloc;
+ { the location of the result of this node (pass2) }
+ location : tlocation;
+ { the parent node of this is node }
+ { this field is set by concattolist }
+ parent : tnode;
+ { next node in control flow on the same block level, i.e.
+ for loop nodes, this is the next node after the end of the loop,
+ same for if and case, if this field is nil, the next node is the procedure exit,
+ for the last node in a loop this is set to the loop header
+ this field is set only for control flow nodes }
+ successor : tnode;
+ { there are some properties about the node stored }
+ flags : tnodeflags;
+ resultdef : tdef;
+ resultdefderef : tderef;
+ fileinfo : tfileposinfo;
+ localswitches : tlocalswitches;
+ verbosity : longint;
+ optinfo : poptinfo;
+ constructor create(t:tnodetype);
+ { this constructor is only for creating copies of class }
+ { the fields are copied by getcopy }
+ constructor createforcopy;
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);virtual;
+ destructor destroy;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);virtual;
+ procedure buildderefimpl;virtual;
+ procedure derefimpl;virtual;
+ procedure resolveppuidx;virtual;
+
+ { toggles the flag }
+ procedure toggleflag(f : tnodeflag);
+
+ { the 1.1 code generator may override pass_1 }
+ { and it need not to implement det_* then }
+ { 1.1: pass_1 returns a value<>0 if the node has been transformed }
+ { 2.0: runs pass_typecheck and det_temp }
+ function pass_1 : tnode;virtual;abstract;
+ { dermines the resultdef of the node }
+ function pass_typecheck : tnode;virtual;abstract;
+
+ { tries to simplify the node, returns a value <>nil if a simplified
+ node has been created }
+ function simplify(forinline : boolean) : tnode;virtual;
+{$ifdef state_tracking}
+ { Does optimizations by keeping track of the variable states
+ in a procedure }
+ function track_state_pass(exec_known:boolean):boolean;virtual;
+{$endif}
+ { For a t1:=t2 tree, mark the part of the tree t1 that gets
+ written to (normally the loadnode) as write access. }
+ procedure mark_write;virtual;
+ { dermines the number of necessary temp. locations to evaluate
+ the node }
+ procedure det_temp;virtual;abstract;
+
+ procedure pass_generate_code;virtual;abstract;
+
+ { comparing of nodes }
+ function isequal(p : tnode) : boolean;
+ { to implement comparisation, override this method }
+ function docompare(p : tnode) : boolean;virtual;
+ { wrapper for getcopy }
+ function getcopy : tnode;
+
+ { does the real copying of a node }
+ function dogetcopy : tnode;virtual;
+
+ { returns the real loadn/temprefn a node refers to,
+ skipping (absolute) equal type conversions }
+ function actualtargetnode: tnode;virtual;
+
+ procedure insertintolist(l : tnodelist);virtual;
+ { writes a node for debugging purpose, shouldn't be called }
+ { direct, because there is no test for nil, use printnode }
+ { to write a complete tree }
+ procedure printnodeinfo(var t:text);virtual;
+ procedure printnodedata(var t:text);virtual;
+ procedure printnodetree(var t:text);virtual;
+ procedure concattolist(l : tlinkedlist);virtual;
+ function ischild(p : tnode) : boolean;virtual;
+
+ { ensures that the optimizer info record is allocated }
+ function allocoptinfo : poptinfo;inline;
+ property ppuidx:longint read getppuidx;
+ end;
+
+ tnodeclass = class of tnode;
+
+ tnodeclassarray = array[tnodetype] of tnodeclass;
+
+ { this node is the anchestor for all nodes with at least }
+ { one child, you have to use it if you want to use }
+ { true- and current_procinfo.CurrFalseLabel }
+ //punarynode = ^tunarynode;
+ tunarynode = class(tnode)
+ left : tnode;
+ constructor create(t:tnodetype;l : tnode);
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
+ destructor destroy;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderefimpl;override;
+ procedure derefimpl;override;
+ procedure concattolist(l : tlinkedlist);override;
+ function ischild(p : tnode) : boolean;override;
+ function docompare(p : tnode) : boolean;override;
+ function dogetcopy : tnode;override;
+ procedure insertintolist(l : tnodelist);override;
+ procedure printnodedata(var t:text);override;
+ end;
+
+ //pbinarynode = ^tbinarynode;
+ tbinarynode = class(tunarynode)
+ right : tnode;
+ constructor create(t:tnodetype;l,r : tnode);
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
+ destructor destroy;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderefimpl;override;
+ procedure derefimpl;override;
+ procedure concattolist(l : tlinkedlist);override;
+ function ischild(p : tnode) : boolean;override;
+ function docompare(p : tnode) : boolean;override;
+ procedure swapleftright;
+ function dogetcopy : tnode;override;
+ procedure insertintolist(l : tnodelist);override;
+ procedure printnodedata(var t:text);override;
+ procedure printnodelist(var t:text);
+ end;
+
+ //ptertiarynode = ^ttertiarynode;
+ ttertiarynode = class(tbinarynode)
+ third : tnode;
+ constructor create(_t:tnodetype;l,r,t : tnode);
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
+ destructor destroy;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderefimpl;override;
+ procedure derefimpl;override;
+ procedure concattolist(l : tlinkedlist);override;
+ function ischild(p : tnode) : boolean;override;
+ function docompare(p : tnode) : boolean;override;
+ function dogetcopy : tnode;override;
+ procedure insertintolist(l : tnodelist);override;
+ procedure printnodedata(var t:text);override;
+ end;
+
+ tbinopnode = class(tbinarynode)
+ constructor create(t:tnodetype;l,r : tnode);virtual;
+ function docompare(p : tnode) : boolean;override;
+ end;
+
+ var
+ { array with all class types for tnodes }
+ nodeclass : tnodeclassarray;
+
+ function nodeppuidxget(i:longint):tnode;
+ function ppuloadnode(ppufile:tcompilerppufile):tnode;
+ procedure ppuwritenode(ppufile:tcompilerppufile;n:tnode);
+ function ppuloadnodetree(ppufile:tcompilerppufile):tnode;
+ procedure ppuwritenodetree(ppufile:tcompilerppufile;n:tnode);
+
+ const
+ printnodespacing = ' ';
+ var
+ { indention used when writing the tree to the screen }
+ printnodeindention : string;
+
+ procedure printnodeindent;
+ procedure printnodeunindent;
+ procedure printnode(var t:text;n:tnode);
+ procedure printnode(n:tnode);
+
+ function is_constnode(p : tnode) : boolean;
+ function is_constintnode(p : tnode) : boolean;
+ function is_constcharnode(p : tnode) : boolean;
+ function is_constrealnode(p : tnode) : boolean;
+ function is_constboolnode(p : tnode) : boolean;
+ function is_constenumnode(p : tnode) : boolean;
+ function is_constwidecharnode(p : tnode) : boolean;
+ function is_constpointernode(p : tnode) : boolean;
+ function is_conststringnode(p : tnode) : boolean;
+ function is_constwidestringnode(p : tnode) : boolean;
+ function is_conststring_or_constcharnode(p : tnode) : boolean;
+
+
+implementation
+
+ uses
+ cutils,verbose,ppu,comphook,
+ symconst,
+ nutils,nflw,
+ defutil;
+
+ const
+ ppunodemarker = 255;
+
+
+{****************************************************************************
+ Helpers
+ ****************************************************************************}
+
+ var
+ nodeppulist : TFPObjectList;
+ nodeppuidx : longint;
+
+
+ procedure nodeppuidxcreate;
+ begin
+ nodeppulist:=TFPObjectList.Create(false);
+ nodeppuidx:=0;
+ end;
+
+
+ procedure nodeppuidxresolve;
+ var
+ i : longint;
+ n : tnode;
+ begin
+ for i:=0 to nodeppulist.count-1 do
+ begin
+ n:=tnode(nodeppulist[i]);
+ if assigned(n) then
+ n.resolveppuidx;
+ end;
+ end;
+
+
+ procedure nodeppuidxfree;
+ begin
+ nodeppulist.free;
+ nodeppulist:=nil;
+ nodeppuidx:=0;
+ end;
+
+
+ procedure nodeppuidxadd(n:tnode);
+ var
+ i : longint;
+ begin
+ i:=n.ppuidx;
+ if i<=0 then
+ internalerror(200311072);
+ if i>=nodeppulist.capacity then
+ nodeppulist.capacity:=((i div 1024)+1)*1024;
+ if i>=nodeppulist.count then
+ nodeppulist.count:=i+1;
+ nodeppulist[i]:=n;
+ end;
+
+
+ function nodeppuidxget(i:longint):tnode;
+ begin
+ if i<=0 then
+ internalerror(200311073);
+ result:=tnode(nodeppulist[i]);
+ end;
+
+
+ function ppuloadnode(ppufile:tcompilerppufile):tnode;
+ var
+ b : byte;
+ t : tnodetype;
+ hppuidx : longint;
+ begin
+ { marker }
+ b:=ppufile.getbyte;
+ if b<>ppunodemarker then
+ internalerror(200208151);
+ { load nodetype }
+ t:=tnodetype(ppufile.getbyte);
+ if t>high(tnodetype) then
+ internalerror(200208152);
+ if t<>emptynode then
+ begin
+ if not assigned(nodeclass[t]) then
+ internalerror(200208153);
+ hppuidx:=ppufile.getlongint;
+ //writeln('load: ',nodetype2str[t]);
+ { generate node of the correct class }
+ result:=nodeclass[t].ppuload(t,ppufile);
+ result.fppuidx:=hppuidx;
+ nodeppuidxadd(result);
+ end
+ else
+ result:=nil;
+ end;
+
+
+ procedure ppuwritenode(ppufile:tcompilerppufile;n:tnode);
+ begin
+ { marker, read by ppuloadnode }
+ ppufile.putbyte(ppunodemarker);
+ { type, read by ppuloadnode }
+ if assigned(n) then
+ begin
+ ppufile.putbyte(byte(n.nodetype));
+ ppufile.putlongint(n.ppuidx);
+ //writeln('write: ',nodetype2str[n.nodetype]);
+ n.ppuwrite(ppufile);
+ end
+ else
+ ppufile.putbyte(byte(emptynode));
+ end;
+
+
+ function ppuloadnodetree(ppufile:tcompilerppufile):tnode;
+ begin
+ if ppufile.readentry<>ibnodetree then
+ Message(unit_f_ppu_read_error);
+ nodeppuidxcreate;
+ result:=ppuloadnode(ppufile);
+ nodeppuidxresolve;
+ nodeppuidxfree;
+ end;
+
+
+ procedure ppuwritenodetree(ppufile:tcompilerppufile;n:tnode);
+ begin
+ nodeppuidxcreate;
+ ppuwritenode(ppufile,n);
+ ppufile.writeentry(ibnodetree);
+ nodeppuidxfree;
+ end;
+
+
+ procedure printnodeindent;
+ begin
+ printnodeindention:=printnodeindention+printnodespacing;
+ end;
+
+
+ procedure printnodeunindent;
+ begin
+ delete(printnodeindention,1,length(printnodespacing));
+ end;
+
+
+ procedure printnode(var t:text;n:tnode);
+ begin
+ if assigned(n) then
+ n.printnodetree(t)
+ else
+ writeln(t,printnodeindention,'nil');
+ end;
+
+
+ procedure printnode(n:tnode);
+ begin
+ printnode(output,n);
+ end;
+
+
+ function is_constnode(p : tnode) : boolean;
+ begin
+ is_constnode:=(p.nodetype in [niln,ordconstn,realconstn,stringconstn,setconstn,guidconstn]);
+ end;
+
+
+ function is_constintnode(p : tnode) : boolean;
+ begin
+ is_constintnode:=(p.nodetype=ordconstn) and is_integer(p.resultdef);
+ end;
+
+
+ function is_constcharnode(p : tnode) : boolean;
+ begin
+ is_constcharnode:=(p.nodetype=ordconstn) and is_char(p.resultdef);
+ end;
+
+
+ function is_constwidecharnode(p : tnode) : boolean;
+ begin
+ is_constwidecharnode:=(p.nodetype=ordconstn) and is_widechar(p.resultdef);
+ end;
+
+
+ function is_constrealnode(p : tnode) : boolean;
+ begin
+ is_constrealnode:=(p.nodetype=realconstn);
+ end;
+
+
+ function is_constboolnode(p : tnode) : boolean;
+ begin
+ is_constboolnode:=(p.nodetype=ordconstn) and is_boolean(p.resultdef);
+ end;
+
+
+ function is_constenumnode(p : tnode) : boolean;
+ begin
+ is_constenumnode:=(p.nodetype=ordconstn) and (p.resultdef.typ=enumdef);
+ end;
+
+
+ function is_constpointernode(p : tnode) : boolean;
+ begin
+ is_constpointernode:=(p.nodetype=pointerconstn);
+ end;
+
+ function is_conststringnode(p : tnode) : boolean;
+ begin
+ is_conststringnode :=
+ (p.nodetype = stringconstn) and is_chararray(p.resultdef);
+ end;
+
+ function is_constwidestringnode(p : tnode) : boolean;
+ begin
+ is_constwidestringnode :=
+ (p.nodetype = stringconstn) and is_widechararray(p.resultdef);
+ end;
+
+ function is_conststring_or_constcharnode(p : tnode) : boolean;
+ begin
+ is_conststring_or_constcharnode :=
+ is_conststringnode(p) or is_constcharnode(p) or
+ is_constwidestringnode(p) or is_constwidecharnode(p);
+ end;
+
+
+{****************************************************************************
+ TNODE
+ ****************************************************************************}
+
+ constructor tnode.create(t:tnodetype);
+
+ begin
+ inherited create;
+ nodetype:=t;
+ blocktype:=block_type;
+ { updated by firstpass }
+ expectloc:=LOC_INVALID;
+ { updated by secondpass }
+ location.loc:=LOC_INVALID;
+ { save local info }
+ fileinfo:=current_filepos;
+ localswitches:=current_settings.localswitches;
+ verbosity:=status.verbosity;
+ resultdef:=nil;
+ flags:=[];
+ end;
+
+ constructor tnode.createforcopy;
+
+ begin
+ end;
+
+ constructor tnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+
+ begin
+ nodetype:=t;
+ { tnode fields }
+ blocktype:=tblock_type(ppufile.getbyte);
+ ppufile.getposinfo(fileinfo);
+ ppufile.getsmallset(localswitches);
+ verbosity:=ppufile.getlongint;
+ ppufile.getderef(resultdefderef);
+ ppufile.getsmallset(flags);
+ { updated by firstpass }
+ expectloc:=LOC_INVALID;
+ { updated by secondpass }
+ location.loc:=LOC_INVALID;
+ end;
+
+
+ procedure tnode.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ ppufile.putbyte(byte(block_type));
+ ppufile.putposinfo(fileinfo);
+ ppufile.putsmallset(localswitches);
+ ppufile.putlongint(verbosity);
+ ppufile.putderef(resultdefderef);
+ ppufile.putsmallset(flags);
+ end;
+
+
+ function tnode.getppuidx:longint;
+ begin
+ if fppuidx=0 then
+ begin
+ inc(nodeppuidx);
+ fppuidx:=nodeppuidx;
+ end;
+ result:=fppuidx;
+ end;
+
+
+ procedure tnode.resolveppuidx;
+ begin
+ end;
+
+
+ procedure tnode.buildderefimpl;
+ begin
+ resultdefderef.build(resultdef);
+ end;
+
+
+ procedure tnode.derefimpl;
+ begin
+ resultdef:=tdef(resultdefderef.resolve);
+ end;
+
+
+ procedure tnode.toggleflag(f : tnodeflag);
+ begin
+ if f in flags then
+ exclude(flags,f)
+ else
+ include(flags,f);
+ end;
+
+
+ function tnode.simplify(forinline : boolean) : tnode;
+ begin
+ result:=nil;
+ end;
+
+
+ destructor tnode.destroy;
+ begin
+ if assigned(optinfo) then
+ dispose(optinfo);
+ end;
+
+
+ procedure tnode.concattolist(l : tlinkedlist);
+ begin
+ end;
+
+
+ function tnode.ischild(p : tnode) : boolean;
+ begin
+ ischild:=false;
+ end;
+
+
+ procedure tnode.mark_write;
+ begin
+{$ifdef EXTDEBUG}
+ Comment(V_Warning,'mark_write not implemented for '+nodetype2str[nodetype]);
+{$endif EXTDEBUG}
+ end;
+
+
+ procedure tnode.printnodeinfo(var t:text);
+ begin
+ write(t,nodetype2str[nodetype]);
+ if assigned(resultdef) then
+ write(t,', resultdef = ',resultdef.typesymbolprettyname,' = "',resultdef.GetTypeName,'"')
+ else
+ write(t,', resultdef = <nil>');
+ write(t,', pos = (',fileinfo.line,',',fileinfo.column,')',
+ ', loc = ',tcgloc2str[location.loc],
+ ', expectloc = ',tcgloc2str[expectloc]);
+ end;
+
+
+ procedure tnode.printnodedata(var t:text);
+ begin
+ end;
+
+
+ procedure tnode.printnodetree(var t:text);
+ begin
+ write(t,printnodeindention,'(');
+ printnodeinfo(t);
+ writeln(t);
+ printnodeindent;
+ printnodedata(t);
+ printnodeunindent;
+ writeln(t,printnodeindention,')');
+ end;
+
+
+ function tnode.isequal(p : tnode) : boolean;
+ begin
+ isequal:=
+ (not assigned(self) and not assigned(p)) or
+ (assigned(self) and assigned(p) and
+ { optimized subclasses have the same nodetype as their }
+ { superclass (for compatibility), so also check the classtype (JM) }
+ (p.classtype=classtype) and
+ (p.nodetype=nodetype) and
+ (flags*flagsequal=p.flags*flagsequal) and
+ docompare(p));
+ end;
+
+{$ifdef state_tracking}
+ function Tnode.track_state_pass(exec_known:boolean):boolean;
+ begin
+ track_state_pass:=false;
+ end;
+{$endif state_tracking}
+
+
+ function tnode.docompare(p : tnode) : boolean;
+ begin
+ docompare:=true;
+ end;
+
+
+ function cleanupcopiedto(var n : tnode;arg : pointer) : foreachnoderesult;
+ begin
+ result:=fen_true;
+ if n.nodetype=labeln then
+ tlabelnode(n).copiedto:=nil;
+ end;
+
+
+ function tnode.getcopy : tnode;
+ begin
+ result:=dogetcopy;
+ foreachnodestatic(pm_postprocess,self,@cleanupcopiedto,nil);
+ end;
+
+
+ function tnode.dogetcopy : tnode;
+ var
+ p : tnode;
+ begin
+ { this is quite tricky because we need a node of the current }
+ { node type and not one of tnode! }
+ p:=tnodeclass(classtype).createforcopy;
+ p.nodetype:=nodetype;
+ p.expectloc:=expectloc;
+ p.location:=location;
+ p.parent:=parent;
+ p.flags:=flags;
+ p.resultdef:=resultdef;
+ p.fileinfo:=fileinfo;
+ p.localswitches:=localswitches;
+ p.verbosity:=verbosity;
+{ p.list:=list; }
+ result:=p;
+ end;
+
+
+ function tnode.actualtargetnode: tnode;
+ begin
+ result:=self;
+ end;
+
+
+ procedure tnode.insertintolist(l : tnodelist);
+ begin
+ end;
+
+
+ { ensures that the optimizer info record is allocated }
+ function tnode.allocoptinfo : poptinfo;inline;
+ begin
+ if not(assigned(optinfo)) then
+ new(optinfo);
+ result:=optinfo;
+ end;
+
+{****************************************************************************
+ TUNARYNODE
+ ****************************************************************************}
+
+ constructor tunarynode.create(t:tnodetype;l : tnode);
+ begin
+ inherited create(t);
+ left:=l;
+ end;
+
+
+ constructor tunarynode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ left:=ppuloadnode(ppufile);
+ end;
+
+
+ destructor tunarynode.destroy;
+ begin
+ left.free;
+ inherited destroy;
+ end;
+
+
+ procedure tunarynode.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppuwritenode(ppufile,left);
+ end;
+
+
+ procedure tunarynode.buildderefimpl;
+ begin
+ inherited buildderefimpl;
+ if assigned(left) then
+ left.buildderefimpl;
+ end;
+
+
+ procedure tunarynode.derefimpl;
+ begin
+ inherited derefimpl;
+ if assigned(left) then
+ left.derefimpl;
+ end;
+
+
+ function tunarynode.docompare(p : tnode) : boolean;
+ begin
+ docompare:=(inherited docompare(p) and
+ ((left=nil) or left.isequal(tunarynode(p).left))
+ );
+ end;
+
+
+ function tunarynode.dogetcopy : tnode;
+ var
+ p : tunarynode;
+ begin
+ p:=tunarynode(inherited dogetcopy);
+ if assigned(left) then
+ p.left:=left.dogetcopy
+ else
+ p.left:=nil;
+ result:=p;
+ end;
+
+
+ procedure tunarynode.insertintolist(l : tnodelist);
+ begin
+ end;
+
+
+ procedure tunarynode.printnodedata(var t:text);
+ begin
+ inherited printnodedata(t);
+ printnode(t,left);
+ end;
+
+
+ procedure tunarynode.concattolist(l : tlinkedlist);
+ begin
+ left.parent:=self;
+ left.concattolist(l);
+ inherited concattolist(l);
+ end;
+
+
+ function tunarynode.ischild(p : tnode) : boolean;
+ begin
+ ischild:=p=left;
+ end;
+
+
+{****************************************************************************
+ TBINARYNODE
+ ****************************************************************************}
+
+ constructor tbinarynode.create(t:tnodetype;l,r : tnode);
+ begin
+ inherited create(t,l);
+ right:=r
+ end;
+
+
+ constructor tbinarynode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ right:=ppuloadnode(ppufile);
+ end;
+
+
+ destructor tbinarynode.destroy;
+ begin
+ right.free;
+ inherited destroy;
+ end;
+
+
+ procedure tbinarynode.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppuwritenode(ppufile,right);
+ end;
+
+
+ procedure tbinarynode.buildderefimpl;
+ begin
+ inherited buildderefimpl;
+ if assigned(right) then
+ right.buildderefimpl;
+ end;
+
+
+ procedure tbinarynode.derefimpl;
+ begin
+ inherited derefimpl;
+ if assigned(right) then
+ right.derefimpl;
+ end;
+
+
+ procedure tbinarynode.concattolist(l : tlinkedlist);
+ begin
+ { we could change that depending on the number of }
+ { required registers }
+ left.parent:=self;
+ left.concattolist(l);
+ left.parent:=self;
+ left.concattolist(l);
+ inherited concattolist(l);
+ end;
+
+
+ function tbinarynode.ischild(p : tnode) : boolean;
+ begin
+ ischild:=(p=right);
+ end;
+
+
+ function tbinarynode.docompare(p : tnode) : boolean;
+ begin
+ docompare:=(inherited docompare(p) and
+ ((right=nil) or right.isequal(tbinarynode(p).right))
+ );
+ end;
+
+
+ function tbinarynode.dogetcopy : tnode;
+ var
+ p : tbinarynode;
+ begin
+ p:=tbinarynode(inherited dogetcopy);
+ if assigned(right) then
+ p.right:=right.dogetcopy
+ else
+ p.right:=nil;
+ result:=p;
+ end;
+
+
+ procedure tbinarynode.insertintolist(l : tnodelist);
+ begin
+ end;
+
+
+ procedure tbinarynode.swapleftright;
+ var
+ swapp : tnode;
+ begin
+ swapp:=right;
+ right:=left;
+ left:=swapp;
+ if nf_swapped in flags then
+ exclude(flags,nf_swapped)
+ else
+ include(flags,nf_swapped);
+ end;
+
+
+ procedure tbinarynode.printnodedata(var t:text);
+ begin
+ inherited printnodedata(t);
+ printnode(t,right);
+ end;
+
+
+ procedure tbinarynode.printnodelist(var t:text);
+ var
+ hp : tbinarynode;
+ begin
+ hp:=self;
+ while assigned(hp) do
+ begin
+ write(t,printnodeindention,'(');
+ printnodeindent;
+ hp.printnodeinfo(t);
+ writeln(t);
+ printnode(t,hp.left);
+ writeln(t);
+ printnodeunindent;
+ writeln(t,printnodeindention,')');
+ hp:=tbinarynode(hp.right);
+ end;
+ end;
+
+
+{****************************************************************************
+ TTERTIARYNODE
+ ****************************************************************************}
+
+ constructor ttertiarynode.create(_t:tnodetype;l,r,t : tnode);
+ begin
+ inherited create(_t,l,r);
+ third:=t;
+ end;
+
+
+ constructor ttertiarynode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(t,ppufile);
+ third:=ppuloadnode(ppufile);
+ end;
+
+
+ destructor ttertiarynode.destroy;
+ begin
+ third.free;
+ inherited destroy;
+ end;
+
+
+ procedure ttertiarynode.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppuwritenode(ppufile,third);
+ end;
+
+
+ procedure ttertiarynode.buildderefimpl;
+ begin
+ inherited buildderefimpl;
+ if assigned(third) then
+ third.buildderefimpl;
+ end;
+
+
+ procedure ttertiarynode.derefimpl;
+ begin
+ inherited derefimpl;
+ if assigned(third) then
+ third.derefimpl;
+ end;
+
+
+ function ttertiarynode.docompare(p : tnode) : boolean;
+ begin
+ docompare:=(inherited docompare(p) and
+ ((third=nil) or third.isequal(ttertiarynode(p).third))
+ );
+ end;
+
+
+ function ttertiarynode.dogetcopy : tnode;
+ var
+ p : ttertiarynode;
+ begin
+ p:=ttertiarynode(inherited dogetcopy);
+ if assigned(third) then
+ p.third:=third.dogetcopy
+ else
+ p.third:=nil;
+ result:=p;
+ end;
+
+
+ procedure ttertiarynode.insertintolist(l : tnodelist);
+ begin
+ end;
+
+
+ procedure ttertiarynode.printnodedata(var t:text);
+ begin
+ inherited printnodedata(t);
+ printnode(t,third);
+ end;
+
+
+ procedure ttertiarynode.concattolist(l : tlinkedlist);
+ begin
+ third.parent:=self;
+ third.concattolist(l);
+ inherited concattolist(l);
+ end;
+
+
+ function ttertiarynode.ischild(p : tnode) : boolean;
+ begin
+ ischild:=p=third;
+ end;
+
+
+{****************************************************************************
+ TBINOPNODE
+ ****************************************************************************}
+
+ constructor tbinopnode.create(t:tnodetype;l,r : tnode);
+ begin
+ inherited create(t,l,r);
+ end;
+
+
+ function tbinopnode.docompare(p : tnode) : boolean;
+ begin
+ docompare:=(inherited docompare(p)) or
+ { if that's in the flags, is p then always a tbinopnode (?) (JM) }
+ ((nf_swapable in flags) and
+ left.isequal(tbinopnode(p).right) and
+ right.isequal(tbinopnode(p).left));
+ end;
+
+begin
+{$push}{$warnings off}
+ { taitype should fit into a 4 byte set for speed reasons }
+ if ord(high(tnodeflags))>31 then
+ internalerror(201110301);
+{$pop}
+end.
+
diff --git a/closures/compiler/nopt.pas b/closures/compiler/nopt.pas
new file mode 100644
index 0000000000..cd1eeb0878
--- /dev/null
+++ b/closures/compiler/nopt.pas
@@ -0,0 +1,394 @@
+{
+ Copyright (c) 1998-2002 by Jonas Maebe
+
+ This unit implements optimized nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit nopt;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses node,nbas,nadd,constexp;
+
+type
+ tsubnodetype = (
+ addsstringcharoptn, { shorstring + char }
+ addsstringcsstringoptn { shortstring + constant shortstring }
+ );
+
+ taddoptnode = class(taddnode)
+ subnodetype: tsubnodetype;
+ constructor create(ts: tsubnodetype; l,r : tnode); virtual; reintroduce;
+ { pass_1 will be overridden by the separate subclasses }
+ { By default, pass_generate_code is the same as for addnode }
+ { Only if there's a processor specific implementation, it }
+ { will be overridden. }
+ function dogetcopy: tnode; override;
+ function docompare(p: tnode): boolean; override;
+ end;
+
+ taddsstringoptnode = class(taddoptnode)
+ { maximum length of the string until now, allows us to skip a compare }
+ { sometimes (it's initialized/updated by calling updatecurmaxlen) }
+ curmaxlen: byte;
+ { pass_1 must be overridden, otherwise we get an endless loop }
+ function pass_typecheck: tnode; override;
+ function pass_1: tnode; override;
+ function dogetcopy: tnode; override;
+ function docompare(p: tnode): boolean; override;
+ protected
+ procedure updatecurmaxlen;
+ end;
+
+ { add a char to a shortstring }
+ taddsstringcharoptnode = class(taddsstringoptnode)
+ constructor create(l,r : tnode); virtual; reintroduce;
+ end;
+ taddsstringcharoptnodeclass = class of taddsstringcharoptnode;
+
+ { add a constant string to a short string }
+ taddsstringcsstringoptnode = class(taddsstringoptnode)
+ constructor create(l,r : tnode); virtual; reintroduce;
+ function pass_1: tnode; override;
+ end;
+ taddsstringcsstringoptnodeclass = class of taddsstringcsstringoptnode;
+
+function canbeaddsstringcharoptnode(p: taddnode): boolean;
+function genaddsstringcharoptnode(p: taddnode): tnode;
+function canbeaddsstringcsstringoptnode(p: taddnode): boolean;
+function genaddsstringcsstringoptnode(p: taddnode): tnode;
+function canbemultistringadd(p: taddnode): boolean;
+function genmultistringadd(p: taddnode): tnode;
+
+
+function is_addsstringoptnode(p: tnode): boolean;
+
+var
+ caddsstringcharoptnode: taddsstringcharoptnodeclass;
+ caddsstringcsstringoptnode: taddsstringcsstringoptnodeclass;
+
+implementation
+
+uses cutils, htypechk, defutil, defcmp, globtype, globals, cpubase, ncnv, ncon,ncal,nld,nmem,
+ verbose, symconst,symdef, cgbase, procinfo;
+
+
+{*****************************************************************************
+ TADDOPTNODE
+*****************************************************************************}
+
+constructor taddoptnode.create(ts: tsubnodetype; l,r : tnode);
+begin
+ { we need to keep the addn nodetype, otherwise taddnode.pass_generate_code will be }
+ { confused. Comparison for equal nodetypes therefore has to be }
+ { implemented using the classtype() method (JM) }
+ inherited create(addn,l,r);
+ subnodetype := ts;
+end;
+
+function taddoptnode.dogetcopy: tnode;
+var
+ hp: taddoptnode;
+begin
+ hp := taddoptnode(inherited dogetcopy);
+ hp.subnodetype := subnodetype;
+ dogetcopy := hp;
+end;
+
+function taddoptnode.docompare(p: tnode): boolean;
+begin
+ docompare :=
+ inherited docompare(p) and
+ (subnodetype = taddoptnode(p).subnodetype);
+end;
+
+
+{*****************************************************************************
+ TADDSSTRINGOPTNODE
+*****************************************************************************}
+
+function taddsstringoptnode.pass_typecheck: tnode;
+begin
+ result := nil;
+ updatecurmaxlen;
+ { left and right are already firstpass'ed by taddnode.pass_1 }
+ if not is_shortstring(left.resultdef) then
+ inserttypeconv(left,cshortstringtype);
+ if not is_shortstring(right.resultdef) then
+ inserttypeconv(right,cshortstringtype);
+ resultdef := left.resultdef;
+end;
+
+function taddsstringoptnode.pass_1: tnode;
+begin
+ pass_1 := nil;
+ expectloc:= LOC_REFERENCE;
+ { here we call STRCONCAT or STRCMP or STRCOPY }
+ include(current_procinfo.flags,pi_do_call);
+end;
+
+function taddsstringoptnode.dogetcopy: tnode;
+var
+ hp: taddsstringoptnode;
+begin
+ hp := taddsstringoptnode(inherited dogetcopy);
+ hp.curmaxlen := curmaxlen;
+ dogetcopy := hp;
+end;
+
+function taddsstringoptnode.docompare(p: tnode): boolean;
+begin
+ docompare :=
+ inherited docompare(p) and
+ (curmaxlen = taddsstringcharoptnode(p).curmaxlen);
+end;
+
+
+function is_addsstringoptnode(p: tnode): boolean;
+begin
+ is_addsstringoptnode :=
+ p.inheritsfrom(taddsstringoptnode);
+end;
+
+procedure taddsstringoptnode.updatecurmaxlen;
+begin
+ if is_addsstringoptnode(left) then
+ begin
+ { made it a separate block so no other if's are processed (would be a }
+ { simple waste of time) (JM) }
+ if (taddsstringoptnode(left).curmaxlen < 255) then
+ case subnodetype of
+ addsstringcharoptn:
+ curmaxlen := succ(taddsstringoptnode(left).curmaxlen);
+ addsstringcsstringoptn:
+ curmaxlen := min(taddsstringoptnode(left).curmaxlen +
+ tstringconstnode(right).len,255)
+ else
+ internalerror(291220001);
+ end
+ else curmaxlen := 255;
+ end
+ else if (left.nodetype = stringconstn) then
+ curmaxlen := min(tstringconstnode(left).len,255)
+ else if is_char(left.resultdef) then
+ curmaxlen := 1
+ else if (left.nodetype = typeconvn) then
+ begin
+ case ttypeconvnode(left).convtype of
+ tc_char_2_string:
+ curmaxlen := 1;
+{ doesn't work yet, don't know why (JM)
+ tc_chararray_2_string:
+ curmaxlen :=
+ min(ttypeconvnode(left).left.resultdef.size,255); }
+ else curmaxlen := 255;
+ end;
+ end
+ else
+ curmaxlen := 255;
+end;
+
+{*****************************************************************************
+ TADDSSTRINGCHAROPTNODE
+*****************************************************************************}
+
+
+constructor taddsstringcharoptnode.create(l,r : tnode);
+begin
+ inherited create(addsstringcharoptn,l,r);
+end;
+
+{*****************************************************************************
+ TADDSSTRINGCSSTRINGOPTNODE
+*****************************************************************************}
+
+
+constructor taddsstringcsstringoptnode.create(l,r : tnode);
+begin
+ inherited create(addsstringcsstringoptn,l,r);
+end;
+
+
+function taddsstringcsstringoptnode.pass_1: tnode;
+begin
+ { create the call to the concat routine both strings as arguments }
+ result := ccallnode.createintern('fpc_shortstr_append_shortstr',
+ ccallparanode.create(left,ccallparanode.create(right,nil)));
+ left:=nil;
+ right:=nil;
+end;
+
+
+{*****************************************************************************
+ HELPERS
+*****************************************************************************}
+
+function canbeaddsstringcharoptnode(p: taddnode): boolean;
+begin
+ canbeaddsstringcharoptnode :=
+ (cs_opt_level1 in current_settings.optimizerswitches) and
+
+{ the shortstring will be gotten through conversion if necessary (JM)
+ is_shortstring(p.left.resultdef) and }
+ ((p.nodetype = addn) and
+ is_char(p.right.resultdef));
+end;
+
+function genaddsstringcharoptnode(p: taddnode): tnode;
+var
+ hp: tnode;
+begin
+ hp := caddsstringcharoptnode.create(p.left.getcopy,p.right.getcopy);
+ hp.flags := p.flags;
+ genaddsstringcharoptnode := hp;
+end;
+
+
+
+function canbeaddsstringcsstringoptnode(p: taddnode): boolean;
+begin
+ canbeaddsstringcsstringoptnode :=
+ (cs_opt_level1 in current_settings.optimizerswitches) and
+
+{ the shortstring will be gotten through conversion if necessary (JM)
+ is_shortstring(p.left.resultdef) and }
+ ((p.nodetype = addn) and
+ (p.right.nodetype = stringconstn));
+end;
+
+function genaddsstringcsstringoptnode(p: taddnode): tnode;
+var
+ hp: tnode;
+begin
+ hp := caddsstringcsstringoptnode.create(p.left.getcopy,p.right.getcopy);
+ hp.flags := p.flags;
+ genaddsstringcsstringoptnode := hp;
+end;
+
+
+function canbemultistringadd(p: taddnode): boolean;
+var
+ hp : tnode;
+ i : longint;
+begin
+ result:=false;
+ if p.resultdef.typ<>stringdef then
+ exit;
+ i:=0;
+ hp:=p;
+ while assigned(hp) and (hp.nodetype=addn) do
+ begin
+ inc(i);
+ hp:=taddnode(hp).left;
+ end;
+ result:=(i>1);
+end;
+
+
+function genmultistringadd(p: taddnode): tnode;
+var
+ hp,sn : tnode;
+ arrp : tarrayconstructornode;
+ newstatement : tstatementnode;
+ tempnode : ttempcreatenode;
+ is_shortstr : boolean;
+ para : tcallparanode;
+begin
+ arrp:=nil;
+ hp:=p;
+ is_shortstr:=is_shortstring(p.resultdef);
+ while assigned(hp) and (hp.nodetype=addn) do
+ begin
+ sn:=taddnode(hp).right.getcopy;
+ inserttypeconv(sn,p.resultdef);
+ if is_shortstr then
+ begin
+ sn:=caddrnode.create(sn);
+ include(sn.flags,nf_internal);
+ end;
+ arrp:=carrayconstructornode.create(sn,arrp);
+ hp:=taddnode(hp).left;
+ end;
+ sn:=hp.getcopy;
+ inserttypeconv(sn,p.resultdef);
+ if is_shortstr then
+ begin
+ sn:=caddrnode.create(sn);
+ include(sn.flags,nf_internal);
+ end;
+ arrp:=carrayconstructornode.create(sn,arrp);
+ if assigned(aktassignmentnode) and
+ (aktassignmentnode.right=p) and
+ (aktassignmentnode.left.resultdef=p.resultdef) and
+ valid_for_var(aktassignmentnode.left,false) then
+ begin
+ para:=ccallparanode.create(
+ arrp,
+ ccallparanode.create(aktassignmentnode.left.getcopy,nil)
+ );
+ if is_ansistring(p.resultdef) then
+ para:=ccallparanode.create(
+ cordconstnode.create(
+ getparaencoding(p.resultdef),
+ u16inttype,
+ true
+ ),
+ para
+ );
+ result:=ccallnode.createintern(
+ 'fpc_'+tstringdef(p.resultdef).stringtypname+'_concat_multi',
+ para
+ );
+ include(aktassignmentnode.flags,nf_assign_done_in_right);
+ end
+ else
+ begin
+ result:=internalstatements(newstatement);
+ tempnode:=ctempcreatenode.create(p.resultdef,p.resultdef.size,tt_persistent ,true);
+ addstatement(newstatement,tempnode);
+ para:=ccallparanode.create(
+ arrp,
+ ccallparanode.create(ctemprefnode.create(tempnode),nil)
+ );
+ if is_ansistring(p.resultdef) then
+ para:=ccallparanode.create(
+ cordconstnode.create(
+ getparaencoding(p.resultdef),
+ u16inttype,
+ true
+ ),
+ para
+ );
+ addstatement(
+ newstatement,
+ ccallnode.createintern(
+ 'fpc_'+tstringdef(p.resultdef).stringtypname+'_concat_multi',
+ para
+ )
+ );
+ addstatement(newstatement,ctempdeletenode.create_normal_temp(tempnode));
+ addstatement(newstatement,ctemprefnode.create(tempnode));
+ end;
+end;
+
+begin
+ caddsstringcharoptnode := taddsstringcharoptnode;
+ caddsstringcsstringoptnode := taddsstringcsstringoptnode;
+end.
diff --git a/closures/compiler/nset.pas b/closures/compiler/nset.pas
new file mode 100644
index 0000000000..acc1871968
--- /dev/null
+++ b/closures/compiler/nset.pas
@@ -0,0 +1,1015 @@
+{
+ Copyright (c) 2000-2002 by Florian Klaempfl
+
+ Type checking and register allocation for set/case nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit nset;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cclasses,constexp,
+ node,globtype,globals,
+ aasmbase,aasmtai,aasmdata,ncon,nflw,symtype;
+
+ type
+ TLabelType = (ltOrdinal, ltConstString);
+
+ pcaselabel = ^tcaselabel;
+ tcaselabel = record
+ { unique blockid }
+ blockid : longint;
+ { left and right tree node }
+ less,
+ greater : pcaselabel;
+
+ { range type }
+ case label_type : TLabelType of
+ ltOrdinal:
+ (
+ _low,
+ _high : TConstExprInt;
+ );
+ ltConstString:
+ (
+ _low_str,
+ _high_str : tstringconstnode;
+ );
+ end;
+
+ pcaseblock = ^tcaseblock;
+ tcaseblock = record
+ { label (only used in pass_generate_code) }
+ blocklabel : tasmlabel;
+
+ statementlabel : tlabelnode;
+ { instructions }
+ statement : tnode;
+ end;
+
+ tsetelementnode = class(tbinarynode)
+ constructor create(l,r : tnode);virtual;
+ function pass_typecheck:tnode;override;
+ function pass_1 : tnode;override;
+ end;
+ tsetelementnodeclass = class of tsetelementnode;
+
+ tinnode = class(tbinopnode)
+ constructor create(l,r : tnode);virtual;reintroduce;
+ function pass_typecheck:tnode;override;
+ function simplify(forinline : boolean):tnode;override;
+ function pass_1 : tnode;override;
+ end;
+ tinnodeclass = class of tinnode;
+
+ trangenode = class(tbinarynode)
+ constructor create(l,r : tnode);virtual;
+ function pass_typecheck:tnode;override;
+ function pass_1 : tnode;override;
+ end;
+ trangenodeclass = class of trangenode;
+
+ tcasenode = class(tunarynode)
+ labels : pcaselabel;
+ blocks : TFPList;
+ elseblock : tnode;
+ constructor create(l:tnode);virtual;
+ destructor destroy;override;
+ constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderefimpl;override;
+ procedure derefimpl;override;
+ function dogetcopy : tnode;override;
+ procedure insertintolist(l : tnodelist);override;
+ function pass_typecheck:tnode;override;
+ function pass_1 : tnode;override;
+ function docompare(p: tnode): boolean; override;
+ procedure addlabel(blockid:longint;l,h : TConstExprInt); overload;
+ procedure addlabel(blockid:longint;l,h : tstringconstnode); overload;
+ procedure addblock(blockid:longint;instr:tnode);
+ procedure addelseblock(instr:tnode);
+ end;
+ tcasenodeclass = class of tcasenode;
+
+ var
+ csetelementnode : tsetelementnodeclass = tsetelementnode;
+ cinnode : tinnodeclass = tinnode;
+ crangenode : trangenodeclass = trangenode;
+ ccasenode : tcasenodeclass = tcasenode;
+
+ { counts the labels }
+ function case_count_labels(root : pcaselabel) : longint;
+ { searches the highest label }
+ function case_get_max(root : pcaselabel) : tconstexprint;
+ { searches the lowest label }
+ function case_get_min(root : pcaselabel) : tconstexprint;
+
+
+implementation
+
+ uses
+ systems,
+ verbose,
+ symconst,symdef,symsym,symtable,defutil,defcmp,
+ htypechk,pass_1,
+ nadd,nbas,ncnv,nld,cgobj,cgbase,
+ widestr;
+
+
+{*****************************************************************************
+ TSETELEMENTNODE
+*****************************************************************************}
+
+ constructor tsetelementnode.create(l,r : tnode);
+
+ begin
+ inherited create(setelementn,l,r);
+ end;
+
+
+ function tsetelementnode.pass_typecheck:tnode;
+ begin
+ result:=nil;
+ typecheckpass(left);
+ if assigned(right) then
+ typecheckpass(right);
+ set_varstate(left,vs_read,[vsf_must_be_valid]);
+ if codegenerror then
+ exit;
+
+ resultdef:=left.resultdef;
+ end;
+
+
+ function tsetelementnode.pass_1 : tnode;
+
+ begin
+ result:=nil;
+ firstpass(left);
+ if assigned(right) then
+ firstpass(right);
+ if codegenerror then
+ exit;
+
+ expectloc:=left.expectloc;
+ end;
+
+
+{*****************************************************************************
+ TINNODE
+*****************************************************************************}
+
+ constructor tinnode.create(l,r : tnode);
+ begin
+ inherited create(inn,l,r);
+ end;
+
+
+ function tinnode.pass_typecheck:tnode;
+
+ var
+ t : tnode;
+
+ function createsetconst(psd : tsetdef) : pconstset;
+ var
+ pcs : pconstset;
+ i : longint;
+ begin
+ new(pcs);
+ case psd.elementdef.typ of
+ enumdef :
+ begin
+ for i := 0 to tenumdef(psd.elementdef).symtable.SymList.Count - 1 do
+ begin
+ include(pcs^,tenumsym(tenumdef(psd.elementdef).symtable.SymList[i]).value);
+ end;
+ end;
+ orddef :
+ begin
+ for i:=int64(torddef(psd.elementdef).low) to int64(torddef(psd.elementdef).high) do
+ include(pcs^,i);
+ end;
+ end;
+ createsetconst:=pcs;
+ end;
+
+ begin
+ result:=nil;
+ resultdef:=pasbool8type;
+ typecheckpass(right);
+ set_varstate(right,vs_read,[vsf_must_be_valid]);
+ if codegenerror then
+ exit;
+
+ { Convert array constructor first to set }
+ if is_array_constructor(right.resultdef) then
+ begin
+ arrayconstructor_to_set(right);
+ firstpass(right);
+ if codegenerror then
+ exit;
+ end;
+
+ typecheckpass(left);
+ set_varstate(left,vs_read,[vsf_must_be_valid]);
+ if codegenerror then
+ exit;
+
+ if not assigned(left.resultdef) then
+ internalerror(20021126);
+
+ t:=self;
+ if isbinaryoverloaded(t) then
+ begin
+ result:=t;
+ exit;
+ end;
+
+ if right.resultdef.typ<>setdef then
+ CGMessage(sym_e_set_expected);
+
+ if codegenerror then
+ exit;
+
+ if (m_tp7 in current_settings.modeswitches) then
+ begin
+ { insert a hint that a range check error might occur on non-byte
+ elements with the in operator.
+ }
+ if (
+ (left.resultdef.typ = orddef) and not
+ (torddef(left.resultdef).ordtype in [s8bit,u8bit,uchar,pasbool8,bool8bit])
+ )
+ or
+ (
+ (left.resultdef.typ = enumdef) and
+ (tenumdef(left.resultdef).maxval > 255)
+ )
+ then
+ CGMessage(type_h_in_range_check);
+
+ { type conversion/check }
+ if assigned(tsetdef(right.resultdef).elementdef) then
+ inserttypeconv(left,tsetdef(right.resultdef).elementdef);
+ end
+ else if not is_ordinal(left.resultdef) or (left.resultdef.size > u32inttype.size) then
+ begin
+ CGMessage(type_h_in_range_check);
+ if is_signed(left.resultdef) then
+ inserttypeconv(left,s32inttype)
+ else
+ inserttypeconv(left,u32inttype);
+ end
+ else if assigned(tsetdef(right.resultdef).elementdef) and
+ not(is_integer(tsetdef(right.resultdef).elementdef) and
+ is_integer(left.resultdef)) then
+ { Type conversion to check things like 'char in set_of_byte'. }
+ { Can't use is_subequal because that will fail for }
+ { 'widechar in set_of_char' }
+ { Can't use the type conversion for integers because then }
+ { "longint in set_of_byte" will give a range check error }
+ { instead of false }
+ inserttypeconv(left,tsetdef(right.resultdef).elementdef);
+
+ { empty set then return false }
+ if not assigned(tsetdef(right.resultdef).elementdef) or
+ ((right.nodetype = setconstn) and
+ (tnormalset(tsetconstnode(right).value_set^) = [])) then
+ begin
+ t:=cordconstnode.create(0,pasbool8type,false);
+ typecheckpass(t);
+ result:=t;
+ exit;
+ end;
+
+ result:=simplify(false);
+ end;
+
+
+ function tinnode.simplify(forinline : boolean):tnode;
+ var
+ t : tnode;
+ begin
+ result:=nil;
+ { constant evaluation }
+ if (left.nodetype=ordconstn) then
+ begin
+ if (right.nodetype=setconstn) then
+ begin
+ { tordconstnode.value is int64 -> signed -> the expression }
+ { below will be converted to longint on 32 bit systems due }
+ { to the rule above -> will give range check error if }
+ { value > high(longint) if we don't take the signedness }
+ { into account }
+ if Tordconstnode(left).value.signed then
+ t:=cordconstnode.create(byte(tordconstnode(left).value.svalue in Tsetconstnode(right).value_set^),
+ pasbool8type,true)
+ else
+ t:=cordconstnode.create(byte(tordconstnode(left).value.uvalue in Tsetconstnode(right).value_set^),
+ pasbool8type,true);
+ typecheckpass(t);
+ result:=t;
+ exit;
+ end
+ else
+ begin
+ if (Tordconstnode(left).value<int64(tsetdef(right.resultdef).setbase)) or
+ (Tordconstnode(left).value>int64(Tsetdef(right.resultdef).setmax)) then
+ begin
+ t:=cordconstnode.create(0, pasbool8type, true);
+ typecheckpass(t);
+ result:=t;
+ exit;
+ end;
+ end;
+ end;
+ end;
+
+
+ function tinnode.pass_1 : tnode;
+ begin
+ result:=nil;
+ expectloc:=LOC_REGISTER;
+
+ firstpass(right);
+ firstpass(left);
+ if codegenerror then
+ exit;
+ end;
+
+
+{*****************************************************************************
+ TRANGENODE
+*****************************************************************************}
+
+ constructor trangenode.create(l,r : tnode);
+ var
+ value: string;
+
+ begin
+ { if right is char and left is string then }
+ { right should be treated as one-symbol string }
+ if is_conststringnode(l) and is_constcharnode(r) then
+ begin
+ value := char(tordconstnode(r).value.uvalue) + ''#0;
+ r.free;
+ r := cstringconstnode.createstr(value);
+ do_typecheckpass(r);
+ end;
+ inherited create(rangen,l,r);
+ end;
+
+
+ function trangenode.pass_typecheck : tnode;
+ begin
+ result:=nil;
+ typecheckpass(left);
+ typecheckpass(right);
+ set_varstate(left,vs_read,[vsf_must_be_valid]);
+ set_varstate(right,vs_read,[vsf_must_be_valid]);
+ if codegenerror then
+ exit;
+ { both types must be compatible }
+ if compare_defs(left.resultdef,right.resultdef,left.nodetype)=te_incompatible then
+ IncompatibleTypes(left.resultdef,right.resultdef);
+ { Check if only when its a constant set }
+ if (left.nodetype=ordconstn) and (right.nodetype=ordconstn) then
+ begin
+ { upper limit must be greater or equal than lower limit }
+ if (tordconstnode(left).value>tordconstnode(right).value) and
+ ((tordconstnode(left).value<0) or (tordconstnode(right).value>=0)) then
+ CGMessage(parser_e_upper_lower_than_lower);
+ end;
+ resultdef:=left.resultdef;
+ end;
+
+
+ function trangenode.pass_1 : tnode;
+ begin
+ result:=nil;
+ firstpass(left);
+ firstpass(right);
+ if codegenerror then
+ exit;
+ expectloc:=left.expectloc;
+ end;
+
+
+{*****************************************************************************
+ Case Helpers
+*****************************************************************************}
+
+ function case_count_labels(root : pcaselabel) : longint;
+ var
+ _l : longint;
+
+ procedure count(p : pcaselabel);
+ begin
+ inc(_l);
+ if assigned(p^.less) then
+ count(p^.less);
+ if assigned(p^.greater) then
+ count(p^.greater);
+ end;
+
+ begin
+ _l:=0;
+ count(root);
+ case_count_labels:=_l;
+ end;
+
+
+ function case_get_max(root : pcaselabel) : tconstexprint;
+ var
+ hp : pcaselabel;
+ begin
+ hp:=root;
+ while assigned(hp^.greater) do
+ hp:=hp^.greater;
+ case_get_max:=hp^._high;
+ end;
+
+
+ function case_get_min(root : pcaselabel) : tconstexprint;
+ var
+ hp : pcaselabel;
+ begin
+ hp:=root;
+ while assigned(hp^.less) do
+ hp:=hp^.less;
+ case_get_min:=hp^._low;
+ end;
+
+ procedure deletecaselabels(p : pcaselabel);
+
+ begin
+ if assigned(p^.greater) then
+ deletecaselabels(p^.greater);
+ if assigned(p^.less) then
+ deletecaselabels(p^.less);
+ if (p^.label_type = ltConstString) then
+ begin
+ p^._low_str.Free;
+ p^._high_str.Free;
+ end;
+ dispose(p);
+ end;
+
+ function copycaselabel(p : pcaselabel) : pcaselabel;
+
+ var
+ n : pcaselabel;
+
+ begin
+ new(n);
+ n^:=p^;
+ if (p^.label_type = ltConstString) then
+ begin
+ n^._low_str := tstringconstnode(p^._low_str.getcopy);
+ n^._high_str := tstringconstnode(p^._high_str.getcopy);
+ end;
+ if assigned(p^.greater) then
+ n^.greater:=copycaselabel(p^.greater);
+ if assigned(p^.less) then
+ n^.less:=copycaselabel(p^.less);
+ copycaselabel:=n;
+ end;
+
+
+ procedure ppuwritecaselabel(ppufile:tcompilerppufile;p : pcaselabel);
+ var
+ b : byte;
+ begin
+ ppufile.putbyte(byte(p^.label_type = ltConstString));
+ if (p^.label_type = ltConstString) then
+ begin
+ p^._low_str.ppuwrite(ppufile);
+ p^._high_str.ppuwrite(ppufile);
+ end
+ else
+ begin
+ ppufile.putexprint(p^._low);
+ ppufile.putexprint(p^._high);
+ end;
+
+ ppufile.putlongint(p^.blockid);
+ b:=ord(assigned(p^.greater)) or (ord(assigned(p^.less)) shl 1);
+ ppufile.putbyte(b);
+ if assigned(p^.greater) then
+ ppuwritecaselabel(ppufile,p^.greater);
+ if assigned(p^.less) then
+ ppuwritecaselabel(ppufile,p^.less);
+ end;
+
+
+ function ppuloadcaselabel(ppufile:tcompilerppufile):pcaselabel;
+ var
+ b : byte;
+ p : pcaselabel;
+ begin
+ new(p);
+ if boolean(ppufile.getbyte) then
+ begin
+ p^.label_type := ltConstString;
+ p^._low_str := cstringconstnode.ppuload(stringconstn,ppufile);
+ p^._high_str := cstringconstnode.ppuload(stringconstn,ppufile);
+ end
+ else
+ begin
+ p^.label_type := ltOrdinal;
+
+ p^._low:=ppufile.getexprint;
+ p^._high:=ppufile.getexprint;
+ end;
+
+ p^.blockid:=ppufile.getlongint;
+ b:=ppufile.getbyte;
+ if (b and 1)=1 then
+ p^.greater:=ppuloadcaselabel(ppufile)
+ else
+ p^.greater:=nil;
+ if (b and 2)=2 then
+ p^.less:=ppuloadcaselabel(ppufile)
+ else
+ p^.less:=nil;
+ ppuloadcaselabel:=p;
+ end;
+
+
+{*****************************************************************************
+ TCASENODE
+*****************************************************************************}
+
+ constructor tcasenode.create(l:tnode);
+ begin
+ inherited create(casen,l);
+ labels:=nil;
+ blocks:=TFPList.create;
+ elseblock:=nil;
+ end;
+
+
+ destructor tcasenode.destroy;
+ var
+ i : longint;
+ hp : pcaseblock;
+ begin
+ elseblock.free;
+ deletecaselabels(labels);
+ for i:=0 to blocks.count-1 do
+ begin
+ pcaseblock(blocks[i])^.statement.free;
+ hp:=pcaseblock(blocks[i]);
+ dispose(hp);
+ end;
+ blocks.free;
+ inherited destroy;
+ end;
+
+
+ constructor tcasenode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
+ var
+ cnt,i : longint;
+ begin
+ inherited ppuload(t,ppufile);
+ elseblock:=ppuloadnode(ppufile);
+ cnt:=ppufile.getlongint();
+ blocks:=TFPList.create;
+ for i:=0 to cnt-1 do
+ addblock(i,ppuloadnode(ppufile));
+ labels:=ppuloadcaselabel(ppufile);
+ end;
+
+
+ procedure tcasenode.ppuwrite(ppufile:tcompilerppufile);
+ var
+ i : longint;
+ begin
+ inherited ppuwrite(ppufile);
+ ppuwritenode(ppufile,elseblock);
+ ppufile.putlongint(blocks.count);
+ for i:=0 to blocks.count-1 do
+ ppuwritenode(ppufile,pcaseblock(blocks[i])^.statement);
+ ppuwritecaselabel(ppufile,labels);
+ end;
+
+
+ procedure tcasenode.buildderefimpl;
+ var
+ i : integer;
+ begin
+ inherited buildderefimpl;
+ if assigned(elseblock) then
+ elseblock.buildderefimpl;
+ for i:=0 to blocks.count-1 do
+ pcaseblock(blocks[i])^.statement.buildderefimpl;
+ end;
+
+
+ procedure tcasenode.derefimpl;
+ var
+ i : integer;
+ begin
+ inherited derefimpl;
+ if assigned(elseblock) then
+ elseblock.derefimpl;
+ for i:=0 to blocks.count-1 do
+ pcaseblock(blocks[i])^.statement.derefimpl;
+ end;
+
+
+ function tcasenode.pass_typecheck : tnode;
+ begin
+ result:=nil;
+ resultdef:=voidtype;
+ end;
+
+
+ function tcasenode.pass_1 : tnode;
+ var
+ i : integer;
+ node_thenblock,node_elseblock,if_node : tnode;
+ tempcaseexpr : ttempcreatenode;
+ if_block, init_block,stmt_block : tblocknode;
+ stmt : tstatementnode;
+ endlabel : tlabelnode;
+
+ function makeifblock(const labtree : pcaselabel; prevconditblock : tnode): tnode;
+ var
+ condit : tnode;
+ begin
+ if assigned(labtree^.less) then
+ result := makeifblock(labtree^.less, prevconditblock)
+ else
+ result := prevconditblock;
+
+ condit := caddnode.create(equaln, left.getcopy, labtree^._low_str.getcopy);
+
+ if (labtree^._low_str.fullcompare(labtree^._high_str)<>0) then
+ begin
+ condit.nodetype := gten;
+ condit := caddnode.create(
+ andn, condit, caddnode.create(
+ lten, left.getcopy, labtree^._high_str.getcopy));
+ end;
+
+ result :=
+ cifnode.create(
+ condit, cgotonode.create(pcaseblock(blocks[labtree^.blockid])^.statementlabel.labsym), result);
+
+ if assigned(labtree^.greater) then
+ result := makeifblock(labtree^.greater, result);
+
+ typecheckpass(result);
+ end;
+
+ begin
+ result:=nil;
+ init_block:=nil;
+ expectloc:=LOC_VOID;
+
+ { evalutes the case expression }
+ firstpass(left);
+ set_varstate(left,vs_read,[vsf_must_be_valid]);
+ if codegenerror then
+ exit;
+
+ { Load caseexpr into temp var if complex. }
+ { No need to do this for ordinal, because }
+ { in that case caseexpr is generated once }
+ if (labels^.label_type = ltConstString) and (not valid_for_addr(left, false)) and
+ (blocks.count > 0) then
+ begin
+ init_block := internalstatements(stmt);
+ tempcaseexpr :=
+ ctempcreatenode.create(
+ left.resultdef, left.resultdef.size, tt_persistent, true);
+ typecheckpass(tnode(tempcaseexpr));
+
+ addstatement(stmt, tempcaseexpr);
+ addstatement(
+ stmt, cassignmentnode.create(
+ ctemprefnode.create(tempcaseexpr), left));
+
+ left := ctemprefnode.create(tempcaseexpr);
+ typecheckpass(left);
+ end;
+
+ { first case }
+ for i:=0 to blocks.count-1 do
+ firstpass(pcaseblock(blocks[i])^.statement);
+
+ { may be handle else tree }
+ if assigned(elseblock) then
+ begin
+ firstpass(elseblock);
+
+ { kill case? }
+ if blocks.count=0 then
+ begin
+ result:=elseblock;
+ elseblock:=nil;
+ exit;
+ end;
+ end
+ else
+ if blocks.count=0 then
+ begin
+ result:=cnothingnode.create;
+ exit;
+ end;
+
+ if (labels^.label_type = ltConstString) then
+ begin
+ endlabel:=clabelnode.create(cnothingnode.create,tlabelsym.create('$casestrofend'));
+ stmt_block:=internalstatements(stmt);
+ for i:=0 to blocks.count-1 do
+ begin
+ pcaseblock(blocks[i])^.statementlabel:=clabelnode.create(cnothingnode.create,tlabelsym.create('$casestrof'));
+ addstatement(stmt,pcaseblock(blocks[i])^.statementlabel);
+ addstatement(stmt,pcaseblock(blocks[i])^.statement);
+ pcaseblock(blocks[i])^.statement:=nil;
+ addstatement(stmt,cgotonode.create(endlabel.labsym));
+ end;
+
+ firstpass(tnode(stmt_block));
+
+ if_node := makeifblock(labels, elseblock);
+
+ if assigned(init_block) then
+ firstpass(tnode(init_block));
+
+ if_block := internalstatements(stmt);
+
+ if assigned(init_block) then
+ addstatement(stmt, init_block);
+
+ addstatement(stmt, if_node);
+ addstatement(stmt,cgotonode.create(endlabel.labsym));
+ addstatement(stmt, stmt_block);
+ addstatement(stmt, endlabel);
+ result := if_block;
+ elseblock := nil;
+ exit;
+ end;
+
+ if is_boolean(left.resultdef) then
+ begin
+ case blocks.count of
+ 2:
+ begin
+ if boolean(qword(labels^._low))=false then
+ begin
+ node_thenblock:=pcaseblock(blocks[labels^.greater^.blockid])^.statement;
+ node_elseblock:=pcaseblock(blocks[labels^.blockid])^.statement;
+ pcaseblock(blocks[labels^.greater^.blockid])^.statement:=nil;
+ end
+ else
+ begin
+ node_thenblock:=pcaseblock(blocks[labels^.blockid])^.statement;
+ node_elseblock:=pcaseblock(blocks[labels^.less^.blockid])^.statement;
+ pcaseblock(blocks[labels^.less^.blockid])^.statement:=nil;
+ end;
+ pcaseblock(blocks[labels^.blockid])^.statement:=nil;
+ end;
+ 1:
+ begin
+ if labels^._low=labels^._high then
+ begin
+ if boolean(qword(labels^._low))=false then
+ begin
+ node_thenblock:=elseblock;
+ node_elseblock:=pcaseblock(blocks[labels^.blockid])^.statement;
+ end
+ else
+ begin
+ node_thenblock:=pcaseblock(blocks[labels^.blockid])^.statement;
+ node_elseblock:=elseblock;
+ end;
+ pcaseblock(blocks[labels^.blockid])^.statement:=nil;
+ elseblock:=nil;
+ end
+ else
+ begin
+ result:=pcaseblock(blocks[labels^.blockid])^.statement;
+ pcaseblock(blocks[labels^.blockid])^.statement:=nil;
+ elseblock:=nil;
+ exit;
+ end;
+ end;
+ else
+ internalerror(200805031);
+ end;
+ result:=cifnode.create(left,node_thenblock,node_elseblock);
+ left:=nil;
+ end;
+ end;
+
+
+ function tcasenode.dogetcopy : tnode;
+
+ var
+ n : tcasenode;
+ i : longint;
+ begin
+ n:=tcasenode(inherited dogetcopy);
+ if assigned(elseblock) then
+ n.elseblock:=elseblock.dogetcopy
+ else
+ n.elseblock:=nil;
+ if assigned(labels) then
+ n.labels:=copycaselabel(labels)
+ else
+ n.labels:=nil;
+ if assigned(blocks) then
+ begin
+ n.blocks:=TFPList.create;
+ for i:=0 to blocks.count-1 do
+ begin
+ if not assigned(blocks[i]) then
+ internalerror(200411302);
+ n.addblock(i,pcaseblock(blocks[i])^.statement.dogetcopy);
+ end;
+ end
+ else
+ n.blocks:=nil;
+ dogetcopy:=n;
+ end;
+
+ procedure tcasenode.insertintolist(l : tnodelist);
+
+ begin
+ end;
+
+ function caselabelsequal(n1,n2: pcaselabel): boolean;
+ begin
+ result :=
+ (not assigned(n1) and not assigned(n2)) or
+ (assigned(n1) and assigned(n2) and
+ (n1^._low = n2^._low) and
+ (n1^._high = n2^._high) and
+ { the rest of the fields don't matter for equality (JM) }
+ caselabelsequal(n1^.less,n2^.less) and
+ caselabelsequal(n1^.greater,n2^.greater))
+ end;
+
+
+ function caseblocksequal(b1,b2:TFPList): boolean;
+ var
+ i : longint;
+ begin
+ result:=false;
+ if b1.count<>b2.count then
+ exit;
+ for i:=0 to b1.count-1 do
+ begin
+ if not pcaseblock(b1[i])^.statement.isequal(pcaseblock(b2[i])^.statement) then
+ exit;
+ end;
+ result:=true;
+ end;
+
+
+ function tcasenode.docompare(p: tnode): boolean;
+ begin
+ result :=
+ inherited docompare(p) and
+ caselabelsequal(labels,tcasenode(p).labels) and
+ caseblocksequal(blocks,tcasenode(p).blocks) and
+ elseblock.isequal(tcasenode(p).elseblock);
+ end;
+
+
+ procedure tcasenode.addblock(blockid:longint;instr:tnode);
+ var
+ hcaseblock : pcaseblock;
+ begin
+ new(hcaseblock);
+ fillchar(hcaseblock^,sizeof(hcaseblock^),0);
+ hcaseblock^.statement:=instr;
+ if blockid>=blocks.count then
+ blocks.count:=blockid+1;
+ blocks[blockid]:=hcaseblock;
+ end;
+
+
+ procedure tcasenode.addelseblock(instr:tnode);
+ begin
+ elseblock:=instr;
+ end;
+
+
+ procedure tcasenode.addlabel(blockid:longint;l,h : TConstExprInt);
+ var
+ hcaselabel : pcaselabel;
+
+ function insertlabel(var p : pcaselabel):pcaselabel;
+ begin
+ if p=nil then
+ begin
+ p:=hcaselabel;
+ result:=p;
+ end
+ else
+ if (p^._low>hcaselabel^._low) and
+ (p^._low>hcaselabel^._high) then
+ begin
+ if (hcaselabel^.blockid = p^.blockid) and
+ (p^._low = hcaselabel^._high + 1) then
+ begin
+ p^._low := hcaselabel^._low;
+ dispose(hcaselabel);
+ result:=p;
+ end
+ else
+ result:=insertlabel(p^.less)
+ end
+ else
+ if (p^._high<hcaselabel^._low) and
+ (p^._high<hcaselabel^._high) then
+ begin
+ if (hcaselabel^.blockid = p^.blockid) and
+ (p^._high+1 = hcaselabel^._low) then
+ begin
+ p^._high := hcaselabel^._high;
+ dispose(hcaselabel);
+ result:=p;
+ end
+ else
+ result:=insertlabel(p^.greater);
+ end
+ else
+ begin
+ dispose(hcaselabel);
+ Message(parser_e_double_caselabel);
+ end
+ end;
+
+ begin
+ new(hcaselabel);
+ fillchar(hcaselabel^,sizeof(tcaselabel),0);
+ hcaselabel^.blockid:=blockid;
+ hcaselabel^.label_type:=ltOrdinal;
+ hcaselabel^._low:=l;
+ hcaselabel^._high:=h;
+ insertlabel(labels);
+ end;
+
+ procedure tcasenode.addlabel(blockid: longint; l, h: tstringconstnode);
+
+ var
+ hcaselabel : pcaselabel;
+
+ function insertlabel(var p : pcaselabel) : pcaselabel;
+ begin
+ if not assigned(p) then
+ begin
+ p := hcaselabel;
+ result := p;
+ end
+ else
+ if (p^._low_str.fullcompare(hcaselabel^._high_str) > 0) then
+ result := insertlabel(p^.less)
+ else
+ if (p^._high_str.fullcompare(hcaselabel^._low_str) < 0) then
+ result := insertlabel(p^.greater)
+ else
+ begin
+ hcaselabel^._low_str.free;
+ hcaselabel^._high_str.free;
+ dispose(hcaselabel);
+ Message(parser_e_double_caselabel);
+ end;
+ end;
+
+ begin
+ new(hcaselabel);
+ fillchar(hcaselabel^, sizeof(tcaselabel), 0);
+ hcaselabel^.blockid := blockid;
+ hcaselabel^.label_type := ltConstString;
+
+ hcaselabel^._low_str := tstringconstnode(l.getcopy);
+ hcaselabel^._high_str := tstringconstnode(h.getcopy);
+
+ insertlabel(labels);
+ end;
+
+end.
diff --git a/closures/compiler/nstate.pas b/closures/compiler/nstate.pas
new file mode 100644
index 0000000000..b7cb53235a
--- /dev/null
+++ b/closures/compiler/nstate.pas
@@ -0,0 +1,123 @@
+{
+ Copyright (c) 1998-2002 by Daniel Mantione
+
+ This unit contains support routines for the state tracker
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+
+unit nstate;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses cclasses,node;
+
+type Tstate_entry=class(Tlinkedlistitem)
+ what:Tnode;
+ value:Tnode;
+ constructor create(w,v:Tnode);
+ end;
+
+ Tstate_storage=class
+ storage:Tlinkedlist;
+ constructor create;
+ procedure store_fact(w,v:Tnode);
+ function find_fact(what:Tnode):Tnode;
+ procedure delete_fact(what:Tnode);
+ end;
+
+var aktstate:Tstate_storage;
+
+implementation
+
+constructor Tstate_entry.create(w,v:Tnode);
+
+begin
+ inherited create;
+ what:=w;
+ value:=v;
+end;
+
+constructor Tstate_storage.create;
+
+begin
+ storage:=Tlinkedlist.create;
+end;
+
+procedure Tstate_storage.store_fact(w,v:Tnode);
+
+var se:Tstate_entry;
+
+begin
+{ writeln('fact:');
+ writenode(w);
+ writeln('=');
+ writenode(v);}
+ se:=Tstate_entry(storage.first);
+ while assigned(se) do
+ begin
+ if se.what.isequal(w) then
+ begin
+ storage.remove(se);
+ se.destroy;
+ break;
+ end;
+ se:=Tstate_entry(se.next);
+ end;
+ se:=Tstate_entry.create(w,v);
+ storage.concat(se);
+end;
+
+function Tstate_storage.find_fact(what:Tnode):Tnode;
+
+var se:Tstate_entry;
+
+begin
+ find_fact:=nil;
+ se:=storage.first as Tstate_entry;
+ while assigned(se) do
+ begin
+ if se.what.isequal(what) then
+ begin
+ find_fact:=se.value;
+ break;
+ end;
+ se:=se.next as Tstate_entry;
+ end;
+end;
+
+procedure Tstate_storage.delete_fact(what:Tnode);
+
+var se:Tstate_entry;
+
+begin
+ se:=storage.first as Tstate_entry;
+ while assigned(se) do
+ begin
+ if se.what.isequal(what) then
+ begin
+ storage.remove(se);
+ se.destroy;
+ break;
+ end;
+ se:=se.next as Tstate_entry;
+ end;
+end;
+
+end.
diff --git a/closures/compiler/nutils.pas b/closures/compiler/nutils.pas
new file mode 100644
index 0000000000..b80bfff8ec
--- /dev/null
+++ b/closures/compiler/nutils.pas
@@ -0,0 +1,1222 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Type checking and register allocation for inline nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit nutils;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ globtype,constexp,
+ symtype,symsym,symbase,symtable,
+ node;
+
+ const
+ NODE_COMPLEXITY_INF = 255;
+
+ type
+ { resultdef of functions that process on all nodes in a (sub)tree }
+ foreachnoderesult = (
+ { false, continue recursion }
+ fen_false,
+ { false, stop recursion }
+ fen_norecurse_false,
+ { true, continue recursion }
+ fen_true,
+ { true, stop recursion }
+ fen_norecurse_true
+ );
+
+ tforeachprocmethod = (pm_preprocess,pm_postprocess,
+ pm_postandagain);
+
+ foreachnodefunction = function(var n: tnode; arg: pointer): foreachnoderesult of object;
+ staticforeachnodefunction = function(var n: tnode; arg: pointer): foreachnoderesult;
+
+ function foreachnode(var n: tnode; f: foreachnodefunction; arg: pointer): boolean;
+ function foreachnode(procmethod : tforeachprocmethod; var n: tnode; f: foreachnodefunction; arg: pointer): boolean;
+ function foreachnodestatic(var n: tnode; f: staticforeachnodefunction; arg: pointer): boolean;
+ function foreachnodestatic(procmethod : tforeachprocmethod; var n: tnode; f: staticforeachnodefunction; arg: pointer): boolean;
+
+ { checks if the given node tree contains only nodes of the given type,
+ if this isn't the case, an ie is thrown
+ }
+ procedure checktreenodetypes(n : tnode;typeset : tnodetypeset);
+
+ procedure load_procvar_from_calln(var p1:tnode);
+ function maybe_call_procvar(var p1:tnode;tponly:boolean):boolean;
+ function get_high_value_sym(vs: tparavarsym):tsym; { marking it as inline causes IE 200311075 during loading from ppu file }
+ function load_high_value_node(vs:tparavarsym):tnode;
+ function load_self_node:tnode;
+ function load_result_node:tnode;
+ function load_self_pointer_node:tnode;
+ function load_vmt_pointer_node:tnode;
+ function is_self_node(p:tnode):boolean;
+
+ function call_fail_node:tnode;
+ function initialize_data_node(p:tnode):tnode;
+ function finalize_data_node(p:tnode):tnode;
+
+ function node_complexity(p: tnode): cardinal;
+ function node_resources_fpu(p: tnode): cardinal;
+ procedure node_tree_set_filepos(var n:tnode;const filepos:tfileposinfo);
+
+ { tries to simplify the given node after inlining }
+ procedure doinlinesimplify(var n : tnode);
+ { creates an ordinal constant, optionally based on the result from a
+ simplify operation: normally the type is the smallest integer type
+ that can hold the value, but when inlining the "def" will be used instead,
+ which was determined during an earlier typecheck pass (because the value
+ may e.g. be a parameter to a call, which needs to be of the declared
+ parameter type) }
+ function create_simplified_ord_const(value: tconstexprint; def: tdef; forinline: boolean): tnode;
+
+
+ { returns true if n is only a tree of administrative nodes
+ containing no code }
+ function has_no_code(n : tnode) : boolean;
+
+ function getpropaccesslist(propsym:tpropertysym; pap:tpropaccesslisttypes;out propaccesslist:tpropaccesslist):boolean;
+ procedure propaccesslist_to_node(var p1:tnode;st:TSymtable;pl:tpropaccesslist);
+ function node_to_propaccesslist(p1:tnode):tpropaccesslist;
+
+ { returns true if n is an array element access of a bitpacked array with
+ elements of the which the vitsize mod 8 <> 0, or if is a field access
+ with bitsize mod 8 <> 0 or bitoffset mod 8 <> 0 of an element in a
+ bitpacked structure }
+ function is_bitpacked_access(n: tnode): boolean;
+
+ { creates a load of field 'fieldname' in the record/class/...
+ represented by n }
+ function genloadfield(n: tnode; const fieldname: string): tnode;
+
+ { returns true, if the tree given might have side effects }
+ function might_have_sideeffects(n : tnode) : boolean;
+
+implementation
+
+ uses
+ cutils,verbose,globals,
+ symconst,symdef,
+ defutil,defcmp,
+ nbas,ncon,ncnv,nld,nflw,nset,ncal,nadd,nmem,ninl,
+ cpubase,cgbase,procinfo,
+ pass_1;
+
+ function foreachnode(procmethod : tforeachprocmethod;var n: tnode; f: foreachnodefunction; arg: pointer): boolean;
+
+ function process_children(res : boolean) : boolean;
+ var
+ i: longint;
+ begin
+ result:=res;
+ case n.nodetype of
+ asn:
+ if assigned(tasnode(n).call) then
+ begin
+ result := foreachnode(procmethod,tasnode(n).call,f,arg);
+ exit
+ end;
+ calln:
+ begin
+ result := foreachnode(procmethod,tnode(tcallnode(n).callinitblock),f,arg) or result;
+ result := foreachnode(procmethod,tcallnode(n).methodpointer,f,arg) or result;
+ result := foreachnode(procmethod,tcallnode(n).funcretnode,f,arg) or result;
+ result := foreachnode(procmethod,tnode(tcallnode(n).callcleanupblock),f,arg) or result;
+ end;
+ ifn, whilerepeatn, forn, tryexceptn, tryfinallyn:
+ begin
+ { not in one statement, won't work because of b- }
+ result := foreachnode(procmethod,tloopnode(n).t1,f,arg) or result;
+ result := foreachnode(procmethod,tloopnode(n).t2,f,arg) or result;
+ end;
+ raisen:
+ { frame tree }
+ result := foreachnode(traisenode(n).third,f,arg) or result;
+ tempcreaten:
+ { temp. initialization code }
+ if assigned(ttempcreatenode(n).tempinfo^.tempinitcode) then
+ result := foreachnode(ttempcreatenode(n).tempinfo^.tempinitcode,f,arg) or result;
+ casen:
+ begin
+ for i := 0 to tcasenode(n).blocks.count-1 do
+ if assigned(tcasenode(n).blocks[i]) then
+ result := foreachnode(procmethod,pcaseblock(tcasenode(n).blocks[i])^.statement,f,arg) or result;
+ result := foreachnode(procmethod,tcasenode(n).elseblock,f,arg) or result;
+ end;
+ end;
+ if n.inheritsfrom(tbinarynode) then
+ begin
+ { first process the "payload" of statementnodes }
+ result := foreachnode(procmethod,tbinarynode(n).left,f,arg) or result;
+ result := foreachnode(procmethod,tbinarynode(n).right,f,arg) or result;
+ end
+ else if n.inheritsfrom(tunarynode) then
+ result := foreachnode(procmethod,tunarynode(n).left,f,arg) or result;
+ end;
+
+ begin
+ result := false;
+ if not assigned(n) then
+ exit;
+ if procmethod=pm_preprocess then
+ result:=process_children(result);
+ case f(n,arg) of
+ fen_norecurse_false:
+ exit;
+ fen_norecurse_true:
+ begin
+ result := true;
+ exit;
+ end;
+ fen_true:
+ result := true;
+ { result is already false
+ fen_false:
+ result := false; }
+ end;
+ if (procmethod=pm_postprocess) or (procmethod=pm_postandagain) then
+ result:=process_children(result);
+ if procmethod=pm_postandagain then
+ begin
+ case f(n,arg) of
+ fen_norecurse_false:
+ exit;
+ fen_norecurse_true:
+ begin
+ result := true;
+ exit;
+ end;
+ fen_true:
+ result := true;
+ end;
+ end;
+ end;
+
+
+ function foreachnode(var n: tnode; f: foreachnodefunction; arg: pointer): boolean;
+ begin
+ result:=foreachnode(pm_postprocess,n,f,arg);
+ end;
+
+
+ function foreachnodestatic(procmethod : tforeachprocmethod;var n: tnode; f: staticforeachnodefunction; arg: pointer): boolean;
+
+ function process_children(res : boolean) : boolean;
+ var
+ i: longint;
+ begin
+ result:=res;
+ case n.nodetype of
+ asn:
+ if assigned(tasnode(n).call) then
+ begin
+ result := foreachnodestatic(procmethod,tasnode(n).call,f,arg);
+ exit
+ end;
+ calln:
+ begin
+ result := foreachnodestatic(procmethod,tnode(tcallnode(n).callinitblock),f,arg) or result;
+ result := foreachnodestatic(procmethod,tcallnode(n).methodpointer,f,arg) or result;
+ result := foreachnodestatic(procmethod,tcallnode(n).funcretnode,f,arg) or result;
+ result := foreachnodestatic(procmethod,tnode(tcallnode(n).callcleanupblock),f,arg) or result;
+ end;
+ ifn, whilerepeatn, forn, tryexceptn, tryfinallyn:
+ begin
+ { not in one statement, won't work because of b- }
+ result := foreachnodestatic(procmethod,tloopnode(n).t1,f,arg) or result;
+ result := foreachnodestatic(procmethod,tloopnode(n).t2,f,arg) or result;
+ end;
+ raisen:
+ { frame tree }
+ result := foreachnodestatic(traisenode(n).third,f,arg) or result;
+ tempcreaten:
+ { temp. initialization code }
+ if assigned(ttempcreatenode(n).tempinfo^.tempinitcode) then
+ result := foreachnodestatic(ttempcreatenode(n).tempinfo^.tempinitcode,f,arg) or result;
+ casen:
+ begin
+ for i := 0 to tcasenode(n).blocks.count-1 do
+ if assigned(tcasenode(n).blocks[i]) then
+ result := foreachnodestatic(procmethod,pcaseblock(tcasenode(n).blocks[i])^.statement,f,arg) or result;
+ result := foreachnodestatic(procmethod,tcasenode(n).elseblock,f,arg) or result;
+ end;
+ end;
+ if n.inheritsfrom(tbinarynode) then
+ begin
+ { first process the "payload" of statementnodes }
+ result := foreachnodestatic(procmethod,tbinarynode(n).left,f,arg) or result;
+ result := foreachnodestatic(procmethod,tbinarynode(n).right,f,arg) or result;
+ end
+ else if n.inheritsfrom(tunarynode) then
+ result := foreachnodestatic(procmethod,tunarynode(n).left,f,arg) or result;
+ end;
+
+ begin
+ result := false;
+ if not assigned(n) then
+ exit;
+ if procmethod=pm_preprocess then
+ result:=process_children(result);
+ case f(n,arg) of
+ fen_norecurse_false:
+ exit;
+ fen_norecurse_true:
+ begin
+ result := true;
+ exit;
+ end;
+ fen_true:
+ result := true;
+ { result is already false
+ fen_false:
+ result := false; }
+ end;
+ if (procmethod=pm_postprocess) or (procmethod=pm_postandagain) then
+ result:=process_children(result);
+ if procmethod=pm_postandagain then
+ begin
+ case f(n,arg) of
+ fen_norecurse_false:
+ exit;
+ fen_norecurse_true:
+ begin
+ result := true;
+ exit;
+ end;
+ fen_true:
+ result := true;
+ end;
+ end;
+ end;
+
+
+ function foreachnodestatic(var n: tnode; f: staticforeachnodefunction; arg: pointer): boolean;
+ begin
+ result:=foreachnodestatic(pm_postprocess,n,f,arg);
+ end;
+
+
+ function do_check(var n: tnode; arg: pointer): foreachnoderesult;
+ begin
+ if not(n.nodetype in pnodetypeset(arg)^) then
+ internalerror(200610141);
+ result:=fen_true;
+ end;
+
+
+ procedure checktreenodetypes(n : tnode;typeset : tnodetypeset);
+ begin
+ foreachnodestatic(n,@do_check,@typeset);
+ end;
+
+
+ procedure load_procvar_from_calln(var p1:tnode);
+ var
+ p2 : tnode;
+ begin
+ if p1.nodetype<>calln then
+ internalerror(200212251);
+ { was it a procvar, then we simply remove the calln and
+ reuse the right }
+ if assigned(tcallnode(p1).right) then
+ begin
+ p2:=tcallnode(p1).right;
+ tcallnode(p1).right:=nil;
+ end
+ else
+ begin
+ p2:=cloadnode.create_procvar(tcallnode(p1).symtableprocentry,
+ tprocdef(tcallnode(p1).procdefinition),tcallnode(p1).symtableproc);
+ { when the methodpointer is typen we've something like:
+ tobject.create. Then only the address is needed of the
+ method without a self pointer }
+ if assigned(tcallnode(p1).methodpointer) and
+ (tcallnode(p1).methodpointer.nodetype<>typen) then
+ tloadnode(p2).set_mp(tcallnode(p1).methodpointer.getcopy);
+ end;
+ typecheckpass(p2);
+ p1.free;
+ p1:=p2;
+ end;
+
+
+ function maybe_call_procvar(var p1:tnode;tponly:boolean):boolean;
+ var
+ hp : tnode;
+ begin
+ result:=false;
+ if (p1.resultdef.typ<>procvardef) or
+ (tponly and
+ not(m_tp_procvar in current_settings.modeswitches)) then
+ exit;
+ { ignore vecn,subscriptn }
+ hp:=p1;
+ repeat
+ case hp.nodetype of
+ vecn,
+ derefn,
+ typeconvn,
+ subscriptn :
+ hp:=tunarynode(hp).left;
+ else
+ break;
+ end;
+ until false;
+ { a tempref is used when it is loaded from a withsymtable }
+ if (hp.nodetype in [calln,loadn,temprefn]) then
+ begin
+ hp:=ccallnode.create_procvar(nil,p1);
+ typecheckpass(hp);
+ p1:=hp;
+ result:=true;
+ end;
+ end;
+
+
+ function get_high_value_sym(vs: tparavarsym):tsym;
+ begin
+ result := tsym(vs.owner.Find('high'+vs.name));
+ end;
+
+
+ function get_local_or_para_sym(const aname:string):tsym;
+ var
+ pd : tprocdef;
+ begin
+ result:=nil;
+ { is not assigned while parsing a property }
+ if not assigned(current_procinfo) then
+ exit;
+ { we can't use searchsym here, because the
+ symtablestack is not fully setup when pass1
+ is run for nested procedures }
+ pd:=current_procinfo.procdef;
+ repeat
+ result := tsym(pd.localst.Find(aname));
+ if assigned(result) then
+ break;
+ result := tsym(pd.parast.Find(aname));
+ if assigned(result) then
+ break;
+ { try the parent of a nested function }
+ if assigned(pd.owner.defowner) and
+ (pd.owner.defowner.typ=procdef) then
+ pd:=tprocdef(pd.owner.defowner)
+ else
+ break;
+ until false;
+ end;
+
+
+ function load_high_value_node(vs:tparavarsym):tnode;
+ var
+ srsym : tsym;
+ begin
+ result:=nil;
+ srsym:=get_high_value_sym(vs);
+ if assigned(srsym) then
+ begin
+ result:=cloadnode.create(srsym,vs.owner);
+ typecheckpass(result);
+ end
+ else
+ CGMessage(parser_e_illegal_expression);
+ end;
+
+
+ function load_self_node:tnode;
+ var
+ srsym : tsym;
+ begin
+ result:=nil;
+
+ srsym:=get_local_or_para_sym('self');
+ if assigned(srsym) then
+ begin
+ result:=cloadnode.create(srsym,srsym.owner);
+ include(tloadnode(result).loadnodeflags,loadnf_is_self);
+ end
+ else
+ begin
+ result:=cerrornode.create;
+ CGMessage(parser_e_illegal_expression);
+ end;
+ typecheckpass(result);
+ end;
+
+
+ function load_result_node:tnode;
+ var
+ srsym : tsym;
+ begin
+ result:=nil;
+ srsym:=get_local_or_para_sym('result');
+ if assigned(srsym) then
+ result:=cloadnode.create(srsym,srsym.owner)
+ else
+ begin
+ result:=cerrornode.create;
+ CGMessage(parser_e_illegal_expression);
+ end;
+ typecheckpass(result);
+ end;
+
+
+ function load_self_pointer_node:tnode;
+ var
+ srsym : tsym;
+ begin
+ result:=nil;
+ srsym:=get_local_or_para_sym('self');
+ if assigned(srsym) then
+ begin
+ result:=cloadnode.create(srsym,srsym.owner);
+ include(tloadnode(result).loadnodeflags,loadnf_load_self_pointer);
+ end
+ else
+ begin
+ result:=cerrornode.create;
+ CGMessage(parser_e_illegal_expression);
+ end;
+ typecheckpass(result);
+ end;
+
+
+ function load_vmt_pointer_node:tnode;
+ var
+ srsym : tsym;
+ begin
+ result:=nil;
+ srsym:=get_local_or_para_sym('vmt');
+ if assigned(srsym) then
+ result:=cloadnode.create(srsym,srsym.owner)
+ else
+ begin
+ result:=cerrornode.create;
+ CGMessage(parser_e_illegal_expression);
+ end;
+ typecheckpass(result);
+ end;
+
+
+ function is_self_node(p:tnode):boolean;
+ begin
+ is_self_node:=(p.nodetype=loadn) and
+ (tloadnode(p).symtableentry.typ=paravarsym) and
+ (vo_is_self in tparavarsym(tloadnode(p).symtableentry).varoptions);
+ end;
+
+
+ function call_fail_node:tnode;
+ var
+ para : tcallparanode;
+ newstatement : tstatementnode;
+ srsym : tsym;
+ begin
+ result:=internalstatements(newstatement);
+
+ { call fail helper and exit normal }
+ if is_class(current_structdef) then
+ begin
+ srsym:=search_struct_member(current_structdef,'FREEINSTANCE');
+ if assigned(srsym) and
+ (srsym.typ=procsym) then
+ begin
+ { if self<>0 and vmt<>0 then freeinstance }
+ addstatement(newstatement,cifnode.create(
+ caddnode.create(andn,
+ caddnode.create(unequaln,
+ load_self_pointer_node,
+ cnilnode.create),
+ caddnode.create(unequaln,
+ load_vmt_pointer_node,
+ cnilnode.create)),
+ ccallnode.create(nil,tprocsym(srsym),srsym.owner,load_self_node,[]),
+ nil));
+ end
+ else
+ internalerror(200305108);
+ end
+ else
+ if is_object(current_structdef) then
+ begin
+ { parameter 3 : vmt_offset }
+ { parameter 2 : pointer to vmt }
+ { parameter 1 : self pointer }
+ para:=ccallparanode.create(
+ cordconstnode.create(tobjectdef(current_structdef).vmt_offset,s32inttype,false),
+ ccallparanode.create(
+ ctypeconvnode.create_internal(
+ load_vmt_pointer_node,
+ voidpointertype),
+ ccallparanode.create(
+ ctypeconvnode.create_internal(
+ load_self_pointer_node,
+ voidpointertype),
+ nil)));
+ addstatement(newstatement,
+ ccallnode.createintern('fpc_help_fail',para));
+ end
+ else
+ internalerror(200305132);
+ { self:=nil }
+ addstatement(newstatement,cassignmentnode.create(
+ load_self_pointer_node,
+ cnilnode.create));
+ { exit }
+ addstatement(newstatement,cexitnode.create(nil));
+ end;
+
+
+ function initialize_data_node(p:tnode):tnode;
+ begin
+ if not assigned(p.resultdef) then
+ typecheckpass(p);
+ if is_ansistring(p.resultdef) or
+ is_wide_or_unicode_string(p.resultdef) or
+ is_interfacecom_or_dispinterface(p.resultdef) or
+ is_dynamic_array(p.resultdef) then
+ begin
+ result:=cassignmentnode.create(
+ ctypeconvnode.create_internal(p,voidpointertype),
+ cnilnode.create
+ );
+ end
+ else if (p.resultdef.typ=variantdef) then
+ begin
+ result:=ccallnode.createintern('fpc_variant_init',
+ ccallparanode.create(
+ ctypeconvnode.create_internal(p,search_system_type('TVARDATA').typedef),
+ nil));
+ end
+ else
+ begin
+ result:=ccallnode.createintern('fpc_initialize',
+ ccallparanode.create(
+ caddrnode.create_internal(
+ crttinode.create(
+ tstoreddef(p.resultdef),initrtti,rdt_normal)),
+ ccallparanode.create(
+ caddrnode.create_internal(p),
+ nil)));
+ end;
+ end;
+
+
+ function finalize_data_node(p:tnode):tnode;
+ var
+ newstatement : tstatementnode;
+ hs : string;
+ begin
+ if not assigned(p.resultdef) then
+ typecheckpass(p);
+ { 'decr_ref' suffix is somewhat misleading, all these helpers
+ set the passed pointer to nil now }
+ if is_ansistring(p.resultdef) then
+ hs:='fpc_ansistr_decr_ref'
+ else if is_widestring(p.resultdef) then
+ hs:='fpc_widestr_decr_ref'
+ else if is_unicodestring(p.resultdef) then
+ hs:='fpc_unicodestr_decr_ref'
+ else if is_interfacecom_or_dispinterface(p.resultdef) then
+ hs:='fpc_intf_decr_ref'
+ else
+ hs:='';
+ if hs<>'' then
+ result:=ccallnode.createintern(hs,
+ ccallparanode.create(
+ ctypeconvnode.create_internal(p,voidpointertype),
+ nil))
+ else if p.resultdef.typ=variantdef then
+ begin
+ result:=ccallnode.createintern('fpc_variant_clear',
+ ccallparanode.create(
+ ctypeconvnode.create_internal(p,search_system_type('TVARDATA').typedef),
+ nil));
+ end
+ else
+ result:=ccallnode.createintern('fpc_finalize',
+ ccallparanode.create(
+ caddrnode.create_internal(
+ crttinode.create(
+ tstoreddef(p.resultdef),initrtti,rdt_normal)),
+ ccallparanode.create(
+ caddrnode.create_internal(p),
+ nil)));
+ end;
+
+
+ { this function must return a very high value ("infinity") for }
+ { trees containing a call, the rest can be balanced more or less }
+ { at will, probably best mainly in terms of required memory }
+ { accesses }
+ function node_complexity(p: tnode): cardinal;
+ var
+ correction: byte;
+{$ifdef ARM}
+ dummy : byte;
+{$endif ARM}
+ begin
+ result := 0;
+ while assigned(p) do
+ begin
+ case p.nodetype of
+ { floating point constants usually need loading from memory }
+ realconstn,
+ temprefn,
+ loadvmtaddrn,
+ { main reason for the next one: we can't take the address of }
+ { loadparentfpnode, so replacing it by a temp which is the }
+ { address of this node's location and then dereferencing }
+ { doesn't work. If changed, check whether webtbs/tw0935 }
+ { still works with nodeinlining (JM) }
+ loadparentfpn:
+ begin
+ result := 1;
+ exit;
+ end;
+ loadn:
+ begin
+ if assigned(tloadnode(p).left) then
+ inc(result,node_complexity(tloadnode(p).left));
+ { threadvars need a helper call }
+ if (tloadnode(p).symtableentry.typ=staticvarsym) and
+ (vo_is_thread_var in tstaticvarsym(tloadnode(p).symtableentry).varoptions) then
+ inc(result,5)
+ else
+ inc(result);
+ if (result >= NODE_COMPLEXITY_INF) then
+ result := NODE_COMPLEXITY_INF;
+ exit;
+ end;
+ subscriptn:
+ begin
+ if is_implicit_pointer_object_type(tunarynode(p).left.resultdef) then
+ inc(result,2);
+ if (result = NODE_COMPLEXITY_INF) then
+ exit;
+ p := tunarynode(p).left;
+ end;
+ blockn,
+ callparan:
+ p := tunarynode(p).left;
+ notn,
+ derefn :
+ begin
+ inc(result);
+ if (result = NODE_COMPLEXITY_INF) then
+ exit;
+ p := tunarynode(p).left;
+ end;
+ typeconvn:
+ begin
+ { may be more complex in some cases }
+ if not(ttypeconvnode(p).convtype in [tc_equal,tc_int_2_int,tc_bool_2_bool,tc_real_2_real,tc_cord_2_pointer]) then
+ inc(result);
+ if (result = NODE_COMPLEXITY_INF) then
+ exit;
+ p := tunarynode(p).left;
+ end;
+ vecn,
+ statementn:
+ begin
+ inc(result,node_complexity(tbinarynode(p).left));
+ if (result >= NODE_COMPLEXITY_INF) then
+ begin
+ result := NODE_COMPLEXITY_INF;
+ exit;
+ end;
+ p := tbinarynode(p).right;
+ end;
+ addn,subn,orn,andn,xorn,muln,divn,modn,symdifn,
+ shln,shrn,
+ equaln,unequaln,gtn,gten,ltn,lten,
+ assignn:
+ begin
+{$ifdef CPU64BITALU}
+ correction:=1;
+{$else CPU64BITALU}
+ correction:=2;
+{$endif CPU64BITALU}
+ inc(result,node_complexity(tbinarynode(p).left)+1*correction);
+ if (p.nodetype in [muln,divn,modn]) then
+ inc(result,5*correction*correction);
+ if (result >= NODE_COMPLEXITY_INF) then
+ begin
+ result := NODE_COMPLEXITY_INF;
+ exit;
+ end;
+ p := tbinarynode(p).right;
+ end;
+ ordconstn:
+ begin
+{$ifdef ARM}
+ if not(is_shifter_const(tordconstnode(p).value.svalue,dummy)) then
+ result:=2;
+{$endif ARM}
+ exit;
+ end;
+ stringconstn,
+ tempcreaten,
+ tempdeleten,
+ pointerconstn,
+ nothingn,
+ niln:
+ exit;
+ inlinen:
+ begin
+ { this code assumes that the inline node has }
+ { already been firstpassed, and consequently }
+ { that inline nodes which are transformed into }
+ { calls already have been transformed }
+ case tinlinenode(p).inlinenumber of
+ in_lo_qword,
+ in_hi_qword,
+ in_lo_long,
+ in_hi_long,
+ in_lo_word,
+ in_hi_word,
+ in_length_x,
+ in_assigned_x,
+ in_pred_x,
+ in_succ_x,
+ in_round_real,
+ in_trunc_real,
+ in_int_real,
+ in_frac_real,
+ in_cos_real,
+ in_sin_real,
+ in_arctan_real,
+ in_pi_real,
+ in_abs_real,
+ in_sqr_real,
+ in_sqrt_real,
+ in_ln_real,
+ in_unaligned_x,
+ in_prefetch_var:
+ begin
+ inc(result);
+ p:=tunarynode(p).left;
+ end;
+ in_abs_long:
+ begin
+ inc(result,3);
+ if (result >= NODE_COMPLEXITY_INF) then
+ begin
+ result:=NODE_COMPLEXITY_INF;
+ exit;
+ end;
+ p:=tunarynode(p).left;
+ end;
+ in_sizeof_x,
+ in_typeof_x:
+ begin
+ inc(result);
+ if (tinlinenode(p).left.nodetype<>typen) then
+ { get instance vmt }
+ p:=tunarynode(p).left
+ else
+ { type vmt = global symbol, result is }
+ { already increased above }
+ exit;
+ end;
+ {$ifdef SUPPORT_MMX}
+ in_mmx_pcmpeqb..in_mmx_pcmpgtw,
+ {$endif SUPPORT_MMX}
+ { load from global symbol }
+ in_typeinfo_x,
+ { load frame pointer }
+ in_get_frame,
+ in_get_caller_frame,
+ in_get_caller_addr:
+ begin
+ inc(result);
+ exit;
+ end;
+
+ in_inc_x,
+ in_dec_x,
+ in_include_x_y,
+ in_exclude_x_y,
+ in_assert_x_y :
+ begin
+ { operation (add, sub, or, and }
+ inc(result);
+ { left expression }
+ inc(result,node_complexity(tcallparanode(tunarynode(p).left).left));
+ if (result >= NODE_COMPLEXITY_INF) then
+ begin
+ result := NODE_COMPLEXITY_INF;
+ exit;
+ end;
+ p:=tcallparanode(tunarynode(p).left).right;
+ if assigned(p) then
+ p:=tcallparanode(p).left;
+ end;
+ else
+ begin
+ result := NODE_COMPLEXITY_INF;
+ exit;
+ end;
+ end;
+
+ end;
+ else
+ begin
+ result := NODE_COMPLEXITY_INF;
+ exit;
+ end;
+ end;
+ end;
+ end;
+
+
+ { this function returns an indication how much fpu registers
+ will be required.
+ Note: The algorithms need to be pessimistic to prevent a
+ fpu stack overflow on i386 }
+ function node_resources_fpu(p: tnode): cardinal;
+ var
+ res1,res2,res3 : cardinal;
+ begin
+ result:=0;
+ res1:=0;
+ res2:=0;
+ res3:=0;
+ if p.inheritsfrom(tunarynode) then
+ begin
+ if assigned(tunarynode(p).left) then
+ res1:=node_resources_fpu(tunarynode(p).left);
+ if p.inheritsfrom(tbinarynode) then
+ begin
+ if assigned(tbinarynode(p).right) then
+ res2:=node_resources_fpu(tbinarynode(p).right);
+ if p.inheritsfrom(ttertiarynode) and assigned(ttertiarynode(p).third) then
+ res3:=node_resources_fpu(ttertiarynode(p).third)
+ end;
+ end;
+ result:=max(max(res1,res2),res3);
+ case p.nodetype of
+ calln:
+ { it could be a recursive call, so we never really know the number of used fpu registers }
+ result:=maxfpuregs;
+ realconstn,
+ typeconvn,
+ loadn :
+ begin
+ if p.expectloc in [LOC_CFPUREGISTER,LOC_FPUREGISTER] then
+ result:=max(result,1);
+ end;
+ assignn,
+ addn,subn,muln,slashn,
+ equaln,unequaln,gtn,gten,ltn,lten :
+ begin
+ if (tbinarynode(p).left.expectloc in [LOC_CFPUREGISTER,LOC_FPUREGISTER]) or
+ (tbinarynode(p).right.expectloc in [LOC_CFPUREGISTER,LOC_FPUREGISTER])then
+ result:=max(result,2);
+ if(p.expectloc in [LOC_CFPUREGISTER,LOC_FPUREGISTER]) then
+ inc(result);
+ end;
+ end;
+ end;
+
+
+ function setnodefilepos(var n: tnode; arg: pointer): foreachnoderesult;
+ begin
+ result:=fen_true;
+ n.fileinfo:=pfileposinfo(arg)^;
+ end;
+
+
+ procedure node_tree_set_filepos(var n:tnode;const filepos:tfileposinfo);
+ begin
+ foreachnodestatic(n,@setnodefilepos,@filepos);
+ end;
+
+
+ function callsimplify(var n: tnode; arg: pointer): foreachnoderesult;
+ var
+ hn : tnode;
+ treechanged : ^boolean;
+ begin
+ result:=fen_false;
+ if n.inheritsfrom(tloopnode) and
+ not (lnf_simplify_processing in tloopnode(n).loopflags) then
+ begin
+ // Try to simplify condition
+ doinlinesimplify(tloopnode(n).left);
+ // call directly second part below,
+ // which might change the loopnode into
+ // something else if the conditino is a constant node
+ include(tloopnode(n).loopflags,lnf_simplify_processing);
+ callsimplify(n,arg);
+ // Be careful, n might have change node type
+ if n.inheritsfrom(tloopnode) then
+ exclude(tloopnode(n).loopflags,lnf_simplify_processing);
+ end
+ else
+ begin
+ hn:=n.simplify(true);
+ if assigned(hn) then
+ begin
+ treechanged := arg;
+ if assigned(treechanged) then
+ treechanged^:=true
+ else
+ internalerror (201008181);
+ n.free;
+ n:=hn;
+ typecheckpass(n);
+ end;
+ end;
+ end;
+
+
+ { tries to simplify the given node calling the simplify method recursively }
+ procedure doinlinesimplify(var n : tnode);
+ var
+ treechanged : boolean;
+ begin
+ // Optimize if code first
+ repeat
+ treechanged:=false;
+ foreachnodestatic(pm_postandagain,n,@callsimplify,@treechanged);
+ until not(treechanged);
+ end;
+
+
+ function create_simplified_ord_const(value: tconstexprint; def: tdef; forinline: boolean): tnode;
+ begin
+ if not forinline then
+ result:=genintconstnode(value)
+ else
+ result:=cordconstnode.create(value,def,cs_check_range in current_settings.localswitches);
+ end;
+
+
+ function getpropaccesslist(propsym:tpropertysym; pap:tpropaccesslisttypes;out propaccesslist:tpropaccesslist):boolean;
+ var
+ hpropsym : tpropertysym;
+ begin
+ result:=false;
+ { find property in the overridden list }
+ hpropsym:=propsym;
+ repeat
+ propaccesslist:=hpropsym.propaccesslist[pap];
+ if not propaccesslist.empty then
+ begin
+ result:=true;
+ exit;
+ end;
+ hpropsym:=hpropsym.overriddenpropsym;
+ until not assigned(hpropsym);
+ end;
+
+
+ procedure propaccesslist_to_node(var p1:tnode;st:TSymtable;pl:tpropaccesslist);
+ var
+ plist : ppropaccesslistitem;
+ begin
+ plist:=pl.firstsym;
+ while assigned(plist) do
+ begin
+ case plist^.sltype of
+ sl_load :
+ begin
+ addsymref(plist^.sym);
+ if not assigned(st) then
+ st:=plist^.sym.owner;
+ { p1 can already contain the loadnode of
+ the class variable. When there is no tree yet we
+ may need to load it for with or objects }
+ if not assigned(p1) then
+ begin
+ case st.symtabletype of
+ withsymtable :
+ p1:=tnode(twithsymtable(st).withrefnode).getcopy;
+ ObjectSymtable :
+ p1:=load_self_node;
+ end;
+ end;
+ if assigned(p1) then
+ p1:=csubscriptnode.create(plist^.sym,p1)
+ else
+ p1:=cloadnode.create(plist^.sym,st);
+ end;
+ sl_subscript :
+ begin
+ addsymref(plist^.sym);
+ p1:=csubscriptnode.create(plist^.sym,p1);
+ end;
+ sl_typeconv :
+ p1:=ctypeconvnode.create_explicit(p1,plist^.def);
+ sl_absolutetype :
+ begin
+ p1:=ctypeconvnode.create(p1,plist^.def);
+ include(p1.flags,nf_absolute);
+ end;
+ sl_vec :
+ p1:=cvecnode.create(p1,cordconstnode.create(plist^.value,plist^.valuedef,true));
+ else
+ internalerror(200110205);
+ end;
+ plist:=plist^.next;
+ end;
+ end;
+
+
+ function node_to_propaccesslist(p1:tnode):tpropaccesslist;
+ var
+ sl : tpropaccesslist;
+
+ procedure addnode(p:tnode);
+ begin
+ case p.nodetype of
+ subscriptn :
+ begin
+ addnode(tsubscriptnode(p).left);
+ sl.addsym(sl_subscript,tsubscriptnode(p).vs);
+ end;
+ typeconvn :
+ begin
+ addnode(ttypeconvnode(p).left);
+ if nf_absolute in ttypeconvnode(p).flags then
+ sl.addtype(sl_absolutetype,ttypeconvnode(p).totypedef)
+ else
+ sl.addtype(sl_typeconv,ttypeconvnode(p).totypedef);
+ end;
+ vecn :
+ begin
+ addnode(tvecnode(p).left);
+ if tvecnode(p).right.nodetype=ordconstn then
+ sl.addconst(sl_vec,tordconstnode(tvecnode(p).right).value,tvecnode(p).right.resultdef)
+ else
+ begin
+ Message(parser_e_illegal_expression);
+ { recovery }
+ sl.addconst(sl_vec,0,tvecnode(p).right.resultdef);
+ end;
+ end;
+ loadn :
+ sl.addsym(sl_load,tloadnode(p).symtableentry);
+ else
+ internalerror(200310282);
+ end;
+ end;
+
+ begin
+ sl:=tpropaccesslist.create;
+ addnode(p1);
+ result:=sl;
+ end;
+
+
+ function is_bitpacked_access(n: tnode): boolean;
+ begin
+ case n.nodetype of
+ vecn:
+ result:=
+ is_packed_array(tvecnode(n).left.resultdef) and
+ { only orddefs and enumdefs are actually bitpacked. Don't consider
+ e.g. an access to a 3-byte record as "bitpacked", since it
+ isn't }
+ (tvecnode(n).left.resultdef.typ in [orddef,enumdef]) and
+ not(tarraydef(tvecnode(n).left.resultdef).elepackedbitsize in [8,16,32,64]);
+ subscriptn:
+ result:=
+ is_packed_record_or_object(tsubscriptnode(n).left.resultdef) and
+ { see above }
+ (tsubscriptnode(n).vs.vardef.typ in [orddef,enumdef]) and
+ (not(tsubscriptnode(n).vs.vardef.packedbitsize in [8,16,32,64]) or
+ (tsubscriptnode(n).vs.fieldoffset mod 8 <> 0));
+ else
+ result:=false;
+ end;
+ end;
+
+
+ function genloadfield(n: tnode; const fieldname: string): tnode;
+ var
+ vs : tsym;
+ begin
+ if not assigned(n.resultdef) then
+ typecheckpass(n);
+ vs:=tsym(tabstractrecorddef(n.resultdef).symtable.find(fieldname));
+ if not assigned(vs) or
+ (vs.typ<>fieldvarsym) then
+ internalerror(2010061902);
+ result:=csubscriptnode.create(vs,n);
+ end;
+
+
+ function has_no_code(n : tnode) : boolean;
+ begin
+ if n=nil then
+ begin
+ result:=true;
+ exit;
+ end;
+ result:=false;
+ case n.nodetype of
+ nothingn:
+ begin
+ result:=true;
+ exit;
+ end;
+ blockn:
+ begin
+ result:=has_no_code(tblocknode(n).left);
+ exit;
+ end;
+ statementn:
+ begin
+ repeat
+ result:=has_no_code(tstatementnode(n).left);
+ n:=tstatementnode(n).right;
+ until not(result) or not assigned(n);
+ exit;
+ end;
+ end;
+ end;
+
+
+ function check_for_sideeffect(var n: tnode; arg: pointer): foreachnoderesult;
+ begin
+ result:=fen_false;
+ if (n.nodetype in [assignn,calln,asmn]) or
+ ((n.nodetype=inlinen) and
+ (tinlinenode(n).inlinenumber in [in_write_x,in_writeln_x,in_read_x,in_readln_x,in_str_x_string,
+ in_val_x,in_reset_x,in_rewrite_x,in_reset_typedfile,in_rewrite_typedfile,in_settextbuf_file_x,
+ in_inc_x,in_dec_x,in_include_x_y,in_exclude_x_y,in_break,in_continue,in_setlength_x,
+ in_finalize_x,in_new_x,in_dispose_x,in_exit,in_copy_x,in_initialize_x,in_leave,in_cycle])
+ ) then
+ result:=fen_norecurse_true;
+ end;
+
+
+ function might_have_sideeffects(n : tnode) : boolean;
+ begin
+ result:=foreachnodestatic(n,@check_for_sideeffect,nil);
+ end;
+
+end.
diff --git a/closures/compiler/objcdef.pas b/closures/compiler/objcdef.pas
new file mode 100644
index 0000000000..0f49ed2070
--- /dev/null
+++ b/closures/compiler/objcdef.pas
@@ -0,0 +1,653 @@
+{
+ Copyright (c) 2010 by Jonas Maebe
+
+ This unit implements some Objective-C type helper routines (minimal
+ unit dependencies, usable in symdef).
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+
+{$i fpcdefs.inc}
+
+unit objcdef;
+
+interface
+
+ uses
+ node,
+ symtype;
+
+ { The internals of Objective-C's @encode() functionality: encode a
+ type into the internal format used by the run time. Returns false
+ if a type is not representable by the Objective-C run time, and in
+ that case also the failing definition. }
+ function objctryencodetype(def: tdef; out encodedtype: ansistring; out founderror: tdef): boolean;
+
+ { Check whether a type can be used in an Objective-C method
+ signature or field declaration. }
+ function objcchecktype(def: tdef; out founderror: tdef): boolean;
+
+ { add type info for def at the end of encodedstr. recordinfostate influences
+ whether a record-style type will be fully encoded, or just using its
+ type name. bpacked indicates whether a record/array is bitpacked.
+ On error, founderror contains the type that triggered the error. }
+ type
+ trecordinfostate = (ris_initial, ris_afterpointer, ris_dontprint);
+
+ function objcaddencodedtype(def: tdef; recordinfostate: trecordinfostate; bpacked: boolean; var encodedstr: ansistring; out founderror: tdef): boolean;
+
+implementation
+
+ uses
+ globtype,
+ cutils,cclasses,
+ verbose,systems,
+ symtable,symconst,symsym,symdef,
+ defutil,paramgr;
+
+{******************************************************************
+ Type encoding
+*******************************************************************}
+
+ function encoderecst(const recname: ansistring; recst: tabstractrecordsymtable; var encodedstr: ansistring; out founderror: tdef): boolean;
+ var
+ variantstarts: tfplist;
+ i, varindex: longint;
+ field,
+ firstfield: tfieldvarsym;
+ firstfieldvariant,
+ bpacked: boolean;
+ begin
+ result:=false;
+ bpacked:=recst.fieldalignment=bit_alignment;
+ { Is the first field already the start of a variant? }
+ firstfield:=nil;
+ firstfieldvariant:=false;
+ for i:=0 to recst.symlist.count-1 do
+ begin
+ if (tsym(recst.symlist[i]).typ<>fieldvarsym) then
+ continue;
+ field:=tfieldvarsym(recst.symlist[i]);
+ if not assigned(firstfield) then
+ firstfield:=field
+ else if (vo_is_first_field in field.varoptions) then
+ begin
+ if (field.fieldoffset=firstfield.fieldoffset) then
+ firstfieldvariant:=true;
+ end;
+ end;
+ variantstarts:=tfplist.create;
+ encodedstr:=encodedstr+'{'+recname+'=';
+ for i:=0 to recst.symlist.count-1 do
+ begin
+ if (tsym(recst.symlist[i]).typ<>fieldvarsym) then
+ continue;
+
+ field:=tfieldvarsym(recst.symlist[i]);
+ { start of a variant part? }
+ if ((field=firstfield) and
+ firstfieldvariant) or
+ ((field<>firstfield) and
+ (vo_is_first_field in field.varoptions)) then
+ begin
+ varindex:=variantstarts.count-1;
+ if (varindex=-1) or
+ (tfieldvarsym(variantstarts[varindex]).fieldoffset<field.fieldoffset) then
+ begin
+ { new, more deeply nested variant }
+ encodedstr:=encodedstr+'(?={?=';
+ variantstarts.add(field);
+ end
+ else
+ begin
+ { close existing nested variants if any }
+ while (varindex>=0) and
+ (tfieldvarsym(variantstarts[varindex]).fieldoffset>field.fieldoffset) do
+ begin
+ { close more deeply nested variants }
+ encodedstr:=encodedstr+'})';
+ dec(varindex);
+ end;
+ if (varindex<0) then
+ internalerror(2009081805);
+ if (tfieldvarsym(variantstarts[varindex]).fieldoffset<>field.fieldoffset) then
+ internalerror(2009081804);
+
+ { variant at the same level as a previous one }
+ variantstarts.count:=varindex+1;
+ { No need to add this field, it has the same offset as the
+ previous one at this position. }
+ if tfieldvarsym(variantstarts[varindex]).fieldoffset<>field.fieldoffset then
+ internalerror(2009081601);
+ { close previous variant sub-part and start new one }
+ encodedstr:=encodedstr+'}{?=';
+ end
+ end;
+ if not objcaddencodedtype(field.vardef,ris_afterpointer,bpacked,encodedstr,founderror) then
+ exit;
+ end;
+ for i:=0 to variantstarts.count-1 do
+ encodedstr:=encodedstr+'})';
+ variantstarts.free;
+ encodedstr:=encodedstr+'}';
+ result:=true
+ end;
+
+
+ function objcaddencodedtype(def: tdef; recordinfostate: trecordinfostate; bpacked: boolean; var encodedstr: ansistring; out founderror: tdef): boolean;
+ var
+ recname: ansistring;
+ recdef: trecorddef;
+ objdef: tobjectdef;
+ len: aint;
+ c: char;
+ newstate: trecordinfostate;
+ addrpara: boolean;
+ begin
+ result:=true;
+ case def.typ of
+ stringdef :
+ begin
+ case tstringdef(def).stringtype of
+ st_shortstring:
+ { include length byte }
+ encodedstr:=encodedstr+'['+tostr(tstringdef(def).len+1)+'C]';
+ else
+ { While we could handle refcounted Pascal strings correctly
+ when such methods are called from Pascal code, things would
+ completely break down if they were called from Objective-C
+ code/reflection since the necessary refcount helper calls
+ would be missing on the caller side (unless we'd
+ automatically generate wrappers). }
+ result:=false;
+ end;
+ end;
+ enumdef,
+ orddef :
+ begin
+ if bpacked and
+ not is_void(def) then
+ encodedstr:=encodedstr+'b'+tostr(def.packedbitsize)
+ else
+ begin
+ if is_void(def) then
+ c:='v'
+ { in gcc, sizeof(_Bool) = sizeof(char) }
+ else if is_boolean(def) and
+ (def.size=1) then
+ c:='B'
+ else
+ begin
+ case def.size of
+ 1:
+ c:='c';
+ 2:
+ c:='s';
+ 4:
+ c:='i';
+ 8:
+ c:='q';
+ else
+ internalerror(2009081502);
+ end;
+ if not is_signed(def) then
+ c:=upcase(c);
+ end;
+ encodedstr:=encodedstr+c;
+ end;
+ end;
+ pointerdef :
+ begin
+ if is_pchar(def) then
+ encodedstr:=encodedstr+'*'
+ else if (def=objc_idtype) then
+ encodedstr:=encodedstr+'@'
+ else if (def=objc_seltype) then
+ encodedstr:=encodedstr+':'
+ else if (def=objc_metaclasstype) then
+ encodedstr:=encodedstr+'#'
+ else
+ begin
+ encodedstr:=encodedstr+'^';
+ newstate:=recordinfostate;
+ if (recordinfostate<ris_dontprint) then
+ newstate:=succ(newstate);
+ if not objcaddencodedtype(tpointerdef(def).pointeddef,newstate,false,encodedstr,founderror) then
+ begin
+ result:=false;
+ { report the exact (nested) error defintion }
+ exit;
+ end;
+ end;
+ end;
+ floatdef :
+ begin
+ case tfloatdef(def).floattype of
+ s32real:
+ c:='f';
+ s64real:
+ c:='d';
+ else
+ begin
+ c:='!';
+ result:=false;
+ end;
+ end;
+ encodedstr:=encodedstr+c;
+ end;
+ filedef :
+ result:=false;
+ recorddef :
+ begin
+ if assigned(def.typesym) then
+ recname:=def.typename
+ else
+ recname:='?';
+
+ if (recordinfostate<>ris_dontprint) then
+ begin
+ if not encoderecst(recname,tabstractrecordsymtable(trecorddef(def).symtable),encodedstr,founderror) then
+ begin
+ result:=false;
+ { report the exact (nested) error defintion }
+ exit;
+ end
+ end
+ else
+ encodedstr:=encodedstr+'{'+recname+'}'
+ end;
+ variantdef :
+ begin
+ recdef:=trecorddef(search_system_type('TVARDATA').typedef);
+ if (recordinfostate<>ris_dontprint) then
+ begin
+ if not encoderecst(recdef.typename,tabstractrecordsymtable(recdef.symtable),encodedstr,founderror) then
+ begin
+ result:=false;
+ { report the exact (nested) error defintion }
+ exit;
+ end
+ end
+ else
+ encodedstr:=encodedstr+'{'+recdef.typename+'}';
+ end;
+ classrefdef :
+ begin
+ encodedstr:=encodedstr+'^';
+ newstate:=recordinfostate;
+ if (recordinfostate<>ris_dontprint) then
+ newstate:=succ(newstate);
+ if is_objcclassref(def) then
+ begin
+ objdef:=tobjectdef(tclassrefdef(def).pointeddef);
+ if (newstate<>ris_dontprint) then
+ { anonymous (objc)class definitions do not exist }
+ begin
+ if not encoderecst(objdef.objextname^,tabstractrecordsymtable(objdef.symtable),encodedstr,founderror) then
+ { The fields of an Objective-C class should always be
+ encodeable. }
+ internalerror(2009081702);
+ end
+ else
+ encodedstr:=encodedstr+'{'+objdef.objextname^+'}'
+ end
+ { Object Pascal classrefdefs point to a vmt, not really useful
+ to completely write those here. I'm not even sure what the
+ Objective-C run time uses this information for, since in C you
+ can have forward struct definitions so not all structs passed
+ to functions can be written out here either -> treat
+ classrefdefs the same as such forward-defined structs. }
+ else
+ begin
+ if assigned(def.typesym) then
+ recname:=def.typename
+ else
+ recname:='?';
+ encodedstr:=encodedstr+'{'+recname;
+ if (newstate<>ris_dontprint) then
+ encodedstr:=encodedstr+'=';
+ encodedstr:=encodedstr+'}'
+ end;
+ end;
+ setdef :
+ begin
+ addrpara:=paramanager.push_addr_param(vs_value,def,pocall_cdecl);
+ if not addrpara then
+ { encode as an record, they are always passed by value in C. }
+ encodedstr:=encodedstr+'{?=';
+ { Encode the set itself as an array. Without an encompassing
+ record, these are always passed by reference in C. }
+ encodedstr:=encodedstr+'['+tostr(def.size)+'C]';
+ if not addrpara then
+ encodedstr:=encodedstr+'}';
+ end;
+ formaldef :
+ begin
+ encodedstr:=encodedstr+'^v';
+ end;
+ arraydef :
+ begin
+ if is_array_of_const(def) then
+ { do nothing, varargs are ignored in signatures }
+ else if is_special_array(def) then
+ result:=false
+ else
+ begin
+ len:=tarraydef(def).highrange-tarraydef(def).lowrange+1;
+ if is_packed_array(def) then
+ begin
+ { convert from bits to bytes for bitpacked arrays }
+ len:=(len+7) div 8;
+ { and encode as plain array of bytes }
+ encodedstr:=encodedstr+'['+tostr(len)+'C]';
+ end
+ else
+ begin
+ encodedstr:=encodedstr+'['+tostr(len);
+ { Embedded structured types in the array are printed
+ in full regardless of the current recordinfostate. }
+ if not objcaddencodedtype(tarraydef(def).elementdef,ris_initial,false,encodedstr,founderror) then
+ begin
+ result:=false;
+ { report the exact (nested) error defintion }
+ exit;
+ end;
+ encodedstr:=encodedstr+']';
+ end;
+ end;
+ end;
+ procvardef :
+ encodedstr:=encodedstr+'^?';
+ objectdef :
+ case tobjectdef(def).objecttype of
+ odt_helper,
+ odt_class,
+ odt_object,
+ odt_cppclass:
+ begin
+ newstate:=recordinfostate;
+ { implicit pointer for classes }
+ if (tobjectdef(def).objecttype in [odt_class,odt_helper]) then
+ begin
+ encodedstr:=encodedstr+'^';
+ { make all classes opaque, so even if they contain a
+ reference-counted field there is no problem. Since a
+ "dereferenced class" object does not exist, this should
+ not cause problems }
+ newstate:=ris_dontprint;
+ end;
+ if newstate<>ris_dontprint then
+ begin
+ if not encoderecst(def.typename,tabstractrecordsymtable(tobjectdef(def).symtable),encodedstr,founderror) then
+ begin
+ result:=false;
+ { report the exact (nested) error defintion }
+ exit;
+ end
+ end
+ else
+ encodedstr:=encodedstr+'{'+def.typename+'}'
+ end;
+ odt_interfacecom,
+ odt_interfacecom_property,
+ odt_interfacecom_function,
+ odt_dispinterface:
+ result:=false;
+ odt_interfacecorba:
+ encodedstr:=encodedstr+'^{'+def.typename+'=}';
+ { In Objective-C, the actual types of class instances are
+ NSObject* etc, and those are encoded as "@". In FPC, to keep
+ the similarity with Delphi-style Object Pascal, the type is
+ NSObject and the pointer is implicit. Objective-C's "NSObject"
+ has "class of NSObject" as equivalent here. }
+ odt_objcclass,
+ odt_objcprotocol:
+ encodedstr:=encodedstr+'@';
+ else
+ internalerror(2009081509);
+ end;
+ undefineddef,
+ errordef :
+ result:=false;
+ procdef :
+ { must be done via objcencodemethod() }
+ internalerror(2009081511);
+ else
+ internalerror(2009150812);
+ end;
+ if not result then
+ founderror:=def;
+ end;
+
+
+ function objctryencodetype(def: tdef; out encodedtype: ansistring; out founderror: tdef): boolean;
+ begin
+ result:=objcaddencodedtype(def,ris_initial,false,encodedtype,founderror);
+ end;
+
+
+{******************************************************************
+ ObjC type validity checking
+*******************************************************************}
+
+ function objcdochecktype(def: tdef; recordinfostate: trecordinfostate; out founderror: tdef): boolean; forward;
+
+ function checkrecsttype(recst: tabstractrecordsymtable; recordinfostate: trecordinfostate; out founderror: tdef): boolean;
+ var
+ i: longint;
+ field: tfieldvarsym;
+ newstate: trecordinfostate;
+ begin
+ result:=false;
+ newstate:=recordinfostate;
+ { Although we never have to print the type info for nested
+ records, check them anyway in case we're not after a pointer
+ since if such records contain refcounted types then they
+ can cause just as much trouble as if they were a simple
+ refcounted field. }
+ if (newstate=ris_afterpointer) then
+ newstate:=ris_dontprint;
+ for i:=0 to recst.symlist.count-1 do
+ begin
+ if (tsym(recst.symlist[i]).typ<>fieldvarsym) then
+ continue;
+
+ field:=tfieldvarsym(recst.symlist[i]);
+ if not objcdochecktype(field.vardef,newstate,founderror) then
+ exit;
+ end;
+ result:=true
+ end;
+
+
+ function objcdochecktype(def: tdef; recordinfostate: trecordinfostate; out founderror: tdef): boolean;
+ var
+ recdef: trecorddef;
+ objdef: tobjectdef;
+ newstate: trecordinfostate;
+ begin
+ result:=true;
+ case def.typ of
+ stringdef :
+ begin
+ case tstringdef(def).stringtype of
+ st_shortstring:
+ ;
+ else
+ { While we could handle refcounted Pascal strings correctly
+ when such methods are called from Pascal code, things would
+ completely break down if they were called from Objective-C
+ code/reflection since the necessary refcount helper calls
+ would be missing on the caller side (unless we'd
+ automatically generate wrappers). }
+ result:=false;
+ end;
+ end;
+ enumdef,
+ orddef :
+ ;
+ pointerdef :
+ begin
+ newstate:=recordinfostate;
+ if (recordinfostate<ris_dontprint) then
+ newstate:=succ(newstate);
+ if not objcdochecktype(tpointerdef(def).pointeddef,newstate,founderror) then
+ begin
+ result:=false;
+ { report the exact (nested) error defintion }
+ exit;
+ end;
+ end;
+ floatdef :
+ begin
+ case tfloatdef(def).floattype of
+ s32real,
+ s64real:
+ ;
+ else
+ result:=false;
+ end;
+ end;
+ filedef :
+ result:=false;
+ recorddef :
+ begin
+ if (recordinfostate<>ris_dontprint) then
+ begin
+ if not checkrecsttype(tabstractrecordsymtable(trecorddef(def).symtable),recordinfostate,founderror) then
+ begin
+ result:=false;
+ { report the exact (nested) error defintion }
+ exit;
+ end
+ end
+ end;
+ variantdef :
+ begin
+ recdef:=trecorddef(search_system_type('TVARDATA').typedef);
+ if (recordinfostate<>ris_dontprint) then
+ begin
+ if not checkrecsttype(tabstractrecordsymtable(recdef.symtable),recordinfostate,founderror) then
+ begin
+ result:=false;
+ { report the exact (nested) error defintion }
+ exit;
+ end
+ end;
+ end;
+ classrefdef:
+ begin
+ if is_objcclassref(def) then
+ begin
+ objdef:=tobjectdef(tclassrefdef(def).pointeddef);
+ newstate:=recordinfostate;
+ if (recordinfostate<ris_dontprint) then
+ newstate:=succ(newstate);
+ if (newstate<>ris_dontprint) then
+ begin
+ if not checkrecsttype(tabstractrecordsymtable(objdef.symtable),recordinfostate,founderror) then
+ begin
+ result:=false;
+ { report the exact (nested) error defintion }
+ exit;
+ end
+ end
+ end
+ end;
+ setdef,
+ formaldef :
+ ;
+ arraydef :
+ begin
+ if is_array_of_const(def) then
+ { ok, varargs are ignored in signatures }
+ else if is_special_array(def) then
+ result:=false
+ else
+ begin
+ if not is_packed_array(def) then
+ begin
+ if not objcdochecktype(tarraydef(def).elementdef,ris_initial,founderror) then
+ begin
+ result:=false;
+ { report the exact (nested) error defintion }
+ exit;
+ end;
+ end;
+ end;
+ end;
+ procvardef :
+ ;
+ objectdef :
+ case tobjectdef(def).objecttype of
+ odt_helper,
+ odt_class,
+ odt_object,
+ odt_cppclass:
+ begin
+ newstate:=recordinfostate;
+ { implicit pointer for classes }
+ if (tobjectdef(def).objecttype in [odt_class,odt_helper]) then
+ begin
+ { make all classes opaque, so even if they contain a
+ reference-counted field there is no problem. Since a
+ "dereferenced class" object does not exist, this should
+ not cause problems }
+ newstate:=ris_dontprint;
+ end;
+ if newstate<>ris_dontprint then
+ begin
+ if not checkrecsttype(tabstractrecordsymtable(tobjectdef(def).symtable),newstate,founderror) then
+ begin
+ result:=false;
+ { report the exact (nested) error defintion }
+ exit;
+ end
+ end
+ end;
+ odt_interfacecom,
+ odt_interfacecom_property,
+ odt_interfacecom_function,
+ odt_dispinterface:
+ result:=false;
+ odt_interfacecorba,
+ odt_objcclass,
+ odt_objcprotocol:
+ ;
+ else
+ internalerror(2009081709);
+ end;
+ undefineddef,
+ errordef :
+ result:=false;
+ procdef :
+ result:=false;
+ else
+ internalerror(2009170812);
+ end;
+ if not result then
+ founderror:=def;
+ end;
+
+
+ function objcchecktype(def: tdef; out founderror: tdef): boolean;
+ begin
+ result:=objcdochecktype(def,ris_initial,founderror);
+ end;
+
+
+end.
diff --git a/closures/compiler/objcgutl.pas b/closures/compiler/objcgutl.pas
new file mode 100644
index 0000000000..6a5ce544d8
--- /dev/null
+++ b/closures/compiler/objcgutl.pas
@@ -0,0 +1,1625 @@
+{
+ Copyright (c) 2009 by Jonas Maebe
+
+ This unit implements some Objective-C helper routines at the code generator
+ level.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License,or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+
+{$i fpcdefs.inc}
+
+unit objcgutl;
+
+interface
+
+ uses
+ cclasses,
+ aasmbase,aasmdata,
+ symbase,symdef;
+
+ procedure objcfinishstringrefpoolentry(entry: phashsetitem; stringpool: tconstpooltype; refsec, stringsec: tasmsectiontype);
+ procedure objcfinishclassrefnfpoolentry(entry: phashsetitem; classdef: tobjectdef);
+
+ procedure MaybeGenerateObjectiveCImageInfo(globalst, localst: tsymtable);
+
+
+implementation
+
+ uses
+ globtype,globals,fmodule,
+ systems,
+ aasmtai,
+ cgbase,
+ objcdef,objcutil,
+ symconst,symtype,symsym,symtable,
+ verbose;
+
+ type
+ tobjcabi = (oa_fragile, oa_nonfragile);
+(* tivarlayouttype = (il_weak,il_strong); *)
+
+ tobjcrttiwriter = class
+ protected
+ fabi: tobjcabi;
+ classdefs,
+ catdefs: tfpobjectlist;
+ classsyms,
+ catsyms: tfpobjectlist;
+ procedure gen_objc_methods(list: tasmlist; objccls: tobjectdef; out methodslabel: tasmlabel; classmethods, iscategory: Boolean);
+ procedure gen_objc_protocol_elements(list: tasmlist; protocol: tobjectdef; out reqinstsym, optinstsym, reqclssym, optclssym: TAsmLabel);
+ procedure gen_objc_protocol_list(list:TAsmList; protolist: TFPObjectList; out protolistsym: TAsmLabel);
+ procedure gen_objc_cat_methods(list:TAsmList; items: TFPObjectList; section: tasmsectiontype;const sectname: string; out listsym: TAsmLabel);
+
+ procedure gen_objc_protocol(list:TAsmList; protocol: tobjectdef; out protocollabel: TAsmSymbol);virtual;abstract;
+ procedure gen_objc_category_sections(list:TAsmList; objccat: tobjectdef; out catlabel: TAsmSymbol);virtual;abstract;
+ procedure gen_objc_classes_sections(list:TAsmList; objclss: tobjectdef; out classlabel: TAsmSymbol);virtual;abstract;
+ procedure gen_objc_info_sections(list: tasmlist);virtual;abstract;
+ public
+ constructor create(_abi: tobjcabi);
+ destructor destroy;override;
+ procedure gen_objc_rtti_sections(list:TAsmList; st:TSymtable);
+ property abi: tobjcabi read fabi;
+ end;
+
+
+ { Used by by PowerPC/32 and i386 }
+ tobjcrttiwriter_fragile = class(tobjcrttiwriter)
+ protected
+ function gen_objc_protocol_ext(list: TAsmList; optinstsym, optclssym: TAsmLabel): TAsmLabel;
+ procedure gen_objc_ivars(list: TAsmList; objccls: tobjectdef; out ivarslabel: TAsmLabel);
+ procedure gen_objc_protocol(list:TAsmList; protocol: tobjectdef; out protocollabel: TAsmSymbol);override;
+ procedure gen_objc_category_sections(list:TAsmList; objccat: tobjectdef; out catlabel: TAsmSymbol);override;
+ procedure gen_objc_classes_sections(list:TAsmList; objclss: tobjectdef; out classlabel: TAsmSymbol);override;
+ procedure gen_objc_info_sections(list: tasmlist);override;
+ public
+ constructor create;
+ end;
+
+
+ { Used by PowerPC/64, ARM, and x86_64 }
+ tobjcrttiwriter_nonfragile = class(tobjcrttiwriter)
+ protected
+ ObjCEmptyCacheVar,
+ ObjCEmptyVtableVar: TAsmSymbol;
+
+ procedure gen_objc_class_ro_part(list: TAsmList; objclss: tobjectdef; protolistsym: TAsmSymbol; out classrolabel: TAsmSymbol; metaclass: boolean);
+ procedure addclasslist(list: tasmlist; section: tasmsectiontype; const symname: string; classes: tfpobjectlist);
+
+ procedure gen_objc_ivars(list: TAsmList; objccls: tobjectdef; out ivarslabel: TAsmLabel);
+ procedure gen_objc_protocol(list:TAsmList; protocol: tobjectdef; out protocollabel: TAsmSymbol);override;
+ procedure gen_objc_category_sections(list:TAsmList; objccat: tobjectdef; out catlabel: TAsmSymbol);override;
+ procedure gen_objc_classes_sections(list:TAsmList; objclss: tobjectdef; out classlabel: TAsmSymbol);override;
+ procedure gen_objc_info_sections(list: tasmlist);override;
+ public
+ constructor create;
+ end;
+
+
+
+{******************************************************************
+ Protocol declaration helpers
+*******************************************************************}
+
+function objcfindprotocolentry(const p: shortstring): TAsmSymbol;
+ var
+ item : PHashSetItem;
+ begin
+ result:=nil;
+ if not assigned(current_asmdata.ConstPools[sp_objcprotocolrefs]) then
+ exit;
+ item:=current_asmdata.constpools[sp_objcprotocolrefs].Find(@p[1], length(p));
+ if not assigned(item) then
+ exit;
+ result:=TAsmSymbol(item^.Data);
+ end;
+
+
+function objcaddprotocolentry(const p: shortstring; ref: TAsmSymbol): Boolean;
+ var
+ item : PHashSetItem;
+ begin
+ item:=current_asmdata.constpools[sp_objcprotocolrefs].FindOrAdd(@p[1], length(p));
+ Result:=(item^.Data=nil);
+ if Result then
+ item^.Data:=ref;
+ end;
+
+{******************************************************************
+ Pool section helpers
+*******************************************************************}
+
+function objcreatestringpoolentryintern(p: pchar; len: longint; pooltype: tconstpooltype; stringsec: tasmsectiontype): TAsmSymbol;
+ var
+ entry : PHashSetItem;
+ strlab : tasmlabel;
+ pc : pchar;
+ pool : THashSet;
+ begin
+ pool := current_asmdata.constpools[pooltype];
+
+ entry:=pool.FindOrAdd(p,len);
+ if not assigned(entry^.data) then
+ begin
+ { create new entry }
+ current_asmdata.getlabel(strlab,alt_data);
+ entry^.Data:=strlab;
+ getmem(pc,entry^.keylength+1);
+ move(entry^.key^,pc^,entry^.keylength);
+ pc[entry^.keylength]:=#0;
+
+ { add the string to the approriate section }
+ new_section(current_asmdata.asmlists[al_objc_pools],stringsec,strlab.name,0);
+ current_asmdata.asmlists[al_objc_pools].concat(Tai_label.Create(strlab));
+ current_asmdata.asmlists[al_objc_pools].concat(Tai_string.Create_pchar(pc,entry^.keylength+1));
+ Result := strlab;
+ end
+ else
+ Result := TAsmLabel(Entry^.Data);
+ end;
+
+
+procedure objcfinishstringrefpoolentry(entry: phashsetitem; stringpool: tconstpooltype; refsec, stringsec: tasmsectiontype);
+ var
+ reflab : tasmlabel;
+ strlab : tasmsymbol;
+ classname: string;
+ begin
+ { have we already generated a reference for this string entry? }
+ if not assigned(entry^.Data) then
+ begin
+ { no, add the string to the associated strings section }
+ strlab:=objcreatestringpoolentryintern(pchar(entry^.key),entry^.keylength,stringpool,stringsec);
+
+ { and now finish the reference }
+ current_asmdata.getlabel(reflab,alt_data);
+ entry^.Data:=reflab;
+
+ { add a pointer to the string in the string references section }
+ new_section(current_asmdata.asmlists[al_objc_pools],refsec,reflab.name,sizeof(pint));
+ current_asmdata.asmlists[al_objc_pools].concat(Tai_label.Create(reflab));
+ current_asmdata.asmlists[al_objc_pools].concat(Tai_const.Create_sym(strlab));
+
+ { in case of a class reference, also add a lazy symbol reference for
+ the class (the linker requires this for the fragile ABI). }
+ if (refsec=sec_objc_cls_refs) and
+ not(target_info.system in systems_objc_nfabi) then
+ begin
+ setlength(classname,entry^.keylength);
+ move(entry^.key^,classname[1],entry^.keylength);
+ current_asmdata.asmlists[al_objc_pools].concat(tai_directive.Create(asd_lazy_reference,'.objc_class_name_'+classname));
+ end;
+ end;
+ end;
+
+
+function objcreatestringpoolentry(const s: string; pooltype: tconstpooltype; stringsec: tasmsectiontype): TAsmSymbol;
+ begin
+ result:=objcreatestringpoolentryintern(@s[1],length(s),pooltype,stringsec);
+ end;
+
+
+procedure objcfinishclassrefnfpoolentry(entry: phashsetitem; classdef: tobjectdef);
+ var
+ reflab: TAsmLabel;
+ classym: TasmSymbol;
+ begin
+ { have we already generated a reference for this class ref entry? }
+ if not assigned(entry^.Data) then
+ begin
+ { no, add the classref to the sec_objc_cls_refs section }
+ current_asmdata.getlabel(reflab,alt_data);
+ entry^.Data:=reflab;
+
+ { add a pointer to the class }
+ new_section(current_asmdata.asmlists[al_objc_pools],sec_objc_cls_refs,reflab.name,sizeof(pint));
+ current_asmdata.asmlists[al_objc_pools].concat(Tai_label.Create(reflab));
+ classym:=current_asmdata.RefAsmSymbol(classdef.rtti_mangledname(objcclassrtti));
+ current_asmdata.asmlists[al_objc_pools].concat(Tai_const.Create_sym(classym));
+ end;
+ end;
+
+{******************************************************************
+ RTTI generation -- Helpers
+*******************************************************************}
+
+procedure ConcatSymOrNil(list: tasmlist; sym: TAsmSymbol); inline;
+begin
+ if Assigned(sym) then
+ list.Concat(tai_const.Create_sym(sym))
+ else
+ list.Concat(tai_const.Create_pint(0));
+end;
+
+
+{******************************************************************
+ RTTI generation -- Common
+*******************************************************************}
+
+{ generate a method list, either of class methods or of instance methods,
+ and both for obj-c classes and categories. }
+procedure tobjcrttiwriter.gen_objc_methods(list: tasmlist; objccls: tobjectdef; out methodslabel: tasmlabel; classmethods, iscategory: Boolean);
+ const
+ clsSectType : array [Boolean] of tasmsectiontype = (sec_objc_inst_meth, sec_objc_cls_meth);
+ clsSectName : array [Boolean] of string = ('_OBJC_INST_METH','_OBJC_CLS_METH');
+ catSectType : array [Boolean] of tasmsectiontype = (sec_objc_cat_inst_meth, sec_objc_cat_cls_meth);
+ catSectName : array [Boolean] of string = ('_OBJC_CAT_INST_METH','_OBJC_CAT_CLS_METH');
+ type
+ method_data = record
+ def : tprocdef;
+ selsym : TAsmSymbol;
+ encsym : TAsmSymbol;
+ end;
+ var
+ i : Integer;
+ def : tprocdef;
+ defs : array of method_data;
+ mcnt : integer;
+ sym : tasmsymbol;
+ mtype : tdef;
+ begin
+ methodslabel:=nil;
+ mcnt:=0;
+ { collect all instance/class methods }
+ SetLength(defs,objccls.vmtentries.count);
+ for i:=0 to objccls.vmtentries.count-1 do
+ begin
+ def:=pvmtentry(objccls.vmtentries[i])^.procdef;
+ if (def.owner.defowner=objccls) and
+ (classmethods = (po_classmethod in def.procoptions)) then
+ begin
+ defs[mcnt].def:=def;
+ defs[mcnt].selsym:=objcreatestringpoolentry(def.messageinf.str^,sp_objcvarnames,sec_objc_meth_var_names);
+ defs[mcnt].encsym:=objcreatestringpoolentry(objcencodemethod(def),sp_objcvartypes,sec_objc_meth_var_types);
+ inc(mcnt);
+ end;
+ end;
+ if mcnt=0 then
+ exit;
+
+ if iscategory then
+ new_section(list,catSectType[classmethods],catSectName[classmethods],sizeof(ptrint))
+ else
+ new_section(list,clsSectType[classmethods],clsSectName[classmethods],sizeof(ptrint));
+
+ current_asmdata.getlabel(methodslabel,alt_data);
+ list.Concat(tai_label.Create(methodslabel));
+
+ if (abi=oa_fragile) then
+ { not used, always zero }
+ list.Concat(tai_const.Create_32bit(0))
+ else
+ begin
+ { size of each entry -- always 32 bit value }
+ mtype:=search_named_unit_globaltype('OBJC','OBJC_METHOD',true).typedef;
+ list.Concat(tai_const.Create_32bit(mtype.size));
+ end;
+ { number of objc_method entries in the method_list array -- always 32 bit}
+ list.Concat(tai_const.Create_32bit(mcnt));
+ for i:=0 to mcnt-1 do
+ begin
+ { reference to the selector name }
+ list.Concat(tai_const.Create_sym(defs[i].selsym));
+ { reference to the obj-c encoded function parameters (signature) }
+ list.Concat(tai_const.Create_sym(defs[i].encsym));
+ { mangled name of the method }
+ sym:=current_asmdata.GetAsmSymbol(defs[i].def.mangledname);
+ if not assigned(sym) then
+ internalerror(2009091601);
+ list.Concat(tai_const.Create_sym(sym));
+ end;
+ end;
+
+
+{ generate method (and in the future also property) info for protocols }
+procedure tobjcrttiwriter.gen_objc_protocol_elements(list: tasmlist; protocol: tobjectdef; out reqinstsym, optinstsym, reqclssym, optclssym: TAsmLabel);
+ var
+ proc : tprocdef;
+ reqinstmlist,
+ reqclsmlist,
+ optinstmlist,
+ optclsmlist : TFPObjectList;
+ i : ptrint;
+ begin
+ reqinstmlist:=TFPObjectList.Create(false);
+ reqclsmlist:=TFPObjectList.Create(false);
+ optinstmlist:=TFPObjectList.Create(false);
+ optclsmlist:=TFPObjectList.Create(false);
+ for i:=0 to protocol.vmtentries.Count-1 do
+ begin
+ proc:=pvmtentry(protocol.vmtentries[i])^.procdef;
+ if (po_classmethod in proc.procoptions) then
+ if not(po_optional in proc.procoptions) then
+ reqclsmlist.Add(proc)
+ else
+ optclsmlist.Add(proc)
+ else if not(po_optional in proc.procoptions) then
+ reqinstmlist.Add(proc)
+ else
+ optinstmlist.Add(proc);
+ end;
+ if reqinstmlist.Count > 0 then
+ gen_objc_cat_methods(list,reqinstmlist,sec_objc_cat_inst_meth,'_OBJC_CAT_INST_METH',reqinstsym)
+ else
+ reqinstsym:=nil;
+ if optinstmlist.Count > 0 then
+ gen_objc_cat_methods(list,optinstmlist,sec_objc_cat_inst_meth,'_OBJC_CAT_INST_METH',optinstsym)
+ else
+ optinstsym:=nil;
+
+ if reqclsmlist.Count>0 then
+ gen_objc_cat_methods(list,reqclsmlist,sec_objc_cat_cls_meth,'_OBJC_CAT_CLS_METH',reqclssym)
+ else
+ reqclssym:=nil;
+ if optclsmlist.Count>0 then
+ gen_objc_cat_methods(list,optclsmlist,sec_objc_cat_cls_meth,'_OBJC_CAT_CLS_METH',optclssym)
+ else
+ optclssym:=nil;
+
+ reqinstmlist.Free;
+ reqclsmlist.Free;
+ optinstmlist.Free;
+ optclsmlist.Free;
+end;
+
+
+(*
+From CLang:
+
+ struct objc_protocol_list
+ {
+#ifdef FRAGILE_ABI
+ struct objc_protocol_list *next;
+ int count;
+#else
+ long count;
+#endif
+ Protocol *list[1];
+ };
+*)
+procedure tobjcrttiwriter.gen_objc_protocol_list(list: tasmlist; protolist: tfpobjectlist; out protolistsym: tasmlabel);
+ var
+ i : Integer;
+ protosym : TAsmSymbol;
+ protodef : tobjectdef;
+ begin
+ if not Assigned(protolist) or
+ (protolist.Count=0) then
+ begin
+ protolistsym:=nil;
+ Exit;
+ end;
+
+ for i:=0 to protolist.Count-1 do
+ begin
+ protodef:=TImplementedInterface(protolist[i]).IntfDef;
+ protosym:=objcfindprotocolentry(protodef.objextname^);
+ if not assigned(protosym) then
+ begin
+ gen_objc_protocol(list,protodef,protosym);
+ objcaddprotocolentry(protodef.objextname^,protosym);
+ end;
+ end;
+
+ { protocol lists are stored in .objc_cat_cls_meth section }
+ new_section(list,sec_objc_cat_cls_meth,'_OBJC_PROTOCOLLIST',sizeof(pint));
+ current_asmdata.getlabel(protolistsym, alt_data);
+ list.Concat(tai_label.Create(protolistsym));
+
+ if (abi=oa_fragile) then
+ { From Clang: next, always nil}
+ list.Concat(tai_const.Create_pint(0));
+ { From Clang: protocols count}
+ list.Concat(Tai_const.Create_pint(protolist.Count));
+ for i:=0 to protolist.Count-1 do
+ begin
+ protodef:=(protolist[i] as TImplementedInterface).IntfDef;
+ protosym:=objcfindprotocolentry(protodef.objextname^);
+ if not Assigned(protosym) then
+ begin
+ { For some reason protosym is not declared, though must be!
+ Probably gen_obcj1_protocol returned wrong protosym
+ }
+ InternalError(2009091602);
+ end;
+ list.Concat(tai_const.Create_sym(protosym));
+ end;
+ end;
+
+
+{ Generate rtti for an Objective-C methods (methods without implementation) }
+{ items : TFPObjectList of Tprocdef }
+procedure tobjcrttiwriter.gen_objc_cat_methods(list:TAsmList; items: TFPObjectList; section: tasmsectiontype;
+ const sectname: string; out listsym: TAsmLabel);
+var
+ i : integer;
+ m : tprocdef;
+ mtype : tdef;
+begin
+ if not assigned(items) or
+ (items.count=0) then
+ exit;
+
+ new_section(list, section, sectname, sizeof(pint));
+ current_asmdata.getlabel(listsym,alt_data);
+ list.Concat(tai_label.Create(listsym));
+ if (abi=oa_nonfragile) then
+ begin
+ { size of each entry -- always 32 bit value }
+ mtype:=search_named_unit_globaltype('OBJC','OBJC_METHOD',true).typedef;
+ list.Concat(tai_const.Create_32bit(mtype.size));
+ end;
+ list.Concat(Tai_const.Create_32bit(items.count));
+ for i:=0 to items.Count-1 do
+ begin
+ m:=tprocdef(items[i]);
+ list.Concat(Tai_const.Create_sym(
+ objcreatestringpoolentry(m.messageinf.str^,sp_objcvarnames,sec_objc_meth_var_names)));
+ list.Concat(Tai_const.Create_sym(
+ objcreatestringpoolentry(objcencodemethod(m),sp_objcvartypes,sec_objc_meth_var_types)));
+ { placeholder for address of implementation? }
+ if (abi=oa_nonfragile) then
+ list.Concat(Tai_const.Create_pint(0));
+ end;
+end;
+
+
+{ Generate the rtti sections for all obj-c classes defined in st, and return
+ these classes in the classes list. }
+procedure tobjcrttiwriter.gen_objc_rtti_sections(list:TAsmList; st:TSymtable);
+ var
+ i: longint;
+ def: tdef;
+ sym : TAsmSymbol;
+ begin
+ if not Assigned(st) then
+ exit;
+
+ for i:=0 to st.DefList.Count-1 do
+ begin
+ def:=tdef(st.DefList[i]);
+ { check whether all types used in Objective-C class/protocol/category
+ declarations can be used with the Objective-C run time (can only be
+ done now, because at parse-time some of these types can still be
+ forwarddefs) }
+ if is_objc_class_or_protocol(def) then
+ if not tobjectdef(def).check_objc_types then
+ continue;
+ if is_objcclass(def) and
+ not(oo_is_external in tobjectdef(def).objectoptions) then
+ begin
+ if not(oo_is_classhelper in tobjectdef(def).objectoptions) then
+ begin
+ gen_objc_classes_sections(list,tobjectdef(def),sym);
+ classsyms.add(sym);
+ classdefs.add(def);
+ end
+ else
+ begin
+ gen_objc_category_sections(list,tobjectdef(def),sym);
+ catsyms.add(sym);
+ catdefs.add(def);
+ end
+ end;
+ end;
+ end;
+
+
+constructor tobjcrttiwriter.create(_abi: tobjcabi);
+ begin
+ fabi:=_abi;
+ classdefs:=tfpobjectlist.create(false);
+ classsyms:=tfpobjectlist.create(false);
+ catdefs:=tfpobjectlist.create(false);
+ catsyms:=tfpobjectlist.create(false);
+ end;
+
+
+destructor tobjcrttiwriter.destroy;
+ begin
+ classdefs.free;
+ classsyms.free;
+ catdefs.free;
+ catsyms.free;
+ inherited destroy;
+ end;
+
+{******************************************************************
+ RTTI generation -- Fragile ABI
+*******************************************************************}
+
+{ generate an instance variables list for an obj-c class. }
+procedure tobjcrttiwriter_fragile.gen_objc_ivars(list: TAsmList; objccls: tobjectdef; out ivarslabel: TAsmLabel);
+ type
+ ivar_data = record
+ vf : tfieldvarsym;
+ namesym : TAsmSymbol;
+ typesym : TAsmSymbol;
+ end;
+ var
+ i : integer;
+ vf : tfieldvarsym;
+ vars : array of ivar_data;
+ vcnt : Integer;
+ enctype : ansistring;
+ encerr : tdef;
+ begin
+ ivarslabel:=nil;
+
+ vcnt:=0;
+ setLength(vars,objccls.symtable.SymList.Count);
+
+ for i:=0 to objccls.symtable.SymList.Count-1 do
+ if tsym(objccls.symtable.SymList[i]).typ=fieldvarsym then
+ begin
+ vf:=tfieldvarsym(objccls.symtable.SymList[i]);
+ if objctryencodetype(vf.vardef,enctype,encerr) then
+ begin
+ vars[vcnt].vf:=vf;
+ vars[vcnt].namesym:=objcreatestringpoolentry(vf.RealName,sp_objcvarnames,sec_objc_meth_var_names);
+ vars[vcnt].typesym:=objcreatestringpoolentry(enctype,sp_objcvartypes,sec_objc_meth_var_types);
+ inc(vcnt);
+ end
+ else
+ { Should be caught during parsing }
+ internalerror(2009090601);
+ end;
+ if vcnt=0 then
+ exit;
+
+ new_section(list,sec_objc_instance_vars,'_OBJC_INSTANCE_VARS',sizeof(pint));
+
+ current_asmdata.getlabel(ivarslabel,alt_data);
+ list.Concat(tai_label.Create(ivarslabel));
+
+ { objc_ivar_list: first the number of elements }
+ list.Concat(tai_const.Create_32bit(vcnt));
+
+ for i:=0 to vcnt-1 do
+ begin
+ { reference to the instance variable name }
+ list.Concat(tai_const.Create_sym(vars[i].namesym));
+ { reference to the encoded type }
+ list.Concat(tai_const.Create_sym(vars[i].typesym));
+ { and the offset of the field }
+ list.Concat(tai_const.Create_32bit(vars[i].vf.fieldoffset));
+ end;
+ end;
+
+
+(* From GCC:
+
+ struct _objc_protocol_extension
+ {
+ uint32_t size; // sizeof (struct _objc_protocol_extension)
+ struct objc_method_list *optional_instance_methods;
+ struct objc_method_list *optional_class_methods;
+ struct objc_prop_list *instance_properties;
+ }
+*)
+function tobjcrttiwriter_fragile.gen_objc_protocol_ext(list: TAsmList; optinstsym, optclssym: TAsmLabel): TAsmLabel;
+ begin
+ if assigned(optinstsym) or
+ assigned(optclssym) then
+ begin
+ new_section(list, sec_objc_protocol_ext,'_OBJC_PROTOCOLEXT',sizeof(pint));
+ current_asmdata.getlabel(Result,alt_data);
+ list.Concat(tai_label.Create(Result));
+ { size of this structure }
+ list.Concat(Tai_const.Create_32bit(16));
+ { optional instance methods }
+ ConcatSymOrNil(list,optinstsym);
+ { optional class methods }
+ ConcatSymOrNil(list,optclssym);
+ { optional properties (todo) }
+ ConcatSymOrNil(list,nil);
+ end
+ else
+ Result:=nil;
+ end;
+
+
+{ Generate rtti for an Objective-C protocol }
+procedure tobjcrttiwriter_fragile.gen_objc_protocol(list:TAsmList; protocol: tobjectdef; out protocollabel: TAsmSymbol);
+ var
+ namesym : TAsmSymbol;
+ protolist : TAsmLabel;
+ reqinstsym,
+ optinstsym,
+ reqclssym,
+ optclssym,
+ protoext,
+ lbl : TAsmLabel;
+ begin
+ gen_objc_protocol_list(list,protocol.ImplementedInterfaces,protolist);
+ gen_objc_protocol_elements(list,protocol,reqinstsym,optinstsym,reqclssym,optclssym);
+ protoext:=gen_objc_protocol_ext(list,optinstsym,optclssym);
+
+ new_section(list, sec_objc_protocol,'_OBJC_PROTOCOL',sizeof(pint));
+ current_asmdata.getlabel(lbl,alt_data);
+ list.Concat(tai_label.Create(lbl));
+ protocollabel:=lbl;
+
+ { protocol's isa - points to information about optional methods/properties }
+ ConcatSymOrNil(list,protoext);
+ { name }
+ namesym:=objcreatestringpoolentry(protocol.objextname^,sp_objcclassnames,sec_objc_class_names);
+ list.Concat(Tai_const.Create_sym(namesym));
+ { protocol's list }
+ ConcatSymOrNil(list,protolist);
+ { instance methods, in __cat_inst_meth }
+ ConcatSymOrNil(list,reqinstsym);
+ { class methods, in __cat_cls_meth }
+ ConcatSymOrNil(list,reqclssym);
+ end;
+
+
+(*
+From Clang:
+
+ struct _objc_category {
+ char *category_name;
+ char *class_name;
+ struct _objc_method_list *instance_methods;
+ struct _objc_method_list *class_methods;
+ struct _objc_protocol_list *protocols;
+ uint32_t size; // <rdar://4585769>
+ struct _objc_property_list *instance_properties;
+ };
+*)
+
+{ Generate rtti for an Objective-C class and its meta-class. }
+procedure tobjcrttiwriter_fragile.gen_objc_category_sections(list:TAsmList; objccat: tobjectdef; out catlabel: TAsmSymbol);
+ var
+ instmthdlist,
+ clsmthdlist,
+ protolistsym : TAsmLabel;
+ catstrsym,
+ clsstrsym,
+ catsym : TAsmSymbol;
+ begin
+ { the category name }
+ catstrsym:=objcreatestringpoolentry(objccat.objextname^,sp_objcclassnames,sec_objc_class_names);
+
+ { the name of the class it extends }
+ clsstrsym:=objcreatestringpoolentry(objccat.childof.objextname^,sp_objcclassnames,sec_objc_class_names);
+
+ { generate the methods lists }
+ gen_objc_methods(list,objccat,instmthdlist,false,true);
+ gen_objc_methods(list,objccat,clsmthdlist,true,true);
+
+ { generate implemented protocols list }
+ gen_objc_protocol_list(list,objccat.ImplementedInterfaces,protolistsym);
+
+ { category declaration section }
+ new_section(list,sec_objc_category,'_OBJC_CATEGORY',sizeof(pint));
+ catsym:=current_asmdata.DefineAsmSymbol(objccat.rtti_mangledname(objcclassrtti),AB_LOCAL,AT_DATA);
+ list.Concat(tai_symbol.Create(catsym,0));
+
+ list.Concat(Tai_const.Create_sym(catstrsym));
+ list.Concat(Tai_const.Create_sym(clsstrsym));
+ ConcatSymOrNil(list,instmthdlist);
+ ConcatSymOrNil(list,clsmthdlist);
+ ConcatSymOrNil(list,protolistsym);
+ { size of this structure }
+ list.Concat(Tai_const.Create_32bit(28));
+ { properties, not yet supported }
+ list.Concat(Tai_const.Create_32bit(0));
+
+ catlabel:=catsym;
+ end;
+
+(*
+From Clang:
+
+ struct _objc_class {
+ Class isa;
+ Class super_class;
+ const char *name;
+ long version;
+ long info;
+ long instance_size;
+ struct _objc_ivar_list *ivars;
+ struct _objc_method_list *methods;
+ struct _objc_cache *cache;
+ struct _objc_protocol_list *protocols;
+ // Objective-C 1.0 extensions (<rdr://4585769>) -- for garbage collection
+ const char *ivar_layout;
+ struct _objc_class_ext *ext;
+ };
+*)
+
+
+
+{ Generate rtti for an Objective-C class and its meta-class. }
+procedure tobjcrttiwriter_fragile.gen_objc_classes_sections(list:TAsmList; objclss: tobjectdef; out classlabel: TAsmSymbol);
+ const
+ CLS_CLASS = 1;
+ CLS_META = 2;
+ CLS_HIDDEN = $20000;
+ META_INST_SIZE = 40+8; // sizeof(objc_class) + 8
+ var
+ root : tobjectdef;
+ superStrSym,
+ classStrSym,
+ metaisaStrSym,
+ metasym,
+ clssym : TAsmSymbol;
+ mthdlist,
+ ivarslist,
+ protolistsym : TAsmLabel;
+ hiddenflag : cardinal;
+ begin
+ { generate the class methods list }
+ gen_objc_methods(list,objclss,mthdlist,true,false);
+
+ { generate implemented protocols list }
+ gen_objc_protocol_list(list,objclss.ImplementedInterfaces,protolistsym);
+
+ { register necessary names }
+ { 1) the superclass }
+ if assigned(objclss.childof) then
+ superStrSym:=objcreatestringpoolentry(objclss.childof.objextname^,sp_objcclassnames,sec_objc_class_names)
+ else
+ { not empty string, but nil! }
+ superStrSym:=nil;
+
+ { 2) the current class }
+ classStrSym:=objcreatestringpoolentry(objclss.objextname^,sp_objcclassnames,sec_objc_class_names);
+ { 3) the isa }
+ { From Clang: The isa for the meta-class is the root of the hierarchy. }
+ root:=objclss;
+ while assigned(root.childof) do
+ root:=root.childof;
+ metaisaStrSym:=objcreatestringpoolentry(root.objextname^,sp_objcclassnames,sec_objc_class_names);
+
+ { 4) the flags }
+ { consider every class declared in the implementation section of a unit
+ as "hidden"
+ }
+ hiddenflag:=0;
+ if (objclss.owner.symtabletype=staticsymtable) and
+ current_module.is_unit then
+ hiddenflag:=CLS_HIDDEN;
+
+ { class declaration section }
+ new_section(list,sec_objc_meta_class,'_OBJC_META_CLASS',sizeof(pint));
+
+ { 1) meta-class declaration }
+ metasym:=current_asmdata.DefineAsmSymbol(objclss.rtti_mangledname(objcmetartti),AB_LOCAL,AT_DATA);
+ list.Concat(tai_symbol.Create(metasym,0));
+
+ list.Concat(Tai_const.Create_sym(metaisaStrSym));
+ { pointer to the superclass name if any, otherwise nil }
+ if assigned(superstrsym) then
+ list.Concat(Tai_const.Create_sym(superStrSym))
+ else
+ list.concat(tai_const.create_32bit(0));
+ { pointer to the class name }
+ list.Concat(Tai_const.Create_sym(classStrSym));
+
+ { version is always 0 currently }
+ list.Concat(Tai_const.Create_32bit(0));
+ { CLS_META for meta-classes }
+ list.Concat(Tai_const.Create_32bit(hiddenflag or CLS_META));
+ { size of the meta-class instance: sizeof(objc_class) + 8 bytes }
+ list.Concat(Tai_const.Create_32bit(META_INST_SIZE) );
+ { meta-classes don't have ivars list (=0) }
+ list.Concat(Tai_const.Create_32bit(0));
+ { class methods list (stored in "__cls_meth" section) }
+ if Assigned(mthdlist) then
+ list.Concat(Tai_const.Create_sym(mthdlist))
+ else
+ list.Concat(Tai_const.Create_32bit(0));
+ { From Clang: cache is always nil }
+ list.Concat(Tai_const.Create_32bit(0));
+ { protocols }
+ ConcatSymOrNil(list, protolistsym);
+ { From Clang: ivar_layout for meta-class is always NULL. }
+ list.Concat(Tai_const.Create_32bit(0));
+ { From Clang: The class extension is always unused for meta-classes. }
+ list.Concat(Tai_const.Create_32bit(0));
+
+ { 2) regular class declaration }
+
+ { generate the instance methods list }
+ gen_objc_methods(list,objclss,mthdlist,false,false);
+ { generate the instance variables list }
+ gen_objc_ivars(list,objclss,ivarslist);
+
+ new_section(list,sec_objc_class,'_OBJC_CLASS',sizeof(pint));
+
+ clssym:=current_asmdata.DefineAsmSymbol(objclss.rtti_mangledname(objcclassrtti),AB_LOCAL,AT_DATA);
+ list.Concat(tai_symbol.Create(clssym,0));
+
+ { for class declaration: the isa points to the meta-class declaration }
+ list.Concat(Tai_const.Create_sym(metasym));
+ { pointer to the super_class name if any, nil otherwise }
+ if assigned(superStrSym) then
+ list.Concat(Tai_const.Create_sym(superStrSym))
+ else
+ list.Concat(Tai_const.Create_32bit(0));
+ { pointer to the class name }
+ list.Concat(Tai_const.Create_sym(classStrSym));
+ { version is always 0 currently }
+ list.Concat(Tai_const.Create_32bit(0));
+ { CLS_CLASS for classes }
+ list.Concat(Tai_const.Create_32bit(hiddenflag or CLS_CLASS));
+ { size of instance: total size of instance variables }
+ list.Concat(Tai_const.Create_32bit(tobjectsymtable(objclss.symtable).datasize));
+ { objc_ivar_list (stored in "__instance_vars" section) }
+ if assigned(ivarslist) then
+ list.Concat(Tai_const.Create_sym(ivarslist))
+ else
+ list.Concat(tai_const.create_32bit(0));
+ { instance methods list (stored in "__inst_meth" section) }
+ if Assigned(mthdlist) then
+ list.Concat(Tai_const.Create_sym(mthdlist))
+ else
+ list.Concat(Tai_const.Create_32bit(0));
+ { From Clang: cache is always NULL }
+ list.Concat(Tai_const.Create_32bit(0));
+ { protocols, protolistsym has been created for meta-class, no need to create another one}
+ ConcatSymOrNil(list, protolistsym);
+ { TODO: From Clang: strong ivar_layout, necessary for garbage collection support }
+ list.Concat(Tai_const.Create_32bit(0));
+ { TODO: From Clang: weak ivar_layout, necessary for garbage collection support }
+ list.Concat(Tai_const.Create_32bit(0));
+
+ classlabel:=clssym;
+ end;
+
+
+{ Generate the global information sections (objc_symbols and objc_module_info)
+ for this module. }
+procedure tobjcrttiwriter_fragile.gen_objc_info_sections(list: tasmlist);
+ var
+ i: longint;
+ sym : TAsmSymbol;
+ parent: tobjectdef;
+ superclasses: tfpobjectlist;
+ begin
+ if (classsyms.count<>0) or
+ (catsyms.count<>0) then
+ begin
+ new_section(list,sec_objc_symbols,'_OBJC_SYMBOLS',sizeof(pint));
+ sym := current_asmdata.DefineAsmSymbol(target_asm.labelprefix+'_OBJC_SYMBOLS_$',AB_LOCAL,AT_DATA);
+
+ { symbol to refer to this information }
+ list.Concat(tai_symbol.Create(sym,0));
+ { ??? (always 0 in Clang) }
+ list.Concat(Tai_const.Create_pint(0));
+ { ??? (From Clang: always 0, pointer to some selector) }
+ list.Concat(Tai_const.Create_pint(0));
+ { From Clang: number of defined classes }
+ list.Concat(Tai_const.Create_16bit(classsyms.count));
+ { From Clang: number of defined categories }
+ list.Concat(Tai_const.Create_16bit(catsyms.count));
+ { first all classes }
+ for i:=0 to classsyms.count-1 do
+ list.Concat(Tai_const.Create_sym(tasmsymbol(classsyms[i])));
+ { then all categories }
+ for i:=0 to catsyms.count-1 do
+ list.Concat(Tai_const.Create_sym(tasmsymbol(catsyms[i])));
+ end
+ else
+ sym:=nil;
+
+ new_section(list,sec_objc_module_info,'_OBJC_MODULE_INFO',4);
+ { version number = 7 (always, both for gcc and clang) }
+ list.Concat(Tai_const.Create_pint(7));
+ { sizeof(objc_module): 4 pointer-size entities }
+ list.Concat(Tai_const.Create_pint(sizeof(pint)*4));
+ { used to be file name, now unused (points to empty string) }
+ list.Concat(Tai_const.Create_sym(objcreatestringpoolentry('',sp_objcclassnames,sec_objc_class_names)));
+ { pointer to classes/categories list declared in this module }
+ if assigned(sym) then
+ list.Concat(Tai_const.Create_sym(sym))
+ else
+ list.concat(tai_const.create_pint(0));
+
+ { Add lazy references to parent classes of all classes defined in this unit }
+ superclasses:=tfpobjectlist.create(false);
+ for i:=0 to classdefs.count-1 do
+ begin
+ parent:=tobjectdef(classdefs[i]).childof;
+ { warning: linear search, performance hazard if large number of subclasses }
+ if assigned(parent) and
+ (superclasses.indexof(parent)=-1) then
+ begin
+ list.concat(tai_directive.create(asd_lazy_reference,'.objc_class_name_'+parent.objextname^));
+ superclasses.add(parent);
+ end;
+ end;
+ for i:=0 to catdefs.count-1 do
+ begin
+ parent:=tobjectdef(catdefs[i]).childof;
+ { warning: linear search, performance hazard if large number of subclasses }
+ if assigned(parent) and
+ (superclasses.indexof(parent)=-1) then
+ begin
+ list.concat(tai_directive.create(asd_lazy_reference,'.objc_class_name_'+parent.objextname^));
+ superclasses.add(parent);
+ end;
+ end;
+ superclasses.free;
+ { reference symbols for all classes and categories defined in this unit }
+ for i:=0 to classdefs.count-1 do
+ list.concat(tai_symbol.Createname_global_value('.objc_class_name_'+tobjectdef(classdefs[i]).objextname^,AT_DATA,0,0));
+ for i:=0 to catdefs.count-1 do
+ list.concat(tai_symbol.Createname_global_value('.objc_category_name_'+
+ tobjectdef(catdefs[i]).childof.objextname^+'_'+
+ tobjectdef(catdefs[i]).objextname^,AT_DATA,0,0));
+ end;
+
+
+constructor tobjcrttiwriter_fragile.create;
+ begin
+ inherited create(oa_fragile);
+ end;
+
+
+{******************************************************************
+ RTTI generation -- Non-Fragile ABI
+*******************************************************************}
+
+(*
+From Clang:
+/// EmitIvarList - Emit the ivar list for the given
+/// implementation. The return value has type
+/// IvarListnfABIPtrTy.
+/// struct _ivar_t {
+/// unsigned long int *offset; // pointer to ivar offset location
+/// char *name;
+/// char *type;
+/// uint32_t alignment;
+/// uint32_t size;
+/// }
+/// struct _ivar_list_t {
+/// uint32 entsize; // sizeof(struct _ivar_t)
+/// uint32 count;
+/// struct _iver_t list[count];
+/// }
+///
+*)
+procedure tobjcrttiwriter_nonfragile.gen_objc_ivars(list: tasmlist; objccls: tobjectdef; out ivarslabel: tasmlabel);
+ type
+ ivar_data = record
+ vf : tfieldvarsym;
+ namesym : TAsmSymbol;
+ typesym : TAsmSymbol;
+ offssym : TAsmSymbol;
+ end;
+ var
+ ivtype: tdef;
+ vf : tfieldvarsym;
+ vars : array of ivar_data;
+ i : integer;
+ vcnt : integer;
+ enctype : ansistring;
+ encerr : tdef;
+ prefix : shortstring;
+ vis : TAsmsymbind;
+ begin
+ ivarslabel:=nil;
+
+ vcnt:=0;
+ setLength(vars,objccls.symtable.SymList.Count);
+
+ for i:=0 to objccls.symtable.SymList.Count-1 do
+ if tsym(objccls.symtable.SymList[i]).typ=fieldvarsym then
+ begin
+ vf:=tfieldvarsym(objccls.symtable.SymList[i]);
+ if objctryencodetype(vf.vardef,enctype,encerr) then
+ begin
+ vars[vcnt].vf:=vf;
+ vars[vcnt].namesym:=objcreatestringpoolentry(vf.RealName,sp_objcvarnames,sec_objc_meth_var_names);
+ vars[vcnt].typesym:=objcreatestringpoolentry(enctype,sp_objcvartypes,sec_objc_meth_var_types);
+ if (vcnt=0) then
+ begin
+ new_section(list,sec_objc_const,'_OBJC_IVAR_OFFSETS',sizeof(pint));
+ prefix:=target_info.cprefix+'OBJC_IVAR_$_'+objccls.objextname^+'.';
+ end;
+ { This matches gcc/Clang, but is strange: I would expect private
+ fields to be local symbols rather than private_extern (which
+ is "package-global") (JM)
+ }
+ if not(vf.visibility in [vis_public,vis_protected,vis_strictprotected]) then
+ vis:=AB_PRIVATE_EXTERN
+ else
+ vis:=AB_GLOBAL;
+ vars[vcnt].offssym:=current_asmdata.DefineAsmSymbol(prefix+vf.RealName,vis,AT_DATA);
+ list.concat(tai_symbol.Create_Global(vars[vcnt].offssym,0));
+ list.concat(tai_const.create_pint(vf.fieldoffset));
+ inc(vcnt);
+ end
+ else
+ { must be caught during parsing }
+ internalerror(2009092301);
+ end;
+ if vcnt=0 then
+ exit;
+
+ new_section(list,sec_objc_instance_vars,'_OBJC_INSTANCE_VARS',sizeof(pint));
+
+ current_asmdata.getlabel(ivarslabel,alt_data);
+ list.Concat(tai_label.Create(ivarslabel));
+
+ { size of each entry -- always 32 bit value }
+ ivtype:=search_named_unit_globaltype('OBJC','OBJC_IVAR',true).typedef;
+ list.concat(tai_const.Create_32bit(ivtype.size));
+ { number of entries -- always 32 bit value }
+ list.Concat(tai_const.Create_32bit(vcnt));
+
+ for i:=0 to vcnt-1 do
+ begin
+ { reference to the offset }
+ list.Concat(tai_const.Create_sym(vars[i].offssym));
+ { reference to the instance variable name }
+ list.Concat(tai_const.Create_sym(vars[i].namesym));
+ { reference to the encoded type }
+ list.Concat(tai_const.Create_sym(vars[i].typesym));
+ { alignment -- always 32 bit value }
+ list.Concat(tai_const.create_32bit(vars[i].vf.vardef.alignment));
+ { size -- always 32 bit value }
+ list.Concat(tai_const.Create_32bit(vars[i].vf.vardef.size));
+ end;
+ end;
+
+
+(*
+From Clang:
+/// GetOrEmitProtocol - Generate the protocol meta-data:
+/// @code
+/// struct _protocol_t {
+/// id isa; // NULL
+/// const char * const protocol_name;
+/// const struct _protocol_list_t * protocol_list; // super protocols
+/// const struct method_list_t * const instance_methods;
+/// const struct method_list_t * const class_methods;
+/// const struct method_list_t *optionalInstanceMethods;
+/// const struct method_list_t *optionalClassMethods;
+/// const struct _prop_list_t * properties;
+/// const uint32_t size; // sizeof(struct _protocol_t)
+/// const uint32_t flags; // = 0
+/// }
+/// @endcode
+*)
+procedure tobjcrttiwriter_nonfragile.gen_objc_protocol(list: tasmlist; protocol: tobjectdef; out protocollabel: tasmsymbol);
+ var
+ lbl,
+ namesym,
+ listsym : TAsmSymbol;
+ protolist : TAsmLabel;
+ reqinstsym,
+ reqclssym,
+ optinstsym,
+ optclssym : TAsmLabel;
+ prottype : tdef;
+ begin
+ gen_objc_protocol_list(list,protocol.ImplementedInterfaces,protolist);
+ gen_objc_protocol_elements(list,protocol,reqinstsym,optinstsym,reqclssym,optclssym);
+
+ new_section(list, sec_data_coalesced,'_OBJC_PROTOCOL',sizeof(pint));
+ { label for the protocol needs to be
+ a) in a coalesced section (so multiple definitions of the same protocol
+ can be merged by the linker)
+ b) private_extern (should only be merged within the same module)
+ c) weakly defined (so multiple definitions don't cause errors)
+ }
+ lbl:=current_asmdata.DefineAsmSymbol(protocol.rtti_mangledname(objcclassrtti),AB_PRIVATE_EXTERN,AT_DATA);
+ list.Concat(tai_symbol.Create_Global(lbl,0));
+ list.Concat(tai_directive.Create(asd_weak_definition,lbl.name));
+ protocollabel:=lbl;
+
+ { protocol's isa - always nil }
+ list.Concat(Tai_const.Create_pint(0));
+ { name }
+ namesym:=objcreatestringpoolentry(protocol.objextname^,sp_objcclassnames,sec_objc_class_names);
+ list.Concat(Tai_const.Create_sym(namesym));
+ { parent protocols list }
+ ConcatSymOrNil(list,protolist);
+ { required instance methods }
+ ConcatSymOrNil(list,reqinstsym);
+ { required class methods }
+ ConcatSymOrNil(list,reqclssym);
+ { optional instance methods }
+ ConcatSymOrNil(list,optinstsym);
+ { optional class methods }
+ ConcatSymOrNil(list,optclssym);
+ { TODO: properties }
+ list.Concat(Tai_const.Create_pint(0));
+ { size of this type }
+ prottype:=search_named_unit_globaltype('OBJC','OBJC_PROTOCOL',true).typedef;
+ list.concat(tai_const.Create_32bit(prottype.size));
+ { flags }
+ list.concat(tai_const.Create_32bit(0));
+
+ { also add an entry to the __DATA, __objc_protolist section, required to
+ register the protocol with the runtime }
+ new_section(list, sec_objc_protolist,'_OBJC_PROTOLIST',sizeof(pint));
+ listsym:=current_asmdata.DefineAsmSymbol(protocol.rtti_mangledname(objcmetartti),AB_PRIVATE_EXTERN,AT_DATA);
+ list.Concat(tai_symbol.Create_Global(listsym,0));
+ list.Concat(tai_const.Create_sym(lbl));
+ list.Concat(tai_directive.Create(asd_weak_definition,listsym.name));
+ end;
+
+(*
+From Clang:
+/// struct _category_t {
+/// const char * const name;
+/// struct _class_t *const cls;
+/// const struct _method_list_t * const instance_methods;
+/// const struct _method_list_t * const class_methods;
+/// const struct _protocol_list_t * const protocols;
+/// const struct _prop_list_t * const properties;
+/// }
+*)
+procedure tobjcrttiwriter_nonfragile.gen_objc_category_sections(list:TAsmList; objccat: tobjectdef; out catlabel: TAsmSymbol);
+ var
+ instmthdlist,
+ clsmthdlist,
+ protolistsym : TAsmLabel;
+ catstrsym,
+ clssym,
+ catsym : TAsmSymbol;
+ begin
+ { the category name }
+ catstrsym:=objcreatestringpoolentry(objccat.objextname^,sp_objcclassnames,sec_objc_class_names);
+
+ { the class it extends }
+ clssym:=current_asmdata.RefAsmSymbol(objccat.childof.rtti_mangledname(objcclassrtti));
+
+ { generate the methods lists }
+ gen_objc_methods(list,objccat,instmthdlist,false,true);
+ gen_objc_methods(list,objccat,clsmthdlist,true,true);
+
+ { generate implemented protocols list }
+ gen_objc_protocol_list(list,objccat.ImplementedInterfaces,protolistsym);
+
+ { category declaration section }
+ new_section(list,sec_objc_const,'_OBJC_CATEGORY',sizeof(pint));
+ catsym:=current_asmdata.DefineAsmSymbol(objccat.rtti_mangledname(objcclassrtti),AB_LOCAL,AT_DATA);
+ list.Concat(tai_symbol.Create(catsym,0));
+
+ list.Concat(Tai_const.Create_sym(catstrsym));
+ list.Concat(Tai_const.Create_sym(clssym));
+ ConcatSymOrNil(list,instmthdlist);
+ ConcatSymOrNil(list,clsmthdlist);
+ ConcatSymOrNil(list,protolistsym);
+ { properties, not yet supported }
+ list.Concat(Tai_const.Create_pint(0));
+
+ catlabel:=catsym;
+ end;
+
+
+(*
+From Clang:
+/// BuildIvarLayout - Builds ivar layout bitmap for the class
+/// implementation for the __strong or __weak case.
+/// The layout map displays which words in ivar list must be skipped
+/// and which must be scanned by GC (see below). String is built of bytes.
+/// Each byte is divided up in two nibbles (4-bit each). Left nibble is count
+/// of words to skip and right nibble is count of words to scan. So, each
+/// nibble represents up to 15 workds to skip or scan. Skipping the rest is
+/// represented by a 0x00 byte which also ends the string.
+/// 1. when ForStrongLayout is true, following ivars are scanned:
+/// - id, Class
+/// - object * // note: this "object" means "Objective-C object" (JM)
+/// - __strong anything
+///
+/// 2. When ForStrongLayout is false, following ivars are scanned:
+/// - __weak anything
+*)
+(*
+
+Only required when supporting garbage collection
+
+procedure tobjcrttiwriter_nonfragile.gen_objc_ivargc_recursive(st: tabstractrecordsymtable; ptrbset: tbitset; startoffset: puint; il: tivarlayouttype);
+var
+ i: longint;
+ fs: tfieldvarsym;
+ includelen: longint;
+begin
+ for i:=0 to st.SymList.count-1 do
+ if (tsym(st.symlist[i]).typ=fieldvarsym) then
+ begin
+ fs:=tfieldvarsym(st.symlist[i]);
+ includelen:=0;
+ case fs.vardef.typ of
+ pointerdef,
+ classrefdef:
+ if (fs.vardef=objc_idtype) or
+ (fs.vardef=objc_metaclasstype) then
+ includelen:=1;
+ recorddef:
+ TODO: bitpacking -> offset differences
+ gen_objc_ivargc_recursive(tabstractrecordsymtable(trecorddef(fs.vardef).symtable),ptrbset,startoffset+fs.fieldoffset,il);
+ arraydef:
+ begin
+ if not is_special_
+ end;
+ objectdef :
+ begin
+ case tobjectdef(fs.vardef).objecttype of
+ odt_objcclass,
+ odt_objcprotocol:
+ includelen:=1;
+ odt_object:
+ gen_objc_ivargc_recursive(tabstractrecordsymtable(tobjectdef(fs.vardef).symtable),ptrbset,startoffset+fs.fieldoffset,il);
+ end;
+ end;
+ end;
+ end;
+end;
+
+
+function tobjcrttiwriter_nonfragile.gen_objc_ivargcstring(objclss: tobjectdef; il: tivarlayouttype): ansistring;
+ var
+ ptrbset: tbitset;
+ parent: tobjectdef;
+ size,
+ startoffset: puint;
+ i: longint;
+ begin
+ size:=tObjectSymtable(objclss.symtable).datasize;
+ if assigned(objclss.childof) then
+ startoffset:=tObjectSymtable(objclss.childof.symtable).datasize
+ else
+ startoffset:=0;
+ size:=size-startoffset;
+ ptrbset:=tbitset.create_bytesize((size+sizeof(ptruint)-1) div sizeof(ptruint));
+ { has to include info for this class' fields and those of all parent
+ classes as well
+ }
+ parent:=obclss;
+ repeat
+ gen_objc_ivargc_recursive(parent.symtable,ptrbset,0,il);
+ parent:=parent.childof;
+ until not assigned(parent);
+ { convert bits set to encoded string }
+ end;
+*)
+
+(*
+From Clang:
+/// struct _class_ro_t {
+/// uint32_t const flags;
+/// uint32_t const instanceStart;
+/// uint32_t const instanceSize;
+/// uint32_t const reserved; // only when building for 64bit targets
+/// const uint8_t * const ivarLayout;
+/// const char *const name;
+/// const struct _method_list_t * const baseMethods;
+/// const struct _protocol_list_t *const baseProtocols;
+/// const struct _ivar_list_t *const ivars;
+/// const uint8_t * const weakIvarLayout;
+/// const struct _prop_list_t * const properties;
+/// }
+*)
+
+procedure tobjcrttiwriter_nonfragile.gen_objc_class_ro_part(list: tasmlist; objclss: tobjectdef; protolistsym: TAsmSymbol; out classrolabel: tasmsymbol; metaclass: boolean);
+ const
+ CLS_CLASS = 0;
+ CLS_META = 1;
+ CLS_ROOT = 2;
+ OBJC2_CLS_HIDDEN = $10;
+ CLS_EXCEPTION = $20;
+ var
+ classStrSym,
+ rosym : TAsmSymbol;
+ methodslab,
+ ivarslab : TAsmLabel;
+ class_type : tdef;
+ start,
+ size,
+ flags : cardinal;
+ rttitype : trttitype;
+ firstfield : tfieldvarsym;
+ i : longint;
+ begin
+ { consider every class declared in the implementation section of a unit
+ as "hidden"
+ }
+ flags:=0;
+ if (objclss.owner.symtabletype=staticsymtable) and
+ current_module.is_unit then
+ flags:=OBJC2_CLS_HIDDEN;
+ if metaclass then
+ begin
+ flags:=flags or CLS_META;
+ rttitype:=objcmetarortti;
+ { metaclass size/start: always size of objc_object }
+ class_type:=search_named_unit_globaltype('OBJC','OBJC_OBJECT',true).typedef;
+ start:=class_type.size;
+ size:=start;
+ end
+ else
+ begin
+ flags:=flags or CLS_CLASS;
+ rttitype:=objcclassrortti;
+ size:=tObjectSymtable(objclss.symtable).datasize;
+ { can't simply use childof's datasize, because alignment may cause the
+ first field to skip a couple of bytes after the previous end }
+ firstfield:=nil;
+ for i:=0 to objclss.symtable.SymList.Count-1 do
+ if (tsym(objclss.symtable.SymList[i]).typ=fieldvarsym) then
+ begin
+ firstfield:=tfieldvarsym(objclss.symtable.SymList[i]);
+ break;
+ end;
+ if assigned(firstfield) then
+ start:=firstfield.fieldoffset
+ else
+ { no extra fields -> start = size }
+ start:=size;
+ end;
+ if not assigned(objclss.childof) then
+ flags:=flags or CLS_ROOT;
+
+ classStrSym:=objcreatestringpoolentry(objclss.objextname^,sp_objcclassnames,sec_objc_class_names);
+ { generate methods list }
+ gen_objc_methods(list,objclss,methodslab,metaclass,false);
+ { generate ivars (nil for metaclass) }
+ if metaclass then
+ ivarslab:=nil
+ else
+ gen_objc_ivars(list,objclss,ivarslab);
+
+ { class declaration section }
+ new_section(list,sec_objc_const,'_OBJC_META_CLASS',sizeof(pint));
+
+ rosym:=current_asmdata.DefineAsmSymbol(objclss.rtti_mangledname(rttitype),AB_LOCAL,AT_DATA);
+ classrolabel:=rosym;
+ list.Concat(tai_symbol.create(rosym,0));
+ list.Concat(tai_const.Create_32bit(longint(flags)));
+ list.Concat(tai_const.Create_32bit(longint(start)));
+ list.Concat(tai_const.Create_32bit(longint(size)));
+{$ifdef cpu64bitaddr}
+ { alignment }
+ list.Concat(tai_const.Create_32bit(0));
+{$endif}
+ { TODO: strong ivar layout for garbage collection }
+ list.concat(tai_const.Create_pint(0));
+ list.concat(tai_const.Create_sym(classStrSym));
+ ConcatSymOrNil(list,methodslab);
+ ConcatSymOrNil(list,protolistsym);
+ ConcatSymOrNil(list,ivarslab);
+ { TODO: weak ivar layout for garbage collection }
+ list.concat(tai_const.Create_pint(0));
+ { TODO: properties }
+ list.concat(tai_const.Create_pint(0));
+ end;
+
+
+(*
+From Clang:
+
+/// struct _class_t {
+/// struct _class_t *isa;
+/// struct _class_t * const superclass;
+/// void *cache;
+/// IMP *vtable;
+/// struct class_ro_t *ro;
+/// }
+///
+*)
+
+{ Generate rtti for an Objective-C class and its meta-class. }
+procedure tobjcrttiwriter_nonfragile.gen_objc_classes_sections(list:TAsmList; objclss: tobjectdef; out classlabel: TAsmSymbol);
+ var
+ root : tobjectdef;
+ superSym,
+ superMetaSym,
+ metaisaSym,
+ metasym,
+ clssym,
+ metarosym,
+ rosym : TAsmSymbol;
+ protolistsym : TAsmLabel;
+ vis : TAsmsymbind;
+ begin
+ { A) Register necessary names }
+
+ { 1) the current class and metaclass }
+ if (objclss.owner.symtabletype=globalsymtable) then
+ vis:=AB_GLOBAL
+ else
+ vis:=AB_PRIVATE_EXTERN;
+ clssym:=current_asmdata.DefineAsmSymbol(objclss.rtti_mangledname(objcclassrtti),vis,AT_DATA);
+ metasym:=current_asmdata.DefineAsmSymbol(objclss.rtti_mangledname(objcmetartti),vis,AT_DATA);
+ { 2) the superclass and meta superclass }
+ if assigned(objclss.childof) then
+ begin
+ superSym:=current_asmdata.RefAsmSymbol(objclss.childof.rtti_mangledname(objcclassrtti));
+ superMetaSym:=current_asmdata.RefAsmSymbol(objclss.childof.rtti_mangledname(objcmetartti));
+ end
+ else
+ begin
+ superSym:=nil;
+ { the class itself }
+ superMetaSym:=clssym;
+ end;
+
+ { 3) the isa }
+ { From Clang: The isa for the meta-class is the root of the hierarchy. }
+ root:=objclss;
+ while assigned(root.childof) do
+ root:=root.childof;
+ metaisaSym:=current_asmdata.RefAsmSymbol(root.rtti_mangledname(objcmetartti));
+
+ { 4) the implemented protocols (same for metaclass and regular class) }
+ gen_objc_protocol_list(list,objclss.ImplementedInterfaces,protolistsym);
+
+ { 5) the read-only parts of the class definitions }
+ gen_objc_class_ro_part(list,objclss,protolistsym,metarosym,true);
+ gen_objc_class_ro_part(list,objclss,protolistsym,rosym,false);
+
+ { B) Class declaration section }
+ { both class and metaclass are in the objc_data section for obj-c 2 }
+ new_section(list,sec_objc_data,'_OBJC_CLASS',sizeof(pint));
+
+ { 1) meta-class declaration }
+ list.Concat(tai_symbol.Create_Global(metasym,0));
+
+ { the isa }
+ list.Concat(Tai_const.Create_sym(metaisaSym));
+ { the superclass }
+ list.Concat(Tai_const.Create_sym(superMetaSym));
+ { pointer to cache }
+ if not assigned(ObjCEmptyCacheVar) then
+ ObjCEmptyCacheVar:=current_asmdata.RefAsmSymbol(target_info.Cprefix+'_objc_empty_cache');
+ list.Concat(Tai_const.Create_sym(ObjCEmptyCacheVar));
+ { pointer to vtable }
+ if not assigned(ObjCEmptyVtableVar) then
+ ObjCEmptyVtableVar:=current_asmdata.RefAsmSymbol(target_info.Cprefix+'_objc_empty_vtable');
+ list.Concat(Tai_const.Create_sym(ObjCEmptyVtableVar));
+ { the read-only part }
+ list.Concat(Tai_const.Create_sym(metarosym));
+
+ { 2) regular class declaration }
+ list.Concat(tai_symbol.Create_Global(clssym,0));
+
+ { the isa }
+ list.Concat(Tai_const.Create_sym(metasym));
+ { the superclass }
+ list.Concat(Tai_const.Create_sym(superSym));
+ { pointer to cache }
+ list.Concat(Tai_const.Create_sym(ObjCEmptyCacheVar));
+ { pointer to vtable }
+ list.Concat(Tai_const.Create_sym(ObjCEmptyVtableVar));
+ { the read-only part }
+ list.Concat(Tai_const.Create_sym(rosym));
+
+ classlabel:=clssym;
+ end;
+
+
+procedure tobjcrttiwriter_nonfragile.addclasslist(list: tasmlist; section: tasmsectiontype; const symname: string; classes: tfpobjectlist);
+ var
+ i: longint;
+ sym: TAsmSymbol;
+ begin
+ if classes.count=0 then
+ exit;
+ new_section(list,section,symname,sizeof(pint));
+ sym:=current_asmdata.DefineAsmSymbol(symname,AB_LOCAL,AT_DATA);
+ list.concat(tai_symbol.Create(sym,0));
+ for i:=0 to classes.count-1 do
+ list.concat(tai_const.Create_sym(current_asmdata.RefAsmSymbol(tobjectdef(classes[i]).rtti_mangledname(objcclassrtti))));
+ end;
+
+
+procedure tobjcrttiwriter_nonfragile.gen_objc_info_sections(list: tasmlist);
+
+ function collectnonlazyclasses(classes: tfpobjectlist): tfpobjectlist;
+ var
+ symentry : tsym;
+ procdef : tprocdef;
+ i,j : longint;
+ begin
+ { non-lazy classes are all classes that define a class method with the
+ selector called "load" (simply inheriting this class method is not enough,
+ they have to implement it themselves)
+
+ -- TODO: this currently only works if the Pascal identifier is also 'load'! }
+ result:=tfpobjectlist.create(false);
+ for i:=0 to classes.count-1 do
+ begin
+ symentry:=tsym(tobjectsymtable(tobjectdef(classes[i]).symtable).find('LOAD'));
+ if assigned(symentry) and
+ (symentry.typ=procsym) then
+ begin
+ for j:=0 to tprocsym(symentry).ProcdefList.count do
+ begin
+ procdef:=tprocdef(tprocsym(symentry).ProcdefList[0]);
+ if ((po_classmethod in procdef.procoptions) and
+ (procdef.messageinf.str^='load')) then
+ begin
+ result.add(classes[i]);
+ break;
+ end;
+ end;
+ end;
+ end;
+ end;
+
+ var
+ nonlazyclasses,
+ nonlazycategories : tfpobjectlist;
+ begin
+ if (classdefs.count=0) and
+ (catdefs.count=0) then
+ exit;
+
+ nonlazyclasses:=collectnonlazyclasses(classdefs);
+ nonlazycategories:=collectnonlazyclasses(catdefs);
+
+ { this list has to include all classes, also the non-lazy ones }
+ addclasslist(list,sec_objc_classlist,target_asm.labelprefix+'_OBJC_LABEL_CLASS_$',classdefs);
+ addclasslist(list,sec_objc_nlclasslist,target_asm.labelprefix+'_OBJC_LABEL_NONLAZY_CLASS_$',nonlazyclasses);
+ { category and non-lazy category lists }
+ addclasslist(list,sec_objc_catlist,target_asm.labelprefix+'_OBJC_LABEL_CATEGORY_$',catdefs);
+ addclasslist(list,sec_objc_nlcatlist,target_asm.labelprefix+'_OBJC_LABEL_NONLAZY_CATEGORY_$',nonlazycategories);
+
+ nonlazyclasses.free;
+ nonlazycategories.free;
+ { the non-fragile abi doesn't have any module info, nor lazy references
+ to used classes or to parent classes }
+ end;
+
+
+constructor tobjcrttiwriter_nonfragile.create;
+ begin
+ inherited create(oa_nonfragile);
+ end;
+
+
+{******************************************************************
+ RTTI generation -- Main function
+*******************************************************************}
+
+procedure MaybeGenerateObjectiveCImageInfo(globalst, localst: tsymtable);
+ var
+ objcrttiwriter: tobjcrttiwriter;
+ begin
+ if (m_objectivec1 in current_settings.modeswitches) then
+ begin
+ { first 4 bytes contain version information about this section (currently version 0),
+ next 4 bytes contain flags (currently only regarding whether the code in the object
+ file supports or requires garbage collection)
+ }
+ new_section(current_asmdata.asmlists[al_objc_data],sec_objc_image_info,'_OBJC_IMAGE_INFO',sizeof(pint));
+ current_asmdata.asmlists[al_objc_data].concat(Tai_symbol.Createname(target_asm.labelprefix+'_OBJC_IMAGE_INFO',AT_LABEL,sizeof(pint)));
+ current_asmdata.asmlists[al_objc_data].concat(Tai_const.Create_64bit(0));
+
+ { generate rtti for all obj-c classes, protocols and categories
+ defined in this module. }
+ if not(target_info.system in systems_objc_nfabi) then
+ objcrttiwriter:=tobjcrttiwriter_fragile.create
+ else
+ objcrttiwriter:=tobjcrttiwriter_nonfragile.create;
+ objcrttiwriter.gen_objc_rtti_sections(current_asmdata.asmlists[al_objc_data],globalst);
+ objcrttiwriter.gen_objc_rtti_sections(current_asmdata.asmlists[al_objc_data],localst);
+ objcrttiwriter.gen_objc_info_sections(current_asmdata.asmlists[al_objc_data]);
+ objcrttiwriter.free;
+ end;
+ end;
+
+
+end.
diff --git a/closures/compiler/objcutil.pas b/closures/compiler/objcutil.pas
new file mode 100644
index 0000000000..23b1bfafd6
--- /dev/null
+++ b/closures/compiler/objcutil.pas
@@ -0,0 +1,291 @@
+{
+ Copyright (c) 2009-2010 by Jonas Maebe
+
+ This unit implements some Objective-C helper routines at the node tree
+ level.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+
+{$i fpcdefs.inc}
+
+unit objcutil;
+
+interface
+
+ uses
+ node,
+ symtype,symdef;
+
+ { Check whether a string contains a syntactically valid selector name. }
+ function objcvalidselectorname(value_str: pchar; len: longint): boolean;
+
+ { Generate a node loading the superclass structure necessary to call
+ an inherited Objective-C method. }
+ function objcsuperclassnode(def: tdef): tnode;
+
+ { Encode a method's parameters and result type into the format used by the
+ run time (for generating protocol and class rtti). }
+ function objcencodemethod(pd: tprocdef): ansistring;
+
+ { Exports all assembler symbols related to the obj-c class }
+ procedure exportobjcclass(def: tobjectdef);
+
+implementation
+
+ uses
+ globtype,
+ cutils,cclasses,
+ pass_1,
+ verbose,systems,
+ symtable,symconst,symsym,
+ objcdef,
+ defutil,paramgr,
+ nbas,nmem,ncal,nld,ncon,ncnv,
+ export;
+
+
+{******************************************************************
+ validselectorname
+*******************************************************************}
+
+function objcvalidselectorname(value_str: pchar; len: longint): boolean;
+ var
+ i : longint;
+ gotcolon : boolean;
+begin
+ result:=false;
+ { empty name is not allowed }
+ if (len=0) then
+ exit;
+
+ gotcolon:=false;
+
+ { if the first character is a colon, all of them must be colons }
+ if (value_str[0] = ':') then
+ begin
+ for i:=1 to len-1 do
+ if (value_str[i]<>':') then
+ exit;
+ end
+ else
+ begin
+ { no special characters other than ':'
+ }
+ for i:=0 to len-1 do
+ if (value_str[i] = ':') then
+ gotcolon:=true
+ else if not(value_str[i] in ['_','A'..'Z','a'..'z','0'..'9',':']) then
+ exit;
+
+ { if there is at least one colon, the final character must
+ also be a colon (in case it's only one character that is
+ a colon, this was already checked before the above loop)
+ }
+ if gotcolon and
+ (value_str[len-1] <> ':') then
+ exit;
+ end;
+
+ result:=true;
+end;
+
+{******************************************************************
+ objcsuperclassnode
+*******************************************************************}
+
+ function objcloadbasefield(n: tnode; const fieldname: string): tnode;
+ var
+ vs : tsym;
+ begin
+ result:=cderefnode.create(ctypeconvnode.create_internal(n,objc_idtype));
+ vs:=tsym(tabstractrecorddef(objc_objecttype).symtable.Find(fieldname));
+ if not assigned(vs) or
+ (vs.typ<>fieldvarsym) then
+ internalerror(200911301);
+ result:=csubscriptnode.create(vs,result);
+ end;
+
+
+ function objcsuperclassnode(def: tdef): tnode;
+ var
+ para : tcallparanode;
+ begin
+ { only valid for Objective-C classes and classrefs }
+ if not is_objcclass(def) and
+ not is_objcclassref(def) then
+ internalerror(2009090901);
+ { Can be done a lot more efficiently with direct symbol accesses, but
+ requires extra node types. Maybe later. }
+ if is_objcclassref(def) then
+ begin
+ if (oo_is_classhelper in tobjectdef(tclassrefdef(def).pointeddef).objectoptions) then
+ begin
+ { in case we are in a category method, we need the metaclass of the
+ superclass class extended by this category (= metaclass of superclass of superclass)
+ for the fragile abi, and the metaclass of the superclass for the non-fragile ABI }
+{$if defined(onlymacosx10_6) or defined(arm) }
+ { NOTE: those send2 methods are only available on Mac OS X 10.6 and later!
+ (but also on all iPhone SDK revisions we support) }
+ if (target_info.system in systems_objc_nfabi) then
+ result:=cloadvmtaddrnode.create(ctypenode.create(tobjectdef(tclassrefdef(def).pointeddef).childof))
+ else
+{$endif onlymacosx10_6 or arm}
+ result:=cloadvmtaddrnode.create(ctypenode.create(tobjectdef(tclassrefdef(def).pointeddef).childof.childof));
+ result:=objcloadbasefield(result,'ISA');
+ typecheckpass(result);
+ { we're done }
+ exit;
+ end
+ else
+ begin
+ { otherwise we need the superclass of the metaclass }
+ para:=ccallparanode.create(cstringconstnode.createstr(tobjectdef(tclassrefdef(def).pointeddef).objextname^),nil);
+ result:=ccallnode.createinternfromunit('OBJC','OBJC_GETMETACLASS',para);
+ end
+ end
+ else
+ begin
+ if not(oo_is_classhelper in tobjectdef(def).objectoptions) then
+ result:=cloadvmtaddrnode.create(ctypenode.create(def))
+ else
+ result:=cloadvmtaddrnode.create(ctypenode.create(tobjectdef(def).childof))
+ end;
+
+{$if defined(onlymacosx10_6) or defined(arm) }
+ { For the non-fragile ABI, the superclass send2 method itself loads the
+ superclass. For the fragile ABI, we have to do this ourselves.
+
+ NOTE: those send2 methods are only available on Mac OS X 10.6 and later!
+ (but also on all iPhone SDK revisions we support) }
+ if not(target_info.system in systems_objc_nfabi) then
+{$endif onlymacosx10_6 or arm}
+ result:=objcloadbasefield(result,'SUPERCLASS');
+ typecheckpass(result);
+ end;
+
+
+{******************************************************************
+ Type encoding
+*******************************************************************}
+
+ function objcparasize(vs: tparavarsym): ptrint;
+ begin
+ result:=vs.paraloc[callerside].intsize;
+ { In Objective-C, all ordinal types are widened to at least the
+ size of the C "int" type. Assume __LP64__/4 byte ints for now. }
+ if is_ordinal(vs.vardef) and
+ (result<4) then
+ result:=4;
+ end;
+
+
+ function objcencodemethod(pd: tprocdef): ansistring;
+ var
+ parasize,
+ totalsize: aint;
+ vs: tparavarsym;
+ i: longint;
+ temp: ansistring;
+ founderror: tdef;
+ begin
+ result:='';
+ totalsize:=0;
+ pd.init_paraloc_info(callerside);
+{$if defined(powerpc) and defined(dummy)}
+ { Disabled, because neither Clang nor gcc does this, and the ObjC
+ runtime contains an explicit fix to detect this error. }
+
+ { On ppc, the callee is responsible for removing the hidden function
+ result parameter from the stack, so it has to know. On i386, it's
+ the caller that does this. }
+ if (pd.returndef<>voidtype) and
+ paramgr.ret_in_param(pd.returndef,pocall_cdecl) then
+ inc(totalsize,sizeof(pint));
+{$endif}
+ for i:=0 to pd.paras.count-1 do
+ begin
+ vs:=tparavarsym(pd.paras[i]);
+ if (vo_is_funcret in vs.varoptions) then
+ continue;
+ { objcaddencodedtype always assumes a value parameter, so add
+ a pointer indirection for var/out parameters. }
+ if not paramanager.push_addr_param(vs_value,vs.vardef,pocall_cdecl) and
+ (vs.varspez in [vs_var,vs_out,vs_constref]) then
+ result:=result+'^';
+ { Add the parameter type. }
+ if not objcaddencodedtype(vs.vardef,ris_initial,false,result,founderror) then
+ { should be checked earlier on }
+ internalerror(2009081701);
+ { And the total size of the parameters coming before this one
+ (i.e., the "offset" of this parameter). }
+ result:=result+tostr(totalsize);
+ { Update the total parameter size }
+ parasize:=objcparasize(vs);
+ inc(totalsize,parasize);
+ end;
+ { Prepend the total parameter size. }
+ result:=tostr(totalsize)+result;
+ { And the type of the function result (void in case of a procedure). }
+ temp:='';
+ if not objcaddencodedtype(pd.returndef,ris_initial,false,temp,founderror) then
+ internalerror(2009081801);
+ result:=temp+result;
+ end;
+
+
+{******************************************************************
+ ObjC class exporting
+*******************************************************************}
+
+ procedure exportobjcclassfields(objccls: tobjectdef);
+ var
+ i: longint;
+ vf: tfieldvarsym;
+ prefix: string;
+ begin
+ prefix:=target_info.cprefix+'OBJC_IVAR_$_'+objccls.objextname^+'.';
+ for i:=0 to objccls.symtable.SymList.Count-1 do
+ if tsym(objccls.symtable.SymList[i]).typ=fieldvarsym then
+ begin
+ vf:=tfieldvarsym(objccls.symtable.SymList[i]);
+ { TODO: package visibility (private_extern) -- must not be exported
+ either}
+ if not(vf.visibility in [vis_private,vis_strictprivate]) then
+ exportname(prefix+vf.RealName,0);
+ end;
+ end;
+
+
+ procedure exportobjcclass(def: tobjectdef);
+ begin
+ if (target_info.system in systems_objc_nfabi) then
+ begin
+ { export class and metaclass symbols }
+ exportname(def.rtti_mangledname(objcclassrtti),0);
+ exportname(def.rtti_mangledname(objcmetartti),0);
+ { export public/protected instance variable offset symbols }
+ exportobjcclassfields(def);
+ end
+ else
+ begin
+ { export the class symbol }
+ exportname('.objc_class_name_'+def.objextname^,0);
+ end;
+ end;
+
+end.
diff --git a/closures/compiler/ogbase.pas b/closures/compiler/ogbase.pas
new file mode 100644
index 0000000000..2c4417b059
--- /dev/null
+++ b/closures/compiler/ogbase.pas
@@ -0,0 +1,2862 @@
+{
+ Copyright (c) 1998-2006 by Peter Vreman
+
+ Contains the base stuff for binary object file writers
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit ogbase;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ { common }
+ cutils,
+ cclasses,
+ { targets }
+ systems,globtype,
+ { outputwriters }
+ owbase,
+ { assembler }
+ aasmbase;
+
+ type
+ TObjSection = class;
+ TObjData = class;
+
+ TExeSection = class;
+ TExeSymbol = class;
+
+ TObjRelocationType = (
+ { Relocation to absolute address }
+ RELOC_ABSOLUTE,
+{$ifdef x86_64}
+ { 32bit Relocation to absolute address }
+ RELOC_ABSOLUTE32,
+ { 64 bit coff only }
+ RELOC_RELATIVE_1,
+ RELOC_RELATIVE_2,
+ RELOC_RELATIVE_3,
+ RELOC_RELATIVE_4,
+ RELOC_RELATIVE_5,
+ { PIC }
+ RELOC_GOTPCREL,
+ RELOC_PLT32,
+{$endif x86_64}
+{$ifdef i386}
+ { PIC }
+ RELOC_GOTPC,
+ RELOC_GOT32,
+ RELOC_PLT32,
+{$endif i386}
+{$ifdef arm}
+ RELOC_RELATIVE_24,
+{$endif arm}
+ { Relative relocation }
+ RELOC_RELATIVE,
+ { PECoff (Windows) RVA relocation }
+ RELOC_RVA,
+ { PECoff (Windows) section relocation, required by DWARF2 debug info }
+ RELOC_SECREL32,
+ { Generate a 0 value at the place of the relocation,
+ this is used to remove unused vtable entries }
+ RELOC_ZERO,
+ { No relocation is needed. It is used in ARM object files.
+ Also internal linker use this reloc to make virtual (not real)
+ links to some sections }
+ RELOC_NONE,
+ { Darwin relocation, using PAIR }
+ RELOC_PIC_PAIR
+ );
+
+{$ifndef x86_64}
+ const
+ RELOC_ABSOLUTE32 = RELOC_ABSOLUTE;
+{$endif x86_64}
+
+ const
+ { stab types }
+ N_GSYM = $20;
+ N_STSYM = 38; { initialized const }
+ N_LCSYM = 40; { non initialized variable}
+ N_Function = $24; { function or const }
+ N_TextLine = $44;
+ N_DataLine = $46;
+ N_BssLine = $48;
+ N_RSYM = $40; { register variable }
+ N_LSYM = $80;
+ N_tsym = 160;
+ N_SourceFile = $64;
+ N_IncludeFile = $84;
+ N_BINCL = $82;
+ N_EINCL = $A2;
+ N_LBRAC = $C0;
+ N_EXCL = $C2;
+ N_RBRAC = $E0;
+
+ { GNU extensions }
+ debuglinkname='.gnu_debuglink';
+
+ type
+ TObjSectionOption = (
+ { Has Data available in the file }
+ oso_Data,
+ { Is loaded into memory }
+ oso_load,
+ { Not loaded into memory }
+ oso_noload,
+ { Read only }
+ oso_readonly,
+ { Read/Write }
+ oso_write,
+ { Contains executable instructions }
+ oso_executable,
+ { Never discard section }
+ oso_keep,
+ { Special common symbols }
+ oso_common,
+ { Contains debug info and can be stripped }
+ oso_debug,
+ { Contains only strings }
+ oso_strings
+ );
+
+ TObjSectionOptions = set of TObjSectionOption;
+
+ TObjSymbol = class(TFPHashObject)
+ public
+ bind : TAsmsymbind;
+ typ : TAsmsymtype;
+ { Current assemble pass, used to detect duplicate labels }
+ pass : byte;
+ objsection : TObjSection;
+ symidx : longint;
+ offset,
+ size : aword;
+ { Used for external and common solving during linking }
+ exesymbol : TExeSymbol;
+
+ { Darwin asm is using indirect symbols resolving }
+ indsymbol : TObjSymbol;
+
+ constructor create(AList:TFPHashObjectList;const AName:string);
+ function address:aword;
+ procedure SetAddress(apass:byte;aobjsec:TObjSection;abind:TAsmsymbind;atyp:Tasmsymtype);
+ end;
+
+ { Stabs is common for all targets }
+ TObjStabEntry=packed record
+ strpos : longint;
+ ntype : byte;
+ nother : byte;
+ ndesc : word;
+ nvalue : longint;
+ end;
+ PObjStabEntry=^TObjStabEntry;
+
+ TObjRelocation = class
+ DataOffset,
+ orgsize : aword; { original size of the symbol to Relocate, required for COFF }
+ symbol : TObjSymbol;
+ objsection : TObjSection; { only used if symbol=nil }
+ typ : TObjRelocationType;
+ constructor CreateSymbol(ADataOffset:aword;s:TObjSymbol;Atyp:TObjRelocationType);
+ constructor CreateSymbolSize(ADataOffset:aword;s:TObjSymbol;Aorgsize:aword;Atyp:TObjRelocationType);
+ constructor CreateSection(ADataOffset:aword;aobjsec:TObjSection;Atyp:TObjRelocationType);
+ end;
+
+ TObjSection = class(TFPHashObject)
+ private
+ FData : TDynamicArray;
+ FSecOptions : TObjSectionOptions;
+ FCachedFullName : pshortstring;
+ procedure SetSecOptions(Aoptions:TObjSectionOptions);
+ public
+ ObjData : TObjData;
+ SecSymIdx : longint; { index for the section in symtab }
+ SecAlign : shortint; { alignment of the section }
+ { section Data }
+ Size,
+ DataPos,
+ MemPos : aword;
+ DataAlignBytes : shortint;
+ { Relocations (=references) to other sections }
+ ObjRelocations : TFPObjectList;
+ { Symbols this defines }
+ ObjSymbolDefines : TFPObjectList;
+ { executable linking }
+ ExeSection : TExeSection;
+ USed : Boolean;
+ VTRefList : TFPObjectList;
+ constructor create(AList:TFPHashObjectList;const Aname:string;Aalign:shortint;Aoptions:TObjSectionOptions);virtual;
+ destructor destroy;override;
+ function write(const d;l:aword):aword;
+ function writestr(const s:string):aword;
+ function WriteZeros(l:longword):aword;
+ function setmempos(mpos:qword):qword;
+ procedure setDatapos(var dpos:aword);
+ procedure alloc(l:aword);
+ procedure addsymReloc(ofs:aword;p:TObjSymbol;Reloctype:TObjRelocationType);
+ procedure addsectionReloc(ofs:aword;aobjsec:TObjSection;Reloctype:TObjRelocationType);
+ procedure AddSymbolDefine(p:TObjSymbol);
+ procedure FixupRelocs;virtual;
+ procedure ReleaseData;
+ function FullName:string;
+ property Data:TDynamicArray read FData;
+ property SecOptions:TObjSectionOptions read FSecOptions write SetSecOptions;
+ end;
+ TObjSectionClass = class of TObjSection;
+
+ TString80 = string[80];
+
+ TObjData = class(TLinkedListItem)
+ private
+ FName : TString80;
+ FCurrObjSec : TObjSection;
+ FObjSectionList : TFPHashObjectList;
+ FCObjSection : TObjSectionClass;
+ { Symbols that will be defined in this object file }
+ FObjSymbolList : TFPHashObjectList;
+ FCachedAsmSymbolList : TFPObjectList;
+ { Special info sections that are written to during object generation }
+ FStabsObjSec,
+ FStabStrObjSec : TObjSection;
+ procedure section_reset(p:TObject;arg:pointer);
+ procedure section_afteralloc(p:TObject;arg:pointer);
+ procedure section_afterwrite(p:TObject;arg:pointer);
+ protected
+ property CObjSection:TObjSectionClass read FCObjSection write FCObjSection;
+ public
+ CurrPass : byte;
+ ImageBase : aword;
+ constructor create(const n:string);virtual;
+ destructor destroy;override;
+ { Sections }
+ function sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;virtual;
+ function sectiontype2options(atype:TAsmSectiontype):TObjSectionOptions;virtual;
+ function sectiontype2align(atype:TAsmSectiontype):shortint;virtual;
+ function createsection(atype:TAsmSectionType;const aname:string='';aorder:TAsmSectionOrder=secorder_default):TObjSection;
+ function createsection(const aname:string;aalign:shortint;aoptions:TObjSectionOptions;DiscardDuplicate:boolean=true):TObjSection;virtual;
+ procedure CreateDebugSections;virtual;
+ function findsection(const aname:string):TObjSection;
+ procedure setsection(asec:TObjSection);
+ { Symbols }
+ function createsymbol(const aname:string):TObjSymbol;
+ function symboldefine(asmsym:TAsmSymbol):TObjSymbol;
+ function symboldefine(const aname:string;abind:TAsmsymbind;atyp:Tasmsymtype):TObjSymbol;
+ function symbolref(asmsym:TAsmSymbol):TObjSymbol;
+ function symbolref(const aname:string):TObjSymbol;
+ procedure ResetCachedAsmSymbols;
+ { Allocation }
+ procedure alloc(len:aword);
+ procedure allocalign(len:shortint);
+ procedure writebytes(const Data;len:aword);
+ procedure writeReloc(Data:aint;len:aword;p:TObjSymbol;Reloctype:TObjRelocationType);virtual;abstract;
+ procedure beforealloc;virtual;
+ procedure beforewrite;virtual;
+ procedure afteralloc;virtual;
+ procedure afterwrite;virtual;
+ procedure resetsections;
+ property Name:TString80 read FName;
+ property CurrObjSec:TObjSection read FCurrObjSec;
+ property ObjSymbolList:TFPHashObjectList read FObjSymbolList;
+ property ObjSectionList:TFPHashObjectList read FObjSectionList;
+ property StabsSec:TObjSection read FStabsObjSec write FStabsObjSec;
+ property StabStrSec:TObjSection read FStabStrObjSec write FStabStrObjSec;
+ end;
+ TObjDataClass = class of TObjData;
+
+ TObjOutput = class
+ private
+ FCObjData : TObjDataClass;
+ protected
+ { writer }
+ FWriter : TObjectwriter;
+ function writeData(Data:TObjData):boolean;virtual;abstract;
+ property CObjData : TObjDataClass read FCObjData write FCObjData;
+ public
+ constructor create(AWriter:TObjectWriter);virtual;
+ destructor destroy;override;
+ function newObjData(const n:string):TObjData;
+ function startObjectfile(const fn:string):boolean;
+ function writeobjectfile(Data:TObjData):boolean;
+ procedure exportsymbol(p:TObjSymbol);
+ property Writer:TObjectWriter read FWriter;
+ end;
+ TObjOutputClass=class of TObjOutput;
+
+ TObjInput = class
+ private
+ FCObjData : TObjDataClass;
+ protected
+ { reader }
+ FReader : TObjectReader;
+ InputFileName : string;
+ property CObjData : TObjDataClass read FCObjData write FCObjData;
+ public
+ constructor create;virtual;
+ destructor destroy;override;
+ function newObjData(const n:string):TObjData;
+ function ReadObjData(AReader:TObjectreader;Data:TObjData):boolean;virtual;abstract;
+ procedure inputerror(const s : string);
+ end;
+ TObjInputClass=class of TObjInput;
+
+ TVTableEntry=record
+ ObjRelocation : TObjRelocation;
+ orgreloctype : TObjRelocationType;
+ Enabled,
+ Used : Boolean;
+ end;
+ PVTableEntry=^TVTableEntry;
+
+ TExeVTable = class
+ private
+ procedure CheckIdx(VTableIdx:longint);
+ public
+ ExeSymbol : TExeSymbol;
+ EntryCnt : Longint;
+ EntryArray : PVTableEntry;
+ Consolidated : Boolean;
+ ChildList : TFPObjectList;
+ constructor Create(AExeSymbol:TExeSymbol);
+ destructor Destroy;override;
+ procedure AddChild(vt:TExeVTable);
+ procedure AddEntry(VTableIdx:Longint);
+ procedure SetVTableSize(ASize:longint);
+ function VTableRef(VTableIdx:Longint):TObjRelocation;
+ end;
+
+ TSymbolState = (symstate_undefined,symstate_defined,symstate_common);
+
+ TExeSymbol = class(TFPHashObject)
+ ObjSymbol : TObjSymbol;
+ ExeSection : TExeSection;
+ State : TSymbolState;
+ { Used for vmt references optimization }
+ VTable : TExeVTable;
+ end;
+
+ TExeSection = class(TFPHashObject)
+ private
+ FSecSymIdx : longint;
+ FObjSectionList : TFPObjectList;
+ public
+ Size,
+ DataPos,
+ MemPos : aword;
+ SecAlign : shortint;
+ SecOptions : TObjSectionOptions;
+ constructor create(AList:TFPHashObjectList;const AName:string);virtual;
+ destructor destroy;override;
+ procedure AddObjSection(objsec:TObjSection);
+ property ObjSectionList:TFPObjectList read FObjSectionList;
+ property SecSymIdx:longint read FSecSymIdx write FSecSymIdx;
+ end;
+ TExeSectionClass=class of TExeSection;
+
+ TStaticLibrary = class(TFPHashObject)
+ private
+ FArReader : TObjectReader;
+ FObjInputClass : TObjInputClass;
+ public
+ constructor create(AList:TFPHashObjectList;const AName:string;AReader:TObjectReader;AObjInputClass:TObjInputClass);
+ destructor destroy;override;
+ property ArReader:TObjectReader read FArReader;
+ property ObjInputClass:TObjInputClass read FObjInputClass;
+ end;
+
+ TImportLibrary = class(TFPHashObject)
+ private
+ FImportSymbolList : TFPHashObjectList;
+ public
+ constructor create(AList:TFPHashObjectList;const AName:string);
+ destructor destroy;override;
+ property ImportSymbolList:TFPHashObjectList read FImportSymbolList;
+ end;
+
+ TImportSymbol = class(TFPHashObject)
+ private
+ FOrdNr : longint;
+ FIsVar : boolean;
+ FMangledName : string;
+ public
+ constructor create(AList:TFPHashObjectList;const AName,AMangledName:string;AOrdNr:longint;AIsVar:boolean);
+ property OrdNr: longint read FOrdNr;
+ property MangledName: string read FMangledName;
+ property IsVar: boolean read FIsVar;
+ end;
+
+ TExeWriteMode = (ewm_exefull,ewm_dbgonly,ewm_exeonly);
+
+ TExeOutput = class
+ private
+ { ExeSectionList }
+ FCObjData : TObjDataClass;
+ FCExeSection : TExeSectionClass;
+ FCurrExeSec : TExeSection;
+ FExeSectionList : TFPHashObjectList;
+ Fzeronr : longint;
+ Fvaluesnr : longint;
+ { Symbols }
+ FExeSymbolList : TFPHashObjectList;
+ FUnresolvedExeSymbols : TFPObjectList;
+ FExternalObjSymbols,
+ FCommonObjSymbols : TFPObjectList;
+ FEntryName : string;
+ FExeVTableList : TFPObjectList;
+ { Objects }
+ FObjDataList : TFPObjectList;
+ { Position calculation }
+ FImageBase : aword;
+ FCurrMemPos : qword;
+ procedure SetCurrMemPos(const AValue: qword);
+ protected
+ { writer }
+ FExeWriteMode : TExeWriteMode;
+ FWriter : TObjectwriter;
+ commonObjSection : TObjSection;
+ internalObjData : TObjData;
+ EntrySym : TObjSymbol;
+ SectionDataAlign,
+ SectionMemAlign : aword;
+ function writeData:boolean;virtual;abstract;
+ property CExeSection:TExeSectionClass read FCExeSection write FCExeSection;
+ property CObjData:TObjDataClass read FCObjData write FCObjData;
+ procedure Order_ObjSectionList(ObjSectionList : TFPObjectList; const aPattern:string);virtual;
+ public
+ CurrDataPos : aword;
+ MaxMemPos : qword;
+ IsSharedLibrary : boolean;
+ constructor create;virtual;
+ destructor destroy;override;
+ function FindExeSection(const aname:string):TExeSection;
+ procedure AddObjData(ObjData:TObjData);
+ procedure Load_Start;virtual;
+ procedure Load_EntryName(const aname:string);virtual;
+ procedure Load_Symbol(const aname:string);virtual;
+ procedure Load_ProvideSymbol(const aname:string);virtual;
+ procedure Load_IsSharedLibrary;
+ procedure Load_ImageBase(const avalue:string);
+ procedure Order_Start;virtual;
+ procedure Order_End;virtual;
+ procedure Order_ExeSection(const aname:string);virtual;
+ procedure Order_Align(const avalue:string);virtual;
+ procedure Order_Zeros(const avalue:string);virtual;
+ procedure Order_Values(bytesize : aword; const avalue:string);virtual;
+ procedure Order_Symbol(const aname:string);virtual;
+ procedure Order_ProvideSymbol(const aname:string);virtual;
+ procedure Order_EndExeSection;virtual;
+ procedure Order_ObjSection(const aname:string);virtual;
+ procedure MemPos_Start;virtual;
+ procedure MemPos_Header;virtual;
+ procedure MemPos_ExeSection(const aname:string);virtual;
+ procedure MemPos_EndExeSection;virtual;
+ procedure DataPos_Start;virtual;
+ procedure DataPos_Header;virtual;
+ procedure DataPos_ExeSection(const aname:string);virtual;
+ procedure DataPos_EndExeSection;virtual;
+ procedure DataPos_Symbols;virtual;
+ procedure BuildVTableTree(VTInheritList,VTEntryList:TFPObjectList);
+ procedure PackUnresolvedExeSymbols(const s:string);
+ procedure ResolveSymbols(StaticLibraryList:TFPHashObjectList);
+ procedure PrintMemoryMap;
+ procedure FixupSymbols;
+ procedure FixupRelocations;
+ procedure MergeStabs;
+ procedure RemoveUnreferencedSections;
+ procedure RemoveEmptySections;
+ procedure RemoveDebugInfo;
+ procedure GenerateLibraryImports(ImportLibraryList:TFPHashObjectList);virtual;
+ procedure GenerateDebugLink(const dbgname:string;dbgcrc:cardinal);
+ function WriteExeFile(const fn:string):boolean;
+ procedure ParseScript (linkscript:TCmdStrList); virtual;
+ property Writer:TObjectWriter read FWriter;
+ property ExeSectionList:TFPHashObjectList read FExeSectionList;
+ property ObjDataList:TFPObjectList read FObjDataList;
+ property ExeSymbolList:TFPHashObjectList read FExeSymbolList;
+ property UnresolvedExeSymbols:TFPObjectList read FUnresolvedExeSymbols;
+ property ExternalObjSymbols:TFPObjectList read FExternalObjSymbols;
+ property CommonObjSymbols:TFPObjectList read FCommonObjSymbols;
+ property ExeVTableList:TFPObjectList read FExeVTableList;
+ property EntryName:string read FEntryName write FEntryName;
+ property ImageBase:aword read FImageBase write FImageBase;
+ property CurrExeSec:TExeSection read FCurrExeSec;
+ property ExeWriteMode:TExeWriteMode read FExeWriteMode write FExeWriteMode;
+ property CurrMemPos:qword read FCurrMemPos write SetCurrMemPos;
+ end;
+ TExeOutputClass=class of TExeOutput;
+
+ var
+ exeoutput : TExeOutput;
+
+
+implementation
+
+ uses
+ SysUtils,
+ globals,verbose,fmodule,ogmap;
+
+ const
+ SectionDataMaxGrow = 4096;
+
+{$ifdef MEMDEBUG}
+ var
+ memobjsymbols,
+ memobjsections : TMemDebug;
+{$endif MEMDEBUG}
+
+{*****************************************************************************
+ TObjSymbol
+*****************************************************************************}
+
+ constructor TObjSymbol.create(AList:TFPHashObjectList;const AName:string);
+ begin;
+ inherited create(AList,AName);
+ bind:=AB_EXTERNAL;
+ typ:=AT_NONE;
+ symidx:=-1;
+ size:=0;
+ offset:=0;
+ objsection:=nil;
+ end;
+
+
+ function TObjSymbol.address:aword;
+ begin
+ if assigned(objsection) then
+ result:=offset+objsection.mempos
+ else
+ result:=0;
+ end;
+
+
+ procedure TObjSymbol.SetAddress(apass:byte;aobjsec:TObjSection;abind:TAsmsymbind;atyp:Tasmsymtype);
+ begin
+ if not(abind in [AB_GLOBAL,AB_LOCAL,AB_COMMON,AB_IMPORT]) then
+ internalerror(200603016);
+ if not assigned(aobjsec) then
+ internalerror(200603017);
+ if (bind in [AB_EXTERNAL,AB_LAZY]) or
+ { Put all COMMON to GLOBAL in step 3 of
+ TExeOutput.ResolveSymbols }
+ ((abind=AB_GLOBAL) and (bind=AB_COMMON)) then
+ begin
+ { Do not change the AB_TYPE of common symbols yet }
+ { This will be done in FixupSymbols }
+ if (pass<>0) or (bind<>AB_COMMON) then
+ bind:=abind;
+ typ:=atyp;
+ end
+ else
+ begin
+ if pass=apass then
+ begin
+ Message1(asmw_e_duplicate_label,name);
+ exit;
+ end;
+ end;
+ pass:=apass;
+ { Code can never grow after a pass }
+ if assigned(objsection) and
+ (objsection=aobjsec) and
+ (aobjsec.size>offset) then
+ internalerror(200603014);
+ objsection:=aobjsec;
+ offset:=aobjsec.size;
+ end;
+
+{****************************************************************************
+ TObjRelocation
+****************************************************************************}
+
+ constructor TObjRelocation.CreateSymbol(ADataOffset:aword;s:TObjSymbol;Atyp:TObjRelocationType);
+ begin
+ if not assigned(s) then
+ internalerror(200603034);
+ DataOffset:=ADataOffset;
+ Symbol:=s;
+ OrgSize:=0;
+ ObjSection:=nil;
+ Typ:=Atyp;
+ end;
+
+
+ constructor TObjRelocation.CreateSymbolSize(ADataOffset:aword;s:TObjSymbol;Aorgsize:aword;Atyp:TObjRelocationType);
+ begin
+ if not assigned(s) then
+ internalerror(200603035);
+ DataOffset:=ADataOffset;
+ Symbol:=s;
+ OrgSize:=Aorgsize;
+ ObjSection:=nil;
+ Typ:=Atyp;
+ end;
+
+
+ constructor TObjRelocation.CreateSection(ADataOffset:aword;aobjsec:TObjSection;Atyp:TObjRelocationType);
+ begin
+ if not assigned(aobjsec) then
+ internalerror(200603036);
+ DataOffset:=ADataOffset;
+ Symbol:=nil;
+ OrgSize:=0;
+ ObjSection:=aobjsec;
+ Typ:=Atyp;
+ end;
+
+
+{****************************************************************************
+ TObjSection
+****************************************************************************}
+
+ constructor TObjSection.create(AList:TFPHashObjectList;const Aname:string;Aalign:shortint;Aoptions:TObjSectionOptions);
+ begin
+ inherited Create(AList,Aname);
+ { Data }
+ Size:=0;
+ Datapos:=0;
+ mempos:=0;
+ FData:=Nil;
+ { Setting the secoptions allocates Data if needed }
+ secoptions:=Aoptions;
+ secalign:=Aalign;
+ secsymidx:=0;
+ { relocation }
+ ObjRelocations:=TFPObjectList.Create(true);
+ ObjSymbolDefines:=TFPObjectList.Create(false);
+ VTRefList:=TFPObjectList.Create(false);
+ end;
+
+
+ destructor TObjSection.destroy;
+ begin
+ if assigned(Data) then
+ Data.Free;
+ stringdispose(FCachedFullName);
+ ObjRelocations.Free;
+ ObjSymbolDefines.Free;
+ VTRefList.Free;
+ inherited destroy;
+ end;
+
+
+ procedure TObjSection.SetSecOptions(Aoptions:TObjSectionOptions);
+ begin
+ FSecOptions:=FSecOptions+AOptions;
+ if (oso_Data in secoptions) and
+ not assigned(FData) then
+ FData:=TDynamicArray.Create(SectionDataMaxGrow);
+ end;
+
+
+ function TObjSection.write(const d;l:aword):aword;
+ begin
+ result:=size;
+ if assigned(Data) then
+ begin
+ if Size<>Data.size then
+ internalerror(200602281);
+ Data.write(d,l);
+ inc(Size,l);
+ end
+ else
+ internalerror(200602289);
+ end;
+
+
+ function TObjSection.writestr(const s:string):aword;
+ begin
+ result:=Write(s[1],length(s));
+ end;
+
+
+ function TObjSection.WriteZeros(l:longword):aword;
+ var
+ empty : array[0..1023] of byte;
+ begin
+ if l>sizeof(empty) then
+ internalerror(200404082);
+ if l>0 then
+ begin
+ fillchar(empty,l,0);
+ result:=Write(empty,l);
+ end
+ else
+ result:=Size;
+ end;
+
+
+ procedure TObjSection.setDatapos(var dpos:aword);
+ begin
+ if oso_Data in secoptions then
+ begin
+ { get aligned Datapos }
+ Datapos:=align(dpos,secalign);
+ Dataalignbytes:=Datapos-dpos;
+ { return updated Datapos }
+ dpos:=Datapos+size;
+ end
+ else
+ Datapos:=dpos;
+ end;
+
+
+ function TObjSection.setmempos(mpos:qword):qword;
+ begin
+ mempos:=align(mpos,secalign);
+ { return updated mempos }
+ result:=mempos+size;
+ end;
+
+
+ procedure TObjSection.alloc(l:aword);
+ begin
+ inc(size,l);
+ end;
+
+
+ procedure TObjSection.addsymReloc(ofs:aword;p:TObjSymbol;Reloctype:TObjRelocationType);
+ begin
+ ObjRelocations.Add(TObjRelocation.CreateSymbol(ofs,p,reloctype));
+ end;
+
+
+ procedure TObjSection.addsectionReloc(ofs:aword;aobjsec:TObjSection;Reloctype:TObjRelocationType);
+ begin
+ ObjRelocations.Add(TObjRelocation.CreateSection(ofs,aobjsec,reloctype));
+ end;
+
+
+ procedure TObjSection.AddSymbolDefine(p:TObjSymbol);
+ begin
+ if p.bind<>AB_GLOBAL then
+ exit;
+ ObjSymbolDefines.Add(p);
+ end;
+
+
+ procedure TObjSection.FixupRelocs;
+ begin
+ end;
+
+
+ procedure TObjSection.ReleaseData;
+ begin
+ if assigned(FData) then
+ begin
+ FData.free;
+ FData:=nil;
+ end;
+ ObjRelocations.free;
+ ObjRelocations:=nil;
+ ObjSymbolDefines.Free;
+ ObjSymbolDefines:=nil;
+ if assigned(FCachedFullName) then
+ begin
+ stringdispose(FCachedFullName);
+ FCachedFullName:=nil;
+ end;
+ end;
+
+
+ function TObjSection.FullName:string;
+ begin
+ if not assigned(FCachedFullName) then
+ begin
+ if assigned(ObjData) then
+ FCachedFullName:=stringdup(ObjData.Name+'('+Name+')')
+ else
+ FCachedFullName:=stringdup(Name);
+ end;
+ result:=FCachedFullName^;
+ end;
+
+
+{****************************************************************************
+ TObjData
+****************************************************************************}
+
+ constructor TObjData.create(const n:string);
+ begin
+ inherited create;
+ FName:=ExtractFileName(n);
+ FObjSectionList:=TFPHashObjectList.Create(true);
+ FStabsObjSec:=nil;
+ FStabStrObjSec:=nil;
+ { symbols }
+ FObjSymbolList:=TFPHashObjectList.Create(true);
+ FCachedAsmSymbolList:=TFPObjectList.Create(false);
+ { section class type for creating of new sections }
+ FCObjSection:=TObjSection;
+ end;
+
+
+ destructor TObjData.destroy;
+ begin
+ { Symbols }
+{$ifdef MEMDEBUG}
+ MemObjSymbols.Start;
+{$endif}
+ ResetCachedAsmSymbols;
+ FCachedAsmSymbolList.free;
+ FObjSymbolList.free;
+{$ifdef MEMDEBUG}
+ MemObjSymbols.Stop;
+{$endif}
+ { Sections }
+{$ifdef MEMDEBUG}
+ MemObjSections.Start;
+{$endif}
+ FObjSectionList.free;
+{$ifdef MEMDEBUG}
+ MemObjSections.Stop;
+{$endif}
+ inherited destroy;
+ end;
+
+
+ function TObjData.sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;
+ const
+ secnames : array[TAsmSectiontype] of string[length('__DATA, __datacoal_nt,coalesced')] = ('','',
+ 'code',
+ 'Data',
+ 'Data',
+ 'roData',
+ 'bss',
+ 'threadvar',
+ 'pdata',
+ 'stub',
+ 'data_nonlazy',
+ 'data_lazy',
+ 'init_func',
+ 'term_func',
+ 'stab','stabstr',
+ 'iData2','iData4','iData5','iData6','iData7','eData',
+ 'eh_frame',
+ 'debug_frame','debug_info','debug_line','debug_abbrev',
+ 'fpc',
+ 'toc',
+ 'init',
+ 'fini',
+ 'objc_class',
+ 'objc_meta_class',
+ 'objc_cat_cls_meth',
+ 'objc_cat_inst_meth',
+ 'objc_protocol',
+ 'objc_string_object',
+ 'objc_cls_meth',
+ 'objc_inst_meth',
+ 'objc_cls_refs',
+ 'objc_message_refs',
+ 'objc_symbols',
+ 'objc_category',
+ 'objc_class_vars',
+ 'objc_instance_vars',
+ 'objc_module_info',
+ 'objc_class_names',
+ 'objc_meth_var_types',
+ 'objc_meth_var_names',
+ 'objc_selector_strs',
+ 'objc_protocol_ext',
+ 'objc_class_ext',
+ 'objc_property',
+ 'objc_image_info',
+ 'objc_cstring_object',
+ 'objc_sel_fixup',
+ '__DATA,__objc_data',
+ '__DATA,__objc_const',
+ '.objc_superrefs',
+ '__DATA, __datacoal_nt,coalesced',
+ '.objc_classlist',
+ '.objc_nlclasslist',
+ '.objc_catlist',
+ '.obcj_nlcatlist',
+ '.objc_protolist'
+ );
+ var
+ sep : string[3];
+ begin
+ if aname<>'' then
+ begin
+ case aorder of
+ secorder_begin :
+ sep:='.b_';
+ secorder_end :
+ sep:='.z_';
+ else
+ sep:='.n_';
+ end;
+ result:=secnames[atype]+sep+aname
+ end
+ else
+ result:=secnames[atype];
+ end;
+
+
+ function TObjData.sectiontype2options(atype:TAsmSectiontype):TObjSectionOptions;
+ const
+ secoptions : array[TAsmSectiontype] of TObjSectionOptions = ([],
+ {user} [oso_Data,oso_load,oso_write,oso_keep],
+ {code} [oso_Data,oso_load,oso_readonly,oso_executable,oso_keep],
+ {Data} [oso_Data,oso_load,oso_write,oso_keep],
+{ TODO: Fix sec_rodata be read-only-with-relocs}
+ {roData} [oso_Data,oso_load,oso_write,oso_keep],
+{ TODO: Fix sec_rodata_norel be read-only/constant}
+ {roData_norel} [oso_Data,oso_load,oso_write,oso_keep],
+ {bss} [oso_load,oso_write,oso_keep],
+ {threadvar} [oso_load,oso_write
+{$ifdef FPC_USE_TLS_DIRECTORY}
+ ,oso_keep
+{$endif FPC_USE_TLS_DIRECTORY}
+ ],
+ {pdata} [oso_data,oso_load,oso_readonly {$ifndef x86_64},oso_keep{$endif}],
+ {stub} [oso_Data,oso_load,oso_readonly,oso_executable],
+ {data_nonlazy} [oso_Data,oso_load,oso_write],
+ {data_lazy} [oso_Data,oso_load,oso_write],
+ {init_func} [oso_Data,oso_load],
+ {term_func} [oso_Data,oso_load],
+ {stab} [oso_Data,oso_noload,oso_debug],
+ {stabstr} [oso_Data,oso_noload,oso_strings,oso_debug],
+ {iData2} [oso_Data,oso_load,oso_write],
+ {iData4} [oso_Data,oso_load,oso_write],
+ {iData5} [oso_Data,oso_load,oso_write],
+ {iData6} [oso_Data,oso_load,oso_write],
+ {iData7} [oso_Data,oso_load,oso_write],
+ {eData} [oso_Data,oso_load,oso_readonly],
+ {eh_frame} [oso_Data,oso_load,oso_readonly],
+ {debug_frame} [oso_Data,oso_noload,oso_debug],
+ {debug_info} [oso_Data,oso_noload,oso_debug],
+ {debug_line} [oso_Data,oso_noload,oso_debug],
+ {debug_abbrev} [oso_Data,oso_noload,oso_debug],
+ {fpc} [oso_Data,oso_load,oso_write,oso_keep],
+ {toc} [oso_Data,oso_load,oso_readonly],
+ {init} [oso_Data,oso_load,oso_readonly,oso_executable,oso_keep],
+ {fini} [oso_Data,oso_load,oso_readonly,oso_executable,oso_keep],
+ {objc_class} [oso_data,oso_load],
+ {objc_meta_class} [oso_data,oso_load],
+ {objc_cat_cls_meth} [oso_data,oso_load],
+ {objc_cat_inst_meth} [oso_data,oso_load],
+ {objc_protocol} [oso_data,oso_load],
+ {objc_string_object} [oso_data,oso_load],
+ {objc_cls_meth} [oso_data,oso_load],
+ {objc_inst_meth} [oso_data,oso_load],
+ {objc_cls_refs} [oso_data,oso_load],
+ {objc_message_refs} [oso_data,oso_load],
+ {objc_symbols} [oso_data,oso_load],
+ {objc_category} [oso_data,oso_load],
+ {objc_class_vars} [oso_data,oso_load],
+ {objc_instance_vars} [oso_data,oso_load],
+ {objc_module_info} [oso_data,oso_load],
+ {objc_class_names} [oso_data,oso_load],
+ {objc_meth_var_types} [oso_data,oso_load],
+ {objc_meth_var_names} [oso_data,oso_load],
+ {objc_selector_strs} [oso_data,oso_load],
+ {objc_protocol_ext} [oso_data,oso_load],
+ {objc_class_ext} [oso_data,oso_load],
+ {objc_property} [oso_data,oso_load],
+ {objc_image_info} [oso_data,oso_load],
+ {objc_cstring_object} [oso_data,oso_load],
+ {objc_sel_fixup} [oso_data,oso_load],
+ {sec_objc_data} [oso_data,oso_load],
+ {sec_objc_const} [oso_data,oso_load],
+ {sec_objc_sup_refs} [oso_data,oso_load],
+ {sec_data_coalesced} [oso_data,oso_load],
+ {sec_objc_classlist} [oso_data,oso_load],
+ {sec_objc_nlclasslist} [oso_data,oso_load],
+ {sec_objc_catlist} [oso_data,oso_load],
+ {sec_objc_nlcatlist} [oso_data,oso_load],
+ {sec_objc_protolist'} [oso_data,oso_load]
+ );
+ begin
+ result:=secoptions[atype];
+ end;
+
+
+ function TObjData.sectiontype2align(atype:TAsmSectiontype):shortint;
+ begin
+ case atype of
+ sec_stabstr,sec_debug_info,sec_debug_line,sec_debug_abbrev:
+ result:=1;
+ sec_code,
+ sec_bss,
+ sec_data:
+ result:=16;
+ { For idata (at least idata2) it must be 4 bytes, because
+ an entry is always (also in win64) 20 bytes and aligning
+ on 8 bytes will insert 4 bytes between the entries resulting
+ in a corrupt idata section.
+ Same story with .pdata, it has 4-byte elements which should
+ be packed without gaps. }
+ sec_idata2,sec_idata4,sec_idata5,sec_idata6,sec_idata7,sec_pdata:
+ result:=4;
+ else
+ result:=sizeof(pint);
+ end;
+ end;
+
+
+ function TObjData.createsection(atype:TAsmSectionType;const aname:string;aorder:TAsmSectionOrder):TObjSection;
+ begin
+ result:=createsection(sectionname(atype,aname,aorder),sectiontype2align(atype),sectiontype2options(atype));
+ end;
+
+
+ function TObjData.createsection(const aname:string;aalign:shortint;aoptions:TObjSectionOptions;DiscardDuplicate:boolean):TObjSection;
+ begin
+ if DiscardDuplicate then
+ result:=TObjSection(FObjSectionList.Find(aname))
+ else
+ result:=nil;
+ if not assigned(result) then
+ begin
+ result:=CObjSection.create(FObjSectionList,aname,aalign,aoptions);
+ result.ObjData:=self;
+ end;
+ FCurrObjSec:=result;
+ end;
+
+
+ procedure TObjData.CreateDebugSections;
+ begin
+ end;
+
+
+ function TObjData.FindSection(const aname:string):TObjSection;
+ begin
+ result:=TObjSection(FObjSectionList.Find(aname));
+ end;
+
+
+ procedure TObjData.setsection(asec:TObjSection);
+ begin
+ if asec.ObjData<>self then
+ internalerror(200403041);
+ FCurrObjSec:=asec;
+ end;
+
+
+ function TObjData.createsymbol(const aname:string):TObjSymbol;
+ begin
+ result:=TObjSymbol(FObjSymbolList.Find(aname));
+ if not assigned(result) then
+ result:=TObjSymbol.Create(FObjSymbolList,aname);
+ end;
+
+
+ function TObjData.symboldefine(asmsym:TAsmSymbol):TObjSymbol;
+ begin
+ if assigned(asmsym) then
+ begin
+ if not assigned(asmsym.cachedObjSymbol) then
+ begin
+ result:=symboldefine(asmsym.name,asmsym.bind,asmsym.typ);
+ asmsym.cachedObjSymbol:=result;
+ FCachedAsmSymbolList.add(asmsym);
+ end
+ else
+ begin
+ result:=TObjSymbol(asmsym.cachedObjSymbol);
+ result.SetAddress(CurrPass,CurrObjSec,asmsym.bind,asmsym.typ);
+ { Register also in TObjSection }
+ CurrObjSec.AddSymbolDefine(result);
+ end;
+ end
+ else
+ result:=nil;
+ end;
+
+
+ function TObjData.symboldefine(const aname:string;abind:TAsmsymbind;atyp:Tasmsymtype):TObjSymbol;
+ begin
+ if not assigned(CurrObjSec) then
+ internalerror(200603051);
+ result:=CreateSymbol(aname);
+ { Register also in TObjSection }
+ CurrObjSec.AddSymbolDefine(result);
+ result.SetAddress(CurrPass,CurrObjSec,abind,atyp);
+ end;
+
+
+ function TObjData.symbolref(asmsym:TAsmSymbol):TObjSymbol;
+ begin
+ if assigned(asmsym) then
+ begin
+ if not assigned(asmsym.cachedObjSymbol) then
+ begin
+ result:=symbolref(asmsym.name);
+ asmsym.cachedObjSymbol:=result;
+ FCachedAsmSymbolList.add(asmsym);
+ end
+ else
+ result:=TObjSymbol(asmsym.cachedObjSymbol);
+ end
+ else
+ result:=nil;
+ end;
+
+
+ function TObjData.symbolref(const aname:string):TObjSymbol;
+ begin
+ if not assigned(CurrObjSec) then
+ internalerror(200603052);
+ result:=CreateSymbol(aname);
+ end;
+
+
+ procedure TObjData.ResetCachedAsmSymbols;
+ var
+ i : longint;
+ begin
+ for i:=0 to FCachedAsmSymbolList.Count-1 do
+ tasmsymbol(FCachedAsmSymbolList[i]).cachedObjSymbol:=nil;
+ FCachedAsmSymbolList.Clear;
+ end;
+
+
+ procedure TObjData.writebytes(const Data;len:aword);
+ begin
+ if not assigned(CurrObjSec) then
+ internalerror(200402251);
+ CurrObjSec.write(Data,len);
+ end;
+
+
+ procedure TObjData.alloc(len:aword);
+ begin
+ if not assigned(CurrObjSec) then
+ internalerror(200402252);
+ CurrObjSec.alloc(len);
+ end;
+
+
+ procedure TObjData.allocalign(len:shortint);
+ begin
+ if not assigned(CurrObjSec) then
+ internalerror(200402253);
+ CurrObjSec.alloc(align(CurrObjSec.size,len)-CurrObjSec.size);
+ end;
+
+
+ procedure TObjData.section_afteralloc(p:TObject;arg:pointer);
+ begin
+ with TObjSection(p) do
+ alloc(align(size,secalign)-size);
+ end;
+
+
+ procedure TObjData.section_afterwrite(p:TObject;arg:pointer);
+ begin
+ with TObjSection(p) do
+ begin
+ if assigned(Data) then
+ writezeros(align(size,secalign)-size);
+ end;
+ end;
+
+
+ procedure TObjData.section_reset(p:TObject;arg:pointer);
+ begin
+ with TObjSection(p) do
+ begin
+ Size:=0;
+ Datapos:=0;
+ mempos:=0;
+ end;
+ end;
+
+
+ procedure TObjData.beforealloc;
+ begin
+ { create stabs sections if debugging }
+ if assigned(StabsSec) then
+ begin
+ StabsSec.Alloc(sizeof(TObjStabEntry));
+ StabStrSec.Alloc(1);
+ end;
+ end;
+
+
+ procedure TObjData.beforewrite;
+ var
+ s : string[1];
+ hstab : TObjStabEntry;
+ begin
+ { create stabs sections if debugging }
+ if assigned(StabsSec) then
+ begin
+ { Create dummy HdrSym stab, it will be overwritten in AfterWrite }
+ fillchar(hstab,sizeof(hstab),0);
+ StabsSec.Write(hstab,sizeof(hstab));
+ { start of stabstr }
+ s:=#0;
+ StabStrSec.write(s[1],length(s));
+ end;
+ end;
+
+
+ procedure TObjData.afteralloc;
+ begin
+ FObjSectionList.ForEachCall(@section_afteralloc,nil);
+ end;
+
+
+ procedure TObjData.afterwrite;
+ var
+ s : string[1];
+ hstab : TObjStabEntry;
+ begin
+ FObjSectionList.ForEachCall(@section_afterwrite,nil);
+ { For the stab section we need an HdrSym which can now be
+ calculated more easily }
+ if assigned(StabsSec) then
+ begin
+ { end of stabstr }
+ s:=#0;
+ StabStrSec.write(s[1],length(s));
+ { header stab }
+ hstab.strpos:=1;
+ hstab.ntype:=0;
+ hstab.nother:=0;
+ hstab.ndesc:=(StabsSec.Size div sizeof(TObjStabEntry))-1;
+ hstab.nvalue:=StabStrSec.Size;
+ StabsSec.Data.seek(0);
+ StabsSec.Data.write(hstab,sizeof(hstab));
+ end;
+ end;
+
+
+ procedure TObjData.resetsections;
+ begin
+ FObjSectionList.ForEachCall(@section_reset,nil);
+ end;
+
+
+{****************************************************************************
+ TObjOutput
+****************************************************************************}
+
+ constructor TObjOutput.create(AWriter:TObjectWriter);
+ begin
+ FWriter:=AWriter;
+ CObjData:=TObjData;
+ end;
+
+
+ destructor TObjOutput.destroy;
+ begin
+ inherited destroy;
+ end;
+
+
+ function TObjOutput.newObjData(const n:string):TObjData;
+ begin
+ result:=CObjData.create(n);
+ if (cs_use_lineinfo in current_settings.globalswitches) or
+ (cs_debuginfo in current_settings.moduleswitches) then
+ result.CreateDebugSections;
+ end;
+
+
+ function TObjOutput.startObjectfile(const fn:string):boolean;
+ begin
+ result:=false;
+ { start the writer already, so the .a generation can initialize
+ the position of the current objectfile }
+ if not FWriter.createfile(fn) then
+ Comment(V_Fatal,'Can''t create object '+fn);
+ result:=true;
+ end;
+
+
+ function TObjOutput.writeobjectfile(Data:TObjData):boolean;
+ begin
+ if errorcount=0 then
+ result:=writeData(Data)
+ else
+ result:=true;
+ { close the writer }
+ FWriter.closefile;
+ end;
+
+
+ procedure TObjOutput.exportsymbol(p:TObjSymbol);
+ begin
+ { export globals and common symbols, this is needed
+ for .a files }
+ if p.bind in [AB_GLOBAL,AB_COMMON] then
+ FWriter.writesym(p.name);
+ end;
+
+
+{****************************************************************************
+ TExeVTable
+****************************************************************************}
+
+ constructor TExeVTable.Create(AExeSymbol:TExeSymbol);
+ begin
+ ExeSymbol:=AExeSymbol;
+ if ExeSymbol.State=symstate_undefined then
+ internalerror(200604012);
+ ChildList:=TFPObjectList.Create(false);
+ end;
+
+
+ destructor TExeVTable.Destroy;
+ begin
+ ChildList.Free;
+ if assigned(EntryArray) then
+ Freemem(EntryArray);
+ end;
+
+
+ procedure TExeVTable.CheckIdx(VTableIdx:longint);
+ var
+ OldEntryCnt : longint;
+ begin
+ if VTableIdx>=EntryCnt then
+ begin
+ OldEntryCnt:=EntryCnt;
+ EntryCnt:=VTableIdx+1;
+ ReAllocMem(EntryArray,EntryCnt*sizeof(TVTableEntry));
+ FillChar(EntryArray[OldEntryCnt],(EntryCnt-OldEntryCnt)*sizeof(TVTableEntry),0);
+ end;
+ end;
+
+
+ procedure TExeVTable.AddChild(vt:TExeVTable);
+ begin
+ ChildList.Add(vt);
+ end;
+
+
+ procedure TExeVTable.AddEntry(VTableIdx:Longint);
+ var
+ i : longint;
+ objreloc : TObjRelocation;
+ vtblentryoffset : aword;
+ begin
+ CheckIdx(VTableIdx);
+ vtblentryoffset:=ExeSymbol.ObjSymbol.Offset+longword(VTableIdx)*sizeof(pint);
+ { Find and disable relocation }
+ for i:=0 to ExeSymbol.ObjSymbol.ObjSection.ObjRelocations.Count-1 do
+ begin
+ objreloc:=TObjRelocation(ExeSymbol.ObjSymbol.ObjSection.ObjRelocations[i]);
+ if objreloc.dataoffset=vtblentryoffset then
+ begin
+ EntryArray[VTableIdx].ObjRelocation:=objreloc;
+ EntryArray[VTableIdx].OrgRelocType:=objreloc.typ;
+ objreloc.typ:=RELOC_ZERO;
+ break;
+ end;
+ end;
+ if not assigned(EntryArray[VTableIdx].ObjRelocation) then
+ internalerror(200604011);
+ end;
+
+
+ procedure TExeVTable.SetVTableSize(ASize:longint);
+ begin
+ if EntryCnt<>0 then
+ internalerror(200603313);
+ EntryCnt:=ASize div sizeof(pint);
+ EntryArray:=AllocMem(EntryCnt*sizeof(TVTableEntry));
+ end;
+
+
+ function TExeVTable.VTableRef(VTableIdx:Longint):TObjRelocation;
+ begin
+ result:=nil;
+ CheckIdx(VTableIdx);
+ if EntryArray[VTableIdx].Used then
+ exit;
+ { Restore relocation if available }
+ if assigned(EntryArray[VTableIdx].ObjRelocation) then
+ begin
+ EntryArray[VTableIdx].ObjRelocation.typ:=EntryArray[VTableIdx].OrgRelocType;
+ result:=EntryArray[VTableIdx].ObjRelocation;
+ end;
+ EntryArray[VTableIdx].Used:=true;
+ end;
+
+
+{****************************************************************************
+ TExeSection
+****************************************************************************}
+
+ constructor TExeSection.create(AList:TFPHashObjectList;const AName:string);
+ begin
+ inherited create(AList,AName);
+ Size:=0;
+ MemPos:=0;
+ DataPos:=0;
+ FSecSymIdx:=0;
+ FObjSectionList:=TFPObjectList.Create(false);
+ end;
+
+
+ destructor TExeSection.destroy;
+ begin
+ ObjSectionList.Free;
+ inherited destroy;
+ end;
+
+
+ procedure TExeSection.AddObjSection(objsec:TObjSection);
+ begin
+ ObjSectionList.Add(objsec);
+ if (SecOptions<>[]) then
+ begin
+ { Only if the section contains (un)initialized data the
+ data flag must match. This check is not needed if the
+ section is empty for a symbol allocation }
+ if (objsec.size>0) and
+ ((oso_Data in SecOptions)<>(oso_Data in objsec.SecOptions)) then
+ Comment(V_Error,'Incompatible section options');
+ end
+ else
+ begin
+ { inherit section options }
+ SecAlign:=objsec.SecAlign;
+ SecOptions:=SecOptions+objsec.SecOptions;
+ end;
+ { relate ObjSection to ExeSection, and mark it Used by default }
+ objsec.ExeSection:=self;
+ objsec.Used:=true;
+ end;
+
+
+{****************************************************************************
+ TStaticLibrary
+****************************************************************************}
+
+ constructor TStaticLibrary.create(AList:TFPHashObjectList;const AName:string;AReader:TObjectReader;AObjInputClass:TObjInputClass);
+ begin
+ inherited create(AList,AName);
+ FArReader:=AReader;
+ FObjInputClass:=AObjInputClass;
+ end;
+
+
+ destructor TStaticLibrary.destroy;
+ begin
+ ArReader.Free;
+ inherited destroy;
+ end;
+
+
+{****************************************************************************
+ TImportLibrary
+****************************************************************************}
+
+ constructor TImportLibrary.create(AList:TFPHashObjectList;const AName:string);
+ begin
+ inherited create(AList,AName);
+ FImportSymbolList:=TFPHashObjectList.Create(true);
+ end;
+
+
+ destructor TImportLibrary.destroy;
+ begin
+ ImportSymbolList.Free;
+ inherited destroy;
+ end;
+
+
+{****************************************************************************
+ TImportSymbol
+****************************************************************************}
+
+ constructor TImportSymbol.create(AList:TFPHashObjectList;
+ const AName,AMangledName:string;AOrdNr:longint;AIsVar:boolean);
+ begin
+ inherited Create(AList, AName);
+ FOrdNr:=AOrdNr;
+ FIsVar:=AIsVar;
+ FMangledName:=AMangledName;
+ { Replace ? and @ in import name, since GNU AS does not allow these characters in symbol names. }
+ { This allows to import VC++ mangled names from DLLs. }
+ if target_info.system in systems_all_windows then
+ begin
+ Replace(FMangledName,'?','__q$$');
+{$ifdef arm}
+ { @ symbol is not allowed in ARM assembler only }
+ Replace(FMangledName,'@','__a$$');
+{$endif arm}
+ end;
+ end;
+
+
+{****************************************************************************
+ TExeOutput
+****************************************************************************}
+
+ constructor TExeOutput.create;
+ begin
+ { init writer }
+ FWriter:=TObjectwriter.create;
+ FExeWriteMode:=ewm_exefull;
+ { object files }
+ FObjDataList:=TFPObjectList.Create(true);
+ { symbols }
+ FExeSymbolList:=TFPHashObjectList.Create(true);
+ FUnresolvedExeSymbols:=TFPObjectList.Create(false);
+ FExternalObjSymbols:=TFPObjectList.Create(false);
+ FCommonObjSymbols:=TFPObjectList.Create(false);
+ FExeVTableList:=TFPObjectList.Create(false);
+ FEntryName:='start';
+ { sections }
+ FExeSectionList:=TFPHashObjectList.Create(true);
+ FImageBase:=0;
+{$ifdef cpu16bitaddr}
+ SectionMemAlign:=$10;
+ SectionDataAlign:=$10;
+{$else cpu16bitaddr}
+ SectionMemAlign:=$1000;
+ SectionDataAlign:=$200;
+{$endif cpu16bitaddr}
+ FCExeSection:=TExeSection;
+ FCObjData:=TObjData;
+ end;
+
+
+ destructor TExeOutput.destroy;
+ begin
+ FExeSymbolList.free;
+ UnresolvedExeSymbols.free;
+ ExternalObjSymbols.free;
+ CommonObjSymbols.free;
+ ExeVTableList.free;
+ FExeSectionList.free;
+ ObjDatalist.free;
+ FWriter.free;
+ inherited destroy;
+ end;
+
+
+ function TExeOutput.WriteExeFile(const fn:string):boolean;
+ begin
+ result:=false;
+ if FWriter.createfile(fn) then
+ begin
+ { Only write the .o if there are no errors }
+ if errorcount=0 then
+ result:=writedata
+ else
+ result:=true;
+ { close the writer }
+ FWriter.closefile;
+ end
+ else
+ Comment(V_Fatal,'Can''t create executable '+fn);
+ end;
+
+
+ procedure TExeOutput.ParseScript (linkscript:TCmdStrList);
+ begin
+ end;
+
+
+ function TExeOutput.FindExeSection(const aname:string):TExeSection;
+ begin
+ result:=TExeSection(ExeSectionList.Find(aname));
+ end;
+
+
+ procedure TExeOutput.AddObjData(ObjData:TObjData);
+ begin
+ if ObjData.classtype<>FCObjData then
+ Comment(V_Error,'Invalid input object format for '+ObjData.name+' got '+ObjData.classname+' expected '+FCObjData.classname);
+ ObjDataList.Add(ObjData);
+ end;
+
+
+ procedure TExeOutput.Load_Start;
+ begin
+ ObjDataList.Clear;
+ { Globals defined in the linker script }
+ if not assigned(internalObjData) then
+ internalObjData:=CObjData.create('*Internal*');
+ AddObjData(internalObjData);
+ { Common Data section }
+ commonObjSection:=internalObjData.createsection(sec_bss,'');
+ end;
+
+
+ procedure TExeOutput.Load_EntryName(const aname:string);
+ begin
+ FEntryName:=aname;
+ end;
+
+
+ procedure TExeOutput.Load_IsSharedLibrary;
+ begin
+ IsSharedLibrary:=true;
+ end;
+
+
+ procedure TExeOutput.Load_ImageBase(const avalue:string);
+ var
+ code : integer;
+ objsec : TObjSection;
+ objsym : TObjSymbol;
+ exesym : TExeSymbol;
+ begin
+ val(avalue,ImageBase,code);
+ if code<>0 then
+ Comment(V_Error,'Invalid number '+avalue);
+ { Create __image_base__ symbol, create the symbol
+ in a section with adress 0 and at offset 0 }
+ objsec:=internalObjData.createsection('*__image_base__',0,[]);
+ internalObjData.setsection(objsec);
+ objsym:=internalObjData.SymbolDefine('__image_base__',AB_GLOBAL,AT_FUNCTION);
+ exesym:=texesymbol.Create(FExeSymbolList,objsym.name);
+ exesym.ObjSymbol:=objsym;
+ end;
+
+
+ procedure TExeOutput.Load_Symbol(const aname:string);
+ begin
+ internalObjData.createsection('*'+aname,0,[]);
+ internalObjData.SymbolDefine(aname,AB_GLOBAL,AT_FUNCTION);
+ end;
+
+ procedure TExeOutput.Load_ProvideSymbol(const aname:string);
+ begin
+ if assigned(ExeSymbolList.Find(aname)) then
+ exit;
+ internalObjData.createsection('*'+aname,0,[]);
+ // Use AB_COMMON to avoid muliple defined complaints
+ internalObjData.SymbolDefine(aname,AB_COMMON,AT_DATA);
+ end;
+
+
+ procedure TExeOutput.Order_Start;
+ begin
+ end;
+
+
+ procedure TExeOutput.Order_End;
+ begin
+ internalObjData.afterwrite;
+ end;
+
+
+ procedure TExeOutput.Order_ExeSection(const aname:string);
+ var
+ sec : TExeSection;
+ begin
+ sec:=FindExeSection(aname);
+ if not assigned(sec) then
+ sec:=CExeSection.create(ExeSectionList,aname);
+ { Clear ExeSection contents }
+ FCurrExeSec:=sec;
+ end;
+
+
+ procedure TExeOutput.Order_EndExeSection;
+ begin
+ if not assigned(CurrExeSec) then
+ internalerror(200602184);
+ FCurrExeSec:=nil;
+ end;
+
+
+ procedure TExeOutput.Order_ObjSection(const aname:string);
+ var
+ i,j : longint;
+ ObjData : TObjData;
+ objsec : TObjSection;
+ TmpObjSectionList : TFPObjectList;
+ begin
+ if not assigned(CurrExeSec) then
+ internalerror(200602181);
+ TmpObjSectionList:=TFPObjectList.Create(false);
+ for i:=0 to ObjDataList.Count-1 do
+ begin
+ ObjData:=TObjData(ObjDataList[i]);
+ for j:=0 to ObjData.ObjSectionList.Count-1 do
+ begin
+ objsec:=TObjSection(ObjData.ObjSectionList[j]);
+ if (not objsec.Used) and
+ MatchPattern(aname,objsec.name) then
+ TmpObjSectionList.Add(objsec);
+ end;
+ end;
+ { Order list if needed }
+ Order_ObjSectionList(TmpObjSectionList,aname);
+ { Add the (ordered) list to the current ExeSection }
+ for i:=0 to TmpObjSectionList.Count-1 do
+ begin
+ objsec:=TObjSection(TmpObjSectionList[i]);
+ CurrExeSec.AddObjSection(objsec);
+ end;
+ TmpObjSectionList.Free;
+ end;
+
+
+ procedure TExeOutput.Order_ObjSectionList(ObjSectionList : TFPObjectList; const aPattern:string);
+ begin
+ end;
+
+
+ procedure TExeOutput.Order_Symbol(const aname:string);
+ var
+ ObjSection : TObjSection;
+ begin
+ ObjSection:=internalObjData.findsection('*'+aname);
+ if not assigned(ObjSection) then
+ internalerror(200603041);
+ CurrExeSec.AddObjSection(ObjSection);
+ end;
+
+ procedure TExeOutput.Order_ProvideSymbol(const aname:string);
+ var
+ ObjSection : TObjSection;
+ begin
+ ObjSection:=internalObjData.findsection('*'+aname);
+ if not assigned(ObjSection) then
+ internalerror(200603041);
+ { Only include this section if the symbol doesn't
+ exist otherwisee }
+ if not assigned(ExeSymbolList.Find(aname)) then
+ CurrExeSec.AddObjSection(ObjSection);
+ end;
+
+
+ procedure TExeOutput.Order_Align(const avalue:string);
+ var
+ code : integer;
+ alignval : shortint;
+ objsec : TObjSection;
+ begin
+ val(avalue,alignval,code);
+ if code<>0 then
+ Comment(V_Error,'Invalid number '+avalue);
+ if alignval<=0 then
+ exit;
+ { Create an empty section with the required aligning }
+ inc(Fzeronr);
+ objsec:=internalObjData.createsection('*align'+tostr(Fzeronr),alignval,CurrExeSec.SecOptions+[oso_Data,oso_keep]);
+ CurrExeSec.AddObjSection(objsec);
+ end;
+
+
+ procedure TExeOutput.Order_Zeros(const avalue:string);
+ var
+ zeros : array[0..1023] of byte;
+ code : integer;
+ len : longint;
+ objsec : TObjSection;
+ begin
+ val(avalue,len,code);
+ if code<>0 then
+ Comment(V_Error,'Invalid number '+avalue);
+ if len<=0 then
+ exit;
+ if len>sizeof(zeros) then
+ internalerror(200602254);
+ fillchar(zeros,len,0);
+ inc(Fzeronr);
+ objsec:=internalObjData.createsection('*zeros'+tostr(Fzeronr),0,CurrExeSec.SecOptions+[oso_Data,oso_keep]);
+ internalObjData.writebytes(zeros,len);
+ CurrExeSec.AddObjSection(objsec);
+ end;
+
+ procedure TExeOutput.Order_Values(bytesize : aword; const avalue:string);
+ const
+ MAXVAL = 128;
+ var
+ bytevalues : array[0..MAXVAL-1] of byte;
+ twobytevalues : array[0..MAXVAL-1] of word;
+ fourbytevalues : array[0..MAXVAL-1] of dword;
+ eightbytevalues : array[0..MAXVAL-1] of qword;
+ allvals, oneval : string;
+ len, commapos : longint;
+ indexpos, code : integer;
+ anumval : qword;
+ signedval : int64;
+ objsec : TObjSection;
+ begin
+ indexpos:=0;
+ allvals:=avalue;
+ repeat
+ commapos:=pos(',',allvals);
+ if commapos>0 then
+ begin
+ oneval:=trim(copy(allvals,1,commapos-1));
+ allvals:=copy(allvals,commapos+1,length(allvals));
+ end
+ else
+ begin
+ oneval:=trim(allvals);
+ allvals:='';
+ end;
+ if oneval<>'' then
+ begin
+ if oneval[1]='-' then
+ begin
+ val(oneval,signedval,code);
+ anumval:=qword(signedval);
+ end
+ else
+ val(oneval,anumval,code);
+ if code<>0 then
+ Comment(V_Error,'Invalid number '+avalue)
+ else
+ begin
+ if (indexpos<MAXVAL) then
+ begin
+ if source_info.endian<>target_info.endian then
+ swapendian(anumval);
+ { No range checking here }
+
+ if bytesize=1 then
+ bytevalues[indexpos]:=byte(anumval)
+ else if bytesize=2 then
+ twobytevalues[indexpos]:=word(anumval)
+ else if bytesize=4 then
+ fourbytevalues[indexpos]:=dword(anumval)
+ else if bytesize=8 then
+ eightbytevalues[indexpos]:=anumval;
+ inc(indexpos);
+ end
+ else
+ Comment(V_Error,'Buffer overrun in Order_values');
+ end;
+ end;
+ until allvals='';
+ if indexpos=0 then
+ begin
+ Comment(V_Error,'Invalid number '+avalue);
+ exit;
+ end;
+ if indexpos=MAXVAL then
+ begin
+ Comment(V_Error,'Too many values '+avalue);
+ internalerror(200602254);
+ end;
+ len:=bytesize*indexpos;
+ inc(Fvaluesnr);
+ objsec:=internalObjData.createsection('*values'+tostr(Fvaluesnr),0,CurrExeSec.SecOptions+[oso_Data,oso_keep]);
+ if bytesize=1 then
+ internalObjData.writebytes(bytevalues,len)
+ else if bytesize=2 then
+ internalObjData.writebytes(twobytevalues,len)
+ else if bytesize=4 then
+ internalObjData.writebytes(fourbytevalues,len)
+ else if bytesize=8 then
+ internalObjData.writebytes(eightbytevalues,len);
+ CurrExeSec.AddObjSection(objsec);
+ end;
+
+
+ procedure TExeOutput.MemPos_Start;
+ begin
+ CurrMemPos:=0;
+ end;
+
+
+ procedure TExeOutput.MemPos_Header;
+ begin
+ end;
+
+
+ procedure TExeOutput.MemPos_ExeSection(const aname:string);
+ var
+ i : longint;
+ objsec : TObjSection;
+ begin
+ { Section can be removed }
+ FCurrExeSec:=FindExeSection(aname);
+ if not assigned(CurrExeSec) then
+ exit;
+
+ { Alignment of ExeSection }
+ CurrMemPos:=align(CurrMemPos,SectionMemAlign);
+ CurrExeSec.MemPos:=CurrMemPos;
+
+ { set position of object ObjSections }
+ for i:=0 to CurrExeSec.ObjSectionList.Count-1 do
+ begin
+ objsec:=TObjSection(CurrExeSec.ObjSectionList[i]);
+ CurrMemPos:=objsec.setmempos(CurrMemPos);
+ end;
+
+ { calculate size of the section }
+ CurrExeSec.Size:=CurrMemPos-CurrExeSec.MemPos;
+ end;
+
+
+ procedure TExeOutput.MemPos_EndExeSection;
+ begin
+ if not assigned(CurrExeSec) then
+ exit;
+ FCurrExeSec:=nil;
+ end;
+
+
+ procedure TExeOutput.DataPos_Start;
+ begin
+ end;
+
+
+ procedure TExeOutput.DataPos_Header;
+ begin
+ end;
+
+
+ procedure TExeOutput.DataPos_ExeSection(const aname:string);
+ var
+ i : longint;
+ objsec : TObjSection;
+ begin
+ { Section can be removed }
+ FCurrExeSec:=FindExeSection(aname);
+ if not assigned(CurrExeSec) then
+ exit;
+
+ { don't write normal section if writing only debug info }
+ if (ExeWriteMode=ewm_dbgonly) and
+ not(oso_debug in CurrExeSec.SecOptions) then
+ exit;
+
+ if (oso_Data in currexesec.SecOptions) then
+ begin
+ CurrDataPos:=align(CurrDataPos,SectionDataAlign);
+ CurrExeSec.DataPos:=CurrDataPos;
+ end;
+
+ { set position of object ObjSections }
+ for i:=0 to CurrExeSec.ObjSectionList.Count-1 do
+ begin
+ objsec:=TObjSection(CurrExeSec.ObjSectionList[i]);
+ if (oso_Data in objsec.SecOptions) then
+ begin
+ if not(oso_Data in currexesec.SecOptions) then
+ internalerror(200603043);
+ if not assigned(objsec.Data) then
+ internalerror(200603044);
+ objsec.setDatapos(CurrDataPos);
+ end;
+ end;
+ end;
+
+
+ procedure TExeOutput.DataPos_EndExeSection;
+ begin
+ if not assigned(CurrExeSec) then
+ exit;
+ FCurrExeSec:=nil;
+ end;
+
+
+ procedure TExeOutput.DataPos_Symbols;
+ var
+ i : longint;
+ sym : TExeSymbol;
+ begin
+ { Removing unused symbols }
+ for i:=0 to ExeSymbolList.Count-1 do
+ begin
+ sym:=TExeSymbol(ExeSymbolList[i]);
+ if not sym.ObjSymbol.objsection.Used then
+ ExeSymbolList[i]:=nil;
+ end;
+ ExeSymbolList.Pack;
+ end;
+
+
+ procedure TExeOutput.BuildVTableTree(VTInheritList,VTEntryList:TFPObjectList);
+ var
+ hs : string;
+ code : integer;
+ i,k,
+ vtableidx : longint;
+ vtableexesym,
+ childexesym,
+ parentexesym : TExeSymbol;
+ objsym : TObjSymbol;
+ begin
+ { Build inheritance tree from VTINHERIT }
+ for i:=0 to VTInheritList.Count-1 do
+ begin
+ objsym:=TObjSymbol(VTInheritList[i]);
+ hs:=objsym.name;
+ { VTINHERIT_<ChildVMTName>$$<ParentVMTName> }
+ Delete(hs,1,Pos('_',hs));
+ k:=Pos('$$',hs);
+ if k=0 then
+ internalerror(200603311);
+ childexesym:=texesymbol(FExeSymbolList.Find(Copy(hs,1,k-1)));
+ parentexesym:=texesymbol(FExeSymbolList.Find(Copy(hs,k+2,length(hs)-k-1)));
+ if not assigned(childexesym) or
+ not assigned(parentexesym)then
+ internalerror(200603312);
+ if not assigned(childexesym.vtable) then
+ begin
+ childexesym.vtable:=TExeVTable.Create(childexesym);
+ ExeVTableList.Add(childexesym.vtable);
+ end;
+ if not assigned(parentexesym.vtable) then
+ begin
+ parentexesym.vtable:=TExeVTable.Create(parentexesym);
+ ExeVTableList.Add(parentexesym.vtable);
+ end;
+ childexesym.vtable.SetVTableSize(childexesym.ObjSymbol.Size);
+ if parentexesym<>childexesym then
+ parentexesym.vtable.AddChild(childexesym.vtable);
+ end;
+
+ { Find VTable entries from VTENTRY }
+ for i:=0 to VTEntryList.Count-1 do
+ begin
+ objsym:=TObjSymbol(VTEntryList[i]);
+ hs:=objsym.name;
+ { VTENTRY_<VTableName>$$<Index> }
+ Delete(hs,1,Pos('_',hs));
+ k:=Pos('$$',hs);
+ if k=0 then
+ internalerror(200603319);
+ vtableexesym:=texesymbol(FExeSymbolList.Find(Copy(hs,1,k-1)));
+ val(Copy(hs,k+2,length(hs)-k-1),vtableidx,code);
+ if (code<>0) then
+ internalerror(200603318);
+ if not assigned(vtableexesym) then
+ internalerror(2006033110);
+ vtableexesym.vtable.AddEntry(vtableidx);
+ end;
+ end;
+
+
+ procedure TExeOutput.PackUnresolvedExeSymbols(const s:string);
+ var
+ i : longint;
+ exesym : TExeSymbol;
+ begin
+ { Generate a list of Unresolved External symbols }
+ for i:=0 to UnresolvedExeSymbols.count-1 do
+ begin
+ exesym:=TExeSymbol(UnresolvedExeSymbols[i]);
+ if exesym.State<>symstate_undefined then
+ UnresolvedExeSymbols[i]:=nil;
+ end;
+ UnresolvedExeSymbols.Pack;
+ Comment(V_Debug,'Number of unresolved externals '+s+' '+tostr(UnresolvedExeSymbols.Count));
+ end;
+
+
+ procedure TExeOutput.ResolveSymbols(StaticLibraryList:TFPHashObjectList);
+ var
+ ObjData : TObjData;
+ exesym : TExeSymbol;
+ objsym,
+ commonsym : TObjSymbol;
+ objinput : TObjInput;
+ StaticLibrary : TStaticLibrary;
+ firstarchive,
+ firstcommon : boolean;
+ i,j : longint;
+ VTEntryList,
+ VTInheritList : TFPObjectList;
+
+ procedure LoadObjDataSymbols(ObjData:TObjData);
+ var
+ j : longint;
+ hs : string;
+ exesym : TExeSymbol;
+ objsym : TObjSymbol;
+ begin
+ for j:=0 to ObjData.ObjSymbolList.Count-1 do
+ begin
+ objsym:=TObjSymbol(ObjData.ObjSymbolList[j]);
+ { From the local symbols we are only interressed in the
+ VTENTRY and VTINHERIT symbols }
+ if objsym.bind=AB_LOCAL then
+ begin
+ if cs_link_opt_vtable in current_settings.globalswitches then
+ begin
+ hs:=objsym.name;
+ if (hs[1]='V') then
+ begin
+ if Copy(hs,1,5)='VTREF' then
+ begin
+ if not assigned(objsym.ObjSection.VTRefList) then
+ objsym.ObjSection.VTRefList:=TFPObjectList.Create(false);
+ objsym.ObjSection.VTRefList.Add(objsym);
+ end
+ else if Copy(hs,1,7)='VTENTRY' then
+ VTEntryList.Add(objsym)
+ else if Copy(hs,1,9)='VTINHERIT' then
+ VTInheritList.Add(objsym);
+ end;
+ end;
+ continue;
+ end;
+ { Search for existing exesymbol }
+ exesym:=texesymbol(FExeSymbolList.Find(objsym.name));
+ if not assigned(exesym) then
+ begin
+ exesym:=texesymbol.Create(FExeSymbolList,objsym.name);
+ exesym.ObjSymbol:=objsym;
+ end;
+ objsym.ExeSymbol:=exesym;
+ case objsym.bind of
+ AB_GLOBAL :
+ begin
+ if exesym.State<>symstate_defined then
+ begin
+ exesym.ObjSymbol:=objsym;
+ exesym.State:=symstate_defined;
+ end
+ else
+ Comment(V_Error,'Multiple defined symbol '+objsym.name);
+ end;
+ AB_EXTERNAL :
+ begin
+ ExternalObjSymbols.add(objsym);
+ { Register unresolved symbols only the first time they
+ are registered }
+ if exesym.ObjSymbol=objsym then
+ UnresolvedExeSymbols.Add(exesym);
+ end;
+ AB_COMMON :
+ begin
+ if exesym.State=symstate_undefined then
+ begin
+ exesym.ObjSymbol:=objsym;
+ exesym.State:=symstate_common;
+ end;
+ CommonObjSymbols.add(objsym);
+ end;
+ end;
+ end;
+ end;
+
+ begin
+ VTEntryList:=TFPObjectList.Create(false);
+ VTInheritList:=TFPObjectList.Create(false);
+
+ {
+ The symbol resolving is done in 3 steps:
+ 1. Register symbols from objects
+ 2. Find symbols in static libraries
+ 3. Define stil undefined common symbols
+ }
+
+ { Step 1, Register symbols from objects }
+ for i:=0 to ObjDataList.Count-1 do
+ begin
+ ObjData:=TObjData(ObjDataList[i]);
+ LoadObjDataSymbols(ObjData);
+ end;
+ PackUnresolvedExeSymbols('in objects');
+
+ { Step 2, Find unresolved symbols in the libraries }
+ firstarchive:=true;
+ for i:=0 to StaticLibraryList.Count-1 do
+ begin
+ StaticLibrary:=TStaticLibrary(StaticLibraryList[i]);
+ { Process list of Unresolved External symbols, we need
+ to use a while loop because the list can be extended when
+ we load members from the library. }
+ j:=0;
+ while (j<UnresolvedExeSymbols.count) do
+ begin
+ exesym:=TExeSymbol(UnresolvedExeSymbols[j]);
+ { Check first if the symbol is still undefined }
+ if exesym.State=symstate_undefined then
+ begin
+ if StaticLibrary.ArReader.OpenFile(exesym.name) then
+ begin
+ if assigned(exemap) then
+ begin
+ if firstarchive then
+ begin
+ exemap.Add('');
+ exemap.Add('Archive member included because of file (symbol)');
+ exemap.Add('');
+ firstarchive:=false;
+ end;
+ exemap.Add(StaticLibrary.ArReader.FileName+' - '+
+ {exesym.ObjSymbol.ObjSection.FullName+}
+ '('+exesym.Name+')');
+ end;
+ objinput:=StaticLibrary.ObjInputClass.Create;
+ objdata:=objinput.newObjData(StaticLibrary.ArReader.FileName);
+ objinput.ReadObjData(StaticLibrary.ArReader,objdata);
+ objinput.free;
+ AddObjData(objdata);
+ LoadObjDataSymbols(objdata);
+ StaticLibrary.ArReader.CloseFile;
+ end;
+ end;
+ inc(j);
+ end;
+ end;
+ PackUnresolvedExeSymbols('after static libraries');
+
+ { Step 3, Match common symbols or add to the globals }
+ firstcommon:=true;
+ for i:=0 to CommonObjSymbols.count-1 do
+ begin
+ objsym:=TObjSymbol(CommonObjSymbols[i]);
+ if objsym.exesymbol.State=symstate_defined then
+ begin
+ if objsym.exesymbol.ObjSymbol.size<>objsym.size then
+ Comment(V_Debug,'Size of common symbol '+objsym.name+' is different, expected '+tostr(objsym.size)+' got '+tostr(objsym.exesymbol.ObjSymbol.size));
+ end
+ else
+ begin
+ { allocate new objsymbol in .bss of *COMMON* and assign
+ it to the exesymbol }
+ if firstcommon then
+ begin
+ if assigned(exemap) then
+ exemap.AddCommonSymbolsHeader;
+ firstcommon:=false;
+ end;
+ internalObjData.setsection(commonObjSection);
+ internalObjData.allocalign(var_align(objsym.size));
+ commonsym:=internalObjData.symboldefine(objsym.name,AB_GLOBAL,AT_FUNCTION);
+ commonsym.size:=objsym.size;
+ internalObjData.alloc(objsym.size);
+ if assigned(exemap) then
+ exemap.AddCommonSymbol(commonsym);
+ { Assign to the exesymbol }
+ objsym.exesymbol.objsymbol:=commonsym;
+ objsym.exesymbol.state:=symstate_defined;
+ end;
+ end;
+ PackUnresolvedExeSymbols('after defining COMMON symbols');
+
+ { Find entry symbol and print in map }
+ exesym:=texesymbol(ExeSymbolList.Find(EntryName));
+ if assigned(exesym) then
+ begin
+ EntrySym:=exesym.ObjSymbol;
+ if assigned(exemap) then
+ begin
+ exemap.Add('');
+ exemap.Add('Entry symbol '+EntryName);
+ end;
+ end
+ else
+ Comment(V_Error,'Entrypoint '+EntryName+' not defined');
+
+ { Generate VTable tree }
+ if cs_link_opt_vtable in current_settings.globalswitches then
+ BuildVTableTree(VTInheritList,VTEntryList);
+ VTInheritList.Free;
+ VTEntryList.Free;
+ end;
+
+
+ procedure TExeOutput.GenerateDebugLink(const dbgname:string;dbgcrc:cardinal);
+ var
+ debuglink : array[0..1023] of byte;
+ len : longint;
+ objsec : TObjSection;
+ exesec : TExeSection;
+ begin
+ { From the gdb manual chapter 15. GDB Files:
+
+ * A filename, with any leading directory components removed, followed by a zero byte,
+ * zero to three bytes of padding, as needed to reach the next four-byte boundary within the section, and
+ * a four-byte CRC checksum, stored in the same endianness used for the executable file itself. The checksum is computed
+ on the debugging information file's full contents by the function given below, passing zero as the crc argument.
+ }
+ fillchar(debuglink,sizeof(debuglink),0);
+ len:=0;
+ move(dbgname[1],debuglink[len],length(dbgname));
+ inc(len,length(dbgname)+1);
+ len:=align(len,4);
+ if source_info.endian<>target_info.endian then
+ SwapEndian(dbgcrc);
+ move(dbgcrc,debuglink[len],sizeof(cardinal));
+ inc(len,4);
+ { Add section }
+ exesec:=FindExeSection(debuglinkname);
+ if not assigned(exesec) then
+ exesec:=CExeSection.create(ExeSectionList,debuglinkname);
+ exesec.SecOptions:=[oso_data,oso_keep];
+ exesec.SecAlign:=4;
+ objsec:=internalObjData.createsection(exesec.name,0,exesec.SecOptions);
+ internalObjData.writebytes(debuglink,len);
+ exesec.AddObjSection(objsec);
+ end;
+
+
+ procedure TExeOutput.GenerateLibraryImports(ImportLibraryList:TFPHashObjectList);
+ begin
+ end;
+
+
+ procedure TExeOutput.PrintMemoryMap;
+ var
+ exesec : TExeSection;
+ objsec : TObjSection;
+ objsym : TObjSymbol;
+ i,j,k : longint;
+ begin
+ if not assigned(exemap) then
+ exit;
+ exemap.AddMemoryMapHeader(ImageBase);
+ for i:=0 to ExeSectionList.Count-1 do
+ begin
+ exesec:=TExeSection(ExeSectionList[i]);
+ exemap.AddMemoryMapExeSection(exesec);
+ for j:=0 to exesec.ObjSectionList.count-1 do
+ begin
+ objsec:=TObjSection(exesec.ObjSectionList[j]);
+ exemap.AddMemoryMapObjectSection(objsec);
+ for k:=0 to objsec.ObjSymbolDefines.Count-1 do
+ begin
+ objsym:=TObjSymbol(objsec.ObjSymbolDefines[k]);
+ exemap.AddMemoryMapSymbol(objsym);
+ end;
+ end;
+ end;
+ end;
+
+
+ procedure TExeOutput.FixupSymbols;
+
+ procedure UpdateSymbol(objsym:TObjSymbol);
+ begin
+ objsym.bind:=objsym.ExeSymbol.ObjSymbol.bind;
+ objsym.offset:=objsym.ExeSymbol.ObjSymbol.offset;
+ objsym.size:=objsym.ExeSymbol.ObjSymbol.size;
+ objsym.typ:=objsym.ExeSymbol.ObjSymbol.typ;
+ objsym.ObjSection:=objsym.ExeSymbol.ObjSymbol.ObjSection;
+ end;
+
+ var
+ i : longint;
+ objsym : TObjSymbol;
+ exesym : TExeSymbol;
+ begin
+ { Print list of Unresolved External symbols }
+ for i:=0 to UnresolvedExeSymbols.count-1 do
+ begin
+ exesym:=TExeSymbol(UnresolvedExeSymbols[i]);
+ if exesym.State<>symstate_defined then
+ Comment(V_Error,'Undefined symbol: '+exesym.name);
+ end;
+
+ { Update ImageBase to ObjData so it can access from ObjSymbols }
+ for i:=0 to ObjDataList.Count-1 do
+ TObjData(ObjDataList[i]).imagebase:=imagebase;
+
+ {
+ Fixing up symbols is done in the following steps:
+ 1. Update common references
+ 2. Update external references
+ }
+
+ { Step 1, Update commons }
+ for i:=0 to CommonObjSymbols.count-1 do
+ begin
+ objsym:=TObjSymbol(CommonObjSymbols[i]);
+ if objsym.bind<>AB_COMMON then
+ internalerror(200606241);
+ UpdateSymbol(objsym);
+ end;
+
+ { Step 2, Update externals }
+ for i:=0 to ExternalObjSymbols.count-1 do
+ begin
+ objsym:=TObjSymbol(ExternalObjSymbols[i]);
+ if objsym.bind<>AB_EXTERNAL then
+ internalerror(200606242);
+ UpdateSymbol(objsym);
+ end;
+ end;
+
+
+ procedure TExeOutput.MergeStabs;
+ var
+ stabexesec,
+ stabstrexesec : TExeSection;
+ relocsec,
+ currstabsec,
+ currstabstrsec,
+ mergedstabsec,
+ mergedstabstrsec : TObjSection;
+ hstabreloc,
+ currstabreloc : TObjRelocation;
+ i,j : longint;
+ currstabrelocidx,
+ mergestabcnt,
+ stabcnt : longword;
+ skipstab : boolean;
+ skipfun : boolean;
+ hstab : TObjStabEntry;
+ stabrelocofs : longword;
+ buf : array[0..1023] of byte;
+ bufend,
+ bufsize : longint;
+ begin
+ stabexesec:=FindExeSection('.stab');
+ stabstrexesec:=FindExeSection('.stabstr');
+ if (stabexesec=nil) or
+ (stabstrexesec=nil) or
+ (stabexesec.ObjSectionlist.count=0) then
+ exit;
+ { Create new stabsection }
+ stabRelocofs:=pbyte(@hstab.nvalue)-pbyte(@hstab);
+ mergedstabsec:=internalObjData.CreateSection(sec_stab,'');
+ mergedstabstrsec:=internalObjData.CreateSection(sec_stabstr,'');
+
+ { write stab for hdrsym }
+ fillchar(hstab,sizeof(TObjStabEntry),0);
+ mergedstabsec.write(hstab,sizeof(TObjStabEntry));
+ mergestabcnt:=1;
+
+ { .stabstr starts with a #0 }
+ buf[0]:=0;
+ mergedstabstrsec.write(buf[0],1);
+
+ skipfun:=false;
+ { Copy stabs and corresponding Relocations }
+ for i:=0 to stabexesec.ObjSectionList.Count-1 do
+ begin
+ currstabsec:=TObjSection(stabexesec.ObjSectionList[i]);
+ currstabstrsec:=currstabsec.ObjData.findsection('.stabstr');
+ if assigned(currstabstrsec) then
+ begin
+ stabcnt:=currstabsec.Data.size div sizeof(TObjStabEntry);
+ currstabsec.Data.seek(0);
+ currstabrelocidx:=0;
+ for j:=0 to stabcnt-1 do
+ begin
+ hstabreloc:=nil;
+ skipstab:=false;
+ currstabsec.Data.read(hstab,sizeof(TObjStabEntry));
+ { Only include first hdrsym stab }
+ if hstab.ntype=0 then
+ skipstab:=true;
+ if skipfun then
+ begin
+ { Skip all stabs for function body until N_RBRAC }
+ skipfun:=hstab.ntype<>N_RBRAC;
+ skipstab:=true;
+ end;
+ if not skipstab then
+ begin
+ { Find corresponding Relocation }
+ currstabreloc:=nil;
+ while (currstabrelocidx<longword(currstabsec.ObjRelocations.Count)) do
+ begin
+ currstabreloc:=TObjRelocation(currstabsec.ObjRelocations[currstabrelocidx]);
+ if assigned(currstabreloc) and
+ (currstabreloc.dataoffset>=longword(j)*sizeof(TObjStabEntry)+stabrelocofs) then
+ break;
+ inc(currstabrelocidx);
+ end;
+ if assigned(currstabreloc) and
+ (currstabreloc.dataoffset=longword(j)*sizeof(TObjStabEntry)+stabrelocofs) then
+ begin
+ hstabReloc:=currstabReloc;
+ inc(currstabrelocidx);
+ end;
+
+ { Check if the stab is refering to a removed section }
+ if assigned(hstabreloc) then
+ begin
+ if assigned(hstabreloc.Symbol) then
+ relocsec:=hstabreloc.Symbol.ObjSection
+ else
+ relocsec:=hstabreloc.ObjSection;
+ if not assigned(relocsec) then
+ internalerror(200603302);
+ if not relocsec.Used then
+ begin
+ skipstab:=true;
+ if (hstab.ntype=N_Function) and (hstab.strpos<>0) then
+ begin
+ currstabstrsec.Data.seek(hstab.strpos);
+ bufsize:=currstabstrsec.Data.read(buf,sizeof(buf));
+ bufend:=indexbyte(buf,bufsize,Ord(':'));
+ if (bufend<>-1) and (bufend<bufsize-1) and (buf[bufend+1]=Ord('F')) then
+ skipfun:=true;
+ end;
+ end;
+ end;
+ end;
+ if not skipstab then
+ begin
+ { Copy string in stabstr }
+ if hstab.strpos<>0 then
+ begin
+ currstabstrsec.Data.seek(hstab.strpos);
+ hstab.strpos:=mergedstabstrsec.Size;
+ repeat
+ bufsize:=currstabstrsec.Data.read(buf,sizeof(buf));
+ bufend:=indexbyte(buf,bufsize,0);
+ if bufend=-1 then
+ bufend:=bufsize
+ else
+ begin
+ { include the #0 }
+ inc(bufend);
+ end;
+ mergedstabstrsec.write(buf,bufend);
+ until (buf[bufend-1]=0) or (bufsize<sizeof(buf));
+ end;
+ { Copy and Update the relocation }
+ if assigned(hstabreloc) then
+ begin
+ hstabreloc.Dataoffset:=mergestabcnt*sizeof(TObjStabEntry)+stabRelocofs;
+ { Remove from List without freeing the object }
+ currstabsec.ObjRelocations.List[currstabrelocidx-1]:=nil;
+ mergedstabsec.ObjRelocations.Add(hstabreloc);
+ end;
+ { Write updated stab }
+ mergedstabsec.write(hstab,sizeof(hstab));
+ inc(mergestabcnt);
+ end;
+ end;
+ end;
+
+ { Unload stabs }
+ if assigned(currstabstrsec) then
+ begin
+ currstabstrsec.Used:=False;
+ currstabstrsec.ReleaseData;
+ end;
+ currstabsec.Used:=false;
+ currstabsec.ReleaseData;
+ end;
+
+ { Generate new HdrSym }
+ if mergedstabsec.Size>0 then
+ begin
+ hstab.strpos:=1;
+ hstab.ntype:=0;
+ hstab.nother:=0;
+ hstab.ndesc:=word(mergestabcnt-1);
+ hstab.nvalue:=mergedstabstrsec.Size;
+ mergedstabsec.Data.seek(0);
+ mergedstabsec.Data.write(hstab,sizeof(hstab));
+ end;
+
+ { Replace all sections with our combined stabsec }
+ stabexesec.ObjSectionList.Clear;
+ stabstrexesec.ObjSectionList.Clear;
+ stabexesec.AddObjSection(mergedstabsec);
+ stabstrexesec.AddObjSection(mergedstabstrsec);
+ end;
+
+
+ procedure TExeOutput.RemoveEmptySections;
+ var
+ i, j : longint;
+ exesec : TExeSection;
+ doremove : boolean;
+ begin
+ for i:=0 to ExeSectionList.Count-1 do
+ begin
+ exesec:=TExeSection(ExeSectionList[i]);
+
+ doremove:=not(oso_keep in exesec.SecOptions) and
+ (
+ (exesec.ObjSectionlist.count=0) or
+ (
+ (cs_link_strip in current_settings.globalswitches) and
+ not(cs_link_separate_dbg_file in current_settings.globalswitches) and
+ (oso_debug in exesec.SecOptions)
+ )
+ );
+ if not doremove then
+ begin
+ { Check if section has no actual data }
+ doremove:=true;
+ for j:=0 to exesec.ObjSectionList.Count-1 do
+ if TObjSection(exesec.ObjSectionList[j]).Size<>0 then
+ begin
+ doremove:=false;
+ break;
+ end;
+ end;
+ if doremove and not (RelocSection and (exesec.Name='.reloc')) then
+ begin
+ Comment(V_Debug,'Deleting empty section '+exesec.name);
+ ExeSectionList[i]:=nil;
+ end;
+ end;
+ ExeSectionList.Pack;
+ end;
+
+
+ procedure TExeOutput.RemoveDebugInfo;
+ var
+ i : longint;
+ exesec : TExeSection;
+ begin
+ for i:=0 to ExeSectionList.Count-1 do
+ begin
+ exesec:=TExeSection(ExeSectionList[i]);
+ if (oso_debug in exesec.SecOptions) then
+ ExeSectionList[i]:=nil;
+ end;
+ ExeSectionList.Pack;
+ end;
+
+
+ procedure TExeOutput.RemoveUnreferencedSections;
+ var
+ ObjSectionWorkList : TFPObjectList;
+
+ procedure AddToObjSectionWorkList(aobjsec:TObjSection);
+ begin
+ if not aobjsec.Used then
+ begin
+ aobjsec.Used:=true;
+ ObjSectionWorkList.Add(aobjsec);
+ end;
+ end;
+
+ procedure DoReloc(objreloc:TObjRelocation);
+ var
+ objsym : TObjSymbol;
+ refobjsec : TObjSection;
+ begin
+ { Disabled Relocation to 0 }
+ if objreloc.typ=RELOC_ZERO then
+ exit;
+ if assigned(objreloc.symbol) then
+ begin
+ objsym:=objreloc.symbol;
+ if objsym.bind<>AB_LOCAL then
+ begin
+ if not(assigned(objsym.exesymbol) and
+ (objsym.exesymbol.State=symstate_defined)) then
+ internalerror(200603063);
+ objsym:=objsym.exesymbol.objsymbol;
+ end;
+ if not assigned(objsym.objsection) then
+ internalerror(200603062);
+ refobjsec:=objsym.objsection;
+ end
+ else
+ if assigned(objreloc.objsection) then
+ refobjsec:=objreloc.objsection
+ else
+ internalerror(200603316);
+ if assigned(exemap) then
+ begin
+ objsym:=objreloc.symbol;
+ if assigned(objsym) then
+ exemap.Add(' References '+objsym.name+' in '
+ +refobjsec.fullname)
+ else
+ exemap.Add(' References '+refobjsec.fullname);
+ end;
+ AddToObjSectionWorkList(refobjsec);
+ end;
+
+ procedure DoVTableRef(vtable:TExeVTable;VTableIdx:longint);
+ var
+ i : longint;
+ objreloc : TObjRelocation;
+ begin
+ objreloc:=vtable.VTableRef(VTableIdx);
+ if assigned(objreloc) then
+ begin
+ { Process the relocation now if the ObjSection is
+ already processed and marked as used. Otherwise we leave it
+ unprocessed. It'll then be resolved when the ObjSection is
+ changed to Used }
+ if vtable.ExeSymbol.ObjSymbol.ObjSection.Used then
+ DoReloc(objreloc);
+ end;
+ { This recursive walking is done here instead of
+ in TExeVTable.VTableRef because we can now process
+ all needed relocations }
+ for i:=0 to vtable.ChildList.Count-1 do
+ DoVTableRef(TExeVTable(vtable.ChildList[i]),VTableIdx);
+ end;
+
+ var
+ hs : string;
+ i,j,k : longint;
+ exesec : TExeSection;
+ objdata : TObjData;
+ objsec : TObjSection;
+ objsym : TObjSymbol;
+ code : integer;
+ vtableidx : longint;
+ vtableexesym : TExeSymbol;
+ begin
+ ObjSectionWorkList:=TFPObjectList.Create(false);
+
+ if assigned(exemap) then
+ exemap.AddHeader('Removing unreferenced sections');
+
+ { Initialize by marking all sections unused and
+ adding the sections with oso_keep flags to the ObjSectionWorkList }
+ for i:=0 to ObjDataList.Count-1 do
+ begin
+ ObjData:=TObjData(ObjDataList[i]);
+ for j:=0 to ObjData.ObjSectionList.Count-1 do
+ begin
+ objsec:=TObjSection(ObjData.ObjSectionList[j]);
+ objsec.Used:=false;
+{ TODO: remove debug section always keep}
+ if oso_debug in objsec.secoptions then
+ objsec.Used:=true;
+ if (oso_keep in objsec.secoptions) then
+ begin
+ AddToObjSectionWorkList(objsec);
+ if objsec.name='.fpc.n_links' then
+ objsec.Used:=false;
+ end;
+ end;
+ end;
+ AddToObjSectionWorkList(entrysym.exesymbol.objsymbol.objsection);
+
+ { Process all sections, add new sections to process based
+ on the symbol references }
+ while ObjSectionWorkList.Count>0 do
+ begin
+ objsec:=TObjSection(ObjSectionWorkList.Last);
+ if assigned(exemap) then
+ exemap.Add('Keeping '+objsec.FullName+' '+ToStr(objsec.ObjRelocations.Count)+' references');
+ ObjSectionWorkList.Delete(ObjSectionWorkList.Count-1);
+
+ { Process Relocations }
+ for i:=0 to objsec.ObjRelocations.count-1 do
+ DoReloc(TObjRelocation(objsec.ObjRelocations[i]));
+
+ { Process Virtual Entry calls }
+ if cs_link_opt_vtable in current_settings.globalswitches then
+ begin
+ for i:=0 to objsec.VTRefList.count-1 do
+ begin
+ objsym:=TObjSymbol(objsec.VTRefList[i]);
+ hs:=objsym.name;
+ Delete(hs,1,Pos('_',hs));
+ k:=Pos('$$',hs);
+ if k=0 then
+ internalerror(200603314);
+ vtableexesym:=texesymbol(FExeSymbolList.Find(Copy(hs,1,k-1)));
+ val(Copy(hs,k+2,length(hs)-k-1),vtableidx,code);
+ if (code<>0) then
+ internalerror(200603317);
+ if not assigned(vtableexesym) then
+ internalerror(200603315);
+ if not assigned(vtableexesym.vtable) then
+ internalerror(200603316);
+ DoVTableRef(vtableexesym.vtable,vtableidx);
+ end;
+ end;
+ end;
+ ObjSectionWorkList.Free;
+ ObjSectionWorkList:=nil;
+
+ { Remove unused objsections from ExeSectionList }
+ for i:=0 to ExeSectionList.Count-1 do
+ begin
+ exesec:=TExeSection(ExeSectionList[i]);
+ for j:=0 to exesec.ObjSectionlist.count-1 do
+ begin
+ objsec:=TObjSection(exesec.ObjSectionlist[j]);
+ if not objsec.used then
+ begin
+ if assigned(exemap) then
+ exemap.Add('Removing '+objsec.FullName);
+ exesec.ObjSectionlist[j]:=nil;
+ objsec.ReleaseData;
+ end;
+ end;
+ exesec.ObjSectionlist.Pack;
+ end;
+ end;
+
+
+ procedure TExeOutput.FixupRelocations;
+ var
+ i,j : longint;
+ exesec : TExeSection;
+ objsec : TObjSection;
+ begin
+ for i:=0 to ExeSectionList.Count-1 do
+ begin
+ exesec:=TExeSection(ExeSectionList[i]);
+ if not assigned(exesec) then
+ continue;
+ for j:=0 to exesec.ObjSectionlist.count-1 do
+ begin
+ objsec:=TObjSection(exesec.ObjSectionlist[j]);
+ if not objsec.Used then
+ internalerror(200603301);
+ objsec.FixupRelocs;
+ end;
+ end;
+ end;
+
+
+ procedure TExeOutput.SetCurrMemPos(const AValue: qword);
+ begin
+ if AValue>MaxMemPos then
+ Message1(link_f_executable_too_big, target_os_string);
+ FCurrMemPos:=AValue;
+ end;
+
+
+{****************************************************************************
+ TObjInput
+****************************************************************************}
+
+ constructor TObjInput.create;
+ begin
+ end;
+
+
+ destructor TObjInput.destroy;
+ begin
+ inherited destroy;
+ end;
+
+
+ function TObjInput.newObjData(const n:string):TObjData;
+ begin
+ result:=CObjData.create(n);
+ end;
+
+
+ procedure TObjInput.inputerror(const s : string);
+ begin
+ Comment(V_Error,s+' while reading '+InputFileName);
+ end;
+
+
+{$ifdef MEMDEBUG}
+initialization
+ memobjsymbols:=TMemDebug.create('ObjSymbols');
+ memobjsymbols.stop;
+ memobjsections:=TMemDebug.create('ObjSections');
+ memobjsections.stop;
+
+finalization
+ memobjsymbols.free;
+ memobjsections.free;
+{$endif MEMDEBUG}
+end.
diff --git a/closures/compiler/ogcoff.pas b/closures/compiler/ogcoff.pas
new file mode 100644
index 0000000000..9e4779a5b3
--- /dev/null
+++ b/closures/compiler/ogcoff.pas
@@ -0,0 +1,3158 @@
+{
+ Copyright (c) 1998-2006 by Peter Vreman
+
+ Contains the binary coff/PE reader and writer
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit ogcoff;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ { common }
+ cclasses,globtype,
+ { target }
+ systems,
+ { assembler }
+ cpuinfo,cpubase,aasmbase,assemble,link,
+ { output }
+ ogbase,
+ owbase;
+
+ const
+ PE_DATADIR_ENTRIES = 16;
+
+ type
+ tcoffpedatadir = packed record
+ vaddr : longword;
+ size : longword;
+ end;
+ tcoffheader = packed record
+ mach : word;
+ nsects : word;
+ time : longword;
+ sympos : longword;
+ syms : longword;
+ opthdr : word;
+ flag : word;
+ end;
+ tcoffpeoptheader = packed record
+ Magic : word;
+ MajorLinkerVersion : byte;
+ MinorLinkerVersion : byte;
+ tsize : longword;
+ dsize : longword;
+ bsize : longword;
+ entry : longword;
+ text_start : longword;
+{$ifndef cpu64bitaddr}
+ data_start : longword;
+{$endif cpu64bitaddr}
+ ImageBase : aword;
+ SectionAlignment : longword;
+ FileAlignment : longword;
+ MajorOperatingSystemVersion : word;
+ MinorOperatingSystemVersion : word;
+ MajorImageVersion : word;
+ MinorImageVersion : word;
+ MajorSubsystemVersion : word;
+ MinorSubsystemVersion : word;
+ Win32Version : longword;
+ SizeOfImage : longword;
+ SizeOfHeaders : longword;
+ CheckSum : longword;
+ Subsystem : word;
+ DllCharacteristics : word;
+ SizeOfStackReserve : aword;
+ SizeOfStackCommit : aword;
+ SizeOfHeapReserve : aword;
+ SizeOfHeapCommit : aword;
+ LoaderFlags : longword; { This field is obsolete }
+ NumberOfRvaAndSizes : longword;
+ DataDirectory : array[0..PE_DATADIR_ENTRIES-1] of tcoffpedatadir;
+ end;
+ tcoffsechdr = packed record
+ name : array[0..7] of char;
+ vsize : longword;
+ rvaofs : longword;
+ datasize : longword;
+ datapos : longword;
+ relocpos : longword;
+ lineno1 : longword;
+ nrelocs : word;
+ lineno2 : word;
+ flags : longword;
+ end;
+
+ TCoffObjSection = class(TObjSection)
+ private
+ orgmempos,
+ coffrelocs,
+ coffrelocpos : aword;
+ public
+ secidx : longword;
+ flags : longword;
+ constructor create(AList:TFPHashObjectList;const Aname:string;Aalign:shortint;Aoptions:TObjSectionOptions);override;
+ procedure addsymsizereloc(ofs:aword;p:TObjSymbol;symsize:aword;reloctype:TObjRelocationType);
+ procedure fixuprelocs;override;
+ end;
+
+ TDJCoffObjSection = class(TCoffObjSection)
+ constructor create(AList:TFPHashObjectList;const Aname:string;Aalign:shortint;Aoptions:TObjSectionOptions);override;
+ end;
+
+ TPECoffObjSection = class(TCoffObjSection)
+ constructor create(AList:TFPHashObjectList;const Aname:string;Aalign:shortint;Aoptions:TObjSectionOptions);override;
+ end;
+
+ TCoffObjData = class(TObjData)
+ private
+ win32 : boolean;
+{$ifdef arm}
+ eVCobj : boolean;
+{$endif arm}
+ public
+ constructor createcoff(const n:string;awin32:boolean;acObjSection:TObjSectionClass);
+ destructor destroy;override;
+ procedure CreateDebugSections;override;
+ function sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;override;
+ procedure writereloc(data:aint;len:aword;p:TObjSymbol;reloctype:TObjRelocationType);override;
+ procedure afteralloc;override;
+ end;
+
+ TDJCoffObjData = class(TCoffObjData)
+ constructor create(const n:string);override;
+ end;
+
+ TPECoffObjData = class(TCoffObjData)
+ constructor create(const n:string);override;
+ end;
+
+ TCoffObjOutput = class(tObjOutput)
+ private
+ win32 : boolean;
+ symidx : longint;
+ FCoffSyms,
+ FCoffStrs : tdynamicarray;
+ procedure write_symbol(const name:string;value:aword;section:smallint;typ,aux:byte);
+ procedure section_write_symbol(p:TObject;arg:pointer);
+ procedure section_write_relocs(p:TObject;arg:pointer);
+ procedure create_symbols(data:TObjData);
+ procedure section_set_datapos(p:TObject;arg:pointer);
+ procedure section_set_reloc_datapos(p:TObject;arg:pointer);
+ procedure section_write_header(p:TObject;arg:pointer);
+ procedure section_write_data(p:TObject;arg:pointer);
+ protected
+ function writedata(data:TObjData):boolean;override;
+ public
+ constructor createcoff(AWriter:TObjectWriter;awin32:boolean);
+ destructor destroy;override;
+ end;
+
+ TDJCoffObjOutput = class(TCoffObjOutput)
+ constructor create(AWriter:TObjectWriter);override;
+ end;
+
+ TPECoffObjOutput = class(TCoffObjOutput)
+ constructor create(AWriter:TObjectWriter);override;
+ end;
+
+ TCoffObjInput = class(tObjInput)
+ private
+ FCoffsyms,
+ FCoffStrs : tdynamicarray;
+ { Convert symidx -> TObjSymbol }
+ FSymTbl : ^TObjSymbolArray;
+ { Convert secidx -> TObjSection }
+ FSecCount : smallint;
+ FSecTbl : ^TObjSectionArray;
+ win32 : boolean;
+ function GetSection(secidx:longint):TObjSection;
+ function Read_str(strpos:longword):string;
+ procedure read_relocs(s:TCoffObjSection);
+ procedure read_symbols(objdata:TObjData);
+ procedure ObjSections_read_data(p:TObject;arg:pointer);
+ procedure ObjSections_read_relocs(p:TObject;arg:pointer);
+ public
+ constructor createcoff(awin32:boolean);
+ destructor destroy;override;
+ function ReadObjData(AReader:TObjectreader;objdata:TObjData):boolean;override;
+ end;
+
+ TDJCoffObjInput = class(TCoffObjInput)
+ constructor create;override;
+ end;
+
+ TPECoffObjInput = class(TCoffObjInput)
+ constructor create;override;
+ end;
+
+ TCoffExeSection = class(TExeSection)
+ private
+ win32 : boolean;
+ public
+ constructor createcoff(AList:TFPHashObjectList;const n:string;awin32:boolean);
+ end;
+
+ TDJCoffExeSection = class(TCoffExeSection)
+ constructor create(AList:TFPHashObjectList;const n:string);override;
+ end;
+
+ TPECoffExeSection = class(TCoffExeSection)
+ constructor create(AList:TFPHashObjectList;const n:string);override;
+ end;
+
+ TCoffexeoutput = class(texeoutput)
+ private
+ FCoffsyms,
+ FCoffStrs : tdynamicarray;
+ win32 : boolean;
+ nsects : word;
+ nsyms,
+ sympos : aword;
+ function totalheadersize:longword;
+ procedure ExeSectionList_pass2_header(p:TObject;arg:pointer);
+ procedure write_symbol(const name:string;value:aword;section:smallint;typ,aux:byte);
+ procedure globalsyms_write_symbol(p:TObject;arg:pointer);
+ procedure ExeSectionList_write_header(p:TObject;arg:pointer);
+ procedure ExeSectionList_write_data(p:TObject;arg:pointer);
+ protected
+ function writedata:boolean;override;
+ procedure Order_ObjSectionList(ObjSectionList : TFPObjectList;const aPattern:string);override;
+ public
+ constructor createcoff(awin32:boolean);
+ procedure MemPos_Header;override;
+ procedure DataPos_Header;override;
+ procedure DataPos_Symbols;override;
+ end;
+
+ TDJCoffexeoutput = class(TCoffexeoutput)
+ constructor create;override;
+ end;
+
+ TPECoffexeoutput = class(TCoffexeoutput)
+ private
+ idatalabnr : longword;
+ FRelocsGenerated : boolean;
+ procedure GenerateRelocs;
+ public
+ constructor create;override;
+ procedure GenerateLibraryImports(ImportLibraryList:TFPHashObjectList);override;
+ procedure Order_End;override;
+ procedure MemPos_ExeSection(const aname:string);override;
+ end;
+
+ TObjSymbolrec = record
+ sym : TObjSymbol;
+ orgsize : aword;
+ end;
+ TObjSymbolArray = array[0..high(word)] of TObjSymbolrec;
+ TObjSectionArray = array[0..high(smallint)] of TObjSection;
+
+ TDJCoffAssembler = class(tinternalassembler)
+ constructor create(smart:boolean);override;
+ end;
+
+ TPECoffassembler = class(tinternalassembler)
+ constructor create(smart:boolean);override;
+ end;
+
+
+ type
+ Treaddllproc = procedure(const dllname,funcname:string) of object;
+
+ const
+{$ifdef i386}
+ COFF_MAGIC = $14c;
+ COFF_OPT_MAGIC = $10b;
+ TLSDIR_SIZE = $18;
+{$endif i386}
+{$ifdef arm}
+ COFF_MAGIC = $1c0;
+ COFF_OPT_MAGIC = $10b;
+ TLSDIR_SIZE = $18;
+{$endif arm}
+{$ifdef x86_64}
+ COFF_MAGIC = $8664;
+ COFF_OPT_MAGIC = $20b;
+ TLSDIR_SIZE = $28;
+{$endif x86_64}
+ function ReadDLLImports(const dllname:string;readdllproc:Treaddllproc):boolean;
+
+implementation
+
+ uses
+{$ifdef win32}
+ Windows,
+{$endif win32}
+ SysUtils,
+ cutils,verbose,globals,
+ fmodule,aasmtai,aasmdata,
+ ogmap,
+ version
+ ;
+
+ const
+ COFF_FLAG_NORELOCS = $0001;
+ COFF_FLAG_EXE = $0002;
+ COFF_FLAG_NOLINES = $0004;
+ COFF_FLAG_NOLSYMS = $0008;
+ COFF_FLAG_AR16WR = $0080; { 16bit little endian }
+ COFF_FLAG_AR32WR = $0100; { 32bit little endian }
+ COFF_FLAG_AR32W = $0200; { 32bit big endian }
+ COFF_FLAG_DLL = $2000;
+
+ COFF_SYM_GLOBAL = 2;
+ COFF_SYM_LOCAL = 3;
+ COFF_SYM_LABEL = 6;
+ COFF_SYM_FUNCTION = 101;
+ COFF_SYM_FILE = 103;
+ COFF_SYM_SECTION = 104;
+
+ COFF_STYP_REG = $0000; { "regular": allocated, relocated, loaded }
+ COFF_STYP_DSECT = $0001; { "dummy": relocated only }
+ COFF_STYP_NOLOAD = $0002; { "noload": allocated, relocated, not loaded }
+ COFF_STYP_GROUP = $0004; { "grouped": formed of input sections }
+ COFF_STYP_PAD = $0008;
+ COFF_STYP_COPY = $0010;
+ COFF_STYP_TEXT = $0020;
+ COFF_STYP_DATA = $0040;
+ COFF_STYP_BSS = $0080;
+
+ PE_SUBSYSTEM_NATIVE = 1;
+ PE_SUBSYSTEM_WINDOWS_GUI = 2;
+ PE_SUBSYSTEM_WINDOWS_CUI = 3;
+ PE_SUBSYSTEM_WINDOWS_CE_GUI = 9;
+
+ PE_FILE_RELOCS_STRIPPED = $0001;
+ PE_FILE_EXECUTABLE_IMAGE = $0002;
+ PE_FILE_LINE_NUMS_STRIPPED = $0004;
+ PE_FILE_LOCAL_SYMS_STRIPPED = $0008;
+ PE_FILE_AGGRESSIVE_WS_TRIM = $0010;
+ PE_FILE_LARGE_ADDRESS_AWARE = $0020;
+ PE_FILE_16BIT_MACHINE = $0040;
+ PE_FILE_BYTES_REVERSED_LO = $0080;
+ PE_FILE_32BIT_MACHINE = $0100;
+ PE_FILE_DEBUG_STRIPPED = $0200;
+ PE_FILE_REMOVABLE_RUN_FROM_SWAP = $0400;
+ PE_FILE_NET_RUN_FROM_SWAP = $0800;
+ PE_FILE_SYSTEM = $1000;
+ PE_FILE_DLL = $2000;
+ PE_FILE_UP_SYSTEM_ONLY = $4000;
+ PE_FILE_BYTES_REVERSED_HI = $8000;
+
+ PE_SCN_CNT_CODE = $00000020; { Section contains code. }
+ PE_SCN_CNT_INITIALIZED_DATA = $00000040; { Section contains initialized data. }
+ PE_SCN_CNT_UNINITIALIZED_DATA = $00000080; { Section contains uninitialized data. }
+ PE_SCN_LNK_OTHER = $00000100; { Reserved. }
+ PE_SCN_LNK_INFO = $00000200; { Section contains comments or some other type of information. }
+ PE_SCN_LNK_REMOVE = $00000800; { Section contents will not become part of image. }
+ PE_SCN_LNK_COMDAT = $00001000; { Section contents comdat. }
+ PE_SCN_MEM_FARDATA = $00008000;
+ PE_SCN_MEM_PURGEABLE = $00020000;
+ PE_SCN_MEM_16BIT = $00020000;
+ PE_SCN_MEM_LOCKED = $00040000;
+ PE_SCN_MEM_PRELOAD = $00080000;
+ PE_SCN_ALIGN_MASK = $00f00000;
+ PE_SCN_ALIGN_1BYTES = $00100000;
+ PE_SCN_ALIGN_2BYTES = $00200000;
+ PE_SCN_ALIGN_4BYTES = $00300000;
+ PE_SCN_ALIGN_8BYTES = $00400000;
+ PE_SCN_ALIGN_16BYTES = $00500000; { Default alignment if no others are specified. }
+ PE_SCN_ALIGN_32BYTES = $00600000;
+ PE_SCN_ALIGN_64BYTES = $00700000;
+ PE_SCN_LNK_NRELOC_OVFL = $01000000; { Section contains extended relocations. }
+ PE_SCN_MEM_NOT_CACHED = $04000000; { Section is not cachable. }
+ PE_SCN_MEM_NOT_PAGED = $08000000; { Section is not pageable. }
+ PE_SCN_MEM_SHARED = $10000000; { Section is shareable. }
+ PE_SCN_MEM_DISCARDABLE = $02000000;
+ PE_SCN_MEM_EXECUTE = $20000000;
+ PE_SCN_MEM_READ = $40000000;
+ PE_SCN_MEM_WRITE = $80000000;
+
+ PE_DATADIR_EDATA = 0;
+ PE_DATADIR_IDATA = 1;
+ PE_DATADIR_RSRC = 2;
+ PE_DATADIR_PDATA = 3;
+ PE_DATADIR_SECURITY = 4;
+ PE_DATADIR_RELOC = 5;
+ PE_DATADIR_DEBUG = 6;
+ PE_DATADIR_DESCRIPTION = 7;
+ PE_DATADIR_SPECIAL = 8;
+ PE_DATADIR_TLS = 9;
+ PE_DATADIR_LOADCFG = 10;
+ PE_DATADIR_BOUNDIMPORT = 11;
+ PE_DATADIR_IMPORTADDRESSTABLE = 12;
+ PE_DATADIR_DELAYIMPORT = 13;
+
+{$ifdef x86_64}
+ IMAGE_REL_AMD64_ABSOLUTE = $0000; { Reference is absolute, no relocation is necessary }
+ IMAGE_REL_AMD64_ADDR64 = $0001; { 64-bit address (VA). }
+ IMAGE_REL_AMD64_ADDR32 = $0002; { 32-bit address (VA). }
+ IMAGE_REL_AMD64_ADDR32NB = $0003; { 32-bit address w/o image base (RVA). }
+ IMAGE_REL_AMD64_REL32 = $0004; { 32-bit relative address from byte following reloc }
+ IMAGE_REL_AMD64_REL32_1 = $0005; { 32-bit relative address from byte distance 1 from reloc }
+ IMAGE_REL_AMD64_REL32_2 = $0006; { 32-bit relative address from byte distance 2 from reloc }
+ IMAGE_REL_AMD64_REL32_3 = $0007; { 32-bit relative address from byte distance 3 from reloc }
+ IMAGE_REL_AMD64_REL32_4 = $0008; { 32-bit relative address from byte distance 4 from reloc }
+ IMAGE_REL_AMD64_REL32_5 = $0009; { 32-bit relative address from byte distance 5 from reloc }
+ IMAGE_REL_AMD64_SECTION = $000A; { Section index }
+ IMAGE_REL_AMD64_SECREL = $000B; { 32 bit offset from base of section containing target }
+ IMAGE_REL_AMD64_SECREL7 = $000C; { 7 bit unsigned offset from base of section containing target }
+ IMAGE_REL_AMD64_TOKEN = $000D; { 32 bit metadata token }
+ IMAGE_REL_AMD64_SREL32 = $000E; { 32 bit signed span-dependent value emitted into object }
+ IMAGE_REL_AMD64_PAIR = $000F;
+ IMAGE_REL_AMD64_SSPAN32 = $0010; { 32 bit signed span-dependent value applied at link time }
+ { Direct 32 bit sign extended,
+ win64 mingw GNU compiler
+ also generates this type
+ inside coff objects
+ We assume they are equivalent to
+ IMAGE_REL_AMD64_ADDR32 PM 2010-11-27 }
+ R_X86_64_32S = $11;
+
+{$endif x86_64}
+
+{$ifdef arm}
+ IMAGE_REL_ARM_ABSOLUTE = $0000; { No relocation required }
+ IMAGE_REL_ARM_ADDR32 = $0001; { 32 bit address }
+ IMAGE_REL_ARM_ADDR32NB = $0002; { 32 bit address w/o image base }
+ IMAGE_REL_ARM_BRANCH24 = $0003; { 24 bit offset << 2 & sign ext. }
+ IMAGE_REL_ARM_BRANCH11 = $0004; { Thumb: 2 11 bit offsets }
+ IMAGE_REL_ARM_TOKEN = $0005; { clr token }
+ IMAGE_REL_ARM_GPREL12 = $0006; { GP-relative addressing (ARM) }
+ IMAGE_REL_ARM_GPREL7 = $0007; { GP-relative addressing (Thumb) }
+ IMAGE_REL_ARM_BLX24 = $0008;
+ IMAGE_REL_ARM_BLX11 = $0009;
+ IMAGE_REL_ARM_SECTION = $000E; { Section table index }
+ IMAGE_REL_ARM_SECREL = $000F; { Offset within section }
+{$endif arm}
+
+{$ifdef i386}
+ IMAGE_REL_I386_DIR32 = 6;
+ IMAGE_REL_I386_IMAGEBASE = 7;
+ IMAGE_REL_I386_SECREL32 = 11;
+ IMAGE_REL_I386_PCRLONG = 20;
+{$endif i386}
+
+ { .reloc section fixup types }
+ IMAGE_REL_BASED_HIGHLOW = 3; { Applies the delta to the 32-bit field at Offset. }
+ IMAGE_REL_BASED_DIR64 = 10; { Applies the delta to the 64-bit field at Offset. }
+
+ type
+ coffdjoptheader=packed record
+ magic : word;
+ vstamp : word;
+ tsize : longint;
+ dsize : longint;
+ bsize : longint;
+ entry : longint;
+ text_start : longint;
+ data_start : longint;
+ end;
+ coffsectionrec=packed record
+ len : longword;
+ nrelocs : word;
+ empty : array[0..11] of char;
+ end;
+ coffreloc=packed record
+ address : longword;
+ sym : longword;
+ reloctype : word;
+ end;
+ coffsymbol=packed record
+ name : array[0..3] of char; { real is [0..7], which overlaps the strpos ! }
+ strpos : longword;
+ value : longword;
+ section : smallint;
+ empty : word;
+ typ : byte;
+ aux : byte;
+ end;
+
+ { This is defined in rtl/win/sysos.inc source }
+ tlsdirectory=packed record
+ data_start, data_end : PUInt;
+ index_pointer, callbacks_pointer : PUInt;
+ zero_fill_size : dword;
+ flags : dword;
+ end;
+
+ const
+ SymbolMaxGrow = 200*sizeof(coffsymbol);
+ StrsMaxGrow = 8192;
+
+ coffsecnames : array[TAsmSectiontype] of string[length('__DATA, __datacoal_nt,coalesced')] = ('','',
+ '.text','.data','.data','.data','.bss','.tls',
+ '.pdata',{pdata}
+ '.text', {stub}
+ '.data',
+ '.data',
+ '.data',
+ '.data',
+ '.stab','.stabstr',
+ '.idata$2','.idata$4','.idata$5','.idata$6','.idata$7','.edata',
+ '.eh_frame',
+ '.debug_frame','.debug_info','.debug_line','.debug_abbrev',
+ '.fpc',
+ '',
+ '.init',
+ '.fini',
+ '.objc_class',
+ '.objc_meta_class',
+ '.objc_cat_cls_meth',
+ '.objc_cat_inst_meth',
+ '.objc_protocol',
+ '.objc_string_object',
+ '.objc_cls_meth',
+ '.objc_inst_meth',
+ '.objc_cls_refs',
+ '.objc_message_refs',
+ '.objc_symbols',
+ '.objc_category',
+ '.objc_class_vars',
+ '.objc_instance_vars',
+ '.objc_module_info',
+ '.objc_class_names',
+ '.objc_meth_var_types',
+ '.objc_meth_var_names',
+ '.objc_selector_strs',
+ '.objc_protocol_ext',
+ '.objc_class_ext',
+ '.objc_property',
+ '.objc_image_info',
+ '.objc_cstring_object',
+ '.objc_sel_fixup',
+ '__DATA,__objc_data',
+ '__DATA,__objc_const',
+ '.objc_superrefs',
+ '__DATA, __datacoal_nt,coalesced',
+ '.objc_classlist',
+ '.objc_nlclasslist',
+ '.objc_catlist',
+ '.obcj_nlcatlist',
+ '.objc_protolist'
+ );
+
+const go32v2stub : array[0..2047] of byte=(
+ $4D,$5A,$00,$00,$04,$00,$00,$00,$20,$00,$27,$00,$FF,$FF,$00,
+ $00,$60,$07,$00,$00,$54,$00,$00,$00,$00,$00,$00,$00,$0D,$0A,
+ $73,$74,$75,$62,$2E,$68,$20,$67,$65,$6E,$65,$72,$61,$74,$65,
+ $64,$20,$66,$72,$6F,$6D,$20,$73,$74,$75,$62,$2E,$61,$73,$6D,
+ $20,$62,$79,$20,$64,$6A,$61,$73,$6D,$2C,$20,$6F,$6E,$20,$54,
+ $68,$75,$20,$44,$65,$63,$20,$20,$39,$20,$31,$30,$3A,$35,$39,
+ $3A,$33,$31,$20,$31,$39,$39,$39,$0D,$0A,$54,$68,$65,$20,$53,
+ $54,$55,$42,$2E,$45,$58,$45,$20,$73,$74,$75,$62,$20,$6C,$6F,
+ $61,$64,$65,$72,$20,$69,$73,$20,$43,$6F,$70,$79,$72,$69,$67,
+ $68,$74,$20,$28,$43,$29,$20,$31,$39,$39,$33,$2D,$31,$39,$39,
+ $35,$20,$44,$4A,$20,$44,$65,$6C,$6F,$72,$69,$65,$2E,$20,$0D,
+ $0A,$50,$65,$72,$6D,$69,$73,$73,$69,$6F,$6E,$20,$67,$72,$61,
+ $6E,$74,$65,$64,$20,$74,$6F,$20,$75,$73,$65,$20,$66,$6F,$72,
+ $20,$61,$6E,$79,$20,$70,$75,$72,$70,$6F,$73,$65,$20,$70,$72,
+ $6F,$76,$69,$64,$65,$64,$20,$74,$68,$69,$73,$20,$63,$6F,$70,
+ $79,$72,$69,$67,$68,$74,$20,$0D,$0A,$72,$65,$6D,$61,$69,$6E,
+ $73,$20,$70,$72,$65,$73,$65,$6E,$74,$20,$61,$6E,$64,$20,$75,
+ $6E,$6D,$6F,$64,$69,$66,$69,$65,$64,$2E,$20,$0D,$0A,$54,$68,
+ $69,$73,$20,$6F,$6E,$6C,$79,$20,$61,$70,$70,$6C,$69,$65,$73,
+ $20,$74,$6F,$20,$74,$68,$65,$20,$73,$74,$75,$62,$2C,$20,$61,
+ $6E,$64,$20,$6E,$6F,$74,$20,$6E,$65,$63,$65,$73,$73,$61,$72,
+ $69,$6C,$79,$20,$74,$68,$65,$20,$77,$68,$6F,$6C,$65,$20,$70,
+ $72,$6F,$67,$72,$61,$6D,$2E,$0A,$0D,$0A,$24,$49,$64,$3A,$20,
+ $73,$74,$75,$62,$2E,$61,$73,$6D,$20,$62,$75,$69,$6C,$74,$20,
+ $31,$32,$2F,$30,$39,$2F,$39,$39,$20,$31,$30,$3A,$35,$39,$3A,
+ $33,$31,$20,$62,$79,$20,$64,$6A,$61,$73,$6D,$20,$24,$0A,$0D,
+ $0A,$40,$28,$23,$29,$20,$73,$74,$75,$62,$2E,$61,$73,$6D,$20,
+ $62,$75,$69,$6C,$74,$20,$31,$32,$2F,$30,$39,$2F,$39,$39,$20,
+ $31,$30,$3A,$35,$39,$3A,$33,$31,$20,$62,$79,$20,$64,$6A,$61,
+ $73,$6D,$0A,$0D,$0A,$1A,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+ $00,$00,$67,$6F,$33,$32,$73,$74,$75,$62,$2C,$20,$76,$20,$32,
+ $2E,$30,$32,$54,$00,$00,$00,$00,$00,$08,$00,$00,$00,$00,$00,
+ $00,$00,$00,$00,$00,$40,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$43,$57,$53,$44,$50,
+ $4D,$49,$2E,$45,$58,$45,$00,$00,$00,$00,$00,$0E,$1F,$8C,$1E,
+ $24,$00,$8C,$06,$60,$07,$FC,$B4,$30,$CD,$21,$3C,$03,$73,$08,
+ $B0,$6D,$BA,$A7,$05,$E9,$D4,$03,$A2,$69,$08,$BE,$20,$00,$8B,
+ $04,$09,$C0,$75,$02,$B4,$FE,$BB,$70,$08,$39,$C3,$73,$02,$89,
+ $C3,$89,$1C,$FE,$C7,$B9,$04,$FF,$D3,$EB,$B4,$4A,$CD,$21,$73,
+ $08,$D3,$E3,$FE,$CF,$89,$1C,$EB,$D8,$26,$8E,$06,$2C,$00,$31,
+ $FF,$30,$C0,$A9,$F2,$AE,$26,$81,$3D,$50,$41,$75,$15,$AF,$26,
+ $81,$3D,$54,$48,$75,$0D,$AF,$26,$80,$3D,$3D,$75,$06,$47,$89,
+ $3E,$8C,$04,$4F,$AE,$75,$DF,$AF,$B4,$3E,$BB,$13,$00,$CD,$21,
+ $B4,$3E,$BB,$12,$00,$CD,$21,$06,$57,$31,$C9,$74,$12,$B0,$6E,
+ $BA,$7E,$05,$E9,$5E,$03,$09,$C9,$75,$F4,$41,$E8,$A1,$03,$72,
+ $EE,$B8,$87,$16,$CD,$2F,$09,$C0,$75,$ED,$80,$E3,$01,$74,$E8,
+ $89,$3E,$00,$06,$8C,$06,$02,$06,$89,$36,$04,$06,$5F,$07,$E8,
+ $D3,$02,$89,$3E,$2A,$00,$89,$36,$62,$07,$80,$3E,$2C,$00,$00,
+ $74,$23,$B9,$08,$00,$BF,$2C,$00,$8A,$05,$47,$08,$C0,$74,$05,
+ $88,$07,$43,$E2,$F4,$66,$C7,$07,$2E,$45,$58,$45,$83,$C3,$04,
+ $C6,$07,$00,$89,$1E,$62,$07,$B8,$00,$3D,$BA,$64,$07,$CD,$21,
+ $0F,$82,$B3,$02,$A3,$06,$06,$89,$C3,$B9,$06,$00,$BA,$B5,$07,
+ $B4,$3F,$CD,$21,$31,$D2,$31,$C9,$A1,$B5,$07,$3D,$4C,$01,$74,
+ $1B,$3D,$4D,$5A,$0F,$85,$98,$02,$8B,$16,$B9,$07,$C1,$E2,$09,
+ $8B,$1E,$B7,$07,$09,$DB,$74,$05,$80,$EE,$02,$01,$DA,$89,$16,
+ $BB,$07,$89,$0E,$BD,$07,$B8,$00,$42,$8B,$1E,$06,$06,$CD,$21,
+ $B9,$A8,$00,$BA,$BF,$07,$B4,$3F,$CD,$21,$3D,$A8,$00,$75,$06,
+ $81,$3E,$BF,$07,$4C,$01,$0F,$85,$61,$02,$66,$A1,$E3,$07,$66,
+ $A3,$10,$06,$66,$8B,$0E,$BB,$07,$66,$A1,$03,$08,$66,$01,$C8,
+ $66,$A3,$08,$06,$66,$A1,$2B,$08,$66,$01,$C8,$66,$A3,$0C,$06,
+ $66,$8B,$1E,$4B,$08,$66,$A1,$4F,$08,$66,$01,$C3,$66,$B8,$01,
+ $00,$01,$00,$66,$39,$C3,$73,$03,$66,$89,$C3,$66,$81,$C3,$FF,
+ $FF,$00,$00,$31,$DB,$66,$89,$1E,$1C,$00,$E8,$F5,$02,$8B,$1E,
+ $04,$06,$09,$DB,$74,$0A,$B4,$48,$CD,$21,$0F,$82,$15,$02,$8E,
+ $C0,$E8,$08,$03,$B8,$01,$00,$FF,$1E,$00,$06,$0F,$82,$0F,$02,
+ $8C,$06,$26,$00,$8C,$0E,$28,$00,$8C,$D8,$A3,$22,$00,$8E,$C0,
+ $31,$C0,$B9,$01,$00,$CD,$31,$72,$07,$A3,$14,$06,$31,$C0,$CD,
+ $31,$0F,$82,$F3,$01,$A3,$16,$06,$66,$8B,$0E,$1C,$00,$B8,$01,
+ $05,$8B,$1E,$1E,$00,$CD,$31,$0F,$82,$E5,$01,$89,$1E,$1A,$06,
+ $89,$0E,$18,$06,$89,$36,$1A,$00,$89,$3E,$18,$00,$B8,$07,$00,
+ $8B,$1E,$14,$06,$8B,$0E,$1A,$06,$8B,$16,$18,$06,$CD,$31,$B8,
+ $09,$00,$8C,$C9,$83,$E1,$03,$C1,$E1,$05,$51,$81,$C9,$9B,$C0,
+ $CD,$31,$B8,$08,$00,$8B,$0E,$1E,$00,$49,$BA,$FF,$FF,$CD,$31,
+ $B8,$07,$00,$8B,$1E,$16,$06,$8B,$0E,$1A,$06,$8B,$16,$18,$06,
+ $CD,$31,$B8,$09,$00,$59,$81,$C9,$93,$C0,$CD,$31,$B8,$08,$00,
+ $8B,$0E,$1E,$00,$49,$BA,$FF,$FF,$CD,$31,$B8,$00,$01,$BB,$00,
+ $0F,$CD,$31,$73,$10,$3D,$08,$00,$0F,$85,$73,$01,$B8,$00,$01,
+ $CD,$31,$0F,$82,$6A,$01,$A3,$1C,$06,$89,$16,$1E,$06,$C1,$E3,
+ $04,$89,$1E,$20,$06,$66,$8B,$36,$08,$06,$66,$8B,$3E,$FB,$07,
+ $66,$8B,$0E,$FF,$07,$E8,$49,$00,$66,$8B,$36,$0C,$06,$66,$8B,
+ $3E,$23,$08,$66,$8B,$0E,$27,$08,$E8,$37,$00,$8E,$06,$16,$06,
+ $66,$8B,$3E,$4B,$08,$66,$8B,$0E,$4F,$08,$66,$31,$C0,$66,$C1,
+ $E9,$02,$67,$F3,$66,$AB,$B4,$3E,$8B,$1E,$06,$06,$CD,$21,$B8,
+ $01,$01,$8B,$16,$1E,$06,$CD,$31,$1E,$0F,$A1,$8E,$1E,$16,$06,
+ $66,$64,$FF,$2E,$10,$06,$66,$89,$F0,$66,$25,$FF,$01,$00,$00,
+ $66,$01,$C1,$29,$C6,$66,$29,$C7,$66,$89,$0E,$26,$06,$66,$89,
+ $3E,$22,$06,$E8,$0F,$01,$89,$36,$3E,$06,$66,$C1,$EE,$10,$89,
+ $36,$42,$06,$8B,$1E,$06,$06,$89,$1E,$3A,$06,$C7,$06,$46,$06,
+ $00,$42,$E8,$03,$01,$A1,$1C,$06,$A3,$4E,$06,$C7,$06,$3E,$06,
+ $00,$00,$C6,$06,$47,$06,$3F,$A1,$28,$06,$09,$C0,$75,$09,$A1,
+ $26,$06,$3B,$06,$20,$06,$76,$03,$A1,$20,$06,$A3,$42,$06,$E8,
+ $D9,$00,$66,$31,$C9,$8B,$0E,$46,$06,$66,$8B,$3E,$22,$06,$66,
+ $01,$0E,$22,$06,$66,$29,$0E,$26,$06,$66,$31,$F6,$C1,$E9,$02,
+ $1E,$06,$8E,$06,$16,$06,$8E,$1E,$1E,$06,$67,$F3,$66,$A5,$07,
+ $1F,$66,$03,$0E,$26,$06,$75,$AF,$C3,$3C,$3A,$74,$06,$3C,$2F,
+ $74,$02,$3C,$5C,$C3,$BE,$64,$07,$89,$F3,$26,$8A,$05,$47,$88,
+ $04,$38,$E0,$74,$0E,$08,$C0,$74,$0A,$46,$E8,$DE,$FF,$75,$EC,
+ $89,$F3,$74,$E8,$C3,$B0,$66,$BA,$48,$05,$EB,$0C,$B0,$67,$BA,
+ $55,$05,$EB,$05,$B0,$68,$BA,$5F,$05,$52,$8B,$1E,$62,$07,$C6,
+ $07,$24,$BB,$64,$07,$EB,$28,$E8,$F5,$00,$B0,$69,$BA,$99,$05,
+ $EB,$1A,$B0,$6A,$BA,$B2,$05,$EB,$13,$B0,$6B,$BA,$C4,$05,$EB,
+ $0C,$B0,$6C,$BA,$D6,$05,$EB,$05,$B0,$69,$BA,$99,$05,$52,$BB,
+ $3B,$05,$E8,$15,$00,$5B,$E8,$11,$00,$BB,$67,$04,$E8,$0B,$00,
+ $B4,$4C,$CD,$21,$43,$50,$B4,$02,$CD,$21,$58,$8A,$17,$80,$FA,
+ $24,$75,$F2,$C3,$0D,$0A,$24,$50,$51,$57,$31,$C0,$BF,$2A,$06,
+ $B9,$19,$00,$F3,$AB,$5F,$59,$58,$C3,$B8,$00,$03,$BB,$21,$00,
+ $31,$C9,$66,$BF,$2A,$06,$00,$00,$CD,$31,$C3,$00,$00,$30,$E4,
+ $E8,$4E,$FF,$89,$DE,$8B,$3E,$8C,$04,$EB,$17,$B4,$3B,$E8,$41,
+ $FF,$81,$FE,$64,$07,$74,$12,$8A,$44,$FF,$E8,$2A,$FF,$74,$04,
+ $C6,$04,$5C,$46,$E8,$03,$00,$72,$E4,$C3,$E8,$34,$00,$BB,$44,
+ $00,$8A,$07,$88,$04,$43,$46,$08,$C0,$75,$F6,$06,$57,$1E,$07,
+ $E8,$9B,$FF,$BB,$2A,$06,$8C,$5F,$04,$89,$5F,$02,$BA,$64,$07,
+ $B8,$00,$4B,$CD,$21,$5F,$07,$72,$09,$B4,$4D,$CD,$21,$2D,$00,
+ $03,$F7,$D8,$EB,$28,$80,$3E,$69,$08,$05,$72,$20,$B8,$00,$58,
+ $CD,$21,$A2,$67,$08,$B8,$02,$58,$CD,$21,$A2,$68,$08,$B8,$01,
+ $58,$BB,$80,$00,$CD,$21,$B8,$03,$58,$BB,$01,$00,$CD,$21,$C3,
+ $9C,$80,$3E,$69,$08,$05,$72,$1A,$50,$53,$B8,$03,$58,$8A,$1E,
+ $68,$08,$30,$FF,$CD,$21,$B8,$01,$58,$8A,$1E,$67,$08,$30,$FF,
+ $CD,$21,$5B,$58,$9D,$C3,$4C,$6F,$61,$64,$20,$65,$72,$72,$6F,
+ $72,$3A,$20,$24,$3A,$20,$63,$61,$6E,$27,$74,$20,$6F,$70,$65,
+ $6E,$24,$3A,$20,$6E,$6F,$74,$20,$45,$58,$45,$24,$3A,$20,$6E,
+ $6F,$74,$20,$43,$4F,$46,$46,$20,$28,$43,$68,$65,$63,$6B,$20,
+ $66,$6F,$72,$20,$76,$69,$72,$75,$73,$65,$73,$29,$24,$6E,$6F,
+ $20,$44,$50,$4D,$49,$20,$2D,$20,$47,$65,$74,$20,$63,$73,$64,
+ $70,$6D,$69,$2A,$62,$2E,$7A,$69,$70,$24,$6E,$6F,$20,$44,$4F,
+ $53,$20,$6D,$65,$6D,$6F,$72,$79,$24,$6E,$65,$65,$64,$20,$44,
+ $4F,$53,$20,$33,$24,$63,$61,$6E,$27,$74,$20,$73,$77,$69,$74,
+ $63,$68,$20,$6D,$6F,$64,$65,$24,$6E,$6F,$20,$44,$50,$4D,$49,
+ $20,$73,$65,$6C,$65,$63,$74,$6F,$72,$73,$24,$6E,$6F,$20,$44,
+ $50,$4D,$49,$20,$6D,$65,$6D,$6F,$72,$79,$24,$90,$90,$90,$90,
+ $90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,$90,
+ $90,$90,$90,$90,$90,$90,$90,$90);
+
+const win32stub : array[0..127] of byte=(
+ $4D,$5A,$90,$00,$03,$00,$00,$00,$04,$00,$00,$00,$FF,$FF,$00,$00,
+ $B8,$00,$00,$00,$00,$00,$00,$00,$40,$00,$00,$00,$00,$00,$00,$00,
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
+ $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$80,$00,$00,$00,
+ $0E,$1F,$BA,$0E,$00,$B4,$09,$CD,$21,$B8,$01,$4C,$CD,$21,$54,$68,
+ $69,$73,$20,$70,$72,$6F,$67,$72,$61,$6D,$20,$63,$61,$6E,$6E,$6F,
+ $74,$20,$62,$65,$20,$72,$75,$6E,$20,$69,$6E,$20,$44,$4F,$53,$20,
+ $6D,$6F,$64,$65,$2E,$0D,$0D,$0A,$24,$00,$00,$00,$00,$00,$00,$00);
+
+const pemagic : array[0..3] of byte = (
+ $50,$45,$00,$00);
+
+{****************************************************************************
+ Helpers
+****************************************************************************}
+
+ function djencodesechdrflags(aoptions:TObjSectionOptions):longword;
+ begin
+ if (oso_load in aoptions) then
+ begin
+ if oso_executable in aoptions then
+ result:=COFF_STYP_TEXT
+ else if not(oso_data in aoptions) then
+ result:=COFF_STYP_BSS
+ else
+ result:=COFF_STYP_DATA;
+ end
+ else
+ result:=COFF_STYP_REG;
+ end;
+
+
+ function djdecodesechdrflags(const aname:string;flags:longword):TObjSectionOptions;
+ begin
+ result:=[];
+ if flags and COFF_STYP_TEXT<>0 then
+ result:=[oso_data,oso_load,oso_executable]
+ else if flags and COFF_STYP_BSS<>0 then
+ result:=[oso_load]
+ else if flags and COFF_STYP_DATA<>0 then
+ result:=[oso_data,oso_load]
+ else
+ result:=[oso_data]
+ end;
+
+
+ function peencodesechdrflags(aoptions:TObjSectionOptions;aalign:shortint):longword;
+ begin
+ result:=0;
+ if (oso_load in aoptions) then
+ begin
+ if oso_executable in aoptions then
+ result:=result or PE_SCN_CNT_CODE or PE_SCN_MEM_EXECUTE
+ else
+ begin
+ if (oso_data in aoptions) then
+ result:=result or PE_SCN_CNT_INITIALIZED_DATA
+ else
+ result:=result or PE_SCN_CNT_UNINITIALIZED_DATA;
+ end;
+ if oso_write in aoptions then
+ result:=result or PE_SCN_MEM_WRITE or PE_SCN_MEM_READ
+ else
+ result:=result or PE_SCN_MEM_READ;
+ end
+ else
+ result:=result or PE_SCN_MEM_DISCARDABLE;
+ case aalign of
+ 1 : result:=result or PE_SCN_ALIGN_1BYTES;
+ 2 : result:=result or PE_SCN_ALIGN_2BYTES;
+ 4 : result:=result or PE_SCN_ALIGN_4BYTES;
+ 8 : result:=result or PE_SCN_ALIGN_8BYTES;
+ 16 : result:=result or PE_SCN_ALIGN_16BYTES;
+ 32 : result:=result or PE_SCN_ALIGN_32BYTES;
+ 64 : result:=result or PE_SCN_ALIGN_64BYTES;
+ else result:=result or PE_SCN_ALIGN_16BYTES;
+ end;
+ end;
+
+
+ procedure pedecodesechdrflags(const aname:string;flags:longword;out aoptions:TObjSectionOptions;out aalign:shortint);
+ var
+ alignflag : longword;
+ begin
+ aoptions:=[];
+ if flags and PE_SCN_CNT_CODE<>0 then
+ include(aoptions,oso_executable);
+ if flags and PE_SCN_MEM_DISCARDABLE<>0 then
+ include(aoptions,oso_debug);
+ if flags and PE_SCN_CNT_UNINITIALIZED_DATA=0 then
+ include(aoptions,oso_data);
+ if (flags and PE_SCN_LNK_REMOVE<>0) or
+ (flags and PE_SCN_MEM_DISCARDABLE<>0) then
+ include(aoptions,oso_noload)
+ else
+ include(aoptions,oso_load);
+ { read/write }
+ if flags and PE_SCN_MEM_WRITE<>0 then
+ include(aoptions,oso_write)
+ else
+ include(aoptions,oso_readonly);
+ { alignment }
+ alignflag:=flags and PE_SCN_ALIGN_MASK;
+ if alignflag=PE_SCN_ALIGN_64BYTES then
+ aalign:=64
+ else if alignflag=PE_SCN_ALIGN_32BYTES then
+ aalign:=32
+ else if alignflag=PE_SCN_ALIGN_16BYTES then
+ aalign:=16
+ else if alignflag=PE_SCN_ALIGN_8BYTES then
+ aalign:=8
+ else if alignflag=PE_SCN_ALIGN_4BYTES then
+ aalign:=4
+ else if alignflag=PE_SCN_ALIGN_2BYTES then
+ aalign:=2
+ else if alignflag=PE_SCN_ALIGN_1BYTES then
+ aalign:=1
+ else if alignflag=0 then
+ aalign:=0
+ else
+ Internalerror(2009050401);
+ end;
+
+
+{****************************************************************************
+ TCoffObjSection
+****************************************************************************}
+
+ constructor TCoffObjSection.create(AList:TFPHashObjectList;const aname:string;aalign:shortint;aoptions:TObjSectionOptions);
+ begin
+ inherited create(AList,aname,aalign,aoptions);
+ end;
+
+
+ procedure TCoffObjSection.addsymsizereloc(ofs:aword;p:TObjSymbol;symsize:aword;reloctype:TObjRelocationType);
+ begin
+ ObjRelocations.Add(TObjRelocation.createsymbolsize(ofs,p,symsize,reloctype));
+ end;
+
+
+ procedure TCoffObjSection.fixuprelocs;
+ var
+ i,zero,address_size : longint;
+ objreloc : TObjRelocation;
+ address,
+ relocval : aint;
+ relocsec : TObjSection;
+{$ifdef cpu64bitaddr}
+ s : string;
+{$endif cpu64bitaddr}
+ begin
+ if (ObjRelocations.Count>0) and
+ not assigned(data) then
+ internalerror(200205183);
+ for i:=0 to ObjRelocations.Count-1 do
+ begin
+ objreloc:=TObjRelocation(ObjRelocations[i]);
+ address_size:=4;
+ case objreloc.typ of
+ RELOC_NONE:
+ continue;
+ RELOC_ZERO:
+ begin
+ data.Seek(objreloc.dataoffset);
+ zero:=0;
+ data.Write(zero,4);
+ continue;
+ end;
+{$ifdef cpu64bitaddr}
+ RELOC_ABSOLUTE:
+ address_size:=8;
+{$endif cpu64bitaddr}
+ end;
+
+ address:=0;
+ data.Seek(objreloc.dataoffset);
+ data.Read(address,address_size);
+ if assigned(objreloc.symbol) then
+ begin
+ relocsec:=objreloc.symbol.objsection;
+ relocval:=objreloc.symbol.address;
+ end
+ else
+ if assigned(objreloc.objsection) then
+ begin
+ relocsec:=objreloc.objsection;
+ relocval:=objreloc.objsection.mempos
+ end
+ else
+ internalerror(200205183);
+ { Only debug sections are allowed to have relocs pointing to unused sections }
+ if not relocsec.used and not (oso_debug in secoptions) then
+ internalerror(200603061);
+
+ if relocsec.used then
+ case objreloc.typ of
+ RELOC_RELATIVE :
+ begin
+ address:=address-mempos+relocval;
+ if TCoffObjData(objdata).win32 then
+ dec(address,objreloc.dataoffset+4);
+ end;
+ RELOC_RVA:
+ begin
+ { fixup address when the symbol was known in defined object }
+ if (relocsec.objdata=objdata) then
+ dec(address,TCoffObjSection(relocsec).orgmempos);
+{$ifdef arm}
+ if (relocsec.objdata=objdata) and not TCoffObjData(objdata).eVCobj then
+ inc(address, relocsec.MemPos)
+ else
+{$endif arm}
+ inc(address,relocval);
+ end;
+ RELOC_SECREL32 :
+ begin
+ { fixup address when the symbol was known in defined object }
+ if (relocsec.objdata=objdata) then
+ dec(address,relocsec.ExeSection.MemPos);
+ inc(address,relocval);
+ end;
+{$ifdef arm}
+ RELOC_RELATIVE_24:
+ begin
+ relocval:=longint(relocval - mempos - objreloc.dataoffset) shr 2 - 2;
+ address:=address or (relocval and $ffffff);
+ relocval:=relocval shr 24;
+ if (relocval<>$3f) and (relocval<>0) then
+ internalerror(200606085); { offset overflow }
+ end;
+{$endif arm}
+{$ifdef x86_64}
+ { 64 bit coff only }
+ RELOC_RELATIVE_1:
+ begin
+ address:=address-mempos+relocval;
+ dec(address,objreloc.dataoffset+1);
+ end;
+ RELOC_RELATIVE_2:
+ begin
+ address:=address-mempos+relocval;
+ dec(address,objreloc.dataoffset+2);
+ end;
+ RELOC_RELATIVE_3:
+ begin
+ address:=address-mempos+relocval;
+ dec(address,objreloc.dataoffset+3);
+ end;
+ RELOC_RELATIVE_4:
+ begin
+ address:=address-mempos+relocval;
+ dec(address,objreloc.dataoffset+4);
+ end;
+ RELOC_RELATIVE_5:
+ begin
+ address:=address-mempos+relocval;
+ dec(address,objreloc.dataoffset+5);
+ end;
+ RELOC_ABSOLUTE32,
+{$endif x86_64}
+ RELOC_ABSOLUTE :
+ begin
+ if oso_common in relocsec.secoptions then
+ dec(address,objreloc.orgsize)
+ else
+ begin
+ { fixup address when the symbol was known in defined object }
+ if (relocsec.objdata=objdata) then
+ dec(address,TCoffObjSection(relocsec).orgmempos);
+ end;
+{$ifdef arm}
+ if (relocsec.objdata=objdata) and not TCoffObjData(objdata).eVCobj then
+ inc(address, relocsec.MemPos)
+ else
+{$endif arm}
+ inc(address,relocval);
+ inc(address,relocsec.objdata.imagebase);
+ end;
+ else
+ internalerror(200604014);
+ end
+ else
+ address:=0; { Relocation in debug section points to unused section, which is eliminated by linker }
+
+ data.Seek(objreloc.dataoffset);
+ data.Write(address,address_size);
+{$ifdef cpu64bitaddr}
+ if (objreloc.typ = RELOC_ABSOLUTE32) and (name <> '.stab') then
+ begin
+ if assigned(objreloc.symbol) then
+ s:=objreloc.symbol.Name
+ else
+ s:=objreloc.objsection.Name;
+ Message2(link_w_32bit_absolute_reloc, ObjData.Name, s);
+ end;
+{$endif cpu64bitaddr}
+ end;
+ {for size = 0 data is not valid PM }
+ if assigned(data) and (data.size <> size) then
+ internalerror(2010092801);
+ end;
+
+
+
+{****************************************************************************
+ TDJCoffObjSection
+****************************************************************************}
+
+ constructor TDJCoffObjSection.create(AList:TFPHashObjectList;const aname:string;aalign:shortint;aoptions:TObjSectionOptions);
+ begin
+ inherited create(alist,aname,aalign,aoptions);
+ end;
+
+
+{****************************************************************************
+ TPECoffObjSection
+****************************************************************************}
+
+ constructor TPECoffObjSection.create(AList:TFPHashObjectList;const aname:string;aalign:shortint;aoptions:TObjSectionOptions);
+ begin
+ inherited create(alist,aname,aalign,aoptions);
+ end;
+
+
+{****************************************************************************
+ TCoffObjData
+****************************************************************************}
+
+ constructor TCoffObjData.createcoff(const n:string;awin32:boolean;acObjSection:TObjSectionClass);
+ begin
+ inherited create(n);
+ CObjSection:=ACObjSection;
+ win32:=awin32;
+ { we need at least the following 3 ObjSections }
+ createsection(sec_code);
+ createsection(sec_data);
+ createsection(sec_bss);
+ if tf_section_threadvars in target_info.flags then
+ createsection(sec_threadvar);
+ end;
+
+
+ destructor TCoffObjData.destroy;
+ begin
+ inherited destroy;
+ end;
+
+
+ function TCoffObjData.sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;
+ var
+ sep : string[3];
+ secname : string;
+ begin
+ { section type user gives the user full controll on the section name }
+ if atype=sec_user then
+ result:=aname
+ else
+ begin
+ secname:=coffsecnames[atype];
+ if create_smartlink_sections and
+ (aname<>'') then
+ begin
+ case aorder of
+ secorder_begin :
+ sep:='.b_';
+ secorder_end :
+ sep:='.z_';
+ else
+ sep:='.n_';
+ end;
+ result:=secname+sep+aname
+ end
+ else
+ result:=secname;
+ end;
+ end;
+
+
+ procedure TCoffObjData.CreateDebugSections;
+ begin
+ if target_dbg.id=dbg_stabs then
+ begin
+ stabssec:=createsection(sec_stab);
+ stabstrsec:=createsection(sec_stabstr);
+ end;
+ end;
+
+
+ procedure TCoffObjData.writereloc(data:aint;len:aword;p:TObjSymbol;reloctype:TObjRelocationType);
+ var
+ curraddr,
+ symaddr : aword;
+ begin
+ if CurrObjSec=nil then
+ internalerror(200403072);
+ if assigned(p) then
+ begin
+ { current address }
+ curraddr:=CurrObjSec.mempos+CurrObjSec.Size;
+ { external/common symbols don't have a fixed memory position yet }
+ if (p.bind=AB_COMMON) then
+ begin
+ { For go32v2 we need to use the size as address }
+ if not win32 then
+ symaddr:=p.size
+ else
+ symaddr:=0;
+ end
+ else
+ symaddr:=p.address;
+ { no symbol relocation need inside a section }
+ if (p.objsection=CurrObjSec) and
+ (p.bind<>AB_COMMON) then
+ begin
+ case reloctype of
+ RELOC_ABSOLUTE :
+ begin
+ CurrObjSec.addsectionreloc(curraddr,CurrObjSec,RELOC_ABSOLUTE);
+ inc(data,symaddr);
+ end;
+{$ifdef cpu64bitaddr}
+ RELOC_ABSOLUTE32 :
+ begin
+ CurrObjSec.addsectionreloc(curraddr,CurrObjSec,RELOC_ABSOLUTE32);
+ inc(data,symaddr);
+ end;
+{$endif cpu64bitaddr}
+ RELOC_RELATIVE :
+ begin
+ //inc(data,symaddr-len-CurrObjSec.Size);
+ data:=data+symaddr-len-CurrObjSec.Size;
+ end;
+ RELOC_RVA,
+ RELOC_SECREL32 :
+ begin
+ CurrObjSec.addsectionreloc(curraddr,CurrObjSec,reloctype);
+ inc(data,symaddr);
+ end;
+ else
+ internalerror(200604013);
+ end;
+ end
+ else
+ begin
+ if (p.objsection<>nil) and
+ (p.bind<>AB_COMMON) and
+ (reloctype<>RELOC_RELATIVE) then
+ CurrObjSec.addsectionreloc(curraddr,p.objsection,reloctype)
+ else
+ CurrObjSec.addsymreloc(curraddr,p,reloctype);
+ if (not win32) or
+ ((reloctype<>RELOC_RELATIVE) and (p.objsection<>nil)) then
+ inc(data,symaddr);
+ if reloctype=RELOC_RELATIVE then
+ begin
+ if win32 then
+ dec(data,len-4)
+ else
+ dec(data,len+CurrObjSec.Size);
+ end;
+ end;
+ end
+ else
+ begin
+ if reloctype=RELOC_RVA then
+ internalerror(200603033);
+ end;
+ CurrObjSec.write(data,len);
+ end;
+
+
+ procedure TCoffObjData.afteralloc;
+ var
+ mempos : qword;
+ i : longint;
+ begin
+ inherited afteralloc;
+ { DJ Coff requires mempositions }
+ if not win32 then
+ begin
+ mempos:=0;
+ for i:=0 to ObjSectionList.Count-1 do
+ mempos:=TObjSection(ObjSectionList[i]).setmempos(mempos);
+ end;
+ end;
+
+
+{****************************************************************************
+ TDJCoffObjData
+****************************************************************************}
+
+ constructor TDJCoffObjData.create(const n:string);
+ begin
+ inherited createcoff(n,false,TDJCoffObjSection);
+ end;
+
+
+{****************************************************************************
+ TPECoffObjData
+****************************************************************************}
+
+ constructor TPECoffObjData.create(const n:string);
+ begin
+ inherited createcoff(n,true,TPECoffObjSection);
+ end;
+
+
+{****************************************************************************
+ TCoffObjOutput
+****************************************************************************}
+
+ constructor TCoffObjOutput.createcoff(AWriter:TObjectWriter;awin32:boolean);
+ begin
+ inherited create(AWriter);
+ win32:=awin32;
+ end;
+
+
+ destructor TCoffObjOutput.destroy;
+ begin
+ if assigned(FCoffSyms) then
+ FCoffSyms.free;
+ if assigned(FCoffStrs) then
+ FCoffStrs.free;
+ inherited destroy;
+ end;
+
+
+ procedure TCoffObjOutput.write_symbol(const name:string;value:aword;section:smallint;typ,aux:byte);
+ var
+ sym : coffsymbol;
+ begin
+ FillChar(sym,sizeof(sym),0);
+ { symbolname }
+ if length(name)>8 then
+ begin
+ sym.strpos:=FCoffStrs.size+4;
+ FCoffStrs.writestr(name);
+ FCoffStrs.writestr(#0);
+ end
+ else
+ move(name[1],sym.name,length(name));
+ sym.value:=value;
+ sym.section:=section;
+ sym.typ:=typ;
+ sym.aux:=aux;
+ inc(symidx);
+ FCoffSyms.write(sym,sizeof(sym));
+ end;
+
+
+ procedure TCoffObjOutput.section_write_symbol(p:TObject;arg:pointer);
+ var
+ secrec : coffsectionrec;
+ begin
+ with TCoffObjSection(p) do
+ begin
+ secidx:=symidx div 2;
+ secsymidx:=symidx;
+ write_symbol(name,mempos,secidx,COFF_SYM_SECTION,1);
+ { AUX }
+ fillchar(secrec,sizeof(secrec),0);
+ secrec.len:=Size;
+ secrec.nrelocs:=ObjRelocations.count;
+ inc(symidx);
+ FCoffSyms.write(secrec,sizeof(secrec));
+ end;
+ end;
+
+
+ procedure TCoffObjOutput.section_write_relocs(p:TObject;arg:pointer);
+ var
+ i : longint;
+ rel : coffreloc;
+ objreloc : TObjRelocation;
+ begin
+ for i:=0 to TObjSection(p).ObjRelocations.Count-1 do
+ begin
+ objreloc:=TObjRelocation(TObjSection(p).ObjRelocations[i]);
+ rel.address:=objreloc.dataoffset;
+ if assigned(objreloc.symbol) then
+ begin
+ if (objreloc.symbol.bind=AB_LOCAL) then
+ rel.sym:=objreloc.symbol.objsection.secsymidx
+ else
+ begin
+ if objreloc.symbol.symidx=-1 then
+ internalerror(200602233);
+ rel.sym:=objreloc.symbol.symidx;
+ end;
+ end
+ else
+ begin
+ if objreloc.objsection<>nil then
+ rel.sym:=objreloc.objsection.secsymidx
+ else
+ rel.sym:=0;
+ end;
+ case objreloc.typ of
+{$ifdef arm}
+ RELOC_ABSOLUTE :
+ rel.reloctype:=IMAGE_REL_ARM_ADDR32;
+
+ { I've no idea if this is correct (FK):
+ RELOC_RELATIVE :
+ rel.reloctype:=IMAGE_REL_ARM_GPREL12;
+ }
+
+ RELOC_RVA :
+ rel.reloctype:=IMAGE_REL_ARM_ADDR32NB;
+ RELOC_SECREL32 :
+ rel.reloctype:=IMAGE_REL_ARM_SECREL;
+{$endif arm}
+{$ifdef i386}
+ RELOC_RELATIVE :
+ rel.reloctype:=IMAGE_REL_I386_PCRLONG;
+ RELOC_ABSOLUTE :
+ rel.reloctype:=IMAGE_REL_I386_DIR32;
+ RELOC_RVA :
+ rel.reloctype:=IMAGE_REL_I386_IMAGEBASE;
+ RELOC_SECREL32 :
+ rel.reloctype:=IMAGE_REL_I386_SECREL32;
+{$endif i386}
+{$ifdef x86_64}
+ RELOC_NONE :
+ rel.reloctype:=IMAGE_REL_AMD64_ABSOLUTE;
+ RELOC_RELATIVE :
+ rel.reloctype:=IMAGE_REL_AMD64_REL32;
+ RELOC_ABSOLUTE32 :
+ rel.reloctype:=IMAGE_REL_AMD64_ADDR32;
+ RELOC_ABSOLUTE :
+ rel.reloctype:=IMAGE_REL_AMD64_ADDR64;
+ RELOC_RVA :
+ rel.reloctype:=IMAGE_REL_AMD64_ADDR32NB;
+ RELOC_RELATIVE_1 :
+ rel.reloctype:=IMAGE_REL_AMD64_REL32_1;
+ RELOC_RELATIVE_2 :
+ rel.reloctype:=IMAGE_REL_AMD64_REL32_2;
+ RELOC_RELATIVE_3 :
+ rel.reloctype:=IMAGE_REL_AMD64_REL32_3;
+ RELOC_RELATIVE_4 :
+ rel.reloctype:=IMAGE_REL_AMD64_REL32_4;
+ RELOC_RELATIVE_5 :
+ rel.reloctype:=IMAGE_REL_AMD64_REL32_5;
+ RELOC_SECREL32 :
+ rel.reloctype:=IMAGE_REL_AMD64_SECREL;
+{$endif x86_64}
+ else
+ internalerror(200905071);
+ end;
+ FWriter.write(rel,sizeof(rel));
+ end;
+ end;
+
+
+ procedure TCoffObjOutput.create_symbols(data:TObjData);
+ var
+ filename : string[18];
+ sectionval : word;
+ globalval : byte;
+ i : longint;
+ value : aword;
+ objsym : TObjSymbol;
+ begin
+ with TCoffObjData(data) do
+ begin
+ symidx:=0;
+ { The `.file' record, and the file name auxiliary record }
+ write_symbol('.file', 0, -2, COFF_SYM_FILE, 1);
+ fillchar(filename,sizeof(filename),0);
+ filename:=ExtractFileName(current_module.mainsource^);
+ inc(symidx);
+ FCoffSyms.write(filename[1],sizeof(filename)-1);
+ { Sections }
+ ObjSectionList.ForEachCall(@section_write_symbol,nil);
+ { ObjSymbols }
+ for i:=0 to ObjSymbolList.Count-1 do
+ begin
+ objsym:=TObjSymbol(ObjSymbolList[i]);
+ if (objsym.typ=AT_LABEL) and (objsym.bind=AB_LOCAL) then
+ continue;
+ case objsym.bind of
+ AB_GLOBAL :
+ begin
+ globalval:=2;
+ sectionval:=TCoffObjSection(objsym.objsection).secidx;
+ value:=objsym.address;
+ end;
+ AB_LOCAL :
+ begin
+ globalval:=3;
+ sectionval:=TCoffObjSection(objsym.objsection).secidx;
+ value:=objsym.address;
+ end;
+ else
+ begin
+ globalval:=2;
+ sectionval:=0;
+ value:=objsym.size;
+ end;
+ end;
+ { symbolname }
+ objsym.symidx:=symidx;
+ write_symbol(objsym.name,value,sectionval,globalval,0);
+ end;
+ end;
+ end;
+
+
+ procedure TCoffObjOutput.section_set_datapos(p:TObject;arg:pointer);
+ begin
+ TObjSection(p).setdatapos(paword(arg)^);
+ end;
+
+
+ procedure TCoffObjOutput.section_set_reloc_datapos(p:TObject;arg:pointer);
+ begin
+ TCoffObjSection(p).coffrelocpos:=paint(arg)^;
+ inc(paint(arg)^,sizeof(coffreloc)*TObjSection(p).ObjRelocations.count);
+ end;
+
+
+ procedure TCoffObjOutput.section_write_header(p:TObject;arg:pointer);
+ var
+ sechdr : tcoffsechdr;
+ s : string;
+ strpos : aword;
+ begin
+ with TCoffObjSection(p) do
+ begin
+ fillchar(sechdr,sizeof(sechdr),0);
+ s:=name;
+ if length(s)>8 then
+ begin
+ strpos:=FCoffStrs.size+4;
+ FCoffStrs.writestr(s);
+ FCoffStrs.writestr(#0);
+ s:='/'+ToStr(strpos);
+ end;
+ move(s[1],sechdr.name,length(s));
+ if not win32 then
+ begin
+ sechdr.rvaofs:=mempos;
+ sechdr.vsize:=mempos;
+ end
+ else
+ begin
+ if not(oso_data in secoptions) then
+ sechdr.vsize:=Size;
+ end;
+ sechdr.DataSize:=size;
+ if (Size>0) and
+ (oso_data in secoptions) then
+ sechdr.datapos:=datapos;
+ sechdr.nrelocs:=ObjRelocations.count;
+ sechdr.relocpos:=coffrelocpos;
+ if win32 then
+ sechdr.flags:=peencodesechdrflags(secoptions,secalign)
+ else
+ sechdr.flags:=djencodesechdrflags(secoptions);
+ FWriter.write(sechdr,sizeof(sechdr));
+ end;
+ end;
+
+
+ procedure TCoffObjOutput.section_write_data(p:TObject;arg:pointer);
+ begin
+ with TObjSection(p) do
+ begin
+ if assigned(data) then
+ begin
+ FWriter.writezeros(dataalignbytes);
+ if Datapos<>FWriter.ObjSize then
+ internalerror(200603052);
+ FWriter.writearray(data);
+ end;
+ end;
+ end;
+
+
+ function TCoffObjOutput.writedata(data:TObjData):boolean;
+ var
+ orgdatapos,
+ datapos,
+ sympos : aword;
+ i : longint;
+ gotreloc : boolean;
+ header : tcoffheader;
+ begin
+ result:=false;
+ FCoffSyms:=TDynamicArray.Create(SymbolMaxGrow);
+ FCoffStrs:=TDynamicArray.Create(StrsMaxGrow);
+ with TCoffObjData(data) do
+ begin
+ { Create Symbol Table }
+ create_symbols(data);
+
+ { Calculate the filepositions }
+ datapos:=sizeof(tcoffheader)+sizeof(tcoffsechdr)*ObjSectionList.Count;
+ { Sections first }
+ ObjSectionList.ForEachCall(@section_set_datapos,@datapos);
+ { relocs }
+ orgdatapos:=datapos;
+ ObjSectionList.ForEachCall(@section_set_reloc_datapos,@datapos);
+ gotreloc:=(orgdatapos<>datapos);
+ { Symbols }
+ sympos:=datapos;
+
+ { Generate COFF header }
+ fillchar(header,sizeof(tcoffheader),0);
+ header.mach:=COFF_MAGIC;
+ header.nsects:=ObjSectionList.Count;
+ header.sympos:=sympos;
+ header.syms:=symidx;
+ if win32 then
+ begin
+{$ifdef arm}
+ header.flag:=PE_FILE_32BIT_MACHINE or
+ PE_FILE_LINE_NUMS_STRIPPED or PE_FILE_LOCAL_SYMS_STRIPPED;
+{$else arm}
+ header.flag:=PE_FILE_BYTES_REVERSED_LO or PE_FILE_32BIT_MACHINE or
+ PE_FILE_LINE_NUMS_STRIPPED or PE_FILE_LOCAL_SYMS_STRIPPED;
+{$endif arm}
+ if not gotreloc then
+ header.flag:=header.flag or PE_FILE_RELOCS_STRIPPED;
+ end
+ else
+ begin
+ header.flag:=COFF_FLAG_AR32WR or COFF_FLAG_NOLINES or COFF_FLAG_NOLSYMS;
+ if not gotreloc then
+ header.flag:=header.flag or COFF_FLAG_NORELOCS;
+ end;
+ FWriter.write(header,sizeof(header));
+ { Section headers }
+ ObjSectionList.ForEachCall(@section_write_header,nil);
+ { ObjSections }
+ ObjSectionList.ForEachCall(@section_write_data,nil);
+ { Relocs }
+ ObjSectionList.ForEachCall(@section_write_relocs,nil);
+ { ObjSymbols }
+ if Sympos<>FWriter.ObjSize then
+ internalerror(200603051);
+ FWriter.writearray(FCoffSyms);
+ { Strings }
+ i:=FCoffStrs.size+4;
+ FWriter.write(i,4);
+ FWriter.writearray(FCoffStrs);
+ end;
+ FCoffStrs.Free;
+ FCoffStrs:=nil;
+ FCoffSyms.Free;
+ FCoffSyms:=nil;
+ end;
+
+
+ constructor TDJCoffObjOutput.create(AWriter:TObjectWriter);
+ begin
+ inherited createcoff(AWriter,false);
+ cobjdata:=TDJCoffObjData;
+ end;
+
+
+ constructor TPECoffObjOutput.create(AWriter:TObjectWriter);
+ begin
+ inherited createcoff(AWriter,true);
+ cobjdata:=TPECoffObjData;
+ end;
+
+
+{****************************************************************************
+ TCoffObjInput
+****************************************************************************}
+
+ constructor TCoffObjInput.createcoff(awin32:boolean);
+ begin
+ inherited create;
+ win32:=awin32;
+ FSymTbl:=nil;
+ end;
+
+
+ destructor TCoffObjInput.destroy;
+ begin
+ if assigned(FCoffSyms) then
+ FCoffSyms.free;
+ if assigned(FCoffStrs) then
+ FCoffStrs.free;
+ if assigned(FSymTbl) then
+ freemem(FSymTbl);
+ if assigned(FSecTbl) then
+ freemem(FSecTbl);
+ inherited destroy;
+ end;
+
+
+ function TCoffObjInput.GetSection(secidx:longint):TObjSection;
+ begin
+ result:=nil;
+ if (secidx<1) or (secidx>FSecCount) then
+ begin
+ InputError('Failed reading coff file, invalid section index');
+ exit;
+ end;
+ result:=FSecTbl^[secidx];
+ end;
+
+
+ function TCoffObjInput.Read_str(strpos:longword):string;
+ begin
+ FCoffStrs.Seek(strpos-4);
+ FCoffStrs.Read(result[1],255);
+ result[255]:=#0;
+ result[0]:=chr(strlen(@result[1]));
+ if result='' then
+ Internalerror(200205172);
+ end;
+
+
+ procedure TCoffObjInput.read_relocs(s:TCoffObjSection);
+ var
+ rel : coffreloc;
+ rel_type : TObjRelocationType;
+ i : longint;
+ p : TObjSymbol;
+ begin
+ for i:=1 to s.coffrelocs do
+ begin
+ FReader.read(rel,sizeof(rel));
+ case rel.reloctype of
+{$ifdef arm}
+ IMAGE_REL_ARM_ABSOLUTE:
+ rel_type:=RELOC_NONE;
+ IMAGE_REL_ARM_ADDR32:
+ rel_type:=RELOC_ABSOLUTE;
+ IMAGE_REL_ARM_ADDR32NB:
+ rel_type:=RELOC_RVA;
+ IMAGE_REL_ARM_BRANCH24:
+ rel_type:=RELOC_RELATIVE_24;
+ IMAGE_REL_ARM_SECREL:
+ rel_type:=RELOC_SECREL32;
+{$endif arm}
+{$ifdef i386}
+ IMAGE_REL_I386_PCRLONG :
+ rel_type:=RELOC_RELATIVE;
+ IMAGE_REL_I386_DIR32 :
+ rel_type:=RELOC_ABSOLUTE;
+ IMAGE_REL_I386_IMAGEBASE :
+ rel_type:=RELOC_RVA;
+ IMAGE_REL_I386_SECREL32 :
+ rel_type:=RELOC_SECREL32;
+{$endif i386}
+{$ifdef x86_64}
+ IMAGE_REL_AMD64_ABSOLUTE:
+ rel_type:=RELOC_NONE;
+ IMAGE_REL_AMD64_REL32:
+ rel_type:=RELOC_RELATIVE;
+ IMAGE_REL_AMD64_ADDR32,
+ R_X86_64_32S:
+ rel_type:=RELOC_ABSOLUTE32;
+ IMAGE_REL_AMD64_ADDR64:
+ rel_type:=RELOC_ABSOLUTE;
+ IMAGE_REL_AMD64_ADDR32NB:
+ rel_type:=RELOC_RVA;
+ IMAGE_REL_AMD64_REL32_1:
+ rel_type:=RELOC_RELATIVE_1;
+ IMAGE_REL_AMD64_REL32_2:
+ rel_type:=RELOC_RELATIVE_2;
+ IMAGE_REL_AMD64_REL32_3:
+ rel_type:=RELOC_RELATIVE_3;
+ IMAGE_REL_AMD64_REL32_4:
+ rel_type:=RELOC_RELATIVE_4;
+ IMAGE_REL_AMD64_REL32_5:
+ rel_type:=RELOC_RELATIVE_5;
+ IMAGE_REL_AMD64_SECREL:
+ rel_type:=RELOC_SECREL32;
+{$endif x86_64}
+ else
+ begin
+ InputError('Failed reading coff file, illegal reloctype $'+system.hexstr(rel.reloctype,4));
+ exit;
+ end;
+ end;
+
+ p:=FSymTbl^[rel.sym].sym;
+ if assigned(p) then
+ s.addsymsizereloc(rel.address-s.mempos,p,FSymTbl^[rel.sym].orgsize,rel_type)
+ else
+ begin
+ InputError('Failed reading coff file, can''t resolve symbol of relocation');
+ exit;
+ end;
+ end;
+ end;
+
+
+ procedure TCoffObjInput.read_symbols(objdata:TObjData);
+ var
+ size,
+ address,
+ nsyms,
+ symidx : aint;
+ i : longint;
+ sym : coffsymbol;
+ objsym : TObjSymbol;
+ bind : Tasmsymbind;
+ strname : string;
+ auxrec : array[0..17] of byte;
+ objsec : TObjSection;
+ begin
+ with TCoffObjData(objdata) do
+ begin
+ nsyms:=FCoffSyms.Size div sizeof(CoffSymbol);
+ { Allocate memory for symidx -> TObjSymbol table }
+ GetMem(FSymTbl,nsyms*sizeof(TObjSymbolrec));
+ FillChar(FSymTbl^,nsyms*sizeof(TObjSymbolrec),0);
+ { Load the Symbols }
+ FCoffSyms.Seek(0);
+ symidx:=0;
+ while (symidx<nsyms) do
+ begin
+ FCoffSyms.Read(sym,sizeof(sym));
+ if plongint(@sym.name)^<>0 then
+ begin
+ move(sym.name,strname[1],8);
+ strname[9]:=#0;
+ strname[0]:=chr(strlen(@strname[1]));
+ if strname='' then
+ Internalerror(200205171);
+ end
+ else
+ strname:=Read_str(sym.strpos);
+ bind:=AB_EXTERNAL;
+ size:=0;
+ address:=0;
+ objsym:=nil;
+ objsec:=nil;
+ case sym.typ of
+ COFF_SYM_GLOBAL :
+ begin
+ if sym.section=0 then
+ begin
+ if sym.value=0 then
+ bind:=AB_EXTERNAL
+ else
+ begin
+ bind:=AB_COMMON;
+ size:=sym.value;
+ end;
+ end
+ else
+ begin
+ bind:=AB_GLOBAL;
+ objsec:=GetSection(sym.section);
+ if sym.value>=objsec.mempos then
+ address:=sym.value-objsec.mempos;
+ end;
+ objsym:=CreateSymbol(strname);
+ objsym.bind:=bind;
+ objsym.typ:=AT_FUNCTION;
+ objsym.objsection:=objsec;
+ objsym.offset:=address;
+ objsym.size:=size;
+ { Register in ObjSection }
+ if assigned(objsec) then
+ objsec.AddSymbolDefine(objsym);
+ end;
+ COFF_SYM_LABEL,
+ COFF_SYM_LOCAL :
+ begin
+ { do not add constants (section=-1) }
+ if sym.section<>-1 then
+ begin
+ bind:=AB_LOCAL;
+ objsec:=GetSection(sym.section);
+ if sym.value>=objsec.mempos then
+ address:=sym.value-objsec.mempos;
+ objsym:=CreateSymbol(strname);
+ objsym.bind:=bind;
+ objsym.typ:=AT_FUNCTION;
+ objsym.objsection:=objsec;
+ objsym.offset:=address;
+ objsym.size:=size;
+ end;
+ end;
+ COFF_SYM_SECTION :
+ begin
+ if sym.section=0 then
+ InputError('Failed reading coff file, illegal section');
+ objsec:=GetSection(sym.section);
+ if assigned(objsec) then
+ begin
+ if sym.value>=objsec.mempos then
+ address:=sym.value-objsec.mempos;
+ objsym:=CreateSymbol(strname);
+ objsym.bind:=AB_LOCAL;
+ objsym.typ:=AT_FUNCTION;
+ objsym.objsection:=objsec;
+ objsym.offset:=address;
+ objsym.size:=size;
+ end;
+ end;
+ COFF_SYM_FUNCTION,
+ COFF_SYM_FILE :
+ ;
+ else
+ internalerror(200602232);
+ end;
+ FSymTbl^[symidx].sym:=objsym;
+ FSymTbl^[symidx].orgsize:=size;
+ { read aux records }
+ for i:=1 to sym.aux do
+ begin
+ FCoffSyms.Read(auxrec,sizeof(auxrec));
+ inc(symidx);
+ end;
+ inc(symidx);
+ end;
+ end;
+ end;
+
+
+ procedure TCoffObjInput.ObjSections_read_data(p:TObject;arg:pointer);
+ begin
+ with TCoffObjSection(p) do
+ begin
+ { Skip debug sections }
+ if (oso_debug in secoptions) and
+ (cs_link_strip in current_settings.globalswitches) and
+ not(cs_link_separate_dbg_file in current_settings.globalswitches) then
+ exit;
+
+ if assigned(data) then
+ begin
+ FReader.Seek(datapos);
+ if not FReader.ReadArray(data,Size) then
+ begin
+ Comment(V_Error,'Error reading coff file, can''t read object data');
+ exit;
+ end;
+ end;
+ end;
+ end;
+
+
+ procedure TCoffObjInput.ObjSections_read_relocs(p:TObject;arg:pointer);
+ begin
+ with TCoffObjSection(p) do
+ begin
+ { Skip debug sections }
+ if (oso_debug in secoptions) and
+ (cs_link_strip in current_settings.globalswitches) and
+ not(cs_link_separate_dbg_file in current_settings.globalswitches) then
+ exit;
+
+ if coffrelocs>0 then
+ begin
+ FReader.Seek(coffrelocpos);
+ read_relocs(TCoffObjSection(p));
+ end;
+ end;
+ end;
+
+
+ function TCoffObjInput.ReadObjData(AReader:TObjectreader;objdata:TObjData):boolean;
+ var
+ secalign : shortint;
+ strsize,
+ strpos,
+ i : longint;
+ code : longint;
+ objsec : TCoffObjSection;
+ secoptions : TObjSectionOptions;
+ header : tcoffheader;
+ sechdr : tcoffsechdr;
+ secname : string;
+ secnamebuf : array[0..15] of char;
+ begin
+ FReader:=AReader;
+ InputFileName:=AReader.FileName;
+ result:=false;
+ FCoffSyms:=TDynamicArray.Create(SymbolMaxGrow);
+ FCoffStrs:=TDynamicArray.Create(StrsMaxGrow);
+ with TCoffObjData(objdata) do
+ begin
+ { Read COFF header }
+ if not AReader.read(header,sizeof(tcoffheader)) then
+ begin
+ InputError('Can''t read COFF Header');
+ exit;
+ end;
+ if header.mach<>COFF_MAGIC then
+ begin
+ InputError('Illegal COFF Magic');
+ exit;
+ end;
+{$ifdef arm}
+ eVCobj:=header.flag=$100;
+{$endif arm}
+ { Strings }
+ AReader.Seek(header.sympos+header.syms*sizeof(CoffSymbol));
+ if not AReader.Read(strsize,4) then
+ begin
+ InputError('Error reading COFF Symtable');
+ exit;
+ end;
+ if (strsize>4) and not AReader.ReadArray(FCoffStrs,Strsize-4) then
+ begin
+ InputError('Error reading COFF Symtable');
+ exit;
+ end;
+ { Section headers }
+ { Allocate SecIdx -> TObjSection table, secidx is 1-based }
+ FSecCount:=header.nsects;
+ GetMem(FSecTbl,(header.nsects+1)*sizeof(TObjSection));
+ FillChar(FSecTbl^,(header.nsects+1)*sizeof(TObjSection),0);
+ AReader.Seek(sizeof(tcoffheader)+header.opthdr);
+ for i:=1 to header.nsects do
+ begin
+ if not AReader.read(sechdr,sizeof(sechdr)) then
+ begin
+ InputError('Error reading COFF Section Headers');
+ exit;
+ end;
+ move(sechdr.name,secnamebuf,8);
+ secnamebuf[8]:=#0;
+ secname:=strpas(secnamebuf);
+ if secname[1]='/' then
+ begin
+ Val(Copy(secname,2,8),strpos,code);
+ if code=0 then
+ secname:=Read_str(strpos)
+ else
+ begin
+ InputError('Error reading COFF Section Headers');
+ secname:='error';
+ end;
+ end;
+ if win32 then
+ pedecodesechdrflags(secname,sechdr.flags,secoptions,secalign)
+ else
+ begin
+ djdecodesechdrflags(secname,sechdr.flags);
+ secalign:=sizeof(pint);
+ end;
+ if (Length(secname)>3) and (secname[2] in ['e','f','i','p','r']) then
+ begin
+ if (Copy(secname,1,6)='.edata') or
+ (Copy(secname,1,5)='.rsrc') or
+{$ifndef x86_64}
+ (Copy(secname,1,6)='.pdata') or
+{$endif}
+ (Copy(secname,1,4)='.fpc') then
+ include(secoptions,oso_keep);
+ if (Copy(secname,1,6)='.idata') then
+ begin
+ { TODO: idata keep can maybe replaced with grouping of text and idata}
+ include(secoptions,oso_keep);
+ secname:=secname + '.' + ExtractFileName(InputFileName);
+ end;
+ end;
+ objsec:=TCoffObjSection(createsection(secname,secalign,secoptions,false));
+ FSecTbl^[i]:=objsec;
+ if not win32 then
+ objsec.mempos:=sechdr.rvaofs;
+ objsec.orgmempos:=sechdr.rvaofs;
+ objsec.coffrelocs:=sechdr.nrelocs;
+ objsec.coffrelocpos:=sechdr.relocpos;
+ objsec.datapos:=sechdr.datapos;
+ objsec.Size:=sechdr.dataSize;
+ end;
+ { ObjSymbols }
+ AReader.Seek(header.sympos);
+ if not AReader.ReadArray(FCoffSyms,header.syms*sizeof(CoffSymbol)) then
+ begin
+ Comment(V_Error,'Error reading coff file');
+ exit;
+ end;
+ { Insert all ObjSymbols }
+ read_symbols(objdata);
+ { Section Data }
+ ObjSectionList.ForEachCall(@objsections_read_data,nil);
+ { Relocs }
+ ObjSectionList.ForEachCall(@objsections_read_relocs,nil);
+ end;
+ FCoffStrs.Free;
+ FCoffStrs:=nil;
+ FCoffSyms.Free;
+ FCoffSyms:=nil;
+ result:=true;
+ end;
+
+
+ constructor TDJCoffObjInput.create;
+ begin
+ inherited createcoff(false);
+ cobjdata:=TDJCoffObjData;
+ end;
+
+
+ constructor TPECoffObjInput.create;
+ begin
+ inherited createcoff(true);
+ cobjdata:=TPECoffObjData;
+ end;
+
+
+{****************************************************************************
+ TCoffexesection
+****************************************************************************}
+
+
+ constructor TCoffExeSection.createcoff(AList:TFPHashObjectList;const n:string;awin32:boolean);
+ begin
+ inherited create(AList,n);
+ win32:=awin32;
+ end;
+
+
+ constructor TDJCoffExeSection.create(AList:TFPHashObjectList;const n:string);
+ begin
+ inherited createcoff(AList,n,false);
+ end;
+
+
+ constructor TPECoffExeSection.create(AList:TFPHashObjectList;const n:string);
+ begin
+ inherited createcoff(AList,n,false);
+ end;
+
+
+{****************************************************************************
+ TCoffexeoutput
+****************************************************************************}
+
+ constructor TCoffexeoutput.createcoff(awin32:boolean);
+ begin
+ inherited create;
+ win32:=awin32;
+ if target_info.system in [system_x86_64_win64] then
+ MaxMemPos:=$FFFFFFFF
+ else
+ if target_info.system in systems_wince then
+ MaxMemPos:=$1FFFFFF
+ else
+ MaxMemPos:=$7FFFFFFF;
+ end;
+
+
+ procedure TCoffexeoutput.write_symbol(const name:string;value:aword;section:smallint;typ,aux:byte);
+ var
+ sym : coffsymbol;
+ begin
+ FillChar(sym,sizeof(sym),0);
+ if length(name)>8 then
+ begin
+ sym.strpos:=FCoffStrs.size+4;
+ FCoffStrs.writestr(name);
+ FCoffStrs.writestr(#0);
+ end
+ else
+ move(name[1],sym.name,length(name));
+ sym.value:=value;
+ sym.section:=section;
+ sym.typ:=typ;
+ sym.aux:=aux;
+ FWriter.write(sym,sizeof(sym));
+ end;
+
+
+ procedure TCoffexeoutput.globalsyms_write_symbol(p:TObject;arg:pointer);
+ var
+ secval,
+ value : aint;
+ globalval : byte;
+ exesec : TExeSection;
+ begin
+ if not assigned(texesymbol(p).objsymbol) then
+ internalerror(200603053);
+ with texesymbol(p).objsymbol do
+ begin
+ exesec:=TExeSection(objsection.exesection);
+ { There is no exesection defined for special internal symbols
+ like __image_base__ }
+ if assigned(exesec) then
+ begin
+ secval:=exesec.secsymidx;
+ value:=address-exesec.mempos;
+ end
+ else
+ begin
+ secval:=-1;
+ value:=address;
+ end;
+ if bind=AB_LOCAL then
+ globalval:=3
+ else
+ globalval:=2;
+ { reloctype address to the section in the executable }
+ write_symbol(name,value,secval,globalval,0);
+ end;
+ end;
+
+
+ procedure TCoffexeoutput.ExeSectionList_write_header(p:TObject;arg:pointer);
+ var
+ sechdr : tcoffsechdr;
+ s : string;
+ strpos : aword;
+ begin
+ with tExeSection(p) do
+ begin
+ fillchar(sechdr,sizeof(sechdr),0);
+ s:=name;
+ if length(s)>8 then
+ begin
+ strpos:=FCoffStrs.size+4;
+ FCoffStrs.writestr(s);
+ FCoffStrs.writestr(#0);
+ s:='/'+ToStr(strpos);
+ end;
+ move(s[1],sechdr.name,length(s));
+ sechdr.rvaofs:=mempos;
+ if win32 then
+ sechdr.vsize:=Size
+ else
+ sechdr.vsize:=mempos;
+
+ { sechdr.dataSize is size of initilized data. Must be zero for sections that
+ do not contain one. In Windows it must be rounded up to FileAlignment
+ (so it can be greater than VirtualSize) }
+ if (oso_data in SecOptions) then
+ begin
+ if win32 then
+ sechdr.dataSize:=Align(Size,SectionDataAlign)
+ else
+ sechdr.dataSize:=Size;
+ if (Size>0) then
+ sechdr.datapos:=datapos;
+ end;
+ sechdr.nrelocs:=0;
+ sechdr.relocpos:=0;
+ if win32 then
+ begin
+ if (target_info.system in systems_nativent) and
+ (apptype = app_native) then
+ sechdr.flags:=peencodesechdrflags(SecOptions,SecAlign) or PE_SCN_MEM_NOT_PAGED
+ else
+ sechdr.flags:=peencodesechdrflags(SecOptions,SecAlign);
+ { some flags are invalid in executables, reset them }
+ sechdr.flags:=sechdr.flags and
+ not(PE_SCN_LNK_INFO or PE_SCN_LNK_REMOVE or
+ PE_SCN_LNK_COMDAT or PE_SCN_ALIGN_MASK);
+ end
+ else
+ sechdr.flags:=djencodesechdrflags(SecOptions);
+ FWriter.write(sechdr,sizeof(sechdr));
+ end;
+ end;
+
+
+ procedure TCoffexeoutput.ExeSectionList_pass2_header(p:TObject;arg:pointer);
+ begin
+ with TExeSection(p) do
+ begin
+ { The debuginfo sections should already be stripped }
+{ if (ExeWriteMode=ewm_exeonly) and
+ (oso_debug in SecOptions) then
+ internalerror(200801161); }
+ inc(plongint(arg)^);
+ secsymidx:=plongint(arg)^;
+ end;
+ end;
+
+
+ procedure Tcoffexeoutput.ExeSectionList_write_Data(p:TObject;arg:pointer);
+ var
+ objsec : TObjSection;
+ i : longint;
+ begin
+ with texesection(p) do
+ begin
+ { don't write normal section if writing only debug info }
+ if (ExeWriteMode=ewm_dbgonly) and
+ not(oso_debug in SecOptions) then
+ exit;
+
+ if oso_data in secoptions then
+ begin
+ FWriter.Writezeros(Align(FWriter.Size,SectionDataAlign)-FWriter.Size);
+ for i:=0 to ObjSectionList.Count-1 do
+ begin
+ objsec:=TObjSection(ObjSectionList[i]);
+ if oso_data in objsec.secoptions then
+ begin
+ if not assigned(objsec.data) then
+ internalerror(200603042);
+ FWriter.writezeros(objsec.dataalignbytes);
+ if objsec.DataPos<>FWriter.Size then
+ internalerror(200602251);
+ FWriter.writearray(objsec.data);
+ end;
+ end;
+ end;
+ end;
+ end;
+
+
+ function tcoffexeoutput.totalheadersize:longword;
+ var
+ stubsize,
+ optheadersize : longword;
+ begin
+ if win32 then
+ begin
+ stubsize:=sizeof(win32stub)+sizeof(pemagic);
+ optheadersize:=sizeof(tcoffpeoptheader);
+ end
+ else
+ begin
+ stubsize:=sizeof(go32v2stub);
+ optheadersize:=sizeof(coffdjoptheader);
+ end;
+ result:=stubsize+sizeof(tcoffheader)+optheadersize;
+ end;
+
+
+ procedure tcoffexeoutput.MemPos_Header;
+ begin
+ { calculate start positions after the headers }
+ currmempos:=totalheadersize+sizeof(tcoffsechdr)*longword(ExeSectionList.Count-2);
+ end;
+
+
+ procedure tcoffexeoutput.DataPos_Header;
+ begin
+ { retrieve amount of sections }
+ nsects:=0;
+ ExeSectionList.ForEachCall(@ExeSectionList_pass2_header,@nsects);
+ { calculate start positions after the headers }
+ currdatapos:=totalheadersize+longword(nsects)*sizeof(tcoffsechdr);
+ end;
+
+
+ procedure tcoffexeoutput.DataPos_Symbols;
+ begin
+ inherited DataPos_Symbols;
+ { Calculating symbols position and size }
+ nsyms:=ExeSymbolList.Count;
+ sympos:=Align(CurrDataPos,SectionDataAlign);
+ inc(CurrDataPos,sizeof(coffsymbol)*nsyms);
+ end;
+
+
+ function TCoffexeoutput.writedata:boolean;
+ var
+ i : longword;
+ header : tcoffheader;
+ djoptheader : coffdjoptheader;
+ peoptheader : tcoffpeoptheader;
+ textExeSec,
+ dataExeSec,
+ bssExeSec,
+ idataExeSec,
+ tlsExeSec : TExeSection;
+ tlsdir : TlsDirectory;
+ hassymbols,
+ writeDbgStrings : boolean;
+
+ procedure UpdateDataDir(const secname:string;idx:longint);
+ var
+ exesec : TExeSection;
+ begin
+ exesec:=FindExeSection(secname);
+ if assigned(exesec) then
+ begin
+ peoptheader.DataDirectory[idx].vaddr:=exesec.mempos;
+ peoptheader.DataDirectory[idx].size:=exesec.Size;
+ end;
+ end;
+
+ procedure UpdateImports;
+ var
+ exesec: TExeSection;
+ objsec, iat_start, iat_end, ilt_start: TObjSection;
+ i: longint;
+ begin
+ exesec:=FindExeSection('.idata');
+ if exesec=nil then
+ exit;
+ iat_start:=nil;
+ iat_end:=nil;
+ ilt_start:=nil;
+ for i:=0 to exesec.ObjSectionList.Count-1 do
+ begin
+ objsec:=TObjSection(exesec.ObjSectionList[i]);
+ if (ilt_start=nil) and (Pos('.idata$4',objsec.Name)=1) then
+ ilt_start:=objsec;
+ if Pos('.idata$5',objsec.Name)=1 then
+ begin
+ if iat_start=nil then
+ iat_start:=objsec;
+ end
+ else
+ if Assigned(iat_start) then
+ begin
+ iat_end:=objsec;
+ Break;
+ end;
+ end;
+
+ peoptheader.DataDirectory[PE_DATADIR_IDATA].vaddr:=exesec.mempos;
+ if Assigned(ilt_start) then
+ peoptheader.DataDirectory[PE_DATADIR_IDATA].size:=ilt_start.mempos-exesec.mempos
+ else { should not happen }
+ peoptheader.DataDirectory[PE_DATADIR_IDATA].size:=exesec.Size;
+
+ if Assigned(iat_start) and Assigned(iat_end) then
+ begin
+ peoptheader.DataDirectory[PE_DATADIR_IMPORTADDRESSTABLE].vaddr:=iat_start.mempos;
+ peoptheader.DataDirectory[PE_DATADIR_IMPORTADDRESSTABLE].size:=iat_end.mempos-iat_start.mempos;
+ end;
+ end;
+
+ procedure UpdateTlsDataDir;
+ var
+ {callbacksection : TExeSection;}
+ tlsexesymbol: TExeSymbol;
+ tlssymbol: TObjSymbol;
+ callbackexesymbol: TExeSymbol;
+ callbacksymbol: TObjSymbol;
+ begin
+ { according to GNU ld,
+ the callback routines should be placed into .CRT$XL*
+ sections, and the thread local variables in .tls
+ __tls_start__ and __tls_end__ symbols
+ should be used for the initialized part,
+ which we do not support yet. }
+ { For now, we only pass the address of the __tls_used
+ asm symbol into PE_DATADIR_TLS with the correct
+ size of this table (different for win32/win64 }
+ tlsexesymbol:=texesymbol(ExeSymbolList.Find(
+ target_info.Cprefix+'_tls_used'));
+ if assigned(tlsexesymbol) then
+ begin
+ tlssymbol:=tlsexesymbol.ObjSymbol;
+ peoptheader.DataDirectory[PE_DATADIR_TLS].vaddr:=tlssymbol.address;
+ { sizeof(TlsDirectory) is different on host and target when cross-compiling }
+ peoptheader.DataDirectory[PE_DATADIR_TLS].size:=TLSDIR_SIZE;
+ if IsSharedLibrary then
+ begin
+ { Here we should reset __FPC_tls_callbacks value to nil }
+ callbackexesymbol:=texesymbol(ExeSymbolList.Find(
+ '__FPC_tls_callbacks'));
+ if assigned (callbackexesymbol) then
+ begin
+ callbacksymbol:=callbackexesymbol.ObjSymbol;
+
+ end;
+ end;
+
+ end;
+ end;
+
+ begin
+ result:=false;
+ FCoffSyms:=TDynamicArray.Create(SymbolMaxGrow);
+ FCoffStrs:=TDynamicArray.Create(StrsMaxGrow);
+ textExeSec:=FindExeSection('.text');
+ dataExeSec:=FindExeSection('.data');
+ bssExeSec:=FindExeSection('.bss');
+ tlsExeSec:=FindExeSection('.tls');
+ if not assigned(TextExeSec) or
+ not assigned(DataExeSec) then
+ internalerror(200602231);
+ { do we need to write symbols? }
+ hassymbols:=(ExeWriteMode=ewm_dbgonly) or
+ (
+ (ExeWriteMode=ewm_exefull) and
+ not(cs_link_strip in current_settings.globalswitches)
+ );
+ writeDbgStrings:=hassymbols or ((ExeWriteMode=ewm_exeonly) and (cs_link_separate_dbg_file in current_settings.globalswitches));
+ { Stub }
+ if win32 then
+ begin
+ FWriter.write(win32stub,sizeof(win32stub));
+ FWriter.write(pemagic,sizeof(pemagic));
+ end
+ else
+ FWriter.write(go32v2stub,sizeof(go32v2stub));
+ { Initial header, will be updated later }
+ fillchar(header,sizeof(header),0);
+ header.mach:=COFF_MAGIC;
+ header.nsects:=nsects;
+ if writeDbgStrings then
+ header.sympos:=sympos;
+ if hassymbols then
+ header.syms:=nsyms;
+ if win32 then
+ header.opthdr:=sizeof(tcoffpeoptheader)
+ else
+ header.opthdr:=sizeof(coffdjoptheader);
+ if win32 then
+ begin
+ header.flag:=PE_FILE_EXECUTABLE_IMAGE or PE_FILE_LINE_NUMS_STRIPPED;
+ if target_info.system in [system_x86_64_win64] then
+ header.flag:=header.flag or PE_FILE_LARGE_ADDRESS_AWARE
+ else
+ header.flag:=header.flag or PE_FILE_32BIT_MACHINE;
+ if IsSharedLibrary then
+ header.flag:=header.flag or PE_FILE_DLL;
+ if FindExeSection('.reloc')=nil then
+ header.flag:=header.flag or PE_FILE_RELOCS_STRIPPED;
+ if (FindExeSection('.stab')=nil) and
+ (FindExeSection('.debug_info')=nil) and
+ (FindExeSection('.gnu_debuglink')=nil) then
+ header.flag:=header.flag or PE_FILE_DEBUG_STRIPPED;
+ if not hassymbols then
+ header.flag:=header.flag or PE_FILE_LOCAL_SYMS_STRIPPED;
+ if SetPEFlagsSetExplicity then
+ header.flag:=header.flag or peflags;
+ end
+ else
+ header.flag:=COFF_FLAG_AR32WR or COFF_FLAG_EXE or COFF_FLAG_NORELOCS or COFF_FLAG_NOLINES;
+ FWriter.write(header,sizeof(header));
+ { Optional COFF Header }
+ if win32 then
+ begin
+ fillchar(peoptheader,sizeof(peoptheader),0);
+ peoptheader.magic:=COFF_OPT_MAGIC;
+ peoptheader.MajorLinkerVersion:=ord(version_nr)-ord('0');
+ peoptheader.MinorLinkerVersion:=(ord(release_nr)-ord('0'))*10 + (ord(patch_nr)-ord('0'));
+ peoptheader.tsize:=TextExeSec.Size;
+ peoptheader.dsize:=DataExeSec.Size;
+ if assigned(BSSExeSec) then
+ peoptheader.bsize:=BSSExeSec.Size;
+ peoptheader.text_start:=TextExeSec.mempos;
+{$ifndef cpu64bitaddr}
+ peoptheader.data_start:=DataExeSec.mempos;
+{$endif cpu64bitaddr}
+ peoptheader.entry:=EntrySym.Address;
+ peoptheader.ImageBase:=ImageBase;
+ peoptheader.SectionAlignment:=SectionMemAlign;
+ peoptheader.FileAlignment:=SectionDataAlign;
+ peoptheader.MajorOperatingSystemVersion:=4;
+ peoptheader.MinorOperatingSystemVersion:=0;
+ peoptheader.MajorImageVersion:=dllmajor;
+ peoptheader.MinorImageVersion:=dllminor;
+ if target_info.system in systems_wince then
+ peoptheader.MajorSubsystemVersion:=3
+ else
+ peoptheader.MajorSubsystemVersion:=4;
+ peoptheader.MinorSubsystemVersion:=0;
+ peoptheader.Win32Version:=0;
+ peoptheader.SizeOfImage:=Align(CurrMemPos,SectionMemAlign);
+ peoptheader.SizeOfHeaders:=textExeSec.DataPos;
+ peoptheader.CheckSum:=0;
+ if (target_info.system in systems_nativent) and (not IsSharedLibrary or (apptype = app_native)) then
+ { Although I did not really test this, it seems that Subsystem is
+ not checked in DLLs except for maybe drivers}
+ peoptheader.Subsystem:=PE_SUBSYSTEM_NATIVE
+ else
+ if target_info.system in systems_wince then
+ peoptheader.Subsystem:=PE_SUBSYSTEM_WINDOWS_CE_GUI
+ else
+ if apptype=app_gui then
+ peoptheader.Subsystem:=PE_SUBSYSTEM_WINDOWS_GUI
+ else
+ peoptheader.Subsystem:=PE_SUBSYSTEM_WINDOWS_CUI;
+ peoptheader.DllCharacteristics:=0;
+ peoptheader.SizeOfStackReserve:=stacksize;
+ peoptheader.SizeOfStackCommit:=$1000;
+ if MinStackSizeSetExplicity then
+ peoptheader.SizeOfStackCommit:=minstacksize;
+ if MaxStackSizeSetExplicity then
+ peoptheader.SizeOfStackReserve:=maxstacksize;
+ peoptheader.SizeOfHeapReserve:=$100000;
+ peoptheader.SizeOfHeapCommit:=$1000;
+ peoptheader.NumberOfRvaAndSizes:=PE_DATADIR_ENTRIES;
+ UpdateImports;
+ UpdateTlsDataDir;
+ UpdateDataDir('.edata',PE_DATADIR_EDATA);
+ UpdateDataDir('.rsrc',PE_DATADIR_RSRC);
+ UpdateDataDir('.pdata',PE_DATADIR_PDATA);
+ UpdateDataDir('.reloc',PE_DATADIR_RELOC);
+ FWriter.write(peoptheader,sizeof(peoptheader));
+ end
+ else
+ begin
+ fillchar(djoptheader,sizeof(djoptheader),0);
+ djoptheader.magic:=COFF_OPT_MAGIC;
+ djoptheader.tsize:=TextExeSec.Size;
+ djoptheader.dsize:=DataExeSec.Size;
+ if assigned(BSSExeSec) then
+ djoptheader.bsize:=BSSExeSec.Size;
+ djoptheader.text_start:=TextExeSec.mempos;
+ djoptheader.data_start:=DataExeSec.mempos;
+ djoptheader.entry:=EntrySym.offset;
+ FWriter.write(djoptheader,sizeof(djoptheader));
+ end;
+
+ { For some unknown reason WM 6.1 requires .idata section to be read only.
+ Otherwise it refuses to load DLLs greater than 64KB.
+ Earlier versions of WinCE load DLLs regardless of .idata flags. }
+ if target_info.system in systems_wince then
+ begin
+ idataExeSec:=FindExeSection('.idata');
+ if idataExeSec<>nil then
+ idataExeSec.SecOptions:=idataExeSec.SecOptions - [oso_write] + [oso_readonly];
+ end;
+
+ { Section headers }
+ ExeSectionList.ForEachCall(@ExeSectionList_write_header,nil);
+ { Section data }
+ ExeSectionList.ForEachCall(@ExeSectionList_write_data,nil);
+ { Align after the last section }
+ FWriter.Writezeros(Align(FWriter.Size,SectionDataAlign)-FWriter.Size);
+
+ { Optional Symbols }
+ if SymPos<>FWriter.Size then
+ internalerror(200602252);
+ if hassymbols then
+ ExeSymbolList.ForEachCall(@globalsyms_write_symbol,nil);
+ if writeDbgStrings then
+ begin
+ { Strings }
+ i:=FCoffStrs.size+4;
+ FWriter.write(i,4);
+ FWriter.writearray(FCoffStrs);
+ end;
+ { Release }
+ FCoffStrs.Free;
+ FCoffSyms.Free;
+ result:=true;
+ end;
+
+
+ function IdataObjSectionCompare(Item1, Item2: Pointer): Integer;
+ var
+ I1 : TObjSection absolute Item1;
+ I2 : TObjSection absolute Item2;
+ begin
+ Result:=CompareStr(I1.Name,I2.Name);
+ end;
+
+ procedure TCoffexeoutput.Order_ObjSectionList(ObjSectionList: TFPObjectList;const aPattern:string);
+ begin
+ { Sort sections having '$' in the name, that's how PECOFF documentation
+ tells to handle them. However, look for '$' in the pattern, not in section
+ names, because the latter often get superfluous '$' due to mangling. }
+ if Pos('$',aPattern)>0 then
+ ObjSectionList.Sort(@IdataObjSectionCompare);
+ end;
+
+
+ constructor TDJCoffexeoutput.create;
+ begin
+ inherited createcoff(false);
+ CExeSection:=TDJCoffExeSection;
+ CObjData:=TPECoffObjData;
+ end;
+
+
+ constructor TPECoffexeoutput.create;
+ begin
+ inherited createcoff(true);
+ CExeSection:=TPECoffExeSection;
+ CObjData:=TPECoffObjData;
+ end;
+
+
+ procedure TPECoffexeoutput.GenerateLibraryImports(ImportLibraryList:TFPHashObjectList);
+ var
+ textobjsection,
+ idata2objsection,
+ idata4objsection,
+ idata5objsection,
+ idata6objsection,
+ idata7objsection : TObjSection;
+ idata2label : TObjSymbol;
+ basedllname : string;
+
+ procedure StartImport(const dllname:string);
+ var
+ idata4label,
+ idata5label,
+ idata7label : TObjSymbol;
+ emptyint : longint;
+ begin
+ if assigned(exemap) then
+ begin
+ exemap.Add('');
+ exemap.Add('Importing from DLL '+dllname);
+ end;
+ emptyint:=0;
+ basedllname:=ExtractFileName(dllname);
+ idata2objsection:=internalobjdata.createsection(sec_idata2,basedllname);
+ idata2label:=internalobjdata.SymbolDefine('__imp_dir_'+basedllname,AB_LOCAL,AT_DATA);
+ idata4objsection:=internalobjdata.createsection(sec_idata4,basedllname);
+ idata4label:=internalobjdata.SymbolDefine('__imp_names_'+basedllname,AB_LOCAL,AT_DATA);
+ idata5objsection:=internalobjdata.createsection(sec_idata5,basedllname);
+ idata5label:=internalobjdata.SymbolDefine('__imp_fixup_'+basedllname,AB_LOCAL,AT_DATA);
+ idata7objsection:=internalobjdata.createsection(sec_idata7,basedllname);
+ idata7label:=internalobjdata.SymbolDefine('__imp_dll_'+basedllname,AB_LOCAL,AT_DATA);
+ { idata2 }
+ internalobjdata.SetSection(idata2objsection);
+ { dummy links to imports finalization }
+ internalobjdata.writereloc(0,0,internalobjdata.SymbolRef('__imp_names_end_'+basedllname),RELOC_NONE);
+ internalobjdata.writereloc(0,0,internalobjdata.SymbolRef('__imp_fixup_end_'+basedllname),RELOC_NONE);
+ { section data }
+ internalobjdata.writereloc(0,sizeof(longint),idata4label,RELOC_RVA);
+ internalobjdata.writebytes(emptyint,sizeof(emptyint));
+ internalobjdata.writebytes(emptyint,sizeof(emptyint));
+ internalobjdata.writereloc(0,sizeof(longint),idata7label,RELOC_RVA);
+ internalobjdata.writereloc(0,sizeof(longint),idata5label,RELOC_RVA);
+ { idata7 }
+ internalobjdata.SetSection(idata7objsection);
+ internalobjdata.writebytes(basedllname[1],length(basedllname));
+ internalobjdata.writebytes(emptyint,1);
+ end;
+
+ procedure EndImport;
+ var
+ emptyint : longint;
+ begin
+ emptyint:=0;
+ { These are referenced from idata2, oso_keep is not necessary. }
+ idata4objsection:=internalobjdata.createsection(sec_idata4, basedllname+'_z_');
+ internalobjdata.SymbolDefine('__imp_names_end_'+basedllname,AB_LOCAL,AT_DATA);
+ idata5objsection:=internalobjdata.createsection(sec_idata5, basedllname+'_z_');
+ internalobjdata.SymbolDefine('__imp_fixup_end_'+basedllname,AB_LOCAL,AT_DATA);
+ { idata4 }
+ internalobjdata.SetSection(idata4objsection);
+ internalobjdata.writebytes(emptyint,sizeof(emptyint));
+ if target_info.system=system_x86_64_win64 then
+ internalobjdata.writebytes(emptyint,sizeof(emptyint));
+ { idata5 }
+ internalobjdata.SetSection(idata5objsection);
+ internalobjdata.writebytes(emptyint,sizeof(emptyint));
+ if target_info.system=system_x86_64_win64 then
+ internalobjdata.writebytes(emptyint,sizeof(emptyint));
+ end;
+
+ function AddImport(const afuncname,amangledname:string; AOrdNr:longint;isvar:boolean):TObjSymbol;
+ const
+{$ifdef x86_64}
+ jmpopcode : array[0..1] of byte = (
+ $ff,$25 // jmp qword [rip + offset32]
+ );
+{$else x86_64}
+ {$ifdef arm}
+ jmpopcode : array[0..7] of byte = (
+ $00,$c0,$9f,$e5, // ldr ip, [pc, #0]
+ $00,$f0,$9c,$e5 // ldr pc, [ip]
+ );
+ {$else arm}
+ jmpopcode : array[0..1] of byte = (
+ $ff,$25
+ );
+ {$endif arm}
+{$endif x86_64}
+ nopopcodes : array[0..1] of byte = (
+ $90,$90
+ );
+ var
+ idata4label,
+ idata5label,
+ idata6label : TObjSymbol;
+ emptyint : longint;
+ secname,
+ num : string;
+ absordnr: word;
+
+ procedure WriteTableEntry;
+ var
+ ordint: dword;
+ begin
+ if AOrdNr <= 0 then
+ begin
+ { import by name }
+ internalobjdata.writereloc(0,sizeof(longint),idata6label,RELOC_RVA);
+ if target_info.system=system_x86_64_win64 then
+ internalobjdata.writebytes(emptyint,sizeof(emptyint));
+ end
+ else
+ begin
+ { import by ordinal }
+ ordint:=AOrdNr;
+ if target_info.system=system_x86_64_win64 then
+ begin
+ internalobjdata.writebytes(ordint,sizeof(ordint));
+ ordint:=$80000000;
+ internalobjdata.writebytes(ordint,sizeof(ordint));
+ end
+ else
+ begin
+ ordint:=ordint or $80000000;
+ internalobjdata.writebytes(ordint,sizeof(ordint));
+ end;
+ end;
+ end;
+
+ begin
+ result:=nil;
+ emptyint:=0;
+ if assigned(exemap) then
+ begin
+ if AOrdNr <= 0 then
+ exemap.Add(' Importing Function '+afuncname)
+ else
+ exemap.Add(' Importing Function '+afuncname+' (OrdNr='+tostr(AOrdNr)+')');
+ end;
+
+ with internalobjdata do
+ begin
+ secname:=basedllname+'_i_'+amangledname;
+ textobjsection:=createsection(sectionname(sec_code,secname,secorder_default),current_settings.alignment.procalign,sectiontype2options(sec_code) - [oso_keep]);
+ idata4objsection:=createsection(sec_idata4, secname);
+ idata5objsection:=createsection(sec_idata5, secname);
+ idata6objsection:=createsection(sec_idata6, secname);
+ end;
+
+ { idata6, import data (ordnr+name) }
+ internalobjdata.SetSection(idata6objsection);
+ inc(idatalabnr);
+ num:=tostr(idatalabnr);
+ idata6label:=internalobjdata.SymbolDefine('__imp_'+num,AB_LOCAL,AT_DATA);
+ absordnr:=Abs(AOrdNr);
+ { write index hint }
+ internalobjdata.writebytes(absordnr,2);
+ if AOrdNr <= 0 then
+ internalobjdata.writebytes(afuncname[1],length(afuncname));
+ internalobjdata.writebytes(emptyint,1);
+ internalobjdata.writebytes(emptyint,align(internalobjdata.CurrObjSec.size,2)-internalobjdata.CurrObjSec.size);
+ { idata4, import lookup table }
+ internalobjdata.SetSection(idata4objsection);
+ idata4label:=internalobjdata.SymbolDefine('__imp_lookup_'+num,AB_LOCAL,AT_DATA);
+ WriteTableEntry;
+ { idata5, import address table }
+ internalobjdata.SetSection(idata5objsection);
+ { dummy back links }
+ internalobjdata.writereloc(0,0,idata4label,RELOC_NONE);
+ internalobjdata.writereloc(0,0,idata2label,RELOC_NONE);
+ { section data }
+ if isvar then
+ result:=internalobjdata.SymbolDefine(amangledname,AB_GLOBAL,AT_DATA)
+ else
+ idata5label:=internalobjdata.SymbolDefine('__imp_'+amangledname,AB_LOCAL,AT_DATA);
+ WriteTableEntry;
+ { text, jmp }
+ if not isvar then
+ begin
+ internalobjdata.SetSection(textobjsection);
+ result:=internalobjdata.SymbolDefine('_'+amangledname,AB_GLOBAL,AT_FUNCTION);
+ internalobjdata.writebytes(jmpopcode,sizeof(jmpopcode));
+{$ifdef x86_64}
+ internalobjdata.writereloc(0,4,idata5label,RELOC_RELATIVE);
+{$else}
+ internalobjdata.writereloc(0,4,idata5label,RELOC_ABSOLUTE32);
+{$endif x86_64}
+
+ internalobjdata.writebytes(nopopcodes,align(internalobjdata.CurrObjSec.size,sizeof(nopopcodes))-internalobjdata.CurrObjSec.size);
+ end;
+ end;
+
+ var
+ i,j : longint;
+ ImportLibrary : TImportLibrary;
+ ImportSymbol : TImportSymbol;
+ exesym : TExeSymbol;
+ begin
+ for i:=0 to ImportLibraryList.Count-1 do
+ begin
+ ImportLibrary:=TImportLibrary(ImportLibraryList[i]);
+ idata2objsection:=nil;
+ idata4objsection:=nil;
+ idata5objsection:=nil;
+ idata6objsection:=nil;
+ idata7objsection:=nil;
+ for j:=0 to ImportLibrary.ImportSymbolList.Count-1 do
+ begin
+ ImportSymbol:=TImportSymbol(ImportLibrary.ImportSymbolList[j]);
+ exesym:=TExeSymbol(ExeSymbolList.Find(ImportSymbol.MangledName));
+ if assigned(exesym) and
+ (exesym.State<>symstate_defined) then
+ begin
+ if not assigned(idata2objsection) then
+ StartImport(ImportLibrary.Name);
+ exesym.objsymbol:=AddImport(ImportSymbol.Name,ImportSymbol.MangledName,ImportSymbol.OrdNr,ImportSymbol.IsVar);
+ exesym.State:=symstate_defined;
+ end;
+ end;
+ if assigned(idata2objsection) then
+ EndImport;
+ end;
+ PackUnresolvedExeSymbols('after DLL imports');
+ end;
+
+
+ procedure TPECoffexeoutput.GenerateRelocs;
+ var
+ pgaddr, hdrpos : longword;
+
+ procedure FinishBlock;
+ var
+ p,len : longint;
+ begin
+ if hdrpos = longword(-1) then
+ exit;
+ p:=0;
+ internalobjdata.writebytes(p,align(internalobjdata.CurrObjSec.size,4)-internalobjdata.CurrObjSec.size);
+ p:=internalObjData.CurrObjSec.Data.Pos;
+ internalObjData.CurrObjSec.Data.seek(hdrpos+4);
+ len:=p-hdrpos;
+ internalObjData.CurrObjSec.Data.write(len,4);
+ internalObjData.CurrObjSec.Data.seek(p);
+ hdrpos:=longword(-1);
+ end;
+
+ var
+ exesec : TExeSection;
+ objsec : TObjSection;
+ objreloc : TObjRelocation;
+ i,j,k : longint;
+ offset : longword;
+ w: word;
+ begin
+ if not RelocSection or FRelocsGenerated then
+ exit;
+ exesec:=FindExeSection('.reloc');
+ if exesec=nil then
+ exit;
+ objsec:=internalObjData.createsection('.reloc',0,exesec.SecOptions+[oso_data]);
+ exesec.AddObjSection(objsec);
+ pgaddr:=longword(-1);
+ hdrpos:=longword(-1);
+ for i:=0 to ExeSectionList.Count-1 do
+ begin
+ exesec:=TExeSection(ExeSectionList[i]);
+ for j:=0 to exesec.ObjSectionList.count-1 do
+ begin
+ objsec:=TObjSection(exesec.ObjSectionList[j]);
+ { create relocs only for sections which are loaded in memory }
+ if not (oso_load in objsec.SecOptions) then
+ continue;
+ for k:=0 to objsec.ObjRelocations.Count-1 do
+ begin
+ objreloc:=TObjRelocation(objsec.ObjRelocations[k]);
+ if not (objreloc.typ in [{$ifdef cpu64bitaddr}RELOC_ABSOLUTE32,{$endif cpu64bitaddr}RELOC_ABSOLUTE]) then
+ continue;
+ offset:=objsec.MemPos+objreloc.dataoffset;
+ if (offset<pgaddr) and (pgaddr<>longword(-1)) then
+ Internalerror(2007062701);
+ if (offset-pgaddr>=4096) or (pgaddr=longword(-1)) then
+ begin
+ FinishBlock;
+ pgaddr:=(offset div 4096)*4096;
+ hdrpos:=internalObjData.CurrObjSec.Data.Pos;
+ internalObjData.writebytes(pgaddr,4);
+ { Reserving space for block size. The size will be written later in FinishBlock }
+ internalObjData.writebytes(k,4);
+ end;
+{$ifdef cpu64bitaddr}
+ if objreloc.typ = RELOC_ABSOLUTE then
+ w:=IMAGE_REL_BASED_DIR64
+ else
+{$endif cpu64bitaddr}
+ w:=IMAGE_REL_BASED_HIGHLOW;
+ w:=(w shl 12) or (offset-pgaddr);
+ internalObjData.writebytes(w,2);
+ end;
+ end;
+ end;
+ FinishBlock;
+ FRelocsGenerated:=true;
+ end;
+
+
+ procedure TPECoffexeoutput.Order_End;
+ var
+ exesec : TExeSection;
+ begin
+ inherited;
+ if not IsSharedLibrary then
+ exit;
+ exesec:=FindExeSection('.reloc');
+ if exesec=nil then
+ exit;
+ exesec.SecOptions:=exesec.SecOptions + [oso_Data,oso_keep,oso_load];
+ end;
+
+
+ procedure TPECoffexeoutput.MemPos_ExeSection(const aname:string);
+ begin
+ if aname='.reloc' then
+ GenerateRelocs;
+ inherited;
+ end;
+
+
+
+{****************************************************************************
+ TDJCoffAssembler
+****************************************************************************}
+
+ constructor TDJCoffAssembler.Create(smart:boolean);
+ begin
+ inherited Create(smart);
+ CObjOutput:=TDJCoffObjOutput;
+ end;
+
+
+{****************************************************************************
+ TPECoffAssembler
+****************************************************************************}
+
+ constructor TPECoffAssembler.Create(smart:boolean);
+ begin
+ inherited Create(smart);
+ CObjOutput:=TPECoffObjOutput;
+ end;
+
+
+{*****************************************************************************
+ DLLReader
+*****************************************************************************}
+
+{$ifdef win32}
+ var
+ Wow64DisableWow64FsRedirection : function (var OldValue : pointer) : boolean;stdcall;
+ Wow64RevertWow64FsRedirection : function (OldValue : pointer) : boolean;stdcall;
+{$endif win32}
+
+ function ReadDLLImports(const dllname:string;readdllproc:Treaddllproc):boolean;
+ type
+ TPECoffExpDir=packed record
+ flag,
+ stamp : cardinal;
+ Major,
+ Minor : word;
+ Name,
+ Base,
+ NumFuncs,
+ NumNames,
+ AddrFuncs,
+ AddrNames,
+ AddrOrds : cardinal;
+ end;
+ var
+ DLLReader : TObjectReader;
+ DosHeader : array[0..$7f] of byte;
+ PEMagic : array[0..3] of byte;
+ Header : TCoffHeader;
+ peheader : tcoffpeoptheader;
+ NameOfs,
+ newheaderofs : longword;
+ FuncName : string;
+ expdir : TPECoffExpDir;
+ i : longint;
+ found : boolean;
+ sechdr : tCoffSecHdr;
+{$ifdef win32}
+ p : pointer;
+{$endif win32}
+ begin
+ result:=false;
+{$ifdef win32}
+ if (target_info.system=system_x86_64_win64) and
+ assigned(Wow64DisableWow64FsRedirection) then
+ Wow64DisableWow64FsRedirection(p);
+{$endif win32}
+ DLLReader:=TObjectReader.Create;
+ DLLReader.OpenFile(dllname);
+{$ifdef win32}
+ if (target_info.system=system_x86_64_win64) and
+ assigned(Wow64RevertWow64FsRedirection) then
+ Wow64RevertWow64FsRedirection(p);
+{$endif win32}
+ if not DLLReader.Read(DosHeader,sizeof(DosHeader)) or
+ (DosHeader[0]<>$4d) or (DosHeader[1]<>$5a) then
+ begin
+ Comment(V_Error,'Invalid DLL '+dllname+', Dos Header invalid');
+ exit;
+ end;
+ newheaderofs:=cardinal(DosHeader[$3c]) or (DosHeader[$3d] shl 8) or (DosHeader[$3e] shl 16) or (DosHeader[$3f] shl 24);
+ DLLReader.Seek(newheaderofs);
+ if not DLLReader.Read(PEMagic,sizeof(PEMagic)) or
+ (PEMagic[0]<>$50) or (PEMagic[1]<>$45) or (PEMagic[2]<>$00) or (PEMagic[3]<>$00) then
+ begin
+ Comment(V_Error,'Invalid DLL '+dllname+': invalid magic code');
+ exit;
+ end;
+ if not DLLReader.Read(Header,sizeof(TCoffHeader)) or
+ (Header.mach<>COFF_MAGIC) or
+ (Header.opthdr<>sizeof(tcoffpeoptheader)) then
+ begin
+ Comment(V_Error,'Invalid DLL '+dllname+', invalid header size');
+ exit;
+ end;
+ { Read optheader }
+ DLLreader.Read(peheader,sizeof(tcoffpeoptheader));
+ { Section headers }
+ found:=false;
+ for i:=1 to header.nsects do
+ begin
+ if not DLLreader.read(sechdr,sizeof(sechdr)) then
+ begin
+ Comment(V_Error,'Error reading coff file '+DLLName);
+ exit;
+ end;
+ if (sechdr.rvaofs<=peheader.DataDirectory[PE_DATADIR_EDATA].vaddr) and
+ (peheader.DataDirectory[PE_DATADIR_EDATA].vaddr<sechdr.rvaofs+sechdr.vsize) then
+ begin
+ found:=true;
+ break;
+ end;
+ end;
+ if not found then
+ begin
+ Comment(V_Warning,'DLL '+DLLName+' does not contain any exports');
+ exit;
+ end;
+ { Process edata }
+ DLLReader.Seek(sechdr.datapos+peheader.DataDirectory[PE_DATADIR_EDATA].vaddr-sechdr.rvaofs);
+ DLLReader.Read(expdir,sizeof(expdir));
+ for i:=0 to expdir.NumNames-1 do
+ begin
+ DLLReader.Seek(sechdr.datapos+expdir.AddrNames-sechdr.rvaofs+i*4);
+ DLLReader.Read(NameOfs,4);
+ Dec(NameOfs,sechdr.rvaofs);
+ if {(NameOfs<0) or}
+ (NameOfs>sechdr.vsize) then
+ begin
+ Comment(V_Error,'DLL does contains invalid exports');
+ break;
+ end;
+ { Read Function name from DLL, prepend _ and terminate with #0 }
+ DLLReader.Seek(sechdr.datapos+NameOfs);
+ DLLReader.Read((@FuncName[1])^,sizeof(FuncName)-3);
+ FuncName[sizeof(FuncName)-1]:=#0;
+ FuncName[0]:=chr(Strlen(@FuncName[1]));
+ readdllproc(DLLName,FuncName);
+ end;
+ DLLReader.Free;
+ end;
+
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+{$ifdef i386}
+ const
+ as_i386_coff_info : tasminfo =
+ (
+ id : as_i386_coff;
+ idtxt : 'COFF';
+ asmbin : '';
+ asmcmd : '';
+ supported_targets : [system_i386_go32v2];
+ flags : [af_outputbinary];
+ labelprefix : '.L';
+ comment : '';
+ );
+
+ as_i386_pecoff_info : tasminfo =
+ (
+ id : as_i386_pecoff;
+ idtxt : 'PECOFF';
+ asmbin : '';
+ asmcmd : '';
+ supported_targets : [system_i386_win32,system_i386_nativent];
+ flags : [af_outputbinary,af_smartlink_sections];
+ labelprefix : '.L';
+ comment : '';
+ );
+
+ as_i386_pecoffwdosx_info : tasminfo =
+ (
+ id : as_i386_pecoffwdosx;
+ idtxt : 'PEWDOSX';
+ asmbin : '';
+ asmcmd : '';
+ supported_targets : [system_i386_wdosx];
+ flags : [af_outputbinary];
+ labelprefix : '.L';
+ comment : '';
+ );
+
+ as_i386_pecoffwince_info : tasminfo =
+ (
+ id : as_i386_pecoffwince;
+ idtxt : 'PECOFFWINCE';
+ asmbin : '';
+ asmcmd : '';
+ supported_targets : [system_i386_wince];
+ flags : [af_outputbinary,af_smartlink_sections];
+ labelprefix : '.L';
+ comment : '';
+ );
+{$endif i386}
+{$ifdef x86_64}
+ const
+ as_x86_64_pecoff_info : tasminfo =
+ (
+ id : as_x86_64_pecoff;
+ idtxt : 'PECOFF';
+ asmbin : '';
+ asmcmd : '';
+ supported_targets : [system_x86_64_win64];
+ flags : [af_outputbinary,af_smartlink_sections];
+ labelprefix : '.L';
+ comment : '';
+ );
+{$endif x86_64}
+{$ifdef arm}
+ const
+ as_arm_pecoffwince_info : tasminfo =
+ (
+ id : as_arm_pecoffwince;
+ idtxt : 'PECOFFWINCE';
+ asmbin : '';
+ asmcmd : '';
+ supported_targets : [system_arm_wince];
+ flags : [af_outputbinary];
+ labelprefix : '.L';
+ comment : '';
+ );
+{$endif arm}
+
+
+{$ifdef win32}
+ procedure SetupProcVars;
+ var
+ hinstLib : THandle;
+ begin
+ Wow64DisableWow64FsRedirection:=nil;
+ Wow64RevertWow64FsRedirection:=nil;
+ hinstLib:=LoadLibrary('kernel32.dll');
+ if hinstLib<>0 then
+ begin
+ pointer(Wow64DisableWow64FsRedirection):=GetProcAddress(hinstLib,'Wow64DisableWow64FsRedirection');
+ pointer(Wow64RevertWow64FsRedirection):=GetProcAddress(hinstLib,'Wow64RevertWow64FsRedirection');
+ FreeLibrary(hinstLib);
+ end;
+ end;
+{$endif win32}
+
+
+initialization
+{$ifdef i386}
+ RegisterAssembler(as_i386_coff_info,TDJCoffAssembler);
+ RegisterAssembler(as_i386_pecoff_info,TPECoffAssembler);
+ RegisterAssembler(as_i386_pecoffwdosx_info,TPECoffAssembler);
+ RegisterAssembler(as_i386_pecoffwince_info,TPECoffAssembler);
+{$endif i386}
+{$ifdef x86_64}
+ RegisterAssembler(as_x86_64_pecoff_info,TPECoffAssembler);
+{$endif x86_64}
+{$ifdef arm}
+ RegisterAssembler(as_arm_pecoffwince_info,TPECoffAssembler);
+{$endif arm}
+{$ifdef win32}
+ SetupProcVars;
+{$endif win32}
+end.
diff --git a/closures/compiler/ogelf.pas b/closures/compiler/ogelf.pas
new file mode 100644
index 0000000000..89e53898ad
--- /dev/null
+++ b/closures/compiler/ogelf.pas
@@ -0,0 +1,1318 @@
+{
+ Copyright (c) 1998-2006 by Peter Vreman
+
+ Contains the binary elf writer
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit ogelf;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ { common }
+ cclasses,globtype,
+ { target }
+ systems,
+ { assembler }
+ cpuinfo,cpubase,aasmbase,aasmtai,aasmdata,assemble,
+ { output }
+ ogbase,
+ owbase;
+
+ type
+ TElfObjSection = class(TObjSection)
+ public
+ secshidx : longint; { index for the section in symtab }
+ shstridx,
+ shtype,
+ shflags,
+ shlink,
+ shinfo,
+ shentsize : longint;
+ constructor create(AList:TFPHashObjectList;const Aname:string;Aalign:shortint;Aoptions:TObjSectionOptions);override;
+ constructor create_ext(AList:TFPHashObjectList;const Aname:string;Ashtype,Ashflags,Ashlink,Ashinfo:longint;Aalign:shortint;Aentsize:longint);
+ destructor destroy;override;
+ end;
+
+ TElfObjData = class(TObjData)
+ public
+ constructor create(const n:string);override;
+ destructor destroy;override;
+ function sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;override;
+ procedure CreateDebugSections;override;
+ procedure writereloc(data:aint;len:aword;p:TObjSymbol;reltype:TObjRelocationType);override;
+ end;
+
+ TElfObjectOutput = class(tObjOutput)
+ private
+ symtabsect,
+ strtabsect,
+ shstrtabsect: TElfObjSection;
+ {gotpcsect,
+ gotoffsect,
+ goTSect,
+ plTSect,
+ symsect : TElfObjSection;}
+ elf32data : TElfObjData;
+ symidx,
+ localsyms : longint;
+ procedure createrelocsection(s:TElfObjSection);
+ procedure createshstrtab;
+ procedure createsymtab;
+ procedure writesectionheader(s:TElfObjSection);
+ procedure writesectiondata(s:TElfObjSection);
+ procedure write_internal_symbol(astridx:longint;ainfo:byte;ashndx:word);
+ procedure section_write_symbol(p:TObject;arg:pointer);
+ procedure section_write_sh_string(p:TObject;arg:pointer);
+ procedure section_count_sections(p:TObject;arg:pointer);
+ procedure section_create_relocsec(p:TObject;arg:pointer);
+ procedure section_set_datapos(p:TObject;arg:pointer);
+ procedure section_write_data(p:TObject;arg:pointer);
+ procedure section_write_sechdr(p:TObject;arg:pointer);
+ protected
+ function writedata(data:TObjData):boolean;override;
+ public
+ constructor Create(AWriter:TObjectWriter);override;
+ destructor Destroy;override;
+ end;
+
+ TElfAssembler = class(tinternalassembler)
+ constructor create(smart:boolean);override;
+ end;
+
+
+implementation
+
+ uses
+ SysUtils,
+ verbose,
+ cutils,globals,fmodule;
+
+ const
+ symbolresize = 200*18;
+
+ const
+ { Relocation types }
+{$ifdef i386}
+ R_386_32 = 1; { ordinary absolute relocation }
+ R_386_PC32 = 2; { PC-relative relocation }
+ R_386_GOT32 = 3; { an offset into GOT }
+ R_386_PLT32 = 4; { a PC-relative offset into PLT }
+ R_386_GOTOFF = 9; { an offset from GOT base }
+ R_386_GOTPC = 10; { a PC-relative offset _to_ GOT }
+ R_386_GNU_VTINHERIT = 250;
+ R_386_GNU_VTENTRY = 251;
+{$endif i386}
+{$ifdef sparc}
+ R_SPARC_32 = 3;
+ R_SPARC_WDISP30 = 7;
+ R_SPARC_HI22 = 9;
+ R_SPARC_LO10 = 12;
+ R_SPARC_GNU_VTINHERIT = 250;
+ R_SPARC_GNU_VTENTRY = 251;
+{$endif sparc}
+{$ifdef x86_64}
+ R_X86_64_NONE = 0;
+ { Direct 64 bit }
+ R_X86_64_64 = 1;
+ { PC relative 32 bit signed }
+ R_X86_64_PC32 = 2;
+ { 32 bit GOT entry }
+ R_X86_64_GOT32 = 3;
+ { 32 bit PLT address }
+ R_X86_64_PLT32 = 4;
+ { Copy symbol at runtime }
+ R_X86_64_COPY = 5;
+ { Create GOT entry }
+ R_X86_64_GLOB_DAT = 6;
+ { Create PLT entry }
+ R_X86_64_JUMP_SLOT = 7;
+ { Adjust by program base }
+ R_X86_64_RELATIVE = 8;
+ { 32 bit signed PC relative offset to GOT }
+ R_X86_64_GOTPCREL = 9;
+ { Direct 32 bit zero extended }
+ R_X86_64_32 = 10;
+ { Direct 32 bit sign extended }
+ R_X86_64_32S = 11;
+ { Direct 16 bit zero extended }
+ R_X86_64_16 = 12;
+ { 16 bit sign extended PC relative }
+ R_X86_64_PC16 = 13;
+ { Direct 8 bit sign extended }
+ R_X86_64_8 = 14;
+ { 8 bit sign extended PC relative }
+ R_X86_64_PC8 = 15;
+ { ID of module containing symbol }
+ R_X86_64_DTPMOD64 = 16;
+ { Offset in module's TLS block }
+ R_X86_64_DTPOFF64 = 17;
+ { Offset in initial TLS block }
+ R_X86_64_TPOFF64 = 18;
+ { 32 bit signed PC relative offset to two GOT entries for GD symbol }
+ R_X86_64_TLSGD = 19;
+ { 32 bit signed PC relative offset to two GOT entries for LD symbol }
+ R_X86_64_TLSLD = 20;
+ { Offset in TLS block }
+ R_X86_64_DTPOFF32 = 21;
+ { 32 bit signed PC relative offset to GOT entry for IE symbol }
+ R_X86_64_GOTTPOFF = 22;
+ { Offset in initial TLS block }
+ R_X86_64_TPOFF32 = 23;
+ { GNU extension to record C++ vtable hierarchy }
+ R_X86_64_GNU_VTINHERIT = 24;
+ { GNU extension to record C++ vtable member usage }
+ R_X86_64_GNU_VTENTRY = 25;
+{$endif x86_64}
+
+ SHN_UNDEF = 0;
+ SHN_ABS = $fff1;
+ SHN_COMMON = $fff2;
+
+ SHT_NULL = 0;
+ SHT_PROGBITS = 1;
+ SHT_SYMTAB = 2;
+ SHT_STRTAB = 3;
+ SHT_RELA = 4;
+ SHT_HASH = 5;
+ SHT_DYNAMIC = 6;
+ SHT_NOTE = 7;
+ SHT_NOBITS = 8;
+ SHT_REL = 9;
+ SHT_SHLIB = 10;
+ SHT_DYNSYM = 11;
+
+ SHF_WRITE = 1;
+ SHF_ALLOC = 2;
+ SHF_EXECINSTR = 4;
+
+ STB_LOCAL = 0;
+ STB_GLOBAL = 1;
+ STB_WEAK = 2;
+
+ STT_NOTYPE = 0;
+ STT_OBJECT = 1;
+ STT_FUNC = 2;
+ STT_SECTION = 3;
+ STT_FILE = 4;
+
+ type
+ { Structures which are written directly to the output file }
+ TElf32header=packed record
+ magic0123 : longint;
+ file_class : byte;
+ data_encoding : byte;
+ file_version : byte;
+ padding : array[$07..$0f] of byte;
+ e_type : word;
+ e_machine : word;
+ e_version : longint;
+ e_entry : longint; { entrypoint }
+ e_phoff : longint; { program header offset }
+ e_shoff : longint; { sections header offset }
+ e_flags : longint;
+ e_ehsize : word; { elf header size in bytes }
+ e_phentsize : word; { size of an entry in the program header array }
+ e_phnum : word; { 0..e_phnum-1 of entrys }
+ e_shentsize : word; { size of an entry in sections header array }
+ e_shnum : word; { 0..e_shnum-1 of entrys }
+ e_shstrndx : word; { index of string section header }
+ end;
+ TElf32sechdr=packed record
+ sh_name : longint;
+ sh_type : longint;
+ sh_flags : longint;
+ sh_addr : longint;
+ sh_offset : longint;
+ sh_size : longint;
+ sh_link : longint;
+ sh_info : longint;
+ sh_addralign : longint;
+ sh_entsize : longint;
+ end;
+ TElf32reloc=packed record
+ address : longint;
+ info : longint; { bit 0-7: type, 8-31: symbol }
+ end;
+ TElf32symbol=packed record
+ st_name : longint;
+ st_value : longint;
+ st_size : longint;
+ st_info : byte; { bit 0-3: type, 4-7: bind }
+ st_other : byte;
+ st_shndx : word;
+ end;
+
+
+ telf64header=packed record
+ magic0123 : longint;
+ file_class : byte;
+ data_encoding : byte;
+ file_version : byte;
+ padding : array[$07..$0f] of byte;
+ e_type : word;
+ e_machine : word;
+ e_version : longint;
+ e_entry : qword; { entrypoint }
+ e_phoff : qword; { program header offset }
+ e_shoff : qword; { sections header offset }
+ e_flags : longint;
+ e_ehsize : word; { elf header size in bytes }
+ e_phentsize : word; { size of an entry in the program header array }
+ e_phnum : word; { 0..e_phnum-1 of entrys }
+ e_shentsize : word; { size of an entry in sections header array }
+ e_shnum : word; { 0..e_shnum-1 of entrys }
+ e_shstrndx : word; { index of string section header }
+ end;
+ telf64sechdr=packed record
+ sh_name : longint;
+ sh_type : longint;
+ sh_flags : qword;
+ sh_addr : qword;
+ sh_offset : qword;
+ sh_size : qword;
+ sh_link : longint;
+ sh_info : longint;
+ sh_addralign : qword;
+ sh_entsize : qword;
+ end;
+ telf64reloc=packed record
+ address : qword;
+ info : qword; { bit 0-31: type, 32-63: symbol }
+ addend : int64; { signed! }
+ end;
+ telf64symbol=packed record
+ st_name : longint;
+ st_info : byte; { bit 0-3: type, 4-7: bind }
+ st_other : byte;
+ st_shndx : word;
+ st_value : qword;
+ st_size : qword;
+ end;
+
+
+{$ifdef cpu64bitaddr}
+ telfheader = telf64header;
+ telfreloc = telf64reloc;
+ telfsymbol = telf64symbol;
+ telfsechdr = telf64sechdr;
+{$else cpu64bitaddr}
+ telfheader = telf32header;
+ telfreloc = telf32reloc;
+ telfsymbol = telf32symbol;
+ telfsechdr = telf32sechdr;
+{$endif cpu64bitaddr}
+
+
+ function MayBeSwapHeader(h : telf32header) : telf32header;
+ begin
+ result:=h;
+ if source_info.endian<>target_info.endian then
+ with h do
+ begin
+ result.e_type:=swapendian(e_type);
+ result.e_machine:=swapendian(e_machine);
+ result.e_version:=swapendian(e_version);
+ result.e_entry:=swapendian(e_entry);
+ result.e_phoff:=swapendian(e_phoff);
+ result.e_shoff:=swapendian(e_shoff);
+ result.e_flags:=swapendian(e_flags);
+ result.e_ehsize:=swapendian(e_ehsize);
+ result.e_phentsize:=swapendian(e_phentsize);
+ result.e_phnum:=swapendian(e_phnum);
+ result.e_shentsize:=swapendian(e_shentsize);
+ result.e_shnum:=swapendian(e_shnum);
+ result.e_shstrndx:=swapendian(e_shstrndx);
+ end;
+ end;
+
+
+ function MayBeSwapHeader(h : telf64header) : telf64header;
+ begin
+ result:=h;
+ if source_info.endian<>target_info.endian then
+ with h do
+ begin
+ result.e_type:=swapendian(e_type);
+ result.e_machine:=swapendian(e_machine);
+ result.e_version:=swapendian(e_version);
+ result.e_entry:=swapendian(e_entry);
+ result.e_phoff:=swapendian(e_phoff);
+ result.e_shoff:=swapendian(e_shoff);
+ result.e_flags:=swapendian(e_flags);
+ result.e_ehsize:=swapendian(e_ehsize);
+ result.e_phentsize:=swapendian(e_phentsize);
+ result.e_phnum:=swapendian(e_phnum);
+ result.e_shentsize:=swapendian(e_shentsize);
+ result.e_shnum:=swapendian(e_shnum);
+ result.e_shstrndx:=swapendian(e_shstrndx);
+ end;
+ end;
+
+
+ function MaybeSwapSecHeader(h : telf32sechdr) : telf32sechdr;
+ begin
+ result:=h;
+ if source_info.endian<>target_info.endian then
+ with h do
+ begin
+ result.sh_name:=swapendian(sh_name);
+ result.sh_type:=swapendian(sh_type);
+ result.sh_flags:=swapendian(sh_flags);
+ result.sh_addr:=swapendian(sh_addr);
+ result.sh_offset:=swapendian(sh_offset);
+ result.sh_size:=swapendian(sh_size);
+ result.sh_link:=swapendian(sh_link);
+ result.sh_info:=swapendian(sh_info);
+ result.sh_addralign:=swapendian(sh_addralign);
+ result.sh_entsize:=swapendian(sh_entsize);
+ end;
+ end;
+
+
+ function MaybeSwapSecHeader(h : telf64sechdr) : telf64sechdr;
+ begin
+ result:=h;
+ if source_info.endian<>target_info.endian then
+ with h do
+ begin
+ result.sh_name:=swapendian(sh_name);
+ result.sh_type:=swapendian(sh_type);
+ result.sh_flags:=swapendian(sh_flags);
+ result.sh_addr:=swapendian(sh_addr);
+ result.sh_offset:=swapendian(sh_offset);
+ result.sh_size:=swapendian(sh_size);
+ result.sh_link:=swapendian(sh_link);
+ result.sh_info:=swapendian(sh_info);
+ result.sh_addralign:=swapendian(sh_addralign);
+ result.sh_entsize:=swapendian(sh_entsize);
+ end;
+ end;
+
+
+ function MaybeSwapElfSymbol(h : telf32symbol) : telf32symbol;
+ begin
+ result:=h;
+ if source_info.endian<>target_info.endian then
+ with h do
+ begin
+ result.st_name:=swapendian(st_name);
+ result.st_value:=swapendian(st_value);
+ result.st_size:=swapendian(st_size);
+ result.st_shndx:=swapendian(st_shndx);
+ end;
+ end;
+
+
+ function MaybeSwapElfSymbol(h : telf64symbol) : telf64symbol;
+ begin
+ result:=h;
+ if source_info.endian<>target_info.endian then
+ with h do
+ begin
+ result.st_name:=swapendian(st_name);
+ result.st_value:=swapendian(st_value);
+ result.st_size:=swapendian(st_size);
+ result.st_shndx:=swapendian(st_shndx);
+ end;
+ end;
+
+
+ function MaybeSwapElfReloc(h : telf32reloc) : telf32reloc;
+ begin
+ result:=h;
+ if source_info.endian<>target_info.endian then
+ with h do
+ begin
+ result.address:=swapendian(address);
+ result.info:=swapendian(info);
+ end;
+ end;
+
+
+ function MaybeSwapElfReloc(h : telf64reloc) : telf64reloc;
+ begin
+ result:=h;
+ if source_info.endian<>target_info.endian then
+ with h do
+ begin
+ result.address:=swapendian(address);
+ result.info:=swapendian(info);
+ end;
+ end;
+
+
+{****************************************************************************
+ Helpers
+****************************************************************************}
+
+ procedure encodesechdrflags(aoptions:TObjSectionOptions;out AshType:longint;out Ashflags:longint);
+ begin
+ { Section Type }
+ AshType:=SHT_PROGBITS;
+ if oso_strings in aoptions then
+ AshType:=SHT_STRTAB
+ else if not(oso_data in aoptions) then
+ AshType:=SHT_NOBITS;
+ { Section Flags }
+ Ashflags:=0;
+ if oso_load in aoptions then
+ Ashflags:=Ashflags or SHF_ALLOC;
+ if oso_executable in aoptions then
+ Ashflags:=Ashflags or SHF_EXECINSTR;
+ if oso_write in aoptions then
+ Ashflags:=Ashflags or SHF_WRITE;
+ end;
+
+
+ procedure decodesechdrflags(AshType:longint;Ashflags:longint;out aoptions:TObjSectionOptions);
+ begin
+ aoptions:=[];
+ { Section Type }
+ if AshType<>SHT_NOBITS then
+ include(aoptions,oso_data);
+ if AshType=SHT_STRTAB then
+ include(aoptions,oso_strings);
+ { Section Flags }
+ if Ashflags and SHF_ALLOC<>0 then
+ include(aoptions,oso_load)
+ else
+ include(aoptions,oso_noload);
+ if Ashflags and SHF_WRITE<>0 then
+ include(aoptions,oso_write)
+ else
+ include(aoptions,oso_readonly);
+ end;
+
+
+{****************************************************************************
+ TSection
+****************************************************************************}
+
+ constructor TElfObjSection.create(AList:TFPHashObjectList;const Aname:string;Aalign:shortint;Aoptions:TObjSectionOptions);
+ begin
+ inherited create(AList,Aname,Aalign,aoptions);
+ secshidx:=0;
+ shstridx:=0;
+ encodesechdrflags(aoptions,shtype,shflags);
+ shlink:=0;
+ shinfo:=0;
+ if name='.stab' then
+ shentsize:=sizeof(TObjStabEntry);
+ end;
+
+
+ constructor TElfObjSection.create_ext(AList:TFPHashObjectList;const Aname:string;Ashtype,Ashflags,Ashlink,Ashinfo:longint;Aalign:shortint;Aentsize:longint);
+ var
+ aoptions : TObjSectionOptions;
+ begin
+ decodesechdrflags(Ashtype,Ashflags,aoptions);
+ inherited create(AList,Aname,Aalign,aoptions);
+ secshidx:=0;
+ shstridx:=0;
+ shtype:=AshType;
+ shflags:=AshFlags;
+ shlink:=Ashlink;
+ shinfo:=Ashinfo;
+ shentsize:=Aentsize;
+ end;
+
+
+ destructor TElfObjSection.destroy;
+ begin
+ inherited destroy;
+ end;
+
+
+{****************************************************************************
+ TElfObjData
+****************************************************************************}
+
+ constructor TElfObjData.create(const n:string);
+ var
+ need_datarel : boolean;
+ begin
+ inherited create(n);
+ CObjSection:=TElfObjSection;
+ { we need at least the following sections }
+ createsection(sec_code);
+ if (cs_create_pic in current_settings.moduleswitches) and
+ not(target_info.system in systems_darwin) then
+ begin
+ { We still need an empty data section }
+ system.exclude(current_settings.moduleswitches,cs_create_pic);
+ need_datarel:=true;
+ end
+ else
+ need_datarel:=false;
+ createsection(sec_data);
+ if need_datarel then
+ system.include(current_settings.moduleswitches,cs_create_pic);
+ createsection(sec_bss);
+ if need_datarel then
+ createsection(sec_data);
+ if tf_section_threadvars in target_info.flags then
+ createsection(sec_threadvar);
+ if (tf_needs_dwarf_cfi in target_info.flags) and
+ (af_supports_dwarf in target_asm.flags) then
+ createsection(sec_debug_frame);
+ end;
+
+
+ destructor TElfObjData.destroy;
+ begin
+ inherited destroy;
+ end;
+
+
+ function TElfObjData.sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;
+ const
+ secnames : array[TAsmSectiontype] of string[length('__DATA, __datacoal_nt,coalesced')] = ('','',
+{$ifdef userodata}
+ '.text','.data','.data','.rodata','.bss','.threadvar',
+{$else userodata}
+ '.text','.data','.data','.data','.bss','.threadvar',
+{$endif userodata}
+ '.pdata',
+ '.text', { darwin stubs }
+ '__DATA,__nl_symbol_ptr',
+ '__DATA,__la_symbol_ptr',
+ '__DATA,__mod_init_func',
+ '__DATA,__mod_term_func',
+ '.stab','.stabstr',
+ '.idata$2','.idata$4','.idata$5','.idata$6','.idata$7','.edata',
+ '.eh_frame',
+ '.debug_frame','.debug_info','.debug_line','.debug_abbrev',
+ '.fpc',
+ '.toc',
+ '.init',
+ '.fini',
+ '.objc_class',
+ '.objc_meta_class',
+ '.objc_cat_cls_meth',
+ '.objc_cat_inst_meth',
+ '.objc_protocol',
+ '.objc_string_object',
+ '.objc_cls_meth',
+ '.objc_inst_meth',
+ '.objc_cls_refs',
+ '.objc_message_refs',
+ '.objc_symbols',
+ '.objc_category',
+ '.objc_class_vars',
+ '.objc_instance_vars',
+ '.objc_module_info',
+ '.objc_class_names',
+ '.objc_meth_var_types',
+ '.objc_meth_var_names',
+ '.objc_selector_strs',
+ '.objc_protocol_ext',
+ '.objc_class_ext',
+ '.objc_property',
+ '.objc_image_info',
+ '.objc_cstring_object',
+ '.objc_sel_fixup',
+ '__DATA,__objc_data',
+ '__DATA,__objc_const',
+ '.objc_superrefs',
+ '__DATA, __datacoal_nt,coalesced',
+ '.objc_classlist',
+ '.objc_nlclasslist',
+ '.objc_catlist',
+ '.obcj_nlcatlist',
+ '.objc_protolist'
+ );
+ secnames_pic : array[TAsmSectiontype] of string[length('__DATA, __datacoal_nt,coalesced')] = ('','',
+ '.text',
+ '.data.rel',
+ '.data.rel',
+ '.data.rel',
+ '.bss',
+ '.threadvar',
+ '.pdata',
+ '', { stubs }
+ '__DATA,__nl_symbol_ptr',
+ '__DATA,__la_symbol_ptr',
+ '__DATA,__mod_init_func',
+ '__DATA,__mod_term_func',
+ '.stab',
+ '.stabstr',
+ '.idata$2','.idata$4','.idata$5','.idata$6','.idata$7','.edata',
+ '.eh_frame',
+ '.debug_frame','.debug_info','.debug_line','.debug_abbrev',
+ '.fpc',
+ '.toc',
+ '.init',
+ '.fini',
+ '.objc_class',
+ '.objc_meta_class',
+ '.objc_cat_cls_meth',
+ '.objc_cat_inst_meth',
+ '.objc_protocol',
+ '.objc_string_object',
+ '.objc_cls_meth',
+ '.objc_inst_meth',
+ '.objc_cls_refs',
+ '.objc_message_refs',
+ '.objc_symbols',
+ '.objc_category',
+ '.objc_class_vars',
+ '.objc_instance_vars',
+ '.objc_module_info',
+ '.objc_class_names',
+ '.objc_meth_var_types',
+ '.objc_meth_var_names',
+ '.objc_selector_strs',
+ '.objc_protocol_ext',
+ '.objc_class_ext',
+ '.objc_property',
+ '.objc_image_info',
+ '.objc_cstring_object',
+ '.objc_sel_fixup',
+ '__DATA,__objc_data',
+ '__DATA,__objc_const',
+ '.objc_superrefs',
+ '__DATA, __datacoal_nt,coalesced',
+ '.objc_classlist',
+ '.objc_nlclasslist',
+ '.objc_catlist',
+ '.obcj_nlcatlist',
+ '.objc_protolist'
+ );
+ var
+ sep : string[3];
+ secname : string;
+ begin
+ { section type user gives the user full controll on the section name }
+ if atype=sec_user then
+ result:=aname
+ else
+ begin
+ if (cs_create_pic in current_settings.moduleswitches) and
+ not(target_info.system in systems_darwin) then
+ secname:=secnames_pic[atype]
+ else
+ secname:=secnames[atype];
+ if (atype=sec_fpc) and (Copy(aname,1,3)='res') then
+ begin
+ result:=secname+'.'+aname;
+ exit;
+ end;
+ if create_smartlink_sections and (aname<>'') then
+ begin
+ case aorder of
+ secorder_begin :
+ sep:='.b_';
+ secorder_end :
+ sep:='.z_';
+ else
+ sep:='.n_';
+ end;
+ result:=secname+sep+aname
+ end
+ else
+ result:=secname;
+ end;
+ end;
+
+
+ procedure TElfObjData.CreateDebugSections;
+ begin
+ if target_dbg.id=dbg_stabs then
+ begin
+ stabssec:=createsection(sec_stab);
+ stabstrsec:=createsection(sec_stabstr);
+ end;
+ end;
+
+
+ procedure TElfObjData.writereloc(data:aint;len:aword;p:TObjSymbol;reltype:TObjRelocationType);
+ var
+ symaddr : aint;
+ begin
+ if CurrObjSec=nil then
+ internalerror(200403292);
+{$ifdef userodata}
+ if CurrObjSec.sectype in [sec_rodata,sec_bss,sec_threadvar] then
+ internalerror(200408252);
+{$endif userodata}
+ { Using RELOC_RVA to map 32-bit RELOC_ABSOLUTE to R_X86_64_32
+ (RELOC_ABSOLUTE maps to R_X86_64_32S) }
+ if (reltype=RELOC_ABSOLUTE) and (len<>sizeof(pint)) then
+ reltype:=RELOC_RVA;
+ if assigned(p) then
+ begin
+ { real address of the symbol }
+ symaddr:=p.address;
+ { Local ObjSymbols can be resolved already or need a section reloc }
+ if (p.bind=AB_LOCAL) and
+ (reltype in [RELOC_RELATIVE,RELOC_ABSOLUTE{$ifdef x86_64},RELOC_ABSOLUTE32,RELOC_RVA{$endif x86_64}]) then
+ begin
+ { For a reltype relocation in the same section the
+ value can be calculated }
+ if (p.objsection=CurrObjSec) and
+ (reltype=RELOC_RELATIVE) then
+ inc(data,symaddr-len-CurrObjSec.Size)
+ else
+ begin
+ CurrObjSec.addsectionreloc(CurrObjSec.Size,p.objsection,reltype);
+ inc(data,symaddr);
+ end;
+ end
+ else
+ begin
+ CurrObjSec.addsymreloc(CurrObjSec.Size,p,reltype);
+{$ifndef x86_64}
+ if (reltype=RELOC_RELATIVE) or (reltype=RELOC_PLT32) then
+ dec(data,len);
+{$endif x86_64}
+ end;
+ end;
+ CurrObjSec.write(data,len);
+ end;
+
+
+{****************************************************************************
+ TElfObjectOutput
+****************************************************************************}
+
+ constructor TElfObjectOutput.create(AWriter:TObjectWriter);
+ begin
+ inherited Create(AWriter);
+ CObjData:=TElfObjData;
+ end;
+
+
+ destructor TElfObjectOutput.destroy;
+ begin
+ inherited destroy;
+ end;
+
+
+ procedure TElfObjectOutput.createrelocsection(s:TElfObjSection);
+ var
+ i : longint;
+ rel : telfreloc;
+ objreloc : TObjRelocation;
+ relsym,
+ reltyp : longint;
+ relocsect : TObjSection;
+{$ifdef x86_64}
+ tmp: aint;
+ asize: longint;
+{$endif x86_64}
+ begin
+ with elf32data do
+ begin
+{$ifdef userodata}
+ { rodata can't have relocations }
+ if s.sectype=sec_rodata then
+ begin
+ if assigned(s.relocations.first) then
+ internalerror(200408251);
+ exit;
+ end;
+{$endif userodata}
+ { create the reloc section }
+{$ifdef i386}
+ relocsect:=TElfObjSection.create_ext(ObjSectionList,'.rel'+s.name,SHT_REL,0,symtabsect.secshidx,s.secshidx,4,sizeof(TElfReloc));
+{$else i386}
+ relocsect:=TElfObjSection.create_ext(ObjSectionList,'.rela'+s.name,SHT_RELA,0,symtabsect.secshidx,s.secshidx,4,sizeof(TElfReloc));
+{$endif i386}
+ { add the relocations }
+ for i:=0 to s.Objrelocations.count-1 do
+ begin
+ objreloc:=TObjRelocation(s.Objrelocations[i]);
+ fillchar(rel,sizeof(rel),0);
+ rel.address:=objreloc.dataoffset;
+
+ { when things settle down, we can create processor specific
+ derived classes }
+ case objreloc.typ of
+{$ifdef i386}
+ RELOC_RELATIVE :
+ reltyp:=R_386_PC32;
+ RELOC_ABSOLUTE :
+ reltyp:=R_386_32;
+ RELOC_GOT32 :
+ reltyp:=R_386_GOT32;
+ RELOC_GOTPC :
+ reltyp:=R_386_GOTPC;
+ RELOC_PLT32 :
+ begin
+ reltyp:=R_386_PLT32;
+ end;
+{$endif i386}
+{$ifdef sparc}
+ RELOC_ABSOLUTE :
+ reltyp:=R_SPARC_32;
+{$endif sparc}
+{$ifdef x86_64}
+ RELOC_RELATIVE :
+ begin
+ reltyp:=R_X86_64_PC32;
+ { length of the relocated location is handled here }
+ rel.addend:=-4;
+ end;
+ RELOC_ABSOLUTE :
+ reltyp:=R_X86_64_64;
+ RELOC_ABSOLUTE32 :
+ reltyp:=R_X86_64_32S;
+ RELOC_RVA :
+ reltyp:=R_X86_64_32;
+ RELOC_GOTPCREL :
+ begin
+ reltyp:=R_X86_64_GOTPCREL;
+ { length of the relocated location is handled here }
+ rel.addend:=-4;
+ end;
+ RELOC_PLT32 :
+ begin
+ reltyp:=R_X86_64_PLT32;
+ { length of the relocated location is handled here }
+ rel.addend:=-4;
+ end;
+{$endif x86_64}
+ else
+ internalerror(200602261);
+ end;
+
+{ This handles ELF 'rela'-styled relocations, which are currently used only for x86_64,
+ but can be used other targets, too. }
+{$ifdef x86_64}
+ s.Data.Seek(objreloc.dataoffset);
+ if objreloc.typ=RELOC_ABSOLUTE then
+ begin
+ asize:=8;
+ s.Data.Read(tmp,8);
+ rel.addend:=rel.addend+tmp;
+ end
+ else
+ begin
+ asize:=4;
+ s.Data.Read(tmp,4);
+ rel.addend:=rel.addend+longint(tmp);
+ end;
+
+ { and zero the data member out }
+ tmp:=0;
+ s.Data.Seek(objreloc.dataoffset);
+ s.Data.Write(tmp,asize);
+{$endif}
+
+ { Symbol }
+ if assigned(objreloc.symbol) then
+ begin
+ if objreloc.symbol.symidx=-1 then
+ begin
+ writeln(objreloc.symbol.Name);
+ internalerror(200603012);
+ end;
+ relsym:=objreloc.symbol.symidx;
+ end
+ else
+ begin
+ if objreloc.objsection<>nil then
+ relsym:=objreloc.objsection.secsymidx
+ else
+ relsym:=SHN_UNDEF;
+ end;
+{$ifdef cpu64bitaddr}
+ rel.info:=(qword(relsym) shl 32) or reltyp;
+{$else cpu64bitaddr}
+ rel.info:=(relsym shl 8) or reltyp;
+{$endif cpu64bitaddr}
+ { write reloc }
+ relocsect.write(MaybeSwapElfReloc(rel),sizeof(rel));
+ end;
+ end;
+ end;
+
+
+ procedure TElfObjectOutput.write_internal_symbol(astridx:longint;ainfo:byte;ashndx:word);
+ var
+ elfsym : telfsymbol;
+ begin
+ fillchar(elfsym,sizeof(elfsym),0);
+ elfsym.st_name:=astridx;
+ elfsym.st_info:=ainfo;
+ elfsym.st_shndx:=ashndx;
+ inc(symidx);
+ inc(localsyms);
+ symtabsect.write(MaybeSwapElfSymbol(elfsym),sizeof(elfsym));
+ end;
+
+
+ procedure TElfObjectOutput.section_write_symbol(p:TObject;arg:pointer);
+ begin
+ TObjSection(p).secsymidx:=symidx;
+ write_internal_symbol(TElfObjSection(p).shstridx,STT_SECTION,TElfObjSection(p).secshidx);
+ end;
+
+
+ procedure TElfObjectOutput.createsymtab;
+
+ procedure WriteSym(objsym:TObjSymbol);
+ var
+ elfsym : telfsymbol;
+ begin
+ with elf32data do
+ begin
+ fillchar(elfsym,sizeof(elfsym),0);
+ { symbolname, write the #0 separate to overcome 255+1 char not possible }
+ elfsym.st_name:=strtabsect.Size;
+ strtabsect.writestr(objsym.name);
+ strtabsect.writestr(#0);
+ elfsym.st_size:=objsym.size;
+ case objsym.bind of
+ AB_LOCAL :
+ begin
+ elfsym.st_value:=objsym.address;
+ elfsym.st_info:=STB_LOCAL shl 4;
+ inc(localsyms);
+ end;
+ AB_COMMON :
+ begin
+ elfsym.st_value:=$10;
+ elfsym.st_info:=STB_GLOBAL shl 4;
+ end;
+ AB_EXTERNAL :
+ elfsym.st_info:=STB_GLOBAL shl 4;
+ AB_WEAK_EXTERNAL :
+ elfsym.st_info:=STB_WEAK shl 4;
+ AB_GLOBAL :
+ begin
+ elfsym.st_value:=objsym.address;
+ elfsym.st_info:=STB_GLOBAL shl 4;
+ end;
+ end;
+ if (objsym.bind<>AB_EXTERNAL) {and
+ not(assigned(objsym.objsection) and
+ not(oso_data in objsym.objsection.secoptions))} then
+ begin
+ case objsym.typ of
+ AT_FUNCTION :
+ elfsym.st_info:=elfsym.st_info or STT_FUNC;
+ AT_DATA :
+ elfsym.st_info:=elfsym.st_info or STT_OBJECT;
+ end;
+ end;
+ if objsym.bind=AB_COMMON then
+ elfsym.st_shndx:=SHN_COMMON
+ else
+ begin
+ if assigned(objsym.objsection) then
+ elfsym.st_shndx:=TElfObjSection(objsym.objsection).secshidx
+ else
+ elfsym.st_shndx:=SHN_UNDEF;
+ end;
+ objsym.symidx:=symidx;
+ inc(symidx);
+ symtabsect.write(MaybeSwapElfSymbol(elfsym),sizeof(elfsym));
+ end;
+ end;
+
+ var
+ i : longint;
+ objsym : TObjSymbol;
+ begin
+ with elf32data do
+ begin
+ symidx:=0;
+ localsyms:=0;
+ { empty entry }
+ write_internal_symbol(0,0,0);
+ { filename entry }
+ write_internal_symbol(1,STT_FILE,SHN_ABS);
+ { section }
+ ObjSectionList.ForEachCall(@section_write_symbol,nil);
+ { First the Local Symbols, this is required by ELF. The localsyms
+ count stored in shinfo is used to skip the local symbols
+ when traversing the symtab }
+ for i:=0 to ObjSymbolList.Count-1 do
+ begin
+ objsym:=TObjSymbol(ObjSymbolList[i]);
+ if (objsym.bind=AB_LOCAL) and (objsym.typ<>AT_LABEL) then
+ WriteSym(objsym);
+ end;
+ { Global Symbols }
+ for i:=0 to ObjSymbolList.Count-1 do
+ begin
+ objsym:=TObjSymbol(ObjSymbolList[i]);
+ if (objsym.bind<>AB_LOCAL) then
+ WriteSym(objsym);
+ end;
+ { update the .symtab section header }
+ symtabsect.shlink:=strtabsect.secshidx;
+ symtabsect.shinfo:=localsyms;
+ end;
+ end;
+
+
+ procedure TElfObjectOutput.section_write_sh_string(p:TObject;arg:pointer);
+ begin
+ TElfObjSection(p).shstridx:=shstrtabsect.writestr(TObjSection(p).name+#0);
+ end;
+
+
+ procedure TElfObjectOutput.createshstrtab;
+ begin
+ with elf32data do
+ begin
+ shstrtabsect.writestr(#0);
+ ObjSectionList.ForEachCall(@section_write_sh_string,nil);
+ end;
+ end;
+
+
+ procedure TElfObjectOutput.writesectionheader(s:TElfObjSection);
+ var
+ sechdr : telfsechdr;
+ begin
+ fillchar(sechdr,sizeof(sechdr),0);
+ sechdr.sh_name:=s.shstridx;
+ sechdr.sh_type:=s.shtype;
+ sechdr.sh_flags:=s.shflags;
+ sechdr.sh_offset:=s.datapos;
+ sechdr.sh_size:=s.Size;
+ sechdr.sh_link:=s.shlink;
+ sechdr.sh_info:=s.shinfo;
+ sechdr.sh_addralign:=s.secalign;
+ sechdr.sh_entsize:=s.shentsize;
+ writer.write(MaybeSwapSecHeader(sechdr),sizeof(sechdr));
+ end;
+
+
+ procedure TElfObjectOutput.writesectiondata(s:TElfObjSection);
+ begin
+ FWriter.writezeros(s.dataalignbytes);
+ if s.Datapos<>FWriter.ObjSize then
+ internalerror(200604031);
+ FWriter.writearray(s.data);
+ end;
+
+
+ procedure TElfObjectOutput.section_count_sections(p:TObject;arg:pointer);
+ begin
+ TElfObjSection(p).secshidx:=pword(arg)^;
+ inc(pword(arg)^);
+ end;
+
+
+ procedure TElfObjectOutput.section_create_relocsec(p:TObject;arg:pointer);
+ begin
+ if (TElfObjSection(p).ObjRelocations.count>0) then
+ createrelocsection(TElfObjSection(p));
+ end;
+
+
+ procedure TElfObjectOutput.section_set_datapos(p:TObject;arg:pointer);
+ begin
+ TObjSection(p).setdatapos(paword(arg)^);
+ end;
+
+
+ procedure TElfObjectOutput.section_write_data(p:TObject;arg:pointer);
+ begin
+ if (oso_data in TObjSection(p).secoptions) then
+ begin
+ if TObjSection(p).data=nil then
+ internalerror(200403073);
+ writesectiondata(TElfObjSection(p));
+ end;
+ end;
+
+
+ procedure TElfObjectOutput.section_write_sechdr(p:TObject;arg:pointer);
+ begin
+ writesectionheader(TElfObjSection(p));
+ end;
+
+
+ function TElfObjectOutput.writedata(data:TObjData):boolean;
+ var
+ header : telfheader;
+ shoffset,
+ datapos : aint;
+ nsections : word;
+ begin
+ result:=false;
+ elf32data:=TElfObjData(data);
+ with elf32data do
+ begin
+ { default sections }
+ symtabsect:=TElfObjSection.create_ext(ObjSectionList,'.symtab',SHT_SYMTAB,0,0,0,4,sizeof(telfsymbol));
+ strtabsect:=TElfObjSection.create_ext(ObjSectionList,'.strtab',SHT_STRTAB,0,0,0,1,0);
+ shstrtabsect:=TElfObjSection.create_ext(ObjSectionList,'.shstrtab',SHT_STRTAB,0,0,0,1,0);
+ { "no executable stack" marker for Linux }
+ if (target_info.system in systems_linux) and
+ not(cs_executable_stack in current_settings.moduleswitches) then
+ TElfObjSection.create_ext(ObjSectionList,'.note.GNU-stack',SHT_PROGBITS,0,0,0,1,0);
+ { insert the empty and filename as first in strtab }
+ strtabsect.writestr(#0);
+ strtabsect.writestr(ExtractFileName(current_module.mainsource^)+#0);
+ { calc amount of sections we have }
+ nsections:=1;
+ { also create the index in the section header table }
+ ObjSectionList.ForEachCall(@section_count_sections,@nsections);
+ { create .symtab and .strtab }
+ createsymtab;
+ { Create the relocation sections, this needs valid secidx and symidx }
+ ObjSectionList.ForEachCall(@section_create_relocsec,nil);
+ { recalc nsections to incude the reloc sections }
+ nsections:=1;
+ ObjSectionList.ForEachCall(@section_count_sections,@nsections);
+ { create .shstrtab }
+ createshstrtab;
+
+ { Calculate the filepositions }
+ datapos:=$40; { elfheader + alignment }
+ { section data }
+ ObjSectionList.ForEachCall(@section_set_datapos,@datapos);
+ { section headers }
+ shoffset:=datapos;
+ inc(datapos,(nsections+1)*sizeof(telfsechdr));
+
+ { Write ELF Header }
+ fillchar(header,sizeof(header),0);
+ header.magic0123:=$464c457f; { = #127'ELF' }
+{$ifdef cpu64bitaddr}
+ header.file_class:=2;
+{$else cpu64bitaddr}
+ header.file_class:=1;
+{$endif cpu64bitaddr}
+ if target_info.endian=endian_big then
+ header.data_encoding:=2
+ else
+ header.data_encoding:=1;
+
+ header.file_version:=1;
+ header.e_type:=1;
+{$ifdef sparc}
+ header.e_machine:=2;
+{$endif sparc}
+{$ifdef i386}
+ header.e_machine:=3;
+{$endif i386}
+{$ifdef m68k}
+ header.e_machine:=4;
+{$endif m68k}
+{$ifdef powerpc}
+ header.e_machine:=20;
+{$endif powerpc}
+{$ifdef arm}
+ header.e_machine:=40;
+ if (current_settings.fputype=cpu_soft) then
+ header.e_flags:=$600;
+{$endif arm}
+{$ifdef x86_64}
+ header.e_machine:=62;
+{$endif x86_64}
+ header.e_version:=1;
+ header.e_shoff:=shoffset;
+ header.e_shstrndx:=shstrtabsect.secshidx;
+
+ header.e_shnum:=nsections;
+ header.e_ehsize:=sizeof(telfheader);
+ header.e_shentsize:=sizeof(telfsechdr);
+ writer.write(MaybeSwapHeader(header),sizeof(header));
+ writer.writezeros($40-sizeof(header)); { align }
+ { Sections }
+ ObjSectionList.ForEachCall(@section_write_data,nil);
+ { section headers, start with an empty header for sh_undef }
+ writer.writezeros(sizeof(telfsechdr));
+ ObjSectionList.ForEachCall(@section_write_sechdr,nil);
+ end;
+ result:=true;
+ end;
+
+
+{****************************************************************************
+ TELFAssembler
+****************************************************************************}
+
+ constructor TElfAssembler.Create(smart:boolean);
+ begin
+ inherited Create(smart);
+ CObjOutput:=TElfObjectOutput;
+ end;
+
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+{$ifdef i386}
+ const
+ as_i386_elf32_info : tasminfo =
+ (
+ id : as_i386_elf32;
+ idtxt : 'ELF';
+ asmbin : '';
+ asmcmd : '';
+ supported_targets : [system_i386_linux,system_i386_beos,system_i386_freebsd,system_i386_haiku,system_i386_Netware,system_i386_netwlibc,
+ system_i386_solaris,system_i386_embedded];
+ flags : [af_outputbinary,af_smartlink_sections,af_supports_dwarf];
+ labelprefix : '.L';
+ comment : '';
+ );
+{$endif i386}
+{$ifdef x86_64}
+ const
+ as_x86_64_elf64_info : tasminfo =
+ (
+ id : as_x86_64_elf64;
+ idtxt : 'ELF';
+ asmbin : '';
+ asmcmd : '';
+ supported_targets : [system_x86_64_linux,system_x86_64_freebsd];
+ flags : [af_outputbinary,af_smartlink_sections,af_supports_dwarf];
+ labelprefix : '.L';
+ comment : '';
+ );
+{$endif x86_64}
+{$ifdef sparc}
+ const
+ as_sparc_elf32_info : tasminfo =
+ (
+ id : as_sparc_elf32;
+ idtxt : 'ELF';
+ asmbin : '';
+ asmcmd : '';
+ supported_targets : [];
+// flags : [af_outputbinary,af_smartlink_sections];
+ flags : [af_outputbinary,af_supports_dwarf];
+ labelprefix : '.L';
+ comment : '';
+ );
+{$endif sparc}
+
+
+initialization
+{$ifdef i386}
+ RegisterAssembler(as_i386_elf32_info,TElfAssembler);
+{$endif i386}
+{$ifdef sparc}
+ RegisterAssembler(as_sparc_elf32_info,TElfAssembler);
+{$endif sparc}
+{$ifdef x86_64}
+ RegisterAssembler(as_x86_64_elf64_info,TElfAssembler);
+{$endif x86_64}
+end.
diff --git a/closures/compiler/oglx.pas b/closures/compiler/oglx.pas
new file mode 100644
index 0000000000..75b9632096
--- /dev/null
+++ b/closures/compiler/oglx.pas
@@ -0,0 +1,394 @@
+{
+ Copyright (c) 2002 by Daniel Mantione, Peter Vreman
+
+ Contains the binary reader and writer for the linear executable
+ format used by OS/2
+
+ * This code was inspired by the NASM sources
+ The Netwide Assembler is copyright (C) 1996 Simon Tatham and
+ Julian Hall. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit oglx;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ { common }
+ cclasses,
+ { target }
+ systems,
+ { assembler }
+ cpubase,aasmbase,assemble,link,
+ { output }
+ ogbase,ogmap,ogcoff;
+
+{ An LX executable is called a module; it can be either an executable
+ or a DLL.
+
+ A module consists of objects. In other executable formats, these
+ are usually called sections.
+
+ Objects consist of pages.
+
+ The objects are numbered, numbers do not have any special meaning. The
+ pages of the object are loaded into memory with the access rights specified
+ the object table entry. (DM)}
+
+
+{ For the operating system the object numbers have no special meaning.
+ However, for Free Pascal generated executables, I define: (DM)}
+
+const code_object = 0;
+ data_object = 1;
+ bss_object = 2;
+ stack_object = 3;
+ heap_object = 4;
+
+type Tlxheader = packed record
+ magic:word; {'LX'}
+ byteorder:byte; {0 = little 1 = big endian.}
+ wordorder:byte; {0 = little 1 = big endian.}
+ format_level:cardinal; {Nothing else than LX level
+ 0 has ever been defined.}
+ cpu_type:word; {1 = 286, 2 = 386, 3 = 486,
+ 4 = pentium.}
+ os_type:word; {1 = OS/2, 2 = Windows,
+ 3 = Siemens MS-Dos 4.0,
+ 4 = Windows 386.}
+ module_version:cardinal; {Version of executable,
+ defined by user.}
+ module_flags:cardinal; {Flags.}
+ module_page_count:cardinal; {Amount of pages in module.}
+ eip_object,eip:cardinal; {Initial EIP, object nr and
+ offset within object.}
+ esp_object,esp:cardinal; {Initial ESP, object nr and
+ offset within object.}
+ page_size,page_shift:cardinal; {Page size, in bytes and
+ 1 << pageshift.}
+ fixup_sect_size:cardinal;
+ fixup_sect_checksum:cardinal;
+ loader_sect_size:cardinal;
+ loader_sect_chksum:cardinal;
+ object_table_offset:cardinal; {Location of object table.}
+ object_count:cardinal; {Amount of objects in module.}
+ object_pagetable_ofs:cardinal; {Location of object page
+ table.}
+ object_iterpages_ofs:cardinal;
+ resource_table_ofs:cardinal; {Location of resource table.}
+ resource_count:cardinal; {Amount of resources in
+ resource table.}
+ resid_name_tbl_ofs:cardinal;
+ entry_table_offset:cardinal;
+ module_dir_offset:cardinal;
+ module_dir_count:cardinal;
+ fixup_pagetab_ofs:cardinal;
+ fixup_recrab_ofs:cardinal;
+ import_modtab_ofs:cardinal;
+ import_modtab_count:cardinal;
+ data_pages_offset:cardinal;
+ preload_page_count:cardinal;
+ nonresid_table_ofs:cardinal;
+ nonresid_table_len:cardinal;
+ nonresid_tbl_chksum:cardinal;
+ auto_ds_object_no:cardinal; {Not used by OS/2.}
+ debug_info_offset:cardinal;
+ inst_preload_count:cardinal;
+ inst_demand_count:cardinal;
+ heapsize:cardinal; {Only used for 16-bit programs.}
+ end;
+
+ Tlxobject_flags = (ofreadable,ofwriteable,ofexecutable,ofresource,
+ ofdiscardable,ofshared,ofpreload,ofinvalid,
+ ofzerofilled);
+ Tlxobject_flag_set = set of Tlxobject_flags;
+
+ Tlxobject_table_entry = packed record
+ virtual_size:cardinal;
+ reloc_base_addr:cardinal;
+ object_flags:Tlxobject_flag_set;
+ page_table_index:cardinal;
+ page_count:cardinal;
+ reserved:cardinal;
+ end;
+
+ Tlxexeoutput = class(texeoutput)
+ private
+{ FCoffsyms,
+ FCoffStrs : tdynamicarray;
+ win32 : boolean;}
+ nsects,
+ nsyms,
+ sympos : longint;
+ procedure write_symbol(const name:string;strpos,value,section,typ,aux:longint);
+ procedure write_symbols;
+ protected
+ function writedata:boolean;override;
+ public
+ constructor createos2;
+ function newobjectinput:tobjectinput;override;
+ procedure CalculateMemoryMap;override;
+ procedure GenerateExecutable(const fn:string);override;
+ end;
+
+ Tlxlinker = class(tinternallinker)
+ constructor create;override;
+ end;
+
+
+implementation
+
+uses
+ strings,
+ cutils,verbose,
+ globtype,globals,fmodule;
+
+
+{****************************************************************************
+ tcoffexeoutput
+****************************************************************************}
+
+ constructor Tlxexeoutput.createos2;
+ begin
+ inherited create;
+ end;
+
+
+ function Tlxexeoutput.newobjectinput:tobjectinput;
+ begin
+ result:=tcoffobjectinput.createdjgpp;
+ end;
+
+
+ procedure Tlxexeoutput.write_symbol(const name:string;strpos,value,section,typ,aux:longint);
+{ var
+ sym : coffsymbol;}
+ begin
+{ FillChar(sym,sizeof(sym),0);
+ if strpos=-1 then
+ move(name[1],sym.name,length(name))
+ else
+ sym.strpos:=strpos;
+ sym.value:=value;
+ sym.section:=section;
+ sym.typ:=typ;
+ sym.aux:=aux;
+ FWriter.write(sym,sizeof(sym));}
+ end;
+
+
+ procedure Tlxexeoutput.write_symbols;
+{ var
+ filename : string[18];
+ sec : TSection;
+ namestr : string[8];
+ nameidx,
+ value,
+ sectionval,
+ i : longint;
+ globalval : byte;
+ secrec : coffsectionrec;
+ objdata : TObjData;
+ p : tasmsymbol;
+ s : string;}
+ begin
+(* objdata:=TObjData(objdatalist.first);
+ while assigned(objdata) do
+ begin
+ with tcoffObjData(objdata) do
+ begin
+ { The symbols used }
+ p:=Tasmsymbol(symbols.First);
+ while assigned(p) do
+ begin
+ if p.section=sec_common then
+ sectionval:=sections[sec_bss].secsymidx
+ else
+ sectionval:=sections[p.section].secsymidx;
+ if p.currbind=AB_LOCAL then
+ globalval:=3
+ else
+ globalval:=2;
+ { if local of global then set the section value to the address
+ of the symbol }
+ if p.currbind in [AB_LOCAL,AB_GLOBAL] then
+ value:=p.address
+ else
+ value:=p.size;
+ { symbolname }
+ s:=p.name;
+ if length(s)>8 then
+ begin
+ nameidx:=FCoffStrs.size+4;
+ FCoffStrs.writestr(s);
+ FCoffStrs.writestr(#0);
+ end
+ else
+ begin
+ nameidx:=-1;
+ namestr:=s;
+ end;
+ write_symbol(namestr,nameidx,value,sectionval,globalval,0);
+ p:=tasmsymbol(p.indexnext);
+ end;
+ end;
+ objdata:=TObjData(objdata.next);
+ end;*)
+ end;
+
+
+ procedure Tlxexeoutput.CalculateMemoryMap;
+{ var
+ objdata : TObjData;
+ secsymidx,
+ mempos,
+ datapos : longint;
+ sec : TSection;
+ sym : tasmsymbol;
+ s : TObjSection;}
+ begin
+(* { retrieve amount of sections }
+ nsects:=0;
+ secsymidx:=0;
+ for sec:=low(TSection) to high(TSection) do
+ begin
+ if sections[sec].available then
+ begin
+ inc(nsects);
+ inc(secsymidx);
+ sections[sec].secsymidx:=secsymidx;
+ end;
+ end;
+ { calculate start positions after the headers }
+ datapos:=sizeof(coffheader)+sizeof(coffoptheader)+sizeof(coffsechdr)*nsects;
+ mempos:=sizeof(coffheader)+sizeof(coffoptheader)+sizeof(coffsechdr)*nsects;
+ if not win32 then
+ inc(mempos,sizeof(go32v2stub)+$1000);
+ { add sections }
+ MapObjData(datapos,mempos);
+ { end symbol }
+ AddGlobalSym('_etext',sections[sec_code].mempos+sections[sec_code].memsize);
+ AddGlobalSym('_edata',sections[sec_data].mempos+sections[sec_data].memsize);
+ AddGlobalSym('end',mempos);
+ { symbols }
+ nsyms:=0;
+ sympos:=0;
+ if not(cs_link_strip in current_settings.globalswitches) then
+ begin
+ sympos:=datapos;
+ objdata:=TObjData(objdatalist.first);
+ while assigned(objdata) do
+ begin
+ inc(nsyms,objdata.symbols.count);
+ objdata:=TObjData(objdata.next);
+ end;
+ end;*)
+ end;
+
+function gen_section_header(sec:Tsection;obj:cardinal):Tlxobject_table_entry;
+ virtual_size:cardinal;
+ reloc_base_addr:cardinal;
+ object_flags:Tlxobject_flag_set;
+ page_table_index:cardinal;
+ page_count:cardinal;
+ reserved:cardinal;
+
+begin
+ gen_section_header.virtual_size:=sections[sec.memsize];
+
+end;
+
+function Tlxexeoutput.writedata:boolean;
+
+var header:Tlxheader;
+ hsym:Tasmsymbol;
+ code_object_header,data_object_header,bss_object_header,stack_object_header,
+ heap_object_header:Tlxobject_table_entry;
+
+
+begin
+ result:=false;
+ fillchar(header,sizeof(header),0);
+ header.magic:=$584c; {'LX'}
+ header.cpu_type:=2; {Intel 386}
+ header.os_type:=1; {OS/2}
+ {Set the initial EIP.}
+ header.eip_object:=code_object;
+ hsym:=tasmsymbol(globalsyms.Find('start'));
+ if not assigned(hsym) then
+ begin
+ comment(V_Error,'Entrypoint "start" not defined');
+ exit;
+ end;
+ header.eip:=hsym.address-sections[sec_code].mempos;
+ {Set the initial ESP.}
+ header.esp_object:=stack_object;
+ header.esp:=stacksize;
+ Fwriter.write(header,sizeof(header));
+ for sec:=low(Tsection) to high(Tsection) do
+ if sections[sec].available then
+ if not(sec in [sec_code,sec_data,sec_bss,sec_stab,sec_stabstr]) then
+ begin
+ result:=false;
+ exit;
+ end;
+ code_object_header:=gen_section_header(sec_code,code_object);
+ data_object_header:=gen_section_header(sec_data,data_object);
+ bss_object_header:=gen_section_header(sec_bss,bss_object);
+ result:=true;
+end;
+
+
+ procedure Tlxexeoutput.GenerateExecutable(const fn:string);
+ begin
+{ AddGlobalSym('_etext',0);
+ AddGlobalSym('_edata',0);
+ AddGlobalSym('end',0);
+ if not CalculateSymbols then
+ exit;
+ CalculateMemoryMap;
+ FixupSymbols;
+ FixupRelocations;
+ writeexefile(fn);}
+ end;
+
+{****************************************************************************
+ TCoffLinker
+****************************************************************************}
+
+ constructor Tlxlinker.Create;
+ begin
+ inherited Create;
+ exeoutput:=Tlxexeoutput.createos2;
+ end;
+
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+
+begin
+{ RegisterAssembler(as_i386_coff_info,TCoffAssembler);
+ RegisterAssembler(as_i386_pecoff_info,TPECoffAssembler);
+ RegisterAssembler(as_i386_pecoffwdosx_info,TPECoffAssembler);
+
+ RegisterLinker(ld_i386_coff,Tlxlinker);}
+end.
diff --git a/closures/compiler/ogmacho.pas b/closures/compiler/ogmacho.pas
new file mode 100644
index 0000000000..963a70c37c
--- /dev/null
+++ b/closures/compiler/ogmacho.pas
@@ -0,0 +1,1223 @@
+{
+ Copyright (c) 2009-2010 by Dmitry Boyarintsev
+
+ Contains the binary mach-o writer
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit ogmacho;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ cclasses,
+ globals, globtype, verbose,
+ owbase, ogbase,
+ aasmbase, assemble,
+ macho, machoutils,
+ systems,
+ { assembler }
+ cpuinfo,cpubase,aasmtai,aasmdata; {for system constants}
+
+type
+
+ { TMachoRawWriter }
+
+ TMachoRawWriter=class(TRawWriter)
+ private
+ fwriter : tobjectwriter;
+ public
+ constructor Create(awriter: tobjectwriter);
+ procedure WriteRaw(const data; datasize: Integer); override;
+ end;
+
+ { TmachoObjSection }
+
+ TMachoSectionType=(mst_Normal, mst_ObjC, mst_Stabs, mst_Dwarf);
+
+ TmachoObjSection=class(tObjSection)
+ public
+ nmsegment : string; {mach-o segment name}
+ nmsection : string; {mach-o section name}
+
+ inSegIdx : Integer; {section index inside segment. one-based number}
+ RelocOfs : aword; {file offset to the first relocation symbol}
+ IndIndex : Integer; {index in indirect table (see DysymTableCommand) for lazy and non-lazy symbol pointers}
+
+ machoSec : TMachoSectionType;
+ function GetRelocCount: Integer;
+ function FileSize: Integer;
+ constructor create(AList:TFPHashObjectList; const Aname:string; Aalign:shortint; Aoptions:TObjSectionOptions);override;
+ end;
+
+ { TmachoObjData }
+
+ TmachoObjData=class(TObjData)
+ public
+ debugcount: Integer;
+ constructor create(const n:string); override;
+ procedure CreateDebugSections; override;
+ function sectionname(atype:TAsmSectiontype; const aname:string; aorder:TAsmSectionOrder):string;override;
+ function sectiontype2align(atype:TAsmSectiontype):shortint;override;
+ function sectiontype2options(atype:TAsmSectiontype):TObjSectionOptions;override;
+ procedure writereloc(data:aint; len:aword; p:TObjSymbol; reltype:TObjRelocationType);override;
+ public
+ end;
+
+ { TMachoObjectOutput }
+
+ TMachoSymbolLocation=(loc_Notused, loc_Local, loc_External, loc_Undef);
+
+ TMachoObjectOutput=class(TObjOutput)
+ private
+ machoData : TMachoObjData;
+ mfile : TMachOWriter;
+ cputarget : cpu_type_t;
+
+ stabsec : TmachoObjSection;
+ strsec : TmachoObjSection;
+
+ sectionscnt : integer;
+ memofs : aword;
+ fileofs : aword;
+
+ symstrofs : aword;
+ symlen : aword;
+ symCount : aint;
+
+ iLocal : Integer;
+ iExtern : Integer;
+ iUndef : Integer;
+ iIndir : Integer;
+
+ symList : TFPObjectList;
+ IndirIndex : tdynamicarray;
+
+ relcount : integer;
+ protected
+ procedure TrailZeros;
+
+ {sections}
+ procedure FixSectionRelocs(s: TMachoObjSection);
+ procedure section_count_sections(p:TObject;arg:pointer);
+ procedure section_set_datamempos(p:TObject;arg:pointer);
+ procedure section_set_relocpos(p:TObject;arg:pointer);
+
+ procedure section_write_data(p:TObject;arg:pointer);
+ procedure section_write_relocdata(p:TObject;arg:pointer);
+ procedure section_prepare_indirect(s: TObjSection);
+
+ {symbols}
+ procedure symbol_write_nlist(sym:TObjSymbol; symstr: tdynamicarray);
+ function dysymbol_location(sym: TObjSymbol): TMachoSymbolLocation;
+
+ function symWriteName(s: TObjSymbol): string;
+ procedure InitSymbolIndexes(var sCount: aint; var symStrLen: aword);
+
+ {mach-o file related}
+ procedure writeSectionsHeader(s: TMachoObjSection);
+ procedure writeSymTabCommand;
+ procedure writeSymbols(symstr: tdynamicarray);
+ procedure writeDySymTabCommand(IndOffset: aword; IndCount: Integer);
+ procedure writeDysymbols;
+
+ function writedata(data:TObjData):boolean;override;
+ public
+ constructor Create(AWriter:TObjectWriter);override;
+ end;
+
+ { TMachoAssembler }
+
+ TMachoAssembler=class(TInternalAssembler)
+ public
+ constructor create(smart:boolean);override;
+ end;
+
+
+implementation
+
+ { TmachoObjData }
+
+ constructor TmachoObjData.create(const n: string);
+ begin
+ inherited create(n);
+ CObjSection:=TmachoObjSection;
+ end;
+
+
+ { TmachoObjData.CreateDebugSections. }
+ { note: mach-o file has specific symbol table command (not sections) to keep symbols and symbol string }
+ procedure TmachoObjData.CreateDebugSections;
+ begin
+ inherited CreateDebugSections;
+ if target_dbg.id=dbg_stabs then
+ begin
+ stabssec:=createsection(sec_stab);
+ stabstrsec:=createsection(sec_stabstr);
+ end;
+ end;
+
+
+ function TmachoObjData.sectionname(atype: TAsmSectiontype; const aname: string; aorder: TAsmSectionOrder): string;
+ const
+ DwarfSect : array [sec_debug_frame..sec_debug_abbrev] of string
+ = ('sec_debug_frame','__debug_info','__debug_line','__debug_abbrev');
+ begin
+ case atype of
+ sec_user: Result:=aname;
+ sec_bss: Result:=MakeSectionName(seg_DATA, '__common');
+ sec_stab: Result:='.stabs';
+ sec_stabstr: Result:='.stabsstr';
+ sec_fpc: Result:=MakeSectionName(seg_TEXT, '.fpc');
+ sec_stub: Result:=MakeSectionName(seg_IMPORT, '__jump_table');
+ sec_code:
+ if (aname='fpc_geteipasebx') or
+ (aname='fpc_geteipasecx') then
+ Result:=MakeSectionName(seg_TEXT, '__textcoal_nt')
+ else
+ Result:=MakeSectionName(seg_TEXT, '__text');
+ sec_rodata_norel: Result:=MakeSectionName(seg_TEXT, '__const'); {.const}
+ sec_rodata: Result:=MakeSectionName(seg_DATA, '__const');
+ sec_data: Result:=MakeSectionName(seg_DATA, '__data');
+ sec_data_nonlazy: Result:=MakeSectionName(seg_DATA, '__nl_symbol_ptr');
+ sec_data_lazy: Result:=MakeSectionName(seg_DATA, '__la_symbol_ptr');
+ sec_init_func: Result:=MakeSectionName(seg_DATA, '__mod_init_func');
+ sec_term_func: Result:=MakeSectionName(seg_DATA, '__mod_term_func');
+
+
+ sec_objc_class: Result:='__OBJC __class';
+ sec_objc_meta_class: Result:='__OBJC __meta_class';
+ sec_objc_cat_cls_meth: Result:='__OBJC __cat_cls_meth';
+ sec_objc_cat_inst_meth: Result:='__OBJC __cat_inst_meth';
+ sec_objc_protocol: Result:='__OBJC __protocol';
+ sec_objc_string_object: Result:='__OBJC __cstring';
+ sec_objc_cls_meth: Result:='__OBJC __cls_meth';
+ sec_objc_inst_meth: Result:='__OBJC __inst_meth';
+ sec_objc_cls_refs: Result:='__OBJC __cls_refs';
+ sec_objc_message_refs: Result:='__OBJC __message_refs';
+ sec_objc_symbols: Result:='__OBJC __symbols';
+ sec_objc_category: Result:='__OBJC __categories';
+ sec_objc_class_vars: Result:='__OBJC __cls_vars';
+ sec_objc_instance_vars: Result:='__OBJC __inst_vars';
+ sec_objc_module_info: Result := '__OBJC __module_info';
+ sec_objc_class_names: Result:='__TEXT __cstring';
+ sec_objc_meth_var_types: Result:='__OBJC __var_types';
+ sec_objc_meth_var_names: Result:='__TEXT __cstring';
+ sec_objc_selector_strs: Result:='__TEXT __cstring';
+ sec_objc_protocol_ext: Result:='__OBJC __protocol_ext';
+ sec_objc_class_ext: Result:='__OBJC __class_ext';
+ sec_objc_property: Result:='__OBJC __property';
+ sec_objc_image_info: Result:='__OBJC __image_info';
+ sec_objc_cstring_object: Result:='__OBJC __cstring_object';
+ sec_objc_sel_fixup: Result:='__OBJC __sel_fixup';
+ { Objective-C non-fragile ABI }
+ sec_objc_data: Result:='__OBJC __data';
+ sec_objc_const: Result:='__OBJC __const';
+ sec_objc_sup_refs: Result:='__OBJC __supc_refs';
+ sec_objc_classlist: Result:='__OBJC __classlist';
+ sec_objc_nlclasslist: Result:='__OBJC __nlclasslist';
+ sec_objc_catlist: Result:='__OBJC __catlist';
+ sec_objc_nlcatlist: Result:='__OBJC __nlcatlist';
+ sec_objc_protolist: Result:='__OBJC __protolist';
+
+ sec_debug_frame,
+ sec_debug_info,
+ sec_debug_line,
+ sec_debug_abbrev:
+ Result:=MakeSectionName(seg_DWARF, DwarfSect[atype])
+
+ else
+ Result:=MakeSectionName(seg_DATA, '__data');
+ end;
+ end;
+
+
+ procedure TmachoObjData.writereloc(data: aint; len: aword; p: TObjSymbol; reltype: TObjRelocationType);
+ var
+ symaddr : longint;
+ begin
+ {stabs relocation}
+ case TMachoObjSection(CurrObjSec).machoSec of
+
+ mst_Stabs:
+ begin
+ if Assigned(p) then
+ begin
+ data:=p.address;
+ CurrObjSec.addsymreloc(CurrObjSec.Size,p,reltype);
+ end;
+ CurrObjSec.write(data, len);
+ end;
+
+ mst_Dwarf:
+ begin
+ if Assigned(p) then
+ begin
+ CurrObjSec.addsectionReloc(CurrObjSec.Size,p.objsection,reltype);
+ data:=p.address;
+ end;
+ CurrObjSec.write(data, len);
+ end;
+
+ else
+ if assigned(p) then
+ begin
+ { real address of the symbol }
+ symaddr:=p.address;
+ { Local ObjSymbols can be resolved already or need a section reloc }
+ if (p.bind=AB_LOCAL) and
+ (reltype in [RELOC_RELATIVE,RELOC_ABSOLUTE{$ifdef x86_64},RELOC_ABSOLUTE32{$endif x86_64}]) then
+ begin
+ { For a reltype relocation in the same section the value can be calculated }
+ if (p.objsection=CurrObjSec) and
+ (reltype=RELOC_RELATIVE) then
+ inc(data,symaddr-len-CurrObjSec.Size)
+ else
+ begin
+ if (p.typ=AT_NONE) then
+ begin
+ {undefined symbol, using section}
+ CurrObjSec.addsectionreloc(CurrObjSec.Size,p.objsection,reltype);
+ data:=symaddr-len-CurrObjSec.Size;
+ end
+ else
+ begin
+ CurrObjSec.addsymreloc(CurrObjSec.Size,p,reltype);
+ if Assigned(p.objsection) and
+ (p.objsection.Name='__TEXT __textcoal_nt') then
+ data:=symaddr-len-CurrObjSec.Size
+ else
+ data:=p.objsection.Size;
+ end;
+ end;
+ end
+ else if (p.bind=AB_GLOBAL) and
+ not Assigned(p.indsymbol) and
+ (reltype<>RELOC_PIC_PAIR) then
+ begin
+ CurrObjSec.addsectionreloc(CurrObjSec.Size,p.objsection,reltype);
+ data:=p.address;
+ end
+ else
+ CurrObjSec.addsymreloc(CurrObjSec.Size,p,reltype);
+ end; {if assigned(p) }
+
+ CurrObjSec.write(data, len);
+ end;
+ end;
+
+
+ function TmachoObjData.sectiontype2align(atype: TAsmSectiontype): shortint;
+ begin
+ case atype of
+ sec_bss:
+ Result:=4;
+ sec_stabstr, sec_stab:
+ Result:=1;
+ sec_stub, sec_data_lazy, sec_data_nonlazy:
+ Result:=4;
+ else
+ Result:=inherited sectiontype2align(atype);
+ end;
+ end;
+
+
+ function TmachoObjData.sectiontype2options(atype: TAsmSectiontype): TObjSectionOptions;
+ begin
+ case atype of
+ sec_objc_meth_var_names,
+ sec_objc_class_names: Result:=[oso_data, oso_load];
+ else
+ Result:=inherited sectiontype2options(atype);
+ end
+ end;
+
+
+ { TMachoAssembler }
+
+ constructor TMachoAssembler.create(smart: boolean);
+ begin
+ inherited create(smart);
+ CObjOutput:=TMachoObjectOutput;
+ end;
+
+
+ { TMachoObjectOutput }
+
+ procedure TMachoObjectOutput.FixSectionRelocs(s: TMachoObjSection);
+ var
+ i : integer;
+ ro : TObjRelocation;
+ dw : aword;
+ begin
+ {todo: is it I386 only core}
+ if not Assigned(s.Data) then
+ Exit;
+
+ for i:=0 to s.ObjRelocations.Count-1 do
+ begin
+ ro:=TObjRelocation(s.ObjRelocations[i]);
+
+ if (Assigned(ro.objsection)) and
+ (ro.objsection.Name='__TEXT __textcoal_nt') then
+ Continue;
+
+ if Assigned(ro.objsection) then
+ begin
+ s.Data.seek(ro.DataOffset);
+ s.Data.read(dw, sizeof(aword));
+
+ dw:=dw+ro.objsection.MemPos;
+
+ s.Data.seek(ro.DataOffset);
+ s.Data.write(dw, sizeof(aword));
+ end
+ else
+ begin
+ if ro.symbol.Name='fpc_geteipasebx' then
+ Continue;
+ if Assigned(ro.symbol.indsymbol) or
+ (ro.typ=RELOC_PIC_PAIR) then
+ begin
+ s.Data.seek(ro.DataOffset);
+ s.Data.read(dw, sizeof(aword));
+ dw:=ro.symbol.address-dw;
+ s.Data.seek(ro.DataOffset);
+ s.Data.write(dw, sizeof(aword));
+ end
+ else if (ro.symbol.bind=AB_LOCAL) then
+ begin
+ dw:=ro.symbol.address;
+ s.Data.seek(ro.DataOffset);
+ s.Data.write(dw, sizeof(aword));
+ end;
+ end;
+
+ end;
+ s.Data.seek(s.Data.Size);
+ end;
+
+
+ procedure TMachoObjectOutput.section_count_sections(p: TObject; arg: pointer);
+ var
+ s : TMachoObjSection;
+ begin
+ s:=TMachoObjSection(p);
+ if s.machoSec=mst_Stabs then
+ Exit;
+ inc(sectionscnt);
+ s.inSegIdx:=sectionscnt;
+ end;
+
+
+ procedure TMachoObjectOutput.section_set_datamempos(p: TObject; arg: pointer);
+ var
+ s : TMachoObjSection;
+ begin
+ s:=TMachoObjSection(p);
+ if s.machoSec=mst_Stabs then
+ Exit;
+
+ s.setDataPos(fileofs);
+ s.setMemPos(memofs);
+ memofs:=Align(memofs+s.Size, s.SecAlign);
+
+ fileofs:=AlignAddr(cputarget, fileofs);
+ end;
+
+
+ procedure TMachoObjectOutput.section_set_relocpos(p:TObject;arg:pointer);
+ var
+ s : TMachoObjSection;
+ sz : Integer;
+ begin
+ s:=TMachoObjSection(p);
+ if s.machoSec=mst_Stabs then
+ Exit;
+
+ sz:=s.GetRelocCount * sizeof(relocation_info);
+ if sz > 0 then
+ begin
+ s.relocofs:=fileofs;
+ inc(fileofs, sz);
+ fileofs:=AlignAddr(cputarget, fileofs);
+ end;
+ end;
+
+
+ procedure TMachoObjectOutput.section_write_data(p: TObject; arg: pointer);
+ var
+ s : TMachoObjSection;
+ begin
+ s:=TMachoObjSection(p);
+ if s.machoSec=mst_Stabs then
+ Exit;
+
+ Writer.writezeros(s.DataAlignBytes);
+
+ FixSectionRelocs(s);
+
+ if s.Datapos<>FWriter.ObjSize then
+ InternalError(200903101);
+ if Assigned(s.data) then
+ Writer.writearray(s.data);
+ TrailZeros;
+ end;
+
+
+ procedure TMachoObjectOutput.section_write_relocdata(p: TObject; arg: pointer);
+ var
+ s : TMachoObjSection;
+ symsec : TMachoObjSection;
+ i : Integer;
+ dw : aword;
+
+ r : relocation_info;
+ sr : scattered_relocation_info;
+ ro : TObjRelocation;
+ symnum : Integer;
+ relpc : Boolean;
+ relextern : Boolean;
+ reltype : Integer;
+
+ begin
+ s:=TMachoObjSection(p);
+
+ {stabs relocation should not present in relocation table}
+ if s.machoSec=mst_Stabs then
+ Exit;
+ {no relocation for the section}
+ if s.relocofs=0 then
+ Exit;
+ {check file alignment}
+ if s.relocofs<>FWriter.ObjSize then
+ InternalError(200903102); {file misalignment}
+
+ relcount:=s.ObjRelocations.Count;
+ {the reversed order, is only to be alike Apple linker}
+ for i:=s.ObjRelocations.Count-1 downto 0 do
+ begin
+ ro:=TObjRelocation(s.ObjRelocations[i]);
+
+ {in-section relocation}
+ if ro.symbol=nil then
+ begin
+ relextern:=false;
+ relpc:=false;
+ symnum:=TmachoObjSection(ro.objsection).inSegIdx;
+ case ro.typ of
+ RELOC_ABSOLUTE:
+ begin
+ RelocInfo(ro.DataOffset, symnum, GENERIC_RELOC_VANILLA, ril_long, relpc, relextern, r);
+ mfile.WriteRelocation(r);
+ end;
+ else
+ relpc:=ro.typ=RELOC_RELATIVE;
+ RelocInfo(ro.DataOffset, symnum, GENERIC_RELOC_VANILLA, ril_long, relpc, relextern, r);
+ mfile.WriteRelocation(r);
+ end;
+
+ end
+ else
+ begin
+ symsec:=TMachoObjSection(ro.symbol.objsection);
+
+ if Assigned(symsec) and
+ (symsec.Name='__TEXT __textcoal_nt') then
+ begin
+ relextern:=true;
+ symnum:=ro.symbol.symidx;
+ end
+ else if ro.symbol.bind=AB_EXTERNAL then
+ begin
+ relextern:=true;
+ symnum:=ro.symbol.symidx;
+ end
+ else if Assigned(ro.symbol.objsection) and
+ (ro.symbol.bind=AB_LOCAL) and
+ (ro.symbol.typ=AT_DATA) then
+ begin
+ relextern:=false;
+ symnum:=TMachoObjSection(ro.symbol.objsection).inSegIdx;
+ end
+ else if (ro.symbol.bind=AB_LOCAL) or
+ (ro.symbol.typ=AT_NONE) then
+ begin
+ relextern:=false;
+ symnum:=s.inSegIdx
+ end
+ else
+ begin
+ relextern:=true;
+ symnum:=ro.symbol.symidx;
+ end;
+
+ relpc:=false;
+ relpc:=(ro.typ=RELOC_RELATIVE);
+ if (ro.typ=RELOC_PIC_PAIR) then
+ begin
+ if ro.symbol.bind=AB_LOCAL then
+ reltype:=GENERIC_RELOC_LOCAL_SECTDIFF
+ else
+ reltype:=GENERIC_RELOC_SECTDIFF;
+ ScatterRelocInfo(ro.symbol.address, ro.DataOffset, reltype, ril_long, false, sr);
+ mfile.WriteScatterReloc(sr);
+
+ { the section data is already fixed to: ro.SymbolOffset - Label.Offset }
+ s.Data.seek(ro.DataOffset);
+ s.Data.read(dw, sizeof(aword));
+ dw:=ro.symbol.address-dw;
+ ScatterRelocInfo(dw, 0, GENERIC_RELOC_PAIR, ril_long, false, sr);
+ mfile.WriteScatterReloc(sr);
+ end
+ else
+ begin
+ RelocInfo(ro.DataOffset, symnum, GENERIC_RELOC_VANILLA, ril_long, relpc, relextern, r);
+ mfile.WriteRelocation(r);
+ end
+ end;
+ if Assigned(s.Data) then
+ s.Data.seek(s.Data.size);
+ end;
+ TrailZeros;
+ end;
+
+
+ procedure TMachoObjectOutput.section_prepare_indirect(s: TObjSection);
+ var
+ t : TObjSymbol;
+ i : Integer;
+ anysym : Boolean;
+ begin
+ if TmachoObjSection(s).machoSec=mst_Stabs then
+ Exit;
+
+ anysym:=false;
+ for i:=0 to machoData.ObjSymbolList.Count-1 do
+ begin
+ t:=TObjSymbol(machoData.ObjSymbolList[i]);
+ if (t.objsection=s) and Assigned(t.indsymbol) then
+ begin
+ if not anysym then
+ begin
+ {remember the index of the first indirect symbol. Will be used later at section header writting}
+ TmachoObjSection(s).indIndex:=IndirIndex.size div SizeOf(Integer);
+ anysym:=true;
+ end;
+ IndirIndex.write(t.symidx, sizeof(Integer));
+ end;
+ end;
+
+ end;
+
+
+ procedure TMachoObjectOutput.symbol_write_nlist(sym:TObjSymbol; symstr: tdynamicarray);
+ var
+ n : nlist_64;
+ sec : TmachoObjSection;
+ begin
+ sec:=TMachoObjSection(sym.objsection);
+ FillChar(n, sizeof(n), 0);
+ n.n_un.n_strx:=symstr.size;
+ symstr.writestr(sym.Name+#0);
+
+ if assigned(sec) and
+ (sec.machoSec=mst_ObjC) and
+ (sec.nmsection='__module_info') then
+ begin
+ n.n_type:=N_ABS or N_EXT;
+ mfile.WriteNList(n);
+ Exit;
+ end;
+
+ if (sym.typ=AT_NONE) then
+ begin
+ n.n_value:=0;
+ if sym.bind<>AB_EXTERNAL then
+ n.n_desc:=n.n_desc or REFERENCE_FLAG_UNDEFINED_LAZY;
+ n.n_type:=n.n_type or N_EXT;
+ end
+ else if sym.bind=AB_LAZY then
+ begin
+ n.n_value:=0;
+ n.n_type:=N_ABS or N_EXT;
+ n.n_sect:=NO_SECT;
+ end
+ else
+ begin
+ n.n_value:=sym.address;
+
+ if Assigned(sec) then
+ begin
+ n.n_sect:=sec.inSegIdx;
+ n.n_type:=n.n_type or N_SECT;
+
+ if (sym.typ=AT_FUNCTION) and
+ (sym.bind=AB_LOCAL) then
+ begin
+ n.n_type:=N_PEXT or N_EXT or N_SECT;
+ n.n_desc:=n.n_desc or N_WEAK_DEF;
+ end;
+ end;
+ end;
+
+ if (sym.bind=AB_GLOBAL) and
+ (n.n_type and N_PEXT=0) then
+ n.n_type:=n.n_type or N_EXT;
+
+ if (sym.typ=AT_FUNCTION) and
+ (sym.bind=AB_GLOBAL) then
+ n.n_desc:=n.n_desc or N_NO_DEAD_STRIP;
+
+ if Assigned(sec) then
+ begin
+ if (sec.nmsection='__nl_symbol_ptr') then
+ n.n_desc:=n.n_desc or REFERENCE_FLAG_UNDEFINED_NON_LAZY;
+ if (sec.nmsegment=seg_Data) and (sec.nmsection='__const') then
+ n.n_desc:=n.n_desc or N_NO_DEAD_STRIP;
+ end;
+
+ mfile.WriteNList(n);
+ end;
+
+
+ function TMachoObjectOutput.dysymbol_location(sym: TObjSymbol): TMachoSymbolLocation;
+ begin
+ if Assigned(sym.objsection) and
+ (TMachoObjSection(sym.objsection).machoSec=mst_Stabs) then
+ Result:=loc_Local
+ else
+ case sym.typ of
+ AT_NONE: Result:=loc_Undef;
+ AT_LABEL: Result:=loc_Notused;
+ else
+ Result:=loc_External;
+ end;
+ end;
+
+
+ procedure TMachoObjectOutput.writeSectionsHeader(s: TMachoObjSection);
+ var
+ sc : TMachoSection;
+ begin
+ section_prepare_indirect(s);
+
+ fillChar(sc, sizeof(sc), 0);
+ sc.segname:=s.nmsegment;
+ sc.sectname:=s.nmsection;
+ sc.size:=s.Size;
+ if s.FileSize>0 then
+ sc.offset:=s.DataPos
+ else
+ sc.offset:=0;
+ sc.addr:=s.MemPos;
+ sc.nreloc:=s.GetRelocCount;
+ sc.reloff:=s.relocofs;
+ sc.flags:=GetSectionFlags(s.nmsegment, s.nmsection);
+ sc.align:=MachoAlign(s.SecAlign);
+ sc.indirectIndex:=s.indIndex;
+
+ if (sc.flags and SECTION_TYPE)=S_SYMBOL_STUBS then
+ sc.stubSize:=GetStubSize(cputarget, false);
+ mfile.WriteSection(sc);
+ end;
+
+
+ procedure TMachoObjectOutput.writeSymTabCommand;
+ begin
+ mfile.WriteLoadCommand(LC_SYMTAB, sizeof(symtab_command));
+ mfile.WriteUint32(fileofs); {symoff}
+ mfile.WriteUint32(symCount); {nsyms}
+ inc(fileofs, symCount*sizeNList(cputarget));
+ fileofs:=AlignAddr(cputarget, fileofs);
+
+ symstrofs:=fileofs;
+ mfile.WriteUint32(fileofs); {stroff}
+ mfile.WriteUint32(symlen); {strsize}
+
+ inc(fileofs, symlen);
+ fileofs:=AlignAddr(cputarget, fileofs);
+ end;
+
+
+ function TMachoObjectOutput.symWriteName(s: TObjSymbol): string;
+ begin
+ if not Assigned(s.indsymbol) then
+ Result:=s.Name
+ else
+ Result:=s.indsymbol.Name;
+ end;
+
+
+{ function getSymWriteNameLength(s: TObjSymbol): Integer; inline;
+ begin
+ Result:=length(symWriteName(s))+1;
+ end;}
+
+
+ procedure TMachoObjectOutput.InitSymbolIndexes(var sCount: aint; var symStrLen: aword);
+ var
+ i : integer;
+ s : TObjSymbol;
+ stabcount : Integer;
+ begin
+ sCount:=0;
+ symStrLen:=0;
+
+ iIndir:=0;
+ for i:=0 to machoData.ObjSymbolList.Count-1 do
+ begin
+ s:=TObjSymbol(machoData.ObjSymbolList[i]);
+ if (s.typ=AT_LABEL) then
+ Continue;
+
+ if Assigned(s.indsymbol) then
+ inc(iIndir);
+ end;
+
+ iLocal:=0;
+ iExtern:=0;
+ iUndef:=0;
+
+ for i:=0 to machoData.ObjSymbolList.Count-1 do
+ begin
+ s:=TObjSymbol(machoData.ObjSymbolList[i]);
+ if (s.typ=AT_LABEL) or
+ Assigned(s.indsymbol) then
+ Continue;
+ if (s.bind=AB_LOCAL) and
+ (s.Name <> 'fpc_geteipasebx') then
+ Continue;
+
+ case dysymbol_location(s) of
+ loc_Local:
+ begin
+ symList.Insert(iLocal, s);
+ inc(iLocal); inc(iExtern); inc(iUndef);
+ end;
+ loc_External:
+ begin
+ symList.Insert(iExtern, s);
+ inc(iExtern); inc(iUndef);
+ end;
+ loc_Undef:
+ begin
+ symList.Insert(iUndef, s);
+ inc(iUndef);
+ end;
+ end;
+ inc(symStrLen, length(s.Name)+1 );
+ end;
+
+ if Assigned(stabsec) then
+ {skipping hdrsym! (added by ogbase) }
+ stabcount:=stabsec.Size div sizeof(TObjStabEntry) - 1
+ else
+ stabcount:=0;
+
+ for i:=0 to symList.Count-1 do
+ TObjSymbol(symList[i]).symidx:=i+stabcount;
+ sCount:=symList.Count+stabcount;
+
+ for i:=0 to machoData.ObjSymbolList.Count-1 do
+ with TObjSymbol(machoData.ObjSymbolList[i]) do
+ if Assigned(indsymbol) then
+ symidx:=indsymbol.symidx;
+
+ if Assigned(strsec) then
+ // 1 byte of zero name (that stands in the end of table, not at zero pos)
+ inc(symlen, strsec.Size + 1)
+ else
+ inc(symlen); {the first zero byte}
+
+ dec(iUndef, iExtern); { iUndef is count of undefined symbols (for dysymtable command) }
+ dec(iExtern, iLocal); { iExtern is count of external symbols (for dysymtable command) }
+ inc(iLocal, stabcount);
+ end;
+
+
+ procedure TMachoObjectOutput.writeSymbols(symstr: tdynamicarray);
+ var
+ i : integer;
+ s : TObjSymbol;
+ b : byte;
+ stab : TObjStabEntry;
+ ro : TObjRelocation;
+ sym : TObjSymbol;
+ addr : aword;
+ text : TmachoObjSection;
+ funofs : AWord;
+ begin
+ if Assigned(stabsec) then
+ begin
+ for i:=0 to stabsec.ObjRelocations.Count - 1 do
+ begin
+ ro:=TObjRelocation(stabsec.ObjRelocations[i]);
+ sym:=ro.symbol;
+ addr:=sym.address;
+ if Assigned(sym.objsection) then
+ begin
+ stabsec.Data.seek(ro.DataOffset-3);
+ b:=TmachoObjSection(sym.objsection).inSegIdx;
+ stabsec.Data.write(b, sizeof(b));
+ end;
+ stabsec.Data.seek(ro.DataOffset);
+ stabsec.Data.write(addr, sizeof(addr));
+ end;
+
+ stabsec.Data.seek(sizeof(TObjStabEntry));
+ funofs:=0;
+ text:=TmachoObjSection(machoData.ObjSectionList.Find(MakeSectionName(seg_TEXT, '__text')));
+ for i:=1 to stabsec.Data.size div SizeOf(TObjStabEntry) - 1 do
+ begin
+ stabsec.Data.read(stab, sizeof(stab));
+ case stab.ntype of
+ N_FUN:
+ begin
+ if stab.strpos=0 then
+ funofs:=0
+ else
+ funofs:=stab.nvalue;
+ end;
+ N_SLINE,N_RBRAC,N_LBRAC:
+ begin
+ if Assigned(text) then
+ begin
+ { SLINE are expected to be in __TEXT __text only }
+ stab.nother:=text.inSegIdx;
+ inc(stab.nvalue, funofs);
+ end;
+ end;
+ N_OSO:
+ begin
+ { null-terminated string is the first in the list }
+ { apple-gdb doesn't recognize it as zero-string for N_OSO }
+ { another zero-string should be added to the list }
+ if stab.strpos=0 then
+ stab.strpos:=symstr.Size;
+ end;
+ end;
+ FWriter.write(stab, sizeof(stab));
+ end;
+ end;
+
+ symstr.Seek(symStr.size);
+ b:=0;
+ symstr.Write(b,1);
+
+ for i:=0 to symList.Count-1 do
+ begin
+ s:=TObjSymbol(symList[i]);
+ symbol_write_nlist(s, symstr);
+ end;
+ end;
+
+
+ procedure TMachoObjectOutput.writeDySymTabCommand(IndOffset: aword; IndCount: Integer);
+ begin
+ mfile.WriteLoadCommand(LC_DYSYMTAB, sizeof(dysymtab_command));
+
+ mfile.WriteUint32(0); {ilocalsym}
+ mfile.WriteUint32(iLocal); {nlocalsym}
+
+ mfile.WriteUint32(iLocal); {iextdefsym}
+ mfile.WriteUint32(iExtern); {nextdefsym}
+
+ mfile.WriteUint32(iLocal + iExtern); {iundefsym}
+ mfile.WriteUint32(iUndef); {nundefsym}
+
+ mfile.WriteUint32(0); {tocoff}
+ mfile.WriteUint32(0); {ntoc}
+ mfile.WriteUint32(0); {modtaboff}
+ mfile.WriteUint32(0); {nmodtab}
+ mfile.WriteUint32(0); {extrefsymoff}
+ mfile.WriteUint32(0); {nextrefsyms}
+ mfile.WriteUint32(IndOffset); {indirectsymoff}
+ mfile.WriteUint32(IndCount); {nindirectsyms}
+ mfile.WriteUint32(0); {extreloff}
+ mfile.WriteUint32(0); {nextrel}
+ mfile.WriteUint32(0); {locreloff}
+ mfile.WriteUint32(0); {nlocrel}
+ end;
+
+
+ procedure TMachoObjectOutput.writeDysymbols;
+ var
+ i : integer;
+ idx : LongWord;
+ begin
+ IndirIndex.seek(0);
+ for i:=0 to (IndirIndex.size div sizeof(Integer))-1 do
+ begin
+ IndirIndex.read(idx, sizeof(idx));
+ mfile.WriteUint32(idx);
+ end;
+ end;
+
+
+ function AddSectionToSegment(var segment: TMachoSegment; section : TMachoObjSection): boolean;
+ begin
+ { sections must be attached one-by-one to the segment }
+ if segment.fileoff=0 then
+ segment.fileoff:=section.DataPos;
+
+ if (segment.fileoff+segment.filesize)<(section.FileSize+section.DataPos) then
+ segment.filesize:=section.FileSize+section.DataPos;
+
+ inc(segment.nsects);
+ inc(segment.vmsize, section.size);
+ Result:=true;
+ end;
+
+
+ procedure TMachoObjectOutput.TrailZeros;
+ var
+ sz : LongWord;
+ begin
+ sz:=AlignAddr(cputarget, FWriter.Size);
+ if sz - FWriter.Size>0 then
+ FWriter.WriteZeros(sz-FWriter.Size);
+ end;
+
+
+ function TMachoObjectOutput.writedata(data: TObjData): boolean;
+ var
+ header : TMachHeader;
+ seg : TMachoSegment;
+ secobj : TMachoObjSection;
+ i : Integer;
+
+ symstr : tdynamicarray;
+ segSize : integer; {size of a segment command - platform dependant}
+ sctSize : integer; {size of a single section header - platform dependant}
+
+ indOfs: aword; {indirect symbol offset}
+
+ begin
+ symList:=TFPObjectList.Create(false);
+ IndirIndex:=tdynamicarray.Create(1024);
+
+ result:=false;
+ machoData:=TMachoObjData(data);
+
+ cputarget:=CPU_TYPE_i386;
+ segSize:=sizeSegment(cputarget);
+ sctSize:=sizeSection(cputarget);
+
+ sectionscnt:=0;
+ stabsec:=TMachoObjSection(machoData.ObjSectionList.Find('.stabs'));
+ strsec:=TMachoObjSection(machoData.ObjSectionList.Find('.stabsstr'));
+
+ {count number of sections}
+ machoData.ObjSectionList.ForEachCall(@section_count_sections, nil);
+
+ {sections data is written after machheader,load-commands. }
+ { basic loadcommands for MH_OBJECT are }
+ { single LC_SEGMENT, containing all sections headers }
+ { symbol linking information at LC_SYMTAB and LC_DYSYMTAB }
+ header.cputype:=cputarget;
+ header.cpusubtype:=CPU_SUBTYPE_i386_ALL;
+ header.filetype:=MH_OBJECT;
+ header.ncmds:=3;
+ header.sizeofcmds:=segSize+sctSize*sectionscnt+sizeof(symtab_command)+sizeof(dysymtab_command);
+ header.flags:=0;
+
+ {setting sections data and memory pos}
+ fileofs:=sizeMachHeader(cputarget)+header.sizeofcmds;
+ fileofs:=AlignAddr(cputarget, fileofs);
+ memofs:=0;
+
+ machoData.ObjSectionList.ForEachCall(@section_set_datamempos, nil);
+ fileofs:=AlignAddr(cputarget, fileofs);
+
+ {setting sections relocation offsets}
+ machoData.ObjSectionList.ForEachCall(@section_set_relocpos, nil);
+ fileofs:=AlignAddr(cputarget, fileofs);
+
+ {creating actual mach-o file writer}
+ mfile:=AllocMachoWriter(CPU_TYPE_I386, TMachoRawWriter.Create(writer), true);
+ {writing macho-o header}
+ mfile.WriteHeader(header);
+
+ {starting the first segment command}
+ InitSegment(seg);
+
+ {initialze symbols. some sections (non_lazy, lazy pointers) are effected}
+ InitSymbolIndexes(symCount, symlen);
+
+ for i:=0 to machoData.ObjSectionList.Count-1 do
+ begin
+ secobj:=TmachoObjSection(machoData.ObjSectionList[i]);
+ if secobj.machoSec=mst_Stabs then
+ Continue;
+ AddSectionToSegment(seg, secobj);
+ end;
+
+ {writting segment command}
+ {for MH_OBJECT, all sections are stored in the single segment}
+ mfile.WriteSegmentCmd(seg, segSize+(seg.nsects)*sctSize);
+
+ {section headers are written inside segment command}
+ for i:=0 to machoData.ObjSectionlist.Count - 1 do
+ begin
+ secobj:=TmachoObjSection(machoData.ObjSectionList[i]);
+ if secobj.machoSec=mst_Stabs then
+ Continue;
+ writeSectionsHeader(secobj);
+ end;
+ TrailZeros;
+
+ if IndirIndex.size div sizeof(Integer)<>iIndir then
+ InternalError(2009121001);
+ if iIndir>0 then
+ indOfs:=fileOfs
+ else
+ indOfs:=0;
+ inc(fileofs, IndirIndex.size);
+
+ {write symtab command}
+ {initilize symbos order. local first, extern second, undef last}
+ writeSymTabCommand;
+ TrailZeros;
+
+ {write dysymtab command}
+ writeDySymTabCommand(indofs, iIndir);
+ TrailZeros;
+
+ {writting sections data, to precalculated offsets}
+ {if precalculated offsets, doesn't match actual written offsets, internal error is risen}
+ machoData.ObjSectionList.ForEachCall(@section_write_data, nil);
+
+ {writting relocation offsets}
+ machoData.ObjSectionList.ForEachCall(@section_write_relocdata, nil);
+
+ {writting dyn symbol tables (indirect symbols arrays)}
+ writeDysymbols;
+
+ {writting symbol table}
+ if Assigned(strsec) then
+ symstr:=strsec.Data
+ else
+ symstr:=tdynamicarray.create(1024);
+
+ writeSymbols(symstr);
+ TrailZeros;
+
+ {writting symbol table strings}
+ FWriter.writearray(symstr);
+ // terminating null name
+ TrailZeros;
+
+ if not Assigned(strsec) then
+ symstr.Free;
+
+ TrailZeros;
+
+ mfile.Free;
+ symList.Free;
+ IndirIndex.Free;
+ end;
+
+
+ constructor TMachoObjectOutput.Create(AWriter: TObjectWriter);
+ begin
+ inherited Create(AWriter);
+ CObjData:=TMachoObjData;
+ end;
+
+
+ { TMachoRawWriter }
+
+ constructor TMachoRawWriter.Create(awriter: tobjectwriter);
+ begin
+ inherited Create;
+ fwriter:=awriter;
+ end;
+
+
+ procedure TMachoRawWriter.WriteRaw(const data; datasize: Integer);
+ begin
+ fwriter.Write(data, datasize);
+ end;
+
+
+ { TmachoObjSection }
+
+ function TmachoObjSection.GetRelocCount: Integer;
+ var
+ i: integer;
+ r: TObjRelocation;
+ begin
+ Result:=ObjRelocations.Count;
+ for i:=0 to ObjRelocations.Count-1 do
+ begin
+ r:=TObjRelocation(ObjRelocations[i]);
+ if (r.typ=RELOC_PIC_PAIR) then
+ inc(Result);
+ end;
+ end;
+
+
+ function TmachoObjSection.FileSize: Integer;
+ begin
+ if Assigned(data) then
+ Result:=data.size
+ else
+ Result:=0;
+ end;
+
+
+ constructor TmachoObjSection.create(AList: TFPHashObjectList;
+ const Aname: string; Aalign: shortint; Aoptions: TObjSectionOptions);
+ begin
+ if Aname = '__TEXT __textcoal_nt' then
+ Aalign:=4;
+
+ inherited create(AList, Aname, Aalign, Aoptions);
+ GetSegmentSectionName(aName, nmsegment, nmsection);
+ if (aname='.stabs') or
+ (aname='.stabsstr') then
+ machoSec:=mst_Stabs
+ else if nmsegment=seg_DWARF then
+ machoSec:=mst_Dwarf
+ else if nmsegment=seg_OBJC then
+ machoSec:=mst_ObjC
+ else
+ machoSec:=mst_Normal;
+ end;
+
+
+ const
+ as_i386_darwin_info : tasminfo =
+ (
+ id : as_i386_macho;
+ idtxt : 'MACHO';
+ asmbin : '';
+ asmcmd : '';
+ supported_targets : [system_i386_darwin,system_i386_iphonesim];
+ flags : [af_outputbinary,af_smartlink_sections,af_supports_dwarf{, af_stabs_use_function_absolute_addresses}];
+ labelprefix : '.L';
+ comment : '#';
+ );
+
+initialization
+ RegisterAssembler(as_i386_darwin_info,TMachoAssembler);
+
+end.
+
diff --git a/closures/compiler/ogmap.pas b/closures/compiler/ogmap.pas
new file mode 100644
index 0000000000..8b5172510d
--- /dev/null
+++ b/closures/compiler/ogmap.pas
@@ -0,0 +1,162 @@
+{
+ Copyright (c) 2001-2002 by Peter Vreman
+
+ Contains the class for generating a map file
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit ogmap;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ { common }
+ cclasses,globtype,systems,
+ { object writer }
+ aasmbase,ogbase
+ ;
+
+ type
+ texemap = class
+ private
+ t : text;
+ FImageBase : aword;
+ public
+ constructor Create(const s:string);
+ destructor Destroy;override;
+ procedure Add(const s:string);
+ procedure AddHeader(const s:string);
+ procedure AddCommonSymbolsHeader;
+ procedure AddCommonSymbol(p:TObjSymbol);
+ procedure AddMemoryMapHeader(abase:aint);
+ procedure AddMemoryMapExeSection(p:texesection);
+ procedure AddMemoryMapObjectSection(p:TObjSection);
+ procedure AddMemoryMapSymbol(p:TObjSymbol);
+ end;
+
+ var
+ exemap : texemap;
+
+
+implementation
+
+ uses
+ cutils,cfileutl,
+ globals,verbose;
+
+
+{****************************************************************************
+ TExeMap
+****************************************************************************}
+
+ constructor TExeMap.Create(const s:string);
+ begin
+ Assign(t,FixFileName(s));
+ Rewrite(t);
+ FImageBase:=0;
+ end;
+
+
+ destructor TExeMap.Destroy;
+ begin
+ Close(t);
+ end;
+
+
+ procedure TExeMap.Add(const s:string);
+ begin
+ writeln(t,s);
+ end;
+
+
+ procedure TExeMap.AddHeader(const s:string);
+ begin
+ Add('');
+ Add(s);
+ end;
+
+
+ procedure TExeMap.AddCommonSymbolsHeader;
+ begin
+ AddHeader('Allocating common symbols');
+ Add('Common symbol size file');
+ Add('');
+ end;
+
+
+ procedure TExeMap.AddCommonSymbol(p:TObjSymbol);
+ var
+ s : string;
+ begin
+ { Common symbol size file }
+ s:=p.name;
+ if length(s)>20 then
+ begin
+ writeln(t,p.name);
+ s:='';
+ end;
+ Add(PadSpace(s,20)+'0x'+PadSpace(hexstr(p.size,1),16)+p.objsection.objdata.name);
+ end;
+
+
+ procedure TExeMap.AddMemoryMapHeader(abase:aint);
+ var
+ imagebasestr : string;
+ begin
+ FImageBase:=abase;
+ if FImageBase<>0 then
+ imagebasestr:=' (ImageBase='+HexStr(FImageBase,sizeof(pint)*2)+')'
+ else
+ imagebasestr:='';
+ AddHeader('Memory map'+imagebasestr);
+ Add('');
+ end;
+
+
+ procedure TExeMap.AddMemoryMapExeSection(p:texesection);
+ begin
+ { .text 0x000018a8 0xd958 }
+ Add(PadSpace(p.name,19)+PadSpace(' 0x'+HexStr(p.mempos+Fimagebase,sizeof(pint)*2),12)+
+ ' 0x'+HexStr(p.size,sizeof(pint)));
+ end;
+
+
+ procedure TExeMap.AddMemoryMapObjectSection(p:TObjSection);
+ var
+ secname : string;
+ begin
+ { .text 0x000018a8 0xd958 object.o }
+ secname:=p.name;
+ if Length(secname)>18 then
+ begin
+ Add(' '+secname);
+ secname:='';
+ end;
+ Add(' '+PadSpace(secname,18)+PadSpace(' 0x'+HexStr(p.mempos+FImageBase,sizeof(pint)*2),12)+
+ ' 0x'+HexStr(p.size,sizeof(pint))+' '+p.objdata.name);
+ end;
+
+
+ procedure TExeMap.AddMemoryMapSymbol(p:TObjSymbol);
+ begin
+ { 0x00001e30 setup_screens }
+ Add(Space(20)+PadSpace('0x'+HexStr(p.address+Fimagebase,sizeof(pint)*2),25)+' '+p.name);
+ end;
+
+end.
diff --git a/closures/compiler/ognlm.pas b/closures/compiler/ognlm.pas
new file mode 100644
index 0000000000..fb0f558a0c
--- /dev/null
+++ b/closures/compiler/ognlm.pas
@@ -0,0 +1,1521 @@
+{
+ Copyright (c) 1998-2006 by Peter Vreman
+ Copyright (c) 2011 by Armin Diehl
+
+ Contains the binary netware nlm executable writer
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit ognlm;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ { common }
+ cclasses,globtype,
+ { target }
+ systems,
+ aasmbase,assemble,link,
+ { output }
+ ogbase,
+ owbase,
+ ogcoff;
+
+{*****************************************************************************
+ NLM File structures and constants
+*****************************************************************************}
+
+{
+
+LString0 -> 1 byte Length, Text, #0
+LString -> 1 byte length, Text
+
+Basic NLM File Structure:
+
+FixedHeader
+ nlm32_i386_external_fixed_header 130 bytes
+
+VarHdr1
+ NLM Description: LString0 2+n bytes
+ Stacksize 4 bytes
+ reserved = 0 4 bytes
+ ' LONG' 5 bytes
+ NLM screen name: LString0 2+n bytes
+ NLM thread name: LString0 2+n bytes
+
+Optional Headers beginning with stamp (without '')
+'VeRsIoN#': nlm32_i386_external_version_header 32 bytes
+'CoPyRiGhT=': LString0 2+n bytes
+'MeSsAgEs': nlm32_i386_external_extended_header 124 bytes
+'CuStHeAd': nlm32_i386_external_custom_header
+'CyGnUsEx': nlm32_i386_external_cygnus_ext_header 16 bytes
+
+.text
+.data
+.relocs=
+ addr(32),addr(32),...
+ addr and $80000000 > 0 -> FixupToSeg=.text else .data
+ addr and $40000000 > 0 -> FixupInSeg=.text else .data
+.importedSymbols
+ name LString 1+n bytes
+ number of references r 4 bytes
+ addresses r*4 bytes
+.exportedSymbols
+ name LString 1+n bytes
+ addr 4 bytes
+ addr and $80000000 > 0 -> .text else .data
+ ...
+.modules
+
+.nlmdebugrecs
+ type (0=.data,1=.code,2,..=????) 1 byte
+ addr 4 bytes
+ name LString 1+n bytes
+ ...
+
+}
+
+
+const NLM_MAX_DESCRIPTION_LENGTH = 127;
+ NLM_MAX_SCREEN_NAME_LENGTH = 71;
+ NLM_MAX_THREAD_NAME_LENGTH = 71; // some netware docs limit this to 12 ?
+ NLM_OLD_THREAD_NAME_LENGTH = 5;
+ NLM_HEADER_VERSION = 4;
+ NLM_DEFAULT_STACKSIZE = (32 * 1024);
+ NLM_VERSION_STAMP = 'VeRsIoN#';
+ NLM_COPYRIGHT_STAMP = 'CoPyRiGhT=';
+ NLM_CYGNUS_STAMP = 'CyGnUsEx';
+ NLM_MESSAGES_STAMP = 'MeSsAgEs';
+ NLM_CUSTOM_STAMP = 'CuStHeAd';
+ NLM_SIGNATURE = 'NetWare Loadable Module'#$1A;
+ NLM_FLAGS_REENTRANT = 1;
+ NLM_FLAGS_MULTILOAD = 2;
+ NLM_FLAGS_SYNCHRONIZE = 4;
+ NLM_FLAGS_PSEUDOPREEMPTION = 8;
+ NLM_FLAGS_OSDOMAIN = $10;
+ NLM_FLAGS_AUTOUNLOAD = $40;
+
+
+ type
+ uint32 = longword;
+
+ nlm32_i386_external_fixed_header = packed record
+ signature : array[0..23] of char;
+ version : uint32;
+ (* The name of the module, which must be a DOS name (1-8 characters followed
+ by a period and a 1-3 character extension). The first byte is the byte
+ length of the name and the last byte is a null terminator byte. This
+ field is fixed length, and any unused bytes should be null bytes. The
+ value is set by the OUTPUT keyword to NLMLINK. *)
+ moduleName : string[13]; //array[0..13] of byte;
+ codeImageOffset : uint32; // The byte offset of the code image from the start of the file.
+ codeImageSize : uint32; // The size of the code image, in bytes.
+ dataImageOffset : uint32; // The byte offset of the data image from the start of the file.
+ dataImageSize : uint32; // The size of the data image, in bytes.
+ uninitializedDataSize : uint32; // The size of the uninitialized data region that the loader has to be
+ // allocated at load time. Uninitialized data follows the initialized
+ // data in the NLM address space.
+ customDataOffset : uint32; // The byte offset of the custom data from the start of the file. The
+ // custom data is set by the CUSTOM keyword to NLMLINK. It is possible
+ // for this to be EOF if there is no custom data.
+ customDataSize : uint32; // The size of the custom data, in bytes.
+ moduleDependencyOffset : uint32; // The byte offset of the module dependencies from the start of the file.
+ // The module dependencies are determined by the MODULE keyword in NLMLINK.
+ numberOfModuleDependencies : uint32; // he number of module dependencies at the moduleDependencyOffset.
+ relocationFixupOffset : uint32; // The byte offset of the relocation fixup data from the start of the file
+ numberOfRelocationFixups : uint32;
+ externalReferencesOffset : uint32;
+ numberOfExternalReferences : uint32;
+ publicsOffset : uint32;
+ numberOfPublics : uint32;
+ debugInfoOffset : uint32; // The byte offset of the internal debug info from the start of the file.
+ // It is possible for this to be EOF if there is no debug info.
+ numberOfDebugRecords : uint32;
+ codeStartOffset : uint32;
+ exitProcedureOffset : uint32;
+ checkUnloadProcedureOffset : uint32;
+ moduleType : uint32;
+ flags : uint32;
+ end;
+
+
+ { The version header is one of the optional auxiliary headers and
+ follows the fixed length and variable length NLM headers. }
+ { The header is recognized by "VeRsIoN#" in the stamp field. }
+
+ nlm32_i386_external_version_header = packed record
+ stamp : array[0..7] of char; // VeRsIoN#
+ majorVersion,
+ minorVersion,
+ revision,
+ year,
+ month,
+ day : uint32;
+ end;
+ { The header is recognized by "MeSsAgEs" in the stamp field. }
+
+ nlm32_i386_external_extended_header = packed record
+ stamp : array[0..7] of char; // MeSsAgEs
+ languageID : uint32;
+ messageFileOffset : uint32;
+ messageFileLength : uint32;
+ messageCount : uint32;
+ helpFileOffset : uint32;
+ helpFileLength : uint32;
+ RPCDataOffset : uint32;
+ RPCDataLength : uint32;
+ sharedCodeOffset : uint32;
+ sharedCodeLength : uint32;
+ sharedDataOffset : uint32;
+ sharedDataLength : uint32;
+ sharedRelocationFixupOffset : uint32;
+ sharedRelocationFixupCount : uint32;
+ sharedExternalReferenceOffset: uint32;
+ sharedExternalReferenceCount : uint32;
+ sharedPublicsOffset : uint32;
+ sharedPublicsCount : uint32;
+ sharedDebugRecordOffset : uint32;
+ sharedDebugRecordCount : uint32;
+ SharedInitializationOffset : uint32;
+ SharedExitProcedureOffset : uint32;
+ productID : longint;
+ reserved0 : longint;
+ reserved1 : longint;
+ reserved2 : longint;
+ reserved3 : longint;
+ reserved4 : longint;
+ reserved5 : longint;
+ end;
+
+ nlm32_i386_external_custom_header = packed record
+ stamp : array[0..7] of char; // CuStHeAd
+ hdrLength : uint32;
+ dataOffset : uint32;
+ dataLength : uint32;
+ //dataStamp : array[0..7] of char;
+ //hdr : uint32;
+ end;
+ { The internal Cygnus header is written out externally as a custom
+ header. We don't try to replicate that structure here. }
+ { The header is recognized by "CyGnUsEx" in the stamp field. }
+ { File location of debugging information. }
+ { Length of debugging information. }
+
+ nlm32_i386_external_cygnus_ext_header = packed record
+ stamp : array[0..7] of char; // CyGnUsEx
+ offset : uint32;
+ length : uint32;
+ end;
+
+
+//------------------
+
+
+ TNLMExeSection = class(TExeSection)
+ public
+ constructor createnw(AList:TFPHashObjectList;const n:string);
+ end;
+
+ TsecType = (Section_text,Section_data,Section_other);
+
+ TNLMexeoutput = class(texeoutput)
+ private
+ FRelocsGenerated,FImportsGenerated : boolean;
+ FNumRelocs : longword;
+ FNumExternals : longword;
+ FNumModules : longword;
+ FNumDebugSymbols : longword;
+ fSizeWoDebugSyms : longword;
+ FnumExports : longword;
+ NlmSymbols : TDynamicArray;
+ ExeSecsListSize : longint;
+ nlmImpNames, // name of import. module name as import
+ nlmImports : TFPHashObjectList; // name of import, list of relocs as object
+ headerAlignBytes : longint;
+ FexportFunctionOffsets:TFPList; // offsets in .exports for function addresses, an offset of $80000000 is needed
+
+ nlmHeader : nlm32_i386_external_fixed_header;
+ nlmVersionHeader : nlm32_i386_external_version_header;
+ nlmExtHeader : nlm32_i386_external_extended_header;
+ nlmCustHeader : nlm32_i386_external_custom_header;
+ //nlmHelpFileName : TCmdStr;
+ //nlmMessagesFileName: TCmdStr;
+ //nlmXdcFileName : TCmdStr;
+ nlmCopyright : string;
+ nlmThreadname : string;
+ nlmScreenname : string;
+ nlmDescription : string;
+
+ function totalheadersize:longword;
+ procedure createNlm_symbol(const name:shortstring;value:longword;secType:TSecType);
+ procedure globalsyms_create_symbol(p:TObject;arg:pointer);
+ procedure ExeSectionList_write_header(p:TObject;arg:pointer);
+ procedure ExeSectionList_calc_size(p:TObject;arg:pointer);
+ procedure ExeSectionList_write_data(p:TObject;arg:pointer);
+ procedure GenerateImports;
+ procedure GenerateExports;
+ procedure GenerateRelocs;
+ procedure ExeSectionList_pass2_header(p:TObject;arg:pointer);
+ protected
+ function writedata:boolean;override;
+ public
+ constructor create; override;
+ destructor destroy; override;
+ procedure MemPos_Header;override;
+ procedure DataPos_Header;override;
+ procedure fillNlmVersionHeader;
+ procedure GenerateLibraryImports(ImportLibraryList:TFPHashObjectList);override;
+ procedure Order_End;override;
+ procedure MemPos_ExeSection(const aname:string);override;
+ procedure DataPos_ExeSection(const aname:string);override;
+ procedure NLMwriteString (const s : string; terminateWithZero : boolean);
+ procedure objNLMwriteString (const s : string; terminateWithZero : boolean);
+ procedure ParseScript (linkscript:TCmdStrList); override;
+ end;
+
+ var
+ {for symbols defined in linker script. To generate a fixup we
+ need to know the segment (.text,.bss or .code) of the symbol
+ Pointer in list is used as TsecType
+ Filled by TInternalLinkerNetware.DefaultLinkScript }
+ nlmSpecialSymbols_Segments : TFPHashList;
+
+ type
+
+ TNLMCoffObjInput = class(TCoffObjInput)
+ constructor create;override;
+ end;
+
+ TNLMCoffassembler = class(tinternalassembler)
+ constructor create(smart:boolean);override;
+ end;
+
+ TNLMCoffObjData = class(TCoffObjData)
+ constructor create(const n:string);override;
+ end;
+
+ TNLMCoffObjOutput = class(TCoffObjOutput)
+ constructor create(AWriter:TObjectWriter);override;
+ end;
+
+ TNLMCoffObjSection = class(TCoffObjSection)
+ constructor create(AList:TFPHashObjectList;const Aname:string;Aalign:shortint;Aoptions:TObjSectionOptions);override;
+ end;
+
+implementation
+
+ uses
+{$ifdef win32}
+ Windows,
+{$endif win32}
+ SysUtils,
+ cutils,verbose,globals,
+ fmodule,aasmdata,
+ ogmap,export
+ ;
+
+
+{****************************************************************************
+ Helpers
+****************************************************************************}
+type
+ TStringObj = class (TObject)
+ fValue : string;
+ constructor create (value:string);
+ property value : string read fValue write fValue;
+ end;
+
+ constructor TStringObj.create(value:string);
+ begin
+ inherited create;
+ fValue := value;
+ end;
+
+
+
+function SectionType (aName : string) : TSecType;
+var s : string;
+ seg: ptruint;
+begin
+ s := copy(aName,1,5);
+ if s = '.text' then result := Section_text else
+ if (s = '.data') or (copy(s,1,4)='.bss') then result := Section_data else
+ if s[1] <> '.' then
+ begin
+ seg := ptruint(nlmSpecialSymbols_Segments.Find(aName));
+ if seg <> 0 then
+ result := TSecType(seg)
+ else
+ result := Section_other;
+ end else
+ result := Section_other;
+end;
+
+{****************************************************************************
+ TNLMexesection
+****************************************************************************}
+
+
+ constructor TNLMExeSection.createnw(AList:TFPHashObjectList;const n:string);
+ begin
+ inherited create(AList,n);
+ end;
+
+
+{****************************************************************************
+ TNLMexeoutput
+****************************************************************************}
+
+ constructor TNLMexeoutput.create;
+ begin
+ inherited create;
+ CExeSection:=TNLMExeSection;
+ CObjData:=TNLMCoffObjData;
+ MaxMemPos:=$7FFFFFFF;
+ SectionMemAlign:=$0;
+ SectionDataAlign:=0;
+ RelocSection := true; // always needed for NLM's
+ nlmImports := TFPHashObjectList.create(true);
+ nlmImpNames := TFPHashObjectList.create(false);
+ NlmSymbols := TDynamicArray.create(4096);
+ FexportFunctionOffsets := TFPList.Create;
+ end;
+
+ destructor TNLMexeoutput.destroy;
+ begin
+ if assigned(nlmImports) then
+ nlmImports.Free;
+ if assigned(nlmImpNames) then
+ nlmImpNames.Free;
+ if assigned(nlmSymbols) then
+ nlmSymbols.Free;
+ if assigned(FexportFunctionOffsets) then
+ FexportFunctionOffsets.Free;
+ inherited destroy;
+ end;
+
+ procedure TNLMexeoutput.createNlm_symbol(const name:shortstring;value:longword;secType:TSecType);
+ var
+ b:byte;
+ begin
+ //Comment (V_Debug,'TNLMexeoutput.write_symbol '+name);
+ { type (0=.data,1=.code,2,..=????) 1 byte
+ addr 4 bytes
+ name LString 1+n bytes }
+ case secType of
+ Section_Text : b := 1;
+ Section_Data : b := 0
+ else
+ exit;
+ end;
+ nlmSymbols.write(b,sizeof(b));
+ assert (sizeof(value)<>4);
+ nlmSymbols.write(value,sizeof(value));
+ nlmSymbols.write(name[0],length(name)+1);
+ inc(FNumDebugSymbols);
+ end;
+
+
+ procedure TNLMexeoutput.globalsyms_create_symbol(p:TObject;arg:pointer);
+ var
+ value : longword;
+ exesec : TExeSection;
+ i : integer;
+ secType : TsecType;
+ begin
+ if not assigned(texesymbol(p).objsymbol) then
+ internalerror(200603053);
+ with texesymbol(p).objsymbol do
+ begin
+ exesec:=TExeSection(objsection.exesection);
+ { There is no exesection defined for special internal symbols
+ like __image_base__ }
+ if assigned(exesec) then
+ begin
+ //secval:=exesec.secsymidx;
+ value:=address-exesec.mempos;
+ end
+ else
+ begin
+ value:=address;
+ end;
+ { reloctype address to the section in the executable }
+ secType := SectionType(objsection.Name);
+ if (secType = Section_Text) or (secType = Section_Data) then
+ begin
+ i := nlmImports.FindIndexOf(texesymbol(p).name);
+ if i < 0 then
+ createNlm_symbol(name,value,secType);
+ end;
+ end;
+ end;
+
+
+
+(*
+function SecOpts(SecOptions:TObjSectionOptions):string;
+ begin
+ result := '[';
+ if oso_Data in SecOptions then result := result + 'oso_Data ';
+ { Is loaded into memory }
+ if oso_load in SecOptions then result := result + 'oso_load ';
+ { Not loaded into memory }
+ if oso_noload in SecOptions then result := result + 'oso_noload ';
+ { Read only }
+ if oso_readonly in SecOptions then result := result + 'oso_readonly ';
+ { Read/Write }
+ if oso_write in SecOptions then result := result + 'oso_write ';
+ { Contains executable instructions }
+ if oso_executable in SecOptions then result := result + 'oso_executable ';
+ { Never discard section }
+ if oso_keep in SecOptions then result := result + 'oso_keep ';
+ { Special common symbols }
+ if oso_common in SecOptions then result := result + 'oso_common ';
+ { Contains debug info and can be stripped }
+ if oso_debug in SecOptions then result := result + 'oso_debug ';
+ { Contains only strings }
+ if oso_strings in SecOptions then result := result + 'oso_strings ';
+ result := result + ']';
+ end;
+*)
+
+ procedure TNLMexeoutput.ExeSectionList_calc_size(p:TObject;arg:pointer);
+ var
+ objsec : TObjSection;
+ i : longint;
+ begin
+ with texesection(p) do
+ begin
+ { don't write normal section if writing only debug info }
+ if (ExeWriteMode=ewm_dbgonly) and
+ not(oso_debug in SecOptions) then
+ exit;
+
+ if oso_data in secoptions then
+ begin
+ inc (fSizeWoDebugSyms,(Align(fSizeWoDebugSyms,SectionDataAlign)-fSizeWoDebugSyms));
+ for i:=0 to ObjSectionList.Count-1 do
+ begin
+ objsec:=TObjSection(ObjSectionList[i]);
+ if oso_data in objsec.secoptions then
+ begin
+ inc(fSizeWoDebugSyms,objsec.size);
+ inc(fSizeWoDebugSyms,objsec.dataalignbytes);
+ end;
+ end;
+ end;
+ end;
+ end;
+
+
+
+ procedure TNLMexeoutput.ExeSectionList_write_Data(p:TObject;arg:pointer);
+ var
+ objsec : TObjSection;
+ i,j : longint;
+ b : byte;
+ begin
+
+ with texesection(p) do
+ begin
+ { don't write normal section if writing only debug info }
+ if (ExeWriteMode=ewm_dbgonly) and
+ not(oso_debug in SecOptions) then
+ exit;
+
+ if oso_data in secoptions then
+ begin
+ //if Align(FWriter.Size,SectionDataAlign)-FWriter.Size>0 then
+ // writeln (name,' align ',Align(FWriter.Size,SectionDataAlign)-FWriter.Size,' SectionDataAlign:',SectionDataAlign);
+ FWriter.Writezeros(Align(FWriter.Size,SectionDataAlign)-FWriter.Size);
+ for i:=0 to ObjSectionList.Count-1 do
+ begin
+ objsec:=TObjSection(ObjSectionList[i]);
+ if oso_data in objsec.secoptions then
+ begin
+ if assigned(exemap) then
+ if objsec.data.size > 0 then
+ exemap.Add(' 0x'+hexstr(objsec.DataPos,8)+': '+objsec.name);
+ //writeln (' ',objsec.name,' size:',objsec.size,' relocs:',objsec.ObjRelocations.count,' DataPos:',objsec.DataPos,' MemPos:',objsec.MemPos);
+ {for j := 0 to objsec.ObjRelocations.count-1 do
+ begin
+ objreloc := TObjRelocation(objsec.ObjRelocations[j]);
+ with objreloc do
+ begin
+ write(' reloc DataOffset: ',DataOffset,' OrgSize:',OrgSize,' typ:',typ);
+ if assigned(symbol) then
+ write(' Name: '#39,symbol.Name,#39' bind:',symbol.bind,' address:',symbol.address,' Size:',symbol.size);
+ writeln;
+ end;
+ end;}
+ if not assigned(objsec.data) then
+ internalerror(200603042);
+ if copy (objsec.Name,1,5) = '.text' then
+ begin // write NOP's instead of zero's for .text, makes disassemble possible
+ b := $90; // NOP
+ if objsec.DataAlignBytes > 0 then
+ for j := 1 to objsec.DataAlignBytes do
+ FWriter.write(b,1);
+ end else
+ FWriter.writezeros(objsec.dataalignbytes);
+ //if objsec.dataalignbytes>0 then
+ // writeln (' ',name,' alignbytes: ',objsec.dataalignbytes);
+ if objsec.DataPos<>FWriter.Size then
+ internalerror(200602251);
+ FWriter.writearray(objsec.data);
+ end else
+ begin
+ if assigned(exemap) then //TExeMap
+ exemap.Add(' skipping: '+objsec.name);
+ end;
+ end;
+ end;
+ end;
+ end;
+
+
+ function TNLMexeoutput.totalheadersize:longword;
+ var
+ varHdrSize,
+ optHdrSize,
+ hdrSize: longword;
+ begin
+ optHdrSize := 0;
+ inc(optHdrSize,2+length(nlmDescription));
+ inc(optHdrSize,8); // Stacksize+reserved
+ inc(optHdrSize,NLM_OLD_THREAD_NAME_LENGTH);
+ inc(optHdrSize,2+length(nlmScreenname));
+ inc(optHdrSize,2+length(nlmThreadname));
+
+ varHdrSize := 0;
+ if nwcopyright <> '' then
+ inc(varHdrSize,sizeof(NLM_COPYRIGHT_STAMP)+2+length(nlmCopyright));
+ hdrSize := sizeof(nlm32_i386_external_fixed_header)+
+ sizeof(nlm32_i386_external_extended_header)+
+ sizeof(nlm32_i386_external_custom_header)+
+ sizeof(nlm32_i386_external_version_header)+ // always
+ sizeof(nlm32_i386_external_cygnus_ext_header)+ // CyGnUsEx
+ varHdrSize+optHdrSize+
+ 8; // empty stamp
+ result := hdrSize;
+ end;
+
+
+ procedure TNLMexeoutput.MemPos_Header;
+ begin
+ { calculate start positions after the headers }
+ currmempos:=0;
+ end;
+
+
+ procedure TNLMexeoutput.ExeSectionList_write_header(p:TObject;arg:pointer);
+ var
+ nam : string;
+ u32,al : longword;
+ alignAmount:longint;
+ begin
+ with tExeSection(p) do
+ begin
+ //comment (v_debug,'ExeSectionList_write_header: '+name);
+ nam := name;
+ alignAmount := 4 - ((length (nam) + 1) MOD 4);
+ FWriter.write(nam[1],length(nam));
+ FWriter.WriteZeros(1+alignAmount);
+ al := 0;
+ // for .stab we have to ignore leading zeros due to alignment in file
+ if nam='.stab' then
+ if assigned(ObjSectionList[0]) then
+ al := TObjSection(ObjSectionList[0]).dataalignbytes;
+ u32 := dataPos+al; FWriter.write(u32,sizeof(u32));
+ u32 := size-al; FWriter.write(u32,sizeof(u32));
+ end;
+ end;
+
+
+
+ procedure TNLMexeoutput.ExeSectionList_pass2_header(p:TObject;arg:pointer);
+ var len,alignAmount:longint;
+ begin
+ {list of sections, extension of binutils,CuStHeAd points to this list
+ The format of the section information is:
+ null terminated section name
+ zeroes to adjust to 4 byte boundary
+ 4 byte section data file pointer
+ 4 byte section size }
+
+ with TExeSection(p) do
+ begin
+ alignAmount := 4 - ((length (Name) + 1) MOD 4);
+ len := length(name) + 1 + alignAmount + 8;
+ if ObjSectionList.Count>0 then
+ inc(len,TObjSection(ObjSectionList[0]).dataalignbytes);
+ inc(plongint(arg)^,len);
+ end;
+ end;
+
+ procedure TNLMexeoutput.DataPos_Header;
+ begin
+ ExeSecsListSize:=0;
+ ExeSectionList.ForEachCall(@ExeSectionList_pass2_header,@ExeSecsListSize);
+
+ headerAlignBytes := align(totalheadersize+ExeSecsListSize,16)-(totalheadersize+ExeSecsListSize); // align as in TObjData.sectiontype2align
+ currdatapos:=totalheadersize+ExeSecsListSize+headerAlignBytes;
+ end;
+
+
+ procedure TNLMexeoutput.fillNlmVersionHeader;
+ var
+ hour,min,sec,hsec,Year,Month,Day : word;
+ begin
+ DecodeTime(Time,hour,min,sec,hsec);
+ DecodeDate(Date,year,month,day);
+ nlmVersionHeader.stamp := NLM_VERSION_STAMP;
+ if nlmVersionHeader.year = 0 then
+ begin
+ nlmVersionHeader.year := Year;
+ nlmVersionHeader.month := Month;
+ nlmVersionHeader.day := Day;
+ end;
+ end;
+
+
+
+ function TNLMexeoutput.writedata:boolean;
+ var
+ dummyLong : array[0..4] of char;
+ textExeSec,
+ dataExeSec,
+ bssExeSec,
+ relocsExeSec,
+ exportsExeSec,
+ importsExeSec,
+ xdcExeSec,
+ messagesExeSec,
+ helpExeSec,
+ customExeSec : TExeSection;
+ hassymbols : boolean;
+ nlmCygnusHeader : nlm32_i386_external_cygnus_ext_header;
+ ModuleName : string;
+ exesym : TExeSymbol;
+ expOffset : PtrUInt;
+ expAddr : longword;
+ i : integer;
+
+ begin
+ result:=false;
+ textExeSec:=FindExeSection('.text');
+ dataExeSec:=FindExeSection('.data');
+ bssExeSec:=FindExeSection('.bss');
+ relocsExeSec:=FindExeSection('.reloc');
+ importsExeSec:=FindExeSection('.imports');
+ exportsExeSec:=FindExeSection('.exports');
+ xdcExeSec:=FindExeSection('.xdc');
+ messagesExeSec:=FindExeSection('.messages');
+ helpExeSec:=FindExeSection('.help');
+ customExeSec:=FindExeSection('.custom');
+
+ // exported function need the upper bit in the address
+ // to be set (=CODE), do this here to avoid another
+ // reloc type. The ExportFunctionOffsets list was
+ // filled in GenerateExports
+ if FexportFunctionOffsets.Count>0 then
+ begin
+ if not assigned(exportsExeSec) then
+ internalerror(201103201); // we have to have a .export section
+ if not assigned(exportsExeSec.ObjSectionList[0]) then
+ internalerror(201103202); // nothing in the .exports section but we have data in FexportFunctionOffsets
+ for i := 0 to FexportFunctionOffsets.Count-1 do
+ begin
+ expOffset := PtrUint(FexportFunctionOffsets[i]);
+ if TObjSection(exportsExeSec.ObjSectionList[0]).Data.size < expOffset+3 then
+ internalerror(201103203); // offset in FexportFunctionOffsets out of range
+ with TObjSection(exportsExeSec.ObjSectionList[0]) do
+ begin // set the upper bit of address to indicate .text
+ Data.seek(expOffset);
+ Data.read(expAddr,4);
+ Data.seek(expOffset);
+ expAddr := expAddr or $80000000;
+ Data.write(expAddr,4);
+ end;
+ end;
+ end;
+
+ if not assigned(TextExeSec) or
+ not assigned(RelocsExeSec) or
+ not assigned(DataExeSec) then
+ internalerror(200602231); // we have to have .data, .text and .reloc
+ { do we need to write symbols? }
+ hassymbols:=(ExeWriteMode=ewm_dbgonly) or
+ (
+ (ExeWriteMode=ewm_exefull) and
+ not(cs_link_strip in current_settings.globalswitches)
+ );
+
+ { Initial header, will be updated later }
+ nlmHeader.signature := NLM_SIGNATURE;
+ nlmHeader.version := NLM_HEADER_VERSION;
+ moduleName := upperCase(current_module.exefilename^);
+ nlmHeader.moduleName := moduleName;
+ nlmHeader.codeImageOffset := TextExeSec.DataPos+TObjSection(TextExeSec.ObjSectionList[0]).dataalignbytes; // ??? may be that align has to be moved to fixups/imports
+ nlmHeader.codeImageSize := TextExeSec.Size;
+ nlmHeader.dataImageOffset := DataExeSec.DataPos;
+ nlmHeader.dataImageSize := DataExeSec.Size;
+ if assigned(BSSExeSec) then
+ nlmHeader.uninitializedDataSize:=BSSExeSec.Size;
+ if assigned(customExeSec) then
+ begin
+ nlmHeader.customDataOffset := customExeSec.DataPos;
+ nlmHeader.customDataSize := customExeSec.Size;
+ end;
+ if FNumModules > 0 then
+ begin
+ nlmHeader.moduleDependencyOffset := FindExeSection('.modules').DataPos+4; // 4 bytes dummy
+ nlmHeader.numberOfModuleDependencies := FNumModules;
+ end;
+ nlmHeader.relocationFixupOffset := relocsExeSec.DataPos;
+ nlmHeader.numberOfRelocationFixups := FNumRelocs;
+ nlmHeader.externalReferencesOffset := importsExeSec.DataPos+4; // 4 bytes dummy
+ nlmHeader.numberOfExternalReferences := FNumExternals;
+ if assigned(exportsExeSec) then
+ if exportsExeSec.Size>0 then
+ begin
+ nlmHeader.publicsOffset := exportsExeSec.dataPos;
+ nlmHeader.numberOfPublics := FnumExports;
+ end;
+ nlmHeader.codeStartOffset := EntrySym.Address;
+
+ {exit function}
+ exesym:=texesymbol(ExeSymbolList.Find('_Stop'));
+ if assigned(exesym) then
+ nlmHeader.exitProcedureOffset := exesym.ObjSymbol.address;
+
+ {check exit function}
+ exesym:=texesymbol(ExeSymbolList.Find('FPC_NW_CHECKFUNCTION'));
+ if assigned(exesym) then
+ nlmHeader.checkUnloadProcedureOffset := exesym.ObjSymbol.address;
+
+ // calc file pos after all exesections
+ fSizeWoDebugSyms := totalheadersize + ExeSecsListSize + headerAlignBytes;
+ ExeSectionList.ForEachCall(@ExeSectionList_calc_size,nil);
+
+ nlmExtHeader.stamp := NLM_MESSAGES_STAMP;
+ //extHeader.languageID // TODO: where to get this from ?
+ if assigned(messagesExeSec) then
+ begin
+ nlmExtHeader.messageFileOffset := messagesExeSec.DataPos;
+ nlmExtHeader.messageFileLength := messagesExeSec.Size;
+ end;
+ //nlmExtHeader.messageCount // TODO: how is messageCount set ?
+ if assigned(helpExeSec) then
+ begin
+ nlmExtHeader.helpFileOffset := helpExeSec.DataPos;
+ nlmExtHeader.helpFileLength := helpExeSec.Size;
+ end;
+ //nlmExtHeader.productID // TODO: were does this came from ?
+ if assigned(xdcExeSec) then
+ begin
+ nlmExtHeader.RPCDataOffset := xdcExeSec.DataPos;
+ nlmExtHeader.RPCDataLength := xdcExeSec.Size;
+ end;
+
+ if hassymbols then
+ begin
+ nlmHeader.debugInfoOffset := fSizeWoDebugSyms;
+ ExeSymbolList.ForEachCall(@globalsyms_create_symbol,nil);
+ nlmHeader.numberOfDebugRecords := FNumDebugSymbols;
+ end;
+
+ fillNlmVersionHeader;
+ FWriter.write(nlmHeader,sizeof(nlmHeader));
+
+ { variable header }
+ NLMWriteString(nlmDescription,true);
+ if stacksize < NLM_DEFAULT_STACKSIZE then stacksize := NLM_DEFAULT_STACKSIZE;
+ FWriter.Write(stacksize,4);
+ FWriter.writezeros(4);
+ dummyLong := ' LONG';
+ FWriter.Write(dummyLong,sizeof(dummyLong)); // old thread name
+ NLMWriteString(nlmScreenname,true);
+ NLMWriteString(nlmThreadname,true);
+
+ {version}
+ FWriter.Write(nlmVersionHeader,sizeof(nlmVersionHeader));
+ {copyright}
+ if nlmCopyright <> '' then
+ begin
+ FWriter.write(NLM_COPYRIGHT_STAMP,sizeof(NLM_COPYRIGHT_STAMP));
+ NLMWriteString(nlmCopyright,true);
+ end;
+ {messages}
+ FWriter.write(nlmExtHeader,sizeof(nlmExtHeader));
+
+ {custhead}
+ nlmCustHeader.stamp := NLM_CUSTOM_STAMP;
+ nlmCustHeader.dataLength := ExeSecsListSize;
+ nlmCustHeader.dataOffset := totalheadersize;
+ nlmCustHeader.hdrLength := $10; // why 16 ?, this is what binutils write
+ FWriter.write(nlmCustHeader,sizeof(nlmCustHeader));
+
+ {CyGnUsEx}
+ // bfd has a strange way to read the sections:
+ // the section directory is written under CuStHeAd
+ // when bfd finds the neader "CyGnUsEx", it uses the
+ // offset and size from CuStHeAd to read the section table
+
+ nlmCygnusHeader.stamp := NLM_CYGNUS_STAMP; // CyGnUsEx
+ // ld writes some unknown values here, bfd irgnores the values at all
+ // lets write the offset and length of the segment table
+ nlmCygnusHeader.offset := nlmCustHeader.dataLength;
+ nlmCygnusHeader.length := nlmCustHeader.dataOffset;
+ FWriter.write(nlmCygnusHeader,sizeof(nlmCygnusHeader));
+ FWriter.WriteZeros(8); // empty stamp + align next to 16 bytes
+
+ if FWriter.Size<>totalheadersize then
+ internalerror(201103061); // headersize <> header written
+
+ { Section headers, CuStHeAd points to this section, not needed by
+ netware. Can be used to find the section in the nlm file, binutils
+ will use this section }
+ ExeSectionList.ForEachCall(@ExeSectionList_write_header,nil);
+ FWriter.WriteZeros(headerAlignBytes);
+ if FWriter.Size<>totalheadersize+ExeSecsListSize+headerAlignBytes then
+ internalerror(201103062);
+ { Section data }
+ if assigned(exemap) then
+ begin
+ exemap.Add('');
+ exemap.Add('NLM file offsets:');
+ end;
+ ExeSectionList.ForEachCall(@ExeSectionList_write_data,nil);
+
+ if hassymbols then
+ FWriter.writearray(NlmSymbols); // specific symbols for the internal netware debugger
+
+ result:=true;
+ end;
+
+
+
+ procedure TNLMexeoutput.GenerateLibraryImports(ImportLibraryList:TFPHashObjectList);
+ var
+ idata5objsection : TObjSection;
+ basedllname : string;
+
+ function AddImport(const afuncname,amangledname:string; isvar:boolean):TObjSymbol;
+ var
+ secname:string;
+ begin
+ //Comment (V_Debug,'TNLMexeoutput.GenerateLibraryImports.AddImport '+afuncName);
+ result:=nil;
+ if assigned(exemap) then
+ exemap.Add(' Importing Function '+afuncname);
+
+ if not isvar then
+ with internalobjdata do
+ begin
+ secname:=basedllname+'_i_'+amangledname;
+ idata5objsection:=createsection(sec_idata5, secname);
+ internalobjdata.SetSection(idata5objsection);
+ result:=internalobjdata.SymbolDefine('_'+amangledname,AB_IMPORT,AT_FUNCTION);
+ end;
+ end;
+
+ var
+ i,j : longint;
+ ImportLibrary : TImportLibrary;
+ ImportSymbol : TImportSymbol;
+ exesym : TExeSymbol;
+ importAddressList : TFPObjectList;
+ begin
+ if ImportLibraryList.Count > 0 then
+ begin
+ {objsec:=}internalObjData.createsection('.imports',0,[oso_data,oso_keep]);
+ i := 0;
+ internalobjdata.writebytes(i,4); // dummy to avoid deletion
+ {objsec:=}internalObjData.createsection('.modules',0,[oso_data,oso_keep]);
+ internalobjdata.writebytes(i,4); // dummy to avoid deletion
+ end;
+ for i:=0 to ImportLibraryList.Count-1 do
+ begin
+ ImportLibrary:=TImportLibrary(ImportLibraryList[i]);
+ idata5objsection:=nil;
+ for j:=0 to ImportLibrary.ImportSymbolList.Count-1 do
+ begin
+ ImportSymbol:=TImportSymbol(ImportLibrary.ImportSymbolList[j]);
+ exesym:=TExeSymbol(ExeSymbolList.Find(ImportSymbol.MangledName));
+ if assigned(exesym) and
+ (exesym.State<>symstate_defined) then
+ begin
+ basedllname:=ExtractFileName(ImportLibrary.Name);
+ exesym.objsymbol:=AddImport(ImportSymbol.Name,ImportSymbol.MangledName,ImportSymbol.IsVar);
+ exesym.State:=symstate_defined;
+ importAddressList := TFPObjectList.create(false);
+ nlmImports.Add(ImportSymbol.Name,importAddressList);
+ if pos('.',basedllname) = 0 then
+ basedllname := basedllname + '.nlm';
+ nlmImpNames.Add(ImportSymbol.Name,TStringObj.create(lower(basedllname)));
+ end;
+ end;
+ end;
+
+ PackUnresolvedExeSymbols('after DLL imports');
+ GenerateExports;
+ end;
+
+
+
+ procedure TNLMexeoutput.GenerateImports;
+ var
+ exesec,
+ impexesec : TExeSection;
+ objsec : TObjSection;
+ objreloc : TObjRelocation;
+ i,j,k : integer;
+ importAddressList : TFPObjectList;
+ name,mName : string;
+ b : byte;
+ modules : string;
+ modName : TStringObj;
+ begin
+ if FImportsGenerated then exit;
+ FImportsGenerated := true;
+ impexesec:=FindExeSection('.imports');
+ if impexesec=nil then exit;
+
+ for i:=0 to ExeSectionList.Count-1 do
+ begin
+ exesec:=TExeSection(ExeSectionList[i]);
+ for j:=0 to exesec.ObjSectionList.count-1 do
+ begin
+ objsec:=TObjSection(exesec.ObjSectionList[j]);
+ if j=0 then
+ begin
+ exesec.DataPos:=objSec.DataPos;
+ exesec.MemPos:=objSec.MemPos;
+ end;
+ if (copy(objsec.name,1,5) <> '.text') and (copy(objsec.name,1,4) <> '.bss') and (copy(objsec.name,1,5) <> '.data') then
+ continue;
+ for k:=0 to objsec.ObjRelocations.Count-1 do
+ begin
+ objreloc := TObjRelocation(objsec.ObjRelocations[k]);
+ if assigned(objreloc.symbol) then
+ begin
+ //writeln (objreloc.symbol.name,' ',objreloc.symbol.bind);
+ if objreloc.symbol.bind = AB_IMPORT then
+ begin
+ importAddressList := TFPObjectList(nlmImports.Find(objreloc.symbol.name));
+ if assigned(importAddressList) then
+ begin
+ objreloc.objsection := objsec; // points to idata5
+ importAddressList.Add(objreloc);
+ end else
+ begin
+ comment(v_error,objreloc.symbol.name+' is external but not defined in nlm imports');
+ end;
+ end;
+ end
+ end;
+ end;
+ end;
+
+ modules := '';
+ for i := 0 to nlmImports.count-1 do
+ begin
+ importAddressList := TFPObjectList(nlmImports.Items[i]);
+ if importAddressList.Count > 0 then
+ begin
+ name := nlmImports.NameOfIndex(i);
+
+ // find the module to be imported and add it to the list
+ // of modules to be auto loaded
+ modName := TStringObj(nlmImpNames.Find(name));
+ if assigned(modName) then
+ begin
+ mName := modName.Value;
+ if mName <> '' then
+ if copy(mName,1,1) <> '!' then // special, with ! only the imp will be included but no module is autoloaded, needed i.e. for netware.imp
+ begin
+ if pos(mName+';',modules) < 1 then
+ begin
+ modules := modules + mName + ';';
+ inc(FNumModules);
+ end;
+ end;
+ end;
+ internalobjdata.SetSection(TObjSection(impexesec.ObjSectionList[0]));
+ objNLMwriteString (name,false); // name of symbol
+ k := importAddressList.Count;
+ internalobjdata.writebytes(k,sizeof(k)); // number of references
+ inc(FNumExternals);
+ for j := 0 to importAddressList.Count-1 do
+ begin
+ objreloc := TObjRelocation(importAddressList[j]);
+ objsec := objreloc.objsection;
+ if oso_executable in objreloc.objsection.SecOptions then
+ begin
+ if objreloc.typ <> RELOC_RELATIVE then comment(v_error,'reference to external symbols must be RELOC_RELATIVE');
+ // TODO: how to check if size is 4 ????
+
+ k := objsec.MemPos + objreloc.DataOffset;
+ k := k or $40000000;
+ // TODO: data|code if we support importing data symbols
+ // i do not know if this is possible with netware
+ internalobjdata.writebytes(k,sizeof(k)); // address
+
+ // the netware loader requires an offset at the import address
+ // for call = E8 this is -4
+ // TODO: how can we check the needed offset ??
+ if objreloc.DataOffset > 0 then
+ begin
+ objsec.Data.seek(objreloc.DataOffset-1);
+ objsec.data.read(b,1);
+ if b <> $E8 then
+ comment(v_error,'no rcall (E8) before imported symbol target address');
+ k := -4;
+ objsec.Data.write(k,sizeof(k));
+ end else
+ begin
+ objsec.Data.seek(objreloc.DataOffset);
+ k := 0;
+ objsec.Data.write(k,sizeof(k));
+ end;
+ objreloc.typ := RELOC_NONE; // to avoid that TCoffObjSection.fixuprelocs changes the address again
+ end else
+ comment(v_error,'Importing of symbols only supported for .text');
+ end;
+ end;
+ end;
+
+ exesec := FindExeSection('.modules');
+ if not assigned(exesec) then internalerror(201103272); // exe section .modules does not exist ???
+ internalobjdata.SetSection(TObjSection(exesec.ObjSectionList[0]));
+ for i := 1 to FNumModules do
+ begin
+ name := GetToken(modules,';');
+ objNLMwriteString (name,false);
+ end;
+ end;
+
+
+ procedure TNLMexeoutput.GenerateExports;
+ var
+ hp : texported_item; { for exports }
+ len : byte;
+ addr: longword;
+ exesym : texesymbol;
+ begin
+ internalObjData.createsection('.exports',0,[oso_data,oso_keep]);
+ {name LString 1+n bytes
+ addr 4 bytes
+ addr and $80000000 > 0 -> .text else .data}
+ hp:=texported_item(current_module._exports.first);
+ if assigned(hp) then
+ if assigned(exemap) then
+ exemap.Add('');
+ while assigned(hp) do
+ begin
+ { Export the Symbol }
+ if assigned(exemap) then
+ exemap.Add(' Exporting Function '+hp.sym.prettyname+' as '+hp.name^);
+ len := length(hp.name^);
+ internalobjdata.writebytes(len,1);
+ internalobjdata.writebytes(hp.name^[1],len);
+ exesym:=texesymbol(ExeSymbolList.Find(hp.sym.prettyname));
+ if not assigned(exesym) then
+ begin
+ comment(v_error,'exported symbol '+hp.sym.prettyname+' not found');
+ exit;
+ end;
+ // for exported functions we have to set the upper bit
+ // this will be done in .writedata
+ if not hp.is_var then
+ FexportFunctionOffsets.Add(pointer(PtrUInt(internalobjdata.CurrObjSec.Size)));
+ internalobjdata.writereloc(0,4,exesym.ObjSymbol,RELOC_ABSOLUTE32);
+
+ addr := 0;
+ internalobjdata.writebytes(addr,4);
+ inc(FnumExports);
+ hp:=texported_item(hp.next);
+ end;
+ end;
+
+ procedure TNLMexeoutput.GenerateRelocs;
+
+ var
+ exesec : TExeSection;
+ objsec : TObjSection;
+ objreloc : TObjRelocation;
+ i,j,k : longint;
+ offset : longword;
+ inSec,toSec : TsecType;
+ targetSectionName : string;
+
+ begin
+ if not RelocSection or FRelocsGenerated then
+ exit;
+ exesec:=FindExeSection('.reloc');
+ if exesec=nil then
+ exit;
+ objsec:=internalObjData.createsection('.reloc',0,exesec.SecOptions+[oso_data]);
+ exesec.AddObjSection(objsec);
+ for i:=0 to ExeSectionList.Count-1 do
+ begin
+ exesec:=TExeSection(ExeSectionList[i]);
+ for j:=0 to exesec.ObjSectionList.count-1 do
+ begin
+ objsec:=TObjSection(exesec.ObjSectionList[j]);
+ //writeln ('Relocs for ',exesec.name,' - ',objsec.name);
+ { create relocs only for sections which are loaded in memory }
+ if not (oso_load in objsec.SecOptions) then
+ continue;
+ { create relocs only for .text and .data }
+ inSec := SectionType (objsec.name);
+ if (inSec <> Section_Text) and (inSec <> Section_Data) then
+ continue;
+
+ for k:=0 to objsec.ObjRelocations.Count-1 do
+ begin
+ objreloc:=TObjRelocation(objsec.ObjRelocations[k]);
+ if objreloc.typ <> RELOC_ABSOLUTE then
+ continue;
+ offset:=objsec.MemPos+objreloc.dataoffset;
+ targetSectionName := '';
+ if objreloc.symbol <> nil then
+ begin
+ // writeln (' MemPos',objsec.MemPos,
+ // ' dataOfs:',objreloc.dataoffset,' ',objsec.name,
+ // ' objreloc.symbol: ',objreloc.symbol.name,
+ // ' objreloc.symbol.objsection.name: ',objreloc.symbol.objsection.name,
+ // ' ',objreloc.symbol.Typ,' ',objrel
+ // oc.symbol.bind,' ',objreloc.Typ);
+ if objreloc.symbol.objsection.name[1] <> '.' then
+ targetSectionName := objreloc.symbol.name // specials like __bss_start__
+ else // dont use objsection.name because it begins with *
+ targetSectionName := copy(objreloc.symbol.objsection.name,1,5); // all others begin with .segment, we only have to check for .text, .data or .bss
+ end else
+ internalerror(2011030603);
+
+ toSec := SectionType(targetSectionName);
+
+ if (toSec = Section_Text) or (toSec = Section_Data) then
+ begin
+ if (inSec = Section_text) then offset := offset or $40000000;
+ if (toSec = Section_text) then offset := offset or $80000000;
+ internalObjData.writebytes(offset,4);
+ inc(FNumRelocs);
+ end;
+ end;
+ end;
+ end;
+ FRelocsGenerated:=true;
+ end;
+
+
+ procedure TNLMexeoutput.Order_End;
+ var
+ exesec : TExeSection;
+ begin
+ inherited;
+ exesec:=FindExeSection('.reloc');
+ if exesec=nil then
+ exit;
+ exesec.SecOptions:=exesec.SecOptions + [oso_Data,oso_keep,oso_load];
+ end;
+
+
+ procedure TNLMexeoutput.MemPos_ExeSection(const aname:string);
+ begin
+ if aname='.reloc' then
+ GenerateRelocs;
+ if aname='.imports' then
+ GenerateImports;
+ if aname='.data' then
+ currMemPos := 0; // both, data and code in the nlm have a start offset of 0
+ inherited;
+ end;
+
+
+ procedure TNLMexeoutput.DataPos_ExeSection(const aname:string);
+ begin
+ inherited;
+ end;
+
+
+ procedure TNLMexeoutput.NLMwriteString (const s : string; terminateWithZero : boolean);
+ var len : byte;
+ begin
+ if length(s) > 254 then len := 254 else len := length(s);
+ FWriter.Write(len,1);
+ if len > 0 then
+ FWriter.write(s[1],len);
+ if terminateWithZero then
+ FWriter.writeZeros(1);
+ end;
+
+
+ procedure TNLMexeoutput.objNLMwriteString (const s : string; terminateWithZero : boolean);
+ var len : byte;
+ begin
+ if length(s) > 254 then len := 254 else len := length(s);
+ Internalobjdata.writebytes(len,1);
+ if len > 0 then
+ Internalobjdata.writebytes(s[1],len);
+ if terminateWithZero then
+ begin
+ len := 0;
+ Internalobjdata.writebytes(s[1],len);
+ end;
+ end;
+
+ { parse netware specific linker options }
+ procedure TNLMexeoutput.ParseScript (linkscript:TCmdStrList);
+ var
+ hp : TCmdStrListItem;
+ opt,keyword,s : string;
+ i : integer;
+
+ function toInteger(s:string; min,max:integer; var res:integer):boolean;
+ var
+ code:word;
+ begin
+ result := false;
+ val (s,res,code);
+ if code<>0 then exit;
+ if (res < min) or (res > max) then exit;
+ result := true;
+ end;
+
+
+ procedure loadFile (const secName, fileName, Desc : string);
+ var
+ fileBuf : array [0..4095] of char;
+ bytesRead : longint;
+ fileH : THandle;
+ fn : TCmdStr;
+
+ begin
+ fn := fileName;
+ if not fileExists(fn) then
+ if not unitsearchpath.FindFile(fileName,true,fn) then
+ begin
+ comment(v_error,'can not find '+desc+' file '+fileName);
+ exit;
+ end;
+ fileH := fileOpen (fn,fmOpenRead);
+ if fileH = THandle(-1) then
+ begin
+ comment(v_error,'can not open '+desc+' file '+fn);
+ exit;
+ end;
+ { load file into section }
+ internalObjData.createsection(secName,0,[oso_data,oso_keep]);
+ repeat
+ bytesRead := fileRead(fileH,fileBuf,sizeof(fileBuf));
+ if bytesRead > 0 then
+ internalobjdata.writebytes(fileBuf,bytesRead);
+ until bytesRead < sizeof(fileBuf);
+ fileClose(fileH);
+ end;
+
+ begin
+ hp:=TCmdStrListItem(linkscript.first);
+ while assigned(hp) do
+ begin
+ opt:=hp.str;
+ if (opt='') or (opt[1]='#') then
+ continue;
+ keyword:=Upper(GetToken(opt,' '));
+ if keyword = 'AUTOUNLOAD' then
+ begin
+ nlmHeader.flags:=nlmHeader.flags or NLM_FLAGS_AUTOUNLOAD;
+ end else
+ if keyword = 'COPYRIGHT' then
+ begin
+ nlmCopyright := GetToken(opt,' ');
+ end else
+ if keyword = 'CUSTOM' then
+ begin
+ loadFile ('.custom',GetToken(opt,' '),'custom data');
+ end;
+ if keyword = 'DATE' then // month day 4-digit-year
+ begin
+ if not toInteger(GetToken(opt,' '),1,12,i) then comment(v_error,'DATE: invalid month')
+ else nlmVersionHeader.month := i;
+ if not toInteger(GetToken(opt,' '),1,31,i) then comment(v_error,'DATE: invalid day')
+ else nlmVersionHeader.day := i;
+ if not toInteger(GetToken(opt,' '),1900,3000,i) then comment(v_error,'DATE: invalid year')
+ else nlmVersionHeader.year := i;
+ end else
+ if keyword = 'DEBUG' then
+ begin
+ // ignore
+ end else
+ if keyword = 'DESCRIPTION' then
+ begin
+ nlmDescription := GetToken(opt,' ');
+ if length (nlmDescription) > NLM_MAX_DESCRIPTION_LENGTH then
+ nlmDescription := copy (nlmDescription,1,NLM_MAX_DESCRIPTION_LENGTH);
+ end else
+ if keyword = 'FLAG' then
+ begin
+ s := upper(GetToken(opt,' '));
+ if (not toInteger(GetToken(opt,' '),1,$FFFFFFF,i)) or ((s <> 'ON') and (S <> 'OFF')) then comment(v_error,'FLAG: invalid') else
+ if (s='ON') then
+ nlmHeader.flags:=nlmHeader.flags or i else
+ nlmHeader.flags:=nlmHeader.flags and ($FFFFFFF-i);
+ end else
+ if keyword = 'HELP' then
+ begin
+ loadFile ('.help',GetToken(opt,' '),'help');
+ end else
+ if keyword = 'MESSAGES' then
+ begin
+ loadFile ('.messages',GetToken(opt,' '),'message');
+ end else
+ if keyword = 'MULTIPLE' then
+ begin
+ nlmHeader.flags:=nlmHeader.flags or NLM_FLAGS_MULTILOAD;
+ end else
+ if keyword = 'OS_DOMAIN' then
+ begin
+ nlmHeader.flags:=nlmHeader.flags or NLM_FLAGS_OSDOMAIN;
+ end else
+ if keyword = 'PSEUDOPREEMPTION' then
+ begin
+ nlmHeader.flags:=nlmHeader.flags or NLM_FLAGS_PSEUDOPREEMPTION;
+ end else
+ if keyword = 'REENTRANT' then
+ begin
+ nlmHeader.flags:=nlmHeader.flags or NLM_FLAGS_REENTRANT;
+ end else
+ if keyword = 'SCREENNAME' then
+ begin
+ nlmScreenname := GetToken(opt,' ');
+ if length(nlmScreenname) > NLM_MAX_SCREEN_NAME_LENGTH then
+ nlmScreenName := copy (nlmScreenName,1,NLM_MAX_SCREEN_NAME_LENGTH);
+ end else
+ if (keyword = 'STACK') or (keyword = 'STACKSIZE') then
+ begin
+ if (not toInteger(GetToken(opt,' '),1,$FFFFFFF,i)) then comment(v_error,'invalid stacksize') else
+ stacksize := i;
+ end else
+ if keyword = 'SYNCHRONIZE' then
+ begin
+ nlmHeader.flags:=nlmHeader.flags or NLM_FLAGS_SYNCHRONIZE;
+ end else
+ if keyword = 'THREADNAME' then
+ begin
+ nlmThreadname := GetToken(opt,' ');
+ if length(nlmThreadname) > NLM_MAX_THREAD_NAME_LENGTH then
+ nlmThreadname := copy (nlmThreadname,1,NLM_MAX_THREAD_NAME_LENGTH);
+ end else
+ if keyword = 'TYPE' then
+ begin
+ if (not toInteger(GetToken(opt,' '),1,16,i)) then comment(v_error,'invalid TYPE') else
+ nlmHeader.moduleType := i; // TODO: set executable extension (.DSK, .LAN, ...)
+ end else
+ if keyword = 'VERSION' then
+ begin
+ if (not toInteger(GetToken(opt,' '),0,$FFFFFFF,i)) then comment(v_error,'invalid major version') else
+ nlmVersionHeader.majorVersion := i;
+ if (not toInteger(GetToken(opt,' '),0,99,i)) then comment(v_error,'invalid minor version') else
+ nlmVersionHeader.minorVersion := i;
+ if (not toInteger(GetToken(opt,' '),0,$FFFFFFF,i)) then comment(v_error,'invalid minor version') else
+ if i > 26 then
+ nlmVersionHeader.revision := 0 else
+ nlmVersionHeader.revision := i;
+ end else
+ if keyword = 'XDCDATA' then
+ begin
+ loadFile ('.xdc',GetToken(opt,' '),'xdc');
+ end;
+ { TODO: check for unknown options. This means all handled option
+ (also in link.pas) have to be flagged if processed }
+ hp:=TCmdStrListItem(hp.next);
+ end;
+ end;
+
+{****************************************************************************
+ TNLMCoffObjData
+****************************************************************************}
+
+ constructor TNLMCoffObjData.create(const n:string);
+ begin
+ inherited createcoff(n,true,TNLMCoffObjSection);
+ end;
+
+
+{****************************************************************************
+ TNLMoffObjSection
+****************************************************************************}
+
+ constructor TNLMCoffObjSection.create(AList:TFPHashObjectList;const aname:string;aalign:shortint;aoptions:TObjSectionOptions);
+ begin
+ inherited create(alist,aname,aalign,aoptions);
+ end;
+
+
+ constructor TNLMCoffObjOutput.create(AWriter:TObjectWriter);
+ begin
+ // ??????
+ // if win32=false, .stabs and .stabstr will be written without oso_debug
+ // Without oso_debug the sections will be removed by the linker
+ inherited createcoff(AWriter,{win32}true);
+ cobjdata:=TNLMCoffObjData;
+ end;
+
+{****************************************************************************
+ TDJCoffAssembler
+****************************************************************************}
+
+ constructor TNLMCoffAssembler.Create(smart:boolean);
+ begin
+ inherited Create(smart);
+ CObjOutput:=TNLMCoffObjOutput;
+ end;
+
+ constructor TNLMCoffObjInput.create;
+ begin
+ inherited createcoff(true);
+ cobjdata:=TNLMCoffObjData;
+ end;
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+const
+ as_i386_nlmcoff_info : tasminfo =
+ (
+ id : as_i386_nlmcoff;
+ idtxt : 'NLMCOFF';
+ asmbin : '';
+ asmcmd : '';
+ supported_targets : [system_i386_Netware,system_i386_netwlibc];
+ flags : [af_outputbinary,af_smartlink_sections];
+ labelprefix : '.L';
+ comment : '';
+ );
+
+
+
+initialization
+{$ifdef i386}
+ RegisterAssembler(as_i386_nlmcoff_info,TNLMCoffAssembler);
+{$endif i386}
+end.
diff --git a/closures/compiler/optbase.pas b/closures/compiler/optbase.pas
new file mode 100644
index 0000000000..c37c5aa974
--- /dev/null
+++ b/closures/compiler/optbase.pas
@@ -0,0 +1,216 @@
+{
+ Basic node optimizer stuff
+
+ Copyright (c) 2007 by Florian Klaempfl
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit optbase;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ globtype;
+
+ type
+ { this should maybe replaced by a spare set,
+ using a dyn. array makes assignments cheap }
+ tdfaset = array of byte;
+ PDFASet = ^TDFASet;
+
+ toptinfo = record
+ { index of the current node inside the dfa sets, aword(-1) if no entry }
+ index : aword;
+ { dfa }
+ def : tdfaset;
+ use : tdfaset;
+ life : tdfaset;
+ defsum : tdfaset;
+ avail : tdfaset;
+ end;
+
+ poptinfo = ^toptinfo;
+
+ { basic set operations for dfa sets }
+
+ { add e to s }
+ procedure DFASetInclude(var s : tdfaset;e : integer);
+
+ { add s to d }
+ procedure DFASetIncludeSet(var d : tdfaset;const s : tdfaset);
+
+ { remove e from s }
+ procedure DFASetExclude(var s : tdfaset;e : integer);
+
+ { test if s contains e }
+ function DFASetIn(const s : tdfaset;e : integer) : boolean;
+
+ { d:=s1+s2; }
+ procedure DFASetUnion(var d : tdfaset;const s1,s2 : tdfaset);
+
+ { d:=s1*s2; }
+ procedure DFASetIntersect(var d : tdfaset;const s1,s2 : tdfaset);
+
+ { d:=s1-s2; }
+ procedure DFASetDiff(var d : tdfaset;const s1,s2 : tdfaset);
+
+ { s1<>s2; }
+ function DFASetNotEqual(const s1,s2 : tdfaset) : boolean;
+
+ { output DFA set }
+ procedure PrintDFASet(var f : text;s : TDFASet);
+
+ implementation
+
+ uses
+ cutils;
+
+ procedure DFASetInclude(var s : tdfaset;e : integer);
+ var
+ e8 : Integer;
+ begin
+ e8:=e div 8;
+ if e8>high(s) then
+ SetLength(s,e8+1);
+ s[e8]:=s[e8] or (1 shl (e mod 8));
+ end;
+
+
+ procedure DFASetIncludeSet(var d : tdfaset;const s : tdfaset);
+ var
+ i : integer;
+ begin
+ if length(s)>length(d) then
+ SetLength(d,length(s));
+ for i:=0 to high(s) do
+ d[i]:=d[i] or s[i];
+ end;
+
+
+ procedure DFASetExclude(var s : tdfaset;e : integer);
+ var
+ e8 : Integer;
+ begin
+ e8:=e div 8;
+ if e8<=high(s) then
+ s[e8]:=s[e8] and not(1 shl (e mod 8));
+ end;
+
+
+ function DFASetIn(const s : tdfaset;e : integer) : boolean;
+ var
+ e8 : Integer;
+ begin
+ e8:=e div 8;
+ if e8<=high(s) then
+ result:=(s[e8] and (1 shl (e mod 8)))<>0
+ else
+ result:=false;
+ end;
+
+
+ procedure DFASetUnion(var d : tdfaset;const s1,s2 : tdfaset);
+ var
+ i : integer;
+ begin
+ SetLength(d,max(Length(s1),Length(s2)));
+ for i:=0 to min(high(s1),high(s2)) do
+ d[i]:=s1[i] or s2[i];
+ if high(s1)<high(s2) then
+ for i:=high(s1)+1 to high(s2) do
+ d[i]:=s2[i]
+ else
+ for i:=high(s2)+1 to high(s1) do
+ d[i]:=s1[i];
+ end;
+
+
+ procedure DFASetIntersect(var d : tdfaset;const s1,s2 : tdfaset);
+ var
+ i : integer;
+ begin
+ SetLength(d,min(Length(s1),Length(s2)));
+ for i:=0 to high(d) do
+ d[i]:=s1[i] and s2[i];
+ end;
+
+
+ procedure DFASetDiff(var d : tdfaset;const s1,s2 : tdfaset);
+ var
+ i : integer;
+ begin
+ SetLength(d,length(s1));
+ for i:=0 to high(d) do
+ if i>high(s2) then
+ d[i]:=s1[i]
+ else
+ d[i]:=s1[i] and not(s2[i]);
+ end;
+
+
+ function DFASetNotEqual(const s1,s2 : tdfaset) : boolean;
+ var
+ i : integer;
+ begin
+ result:=true;
+ { one set could be larger than the other }
+ if length(s1)>length(s2) then
+ begin
+ for i:=0 to high(s2) do
+ if s1[i]<>s2[i] then
+ exit;
+ { check remaining part being zero }
+ for i:=length(s2) to high(s1) do
+ if s1[i]<>0 then
+ exit;
+ end
+ else
+ begin
+ for i:=0 to high(s1) do
+ if s1[i]<>s2[i] then
+ exit;
+ { check remaining part being zero }
+ for i:=length(s1) to high(s2) do
+ if s2[i]<>0 then
+ exit;
+ end;
+ result:=false;
+ end;
+
+
+ procedure PrintDFASet(var f : text;s : TDFASet);
+ var
+ i : integer;
+ first : boolean;
+ begin
+ first:=true;
+ for i:=0 to Length(s)*8 do
+ begin
+ if DFASetIn(s,i) then
+ begin
+ if not(first) then
+ write(f,',');
+ write(f,i);
+ first:=false;
+ end;
+ end;
+ end;
+
+
+end.
diff --git a/closures/compiler/optcse.pas b/closures/compiler/optcse.pas
new file mode 100644
index 0000000000..592c7cd28a
--- /dev/null
+++ b/closures/compiler/optcse.pas
@@ -0,0 +1,335 @@
+{
+ Common subexpression elimination on base blocks
+
+ Copyright (c) 2005 by Florian Klaempfl
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit optcse;
+
+{$i fpcdefs.inc}
+
+{ $define csedebug}
+{ $define csestats}
+
+ interface
+
+ uses
+ node;
+
+ {
+ the function creates non optimal code so far:
+ - call para nodes are cse barriers because they can be reordered and thus the
+ temp. creation can be done too late
+ - cse's in chained expressions are not recognized: the common subexpression
+ in (a1 and b and c) vs. (a2 and b and c) is not recognized because there is no common
+ subtree b and c
+ - the cse knows nothing about register pressure. In case of high register pressure, cse might
+ have a negative impact
+ - assignment nodes are currently cse borders: things like a[i,j]:=a[i,j]+1; are not improved
+ - the list of cseinvariant node types and inline numbers is not complete yet
+
+ Further, it could be done probably in a faster way though the complexity can't probably not reduced
+ }
+ function do_optcse(var rootnode : tnode) : tnode;
+
+ implementation
+
+ uses
+ globtype,
+ cclasses,
+ verbose,
+ nutils,
+ procinfo,
+ nbas,nld,ninl,ncal,ncnv,nadd,
+ pass_1,
+ symconst,symtype,symdef,symsym,
+ defutil,
+ optbase;
+
+ const
+ cseinvariant : set of tnodetype = [addn,muln,subn,divn,slashn,modn,andn,orn,xorn,notn,vecn,
+ derefn,equaln,unequaln,ltn,gtn,lten,gten,typeconvn,subscriptn,
+ inn,symdifn,shrn,shln,ordconstn,realconstn,unaryminusn,pointerconstn,stringconstn,setconstn,
+ isn,asn,starstarn,nothingn,temprefn,loadparentfpn {,callparan}];
+
+ function searchsubdomain(var n:tnode; arg: pointer) : foreachnoderesult;
+ begin
+ if (n.nodetype in cseinvariant) or
+ ((n.nodetype=inlinen) and
+ (tinlinenode(n).inlinenumber in [in_assigned_x])
+ ) or
+ ((n.nodetype=loadn) and
+ not((tloadnode(n).symtableentry.typ in [staticvarsym,localvarsym,paravarsym]) and
+ (vo_volatile in tabstractvarsym(tloadnode(n).symtableentry).varoptions))
+ ) then
+ result:=fen_true
+ else
+ begin
+ pboolean(arg)^:=false;
+ result:=fen_norecurse_true;
+ end;
+ end;
+
+ type
+ tlists = record
+ nodelist : tfplist;
+ locationlist : tfplist;
+ equalto : tfplist;
+ refs : tfplist;
+ avail : TDFASet;
+ end;
+
+ plists = ^tlists;
+
+ { collectnodes needs the address of itself to call foreachnodestatic,
+ so we need a wrapper because @<func> inside <func doesn't work }
+
+ function collectnodes(var n:tnode; arg: pointer) : foreachnoderesult;forward;
+
+ function collectnodes2(var n:tnode; arg: pointer) : foreachnoderesult;
+ begin
+ result:=collectnodes(n,arg);
+ end;
+
+ function collectnodes(var n:tnode; arg: pointer) : foreachnoderesult;
+ var
+ i,j : longint;
+ begin
+ result:=fen_false;
+ { don't add the tree below an untyped const parameter: there is
+ no information available that this kind of tree actually needs
+ to be addresable, this could be improved }
+ if ((n.nodetype=callparan) and
+ (tcallparanode(n).left.resultdef.typ=formaldef) and
+ (tcallparanode(n).parasym.varspez=vs_const)) then
+ begin
+ result:=fen_norecurse_false;
+ exit;
+ end;
+ { so far, we can handle only nodes being read }
+ if (n.flags*[nf_write,nf_modify]=[]) and
+ { node possible to add? }
+ assigned(n.resultdef) and
+ (tstoreddef(n.resultdef).is_intregable or tstoreddef(n.resultdef).is_fpuregable) and
+ { is_int/fpuregable allows arrays and records to be in registers, cse cannot handle this }
+ not(n.resultdef.typ in [arraydef,recorddef]) and
+ { same for voiddef }
+ not(is_void(n.resultdef)) and
+ { adding tempref nodes is worthless but their complexity is probably <= 1 anyways }
+ not(n.nodetype in [temprefn]) and
+
+ { node worth to add?
+
+ We consider almost every node because even loading a variables from
+ a register instead of memory is more beneficial. This behaviour should
+ not increase register pressure because if a variable is already
+ in a register, the reg. allocator can merge the nodes. If a variable
+ is loaded from memory, loading this variable and spilling another register
+ should not add a speed penalty.
+ }
+ {
+ load nodes are not considered if they load para or local symbols from the
+ current stack frame, those are in registers anyways if possible
+ }
+ (not(n.nodetype=loadn) or
+ not(tloadnode(n).symtableentry.typ in [paravarsym,localvarsym]) or
+ (tloadnode(n).symtable.symtablelevel<>current_procinfo.procdef.parast.symtablelevel)
+ ) and
+
+ {
+ Const nodes however are only considered if their complexity is >1
+ This might be the case for the risc architectures if they need
+ more than one instruction to load this particular value
+ }
+ (not(is_constnode(n)) or (node_complexity(n)>1)) then
+ begin
+ plists(arg)^.nodelist.Add(n);
+ plists(arg)^.locationlist.Add(@n);
+ plists(arg)^.refs.Add(nil);
+ plists(arg)^.equalto.Add(pointer(-1));
+
+ DFASetInclude(plists(arg)^.avail,plists(arg)^.nodelist.count-1);
+
+ for i:=0 to plists(arg)^.nodelist.count-2 do
+ begin
+ if tnode(plists(arg)^.nodelist[i]).isequal(n) and DFASetIn(plists(arg)^.avail,i) then
+ begin
+ { use always the first occurence }
+ if plists(arg)^.equalto[i]<>pointer(-1) then
+ plists(arg)^.equalto[plists(arg)^.nodelist.count-1]:=plists(arg)^.equalto[i]
+ else
+ plists(arg)^.equalto[plists(arg)^.nodelist.count-1]:=pointer(ptrint(i));
+ plists(arg)^.refs[i]:=pointer(plists(arg)^.refs[i])+1;
+ break;
+ end;
+ end;
+
+ { boolean and/or require a special handling: after evaluating the and/or node,
+ the expressions of the right side might not be available due to short boolean
+ evaluation, so after handling the right side, mark those expressions
+ as unavailable }
+ if (n.nodetype in [orn,andn]) and is_boolean(taddnode(n).left.resultdef) then
+ begin
+ foreachnodestatic(pm_postprocess,taddnode(n).left,@collectnodes2,arg);
+ j:=plists(arg)^.nodelist.count;
+ foreachnodestatic(pm_postprocess,taddnode(n).right,@collectnodes2,arg);
+ for i:=j to plists(arg)^.nodelist.count-1 do
+ DFASetExclude(plists(arg)^.avail,i);
+ result:=fen_norecurse_false;
+ end;
+ end;
+ end;
+
+
+ function searchcsedomain(var n: tnode; arg: pointer) : foreachnoderesult;
+ var
+ csedomain : boolean;
+ lists : tlists;
+ templist : tfplist;
+ i : longint;
+ def : tstoreddef;
+ nodes : tblocknode;
+ creates,
+ statements : tstatementnode;
+ hp : ttempcreatenode;
+ begin
+ result:=fen_false;
+ if n.nodetype in cseinvariant then
+ begin
+ csedomain:=true;
+ foreachnodestatic(pm_postprocess,n,@searchsubdomain,@csedomain);
+ { found a cse domain }
+ if csedomain then
+ begin
+ statements:=nil;
+ result:=fen_norecurse_true;
+{$ifdef csedebug}
+ writeln('============ cse domain ==================');
+ printnode(output,n);
+ writeln('Complexity: ',node_complexity(n));
+{$endif csedebug}
+ lists.nodelist:=tfplist.create;
+ lists.locationlist:=tfplist.create;
+ lists.equalto:=tfplist.create;
+ lists.refs:=tfplist.create;
+ foreachnodestatic(pm_postprocess,n,@collectnodes,@lists);
+
+ templist:=tfplist.create;
+ templist.count:=lists.nodelist.count;
+
+ { check all nodes if one is used more than once }
+ for i:=0 to lists.nodelist.count-1 do
+ begin
+ { current node used more than once? }
+ if assigned(lists.refs[i]) then
+ begin
+ if not(assigned(statements)) then
+ begin
+ nodes:=internalstatements(statements);
+ addstatement(statements,internalstatements(creates));
+ end;
+
+ def:=tstoreddef(tnode(lists.nodelist[i]).resultdef);
+ templist[i]:=ctempcreatenode.create_value(def,def.size,tt_persistent,
+ def.is_intregable or def.is_fpuregable,tnode(lists.nodelist[i]));
+ { make debugging easier and set temp. location to the original location }
+ tnode(templist[i]).fileinfo:=tnode(lists.nodelist[i]).fileinfo;
+
+ addstatement(creates,tnode(templist[i]));
+ { make debugging easier and set temp. location to the original location }
+ creates.fileinfo:=tnode(lists.nodelist[i]).fileinfo;
+
+ hp:=ttempcreatenode(templist[i]);
+ do_firstpass(tnode(hp));
+ templist[i]:=hp;
+
+ pnode(lists.locationlist[i])^:=ctemprefnode.create(ttempcreatenode(templist[i]));
+ { make debugging easier and set temp. location to the original location }
+ pnode(lists.locationlist[i])^.fileinfo:=tnode(lists.nodelist[i]).fileinfo;
+
+ do_firstpass(pnode(lists.locationlist[i])^);
+{$ifdef csedebug}
+ printnode(output,statements);
+{$endif csedebug}
+ end
+ { current node reference to another node? }
+ else if lists.equalto[i]<>pointer(-1) then
+ begin
+{$if defined(csedebug) or defined(csestats)}
+ printnode(output,tnode(lists.nodelist[i]));
+ writeln(i,' equals ',ptrint(lists.equalto[i]));
+ printnode(output,tnode(lists.nodelist[ptrint(lists.equalto[i])]));
+{$endif defined(csedebug) or defined(csestats)}
+ templist[i]:=templist[ptrint(lists.equalto[i])];
+ pnode(lists.locationlist[i])^:=ctemprefnode.create(ttempcreatenode(templist[ptrint(lists.equalto[i])]));
+
+ { make debugging easier and set temp. location to the original location }
+ pnode(lists.locationlist[i])^.fileinfo:=tnode(lists.nodelist[i]).fileinfo;
+
+ do_firstpass(pnode(lists.locationlist[i])^);
+ end;
+ end;
+ { clean up unused trees }
+ for i:=0 to lists.nodelist.count-1 do
+ if lists.equalto[i]<>pointer(-1) then
+ tnode(lists.nodelist[i]).free;
+{$ifdef csedebug}
+ writeln('nodes: ',lists.nodelist.count);
+ writeln('==========================================');
+{$endif csedebug}
+ lists.nodelist.free;
+ lists.locationlist.free;
+ lists.equalto.free;
+ lists.refs.free;
+ templist.free;
+
+ if assigned(statements) then
+ begin
+ { call para nodes need a special handling because
+ they can be only children nodes of call nodes
+ so the initialization code is inserted below the
+ call para node
+ }
+ if n.nodetype=callparan then
+ begin
+ addstatement(statements,tcallparanode(n).left);
+ tcallparanode(n).left:=nodes;
+ do_firstpass(tcallparanode(n).left);
+ end
+ else
+ begin
+ addstatement(statements,n);
+ n:=nodes;
+ do_firstpass(n);
+ end;
+{$ifdef csedebug}
+ printnode(output,nodes);
+{$endif csedebug}
+ end;
+ end
+ end;
+ end;
+
+
+ function do_optcse(var rootnode : tnode) : tnode;
+ begin
+ foreachnodestatic(pm_postprocess,rootnode,@searchcsedomain,nil);
+ result:=nil;
+ end;
+
+end.
diff --git a/closures/compiler/optdead.pas b/closures/compiler/optdead.pas
new file mode 100644
index 0000000000..080f7dcc2d
--- /dev/null
+++ b/closures/compiler/optdead.pas
@@ -0,0 +1,424 @@
+{
+ Copyright (c) 2008 by Jonas Maebe
+
+ Optimization information related to dead code removal
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+
+unit optdead;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ globtype,
+ cclasses,
+ symtype,
+ wpobase;
+
+ type
+
+ { twpodeadcodeinfo }
+
+ twpodeadcodeinfo = class(twpodeadcodehandler)
+ private
+ { hashtable of symbols which are live }
+ fsymbols : tfphashlist;
+
+ procedure documentformat(writer: twposectionwriterintf);
+ public
+ constructor create; override;
+ destructor destroy; override;
+
+ class function getwpotype: twpotype; override;
+ class function generatesinfoforwposwitches: twpoptimizerswitches; override;
+ class function performswpoforswitches: twpoptimizerswitches; override;
+ class function sectionname: shortstring; override;
+
+ class procedure checkoptions; override;
+
+ { information collection }
+ procedure storewpofilesection(writer: twposectionwriterintf); override;
+
+ { information providing }
+ procedure loadfromwpofilesection(reader: twposectionreaderintf); override;
+ function symbolinfinalbinary(const s: shortstring): boolean;override;
+
+ end;
+
+ { tdeadcodeinfofromexternallinker }
+
+ twpodeadcodeinfofromexternallinker = class(twpodeadcodeinfo)
+ private
+
+ fsymtypepos,
+ fsymnamepos : longint;
+ fsymfile : text;
+ fsymfilename : tcmdstr;
+ function parselinenm(const line: ansistring): boolean;
+ function parselineobjdump(const line: ansistring): boolean;
+ public
+ class procedure checkoptions; override;
+
+ { information collection }
+ procedure constructfromcompilerstate; override;
+ end;
+
+
+ implementation
+
+ uses
+ cutils,cfileutl,
+ sysutils,
+ globals,systems,fmodule,
+ verbose;
+
+
+ const
+ SYMBOL_SECTION_NAME = 'live_symbols';
+
+ { twpodeadcodeinfo }
+
+ constructor twpodeadcodeinfo.create;
+ begin
+ inherited create;
+ fsymbols:=tfphashlist.create;
+ end;
+
+
+ destructor twpodeadcodeinfo.destroy;
+ begin
+ fsymbols.free;
+ fsymbols:=nil;
+ inherited destroy;
+ end;
+
+
+ class function twpodeadcodeinfo.getwpotype: twpotype;
+ begin
+ result:=wpo_live_symbol_information;
+ end;
+
+
+ class function twpodeadcodeinfo.generatesinfoforwposwitches: twpoptimizerswitches;
+ begin
+ result:=[cs_wpo_symbol_liveness];
+ end;
+
+
+ class function twpodeadcodeinfo.performswpoforswitches: twpoptimizerswitches;
+ begin
+ result:=[cs_wpo_symbol_liveness];
+ end;
+
+
+ class function twpodeadcodeinfo.sectionname: shortstring;
+ begin
+ result:=SYMBOL_SECTION_NAME;
+ end;
+
+
+ class procedure twpodeadcodeinfo.checkoptions;
+ begin
+ { we don't have access to the symbol info if the linking
+ hasn't happend
+ }
+ if (([cs_link_on_target,cs_link_nolink] * init_settings.globalswitches) <> []) then
+ begin
+ cgmessage(wpo_cannot_extract_live_symbol_info_no_link);
+ exit;
+ end;
+
+ { without dead code stripping/smart linking, this doesn't make sense }
+ if not(cs_link_smart in init_settings.globalswitches) then
+ begin
+ cgmessage(wpo_symbol_live_info_needs_smart_linking);
+ exit;
+ end;
+ end;
+
+
+ procedure twpodeadcodeinfo.documentformat(writer: twposectionwriterintf);
+ begin
+ writer.sectionputline('# section format:');
+ writer.sectionputline('# symbol1_that_is_live');
+ writer.sectionputline('# symbol2_that_is_live');
+ writer.sectionputline('# ...');
+ writer.sectionputline('#');
+ end;
+
+
+ procedure twpodeadcodeinfo.storewpofilesection(writer: twposectionwriterintf);
+ var
+ i: longint;
+ begin
+ writer.startsection(SYMBOL_SECTION_NAME);
+ documentformat(writer);
+ for i:=0 to fsymbols.count-1 do
+ writer.sectionputline(fsymbols.nameofindex(i));
+ end;
+
+
+ procedure twpodeadcodeinfo.loadfromwpofilesection(reader: twposectionreaderintf);
+ var
+ symname: shortstring;
+ begin
+ while reader.sectiongetnextline(symname) do
+ fsymbols.add(symname,pointer(1));
+ end;
+
+
+ function twpodeadcodeinfo.symbolinfinalbinary(const s: shortstring): boolean;
+ begin
+ result:=fsymbols.find(s)<>nil;
+ end;
+
+
+ { twpodeadcodeinfofromexternallinker }
+
+{$ifdef relaxed_objdump_parsing}
+const
+ objdumpcheckstr='.text';
+{$else}
+const
+ objdumpcheckstr='F .text';
+{$endif}
+ objdumpsearchstr=' '+objdumpcheckstr;
+
+ class procedure twpodeadcodeinfofromexternallinker.checkoptions;
+ begin
+ inherited checkoptions;
+
+ { we need symbol information }
+ if (cs_link_strip in init_settings.globalswitches) then
+ begin
+ cgmessage(wpo_cannot_extract_live_symbol_info_strip);
+ exit;
+ end;
+ end;
+
+
+ function twpodeadcodeinfofromexternallinker.parselinenm(const line: ansistring): boolean;
+ begin
+ if (length(line) < fsymnamepos) then
+ begin
+ cgmessage1(wpo_error_reading_symbol_file,'nm');
+ close(fsymfile);
+ deletefile(fsymfilename);
+ result:=false;
+ exit;
+ end;
+ if (line[fsymtypepos] in ['T','t']) then
+ fsymbols.add(copy(line,fsymnamepos,length(line)),pointer(1));
+ result:=true;
+ end;
+
+
+ function twpodeadcodeinfofromexternallinker.parselineobjdump(const line: ansistring): boolean;
+ begin
+ { there are a couple of empty lines at the end }
+ if (line='') then
+ begin
+ result:=true;
+ exit;
+ end;
+ if (length(line) < fsymtypepos) then
+ begin
+ cgmessage1(wpo_error_reading_symbol_file,'objdump');
+ close(fsymfile);
+ deletefile(fsymfilename);
+ result:=false;
+ exit;
+ end;
+ if (copy(line,fsymtypepos,length(objdumpcheckstr))=objdumpcheckstr) then
+ fsymbols.add(copy(line,fsymnamepos,length(line)),pointer(1));
+ result:=true;
+ end;
+
+
+ procedure twpodeadcodeinfofromexternallinker.constructfromcompilerstate;
+
+ type
+ tparselineproc = function(const line: ansistring): boolean of object;
+
+ var
+ nmfullname,
+ objdumpfullname,
+ symbolprogfullpath : tcmdstr;
+ line : ansistring;
+ parseline : tparselineproc;
+ exitcode : longint;
+ symbolprogfound : boolean;
+ symbolprogisnm : boolean;
+
+
+ function findutil(const utilname: string; out fullutilname, fullutilpath: tcmdstr): boolean;
+ begin
+ result:=false;
+ fullutilname:=utilsprefix+changefileext(utilname,source_info.exeext);
+ if utilsdirectory<>'' then
+ result:=findfile(fullutilname,utilsdirectory,false,fullutilpath);
+ if not result then
+ result:=findexe(fullutilname,false,fullutilpath);
+ end;
+
+
+ function failiferror(error: boolean): boolean;
+ begin
+ result:=error;
+ if not result then
+ exit;
+ cgmessage1(wpo_error_reading_symbol_file,symbolprogfullpath);
+{$push}{$i-}
+ close(fsymfile);
+{$pop}
+ if fileexists(fsymfilename) then
+ deletefile(fsymfilename);
+ end;
+
+
+ function setnminfo: boolean;
+ begin
+ { expected format:
+ 0000bce0 T FPC_ABSTRACTERROR
+ ...
+ }
+ result:=false;
+ fsymtypepos:=pos(' ',line)+1;
+ fsymnamepos:=fsymtypepos+2;
+ { on Linux/ppc64, there is an extra '.' at the start
+ of public function names
+ }
+ if (target_info.system=system_powerpc64_linux) then
+ inc(fsymnamepos);
+ if failiferror(fsymtypepos<=0) then
+ exit;
+ { make sure there's room for the name }
+ if failiferror(fsymnamepos>length(line)) then
+ exit;
+ { and that we're not in the middle of some other column }
+ if failiferror(pos(' ',copy(line,fsymnamepos,length(line)))>0) then
+ exit;
+ result:=true;
+ end;
+
+
+ function setobjdumpinfo: boolean;
+ begin
+ { expected format:
+ prog: file format elf32-i386
+
+ SYMBOL TABLE:
+ 08048080 l d .text 00000000 .text
+ 00000000 l d .stabstr 00000000 .stabstr
+ 00000000 l df *ABS* 00000000 nest.pp
+ 08048160 l F .text 00000068 SYSTEM_INITSYSCALLINTF
+ ...
+ }
+ result:=false;
+ while (pos(objdumpsearchstr,line)<=0) do
+ begin
+ if failiferror(eof(fsymfile)) then
+ exit;
+ readln(fsymfile,line)
+ end;
+ fsymtypepos:=pos(objdumpsearchstr,line)+1;
+ { find begin of symbol name }
+ fsymnamepos:=(pointer(strrscan(pchar(line),' '))-pointer(@line[1]))+2;
+ { sanity check }
+ if (fsymnamepos <= fsymtypepos+length(objdumpcheckstr)) then
+ exit;
+ result:=true;
+ end;
+
+
+ begin { twpodeadcodeinfofromexternallinker }
+ { gnu-nm (e.g., on solaris) }
+ symbolprogfound:=findutil('gnm',nmfullname,symbolprogfullpath);
+ { regular nm }
+ if not symbolprogfound then
+ symbolprogfound:=findutil('nm',nmfullname,symbolprogfullpath);
+ if not symbolprogfound then
+ begin
+ { try objdump }
+ symbolprogfound:=findutil('objdump',objdumpfullname,symbolprogfullpath);
+ symbolprogfullpath:=symbolprogfullpath+' -t ';
+ symbolprogisnm:=false;
+ end
+ else
+ begin
+ symbolprogfullpath:=symbolprogfullpath+' -p ';
+ symbolprogisnm:=true;
+ end;
+ if not symbolprogfound then
+ begin
+ cgmessage2(wpo_cannot_find_symbol_progs,nmfullname,objdumpfullname);
+ exit;
+ end;
+
+ { upper case to have the least chance of tripping some long file name
+ conversion stuff
+ }
+ fsymfilename:=outputexedir+'FPCWPO.SYM';
+ { -p gives the same kind of output with Solaris nm as
+ with GNU nm, and for GNU nm it simply means "unsorted"
+ }
+ exitcode:=shell(symbolprogfullpath+maybequoted(current_module.exefilename^)+' > '+fsymfilename);
+ if (exitcode<>0) then
+ begin
+ cgmessage2(wpo_error_executing_symbol_prog,symbolprogfullpath,tostr(exitcode));
+ if fileexists(fsymfilename) then
+ deletefile(fsymfilename);
+ exit;
+ end;
+
+ assign(fsymfile,fsymfilename);
+{$push}{$i-}
+ reset(fsymfile);
+{$pop}
+ if failiferror((ioresult<>0) or eof(fsymfile)) then
+ exit;
+ readln(fsymfile, line);
+ if (symbolprogisnm) then
+ begin
+ if not setnminfo then
+ exit;
+ parseline:=@parselinenm
+ end
+ else
+ begin
+ if not setobjdumpinfo then
+ exit;
+ parseline:=@parselineobjdump;
+ end;
+ if not parseline(line) then
+ exit;
+ while not eof(fsymfile) do
+ begin
+ readln(fsymfile,line);
+ if not parseline(line) then
+ exit;
+ end;
+ close(fsymfile);
+ deletefile(fsymfilename);
+ end;
+
+
+end.
+
diff --git a/closures/compiler/optdfa.pas b/closures/compiler/optdfa.pas
new file mode 100644
index 0000000000..28f2f6fd46
--- /dev/null
+++ b/closures/compiler/optdfa.pas
@@ -0,0 +1,616 @@
+{
+ DFA
+
+ Copyright (c) 2007 by Florian Klaempfl
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+
+{ $define DEBUG_DFA}
+{ $define EXTDEBUG_DFA}
+
+{ this unit implements routines to perform dfa }
+unit optdfa;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ node,optutils;
+
+ type
+ TDFABuilder = class
+ protected
+ procedure CreateLifeInfo(node : tnode;map : TIndexedNodeSet);
+ public
+ resultnode : tnode;
+ nodemap : TIndexedNodeSet;
+ { reset all dfa info, this is required before creating dfa info
+ if the tree has been changed without updating dfa }
+ procedure resetdfainfo(node : tnode);
+
+ procedure createdfainfo(node : tnode);
+ destructor destroy;override;
+ end;
+
+ implementation
+
+ uses
+ globtype,globals,
+ verbose,
+ cpuinfo,
+ symconst,symdef,
+ defutil,
+ procinfo,
+ nutils,
+ nbas,nflw,ncon,ninl,ncal,nset,
+ optbase;
+
+
+ (*
+ function initnodes(var n:tnode; arg: pointer) : foreachnoderesult;
+ begin
+ { node worth to add? }
+ if (node_complexity(n)>1) and (tstoreddef(n.resultdef).is_intregable or tstoreddef(n.resultdef).is_fpuregable) then
+ begin
+ plists(arg)^.nodelist.Add(n);
+ plists(arg)^.locationlist.Add(@n);
+ result:=fen_false;
+ end
+ else
+ result:=fen_norecurse_false;
+ end;
+ *)
+
+ {
+ x:=f; read: [f]
+
+ while x do read: []
+
+ a:=b; read: [a,b,d] def: [a] life: read*def=[a]
+ c:=d; read: [a,d] def: [a,c] life: read*def=[a]
+ e:=a; read: [a] def: [a,c,e] life: read*def=[a]
+
+
+ function f(b,d,x : type) : type;
+
+ begin
+ while x do alive: b,d,x
+ begin
+ a:=b; alive: b,d,x
+ c:=d; alive: a,d,x
+ e:=a+c; alive: a,c,x
+ dec(x); alive: c,e,x
+ end;
+ result:=c+e; alive: c,e
+ end; alive: result
+
+ }
+
+ type
+ tdfainfo = record
+ use : PDFASet;
+ def : PDFASet;
+ map : TIndexedNodeSet
+ end;
+ pdfainfo = ^tdfainfo;
+
+ function AddDefUse(var n: tnode; arg: pointer): foreachnoderesult;
+ begin
+ case n.nodetype of
+ loadn:
+ begin
+ pdfainfo(arg)^.map.Add(n);
+ if nf_modify in n.flags then
+ begin
+ DFASetInclude(pdfainfo(arg)^.use^,n.optinfo^.index);
+ DFASetInclude(pdfainfo(arg)^.def^,n.optinfo^.index)
+ end
+ else if nf_write in n.flags then
+ DFASetInclude(pdfainfo(arg)^.def^,n.optinfo^.index)
+ else
+ DFASetInclude(pdfainfo(arg)^.use^,n.optinfo^.index);
+ {
+ write('Use Set: ');
+ PrintDFASet(output,pdfainfo(arg)^.use^);
+ write(' Def Set: ');
+ PrintDFASet(output,pdfainfo(arg)^.def^);
+ writeln;
+ }
+ end;
+ end;
+ result:=fen_false;
+ end;
+
+
+ function ResetProcessing(var n: tnode; arg: pointer): foreachnoderesult;
+ begin
+ exclude(n.flags,nf_processing);
+ result:=fen_false;
+ end;
+
+
+ function ResetDFA(var n: tnode; arg: pointer): foreachnoderesult;
+ begin
+ if assigned(n.optinfo) then
+ begin
+ with n.optinfo^ do
+ begin
+ life:=nil;
+ def:=nil;
+ use:=nil;
+ defsum:=nil;
+ end;
+ end;
+ result:=fen_false;
+ end;
+
+
+ procedure TDFABuilder.CreateLifeInfo(node : tnode;map : TIndexedNodeSet);
+
+ var
+ changed : boolean;
+
+ procedure CreateInfo(node : tnode);
+
+ { update life entry of a node with l, set changed if this changes
+ life info for the node
+ }
+ procedure updatelifeinfo(n : tnode;l : TDFASet);
+ var
+ b : boolean;
+ begin
+ b:=DFASetNotEqual(l,n.optinfo^.life);
+ {
+ if b then
+ begin
+ printnode(output,n);
+ printdfaset(output,l);
+ writeln;
+ printdfaset(output,n.optinfo^.life);
+ writeln;
+ end;
+ }
+{$ifdef DEBUG_DFA}
+ if not(changed) and b then
+ writeln('Another DFA pass caused by: ',nodetype2str[n.nodetype],'(',n.fileinfo.line,',',n.fileinfo.column,')');
+{$endif DEBUG_DFA}
+
+ changed:=changed or b;
+ node.optinfo^.life:=l;
+ end;
+
+ procedure calclife(n : tnode);
+ var
+ l : TDFASet;
+ begin
+ if assigned(n.successor) then
+ begin
+ {
+ write('Successor Life: ');
+ printdfaset(output,n.successor.optinfo^.life);
+ writeln;
+ write('Def.');
+ printdfaset(output,n.optinfo^.def);
+ writeln;
+ }
+ { ensure we can access optinfo }
+ DFASetDiff(l,n.successor.optinfo^.life,n.optinfo^.def);
+ {
+ printdfaset(output,l);
+ writeln;
+ }
+ DFASetIncludeSet(l,n.optinfo^.use);
+ DFASetIncludeSet(l,n.optinfo^.life);
+ end
+ else
+ begin
+ { last node, not exit or raise node and function? }
+ if assigned(resultnode) and
+ not(node.nodetype in [raisen,exitn]) then
+ begin
+ { if yes, result lifes }
+ DFASetDiff(l,resultnode.optinfo^.life,n.optinfo^.def);
+ DFASetIncludeSet(l,n.optinfo^.use);
+ DFASetIncludeSet(l,n.optinfo^.life);
+ end
+ else
+ begin
+ l:=n.optinfo^.use;
+ DFASetIncludeSet(l,n.optinfo^.life);
+ end;
+ end;
+ updatelifeinfo(n,l);
+ end;
+
+ var
+ dfainfo : tdfainfo;
+ l : TDFASet;
+ save: TDFASet;
+ i : longint;
+
+ begin
+ if node=nil then
+ exit;
+
+ { ensure we've already optinfo set }
+ node.allocoptinfo;
+
+ if nf_processing in node.flags then
+ exit;
+ include(node.flags,nf_processing);
+
+ if assigned(node.successor) then
+ CreateInfo(node.successor);
+
+{$ifdef EXTDEBUG_DFA}
+ writeln('Handling: ',nodetype2str[node.nodetype],'(',node.fileinfo.line,',',node.fileinfo.column,')');
+{$endif EXTDEBUG_DFA}
+ { life:=succesorlive-definition+use }
+
+ case node.nodetype of
+ whilerepeatn:
+ begin
+ { analyze the loop condition }
+ if not(assigned(node.optinfo^.def)) and
+ not(assigned(node.optinfo^.use)) then
+ begin
+ dfainfo.use:=@node.optinfo^.use;
+ dfainfo.def:=@node.optinfo^.def;
+ dfainfo.map:=map;
+ foreachnodestatic(pm_postprocess,twhilerepeatnode(node).left,@AddDefUse,@dfainfo);
+ end;
+
+ { NB: this node should typically have empty def set }
+ if assigned(node.successor) then
+ DFASetDiff(l,node.successor.optinfo^.life,node.optinfo^.def)
+ else if assigned(resultnode) then
+ DFASetDiff(l,resultnode.optinfo^.life,node.optinfo^.def)
+ else
+ l:=nil;
+
+ { for repeat..until, node use set in included at the end of loop }
+ if not (lnf_testatbegin in twhilerepeatnode(node).loopflags) then
+ DFASetIncludeSet(l,node.optinfo^.use);
+
+ DFASetIncludeSet(l,node.optinfo^.life);
+
+ save:=node.optinfo^.life;
+ { to process body correctly, we need life info in place (because
+ whilerepeatnode is successor of its body). }
+ node.optinfo^.life:=l;
+
+ { now process the body }
+ CreateInfo(twhilerepeatnode(node).right);
+
+ { restore, to prevent infinite recursion via changed flag }
+ node.optinfo^.life:=save;
+
+ { for while loops, node use set is included at the beginning of loop }
+ l:=twhilerepeatnode(node).right.optinfo^.life;
+ if lnf_testatbegin in twhilerepeatnode(node).loopflags then
+ DFASetIncludeSet(l,node.optinfo^.use);
+
+ UpdateLifeInfo(node,l);
+
+ { ... and a second iteration for fast convergence }
+ CreateInfo(twhilerepeatnode(node).right);
+ end;
+
+ forn:
+ begin
+ {
+ left: loopvar
+ right: from
+ t1: to
+ t2: body
+ }
+ { take care of the sucessor if it's possible that we don't have one execution of the body }
+ if not((tfornode(node).right.nodetype=ordconstn) and (tfornode(node).t1.nodetype=ordconstn)) then
+ calclife(node);
+ node.allocoptinfo;
+ if not(assigned(node.optinfo^.def)) and
+ not(assigned(node.optinfo^.use)) then
+ begin
+ dfainfo.use:=@node.optinfo^.use;
+ dfainfo.def:=@node.optinfo^.def;
+ dfainfo.map:=map;
+ foreachnodestatic(pm_postprocess,tfornode(node).left,@AddDefUse,@dfainfo);
+ foreachnodestatic(pm_postprocess,tfornode(node).right,@AddDefUse,@dfainfo);
+ foreachnodestatic(pm_postprocess,tfornode(node).t1,@AddDefUse,@dfainfo);
+ end;
+ { take care of the sucessor if it's possible that we don't have one execution of the body }
+ if not((tfornode(node).right.nodetype=ordconstn) and (tfornode(node).t1.nodetype=ordconstn)) then
+ calclife(node);
+
+ { create life for the body }
+ CreateInfo(tfornode(node).t2);
+
+ { update for node }
+ { life:=life+use+body }
+ l:=copy(node.optinfo^.life);
+ DFASetIncludeSet(l,tfornode(node).t2.optinfo^.life);
+ { the for loop always updates its control variable }
+ DFASetDiff(l,l,node.optinfo^.def);
+
+ { ... but it could be that left/right use it, so do it after
+ removing def }
+ DFASetIncludeSet(l,node.optinfo^.use);
+
+ UpdateLifeInfo(node,l);
+
+ { ... and a second iteration for fast convergence }
+ CreateInfo(tfornode(node).t2);
+ end;
+
+ temprefn,
+ loadn,
+ typeconvn,
+ assignn:
+ begin
+ if not(assigned(node.optinfo^.def)) and
+ not(assigned(node.optinfo^.use)) then
+ begin
+ dfainfo.use:=@node.optinfo^.use;
+ dfainfo.def:=@node.optinfo^.def;
+ dfainfo.map:=map;
+ foreachnodestatic(pm_postprocess,node,@AddDefUse,@dfainfo);
+ end;
+ calclife(node);
+ end;
+
+ statementn:
+ begin
+ { nested statement }
+ CreateInfo(tstatementnode(node).statement);
+ { inherit info }
+ node.optinfo^.life:=tstatementnode(node).statement.optinfo^.life;
+ end;
+
+ blockn:
+ begin
+ CreateInfo(tblocknode(node).statements);
+ if assigned(tblocknode(node).statements) then
+ node.optinfo^.life:=tblocknode(node).statements.optinfo^.life;
+ end;
+
+ ifn:
+ begin
+ { get information from cond. expression }
+ if not(assigned(node.optinfo^.def)) and
+ not(assigned(node.optinfo^.use)) then
+ begin
+ dfainfo.use:=@node.optinfo^.use;
+ dfainfo.def:=@node.optinfo^.def;
+ dfainfo.map:=map;
+ foreachnodestatic(pm_postprocess,tifnode(node).left,@AddDefUse,@dfainfo);
+ end;
+ { create life info for then and else node }
+ CreateInfo(tifnode(node).right);
+ CreateInfo(tifnode(node).t1);
+
+ { ensure that we don't remove life info }
+ l:=node.optinfo^.life;
+
+ { get life info from then branch }
+ if assigned(tifnode(node).right) then
+ DFASetIncludeSet(l,tifnode(node).right.optinfo^.life);
+ { get life info from else branch }
+ if assigned(tifnode(node).t1) then
+ DFASetIncludeSet(l,tifnode(node).t1.optinfo^.life)
+ else
+ if assigned(node.successor) then
+ DFASetIncludeSet(l,node.successor.optinfo^.life)
+ { last node and function? }
+ else
+ if assigned(resultnode) then
+ DFASetIncludeSet(l,resultnode.optinfo^.life);
+
+ { add use info from the cond. expression }
+ DFASetIncludeSet(l,tifnode(node).optinfo^.use);
+ { finally, update the life info of the node }
+ UpdateLifeInfo(node,l);
+ end;
+
+ casen:
+ begin
+ { get information from "case" expression }
+ if not(assigned(node.optinfo^.def)) and
+ not(assigned(node.optinfo^.use)) then
+ begin
+ dfainfo.use:=@node.optinfo^.use;
+ dfainfo.def:=@node.optinfo^.def;
+ dfainfo.map:=map;
+ foreachnodestatic(pm_postprocess,tcasenode(node).left,@AddDefUse,@dfainfo);
+ end;
+
+ { create life info for block and else nodes }
+ for i:=0 to tcasenode(node).blocks.count-1 do
+ CreateInfo(pcaseblock(tcasenode(node).blocks[i])^.statement);
+
+ CreateInfo(tcasenode(node).elseblock);
+
+ { ensure that we don't remove life info }
+ l:=node.optinfo^.life;
+
+ { get life info from case branches }
+ for i:=0 to tcasenode(node).blocks.count-1 do
+ DFASetIncludeSet(l,pcaseblock(tcasenode(node).blocks[i])^.statement.optinfo^.life);
+
+ { get life info from else branch or the succesor }
+ if assigned(tcasenode(node).elseblock) then
+ DFASetIncludeSet(l,tcasenode(node).elseblock.optinfo^.life)
+ else
+ if assigned(node.successor) then
+ DFASetIncludeSet(l,node.successor.optinfo^.life)
+ { last node and function? }
+ else
+ if assigned(resultnode) then
+ DFASetIncludeSet(l,resultnode.optinfo^.life);
+
+ { add use info from the "case" expression }
+ DFASetIncludeSet(l,tcasenode(node).optinfo^.use);
+
+ { finally, update the life info of the node }
+ UpdateLifeInfo(node,l);
+ end;
+
+ exitn:
+ begin
+ if not(is_void(current_procinfo.procdef.returndef)) and
+ not(current_procinfo.procdef.proctypeoption=potype_constructor) then
+ begin
+ if not(assigned(node.optinfo^.def)) and
+ not(assigned(node.optinfo^.use)) then
+ begin
+ if assigned(texitnode(node).left) then
+ begin
+ node.optinfo^.def:=resultnode.optinfo^.def;
+
+ dfainfo.use:=@node.optinfo^.use;
+ dfainfo.def:=@node.optinfo^.def;
+ dfainfo.map:=map;
+ foreachnodestatic(pm_postprocess,texitnode(node).left,@AddDefUse,@dfainfo);
+ calclife(node);
+ end
+ else
+ begin
+ { get info from faked resultnode }
+ node.optinfo^.use:=resultnode.optinfo^.use;
+ node.optinfo^.life:=node.optinfo^.use;
+ changed:=true;
+ end;
+ end;
+ end;
+ end;
+
+ raisen:
+ begin
+ if not(assigned(node.optinfo^.life)) then
+ begin
+ dfainfo.use:=@node.optinfo^.use;
+ dfainfo.def:=@node.optinfo^.def;
+ dfainfo.map:=map;
+ foreachnodestatic(pm_postprocess,traisenode(node).left,@AddDefUse,@dfainfo);
+ foreachnodestatic(pm_postprocess,traisenode(node).right,@AddDefUse,@dfainfo);
+ foreachnodestatic(pm_postprocess,traisenode(node).third,@AddDefUse,@dfainfo);
+ { update node }
+ l:=node.optinfo^.life;
+ DFASetIncludeSet(l,node.optinfo^.use);
+ UpdateLifeInfo(node,l);
+ printdfainfo(output,node);
+ end;
+ end;
+
+ calln:
+ begin
+ if not(assigned(node.optinfo^.def)) and
+ not(assigned(node.optinfo^.use)) then
+ begin
+ dfainfo.use:=@node.optinfo^.use;
+ dfainfo.def:=@node.optinfo^.def;
+ dfainfo.map:=map;
+ foreachnodestatic(pm_postprocess,node,@AddDefUse,@dfainfo);
+ end;
+ calclife(node);
+ end;
+
+ tempcreaten,
+ tempdeleten,
+ inlinen,
+ nothingn,
+ continuen,
+ goton,
+ breakn,
+ labeln:
+ begin
+ calclife(node);
+ end;
+ else
+ begin
+ writeln(nodetype2str[node.nodetype]);
+ internalerror(2007050502);
+ end;
+ end;
+
+ // exclude(node.flags,nf_processing);
+ end;
+
+ var
+ runs : integer;
+ dfarec : tdfainfo;
+ begin
+ runs:=0;
+ if not(is_void(current_procinfo.procdef.returndef)) and
+ not(current_procinfo.procdef.proctypeoption=potype_constructor) then
+ begin
+ { create a fake node using the result }
+ resultnode:=load_result_node;
+ resultnode.allocoptinfo;
+ dfarec.use:=@resultnode.optinfo^.use;
+ dfarec.def:=@resultnode.optinfo^.def;
+ dfarec.map:=map;
+ AddDefUse(resultnode,@dfarec);
+ resultnode.optinfo^.life:=resultnode.optinfo^.use;
+ end
+ else
+ resultnode:=nil;
+
+ repeat
+ inc(runs);
+ changed:=false;
+ CreateInfo(node);
+ foreachnodestatic(pm_postprocess,node,@ResetProcessing,nil);
+{$ifdef DEBUG_DFA}
+ PrintIndexedNodeSet(output,map);
+ PrintDFAInfo(output,node);
+{$endif DEBUG_DFA}
+ until not(changed);
+{$ifdef DEBUG_DFA}
+ writeln('DFA solver iterations: ',runs);
+{$endif DEBUG_DFA}
+ end;
+
+
+ { reset all dfa info, this is required before creating dfa info
+ if the tree has been changed without updating dfa }
+ procedure TDFABuilder.resetdfainfo(node : tnode);
+ begin
+ foreachnodestatic(pm_postprocess,node,@ResetDFA,nil);
+ end;
+
+
+ procedure TDFABuilder.createdfainfo(node : tnode);
+ begin
+ if not(assigned(nodemap)) then
+ nodemap:=TIndexedNodeSet.Create;
+ { add controll flow information }
+ SetNodeSucessors(node);
+ { now, collect life information }
+ CreateLifeInfo(node,nodemap);
+ end;
+
+
+ destructor TDFABuilder.Destroy;
+ begin
+ Resultnode.free;
+ nodemap.free;
+ inherited destroy;
+ end;
+
+end.
diff --git a/closures/compiler/options.pas b/closures/compiler/options.pas
new file mode 100644
index 0000000000..119ac99cb0
--- /dev/null
+++ b/closures/compiler/options.pas
@@ -0,0 +1,2958 @@
+{
+ Copyright (c) 1998-2008 by Florian Klaempfl and Peter Vreman
+
+ Reads command line options and config files
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit options;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ CClasses,cfileutl,
+ globtype,globals,verbose,systems,cpuinfo, comprsrc;
+
+Type
+ TOption=class
+ FirstPass,
+ ParaLogo,
+ NoPressEnter,
+ LogoWritten,
+ FPUSetExplicitly,
+ CPUSetExplicitly,
+ OptCPUSetExplicitly: boolean;
+ FileLevel : longint;
+ QuickInfo : string;
+ ParaIncludePath,
+ ParaUnitPath,
+ ParaObjectPath,
+ ParaLibraryPath,
+ ParaFrameworkPath : TSearchPathList;
+ ParaAlignment : TAlignmentInfo;
+ Constructor Create;
+ Destructor Destroy;override;
+ procedure WriteLogo;
+ procedure WriteInfo;
+ procedure WriteHelpPages;
+ procedure WriteQuickInfo;
+ procedure IllegalPara(const opt:TCmdStr);
+ procedure UnsupportedPara(const opt:TCmdStr);
+ procedure IgnoredPara(const opt:TCmdStr);
+ function Unsetbool(var Opts:TCmdStr; Pos: Longint):boolean;
+ procedure interpret_option(const opt :TCmdStr;ispara:boolean);
+ procedure Interpret_envvar(const envname : TCmdStr);
+ procedure Interpret_file(const filename : TPathStr);
+ procedure Read_Parameters;
+ procedure parsecmd(cmd:TCmdStr);
+ procedure TargetOptions(def:boolean);
+ procedure CheckOptionsCompatibility;
+ procedure ForceStaticLinking;
+ end;
+
+ TOptionClass=class of toption;
+
+var
+ coption : TOptionClass;
+
+procedure read_arguments(cmd:TCmdStr);
+
+
+implementation
+
+uses
+ widestr,
+ {$if FPC_FULLVERSION<20700}ccharset{$else}charset{$endif},
+ SysUtils,
+ version,
+ cutils,cmsgs,
+ comphook,
+ symtable,scanner,rabase,
+ wpobase,
+ symconst,
+ i_bsd;
+
+const
+ page_size = 24;
+
+var
+ option : toption;
+ read_configfile, { read config file, set when a cfgfile is found }
+ disable_configfile : boolean;
+ fpcdir,
+ ppccfg,
+ param_file : string; { file to compile specified on the commandline }
+
+
+{****************************************************************************
+ Options not supported on all platforms
+****************************************************************************}
+
+const
+ { pointer checking (requires special code in FPC_CHECKPOINTER,
+ and can never work for libc-based targets or any other program
+ linking to an external library)
+ }
+ supported_targets_gc = [system_i386_linux,system_powerpc_linux]
+ + [system_i386_win32]
+ + [system_i386_GO32V2]
+ + [system_i386_os2]
+ + [system_i386_beos,system_i386_haiku]
+ + [system_powerpc_morphos];
+
+ { gprof (requires implementation of g_profilecode in the code generator) }
+ supported_targets_pg = [system_i386_linux,system_x86_64_linux]
+ + [system_i386_win32]
+ + [system_powerpc_darwin,system_x86_64_darwin]
+ + [system_i386_GO32V2]
+ + [system_i386_freebsd]
+ + [system_i386_netbsd]
+ + [system_i386_wdosx];
+
+ suppported_targets_x_smallr = systems_linux + systems_solaris
+ + [system_i386_haiku]
+ + [system_i386_beos];
+
+{****************************************************************************
+ Defines
+****************************************************************************}
+
+procedure set_default_link_type;
+begin
+ undef_system_macro('FPC_LINK_SMART');
+ def_system_macro('FPC_LINK_STATIC');
+ undef_system_macro('FPC_LINK_DYNAMIC');
+ init_settings.globalswitches:=init_settings.globalswitches+[cs_link_static];
+ init_settings.globalswitches:=init_settings.globalswitches-[cs_link_shared,cs_link_smart];
+end;
+
+{****************************************************************************
+ Toption
+****************************************************************************}
+
+procedure StopOptions(err:longint);
+begin
+ if assigned(Option) then
+ begin
+ Option.free;
+ Option:=nil;
+ end;
+ raise ECompilerAbortSilent.Create;
+end;
+
+
+procedure Toption.WriteLogo;
+var
+ p : pchar;
+begin
+ if not LogoWritten then
+ begin
+ p:=MessagePchar(option_logo);
+ while assigned(p) do
+ Comment(V_Normal,GetMsgLine(p));
+ LogoWritten:= true;
+ end;
+end;
+
+
+procedure Toption.WriteInfo;
+var
+ p : pchar;
+ hs,hs1,s : TCmdStr;
+ target : tsystem;
+ cpu : tcputype;
+ fpu : tfputype;
+ opt : toptimizerswitch;
+ wpopt: twpoptimizerswitch;
+ abi : tabi;
+{$if defined(arm) or defined(avr)}
+ controllertype : tcontrollertype;
+{$endif defined(arm) or defined(avr)}
+begin
+ p:=MessagePchar(option_info);
+ while assigned(p) do
+ begin
+ s:=GetMsgLine(p);
+ { list OS Targets }
+ if pos('$OSTARGETS',s)>0 then
+ begin
+ for target:=low(tsystem) to high(tsystem) do
+ if assigned(targetinfos[target]) then
+ begin
+ hs:=s;
+ hs1:=targetinfos[target]^.name;
+ if tf_under_development in targetinfos[target]^.flags then
+ hs1:=hs1+' (under development)';
+ Replace(hs,'$OSTARGETS',hs1);
+ Comment(V_Normal,hs);
+ end;
+ end
+ else if pos('$INSTRUCTIONSETS',s)>0 then
+ begin
+ for cpu:=low(tcputype) to high(tcputype) do
+ begin
+ hs:=s;
+ hs1:=cputypestr[cpu];
+ if hs1<>'' then
+ begin
+ Replace(hs,'$INSTRUCTIONSETS',hs1);
+ Comment(V_Normal,hs);
+ end;
+ end;
+ end
+ else if pos('$FPUINSTRUCTIONSETS',s)>0 then
+ begin
+ for fpu:=low(tfputype) to high(tfputype) do
+ begin
+ hs:=s;
+ hs1:=fputypestr[fpu];
+ if hs1<>'' then
+ begin
+ Replace(hs,'$FPUINSTRUCTIONSETS',hs1);
+ Comment(V_Normal,hs);
+ end;
+ end;
+ end
+ else if pos('$ABITARGETS',s)>0 then
+ begin
+ for abi:=low(abi) to high(abi) do
+ begin
+ hs:=s;
+ hs1:=abi2str[abi];
+ if hs1<>'' then
+ begin
+ Replace(hs,'$ABITARGETS',hs1);
+ Comment(V_Normal,hs);
+ end;
+ end;
+ end
+ else if pos('$OPTIMIZATIONS',s)>0 then
+ begin
+ for opt:=low(toptimizerswitch) to high(toptimizerswitch) do
+ begin
+ if opt in supported_optimizerswitches then
+ begin
+ hs:=s;
+ hs1:=OptimizerSwitchStr[opt];
+ if hs1<>'' then
+ begin
+ Replace(hs,'$OPTIMIZATIONS',hs1);
+ Comment(V_Normal,hs);
+ end;
+ end;
+ end;
+ end
+ else if pos('$WPOPTIMIZATIONS',s)>0 then
+ begin
+ for wpopt:=low(twpoptimizerswitch) to high(twpoptimizerswitch) do
+ begin
+{ currently all whole program optimizations are platform-independent
+ if opt in supported_wpoptimizerswitches then
+}
+ begin
+ hs:=s;
+ hs1:=WPOptimizerSwitchStr[wpopt];
+ if hs1<>'' then
+ begin
+ Replace(hs,'$WPOPTIMIZATIONS',hs1);
+ Comment(V_Normal,hs);
+ end;
+ end;
+ end
+ end
+ else if pos('$CONTROLLERTYPES',s)>0 then
+ begin
+{$if defined(arm) or defined(avr)}
+ for controllertype:=low(tcontrollertype) to high(tcontrollertype) do
+ begin
+{ currently all whole program optimizations are platform-independent
+ if opt in supported_wpoptimizerswitches then
+}
+ begin
+ hs:=s;
+ hs1:=embedded_controllers[controllertype].ControllerTypeStr;
+ if hs1<>'' then
+ begin
+ Replace(hs,'$CONTROLLERTYPES',hs1);
+ Comment(V_Normal,hs);
+ end;
+ end;
+ end
+{$else defined(arm) or defined(avr)}
+{$endif defined(arm) or defined(avr)}
+ end
+ else
+ Comment(V_Normal,s);
+ end;
+ StopOptions(0);
+end;
+
+
+procedure Toption.WriteHelpPages;
+
+ function PadEnd(s:string;i:longint):string;
+ begin
+ while (length(s)<i) do
+ s:=s+' ';
+ PadEnd:=s;
+ end;
+
+var
+ lastident,
+ j,outline,
+ ident,
+ lines : longint;
+ show : boolean;
+ opt : string[32];
+ input,
+ s : string;
+ p : pchar;
+begin
+ WriteLogo;
+ Lines:=4;
+ Message1(option_usage,FixFileName(system.paramstr(0)));
+ lastident:=0;
+ p:=MessagePChar(option_help_pages);
+ while assigned(p) do
+ begin
+ { get a line and reset }
+ s:=GetMsgLine(p);
+ ident:=0;
+ show:=false;
+ { parse options }
+ case s[1] of
+{$ifdef UNITALIASES}
+ 'a',
+{$endif}
+{$ifdef EXTDEBUG}
+ 'e',
+{$endif EXTDEBUG}
+{$ifdef i386}
+ '3',
+{$endif}
+{$ifdef x86_64}
+ '4',
+{$endif}
+{$ifdef m68k}
+ '6',
+{$endif}
+{$ifdef arm}
+ 'A',
+{$endif}
+{$ifdef powerpc}
+ 'P',
+{$endif}
+{$ifdef powerpc64}
+ 'p',
+{$endif}
+{$ifdef sparc}
+ 'S',
+{$endif}
+{$ifdef vis}
+ 'I',
+{$endif}
+{$ifdef avr}
+ 'V',
+{$endif}
+ '*' : show:=true;
+ end;
+ if show then
+ begin
+ case s[2] of
+ 'g',
+{$ifdef Unix}
+ 'L',
+{$endif}
+{$ifdef os2}
+ 'O',
+{$endif}
+ '*' : show:=true;
+ else
+ show:=false;
+ end;
+ end;
+ { now we may show the message or not }
+ if show then
+ begin
+ case s[3] of
+ '0' : begin
+ ident:=0;
+ outline:=0;
+ end;
+ '1' : begin
+ ident:=2;
+ outline:=7;
+ end;
+ '2' : begin
+ ident:=6;
+ outline:=11;
+ end;
+ '3' : begin
+ ident:=9;
+ outline:=11;
+ end;
+ end;
+ j:=pos('_',s);
+ opt:=Copy(s,4,j-4);
+ if opt='*' then
+ opt:=''
+ else
+ if opt=' ' then
+ opt:=PadEnd(opt,outline)
+ else
+ opt:=PadEnd('-'+opt,outline);
+ if (ident=0) and (lastident<>0) then
+ begin
+ Comment(V_Normal,'');
+ inc(Lines);
+ end;
+ { page full ? }
+ if (lines >= page_size - 1) then
+ begin
+ if not NoPressEnter then
+ begin
+ Message(option_help_press_enter);
+ readln(input);
+ if upper(input)='Q' then
+ StopOptions(0);
+ end;
+ lines:=0;
+ end;
+ Comment(V_Normal,PadEnd('',ident)+opt+Copy(s,j+1,255));
+ LastIdent:=Ident;
+ inc(Lines);
+ end;
+ end;
+ StopOptions(0);
+end;
+
+
+procedure Toption.IllegalPara(const opt:TCmdStr);
+begin
+ Message1(option_illegal_para,opt);
+ Message(option_help_pages_para);
+ StopOptions(1);
+end;
+
+
+procedure toption.UnsupportedPara(const opt: TCmdStr);
+begin
+ Message1(option_unsupported_target,opt);
+ StopOptions(1);
+end;
+
+
+procedure toption.IgnoredPara(const opt: TCmdStr);
+begin
+ Message1(option_ignored_target,opt);
+end;
+
+
+procedure toption.ForceStaticLinking;
+begin
+ def_system_macro('FPC_LINK_STATIC');
+ undef_system_macro('FPC_LINK_SMART');
+ undef_system_macro('FPC_LINK_DYNAMIC');
+ include(init_settings.globalswitches,cs_link_static);
+ exclude(init_settings.globalswitches,cs_link_smart);
+ exclude(init_settings.globalswitches,cs_link_shared);
+ LinkTypeSetExplicitly:=true;
+end;
+
+
+function Toption.Unsetbool(var Opts:TCmdStr; Pos: Longint):boolean;
+{ checks if the character after pos in Opts is a + or a - and returns resp.
+ false or true. If it is another character (or none), it also returns false }
+begin
+ UnsetBool := false;
+ if Length(Opts)>Pos then
+ begin
+ inc(Pos);
+ UnsetBool := Opts[Pos] = '-';
+ if Opts[Pos] in ['-','+']then
+ delete(Opts,Pos,1);
+ end;
+end;
+
+
+procedure TOption.interpret_option(const opt:TCmdStr;ispara:boolean);
+var
+ code : integer;
+ c : char;
+ more : TCmdStr;
+ major,minor : longint;
+ error : integer;
+ j,l : longint;
+ d,s : TCmdStr;
+ unicodemapping : punicodemap;
+begin
+ if opt='' then
+ exit;
+
+ { only parse define,undef,target,verbosity,link etc options the firsttime }
+ if firstpass and
+ not(
+ (opt[1]='-') and
+ (
+ ((length(opt)>1) and (opt[2] in ['i','d','v','T','u','n','X','l'])) or
+ ((length(opt)>3) and (opt[2]='F') and (opt[3]='e'))
+ )
+ ) then
+ exit;
+
+ Message1(option_handling_option,opt);
+ case opt[1] of
+ '-' :
+ begin
+ more:=Copy(opt,3,2147483647);
+ if firstpass then
+ Message1(option_interpreting_firstpass_option,opt)
+ else
+ Message1(option_interpreting_option,opt);
+ case opt[2] of
+ '?' :
+ WriteHelpPages;
+
+ 'a' :
+ begin
+ include(init_settings.globalswitches,cs_asm_leave);
+ j:=1;
+ while j<=length(more) do
+ begin
+ case more[j] of
+ 'l' :
+ include(init_settings.globalswitches,cs_asm_source);
+ 'r' :
+ include(init_settings.globalswitches,cs_asm_regalloc);
+ 't' :
+ include(init_settings.globalswitches,cs_asm_tempalloc);
+ 'n' :
+ include(init_settings.globalswitches,cs_asm_nodes);
+ 'p' :
+ begin
+ exclude(init_settings.globalswitches,cs_asm_leave);
+ if UnsetBool(More, 0) then
+ exclude(init_settings.globalswitches,cs_asm_pipe)
+ else
+ include(init_settings.globalswitches,cs_asm_pipe);
+ end;
+ '-' :
+ init_settings.globalswitches:=init_settings.globalswitches -
+ [cs_asm_leave, cs_asm_source,cs_asm_regalloc, cs_asm_tempalloc,
+ cs_asm_nodes, cs_asm_pipe];
+ else
+ IllegalPara(opt);
+ end;
+ inc(j);
+ end;
+ end;
+
+ 'A' :
+ begin
+ paratargetasm:=find_asm_by_string(More);
+ if paratargetasm=as_none then
+ IllegalPara(opt);
+ end;
+
+ 'b' :
+ begin
+ // Message1(option_obsolete_switch,'-b');
+ if UnsetBool(More,0) then
+ begin
+ init_settings.moduleswitches:=init_settings.moduleswitches-[cs_browser];
+ init_settings.moduleswitches:=init_settings.moduleswitches-[cs_local_browser];
+ end
+ else
+ begin
+ init_settings.moduleswitches:=init_settings.moduleswitches+[cs_browser];
+ end;
+ if More<>'' then
+ if (More='l') or (More='l+') then
+ init_settings.moduleswitches:=init_settings.moduleswitches+[cs_local_browser]
+ else if More='l-' then
+ init_settings.moduleswitches:=init_settings.moduleswitches-[cs_local_browser]
+ else
+ IllegalPara(opt);
+ end;
+
+ 'B' :
+ do_build:=not UnSetBool(more,0);
+
+ 'C' :
+ begin
+ j:=1;
+ while j<=length(more) do
+ begin
+ case more[j] of
+ '3' :
+ If UnsetBool(More, j) then
+ exclude(init_settings.localswitches,cs_ieee_errors)
+ Else
+ include(init_settings.localswitches,cs_ieee_errors);
+ 'a' :
+ begin
+ s:=upper(copy(more,j+1,length(more)-j));
+ if not(SetAbiType(s,target_info.abi)) then
+ IllegalPara(opt);
+ break;
+ end;
+
+ 'b' :
+ begin
+ if UnsetBool(More, j) then
+ target_info.endian:=endian_little
+ else
+ target_info.endian:=endian_big;
+ end;
+
+ 'c' :
+ begin
+ if not SetAktProcCall(upper(copy(more,j+1,length(more)-j)),init_settings.defproccall) then
+ IllegalPara(opt);
+ break;
+ end;
+{$ifdef cpufpemu}
+ 'e' :
+ begin
+ If UnsetBool(More, j) then
+ exclude(init_settings.moduleswitches,cs_fp_emulation)
+ Else
+ include(init_settings.moduleswitches,cs_fp_emulation);
+ end;
+{$endif cpufpemu}
+ 'f' :
+ begin
+ s:=upper(copy(more,j+1,length(more)-j));
+ if not(SetFpuType(s,init_settings.fputype)) then
+ IllegalPara(opt);
+ FPUSetExplicitly:=True;
+ break;
+ end;
+ 'F' :
+ begin
+ if not SetMinFPConstPrec(copy(more,j+1,length(more)-j),init_settings.minfpconstprec) then
+ IllegalPara(opt);
+ break;
+ end;
+ 'g' :
+ begin
+ if tf_no_pic_supported in target_info.flags then
+ begin
+ { consume a possible '-' coming after it }
+ UnsetBool(More, j);
+ message(scan_w_pic_ignored);
+ end
+ else if UnsetBool(More, j) then
+ exclude(init_settings.moduleswitches,cs_create_pic)
+ else
+ include(init_settings.moduleswitches,cs_create_pic);
+ end;
+ 'h' :
+ begin
+ val(copy(more,j+1,length(more)-j),heapsize,code);
+ if (code<>0) or (heapsize<1024) then
+ IllegalPara(opt);
+ break;
+ end;
+ 'i' :
+ If UnsetBool(More, j) then
+ exclude(init_settings.localswitches,cs_check_io)
+ else
+ include(init_settings.localswitches,cs_check_io);
+ 'n' :
+ If UnsetBool(More, j) then
+ exclude(init_settings.globalswitches,cs_link_nolink)
+ Else
+ include(init_settings.globalswitches,cs_link_nolink);
+ 'o' :
+ If UnsetBool(More, j) then
+ exclude(init_settings.localswitches,cs_check_overflow)
+ Else
+ include(init_settings.localswitches,cs_check_overflow);
+ 'O' :
+ If UnsetBool(More, j) then
+ exclude(init_settings.localswitches,cs_check_ordinal_size)
+ Else
+ include(init_settings.localswitches,cs_check_ordinal_size);
+ 'p' :
+ begin
+ s:=upper(copy(more,j+1,length(more)-j));
+ if not(Setcputype(s,init_settings.cputype)) then
+ IllegalPara(opt);
+ CPUSetExplicitly:=true;
+ break;
+ end;
+ 'P':
+ begin
+ delete(more,1,1);
+ if upper(copy(more,1,pos('=',more)-1))='PACKSET' then
+ begin
+ delete(more,1,pos('=',more));
+ if more='0' then
+ init_settings.setalloc:=0
+ else if (more='1') or (more='DEFAULT') or (more='NORMAL') then
+ init_settings.setalloc:=1
+ else if more='2' then
+ init_settings.setalloc:=2
+ else if more='4' then
+ init_settings.setalloc:=4
+ else if more='8' then
+ init_settings.setalloc:=8
+ else
+ IllegalPara(opt);
+ end
+ else
+ IllegalPara(opt);
+ end;
+ 'r' :
+ If UnsetBool(More, j) then
+ exclude(init_settings.localswitches,cs_check_range)
+ Else
+ include(init_settings.localswitches,cs_check_range);
+ 'R' :
+ If UnsetBool(More, j) then
+ begin
+ exclude(init_settings.localswitches,cs_check_range);
+ exclude(init_settings.localswitches,cs_check_object);
+ end
+ Else
+ begin
+ include(init_settings.localswitches,cs_check_range);
+ include(init_settings.localswitches,cs_check_object);
+ end;
+ 's' :
+ begin
+ val(copy(more,j+1,length(more)-j),stacksize,code);
+ if (code<>0) or (stacksize>=67107840) or (stacksize<1024) then
+ IllegalPara(opt);
+ break;
+ end;
+ 't' :
+ If UnsetBool(More, j) then
+ exclude(init_settings.localswitches,cs_check_stack)
+ Else
+ include(init_settings.localswitches,cs_check_stack);
+ 'D' :
+ If UnsetBool(More, j) then
+ exclude(init_settings.moduleswitches,cs_create_dynamic)
+ Else
+ include(init_settings.moduleswitches,cs_create_dynamic);
+ 'X' :
+ If UnsetBool(More, j) then
+ exclude(init_settings.moduleswitches,cs_create_smart)
+ Else
+ include(init_settings.moduleswitches,cs_create_smart);
+ else
+ IllegalPara(opt);
+ end;
+ inc(j);
+ end;
+ end;
+
+ 'd' :
+ if more <> '' then
+ begin
+ l:=Pos(':=',more);
+ if l>0 then
+ set_system_compvar(Copy(more,1,l-1),Copy(more,l+2,255))
+ else
+ def_system_macro(more);
+ end;
+ 'D' :
+ begin
+ include(init_settings.globalswitches,cs_link_deffile);
+ j:=1;
+ while j<=length(more) do
+ begin
+ case more[j] of
+ 'd' :
+ begin
+ description:=Copy(more,j+1,255);
+ break;
+ end;
+ 'v' :
+ begin
+ dllversion:=Copy(more,j+1,255);
+ l:=pos('.',dllversion);
+ dllminor:=0;
+ error:=0;
+ if l>0 then
+ begin
+ val(copy(dllversion,l+1,255),minor,error);
+ if (error=0) and
+ (minor>=0) and (minor<=$ffff) then
+ dllminor:=minor
+ else
+ if error=0 then
+ error:=1;
+ end;
+ if l=0 then
+ l:=256;
+ dllmajor:=1;
+ if error=0 then
+ val(copy(dllversion,1,l-1),major,error);
+ if (error=0) and (major>=0) and (major<=$ffff) then
+ dllmajor:=major
+ else
+ if error=0 then
+ error:=1;
+ if error<>0 then
+ Message1(scan_w_wrong_version_ignored,dllversion);
+ break;
+ end;
+ 'w' :
+ usewindowapi:=true;
+ '-' :
+ begin
+ exclude(init_settings.globalswitches,cs_link_deffile);
+ usewindowapi:=false;
+ end;
+ else
+ IllegalPara(opt);
+ end;
+ inc(j);
+ end;
+ end;
+
+ 'e' :
+ exepath:=FixPath(More,true);
+
+ 'E' :
+ begin
+ if UnsetBool(More, 0) then
+ exclude(init_settings.globalswitches,cs_link_nolink)
+ else
+ include(init_settings.globalswitches,cs_link_nolink);
+ end;
+
+ 'f' :
+ begin
+ if more='PIC' then
+ begin
+ if tf_no_pic_supported in target_info.flags then
+ message(scan_w_pic_ignored)
+ else
+ include(init_settings.moduleswitches,cs_create_pic)
+ end
+ else
+ IllegalPara(opt);
+ end;
+
+ 'F' :
+ begin
+ if more='' then
+ IllegalPara(opt);
+ c:=more[1];
+ Delete(more,1,1);
+ DefaultReplacements(More);
+ case c of
+ 'a' :
+ autoloadunits:=more;
+ 'c' :
+ begin
+ if (upper(more)='UTF8') or (upper(more)='UTF-8') then
+ init_settings.sourcecodepage:=CP_UTF8
+ else if not(cpavailable(more)) then
+ Message1(option_code_page_not_available,more)
+ else
+ init_settings.sourcecodepage:=codepagebyname(more);
+ include(init_settings.moduleswitches,cs_explicit_codepage);
+ end;
+ 'C' :
+ RCCompiler := More;
+ 'd' :
+ if UnsetBool(more, 0) then
+ init_settings.disabledircache:=false
+ else
+ init_settings.disabledircache:=true;
+ 'D' :
+ utilsdirectory:=FixPath(More,true);
+ 'e' :
+ SetRedirectFile(More);
+ 'E' :
+ OutputExeDir:=FixPath(More,true);
+ 'f' :
+ if (target_info.system in systems_darwin) then
+ if ispara then
+ ParaFrameworkPath.AddPath(More,false)
+ else
+ frameworksearchpath.AddPath(More,true)
+ else
+ IllegalPara(opt);
+ 'i' :
+ begin
+ if ispara then
+ ParaIncludePath.AddPath(More,false)
+ else
+ includesearchpath.AddPath(More,true);
+ end;
+ 'm' :
+ begin
+ s:=ExtractFileDir(more);
+ if TryStrToInt(ExtractFileName(more),j) then
+ begin
+ unicodemapping:=loadunicodemapping(More,More+'.txt',j);
+ if assigned(unicodemapping) then
+ registermapping(unicodemapping)
+ else
+ IllegalPara(opt);
+ end
+ else
+ IllegalPara(opt);
+ end;
+ 'g' :
+ Message2(option_obsolete_switch_use_new,'-Fg','-Fl');
+ 'l' :
+ begin
+ if ispara then
+ ParaLibraryPath.AddPath(sysrootpath,More,false)
+ else
+ LibrarySearchPath.AddPath(sysrootpath,More,true);
+ end;
+ 'L' :
+ begin
+ if More<>'' then
+ ParaDynamicLinker:=More
+ else
+ IllegalPara(opt);
+ end;
+ 'o' :
+ begin
+ if ispara then
+ ParaObjectPath.AddPath(More,false)
+ else
+ ObjectSearchPath.AddPath(More,true);
+ end;
+ 'r' :
+ Msgfilename:=More;
+ 'R' :
+ ResCompiler := More;
+ 'u' :
+ begin
+ if ispara then
+ ParaUnitPath.AddPath(More,false)
+ else
+ unitsearchpath.AddPath(More,true);
+ end;
+ 'U' :
+ OutputUnitDir:=FixPath(More,true);
+ 'W',
+ 'w':
+ begin
+ if More<>'' then
+ begin
+ DefaultReplacements(More);
+ D:=ExtractFilePath(More);
+ if (D<>'') then
+ D:=FixPath(D,True);
+ D:=D+ExtractFileName(More);
+ if (c='W') then
+ WpoFeedbackOutput:=D
+ else
+ WpoFeedbackInput:=D;
+ end
+ else
+ IllegalPara(opt);
+ end;
+ else
+ IllegalPara(opt);
+ end;
+ end;
+
+ 'g' :
+ begin
+ if UnsetBool(More, 0) then
+ begin
+ exclude(init_settings.moduleswitches,cs_debuginfo);
+ exclude(init_settings.globalswitches,cs_use_heaptrc);
+ exclude(init_settings.globalswitches,cs_use_lineinfo);
+ exclude(init_settings.localswitches,cs_checkpointer);
+ localvartrashing := -1;
+ end
+ else
+ begin
+ include(init_settings.moduleswitches,cs_debuginfo);
+ if paratargetdbg=dbg_none then
+ paratargetdbg:=target_info.dbg;
+ end;
+ if not RelocSectionSetExplicitly then
+ RelocSection:=false;
+ j:=1;
+ while j<=length(more) do
+ begin
+ case more[j] of
+ 'c' :
+ begin
+ if UnsetBool(More, j) then
+ exclude(init_settings.localswitches,cs_checkpointer)
+ else if (target_info.system in supported_targets_gc) then
+ include(init_settings.localswitches,cs_checkpointer)
+ else
+ UnsupportedPara('-gc');
+ end;
+ 'h' :
+ begin
+ if UnsetBool(More, j) then
+ exclude(init_settings.globalswitches,cs_use_heaptrc)
+ else
+ include(init_settings.globalswitches,cs_use_heaptrc);
+ end;
+ 'l' :
+ begin
+ if UnsetBool(More, j) then
+ exclude(init_settings.globalswitches,cs_use_lineinfo)
+ else
+ include(init_settings.globalswitches,cs_use_lineinfo);
+ end;
+ 'o' :
+ begin
+ if not UpdateDebugStr(copy(more,j+1,length(more)),init_settings.debugswitches) then
+ IllegalPara(opt);
+ break;
+ end;
+ 'p' :
+ begin
+ if UnsetBool(More, j) then
+ exclude(init_settings.globalswitches,cs_stabs_preservecase)
+ else
+ include(init_settings.globalswitches,cs_stabs_preservecase);
+ end;
+ 's' :
+ begin
+ paratargetdbg:=dbg_stabs;
+ end;
+ 't' :
+ begin
+ if UnsetBool(More, j) then
+ localvartrashing := -1
+ else
+ localvartrashing := (localvartrashing + 1) mod nroftrashvalues;
+ end;
+ 'v' :
+ begin
+ if UnsetBool(More, j) then
+ exclude(init_settings.globalswitches,cs_gdb_valgrind)
+ else
+ include(init_settings.globalswitches,cs_gdb_valgrind);
+ end;
+ 'w' :
+ begin
+ if (j<length(more)) and (more[j+1] in ['2','3','4']) then
+ begin
+ case more[j+1] of
+ '2': paratargetdbg:=dbg_dwarf2;
+ '3': paratargetdbg:=dbg_dwarf3;
+ '4': paratargetdbg:=dbg_dwarf4;
+ end;
+ inc(j);
+ end
+ else
+ paratargetdbg:=dbg_dwarf2;
+ end;
+ else
+ IllegalPara(opt);
+ end;
+ inc(j);
+ end;
+ end;
+
+ 'h' :
+ begin
+ NoPressEnter:=true;
+ WriteHelpPages;
+ end;
+
+ 'i' :
+ begin
+ if More='' then
+ WriteInfo
+ else
+ QuickInfo:=QuickInfo+More;
+ end;
+
+ 'I' :
+ begin
+ if ispara then
+ ParaIncludePath.AddPath(More,false)
+ else
+ includesearchpath.AddPath(More,false);
+ end;
+
+ 'k' :
+ begin
+ if more<>'' then
+ ParaLinkOptions:=ParaLinkOptions+' '+More
+ else
+ IllegalPara(opt);
+ end;
+
+ 'l' :
+ ParaLogo:=not UnSetBool(more,0);
+
+ 'm' :
+ parapreprocess:=not UnSetBool(more,0);
+
+ 'M' :
+ begin
+ more:=Upper(more);
+ if not SetCompileMode(more, true) then
+ if not SetCompileModeSwitch(more, true) then
+ IllegalPara(opt);
+ end;
+
+ 'n' :
+ begin
+ if More='' then
+ disable_configfile:=true
+ else
+ IllegalPara(opt);
+ end;
+
+ 'o' :
+ begin
+ if More<>'' then
+ begin
+ DefaultReplacements(More);
+ D:=ExtractFilePath(More);
+ if (D<>'') then
+ OutputExeDir:=FixPath(D,True);
+ OutputFileName:=ExtractFileName(More);
+ end
+ else
+ IllegalPara(opt);
+ end;
+
+ 'O' :
+ begin
+ j:=1;
+ while j<=length(more) do
+ begin
+ case more[j] of
+ '1' :
+ init_settings.optimizerswitches:=init_settings.optimizerswitches+level1optimizerswitches;
+ '2' :
+ init_settings.optimizerswitches:=init_settings.optimizerswitches+level2optimizerswitches;
+ '3' :
+ init_settings.optimizerswitches:=init_settings.optimizerswitches+level3optimizerswitches;
+ 'a' :
+ begin
+ if not(UpdateAlignmentStr(Copy(Opt,j+3,255),ParaAlignment)) then
+ IllegalPara(opt);
+ break;
+ end;
+ 's' :
+ include(init_settings.optimizerswitches,cs_opt_size);
+ 'p' :
+ begin
+ if not Setcputype(copy(more,j+1,length(more)),init_settings.optimizecputype) then
+ begin
+ OptCPUSetExplicitly:=true;
+ { Give warning for old i386 switches }
+ if (Length(More)-j=1) and
+ (More[j+1]>='1') and (More[j+1]<='5')then
+ Message2(option_obsolete_switch_use_new,'-Op<nr>','-Op<name>')
+ else
+ IllegalPara(opt);
+ end;
+ break;
+ end;
+ 'o' :
+ begin
+ if not UpdateOptimizerStr(copy(more,j+1,length(more)),init_settings.optimizerswitches) then
+ IllegalPara(opt);
+ break;
+ end;
+ '-' :
+ begin
+ init_settings.optimizerswitches:=[];
+ FillChar(ParaAlignment,sizeof(ParaAlignment),0);
+ end;
+ { Obsolete switches }
+ 'g' :
+ Message2(option_obsolete_switch_use_new,'-Og','-Os');
+ 'G' :
+ Message1(option_obsolete_switch,'-OG');
+ 'r' :
+ Message2(option_obsolete_switch_use_new,'-Or','-O2 or -Ooregvar');
+ 'u' :
+ Message2(option_obsolete_switch_use_new,'-Ou','-Oouncertain');
+ 'w' :
+ begin
+ if not UpdateWpoStr(copy(more,j+1,length(more)),init_settings.dowpoptimizerswitches) then
+ IllegalPara(opt);
+ break;
+ end;
+ 'W' :
+ begin
+ if not UpdateWpoStr(copy(more,j+1,length(more)),init_settings.genwpoptimizerswitches) then
+ IllegalPara(opt);
+ break;
+ end;
+ else
+ IllegalPara(opt);
+ end;
+ inc(j);
+ end;
+ end;
+
+ 'p' :
+ begin
+ if UnsetBool(More, 0) then
+ begin
+ init_settings.moduleswitches:=init_settings.moduleswitches-[cs_profile];
+ undef_system_macro('FPC_PROFILE');
+ end
+ else
+ if Length(More)=0 then
+ IllegalPara(opt)
+ else
+ case more[1] of
+ 'g' : if UnsetBool(more, 1) then
+ begin
+ exclude(init_settings.moduleswitches,cs_profile);
+ undef_system_macro('FPC_PROFILE');
+ end
+ else if (target_info.system in supported_targets_pg) then
+ begin
+ include(init_settings.moduleswitches,cs_profile);
+ def_system_macro('FPC_PROFILE');
+ end
+ else
+ UnsupportedPara('-pg');
+ else
+ IllegalPara(opt);
+ end;
+ end;
+
+ 'P' : ; { Ignore used by fpc.pp }
+
+ 'R' :
+ begin
+ if not SetAsmReadMode(More,init_settings.asmmode) then
+ IllegalPara(opt);
+ end;
+
+ 's' :
+ begin
+ if UnsetBool(More, 0) then
+ begin
+ init_settings.globalswitches:=init_settings.globalswitches-[cs_asm_extern,cs_link_extern,cs_link_nolink];
+ if more<>'' then
+ IllegalPara(opt);
+ end
+ else
+ begin
+ init_settings.globalswitches:=init_settings.globalswitches+[cs_asm_extern,cs_link_extern,cs_link_nolink];
+ if more='h' then
+ init_settings.globalswitches:=init_settings.globalswitches-[cs_link_on_target]
+ else if more='t' then
+ init_settings.globalswitches:=init_settings.globalswitches+[cs_link_on_target]
+ else if more='r' then
+ init_settings.globalswitches:=init_settings.globalswitches+[cs_asm_leave,cs_no_regalloc]
+ else if more<>'' then
+ IllegalPara(opt);
+ end;
+ end;
+
+ 'S' :
+ begin
+ if more='' then
+ IllegalPara(opt);
+ if more[1]='I' then
+ begin
+ if upper(more)='ICOM' then
+ init_settings.interfacetype:=it_interfacecom
+ else if upper(more)='ICORBA' then
+ init_settings.interfacetype:=it_interfacecorba
+ else
+ IllegalPara(opt);
+ end
+ else
+ begin
+ j:=1;
+ while j<=length(more) do
+ begin
+ case more[j] of
+ '2' : //an alternative to -Mobjfpc
+ SetCompileMode('OBJFPC',true);
+ 'a' :
+ If UnsetBool(More, j) then
+ exclude(init_settings.localswitches,cs_do_assertion)
+ else
+ include(init_settings.localswitches,cs_do_assertion);
+ 'c' :
+ If UnsetBool(More, j) then
+ include(init_settings.moduleswitches,cs_support_c_operators)
+ else
+ include(init_settings.moduleswitches,cs_support_c_operators);
+ 'd' : //an alternative to -Mdelphi
+ SetCompileMode('DELPHI',true);
+ 'e' :
+ begin
+ SetErrorFlags(copy(more,j+1,length(more)));
+ break;
+ end;
+ 'f' :
+ begin
+ inc(j);
+ if more[j]='-' then
+ begin
+ features:=[];
+ if length(more)>j then
+ IllegalPara(opt);
+ end
+ else
+ begin
+ if (IncludeFeature(upper(copy(more,j,length(more)-j+1)))) then
+ j:=length(more)
+ else
+ IllegalPara(opt);
+ end;
+ end;
+ 'g' :
+ If UnsetBool(More, j) then
+ exclude(init_settings.moduleswitches,cs_support_goto)
+ else
+ include(init_settings.moduleswitches,cs_support_goto);
+ 'h' :
+ If UnsetBool(More, j) then
+ exclude(init_settings.localswitches,cs_ansistrings)
+ else
+ include(init_settings.localswitches,cs_ansistrings);
+ 'i' :
+ If UnsetBool(More, j) then
+ exclude(init_settings.localswitches,cs_do_inline)
+ else
+ include(init_settings.localswitches,cs_do_inline);
+ 'k' :
+ If UnsetBool(More, j) then
+ exclude(init_settings.globalswitches,cs_load_fpcylix_unit)
+ else
+ include(init_settings.globalswitches,cs_load_fpcylix_unit);
+ 'm' :
+ If UnsetBool(More, j) then
+ exclude(init_settings.moduleswitches,cs_support_macro)
+ else
+ include(init_settings.moduleswitches,cs_support_macro);
+ 'o' : //an alternative to -Mtp
+ SetCompileMode('TP',true);
+{$ifdef gpc_mode}
+ 'p' : //an alternative to -Mgpc
+ SetCompileMode('GPC',true);
+{$endif}
+ 's' :
+ If UnsetBool(More, j) then
+ exclude(init_settings.globalswitches,cs_constructor_name)
+ else
+ include(init_settings.globalswitches,cs_constructor_name);
+ 't' :
+ Message1(option_obsolete_switch,'-St');
+ 'v' :
+ If UnsetBool(More, j) then
+ exclude(init_settings.globalswitches,cs_support_vectors)
+ else
+ include(init_settings.globalswitches,cs_support_vectors);
+ 'x' :
+ If UnsetBool(More, j) then
+ exclude(init_settings.globalswitches,cs_support_exceptions)
+ else
+ include(init_settings.globalswitches,cs_support_exceptions);
+ 'y' :
+ If UnsetBool(More, j) then
+ exclude(init_settings.localswitches,cs_typed_addresses)
+ else
+ include(init_settings.localswitches,cs_typed_addresses);
+ '-' :
+ begin
+ init_settings.globalswitches:=init_settings.globalswitches - [cs_constructor_name,cs_support_exceptions,
+ cs_support_vectors,cs_load_fpcylix_unit];
+
+ init_settings.localswitches:=init_settings.localswitches - [cs_do_assertion,cs_do_inline, cs_ansistrings,
+ cs_typed_addresses];
+
+ init_settings.moduleswitches:=init_settings.moduleswitches - [cs_support_c_operators, cs_support_goto,
+ cs_support_macro];
+ end;
+ else
+ IllegalPara(opt);
+ end;
+ inc(j);
+ end;
+ end;
+ end;
+
+ 'T' :
+ begin
+ more:=Upper(More);
+ if paratarget=system_none then
+ begin
+ { remove old target define }
+ TargetOptions(false);
+ { load new target }
+ paratarget:=find_system_by_string(More);
+ if paratarget<>system_none then
+ set_target(paratarget)
+ else
+ IllegalPara(opt);
+ { set new define }
+ TargetOptions(true);
+ end
+ else
+ if More<>upper(target_info.shortname) then
+ Message1(option_target_is_already_set,target_info.shortname);
+ end;
+
+ 'u' :
+ if more <> '' then
+ undef_system_macro(more);
+ 'U' :
+ begin
+ j:=1;
+ while j<=length(more) do
+ begin
+ case more[j] of
+{$ifdef UNITALIASES}
+ 'a' :
+ begin
+ AddUnitAlias(Copy(More,j+1,255));
+ break;
+ end;
+{$endif UNITALIASES}
+ 'n' :
+ exclude(init_settings.globalswitches,cs_check_unit_name);
+ 'p' :
+ begin
+ Message2(option_obsolete_switch_use_new,'-Up','-Fu');
+ break;
+ end;
+ 'r' :
+ do_release:=true;
+ 's' :
+ include(init_settings.moduleswitches,cs_compilesystem);
+ '-' :
+ begin
+ exclude(init_settings.moduleswitches,cs_compilesystem);
+ exclude(init_settings.globalswitches,cs_check_unit_name);
+ end;
+ else
+ IllegalPara(opt);
+ end;
+ inc(j);
+ end;
+ end;
+
+ 'v' :
+ begin
+ if not setverbosity(More) then
+ IllegalPara(opt);
+ end;
+
+ 'V' : ; { Ignore used by fpc }
+
+ 'W' :
+ begin
+ j:=1;
+ while j<=length(More) do
+ begin
+ case More[j] of
+ 'A':
+ begin
+ if target_info.system in systems_all_windows then
+ begin
+ if UnsetBool(More, j) then
+ apptype:=app_cui
+ else
+ apptype:=app_native;
+ end
+ else
+ IllegalPara(opt);
+ end;
+ 'b':
+ begin
+ if target_info.system in systems_darwin then
+ begin
+ if UnsetBool(More, j) then
+ apptype:=app_cui
+ else
+ apptype:=app_bundle
+ end
+ else
+ IllegalPara(opt);
+ end;
+ 'B':
+ begin
+ if target_info.system in systems_all_windows+systems_symbian then
+ begin
+ { -WB200000 means set trefered base address
+ to $200000, but does not change relocsection boolean
+ this way we can create both relocatble and
+ non relocatable DLL at a specific base address PM }
+ if (length(More)>j) then
+ begin
+ val('$'+Copy(More,j+1,255),imagebase,code);
+ if code<>0 then
+ IllegalPara(opt);
+ ImageBaseSetExplicity:=true;
+ end
+ else
+ begin
+ RelocSection:=true;
+ RelocSectionSetExplicitly:=true;
+ end;
+ break;
+ end
+ else
+ IllegalPara(opt);
+ end;
+ 'C':
+ begin
+ if target_info.system in systems_all_windows+systems_os2+systems_macos then
+ begin
+ if UnsetBool(More, j) then
+ apptype:=app_gui
+ else
+ apptype:=app_cui;
+ end
+ else
+ IllegalPara(opt);
+ end;
+ 'D':
+ begin
+ if target_info.system in systems_all_windows then
+ begin
+ UseDeffileForExports:=not UnsetBool(More, j);
+ UseDeffileForExportsSetExplicitly:=true;
+ end
+ else
+ IllegalPara(opt);
+ end;
+ 'e':
+ begin
+ if (target_info.system in systems_darwin) then
+ begin
+ RegisterRes(res_macosx_ext_info,TWinLikeResourceFile);
+ set_target_res(res_ext);
+ target_info.resobjext:='.fpcres';
+ end
+ else
+ IllegalPara(opt);
+ end;
+ 'F':
+ begin
+ if target_info.system in systems_os2 then
+ begin
+ if UnsetBool(More, j) then
+ apptype:=app_cui
+ else
+ apptype:=app_fs;
+ end
+ else
+ IllegalPara(opt);
+ end;
+ 'G':
+ begin
+ if target_info.system in systems_all_windows+systems_os2+systems_macos then
+ begin
+ if UnsetBool(More, j) then
+ apptype:=app_cui
+ else
+ apptype:=app_gui;
+ end
+ else
+ IllegalPara(opt);
+ end;
+ 'I':
+ begin
+ if target_info.system in systems_all_windows then
+ begin
+ GenerateImportSection:=not UnsetBool(More,j);
+ GenerateImportSectionSetExplicitly:=true;
+ end
+ else
+ IllegalPara(opt);
+ end;
+ 'i':
+ begin
+ if (target_info.system in systems_darwin) then
+ begin
+ set_target_res(res_macho);
+ target_info.resobjext:=
+ targetinfos[target_info.system]^.resobjext;
+ end
+ else
+ IllegalPara(opt);
+ end;
+ 'N':
+ begin
+ if target_info.system in systems_all_windows then
+ begin
+ RelocSection:=UnsetBool(More,j);
+ RelocSectionSetExplicitly:=true;
+ end
+ else
+ IllegalPara(opt);
+ end;
+ 'p':
+ begin
+{$if defined(arm) or defined(avr)}
+ if (target_info.system in systems_embedded) then
+ begin
+ s:=upper(copy(more,j+1,length(more)-j));
+ if not(SetControllerType(s,init_settings.controllertype)) then
+ IllegalPara(opt);
+ break;
+ end
+ else
+{$endif defined(arm) or defined(avr)}
+ IllegalPara(opt);
+ end;
+ 'R':
+ begin
+ if target_info.system in systems_all_windows then
+ begin
+ { support -WR+ / -WR- as synonyms to -WR / -WN }
+ RelocSection:=not UnsetBool(More,j);
+ RelocSectionSetExplicitly:=true;
+ end
+ else
+ IllegalPara(opt);
+ end;
+ 'T':
+ begin
+ if target_info.system in systems_macos then
+ begin
+ if UnsetBool(More, j) then
+ apptype:=app_cui
+ else
+ apptype:=app_tool;
+ end
+ else
+ IllegalPara(opt);
+ end;
+ 'X':
+ begin
+ if (target_info.system in systems_linux) then
+ begin
+ if UnsetBool(More, j) then
+ exclude(init_settings.moduleswitches,cs_executable_stack)
+ else
+ include(init_settings.moduleswitches,cs_executable_stack)
+ end
+ else
+ IllegalPara(opt);
+ end
+ else
+ IllegalPara(opt);
+ end;
+ inc(j);
+ end;
+ end;
+
+ 'X' :
+ begin
+ j:=1;
+ while j<=length(more) do
+ begin
+ case More[j] of
+ 'c' : Cshared:=TRUE;
+ 'd' : Dontlinkstdlibpath:=TRUE;
+ 'e' :
+ begin
+ If UnsetBool(More, j) then
+ exclude(init_settings.globalswitches,cs_link_extern)
+ else
+ include(init_settings.globalswitches,cs_link_extern);
+ end;
+ 'f' :
+ include(init_settings.globalswitches,cs_link_pthread);
+ 'g' :
+ begin
+ If UnsetBool(More, j) then
+ exclude(init_settings.globalswitches,cs_link_separate_dbg_file)
+ else
+ include(init_settings.globalswitches,cs_link_separate_dbg_file);
+ end;
+ 'i' :
+ begin
+ If UnsetBool(More, j) then
+ include(init_settings.globalswitches,cs_link_extern)
+ else
+ exclude(init_settings.globalswitches,cs_link_extern);
+ end;
+ 'n' :
+ begin
+ If UnsetBool(More, j) then
+ exclude(init_settings.globalswitches,cs_link_native)
+ else
+ include(init_settings.globalswitches,cs_link_native);
+ end;
+
+ 'm' :
+ begin
+ If UnsetBool(More, j) then
+ exclude(init_settings.globalswitches,cs_link_map)
+ else
+ include(init_settings.globalswitches,cs_link_map);
+ end;
+ 'p' : ; { Ignore used by fpc.pp }
+ 'r' :
+ begin
+ if (target_info.system in suppported_targets_x_smallr) then
+ begin
+ rlinkpath:=Copy(more,2,length(More)-1);
+ DefaultReplacements(rlinkpath);
+ end
+ else
+ IgnoredPara('-Xr');
+ more:='';
+ end;
+ 'R' :
+ begin
+ sysrootpath:=copy(more,2,length(more)-1);
+ defaultreplacements(sysrootpath);
+ more:='';
+ end;
+ 's' :
+ begin
+ If UnsetBool(More, j) then
+ exclude(init_settings.globalswitches,cs_link_strip)
+ else
+ include(init_settings.globalswitches,cs_link_strip);
+ end;
+ 't' :
+ include(init_settings.globalswitches,cs_link_staticflag);
+ 'v' :
+ begin
+ If UnsetBool(More, j) then
+ exclude(init_settings.globalswitches,cs_link_opt_vtable)
+ else
+ include(init_settings.globalswitches,cs_link_opt_vtable);
+ end;
+ 'D' :
+ begin
+ def_system_macro('FPC_LINK_DYNAMIC');
+ undef_system_macro('FPC_LINK_SMART');
+ undef_system_macro('FPC_LINK_STATIC');
+ exclude(init_settings.globalswitches,cs_link_static);
+ exclude(init_settings.globalswitches,cs_link_smart);
+ include(init_settings.globalswitches,cs_link_shared);
+ LinkTypeSetExplicitly:=true;
+ end;
+ 'M' :
+ begin
+ mainaliasname:=Copy(more,2,length(More)-1);
+ More:='';
+ end;
+ 'P' :
+ begin
+ utilsprefix:=Copy(more,2,length(More)-1);
+ DefaultReplacements(utilsprefix);
+ More:='';
+ end;
+ 'L' : begin // -XLO is link order -XLA is link alias. -XLD avoids load defaults.
+ // these are not aggregable.
+ if (j=length(more)) or not (more[j+1] in ['O','A','D']) then
+ IllegalPara(opt)
+ else
+ begin
+ case more[j+1] of
+ 'A' : begin
+ s:=Copy(more,3,length(More)-2);
+ if not LinkLibraryAliases.AddDep(s) Then
+ IllegalPara(opt);
+ end;
+ 'O' : begin
+ s:=Copy(more,3,length(More)-2);
+ if not LinkLibraryOrder.AddWeight(s) Then
+ IllegalPara(opt);
+ end;
+ 'D' : include(init_settings.globalswitches,cs_link_no_default_lib_order)
+ else
+ IllegalPara(opt);
+ end; {case}
+ j:=length(more);
+ end; {else begin}
+ end;
+ 'S' :
+ begin
+ ForceStaticLinking;
+ end;
+ 'X' :
+ begin
+ def_system_macro('FPC_LINK_SMART');
+ undef_system_macro('FPC_LINK_STATIC');
+ undef_system_macro('FPC_LINK_DYNAMIC');
+ exclude(init_settings.globalswitches,cs_link_static);
+ include(init_settings.globalswitches,cs_link_smart);
+ exclude(init_settings.globalswitches,cs_link_shared);
+ LinkTypeSetExplicitly:=true;
+ end;
+ '-' :
+ begin
+ exclude(init_settings.globalswitches,cs_link_staticflag);
+ exclude(init_settings.globalswitches,cs_link_strip);
+ exclude(init_settings.globalswitches,cs_link_map);
+ set_default_link_type;
+ end;
+ else
+ IllegalPara(opt);
+ end;
+ inc(j);
+ end;
+ end;
+ else
+ IllegalPara(opt);
+ end;
+ end;
+
+ '@' :
+ begin
+ Message(option_no_nested_response_file);
+ StopOptions(1);
+ end;
+
+ else
+ begin
+ if (length(param_file)<>0) then
+ Message2(option_only_one_source_support,param_file,opt);
+ param_file:=opt;
+ Message1(option_found_file,opt);
+ end;
+ end;
+end;
+
+
+procedure Toption.Interpret_file(const filename : TPathStr);
+
+ procedure RemoveSep(var fn:TPathStr);
+ var
+ i : longint;
+ begin
+ i:=0;
+ while (i<length(fn)) and (fn[i+1] in [',',' ',#9]) do
+ inc(i);
+ Delete(fn,1,i);
+ i:=length(fn);
+ while (i>0) and (fn[i] in [',',' ',#9]) do
+ dec(i);
+ fn:=copy(fn,1,i);
+ end;
+
+ function GetName(var fn:TPathStr):TPathStr;
+ var
+ i : longint;
+ begin
+ i:=0;
+ while (i<length(fn)) and (fn[i+1] in ['a'..'z','A'..'Z','0'..'9','_','-']) do
+ inc(i);
+ GetName:=Copy(fn,1,i);
+ Delete(fn,1,i);
+ end;
+
+const
+ maxlevel = 15;
+var
+ f : text;
+ s, tmp,
+ opts : TCmdStr;
+ skip : array[0..maxlevel] of boolean;
+ line,
+ level : longint;
+ option_read : boolean;
+begin
+{ avoid infinite loop }
+ Inc(FileLevel);
+ Option_read:=false;
+ If FileLevel>MaxLevel then
+ Message(option_too_many_cfg_files);
+{ Maybe It's Directory ?} //Jaro Change:
+ if PathExists(filename,false) then
+ begin
+ Message1(option_config_is_dir,filename);
+ exit;
+ end;
+{ open file }
+ Message1(option_using_file,filename);
+ assign(f,ExpandFileName(filename));
+ {$push}{$I-}
+ reset(f);
+ {$pop}
+ if ioresult<>0 then
+ begin
+ Message1(option_unable_open_file,filename);
+ exit;
+ end;
+ Message1(option_start_reading_configfile,filename);
+ fillchar(skip,sizeof(skip),0);
+ level:=0;
+ line:=0;
+ while not eof(f) do
+ begin
+ readln(f,opts);
+ inc(line);
+ RemoveSep(opts);
+ if (opts<>'') and (opts[1]<>';') then
+ begin
+ if opts[1]='#' then
+ begin
+ Message1(option_interpreting_file_option,opts);
+ Delete(opts,1,1);
+ s:=upper(GetName(opts));
+ if (s='SECTION') then
+ begin
+ RemoveSep(opts);
+ s:=upper(GetName(opts));
+ if level=0 then
+ skip[level]:=not defined_macro(s) or (s='COMMON');
+ end
+ else
+ if (s='IFDEF') then
+ begin
+ RemoveSep(opts);
+ if Level>=maxlevel then
+ begin
+ Message2(option_too_many_ifdef,filename,tostr(line));
+ stopOptions(1);
+ end;
+ inc(Level);
+ skip[level]:=(skip[level-1] or not defined_macro(upper(GetName(opts))));
+ end
+ else
+ if (s='IFNDEF') then
+ begin
+ RemoveSep(opts);
+ if Level>=maxlevel then
+ begin
+ Message2(option_too_many_ifdef,filename,tostr(line));
+ stopOptions(1);
+ end;
+ inc(Level);
+ skip[level]:=(skip[level-1] or defined_macro(upper(GetName(opts))));
+ end
+ else
+ if (s='ELSE') then
+ begin
+ if Level=0 then
+ begin
+ Message2(option_else_without_if,filename,tostr(line));
+ stopOptions(1);
+ end
+ else
+ skip[level]:=skip[level-1] or (not skip[level])
+ end
+ else
+ if (s='ENDIF') then
+ begin
+ skip[level]:=false;
+ if Level=0 then
+ begin
+ Message2(option_too_many_endif,filename,tostr(line));
+ stopOptions(1);
+ end;
+ dec(level);
+ end
+ else
+ if (not skip[level]) then
+ begin
+ if (s='DEFINE') then
+ begin
+ RemoveSep(opts);
+ tmp:= GetName(opts);
+ if tmp <> '' then
+ def_system_macro(tmp);
+ end
+ else
+ if (s='UNDEF') then
+ begin
+ RemoveSep(opts);
+ tmp:= GetName(opts);
+ if tmp <> '' then
+ undef_system_macro(tmp);
+ end
+ else
+ if (s='WRITE') then
+ begin
+ Delete(opts,1,1);
+ WriteLn(opts);
+ end
+ else
+ if (s='INCLUDE') then
+ begin
+ Delete(opts,1,1);
+ Interpret_file(opts);
+ end;
+ end;
+ end
+ else
+ begin
+ if (opts[1]='-') or (opts[1]='@') then
+ begin
+ if (not skip[level]) then
+ interpret_option(opts,false);
+ Option_read:=true;
+ end
+ else
+ Message1(option_illegal_para,opts);
+ end;
+ end;
+ end;
+ if Level>0 then
+ Message(option_too_less_endif);
+ if Not Option_read then
+ Message1(option_no_option_found,filename)
+ else
+ Message1(option_end_reading_configfile,filename);
+ Close(f);
+ Dec(FileLevel);
+end;
+
+
+procedure Toption.Interpret_envvar(const envname : TCmdStr);
+var
+ argstart,
+ env,
+ pc : pchar;
+ arglen : longint;
+ quote : set of char;
+ hs : TCmdStr;
+begin
+ Message1(option_using_env,envname);
+ env:=GetEnvPChar(envname);
+ pc:=env;
+ if assigned(pc) then
+ begin
+ repeat
+ { skip leading spaces }
+ while pc^ in [' ',#9,#13] do
+ inc(pc);
+ case pc^ of
+ #0 :
+ break;
+ '"' :
+ begin
+ quote:=['"'];
+ inc(pc);
+ end;
+ '''' :
+ begin
+ quote:=[''''];
+ inc(pc);
+ end;
+ else
+ quote:=[' ',#9,#13];
+ end;
+ { scan until the end of the argument }
+ argstart:=pc;
+ while (pc^<>#0) and not(pc^ in quote) do
+ inc(pc);
+ { create argument }
+ arglen:=pc-argstart;
+{ TODO: FIXME: silent truncation of environment parameters }
+ if (arglen > 255) then
+ arglen := 255;
+ setlength(hs,arglen);
+ move(argstart^,hs[1],arglen);
+ interpret_option(hs,true);
+ { skip quote }
+ if pc^ in quote then
+ inc(pc);
+ until false;
+ end
+ else
+ Message1(option_no_option_found,'(env) '+envname);
+ FreeEnvPChar(env);
+end;
+
+
+procedure toption.read_parameters;
+var
+ opts : TCmdStr;
+ paramindex : longint;
+begin
+ paramindex:=0;
+ while paramindex<paramcount do
+ begin
+ inc(paramindex);
+ opts:=objpas.paramstr(paramindex);
+ if length(opts)>0 then
+ case opts[1] of
+ '@' :
+ if not firstpass then
+ begin
+ Delete(opts,1,1);
+ Message1(option_reading_further_from,opts);
+ interpret_file(opts);
+ end;
+ '!' :
+ if not firstpass then
+ begin
+ Delete(opts,1,1);
+ Message1(option_reading_further_from,'(env) '+opts);
+ interpret_envvar(opts);
+ end;
+ else
+ interpret_option(opts,true);
+ end;
+ end;
+end;
+
+
+procedure toption.parsecmd(cmd:TCmdStr);
+var
+ i,ps : longint;
+ opts : TCmdStr;
+begin
+ while (cmd<>'') do
+ begin
+ while cmd[1]=' ' do
+ delete(cmd,1,1);
+ i:=pos(' ',cmd);
+ if i=0 then
+ i:=2147483647;
+ opts:=Copy(cmd,1,i-1);
+ Delete(cmd,1,i);
+ case opts[1] of
+ '@' :
+ if not firstpass then
+ begin
+ Delete(opts,1,1);
+ Message1(option_reading_further_from,opts);
+ interpret_file(opts);
+ end;
+ '!' :
+ if not firstpass then
+ begin
+ Delete(opts,1,1);
+ Message1(option_reading_further_from,'(env) '+opts);
+ interpret_envvar(opts);
+ end;
+ '"' :
+ begin
+ Delete(opts,1,1);
+ ps:=pos('"',cmd);
+ if (i<>256) and (ps>0) then
+ begin
+ opts:=opts + ' '+ copy(cmd,1,ps-1);
+ cmd:=copy(cmd,ps+1,255);
+ end;
+ interpret_option(opts,true);
+ end;
+ else
+ interpret_option(opts,true);
+ end;
+ end;
+end;
+
+
+procedure toption.writequickinfo;
+var
+ s : string;
+ i : longint;
+
+ procedure addinfo(const hs:string);
+ begin
+ if s<>'' then
+ s:=s+' '+hs
+ else
+ s:=hs;
+ end;
+
+begin
+ s:='';
+ i:=0;
+ while (i<length(quickinfo)) do
+ begin
+ inc(i);
+ case quickinfo[i] of
+ 'S' :
+ begin
+ inc(i);
+ case quickinfo[i] of
+ 'O' :
+ addinfo(lower(source_info.shortname));
+ 'P' :
+ addinfo(source_cpu_string);
+ else
+ IllegalPara('-i'+QuickInfo);
+ end;
+ end;
+ 'T' :
+ begin
+ inc(i);
+ case quickinfo[i] of
+ 'O' :
+ addinfo(lower(target_info.shortname));
+ 'P' :
+ AddInfo(target_cpu_string);
+ else
+ IllegalPara('-i'+QuickInfo);
+ end;
+ end;
+ 'V' :
+ AddInfo(version_string);
+ 'W' :
+ AddInfo(full_version_string);
+ 'D' :
+ AddInfo(date_string);
+ '_' :
+ ;
+ else
+ IllegalPara('-i'+QuickInfo);
+ end;
+ end;
+ if s<>'' then
+ begin
+ writeln(s);
+ stopoptions(0);
+ end;
+end;
+
+
+procedure TOption.TargetOptions(def:boolean);
+var
+ s : string;
+ i : integer;
+ target_unsup_features : tfeatures;
+begin
+ if def then
+ def_system_macro(target_info.shortname)
+ else
+ undef_system_macro(target_info.shortname);
+
+ s:=target_info.extradefines;
+ while (s<>'') do
+ begin
+ i:=pos(';',s);
+ if i=0 then
+ i:=length(s)+1;
+ if def then
+ def_system_macro(Copy(s,1,i-1))
+ else
+ undef_system_macro(Copy(s,1,i-1));
+ delete(s,1,i);
+ end;
+
+ if (tf_winlikewidestring in target_info.flags) then
+ if def then
+ def_system_macro('FPC_WINLIKEWIDESTRING')
+ else
+ undef_system_macro('FPC_WINLIKEWIDESTRING');
+
+ if (tf_requires_proper_alignment in target_info.flags) then
+ if def then
+ def_system_macro('FPC_REQUIRES_PROPER_ALIGNMENT')
+ else
+ undef_system_macro('FPC_REQUIRES_PROPER_ALIGNMENT');
+
+ if source_info.system<>target_info.system then
+ if def then
+ def_system_macro('FPC_CROSSCOMPILING')
+ else
+ undef_system_macro('FPC_CROSSCOMPILING');
+
+ if source_info.cpu<>target_info.cpu then
+ if def then
+ def_system_macro('FPC_CPUCROSSCOMPILING')
+ else
+ def_system_macro('FPC_CPUCROSSCOMPILING');
+
+ if (tf_no_generic_stackcheck in target_info.flags) then
+ if def then
+ def_system_macro('FPC_NO_GENERIC_STACK_CHECK')
+ else
+ undef_system_macro('FPC_NO_GENERIC_STACK_CHECK');
+
+ { Code generation flags }
+ if def and
+ (tf_pic_default in target_info.flags) then
+ include(init_settings.moduleswitches,cs_create_pic)
+ else
+ exclude(init_settings.moduleswitches,cs_create_pic);
+
+ { Resources support }
+ if (tf_has_winlike_resources in target_info.flags) then
+ if def then
+ def_system_macro('FPC_HAS_WINLIKERESOURCES')
+ else
+ undef_system_macro('FPC_HAS_WINLIKERESOURCES');
+
+ { Features }
+ case target_info.system of
+ system_arm_gba:
+ target_unsup_features:=[f_dynlibs];
+ system_arm_nds:
+ target_unsup_features:=[f_threading,f_commandargs,f_fileio,f_textio,f_consoleio,f_dynlibs];
+ system_i386_nativent:
+ // until these features are implemented, they are disabled in the compiler
+ target_unsup_features:=[f_stackcheck];
+ else
+ target_unsup_features:=[];
+ end;
+ if def then
+ features:=features-target_unsup_features
+ else
+ features:=features+target_unsup_features;
+end;
+
+procedure TOption.checkoptionscompatibility;
+begin
+ if (paratargetdbg in [dbg_dwarf2,dbg_dwarf3]) and
+ not(target_info.system in systems_darwin) then
+ begin
+ { smartlink creation does not yet work with DWARF
+ debug info on most targets, but it works in internal assembler }
+ if (cs_create_smart in init_settings.moduleswitches) and
+ not (af_outputbinary in target_asm.flags) then
+ begin
+ Message(option_dwarf_smartlink_creation);
+ exclude(init_settings.moduleswitches,cs_create_smart);
+ end;
+
+ { smart linking does not yet work with DWARF debug info on most targets }
+ if (cs_link_smart in init_settings.globalswitches) then
+ begin
+ Message(option_dwarf_smart_linking);
+ ForceStaticLinking;
+ end;
+ end;
+
+ { external debug info is only supported for DWARF on darwin }
+ if (target_info.system in systems_darwin) and
+ (cs_link_separate_dbg_file in init_settings.globalswitches) and
+ not(paratargetdbg in [dbg_dwarf2,dbg_dwarf3]) then
+ begin
+ Message(option_debug_external_unsupported);
+ exclude(init_settings.globalswitches,cs_link_separate_dbg_file);
+ end;
+end;
+
+
+constructor TOption.create;
+begin
+ LogoWritten:=false;
+ NoPressEnter:=false;
+ FirstPass:=false;
+ FPUSetExplicitly:=false;
+ CPUSetExplicitly:=false;
+ OptCPUSetExplicitly:=false;
+ FileLevel:=0;
+ Quickinfo:='';
+ ParaIncludePath:=TSearchPathList.Create;
+ ParaObjectPath:=TSearchPathList.Create;
+ ParaUnitPath:=TSearchPathList.Create;
+ ParaLibraryPath:=TSearchPathList.Create;
+ ParaFrameworkPath:=TSearchPathList.Create;
+ FillChar(ParaAlignment,sizeof(ParaAlignment),0);
+end;
+
+
+destructor TOption.destroy;
+begin
+ ParaIncludePath.Free;
+ ParaObjectPath.Free;
+ ParaUnitPath.Free;
+ ParaLibraryPath.Free;
+ ParaFrameworkPath.Free;
+end;
+
+
+{****************************************************************************
+ Callable Routines
+****************************************************************************}
+
+function check_configfile(const fn:string;var foundfn:string):boolean;
+
+ function CfgFileExists(const fn:string):boolean;
+ begin
+ Comment(V_Tried,'Configfile search: '+fn);
+ CfgFileExists:=FileExists(fn);
+ end;
+
+var
+{$ifdef Unix}
+ hs,
+{$endif Unix}
+ configpath : string;
+begin
+ foundfn:=fn;
+ check_configfile:=true;
+ { retrieve configpath }
+ configpath:=FixPath(GetEnvironmentVariable('PPC_CONFIG_PATH'),false);
+{$ifdef Unix}
+ if configpath='' then
+ configpath:=ExpandFileName(FixPath(exepath+'../etc/',false));
+{$endif}
+ {
+ Order to read configuration file :
+ try reading fpc.cfg in :
+ 1 - current dir
+ 2 - configpath
+ 3 - compiler path
+ }
+ if not FileExists(fn) then
+ begin
+{$ifdef Unix}
+ hs:=GetEnvironmentVariable('HOME');
+ if (hs<>'') and CfgFileExists(FixPath(hs,false)+'.'+fn) then
+ foundfn:=FixPath(hs,false)+'.'+fn
+ else
+{$endif}
+ if CfgFileExists(configpath+fn) then
+ foundfn:=configpath+fn
+ else
+{$ifdef WINDOWS}
+ if (GetEnvironmentVariable('USERPROFILE')<>'') and CfgFileExists(FixPath(GetEnvironmentVariable('USERPROFILE'),false)+fn) then
+ foundfn:=FixPath(GetEnvironmentVariable('USERPROFILE'),false)+fn
+ else
+ if (GetEnvironmentVariable('ALLUSERSPROFILE')<>'') and CfgFileExists(FixPath(GetEnvironmentVariable('ALLUSERSPROFILE'),false)+fn) then
+ foundfn:=FixPath(GetEnvironmentVariable('ALLUSERSPROFILE'),false)+fn
+ else
+{$endif WINDOWS}
+{$ifndef Unix}
+ if CfgFileExists(exepath+fn) then
+ foundfn:=exepath+fn
+ else
+{$else}
+ if CfgFileExists('/etc/'+fn) then
+ foundfn:='/etc/'+fn
+ else
+{$endif}
+ check_configfile:=false;
+ end;
+end;
+
+
+procedure read_arguments(cmd:TCmdStr);
+var
+ env: ansistring;
+ i : tfeature;
+ abi : tabi;
+begin
+ option:=coption.create;
+ disable_configfile:=false;
+
+ { Non-core target defines }
+ Option.TargetOptions(true);
+
+{ get default messagefile }
+ msgfilename:=GetEnvironmentVariable('PPC_ERROR_FILE');
+
+{ default configfile can be specified on the commandline,
+ remove it first }
+ if (cmd<>'') and (cmd[1]='[') then
+ begin
+ ppccfg:=Copy(cmd,2,pos(']',cmd)-2);
+ Delete(cmd,1,pos(']',cmd));
+ end
+ else
+ ppccfg:='fpc.cfg';
+
+{ first pass reading of parameters, only -i -v -T etc.}
+ option.firstpass:=true;
+ if cmd<>'' then
+ option.parsecmd(cmd)
+ else
+ begin
+ option.read_parameters;
+ { Write only quickinfo }
+ if option.quickinfo<>'' then
+ option.writequickinfo;
+ end;
+ option.firstpass:=false;
+
+ { redefine target options so all defines are written even if no -Txxx is passed on the command line }
+ Option.TargetOptions(true);
+
+{ target is set here, for wince the default app type is gui }
+ if target_info.system in systems_wince then
+ apptype:=app_gui;
+
+{ default defines }
+ def_system_macro(target_info.shortname);
+ def_system_macro('FPC');
+ def_system_macro('VER'+version_nr);
+ def_system_macro('VER'+version_nr+'_'+release_nr);
+ def_system_macro('VER'+version_nr+'_'+release_nr+'_'+patch_nr);
+
+{ Temporary defines, until things settle down }
+ def_system_macro('RESSTRSECTIONS');
+ def_system_macro('FPC_HASFIXED64BITVARIANT');
+ def_system_macro('FPC_HASINTERNALOLEVARIANT2VARIANTCAST');
+ def_system_macro('FPC_HAS_VARSETS');
+ def_system_macro('FPC_HAS_VALGRINDBOOL');
+ def_system_macro('FPC_HAS_STR_CURRENCY');
+ def_system_macro('FPC_REAL2REAL_FIXED');
+ def_system_macro('FPC_STRTOCHARARRAYPROC');
+ def_system_macro('FPC_STRTOSHORTSTRINGPROC');
+ def_system_macro('FPC_OBJFPC_EXTENDED_IF');
+ def_system_macro('FPC_HAS_OPERATOR_ENUMERATOR');
+ def_system_macro('FPC_HAS_CONSTREF');
+ def_system_macro('FPC_STATICRIPFIXED');
+ def_system_macro('FPC_VARIANTCOPY_FIXED');
+{$if defined(x86) or defined(powerpc) or defined(powerpc64)}
+ def_system_macro('FPC_HAS_INTERNAL_ABS_LONG');
+{$endif}
+ def_system_macro('FPC_HAS_UNICODESTRING');
+ def_system_macro('FPC_RTTI_PACKSET1');
+ def_system_macro('FPC_HAS_CPSTRING');
+{$ifdef x86_64}
+ def_system_macro('FPC_HAS_RIP_RELATIVE');
+{$endif x86_64}
+ def_system_macro('FPC_HAS_CEXTENDED');
+ def_system_macro('FPC_HAS_RESSTRINITS');
+
+{ these cpus have an inline rol/ror implementaion }
+{$ifdef cpurox}
+ def_system_macro('FPC_HAS_INTERNAL_ROX');
+{$endif}
+
+{ these cpus have an inline sar implementaion }
+{ currently, all supported CPUs have an internal sar implementation }
+{ $if defined(x86) or defined(arm) or defined(powerpc) or defined(powerpc64) or defined(sparc)}
+ def_system_macro('FPC_HAS_INTERNAL_SAR');
+{ $endif}
+
+{ inline bsf/bsr implementation }
+{$if defined(x86) or defined(x86_64)}
+ def_system_macro('FPC_HAS_INTERNAL_BSX');
+{$endif}
+
+{$ifdef powerpc64}
+ def_system_macro('FPC_HAS_LWSYNC');
+{$endif}
+ def_system_macro('FPC_HAS_MEMBAR');
+ def_system_macro('FPC_SETBASE_USED');
+
+{$if defined(x86) or defined(arm)}
+ def_system_macro('INTERNAL_BACKTRACE');
+{$endif}
+ def_system_macro('STR_CONCAT_PROCS');
+{$warnings off}
+ if pocall_default = pocall_register then
+ def_system_macro('REGCALL');
+{$warnings on}
+ { don't remove this, it's also for fpdoc necessary (FK) }
+ def_system_macro('FPC_HAS_FEATURE_SUPPORT');
+{ using a case is pretty useless here (FK) }
+{ some stuff for TP compatibility }
+{$ifdef i386}
+ def_system_macro('CPU86');
+ def_system_macro('CPU87');
+ def_system_macro('CPU386');
+{$endif}
+
+{ new processor stuff }
+{$ifdef i386}
+ def_system_macro('CPUI386');
+ def_system_macro('CPU32');
+ def_system_macro('FPC_HAS_TYPE_EXTENDED');
+ def_system_macro('FPC_HAS_TYPE_DOUBLE');
+ def_system_macro('FPC_HAS_TYPE_SINGLE');
+{$endif}
+{$ifdef m68k}
+ def_system_macro('CPU68');
+ def_system_macro('CPU68K');
+ def_system_macro('CPUM68K');
+ def_system_macro('CPU32');
+ def_system_macro('FPC_CURRENCY_IS_INT64');
+ def_system_macro('FPC_COMP_IS_INT64');
+{$endif}
+{$ifdef ALPHA}
+ def_system_macro('CPUALPHA');
+ def_system_macro('CPU64');
+{$endif}
+{$ifdef powerpc}
+ def_system_macro('CPUPOWERPC');
+ def_system_macro('CPUPOWERPC32');
+ def_system_macro('CPU32');
+ def_system_macro('FPC_CURRENCY_IS_INT64');
+ def_system_macro('FPC_COMP_IS_INT64');
+{$endif}
+{$ifdef POWERPC64}
+ def_system_macro('CPUPOWERPC');
+ def_system_macro('CPUPOWERPC64');
+ def_system_macro('CPU64');
+ def_system_macro('FPC_CURRENCY_IS_INT64');
+ def_system_macro('FPC_COMP_IS_INT64');
+{$endif}
+{$ifdef iA64}
+ def_system_macro('CPUIA64');
+ def_system_macro('CPU64');
+{$endif}
+{$ifdef x86_64}
+ def_system_macro('CPUX86_64');
+ def_system_macro('CPUAMD64');
+ def_system_macro('CPU64');
+ { not supported for now, afaik (FK)
+ def_system_macro('FPC_HAS_TYPE_FLOAT128'); }
+ { win64 doesn't support the legacy fpu }
+ if target_info.system=system_x86_64_win64 then
+ begin
+ def_system_macro('FPC_CURRENCY_IS_INT64');
+ def_system_macro('FPC_COMP_IS_INT64');
+ end;
+{$endif}
+{$ifdef sparc}
+ def_system_macro('CPUSPARC');
+ def_system_macro('CPUSPARC32');
+ def_system_macro('CPU32');
+ def_system_macro('FPC_CURRENCY_IS_INT64');
+ def_system_macro('FPC_COMP_IS_INT64');
+{$endif}
+{$ifdef vis}
+ def_system_macro('CPUVIS');
+ def_system_macro('CPU32');
+{$endif}
+{$ifdef arm}
+ def_system_macro('CPUARM');
+ def_system_macro('CPU32');
+ def_system_macro('FPC_CURRENCY_IS_INT64');
+ def_system_macro('FPC_COMP_IS_INT64');
+{$endif arm}
+{$ifdef avr}
+ def_system_macro('CPUAVR');
+ def_system_macro('CPU16');
+ def_system_macro('FPC_CURRENCY_IS_INT64');
+ def_system_macro('FPC_COMP_IS_INT64');
+{$endif avr}
+
+ { read configuration file }
+ if (not disable_configfile) and
+ (ppccfg<>'') then
+ read_configfile:=check_configfile(ppccfg,ppccfg)
+ else
+ read_configfile := false;
+
+{ Read commandline and configfile }
+ param_file:='';
+
+ { read configfile }
+ if read_configfile then
+ option.interpret_file(ppccfg);
+
+ { read parameters again to override config file }
+ if cmd<>'' then
+ option.parsecmd(cmd)
+ else
+ begin
+ { Write help pages if no parameters are passed }
+ if (paramcount=0) then
+ Option.WriteHelpPages;
+ option.read_parameters;
+ { Write only quickinfo }
+ if option.quickinfo<>'' then
+ option.writequickinfo;
+ end;
+
+ { check the compatibility of different options and adjust them if necessary
+ (and print possible errors)
+ }
+ option.checkoptionscompatibility;
+
+ { Stop if errors in options }
+ if ErrorCount>0 then
+ StopOptions(1);
+
+ { endian define }
+ case target_info.endian of
+ endian_little :
+ begin
+ def_system_macro('ENDIAN_LITTLE');
+ def_system_macro('FPC_LITTLE_ENDIAN');
+ end;
+ endian_big :
+ begin
+ def_system_macro('ENDIAN_BIG');
+ def_system_macro('FPC_BIG_ENDIAN');
+ end;
+ end;
+
+ { define abi }
+ for abi:=low(tabi) to high(tabi) do
+ undef_system_macro('FPC_ABI_'+abi2str[abi]);
+ def_system_macro('FPC_ABI_'+abi2str[target_info.abi]);
+
+ { Write logo }
+ if option.ParaLogo then
+ option.writelogo;
+
+{ Check file to compile }
+ if param_file='' then
+ begin
+ Message(option_no_source_found);
+ StopOptions(1);
+ end;
+{$ifndef Unix}
+ param_file:=FixFileName(param_file);
+{$endif not unix}
+ inputfilepath:=ExtractFilePath(param_file);
+ inputfilename:=ExtractFileName(param_file);
+ if ExtractFileExt(inputfilename)='' then
+ begin
+ if FileExists(inputfilepath+ChangeFileExt(inputfilename,sourceext)) then
+ inputfilename:=ChangeFileExt(inputfilename,sourceext)
+ else if FileExists(inputfilepath+ChangeFileExt(inputfilename,pasext)) then
+ inputfilename:=ChangeFileExt(inputfilename,pasext)
+ else if ((m_mac in current_settings.modeswitches) or
+ (tf_p_ext_support in target_info.flags))
+ and FileExists(inputfilepath+ChangeFileExt(inputfilename,pext)) then
+ inputfilename:=ChangeFileExt(inputfilename,pext);
+ end;
+
+ { Check output dir }
+ if (OutputExeDir<>'') and
+ not PathExists(OutputExeDir,false) then
+ begin
+ Message1(general_e_path_does_not_exist,OutputExeDir);
+ StopOptions(1);
+ end;
+
+ { Add paths specified with parameters to the searchpaths }
+ UnitSearchPath.AddList(option.ParaUnitPath,true);
+ ObjectSearchPath.AddList(option.ParaObjectPath,true);
+ IncludeSearchPath.AddList(option.ParaIncludePath,true);
+ LibrarySearchPath.AddList(option.ParaLibraryPath,true);
+ FrameworkSearchPath.AddList(option.ParaFrameworkPath,true);
+
+ { add unit environment and exepath to the unit search path }
+ if inputfilepath<>'' then
+ Unitsearchpath.AddPath(inputfilepath,true);
+ if not disable_configfile then
+ begin
+ env:=GetEnvironmentVariable(target_info.unit_env);
+ if env<>'' then
+ UnitSearchPath.AddPath(GetEnvironmentVariable(target_info.unit_env),false);
+ end;
+
+{$ifdef Unix}
+ fpcdir:=FixPath(GetEnvironmentVariable('FPCDIR'),false);
+ if fpcdir='' then
+ begin
+ if PathExists('/usr/local/lib/fpc/'+version_string,true) then
+ fpcdir:='/usr/local/lib/fpc/'+version_string+'/'
+ else
+ fpcdir:='/usr/lib/fpc/'+version_string+'/';
+ end;
+{$else unix}
+ fpcdir:=FixPath(GetEnvironmentVariable('FPCDIR'),false);
+ if fpcdir='' then
+ begin
+ fpcdir:=ExePath+'../';
+ if not(PathExists(fpcdir+'units',true)) and
+ not(PathExists(fpcdir+'rtl',true)) then
+ fpcdir:=fpcdir+'../';
+ end;
+{$endif unix}
+ { first try development RTL, else use the default installation path }
+ if not disable_configfile then
+ begin
+ if PathExists(FpcDir+'rtl',true) then
+ if tf_use_8_3 in Source_Info.Flags then
+ UnitSearchPath.AddPath(FpcDir+'rtl/'+target_os_string,false)
+ else
+ UnitSearchPath.AddPath(FpcDir+'rtl/'+target_full_string,false)
+ else
+ if tf_use_8_3 in Source_Info.Flags then
+ UnitSearchPath.AddPath(FpcDir+'units/'+target_os_string+'/rtl',false)
+ else
+ UnitSearchPath.AddPath(FpcDir+'units/'+target_full_string+'/rtl',false);
+ end;
+ { Add exepath if the exe is not in the current dir, because that is always searched already.
+ Do not add it when linking on the target because then we can maybe already find
+ .o files that are not for the target }
+ if (ExePath<>GetCurrentDir) and
+ not(cs_link_on_target in init_settings.globalswitches) then
+ UnitSearchPath.AddPath(ExePath,false);
+ { Add unit dir to the object and library path }
+ objectsearchpath.AddList(unitsearchpath,false);
+ librarysearchpath.AddList(unitsearchpath,false);
+
+ { maybe override assembler }
+ if (paratargetasm<>as_none) then
+ begin
+ if not set_target_asm(paratargetasm) then
+ begin
+ Message2(option_incompatible_asm,asminfos[paratargetasm]^.idtxt,target_info.name);
+ set_target_asm(target_info.assemextern);
+ Message1(option_asm_forced,target_asm.idtxt);
+ end;
+ if (af_no_debug in asminfos[paratargetasm]^.flags) and
+ (paratargetdbg<>dbg_none) then
+ begin
+ Message1(option_confict_asm_debug,
+ asminfos[paratargetasm]^.idtxt);
+ paratargetdbg:=dbg_none;
+ exclude(init_settings.moduleswitches,cs_debuginfo);
+ end;
+ end;
+ {TOptionheck a second time as we might have changed assembler just above }
+ option.checkoptionscompatibility;
+
+ { maybe override debug info format }
+ if (paratargetdbg<>dbg_none) then
+ set_target_dbg(paratargetdbg);
+
+ { switch assembler if it's binary and we got -a on the cmdline }
+ if (cs_asm_leave in init_settings.globalswitches) and
+ (af_outputbinary in target_asm.flags) then
+ begin
+ Message(option_switch_bin_to_src_assembler);
+ set_target_asm(target_info.assemextern);
+ end;
+
+ { Force use of external linker if there is no
+ internal linker or the linking is skipped }
+ if not(cs_link_extern in init_settings.globalswitches) and
+ (not assigned(target_info.link) or
+ (cs_link_nolink in init_settings.globalswitches)) then
+ include(init_settings.globalswitches,cs_link_extern);
+
+ { turn off stripping if compiling with debuginfo or profile }
+ if (
+ (cs_debuginfo in init_settings.moduleswitches) or
+ (cs_profile in init_settings.moduleswitches)
+ ) and
+ not(cs_link_separate_dbg_file in init_settings.globalswitches) then
+ exclude(init_settings.globalswitches,cs_link_strip);
+
+ { force fpu emulation on arm/wince, arm/gba, arm/embedded, arm/nds and
+ arm/darwin if fpu type not explicitly set }
+ if not(option.FPUSetExplicitly) and
+ ((target_info.system in [system_arm_wince,system_arm_gba,system_m68k_amiga,
+ system_m68k_linux,system_arm_nds,system_arm_embedded,system_arm_darwin])
+{$ifdef arm}
+ or (target_info.abi=abi_eabi)
+{$endif arm}
+ )
+{$ifdef arm}
+ or (init_settings.fputype=fpu_soft)
+{$endif arm}
+ then
+ begin
+{$ifdef cpufpemu}
+ include(init_settings.moduleswitches,cs_fp_emulation);
+ { cs_fp_emulation and fpu_soft are equal on arm }
+ init_settings.fputype:=fpu_soft;
+{$endif cpufpemu}
+ end;
+
+{$ifdef arm}
+{ set default cpu type to ARMv6 for Darwin unless specified otherwise }
+if (target_info.system=system_arm_darwin) then
+ begin
+ if not option.CPUSetExplicitly then
+ init_settings.cputype:=cpu_armv6;
+ if not option.OptCPUSetExplicitly then
+ init_settings.optimizecputype:=cpu_armv6;
+ end;
+{$endif arm}
+
+ { now we can define cpu and fpu type }
+ def_system_macro('CPU'+Cputypestr[init_settings.cputype]);
+
+ def_system_macro('FPU'+fputypestr[init_settings.fputype]);
+
+ if init_settings.fputype<>fpu_none then
+ begin
+{$if defined(i386)}
+ def_system_macro('FPC_HAS_TYPE_EXTENDED');
+{$endif}
+ def_system_macro('FPC_HAS_TYPE_SINGLE');
+ def_system_macro('FPC_HAS_TYPE_DOUBLE');
+{$if not defined(i386) and not defined(x86_64)}
+ def_system_macro('FPC_INCLUDE_SOFTWARE_INT64_TO_DOUBLE');
+{$endif}
+{$ifdef x86_64}
+ { win64 doesn't support the legacy fpu }
+ if target_info.system=system_x86_64_win64 then
+ undef_system_macro('FPC_HAS_TYPE_EXTENDED')
+ else
+ def_system_macro('FPC_HAS_TYPE_EXTENDED');
+{$endif}
+ end;
+ { Enable now for testing }
+{$ifndef DISABLE_TLS_DIRECTORY}
+ if target_info.system in systems_windows then
+ def_system_macro('FPC_USE_TLS_DIRECTORY');
+{$endif not DISABLE_TLS_DIRECTORY}
+
+{$ifdef TEST_WIN64_SEH}
+ if target_info.system=system_x86_64_win64 then
+ def_system_macro('FPC_USE_WIN64_SEH');
+{$endif TEST_WIN64_SEH}
+
+{$ifdef ARM}
+ { define FPC_DOUBLE_HILO_SWAPPED if needed to properly handle doubles in RTL }
+ if (init_settings.fputype in [fpu_fpa,fpu_fpa10,fpu_fpa11]) and
+ not(cs_fp_emulation in init_settings.moduleswitches) then
+ def_system_macro('FPC_DOUBLE_HILO_SWAPPED');
+{$endif ARM}
+
+ { Section smartlinking conflicts with import sections on Windows }
+ if GenerateImportSection and
+ (target_info.system in [system_i386_win32,system_x86_64_win64]) then
+ exclude(target_info.flags,tf_smartlink_sections);
+
+ if not LinkTypeSetExplicitly then
+ set_default_link_type;
+
+ { Default alignment settings,
+ 1. load the defaults for the target
+ 2. override with generic optimizer setting (little size)
+ 3. override with the user specified -Oa }
+ UpdateAlignment(init_settings.alignment,target_info.alignment);
+ if (cs_opt_size in current_settings.optimizerswitches) then
+ begin
+ init_settings.alignment.procalign:=1;
+ init_settings.alignment.jumpalign:=1;
+ init_settings.alignment.loopalign:=1;
+ end;
+
+ UpdateAlignment(init_settings.alignment,option.paraalignment);
+
+ set_system_macro('FPC_VERSION',version_nr);
+ set_system_macro('FPC_RELEASE',release_nr);
+ set_system_macro('FPC_PATCH',patch_nr);
+ set_system_macro('FPC_FULLVERSION',Format('%d%.02d%.02d',[StrToInt(version_nr),StrToInt(release_nr),StrToInt(patch_nr)]));
+
+ if not(target_info.system in systems_windows) then
+ def_system_macro('FPC_WIDESTRING_EQUAL_UNICODESTRING');
+
+ for i:=low(tfeature) to high(tfeature) do
+ if i in features then
+ def_system_macro('FPC_HAS_FEATURE_'+featurestr[i]);
+ option.free;
+ Option:=nil;
+
+ clearstack_pocalls := [pocall_cdecl,pocall_cppdecl,pocall_syscall,pocall_mwpascal];
+ cdecl_pocalls := [pocall_cdecl, pocall_cppdecl];
+ if (tf_safecall_clearstack in target_info.flags) then
+ begin
+ include (cdecl_pocalls, pocall_safecall);
+ include (clearstack_pocalls, pocall_safecall)
+ end;
+end;
+
+
+initialization
+ coption:=toption;
+finalization
+ if assigned(option) then
+ option.free;
+end.
diff --git a/closures/compiler/optloop.pas b/closures/compiler/optloop.pas
new file mode 100644
index 0000000000..5eb0228fb0
--- /dev/null
+++ b/closures/compiler/optloop.pas
@@ -0,0 +1,487 @@
+{
+ Loop optimization
+
+ Copyright (c) 2005 by Florian Klaempfl
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit optloop;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ node;
+
+ function unroll_loop(node : tnode) : tnode;
+ function OptimizeInductionVariables(node : tnode) : boolean;
+
+ implementation
+
+ uses
+ cutils,cclasses,
+ globtype,globals,constexp,
+ symdef,symsym,
+ defutil,
+ cpuinfo,
+ nutils,
+ nadd,nbas,nflw,ncon,ninl,ncal,nld,nmem,ncnv,
+ ncgmem,
+ pass_1,
+ optbase,optutils,
+ procinfo;
+
+ var
+ nodecount : aword;
+
+ function donodecount(var n: tnode; arg: pointer): foreachnoderesult;
+ begin
+ inc(nodecount);
+ result:=fen_false;
+ end;
+
+
+ { rough estimation how large the tree "node" is }
+ function countnodes(node : tnode) : aword;
+ begin
+ nodecount:=0;
+ foreachnodestatic(node,@donodecount,nil);
+ result:=nodecount;
+ end;
+
+
+ function number_unrolls(node : tnode) : cardinal;
+ begin
+{$ifdef i386}
+ { multiply by 2 for CPUs with a long pipeline }
+ if current_settings.cputype in [cpu_Pentium4] then
+ number_unrolls:=60 div countnodes(node)
+ else
+{$endif i386}
+ number_unrolls:=30 div countnodes(node);
+
+ if number_unrolls=0 then
+ number_unrolls:=1;
+ end;
+
+
+ function unroll_loop(node : tnode) : tnode;
+ var
+ unrolls,i : cardinal;
+ counts : qword;
+ unrollstatement,newforstatement : tstatementnode;
+ unrollblock : tblocknode;
+ begin
+ result:=nil;
+ if (cs_opt_size in current_settings.optimizerswitches) then
+ exit;
+ if not(node.nodetype in [forn]) then
+ exit;
+ unrolls:=number_unrolls(tfornode(node).t2);
+ if unrolls>1 then
+ begin
+ { number of executions known? }
+ if (tfornode(node).right.nodetype=ordconstn) and (tfornode(node).t1.nodetype=ordconstn) then
+ begin
+ if lnf_backward in tfornode(node).loopflags then
+ counts:=tordconstnode(tfornode(node).right).value-tordconstnode(tfornode(node).t1).value+1
+ else
+ counts:=tordconstnode(tfornode(node).t1).value-tordconstnode(tfornode(node).right).value+1;
+
+ { don't unroll more than we need }
+ if unrolls>counts then
+ unrolls:=counts;
+
+ { create block statement }
+ unrollblock:=internalstatements(unrollstatement);
+
+ { let's unroll (and rock of course) }
+ for i:=1 to unrolls do
+ begin
+ { create and insert copy of the statement block }
+ addstatement(unrollstatement,tfornode(node).t2.getcopy);
+
+ { set and insert entry label? }
+ if (counts mod unrolls<>0) and
+ ((counts mod unrolls)=unrolls-i) then
+ begin
+ tfornode(node).entrylabel:=clabelnode.create(cnothingnode.create,tlabelsym.create('$optunrol'));
+ addstatement(unrollstatement,tfornode(node).entrylabel);
+ end;
+
+ { for itself increases at the last iteration }
+ if i<unrolls then
+ begin
+ { insert incr/decrementation of counter var }
+ if lnf_backward in tfornode(node).loopflags then
+ addstatement(unrollstatement,
+ geninlinenode(in_dec_x,false,ccallparanode.create(tfornode(node).left.getcopy,nil)))
+ else
+ addstatement(unrollstatement,
+ geninlinenode(in_inc_x,false,ccallparanode.create(tfornode(node).left.getcopy,nil)));
+ end;
+ end;
+ { can we get rid of the for statement? }
+ if unrolls=counts then
+ begin
+ { create block statement }
+ result:=internalstatements(newforstatement);
+ { initial assignment }
+ addstatement(newforstatement,cassignmentnode.create(
+ tfornode(node).left.getcopy,tfornode(node).right.getcopy));
+ addstatement(newforstatement,unrollblock);
+ end;
+ end
+ else
+ begin
+ { unrolling is a little bit more tricky if we don't know the
+ loop count at compile time, but the solution is to use a jump table
+ which is indexed by "loop count mod unrolls" at run time and which
+ jumps then at the appropriate place inside the loop. Because
+ a module division is expensive, we can use only unroll counts dividable
+ by 2 }
+ case unrolls of
+ 1..2:
+ ;
+ 3:
+ unrolls:=2;
+ 4..7:
+ unrolls:=4;
+ { unrolls>4 already make no sense imo, but who knows (FK) }
+ 8..15:
+ unrolls:=8;
+ 16..31:
+ unrolls:=16;
+ 32..63:
+ unrolls:=32;
+ 64..$7fff:
+ unrolls:=64;
+ else
+ exit;
+ end;
+ { we don't handle this yet }
+ exit;
+ end;
+ if not(assigned(result)) then
+ begin
+ tfornode(node).t2.free;
+ tfornode(node).t2:=unrollblock;
+ end;
+ end;
+ end;
+
+ var
+ initcode,
+ calccode,
+ deletecode : tblocknode;
+ initcodestatements,
+ calccodestatements,
+ deletecodestatements: tstatementnode;
+ templist : tfplist;
+ inductionexprs : tfplist;
+ changedforloop,
+ containsnestedforloop : boolean;
+
+ function is_loop_invariant(loop : tnode;expr : tnode) : boolean;
+ begin
+ result:=is_constnode(expr);
+ case expr.nodetype of
+ loadn:
+ begin
+ if (pi_dfaavailable in current_procinfo.flags) and
+ assigned(loop.optinfo) and
+ assigned(expr.optinfo) then
+ { no aliasing? }
+ result:=not(tabstractvarsym(tloadnode(expr).symtableentry).addr_taken) and
+ { no definition in the loop? }
+ not(DFASetIn(loop.optinfo^.defsum,expr.optinfo^.index));
+ end;
+ vecn:
+ begin
+ result:=((tvecnode(expr).left.nodetype=loadn) or is_loop_invariant(loop,tvecnode(expr).left)) and
+ is_loop_invariant(loop,tvecnode(expr).right);
+ end;
+ typeconvn:
+ result:=is_loop_invariant(loop,ttypeconvnode(expr).left);
+ end;
+ end;
+
+
+ { checks if the strength of n can be recuded, arg is the tforloop being considered }
+ function dostrengthreductiontest(var n: tnode; arg: pointer): foreachnoderesult;
+
+ function findpreviousstrengthreduction : boolean;
+ var
+ i : longint;
+ begin
+ result:=false;
+ for i:=0 to inductionexprs.count-1 do
+ begin
+ { do we already maintain one expression? }
+ if tnode(inductionexprs[i]).isequal(n) then
+ begin
+ n.free;
+ case n.nodetype of
+ muln:
+ n:=ctemprefnode.create(ttempcreatenode(templist[i]));
+ vecn:
+ n:=ctypeconvnode.create_internal(cderefnode.create(ctemprefnode.create(
+ ttempcreatenode(templist[i]))),n.resultdef);
+ else
+ internalerror(200809211);
+ end;
+ result:=true;
+ exit;
+ end;
+ end;
+ end;
+
+
+ procedure CreateNodes;
+ begin
+ if not assigned(initcode) then
+ begin
+ initcode:=internalstatements(initcodestatements);
+ calccode:=internalstatements(calccodestatements);
+ deletecode:=internalstatements(deletecodestatements);
+ end;
+ end;
+
+ var
+ tempnode : ttempcreatenode;
+ dummy : longint;
+ begin
+ result:=fen_false;
+ case n.nodetype of
+ forn:
+ { inform for loop search routine, that it needs to search more deeply }
+ containsnestedforloop:=true;
+ muln:
+ begin
+ if (taddnode(n).right.nodetype=loadn) and
+ taddnode(n).right.isequal(tfornode(arg).left) and
+ { plain read of the loop variable? }
+ not(nf_write in taddnode(n).right.flags) and
+ not(nf_modify in taddnode(n).right.flags) and
+ is_loop_invariant(tfornode(arg),taddnode(n).left) and
+ { for now, we can handle only constant lower borders }
+ is_constnode(tfornode(arg).right) then
+ taddnode(n).swapleftright;
+
+ if (taddnode(n).left.nodetype=loadn) and
+ taddnode(n).left.isequal(tfornode(arg).left) and
+ { plain read of the loop variable? }
+ not(nf_write in taddnode(n).left.flags) and
+ not(nf_modify in taddnode(n).left.flags) and
+ is_loop_invariant(tfornode(arg),taddnode(n).right) and
+ { for now, we can handle only constant lower borders }
+ is_constnode(tfornode(arg).right) then
+ begin
+ changedforloop:=true;
+ { did we use the same expression before already? }
+ if not(findpreviousstrengthreduction) then
+ begin
+ tempnode:=ctempcreatenode.create(n.resultdef,n.resultdef.size,tt_persistent,
+ tstoreddef(n.resultdef).is_intregable or tstoreddef(n.resultdef).is_fpuregable);
+
+ templist.Add(tempnode);
+ inductionexprs.Add(n);
+ CreateNodes;
+
+ if lnf_backward in tfornode(arg).loopflags then
+ addstatement(calccodestatements,
+ geninlinenode(in_dec_x,false,
+ ccallparanode.create(ctemprefnode.create(tempnode),ccallparanode.create(taddnode(n).right.getcopy,nil))))
+ else
+ addstatement(calccodestatements,
+ geninlinenode(in_inc_x,false,
+ ccallparanode.create(ctemprefnode.create(tempnode),ccallparanode.create(taddnode(n).right.getcopy,nil))));
+
+ addstatement(initcodestatements,tempnode);
+ addstatement(initcodestatements,cassignmentnode.create(ctemprefnode.create(tempnode),
+ caddnode.create(muln,
+ caddnode.create(subn,tfornode(arg).right.getcopy,cordconstnode.create(1,tfornode(arg).right.resultdef,false)),
+ taddnode(n).right.getcopy)
+ )
+ );
+
+ { finally replace the node by a temp. ref }
+ n:=ctemprefnode.create(tempnode);
+
+ { ... and add a temp. release node }
+ addstatement(deletecodestatements,ctempdeletenode.create(tempnode));
+ end;
+ { set types }
+ do_firstpass(n);
+ result:=fen_norecurse_false;
+ end;
+ end;
+ vecn:
+ begin
+ { is the index the counter variable? }
+ if not(is_special_array(tvecnode(n).left.resultdef)) and
+ (tvecnode(n).right.isequal(tfornode(arg).left) or
+ { fpc usually creates a type cast to access an array }
+ ((tvecnode(n).right.nodetype=typeconvn) and
+ ttypeconvnode(tvecnode(n).right).left.isequal(tfornode(arg).left)
+ )
+ ) and
+ { plain read of the loop variable? }
+ not(nf_write in tvecnode(n).right.flags) and
+ not(nf_modify in tvecnode(n).right.flags) and
+ { direct array access? }
+ ((tvecnode(n).left.nodetype=loadn) or
+ { ... or loop invariant expression? }
+ is_loop_invariant(tfornode(arg),tvecnode(n).left)) and
+ { removing the multiplication is only worth the
+ effort if it's not a simple shift }
+ not(ispowerof2(tcgvecnode(n).get_mul_size,dummy)) then
+ begin
+ changedforloop:=true;
+ { did we use the same expression before already? }
+ if not(findpreviousstrengthreduction) then
+ begin
+ tempnode:=ctempcreatenode.create(voidpointertype,voidpointertype.size,tt_persistent,true);
+
+ templist.Add(tempnode);
+ inductionexprs.Add(n);
+ CreateNodes;
+
+ if lnf_backward in tfornode(arg).loopflags then
+ addstatement(calccodestatements,
+ geninlinenode(in_dec_x,false,
+ ccallparanode.create(ctemprefnode.create(tempnode),ccallparanode.create(
+ cordconstnode.create(tcgvecnode(n).get_mul_size,tfornode(arg).right.resultdef,false),nil))))
+ else
+ addstatement(calccodestatements,
+ geninlinenode(in_inc_x,false,
+ ccallparanode.create(ctemprefnode.create(tempnode),ccallparanode.create(
+ cordconstnode.create(tcgvecnode(n).get_mul_size,tfornode(arg).right.resultdef,false),nil))));
+
+ addstatement(initcodestatements,tempnode);
+ addstatement(initcodestatements,cassignmentnode.create(ctemprefnode.create(tempnode),
+ caddrnode.create(
+ cvecnode.create(tvecnode(n).left.getcopy,tfornode(arg).right.getcopy)
+ )
+ ));
+
+ { finally replace the node by a temp. ref }
+ n:=ctypeconvnode.create_internal(cderefnode.create(ctemprefnode.create(tempnode)),n.resultdef);
+
+ { ... and add a temp. release node }
+ addstatement(deletecodestatements,ctempdeletenode.create(tempnode));
+ end;
+ { set types }
+ do_firstpass(n);
+ result:=fen_norecurse_false;
+ end;
+ end;
+ end;
+ end;
+
+
+ function OptimizeInductionVariablesSingleForLoop(node : tnode) : tnode;
+ var
+ loopcode : tblocknode;
+ loopcodestatements,
+ newcodestatements : tstatementnode;
+ fornode : tfornode;
+ begin
+ result:=nil;
+ if node.nodetype<>forn then
+ exit;
+ templist:=TFPList.Create;
+ inductionexprs:=TFPList.Create;
+ initcode:=nil;
+ calccode:=nil;
+ deletecode:=nil;
+ initcodestatements:=nil;
+ calccodestatements:=nil;
+ deletecodestatements:=nil;
+ { find all expressions being candidates for strength reduction
+ and replace them }
+ foreachnodestatic(pm_postprocess,node,@dostrengthreductiontest,node);
+
+ { clue everything together }
+ if assigned(initcode) then
+ begin
+ do_firstpass(tnode(initcode));
+ do_firstpass(tnode(calccode));
+ do_firstpass(tnode(deletecode));
+ { create a new for node, the old one will be released by the compiler }
+ with tfornode(node) do
+ begin
+ fornode:=cfornode.create(left,right,t1,t2,lnf_backward in loopflags);
+ left:=nil;
+ right:=nil;
+ t1:=nil;
+ t2:=nil;
+ end;
+ node:=fornode;
+
+ loopcode:=internalstatements(loopcodestatements);
+ addstatement(loopcodestatements,calccode);
+ addstatement(loopcodestatements,tfornode(node).t2);
+ tfornode(node).t2:=loopcode;
+ do_firstpass(node);
+
+ result:=internalstatements(newcodestatements);
+ addstatement(newcodestatements,initcode);
+ addstatement(newcodestatements,node);
+ addstatement(newcodestatements,deletecode);
+ end;
+ templist.Free;
+ inductionexprs.Free;
+ end;
+
+
+ function iterforloops(var n: tnode; arg: pointer): foreachnoderesult;
+ var
+ hp : tnode;
+ begin
+ Result:=fen_false;
+ if n.nodetype=forn then
+ begin
+ { do we have DFA available? }
+ if pi_dfaavailable in current_procinfo.flags then
+ begin
+ CalcDefSum(n);
+ end;
+
+ containsnestedforloop:=false;
+ hp:=OptimizeInductionVariablesSingleForLoop(n);
+ if assigned(hp) then
+ begin
+ n.Free;
+ n:=hp;
+ end;
+ { can we avoid further searching? }
+ if not(containsnestedforloop) then
+ Result:=fen_norecurse_false;
+ end;
+ end;
+
+
+ function OptimizeInductionVariables(node : tnode) : boolean;
+ begin
+ changedforloop:=false;
+ foreachnodestatic(pm_postprocess,node,@iterforloops,nil);
+ Result:=changedforloop;
+ end;
+
+end.
diff --git a/closures/compiler/opttail.pas b/closures/compiler/opttail.pas
new file mode 100644
index 0000000000..b4adfa72d5
--- /dev/null
+++ b/closures/compiler/opttail.pas
@@ -0,0 +1,212 @@
+{
+ Tail recursion optimization
+
+ Copyright (c) 2006 by Florian Klaempfl
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit opttail;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ symdef,node;
+
+ procedure do_opttail(var n : tnode;p : tprocdef);
+
+ implementation
+
+ uses
+ globtype,
+ symconst,symsym,
+ defcmp,defutil,
+ nutils,nbas,nflw,ncal,nld,ncnv,
+ pass_1,
+ paramgr;
+
+ procedure do_opttail(var n : tnode;p : tprocdef);
+
+ var
+ labelnode : tlabelnode;
+
+ function find_and_replace_tailcalls(var n : tnode) : boolean;
+
+ var
+ usedcallnode : tcallnode;
+
+ function is_recursivecall(n : tnode) : boolean;
+ begin
+ result:=(n.nodetype=calln) and (tcallnode(n).procdefinition=p) and not(assigned(tcallnode(n).methodpointer));
+ if result then
+ usedcallnode:=tcallnode(n)
+ else
+ { obsolete type cast? }
+ result:=((n.nodetype=typeconvn) and (ttypeconvnode(n).convtype=tc_equal) and is_recursivecall(ttypeconvnode(n).left));
+ end;
+
+ function is_resultassignment(n : tnode) : boolean;
+ begin
+ result:=((n.nodetype=loadn) and (tloadnode(n).symtableentry=p.funcretsym)) or
+ ((n.nodetype=typeconvn) and (ttypeconvnode(n).convtype=tc_equal) and is_resultassignment(ttypeconvnode(n).left));
+ end;
+
+ var
+ calcnodes,
+ copynodes,
+ hp : tnode;
+ nodes,
+ calcstatements,
+ copystatements : tstatementnode;
+ paranode : tcallparanode;
+ tempnode : ttempcreatenode;
+ loadnode : tloadnode;
+ oldnodetree : tnode;
+ begin
+ { no tail call found and replaced so far }
+ result:=false;
+ if n=nil then
+ exit;
+ case n.nodetype of
+ statementn:
+ begin
+ hp:=n;
+ { search last node }
+ while assigned(tstatementnode(hp).right) do
+ hp:=tstatementnode(hp).right;
+ result:=find_and_replace_tailcalls(tstatementnode(hp).left);
+ end;
+ ifn:
+ begin
+ result:=find_and_replace_tailcalls(tifnode(n).right);
+ { avoid short bool eval here }
+ result:=find_and_replace_tailcalls(tifnode(n).t1) or result;
+ end;
+ assignn:
+ begin
+ if is_resultassignment(tbinarynode(n).left) and
+ is_recursivecall(tbinarynode(n).right) then
+ begin
+ { found one! }
+ {
+ writeln('tail recursion optimization for ',p.mangledname);
+ printnode(output,n);
+ }
+ { create assignments for all parameters }
+
+ { this is hairy to do because one parameter could be used to calculate another one, so
+ assign them first to temps and then add them }
+
+ calcnodes:=internalstatements(calcstatements);
+ copynodes:=internalstatements(copystatements);
+ paranode:=tcallparanode(usedcallnode.left);
+ while assigned(paranode) do
+ begin
+ tempnode:=ctempcreatenode.create(paranode.left.resultdef,paranode.left.resultdef.size,tt_persistent,true);
+ addstatement(calcstatements,tempnode);
+ addstatement(calcstatements,
+ cassignmentnode.create(
+ ctemprefnode.create(tempnode),
+ paranode.left
+ ));
+
+ { "cast" away const varspezs }
+ loadnode:=cloadnode.create(paranode.parasym,paranode.parasym.owner);
+ include(tloadnode(loadnode).loadnodeflags,loadnf_isinternal_ignoreconst);
+
+ addstatement(copystatements,
+ cassignmentnode.create(
+ loadnode,
+ ctemprefnode.create(tempnode)
+ ));
+ addstatement(copystatements,ctempdeletenode.create_normal_temp(tempnode));
+
+ { reused }
+ paranode.left:=nil;
+ paranode:=tcallparanode(paranode.right);
+ end;
+
+ oldnodetree:=n;
+ n:=internalstatements(nodes);
+
+ if assigned(usedcallnode.callinitblock) then
+ begin
+ addstatement(nodes,usedcallnode.callinitblock);
+ usedcallnode.callinitblock:=nil;
+ end;
+
+ addstatement(nodes,calcnodes);
+ addstatement(nodes,copynodes);
+
+ { create goto }
+ addstatement(nodes,cgotonode.create(labelnode.labsym));
+
+ if assigned(usedcallnode.callcleanupblock) then
+ begin
+ { callcleanupblock should contain only temp. node clean up }
+ checktreenodetypes(usedcallnode.callcleanupblock,
+ [tempdeleten,blockn,statementn,temprefn,nothingn]);
+ addstatement(nodes,usedcallnode.callcleanupblock);
+ usedcallnode.callcleanupblock:=nil;
+ end;
+
+ oldnodetree.free;
+
+ do_firstpass(n);
+ result:=true;
+ end;
+ end;
+ blockn:
+ result:=find_and_replace_tailcalls(tblocknode(n).left);
+ end;
+ end;
+
+ var
+ s : tstatementnode;
+ oldnodes : tnode;
+ i : longint;
+ labelsym : tlabelsym;
+ begin
+ { check if the parameters actually would support tail recursion elimination }
+ for i:=0 to p.paras.count-1 do
+ with tparavarsym(p.paras[i]) do
+ if (varspez in [vs_out,vs_var,vs_constref]) or
+ ((varspez=vs_const) and
+ (paramanager.push_addr_param(varspez,vardef,p.proccalloption)) or
+ { parameters requiring tables are too complicated to handle
+ and slow down things anyways so a tail recursion call
+ makes no sense
+ }
+ is_managed_type(vardef)) then
+ exit;
+
+ labelsym:=tlabelsym.create('$opttail');
+ labelnode:=clabelnode.create(cnothingnode.create,labelsym);
+ if find_and_replace_tailcalls(n) then
+ begin
+ oldnodes:=n;
+ n:=internalstatements(s);
+ addstatement(s,labelnode);
+ addstatement(s,oldnodes);
+ end
+ else
+ labelnode.free;
+ end;
+
+end.
+
diff --git a/closures/compiler/optutils.pas b/closures/compiler/optutils.pas
new file mode 100644
index 0000000000..2cca995efc
--- /dev/null
+++ b/closures/compiler/optutils.pas
@@ -0,0 +1,327 @@
+{
+ Helper routines for the optimizer
+
+ Copyright (c) 2007 by Florian Klaempfl
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit optutils;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ cclasses,
+ node;
+
+ type
+ { this implementation should be really improved,
+ its purpose is to find equal nodes }
+ TIndexedNodeSet = class(TFPList)
+ function Add(node : tnode) : boolean;
+ function Includes(node : tnode) : tnode;
+ function Remove(node : tnode) : boolean;
+ end;
+
+ procedure SetNodeSucessors(p : tnode);
+ procedure PrintDFAInfo(var f : text;p : tnode);
+ procedure PrintIndexedNodeSet(var f : text;s : TIndexedNodeSet);
+ { determines the optinfo.defsum field for the given node
+ this field contains a sum of all expressions defined by
+ all child expressions reachable through p
+ }
+ procedure CalcDefSum(p : tnode);
+
+ implementation
+
+ uses
+ verbose,
+ optbase,
+ nbas,nflw,nutils,nset;
+
+ function TIndexedNodeSet.Add(node : tnode) : boolean;
+ var
+ i : Integer;
+ p : tnode;
+ begin
+ node.allocoptinfo;
+ p:=Includes(node);
+ if assigned(p) then
+ begin
+ result:=false;
+ node.optinfo^.index:=p.optinfo^.index;
+ end
+ else
+ begin
+ i:=inherited Add(node);
+ node.optinfo^.index:=i;
+ result:=true;
+ end
+ end;
+
+
+ function TIndexedNodeSet.Includes(node : tnode) : tnode;
+ var
+ i : longint;
+ begin
+ for i:=0 to Count-1 do
+ if tnode(List^[i]).isequal(node) then
+ begin
+ result:=tnode(List^[i]);
+ exit;
+ end;
+ result:=nil;
+ end;
+
+
+ function TIndexedNodeSet.Remove(node : tnode) : boolean;
+ var
+ p : tnode;
+ begin
+ result:=false;
+ p:=Includes(node);
+ if assigned(p) then
+ begin
+ if inherited Remove(p)<>-1 then
+ result:=true;
+ end;
+ end;
+
+
+ procedure PrintIndexedNodeSet(var f : text;s : TIndexedNodeSet);
+ var
+ i : integer;
+ begin
+ for i:=0 to s.count-1 do
+ begin
+ writeln(f,'=============================== Node ',i,' ===============================');
+ printnode(f,tnode(s[i]));
+ writeln(f);
+ end;
+ end;
+
+
+ function PrintNodeDFA(var n: tnode; arg: pointer): foreachnoderesult;
+ begin
+ if assigned(n.optinfo) and ((n.optinfo^.life<>nil) or (n.optinfo^.use<>nil) or (n.optinfo^.def<>nil)) then
+ begin
+ write(text(arg^),nodetype2str[n.nodetype],'(',n.fileinfo.line,',',n.fileinfo.column,') Life: ');
+ PrintDFASet(text(arg^),n.optinfo^.life);
+ write(text(arg^),' Def: ');
+ PrintDFASet(text(arg^),n.optinfo^.def);
+ write(text(arg^),' Use: ');
+ PrintDFASet(text(arg^),n.optinfo^.use);
+ writeln(text(arg^));
+ end;
+ result:=fen_false;
+ end;
+
+
+ procedure PrintDFAInfo(var f : text;p : tnode);
+ begin
+ foreachnodestatic(pm_postprocess,p,@PrintNodeDFA,@f);
+ end;
+
+
+ procedure SetNodeSucessors(p : tnode);
+ var
+ Continuestack : TFPList;
+ Breakstack : TFPList;
+ { sets the successor nodes of a node tree block
+ returns the first node of the tree if it's a controll flow node }
+ function DoSet(p : tnode;succ : tnode) : tnode;
+ var
+ hp1,hp2 : tnode;
+ i : longint;
+ begin
+ result:=nil;
+ if p=nil then
+ exit;
+ case p.nodetype of
+ statementn:
+ begin
+ hp1:=p;
+ result:=p;
+ while assigned(hp1) do
+ begin
+ { does another statement follow? }
+ if assigned(tstatementnode(hp1).next) then
+ begin
+ hp2:=DoSet(tstatementnode(hp1).statement,tstatementnode(hp1).next);
+ if assigned(hp2) then
+ tstatementnode(hp1).successor:=hp2
+ else
+ tstatementnode(hp1).successor:=tstatementnode(hp1).next;
+ end
+ else
+ begin
+ hp2:=DoSet(tstatementnode(hp1).statement,succ);
+ if assigned(hp2) then
+ tstatementnode(hp1).successor:=hp2
+ else
+ tstatementnode(hp1).successor:=succ;
+ end;
+ hp1:=tstatementnode(hp1).next;
+ end;
+ end;
+ blockn:
+ begin
+ result:=p;
+ DoSet(tblocknode(p).statements,succ);
+ p.successor:=succ;
+ end;
+ forn:
+ begin
+ Breakstack.Add(succ);
+ Continuestack.Add(p);
+ result:=p;
+ { the successor of the last node of the for body is the for node itself }
+ DoSet(tfornode(p).t2,p);
+ Breakstack.Delete(Breakstack.Count-1);
+ Continuestack.Delete(Continuestack.Count-1);
+ p.successor:=succ;
+ end;
+ breakn:
+ begin
+ result:=p;
+ p.successor:=tnode(Breakstack.Last);
+ end;
+ continuen:
+ begin
+ result:=p;
+ p.successor:=tnode(Continuestack.Last);
+ end;
+ whilerepeatn:
+ begin
+ Breakstack.Add(succ);
+ Continuestack.Add(p);
+ result:=p;
+ { the successor of the last node of the while body is the while node itself }
+ DoSet(twhilerepeatnode(p).right,p);
+ p.successor:=succ;
+ Breakstack.Delete(Breakstack.Count-1);
+ Continuestack.Delete(Continuestack.Count-1);
+ end;
+ ifn:
+ begin
+ result:=p;
+ DoSet(tifnode(p).right,succ);
+ DoSet(tifnode(p).t1,succ);
+ p.successor:=succ;
+ end;
+ labeln:
+ begin
+ result:=p;
+ if assigned(tlabelnode(p).left) then
+ begin
+ DoSet(tlabelnode(p).left,succ);
+ p.successor:=tlabelnode(p).left;
+ end
+ else
+ p.successor:=succ;
+ end;
+ assignn:
+ begin
+ result:=p;
+ p.successor:=succ;
+ end;
+ goton:
+ begin
+ result:=p;
+ if not(assigned(tgotonode(p).labelnode)) then
+ internalerror(2007050701);
+ p.successor:=tgotonode(p).labelnode;
+ end;
+ exitn:
+ begin
+ result:=p;
+ p.successor:=nil;
+ end;
+ casen:
+ begin
+ result:=p;
+ DoSet(tcasenode(p).elseblock,succ);
+ for i:=0 to tcasenode(p).blocks.count-1 do
+ DoSet(pcaseblock(tcasenode(p).blocks[i])^.statement,succ);
+ p.successor:=succ;
+ end;
+ calln:
+ begin
+ { not sure if this is enough (FK) }
+ result:=p;
+ p.successor:=succ;
+ end;
+ inlinen:
+ begin
+ { not sure if this is enough (FK) }
+ result:=p;
+ p.successor:=succ;
+ end;
+ tempcreaten,
+ tempdeleten,
+ nothingn:
+ begin
+ result:=p;
+ p.successor:=succ;
+ end;
+ raisen:
+ begin
+ result:=p;
+ { raise never returns }
+ p.successor:=nil;
+ end;
+ withn,
+ tryexceptn,
+ tryfinallyn,
+ onn:
+ internalerror(2007050501);
+ end;
+ end;
+
+ begin
+ Breakstack:=TFPList.Create;
+ Continuestack:=TFPList.Create;
+ DoSet(p,nil);
+ Continuestack.Free;
+ Breakstack.Free;
+ end;
+
+ var
+ sum : TDFASet;
+
+ function adddef(var n: tnode; arg: pointer): foreachnoderesult;
+ begin
+ if assigned(n.optinfo) then
+ DFASetIncludeSet(sum,n.optinfo^.def);
+ Result:=fen_false;
+ end;
+
+
+ procedure CalcDefSum(p : tnode);
+ begin
+ p.allocoptinfo;
+ if not assigned(p.optinfo^.defsum) then
+ begin
+ sum:=nil;
+ foreachnodestatic(pm_postprocess,p,@adddef,nil);
+ p.optinfo^.defsum:=sum;
+ end;
+ end;
+
+end.
+
diff --git a/closures/compiler/optvirt.pas b/closures/compiler/optvirt.pas
new file mode 100644
index 0000000000..9646c1b172
--- /dev/null
+++ b/closures/compiler/optvirt.pas
@@ -0,0 +1,1181 @@
+{
+ Copyright (c) 2008 by Jonas Maebe
+
+ Virtual methods optimizations (devirtualization)
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit optvirt;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ globtype,
+ cclasses,
+ symtype,symdef,
+ wpobase;
+
+ type
+ { node in an inheritance tree, contains a link to the parent type (if any) and to all
+ child types
+ }
+ tinheritancetreenode = class
+ private
+ fdef: tobjectdef;
+ fparent: tinheritancetreenode;
+ fchilds: tfpobjectlist;
+ fcalledvmtmethods: tbitset;
+ finstantiated: boolean;
+
+ function getchild(index: longint): tinheritancetreenode;
+ public
+ constructor create(_parent: tinheritancetreenode; _def: tobjectdef; _instantiated: boolean);
+ { destroys both this node and all of its siblings }
+ destructor destroy; override;
+ function childcount: longint;
+ function haschilds: boolean;
+ property childs[index: longint]: tinheritancetreenode read getchild;
+ property parent: tinheritancetreenode read fparent;
+ property def: tobjectdef read fdef;
+ property instantiated: boolean read finstantiated write finstantiated;
+ { if def is not yet a child of this node, add it. In all cases, return node containing
+ this def (either new or existing one
+ }
+ function maybeaddchild(_def: tobjectdef; _instantiated: boolean): tinheritancetreenode;
+ function findchild(_def: tobjectdef): tinheritancetreenode;
+ end;
+
+
+ tinheritancetreecallback = procedure(node: tinheritancetreenode; arg: pointer) of object;
+
+ tinheritancetree = class
+ private
+ { just a regular node with parent = nil }
+ froots: tinheritancetreenode;
+
+ classrefdefs: tfpobjectlist;
+
+ procedure foreachnodefromroot(root: tinheritancetreenode; proctocall: tinheritancetreecallback; arg: pointer);
+ function registerinstantiatedobjectdefrecursive(def: tobjectdef; instantiated: boolean): tinheritancetreenode;
+ procedure markvmethods(node: tinheritancetreenode; p: pointer);
+ procedure printobjectvmtinfo(node: tinheritancetreenode; arg: pointer);
+ procedure addcalledvmtentries(node: tinheritancetreenode; arg: pointer);
+
+ function getnodefordef(def: tobjectdef): tinheritancetreenode;
+ public
+ constructor create;
+ destructor destroy; override;
+ { adds an objectdef (the def itself, and all of its parents that do not yet exist) to
+ the tree, and returns the leaf node
+ }
+ procedure registerinstantiatedobjdef(def: tdef);
+ procedure registerinstantiatedclassrefdef(def: tdef);
+ procedure registercalledvmtentries(entries: tcalledvmtentries);
+ procedure checkforclassrefinheritance(def: tdef);
+ procedure foreachnode(proctocall: tinheritancetreecallback; arg: pointer);
+ procedure foreachleafnode(proctocall: tinheritancetreecallback; arg: pointer);
+ procedure optimizevirtualmethods;
+ procedure printvmtinfo;
+ end;
+
+
+ { devirtualisation information for a class }
+
+ tclassdevirtinfo = class(tfphashobject)
+ private
+ { array (indexed by vmt entry nr) of replacement statically callable method names }
+ fstaticmethodnames: tfplist;
+ { is this class instantiated by the program? }
+ finstantiated: boolean;
+ function isstaticvmtentry(vmtindex: longint; out replacementname: pshortstring): boolean;
+ public
+ constructor create(hashobjectlist:tfphashobjectlist;const n: shortstring; instantiated: boolean);
+ destructor destroy; override;
+
+ property instantiated: boolean read finstantiated;
+
+ procedure addstaticmethod(vmtindex: longint; const replacementname: shortstring);
+ end;
+
+
+ { devirtualisation information for all classes in a unit }
+
+ tunitdevirtinfo = class(tfphashobject)
+ private
+ { hashtable of classes }
+ fclasses: tfphashobjectlist;
+ public
+ constructor create(hashobjectlist:tfphashobjectlist;const n: shortstring);reintroduce;
+ destructor destroy; override;
+
+ function addclass(const n: shortstring; instantiated: boolean): tclassdevirtinfo;
+ function findclass(const n: shortstring): tclassdevirtinfo;
+ end;
+
+ { devirtualisation information for all units in a program }
+
+ { tprogdevirtinfo }
+
+ tprogdevirtinfo = class(twpodevirtualisationhandler)
+ private
+ { hashtable of tunitdevirtinfo (which contain tclassdevirtinfo) }
+ funits: tfphashobjectlist;
+
+ procedure converttreenode(node: tinheritancetreenode; arg: pointer);
+ function addunitifnew(const n: shortstring): tunitdevirtinfo;
+ function findunit(const n: shortstring): tunitdevirtinfo;
+ function getstaticname(forvmtentry: boolean; objdef, procdef: tdef; out staticname: string): boolean;
+ procedure documentformat(writer: twposectionwriterintf);
+ public
+ constructor create; override;
+ destructor destroy; override;
+
+ class function getwpotype: twpotype; override;
+ class function generatesinfoforwposwitches: twpoptimizerswitches; override;
+ class function performswpoforswitches: twpoptimizerswitches; override;
+ class function sectionname: shortstring; override;
+
+ { information collection }
+ procedure constructfromcompilerstate; override;
+ procedure storewpofilesection(writer: twposectionwriterintf); override;
+
+ { information providing }
+ procedure loadfromwpofilesection(reader: twposectionreaderintf); override;
+ function staticnameforcallingvirtualmethod(objdef, procdef: tdef; out staticname: string): boolean; override;
+ function staticnameforvmtentry(objdef, procdef: tdef; out staticname: string): boolean; override;
+
+ end;
+
+
+ implementation
+
+ uses
+ cutils,
+ fmodule,
+ symconst,
+ symbase,
+ symtable,
+ nobj,
+ verbose;
+
+ const
+ DEVIRT_SECTION_NAME = 'contextinsensitive_devirtualization';
+
+ { *************************** tinheritancetreenode ************************* }
+
+ constructor tinheritancetreenode.create(_parent: tinheritancetreenode; _def: tobjectdef; _instantiated: boolean);
+ begin
+ fparent:=_parent;
+ fdef:=_def;
+ finstantiated:=_instantiated;
+ if assigned(_def) then
+ fcalledvmtmethods:=tbitset.create(_def.vmtentries.count);
+ end;
+
+
+ destructor tinheritancetreenode.destroy;
+ begin
+ { fchilds owns its members, so it will free them too }
+ fchilds.free;
+ fcalledvmtmethods.free;
+ inherited destroy;
+ end;
+
+
+ function tinheritancetreenode.childcount: longint;
+ begin
+ if assigned(fchilds) then
+ result:=fchilds.count
+ else
+ result:=0;
+ end;
+
+
+ function tinheritancetreenode.haschilds: boolean;
+ begin
+ result:=assigned(fchilds)
+ end;
+
+
+ function tinheritancetreenode.getchild(index: longint): tinheritancetreenode;
+ begin
+ result:=tinheritancetreenode(fchilds[index]);
+ end;
+
+
+ function tinheritancetreenode.maybeaddchild(_def: tobjectdef; _instantiated: boolean): tinheritancetreenode;
+ begin
+ { sanity check }
+ if assigned(_def.childof) then
+ begin
+ if (_def.childof<>def) then
+ internalerror(2008092201);
+ end
+ else if assigned(fparent) then
+ internalerror(2008092202);
+
+ if not assigned(fchilds) then
+ fchilds:=tfpobjectlist.create(true);
+ { def already a child -> return }
+ result:=findchild(_def);
+ if assigned(result) then
+ result.finstantiated:=result.finstantiated or _instantiated
+ else
+ begin
+ { not found, add new child }
+ result:=tinheritancetreenode.create(self,_def,_instantiated);
+ fchilds.add(result);
+ end;
+ end;
+
+
+ function tinheritancetreenode.findchild(_def: tobjectdef): tinheritancetreenode;
+ var
+ i: longint;
+ begin
+ result:=nil;
+ if assigned(fchilds) then
+ for i := 0 to fchilds.count-1 do
+ if (tinheritancetreenode(fchilds[i]).def=_def) then
+ begin
+ result:=tinheritancetreenode(fchilds[i]);
+ break;
+ end;
+ end;
+
+ { *************************** tinheritancetree ************************* }
+
+ constructor tinheritancetree.create;
+ begin
+ froots:=tinheritancetreenode.create(nil,nil,false);
+ classrefdefs:=tfpobjectlist.create(false);
+ end;
+
+
+ destructor tinheritancetree.destroy;
+ begin
+ froots.free;
+ classrefdefs.free;
+ inherited destroy;
+ end;
+
+
+ function tinheritancetree.registerinstantiatedobjectdefrecursive(def: tobjectdef; instantiated: boolean): tinheritancetreenode;
+ begin
+ if assigned(def.childof) then
+ begin
+ { recursively add parent, of which we have no info about whether or not it is
+ instantiated at this point -> default to false (will be overridden by "true"
+ if this class is instantioted, since then registerinstantiatedobjdef() will
+ be called for this class as well)
+ }
+ result:=registerinstantiatedobjectdefrecursive(def.childof,false);
+ { and add ourselves to the parent }
+ result:=result.maybeaddchild(def,instantiated);
+ end
+ else
+ { add ourselves to the roots }
+ result:=froots.maybeaddchild(def,instantiated);
+ end;
+
+
+ procedure tinheritancetree.registerinstantiatedobjdef(def: tdef);
+ begin
+ { add the def }
+ if (def.typ=objectdef) then
+ registerinstantiatedobjectdefrecursive(tobjectdef(def),true)
+ else
+ internalerror(2008092401);
+ end;
+
+
+ procedure tinheritancetree.registerinstantiatedclassrefdef(def: tdef);
+ begin
+ { queue for later checking (these are the objectdefs
+ to which the classrefdefs point) }
+ if (def.typ=objectdef) then
+ classrefdefs.add(def)
+ else
+ internalerror(2008101401);
+ end;
+
+
+ function tinheritancetree.getnodefordef(def: tobjectdef): tinheritancetreenode;
+ begin
+ if assigned(def.childof) then
+ begin
+ result:=getnodefordef(def.childof);
+ if assigned(result) then
+ result:=result.findchild(def);
+ end
+ else
+ result:=froots.findchild(def);
+ end;
+
+
+ procedure tinheritancetree.registercalledvmtentries(entries: tcalledvmtentries);
+ var
+ node: tinheritancetreenode;
+ begin
+ node:=getnodefordef(tobjectdef(entries.objdef));
+ { it's possible that no instance of this class or its descendants are
+ instantiated
+ }
+ if not assigned(node) then
+ exit;
+ { now mark these methods as (potentially) called for this type and for
+ all of its descendants
+ }
+ addcalledvmtentries(node,entries.calledentries);
+ foreachnodefromroot(node,@addcalledvmtentries,entries.calledentries);
+ end;
+
+
+ procedure tinheritancetree.checkforclassrefinheritance(def: tdef);
+ var
+ i: longint;
+ begin
+ if (def.typ=objectdef) then
+ begin
+{$ifdef debug_devirt}
+ write(' Checking for classrefdef inheritance of ',def.typename);
+{$endif debug_devirt}
+ for i:=0 to classrefdefs.count-1 do
+ if tobjectdef(def).is_related(tobjectdef(classrefdefs[i])) then
+ begin
+{$ifdef debug_devirt}
+ writeln('... Found: inherits from Class Of ',tobjectdef(classrefdefs[i]).typename);
+{$endif debug_devirt}
+ registerinstantiatedobjdef(def);
+ exit;
+ end;
+{$ifdef debug_devirt}
+ writeln('... Not found!');
+{$endif debug_devirt}
+ end;
+ end;
+
+
+ procedure tinheritancetree.foreachnodefromroot(root: tinheritancetreenode; proctocall: tinheritancetreecallback; arg: pointer);
+
+ procedure process(const node: tinheritancetreenode);
+ var
+ i: longint;
+ begin
+ for i:=0 to node.childcount-1 do
+ if node.childs[i].haschilds then
+ begin
+ proctocall(node.childs[i],arg);
+ process(node.childs[i])
+ end
+ else
+ proctocall(node.childs[i],arg);
+ end;
+
+ begin
+ process(root);
+ end;
+
+
+ procedure tinheritancetree.foreachnode(proctocall: tinheritancetreecallback; arg: pointer);
+ begin
+ foreachnodefromroot(froots,proctocall,arg);
+ end;
+
+
+ procedure tinheritancetree.foreachleafnode(proctocall: tinheritancetreecallback; arg: pointer);
+
+ procedure process(const node: tinheritancetreenode);
+ var
+ i: longint;
+ begin
+ for i:=0 to node.childcount-1 do
+ if node.childs[i].haschilds then
+ process(node.childs[i])
+ else
+ proctocall(node.childs[i],arg);
+ end;
+
+ begin
+ process(froots);
+ end;
+
+
+ procedure tinheritancetree.markvmethods(node: tinheritancetreenode; p: pointer);
+ var
+ currnode: tinheritancetreenode;
+ pd: tprocdef;
+ i: longint;
+ makeallvirtual: boolean;
+ begin
+ {$IFDEF DEBUG_DEVIRT}
+ writeln('processing leaf node ',node.def.typename);
+ {$ENDIF}
+ { todo: also process interfaces (ImplementedInterfaces) }
+ if (node.def.vmtentries.count=0) then
+ exit;
+ { process all vmt entries for this class/object }
+ for i:=0 to node.def.vmtentries.count-1 do
+ begin
+ currnode:=node;
+ { extra tprocdef(tobject(..)) typecasts so that -CR can catch
+ errors in case the vmtentries are not properly (re)deref'd }
+ pd:=tprocdef(tobject(pvmtentry(currnode.def.vmtentries[i])^.procdef));
+ { abstract methods cannot be called directly }
+ if (po_abstractmethod in pd.procoptions) then
+ continue;
+ {$IFDEF DEBUG_DEVIRT}
+ writeln(' method ',pd.typename);
+ {$ENDIF}
+ { Now mark all virtual methods static that are the same in parent
+ classes as in this instantiated child class (only instantiated
+ classes can be leaf nodes, since only instantiated classes were
+ added to the tree).
+ If a first child does not override a parent method while a
+ a second one does, the first will mark it as statically
+ callable, but the second will set it to not statically callable.
+ In the opposite situation, the first will mark it as not
+ statically callable and the second will leave it alone.
+ }
+ makeallvirtual:=false;
+ repeat
+ if { stop when this method does not exist in a parent }
+ (currnode.def.vmtentries.count<=i) then
+ break;
+
+ if not assigned(currnode.def.vmcallstaticinfo) then
+ currnode.def.vmcallstaticinfo:=allocmem(currnode.def.vmtentries.count*sizeof(tvmcallstatic));
+ { if this method cannot be called, we can just mark it as
+ unreachable. This will cause its static name to be set to
+ FPC_ABSTRACTERROR later on. Exception: published methods are
+ always reachable (via RTTI).
+ }
+ if (pd.visibility<>vis_published) and
+ not(currnode.fcalledvmtmethods.isset(i)) then
+ begin
+ currnode.def.vmcallstaticinfo^[i]:=vmcs_unreachable;
+ currnode:=currnode.parent;
+ end
+ { same procdef as in all instantiated childs? (yes or don't know) }
+ else if (currnode.def.vmcallstaticinfo^[i] in [vmcs_default,vmcs_yes]) then
+ begin
+ { methods in uninstantiated classes can be made static if
+ they are the same in all instantiated derived classes
+ }
+ if ((pvmtentry(currnode.def.vmtentries[i])^.procdef=pd) or
+ (not currnode.instantiated and
+ (currnode.def.vmcallstaticinfo^[i]=vmcs_default))) and
+ not makeallvirtual then
+ begin
+ {$IFDEF DEBUG_DEVIRT}
+ writeln(' marking as static for ',currnode.def.typename);
+ {$ENDIF}
+ currnode.def.vmcallstaticinfo^[i]:=vmcs_yes;
+ { this is in case of a non-instantiated parent of an instantiated child:
+ the method declared in the child will always be called here
+ }
+ pvmtentry(currnode.def.vmtentries[i])^.procdef:=pd;
+ end
+ else
+ begin
+ {$IFDEF DEBUG_DEVIRT}
+ writeln(' marking as non-static for ',currnode.def.typename);
+ {$ENDIF}
+ { this vmt entry must also remain virtual for all parents }
+ makeallvirtual:=true;
+ currnode.def.vmcallstaticinfo^[i]:=vmcs_no;
+ end;
+ currnode:=currnode.parent;
+ end
+ else if (currnode.def.vmcallstaticinfo^[i]=vmcs_no) then
+ begin
+ {$IFDEF DEBUG_DEVIRT}
+ writeln(' not processing parents, already non-static for ',currnode.def.typename);
+ {$ENDIF}
+ { parents are already set to vmcs_no, so no need to continue }
+ currnode:=nil;
+ end
+ else
+ currnode:=currnode.parent;
+ until not assigned(currnode) or
+ not assigned(currnode.def);
+ end;
+ end;
+
+
+ procedure tinheritancetree.optimizevirtualmethods;
+ begin
+ foreachleafnode(@markvmethods,nil);
+ end;
+
+
+ procedure tinheritancetree.printobjectvmtinfo(node: tinheritancetreenode; arg: pointer);
+ var
+ i,
+ totaldevirtualised,
+ totalvirtual,
+ totalunreachable: ptrint;
+ begin
+ totaldevirtualised:=0;
+ totalvirtual:=0;
+ totalunreachable:=0;
+ writeln(node.def.typename);
+ if (node.def.vmtentries.count=0) then
+ begin
+ writeln(' No virtual methods!');
+ exit;
+ end;
+ for i:=0 to node.def.vmtentries.count-1 do
+ if (po_virtualmethod in pvmtentry(node.def.vmtentries[i])^.procdef.procoptions) then
+ begin
+ inc(totalvirtual);
+ if (node.def.vmcallstaticinfo^[i]=vmcs_yes) then
+ begin
+ inc(totaldevirtualised);
+ writeln(' Devirtualised: ',pvmtentry(node.def.vmtentries[i])^.procdef.typename);
+ end
+ else if (node.def.vmcallstaticinfo^[i]=vmcs_unreachable) then
+ begin
+ inc(totalunreachable);
+ writeln(' Unreachable: ',pvmtentry(node.def.vmtentries[i])^.procdef.typename);
+ end;
+ end;
+ writeln('Total devirtualised/unreachable/all: ',totaldevirtualised,'/',totalunreachable,'/',totalvirtual);
+ writeln;
+ end;
+
+
+ procedure tinheritancetree.addcalledvmtentries(node: tinheritancetreenode; arg: pointer);
+ var
+ vmtentries: tbitset absolute arg;
+ begin
+ node.fcalledvmtmethods.addset(vmtentries);
+ end;
+
+
+ procedure tinheritancetree.printvmtinfo;
+ begin
+ foreachnode(@printobjectvmtinfo,nil);
+ end;
+
+
+ { helper routines: decompose an object & procdef combo into a unitname, class name and vmtentry number
+ (unit name where the objectdef is declared, class name of the objectdef, vmtentry number of the
+ procdef -- procdef does not necessarily belong to objectdef, it may also belong to a descendant
+ or parent)
+ }
+
+ procedure defunitclassname(objdef: tobjectdef; out unitname, classname: pshortstring);
+ const
+ mainprogname: string[2] = 'P$';
+ var
+ mainsymtab,
+ objparentsymtab : tsymtable;
+ begin
+ objparentsymtab:=objdef.symtable;
+ mainsymtab:=objparentsymtab.defowner.owner;
+ { main symtable must be static or global }
+ if not(mainsymtab.symtabletype in [staticsymtable,globalsymtable]) then
+ internalerror(200204175);
+ if (TSymtable(main_module.localsymtable)=mainsymtab) and
+ (not main_module.is_unit) then
+ { same convention as for mangled names }
+ unitname:=@mainprogname
+ else
+ unitname:=mainsymtab.name;
+ classname:=tobjectdef(objparentsymtab.defowner).objname;
+ end;
+
+
+ procedure defsdecompose(objdef: tobjectdef; procdef: tprocdef; out unitname, classname: pshortstring; out vmtentry: longint);
+ begin
+ defunitclassname(objdef,unitname,classname);
+ vmtentry:=procdef.extnumber;
+ { if it's $ffff, this is not a valid virtual method }
+ if (vmtentry=$ffff) then
+ internalerror(2008100509);
+ end;
+
+
+ { tclassdevirtinfo }
+
+ constructor tclassdevirtinfo.create(hashobjectlist:tfphashobjectlist;const n: shortstring; instantiated: boolean);
+ begin
+ inherited create(hashobjectlist,n);
+ finstantiated:=instantiated;
+ fstaticmethodnames:=tfplist.create;
+ end;
+
+ destructor tclassdevirtinfo.destroy;
+ var
+ i: longint;
+ begin
+ for i:=0 to fstaticmethodnames.count-1 do
+ if assigned(fstaticmethodnames[i]) then
+ freemem(fstaticmethodnames[i]);
+ fstaticmethodnames.free;
+ inherited destroy;
+ end;
+
+ procedure tclassdevirtinfo.addstaticmethod(vmtindex: longint;
+ const replacementname: shortstring);
+ begin
+ if (vmtindex>=fstaticmethodnames.count) then
+ fstaticmethodnames.Count:=vmtindex+10;
+ fstaticmethodnames[vmtindex]:=stringdup(replacementname);
+ end;
+
+ function tclassdevirtinfo.isstaticvmtentry(vmtindex: longint; out
+ replacementname: pshortstring): boolean;
+ begin
+ result:=false;
+ if (vmtindex>=fstaticmethodnames.count) then
+ exit;
+
+ replacementname:=fstaticmethodnames[vmtindex];
+ result:=assigned(replacementname);
+ end;
+
+ { tunitdevirtinfo }
+
+ constructor tunitdevirtinfo.create(hashobjectlist:tfphashobjectlist;const n: shortstring);
+ begin
+ inherited create(hashobjectlist,n);
+ fclasses:=tfphashobjectlist.create(true);
+ end;
+
+ destructor tunitdevirtinfo.destroy;
+ begin
+ fclasses.free;
+ inherited destroy;
+ end;
+
+ function tunitdevirtinfo.addclass(const n: shortstring; instantiated: boolean): tclassdevirtinfo;
+ begin
+ result:=findclass(n);
+ { can't have two classes with the same name in a single unit }
+ if assigned(result) then
+ internalerror(2008100501);
+ result:=tclassdevirtinfo.create(fclasses,n,instantiated);
+ end;
+
+ function tunitdevirtinfo.findclass(const n: shortstring): tclassdevirtinfo;
+ begin
+ result:=tclassdevirtinfo(fclasses.find(n));
+ end;
+
+
+ { tprogdevirtinfo }
+
+ procedure tprogdevirtinfo.converttreenode(node: tinheritancetreenode; arg: pointer);
+ var
+ i: longint;
+ unitid, classid: pshortstring;
+ unitdevirtinfo: tunitdevirtinfo;
+ classdevirtinfo: tclassdevirtinfo;
+ begin
+ if (not node.instantiated) and
+ (node.def.vmtentries.count=0) then
+ exit;
+ { always add a class entry for an instantiated class, so we can
+ fill the vmt's of non-instantiated classes with calls to
+ FPC_ABSTRACTERROR during the optimisation phase
+ }
+ defunitclassname(node.def,unitid,classid);
+ unitdevirtinfo:=addunitifnew(unitid^);
+ classdevirtinfo:=unitdevirtinfo.addclass(classid^,node.instantiated);
+ if (node.def.vmtentries.count=0) then
+ exit;
+ for i:=0 to node.def.vmtentries.count-1 do
+ if (po_virtualmethod in pvmtentry(node.def.vmtentries[i])^.procdef.procoptions) then
+ case node.def.vmcallstaticinfo^[i] of
+ vmcs_yes:
+ begin
+ { add info about devirtualised vmt entry }
+ classdevirtinfo.addstaticmethod(i,pvmtentry(node.def.vmtentries[i])^.procdef.mangledname);
+ end;
+ vmcs_unreachable:
+ begin
+ { static reference to FPC_ABSTRACTERROR }
+ classdevirtinfo.addstaticmethod(i,'FPC_ABSTRACTERROR');
+ end;
+ end;
+ end;
+
+
+ constructor tprogdevirtinfo.create;
+ begin
+ inherited create;
+ end;
+
+
+ destructor tprogdevirtinfo.destroy;
+ begin
+ funits.free;
+ inherited destroy;
+ end;
+
+
+ class function tprogdevirtinfo.getwpotype: twpotype;
+ begin
+ result:=wpo_devirtualization_context_insensitive;
+ end;
+
+
+ class function tprogdevirtinfo.generatesinfoforwposwitches: twpoptimizerswitches;
+ begin
+ result:=[cs_wpo_devirtualize_calls,cs_wpo_optimize_vmts];
+ end;
+
+
+ class function tprogdevirtinfo.performswpoforswitches: twpoptimizerswitches;
+ begin
+ result:=[cs_wpo_devirtualize_calls,cs_wpo_optimize_vmts];
+ end;
+
+
+ class function tprogdevirtinfo.sectionname: shortstring;
+ begin
+ result:=DEVIRT_SECTION_NAME;
+ end;
+
+
+ procedure tprogdevirtinfo.constructfromcompilerstate;
+ var
+ hp: tmodule;
+ i: longint;
+ inheritancetree: tinheritancetree;
+ begin
+ { register all instantiated class/object types }
+ hp:=tmodule(loaded_units.first);
+ while assigned(hp) do
+ begin
+ if assigned(hp.wpoinfo.createdobjtypes) then
+ for i:=0 to hp.wpoinfo.createdobjtypes.count-1 do
+ tdef(hp.wpoinfo.createdobjtypes[i]).register_created_object_type;
+ if assigned(hp.wpoinfo.createdclassrefobjtypes) then
+ for i:=0 to hp.wpoinfo.createdclassrefobjtypes.count-1 do
+ tobjectdef(hp.wpoinfo.createdclassrefobjtypes[i]).register_created_classref_type;
+ if assigned(hp.wpoinfo.maybecreatedbyclassrefdeftypes) then
+ for i:=0 to hp.wpoinfo.maybecreatedbyclassrefdeftypes.count-1 do
+ tobjectdef(hp.wpoinfo.maybecreatedbyclassrefdeftypes[i]).register_maybe_created_object_type;
+ hp:=tmodule(hp.next);
+ end;
+ inheritancetree:=tinheritancetree.create;
+
+ { add all constructed class/object types to the tree }
+{$IFDEF DEBUG_DEVIRT}
+ writeln('constructed object/class/classreftypes in ',current_module.realmodulename^);
+{$ENDIF}
+ for i := 0 to current_module.wpoinfo.createdobjtypes.count-1 do
+ begin
+ inheritancetree.registerinstantiatedobjdef(tdef(current_module.wpoinfo.createdobjtypes[i]));
+{$IFDEF DEBUG_DEVIRT}
+ write(' ',tdef(current_module.wpoinfo.createdobjtypes[i]).GetTypeName);
+{$ENDIF}
+ case tdef(current_module.wpoinfo.createdobjtypes[i]).typ of
+ objectdef:
+ case tobjectdef(current_module.wpoinfo.createdobjtypes[i]).objecttype of
+ odt_object:
+{$IFDEF DEBUG_DEVIRT}
+ writeln(' (object)')
+{$ENDIF}
+ ;
+ odt_class:
+{$IFDEF DEBUG_DEVIRT}
+ writeln(' (class)')
+{$ENDIF}
+ ;
+ else
+ internalerror(2008092101);
+ end;
+ else
+ internalerror(2008092102);
+ end;
+ end;
+
+ { register all instantiated classrefdefs with the tree }
+ for i := 0 to current_module.wpoinfo.createdclassrefobjtypes.count-1 do
+ begin
+ inheritancetree.registerinstantiatedclassrefdef(tdef(current_module.wpoinfo.createdclassrefobjtypes[i]));
+{$IFDEF DEBUG_DEVIRT}
+ write(' Class Of ',tdef(current_module.wpoinfo.createdclassrefobjtypes[i]).GetTypeName);
+{$ENDIF}
+ case tdef(current_module.wpoinfo.createdclassrefobjtypes[i]).typ of
+ objectdef:
+{$IFDEF DEBUG_DEVIRT}
+ writeln(' (classrefdef)')
+{$ENDIF}
+ ;
+ else
+ internalerror(2008101101);
+ end;
+ end;
+
+
+ { now add all objectdefs that are referred somewhere (via a
+ loadvmtaddr node) and that are derived from an instantiated
+ classrefdef to the tree (as they can, in theory, all
+ be instantiated as well)
+ }
+ for i := 0 to current_module.wpoinfo.maybecreatedbyclassrefdeftypes.count-1 do
+ begin
+ inheritancetree.checkforclassrefinheritance(tdef(current_module.wpoinfo.maybecreatedbyclassrefdeftypes[i]));
+{$IFDEF DEBUG_DEVIRT}
+ write(' Class Of ',tdef(current_module.wpoinfo.maybecreatedbyclassrefdeftypes[i]).GetTypeName);
+{$ENDIF}
+ case tdef(current_module.wpoinfo.maybecreatedbyclassrefdeftypes[i]).typ of
+ objectdef:
+{$IFDEF DEBUG_DEVIRT}
+ writeln(' (classrefdef)')
+{$ENDIF}
+ ;
+ else
+ internalerror(2008101101);
+ end;
+ end;
+
+ { add info about called virtual methods }
+ hp:=tmodule(loaded_units.first);
+ while assigned(hp) do
+ begin
+ if assigned(hp.wpoinfo.calledvmtentries) then
+ for i:=0 to hp.wpoinfo.calledvmtentries.count-1 do
+ inheritancetree.registercalledvmtentries(tcalledvmtentries(hp.wpoinfo.calledvmtentries[i]));
+ hp:=tmodule(hp.next);
+ end;
+
+
+ inheritancetree.optimizevirtualmethods;
+{$ifdef DEBUG_DEVIRT}
+ inheritancetree.printvmtinfo;
+{$endif DEBUG_DEVIRT}
+ inheritancetree.foreachnode(@converttreenode,nil);
+ inheritancetree.free;
+ end;
+
+
+ function tprogdevirtinfo.addunitifnew(const n: shortstring): tunitdevirtinfo;
+ begin
+ if assigned(funits) then
+ result:=findunit(n)
+ else
+ begin
+ funits:=tfphashobjectlist.create;
+ result:=nil;
+ end;
+ if not assigned(result) then
+ begin
+ result:=tunitdevirtinfo.create(funits,n);
+ end;
+ end;
+
+
+ function tprogdevirtinfo.findunit(const n: shortstring): tunitdevirtinfo;
+ begin
+ result:=tunitdevirtinfo(funits.find(n));
+ end;
+
+
+ procedure tprogdevirtinfo.loadfromwpofilesection(reader: twposectionreaderintf);
+ var
+ unitid,
+ classid,
+ vmtentryname: string;
+ vmttype: string[15];
+ vmtentrynrstr: string[7];
+ classinstantiated: string[1];
+ vmtentry, error: longint;
+ unitdevirtinfo: tunitdevirtinfo;
+ classdevirtinfo: tclassdevirtinfo;
+ instantiated: boolean;
+ begin
+ { format:
+ # unitname^
+ unit1^
+ # classname&
+ class1&
+ # instantiated?
+ 1
+ # vmt type (base or some interface)
+ basevmt
+ # vmt entry nr
+ 0
+ # name of routine to call instead
+ staticvmtentryforslot0
+ 5
+ staticvmtentryforslot5
+ intfvmt1
+ 0
+ staticvmtentryforslot0
+
+ # non-instantiated class (but if we encounter a variable of this
+ # type, we can optimise class to vmtentry 1)
+ class2&
+ 0
+ basevmt
+ 1
+ staticvmtentryforslot1
+
+ # instantiated class without optimisable virtual methods
+ class3&
+ 1
+
+ unit2^
+ 1
+ class3&
+ ...
+
+ currently, only basevmt is supported (no interfaces yet)
+ }
+ { could be empty if no classes or so }
+ if not reader.sectiongetnextline(unitid) then
+ exit;
+ repeat
+ if (unitid='') or
+ (unitid[length(unitid)]<>'^') then
+ internalerror(2008100502);
+ { cut off the trailing ^ }
+ setlength(unitid,length(unitid)-1);
+ unitdevirtinfo:=addunitifnew(unitid);
+ { now read classes }
+ if not reader.sectiongetnextline(classid) then
+ internalerror(2008100505);
+ repeat
+ if (classid='') or
+ (classid[length(classid)]<>'&') then
+ internalerror(2008100503);
+ { instantiated? }
+ if not reader.sectiongetnextline(classinstantiated) then
+ internalerror(2008101901);
+ instantiated:=classinstantiated='1';
+ { cut off the trailing & }
+ setlength(classid,length(classid)-1);
+ classdevirtinfo:=unitdevirtinfo.addclass(classid,instantiated);
+ { last class could be an instantiated class without any
+ optimisable methods. }
+ if not reader.sectiongetnextline(vmttype) then
+ exit;
+ { any optimisable virtual methods? }
+ if (vmttype<>'') then
+ begin
+ { interface info is not yet supported }
+ if (vmttype<>'basevmt') then
+ internalerror(2008100507);
+ { read all vmt entries for this class }
+ while reader.sectiongetnextline(vmtentrynrstr) and
+ (vmtentrynrstr<>'') do
+ begin
+ val(vmtentrynrstr,vmtentry,error);
+ if (error<>0) then
+ internalerror(2008100504);
+ if not reader.sectiongetnextline(vmtentryname) or
+ (vmtentryname='') then
+ internalerror(2008100508);
+ classdevirtinfo.addstaticmethod(vmtentry,vmtentryname);
+ end;
+ end;
+ { end of section -> exit }
+ if not(reader.sectiongetnextline(classid)) then
+ exit;
+ until (classid='') or
+ (classid[length(classid)]='^');
+ { next unit, or error }
+ unitid:=classid;
+ until false;
+ end;
+
+
+ procedure tprogdevirtinfo.documentformat(writer: twposectionwriterintf);
+ begin
+ writer.sectionputline('# section format:');
+ writer.sectionputline('# unit1^');
+ writer.sectionputline('# class1& ; classname&');
+ writer.sectionputline('# 1 ; instantiated or not');
+ writer.sectionputline('# basevmt ; vmt type (base or some interface)');
+ writer.sectionputline('# # vmt entry nr');
+ writer.sectionputline('# 0 ; vmt entry nr');
+ writer.sectionputline('# staticvmtentryforslot0 ; name or routine to call instead');
+ writer.sectionputline('# 5');
+ writer.sectionputline('# staticvmtentryforslot5');
+ writer.sectionputline('# intfvmt1');
+ writer.sectionputline('# 0');
+ writer.sectionputline('# staticvmtentryforslot0');
+ writer.sectionputline('#');
+ writer.sectionputline('# class2&');
+ writer.sectionputline('# 0 ; non-instantiated class (can be variables of this type, e.g. TObject)');
+ writer.sectionputline('# basevmt');
+ writer.sectionputline('# 1');
+ writer.sectionputline('# staticvmtentryforslot1');
+ writer.sectionputline('#');
+ writer.sectionputline('# class3& ; instantiated class without optimisable virtual methods');
+ writer.sectionputline('# 1');
+ writer.sectionputline('#');
+ writer.sectionputline('# unit2^');
+ writer.sectionputline('# 1');
+ writer.sectionputline('# class3&');
+ writer.sectionputline('# ...');
+ writer.sectionputline('#');
+ writer.sectionputline('# currently, only basevmt is supported (no interfaces yet)');
+ writer.sectionputline('#');
+ end;
+
+
+ procedure tprogdevirtinfo.storewpofilesection(writer: twposectionwriterintf);
+ var
+ unitcount,
+ classcount,
+ vmtentrycount: longint;
+ unitdevirtinfo: tunitdevirtinfo;
+ classdevirtinfo: tclassdevirtinfo;
+ first: boolean;
+ begin
+ writer.startsection(DEVIRT_SECTION_NAME);
+ { if there are no optimised virtual methods, we have stored no info }
+ if not assigned(funits) then
+ exit;
+ documentformat(writer);
+ for unitcount:=0 to funits.count-1 do
+ begin
+ unitdevirtinfo:=tunitdevirtinfo(funits[unitcount]);
+ writer.sectionputline(unitdevirtinfo.name+'^');
+ for classcount:=0 to unitdevirtinfo.fclasses.count-1 do
+ begin
+ classdevirtinfo:=tclassdevirtinfo(tunitdevirtinfo(funits[unitcount]).fclasses[classcount]);
+ writer.sectionputline(classdevirtinfo.name+'&');
+ writer.sectionputline(tostr(ord(classdevirtinfo.instantiated)));
+ first:=true;
+ for vmtentrycount:=0 to classdevirtinfo.fstaticmethodnames.count-1 do
+ if assigned(classdevirtinfo.fstaticmethodnames[vmtentrycount]) then
+ begin
+ if first then
+ begin
+ writer.sectionputline('basevmt');
+ first:=false;
+ end;
+ writer.sectionputline(tostr(vmtentrycount));
+ writer.sectionputline(pshortstring(classdevirtinfo.fstaticmethodnames[vmtentrycount])^);
+ end;
+ writer.sectionputline('');
+ end;
+ end;
+ end;
+
+
+ function tprogdevirtinfo.getstaticname(forvmtentry: boolean; objdef, procdef: tdef; out staticname: string): boolean;
+ var
+ unitid,
+ classid,
+ newname: pshortstring;
+ unitdevirtinfo: tunitdevirtinfo;
+ classdevirtinfo: tclassdevirtinfo;
+ vmtentry: longint;
+ realobjdef: tobjectdef;
+ begin
+ { if we don't have any devirtualisation info, exit }
+ if not assigned(funits) then
+ begin
+ result:=false;
+ exit
+ end;
+ { class methods are in the regular vmt, so we can handle classrefs
+ the same way as plain objectdefs
+ }
+ if (objdef.typ=classrefdef) then
+ realobjdef:=tobjectdef(tclassrefdef(objdef).pointeddef)
+ else if (objdef.typ=objectdef) and
+ (tobjectdef(objdef).objecttype in [odt_class,odt_object]) then
+ realobjdef:=tobjectdef(objdef)
+ else
+ begin
+ { we don't support interfaces yet }
+ result:=false;
+ exit;
+ end;
+
+ { if it's for a vmtentry of an objdef and the objdef is
+ not instantiated, then we can fill the vmt with pointers
+ to FPC_ABSTRACTERROR, except for published methods
+ (these can be called via rtti, so always have to point
+ to the original method)
+ }
+ if forvmtentry and
+ (tprocdef(procdef).visibility=vis_published) then
+ begin
+ result:=false;
+ exit;
+ end;
+
+ { get the component names for the class/procdef combo }
+ defsdecompose(realobjdef,tprocdef(procdef),unitid,classid,vmtentry);
+
+ { If we don't have information about a particular unit/class/method,
+ it means that such class cannot be instantiated. So if we are
+ looking up information for a vmt entry, we can always safely return
+ FPC_ABSTRACTERROR if we do not find anything, unless it's a
+ published method (but those are handled already above) or a
+ class method (can be called even if the class is not instantiated).
+ }
+ result:=
+ forvmtentry and
+ not(po_classmethod in tprocdef(procdef).procoptions);
+ staticname:='FPC_ABSTRACTERROR';
+
+ { do we have any info for this unit? }
+ unitdevirtinfo:=findunit(unitid^);
+ if not assigned(unitdevirtinfo) then
+ exit;
+ { and for this class? }
+ classdevirtinfo:=unitdevirtinfo.findclass(classid^);
+ if not assigned(classdevirtinfo) then
+ exit;
+ if forvmtentry and
+ (objdef.typ=objectdef) and
+ not classdevirtinfo.instantiated and
+ { virtual class methods can be called even if the class is not instantiated }
+ not(po_classmethod in tprocdef(procdef).procoptions) then
+ begin
+ { already set above
+ staticname:='FPC_ABSTRACTERROR';
+ }
+ result:=true;
+ end
+ else
+ begin
+ { now check whether it can be devirtualised, and if so to what }
+ result:=classdevirtinfo.isstaticvmtentry(vmtentry,newname);
+ if result then
+ staticname:=newname^;
+ end;
+ end;
+
+
+
+ function tprogdevirtinfo.staticnameforcallingvirtualmethod(objdef, procdef: tdef; out staticname: string): boolean;
+ begin
+ result:=getstaticname(false,objdef,procdef,staticname);
+ end;
+
+
+ function tprogdevirtinfo.staticnameforvmtentry(objdef, procdef: tdef; out staticname: string): boolean;
+ begin
+ result:=getstaticname(true,objdef,procdef,staticname);
+ end;
+
+end.
diff --git a/closures/compiler/owar.pas b/closures/compiler/owar.pas
new file mode 100644
index 0000000000..b714700385
--- /dev/null
+++ b/closures/compiler/owar.pas
@@ -0,0 +1,522 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ Contains the stuff for writing .a files directly
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit owar;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ cclasses,
+ owbase;
+
+type
+ tarhdr=packed record
+ name : array[0..15] of char;
+ date : array[0..11] of char;
+ uid : array[0..5] of char;
+ gid : array[0..5] of char;
+ mode : array[0..7] of char;
+ size : array[0..9] of char;
+ fmag : array[0..1] of char;
+ end;
+
+ tarobjectwriter=class(tobjectwriter)
+ constructor create(const Aarfn:string);
+ destructor destroy;override;
+ function createfile(const fn:string):boolean;override;
+ procedure closefile;override;
+ procedure writesym(const sym:string);override;
+ procedure write(const b;len:longword);override;
+ private
+ arfn : string;
+ arhdr : tarhdr;
+ symreloc,
+ symstr,
+ lfnstr,
+ ardata : TDynamicArray;
+ objpos : longint;
+ objfn : string;
+ timestamp : string[12];
+ procedure createarhdr(fn:string;asize:longint;const gid,uid,mode:string);
+ procedure writear;
+ end;
+
+ tarobjectreader=class(tobjectreader)
+ private
+ ArSymbols : TFPHashObjectList;
+ LFNStrs : PChar;
+ LFNSize : longint;
+ CurrMemberPos,
+ CurrMemberSize : longint;
+ CurrMemberName : string;
+ function DecodeMemberName(ahdr:TArHdr):string;
+ function DecodeMemberSize(ahdr:TArHdr):longint;
+ procedure ReadArchive;
+ protected
+ function getfilename:string;override;
+ public
+ constructor create(const Aarfn:string);
+ destructor destroy;override;
+ function openfile(const fn:string):boolean;override;
+ procedure closefile;override;
+ procedure seek(len:longint);override;
+ end;
+
+
+implementation
+
+ uses
+ SysUtils,
+ cstreams,
+ systems,
+ globals,
+ verbose;
+
+ const
+ symrelocbufsize = 4096;
+ symstrbufsize = 8192;
+ lfnstrbufsize = 4096;
+ arbufsize = 65536;
+
+ armagic:array[1..8] of char='!<arch>'#10;
+
+ type
+ TArSymbol = class(TFPHashObject)
+ MemberPos : longint;
+ end;
+
+
+{*****************************************************************************
+ Helpers
+*****************************************************************************}
+
+ const
+ C1970=2440588;
+ D0=1461;
+ D1=146097;
+ D2=1721119;
+ Function Gregorian2Julian(DT:TSystemTime):LongInt;
+ Var
+ Century,XYear,Month : LongInt;
+ Begin
+ Month:=DT.Month;
+ If Month<=2 Then
+ Begin
+ Dec(DT.Year);
+ Inc(Month,12);
+ End;
+ Dec(Month,3);
+ Century:=(longint(DT.Year Div 100)*D1) shr 2;
+ XYear:=(longint(DT.Year Mod 100)*D0) shr 2;
+ Gregorian2Julian:=((((Month*153)+2) div 5)+DT.Day)+D2+XYear+Century;
+ End;
+
+
+ function DT2Unix(DT:TSystemTime):LongInt;
+ Begin
+ DT2Unix:=(Gregorian2Julian(DT)-C1970)*86400+(LongInt(DT.Hour)*3600)+(DT.Minute*60)+DT.Second;
+ end;
+
+
+ function lsb2msb(l:longint):longint;
+ type
+ bytearr=array[0..3] of byte;
+ begin
+{$ifndef FPC_BIG_ENDIAN}
+ bytearr(result)[0]:=bytearr(l)[3];
+ bytearr(result)[1]:=bytearr(l)[2];
+ bytearr(result)[2]:=bytearr(l)[1];
+ bytearr(result)[3]:=bytearr(l)[0];
+{$else}
+ result:=l;
+{$endif}
+ end;
+
+
+{*****************************************************************************
+ TArObjectWriter
+*****************************************************************************}
+
+ constructor tarobjectwriter.create(const Aarfn:string);
+ var
+ time : TSystemTime;
+ begin
+ arfn:=Aarfn;
+ ardata:=TDynamicArray.Create(arbufsize);
+ symreloc:=TDynamicArray.Create(symrelocbufsize);
+ symstr:=TDynamicArray.Create(symstrbufsize);
+ lfnstr:=TDynamicArray.Create(lfnstrbufsize);
+ { create timestamp }
+ GetLocalTime(time);
+ Str(DT2Unix(time),timestamp);
+ end;
+
+
+ destructor tarobjectwriter.destroy;
+ begin
+ if Errorcount=0 then
+ writear;
+ arData.Free;
+ symreloc.Free;
+ symstr.Free;
+ lfnstr.Free;
+ end;
+
+
+ procedure tarobjectwriter.createarhdr(fn:string;asize:longint;const gid,uid,mode:string);
+ var
+ tmp : string[9];
+ hfn : string;
+ begin
+ { create ar header }
+ fillchar(arhdr,sizeof(tarhdr),' ');
+ { win32 will change names starting with .\ to ./ when using lfn, corrupting
+ the sort order required for the idata sections. To prevent this strip
+ always the path from the filename. (PFV) }
+ hfn:=ExtractFileName(fn);
+ if hfn='' then
+ hfn:=fn;
+ fn:=hfn+'/';
+ if length(fn)>16 then
+ begin
+ arhdr.name[0]:='/';
+ str(lfnstr.size,tmp);
+ move(tmp[1],arhdr.name[1],length(tmp));
+ fn:=fn+#10;
+ lfnstr.write(fn[1],length(fn));
+ end
+ else
+ move(fn[1],arhdr.name,length(fn));
+ { don't write a date if also no gid/uid/mode is specified }
+ if gid<>'' then
+ move(timestamp[1],arhdr.date,length(timestamp));
+ str(asize,tmp);
+ move(tmp[1],arhdr.size,length(tmp));
+ move(gid[1],arhdr.gid,length(gid));
+ move(uid[1],arhdr.uid,length(uid));
+ move(mode[1],arhdr.mode,length(mode));
+ arhdr.fmag:='`'#10;
+ end;
+
+
+ function tarobjectwriter.createfile(const fn:string):boolean;
+ begin
+ objfn:=fn;
+ objpos:=ardata.size;
+ ardata.seek(objpos + sizeof(tarhdr));
+ createfile:=true;
+ fobjsize:=0;
+ end;
+
+
+ procedure tarobjectwriter.closefile;
+ begin
+ ardata.align(2);
+ { fix the size in the header }
+ createarhdr(objfn,ardata.size-objpos-sizeof(tarhdr),'42','42','644');
+ { write the header }
+ ardata.seek(objpos);
+ ardata.write(arhdr,sizeof(tarhdr));
+ fobjsize:=0;
+ end;
+
+
+ procedure tarobjectwriter.writesym(const sym:string);
+ var
+ c : char;
+ begin
+ c:=#0;
+ symreloc.write(objpos,4);
+ symstr.write(sym[1],length(sym));
+ symstr.write(c,1);
+ end;
+
+
+ procedure tarobjectwriter.write(const b;len:longword);
+ begin
+ inc(fobjsize,len);
+ inc(fsize,len);
+ ardata.write(b,len);
+ end;
+
+
+ procedure tarobjectwriter.writear;
+ var
+ arf : TCCustomFileStream;
+ fixup,l,
+ relocs,i : longint;
+ begin
+ arf:=CFileStreamClass.Create(arfn,fmCreate);
+ if CStreamError<>0 then
+ begin
+ Message1(exec_e_cant_create_archivefile,arfn);
+ exit;
+ end;
+ arf.Write(armagic,sizeof(armagic));
+ { align first, because we need the size for the fixups of the symbol reloc }
+ if lfnstr.size>0 then
+ lfnstr.align(2);
+ if symreloc.size>0 then
+ begin
+ symstr.align(2);
+ fixup:=12+sizeof(tarhdr)+symreloc.size+symstr.size;
+ if lfnstr.size>0 then
+ inc(fixup,lfnstr.size+sizeof(tarhdr));
+ relocs:=symreloc.size div 4;
+ { fixup relocs }
+ for i:=0to relocs-1 do
+ begin
+ symreloc.seek(i*4);
+ symreloc.read(l,4);
+ symreloc.seek(i*4);
+ l:=lsb2msb(l+fixup);
+ symreloc.write(l,4);
+ end;
+ createarhdr('',4+symreloc.size+symstr.size,'0','0','0');
+ arf.Write(arhdr,sizeof(tarhdr));
+ relocs:=lsb2msb(relocs);
+ arf.Write(relocs,4);
+ symreloc.WriteStream(arf);
+ symstr.WriteStream(arf);
+ end;
+ if lfnstr.size>0 then
+ begin
+ createarhdr('/',lfnstr.size,'','','');
+ arf.Write(arhdr,sizeof(tarhdr));
+ lfnstr.WriteStream(arf);
+ end;
+ ardata.WriteStream(arf);
+ Arf.Free;
+ end;
+
+
+{*****************************************************************************
+ TArObjectReader
+*****************************************************************************}
+
+
+ constructor tarobjectreader.create(const Aarfn:string);
+ begin
+ inherited Create;
+ ArSymbols:=TFPHashObjectList.Create(true);
+ CurrMemberPos:=0;
+ CurrMemberSize:=0;
+ CurrMemberName:='';
+ if inherited openfile(Aarfn) then
+ ReadArchive;
+ end;
+
+
+ destructor tarobjectreader.destroy;
+ begin
+ inherited closefile;
+ ArSymbols.destroy;
+ if assigned(LFNStrs) then
+ FreeMem(LFNStrs);
+ inherited Destroy;
+ end;
+
+
+ function tarobjectreader.getfilename : string;
+ begin
+ result:=inherited getfilename;
+ if CurrMemberName<>'' then
+ result:=result+'('+CurrMemberName+')';
+ end;
+
+
+ function tarobjectreader.DecodeMemberName(ahdr:TArHdr):string;
+ var
+ hs : string;
+ code : integer;
+ hsp,
+ p : pchar;
+ lfnidx : longint;
+ begin
+ result:='';
+ p:=@ahdr.name[0];
+ hsp:=@hs[1];
+ while (p^<>' ') and (hsp-@hs[1]<16) do
+ begin
+ hsp^:=p^;
+ inc(p);
+ inc(hsp);
+ end;
+ hs[0]:=chr(hsp-@hs[1]);
+ if (hs[1]='/') and (hs[2] in ['0'..'9']) then
+ begin
+ Delete(hs,1,1);
+ val(hs,lfnidx,code);
+ if (lfnidx<0) or (lfnidx>=LFNSize) then
+ begin
+ Comment(V_Error,'Invalid ar member lfn name index in '+filename);
+ exit;
+ end;
+ p:=@LFNStrs[lfnidx];
+ hsp:=@result[1];
+ while p^<>#10 do
+ begin
+ hsp^:=p^;
+ inc(p);
+ inc(hsp);
+ end;
+ result[0]:=chr(hsp-@result[1]);
+ end
+ else
+ result:=hs;
+ { Strip ending / }
+ if result[length(result)]='/' then
+ dec(result[0]);
+ end;
+
+
+ function tarobjectreader.DecodeMemberSize(ahdr:TArHdr):longint;
+ var
+ hs : string;
+ code : integer;
+ hsp,
+ p : pchar;
+ begin
+ p:=@ahdr.size[0];
+ hsp:=@hs[1];
+ while p^<>' ' do
+ begin
+ hsp^:=p^;
+ inc(p);
+ inc(hsp);
+ end;
+ hs[0]:=chr(hsp-@hs[1]);
+ val(hs,result,code);
+ if result<=0 then
+ Comment(V_Error,'Invalid ar member size in '+filename);
+ end;
+
+
+ procedure tarobjectreader.ReadArchive;
+ var
+ currarmagic : array[0..sizeof(armagic)-1] of char;
+ currarhdr : tarhdr;
+ nrelocs,
+ relocidx,
+ currfilesize,
+ relocsize,
+ symsize : longint;
+ arsym : TArSymbol;
+ s : string;
+ syms,
+ currp,
+ endp,
+ startp : pchar;
+ relocs : plongint;
+ begin
+ Read(currarmagic,sizeof(armagic));
+ if CompareByte(currarmagic,armagic,sizeof(armagic))<>0 then
+ begin
+ Comment(V_Error,'Not a ar file, illegal magic: '+filename);
+ exit;
+ end;
+ Read(currarhdr,sizeof(currarhdr));
+ { Read number of relocs }
+ Read(nrelocs,sizeof(nrelocs));
+ nrelocs:=lsb2msb(nrelocs);
+ { Calculate sizes }
+ currfilesize:=DecodeMemberSize(currarhdr);
+ relocsize:=nrelocs*4;
+ symsize:=currfilesize-relocsize-4;
+ if symsize<0 then
+ begin
+ Comment(V_Error,'Illegal symtable in ar file '+filename);
+ exit;
+ end;
+ { Read relocs }
+ getmem(Relocs,relocsize);
+ Read(relocs^,relocsize);
+ { Read symbols, force terminating #0 to prevent overflow }
+ getmem(syms,symsize+1);
+ syms[symsize]:=#0;
+ Read(syms^,symsize);
+ { Parse symbols }
+ relocidx:=0;
+ currp:=syms;
+ endp:=syms+symsize;
+ for relocidx:=0 to nrelocs-1 do
+ begin
+ startp:=currp;
+ while (currp^<>#0) do
+ inc(currp);
+ s[0]:=chr(currp-startp);
+ move(startp^,s[1],byte(s[0]));
+ arsym:=TArSymbol.create(ArSymbols,s);
+ arsym.MemberPos:=lsb2msb(relocs[relocidx]);
+ inc(currp);
+ if currp>endp then
+ begin
+ Comment(V_Error,'Illegal symtable in ar file '+filename);
+ break;
+ end;
+ end;
+ freemem(relocs);
+ freemem(syms);
+ { LFN names }
+ Read(currarhdr,sizeof(currarhdr));
+ if DecodeMemberName(currarhdr)='/' then
+ begin
+ lfnsize:=DecodeMemberSize(currarhdr);
+ getmem(lfnstrs,lfnsize);
+ Read(lfnstrs^,lfnsize);
+ end;
+ end;
+
+
+ function tarobjectreader.openfile(const fn:string):boolean;
+ var
+ arsym : TArSymbol;
+ arhdr : TArHdr;
+ begin
+ result:=false;
+ arsym:=TArSymbol(ArSymbols.Find(fn));
+ if not assigned(arsym) then
+ exit;
+ inherited Seek(arsym.MemberPos);
+ Read(arhdr,sizeof(arhdr));
+ CurrMemberName:=DecodeMemberName(arhdr);
+ CurrMemberSize:=DecodeMemberSize(arhdr);
+ CurrMemberPos:=arsym.MemberPos+sizeof(arhdr);
+ result:=true;
+ end;
+
+
+ procedure tarobjectreader.closefile;
+ begin
+ CurrMemberPos:=0;
+ CurrMemberSize:=0;
+ CurrMemberName:='';
+ end;
+
+
+ procedure tarobjectreader.seek(len:longint);
+ begin
+ inherited Seek(CurrMemberPos+len);
+ end;
+
+end.
diff --git a/closures/compiler/owbase.pas b/closures/compiler/owbase.pas
new file mode 100644
index 0000000000..ac90487825
--- /dev/null
+++ b/closures/compiler/owbase.pas
@@ -0,0 +1,304 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ Contains the base stuff for writing for object files to disk
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit owbase;
+
+{$i fpcdefs.inc}
+
+interface
+uses
+ cstreams,
+ cclasses;
+
+type
+ tobjectwriter=class
+ private
+ f : TCCustomFileStream;
+ opened : boolean;
+ buf : pchar;
+ bufidx : longword;
+ procedure writebuf;
+ protected
+ fsize,
+ fobjsize : longword;
+ public
+ constructor create;
+ destructor destroy;override;
+ function createfile(const fn:string):boolean;virtual;
+ procedure closefile;virtual;
+ procedure writesym(const sym:string);virtual;
+ procedure write(const b;len:longword);virtual;
+ procedure WriteZeros(l:longword);
+ procedure writearray(a:TDynamicArray);
+ property Size:longword read FSize;
+ property ObjSize:longword read FObjSize;
+ end;
+
+ tobjectreader=class
+ private
+ f : TCCustomFileStream;
+ opened : boolean;
+ buf : pchar;
+ ffilename : string;
+ bufidx,
+ bufmax : longint;
+ function readbuf:boolean;
+ protected
+ function getfilename : string;virtual;
+ public
+ constructor create;
+ destructor destroy;override;
+ function openfile(const fn:string):boolean;virtual;
+ procedure closefile;virtual;
+ procedure seek(len:longint);virtual;
+ function read(out b;len:longint):boolean;virtual;
+ function readarray(a:TDynamicArray;len:longint):boolean;
+ property filename : string read getfilename;
+ end;
+
+implementation
+
+uses
+ SysUtils,
+ verbose, globals;
+
+const
+ bufsize = 32768;
+
+
+{****************************************************************************
+ TObjectWriter
+****************************************************************************}
+
+constructor tobjectwriter.create;
+begin
+ getmem(buf,bufsize);
+ bufidx:=0;
+ opened:=false;
+ fsize:=0;
+end;
+
+
+destructor tobjectwriter.destroy;
+begin
+ if opened then
+ closefile;
+ freemem(buf,bufsize);
+end;
+
+
+function tobjectwriter.createfile(const fn:string):boolean;
+begin
+ createfile:=false;
+ f:=CFileStreamClass.Create(fn,fmCreate);
+ if CStreamError<>0 then
+ begin
+ Message2(exec_e_cant_create_objectfile,fn,IntToStr(CStreamError));
+ exit;
+ end;
+ bufidx:=0;
+ fsize:=0;
+ fobjsize:=0;
+ opened:=true;
+ createfile:=true;
+end;
+
+
+procedure tobjectwriter.closefile;
+var
+ fn : string;
+begin
+ if bufidx>0 then
+ writebuf;
+ fn:=f.filename;
+ f.free;
+{ Remove if size is 0 }
+ if size=0 then
+ DeleteFile(fn);
+ opened:=false;
+ fsize:=0;
+ fobjsize:=0;
+end;
+
+
+procedure tobjectwriter.writebuf;
+begin
+ f.write(buf^,bufidx);
+ bufidx:=0;
+end;
+
+
+procedure tobjectwriter.writesym(const sym:string);
+begin
+end;
+
+
+procedure tobjectwriter.write(const b;len:longword);
+var
+ p : pchar;
+ bufleft,
+ idx : longword;
+begin
+ inc(fsize,len);
+ inc(fobjsize,len);
+ p:=pchar(@b);
+ idx:=0;
+ while len>0 do
+ begin
+ bufleft:=bufsize-bufidx;
+ if len>bufleft then
+ begin
+ move(p[idx],buf[bufidx],bufleft);
+ dec(len,bufleft);
+ inc(idx,bufleft);
+ inc(bufidx,bufleft);
+ writebuf;
+ end
+ else
+ begin
+ move(p[idx],buf[bufidx],len);
+ inc(bufidx,len);
+ exit;
+ end;
+ end;
+end;
+
+
+procedure tobjectwriter.WriteZeros(l:longword);
+var
+ empty : array[0..1023] of byte;
+begin
+ if l>sizeof(empty) then
+ internalerror(200404081);
+ if l>0 then
+ begin
+ fillchar(empty,l,0);
+ Write(empty,l);
+ end;
+end;
+
+
+procedure tobjectwriter.writearray(a:TDynamicArray);
+var
+ hp : pdynamicblock;
+begin
+ hp:=a.firstblock;
+ while assigned(hp) do
+ begin
+ write(hp^.data,hp^.used);
+ hp:=hp^.next;
+ end;
+end;
+
+
+{****************************************************************************
+ TObjectReader
+****************************************************************************}
+
+constructor tobjectreader.create;
+begin
+ buf:=nil;
+ bufidx:=0;
+ bufmax:=0;
+ ffilename:='';
+ opened:=false;
+end;
+
+
+destructor tobjectreader.destroy;
+begin
+ if opened then
+ closefile;
+end;
+
+
+function tobjectreader.openfile(const fn:string):boolean;
+begin
+ openfile:=false;
+ f:=CFileStreamClass.Create(fn,fmOpenRead);
+ if CStreamError<>0 then
+ begin
+ Comment(V_Error,'Can''t open object file: '+fn);
+ exit;
+ end;
+ ffilename:=fn;
+ getmem(buf,f.Size);
+ f.read(buf^,f.Size);
+ bufmax:=f.Size;
+ f.free;
+ bufidx:=0;
+ opened:=true;
+ openfile:=true;
+end;
+
+
+procedure tobjectreader.closefile;
+begin
+ opened:=false;
+ bufidx:=0;
+ bufmax:=0;
+ freemem(buf);
+end;
+
+
+function tobjectreader.readbuf:boolean;
+begin
+ result:=bufidx<bufmax;
+end;
+
+
+procedure tobjectreader.seek(len:longint);
+begin
+ bufidx:=len;
+end;
+
+
+function tobjectreader.read(out b;len:longint):boolean;
+begin
+ result:=true;
+ if bufidx+len>bufmax then
+ begin
+ result:=false;
+ len:=bufmax-bufidx;
+ end;
+ move(buf[bufidx],b,len);
+ inc(bufidx,len);
+end;
+
+
+function tobjectreader.readarray(a:TDynamicArray;len:longint):boolean;
+begin
+ result:=true;
+ if bufidx+len>bufmax then
+ begin
+ result:=false;
+ len:=bufmax-bufidx;
+ end;
+ a.write(buf[bufidx],len);
+ inc(bufidx,len);
+end;
+
+function tobjectreader.getfilename : string;
+ begin
+ result:=ffilename;
+ end;
+
+end.
diff --git a/closures/compiler/parabase.pas b/closures/compiler/parabase.pas
new file mode 100644
index 0000000000..047f7f1a7e
--- /dev/null
+++ b/closures/compiler/parabase.pas
@@ -0,0 +1,372 @@
+{
+ Copyright (c) 2002 by Florian Klaempfl
+
+ Generic calling convention handling
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ ****************************************************************************
+}
+unit parabase;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ cclasses,globtype,
+ cpubase,cgbase,cgutils,
+ symtype, ppu;
+
+ type
+ TCGParaReference = record
+ index : tregister;
+ offset : aint;
+ end;
+
+ PCGParaLocation = ^TCGParaLocation;
+ TCGParaLocation = record
+ Next : PCGParaLocation;
+ Size : TCGSize; { size of this location }
+ Loc : TCGLoc;
+ case TCGLoc of
+ LOC_REFERENCE : (reference : TCGParaReference);
+ LOC_FPUREGISTER,
+ LOC_CFPUREGISTER,
+ LOC_MMREGISTER,
+ LOC_CMMREGISTER,
+ LOC_REGISTER,
+ LOC_CREGISTER : (
+ { The number of bits the value in the register must be shifted to the left before
+ it can be stored to memory in the function prolog.
+ This is used for passing OS_NO memory blocks less than register size and of "odd"
+ (3, 5, 6, 7) size on big endian machines, so that small memory blocks passed via
+ registers are properly aligned.
+
+ E.g. the value $5544433 is passed in bits 40-63 of the register (others are zero),
+ but they should actually be stored in the first bits of the stack location reserved
+ for this value. So they have to be shifted left by this amount of bits before. }
+ {$IFDEF POWERPC64}shiftval : byte;{$ENDIF POWERPC64}
+ register : tregister);
+ end;
+
+ TCGPara = object
+ Location : PCGParalocation;
+ IntSize : tcgint; { size of the total location in bytes }
+ Alignment : ShortInt;
+ Size : TCGSize; { Size of the parameter included in all locations }
+{$ifdef powerpc}
+ composite: boolean; { under the AIX abi, how certain parameters are passed depends on whether they are composite or not }
+{$endif powerpc}
+ constructor init;
+ destructor done;
+ procedure reset;
+ function getcopy:tcgpara;
+ procedure check_simple_location;
+ function add_location:pcgparalocation;
+ procedure get_location(var newloc:tlocation);
+
+ procedure ppuwrite(ppufile:tcompilerppufile);
+ procedure ppuload(ppufile:tcompilerppufile);
+ end;
+
+ tvarargsinfo = (
+ va_uses_float_reg
+ );
+
+ tparalist = class(TFPObjectList)
+ procedure SortParas;
+ end;
+
+ tvarargsparalist = class(tparalist)
+ varargsinfo : set of tvarargsinfo;
+{$ifdef x86_64}
+ { x86_64 requires %al to contain the no. SSE regs passed }
+ mmregsused : longint;
+{$endif x86_64}
+ end;
+
+
+
+implementation
+
+ uses
+ systems,verbose,
+ symsym;
+
+
+{****************************************************************************
+ TCGPara
+****************************************************************************}
+
+ constructor tcgpara.init;
+ begin
+ alignment:=0;
+ size:=OS_NO;
+ intsize:=0;
+ location:=nil;
+{$ifdef powerpc}
+ composite:=false;
+{$endif powerpc}
+ end;
+
+
+ destructor tcgpara.done;
+ begin
+ reset;
+ end;
+
+
+ procedure tcgpara.reset;
+ var
+ hlocation : pcgparalocation;
+ begin
+ while assigned(location) do
+ begin
+ hlocation:=location^.next;
+ dispose(location);
+ location:=hlocation;
+ end;
+ alignment:=0;
+ size:=OS_NO;
+ intsize:=0;
+{$ifdef powerpc}
+ composite:=false;
+{$endif powerpc}
+ end;
+
+
+ function tcgpara.getcopy:tcgpara;
+ var
+ hlocation : pcgparalocation;
+ begin
+ result.init;
+ while assigned(location) do
+ begin
+ hlocation:=result.add_location;
+ hlocation^:=location^;
+ hlocation^.next:=nil;
+ location:=location^.next;
+ end;
+ result.alignment:=alignment;
+ result.size:=size;
+ result.intsize:=intsize;
+{$ifdef powerpc}
+ result.composite:=composite;
+{$endif powerpc}
+ end;
+
+
+ function tcgpara.add_location:pcgparalocation;
+ var
+ prevlocation,
+ hlocation : pcgparalocation;
+ begin
+ prevlocation:=nil;
+ hlocation:=location;
+ while assigned(hlocation) do
+ begin
+ prevlocation:=hlocation;
+ hlocation:=hlocation^.next;
+ end;
+ new(hlocation);
+ Fillchar(hlocation^,sizeof(tcgparalocation),0);
+ if assigned(prevlocation) then
+ prevlocation^.next:=hlocation
+ else
+ location:=hlocation;
+ result:=hlocation;
+ end;
+
+
+ procedure tcgpara.check_simple_location;
+ begin
+ if not assigned(location) then
+ internalerror(200408161);
+ if assigned(location^.next) then
+ internalerror(200408162);
+ end;
+
+
+ procedure tcgpara.get_location(var newloc:tlocation);
+ begin
+ if not assigned(location) then
+ internalerror(200408205);
+ fillchar(newloc,sizeof(newloc),0);
+ newloc.loc:=location^.loc;
+ newloc.size:=size;
+ case location^.loc of
+ LOC_REGISTER :
+ begin
+{$ifndef cpu64bitalu}
+ if size in [OS_64,OS_S64] then
+ begin
+ if not assigned(location^.next) then
+ internalerror(200408206);
+ if (location^.next^.loc<>LOC_REGISTER) then
+ internalerror(200408207);
+ if (target_info.endian = ENDIAN_BIG) then
+ begin
+ newloc.register64.reghi:=location^.register;
+ newloc.register64.reglo:=location^.next^.register;
+ end
+ else
+ begin
+ newloc.register64.reglo:=location^.register;
+ newloc.register64.reghi:=location^.next^.register;
+ end;
+ end
+ else
+{$endif}
+ newloc.register:=location^.register;
+ end;
+ LOC_FPUREGISTER,
+ LOC_MMREGISTER :
+ newloc.register:=location^.register;
+ LOC_REFERENCE :
+ begin
+ newloc.reference.base:=location^.reference.index;
+ newloc.reference.offset:=location^.reference.offset;
+ newloc.reference.alignment:=alignment;
+ end;
+ end;
+ end;
+
+
+ procedure TCGPara.ppuwrite(ppufile: tcompilerppufile);
+ var
+ hparaloc: PCGParaLocation;
+ nparaloc: byte;
+ begin
+ ppufile.putbyte(byte(Alignment));
+ ppufile.putbyte(ord(Size));
+ ppufile.putaint(IntSize);
+{$ifdef powerpc}
+ ppufile.putbyte(byte(composite));
+{$endif}
+ nparaloc:=0;
+ hparaloc:=location;
+ while assigned(hparaloc) do
+ begin
+ inc(nparaloc);
+ hparaloc:=hparaloc^.Next;
+ end;
+ ppufile.putbyte(nparaloc);
+ hparaloc:=location;
+ while assigned(hparaloc) do
+ begin
+ ppufile.putbyte(byte(hparaloc^.Size));
+ ppufile.putbyte(byte(hparaloc^.loc));
+ case hparaloc^.loc of
+ LOC_REFERENCE:
+ begin
+ ppufile.putlongint(longint(hparaloc^.reference.index));
+ ppufile.putaint(hparaloc^.reference.offset);
+ end;
+ LOC_FPUREGISTER,
+ LOC_CFPUREGISTER,
+ LOC_MMREGISTER,
+ LOC_CMMREGISTER,
+ LOC_REGISTER,
+ LOC_CREGISTER :
+ begin
+{$ifdef powerpc64}
+ ppufile.putbyte(hparaloc^.shiftval);
+{$endif}
+ ppufile.putlongint(longint(hparaloc^.register));
+ end;
+ { This seems to be required for systems using explicitparaloc (eg. MorphOS)
+ or otherwise it hits the internalerror below. I don't know if this is
+ the proper way to fix this, someone else with clue might want to take a
+ look. The compiler cycles on the affected systems with this enabled. (KB) }
+ LOC_VOID:
+ begin end
+ else
+ internalerror(2010053115);
+ end;
+ hparaloc:=hparaloc^.next;
+ end;
+ end;
+
+
+ procedure TCGPara.ppuload(ppufile: tcompilerppufile);
+ var
+ hparaloc: PCGParaLocation;
+ nparaloc: byte;
+ begin
+ reset;
+ Alignment:=shortint(ppufile.getbyte);
+ Size:=TCgSize(ppufile.getbyte);
+ IntSize:=ppufile.getaint;
+{$ifdef powerpc}
+ composite:=boolean(ppufile.getbyte);
+{$endif}
+ nparaloc:=ppufile.getbyte;
+ while nparaloc>0 do
+ begin
+ hparaloc:=add_location;
+ hparaloc^.size:=TCGSize(ppufile.getbyte);
+ hparaloc^.loc:=TCGLoc(ppufile.getbyte);
+ case hparaloc^.loc of
+ LOC_REFERENCE:
+ begin
+ hparaloc^.reference.index:=tregister(ppufile.getlongint);
+ hparaloc^.reference.offset:=ppufile.getaint;
+ end;
+ LOC_FPUREGISTER,
+ LOC_CFPUREGISTER,
+ LOC_MMREGISTER,
+ LOC_CMMREGISTER,
+ LOC_REGISTER,
+ LOC_CREGISTER :
+ begin
+{$ifdef powerpc64}
+ hparaloc^.shiftval:=ppufile.getbyte;
+{$endif}
+ hparaloc^.register:=tregister(ppufile.getlongint);
+ end;
+ { This seems to be required for systems using explicitparaloc (eg. MorphOS)
+ or otherwise it hits the internalerror below. I don't know if this is
+ the proper way to fix this, someone else with clue might want to take a
+ look. The compiler cycles on the affected systems with this enabled. (KB) }
+ LOC_VOID:
+ begin end
+ else
+ internalerror(2010051301);
+ end;
+ dec(nparaloc);
+ end;
+ end;
+
+
+{****************************************************************************
+ TParaList
+****************************************************************************}
+
+ function ParaNrCompare(Item1, Item2: Pointer): Integer;
+ var
+ I1 : tparavarsym absolute Item1;
+ I2 : tparavarsym absolute Item2;
+ begin
+ Result:=longint(I1.paranr)-longint(I2.paranr);
+ end;
+
+
+ procedure TParaList.SortParas;
+ begin
+ Sort(@ParaNrCompare);
+ end;
+
+
+end.
diff --git a/closures/compiler/paramgr.pas b/closures/compiler/paramgr.pas
new file mode 100644
index 0000000000..13d149b641
--- /dev/null
+++ b/closures/compiler/paramgr.pas
@@ -0,0 +1,484 @@
+{
+ Copyright (c) 2002 by Florian Klaempfl
+
+ Generic calling convention handling
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ ****************************************************************************
+}
+{# Parameter passing manager. Used to manage how
+ parameters are passed to routines.
+}
+unit paramgr;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ cclasses,globtype,
+ cpubase,cgbase,cgutils,
+ parabase,
+ aasmtai,aasmdata,
+ symconst,symtype,symsym,symdef;
+
+ type
+ {# This class defines some methods to take care of routine
+ parameters. It should be overridden for each new processor
+ }
+
+ { tparamanager }
+
+ tparamanager = class
+ { true if the location in paraloc can be reused as localloc }
+ function param_use_paraloc(const cgpara:tcgpara):boolean;virtual;
+ {# Returns true if the return value is actually a parameter
+ pointer.
+ }
+ function ret_in_param(def : tdef;calloption : tproccalloption) : boolean;virtual;
+
+ function push_high_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;virtual;
+
+ { Returns true if a parameter is too large to copy and only
+ the address is pushed
+ }
+ function push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;virtual;abstract;
+ { return the size of a push }
+ function push_size(varspez:tvarspez;def : tdef;calloption : tproccalloption) : longint;
+ {# Returns a structure giving the information on
+ the storage of the parameter (which must be
+ an integer parameter). This is only used when calling
+ internal routines directly, where all parameters must
+ be 4-byte values.
+
+ In case the location is a register, this register is allocated.
+ Call freeintparaloc() after the call to free the locations again.
+ Default implementation: don't do anything at all (in case you don't
+ use register parameter passing)
+
+ @param(list Current assembler list)
+ @param(nr Parameter number of routine, starting from 1)
+ }
+ function get_para_align(calloption : tproccalloption):byte;virtual;
+ function get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;virtual;
+ function get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;virtual;
+ function get_volatile_registers_flags(calloption : tproccalloption):tcpuregisterset;virtual;
+ function get_volatile_registers_mm(calloption : tproccalloption):tcpuregisterset;virtual;
+
+ procedure getintparaloc(calloption : tproccalloption; nr : longint;var cgpara:TCGPara);virtual;abstract;
+
+ {# allocate an individual pcgparalocation that's part of a tcgpara
+
+ @param(list Current assembler list)
+ @param(loc Parameter location element)
+ }
+ procedure allocparaloc(list: TAsmList; const paraloc: pcgparalocation);
+
+ {# allocate a parameter location created with create_paraloc_info
+
+ @param(list Current assembler list)
+ @param(loc Parameter location)
+ }
+ procedure alloccgpara(list: TAsmList; const cgpara: TCGPara); virtual;
+
+ {# free a parameter location allocated with alloccgpara
+
+ @param(list Current assembler list)
+ @param(loc Parameter location)
+ }
+ procedure freecgpara(list: TAsmList; const cgpara: TCGPara); virtual;
+
+ { This is used to populate the location information on all parameters
+ for the routine as seen in either the caller or the callee. It returns
+ the size allocated on the stack
+ }
+ function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;virtual;abstract;
+
+ { Returns the location of the function result if p had def as
+ function result instead of its actual result. Used if the compiler
+ forces the function result to something different than the real
+ result. }
+ function get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tcgpara;virtual;abstract;
+
+ { This is used to populate the location information on all parameters
+ for the routine when it is being inlined. It returns
+ the size allocated on the stack
+ }
+ function create_inline_paraloc_info(p : tabstractprocdef):longint;virtual;
+
+ { This is used to populate the location information on all parameters
+ for the routine that are passed as varargs. It returns
+ the size allocated on the stack (including the normal parameters)
+ }
+ function create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;virtual;abstract;
+
+ function is_stack_paraloc(paraloc: pcgparalocation): boolean;
+ procedure createtempparaloc(list: TAsmList;calloption : tproccalloption;parasym : tparavarsym;can_use_final_stack_loc : boolean;var cgpara:TCGPara);virtual;
+ procedure duplicatecgparaloc(const orgparaloc: pcgparalocation; intonewparaloc: pcgparalocation);
+ procedure duplicateparaloc(list: TAsmList;calloption : tproccalloption;parasym : tparavarsym;var cgpara:TCGPara);
+
+ function parseparaloc(parasym : tparavarsym;const s : string) : boolean;virtual;
+ function parsefuncretloc(p : tabstractprocdef; const s : string) : boolean;virtual;
+
+ { allocate room for parameters on the stack in the entry code? }
+ function use_fixed_stack: boolean;
+ { whether stack pointer can be changed in the middle of procedure }
+ function use_stackalloc: boolean;
+ end;
+
+
+ var
+ paramanager : tparamanager;
+
+
+implementation
+
+ uses
+ systems,
+ cgobj,tgobj,
+ defutil,verbose;
+
+ { true if the location in paraloc can be reused as localloc }
+ function tparamanager.param_use_paraloc(const cgpara:tcgpara):boolean;
+ begin
+ result:=false;
+ end;
+
+
+ { true if uses a parameter as return value }
+ function tparamanager.ret_in_param(def : tdef;calloption : tproccalloption) : boolean;
+ begin
+ ret_in_param:=((def.typ=arraydef) and not(is_dynamic_array(def))) or
+ (def.typ=recorddef) or
+ (def.typ=stringdef) or
+ ((def.typ=procvardef) and not tprocvardef(def).is_addressonly) or
+ { interfaces are also passed by reference to be compatible with delphi and COM }
+ ((def.typ=objectdef) and (is_object(def) or is_interface(def) or is_dispinterface(def))) or
+ (def.typ=variantdef) or
+ ((def.typ=setdef) and not is_smallset(def));
+ end;
+
+
+ function tparamanager.push_high_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;
+ begin
+ push_high_param:=not(calloption in cdecl_pocalls) and
+ (
+ is_open_array(def) or
+ is_open_string(def) or
+ is_array_of_const(def)
+ );
+ end;
+
+
+ { return the size of a push }
+ function tparamanager.push_size(varspez:tvarspez;def : tdef;calloption : tproccalloption) : longint;
+ begin
+ push_size:=-1;
+ case varspez of
+ vs_constref,
+ vs_out,
+ vs_var :
+ push_size:=sizeof(pint);
+ vs_value,
+ vs_const :
+ begin
+ if push_addr_param(varspez,def,calloption) then
+ push_size:=sizeof(pint)
+ else
+ begin
+ { special array are normally pushed by addr, only for
+ cdecl array of const it comes here and the pushsize
+ is unknown }
+ if is_array_of_const(def) then
+ push_size:=0
+ else
+ push_size:=def.size;
+ end;
+ end;
+ end;
+ end;
+
+
+ function tparamanager.get_para_align(calloption : tproccalloption):byte;
+ begin
+ result:=std_param_align;
+ end;
+
+
+ function tparamanager.get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;
+ begin
+ result:=[];
+ end;
+
+
+ function tparamanager.get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;
+ begin
+ result:=[];
+ end;
+
+
+ function tparamanager.get_volatile_registers_flags(calloption : tproccalloption):tcpuregisterset;
+ begin
+ result:=[];
+ end;
+
+
+ function tparamanager.get_volatile_registers_mm(calloption : tproccalloption):tcpuregisterset;
+ begin
+ result:=[];
+ end;
+
+{$if first_mm_imreg = 0}
+ {$WARN 4044 OFF} { Comparison might be always false ... }
+{$endif}
+
+ procedure tparamanager.allocparaloc(list: TAsmList; const paraloc: pcgparalocation);
+ begin
+ case paraloc^.loc of
+ LOC_REGISTER,
+ LOC_CREGISTER:
+ begin
+ if getsupreg(paraloc^.register)<first_int_imreg then
+ cg.getcpuregister(list,paraloc^.register);
+ end;
+{$ifndef x86}
+{ don't allocate ST(x), they're not handled by the register allocator }
+ LOC_FPUREGISTER,
+ LOC_CFPUREGISTER:
+ begin
+ if getsupreg(paraloc^.register)<first_fpu_imreg then
+ cg.getcpuregister(list,paraloc^.register);
+ end;
+{$endif not x86}
+ LOC_MMREGISTER,
+ LOC_CMMREGISTER :
+ begin
+ if getsupreg(paraloc^.register)<first_mm_imreg then
+ cg.getcpuregister(list,paraloc^.register);
+ end;
+ end;
+ end;
+
+
+ procedure tparamanager.alloccgpara(list: TAsmList; const cgpara: TCGPara);
+ var
+ paraloc : pcgparalocation;
+ begin
+ paraloc:=cgpara.location;
+ while assigned(paraloc) do
+ begin
+ allocparaloc(list,paraloc);
+ paraloc:=paraloc^.next;
+ end;
+ end;
+
+
+ procedure tparamanager.freecgpara(list: TAsmList; const cgpara: TCGPara);
+ var
+ paraloc : Pcgparalocation;
+ href : treference;
+ begin
+ paraloc:=cgpara.location;
+ while assigned(paraloc) do
+ begin
+ case paraloc^.loc of
+ LOC_VOID:
+ ;
+ LOC_REGISTER,
+ LOC_CREGISTER:
+ begin
+ if getsupreg(paraloc^.register)<first_int_imreg then
+ cg.ungetcpuregister(list,paraloc^.register);
+ end;
+ LOC_FPUREGISTER,
+ LOC_CFPUREGISTER:
+ begin
+ if getsupreg(paraloc^.register)<first_fpu_imreg then
+ cg.ungetcpuregister(list,paraloc^.register);
+ end;
+ LOC_MMREGISTER,
+ LOC_CMMREGISTER :
+ begin
+ if getsupreg(paraloc^.register)<first_mm_imreg then
+ cg.ungetcpuregister(list,paraloc^.register);
+ end;
+ LOC_REFERENCE,
+ LOC_CREFERENCE :
+ begin
+ if use_fixed_stack then
+ begin
+ { don't use reference_reset_base, because that will depend on cgobj }
+ fillchar(href,sizeof(href),0);
+ href.base:=paraloc^.reference.index;
+ href.offset:=paraloc^.reference.offset;
+ tg.ungetiftemp(list,href);
+ end;
+ end;
+ else
+ internalerror(2004110212);
+ end;
+ paraloc:=paraloc^.next;
+ end;
+ end;
+
+
+ function tparamanager.is_stack_paraloc(paraloc: pcgparalocation): boolean;
+ begin
+ result:=
+ assigned(paraloc) and
+ (paraloc^.loc=LOC_REFERENCE) and
+ (paraloc^.reference.index=NR_STACK_POINTER_REG);
+ end;
+
+
+ procedure tparamanager.createtempparaloc(list: TAsmList;calloption : tproccalloption;parasym : tparavarsym;can_use_final_stack_loc : boolean;var cgpara:TCGPara);
+ var
+ href : treference;
+ len : aint;
+ paraloc,
+ newparaloc : pcgparalocation;
+ begin
+ paraloc:=parasym.paraloc[callerside].location;
+ cgpara.reset;
+ cgpara.size:=parasym.paraloc[callerside].size;
+ cgpara.intsize:=parasym.paraloc[callerside].intsize;
+ cgpara.alignment:=parasym.paraloc[callerside].alignment;
+{$ifdef powerpc}
+ cgpara.composite:=parasym.paraloc[callerside].composite;
+{$endif powerpc}
+ while assigned(paraloc) do
+ begin
+ if paraloc^.size=OS_NO then
+ len:=push_size(parasym.varspez,parasym.vardef,calloption)
+ else
+ len:=tcgsize2size[paraloc^.size];
+ newparaloc:=cgpara.add_location;
+ newparaloc^.size:=paraloc^.size;
+ { $warning maybe release this optimization for all targets? }
+ { released for all CPUs:
+ i386 isn't affected anyways because it uses the stack to push parameters
+ on arm it reduces executable size of the compiler by 2.1 per cent (FK) }
+ { Does it fit a register? }
+ if ((not can_use_final_stack_loc and
+ use_fixed_stack) or
+ not is_stack_paraloc(paraloc)) and
+ (len<=sizeof(pint)) and
+ (paraloc^.size in [OS_8,OS_16,OS_32,OS_64,OS_128,OS_S8,OS_S16,OS_S32,OS_S64,OS_S128]) then
+ newparaloc^.loc:=LOC_REGISTER
+ else
+ newparaloc^.loc:=paraloc^.loc;
+ case newparaloc^.loc of
+ LOC_REGISTER :
+ newparaloc^.register:=cg.getintregister(list,paraloc^.size);
+ LOC_FPUREGISTER :
+ newparaloc^.register:=cg.getfpuregister(list,paraloc^.size);
+ LOC_MMREGISTER :
+ newparaloc^.register:=cg.getmmregister(list,paraloc^.size);
+ LOC_REFERENCE :
+ begin
+ if (can_use_final_stack_loc or
+ not use_fixed_stack) and
+ is_stack_paraloc(paraloc) then
+ duplicatecgparaloc(paraloc,newparaloc)
+ else
+ begin
+ tg.gettemp(list,len,cgpara.alignment,tt_persistent,href);
+ newparaloc^.reference.index:=href.base;
+ newparaloc^.reference.offset:=href.offset;
+ end;
+ end;
+ end;
+ paraloc:=paraloc^.next;
+ end;
+ end;
+
+
+ procedure tparamanager.duplicatecgparaloc(const orgparaloc: pcgparalocation; intonewparaloc: pcgparalocation);
+ begin
+ move(orgparaloc^,intonewparaloc^,sizeof(intonewparaloc^));
+ intonewparaloc^.next:=nil;
+ end;
+
+
+ procedure tparamanager.duplicateparaloc(list: TAsmList;calloption : tproccalloption;parasym : tparavarsym;var cgpara:TCGPara);
+ var
+ paraloc,
+ newparaloc : pcgparalocation;
+ begin
+ cgpara.reset;
+ cgpara.size:=parasym.paraloc[callerside].size;
+ cgpara.intsize:=parasym.paraloc[callerside].intsize;
+ cgpara.alignment:=parasym.paraloc[callerside].alignment;
+{$ifdef powerpc}
+ cgpara.composite:=parasym.paraloc[callerside].composite;
+{$endif powerpc}
+ paraloc:=parasym.paraloc[callerside].location;
+ while assigned(paraloc) do
+ begin
+ newparaloc:=cgpara.add_location;
+ duplicatecgparaloc(paraloc,newparaloc);
+ paraloc:=paraloc^.next;
+ end;
+ end;
+
+
+ function tparamanager.create_inline_paraloc_info(p : tabstractprocdef):longint;
+ begin
+ { We need to return the size allocated }
+ p.init_paraloc_info(callbothsides);
+ result:=p.calleeargareasize;
+ end;
+
+
+ function tparamanager.parseparaloc(parasym: tparavarsym; const s: string): boolean;
+ begin
+ Result:=False;
+ internalerror(200807235);
+ end;
+
+
+ function tparamanager.parsefuncretloc(p: tabstractprocdef; const s: string): boolean;
+ begin
+ Result:=False;
+ internalerror(200807236);
+ end;
+
+
+ function tparamanager.use_fixed_stack: boolean;
+ begin
+{$ifdef i386}
+ result := (target_info.system in [system_i386_darwin,system_i386_iphonesim]);
+{$else i386}
+{$ifdef cputargethasfixedstack}
+ result := true;
+{$else cputargethasfixedstack}
+ result := false;
+{$endif cputargethasfixedstack}
+{$endif i386}
+ end;
+
+ { This is a separate function because at least win64 allows stack allocations
+ despite of fixed stack semantics (actually supporting it requires generating
+ a compliant stack frame, not yet possible) }
+ function tparamanager.use_stackalloc: boolean;
+ begin
+ result:=not use_fixed_stack;
+ end;
+
+initialization
+ ;
+finalization
+ paramanager.free;
+end.
diff --git a/closures/compiler/parser.pas b/closures/compiler/parser.pas
new file mode 100644
index 0000000000..56a2a5cfdf
--- /dev/null
+++ b/closures/compiler/parser.pas
@@ -0,0 +1,529 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit does the parsing process
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit parser;
+
+{$i fpcdefs.inc}
+
+interface
+
+{$ifdef PREPROCWRITE}
+ procedure preprocess(const filename:string);
+{$endif PREPROCWRITE}
+ procedure compile(const filename:string);
+ procedure initparser;
+ procedure doneparser;
+
+implementation
+
+ uses
+{$IFNDEF USE_FAKE_SYSUTILS}
+ sysutils,
+{$ELSE}
+ fksysutl,
+{$ENDIF}
+ cutils,cclasses,
+ globtype,version,tokens,systems,globals,verbose,switches,
+ symbase,symtable,symdef,symsym,
+ finput,fmodule,fppu,
+ aasmbase,aasmtai,aasmdata,
+ cgbase,
+ script,gendef,
+ comphook,
+ scanner,scandir,
+ pbase,ptype,psystem,pmodules,psub,ncgrtti,htypechk,
+ cresstr,cpuinfo,procinfo;
+
+
+ procedure initparser;
+ begin
+ { Current compiled module/proc }
+ set_current_module(nil);
+ current_module:=nil;
+ current_asmdata:=nil;
+ current_procinfo:=nil;
+ current_structdef:=nil;
+ current_genericdef:=nil;
+ current_specializedef:=nil;
+
+ loaded_units:=TLinkedList.Create;
+
+ usedunits:=TLinkedList.Create;
+
+ unloaded_units:=TLinkedList.Create;
+
+ { global switches }
+ current_settings.globalswitches:=init_settings.globalswitches;
+
+ current_settings.sourcecodepage:=init_settings.sourcecodepage;
+
+ { initialize scanner }
+ InitScanner;
+ InitScannerDirectives;
+
+ { scanner }
+ c:=#0;
+ pattern:='';
+ orgpattern:='';
+ cstringpattern:='';
+ current_scanner:=nil;
+ switchesstatestackpos:=0;
+
+ { register all nodes and tais }
+ registernodes;
+ registertais;
+
+ { memory sizes }
+ if stacksize=0 then
+ stacksize:=target_info.stacksize;
+
+ { RTTI writer }
+ RTTIWriter:=TRTTIWriter.Create;
+
+ { open assembler response }
+ if cs_link_on_target in current_settings.globalswitches then
+ GenerateAsmRes(outputexedir+ChangeFileExt(inputfilename,'_ppas'))
+ else
+ GenerateAsmRes(outputexedir+'ppas');
+
+ { open deffile }
+ DefFile:=TDefFile.Create(outputexedir+ChangeFileExt(inputfilename,target_info.defext));
+
+ { list of generated .o files, so the linker can remove them }
+ SmartLinkOFiles:=TCmdStrList.Create;
+
+ { codegen }
+ if paraprintnodetree<>0 then
+ printnode_reset;
+
+ { target specific stuff }
+ case target_info.system of
+ system_powerpc_amiga:
+ include(supported_calling_conventions,pocall_syscall);
+ system_powerpc_morphos:
+ include(supported_calling_conventions,pocall_syscall);
+ system_m68k_amiga:
+ include(supported_calling_conventions,pocall_syscall);
+ end;
+ end;
+
+
+ procedure doneparser;
+ begin
+ { Reset current compiling info, so destroy routines can't
+ reference the data that might already be destroyed }
+ set_current_module(nil);
+ current_module:=nil;
+ current_procinfo:=nil;
+ current_asmdata:=nil;
+ current_structdef:=nil;
+ current_genericdef:=nil;
+ current_specializedef:=nil;
+
+ { unload units }
+ if assigned(loaded_units) then
+ begin
+ loaded_units.free;
+ loaded_units:=nil;
+ end;
+ if assigned(usedunits) then
+ begin
+ usedunits.free;
+ usedunits:=nil;
+ end;
+ if assigned(unloaded_units) then
+ begin
+ unloaded_units.free;
+ unloaded_units:=nil;
+ end;
+
+ { if there was an error in the scanner, the scanner is
+ still assinged }
+ if assigned(current_scanner) then
+ begin
+ current_scanner.free;
+ current_scanner:=nil;
+ end;
+
+ { close scanner }
+ DoneScanner;
+
+ RTTIWriter.free;
+
+ { close ppas,deffile }
+ asmres.free;
+ deffile.free;
+
+ { free list of .o files }
+ SmartLinkOFiles.Free;
+ end;
+
+
+
+
+{$ifdef PREPROCWRITE}
+ procedure preprocess(const filename:string);
+ var
+ i : longint;
+ begin
+ new(preprocfile,init('pre'));
+ { initialize a module }
+ set_current_module(new(pmodule,init(filename,false)));
+
+ macrosymtablestack:= initialmacrosymtable;
+ current_module.localmacrosymtable:= tmacrosymtable.create(false);
+ current_module.localmacrosymtable.next:= initialmacrosymtable;
+ macrosymtablestack:= current_module.localmacrosymtable;
+
+ main_module:=current_module;
+ { startup scanner, and save in current_module }
+ current_scanner:=new(pscannerfile,Init(filename));
+ current_module.scanner:=current_scanner;
+ { loop until EOF is found }
+ repeat
+ current_scanner^.readtoken(true);
+ preprocfile^.AddSpace;
+ case token of
+ _ID :
+ begin
+ preprocfile^.Add(orgpattern);
+ end;
+ _REALNUMBER,
+ _INTCONST :
+ preprocfile^.Add(pattern);
+ _CSTRING :
+ begin
+ i:=0;
+ while (i<length(cstringpattern)) do
+ begin
+ inc(i);
+ if cstringpattern[i]='''' then
+ begin
+ insert('''',cstringpattern,i);
+ inc(i);
+ end;
+ end;
+ preprocfile^.Add(''''+cstringpattern+'''');
+ end;
+ _CCHAR :
+ begin
+ case pattern[1] of
+ #39 :
+ pattern:='''''''';
+ #0..#31,
+ #128..#255 :
+ begin
+ str(ord(pattern[1]),pattern);
+ pattern:='#'+pattern;
+ end;
+ else
+ pattern:=''''+pattern[1]+'''';
+ end;
+ preprocfile^.Add(pattern);
+ end;
+ _EOF :
+ break;
+ else
+ preprocfile^.Add(tokeninfo^[token].str)
+ end;
+ until false;
+ { free scanner }
+ dispose(current_scanner,done);
+ current_scanner:=nil;
+ { close }
+ dispose(preprocfile,done);
+ end;
+{$endif PREPROCWRITE}
+
+
+{*****************************************************************************
+ Compile a source file
+*****************************************************************************}
+
+ procedure compile(const filename:string);
+ type
+ polddata=^tolddata;
+ tolddata=record
+ { scanner }
+ oldidtoken,
+ oldtoken : ttoken;
+ oldtokenpos : tfileposinfo;
+ oldc : char;
+ oldpattern,
+ oldorgpattern : string;
+ old_block_type : tblock_type;
+ { symtable }
+ oldsymtablestack,
+ oldmacrosymtablestack : TSymtablestack;
+ oldaktprocsym : tprocsym;
+ { cg }
+ oldparse_only : boolean;
+ { akt.. things }
+ oldcurrent_filepos : tfileposinfo;
+ old_current_module : tmodule;
+ oldcurrent_procinfo : tprocinfo;
+ old_settings : tsettings;
+ old_switchesstatestack : tswitchesstatestack;
+ old_switchesstatestackpos : Integer;
+ end;
+
+ var
+ olddata : polddata;
+ hp,hp2 : tmodule;
+ begin
+ { parsing a procedure or declaration should be finished }
+ if assigned(current_procinfo) then
+ internalerror(200811121);
+ if assigned(current_structdef) then
+ internalerror(200811122);
+ inc(compile_level);
+ parser_current_file:=filename;
+ { Uses heap memory instead of placing everything on the
+ stack. This is needed because compile() can be called
+ recursively }
+ new(olddata);
+ with olddata^ do
+ begin
+ old_current_module:=current_module;
+
+ { save symtable state }
+ oldsymtablestack:=symtablestack;
+ oldmacrosymtablestack:=macrosymtablestack;
+ oldcurrent_procinfo:=current_procinfo;
+
+ { save scanner state }
+ oldc:=c;
+ oldpattern:=pattern;
+ oldorgpattern:=orgpattern;
+ oldtoken:=token;
+ oldidtoken:=idtoken;
+ old_block_type:=block_type;
+ oldtokenpos:=current_tokenpos;
+ old_switchesstatestack:=switchesstatestack;
+ old_switchesstatestackpos:=switchesstatestackpos;
+
+ { save cg }
+ oldparse_only:=parse_only;
+
+ { save akt... state }
+ { handle the postponed case first }
+ flushpendingswitchesstate;
+ oldcurrent_filepos:=current_filepos;
+ old_settings:=current_settings;
+ end;
+
+ { reset parser, a previous fatal error could have left these variables in an unreliable state, this is
+ important for the IDE }
+ afterassignment:=false;
+ in_args:=false;
+ named_args_allowed:=false;
+ got_addrn:=false;
+ getprocvardef:=nil;
+ allow_array_constructor:=false;
+
+ { show info }
+ Message1(parser_i_compiling,filename);
+
+ { reset symtable }
+ symtablestack:=tdefawaresymtablestack.create;
+ macrosymtablestack:=TSymtablestack.create;
+ systemunit:=nil;
+ current_settings.defproccall:=init_settings.defproccall;
+ current_exceptblock:=0;
+ exceptblockcounter:=0;
+ current_settings.maxfpuregisters:=-1;
+ current_settings.pmessage:=nil;
+ { reset the unit or create a new program }
+ { a unit compiled at command line must be inside the loaded_unit list }
+ if (compile_level=1) then
+ begin
+ if assigned(current_module) then
+ internalerror(200501158);
+ set_current_module(tppumodule.create(nil,'',filename,false));
+ addloadedunit(current_module);
+ main_module:=current_module;
+ current_module.state:=ms_compile;
+ end;
+ if not(assigned(current_module) and
+ (current_module.state in [ms_compile,ms_second_compile])) then
+ internalerror(200212281);
+
+ { Load current state from the init values }
+ current_settings:=init_settings;
+
+ { load current asmdata from current_module }
+ current_asmdata:=TAsmData(current_module.asmdata);
+
+ { startup scanner and load the first file }
+ current_scanner:=tscannerfile.Create(filename);
+ current_scanner.firstfile;
+ current_module.scanner:=current_scanner;
+
+ { init macros before anything in the file is parsed.}
+ current_module.localmacrosymtable:= tmacrosymtable.create(false);
+ macrosymtablestack.push(initialmacrosymtable);
+ macrosymtablestack.push(current_module.localmacrosymtable);
+
+ { read the first token }
+ current_scanner.readtoken(false);
+
+ { If the compile level > 1 we get a nice "unit expected" error
+ message if we are trying to use a program as unit.}
+ try
+ try
+ if (token=_UNIT) or (compile_level>1) then
+ begin
+ current_module.is_unit:=true;
+ proc_unit;
+ end
+ else if (token=_ID) and (idtoken=_PACKAGE) then
+ begin
+ current_module.IsPackage:=true;
+ proc_package;
+ end
+ else
+ proc_program(token=_LIBRARY);
+ except
+ on ECompilerAbort do
+ raise;
+ on Exception do
+ begin
+ { Increase errorcounter to prevent some
+ checks during cleanup }
+ inc(status.errorcount);
+ raise;
+ end;
+ end;
+ finally
+ if assigned(current_module) then
+ begin
+ { module is now compiled }
+ tppumodule(current_module).state:=ms_compiled;
+
+ { free ppu }
+ if assigned(tppumodule(current_module).ppufile) then
+ begin
+ tppumodule(current_module).ppufile.free;
+ tppumodule(current_module).ppufile:=nil;
+ end;
+
+ { free asmdata }
+ if assigned(current_module.asmdata) then
+ begin
+ current_module.asmdata.free;
+ current_module.asmdata:=nil;
+ end;
+
+ { free scanner }
+ if assigned(current_module.scanner) then
+ begin
+ if current_scanner=tscannerfile(current_module.scanner) then
+ current_scanner:=nil;
+ tscannerfile(current_module.scanner).free;
+ current_module.scanner:=nil;
+ end;
+
+ { free symtable stack }
+ if assigned(symtablestack) then
+ begin
+ symtablestack.free;
+ symtablestack:=nil;
+ end;
+ if assigned(macrosymtablestack) then
+ begin
+ macrosymtablestack.free;
+ macrosymtablestack:=nil;
+ end;
+ end;
+
+ if (compile_level=1) and
+ (status.errorcount=0) then
+ { Write Browser Collections }
+ do_extractsymbolinfo;
+
+ with olddata^ do
+ begin
+ { restore scanner }
+ c:=oldc;
+ pattern:=oldpattern;
+ orgpattern:=oldorgpattern;
+ token:=oldtoken;
+ idtoken:=oldidtoken;
+ current_tokenpos:=oldtokenpos;
+ block_type:=old_block_type;
+ switchesstatestack:=old_switchesstatestack;
+ switchesstatestackpos:=old_switchesstatestackpos;
+
+ { restore cg }
+ parse_only:=oldparse_only;
+
+ { restore symtable state }
+ symtablestack:=oldsymtablestack;
+ macrosymtablestack:=oldmacrosymtablestack;
+ current_procinfo:=oldcurrent_procinfo;
+ current_filepos:=oldcurrent_filepos;
+ current_settings:=old_settings;
+ { Restore all locally modified warning messages }
+ RestoreLocalVerbosity(current_settings.pmessage);
+ current_exceptblock:=0;
+ exceptblockcounter:=0;
+ end;
+ { Shut down things when the last file is compiled succesfull }
+ if (compile_level=1) and
+ (status.errorcount=0) then
+ begin
+ parser_current_file:='';
+ { Close script }
+ if (not AsmRes.Empty) then
+ begin
+ Message1(exec_i_closing_script,AsmRes.Fn);
+ AsmRes.WriteToDisk;
+ end;
+ end;
+
+ { free now what we did not free earlier in
+ proc_program PM }
+ if (compile_level=1) and needsymbolinfo then
+ begin
+ hp:=tmodule(loaded_units.first);
+ while assigned(hp) do
+ begin
+ hp2:=tmodule(hp.next);
+ if (hp<>current_module) then
+ begin
+ loaded_units.remove(hp);
+ hp.free;
+ end;
+ hp:=hp2;
+ end;
+ { free also unneeded units we didn't free before }
+ unloaded_units.Clear;
+ end;
+ dec(compile_level);
+ set_current_module(olddata^.old_current_module);
+
+ FreeLocalVerbosity(current_settings.pmessage);
+
+ dispose(olddata);
+ end;
+ end;
+
+end.
diff --git a/closures/compiler/pass_1.pas b/closures/compiler/pass_1.pas
new file mode 100644
index 0000000000..41f5cbcb9c
--- /dev/null
+++ b/closures/compiler/pass_1.pas
@@ -0,0 +1,253 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit handles the pass_typecheck and node conversion pass
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit pass_1;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node;
+
+ procedure typecheckpass(var p : tnode);
+ function do_typecheckpass(var p : tnode) : boolean;
+ function do_typecheckpass_changed(var p : tnode; out nodechanged: boolean) : boolean;
+
+ procedure firstpass(var p : tnode);
+ function do_firstpass(var p : tnode) : boolean;
+{$ifdef state_tracking}
+ procedure do_track_state_pass(p:Tnode);
+{$endif}
+
+
+implementation
+
+ uses
+ globtype,comphook,systems,cclasses,
+ cutils,globals,
+ procinfo,
+ cgbase,symdef
+{$ifdef extdebug}
+ ,verbose,htypechk
+{$endif extdebug}
+{$ifdef state_tracking}
+ ,nstate
+{$endif}
+ ;
+
+{*****************************************************************************
+ Global procedures
+*****************************************************************************}
+
+ procedure typecheckpass_internal(var p : tnode; out node_changed: boolean);
+ var
+ oldcodegenerror : boolean;
+ oldlocalswitches : tlocalswitches;
+ oldverbosity : longint;
+ oldpos : tfileposinfo;
+ hp : tnode;
+ begin
+ node_changed:=false;
+ if (p.resultdef=nil) then
+ begin
+ oldcodegenerror:=codegenerror;
+ oldpos:=current_filepos;
+ oldlocalswitches:=current_settings.localswitches;
+ oldverbosity:=status.verbosity;
+ codegenerror:=false;
+ current_filepos:=p.fileinfo;
+ current_settings.localswitches:=p.localswitches;
+ status.verbosity:=p.verbosity;
+ hp:=p.pass_typecheck;
+ { should the node be replaced? }
+ if assigned(hp) then
+ begin
+ node_changed:=true;
+ p.free;
+ { switch to new node }
+ p:=hp;
+ { run typecheckpass }
+ typecheckpass(p);
+ end;
+ current_settings.localswitches:=oldlocalswitches;
+ current_filepos:=oldpos;
+ status.verbosity:=oldverbosity;
+ if codegenerror then
+ begin
+ include(p.flags,nf_error);
+ { default to errortype if no type is set yet }
+ if p.resultdef=nil then
+ p.resultdef:=generrordef;
+ end;
+ codegenerror:=codegenerror or oldcodegenerror;
+ end
+ else
+ begin
+ { update the codegenerror boolean with the previous result of this node }
+ if (nf_error in p.flags) then
+ codegenerror:=true;
+ end;
+ end;
+
+
+ procedure typecheckpass(var p : tnode);
+ var
+ node_changed: boolean;
+ begin
+ typecheckpass_internal(p,node_changed);
+ end;
+
+
+ function do_typecheckpass_changed(var p : tnode; out nodechanged: boolean) : boolean;
+ begin
+ codegenerror:=false;
+ typecheckpass_internal(p,nodechanged);
+ do_typecheckpass_changed:=codegenerror;
+ end;
+
+
+ function do_typecheckpass(var p : tnode) : boolean;
+ var
+ nodechanged: boolean;
+ begin
+ result:=do_typecheckpass_changed(p,nodechanged);
+ end;
+
+
+ procedure firstpass(var p : tnode);
+ var
+ oldcodegenerror : boolean;
+ oldlocalswitches : tlocalswitches;
+ oldpos : tfileposinfo;
+ oldverbosity: longint;
+ hp : tnode;
+ begin
+ if (nf_pass1_done in p.flags) then
+ exit;
+ if not(nf_error in p.flags) then
+ begin
+ oldcodegenerror:=codegenerror;
+ oldpos:=current_filepos;
+ oldlocalswitches:=current_settings.localswitches;
+ oldverbosity:=status.verbosity;
+ codegenerror:=false;
+ current_filepos:=p.fileinfo;
+ current_settings.localswitches:=p.localswitches;
+ status.verbosity:=p.verbosity;
+ { checks make always a call }
+ if ([cs_check_range,cs_check_overflow,cs_check_stack] * current_settings.localswitches <> []) then
+ include(current_procinfo.flags,pi_do_call);
+ { determine the resultdef if not done }
+ if (p.resultdef=nil) then
+ begin
+ hp:=p.pass_typecheck;
+ { should the node be replaced? }
+ if assigned(hp) then
+ begin
+ p.free;
+ { switch to new node }
+ p:=hp;
+ { run typecheckpass }
+ typecheckpass(p);
+ end;
+ if codegenerror then
+ begin
+ include(p.flags,nf_error);
+ { default to errortype if no type is set yet }
+ if p.resultdef=nil then
+ p.resultdef:=generrordef;
+ end;
+ codegenerror:=codegenerror or oldcodegenerror;
+ end;
+ if not(nf_error in p.flags) then
+ begin
+ { first pass }
+ hp:=p.pass_1;
+ { should the node be replaced? }
+ if assigned(hp) then
+ begin
+ p.free;
+ { switch to new node }
+ p := hp;
+ { run firstpass }
+ firstpass(p);
+ end
+ else
+ begin
+ { inlining happens in pass_1 and can cause new }
+ { simplify opportunities }
+ hp:=p.simplify(true);
+ if assigned(hp) then
+ begin
+ p.free;
+ p := hp;
+ firstpass(p);
+ end;
+ end;
+ if codegenerror then
+ include(p.flags,nf_error)
+ else
+ begin
+{$ifdef EXTDEBUG}
+ if (p.expectloc=LOC_INVALID) then
+ Comment(V_Warning,'Expectloc is not set in firstpass: '+nodetype2str[p.nodetype]);
+{$endif EXTDEBUG}
+ end;
+ end;
+ include(p.flags,nf_pass1_done);
+ codegenerror:=codegenerror or oldcodegenerror;
+ current_settings.localswitches:=oldlocalswitches;
+ current_filepos:=oldpos;
+ status.verbosity:=oldverbosity;
+ end
+ else
+ codegenerror:=true;
+ end;
+
+
+ function do_firstpass(var p : tnode) : boolean;
+ begin
+ codegenerror:=false;
+ firstpass(p);
+{$ifdef state_tracking}
+ writeln('TRACKSTART');
+ writeln('before');
+ writenode(p);
+ do_track_state_pass(p);
+ writeln('after');
+ writenode(p);
+ writeln('TRACKDONE');
+{$endif}
+ do_firstpass:=codegenerror;
+ end;
+
+{$ifdef state_tracking}
+ procedure do_track_state_pass(p:Tnode);
+
+ begin
+ aktstate:=Tstate_storage.create;
+ p.track_state_pass(true);
+ aktstate.destroy;
+ end;
+{$endif}
+
+end.
diff --git a/closures/compiler/pass_2.pas b/closures/compiler/pass_2.pas
new file mode 100644
index 0000000000..2aa9879912
--- /dev/null
+++ b/closures/compiler/pass_2.pas
@@ -0,0 +1,234 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit handles the codegeneration pass
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit pass_2;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ node;
+
+ type
+ tenumflowcontrol = (
+ fc_exit,
+ fc_break,
+ fc_continue,
+ fc_inflowcontrol,
+ fc_gotolabel,
+ { in try block of try..finally }
+ fc_unwind,
+ { the left side of an expression is already handled, so we are
+ not allowed to do ssl }
+ fc_lefthandled);
+
+ tflowcontrol = set of tenumflowcontrol;
+
+ var
+ flowcontrol : tflowcontrol;
+
+{ produces the actual code }
+function do_secondpass(var p : tnode) : boolean;
+procedure secondpass(var p : tnode);
+
+
+implementation
+
+ uses
+{$ifdef EXTDEBUG}
+ cutils,
+{$endif}
+ globtype,systems,verbose,
+ globals,
+ paramgr,
+ aasmtai,aasmdata,
+ cgbase,
+ nflw,cgobj;
+
+{*****************************************************************************
+ SecondPass
+*****************************************************************************}
+
+{$ifdef EXTDEBUG}
+ var
+ secondprefix : string;
+
+ procedure logsecond(ht:tnodetype; entry: boolean);
+ const
+ secondnames: array[tnodetype] of string[13] =
+ ('<emptynode>',
+ 'add-addn', {addn}
+ 'add-muln', {muln}
+ 'add-subn', {subn}
+ 'moddiv-divn', {divn}
+ 'add-symdifn', {symdifn}
+ 'moddiv-modn', {modn}
+ 'assignment', {assignn}
+ 'load', {loadn}
+ 'nothing-range', {range}
+ 'add-ltn', {ltn}
+ 'add-lten', {lten}
+ 'add-gtn', {gtn}
+ 'add-gten', {gten}
+ 'add-equaln', {equaln}
+ 'add-unequaln', {unequaln}
+ 'in', {inn}
+ 'add-orn', {orn}
+ 'add-xorn', {xorn}
+ 'shlshr-shrn', {shrn}
+ 'shlshr-shln', {shln}
+ 'add-slashn', {slashn}
+ 'add-andn', {andn}
+ 'subscriptn', {subscriptn}
+ 'deref', {derefn}
+ 'addr', {addrn}
+ 'ordconst', {ordconstn}
+ 'typeconv', {typeconvn}
+ 'calln', {calln}
+ 'noth-callpar',{callparan}
+ 'realconst', {realconstn}
+ 'unaryminus', {unaryminusn}
+ 'unaryplus', {unaryplusn}
+ 'asm', {asmn}
+ 'vecn', {vecn}
+ 'pointerconst',{pointerconstn}
+ 'stringconst', {stringconstn}
+ 'not', {notn}
+ 'inline', {inlinen}
+ 'niln', {niln}
+ 'error', {errorn}
+ 'nothing-typen', {typen}
+ 'setelement', {setelementn}
+ 'setconst', {setconstn}
+ 'blockn', {blockn}
+ 'statement', {statementn}
+ 'ifn', {ifn}
+ 'breakn', {breakn}
+ 'continuen', {continuen}
+ 'while_repeat', {whilerepeatn}
+ 'for', {forn}
+ 'exitn', {exitn}
+ 'with', {withn}
+ 'case', {casen}
+ 'label', {labeln}
+ 'goto', {goton}
+ 'tryexcept', {tryexceptn}
+ 'raise', {raisen}
+ 'tryfinally', {tryfinallyn}
+ 'on', {onn}
+ 'is', {isn}
+ 'as', {asn}
+ 'add-starstar', {starstarn}
+ 'arrayconstruc', {arrayconstructn}
+ 'noth-arrcnstr', {arrayconstructrangen}
+ 'tempcreaten',
+ 'temprefn',
+ 'tempdeleten',
+ 'addoptn',
+ 'nothing-nothg', {nothingn}
+ 'loadvmt', {loadvmtn}
+ 'guidconstn',
+ 'rttin',
+ 'loadparentfpn',
+ 'dataconstn',
+ 'objselectorn',
+ 'objcprotocoln'
+ );
+ var
+ p: pchar;
+ begin
+ if entry then
+ begin
+ secondprefix:=secondprefix+' ';
+ p := strpnew(secondprefix+'second '+secondnames[ht]+' (entry)')
+ end
+ else
+ begin
+ p := strpnew(secondprefix+'second '+secondnames[ht]+' (exit)');
+ delete(secondprefix,length(secondprefix),1);
+ end;
+ current_asmdata.CurrAsmList.concat(tai_comment.create(p));
+ end;
+{$endif EXTDEBUG}
+
+ procedure secondpass(var p : tnode);
+ var
+ oldcodegenerror : boolean;
+ oldlocalswitches : tlocalswitches;
+ oldpos : tfileposinfo;
+ begin
+ if not assigned(p) then
+ internalerror(200208221);
+ if not(nf_error in p.flags) then
+ begin
+ oldcodegenerror:=codegenerror;
+ oldlocalswitches:=current_settings.localswitches;
+ oldpos:=current_filepos;
+ current_filepos:=p.fileinfo;
+ current_settings.localswitches:=p.localswitches;
+ codegenerror:=false;
+{$ifdef EXTDEBUG}
+ if (p.expectloc=LOC_INVALID) then
+ Comment(V_Warning,'ExpectLoc is not set before secondpass: '+nodetype2str[p.nodetype]);
+ if (p.location.loc<>LOC_INVALID) then
+ Comment(V_Warning,'Location.Loc is already set before secondpass: '+nodetype2str[p.nodetype]);
+ if (cs_asm_nodes in current_settings.globalswitches) then
+ logsecond(p.nodetype,true);
+{$endif EXTDEBUG}
+ p.pass_generate_code;
+{$ifdef EXTDEBUG}
+ if (cs_asm_nodes in current_settings.globalswitches) then
+ logsecond(p.nodetype,false);
+ if (not codegenerror) then
+ begin
+ if (p.location.loc<>p.expectloc) then
+ Comment(V_Warning,'Location ('+tcgloc2str[p.location.loc]+') not equal to expectloc ('+tcgloc2str[p.expectloc]+'): '+nodetype2str[p.nodetype]);
+ if (p.location.loc=LOC_INVALID) then
+ Comment(V_Warning,'Location not set in secondpass: '+nodetype2str[p.nodetype]);
+ end;
+{$endif EXTDEBUG}
+ if codegenerror then
+ include(p.flags,nf_error);
+ codegenerror:=codegenerror or oldcodegenerror;
+ current_settings.localswitches:=oldlocalswitches;
+ current_filepos:=oldpos;
+ end
+ else
+ codegenerror:=true;
+ end;
+
+
+ function do_secondpass(var p : tnode) : boolean;
+ begin
+ { current_asmdata.CurrAsmList must be empty }
+ if not current_asmdata.CurrAsmList.empty then
+ internalerror(200405201);
+
+ { clear errors before starting }
+ codegenerror:=false;
+ if not(nf_error in p.flags) then
+ secondpass(p);
+ do_secondpass:=codegenerror;
+ end;
+
+
+end.
diff --git a/closures/compiler/pbase.pas b/closures/compiler/pbase.pas
new file mode 100644
index 0000000000..6478711aa6
--- /dev/null
+++ b/closures/compiler/pbase.pas
@@ -0,0 +1,379 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Contains some helper routines for the parser
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit pbase;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cutils,cclasses,
+ tokens,globtype,
+ symconst,symbase,symtype,symdef,symsym,symtable
+ ;
+
+ const
+ { tokens that end a block or statement. And don't require
+ a ; on the statement before }
+ endtokens = [_SEMICOLON,_END,_ELSE,_UNTIL,_EXCEPT,_FINALLY];
+
+ { true, if we are after an assignement }
+ afterassignment : boolean = false;
+
+ { true, if we are parsing arguments }
+ in_args : boolean = false;
+
+ { true, if we are parsing arguments allowing named parameters }
+ named_args_allowed : boolean = false;
+
+ { true, if we got an @ to get the address }
+ got_addrn : boolean = false;
+
+ { special for handling procedure vars }
+ getprocvardef : tprocvardef = nil;
+
+ var
+ { for operators }
+ optoken : ttoken;
+
+ { true, if only routine headers should be parsed }
+ parse_only : boolean;
+
+ { true, if we found a name for a named arg }
+ found_arg_name : boolean;
+
+ { true, if we are parsing generic declaration }
+ parse_generic : boolean;
+
+ procedure identifier_not_found(const s:string);
+
+{ function tokenstring(i : ttoken):string;}
+
+ { consumes token i, if the current token is unequal i }
+ { a syntax error is written }
+ procedure consume(i : ttoken);
+
+ {Tries to consume the token i, and returns true if it was consumed:
+ if token=i.}
+ function try_to_consume(i:Ttoken):boolean;
+
+ { consumes all tokens til atoken (for error recovering }
+ procedure consume_all_until(atoken : ttoken);
+
+ { consumes tokens while they are semicolons }
+ procedure consume_emptystats;
+
+ { reads a list of identifiers into a string list }
+ { consume a symbol, if not found give an error and
+ and return an errorsym }
+ function consume_sym(var srsym:tsym;var srsymtable:TSymtable):boolean;
+ function consume_sym_orgid(var srsym:tsym;var srsymtable:TSymtable;var s : string):boolean;
+
+ function try_consume_unitsym(var srsym:tsym;var srsymtable:TSymtable;var tokentoconsume:ttoken;consume_id:boolean):boolean;
+
+ function try_consume_hintdirective(var symopt:tsymoptions; var deprecatedmsg:pshortstring):boolean;
+
+ { just for an accurate position of the end of a procedure (PM) }
+ var
+ last_endtoken_filepos: tfileposinfo;
+
+
+implementation
+
+ uses
+ globals,htypechk,scanner,systems,verbose,fmodule;
+
+{****************************************************************************
+ Token Parsing
+****************************************************************************}
+
+ procedure identifier_not_found(const s:string);
+ begin
+ Message1(sym_e_id_not_found,s);
+ { show a fatal that you need -S2 or -Sd, but only
+ if we just parsed the a token that has m_class }
+ if not(m_class in current_settings.modeswitches) and
+ (Upper(s)=pattern) and
+ (tokeninfo^[idtoken].keyword=m_class) then
+ Message(parser_f_need_objfpc_or_delphi_mode);
+ end;
+
+
+ { consumes token i, write error if token is different }
+ procedure consume(i : ttoken);
+ begin
+ if (token<>i) and (idtoken<>i) then
+ if token=_id then
+ Message2(scan_f_syn_expected,tokeninfo^[i].str,'identifier '+pattern)
+ else
+ Message2(scan_f_syn_expected,tokeninfo^[i].str,tokeninfo^[token].str)
+ else
+ begin
+ if token=_END then
+ last_endtoken_filepos:=current_tokenpos;
+ current_scanner.readtoken(true);
+ end;
+ end;
+
+
+ function try_to_consume(i:Ttoken):boolean;
+ begin
+ try_to_consume:=false;
+ if (token=i) or (idtoken=i) then
+ begin
+ try_to_consume:=true;
+ if token=_END then
+ last_endtoken_filepos:=current_tokenpos;
+ current_scanner.readtoken(true);
+ end;
+ end;
+
+
+ procedure consume_all_until(atoken : ttoken);
+ begin
+ while (token<>atoken) and (idtoken<>atoken) do
+ begin
+ Consume(token);
+ if token=_EOF then
+ begin
+ Consume(atoken);
+ Message(scan_f_end_of_file);
+ exit;
+ end;
+ end;
+ end;
+
+
+ procedure consume_emptystats;
+ begin
+ repeat
+ until not try_to_consume(_SEMICOLON);
+ end;
+
+
+ { check if a symbol contains the hint directive, and if so gives out a hint
+ if required.
+
+ If this code is changed, it's likly that consume_sym_orgid and factor_read_id
+ must be changed as well (FK)
+ }
+ function consume_sym(var srsym:tsym;var srsymtable:TSymtable):boolean;
+ var
+ t : ttoken;
+ begin
+ { first check for identifier }
+ if token<>_ID then
+ begin
+ consume(_ID);
+ srsym:=generrorsym;
+ srsymtable:=nil;
+ result:=false;
+ exit;
+ end;
+ searchsym(pattern,srsym,srsymtable);
+ { handle unit specification like System.Writeln }
+ try_consume_unitsym(srsym,srsymtable,t,true);
+ { if nothing found give error and return errorsym }
+ if assigned(srsym) then
+ check_hints(srsym,srsym.symoptions,srsym.deprecatedmsg)
+ else
+ begin
+ identifier_not_found(orgpattern);
+ srsym:=generrorsym;
+ srsymtable:=nil;
+ end;
+ consume(t);
+ result:=assigned(srsym);
+ end;
+
+
+ { check if a symbol contains the hint directive, and if so gives out a hint
+ if required and returns the id with it's original casing
+ }
+ function consume_sym_orgid(var srsym:tsym;var srsymtable:TSymtable;var s : string):boolean;
+ var
+ t : ttoken;
+ begin
+ { first check for identifier }
+ if token<>_ID then
+ begin
+ consume(_ID);
+ srsym:=generrorsym;
+ srsymtable:=nil;
+ result:=false;
+ exit;
+ end;
+ searchsym(pattern,srsym,srsymtable);
+ { handle unit specification like System.Writeln }
+ try_consume_unitsym(srsym,srsymtable,t,true);
+ { if nothing found give error and return errorsym }
+ if assigned(srsym) then
+ check_hints(srsym,srsym.symoptions,srsym.deprecatedmsg)
+ else
+ begin
+ identifier_not_found(orgpattern);
+ srsym:=generrorsym;
+ srsymtable:=nil;
+ end;
+ s:=orgpattern;
+ consume(t);
+ result:=assigned(srsym);
+ end;
+
+
+ function try_consume_unitsym(var srsym:tsym;var srsymtable:TSymtable;var tokentoconsume:ttoken;consume_id:boolean):boolean;
+ var
+ hmodule: tmodule;
+ ns:ansistring;
+ nssym:tsym;
+ begin
+ result:=false;
+ tokentoconsume:=_ID;
+
+ if assigned(srsym) and (srsym.typ in [unitsym,namespacesym]) then
+ begin
+ if not(srsym.owner.symtabletype in [staticsymtable,globalsymtable]) then
+ internalerror(200501154);
+ { only allow unit.symbol access if the name was
+ found in the current module
+ we can use iscurrentunit because generic specializations does not
+ change current_unit variable }
+ hmodule:=find_module_from_symtable(srsym.Owner);
+ if not Assigned(hmodule) then
+ internalerror(201001120);
+ if hmodule.unit_index=current_filepos.moduleindex then
+ begin
+ if consume_id then
+ consume(_ID);
+ consume(_POINT);
+ if srsym.typ=namespacesym then
+ begin
+ ns:=srsym.name;
+ nssym:=srsym;
+ while assigned(srsym) and (srsym.typ=namespacesym) do
+ begin
+ { we have a namespace. the next identifier should be either a namespace or a unit }
+ searchsym_in_module(hmodule,ns+'.'+pattern,srsym,srsymtable);
+ if assigned(srsym) and (srsym.typ in [namespacesym,unitsym]) then
+ begin
+ ns:=ns+'.'+pattern;
+ nssym:=srsym;
+ consume(_ID);
+ consume(_POINT);
+ end;
+ end;
+ { check if there is a hidden unit with this pattern in the namespace }
+ if not assigned(srsym) and
+ assigned(nssym) and (nssym.typ=namespacesym) and assigned(tnamespacesym(nssym).unitsym) then
+ srsym:=tnamespacesym(nssym).unitsym;
+ if assigned(srsym) and (srsym.typ<>unitsym) then
+ internalerror(201108260);
+ if not assigned(srsym) then
+ begin
+ result:=true;
+ srsymtable:=nil;
+ exit;
+ end;
+ end;
+ case token of
+ _ID:
+ searchsym_in_module(tunitsym(srsym).module,pattern,srsym,srsymtable);
+ _STRING:
+ begin
+ { system.string? }
+ if tmodule(tunitsym(srsym).module).globalsymtable=systemunit then
+ begin
+ if cs_ansistrings in current_settings.localswitches then
+ searchsym_in_module(tunitsym(srsym).module,'ANSISTRING',srsym,srsymtable)
+ else
+ searchsym_in_module(tunitsym(srsym).module,'SHORTSTRING',srsym,srsymtable);
+ tokentoconsume:=_STRING;
+ end;
+ end
+ end;
+ end
+ else
+ begin
+ srsym:=nil;
+ srsymtable:=nil;
+ end;
+ result:=true;
+ end;
+ end;
+
+
+ function try_consume_hintdirective(var symopt:tsymoptions; var deprecatedmsg:pshortstring):boolean;
+ var
+ last_is_deprecated:boolean;
+ begin
+ try_consume_hintdirective:=false;
+ if not(m_hintdirective in current_settings.modeswitches) then
+ exit;
+ repeat
+ last_is_deprecated:=false;
+ case idtoken of
+ _LIBRARY :
+ begin
+ include(symopt,sp_hint_library);
+ try_consume_hintdirective:=true;
+ end;
+ _DEPRECATED :
+ begin
+ include(symopt,sp_hint_deprecated);
+ try_consume_hintdirective:=true;
+ last_is_deprecated:=true;
+ end;
+ _EXPERIMENTAL :
+ begin
+ include(symopt,sp_hint_experimental);
+ try_consume_hintdirective:=true;
+ end;
+ _PLATFORM :
+ begin
+ include(symopt,sp_hint_platform);
+ try_consume_hintdirective:=true;
+ end;
+ _UNIMPLEMENTED :
+ begin
+ include(symopt,sp_hint_unimplemented);
+ try_consume_hintdirective:=true;
+ end;
+ else
+ break;
+ end;
+ consume(Token);
+ { handle deprecated message }
+ if ((token=_CSTRING) or (token=_CCHAR)) and last_is_deprecated then
+ begin
+ if deprecatedmsg<>nil then
+ internalerror(200910181);
+ if token=_CSTRING then
+ deprecatedmsg:=stringdup(cstringpattern)
+ else
+ deprecatedmsg:=stringdup(pattern);
+ consume(token);
+ include(symopt,sp_has_deprecated_msg);
+ end;
+ until false;
+ end;
+
+end.
diff --git a/closures/compiler/pdecl.pas b/closures/compiler/pdecl.pas
new file mode 100644
index 0000000000..267f978e0a
--- /dev/null
+++ b/closures/compiler/pdecl.pas
@@ -0,0 +1,874 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Does declaration (but not type) parsing for Free Pascal
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit pdecl;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ { common }
+ cclasses,
+ { global }
+ globtype,
+ { symtable }
+ symsym,symdef,
+ { pass_1 }
+ node;
+
+ function readconstant(const orgname:string;const filepos:tfileposinfo):tconstsym;
+
+ procedure const_dec;
+ procedure consts_dec(in_structure: boolean);
+ procedure label_dec;
+ procedure type_dec;
+ procedure types_dec(in_structure: boolean);
+ procedure var_dec;
+ procedure threadvar_dec;
+ procedure property_dec(is_classpropery: boolean);
+ procedure resourcestring_dec;
+
+implementation
+
+ uses
+ SysUtils,
+ { common }
+ cutils,
+ { global }
+ globals,tokens,verbose,widestr,constexp,
+ systems,
+ { aasm }
+ aasmbase,aasmtai,aasmdata,fmodule,
+ { symtable }
+ symconst,symbase,symtype,symtable,paramgr,defutil,
+ { pass 1 }
+ nmat,nadd,ncal,nset,ncnv,ninl,ncon,nld,nflw,nobj,
+ { codegen }
+ ncgutil,
+ { parser }
+ scanner,
+ pbase,pexpr,ptype,ptconst,pdecsub,pdecvar,pdecobj,pgenutil,
+ { cpu-information }
+ cpuinfo
+ ;
+
+
+ function readconstant(const orgname:string;const filepos:tfileposinfo):tconstsym;
+ var
+ hp : tconstsym;
+ p : tnode;
+ ps : pconstset;
+ pd : pbestreal;
+ pg : pguid;
+ sp : pchar;
+ pw : pcompilerwidestring;
+ storetokenpos : tfileposinfo;
+ begin
+ readconstant:=nil;
+ if orgname='' then
+ internalerror(9584582);
+ hp:=nil;
+ p:=comp_expr(true,false);
+ storetokenpos:=current_tokenpos;
+ current_tokenpos:=filepos;
+ case p.nodetype of
+ ordconstn:
+ begin
+ if p.resultdef.typ=pointerdef then
+ hp:=tconstsym.create_ordptr(orgname,constpointer,tordconstnode(p).value.uvalue,p.resultdef)
+ else
+ hp:=tconstsym.create_ord(orgname,constord,tordconstnode(p).value,p.resultdef);
+ end;
+ stringconstn:
+ begin
+ if is_wide_or_unicode_string(p.resultdef) then
+ begin
+ initwidestring(pw);
+ copywidestring(pcompilerwidestring(tstringconstnode(p).value_str),pw);
+ hp:=tconstsym.create_wstring(orgname,constwstring,pw);
+ end
+ else
+ begin
+ getmem(sp,tstringconstnode(p).len+1);
+ move(tstringconstnode(p).value_str^,sp^,tstringconstnode(p).len+1);
+ hp:=tconstsym.create_string(orgname,conststring,sp,tstringconstnode(p).len);
+ end;
+ end;
+ realconstn :
+ begin
+ new(pd);
+ pd^:=trealconstnode(p).value_real;
+ hp:=tconstsym.create_ptr(orgname,constreal,pd,p.resultdef);
+ end;
+ setconstn :
+ begin
+ new(ps);
+ ps^:=tsetconstnode(p).value_set^;
+ hp:=tconstsym.create_ptr(orgname,constset,ps,p.resultdef);
+ end;
+ pointerconstn :
+ begin
+ hp:=tconstsym.create_ordptr(orgname,constpointer,tpointerconstnode(p).value,p.resultdef);
+ end;
+ niln :
+ begin
+ hp:=tconstsym.create_ord(orgname,constnil,0,p.resultdef);
+ end;
+ typen :
+ begin
+ if is_interface(p.resultdef) then
+ begin
+ if assigned(tobjectdef(p.resultdef).iidguid) then
+ begin
+ new(pg);
+ pg^:=tobjectdef(p.resultdef).iidguid^;
+ hp:=tconstsym.create_ptr(orgname,constguid,pg,p.resultdef);
+ end
+ else
+ Message1(parser_e_interface_has_no_guid,tobjectdef(p.resultdef).objrealname^);
+ end
+ else
+ Message(parser_e_illegal_expression);
+ end;
+ else
+ Message(parser_e_illegal_expression);
+ end;
+ current_tokenpos:=storetokenpos;
+ p.free;
+ readconstant:=hp;
+ end;
+
+ procedure const_dec;
+ begin
+ consume(_CONST);
+ consts_dec(false);
+ end;
+
+ procedure consts_dec(in_structure: boolean);
+ var
+ orgname : TIDString;
+ hdef : tdef;
+ sym, tmp : tsym;
+ dummysymoptions : tsymoptions;
+ deprecatedmsg : pshortstring;
+ storetokenpos,filepos : tfileposinfo;
+ old_block_type : tblock_type;
+ skipequal : boolean;
+ tclist : tasmlist;
+ varspez : tvarspez;
+ static_name : string;
+ sl : tpropaccesslist;
+ begin
+ old_block_type:=block_type;
+ block_type:=bt_const;
+ repeat
+ orgname:=orgpattern;
+ filepos:=current_tokenpos;
+ consume(_ID);
+ case token of
+
+ _EQ:
+ begin
+ consume(_EQ);
+ sym:=readconstant(orgname,filepos);
+ { Support hint directives }
+ dummysymoptions:=[];
+ deprecatedmsg:=nil;
+ try_consume_hintdirective(dummysymoptions,deprecatedmsg);
+ if assigned(sym) then
+ begin
+ sym.symoptions:=sym.symoptions+dummysymoptions;
+ sym.deprecatedmsg:=deprecatedmsg;
+ sym.visibility:=symtablestack.top.currentvisibility;
+ symtablestack.top.insert(sym);
+ end
+ else
+ stringdispose(deprecatedmsg);
+ consume(_SEMICOLON);
+ end;
+
+ _COLON:
+ begin
+ { set the blocktype first so a consume also supports a
+ caret, to support const s : ^string = nil }
+ block_type:=bt_const_type;
+ consume(_COLON);
+ read_anon_type(hdef,false);
+ block_type:=bt_const;
+ skipequal:=false;
+ { create symbol }
+ storetokenpos:=current_tokenpos;
+ current_tokenpos:=filepos;
+ if not (cs_typed_const_writable in current_settings.localswitches) then
+ varspez:=vs_const
+ else
+ varspez:=vs_value;
+ { if we are dealing with structure const then we need to handle it as a
+ structure static variable: create a symbol in unit symtable and a reference
+ to it from the structure or linking will fail }
+ if symtablestack.top.symtabletype in [recordsymtable,ObjectSymtable] then
+ begin
+ { generate the symbol which reserves the space }
+ static_name:=lower(generate_nested_name(symtablestack.top,'_'))+'_'+orgname;
+ sym:=tstaticvarsym.create('$_static_'+static_name,varspez,hdef,[]);
+ include(sym.symoptions,sp_internal);
+ tabstractrecordsymtable(symtablestack.top).get_unit_symtable.insert(sym);
+ { generate the symbol for the access }
+ sl:=tpropaccesslist.create;
+ sl.addsym(sl_load,sym);
+ tmp:=tabsolutevarsym.create_ref(orgname,hdef,sl);
+ tmp.visibility:=symtablestack.top.currentvisibility;
+ symtablestack.top.insert(tmp);
+ end
+ else
+ begin
+ sym:=tstaticvarsym.create(orgname,varspez,hdef,[]);
+ sym.visibility:=symtablestack.top.currentvisibility;
+ symtablestack.top.insert(sym);
+ end;
+ current_tokenpos:=storetokenpos;
+ { procvar can have proc directives, but not type references }
+ if (hdef.typ=procvardef) and
+ (hdef.typesym=nil) then
+ begin
+ { support p : procedure;stdcall=nil; }
+ if try_to_consume(_SEMICOLON) then
+ begin
+ if check_proc_directive(true) then
+ parse_var_proc_directives(sym)
+ else
+ begin
+ Message(parser_e_proc_directive_expected);
+ skipequal:=true;
+ end;
+ end
+ else
+ { support p : procedure stdcall=nil; }
+ begin
+ if check_proc_directive(true) then
+ parse_var_proc_directives(sym);
+ end;
+ { add default calling convention }
+ handle_calling_convention(tabstractprocdef(hdef));
+ end;
+ if not skipequal then
+ begin
+ { get init value }
+ consume(_EQ);
+ if (cs_typed_const_writable in current_settings.localswitches) then
+ tclist:=current_asmdata.asmlists[al_typedconsts]
+ else
+ tclist:=current_asmdata.asmlists[al_rotypedconsts];
+ read_typed_const(tclist,tstaticvarsym(sym),in_structure);
+ end;
+ end;
+
+ else
+ { generate an error }
+ consume(_EQ);
+ end;
+ until (token<>_ID)or(in_structure and (idtoken in [_PRIVATE,_PROTECTED,_PUBLIC,_PUBLISHED,_STRICT]));
+ block_type:=old_block_type;
+ end;
+
+
+ procedure label_dec;
+ var
+ labelsym : tlabelsym;
+ begin
+ consume(_LABEL);
+ if not(cs_support_goto in current_settings.moduleswitches) then
+ Message(sym_e_goto_and_label_not_supported);
+ repeat
+ if not(token in [_ID,_INTCONST]) then
+ consume(_ID)
+ else
+ begin
+ if token=_ID then
+ labelsym:=tlabelsym.create(orgpattern)
+ else
+ labelsym:=tlabelsym.create(pattern);
+ symtablestack.top.insert(labelsym);
+ if m_non_local_goto in current_settings.modeswitches then
+ begin
+ if symtablestack.top.symtabletype=localsymtable then
+ begin
+ labelsym.jumpbuf:=tlocalvarsym.create('LABEL$_'+labelsym.name,vs_value,rec_jmp_buf,[]);
+ symtablestack.top.insert(labelsym.jumpbuf);
+ end
+ else
+ begin
+ labelsym.jumpbuf:=tstaticvarsym.create('LABEL$_'+labelsym.name,vs_value,rec_jmp_buf,[]);
+ symtablestack.top.insert(labelsym.jumpbuf);
+ insertbssdata(tstaticvarsym(labelsym.jumpbuf));
+ end;
+ include(labelsym.jumpbuf.symoptions,sp_internal);
+ { the buffer will be setup later, but avoid a hint }
+ tabstractvarsym(labelsym.jumpbuf).varstate:=vs_written;
+ end;
+ consume(token);
+ end;
+ if token<>_SEMICOLON then consume(_COMMA);
+ until not(token in [_ID,_INTCONST]);
+ consume(_SEMICOLON);
+ end;
+
+ procedure types_dec(in_structure: boolean);
+
+ procedure finalize_objc_class_or_protocol_external_status(od: tobjectdef);
+ begin
+ if [oo_is_external,oo_is_forward] <= od.objectoptions then
+ begin
+ { formal definition: x = objcclass external; }
+ exclude(od.objectoptions,oo_is_forward);
+ include(od.objectoptions,oo_is_formal);
+ end;
+ end;
+
+ var
+ typename,orgtypename,
+ gentypename,genorgtypename : TIDString;
+ newtype : ttypesym;
+ sym : tsym;
+ hdef : tdef;
+ defpos,storetokenpos : tfileposinfo;
+ old_block_type : tblock_type;
+ old_checkforwarddefs: TFPObjectList;
+ objecttype : tobjecttyp;
+ isgeneric,
+ isunique,
+ istyperenaming : boolean;
+ generictypelist : TFPObjectList;
+ generictokenbuf : tdynamicarray;
+ vmtbuilder : TVMTBuilder;
+ p:tnode;
+ gendef : tstoreddef;
+ s : shortstring;
+ pd: tprocdef;
+ hashedid : thashedidstring;
+ begin
+ old_block_type:=block_type;
+ { save unit container of forward declarations -
+ we can be inside nested class type block }
+ old_checkforwarddefs:=current_module.checkforwarddefs;
+ current_module.checkforwarddefs:=TFPObjectList.Create(false);
+ block_type:=bt_type;
+ repeat
+ defpos:=current_tokenpos;
+ istyperenaming:=false;
+ generictypelist:=nil;
+ generictokenbuf:=nil;
+
+ { fpc generic declaration? }
+ isgeneric:=not(m_delphi in current_settings.modeswitches) and try_to_consume(_GENERIC);
+
+ typename:=pattern;
+ orgtypename:=orgpattern;
+ consume(_ID);
+
+ { delphi generic declaration? }
+ if (m_delphi in current_settings.modeswitches) then
+ isgeneric:=token=_LSHARPBRACKET;
+
+ { Generic type declaration? }
+ if isgeneric then
+ begin
+ if assigned(current_genericdef) then
+ Message(parser_f_no_generic_inside_generic);
+
+ consume(_LSHARPBRACKET);
+ generictypelist:=parse_generic_parameters;
+ consume(_RSHARPBRACKET);
+
+ str(generictypelist.Count,s);
+ gentypename:=typename+'$'+s;
+ genorgtypename:=orgtypename+'$'+s;
+ end
+ else
+ begin
+ gentypename:=typename;
+ genorgtypename:=orgtypename;
+ end;
+
+
+ consume(_EQ);
+
+ { support 'ttype=type word' syntax }
+ isunique:=try_to_consume(_TYPE);
+
+ { MacPas object model is more like Delphi's than like TP's, but }
+ { uses the object keyword instead of class }
+ if (m_mac in current_settings.modeswitches) and
+ (token = _OBJECT) then
+ token := _CLASS;
+
+ { Start recording a generic template }
+ if assigned(generictypelist) then
+ begin
+ generictokenbuf:=tdynamicarray.create(256);
+ current_scanner.startrecordtokens(generictokenbuf);
+ end;
+
+ { is the type already defined? -- must be in the current symtable,
+ not in a nested symtable or one higher up the stack -> don't
+ use searchsym & frinds! }
+ sym:=tsym(symtablestack.top.find(gentypename));
+ newtype:=nil;
+ { found a symbol with this name? }
+ if assigned(sym) then
+ begin
+ if (sym.typ=typesym) and
+ { this should not be a symbol that was created by a generic
+ that was declared earlier }
+ not (
+ (ttypesym(sym).typedef.typ=undefineddef) and
+ (sp_generic_dummy in sym.symoptions)
+ ) then
+ begin
+ if ((token=_CLASS) or
+ (token=_INTERFACE) or
+ (token=_DISPINTERFACE) or
+ (token=_OBJCCLASS) or
+ (token=_OBJCPROTOCOL) or
+ (token=_OBJCCATEGORY)) and
+ (assigned(ttypesym(sym).typedef)) and
+ is_implicit_pointer_object_type(ttypesym(sym).typedef) and
+ (oo_is_forward in tobjectdef(ttypesym(sym).typedef).objectoptions) then
+ begin
+ case token of
+ _CLASS :
+ objecttype:=odt_class;
+ _INTERFACE :
+ if current_settings.interfacetype=it_interfacecom then
+ objecttype:=odt_interfacecom
+ else
+ objecttype:=odt_interfacecorba;
+ _DISPINTERFACE :
+ objecttype:=odt_dispinterface;
+ _OBJCCLASS,
+ _OBJCCATEGORY :
+ objecttype:=odt_objcclass;
+ _OBJCPROTOCOL :
+ objecttype:=odt_objcprotocol;
+ else
+ internalerror(200811072);
+ end;
+ consume(token);
+ { we can ignore the result, the definition is modified }
+ object_dec(objecttype,genorgtypename,nil,nil,tobjectdef(ttypesym(sym).typedef),ht_none);
+ newtype:=ttypesym(sym);
+ hdef:=newtype.typedef;
+ end
+ else
+ message1(parser_h_type_redef,genorgtypename);
+ end;
+ end;
+ { no old type reused ? Then insert this new type }
+ if not assigned(newtype) then
+ begin
+ { insert the new type first with an errordef, so that
+ referencing the type before it's really set it
+ will give an error (PFV) }
+ hdef:=generrordef;
+ gendef:=nil;
+ storetokenpos:=current_tokenpos;
+ if isgeneric then
+ begin
+ { for generics we need to check whether a non-generic type
+ already exists and if not we need to insert a symbol with
+ the non-generic name (available in (org)typename) that is a
+ undefineddef, so that inline specializations can be used }
+ sym:=tsym(symtablestack.top.Find(typename));
+ if not assigned(sym) then
+ begin
+ sym:=ttypesym.create(orgtypename,tundefineddef.create);
+ Include(sym.symoptions,sp_generic_dummy);
+ ttypesym(sym).typedef.typesym:=sym;
+ sym.visibility:=symtablestack.top.currentvisibility;
+ symtablestack.top.insert(sym);
+ ttypesym(sym).typedef.owner:=sym.owner;
+ end
+ else
+ { this is not allowed in non-Delphi modes }
+ if not (m_delphi in current_settings.modeswitches) then
+ Message1(sym_e_duplicate_id,genorgtypename)
+ else
+ { we need to find this symbol even if it's a variable or
+ something else when doing an inline specialization }
+ Include(sym.symoptions,sp_generic_dummy);
+ end
+ else
+ begin
+ if assigned(sym) and (sym.typ=typesym) and
+ (ttypesym(sym).typedef.typ=undefineddef) and
+ (sp_generic_dummy in sym.symoptions) then
+ begin
+ { this is a symbol that was added by an earlier generic
+ declaration, reuse it }
+ newtype:=ttypesym(sym);
+ newtype.typedef:=hdef;
+ sym:=nil;
+ end;
+
+ { check whether this is a declaration of a type inside a
+ specialization }
+ if assigned(current_structdef) and
+ (df_specialization in current_structdef.defoptions) then
+ begin
+ if not assigned(current_structdef.genericdef) or
+ not (current_structdef.genericdef.typ in [recorddef,objectdef]) then
+ internalerror(2011052301);
+ hashedid.id:=gentypename;
+ { we could be inside a method of the specialization
+ instead of its declaration, so check that first (as
+ local nested types aren't allowed we don't need to
+ walk the symtablestack to find the localsymtable) }
+ if symtablestack.top.symtabletype=localsymtable then
+ begin
+ { we are in a method }
+ if not assigned(symtablestack.top.defowner) or
+ (symtablestack.top.defowner.typ<>procdef) then
+ internalerror(2011120701);
+ pd:=tprocdef(symtablestack.top.defowner);
+ if not assigned(pd.genericdef) or (pd.genericdef.typ<>procdef) then
+ internalerror(2011120702);
+ sym:=tsym(tprocdef(pd.genericdef).localst.findwithhash(hashedid));
+ end
+ else
+ sym:=nil;
+ if not assigned(sym) or not (sym.typ=typesym) then
+ begin
+ { now search in the declaration of the generic }
+ sym:=tsym(tabstractrecorddef(current_structdef.genericdef).symtable.findwithhash(hashedid));
+ if not assigned(sym) or not (sym.typ=typesym) then
+ internalerror(2011052302);
+ end;
+ { use the corresponding type in the generic's symtable as
+ genericdef for the specialized type }
+ gendef:=tstoreddef(ttypesym(sym).typedef);
+ end;
+ end;
+ { insert a new type if we don't reuse an existing symbol }
+ if not assigned(newtype) then
+ begin
+ newtype:=ttypesym.create(genorgtypename,hdef);
+ newtype.visibility:=symtablestack.top.currentvisibility;
+ symtablestack.top.insert(newtype);
+ end;
+ current_tokenpos:=defpos;
+ current_tokenpos:=storetokenpos;
+ { read the type definition }
+ read_named_type(hdef,genorgtypename,gendef,generictypelist,false);
+ { update the definition of the type }
+ if assigned(hdef) then
+ begin
+ if assigned(hdef.typesym) then
+ istyperenaming:=true;
+ if isunique then
+ begin
+ if is_objc_class_or_protocol(hdef) then
+ Message(parser_e_no_objc_unique);
+
+ hdef:=tstoreddef(hdef).getcopy;
+
+ { check if it is an ansistirng(codepage) declaration }
+ if is_ansistring(hdef) and try_to_consume(_LKLAMMER) then
+ begin
+ p:=comp_expr(true,false);
+ consume(_RKLAMMER);
+ if not is_constintnode(p) then
+ begin
+ Message(parser_e_illegal_expression);
+ { error recovery }
+ end
+ else
+ begin
+ if (tordconstnode(p).value<0) or (tordconstnode(p).value>65535) then
+ begin
+ Message(parser_e_invalid_codepage);
+ tordconstnode(p).value:=0;
+ end;
+ tstringdef(hdef).encoding:=int64(tordconstnode(p).value);
+ end;
+ p.free;
+ end;
+
+ { fix name, it is used e.g. for tables }
+ if is_class_or_interface_or_dispinterface(hdef) then
+ with tobjectdef(hdef) do
+ begin
+ stringdispose(objname);
+ stringdispose(objrealname);
+ objrealname:=stringdup(genorgtypename);
+ objname:=stringdup(upper(genorgtypename));
+ end;
+
+ include(hdef.defoptions,df_unique);
+ if (hdef.typ in [pointerdef,classrefdef]) and
+ (tabstractpointerdef(hdef).pointeddef.typ=forwarddef) then
+ current_module.checkforwarddefs.add(hdef);
+ end;
+ if not assigned(hdef.typesym) then
+ hdef.typesym:=newtype;
+ end;
+ { in non-Delphi modes we need a reference to the generic def
+ without the generic suffix, so it can be found easily when
+ parsing method implementations }
+ if isgeneric and assigned(sym) and
+ not (m_delphi in current_settings.modeswitches) and
+ (ttypesym(sym).typedef.typ=undefineddef) then
+ { don't free the undefineddef as the defids rely on the count
+ of the defs in the def list of the module}
+ ttypesym(sym).typedef:=hdef;
+ newtype.typedef:=hdef;
+ { KAZ: handle TGUID declaration in system unit }
+ if (cs_compilesystem in current_settings.moduleswitches) and not assigned(rec_tguid) and
+ (gentypename='TGUID') and { name: TGUID and size=16 bytes that is 128 bits }
+ assigned(hdef) and (hdef.typ=recorddef) and (hdef.size=16) then
+ rec_tguid:=trecorddef(hdef);
+ end;
+ if assigned(hdef) then
+ begin
+ case hdef.typ of
+ pointerdef :
+ begin
+ try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg);
+ consume(_SEMICOLON);
+ if try_to_consume(_FAR) then
+ begin
+ tpointerdef(hdef).is_far:=true;
+ consume(_SEMICOLON);
+ end;
+ end;
+ procvardef :
+ begin
+ { in case of type renaming, don't parse proc directives }
+ if istyperenaming then
+ begin
+ try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg);
+ consume(_SEMICOLON);
+ end
+ else
+ begin
+ if not check_proc_directive(true) then
+ begin
+ try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg);
+ consume(_SEMICOLON);
+ end;
+ parse_var_proc_directives(tsym(newtype));
+ handle_calling_convention(tprocvardef(hdef));
+ if try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg) then
+ consume(_SEMICOLON);
+ end;
+ end;
+ objectdef :
+ begin
+ try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg);
+ consume(_SEMICOLON);
+
+ { change a forward and external objcclass declaration into
+ formal external definition, so the compiler does not
+ expect an real definition later }
+ if is_objc_class_or_protocol(hdef) then
+ finalize_objc_class_or_protocol_external_status(tobjectdef(hdef));
+
+ { Build VMT indexes, skip for type renaming and forward classes }
+ if (hdef.typesym=newtype) and
+ not(oo_is_forward in tobjectdef(hdef).objectoptions) and
+ not(df_generic in hdef.defoptions) then
+ begin
+ vmtbuilder:=TVMTBuilder.Create(tobjectdef(hdef));
+ vmtbuilder.generate_vmt;
+ vmtbuilder.free;
+ end;
+
+ { In case of an objcclass, verify that all methods have a message
+ name set. We only check this now, because message names can be set
+ during the protocol (interface) mapping. At the same time, set the
+ mangled names (these depend on the "external" name of the class),
+ and mark private fields of external classes as "used" (to avoid
+ bogus notes about them being unused)
+ }
+ { watch out for crashes in case of errors }
+ if is_objc_class_or_protocol(hdef) and
+ (not is_objccategory(hdef) or
+ assigned(tobjectdef(hdef).childof)) then
+ tobjectdef(hdef).finish_objc_data;
+
+ if is_cppclass(hdef) then
+ tobjectdef(hdef).finish_cpp_data;
+ end;
+ recorddef :
+ begin
+ try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg);
+ consume(_SEMICOLON);
+ end;
+ else
+ begin
+ try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg);
+ consume(_SEMICOLON);
+ end;
+ end;
+ end;
+
+ if isgeneric and (not(hdef.typ in [objectdef,recorddef,arraydef,procvardef])
+ or is_objectpascal_helper(hdef)) then
+ message(parser_e_cant_create_generics_of_this_type);
+
+ { Stop recording a generic template }
+ if assigned(generictypelist) then
+ begin
+ current_scanner.stoprecordtokens;
+ tstoreddef(hdef).generictokenbuf:=generictokenbuf;
+ { Generic is never a type renaming }
+ hdef.typesym:=newtype;
+ generictypelist.free;
+ end;
+ until (token<>_ID)or(in_structure and (idtoken in [_PRIVATE,_PROTECTED,_PUBLIC,_PUBLISHED,_STRICT]));
+ { resolve type block forward declarations and restore a unit
+ container for them }
+ resolve_forward_types;
+ current_module.checkforwarddefs.free;
+ current_module.checkforwarddefs:=old_checkforwarddefs;
+ block_type:=old_block_type;
+ end;
+
+
+ { reads a type declaration to the symbol table }
+ procedure type_dec;
+ begin
+ consume(_TYPE);
+ types_dec(false);
+ end;
+
+
+ procedure var_dec;
+ { parses variable declarations and inserts them in }
+ { the top symbol table of symtablestack }
+ begin
+ consume(_VAR);
+ read_var_decls([]);
+ end;
+
+
+ procedure property_dec(is_classpropery: boolean);
+ var
+ old_block_type : tblock_type;
+ begin
+ consume(_PROPERTY);
+ if not(symtablestack.top.symtabletype in [staticsymtable,globalsymtable]) then
+ message(parser_e_resourcestring_only_sg);
+ old_block_type:=block_type;
+ block_type:=bt_const;
+ repeat
+ read_property_dec(is_classpropery, nil);
+ consume(_SEMICOLON);
+ until token<>_ID;
+ block_type:=old_block_type;
+ end;
+
+
+ procedure threadvar_dec;
+ { parses thread variable declarations and inserts them in }
+ { the top symbol table of symtablestack }
+ begin
+ consume(_THREADVAR);
+ if not(symtablestack.top.symtabletype in [staticsymtable,globalsymtable]) then
+ message(parser_e_threadvars_only_sg);
+ read_var_decls([vd_threadvar]);
+ end;
+
+
+ procedure resourcestring_dec;
+ var
+ orgname : TIDString;
+ p : tnode;
+ dummysymoptions : tsymoptions;
+ deprecatedmsg : pshortstring;
+ storetokenpos,filepos : tfileposinfo;
+ old_block_type : tblock_type;
+ sp : pchar;
+ sym : tsym;
+ begin
+ consume(_RESOURCESTRING);
+ if not(symtablestack.top.symtabletype in [staticsymtable,globalsymtable]) then
+ message(parser_e_resourcestring_only_sg);
+ old_block_type:=block_type;
+ block_type:=bt_const;
+ repeat
+ orgname:=orgpattern;
+ filepos:=current_tokenpos;
+ consume(_ID);
+ case token of
+ _EQ:
+ begin
+ consume(_EQ);
+ p:=comp_expr(true,false);
+ storetokenpos:=current_tokenpos;
+ current_tokenpos:=filepos;
+ sym:=nil;
+ case p.nodetype of
+ ordconstn:
+ begin
+ if is_constcharnode(p) then
+ begin
+ getmem(sp,2);
+ sp[0]:=chr(tordconstnode(p).value.svalue);
+ sp[1]:=#0;
+ sym:=tconstsym.create_string(orgname,constresourcestring,sp,1);
+ end
+ else
+ Message(parser_e_illegal_expression);
+ end;
+ stringconstn:
+ with Tstringconstnode(p) do
+ begin
+ getmem(sp,len+1);
+ move(value_str^,sp^,len+1);
+ sym:=tconstsym.create_string(orgname,constresourcestring,sp,len);
+ end;
+ else
+ Message(parser_e_illegal_expression);
+ end;
+ current_tokenpos:=storetokenpos;
+ { Support hint directives }
+ dummysymoptions:=[];
+ deprecatedmsg:=nil;
+ try_consume_hintdirective(dummysymoptions,deprecatedmsg);
+ if assigned(sym) then
+ begin
+ sym.symoptions:=sym.symoptions+dummysymoptions;
+ sym.deprecatedmsg:=deprecatedmsg;
+ symtablestack.top.insert(sym);
+ end
+ else
+ stringdispose(deprecatedmsg);
+ consume(_SEMICOLON);
+ p.free;
+ end;
+ else consume(_EQ);
+ end;
+ until token<>_ID;
+ block_type:=old_block_type;
+ end;
+
+end.
diff --git a/closures/compiler/pdecobj.pas b/closures/compiler/pdecobj.pas
new file mode 100644
index 0000000000..1c29df2437
--- /dev/null
+++ b/closures/compiler/pdecobj.pas
@@ -0,0 +1,1281 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Does object types for Free Pascal
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit pdecobj;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cclasses,
+ globtype,symconst,symtype,symdef;
+
+ { parses a object declaration }
+ function object_dec(objecttype:tobjecttyp;const n:tidstring;genericdef:tstoreddef;genericlist:TFPObjectList;fd : tobjectdef;helpertype:thelpertype) : tobjectdef;
+
+ function class_constructor_head:tprocdef;
+ function class_destructor_head:tprocdef;
+ function constructor_head:tprocdef;
+ function destructor_head:tprocdef;
+ procedure struct_property_dec(is_classproperty:boolean);
+
+implementation
+
+ uses
+ sysutils,cutils,
+ globals,verbose,systems,tokens,
+ symbase,symsym,symtable,
+ node,nld,nmem,ncon,ncnv,ncal,
+ fmodule,scanner,
+ pbase,pexpr,pdecsub,pdecvar,ptype,pdecl,pgenutil,ppu
+ ;
+
+ const
+ { Please leave this here, this module should NOT use
+ these variables.
+ Declaring it as string here results in an error when compiling (PFV) }
+ current_procinfo = 'error';
+
+ var
+ current_objectdef : tobjectdef absolute current_structdef;
+
+ function class_constructor_head:tprocdef;
+ var
+ pd : tprocdef;
+ begin
+ result:=nil;
+ consume(_CONSTRUCTOR);
+ { must be at same level as in implementation }
+ parse_proc_head(current_structdef,potype_class_constructor,pd);
+ if not assigned(pd) then
+ begin
+ consume(_SEMICOLON);
+ exit;
+ end;
+ pd.calcparas;
+ if (pd.maxparacount>0) then
+ Message(parser_e_no_paras_for_class_constructor);
+ consume(_SEMICOLON);
+ include(current_structdef.objectoptions,oo_has_class_constructor);
+ current_module.flags:=current_module.flags or uf_classinits;
+ { no return value }
+ pd.returndef:=voidtype;
+ result:=pd;
+ end;
+
+ function constructor_head:tprocdef;
+ var
+ pd : tprocdef;
+ begin
+ result:=nil;
+ consume(_CONSTRUCTOR);
+ { must be at same level as in implementation }
+ parse_proc_head(current_structdef,potype_constructor,pd);
+ if not assigned(pd) then
+ begin
+ consume(_SEMICOLON);
+ exit;
+ end;
+ if (cs_constructor_name in current_settings.globalswitches) and
+ (pd.procsym.name<>'INIT') then
+ Message(parser_e_constructorname_must_be_init);
+ consume(_SEMICOLON);
+ include(current_structdef.objectoptions,oo_has_constructor);
+ { Set return type, class and record constructors return the
+ created instance, object constructors return boolean }
+ if is_class(pd.struct) or is_record(pd.struct) then
+ pd.returndef:=pd.struct
+ else
+{$ifdef CPU64bitaddr}
+ pd.returndef:=bool64type;
+{$else CPU64bitaddr}
+ pd.returndef:=bool32type;
+{$endif CPU64bitaddr}
+ result:=pd;
+ end;
+
+
+ procedure struct_property_dec(is_classproperty:boolean);
+ var
+ p : tpropertysym;
+ begin
+ { check for a class, record or helper }
+ if not((is_class_or_interface_or_dispinterface(current_structdef) or is_record(current_structdef) or is_objectpascal_helper(current_structdef)) or
+ (not(m_tp7 in current_settings.modeswitches) and (is_object(current_structdef)))) then
+ Message(parser_e_syntax_error);
+ consume(_PROPERTY);
+ p:=read_property_dec(is_classproperty,current_structdef);
+ consume(_SEMICOLON);
+ if try_to_consume(_DEFAULT) then
+ begin
+ if oo_has_default_property in current_structdef.objectoptions then
+ message(parser_e_only_one_default_property);
+ include(current_structdef.objectoptions,oo_has_default_property);
+ include(p.propoptions,ppo_defaultproperty);
+ if not(ppo_hasparameters in p.propoptions) then
+ message(parser_e_property_need_paras);
+ if (token=_COLON) then
+ begin
+ Message(parser_e_field_not_allowed_here);
+ consume_all_until(_SEMICOLON);
+ end;
+ consume(_SEMICOLON);
+ end;
+ { parse possible enumerator modifier }
+ if try_to_consume(_ENUMERATOR) then
+ begin
+ if (token = _ID) then
+ begin
+ if pattern='CURRENT' then
+ begin
+ if oo_has_enumerator_current in current_structdef.objectoptions then
+ message(parser_e_only_one_enumerator_current);
+ if not p.propaccesslist[palt_read].empty then
+ begin
+ include(current_structdef.objectoptions,oo_has_enumerator_current);
+ include(p.propoptions,ppo_enumerator_current);
+ end
+ else
+ Message(parser_e_enumerator_current_is_not_valid) // property has no reader
+ end
+ else
+ Message1(parser_e_invalid_enumerator_identifier, pattern);
+ consume(token);
+ end
+ else
+ Message(parser_e_enumerator_identifier_required);
+ consume(_SEMICOLON);
+ end;
+ { hint directives, these can be separated by semicolons here,
+ that needs to be handled here with a loop (PFV) }
+ while try_consume_hintdirective(p.symoptions,p.deprecatedmsg) do
+ Consume(_SEMICOLON);
+ end;
+
+
+ function class_destructor_head:tprocdef;
+ var
+ pd : tprocdef;
+ begin
+ result:=nil;
+ consume(_DESTRUCTOR);
+ parse_proc_head(current_structdef,potype_class_destructor,pd);
+ if not assigned(pd) then
+ begin
+ consume(_SEMICOLON);
+ exit;
+ end;
+ pd.calcparas;
+ if (pd.maxparacount>0) then
+ Message(parser_e_no_paras_for_class_destructor);
+ consume(_SEMICOLON);
+ include(current_structdef.objectoptions,oo_has_class_destructor);
+ current_module.flags:=current_module.flags or uf_classinits;
+ { no return value }
+ pd.returndef:=voidtype;
+ result:=pd;
+ end;
+
+ function destructor_head:tprocdef;
+ var
+ pd : tprocdef;
+ begin
+ result:=nil;
+ consume(_DESTRUCTOR);
+ parse_proc_head(current_structdef,potype_destructor,pd);
+ if not assigned(pd) then
+ begin
+ consume(_SEMICOLON);
+ exit;
+ end;
+ if (cs_constructor_name in current_settings.globalswitches) and
+ (pd.procsym.name<>'DONE') then
+ Message(parser_e_destructorname_must_be_done);
+ pd.calcparas;
+ if not(pd.maxparacount=0) and
+ (m_fpc in current_settings.modeswitches) then
+ Message(parser_e_no_paras_for_destructor);
+ consume(_SEMICOLON);
+ include(current_structdef.objectoptions,oo_has_destructor);
+ { no return value }
+ pd.returndef:=voidtype;
+ result:=pd;
+ end;
+
+
+ procedure setinterfacemethodoptions;
+ var
+ i : longint;
+ def : tdef;
+ begin
+ include(current_structdef.objectoptions,oo_has_virtual);
+ for i:=0 to current_structdef.symtable.DefList.count-1 do
+ begin
+ def:=tdef(current_structdef.symtable.DefList[i]);
+ if assigned(def) and
+ (def.typ=procdef) then
+ begin
+ include(tprocdef(def).procoptions,po_virtualmethod);
+ tprocdef(def).forwarddef:=false;
+ end;
+ end;
+ end;
+
+
+ procedure setobjcclassmethodoptions;
+ var
+ i : longint;
+ def : tdef;
+ begin
+ for i:=0 to current_structdef.symtable.DefList.count-1 do
+ begin
+ def:=tdef(current_structdef.symtable.DefList[i]);
+ if assigned(def) and
+ (def.typ=procdef) then
+ begin
+ include(tprocdef(def).procoptions,po_virtualmethod);
+ end;
+ end;
+ end;
+
+
+ procedure handleImplementedInterface(intfdef : tobjectdef);
+ begin
+ if not is_interface(intfdef) then
+ begin
+ Message1(type_e_interface_type_expected,intfdef.typename);
+ exit;
+ end;
+ if current_objectdef.find_implemented_interface(intfdef)<>nil then
+ Message1(sym_e_duplicate_id,intfdef.objname^)
+ else
+ begin
+ { allocate and prepare the GUID only if the class
+ implements some interfaces. }
+ if current_objectdef.ImplementedInterfaces.count = 0 then
+ current_objectdef.prepareguid;
+ current_objectdef.ImplementedInterfaces.Add(TImplementedInterface.Create(intfdef));
+ end;
+ end;
+
+
+ procedure handleImplementedProtocol(intfdef : tobjectdef);
+ begin
+ intfdef:=find_real_objcclass_definition(intfdef,false);
+ if not is_objcprotocol(intfdef) then
+ begin
+ Message1(type_e_protocol_type_expected,intfdef.typename);
+ exit;
+ end;
+ if ([oo_is_forward,oo_is_formal] * intfdef.objectoptions <> []) then
+ begin
+ Message1(parser_e_forward_protocol_declaration_must_be_resolved,intfdef.objrealname^);
+ exit;
+ end;
+ if current_objectdef.find_implemented_interface(intfdef)<>nil then
+ Message1(sym_e_duplicate_id,intfdef.objname^)
+ else
+ begin
+ current_objectdef.ImplementedInterfaces.Add(TImplementedInterface.Create(intfdef));
+ end;
+ end;
+
+
+ procedure readImplementedInterfacesAndProtocols(intf: boolean);
+ var
+ hdef : tdef;
+ begin
+ while try_to_consume(_COMMA) do
+ begin
+ { use single_type instead of id_type for specialize support }
+ single_type(hdef,[stoAllowSpecialization,stoParseClassParent]);
+ if (hdef.typ<>objectdef) then
+ begin
+ if intf then
+ Message1(type_e_interface_type_expected,hdef.typename)
+ else
+ Message1(type_e_protocol_type_expected,hdef.typename);
+ continue;
+ end;
+ if intf then
+ handleImplementedInterface(tobjectdef(hdef))
+ else
+ handleImplementedProtocol(tobjectdef(hdef));
+ end;
+ end;
+
+
+ procedure readinterfaceiid;
+ var
+ p : tnode;
+ valid : boolean;
+ begin
+ p:=comp_expr(true,false);
+ if p.nodetype=stringconstn then
+ begin
+ stringdispose(current_objectdef.iidstr);
+ current_objectdef.iidstr:=stringdup(strpas(tstringconstnode(p).value_str));
+ valid:=string2guid(current_objectdef.iidstr^,current_objectdef.iidguid^);
+ if (current_objectdef.objecttype in [odt_interfacecom,odt_dispinterface]) and
+ not valid then
+ Message(parser_e_improper_guid_syntax);
+ include(current_structdef.objectoptions,oo_has_valid_guid);
+ end
+ else
+ Message(parser_e_illegal_expression);
+ p.free;
+ end;
+
+ procedure get_cpp_class_external_status(od: tobjectdef);
+ var
+ hs: string;
+ begin
+ { C++ classes can be external -> all methods inside are external
+ (defined at the class level instead of per method, so that you cannot
+ define some methods as external and some not)
+ }
+ if try_to_consume(_EXTERNAL) then
+ begin
+ if token in [_CSTRING,_CWSTRING,_CCHAR,_CWCHAR] then
+ begin
+ { Always add library prefix and suffix to create an uniform name }
+ hs:=get_stringconst;
+ if ExtractFileExt(hs)='' then
+ hs:=ChangeFileExt(hs,target_info.sharedlibext);
+ if Copy(hs,1,length(target_info.sharedlibprefix))<>target_info.sharedlibprefix then
+ hs:=target_info.sharedlibprefix+hs;
+ od.import_lib:=stringdup(hs);
+ end;
+ include(od.objectoptions, oo_is_external);
+ { check if we shall use another name for the class }
+ if try_to_consume(_NAME) then
+ od.objextname:=stringdup(get_stringconst)
+ else
+ od.objextname:=stringdup(od.objrealname^);
+ include(od.objectoptions,oo_is_external);
+ end
+ else
+ od.objextname:=stringdup(od.objrealname^);
+ { ToDo: read the namespace of the class (influences the mangled name)}
+ end;
+
+ procedure get_objc_class_or_protocol_external_status(od: tobjectdef);
+ begin
+ { Objective-C classes can be external -> all messages inside are
+ external (defined at the class level instead of per method, so
+ that you cannot define some methods as external and some not)
+ }
+ if try_to_consume(_EXTERNAL) then
+ begin
+ if try_to_consume(_NAME) then
+ od.objextname:=stringdup(get_stringconst)
+ else
+ { the external name doesn't matter for formally declared
+ classes, and allowing to specify one would mean that we would
+ have to check it for consistency with the actual definition
+ later on }
+ od.objextname:=stringdup(od.objrealname^);
+ include(od.objectoptions,oo_is_external);
+ end
+ else
+ od.objextname:=stringdup(od.objrealname^);
+ end;
+
+
+ procedure parse_object_options;
+ begin
+ case current_objectdef.objecttype of
+ odt_object,odt_class:
+ begin
+ while true do
+ begin
+ if try_to_consume(_ABSTRACT) then
+ include(current_structdef.objectoptions,oo_is_abstract)
+ else
+ if try_to_consume(_SEALED) then
+ include(current_structdef.objectoptions,oo_is_sealed)
+ else
+ break;
+ end;
+ if [oo_is_abstract, oo_is_sealed] * current_structdef.objectoptions = [oo_is_abstract, oo_is_sealed] then
+ Message(parser_e_abstract_and_sealed_conflict);
+ end;
+ odt_cppclass:
+ get_cpp_class_external_status(current_objectdef);
+ odt_objcclass,odt_objcprotocol,odt_objccategory:
+ get_objc_class_or_protocol_external_status(current_objectdef);
+ odt_helper: ; // nothing
+ end;
+ end;
+
+ procedure parse_parent_classes;
+ var
+ intfchildof,
+ childof : tobjectdef;
+ hdef : tdef;
+ hasparentdefined : boolean;
+ begin
+ childof:=nil;
+ intfchildof:=nil;
+ hasparentdefined:=false;
+
+ { reads the parent class }
+ if (token=_LKLAMMER) or
+ is_objccategory(current_structdef) then
+ begin
+ consume(_LKLAMMER);
+ { use single_type instead of id_type for specialize support }
+ single_type(hdef,[stoAllowSpecialization, stoParseClassParent]);
+ if (not assigned(hdef)) or
+ (hdef.typ<>objectdef) then
+ begin
+ if assigned(hdef) then
+ Message1(type_e_class_type_expected,hdef.typename)
+ else if is_objccategory(current_structdef) then
+ { a category must specify the class to extend }
+ Message(type_e_objcclass_type_expected);
+ end
+ else
+ begin
+ childof:=tobjectdef(hdef);
+ { a mix of class, interfaces, objects and cppclasses
+ isn't allowed }
+ case current_objectdef.objecttype of
+ odt_class:
+ if not(is_class(childof)) then
+ begin
+ if is_interface(childof) then
+ begin
+ { we insert the interface after the child
+ is set, see below
+ }
+ intfchildof:=childof;
+ childof:=class_tobject;
+ end
+ else
+ Message(parser_e_mix_of_classes_and_objects);
+ end
+ else
+ if oo_is_sealed in childof.objectoptions then
+ Message1(parser_e_sealed_descendant,childof.typename);
+ odt_interfacecorba,
+ odt_interfacecom:
+ begin
+ if not(is_interface(childof)) then
+ Message(parser_e_mix_of_classes_and_objects);
+ current_objectdef.objecttype:=childof.objecttype;
+ end;
+ odt_cppclass:
+ if not(is_cppclass(childof)) then
+ Message(parser_e_mix_of_classes_and_objects);
+ odt_objcclass:
+ if not(is_objcclass(childof) or
+ is_objccategory(childof)) then
+ begin
+ if is_objcprotocol(childof) then
+ begin
+ if not(oo_is_classhelper in current_structdef.objectoptions) then
+ begin
+ intfchildof:=childof;
+ childof:=nil;
+ CGMessage(parser_h_no_objc_parent);
+ end
+ else
+ { a category must specify the class to extend }
+ CGMessage(type_e_objcclass_type_expected);
+ end
+ else
+ Message(parser_e_mix_of_classes_and_objects);
+ end
+ else
+ childof:=find_real_objcclass_definition(childof,true);
+ odt_objcprotocol:
+ begin
+ if not(is_objcprotocol(childof)) then
+ Message(parser_e_mix_of_classes_and_objects);
+ intfchildof:=childof;
+ childof:=nil;
+ end;
+ odt_object:
+ if not(is_object(childof)) then
+ Message(parser_e_mix_of_classes_and_objects)
+ else
+ if oo_is_sealed in childof.objectoptions then
+ Message1(parser_e_sealed_descendant,childof.typename);
+ odt_dispinterface:
+ Message(parser_e_dispinterface_cant_have_parent);
+ odt_helper:
+ if not is_objectpascal_helper(childof) then
+ begin
+ Message(type_e_helper_type_expected);
+ childof:=nil;
+ end;
+ end;
+ end;
+ hasparentdefined:=true;
+ end;
+
+ { if no parent class, then a class get tobject as parent }
+ if not assigned(childof) then
+ begin
+ case current_objectdef.objecttype of
+ odt_class:
+ if current_objectdef<>class_tobject then
+ childof:=class_tobject;
+ odt_interfacecom:
+ if current_objectdef<>interface_iunknown then
+ childof:=interface_iunknown;
+ odt_dispinterface:
+ childof:=interface_idispatch;
+ odt_objcclass:
+ CGMessage(parser_h_no_objc_parent);
+ end;
+ end;
+
+ if assigned(childof) then
+ begin
+ { Forbid not completly defined objects to be used as parents. This will
+ also prevent circular loops of classes, because we set the forward flag
+ at the start of the new definition and will reset it below after the
+ parent has been set }
+ if (oo_is_forward in childof.objectoptions) then
+ Message1(parser_e_forward_declaration_must_be_resolved,childof.objrealname^)
+ else if not(oo_is_formal in childof.objectoptions) then
+ current_objectdef.set_parent(childof)
+ else
+ Message1(sym_e_objc_formal_class_not_resolved,childof.objrealname^);
+ end;
+
+ { remove forward flag, is resolved }
+ exclude(current_structdef.objectoptions,oo_is_forward);
+
+ if hasparentdefined then
+ begin
+ if current_objectdef.objecttype in [odt_class,odt_objcclass,odt_objcprotocol] then
+ begin
+ if assigned(intfchildof) then
+ if current_objectdef.objecttype=odt_class then
+ handleImplementedInterface(intfchildof)
+ else
+ handleImplementedProtocol(intfchildof);
+ readImplementedInterfacesAndProtocols(current_objectdef.objecttype=odt_class);
+ end;
+ consume(_RKLAMMER);
+ end;
+ end;
+
+ procedure parse_extended_type(helpertype:thelpertype);
+ var
+ hdef: tdef;
+ begin
+ if not is_objectpascal_helper(current_structdef) then
+ Internalerror(2011021103);
+ if helpertype=ht_none then
+ Internalerror(2011021001);
+
+ consume(_FOR);
+ single_type(hdef,[stoParseClassParent]);
+ if (not assigned(hdef)) or
+ not (hdef.typ in [objectdef,recorddef]) then
+ begin
+ if helpertype=ht_class then
+ Message1(type_e_class_type_expected,hdef.typename)
+ else
+ if helpertype=ht_record then
+ Message1(type_e_record_type_expected,hdef.typename);
+ end
+ else
+ begin
+ case helpertype of
+ ht_class:
+ begin
+ if not is_class(hdef) then
+ Message1(type_e_class_type_expected,hdef.typename);
+ { a class helper must extend the same class or a subclass
+ of the class extended by the parent class helper }
+ if assigned(current_objectdef.childof) then
+ begin
+ if not is_class(current_objectdef.childof.extendeddef) then
+ Internalerror(2011021101);
+ if not hdef.is_related(current_objectdef.childof.extendeddef) then
+ Message1(type_e_class_helper_must_extend_subclass,current_objectdef.childof.extendeddef.typename);
+ end;
+ end;
+ ht_record:
+ begin
+ if not is_record(hdef) then
+ Message1(type_e_record_type_expected,hdef.typename);
+ { a record helper must extend the same record as the
+ parent helper }
+ if assigned(current_objectdef.childof) then
+ begin
+ if not is_record(current_objectdef.childof.extendeddef) then
+ Internalerror(2011021102);
+ if hdef<>current_objectdef.childof.extendeddef then
+ Message1(type_e_record_helper_must_extend_same_record,current_objectdef.childof.extendeddef.typename);
+ end;
+ end;
+ else
+ hdef:=nil;
+ end;
+ end;
+
+ if assigned(hdef) then
+ current_objectdef.extendeddef:=hdef
+ else
+ current_objectdef.extendeddef:=generrordef;
+ end;
+
+ procedure parse_guid;
+ begin
+ { read GUID }
+ if (current_objectdef.objecttype in [odt_interfacecom,odt_interfacecorba,odt_dispinterface]) and
+ try_to_consume(_LECKKLAMMER) then
+ begin
+ readinterfaceiid;
+ consume(_RECKKLAMMER);
+ end
+ else if (current_objectdef.objecttype=odt_dispinterface) then
+ message(parser_e_dispinterface_needs_a_guid);
+ end;
+
+ procedure parse_object_members;
+
+ procedure chkobjc(pd: tprocdef);
+ begin
+ if is_objc_class_or_protocol(pd.struct) then
+ begin
+ include(pd.procoptions,po_objc);
+ end;
+ end;
+
+
+ procedure chkcpp(pd:tprocdef);
+ begin
+ { nothing currently }
+ end;
+
+ procedure maybe_parse_hint_directives(pd:tprocdef);
+ var
+ dummysymoptions : tsymoptions;
+ deprecatedmsg : pshortstring;
+ begin
+ dummysymoptions:=[];
+ deprecatedmsg:=nil;
+ while try_consume_hintdirective(dummysymoptions,deprecatedmsg) do
+ Consume(_SEMICOLON);
+ if assigned(pd) then
+ begin
+ pd.symoptions:=pd.symoptions+dummysymoptions;
+ pd.deprecatedmsg:=deprecatedmsg;
+ end
+ else
+ stringdispose(deprecatedmsg);
+ end;
+
+ var
+ pd : tprocdef;
+ has_destructor,
+ oldparse_only: boolean;
+ object_member_blocktype : tblock_type;
+ fields_allowed, is_classdef, classfields: boolean;
+ vdoptions: tvar_dec_options;
+ begin
+ { empty class declaration ? }
+ if (current_objectdef.objecttype in [odt_class,odt_objcclass]) and
+ (token=_SEMICOLON) then
+ exit;
+
+ { in "publishable" classes the default access type is published }
+ if (oo_can_have_published in current_structdef.objectoptions) then
+ current_structdef.symtable.currentvisibility:=vis_published
+ else
+ current_structdef.symtable.currentvisibility:=vis_public;
+ has_destructor:=false;
+ fields_allowed:=true;
+ is_classdef:=false;
+ classfields:=false;
+ object_member_blocktype:=bt_general;
+ repeat
+ case token of
+ _TYPE :
+ begin
+ if not(current_objectdef.objecttype in [odt_class,odt_object,odt_helper]) then
+ Message(parser_e_type_var_const_only_in_records_and_classes);
+ consume(_TYPE);
+ object_member_blocktype:=bt_type;
+ end;
+ _VAR :
+ begin
+ if not(current_objectdef.objecttype in [odt_class,odt_object,odt_helper]) then
+ Message(parser_e_type_var_const_only_in_records_and_classes);
+ consume(_VAR);
+ fields_allowed:=true;
+ object_member_blocktype:=bt_general;
+ classfields:=is_classdef;
+ is_classdef:=false;
+ end;
+ _CONST:
+ begin
+ if not(current_objectdef.objecttype in [odt_class,odt_object,odt_helper]) then
+ Message(parser_e_type_var_const_only_in_records_and_classes);
+ consume(_CONST);
+ object_member_blocktype:=bt_const;
+ end;
+ _ID :
+ begin
+ if is_objcprotocol(current_structdef) and
+ ((idtoken=_REQUIRED) or
+ (idtoken=_OPTIONAL)) then
+ begin
+ current_structdef.symtable.currentlyoptional:=(idtoken=_OPTIONAL);
+ consume(idtoken)
+ end
+ else case idtoken of
+ _PRIVATE :
+ begin
+ if is_interface(current_structdef) or
+ is_objc_protocol_or_category(current_structdef) then
+ Message(parser_e_no_access_specifier_in_interfaces);
+ consume(_PRIVATE);
+ current_structdef.symtable.currentvisibility:=vis_private;
+ include(current_structdef.objectoptions,oo_has_private);
+ fields_allowed:=true;
+ is_classdef:=false;
+ classfields:=false;
+ object_member_blocktype:=bt_general;
+ end;
+ _PROTECTED :
+ begin
+ if is_interface(current_structdef) or
+ is_objc_protocol_or_category(current_structdef) then
+ Message(parser_e_no_access_specifier_in_interfaces);
+ consume(_PROTECTED);
+ current_structdef.symtable.currentvisibility:=vis_protected;
+ include(current_structdef.objectoptions,oo_has_protected);
+ fields_allowed:=true;
+ is_classdef:=false;
+ classfields:=false;
+ object_member_blocktype:=bt_general;
+ end;
+ _PUBLIC :
+ begin
+ if is_interface(current_structdef) or
+ is_objc_protocol_or_category(current_structdef) then
+ Message(parser_e_no_access_specifier_in_interfaces);
+ consume(_PUBLIC);
+ current_structdef.symtable.currentvisibility:=vis_public;
+ fields_allowed:=true;
+ is_classdef:=false;
+ classfields:=false;
+ object_member_blocktype:=bt_general;
+ end;
+ _PUBLISHED :
+ begin
+ { we've to check for a pushlished section in non- }
+ { publishable classes later, if a real declaration }
+ { this is the way, delphi does it }
+ if is_interface(current_structdef) then
+ Message(parser_e_no_access_specifier_in_interfaces);
+ { Objective-C classes do not support "published",
+ as basically everything is published. }
+ if is_objc_class_or_protocol(current_structdef) then
+ Message(parser_e_no_objc_published);
+ consume(_PUBLISHED);
+ current_structdef.symtable.currentvisibility:=vis_published;
+ fields_allowed:=true;
+ is_classdef:=false;
+ classfields:=false;
+ object_member_blocktype:=bt_general;
+ end;
+ _STRICT :
+ begin
+ if is_interface(current_structdef) or
+ is_objc_protocol_or_category(current_structdef) then
+ Message(parser_e_no_access_specifier_in_interfaces);
+ consume(_STRICT);
+ if token=_ID then
+ begin
+ case idtoken of
+ _PRIVATE:
+ begin
+ consume(_PRIVATE);
+ current_structdef.symtable.currentvisibility:=vis_strictprivate;
+ include(current_structdef.objectoptions,oo_has_strictprivate);
+ end;
+ _PROTECTED:
+ begin
+ consume(_PROTECTED);
+ current_structdef.symtable.currentvisibility:=vis_strictprotected;
+ include(current_structdef.objectoptions,oo_has_strictprotected);
+ end;
+ else
+ message(parser_e_protected_or_private_expected);
+ end;
+ end
+ else
+ message(parser_e_protected_or_private_expected);
+ fields_allowed:=true;
+ is_classdef:=false;
+ classfields:=false;
+ object_member_blocktype:=bt_general;
+ end
+ else
+ begin
+ if object_member_blocktype=bt_general then
+ begin
+ if is_interface(current_structdef) or
+ is_objc_protocol_or_category(current_structdef) or
+ is_objectpascal_helper(current_structdef) then
+ Message(parser_e_no_vars_in_interfaces);
+
+ if (current_structdef.symtable.currentvisibility=vis_published) and
+ not(oo_can_have_published in current_structdef.objectoptions) then
+ Message(parser_e_cant_have_published);
+ if (not fields_allowed) then
+ Message(parser_e_field_not_allowed_here);
+
+ vdoptions:=[vd_object];
+ if classfields then
+ include(vdoptions,vd_class);
+ read_record_fields(vdoptions);
+ end
+ else if object_member_blocktype=bt_type then
+ types_dec(true)
+ else if object_member_blocktype=bt_const then
+ consts_dec(true)
+ else
+ internalerror(201001110);
+ end;
+ end;
+ end;
+ _PROPERTY :
+ begin
+ struct_property_dec(is_classdef);
+ fields_allowed:=false;
+ is_classdef:=false;
+ end;
+ _CLASS:
+ begin
+ is_classdef:=false;
+ { read class method/field/property }
+ consume(_CLASS);
+ { class modifier is only allowed for procedures, functions, }
+ { constructors, destructors, fields and properties }
+ if not(token in [_FUNCTION,_PROCEDURE,_PROPERTY,_VAR,_CONSTRUCTOR,_DESTRUCTOR]) then
+ Message(parser_e_procedure_or_function_expected);
+
+ if is_interface(current_structdef) then
+ Message(parser_e_no_static_method_in_interfaces)
+ else
+ { class methods are also allowed for Objective-C protocols }
+ is_classdef:=true;
+ end;
+ _PROCEDURE,
+ _FUNCTION:
+ begin
+ if (current_structdef.symtable.currentvisibility=vis_published) and
+ not(oo_can_have_published in current_structdef.objectoptions) then
+ Message(parser_e_cant_have_published);
+
+ oldparse_only:=parse_only;
+ parse_only:=true;
+ pd:=parse_proc_dec(is_classdef,current_structdef);
+
+ { this is for error recovery as well as forward }
+ { interface mappings, i.e. mapping to a method }
+ { which isn't declared yet }
+ if assigned(pd) then
+ begin
+ parse_object_proc_directives(pd);
+
+ { check if dispid is set }
+ if is_dispinterface(pd.struct) and not (po_dispid in pd.procoptions) then
+ begin
+ pd.dispid:=tobjectdef(pd.struct).get_next_dispid;
+ include(pd.procoptions, po_dispid);
+ end;
+
+ { all Macintosh Object Pascal methods are virtual. }
+ { this can't be a class method, because macpas mode }
+ { has no m_class }
+ if (m_mac in current_settings.modeswitches) then
+ include(pd.procoptions,po_virtualmethod);
+
+ { for record helpers only static class methods are allowed }
+ if is_objectpascal_helper(current_structdef) and
+ is_record(current_objectdef.extendeddef) and
+ is_classdef and not (po_staticmethod in pd.procoptions) then
+ MessagePos(pd.fileinfo, parser_e_class_methods_only_static_in_records);
+
+ handle_calling_convention(pd);
+
+ { add definition to procsym }
+ proc_add_definition(pd);
+
+ { add procdef options to objectdef options }
+ if (po_msgint in pd.procoptions) then
+ include(current_structdef.objectoptions,oo_has_msgint);
+ if (po_msgstr in pd.procoptions) then
+ include(current_structdef.objectoptions,oo_has_msgstr);
+ if (po_virtualmethod in pd.procoptions) then
+ include(current_structdef.objectoptions,oo_has_virtual);
+
+ chkcpp(pd);
+ chkobjc(pd);
+ end;
+
+ maybe_parse_hint_directives(pd);
+
+ parse_only:=oldparse_only;
+ fields_allowed:=false;
+ is_classdef:=false;
+ end;
+ _CONSTRUCTOR :
+ begin
+ if (current_structdef.symtable.currentvisibility=vis_published) and
+ not(oo_can_have_published in current_structdef.objectoptions) then
+ Message(parser_e_cant_have_published);
+
+ if not is_classdef and not(current_structdef.symtable.currentvisibility in [vis_public,vis_published]) then
+ Message(parser_w_constructor_should_be_public);
+
+ if is_interface(current_structdef) then
+ Message(parser_e_no_con_des_in_interfaces);
+
+ { Objective-C does not know the concept of a constructor }
+ if is_objc_class_or_protocol(current_structdef) then
+ Message(parser_e_objc_no_constructor_destructor);
+
+ if is_objectpascal_helper(current_structdef) then
+ if is_classdef then
+ { class constructors are not allowed in class helpers }
+ Message(parser_e_no_class_constructor_in_helpers)
+ else
+ if is_record(current_objectdef.extendeddef) then
+ { as long as constructors aren't allowed in records they
+ aren't allowed in helpers either }
+ Message(parser_e_no_constructor_in_records);
+
+ { only 1 class constructor is allowed }
+ if is_classdef and (oo_has_class_constructor in current_structdef.objectoptions) then
+ Message1(parser_e_only_one_class_constructor_allowed, current_structdef.objrealname^);
+
+ oldparse_only:=parse_only;
+ parse_only:=true;
+ if is_classdef then
+ pd:=class_constructor_head
+ else
+ pd:=constructor_head;
+ parse_object_proc_directives(pd);
+ handle_calling_convention(pd);
+
+ { add definition to procsym }
+ proc_add_definition(pd);
+
+ { add procdef options to objectdef options }
+ if (po_virtualmethod in pd.procoptions) then
+ include(current_structdef.objectoptions,oo_has_virtual);
+ chkcpp(pd);
+ maybe_parse_hint_directives(pd);
+
+ parse_only:=oldparse_only;
+ fields_allowed:=false;
+ is_classdef:=false;
+ end;
+ _DESTRUCTOR :
+ begin
+ if (current_structdef.symtable.currentvisibility=vis_published) and
+ not(oo_can_have_published in current_structdef.objectoptions) then
+ Message(parser_e_cant_have_published);
+
+ if not is_classdef then
+ if has_destructor then
+ Message(parser_n_only_one_destructor)
+ else
+ has_destructor:=true;
+
+ if is_interface(current_structdef) then
+ Message(parser_e_no_con_des_in_interfaces);
+
+ { (class) destructors are not allowed in class helpers }
+ if is_objectpascal_helper(current_structdef) then
+ Message(parser_e_no_destructor_in_records);
+
+ if not is_classdef and (current_structdef.symtable.currentvisibility<>vis_public) then
+ Message(parser_w_destructor_should_be_public);
+
+ { Objective-C does not know the concept of a destructor }
+ if is_objc_class_or_protocol(current_structdef) then
+ Message(parser_e_objc_no_constructor_destructor);
+
+ { only 1 class destructor is allowed }
+ if is_classdef and (oo_has_class_destructor in current_structdef.objectoptions) then
+ Message1(parser_e_only_one_class_destructor_allowed, current_structdef.objrealname^);
+
+ oldparse_only:=parse_only;
+ parse_only:=true;
+ if is_classdef then
+ pd:=class_destructor_head
+ else
+ pd:=destructor_head;
+ parse_object_proc_directives(pd);
+ handle_calling_convention(pd);
+
+ { add definition to procsym }
+ proc_add_definition(pd);
+
+ { add procdef options to objectdef options }
+ if (po_virtualmethod in pd.procoptions) then
+ include(current_structdef.objectoptions,oo_has_virtual);
+
+ chkcpp(pd);
+ maybe_parse_hint_directives(pd);
+
+ parse_only:=oldparse_only;
+ fields_allowed:=false;
+ is_classdef:=false;
+ end;
+ _END :
+ begin
+ consume(_END);
+ break;
+ end;
+ else
+ consume(_ID); { Give a ident expected message, like tp7 }
+ end;
+ until false;
+ end;
+
+
+ function object_dec(objecttype:tobjecttyp;const n:tidstring;genericdef:tstoreddef;genericlist:TFPObjectList;fd : tobjectdef;helpertype:thelpertype) : tobjectdef;
+ var
+ old_current_structdef: tabstractrecorddef;
+ old_current_genericdef,
+ old_current_specializedef: tstoreddef;
+ old_parse_generic: boolean;
+ list: TFPObjectList;
+ s: String;
+ st: TSymtable;
+ begin
+ old_current_structdef:=current_structdef;
+ old_current_genericdef:=current_genericdef;
+ old_current_specializedef:=current_specializedef;
+ old_parse_generic:=parse_generic;
+
+ current_structdef:=nil;
+ current_genericdef:=nil;
+ current_specializedef:=nil;
+
+ { objects and class types can't be declared local }
+ if not(symtablestack.top.symtabletype in [globalsymtable,staticsymtable,objectsymtable,recordsymtable]) and
+ not assigned(genericlist) then
+ Message(parser_e_no_local_objects);
+
+ { reuse forward objectdef? }
+ if assigned(fd) then
+ begin
+ if fd.objecttype<>objecttype then
+ begin
+ Message(parser_e_forward_mismatch);
+ { recover }
+ current_structdef:=tobjectdef.create(current_objectdef.objecttype,n,nil);
+ include(current_structdef.objectoptions,oo_is_forward);
+ end
+ else
+ current_structdef:=fd
+ end
+ else
+ begin
+ { anonym objects aren't allow (o : object a : longint; end;) }
+ if n='' then
+ Message(parser_f_no_anonym_objects);
+
+ { create new class }
+ current_structdef:=tobjectdef.create(objecttype,n,nil);
+
+ { include always the forward flag, it'll be removed after the parent class have been
+ added. This is to prevent circular childof loops }
+ include(current_structdef.objectoptions,oo_is_forward);
+
+ if (cs_compilesystem in current_settings.moduleswitches) then
+ begin
+ case current_objectdef.objecttype of
+ odt_interfacecom :
+ if (current_structdef.objname^='IUNKNOWN') then
+ interface_iunknown:=current_objectdef
+ else
+ if (current_structdef.objname^='IDISPATCH') then
+ interface_idispatch:=current_objectdef;
+ odt_class :
+ if (current_structdef.objname^='TOBJECT') then
+ class_tobject:=current_objectdef;
+ end;
+ end;
+ if (current_module.modulename^='OBJCBASE') then
+ begin
+ case current_objectdef.objecttype of
+ odt_objcclass:
+ if (current_objectdef.objname^='Protocol') then
+ objc_protocoltype:=current_objectdef;
+ end;
+ end;
+ end;
+
+ { usage of specialized type inside its generic template }
+ if assigned(genericdef) then
+ current_specializedef:=current_structdef
+ { reject declaration of generic class inside generic class }
+ else if assigned(genericlist) then
+ current_genericdef:=current_structdef;
+
+ { nested types of specializations are specializations as well }
+ if assigned(old_current_structdef) and
+ (df_specialization in old_current_structdef.defoptions) then
+ include(current_structdef.defoptions,df_specialization);
+
+ { set published flag in $M+ mode, it can also be inherited and will
+ be added when the parent class set with tobjectdef.set_parent (PFV) }
+ if (cs_generate_rtti in current_settings.localswitches) and
+ (current_objectdef.objecttype in [odt_interfacecom,odt_class,odt_helper]) then
+ include(current_structdef.objectoptions,oo_can_have_published);
+
+ { Objective-C objectdefs can be "formal definitions", in which case
+ the syntax is "type tc = objcclass external;" -> we have to parse
+ its object options (external) already here, to make sure that such
+ definitions are recognised as formal defs }
+ if objecttype in [odt_objcclass,odt_objcprotocol,odt_objccategory] then
+ parse_object_options;
+
+ { forward def? }
+ if not assigned(fd) and
+ (token=_SEMICOLON) then
+ begin
+ { add to the list of definitions to check that the forward
+ is resolved. this is required for delphi mode }
+ current_module.checkforwarddefs.add(current_structdef);
+ end
+ else
+ begin
+ { change objccategories into objcclass helpers }
+ if (objecttype=odt_objccategory) then
+ begin
+ current_objectdef.objecttype:=odt_objcclass;
+ include(current_structdef.objectoptions,oo_is_classhelper);
+ end;
+
+ { include the class helper flag for Object Pascal helpers }
+ if (objecttype=odt_helper) then
+ include(current_objectdef.objectoptions,oo_is_classhelper);
+
+ { parse list of options (abstract / sealed) }
+ if not(objecttype in [odt_objcclass,odt_objcprotocol,odt_objccategory]) then
+ parse_object_options;
+
+ symtablestack.push(current_structdef.symtable);
+ insert_generic_parameter_types(current_structdef,genericdef,genericlist);
+ { when we are parsing a generic already then this is a generic as
+ well }
+ if old_parse_generic then
+ include(current_structdef.defoptions, df_generic);
+ parse_generic:=(df_generic in current_structdef.defoptions);
+
+ { parse list of parent classes }
+ { for record helpers in mode Delphi this is not allowed }
+ if not (is_objectpascal_helper(current_objectdef) and
+ (m_delphi in current_settings.modeswitches) and
+ (helpertype=ht_record)) then
+ parse_parent_classes
+ else
+ { remove forward flag, is resolved (this is normally done inside
+ parse_parent_classes) }
+ exclude(current_structdef.objectoptions,oo_is_forward);
+
+ { parse extended type for helpers }
+ if is_objectpascal_helper(current_structdef) then
+ parse_extended_type(helpertype);
+
+ { parse optional GUID for interfaces }
+ parse_guid;
+
+ { parse and insert object members }
+ parse_object_members;
+ symtablestack.pop(current_structdef.symtable);
+ end;
+
+ { generate vmt space if needed }
+ if not(oo_has_vmt in current_structdef.objectoptions) and
+ not(oo_is_forward in current_structdef.objectoptions) and
+ (
+ ([oo_has_virtual,oo_has_constructor,oo_has_destructor]*current_structdef.objectoptions<>[]) or
+ (current_objectdef.objecttype in [odt_class])
+ ) then
+ current_objectdef.insertvmt;
+
+ { for implemented classes with a vmt check if there is a constructor }
+ if (oo_has_vmt in current_structdef.objectoptions) and
+ not(oo_is_forward in current_structdef.objectoptions) and
+ not(oo_has_constructor in current_structdef.objectoptions) and
+ not is_objc_class_or_protocol(current_structdef) then
+ Message1(parser_w_virtual_without_constructor,current_structdef.objrealname^);
+
+ if is_interface(current_structdef) or
+ is_objcprotocol(current_structdef) then
+ setinterfacemethodoptions
+ else if is_objcclass(current_structdef) then
+ setobjcclassmethodoptions;
+
+ { if this helper is defined in the implementation section of the unit
+ or inside the main project file, the extendeddefs list of the current
+ module must be updated (it will be removed when poping the symtable) }
+ if is_objectpascal_helper(current_structdef) and
+ (current_objectdef.extendeddef.typ in [recorddef,objectdef]) then
+ begin
+ { the topmost symtable must be a static symtable }
+ st:=current_structdef.owner;
+ while st.symtabletype in [objectsymtable,recordsymtable] do
+ st:=st.defowner.owner;
+ if st.symtabletype=staticsymtable then
+ begin
+ s:=make_mangledname('',tabstractrecorddef(current_objectdef.extendeddef).symtable,'');
+ list:=TFPObjectList(current_module.extendeddefs.Find(s));
+ if not assigned(list) then
+ begin
+ list:=TFPObjectList.Create(false);
+ current_module.extendeddefs.Add(s, list);
+ end;
+ list.add(current_structdef);
+ end;
+ end;
+ tabstractrecordsymtable(current_objectdef.symtable).addalignmentpadding;
+
+ { return defined objectdef }
+ result:=current_objectdef;
+
+ { restore old state }
+ current_structdef:=old_current_structdef;
+ current_genericdef:=old_current_genericdef;
+ current_specializedef:=old_current_specializedef;
+ parse_generic:=old_parse_generic;
+ end;
+
+end.
diff --git a/closures/compiler/pdecsub.pas b/closures/compiler/pdecsub.pas
new file mode 100644
index 0000000000..b73c4b3a3a
--- /dev/null
+++ b/closures/compiler/pdecsub.pas
@@ -0,0 +1,3388 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl, Daniel Mantione
+
+ Does the parsing of the procedures/functions
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit pdecsub;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ tokens,symconst,symtype,symdef,symsym;
+
+ type
+ tpdflag=(
+ pd_body, { directive needs a body }
+ pd_implemen, { directive can be used in implementation section }
+ pd_interface, { directive can be used in interface section }
+ pd_object, { directive can be used with object declaration }
+ pd_record, { directive can be used with record declaration }
+ pd_procvar, { directive can be used with procvar declaration }
+ pd_notobject, { directive can not be used with object declaration }
+ pd_notrecord, { directive can not be used with record declaration }
+ pd_notobjintf, { directive can not be used with interface declaration }
+ pd_notprocvar, { directive can not be used with procvar declaration }
+ pd_dispinterface,{ directive can be used with dispinterface methods }
+ pd_cppobject, { directive can be used with cppclass }
+ pd_objcclass, { directive can be used with objcclass }
+ pd_objcprot, { directive can be used with objcprotocol }
+ pd_nothelper { directive can not be used with record/class helper declaration }
+ );
+ tpdflags=set of tpdflag;
+
+ function check_proc_directive(isprocvar:boolean):boolean;
+
+ procedure insert_funcret_local(pd:tprocdef);
+
+ function proc_add_definition(var currpd:tprocdef):boolean;
+ function proc_get_importname(pd:tprocdef):string;
+ procedure proc_set_mangledname(pd:tprocdef);
+
+ procedure handle_calling_convention(pd:tabstractprocdef);
+
+ procedure parse_parameter_dec(pd:tabstractprocdef);
+ procedure parse_proc_directives(pd:tabstractprocdef;var pdflags:tpdflags);
+ procedure parse_var_proc_directives(sym:tsym);
+ procedure parse_object_proc_directives(pd:tabstractprocdef);
+ procedure parse_record_proc_directives(pd:tabstractprocdef);
+ function parse_proc_head(astruct:tabstractrecorddef;potype:tproctypeoption;out pd:tprocdef):boolean;
+ function parse_proc_dec(isclassmethod:boolean;astruct:tabstractrecorddef):tprocdef;
+
+ { helper functions - they insert nested objects hierarcy to the symtablestack
+ with object hierarchy
+ }
+ function push_child_hierarcy(obj:tabstractrecorddef):integer;
+ function pop_child_hierarchy(obj:tabstractrecorddef):integer;
+ function push_nested_hierarchy(obj:tabstractrecorddef):integer;
+ function pop_nested_hierarchy(obj:tabstractrecorddef):integer;
+
+implementation
+
+ uses
+ SysUtils,
+ { common }
+ cutils,cclasses,
+ { global }
+ globtype,globals,verbose,constexp,
+ systems,fpccrc,
+ cpuinfo,
+ { symtable }
+ symbase,symtable,defutil,defcmp,paramgr,cpupara,
+ { pass 1 }
+ fmodule,node,htypechk,
+ nmat,nadd,ncal,nset,ncnv,ninl,ncon,nld,nflw,
+ objcutil,
+ { parser }
+ scanner,
+ pbase,pexpr,ptype,pdecl
+ ;
+
+ const
+ { Please leave this here, this module should NOT use
+ these variables.
+ Declaring it as string here results in an error when compiling (PFV) }
+ current_procinfo = 'error';
+
+ function push_child_hierarcy(obj:tabstractrecorddef):integer;
+ var
+ _class,hp : tobjectdef;
+ begin
+ if obj.typ=recorddef then
+ begin
+ symtablestack.push(obj.symtable);
+ result:=1;
+ exit;
+ end;
+ result:=0;
+ { insert class hierarchy in the reverse order }
+ hp:=nil;
+ repeat
+ _class:=tobjectdef(obj);
+ while _class.childof<>hp do
+ _class:=_class.childof;
+ hp:=_class;
+ symtablestack.push(_class.symtable);
+ inc(result);
+ until hp=obj;
+ end;
+
+ function push_nested_hierarchy(obj:tabstractrecorddef):integer;
+ begin
+ result:=0;
+ if obj.owner.symtabletype in [ObjectSymtable,recordsymtable] then
+ inc(result,push_nested_hierarchy(tabstractrecorddef(obj.owner.defowner)));
+ inc(result,push_child_hierarcy(obj));
+ end;
+
+ function pop_child_hierarchy(obj:tabstractrecorddef):integer;
+ var
+ _class : tobjectdef;
+ begin
+ if obj.typ=recorddef then
+ begin
+ symtablestack.pop(obj.symtable);
+ result:=1;
+ exit;
+ end;
+ result:=0;
+ _class:=tobjectdef(obj);
+ while assigned(_class) do
+ begin
+ symtablestack.pop(_class.symtable);
+ _class:=_class.childof;
+ inc(result);
+ end;
+ end;
+
+ function pop_nested_hierarchy(obj:tabstractrecorddef):integer;
+ begin
+ result:=pop_child_hierarchy(obj);
+ if obj.owner.symtabletype in [ObjectSymtable,recordsymtable] then
+ inc(result,pop_nested_hierarchy(tabstractrecorddef(obj.owner.defowner)));
+ end;
+
+ procedure insert_funcret_para(pd:tabstractprocdef);
+ var
+ storepos : tfileposinfo;
+ vs : tparavarsym;
+ paranr : word;
+ begin
+ if not(pd.proctypeoption in [potype_constructor,potype_destructor]) and
+ not is_void(pd.returndef) and
+ paramanager.ret_in_param(pd.returndef,pd.proccalloption) then
+ begin
+ storepos:=current_tokenpos;
+ if pd.typ=procdef then
+ current_tokenpos:=tprocdef(pd).fileinfo;
+
+{$if defined(i386)}
+ { For left to right add it at the end to be delphi compatible.
+ In the case of safecalls with safecal-exceptions support the
+ funcret-para is (from the 'c'-point of view) a normal parameter
+ which has to be added to the end of the parameter-list }
+ if (pd.proccalloption in (pushleftright_pocalls)) or
+ ((tf_safecall_exceptions in target_info.flags) and
+ (pd.proccalloption=pocall_safecall)) then
+ paranr:=paranr_result_leftright
+ else
+{$elseif defined(x86) or defined(arm)}
+ if (tf_safecall_exceptions in target_info.flags) and
+ (pd.proccalloption = pocall_safecall) then
+ paranr:=paranr_result_leftright
+ else
+{$endif}
+ paranr:=paranr_result;
+ { Generate result variable accessing function result }
+ vs:=tparavarsym.create('$result',paranr,vs_var,pd.returndef,[vo_is_funcret,vo_is_hidden_para]);
+ pd.parast.insert(vs);
+ { Store the this symbol as funcretsym for procedures }
+ if pd.typ=procdef then
+ tprocdef(pd).funcretsym:=vs;
+
+ current_tokenpos:=storepos;
+ end;
+ end;
+
+
+ procedure insert_parentfp_para(pd:tabstractprocdef);
+ var
+ storepos : tfileposinfo;
+ vs : tparavarsym;
+ paranr : longint;
+ begin
+ if pd.parast.symtablelevel>normal_function_level then
+ begin
+ storepos:=current_tokenpos;
+ if pd.typ=procdef then
+ current_tokenpos:=tprocdef(pd).fileinfo;
+
+ { if no support for nested procvars is activated, use the old
+ calling convention to pass the parent frame pointer for backwards
+ compatibility }
+ if not(m_nested_procvars in current_settings.modeswitches) then
+ paranr:=paranr_parentfp
+ { nested procvars require Delphi-style parentfp passing, see
+ po_delphi_nested_cc declaration for more info }
+{$ifdef i386}
+ else if (pd.proccalloption in pushleftright_pocalls) then
+ paranr:=paranr_parentfp_delphi_cc_leftright
+{$endif i386}
+ else
+ paranr:=paranr_parentfp_delphi_cc;
+ { Generate result variable accessing function result, it
+ can't be put in a register since it must be accessable
+ from the framepointer }
+ vs:=tparavarsym.create('$parentfp',paranr,vs_value
+ ,voidpointertype,[vo_is_parentfp,vo_is_hidden_para]);
+ vs.varregable:=vr_none;
+ pd.parast.insert(vs);
+
+ current_tokenpos:=storepos;
+ end;
+ end;
+
+
+ procedure insert_self_and_vmt_para(pd:tabstractprocdef);
+ var
+ storepos : tfileposinfo;
+ vs : tparavarsym;
+ hdef : tdef;
+ selfdef : tdef;
+ vsp : tvarspez;
+ aliasvs : tabsolutevarsym;
+ sl : tpropaccesslist;
+ begin
+ if (pd.typ=procdef) and
+ is_objc_class_or_protocol(tprocdef(pd).struct) and
+ (pd.parast.symtablelevel=normal_function_level) then
+ begin
+ { insert Objective-C self and selector parameters }
+ vs:=tparavarsym.create('$_cmd',paranr_objc_cmd,vs_value,objc_seltype,[vo_is_msgsel,vo_is_hidden_para]);
+ pd.parast.insert(vs);
+ { make accessible to code }
+ sl:=tpropaccesslist.create;
+ sl.addsym(sl_load,vs);
+ aliasvs:=tabsolutevarsym.create_ref('_CMD',objc_seltype,sl);
+ include(aliasvs.varoptions,vo_is_msgsel);
+ tlocalsymtable(tprocdef(pd).localst).insert(aliasvs);
+
+ if (po_classmethod in pd.procoptions) then
+ { compatible with what gcc does }
+ hdef:=objc_idtype
+ else
+ hdef:=tprocdef(pd).struct;
+
+ vs:=tparavarsym.create('$self',paranr_objc_self,vs_value,hdef,[vo_is_self,vo_is_hidden_para]);
+ pd.parast.insert(vs);
+ end
+ else if (pd.typ=procvardef) and
+ pd.is_methodpointer then
+ begin
+ { Generate self variable }
+ vs:=tparavarsym.create('$self',paranr_self,vs_value,voidpointertype,[vo_is_self,vo_is_hidden_para]);
+ pd.parast.insert(vs);
+ end
+ else
+ begin
+ if (pd.typ=procdef) and
+ assigned(tprocdef(pd).struct) and
+ (pd.parast.symtablelevel=normal_function_level) then
+ begin
+ { static class methods have no hidden self/vmt pointer }
+ if pd.no_self_node then
+ exit;
+
+ storepos:=current_tokenpos;
+ current_tokenpos:=tprocdef(pd).fileinfo;
+
+ { Generate VMT variable for constructor/destructor }
+ if (pd.proctypeoption in [potype_constructor,potype_destructor]) and
+ not(is_cppclass(tprocdef(pd).struct) or is_record(tprocdef(pd).struct)) then
+ begin
+ { can't use classrefdef as type because inheriting
+ will then always file because of a type mismatch }
+ vs:=tparavarsym.create('$vmt',paranr_vmt,vs_value,voidpointertype,[vo_is_vmt,vo_is_hidden_para]);
+ pd.parast.insert(vs);
+ end;
+
+ { for helpers the type of Self is equivalent to the extended
+ type or equal to an instance of it }
+ if is_objectpascal_helper(tprocdef(pd).struct) then
+ selfdef:=tobjectdef(tprocdef(pd).struct).extendeddef
+ else
+ selfdef:=tprocdef(pd).struct;
+ { Generate self variable, for classes we need
+ to use the generic voidpointer to be compatible with
+ methodpointers }
+ vsp:=vs_value;
+ if (po_staticmethod in pd.procoptions) or
+ (po_classmethod in pd.procoptions) then
+ hdef:=tclassrefdef.create(selfdef)
+ else
+ begin
+ if is_object(selfdef) or is_record(selfdef) then
+ vsp:=vs_var;
+ hdef:=selfdef;
+ end;
+ vs:=tparavarsym.create('$self',paranr_self,vsp,hdef,[vo_is_self,vo_is_hidden_para]);
+ pd.parast.insert(vs);
+
+ current_tokenpos:=storepos;
+ end;
+ end;
+ end;
+
+
+ procedure insert_funcret_local(pd:tprocdef);
+ var
+ storepos : tfileposinfo;
+ vs : tlocalvarsym;
+ aliasvs : tabsolutevarsym;
+ sl : tpropaccesslist;
+ hs : string;
+ begin
+ { The result from constructors and destructors can't be accessed directly }
+ if not(pd.proctypeoption in [potype_constructor,potype_destructor]) and
+ not is_void(pd.returndef) then
+ begin
+ storepos:=current_tokenpos;
+ current_tokenpos:=pd.fileinfo;
+
+ { We need to insert a varsym for the result in the localst
+ when it is returning in a register }
+ if not paramanager.ret_in_param(pd.returndef,pd.proccalloption) then
+ begin
+ vs:=tlocalvarsym.create('$result',vs_value,pd.returndef,[vo_is_funcret]);
+ pd.localst.insert(vs);
+ pd.funcretsym:=vs;
+ end;
+
+ { insert the name of the procedure as alias for the function result,
+ we can't use realname because that will not work for compilerprocs
+ as the name is lowercase and unreachable from the code }
+ if assigned(pd.resultname) then
+ hs:=pd.resultname^
+ else
+ hs:=pd.procsym.name;
+ sl:=tpropaccesslist.create;
+ sl.addsym(sl_load,pd.funcretsym);
+ aliasvs:=tabsolutevarsym.create_ref(hs,pd.returndef,sl);
+ include(aliasvs.varoptions,vo_is_funcret);
+ tlocalsymtable(pd.localst).insert(aliasvs);
+
+ { insert result also if support is on }
+ if (m_result in current_settings.modeswitches) then
+ begin
+ sl:=tpropaccesslist.create;
+ sl.addsym(sl_load,pd.funcretsym);
+ aliasvs:=tabsolutevarsym.create_ref('RESULT',pd.returndef,sl);
+ include(aliasvs.varoptions,vo_is_funcret);
+ include(aliasvs.varoptions,vo_is_result);
+ tlocalsymtable(pd.localst).insert(aliasvs);
+ end;
+
+ current_tokenpos:=storepos;
+ end;
+ end;
+
+
+ procedure insert_hidden_para(p:TObject;arg:pointer);
+ var
+ hvs : tparavarsym;
+ pd : tabstractprocdef absolute arg;
+ begin
+ if (tsym(p).typ<>paravarsym) then
+ exit;
+ with tparavarsym(p) do
+ begin
+ { We need a local copy for a value parameter when only the
+ address is pushed. Open arrays and Array of Const are
+ an exception because they are allocated at runtime and the
+ address that is pushed is patched }
+ if (varspez=vs_value) and
+ paramanager.push_addr_param(varspez,vardef,pd.proccalloption) and
+ not(is_open_array(vardef) or
+ is_array_of_const(vardef)) then
+ include(varoptions,vo_has_local_copy);
+
+ { needs high parameter ? }
+ if paramanager.push_high_param(varspez,vardef,pd.proccalloption) then
+ begin
+ hvs:=tparavarsym.create('$high'+name,paranr+1,vs_const,sinttype,[vo_is_high_para,vo_is_hidden_para]);
+ hvs.symoptions:=[];
+ owner.insert(hvs);
+ { don't place to register if it will be accessed from implicit finally block }
+ if (varspez=vs_value) and
+ is_open_array(vardef) and
+ is_managed_type(vardef) then
+ hvs.varregable:=vr_none;
+ end
+ else
+ begin
+ { Give a warning that cdecl routines does not include high()
+ support }
+ if (pd.proccalloption in cdecl_pocalls) and
+ paramanager.push_high_param(varspez,vardef,pocall_default) then
+ begin
+ if is_open_string(vardef) then
+ MessagePos(fileinfo,parser_w_cdecl_no_openstring);
+ if not(po_external in pd.procoptions) and
+ (pd.typ<>procvardef) and
+ not is_objc_class_or_protocol(tprocdef(pd).struct) then
+ if is_array_of_const(vardef) then
+ MessagePos(fileinfo,parser_e_varargs_need_cdecl_and_external)
+ else
+ MessagePos(fileinfo,parser_w_cdecl_has_no_high);
+ end;
+ if (vardef.typ=formaldef) and (Tformaldef(vardef).typed) then
+ begin
+ hvs:=tparavarsym.create('$typinfo'+name,paranr+1,vs_const,voidpointertype,
+ [vo_is_typinfo_para,vo_is_hidden_para]);
+ owner.insert(hvs);
+ end;
+ end;
+ end;
+ end;
+
+
+ procedure check_c_para(pd:Tabstractprocdef);
+ var
+ i,
+ lastparaidx : longint;
+ sym : TSym;
+ begin
+ lastparaidx:=pd.parast.SymList.Count-1;
+ for i:=0 to pd.parast.SymList.Count-1 do
+ begin
+ sym:=tsym(pd.parast.SymList[i]);
+ if (sym.typ=paravarsym) and
+ (tparavarsym(sym).vardef.typ=arraydef) then
+ begin
+ if not is_variant_array(tparavarsym(sym).vardef) and
+ not is_array_of_const(tparavarsym(sym).vardef) and
+ (tparavarsym(sym).varspez<>vs_var) then
+ MessagePos(tparavarsym(sym).fileinfo,parser_h_c_arrays_are_references);
+ if is_array_of_const(tparavarsym(sym).vardef) and
+ (i<lastparaidx) and
+ (tsym(pd.parast.SymList[i+1]).typ=paravarsym) and
+ not(vo_is_high_para in tparavarsym(pd.parast.SymList[i+1]).varoptions) then
+ MessagePos(tparavarsym(sym).fileinfo,parser_e_C_array_of_const_must_be_last);
+ end;
+ end;
+ end;
+
+
+ procedure check_msg_para(p:TObject;arg:pointer);
+ begin
+ if (tsym(p).typ<>paravarsym) then
+ exit;
+ with tparavarsym(p) do
+ begin
+ { Count parameters }
+ if (paranr>=10) then
+ inc(plongint(arg)^);
+ { First parameter must be var }
+ if (paranr=10) and
+ (varspez<>vs_var) then
+ MessagePos(fileinfo,parser_e_ill_msg_param);
+ end;
+ end;
+
+
+ procedure set_addr_param_regable(p:TObject;arg:pointer);
+ begin
+ if (tsym(p).typ<>paravarsym) then
+ exit;
+ with tparavarsym(p) do
+ begin
+ if (not needs_finalization) and
+ paramanager.push_addr_param(varspez,vardef,tprocdef(arg).proccalloption) then
+ varregable:=vr_intreg;
+ end;
+ end;
+
+
+ procedure parse_parameter_dec(pd:tabstractprocdef);
+ {
+ handle_procvar needs the same changes
+ }
+ type
+ tppv = (pv_none,pv_proc,pv_func);
+ var
+ sc : TFPObjectList;
+ hdef : tdef;
+ arrayelementdef : tdef;
+ vs : tparavarsym;
+ i : longint;
+ srsym : tsym;
+ pv : tprocvardef;
+ varspez : Tvarspez;
+ defaultvalue : tconstsym;
+ defaultrequired : boolean;
+ old_block_type : tblock_type;
+ currparast : tparasymtable;
+ parseprocvar : tppv;
+ locationstr : string;
+ paranr : integer;
+ dummytype : ttypesym;
+ explicit_paraloc,
+ need_array,
+ is_univ: boolean;
+ begin
+ old_block_type:=block_type;
+ explicit_paraloc:=false;
+ consume(_LKLAMMER);
+ { Delphi/Kylix supports nonsense like }
+ { procedure p(); }
+ if try_to_consume(_RKLAMMER) and
+ not(m_tp7 in current_settings.modeswitches) then
+ exit;
+ { parsing a proc or procvar ? }
+ currparast:=tparasymtable(pd.parast);
+ { reset }
+ sc:=TFPObjectList.create(false);
+ defaultrequired:=false;
+ paranr:=0;
+ block_type:=bt_var;
+ is_univ:=false;
+ repeat
+ parseprocvar:=pv_none;
+ if try_to_consume(_VAR) then
+ varspez:=vs_var
+ else
+ if try_to_consume(_CONST) then
+ varspez:=vs_const
+ else
+ if (m_out in current_settings.modeswitches) and
+ try_to_consume(_OUT) then
+ varspez:=vs_out
+ else
+ if try_to_consume(_CONSTREF) then
+ varspez:=vs_constref
+ else
+ if (m_mac in current_settings.modeswitches) and
+ try_to_consume(_POINTPOINTPOINT) then
+ begin
+ include(pd.procoptions,po_varargs);
+ break;
+ end
+ else
+ if (m_nested_procvars in current_settings.modeswitches) and
+ try_to_consume(_PROCEDURE) then
+ begin
+ parseprocvar:=pv_proc;
+ varspez:=vs_const;
+ end
+ else
+ if (m_nested_procvars in current_settings.modeswitches) and
+ try_to_consume(_FUNCTION) then
+ begin
+ parseprocvar:=pv_func;
+ varspez:=vs_const;
+ end
+ else
+ varspez:=vs_value;
+ defaultvalue:=nil;
+ hdef:=nil;
+ { read identifiers and insert with error type }
+ sc.clear;
+ repeat
+ inc(paranr);
+ vs:=tparavarsym.create(orgpattern,paranr*10,varspez,generrordef,[]);
+ currparast.insert(vs);
+ if assigned(vs.owner) then
+ sc.add(vs)
+ else
+ vs.free;
+ consume(_ID);
+ until not try_to_consume(_COMMA);
+ locationstr:='';
+ { macpas anonymous procvar }
+ if parseprocvar<>pv_none then
+ begin
+ { inline procvar definitions are always nested procvars }
+ pv:=tprocvardef.create(normal_function_level+1);
+ if token=_LKLAMMER then
+ parse_parameter_dec(pv);
+ if parseprocvar=pv_func then
+ begin
+ block_type:=bt_var_type;
+ consume(_COLON);
+ single_type(pv.returndef,[]);
+ block_type:=bt_var;
+ end;
+ hdef:=pv;
+ { possible proc directives }
+ if check_proc_directive(true) then
+ begin
+ dummytype:=ttypesym.create('unnamed',hdef);
+ parse_var_proc_directives(tsym(dummytype));
+ dummytype.typedef:=nil;
+ hdef.typesym:=nil;
+ dummytype.free;
+ end;
+ { Add implicit hidden parameters and function result }
+ handle_calling_convention(pv);
+ end
+ else
+ { read type declaration, force reading for value paras }
+ if (token=_COLON) or (varspez=vs_value) then
+ begin
+ consume(_COLON);
+ { check for an open array }
+ need_array:=false;
+ { bitpacked open array are not yet supported }
+ if (token=_PACKED) and
+ not(cs_bitpacking in current_settings.localswitches) then
+ begin
+ consume(_PACKED);
+ need_array:=true;
+ end;
+ if (token=_ARRAY) or
+ need_array then
+ begin
+ consume(_ARRAY);
+ consume(_OF);
+ { define range and type of range }
+ hdef:=tarraydef.create(0,-1,s32inttype);
+ { array of const ? }
+ if (token=_CONST) and (m_objpas in current_settings.modeswitches) then
+ begin
+ consume(_CONST);
+ srsym:=search_system_type('TVARREC');
+ tarraydef(hdef).elementdef:=ttypesym(srsym).typedef;
+ include(tarraydef(hdef).arrayoptions,ado_IsArrayOfConst);
+ end
+ else
+ begin
+ { define field type }
+ single_type(arrayelementdef,[]);
+ tarraydef(hdef).elementdef:=arrayelementdef;
+ end;
+ end
+ else
+ begin
+ if (m_mac in current_settings.modeswitches) then
+ is_univ:=try_to_consume(_UNIV);
+
+ if try_to_consume(_TYPE) then
+ hdef:=ctypedformaltype
+ else
+ begin
+ block_type:=bt_var_type;
+ single_type(hdef,[stoAllowSpecialization]);
+ block_type:=bt_var;
+ end;
+
+ { open string ? }
+ if is_shortstring(hdef) then
+ begin
+ case varspez of
+ vs_var,vs_out,vs_constref:
+ begin
+ { not 100% Delphi-compatible: type xstr=string[255] cannot
+ become an openstring there, while here it can }
+ if (cs_openstring in current_settings.moduleswitches) and
+ (tstringdef(hdef).len=255) then
+ hdef:=openshortstringtype
+ end;
+ vs_value:
+ begin
+ { value "openstring" parameters don't make sense (the
+ original string can never be modified, so there's no
+ use in passing its original length), so change these
+ into regular shortstring parameters (seems to be what
+ Delphi also does) }
+ if is_open_string(hdef) then
+ hdef:=cshortstringtype;
+ end;
+ end;
+ end;
+ if (target_info.system in [system_powerpc_morphos,system_m68k_amiga]) then
+ begin
+ if (idtoken=_LOCATION) then
+ begin
+ consume(_LOCATION);
+ locationstr:=cstringpattern;
+ consume(_CSTRING);
+ end
+ else
+ begin
+ if explicit_paraloc then
+ Message(parser_e_paraloc_all_paras);
+ locationstr:='';
+ end;
+ end
+ else
+ locationstr:='';
+
+ { default parameter }
+ if (m_default_para in current_settings.modeswitches) then
+ begin
+ if try_to_consume(_EQ) then
+ begin
+ vs:=tparavarsym(sc[0]);
+ if sc.count>1 then
+ Message(parser_e_default_value_only_one_para);
+ { prefix 'def' to the parameter name }
+ defaultvalue:=ReadConstant('$def'+vs.name,vs.fileinfo);
+ if assigned(defaultvalue) then
+ begin
+ include(defaultvalue.symoptions,sp_internal);
+ pd.parast.insert(defaultvalue);
+ end;
+ defaultrequired:=true;
+ end
+ else
+ begin
+ if defaultrequired then
+ Message1(parser_e_default_value_expected_for_para,vs.name);
+ end;
+ end;
+ end;
+ end
+ else
+ hdef:=cformaltype;
+
+ { File types are only allowed for var and out parameters }
+ if (hdef.typ=filedef) and
+ not(varspez in [vs_out,vs_var]) then
+ CGMessage(cg_e_file_must_call_by_reference);
+
+ { Dispinterfaces are restricted to using only automatable types }
+ if (pd.typ=procdef) and is_dispinterface(tprocdef(pd).struct) and
+ not is_automatable(hdef) then
+ Message1(type_e_not_automatable,hdef.typename);
+
+ { univ cannot be used with types whose size is not known at compile
+ time }
+ if is_univ and
+ not is_valid_univ_para_type(hdef) then
+ Message1(parser_e_invalid_univ_para,hdef.typename);
+
+ for i:=0 to sc.count-1 do
+ begin
+ vs:=tparavarsym(sc[i]);
+ vs.univpara:=is_univ;
+ { update varsym }
+ vs.vardef:=hdef;
+ vs.defaultconstsym:=defaultvalue;
+
+ if (target_info.system in [system_powerpc_morphos,system_m68k_amiga]) then
+ begin
+ if locationstr<>'' then
+ begin
+ if sc.count>1 then
+ Message(parser_e_paraloc_only_one_para);
+ if (paranr>1) and not(explicit_paraloc) then
+ Message(parser_e_paraloc_all_paras);
+ explicit_paraloc:=true;
+ include(vs.varoptions,vo_has_explicit_paraloc);
+ if not(paramanager.parseparaloc(vs,upper(locationstr))) then
+ message(parser_e_illegal_explicit_paraloc);
+ end
+ else
+ if explicit_paraloc then
+ Message(parser_e_paraloc_all_paras);
+ end;
+ end;
+ until not try_to_consume(_SEMICOLON);
+
+ if explicit_paraloc then
+ begin
+ pd.has_paraloc_info:=callerside;
+ include(pd.procoptions,po_explicitparaloc);
+ end;
+ { remove parasymtable from stack }
+ sc.free;
+ { reset object options }
+ block_type:=old_block_type;
+ consume(_RKLAMMER);
+ end;
+
+
+ function parse_proc_head(astruct:tabstractrecorddef;potype:tproctypeoption;out pd:tprocdef):boolean;
+ var
+ hs : string;
+ orgsp,sp : TIDString;
+ srsym : tsym;
+ checkstack : psymtablestackitem;
+ procstartfilepos : tfileposinfo;
+ searchagain : boolean;
+ st,
+ genericst: TSymtable;
+ aprocsym : tprocsym;
+ popclass : integer;
+ ImplIntf : TImplementedInterface;
+ old_parse_generic : boolean;
+ old_current_structdef: tabstractrecorddef;
+ old_current_genericdef,
+ old_current_specializedef: tstoreddef;
+ lasttoken,lastidtoken: ttoken;
+
+ procedure parse_operator_name;
+ begin
+ if (lasttoken in [first_overloaded..last_overloaded]) then
+ begin
+ optoken:=token;
+ end
+ else
+ begin
+ case lasttoken of
+ _CARET:
+ Message1(parser_e_overload_operator_failed,'**');
+ _ID:
+ case lastidtoken of
+ _ENUMERATOR:optoken:=_OP_ENUMERATOR;
+ _EXPLICIT:optoken:=_OP_EXPLICIT;
+ _INC:optoken:=_OP_INC;
+ _DEC:optoken:=_OP_DEC;
+ else
+ if (m_delphi in current_settings.modeswitches) then
+ case lastidtoken of
+ _IMPLICIT:optoken:=_ASSIGNMENT;
+ _NEGATIVE:optoken:=_MINUS;
+ _POSITIVE:optoken:=_PLUS;
+ _LOGICALNOT:optoken:=_OP_NOT;
+ _IN:optoken:=_OP_IN;
+ _EQUAL:optoken:=_EQ;
+ _NOTEQUAL:optoken:=_NE;
+ _GREATERTHAN:optoken:=_GT;
+ _GREATERTHANOREQUAL:optoken:=_GTE;
+ _LESSTHAN:optoken:=_LT;
+ _LESSTHANOREQUAL:optoken:=_LTE;
+ _ADD:optoken:=_PLUS;
+ _SUBTRACT:optoken:=_MINUS;
+ _MULTIPLY:optoken:=_STAR;
+ _DIVIDE:optoken:=_SLASH;
+ _INTDIVIDE:optoken:=_OP_DIV;
+ _MODULUS:optoken:=_OP_MOD;
+ _LEFTSHIFT:optoken:=_OP_SHL;
+ _RIGHTSHIFT:optoken:=_OP_SHR;
+ _LOGICALAND:optoken:=_OP_AND;
+ _LOGICALOR:optoken:=_OP_OR;
+ _LOGICALXOR:optoken:=_OP_XOR;
+ _BITWISEAND:optoken:=_OP_AND;
+ _BITWISEOR:optoken:=_OP_OR;
+ _BITWISEXOR:optoken:=_OP_XOR;
+ else
+ Message1(parser_e_overload_operator_failed,'');
+ end
+ else
+ Message1(parser_e_overload_operator_failed,'');
+ end
+ else
+ Message1(parser_e_overload_operator_failed,'');
+ end;
+ end;
+ sp:=overloaded_names[optoken];
+ orgsp:=sp;
+ end;
+
+ procedure consume_proc_name;
+ begin
+ lasttoken:=token;
+ lastidtoken:=idtoken;
+ if potype=potype_operator then
+ optoken:=NOTOKEN;
+ if (potype=potype_operator) and (token<>_ID) then
+ begin
+ parse_operator_name;
+ consume(token);
+ end
+ else
+ begin
+ sp:=pattern;
+ orgsp:=orgpattern;
+ consume(_ID);
+ end;
+ end;
+
+ function search_object_name(sp:TIDString;gen_error:boolean):tsym;
+ var
+ storepos:tfileposinfo;
+ srsymtable:TSymtable;
+ begin
+ storepos:=current_tokenpos;
+ current_tokenpos:=procstartfilepos;
+ searchsym(sp,result,srsymtable);
+ if not assigned(result) then
+ begin
+ if gen_error then
+ identifier_not_found(orgsp);
+ result:=generrorsym;
+ end;
+ current_tokenpos:=storepos;
+ end;
+
+ function consume_generic_type_parameter:boolean;
+ var
+ idx : integer;
+ genparalistdecl : TFPHashList;
+ genname : tidstring;
+ s : shortstring;
+ begin
+ result:=not assigned(astruct)and(m_delphi in current_settings.modeswitches);
+ if result then
+ begin
+ { parse all parameters first so we can check whether we have
+ the correct generic def available }
+ genparalistdecl:=TFPHashList.Create;
+ if try_to_consume(_LT) then
+ begin
+ { start with 1, so Find can return Nil (= 0) }
+ idx:=1;
+ repeat
+ if token=_ID then
+ begin
+ genparalistdecl.Add(pattern, Pointer(PtrInt(idx)));
+ consume(_ID);
+ inc(idx);
+ end
+ else
+ begin
+ message2(scan_f_syn_expected,arraytokeninfo[_ID].str,arraytokeninfo[token].str);
+ if token<>_COMMA then
+ consume(token);
+ end;
+ until not try_to_consume(_COMMA);
+ if not try_to_consume(_GT) then
+ consume(_RSHARPBRACKET);
+ end
+ else
+ begin
+ { no generic }
+ srsym:=nil;
+ exit;
+ end;
+
+ s:='';
+ str(genparalistdecl.count,s);
+ genname:=sp+'$'+s;
+
+ genparalistdecl.free;
+
+ srsym:=search_object_name(genname,false);
+
+ if not assigned(srsym) then
+ begin
+ { TODO : print a nicer typename that contains the parsed
+ generic types }
+ Message1(type_e_generic_declaration_does_not_match,genname);
+ srsym:=nil;
+ exit;
+ end;
+ end;
+ end;
+
+ begin
+ { Save the position where this procedure really starts }
+ procstartfilepos:=current_tokenpos;
+ old_parse_generic:=parse_generic;
+
+ result:=false;
+ pd:=nil;
+ aprocsym:=nil;
+
+ consume_proc_name;
+
+ { examine interface map: function/procedure iname.functionname=locfuncname }
+ if assigned(astruct) and
+ (astruct.typ=objectdef) and
+ assigned(tobjectdef(astruct).ImplementedInterfaces) and
+ (tobjectdef(astruct).ImplementedInterfaces.count>0) and
+ try_to_consume(_POINT) then
+ begin
+ srsym:=search_object_name(sp,true);
+ { qualifier is interface? }
+ ImplIntf:=nil;
+ if (srsym.typ=typesym) and
+ (ttypesym(srsym).typedef.typ=objectdef) then
+ ImplIntf:=tobjectdef(astruct).find_implemented_interface(tobjectdef(ttypesym(srsym).typedef));
+ if ImplIntf=nil then
+ Message(parser_e_interface_id_expected);
+ { must be a directly implemented interface }
+ if Assigned(ImplIntf.ImplementsGetter) then
+ Message2(parser_e_implements_no_mapping,ImplIntf.IntfDef.typename,astruct.objrealname^);
+ consume(_ID);
+ { Create unique name <interface>.<method> }
+ hs:=sp+'.'+pattern;
+ consume(_EQ);
+ if assigned(ImplIntf) and
+ (token=_ID) then
+ ImplIntf.AddMapping(hs,pattern);
+ consume(_ID);
+ result:=true;
+ exit;
+ end;
+
+ { method ? }
+ srsym:=nil;
+ if (consume_generic_type_parameter or not assigned(astruct)) and
+ (symtablestack.top.symtablelevel=main_program_level) and
+ try_to_consume(_POINT) then
+ begin
+ repeat
+ searchagain:=false;
+ if not assigned(astruct) and not assigned(srsym) then
+ srsym:=search_object_name(sp,true);
+ { consume proc name }
+ procstartfilepos:=current_tokenpos;
+ consume_proc_name;
+ { qualifier is class name ? }
+ if (srsym.typ=typesym) and
+ (ttypesym(srsym).typedef.typ in [objectdef,recorddef]) then
+ begin
+ astruct:=tabstractrecorddef(ttypesym(srsym).typedef);
+ if (token<>_POINT) then
+ if (potype in [potype_class_constructor,potype_class_destructor]) then
+ sp:=lower(sp)
+ else
+ if (potype=potype_operator)and(optoken=NOTOKEN) then
+ parse_operator_name;
+ srsym:=tsym(astruct.symtable.Find(sp));
+ if assigned(srsym) then
+ begin
+ if srsym.typ=procsym then
+ aprocsym:=tprocsym(srsym)
+ else
+ if (srsym.typ=typesym) and
+ (ttypesym(srsym).typedef.typ in [objectdef,recorddef]) then
+ begin
+ searchagain:=true;
+ consume(_POINT);
+ end
+ else
+ begin
+ { we use a different error message for tp7 so it looks more compatible }
+ if (m_fpc in current_settings.modeswitches) then
+ Message1(parser_e_overloaded_no_procedure,srsym.realname)
+ else
+ Message(parser_e_methode_id_expected);
+ { rename the name to an unique name to avoid an
+ error when inserting the symbol in the symtable }
+ orgsp:=orgsp+'$'+tostr(current_filepos.line);
+ end;
+ end
+ else
+ begin
+ Message(parser_e_methode_id_expected);
+ { recover by making it a normal procedure instead of method }
+ astruct:=nil;
+ end;
+ end
+ else
+ Message(parser_e_class_id_expected);
+ until not searchagain;
+ end
+ else
+ begin
+ { check for constructor/destructor/class operators which are not allowed here }
+ if (not parse_only) and
+ ((potype in [potype_constructor,potype_destructor,
+ potype_class_constructor,potype_class_destructor]) or
+ ((potype=potype_operator) and (m_delphi in current_settings.modeswitches))) then
+ Message(parser_e_only_methods_allowed);
+
+ repeat
+ searchagain:=false;
+ current_tokenpos:=procstartfilepos;
+
+ if (potype=potype_operator)and(optoken=NOTOKEN) then
+ parse_operator_name;
+
+ srsym:=tsym(symtablestack.top.Find(sp));
+
+ { Also look in the globalsymtable if we didn't found
+ the symbol in the localsymtable }
+ if not assigned(srsym) and
+ not(parse_only) and
+ (symtablestack.top=current_module.localsymtable) and
+ assigned(current_module.globalsymtable) then
+ srsym:=tsym(current_module.globalsymtable.Find(sp));
+
+ { Check if overloaded is a procsym }
+ if assigned(srsym) then
+ begin
+ if srsym.typ=procsym then
+ aprocsym:=tprocsym(srsym)
+ else
+ begin
+ { when the other symbol is a unit symbol then hide the unit
+ symbol, this is not supported in tp7 }
+ if not(m_tp7 in current_settings.modeswitches) and
+ (srsym.typ=unitsym) then
+ begin
+ HideSym(srsym);
+ searchagain:=true;
+ end
+ else
+ begin
+ { we use a different error message for tp7 so it looks more compatible }
+ if (m_fpc in current_settings.modeswitches) then
+ Message1(parser_e_overloaded_no_procedure,srsym.realname)
+ else
+ Message1(sym_e_duplicate_id,srsym.realname);
+ { rename the name to an unique name to avoid an
+ error when inserting the symbol in the symtable }
+ orgsp:=orgsp+'$'+tostr(current_filepos.line);
+ end;
+ end;
+ end;
+ until not searchagain;
+ end;
+
+ { test again if assigned, it can be reset to recover }
+ if not assigned(aprocsym) then
+ begin
+ { create a new procsym and set the real filepos }
+ current_tokenpos:=procstartfilepos;
+ { for operator we have only one procsym for each overloaded
+ operation }
+ if (potype=potype_operator) then
+ begin
+ aprocsym:=Tprocsym(symtablestack.top.Find(sp));
+ if aprocsym=nil then
+ aprocsym:=tprocsym.create('$'+sp);
+ end
+ else
+ if (potype in [potype_class_constructor,potype_class_destructor]) then
+ aprocsym:=tprocsym.create('$'+lower(sp))
+ else
+ aprocsym:=tprocsym.create(orgsp);
+ symtablestack.top.insert(aprocsym);
+ end;
+
+ { to get the correct symtablelevel we must ignore ObjectSymtables }
+ st:=nil;
+ checkstack:=symtablestack.stack;
+ while assigned(checkstack) do
+ begin
+ st:=checkstack^.symtable;
+ if st.symtabletype in [staticsymtable,globalsymtable,localsymtable] then
+ break;
+ checkstack:=checkstack^.next;
+ end;
+ pd:=tprocdef.create(st.symtablelevel+1);
+ pd.struct:=astruct;
+ pd.procsym:=aprocsym;
+ pd.proctypeoption:=potype;
+
+ { methods inherit df_generic or df_specialization from the objectdef }
+ if assigned(pd.struct) and
+ (pd.parast.symtablelevel=normal_function_level) then
+ begin
+ if (df_generic in pd.struct.defoptions) then
+ begin
+ include(pd.defoptions,df_generic);
+ parse_generic:=true;
+ end;
+ if (df_specialization in pd.struct.defoptions) then
+ begin
+ include(pd.defoptions,df_specialization);
+ { Find corresponding genericdef, we need it later to
+ replay the tokens to generate the body }
+ if not assigned(pd.struct.genericdef) then
+ internalerror(200512113);
+ genericst:=pd.struct.genericdef.GetSymtable(gs_record);
+ if not assigned(genericst) then
+ internalerror(200512114);
+ { We are parsing the same objectdef, the def index numbers
+ are the same }
+ pd.genericdef:=tstoreddef(genericst.DefList[pd.owner.DefList.IndexOf(pd)]);
+ if not assigned(pd.genericdef) or
+ (pd.genericdef.typ<>procdef) then
+ internalerror(200512115);
+ end;
+ end;
+
+ { methods need to be exported }
+ if assigned(astruct) and
+ (
+ (symtablestack.top.symtabletype in [ObjectSymtable,recordsymtable]) or
+ (symtablestack.top.symtablelevel=main_program_level)
+ ) then
+ include(pd.procoptions,po_global);
+
+ { symbol options that need to be kept per procdef }
+ pd.fileinfo:=procstartfilepos;
+ pd.visibility:=symtablestack.top.currentvisibility;
+ if symtablestack.top.currentlyoptional then
+ include(pd.procoptions,po_optional);
+
+ { parse parameters }
+ if token=_LKLAMMER then
+ begin
+ { Add ObjectSymtable to be able to find nested type definitions }
+ popclass:=0;
+ if assigned(pd.struct) and
+ (pd.parast.symtablelevel>=normal_function_level) and
+ not(symtablestack.top.symtabletype in [ObjectSymtable,recordsymtable]) then
+ begin
+ popclass:=push_nested_hierarchy(pd.struct);
+ old_current_structdef:=current_structdef;
+ old_current_genericdef:=current_genericdef;
+ old_current_specializedef:=current_specializedef;
+ current_structdef:=pd.struct;
+ if assigned(current_structdef) and (df_generic in current_structdef.defoptions) then
+ current_genericdef:=current_structdef;
+ if assigned(current_structdef) and (df_specialization in current_structdef.defoptions) then
+ current_specializedef:=current_structdef;
+ end;
+ { Add parameter symtable }
+ if pd.parast.symtabletype<>staticsymtable then
+ symtablestack.push(pd.parast);
+ parse_parameter_dec(pd);
+ if pd.parast.symtabletype<>staticsymtable then
+ symtablestack.pop(pd.parast);
+ if popclass>0 then
+ begin
+ current_structdef:=old_current_structdef;
+ current_genericdef:=old_current_genericdef;
+ current_specializedef:=old_current_specializedef;
+ dec(popclass,pop_nested_hierarchy(pd.struct));
+ if popclass<>0 then
+ internalerror(201011260); // 11 nov 2010 index 0
+ end;
+ end;
+
+ parse_generic:=old_parse_generic;
+ result:=true;
+ end;
+
+
+ function parse_proc_dec(isclassmethod:boolean;astruct:tabstractrecorddef):tprocdef;
+ var
+ pd: tprocdef;
+ locationstr: string;
+ i: integer;
+ found: boolean;
+
+ procedure read_returndef(pd: tprocdef);
+ var
+ popclass: integer;
+ old_parse_generic: boolean;
+ old_current_structdef: tabstractrecorddef;
+ old_current_genericdef,
+ old_current_specializedef: tstoreddef;
+ begin
+ old_parse_generic:=parse_generic;
+ { Add ObjectSymtable to be able to find generic type definitions }
+ popclass:=0;
+ if assigned(pd.struct) and
+ (pd.parast.symtablelevel>=normal_function_level) and
+ not (symtablestack.top.symtabletype in [ObjectSymtable,recordsymtable]) then
+ begin
+ popclass:=push_nested_hierarchy(pd.struct);
+ parse_generic:=(df_generic in pd.struct.defoptions);
+ old_current_structdef:=current_structdef;
+ old_current_genericdef:=current_genericdef;
+ old_current_specializedef:=current_specializedef;
+ current_structdef:=pd.struct;
+ if assigned(current_structdef) and (df_generic in current_structdef.defoptions) then
+ current_genericdef:=current_structdef;
+ if assigned(current_structdef) and (df_specialization in current_structdef.defoptions) then
+ current_specializedef:=current_structdef;
+ end;
+ single_type(pd.returndef,[stoAllowSpecialization]);
+
+ if is_dispinterface(pd.struct) and not is_automatable(pd.returndef) then
+ Message1(type_e_not_automatable,pd.returndef.typename);
+
+ if popclass>0 then
+ begin
+ current_structdef:=old_current_structdef;
+ current_genericdef:=old_current_genericdef;
+ current_specializedef:=old_current_specializedef;
+ dec(popclass,pop_nested_hierarchy(pd.struct));
+ if popclass<>0 then
+ internalerror(201012020);
+ end;
+ parse_generic:=old_parse_generic;
+ end;
+
+ begin
+ locationstr:='';
+ pd:=nil;
+ case token of
+ _FUNCTION :
+ begin
+ consume(_FUNCTION);
+ if parse_proc_head(astruct,potype_function,pd) then
+ begin
+ { pd=nil when it is a interface mapping }
+ if assigned(pd) then
+ begin
+ if try_to_consume(_COLON) then
+ begin
+ read_returndef(pd);
+ if (target_info.system in [system_m68k_amiga]) then
+ begin
+ if (idtoken=_LOCATION) then
+ begin
+ if po_explicitparaloc in pd.procoptions then
+ begin
+ consume(_LOCATION);
+ locationstr:=cstringpattern;
+ consume(_CSTRING);
+ end
+ else
+ { I guess this needs a new message... (KB) }
+ Message(parser_e_paraloc_all_paras);
+ end
+ else
+ begin
+ if po_explicitparaloc in pd.procoptions then
+ { assign default locationstr, if none specified }
+ { and we've arguments with explicit paraloc }
+ locationstr:='D0';
+ end;
+ end;
+
+ end
+ else
+ begin
+ if (
+ parse_only and
+ not(is_interface(pd.struct))
+ ) or
+ (m_repeat_forward in current_settings.modeswitches) then
+ begin
+ consume(_COLON);
+ consume_all_until(_SEMICOLON);
+ end;
+ end;
+ if isclassmethod then
+ include(pd.procoptions,po_classmethod);
+ end;
+ end
+ else
+ begin
+ { recover }
+ consume(_COLON);
+ consume_all_until(_SEMICOLON);
+ end;
+ end;
+
+ _PROCEDURE :
+ begin
+ consume(_PROCEDURE);
+ if parse_proc_head(astruct,potype_procedure,pd) then
+ begin
+ { pd=nil when it is an interface mapping }
+ if assigned(pd) then
+ begin
+ pd.returndef:=voidtype;
+ if isclassmethod then
+ include(pd.procoptions,po_classmethod);
+ end;
+ end;
+ end;
+
+ _CONSTRUCTOR :
+ begin
+ consume(_CONSTRUCTOR);
+ if isclassmethod then
+ parse_proc_head(astruct,potype_class_constructor,pd)
+ else
+ parse_proc_head(astruct,potype_constructor,pd);
+ if not isclassmethod and
+ assigned(pd) and
+ assigned(pd.struct) then
+ begin
+ { Set return type, class constructors return the
+ created instance, object constructors return boolean }
+ if is_class(pd.struct) or is_record(pd.struct) then
+ pd.returndef:=pd.struct
+ else
+{$ifdef CPU64bitaddr}
+ pd.returndef:=bool64type;
+{$else CPU64bitaddr}
+ pd.returndef:=bool32type;
+{$endif CPU64bitaddr}
+ end
+ else
+ pd.returndef:=voidtype;
+ end;
+
+ _DESTRUCTOR :
+ begin
+ consume(_DESTRUCTOR);
+ if isclassmethod then
+ parse_proc_head(astruct,potype_class_destructor,pd)
+ else
+ parse_proc_head(astruct,potype_destructor,pd);
+ if assigned(pd) then
+ pd.returndef:=voidtype;
+ end;
+ else
+ if (token=_OPERATOR) or
+ (isclassmethod and (idtoken=_OPERATOR)) then
+ begin
+ consume(_OPERATOR);
+ parse_proc_head(astruct,potype_operator,pd);
+ if assigned(pd) then
+ begin
+ { operators always need to be searched in all units }
+ include(pd.procoptions,po_overload);
+ if pd.parast.symtablelevel>normal_function_level then
+ Message(parser_e_no_local_operator);
+ if isclassmethod then
+ include(pd.procoptions,po_classmethod);
+ if token<>_ID then
+ begin
+ if not(m_result in current_settings.modeswitches) then
+ consume(_ID);
+ end
+ else
+ begin
+ pd.resultname:=stringdup(orgpattern);
+ consume(_ID);
+ end;
+ if not try_to_consume(_COLON) then
+ begin
+ consume(_COLON);
+ pd.returndef:=generrordef;
+ consume_all_until(_SEMICOLON);
+ end
+ else
+ begin
+ read_returndef(pd);
+ { check that class operators have either return type of structure or }
+ { at least one argument of that type }
+ if (po_classmethod in pd.procoptions) and
+ (pd.returndef <> pd.struct) then
+ begin
+ found:=false;
+ for i := 0 to pd.parast.SymList.Count - 1 do
+ if tparavarsym(pd.parast.SymList[i]).vardef=pd.struct then
+ begin
+ found:=true;
+ break;
+ end;
+ if not found then
+ if assigned(pd.struct) then
+ Message1(parser_e_at_least_one_argument_must_be_of_type,pd.struct.RttiName)
+ else
+ MessagePos(pd.fileinfo,type_e_type_id_expected);
+ end;
+ if (optoken in [_EQ,_NE,_GT,_LT,_GTE,_LTE,_OP_IN]) and
+ ((pd.returndef.typ<>orddef) or
+ (torddef(pd.returndef).ordtype<>pasbool8)) then
+ Message(parser_e_comparative_operator_return_boolean);
+ if (optoken in [_ASSIGNMENT,_OP_EXPLICIT]) and
+ equal_defs(pd.returndef,tparavarsym(pd.parast.SymList[0]).vardef) and
+ (pd.returndef.typ<>undefineddef) and (tparavarsym(pd.parast.SymList[0]).vardef.typ<>undefineddef) then
+ message(parser_e_no_such_assignment)
+ else if not isoperatoracceptable(pd,optoken) then
+ Message(parser_e_overload_impossible);
+ end;
+ end
+ else
+ begin
+ { recover }
+ try_to_consume(_ID);
+ consume(_COLON);
+ consume_all_until(_SEMICOLON);
+ end;
+ end;
+ end;
+ { file types can't be function results }
+ if assigned(pd) and
+ (pd.returndef.typ=filedef) then
+ message(parser_e_illegal_function_result);
+ { support procedure proc stdcall export; }
+ if not(check_proc_directive(false)) then
+ begin
+ if (token=_COLON) then
+ begin
+ message(parser_e_field_not_allowed_here);
+ consume_all_until(_SEMICOLON);
+ end;
+ consume(_SEMICOLON);
+ end;
+ result:=pd;
+
+ if locationstr<>'' then
+ begin
+ if not(paramanager.parsefuncretloc(pd,upper(locationstr))) then
+ { I guess this needs a new message... (KB) }
+ message(parser_e_illegal_explicit_paraloc);
+ end;
+ end;
+
+
+{****************************************************************************
+ Procedure directive handlers
+****************************************************************************}
+
+procedure pd_far(pd:tabstractprocdef);
+begin
+ Message1(parser_w_proc_directive_ignored,'FAR');
+end;
+
+procedure pd_near(pd:tabstractprocdef);
+begin
+ Message1(parser_w_proc_directive_ignored,'NEAR');
+end;
+
+procedure pd_export(pd:tabstractprocdef);
+begin
+ if pd.typ<>procdef then
+ internalerror(200304264);
+ if assigned(tprocdef(pd).struct) then
+ Message(parser_e_methods_dont_be_export);
+ if pd.parast.symtablelevel>normal_function_level then
+ Message(parser_e_dont_nest_export);
+end;
+
+procedure pd_forward(pd:tabstractprocdef);
+begin
+ if pd.typ<>procdef then
+ internalerror(200304265);
+ tprocdef(pd).forwarddef:=true;
+end;
+
+
+procedure pd_alias(pd:tabstractprocdef);
+begin
+ if pd.typ<>procdef then
+ internalerror(200304266);
+ consume(_COLON);
+ tprocdef(pd).aliasnames.insert(get_stringconst);
+ include(pd.procoptions,po_has_public_name);
+end;
+
+
+procedure pd_public(pd:tabstractprocdef);
+begin
+ if pd.typ<>procdef then
+ internalerror(200304266);
+ if try_to_consume(_NAME) then
+ begin
+ tprocdef(pd).aliasnames.insert(get_stringconst);
+ include(pd.procoptions,po_has_public_name);
+ end;
+end;
+
+
+procedure pd_asmname(pd:tabstractprocdef);
+begin
+ if pd.typ<>procdef then
+ internalerror(200304267);
+ if token=_CCHAR then
+ begin
+ tprocdef(pd).aliasnames.insert(target_info.Cprefix+pattern);
+ consume(_CCHAR)
+ end
+ else
+ begin
+ tprocdef(pd).aliasnames.insert(target_info.Cprefix+cstringpattern);
+ consume(_CSTRING);
+ end;
+ { we don't need anything else }
+ tprocdef(pd).forwarddef:=false;
+end;
+
+
+procedure pd_internconst(pd:tabstractprocdef);
+
+var v:Tconstexprint;
+
+begin
+ if pd.typ<>procdef then
+ internalerror(200304268);
+ consume(_COLON);
+ v:=get_intconst;
+ if (v<int64(low(longint))) or (v>int64(high(longint))) then
+ message(parser_e_range_check_error)
+ else
+ Tprocdef(pd).extnumber:=longint(v.svalue);
+end;
+
+
+procedure pd_internproc(pd:tabstractprocdef);
+
+var v:Tconstexprint;
+
+begin
+ if pd.typ<>procdef then
+ internalerror(200304268);
+ consume(_COLON);
+ v:=get_intconst;
+ if (v<int64(low(longint))) or (v>int64(high(longint))) then
+ message(parser_e_range_check_error)
+ else
+ Tprocdef(pd).extnumber:=longint(v.svalue);
+ { the proc is defined }
+ tprocdef(pd).forwarddef:=false;
+end;
+
+procedure pd_interrupt(pd:tabstractprocdef);
+
+{$ifdef FPC_HAS_SYSTEMS_INTERRUPT_TABLE}
+var v: Tconstexprint;
+{$endif FPC_HAS_SYSTEMS_INTERRUPT_TABLE}
+
+begin
+ if pd.parast.symtablelevel>normal_function_level then
+ Message(parser_e_dont_nest_interrupt);
+
+{$ifdef FPC_HAS_SYSTEMS_INTERRUPT_TABLE}
+ if target_info.system in systems_interrupt_table then
+ begin
+ if token<>_SEMICOLON then
+ begin
+ pd.proccalloption:=pocall_interrupt;
+ v:=get_intconst;
+ Tprocdef(pd).interruptvector:=v.uvalue;
+ end;
+ end;
+{$endif FPC_HAS_SYSTEMS_INTERRUPT_TABLE}
+end;
+
+procedure pd_abstract(pd:tabstractprocdef);
+begin
+ if pd.typ<>procdef then
+ internalerror(200304269);
+ if is_objectpascal_helper(tprocdef(pd).struct) then
+ Message1(parser_e_not_allowed_in_helper, arraytokeninfo[_ABSTRACT].str);
+ if assigned(tprocdef(pd).struct) and
+ (oo_is_sealed in tprocdef(pd).struct.objectoptions) then
+ Message(parser_e_sealed_class_cannot_have_abstract_methods)
+ else
+ if (po_virtualmethod in pd.procoptions) then
+ include(pd.procoptions,po_abstractmethod)
+ else
+ Message(parser_e_only_virtual_methods_abstract);
+ { the method is defined }
+ tprocdef(pd).forwarddef:=false;
+end;
+
+procedure pd_final(pd:tabstractprocdef);
+begin
+ if pd.typ<>procdef then
+ internalerror(200910170);
+ if is_objectpascal_helper(tprocdef(pd).struct) and
+ (m_objfpc in current_settings.modeswitches) then
+ Message1(parser_e_not_allowed_in_helper, arraytokeninfo[_FINAL].str);
+ if (po_virtualmethod in pd.procoptions) then
+ include(pd.procoptions,po_finalmethod)
+ else
+ Message(parser_e_only_virtual_methods_final);
+end;
+
+procedure pd_enumerator(pd:tabstractprocdef);
+begin
+ if pd.typ<>procdef then
+ internalerror(200910250);
+ if (token = _ID) then
+ begin
+ if pattern='MOVENEXT' then
+ begin
+ if oo_has_enumerator_movenext in tprocdef(pd).struct.objectoptions then
+ message(parser_e_only_one_enumerator_movenext);
+ pd.calcparas;
+ if (pd.proctypeoption = potype_function) and is_boolean(pd.returndef) and
+ (pd.minparacount = 0) then
+ begin
+ include(tprocdef(pd).struct.objectoptions, oo_has_enumerator_movenext);
+ include(pd.procoptions,po_enumerator_movenext);
+ end
+ else
+ Message(parser_e_enumerator_movenext_is_not_valid)
+ end
+ else
+ Message1(parser_e_invalid_enumerator_identifier, pattern);
+ consume(token);
+ end
+ else
+ Message(parser_e_enumerator_identifier_required);
+end;
+
+procedure pd_virtual(pd:tabstractprocdef);
+{$ifdef WITHDMT}
+var
+ pt : tnode;
+{$endif WITHDMT}
+begin
+ if pd.typ<>procdef then
+ internalerror(2003042610);
+ if (pd.proctypeoption=potype_constructor) and
+ is_object(tprocdef(pd).struct) then
+ Message(parser_e_constructor_cannot_be_not_virtual);
+ if is_objectpascal_helper(tprocdef(pd).struct) and
+ (m_objfpc in current_settings.modeswitches) then
+ Message1(parser_e_not_allowed_in_helper, arraytokeninfo[_VIRTUAL].str);
+{$ifdef WITHDMT}
+ if is_object(tprocdef(pd).struct) and
+ (token<>_SEMICOLON) then
+ begin
+ { any type of parameter is allowed here! }
+ pt:=comp_expr(true);
+ if is_constintnode(pt) then
+ begin
+ include(pd.procoptions,po_msgint);
+ pd.messageinf.i:=pt.value;
+ end
+ else
+ Message(parser_e_ill_msg_expr);
+ disposetree(pt);
+ end;
+{$endif WITHDMT}
+end;
+
+
+procedure pd_dispid(pd:tabstractprocdef);
+
+var pt:Tnode;
+
+begin
+ if pd.typ<>procdef then
+ internalerror(200604301);
+ pt:=comp_expr(true,false);
+ if is_constintnode(pt) then
+ if (Tordconstnode(pt).value<int64(low(longint))) or (Tordconstnode(pt).value>int64(high(longint))) then
+ message(parser_e_range_check_error)
+ else
+ Tprocdef(pd).dispid:=Tordconstnode(pt).value.svalue
+ else
+ message(parser_e_dispid_must_be_ord_const);
+ pt.free;
+end;
+
+
+procedure pd_static(pd:tabstractprocdef);
+begin
+ if pd.typ=procdef then
+ include(tprocdef(pd).procsym.symoptions,sp_static);
+ include(pd.procoptions,po_staticmethod);
+end;
+
+procedure pd_override(pd:tabstractprocdef);
+begin
+ if pd.typ<>procdef then
+ internalerror(2003042611);
+ if is_objectpascal_helper(tprocdef(pd).struct) then
+ begin
+ if m_objfpc in current_settings.modeswitches then
+ Message1(parser_e_not_allowed_in_helper, arraytokeninfo[_OVERRIDE].str)
+ end
+ else if not(is_class_or_interface_or_objc(tprocdef(pd).struct)) then
+ Message(parser_e_no_object_override)
+ else if is_objccategory(tprocdef(pd).struct) then
+ Message(parser_e_no_category_override)
+ else if not is_objc_class_or_protocol(tprocdef(pd).struct) and
+ not is_cppclass(tprocdef(pd).struct) and
+ (po_external in pd.procoptions) then
+ Message1(parser_e_proc_dir_conflict,'OVERRIDE');
+end;
+
+procedure pd_overload(pd:tabstractprocdef);
+begin
+ if pd.typ<>procdef then
+ internalerror(2003042612);
+ include(tprocdef(pd).procsym.symoptions,sp_has_overloaded);
+end;
+
+procedure pd_message(pd:tabstractprocdef);
+var
+ pt : tnode;
+ paracnt : longint;
+begin
+ if pd.typ<>procdef then
+ internalerror(2003042613);
+ if is_objectpascal_helper(tprocdef(pd).struct) then
+ begin
+ if m_objfpc in current_settings.modeswitches then
+ Message1(parser_e_not_allowed_in_helper, arraytokeninfo[_MESSAGE].str);
+ end
+ else
+ if not is_class(tprocdef(pd).struct) and
+ not is_objc_class_or_protocol(tprocdef(pd).struct) then
+ Message(parser_e_msg_only_for_classes);
+ if ([po_msgstr,po_msgint]*pd.procoptions)<>[] then
+ Message(parser_e_multiple_messages);
+ { check parameter type }
+ if not is_objc_class_or_protocol(tprocdef(pd).struct) then
+ begin
+ if po_external in pd.procoptions then
+ Message1(parser_e_proc_dir_conflict,'MESSAGE');
+ paracnt:=0;
+ pd.parast.SymList.ForEachCall(@check_msg_para,@paracnt);
+ if paracnt<>1 then
+ Message(parser_e_ill_msg_param);
+ end;
+ pt:=comp_expr(true,false);
+ { message is 1-character long }
+ if is_constcharnode(pt) then
+ begin
+ include(pd.procoptions,po_msgstr);
+ tprocdef(pd).messageinf.str:=stringdup(chr(byte(tordconstnode(pt).value.uvalue and $FF)));
+ end
+ else if pt.nodetype=stringconstn then
+ begin
+ include(pd.procoptions,po_msgstr);
+ if (tstringconstnode(pt).len>255) then
+ Message(parser_e_message_string_too_long);
+ tprocdef(pd).messageinf.str:=stringdup(tstringconstnode(pt).value_str);
+ end
+ else
+ if is_constintnode(pt) and
+ (is_class(tprocdef(pd).struct) or
+ is_objectpascal_helper(tprocdef(pd).struct)) then
+ begin
+ include(pd.procoptions,po_msgint);
+ if (Tordconstnode(pt).value<int64(low(Tprocdef(pd).messageinf.i))) or
+ (Tordconstnode(pt).value>int64(high(Tprocdef(pd).messageinf.i))) then
+ message(parser_e_range_check_error)
+ else
+ Tprocdef(pd).messageinf.i:=tordconstnode(pt).value.svalue;
+ end
+ else
+ Message(parser_e_ill_msg_expr);
+ { check whether the selector name is valid in case of Objective-C }
+ if (po_msgstr in pd.procoptions) and
+ is_objc_class_or_protocol(tprocdef(pd).struct) and
+ not objcvalidselectorname(@tprocdef(pd).messageinf.str^[1],length(tprocdef(pd).messageinf.str^)) then
+ Message1(type_e_invalid_objc_selector_name,tprocdef(pd).messageinf.str^);
+ pt.free;
+end;
+
+
+procedure pd_reintroduce(pd:tabstractprocdef);
+begin
+ if pd.typ<>procdef then
+ internalerror(200401211);
+ if is_objectpascal_helper(tprocdef(pd).struct) then
+ begin
+ if m_objfpc in current_settings.modeswitches then
+ Message1(parser_e_not_allowed_in_helper, arraytokeninfo[_REINTRODUCE].str);
+ end
+ else
+ if not(is_class_or_interface_or_object(tprocdef(pd).struct)) and
+ not(is_objccategory(tprocdef(pd).struct)) then
+ Message(parser_e_no_object_reintroduce);
+end;
+
+
+procedure pd_syscall(pd:tabstractprocdef);
+{$if defined(powerpc) or defined(m68k)}
+var
+ vs : tparavarsym;
+ sym : tsym;
+ symtable : TSymtable;
+ v: Tconstexprint;
+{$endif defined(powerpc) or defined(m68k)}
+begin
+ if (pd.typ<>procdef) and (target_info.system <> system_powerpc_amiga) then
+ internalerror(2003042614);
+ tprocdef(pd).forwarddef:=false;
+{$ifdef m68k}
+ if target_info.system in [system_m68k_amiga] then
+ begin
+ include(pd.procoptions,po_syscall_legacy);
+
+ if consume_sym(sym,symtable) then
+ begin
+ if (sym.typ=staticvarsym) and
+ (
+ (tabstractvarsym(sym).vardef.typ=pointerdef) or
+ is_32bitint(tabstractvarsym(sym).vardef)
+ ) then
+ begin
+ tprocdef(pd).libsym:=sym;
+ if po_syscall_legacy in tprocdef(pd).procoptions then
+ begin
+ vs:=tparavarsym.create('$syscalllib',paranr_syscall_legacy,vs_value,tabstractvarsym(sym).vardef,[vo_is_syscall_lib,vo_is_hidden_para,vo_has_explicit_paraloc]);
+ paramanager.parseparaloc(vs,'A6');
+ pd.parast.insert(vs);
+ end
+ end
+ else
+ Message(parser_e_32bitint_or_pointer_variable_expected);
+ end;
+ (paramanager as tm68kparamanager).create_funcretloc_info(pd,calleeside);
+ (paramanager as tm68kparamanager).create_funcretloc_info(pd,callerside);
+
+ v:=get_intconst;
+ if (v<low(Tprocdef(pd).extnumber)) or (v>high(Tprocdef(pd).extnumber)) then
+ message(parser_e_range_check_error)
+ else
+ Tprocdef(pd).extnumber:=v.uvalue;
+ end;
+{$endif m68k}
+{$ifdef powerpc}
+ if target_info.system = system_powerpc_amiga then
+ begin
+ include(pd.procoptions,po_syscall_basesysv);
+
+ if consume_sym(sym,symtable) then
+ begin
+ if (sym.typ=staticvarsym) and
+ (
+ (tabstractvarsym(sym).vardef.typ=pointerdef) or
+ is_32bitint(tabstractvarsym(sym).vardef)
+ ) then
+ begin
+ tprocdef(pd).libsym:=sym;
+ vs:=tparavarsym.create('$syscalllib',paranr_syscall_basesysv,vs_value,tabstractvarsym(sym).vardef,[vo_is_syscall_lib,vo_is_hidden_para]);
+ pd.parast.insert(vs);
+ end
+ else
+ Message(parser_e_32bitint_or_pointer_variable_expected);
+ end;
+
+ (paramanager as tppcparamanager).create_funcretloc_info(pd,calleeside);
+ (paramanager as tppcparamanager).create_funcretloc_info(pd,callerside);
+
+ v:=get_intconst;
+ if (v<low(Tprocdef(pd).extnumber)) or (v>high(Tprocdef(pd).extnumber)) then
+ message(parser_e_range_check_error)
+ else
+ Tprocdef(pd).extnumber:=v.uvalue;
+ end else
+
+ if target_info.system = system_powerpc_morphos then
+ begin
+ if idtoken=_LEGACY then
+ begin
+ consume(_LEGACY);
+ include(pd.procoptions,po_syscall_legacy);
+ end
+ else if idtoken=_SYSV then
+ begin
+ consume(_SYSV);
+ include(pd.procoptions,po_syscall_sysv);
+ end
+ else if idtoken=_BASESYSV then
+ begin
+ consume(_BASESYSV);
+ include(pd.procoptions,po_syscall_basesysv);
+ end
+ else if idtoken=_SYSVBASE then
+ begin
+ consume(_SYSVBASE);
+ include(pd.procoptions,po_syscall_sysvbase);
+ end
+ else if idtoken=_R12BASE then
+ begin
+ consume(_R12BASE);
+ include(pd.procoptions,po_syscall_r12base);
+ end
+ else
+ if syscall_convention='LEGACY' then
+ include(pd.procoptions,po_syscall_legacy)
+ else if syscall_convention='SYSV' then
+ include(pd.procoptions,po_syscall_sysv)
+ else if syscall_convention='BASESYSV' then
+ include(pd.procoptions,po_syscall_basesysv)
+ else if syscall_convention='SYSVBASE' then
+ include(pd.procoptions,po_syscall_sysvbase)
+ else if syscall_convention='R12BASE' then
+ include(pd.procoptions,po_syscall_r12base)
+ else
+ internalerror(2005010404);
+
+ if consume_sym(sym,symtable) then
+ begin
+ if (sym.typ=staticvarsym) and
+ (
+ (tabstractvarsym(sym).vardef.typ=pointerdef) or
+ is_32bitint(tabstractvarsym(sym).vardef)
+ ) then
+ begin
+ tprocdef(pd).libsym:=sym;
+ if po_syscall_legacy in tprocdef(pd).procoptions then
+ begin
+ vs:=tparavarsym.create('$syscalllib',paranr_syscall_legacy,vs_value,tabstractvarsym(sym).vardef,[vo_is_syscall_lib,vo_is_hidden_para,vo_has_explicit_paraloc]);
+ paramanager.parseparaloc(vs,'A6');
+ pd.parast.insert(vs);
+ end
+ else if po_syscall_sysv in tprocdef(pd).procoptions then
+ begin
+ { Nothing to be done for sysv here for now, but this might change }
+ end
+ else if po_syscall_basesysv in tprocdef(pd).procoptions then
+ begin
+ vs:=tparavarsym.create('$syscalllib',paranr_syscall_basesysv,vs_value,tabstractvarsym(sym).vardef,[vo_is_syscall_lib,vo_is_hidden_para]);
+ pd.parast.insert(vs);
+ end
+ else if po_syscall_sysvbase in tprocdef(pd).procoptions then
+ begin
+ vs:=tparavarsym.create('$syscalllib',paranr_syscall_sysvbase,vs_value,tabstractvarsym(sym).vardef,[vo_is_syscall_lib,vo_is_hidden_para]);
+ pd.parast.insert(vs);
+ end
+ else if po_syscall_r12base in tprocdef(pd).procoptions then
+ begin
+ vs:=tparavarsym.create('$syscalllib',paranr_syscall_r12base,vs_value,tabstractvarsym(sym).vardef,[vo_is_syscall_lib,vo_is_hidden_para,vo_has_explicit_paraloc]);
+ paramanager.parseparaloc(vs,'R12');
+ pd.parast.insert(vs);
+ end
+ else
+ internalerror(2005010501);
+ end
+ else
+ Message(parser_e_32bitint_or_pointer_variable_expected);
+ end;
+ (paramanager as tppcparamanager).create_funcretloc_info(pd,calleeside);
+ (paramanager as tppcparamanager).create_funcretloc_info(pd,callerside);
+
+ v:=get_intconst;
+ if (v<low(Tprocdef(pd).extnumber)) or (v>high(Tprocdef(pd).extnumber)) then
+ message(parser_e_range_check_error)
+ else
+ Tprocdef(pd).extnumber:=v.uvalue;
+ end;
+{$endif powerpc}
+end;
+
+
+procedure pd_external(pd:tabstractprocdef);
+{
+ If import_dll=nil the procedure is assumed to be in another
+ object file. In that object file it should have the name to
+ which import_name is pointing to. Otherwise, the procedure is
+ assumed to be in the DLL to which import_dll is pointing to. In
+ that case either import_nr<>0 or import_name<>nil is true, so
+ the procedure is either imported by number or by name. (DM)
+}
+var
+ hs : string;
+ v:Tconstexprint;
+
+begin
+ if pd.typ<>procdef then
+ internalerror(2003042615);
+ with tprocdef(pd) do
+ begin
+ forwarddef:=false;
+ { forbid local external procedures }
+ if parast.symtablelevel>normal_function_level then
+ Message(parser_e_no_local_proc_external);
+ { If the procedure should be imported from a DLL, a constant string follows.
+ This isn't really correct, an contant string expression follows
+ so we check if an semicolon follows, else a string constant have to
+ follow (FK) }
+ if not(token=_SEMICOLON) and not(idtoken=_NAME) then
+ begin
+ { Always add library prefix and suffix to create an uniform name }
+ hs:=get_stringconst;
+ if ExtractFileExt(hs)='' then
+ hs:=ChangeFileExt(hs,target_info.sharedlibext);
+ if Copy(hs,1,length(target_info.sharedlibprefix))<>target_info.sharedlibprefix then
+ hs:=target_info.sharedlibprefix+hs;
+ import_dll:=stringdup(hs);
+ include(procoptions,po_has_importdll);
+ if (idtoken=_NAME) then
+ begin
+ consume(_NAME);
+ import_name:=stringdup(get_stringconst);
+ include(procoptions,po_has_importname);
+ if import_name^='' then
+ message(parser_e_empty_import_name);
+ end;
+ if (idtoken=_INDEX) then
+ begin
+ {After the word index follows the index number in the DLL.}
+ consume(_INDEX);
+ v:=get_intconst;
+ if (v<int64(low(import_nr))) or (v>int64(high(import_nr))) then
+ message(parser_e_range_check_error)
+ else
+ import_nr:=longint(v.svalue);
+ end;
+ { default is to used the realname of the procedure }
+ if (import_nr=0) and not assigned(import_name) then
+ begin
+ import_name:=stringdup(procsym.realname);
+ include(procoptions,po_has_importname);
+ end;
+ end
+ else
+ begin
+ if (idtoken=_NAME) then
+ begin
+ consume(_NAME);
+ import_name:=stringdup(get_stringconst);
+ include(procoptions,po_has_importname);
+ if import_name^='' then
+ message(parser_e_empty_import_name);
+ end;
+ end;
+ end;
+end;
+
+
+procedure pd_weakexternal(pd:tabstractprocdef);
+begin
+ if not(target_info.system in systems_weak_linking) then
+ message(parser_e_weak_external_not_supported)
+ else
+ pd_external(pd);
+end;
+
+
+type
+ pd_handler=procedure(pd:tabstractprocdef);
+ proc_dir_rec=record
+ idtok : ttoken;
+ pd_flags : tpdflags;
+ handler : pd_handler;
+ pocall : tproccalloption;
+ pooption : tprocoptions;
+ mutexclpocall : tproccalloptions;
+ mutexclpotype : tproctypeoptions;
+ mutexclpo : tprocoptions;
+ end;
+const
+ {Should contain the number of procedure directives we support.}
+ num_proc_directives=43;
+ proc_direcdata:array[1..num_proc_directives] of proc_dir_rec=
+ (
+ (
+ idtok:_ABSTRACT;
+ pd_flags : [pd_interface,pd_object,pd_notobjintf,pd_notrecord];
+ handler : @pd_abstract;
+ pocall : pocall_none;
+ pooption : [po_abstractmethod];
+ mutexclpocall : [pocall_internproc];
+ mutexclpotype : [];
+ mutexclpo : [po_exports,po_interrupt,po_external,po_inline]
+ ),(
+ idtok:_ALIAS;
+ pd_flags : [pd_implemen,pd_body,pd_notobjintf];
+ handler : @pd_alias;
+ pocall : pocall_none;
+ pooption : [];
+ mutexclpocall : [];
+ mutexclpotype : [];
+ mutexclpo : [po_external,po_inline]
+ ),(
+ idtok:_ASMNAME;
+ pd_flags : [pd_interface,pd_implemen,pd_notobjintf];
+ handler : @pd_asmname;
+ pocall : pocall_cdecl;
+ pooption : [po_external];
+ mutexclpocall : [pocall_internproc];
+ mutexclpotype : [];
+ mutexclpo : [po_external,po_inline]
+ ),(
+ idtok:_ASSEMBLER;
+ pd_flags : [pd_interface,pd_implemen,pd_body,pd_notobjintf];
+ handler : nil;
+ pocall : pocall_none;
+ pooption : [po_assembler];
+ mutexclpocall : [];
+ mutexclpotype : [];
+ mutexclpo : [po_external]
+ ),(
+ idtok:_C; {same as cdecl for mode mac}
+ pd_flags : [pd_interface,pd_implemen,pd_body,pd_procvar];
+ handler : nil;
+ pocall : pocall_cdecl;
+ pooption : [];
+ mutexclpocall : [];
+ mutexclpotype : [potype_constructor,potype_destructor,potype_class_constructor,potype_class_destructor];
+ mutexclpo : [po_assembler,po_external]
+ ),(
+ idtok:_CDECL;
+ pd_flags : [pd_interface,pd_implemen,pd_body,pd_procvar];
+ handler : nil;
+ pocall : pocall_cdecl;
+ pooption : [];
+ mutexclpocall : [];
+ mutexclpotype : [potype_constructor,potype_destructor,potype_class_constructor,potype_class_destructor];
+ mutexclpo : [po_assembler,po_external]
+ ),(
+ idtok:_DISPID;
+ pd_flags : [pd_dispinterface];
+ handler : @pd_dispid;
+ pocall : pocall_none;
+ pooption : [po_dispid];
+ mutexclpocall : [pocall_internproc];
+ mutexclpotype : [potype_constructor,potype_destructor,potype_operator,potype_class_constructor,potype_class_destructor];
+ mutexclpo : [po_interrupt,po_external,po_inline]
+ ),(
+ idtok:_DYNAMIC;
+ pd_flags : [pd_interface,pd_object,pd_notobjintf,pd_notrecord];
+ handler : @pd_virtual;
+ pocall : pocall_none;
+ pooption : [po_virtualmethod];
+ mutexclpocall : [pocall_internproc];
+ mutexclpotype : [potype_class_constructor,potype_class_destructor];
+ mutexclpo : [po_exports,po_interrupt,po_external,po_overridingmethod,po_inline]
+ ),(
+ idtok:_EXPORT;
+ pd_flags : [pd_body,pd_interface,pd_implemen,pd_notobjintf,pd_notrecord,pd_nothelper];
+ handler : @pd_export;
+ pocall : pocall_none;
+ pooption : [po_exports,po_global];
+ mutexclpocall : [pocall_internproc];
+ mutexclpotype : [potype_constructor,potype_destructor,potype_class_constructor,potype_class_destructor];
+ mutexclpo : [po_external,po_interrupt,po_inline]
+ ),(
+ idtok:_EXTERNAL;
+ pd_flags : [pd_implemen,pd_interface,pd_notobject,pd_notobjintf,pd_cppobject,pd_notrecord,pd_nothelper];
+ handler : @pd_external;
+ pocall : pocall_none;
+ pooption : [po_external];
+ mutexclpocall : [pocall_internproc,pocall_syscall];
+ { allowed for external cpp classes }
+ mutexclpotype : [{potype_constructor,potype_destructor}potype_class_constructor,potype_class_destructor];
+ mutexclpo : [po_public,po_exports,po_interrupt,po_assembler,po_inline]
+ ),(
+ idtok:_FAR;
+ pd_flags : [pd_implemen,pd_body,pd_interface,pd_procvar,pd_notobject,pd_notobjintf,pd_notrecord,pd_nothelper];
+ handler : @pd_far;
+ pocall : pocall_none;
+ pooption : [];
+ mutexclpocall : [pocall_internproc];
+ mutexclpotype : [];
+ mutexclpo : [po_inline]
+ ),(
+ idtok:_FAR16;
+ pd_flags : [pd_interface,pd_implemen,pd_body,pd_procvar,pd_notobject,pd_notrecord,pd_nothelper];
+ handler : nil;
+ pocall : pocall_far16;
+ pooption : [];
+ mutexclpocall : [];
+ mutexclpotype : [];
+ mutexclpo : [po_external]
+ ),(
+ idtok:_FINAL;
+ pd_flags : [pd_interface,pd_object,pd_notobjintf,pd_notrecord];
+ handler : @pd_final;
+ pocall : pocall_none;
+ pooption : [po_finalmethod];
+ mutexclpocall : [pocall_internproc];
+ mutexclpotype : [];
+ mutexclpo : [po_exports,po_interrupt,po_external,po_inline]
+ ),(
+ idtok:_FORWARD;
+ pd_flags : [pd_implemen,pd_notobject,pd_notobjintf,pd_notrecord,pd_nothelper];
+ handler : @pd_forward;
+ pocall : pocall_none;
+ pooption : [];
+ mutexclpocall : [pocall_internproc];
+ mutexclpotype : [];
+ mutexclpo : [po_external,po_inline]
+ ),(
+ idtok:_OLDFPCCALL;
+ pd_flags : [pd_interface,pd_implemen,pd_body,pd_procvar];
+ handler : nil;
+ pocall : pocall_oldfpccall;
+ pooption : [];
+ mutexclpocall : [];
+ mutexclpotype : [];
+ mutexclpo : []
+ ),(
+ idtok:_INLINE;
+ pd_flags : [pd_interface,pd_implemen,pd_body,pd_notobjintf];
+ handler : nil;
+ pocall : pocall_none;
+ pooption : [po_inline];
+ mutexclpocall : [];
+ mutexclpotype : [potype_constructor,potype_destructor,potype_class_constructor,potype_class_destructor];
+ mutexclpo : [po_exports,po_external,po_interrupt,po_virtualmethod]
+ ),(
+ idtok:_INTERNCONST;
+ pd_flags : [pd_interface,pd_body,pd_notobject,pd_notobjintf,pd_notrecord,pd_nothelper];
+ handler : @pd_internconst;
+ pocall : pocall_none;
+ pooption : [po_internconst];
+ mutexclpocall : [];
+ mutexclpotype : [potype_operator];
+ mutexclpo : []
+ ),(
+ idtok:_INTERNPROC;
+ pd_flags : [pd_interface,pd_notobject,pd_notobjintf,pd_notrecord,pd_nothelper];
+ handler : @pd_internproc;
+ pocall : pocall_internproc;
+ pooption : [];
+ mutexclpocall : [];
+ mutexclpotype : [potype_constructor,potype_destructor,potype_operator,potype_class_constructor,potype_class_destructor];
+ mutexclpo : [po_exports,po_external,po_interrupt,po_assembler,po_iocheck,po_virtualmethod]
+ ),(
+ idtok:_INTERRUPT;
+ pd_flags : [pd_implemen,pd_body,pd_notobject,pd_notobjintf,pd_notrecord,pd_nothelper];
+ handler : @pd_interrupt;
+ pocall : pocall_oldfpccall;
+ pooption : [po_interrupt];
+ mutexclpocall : [pocall_internproc,pocall_cdecl,pocall_cppdecl,pocall_stdcall,
+ pocall_pascal,pocall_far16,pocall_oldfpccall];
+ mutexclpotype : [potype_constructor,potype_destructor,potype_operator,potype_class_constructor,potype_class_destructor];
+ mutexclpo : [po_external,po_inline]
+ ),(
+ idtok:_IOCHECK;
+ pd_flags : [pd_implemen,pd_body,pd_notobjintf];
+ handler : nil;
+ pocall : pocall_none;
+ pooption : [po_iocheck];
+ mutexclpocall : [pocall_internproc];
+ mutexclpotype : [];
+ mutexclpo : [po_external]
+ ),(
+ idtok:_LOCAL;
+ pd_flags : [pd_implemen,pd_body];
+ handler : nil;
+ pocall : pocall_none;
+ pooption : [po_kylixlocal];
+ mutexclpocall : [pocall_internproc,pocall_far16];
+ mutexclpotype : [];
+ mutexclpo : [po_external,po_exports]
+ ),(
+ idtok:_MESSAGE;
+ pd_flags : [pd_interface,pd_object,pd_notobjintf,pd_objcclass,pd_objcprot,pd_notrecord];
+ handler : @pd_message;
+ pocall : pocall_none;
+ pooption : []; { can be po_msgstr or po_msgint }
+ mutexclpocall : [pocall_internproc];
+ mutexclpotype : [potype_constructor,potype_destructor,potype_operator,potype_class_constructor,potype_class_destructor];
+ mutexclpo : [po_interrupt,po_inline]
+ ),(
+ idtok:_MWPASCAL;
+ pd_flags : [pd_interface,pd_implemen,pd_body,pd_procvar];
+ handler : nil;
+ pocall : pocall_mwpascal;
+ pooption : [];
+ mutexclpocall : [];
+ mutexclpotype : [];
+ mutexclpo : []
+ ),(
+ idtok:_NEAR;
+ pd_flags : [pd_implemen,pd_body,pd_procvar,pd_notobjintf,pd_notrecord,pd_nothelper];
+ handler : @pd_near;
+ pocall : pocall_none;
+ pooption : [];
+ mutexclpocall : [pocall_internproc];
+ mutexclpotype : [];
+ mutexclpo : []
+ ),(
+ idtok:_NOSTACKFRAME;
+ pd_flags : [pd_implemen,pd_body,pd_procvar,pd_notobjintf];
+ handler : nil;
+ pocall : pocall_none;
+ pooption : [po_nostackframe];
+ mutexclpocall : [pocall_internproc];
+ mutexclpotype : [];
+ mutexclpo : []
+ ),(
+ idtok:_OVERLOAD;
+ pd_flags : [pd_implemen,pd_interface,pd_body];
+ handler : @pd_overload;
+ pocall : pocall_none;
+ pooption : [po_overload];
+ mutexclpocall : [pocall_internproc];
+ mutexclpotype : [];
+ mutexclpo : []
+ ),(
+ idtok:_OVERRIDE;
+ pd_flags : [pd_interface,pd_object,pd_notobjintf,pd_objcclass,pd_notrecord];
+ handler : @pd_override;
+ pocall : pocall_none;
+ pooption : [po_overridingmethod,po_virtualmethod];
+ mutexclpocall : [pocall_internproc];
+ mutexclpotype : [];
+ mutexclpo : [po_exports,po_interrupt,po_virtualmethod,po_inline]
+ ),(
+ idtok:_PASCAL;
+ pd_flags : [pd_interface,pd_implemen,pd_body,pd_procvar];
+ handler : nil;
+ pocall : pocall_pascal;
+ pooption : [];
+ mutexclpocall : [];
+ mutexclpotype : [potype_constructor,potype_destructor,potype_class_constructor,potype_class_destructor];
+ mutexclpo : [po_external]
+ ),(
+ idtok:_PUBLIC;
+ pd_flags : [pd_interface,pd_implemen,pd_body,pd_notobject,pd_notobjintf,pd_notrecord,pd_nothelper];
+ handler : @pd_public;
+ pocall : pocall_none;
+ pooption : [po_public,po_global];
+ mutexclpocall : [pocall_internproc];
+ mutexclpotype : [];
+ mutexclpo : [po_external,po_inline]
+ ),(
+ idtok:_REGISTER;
+ pd_flags : [pd_interface,pd_implemen,pd_body,pd_procvar];
+ handler : nil;
+ pocall : pocall_register;
+ pooption : [];
+ mutexclpocall : [];
+ mutexclpotype : [potype_constructor,potype_destructor,potype_class_constructor,potype_class_destructor];
+ mutexclpo : [po_external]
+ ),(
+ idtok:_REINTRODUCE;
+ pd_flags : [pd_interface,pd_object,pd_notobjintf,pd_objcclass,pd_notrecord];
+ handler : @pd_reintroduce;
+ pocall : pocall_none;
+ pooption : [po_reintroduce];
+ mutexclpocall : [pocall_internproc];
+ mutexclpotype : [];
+ mutexclpo : [po_external,po_interrupt,po_exports,po_overridingmethod,po_inline]
+ ),(
+ idtok:_SAFECALL;
+ pd_flags : [pd_interface,pd_implemen,pd_body,pd_procvar];
+ handler : nil;
+ pocall : pocall_safecall;
+ pooption : [];
+ mutexclpocall : [];
+ mutexclpotype : [potype_constructor,potype_destructor,potype_class_constructor,potype_class_destructor];
+ mutexclpo : [po_external]
+ ),(
+ idtok:_SOFTFLOAT;
+ pd_flags : [pd_interface,pd_implemen,pd_body,pd_procvar];
+ handler : nil;
+ pocall : pocall_softfloat;
+ pooption : [];
+ mutexclpocall : [];
+ mutexclpotype : [potype_constructor,potype_destructor,potype_class_constructor,potype_class_destructor];
+ { it's available with po_external because the libgcc floating point routines on the arm
+ uses this calling convention }
+ mutexclpo : []
+ ),(
+ idtok:_STATIC;
+ pd_flags : [pd_interface,pd_implemen,pd_body,pd_object,pd_record,pd_notobjintf];
+ handler : @pd_static;
+ pocall : pocall_none;
+ pooption : [po_staticmethod];
+ mutexclpocall : [pocall_internproc];
+ mutexclpotype : [potype_constructor,potype_destructor,potype_class_constructor,potype_class_destructor];
+ mutexclpo : [po_external,po_interrupt,po_exports]
+ ),(
+ idtok:_STDCALL;
+ pd_flags : [pd_interface,pd_implemen,pd_body,pd_procvar];
+ handler : nil;
+ pocall : pocall_stdcall;
+ pooption : [];
+ mutexclpocall : [];
+ mutexclpotype : [potype_constructor,potype_destructor,potype_class_constructor,potype_class_destructor];
+ mutexclpo : [po_external]
+ ),(
+ idtok:_SYSCALL;
+ { Different kind of syscalls are valid for AOS68k, AOSPPC and MOS. }
+ { FIX ME!!! MorphOS/AOS68k pd_flags should be:
+ pd_interface, pd_implemen, pd_notobject, pd_notobjintf (KB) }
+ pd_flags : [pd_interface,pd_implemen,pd_procvar];
+ handler : @pd_syscall;
+ pocall : pocall_syscall;
+ pooption : [];
+ mutexclpocall : [];
+ mutexclpotype : [potype_constructor,potype_destructor,potype_class_constructor,potype_class_destructor];
+ mutexclpo : [po_external,po_assembler,po_interrupt,po_exports]
+ ),(
+ idtok:_VIRTUAL;
+ pd_flags : [pd_interface,pd_object,pd_notobjintf,pd_notrecord];
+ handler : @pd_virtual;
+ pocall : pocall_none;
+ pooption : [po_virtualmethod];
+ mutexclpocall : [pocall_internproc];
+ mutexclpotype : [potype_class_constructor,potype_class_destructor];
+ mutexclpo : [po_external,po_interrupt,po_exports,po_overridingmethod,po_inline]
+ ),(
+ idtok:_CPPDECL;
+ pd_flags : [pd_interface,pd_implemen,pd_body,pd_procvar];
+ handler : nil;
+ pocall : pocall_cppdecl;
+ pooption : [];
+ mutexclpocall : [];
+ mutexclpotype : [potype_constructor,potype_destructor,potype_class_constructor,potype_class_destructor];
+ mutexclpo : [po_assembler,po_external,po_virtualmethod]
+ ),(
+ idtok:_VARARGS;
+ pd_flags : [pd_interface,pd_implemen,pd_procvar,pd_objcclass,pd_objcprot];
+ handler : nil;
+ pocall : pocall_none;
+ pooption : [po_varargs];
+ mutexclpocall : [pocall_internproc,pocall_stdcall,pocall_register,
+ pocall_far16,pocall_oldfpccall,pocall_mwpascal];
+ mutexclpotype : [];
+ mutexclpo : [po_assembler,po_interrupt,po_inline]
+ ),(
+ idtok:_COMPILERPROC;
+ pd_flags : [pd_interface,pd_implemen,pd_body,pd_notobjintf];
+ handler : nil;
+ pocall : pocall_none;
+ pooption : [po_compilerproc];
+ mutexclpocall : [];
+ mutexclpotype : [potype_constructor,potype_destructor,potype_class_constructor,potype_class_destructor];
+ mutexclpo : [po_interrupt]
+ ),(
+ idtok:_WEAKEXTERNAL;
+ pd_flags : [pd_implemen,pd_interface,pd_notobject,pd_notobjintf,pd_cppobject,pd_notrecord,pd_nothelper];
+ handler : @pd_weakexternal;
+ pocall : pocall_none;
+ { mark it both external and weak external, so we don't have to
+ adapt all code for external symbols to also check for weak external
+ }
+ pooption : [po_external,po_weakexternal];
+ mutexclpocall : [pocall_internproc,pocall_syscall];
+ { allowed for external cpp classes }
+ mutexclpotype : [{potype_constructor,potype_destructor}potype_class_constructor,potype_class_destructor];
+ mutexclpo : [po_public,po_exports,po_interrupt,po_assembler,po_inline]
+ ),(
+ idtok:_ENUMERATOR;
+ pd_flags : [pd_interface,pd_object,pd_record];
+ handler : @pd_enumerator;
+ pocall : pocall_none;
+ pooption : [];
+ mutexclpocall : [pocall_internproc];
+ mutexclpotype : [];
+ mutexclpo : [po_exports,po_interrupt,po_external,po_inline]
+ ),(
+ idtok:_RTLPROC;
+ pd_flags : [pd_interface,pd_implemen,pd_body,pd_notobjintf];
+ handler : nil;
+ pocall : pocall_none;
+ pooption : [po_rtlproc];
+ mutexclpocall : [];
+ mutexclpotype : [potype_constructor,potype_destructor,potype_class_constructor,potype_class_destructor];
+ mutexclpo : [po_interrupt]
+ )
+ );
+
+
+ function check_proc_directive(isprocvar:boolean):boolean;
+ var
+ i : longint;
+ begin
+ result:=false;
+ for i:=1 to num_proc_directives do
+ if proc_direcdata[i].idtok=idtoken then
+ begin
+ if ((not isprocvar) or
+ (pd_procvar in proc_direcdata[i].pd_flags)) and
+ { don't eat a public directive in classes }
+ not((idtoken=_PUBLIC) and (symtablestack.top.symtabletype=ObjectSymtable)) then
+ result:=true;
+ exit;
+ end;
+ end;
+
+
+ function parse_proc_direc(pd:tabstractprocdef;var pdflags:tpdflags):boolean;
+ {
+ Parse the procedure directive, returns true if a correct directive is found
+ }
+ var
+ p : longint;
+ found : boolean;
+ name : TIDString;
+ begin
+ parse_proc_direc:=false;
+ name:=tokeninfo^[idtoken].str;
+ found:=false;
+
+ { Hint directive? Then exit immediatly }
+ if (m_hintdirective in current_settings.modeswitches) then
+ begin
+ case idtoken of
+ _LIBRARY,
+ _PLATFORM,
+ _UNIMPLEMENTED,
+ _EXPERIMENTAL,
+ _DEPRECATED :
+ exit;
+ end;
+ end;
+
+ { C directive is MacPas only, because it breaks too much existing code
+ on other platforms (PFV) }
+ if (idtoken=_C) and
+ not(m_mac in current_settings.modeswitches) then
+ exit;
+
+ { retrieve data for directive if found }
+ for p:=1 to num_proc_directives do
+ if proc_direcdata[p].idtok=idtoken then
+ begin
+ found:=true;
+ break;
+ end;
+
+ { Check if the procedure directive is known }
+ if not found then
+ begin
+ { parsing a procvar type the name can be any
+ next variable !! }
+ if ((pdflags * [pd_procvar,pd_object,pd_record,pd_objcclass,pd_objcprot])=[]) and
+ not(idtoken=_PROPERTY) then
+ Message1(parser_w_unknown_proc_directive_ignored,name);
+ exit;
+ end;
+
+ { check if method and directive not for object, like public.
+ This needs to be checked also for procvars }
+ if (pd_notobject in proc_direcdata[p].pd_flags) and
+ (symtablestack.top.symtabletype=ObjectSymtable) and
+ { directive allowed for cpp classes? }
+ not(is_cppclass(tdef(symtablestack.top.defowner)) and (pd_cppobject in proc_direcdata[p].pd_flags)) then
+ exit;
+
+ if (pd_notrecord in proc_direcdata[p].pd_flags) and
+ (symtablestack.top.symtabletype=recordsymtable) then
+ exit;
+
+ { Conflicts between directives ? }
+ if (pd.proctypeoption in proc_direcdata[p].mutexclpotype) or
+ (pd.proccalloption in proc_direcdata[p].mutexclpocall) or
+ ((pd.procoptions*proc_direcdata[p].mutexclpo)<>[]) then
+ begin
+ Message1(parser_e_proc_dir_conflict,name);
+ exit;
+ end;
+
+ { set calling convention }
+ if proc_direcdata[p].pocall<>pocall_none then
+ begin
+ if (po_hascallingconvention in pd.procoptions) then
+ begin
+ Message2(parser_w_proc_overriding_calling,
+ proccalloptionStr[pd.proccalloption],
+ proccalloptionStr[proc_direcdata[p].pocall]);
+ end;
+ { check if the target processor supports this calling convention }
+ if not(proc_direcdata[p].pocall in supported_calling_conventions) then
+ begin
+ Message1(parser_e_illegal_calling_convention,proccalloptionStr[proc_direcdata[p].pocall]);
+ { recover }
+ proc_direcdata[p].pocall:=pocall_stdcall;
+ end;
+ pd.proccalloption:=proc_direcdata[p].pocall;
+ include(pd.procoptions,po_hascallingconvention);
+ end;
+
+ if pd.typ=procdef then
+ begin
+ { Check if the directive is only for objects }
+ if (pd_object in proc_direcdata[p].pd_flags) and
+ not assigned(tprocdef(pd).struct) then
+ exit;
+
+ { Check if the directive is only for records }
+ if (pd_record in proc_direcdata[p].pd_flags) and
+ not assigned(tprocdef(pd).struct) then
+ exit;
+
+ { check if method and directive not for interface }
+ if (pd_notobjintf in proc_direcdata[p].pd_flags) and
+ is_interface(tprocdef(pd).struct) then
+ exit;
+
+ { check if method and directive not for interface }
+ if is_dispinterface(tprocdef(pd).struct) and
+ not(pd_dispinterface in proc_direcdata[p].pd_flags) then
+ exit;
+
+ { check if method and directive not for objcclass }
+ if is_objcclass(tprocdef(pd).struct) and
+ not(pd_objcclass in proc_direcdata[p].pd_flags) then
+ exit;
+
+ { check if method and directive not for objcprotocol }
+ if is_objcprotocol(tprocdef(pd).struct) and
+ not(pd_objcprot in proc_direcdata[p].pd_flags) then
+ exit;
+
+ { check if method and directive not for record/class helper }
+ if is_objectpascal_helper(tprocdef(pd).struct) and
+ (pd_nothelper in proc_direcdata[p].pd_flags) then
+ exit;
+
+ end;
+
+ { consume directive, and turn flag on }
+ consume(token);
+ parse_proc_direc:=true;
+
+ { Check the pd_flags if the directive should be allowed }
+ if (pd_interface in pdflags) and
+ not(pd_interface in proc_direcdata[p].pd_flags) then
+ begin
+ Message1(parser_e_proc_dir_not_allowed_in_interface,name);
+ exit;
+ end;
+ if (pd_implemen in pdflags) and
+ not(pd_implemen in proc_direcdata[p].pd_flags) then
+ begin
+ Message1(parser_e_proc_dir_not_allowed_in_implementation,name);
+ exit;
+ end;
+ if (pd_procvar in pdflags) and
+ not(pd_procvar in proc_direcdata[p].pd_flags) then
+ begin
+ Message1(parser_e_proc_dir_not_allowed_in_procvar,name);
+ exit;
+ end;
+
+ { Return the new pd_flags }
+ if not(pd_body in proc_direcdata[p].pd_flags) then
+ exclude(pdflags,pd_body);
+
+ { Add the correct flag }
+ pd.procoptions:=pd.procoptions+proc_direcdata[p].pooption;
+
+ { Call the handler }
+ if pointer(proc_direcdata[p].handler)<>nil then
+ proc_direcdata[p].handler(pd);
+ end;
+
+
+
+ function proc_get_importname(pd:tprocdef):string;
+ var
+ dllname, importname : string;
+
+ begin
+ result:='';
+ if not(po_external in pd.procoptions) then
+ internalerror(200412151);
+ { external name or number is specified }
+ if assigned(pd.import_name) or (pd.import_nr<>0) then
+ begin
+ if assigned(pd.import_dll) then
+ dllname:=pd.import_dll^
+ else
+ dllname:='';
+ if assigned(pd.import_name) then
+ importname:=pd.import_name^
+ else
+ importname:='';
+ proc_get_importname:=make_dllmangledname(dllname,
+ importname,pd.import_nr,pd.proccalloption);
+ end
+ else
+ begin
+ { Default names when importing variables }
+ case pd.proccalloption of
+ pocall_cdecl :
+ begin
+ if assigned(pd.struct) then
+ result:=target_info.Cprefix+pd.struct.objrealname^+'_'+pd.procsym.realname
+ else
+ result:=target_info.Cprefix+pd.procsym.realname;
+ end;
+ pocall_cppdecl :
+ begin
+ result:=target_info.Cprefix+pd.cplusplusmangledname;
+ end;
+ else
+ begin
+ {In MacPas a single "external" has the same effect as "external name 'xxx'" }
+ { but according to MacPas mode description
+ Cprefix should still be used PM }
+ if (m_mac in current_settings.modeswitches) then
+ result:=target_info.Cprefix+tprocdef(pd).procsym.realname;
+ end;
+ end;
+ end;
+ end;
+
+
+ procedure proc_set_mangledname(pd:tprocdef);
+ var
+ s : string;
+ begin
+ { When the mangledname is already set we aren't allowed to change
+ it because it can already be used somewhere (PFV) }
+ if not(po_has_mangledname in pd.procoptions) then
+ begin
+ if (po_external in pd.procoptions) then
+ begin
+ { External Procedures are only allowed to change the mangledname
+ in their first declaration }
+ if (pd.forwarddef or (not pd.hasforward)) then
+ begin
+ s:=proc_get_importname(pd);
+ if s<>'' then
+ begin
+ pd.setmangledname(s);
+ end;
+ end;
+ end
+ else
+ { Normal procedures }
+ begin
+ if (po_compilerproc in pd.procoptions) then
+ begin
+ pd.setmangledname(lower(pd.procsym.name));
+ end;
+ end;
+ end;
+
+ { Public/exported alias names }
+ if (([po_public,po_exports]*pd.procoptions)<>[]) and
+ not(po_has_public_name in pd.procoptions) then
+ begin
+ case pd.proccalloption of
+ pocall_cdecl :
+ begin
+ if assigned(pd.struct) then
+ pd.aliasnames.insert(target_info.Cprefix+pd.struct.objrealname^+'_'+pd.procsym.realname)
+ else
+ begin
+ { Export names are not mangled on Windows and OS/2, see also pexports.pas }
+ if (target_info.system in (systems_all_windows+[system_i386_emx, system_i386_os2])) and
+ (po_exports in pd.procoptions) then
+ pd.aliasnames.insert(pd.procsym.realname)
+ else
+ pd.aliasnames.insert(target_info.Cprefix+pd.procsym.realname);
+ end;
+ end;
+ pocall_cppdecl :
+ begin
+ pd.aliasnames.insert(target_info.Cprefix+pd.cplusplusmangledname);
+ end;
+ end;
+ { prevent adding the alias a second time }
+ include(pd.procoptions,po_has_public_name);
+ end;
+ end;
+
+
+ procedure handle_calling_convention(pd:tabstractprocdef);
+ begin
+ { set the default calling convention if none provided }
+ if (pd.typ=procdef) and
+ (is_objc_class_or_protocol(tprocdef(pd).struct) or
+ is_cppclass(tprocdef(pd).struct)) then
+ begin
+ { none of the explicit calling conventions should be allowed }
+ if (po_hascallingconvention in pd.procoptions) then
+ internalerror(2009032501);
+ if is_cppclass(tprocdef(pd).struct) then
+ pd.proccalloption:=pocall_cppdecl
+ else
+ pd.proccalloption:=pocall_cdecl;
+ end
+ else if not(po_hascallingconvention in pd.procoptions) then
+ pd.proccalloption:=current_settings.defproccall
+ else
+ begin
+ if pd.proccalloption=pocall_none then
+ internalerror(200309081);
+ end;
+
+ { handle proccall specific settings }
+ case pd.proccalloption of
+ pocall_cdecl,
+ pocall_cppdecl :
+ begin
+ { check C cdecl para types }
+ check_c_para(pd);
+ end;
+ pocall_far16 :
+ begin
+ { Temporary stub, must be rewritten to support OS/2 far16 }
+ Message1(parser_w_proc_directive_ignored,'FAR16');
+ end;
+ end;
+
+ { Inlining is enabled and supported? }
+ if (po_inline in pd.procoptions) and
+ not(cs_do_inline in current_settings.localswitches) then
+ begin
+ { Give an error if inline is not supported by the compiler mode,
+ otherwise only give a warning that this procedure will not be inlined }
+ if not(m_default_inline in current_settings.modeswitches) then
+ Message(parser_e_proc_inline_not_supported)
+ else
+ Message(parser_w_inlining_disabled);
+ exclude(pd.procoptions,po_inline);
+ end;
+
+ { For varargs directive also cdecl and external must be defined }
+ if (po_varargs in pd.procoptions) then
+ begin
+ { check first for external in the interface, if available there
+ then the cdecl must also be there since there is no implementation
+ available to contain it }
+ if parse_only then
+ begin
+ { if external is available, then cdecl must also be available,
+ procvars don't need external }
+ if not((po_external in pd.procoptions) or
+ (pd.typ=procvardef) or
+ { for objcclasses this is checked later, because the entire
+ class may be external. }
+ is_objc_class_or_protocol(tprocdef(pd).struct)) and
+ not(pd.proccalloption in (cdecl_pocalls + [pocall_mwpascal])) then
+ Message(parser_e_varargs_need_cdecl_and_external);
+ end
+ else
+ begin
+ { both must be defined now }
+ if not((po_external in pd.procoptions) or
+ (pd.typ=procvardef)) or
+ not(pd.proccalloption in (cdecl_pocalls + [pocall_mwpascal])) then
+ Message(parser_e_varargs_need_cdecl_and_external);
+ end;
+ end;
+
+ { insert hidden high parameters }
+ pd.parast.SymList.ForEachCall(@insert_hidden_para,pd);
+
+ { insert hidden self parameter }
+ insert_self_and_vmt_para(pd);
+
+ { insert funcret parameter if required }
+ insert_funcret_para(pd);
+
+ { Make var parameters regable, this must be done after the calling
+ convention is set. }
+ { this must be done before parentfp is insert, because getting all cases
+ where parentfp must be in a memory location isn't catched properly so
+ we put parentfp never in a register }
+ pd.parast.SymList.ForEachCall(@set_addr_param_regable,pd);
+
+ { insert parentfp parameter if required }
+ insert_parentfp_para(pd);
+
+ { Calculate parameter tlist }
+ pd.calcparas;
+ end;
+
+
+ procedure parse_proc_directives(pd:tabstractprocdef;var pdflags:tpdflags);
+ {
+ Parse the procedure directives. It does not matter if procedure directives
+ are written using ;procdir; or ['procdir'] syntax.
+ }
+ var
+ res : boolean;
+ begin
+ if (m_mac in current_settings.modeswitches) and (cs_externally_visible in current_settings.localswitches) then
+ begin
+ tprocdef(pd).aliasnames.insert(target_info.Cprefix+tprocdef(pd).procsym.realname);
+ include(pd.procoptions,po_public);
+ include(pd.procoptions,po_has_public_name);
+ include(pd.procoptions,po_global);
+ end;
+
+ { methods from external class definitions are all external themselves }
+ if (pd.typ=procdef) and
+ assigned(tprocdef(pd).struct) and
+ (tprocdef(pd).struct.typ=objectdef) and
+ (oo_is_external in tobjectdef(tprocdef(pd).struct).objectoptions) then
+ tprocdef(pd).make_external;
+
+ { Class constructors and destructor are static class methods in real. }
+ { There are many places in the compiler where either class or static }
+ { method flag changes the behavior. It is simplier to add them to }
+ { the class constructors/destructors options than to fix all the }
+ { occurencies. (Paul) }
+ if pd.proctypeoption in [potype_class_constructor,potype_class_destructor] then
+ begin
+ include(pd.procoptions,po_classmethod);
+ include(pd.procoptions,po_staticmethod);
+ end;
+
+ while token in [_ID,_LECKKLAMMER] do
+ begin
+ if try_to_consume(_LECKKLAMMER) then
+ begin
+ repeat
+ parse_proc_direc(pd,pdflags);
+ until not try_to_consume(_COMMA);
+ consume(_RECKKLAMMER);
+ { we always expect at least '[];' }
+ res:=true;
+ end
+ else
+ begin
+ res:=parse_proc_direc(pd,pdflags);
+ end;
+ { A procedure directive normally followed by a semicolon, but in
+ a const section or reading a type we should stop when _EQ is found,
+ because a constant/default value follows }
+ if res then
+ begin
+ if (block_type=bt_const_type) and
+ (token=_EQ) then
+ break;
+ { support procedure proc;stdcall export; }
+ if not(check_proc_directive((pd.typ=procvardef))) then
+ begin
+ { support "record p : procedure stdcall end;" and
+ "var p : procedure stdcall = nil;" }
+ if (pd_procvar in pdflags) and
+ (token in [_END,_RKLAMMER,_EQ]) then
+ break
+ else
+ begin
+ if (token=_COLON) then
+ begin
+ Message(parser_e_field_not_allowed_here);
+ consume_all_until(_SEMICOLON);
+ end;
+ consume(_SEMICOLON)
+ end;
+ end;
+ end
+ else
+ break;
+ end;
+ end;
+
+
+ procedure parse_var_proc_directives(sym:tsym);
+ var
+ pdflags : tpdflags;
+ pd : tabstractprocdef;
+ begin
+ pdflags:=[pd_procvar];
+ pd:=nil;
+ case sym.typ of
+ fieldvarsym,
+ staticvarsym,
+ localvarsym,
+ paravarsym :
+ pd:=tabstractprocdef(tabstractvarsym(sym).vardef);
+ typesym :
+ pd:=tabstractprocdef(ttypesym(sym).typedef);
+ else
+ internalerror(2003042617);
+ end;
+ if pd.typ<>procvardef then
+ internalerror(2003042618);
+ { names should never be used anyway }
+ parse_proc_directives(pd,pdflags);
+ end;
+
+
+ procedure parse_object_proc_directives(pd:tabstractprocdef);
+ var
+ pdflags : tpdflags;
+ begin
+ pdflags:=[pd_object];
+ parse_proc_directives(pd,pdflags);
+ end;
+
+ procedure parse_record_proc_directives(pd:tabstractprocdef);
+ var
+ pdflags : tpdflags;
+ begin
+ pdflags:=[pd_record];
+ parse_proc_directives(pd,pdflags);
+ end;
+
+ function proc_add_definition(var currpd:tprocdef):boolean;
+ {
+ Add definition aprocdef to the overloaded definitions of aprocsym. If a
+ forwarddef is found and reused it returns true
+ }
+ var
+ fwpd : tprocdef;
+ currparasym,
+ fwparasym : tsym;
+ currparacnt,
+ fwparacnt,
+ curridx,
+ fwidx,
+ i : longint;
+ po_comp : tprocoptions;
+ paracompopt: tcompare_paras_options;
+ forwardfound : boolean;
+ symentry: TSymEntry;
+ begin
+ forwardfound:=false;
+
+ { check overloaded functions if the same function already exists }
+ for i:=0 to tprocsym(currpd.procsym).ProcdefList.Count-1 do
+ begin
+ fwpd:=tprocdef(tprocsym(currpd.procsym).ProcdefList[i]);
+
+ { Skip overloaded definitions that are declared in other units }
+ if fwpd.procsym<>currpd.procsym then
+ continue;
+
+ { check the parameters, for delphi/tp it is possible to
+ leave the parameters away in the implementation (forwarddef=false).
+ But for an overload declared function this is not allowed }
+ if { check if empty implementation arguments match is allowed }
+ (
+ not(m_repeat_forward in current_settings.modeswitches) and
+ not(currpd.forwarddef) and
+ is_bareprocdef(currpd) and
+ not(po_overload in fwpd.procoptions)
+ ) or
+ { check arguments, we need to check only the user visible parameters. The hidden parameters
+ can be in a different location because of the calling convention, eg. L-R vs. R-L order (PFV) }
+ (
+ (compare_paras(currpd.paras,fwpd.paras,cp_none,[cpo_comparedefaultvalue,cpo_ignorehidden,cpo_openequalisexact,cpo_ignoreuniv])=te_exact) and
+ (compare_defs(fwpd.returndef,currpd.returndef,nothingn)=te_exact)
+ ) then
+ begin
+ { Check if we've found the forwarddef, if found then
+ we need to update the forward def with the current
+ implementation settings }
+ if fwpd.forwarddef then
+ begin
+ forwardfound:=true;
+
+ if not(m_repeat_forward in current_settings.modeswitches) and
+ (fwpd.proccalloption<>currpd.proccalloption) then
+ paracompopt:=[cpo_ignorehidden,cpo_comparedefaultvalue,cpo_openequalisexact,cpo_ignoreuniv]
+ else
+ paracompopt:=[cpo_comparedefaultvalue,cpo_openequalisexact,cpo_ignoreuniv];
+
+ { Check calling convention }
+ if (fwpd.proccalloption<>currpd.proccalloption) then
+ begin
+ { In delphi it is possible to specify the calling
+ convention in the interface or implementation if
+ there was no convention specified in the other
+ part }
+ if (m_delphi in current_settings.modeswitches) then
+ begin
+ if not(po_hascallingconvention in currpd.procoptions) then
+ currpd.proccalloption:=fwpd.proccalloption
+ else
+ if not(po_hascallingconvention in fwpd.procoptions) then
+ fwpd.proccalloption:=currpd.proccalloption
+ else
+ begin
+ MessagePos(currpd.fileinfo,parser_e_call_convention_dont_match_forward);
+ tprocsym(currpd.procsym).write_parameter_lists(currpd);
+ { restore interface settings }
+ currpd.proccalloption:=fwpd.proccalloption;
+ end;
+ end
+ else
+ begin
+ MessagePos(currpd.fileinfo,parser_e_call_convention_dont_match_forward);
+ tprocsym(currpd.procsym).write_parameter_lists(currpd);
+ { restore interface settings }
+ currpd.proccalloption:=fwpd.proccalloption;
+ end;
+ end;
+
+ { Check static }
+ if (po_staticmethod in fwpd.procoptions) then
+ begin
+ if not (po_staticmethod in currpd.procoptions) then
+ begin
+ include(currpd.procoptions, po_staticmethod);
+ if (po_classmethod in currpd.procoptions) then
+ begin
+ { remove self from the hidden paras }
+ symentry:=currpd.parast.Find('self');
+ if symentry<>nil then
+ begin
+ currpd.parast.Delete(symentry);
+ currpd.calcparas;
+ end;
+ end;
+ end;
+ end;
+
+ { Check if the procedure type and return type are correct,
+ also the parameters must match also with the type }
+ if ((m_repeat_forward in current_settings.modeswitches) or
+ not is_bareprocdef(currpd)) and
+ ((compare_paras(currpd.paras,fwpd.paras,cp_all,paracompopt)<>te_exact) or
+ (compare_defs(fwpd.returndef,currpd.returndef,nothingn)<>te_exact)) then
+ begin
+ MessagePos1(currpd.fileinfo,parser_e_header_dont_match_forward,
+ fwpd.fullprocname(false));
+ tprocsym(currpd.procsym).write_parameter_lists(currpd);
+ break;
+ end;
+
+ { Check if both are declared forward }
+ if fwpd.forwarddef and currpd.forwarddef then
+ begin
+ MessagePos1(currpd.fileinfo,parser_e_function_already_declared_public_forward,
+ currpd.fullprocname(false));
+ end;
+
+ { internconst or internproc only need to be defined once }
+ if (fwpd.proccalloption=pocall_internproc) then
+ currpd.proccalloption:=fwpd.proccalloption
+ else
+ if (currpd.proccalloption=pocall_internproc) then
+ fwpd.proccalloption:=currpd.proccalloption;
+
+ { Check procedure options, Delphi requires that class is
+ repeated in the implementation for class methods }
+ if (m_fpc in current_settings.modeswitches) then
+ po_comp:=[po_classmethod,po_varargs,po_methodpointer,po_interrupt]
+ else
+ po_comp:=[po_classmethod,po_methodpointer];
+
+ if ((po_comp * fwpd.procoptions)<>(po_comp * currpd.procoptions)) or
+ (fwpd.proctypeoption <> currpd.proctypeoption) or
+ { if the implementation version has an "overload" modifier,
+ the interface version must also have it (otherwise we can
+ get annoying crashes due to interface crc changes) }
+ (not(po_overload in fwpd.procoptions) and
+ (po_overload in currpd.procoptions)) then
+ begin
+ MessagePos1(currpd.fileinfo,parser_e_header_dont_match_forward,
+ fwpd.fullprocname(false));
+ tprocsym(fwpd.procsym).write_parameter_lists(fwpd);
+ { This error is non-fatal, we can recover }
+ end;
+
+ { Forward declaration is external? }
+ if (po_external in fwpd.procoptions) then
+ MessagePos(currpd.fileinfo,parser_e_proc_already_external);
+
+ { Check parameters }
+ if (m_repeat_forward in current_settings.modeswitches) or
+ (currpd.minparacount>0) then
+ begin
+ { If mangled names are equal then they have the same amount of arguments }
+ { We can check the names of the arguments }
+ { both symtables are in the same order from left to right }
+ curridx:=0;
+ fwidx:=0;
+ currparacnt:=currpd.parast.SymList.Count;
+ fwparacnt:=fwpd.parast.SymList.Count;
+ repeat
+ { skip default parameter constsyms }
+ while (curridx<currparacnt) and
+ (tsym(currpd.parast.SymList[curridx]).typ<>paravarsym) do
+ inc(curridx);
+ while (fwidx<fwparacnt) and
+ (tsym(fwpd.parast.SymList[fwidx]).typ<>paravarsym) do
+ inc(fwidx);
+ { stop when one of the two lists is at the end }
+ if (fwidx>=fwparacnt) or (curridx>=currparacnt) then
+ break;
+ { compare names of parameters, ignore implictly
+ renamed parameters }
+ currparasym:=tsym(currpd.parast.SymList[curridx]);
+ fwparasym:=tsym(fwpd.parast.SymList[fwidx]);
+ if not(sp_implicitrename in currparasym.symoptions) and
+ not(sp_implicitrename in fwparasym.symoptions) then
+ begin
+ if (currparasym.name<>fwparasym.name) then
+ begin
+ MessagePos3(currpd.fileinfo,parser_e_header_different_var_names,
+ tprocsym(currpd.procsym).realname,fwparasym.realname,currparasym.realname);
+ break;
+ end;
+ end;
+ { next parameter }
+ inc(curridx);
+ inc(fwidx);
+ until false;
+ end;
+ { Everything is checked, now we can update the forward declaration
+ with the new data from the implementation }
+ fwpd.forwarddef:=currpd.forwarddef;
+ fwpd.hasforward:=true;
+ fwpd.procoptions:=fwpd.procoptions+currpd.procoptions;
+
+ { marked as local but exported from unit? }
+ if (po_kylixlocal in fwpd.procoptions) and (fwpd.owner.symtabletype=globalsymtable) then
+ MessagePos(fwpd.fileinfo,type_e_cant_export_local);
+
+ if fwpd.extnumber=$ffff then
+ fwpd.extnumber:=currpd.extnumber;
+ while not currpd.aliasnames.empty do
+ fwpd.aliasnames.insert(currpd.aliasnames.getfirst);
+ { update fileinfo so position references the implementation,
+ also update funcretsym if it is already generated }
+ fwpd.fileinfo:=currpd.fileinfo;
+ if assigned(fwpd.funcretsym) then
+ fwpd.funcretsym.fileinfo:=currpd.fileinfo;
+ if assigned(currpd.deprecatedmsg) then
+ begin
+ stringdispose(fwpd.deprecatedmsg);
+ fwpd.deprecatedmsg:=stringdup(currpd.deprecatedmsg^);
+ end;
+ { import names }
+ if assigned(currpd.import_dll) then
+ begin
+ stringdispose(fwpd.import_dll);
+ fwpd.import_dll:=stringdup(currpd.import_dll^);
+ end;
+ if assigned(currpd.import_name) then
+ begin
+ stringdispose(fwpd.import_name);
+ fwpd.import_name:=stringdup(currpd.import_name^);
+ end;
+ fwpd.import_nr:=currpd.import_nr;
+ { for compilerproc defines we need to rename and update the
+ symbolname to lowercase }
+ if (po_compilerproc in fwpd.procoptions) then
+ begin
+ { rename to lowercase so users can't access it }
+ fwpd.procsym.realname:='$'+lower(fwpd.procsym.name);
+ { the mangeled name is already changed by the pd_compilerproc }
+ { handler. It must be done immediately because if we have a }
+ { call to a compilerproc before it's implementation is }
+ { encountered, it must already use the new mangled name (JM) }
+ end;
+
+ { Release current procdef }
+ currpd.owner.deletedef(currpd);
+ currpd:=fwpd;
+ end
+ else
+ begin
+ { abstract methods aren't forward defined, but this }
+ { needs another error message }
+ if (po_abstractmethod in fwpd.procoptions) then
+ MessagePos(currpd.fileinfo,parser_e_abstract_no_definition)
+ else
+ begin
+ MessagePos(currpd.fileinfo,parser_e_overloaded_have_same_parameters);
+ tprocsym(currpd.procsym).write_parameter_lists(currpd);
+ end;
+ end;
+
+ { we found one proc with the same arguments, there are no others
+ so we can stop }
+ break;
+ end;
+
+ { check for allowing overload directive }
+ if not(m_fpc in current_settings.modeswitches) then
+ begin
+ { overload directive turns on overloading }
+ if ((po_overload in currpd.procoptions) or
+ (po_overload in fwpd.procoptions)) then
+ begin
+ { check if all procs have overloading, but not if the proc is a method or
+ already declared forward, then the check is already done }
+ if not(fwpd.hasforward or
+ assigned(currpd.struct) or
+ (currpd.forwarddef<>fwpd.forwarddef) or
+ ((po_overload in currpd.procoptions) and
+ (po_overload in fwpd.procoptions))) then
+ begin
+ MessagePos1(currpd.fileinfo,parser_e_no_overload_for_all_procs,currpd.procsym.realname);
+ break;
+ end
+ end
+ else
+ begin
+ if not(fwpd.forwarddef) then
+ begin
+ if (m_tp7 in current_settings.modeswitches) then
+ MessagePos(currpd.fileinfo,parser_e_procedure_overloading_is_off)
+ else
+ MessagePos1(currpd.fileinfo,parser_e_no_overload_for_all_procs,currpd.procsym.realname);
+ break;
+ end;
+ end;
+ end; { equal arguments }
+ end;
+
+ { if we didn't reuse a forwarddef then we add the procdef to the overloaded
+ list }
+ if not forwardfound then
+ begin
+ { can happen in Delphi mode }
+ if (currpd.proctypeoption = potype_function) and
+ is_void(currpd.returndef) then
+ MessagePos1(currpd.fileinfo,parser_e_no_funcret_specified,currpd.procsym.realname);
+ tprocsym(currpd.procsym).ProcdefList.Add(currpd);
+ end;
+
+ proc_add_definition:=forwardfound;
+ end;
+
+end.
diff --git a/closures/compiler/pdecvar.pas b/closures/compiler/pdecvar.pas
new file mode 100644
index 0000000000..e4be488a71
--- /dev/null
+++ b/closures/compiler/pdecvar.pas
@@ -0,0 +1,1864 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Parses variable declarations. Used for var statement and record
+ definitions
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit pdecvar;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ symsym,symdef;
+
+ type
+ tvar_dec_option=(vd_record,vd_object,vd_threadvar,vd_class);
+ tvar_dec_options=set of tvar_dec_option;
+
+ function read_property_dec(is_classproperty:boolean;astruct:tabstractrecorddef):tpropertysym;
+
+ procedure read_var_decls(options:Tvar_dec_options);
+
+ procedure read_record_fields(options:Tvar_dec_options);
+
+ procedure read_public_and_external(vs: tabstractvarsym);
+
+ procedure try_consume_sectiondirective(var asection: ansistring);
+
+implementation
+
+ uses
+ SysUtils,
+ { common }
+ cutils,cclasses,
+ { global }
+ globtype,globals,tokens,verbose,constexp,
+ systems,
+ { symtable }
+ symconst,symbase,symtype,symtable,defutil,defcmp,
+ fmodule,htypechk,
+ { pass 1 }
+ node,pass_1,aasmdata,
+ nmat,nadd,ncal,nset,ncnv,ninl,ncon,nld,nflw,nmem,nutils,
+ { codegen }
+ ncgutil,
+ { parser }
+ scanner,
+ pbase,pexpr,ptype,ptconst,pdecsub,
+ { link }
+ import
+ ;
+
+
+ function read_property_dec(is_classproperty:boolean;astruct:tabstractrecorddef):tpropertysym;
+
+ { convert a node tree to symlist and return the last
+ symbol }
+ function parse_symlist(pl:tpropaccesslist;var def:tdef):boolean;
+ var
+ idx : longint;
+ sym : tsym;
+ srsymtable : TSymtable;
+ st : TSymtable;
+ p : tnode;
+ begin
+ result:=true;
+ def:=nil;
+ if token=_ID then
+ begin
+ if assigned(astruct) then
+ sym:=search_struct_member(astruct,pattern)
+ else
+ searchsym(pattern,sym,srsymtable);
+ if assigned(sym) then
+ begin
+ if assigned(astruct) and
+ not is_visible_for_object(sym,astruct) then
+ Message(parser_e_cant_access_private_member);
+ case sym.typ of
+ fieldvarsym :
+ begin
+ if (symtablestack.top.currentvisibility<>vis_private) then
+ addsymref(sym);
+ pl.addsym(sl_load,sym);
+ def:=tfieldvarsym(sym).vardef;
+ end;
+ procsym :
+ begin
+ if (symtablestack.top.currentvisibility<>vis_private) then
+ addsymref(sym);
+ pl.addsym(sl_call,sym);
+ end;
+ else
+ begin
+ Message1(parser_e_illegal_field_or_method,orgpattern);
+ def:=generrordef;
+ result:=false;
+ end;
+ end;
+ end
+ else
+ begin
+ Message1(parser_e_illegal_field_or_method,orgpattern);
+ def:=generrordef;
+ result:=false;
+ end;
+ consume(_ID);
+ repeat
+ case token of
+ _ID,
+ _SEMICOLON :
+ begin
+ break;
+ end;
+ _POINT :
+ begin
+ consume(_POINT);
+ if assigned(def) then
+ begin
+ st:=def.GetSymtable(gs_record);
+ if assigned(st) then
+ begin
+ sym:=tsym(st.Find(pattern));
+ if not(assigned(sym)) and is_object(def) then
+ sym:=search_struct_member(tobjectdef(def),pattern);
+ if assigned(sym) then
+ begin
+ pl.addsym(sl_subscript,sym);
+ case sym.typ of
+ fieldvarsym :
+ def:=tfieldvarsym(sym).vardef;
+ else
+ begin
+ Message1(sym_e_illegal_field,orgpattern);
+ result:=false;
+ end;
+ end;
+ end
+ else
+ begin
+ Message1(sym_e_illegal_field,orgpattern);
+ result:=false;
+ end;
+ end
+ else
+ begin
+ Message(parser_e_invalid_qualifier);
+ result:=false;
+ end;
+ end
+ else
+ begin
+ Message(parser_e_invalid_qualifier);
+ result:=false;
+ end;
+ consume(_ID);
+ end;
+ _LECKKLAMMER :
+ begin
+ consume(_LECKKLAMMER);
+ repeat
+ if def.typ=arraydef then
+ begin
+ idx:=0;
+ p:=comp_expr(true,false);
+ if (not codegenerror) then
+ begin
+ if (p.nodetype=ordconstn) then
+ begin
+ { type/range checking }
+ inserttypeconv(p,tarraydef(def).rangedef);
+ if (Tordconstnode(p).value<int64(low(longint))) or
+ (Tordconstnode(p).value>int64(high(longint))) then
+ message(parser_e_array_range_out_of_bounds)
+ else
+ idx:=Tordconstnode(p).value.svalue
+ end
+ else
+ Message(type_e_ordinal_expr_expected)
+ end;
+ pl.addconst(sl_vec,idx,p.resultdef);
+ p.free;
+ def:=tarraydef(def).elementdef;
+ end
+ else
+ begin
+ Message(parser_e_invalid_qualifier);
+ result:=false;
+ end;
+ until not try_to_consume(_COMMA);
+ consume(_RECKKLAMMER);
+ end;
+ else
+ begin
+ Message(parser_e_ill_property_access_sym);
+ result:=false;
+ break;
+ end;
+ end;
+ until false;
+ end
+ else
+ begin
+ Message(parser_e_ill_property_access_sym);
+ result:=false;
+ end;
+ end;
+
+ function allow_default_property(p : tpropertysym) : boolean;
+
+ begin
+ allow_default_property:=
+ (is_ordinal(p.propdef) or
+{$ifndef cpu64bitaddr}
+ is_64bitint(p.propdef) or
+{$endif cpu64bitaddr}
+ is_class(p.propdef) or
+ is_single(p.propdef) or
+ (p.propdef.typ in [classrefdef,pointerdef]) or
+ is_smallset(p.propdef)
+ ) and not
+ (
+ (p.propdef.typ=arraydef) and
+ (ppo_indexed in p.propoptions)
+ ) and not
+ (ppo_hasparameters in p.propoptions);
+ end;
+
+ procedure create_accessor_procsym(p: tpropertysym; pd: tprocdef; const prefix: string;
+ accesstype: tpropaccesslisttypes);
+ var
+ sym: tprocsym;
+ begin
+ handle_calling_convention(pd);
+ sym:=tprocsym.create(prefix+lower(p.realname));
+ symtablestack.top.insert(sym);
+ pd.procsym:=sym;
+ include(pd.procoptions,po_dispid);
+ include(pd.procoptions,po_global);
+ pd.visibility:=vis_private;
+ proc_add_definition(pd);
+ p.propaccesslist[accesstype].addsym(sl_call,sym);
+ p.propaccesslist[accesstype].procdef:=pd;
+ end;
+
+ procedure parse_dispinterface(p : tpropertysym; readpd,writepd: tprocdef;
+ var paranr: word);
+ var
+ hasread, haswrite: boolean;
+ pt: tnode;
+ hdispid: longint;
+ hparavs: tparavarsym;
+ begin
+ p.propaccesslist[palt_read].clear;
+ p.propaccesslist[palt_write].clear;
+
+ hasread:=true;
+ haswrite:=true;
+
+ if try_to_consume(_READONLY) then
+ haswrite:=false
+ else if try_to_consume(_WRITEONLY) then
+ hasread:=false;
+
+ if try_to_consume(_DISPID) then
+ begin
+ pt:=comp_expr(true,false);
+ if is_constintnode(pt) then
+ if (Tordconstnode(pt).value<int64(low(longint))) or (Tordconstnode(pt).value>int64(high(longint))) then
+ message(parser_e_range_check_error)
+ else
+ hdispid:=Tordconstnode(pt).value.svalue
+ else
+ Message(parser_e_dispid_must_be_ord_const);
+ pt.free;
+ end
+ else
+ hdispid:=tobjectdef(astruct).get_next_dispid;
+
+ { COM property is simply a pair of methods, tagged with 'propertyget'
+ and 'propertyset' flags (or a single method if access is restricted).
+ Creating these implicit accessor methods also allows the rest of compiler
+ to handle dispinterface properties the same way as regular ones. }
+ if hasread then
+ begin
+ readpd.returndef:=p.propdef;
+ readpd.dispid:=hdispid;
+ readpd.proctypeoption:=potype_propgetter;
+ create_accessor_procsym(p,readpd,'get$',palt_read);
+ end;
+ if haswrite then
+ begin
+ { add an extra parameter, a placeholder of the value to set }
+ inc(paranr);
+ hparavs:=tparavarsym.create('$value',10*paranr,vs_value,p.propdef,[]);
+ writepd.parast.insert(hparavs);
+
+ writepd.proctypeoption:=potype_propsetter;
+ writepd.dispid:=hdispid;
+ create_accessor_procsym(p,writepd,'put$',palt_write);
+ end;
+ end;
+
+ procedure add_parameters(p: tpropertysym; readprocdef, writeprocdef: tprocdef);
+ var
+ i: integer;
+ orig, hparavs: tparavarsym;
+ begin
+ for i := 0 to p.parast.SymList.Count - 1 do
+ begin
+ orig:=tparavarsym(p.parast.SymList[i]);
+ hparavs:=tparavarsym.create(orig.RealName,orig.paranr,orig.varspez,orig.vardef,[]);
+ readprocdef.parast.insert(hparavs);
+ hparavs:=tparavarsym.create(orig.RealName,orig.paranr,orig.varspez,orig.vardef,[]);
+ writeprocdef.parast.insert(hparavs);
+ end;
+ end;
+
+ procedure add_index_parameter(var paranr: word; p: tpropertysym; readprocdef, writeprocdef: tprocdef);
+ var
+ hparavs: tparavarsym;
+ begin
+ inc(paranr);
+ hparavs:=tparavarsym.create('$index',10*paranr,vs_value,p.indexdef,[]);
+ readprocdef.parast.insert(hparavs);
+ hparavs:=tparavarsym.create('$index',10*paranr,vs_value,p.indexdef,[]);
+ writeprocdef.parast.insert(hparavs);
+ end;
+
+ var
+ sym : tsym;
+ srsymtable: tsymtable;
+ p : tpropertysym;
+ overridden : tsym;
+ varspez : tvarspez;
+ hdef : tdef;
+ arraytype : tdef;
+ def : tdef;
+ pt : tnode;
+ sc : TFPObjectList;
+ paranr : word;
+ i : longint;
+ ImplIntf : TImplementedInterface;
+ found : boolean;
+ hreadparavs,
+ hparavs : tparavarsym;
+ storedprocdef: tprocvardef;
+ readprocdef,
+ writeprocdef : tprocdef;
+ begin
+ { Generate temp procdefs to search for matching read/write
+ procedures. the readprocdef will store all definitions }
+ paranr:=0;
+ readprocdef:=tprocdef.create(normal_function_level);
+ writeprocdef:=tprocdef.create(normal_function_level);
+
+ readprocdef.struct:=astruct;
+ writeprocdef.struct:=astruct;
+
+ if assigned(astruct) and is_classproperty then
+ begin
+ readprocdef.procoptions:=[po_staticmethod,po_classmethod];
+ writeprocdef.procoptions:=[po_staticmethod,po_classmethod];
+ end;
+
+ if token<>_ID then
+ begin
+ consume(_ID);
+ consume(_SEMICOLON);
+ exit;
+ end;
+ { Generate propertysym and insert in symtablestack }
+ p:=tpropertysym.create(orgpattern);
+ p.visibility:=symtablestack.top.currentvisibility;
+ p.default:=longint($80000000);
+ if is_classproperty then
+ include(p.symoptions, sp_static);
+ symtablestack.top.insert(p);
+ consume(_ID);
+ { property parameters ? }
+ if try_to_consume(_LECKKLAMMER) then
+ begin
+ if (p.visibility=vis_published) and
+ not (m_delphi in current_settings.modeswitches) then
+ Message(parser_e_cant_publish_that_property);
+ { create a list of the parameters }
+ p.parast:=tparasymtable.create(nil,0);
+ symtablestack.push(p.parast);
+ sc:=TFPObjectList.create(false);
+ repeat
+ if try_to_consume(_VAR) then
+ varspez:=vs_var
+ else if try_to_consume(_CONST) then
+ varspez:=vs_const
+ else if try_to_consume(_CONSTREF) then
+ varspez:=vs_constref
+ else if (m_out in current_settings.modeswitches) and try_to_consume(_OUT) then
+ varspez:=vs_out
+ else
+ varspez:=vs_value;
+ sc.clear;
+ repeat
+ inc(paranr);
+ hreadparavs:=tparavarsym.create(orgpattern,10*paranr,varspez,generrordef,[]);
+ p.parast.insert(hreadparavs);
+ sc.add(hreadparavs);
+ consume(_ID);
+ until not try_to_consume(_COMMA);
+ if try_to_consume(_COLON) then
+ begin
+ if try_to_consume(_ARRAY) then
+ begin
+ consume(_OF);
+ { define range and type of range }
+ hdef:=tarraydef.create(0,-1,s32inttype);
+ { define field type }
+ single_type(arraytype,[]);
+ tarraydef(hdef).elementdef:=arraytype;
+ end
+ else
+ single_type(hdef,[]);
+ end
+ else
+ hdef:=cformaltype;
+ for i:=0 to sc.count-1 do
+ tparavarsym(sc[i]).vardef:=hdef;
+ until not try_to_consume(_SEMICOLON);
+ sc.free;
+ symtablestack.pop(p.parast);
+ consume(_RECKKLAMMER);
+
+ { the parser need to know if a property has parameters, the
+ index parameter doesn't count (PFV) }
+ if paranr>0 then
+ begin
+ add_parameters(p,readprocdef,writeprocdef);
+ include(p.propoptions,ppo_hasparameters);
+ end;
+ end;
+ { overridden property ? }
+ { force property interface
+ there is a property parameter
+ a global property }
+ if (token=_COLON) or (paranr>0) or (astruct=nil) then
+ begin
+ consume(_COLON);
+ single_type(p.propdef,[stoAllowSpecialization]);
+
+ if is_dispinterface(astruct) and not is_automatable(p.propdef) then
+ Message1(type_e_not_automatable,p.propdef.typename);
+
+ if (idtoken=_INDEX) then
+ begin
+ consume(_INDEX);
+ pt:=comp_expr(true,false);
+ { Only allow enum and integer indexes. Convert all integer
+ values to s32int to be compatible with delphi, because the
+ procedure matching requires equal parameters }
+ if is_constnode(pt) and
+ is_ordinal(pt.resultdef)
+{$ifndef cpu64bitaddr}
+ and (not is_64bitint(pt.resultdef))
+{$endif cpu64bitaddr}
+ then
+ begin
+ if is_integer(pt.resultdef) then
+ inserttypeconv_internal(pt,s32inttype);
+ p.index:=tordconstnode(pt).value.svalue;
+ end
+ else
+ begin
+ Message(parser_e_invalid_property_index_value);
+ p.index:=0;
+ end;
+ p.indexdef:=pt.resultdef;
+ include(p.propoptions,ppo_indexed);
+ { concat a longint to the para templates }
+ add_index_parameter(paranr,p,readprocdef,writeprocdef);
+ pt.free;
+ end;
+ end
+ else
+ begin
+ { do an property override }
+ if (astruct.typ=objectdef) then
+ overridden:=search_struct_member(tobjectdef(astruct).childof,p.name)
+ else
+ overridden:=nil;
+ if assigned(overridden) and
+ (overridden.typ=propertysym) and
+ not(is_dispinterface(astruct)) then
+ begin
+ p.overriddenpropsym:=tpropertysym(overridden);
+ { inherit all type related entries }
+ p.indexdef:=tpropertysym(overridden).indexdef;
+ p.propdef:=tpropertysym(overridden).propdef;
+ p.index:=tpropertysym(overridden).index;
+ p.default:=tpropertysym(overridden).default;
+ p.propoptions:=tpropertysym(overridden).propoptions + [ppo_overrides];
+ if ppo_hasparameters in p.propoptions then
+ begin
+ p.parast:=tpropertysym(overridden).parast.getcopy;
+ add_parameters(p,readprocdef,writeprocdef);
+ paranr:=p.parast.SymList.Count;
+ end;
+ if ppo_indexed in p.propoptions then
+ add_index_parameter(paranr,p,readprocdef,writeprocdef);
+ end
+ else
+ begin
+ p.propdef:=generrordef;
+ message(parser_e_no_property_found_to_override);
+ end;
+ end;
+ if ((p.visibility=vis_published) or is_dispinterface(astruct)) and
+ (not(p.propdef.is_publishable) or (sp_static in p.symoptions)) then
+ begin
+ Message(parser_e_cant_publish_that_property);
+ p.visibility:=vis_public;
+ end;
+
+ if not(is_dispinterface(astruct)) then
+ begin
+ if try_to_consume(_READ) then
+ begin
+ p.propaccesslist[palt_read].clear;
+ if parse_symlist(p.propaccesslist[palt_read],def) then
+ begin
+ sym:=p.propaccesslist[palt_read].firstsym^.sym;
+ case sym.typ of
+ procsym :
+ begin
+ { read is function returning the type of the property }
+ readprocdef.returndef:=p.propdef;
+ { Insert hidden parameters }
+ handle_calling_convention(readprocdef);
+ { search procdefs matching readprocdef }
+ { we ignore hidden stuff here because the property access symbol might have
+ non default calling conventions which might change the hidden stuff;
+ see tw3216.pp (FK) }
+ p.propaccesslist[palt_read].procdef:=Tprocsym(sym).Find_procdef_bypara(readprocdef.paras,p.propdef,[cpo_allowdefaults,cpo_ignorehidden]);
+ if not assigned(p.propaccesslist[palt_read].procdef) or
+ { because of cpo_ignorehidden we need to compare if it is a static class method and we have a class property }
+ ((sp_static in p.symoptions) <> tprocdef(p.propaccesslist[palt_read].procdef).no_self_node) then
+ Message(parser_e_ill_property_access_sym);
+ end;
+ fieldvarsym :
+ begin
+ if not assigned(def) then
+ internalerror(200310071);
+ if compare_defs(def,p.propdef,nothingn)>=te_equal then
+ begin
+ { property parameters are allowed if this is
+ an indexed property, because the index is then
+ the parameter.
+ Note: In the help of Kylix it is written
+ that it isn't allowed, but the compiler accepts it (PFV) }
+ if (ppo_hasparameters in p.propoptions) or
+ ((sp_static in p.symoptions) <> (sp_static in sym.symoptions)) then
+ Message(parser_e_ill_property_access_sym);
+ end
+ else
+ IncompatibleTypes(def,p.propdef);
+ end;
+ else
+ Message(parser_e_ill_property_access_sym);
+ end;
+ end;
+ end;
+ if try_to_consume(_WRITE) then
+ begin
+ p.propaccesslist[palt_write].clear;
+ if parse_symlist(p.propaccesslist[palt_write],def) then
+ begin
+ sym:=p.propaccesslist[palt_write].firstsym^.sym;
+ case sym.typ of
+ procsym :
+ begin
+ { write is a procedure with an extra value parameter
+ of the of the property }
+ writeprocdef.returndef:=voidtype;
+ inc(paranr);
+ hparavs:=tparavarsym.create('$value',10*paranr,vs_value,p.propdef,[]);
+ writeprocdef.parast.insert(hparavs);
+ { Insert hidden parameters }
+ handle_calling_convention(writeprocdef);
+ { search procdefs matching writeprocdef }
+ if cs_varpropsetter in current_settings.localswitches then
+ p.propaccesslist[palt_write].procdef:=Tprocsym(sym).Find_procdef_bypara(writeprocdef.paras,writeprocdef.returndef,[cpo_allowdefaults,cpo_ignorevarspez])
+ else
+ p.propaccesslist[palt_write].procdef:=Tprocsym(sym).Find_procdef_bypara(writeprocdef.paras,writeprocdef.returndef,[cpo_allowdefaults]);
+ if not assigned(p.propaccesslist[palt_write].procdef) then
+ Message(parser_e_ill_property_access_sym);
+ end;
+ fieldvarsym :
+ begin
+ if not assigned(def) then
+ internalerror(200310072);
+ if compare_defs(def,p.propdef,nothingn)>=te_equal then
+ begin
+ { property parameters are allowed if this is
+ an indexed property, because the index is then
+ the parameter.
+ Note: In the help of Kylix it is written
+ that it isn't allowed, but the compiler accepts it (PFV) }
+ if (ppo_hasparameters in p.propoptions) or
+ ((sp_static in p.symoptions) <> (sp_static in sym.symoptions)) then
+ Message(parser_e_ill_property_access_sym);
+ end
+ else
+ IncompatibleTypes(def,p.propdef);
+ end;
+ else
+ Message(parser_e_ill_property_access_sym);
+ end;
+ end;
+ end;
+ end
+ else
+ parse_dispinterface(p,readprocdef,writeprocdef,paranr);
+
+ { stored is not allowed for dispinterfaces, records or class properties }
+ if assigned(astruct) and not(is_dispinterface(astruct) or is_record(astruct)) and not is_classproperty then
+ begin
+ { ppo_stored is default on for not overridden properties }
+ if not assigned(p.overriddenpropsym) then
+ include(p.propoptions,ppo_stored);
+ if try_to_consume(_STORED) then
+ begin
+ include(p.propoptions,ppo_stored);
+ p.propaccesslist[palt_stored].clear;
+ case token of
+ _ID:
+ begin
+ { in the case that idtoken=_DEFAULT }
+ { we have to do nothing except }
+ { setting ppo_stored, it's the same }
+ { as stored true }
+ if idtoken<>_DEFAULT then
+ begin
+ { parse_symlist cannot deal with constsyms, and
+ we also don't want to put constsyms in symlists
+ since they have to be evaluated immediately rather
+ than each time the property is accessed
+
+ The proper fix would be to always create a parse tree
+ and then convert that one, if appropriate, to a symlist.
+ Currently, we e.g. don't support any constant expressions
+ yet either here, while Delphi does.
+
+ }
+ { make sure we don't let constants mask class fields/
+ methods
+ }
+ if (not assigned(astruct) or
+ (search_struct_member(astruct,pattern)=nil)) and
+ searchsym(pattern,sym,srsymtable) and
+ (sym.typ = constsym) then
+ begin
+ addsymref(sym);
+ if not is_boolean(tconstsym(sym).constdef) then
+ Message(parser_e_stored_property_must_be_boolean)
+ else if (tconstsym(sym).value.valueord=0) then
+ { same as for _FALSE }
+ exclude(p.propoptions,ppo_stored)
+ else
+ { same as for _TRUE }
+ p.default:=longint($80000000);
+ consume(_ID);
+ end
+ else if parse_symlist(p.propaccesslist[palt_stored],def) then
+ begin
+ sym:=p.propaccesslist[palt_stored].firstsym^.sym;
+ case sym.typ of
+ procsym :
+ begin
+ { Create a temporary procvardef to handle parameters }
+ storedprocdef:=tprocvardef.create(normal_function_level);
+ include(storedprocdef.procoptions,po_methodpointer);
+ { Return type must be boolean }
+ storedprocdef.returndef:=pasbool8type;
+ { Add index parameter if needed }
+ if ppo_indexed in p.propoptions then
+ begin
+ hparavs:=tparavarsym.create('$index',10,vs_value,p.indexdef,[]);
+ storedprocdef.parast.insert(hparavs);
+ end;
+
+ { Insert hidden parameters }
+ handle_calling_convention(storedprocdef);
+ p.propaccesslist[palt_stored].procdef:=Tprocsym(sym).Find_procdef_bypara(storedprocdef.paras,storedprocdef.returndef,[cpo_allowdefaults,cpo_ignorehidden]);
+ if not assigned(p.propaccesslist[palt_stored].procdef) then
+ message(parser_e_ill_property_storage_sym);
+ { Not needed anymore }
+ storedprocdef.owner.deletedef(storedprocdef);
+ end;
+ fieldvarsym :
+ begin
+ if not assigned(def) then
+ internalerror(200310073);
+ if (ppo_hasparameters in p.propoptions) or
+ not(is_boolean(def)) then
+ Message(parser_e_stored_property_must_be_boolean);
+ end;
+ else
+ Message(parser_e_ill_property_access_sym);
+ end;
+ end;
+ end;
+ end;
+ _FALSE:
+ begin
+ consume(_FALSE);
+ exclude(p.propoptions,ppo_stored);
+ end;
+ _TRUE:
+ begin
+ p.default:=longint($80000000);
+ consume(_TRUE);
+ end;
+ end;
+ end;
+ end;
+ if not is_record(astruct) and try_to_consume(_DEFAULT) then
+ begin
+ if not allow_default_property(p) then
+ begin
+ Message(parser_e_property_cant_have_a_default_value);
+ { Error recovery }
+ pt:=comp_expr(true,false);
+ pt.free;
+ end
+ else
+ begin
+ { Get the result of the default, the firstpass is
+ needed to support values like -1 }
+ pt:=comp_expr(true,false);
+ if (p.propdef.typ=setdef) and
+ (pt.nodetype=arrayconstructorn) then
+ begin
+ arrayconstructor_to_set(pt);
+ do_typecheckpass(pt);
+ end;
+ inserttypeconv(pt,p.propdef);
+ if not(is_constnode(pt)) then
+ Message(parser_e_property_default_value_must_const);
+ { Set default value }
+ case pt.nodetype of
+ setconstn :
+ p.default:=plongint(tsetconstnode(pt).value_set)^;
+ ordconstn :
+ if (Tordconstnode(pt).value<int64(low(longint))) or
+ (Tordconstnode(pt).value>int64(high(cardinal))) then
+ message(parser_e_range_check_error)
+ else
+ p.default:=longint(tordconstnode(pt).value.svalue);
+ niln :
+ p.default:=0;
+ realconstn:
+ p.default:=longint(single(trealconstnode(pt).value_real));
+ end;
+ pt.free;
+ end;
+ end
+ else if not is_record(astruct) and try_to_consume(_NODEFAULT) then
+ begin
+ p.default:=longint($80000000);
+ end;
+(*
+ else {if allow_default_property(p) then
+ begin
+ p.default:=longint($80000000);
+ end;
+*)
+ { Parse possible "implements" keyword }
+ if not is_record(astruct) and try_to_consume(_IMPLEMENTS) then
+ repeat
+ single_type(def,[]);
+
+ if not(is_interface(def)) then
+ message(parser_e_class_implements_must_be_interface);
+
+ if is_interface(p.propdef) then
+ begin
+ { an interface type may delegate itself or one of its ancestors }
+ if not p.propdef.is_related(def) then
+ begin
+ message2(parser_e_implements_must_have_correct_type,def.typename,p.propdef.typename);
+ exit;
+ end;
+ end
+ else if is_class(p.propdef) then
+ begin
+ ImplIntf:=tobjectdef(p.propdef).find_implemented_interface(tobjectdef(def));
+ if assigned(ImplIntf) then
+ begin
+ if compare_defs(ImplIntf.IntfDef,def,nothingn)<te_equal then
+ begin
+ message2(parser_e_implements_must_have_correct_type,ImplIntf.IntfDef.typename,def.typename);
+ exit;
+ end;
+ end
+ else
+ begin
+ message2(parser_e_class_doesnt_implement_interface,p.propdef.typename,def.typename);
+ exit;
+ end;
+ end
+ else
+ begin
+ message(parser_e_implements_must_be_class_or_interface);
+ exit;
+ end;
+
+
+ if not assigned(p.propaccesslist[palt_read].firstsym) then
+ begin
+ message(parser_e_implements_must_read_specifier);
+ exit;
+ end;
+ if assigned(p.propaccesslist[palt_read].procdef) and
+ (tprocdef(p.propaccesslist[palt_read].procdef).proccalloption<>pocall_default) then
+ message(parser_e_implements_getter_not_default_cc);
+ if assigned(p.propaccesslist[palt_write].firstsym) then
+ begin
+ message(parser_e_implements_must_not_have_write_specifier);
+ exit;
+ end;
+ if assigned(p.propaccesslist[palt_stored].firstsym) then
+ begin
+ message(parser_e_implements_must_not_have_stored_specifier);
+ exit;
+ end;
+ found:=false;
+ for i:=0 to tobjectdef(astruct).ImplementedInterfaces.Count-1 do
+ begin
+ ImplIntf:=TImplementedInterface(tobjectdef(astruct).ImplementedInterfaces[i]);
+
+ if compare_defs(def,ImplIntf.IntfDef,nothingn)>=te_equal then
+ begin
+ found:=true;
+ break;
+ end;
+ end;
+ if found then
+ begin
+ { An interface may not be delegated by more than one property,
+ it also may not have method mappings. }
+ if Assigned(ImplIntf.ImplementsGetter) then
+ message1(parser_e_duplicate_implements_clause,ImplIntf.IntfDef.typename);
+ if Assigned(ImplIntf.NameMappings) then
+ message2(parser_e_mapping_no_implements,ImplIntf.IntfDef.typename,astruct.objrealname^);
+
+ ImplIntf.ImplementsGetter:=p;
+ ImplIntf.VtblImplIntf:=ImplIntf;
+ case p.propaccesslist[palt_read].firstsym^.sym.typ of
+ procsym :
+ begin
+ if (po_virtualmethod in tprocdef(p.propaccesslist[palt_read].procdef).procoptions) and
+ not is_objectpascal_helper(tprocdef(p.propaccesslist[palt_read].procdef).struct) then
+ ImplIntf.IType:=etVirtualMethodResult
+ else
+ ImplIntf.IType:=etStaticMethodResult;
+ end;
+ fieldvarsym :
+ begin
+ ImplIntf.IType:=etFieldValue;
+ { this must be done more sophisticated, here is also probably the wrong place }
+ ImplIntf.IOffset:=tfieldvarsym(p.propaccesslist[palt_read].firstsym^.sym).fieldoffset;
+ end
+ else
+ internalerror(200802161);
+ end;
+ if not is_interface(p.propdef) then
+ case ImplIntf.IType of
+ etVirtualMethodResult: ImplIntf.IType := etVirtualMethodClass;
+ etStaticMethodResult: ImplIntf.IType := etStaticMethodClass;
+ etFieldValue: ImplIntf.IType := etFieldValueClass;
+ else
+ internalerror(200912101);
+ end;
+ end
+ else
+ message1(parser_e_implements_uses_non_implemented_interface,def.typename);
+ until not try_to_consume(_COMMA);
+
+ { remove unneeded procdefs }
+ if readprocdef.proctypeoption<>potype_propgetter then
+ readprocdef.owner.deletedef(readprocdef);
+ if writeprocdef.proctypeoption<>potype_propsetter then
+ writeprocdef.owner.deletedef(writeprocdef);
+
+ result:=p;
+ end;
+
+
+ function maybe_parse_proc_directives(def:tdef):boolean;
+ var
+ newtype : ttypesym;
+ begin
+ result:=false;
+ { Process procvar directives before = and ; }
+ if (def.typ=procvardef) and
+ (def.typesym=nil) and
+ check_proc_directive(true) then
+ begin
+ newtype:=ttypesym.create('unnamed',def);
+ parse_var_proc_directives(tsym(newtype));
+ newtype.typedef:=nil;
+ def.typesym:=nil;
+ newtype.free;
+ result:=true;
+ end;
+ end;
+
+
+ const
+ variantrecordlevel : longint = 0;
+
+
+ procedure read_public_and_external_sc(sc:TFPObjectList);
+ var
+ vs: tabstractvarsym;
+ begin
+ { only allowed for one var }
+ vs:=tabstractvarsym(sc[0]);
+ if sc.count>1 then
+ Message(parser_e_absolute_only_one_var);
+ read_public_and_external(vs);
+ end;
+
+
+ procedure read_public_and_external(vs: tabstractvarsym);
+ var
+ is_dll,
+ is_cdecl,
+ is_external_var,
+ is_weak_external,
+ is_public_var : boolean;
+ dll_name,section_name,
+ C_name,mangledname : string;
+ begin
+ { only allowed for one var }
+ { only allow external and public on global symbols }
+ if vs.typ<>staticvarsym then
+ begin
+ Message(parser_e_no_local_var_external);
+ exit;
+ end;
+ { defaults }
+ is_dll:=false;
+ is_cdecl:=false;
+ is_external_var:=false;
+ is_public_var:=false;
+ section_name := '';
+ C_name:=vs.realname;
+
+ { macpas specific handling due to some switches}
+ if (m_mac in current_settings.modeswitches) then
+ begin
+ if (cs_external_var in current_settings.localswitches) then
+ begin {The effect of this is the same as if cvar; external; has been given as directives.}
+ is_cdecl:=true;
+ is_external_var:=true;
+ end
+ else if (cs_externally_visible in current_settings.localswitches) then
+ begin {The effect of this is the same as if cvar has been given as directives and it's made public.}
+ is_cdecl:=true;
+ is_public_var:=true;
+ end;
+ end;
+
+ { cdecl }
+ if try_to_consume(_CVAR) then
+ begin
+ consume(_SEMICOLON);
+ is_cdecl:=true;
+ end;
+
+ { external }
+ is_weak_external:=try_to_consume(_WEAKEXTERNAL);
+ if is_weak_external or
+ try_to_consume(_EXTERNAL) then
+ begin
+ is_external_var:=true;
+ if (idtoken<>_NAME) and (token<>_SEMICOLON) then
+ begin
+ is_dll:=true;
+ dll_name:=get_stringconst;
+ if ExtractFileExt(dll_name)='' then
+ dll_name:=ChangeFileExt(dll_name,target_info.sharedlibext);
+ end;
+ if not(is_cdecl) and try_to_consume(_NAME) then
+ C_name:=get_stringconst;
+ consume(_SEMICOLON);
+ end;
+
+ { export or public }
+ if idtoken in [_EXPORT,_PUBLIC] then
+ begin
+ consume(_ID);
+ if is_external_var then
+ Message(parser_e_not_external_and_export)
+ else
+ is_public_var:=true;
+ if try_to_consume(_NAME) then
+ C_name:=get_stringconst;
+ if (target_info.system in systems_allow_section_no_semicolon) and
+ (vs.typ=staticvarsym) and
+ try_to_consume (_SECTION) then
+ section_name:=get_stringconst;
+ consume(_SEMICOLON);
+ end;
+
+ { Windows uses an indirect reference using import tables }
+ if is_dll and
+ (target_info.system in systems_all_windows) then
+ include(vs.varoptions,vo_is_dll_var);
+
+ { This can only happen if vs.typ=staticvarsym }
+ if section_name<>'' then
+ begin
+ tstaticvarsym(vs).section:=section_name;
+ include(vs.varoptions,vo_has_section);
+ end;
+
+
+ { Add C _ prefix }
+ if is_cdecl or
+ (
+ is_dll and
+ (target_info.system in systems_darwin)
+ ) then
+ C_Name := target_info.Cprefix+C_Name;
+
+ if is_public_var then
+ begin
+ include(vs.varoptions,vo_is_public);
+ vs.varregable := vr_none;
+ { mark as referenced }
+ inc(vs.refs);
+ end;
+
+ mangledname:=C_name;
+ { now we can insert it in the import lib if its a dll, or
+ add it to the externals }
+ if is_external_var then
+ begin
+ if vo_is_typed_const in vs.varoptions then
+ Message(parser_e_initialized_not_for_external);
+ include(vs.varoptions,vo_is_external);
+ if (is_weak_external) then
+ begin
+ if not(target_info.system in systems_weak_linking) then
+ message(parser_e_weak_external_not_supported);
+ include(vs.varoptions,vo_is_weak_external);
+ end;
+ vs.varregable := vr_none;
+ if is_dll then
+ begin
+ if target_info.system in (systems_all_windows + systems_nativent +
+ [system_i386_emx, system_i386_os2]) then
+ mangledname:=make_dllmangledname(dll_name,C_name,0,pocall_none);
+
+ current_module.AddExternalImport(dll_name,C_Name,mangledname,0,true,false);
+ end
+ else
+ if tf_has_dllscanner in target_info.flags then
+ current_module.dllscannerinputlist.Add(vs.mangledname,vs);
+ end;
+
+ { Set the assembler name }
+ tstaticvarsym(vs).set_mangledname(mangledname);
+ end;
+
+
+ procedure try_consume_sectiondirective(var asection: ansistring);
+ begin
+ if idtoken=_SECTION then
+ begin
+ consume(_ID);
+ asection:=get_stringconst;
+ consume(_SEMICOLON);
+ end;
+ end;
+
+
+ procedure read_var_decls(options:Tvar_dec_options);
+
+ procedure read_default_value(sc : TFPObjectList);
+ var
+ vs : tabstractnormalvarsym;
+ tcsym : tstaticvarsym;
+ begin
+ vs:=tabstractnormalvarsym(sc[0]);
+ if sc.count>1 then
+ Message(parser_e_initialized_only_one_var);
+ if vo_is_thread_var in vs.varoptions then
+ Message(parser_e_initialized_not_for_threadvar);
+ consume(_EQ);
+ case vs.typ of
+ localvarsym :
+ begin
+ tcsym:=tstaticvarsym.create('$default'+vs.realname,vs_const,vs.vardef,[]);
+ include(tcsym.symoptions,sp_internal);
+ vs.defaultconstsym:=tcsym;
+ symtablestack.top.insert(tcsym);
+ read_typed_const(current_asmdata.asmlists[al_typedconsts],tcsym,false);
+ end;
+ staticvarsym :
+ begin
+ read_typed_const(current_asmdata.asmlists[al_typedconsts],tstaticvarsym(vs),false);
+ end;
+ else
+ internalerror(200611051);
+ end;
+ vs.varstate:=vs_initialised;
+ end;
+
+{$ifdef gpc_mode}
+ procedure read_gpc_name(sc : TFPObjectList);
+ var
+ vs : tabstractnormalvarsym;
+ C_Name : string;
+ begin
+ consume(_ID);
+ C_Name:=get_stringconst;
+ vs:=tabstractnormalvarsym(sc[0]);
+ if sc.count>1 then
+ Message(parser_e_absolute_only_one_var);
+ if vs.typ=staticvarsym then
+ begin
+ tstaticvarsym(vs).set_mangledname(C_Name);
+ include(vs.varoptions,vo_is_external);
+ end
+ else
+ Message(parser_e_no_local_var_external);
+ end;
+{$endif}
+
+ procedure read_absolute(sc : TFPObjectList);
+ var
+ vs : tabstractvarsym;
+ abssym : tabsolutevarsym;
+ pt,hp : tnode;
+ st : tsymtable;
+ {$ifdef i386}
+ tmpaddr : int64;
+ {$endif}
+ begin
+ abssym:=nil;
+ { only allowed for one var }
+ vs:=tabstractvarsym(sc[0]);
+ if sc.count>1 then
+ Message(parser_e_absolute_only_one_var);
+ if vo_is_typed_const in vs.varoptions then
+ Message(parser_e_initialized_not_for_external);
+ { parse the rest }
+ pt:=expr(true);
+ { check allowed absolute types }
+ if (pt.nodetype=stringconstn) or
+ (is_constcharnode(pt)) then
+ begin
+ abssym:=tabsolutevarsym.create(vs.realname,vs.vardef);
+ abssym.fileinfo:=vs.fileinfo;
+ if pt.nodetype=stringconstn then
+ abssym.asmname:=stringdup(strpas(tstringconstnode(pt).value_str))
+ else
+ abssym.asmname:=stringdup(chr(tordconstnode(pt).value.svalue));
+ consume(token);
+ abssym.abstyp:=toasm;
+ end
+ { address }
+ else if is_constintnode(pt) then
+ begin
+ abssym:=tabsolutevarsym.create(vs.realname,vs.vardef);
+ abssym.fileinfo:=vs.fileinfo;
+ abssym.abstyp:=toaddr;
+{$ifndef cpu64bitaddr}
+ { on 64 bit systems, abssym.addroffset is a qword and hence this
+ test is useless (value is a 64 bit entity) and will always fail
+ for positive values (since int64(high(abssym.addroffset))=-1
+ }
+ if (Tordconstnode(pt).value<int64(low(abssym.addroffset))) or
+ (Tordconstnode(pt).value>int64(high(abssym.addroffset))) then
+ message(parser_e_range_check_error)
+ else
+{$endif}
+ abssym.addroffset:=Tordconstnode(pt).value.svalue;
+{$ifdef i386}
+ abssym.absseg:=false;
+ if (target_info.system in [system_i386_go32v2,system_i386_watcom]) and
+ try_to_consume(_COLON) then
+ begin
+ pt.free;
+ pt:=expr(true);
+ if is_constintnode(pt) then
+ begin
+ tmpaddr:=abssym.addroffset shl 4+tordconstnode(pt).value.svalue;
+ if (tmpaddr<int64(low(abssym.addroffset))) or
+ (tmpaddr>int64(high(abssym.addroffset))) then
+ message(parser_e_range_check_error)
+ else
+ abssym.addroffset:=tmpaddr;
+ abssym.absseg:=true;
+ end
+ else
+ Message(type_e_ordinal_expr_expected);
+ end;
+{$endif i386}
+ end
+ { variable }
+ else
+ begin
+ { we have to be able to take the address of the absolute
+ expression
+ }
+ valid_for_addr(pt,true);
+ { remove subscriptn before checking for loadn }
+ hp:=pt;
+ while (hp.nodetype in [subscriptn,typeconvn,vecn]) do
+ begin
+ { check for implicit dereferencing and reject it }
+ if (hp.nodetype in [subscriptn,vecn]) then
+ begin
+ if (tunarynode(hp).left.resultdef.typ in [pointerdef,classrefdef]) then
+ break;
+ { catch, e.g., 'var b: char absolute pchar_var[5];"
+ (pchar_var[5] is a pchar_2_string typeconv ->
+ the vecn only sees an array of char)
+ I don't know if all of these type conversions are
+ possible, but they're definitely all bad.
+ }
+ if (tunarynode(hp).left.nodetype=typeconvn) and
+ (ttypeconvnode(tunarynode(hp).left).convtype in
+ [tc_pchar_2_string,tc_pointer_2_array,
+ tc_intf_2_string,tc_intf_2_guid,
+ tc_dynarray_2_variant,tc_interface_2_variant,
+ tc_array_2_dynarray]) then
+ break;
+
+ if (tunarynode(hp).left.resultdef.typ=stringdef) and
+ not(tstringdef(tunarynode(hp).left.resultdef).stringtype in [st_shortstring,st_longstring]) then
+ break;
+ if (tunarynode(hp).left.resultdef.typ=objectdef) and
+ (tobjectdef(tunarynode(hp).left.resultdef).objecttype<>odt_object) then
+ break;
+ if is_dynamic_array(tunarynode(hp).left.resultdef) then
+ break;
+ end;
+ hp:=tunarynode(hp).left;
+ end;
+ if (hp.nodetype=loadn) then
+ begin
+ { we should check the result type of loadn }
+ if not (tloadnode(hp).symtableentry.typ in [fieldvarsym,staticvarsym,localvarsym,paravarsym]) then
+ Message(parser_e_absolute_only_to_var_or_const);
+ abssym:=tabsolutevarsym.create(vs.realname,vs.vardef);
+ abssym.fileinfo:=vs.fileinfo;
+ abssym.abstyp:=tovar;
+ abssym.ref:=node_to_propaccesslist(pt);
+
+ { if the sizes are different, can't be a regvar since you }
+ { can't be "absolute upper 8 bits of a register" (except }
+ { if its a record field of the same size of a record }
+ { regvar, but in that case pt.resultdef.size will have }
+ { the same size since it refers to the field and not to }
+ { the whole record -- which is why we use pt and not hp) }
+
+ { we can't take the size of an open array }
+ if is_open_array(pt.resultdef) or
+ (vs.vardef.size <> pt.resultdef.size) then
+ make_not_regable(pt,[ra_addr_regable]);
+ end
+ else
+ Message(parser_e_absolute_only_to_var_or_const);
+ end;
+ pt.free;
+ { replace old varsym with the new absolutevarsym }
+ if assigned(abssym) then
+ begin
+ st:=vs.owner;
+ vs.owner.Delete(vs);
+ st.insert(abssym);
+ sc[0]:=abssym;
+ end;
+ end;
+
+ var
+ sc : TFPObjectList;
+ vs : tabstractvarsym;
+ hdef : tdef;
+ i : longint;
+ semicoloneaten,
+ allowdefaultvalue,
+ hasdefaultvalue : boolean;
+ hintsymoptions : tsymoptions;
+ deprecatedmsg : pshortstring;
+ old_block_type : tblock_type;
+ sectionname : ansistring;
+ begin
+ old_block_type:=block_type;
+ block_type:=bt_var;
+ { Force an expected ID error message }
+ if not (token in [_ID,_CASE,_END]) then
+ consume(_ID);
+ { read vars }
+ sc:=TFPObjectList.create(false);
+ while (token=_ID) do
+ begin
+ semicoloneaten:=false;
+ hasdefaultvalue:=false;
+ allowdefaultvalue:=true;
+ sc.clear;
+ repeat
+ if (token = _ID) then
+ begin
+ case symtablestack.top.symtabletype of
+ localsymtable :
+ vs:=tlocalvarsym.create(orgpattern,vs_value,generrordef,[]);
+ staticsymtable,
+ globalsymtable :
+ begin
+ vs:=tstaticvarsym.create(orgpattern,vs_value,generrordef,[]);
+ if vd_threadvar in options then
+ include(vs.varoptions,vo_is_thread_var);
+ end;
+ else
+ internalerror(200411064);
+ end;
+ sc.add(vs);
+ symtablestack.top.insert(vs);
+ end;
+ consume(_ID);
+ until not try_to_consume(_COMMA);
+
+ { read variable type def }
+ block_type:=bt_var_type;
+ consume(_COLON);
+
+{$ifdef gpc_mode}
+ if (m_gpc in current_settings.modeswitches) and
+ (token=_ID) and
+ (orgpattern='__asmname__') then
+ read_gpc_name(sc);
+{$endif}
+
+ read_anon_type(hdef,false);
+ for i:=0 to sc.count-1 do
+ begin
+ vs:=tabstractvarsym(sc[i]);
+ vs.vardef:=hdef;
+ end;
+ block_type:=bt_var;
+
+ { Process procvar directives }
+ if maybe_parse_proc_directives(hdef) then
+ semicoloneaten:=true;
+
+ { check for absolute }
+ if try_to_consume(_ABSOLUTE) then
+ begin
+ read_absolute(sc);
+ allowdefaultvalue:=false;
+ end;
+
+ { Check for EXTERNAL etc directives before a semicolon }
+ if (idtoken in [_EXPORT,_EXTERNAL,_WEAKEXTERNAL,_PUBLIC,_CVAR]) then
+ begin
+ read_public_and_external_sc(sc);
+ allowdefaultvalue:=false;
+ semicoloneaten:=true;
+ end;
+
+ { try to parse the hint directives }
+ hintsymoptions:=[];
+ deprecatedmsg:=nil;
+ try_consume_hintdirective(hintsymoptions,deprecatedmsg);
+ for i:=0 to sc.count-1 do
+ begin
+ vs:=tabstractvarsym(sc[i]);
+ vs.symoptions := vs.symoptions + hintsymoptions;
+ if deprecatedmsg<>nil then
+ vs.deprecatedmsg:=stringdup(deprecatedmsg^);
+ end;
+ stringdispose(deprecatedmsg);
+
+ { Handling of Delphi typed const = initialized vars }
+ if allowdefaultvalue and
+ (token=_EQ) and
+ not(m_tp7 in current_settings.modeswitches) and
+ (symtablestack.top.symtabletype<>parasymtable) then
+ begin
+ { Add calling convention for procvar }
+ if (hdef.typ=procvardef) and
+ (hdef.typesym=nil) then
+ handle_calling_convention(tprocvardef(hdef));
+ read_default_value(sc);
+ hasdefaultvalue:=true;
+ end
+ else
+ begin
+ if not(semicoloneaten) then
+ consume(_SEMICOLON);
+ end;
+
+ { Support calling convention for procvars after semicolon }
+ if not(hasdefaultvalue) and
+ (hdef.typ=procvardef) and
+ (hdef.typesym=nil) then
+ begin
+ { Parse procvar directives after ; }
+ maybe_parse_proc_directives(hdef);
+ { Add calling convention for procvar }
+ handle_calling_convention(tprocvardef(hdef));
+ { Handling of Delphi typed const = initialized vars }
+ if (token=_EQ) and
+ not(m_tp7 in current_settings.modeswitches) and
+ (symtablestack.top.symtabletype<>parasymtable) then
+ begin
+ read_default_value(sc);
+ hasdefaultvalue:=true;
+ end;
+ end;
+
+ { Check for EXTERNAL etc directives or, in macpas, if cs_external_var is set}
+ if (
+ (
+ (idtoken in [_EXPORT,_EXTERNAL,_WEAKEXTERNAL,_PUBLIC,_CVAR]) and
+ (m_cvar_support in current_settings.modeswitches)
+ ) or
+ (
+ (m_mac in current_settings.modeswitches) and
+ (
+ (cs_external_var in current_settings.localswitches) or
+ (cs_externally_visible in current_settings.localswitches)
+ )
+ )
+ ) then
+ read_public_and_external_sc(sc);
+
+ { try to parse a section directive }
+ if (target_info.system in systems_allow_section) and
+ (symtablestack.top.symtabletype in [staticsymtable,globalsymtable]) and
+ (idtoken=_SECTION) then
+ begin
+ try_consume_sectiondirective(sectionname);
+ if sectionname<>'' then
+ begin
+ for i:=0 to sc.count-1 do
+ begin
+ vs:=tabstractvarsym(sc[i]);
+ if (vs.varoptions *[vo_is_external,vo_is_weak_external])<>[] then
+ Message(parser_e_externals_no_section);
+ if vs.typ<>staticvarsym then
+ Message(parser_e_section_no_locals);
+ tstaticvarsym(vs).section:=sectionname;
+ include(vs.varoptions, vo_has_section);
+ end;
+ end;
+ end;
+
+ { allocate normal variable (non-external and non-typed-const) staticvarsyms }
+ for i:=0 to sc.count-1 do
+ begin
+ vs:=tabstractvarsym(sc[i]);
+ if (vs.typ=staticvarsym) and
+ not(vo_is_typed_const in vs.varoptions) and
+ not(vo_is_external in vs.varoptions) then
+ insertbssdata(tstaticvarsym(vs));
+ end;
+ end;
+ block_type:=old_block_type;
+ { free the list }
+ sc.free;
+ end;
+
+
+ procedure read_record_fields(options:Tvar_dec_options);
+ var
+ sc : TFPObjectList;
+ i : longint;
+ hs,sorg,static_name : string;
+ hdef,casetype : tdef;
+ { maxsize contains the max. size of a variant }
+ { startvarrec contains the start of the variant part of a record }
+ maxsize, startvarrecsize : longint;
+ usedalign,
+ maxalignment,startvarrecalign,
+ maxpadalign, startpadalign: shortint;
+ pt : tnode;
+ fieldvs : tfieldvarsym;
+ hstaticvs : tstaticvarsym;
+ vs : tabstractvarsym;
+ srsym : tsym;
+ srsymtable : TSymtable;
+ visibility : tvisibility;
+ recst : tabstractrecordsymtable;
+ recstlist : tfpobjectlist;
+ unionsymtable : trecordsymtable;
+ offset : longint;
+ uniondef : trecorddef;
+ hintsymoptions : tsymoptions;
+ deprecatedmsg : pshortstring;
+ semicoloneaten,
+ removeclassoption: boolean;
+{$if defined(powerpc) or defined(powerpc64)}
+ tempdef: tdef;
+ is_first_type: boolean;
+{$endif powerpc or powerpc64}
+ sl: tpropaccesslist;
+ old_block_type: tblock_type;
+ begin
+ old_block_type:=block_type;
+ block_type:=bt_var;
+ recst:=tabstractrecordsymtable(symtablestack.top);
+{$if defined(powerpc) or defined(powerpc64)}
+ is_first_type:=true;
+{$endif powerpc or powerpc64}
+ { Force an expected ID error message }
+ if not (token in [_ID,_CASE,_END]) then
+ consume(_ID);
+ { read vars }
+ sc:=TFPObjectList.create(false);
+ recstlist:=TFPObjectList.create(false);
+ removeclassoption:=false;
+ while (token=_ID) and
+ not(((vd_object in options) or
+ ((vd_record in options) and (m_advanced_records in current_settings.modeswitches))) and
+ (idtoken in [_PUBLIC,_PRIVATE,_PUBLISHED,_PROTECTED,_STRICT])) do
+ begin
+ visibility:=symtablestack.top.currentvisibility;
+ semicoloneaten:=false;
+ sc.clear;
+ repeat
+ sorg:=orgpattern;
+ if token=_ID then
+ begin
+ vs:=tfieldvarsym.create(sorg,vs_value,generrordef,[]);
+ sc.add(vs);
+ recst.insert(vs);
+ end;
+ consume(_ID);
+ until not try_to_consume(_COMMA);
+ if m_delphi in current_settings.modeswitches then
+ block_type:=bt_var_type
+ else
+ block_type:=old_block_type;
+ consume(_COLON);
+
+ { Don't search for types where they can't be:
+ types can be only in objects, classes and records.
+ This just speedup the search a bit. }
+ recstlist.count:=0;
+ if not is_class_or_object(tdef(recst.defowner)) and
+ not is_record(tdef(recst.defowner)) then
+ begin
+ recstlist.add(recst);
+ symtablestack.pop(recst);
+ end;
+ read_anon_type(hdef,false);
+ block_type:=bt_var;
+ { allow only static fields reference to struct where they are declared }
+ if not (vd_class in options) and
+ (is_object(hdef) or is_record(hdef)) and
+ is_owned_by(tabstractrecorddef(recst.defowner),tabstractrecorddef(hdef)) then
+ begin
+ Message1(type_e_type_is_not_completly_defined, tabstractrecorddef(hdef).RttiName);
+ { for error recovery or compiler will crash later }
+ hdef:=generrordef;
+ end;
+ { restore stack }
+ for i:=recstlist.count-1 downto 0 do
+ begin
+ recst:=tabstractrecordsymtable(recstlist[i]);
+ symtablestack.push(recst);
+ end;
+
+ { Process procvar directives }
+ if maybe_parse_proc_directives(hdef) then
+ semicoloneaten:=true;
+
+{$if defined(powerpc) or defined(powerpc64)}
+ { from gcc/gcc/config/rs6000/rs6000.h:
+ /* APPLE LOCAL begin Macintosh alignment 2002-1-22 ff */
+ /* Return the alignment of a struct based on the Macintosh PowerPC
+ alignment rules. In general the alignment of a struct is
+ determined by the greatest alignment of its elements. However, the
+ PowerPC rules cause the alignment of a struct to peg at word
+ alignment except when the first field has greater than word
+ (32-bit) alignment, in which case the alignment is determined by
+ the alignment of the first field. */
+ }
+ if (target_info.system in [system_powerpc_darwin, system_powerpc_macos, system_powerpc64_darwin]) and
+ is_first_type and
+ (symtablestack.top.symtabletype=recordsymtable) and
+ (trecordsymtable(symtablestack.top).usefieldalignment=C_alignment) then
+ begin
+ tempdef:=hdef;
+ while tempdef.typ=arraydef do
+ tempdef:=tarraydef(tempdef).elementdef;
+ if tempdef.typ<>recorddef then
+ maxpadalign:=tempdef.alignment
+ else
+ maxpadalign:=trecorddef(tempdef).padalignment;
+
+ if (maxpadalign>4) and
+ (maxpadalign>trecordsymtable(symtablestack.top).padalignment) then
+ trecordsymtable(symtablestack.top).padalignment:=maxpadalign;
+ is_first_type:=false;
+ end;
+{$endif powerpc or powerpc64}
+
+ { types that use init/final are not allowed in variant parts, but
+ classes are allowed }
+ if (variantrecordlevel>0) then
+ if is_managed_type(hdef) then
+ Message(parser_e_cant_use_inittable_here)
+ else
+ if hdef.typ=undefineddef then
+ Message(parser_e_cant_use_type_parameters_here);
+
+ { try to parse the hint directives }
+ hintsymoptions:=[];
+ deprecatedmsg:=nil;
+ try_consume_hintdirective(hintsymoptions,deprecatedmsg);
+
+ { update variable type and hints }
+ for i:=0 to sc.count-1 do
+ begin
+ fieldvs:=tfieldvarsym(sc[i]);
+ fieldvs.vardef:=hdef;
+ { insert any additional hint directives }
+ fieldvs.symoptions := fieldvs.symoptions + hintsymoptions;
+ if deprecatedmsg<>nil then
+ fieldvs.deprecatedmsg:=stringdup(deprecatedmsg^);
+ end;
+ stringdispose(deprecatedmsg);
+
+ { Records and objects can't have default values }
+ { for a record there doesn't need to be a ; before the END or ) }
+ if not(token in [_END,_RKLAMMER]) and
+ not(semicoloneaten) then
+ consume(_SEMICOLON);
+
+ { Parse procvar directives after ; }
+ maybe_parse_proc_directives(hdef);
+
+ { Add calling convention for procvar }
+ if (hdef.typ=procvardef) and
+ (hdef.typesym=nil) then
+ handle_calling_convention(tprocvardef(hdef));
+
+ { check if it is a class field }
+ if (vd_object in options) then
+ begin
+ { if it is not a class var section and token=STATIC then it is a class field too }
+ if not (vd_class in options) and try_to_consume(_STATIC) then
+ begin
+ consume(_SEMICOLON);
+ include(options,vd_class);
+ removeclassoption:=true;
+ end;
+ end;
+ if vd_class in options then
+ begin
+ { add static flag and staticvarsyms }
+ for i:=0 to sc.count-1 do
+ begin
+ fieldvs:=tfieldvarsym(sc[i]);
+ include(fieldvs.symoptions,sp_static);
+ { generate the symbol which reserves the space }
+ static_name:=lower(generate_nested_name(recst,'_'))+'_'+fieldvs.name;
+ hstaticvs:=tstaticvarsym.create('$_static_'+static_name,vs_value,hdef,[]);
+ include(hstaticvs.symoptions,sp_internal);
+ recst.get_unit_symtable.insert(hstaticvs);
+ insertbssdata(hstaticvs);
+ { generate the symbol for the access }
+ sl:=tpropaccesslist.create;
+ sl.addsym(sl_load,hstaticvs);
+ recst.insert(tabsolutevarsym.create_ref('$'+static_name,hdef,sl));
+ end;
+ if removeclassoption then
+ begin
+ exclude(options,vd_class);
+ removeclassoption:=false;
+ end;
+ end;
+ if (visibility=vis_published) and
+ not(is_class(hdef)) then
+ begin
+ MessagePos(tfieldvarsym(sc[0]).fileinfo,parser_e_cant_publish_that);
+ visibility:=vis_public;
+ end;
+
+ if (visibility=vis_published) and
+ not(oo_can_have_published in tobjectdef(hdef).objectoptions) and
+ not(m_delphi in current_settings.modeswitches) then
+ begin
+ MessagePos(tfieldvarsym(sc[0]).fileinfo,parser_e_only_publishable_classes_can_be_published);
+ visibility:=vis_public;
+ end;
+
+ { Generate field in the recordsymtable }
+ for i:=0 to sc.count-1 do
+ begin
+ fieldvs:=tfieldvarsym(sc[i]);
+ { static data fields are already inserted in the globalsymtable }
+ if not(sp_static in fieldvs.symoptions) then
+ recst.addfield(fieldvs,visibility);
+ end;
+ end;
+ recstlist.free;
+
+ if m_delphi in current_settings.modeswitches then
+ block_type:=bt_var_type
+ else
+ block_type:=old_block_type;
+ { Check for Case }
+ if (vd_record in options) and
+ try_to_consume(_CASE) then
+ begin
+ maxsize:=0;
+ maxalignment:=0;
+ maxpadalign:=0;
+ { including a field declaration? }
+ fieldvs:=nil;
+ sorg:=orgpattern;
+ hs:=pattern;
+ searchsym(hs,srsym,srsymtable);
+ if not(assigned(srsym) and (srsym.typ in [typesym,unitsym])) then
+ begin
+ consume(_ID);
+ consume(_COLON);
+ fieldvs:=tfieldvarsym.create(sorg,vs_value,generrordef,[]);
+ symtablestack.top.insert(fieldvs);
+ end;
+ read_anon_type(casetype,true);
+ block_type:=bt_var;
+ if assigned(fieldvs) then
+ begin
+ fieldvs.vardef:=casetype;
+ recst.addfield(fieldvs,recst.currentvisibility);
+ end;
+ if not(is_ordinal(casetype))
+{$ifndef cpu64bitaddr}
+ or is_64bitint(casetype)
+{$endif cpu64bitaddr}
+ then
+ Message(type_e_ordinal_expr_expected);
+ consume(_OF);
+
+ UnionSymtable:=trecordsymtable.create('',current_settings.packrecords);
+ UnionDef:=trecorddef.create('',unionsymtable);
+ uniondef.isunion:=true;
+ startvarrecsize:=UnionSymtable.datasize;
+ { align the bitpacking to the next byte }
+ UnionSymtable.datasize:=startvarrecsize;
+ startvarrecalign:=UnionSymtable.fieldalignment;
+ startpadalign:=Unionsymtable.padalignment;
+ symtablestack.push(UnionSymtable);
+ repeat
+ repeat
+ pt:=comp_expr(true,false);
+ if not(pt.nodetype=ordconstn) then
+ Message(parser_e_illegal_expression);
+ if try_to_consume(_POINTPOINT) then
+ pt:=crangenode.create(pt,comp_expr(true,false));
+ pt.free;
+ if token=_COMMA then
+ consume(_COMMA)
+ else
+ break;
+ until false;
+ if m_delphi in current_settings.modeswitches then
+ block_type:=bt_var_type
+ else
+ block_type:=old_block_type;
+ consume(_COLON);
+ { read the vars }
+ consume(_LKLAMMER);
+ inc(variantrecordlevel);
+ if token<>_RKLAMMER then
+ read_record_fields([vd_record]);
+ dec(variantrecordlevel);
+ consume(_RKLAMMER);
+ { calculates maximal variant size }
+ maxsize:=max(maxsize,unionsymtable.datasize);
+ maxalignment:=max(maxalignment,unionsymtable.fieldalignment);
+ maxpadalign:=max(maxpadalign,unionsymtable.padalignment);
+ { the items of the next variant are overlayed }
+ unionsymtable.datasize:=startvarrecsize;
+ unionsymtable.fieldalignment:=startvarrecalign;
+ unionsymtable.padalignment:=startpadalign;
+ if (token<>_END) and (token<>_RKLAMMER) then
+ consume(_SEMICOLON)
+ else
+ break;
+ until (token=_END) or (token=_RKLAMMER);
+ symtablestack.pop(UnionSymtable);
+ { at last set the record size to that of the biggest variant }
+ unionsymtable.datasize:=maxsize;
+ unionsymtable.fieldalignment:=maxalignment;
+ unionsymtable.addalignmentpadding;
+{$if defined(powerpc) or defined(powerpc64)}
+ { parent inherits the alignment padding if the variant is the first "field" of the parent record/variant }
+ if (target_info.system in [system_powerpc_darwin, system_powerpc_macos, system_powerpc64_darwin]) and
+ is_first_type and
+ (recst.usefieldalignment=C_alignment) and
+ (maxpadalign>recst.padalignment) then
+ recst.padalignment:=maxpadalign;
+{$endif powerpc or powerpc64}
+ { Align the offset where the union symtable is added }
+ case recst.usefieldalignment of
+ { allow the unionsymtable to be aligned however it wants }
+ { (within the global min/max limits) }
+ 0, { default }
+ C_alignment:
+ usedalign:=used_align(unionsymtable.recordalignment,current_settings.alignment.recordalignmin,current_settings.alignment.maxCrecordalign);
+ { 1 byte alignment if we are bitpacked }
+ bit_alignment:
+ usedalign:=1;
+ mac68k_alignment:
+ usedalign:=2;
+ { otherwise alignment at the packrecords alignment of the }
+ { current record }
+ else
+ usedalign:=used_align(recst.fieldalignment,current_settings.alignment.recordalignmin,current_settings.alignment.recordalignmax);
+ end;
+ offset:=align(recst.datasize,usedalign);
+ recst.datasize:=offset+unionsymtable.datasize;
+
+ if unionsymtable.recordalignment>recst.fieldalignment then
+ recst.fieldalignment:=unionsymtable.recordalignment;
+
+ trecordsymtable(recst).insertunionst(Unionsymtable,offset);
+ uniondef.owner.deletedef(uniondef);
+ end;
+ { free the list }
+ sc.free;
+{$ifdef powerpc}
+ is_first_type := false;
+{$endif powerpc}
+ block_type:=old_block_type;
+ end;
+
+end.
diff --git a/closures/compiler/pexports.pas b/closures/compiler/pexports.pas
new file mode 100644
index 0000000000..4b6d45eb33
--- /dev/null
+++ b/closures/compiler/pexports.pas
@@ -0,0 +1,249 @@
+{
+ Copyright (c) 1998-2005 by Florian Klaempfl
+
+ This unit handles the exports parsing
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit pexports;
+
+{$i fpcdefs.inc}
+
+interface
+
+ { reads an exports statement in a library }
+ procedure read_exports;
+
+implementation
+
+ uses
+ { common }
+ cutils,
+ { global }
+ globals,globtype,tokens,verbose,constexp,
+ systems,
+ ppu,fmodule,
+ { symtable }
+ symconst,symbase,symdef,symtype,symsym,
+ { pass 1 }
+ node,
+ ncon,
+ { parser }
+ scanner,
+ pbase,pexpr,
+ { obj-c }
+ objcutil,
+ { link }
+ gendef,export
+ ;
+
+
+ procedure read_exports;
+ var
+ orgs,
+ DefString,
+ InternalProcName : string;
+ pd : tprocdef;
+ pt : tnode;
+ srsym : tsym;
+ srsymtable : TSymtable;
+ hpname : shortstring;
+ index : longint;
+ options : word;
+
+ function IsGreater(hp1,hp2:texported_item):boolean;
+ var
+ i2 : boolean;
+ begin
+ i2:=(hp2.options and eo_index)<>0;
+ if (hp1.options and eo_index)<>0 then
+ begin
+ if i2 then
+ IsGreater:=hp1.index>hp2.index
+ else
+ IsGreater:=false;
+ end
+ else
+ IsGreater:=i2;
+ end;
+
+ begin
+ current_module.flags:=current_module.flags or uf_has_exports;
+ DefString:='';
+ InternalProcName:='';
+ consume(_EXPORTS);
+ repeat
+ hpname:='';
+ options:=0;
+ index:=0;
+ if token=_ID then
+ begin
+ consume_sym_orgid(srsym,srsymtable,orgs);
+ { orgpattern is still valid here }
+ InternalProcName:='';
+ case srsym.typ of
+ staticvarsym :
+ InternalProcName:=tstaticvarsym(srsym).mangledname;
+ procsym :
+ begin
+ pd:=tprocdef(tprocsym(srsym).ProcdefList[0]);
+ if (Tprocsym(srsym).ProcdefList.Count>1) or
+ (po_kylixlocal in pd.procoptions) or
+ ((tf_need_export in target_info.flags) and
+ not(po_exports in pd.procoptions)) then
+ Message(parser_e_illegal_symbol_exported)
+ else
+ InternalProcName:=pd.mangledname;
+ end;
+ typesym :
+ begin
+ if not is_objcclass(ttypesym(srsym).typedef) then
+ Message(parser_e_illegal_symbol_exported)
+ end;
+ else
+ Message(parser_e_illegal_symbol_exported)
+ end;
+ if (srsym.typ<>typesym) then
+ begin
+ if InternalProcName<>'' then
+ begin
+ { This is wrong if the first is not
+ an underline }
+ if InternalProcName[1]='_' then
+ delete(InternalProcName,1,1)
+ else if (target_info.system in [system_i386_win32,system_i386_wdosx,system_arm_wince,system_i386_wince]) and UseDeffileForExports then
+ begin
+ Message(parser_e_dlltool_unit_var_problem);
+ Message(parser_e_dlltool_unit_var_problem2);
+ end;
+ if length(InternalProcName)<2 then
+ Message(parser_e_procname_to_short_for_export);
+ DefString:=srsym.realname+'='+InternalProcName;
+ end;
+ if try_to_consume(_INDEX) then
+ begin
+ pt:=comp_expr(true,false);
+ if pt.nodetype=ordconstn then
+ if (Tordconstnode(pt).value<int64(low(index))) or
+ (Tordconstnode(pt).value>int64(high(index))) then
+ begin
+ index:=0;
+ message(parser_e_range_check_error)
+ end
+ else
+ index:=Tordconstnode(pt).value.svalue
+ else
+ begin
+ index:=0;
+ consume(_INTCONST);
+ end;
+ options:=options or eo_index;
+ pt.free;
+ if target_info.system in [system_i386_win32,system_i386_wdosx,system_arm_wince,system_i386_wince] then
+ DefString:=srsym.realname+'='+InternalProcName+' @ '+tostr(index)
+ else
+ DefString:=srsym.realname+'='+InternalProcName; {Index ignored!}
+ end;
+ if try_to_consume(_NAME) then
+ begin
+ pt:=comp_expr(true,false);
+ if pt.nodetype=stringconstn then
+ hpname:=strpas(tstringconstnode(pt).value_str)
+ else
+ consume(_CSTRING);
+ options:=options or eo_name;
+ pt.free;
+ DefString:=hpname+'='+InternalProcName;
+ end;
+ if try_to_consume(_RESIDENT) then
+ begin
+ options:=options or eo_resident;
+ DefString:=srsym.realname+'='+InternalProcName;{Resident ignored!}
+ end;
+ if (DefString<>'') and UseDeffileForExports then
+ DefFile.AddExport(DefString);
+ end;
+ case srsym.typ of
+ procsym:
+ begin
+ { if no specific name or index was given, then if }
+ { the procedure has aliases defined export those, }
+ { otherwise export the name as it appears in the }
+ { export section (it doesn't make sense to export }
+ { the generic mangled name, because the name of }
+ { the parent unit is used in that) }
+ if ((options and (eo_name or eo_index))=0) and
+ (tprocdef(tprocsym(srsym).procdeflist[0]).aliasnames.count>1) then
+ exportallprocsymnames(tprocsym(srsym),options)
+ else
+ begin
+ { there's a name or an index -> export only one name }
+ { correct? Or can you export multiple names with the }
+ { same index? And/or should we also export the aliases }
+ { if a name is specified? (JM) }
+
+ if ((options and eo_name)=0) then
+ { Export names are not mangled on Windows and OS/2 }
+ if (target_info.system in (systems_all_windows+[system_i386_emx, system_i386_os2])) then
+ hpname:=orgs
+ { Use set mangled name in case of cdecl/cppdecl/mwpascal }
+ { and no name specified }
+ else if (tprocdef(tprocsym(srsym).procdeflist[0]).proccalloption in [pocall_cdecl,pocall_mwpascal]) then
+ hpname:=target_info.cprefix+tprocsym(srsym).realname
+ else if (tprocdef(tprocsym(srsym).procdeflist[0]).proccalloption in [pocall_cppdecl]) then
+ hpname:=target_info.cprefix+tprocdef(tprocsym(srsym).procdeflist[0]).cplusplusmangledname
+ else
+ hpname:=orgs;
+
+ exportprocsym(srsym,hpname,index,options);
+ end
+ end;
+ staticvarsym:
+ begin
+ if ((options and eo_name)=0) then
+ { for "cvar" }
+ if (vo_has_mangledname in tstaticvarsym(srsym).varoptions) then
+ hpname:=srsym.mangledname
+ else
+ hpname:=orgs;
+ exportvarsym(srsym,hpname,index,options);
+ end;
+ typesym:
+ begin
+ case ttypesym(srsym).typedef.typ of
+ objectdef:
+ case tobjectdef(ttypesym(srsym).typedef).objecttype of
+ odt_objcclass:
+ exportobjcclass(tobjectdef(ttypesym(srsym).typedef));
+ else
+ internalerror(2009092601);
+ end;
+ else
+ internalerror(2009092602);
+ end;
+ end;
+ end
+ end
+ else
+ consume(_ID);
+ until not try_to_consume(_COMMA);
+ consume(_SEMICOLON);
+ if not DefFile.empty then
+ DefFile.writefile;
+ end;
+
+end.
diff --git a/closures/compiler/pexpr.pas b/closures/compiler/pexpr.pas
new file mode 100644
index 0000000000..98002d8b10
--- /dev/null
+++ b/closures/compiler/pexpr.pas
@@ -0,0 +1,3430 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Does parsing of expression for Free Pascal
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit pexpr;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ symtype,symdef,symbase,
+ node,ncal,
+ tokens,globtype,globals,constexp;
+
+ { reads a whole expression }
+ function expr(dotypecheck:boolean) : tnode;
+
+ { reads an expression without assignements and .. }
+ function comp_expr(accept_equal,typeonly:boolean):tnode;
+
+ { reads a single factor }
+ function factor(getaddr,typeonly:boolean) : tnode;
+
+ procedure string_dec(var def: tdef; allowtypedef: boolean);
+
+ function parse_paras(__colon,__namedpara : boolean;end_of_paras : ttoken) : tnode;
+
+ { the ID token has to be consumed before calling this function }
+ procedure do_member_read(structh:tabstractrecorddef;getaddr:boolean;sym:tsym;var p1:tnode;var again:boolean;callflags:tcallnodeflags);
+
+ function get_intconst:TConstExprInt;
+ function get_stringconst:string;
+
+ { Does some postprocessing for a generic type (especially when nested types
+ of the specialization are used) }
+ procedure post_comp_expr_gendef(var def: tdef);
+
+implementation
+
+ uses
+ { common }
+ cutils,
+ { global }
+ verbose,
+ systems,widestr,
+ { symtable }
+ symconst,symtable,symsym,defutil,defcmp,
+ { module }
+ fmodule,ppu,
+ { pass 1 }
+ pass_1,htypechk,
+ nmat,nadd,nmem,nset,ncnv,ninl,ncon,nld,nflw,nbas,nutils,
+ { parser }
+ scanner,
+ pbase,pinline,ptype,pgenutil,
+ { codegen }
+ cgbase,procinfo,cpuinfo
+ ;
+
+ { sub_expr(opmultiply) is need to get -1 ** 4 to be
+ read as - (1**4) and not (-1)**4 PM }
+ type
+ Toperator_precedence=(opcompare,opaddition,opmultiply,oppower);
+
+ const
+ highest_precedence = oppower;
+
+ function sub_expr(pred_level:Toperator_precedence;accept_equal,typeonly:boolean;factornode:tnode):tnode;forward;
+
+ const
+ { true, if the inherited call is anonymous }
+ anon_inherited : boolean = false;
+ { last def found, only used by anon. inherited calls to insert proper type casts }
+ srdef : tdef = nil;
+
+ procedure string_dec(var def:tdef; allowtypedef: boolean);
+ { reads a string type with optional length }
+ { and returns a pointer to the string }
+ { definition }
+ var
+ p : tnode;
+ begin
+ def:=cshortstringtype;
+ consume(_STRING);
+ if token=_LECKKLAMMER then
+ begin
+ if not(allowtypedef) then
+ Message(parser_e_no_local_para_def);
+ consume(_LECKKLAMMER);
+ p:=comp_expr(true,false);
+ if not is_constintnode(p) then
+ begin
+ Message(parser_e_illegal_expression);
+ { error recovery }
+ consume(_RECKKLAMMER);
+ end
+ else
+ begin
+ if (tordconstnode(p).value<=0) then
+ begin
+ Message(parser_e_invalid_string_size);
+ tordconstnode(p).value:=255;
+ end;
+ if tordconstnode(p).value>255 then
+ begin
+ { longstring is currently unsupported (CEC)! }
+{ t:=tstringdef.createlong(tordconstnode(p).value))}
+ Message(parser_e_invalid_string_size);
+ tordconstnode(p).value:=255;
+ def:=tstringdef.createshort(int64(tordconstnode(p).value));
+ end
+ else
+ if tordconstnode(p).value<>255 then
+ def:=tstringdef.createshort(int64(tordconstnode(p).value));
+ consume(_RECKKLAMMER);
+ end;
+ p.free;
+ end
+ else
+ begin
+ if cs_ansistrings in current_settings.localswitches then
+ def:=getansistringdef
+ else
+ def:=cshortstringtype;
+ end;
+ end;
+
+
+ function parse_paras(__colon,__namedpara : boolean;end_of_paras : ttoken) : tnode;
+ var
+ p1,p2,argname : tnode;
+ prev_in_args,
+ old_named_args_allowed,
+ old_allow_array_constructor : boolean;
+ begin
+ if token=end_of_paras then
+ begin
+ parse_paras:=nil;
+ exit;
+ end;
+ { save old values }
+ prev_in_args:=in_args;
+ old_allow_array_constructor:=allow_array_constructor;
+ old_named_args_allowed:=named_args_allowed;
+ { set para parsing values }
+ in_args:=true;
+ named_args_allowed:=false;
+ allow_array_constructor:=true;
+ p2:=nil;
+ repeat
+ if __namedpara then
+ begin
+ if token=_COMMA then
+ begin
+ { empty parameter }
+ p2:=ccallparanode.create(cnothingnode.create,p2);
+ end
+ else
+ begin
+ named_args_allowed:=true;
+ p1:=comp_expr(true,false);
+ named_args_allowed:=false;
+ if found_arg_name then
+ begin
+ argname:=p1;
+ p1:=comp_expr(true,false);
+ p2:=ccallparanode.create(p1,p2);
+ tcallparanode(p2).parametername:=argname;
+ end
+ else
+ p2:=ccallparanode.create(p1,p2);
+ found_arg_name:=false;
+ end;
+ end
+ else
+ begin
+ p1:=comp_expr(true,false);
+ p2:=ccallparanode.create(p1,p2);
+ end;
+ { it's for the str(l:5,s); }
+ if __colon and (token=_COLON) then
+ begin
+ consume(_COLON);
+ p1:=comp_expr(true,false);
+ p2:=ccallparanode.create(p1,p2);
+ include(tcallparanode(p2).callparaflags,cpf_is_colon_para);
+ if try_to_consume(_COLON) then
+ begin
+ p1:=comp_expr(true,false);
+ p2:=ccallparanode.create(p1,p2);
+ include(tcallparanode(p2).callparaflags,cpf_is_colon_para);
+ end
+ end;
+ until not try_to_consume(_COMMA);
+ allow_array_constructor:=old_allow_array_constructor;
+ in_args:=prev_in_args;
+ named_args_allowed:=old_named_args_allowed;
+ parse_paras:=p2;
+ end;
+
+
+ function gen_c_style_operator(ntyp:tnodetype;p1,p2:tnode) : tnode;
+ var
+ hp : tnode;
+ hdef : tdef;
+ temp : ttempcreatenode;
+ newstatement : tstatementnode;
+ begin
+ { Properties are not allowed, because the write can
+ be different from the read }
+ if (nf_isproperty in p1.flags) then
+ begin
+ Message(type_e_variable_id_expected);
+ { We can continue with the loading,
+ it'll not create errors. Only the expected
+ result can be wrong }
+ end;
+
+ hp:=p1;
+ while assigned(hp) and
+ (hp.nodetype in [derefn,subscriptn,vecn,typeconvn]) do
+ hp:=tunarynode(hp).left;
+ if not assigned(hp) then
+ internalerror(200410121);
+ if (hp.nodetype=calln) then
+ begin
+ typecheckpass(p1);
+ result:=internalstatements(newstatement);
+ hdef:=tpointerdef.create(p1.resultdef);
+ temp:=ctempcreatenode.create(hdef,sizeof(pint),tt_persistent,false);
+ addstatement(newstatement,temp);
+ addstatement(newstatement,cassignmentnode.create(ctemprefnode.create(temp),caddrnode.create_internal(p1)));
+ addstatement(newstatement,cassignmentnode.create(
+ cderefnode.create(ctemprefnode.create(temp)),
+ caddnode.create(ntyp,
+ cderefnode.create(ctemprefnode.create(temp)),
+ p2)));
+ addstatement(newstatement,ctempdeletenode.create(temp));
+ end
+ else
+ result:=cassignmentnode.create(p1,caddnode.create(ntyp,p1.getcopy,p2));
+ end;
+
+
+ function statement_syssym(l : byte) : tnode;
+ var
+ p1,p2,paras : tnode;
+ err,
+ prev_in_args : boolean;
+ begin
+ prev_in_args:=in_args;
+ case l of
+
+ in_new_x :
+ begin
+ if afterassignment or in_args then
+ statement_syssym:=new_function
+ else
+ statement_syssym:=new_dispose_statement(true);
+ end;
+
+ in_dispose_x :
+ begin
+ statement_syssym:=new_dispose_statement(false);
+ end;
+
+ in_ord_x :
+ begin
+ consume(_LKLAMMER);
+ in_args:=true;
+ p1:=comp_expr(true,false);
+ consume(_RKLAMMER);
+ p1:=geninlinenode(in_ord_x,false,p1);
+ statement_syssym := p1;
+ end;
+
+ in_exit :
+ begin
+ if try_to_consume(_LKLAMMER) then
+ begin
+ if not (m_mac in current_settings.modeswitches) then
+ begin
+ if not(try_to_consume(_RKLAMMER)) then
+ begin
+ p1:=comp_expr(true,false);
+ consume(_RKLAMMER);
+ if (not assigned(current_procinfo) or
+ is_void(current_procinfo.procdef.returndef)) then
+ begin
+ Message(parser_e_void_function);
+ { recovery }
+ p1.free;
+ p1:=nil;
+ end;
+ end
+ else
+ p1:=nil;
+ end
+ else
+ begin
+ if not (current_procinfo.procdef.procsym.name = pattern) then
+ Message(parser_e_macpas_exit_wrong_param);
+ consume(_ID);
+ consume(_RKLAMMER);
+ p1:=nil;
+ end
+ end
+ else
+ p1:=nil;
+ statement_syssym:=cexitnode.create(p1);
+ end;
+
+ in_break :
+ begin
+ statement_syssym:=cbreaknode.create
+ end;
+
+ in_continue :
+ begin
+ statement_syssym:=ccontinuenode.create
+ end;
+
+ in_leave :
+ begin
+ if m_mac in current_settings.modeswitches then
+ statement_syssym:=cbreaknode.create
+ else
+ begin
+ Message1(sym_e_id_not_found, orgpattern);
+ statement_syssym:=cerrornode.create;
+ end;
+ end;
+
+ in_cycle :
+ begin
+ if m_mac in current_settings.modeswitches then
+ statement_syssym:=ccontinuenode.create
+ else
+ begin
+ Message1(sym_e_id_not_found, orgpattern);
+ statement_syssym:=cerrornode.create;
+ end;
+ end;
+
+ in_typeof_x :
+ begin
+ consume(_LKLAMMER);
+ in_args:=true;
+ p1:=comp_expr(true,false);
+ consume(_RKLAMMER);
+ if p1.nodetype=typen then
+ ttypenode(p1).allowed:=true;
+ { Allow classrefdef, which is required for
+ Typeof(self) in static class methods }
+ if not(is_objc_class_or_protocol(p1.resultdef)) and
+ ((p1.resultdef.typ = objectdef) or
+ (assigned(current_procinfo) and
+ ((po_classmethod in current_procinfo.procdef.procoptions) or
+ (po_staticmethod in current_procinfo.procdef.procoptions)) and
+ (p1.resultdef.typ=classrefdef))) then
+ statement_syssym:=geninlinenode(in_typeof_x,false,p1)
+ else
+ begin
+ Message(parser_e_class_id_expected);
+ p1.destroy;
+ statement_syssym:=cerrornode.create;
+ end;
+ end;
+
+ in_sizeof_x,
+ in_bitsizeof_x :
+ begin
+ consume(_LKLAMMER);
+ in_args:=true;
+ p1:=comp_expr(true,false);
+ consume(_RKLAMMER);
+ if ((p1.nodetype<>typen) and
+
+ (
+ (is_object(p1.resultdef) and
+ (oo_has_constructor in tobjectdef(p1.resultdef).objectoptions)) or
+ is_open_array(p1.resultdef) or
+ is_array_of_const(p1.resultdef) or
+ is_open_string(p1.resultdef)
+ )) or
+ { keep the function call if it is a type parameter to avoid arithmetic errors due to constant folding }
+ (p1.resultdef.typ=undefineddef) then
+ begin
+ statement_syssym:=geninlinenode(in_sizeof_x,false,p1);
+ { no packed bit support for these things }
+ if (l = in_bitsizeof_x) then
+ statement_syssym:=caddnode.create(muln,statement_syssym,cordconstnode.create(8,sinttype,true));
+ end
+ else
+ begin
+ { allow helpers for SizeOf and BitSizeOf }
+ if p1.nodetype=typen then
+ ttypenode(p1).helperallowed:=true;
+ if (p1.resultdef.typ=forwarddef) then
+ Message1(type_e_type_is_not_completly_defined,tforwarddef(p1.resultdef).tosymname^);
+ if (l = in_sizeof_x) or
+ (not((p1.nodetype = vecn) and
+ is_packed_array(tvecnode(p1).left.resultdef)) and
+ not((p1.nodetype = subscriptn) and
+ is_packed_record_or_object(tsubscriptnode(p1).left.resultdef))) then
+ begin
+ statement_syssym:=cordconstnode.create(p1.resultdef.size,sinttype,true);
+ if (l = in_bitsizeof_x) then
+ statement_syssym:=caddnode.create(muln,statement_syssym,cordconstnode.create(8,sinttype,true));
+ end
+ else
+ statement_syssym:=cordconstnode.create(p1.resultdef.packedbitsize,sinttype,true);
+ { p1 not needed !}
+ p1.destroy;
+ end;
+ end;
+
+ in_typeinfo_x,
+ in_objc_encode_x :
+ begin
+ if (l=in_typeinfo_x) or
+ (m_objectivec1 in current_settings.modeswitches) then
+ begin
+ consume(_LKLAMMER);
+ in_args:=true;
+ p1:=comp_expr(true,false);
+ { When reading a class type it is parsed as loadvmtaddrn,
+ typeinfo only needs the type so we remove the loadvmtaddrn }
+ if p1.nodetype=loadvmtaddrn then
+ begin
+ p2:=tloadvmtaddrnode(p1).left;
+ tloadvmtaddrnode(p1).left:=nil;
+ p1.free;
+ p1:=p2;
+ end;
+ if p1.nodetype=typen then
+ begin
+ ttypenode(p1).allowed:=true;
+ { allow helpers for TypeInfo }
+ if l=in_typeinfo_x then
+ ttypenode(p1).helperallowed:=true;
+ end;
+ { else
+ begin
+ p1.destroy;
+ p1:=cerrornode.create;
+ Message(parser_e_illegal_parameter_list);
+ end;}
+ consume(_RKLAMMER);
+ p2:=geninlinenode(l,false,p1);
+ statement_syssym:=p2;
+ end
+ else
+ begin
+ Message1(sym_e_id_not_found, orgpattern);
+ statement_syssym:=cerrornode.create;
+ end;
+ end;
+
+ in_unaligned_x :
+ begin
+ err:=false;
+ consume(_LKLAMMER);
+ in_args:=true;
+ p1:=comp_expr(true,false);
+ p2:=ccallparanode.create(p1,nil);
+ p2:=geninlinenode(in_unaligned_x,false,p2);
+ consume(_RKLAMMER);
+ statement_syssym:=p2;
+ end;
+
+ in_assigned_x :
+ begin
+ err:=false;
+ consume(_LKLAMMER);
+ in_args:=true;
+ p1:=comp_expr(true,false);
+ { When reading a class type it is parsed as loadvmtaddrn,
+ typeinfo only needs the type so we remove the loadvmtaddrn }
+ if p1.nodetype=loadvmtaddrn then
+ begin
+ p2:=tloadvmtaddrnode(p1).left;
+ tloadvmtaddrnode(p1).left:=nil;
+ p1.free;
+ p1:=p2;
+ end;
+ if not codegenerror then
+ begin
+ case p1.resultdef.typ of
+ procdef, { procvar }
+ pointerdef,
+ procvardef,
+ classrefdef : ;
+ objectdef :
+ if not is_implicit_pointer_object_type(p1.resultdef) then
+ begin
+ Message(parser_e_illegal_parameter_list);
+ err:=true;
+ end;
+ arraydef :
+ if not is_dynamic_array(p1.resultdef) then
+ begin
+ Message(parser_e_illegal_parameter_list);
+ err:=true;
+ end;
+ else
+ if p1.resultdef.typ<>undefineddef then
+ begin
+ Message(parser_e_illegal_parameter_list);
+ err:=true;
+ end;
+ end;
+ end
+ else
+ err:=true;
+ if not err then
+ begin
+ p2:=ccallparanode.create(p1,nil);
+ p2:=geninlinenode(in_assigned_x,false,p2);
+ end
+ else
+ begin
+ p1.free;
+ p2:=cerrornode.create;
+ end;
+ consume(_RKLAMMER);
+ statement_syssym:=p2;
+ end;
+
+ in_addr_x :
+ begin
+ consume(_LKLAMMER);
+ in_args:=true;
+ p1:=comp_expr(true,false);
+ p1:=caddrnode.create(p1);
+ consume(_RKLAMMER);
+ statement_syssym:=p1;
+ end;
+
+ in_ofs_x :
+ begin
+ consume(_LKLAMMER);
+ in_args:=true;
+ p1:=comp_expr(true,false);
+ p1:=caddrnode.create(p1);
+ do_typecheckpass(p1);
+ { Ofs() returns a cardinal/qword, not a pointer }
+ p1.resultdef:=uinttype;
+ consume(_RKLAMMER);
+ statement_syssym:=p1;
+ end;
+
+ in_seg_x :
+ begin
+ consume(_LKLAMMER);
+ in_args:=true;
+ p1:=comp_expr(true,false);
+ p1:=geninlinenode(in_seg_x,false,p1);
+ consume(_RKLAMMER);
+ statement_syssym:=p1;
+ end;
+
+ in_high_x,
+ in_low_x :
+ begin
+ consume(_LKLAMMER);
+ in_args:=true;
+ p1:=comp_expr(true,false);
+ p2:=geninlinenode(l,false,p1);
+ consume(_RKLAMMER);
+ statement_syssym:=p2;
+ end;
+
+ in_succ_x,
+ in_pred_x :
+ begin
+ consume(_LKLAMMER);
+ in_args:=true;
+ p1:=comp_expr(true,false);
+ p2:=geninlinenode(l,false,p1);
+ consume(_RKLAMMER);
+ statement_syssym:=p2;
+ end;
+
+ in_inc_x,
+ in_dec_x :
+ begin
+ consume(_LKLAMMER);
+ in_args:=true;
+ p1:=comp_expr(true,false);
+ if try_to_consume(_COMMA) then
+ p2:=ccallparanode.create(comp_expr(true,false),nil)
+ else
+ p2:=nil;
+ p2:=ccallparanode.create(p1,p2);
+ statement_syssym:=geninlinenode(l,false,p2);
+ consume(_RKLAMMER);
+ end;
+
+ in_slice_x:
+ begin
+ if not(in_args) then
+ begin
+ message(parser_e_illegal_slice);
+ consume(_LKLAMMER);
+ in_args:=true;
+ comp_expr(true,false).free;
+ if try_to_consume(_COMMA) then
+ comp_expr(true,false).free;
+ statement_syssym:=cerrornode.create;
+ consume(_RKLAMMER);
+ end
+ else
+ begin
+ consume(_LKLAMMER);
+ in_args:=true;
+ p1:=comp_expr(true,false);
+ Consume(_COMMA);
+ if not(codegenerror) then
+ p2:=ccallparanode.create(comp_expr(true,false),nil)
+ else
+ p2:=cerrornode.create;
+ p2:=ccallparanode.create(p1,p2);
+ statement_syssym:=geninlinenode(l,false,p2);
+ consume(_RKLAMMER);
+ end;
+ end;
+
+ in_initialize_x:
+ begin
+ statement_syssym:=inline_initialize;
+ end;
+
+ in_finalize_x:
+ begin
+ statement_syssym:=inline_finalize;
+ end;
+
+ in_copy_x:
+ begin
+ statement_syssym:=inline_copy;
+ end;
+
+ in_concat_x :
+ begin
+ consume(_LKLAMMER);
+ in_args:=true;
+ { Translate to x:=x+y[+z]. The addnode will do the
+ type checking }
+ p2:=nil;
+ repeat
+ p1:=comp_expr(true,false);
+ if p2<>nil then
+ p2:=caddnode.create(addn,p2,p1)
+ else
+ begin
+ { Force string type if it isn't yet }
+ if not(
+ (p1.resultdef.typ=stringdef) or
+ is_chararray(p1.resultdef) or
+ is_char(p1.resultdef)
+ ) then
+ inserttypeconv(p1,cshortstringtype);
+ p2:=p1;
+ end;
+ until not try_to_consume(_COMMA);
+ consume(_RKLAMMER);
+ statement_syssym:=p2;
+ end;
+
+ in_read_x,
+ in_readln_x,
+ in_readstr_x:
+ begin
+ if try_to_consume(_LKLAMMER) then
+ begin
+ paras:=parse_paras(false,false,_RKLAMMER);
+ consume(_RKLAMMER);
+ end
+ else
+ paras:=nil;
+ p1:=geninlinenode(l,false,paras);
+ statement_syssym := p1;
+ end;
+
+ in_setlength_x:
+ begin
+ statement_syssym := inline_setlength;
+ end;
+
+ in_objc_selector_x:
+ begin
+ if (m_objectivec1 in current_settings.modeswitches) then
+ begin
+ consume(_LKLAMMER);
+ in_args:=true;
+ { don't turn procsyms into calls (getaddr = true) }
+ p1:=factor(true,false);
+ p2:=geninlinenode(l,false,p1);
+ consume(_RKLAMMER);
+ statement_syssym:=p2;
+ end
+ else
+ begin
+ Message1(sym_e_id_not_found, orgpattern);
+ statement_syssym:=cerrornode.create;
+ end;
+ end;
+ in_length_x:
+ begin
+ consume(_LKLAMMER);
+ in_args:=true;
+ p1:=comp_expr(true,false);
+ p2:=geninlinenode(l,false,p1);
+ consume(_RKLAMMER);
+ statement_syssym:=p2;
+ end;
+
+ in_write_x,
+ in_writeln_x,
+ in_writestr_x :
+ begin
+ if try_to_consume(_LKLAMMER) then
+ begin
+ paras:=parse_paras(true,false,_RKLAMMER);
+ consume(_RKLAMMER);
+ end
+ else
+ paras:=nil;
+ p1 := geninlinenode(l,false,paras);
+ statement_syssym := p1;
+ end;
+
+ in_str_x_string :
+ begin
+ consume(_LKLAMMER);
+ paras:=parse_paras(true,false,_RKLAMMER);
+ consume(_RKLAMMER);
+ p1 := geninlinenode(l,false,paras);
+ statement_syssym := p1;
+ end;
+
+ in_val_x:
+ Begin
+ consume(_LKLAMMER);
+ in_args := true;
+ p1:= ccallparanode.create(comp_expr(true,false), nil);
+ consume(_COMMA);
+ p2 := ccallparanode.create(comp_expr(true,false),p1);
+ if try_to_consume(_COMMA) then
+ p2 := ccallparanode.create(comp_expr(true,false),p2);
+ consume(_RKLAMMER);
+ p2 := geninlinenode(l,false,p2);
+ statement_syssym := p2;
+ End;
+
+ in_include_x_y,
+ in_exclude_x_y :
+ begin
+ consume(_LKLAMMER);
+ in_args:=true;
+ p1:=comp_expr(true,false);
+ consume(_COMMA);
+ p2:=comp_expr(true,false);
+ statement_syssym:=geninlinenode(l,false,ccallparanode.create(p1,ccallparanode.create(p2,nil)));
+ consume(_RKLAMMER);
+ end;
+
+ in_pack_x_y_z,
+ in_unpack_x_y_z :
+ begin
+ consume(_LKLAMMER);
+ in_args:=true;
+ p1:=comp_expr(true,false);
+ consume(_COMMA);
+ p2:=comp_expr(true,false);
+ consume(_COMMA);
+ paras:=comp_expr(true,false);
+ statement_syssym:=geninlinenode(l,false,ccallparanode.create(p1,ccallparanode.create(p2,ccallparanode.create(paras,nil))));
+ consume(_RKLAMMER);
+ end;
+
+ in_assert_x_y :
+ begin
+ consume(_LKLAMMER);
+ in_args:=true;
+ p1:=comp_expr(true,false);
+ if try_to_consume(_COMMA) then
+ p2:=comp_expr(true,false)
+ else
+ begin
+ { then insert an empty string }
+ p2:=cstringconstnode.createstr('');
+ end;
+ statement_syssym:=geninlinenode(l,false,ccallparanode.create(p1,ccallparanode.create(p2,nil)));
+ consume(_RKLAMMER);
+ end;
+ in_get_frame:
+ begin
+ statement_syssym:=geninlinenode(l,false,nil);
+ end;
+(*
+ in_get_caller_frame:
+ begin
+ if try_to_consume(_LKLAMMER) then
+ begin
+ {You used to call get_caller_frame as get_caller_frame(get_frame),
+ however, as a stack frame may not exist, it does more harm than
+ good, so ignore it.}
+ in_args:=true;
+ p1:=comp_expr(true,false);
+ p1.destroy;
+ consume(_RKLAMMER);
+ end;
+ statement_syssym:=geninlinenode(l,false,nil);
+ end;
+*)
+ else
+ internalerror(15);
+
+ end;
+ in_args:=prev_in_args;
+ end;
+
+
+ function maybe_load_methodpointer(st:TSymtable;var p1:tnode):boolean;
+ begin
+ maybe_load_methodpointer:=false;
+ if not assigned(p1) then
+ begin
+ case st.symtabletype of
+ withsymtable :
+ begin
+ if (st.defowner.typ=objectdef) then
+ p1:=tnode(twithsymtable(st).withrefnode).getcopy;
+ end;
+ ObjectSymtable,
+ recordsymtable:
+ begin
+ { We are calling from the static class method which has no self node }
+ if assigned(current_procinfo) and current_procinfo.procdef.no_self_node then
+ p1:=cloadvmtaddrnode.create(ctypenode.create(current_procinfo.procdef.struct))
+ else
+ p1:=load_self_node;
+ { We are calling a member }
+ maybe_load_methodpointer:=true;
+ end;
+ end;
+ end;
+ end;
+
+
+ { reads the parameter for a subroutine call }
+ procedure do_proc_call(sym:tsym;st:TSymtable;obj:tabstractrecorddef;getaddr:boolean;var again : boolean;var p1:tnode;callflags:tcallnodeflags);
+ var
+ membercall,
+ prevafterassn : boolean;
+ i : integer;
+ para,p2 : tnode;
+ currpara : tparavarsym;
+ aprocdef : tprocdef;
+ begin
+ prevafterassn:=afterassignment;
+ afterassignment:=false;
+ membercall:=false;
+ aprocdef:=nil;
+
+ { when it is a call to a member we need to load the
+ methodpointer first
+ }
+ membercall:=maybe_load_methodpointer(st,p1);
+
+ { When we are expecting a procvar we also need
+ to get the address in some cases }
+ if assigned(getprocvardef) then
+ begin
+ if (block_type=bt_const) or
+ getaddr then
+ begin
+ aprocdef:=Tprocsym(sym).Find_procdef_byprocvardef(getprocvardef);
+ getaddr:=true;
+ end
+ else
+ if ((m_tp_procvar in current_settings.modeswitches) or
+ (m_mac_procvar in current_settings.modeswitches)) and
+ not(token in [_CARET,_POINT,_LKLAMMER]) then
+ begin
+ aprocdef:=Tprocsym(sym).Find_procdef_byprocvardef(getprocvardef);
+ if assigned(aprocdef) then
+ getaddr:=true;
+ end;
+ end;
+
+ { only need to get the address of the procedure? }
+ if getaddr then
+ begin
+ { Retrieve info which procvar to call. For tp_procvar the
+ aprocdef is already loaded above so we can reuse it }
+ if not assigned(aprocdef) and
+ assigned(getprocvardef) then
+ aprocdef:=Tprocsym(sym).Find_procdef_byprocvardef(getprocvardef);
+
+ { generate a methodcallnode or proccallnode }
+ { we shouldn't convert things like @tcollection.load }
+ p2:=cloadnode.create_procvar(sym,aprocdef,st);
+ if assigned(p1) then
+ begin
+ { for loading methodpointer of an inherited function
+ we use self as instance and load the address of
+ the function directly and not through the vmt (PFV) }
+ if (cnf_inherited in callflags) then
+ begin
+ include(tloadnode(p2).loadnodeflags,loadnf_inherited);
+ p1.free;
+ p1:=load_self_node;
+ end;
+ if (p1.nodetype<>typen) then
+ tloadnode(p2).set_mp(p1)
+ else
+ p1.free;
+ end;
+ p1:=p2;
+
+ { no postfix operators }
+ again:=false;
+ end
+ else
+ begin
+ para:=nil;
+ if anon_inherited then
+ begin
+ if not assigned(current_procinfo) then
+ internalerror(200305054);
+ for i:=0 to current_procinfo.procdef.paras.count-1 do
+ begin
+ currpara:=tparavarsym(current_procinfo.procdef.paras[i]);
+ if not(vo_is_hidden_para in currpara.varoptions) then
+ begin
+ { inheritance by msgint? }
+ if assigned(srdef) then
+ { anonymous inherited via msgid calls only require a var parameter for
+ both methods, so we need some type casting here }
+ para:=ccallparanode.create(ctypeconvnode.create_internal(ctypeconvnode.create_internal(
+ cloadnode.create(currpara,currpara.owner),cformaltype),tparavarsym(tprocdef(srdef).paras[i]).vardef),
+ para)
+ else
+ para:=ccallparanode.create(cloadnode.create(currpara,currpara.owner),para);
+ end;
+ end;
+ end
+ else
+ begin
+ if try_to_consume(_LKLAMMER) then
+ begin
+ para:=parse_paras(false,false,_RKLAMMER);
+ consume(_RKLAMMER);
+ end;
+ end;
+ { indicate if this call was generated by a member and
+ no explicit self is used, this is needed to determine
+ how to handle a destructor call (PFV) }
+ if membercall then
+ include(callflags,cnf_member_call);
+ if assigned(obj) then
+ begin
+ if not (st.symtabletype in [ObjectSymtable,recordsymtable]) then
+ internalerror(200310031);
+ p1:=ccallnode.create(para,tprocsym(sym),obj.symtable,p1,callflags);
+ end
+ else
+ p1:=ccallnode.create(para,tprocsym(sym),st,p1,callflags);
+ end;
+ afterassignment:=prevafterassn;
+ end;
+
+
+ procedure handle_procvar(pv : tprocvardef;var p2 : tnode);
+ var
+ hp,hp2 : tnode;
+ hpp : ^tnode;
+ currprocdef : tprocdef;
+ begin
+ if not assigned(pv) then
+ internalerror(200301121);
+ if (m_tp_procvar in current_settings.modeswitches) or
+ (m_mac_procvar in current_settings.modeswitches) then
+ begin
+ hp:=p2;
+ hpp:=@p2;
+ while assigned(hp) and
+ (hp.nodetype=typeconvn) do
+ begin
+ hp:=ttypeconvnode(hp).left;
+ { save orignal address of the old tree so we can replace the node }
+ hpp:=@hp;
+ end;
+ if (hp.nodetype=calln) and
+ { a procvar can't have parameters! }
+ not assigned(tcallnode(hp).left) then
+ begin
+ currprocdef:=tcallnode(hp).symtableprocentry.Find_procdef_byprocvardef(pv);
+ if assigned(currprocdef) then
+ begin
+ hp2:=cloadnode.create_procvar(tprocsym(tcallnode(hp).symtableprocentry),currprocdef,tcallnode(hp).symtableproc);
+ if (po_methodpointer in pv.procoptions) then
+ tloadnode(hp2).set_mp(tcallnode(hp).methodpointer.getcopy);
+ hp.destroy;
+ { replace the old callnode with the new loadnode }
+ hpp^:=hp2;
+ end;
+ end;
+ end;
+ end;
+
+
+ { checks whether sym is a static field and if so, translates the access
+ to the appropriate node tree }
+ function handle_staticfield_access(sym: tsym; nested: boolean; var p1: tnode): boolean;
+ var
+ static_name: shortstring;
+ srsymtable: tsymtable;
+ begin
+ result:=false;
+ { generate access code }
+ if (sp_static in sym.symoptions) then
+ begin
+ result:=true;
+ if not nested then
+ static_name:=lower(sym.owner.name^)+'_'+sym.name
+ else
+ static_name:=lower(generate_nested_name(sym.owner,'_'))+'_'+sym.name;
+ if sym.owner.defowner.typ=objectdef then
+ searchsym_in_class(tobjectdef(sym.owner.defowner),tobjectdef(sym.owner.defowner),static_name,sym,srsymtable,true)
+ else
+ searchsym_in_record(trecorddef(sym.owner.defowner),static_name,sym,srsymtable);
+ if assigned(sym) then
+ check_hints(sym,sym.symoptions,sym.deprecatedmsg);
+ p1.free;
+ p1:=nil;
+ { static syms are always stored as absolutevarsym to handle scope and storage properly }
+ propaccesslist_to_node(p1,nil,tabsolutevarsym(sym).ref);
+ end;
+ end;
+
+
+ { the following procedure handles the access to a property symbol }
+ procedure handle_propertysym(propsym : tpropertysym;st : TSymtable;var p1 : tnode);
+ var
+ paras : tnode;
+ p2 : tnode;
+ membercall : boolean;
+ callflags : tcallnodeflags;
+ propaccesslist : tpropaccesslist;
+ sym: tsym;
+ begin
+ { property parameters? read them only if the property really }
+ { has parameters }
+ paras:=nil;
+ if (ppo_hasparameters in propsym.propoptions) then
+ begin
+ if try_to_consume(_LECKKLAMMER) then
+ begin
+ paras:=parse_paras(false,false,_RECKKLAMMER);
+ consume(_RECKKLAMMER);
+ end;
+ end;
+ { indexed property }
+ if (ppo_indexed in propsym.propoptions) then
+ begin
+ p2:=cordconstnode.create(propsym.index,propsym.indexdef,true);
+ paras:=ccallparanode.create(p2,paras);
+ end;
+ { we need only a write property if a := follows }
+ { if not(afterassignment) and not(in_args) then }
+ if token=_ASSIGNMENT then
+ begin
+ if getpropaccesslist(propsym,palt_write,propaccesslist) then
+ begin
+ sym:=propaccesslist.firstsym^.sym;
+ case sym.typ of
+ procsym :
+ begin
+ callflags:=[];
+ { generate the method call }
+ membercall:=maybe_load_methodpointer(st,p1);
+ if membercall then
+ include(callflags,cnf_member_call);
+ p1:=ccallnode.create(paras,tprocsym(sym),st,p1,callflags);
+ addsymref(sym);
+ paras:=nil;
+ consume(_ASSIGNMENT);
+ { read the expression }
+ if propsym.propdef.typ=procvardef then
+ getprocvardef:=tprocvardef(propsym.propdef);
+ p2:=comp_expr(true,false);
+ if assigned(getprocvardef) then
+ handle_procvar(getprocvardef,p2);
+ tcallnode(p1).left:=ccallparanode.create(p2,tcallnode(p1).left);
+ { mark as property, both the tcallnode and the real call block }
+ include(p1.flags,nf_isproperty);
+ getprocvardef:=nil;
+ end;
+ fieldvarsym :
+ begin
+ { generate access code }
+ if not handle_staticfield_access(sym,false,p1) then
+ propaccesslist_to_node(p1,st,propaccesslist);
+ include(p1.flags,nf_isproperty);
+ consume(_ASSIGNMENT);
+ { read the expression }
+ p2:=comp_expr(true,false);
+ p1:=cassignmentnode.create(p1,p2);
+ end
+ else
+ begin
+ p1:=cerrornode.create;
+ Message(parser_e_no_procedure_to_access_property);
+ end;
+ end;
+ end
+ else
+ begin
+ p1:=cerrornode.create;
+ Message(parser_e_no_procedure_to_access_property);
+ end;
+ end
+ else
+ begin
+ if getpropaccesslist(propsym,palt_read,propaccesslist) then
+ begin
+ sym := propaccesslist.firstsym^.sym;
+ case sym.typ of
+ fieldvarsym :
+ begin
+ { generate access code }
+ if not handle_staticfield_access(sym,false,p1) then
+ propaccesslist_to_node(p1,st,propaccesslist);
+ include(p1.flags,nf_isproperty);
+ end;
+ procsym :
+ begin
+ callflags:=[];
+ { generate the method call }
+ membercall:=maybe_load_methodpointer(st,p1);
+ if membercall then
+ include(callflags,cnf_member_call);
+ p1:=ccallnode.create(paras,tprocsym(sym),st,p1,callflags);
+ paras:=nil;
+ include(p1.flags,nf_isproperty);
+ end
+ else
+ begin
+ p1:=cerrornode.create;
+ Message(type_e_mismatch);
+ end;
+ end;
+ end
+ else
+ begin
+ { error, no function to read property }
+ p1:=cerrornode.create;
+ Message(parser_e_no_procedure_to_access_property);
+ end;
+ end;
+ { release paras if not used }
+ if assigned(paras) then
+ paras.free;
+ end;
+
+
+ { the ID token has to be consumed before calling this function }
+ procedure do_member_read(structh:tabstractrecorddef;getaddr:boolean;sym:tsym;var p1:tnode;var again:boolean;callflags:tcallnodeflags);
+ var
+ isclassref:boolean;
+ begin
+ if sym=nil then
+ begin
+ { pattern is still valid unless
+ there is another ID just after the ID of sym }
+ Message1(sym_e_id_no_member,orgpattern);
+ p1.free;
+ p1:=cerrornode.create;
+ { try to clean up }
+ again:=false;
+ end
+ else
+ begin
+ if assigned(p1) then
+ begin
+ if not assigned(p1.resultdef) then
+ do_typecheckpass(p1);
+ isclassref:=(p1.resultdef.typ=classrefdef);
+ end
+ else
+ isclassref:=false;
+
+ { we assume, that only procsyms and varsyms are in an object }
+ { symbol table, for classes, properties are allowed }
+ case sym.typ of
+ procsym:
+ begin
+ do_proc_call(sym,sym.owner,structh,
+ (getaddr and not(token in [_CARET,_POINT])),
+ again,p1,callflags);
+ { we need to know which procedure is called }
+ do_typecheckpass(p1);
+ { calling using classref? }
+ if isclassref and
+ (p1.nodetype=calln) and
+ assigned(tcallnode(p1).procdefinition) and
+ not(po_classmethod in tcallnode(p1).procdefinition.procoptions) and
+ not(tcallnode(p1).procdefinition.proctypeoption=potype_constructor) then
+ Message(parser_e_only_class_members_via_class_ref);
+ end;
+ fieldvarsym:
+ begin
+ if not handle_staticfield_access(sym,true,p1) then
+ begin
+ if isclassref then
+ if assigned(p1) and
+ (
+ is_self_node(p1) or
+ (assigned(current_procinfo) and (current_procinfo.procdef.no_self_node) and
+ (current_procinfo.procdef.struct=structh))) then
+ Message(parser_e_only_class_members)
+ else
+ Message(parser_e_only_class_members_via_class_ref);
+ p1:=csubscriptnode.create(sym,p1);
+ end;
+ end;
+ propertysym:
+ begin
+ if isclassref and not (sp_static in sym.symoptions) then
+ Message(parser_e_only_class_members_via_class_ref);
+ handle_propertysym(tpropertysym(sym),sym.owner,p1);
+ end;
+ typesym:
+ begin
+ p1.free;
+ if try_to_consume(_LKLAMMER) then
+ begin
+ p1:=comp_expr(true,false);
+ consume(_RKLAMMER);
+ p1:=ctypeconvnode.create_explicit(p1,ttypesym(sym).typedef);
+ end
+ else
+ begin
+ p1:=ctypenode.create(ttypesym(sym).typedef);
+ if (is_class(ttypesym(sym).typedef) or is_objcclass(ttypesym(sym).typedef)) and
+ not(block_type in [bt_type,bt_const_type,bt_var_type]) then
+ p1:=cloadvmtaddrnode.create(p1);
+ end;
+ end;
+ constsym:
+ begin
+ p1.free;
+ p1:=genconstsymtree(tconstsym(sym));
+ end;
+ staticvarsym:
+ begin
+ { typed constant is a staticvarsym
+ now they are absolutevarsym }
+ p1.free;
+ p1:=cloadnode.create(sym,sym.Owner);
+ end;
+ absolutevarsym:
+ begin
+ p1.free;
+ p1:=nil;
+ { typed constants are absolutebarsyms now to handle storage properly }
+ propaccesslist_to_node(p1,nil,tabsolutevarsym(sym).ref);
+ end
+ else
+ internalerror(16);
+ end;
+ end;
+ end;
+
+ function handle_factor_typenode(hdef:tdef;getaddr:boolean;var again:boolean;sym:tsym;typeonly:boolean):tnode;
+ var
+ srsym : tsym;
+ srsymtable : tsymtable;
+ begin
+ if sym=nil then
+ sym:=hdef.typesym;
+ { allow Ordinal(Value) for type declarations since it
+ can be an enummeration declaration or a set lke:
+ (OrdinalType(const1)..OrdinalType(const2) }
+ if (not typeonly or is_ordinal(hdef))and try_to_consume(_LKLAMMER) then
+ begin
+ result:=comp_expr(true,false);
+ consume(_RKLAMMER);
+ { type casts to class helpers aren't allowed }
+ if is_objectpascal_helper(hdef) then
+ Message(parser_e_no_category_as_types)
+ { recovery by not creating a conversion node }
+ else
+ result:=ctypeconvnode.create_explicit(result,hdef);
+ end
+ else { not LKLAMMER }
+ if (token=_POINT) and
+ (is_object(hdef) or is_record(hdef)) then
+ begin
+ consume(_POINT);
+ { handles calling methods declared in parent objects
+ using "parentobject.methodname()" }
+ if assigned(current_structdef) and
+ not(getaddr) and
+ current_structdef.is_related(hdef) then
+ begin
+ result:=ctypenode.create(hdef);
+ ttypenode(result).typesym:=sym;
+ { search also in inherited methods }
+ searchsym_in_class(tobjectdef(hdef),tobjectdef(current_structdef),pattern,srsym,srsymtable,true);
+ if assigned(srsym) then
+ check_hints(srsym,srsym.symoptions,srsym.deprecatedmsg);
+ consume(_ID);
+ do_member_read(tabstractrecorddef(hdef),false,srsym,result,again,[]);
+ end
+ else
+ begin
+ { handles:
+ * @TObject.Load
+ * static methods and variables }
+ result:=ctypenode.create(hdef);
+ ttypenode(result).typesym:=sym;
+ { TP allows also @TMenu.Load if Load is only }
+ { defined in an anchestor class }
+ srsym:=search_struct_member(tabstractrecorddef(hdef),pattern);
+ if assigned(srsym) then
+ begin
+ check_hints(srsym,srsym.symoptions,srsym.deprecatedmsg);
+ consume(_ID);
+ do_member_read(tabstractrecorddef(hdef),getaddr,srsym,result,again,[]);
+ end
+ else
+ Message1(sym_e_id_no_member,orgpattern);
+ end;
+ end
+ else
+ begin
+ { Normally here would be the check against the usage
+ of "TClassHelper.Something", but as that might be
+ used inside of system symbols like sizeof and
+ typeinfo this check is put into ttypenode.pass_1
+ (for "TClassHelper" alone) and tcallnode.pass_1
+ (for "TClassHelper.Something") }
+ { class reference ? }
+ if is_class(hdef) or
+ is_objcclass(hdef) then
+ begin
+ if getaddr and (token=_POINT) then
+ begin
+ consume(_POINT);
+ { allows @Object.Method }
+ { also allows static methods and variables }
+ result:=ctypenode.create(hdef);
+ ttypenode(result).typesym:=sym;
+ { TP allows also @TMenu.Load if Load is only }
+ { defined in an anchestor class }
+ srsym:=search_struct_member(tobjectdef(hdef),pattern);
+ if assigned(srsym) then
+ begin
+ check_hints(srsym,srsym.symoptions,srsym.deprecatedmsg);
+ consume(_ID);
+ do_member_read(tabstractrecorddef(hdef),getaddr,srsym,result,again,[]);
+ end
+ else
+ begin
+ Message1(sym_e_id_no_member,orgpattern);
+ consume(_ID);
+ end;
+ end
+ else
+ begin
+ result:=ctypenode.create(hdef);
+ ttypenode(result).typesym:=sym;
+ { For a type block we simply return only
+ the type. For all other blocks we return
+ a loadvmt node }
+ if not(block_type in [bt_type,bt_const_type,bt_var_type]) then
+ result:=cloadvmtaddrnode.create(result);
+ end;
+ end
+ else
+ begin
+ result:=ctypenode.create(hdef);
+ ttypenode(result).typesym:=sym;
+ end;
+ end;
+ end;
+
+{****************************************************************************
+ Factor
+****************************************************************************}
+
+
+{---------------------------------------------
+ PostFixOperators
+---------------------------------------------}
+
+ { returns whether or not p1 has been changed }
+ function postfixoperators(var p1:tnode;var again:boolean;getaddr:boolean): boolean;
+
+ { tries to avoid syntax errors after invalid qualifiers }
+ procedure recoverconsume_postfixops;
+ begin
+ repeat
+ if not try_to_consume(_CARET) then
+ if try_to_consume(_POINT) then
+ try_to_consume(_ID)
+ else if try_to_consume(_LECKKLAMMER) then
+ begin
+ repeat
+ comp_expr(true,false);
+ until not try_to_consume(_COMMA);
+ consume(_RECKKLAMMER);
+ end
+ else if try_to_consume(_LKLAMMER) then
+ begin
+ repeat
+ comp_expr(true,false);
+ until not try_to_consume(_COMMA);
+ consume(_RKLAMMER);
+ end
+ else
+ break;
+ until false;
+ end;
+
+
+ procedure handle_variantarray;
+ var
+ p4 : tnode;
+ newstatement : tstatementnode;
+ tempresultvariant,
+ temp : ttempcreatenode;
+ paras : tcallparanode;
+ newblock : tnode;
+ countindices : aint;
+ begin
+ { create statements with call initialize the arguments and
+ call fpc_dynarr_setlength }
+ newblock:=internalstatements(newstatement);
+
+ { get temp for array of indicies,
+ we set the real size later }
+ temp:=ctempcreatenode.create(s32inttype,4,tt_persistent,false);
+ addstatement(newstatement,temp);
+
+ countindices:=0;
+ repeat
+ p4:=comp_expr(true,false);
+
+ addstatement(newstatement,cassignmentnode.create(
+ ctemprefnode.create_offset(temp,countindices*s32inttype.size),p4));
+ inc(countindices);
+ until not try_to_consume(_COMMA);
+
+ { set real size }
+ temp.size:=countindices*s32inttype.size;
+
+ consume(_RECKKLAMMER);
+
+ { we need only a write access if a := follows }
+ if token=_ASSIGNMENT then
+ begin
+ consume(_ASSIGNMENT);
+ p4:=comp_expr(true,false);
+
+ { create call to fpc_vararray_put }
+ paras:=ccallparanode.create(cordconstnode.create
+ (countindices,s32inttype,true),
+ ccallparanode.create(caddrnode.create_internal
+ (ctemprefnode.create(temp)),
+ ccallparanode.create(ctypeconvnode.create_internal(p4,cvarianttype),
+ ccallparanode.create(ctypeconvnode.create_internal(p1,cvarianttype)
+ ,nil))));
+
+ addstatement(newstatement,ccallnode.createintern('fpc_vararray_put',paras));
+ addstatement(newstatement,ctempdeletenode.create(temp));
+ end
+ else
+ begin
+ { create temp for result }
+ tempresultvariant:=ctempcreatenode.create(cvarianttype,cvarianttype.size,tt_persistent,true);
+ addstatement(newstatement,tempresultvariant);
+
+ { create call to fpc_vararray_get }
+ paras:=ccallparanode.create(cordconstnode.create
+ (countindices,s32inttype,true),
+ ccallparanode.create(caddrnode.create_internal
+ (ctemprefnode.create(temp)),
+ ccallparanode.create(p1,
+ ccallparanode.create(
+ ctemprefnode.create(tempresultvariant)
+ ,nil))));
+
+ addstatement(newstatement,ccallnode.createintern('fpc_vararray_get',paras));
+ addstatement(newstatement,ctempdeletenode.create(temp));
+ { the last statement should return the value as
+ location and type, this is done be referencing the
+ temp and converting it first from a persistent temp to
+ normal temp }
+ addstatement(newstatement,ctempdeletenode.create_normal_temp(tempresultvariant));
+ addstatement(newstatement,ctemprefnode.create(tempresultvariant));
+ end;
+ p1:=newblock;
+ end;
+
+ function parse_array_constructor(arrdef:tarraydef): tnode;
+ var
+ newstatement,assstatement:tstatementnode;
+ arrnode:ttempcreatenode;
+ temp2:ttempcreatenode;
+ assnode:tnode;
+ paracount:integer;
+ begin
+ result:=internalstatements(newstatement);
+ { create temp for result }
+ arrnode:=ctempcreatenode.create(arrdef,arrdef.size,tt_persistent,true);
+ addstatement(newstatement,arrnode);
+
+ paracount:=0;
+ { check arguments and create an assignment calls }
+ if try_to_consume(_LKLAMMER) then
+ begin
+ assnode:=internalstatements(assstatement);
+ repeat
+ { arr[i] := param_i }
+ addstatement(assstatement,
+ cassignmentnode.create(
+ cvecnode.create(
+ ctemprefnode.create(arrnode),
+ cordconstnode.create(paracount,arrdef.rangedef,false)),
+ comp_expr(true,false)));
+ inc(paracount);
+ until not try_to_consume(_COMMA);
+ consume(_RKLAMMER);
+ end
+ else
+ assnode:=nil;
+
+ { get temp for array of lengths }
+ temp2:=ctempcreatenode.create(sinttype,sinttype.size,tt_persistent,false);
+ addstatement(newstatement,temp2);
+
+ { one dimensional }
+ addstatement(newstatement,cassignmentnode.create(
+ ctemprefnode.create_offset(temp2,0),
+ cordconstnode.create
+ (paracount,s32inttype,true)));
+ { create call to fpc_dynarr_setlength }
+ addstatement(newstatement,ccallnode.createintern('fpc_dynarray_setlength',
+ ccallparanode.create(caddrnode.create_internal
+ (ctemprefnode.create(temp2)),
+ ccallparanode.create(cordconstnode.create
+ (1,s32inttype,true),
+ ccallparanode.create(caddrnode.create_internal
+ (crttinode.create(tstoreddef(arrdef),initrtti,rdt_normal)),
+ ccallparanode.create(
+ ctypeconvnode.create_internal(
+ ctemprefnode.create(arrnode),voidpointertype),
+ nil))))
+
+ ));
+ { add assignment statememnts }
+ addstatement(newstatement,ctempdeletenode.create(temp2));
+ if assigned(assnode) then
+ addstatement(newstatement,assnode);
+ { the last statement should return the value as
+ location and type, this is done be referencing the
+ temp and converting it first from a persistent temp to
+ normal temp }
+ addstatement(newstatement,ctempdeletenode.create_normal_temp(arrnode));
+ addstatement(newstatement,ctemprefnode.create(arrnode));
+ end;
+
+ var
+ protsym : tpropertysym;
+ p2,p3 : tnode;
+ srsym : tsym;
+ srsymtable : TSymtable;
+ structh : tabstractrecorddef;
+ { shouldn't be used that often, so the extra overhead is ok to save
+ stack space }
+ dispatchstring : ansistring;
+ nodechanged : boolean;
+ calltype: tdispcalltype;
+ label
+ skipreckklammercheck;
+ begin
+ result:=false;
+ again:=true;
+ while again do
+ begin
+ { we need the resultdef }
+ do_typecheckpass_changed(p1,nodechanged);
+ result:=result or nodechanged;
+
+ if codegenerror then
+ begin
+ recoverconsume_postfixops;
+ exit;
+ end;
+ { handle token }
+ case token of
+ _CARET:
+ begin
+ consume(_CARET);
+
+ { support tp/mac procvar^ if the procvar returns a
+ pointer type }
+ if ((m_tp_procvar in current_settings.modeswitches) or
+ (m_mac_procvar in current_settings.modeswitches)) and
+ (p1.resultdef.typ=procvardef) and
+ (tprocvardef(p1.resultdef).returndef.typ=pointerdef) then
+ begin
+ p1:=ccallnode.create_procvar(nil,p1);
+ typecheckpass(p1);
+ end;
+
+ if (p1.resultdef.typ<>pointerdef) then
+ begin
+ { ^ as binary operator is a problem!!!! (FK) }
+ again:=false;
+ Message(parser_e_invalid_qualifier);
+ recoverconsume_postfixops;
+ p1.destroy;
+ p1:=cerrornode.create;
+ end
+ else
+ p1:=cderefnode.create(p1);
+ end;
+
+ _LECKKLAMMER:
+ begin
+ if is_class_or_interface_or_object(p1.resultdef) or
+ is_dispinterface(p1.resultdef) or is_record(p1.resultdef) then
+ begin
+ { default property }
+ protsym:=search_default_property(tabstractrecorddef(p1.resultdef));
+ if not(assigned(protsym)) then
+ begin
+ p1.destroy;
+ p1:=cerrornode.create;
+ again:=false;
+ message(parser_e_no_default_property_available);
+ end
+ else
+ begin
+ { The property symbol is referenced indirect }
+ protsym.IncRefCount;
+ handle_propertysym(protsym,protsym.owner,p1);
+ end;
+ end
+ else
+ begin
+ consume(_LECKKLAMMER);
+ repeat
+ { in all of the cases below, p1 is changed }
+ case p1.resultdef.typ of
+ pointerdef:
+ begin
+ { support delphi autoderef }
+ if (tpointerdef(p1.resultdef).pointeddef.typ=arraydef) and
+ (m_autoderef in current_settings.modeswitches) then
+ p1:=cderefnode.create(p1);
+ p2:=comp_expr(true,false);
+ { Support Pbytevar[0..9] which returns array [0..9].}
+ if try_to_consume(_POINTPOINT) then
+ p2:=crangenode.create(p2,comp_expr(true,false));
+ p1:=cvecnode.create(p1,p2);
+ end;
+ variantdef:
+ begin
+ handle_variantarray;
+ { the RECKKLAMMER is already read }
+ goto skipreckklammercheck;
+ end;
+ stringdef :
+ begin
+ p2:=comp_expr(true,false);
+ { Support string[0..9] which returns array [0..9] of char.}
+ if try_to_consume(_POINTPOINT) then
+ p2:=crangenode.create(p2,comp_expr(true,false));
+ p1:=cvecnode.create(p1,p2);
+ end;
+ arraydef:
+ begin
+ p2:=comp_expr(true,false);
+ { support SEG:OFS for go32v2 Mem[] }
+ if (target_info.system in [system_i386_go32v2,system_i386_watcom]) and
+ (p1.nodetype=loadn) and
+ assigned(tloadnode(p1).symtableentry) and
+ assigned(tloadnode(p1).symtableentry.owner.name) and
+ (tloadnode(p1).symtableentry.owner.name^='SYSTEM') and
+ ((tloadnode(p1).symtableentry.name='MEM') or
+ (tloadnode(p1).symtableentry.name='MEMW') or
+ (tloadnode(p1).symtableentry.name='MEML')) then
+ begin
+ if try_to_consume(_COLON) then
+ begin
+ p3:=caddnode.create(muln,cordconstnode.create($10,s32inttype,false),p2);
+ p2:=comp_expr(true,false);
+ p2:=caddnode.create(addn,p2,p3);
+ if try_to_consume(_POINTPOINT) then
+ { Support mem[$a000:$0000..$07ff] which returns array [0..$7ff] of memtype.}
+ p2:=crangenode.create(p2,caddnode.create(addn,comp_expr(true,false),p3.getcopy));
+ p1:=cvecnode.create(p1,p2);
+ include(tvecnode(p1).flags,nf_memseg);
+ include(tvecnode(p1).flags,nf_memindex);
+ end
+ else
+ begin
+ if try_to_consume(_POINTPOINT) then
+ { Support mem[$80000000..$80000002] which returns array [0..2] of memtype.}
+ p2:=crangenode.create(p2,comp_expr(true,false));
+ p1:=cvecnode.create(p1,p2);
+ include(tvecnode(p1).flags,nf_memindex);
+ end;
+ end
+ else
+ begin
+ if try_to_consume(_POINTPOINT) then
+ { Support arrayvar[0..9] which returns array [0..9] of arraytype.}
+ p2:=crangenode.create(p2,comp_expr(true,false));
+ p1:=cvecnode.create(p1,p2);
+ end;
+ end;
+ else
+ begin
+ if p1.resultdef.typ<>undefineddef then
+ Message(parser_e_invalid_qualifier);
+ p1.destroy;
+ p1:=cerrornode.create;
+ comp_expr(true,false);
+ again:=false;
+ end;
+ end;
+ do_typecheckpass(p1);
+ until not try_to_consume(_COMMA);
+ consume(_RECKKLAMMER);
+ { handle_variantarray eats the RECKKLAMMER and jumps here }
+ skipreckklammercheck:
+ end;
+ end;
+
+ _POINT :
+ begin
+ consume(_POINT);
+ if (p1.resultdef.typ=pointerdef) and
+ (m_autoderef in current_settings.modeswitches) and
+ { don't auto-deref objc.id, because then the code
+ below for supporting id.anyobjcmethod isn't triggered }
+ (p1.resultdef<>objc_idtype) then
+ begin
+ p1:=cderefnode.create(p1);
+ do_typecheckpass(p1);
+ end;
+ { procvar.<something> can never mean anything so always
+ try to call it in case it returns a record/object/... }
+ maybe_call_procvar(p1,false);
+
+ case p1.resultdef.typ of
+ recorddef:
+ begin
+ if token=_ID then
+ begin
+ structh:=tabstractrecorddef(p1.resultdef);
+ searchsym_in_record(structh,pattern,srsym,srsymtable);
+ if assigned(srsym) then
+ begin
+ check_hints(srsym,srsym.symoptions,srsym.deprecatedmsg);
+ consume(_ID);
+ do_member_read(structh,getaddr,srsym,p1,again,[]);
+ end
+ else
+ begin
+ Message1(sym_e_id_no_member,orgpattern);
+ p1.destroy;
+ p1:=cerrornode.create;
+ { try to clean up }
+ consume(_ID);
+ end;
+ end
+ else
+ consume(_ID);
+ end;
+ enumdef:
+ begin
+ if token=_ID then
+ begin
+ srsym:=tsym(tenumdef(p1.resultdef).symtable.Find(pattern));
+ p1.destroy;
+ if assigned(srsym) and (srsym.typ=enumsym) then
+ begin
+ check_hints(srsym,srsym.symoptions,srsym.deprecatedmsg);
+ p1:=genenumnode(tenumsym(srsym));
+ end
+ else
+ begin
+ Message1(sym_e_id_no_member,orgpattern);
+ p1:=cerrornode.create;
+ end;
+ end;
+ consume(_ID);
+ end;
+ arraydef:
+ begin
+ if is_dynamic_array(p1.resultdef) then
+ begin
+ if token=_ID then
+ begin
+ if pattern='CREATE' then
+ begin
+ consume(_ID);
+ p2:=parse_array_constructor(tarraydef(p1.resultdef));
+ p1.destroy;
+ p1:=p2;
+ end
+ else
+ begin
+ Message2(scan_f_syn_expected,'CREATE',pattern);
+ p1.destroy;
+ p1:=cerrornode.create;
+ consume(_ID);
+ end;
+ end;
+ end
+ else
+ begin
+ Message(parser_e_invalid_qualifier);
+ p1.destroy;
+ p1:=cerrornode.create;
+ consume(_ID);
+ end;
+ end;
+ variantdef:
+ begin
+ { dispatch call? }
+ { lhs := v.ident[parameters] -> property get
+ lhs := v.ident(parameters) -> method call
+ v.ident[parameters] := rhs -> property put
+ v.ident(parameters) := rhs -> also property put }
+ if token=_ID then
+ begin
+ dispatchstring:=orgpattern;
+ consume(_ID);
+ calltype:=dct_method;
+ if try_to_consume(_LKLAMMER) then
+ begin
+ p2:=parse_paras(false,true,_RKLAMMER);
+ consume(_RKLAMMER);
+ end
+ else if try_to_consume(_LECKKLAMMER) then
+ begin
+ p2:=parse_paras(false,true,_RECKKLAMMER);
+ consume(_RECKKLAMMER);
+ calltype:=dct_propget;
+ end
+ else
+ p2:=nil;
+ { property setter? }
+ if (token=_ASSIGNMENT) and not(afterassignment) then
+ begin
+ consume(_ASSIGNMENT);
+ { read the expression }
+ p3:=comp_expr(true,false);
+ { concat value parameter too }
+ p2:=ccallparanode.create(p3,p2);
+ p1:=translate_disp_call(p1,p2,dct_propput,dispatchstring,0,voidtype);
+ end
+ else
+ { this is only an approximation
+ setting useresult if not necessary is only a waste of time, no more, no less (FK) }
+ if afterassignment or in_args or (token<>_SEMICOLON) then
+ p1:=translate_disp_call(p1,p2,calltype,dispatchstring,0,cvarianttype)
+ else
+ p1:=translate_disp_call(p1,p2,calltype,dispatchstring,0,voidtype);
+ end
+ else { Error }
+ Consume(_ID);
+ end;
+ classrefdef:
+ begin
+ if token=_ID then
+ begin
+ structh:=tobjectdef(tclassrefdef(p1.resultdef).pointeddef);
+ searchsym_in_class(tobjectdef(structh),tobjectdef(structh),pattern,srsym,srsymtable,true);
+ if assigned(srsym) then
+ begin
+ check_hints(srsym,srsym.symoptions,srsym.deprecatedmsg);
+ consume(_ID);
+ do_member_read(structh,getaddr,srsym,p1,again,[]);
+ end
+ else
+ begin
+ Message1(sym_e_id_no_member,orgpattern);
+ p1.destroy;
+ p1:=cerrornode.create;
+ { try to clean up }
+ consume(_ID);
+ end;
+ end
+ else { Error }
+ Consume(_ID);
+ end;
+ objectdef:
+ begin
+ if token=_ID then
+ begin
+ structh:=tobjectdef(p1.resultdef);
+ searchsym_in_class(tobjectdef(structh),tobjectdef(structh),pattern,srsym,srsymtable,true);
+ if assigned(srsym) then
+ begin
+ check_hints(srsym,srsym.symoptions,srsym.deprecatedmsg);
+ consume(_ID);
+ do_member_read(structh,getaddr,srsym,p1,again,[]);
+ end
+ else
+ begin
+ Message1(sym_e_id_no_member,orgpattern);
+ p1.destroy;
+ p1:=cerrornode.create;
+ { try to clean up }
+ consume(_ID);
+ end;
+ end
+ else { Error }
+ Consume(_ID);
+ end;
+ pointerdef:
+ begin
+ if (p1.resultdef=objc_idtype) then
+ begin
+ { objc's id type can be used to call any
+ Objective-C method of any Objective-C class
+ type that's currently in scope }
+ if search_objc_method(pattern,srsym,srsymtable) then
+ begin
+ consume(_ID);
+ do_proc_call(srsym,srsymtable,nil,
+ (getaddr and not(token in [_CARET,_POINT])),
+ again,p1,[cnf_objc_id_call]);
+ { we need to know which procedure is called }
+ do_typecheckpass(p1);
+ end
+ else
+ begin
+ consume(_ID);
+ Message(parser_e_methode_id_expected);
+ end;
+ end
+ else
+ begin
+ Message(parser_e_invalid_qualifier);
+ if tpointerdef(p1.resultdef).pointeddef.typ in [recorddef,objectdef,classrefdef] then
+ Message(parser_h_maybe_deref_caret_missing);
+ end
+ end;
+ else
+ begin
+ if p1.resultdef.typ<>undefineddef then
+ Message(parser_e_invalid_qualifier);
+ p1.destroy;
+ p1:=cerrornode.create;
+ { Error }
+ consume(_ID);
+ end;
+ end;
+ end;
+
+ else
+ begin
+ { is this a procedure variable ? }
+ if assigned(p1.resultdef) and
+ (p1.resultdef.typ=procvardef) then
+ begin
+ { Typenode for typecasting or expecting a procvar }
+ if (p1.nodetype=typen) or
+ (
+ assigned(getprocvardef) and
+ equal_defs(p1.resultdef,getprocvardef)
+ ) then
+ begin
+ if try_to_consume(_LKLAMMER) then
+ begin
+ p1:=comp_expr(true,false);
+ consume(_RKLAMMER);
+ p1:=ctypeconvnode.create_explicit(p1,p1.resultdef);
+ end
+ else
+ again:=false
+ end
+ else
+ begin
+ if try_to_consume(_LKLAMMER) then
+ begin
+ p2:=parse_paras(false,false,_RKLAMMER);
+ consume(_RKLAMMER);
+ p1:=ccallnode.create_procvar(p2,p1);
+ { proc():= is never possible }
+ if token=_ASSIGNMENT then
+ begin
+ Message(parser_e_illegal_expression);
+ p1.free;
+ p1:=cerrornode.create;
+ again:=false;
+ end;
+ end
+ else
+ again:=false;
+ end;
+ end
+ else
+ again:=false;
+ end;
+ end;
+
+ { we only try again if p1 was changed }
+ if again or
+ (p1.nodetype=errorn) then
+ result:=true;
+ end; { while again }
+ end;
+
+ function is_member_read(sym: tsym; st: tsymtable; var p1: tnode;
+ out memberparentdef: tdef): boolean;
+ var
+ hdef : tdef;
+ begin
+ result:=true;
+ memberparentdef:=nil;
+
+ case st.symtabletype of
+ ObjectSymtable,
+ recordsymtable:
+ begin
+ memberparentdef:=tdef(st.defowner);
+ exit;
+ end;
+ WithSymtable:
+ begin
+ if assigned(p1) then
+ internalerror(2007012002);
+
+ hdef:=tnode(twithsymtable(st).withrefnode).resultdef;
+ p1:=tnode(twithsymtable(st).withrefnode).getcopy;
+
+ if not(hdef.typ in [objectdef,classrefdef]) then
+ exit;
+
+ if (hdef.typ=classrefdef) then
+ hdef:=tclassrefdef(hdef).pointeddef;
+ memberparentdef:=hdef;
+ end;
+ else
+ result:=false;
+ end;
+ end;
+
+ {$maxfpuregisters 0}
+
+ function factor(getaddr,typeonly:boolean) : tnode;
+
+ {---------------------------------------------
+ Factor_read_id
+ ---------------------------------------------}
+
+ procedure factor_read_id(out p1:tnode;var again:boolean);
+ var
+ srsym : tsym;
+ srsymtable : TSymtable;
+ hdef : tdef;
+ orgstoredpattern,
+ storedpattern : string;
+ callflags: tcallnodeflags;
+ t : ttoken;
+ unit_found : boolean;
+ begin
+ { allow post fix operators }
+ again:=true;
+
+ { first check for identifier }
+ if token<>_ID then
+ begin
+ srsym:=generrorsym;
+ srsymtable:=nil;
+ consume(_ID);
+ end
+ else
+ begin
+ if typeonly then
+ searchsym_type(pattern,srsym,srsymtable)
+ else
+ searchsym(pattern,srsym,srsymtable);
+
+ { handle unit specification like System.Writeln }
+ unit_found:=try_consume_unitsym(srsym,srsymtable,t,true);
+ storedpattern:=pattern;
+ orgstoredpattern:=orgpattern;
+ consume(t);
+
+ { named parameter support }
+ found_arg_name:=false;
+
+ if not(unit_found) and
+ named_args_allowed and
+ (token=_ASSIGNMENT) then
+ begin
+ found_arg_name:=true;
+ p1:=cstringconstnode.createstr(storedpattern);
+ consume(_ASSIGNMENT);
+ exit;
+ end;
+
+ { check hints, but only if it isn't a potential generic symbol;
+ that is checked in sub_expr if it isn't a generic }
+ if assigned(srsym) and
+ not (
+ (srsym.typ=typesym) and
+ (ttypesym(srsym).typedef.typ in [recorddef,objectdef,arraydef,procvardef,undefineddef]) and
+ not (sp_generic_para in srsym.symoptions) and
+ (token in [_LT, _LSHARPBRACKET])
+ ) then
+ check_hints(srsym,srsym.symoptions,srsym.deprecatedmsg);
+
+ { if nothing found give error and return errorsym }
+ if not assigned(srsym) or
+ { is this a generic dummy symbol? }
+ ((srsym.typ=typesym) and
+ assigned(ttypesym(srsym).typedef) and
+ (ttypesym(srsym).typedef.typ=undefineddef) and
+ not (sp_generic_para in srsym.symoptions) and
+ not (token in [_LT, _LSHARPBRACKET]) and
+ not (
+ { in non-Delphi modes the generic class' name without a
+ "specialization" or "<T>" may be used to identify the
+ current class }
+ (sp_generic_dummy in srsym.symoptions) and
+ assigned(current_structdef) and
+ (df_generic in current_structdef.defoptions) and
+ not (m_delphi in current_settings.modeswitches) and
+ (upper(srsym.realname)=copy(current_structdef.objname^,1,pos('$',current_structdef.objname^)-1))
+ )) then
+ begin
+ identifier_not_found(orgstoredpattern);
+ srsym:=generrorsym;
+ srsymtable:=nil;
+ end;
+ end;
+
+ { Access to funcret or need to call the function? }
+ if (srsym.typ in [absolutevarsym,localvarsym,paravarsym]) and
+ (vo_is_funcret in tabstractvarsym(srsym).varoptions) and
+ { result(x) is not allowed }
+ not(vo_is_result in tabstractvarsym(srsym).varoptions) and
+ (
+ (token=_LKLAMMER) or
+ (
+ (
+ (m_tp7 in current_settings.modeswitches) or
+ (m_delphi in current_settings.modeswitches)
+ ) and
+ (afterassignment or in_args)
+ )
+ ) then
+ begin
+ hdef:=tdef(srsym.owner.defowner);
+ if assigned(hdef) and
+ (hdef.typ=procdef) then
+ srsym:=tprocdef(hdef).procsym
+ else
+ begin
+ Message(parser_e_illegal_expression);
+ srsym:=generrorsym;
+ end;
+ srsymtable:=srsym.owner;
+ end;
+
+ begin
+ case srsym.typ of
+ absolutevarsym :
+ begin
+ if (tabsolutevarsym(srsym).abstyp=tovar) then
+ begin
+ p1:=nil;
+ propaccesslist_to_node(p1,nil,tabsolutevarsym(srsym).ref);
+ p1:=ctypeconvnode.create(p1,tabsolutevarsym(srsym).vardef);
+ include(p1.flags,nf_absolute);
+ end
+ else
+ p1:=cloadnode.create(srsym,srsymtable);
+ end;
+
+ staticvarsym,
+ localvarsym,
+ paravarsym,
+ fieldvarsym :
+ begin
+ { check if we are reading a field of an object/class/ }
+ { record. is_member_read() will deal with withsymtables }
+ { if needed. }
+ p1:=nil;
+ if is_member_read(srsym,srsymtable,p1,hdef) then
+ begin
+ { if the field was originally found in an }
+ { objectsymtable, it means it's part of self }
+ { if only method from which it was called is }
+ { not class static }
+ if (srsymtable.symtabletype in [ObjectSymtable,recordsymtable]) then
+ { if we are accessing a owner procsym from the nested }
+ { class we need to call it as a class member }
+ if assigned(current_structdef) and (current_structdef<>hdef) and is_owned_by(current_structdef,hdef) then
+ p1:=cloadvmtaddrnode.create(ctypenode.create(hdef))
+ else
+ if assigned(current_procinfo) and current_procinfo.procdef.no_self_node then
+ p1:=cloadvmtaddrnode.create(ctypenode.create(current_procinfo.procdef.struct))
+ else
+ p1:=load_self_node;
+ { now, if the field itself is part of an objectsymtab }
+ { (it can be even if it was found in a withsymtable, }
+ { e.g., "with classinstance do field := 5"), then }
+ { let do_member_read handle it }
+ if (srsym.owner.symtabletype in [ObjectSymtable,recordsymtable]) then
+ do_member_read(tabstractrecorddef(hdef),getaddr,srsym,p1,again,[])
+ else
+ { otherwise it's a regular record subscript }
+ p1:=csubscriptnode.create(srsym,p1);
+ end
+ else
+ { regular non-field load }
+ p1:=cloadnode.create(srsym,srsymtable);
+ end;
+
+ syssym :
+ begin
+ p1:=statement_syssym(tsyssym(srsym).number);
+ end;
+
+ typesym :
+ begin
+ hdef:=ttypesym(srsym).typedef;
+ if not assigned(hdef) then
+ begin
+ again:=false;
+ end
+ else
+ begin
+ { We need to know if this unit uses Variants }
+ if (hdef=cvarianttype) and
+ not(cs_compilesystem in current_settings.moduleswitches) then
+ current_module.flags:=current_module.flags or uf_uses_variants;
+ p1:=handle_factor_typenode(hdef,getaddr,again,srsym,typeonly);
+ end;
+ end;
+
+ enumsym :
+ begin
+ p1:=genenumnode(tenumsym(srsym));
+ end;
+
+ constsym :
+ begin
+ if tconstsym(srsym).consttyp=constresourcestring then
+ begin
+ p1:=cloadnode.create(srsym,srsymtable);
+ do_typecheckpass(p1);
+ p1.resultdef:=getansistringdef;
+ end
+ else
+ p1:=genconstsymtree(tconstsym(srsym));
+ end;
+
+ procsym :
+ begin
+ p1:=nil;
+ { check if it's a method/class method }
+ if is_member_read(srsym,srsymtable,p1,hdef) then
+ begin
+ { if we are accessing a owner procsym from the nested }
+ { class we need to call it as a class member }
+ if (srsymtable.symtabletype in [ObjectSymtable,recordsymtable]) and
+ assigned(current_structdef) and (current_structdef<>hdef) and is_owned_by(current_structdef,hdef) then
+ p1:=cloadvmtaddrnode.create(ctypenode.create(hdef));
+ { not srsymtable.symtabletype since that can be }
+ { withsymtable as well }
+ if (srsym.owner.symtabletype in [ObjectSymtable,recordsymtable]) then
+ do_member_read(tabstractrecorddef(hdef),getaddr,srsym,p1,again,[])
+ else
+ { no procsyms in records (yet) }
+ internalerror(2007012006);
+ end
+ else
+ begin
+ { regular procedure/function call }
+ if not unit_found then
+ callflags:=[]
+ else
+ callflags:=[cnf_unit_specified];
+ do_proc_call(srsym,srsymtable,nil,
+ (getaddr and not(token in [_CARET,_POINT,_LECKKLAMMER])),
+ again,p1,callflags);
+ end;
+ end;
+
+ propertysym :
+ begin
+ p1:=nil;
+ { property of a class/object? }
+ if is_member_read(srsym,srsymtable,p1,hdef) then
+ begin
+ if (srsymtable.symtabletype in [ObjectSymtable,recordsymtable]) then
+ { if we are accessing a owner procsym from the nested }
+ { class we need to call it as a class member }
+ if assigned(current_structdef) and (current_structdef<>hdef) and is_owned_by(current_structdef,hdef) then
+ p1:=cloadvmtaddrnode.create(ctypenode.create(hdef))
+ else
+ if assigned(current_procinfo) and current_procinfo.procdef.no_self_node then
+ { no self node in static class methods }
+ p1:=cloadvmtaddrnode.create(ctypenode.create(hdef))
+ else
+ p1:=load_self_node;
+ { not srsymtable.symtabletype since that can be }
+ { withsymtable as well }
+ if (srsym.owner.symtabletype in [ObjectSymtable,recordsymtable]) then
+ do_member_read(tabstractrecorddef(hdef),getaddr,srsym,p1,again,[])
+ else
+ { no propertysyms in records (yet) }
+ internalerror(2009111510);
+ end
+ else
+ { no method pointer }
+ begin
+ handle_propertysym(tpropertysym(srsym),srsymtable,p1);
+ end;
+ end;
+
+ labelsym :
+ begin
+ { Support @label }
+ if getaddr then
+ begin
+ if srsym.owner<>current_procinfo.procdef.localst then
+ CGMessage(parser_e_label_outside_proc);
+ p1:=cloadnode.create(srsym,srsym.owner)
+ end
+ else
+ begin
+ consume(_COLON);
+ if tlabelsym(srsym).defined then
+ Message(sym_e_label_already_defined);
+ if symtablestack.top.symtablelevel<>srsymtable.symtablelevel then
+ begin
+ tlabelsym(srsym).nonlocal:=true;
+ exclude(current_procinfo.procdef.procoptions,po_inline);
+ end;
+ if tlabelsym(srsym).nonlocal and
+ (current_procinfo.procdef.proctypeoption in [potype_unitinit,potype_unitfinalize]) then
+ Message(sym_e_interprocgoto_into_init_final_code_not_allowed);
+ tlabelsym(srsym).defined:=true;
+ p1:=clabelnode.create(nil,tlabelsym(srsym));
+ tlabelsym(srsym).code:=p1;
+ end;
+ end;
+
+ errorsym :
+ begin
+ p1:=cerrornode.create;
+ if try_to_consume(_LKLAMMER) then
+ begin
+ parse_paras(false,false,_RKLAMMER);
+ consume(_RKLAMMER);
+ end;
+ end;
+
+ else
+ begin
+ p1:=cerrornode.create;
+ Message(parser_e_illegal_expression);
+ end;
+ end; { end case }
+ end;
+ end;
+
+ {---------------------------------------------
+ Factor_Read_Set
+ ---------------------------------------------}
+
+ { Read a set between [] }
+ function factor_read_set:tnode;
+ var
+ p1,p2 : tnode;
+ lastp,
+ buildp : tarrayconstructornode;
+ old_allow_array_constructor : boolean;
+ begin
+ buildp:=nil;
+ { be sure that a least one arrayconstructn is used, also for an
+ empty [] }
+ if token=_RECKKLAMMER then
+ buildp:=carrayconstructornode.create(nil,buildp)
+ else
+ repeat
+ { nested array constructors are not allowed, see also tests/webtbs/tw17213.pp }
+ old_allow_array_constructor:=allow_array_constructor;
+ allow_array_constructor:=false;
+ p1:=comp_expr(true,false);
+ if try_to_consume(_POINTPOINT) then
+ begin
+ p2:=comp_expr(true,false);
+ p1:=carrayconstructorrangenode.create(p1,p2);
+ end;
+ { insert at the end of the tree, to get the correct order }
+ if not assigned(buildp) then
+ begin
+ buildp:=carrayconstructornode.create(p1,nil);
+ lastp:=buildp;
+ end
+ else
+ begin
+ lastp.right:=carrayconstructornode.create(p1,nil);
+ lastp:=tarrayconstructornode(lastp.right);
+ end;
+ allow_array_constructor:=old_allow_array_constructor;
+ { there could be more elements }
+ until not try_to_consume(_COMMA);
+ factor_read_set:=buildp;
+ end;
+
+
+ {---------------------------------------------
+ Factor (Main)
+ ---------------------------------------------}
+
+ var
+ l : longint;
+ ic : int64;
+ qc : qword;
+ p1 : tnode;
+ code : integer;
+ srsym : tsym;
+ srsymtable : TSymtable;
+ pd : tprocdef;
+ hclassdef : tobjectdef;
+ d : bestreal;
+ cur : currency;
+ hs,hsorg : string;
+ hdef : tdef;
+ filepos : tfileposinfo;
+ callflags : tcallnodeflags;
+ again,
+ updatefpos,
+ nodechanged : boolean;
+ begin
+ { can't keep a copy of p1 and compare pointers afterwards, because
+ p1 may be freed and reallocated in the same place! }
+ updatefpos:=false;
+ p1:=nil;
+ filepos:=current_tokenpos;
+ again:=false;
+ if token=_ID then
+ begin
+ again:=true;
+ { Handle references to self }
+ if (idtoken=_SELF) and
+ not(block_type in [bt_const,bt_type,bt_const_type,bt_var_type]) and
+ assigned(current_structdef) then
+ begin
+ p1:=load_self_node;
+ consume(_ID);
+ again:=true;
+ end
+ else
+ factor_read_id(p1,again);
+
+ if assigned(p1) then
+ begin
+ { factor_read_id will set the filepos to after the id,
+ and in case of _SELF the filepos will already be the
+ same as filepos (so setting it again doesn't hurt). }
+ p1.fileinfo:=filepos;
+ filepos:=current_tokenpos;
+ end;
+ { handle post fix operators }
+ updatefpos:=postfixoperators(p1,again,getaddr);
+ end
+ else
+ begin
+ updatefpos:=true;
+ case token of
+ _RETURN :
+ begin
+ consume(_RETURN);
+ if not(token in [_SEMICOLON,_ELSE,_END]) then
+ p1 := cexitnode.create(comp_expr(true,false))
+ else
+ p1 := cexitnode.create(nil);
+ end;
+ _INHERITED :
+ begin
+ again:=true;
+ consume(_INHERITED);
+ if assigned(current_procinfo) and
+ assigned(current_structdef) and
+ (current_structdef.typ=objectdef) then
+ begin
+ { for record helpers in mode Delphi "inherited" is not
+ allowed }
+ if is_objectpascal_helper(current_structdef) and
+ (m_delphi in current_settings.modeswitches) and
+ is_record(tobjectdef(current_structdef).extendeddef) then
+ Message(parser_e_inherited_not_in_record);
+ hclassdef:=tobjectdef(current_structdef).childof;
+ { Objective-C categories *replace* methods in the class
+ they extend, or add methods to it. So calling an
+ inherited method always calls the method inherited from
+ the parent of the extended class }
+ if is_objccategory(current_structdef) then
+ hclassdef:=hclassdef.childof;
+ { if inherited; only then we need the method with
+ the same name }
+ if token <> _ID then
+ begin
+ hs:=current_procinfo.procdef.procsym.name;
+ hsorg:=current_procinfo.procdef.procsym.realname;
+ anon_inherited:=true;
+ { For message methods we need to search using the message
+ number or string }
+ pd:=tprocdef(tprocsym(current_procinfo.procdef.procsym).ProcdefList[0]);
+ srdef:=nil;
+ if (po_msgint in pd.procoptions) then
+ searchsym_in_class_by_msgint(hclassdef,pd.messageinf.i,srdef,srsym,srsymtable)
+ else
+ if (po_msgstr in pd.procoptions) then
+ searchsym_in_class_by_msgstr(hclassdef,pd.messageinf.str^,srsym,srsymtable)
+ else
+ { helpers have their own ways of dealing with inherited }
+ if is_objectpascal_helper(current_structdef) then
+ searchsym_in_helper(tobjectdef(current_structdef),tobjectdef(current_structdef),hs,srsym,srsymtable,true)
+ else
+ searchsym_in_class(hclassdef,tobjectdef(current_structdef),hs,srsym,srsymtable,true);
+ end
+ else
+ begin
+ hs:=pattern;
+ hsorg:=orgpattern;
+ consume(_ID);
+ anon_inherited:=false;
+ { helpers have their own ways of dealing with inherited }
+ if is_objectpascal_helper(current_structdef) then
+ searchsym_in_helper(tobjectdef(current_structdef),tobjectdef(current_structdef),hs,srsym,srsymtable,true)
+ else
+ searchsym_in_class(hclassdef,tobjectdef(current_structdef),hs,srsym,srsymtable,true);
+ end;
+ if assigned(srsym) then
+ begin
+ check_hints(srsym,srsym.symoptions,srsym.deprecatedmsg);
+ { load the procdef from the inherited class and
+ not from self }
+ case srsym.typ of
+ procsym:
+ begin
+ if is_objectpascal_helper(current_structdef) then
+ begin
+ { for a helper load the procdef either from the
+ extended type, from the parent helper or from
+ the extended type of the parent helper
+ depending on the def the found symbol belongs
+ to }
+ if (srsym.Owner.defowner.typ=objectdef) and
+ is_objectpascal_helper(tobjectdef(srsym.Owner.defowner)) then
+ if current_structdef.is_related(tdef(srsym.Owner.defowner)) and
+ assigned(tobjectdef(current_structdef).childof) then
+ hdef:=tobjectdef(current_structdef).childof
+ else
+ hdef:=tobjectdef(srsym.Owner.defowner).extendeddef
+ else
+ hdef:=tdef(srsym.Owner.defowner);
+ end
+ else
+ hdef:=hclassdef;
+ if (po_classmethod in current_procinfo.procdef.procoptions) or
+ (po_staticmethod in current_procinfo.procdef.procoptions) then
+ hdef:=tclassrefdef.create(hdef);
+ p1:=ctypenode.create(hdef);
+ { we need to allow helpers here }
+ ttypenode(p1).helperallowed:=true;
+ end;
+ propertysym:
+ ;
+ else
+ begin
+ Message(parser_e_methode_id_expected);
+ p1:=cerrornode.create;
+ end;
+ end;
+ callflags:=[cnf_inherited];
+ if anon_inherited then
+ include(callflags,cnf_anon_inherited);
+ do_member_read(hclassdef,getaddr,srsym,p1,again,callflags);
+ end
+ else
+ begin
+ if anon_inherited then
+ begin
+ { For message methods we need to call DefaultHandler }
+ if (po_msgint in pd.procoptions) or
+ (po_msgstr in pd.procoptions) then
+ begin
+ searchsym_in_class(hclassdef,hclassdef,'DEFAULTHANDLER',srsym,srsymtable,true);
+ if not assigned(srsym) or
+ (srsym.typ<>procsym) then
+ internalerror(200303171);
+ p1:=nil;
+ do_proc_call(srsym,srsym.owner,hclassdef,false,again,p1,[]);
+ end
+ else
+ begin
+ { we need to ignore the inherited; }
+ p1:=cnothingnode.create;
+ end;
+ end
+ else
+ begin
+ Message1(sym_e_id_no_member,hsorg);
+ p1:=cerrornode.create;
+ end;
+ again:=false;
+ end;
+ { turn auto inheriting off }
+ anon_inherited:=false;
+ end
+ else
+ begin
+ { in case of records we use a more clear error message }
+ if assigned(current_structdef) and
+ (current_structdef.typ=recorddef) then
+ Message(parser_e_inherited_not_in_record)
+ else
+ Message(parser_e_generic_methods_only_in_methods);
+ again:=false;
+ p1:=cerrornode.create;
+ end;
+ postfixoperators(p1,again,getaddr);
+ end;
+
+ _INTCONST :
+ begin
+ {Try first wether the value fits in an int64.}
+ val(pattern,ic,code);
+ if code=0 then
+ begin
+ consume(_INTCONST);
+ int_to_type(ic,hdef);
+ p1:=cordconstnode.create(ic,hdef,true);
+ end
+ else
+ begin
+ { try qword next }
+ val(pattern,qc,code);
+ if code=0 then
+ begin
+ consume(_INTCONST);
+ int_to_type(qc,hdef);
+ p1:=cordconstnode.create(qc,hdef,true);
+ end;
+ end;
+ if code<>0 then
+ begin
+ { finally float }
+ val(pattern,d,code);
+ if code<>0 then
+ begin
+ Message(parser_e_invalid_integer);
+ consume(_INTCONST);
+ l:=1;
+ p1:=cordconstnode.create(l,sinttype,true);
+ end
+ else
+ begin
+ consume(_INTCONST);
+ p1:=crealconstnode.create(d,pbestrealtype^);
+ end;
+ end
+ else
+ { the necessary range checking has already been done by val }
+ tordconstnode(p1).rangecheck:=false;
+ end;
+
+ _REALNUMBER :
+ begin
+ val(pattern,d,code);
+ if code<>0 then
+ begin
+ Message(parser_e_error_in_real);
+ d:=1.0;
+ end;
+ consume(_REALNUMBER);
+{$ifdef FPC_REAL2REAL_FIXED}
+ if current_settings.fputype=fpu_none then
+ Message(parser_e_unsupported_real);
+ if (current_settings.minfpconstprec=s32real) and
+ (d = single(d)) then
+ p1:=crealconstnode.create(d,s32floattype)
+ else if (current_settings.minfpconstprec=s64real) and
+ (d = double(d)) then
+ p1:=crealconstnode.create(d,s64floattype)
+ else
+{$endif FPC_REAL2REAL_FIXED}
+ p1:=crealconstnode.create(d,pbestrealtype^);
+{$ifdef FPC_HAS_STR_CURRENCY}
+ val(pattern,cur,code);
+ if code=0 then
+ trealconstnode(p1).value_currency:=cur;
+{$endif FPC_HAS_STR_CURRENCY}
+ end;
+
+ _STRING :
+ begin
+ string_dec(hdef,true);
+ { STRING can be also a type cast }
+ if try_to_consume(_LKLAMMER) then
+ begin
+ p1:=comp_expr(true,false);
+ consume(_RKLAMMER);
+ p1:=ctypeconvnode.create_explicit(p1,hdef);
+ { handle postfix operators here e.g. string(a)[10] }
+ again:=true;
+ postfixoperators(p1,again,getaddr);
+ end
+ else
+ p1:=ctypenode.create(hdef);
+ end;
+
+ _FILE :
+ begin
+ hdef:=cfiletype;
+ consume(_FILE);
+ { FILE can be also a type cast }
+ if try_to_consume(_LKLAMMER) then
+ begin
+ p1:=comp_expr(true,false);
+ consume(_RKLAMMER);
+ p1:=ctypeconvnode.create_explicit(p1,hdef);
+ { handle postfix operators here e.g. string(a)[10] }
+ again:=true;
+ postfixoperators(p1,again,getaddr);
+ end
+ else
+ begin
+ p1:=ctypenode.create(hdef);
+ end;
+ end;
+
+ _CSTRING :
+ begin
+ p1:=cstringconstnode.createpchar(ansistring2pchar(cstringpattern),length(cstringpattern));
+ consume(_CSTRING);
+ end;
+
+ _CCHAR :
+ begin
+ p1:=cordconstnode.create(ord(pattern[1]),cchartype,true);
+ consume(_CCHAR);
+ end;
+
+ _CWSTRING:
+ begin
+ p1:=cstringconstnode.createwstr(patternw);
+ consume(_CWSTRING);
+ end;
+
+ _CWCHAR:
+ begin
+ p1:=cordconstnode.create(ord(getcharwidestring(patternw,0)),cwidechartype,true);
+ consume(_CWCHAR);
+ end;
+
+ _KLAMMERAFFE :
+ begin
+ consume(_KLAMMERAFFE);
+ got_addrn:=true;
+ { support both @<x> and @(<x>) }
+ if try_to_consume(_LKLAMMER) then
+ begin
+ p1:=factor(true,false);
+ if token in [_CARET,_POINT,_LECKKLAMMER] then
+ begin
+ again:=true;
+ postfixoperators(p1,again,getaddr);
+ end
+ else
+ consume(_RKLAMMER);
+ end
+ else
+ p1:=factor(true,false);
+ if token in [_CARET,_POINT,_LECKKLAMMER] then
+ begin
+ again:=true;
+ postfixoperators(p1,again,getaddr);
+ end;
+ got_addrn:=false;
+ p1:=caddrnode.create(p1);
+ p1.fileinfo:=filepos;
+ if cs_typed_addresses in current_settings.localswitches then
+ include(p1.flags,nf_typedaddr);
+ { Store the procvar that we are expecting, the
+ addrn will use the information to find the correct
+ procdef or it will return an error }
+ if assigned(getprocvardef) and
+ (taddrnode(p1).left.nodetype = loadn) then
+ taddrnode(p1).getprocvardef:=getprocvardef;
+ end;
+
+ _LKLAMMER :
+ begin
+ consume(_LKLAMMER);
+ p1:=comp_expr(true,false);
+ consume(_RKLAMMER);
+ { it's not a good solution }
+ { but (a+b)^ makes some problems }
+ if token in [_CARET,_POINT,_LECKKLAMMER] then
+ begin
+ again:=true;
+ postfixoperators(p1,again,getaddr);
+ end;
+ end;
+
+ _LECKKLAMMER :
+ begin
+ consume(_LECKKLAMMER);
+ p1:=factor_read_set;
+ consume(_RECKKLAMMER);
+ end;
+
+ _PLUS :
+ begin
+ consume(_PLUS);
+ p1:=factor(false,false);
+ p1:=cunaryplusnode.create(p1);
+ end;
+
+ _MINUS :
+ begin
+ consume(_MINUS);
+ if (token = _INTCONST) and not(m_isolike_unary_minus in current_settings.modeswitches) then
+ begin
+ { ugly hack, but necessary to be able to parse }
+ { -9223372036854775808 as int64 (JM) }
+ pattern := '-'+pattern;
+ p1:=sub_expr(oppower,false,false,nil);
+ { -1 ** 4 should be - (1 ** 4) and not
+ (-1) ** 4
+ This was the reason of tw0869.pp test failure PM }
+ if p1.nodetype=starstarn then
+ begin
+ if tbinarynode(p1).left.nodetype=ordconstn then
+ begin
+ tordconstnode(tbinarynode(p1).left).value:=-tordconstnode(tbinarynode(p1).left).value;
+ p1:=cunaryminusnode.create(p1);
+ end
+ else if tbinarynode(p1).left.nodetype=realconstn then
+ begin
+ trealconstnode(tbinarynode(p1).left).value_real:=-trealconstnode(tbinarynode(p1).left).value_real;
+ trealconstnode(tbinarynode(p1).left).value_currency:=-trealconstnode(tbinarynode(p1).left).value_currency;
+ p1:=cunaryminusnode.create(p1);
+ end
+ else
+ internalerror(20021029);
+ end;
+ end
+ else
+ begin
+ if m_isolike_unary_minus in current_settings.modeswitches then
+ p1:=sub_expr(opmultiply,false,false,nil)
+ else
+ p1:=sub_expr(oppower,false,false,nil);
+
+ p1:=cunaryminusnode.create(p1);
+ end;
+ end;
+
+ _OP_NOT :
+ begin
+ consume(_OP_NOT);
+ p1:=factor(false,false);
+ p1:=cnotnode.create(p1);
+ end;
+
+ _TRUE :
+ begin
+ consume(_TRUE);
+ p1:=cordconstnode.create(1,pasbool8type,false);
+ end;
+
+ _FALSE :
+ begin
+ consume(_FALSE);
+ p1:=cordconstnode.create(0,pasbool8type,false);
+ end;
+
+ _NIL :
+ begin
+ consume(_NIL);
+ p1:=cnilnode.create;
+ { It's really ugly code nil^, but delphi allows it }
+ if token in [_CARET] then
+ begin
+ again:=true;
+ postfixoperators(p1,again,getaddr);
+ end;
+ end;
+ _OBJCPROTOCOL:
+ begin
+ { The @protocol keyword is used in two ways in Objective-C:
+ 1) to declare protocols (~ Object Pascal interfaces)
+ 2) to obtain the metaclass (~ Object Pascal) "class of")
+ of a declared protocol
+ This code is for handling the second case. Because of 1),
+ we cannot simply use a system unit symbol.
+ }
+ consume(_OBJCPROTOCOL);
+ consume(_LKLAMMER);
+ p1:=factor(false,false);
+ consume(_RKLAMMER);
+ p1:=cinlinenode.create(in_objc_protocol_x,false,p1);
+ end;
+
+ else
+ begin
+ Message(parser_e_illegal_expression);
+ p1:=cerrornode.create;
+ { recover }
+ consume(token);
+ end;
+ end;
+ end;
+
+ { generate error node if no node is created }
+ if not assigned(p1) then
+ begin
+{$ifdef EXTDEBUG}
+ Comment(V_Warning,'factor: p1=nil');
+{$endif}
+ p1:=cerrornode.create;
+ updatefpos:=true;
+ end;
+
+ { get the resultdef for the node }
+ if (not assigned(p1.resultdef)) then
+ begin
+ do_typecheckpass_changed(p1,nodechanged);
+ updatefpos:=updatefpos or nodechanged;
+ end;
+
+ if assigned(p1) and
+ updatefpos then
+ p1.fileinfo:=filepos;
+ factor:=p1;
+ end;
+ {$maxfpuregisters default}
+
+ procedure post_comp_expr_gendef(var def: tdef);
+ var
+ p1 : tnode;
+ again : boolean;
+ begin
+ if not assigned(def) then
+ internalerror(2011053001);
+ again:=false;
+ { handle potential typecasts, etc }
+ p1:=handle_factor_typenode(def,false,again,nil,false);
+ { parse postfix operators }
+ postfixoperators(p1,again,false);
+ if assigned(p1) and (p1.nodetype=typen) then
+ def:=ttypenode(p1).typedef
+ else
+ def:=generrordef;
+ end;
+
+{****************************************************************************
+ Sub_Expr
+****************************************************************************}
+ const
+ { Warning these stay be ordered !! }
+ operator_levels:array[Toperator_precedence] of set of NOTOKEN..last_operator=
+ ([_LT,_LTE,_GT,_GTE,_EQ,_NE,_OP_IN],
+ [_PLUS,_MINUS,_OP_OR,_PIPE,_OP_XOR],
+ [_CARET,_SYMDIF,_STARSTAR,_STAR,_SLASH,
+ _OP_AS,_OP_IS,_OP_AND,_AMPERSAND,_OP_DIV,_OP_MOD,_OP_SHL,_OP_SHR],
+ [_STARSTAR] );
+
+ function sub_expr(pred_level:Toperator_precedence;accept_equal,typeonly:boolean;factornode:tnode):tnode;
+ {Reads a subexpression while the operators are of the current precedence
+ level, or any higher level. Replaces the old term, simpl_expr and
+ simpl2_expr.}
+
+ function istypenode(n:tnode):boolean;inline;
+ { Checks whether the given node is a type node or a VMT node containing a
+ typenode. This is used in the code for inline specializations in the
+ _LT branch below }
+ begin
+ result:=assigned(n) and
+ (
+ (n.nodetype=typen) or
+ (
+ (n.nodetype=loadvmtaddrn) and
+ (tloadvmtaddrnode(n).left.nodetype=typen)
+ )
+ );
+ end;
+
+ function gettypedef(n:tnode):tdef;inline;
+ { This returns the typedef that belongs to the given typenode or
+ loadvmtaddrnode. n must not be Nil! }
+ begin
+ if n.nodetype=typen then
+ result:=ttypenode(n).typedef
+ else
+ result:=ttypenode(tloadvmtaddrnode(n).left).typedef;
+ end;
+
+ function getgenericsym(n:tnode;out srsym:tsym):boolean;
+ var
+ srsymtable : tsymtable;
+ begin
+ srsym:=nil;
+ case n.nodetype of
+ typen:
+ srsym:=ttypenode(n).typedef.typesym;
+ loadvmtaddrn:
+ srsym:=ttypenode(tloadvmtaddrnode(n).left).typedef.typesym;
+ loadn:
+ if not searchsym_with_symoption(tloadnode(n).symtableentry.Name,srsym,srsymtable,sp_generic_dummy) then
+ srsym:=nil;
+ { TODO : handle const nodes }
+ end;
+ result:=assigned(srsym);
+ end;
+
+ label
+ SubExprStart;
+ var
+ p1,p2 : tnode;
+ oldt : Ttoken;
+ filepos : tfileposinfo;
+ again : boolean;
+ gendef,parseddef : tdef;
+ gensym : tsym;
+ begin
+ SubExprStart:
+ if pred_level=highest_precedence then
+ begin
+ if factornode=nil then
+ p1:=factor(false,typeonly)
+ else
+ p1:=factornode;
+ end
+ else
+ p1:=sub_expr(succ(pred_level),true,typeonly,factornode);
+ repeat
+ if (token in [NOTOKEN..last_operator]) and
+ (token in operator_levels[pred_level]) and
+ ((token<>_EQ) or accept_equal) then
+ begin
+ oldt:=token;
+ filepos:=current_tokenpos;
+ consume(token);
+ if pred_level=highest_precedence then
+ p2:=factor(false,false)
+ else
+ p2:=sub_expr(succ(pred_level),true,typeonly,nil);
+ case oldt of
+ _PLUS :
+ p1:=caddnode.create(addn,p1,p2);
+ _MINUS :
+ p1:=caddnode.create(subn,p1,p2);
+ _STAR :
+ p1:=caddnode.create(muln,p1,p2);
+ _SLASH :
+ p1:=caddnode.create(slashn,p1,p2);
+ _EQ:
+ p1:=caddnode.create(equaln,p1,p2);
+ _GT :
+ p1:=caddnode.create(gtn,p1,p2);
+ _LT :
+ begin
+ { we need to decice whether we have an inline specialization
+ (type nodes to the left and right of "<", mode Delphi and
+ ">" or "," following) or a normal "<" comparison }
+ { TODO : p1 could be a non type if e.g. a variable with the
+ same name is defined in the same unit where the
+ generic is defined (though "same unit" is not
+ necessarily needed) }
+ if getgenericsym(p1,gensym) and
+ { Attention: when nested specializations are supported
+ p2 could be a loadn if a "<" follows }
+ istypenode(p2) and
+ (m_delphi in current_settings.modeswitches) and
+ { TODO : add _LT, _LSHARPBRACKET for nested specializations }
+ (token in [_GT,_RSHARPBRACKET,_COMMA]) then
+ begin
+ { this is an inline specialization }
+
+ { retrieve the defs of two nodes }
+ gendef:=nil;
+ parseddef:=gettypedef(p2);
+
+ if parseddef.typesym.typ<>typesym then
+ Internalerror(2011051001);
+
+ { check the hints for parseddef }
+ check_hints(parseddef.typesym,parseddef.typesym.symoptions,parseddef.typesym.deprecatedmsg);
+
+ { generate the specialization }
+ generate_specialization(gendef,false,'',parseddef,gensym.RealName);
+
+ { we don't need the old left and right nodes anymore }
+ p1.Free;
+ p2.Free;
+ { in case of a class or a record the specialized generic
+ is always a classrefdef }
+ again:=false;
+ { handle potential typecasts, etc }
+ p1:=handle_factor_typenode(gendef,false,again,nil,false);
+ { parse postfix operators }
+ if postfixoperators(p1,again,false) then
+ if assigned(p1) then
+ p1.fileinfo:=filepos
+ else
+ p1:=cerrornode.create;
+
+ { with p1 now set we are in reality directly behind the
+ call to "factor" thus we need to call down to that
+ again }
+ { This is disabled until specializations on the right
+ hand side work as well, because
+ "not working expressions" is better than "half working
+ expressions" }
+ {factornode:=p1;
+ goto SubExprStart;}
+ end
+ else
+ begin
+ { this is a normal "<" comparison }
+
+ { potential generic types that are followed by a "<" }
+
+ { a) are not checked whether they are an undefined def,
+ but not a generic parameter }
+ if (p1.nodetype=typen) and
+ (ttypenode(p1).typedef.typ=undefineddef) and
+ assigned(ttypenode(p1).typedef.typesym) and
+ not (sp_generic_para in ttypenode(p1).typedef.typesym.symoptions) then
+ begin
+ identifier_not_found(ttypenode(p1).typedef.typesym.RealName);
+ p1.Free;
+ p1:=cerrornode.create;
+ end;
+
+ { b) don't have their hints checked }
+ if istypenode(p1) then
+ begin
+ gendef:=gettypedef(p1);
+ if gendef.typ in [objectdef,recorddef,arraydef,procvardef] then
+ check_hints(gendef.typesym,gendef.typesym.symoptions,gendef.typesym.deprecatedmsg);
+ end;
+
+ { Note: the second part of the expression will be needed
+ for nested specializations }
+ if istypenode(p2) {and
+ not (token in [_LT, _LSHARPBRACKET])} then
+ begin
+ gendef:=gettypedef(p2);
+ if gendef.typ in [objectdef,recorddef,arraydef,procvardef] then
+ check_hints(gendef.typesym,gendef.typesym.symoptions,gendef.typesym.deprecatedmsg);
+ end;
+
+ { create the comparison node for "<" }
+ p1:=caddnode.create(ltn,p1,p2)
+ end;
+ end;
+ _GTE :
+ p1:=caddnode.create(gten,p1,p2);
+ _LTE :
+ p1:=caddnode.create(lten,p1,p2);
+ _SYMDIF :
+ p1:=caddnode.create(symdifn,p1,p2);
+ _STARSTAR :
+ p1:=caddnode.create(starstarn,p1,p2);
+ _OP_AS,
+ _OP_IS :
+ begin
+ if token in [_LT, _LSHARPBRACKET] then
+ begin
+ { for now we're handling this as a generic declaration;
+ there could be cases though (because of operator
+ overloading) where this is the wrong decision... }
+ { TODO : here the same note as in _LT applies as p2 could
+ point to a variable, etc }
+ gendef:=gettypedef(p2);
+
+ if gendef.typesym.typ<>typesym then
+ Internalerror(2011071401);
+
+ { generate the specialization }
+ generate_specialization(gendef,false,'',nil,'');
+
+ { we don't need the old p2 anymore }
+ p2.Free;
+
+ again:=false;
+ { handle potential typecasts, etc }
+ p2:=handle_factor_typenode(gendef,false,again,nil,false);
+ { parse postfix operators }
+ if postfixoperators(p2,again,false) then
+ if assigned(p2) then
+ p2.fileinfo:=filepos
+ else
+ p2:=cerrornode.create;
+
+ { here we don't need to call back down to "factor", thus
+ no "goto" }
+ end;
+
+ { now generate the "is" or "as" node }
+ case oldt of
+ _OP_AS:
+ p1:=casnode.create(p1,p2);
+ _OP_IS:
+ p1:=cisnode.create(p1,p2);
+ end;
+ end;
+ _OP_IN :
+ p1:=cinnode.create(p1,p2);
+ _OP_OR,
+ _PIPE {macpas only} :
+ begin
+ p1:=caddnode.create(orn,p1,p2);
+ if (oldt = _PIPE) then
+ include(p1.flags,nf_short_bool);
+ end;
+ _OP_AND,
+ _AMPERSAND {macpas only} :
+ begin
+ p1:=caddnode.create(andn,p1,p2);
+ if (oldt = _AMPERSAND) then
+ include(p1.flags,nf_short_bool);
+ end;
+ _OP_DIV :
+ p1:=cmoddivnode.create(divn,p1,p2);
+ _OP_NOT :
+ p1:=cnotnode.create(p1);
+ _OP_MOD :
+ begin
+ p1:=cmoddivnode.create(modn,p1,p2);
+ if m_iso in current_settings.modeswitches then
+ include(p1.flags,nf_isomod);
+ end;
+ _OP_SHL :
+ p1:=cshlshrnode.create(shln,p1,p2);
+ _OP_SHR :
+ p1:=cshlshrnode.create(shrn,p1,p2);
+ _OP_XOR :
+ p1:=caddnode.create(xorn,p1,p2);
+ _ASSIGNMENT :
+ p1:=cassignmentnode.create(p1,p2);
+ _NE :
+ p1:=caddnode.create(unequaln,p1,p2);
+ end;
+ p1.fileinfo:=filepos;
+ end
+ else
+ break;
+ until false;
+ sub_expr:=p1;
+ end;
+
+
+ function comp_expr(accept_equal,typeonly:boolean):tnode;
+ var
+ oldafterassignment : boolean;
+ p1 : tnode;
+ begin
+ oldafterassignment:=afterassignment;
+ afterassignment:=true;
+ p1:=sub_expr(opcompare,accept_equal,typeonly,nil);
+ { get the resultdef for this expression }
+ if not assigned(p1.resultdef) then
+ do_typecheckpass(p1);
+ afterassignment:=oldafterassignment;
+ comp_expr:=p1;
+ end;
+
+
+ function expr(dotypecheck : boolean) : tnode;
+
+ var
+ p1,p2 : tnode;
+ filepos : tfileposinfo;
+ oldafterassignment,
+ updatefpos : boolean;
+
+ begin
+ oldafterassignment:=afterassignment;
+ p1:=sub_expr(opcompare,true,false,nil);
+ { get the resultdef for this expression }
+ if not assigned(p1.resultdef) and
+ dotypecheck then
+ do_typecheckpass(p1);
+ filepos:=current_tokenpos;
+ if token in [_ASSIGNMENT,_PLUSASN,_MINUSASN,_STARASN,_SLASHASN] then
+ afterassignment:=true;
+ updatefpos:=true;
+ case token of
+ _POINTPOINT :
+ begin
+ consume(_POINTPOINT);
+ p2:=sub_expr(opcompare,true,false,nil);
+ p1:=crangenode.create(p1,p2);
+ end;
+ _ASSIGNMENT :
+ begin
+ consume(_ASSIGNMENT);
+ if assigned(p1.resultdef) and (p1.resultdef.typ=procvardef) then
+ getprocvardef:=tprocvardef(p1.resultdef);
+ p2:=sub_expr(opcompare,true,false,nil);
+ if assigned(getprocvardef) then
+ handle_procvar(getprocvardef,p2);
+ getprocvardef:=nil;
+ p1:=cassignmentnode.create(p1,p2);
+ end;
+ _PLUSASN :
+ begin
+ consume(_PLUSASN);
+ p2:=sub_expr(opcompare,true,false,nil);
+ p1:=gen_c_style_operator(addn,p1,p2);
+ end;
+ _MINUSASN :
+ begin
+ consume(_MINUSASN);
+ p2:=sub_expr(opcompare,true,false,nil);
+ p1:=gen_c_style_operator(subn,p1,p2);
+ end;
+ _STARASN :
+ begin
+ consume(_STARASN );
+ p2:=sub_expr(opcompare,true,false,nil);
+ p1:=gen_c_style_operator(muln,p1,p2);
+ end;
+ _SLASHASN :
+ begin
+ consume(_SLASHASN );
+ p2:=sub_expr(opcompare,true,false,nil);
+ p1:=gen_c_style_operator(slashn,p1,p2);
+ end;
+ else
+ updatefpos:=false;
+ end;
+ { get the resultdef for this expression }
+ if not assigned(p1.resultdef) and
+ dotypecheck then
+ do_typecheckpass(p1);
+ afterassignment:=oldafterassignment;
+ if updatefpos then
+ p1.fileinfo:=filepos;
+ expr:=p1;
+ end;
+
+ function get_intconst:TConstExprInt;
+ {Reads an expression, tries to evalute it and check if it is an integer
+ constant. Then the constant is returned.}
+ var
+ p:tnode;
+ begin
+ result:=0;
+ p:=comp_expr(true,false);
+ if not codegenerror then
+ begin
+ if (p.nodetype<>ordconstn) or
+ not(is_integer(p.resultdef)) then
+ Message(parser_e_illegal_expression)
+ else
+ result:=tordconstnode(p).value;
+ end;
+ p.free;
+ end;
+
+
+ function get_stringconst:string;
+ {Reads an expression, tries to evaluate it and checks if it is a string
+ constant. Then the constant is returned.}
+ var
+ p:tnode;
+ begin
+ get_stringconst:='';
+ p:=comp_expr(true,false);
+ if p.nodetype<>stringconstn then
+ begin
+ if (p.nodetype=ordconstn) and is_char(p.resultdef) then
+ get_stringconst:=char(int64(tordconstnode(p).value))
+ else
+ Message(parser_e_illegal_expression);
+ end
+ else
+ get_stringconst:=strpas(tstringconstnode(p).value_str);
+ p.free;
+ end;
+
+end.
diff --git a/closures/compiler/pgenutil.pas b/closures/compiler/pgenutil.pas
new file mode 100644
index 0000000000..b2bbdf4ab9
--- /dev/null
+++ b/closures/compiler/pgenutil.pas
@@ -0,0 +1,558 @@
+{
+ Copyright (c) 2011
+
+ Contains different functions that are used in the context of
+ parsing generics.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit pgenutil;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ { common }
+ cclasses,
+ { symtable }
+ symtype,symdef;
+
+ procedure generate_specialization(var tt:tdef;parse_class_parent:boolean;_prettyname:string;parsedtype:tdef;symname:string);
+ function parse_generic_parameters:TFPObjectList;
+ procedure insert_generic_parameter_types(def:tstoreddef;genericdef:tstoreddef;genericlist:TFPObjectList);
+
+implementation
+
+uses
+ { common }
+ cutils,
+ { global }
+ globals,globtype,tokens,verbose,
+ { symtable }
+ symconst,symbase,symsym,symtable,
+ { modules }
+ fmodule,
+ { pass 1 }
+ htypechk,
+ node,nobj,nmem,
+ { parser }
+ scanner,
+ pbase,pexpr,pdecsub,ptype;
+
+
+ procedure generate_specialization(var tt:tdef;parse_class_parent:boolean;_prettyname:string;parsedtype:tdef;symname:string);
+ var
+ st : TSymtable;
+ srsym : tsym;
+ pt2 : tnode;
+ found,
+ first,
+ err : boolean;
+ i,
+ gencount : longint;
+ genericdef : tstoreddef;
+ generictype : ttypesym;
+ genericdeflist : TFPObjectList;
+ generictypelist : TFPObjectList;
+ oldsymtablestack : tsymtablestack;
+ oldextendeddefs : TFPHashObjectList;
+ hmodule : tmodule;
+ pu : tused_unit;
+ prettyname : ansistring;
+ uspecializename,
+ countstr,genname,ugenname,specializename : string;
+ vmtbuilder : TVMTBuilder;
+ specializest : tsymtable;
+ item : tobject;
+ old_current_structdef : tabstractrecorddef;
+ old_current_genericdef,old_current_specializedef : tstoreddef;
+ tempst : tglobalsymtable;
+ old_block_type: tblock_type;
+ hashedid: thashedidstring;
+ begin
+ { retrieve generic def that we are going to replace }
+ genericdef:=tstoreddef(tt);
+ tt:=nil;
+
+ { either symname must be given or genericdef needs to be valid }
+ if (symname='') and
+ (not assigned(genericdef) or
+ not assigned(genericdef.typesym) or
+ (genericdef.typesym.typ<>typesym)) then
+ internalerror(2011042701);
+
+ { Only parse the parameters for recovery or
+ for recording in genericbuf }
+ if parse_generic then
+ begin
+ if not try_to_consume(_LT) then
+ consume(_LSHARPBRACKET);
+ gencount:=0;
+ repeat
+ pt2:=factor(false,true);
+ pt2.free;
+ inc(gencount);
+ until not try_to_consume(_COMMA);
+ if not try_to_consume(_GT) then
+ consume(_RSHARPBRACKET);
+ { we need to return a def that can later pass some checks like
+ whether it's an interface or not }
+ if parse_generic and (not assigned(tt) or (tt.typ=undefineddef)) then
+ begin
+ if (symname='') and (df_generic in genericdef.defoptions) then
+ { this happens in non-Delphi modes }
+ tt:=genericdef
+ else
+ begin
+ { find the corresponding generic symbol so that any checks
+ done on the returned def will be handled correctly }
+ str(gencount,countstr);
+ if symname='' then
+ genname:=ttypesym(genericdef.typesym).realname
+ else
+ genname:=symname;
+ genname:=genname+'$'+countstr;
+ ugenname:=upper(genname);
+ if not searchsym(ugenname,srsym,st) or
+ (srsym.typ<>typesym) then
+ begin
+ identifier_not_found(genname);
+ exit;
+ end;
+ tt:=ttypesym(srsym).typedef;
+ { this happens in non-Delphi modes if we encounter a
+ specialization of the generic class or record we're
+ currently parsing }
+ if (tt.typ=errordef) and assigned(current_structdef) and
+ (current_structdef.objname^=ugenname) then
+ tt:=current_structdef;
+ end;
+ end;
+ exit;
+ end;
+
+ if not assigned(parsedtype) and not try_to_consume(_LT) then
+ consume(_LSHARPBRACKET);
+
+ generictypelist:=TFPObjectList.create(false);
+ genericdeflist:=TFPObjectList.Create(false);
+
+ { Parse type parameters }
+ err:=false;
+ { set the block type to type, so that the parsed type are returned as
+ ttypenode (e.g. classes are in non type-compatible blocks returned as
+ tloadvmtaddrnode) }
+ old_block_type:=block_type;
+ { if parsedtype is set, then the first type identifer was already parsed
+ (happens in inline specializations) and thus we only need to parse
+ the remaining types and do as if the first one was already given }
+ first:=not assigned(parsedtype);
+ if assigned(parsedtype) then
+ begin
+ genericdeflist.Add(parsedtype);
+ specializename:='$'+parsedtype.typesym.realname;
+ prettyname:=parsedtype.typesym.prettyname;
+ end
+ else
+ begin
+ specializename:='';
+ prettyname:='';
+ end;
+ while not (token in [_GT,_RSHARPBRACKET]) do
+ begin
+ { "first" is set to false at the end of the loop! }
+ if not first then
+ consume(_COMMA);
+ block_type:=bt_type;
+ pt2:=factor(false,true);
+ if pt2.nodetype=typen then
+ begin
+ if df_generic in pt2.resultdef.defoptions then
+ Message(parser_e_no_generics_as_params);
+ genericdeflist.Add(pt2.resultdef);
+ if not assigned(pt2.resultdef.typesym) then
+ message(type_e_generics_cannot_reference_itself)
+ else
+ begin
+ specializename:=specializename+'$'+pt2.resultdef.typesym.realname;
+ if first then
+ prettyname:=prettyname+pt2.resultdef.typesym.prettyname
+ else
+ prettyname:=prettyname+','+pt2.resultdef.typesym.prettyname;
+ end;
+ end
+ else
+ begin
+ Message(type_e_type_id_expected);
+ err:=true;
+ end;
+ pt2.free;
+ first:=false;
+ end;
+ block_type:=old_block_type;
+
+ if err then
+ begin
+ try_to_consume(_RSHARPBRACKET);
+ exit;
+ end;
+
+ { search a generic with the given count of params }
+ countstr:='';
+ str(genericdeflist.Count,countstr);
+ { use the name of the symbol as procvars return a user friendly version
+ of the name }
+ if symname='' then
+ genname:=ttypesym(genericdef.typesym).realname
+ else
+ genname:=symname;
+ { in case of non-Delphi mode the type name could already be a generic
+ def (but maybe the wrong one) }
+ if assigned(genericdef) and (df_generic in genericdef.defoptions) then
+ begin
+ { remove the type count suffix from the generic's name }
+ for i:=Length(genname) downto 1 do
+ if genname[i]='$' then
+ begin
+ genname:=copy(genname,1,i-1);
+ break;
+ end;
+ end;
+ genname:=genname+'$'+countstr;
+ ugenname:=upper(genname);
+
+ if assigned(genericdef) and (genericdef.owner.symtabletype in [objectsymtable,recordsymtable]) then
+ begin
+ if genericdef.owner.symtabletype = objectsymtable then
+ found:=searchsym_in_class(tobjectdef(genericdef.owner.defowner),tobjectdef(genericdef.owner.defowner),ugenname,srsym,st,false)
+ else
+ found:=searchsym_in_record(tabstractrecorddef(genericdef.owner.defowner),ugenname,srsym,st);
+ end
+ else
+ found:=searchsym(ugenname,srsym,st);
+
+ if not found or (srsym.typ<>typesym) then
+ begin
+ identifier_not_found(genname);
+ genericdeflist.Free;
+ generictypelist.Free;
+ exit;
+ end;
+
+ { we've found the correct def }
+ genericdef:=tstoreddef(ttypesym(srsym).typedef);
+
+ { build the new type's name }
+ specializename:=genname+specializename;
+ uspecializename:=upper(specializename);
+ prettyname:=genericdef.typesym.prettyname+'<'+prettyname+'>';
+
+ { select the symtable containing the params }
+ case genericdef.typ of
+ procdef:
+ st:=genericdef.GetSymtable(gs_para);
+ objectdef,
+ recorddef:
+ st:=genericdef.GetSymtable(gs_record);
+ arraydef:
+ st:=tarraydef(genericdef).symtable;
+ procvardef:
+ st:=genericdef.GetSymtable(gs_para);
+ else
+ internalerror(200511182);
+ end;
+
+ { build the list containing the types for the generic params }
+ gencount:=0;
+ for i:=0 to st.SymList.Count-1 do
+ begin
+ srsym:=tsym(st.SymList[i]);
+ if sp_generic_para in srsym.symoptions then
+ begin
+ if gencount=genericdeflist.Count then
+ internalerror(2011042702);
+ generictype:=ttypesym.create(srsym.realname,tdef(genericdeflist[gencount]));
+ generictypelist.add(generictype);
+ inc(gencount);
+ end;
+ end;
+
+
+ { Special case if we are referencing the current defined object }
+ if assigned(current_structdef) and
+ (current_structdef.objname^=uspecializename) then
+ tt:=current_structdef;
+
+ { decide in which symtable to put the specialization }
+ if current_module.is_unit and current_module.in_interface then
+ specializest:=current_module.globalsymtable
+ else
+ specializest:=current_module.localsymtable;
+
+ { Can we reuse an already specialized type? }
+ if not assigned(tt) then
+ begin
+ hashedid.id:=uspecializename;
+
+ srsym:=tsym(specializest.findwithhash(hashedid));
+ if assigned(srsym) then
+ begin
+ if srsym.typ<>typesym then
+ internalerror(200710171);
+ tt:=ttypesym(srsym).typedef;
+ end
+ else
+ { the generic could have been specialized in the globalsymtable
+ already, so search there as well }
+ if (specializest<>current_module.globalsymtable) and assigned(current_module.globalsymtable) then
+ begin
+ srsym:=tsym(current_module.globalsymtable.findwithhash(hashedid));
+ if assigned(srsym) then
+ begin
+ if srsym.typ<>typesym then
+ internalerror(2011121101);
+ tt:=ttypesym(srsym).typedef;
+ end;
+ end;
+ end;
+
+ if not assigned(tt) then
+ begin
+ { Setup symtablestack at definition time
+ to get types right, however this is not perfect, we should probably record
+ the resolved symbols }
+ oldsymtablestack:=symtablestack;
+ oldextendeddefs:=current_module.extendeddefs;
+ current_module.extendeddefs:=TFPHashObjectList.create(true);
+ symtablestack:=tdefawaresymtablestack.create;
+ if not assigned(genericdef) then
+ internalerror(200705151);
+ hmodule:=find_module_from_symtable(genericdef.owner);
+ if hmodule=nil then
+ internalerror(200705152);
+ pu:=tused_unit(hmodule.used_units.first);
+ while assigned(pu) do
+ begin
+ if not assigned(pu.u.globalsymtable) then
+ internalerror(200705153);
+ symtablestack.push(pu.u.globalsymtable);
+ pu:=tused_unit(pu.next);
+ end;
+
+ if assigned(hmodule.globalsymtable) then
+ symtablestack.push(hmodule.globalsymtable);
+
+ { push the localsymtable if needed }
+ if (hmodule<>current_module) or not current_module.in_interface then
+ symtablestack.push(hmodule.localsymtable);
+
+ { push a temporary global symtable so that the specialization is
+ added to the correct symtable; this symtable does not contain
+ any other symbols, so that the type resolution can not be
+ influenced by symbols in the current unit }
+ tempst:=tspecializesymtable.create(current_module.modulename^,current_module.moduleid);
+ symtablestack.push(tempst);
+
+ { Reparse the original type definition }
+ if not err then
+ begin
+ if parse_class_parent then
+ begin
+ old_current_structdef:=current_structdef;
+ old_current_genericdef:=current_genericdef;
+ old_current_specializedef:=current_specializedef;
+
+ if genericdef.owner.symtabletype in [recordsymtable,objectsymtable] then
+ current_structdef:=tabstractrecorddef(genericdef.owner.defowner)
+ else
+ current_structdef:=nil;
+ current_genericdef:=nil;
+ current_specializedef:=nil;
+ end;
+
+ { First a new typesym so we can reuse this specialization and
+ references to this specialization can be handled }
+ srsym:=ttypesym.create(specializename,generrordef);
+ specializest.insert(srsym);
+
+ { specializations are declarations as such it is the wisest to
+ declare set the blocktype to "type"; otherwise we'll
+ experience unexpected side effects like the addition of
+ classrefdefs if we have a generic that's derived from another
+ generic }
+ old_block_type:=block_type;
+ block_type:=bt_type;
+
+ if not assigned(genericdef.generictokenbuf) then
+ internalerror(200511171);
+ current_scanner.startreplaytokens(genericdef.generictokenbuf,
+ genericdef.change_endian);
+ read_named_type(tt,specializename,genericdef,generictypelist,false);
+ ttypesym(srsym).typedef:=tt;
+ tt.typesym:=srsym;
+
+ if _prettyname<>'' then
+ ttypesym(tt.typesym).fprettyname:=_prettyname
+ else
+ ttypesym(tt.typesym).fprettyname:=prettyname;
+
+ { Note regarding hint directives:
+ There is no need to remove the flags for them from the
+ specialized generic symbol, because hint directives that
+ follow the specialization are handled by the code in
+ pdecl.types_dec and added to the type symbol.
+ E.g.: TFoo = TBar<Blubb> deprecated;
+ Here the symbol TBar$1$Blubb will contain the
+ "sp_hint_deprecated" flag while the TFoo symbol won't.}
+
+ case tt.typ of
+ { Build VMT indexes for classes and read hint directives }
+ objectdef:
+ begin
+ try_consume_hintdirective(srsym.symoptions,srsym.deprecatedmsg);
+ consume(_SEMICOLON);
+
+ vmtbuilder:=TVMTBuilder.Create(tobjectdef(tt));
+ vmtbuilder.generate_vmt;
+ vmtbuilder.free;
+ end;
+ { handle params, calling convention, etc }
+ procvardef:
+ begin
+ if not check_proc_directive(true) then
+ begin
+ try_consume_hintdirective(ttypesym(srsym).symoptions,ttypesym(srsym).deprecatedmsg);
+ consume(_SEMICOLON);
+ end;
+ parse_var_proc_directives(ttypesym(srsym));
+ handle_calling_convention(tprocvardef(tt));
+ if try_consume_hintdirective(ttypesym(srsym).symoptions,ttypesym(srsym).deprecatedmsg) then
+ consume(_SEMICOLON);
+ end;
+ else
+ { parse hint directives for records and arrays }
+ begin
+ try_consume_hintdirective(srsym.symoptions,srsym.deprecatedmsg);
+ consume(_SEMICOLON);
+ end;
+ end;
+ { Consume the semicolon if it is also recorded }
+ try_to_consume(_SEMICOLON);
+
+ block_type:=old_block_type;
+ if parse_class_parent then
+ begin
+ current_structdef:=old_current_structdef;
+ current_genericdef:=old_current_genericdef;
+ current_specializedef:=old_current_specializedef;
+ end;
+ end;
+
+ { extract all created symbols and defs from the temporary symtable
+ and add them to the specializest }
+ for i:=0 to tempst.SymList.Count-1 do
+ begin
+ item:=tempst.SymList.Items[i];
+ specializest.SymList.Add(tempst.SymList.NameOfIndex(i),item);
+ tsym(item).Owner:=specializest;
+ tempst.SymList.Extract(item);
+ end;
+
+ for i:=0 to tempst.DefList.Count-1 do
+ begin
+ item:=tempst.DefList.Items[i];
+ specializest.DefList.Add(item);
+ tdef(item).owner:=specializest;
+ tempst.DefList.Extract(item);
+ end;
+
+ tempst.free;
+
+ { Restore symtablestack }
+ current_module.extendeddefs.free;
+ current_module.extendeddefs:=oldextendeddefs;
+ symtablestack.free;
+ symtablestack:=oldsymtablestack;
+ end;
+
+ if not (token in [_GT, _RSHARPBRACKET]) then
+ begin
+ consume(_RSHARPBRACKET);
+ exit;
+ end
+ else
+ consume(token);
+
+ genericdeflist.free;
+ generictypelist.free;
+ if assigned(genericdef) then
+ begin
+ { check the hints of the found generic symbol }
+ srsym:=genericdef.typesym;
+ check_hints(srsym,srsym.symoptions,srsym.deprecatedmsg);
+ end;
+ end;
+
+
+ function parse_generic_parameters:TFPObjectList;
+ var
+ generictype : ttypesym;
+ begin
+ result:=TFPObjectList.Create(false);
+ repeat
+ if token=_ID then
+ begin
+ generictype:=ttypesym.create(orgpattern,cundefinedtype);
+ include(generictype.symoptions,sp_generic_para);
+ result.add(generictype);
+ end;
+ consume(_ID);
+ until not try_to_consume(_COMMA) ;
+ end;
+
+
+ procedure insert_generic_parameter_types(def:tstoreddef;genericdef:tstoreddef;genericlist:TFPObjectList);
+ var
+ i: longint;
+ generictype: ttypesym;
+ st: tsymtable;
+ begin
+ def.genericdef:=genericdef;
+ if not assigned(genericlist) then
+ exit;
+
+ case def.typ of
+ recorddef,objectdef: st:=tabstractrecorddef(def).symtable;
+ arraydef: st:=tarraydef(def).symtable;
+ procvardef,procdef: st:=tabstractprocdef(def).parast;
+ else
+ internalerror(201101020);
+ end;
+
+ for i:=0 to genericlist.count-1 do
+ begin
+ generictype:=ttypesym(genericlist[i]);
+ if generictype.typedef.typ=undefineddef then
+ include(def.defoptions,df_generic)
+ else
+ include(def.defoptions,df_specialization);
+ st.insert(generictype);
+ end;
+ end;
+
+end.
diff --git a/closures/compiler/pinline.pas b/closures/compiler/pinline.pas
new file mode 100644
index 0000000000..ddb5706291
--- /dev/null
+++ b/closures/compiler/pinline.pas
@@ -0,0 +1,784 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generates nodes for routines that need compiler support
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit pinline;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ symtype,
+ node,
+ globals,
+ cpuinfo;
+
+ function new_dispose_statement(is_new:boolean) : tnode;
+ function new_function : tnode;
+
+ function inline_setlength : tnode;
+ function inline_initialize : tnode;
+ function inline_finalize : tnode;
+ function inline_copy : tnode;
+
+
+implementation
+
+ uses
+ { common }
+ cutils,
+ { global }
+ globtype,tokens,verbose,constexp,
+ systems,
+ { symtable }
+ symbase,symconst,symdef,symsym,symtable,defutil,
+ { pass 1 }
+ pass_1,htypechk,
+ nmat,nadd,ncal,nmem,nset,ncnv,ninl,ncon,nld,nflw,nbas,nutils,
+ { parser }
+ scanner,
+ pbase,pexpr,
+ { codegen }
+ cgbase,procinfo
+ ;
+
+
+ function new_dispose_statement(is_new:boolean) : tnode;
+ var
+ newstatement : tstatementnode;
+ temp : ttempcreatenode;
+ para : tcallparanode;
+ p,p2 : tnode;
+ again : boolean; { dummy for do_proc_call }
+ destructorname : TIDString;
+ sym : tsym;
+ classh : tobjectdef;
+ callflag : tcallnodeflag;
+ destructorpos,
+ storepos : tfileposinfo;
+ begin
+ consume(_LKLAMMER);
+ p:=comp_expr(true,false);
+ { calc return type }
+ if is_new then
+ begin
+ set_varstate(p,vs_written,[]);
+ valid_for_var(p,true);
+ end
+ else
+ set_varstate(p,vs_readwritten,[vsf_must_be_valid]);
+ if (m_mac in current_settings.modeswitches) and
+ is_class(p.resultdef) then
+ begin
+ classh:=tobjectdef(p.resultdef);
+
+ { make sure we call ObjPas.TObject.Create/Free and not a random }
+ { create/free method in a macpas descendent object (since those }
+ { are not supposed to be called automatically when you call }
+ { new/dispose) }
+ while assigned(classh.childof) do
+ classh := classh.childof;
+ if is_new then
+ begin
+ sym:=search_struct_member(classh,'CREATE');
+ p2 := cloadvmtaddrnode.create(ctypenode.create(p.resultdef));
+ end
+ else
+ begin
+ sym:=search_struct_member(classh,'FREE');
+ p2 := p;
+ end;
+
+ if not(assigned(sym)) then
+ begin
+ p.free;
+ if is_new then
+ p2.free;
+ new_dispose_statement := cerrornode.create;
+ consume_all_until(_RKLAMMER);
+ consume(_RKLAMMER);
+ exit;
+ end;
+
+ do_member_read(classh,false,sym,p2,again,[]);
+
+ { we need the real called method }
+ do_typecheckpass(p2);
+
+ if (p2.nodetype=calln) and
+ assigned(tcallnode(p2).procdefinition) then
+ begin
+ if is_new then
+ begin
+ if (tcallnode(p2).procdefinition.proctypeoption<>potype_constructor) then
+ Message(parser_e_expr_have_to_be_constructor_call);
+ p2.resultdef:=p.resultdef;
+ p2:=cassignmentnode.create(p,p2);
+ typecheckpass(p2);
+ end
+ else
+ begin
+ { Free is not a destructor
+ if (tcallnode(p2).procdefinition.proctypeoption<>potype_destructor) then
+ Message(parser_e_expr_have_to_be_destructor_call);
+ }
+ end
+ end
+ else
+ internalerror(2005061202);
+ new_dispose_statement := p2;
+ end
+ { constructor,destructor specified }
+ else if not(m_mac in current_settings.modeswitches) and
+ try_to_consume(_COMMA) then
+ begin
+ { extended syntax of new and dispose }
+ { function styled new is handled in factor }
+ { destructors have no parameters }
+ destructorname:=pattern;
+ destructorpos:=current_tokenpos;
+ consume(_ID);
+
+ if (p.resultdef.typ<>pointerdef) then
+ begin
+ Message1(type_e_pointer_type_expected,p.resultdef.typename);
+ p.free;
+ p:=factor(false,false);
+ p.free;
+ consume(_RKLAMMER);
+ new_dispose_statement:=cerrornode.create;
+ exit;
+ end;
+ { first parameter must be an object or class }
+ if tpointerdef(p.resultdef).pointeddef.typ<>objectdef then
+ begin
+ Message(parser_e_pointer_to_class_expected);
+ p.free;
+ new_dispose_statement:=factor(false,false);
+ consume_all_until(_RKLAMMER);
+ consume(_RKLAMMER);
+ exit;
+ end;
+ { check, if the first parameter is a pointer to a _class_ }
+ classh:=tobjectdef(tpointerdef(p.resultdef).pointeddef);
+ if is_class(classh) then
+ begin
+ Message(parser_e_no_new_or_dispose_for_classes);
+ new_dispose_statement:=factor(false,false);
+ consume_all_until(_RKLAMMER);
+ consume(_RKLAMMER);
+ exit;
+ end;
+ { search cons-/destructor, also in parent classes }
+ storepos:=current_tokenpos;
+ current_tokenpos:=destructorpos;
+ sym:=search_struct_member(classh,destructorname);
+ current_tokenpos:=storepos;
+
+ { the second parameter of new/dispose must be a call }
+ { to a cons-/destructor }
+ if (not assigned(sym)) or (sym.typ<>procsym) then
+ begin
+ if is_new then
+ Message(parser_e_expr_have_to_be_constructor_call)
+ else
+ Message(parser_e_expr_have_to_be_destructor_call);
+ p.free;
+ new_dispose_statement:=cerrornode.create;
+ end
+ else
+ begin
+ { For new(var,constructor) we need to take a copy because
+ p is also used in the assignmentn below }
+ if is_new then
+ begin
+ p2:=cderefnode.create(p.getcopy);
+ include(p2.flags,nf_no_checkpointer);
+ end
+ else
+ p2:=cderefnode.create(p);
+ do_typecheckpass(p2);
+ if is_new then
+ callflag:=cnf_new_call
+ else
+ callflag:=cnf_dispose_call;
+ if is_new then
+ do_member_read(classh,false,sym,p2,again,[callflag])
+ else
+ begin
+ if not(m_fpc in current_settings.modeswitches) then
+ do_member_read(classh,false,sym,p2,again,[callflag])
+ else
+ begin
+ p2:=ccallnode.create(nil,tprocsym(sym),sym.owner,p2,[callflag]);
+ { support dispose(p,done()); }
+ if try_to_consume(_LKLAMMER) then
+ begin
+ if not try_to_consume(_RKLAMMER) then
+ begin
+ Message(parser_e_no_paras_for_destructor);
+ consume_all_until(_RKLAMMER);
+ consume(_RKLAMMER);
+ end;
+ end;
+ end;
+ end;
+
+ { we need the real called method }
+ do_typecheckpass(p2);
+
+ if (p2.nodetype=calln) and
+ assigned(tcallnode(p2).procdefinition) then
+ begin
+ if is_new then
+ begin
+ if (tcallnode(p2).procdefinition.proctypeoption<>potype_constructor) then
+ Message(parser_e_expr_have_to_be_constructor_call);
+ p2.resultdef:=p.resultdef;
+ p2:=cassignmentnode.create(p,p2);
+ end
+ else
+ begin
+ if (tcallnode(p2).procdefinition.proctypeoption<>potype_destructor) then
+ Message(parser_e_expr_have_to_be_destructor_call);
+ end;
+ end
+ else
+ begin
+ if is_new then
+ CGMessage(parser_e_expr_have_to_be_constructor_call)
+ else
+ CGMessage(parser_e_expr_have_to_be_destructor_call);
+ end;
+
+ result:=p2;
+ end;
+ end
+ else
+ begin
+ if (p.resultdef.typ<>pointerdef) then
+ Begin
+ Message1(type_e_pointer_type_expected,p.resultdef.typename);
+ new_dispose_statement:=cerrornode.create;
+ end
+ else
+ begin
+ if (tpointerdef(p.resultdef).pointeddef.typ=objectdef) and
+ (oo_has_vmt in tobjectdef(tpointerdef(p.resultdef).pointeddef).objectoptions) then
+ Message(parser_w_use_extended_syntax_for_objects);
+ if (tpointerdef(p.resultdef).pointeddef.typ=orddef) and
+ (torddef(tpointerdef(p.resultdef).pointeddef).ordtype=uvoid) then
+ begin
+ if (m_tp7 in current_settings.modeswitches) or
+ (m_delphi in current_settings.modeswitches) then
+ Message(parser_w_no_new_dispose_on_void_pointers)
+ else
+ Message(parser_e_no_new_dispose_on_void_pointers);
+ end;
+
+ { create statements with call to getmem+initialize or
+ finalize+freemem }
+ new_dispose_statement:=internalstatements(newstatement);
+
+ if is_new then
+ begin
+ { create temp for result }
+ temp := ctempcreatenode.create(p.resultdef,p.resultdef.size,tt_persistent,true);
+ addstatement(newstatement,temp);
+
+ { create call to fpc_getmem }
+ para := ccallparanode.create(cordconstnode.create
+ (tpointerdef(p.resultdef).pointeddef.size,s32inttype,true),nil);
+ addstatement(newstatement,cassignmentnode.create(
+ ctemprefnode.create(temp),
+ ccallnode.createintern('fpc_getmem',para)));
+
+ { create call to fpc_initialize }
+ if is_managed_type(tpointerdef(p.resultdef).pointeddef) or
+ ((m_iso in current_settings.modeswitches) and (tpointerdef(p.resultdef).pointeddef.typ=filedef)) then
+ addstatement(newstatement,initialize_data_node(cderefnode.create(ctemprefnode.create(temp))));
+
+ { copy the temp to the destination }
+ addstatement(newstatement,cassignmentnode.create(
+ p,
+ ctemprefnode.create(temp)));
+
+ { release temp }
+ addstatement(newstatement,ctempdeletenode.create(temp));
+ end
+ else
+ begin
+ { create call to fpc_finalize }
+ if is_managed_type(tpointerdef(p.resultdef).pointeddef) then
+ addstatement(newstatement,finalize_data_node(cderefnode.create(p.getcopy)));
+
+ { create call to fpc_freemem }
+ para := ccallparanode.create(p,nil);
+ addstatement(newstatement,ccallnode.createintern('fpc_freemem',para));
+ end;
+ end;
+ end;
+ consume(_RKLAMMER);
+ end;
+
+
+ function new_function : tnode;
+ var
+ newstatement : tstatementnode;
+ newblock : tblocknode;
+ temp : ttempcreatenode;
+ para : tcallparanode;
+ p1,p2 : tnode;
+ classh : tobjectdef;
+ srsym : tsym;
+ srsymtable : TSymtable;
+ again : boolean; { dummy for do_proc_call }
+ begin
+ consume(_LKLAMMER);
+ p1:=factor(false,false);
+ if p1.nodetype<>typen then
+ begin
+ Message(type_e_type_id_expected);
+ consume_all_until(_RKLAMMER);
+ consume(_RKLAMMER);
+ p1.destroy;
+ new_function:=cerrornode.create;
+ exit;
+ end;
+
+ if (p1.resultdef.typ<>pointerdef) then
+ begin
+ Message1(type_e_pointer_type_expected,p1.resultdef.typename);
+ consume_all_until(_RKLAMMER);
+ consume(_RKLAMMER);
+ p1.destroy;
+ new_function:=cerrornode.create;
+ exit;
+ end;
+
+ if try_to_consume(_RKLAMMER) then
+ begin
+ if (tpointerdef(p1.resultdef).pointeddef.typ=objectdef) and
+ (oo_has_vmt in tobjectdef(tpointerdef(p1.resultdef).pointeddef).objectoptions) then
+ Message(parser_w_use_extended_syntax_for_objects);
+
+ { create statements with call to getmem+initialize }
+ newblock:=internalstatements(newstatement);
+
+ { create temp for result }
+ temp := ctempcreatenode.create(p1.resultdef,p1.resultdef.size,tt_persistent,true);
+ addstatement(newstatement,temp);
+
+ { create call to fpc_getmem }
+ para := ccallparanode.create(cordconstnode.create
+ (tpointerdef(p1.resultdef).pointeddef.size,s32inttype,true),nil);
+ addstatement(newstatement,cassignmentnode.create(
+ ctemprefnode.create(temp),
+ ccallnode.createintern('fpc_getmem',para)));
+
+ { create call to fpc_initialize }
+ if is_managed_type(tpointerdef(p1.resultdef).pointeddef) then
+ begin
+ para := ccallparanode.create(caddrnode.create_internal(crttinode.create
+ (tstoreddef(tpointerdef(p1.resultdef).pointeddef),initrtti,rdt_normal)),
+ ccallparanode.create(ctemprefnode.create
+ (temp),nil));
+ addstatement(newstatement,ccallnode.createintern('fpc_initialize',para));
+ end;
+
+ { the last statement should return the value as
+ location and type, this is done be referencing the
+ temp and converting it first from a persistent temp to
+ normal temp }
+ addstatement(newstatement,ctempdeletenode.create_normal_temp(temp));
+ addstatement(newstatement,ctemprefnode.create(temp));
+
+ p1.destroy;
+ p1:=newblock;
+ end
+ else
+ begin
+ consume(_COMMA);
+ if tpointerdef(p1.resultdef).pointeddef.typ<>objectdef then
+ begin
+ Message(parser_e_pointer_to_class_expected);
+ consume_all_until(_RKLAMMER);
+ consume(_RKLAMMER);
+ p1.destroy;
+ new_function:=cerrornode.create;
+ exit;
+ end;
+ classh:=tobjectdef(tpointerdef(p1.resultdef).pointeddef);
+ { use the objectdef for loading the VMT }
+ p2:=p1;
+ p1:=ctypenode.create(tpointerdef(p1.resultdef).pointeddef);
+ do_typecheckpass(p1);
+ { search the constructor also in the symbol tables of
+ the parents }
+ afterassignment:=false;
+ searchsym_in_class(classh,classh,pattern,srsym,srsymtable,true);
+ consume(_ID);
+ do_member_read(classh,false,srsym,p1,again,[cnf_new_call]);
+ { we need to know which procedure is called }
+ do_typecheckpass(p1);
+ if not(
+ (p1.nodetype=calln) and
+ assigned(tcallnode(p1).procdefinition) and
+ (tcallnode(p1).procdefinition.proctypeoption=potype_constructor)
+ ) then
+ Message(parser_e_expr_have_to_be_constructor_call);
+ { constructors return boolean, update resultdef to return
+ the pointer to the object }
+ p1.resultdef:=p2.resultdef;
+ p2.free;
+ consume(_RKLAMMER);
+ end;
+ new_function:=p1;
+ end;
+
+
+ function inline_setlength : tnode;
+ var
+ paras : tnode;
+ npara,
+ ppn : tcallparanode;
+ dims,
+ counter : integer;
+ isarray : boolean;
+ def : tdef;
+ destppn : tnode;
+ newstatement : tstatementnode;
+ temp : ttempcreatenode;
+ newblock : tnode;
+ begin
+ { for easy exiting if something goes wrong }
+ result := cerrornode.create;
+
+ consume(_LKLAMMER);
+ paras:=parse_paras(false,false,_RKLAMMER);
+ consume(_RKLAMMER);
+ if not assigned(paras) then
+ begin
+ CGMessage1(parser_e_wrong_parameter_size,'SetLength');
+ exit;
+ end;
+
+ dims:=0;
+ if assigned(paras) then
+ begin
+ { check type of lengths }
+ ppn:=tcallparanode(paras);
+ while assigned(ppn.right) do
+ begin
+ set_varstate(ppn.left,vs_read,[vsf_must_be_valid]);
+ inserttypeconv(ppn.left,sinttype);
+ inc(dims);
+ ppn:=tcallparanode(ppn.right);
+ end;
+ end;
+ if dims=0 then
+ begin
+ CGMessage1(parser_e_wrong_parameter_size,'SetLength');
+ paras.free;
+ exit;
+ end;
+ { last param must be var }
+ destppn:=ppn.left;
+ valid_for_var(destppn,true);
+ set_varstate(destppn,vs_written,[]);
+ { first param must be a string or dynamic array ...}
+ isarray:=is_dynamic_array(destppn.resultdef);
+ if not((destppn.resultdef.typ=stringdef) or
+ isarray) then
+ begin
+ { possibly generic involved? }
+ if df_generic in current_procinfo.procdef.defoptions then
+ begin
+ result.free;
+ result:=internalstatements(newstatement);
+ paras.free;
+ exit;
+ end
+ else
+ begin
+ CGMessage(type_e_mismatch);
+ paras.free;
+ exit;
+ end;
+ end;
+ { only dynamic arrays accept more dimensions }
+ if (dims>1) then
+ begin
+ if (not isarray) then
+ CGMessage(type_e_mismatch)
+ else
+ begin
+ { check if the amount of dimensions is valid }
+ def := tarraydef(destppn.resultdef).elementdef;
+ counter:=dims;
+ while counter > 1 do
+ begin
+ if not(is_dynamic_array(def)) then
+ begin
+ CGMessage1(parser_e_wrong_parameter_size,'SetLength');
+ break;
+ end;
+ dec(counter);
+ def := tarraydef(def).elementdef;
+ end;
+ end;
+ end;
+
+ if isarray then
+ begin
+ { create statements with call initialize the arguments and
+ call fpc_dynarr_setlength }
+ newblock:=internalstatements(newstatement);
+
+ { get temp for array of lengths }
+ temp := ctempcreatenode.create(sinttype,dims*sinttype.size,tt_persistent,false);
+ addstatement(newstatement,temp);
+
+ { load array of lengths }
+ ppn:=tcallparanode(paras);
+ counter:=dims-1;
+ while assigned(ppn.right) do
+ begin
+ addstatement(newstatement,cassignmentnode.create(
+ ctemprefnode.create_offset(temp,counter*sinttype.size),
+ ppn.left));
+ ppn.left:=nil;
+ dec(counter);
+ ppn:=tcallparanode(ppn.right);
+ end;
+ { destppn is also reused }
+ ppn.left:=nil;
+
+ { create call to fpc_dynarr_setlength }
+ npara:=ccallparanode.create(caddrnode.create_internal
+ (ctemprefnode.create(temp)),
+ ccallparanode.create(cordconstnode.create
+ (dims,sinttype,true),
+ ccallparanode.create(caddrnode.create_internal
+ (crttinode.create(tstoreddef(destppn.resultdef),initrtti,rdt_normal)),
+ ccallparanode.create(ctypeconvnode.create_internal(destppn,voidpointertype),nil))));
+ addstatement(newstatement,ccallnode.createintern('fpc_dynarray_setlength',npara));
+ addstatement(newstatement,ctempdeletenode.create(temp));
+
+ { we don't need original the callparanodes tree }
+ paras.free;
+ end
+ else if is_ansistring(destppn.resultdef) then
+ begin
+ newblock:=ccallnode.createintern(
+ 'fpc_'+tstringdef(destppn.resultdef).stringtypname+'_setlength',
+ ccallparanode.create(
+ cordconstnode.create(getparaencoding(destppn.resultdef),u16inttype,true),
+ paras
+ )
+ );
+ end
+ else
+ begin
+ { we can reuse the supplied parameters }
+ newblock:=ccallnode.createintern(
+ 'fpc_'+tstringdef(destppn.resultdef).stringtypname+'_setlength',paras);
+ end;
+
+ result.free;
+ result:=newblock;
+ end;
+
+
+ function inline_initfinal(isinit: boolean): tnode;
+ var
+ newblock,
+ paras : tnode;
+ npara,
+ destppn,
+ ppn : tcallparanode;
+ begin
+ { for easy exiting if something goes wrong }
+ result := cerrornode.create;
+
+ consume(_LKLAMMER);
+ paras:=parse_paras(false,false,_RKLAMMER);
+ consume(_RKLAMMER);
+ ppn:=tcallparanode(paras);
+
+ if not assigned(paras) or
+ (assigned(ppn.right) and
+ assigned(tcallparanode(ppn.right).right)) then
+ begin
+ if isinit then
+ CGMessage1(parser_e_wrong_parameter_size,'Initialize')
+ else
+ CGMessage1(parser_e_wrong_parameter_size,'Finalize');
+ exit;
+ end;
+
+ { 2 arguments? }
+ if assigned(ppn.right) then
+ begin
+ destppn:=tcallparanode(ppn.right);
+ { create call to fpc_initialize/finalize_array }
+ npara:=ccallparanode.create(ctypeconvnode.create
+ (ppn.left,s32inttype),
+ ccallparanode.create(caddrnode.create_internal
+ (crttinode.create(tstoreddef(destppn.left.resultdef),initrtti,rdt_normal)),
+ ccallparanode.create(caddrnode.create_internal
+ (destppn.left),nil)));
+ if isinit then
+ newblock:=ccallnode.createintern('fpc_initialize_array',npara)
+ else
+ newblock:=ccallnode.createintern('fpc_finalize_array',npara);
+ destppn.left:=nil;
+ end
+ else
+ begin
+ if isinit then
+ newblock:=initialize_data_node(ppn.left)
+ else
+ newblock:=finalize_data_node(ppn.left);
+ end;
+ ppn.left:=nil;
+ paras.free;
+ result.free;
+ result:=newblock;
+ end;
+
+
+ function inline_initialize : tnode;
+ begin
+ result:=inline_initfinal(true);
+ end;
+
+
+ function inline_finalize : tnode;
+ begin
+ result:=inline_initfinal(false);
+ end;
+
+
+ function inline_copy : tnode;
+ var
+ copynode,
+ lowppn,
+ highppn,
+ npara,
+ paras : tnode;
+ ppn : tcallparanode;
+ paradef : tdef;
+ counter : integer;
+ begin
+ { for easy exiting if something goes wrong }
+ result := cerrornode.create;
+
+ consume(_LKLAMMER);
+ paras:=parse_paras(false,false,_RKLAMMER);
+ consume(_RKLAMMER);
+ if not assigned(paras) then
+ begin
+ CGMessage1(parser_e_wrong_parameter_size,'Copy');
+ exit;
+ end;
+
+ { determine copy function to use based on the first argument,
+ also count the number of arguments in this loop }
+ counter:=1;
+ ppn:=tcallparanode(paras);
+ while assigned(ppn.right) do
+ begin
+ inc(counter);
+ ppn:=tcallparanode(ppn.right);
+ end;
+ paradef:=ppn.left.resultdef;
+ if is_ansistring(paradef) or
+ (is_chararray(paradef) and
+ (paradef.size>255)) or
+ ((cs_ansistrings in current_settings.localswitches) and
+ is_pchar(paradef)) then
+ copynode:=ccallnode.createintern('fpc_ansistr_copy',paras)
+ else
+ if is_widestring(paradef) then
+ copynode:=ccallnode.createintern('fpc_widestr_copy',paras)
+ else
+ if is_unicodestring(paradef) or
+ is_widechararray(paradef) or
+ is_pwidechar(paradef) then
+ copynode:=ccallnode.createintern('fpc_unicodestr_copy',paras)
+ else
+ if is_char(paradef) then
+ copynode:=ccallnode.createintern('fpc_char_copy',paras)
+ else
+ if is_dynamic_array(paradef) then
+ begin
+ { Only allow 1 or 3 arguments }
+ if (counter<>1) and (counter<>3) then
+ begin
+ CGMessage1(parser_e_wrong_parameter_size,'Copy');
+ exit;
+ end;
+
+ { create statements with call }
+
+ if (counter=3) then
+ begin
+ highppn:=tcallparanode(paras).left.getcopy;
+ lowppn:=tcallparanode(tcallparanode(paras).right).left.getcopy;
+ end
+ else
+ begin
+ { use special -1,-1 argument to copy the whole array }
+ highppn:=cordconstnode.create(int64(-1),s32inttype,false);
+ lowppn:=cordconstnode.create(int64(-1),s32inttype,false);
+ end;
+
+ { create call to fpc_dynarray_copy }
+ npara:=ccallparanode.create(highppn,
+ ccallparanode.create(lowppn,
+ ccallparanode.create(caddrnode.create_internal
+ (crttinode.create(tstoreddef(ppn.left.resultdef),initrtti,rdt_normal)),
+ ccallparanode.create
+ (ctypeconvnode.create_internal(ppn.left,voidpointertype),nil))));
+ copynode:=ccallnode.createinternres('fpc_dynarray_copy',npara,ppn.left.resultdef);
+
+ ppn.left:=nil;
+ paras.free;
+ end
+ else
+ begin
+ { generic fallback that will give an error if a wrong
+ type is passed }
+ if (counter=3) then
+ copynode:=ccallnode.createintern('fpc_shortstr_copy',paras)
+ else
+ begin
+ CGMessagePos(ppn.left.fileinfo,type_e_mismatch);
+ copynode:=cerrornode.create;
+ end
+ end;
+
+ result.free;
+ result:=copynode;
+ end;
+
+end.
diff --git a/closures/compiler/pmodules.pas b/closures/compiler/pmodules.pas
new file mode 100644
index 0000000000..d8c64a1124
--- /dev/null
+++ b/closures/compiler/pmodules.pas
@@ -0,0 +1,2523 @@
+{
+ Copyright (c) 1998-2008 by Florian Klaempfl
+
+ Handles the parsing and loading of the modules (ppufiles)
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit pmodules;
+
+{$i fpcdefs.inc}
+
+interface
+
+ procedure proc_unit;
+ procedure proc_package;
+ procedure proc_program(islibrary : boolean);
+
+implementation
+
+ uses
+ SysUtils,
+ globtype,version,systems,tokens,
+ cutils,cfileutl,cclasses,comphook,
+ globals,verbose,fmodule,finput,fppu,
+ symconst,symbase,symtype,symdef,symsym,symtable,
+ wpoinfo,
+ aasmtai,aasmdata,aasmcpu,aasmbase,
+ cgbase,cgobj,
+ nbas,nutils,ncgutil,
+ link,assemble,import,export,gendef,ppu,comprsrc,dbgbase,
+ cresstr,procinfo,
+ pexports,
+ objcgutl,
+ wpobase,
+ scanner,pbase,pexpr,psystem,psub,pdecsub,ptype,
+ cpuinfo;
+
+
+ procedure create_objectfile;
+ var
+ DLLScanner : TDLLScanner;
+ s : string;
+ KeepShared : TCmdStrList;
+ begin
+ { try to create import entries from system dlls }
+ if (tf_has_dllscanner in target_info.flags) and
+ (not current_module.linkOtherSharedLibs.Empty) then
+ begin
+ { Init DLLScanner }
+ if assigned(CDLLScanner[target_info.system]) then
+ DLLScanner:=CDLLScanner[target_info.system].Create
+ else
+ internalerror(200104121);
+ KeepShared:=TCmdStrList.Create;
+ { Walk all shared libs }
+ While not current_module.linkOtherSharedLibs.Empty do
+ begin
+ S:=current_module.linkOtherSharedLibs.Getusemask(link_always);
+ if not DLLScanner.scan(s) then
+ KeepShared.Concat(s);
+ end;
+ DLLscanner.Free;
+ { Recreate import section }
+ if (target_info.system in [system_i386_win32,system_i386_wdosx]) then
+ begin
+ if assigned(current_asmdata.asmlists[al_imports]) then
+ current_asmdata.asmlists[al_imports].clear
+ else
+ current_asmdata.asmlists[al_imports]:=TAsmList.Create;
+ importlib.generatelib;
+ end;
+ { Readd the not processed files }
+ while not KeepShared.Empty do
+ begin
+ s:=KeepShared.GetFirst;
+ current_module.linkOtherSharedLibs.add(s,link_always);
+ end;
+ KeepShared.Free;
+ end;
+
+ { Start and end module debuginfo, at least required for stabs
+ to insert n_sourcefile lines }
+ if (cs_debuginfo in current_settings.moduleswitches) or
+ (cs_use_lineinfo in current_settings.globalswitches) then
+ current_debuginfo.insertmoduleinfo;
+
+ { create the .s file and assemble it }
+ GenerateAsm(false);
+
+ { Also create a smartlinked version ? }
+ if create_smartlink_library then
+ begin
+ GenerateAsm(true);
+ if (af_needar in target_asm.flags) then
+ Linker.MakeStaticLibrary;
+ end;
+
+ { resource files }
+ CompileResourceFiles;
+ end;
+
+
+ procedure insertobjectfile;
+ { Insert the used object file for this unit in the used list for this unit }
+ begin
+ current_module.linkunitofiles.add(current_module.objfilename^,link_static);
+ current_module.flags:=current_module.flags or uf_static_linked;
+
+ if create_smartlink_library then
+ begin
+ current_module.linkunitstaticlibs.add(current_module.staticlibfilename^,link_smart);
+ current_module.flags:=current_module.flags or uf_smart_linked;
+ end;
+ end;
+
+
+ procedure create_dwarf_frame;
+ begin
+ { Dwarf conflicts with smartlinking in separate .a files }
+ if create_smartlink_library then
+ exit;
+ { Call frame information }
+ { MWE: we write our own info, so dwarf asm support is not really needed }
+ { if (af_supports_dwarf in target_asm.flags) and }
+ { CFI is currently broken for Darwin }
+ if not(target_info.system in systems_darwin) and
+ (
+ (tf_needs_dwarf_cfi in target_info.flags) or
+ (paratargetdbg in [dbg_dwarf2, dbg_dwarf3])
+ ) then
+ begin
+ current_asmdata.asmlists[al_dwarf_frame].Free;
+ current_asmdata.asmlists[al_dwarf_frame] := TAsmList.create;
+ current_asmdata.asmcfi.generate_code(current_asmdata.asmlists[al_dwarf_frame]);
+ end;
+ end;
+
+
+ procedure InsertThreadvarTablesTable;
+ var
+ hp : tused_unit;
+ ltvTables : TAsmList;
+ count : longint;
+ begin
+ if (tf_section_threadvars in target_info.flags) then
+ exit;
+ ltvTables:=TAsmList.Create;
+ count:=0;
+ hp:=tused_unit(usedunits.first);
+ while assigned(hp) do
+ begin
+ If (hp.u.flags and uf_threadvars)=uf_threadvars then
+ begin
+ ltvTables.concat(Tai_const.Createname(make_mangledname('THREADVARLIST',hp.u.globalsymtable,''),0));
+ inc(count);
+ end;
+ hp:=tused_unit(hp.next);
+ end;
+ { Add program threadvars, if any }
+ If (current_module.flags and uf_threadvars)=uf_threadvars then
+ begin
+ ltvTables.concat(Tai_const.Createname(make_mangledname('THREADVARLIST',current_module.localsymtable,''),0));
+ inc(count);
+ end;
+ { Insert TableCount at start }
+ ltvTables.insert(Tai_const.Create_32bit(count));
+ { insert in data segment }
+ maybe_new_object_file(current_asmdata.asmlists[al_globals]);
+ new_section(current_asmdata.asmlists[al_globals],sec_data,'FPC_THREADVARTABLES',sizeof(pint));
+ current_asmdata.asmlists[al_globals].concat(Tai_symbol.Createname_global('FPC_THREADVARTABLES',AT_DATA,0));
+ current_asmdata.asmlists[al_globals].concatlist(ltvTables);
+ current_asmdata.asmlists[al_globals].concat(Tai_symbol_end.Createname('FPC_THREADVARTABLES'));
+ ltvTables.free;
+ end;
+
+ procedure AddToThreadvarList(p:TObject;arg:pointer);
+ var
+ ltvTable : TAsmList;
+ begin
+ ltvTable:=TAsmList(arg);
+ if (tsym(p).typ=staticvarsym) and
+ (vo_is_thread_var in tstaticvarsym(p).varoptions) then
+ begin
+ { address of threadvar }
+ ltvTable.concat(tai_const.Createname(tstaticvarsym(p).mangledname,0));
+ { size of threadvar }
+ ltvTable.concat(tai_const.create_32bit(tstaticvarsym(p).getsize));
+ end;
+ end;
+
+
+ procedure InsertThreadvars;
+ var
+ s : string;
+ ltvTable : TAsmList;
+ begin
+ if (tf_section_threadvars in target_info.flags) then
+ exit;
+ ltvTable:=TAsmList.create;
+ if assigned(current_module.globalsymtable) then
+ current_module.globalsymtable.SymList.ForEachCall(@AddToThreadvarList,ltvTable);
+ current_module.localsymtable.SymList.ForEachCall(@AddToThreadvarList,ltvTable);
+ if ltvTable.first<>nil then
+ begin
+ s:=make_mangledname('THREADVARLIST',current_module.localsymtable,'');
+ { end of the list marker }
+ ltvTable.concat(tai_const.create_sym(nil));
+ { add to datasegment }
+ maybe_new_object_file(current_asmdata.asmlists[al_globals]);
+ new_section(current_asmdata.asmlists[al_globals],sec_data,s,sizeof(pint));
+ current_asmdata.asmlists[al_globals].concat(Tai_symbol.Createname_global(s,AT_DATA,0));
+ current_asmdata.asmlists[al_globals].concatlist(ltvTable);
+ current_asmdata.asmlists[al_globals].concat(Tai_symbol_end.Createname(s));
+ current_module.flags:=current_module.flags or uf_threadvars;
+ end;
+ ltvTable.Free;
+ end;
+
+ procedure InsertRuntimeInits(const prefix:string;list:TLinkedList;unitflag:cardinal);
+ var
+ s: string;
+ item: TTCInitItem;
+ begin
+ item:=TTCInitItem(list.First);
+ if item=nil then
+ exit;
+ s:=make_mangledname(prefix,current_module.localsymtable,'');
+ maybe_new_object_file(current_asmdata.asmlists[al_globals]);
+ new_section(current_asmdata.asmlists[al_globals],sec_data,s,sizeof(pint));
+ current_asmdata.asmlists[al_globals].concat(Tai_symbol.Createname_global(s,AT_DATA,0));
+ repeat
+ { optimize away unused local/static symbols }
+ if (item.sym.refs>0) or (item.sym.owner.symtabletype=globalsymtable) then
+ begin
+ { address to initialize }
+ current_asmdata.asmlists[al_globals].concat(Tai_const.createname(item.sym.mangledname, item.offset));
+ { value with which to initialize }
+ current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(item.datalabel));
+ end;
+ item:=TTCInitItem(item.Next);
+ until item=nil;
+ { end-of-list marker }
+ current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(nil));
+ current_asmdata.asmlists[al_globals].concat(Tai_symbol_end.Createname(s));
+ current_module.flags:=current_module.flags or unitflag;
+ end;
+
+ procedure InsertRuntimeInitsTablesTable(const prefix,tablename:string;unitflag:cardinal);
+ var
+ hp: tused_unit;
+ hlist: TAsmList;
+ count: longint;
+ begin
+ hlist:=TAsmList.Create;
+ count:=0;
+ hp:=tused_unit(usedunits.first);
+ while assigned(hp) do
+ begin
+ if (hp.u.flags and unitflag)=unitflag then
+ begin
+ hlist.concat(Tai_const.Createname(make_mangledname(prefix,hp.u.globalsymtable,''),0));
+ inc(count);
+ end;
+ hp:=tused_unit(hp.next);
+ end;
+ { Add items from program, if any }
+ if (current_module.flags and unitflag)=unitflag then
+ begin
+ hlist.concat(Tai_const.Createname(make_mangledname(prefix,current_module.localsymtable,''),0));
+ inc(count);
+ end;
+ { Insert TableCount at start }
+ hlist.insert(Tai_const.Create_32bit(count));
+ { insert in data segment }
+ maybe_new_object_file(current_asmdata.asmlists[al_globals]);
+ new_section(current_asmdata.asmlists[al_globals],sec_data,tablename,sizeof(pint));
+ current_asmdata.asmlists[al_globals].concat(Tai_symbol.Createname_global(tablename,AT_DATA,0));
+ current_asmdata.asmlists[al_globals].concatlist(hlist);
+ current_asmdata.asmlists[al_globals].concat(Tai_symbol_end.Createname(tablename));
+ hlist.free;
+ end;
+
+ procedure InsertWideInits;
+ begin
+ InsertRuntimeInits('WIDEINITS',current_asmdata.WideInits,uf_wideinits);
+ end;
+
+ procedure InsertResStrInits;
+ begin
+ InsertRuntimeInits('RESSTRINITS',current_asmdata.ResStrInits,uf_resstrinits);
+ end;
+
+ procedure InsertWideInitsTablesTable;
+ begin
+ InsertRuntimeInitsTablesTable('WIDEINITS','FPC_WIDEINITTABLES',uf_wideinits);
+ end;
+
+ procedure InsertResStrTablesTable;
+ begin
+ InsertRuntimeInitsTablesTable('RESSTRINITS','FPC_RESSTRINITTABLES',uf_resstrinits);
+ end;
+
+ Function CheckResourcesUsed : boolean;
+ var
+ hp : tused_unit;
+ found : Boolean;
+ begin
+ CheckResourcesUsed:=tf_has_winlike_resources in target_info.flags;
+ if not CheckResourcesUsed then exit;
+
+ hp:=tused_unit(usedunits.first);
+ found:=((current_module.flags and uf_has_resourcefiles)=uf_has_resourcefiles);
+ If not found then
+ While Assigned(hp) and not found do
+ begin
+ Found:=((hp.u.flags and uf_has_resourcefiles)=uf_has_resourcefiles);
+ hp:=tused_unit(hp.next);
+ end;
+ CheckResourcesUsed:=found;
+ end;
+
+ Procedure InsertResourceInfo(ResourcesUsed : boolean);
+
+ var
+ ResourceInfo : TAsmList;
+
+ begin
+ if (target_res.id in [res_elf,res_macho]) then
+ begin
+ ResourceInfo:=TAsmList.Create;
+
+ maybe_new_object_file(ResourceInfo);
+ new_section(ResourceInfo,sec_data,'FPC_RESLOCATION',sizeof(aint));
+ ResourceInfo.concat(Tai_symbol.Createname_global('FPC_RESLOCATION',AT_DATA,0));
+ if ResourcesUsed then
+ { Valid pointer to resource information }
+ ResourceInfo.concat(Tai_const.Createname('FPC_RESSYMBOL',0))
+ else
+ { Nil pointer to resource information }
+ {$IFNDEF cpu64bitaddr}
+ ResourceInfo.Concat(Tai_const.Create_32bit(0));
+ {$ELSE}
+ ResourceInfo.Concat(Tai_const.Create_64bit(0));
+ {$ENDIF}
+ maybe_new_object_file(current_asmdata.asmlists[al_globals]);
+ current_asmdata.asmlists[al_globals].concatlist(ResourceInfo);
+ ResourceInfo.free;
+ end;
+ end;
+
+
+ Procedure InsertResourceTablesTable;
+ var
+ hp : tmodule;
+ ResourceStringTables : tasmlist;
+ count : longint;
+ begin
+ ResourceStringTables:=tasmlist.Create;
+ count:=0;
+ hp:=tmodule(loaded_units.first);
+ while assigned(hp) do
+ begin
+ If (hp.flags and uf_has_resourcestrings)=uf_has_resourcestrings then
+ begin
+ ResourceStringTables.concat(Tai_const.Createname(make_mangledname('RESSTR',hp.localsymtable,'START'),0));
+ ResourceStringTables.concat(Tai_const.Createname(make_mangledname('RESSTR',hp.localsymtable,'END'),0));
+ inc(count);
+ end;
+ hp:=tmodule(hp.next);
+ end;
+ { Insert TableCount at start }
+ ResourceStringTables.insert(Tai_const.Create_pint(count));
+ { Add to data segment }
+ maybe_new_object_file(current_asmdata.AsmLists[al_globals]);
+ new_section(current_asmdata.AsmLists[al_globals],sec_data,'FPC_RESOURCESTRINGTABLES',sizeof(pint));
+ current_asmdata.AsmLists[al_globals].concat(Tai_symbol.Createname_global('FPC_RESOURCESTRINGTABLES',AT_DATA,0));
+ current_asmdata.AsmLists[al_globals].concatlist(ResourceStringTables);
+ current_asmdata.AsmLists[al_globals].concat(Tai_symbol_end.Createname('FPC_RESOURCESTRINGTABLES'));
+ ResourceStringTables.free;
+ end;
+
+ procedure AddToStructInits(p:TObject;arg:pointer);
+ var
+ StructList: TFPList absolute arg;
+ begin
+ if (tdef(p).typ in [objectdef,recorddef]) and
+ ([oo_has_class_constructor,oo_has_class_destructor] * tabstractrecorddef(p).objectoptions <> []) then
+ StructList.Add(p);
+ end;
+
+ procedure InsertInitFinalTable;
+ var
+ hp : tused_unit;
+ unitinits : TAsmList;
+ count : longint;
+
+ procedure write_struct_inits(u: tmodule);
+ var
+ i: integer;
+ structlist: TFPList;
+ pd: tprocdef;
+ begin
+ structlist := TFPList.Create;
+ if assigned(u.globalsymtable) then
+ u.globalsymtable.DefList.ForEachCall(@AddToStructInits,structlist);
+ u.localsymtable.DefList.ForEachCall(@AddToStructInits,structlist);
+ { write structures }
+ for i := 0 to structlist.Count - 1 do
+ begin
+ pd := tabstractrecorddef(structlist[i]).find_procdef_bytype(potype_class_constructor);
+ if assigned(pd) then
+ unitinits.concat(Tai_const.Createname(pd.mangledname,0))
+ else
+ unitinits.concat(Tai_const.Create_pint(0));
+ pd := tabstractrecorddef(structlist[i]).find_procdef_bytype(potype_class_destructor);
+ if assigned(pd) then
+ unitinits.concat(Tai_const.Createname(pd.mangledname,0))
+ else
+ unitinits.concat(Tai_const.Create_pint(0));
+ inc(count);
+ end;
+ structlist.free;
+ end;
+
+ begin
+ unitinits:=TAsmList.Create;
+ count:=0;
+ hp:=tused_unit(usedunits.first);
+ while assigned(hp) do
+ begin
+ { insert class constructors/destructors of the unit }
+ if (hp.u.flags and uf_classinits) <> 0 then
+ write_struct_inits(hp.u);
+ { call the unit init code and make it external }
+ if (hp.u.flags and (uf_init or uf_finalize))<>0 then
+ begin
+ if (hp.u.flags and uf_init)<>0 then
+ unitinits.concat(Tai_const.Createname(make_mangledname('INIT$',hp.u.globalsymtable,''),0))
+ else
+ unitinits.concat(Tai_const.Create_sym(nil));
+ if (hp.u.flags and uf_finalize)<>0 then
+ unitinits.concat(Tai_const.Createname(make_mangledname('FINALIZE$',hp.u.globalsymtable,''),0))
+ else
+ unitinits.concat(Tai_const.Create_sym(nil));
+ inc(count);
+ end;
+ hp:=tused_unit(hp.next);
+ end;
+ { insert class constructors/destructor of the program }
+ if (current_module.flags and uf_classinits) <> 0 then
+ write_struct_inits(current_module);
+ { Insert initialization/finalization of the program }
+ if (current_module.flags and (uf_init or uf_finalize))<>0 then
+ begin
+ if (current_module.flags and uf_init)<>0 then
+ unitinits.concat(Tai_const.Createname(make_mangledname('INIT$',current_module.localsymtable,''),0))
+ else
+ unitinits.concat(Tai_const.Create_sym(nil));
+ if (current_module.flags and uf_finalize)<>0 then
+ unitinits.concat(Tai_const.Createname(make_mangledname('FINALIZE$',current_module.localsymtable,''),0))
+ else
+ unitinits.concat(Tai_const.Create_sym(nil));
+ inc(count);
+ end;
+ { Insert TableCount,InitCount at start }
+ unitinits.insert(Tai_const.Create_32bit(0));
+ unitinits.insert(Tai_const.Create_32bit(count));
+ { Add to data segment }
+ maybe_new_object_file(current_asmdata.asmlists[al_globals]);
+ new_section(current_asmdata.asmlists[al_globals],sec_data,'INITFINAL',sizeof(pint));
+ current_asmdata.asmlists[al_globals].concat(Tai_symbol.Createname_global('INITFINAL',AT_DATA,0));
+ current_asmdata.asmlists[al_globals].concatlist(unitinits);
+ current_asmdata.asmlists[al_globals].concat(Tai_symbol_end.Createname('INITFINAL'));
+ unitinits.free;
+ end;
+
+
+ procedure InsertMemorySizes;
+{$IFDEF POWERPC}
+ var
+ stkcookie: string;
+{$ENDIF POWERPC}
+ begin
+ maybe_new_object_file(current_asmdata.asmlists[al_globals]);
+ { Insert Ident of the compiler in the .fpc.version section }
+ new_section(current_asmdata.asmlists[al_globals],sec_fpc,'version',const_align(32));
+ current_asmdata.asmlists[al_globals].concat(Tai_string.Create('FPC '+full_version_string+
+ ' ['+date_string+'] for '+target_cpu_string+' - '+target_info.shortname));
+ if not(tf_no_generic_stackcheck in target_info.flags) then
+ begin
+ { stacksize can be specified and is now simulated }
+ new_section(current_asmdata.asmlists[al_globals],sec_data,'__stklen', sizeof(pint));
+ current_asmdata.asmlists[al_globals].concat(Tai_symbol.Createname_global('__stklen',AT_DATA,sizeof(pint)));
+ current_asmdata.asmlists[al_globals].concat(Tai_const.Create_pint(stacksize));
+ end;
+{$IFDEF POWERPC}
+ { AmigaOS4 "stack cookie" support }
+ if ( target_info.system = system_powerpc_amiga ) then
+ begin
+ { this symbol is needed to ignite powerpc amigaos' }
+ { stack allocation magic for us with the given stack size. }
+ { note: won't work for m68k amigaos or morphos. (KB) }
+ str(stacksize,stkcookie);
+ stkcookie:='$STACK: '+stkcookie+#0;
+ maybe_new_object_file(current_asmdata.asmlists[al_globals]);
+ new_section(current_asmdata.asmlists[al_globals],sec_data,'__stack_cookie',length(stkcookie));
+ current_asmdata.asmlists[al_globals].concat(Tai_symbol.Createname_global('__stack_cookie',AT_DATA,length(stkcookie)));
+ current_asmdata.asmlists[al_globals].concat(Tai_string.Create(stkcookie));
+ end;
+{$ENDIF POWERPC}
+ { Initial heapsize }
+ maybe_new_object_file(current_asmdata.asmlists[al_globals]);
+ new_section(current_asmdata.asmlists[al_globals],sec_data,'__heapsize',sizeof(pint));
+ current_asmdata.asmlists[al_globals].concat(Tai_symbol.Createname_global('__heapsize',AT_DATA,sizeof(pint)));
+ current_asmdata.asmlists[al_globals].concat(Tai_const.Create_pint(heapsize));
+ { Initial heapsize }
+ maybe_new_object_file(current_asmdata.asmlists[al_globals]);
+ new_section(current_asmdata.asmlists[al_globals],sec_data,'__fpc_valgrind',sizeof(boolean));
+ current_asmdata.asmlists[al_globals].concat(Tai_symbol.Createname_global('__fpc_valgrind',AT_DATA,sizeof(boolean)));
+ current_asmdata.asmlists[al_globals].concat(Tai_const.create_8bit(byte(cs_gdb_valgrind in current_settings.globalswitches)));
+ end;
+
+
+ procedure AddUnit(const s:string);
+ var
+ hp : tppumodule;
+ unitsym : tunitsym;
+ begin
+ { load unit }
+ hp:=registerunit(current_module,s,'');
+ hp.loadppu;
+ hp.adddependency(current_module);
+ { add to symtable stack }
+ symtablestack.push(hp.globalsymtable);
+ if (m_mac in current_settings.modeswitches) and
+ assigned(hp.globalmacrosymtable) then
+ macrosymtablestack.push(hp.globalmacrosymtable);
+ { insert unitsym }
+ unitsym:=tunitsym.create(s,hp);
+ inc(unitsym.refs);
+ tabstractunitsymtable(current_module.localsymtable).insertunit(unitsym);
+ { add to used units }
+ current_module.addusedunit(hp,false,unitsym);
+ end;
+
+
+ procedure maybeloadvariantsunit;
+ var
+ hp : tmodule;
+ begin
+ { Do we need the variants unit? Skip this
+ for VarUtils unit for bootstrapping }
+ if (current_module.flags and uf_uses_variants=0) or
+ (current_module.modulename^='VARUTILS') then
+ exit;
+ { Variants unit already loaded? }
+ hp:=tmodule(loaded_units.first);
+ while assigned(hp) do
+ begin
+ if hp.modulename^='VARIANTS' then
+ exit;
+ hp:=tmodule(hp.next);
+ end;
+ { Variants unit is not loaded yet, load it now }
+ Message(parser_w_implicit_uses_of_variants_unit);
+ AddUnit('variants');
+ end;
+
+
+ function MaybeRemoveResUnit : boolean;
+ var
+ resources_used : boolean;
+ hp : tmodule;
+ uu : tused_unit;
+ unitname : shortstring;
+ begin
+ { We simply remove the unit from:
+ - usedunit list, so that things like init/finalization table won't
+ contain references to this unit
+ - loaded_units list, so that the unit object file doesn't get linked
+ with the executable. }
+ { Note: on windows we always need resources! }
+ resources_used:=(target_info.system in systems_all_windows)
+ or CheckResourcesUsed;
+ if (not resources_used) and (tf_has_winlike_resources in target_info.flags) then
+ begin
+ { resources aren't used, so we don't need this unit }
+ if target_res.id=res_ext then
+ unitname:='FPEXTRES'
+ else
+ unitname:='FPINTRES';
+ Message1(unit_u_unload_resunit,unitname);
+ { find the module }
+ hp:=tmodule(loaded_units.first);
+ while assigned(hp) do
+ begin
+ if hp.is_unit and (hp.modulename^=unitname) then break;
+ hp:=tmodule(hp.next);
+ end;
+ if not assigned(hp) then
+ internalerror(200801071);
+ { find its tused_unit in the global list }
+ uu:=tused_unit(usedunits.first);
+ while assigned(uu) do
+ begin
+ if uu.u=hp then break;
+ uu:=tused_unit(uu.next);
+ end;
+ if not assigned(uu) then
+ internalerror(200801072);
+ { remove the tused_unit }
+ usedunits.Remove(uu);
+ uu.Free;
+ { remove the module }
+ loaded_units.Remove(hp);
+ unloaded_units.Concat(hp);
+ end;
+ MaybeRemoveResUnit:=resources_used;
+ end;
+
+
+ procedure loaddefaultunits;
+ begin
+ { we are going to rebuild the symtablestack, clear it first }
+ symtablestack.clear;
+ macrosymtablestack.clear;
+
+ { macro symtable }
+ macrosymtablestack.push(initialmacrosymtable);
+
+ { are we compiling the system unit? }
+ if (cs_compilesystem in current_settings.moduleswitches) then
+ begin
+ systemunit:=tglobalsymtable(current_module.localsymtable);
+ { create system defines }
+ create_intern_symbols;
+ create_intern_types;
+ { Set the owner of errorsym and errortype to symtable to
+ prevent crashes when accessing .owner }
+ generrorsym.owner:=systemunit;
+ generrordef.owner:=systemunit;
+ exit;
+ end;
+
+ { insert the system unit, it is allways the first. Load also the
+ internal types from the system unit }
+ AddUnit('system');
+ systemunit:=tglobalsymtable(symtablestack.top);
+ load_intern_types;
+
+ { Set the owner of errorsym and errortype to symtable to
+ prevent crashes when accessing .owner }
+ generrorsym.owner:=systemunit;
+ generrordef.owner:=systemunit;
+
+ { Units only required for main module }
+ if not(current_module.is_unit) then
+ begin
+ { Heaptrc unit, load heaptrace before any other units especially objpas }
+ if (cs_use_heaptrc in current_settings.globalswitches) then
+ AddUnit('heaptrc');
+ { Lineinfo unit }
+ if (cs_use_lineinfo in current_settings.globalswitches) then begin
+ if (paratargetdbg = dbg_stabs) then
+ AddUnit('lineinfo')
+ else
+ AddUnit('lnfodwrf');
+ end;
+ { Valgrind requires c memory manager }
+ if (cs_gdb_valgrind in current_settings.globalswitches) then
+ AddUnit('cmem');
+{$ifdef cpufpemu}
+ { Floating point emulation unit?
+ softfpu must be in the system unit anyways (FK)
+ if (cs_fp_emulation in current_settings.moduleswitches) and not(target_info.system in system_wince) then
+ AddUnit('softfpu');
+ }
+{$endif cpufpemu}
+ { Which kind of resource support?
+ Note: if resources aren't used this unit will be removed later,
+ otherwise we need it here since it must be loaded quite early }
+ if (tf_has_winlike_resources in target_info.flags) then
+ if target_res.id=res_ext then
+ AddUnit('fpextres')
+ else
+ AddUnit('fpintres');
+ end;
+ { Objpas unit? }
+ if m_objpas in current_settings.modeswitches then
+ AddUnit('objpas');
+
+ { Macpas unit? }
+ if m_mac in current_settings.modeswitches then
+ AddUnit('macpas');
+
+ if m_iso in current_settings.modeswitches then
+ AddUnit('iso7185');
+
+ { Objective-C support unit? }
+ if (m_objectivec1 in current_settings.modeswitches) then
+ begin
+ { interface to Objective-C run time }
+ AddUnit('objc');
+ loadobjctypes;
+ { NSObject }
+ if not(current_module.is_unit) or
+ (current_module.modulename^<>'OBJCBASE') then
+ AddUnit('objcbase');
+ end;
+ { Profile unit? Needed for go32v2 only }
+ if (cs_profile in current_settings.moduleswitches) and
+ (target_info.system in [system_i386_go32v2,system_i386_watcom]) then
+ AddUnit('profile');
+ if (cs_load_fpcylix_unit in current_settings.globalswitches) then
+ begin
+ AddUnit('fpcylix');
+ AddUnit('dynlibs');
+ end;
+
+ { CPU targets with microcontroller support can add a controller specific unit }
+{$if defined(ARM) or defined(AVR)}
+ if (target_info.system in systems_embedded) and (current_settings.controllertype<>ct_none) and
+ (embedded_controllers[current_settings.controllertype].controllerunitstr<>'') then
+ AddUnit(embedded_controllers[current_settings.controllertype].controllerunitstr);
+{$endif ARM}
+ end;
+
+
+ procedure loadautounits;
+ var
+ hs,s : string;
+ begin
+ hs:=autoloadunits;
+ repeat
+ s:=GetToken(hs,',');
+ if s='' then
+ break;
+ AddUnit(s);
+ until false;
+ end;
+
+
+ procedure loadunits;
+ var
+ s,sorg : ansistring;
+ fn : string;
+ pu : tused_unit;
+ hp2 : tmodule;
+ unitsym : tunitsym;
+ begin
+ consume(_USES);
+ repeat
+ s:=pattern;
+ sorg:=orgpattern;
+ consume(_ID);
+ while token=_POINT do
+ begin
+ consume(_POINT);
+ s:=s+'.'+pattern;
+ sorg:=sorg+'.'+orgpattern;
+ consume(_ID);
+ end;
+ { support "<unit> in '<file>'" construct, but not for tp7 }
+ fn:='';
+ if not(m_tp7 in current_settings.modeswitches) and
+ try_to_consume(_OP_IN) then
+ fn:=FixFileName(get_stringconst);
+ { Give a warning if lineinfo is loaded }
+ if s='LINEINFO' then begin
+ Message(parser_w_no_lineinfo_use_switch);
+ if (paratargetdbg in [dbg_dwarf2, dbg_dwarf3]) then
+ s := 'LNFODWRF';
+ sorg := s;
+ end;
+ { Give a warning if objpas is loaded }
+ if s='OBJPAS' then
+ Message(parser_w_no_objpas_use_mode);
+ { Using the unit itself is not possible }
+ if (s<>current_module.modulename^) then
+ begin
+ { check if the unit is already used }
+ hp2:=nil;
+ pu:=tused_unit(current_module.used_units.first);
+ while assigned(pu) do
+ begin
+ if (pu.u.modulename^=s) then
+ begin
+ hp2:=pu.u;
+ break;
+ end;
+ pu:=tused_unit(pu.next);
+ end;
+ if not assigned(hp2) then
+ hp2:=registerunit(current_module,sorg,fn)
+ else
+ Message1(sym_e_duplicate_id,s);
+ { Create unitsym, we need to use the name as specified, we
+ can not use the modulename because that can be different
+ when -Un is used }
+ unitsym:=tunitsym.create(sorg,nil);
+ tabstractunitsymtable(current_module.localsymtable).insertunit(unitsym);
+ { the current module uses the unit hp2 }
+ current_module.addusedunit(hp2,true,unitsym);
+ end
+ else
+ Message1(sym_e_duplicate_id,s);
+ if token=_COMMA then
+ begin
+ pattern:='';
+ consume(_COMMA);
+ end
+ else
+ break;
+ until false;
+
+ { Load the units }
+ pu:=tused_unit(current_module.used_units.first);
+ while assigned(pu) do
+ begin
+ { Only load the units that are in the current
+ (interface/implementation) uses clause }
+ if pu.in_uses and
+ (pu.in_interface=current_module.in_interface) then
+ begin
+ tppumodule(pu.u).loadppu;
+ { is our module compiled? then we can stop }
+ if current_module.state=ms_compiled then
+ exit;
+ { add this unit to the dependencies }
+ pu.u.adddependency(current_module);
+ { save crc values }
+ pu.checksum:=pu.u.crc;
+ pu.interface_checksum:=pu.u.interface_crc;
+ pu.indirect_checksum:=pu.u.indirect_crc;
+ { connect unitsym to the module }
+ pu.unitsym.module:=pu.u;
+ { add to symtable stack }
+ symtablestack.push(pu.u.globalsymtable);
+ if (m_mac in current_settings.modeswitches) and
+ assigned(pu.u.globalmacrosymtable) then
+ macrosymtablestack.push(pu.u.globalmacrosymtable);
+ { check hints }
+ pu.u.check_hints;
+ end;
+ pu:=tused_unit(pu.next);
+ end;
+
+ consume(_SEMICOLON);
+ end;
+
+
+ procedure reset_all_defs;
+ begin
+ if assigned(current_module.wpoinfo) then
+ current_module.wpoinfo.resetdefs;
+ end;
+
+
+ procedure free_localsymtables(st:TSymtable);
+ var
+ i : longint;
+ def : tstoreddef;
+ pd : tprocdef;
+ begin
+ for i:=0 to st.DefList.Count-1 do
+ begin
+ def:=tstoreddef(st.DefList[i]);
+ if def.typ=procdef then
+ begin
+ pd:=tprocdef(def);
+ if assigned(pd.localst) and
+ (pd.localst.symtabletype<>staticsymtable) and
+ not(po_inline in pd.procoptions) then
+ begin
+ free_localsymtables(pd.localst);
+ pd.localst.free;
+ pd.localst:=nil;
+ end;
+ end;
+ end;
+ end;
+
+
+ procedure parse_implementation_uses;
+ begin
+ if token=_USES then
+ loadunits;
+ end;
+
+
+ procedure setupglobalswitches;
+ begin
+ if (cs_create_pic in current_settings.moduleswitches) then
+ begin
+ def_system_macro('FPC_PIC');
+ def_system_macro('PIC');
+ end;
+ end;
+
+
+ function create_main_proc(const name:string;potype:tproctypeoption;st:TSymtable):tcgprocinfo;
+ var
+ ps : tprocsym;
+ pd : tprocdef;
+ begin
+ { there should be no current_procinfo available }
+ if assigned(current_procinfo) then
+ internalerror(200304275);
+ {Generate a procsym for main}
+ ps:=tprocsym.create('$'+name);
+ { main are allways used }
+ inc(ps.refs);
+ st.insert(ps);
+ pd:=tprocdef.create(main_program_level);
+ include(pd.procoptions,po_global);
+ pd.procsym:=ps;
+ ps.ProcdefList.Add(pd);
+ { set procdef options }
+ pd.proctypeoption:=potype;
+ pd.proccalloption:=pocall_default;
+ include(pd.procoptions,po_hascallingconvention);
+ pd.forwarddef:=false;
+ pd.setmangledname(target_info.cprefix+name);
+ pd.aliasnames.insert(pd.mangledname);
+ handle_calling_convention(pd);
+ { We don't need is a local symtable. Change it into the static
+ symtable }
+ pd.localst.free;
+ pd.localst:=st;
+ { set procinfo and current_procinfo.procdef }
+ result:=tcgprocinfo(cprocinfo.create(nil));
+ result.procdef:=pd;
+ { main proc does always a call e.g. to init system unit }
+ include(result.flags,pi_do_call);
+ end;
+
+
+ procedure release_main_proc(pi:tcgprocinfo);
+ begin
+ { remove localst as it was replaced by staticsymtable }
+ pi.procdef.localst:=nil;
+ { remove procinfo }
+ current_module.procinfo:=nil;
+ pi.free;
+ pi:=nil;
+ end;
+
+
+
+ { Insert _GLOBAL_OFFSET_TABLE_ symbol if system uses it }
+
+ procedure maybe_load_got;
+{$ifdef i386}
+ var
+ gotvarsym : tstaticvarsym;
+{$endif i386}
+ begin
+{$ifdef i386}
+ if (cs_create_pic in current_settings.moduleswitches) and
+ (tf_pic_uses_got in target_info.flags) then
+ begin
+ { insert symbol for got access in assembler code}
+ gotvarsym:=tstaticvarsym.create('_GLOBAL_OFFSET_TABLE_',
+ vs_value,voidpointertype,[vo_is_external]);
+ gotvarsym.set_mangledname('_GLOBAL_OFFSET_TABLE_');
+ current_module.localsymtable.insert(gotvarsym);
+ { avoid unnecessary warnings }
+ gotvarsym.varstate:=vs_read;
+ gotvarsym.refs:=1;
+ end;
+{$endif i386}
+ end;
+
+ function gen_implicit_initfinal(flag:word;st:TSymtable):tcgprocinfo;
+ begin
+ { create procdef }
+ case flag of
+ uf_init :
+ begin
+ result:=create_main_proc(make_mangledname('',current_module.localsymtable,'init_implicit'),potype_unitinit,st);
+ result.procdef.aliasnames.insert(make_mangledname('INIT$',current_module.localsymtable,''));
+ end;
+ uf_finalize :
+ begin
+ result:=create_main_proc(make_mangledname('',current_module.localsymtable,'finalize_implicit'),potype_unitfinalize,st);
+ result.procdef.aliasnames.insert(make_mangledname('FINALIZE$',current_module.localsymtable,''));
+ if (not current_module.is_unit) then
+ result.procdef.aliasnames.insert('PASCALFINALIZE');
+ end;
+ else
+ internalerror(200304253);
+ end;
+ result.code:=cnothingnode.create;
+ end;
+
+
+ procedure copy_macro(p:TObject; arg:pointer);
+ begin
+ current_module.globalmacrosymtable.insert(tmacro(p).getcopy);
+ end;
+
+ function try_consume_hintdirective(var moduleopt:tmoduleoptions; var deprecatedmsg:pshortstring):boolean;
+ var
+ last_is_deprecated:boolean;
+ begin
+ try_consume_hintdirective:=false;
+ repeat
+ last_is_deprecated:=false;
+ case idtoken of
+ _LIBRARY :
+ begin
+ include(moduleopt,mo_hint_library);
+ try_consume_hintdirective:=true;
+ end;
+ _DEPRECATED :
+ begin
+ include(moduleopt,mo_hint_deprecated);
+ try_consume_hintdirective:=true;
+ last_is_deprecated:=true;
+ end;
+ _EXPERIMENTAL :
+ begin
+ include(moduleopt,mo_hint_experimental);
+ try_consume_hintdirective:=true;
+ end;
+ _PLATFORM :
+ begin
+ include(moduleopt,mo_hint_platform);
+ try_consume_hintdirective:=true;
+ end;
+ _UNIMPLEMENTED :
+ begin
+ include(moduleopt,mo_hint_unimplemented);
+ try_consume_hintdirective:=true;
+ end;
+ else
+ break;
+ end;
+ consume(Token);
+ { handle deprecated message }
+ if ((token=_CSTRING) or (token=_CCHAR)) and last_is_deprecated then
+ begin
+ if deprecatedmsg<>nil then
+ internalerror(201001221);
+ if token=_CSTRING then
+ deprecatedmsg:=stringdup(cstringpattern)
+ else
+ deprecatedmsg:=stringdup(pattern);
+ consume(token);
+ include(moduleopt,mo_has_deprecated_msg);
+ end;
+ until false;
+ end;
+
+ procedure proc_unit;
+
+ function is_assembler_generated:boolean;
+ var
+ hal : tasmlisttype;
+ begin
+ result:=false;
+ if Errorcount=0 then
+ begin
+ for hal:=low(TasmlistType) to high(TasmlistType) do
+ if not current_asmdata.asmlists[hal].empty then
+ begin
+ result:=true;
+ exit;
+ end;
+ end;
+ end;
+
+ var
+ main_file: tinputfile;
+{$ifdef EXTDEBUG}
+ store_crc,
+{$endif EXTDEBUG}
+ store_interface_crc,
+ store_indirect_crc: cardinal;
+ s1,s2 : ^string; {Saves stack space}
+ force_init_final : boolean;
+ init_procinfo,
+ finalize_procinfo : tcgprocinfo;
+ unitname : ansistring;
+ unitname8 : string[8];
+ ag: boolean;
+{$ifdef debug_devirt}
+ i: longint;
+{$endif debug_devirt}
+ begin
+ init_procinfo:=nil;
+ finalize_procinfo:=nil;
+
+ if m_mac in current_settings.modeswitches then
+ current_module.mode_switch_allowed:= false;
+
+ consume(_UNIT);
+ if compile_level=1 then
+ Status.IsExe:=false;
+
+ unitname:=orgpattern;
+ consume(_ID);
+ while token=_POINT do
+ begin
+ consume(_POINT);
+ unitname:=unitname+'.'+orgpattern;
+ consume(_ID);
+ end;
+
+ { create filenames and unit name }
+ main_file := current_scanner.inputfile;
+ while assigned(main_file.next) do
+ main_file := main_file.next;
+
+ new(s1);
+ s1^:=current_module.modulename^;
+ current_module.SetFileName(main_file.path^+main_file.name^,true);
+ current_module.SetModuleName(unitname);
+
+ { check for system unit }
+ new(s2);
+ s2^:=upper(ChangeFileExt(ExtractFileName(main_file.name^),''));
+ unitname8:=copy(current_module.modulename^,1,8);
+ if (cs_check_unit_name in current_settings.globalswitches) and
+ (
+ not(
+ (current_module.modulename^=s2^) or
+ (
+ (length(current_module.modulename^)>8) and
+ (unitname8=s2^)
+ )
+ )
+ or
+ (
+ (length(s1^)>8) and
+ (s1^<>current_module.modulename^)
+ )
+ ) then
+ Message1(unit_e_illegal_unit_name,current_module.realmodulename^);
+ if (current_module.modulename^='SYSTEM') then
+ include(current_settings.moduleswitches,cs_compilesystem);
+ dispose(s2);
+ dispose(s1);
+
+ if (target_info.system in systems_unit_program_exports) then
+ exportlib.preparelib(current_module.realmodulename^);
+
+ { parse hint directives }
+ try_consume_hintdirective(current_module.moduleoptions, current_module.deprecatedmsg);
+
+ consume(_SEMICOLON);
+ consume(_INTERFACE);
+ { global switches are read, so further changes aren't allowed }
+ current_module.in_global:=false;
+
+ { handle the global switches }
+ setupglobalswitches;
+
+ message1(unit_u_loading_interface_units,current_module.modulename^);
+
+ { update status }
+ status.currentmodule:=current_module.realmodulename^;
+
+ { maybe turn off m_objpas if we are compiling objpas }
+ if (current_module.modulename^='OBJPAS') then
+ exclude(current_settings.modeswitches,m_objpas);
+
+ { maybe turn off m_mac if we are compiling macpas }
+ if (current_module.modulename^='MACPAS') then
+ exclude(current_settings.modeswitches,m_mac);
+
+ parse_only:=true;
+
+ { generate now the global symboltable,
+ define first as local to overcome dependency conflicts }
+ current_module.localsymtable:=tglobalsymtable.create(current_module.modulename^,current_module.moduleid);
+
+ { insert unitsym of this unit to prevent other units having
+ the same name }
+ tabstractunitsymtable(current_module.localsymtable).insertunit(tunitsym.create(current_module.realmodulename^,current_module));
+
+ { load default units, like the system unit }
+ loaddefaultunits;
+
+ { insert qualifier for the system unit (allows system.writeln) }
+ if not(cs_compilesystem in current_settings.moduleswitches) and
+ (token=_USES) then
+ begin
+ loadunits;
+ { has it been compiled at a higher level ?}
+ if current_module.state=ms_compiled then
+ exit;
+ end;
+
+ { move the global symtable from the temporary local to global }
+ current_module.globalsymtable:=current_module.localsymtable;
+ current_module.localsymtable:=nil;
+
+ { number all units, so we know if a unit is used by this unit or
+ needs to be added implicitly }
+ current_module.updatemaps;
+
+ { create whole program optimisation information (may already be
+ updated in the interface, e.g., in case of classrefdef typed
+ constants }
+ current_module.wpoinfo:=tunitwpoinfo.create;
+
+ { ... parse the declarations }
+ Message1(parser_u_parsing_interface,current_module.realmodulename^);
+ symtablestack.push(current_module.globalsymtable);
+ read_interface_declarations;
+ symtablestack.pop(current_module.globalsymtable);
+
+ { Export macros defined in the interface for macpas. The macros
+ are put in the globalmacrosymtable that will only be used by other
+ units. The current unit continues to use the localmacrosymtable }
+ if (m_mac in current_settings.modeswitches) then
+ begin
+ current_module.globalmacrosymtable:=tmacrosymtable.create(true);
+ current_module.localmacrosymtable.SymList.ForEachCall(@copy_macro,nil);
+ end;
+
+ { leave when we got an error }
+ if (Errorcount>0) and not status.skip_error then
+ begin
+ Message1(unit_f_errors_in_unit,tostr(Errorcount));
+ status.skip_error:=true;
+ exit;
+ end;
+
+ { Our interface is compiled, generate CRC and switch to implementation }
+ if not(cs_compilesystem in current_settings.moduleswitches) and
+ (Errorcount=0) then
+ tppumodule(current_module).getppucrc;
+ current_module.in_interface:=false;
+ current_module.interface_compiled:=true;
+
+ { First reload all units depending on our interface, we need to do this
+ in the implementation part to prevent erroneous circular references }
+ tppumodule(current_module).setdefgeneration;
+ tppumodule(current_module).reload_flagged_units;
+
+ { Parse the implementation section }
+ if (m_mac in current_settings.modeswitches) and try_to_consume(_END) then
+ current_module.interface_only:=true
+ else
+ current_module.interface_only:=false;
+
+ parse_only:=false;
+
+ { create static symbol table }
+ current_module.localsymtable:=tstaticsymtable.create(current_module.modulename^,current_module.moduleid);
+
+ { Insert _GLOBAL_OFFSET_TABLE_ symbol if system uses it }
+ maybe_load_got;
+
+ if not current_module.interface_only then
+ begin
+ consume(_IMPLEMENTATION);
+ Message1(unit_u_loading_implementation_units,current_module.modulename^);
+ { Read the implementation units }
+ parse_implementation_uses;
+ end;
+
+ if current_module.state=ms_compiled then
+ exit;
+
+ { All units are read, now give them a number }
+ current_module.updatemaps;
+
+ symtablestack.push(current_module.globalsymtable);
+ symtablestack.push(current_module.localsymtable);
+
+ if not current_module.interface_only then
+ begin
+ Message1(parser_u_parsing_implementation,current_module.modulename^);
+ if current_module.in_interface then
+ internalerror(200212285);
+
+ { Compile the unit }
+ init_procinfo:=create_main_proc(make_mangledname('',current_module.localsymtable,'init'),potype_unitinit,current_module.localsymtable);
+ init_procinfo.procdef.aliasnames.insert(make_mangledname('INIT$',current_module.localsymtable,''));
+ init_procinfo.parse_body;
+ { save file pos for debuginfo }
+ current_module.mainfilepos:=init_procinfo.entrypos;
+ end;
+
+ { Generate specializations of objectdefs methods }
+ generate_specialization_procs;
+
+ { if the unit contains ansi/widestrings, initialization and
+ finalization code must be forced }
+ force_init_final:=tglobalsymtable(current_module.globalsymtable).needs_init_final or
+ tstaticsymtable(current_module.localsymtable).needs_init_final;
+
+ { should we force unit initialization? }
+ { this is a hack, but how can it be done better ? }
+ { Now the sole purpose of this is to change 'init' to 'init_implicit', is it needed at all? (Sergei) }
+ if force_init_final and assigned(init_procinfo) and has_no_code(init_procinfo.code) then
+ begin
+ { first release the not used init procinfo }
+ if assigned(init_procinfo) then
+ release_main_proc(init_procinfo);
+ init_procinfo:=gen_implicit_initfinal(uf_init,current_module.localsymtable);
+ end;
+ { finalize? }
+ if not current_module.interface_only and (token=_FINALIZATION) then
+ begin
+ { Compile the finalize }
+ finalize_procinfo:=create_main_proc(make_mangledname('',current_module.localsymtable,'finalize'),potype_unitfinalize,current_module.localsymtable);
+ finalize_procinfo.procdef.aliasnames.insert(make_mangledname('FINALIZE$',current_module.localsymtable,''));
+ finalize_procinfo.parse_body;
+ end
+ else if force_init_final then
+ finalize_procinfo:=gen_implicit_initfinal(uf_finalize,current_module.localsymtable);
+
+ { Now both init and finalize bodies are read and it is known
+ which variables are used in both init and finalize we can now
+ generate the code. This is required to prevent putting a variable in
+ a register that is also used in the finalize body (PFV) }
+ if assigned(init_procinfo) then
+ begin
+ if force_init_final or not(has_no_code(init_procinfo.code)) then
+ begin
+ init_procinfo.generate_code;
+ current_module.flags:=current_module.flags or uf_init;
+ end;
+ init_procinfo.resetprocdef;
+ release_main_proc(init_procinfo);
+ end;
+ if assigned(finalize_procinfo) then
+ begin
+ if force_init_final or not(has_no_code(finalize_procinfo.code)) then
+ begin
+ finalize_procinfo.generate_code;
+ current_module.flags:=current_module.flags or uf_finalize;
+ end;
+ finalize_procinfo.resetprocdef;
+ release_main_proc(finalize_procinfo);
+ end;
+
+ symtablestack.pop(current_module.localsymtable);
+ symtablestack.pop(current_module.globalsymtable);
+
+ { the last char should always be a point }
+ consume(_POINT);
+
+ { reset wpo flags for all defs }
+ reset_all_defs;
+
+ if (Errorcount=0) then
+ begin
+ { tests, if all (interface) forwards are resolved }
+ tstoredsymtable(current_module.globalsymtable).check_forwards;
+ { check if all private fields are used }
+ tstoredsymtable(current_module.globalsymtable).allprivatesused;
+
+ { test static symtable }
+ tstoredsymtable(current_module.localsymtable).allsymbolsused;
+ tstoredsymtable(current_module.localsymtable).allprivatesused;
+ tstoredsymtable(current_module.localsymtable).check_forwards;
+ tstoredsymtable(current_module.localsymtable).checklabels;
+
+ { used units }
+ current_module.allunitsused;
+ end;
+
+ { leave when we got an error }
+ if (Errorcount>0) and not status.skip_error then
+ begin
+ Message1(unit_f_errors_in_unit,tostr(Errorcount));
+ status.skip_error:=true;
+ exit;
+ end;
+
+ { if an Objective-C module, generate rtti and module info }
+ MaybeGenerateObjectiveCImageInfo(current_module.globalsymtable,current_module.localsymtable);
+
+ { do we need to add the variants unit? }
+ maybeloadvariantsunit;
+
+ { generate wrappers for interfaces }
+ gen_intf_wrappers(current_asmdata.asmlists[al_procedures],current_module.globalsymtable,false);
+ gen_intf_wrappers(current_asmdata.asmlists[al_procedures],current_module.localsymtable,false);
+
+ { generate rtti/init tables }
+ write_persistent_type_info(current_module.globalsymtable);
+ write_persistent_type_info(current_module.localsymtable);
+
+ { Tables }
+ InsertThreadvars;
+
+ { Resource strings }
+ GenerateResourceStrings;
+
+ { Widestring typed constants }
+ InsertWideInits;
+
+ { Resourcestring references }
+ InsertResStrInits;
+
+ { generate debuginfo }
+ if (cs_debuginfo in current_settings.moduleswitches) then
+ current_debuginfo.inserttypeinfo;
+
+ { generate imports }
+ if current_module.ImportLibraryList.Count>0 then
+ importlib.generatelib;
+
+ { insert own objectfile, or say that it's in a library
+ (no check for an .o when loading) }
+ ag:=is_assembler_generated;
+ if ag then
+ insertobjectfile
+ else
+ begin
+ current_module.flags:=current_module.flags or uf_no_link;
+ current_module.flags:=current_module.flags and not (uf_has_stabs_debuginfo or uf_has_dwarf_debuginfo);
+ end;
+
+ if ag then
+ begin
+ { create callframe info }
+ create_dwarf_frame;
+ { assemble }
+ create_objectfile;
+ end;
+
+ { Write out the ppufile after the object file has been created }
+ store_interface_crc:=current_module.interface_crc;
+ store_indirect_crc:=current_module.indirect_crc;
+{$ifdef EXTDEBUG}
+ store_crc:=current_module.crc;
+{$endif EXTDEBUG}
+ if (Errorcount=0) then
+ tppumodule(current_module).writeppu;
+
+ if not(cs_compilesystem in current_settings.moduleswitches) then
+ begin
+ if store_interface_crc<>current_module.interface_crc then
+ Message1(unit_u_interface_crc_changed,current_module.ppufilename^);
+ if store_indirect_crc<>current_module.indirect_crc then
+ Message1(unit_u_indirect_crc_changed,current_module.ppufilename^);
+ end;
+{$ifdef EXTDEBUG}
+ if not(cs_compilesystem in current_settings.moduleswitches) then
+ if (store_crc<>current_module.crc) and simplify_ppu then
+ Message1(unit_u_implementation_crc_changed,current_module.ppufilename^);
+{$endif EXTDEBUG}
+
+ { release local symtables that are not needed anymore }
+ free_localsymtables(current_module.globalsymtable);
+ free_localsymtables(current_module.localsymtable);
+
+ { leave when we got an error }
+ if (Errorcount>0) and not status.skip_error then
+ begin
+ Message1(unit_f_errors_in_unit,tostr(Errorcount));
+ status.skip_error:=true;
+ exit;
+ end;
+
+{$ifdef debug_devirt}
+ { print out all instantiated class/object types }
+ writeln('constructed object/class/classreftypes in ',current_module.realmodulename^);
+ for i := 0 to current_module.wpoinfo.createdobjtypes.count-1 do
+ begin
+ write(' ',tdef(current_module.wpoinfo.createdobjtypes[i]).GetTypeName);
+ case tdef(current_module.wpoinfo.createdobjtypes[i]).typ of
+ objectdef:
+ case tobjectdef(current_module.wpoinfo.createdobjtypes[i]).objecttype of
+ odt_object:
+ writeln(' (object)');
+ odt_class:
+ writeln(' (class)');
+ else
+ internalerror(2008101103);
+ end;
+ else
+ internalerror(2008101104);
+ end;
+ end;
+
+ for i := 0 to current_module.wpoinfo.createdclassrefobjtypes.count-1 do
+ begin
+ write(' Class Of ',tdef(current_module.wpoinfo.createdclassrefobjtypes[i]).GetTypeName);
+ case tdef(current_module.wpoinfo.createdclassrefobjtypes[i]).typ of
+ objectdef:
+ case tobjectdef(current_module.wpoinfo.createdclassrefobjtypes[i]).objecttype of
+ odt_class:
+ writeln(' (classrefdef)');
+ else
+ internalerror(2008101105);
+ end
+ else
+ internalerror(2008101102);
+ end;
+ end;
+{$endif debug_devirt}
+
+ Message1(unit_u_finished_compiling,current_module.modulename^);
+ end;
+
+
+ procedure procexport(const s : string);
+ var
+ hp : texported_item;
+ begin
+ hp:=texported_item.create;
+ hp.name:=stringdup(s);
+ hp.options:=hp.options or eo_name;
+ exportlib.exportprocedure(hp);
+ end;
+
+
+ procedure varexport(const s : string);
+ var
+ hp : texported_item;
+ begin
+ hp:=texported_item.create;
+ hp.name:=stringdup(s);
+ hp.options:=hp.options or eo_name;
+ exportlib.exportvar(hp);
+ end;
+
+
+ procedure insert_export(sym : TObject;arg:pointer);
+ var
+ i : longint;
+ item : TCmdStrListItem;
+ begin
+ case TSym(sym).typ of
+ { ignore: }
+ unitsym,
+ syssym,
+ constsym,
+ enumsym,
+ typesym:
+ ;
+ procsym:
+ begin
+ for i:=0 to tprocsym(sym).ProcdefList.Count-1 do
+ begin
+ if not(tprocdef(tprocsym(sym).ProcdefList[i]).proccalloption in [pocall_internproc]) and
+ ((tprocdef(tprocsym(sym).ProcdefList[i]).procoptions*[po_external])=[]) and
+ ((tsymtable(arg).symtabletype=globalsymtable) or
+ ((tsymtable(arg).symtabletype=staticsymtable) and (po_public in tprocdef(tprocsym(sym).ProcdefList[i]).procoptions))
+ ) then
+ begin
+ procexport(tprocdef(tprocsym(sym).ProcdefList[i]).mangledname);
+ { walk through all aliases }
+ item:=TCmdStrListItem(tprocdef(tprocsym(sym).ProcdefList[i]).aliasnames.first);
+ while assigned(item) do
+ begin
+ { avoid duplicate entries, sometimes aliasnames contains the mangledname }
+ if item.str<>tprocdef(tprocsym(sym).ProcdefList[i]).mangledname then
+ procexport(item.str);
+ item:=TCmdStrListItem(item.next);
+ end;
+ end;
+ end;
+ end;
+ staticvarsym:
+ begin
+ varexport(tsym(sym).mangledname);
+ end;
+ else
+ begin
+ writeln('unknown: ',ord(TSym(sym).typ));
+ end;
+ end;
+ end;
+
+
+ Function RewritePPU(const PPUFn,PPLFn:String):Boolean;
+ Var
+ MakeStatic : Boolean;
+ Var
+ buffer : array[0..$1fff] of byte;
+ inppu,
+ outppu : tppufile;
+ b,
+ untilb : byte;
+ l,m : longint;
+ f : file;
+ ext,
+ s : string;
+ ppuversion : dword;
+ begin
+ Result:=false;
+ MakeStatic:=False;
+ inppu:=tppufile.create(PPUFn);
+ if not inppu.openfile then
+ begin
+ inppu.free;
+ Comment(V_Error,'Could not open : '+PPUFn);
+ Exit;
+ end;
+ { Check the ppufile }
+ if not inppu.CheckPPUId then
+ begin
+ inppu.free;
+ Comment(V_Error,'Not a PPU File : '+PPUFn);
+ Exit;
+ end;
+ ppuversion:=inppu.GetPPUVersion;
+ if ppuversion<CurrentPPUVersion then
+ begin
+ inppu.free;
+ Comment(V_Error,'Wrong PPU Version '+tostr(ppuversion)+' in '+PPUFn);
+ Exit;
+ end;
+ { No .o file generated for this ppu, just skip }
+ if (inppu.header.flags and uf_no_link)<>0 then
+ begin
+ inppu.free;
+ Result:=true;
+ Exit;
+ end;
+ { Already a lib? }
+ if (inppu.header.flags and uf_in_library)<>0 then
+ begin
+ inppu.free;
+ Comment(V_Error,'PPU is already in a library : '+PPUFn);
+ Exit;
+ end;
+ { We need a static linked unit }
+ if (inppu.header.flags and uf_static_linked)=0 then
+ begin
+ inppu.free;
+ Comment(V_Error,'PPU is not static linked : '+PPUFn);
+ Exit;
+ end;
+ { Check if shared is allowed }
+ if tsystem(inppu.header.target) in [system_i386_go32v2] then
+ begin
+ Comment(V_Error,'Shared library not supported for ppu target, switching to static library');
+ MakeStatic:=true;
+ end;
+ { Create the new ppu }
+ if PPUFn=PPLFn then
+ outppu:=tppufile.create('ppumove.$$$')
+ else
+ outppu:=tppufile.create(PPLFn);
+ outppu.createfile;
+ { Create new header, with the new flags }
+ outppu.header:=inppu.header;
+ outppu.header.flags:=outppu.header.flags or uf_in_library;
+ if MakeStatic then
+ outppu.header.flags:=outppu.header.flags or uf_static_linked
+ else
+ outppu.header.flags:=outppu.header.flags or uf_shared_linked;
+ { read until the object files are found }
+ untilb:=iblinkunitofiles;
+ repeat
+ b:=inppu.readentry;
+ if b in [ibendinterface,ibend] then
+ begin
+ inppu.free;
+ outppu.free;
+ Comment(V_Error,'No files to be linked found : '+PPUFn);
+ Exit;
+ end;
+ if b<>untilb then
+ begin
+ repeat
+ inppu.getdatabuf(buffer,sizeof(buffer),l);
+ outppu.putdata(buffer,l);
+ until l<sizeof(buffer);
+ outppu.writeentry(b);
+ end;
+ until (b=untilb);
+ { we have now reached the section for the files which need to be added,
+ now add them to the list }
+ case b of
+ iblinkunitofiles :
+ begin
+ { add all o files, and save the entry when not creating a static
+ library to keep staticlinking possible }
+ while not inppu.endofentry do
+ begin
+ s:=inppu.getstring;
+ m:=inppu.getlongint;
+ if not MakeStatic then
+ begin
+ outppu.putstring(s);
+ outppu.putlongint(m);
+ end;
+ current_module.linkotherofiles.add(s,link_always);;
+ end;
+ if not MakeStatic then
+ outppu.writeentry(b);
+ end;
+ { iblinkunitstaticlibs :
+ begin
+ AddToLinkFiles(ExtractLib(inppu.getstring));
+ if not inppu.endofentry then
+ begin
+ repeat
+ inppu.getdatabuf(buffer^,bufsize,l);
+ outppu.putdata(buffer^,l);
+ until l<bufsize;
+ outppu.writeentry(b);
+ end;
+ end; }
+ end;
+ { just add a new entry with the new lib }
+ if MakeStatic then
+ begin
+ outppu.putstring('imp'+current_module.realmodulename^);
+ outppu.putlongint(link_static);
+ outppu.writeentry(iblinkunitstaticlibs)
+ end
+ else
+ begin
+ outppu.putstring('imp'+current_module.realmodulename^);
+ outppu.putlongint(link_shared);
+ outppu.writeentry(iblinkunitsharedlibs);
+ end;
+ { read all entries until the end and write them also to the new ppu }
+ repeat
+ b:=inppu.readentry;
+ { don't write ibend, that's written automatically }
+ if b<>ibend then
+ begin
+ if b=iblinkothersharedlibs then
+ begin
+ while not inppu.endofentry do
+ begin
+ s:=inppu.getstring;
+ m:=inppu.getlongint;
+
+ outppu.putstring(s);
+ outppu.putlongint(m);
+
+ { strip lib prefix }
+ if copy(s,1,3)='lib' then
+ delete(s,1,3);
+ ext:=ExtractFileExt(s);
+ if ext<>'' then
+ delete(s,length(s)-length(ext)+1,length(ext));
+
+ current_module.linkOtherSharedLibs.add(s,link_always);
+ end;
+ end
+ else
+ repeat
+ inppu.getdatabuf(buffer,sizeof(buffer),l);
+ outppu.putdata(buffer,l);
+ until l<sizeof(buffer);
+ outppu.writeentry(b);
+ end;
+ until b=ibend;
+ { write the last stuff and close }
+ outppu.flush;
+ outppu.writeheader;
+ outppu.free;
+ inppu.free;
+ { rename }
+ if PPUFn=PPLFn then
+ begin
+ {$push}{$I-}
+ assign(f,PPUFn);
+ erase(f);
+ assign(f,'ppumove.$$$');
+ rename(f,PPUFn);
+ {$pop}
+ if ioresult<>0 then;
+ end;
+ Result:=True;
+ end;
+
+
+ procedure createimportlibfromexports;
+ var
+ hp : texported_item;
+ begin
+ hp:=texported_item(current_module._exports.first);
+ while assigned(hp) do
+ begin
+ current_module.AddExternalImport(current_module.realmodulename^,hp.name^,hp.name^,hp.index,hp.is_var,false);
+ hp:=texported_item(hp.next);
+ end;
+ end;
+
+
+ procedure proc_package;
+ var
+ main_file : tinputfile;
+ hp,hp2 : tmodule;
+ {finalize_procinfo,
+ init_procinfo,
+ main_procinfo : tcgprocinfo;}
+ force_init_final : boolean;
+ uu : tused_unit;
+ module_name: ansistring;
+ begin
+ Status.IsPackage:=true;
+ Status.IsExe:=true;
+ parse_only:=false;
+ {main_procinfo:=nil;
+ init_procinfo:=nil;
+ finalize_procinfo:=nil;}
+
+ if not RelocSectionSetExplicitly then
+ RelocSection:=true;
+
+ { Relocation works only without stabs under Windows when }
+ { external linker (LD) is used. LD generates relocs for }
+ { stab sections which is not loaded in memory. It causes }
+ { AV error when DLL is loaded and relocation is needed. }
+ { Internal linker does not have this problem. }
+ if RelocSection and
+ (target_info.system in systems_all_windows+[system_i386_wdosx]) and
+ (cs_link_extern in current_settings.globalswitches) then
+ begin
+ include(current_settings.globalswitches,cs_link_strip);
+ { Warning stabs info does not work with reloc section !! }
+ if (cs_debuginfo in current_settings.moduleswitches) and
+ (target_dbg.id=dbg_stabs) then
+ begin
+ Message1(parser_w_parser_reloc_no_debug,current_module.mainsource^);
+ Message(parser_w_parser_win32_debug_needs_WN);
+ exclude(current_settings.moduleswitches,cs_debuginfo);
+ end;
+ end;
+ { get correct output names }
+ main_file := current_scanner.inputfile;
+ while assigned(main_file.next) do
+ main_file := main_file.next;
+
+ current_module.SetFileName(main_file.path^+main_file.name^,true);
+
+ { consume _PACKAGE word }
+ consume(_ID);
+
+ module_name:=orgpattern;
+ consume(_ID);
+ while token=_POINT do
+ begin
+ consume(_POINT);
+ module_name:=module_name+'.'+orgpattern;
+ consume(_ID);
+ end;
+
+ current_module.setmodulename(module_name);
+ current_module.ispackage:=true;
+ exportlib.preparelib(module_name);
+
+ if tf_library_needs_pic in target_info.flags then
+ include(current_settings.moduleswitches,cs_create_pic);
+
+ consume(_SEMICOLON);
+
+ { global switches are read, so further changes aren't allowed }
+ current_module.in_global:=false;
+
+ { setup things using the switches }
+ setupglobalswitches;
+
+ { set implementation flag }
+ current_module.in_interface:=false;
+ current_module.interface_compiled:=true;
+
+ { insert after the unit symbol tables the static symbol table }
+ { of the program }
+ current_module.localsymtable:=tstaticsymtable.create(current_module.modulename^,current_module.moduleid);
+
+ {Load the units used by the program we compile.}
+ if token=_REQUIRES then
+ begin
+ end;
+
+ {Load the units used by the program we compile.}
+ if (token=_ID) and (idtoken=_CONTAINS) then
+ begin
+ { consume _CONTAINS word }
+ consume(_ID);
+ while true do
+ begin
+ if token=_ID then
+ begin
+ module_name:=pattern;
+ consume(_ID);
+ while token=_POINT do
+ begin
+ consume(_POINT);
+ module_name:=module_name+'.'+orgpattern;
+ consume(_ID);
+ end;
+ AddUnit(module_name);
+ end
+ else
+ consume(_ID);
+ if token=_COMMA then
+ consume(_COMMA)
+ else break;
+ end;
+ consume(_SEMICOLON);
+ end;
+
+ { All units are read, now give them a number }
+ current_module.updatemaps;
+
+ {Insert the name of the main program into the symbol table.}
+ if current_module.realmodulename^<>'' then
+ tabstractunitsymtable(current_module.localsymtable).insertunit(tunitsym.create(current_module.realmodulename^,current_module));
+
+ Message1(parser_u_parsing_implementation,current_module.mainsource^);
+
+ symtablestack.push(current_module.localsymtable);
+
+ { create whole program optimisation information }
+ current_module.wpoinfo:=tunitwpoinfo.create;
+
+ { should we force unit initialization? }
+ force_init_final:=tstaticsymtable(current_module.localsymtable).needs_init_final;
+ if force_init_final then
+ {init_procinfo:=gen_implicit_initfinal(uf_init,current_module.localsymtable)};
+
+ { Add symbol to the exports section for win32 so smartlinking a
+ DLL will include the edata section }
+ if assigned(exportlib) and
+ (target_info.system in [system_i386_win32,system_i386_wdosx]) and
+ ((current_module.flags and uf_has_exports)<>0) then
+ current_asmdata.asmlists[al_procedures].concat(tai_const.createname(make_mangledname('EDATA',current_module.localsymtable,''),0));
+
+ { all labels must be defined before generating code }
+ if Errorcount=0 then
+ tstoredsymtable(current_module.localsymtable).checklabels;
+
+ symtablestack.pop(current_module.localsymtable);
+
+ { consume the last point }
+ consume(_END);
+ consume(_POINT);
+
+ if (Errorcount=0) then
+ begin
+ { test static symtable }
+ tstoredsymtable(current_module.localsymtable).allsymbolsused;
+ tstoredsymtable(current_module.localsymtable).allprivatesused;
+ tstoredsymtable(current_module.localsymtable).check_forwards;
+
+ current_module.allunitsused;
+ end;
+
+ new_section(current_asmdata.asmlists[al_globals],sec_data,'_FPCDummy',4);
+ current_asmdata.asmlists[al_globals].concat(tai_symbol.createname_global('_FPCDummy',AT_DATA,0));
+ current_asmdata.asmlists[al_globals].concat(tai_const.create_32bit(0));
+
+ new_section(current_asmdata.asmlists[al_procedures],sec_code,'',0);
+ current_asmdata.asmlists[al_procedures].concat(tai_symbol.createname_global('_DLLMainCRTStartup',AT_FUNCTION,0));
+ gen_fpc_dummy(current_asmdata.asmlists[al_procedures]);
+ current_asmdata.asmlists[al_procedures].concat(tai_const.createname('_FPCDummy',0));
+
+ { leave when we got an error }
+ if (Errorcount>0) and not status.skip_error then
+ begin
+ Message1(unit_f_errors_in_unit,tostr(Errorcount));
+ status.skip_error:=true;
+ exit;
+ end;
+
+ { remove all unused units, this happends when units are removed
+ from the uses clause in the source and the ppu was already being loaded }
+ hp:=tmodule(loaded_units.first);
+ while assigned(hp) do
+ begin
+ hp2:=hp;
+ hp:=tmodule(hp.next);
+ if hp2.is_unit and
+ not assigned(hp2.globalsymtable) then
+ loaded_units.remove(hp2);
+ end;
+
+ { force exports }
+ uu:=tused_unit(usedunits.first);
+ while assigned(uu) do
+ begin
+ uu.u.globalsymtable.symlist.ForEachCall(@insert_export,uu.u.globalsymtable);
+ { check localsymtable for exports too to get public symbols }
+ uu.u.localsymtable.symlist.ForEachCall(@insert_export,uu.u.localsymtable);
+
+ { create special exports }
+ if (uu.u.flags and uf_init)<>0 then
+ procexport(make_mangledname('INIT$',uu.u.globalsymtable,''));
+ if (uu.u.flags and uf_finalize)<>0 then
+ procexport(make_mangledname('FINALIZE$',uu.u.globalsymtable,''));
+ if (uu.u.flags and uf_threadvars)=uf_threadvars then
+ varexport(make_mangledname('THREADVARLIST',uu.u.globalsymtable,''));
+
+ uu:=tused_unit(uu.next);
+ end;
+
+{$ifdef arm}
+ { Insert .pdata section for arm-wince.
+ It is needed for exception handling. }
+ if target_info.system in [system_arm_wince] then
+ InsertPData;
+{$endif arm}
+
+ { generate debuginfo }
+ if (cs_debuginfo in current_settings.moduleswitches) then
+ current_debuginfo.inserttypeinfo;
+
+ exportlib.generatelib;
+
+ { write all our exports to the import library,
+ needs to be done after exportlib.generatelib; }
+ createimportlibfromexports;
+
+ { generate imports }
+ if current_module.ImportLibraryList.Count>0 then
+ importlib.generatelib;
+
+ { Reference all DEBUGINFO sections from the main .fpc section }
+ if (cs_debuginfo in current_settings.moduleswitches) then
+ current_debuginfo.referencesections(current_asmdata.asmlists[al_procedures]);
+
+ { insert own objectfile }
+ insertobjectfile;
+
+ { assemble and link }
+ create_objectfile;
+
+ { We might need the symbols info if not using
+ the default do_extractsymbolinfo
+ which is a dummy function PM }
+ needsymbolinfo:=do_extractsymbolinfo<>@def_extractsymbolinfo;
+ { release all local symtables that are not needed anymore }
+ if (not needsymbolinfo) then
+ free_localsymtables(current_module.localsymtable);
+
+ { leave when we got an error }
+ if (Errorcount>0) and not status.skip_error then
+ begin
+ Message1(unit_f_errors_in_unit,tostr(Errorcount));
+ status.skip_error:=true;
+ exit;
+ end;
+
+ if (not current_module.is_unit) then
+ begin
+ { finally rewrite all units included into the package }
+ uu:=tused_unit(usedunits.first);
+ while assigned(uu) do
+ begin
+ RewritePPU(uu.u.ppufilename^,uu.u.ppufilename^);
+ uu:=tused_unit(uu.next);
+ end;
+
+ { create the executable when we are at level 1 }
+ if (compile_level=1) then
+ begin
+ { create global resource file by collecting all resource files }
+ CollectResourceFiles;
+ { write .def file }
+ if (cs_link_deffile in current_settings.globalswitches) then
+ deffile.writefile;
+ { insert all .o files from all loaded units and
+ unload the units, we don't need them anymore.
+ Keep the current_module because that is still needed }
+ hp:=tmodule(loaded_units.first);
+ while assigned(hp) do
+ begin
+ { the package itself contains no code so far }
+ linker.AddModuleFiles(hp);
+ hp2:=tmodule(hp.next);
+ if (hp<>current_module) and
+ (not needsymbolinfo) then
+ begin
+ loaded_units.remove(hp);
+ hp.free;
+ end;
+ hp:=hp2;
+ end;
+ linker.MakeSharedLibrary
+ end;
+
+ { Give Fatal with error count for linker errors }
+ if (Errorcount>0) and not status.skip_error then
+ begin
+ Message1(unit_f_errors_in_unit,tostr(Errorcount));
+ status.skip_error:=true;
+ end;
+ end;
+ end;
+
+
+ procedure proc_program(islibrary : boolean);
+ var
+ main_file : tinputfile;
+ hp,hp2 : tmodule;
+ finalize_procinfo,
+ init_procinfo,
+ main_procinfo : tcgprocinfo;
+ force_init_final : boolean;
+ resources_used : boolean;
+ program_name : ansistring;
+ begin
+ DLLsource:=islibrary;
+ Status.IsLibrary:=IsLibrary;
+ Status.IsPackage:=false;
+ Status.IsExe:=true;
+ parse_only:=false;
+ main_procinfo:=nil;
+ init_procinfo:=nil;
+ finalize_procinfo:=nil;
+ resources_used:=false;
+
+ { DLL defaults to create reloc info }
+ if islibrary then
+ begin
+ if not RelocSectionSetExplicitly then
+ RelocSection:=true;
+ end;
+
+ { Relocation works only without stabs under Windows when }
+ { external linker (LD) is used. LD generates relocs for }
+ { stab sections which is not loaded in memory. It causes }
+ { AV error when DLL is loaded and relocation is needed. }
+ { Internal linker does not have this problem. }
+ if RelocSection and
+ (target_info.system in systems_all_windows+[system_i386_wdosx]) and
+ (cs_link_extern in current_settings.globalswitches) then
+ begin
+ include(current_settings.globalswitches,cs_link_strip);
+ { Warning stabs info does not work with reloc section !! }
+ if (cs_debuginfo in current_settings.moduleswitches) and
+ (target_dbg.id=dbg_stabs) then
+ begin
+ Message1(parser_w_parser_reloc_no_debug,current_module.mainsource^);
+ Message(parser_w_parser_win32_debug_needs_WN);
+ exclude(current_settings.moduleswitches,cs_debuginfo);
+ end;
+ end;
+ { get correct output names }
+ main_file := current_scanner.inputfile;
+ while assigned(main_file.next) do
+ main_file := main_file.next;
+
+ current_module.SetFileName(main_file.path^+main_file.name^,true);
+
+ if islibrary then
+ begin
+ consume(_LIBRARY);
+ program_name:=orgpattern;
+ consume(_ID);
+ while token=_POINT do
+ begin
+ consume(_POINT);
+ program_name:=program_name+'.'+orgpattern;
+ consume(_ID);
+ end;
+ current_module.setmodulename(program_name);
+ current_module.islibrary:=true;
+ exportlib.preparelib(program_name);
+
+ if tf_library_needs_pic in target_info.flags then
+ include(current_settings.moduleswitches,cs_create_pic);
+
+ consume(_SEMICOLON);
+ end
+ else
+ { is there an program head ? }
+ if token=_PROGRAM then
+ begin
+ consume(_PROGRAM);
+ program_name:=orgpattern;
+ consume(_ID);
+ while token=_POINT do
+ begin
+ consume(_POINT);
+ program_name:=program_name+'.'+orgpattern;
+ consume(_ID);
+ end;
+ current_module.setmodulename(program_name);
+ if (target_info.system in systems_unit_program_exports) then
+ exportlib.preparelib(program_name);
+ if token=_LKLAMMER then
+ begin
+ consume(_LKLAMMER);
+ repeat
+ consume(_ID);
+ until not try_to_consume(_COMMA);
+ consume(_RKLAMMER);
+ end;
+ consume(_SEMICOLON);
+ end
+ else if (target_info.system in systems_unit_program_exports) then
+ exportlib.preparelib(current_module.realmodulename^);
+
+ { global switches are read, so further changes aren't allowed }
+ current_module.in_global:=false;
+
+ { setup things using the switches }
+ setupglobalswitches;
+
+ { set implementation flag }
+ current_module.in_interface:=false;
+ current_module.interface_compiled:=true;
+
+ { insert after the unit symbol tables the static symbol table }
+ { of the program }
+ current_module.localsymtable:=tstaticsymtable.create(current_module.modulename^,current_module.moduleid);
+
+ { load standard units (system,objpas,profile unit) }
+ loaddefaultunits;
+
+ { Load units provided on the command line }
+ loadautounits;
+
+ {Load the units used by the program we compile.}
+ if token=_USES then
+ loadunits;
+
+ { All units are read, now give them a number }
+ current_module.updatemaps;
+
+ {Insert the name of the main program into the symbol table.}
+ if current_module.realmodulename^<>'' then
+ tabstractunitsymtable(current_module.localsymtable).insertunit(tunitsym.create(current_module.realmodulename^,current_module));
+
+ Message1(parser_u_parsing_implementation,current_module.mainsource^);
+
+ symtablestack.push(current_module.localsymtable);
+
+ { Insert _GLOBAL_OFFSET_TABLE_ symbol if system uses it }
+ maybe_load_got;
+
+ { create whole program optimisation information }
+ current_module.wpoinfo:=tunitwpoinfo.create;
+
+ { The program intialization needs an alias, so it can be called
+ from the bootstrap code.}
+ if islibrary then
+ begin
+ main_procinfo:=create_main_proc(make_mangledname('',current_module.localsymtable,mainaliasname),potype_proginit,current_module.localsymtable);
+ { Win32 startup code needs a single name }
+ if not(target_info.system in systems_darwin) then
+ main_procinfo.procdef.aliasnames.insert('PASCALMAIN')
+ else
+ main_procinfo.procdef.aliasnames.insert(target_info.Cprefix+'PASCALMAIN')
+ end
+ else if (target_info.system in ([system_i386_netware,system_i386_netwlibc,system_powerpc_macos]+systems_darwin)) then
+ begin
+ main_procinfo:=create_main_proc('PASCALMAIN',potype_proginit,current_module.localsymtable);
+ end
+ else
+ begin
+ main_procinfo:=create_main_proc(mainaliasname,potype_proginit,current_module.localsymtable);
+ main_procinfo.procdef.aliasnames.insert('PASCALMAIN');
+ end;
+ main_procinfo.parse_body;
+ { save file pos for debuginfo }
+ current_module.mainfilepos:=main_procinfo.entrypos;
+
+ { Generate specializations of objectdefs methods }
+ generate_specialization_procs;
+
+ { should we force unit initialization? }
+ force_init_final:=tstaticsymtable(current_module.localsymtable).needs_init_final;
+ if force_init_final then
+ init_procinfo:=gen_implicit_initfinal(uf_init,current_module.localsymtable);
+
+ { Add symbol to the exports section for win32 so smartlinking a
+ DLL will include the edata section }
+ if assigned(exportlib) and
+ (target_info.system in [system_i386_win32,system_i386_wdosx]) and
+ ((current_module.flags and uf_has_exports)<>0) then
+ current_asmdata.asmlists[al_procedures].concat(tai_const.createname(make_mangledname('EDATA',current_module.localsymtable,''),0));
+
+ { finalize? }
+ if token=_FINALIZATION then
+ begin
+ { Parse the finalize }
+ finalize_procinfo:=create_main_proc(make_mangledname('',current_module.localsymtable,'finalize'),potype_unitfinalize,current_module.localsymtable);
+ finalize_procinfo.procdef.aliasnames.insert(make_mangledname('FINALIZE$',current_module.localsymtable,''));
+ finalize_procinfo.procdef.aliasnames.insert('PASCALFINALIZE');
+ finalize_procinfo.parse_body;
+ end
+ else
+ if force_init_final then
+ finalize_procinfo:=gen_implicit_initfinal(uf_finalize,current_module.localsymtable);
+
+ { the finalization routine of libraries is generic (and all libraries need to }
+ { be finalized, so they can finalize any units they use }
+ if (islibrary) then
+ exportlib.setfininame(current_asmdata.asmlists[al_procedures],'FPC_LIB_EXIT');
+
+ { all labels must be defined before generating code }
+ if Errorcount=0 then
+ tstoredsymtable(current_module.localsymtable).checklabels;
+
+ { See remark in unit init/final }
+ main_procinfo.generate_code;
+ main_procinfo.resetprocdef;
+ release_main_proc(main_procinfo);
+ if assigned(init_procinfo) then
+ begin
+ { initialization can be implicit only }
+ current_module.flags:=current_module.flags or uf_init;
+ init_procinfo.generate_code;
+ init_procinfo.resetprocdef;
+ release_main_proc(init_procinfo);
+ end;
+ if assigned(finalize_procinfo) then
+ begin
+ if force_init_final or not (has_no_code(finalize_procinfo.code)) then
+ begin
+ finalize_procinfo.generate_code;
+ current_module.flags:=current_module.flags or uf_finalize;
+ end;
+ finalize_procinfo.resetprocdef;
+ release_main_proc(finalize_procinfo);
+ end;
+
+ symtablestack.pop(current_module.localsymtable);
+
+ { consume the last point }
+ consume(_POINT);
+
+ { reset wpo flags for all defs }
+ reset_all_defs;
+
+ if (Errorcount=0) then
+ begin
+ { test static symtable }
+ tstoredsymtable(current_module.localsymtable).allsymbolsused;
+ tstoredsymtable(current_module.localsymtable).allprivatesused;
+ tstoredsymtable(current_module.localsymtable).check_forwards;
+
+ current_module.allunitsused;
+ end;
+
+ { leave when we got an error }
+ if (Errorcount>0) and not status.skip_error then
+ begin
+ Message1(unit_f_errors_in_unit,tostr(Errorcount));
+ status.skip_error:=true;
+ exit;
+ end;
+
+ { remove all unused units, this happens when units are removed
+ from the uses clause in the source and the ppu was already being loaded }
+ hp:=tmodule(loaded_units.first);
+ while assigned(hp) do
+ begin
+ hp2:=hp;
+ hp:=tmodule(hp.next);
+ if hp2.is_unit and
+ not assigned(hp2.globalsymtable) then
+ begin
+ loaded_units.remove(hp2);
+ unloaded_units.concat(hp2);
+ end;
+ end;
+
+ { do we need to add the variants unit? }
+ maybeloadvariantsunit;
+
+ { Now that everything has been compiled we know if we need resource
+ support. If not, remove the unit. }
+ resources_used:=MaybeRemoveResUnit;
+
+ linker.initsysinitunitname;
+ if target_info.system in systems_internal_sysinit then
+ begin
+ { add start/halt unit }
+ AddUnit(linker.sysinitunit);
+ end;
+
+{$ifdef arm}
+ { Insert .pdata section for arm-wince.
+ It is needed for exception handling. }
+ if target_info.system in [system_arm_wince] then
+ InsertPData;
+{$endif arm}
+
+ InsertThreadvars;
+
+ { generate rtti/init tables }
+ write_persistent_type_info(current_module.localsymtable);
+
+ { if an Objective-C module, generate rtti and module info }
+ MaybeGenerateObjectiveCImageInfo(nil,current_module.localsymtable);
+
+ { generate wrappers for interfaces }
+ gen_intf_wrappers(current_asmdata.asmlists[al_procedures],current_module.localsymtable,false);
+
+ { generate imports }
+ if current_module.ImportLibraryList.Count>0 then
+ importlib.generatelib;
+
+ { generate debuginfo }
+ if (cs_debuginfo in current_settings.moduleswitches) then
+ current_debuginfo.inserttypeinfo;
+
+ if islibrary or (target_info.system in systems_unit_program_exports) then
+ exportlib.generatelib;
+
+ { Reference all DEBUGINFO sections from the main .fpc section }
+ if (cs_debuginfo in current_settings.moduleswitches) then
+ current_debuginfo.referencesections(current_asmdata.asmlists[al_procedures]);
+
+ { Resource strings }
+ GenerateResourceStrings;
+
+ { Windows widestring needing initialization }
+ InsertWideInits;
+
+ { Resourcestring references (const foo:string=someresourcestring) }
+ InsertResStrInits;
+
+ { insert Tables and StackLength }
+ InsertInitFinalTable;
+ InsertThreadvarTablesTable;
+ InsertResourceTablesTable;
+ InsertWideInitsTablesTable;
+ InsertResStrTablesTable;
+ InsertMemorySizes;
+
+{$ifdef FPC_HAS_SYSTEMS_INTERRUPT_TABLE}
+ if target_info.system in systems_interrupt_table then
+ InsertInterruptTable;
+{$endif FPC_HAS_SYSTEMS_INTERRUPT_TABLE}
+
+ { Insert symbol to resource info }
+ InsertResourceInfo(resources_used);
+
+ { create callframe info }
+ create_dwarf_frame;
+
+ { insert own objectfile }
+ insertobjectfile;
+
+ { assemble and link }
+ create_objectfile;
+
+ { We might need the symbols info if not using
+ the default do_extractsymbolinfo
+ which is a dummy function PM }
+ needsymbolinfo:=
+ (do_extractsymbolinfo<>@def_extractsymbolinfo) or
+ ((current_settings.genwpoptimizerswitches*WPOptimizationsNeedingAllUnitInfo)<>[]);
+
+ { release all local symtables that are not needed anymore }
+ if (not needsymbolinfo) then
+ free_localsymtables(current_module.localsymtable);
+
+ { leave when we got an error }
+ if (Errorcount>0) and not status.skip_error then
+ begin
+ Message1(unit_f_errors_in_unit,tostr(Errorcount));
+ status.skip_error:=true;
+ exit;
+ end;
+
+ if (not current_module.is_unit) then
+ begin
+ { create the executable when we are at level 1 }
+ if (compile_level=1) then
+ begin
+ { create global resource file by collecting all resource files }
+ CollectResourceFiles;
+ { write .def file }
+ if (cs_link_deffile in current_settings.globalswitches) then
+ deffile.writefile;
+ { insert all .o files from all loaded units and
+ unload the units, we don't need them anymore.
+ Keep the current_module because that is still needed }
+ hp:=tmodule(loaded_units.first);
+ while assigned(hp) do
+ begin
+ linker.AddModuleFiles(hp);
+ hp2:=tmodule(hp.next);
+ if (hp<>current_module) and
+ (not needsymbolinfo) then
+ begin
+ loaded_units.remove(hp);
+ hp.free;
+ end;
+ hp:=hp2;
+ end;
+ { free also unneeded units we didn't free before }
+ if not needsymbolinfo then
+ unloaded_units.Clear;
+ { finally we can create a executable }
+ if DLLSource then
+ linker.MakeSharedLibrary
+ else
+ linker.MakeExecutable;
+
+ { collect all necessary information for whole-program optimization }
+ wpoinfomanager.extractwpoinfofromprogram;
+ end;
+
+
+ { Give Fatal with error count for linker errors }
+ if (Errorcount>0) and not status.skip_error then
+ begin
+ Message1(unit_f_errors_in_unit,tostr(Errorcount));
+ status.skip_error:=true;
+ end;
+ end;
+ end;
+
+end.
diff --git a/closures/compiler/powerpc/agppcmpw.pas b/closures/compiler/powerpc/agppcmpw.pas
new file mode 100644
index 0000000000..2ca3ddcee1
--- /dev/null
+++ b/closures/compiler/powerpc/agppcmpw.pas
@@ -0,0 +1,1248 @@
+{
+ Copyright (c) 2002 by Florian Klaempfl
+
+ This unit implements an asmoutput class for PowerPC with MPW syntax
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+{
+ This unit implements an asmoutput class for PowerPC with MPW syntax
+}
+unit agppcmpw;
+
+{$i fpcdefs.inc}
+ { We know that use_PR is a const boolean
+ but we don't care about this warning }
+ {$WARN 6018 OFF}
+
+interface
+
+ uses
+ aasmtai,aasmdata,
+ globals,aasmbase,aasmcpu,assemble,
+ cpubase;
+
+ type
+ TPPCMPWAssembler = class(TExternalAssembler)
+ procedure WriteTree(p:TAsmList);override;
+ procedure WriteAsmList;override;
+ Function DoAssemble:boolean;override;
+ procedure WriteExternals;
+ procedure WriteAsmFileHeader;
+ private
+ cur_CSECT_name: String;
+ cur_CSECT_class: String;
+
+ procedure WriteInstruction(hp : tai);
+ procedure WriteProcedureHeader(var hp:tai);
+ procedure WriteDataHeader(var s:string; isExported, isConst:boolean);
+ end;
+
+
+ implementation
+
+ uses
+ cutils,globtype,systems,cclasses,
+ verbose,finput,fmodule,script,cpuinfo,
+ cgbase,cgutils,
+ itcpugas
+ ;
+
+ const
+ line_length = 70;
+
+ {Whether internal procedure references should be xxx[PR]: }
+ use_PR = false;
+
+ const_storage_class = '';
+ var_storage_class = '';
+
+ secnames : array[TAsmSectiontype] of string[10] = (
+ '', {none}
+ '', {user}
+ 'csect', {code}
+ 'csect', {data}
+ 'csect', {read only data}
+ 'csect', {read only data - no relocations}
+ 'csect', {bss} 'csect', '',
+ 'csect','csect','csect','csect','csect',
+ 'csect','csect','csect',
+ '','','','','','','','','','','','','','',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ ''
+ );
+
+ type
+ t64bitarray = array[0..7] of byte;
+ t32bitarray = array[0..3] of byte;
+
+ function ReplaceForbiddenChars(var s: string):Boolean;
+ {Returns wheater a replacement has occured.}
+
+ var
+ i:Integer;
+
+ {The dollar sign is not allowed in MPW PPCAsm}
+
+ begin
+ ReplaceForbiddenChars:=false;
+ for i:=1 to Length(s) do
+ if s[i]='$' then
+ begin
+ s[i]:='s';
+ ReplaceForbiddenChars:=true;
+ end;
+ end;
+
+
+{*** From here is copyed from agppcgas.pp, except where marked with CHANGED.
+ Perhaps put in a third common file. ***}
+
+
+ function getreferencestring(var ref : treference) : string;
+ var
+ s : string;
+ begin
+ with ref do
+ begin
+ if (refaddr <> addr_no) then
+ InternalError(2002110301)
+ else if ((offset < -32768) or (offset > 32767)) then
+ InternalError(19991);
+
+
+ if assigned(symbol) then
+ begin
+ s:= symbol.name;
+ ReplaceForbiddenChars(s);
+ {if symbol.typ = AT_FUNCTION then
+ ;}
+
+ s:= s+'[TC]' {ref to TOC entry }
+ end
+ else
+ s:= '';
+
+
+ if offset<0 then
+ s:=s+tostr(offset)
+ else
+ if (offset>0) then
+ begin
+ if assigned(symbol) then
+ s:=s+'+'+tostr(offset)
+ else
+ s:=s+tostr(offset);
+ end;
+
+ if (index=NR_NO) and (base<>NR_NO) then
+ begin
+ if offset=0 then
+ if not assigned(symbol) then
+ s:=s+'0';
+ s:=s+'('+gas_regname(base)+')';
+ end
+ else if (index<>NR_NO) and (base<>NR_NO) and (offset=0) then
+ begin
+ if (offset=0) then
+ s:=s+gas_regname(base)+','+gas_regname(index)
+ else
+ internalerror(19992);
+ end
+ else if (base=NR_NO) and (offset=0) then
+ begin
+ {Temporary fix for inline asm, where a local var is referenced.}
+ //if assigned(symbol) then
+ // s:= s+'(rtoc)';
+ end;
+ end;
+ getreferencestring:=s;
+ end;
+
+ function getopstr_jmp(const o:toper) : string;
+ var
+ hs : string;
+ begin
+ case o.typ of
+ top_reg :
+ getopstr_jmp:=gas_regname(o.reg);
+ { no top_ref jumping for powerpc }
+ top_const :
+ getopstr_jmp:=tostr(o.val);
+ top_ref :
+ begin
+ if o.ref^.refaddr=addr_full then
+ begin
+ hs:=o.ref^.symbol.name;
+ ReplaceForbiddenChars(hs);
+ case o.ref^.symbol.typ of
+ AT_FUNCTION:
+ begin
+ if hs[1] <> '@' then {if not local label}
+ if use_PR then
+ hs:= '.'+hs+'[PR]'
+ else
+ hs:= '.'+hs
+ end
+ else
+ ;
+ end;
+ if o.ref^.offset>0 then
+ hs:=hs+'+'+tostr(o.ref^.offset)
+ else
+ if o.ref^.offset<0 then
+ hs:=hs+tostr(o.ref^.offset);
+ getopstr_jmp:=hs;
+ end
+ else
+ internalerror(200402263);
+ end;
+ top_none:
+ getopstr_jmp:='';
+ else
+ internalerror(2002070603);
+ end;
+ end;
+
+ function getopstr(const o:toper) : string;
+ var
+ hs : string;
+ begin
+ case o.typ of
+ top_reg:
+ getopstr:=gas_regname(o.reg);
+ top_const:
+ getopstr:=tostr(longint(o.val));
+ top_ref:
+ if o.ref^.refaddr=addr_no then
+ getopstr:=getreferencestring(o.ref^)
+ else
+ begin
+ hs:=o.ref^.symbol.name;
+ ReplaceForbiddenChars(hs);
+ if o.ref^.offset>0 then
+ hs:=hs+'+'+tostr(o.ref^.offset)
+ else
+ if o.ref^.offset<0 then
+ hs:=hs+tostr(o.ref^.offset);
+ getopstr:=hs;
+ end;
+ else
+ internalerror(2002070604);
+ end;
+ end;
+
+ type
+ topstr = string[4];
+
+ function branchmode(o: tasmop): topstr;
+ var tempstr: topstr;
+ begin
+ tempstr := '';
+ case o of
+ A_BCCTR,A_BCCTRL: tempstr := 'ctr';
+ A_BCLR,A_BCLRL: tempstr := 'lr';
+ end;
+ case o of
+ A_BL,A_BLA,A_BCL,A_BCLA,A_BCCTRL,A_BCLRL: tempstr := tempstr+'l';
+ end;
+ case o of
+ A_BA,A_BLA,A_BCA,A_BCLA: tempstr:=tempstr+'a';
+ end;
+ branchmode := tempstr;
+ end;
+
+ function cond2str(op: tasmop; c: tasmcond): string;
+ { note: no checking is performed whether the given combination of }
+ { conditions is valid }
+ var
+ tempstr: string;
+ begin
+ tempstr:=#9;
+ case c.simple of
+ false:
+ begin
+ cond2str := tempstr+gas_op2str[op];
+ case c.dirhint of
+ DH_None:;
+ DH_Minus:
+ cond2str:=cond2str+'-';
+ DH_Plus:
+ cond2str:=cond2str+'+';
+ else
+ internalerror(2003112901);
+ end;
+ cond2str:=cond2str+#9+tostr(c.bo)+','+tostr(c.bi)+',';
+ end;
+ true:
+ if (op >= A_B) and (op <= A_BCLRL) then
+ case c.cond of
+ { unconditional branch }
+ C_NONE:
+ cond2str := tempstr+gas_op2str[op];
+ { bdnzt etc }
+ else
+ begin
+ tempstr := tempstr+'b'+asmcondflag2str[c.cond]+
+ branchmode(op);
+ case c.dirhint of
+ DH_None:
+ tempstr:=tempstr+#9;
+ DH_Minus:
+ tempstr:=tempstr+('-'+#9);
+ DH_Plus:
+ tempstr:=tempstr+('+'+#9);
+ else
+ internalerror(2003112901);
+ end;
+ case c.cond of
+ C_LT..C_NU:
+ cond2str := tempstr+gas_regname(newreg(R_SPECIALREGISTER,c.cr,R_SUBWHOLE));
+ C_T,C_F,C_DNZT,C_DNZF,C_DZT,C_DZF:
+ cond2str := tempstr+tostr(c.crbit);
+ else
+ cond2str := tempstr;
+ end;
+ end;
+ end
+ { we have a trap instruction }
+ else
+ begin
+ internalerror(2002070601);
+ { not yet implemented !!!!!!!!!!!!!!!!!!!!! }
+ { case tempstr := 'tw';}
+ end;
+ end;
+ end;
+
+ procedure TPPCMPWAssembler.WriteInstruction(hp : tai);
+ var op: TAsmOp;
+ s: string;
+ i: byte;
+ sep: string[3];
+ begin
+ op:=taicpu(hp).opcode;
+ if is_calljmp(op) then
+ begin
+ { direct BO/BI in op[0] and op[1] not supported, put them in condition! }
+ case op of
+ A_B,A_BA:
+ s:=#9+gas_op2str[op]+#9;
+ A_BCTR,A_BCTRL,A_BLR,A_BLRL:
+ s:=#9+gas_op2str[op];
+ A_BL,A_BLA:
+ s:=#9+gas_op2str[op]+#9;
+ else
+ begin
+ s:=cond2str(op,taicpu(hp).condition);
+ if (s[length(s)] <> #9) and
+ (taicpu(hp).ops>0) then
+ s := s + ',';
+ end;
+ end;
+ if (taicpu(hp).ops>0) and (taicpu(hp).oper[0]^.typ<>top_none) then
+ begin
+ { first write the current contents of s, because the symbol }
+ { may be 255 characters }
+ asmwrite(s);
+ s:=getopstr_jmp(taicpu(hp).oper[0]^);
+ end;
+ end
+ else
+ { process operands }
+ begin
+ s:=#9+gas_op2str[op];
+ if taicpu(hp).ops<>0 then
+ begin
+ sep:=#9;
+ for i:=0 to taicpu(hp).ops-1 do
+ begin
+ s:=s+sep+getopstr(taicpu(hp).oper[i]^);
+ sep:=',';
+ end;
+ end;
+ end;
+ AsmWriteLn(s);
+ end;
+
+ {*** Until here is copyed from agppcgas.pp. ***}
+
+
+ function single2str(d : single) : string;
+ var
+ hs : string;
+ p : byte;
+ begin
+ str(d,hs);
+ { nasm expects a lowercase e }
+ p:=pos('E',hs);
+ if p>0 then
+ hs[p]:='e';
+ p:=pos('+',hs);
+ if p>0 then
+ delete(hs,p,1);
+ single2str:=lower(hs);
+ end;
+
+ function double2str(d : double) : string;
+ var
+ hs : string;
+ p : byte;
+ begin
+ str(d,hs);
+ { nasm expects a lowercase e }
+ p:=pos('E',hs);
+ if p>0 then
+ hs[p]:='e';
+ p:=pos('+',hs);
+ if p>0 then
+ delete(hs,p,1);
+ double2str:=lower(hs);
+ end;
+
+ { convert floating point values }
+ { to correct endian }
+ procedure swap64bitarray(var t: t64bitarray);
+ var
+ b: byte;
+ begin
+ b:= t[7];
+ t[7] := t[0];
+ t[0] := b;
+
+ b := t[6];
+ t[6] := t[1];
+ t[1] := b;
+
+ b:= t[5];
+ t[5] := t[2];
+ t[2] := b;
+
+ b:= t[4];
+ t[4] := t[3];
+ t[3] := b;
+ end;
+
+ procedure swap32bitarray(var t: t32bitarray);
+ var
+ b: byte;
+ begin
+ b:= t[1];
+ t[1]:= t[2];
+ t[2]:= b;
+
+ b:= t[0];
+ t[0]:= t[3];
+ t[3]:= b;
+ end;
+
+ Function PadTabs(const p:string;addch:char):string;
+ var
+ s : string;
+ i : longint;
+ begin
+ i:=length(p);
+ if addch<>#0 then
+ begin
+ inc(i);
+ s:=p+addch;
+ end
+ else
+ s:=p;
+ if i<8 then
+ PadTabs:=s+#9#9
+ else
+ PadTabs:=s+#9;
+ end;
+
+{****************************************************************************
+ PowerPC MPW Assembler
+ ****************************************************************************}
+ procedure TPPCMPWAssembler.WriteProcedureHeader(var hp:tai);
+ {Returns the current hp where the caller should continue from}
+ {For multiple entry procedures, only the last is exported as xxx[PR]
+ (if use_PR is set) }
+
+ procedure WriteExportHeader(hp:tai);
+
+ var
+ s: string;
+ replaced: boolean;
+
+ begin
+ s:= tai_symbol(hp).sym.name;
+ replaced:= ReplaceForbiddenChars(s);
+
+ if not use_PR then
+ begin
+ AsmWrite(#9'export'#9'.');
+ AsmWrite(s);
+ if replaced then
+ begin
+ AsmWrite(' => ''.');
+ AsmWrite(tai_symbol(hp).sym.name);
+ AsmWrite('''');
+ end;
+ AsmLn;
+ end;
+
+ AsmWrite(#9'export'#9);
+ AsmWrite(s);
+ AsmWrite('[DS]');
+ if replaced then
+ begin
+ AsmWrite(' => ''');
+ AsmWrite(tai_symbol(hp).sym.name);
+ AsmWrite('[DS]''');
+ end;
+ AsmLn;
+
+ {Entry in transition vector: }
+ AsmWrite(#9'csect'#9); AsmWrite(s); AsmWriteLn('[DS]');
+
+ AsmWrite(#9'dc.l'#9'.'); AsmWriteLn(s);
+
+ AsmWriteln(#9'dc.l'#9'TOC[tc0]');
+
+ {Entry in TOC: }
+ AsmWriteLn(#9'toc');
+
+ AsmWrite(#9'tc'#9);
+ AsmWrite(s); AsmWrite('[TC],');
+ AsmWrite(s); AsmWriteln('[DS]');
+ end;
+
+ function GetAdjacentTaiSymbol(var hp:tai):Boolean;
+
+ begin
+ GetAdjacentTaiSymbol:= false;
+ while assigned(hp.next) do
+ case tai(hp.next).typ of
+ ait_symbol:
+ begin
+ hp:=tai(hp.next);
+ GetAdjacentTaiSymbol:= true;
+ Break;
+ end;
+ ait_function_name:
+ hp:=tai(hp.next);
+ else
+ begin
+ //AsmWriteln(' ;#*#*# ' + tostr(Ord(tai(hp.next).typ)));
+ Break;
+ end;
+ end;
+ end;
+
+ var
+ first,last: tai;
+ s: string;
+ replaced: boolean;
+
+
+ begin
+ s:= tai_symbol(hp).sym.name;
+ {Write all headers}
+ first:= hp;
+ repeat
+ WriteExportHeader(hp);
+ last:= hp;
+ until not GetAdjacentTaiSymbol(hp);
+
+ {Start the section of the body of the proc: }
+ s:= tai_symbol(last).sym.name;
+ replaced:= ReplaceForbiddenChars(s);
+
+ if use_PR then
+ begin
+ AsmWrite(#9'export'#9'.'); AsmWrite(s); AsmWrite('[PR]');
+ if replaced then
+ begin
+ AsmWrite(' => ''.');
+ AsmWrite(tai_symbol(last).sym.name);
+ AsmWrite('[PR]''');
+ end;
+ AsmLn;
+ end;
+
+ {Starts the section: }
+ AsmWrite(#9'csect'#9'.');
+ AsmWrite(s);
+ AsmWriteLn('[PR]');
+
+ {Info for the debugger: }
+ AsmWrite(#9'function'#9'.');
+ AsmWrite(s);
+ AsmWriteLn('[PR]');
+
+ {Write all labels: }
+ hp:= first;
+ repeat
+ s:= tai_symbol(hp).sym.name;
+ ReplaceForbiddenChars(s);
+ AsmWrite('.'); AsmWrite(s); AsmWriteLn(':');
+ until not GetAdjacentTaiSymbol(hp);
+ end;
+
+ procedure TPPCMPWAssembler.WriteDataHeader(var s:string; isExported, isConst:boolean);
+ // Returns in s the changed string
+ var
+ sym: string;
+ replaced: boolean;
+
+ begin
+ sym:= s;
+ replaced:= ReplaceForbiddenChars(s);
+
+ if isExported then
+ begin
+ AsmWrite(#9'export'#9);
+ AsmWrite(s);
+ if isConst then
+ AsmWrite(const_storage_class)
+ else
+ AsmWrite(var_storage_class);
+ if replaced then
+ begin
+ AsmWrite(' => ''');
+ AsmWrite(sym);
+ AsmWrite('''');
+ end;
+ AsmLn;
+ end;
+
+ if not macos_direct_globals then
+ begin
+ {The actual section is here interrupted, by inserting a "tc" entry}
+ AsmWriteLn(#9'toc');
+
+ AsmWrite(#9'tc'#9);
+ AsmWrite(s);
+ AsmWrite('[TC], ');
+ AsmWrite(s);
+ if isConst then
+ AsmWrite(const_storage_class)
+ else
+ AsmWrite(var_storage_class);
+ AsmLn;
+
+ {The interrupted section is here continued.}
+ AsmWrite(#9'csect'#9);
+ AsmWriteln(cur_CSECT_name+cur_CSECT_class);
+ AsmWrite(PadTabs(s+':',#0));
+ end
+ else
+ begin
+ AsmWrite(#9'csect'#9);
+ AsmWrite(s);
+ AsmWrite('[TC]');
+ end;
+
+ AsmLn;
+ end;
+
+ const
+ ait_const2str:array[aitconst_32bit..aitconst_8bit] of string[8]=
+ (#9'dc.l'#9,#9'dc.w'#9,#9'dc.b'#9);
+
+
+ procedure TPPCMPWAssembler.WriteTree(p:TAsmList);
+ var
+ s : string;
+ hp : tai;
+ counter,
+ lines,
+ InlineLevel : longint;
+ i,j,l : longint;
+ consttype : taiconst_type;
+ do_line,DoNotSplitLine,
+ quoted : boolean;
+ sin : single;
+ d : double;
+
+ begin
+ if not assigned(p) then
+ exit;
+ InlineLevel:=0;
+ { lineinfo is only needed for al_procedures (PFV) }
+ do_line:=((cs_asm_source in current_settings.globalswitches) or
+ (cs_lineinfo in current_settings.moduleswitches))
+ and (p=current_asmdata.asmlists[al_procedures]);
+ DoNotSplitLine:=false;
+ hp:=tai(p.first);
+ while assigned(hp) do
+ begin
+ prefetch(pointer(hp.next)^);
+ if not(hp.typ in SkipLineInfo) then
+ begin
+ current_filepos:=tailineinfo(hp).fileinfo;
+ { no line info for inlined code }
+ if do_line and (inlinelevel=0) and not DoNotSplitLine then
+ WriteSourceLine(hp as tailineinfo);
+ end;
+
+ DoNotSplitLine:=false;
+
+ case hp.typ of
+ ait_comment:
+ begin
+ AsmWrite(target_asm.comment);
+ AsmWritePChar(tai_comment(hp).str);
+ AsmLn;
+ end;
+ ait_regalloc,
+ ait_tempalloc:
+ ;
+ ait_section:
+ begin
+ {if LastSecType<>sec_none then
+ AsmWriteLn('_'+target_asm.secnames[LastSecType]+#9#9'ENDS');}
+
+ if tai_section(hp).sectype<>sec_none then
+ begin
+ if tai_section(hp).sectype in [sec_data,sec_rodata,sec_bss] then
+ cur_CSECT_class:= '[RW]'
+ else if tai_section(hp).sectype in [sec_code] then
+ cur_CSECT_class:= ''
+ else
+ cur_CSECT_class:= '[RO]';
+
+ s:= tai_section(hp).name^;
+ if s = '' then
+ InternalError(2004101001); {Nameless sections should not occur on MPW}
+ ReplaceForbiddenChars(s);
+ cur_CSECT_name:= s;
+
+ AsmLn;
+ AsmWriteLn(#9+secnames[tai_section(hp).sectype]+' '+cur_CSECT_name+cur_CSECT_class);
+ end;
+ LastSecType:=tai_section(hp).sectype;
+ end;
+ ait_align:
+ begin
+ case tai_align(hp).aligntype of
+ 1:AsmWriteLn(#9'align 0');
+ 2:AsmWriteLn(#9'align 1');
+ 4:AsmWriteLn(#9'align 2');
+ otherwise internalerror(2002110302);
+ end;
+ end;
+ ait_datablock: {Storage for global variables.}
+ begin
+ s:= tai_datablock(hp).sym.name;
+
+ WriteDataHeader(s, tai_datablock(hp).is_global, false);
+ if not macos_direct_globals then
+ begin
+ AsmWriteLn(#9'ds.b '+tostr(tai_datablock(hp).size));
+ end
+ else
+ begin
+ AsmWriteLn(PadTabs(s+':',#0)+'ds.b '+tostr(tai_datablock(hp).size));
+ {TODO: ? PadTabs(s,#0) }
+ end;
+ end;
+
+ ait_const:
+ begin
+ consttype:=tai_const(hp).consttype;
+ case consttype of
+ aitconst_128bit:
+ begin
+ internalerror(200404291);
+ end;
+ aitconst_64bit:
+ begin
+ if assigned(tai_const(hp).sym) then
+ internalerror(200404292);
+ AsmWrite(ait_const2str[aitconst_32bit]);
+ if target_info.endian = endian_little then
+ begin
+ AsmWrite(tostr(longint(lo(tai_const(hp).value))));
+ AsmWrite(',');
+ AsmWrite(tostr(longint(hi(tai_const(hp).value))));
+ end
+ else
+ begin
+ AsmWrite(tostr(longint(hi(tai_const(hp).value))));
+ AsmWrite(',');
+ AsmWrite(tostr(longint(lo(tai_const(hp).value))));
+ end;
+ AsmLn;
+ end;
+
+ aitconst_uleb128bit,
+ aitconst_sleb128bit,
+ aitconst_32bit,
+ aitconst_16bit,
+ aitconst_8bit,
+ aitconst_rva_symbol :
+ begin
+ AsmWrite(ait_const2str[consttype]);
+ l:=0;
+ repeat
+ if assigned(tai_const(hp).sym) then
+ begin
+ if assigned(tai_const(hp).endsym) then
+ begin
+ if (tai_const(hp).endsym.typ = AT_FUNCTION) and use_PR then
+ AsmWrite('.');
+
+ s:=tai_const(hp).endsym.name;
+ ReplaceForbiddenChars(s);
+ AsmWrite(s);
+ inc(l,length(s));
+
+ if tai_const(hp).endsym.typ = AT_FUNCTION then
+ begin
+ if use_PR then
+ AsmWrite('[PR]')
+ else
+ AsmWrite('[DS]');
+ end;
+
+ AsmWrite('-');
+ inc(l,5); {Approx 5 extra, no need to be exactly}
+ end;
+
+ if (tai_const(hp).sym.typ = AT_FUNCTION) and use_PR then
+ AsmWrite('.');
+
+ s:= tai_const(hp).sym.name;
+ ReplaceForbiddenChars(s);
+ AsmWrite(s);
+ inc(l,length(s));
+
+ if tai_const(hp).sym.typ = AT_FUNCTION then
+ begin
+ if use_PR then
+ AsmWrite('[PR]')
+ else
+ AsmWrite('[DS]');
+ end;
+ inc(l,5); {Approx 5 extra, no need to be exactly}
+
+ if tai_const(hp).value > 0 then
+ s:= '+'+tostr(tai_const(hp).value)
+ else if tai_const(hp).value < 0 then
+ s:= '-'+tostr(tai_const(hp).value)
+ else
+ s:= '';
+ if s<>'' then
+ begin
+ AsmWrite(s);
+ inc(l,length(s));
+ end;
+ end
+ else
+ begin
+ s:= tostr(tai_const(hp).value);
+ AsmWrite(s);
+ inc(l,length(s));
+ end;
+
+ if (l>line_length) or
+ (hp.next=nil) or
+ (tai(hp.next).typ<>ait_const) or
+ (tai_const(hp.next).consttype<>consttype) then
+ break;
+ hp:=tai(hp.next);
+ AsmWrite(',');
+ until false;
+ AsmLn;
+ end;
+ end;
+ end;
+
+ ait_real_64bit :
+ begin
+ AsmWriteLn(target_asm.comment+'value: '+double2str(tai_real_64bit(hp).value));
+ d:=tai_real_64bit(hp).value;
+ { swap the values to correct endian if required }
+ if source_info.endian <> target_info.endian then
+ swap64bitarray(t64bitarray(d));
+ AsmWrite(#9'dc.b'#9);
+ begin
+ for i:=0 to 7 do
+ begin
+ if i<>0 then
+ AsmWrite(',');
+ AsmWrite(tostr(t64bitarray(d)[i]));
+ end;
+ end;
+ AsmLn;
+ end;
+
+ ait_real_32bit :
+ begin
+ AsmWriteLn(target_asm.comment+'value: '+single2str(tai_real_32bit(hp).value));
+ sin:=tai_real_32bit(hp).value;
+ { swap the values to correct endian if required }
+ if source_info.endian <> target_info.endian then
+ swap32bitarray(t32bitarray(sin));
+ AsmWrite(#9'dc.b'#9);
+ for i:=0 to 3 do
+ begin
+ if i<>0 then
+ AsmWrite(',');
+ AsmWrite(tostr(t32bitarray(sin)[i]));
+ end;
+ AsmLn;
+ end;
+
+ ait_string:
+ begin
+ {NOTE When a single quote char is encountered, it is
+ replaced with a numeric ascii value. It could also
+ have been replaced with the escape seq of double quotes.
+ Backslash seems to be used as an escape char, although
+ this is not mentioned in the PPCAsm documentation.}
+ counter := 0;
+ lines := tai_string(hp).len div line_length;
+ { separate lines in different parts }
+ if tai_string(hp).len > 0 then
+ begin
+ for j := 0 to lines-1 do
+ begin
+ AsmWrite(#9'dc.b'#9);
+ quoted:=false;
+ for i:=counter to counter+line_length-1 do
+ begin
+ { it is an ascii character. }
+ if (ord(tai_string(hp).str[i])>31) and
+ (ord(tai_string(hp).str[i])<128) and
+ (tai_string(hp).str[i]<>'''') and
+ (tai_string(hp).str[i]<>'\') then
+ begin
+ if not(quoted) then
+ begin
+ if i>counter then
+ AsmWrite(',');
+ AsmWrite('''');
+ end;
+ AsmWrite(tai_string(hp).str[i]);
+ quoted:=true;
+ end { if > 31 and < 128 and ord('"') }
+ else
+ begin
+ if quoted then
+ AsmWrite('''');
+ if i>counter then
+ AsmWrite(',');
+ quoted:=false;
+ AsmWrite(tostr(ord(tai_string(hp).str[i])));
+ end;
+ end; { end for i:=0 to... }
+ if quoted then AsmWrite('''');
+ AsmLn;
+ counter := counter+line_length;
+ end; { end for j:=0 ... }
+
+ { do last line of lines }
+ if counter < tai_string(hp).len then
+ AsmWrite(#9'dc.b'#9);
+ quoted:=false;
+ for i:=counter to tai_string(hp).len-1 do
+ begin
+ { it is an ascii character. }
+ if (ord(tai_string(hp).str[i])>31) and
+ (ord(tai_string(hp).str[i])<128) and
+ (tai_string(hp).str[i]<>'''') and
+ (tai_string(hp).str[i]<>'\') then
+ begin
+ if not(quoted) then
+ begin
+ if i>counter then
+ AsmWrite(',');
+ AsmWrite('''');
+ end;
+ AsmWrite(tai_string(hp).str[i]);
+ quoted:=true;
+ end { if > 31 and < 128 and " }
+ else
+ begin
+ if quoted then
+ AsmWrite('''');
+ if i>counter then
+ AsmWrite(',');
+ quoted:=false;
+ AsmWrite(tostr(ord(tai_string(hp).str[i])));
+ end;
+ end; { end for i:=0 to... }
+ if quoted then
+ AsmWrite('''');
+ end;
+ AsmLn;
+ end;
+ ait_label:
+ begin
+ if tai_label(hp).labsym.is_used then
+ begin
+ s:= tai_label(hp).labsym.name;
+ if s[1] = '@' then
+ begin
+ ReplaceForbiddenChars(s);
+ //Local labels:
+ AsmWriteLn(s+':')
+ end
+ else
+ begin
+ //Procedure entry points:
+ if not macos_direct_globals then
+ begin
+ WriteDataHeader(s, tai_label(hp).is_global, true);
+ end
+ else
+ begin
+ ReplaceForbiddenChars(s);
+ AsmWrite(#9'csect'#9); AsmWrite(s);
+ AsmWriteLn('[TC]');
+
+ AsmWriteLn(PadTabs(s+':',#0));
+ end;
+ end;
+ end;
+ end;
+ ait_symbol:
+ begin
+ if tai_symbol(hp).sym.typ=AT_FUNCTION then
+ WriteProcedureHeader(hp)
+ else if tai_symbol(hp).sym.typ=AT_DATA then
+ begin
+ s:= tai_symbol(hp).sym.name;
+ WriteDataHeader(s, tai_symbol(hp).is_global, true);
+ if macos_direct_globals then
+ begin
+ AsmWrite(s);
+ AsmWriteLn(':');
+ end;
+ end
+ else
+ InternalError(2003071301);
+ end;
+ ait_symbol_end:
+ ;
+ ait_instruction:
+ WriteInstruction(hp);
+ ait_stab,
+ ait_force_line,
+ ait_function_name : ;
+ ait_cutobject :
+ begin
+ InternalError(2004101101); {Smart linking is done transparently by the MPW linker.}
+ end;
+ ait_marker :
+ begin
+ if tai_marker(hp).kind=mark_NoLineInfoStart then
+ inc(InlineLevel)
+ else if tai_marker(hp).kind=mark_NoLineInfoEnd then
+ dec(InlineLevel);
+ end;
+ else
+ internalerror(2002110303);
+ end;
+ hp:=tai(hp.next);
+ end;
+ end;
+
+ var
+ currentasmlist : TExternalAssembler;
+
+ procedure writeexternal(p:tasmsymbol);
+
+ var
+ s:string;
+ replaced: boolean;
+
+ begin
+ if tasmsymbol(p).bind=AB_EXTERNAL then
+ begin
+ //Writeln('ZZZ ',p.name,' ',p.classname,' ',Ord(tasmsymbol(p).typ));
+ s:= p.name;
+ replaced:= ReplaceForbiddenChars(s);
+
+ with currentasmlist do
+ case tasmsymbol(p).typ of
+ AT_FUNCTION:
+ begin
+ AsmWrite(#9'import'#9'.');
+ AsmWrite(s);
+ if use_PR then
+ AsmWrite('[PR]');
+
+ if replaced then
+ begin
+ AsmWrite(' <= ''.');
+ AsmWrite(p.name);
+ if use_PR then
+ AsmWrite('[PR]''')
+ else
+ AsmWrite('''');
+ end;
+ AsmLn;
+
+ AsmWrite(#9'import'#9);
+ AsmWrite(s);
+ AsmWrite('[DS]');
+ if replaced then
+ begin
+ AsmWrite(' <= ''');
+ AsmWrite(p.name);
+ AsmWrite('[DS]''');
+ end;
+ AsmLn;
+
+ AsmWriteLn(#9'toc');
+
+ AsmWrite(#9'tc'#9);
+ AsmWrite(s);
+ AsmWrite('[TC],');
+ AsmWrite(s);
+ AsmWriteLn('[DS]');
+ end;
+ AT_DATA:
+ begin
+ AsmWrite(#9'import'#9);
+ AsmWrite(s);
+ AsmWrite(var_storage_class);
+ if replaced then
+ begin
+ AsmWrite(' <= ''');
+ AsmWrite(p.name);
+ AsmWrite('''');
+ end;
+ AsmLn;
+
+ AsmWriteLn(#9'toc');
+ AsmWrite(#9'tc'#9);
+ AsmWrite(s);
+ AsmWrite('[TC],');
+ AsmWrite(s);
+ AsmWriteLn(var_storage_class);
+ end
+ else
+ InternalError(2003090901);
+ end;
+ end;
+ end;
+
+ procedure TPPCMPWAssembler.WriteExternals;
+ var
+ i : longint;
+ begin
+ currentasmlist:=self;
+// current_asmdata.asmsymboldict.foreach_static(@writeexternal,nil);
+ for i:=0 to current_asmdata.AsmSymbolDict.Count-1 do
+ begin
+ writeexternal(tasmsymbol(current_asmdata.AsmSymbolDict[i]));
+ end;
+ end;
+
+
+ function TPPCMPWAssembler.DoAssemble : boolean;
+ begin
+ DoAssemble:=Inherited DoAssemble;
+ end;
+
+ procedure TPPCMPWAssembler.WriteAsmFileHeader;
+
+ begin
+ AsmWriteLn(#9'string asis'); {Interpret strings just to be the content between the quotes.}
+ AsmWriteLn(#9'aligning off'); {We do our own aligning.}
+ AsmLn;
+ end;
+
+ procedure TPPCMPWAssembler.WriteAsmList;
+ var
+ hal : tasmlisttype;
+ begin
+{$ifdef EXTDEBUG}
+ if assigned(current_module.mainsource) then
+ comment(v_info,'Start writing MPW-styled assembler output for '+current_module.mainsource^);
+{$endif}
+
+ WriteAsmFileHeader;
+ WriteExternals;
+
+ for hal:=low(TasmlistType) to high(TasmlistType) do
+ begin
+ AsmWriteLn(target_asm.comment+'Begin asmlist '+AsmListTypeStr[hal]);
+ writetree(current_asmdata.asmlists[hal]);
+ AsmWriteLn(target_asm.comment+'End asmlist '+AsmListTypeStr[hal]);
+ end;
+
+ AsmWriteLn(#9'end');
+ AsmLn;
+
+{$ifdef EXTDEBUG}
+ if assigned(current_module.mainsource) then
+ comment(v_info,'Done writing MPW-styled assembler output for '+current_module.mainsource^);
+{$endif EXTDEBUG}
+ end;
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+ const
+ as_powerpc_mpw_info : tasminfo =
+ (
+ id : as_powerpc_mpw;
+ idtxt : 'MPW';
+ asmbin : 'PPCAsm';
+ asmcmd : '-case on $ASM -o $OBJ';
+ supported_targets : [system_powerpc_macos];
+ flags : [af_allowdirect,af_needar,af_smartlink_sections,af_labelprefix_only_inside_procedure];
+ labelprefix : '@';
+ comment : '; ';
+ );
+
+initialization
+ RegisterAssembler(as_powerpc_mpw_info,TPPCMPWAssembler);
+end.
diff --git a/closures/compiler/powerpc/agppcvasm.pas b/closures/compiler/powerpc/agppcvasm.pas
new file mode 100644
index 0000000000..e24b8fbfd6
--- /dev/null
+++ b/closures/compiler/powerpc/agppcvasm.pas
@@ -0,0 +1,406 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit is the VASM writer for PowerPC
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+
+{****************************************************************************}
+{ Helper routines for Instruction Writer }
+{****************************************************************************}
+
+unit agppcvasm;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ aasmbase,
+ aasmtai,aasmdata,
+ aggas,
+ cpubase,cgutils,
+ globtype;
+
+ type
+ TPPCInstrWriter=class(TCPUInstrWriter)
+ procedure WriteInstruction(hp : tai);override;
+ end;
+
+ TPPCVASM=class(TGNUassembler)
+ constructor create(smart: boolean); override;
+ function MakeCmdLine: TCmdStr; override;
+ end;
+
+ topstr = string[4];
+
+ function getreferencestring(var ref : treference) : string;
+ function getopstr_jmp(const o:toper) : string;
+ function getopstr(const o:toper) : string;
+ function branchmode(o: tasmop): topstr;
+ function cond2str(op: tasmop; c: tasmcond): string;
+
+ implementation
+
+ uses
+ cutils,cfileutl,globals,verbose,
+ cgbase,systems,
+ assemble,script,
+ itcpugas,cpuinfo,
+ aasmcpu;
+
+{$ifdef cpu64bitaddr}
+ const
+ refaddr2str: array[trefaddr] of string[9] = ('', '', '', '', '@l', '@h', '@higher', '@highest', '@ha', '@highera', '@highesta');
+ verbose_refaddrs = [addr_low, addr_high, addr_higher, addr_highest, addr_higha, addr_highera, addr_highesta];
+ refaddr2str_darwin: array[trefaddr] of string[4] = ('','','','','lo16', 'hi16', '@err', '@err', 'ha16', '@err', '@err');
+{$else cpu64bitaddr}
+ const
+ refaddr2str: array[trefaddr] of string[3] = ('','','','','@l','@h','@ha');
+ refaddr2str_darwin: array[trefaddr] of string[4] = ('','','','','lo16','hi16','ha16');
+ verbose_refaddrs = [addr_low,addr_high,addr_higha];
+{$endif cpu64bitaddr}
+
+
+ function getreferencestring(var ref : treference) : string;
+ var
+ s : string;
+ begin
+ with ref do
+ begin
+ if ((offset < -32768) or (offset > 32767)) and
+ (refaddr = addr_no) then
+ internalerror(2006052501);
+ if (refaddr = addr_no) then
+ s := ''
+ else
+ begin
+ if target_info.system in [system_powerpc_darwin,system_powerpc64_darwin] then
+ s := refaddr2str_darwin[refaddr]
+ else
+ s :='';
+ s := s+'(';
+ if assigned(symbol) then
+ begin
+ s:=s+symbol.name;
+ if assigned(relsymbol) then
+ s:=s+'-'+relsymbol.name;
+ end;
+ end;
+ if offset<0 then
+ s:=s+tostr(offset)
+ else
+ if (offset>0) then
+ begin
+ if assigned(symbol) then
+ s:=s+'+'+tostr(offset)
+ else
+ s:=s+tostr(offset);
+ end;
+
+ if (refaddr in verbose_refaddrs) then
+ begin
+ s := s+')';
+ if not(target_info.system in [system_powerpc_darwin,system_powerpc64_darwin]) then
+ s := s+refaddr2str[refaddr];
+ end;
+{$ifdef cpu64bitaddr}
+ if (refaddr = addr_pic) then
+ if (target_info.system <> system_powerpc64_linux) then
+ s := s + ')'
+ else
+ s := s + ')@got';
+{$endif cpu64bitaddr}
+
+ if (index=NR_NO) then
+ begin
+ if offset=0 then
+ begin
+ if not (assigned(symbol)) then
+ s:=s+'0';
+ end;
+ if (base<>NR_NO) then
+ s:=s+'('+gas_regname(base)+')'
+ else if not assigned(symbol) and
+ not(refaddr in verbose_refaddrs) then
+ s:=s+'(0)';
+ end
+ else if (index<>NR_NO) and (base<>NR_NO) then
+ begin
+ if (offset=0) then
+ s:=s+gas_regname(base)+','+gas_regname(index)
+ else
+ internalerror(2006052502);
+ end;
+ end;
+ getreferencestring:=s;
+ end;
+
+
+ function getopstr_jmp(const o:toper) : string;
+ var
+ hs : string;
+ begin
+ case o.typ of
+ top_reg :
+ getopstr_jmp:=gas_regname(o.reg);
+ { no top_ref jumping for powerpc }
+ top_const :
+ getopstr_jmp:=tostr(o.val);
+ top_ref :
+ begin
+ if o.ref^.refaddr<>addr_full then
+ internalerror(200402262);
+ hs:=o.ref^.symbol.name;
+ if o.ref^.offset>0 then
+ hs:=hs+'+'+tostr(o.ref^.offset)
+ else
+ if o.ref^.offset<0 then
+ hs:=hs+tostr(o.ref^.offset);
+ getopstr_jmp:=hs;
+ end;
+ top_none:
+ getopstr_jmp:='';
+ else
+ internalerror(2002070603);
+ end;
+ end;
+
+
+ function getopstr(const o:toper) : string;
+ var
+ hs : string;
+ begin
+ case o.typ of
+ top_reg:
+ getopstr:=gas_regname(o.reg);
+ top_const:
+ getopstr:=tostr(longint(o.val));
+ top_ref:
+ if o.ref^.refaddr=addr_full then
+ begin
+ hs:=o.ref^.symbol.name;
+ if o.ref^.offset>0 then
+ hs:=hs+'+'+tostr(o.ref^.offset)
+ else
+ if o.ref^.offset<0 then
+ hs:=hs+tostr(o.ref^.offset);
+ getopstr:=hs;
+ end
+ else
+ getopstr:=getreferencestring(o.ref^);
+ else
+ internalerror(2002070604);
+ end;
+ end;
+
+
+ function branchmode(o: tasmop): topstr;
+ var tempstr: topstr;
+ begin
+ tempstr := '';
+ case o of
+ A_BCCTR,A_BCCTRL: tempstr := 'ctr';
+ A_BCLR,A_BCLRL: tempstr := 'lr';
+ end;
+ case o of
+ A_BL,A_BLA,A_BCL,A_BCLA,A_BCCTRL,A_BCLRL: tempstr := tempstr+'l';
+ end;
+ case o of
+ A_BA,A_BLA,A_BCA,A_BCLA: tempstr:=tempstr+'a';
+ end;
+ branchmode := tempstr;
+ end;
+
+
+ function cond2str(op: tasmop; c: tasmcond): string;
+ { note: no checking is performed whether the given combination of }
+ { conditions is valid }
+ var
+ tempstr: string;
+ begin
+ tempstr:=#9;
+ case c.simple of
+ false:
+ begin
+ cond2str := tempstr+gas_op2str[op];
+ case c.dirhint of
+ DH_None:;
+ DH_Minus:
+ cond2str:=cond2str+'-';
+ DH_Plus:
+ cond2str:=cond2str+'+';
+ else
+ internalerror(2003112901);
+ end;
+ cond2str:=cond2str+#9+tostr(c.bo)+','+tostr(c.bi);
+ end;
+ true:
+ if (op >= A_B) and (op <= A_BCLRL) then
+ case c.cond of
+ { unconditional branch }
+ C_NONE:
+ cond2str := tempstr+gas_op2str[op];
+ { bdnzt etc }
+ else
+ begin
+ tempstr := tempstr+'b'+asmcondflag2str[c.cond]+
+ branchmode(op);
+ case c.dirhint of
+ DH_None:
+ tempstr:=tempstr+#9;
+ DH_Minus:
+ tempstr:=tempstr+('-'+#9);
+ DH_Plus:
+ tempstr:=tempstr+('+'+#9);
+ else
+ internalerror(2003112901);
+ end;
+ case c.cond of
+ C_LT..C_NU:
+ cond2str := tempstr+gas_regname(newreg(R_SPECIALREGISTER,c.cr,R_SUBWHOLE));
+ C_T,C_F,C_DNZT,C_DNZF,C_DZT,C_DZF:
+ cond2str := tempstr+tostr(c.crbit);
+ else
+ cond2str := tempstr;
+ end;
+ end;
+ end
+ { we have a trap instruction }
+ else
+ begin
+ internalerror(2002070601);
+ { not yet implemented !!!!!!!!!!!!!!!!!!!!! }
+ { case tempstr := 'tw';}
+ end;
+ end;
+ end;
+
+
+{****************************************************************************}
+{ PowerPC Instruction Writer }
+{****************************************************************************}
+
+ Procedure TPPCInstrWriter.WriteInstruction(hp : tai);
+ var op: TAsmOp;
+ s: string;
+ i: byte;
+ sep: string[3];
+ begin
+ op:=taicpu(hp).opcode;
+ if is_calljmp(op) then
+ begin
+ { direct BO/BI in op[0] and op[1] not supported, put them in condition! }
+ case op of
+ A_B,A_BA,A_BL,A_BLA:
+ s:=#9+gas_op2str[op]+#9;
+ A_BCTR,A_BCTRL,A_BLR,A_BLRL:
+ s:=#9+gas_op2str[op]
+ else
+ begin
+ s:=cond2str(op,taicpu(hp).condition);
+ if (s[length(s)] <> #9) and
+ (taicpu(hp).ops>0) then
+ s := s + ',';
+ end;
+ end;
+
+ if (taicpu(hp).ops>0) and (taicpu(hp).oper[0]^.typ<>top_none) then
+ begin
+ { first write the current contents of s, because the symbol }
+ { may be 255 characters }
+ owner.asmwrite(s);
+ s:=getopstr_jmp(taicpu(hp).oper[0]^);
+ end;
+ end
+ else
+ { process operands }
+ begin
+ s:=#9+gas_op2str[op];
+ if taicpu(hp).ops<>0 then
+ begin
+ {
+ if not is_calljmp(op) then
+ sep:=','
+ else
+ }
+ sep:=#9;
+ for i:=0 to taicpu(hp).ops-1 do
+ begin
+ // debug code
+ // writeln(s);
+ // writeln(taicpu(hp).fileinfo.line);
+ s:=s+sep+getopstr(taicpu(hp).oper[i]^);
+ sep:=',';
+ end;
+ end;
+ end;
+ owner.AsmWriteLn(s);
+ end;
+
+
+{****************************************************************************}
+{ GNU PPC Assembler writer }
+{****************************************************************************}
+
+
+ constructor TPPCVASM.create(smart: boolean);
+ begin
+ inherited create(smart);
+ InstrWriter := TPPCInstrWriter.create(self);
+ end;
+
+ function TPPCVASM.MakeCmdLine: TCmdStr;
+ begin
+ result:=target_asm.asmcmd;
+
+ if (cs_link_on_target in current_settings.globalswitches) then
+ begin
+ Replace(result,'$ASM',maybequoted(ScriptFixFileName(AsmFileName)));
+ Replace(result,'$OBJ',maybequoted(ScriptFixFileName(ObjFileName)));
+ end
+ else
+ begin
+ Replace(result,'$ASM',maybequoted(Unix2AmigaPath(AsmFileName)));
+ Replace(result,'$OBJ',maybequoted(Unix2AmigaPath(ObjFileName)));
+ end;
+ end;
+
+
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+ const
+ as_powerpc_vasm_info : tasminfo =
+ (
+ id : as_powerpc_vasm;
+
+ idtxt : 'VASM';
+ asmbin : 'fpcvasm';
+ asmcmd: '-quiet -Felf -o $OBJ $ASM';
+ supported_targets : [system_powerpc_morphos];
+ flags : [af_allowdirect,af_needar,af_smartlink_sections];
+ labelprefix : '.L';
+ comment : '# ';
+ );
+
+begin
+ RegisterAssembler(as_powerpc_vasm_info,TPPCVASM);
+end.
diff --git a/closures/compiler/powerpc/aoptcpu.pas b/closures/compiler/powerpc/aoptcpu.pas
new file mode 100644
index 0000000000..cacde466d2
--- /dev/null
+++ b/closures/compiler/powerpc/aoptcpu.pas
@@ -0,0 +1,535 @@
+{
+ Copyright (c) 1998-2002 by Jonas Maebe, member of the Free Pascal
+ Development Team
+
+ This unit implements the PowerPC optimizer object
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+
+
+Unit aoptcpu;
+
+Interface
+
+{$i fpcdefs.inc}
+
+uses cpubase, aoptobj, aoptcpub, aopt, aasmtai,aasmdata, aasmcpu;
+
+Type
+ TCpuAsmOptimizer = class(TAsmOptimizer)
+ { uses the same constructor as TAopObj }
+ function PeepHoleOptPass1Cpu(var p: tai): boolean; override;
+
+ function PostPeepHoleOptsCpu(var p: tai): boolean; override;
+
+ private
+ function cmpi_mfcr_opt(p, next1, next2: taicpu): boolean;
+ End;
+
+Implementation
+
+ uses
+ cutils, cgbase, cgcpu, cgobj;
+
+const
+ calculation_target_op0: array[tasmop] of tasmop = (a_none,
+ a_add, a_add_, a_addo, a_addo_, a_addc, a_addc_, a_addco, a_addco_,
+ a_adde, a_adde_, a_addeo, a_addeo_, a_addi, a_addic, a_addic_, a_addis,
+ a_addme, a_addme_, a_addmeo, a_addmeo_, a_addze, a_addze_, a_addzeo,
+ a_addzeo_, a_and, a_and_, a_andc, a_andc_, a_andi_, a_andis_, a_none,
+ a_none, a_none, a_none, a_none, a_none, a_none, a_none, a_none, a_none, a_none,
+ a_none, a_none, a_none, a_none, a_none, a_cntlzw, a_cntlzw_, a_none,
+ a_none, a_none, a_none, a_none, a_none, a_none, a_none, a_none,
+ a_none, a_none, a_none, a_none, a_none, a_none, a_divw, a_divw_, a_divwo, a_divwo_,
+ a_divwu, a_divwu_, a_divwuo, a_divwuo_, a_none, a_none, a_none, a_eqv,
+ a_eqv_, a_extsb, a_extsb_, a_extsh, a_extsh_, a_fabs, a_fabs_, a_fadd,
+ a_fadd_, a_fadds, a_fadds_, a_none, a_none,
+ a_fctid, a_fctid_, a_fctidz, a_fctidz_,
+ a_fctiw, a_fctiw_, a_fctiwz, a_fctiwz_,
+ a_fdiv, a_fdiv_, a_fdivs, a_fdivs_, a_fmadd, a_fmadd_, a_fmadds,
+ a_fmadds_, a_none, a_fmsub, a_fmsub_, a_fmsubs, a_fmsubs_, a_fmul, a_fmul_,
+ a_fmuls, a_fmuls_, a_fnabs, a_fnabs_, a_fneg, a_fneg_, a_fnmadd,
+ a_fnmadd_, a_fnmadds, a_fnmadds_, a_fnmsub, a_fnmsub_, a_fnmsubs,
+ a_fnmsubs_, a_fres, a_fres_, a_frsp, a_frsp_, a_frsqrte, a_frsqrte_,
+ a_none, a_none, a_fsqrt, a_fsqrt_, a_fsqrts, a_fsqrts_, a_fsub, a_fsub_,
+ a_fsubs, a_fsubs_, a_none, a_none, a_none, a_none, a_none, a_none,
+ a_none, a_none, a_none, a_none, a_none, a_none, a_none, a_none, a_none,
+ a_none, a_none, a_none, a_none, a_none, a_none, a_none, a_none, a_none,
+ a_none, a_none, a_none, a_none, a_none, a_none, a_none, a_none, a_none,
+ a_none, a_none, a_none, a_none, a_none, a_none, a_none, a_none,
+ a_none, a_none, a_none, a_none, a_none, a_none, a_none,
+ a_none, a_none, a_none, a_none, a_none, a_none, a_mulhw,
+ a_mulhw_, a_mulhwu, a_mulhwu_, a_mulli, a_mullw, a_mullw_, a_mullwo,
+ a_mullwo_, a_nand, a_nand_, a_neg, a_neg_, a_nego, a_nego_, a_nor, a_nor_,
+ a_or, a_or_, a_orc, a_orc_, a_ori, a_oris, a_rfi, a_rlwimi, a_rlwimi_,
+ a_rlwinm, a_rlwinm_, a_rlwnm, a_rlwnm_, a_none, a_slw, a_slw_, a_sraw, a_sraw_,
+ a_srawi, a_srawi_,a_srw, a_srw_, a_none, a_none, a_none, a_none, a_none,
+ a_none, a_none, a_none, a_none, a_none, a_none, a_none, a_none,
+ a_none, a_none, a_none, a_none, a_none, a_none, a_none, a_none, a_none,
+ a_none, a_none, a_none, a_none, a_none, a_subf, a_subf_, a_subfo,
+ a_subfo_, a_subfc, a_subfc_, a_subfco, a_subfco_, a_subfe, a_subfe_,
+ a_subfeo, a_subfeo_, a_subfic, a_subfme, a_subfme_, a_subfmeo, a_subfmeo_,
+ a_subfze, a_subfze_, a_subfzeo, a_subfzeo_, a_none, a_none, a_none,
+ a_none, a_none, a_none, a_xor, a_xor_, a_xori, a_xoris,
+ { simplified mnemonics }
+ a_subi, a_subis, a_subic, a_subic_, a_sub, a_sub_, a_subo, a_subo_,
+ a_subc, a_subc_, a_subco, a_subco_, a_none, a_none, a_none, a_none,
+ a_extlwi, a_extlwi_, a_extrwi, a_extrwi_, a_inslwi, a_inslwi_, a_insrwi,
+ a_insrwi_, a_rotlwi, a_rotlwi_, a_rotlw, a_rotlw_, a_slwi, a_slwi_,
+ a_srwi, a_srwi_, a_clrlwi, a_clrlwi_, a_clrrwi, a_clrrwi_, a_clrslwi,
+ a_clrslwi_, a_none, a_none, a_none, a_none, a_none, a_none, a_none,
+ a_none, a_none {move to special prupose reg}, a_none {move from special purpose reg},
+ a_none, a_none, a_none, a_none, a_none, a_none, a_not, a_not_, a_none, a_none, a_none,
+ a_none, a_none, a_none, a_none);
+
+ function TCpuAsmOptimizer.cmpi_mfcr_opt(p, next1, next2: taicpu): boolean;
+ var
+ next3, prev: tai;
+ inverse, prevrlwinm: boolean;
+ begin
+ result := true;
+ inverse :=
+ getnextinstruction(next2,next3) and
+ (next3.typ = ait_instruction) and
+ (taicpu(next3).opcode = A_XORI) and
+ (taicpu(next3).oper[0]^.reg = taicpu(next3).oper[1]^.reg) and
+ (taicpu(next3).oper[0]^.reg = taicpu(next2).oper[0]^.reg) and
+ (taicpu(next3).oper[2]^.val = 1);
+ case taicpu(next2).oper[2]^.val of
+ 1:
+ begin
+ // less than zero or greater/equal than zero (the xori remains in
+ // in the latter case). Doesn't make sense for unsigned comparisons.
+ if (p.opcode = A_CMPWI) then
+ begin
+ p.opcode := A_SRWI;
+ p.ops := 3;
+ p.loadreg(1,p.oper[0]^.reg);
+ p.loadreg(0,next1.oper[0]^.reg);
+ p.loadconst(2,31);
+ asml.remove(next1);
+ next1.free;
+ asml.remove(next2);
+ next2.free;
+ end
+ else
+ result := false;
+ end;
+{
+ needs two registers to work with
+ 2:
+ begin
+ // greater or less/equal to zero
+ end;
+}
+ 3:
+ begin
+ prevrlwinm :=
+ getlastinstruction(p,prev) and
+ (prev.typ = ait_instruction) and
+ ((taicpu(prev).opcode = A_RLWINM) or
+ (taicpu(prev).opcode = A_RLWINM_)) and
+ (taicpu(prev).oper[0]^.reg = p.oper[0]^.reg) and
+ (taicpu(prev).oper[3]^.val = taicpu(prev).oper[4]^.val);
+
+ if (prevrlwinm) then
+ begin
+ // isolate the bit we need
+ if (taicpu(prev).oper[3]^.val <> 31) then
+ begin
+ p.opcode := A_RLWINM;
+ p.ops := 5;
+ p.loadreg(1,p.oper[0]^.reg);
+ p.loadreg(0,next1.oper[0]^.reg);
+ p.loadconst(2,taicpu(prev).oper[3]^.val + 1);
+ p.loadconst(3,31);
+ p.loadconst(4,31);
+ end
+ else { if (taicpu(prev).oper[0]^.reg <> next1.oper[0]^.reg) then }
+ begin
+ p.opcode := A_MR;
+ p.loadreg(1,p.oper[0]^.reg);
+ p.loadreg(0,next1.oper[0]^.reg);
+ end;
+ if not inverse then
+ begin
+ next1.ops := 3;
+ next1.opcode := A_XORI;
+ next1.loadreg(1,next1.oper[0]^.reg);
+ next1.loadconst(2,1);
+ end
+ else
+ begin
+ asml.remove(next1);
+ next1.free;
+ asml.remove(next3);
+ next3.free;
+ end;
+ asml.remove(next2);
+ next2.free;
+ end
+ else
+ begin
+ // equal/not equal to zero (the xori remains in the latter case;
+ // there's a more optimal sequence without it, but needs extra
+ // register)
+ p.opcode := A_CNTLZW;
+ p.loadreg(1,p.oper[0]^.reg);
+ p.loadreg(0,next1.oper[0]^.reg);
+ next1.ops := 3;
+ next1.opcode := A_SRWI;
+ next1.loadreg(1,next1.oper[0]^.reg);
+ next1.loadconst(2,5);
+ asml.remove(next2);
+ next2.free;
+ end;
+ end;
+ else
+ result := false;
+ end;
+ end;
+
+
+ function rlwinm2mask(l1,l2: longint): longint;
+ begin
+ // 1 shl 32 = 1 instead of 0 on x86
+ if (l1 <> 0) then
+ result := longint(cardinal(1) shl (32 - l1) - 1) xor (cardinal(1) shl (31 - l2) - 1)
+ else
+ result := longint(not(cardinal(1) shl (31 - l2) - 1));
+ if (l1 > l2) then
+ result := not(result);
+ end;
+
+
+ function TCpuAsmOptimizer.PeepHoleOptPass1Cpu(var p: tai): boolean;
+ var
+ next1, next2: tai;
+ l1, l2, shlcount: longint;
+ begin
+ result := false;
+ case p.typ of
+ ait_instruction:
+ begin
+ case taicpu(p).opcode of
+ A_CMPWI,
+ A_CMPLWI:
+ begin
+ if (taicpu(p).oper[1]^.typ = top_const) and
+ (taicpu(p).oper[1]^.val = 0) and
+ getnextinstruction(p,next1) and
+ (next1.typ = ait_instruction) and
+ (taicpu(next1).opcode = A_MFCR) and
+ getnextinstruction(next1,next2) and
+ (taicpu(next2).opcode = A_RLWINM) and
+ (taicpu(next2).oper[0]^.reg = taicpu(next2).oper[1]^.reg) and
+ (taicpu(next2).oper[0]^.reg = taicpu(next1).oper[0]^.reg) and
+ (taicpu(next2).oper[3]^.val = 31) and
+ (taicpu(next2).oper[4]^.val = 31) and
+ cmpi_mfcr_opt(taicpu(p),taicpu(next1),taicpu(next2)) then
+ result := true;
+ end;
+{ seems the register allocator doesn't generate superfluous fmr's }
+{ A_FMR, }
+ A_MR:
+ begin
+ if getnextinstruction(p,next1) and
+ (next1.typ = ait_instruction) and
+ (calculation_target_op0[taicpu(next1).opcode] <> a_none) and
+ (taicpu(next1).oper[0]^.reg = taicpu(p).oper[0]^.reg) then
+ begin
+ for l1 := 1 to taicpu(next1).ops - 1 do
+ if (taicpu(next1).oper[l1]^.typ = top_reg) and
+ (taicpu(next1).oper[l1]^.reg = taicpu(p).oper[0]^.reg) then
+ taicpu(next1).loadreg(l1,taicpu(p).oper[1]^.reg);
+ asml.remove(p);
+ p.free;
+ p := next1;
+ result := true;
+ end;
+ end;
+ A_SLWI:
+ begin
+ if getnextinstruction(p,next1) and
+ (next1.typ = ait_instruction) and
+ ((taicpu(next1).opcode = A_RLWINM) or
+ (taicpu(next1).opcode = A_SLWI) or
+ (taicpu(next1).opcode = A_SRWI)) and
+ (taicpu(next1).oper[0]^.reg = taicpu(p).oper[0]^.reg) and
+ (taicpu(next1).oper[1]^.reg = taicpu(p).oper[0]^.reg) then
+ begin
+ { convert slwi to rlwinm and see if the rlwinm }
+ { optimization can do something with it }
+ taicpu(p).opcode := A_RLWINM;
+ taicpu(p).ops := 5;
+ taicpu(p).loadconst(2,taicpu(p).oper[2]^.val);
+ taicpu(p).loadconst(3,0);
+ taicpu(p).loadconst(4,31-taicpu(p).oper[2]^.val);
+ result := true;
+ end;
+ end;
+ A_SRWI:
+ begin
+ if getnextinstruction(p,next1) and
+ (next1.typ = ait_instruction) and
+ ((taicpu(next1).opcode = A_SLWI) or
+ (taicpu(next1).opcode = A_RLWINM) or
+ (taicpu(next1).opcode = A_SRWI)) and
+ (taicpu(next1).oper[0]^.reg = taicpu(p).oper[0]^.reg) and
+ (taicpu(next1).oper[1]^.reg = taicpu(p).oper[0]^.reg) then
+ case taicpu(next1).opcode of
+ A_SLWI:
+ begin
+ taicpu(p).opcode := A_RLWINM;
+ taicpu(p).ops := 5;
+ taicpu(p).loadconst(2,taicpu(next1).oper[2]^.val-taicpu(p).oper[2]^.val);
+ if (taicpu(p).oper[2]^.val < 0) then
+ begin
+ taicpu(p).loadconst(3,-taicpu(p).oper[2]^.val);
+ taicpu(p).loadconst(4,31-taicpu(next1).oper[2]^.val);
+ inc(taicpu(p).oper[2]^.val,32);
+ end
+ else
+ begin
+ taicpu(p).loadconst(3,0);
+ taicpu(p).loadconst(4,31-taicpu(next1).oper[2]^.val);
+ end;
+ asml.remove(next1);
+ next1.free;
+ result := true;
+ end;
+ A_RLWINM:
+ begin
+ { convert srwi to rlwinm and see if the rlwinm }
+ { optimization can do something with it }
+ taicpu(p).opcode := A_RLWINM;
+ taicpu(p).ops := 5;
+ taicpu(p).loadconst(3,taicpu(p).oper[2]^.val);
+ taicpu(p).loadconst(4,31);
+ taicpu(p).loadconst(2,(32-taicpu(p).oper[2]^.val) and 31);
+ result := true;
+ end;
+ end;
+ end;
+ A_RLWINM:
+ begin
+ if getnextinstruction(p,next1) and
+ (next1.typ = ait_instruction) and
+ ((taicpu(next1).opcode = A_RLWINM) or
+ (taicpu(next1).opcode = A_SRWI) or
+ (taicpu(next1).opcode = A_SLWI)) and
+ (taicpu(next1).oper[0]^.reg = taicpu(p).oper[0]^.reg) and
+ // both source and target of next1 must equal target of p
+ (taicpu(next1).oper[1]^.reg = taicpu(p).oper[0]^.reg) then
+ begin
+ case taicpu(next1).opcode of
+ A_RLWINM:
+ begin
+ shlcount := taicpu(next1).oper[2]^.val;
+ l2 := rlwinm2mask(taicpu(next1).oper[3]^.val,taicpu(next1).oper[4]^.val);
+ end;
+ A_SLWI:
+ begin
+ shlcount := taicpu(next1).oper[2]^.val;
+ l2 := (-1) shl shlcount;
+ end;
+ A_SRWI:
+ begin
+ shlcount := 32-taicpu(next1).oper[2]^.val;
+ l2 := (-1) shr taicpu(next1).oper[2]^.val;
+ end;
+ end;
+ l1 := rlwinm2mask((taicpu(p).oper[3]^.val-shlcount) and 31,(taicpu(p).oper[4]^.val-shlcount) and 31);
+ l1 := l1 and l2;
+ case l1 of
+ -1:
+ begin
+ taicpu(p).oper[2]^.val := (taicpu(p).oper[2]^.val + shlcount) and 31;
+ asml.remove(next1);
+ next1.free;
+ if (taicpu(p).oper[2]^.val = 0) then
+ begin
+ next1 := tai(p.next);
+ asml.remove(p);
+ p.free;
+ p := next1;
+ result := true;
+ end;
+ end;
+ 0:
+ begin
+ // masks have no bits in common
+ taicpu(p).opcode := A_LI;
+ taicpu(p).loadconst(1,0);
+ taicpu(p).freeop(2);
+ taicpu(p).freeop(3);
+ taicpu(p).freeop(4);
+ taicpu(p).ops := 2;
+ taicpu(p).opercnt := 2;
+ asml.remove(next1);
+ next1.free;
+ result := true;
+ end
+ else if tcgppc(cg).get_rlwi_const(l1,l1,l2) then
+ begin
+ taicpu(p).oper[2]^.val := (taicpu(p).oper[2]^.val + shlcount) and 31;
+ taicpu(p).oper[3]^.val := l1;
+ taicpu(p).oper[4]^.val := l2;
+ asml.remove(next1);
+ next1.free;
+ result := true;
+ end;
+ end;
+ end;
+ end;
+ end;
+ end;
+ end;
+ end;
+
+
+ const
+ modifyflags: array[tasmop] of tasmop =
+ (a_none, a_add_, a_add_, a_addo_, a_addo_, a_addc_, a_addc_, a_addco_, a_addco_,
+ a_adde_, a_adde_, a_addeo_, a_addeo_, {a_addi could be addic_ if sure doesn't disturb carry} a_none, a_addic_, a_addic_, a_none,
+ a_addme_, a_addme_, a_addmeo_, a_addmeo_, a_addze_, a_addze_, a_addzeo_,
+ a_addzeo_, a_and_, a_and_, a_andc_, a_andc_, a_andi_, a_andis_, a_none,
+ a_none, a_none, a_none, a_none, a_none, a_none, a_none, a_none, a_none, a_none,
+ a_none, a_none, a_none, a_none, a_none, a_cntlzw_, a_cntlzw_, a_none,
+ a_none, a_none, a_none, a_none, a_none, a_none, a_none, a_none,
+ a_none, a_none, a_none, a_none, a_none, a_none, a_divw_, a_divw_, a_divwo_, a_divwo_,
+ a_divwu_, a_divwu_, a_divwuo_, a_divwuo_, a_none, a_none, a_none, a_eqv_,
+ a_eqv_, a_extsb_, a_extsb_, a_extsh_, a_extsh_, a_none, a_none, a_none,
+ a_none, a_none, a_none, a_none, a_none, a_none, a_none, a_none,
+ a_none, a_none, a_none, a_none, a_none, a_none, a_none, a_none,
+ a_none, a_none, a_none, a_none, a_none, a_none, a_none, a_none,
+ a_none, a_none, a_none, a_none, a_none, a_none, a_none,
+ a_none, a_none, a_none, a_none, a_none, a_none,
+ a_none, a_none, a_none, a_none,
+ a_none, a_none, a_none, a_none, a_none, a_none, a_none,
+ a_none, a_none, a_none, a_none, a_none, a_none, a_none, a_none,
+ a_none, a_none, a_none, a_none, a_none, a_none, a_none, a_none,
+ a_none, a_none, a_none, a_none, a_none, a_none, a_none, a_none, a_none,
+ a_none, a_none, a_none, a_none, a_none, a_none, a_none, a_none, a_none,
+ a_none, a_none, a_none, a_none, a_none, a_none, a_none, a_none, a_none,
+ a_none, a_none, a_none, a_mffs, a_mffs_, a_mfmsr, a_mfspr, a_mfsr,
+ a_mfsrin, a_mftb, a_mtcrf, a_none, a_none, a_none, a_none,
+ a_none, a_none, a_none, a_none, a_none, a_none, a_mulhw_,
+ a_mulhw_, a_mulhwu_, a_mulhwu_, a_none, a_mullw_, a_mullw_, a_mullwo_,
+ a_mullwo_, a_nand_, a_nand_, a_neg_, a_neg_, a_nego_, a_nego_, a_nor_, a_nor_,
+ a_or_, a_or_, a_orc_, a_orc_, a_none, a_none, a_none, a_rlwimi_, a_rlwimi_,
+ a_rlwinm_, a_rlwinm_, a_rlwnm_, a_rlwnm_, a_none, a_slw_, a_slw_, a_sraw_, a_sraw_,
+ a_srawi_, a_srawi_,a_srw_, a_srw_, a_none, a_none, a_none, a_none, a_none,
+ a_none, a_none, a_none, a_none, a_none, a_none, a_none, a_none,
+ a_none, a_none, a_none, a_none, a_none, a_none, a_none, a_none, a_none,
+ a_none, a_none, a_none, a_none, a_none, a_subf_, a_subf_, a_subfo_,
+ a_subfo_, a_subfc_, a_subfc_, a_subfco_, a_subfco_, a_subfe_, a_subfe_,
+ a_subfeo_, a_subfeo_, a_none, a_subfme_, a_subfme_, a_subfmeo_, a_subfmeo_,
+ a_subfze_, a_subfze_, a_subfzeo_, a_subfzeo_, a_none, a_none, a_none,
+ a_none, a_none, a_none, a_xor_, a_xor_, a_none, a_none,
+ { simplified mnemonics }
+ a_none, a_none, a_subic_, a_subic_, a_sub_, a_sub_, a_subo_, a_subo_,
+ a_subc_, a_subc_, a_subco_, a_subco_, a_none, a_none, a_none, a_none,
+ a_extlwi_, a_extlwi_, a_extrwi_, a_extrwi_, a_inslwi_, a_inslwi_, a_insrwi_,
+ a_insrwi_, a_rotlwi_, a_rotlwi_, a_rotlw_, a_rotlw_, a_slwi_, a_slwi_,
+ a_srwi_, a_srwi_, a_clrlwi_, a_clrlwi_, a_clrrwi_, a_clrrwi_, a_clrslwi_,
+ a_clrslwi_, a_none, a_none, a_none, a_none, a_none, a_none, a_none,
+ a_none, a_none {move to special prupose reg}, a_none {move from special purpose reg},
+ a_none, a_none, a_none, a_none, a_mr_, a_mr_, a_not_, a_not_, a_none, a_none, a_none,
+ a_none, a_none, a_none, a_none);
+
+ function changetomodifyflags(p: taicpu): boolean;
+ begin
+ result := false;
+ if (modifyflags[p.opcode] <> a_none) then
+ begin
+ p.opcode := modifyflags[p.opcode];
+ result := true;
+ end;
+ end;
+
+ function TCpuAsmOptimizer.PostPeepHoleOptsCpu(var p: tai): boolean;
+ var
+ next1: tai;
+ begin
+ result := false;
+ case p.typ of
+ ait_instruction:
+ begin
+ case taicpu(p).opcode of
+ A_RLWINM_:
+ begin
+ // rlwinm_ is cracked on the G5, andi_/andis_ aren't
+ if (taicpu(p).oper[2]^.val = 0) then
+ if (taicpu(p).oper[3]^.val < 16) and
+ (taicpu(p).oper[4]^.val < 16) then
+ begin
+ taicpu(p).opcode := A_ANDIS_;
+ taicpu(p).oper[2]^.val := word(
+ ((1 shl (16-taicpu(p).oper[3]^.val)) - 1) xor
+ ((1 shl (15-taicpu(p).oper[4]^.val)) - 1));
+ taicpu(p).freeop(3);
+ taicpu(p).freeop(4);
+ taicpu(p).ops := 3;
+ taicpu(p).opercnt := 3;
+ end
+ else if (taicpu(p).oper[3]^.val >= 16) and
+ (taicpu(p).oper[4]^.val >= 16) then
+ begin
+ taicpu(p).opcode := A_ANDI_;
+ taicpu(p).oper[2]^.val := word(rlwinm2mask(taicpu(p).oper[3]^.val,taicpu(p).oper[4]^.val));
+ taicpu(p).freeop(3);
+ taicpu(p).freeop(4);
+ taicpu(p).ops := 3;
+ taicpu(p).opercnt := 3;
+ end;
+ end;
+ end;
+
+ // change "integer operation with destination reg" followed by a
+ // comparison to zero of that reg, with a variant of that integer
+ // operation which sets the flags (if it exists)
+ if not(result) and
+ (taicpu(p).ops >= 2) and
+ (taicpu(p).oper[0]^.typ = top_reg) and
+ (taicpu(p).oper[1]^.typ = top_reg) and
+ getnextinstruction(p,next1) and
+ (next1.typ = ait_instruction) and
+ (taicpu(next1).opcode = A_CMPWI) and
+ // make sure it the result goes to cr0
+ (((taicpu(next1).ops = 2) and
+ (taicpu(next1).oper[1]^.val = 0) and
+ (taicpu(next1).oper[0]^.reg = taicpu(p).oper[0]^.reg)) or
+ ((taicpu(next1).ops = 3) and
+ (taicpu(next1).oper[2]^.val = 0) and
+ (taicpu(next1).oper[0]^.typ = top_reg) and
+ (getsupreg(taicpu(next1).oper[0]^.reg) = RS_CR0) and
+ (taicpu(next1).oper[1]^.reg = taicpu(p).oper[0]^.reg))) and
+ changetomodifyflags(taicpu(p)) then
+ begin
+ asml.remove(next1);
+ next1.free;
+ result := true;
+ end;
+ end;
+ end;
+ end;
+
+begin
+ casmoptimizer:=TCpuAsmOptimizer;
+End.
diff --git a/closures/compiler/powerpc/aoptcpub.pas b/closures/compiler/powerpc/aoptcpub.pas
new file mode 100644
index 0000000000..26507ec19d
--- /dev/null
+++ b/closures/compiler/powerpc/aoptcpub.pas
@@ -0,0 +1,121 @@
+ {
+ Copyright (c) 1998-2002 by Jonas Maebe, member of the Free Pascal
+ Development Team
+
+ This unit contains several types and constants necessary for the
+ optimizer to work on the 80x86 architecture
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+Unit aoptcpub; { Assembler OPTimizer CPU specific Base }
+
+{$i fpcdefs.inc}
+
+{ enable the following define if memory references can have both a base and }
+{ index register in 1 operand }
+
+{$define RefsHaveIndexReg}
+
+{ enable the following define if memory references can have a scaled index }
+
+{ define RefsHaveScale}
+
+{ enable the following define if memory references can have a segment }
+{ override }
+
+{ define RefsHaveSegment}
+
+Interface
+
+Uses
+ aasmcpu,AOptBase, cpubase;
+
+Type
+
+{ type of a normal instruction }
+ TInstr = Taicpu;
+ PInstr = ^TInstr;
+
+{ ************************************************************************* }
+{ **************************** TCondRegs ********************************** }
+{ ************************************************************************* }
+{ Info about the conditional registers }
+ TCondRegs = Object
+ Constructor Init;
+ Destructor Done;
+ End;
+
+{ ************************************************************************* }
+{ **************************** TAoptBaseCpu ******************************* }
+{ ************************************************************************* }
+
+ TAoptBaseCpu = class(TAoptBase)
+ End;
+
+
+{ ************************************************************************* }
+{ ******************************* Constants ******************************* }
+{ ************************************************************************* }
+Const
+
+{ the maximum number of things (registers, memory, ...) a single instruction }
+{ changes }
+
+ MaxCh = 3;
+
+{ the maximum number of operands an instruction has }
+
+ MaxOps = 5;
+
+{Oper index of operand that contains the source (reference) with a load }
+{instruction }
+
+ LoadSrc = 1;
+
+{Oper index of operand that contains the destination (register) with a load }
+{instruction }
+
+ LoadDst = 0;
+
+{Oper index of operand that contains the source (register) with a store }
+{instruction }
+
+ StoreSrc = 0;
+
+{Oper index of operand that contains the destination (reference) with a load }
+{instruction }
+
+ StoreDst = 1;
+
+
+ aopt_uncondjmp = A_B;
+ aopt_condjmp = A_BC;
+
+Implementation
+
+{ ************************************************************************* }
+{ **************************** TCondRegs ********************************** }
+{ ************************************************************************* }
+Constructor TCondRegs.init;
+Begin
+End;
+
+Destructor TCondRegs.Done; {$ifdef inl} inline; {$endif inl}
+Begin
+End;
+
+End.
diff --git a/closures/compiler/powerpc/aoptcpuc.pas b/closures/compiler/powerpc/aoptcpuc.pas
new file mode 100644
index 0000000000..4b82e87f4a
--- /dev/null
+++ b/closures/compiler/powerpc/aoptcpuc.pas
@@ -0,0 +1,40 @@
+ {
+ Copyright (c) 1998-2002 by Jonas Maebe, member of the Free Pascal
+ Development Team
+
+ This unit contains the processor specific implementation of the
+ assembler optimizer common subexpression elimination object.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit aoptcpuc;
+
+Interface
+
+{$i fpcdefs.inc}
+
+Uses
+ AOptCs;
+
+Type
+ TRegInfoCpu = Object(TRegInfo)
+ End;
+
+
+Implementation
+
+End.
diff --git a/closures/compiler/powerpc/aoptcpud.pas b/closures/compiler/powerpc/aoptcpud.pas
new file mode 100644
index 0000000000..2df7e2e49e
--- /dev/null
+++ b/closures/compiler/powerpc/aoptcpud.pas
@@ -0,0 +1,40 @@
+{
+ Copyright (c) 1998-2002 by Jonas Maebe, member of the Free Pascal
+ Development Team
+
+ This unit contains the processor specific implementation of the
+ assembler optimizer data flow analyzer.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+Unit aoptcpud;
+
+{$i fpcdefs.inc}
+
+Interface
+
+uses
+ AOptDA;
+
+Type
+ TAOptDFACpu = class(TAOptDFA)
+ End;
+
+Implementation
+
+
+End.
diff --git a/closures/compiler/powerpc/cgcpu.pas b/closures/compiler/powerpc/cgcpu.pas
new file mode 100644
index 0000000000..fd8fe8976a
--- /dev/null
+++ b/closures/compiler/powerpc/cgcpu.pas
@@ -0,0 +1,1820 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit implements the code generator for the PowerPC
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit cgcpu;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ globtype,symtype,symdef,
+ cgbase,cgobj,cgppc,
+ aasmbase,aasmcpu,aasmtai,aasmdata,
+ cpubase,cpuinfo,cgutils,cg64f32,rgcpu,
+ parabase;
+
+ type
+ tcgppc = class(tcgppcgen)
+ procedure init_register_allocators;override;
+ procedure done_register_allocators;override;
+
+ procedure a_call_name(list : TAsmList;const s : string; weak: boolean);override;
+ procedure a_call_reg(list : TAsmList;reg: tregister); override;
+
+ procedure a_op_const_reg(list : TAsmList; Op: TOpCG; size: TCGSize; a: tcgint; reg: TRegister); override;
+ procedure a_op_reg_reg(list : TAsmList; Op: TOpCG; size: TCGSize; src, dst: TRegister); override;
+
+ procedure a_op_const_reg_reg(list: TAsmList; op: TOpCg;
+ size: tcgsize; a: tcgint; src, dst: tregister); override;
+ procedure a_op_reg_reg_reg(list: TAsmList; op: TOpCg;
+ size: tcgsize; src1, src2, dst: tregister); override;
+
+ { move instructions }
+ procedure a_load_const_reg(list : TAsmList; size: tcgsize; a : tcgint;reg : tregister);override;
+ procedure a_load_ref_reg(list : TAsmList; fromsize, tosize : tcgsize;const Ref : treference;reg : tregister);override;
+ procedure a_load_reg_reg(list : TAsmList; fromsize, tosize : tcgsize;reg1,reg2 : tregister);override;
+
+ procedure a_load_subsetreg_reg(list : TAsmList; subsetsize: tcgsize;
+ tosize: tcgsize; const sreg: tsubsetregister; destreg: tregister); override;
+ procedure a_load_subsetreg_subsetreg(list: TAsmlist; fromsubsetsize, tosubsetsize: tcgsize; const fromsreg, tosreg: tsubsetregister); override;
+
+ { comparison operations }
+ procedure a_cmp_const_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;a : tcgint;reg : tregister;
+ l : tasmlabel);override;
+ procedure a_cmp_reg_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel); override;
+
+ procedure a_jmp_name(list : TAsmList;const s : string); override;
+ procedure a_jmp_always(list : TAsmList;l: tasmlabel); override;
+ procedure a_jmp_flags(list : TAsmList;const f : TResFlags;l: tasmlabel); override;
+
+ procedure g_flags2reg(list: TAsmList; size: TCgSize; const f: TResFlags; reg: TRegister); override;
+
+ procedure g_proc_entry(list : TAsmList;localsize : longint;nostackframe:boolean);override;
+ procedure g_proc_exit(list : TAsmList;parasize : longint;nostackframe:boolean); override;
+ procedure g_save_registers(list:TAsmList); override;
+ procedure g_restore_registers(list:TAsmList); override;
+
+ procedure g_concatcopy(list : TAsmList;const source,dest : treference;len : tcgint);override;
+
+ { find out whether a is of the form 11..00..11b or 00..11...00. If }
+ { that's the case, we can use rlwinm to do an AND operation }
+ function get_rlwi_const(a: aint; var l1, l2: longint): boolean;
+
+ protected
+ procedure a_load_regconst_subsetreg_intern(list : TAsmList; fromsize, subsetsize: tcgsize; fromreg: tregister; const sreg: tsubsetregister; slopt: tsubsetloadopt); override;
+ private
+
+ (* NOT IN USE: *)
+ procedure g_stackframe_entry_mac(list : TAsmList;localsize : longint);
+ (* NOT IN USE: *)
+ procedure g_return_from_proc_mac(list : TAsmList;parasize : tcgint);
+
+ { clear out potential overflow bits from 8 or 16 bit operations }
+ { the upper 24/16 bits of a register after an operation }
+ procedure maybeadjustresult(list: TAsmList; op: TOpCg; size: tcgsize; dst: tregister);
+
+ { returns whether a reference can be used immediately in a powerpc }
+ { instruction }
+ function issimpleref(const ref: treference): boolean;
+
+ function save_regs(list : TAsmList):longint;
+ procedure restore_regs(list : TAsmList);
+ end;
+
+ tcg64fppc = class(tcg64f32)
+ procedure a_op64_reg_reg(list : TAsmList;op:TOpCG;size : tcgsize;regsrc,regdst : tregister64);override;
+ procedure a_op64_const_reg(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;reg : tregister64);override;
+ procedure a_op64_const_reg_reg(list: TAsmList;op:TOpCG;size : tcgsize;value : int64;regsrc,regdst : tregister64);override;
+ procedure a_op64_reg_reg_reg(list: TAsmList;op:TOpCG;size : tcgsize;regsrc1,regsrc2,regdst : tregister64);override;
+ end;
+
+ procedure create_codegen;
+
+const
+ TOpCG2AsmOpConstLo: Array[topcg] of TAsmOp = (A_NONE,A_MR,A_ADDI,A_ANDI_,A_DIVWU,
+ A_DIVW,A_MULLW, A_MULLW, A_NONE,A_NONE,A_ORI,
+ A_SRAWI,A_SLWI,A_SRWI,A_SUBI,A_XORI,A_NONE,A_NONE);
+ TOpCG2AsmOpConstHi: Array[topcg] of TAsmOp = (A_NONE,A_MR,A_ADDIS,A_ANDIS_,
+ A_DIVWU,A_DIVW, A_MULLW,A_MULLW,A_NONE,A_NONE,
+ A_ORIS,A_NONE, A_NONE,A_NONE,A_SUBIS,A_XORIS,A_NONE,A_NONE);
+
+ implementation
+
+ uses
+ globals,verbose,systems,cutils,
+ symconst,symsym,fmodule,
+ rgobj,tgobj,cpupi,procinfo,paramgr;
+
+
+ procedure tcgppc.init_register_allocators;
+ begin
+ inherited init_register_allocators;
+ if target_info.system=system_powerpc_darwin then
+ begin
+{
+ if pi_needs_got in current_procinfo.flags then
+ begin
+ current_procinfo.got:=NR_R31;
+ rg[R_INTREGISTER]:=trgcpu.create(R_INTREGISTER,R_SUBWHOLE,
+ [RS_R2,RS_R3,RS_R4,RS_R5,RS_R6,RS_R7,RS_R8,
+ RS_R9,RS_R10,RS_R11,RS_R12,RS_R30,RS_R29,
+ RS_R28,RS_R27,RS_R26,RS_R25,RS_R24,RS_R23,RS_R22,
+ RS_R21,RS_R20,RS_R19,RS_R18,RS_R17,RS_R16,RS_R15,
+ RS_R14,RS_R13],first_int_imreg,[]);
+ end
+ else}
+ rg[R_INTREGISTER]:=trgintcpu.create(R_INTREGISTER,R_SUBWHOLE,
+ [{$ifdef user0} RS_R0,{$endif} RS_R2,RS_R3,RS_R4,RS_R5,RS_R6,RS_R7,RS_R8,
+ RS_R9,RS_R10,RS_R11,RS_R12,RS_R31,RS_R30,RS_R29,
+ RS_R28,RS_R27,RS_R26,RS_R25,RS_R24,RS_R23,RS_R22,
+ RS_R21,RS_R20,RS_R19,RS_R18,RS_R17,RS_R16,RS_R15,
+ RS_R14,RS_R13],first_int_imreg,[]);
+ end
+ else
+ rg[R_INTREGISTER]:=trgintcpu.create(R_INTREGISTER,R_SUBWHOLE,
+ [{$ifdef user0} RS_R0,{$endif}RS_R3,RS_R4,RS_R5,RS_R6,RS_R7,RS_R8,
+ RS_R9,RS_R10,RS_R11,RS_R12,RS_R31,RS_R30,RS_R29,
+ RS_R28,RS_R27,RS_R26,RS_R25,RS_R24,RS_R23,RS_R22,
+ RS_R21,RS_R20,RS_R19,RS_R18,RS_R17,RS_R16,RS_R15,
+ RS_R14,RS_R13],first_int_imreg,[]);
+ rg[R_FPUREGISTER]:=trgcpu.create(R_FPUREGISTER,R_SUBNONE,
+ [RS_F0,RS_F1,RS_F2,RS_F3,RS_F4,RS_F5,RS_F6,RS_F7,RS_F8,RS_F9,
+ RS_F10,RS_F11,RS_F12,RS_F13,RS_F31,RS_F30,RS_F29,RS_F28,RS_F27,
+ RS_F26,RS_F25,RS_F24,RS_F23,RS_F22,RS_F21,RS_F20,RS_F19,RS_F18,
+ RS_F17,RS_F16,RS_F15,RS_F14],first_fpu_imreg,[]);
+ { TODO: FIX ME}
+ rg[R_MMREGISTER]:=trgcpu.create(R_MMREGISTER,R_SUBNONE,
+ [RS_M0,RS_M1,RS_M2],first_mm_imreg,[]);
+ end;
+
+
+ procedure tcgppc.done_register_allocators;
+ begin
+ rg[R_INTREGISTER].free;
+ rg[R_FPUREGISTER].free;
+ rg[R_MMREGISTER].free;
+ inherited done_register_allocators;
+ end;
+
+ { calling a procedure by name }
+ procedure tcgppc.a_call_name(list : TAsmList;const s : string; weak: boolean);
+ begin
+ { MacOS: The linker on MacOS (PPCLink) inserts a call to glue code,
+ if it is a cross-TOC call. If so, it also replaces the NOP
+ with some restore code.}
+ if (target_info.system <> system_powerpc_darwin) then
+ begin
+ if not(weak) then
+ list.concat(taicpu.op_sym(A_BL,current_asmdata.RefAsmSymbol(s)))
+ else
+ list.concat(taicpu.op_sym(A_BL,current_asmdata.WeakRefAsmSymbol(s)));
+
+ if target_info.system=system_powerpc_macos then
+ list.concat(taicpu.op_none(A_NOP));
+ end
+ else
+ list.concat(taicpu.op_sym(A_BL,get_darwin_call_stub(s,weak)));
+{
+ the compiler does not properly set this flag anymore in pass 1, and
+ for now we only need it after pass 2 (I hope) (JM)
+ if not(pi_do_call in current_procinfo.flags) then
+ internalerror(2003060703);
+}
+ include(current_procinfo.flags,pi_do_call);
+ end;
+
+ { calling a procedure by address }
+ procedure tcgppc.a_call_reg(list : TAsmList;reg: tregister);
+
+ var
+ tmpreg : tregister;
+ tmpref : treference;
+
+ begin
+ if target_info.system=system_powerpc_macos then
+ begin
+ {Generate instruction to load the procedure address from
+ the transition vector.}
+ //TODO: Support cross-TOC calls.
+ tmpreg := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
+ reference_reset(tmpref,4);
+ tmpref.offset := 0;
+ //tmpref.symaddr := refs_full;
+ tmpref.base:= reg;
+ list.concat(taicpu.op_reg_ref(A_LWZ,tmpreg,tmpref));
+ end
+ else
+ tmpreg:=reg;
+ inherited a_call_reg(list,tmpreg);
+ end;
+
+
+{********************** load instructions ********************}
+
+ procedure tcgppc.a_load_const_reg(list : TAsmList; size: TCGSize; a : tcgint; reg : TRegister);
+
+ begin
+ if not(size in [OS_8,OS_S8,OS_16,OS_S16,OS_32,OS_S32]) then
+ internalerror(2002090902);
+ if (a >= low(smallint)) and
+ (a <= high(smallint)) then
+ list.concat(taicpu.op_reg_const(A_LI,reg,smallint(a)))
+ else if ((a and $ffff) <> 0) then
+ begin
+ list.concat(taicpu.op_reg_const(A_LI,reg,smallint(a and $ffff)));
+ if ((a shr 16) <> 0) or
+ (smallint(a and $ffff) < 0) then
+ list.concat(taicpu.op_reg_reg_const(A_ADDIS,reg,reg,
+ smallint((a shr 16)+ord(smallint(a and $ffff) < 0))))
+ end
+ else
+ list.concat(taicpu.op_reg_const(A_LIS,reg,smallint(a shr 16)));
+ end;
+
+
+ procedure tcgppc.a_load_ref_reg(list : TAsmList; fromsize,tosize : tcgsize;const ref: treference;reg : tregister);
+
+ const
+ LoadInstr: Array[OS_8..OS_S32,boolean, boolean] of TAsmOp =
+ { indexed? updating?}
+ (((A_LBZ,A_LBZU),(A_LBZX,A_LBZUX)),
+ ((A_LHZ,A_LHZU),(A_LHZX,A_LHZUX)),
+ ((A_LWZ,A_LWZU),(A_LWZX,A_LWZUX)),
+ { 64bit stuff should be handled separately }
+ ((A_NONE,A_NONE),(A_NONE,A_NONE)),
+ { 128bit stuff too }
+ ((A_NONE,A_NONE),(A_NONE,A_NONE)),
+ { there's no load-byte-with-sign-extend :( }
+ ((A_LBZ,A_LBZU),(A_LBZX,A_LBZUX)),
+ ((A_LHA,A_LHAU),(A_LHAX,A_LHAUX)),
+ ((A_LWZ,A_LWZU),(A_LWZX,A_LWZUX)));
+ var
+ op: tasmop;
+ ref2: treference;
+
+ begin
+ { TODO: optimize/take into consideration fromsize/tosize. Will }
+ { probably only matter for OS_S8 loads though }
+ if not(fromsize in [OS_8,OS_S8,OS_16,OS_S16,OS_32,OS_S32]) then
+ internalerror(2002090903);
+ ref2 := ref;
+ fixref(list,ref2);
+ { the caller is expected to have adjusted the reference already }
+ { in this case }
+ if (TCGSize2Size[fromsize] >= TCGSize2Size[tosize]) then
+ fromsize := tosize;
+ op := loadinstr[fromsize,ref2.index<>NR_NO,false];
+ a_load_store(list,op,reg,ref2);
+ { sign extend shortint if necessary (because there is
+ no load instruction to sign extend an 8 bit value automatically)
+ and mask out extra sign bits when loading from a smaller signed
+ to a larger unsigned type }
+ if fromsize = OS_S8 then
+ begin
+ a_load_reg_reg(list, OS_8, OS_S8, reg, reg);
+ a_load_reg_reg(list, OS_S8, tosize, reg, reg);
+ end;
+ end;
+
+
+ procedure tcgppc.a_load_reg_reg(list : TAsmList;fromsize, tosize : tcgsize;reg1,reg2 : tregister);
+
+ var
+ instr: taicpu;
+ begin
+ if (tcgsize2size[fromsize] > tcgsize2size[tosize]) or
+ ((tcgsize2size[fromsize] = tcgsize2size[tosize]) and
+ (fromsize <> tosize)) or
+ { needs to mask out the sign in the top 16 bits }
+ ((fromsize = OS_S8) and
+ (tosize = OS_16)) then
+ case tosize of
+ OS_8:
+ instr := taicpu.op_reg_reg_const_const_const(A_RLWINM,
+ reg2,reg1,0,31-8+1,31);
+ OS_S8:
+ instr := taicpu.op_reg_reg(A_EXTSB,reg2,reg1);
+ OS_16:
+ instr := taicpu.op_reg_reg_const_const_const(A_RLWINM,
+ reg2,reg1,0,31-16+1,31);
+ OS_S16:
+ instr := taicpu.op_reg_reg(A_EXTSH,reg2,reg1);
+ OS_32,OS_S32:
+ instr := taicpu.op_reg_reg(A_MR,reg2,reg1);
+ else internalerror(2002090901);
+ end
+ else
+ instr := taicpu.op_reg_reg(A_MR,reg2,reg1);
+
+ list.concat(instr);
+ rg[R_INTREGISTER].add_move_instruction(instr);
+ end;
+
+
+ procedure tcgppc.a_load_subsetreg_reg(list : TAsmList; subsetsize, tosize: tcgsize; const sreg: tsubsetregister; destreg: tregister);
+
+ begin
+ if (sreg.bitlen > 32) then
+ internalerror(2008020701);
+ if (sreg.bitlen <> 32) then
+ begin
+ list.concat(taicpu.op_reg_reg_const_const_const(A_RLWINM,destreg,
+ sreg.subsetreg,(32-sreg.startbit) and 31,32-sreg.bitlen,31));
+ { types with a negative lower bound are always a base type (8, 16, 32 bits) }
+ if (subsetsize in [OS_S8..OS_S128]) then
+ if ((sreg.bitlen mod 8) = 0) then
+ begin
+ a_load_reg_reg(list,tcgsize2unsigned[subsetsize],subsetsize,destreg,destreg);
+ a_load_reg_reg(list,subsetsize,tosize,destreg,destreg);
+ end
+ else
+ begin
+ a_op_const_reg(list,OP_SHL,OS_INT,32-sreg.bitlen,destreg);
+ a_op_const_reg(list,OP_SAR,OS_INT,32-sreg.bitlen,destreg);
+ end;
+ end
+ else
+ a_load_reg_reg(list,subsetsize,tosize,sreg.subsetreg,destreg);
+ end;
+
+
+ procedure tcgppc.a_load_regconst_subsetreg_intern(list : TAsmList; fromsize, subsetsize: tcgsize; fromreg: tregister; const sreg: tsubsetregister; slopt: tsubsetloadopt);
+
+ begin
+ if (slopt in [SL_SETZERO,SL_SETMAX]) then
+ inherited a_load_regconst_subsetreg_intern(list,fromsize,subsetsize,fromreg,sreg,slopt)
+ else if (sreg.bitlen>32) then
+ internalerror(2008020702)
+ else if (sreg.bitlen <> 32) then
+ list.concat(taicpu.op_reg_reg_const_const_const(A_RLWIMI,sreg.subsetreg,fromreg,
+ sreg.startbit,32-sreg.startbit-sreg.bitlen,31-sreg.startbit))
+ else
+ a_load_reg_reg(list,fromsize,subsetsize,fromreg,sreg.subsetreg);
+ end;
+
+
+ procedure tcgppc.a_load_subsetreg_subsetreg(list: TAsmlist; fromsubsetsize, tosubsetsize: tcgsize; const fromsreg, tosreg: tsubsetregister);
+
+ begin
+ if (tosreg.bitlen>32) or (tosreg.startbit>31) then
+ internalerror(2008020703);
+ if (fromsreg.bitlen >= tosreg.bitlen) then
+ list.concat(taicpu.op_reg_reg_const_const_const(A_RLWIMI,tosreg.subsetreg, fromsreg.subsetreg,
+ (tosreg.startbit-fromsreg.startbit) and 31,
+ 32-tosreg.startbit-tosreg.bitlen,31-tosreg.startbit))
+ else
+ inherited a_load_subsetreg_subsetreg(list,fromsubsetsize,tosubsetsize,fromsreg,tosreg);
+ end;
+
+
+ procedure tcgppc.a_op_const_reg(list : TAsmList; Op: TOpCG; size: TCGSize; a: tcgint; reg: TRegister);
+
+ begin
+ a_op_const_reg_reg(list,op,size,a,reg,reg);
+ end;
+
+
+ procedure tcgppc.a_op_reg_reg(list : TAsmList; Op: TOpCG; size: TCGSize; src, dst: TRegister);
+
+ begin
+ a_op_reg_reg_reg(list,op,size,src,dst,dst);
+ end;
+
+
+ procedure tcgppc.maybeadjustresult(list: TAsmList; op: TOpCg; size: tcgsize; dst: tregister);
+ const
+ overflowops = [OP_MUL,OP_SHL,OP_ADD,OP_SUB,OP_NOT,OP_NEG];
+ begin
+ if (op in overflowops) and
+ (size in [OS_8,OS_S8,OS_16,OS_S16]) then
+ a_load_reg_reg(list,OS_32,size,dst,dst);
+ end;
+
+
+ procedure tcgppc.a_op_const_reg_reg(list: TAsmList; op: TOpCg;
+ size: tcgsize; a: tcgint; src, dst: tregister);
+ var
+ l1,l2: longint;
+ oplo, ophi: tasmop;
+ scratchreg: tregister;
+ useReg, gotrlwi: boolean;
+
+
+ procedure do_lo_hi;
+ begin
+ list.concat(taicpu.op_reg_reg_const(oplo,dst,src,word(a)));
+ list.concat(taicpu.op_reg_reg_const(ophi,dst,dst,word(a shr 16)));
+ end;
+
+ begin
+ if (op = OP_MOVE) then
+ internalerror(2006031401);
+ if op = OP_SUB then
+ begin
+ a_op_const_reg_reg(list,OP_ADD,size,-a,src,dst);
+ exit;
+ end;
+ ophi := TOpCG2AsmOpConstHi[op];
+ oplo := TOpCG2AsmOpConstLo[op];
+ gotrlwi := get_rlwi_const(aint(a),l1,l2);
+ if (op in [OP_AND,OP_OR,OP_XOR]) then
+ begin
+ if (a = 0) then
+ begin
+ if op = OP_AND then
+ list.concat(taicpu.op_reg_const(A_LI,dst,0))
+ else
+ a_load_reg_reg(list,size,size,src,dst);
+ exit;
+ end
+ else if (a = -1) then
+ begin
+ case op of
+ OP_OR:
+ list.concat(taicpu.op_reg_const(A_LI,dst,-1));
+ OP_XOR:
+ list.concat(taicpu.op_reg_reg(A_NOT,dst,src));
+ OP_AND:
+ a_load_reg_reg(list,size,size,src,dst);
+ end;
+ exit;
+ end
+ else if (aword(a) <= high(word)) and
+ ((op <> OP_AND) or
+ not gotrlwi) then
+ begin
+ if ((size = OS_8) and
+ (byte(a) <> a)) or
+ ((size = OS_S8) and
+ (shortint(a) <> a)) then
+ internalerror(200604142);
+ list.concat(taicpu.op_reg_reg_const(oplo,dst,src,word(a)));
+ { and/or/xor -> cannot overflow in high 16 bits }
+ exit;
+ end;
+ { all basic constant instructions also have a shifted form that }
+ { works only on the highest 16bits, so if lo(a) is 0, we can }
+ { use that one }
+ if (word(a) = 0) and
+ (not(op = OP_AND) or
+ not gotrlwi) then
+ begin
+ if (size in [OS_8,OS_S8,OS_16,OS_S16]) then
+ internalerror(200604141);
+ list.concat(taicpu.op_reg_reg_const(ophi,dst,src,word(a shr 16)));
+ exit;
+ end;
+ end
+ else if (op = OP_ADD) then
+ if a = 0 then
+ begin
+ a_load_reg_reg(list,size,size,src,dst);
+ exit
+ end
+ else if (a >= low(smallint)) and
+ (a <= high(smallint)) then
+ begin
+ list.concat(taicpu.op_reg_reg_const(A_ADDI,dst,src,smallint(a)));
+ maybeadjustresult(list,op,size,dst);
+ exit;
+ end;
+
+ { otherwise, the instructions we can generate depend on the }
+ { operation }
+ useReg := false;
+ case op of
+ OP_DIV,OP_IDIV:
+ if (a = 0) then
+ internalerror(200208103)
+ else if (a = 1) then
+ begin
+ a_load_reg_reg(list,OS_INT,OS_INT,src,dst);
+ exit
+ end
+ else if ispowerof2(a,l1) then
+ begin
+ case op of
+ OP_DIV:
+ list.concat(taicpu.op_reg_reg_const(A_SRWI,dst,src,l1));
+ OP_IDIV:
+ begin
+ list.concat(taicpu.op_reg_reg_const(A_SRAWI,dst,src,l1));
+ list.concat(taicpu.op_reg_reg(A_ADDZE,dst,dst));
+ end;
+ end;
+ exit;
+ end
+ else
+ usereg := true;
+ OP_IMUL, OP_MUL:
+ if (a = 0) then
+ begin
+ list.concat(taicpu.op_reg_const(A_LI,dst,0));
+ exit
+ end
+ else if (a = 1) then
+ begin
+ a_load_reg_reg(list,OS_INT,OS_INT,src,dst);
+ exit
+ end
+ else if ispowerof2(a,l1) then
+ list.concat(taicpu.op_reg_reg_const(A_SLWI,dst,src,l1))
+ else if (longint(a) >= low(smallint)) and
+ (longint(a) <= high(smallint)) then
+ list.concat(taicpu.op_reg_reg_const(A_MULLI,dst,src,smallint(a)))
+ else
+ usereg := true;
+ OP_ADD:
+ begin
+ list.concat(taicpu.op_reg_reg_const(oplo,dst,src,smallint(a)));
+ list.concat(taicpu.op_reg_reg_const(ophi,dst,dst,
+ smallint((a shr 16) + ord(smallint(a) < 0))));
+ end;
+ OP_OR:
+ { try to use rlwimi }
+ if gotrlwi and
+ (src = dst) then
+ begin
+ scratchreg := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
+ list.concat(taicpu.op_reg_const(A_LI,scratchreg,-1));
+ list.concat(taicpu.op_reg_reg_const_const_const(A_RLWIMI,dst,
+ scratchreg,0,l1,l2));
+ end
+ else
+ do_lo_hi;
+ OP_AND:
+ { try to use rlwinm }
+ if gotrlwi then
+ list.concat(taicpu.op_reg_reg_const_const_const(A_RLWINM,dst,
+ src,0,l1,l2))
+ else
+ useReg := true;
+ OP_XOR:
+ do_lo_hi;
+ OP_SHL,OP_SHR,OP_SAR:
+ begin
+ if (a and 31) <> 0 Then
+ list.concat(taicpu.op_reg_reg_const(
+ TOpCG2AsmOpConstLo[Op],dst,src,a and 31))
+ else
+ a_load_reg_reg(list,size,size,src,dst);
+ if (a shr 5) <> 0 then
+ internalError(68991);
+ end;
+ OP_ROL:
+ begin
+ if (not (size in [OS_32, OS_S32])) then begin
+ internalerror(2008091307);
+ end;
+ list.concat(taicpu.op_reg_reg_const_const_const(A_RLWINM, dst, src, a and 31, 0, 31));
+ end;
+ OP_ROR:
+ begin
+ if (not (size in [OS_32, OS_S32])) then begin
+ internalerror(2008091308);
+ end;
+ list.concat(taicpu.op_reg_reg_const_const_const(A_RLWINM, dst, src, (32 - a) and 31, 0, 31));
+ end
+ else
+ internalerror(200109091);
+ end;
+ { if all else failed, load the constant in a register and then }
+ { perform the operation }
+ if useReg then
+ begin
+ scratchreg := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
+ a_load_const_reg(list,OS_32,a,scratchreg);
+ a_op_reg_reg_reg(list,op,OS_32,scratchreg,src,dst);
+ end;
+ maybeadjustresult(list,op,size,dst);
+ end;
+
+
+ procedure tcgppc.a_op_reg_reg_reg(list: TAsmList; op: TOpCg;
+ size: tcgsize; src1, src2, dst: tregister);
+
+ const
+ op_reg_reg_opcg2asmop: array[TOpCG] of tasmop =
+ (A_NONE,A_MR,A_ADD,A_AND,A_DIVWU,A_DIVW,A_MULLW,A_MULLW,A_NEG,A_NOT,A_OR,
+ A_SRAW,A_SLW,A_SRW,A_SUB,A_XOR,A_NONE,A_NONE);
+ var
+ tmpreg : TRegister;
+
+ begin
+ if (op = OP_MOVE) then
+ internalerror(2006031402);
+ case op of
+ OP_NEG,OP_NOT:
+ begin
+ list.concat(taicpu.op_reg_reg(op_reg_reg_opcg2asmop[op],dst,src1));
+ if (op = OP_NOT) and
+ not(size in [OS_32,OS_S32]) then
+ { zero/sign extend result again }
+ a_load_reg_reg(list,OS_32,size,dst,dst);
+ end;
+ OP_ROL:
+ begin
+ if (not (size in [OS_32, OS_S32])) then begin
+ internalerror(2008091305);
+ end;
+ list.concat(taicpu.op_reg_reg_reg_const_const(A_RLWNM, dst, src2, src1, 0, 31));
+ end;
+ OP_ROR:
+ begin
+ if (not (size in [OS_32, OS_S32])) then begin
+ internalerror(2008091306);
+ end;
+ tmpreg := getintregister(current_asmdata.CurrAsmList, OS_INT);
+ list.concat(taicpu.op_reg_reg(A_NEG, tmpreg, src1));
+ list.concat(taicpu.op_reg_reg_reg_const_const(A_RLWNM, dst, src2, tmpreg, 0, 31));
+ end;
+ else
+ list.concat(taicpu.op_reg_reg_reg(op_reg_reg_opcg2asmop[op],dst,src2,src1));
+ end;
+ maybeadjustresult(list,op,size,dst);
+ end;
+
+
+{*************** compare instructructions ****************}
+
+ procedure tcgppc.a_cmp_const_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;a : tcgint;reg : tregister;
+ l : tasmlabel);
+
+ var
+ scratch_register: TRegister;
+ signed: boolean;
+
+ begin
+ signed := cmp_op in [OC_GT,OC_LT,OC_GTE,OC_LTE,OC_EQ,OC_NE];
+ { in the following case, we generate more efficient code when }
+ { signed is false }
+ if (cmp_op in [OC_EQ,OC_NE]) and
+ (aword(a) >= $8000) and
+ (aword(a) <= $ffff) then
+ signed := false;
+ if signed then
+ if (a >= low(smallint)) and (a <= high(smallint)) Then
+ list.concat(taicpu.op_reg_reg_const(A_CMPWI,NR_CR0,reg,a))
+ else
+ begin
+ scratch_register := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
+ a_load_const_reg(list,OS_32,a,scratch_register);
+ list.concat(taicpu.op_reg_reg_reg(A_CMPW,NR_CR0,reg,scratch_register));
+ end
+ else
+ if (aword(a) <= $ffff) then
+ list.concat(taicpu.op_reg_reg_const(A_CMPLWI,NR_CR0,reg,aword(a)))
+ else
+ begin
+ scratch_register := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
+ a_load_const_reg(list,OS_32,a,scratch_register);
+ list.concat(taicpu.op_reg_reg_reg(A_CMPLW,NR_CR0,reg,scratch_register));
+ end;
+ a_jmp(list,A_BC,TOpCmp2AsmCond[cmp_op],0,l);
+ end;
+
+
+ procedure tcgppc.a_cmp_reg_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;
+ reg1,reg2 : tregister;l : tasmlabel);
+
+ var
+ op: tasmop;
+
+ begin
+ if cmp_op in [OC_GT,OC_LT,OC_GTE,OC_LTE] then
+ op := A_CMPW
+ else
+ op := A_CMPLW;
+ list.concat(taicpu.op_reg_reg_reg(op,NR_CR0,reg2,reg1));
+ a_jmp(list,A_BC,TOpCmp2AsmCond[cmp_op],0,l);
+ end;
+
+
+ procedure tcgppc.a_jmp_name(list : TAsmList;const s : string);
+ var
+ p : taicpu;
+ begin
+ if (target_info.system = system_powerpc_darwin) then
+ p := taicpu.op_sym(A_B,get_darwin_call_stub(s,false))
+ else
+ p := taicpu.op_sym(A_B,current_asmdata.RefAsmSymbol(s));
+ p.is_jmp := true;
+ list.concat(p)
+ end;
+
+
+ procedure tcgppc.a_jmp_always(list : TAsmList;l: tasmlabel);
+
+ begin
+ a_jmp(list,A_B,C_None,0,l);
+ end;
+
+ procedure tcgppc.a_jmp_flags(list : TAsmList;const f : TResFlags;l: tasmlabel);
+
+ var
+ c: tasmcond;
+ begin
+ c := flags_to_cond(f);
+ a_jmp(list,A_BC,c.cond,c.cr-RS_CR0,l);
+ end;
+
+ procedure tcgppc.g_flags2reg(list: TAsmList; size: TCgSize; const f: TResFlags; reg: TRegister);
+
+ var
+ testbit: byte;
+ bitvalue: boolean;
+
+ begin
+ { get the bit to extract from the conditional register + its }
+ { requested value (0 or 1) }
+ testbit := ((f.cr-RS_CR0) * 4);
+ case f.flag of
+ F_EQ,F_NE:
+ begin
+ inc(testbit,2);
+ bitvalue := f.flag = F_EQ;
+ end;
+ F_LT,F_GE:
+ begin
+ bitvalue := f.flag = F_LT;
+ end;
+ F_GT,F_LE:
+ begin
+ inc(testbit);
+ bitvalue := f.flag = F_GT;
+ end;
+ else
+ internalerror(200112261);
+ end;
+ { load the conditional register in the destination reg }
+ list.concat(taicpu.op_reg(A_MFCR,reg));
+ { we will move the bit that has to be tested to bit 0 by rotating }
+ { left }
+ testbit := (testbit + 1) and 31;
+ { extract bit }
+ list.concat(taicpu.op_reg_reg_const_const_const(
+ A_RLWINM,reg,reg,testbit,31,31));
+ { if we need the inverse, xor with 1 }
+ if not bitvalue then
+ list.concat(taicpu.op_reg_reg_const(A_XORI,reg,reg,1));
+ end;
+
+(*
+ procedure tcgppc.g_cond2reg(list: TAsmList; const f: TAsmCond; reg: TRegister);
+
+ var
+ testbit: byte;
+ bitvalue: boolean;
+
+ begin
+ { get the bit to extract from the conditional register + its }
+ { requested value (0 or 1) }
+ case f.simple of
+ false:
+ begin
+ { we don't generate this in the compiler }
+ internalerror(200109062);
+ end;
+ true:
+ case f.cond of
+ C_None:
+ internalerror(200109063);
+ C_LT..C_NU:
+ begin
+ testbit := (ord(f.cr) - ord(R_CR0))*4;
+ inc(testbit,AsmCondFlag2BI[f.cond]);
+ bitvalue := AsmCondFlagTF[f.cond];
+ end;
+ C_T,C_F,C_DNZT,C_DNZF,C_DZT,C_DZF:
+ begin
+ testbit := f.crbit
+ bitvalue := AsmCondFlagTF[f.cond];
+ end;
+ else
+ internalerror(200109064);
+ end;
+ end;
+ { load the conditional register in the destination reg }
+ list.concat(taicpu.op_reg_reg(A_MFCR,reg));
+ { we will move the bit that has to be tested to bit 31 -> rotate }
+ { left by bitpos+1 (remember, this is big-endian!) }
+ if bitpos <> 31 then
+ inc(bitpos)
+ else
+ bitpos := 0;
+ { extract bit }
+ list.concat(taicpu.op_reg_reg_const_const_const(
+ A_RLWINM,reg,reg,bitpos,31,31));
+ { if we need the inverse, xor with 1 }
+ if not bitvalue then
+ list.concat(taicpu.op_reg_reg_const(A_XORI,reg,reg,1));
+ end;
+*)
+
+{ *********** entry/exit code and address loading ************ }
+
+ procedure tcgppc.g_save_registers(list:TAsmList);
+ begin
+ { this work is done in g_proc_entry }
+ end;
+
+
+ procedure tcgppc.g_restore_registers(list:TAsmList);
+ begin
+ { this work is done in g_proc_exit }
+ end;
+
+
+ procedure tcgppc.g_proc_entry(list : TAsmList;localsize : longint;nostackframe:boolean);
+ { generated the entry code of a procedure/function. Note: localsize is the }
+ { sum of the size necessary for local variables and the maximum possible }
+ { combined size of ALL the parameters of a procedure called by the current }
+ { one. }
+ { This procedure may be called before, as well as after g_return_from_proc }
+ { is called. NOTE registers are not to be allocated through the register }
+ { allocator here, because the register colouring has already occured !! }
+
+
+ var regcounter,firstregfpu,firstregint: TSuperRegister;
+ href : treference;
+ usesfpr,usesgpr : boolean;
+
+ begin
+ { CR and LR only have to be saved in case they are modified by the current }
+ { procedure, but currently this isn't checked, so save them always }
+ { following is the entry code as described in "Altivec Programming }
+ { Interface Manual", bar the saving of AltiVec registers }
+ a_reg_alloc(list,NR_STACK_POINTER_REG);
+
+ usesgpr := false;
+ usesfpr := false;
+ if not(po_assembler in current_procinfo.procdef.procoptions) then
+ begin
+ { save link register? }
+ if save_lr_in_prologue then
+ begin
+ a_reg_alloc(list,NR_R0);
+ { save return address... }
+ { warning: if this is no longer done via r0, or if r0 is }
+ { added to the usable registers, adapt tcgppcgen.g_profilecode }
+ list.concat(taicpu.op_reg(A_MFLR,NR_R0));
+ { ... in caller's frame }
+ case target_info.abi of
+ abi_powerpc_aix:
+ reference_reset_base(href,NR_STACK_POINTER_REG,LA_LR_AIX,4);
+ abi_powerpc_sysv:
+ reference_reset_base(href,NR_STACK_POINTER_REG,LA_LR_SYSV,4);
+ end;
+ list.concat(taicpu.op_reg_ref(A_STW,NR_R0,href));
+ if not(cs_profile in current_settings.moduleswitches) then
+ a_reg_dealloc(list,NR_R0);
+ end;
+
+(*
+ { save the CR if necessary in callers frame. }
+ if target_info.abi = abi_powerpc_aix then
+ if false then { Not needed at the moment. }
+ begin
+ a_reg_alloc(list,NR_R0);
+ list.concat(taicpu.op_reg_reg(A_MFSPR,NR_R0,NR_CR));
+ reference_reset_base(href,NR_STACK_POINTER_REG,LA_CR_AIX);
+ list.concat(taicpu.op_reg_ref(A_STW,NR_R0,href));
+ a_reg_dealloc(list,NR_R0);
+ end;
+*)
+
+ firstregfpu := tppcprocinfo(current_procinfo).get_first_save_fpu_reg;
+ firstregint := tppcprocinfo(current_procinfo).get_first_save_int_reg;
+ usesgpr := firstregint <> 32;
+ usesfpr := firstregfpu <> 32;
+
+ if (tppcprocinfo(current_procinfo).needs_frame_pointer) then
+ begin
+ a_reg_alloc(list,NR_R12);
+ list.concat(taicpu.op_reg_reg(A_MR,NR_R12,NR_STACK_POINTER_REG));
+ end;
+ end;
+
+ if usesfpr then
+ begin
+ reference_reset_base(href,NR_R1,-8,8);
+ for regcounter:=firstregfpu to RS_F31 do
+ begin
+ a_loadfpu_reg_ref(list,OS_F64,OS_F64,newreg(R_FPUREGISTER,regcounter,R_SUBNONE),href);
+ dec(href.offset,8);
+ end;
+ { compute start of gpr save area }
+ inc(href.offset,4);
+ end
+ else
+ { compute start of gpr save area }
+ reference_reset_base(href,NR_R1,-4,4);
+
+ { save gprs and fetch GOT pointer }
+ if usesgpr then
+ begin
+ if (firstregint <= RS_R22) or
+ ((cs_opt_size in current_settings.optimizerswitches) and
+ { with RS_R30 it's also already smaller, but too big a speed trade-off to make }
+ (firstregint <= RS_R29)) then
+ begin
+ { TODO: TODO: 64 bit support }
+ dec(href.offset,(RS_R31-firstregint)*sizeof(pint));
+ list.concat(taicpu.op_reg_ref(A_STMW,newreg(R_INTREGISTER,firstregint,R_SUBNONE),href));
+ end
+ else
+ for regcounter:=firstregint to RS_R31 do
+ begin
+ a_load_reg_ref(list,OS_INT,OS_INT,newreg(R_INTREGISTER,regcounter,R_SUBNONE),href);
+ dec(href.offset,4);
+ end;
+ end;
+
+{ done in ncgutil because it may only be released after the parameters }
+{ have been moved to their final resting place }
+{ if (tppcprocinfo(current_procinfo).needs_frame_pointer) then }
+{ a_reg_dealloc(list,NR_R12); }
+
+ if (not nostackframe) and
+ tppcprocinfo(current_procinfo).needstackframe and
+ (localsize <> 0) then
+ begin
+ if (localsize <= high(smallint)) then
+ begin
+ reference_reset_base(href,NR_STACK_POINTER_REG,-localsize,8);
+ a_load_store(list,A_STWU,NR_STACK_POINTER_REG,href);
+ end
+ else
+ begin
+ reference_reset_base(href,NR_STACK_POINTER_REG,0,4);
+ { can't use getregisterint here, the register colouring }
+ { is already done when we get here }
+ { R12 may hold previous stack pointer, R11 may be in }
+ { use as got => use R0 (but then we can't use }
+ { a_load_const_reg) }
+ href.index := NR_R0;
+ a_reg_alloc(list,href.index);
+ list.concat(taicpu.op_reg_const(A_LI,NR_R0,smallint((-localsize) and $ffff)));
+ if (smallint((-localsize) and $ffff) < 0) then
+ { upper 16 bits are now $ffff -> xor with inverse }
+ list.concat(taicpu.op_reg_reg_const(A_XORIS,NR_R0,NR_R0,word(not(((-localsize) shr 16) and $ffff))))
+ else
+ list.concat(taicpu.op_reg_reg_const(A_ORIS,NR_R0,NR_R0,word(((-localsize) shr 16) and $ffff)));
+ a_load_store(list,A_STWUX,NR_STACK_POINTER_REG,href);
+ a_reg_dealloc(list,href.index);
+ end;
+ end;
+
+ { save the CR if necessary ( !!! never done currently ) }
+{ still need to find out where this has to be done for SystemV
+ a_reg_alloc(list,R_0);
+ list.concat(taicpu.op_reg_reg(A_MFSPR,R_0,R_CR);
+ list.concat(taicpu.op_reg_ref(A_STW,scratch_register,
+ new_reference(STACK_POINTER_REG,LA_CR)));
+ a_reg_dealloc(list,R_0);
+}
+ { now comes the AltiVec context save, not yet implemented !!! }
+
+ end;
+
+
+ procedure tcgppc.g_proc_exit(list : TAsmList;parasize : longint;nostackframe:boolean);
+ { This procedure may be called before, as well as after g_stackframe_entry }
+ { is called. NOTE registers are not to be allocated through the register }
+ { allocator here, because the register colouring has already occured !! }
+
+ var
+ regcounter,firstregfpu,firstregint: TsuperRegister;
+ href : treference;
+ usesfpr,usesgpr,genret : boolean;
+ localsize: tcgint;
+ begin
+ { AltiVec context restore, not yet implemented !!! }
+
+ usesfpr:=false;
+ usesgpr:=false;
+ if not (po_assembler in current_procinfo.procdef.procoptions) then
+ begin
+ firstregfpu := tppcprocinfo(current_procinfo).get_first_save_fpu_reg;
+ firstregint := tppcprocinfo(current_procinfo).get_first_save_int_reg;
+ usesgpr := firstregint <> 32;
+ usesfpr := firstregfpu <> 32;
+ end;
+
+ localsize:= tppcprocinfo(current_procinfo).calc_stackframe_size;
+
+ { adjust r1 }
+ { (register allocator is no longer valid at this time and an add of 0 }
+ { is translated into a move, which is then registered with the register }
+ { allocator, causing a crash }
+ if (not nostackframe) and
+ tppcprocinfo(current_procinfo).needstackframe and
+ (localsize <> 0) then
+ a_op_const_reg(list,OP_ADD,OS_ADDR,localsize,NR_R1);
+
+ { no return (blr) generated yet }
+ genret:=true;
+ if usesfpr then
+ begin
+ reference_reset_base(href,NR_R1,-8,8);
+ for regcounter := firstregfpu to RS_F31 do
+ begin
+ a_loadfpu_ref_reg(list,OS_F64,OS_F64,href,newreg(R_FPUREGISTER,regcounter,R_SUBNONE));
+ dec(href.offset,8);
+ end;
+ inc(href.offset,4);
+ end
+ else
+ reference_reset_base(href,NR_R1,-4,4);
+
+ if (usesgpr) then
+ begin
+ if (firstregint <= RS_R22) or
+ ((cs_opt_size in current_settings.optimizerswitches) and
+ { with RS_R30 it's also already smaller, but too big a speed trade-off to make }
+ (firstregint <= RS_R29)) then
+ begin
+ { TODO: TODO: 64 bit support }
+ dec(href.offset,(RS_R31-firstregint)*sizeof(pint));
+ list.concat(taicpu.op_reg_ref(A_LMW,newreg(R_INTREGISTER,firstregint,R_SUBNONE),href));
+ end
+ else
+ for regcounter:=firstregint to RS_R31 do
+ begin
+ a_load_ref_reg(list,OS_INT,OS_INT,href,newreg(R_INTREGISTER,regcounter,R_SUBNONE));
+ dec(href.offset,4);
+ end;
+ end;
+
+(*
+ { restore fprs and return }
+ if usesfpr then
+ begin
+ { address of fpr save area to r11 }
+ r:=NR_R12;
+ list.concat(taicpu.op_reg_reg_const(A_ADDI,r,r,(ord(R_F31)-ord(firstregfpu.enum)+1)*8));
+ {
+ if (pi_do_call in current_procinfo.flags) then
+ a_call_name(current_asmdata.RefAsmSymbol('_restfpr_'+tostr(ord(firstregfpu)-ord(R_F14)+14)+'_x'))
+ else
+ { leaf node => lr haven't to be restored }
+ a_call_name('_restfpr_'+tostr(ord(firstregfpu.enum)-ord(R_F14)+14)+'_l');
+ genret:=false;
+ }
+ end;
+*)
+
+ { if we didn't generate the return code, we've to do it now }
+ if genret then
+ begin
+ { load link register? }
+ if not (po_assembler in current_procinfo.procdef.procoptions) then
+ begin
+ if (pi_do_call in current_procinfo.flags) then
+ begin
+ case target_info.abi of
+ abi_powerpc_aix:
+ reference_reset_base(href,NR_STACK_POINTER_REG,LA_LR_AIX,4);
+ abi_powerpc_sysv:
+ reference_reset_base(href,NR_STACK_POINTER_REG,LA_LR_SYSV,4);
+ end;
+ a_reg_alloc(list,NR_R0);
+ list.concat(taicpu.op_reg_ref(A_LWZ,NR_R0,href));
+ list.concat(taicpu.op_reg(A_MTLR,NR_R0));
+ a_reg_dealloc(list,NR_R0);
+ end;
+
+(*
+ { restore the CR if necessary from callers frame}
+ if target_info.abi = abi_powerpc_aix then
+ if false then { Not needed at the moment. }
+ begin
+ reference_reset_base(href,NR_STACK_POINTER_REG,LA_CR_AIX);
+ list.concat(taicpu.op_reg_ref(A_LWZ,NR_R0,href));
+ list.concat(taicpu.op_reg_reg(A_MTSPR,NR_R0,NR_CR));
+ a_reg_dealloc(list,NR_R0);
+ end;
+*)
+ end;
+
+ list.concat(taicpu.op_none(A_BLR));
+ end;
+ end;
+
+
+ function tcgppc.save_regs(list : TAsmList):longint;
+ {Generates code which saves used non-volatile registers in
+ the save area right below the address the stackpointer point to.
+ Returns the actual used save area size.}
+
+ var regcounter,firstregfpu,firstreggpr: TSuperRegister;
+ usesfpr,usesgpr: boolean;
+ href : treference;
+ offset: tcgint;
+ regcounter2, firstfpureg: Tsuperregister;
+ begin
+ usesfpr:=false;
+ if not (po_assembler in current_procinfo.procdef.procoptions) then
+ begin
+ { FIXME: has to be R_F14 instad of R_F8 for SYSV-64bit }
+ case target_info.abi of
+ abi_powerpc_aix:
+ firstfpureg := RS_F14;
+ abi_powerpc_sysv:
+ firstfpureg := RS_F9;
+ else
+ internalerror(2003122903);
+ end;
+ for regcounter:=firstfpureg to RS_F31 do
+ begin
+ if regcounter in rg[R_FPUREGISTER].used_in_proc then
+ begin
+ usesfpr:=true;
+ firstregfpu:=regcounter;
+ break;
+ end;
+ end;
+ end;
+ usesgpr:=false;
+ if not (po_assembler in current_procinfo.procdef.procoptions) then
+ for regcounter2:=RS_R13 to RS_R31 do
+ begin
+ if regcounter2 in rg[R_INTREGISTER].used_in_proc then
+ begin
+ usesgpr:=true;
+ firstreggpr:=regcounter2;
+ break;
+ end;
+ end;
+ offset:= 0;
+
+ { save floating-point registers }
+ if usesfpr then
+ for regcounter := firstregfpu to RS_F31 do
+ begin
+ offset:= offset - 8;
+ reference_reset_base(href, NR_STACK_POINTER_REG, offset, 8);
+ list.concat(taicpu.op_reg_ref(A_STFD, tregister(regcounter), href));
+ end;
+ (* Optimiztion in the future: a_call_name(list,'_savefXX'); *)
+
+ { save gprs in gpr save area }
+ if usesgpr then
+ if firstreggpr < RS_R30 then
+ begin
+ offset:= offset - 4 * (RS_R31 - firstreggpr + 1);
+ reference_reset_base(href,NR_STACK_POINTER_REG,offset,4);
+ list.concat(taicpu.op_reg_ref(A_STMW,tregister(firstreggpr),href));
+ {STMW stores multiple registers}
+ end
+ else
+ begin
+ for regcounter := firstreggpr to RS_R31 do
+ begin
+ offset:= offset - 4;
+ reference_reset_base(href, NR_STACK_POINTER_REG, offset, 4);
+ list.concat(taicpu.op_reg_ref(A_STW, newreg(R_INTREGISTER,regcounter,R_SUBWHOLE), href));
+ end;
+ end;
+
+ { now comes the AltiVec context save, not yet implemented !!! }
+
+ save_regs:= -offset;
+ end;
+
+ procedure tcgppc.restore_regs(list : TAsmList);
+ {Generates code which restores used non-volatile registers from
+ the save area right below the address the stackpointer point to.}
+
+ var regcounter,firstregfpu,firstreggpr: TSuperRegister;
+ usesfpr,usesgpr: boolean;
+ href : treference;
+ offset: integer;
+ regcounter2, firstfpureg: Tsuperregister;
+
+ begin
+ usesfpr:=false;
+ if not (po_assembler in current_procinfo.procdef.procoptions) then
+ begin
+ { FIXME: has to be R_F14 instad of R_F8 for SYSV-64bit }
+ case target_info.abi of
+ abi_powerpc_aix:
+ firstfpureg := RS_F14;
+ abi_powerpc_sysv:
+ firstfpureg := RS_F9;
+ else
+ internalerror(2003122903);
+ end;
+ for regcounter:=firstfpureg to RS_F31 do
+ begin
+ if regcounter in rg[R_FPUREGISTER].used_in_proc then
+ begin
+ usesfpr:=true;
+ firstregfpu:=regcounter;
+ break;
+ end;
+ end;
+ end;
+
+ usesgpr:=false;
+ if not (po_assembler in current_procinfo.procdef.procoptions) then
+ for regcounter2:=RS_R13 to RS_R31 do
+ begin
+ if regcounter2 in rg[R_INTREGISTER].used_in_proc then
+ begin
+ usesgpr:=true;
+ firstreggpr:=regcounter2;
+ break;
+ end;
+ end;
+
+ offset:= 0;
+
+ { restore fp registers }
+ if usesfpr then
+ for regcounter := firstregfpu to RS_F31 do
+ begin
+ offset:= offset - 8;
+ reference_reset_base(href, NR_STACK_POINTER_REG, offset, 8);
+ list.concat(taicpu.op_reg_ref(A_LFD, newreg(R_FPUREGISTER,regcounter,R_SUBWHOLE), href));
+ end;
+ (* Optimiztion in the future: a_call_name(list,'_restfXX'); *)
+
+ { restore gprs }
+ if usesgpr then
+ if firstreggpr < RS_R30 then
+ begin
+ offset:= offset - 4 * (RS_R31 - firstreggpr + 1);
+ reference_reset_base(href,NR_STACK_POINTER_REG,offset, 4); //-220
+ list.concat(taicpu.op_reg_ref(A_LMW,tregister(firstreggpr),href));
+ {LMW loads multiple registers}
+ end
+ else
+ begin
+ for regcounter := firstreggpr to RS_R31 do
+ begin
+ offset:= offset - 4;
+ reference_reset_base(href, NR_STACK_POINTER_REG, offset, 4);
+ list.concat(taicpu.op_reg_ref(A_LWZ, newreg(R_INTREGISTER,regcounter,R_SUBWHOLE), href));
+ end;
+ end;
+
+ { now comes the AltiVec context restore, not yet implemented !!! }
+ end;
+
+
+ procedure tcgppc.g_stackframe_entry_mac(list : TAsmList;localsize : longint);
+ (* NOT IN USE *)
+
+ { generated the entry code of a procedure/function. Note: localsize is the }
+ { sum of the size necessary for local variables and the maximum possible }
+ { combined size of ALL the parameters of a procedure called by the current }
+ { one }
+
+ const
+ macosLinkageAreaSize = 24;
+
+ var
+ href : treference;
+ registerSaveAreaSize : longint;
+
+ begin
+ if (localsize mod 8) <> 0 then
+ internalerror(58991);
+ { CR and LR only have to be saved in case they are modified by the current }
+ { procedure, but currently this isn't checked, so save them always }
+ { following is the entry code as described in "Altivec Programming }
+ { Interface Manual", bar the saving of AltiVec registers }
+ a_reg_alloc(list,NR_STACK_POINTER_REG);
+ a_reg_alloc(list,NR_R0);
+
+ { save return address in callers frame}
+ list.concat(taicpu.op_reg_reg(A_MFSPR,NR_R0,NR_LR));
+ { ... in caller's frame }
+ reference_reset_base(href,NR_STACK_POINTER_REG,8, 8);
+ list.concat(taicpu.op_reg_ref(A_STW,NR_R0,href));
+ a_reg_dealloc(list,NR_R0);
+
+ { save non-volatile registers in callers frame}
+ registerSaveAreaSize:= save_regs(list);
+
+ { save the CR if necessary in callers frame ( !!! always done currently ) }
+ a_reg_alloc(list,NR_R0);
+ list.concat(taicpu.op_reg_reg(A_MFSPR,NR_R0,NR_CR));
+ reference_reset_base(href,NR_STACK_POINTER_REG,LA_CR_AIX,4);
+ list.concat(taicpu.op_reg_ref(A_STW,NR_R0,href));
+ a_reg_dealloc(list,NR_R0);
+
+ (*
+ { save pointer to incoming arguments }
+ list.concat(taicpu.op_reg_reg_const(A_ORI,R_31,STACK_POINTER_REG,0));
+ *)
+
+ (*
+ a_reg_alloc(list,R_12);
+
+ { 0 or 8 based on SP alignment }
+ list.concat(taicpu.op_reg_reg_const_const_const(A_RLWINM,
+ R_12,STACK_POINTER_REG,0,28,28));
+ { add in stack length }
+ list.concat(taicpu.op_reg_reg_const(A_SUBFIC,R_12,R_12,
+ -localsize));
+ { establish new alignment }
+ list.concat(taicpu.op_reg_reg_reg(A_STWUX,STACK_POINTER_REG,STACK_POINTER_REG,R_12));
+
+ a_reg_dealloc(list,R_12);
+ *)
+
+ { allocate stack frame }
+ localsize:= align(localsize + macosLinkageAreaSize + registerSaveAreaSize, 16);
+ inc(localsize,tg.lasttemp);
+ localsize:=align(localsize,16);
+ //tppcprocinfo(current_procinfo).localsize:=localsize;
+
+ if (localsize <> 0) then
+ begin
+ if (localsize <= high(smallint)) then
+ begin
+ reference_reset_base(href,NR_STACK_POINTER_REG,-localsize,8);
+ a_load_store(list,A_STWU,NR_STACK_POINTER_REG,href);
+ end
+ else
+ begin
+ reference_reset_base(href,NR_STACK_POINTER_REG,0,8);
+ href.index := NR_R11;
+ a_reg_alloc(list,href.index);
+ a_load_const_reg(list,OS_S32,-localsize,href.index);
+ a_load_store(list,A_STWUX,NR_STACK_POINTER_REG,href);
+ a_reg_dealloc(list,href.index);
+ end;
+ end;
+ end;
+
+ procedure tcgppc.g_return_from_proc_mac(list : TAsmList;parasize : tcgint);
+ (* NOT IN USE *)
+
+ var
+ href : treference;
+ begin
+ a_reg_alloc(list,NR_R0);
+
+ { restore stack pointer }
+ reference_reset_base(href,NR_STACK_POINTER_REG,LA_SP,4);
+ list.concat(taicpu.op_reg_ref(A_LWZ,NR_STACK_POINTER_REG,href));
+ (*
+ list.concat(taicpu.op_reg_reg_const(A_ORI,NR_STACK_POINTER_REG,R_31,0));
+ *)
+
+ { restore the CR if necessary from callers frame
+ ( !!! always done currently ) }
+ reference_reset_base(href,NR_STACK_POINTER_REG,LA_CR_AIX,4);
+ list.concat(taicpu.op_reg_ref(A_LWZ,NR_R0,href));
+ list.concat(taicpu.op_reg_reg(A_MTSPR,NR_R0,NR_CR));
+ a_reg_dealloc(list,NR_R0);
+
+ (*
+ { restore return address from callers frame }
+ reference_reset_base(href,STACK_POINTER_REG,8);
+ list.concat(taicpu.op_reg_ref(A_LWZ,R_0,href));
+ *)
+
+ { restore non-volatile registers from callers frame }
+ restore_regs(list);
+
+ (*
+ { return to caller }
+ list.concat(taicpu.op_reg_reg(A_MTSPR,R_0,R_LR));
+ list.concat(taicpu.op_none(A_BLR));
+ *)
+
+ { restore return address from callers frame }
+ reference_reset_base(href,NR_STACK_POINTER_REG,8,8);
+ list.concat(taicpu.op_reg_ref(A_LWZ,NR_R0,href));
+
+ { return to caller }
+ list.concat(taicpu.op_reg_reg(A_MTSPR,NR_R0,NR_LR));
+ list.concat(taicpu.op_none(A_BLR));
+ end;
+
+
+{ ************* concatcopy ************ }
+
+{$ifdef use8byteconcatcopy}
+ const
+ maxmoveunit = 8;
+{$else use8byteconcatcopy}
+ const
+ maxmoveunit = 4;
+{$endif use8byteconcatcopy}
+
+ procedure tcgppc.g_concatcopy(list : TAsmList;const source,dest : treference;len : tcgint);
+
+ var
+ countreg: TRegister;
+ src, dst: TReference;
+ lab: tasmlabel;
+ count, count2: aint;
+ size: tcgsize;
+ copyreg: tregister;
+
+ begin
+{$ifdef extdebug}
+ if len > high(longint) then
+ internalerror(2002072704);
+{$endif extdebug}
+
+ if (references_equal(source,dest)) then
+ exit;
+
+ { make sure short loads are handled as optimally as possible }
+ if (len <= maxmoveunit) and
+ (byte(len) in [1,2,4,8]) then
+ begin
+ if len < 8 then
+ begin
+ size := int_cgsize(len);
+ a_load_ref_ref(list,size,size,source,dest);
+ end
+ else
+ begin
+ copyreg := getfpuregister(list,OS_F64);
+ a_loadfpu_ref_reg(list,OS_F64,OS_F64,source,copyreg);
+ a_loadfpu_reg_ref(list,OS_F64,OS_F64,copyreg,dest);
+ end;
+ exit;
+ end;
+
+ count := len div maxmoveunit;
+
+ reference_reset(src,source.alignment);
+ reference_reset(dst,dest.alignment);
+ { load the address of source into src.base }
+ if (count > 4) or
+ not issimpleref(source) or
+ ((source.index <> NR_NO) and
+ ((source.offset + longint(len)) > high(smallint))) then
+ begin
+ src.base := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
+ a_loadaddr_ref_reg(list,source,src.base);
+ end
+ else
+ begin
+ src := source;
+ end;
+ { load the address of dest into dst.base }
+ if (count > 4) or
+ not issimpleref(dest) or
+ ((dest.index <> NR_NO) and
+ ((dest.offset + longint(len)) > high(smallint))) then
+ begin
+ dst.base := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
+ a_loadaddr_ref_reg(list,dest,dst.base);
+ end
+ else
+ begin
+ dst := dest;
+ end;
+
+{$ifdef use8byteconcatcopy}
+ if count > 4 then
+ { generate a loop }
+ begin
+ { the offsets are zero after the a_loadaddress_ref_reg and just }
+ { have to be set to 8. I put an Inc there so debugging may be }
+ { easier (should offset be different from zero here, it will be }
+ { easy to notice in the generated assembler }
+ inc(dst.offset,8);
+ inc(src.offset,8);
+ list.concat(taicpu.op_reg_reg_const(A_SUBI,src.base,src.base,8));
+ list.concat(taicpu.op_reg_reg_const(A_SUBI,dst.base,dst.base,8));
+ countreg := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
+ a_load_const_reg(list,OS_32,count,countreg);
+ copyreg := getfpuregister(list,OS_F64);
+ a_reg_sync(list,copyreg);
+ current_asmdata.getjumplabel(lab);
+ a_label(list, lab);
+ list.concat(taicpu.op_reg_reg_const(A_SUBIC_,countreg,countreg,1));
+ list.concat(taicpu.op_reg_ref(A_LFDU,copyreg,src));
+ list.concat(taicpu.op_reg_ref(A_STFDU,copyreg,dst));
+ a_jmp(list,A_BC,C_NE,0,lab);
+ a_reg_sync(list,copyreg);
+ len := len mod 8;
+ end;
+
+ count := len div 8;
+ if count > 0 then
+ { unrolled loop }
+ begin
+ copyreg := getfpuregister(list,OS_F64);
+ for count2 := 1 to count do
+ begin
+ a_loadfpu_ref_reg(list,OS_F64,OS_F64,src,copyreg);
+ a_loadfpu_reg_ref(list,OS_F64,OS_F64,copyreg,dst);
+ inc(src.offset,8);
+ inc(dst.offset,8);
+ end;
+ len := len mod 8;
+ end;
+
+ if (len and 4) <> 0 then
+ begin
+ a_reg_alloc(list,NR_R0);
+ a_load_ref_reg(list,OS_32,OS_32,src,NR_R0);
+ a_load_reg_ref(list,OS_32,OS_32,NR_R0,dst);
+ inc(src.offset,4);
+ inc(dst.offset,4);
+ a_reg_dealloc(list,NR_R0);
+ end;
+{$else use8byteconcatcopy}
+ if count > 4 then
+ { generate a loop }
+ begin
+ { the offsets are zero after the a_loadaddress_ref_reg and just }
+ { have to be set to 4. I put an Inc there so debugging may be }
+ { easier (should offset be different from zero here, it will be }
+ { easy to notice in the generated assembler }
+ inc(dst.offset,4);
+ inc(src.offset,4);
+ list.concat(taicpu.op_reg_reg_const(A_SUBI,src.base,src.base,4));
+ list.concat(taicpu.op_reg_reg_const(A_SUBI,dst.base,dst.base,4));
+ countreg := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
+ a_load_const_reg(list,OS_32,count,countreg);
+ { explicitely allocate R_0 since it can be used safely here }
+ { (for holding date that's being copied) }
+ a_reg_alloc(list,NR_R0);
+ current_asmdata.getjumplabel(lab);
+ a_label(list, lab);
+ list.concat(taicpu.op_reg_reg_const(A_SUBIC_,countreg,countreg,1));
+ list.concat(taicpu.op_reg_ref(A_LWZU,NR_R0,src));
+ list.concat(taicpu.op_reg_ref(A_STWU,NR_R0,dst));
+ a_jmp(list,A_BC,C_NE,0,lab);
+ a_reg_dealloc(list,NR_R0);
+ len := len mod 4;
+ end;
+
+ count := len div 4;
+ if count > 0 then
+ { unrolled loop }
+ begin
+ a_reg_alloc(list,NR_R0);
+ for count2 := 1 to count do
+ begin
+ a_load_ref_reg(list,OS_32,OS_32,src,NR_R0);
+ a_load_reg_ref(list,OS_32,OS_32,NR_R0,dst);
+ inc(src.offset,4);
+ inc(dst.offset,4);
+ end;
+ a_reg_dealloc(list,NR_R0);
+ len := len mod 4;
+ end;
+{$endif use8byteconcatcopy}
+ { copy the leftovers }
+ if (len and 2) <> 0 then
+ begin
+ a_reg_alloc(list,NR_R0);
+ a_load_ref_reg(list,OS_16,OS_16,src,NR_R0);
+ a_load_reg_ref(list,OS_16,OS_16,NR_R0,dst);
+ inc(src.offset,2);
+ inc(dst.offset,2);
+ a_reg_dealloc(list,NR_R0);
+ end;
+ if (len and 1) <> 0 then
+ begin
+ a_reg_alloc(list,NR_R0);
+ a_load_ref_reg(list,OS_8,OS_8,src,NR_R0);
+ a_load_reg_ref(list,OS_8,OS_8,NR_R0,dst);
+ a_reg_dealloc(list,NR_R0);
+ end;
+ end;
+
+
+{***************** This is private property, keep out! :) *****************}
+
+ function tcgppc.issimpleref(const ref: treference): boolean;
+
+ begin
+ if (ref.base = NR_NO) and
+ (ref.index <> NR_NO) then
+ internalerror(200208101);
+ result :=
+ not(assigned(ref.symbol)) and
+ (((ref.index = NR_NO) and
+ (ref.offset >= low(smallint)) and
+ (ref.offset <= high(smallint))) or
+ ((ref.index <> NR_NO) and
+ (ref.offset = 0)));
+ end;
+
+
+ { find out whether a is of the form 11..00..11b or 00..11...00. If }
+ { that's the case, we can use rlwinm to do an AND operation }
+ function tcgppc.get_rlwi_const(a: aint; var l1, l2: longint): boolean;
+
+ var
+ temp : longint;
+ testbit : aint;
+ compare: boolean;
+
+ begin
+ get_rlwi_const := false;
+ if (a = 0) or (a = -1) then
+ exit;
+ { start with the lowest bit }
+ testbit := 1;
+ { check its value }
+ compare := boolean(a and testbit);
+ { find out how long the run of bits with this value is }
+ { (it's impossible that all bits are 1 or 0, because in that case }
+ { this function wouldn't have been called) }
+ l1 := 31;
+ while (((a and testbit) <> 0) = compare) do
+ begin
+ testbit := testbit shl 1;
+ dec(l1);
+ end;
+
+ { check the length of the run of bits that comes next }
+ compare := not compare;
+ l2 := l1;
+ while (((a and testbit) <> 0) = compare) and
+ (l2 >= 0) do
+ begin
+ testbit := testbit shl 1;
+ dec(l2);
+ end;
+
+ { and finally the check whether the rest of the bits all have the }
+ { same value }
+ compare := not compare;
+ temp := l2;
+ if temp >= 0 then
+ if (a shr (31-temp)) <> ((-ord(compare)) shr (31-temp)) then
+ exit;
+
+ { we have done "not(not(compare))", so compare is back to its }
+ { initial value. If the lowest bit was 0, a is of the form }
+ { 00..11..00 and we need "rlwinm reg,reg,0,l2+1,l1", (+1 }
+ { because l2 now contains the position of the last zero of the }
+ { first run instead of that of the first 1) so switch l1 and l2 }
+ { in that case (we will generate "rlwinm reg,reg,0,l1,l2") }
+ if not compare then
+ begin
+ temp := l1;
+ l1 := l2+1;
+ l2 := temp;
+ end
+ else
+ { otherwise, l1 currently contains the position of the last }
+ { zero instead of that of the first 1 of the second run -> +1 }
+ inc(l1);
+ { the following is the same as "if l1 = -1 then l1 := 31;" }
+ l1 := l1 and 31;
+ l2 := l2 and 31;
+ get_rlwi_const := true;
+ end;
+
+
+ procedure tcg64fppc.a_op64_reg_reg(list : TAsmList;op:TOpCG;size : tcgsize;regsrc,regdst : tregister64);
+ begin
+ case op of
+ OP_NOT:
+ begin
+ cg.a_op_reg_reg(list,OP_NOT,OS_32,regsrc.reglo,regdst.reglo);
+ cg.a_op_reg_reg(list,OP_NOT,OS_32,regsrc.reghi,regdst.reghi);
+ end;
+ OP_NEG:
+ begin
+ list.concat(taicpu.op_reg_reg_const(a_subfic,regdst.reglo,regsrc.reglo,0));
+ list.concat(taicpu.op_reg_reg(a_subfze,regdst.reghi,regsrc.reghi));
+ end;
+ else
+ a_op64_reg_reg_reg(list,op,size,regsrc,regdst,regdst);
+ end;
+ end;
+
+
+ procedure tcg64fppc.a_op64_const_reg(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;reg : tregister64);
+ begin
+ a_op64_const_reg_reg(list,op,size,value,reg,reg);
+ end;
+
+
+ procedure tcg64fppc.a_op64_reg_reg_reg(list: TAsmList;op:TOpCG;size : tcgsize;regsrc1,regsrc2,regdst : tregister64);
+ begin
+ case op of
+ OP_AND,OP_OR,OP_XOR:
+ begin
+ cg.a_op_reg_reg_reg(list,op,OS_32,regsrc1.reglo,regsrc2.reglo,regdst.reglo);
+ cg.a_op_reg_reg_reg(list,op,OS_32,regsrc1.reghi,regsrc2.reghi,regdst.reghi);
+ end;
+ OP_ADD:
+ begin
+ list.concat(taicpu.op_reg_reg_reg(A_ADDC,regdst.reglo,regsrc1.reglo,regsrc2.reglo));
+ list.concat(taicpu.op_reg_reg_reg(A_ADDE,regdst.reghi,regsrc1.reghi,regsrc2.reghi));
+ end;
+ OP_SUB:
+ begin
+ list.concat(taicpu.op_reg_reg_reg(A_SUBC,regdst.reglo,regsrc2.reglo,regsrc1.reglo));
+ list.concat(taicpu.op_reg_reg_reg(A_SUBFE,regdst.reghi,regsrc1.reghi,regsrc2.reghi));
+ end;
+ else
+ internalerror(2002072801);
+ end;
+ end;
+
+
+ procedure tcg64fppc.a_op64_const_reg_reg(list: TAsmList;op:TOpCG;size : tcgsize;value : int64;regsrc,regdst : tregister64);
+
+ const
+ ops: array[boolean,1..3] of tasmop = ((A_ADDIC,A_ADDC,A_ADDZE),
+ (A_SUBIC,A_SUBC,A_ADDME));
+ var
+ tmpreg: tregister;
+ tmpreg64: tregister64;
+ issub: boolean;
+ begin
+ case op of
+ OP_AND,OP_OR,OP_XOR:
+ begin
+ cg.a_op_const_reg_reg(list,op,OS_32,aint(value),regsrc.reglo,regdst.reglo);
+ cg.a_op_const_reg_reg(list,op,OS_32,aint(value shr 32),regsrc.reghi,
+ regdst.reghi);
+ end;
+ OP_ADD, OP_SUB:
+ begin
+ if (value < 0) and
+ (value <> low(value)) then
+ begin
+ if op = OP_ADD then
+ op := OP_SUB
+ else
+ op := OP_ADD;
+ value := -value;
+ end;
+ if (longint(value) <> 0) then
+ begin
+ issub := op = OP_SUB;
+ if (value > 0) and
+ (value-ord(issub) <= 32767) then
+ begin
+ list.concat(taicpu.op_reg_reg_const(ops[issub,1],
+ regdst.reglo,regsrc.reglo,longint(value)));
+ list.concat(taicpu.op_reg_reg(ops[issub,3],
+ regdst.reghi,regsrc.reghi));
+ end
+ else if ((value shr 32) = 0) then
+ begin
+ tmpreg := tcgppc(cg).rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
+ cg.a_load_const_reg(list,OS_32,aint(value),tmpreg);
+ list.concat(taicpu.op_reg_reg_reg(ops[issub,2],
+ regdst.reglo,regsrc.reglo,tmpreg));
+ list.concat(taicpu.op_reg_reg(ops[issub,3],
+ regdst.reghi,regsrc.reghi));
+ end
+ else
+ begin
+ tmpreg64.reglo := tcgppc(cg).rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
+ tmpreg64.reghi := tcgppc(cg).rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
+ a_load64_const_reg(list,value,tmpreg64);
+ a_op64_reg_reg_reg(list,op,size,tmpreg64,regsrc,regdst);
+ end
+ end
+ else
+ begin
+ cg.a_load_reg_reg(list,OS_INT,OS_INT,regsrc.reglo,regdst.reglo);
+ cg.a_op_const_reg_reg(list,op,OS_32,aint(value shr 32),regsrc.reghi,
+ regdst.reghi);
+ end;
+ end;
+ else
+ internalerror(2002072802);
+ end;
+ end;
+
+
+ procedure create_codegen;
+ begin
+ cg := tcgppc.create;
+ cg64 :=tcg64fppc.create;
+ end;
+
+end.
diff --git a/closures/compiler/powerpc/cpubase.pas b/closures/compiler/powerpc/cpubase.pas
new file mode 100644
index 0000000000..4c14d2449f
--- /dev/null
+++ b/closures/compiler/powerpc/cpubase.pas
@@ -0,0 +1,575 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Contains the base types for the PowerPC
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+{ This Unit contains the base types for the PowerPC
+}
+unit cpubase;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ strings,globtype,
+ cutils,cclasses,aasmbase,cpuinfo,cgbase;
+
+
+{*****************************************************************************
+ Assembler Opcodes
+*****************************************************************************}
+
+ type
+ TAsmOp=(A_None,
+ { normal opcodes }
+ a_add, a_add_, a_addo, a_addo_, a_addc, a_addc_, a_addco, a_addco_,
+ a_adde, a_adde_, a_addeo, a_addeo_, a_addi, a_addic, a_addic_, a_addis,
+ a_addme, a_addme_, a_addmeo, a_addmeo_, a_addze, a_addze_, a_addzeo,
+ a_addzeo_, a_and, a_and_, a_andc, a_andc_, a_andi_, a_andis_, a_b,
+ a_ba, a_bl, a_bla, a_bc, a_bca, a_bcl, a_bcla, a_bcctr, a_bcctrl, a_bclr,
+ a_bclrl, a_cmp, a_cmpi, a_cmpl, a_cmpli, a_cntlzw, a_cntlzw_, a_crand,
+ a_crandc, a_creqv, a_crnand, a_crnor, a_cror, a_crorc, a_crxor, a_dcba,
+ a_dcbf, a_dcbi, a_dcbst, a_dcbt, a_dcbtst, a_dcbz, a_divw, a_divw_, a_divwo, a_divwo_,
+ a_divwu, a_divwu_, a_divwuo, a_divwuo_, a_eciwx, a_ecowx, a_eieio, a_eqv,
+ a_eqv_, a_extsb, a_extsb_, a_extsh, a_extsh_, a_fabs, a_fabs_, a_fadd,
+ a_fadd_, a_fadds, a_fadds_, a_fcmpo, a_fcmpu, a_fctid, a_fctid_,
+ a_fctidz, a_fctidz_, a_fctiw, a_fctiw_, a_fctiwz, a_fctiwz_,
+ a_fdiv, a_fdiv_, a_fdivs, a_fdivs_, a_fmadd, a_fmadd_, a_fmadds,
+ a_fmadds_, a_fmr, a_fmsub, a_fmsub_, a_fmsubs, a_fmsubs_, a_fmul, a_fmul_,
+ a_fmuls, a_fmuls_, a_fnabs, a_fnabs_, a_fneg, a_fneg_, a_fnmadd,
+ a_fnmadd_, a_fnmadds, a_fnmadds_, a_fnmsub, a_fnmsub_, a_fnmsubs,
+ a_fnmsubs_, a_fres, a_fres_, a_frsp, a_frsp_, a_frsqrte, a_frsqrte_,
+ a_fsel, a_fsel_, a_fsqrt, a_fsqrt_, a_fsqrts, a_fsqrts_, a_fsub, a_fsub_,
+ a_fsubs, a_fsubs_, a_icbi, a_isync, a_lbz, a_lbzu, a_lbzux, a_lbzx,
+ a_lfd, a_lfdu, a_lfdux, a_lfdx, a_lfs, a_lfsu, a_lfsux, a_lfsx, a_lha,
+ a_lhau, a_lhaux, a_lhax, a_lhbrx, a_lhz, a_lhzu, a_lhzux, a_lhzx, a_lmw,
+ a_lswi, a_lswx, a_lwarx, a_lwbrx, a_lwz, a_lwzu, a_lwzux, a_lwzx, a_mcrf,
+ a_mcrfs, a_mcrxr, a_mfcr, a_mffs, a_mffs_, a_mfmsr, a_mfspr, a_mfsr,
+ a_mfsrin, a_mftb, a_mtcrf, a_mtfsb0, a_mtfsb1, a_mtfsf, a_mtfsf_,
+ a_mtfsfi, a_mtfsfi_, a_mtmsr, a_mtspr, a_mtsr, a_mtsrin, a_mulhw,
+ a_mulhw_, a_mulhwu, a_mulhwu_, a_mulli, a_mullw, a_mullw_, a_mullwo,
+ a_mullwo_, a_nand, a_nand_, a_neg, a_neg_, a_nego, a_nego_, a_nor, a_nor_,
+ a_or, a_or_, a_orc, a_orc_, a_ori, a_oris, a_rfi, a_rlwimi, a_rlwimi_,
+ a_rlwinm, a_rlwinm_, a_rlwnm, a_rlwnm_, a_sc, a_slw, a_slw_, a_sraw, a_sraw_,
+ a_srawi, a_srawi_,a_srw, a_srw_, a_stb, a_stbu, a_stbux, a_stbx, a_stfd,
+ a_stfdu, a_stfdux, a_stfdx, a_stfiwx, a_stfs, a_stfsu, a_stfsux, a_stfsx,
+ a_sth, a_sthbrx, a_sthu, a_sthux, a_sthx, a_stmw, a_stswi, a_stswx, a_stw,
+ a_stwbrx, a_stwcx_, a_stwu, a_stwux, a_stwx, a_subf, a_subf_, a_subfo,
+ a_subfo_, a_subfc, a_subfc_, a_subfco, a_subfco_, a_subfe, a_subfe_,
+ a_subfeo, a_subfeo_, a_subfic, a_subfme, a_subfme_, a_subfmeo, a_subfmeo_,
+ a_subfze, a_subfze_, a_subfzeo, a_subfzeo_, a_sync, a_tlbia, a_tlbie,
+ a_tlbsync, a_tw, a_twi, a_xor, a_xor_, a_xori, a_xoris,
+ { simplified mnemonics }
+ a_subi, a_subis, a_subic, a_subic_, a_sub, a_sub_, a_subo, a_subo_,
+ a_subc, a_subc_, a_subco, a_subco_, a_cmpwi, a_cmpw, a_cmplwi, a_cmplw,
+ a_extlwi, a_extlwi_, a_extrwi, a_extrwi_, a_inslwi, a_inslwi_, a_insrwi,
+ a_insrwi_, a_rotlwi, a_rotlwi_, a_rotlw, a_rotlw_, a_slwi, a_slwi_,
+ a_srwi, a_srwi_, a_clrlwi, a_clrlwi_, a_clrrwi, a_clrrwi_, a_clrslwi,
+ a_clrslwi_, a_blr, a_bctr, a_blrl, a_bctrl, a_crset, a_crclr, a_crmove,
+ a_crnot, a_mt {move to special prupose reg}, a_mf {move from special purpose reg},
+ a_nop, a_li, a_lis, a_la, a_mr, a_mr_, a_not, a_not_, a_mtcr, a_mtlr, a_mflr,
+ a_mtctr, a_mfctr, a_mftbu, a_mfxer);
+
+ {# This should define the array of instructions as string }
+ op2strtable=array[tasmop] of string[8];
+
+ Const
+ {# First value of opcode enumeration }
+ firstop = low(tasmop);
+ {# Last value of opcode enumeration }
+ lastop = high(tasmop);
+
+
+{*****************************************************************************
+ Registers
+*****************************************************************************}
+
+ type
+ { Number of registers used for indexing in tables }
+ tregisterindex=0..{$i rppcnor.inc}-1;
+ totherregisterset = set of tregisterindex;
+
+ const
+ maxvarregs = 32-6; { 32 int registers - r0 - stackpointer - r2 - 3 scratch registers }
+ maxfpuvarregs = 28; { 32 fpuregisters - some scratch registers (minimally 2) }
+ { Available Superregisters }
+ {$i rppcsup.inc}
+
+ { No Subregisters }
+ R_SUBWHOLE=R_SUBNONE;
+
+ { Available Registers }
+ {$i rppccon.inc}
+
+ { Integer Super registers first and last }
+ first_int_imreg = $20;
+
+ { Float Super register first and last }
+ first_fpu_imreg = $20;
+
+ { MM Super register first and last }
+ first_mm_imreg = $20;
+
+{ TODO: Calculate bsstart}
+ regnumber_count_bsstart = 64;
+
+ regnumber_table : array[tregisterindex] of tregister = (
+ {$i rppcnum.inc}
+ );
+
+ regstabs_table : array[tregisterindex] of shortint = (
+ {$i rppcstab.inc}
+ );
+
+ regdwarf_table : array[tregisterindex] of shortint = (
+ {$i rppcdwrf.inc}
+ );
+
+{*****************************************************************************
+ Conditions
+*****************************************************************************}
+
+ type
+ TAsmCondFlag = (C_None { unconditional jumps },
+ { conditions when not using ctr decrement etc }
+ C_LT,C_LE,C_EQ,C_GE,C_GT,C_NL,C_NE,C_NG,C_SO,C_NS,C_UN,C_NU,
+ { conditions when using ctr decrement etc }
+ C_T,C_F,C_DNZ,C_DNZT,C_DNZF,C_DZ,C_DZT,C_DZF);
+
+ TDirHint = (DH_None,DH_Minus,DH_Plus);
+
+ const
+ { these are in the XER, but when moved to CR_x they correspond with the }
+ { bits below }
+ C_OV = C_GT;
+ C_CA = C_EQ;
+ C_NO = C_NG;
+ C_NC = C_NE;
+
+ type
+ TAsmCond = packed record
+ dirhint : tdirhint;
+ case simple: boolean of
+ false: (BO, BI: byte);
+ true: (
+ cond: TAsmCondFlag;
+ case byte of
+ 0: ();
+ { specifies in which part of the cr the bit has to be }
+ { tested for blt,bgt,beq,..,bnu }
+ 1: (cr: RS_CR0..RS_CR7);
+ { specifies the bit to test for bt,bf,bdz,..,bdzf }
+ 2: (crbit: byte)
+ );
+ end;
+
+ const
+ AsmCondFlag2BO: Array[C_T..C_DZF] of Byte =
+ (12,4,16,8,0,18,10,2);
+
+ AsmCondFlag2BOLT_NU: Array[C_LT..C_NU] of Byte =
+ (12,4,12,4,12,4,4,4,12,4,12,4);
+
+ AsmCondFlag2BI: Array[C_LT..C_NU] of Byte =
+ (0,1,2,0,1,0,2,1,3,3,3,3);
+
+ AsmCondFlagTF: Array[TAsmCondFlag] of Boolean =
+ (false,true,false,true,false,true,false,false,false,true,false,true,false,
+ true,false,false,true,false,false,true,false);
+
+ AsmCondFlag2Str: Array[TAsmCondFlag] of string[4] = ({cf_none}'',
+ { conditions when not using ctr decrement etc}
+ 'lt','le','eq','ge','gt','nl','ne','ng','so','ns','un','nu',
+ 't','f','dnz','dnzt','dnzf','dz','dzt','dzf');
+
+ UpperAsmCondFlag2Str: Array[TAsmCondFlag] of string[4] = ({cf_none}'',
+ { conditions when not using ctr decrement etc}
+ 'LT','LE','EQ','GE','GT','NL','NE','NG','SO','NS','UN','NU',
+ 'T','F','DNZ','DNZT','DNZF','DZ','DZT','DZF');
+
+
+ const
+ CondAsmOps=3;
+ CondAsmOp:array[0..CondAsmOps-1] of TasmOp=(
+ A_BC, A_TW, A_TWI
+ );
+ CondAsmOpStr:array[0..CondAsmOps-1] of string[7]=(
+ 'BC','TW','TWI'
+ );
+
+
+{*****************************************************************************
+ Flags
+*****************************************************************************}
+
+ type
+ TResFlagsEnum = (F_EQ,F_NE,F_LT,F_LE,F_GT,F_GE,F_SO,F_FX,F_FEX,F_VX,F_OX);
+ TResFlags = record
+ cr: RS_CR0..RS_CR7;
+ flag: TResFlagsEnum;
+ end;
+
+ (*
+ const
+ { arrays for boolean location conversions }
+
+ flag_2_cond : array[TResFlags] of TAsmCond =
+ (C_E,C_NE,C_LT,C_LE,C_GT,C_GE,???????????????);
+ *)
+
+{*****************************************************************************
+ Reference
+*****************************************************************************}
+
+ const
+ { MacOS only. Whether the direct data area (TOC) directly contain
+ global variables. Otherwise it contains pointers to global variables. }
+ macos_direct_globals = false;
+
+{*****************************************************************************
+ Operand Sizes
+*****************************************************************************}
+
+
+{*****************************************************************************
+ Constants
+*****************************************************************************}
+
+ const
+ max_operands = 5;
+
+
+{*****************************************************************************
+ Default generic sizes
+*****************************************************************************}
+
+ {# Defines the default address size for a processor, }
+ OS_ADDR = OS_32;
+ {# the natural int size for a processor, }
+ OS_INT = OS_32;
+ OS_SINT = OS_S32;
+ {# the maximum float size for a processor, }
+ OS_FLOAT = OS_F64;
+ {# the size of a vector register for a processor }
+ OS_VECTOR = OS_M128;
+
+{*****************************************************************************
+ GDB Information
+*****************************************************************************}
+
+ {# Register indexes for stabs information, when some
+ parameters or variables are stored in registers.
+
+ Taken from rs6000.h (DBX_REGISTER_NUMBER)
+ from GCC 3.x source code. PowerPC has 1:1 mapping
+ according to the order of the registers defined
+ in GCC
+
+ }
+
+ stab_regindex : array[tregisterindex] of shortint = (
+ {$i rppcstab.inc}
+ );
+
+
+{*****************************************************************************
+ Generic Register names
+*****************************************************************************}
+
+ {# Stack pointer register }
+ NR_STACK_POINTER_REG = NR_R1;
+ RS_STACK_POINTER_REG = RS_R1;
+ {# Frame pointer register }
+ NR_FRAME_POINTER_REG = NR_STACK_POINTER_REG;
+ RS_FRAME_POINTER_REG = RS_STACK_POINTER_REG;
+ {# Register for addressing absolute data in a position independant way,
+ such as in PIC code. The exact meaning is ABI specific. For
+ further information look at GCC source : PIC_OFFSET_TABLE_REGNUM
+
+ Taken from GCC rs6000.h
+ }
+{ TODO: As indicated in rs6000.h, but can't find it anywhere else!}
+ NR_PIC_OFFSET_REG = NR_R30;
+ { Return address of a function }
+ NR_RETURN_ADDRESS_REG = NR_R0;
+ { Results are returned in this register (32-bit values) }
+ NR_FUNCTION_RETURN_REG = NR_R3;
+ RS_FUNCTION_RETURN_REG = RS_R3;
+ { Low part of 64bit return value }
+ NR_FUNCTION_RETURN64_LOW_REG = NR_R4;
+ RS_FUNCTION_RETURN64_LOW_REG = RS_R4;
+ { High part of 64bit return value }
+ NR_FUNCTION_RETURN64_HIGH_REG = NR_R3;
+ RS_FUNCTION_RETURN64_HIGH_REG = RS_R3;
+ { The value returned from a function is available in this register }
+ NR_FUNCTION_RESULT_REG = NR_FUNCTION_RETURN_REG;
+ RS_FUNCTION_RESULT_REG = RS_FUNCTION_RETURN_REG;
+ { The lowh part of 64bit value returned from a function }
+ NR_FUNCTION_RESULT64_LOW_REG = NR_FUNCTION_RETURN64_LOW_REG;
+ RS_FUNCTION_RESULT64_LOW_REG = RS_FUNCTION_RETURN64_LOW_REG;
+ { The high part of 64bit value returned from a function }
+ NR_FUNCTION_RESULT64_HIGH_REG = NR_FUNCTION_RETURN64_HIGH_REG;
+ RS_FUNCTION_RESULT64_HIGH_REG = RS_FUNCTION_RETURN64_HIGH_REG;
+
+ NR_FPU_RESULT_REG = NR_F1;
+ NR_MM_RESULT_REG = NR_M0;
+
+
+{*****************************************************************************
+ GCC /ABI linking information
+*****************************************************************************}
+
+ {# Registers which must be saved when calling a routine declared as
+ cppdecl, cdecl, stdcall, safecall, palmossyscall. The registers
+ saved should be the ones as defined in the target ABI and / or GCC.
+
+ This value can be deduced from CALLED_USED_REGISTERS array in the
+ GCC source.
+ }
+ saved_standard_registers : array[0..18] of tsuperregister = (
+ RS_R13,RS_R14,RS_R15,RS_R16,RS_R17,RS_R18,RS_R19,
+ RS_R20,RS_R21,RS_R22,RS_R23,RS_R24,RS_R25,RS_R26,RS_R27,RS_R28,RS_R29,
+ RS_R30,RS_R31
+ );
+
+ { this is only for the generic code which is not used for this architecture }
+ saved_mm_registers : array[0..0] of tsuperregister = (RS_NO);
+
+ {# Required parameter alignment when calling a routine declared as
+ stdcall and cdecl. The alignment value should be the one defined
+ by GCC or the target ABI.
+
+ The value of this constant is equal to the constant
+ PARM_BOUNDARY / BITS_PER_UNIT in the GCC source.
+ }
+ std_param_align = 4; { for 32-bit version only }
+
+
+{*****************************************************************************
+ CPU Dependent Constants
+*****************************************************************************}
+
+ LinkageAreaSizeAIX = 24;
+ LinkageAreaSizeSYSV = 8;
+ { offset in the linkage area for the saved stack pointer }
+ LA_SP = 0;
+ { offset in the linkage area for the saved conditional register}
+ LA_CR_AIX = 4;
+ { offset in the linkage area for the saved link register}
+ LA_LR_AIX = 8;
+ LA_LR_SYSV = 4;
+ { offset in the linkage area for the saved RTOC register}
+ LA_RTOC_AIX = 20;
+
+ PARENT_FRAMEPOINTER_OFFSET = 12;
+
+ NR_RTOC = NR_R2;
+
+ maxfpuregs = 8;
+
+{*****************************************************************************
+ Helpers
+*****************************************************************************}
+
+ function is_calljmp(o:tasmop):boolean;
+
+ procedure inverse_flags(var r : TResFlags);
+ function flags_to_cond(const f: TResFlags) : TAsmCond;
+ procedure create_cond_imm(BO,BI:byte;var r : TAsmCond);
+ procedure create_cond_norm(cond: TAsmCondFlag; cr: byte;var r : TasmCond);
+
+ function cgsize2subreg(regtype: tregistertype; s:Tcgsize):Tsubregister;
+ { Returns the tcgsize corresponding with the size of reg.}
+ function reg_cgsize(const reg: tregister) : tcgsize;
+
+ function findreg_by_number(r:Tregister):tregisterindex;
+ function std_regnum_search(const s:string):Tregister;
+ function std_regname(r:Tregister):string;
+ function is_condreg(r : tregister):boolean;
+
+ function inverse_cond(const c: TAsmCond): Tasmcond; {$ifdef USEINLINE}inline;{$endif USEINLINE}
+ function conditions_equal(const c1, c2: TAsmCond): boolean;
+ function dwarf_reg(r:tregister):shortint;
+
+implementation
+
+ uses
+ rgbase,verbose;
+
+ const
+ std_regname_table : array[tregisterindex] of string[7] = (
+ {$i rppcstd.inc}
+ );
+
+ regnumber_index : array[tregisterindex] of tregisterindex = (
+ {$i rppcrni.inc}
+ );
+
+ std_regname_index : array[tregisterindex] of tregisterindex = (
+ {$i rppcsri.inc}
+ );
+
+
+{*****************************************************************************
+ Helpers
+*****************************************************************************}
+
+ function is_calljmp(o:tasmop):boolean;
+ begin
+ is_calljmp:=false;
+ case o of
+ A_B,A_BA,A_BL,A_BLA,A_BC,A_BCA,A_BCL,A_BCLA,A_BCCTR,A_BCCTRL,A_BCLR,
+ A_BCLRL,A_TW,A_TWI: is_calljmp:=true;
+ end;
+ end;
+
+
+ procedure inverse_flags(var r: TResFlags);
+ const
+ inv_flags: array[F_EQ..F_GE] of TResFlagsEnum =
+ (F_NE,F_EQ,F_GE,F_GE,F_LE,F_LT);
+ begin
+ r.flag := inv_flags[r.flag];
+ end;
+
+
+ function inverse_cond(const c: TAsmCond): Tasmcond; {$ifdef USEINLINE}inline;{$endif USEINLINE}
+ const
+ inv_condflags:array[TAsmCondFlag] of TAsmCondFlag=(C_None,
+ C_GE,C_GT,C_NE,C_LT,C_LE,C_LT,C_EQ,C_GT,C_NS,C_SO,C_NU,C_UN,
+ C_F,C_T,C_DNZ,C_DNZF,C_DNZT,C_DZ,C_DZF,C_DZT);
+ begin
+ if (c.cond in [C_DNZ,C_DZ]) then
+ internalerror(2005022501);
+ result := c;
+ result.cond := inv_condflags[c.cond];
+ end;
+
+
+ function conditions_equal(const c1, c2: TAsmCond): boolean;
+ begin
+ result :=
+ (c1.simple and c2.simple) and
+ (c1.cond = c2.cond) and
+ ((not(c1.cond in [C_T..C_DZF]) and
+ (c1.cr = c2.cr)) or
+ (c1.crbit = c2.crbit));
+ end;
+
+
+ function flags_to_cond(const f: TResFlags) : TAsmCond;
+ const
+ flag_2_cond: array[F_EQ..F_SO] of TAsmCondFlag =
+ (C_EQ,C_NE,C_LT,C_LE,C_GT,C_GE,C_SO);
+ begin
+ if f.flag > high(flag_2_cond) then
+ internalerror(200112301);
+ result.simple := true;
+ result.cr := f.cr;
+ result.cond := flag_2_cond[f.flag];
+ end;
+
+
+ procedure create_cond_imm(BO,BI:byte;var r : TAsmCond);
+ begin
+ r.simple := false;
+ r.bo := bo;
+ r.bi := bi;
+ end;
+
+
+ procedure create_cond_norm(cond: TAsmCondFlag; cr: byte;var r : TasmCond);
+ begin
+ r.simple := true;
+ r.cond := cond;
+ case cond of
+ C_NONE:;
+ C_T..C_DZF: r.crbit := cr
+ else r.cr := RS_CR0+cr;
+ end;
+ end;
+
+
+ function is_condreg(r : tregister):boolean;
+ var
+ supreg: tsuperregister;
+ begin
+ result := false;
+ if (getregtype(r) = R_SPECIALREGISTER) then
+ begin
+ supreg := getsupreg(r);
+ result := (supreg >= RS_CR0) and (supreg <= RS_CR7);
+ end;
+ end;
+
+
+ function reg_cgsize(const reg: tregister): tcgsize;
+ begin
+ case getregtype(reg) of
+ R_INTREGISTER :
+ result:=OS_32;
+ R_MMREGISTER:
+ result:=OS_M128;
+ R_FPUREGISTER:
+ result:=OS_F64;
+ else
+ internalerror(200303181);
+ end;
+ end;
+
+
+ function cgsize2subreg(regtype: tregistertype; s:Tcgsize):Tsubregister;
+ begin
+ cgsize2subreg:=R_SUBWHOLE;
+ end;
+
+
+ function findreg_by_number(r:Tregister):tregisterindex;
+ begin
+ result:=rgBase.findreg_by_number_table(r,regnumber_index);
+ end;
+
+
+ function std_regnum_search(const s:string):Tregister;
+ begin
+ result:=regnumber_table[findreg_by_name_table(s,std_regname_table,std_regname_index)];
+ end;
+
+
+ function std_regname(r:Tregister):string;
+ var
+ p : tregisterindex;
+ begin
+ p:=findreg_by_number_table(r,regnumber_index);
+ if p<>0 then
+ result:=std_regname_table[p]
+ else
+ result:=generic_regname(r);
+ end;
+
+
+ function dwarf_reg(r:tregister):shortint;
+ begin
+ result:=regdwarf_table[findreg_by_number(r)];
+ if result=-1 then
+ internalerror(200603251);
+ end;
+
+end.
diff --git a/closures/compiler/powerpc/cpuinfo.pas b/closures/compiler/powerpc/cpuinfo.pas
new file mode 100644
index 0000000000..1d91423462
--- /dev/null
+++ b/closures/compiler/powerpc/cpuinfo.pas
@@ -0,0 +1,88 @@
+{
+ Copyright (c) 1998-2002 by the Free Pascal development team
+
+ Basic Processor information for the PowerPC
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+Unit CPUInfo;
+
+Interface
+
+ uses
+ globtype;
+
+Type
+ bestreal = double;
+ ts32real = single;
+ ts64real = double;
+ ts80real = extended;
+ ts128real = extended;
+ ts64comp = comp;
+
+ pbestreal=^bestreal;
+
+ { possible supported processors for this target }
+ tcputype =
+ (cpu_none,
+ cpu_ppc604,
+ cpu_ppc750,
+ cpu_ppc7400,
+ cpu_ppc970
+ );
+
+ tfputype =
+ (fpu_none,
+ fpu_soft,
+ fpu_standard
+ );
+
+
+Const
+ { calling conventions supported by the code generator }
+ supported_calling_conventions : tproccalloptions = [
+ pocall_internproc,
+ pocall_stdcall,
+ { the difference to stdcall is only the name mangling }
+ pocall_cdecl,
+ { the difference to stdcall is only the name mangling }
+ pocall_cppdecl,
+ { pass all const records by reference }
+ pocall_mwpascal
+ ];
+
+ cputypestr : array[tcputype] of string[10] = ('',
+ '604',
+ '750',
+ '7400',
+ '970'
+ );
+
+ fputypestr : array[tfputype] of string[8] = (
+ 'NONE',
+ 'SOFT',
+ 'STANDARD'
+ );
+
+ { Supported optimizations, only used for information }
+ supported_optimizerswitches = genericlevel1optimizerswitches+
+ genericlevel2optimizerswitches+
+ genericlevel3optimizerswitches-
+ { no need to write info about those }
+ [cs_opt_level1,cs_opt_level2,cs_opt_level3]+
+ [cs_opt_regvar,cs_opt_loopunroll,cs_opt_nodecse,cs_opt_tailrecursion];
+
+ level1optimizerswitches = genericlevel1optimizerswitches;
+ level2optimizerswitches = genericlevel2optimizerswitches + level1optimizerswitches + [cs_opt_regvar,cs_opt_nodecse,cs_opt_tailrecursion];
+ level3optimizerswitches = genericlevel3optimizerswitches + level2optimizerswitches + [{,cs_opt_loopunroll}];
+
+Implementation
+
+end.
diff --git a/closures/compiler/powerpc/cpunode.pas b/closures/compiler/powerpc/cpunode.pas
new file mode 100644
index 0000000000..4be69d046b
--- /dev/null
+++ b/closures/compiler/powerpc/cpunode.pas
@@ -0,0 +1,51 @@
+{
+ Copyright (c) 2000-2002 by Florian Klaempfl
+
+ Includes the PowerPC code generator
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit cpunode;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ implementation
+
+ uses
+ { generic nodes }
+ ncgbas,ncgld,ncgflw,ncgcnv,ncgmem,ncgcon,ncgcal,ncgset,ncginl,ncgopt,
+ ncgobjc,
+ { to be able to only parts of the generic code,
+ the processor specific nodes must be included
+ after the generic one (FK)
+ }
+ nppcadd,
+ nppccal,
+// nppccon,
+// nppcflw,
+// nppcmem,
+ ngppcset,
+ ngppcinl,
+// nppcopt,
+ nppcmat,
+ nppccnv
+// nppcld
+ ;
+
+end.
diff --git a/closures/compiler/powerpc/cpupara.pas b/closures/compiler/powerpc/cpupara.pas
new file mode 100644
index 0000000000..1ee35eb781
--- /dev/null
+++ b/closures/compiler/powerpc/cpupara.pas
@@ -0,0 +1,709 @@
+{
+ Copyright (c) 2002 by Florian Klaempfl
+
+ PowerPC specific calling conventions
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ ****************************************************************************
+}
+unit cpupara;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ globtype,
+ aasmtai,aasmdata,
+ cpubase,
+ symconst,symtype,symdef,symsym,
+ paramgr,parabase,cgbase,cgutils;
+
+ type
+ tppcparamanager = class(tparamanager)
+ function get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;override;
+ function get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;override;
+ function push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override;
+
+ procedure getintparaloc(calloption : tproccalloption; nr : longint;var cgpara:TCGPara);override;
+ function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override;
+ function create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;override;
+ function get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tcgpara;override;
+ procedure create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
+ private
+ procedure init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword);
+ function create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras:tparalist;
+ var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword; varargsparas: boolean):longint;
+ function parseparaloc(p : tparavarsym;const s : string) : boolean;override;
+ end;
+
+ implementation
+
+ uses
+ verbose,systems,
+ defutil,symtable,
+ procinfo,cpupi;
+
+
+ function tppcparamanager.get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;
+ begin
+ if (target_info.system = system_powerpc_darwin) then
+ result := [RS_R0,RS_R2..RS_R12]
+ else
+ result := [RS_R0,RS_R3..RS_R12];
+ end;
+
+
+ function tppcparamanager.get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;
+ begin
+ case target_info.abi of
+ abi_powerpc_aix,
+ abi_powerpc_sysv:
+ result := [RS_F0..RS_F13];
+ else
+ internalerror(2003091401);
+ end;
+ end;
+
+
+ procedure tppcparamanager.getintparaloc(calloption : tproccalloption; nr : longint;var cgpara:TCGPara);
+ var
+ paraloc : pcgparalocation;
+ begin
+ cgpara.reset;
+ cgpara.size:=OS_ADDR;
+ cgpara.intsize:=sizeof(pint);
+ cgpara.alignment:=get_para_align(calloption);
+ paraloc:=cgpara.add_location;
+ with paraloc^ do
+ begin
+ size:=OS_INT;
+ if (nr<=8) then
+ begin
+ if nr=0 then
+ internalerror(200309271);
+ loc:=LOC_REGISTER;
+ register:=newreg(R_INTREGISTER,RS_R2+nr,R_SUBWHOLE);
+ end
+ else
+ begin
+ loc:=LOC_REFERENCE;
+ paraloc^.reference.index:=NR_STACK_POINTER_REG;
+ if (target_info.abi <> abi_powerpc_aix) then
+ reference.offset:=sizeof(pint)*(nr-8)
+ else
+ reference.offset:=sizeof(pint)*(nr);
+ end;
+ end;
+ end;
+
+
+
+ function getparaloc(p : tdef) : tcgloc;
+
+ begin
+ { Later, the LOC_REFERENCE is in most cases changed into LOC_REGISTER
+ if push_addr_param for the def is true
+ }
+ case p.typ of
+ orddef:
+ result:=LOC_REGISTER;
+ floatdef:
+ result:=LOC_FPUREGISTER;
+ enumdef:
+ result:=LOC_REGISTER;
+ pointerdef:
+ result:=LOC_REGISTER;
+ formaldef:
+ result:=LOC_REGISTER;
+ classrefdef:
+ result:=LOC_REGISTER;
+ procvardef:
+ if (target_info.abi = abi_powerpc_aix) or
+ (p.size = sizeof(pint)) then
+ result:=LOC_REGISTER
+ else
+ result:=LOC_REFERENCE;
+ recorddef:
+ if (target_info.abi<>abi_powerpc_aix) or
+ ((p.size >= 3) and
+ ((p.size mod 4) <> 0)) then
+ result:=LOC_REFERENCE
+ else
+ result:=LOC_REGISTER;
+ objectdef:
+ if is_object(p) then
+ result:=LOC_REFERENCE
+ else
+ result:=LOC_REGISTER;
+ stringdef:
+ if is_shortstring(p) or is_longstring(p) then
+ result:=LOC_REFERENCE
+ else
+ result:=LOC_REGISTER;
+ filedef:
+ result:=LOC_REGISTER;
+ arraydef:
+ result:=LOC_REFERENCE;
+ setdef:
+ if is_smallset(p) then
+ result:=LOC_REGISTER
+ else
+ result:=LOC_REFERENCE;
+ variantdef:
+ result:=LOC_REFERENCE;
+ { avoid problems with errornous definitions }
+ errordef:
+ result:=LOC_REGISTER;
+ else
+ internalerror(2002071001);
+ end;
+ end;
+
+
+ function tppcparamanager.push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;
+ begin
+ result:=false;
+ { var,out,constref always require address }
+ if varspez in [vs_var,vs_out,vs_constref] then
+ begin
+ result:=true;
+ exit;
+ end;
+ case def.typ of
+ variantdef,
+ formaldef :
+ result:=true;
+ { regular procvars must be passed by value, because you cannot pass
+ the address of a local stack location when calling e.g.
+ pthread_create with the address of a function (first of all it
+ expects the address of the function to execute and not the address
+ of a memory location containing that address, and secondly if you
+ first store the address on the stack and then pass the address of
+ this stack location, then this stack location may no longer be
+ valid when the newly started thread accesses it.
+
+ However, for "procedure of object" we must use the same calling
+ convention as for "8 byte record" due to the need for
+ interchangeability with the TMethod record type.
+ }
+ procvardef :
+ result:=
+ (target_info.abi <> abi_powerpc_aix) and
+ (def.size <> sizeof(pint));
+ recorddef :
+ result :=
+ (target_info.abi<>abi_powerpc_aix) or
+ ((varspez = vs_const) and
+ ((calloption = pocall_mwpascal) or
+ (not (calloption in [pocall_cdecl,pocall_cppdecl]) and
+ (def.size > 8)
+ )
+ )
+ );
+ arraydef:
+ result:=(tarraydef(def).highrange>=tarraydef(def).lowrange) or
+ is_open_array(def) or
+ is_array_of_const(def) or
+ is_array_constructor(def);
+ objectdef :
+ result:=is_object(def);
+ setdef :
+ result:=not is_smallset(def);
+ stringdef :
+ result:=tstringdef(def).stringtype in [st_shortstring,st_longstring];
+ end;
+ end;
+
+
+ procedure tppcparamanager.init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword);
+ begin
+ case target_info.abi of
+ abi_powerpc_aix:
+ cur_stack_offset:=24;
+ abi_powerpc_sysv:
+ cur_stack_offset:=8;
+ else
+ internalerror(2003051901);
+ end;
+ curintreg:=RS_R3;
+ curfloatreg:=RS_F1;
+ curmmreg:=RS_M1;
+ end;
+
+
+ procedure tppcparamanager.create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
+ begin
+ p.funcretloc[side]:=get_funcretloc(p,side,p.returndef);
+ end;
+
+
+ function tppcparamanager.get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tcgpara;
+ var
+ paraloc : pcgparalocation;
+ retcgsize : tcgsize;
+ begin
+ result.init;
+ result.alignment:=get_para_align(p.proccalloption);
+ { void has no location }
+ if is_void(def) then
+ begin
+ paraloc:=result.add_location;
+ result.size:=OS_NO;
+ result.intsize:=0;
+ paraloc^.size:=OS_NO;
+ paraloc^.loc:=LOC_VOID;
+ exit;
+ end;
+ { Constructors return self instead of a boolean }
+ if (p.proctypeoption=potype_constructor) then
+ begin
+ retcgsize:=OS_ADDR;
+ result.intsize:=sizeof(pint);
+ end
+ else
+ begin
+ retcgsize:=def_cgsize(def);
+ result.intsize:=def.size;
+ end;
+ result.size:=retcgsize;
+ { Return is passed as var parameter }
+ if ret_in_param(def,p.proccalloption) then
+ begin
+ paraloc:=result.add_location;
+ paraloc^.loc:=LOC_REFERENCE;
+ paraloc^.size:=retcgsize;
+ exit;
+ end;
+
+ paraloc:=result.add_location;
+ { Return in FPU register? }
+ if def.typ=floatdef then
+ begin
+ paraloc^.loc:=LOC_FPUREGISTER;
+ paraloc^.register:=NR_FPU_RESULT_REG;
+ paraloc^.size:=retcgsize;
+ end
+ else
+ { Return in register }
+ begin
+ if retcgsize in [OS_64,OS_S64] then
+ begin
+ { low 32bits }
+ paraloc^.loc:=LOC_REGISTER;
+ if side=callerside then
+ paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG
+ else
+ paraloc^.register:=NR_FUNCTION_RETURN64_HIGH_REG;
+ paraloc^.size:=OS_32;
+ { high 32bits }
+ paraloc:=result.add_location;
+ paraloc^.loc:=LOC_REGISTER;
+ if side=callerside then
+ paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG
+ else
+ paraloc^.register:=NR_FUNCTION_RETURN64_LOW_REG;
+ paraloc^.size:=OS_32;
+ end
+ else
+ begin
+ paraloc^.loc:=LOC_REGISTER;
+ if side=callerside then
+ paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize))
+ else
+ paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(R_INTREGISTER,retcgsize));
+ paraloc^.size:=retcgsize;
+ end;
+ end;
+ end;
+
+
+ function tppcparamanager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;
+
+ var
+ cur_stack_offset: aword;
+ curintreg, curfloatreg, curmmreg: tsuperregister;
+ begin
+ init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset);
+
+ result := create_paraloc_info_intern(p,side,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset,false);
+
+ create_funcretloc_info(p,side);
+ end;
+
+
+
+ function tppcparamanager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras:tparalist;
+ var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword; varargsparas: boolean):longint;
+ var
+ stack_offset: longint;
+ paralen: aint;
+ nextintreg,nextfloatreg,nextmmreg, maxfpureg : tsuperregister;
+ paradef : tdef;
+ paraloc : pcgparalocation;
+ i : integer;
+ hp : tparavarsym;
+ loc : tcgloc;
+ paracgsize: tcgsize;
+ sym: tfieldvarsym;
+
+ begin
+{$ifdef extdebug}
+ if po_explicitparaloc in p.procoptions then
+ internalerror(200411141);
+{$endif extdebug}
+
+ result:=0;
+ nextintreg := curintreg;
+ nextfloatreg := curfloatreg;
+ nextmmreg := curmmreg;
+ stack_offset := cur_stack_offset;
+ case target_info.abi of
+ abi_powerpc_aix:
+ maxfpureg := RS_F13;
+ abi_powerpc_sysv:
+ maxfpureg := RS_F8;
+ else internalerror(2004070912);
+ end;
+
+ for i:=0 to paras.count-1 do
+ begin
+ hp:=tparavarsym(paras[i]);
+ paradef := hp.vardef;
+ { Syscall for Morphos can have already a paraloc set }
+ if (vo_has_explicit_paraloc in hp.varoptions) then
+ begin
+ if not(vo_is_syscall_lib in hp.varoptions) then
+ internalerror(200412153);
+ continue;
+ end;
+ hp.paraloc[side].reset;
+ { currently only support C-style array of const }
+ if (p.proccalloption in [pocall_cdecl,pocall_cppdecl,pocall_mwpascal]) and
+ is_array_of_const(paradef) then
+ begin
+ paraloc:=hp.paraloc[side].add_location;
+ { hack: the paraloc must be valid, but is not actually used }
+ paraloc^.loc := LOC_REGISTER;
+ paraloc^.register := NR_R0;
+ paraloc^.size := OS_ADDR;
+ break;
+ end;
+
+ if (hp.varspez in [vs_var,vs_out]) or
+ push_addr_param(hp.varspez,paradef,p.proccalloption) or
+ is_open_array(paradef) or
+ is_array_of_const(paradef) then
+ begin
+ paradef:=voidpointertype;
+ loc:=LOC_REGISTER;
+ paracgsize := OS_ADDR;
+ paralen := tcgsize2size[OS_ADDR];
+ end
+ else
+ begin
+ if not is_special_array(paradef) then
+ paralen := paradef.size
+ else
+ paralen := tcgsize2size[def_cgsize(paradef)];
+ if (target_info.abi = abi_powerpc_aix) and
+ (paradef.typ = recorddef) and
+ (hp.varspez in [vs_value,vs_const]) then
+ begin
+ { if a record has only one field and that field is }
+ { non-composite (not array or record), it must be }
+ { passed according to the rules of that type. }
+ if tabstractrecordsymtable(tabstractrecorddef(paradef).symtable).has_single_field(sym) and
+ ((sym.vardef.typ=floatdef) or
+ ((target_info.system=system_powerpc_darwin) and
+ (sym.vardef.typ in [orddef,enumdef]))) then
+ begin
+ paradef:=sym.vardef;
+ paracgsize:=def_cgsize(paradef);
+ end
+ else
+ begin
+ paracgsize := int_cgsize(paralen);
+ end;
+ end
+ else
+ begin
+ paracgsize:=def_cgsize(paradef);
+ { for things like formaldef }
+ if (paracgsize=OS_NO) then
+ begin
+ paracgsize:=OS_ADDR;
+ paralen := tcgsize2size[OS_ADDR];
+ end;
+ end
+ end;
+
+ loc := getparaloc(paradef);
+ if varargsparas and
+ (target_info.abi = abi_powerpc_aix) and
+ (paradef.typ = floatdef) then
+ begin
+ loc := LOC_REGISTER;
+ if paracgsize = OS_F64 then
+ paracgsize := OS_64
+ else
+ paracgsize := OS_32;
+ end;
+
+ hp.paraloc[side].alignment:=std_param_align;
+ hp.paraloc[side].size:=paracgsize;
+ hp.paraloc[side].intsize:=paralen;
+ if (target_info.abi = abi_powerpc_aix) and
+ (paradef.typ in [recorddef,arraydef]) then
+ hp.paraloc[side].composite:=true;
+{$ifndef cpu64bitaddr}
+ if (target_info.abi=abi_powerpc_sysv) and
+ is_64bit(paradef) and
+ odd(nextintreg-RS_R3) then
+ inc(nextintreg);
+{$endif not cpu64bitaddr}
+ if (paralen = 0) then
+ if (paradef.typ = recorddef) then
+ begin
+ paraloc:=hp.paraloc[side].add_location;
+ paraloc^.loc := LOC_VOID;
+ end
+ else
+ internalerror(2005011310);
+ { can become < 0 for e.g. 3-byte records }
+ while (paralen > 0) do
+ begin
+ paraloc:=hp.paraloc[side].add_location;
+ { In case of po_delphi_nested_cc, the parent frame pointer
+ is always passed on the stack. }
+ if (loc = LOC_REGISTER) and
+ (nextintreg <= RS_R10) and
+ (not(vo_is_parentfp in hp.varoptions) or
+ not(po_delphi_nested_cc in p.procoptions)) then
+ begin
+ paraloc^.loc := loc;
+ { make sure we don't lose whether or not the type is signed }
+ if (paradef.typ <> orddef) then
+ paracgsize := int_cgsize(paralen);
+ if (paracgsize in [OS_NO,OS_64,OS_S64,OS_128,OS_S128]) then
+ paraloc^.size := OS_INT
+ else
+ paraloc^.size := paracgsize;
+ paraloc^.register:=newreg(R_INTREGISTER,nextintreg,R_SUBNONE);
+ inc(nextintreg);
+ dec(paralen,tcgsize2size[paraloc^.size]);
+ if target_info.abi=abi_powerpc_aix then
+ inc(stack_offset,align(tcgsize2size[paraloc^.size],4));
+ end
+ else if (loc = LOC_FPUREGISTER) and
+ (nextfloatreg <= maxfpureg) then
+ begin
+ paraloc^.loc:=loc;
+ paraloc^.size := paracgsize;
+ paraloc^.register:=newreg(R_FPUREGISTER,nextfloatreg,R_SUBWHOLE);
+ inc(nextfloatreg);
+ dec(paralen,tcgsize2size[paraloc^.size]);
+ { if nextfpureg > maxfpureg, all intregs are already used, since there }
+ { are less of those available for parameter passing in the AIX abi }
+ if target_info.abi=abi_powerpc_aix then
+{$ifndef cpu64bitaddr}
+ if (paracgsize = OS_F32) then
+ begin
+ inc(stack_offset,4);
+ if (nextintreg < RS_R11) then
+ inc(nextintreg);
+ end
+ else
+ begin
+ inc(stack_offset,8);
+ if (nextintreg < RS_R10) then
+ inc(nextintreg,2)
+ else
+ nextintreg := RS_R11;
+ end;
+{$else not cpu64bitaddr}
+ begin
+ inc(stack_offset,tcgsize2size[paracgsize]);
+ if (nextintreg < RS_R11) then
+ inc(nextintreg);
+ end;
+{$endif not cpu64bitaddr}
+ end
+ else { LOC_REFERENCE }
+ begin
+ paraloc^.loc:=LOC_REFERENCE;
+ case loc of
+ LOC_FPUREGISTER:
+ paraloc^.size:=int_float_cgsize(paralen);
+ LOC_REGISTER,
+ LOC_REFERENCE:
+ paraloc^.size:=int_cgsize(paralen);
+ else
+ internalerror(2006011101);
+ end;
+ if (side = callerside) then
+ paraloc^.reference.index:=NR_STACK_POINTER_REG
+ else
+ begin
+ paraloc^.reference.index:=NR_R12;
+ tppcprocinfo(current_procinfo).needs_frame_pointer := true;
+ end;
+
+ if (target_info.abi = abi_powerpc_aix) and
+ (hp.paraloc[side].intsize < 3) then
+ paraloc^.reference.offset:=stack_offset+(4-paralen)
+ else
+ paraloc^.reference.offset:=stack_offset;
+
+ inc(stack_offset,align(paralen,4));
+ while (paralen > 0) and
+ (nextintreg < RS_R11) do
+ begin
+ inc(nextintreg);
+ dec(paralen,sizeof(pint));
+ end;
+ paralen := 0;
+ end;
+ end;
+ end;
+ curintreg:=nextintreg;
+ curfloatreg:=nextfloatreg;
+ curmmreg:=nextmmreg;
+ cur_stack_offset:=stack_offset;
+ result:=stack_offset;
+ end;
+
+
+ function tppcparamanager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;
+ var
+ cur_stack_offset: aword;
+ parasize, l: longint;
+ curintreg, firstfloatreg, curfloatreg, curmmreg: tsuperregister;
+ i : integer;
+ hp: tparavarsym;
+ paraloc: pcgparalocation;
+ begin
+ init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset);
+ firstfloatreg:=curfloatreg;
+
+ result:=create_paraloc_info_intern(p,callerside,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset, false);
+ if (p.proccalloption in [pocall_cdecl,pocall_cppdecl,pocall_mwpascal]) then
+ { just continue loading the parameters in the registers }
+ begin
+ result:=create_paraloc_info_intern(p,callerside,varargspara,curintreg,curfloatreg,curmmreg,cur_stack_offset,true);
+ { varargs routines have to reserve at least 32 bytes for the AIX abi }
+ if (target_info.abi = abi_powerpc_aix) and
+ (result < 32) then
+ result := 32;
+ end
+ else
+ begin
+ parasize:=cur_stack_offset;
+ for i:=0 to varargspara.count-1 do
+ begin
+ hp:=tparavarsym(varargspara[i]);
+ hp.paraloc[callerside].alignment:=4;
+ paraloc:=hp.paraloc[callerside].add_location;
+ paraloc^.loc:=LOC_REFERENCE;
+ paraloc^.size:=def_cgsize(hp.vardef);
+ paraloc^.reference.index:=NR_STACK_POINTER_REG;
+ l:=push_size(hp.varspez,hp.vardef,p.proccalloption);
+ paraloc^.reference.offset:=parasize;
+ parasize:=parasize+l;
+ end;
+ result:=parasize;
+ end;
+ if curfloatreg<>firstfloatreg then
+ include(varargspara.varargsinfo,va_uses_float_reg);
+ end;
+
+
+ function tppcparamanager.parseparaloc(p : tparavarsym;const s : string) : boolean;
+ var
+ paraloc : pcgparalocation;
+ paracgsize : tcgsize;
+ begin
+ result:=false;
+ case target_info.system of
+ system_powerpc_morphos:
+ begin
+ paracgsize:=def_cgsize(p.vardef);
+ p.paraloc[callerside].alignment:=4;
+ p.paraloc[callerside].size:=paracgsize;
+ p.paraloc[callerside].intsize:=tcgsize2size[paracgsize];
+ paraloc:=p.paraloc[callerside].add_location;
+ paraloc^.loc:=LOC_REFERENCE;
+ paraloc^.size:=paracgsize;
+ paraloc^.reference.index:=newreg(R_INTREGISTER,RS_R2,R_SUBWHOLE);
+ { pattern is always uppercase'd }
+ if s='D0' then
+ paraloc^.reference.offset:=0
+ else if s='D1' then
+ paraloc^.reference.offset:=4
+ else if s='D2' then
+ paraloc^.reference.offset:=8
+ else if s='D3' then
+ paraloc^.reference.offset:=12
+ else if s='D4' then
+ paraloc^.reference.offset:=16
+ else if s='D5' then
+ paraloc^.reference.offset:=20
+ else if s='D6' then
+ paraloc^.reference.offset:=24
+ else if s='D7' then
+ paraloc^.reference.offset:=28
+ else if s='A0' then
+ paraloc^.reference.offset:=32
+ else if s='A1' then
+ paraloc^.reference.offset:=36
+ else if s='A2' then
+ paraloc^.reference.offset:=40
+ else if s='A3' then
+ paraloc^.reference.offset:=44
+ else if s='A4' then
+ paraloc^.reference.offset:=48
+ else if s='A5' then
+ paraloc^.reference.offset:=52
+ { 'A6' (offset 56) is used by mossyscall as libbase, so API
+ never passes parameters in it,
+ Indeed, but this allows to declare libbase either explicitly
+ or let the compiler insert it }
+ else if s='A6' then
+ paraloc^.reference.offset:=56
+ { 'A7' is the stack pointer on 68k, can't be overwritten
+ by API calls, so it has no offset }
+ { 'R12' is special, used internally to support r12base sysv
+ calling convention }
+ else if s='R12' then
+ begin
+ paraloc^.loc:=LOC_REGISTER;
+ paraloc^.size:=OS_ADDR;
+ paraloc^.register:=NR_R12;
+ end
+ else
+ exit;
+
+ { copy to callee side }
+ p.paraloc[calleeside].add_location^:=paraloc^;
+ end;
+ else
+ internalerror(200404182);
+ end;
+ result:=true;
+ end;
+
+begin
+ paramanager:=tppcparamanager.create;
+end.
diff --git a/closures/compiler/powerpc/cpupi.pas b/closures/compiler/powerpc/cpupi.pas
new file mode 100644
index 0000000000..3efec0189a
--- /dev/null
+++ b/closures/compiler/powerpc/cpupi.pas
@@ -0,0 +1,207 @@
+{
+ Copyright (c) 2002 by Florian Klaempfl
+
+ This unit contains the CPU specific part of tprocinfo
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+
+{ This unit contains the CPU specific part of tprocinfo. }
+unit cpupi;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ cutils,globtype,
+ cgbase,aasmdata,
+ procinfo,cpuinfo,psub;
+
+ type
+ tppcprocinfo = class(tcgprocinfo)
+ needstackframe: boolean;
+
+ { offset where the frame pointer from the outer procedure is stored. }
+ parent_framepointer_offset : longint;
+ constructor create(aparent:tprocinfo);override;
+ procedure set_first_temp_offset;override;
+ function calc_stackframe_size:longint;override;
+
+ function uses_stack_temps: boolean;
+ procedure allocate_got_register(list: TAsmList);override;
+ private
+ first_save_int_reg, first_save_fpu_reg: tsuperregister;
+ public
+ needs_frame_pointer: boolean;
+
+ property get_first_save_int_reg: tsuperregister read first_save_int_reg;
+ property get_first_save_fpu_reg: tsuperregister read first_save_fpu_reg;
+
+ end;
+
+
+ implementation
+
+ uses
+ globals,systems,
+ cpubase,
+ aasmtai,
+ tgobj,cgobj,
+ symconst,symsym,paramgr,symutil,symtable,
+ verbose;
+
+ constructor tppcprocinfo.create(aparent:tprocinfo);
+
+ begin
+ inherited create(aparent);
+ first_save_int_reg:=32;
+ first_save_fpu_reg:=32;
+ needs_frame_pointer:=false;
+ end;
+
+
+ procedure tppcprocinfo.set_first_temp_offset;
+ var
+ ofs : aword;
+ begin
+ if not(po_assembler in procdef.procoptions) then
+ begin
+ case target_info.abi of
+ abi_powerpc_aix:
+ ofs:=maxpushedparasize+LinkageAreaSizeAIX;
+ abi_powerpc_sysv:
+ ofs:=maxpushedparasize+LinkageAreaSizeSYSV;
+ else
+ internalerror(200402191);
+ end;
+ tg.setfirsttemp(ofs);
+ end
+ else
+ begin
+ if (current_procinfo.procdef.localst.symtabletype=localsymtable) and
+ (tabstractlocalsymtable(current_procinfo.procdef.localst).count_locals <> 0) then
+ begin
+ { at 0(r1), the previous value of r1 will be stored }
+ tg.setfirsttemp(4);
+ end
+ end;
+ end;
+
+
+(*
+ procedure tppcprocinfo.after_pass1;
+ begin
+ if not(po_assembler in procdef.procoptions) then
+ begin
+ if cs_asm_source in current_settings.globalswitches then
+ aktproccode.insert(Tai_comment.Create(strpnew('Parameter copies start at: r1+'+tostr(procdef.parast.address_fixup))));
+
+ if cs_asm_source in current_settings.globalswitches then
+ aktproccode.insert(Tai_comment.Create(strpnew('Locals start at: r1+'+tostr(procdef.localst.address_fixup))));
+ firsttemp_offset:=align(procdef.localst.address_fixup+procdef.localst.datasize,16);
+ if cs_asm_source in current_settings.globalswitches then
+ aktproccode.insert(Tai_comment.Create(strpnew('Temp. space start: r1+'+tostr(firsttemp_offset))));
+
+ //!!!! tg.setfirsttemp(firsttemp_offset);
+ tg.firsttemp:=firsttemp_offset;
+ tg.lasttemp:=firsttemp_offset;
+ inherited after_pass1;
+ end;
+ end;
+*)
+
+
+ function tppcprocinfo.uses_stack_temps: boolean;
+ begin
+ result := tg.firsttemp <> tg.lasttemp;
+ end;
+
+
+ function tppcprocinfo.calc_stackframe_size:longint;
+ var
+ low_nonvol_fpu_reg, regcounter: tsuperregister;
+ begin
+ if not (po_assembler in procdef.procoptions) then
+ begin
+ first_save_fpu_reg := 32;
+ first_save_int_reg := 32;
+ { FIXME: has to be R_F14 instead of R_F8 for SYSV-64bit }
+ case target_info.abi of
+ abi_powerpc_aix:
+ low_nonvol_fpu_reg := RS_F14;
+ abi_powerpc_sysv:
+ low_nonvol_fpu_reg := RS_F14;
+ else
+ internalerror(2003122903);
+ end;
+ for regcounter := low_nonvol_fpu_reg to RS_F31 do
+ begin
+ if regcounter in cg.rg[R_FPUREGISTER].used_in_proc then
+ begin
+ first_save_fpu_reg := ord(regcounter) - ord(RS_F0);
+ break;
+ end;
+ end;
+ for regcounter := RS_R13 to RS_R31 do
+ begin
+ if regcounter in cg.rg[R_INTREGISTER].used_in_proc then
+ begin
+ first_save_int_reg := ord(regcounter) - ord(RS_R0);
+ break;
+ end;
+ end;
+ if not(pi_do_call in flags) and
+ (not uses_stack_temps) and
+ (((target_info.abi = abi_powerpc_aix) and
+ ((32-first_save_int_reg)*4+(32-first_save_fpu_reg)*8 <= 220)) or
+ ((target_info.abi = abi_powerpc_sysv) and
+ (first_save_int_reg + first_save_fpu_reg = 64))) then
+ begin
+ { don't allocate a stack frame }
+ result := (32-first_save_int_reg)*4+(32-first_save_fpu_reg)*8;
+ needstackframe := false;
+ end
+ else
+ begin
+ result := (32-first_save_int_reg)*4+(32-first_save_fpu_reg)*8+tg.lasttemp;
+ result := align(result,16);
+ needstackframe := result<>0;
+ end;
+ end
+ else
+ begin
+ result := align(tg.lasttemp,16);
+ needstackframe := result<>0;
+ end;
+ end;
+
+
+ procedure tppcprocinfo.allocate_got_register(list: TAsmList);
+ begin
+ if (target_info.system = system_powerpc_darwin) and
+ (cs_create_pic in current_settings.moduleswitches) then
+ begin
+ got := cg.getaddressregister(list);
+ end;
+ end;
+
+
+begin
+ cprocinfo:=tppcprocinfo;
+end.
+
diff --git a/closures/compiler/powerpc/cputarg.pas b/closures/compiler/powerpc/cputarg.pas
new file mode 100644
index 0000000000..d96634fc23
--- /dev/null
+++ b/closures/compiler/powerpc/cputarg.pas
@@ -0,0 +1,99 @@
+{
+ Copyright (c) 2001-2002 by Peter Vreman
+
+ Includes the powerpc dependent target units
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit cputarg;
+
+{$i fpcdefs.inc}
+
+interface
+
+
+implementation
+
+ uses
+ systems { prevent a syntax error when nothing is included }
+
+{**************************************
+ Targets
+**************************************}
+
+ {$ifndef NOTARGETLINUX}
+ ,t_linux
+ {$endif}
+ {$ifndef NOTARGETMACOS}
+ ,t_macos
+ {$endif}
+ {$ifndef NOTARGETDARWIN}
+ ,t_bsd
+ {$endif}
+ {$ifndef NOTARGETMORPHOS}
+ ,t_morph
+ {$endif}
+ {$ifndef NOTARGETAMIGA}
+ ,t_amiga
+ {$endif}
+ {$ifndef NOTARGETWII}
+ ,t_wii
+ {$endif}
+
+{**************************************
+ Assemblers
+**************************************}
+
+ {$ifndef NOAGPPCGAS}
+ ,agppcgas
+ {$endif}
+ {$ifndef NOAGPPPCMPW}
+ ,agppcmpw
+ {$endif}
+ {$ifndef NOAGPPCVASM}
+ ,agppcvasm
+ {$endif}
+
+{**************************************
+ Assembler Readers
+**************************************}
+
+ {$ifndef NoRaPPCGas}
+ ,rappcgas
+ {$endif NoRaPPCGas}
+
+{**************************************
+ Debuginfo
+**************************************}
+
+ {$ifndef NoDbgStabs}
+ ,dbgstabs
+ {$endif NoDbgStabs}
+ {$ifndef NoDbgDwarf}
+ ,dbgdwarf
+ {$endif NoDbgDwarf}
+
+{**************************************
+ Optimizer
+**************************************}
+
+ {$ifndef NOOPT}
+ , aoptcpu
+ {$endif NOOPT}
+ ;
+
+end.
diff --git a/closures/compiler/powerpc/itcpugas.pas b/closures/compiler/powerpc/itcpugas.pas
new file mode 100644
index 0000000000..31ff05fdc0
--- /dev/null
+++ b/closures/compiler/powerpc/itcpugas.pas
@@ -0,0 +1,151 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit contains the PowerPC GAS instruction tables
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit itcpugas;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cpubase,cgbase;
+
+ const
+ gas_op2str : array[tasmop] of string[14] = ('<none>',
+ 'add','add.','addo','addo.','addc','addc.','addco','addco.',
+ 'adde','adde.','addeo','addeo.','addi','addic','addic.','addis',
+ 'addme','addme.','addmeo','addmeo.','addze','addze.','addzeo',
+ 'addzeo.','and','and.','andc','andc.','andi.','andis.','b',
+ 'ba','bl','bla','bc','bca','bcl','bcla','bcctr','bcctrl','bclr',
+ 'bclrl','cmp','cmpi','cmpl','cmpli','cntlzw','cntlzw.','crand',
+ 'crandc','creqv','crnand','crnor','cror','crorc','crxor','dcba',
+ 'dcbf','dcbi','dcbst','dcbt','dcbtst','dcbz','divw','divw.','divwo','divwo.',
+ 'divwu','divwu.','divwuo','divwuo.','eciwx','ecowx','eieio','eqv',
+ 'eqv.','extsb','extsb.','extsh','extsh.','fabs','fabs.','fadd',
+ 'fadd.','fadds','fadds.','fcmpo','fcmpu','fctid','fctid.','fctidz',
+ 'fctidz.','fctiw','fctiw.','fctiwz',
+ 'fctiwz.','fdiv','fdiv.','fdivs','fdivs.','fmadd','fmadd.','fmadds',
+ 'fmadds.','fmr','fmsub','fmsub.','fmsubs','fmsubs.','fmul','fmul.',
+ 'fmuls','fmuls.','fnabs','fnabs.','fneg','fneg.','fnmadd',
+ 'fnmadd.','fnmadds','fnmadds.','fnmsub','fnmsub.','fnmsubs',
+ 'fnmsubs.','fres','fres.','frsp','frsp.','frsqrte','frsqrte.',
+ 'fsel','fsel.','fsqrt','fsqrt.','fsqrts','fsqrts.','fsub','fsub.',
+ 'fsubs','fsubs.','icbi','isync','lbz','lbzu','lbzux','lbzx',
+ 'lfd','lfdu','lfdux','lfdx','lfs','lfsu','lfsux','lfsx','lha',
+ 'lhau','lhaux','lhax','lhbrx','lhz','lhzu','lhzux','lhzx','lmw',
+ 'lswi','lswx','lwarx','lwbrx','lwz','lwzu','lwzux','lwzx','mcrf',
+ 'mcrfs','mcrxr','mfcr','mffs','mffs.','mfmsr','mfspr','mfsr',
+ 'mfsrin','mftb','mtcrf','mtfsb0','mtfsb1','mtfsf','mtfsf.',
+ 'mtfsfi','mtfsfi.','mtmsr','mtspr','mtsr','mtsrin','mulhw',
+ 'mulhw.','mulhwu','mulhwu.','mulli','mullw','mullw.','mullwo',
+ 'mullwo.','nand','nand.','neg','neg.','nego','nego.','nor','nor.',
+ 'or','or.','orc','orc.','ori','oris', 'rfi', 'rlwimi', 'rlwimi.',
+ 'rlwinm', 'rlwinm.','rlwnm','rlwnm.','sc','slw', 'slw.', 'sraw', 'sraw.',
+ 'srawi', 'srawi.','srw', 'srw.', 'stb', 'stbu', 'stbux','stbx','stfd',
+ 'stfdu', 'stfdux', 'stfdx', 'stfiwx', 'stfs', 'stfsu', 'stfsux', 'stfsx',
+ 'sth', 'sthbrx', 'sthu', 'sthux', 'sthx', 'stmw', 'stswi', 'stswx', 'stw',
+ 'stwbrx', 'stwcx.', 'stwu', 'stwux', 'stwx', 'subf', 'subf.', 'subfo',
+ 'subfo.', 'subfc', 'subc.', 'subfco', 'subfco.', 'subfe', 'subfe.',
+ 'subfeo', 'subfeo.', 'subfic', 'subfme', 'subfme.', 'subfmeo', 'subfmeo.',
+ 'subfze', 'subfze.', 'subfzeo', 'subfzeo.', 'sync', 'tlbia', 'tlbie',
+ 'tlbsync', 'tw', 'twi', 'xor', 'xor.', 'xori', 'xoris',
+ { some simplified mnemonics }
+ 'subi', 'subis', 'subic', 'subic.', 'sub', 'sub.', 'subo', 'subo.',
+ 'subc', 'subc.', 'subco', 'subco.', 'cmpwi', 'cmpw', 'cmplwi', 'cmplw',
+ 'extlwi', 'extlwi.', 'extrwi', 'extrwi.', 'inslwi', 'inslwi.', 'insrwi',
+ 'insrwi.', 'rotlwi', 'rotlwi.', 'rotlw', 'rotlw.', 'slwi', 'slwi.',
+ 'srwi', 'srwi.', 'clrlwi', 'clrlwi.', 'clrrwi', 'clrrwi.', 'clrslwi',
+ 'clrslwi.', 'blr', 'bctr', 'blrl', 'bctrl', 'crset', 'crclr', 'crmove',
+ 'crnot', 'mt', 'mf','nop', 'li', 'lis', 'la', 'mr','mr.','not', 'not.',
+ 'mtcr', 'mtlr', 'mflr','mtctr', 'mfctr', 'mftbu', 'mfxer');
+
+ function gas_regnum_search(const s:string):Tregister;
+ function gas_regname(r:Tregister):string;
+
+
+implementation
+
+ uses
+ globtype,globals,aasmbase,
+ cutils,verbose, systems;
+
+ const
+ gas_regname_table : array[tregisterindex] of string[7] = (
+ {$i rppcgas.inc}
+ );
+
+ gas_regname_short_table : array[tregisterindex] of string[7] = (
+ {$i rppcgss.inc}
+ );
+
+ gas_regname_index : array[tregisterindex] of tregisterindex = (
+ {$i rppcgri.inc}
+ );
+
+
+ function findreg_by_gasname(const s:string):tregisterindex;
+ var
+ i,p : tregisterindex;
+ begin
+ {Binary search.}
+ p:=0;
+ i:=regnumber_count_bsstart;
+ repeat
+ if (p+i<=high(tregisterindex)) and (gas_regname_table[gas_regname_index[p+i]]<=s) then
+ p:=p+i;
+ i:=i shr 1;
+ until i=0;
+ if gas_regname_table[gas_regname_index[p]]=s then
+ findreg_by_gasname:=gas_regname_index[p]
+ else
+ findreg_by_gasname:=0;
+ end;
+
+
+ function gas_regnum_search(const s:string):Tregister;
+ begin
+ result:=regnumber_table[findreg_by_gasname(s)];
+ end;
+
+
+ function gas_regname(r:Tregister):string;
+ var
+ p : longint;
+ begin
+ p:=findreg_by_number(r);
+ if p<>0 then
+ {The GNU assembler only accepts numbers and no full register names (at least in older versions). To
+ make the assembler code more readable, we define macros at the start of all assembler files we write
+ to redefine r1..r31 and f1..f31 to 1..31, and then use the full register names.
+
+ However, we do not do this for smart linked files since that would cause a lot of (mostly useless)
+ overhead. In theory, we could also not do it if "-a" is not used. The Mac OS X assembler (which is
+ based on GNU as) "natively" supports full register names.}
+ if create_smartlink_library and
+ (target_info.system <> system_powerpc_darwin) then
+ result:=gas_regname_short_table[p]
+ else
+ result:=gas_regname_table[p]
+ else
+ result:=generic_regname(r);
+ end;
+
+end.
diff --git a/closures/compiler/powerpc/nppcadd.pas b/closures/compiler/powerpc/nppcadd.pas
new file mode 100644
index 0000000000..f72f6cf767
--- /dev/null
+++ b/closures/compiler/powerpc/nppcadd.pas
@@ -0,0 +1,965 @@
+{
+ Copyright (c) 2000-2002 by Florian Klaempfl and Jonas Maebe
+
+ Code generation for add nodes on the PowerPC
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit nppcadd;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,nadd,ncgadd,ngppcadd,cpubase;
+
+ type
+ tppcaddnode = class(tgenppcaddnode)
+ procedure pass_generate_code;override;
+ protected
+ function use_generic_mul32to64: boolean; override;
+ private
+ procedure emit_compare(unsigned : boolean); override;
+{$ifdef SUPPORT_MMX}
+ procedure second_addmmx;override;
+{$endif SUPPORT_MMX}
+ procedure second_add64bit;override;
+ end;
+
+ implementation
+
+ uses
+ globtype,systems,
+ cutils,verbose,globals,
+ symconst,symdef,paramgr,
+ aasmbase,aasmtai,aasmdata,aasmcpu,defutil,htypechk,
+ cgbase,cpuinfo,pass_1,pass_2,regvars,
+ cpupara,cgcpu,cgutils,procinfo,
+ ncon,nset,
+ ncgutil,tgobj,rgobj,rgcpu,cgobj,cg64f32;
+
+
+{*****************************************************************************
+ Pass 1
+*****************************************************************************}
+
+ function tppcaddnode.use_generic_mul32to64: boolean;
+ begin
+ result := false;
+ end;
+
+{*****************************************************************************
+ Helpers
+*****************************************************************************}
+
+ procedure tppcaddnode.emit_compare(unsigned: boolean);
+ var
+ op : tasmop;
+ tmpreg : tregister;
+ useconst : boolean;
+ begin
+ // get the constant on the right if there is one
+ if (left.location.loc = LOC_CONSTANT) then
+ swapleftright;
+ // can we use an immediate, or do we have to load the
+ // constant in a register first?
+ if (right.location.loc = LOC_CONSTANT) then
+ begin
+{$ifdef dummy}
+ if (right.location.size in [OS_64,OS_S64]) and (hi(right.location.value64)<>0) and ((hi(right.location.value64)<>$ffffffff) or unsigned) then
+ internalerror(2002080301);
+{$endif extdebug}
+ if (nodetype in [equaln,unequaln]) then
+ if (unsigned and
+ (aword(right.location.value) > high(word))) or
+ (not unsigned and
+ (aint(right.location.value) < low(smallint)) or
+ (aint(right.location.value) > high(smallint))) then
+ { we can then maybe use a constant in the 'othersigned' case
+ (the sign doesn't matter for // equal/unequal)}
+ unsigned := not unsigned;
+
+ if (unsigned and
+ (aword(right.location.value) <= high(word))) or
+ (not(unsigned) and
+ (aint(right.location.value) >= low(smallint)) and
+ (aint(right.location.value) <= high(smallint))) then
+ useconst := true
+ else
+ begin
+ useconst := false;
+ tmpreg := cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+ cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_INT,
+ right.location.value,tmpreg);
+ end
+ end
+ else
+ useconst := false;
+ location.loc := LOC_FLAGS;
+ location.resflags := getresflags;
+ if not unsigned then
+ if useconst then
+ op := A_CMPWI
+ else
+ op := A_CMPW
+ else
+ if useconst then
+ op := A_CMPLWI
+ else
+ op := A_CMPLW;
+
+ if (right.location.loc = LOC_CONSTANT) then
+ begin
+ if useconst then
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(op,left.location.register,longint(right.location.value)))
+ else
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op,left.location.register,tmpreg));
+ end
+ else
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op,
+ left.location.register,right.location.register));
+ end;
+
+
+{*****************************************************************************
+ Add64bit
+*****************************************************************************}
+
+ procedure tppcaddnode.second_add64bit;
+ var
+ op : TOpCG;
+ op1,op2 : TAsmOp;
+ cmpop,
+ unsigned : boolean;
+
+
+ procedure emit_cmp64_hi;
+
+ var
+ oldleft, oldright: tlocation;
+ begin
+ // put the high part of the location in the low part
+ location_copy(oldleft,left.location);
+ location_copy(oldright,right.location);
+ if left.location.loc = LOC_CONSTANT then
+ left.location.value64 := left.location.value64 shr 32
+ else
+ left.location.register64.reglo := left.location.register64.reghi;
+ if right.location.loc = LOC_CONSTANT then
+ right.location.value64 := right.location.value64 shr 32
+ else
+ right.location.register64.reglo := right.location.register64.reghi;
+
+ // and call the normal emit_compare
+ emit_compare(unsigned);
+ location_copy(left.location,oldleft);
+ location_copy(right.location,oldright);
+ end;
+
+
+ procedure emit_cmp64_lo;
+
+ begin
+ emit_compare(true);
+ end;
+
+
+ procedure firstjmp64bitcmp;
+
+ var
+ oldnodetype: tnodetype;
+ begin
+{$ifdef OLDREGVARS}
+ load_all_regvars(current_asmdata.CurrAsmList);
+{$endif OLDREGVARS}
+ { the jump the sequence is a little bit hairy }
+ case nodetype of
+ ltn,gtn:
+ begin
+ cg.a_jmp_flags(current_asmdata.CurrAsmList,getresflags,current_procinfo.CurrTrueLabel);
+ { cheat a little bit for the negative test }
+ toggleflag(nf_swapped);
+ cg.a_jmp_flags(current_asmdata.CurrAsmList,getresflags,current_procinfo.CurrFalseLabel);
+ toggleflag(nf_swapped);
+ end;
+ lten,gten:
+ begin
+ oldnodetype:=nodetype;
+ if nodetype=lten then
+ nodetype:=ltn
+ else
+ nodetype:=gtn;
+ cg.a_jmp_flags(current_asmdata.CurrAsmList,getresflags,current_procinfo.CurrTrueLabel);
+ { cheat for the negative test }
+ if nodetype=ltn then
+ nodetype:=gtn
+ else
+ nodetype:=ltn;
+ cg.a_jmp_flags(current_asmdata.CurrAsmList,getresflags,current_procinfo.CurrFalseLabel);
+ nodetype:=oldnodetype;
+ end;
+ equaln:
+ begin
+ nodetype := unequaln;
+ cg.a_jmp_flags(current_asmdata.CurrAsmList,getresflags,current_procinfo.CurrFalseLabel);
+ nodetype := equaln;
+ end;
+ unequaln:
+ begin
+ cg.a_jmp_flags(current_asmdata.CurrAsmList,getresflags,current_procinfo.CurrTrueLabel);
+ end;
+ end;
+ end;
+
+
+ procedure secondjmp64bitcmp;
+
+ begin
+ { the jump the sequence is a little bit hairy }
+ case nodetype of
+ ltn,gtn,lten,gten:
+ begin
+ { the comparison of the low dword always has }
+ { to be always unsigned! }
+ cg.a_jmp_flags(current_asmdata.CurrAsmList,getresflags,current_procinfo.CurrTrueLabel);
+ cg.a_jmp_always(current_asmdata.CurrAsmList,current_procinfo.CurrFalseLabel);
+ end;
+ equaln:
+ begin
+ nodetype := unequaln;
+ cg.a_jmp_flags(current_asmdata.CurrAsmList,getresflags,current_procinfo.CurrFalseLabel);
+ cg.a_jmp_always(current_asmdata.CurrAsmList,current_procinfo.CurrTrueLabel);
+ nodetype := equaln;
+ end;
+ unequaln:
+ begin
+ cg.a_jmp_flags(current_asmdata.CurrAsmList,getresflags,current_procinfo.CurrTrueLabel);
+ cg.a_jmp_always(current_asmdata.CurrAsmList,current_procinfo.CurrFalseLabel);
+ end;
+ end;
+ end;
+
+
+ var
+ tempreg64: tregister64;
+
+ begin
+ firstcomplex(self);
+
+ pass_left_and_right;
+
+ cmpop:=false;
+ unsigned:=((left.resultdef.typ=orddef) and
+ (torddef(left.resultdef).ordtype=u64bit)) or
+ ((right.resultdef.typ=orddef) and
+ (torddef(right.resultdef).ordtype=u64bit));
+ case nodetype of
+ addn :
+ begin
+ op:=OP_ADD;
+ end;
+ subn :
+ begin
+ op:=OP_SUB;
+ if (nf_swapped in flags) then
+ swapleftright;
+ end;
+ ltn,lten,
+ gtn,gten,
+ equaln,unequaln:
+ begin
+ op:=OP_NONE;
+ cmpop:=true;
+ end;
+ xorn:
+ op:=OP_XOR;
+ orn:
+ op:=OP_OR;
+ andn:
+ op:=OP_AND;
+ muln:
+ begin
+ { should be handled in pass_1 (JM) }
+ if not(torddef(left.resultdef).ordtype in [U32bit,s32bit]) or
+ (torddef(left.resultdef).typ <> torddef(right.resultdef).typ) then
+ internalerror(200109051);
+ { handled separately }
+ op := OP_NONE;
+ end;
+ else
+ internalerror(2002072705);
+ end;
+
+ if not cmpop then
+ location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
+
+ load_left_right(cmpop,((cs_check_overflow in current_settings.localswitches) and
+ (nodetype in [addn,subn])) or (nodetype = muln));
+
+ if (nodetype <> muln) and
+ (not(cs_check_overflow in current_settings.localswitches) or
+ not(nodetype in [addn,subn])) then
+ begin
+ case nodetype of
+ ltn,lten,
+ gtn,gten:
+ begin
+ emit_cmp64_hi;
+ firstjmp64bitcmp;
+ emit_cmp64_lo;
+ secondjmp64bitcmp;
+ end;
+ equaln,unequaln:
+ begin
+ // instead of doing a complicated compare, do
+ // (left.hi xor right.hi) or (left.lo xor right.lo)
+ // (somewhate optimized so that no superfluous 'mr's are
+ // generated)
+ if (left.location.loc = LOC_CONSTANT) then
+ swapleftright;
+ if (right.location.loc = LOC_CONSTANT) then
+ begin
+ if left.location.loc = LOC_REGISTER then
+ begin
+ tempreg64.reglo := left.location.register64.reglo;
+ tempreg64.reghi := left.location.register64.reghi;
+ end
+ else
+ begin
+ if (aint(right.location.value64) <> 0) then
+ tempreg64.reglo := cg.getintregister(current_asmdata.CurrAsmList,OS_32)
+ else
+ tempreg64.reglo := left.location.register64.reglo;
+ if ((right.location.value64 shr 32) <> 0) then
+ tempreg64.reghi := cg.getintregister(current_asmdata.CurrAsmList,OS_32)
+ else
+ tempreg64.reghi := left.location.register64.reghi;
+ end;
+
+ if (aint(right.location.value64) <> 0) then
+ { negative values can be handled using SUB, }
+ { positive values < 65535 using XOR. }
+ if (longint(right.location.value64) >= -32767) and
+ (longint(right.location.value64) < 0) then
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SUB,OS_INT,
+ aint(right.location.value64),
+ left.location.register64.reglo,tempreg64.reglo)
+ else
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_XOR,OS_INT,
+ aint(right.location.value64),
+ left.location.register64.reglo,tempreg64.reglo);
+
+ if ((right.location.value64 shr 32) <> 0) then
+ if (longint(right.location.value64 shr 32) >= -32767) and
+ (longint(right.location.value64 shr 32) < 0) then
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SUB,OS_INT,
+ aint(right.location.value64 shr 32),
+ left.location.register64.reghi,tempreg64.reghi)
+ else
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_XOR,OS_INT,
+ aint(right.location.value64 shr 32),
+ left.location.register64.reghi,tempreg64.reghi);
+ end
+ else
+ begin
+ tempreg64.reglo := cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+ tempreg64.reghi := cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+ cg64.a_op64_reg_reg_reg(current_asmdata.CurrAsmList,OP_XOR,location.size,
+ left.location.register64,right.location.register64,
+ tempreg64);
+ end;
+
+ cg.a_reg_alloc(current_asmdata.CurrAsmList,NR_R0);
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_OR_,NR_R0,
+ tempreg64.reglo,tempreg64.reghi));
+ cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_R0);
+
+ location_reset(location,LOC_FLAGS,OS_NO);
+ location.resflags := getresflags;
+ end;
+ xorn,orn,andn,addn:
+ begin
+ location.register64.reglo := cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+ location.register64.reghi := cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+
+ if (left.location.loc = LOC_CONSTANT) then
+ swapleftright;
+ if (right.location.loc = LOC_CONSTANT) then
+ cg64.a_op64_const_reg_reg(current_asmdata.CurrAsmList,op,location.size,right.location.value64,
+ left.location.register64,location.register64)
+ else
+ cg64.a_op64_reg_reg_reg(current_asmdata.CurrAsmList,op,location.size,right.location.register64,
+ left.location.register64,location.register64);
+ end;
+ subn:
+ begin
+ location.register64.reglo := cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+ location.register64.reghi := cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+ if left.location.loc <> LOC_CONSTANT then
+ begin
+ if right.location.loc <> LOC_CONSTANT then
+ // reg64 - reg64
+ cg64.a_op64_reg_reg_reg(current_asmdata.CurrAsmList,OP_SUB,location.size,
+ right.location.register64,left.location.register64,
+ location.register64)
+ else
+ // reg64 - const64
+ cg64.a_op64_const_reg_reg(current_asmdata.CurrAsmList,OP_SUB,location.size,
+ right.location.value64,left.location.register64,
+ location.register64)
+ end
+ else if ((left.location.value64 shr 32) = 0) then
+ begin
+ if (int64(left.location.value64) >= low(smallint)) and
+ (int64(left.location.value64) <= high(smallint)) then
+ begin
+ // consts16 - reg64
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_const(A_SUBFIC,
+ location.register64.reglo,right.location.register64.reglo,
+ left.location.value));
+ end
+ else
+ begin
+ // const32 - reg64
+ location_force_reg(current_asmdata.CurrAsmList,left.location,
+ OS_32,true);
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SUBC,
+ location.register64.reglo,left.location.register64.reglo,
+ right.location.register64.reglo));
+ end;
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_SUBFZE,
+ location.register64.reghi,right.location.register64.reghi));
+ end
+ else if (aint(left.location.value64) = 0) then
+ begin
+ // (const32 shl 32) - reg64
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_const(A_SUBFIC,
+ location.register64.reglo,right.location.register64.reglo,0));
+ left.location.value64 := left.location.value64 shr 32;
+ location_force_reg(current_asmdata.CurrAsmList,left.location,OS_32,true);
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SUBFE,
+ location.register64.reghi,right.location.register64.reghi,
+ left.location.register));
+ end
+ else
+ begin
+ // const64 - reg64
+ location_force_reg(current_asmdata.CurrAsmList,left.location,
+ def_cgsize(left.resultdef),false);
+ cg64.a_op64_reg_reg_reg(current_asmdata.CurrAsmList,OP_SUB,location.size,
+ right.location.register64,left.location.register64,
+ location.register64);
+ end;
+ end;
+ else
+ internalerror(2002072803);
+ end;
+ end
+ else
+ begin
+ if is_signed(resultdef) then
+ begin
+ case nodetype of
+ addn:
+ begin
+ op1 := A_ADDC;
+ op2 := A_ADDEO;
+ end;
+ subn:
+ begin
+ op1 := A_SUBC;
+ op2 := A_SUBFEO;
+ end;
+ muln:
+ begin
+ op1 := A_MULLW;
+ op2 := A_MULHW
+ end;
+ else
+ internalerror(2002072806);
+ end
+ end
+ else
+ begin
+ case nodetype of
+ addn:
+ begin
+ op1 := A_ADDC;
+ op2 := A_ADDE;
+ end;
+ subn:
+ begin
+ op1 := A_SUBC;
+ op2 := A_SUBFE;
+ end;
+ muln:
+ begin
+ op1 := A_MULLW;
+ op2 := A_MULHWU
+ end;
+ end;
+ end;
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(op1,location.register64.reglo,
+ left.location.register64.reglo,right.location.register64.reglo));
+
+ if (nodetype <> muln) then
+ begin
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(op2,location.register64.reghi,
+ right.location.register64.reghi,left.location.register64.reghi));
+ if not(is_signed(resultdef)) then
+ if nodetype = addn then
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CMPLW,location.register64.reghi,left.location.register64.reghi))
+ else
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CMPLW,left.location.register64.reghi,location.register64.reghi));
+ cg.g_overflowcheck(current_asmdata.CurrAsmList,location,resultdef);
+ end
+ else
+ begin
+ { 32 * 32 -> 64 cannot overflow }
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(op2,location.register64.reghi,
+ left.location.register64.reglo,right.location.register64.reglo));
+ end
+ end;
+
+ { set result location }
+ { (emit_compare sets it to LOC_FLAGS for compares, so set the }
+ { real location only now) (JM) }
+ if cmpop and
+ not(nodetype in [equaln,unequaln]) then
+ location_reset(location,LOC_JUMP,OS_NO);
+ end;
+
+
+{*****************************************************************************
+ AddMMX
+*****************************************************************************}
+
+{$ifdef SUPPORT_MMX}
+ procedure ti386addnode.second_addmmx;
+ var
+ op : TAsmOp;
+ cmpop : boolean;
+ mmxbase : tmmxtype;
+ hregister : tregister;
+ begin
+ pass_left_and_right;
+
+ cmpop:=false;
+ mmxbase:=mmx_type(left.resultdef);
+ case nodetype of
+ addn :
+ begin
+ if (cs_mmx_saturation in current_settings.localswitches) then
+ begin
+ case mmxbase of
+ mmxs8bit:
+ op:=A_PADDSB;
+ mmxu8bit:
+ op:=A_PADDUSB;
+ mmxs16bit,mmxfixed16:
+ op:=A_PADDSB;
+ mmxu16bit:
+ op:=A_PADDUSW;
+ end;
+ end
+ else
+ begin
+ case mmxbase of
+ mmxs8bit,mmxu8bit:
+ op:=A_PADDB;
+ mmxs16bit,mmxu16bit,mmxfixed16:
+ op:=A_PADDW;
+ mmxs32bit,mmxu32bit:
+ op:=A_PADDD;
+ end;
+ end;
+ end;
+ muln :
+ begin
+ case mmxbase of
+ mmxs16bit,mmxu16bit:
+ op:=A_PMULLW;
+ mmxfixed16:
+ op:=A_PMULHW;
+ end;
+ end;
+ subn :
+ begin
+ if (cs_mmx_saturation in current_settings.localswitches) then
+ begin
+ case mmxbase of
+ mmxs8bit:
+ op:=A_PSUBSB;
+ mmxu8bit:
+ op:=A_PSUBUSB;
+ mmxs16bit,mmxfixed16:
+ op:=A_PSUBSB;
+ mmxu16bit:
+ op:=A_PSUBUSW;
+ end;
+ end
+ else
+ begin
+ case mmxbase of
+ mmxs8bit,mmxu8bit:
+ op:=A_PSUBB;
+ mmxs16bit,mmxu16bit,mmxfixed16:
+ op:=A_PSUBW;
+ mmxs32bit,mmxu32bit:
+ op:=A_PSUBD;
+ end;
+ end;
+ end;
+ xorn:
+ op:=A_PXOR;
+ orn:
+ op:=A_POR;
+ andn:
+ op:=A_PAND;
+ else
+ internalerror(200403183);
+ end;
+
+ { left and right no register? }
+ { then one must be demanded }
+ if (left.location.loc<>LOC_MMXREGISTER) then
+ begin
+ if (right.location.loc=LOC_MMXREGISTER) then
+ begin
+ location_swap(left.location,right.location);
+ toggleflag(nf_swapped);
+ end
+ else
+ begin
+ { register variable ? }
+ if (left.location.loc=LOC_CMMXREGISTER) then
+ begin
+ hregister:=rg.getregistermm(current_asmdata.CurrAsmList);
+ emit_reg_reg(A_MOVQ,S_NO,left.location.register,hregister);
+ end
+ else
+ begin
+ if not(left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
+ internalerror(200203245);
+
+ location_release(current_asmdata.CurrAsmList,left.location);
+
+ hregister:=rg.getregistermm(current_asmdata.CurrAsmList);
+ emit_ref_reg(A_MOVQ,S_NO,left.location.reference,hregister);
+ end;
+
+ location_reset(left.location,LOC_MMXREGISTER,OS_NO);
+ left.location.register:=hregister;
+ end;
+ end;
+
+ { at this point, left.location.loc should be LOC_MMXREGISTER }
+ if right.location.loc<>LOC_MMXREGISTER then
+ begin
+ if (nodetype=subn) and (nf_swapped in flags) then
+ begin
+ if right.location.loc=LOC_CMMXREGISTER then
+ begin
+ emit_reg_reg(A_MOVQ,S_NO,right.location.register,R_MM7);
+ emit_reg_reg(op,S_NO,left.location.register,R_MM7);
+ emit_reg_reg(A_MOVQ,S_NO,R_MM7,left.location.register);
+ end
+ else
+ begin
+ if not(left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
+ internalerror(200203247);
+ emit_ref_reg(A_MOVQ,S_NO,right.location.reference,R_MM7);
+ emit_reg_reg(op,S_NO,left.location.register,R_MM7);
+ emit_reg_reg(A_MOVQ,S_NO,R_MM7,left.location.register);
+ location_release(current_asmdata.CurrAsmList,right.location);
+ end;
+ end
+ else
+ begin
+ if (right.location.loc=LOC_CMMXREGISTER) then
+ begin
+ emit_reg_reg(op,S_NO,right.location.register,left.location.register);
+ end
+ else
+ begin
+ if not(right.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
+ internalerror(200203246);
+ emit_ref_reg(op,S_NO,right.location.reference,left.location.register);
+ location_release(current_asmdata.CurrAsmList,right.location);
+ end;
+ end;
+ end
+ else
+ begin
+ { right.location=LOC_MMXREGISTER }
+ if (nodetype=subn) and (nf_swapped in flags) then
+ begin
+ emit_reg_reg(op,S_NO,left.location.register,right.location.register);
+ location_swap(left.location,right.location);
+ toggleflag(nf_swapped);
+ end
+ else
+ begin
+ emit_reg_reg(op,S_NO,right.location.register,left.location.register);
+ end;
+ end;
+
+ location_freetemp(current_asmdata.CurrAsmList,right.location);
+ location_release(current_asmdata.CurrAsmList,right.location);
+ if cmpop then
+ begin
+ location_freetemp(current_asmdata.CurrAsmList,left.location);
+ location_release(current_asmdata.CurrAsmList,left.location);
+ end;
+ set_result_location(cmpop,true);
+ end;
+{$endif SUPPORT_MMX}
+
+
+{*****************************************************************************
+ pass_2
+*****************************************************************************}
+
+ procedure tppcaddnode.pass_generate_code;
+ { is also being used for xor, and "mul", "sub, or and comparative }
+ { operators }
+ var
+ cgop : topcg;
+ op : tasmop;
+ tmpreg : tregister;
+ hl : tasmlabel;
+ cmpop : boolean;
+ { true, if unsigned types are compared }
+ unsigned : boolean;
+ checkoverflow : boolean;
+
+ begin
+ { to make it more readable, string and set (not smallset!) have their
+ own procedures }
+ case left.resultdef.typ of
+ orddef :
+ begin
+ { handling boolean expressions }
+ if is_boolean(left.resultdef) and
+ is_boolean(right.resultdef) then
+ begin
+ second_addboolean;
+ exit;
+ end
+ { 64bit operations }
+ else if is_64bit(resultdef) or
+ is_64bit(left.resultdef) then
+ begin
+ second_add64bit;
+ exit;
+ end;
+ end;
+ stringdef :
+ begin
+ internalerror(2002072402);
+ exit;
+ end;
+ setdef :
+ begin
+ { normalsets are already handled in pass1 }
+ if not is_smallset(left.resultdef) then
+ internalerror(200109042);
+ second_addsmallset;
+ exit;
+ end;
+ arraydef :
+ begin
+{$ifdef SUPPORT_MMX}
+ if is_mmx_able_array(left.resultdef) then
+ begin
+ second_addmmx;
+ exit;
+ end;
+{$endif SUPPORT_MMX}
+ end;
+ floatdef :
+ begin
+ second_addfloat;
+ exit;
+ end;
+ end;
+
+ { defaults }
+ cmpop:=nodetype in [ltn,lten,gtn,gten,equaln,unequaln];
+ unsigned:=not(is_signed(left.resultdef)) or
+ not(is_signed(right.resultdef));
+
+ pass_left_and_right;
+
+ { Convert flags to register first }
+ { can any of these things be in the flags actually?? (JM) }
+
+ if (left.location.loc = LOC_FLAGS) or
+ (right.location.loc = LOC_FLAGS) then
+ internalerror(2002072602);
+
+ { set result location }
+ if not cmpop then
+ location_reset(location,LOC_REGISTER,def_cgsize(resultdef))
+ else
+ location_reset(location,LOC_FLAGS,OS_NO);
+
+ checkoverflow:=
+ (nodetype in [addn,subn,muln]) and
+ (cs_check_overflow in current_settings.localswitches) and
+ (left.resultdef.typ<>pointerdef) and
+ (right.resultdef.typ<>pointerdef);
+
+ load_left_right(cmpop, checkoverflow);
+
+ if not(cmpop) then
+ location.register := cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+
+ if not(checkoverflow) then
+ begin
+ case nodetype of
+ addn, muln, xorn, orn, andn:
+ begin
+ case nodetype of
+ addn:
+ cgop := OP_ADD;
+ muln:
+ if unsigned then
+ cgop := OP_MUL
+ else
+ cgop := OP_IMUL;
+ xorn:
+ cgop := OP_XOR;
+ orn:
+ cgop := OP_OR;
+ andn:
+ cgop := OP_AND;
+ end;
+ if (left.location.loc = LOC_CONSTANT) then
+ swapleftright;
+ if (right.location.loc <> LOC_CONSTANT) then
+ cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,cgop,OS_INT,
+ left.location.register,right.location.register,
+ location.register)
+ else
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,cgop,OS_INT,
+ right.location.value,left.location.register,
+ location.register);
+ end;
+ subn:
+ begin
+ if (nf_swapped in flags) then
+ swapleftright;
+ if left.location.loc <> LOC_CONSTANT then
+ if right.location.loc <> LOC_CONSTANT then
+ cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,OP_SUB,OS_INT,
+ right.location.register,left.location.register,
+ location.register)
+ else
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SUB,OS_INT,
+ right.location.value,left.location.register,
+ location.register)
+ else
+ if (longint(left.location.value) >= low(smallint)) and
+ (longint(left.location.value) <= high(smallint)) then
+ begin
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_const(A_SUBFIC,
+ location.register,right.location.register,
+ longint(left.location.value)));
+ end
+ else
+ begin
+ tmpreg := cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+ cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_INT,
+ left.location.value,tmpreg);
+ cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,OP_SUB,OS_INT,
+ right.location.register,tmpreg,location.register);
+ end;
+ end;
+ ltn,lten,gtn,gten,equaln,unequaln :
+ begin
+ emit_compare(unsigned);
+ end;
+ end;
+ end
+ else
+ // overflow checking is on and we have an addn, subn or muln
+ begin
+ if is_signed(resultdef) then
+ begin
+ case nodetype of
+ addn:
+ op := A_ADDO;
+ subn:
+ begin
+ op := A_SUBO;
+ if (nf_swapped in flags) then
+ swapleftright;
+ end;
+ muln:
+ op := A_MULLWO;
+ else
+ internalerror(2002072601);
+ end;
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(op,location.register,
+ left.location.register,right.location.register));
+ cg.g_overflowcheck(current_asmdata.CurrAsmList,location,resultdef);
+ end
+ else
+ begin
+ case nodetype of
+ addn:
+ begin
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_ADD,location.register,
+ left.location.register,right.location.register));
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CMPLW,location.register,left.location.register));
+ cg.g_overflowcheck(current_asmdata.CurrAsmList,location,resultdef);
+ end;
+ subn:
+ begin
+ if nf_swapped in flags then
+ swapleftright;
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SUB,location.register,
+ left.location.register,right.location.register));
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CMPLW,left.location.register,location.register));
+ cg.g_overflowcheck(current_asmdata.CurrAsmList,location,resultdef);
+ end;
+ muln:
+ begin
+ { calculate the upper 32 bits of the product, = 0 if no overflow }
+ cg.a_reg_alloc(current_asmdata.CurrAsmList,NR_R0);
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_MULHWU_,NR_R0,
+ left.location.register,right.location.register));
+ cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_R0);
+ { calculate the real result }
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_MULLW,location.register,
+ left.location.register,right.location.register));
+ { g_overflowcheck generates a OC_AE instead of OC_EQ :/ }
+ current_asmdata.getjumplabel(hl);
+ tcgppc(cg).a_jmp_cond(current_asmdata.CurrAsmList,OC_EQ,hl);
+ cg.a_call_name(current_asmdata.CurrAsmList,'FPC_OVERFLOW',false);
+ cg.a_label(current_asmdata.CurrAsmList,hl);
+ end;
+ end;
+ end;
+ end;
+ end;
+
+begin
+ caddnode:=tppcaddnode;
+end.
diff --git a/closures/compiler/powerpc/nppccal.pas b/closures/compiler/powerpc/nppccal.pas
new file mode 100644
index 0000000000..44b6cebc39
--- /dev/null
+++ b/closures/compiler/powerpc/nppccal.pas
@@ -0,0 +1,147 @@
+{
+ Copyright (c) 2002 by Florian Klaempfl
+
+ Implements the PowerPC specific part of call nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit nppccal;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ symdef,node,ncal,ncgcal;
+
+ type
+ tppccallnode = class(tcgcallnode)
+ procedure extra_call_code;override;
+ procedure do_syscall;override;
+ end;
+
+
+implementation
+
+ uses
+ globtype,systems,
+ cutils,verbose,globals,
+ symconst,symbase,symsym,symtable,defutil,paramgr,parabase,
+ cgbase,pass_2,
+ cpuinfo,cpubase,aasmbase,aasmtai,aasmdata,aasmcpu,
+ nmem,nld,ncnv,
+ ncgutil,cgutils,cgobj,tgobj,regvars,rgobj,rgcpu,
+ cg64f32,cgcpu,cpupi,procinfo;
+
+
+ procedure tppccallnode.extra_call_code;
+ begin
+ if assigned(varargsparas) then
+ begin
+ if (target_info.abi = abi_powerpc_sysv) then
+ begin
+ if va_uses_float_reg in varargsparas.varargsinfo then
+ current_asmdata.CurrAsmList.concat(taicpu.op_const_const_const(A_CREQV,6,6,6))
+ else
+ current_asmdata.CurrAsmList.concat(taicpu.op_const_const_const(A_CRXOR,6,6,6));
+ end;
+ end;
+ end;
+
+
+ procedure tppccallnode.do_syscall;
+ var
+ tmpref: treference;
+ begin
+ case target_info.system of
+ system_powerpc_amiga:
+ begin
+ // one syscall convention for Amiga/PowerPC
+ // which is very similar to basesysv on MorphOS
+ cg.getcpuregister(current_asmdata.CurrAsmList,NR_R0);
+ reference_reset_base(tmpref,NR_R3,tprocdef(procdefinition).extnumber,sizeof(pint));
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_ref(A_LWZ,NR_R0,tmpref));
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg(A_MTCTR,NR_R0));
+ current_asmdata.CurrAsmList.concat(taicpu.op_none(A_BCTRL));
+ cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_R0);
+ end;
+ system_powerpc_morphos:
+ begin
+ if (po_syscall_sysv in tprocdef(procdefinition).procoptions) or
+ (po_syscall_sysvbase in tprocdef(procdefinition).procoptions) then
+ begin
+ cg.getcpuregister(current_asmdata.CurrAsmList,NR_R0);
+ cg.getcpuregister(current_asmdata.CurrAsmList,NR_R12);
+
+ reference_reset(tmpref,sizeof(pint));
+ tmpref.symbol:=current_asmdata.RefAsmSymbol(tstaticvarsym(tprocdef(procdefinition).libsym).mangledname);
+ tmpref.refaddr:=addr_higha;
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_ref(A_LIS,NR_R12,tmpref));
+ tmpref.base:=NR_R12;
+ tmpref.refaddr:=addr_low;
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_ref(A_LWZ,NR_R12,tmpref));
+
+ reference_reset_base(tmpref,NR_R12,-tprocdef(procdefinition).extnumber,sizeof(pint));
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_ref(A_LWZ,NR_R0,tmpref));
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg(A_MTCTR,NR_R0));
+ current_asmdata.CurrAsmList.concat(taicpu.op_none(A_BCTRL));
+
+ cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_R12);
+ cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_R0);
+ end
+ else if (po_syscall_basesysv in tprocdef(procdefinition).procoptions) or
+ (po_syscall_r12base in tprocdef(procdefinition).procoptions) then
+ begin
+ cg.getcpuregister(current_asmdata.CurrAsmList,NR_R0);
+ if (po_syscall_basesysv in tprocdef(procdefinition).procoptions) then
+ reference_reset_base(tmpref,NR_R3,-tprocdef(procdefinition).extnumber,sizeof(pint))
+ else
+ reference_reset_base(tmpref,NR_R12,-tprocdef(procdefinition).extnumber,sizeof(pint));
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_ref(A_LWZ,NR_R0,tmpref));
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg(A_MTCTR,NR_R0));
+ current_asmdata.CurrAsmList.concat(taicpu.op_none(A_BCTRL));
+ cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_R0);
+ end
+ else if po_syscall_legacy in tprocdef(procdefinition).procoptions then
+ begin
+ cg.getcpuregister(current_asmdata.CurrAsmList,NR_R0);
+ cg.getcpuregister(current_asmdata.CurrAsmList,NR_R3);
+
+ { store call offset into R3 }
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_LI,NR_R3,-tprocdef(procdefinition).extnumber));
+
+ { prepare LR, and call function }
+ reference_reset_base(tmpref,NR_R2,100,4); { 100 ($64) is EmulDirectCallOS offset }
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_ref(A_LWZ,NR_R0,tmpref));
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg(A_MTLR,NR_R0));
+ current_asmdata.CurrAsmList.concat(taicpu.op_none(A_BLRL));
+
+ cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_R3);
+ cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_R0);
+ end
+ else
+ internalerror(2005010403);
+ end;
+ else
+ internalerror(2004042901);
+ end;
+ end;
+
+
+begin
+ ccallnode:=tppccallnode;
+end.
diff --git a/closures/compiler/powerpc/nppccnv.pas b/closures/compiler/powerpc/nppccnv.pas
new file mode 100644
index 0000000000..e9fb33f1b8
--- /dev/null
+++ b/closures/compiler/powerpc/nppccnv.pas
@@ -0,0 +1,231 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate PowerPC assembler for type converting nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit nppccnv;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,ncnv,ncgcnv,ngppccnv;
+
+ type
+ tppctypeconvnode = class(tgenppctypeconvnode)
+ protected
+ { procedure second_int_to_int;override; }
+ { procedure second_string_to_string;override; }
+ { procedure second_cstring_to_pchar;override; }
+ { procedure second_string_to_chararray;override; }
+ { procedure second_array_to_pointer;override; }
+ function first_int_to_real: tnode; override;
+ { procedure second_pointer_to_array;override; }
+ { procedure second_chararray_to_string;override; }
+ { procedure second_char_to_string;override; }
+ procedure second_int_to_real;override;
+ { procedure second_real_to_real;override; }
+ { procedure second_cord_to_pointer;override; }
+ { procedure second_proc_to_procvar;override; }
+ { procedure second_bool_to_int;override; }
+ { procedure second_int_to_bool;override; }
+ { procedure second_set_to_set;override; }
+ { procedure second_ansistring_to_pchar;override; }
+ { procedure second_pchar_to_string;override; }
+ { procedure second_class_to_intf;override; }
+ { procedure second_char_to_char;override; }
+ end;
+
+implementation
+
+ uses
+ verbose,globtype,globals,systems,
+ symconst,symdef,aasmbase,aasmtai,aasmdata,
+ defutil,
+ cgbase,cgutils,pass_1,pass_2,
+ ncon,ncal,
+ ncgutil,procinfo,
+ cpubase,aasmcpu,
+ rgobj,tgobj,cgobj;
+
+
+{*****************************************************************************
+ FirstTypeConv
+*****************************************************************************}
+
+ function tppctypeconvnode.first_int_to_real: tnode;
+ var
+ fname: string[19];
+ begin
+ { converting a 64bit integer to a float requires a helper }
+ if is_64bitint(left.resultdef) or
+ is_currency(left.resultdef) then
+ begin
+ { hack to avoid double division by 10000, as it's }
+ { already done by typecheckpass.resultdef_int_to_real }
+ if is_currency(left.resultdef) then
+ left.resultdef := s64inttype;
+ if is_signed(left.resultdef) then
+ fname := 'fpc_int64_to_double'
+ else
+ fname := 'fpc_qword_to_double';
+ result := ccallnode.createintern(fname,ccallparanode.create(
+ left,nil));
+ left:=nil;
+ firstpass(result);
+ exit;
+ end
+ else
+ { other integers are supposed to be 32 bit }
+ begin
+ if is_signed(left.resultdef) then
+ inserttypeconv(left,s32inttype)
+ else
+ inserttypeconv(left,u32inttype);
+ firstpass(left);
+ end;
+ result := nil;
+ expectloc:=LOC_FPUREGISTER;
+ end;
+
+
+{*****************************************************************************
+ SecondTypeConv
+*****************************************************************************}
+
+ procedure tppctypeconvnode.second_int_to_real;
+
+ type
+ tdummyarray = packed array[0..7] of byte;
+
+ const
+ dummy1: int64 = $4330000080000000;
+ dummy2: int64 = $4330000000000000;
+
+ var
+ tempconst: tnode;
+ ref: treference;
+ valuereg, tempreg, leftreg, tmpfpureg: tregister;
+ size: tcgsize;
+ signed : boolean;
+ begin
+ location_reset(location,LOC_FPUREGISTER,def_cgsize(resultdef));
+
+ { the code here comes from the PowerPC Compiler Writer's Guide }
+
+ { * longint to double }
+ { addis R0,R0,0x4330 # R0 = 0x43300000 }
+ { stw R0,disp(R1) # store upper half }
+ { xoris R3,R3,0x8000 # flip sign bit }
+ { stw R3,disp+4(R1) # store lower half }
+ { lfd FR1,disp(R1) # float load double of value }
+ { fsub FR1,FR1,FR2 # subtract 0x4330000080000000 }
+
+ { * cardinal to double }
+ { addis R0,R0,0x4330 # R0 = 0x43300000 }
+ { stw R0,disp(R1) # store upper half }
+ { stw R3,disp+4(R1) # store lower half }
+ { lfd FR1,disp(R1) # float load double of value }
+ { fsub FR1,FR1,FR2 # subtract 0x4330000000000000 }
+ tg.Gettemp(current_asmdata.CurrAsmList,8,8,tt_normal,ref);
+
+ signed := is_signed(left.resultdef);
+
+ { we need a certain constant for the conversion, so create it here }
+ if signed then
+ tempconst :=
+ crealconstnode.create(double(tdummyarray(dummy1)),
+ pbestrealtype^)
+ else
+ tempconst :=
+ crealconstnode.create(double(tdummyarray(dummy2)),
+ pbestrealtype^);
+
+ typecheckpass(tempconst);
+ firstpass(tempconst);
+ secondpass(tempconst);
+ if (tempconst.location.loc <> LOC_CREFERENCE) or
+ { has to be handled by a helper }
+ is_64bitint(left.resultdef) then
+ internalerror(200110011);
+
+ if not(left.location.loc in [LOC_REGISTER,LOC_CREGISTER,LOC_REFERENCE,LOC_CREFERENCE]) then
+ location_force_reg(current_asmdata.CurrAsmList,left.location,left.location.size,false);
+ case left.location.loc of
+ LOC_REGISTER:
+ begin
+ leftreg := left.location.register;
+ valuereg := leftreg;
+ end;
+ LOC_CREGISTER:
+ begin
+ leftreg := left.location.register;
+ if signed then
+ valuereg := cg.getintregister(current_asmdata.CurrAsmList,OS_INT)
+ else
+ valuereg := leftreg;
+ end;
+ LOC_REFERENCE,LOC_CREFERENCE:
+ begin
+ leftreg := cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+ valuereg := leftreg;
+ if signed then
+ size := OS_S32
+ else
+ size := OS_32;
+ cg.a_load_ref_reg(current_asmdata.CurrAsmList,def_cgsize(left.resultdef),
+ size,left.location.reference,leftreg);
+ end
+ else
+ internalerror(200110012);
+ end;
+ tempreg := cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_LIS,tempreg,$4330));
+ cg.a_load_reg_ref(current_asmdata.CurrAsmList,OS_32,OS_32,tempreg,ref);
+ if signed then
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_const(A_XORIS,valuereg,
+ { xoris expects a unsigned 16 bit int (FK) }
+ leftreg,$8000));
+ inc(ref.offset,4);
+ cg.a_load_reg_ref(current_asmdata.CurrAsmList,OS_32,OS_32,valuereg,ref);
+ dec(ref.offset,4);
+
+ tmpfpureg := cg.getfpuregister(current_asmdata.CurrAsmList,OS_F64);
+ cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,OS_F64,OS_F64,tempconst.location.reference,
+ tmpfpureg);
+ tempconst.free;
+
+ location.register := cg.getfpuregister(current_asmdata.CurrAsmList,OS_F64);
+ cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,OS_F64,OS_F64,ref,location.register);
+
+ tg.ungetiftemp(current_asmdata.CurrAsmList,ref);
+
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_FSUB,location.register,
+ location.register,tmpfpureg));
+
+ { make sure the precision is correct }
+ if (tfloatdef(resultdef).floattype = s32real) then
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FRSP,location.register,
+ location.register));
+ end;
+
+begin
+ ctypeconvnode:=tppctypeconvnode;
+end.
diff --git a/closures/compiler/powerpc/nppcmat.pas b/closures/compiler/powerpc/nppcmat.pas
new file mode 100644
index 0000000000..767a5abcd6
--- /dev/null
+++ b/closures/compiler/powerpc/nppcmat.pas
@@ -0,0 +1,721 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate PowerPC assembler for math nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit nppcmat;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,nmat;
+
+ type
+ tppcmoddivnode = class(tmoddivnode)
+ function pass_1: tnode;override;
+ procedure pass_generate_code;override;
+ end;
+
+ tppcshlshrnode = class(tshlshrnode)
+ procedure pass_generate_code;override;
+ { everything will be handled in pass_2 }
+ function first_shlshr64bitint: tnode; override;
+ end;
+
+ tppcunaryminusnode = class(tunaryminusnode)
+ procedure pass_generate_code;override;
+ end;
+
+ tppcnotnode = class(tnotnode)
+ procedure pass_generate_code;override;
+ end;
+
+implementation
+
+ uses
+ globtype,systems,constexp,
+ cutils,verbose,globals,
+ symconst,
+ aasmbase,aasmcpu,aasmtai,aasmdata,
+ defutil,
+ cgbase,cgutils,cgobj,pass_2,
+ ncon,procinfo,
+ cpubase,
+ ncgutil,cgcpu;
+
+{$push}
+{$r-}
+{$q-}
+{ helper functions }
+procedure getmagic_unsigned32(d : dword; out magic_m : dword; out magic_add : boolean; out magic_shift : dword);
+var
+ p : longint;
+ nc, delta, q1, r1, q2, r2 : dword;
+
+begin
+ assert(d > 0);
+
+ magic_add := false;
+ nc := dword(- 1) - dword(-d) mod d;
+ p := 31; { initialize p }
+ q1 := $80000000 div nc; { initialize q1 = 2p/nc }
+ r1 := $80000000 - q1*nc; { initialize r1 = rem(2p,nc) }
+ q2 := $7FFFFFFF div d; { initialize q2 = (2p-1)/d }
+ r2 := $7FFFFFFF - q2*d; { initialize r2 = rem((2p-1),d) }
+ repeat
+ inc(p);
+ if (r1 >= (nc - r1)) then begin
+ q1 := 2 * q1 + 1; { update q1 }
+ r1 := 2*r1 - nc; { update r1 }
+ end else begin
+ q1 := 2*q1; { update q1 }
+ r1 := 2*r1; { update r1 }
+ end;
+ if ((r2 + 1) >= (d - r2)) then begin
+ if (q2 >= $7FFFFFFF) then
+ magic_add := true;
+ q2 := 2*q2 + 1; { update q2 }
+ r2 := 2*r2 + 1 - d; { update r2 }
+ end else begin
+ if (q2 >= $80000000) then
+ magic_add := true;
+ q2 := 2*q2; { update q2 }
+ r2 := 2*r2 + 1; { update r2 }
+ end;
+ delta := d - 1 - r2;
+ until not ((p < 64) and ((q1 < delta) or ((q1 = delta) and (r1 = 0))));
+ magic_m := q2 + 1; { resulting magic number }
+ magic_shift := p - 32; { resulting shift }
+end;
+
+procedure getmagic_signed32(d : longint; out magic_m : longint; out magic_s : longint);
+const
+ two_31 : DWord = high(longint)+1;
+var
+ p : Longint;
+ ad, anc, delta, q1, r1, q2, r2, t : DWord;
+
+begin
+ assert((d < -1) or (d > 1));
+
+ ad := abs(d);
+ t := two_31 + (DWord(d) shr 31);
+ anc := t - 1 - t mod ad; { absolute value of nc }
+ p := 31; { initialize p }
+ q1 := two_31 div anc; { initialize q1 = 2p/abs(nc) }
+ r1 := two_31 - q1*anc; { initialize r1 = rem(2p,abs(nc)) }
+ q2 := two_31 div ad; { initialize q2 = 2p/abs(d) }
+ r2 := two_31 - q2*ad; { initialize r2 = rem(2p,abs(d)) }
+ repeat
+ inc(p);
+ q1 := 2*q1; { update q1 = 2p/abs(nc) }
+ r1 := 2*r1; { update r1 = rem(2p/abs(nc)) }
+ if (r1 >= anc) then begin { must be unsigned comparison }
+ inc(q1);
+ dec(r1, anc);
+ end;
+ q2 := 2*q2; { update q2 = 2p/abs(d) }
+ r2 := 2*r2; { update r2 = rem(2p/abs(d)) }
+ if (r2 >= ad) then begin { must be unsigned comparison }
+ inc(q2);
+ dec(r2, ad);
+ end;
+ delta := ad - r2;
+ until not ((q1 < delta) or ((q1 = delta) and (r1 = 0)));
+ magic_m := q2 + 1;
+ if (d < 0) then begin
+ magic_m := -magic_m; { resulting magic number }
+ end;
+ magic_s := p - 32; { resulting shift }
+end;
+
+{$pop}
+
+{*****************************************************************************
+ TPPCMODDIVNODE
+*****************************************************************************}
+
+ function tppcmoddivnode.pass_1: tnode;
+ begin
+ result := inherited pass_1;
+ if not assigned(result) then
+ include(current_procinfo.flags,pi_do_call);
+ end;
+
+
+ procedure tppcmoddivnode.pass_generate_code;
+ const
+ { signed overflow }
+ divops: array[boolean, boolean] of tasmop =
+ ((A_DIVWU,A_DIVWU_),(A_DIVW,A_DIVWO_));
+ zerocond: tasmcond = (dirhint: DH_Plus; simple: true; cond:C_NE; cr: RS_CR1);
+ var
+ power : longint;
+ op : tasmop;
+ numerator,
+ divider,
+ resultreg : tregister;
+ size : Tcgsize;
+ hl : tasmlabel;
+ done: boolean;
+
+ procedure genOrdConstNodeDiv;
+ const
+ negops : array[boolean] of tasmop = (A_NEG, A_NEGO);
+ var
+ magic, shift : longint;
+ u_magic, u_shift : dword;
+ u_add : boolean;
+
+ divreg : tregister;
+ begin
+ if (tordconstnode(right).value = 0) then begin
+ internalerror(2005061701);
+ end else if (tordconstnode(right).value = 1) then begin
+ cg.a_load_reg_reg(current_asmdata.CurrAsmList, OS_INT, OS_INT, numerator, resultreg);
+ end else if (tordconstnode(right).value = int64(-1)) then begin
+ // note: only in the signed case possible..., may overflow
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(negops[cs_check_overflow in current_settings.localswitches], resultreg, numerator));
+ end else if (ispowerof2(tordconstnode(right).value, power)) then begin
+ if (is_signed(right.resultdef)) then begin
+ { From "The PowerPC Compiler Writer's Guide", pg. 52ff }
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_SAR, OS_INT, power,
+ numerator, resultreg);
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_ADDZE, resultreg, resultreg));
+ end else begin
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_SHR, OS_INT, power, numerator, resultreg)
+ end;
+ end else begin
+ { replace division by multiplication, both implementations }
+ { from "The PowerPC Compiler Writer's Guide" pg. 53ff }
+ divreg := cg.getintregister(current_asmdata.CurrAsmList, OS_INT);
+ if (is_signed(right.resultdef)) then begin
+ getmagic_signed32(tordconstnode(right).value.svalue, magic, shift);
+ // load magic value
+ cg.a_load_const_reg(current_asmdata.CurrAsmList, OS_INT, magic, divreg);
+ // multiply
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_MULHW, resultreg, numerator, divreg));
+ // add/subtract numerator
+ if (tordconstnode(right).value > 0) and (magic < 0) then begin
+ cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList, OP_ADD, OS_INT, numerator, resultreg, resultreg);
+ end else if (tordconstnode(right).value < 0) and (magic > 0) then begin
+ cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList, OP_SUB, OS_INT, numerator, resultreg, resultreg);
+ end;
+ // shift shift places to the right (arithmetic)
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_SAR, OS_INT, shift, resultreg, resultreg);
+ // extract and add sign bit
+ if (tordconstnode(right).value >= 0) then begin
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_SHR, OS_INT, 31, numerator, divreg);
+ end else begin
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_SHR, OS_INT, 31, resultreg, divreg);
+ end;
+ cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList, OP_ADD, OS_INT, resultreg, divreg, resultreg);
+ end else begin
+ getmagic_unsigned32(tordconstnode(right).value.uvalue, u_magic, u_add, u_shift);
+ // load magic in divreg
+ cg.a_load_const_reg(current_asmdata.CurrAsmList, OS_INT, aint(u_magic), divreg);
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_MULHWU, resultreg, numerator, divreg));
+ if (u_add) then begin
+ cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList, OP_SUB, OS_INT, resultreg, numerator, divreg);
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_SHR, OS_INT, 1, divreg, divreg);
+ cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList, OP_ADD, OS_INT, divreg, resultreg, divreg);
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_SHR, OS_INT, u_shift-1, divreg, resultreg);
+ end else begin
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_SHR, OS_INT, u_shift, resultreg, resultreg);
+ end;
+ end;
+ end;
+ done := true;
+ end;
+
+ procedure genOrdConstNodeMod;
+ var
+ modreg, maskreg, tempreg : tregister;
+ begin
+ if (tordconstnode(right).value = 0) then begin
+ internalerror(2005061702);
+ end else if (abs(tordconstnode(right).value.svalue) = 1) then begin
+ // x mod +/-1 is always zero
+ cg.a_load_const_reg(current_asmdata.CurrAsmList, OS_INT, 0, resultreg);
+ end else if (ispowerof2(tordconstnode(right).value, power)) then begin
+ if (is_signed(right.resultdef)) then begin
+
+ tempreg := cg.getintregister(current_asmdata.CurrAsmList, OS_INT);
+ maskreg := cg.getintregister(current_asmdata.CurrAsmList, OS_INT);
+ modreg := cg.getintregister(current_asmdata.CurrAsmList, OS_INT);
+
+ cg.a_load_const_reg(current_asmdata.CurrAsmList, OS_INT, abs(tordconstnode(right).value.svalue)-1, modreg);
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_SAR, OS_INT, 31, numerator, maskreg);
+ cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList, OP_AND, OS_INT, numerator, modreg, tempreg);
+
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_ANDC, maskreg, maskreg, modreg));
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_const(A_SUBFIC, modreg, tempreg, 0));
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SUBFE, modreg, modreg, modreg));
+ cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList, OP_AND, OS_INT, modreg, maskreg, maskreg);
+ cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList, OP_OR, OS_INT, maskreg, tempreg, resultreg);
+ end else begin
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_AND, OS_INT, tordconstnode(right).value.svalue-1, numerator, resultreg);
+ end;
+ end else begin
+ genOrdConstNodeDiv();
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_MUL, OS_INT, tordconstnode(right).value.svalue, resultreg, resultreg);
+ cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList, OP_SUB, OS_INT, resultreg, numerator, resultreg);
+ end;
+ end;
+
+
+ begin
+ secondpass(left);
+ secondpass(right);
+ location_copy(location,left.location);
+
+ { put numerator in register }
+ size:=def_cgsize(left.resultdef);
+ location_force_reg(current_asmdata.CurrAsmList,left.location,
+ size,true);
+ location_copy(location,left.location);
+ numerator := location.register;
+ resultreg := location.register;
+ if (location.loc = LOC_CREGISTER) then begin
+ location.loc := LOC_REGISTER;
+ location.register := cg.getintregister(current_asmdata.CurrAsmList,size);
+ resultreg := location.register;
+ end else if (nodetype = modn) or (right.nodetype = ordconstn) then begin
+ // for a modulus op, and for const nodes we need the result register
+ // to be an extra register
+ resultreg := cg.getintregister(current_asmdata.CurrAsmList,size);
+ end;
+
+ done := false;
+ if (right.nodetype = ordconstn) then begin
+ if (nodetype = divn) then
+ genOrdConstNodeDiv
+ else
+ genOrdConstNodeMod;
+ done := true;
+ end;
+
+ if (not done) then begin
+ { load divider in a register if necessary }
+ location_force_reg(current_asmdata.CurrAsmList,right.location,
+ def_cgsize(right.resultdef),true);
+ if (right.nodetype <> ordconstn) then
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_const(A_CMPWI,NR_CR1,
+ right.location.register,0));
+ divider := right.location.register;
+
+ { needs overflow checking, (-maxlongint-1) div (-1) overflows! }
+ op := divops[is_signed(right.resultdef),
+ cs_check_overflow in current_settings.localswitches];
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(op,resultreg,numerator,
+ divider));
+
+ if (nodetype = modn) then
+ begin
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_MULLW,resultreg,
+ divider,resultreg));
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SUB,location.register,
+ numerator,resultreg));
+ resultreg := location.register;
+ end;
+ end;
+ { set result location }
+ location.loc:=LOC_REGISTER;
+ location.register:=resultreg;
+ if right.nodetype <> ordconstn then
+ begin
+ current_asmdata.getjumplabel(hl);
+ current_asmdata.CurrAsmList.concat(taicpu.op_cond_sym(A_BC,zerocond,hl));
+ cg.a_call_name(current_asmdata.CurrAsmList,'FPC_DIVBYZERO',false);
+ cg.a_label(current_asmdata.CurrAsmList,hl);
+ end;
+ { unsigned division/module can only overflow in case of division by zero }
+ { (but checking this overflow flag is more convoluted than performing a }
+ { simple comparison with 0) }
+ if is_signed(right.resultdef) then
+ cg.g_overflowcheck(current_asmdata.CurrAsmList,location,resultdef);
+ end;
+
+
+{*****************************************************************************
+ TPPCSHLRSHRNODE
+*****************************************************************************}
+
+ function tppcshlshrnode.first_shlshr64bitint: tnode;
+ begin
+ result := nil;
+ end;
+
+ procedure tppcshlshrnode.pass_generate_code;
+
+ var
+ resultreg, hregister1,hregister2,
+ hreg64hi,hreg64lo : tregister;
+ op : topcg;
+ asmop1, asmop2: tasmop;
+ shiftval: aint;
+
+ begin
+ secondpass(left);
+ secondpass(right);
+
+ if is_64bitint(left.resultdef) then
+ begin
+ location_force_reg(current_asmdata.CurrAsmList,left.location,
+ def_cgsize(left.resultdef),true);
+ location_copy(location,left.location);
+ hreg64hi := location.register64.reghi;
+ hreg64lo := location.register64.reglo;
+ if (location.loc = LOC_CREGISTER) then
+ begin
+ location.loc := LOC_REGISTER;
+ location.register64.reghi := cg.getintregister(current_asmdata.CurrAsmList,OS_32);
+ location.register64.reglo := cg.getintregister(current_asmdata.CurrAsmList,OS_32);
+ end;
+ if (right.nodetype = ordconstn) then
+ begin
+ shiftval := tordconstnode(right).value.svalue;
+ shiftval := shiftval and 63;
+{
+ I think the statements below is much more correct instead of the hack above,
+ but then we fail tshlshr.pp :/
+
+ if shiftval > 63 then
+ begin
+ cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_32,0,location.register64.reglo);
+ cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_32,0,location.register64.reglo);
+ end
+ else } if shiftval > 31 then
+ begin
+ if nodetype = shln then
+ begin
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SHL,OS_32,
+ shiftval and 31,hreg64lo,location.register64.reghi);
+ cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_32,0,location.register64.reglo);
+ end
+ else
+ begin
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SHR,OS_32,
+ shiftval and 31,hreg64hi,location.register64.reglo);
+ cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_32,0,location.register64.reghi);
+ end;
+ end
+ else
+ begin
+ if nodetype = shln then
+ begin
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_const_const_const(
+ A_RLWINM,location.register64.reghi,hreg64hi,shiftval,
+ 0,31-shiftval));
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_const_const_const(
+ A_RLWIMI,location.register64.reghi,hreg64lo,shiftval,
+ 32-shiftval,31));
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_const_const_const(
+ A_RLWINM,location.register64.reglo,hreg64lo,shiftval,
+ 0,31-shiftval));
+ end
+ else
+ begin
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_const_const_const(
+ A_RLWINM,location.register64.reglo,hreg64lo,32-shiftval,
+ shiftval,31));
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_const_const_const(
+ A_RLWIMI,location.register64.reglo,hreg64hi,32-shiftval,
+ 0,shiftval-1));
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_const_const_const(
+ A_RLWINM,location.register64.reghi,hreg64hi,32-shiftval,
+ shiftval,31));
+ end;
+ end;
+ end
+ else
+ { no constant shiftcount }
+ begin
+ location_force_reg(current_asmdata.CurrAsmList,right.location,OS_S32,true);
+ hregister1 := right.location.register;
+ if nodetype = shln then
+ begin
+ asmop1 := A_SLW;
+ asmop2 := A_SRW;
+ end
+ else
+ begin
+ asmop1 := A_SRW;
+ asmop2 := A_SLW;
+ resultreg := hreg64hi;
+ hreg64hi := hreg64lo;
+ hreg64lo := resultreg;
+ resultreg := location.register64.reghi;
+ location.register64.reghi := location.register64.reglo;
+ location.register64.reglo := resultreg;
+ end;
+
+ cg.getcpuregister(current_asmdata.CurrAsmList,NR_R0);
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_const(A_SUBFIC,
+ NR_R0,hregister1,32));
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(asmop1,
+ location.register64.reghi,hreg64hi,hregister1));
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(asmop2,
+ NR_R0,hreg64lo,NR_R0));
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_OR,
+ location.register64.reghi,location.register64.reghi,NR_R0));
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_const(A_SUBI,
+ NR_R0,hregister1,32));
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(asmop1,
+ NR_R0,hreg64lo,NR_R0));
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_OR,
+ location.register64.reghi,location.register64.reghi,NR_R0));
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(asmop1,
+ location.register64.reglo,hreg64lo,hregister1));
+ cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_R0);
+
+ if nodetype = shrn then
+ begin
+ resultreg := location.register64.reghi;
+ location.register64.reghi := location.register64.reglo;
+ location.register64.reglo := resultreg;
+ end;
+ end
+ end
+ else
+ begin
+ { load left operators in a register }
+ location_force_reg(current_asmdata.CurrAsmList,left.location,def_cgsize(left.resultdef),true);
+ location_copy(location,left.location);
+ resultreg := location.register;
+ hregister1 := location.register;
+ location.loc := LOC_REGISTER;
+ resultreg := cg.getintregister(current_asmdata.CurrAsmList,location.size);
+ location.register := resultreg;
+
+ { determine operator }
+ if nodetype=shln then
+ op:=OP_SHL
+ else
+ op:=OP_SHR;
+
+ { shifting by a constant directly coded: }
+ if (right.nodetype=ordconstn) then
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,op,location.size,
+ tordconstnode(right).value.svalue and 31,hregister1,resultreg)
+ else
+ begin
+ { load shift count in a register if necessary }
+ location_force_reg(current_asmdata.CurrAsmList,right.location,def_cgsize(right.resultdef),true);
+ hregister2 := right.location.register;
+
+ cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,op,location.size,hregister2,
+ hregister1,resultreg);
+ end;
+ end;
+ end;
+
+
+{*****************************************************************************
+ TPPCUNARYMINUSNODE
+*****************************************************************************}
+
+ procedure tppcunaryminusnode.pass_generate_code;
+
+ var
+ src1: tregister;
+ op: tasmop;
+
+ begin
+ secondpass(left);
+ if is_64bit(left.resultdef) then
+ begin
+ location_force_reg(current_asmdata.CurrAsmList,left.location,def_cgsize(left.resultdef),true);
+ location_copy(location,left.location);
+ if (location.loc = LOC_CREGISTER) then
+ begin
+ location.register64.reglo := cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+ location.register64.reghi := cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+ location.loc := LOC_REGISTER;
+ end;
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_const(A_SUBFIC,
+ location.register64.reglo,left.location.register64.reglo,0));
+ if not(cs_check_overflow in current_settings.localswitches) then
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_SUBFZE,
+ location.register64.reghi,left.location.register64.reghi))
+ else
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_SUBFZEO_,
+ location.register64.reghi,left.location.register64.reghi));
+ end
+ else
+ begin
+ if left.location.loc in [LOC_SUBSETREG,LOC_CSUBSETREG,LOC_SUBSETREF,LOC_CSUBSETREF] then
+ location_force_reg(current_asmdata.CurrAsmList,left.location,left.location.size,true);
+ location_copy(location,left.location);
+ location.loc:=LOC_REGISTER;
+ case left.location.loc of
+ LOC_FPUREGISTER, LOC_REGISTER:
+ begin
+ src1 := left.location.register;
+ location.register := src1;
+ end;
+ LOC_CFPUREGISTER, LOC_CREGISTER:
+ begin
+ src1 := left.location.register;
+ if left.location.loc = LOC_CREGISTER then
+ location.register := cg.getintregister(current_asmdata.CurrAsmList,OS_INT)
+ else
+ location.register := cg.getfpuregister(current_asmdata.CurrAsmList,location.size);
+ end;
+ LOC_REFERENCE,LOC_CREFERENCE:
+ begin
+ if (left.resultdef.typ=floatdef) then
+ begin
+ src1 := cg.getfpuregister(current_asmdata.CurrAsmList,def_cgsize(left.resultdef));
+ location.register := src1;
+ cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,
+ left.location.size,left.location.size,
+ left.location.reference,src1);
+ end
+ else
+ begin
+ src1 := cg.getintregister(current_asmdata.CurrAsmList,OS_32);
+ location.register:= src1;
+ cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_32,OS_32,
+ left.location.reference,src1);
+ end;
+ end;
+ end;
+ { choose appropriate operand }
+ if left.resultdef.typ <> floatdef then
+ begin
+ if not(cs_check_overflow in current_settings.localswitches) then
+ op := A_NEG
+ else
+ op := A_NEGO_;
+ location.loc := LOC_REGISTER;
+ end
+ else
+ begin
+ op := A_FNEG;
+ location.loc := LOC_FPUREGISTER;
+ end;
+ { emit operation }
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op,location.register,src1));
+ end;
+{ Here was a problem... }
+{ Operand to be negated always }
+{ seems to be converted to signed }
+{ 32-bit before doing neg!! }
+{ So this is useless... }
+{ that's not true: -2^31 gives an overflow error if it is negated (FK) }
+ cg.g_overflowcheck(current_asmdata.CurrAsmList,location,resultdef);
+ end;
+
+
+{*****************************************************************************
+ TPPCNOTNODE
+*****************************************************************************}
+
+ procedure tppcnotnode.pass_generate_code;
+
+ var
+ hl : tasmlabel;
+ tmpreg: tregister;
+ begin
+ if is_boolean(resultdef) then
+ begin
+ { if the location is LOC_JUMP, we do the secondpass after the
+ labels are allocated
+ }
+ if left.expectloc=LOC_JUMP then
+ begin
+ hl:=current_procinfo.CurrTrueLabel;
+ current_procinfo.CurrTrueLabel:=current_procinfo.CurrFalseLabel;
+ current_procinfo.CurrFalseLabel:=hl;
+ secondpass(left);
+ maketojumpbool(current_asmdata.CurrAsmList,left,lr_load_regvars);
+ hl:=current_procinfo.CurrTrueLabel;
+ current_procinfo.CurrTrueLabel:=current_procinfo.CurrFalseLabel;
+ current_procinfo.CurrFalseLabel:=hl;
+ location.loc:=LOC_JUMP;
+ end
+ else
+ begin
+ secondpass(left);
+ case left.location.loc of
+ LOC_FLAGS :
+ begin
+ location_copy(location,left.location);
+ inverse_flags(location.resflags);
+ end;
+ LOC_REGISTER, LOC_CREGISTER,
+ LOC_REFERENCE, LOC_CREFERENCE,
+ LOC_SUBSETREG, LOC_CSUBSETREG,
+ LOC_SUBSETREF, LOC_CSUBSETREF:
+ begin
+ location_force_reg(current_asmdata.CurrAsmList,left.location,def_cgsize(left.resultdef),true);
+ tmpreg:=left.location.register;
+{$ifndef cpu64bitalu}
+ { 64 bit pascal booleans have their truth value stored in
+ the lower 32 bits; with cbools, it can be anywhere }
+ if (left.location.size in [OS_64,OS_S64]) and
+ not is_pasbool(left.resultdef) then
+ begin
+ tmpreg:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
+ cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,OP_OR,OS_32,left.location.register64.reglo,left.location.register64.reghi,tmpreg);
+ end;
+{$endif not cpu64bitalu}
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_CMPWI,tmpreg,0));
+ location_reset(location,LOC_FLAGS,OS_NO);
+ location.resflags.cr:=RS_CR0;
+ location.resflags.flag:=F_EQ;
+ end;
+ else
+ internalerror(2003042401);
+ end;
+ end;
+ end
+ else if is_64bitint(left.resultdef) then
+ begin
+ secondpass(left);
+ location_force_reg(current_asmdata.CurrAsmList,left.location,def_cgsize(left.resultdef),false);
+ location_copy(location,left.location);
+ { perform the NOT operation }
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_NOT,location.register64.reghi,
+ location.register64.reghi));
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_NOT,location.register64.reglo,
+ location.register64.reglo));
+ end
+ else
+ begin
+ secondpass(left);
+ location_force_reg(current_asmdata.CurrAsmList,left.location,def_cgsize(left.resultdef),true);
+ location_copy(location,left.location);
+ location.loc := LOC_REGISTER;
+ location.register := cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+ { perform the NOT operation }
+ cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_NOT,def_cgsize(resultdef),left.location.register,
+ location.register);
+ end;
+ end;
+
+begin
+ cmoddivnode:=tppcmoddivnode;
+ cshlshrnode:=tppcshlshrnode;
+ cunaryminusnode:=tppcunaryminusnode;
+ cnotnode:=tppcnotnode;
+end.
diff --git a/closures/compiler/powerpc/ppcins.dat b/closures/compiler/powerpc/ppcins.dat
new file mode 100644
index 0000000000..43ec86b907
--- /dev/null
+++ b/closures/compiler/powerpc/ppcins.dat
@@ -0,0 +1,68 @@
+;****************************************************************************
+;
+; Copyright (c) 2002 by Florian Klaempfl
+;
+; Instruction template table for the PowerPC
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+;
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program; if not, write to the Free Software
+; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+;
+;****************************************************************************
+;
+add rD,rA,rB opcode=31,op22=266,oe=0,rc=0
+add_ rD,rA,rB opcode=31,op22=266,oe=0,rc=1
+addo rD,rA,rB opcode=31,op22=266,oe=1,rc=0
+addo_ rD,rA,rB opcode=31,op22=266,oe=1,rc=1
+addc rD,rA,rB opcode=31,op22=10,oe=0,rc=0
+addc_ rD,rA,rB opcode=31,op22=10,oe=0,rc=1
+addco rD,rA,rB opcode=31,op22=10,oe=1,rc=0
+addco_ rD,rA,rB opcode=31,op22=10,oe=1,rc=1
+adde rD,rA,rB opcode=31,op22=138,oe=0,rc=0
+adde_ rD,rA,rB opcode=31,op22=138,oe=0,rc=1
+addeo rD,rA,rB opcode=31,op22=138,oe=1,rc=0
+addeo_ rD,rA,rB opcode=31,op22=138,oe=1,rc=1
+addi rD,rA,SIMM opcode=14
+addic rD,rA,SIMM opcode=12
+addic_ rD,rA,SIMM opcode=13
+addis rD,rA,SIMM opcode=15
+addme rD,rA opcode=31,op22=234,oe=0,rc=0,reserved=$000f0000
+addme_ rD,rA opcode=31,op22=234,oe=0,rc=1,reserved=$000f0000
+addmeo rD,rA opcode=31,op22=234,oe=1,rc=0,reserved=$000f0000
+addmeo_ rD,rA opcode=31,op22=234,oe=1,rc=1,reserved=$000f0000
+addze rD,rA opcode=31,op22=202,oe=0,rc=0,reserved=$000f0000
+addze_ rD,rA opcode=31,op22=202,oe=0,rc=1,reserved=$000f0000
+addzeo rD,rA opcode=31,op22=202,oe=1,rc=0,reserved=$000f0000
+addzeo_ rD,rA opcode=31,op22=202,oe=1,rc=1,reserved=$000f0000
+and rA,rS,rB opcode=31,op21=28,rc=0
+and_ rA,rS,rB opcode=31,op21=28,rc=1
+andc rA,rS,rB opcode=31,op21=60,rc=0
+andc_ rA,rS,rB opcode=31,op21=60,rc=1
+andi_ rA,rS,UIMM opcode=28
+andis_ rA,rS,UIMM opcode=29
+b TA24 opcode=18,aa=0,lk=0
+ba TA24 opcode=18,aa=1,lk=0
+bl TA24 opcode=18,aa=0,lk=1
+bla TA24 opcode=18,aa=1,lk=1
+bc BO,BI,TA14 opcode=16,aa=0,lk=0
+bca BO,BI,TA14 opcode=16,aa=1,lk=0
+bcl BO,BI,TA14 opcode=16,aa=0,lk=1
+bcla BO,BI,TA14 opcode=16,aa=1,lk=1
+bcctr BO,BI opcode=19,op21=528,lk=0,reserved=$000f0000
+bcctrl BO,BI opcode=19,op21=528,lk=1,reserved=$000f0000
+bcltr BO,BI opcode=19,op21=16,lk=0,reserved=$000f0000
+bcltrl BO,BI opcode=19,op21=16,lk=1,reserved=$000f0000
+cmp crfD,L,rA,rB opcode=31,op21=0,reserved=$80000200
+cmpi crfD,L,rA,SIMM opcode=11,reserved=$00000200
+cmpl crfD,L,rA,rB opcode=31,op21=32,reserved=$80000200
+cmpli crfD,L,rA,UIMM opcode=10,reserved=$00000200
diff --git a/closures/compiler/powerpc/ppcreg.dat b/closures/compiler/powerpc/ppcreg.dat
new file mode 100644
index 0000000000..92322e30c9
--- /dev/null
+++ b/closures/compiler/powerpc/ppcreg.dat
@@ -0,0 +1,120 @@
+;
+; PowerPC registers
+;
+; layout
+; <name>,<value>,<stdname>,<gasname>,<gasshortname>,<motname>,<stabidx>
+;
+NO,$00,$00,INVALID,INVALID,INVALID,INVALID,-1,-1
+
+R0,$01,$00,r0,r0,0,r0,0,0
+R1,$01,$01,r1,r1,1,r1,1,1
+R2,$01,$02,r2,r2,2,r2,2,2
+R3,$01,$03,r3,r3,3,r3,3,3
+R4,$01,$04,r4,r4,4,r4,4,4
+R5,$01,$05,r5,r5,5,r5,5,5
+R6,$01,$06,r6,r6,6,r6,6,6
+R7,$01,$07,r7,r7,7,r7,7,7
+R8,$01,$08,r8,r8,8,r8,8,8
+R9,$01,$09,r9,r9,9,r9,9,9
+R10,$01,$0a,r10,r10,10,r10,10,10
+R11,$01,$0b,r11,r11,11,r11,11,11
+R12,$01,$0c,r12,r12,12,r12,12,12
+R13,$01,$0d,r13,r13,13,r13,13,13
+R14,$01,$0e,r14,r14,14,r14,14,14
+R15,$01,$0f,r15,r15,15,r15,15,15
+R16,$01,$10,r16,r16,16,r16,16,16
+R17,$01,$11,r17,r17,17,r17,17,17
+R18,$01,$12,r18,r18,18,r18,18,18
+R19,$01,$13,r19,r19,19,r19,19,19
+R20,$01,$14,r20,r20,20,r20,20,20
+R21,$01,$15,r21,r21,21,r21,21,21
+R22,$01,$16,r22,r22,22,r22,22,22
+R23,$01,$17,r23,r23,23,r23,23,23
+R24,$01,$18,r24,r24,24,r24,24,24
+R25,$01,$19,r25,r25,25,r25,25,25
+R26,$01,$1a,r26,r26,26,r26,26,26
+R27,$01,$1b,r27,r27,27,r27,27,27
+R28,$01,$1c,r28,r28,28,r28,28,28
+R29,$01,$1d,r29,r29,29,r29,29,29
+R30,$01,$1e,r30,r30,30,r30,30,30
+R31,$01,$1f,r31,r31,31,r31,31,31
+
+F0,$02,$00,F0,f0,0,F0,32,32
+F1,$02,$01,F1,f1,1,F1,33,33
+F2,$02,$02,F2,f2,2,F2,34,34
+F3,$02,$03,F3,f3,3,F3,35,35
+F4,$02,$04,F4,f4,4,F4,36,36
+F5,$02,$05,F5,f5,5,F5,37,37
+F6,$02,$06,F6,f6,6,F6,38,38
+F7,$02,$07,F7,f7,7,F7,39,39
+F8,$02,$08,F8,f8,8,F8,40,40
+F9,$02,$09,F9,f9,9,F9,41,41
+F10,$02,$0a,F10,f10,10,F10,42,42
+F11,$02,$0b,F11,f11,11,F11,43,43
+F12,$02,$0c,F12,f12,12,F12,44,44
+F13,$02,$0d,F13,f13,13,F13,45,45
+F14,$02,$0e,F14,f14,14,F14,46,46
+F15,$02,$0f,F15,f15,15,F15,47,47
+F16,$02,$10,F16,f16,16,F16,48,48
+F17,$02,$11,F17,f17,17,F17,49,49
+F18,$02,$12,F18,f18,18,F18,50,50
+F19,$02,$13,F19,f19,19,F19,51,51
+F20,$02,$14,F20,f20,20,F20,52,52
+F21,$02,$15,F21,f21,21,F21,53,53
+F22,$02,$16,F22,f22,22,F22,54,54
+F23,$02,$17,F23,f23,23,F23,55,55
+F24,$02,$18,F24,f24,24,F24,56,56
+F25,$02,$19,F25,f25,25,F25,57,57
+F26,$02,$1a,F26,f26,26,F26,58,58
+F27,$02,$1b,F27,f27,27,F27,59,59
+F28,$02,$1c,F28,f28,28,F28,60,60
+F29,$02,$1d,F29,f29,29,F29,61,61
+F30,$02,$1e,F30,f30,30,F30,62,62
+F31,$02,$1f,F31,f31,31,F31,63,63
+
+M0,$03,$00,M0,v0,0,M0,-1,-1
+M1,$03,$01,M1,v1,1,M1,-1,-1
+M2,$03,$02,M2,v2,2,M2,-1,-1
+M3,$03,$03,M3,v3,3,M3,-1,-1
+M4,$03,$04,M4,v4,4,M4,-1,-1
+M5,$03,$05,M5,v5,5,M5,-1,-1
+M6,$03,$06,M6,v6,6,M6,-1,-1
+M7,$03,$07,M7,v7,7,M7,-1,-1
+M8,$03,$08,M8,v8,8,M8,-1,-1
+M9,$03,$09,M9,v9,9,M9,-1,-1
+M10,$03,$0a,M10,v10,10,M10,-1,-1
+M11,$03,$0b,M11,v11,11,M11,-1,-1
+M12,$03,$0c,M12,v12,12,M12,-1,-1
+M13,$03,$0d,M13,v13,13,M13,-1,-1
+M14,$03,$0e,M14,v14,14,M14,-1,-1
+M15,$03,$0f,M15,v15,15,M15,-1,-1
+M16,$03,$10,M16,v16,16,M16,-1,-1
+M17,$03,$11,M17,v17,17,M17,-1,-1
+M18,$03,$12,M18,v18,18,M18,-1,-1
+M19,$03,$13,M19,v19,19,M19,-1,-1
+M20,$03,$14,M20,v20,20,M20,-1,-1
+M21,$03,$15,M21,v21,21,M21,-1,-1
+M22,$03,$16,M22,v22,22,M22,-1,-1
+M23,$03,$17,M23,v23,23,M23,-1,-1
+M24,$03,$18,M24,v24,24,M24,-1,-1
+M25,$03,$19,M25,v25,25,M25,-1,-1
+M26,$03,$1a,M26,v26,26,M26,-1,-1
+M27,$03,$1b,M27,v27,27,M27,-1,-1
+M28,$03,$1c,M28,v28,28,M28,-1,-1
+M29,$03,$1d,M29,v29,29,M29,-1,-1
+M30,$03,$1e,M30,v30,30,M30,-1,-1
+M31,$03,$1f,M31,v31,31,M31,-1,-1
+
+CR,$05,$00,CR,cr,cr,CR,-1,-1
+CR0,$05,$01,CR0,cr0,cr0,CR0,68,68
+CR1,$05,$02,CR1,cr1,cr1,CR1,69,69
+CR2,$05,$03,CR2,cr2,cr2,CR2,70,70
+CR3,$05,$04,CR3,cr3,cr3,CR3,71,71
+CR4,$05,$05,CR4,cr4,cr4,CR4,72,72
+CR5,$05,$06,CR5,cr5,cr5,CR5,73,73
+CR6,$05,$07,CR6,cr6,cr6,CR6,74,74
+CR7,$05,$08,CR7,cr7,cr7,CR7,75,75
+XER,$05,$09,XER,xer,xer,XER,76,76
+LR,$05,$0a,LR,lr,lr,LR,65,65
+CTR,$05,$0b,CTR,ctr,ctr,CTR,66,66
+FPSCR,$05,$0c,FPSCR,fpscr,fpscr,FPSCR,-1,-1
diff --git a/closures/compiler/powerpc/rappc.pas b/closures/compiler/powerpc/rappc.pas
new file mode 100644
index 0000000000..4ae4ab8452
--- /dev/null
+++ b/closures/compiler/powerpc/rappc.pas
@@ -0,0 +1,41 @@
+{
+ Copyright (c) 1998-2003 by Carl Eric Codere and Peter Vreman
+
+ Handles the common ppc assembler reader routines
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit rappc;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ aasmbase,aasmtai,aasmdata,aasmcpu,
+ cpubase,rautils,cclasses;
+
+ type
+ TPPCOperand=class(TOperand)
+ end;
+
+ TPPCInstruction=class(TInstruction)
+ end;
+
+ implementation
+
+end.
diff --git a/closures/compiler/powerpc/rappcgas.pas b/closures/compiler/powerpc/rappcgas.pas
new file mode 100644
index 0000000000..1a3ca2a518
--- /dev/null
+++ b/closures/compiler/powerpc/rappcgas.pas
@@ -0,0 +1,799 @@
+{
+ Copyright (c) 1998-2002 by Carl Eric Codere and Peter Vreman
+
+ Does the parsing for the PowerPC GNU AS styled inline assembler.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+Unit rappcgas;
+
+{$i fpcdefs.inc}
+
+ Interface
+
+ uses
+ raatt,rappc;
+
+ type
+ tppcattreader = class(tattreader)
+ function is_asmopcode(const s: string):boolean;override;
+ procedure handleopcode;override;
+ procedure BuildReference(oper : tppcoperand);
+ procedure BuildOperand(oper : tppcoperand);
+ procedure BuildOpCode(instr : tppcinstruction);
+ procedure ReadAt(oper : tppcoperand);
+ procedure ReadSym(oper : tppcoperand);
+ procedure ConvertCalljmp(instr : tppcinstruction);
+ end;
+
+
+ Implementation
+
+ uses
+ { helpers }
+ cutils,
+ { global }
+ globtype,verbose,
+ systems,
+ { aasm }
+ cpubase,aasmbase,aasmtai,aasmdata,aasmcpu,
+ { symtable }
+ symconst,symsym,
+ { parser }
+ procinfo,
+ rabase,rautils,
+ cgbase,cgobj
+ ;
+
+ procedure tppcattreader.ReadSym(oper : tppcoperand);
+ var
+ tempstr, mangledname : string;
+ typesize,l,k : aint;
+ begin
+ tempstr:=actasmpattern;
+ Consume(AS_ID);
+ { typecasting? }
+ if (actasmtoken=AS_LPAREN) and
+ SearchType(tempstr,typesize) then
+ begin
+ oper.hastype:=true;
+ Consume(AS_LPAREN);
+ BuildOperand(oper);
+ Consume(AS_RPAREN);
+ if oper.opr.typ in [OPR_REFERENCE,OPR_LOCAL] then
+ oper.SetSize(typesize,true);
+ end
+ else
+ if not oper.SetupVar(tempstr,false) then
+ Message1(sym_e_unknown_id,tempstr);
+ { record.field ? }
+ if actasmtoken=AS_DOT then
+ begin
+ BuildRecordOffsetSize(tempstr,l,k,mangledname,false);
+ if (mangledname<>'') then
+ Message(asmr_e_invalid_reference_syntax);
+ inc(oper.opr.ref.offset,l);
+ end;
+ end;
+
+
+ procedure tppcattreader.ReadAt(oper : tppcoperand);
+ begin
+ { check for ...@ }
+ if actasmtoken=AS_AT then
+ begin
+ if (oper.opr.ref.symbol=nil) and
+ (oper.opr.ref.offset = 0) then
+ Message(asmr_e_invalid_reference_syntax);
+ Consume(AS_AT);
+ if actasmtoken=AS_ID then
+ begin
+ if upper(actasmpattern)='L' then
+ oper.opr.ref.refaddr:=addr_low
+ else if upper(actasmpattern)='HI' then
+ oper.opr.ref.refaddr:=addr_high
+ else if upper(actasmpattern)='HA' then
+ oper.opr.ref.refaddr:=addr_higha
+ else
+ Message(asmr_e_invalid_reference_syntax);
+ Consume(AS_ID);
+ end
+ else
+ Message(asmr_e_invalid_reference_syntax);
+ end;
+ end;
+
+
+ Procedure tppcattreader.BuildReference(oper : tppcoperand);
+
+ procedure Consume_RParen;
+ begin
+ if actasmtoken <> AS_RPAREN then
+ Begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(true);
+ end
+ else
+ begin
+ Consume(AS_RPAREN);
+ if not (actasmtoken in [AS_COMMA,AS_SEPARATOR,AS_END]) then
+ Begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(true);
+ end;
+ end;
+ end;
+
+ var
+ l : aint;
+ relsym: string;
+ asmsymtyp: tasmsymtype;
+
+ begin
+ Consume(AS_LPAREN);
+ Case actasmtoken of
+ AS_INTNUM,
+ AS_MINUS,
+ AS_PLUS:
+ Begin
+ { offset(offset) is invalid }
+ If oper.opr.Ref.Offset <> 0 Then
+ Begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(true);
+ End
+ Else
+ Begin
+ oper.opr.Ref.Offset:=BuildConstExpression(false,true);
+ Consume(AS_RPAREN);
+ if actasmtoken=AS_AT then
+ ReadAt(oper);
+ end;
+ exit;
+ End;
+ AS_REGISTER: { (reg ... }
+ Begin
+ if ((oper.opr.typ=OPR_REFERENCE) and (oper.opr.ref.base<>NR_NO)) or
+ ((oper.opr.typ=OPR_LOCAL) and (oper.opr.localsym.localloc.loc<>LOC_REGISTER)) then
+ message(asmr_e_cannot_index_relative_var);
+ oper.opr.ref.base:=actasmregister;
+ Consume(AS_REGISTER);
+ { can either be a register or a right parenthesis }
+ { (reg) }
+ if actasmtoken=AS_RPAREN then
+ Begin
+ Consume_RParen;
+ exit;
+ end;
+ { (reg,reg .. }
+ Consume(AS_COMMA);
+ if (actasmtoken=AS_REGISTER) and
+ (oper.opr.Ref.Offset = 0) then
+ Begin
+ oper.opr.ref.index:=actasmregister;
+ Consume(AS_REGISTER);
+ Consume_RParen;
+ end
+ else
+ Begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(false);
+ end;
+ end; {end case }
+ AS_ID:
+ Begin
+ ReadSym(oper);
+ case actasmtoken of
+ AS_PLUS:
+ begin
+ { add a constant expression? }
+ l:=BuildConstExpression(true,true);
+ case oper.opr.typ of
+ OPR_CONSTANT :
+ inc(oper.opr.val,l);
+ OPR_LOCAL :
+ inc(oper.opr.localsymofs,l);
+ OPR_REFERENCE :
+ inc(oper.opr.ref.offset,l);
+ else
+ internalerror(200309202);
+ end;
+ end;
+ AS_MINUS:
+ begin
+ Consume(AS_MINUS);
+ BuildConstSymbolExpression(false,true,false,l,relsym,asmsymtyp);
+ if (relsym<>'') then
+ begin
+ if (oper.opr.typ = OPR_REFERENCE) then
+ oper.opr.ref.relsymbol:=current_asmdata.RefAsmSymbol(relsym)
+ else
+ begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(false);
+ end
+ end
+ else
+ begin
+ case oper.opr.typ of
+ OPR_CONSTANT :
+ dec(oper.opr.val,l);
+ OPR_LOCAL :
+ dec(oper.opr.localsymofs,l);
+ OPR_REFERENCE :
+ dec(oper.opr.ref.offset,l);
+ else
+ internalerror(2007092601);
+ end;
+ end;
+ end;
+ end;
+ Consume(AS_RPAREN);
+ if actasmtoken=AS_AT then
+ ReadAt(oper);
+ End;
+ AS_COMMA: { (, ... can either be scaling, or index }
+ Begin
+ Consume(AS_COMMA);
+ { Index }
+ if (actasmtoken=AS_REGISTER) then
+ Begin
+ oper.opr.ref.index:=actasmregister;
+ Consume(AS_REGISTER);
+ { check for scaling ... }
+ Consume_RParen;
+ end
+ else
+ begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(false);
+ end;
+ end;
+ else
+ Begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(false);
+ end;
+ end;
+ end;
+
+
+ Procedure tppcattreader.BuildOperand(oper : tppcoperand);
+ var
+ expr : string;
+ typesize,l : aint;
+
+
+ procedure AddLabelOperand(hl:tasmlabel);
+ begin
+ if not(actasmtoken in [AS_PLUS,AS_MINUS,AS_LPAREN]) and
+ is_calljmp(actopcode) then
+ begin
+ oper.opr.typ:=OPR_SYMBOL;
+ oper.opr.symbol:=hl;
+ end
+ else
+ begin
+ oper.InitRef;
+ oper.opr.ref.symbol:=hl;
+ end;
+ end;
+
+
+ procedure MaybeRecordOffset;
+ var
+ mangledname: string;
+ hasdot : boolean;
+ l,
+ toffset,
+ tsize : aint;
+ begin
+ if not(actasmtoken in [AS_DOT,AS_PLUS,AS_MINUS]) then
+ exit;
+ l:=0;
+ hasdot:=(actasmtoken=AS_DOT);
+ if hasdot then
+ begin
+ if expr<>'' then
+ begin
+ BuildRecordOffsetSize(expr,toffset,tsize,mangledname,false);
+ if (oper.opr.typ<>OPR_CONSTANT) and
+ (mangledname<>'') then
+ Message(asmr_e_wrong_sym_type);
+ inc(l,toffset);
+ oper.SetSize(tsize,true);
+ end;
+ end;
+ if actasmtoken in [AS_PLUS,AS_MINUS] then
+ inc(l,BuildConstExpression(true,false));
+ case oper.opr.typ of
+ OPR_LOCAL :
+ begin
+ { don't allow direct access to fields of parameters, because that
+ will generate buggy code. Allow it only for explicit typecasting }
+ if hasdot and
+ (not oper.hastype) and
+ (tabstractvarsym(oper.opr.localsym).owner.symtabletype=parasymtable) and
+ (current_procinfo.procdef.proccalloption<>pocall_register) then
+ Message(asmr_e_cannot_access_field_directly_for_parameters);
+ inc(oper.opr.localsymofs,l)
+ end;
+ OPR_CONSTANT :
+ if (mangledname<>'') then
+ begin
+ if (oper.opr.val<>0) then
+ Message(asmr_e_wrong_sym_type);
+ oper.opr.typ:=OPR_SYMBOL;
+ oper.opr.symbol:=current_asmdata.RefAsmSymbol(mangledname);
+ end
+ else
+ inc(oper.opr.val,l);
+ OPR_REFERENCE :
+ inc(oper.opr.ref.offset,l);
+ OPR_SYMBOL:
+ Message(asmr_e_invalid_symbol_ref);
+ else
+ internalerror(200309221);
+ end;
+ end;
+
+
+ function MaybeBuildReference:boolean;
+ { Try to create a reference, if not a reference is found then false
+ is returned }
+ begin
+ MaybeBuildReference:=true;
+ case actasmtoken of
+ AS_INTNUM,
+ AS_MINUS,
+ AS_PLUS:
+ Begin
+ oper.opr.ref.offset:=BuildConstExpression(True,False);
+ if actasmtoken<>AS_LPAREN then
+ Message(asmr_e_invalid_reference_syntax)
+ else
+ BuildReference(oper);
+ end;
+ AS_LPAREN:
+ BuildReference(oper);
+ AS_ID: { only a variable is allowed ... }
+ Begin
+ ReadSym(oper);
+ case actasmtoken of
+ AS_END,
+ AS_SEPARATOR,
+ AS_COMMA: ;
+ AS_LPAREN:
+ BuildReference(oper);
+ else
+ Begin
+ Message(asmr_e_invalid_reference_syntax);
+ Consume(actasmtoken);
+ end;
+ end; {end case }
+ end;
+ else
+ MaybeBuildReference:=false;
+ end; { end case }
+ end;
+
+
+ var
+ tempreg : tregister;
+ hl : tasmlabel;
+ ofs : aint;
+ Begin
+ expr:='';
+ case actasmtoken of
+ AS_LPAREN: { Memory reference or constant expression }
+ Begin
+ oper.InitRef;
+ BuildReference(oper);
+ end;
+
+ AS_INTNUM,
+ AS_MINUS,
+ AS_PLUS:
+ Begin
+ { Constant memory offset }
+ { This must absolutely be followed by ( }
+ oper.InitRef;
+ oper.opr.ref.offset:=BuildConstExpression(True,False);
+ if actasmtoken<>AS_LPAREN then
+ begin
+ ofs:=oper.opr.ref.offset;
+ BuildConstantOperand(oper);
+ inc(oper.opr.val,ofs);
+ end
+ else
+ BuildReference(oper);
+ end;
+
+ AS_ID: { A constant expression, or a Variable ref. }
+ Begin
+ { Local Label ? }
+ if is_locallabel(actasmpattern) then
+ begin
+ CreateLocalLabel(actasmpattern,hl,false);
+ Consume(AS_ID);
+ AddLabelOperand(hl);
+ end
+ else
+ { Check for label }
+ if SearchLabel(actasmpattern,hl,false) then
+ begin
+ Consume(AS_ID);
+ AddLabelOperand(hl);
+ end
+ else
+ { probably a variable or normal expression }
+ { or a procedure (such as in CALL ID) }
+ Begin
+ { is it a constant ? }
+ if SearchIConstant(actasmpattern,l) then
+ Begin
+ if not (oper.opr.typ in [OPR_NONE,OPR_CONSTANT]) then
+ Message(asmr_e_invalid_operand_type);
+ BuildConstantOperand(oper);
+ end
+ else
+ begin
+ expr:=actasmpattern;
+ Consume(AS_ID);
+ { typecasting? }
+ if (actasmtoken=AS_LPAREN) and
+ SearchType(expr,typesize) then
+ begin
+ oper.hastype:=true;
+ Consume(AS_LPAREN);
+ BuildOperand(oper);
+ Consume(AS_RPAREN);
+ if oper.opr.typ in [OPR_REFERENCE,OPR_LOCAL] then
+ oper.SetSize(typesize,true);
+ end
+ else
+ begin
+ if oper.SetupVar(expr,false) then
+ ReadAt(oper)
+ else
+ Begin
+ { look for special symbols ... }
+ if expr= '__HIGH' then
+ begin
+ consume(AS_LPAREN);
+ if not oper.setupvar('high'+actasmpattern,false) then
+ Message1(sym_e_unknown_id,'high'+actasmpattern);
+ consume(AS_ID);
+ consume(AS_RPAREN);
+ end
+ else
+ if expr = '__RESULT' then
+ oper.SetUpResult
+ else
+ if expr = '__SELF' then
+ oper.SetupSelf
+ else
+ if expr = '__OLDEBP' then
+ oper.SetupOldEBP
+ else
+ Message1(sym_e_unknown_id,expr);
+ end;
+ end;
+ end;
+ if actasmtoken=AS_DOT then
+ MaybeRecordOffset;
+ { add a constant expression? }
+ if (actasmtoken=AS_PLUS) then
+ begin
+ l:=BuildConstExpression(true,false);
+ case oper.opr.typ of
+ OPR_CONSTANT :
+ inc(oper.opr.val,l);
+ OPR_LOCAL :
+ inc(oper.opr.localsymofs,l);
+ OPR_REFERENCE :
+ inc(oper.opr.ref.offset,l);
+ else
+ internalerror(200309202);
+ end;
+ end
+ end;
+ { Do we have a indexing reference, then parse it also }
+ if actasmtoken=AS_LPAREN then
+ BuildReference(oper);
+ end;
+
+ AS_REGISTER: { Register, a variable reference or a constant reference }
+ Begin
+ { save the type of register used. }
+ tempreg:=actasmregister;
+ Consume(AS_REGISTER);
+ if (actasmtoken in [AS_END,AS_SEPARATOR,AS_COMMA]) then
+ if is_condreg(tempreg) and
+ ((actopcode = A_BC) or
+ (actopcode = A_BCCTR) or
+ (actopcode = A_BCLR) or
+ (actopcode = A_TW) or
+ (actopcode = A_TWI)) then
+ begin
+ { it isn't a real operand, everything is stored in the condition }
+ oper.opr.typ:=OPR_NONE;
+ actcondition.cr := getsupreg(tempreg);
+ end
+ else
+ begin
+ if not (oper.opr.typ in [OPR_NONE,OPR_REGISTER]) then
+ Message(asmr_e_invalid_operand_type);
+ oper.opr.typ:=OPR_REGISTER;
+ oper.opr.reg:=tempreg;
+ end
+ else if is_condreg(tempreg) then
+ begin
+ if not(actcondition.cond in [C_T..C_DZF]) then
+ Message(asmr_e_syn_operand);
+ if actasmtoken=AS_STAR then
+ begin
+ consume(AS_STAR);
+ if (actasmtoken=AS_INTNUM) then
+ begin
+ consume(AS_INTNUM);
+ if actasmtoken=AS_PLUS then
+ begin
+ consume(AS_PLUS);
+ if (actasmtoken=AS_ID) then
+ begin
+ oper.opr.typ:=OPR_NONE;
+ if actasmpattern='LT' then
+ actcondition.crbit:=(getsupreg(tempreg)-(RS_CR0))*4
+ else if actasmpattern='GT' then
+ actcondition.crbit:=(getsupreg(tempreg)-(RS_CR0))*4+1
+ else if actasmpattern='EQ' then
+ actcondition.crbit:=(getsupreg(tempreg)-(RS_CR0))*4+2
+ else if actasmpattern='SO' then
+ actcondition.crbit:=(getsupreg(tempreg)-(RS_CR0))*4+3
+ else
+ Message(asmr_e_syn_operand);
+ consume(AS_ID);
+ end
+ else
+ Message(asmr_e_syn_operand);
+ end
+ else
+ Message(asmr_e_syn_operand);
+ end
+ else
+ Message(asmr_e_syn_operand);
+ end
+ else
+ Message(asmr_e_syn_operand);
+ end
+ else
+ Message(asmr_e_syn_operand);
+ end;
+ AS_END,
+ AS_SEPARATOR,
+ AS_COMMA: ;
+ else
+ Begin
+ Message(asmr_e_syn_operand);
+ Consume(actasmtoken);
+ end;
+ end; { end case }
+ end;
+
+
+{*****************************************************************************
+ tppcattreader
+*****************************************************************************}
+
+ procedure tppcattreader.BuildOpCode(instr : tppcinstruction);
+ var
+ operandnum : longint;
+ Begin
+ { opcode }
+ if (actasmtoken<>AS_OPCODE) then
+ Begin
+ Message(asmr_e_invalid_or_missing_opcode);
+ RecoverConsume(true);
+ exit;
+ end;
+ { Fill the instr object with the current state }
+ with instr do
+ begin
+ Opcode:=ActOpcode;
+ condition:=ActCondition;
+ end;
+
+ { We are reading operands, so opcode will be an AS_ID }
+ operandnum:=1;
+ Consume(AS_OPCODE);
+ { Zero operand opcode ? }
+ if actasmtoken in [AS_SEPARATOR,AS_END] then
+ begin
+ operandnum:=0;
+ exit;
+ end;
+ { Read the operands }
+ repeat
+ case actasmtoken of
+ AS_COMMA: { Operand delimiter }
+ Begin
+ if operandnum>Max_Operands then
+ Message(asmr_e_too_many_operands)
+ else
+ begin
+ { condition operands doesn't set the operand but write to the
+ condition field of the instruction
+ }
+ if instr.Operands[operandnum].opr.typ<>OPR_NONE then
+ Inc(operandnum);
+ end;
+ Consume(AS_COMMA);
+ end;
+ AS_SEPARATOR,
+ AS_END : { End of asm operands for this opcode }
+ begin
+ break;
+ end;
+ else
+ BuildOperand(instr.Operands[operandnum] as tppcoperand);
+ end; { end case }
+ until false;
+ if (operandnum=1) and (instr.Operands[operandnum].opr.typ=OPR_NONE) then
+ dec(operandnum);
+ instr.Ops:=operandnum;
+ end;
+
+
+ function tppcattreader.is_asmopcode(const s: string):boolean;
+ var
+ cond : tasmcondflag;
+ hs : string;
+
+ Begin
+ { making s a value parameter would break other assembler readers }
+ hs:=s;
+ is_asmopcode:=false;
+
+ { clear op code }
+ actopcode:=A_None;
+ { clear condition }
+ fillchar(actcondition,sizeof(actcondition),0);
+
+ { check for direction hint }
+ if hs[length(s)]='-' then
+ begin
+ dec(ord(hs[0]));
+ actcondition.dirhint:=DH_Minus;
+ end
+ else if hs[length(s)]='+' then
+ begin
+ dec(ord(hs[0]));
+ actcondition.dirhint:=DH_Plus;
+ end;
+ actopcode := tasmop(ptruint(iasmops.find(hs)));
+ if actopcode <> A_NONE then
+ begin
+ if actcondition.dirhint<>DH_None then
+ message1(asmr_e_unknown_opcode,actasmpattern);
+ actasmtoken:=AS_OPCODE;
+ is_asmopcode:=true;
+ exit;
+ end;
+ { not found, check branch instructions }
+ if hs[1]='B' then
+ begin
+ { we can search here without an extra table which is sorted by string length
+ because we take the whole remaining string without the leading B }
+ if copy(hs,length(s)-1,2)='LR' then
+ begin
+ actopcode := A_BCLR;
+ setlength(hs,length(hs)-2)
+ end
+ else if copy(hs,length(s)-2,3)='CTR' then
+ begin
+ actopcode := A_BCCTR;
+ setlength(hs,length(hs)-3)
+ end
+ else
+ actopcode := A_BC;
+ for cond:=low(TAsmCondFlag) to high(TAsmCondFlag) do
+ if copy(hs,2,length(s)-1)=UpperAsmCondFlag2Str[cond] then
+ begin
+ actcondition.simple:=true;
+ actcondition.cond:=cond;
+ if (cond in [C_LT,C_LE,C_EQ,C_GE,C_GT,C_NL,C_NE,C_NG,C_SO,C_NS,C_UN,C_NU]) then
+ actcondition.cr := RS_CR0;
+ actasmtoken:=AS_OPCODE;
+ is_asmopcode:=true;
+ exit;
+ end;
+ end;
+ end;
+
+ procedure tppcattreader.ConvertCalljmp(instr : tppcinstruction);
+ begin
+ if instr.Operands[1].opr.typ = OPR_CONSTANT then
+ begin
+ if (instr.operands[1].opr.val > 31) or
+ (instr.operands[2].opr.typ <> OPR_CONSTANT) or
+ (instr.operands[2].opr.val > 31) or
+ not(instr.operands[3].opr.typ in [OPR_REFERENCE,OPR_SYMBOL]) then
+ Message(asmr_e_syn_operand);
+ { BO/BI notation }
+ instr.condition.simple := false;
+ instr.condition.bo := instr.operands[1].opr.val;
+ instr.condition.bi := instr.operands[2].opr.val;
+ instr.operands[1].free;
+ instr.operands[2].free;
+ instr.operands[2] := nil;
+ instr.operands[1] := instr.operands[3];
+ instr.operands[3] := nil;
+ instr.ops := 1;
+ end;
+ if instr.Operands[1].opr.typ = OPR_REFERENCE then
+ begin
+ instr.Operands[1].opr.ref.refaddr:=addr_full;
+ if (instr.Operands[1].opr.ref.base<>NR_NO) or
+ (instr.Operands[1].opr.ref.index<>NR_NO) then
+ Message(asmr_e_syn_operand);
+ end;
+ end;
+
+
+ procedure tppcattreader.handleopcode;
+ var
+ instr : tppcinstruction;
+ begin
+ instr:=TPPCInstruction.Create(TPPCOperand);
+ BuildOpcode(instr);
+ instr.condition := actcondition;
+ if is_calljmp(instr.opcode) then
+ ConvertCalljmp(instr);
+ {
+ instr.AddReferenceSizes;
+ instr.SetInstructionOpsize;
+ instr.CheckOperandSizes;
+ }
+ instr.ConcatInstruction(curlist);
+ instr.Free;
+ end;
+
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+const
+ asmmode_ppc_att_info : tasmmodeinfo =
+ (
+ id : asmmode_ppc_gas;
+ idtxt : 'GAS';
+ casmreader : tppcattreader;
+ );
+
+ asmmode_ppc_standard_info : tasmmodeinfo =
+ (
+ id : asmmode_standard;
+ idtxt : 'STANDARD';
+ casmreader : tppcattreader;
+ );
+
+initialization
+ RegisterAsmMode(asmmode_ppc_att_info);
+ RegisterAsmMode(asmmode_ppc_standard_info);
+end.
diff --git a/closures/compiler/powerpc/rppccon.inc b/closures/compiler/powerpc/rppccon.inc
new file mode 100644
index 0000000000..4ff6799228
--- /dev/null
+++ b/closures/compiler/powerpc/rppccon.inc
@@ -0,0 +1,111 @@
+{ don't edit, this file is generated from ppcreg.dat }
+NR_NO = tregister($00000000);
+NR_R0 = tregister($01000000);
+NR_R1 = tregister($01000001);
+NR_R2 = tregister($01000002);
+NR_R3 = tregister($01000003);
+NR_R4 = tregister($01000004);
+NR_R5 = tregister($01000005);
+NR_R6 = tregister($01000006);
+NR_R7 = tregister($01000007);
+NR_R8 = tregister($01000008);
+NR_R9 = tregister($01000009);
+NR_R10 = tregister($0100000a);
+NR_R11 = tregister($0100000b);
+NR_R12 = tregister($0100000c);
+NR_R13 = tregister($0100000d);
+NR_R14 = tregister($0100000e);
+NR_R15 = tregister($0100000f);
+NR_R16 = tregister($01000010);
+NR_R17 = tregister($01000011);
+NR_R18 = tregister($01000012);
+NR_R19 = tregister($01000013);
+NR_R20 = tregister($01000014);
+NR_R21 = tregister($01000015);
+NR_R22 = tregister($01000016);
+NR_R23 = tregister($01000017);
+NR_R24 = tregister($01000018);
+NR_R25 = tregister($01000019);
+NR_R26 = tregister($0100001a);
+NR_R27 = tregister($0100001b);
+NR_R28 = tregister($0100001c);
+NR_R29 = tregister($0100001d);
+NR_R30 = tregister($0100001e);
+NR_R31 = tregister($0100001f);
+NR_F0 = tregister($02000000);
+NR_F1 = tregister($02000001);
+NR_F2 = tregister($02000002);
+NR_F3 = tregister($02000003);
+NR_F4 = tregister($02000004);
+NR_F5 = tregister($02000005);
+NR_F6 = tregister($02000006);
+NR_F7 = tregister($02000007);
+NR_F8 = tregister($02000008);
+NR_F9 = tregister($02000009);
+NR_F10 = tregister($0200000a);
+NR_F11 = tregister($0200000b);
+NR_F12 = tregister($0200000c);
+NR_F13 = tregister($0200000d);
+NR_F14 = tregister($0200000e);
+NR_F15 = tregister($0200000f);
+NR_F16 = tregister($02000010);
+NR_F17 = tregister($02000011);
+NR_F18 = tregister($02000012);
+NR_F19 = tregister($02000013);
+NR_F20 = tregister($02000014);
+NR_F21 = tregister($02000015);
+NR_F22 = tregister($02000016);
+NR_F23 = tregister($02000017);
+NR_F24 = tregister($02000018);
+NR_F25 = tregister($02000019);
+NR_F26 = tregister($0200001a);
+NR_F27 = tregister($0200001b);
+NR_F28 = tregister($0200001c);
+NR_F29 = tregister($0200001d);
+NR_F30 = tregister($0200001e);
+NR_F31 = tregister($0200001f);
+NR_M0 = tregister($03000000);
+NR_M1 = tregister($03000001);
+NR_M2 = tregister($03000002);
+NR_M3 = tregister($03000003);
+NR_M4 = tregister($03000004);
+NR_M5 = tregister($03000005);
+NR_M6 = tregister($03000006);
+NR_M7 = tregister($03000007);
+NR_M8 = tregister($03000008);
+NR_M9 = tregister($03000009);
+NR_M10 = tregister($0300000a);
+NR_M11 = tregister($0300000b);
+NR_M12 = tregister($0300000c);
+NR_M13 = tregister($0300000d);
+NR_M14 = tregister($0300000e);
+NR_M15 = tregister($0300000f);
+NR_M16 = tregister($03000010);
+NR_M17 = tregister($03000011);
+NR_M18 = tregister($03000012);
+NR_M19 = tregister($03000013);
+NR_M20 = tregister($03000014);
+NR_M21 = tregister($03000015);
+NR_M22 = tregister($03000016);
+NR_M23 = tregister($03000017);
+NR_M24 = tregister($03000018);
+NR_M25 = tregister($03000019);
+NR_M26 = tregister($0300001a);
+NR_M27 = tregister($0300001b);
+NR_M28 = tregister($0300001c);
+NR_M29 = tregister($0300001d);
+NR_M30 = tregister($0300001e);
+NR_M31 = tregister($0300001f);
+NR_CR = tregister($05000000);
+NR_CR0 = tregister($05000001);
+NR_CR1 = tregister($05000002);
+NR_CR2 = tregister($05000003);
+NR_CR3 = tregister($05000004);
+NR_CR4 = tregister($05000005);
+NR_CR5 = tregister($05000006);
+NR_CR6 = tregister($05000007);
+NR_CR7 = tregister($05000008);
+NR_XER = tregister($05000009);
+NR_LR = tregister($0500000a);
+NR_CTR = tregister($0500000b);
+NR_FPSCR = tregister($0500000c);
diff --git a/closures/compiler/powerpc/rppcdwrf.inc b/closures/compiler/powerpc/rppcdwrf.inc
new file mode 100644
index 0000000000..2c9c9942a8
--- /dev/null
+++ b/closures/compiler/powerpc/rppcdwrf.inc
@@ -0,0 +1,111 @@
+{ don't edit, this file is generated from ppcreg.dat }
+-1,
+0,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+8,
+9,
+10,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+20,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+31,
+32,
+33,
+34,
+35,
+36,
+37,
+38,
+39,
+40,
+41,
+42,
+43,
+44,
+45,
+46,
+47,
+48,
+49,
+50,
+51,
+52,
+53,
+54,
+55,
+56,
+57,
+58,
+59,
+60,
+61,
+62,
+63,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+68,
+69,
+70,
+71,
+72,
+73,
+74,
+75,
+76,
+65,
+66,
+-1
diff --git a/closures/compiler/powerpc/rppcgas.inc b/closures/compiler/powerpc/rppcgas.inc
new file mode 100644
index 0000000000..3c68549ce1
--- /dev/null
+++ b/closures/compiler/powerpc/rppcgas.inc
@@ -0,0 +1,111 @@
+{ don't edit, this file is generated from ppcreg.dat }
+'INVALID',
+'r0',
+'r1',
+'r2',
+'r3',
+'r4',
+'r5',
+'r6',
+'r7',
+'r8',
+'r9',
+'r10',
+'r11',
+'r12',
+'r13',
+'r14',
+'r15',
+'r16',
+'r17',
+'r18',
+'r19',
+'r20',
+'r21',
+'r22',
+'r23',
+'r24',
+'r25',
+'r26',
+'r27',
+'r28',
+'r29',
+'r30',
+'r31',
+'f0',
+'f1',
+'f2',
+'f3',
+'f4',
+'f5',
+'f6',
+'f7',
+'f8',
+'f9',
+'f10',
+'f11',
+'f12',
+'f13',
+'f14',
+'f15',
+'f16',
+'f17',
+'f18',
+'f19',
+'f20',
+'f21',
+'f22',
+'f23',
+'f24',
+'f25',
+'f26',
+'f27',
+'f28',
+'f29',
+'f30',
+'f31',
+'v0',
+'v1',
+'v2',
+'v3',
+'v4',
+'v5',
+'v6',
+'v7',
+'v8',
+'v9',
+'v10',
+'v11',
+'v12',
+'v13',
+'v14',
+'v15',
+'v16',
+'v17',
+'v18',
+'v19',
+'v20',
+'v21',
+'v22',
+'v23',
+'v24',
+'v25',
+'v26',
+'v27',
+'v28',
+'v29',
+'v30',
+'v31',
+'cr',
+'cr0',
+'cr1',
+'cr2',
+'cr3',
+'cr4',
+'cr5',
+'cr6',
+'cr7',
+'xer',
+'lr',
+'ctr',
+'fpscr'
diff --git a/closures/compiler/powerpc/rppcgri.inc b/closures/compiler/powerpc/rppcgri.inc
new file mode 100644
index 0000000000..b26f900caa
--- /dev/null
+++ b/closures/compiler/powerpc/rppcgri.inc
@@ -0,0 +1,111 @@
+{ don't edit, this file is generated from ppcreg.dat }
+0,
+97,
+98,
+99,
+100,
+101,
+102,
+103,
+104,
+105,
+108,
+33,
+34,
+43,
+44,
+45,
+46,
+47,
+48,
+49,
+50,
+51,
+52,
+35,
+53,
+54,
+55,
+56,
+57,
+58,
+59,
+60,
+61,
+62,
+36,
+63,
+64,
+37,
+38,
+39,
+40,
+41,
+42,
+109,
+107,
+1,
+2,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+20,
+3,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+4,
+31,
+32,
+5,
+6,
+7,
+8,
+9,
+10,
+65,
+66,
+75,
+76,
+77,
+78,
+79,
+80,
+81,
+82,
+83,
+84,
+67,
+85,
+86,
+87,
+88,
+89,
+90,
+91,
+92,
+93,
+94,
+68,
+95,
+96,
+69,
+70,
+71,
+72,
+73,
+74,
+106
diff --git a/closures/compiler/powerpc/rppcgss.inc b/closures/compiler/powerpc/rppcgss.inc
new file mode 100644
index 0000000000..5d5aa809d8
--- /dev/null
+++ b/closures/compiler/powerpc/rppcgss.inc
@@ -0,0 +1,111 @@
+{ don't edit, this file is generated from ppcreg.dat }
+'INVALID',
+'0',
+'1',
+'2',
+'3',
+'4',
+'5',
+'6',
+'7',
+'8',
+'9',
+'10',
+'11',
+'12',
+'13',
+'14',
+'15',
+'16',
+'17',
+'18',
+'19',
+'20',
+'21',
+'22',
+'23',
+'24',
+'25',
+'26',
+'27',
+'28',
+'29',
+'30',
+'31',
+'0',
+'1',
+'2',
+'3',
+'4',
+'5',
+'6',
+'7',
+'8',
+'9',
+'10',
+'11',
+'12',
+'13',
+'14',
+'15',
+'16',
+'17',
+'18',
+'19',
+'20',
+'21',
+'22',
+'23',
+'24',
+'25',
+'26',
+'27',
+'28',
+'29',
+'30',
+'31',
+'0',
+'1',
+'2',
+'3',
+'4',
+'5',
+'6',
+'7',
+'8',
+'9',
+'10',
+'11',
+'12',
+'13',
+'14',
+'15',
+'16',
+'17',
+'18',
+'19',
+'20',
+'21',
+'22',
+'23',
+'24',
+'25',
+'26',
+'27',
+'28',
+'29',
+'30',
+'31',
+'cr',
+'cr0',
+'cr1',
+'cr2',
+'cr3',
+'cr4',
+'cr5',
+'cr6',
+'cr7',
+'xer',
+'lr',
+'ctr',
+'fpscr'
diff --git a/closures/compiler/powerpc/rppcmot.inc b/closures/compiler/powerpc/rppcmot.inc
new file mode 100644
index 0000000000..4fc340afd7
--- /dev/null
+++ b/closures/compiler/powerpc/rppcmot.inc
@@ -0,0 +1,111 @@
+{ don't edit, this file is generated from ppcreg.dat }
+'INVALID',
+'r0',
+'r1',
+'r2',
+'r3',
+'r4',
+'r5',
+'r6',
+'r7',
+'r8',
+'r9',
+'r10',
+'r11',
+'r12',
+'r13',
+'r14',
+'r15',
+'r16',
+'r17',
+'r18',
+'r19',
+'r20',
+'r21',
+'r22',
+'r23',
+'r24',
+'r25',
+'r26',
+'r27',
+'r28',
+'r29',
+'r30',
+'r31',
+'F0',
+'F1',
+'F2',
+'F3',
+'F4',
+'F5',
+'F6',
+'F7',
+'F8',
+'F9',
+'F10',
+'F11',
+'F12',
+'F13',
+'F14',
+'F15',
+'F16',
+'F17',
+'F18',
+'F19',
+'F20',
+'F21',
+'F22',
+'F23',
+'F24',
+'F25',
+'F26',
+'F27',
+'F28',
+'F29',
+'F30',
+'F31',
+'M0',
+'M1',
+'M2',
+'M3',
+'M4',
+'M5',
+'M6',
+'M7',
+'M8',
+'M9',
+'M10',
+'M11',
+'M12',
+'M13',
+'M14',
+'M15',
+'M16',
+'M17',
+'M18',
+'M19',
+'M20',
+'M21',
+'M22',
+'M23',
+'M24',
+'M25',
+'M26',
+'M27',
+'M28',
+'M29',
+'M30',
+'M31',
+'CR',
+'CR0',
+'CR1',
+'CR2',
+'CR3',
+'CR4',
+'CR5',
+'CR6',
+'CR7',
+'XER',
+'LR',
+'CTR',
+'FPSCR'
diff --git a/closures/compiler/powerpc/rppcmri.inc b/closures/compiler/powerpc/rppcmri.inc
new file mode 100644
index 0000000000..9a59178c7d
--- /dev/null
+++ b/closures/compiler/powerpc/rppcmri.inc
@@ -0,0 +1,111 @@
+{ don't edit, this file is generated from ppcreg.dat }
+97,
+98,
+99,
+100,
+101,
+102,
+103,
+104,
+105,
+108,
+33,
+34,
+43,
+44,
+45,
+46,
+47,
+48,
+49,
+50,
+51,
+52,
+35,
+53,
+54,
+55,
+56,
+57,
+58,
+59,
+60,
+61,
+62,
+36,
+63,
+64,
+37,
+38,
+39,
+40,
+41,
+42,
+109,
+0,
+107,
+65,
+66,
+75,
+76,
+77,
+78,
+79,
+80,
+81,
+82,
+83,
+84,
+67,
+85,
+86,
+87,
+88,
+89,
+90,
+91,
+92,
+93,
+94,
+68,
+95,
+96,
+69,
+70,
+71,
+72,
+73,
+74,
+106,
+1,
+2,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+20,
+3,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+4,
+31,
+32,
+5,
+6,
+7,
+8,
+9,
+10
diff --git a/closures/compiler/powerpc/rppcnor.inc b/closures/compiler/powerpc/rppcnor.inc
new file mode 100644
index 0000000000..387be62acb
--- /dev/null
+++ b/closures/compiler/powerpc/rppcnor.inc
@@ -0,0 +1,2 @@
+{ don't edit, this file is generated from ppcreg.dat }
+110
diff --git a/closures/compiler/powerpc/rppcnum.inc b/closures/compiler/powerpc/rppcnum.inc
new file mode 100644
index 0000000000..d612e34d8a
--- /dev/null
+++ b/closures/compiler/powerpc/rppcnum.inc
@@ -0,0 +1,111 @@
+{ don't edit, this file is generated from ppcreg.dat }
+tregister($00000000),
+tregister($01000000),
+tregister($01000001),
+tregister($01000002),
+tregister($01000003),
+tregister($01000004),
+tregister($01000005),
+tregister($01000006),
+tregister($01000007),
+tregister($01000008),
+tregister($01000009),
+tregister($0100000a),
+tregister($0100000b),
+tregister($0100000c),
+tregister($0100000d),
+tregister($0100000e),
+tregister($0100000f),
+tregister($01000010),
+tregister($01000011),
+tregister($01000012),
+tregister($01000013),
+tregister($01000014),
+tregister($01000015),
+tregister($01000016),
+tregister($01000017),
+tregister($01000018),
+tregister($01000019),
+tregister($0100001a),
+tregister($0100001b),
+tregister($0100001c),
+tregister($0100001d),
+tregister($0100001e),
+tregister($0100001f),
+tregister($02000000),
+tregister($02000001),
+tregister($02000002),
+tregister($02000003),
+tregister($02000004),
+tregister($02000005),
+tregister($02000006),
+tregister($02000007),
+tregister($02000008),
+tregister($02000009),
+tregister($0200000a),
+tregister($0200000b),
+tregister($0200000c),
+tregister($0200000d),
+tregister($0200000e),
+tregister($0200000f),
+tregister($02000010),
+tregister($02000011),
+tregister($02000012),
+tregister($02000013),
+tregister($02000014),
+tregister($02000015),
+tregister($02000016),
+tregister($02000017),
+tregister($02000018),
+tregister($02000019),
+tregister($0200001a),
+tregister($0200001b),
+tregister($0200001c),
+tregister($0200001d),
+tregister($0200001e),
+tregister($0200001f),
+tregister($03000000),
+tregister($03000001),
+tregister($03000002),
+tregister($03000003),
+tregister($03000004),
+tregister($03000005),
+tregister($03000006),
+tregister($03000007),
+tregister($03000008),
+tregister($03000009),
+tregister($0300000a),
+tregister($0300000b),
+tregister($0300000c),
+tregister($0300000d),
+tregister($0300000e),
+tregister($0300000f),
+tregister($03000010),
+tregister($03000011),
+tregister($03000012),
+tregister($03000013),
+tregister($03000014),
+tregister($03000015),
+tregister($03000016),
+tregister($03000017),
+tregister($03000018),
+tregister($03000019),
+tregister($0300001a),
+tregister($0300001b),
+tregister($0300001c),
+tregister($0300001d),
+tregister($0300001e),
+tregister($0300001f),
+tregister($05000000),
+tregister($05000001),
+tregister($05000002),
+tregister($05000003),
+tregister($05000004),
+tregister($05000005),
+tregister($05000006),
+tregister($05000007),
+tregister($05000008),
+tregister($05000009),
+tregister($0500000a),
+tregister($0500000b),
+tregister($0500000c)
diff --git a/closures/compiler/powerpc/rppcrni.inc b/closures/compiler/powerpc/rppcrni.inc
new file mode 100644
index 0000000000..1a49189c1d
--- /dev/null
+++ b/closures/compiler/powerpc/rppcrni.inc
@@ -0,0 +1,111 @@
+{ don't edit, this file is generated from ppcreg.dat }
+0,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+8,
+9,
+10,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+20,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+31,
+32,
+33,
+34,
+35,
+36,
+37,
+38,
+39,
+40,
+41,
+42,
+43,
+44,
+45,
+46,
+47,
+48,
+49,
+50,
+51,
+52,
+53,
+54,
+55,
+56,
+57,
+58,
+59,
+60,
+61,
+62,
+63,
+64,
+65,
+66,
+67,
+68,
+69,
+70,
+71,
+72,
+73,
+74,
+75,
+76,
+77,
+78,
+79,
+80,
+81,
+82,
+83,
+84,
+85,
+86,
+87,
+88,
+89,
+90,
+91,
+92,
+93,
+94,
+95,
+96,
+97,
+98,
+99,
+100,
+101,
+102,
+103,
+104,
+105,
+106,
+107,
+108,
+109
diff --git a/closures/compiler/powerpc/rppcsri.inc b/closures/compiler/powerpc/rppcsri.inc
new file mode 100644
index 0000000000..9a59178c7d
--- /dev/null
+++ b/closures/compiler/powerpc/rppcsri.inc
@@ -0,0 +1,111 @@
+{ don't edit, this file is generated from ppcreg.dat }
+97,
+98,
+99,
+100,
+101,
+102,
+103,
+104,
+105,
+108,
+33,
+34,
+43,
+44,
+45,
+46,
+47,
+48,
+49,
+50,
+51,
+52,
+35,
+53,
+54,
+55,
+56,
+57,
+58,
+59,
+60,
+61,
+62,
+36,
+63,
+64,
+37,
+38,
+39,
+40,
+41,
+42,
+109,
+0,
+107,
+65,
+66,
+75,
+76,
+77,
+78,
+79,
+80,
+81,
+82,
+83,
+84,
+67,
+85,
+86,
+87,
+88,
+89,
+90,
+91,
+92,
+93,
+94,
+68,
+95,
+96,
+69,
+70,
+71,
+72,
+73,
+74,
+106,
+1,
+2,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+20,
+3,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+4,
+31,
+32,
+5,
+6,
+7,
+8,
+9,
+10
diff --git a/closures/compiler/powerpc/rppcstab.inc b/closures/compiler/powerpc/rppcstab.inc
new file mode 100644
index 0000000000..2c9c9942a8
--- /dev/null
+++ b/closures/compiler/powerpc/rppcstab.inc
@@ -0,0 +1,111 @@
+{ don't edit, this file is generated from ppcreg.dat }
+-1,
+0,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+8,
+9,
+10,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+20,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+31,
+32,
+33,
+34,
+35,
+36,
+37,
+38,
+39,
+40,
+41,
+42,
+43,
+44,
+45,
+46,
+47,
+48,
+49,
+50,
+51,
+52,
+53,
+54,
+55,
+56,
+57,
+58,
+59,
+60,
+61,
+62,
+63,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+68,
+69,
+70,
+71,
+72,
+73,
+74,
+75,
+76,
+65,
+66,
+-1
diff --git a/closures/compiler/powerpc/rppcstd.inc b/closures/compiler/powerpc/rppcstd.inc
new file mode 100644
index 0000000000..4fc340afd7
--- /dev/null
+++ b/closures/compiler/powerpc/rppcstd.inc
@@ -0,0 +1,111 @@
+{ don't edit, this file is generated from ppcreg.dat }
+'INVALID',
+'r0',
+'r1',
+'r2',
+'r3',
+'r4',
+'r5',
+'r6',
+'r7',
+'r8',
+'r9',
+'r10',
+'r11',
+'r12',
+'r13',
+'r14',
+'r15',
+'r16',
+'r17',
+'r18',
+'r19',
+'r20',
+'r21',
+'r22',
+'r23',
+'r24',
+'r25',
+'r26',
+'r27',
+'r28',
+'r29',
+'r30',
+'r31',
+'F0',
+'F1',
+'F2',
+'F3',
+'F4',
+'F5',
+'F6',
+'F7',
+'F8',
+'F9',
+'F10',
+'F11',
+'F12',
+'F13',
+'F14',
+'F15',
+'F16',
+'F17',
+'F18',
+'F19',
+'F20',
+'F21',
+'F22',
+'F23',
+'F24',
+'F25',
+'F26',
+'F27',
+'F28',
+'F29',
+'F30',
+'F31',
+'M0',
+'M1',
+'M2',
+'M3',
+'M4',
+'M5',
+'M6',
+'M7',
+'M8',
+'M9',
+'M10',
+'M11',
+'M12',
+'M13',
+'M14',
+'M15',
+'M16',
+'M17',
+'M18',
+'M19',
+'M20',
+'M21',
+'M22',
+'M23',
+'M24',
+'M25',
+'M26',
+'M27',
+'M28',
+'M29',
+'M30',
+'M31',
+'CR',
+'CR0',
+'CR1',
+'CR2',
+'CR3',
+'CR4',
+'CR5',
+'CR6',
+'CR7',
+'XER',
+'LR',
+'CTR',
+'FPSCR'
diff --git a/closures/compiler/powerpc/rppcsup.inc b/closures/compiler/powerpc/rppcsup.inc
new file mode 100644
index 0000000000..4e6f879355
--- /dev/null
+++ b/closures/compiler/powerpc/rppcsup.inc
@@ -0,0 +1,111 @@
+{ don't edit, this file is generated from ppcreg.dat }
+RS_NO = $00;
+RS_R0 = $00;
+RS_R1 = $01;
+RS_R2 = $02;
+RS_R3 = $03;
+RS_R4 = $04;
+RS_R5 = $05;
+RS_R6 = $06;
+RS_R7 = $07;
+RS_R8 = $08;
+RS_R9 = $09;
+RS_R10 = $0a;
+RS_R11 = $0b;
+RS_R12 = $0c;
+RS_R13 = $0d;
+RS_R14 = $0e;
+RS_R15 = $0f;
+RS_R16 = $10;
+RS_R17 = $11;
+RS_R18 = $12;
+RS_R19 = $13;
+RS_R20 = $14;
+RS_R21 = $15;
+RS_R22 = $16;
+RS_R23 = $17;
+RS_R24 = $18;
+RS_R25 = $19;
+RS_R26 = $1a;
+RS_R27 = $1b;
+RS_R28 = $1c;
+RS_R29 = $1d;
+RS_R30 = $1e;
+RS_R31 = $1f;
+RS_F0 = $00;
+RS_F1 = $01;
+RS_F2 = $02;
+RS_F3 = $03;
+RS_F4 = $04;
+RS_F5 = $05;
+RS_F6 = $06;
+RS_F7 = $07;
+RS_F8 = $08;
+RS_F9 = $09;
+RS_F10 = $0a;
+RS_F11 = $0b;
+RS_F12 = $0c;
+RS_F13 = $0d;
+RS_F14 = $0e;
+RS_F15 = $0f;
+RS_F16 = $10;
+RS_F17 = $11;
+RS_F18 = $12;
+RS_F19 = $13;
+RS_F20 = $14;
+RS_F21 = $15;
+RS_F22 = $16;
+RS_F23 = $17;
+RS_F24 = $18;
+RS_F25 = $19;
+RS_F26 = $1a;
+RS_F27 = $1b;
+RS_F28 = $1c;
+RS_F29 = $1d;
+RS_F30 = $1e;
+RS_F31 = $1f;
+RS_M0 = $00;
+RS_M1 = $01;
+RS_M2 = $02;
+RS_M3 = $03;
+RS_M4 = $04;
+RS_M5 = $05;
+RS_M6 = $06;
+RS_M7 = $07;
+RS_M8 = $08;
+RS_M9 = $09;
+RS_M10 = $0a;
+RS_M11 = $0b;
+RS_M12 = $0c;
+RS_M13 = $0d;
+RS_M14 = $0e;
+RS_M15 = $0f;
+RS_M16 = $10;
+RS_M17 = $11;
+RS_M18 = $12;
+RS_M19 = $13;
+RS_M20 = $14;
+RS_M21 = $15;
+RS_M22 = $16;
+RS_M23 = $17;
+RS_M24 = $18;
+RS_M25 = $19;
+RS_M26 = $1a;
+RS_M27 = $1b;
+RS_M28 = $1c;
+RS_M29 = $1d;
+RS_M30 = $1e;
+RS_M31 = $1f;
+RS_CR = $00;
+RS_CR0 = $01;
+RS_CR1 = $02;
+RS_CR2 = $03;
+RS_CR3 = $04;
+RS_CR4 = $05;
+RS_CR5 = $06;
+RS_CR6 = $07;
+RS_CR7 = $08;
+RS_XER = $09;
+RS_LR = $0a;
+RS_CTR = $0b;
+RS_FPSCR = $0c;
diff --git a/closures/compiler/powerpc64/aoptcpu.pas b/closures/compiler/powerpc64/aoptcpu.pas
new file mode 100644
index 0000000000..bd96f25524
--- /dev/null
+++ b/closures/compiler/powerpc64/aoptcpu.pas
@@ -0,0 +1,41 @@
+{
+ Copyright (c) 1998-2002 by Jonas Maebe, member of the Free Pascal
+ Development Team
+
+ This unit implements the PowerPC optimizer object
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+
+unit aoptcpu;
+
+interface
+
+{$I fpcdefs.inc}
+
+uses cpubase, aoptobj, aoptcpub, aopt;
+
+type
+ TCpuAsmOptimizer = class(TAsmOptimizer)
+ { uses the same constructor as TAopObj }
+ end;
+
+implementation
+
+begin
+ casmoptimizer := TCpuAsmOptimizer;
+end.
diff --git a/closures/compiler/powerpc64/aoptcpub.pas b/closures/compiler/powerpc64/aoptcpub.pas
new file mode 100644
index 0000000000..b2e82450c5
--- /dev/null
+++ b/closures/compiler/powerpc64/aoptcpub.pas
@@ -0,0 +1,123 @@
+{
+ Copyright (c) 1998-2002 by Jonas Maebe, member of the Free Pascal
+ Development Team
+
+ This unit contains several types and constants necessary for the
+ optimizer to work on the PowerPC64 architecture
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+****************************************************************************
+}
+unit aoptcpub; { Assembler OPTimizer CPU specific Base }
+
+{$I fpcdefs.inc}
+
+{ enable the following define if memory references can have both a base and }
+{ index register in 1 operand }
+
+{$DEFINE RefsHaveIndexReg}
+
+{ enable the following define if memory references can have a scaled index }
+
+{ define RefsHaveScale}
+
+{ enable the following define if memory references can have a segment }
+{ override }
+
+{ define RefsHaveSegment}
+
+interface
+
+uses
+ aasmcpu, AOptBase, cpubase;
+
+type
+
+ { type of a normal instruction }
+ TInstr = Taicpu;
+ PInstr = ^TInstr;
+
+ { ************************************************************************* }
+ { **************************** TCondRegs ********************************** }
+ { ************************************************************************* }
+ { Info about the conditional registers }
+ TCondRegs = object
+ constructor Init;
+ destructor Done;
+ end;
+
+ { ************************************************************************* }
+ { **************************** TAoptBaseCpu ******************************* }
+ { ************************************************************************* }
+
+ TAoptBaseCpu = class(TAoptBase)
+ end;
+
+ { ************************************************************************* }
+ { ******************************* Constants ******************************* }
+ { ************************************************************************* }
+const
+
+ { the maximum number of things (registers, memory, ...) a single instruction }
+ { changes }
+
+ MaxCh = 3;
+
+ { the maximum number of operands an instruction has }
+
+ MaxOps = 5;
+
+ {Oper index of operand that contains the source (reference) with a load }
+ {instruction }
+
+ LoadSrc = 1;
+
+ {Oper index of operand that contains the destination (register) with a load }
+ {instruction }
+
+ LoadDst = 0;
+
+ {Oper index of operand that contains the source (register) with a store }
+ {instruction }
+
+ StoreSrc = 0;
+
+ {Oper index of operand that contains the destination (reference) with a load }
+ {instruction }
+
+ StoreDst = 1;
+
+ aopt_uncondjmp = A_B;
+ aopt_condjmp = A_BC;
+
+implementation
+
+{ ************************************************************************* }
+{ **************************** TCondRegs ********************************** }
+{ ************************************************************************* }
+
+constructor TCondRegs.init;
+begin
+end;
+
+destructor TCondRegs.Done;
+{$IFDEF inl}inline;
+{$ENDIF inl}
+begin
+end;
+
+end.
+
diff --git a/closures/compiler/powerpc64/aoptcpuc.pas b/closures/compiler/powerpc64/aoptcpuc.pas
new file mode 100644
index 0000000000..e002fedb21
--- /dev/null
+++ b/closures/compiler/powerpc64/aoptcpuc.pas
@@ -0,0 +1,40 @@
+{
+ Copyright (c) 1998-2002 by Jonas Maebe, member of the Free Pascal
+ Development Team
+
+ This unit contains the processor specific implementation of the
+ assembler optimizer common subexpression elimination object.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+****************************************************************************
+}
+unit aoptcpuc;
+
+interface
+
+{$I fpcdefs.inc}
+
+uses
+ AOptCs;
+
+type
+ TRegInfoCpu = object(TRegInfo)
+ end;
+
+implementation
+
+end.
+
diff --git a/closures/compiler/powerpc64/aoptcpud.pas b/closures/compiler/powerpc64/aoptcpud.pas
new file mode 100644
index 0000000000..5e6e7fc308
--- /dev/null
+++ b/closures/compiler/powerpc64/aoptcpud.pas
@@ -0,0 +1,40 @@
+{
+ Copyright (c) 1998-2002 by Jonas Maebe, member of the Free Pascal
+ Development Team
+
+ This unit contains the processor specific implementation of the
+ assembler optimizer data flow analyzer.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit aoptcpud;
+
+{$I fpcdefs.inc}
+
+interface
+
+uses
+ AOptDA;
+
+type
+ TAOptDFACpu = class(TAOptDFA)
+ end;
+
+implementation
+
+end.
+
diff --git a/closures/compiler/powerpc64/cgcpu.pas b/closures/compiler/powerpc64/cgcpu.pas
new file mode 100644
index 0000000000..8b6282a7ec
--- /dev/null
+++ b/closures/compiler/powerpc64/cgcpu.pas
@@ -0,0 +1,2199 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit implements the code generator for the PowerPC
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit cgcpu;
+
+{$I fpcdefs.inc}
+
+interface
+
+uses
+ globtype, symtype, symdef, symsym,
+ cgbase, cgobj,cgppc,
+ aasmbase, aasmcpu, aasmtai,aasmdata,
+ cpubase, cpuinfo, cgutils, rgcpu,
+ parabase;
+
+type
+ tcgppc = class(tcgppcgen)
+ procedure init_register_allocators; override;
+ procedure done_register_allocators; override;
+
+ { passing parameters, per default the parameter is pushed }
+ { nr gives the number of the parameter (enumerated from }
+ { left to right), this allows to move the parameter to }
+ { register, if the cpu supports register calling }
+ { conventions }
+ procedure a_load_ref_cgpara(list: TAsmList; size: tcgsize; const r: treference;
+ const paraloc: tcgpara); override;
+
+ procedure a_call_name(list: TAsmList; const s: string; weak: boolean); override;
+ procedure a_call_reg(list: TAsmList; reg: tregister); override;
+
+ procedure a_op_const_reg(list: TAsmList; Op: TOpCG; size: TCGSize; a:
+ aint; reg: TRegister); override;
+ procedure a_op_reg_reg(list: TAsmList; Op: TOpCG; size: TCGSize; src,
+ dst: TRegister); override;
+
+ procedure a_op_const_reg_reg(list: TAsmList; op: TOpCg;
+ size: tcgsize; a: aint; src, dst: tregister); override;
+ procedure a_op_reg_reg_reg(list: TAsmList; op: TOpCg;
+ size: tcgsize; src1, src2, dst: tregister); override;
+
+ { move instructions }
+ procedure a_load_const_reg(list: TAsmList; size: tcgsize; a: aint; reg:
+ tregister); override;
+ { loads the memory pointed to by ref into register reg }
+ procedure a_load_ref_reg(list: TAsmList; fromsize, tosize: tcgsize; const
+ Ref: treference; reg: tregister); override;
+ procedure a_load_reg_reg(list: TAsmList; fromsize, tosize: tcgsize; reg1,
+ reg2: tregister); override;
+
+ procedure a_load_subsetreg_reg(list : TAsmList; subsetsize, tosize: tcgsize; const sreg: tsubsetregister; destreg: tregister); override;
+ procedure a_load_const_subsetreg(list: TAsmlist; subsetsize: tcgsize; a: aint; const sreg: tsubsetregister); override;
+
+ { comparison operations }
+ procedure a_cmp_const_reg_label(list: TAsmList; size: tcgsize; cmp_op:
+ topcmp; a: aint; reg: tregister;
+ l: tasmlabel); override;
+ procedure a_cmp_reg_reg_label(list: TAsmList; size: tcgsize; cmp_op:
+ topcmp; reg1, reg2: tregister; l: tasmlabel); override;
+
+ procedure a_jmp_name(list: TAsmList; const s: string); override;
+ procedure a_jmp_always(list: TAsmList; l: tasmlabel); override;
+ procedure a_jmp_flags(list: TAsmList; const f: TResFlags; l: tasmlabel);
+ override;
+
+ procedure g_flags2reg(list: TAsmList; size: TCgSize; const f: TResFlags;
+ reg: TRegister); override;
+
+ { need to override this for ppc64 to avoid calling CG methods which allocate
+ registers during creation of the interface wrappers to subtract ioffset from
+ the self pointer. But register allocation does not take place for them (which
+ would probably be the generic fix) so we need to have a specialized method
+ that uses the R11 scratch register in these cases.
+ At the same time this allows > 32 bit offsets as well.
+ }
+ procedure g_adjust_self_value(list:TAsmList;procdef: tprocdef;ioffset: aint);override;
+
+ procedure g_profilecode(list: TAsmList); override;
+ procedure g_proc_entry(list: TAsmList; localsize: longint; nostackframe:
+ boolean); override;
+ procedure g_proc_exit(list: TAsmList; parasize: longint; nostackframe:
+ boolean); override;
+ procedure g_save_registers(list: TAsmList); override;
+ procedure g_restore_registers(list: TAsmList); override;
+
+ procedure a_loadaddr_ref_reg(list: TAsmList; const ref: treference; r:
+ tregister); override;
+
+ procedure g_concatcopy(list: TAsmList; const source, dest: treference;
+ len: aint); override;
+
+ procedure g_external_wrapper(list: TAsmList; pd: TProcDef; const externalname: string); override;
+
+ private
+
+ procedure a_load_regconst_subsetreg_intern(list : TAsmList; fromsize, subsetsize: tcgsize; fromreg: tregister; const sreg: tsubsetregister; slopt: tsubsetloadopt); override;
+
+ procedure maybeadjustresult(list: TAsmList; op: TOpCg; size: tcgsize; dst: tregister);
+
+ { returns whether a reference can be used immediately in a powerpc }
+ { instruction }
+ function issimpleref(const ref: treference): boolean;
+
+ { contains the common code of a_load_reg_ref and a_load_ref_reg }
+ procedure a_load_store(list: TAsmList; op: tasmop; reg: tregister;
+ ref: treference); override;
+
+ { returns the lowest numbered FP register in use, and the number of used FP registers
+ for the current procedure }
+ procedure calcFirstUsedFPR(out firstfpr : TSuperRegister; out fprcount : aint);
+ { returns the lowest numbered GP register in use, and the number of used GP registers
+ for the current procedure }
+ procedure calcFirstUsedGPR(out firstgpr : TSuperRegister; out gprcount : aint);
+
+ { generates code to call a method with the given string name. The boolean options
+ control code generation. If prependDot is true, a single dot character is prepended to
+ the string, if addNOP is true a single NOP instruction is added after the call, and
+ if includeCall is true, the method is marked as having a call, not if false. This
+ option is particularly useful to prevent generation of a larger stack frame for the
+ register save and restore helper functions. }
+ procedure a_call_name_direct(list: TAsmList; s: string; weak: boolean; prependDot : boolean;
+ addNOP : boolean; includeCall : boolean = true);
+
+ procedure a_jmp_name_direct(list : TAsmList; s : string; prependDot : boolean);
+
+ { emits code to store the given value a into the TOC (if not already in there), and load it from there
+ as well }
+ procedure loadConstantPIC(list : TAsmList; size : TCGSize; a : aint; reg : TRegister);
+
+ procedure profilecode_savepara(para : tparavarsym; list : TAsmList);
+ procedure profilecode_restorepara(para : tparavarsym; list : TAsmList);
+ end;
+
+ procedure create_codegen;
+
+const
+ TShiftOpCG2AsmOpConst : array[boolean, OP_SAR..OP_SHR] of TAsmOp = (
+ (A_SRAWI, A_SLWI, A_SRWI), (A_SRADI, A_SLDI, A_SRDI)
+ );
+
+implementation
+
+uses
+ sysutils, cclasses,
+ globals, verbose, systems, cutils,
+ symconst, fmodule,
+ rgobj, tgobj, cpupi, procinfo, paramgr, cpupara;
+
+function is_signed_cgsize(const size : TCgSize) : Boolean;
+begin
+ case size of
+ OS_S8,OS_S16,OS_S32,OS_S64 : result := true;
+ OS_8,OS_16,OS_32,OS_64 : result := false;
+ else
+ internalerror(2006050701);
+ end;
+end;
+
+{$push}
+{$r-}
+{$q-}
+{ helper function which calculate "magic" values for replacement of unsigned
+ division by constant operation by multiplication. See the PowerPC compiler
+ developer manual for more information }
+procedure getmagic_unsignedN(const N : byte; const d : aWord;
+ out magic_m : aWord; out magic_add : boolean; out magic_shift : byte);
+var
+ p : aInt;
+ nc, delta, q1, r1, q2, r2, two_N_minus_1 : aWord;
+begin
+ assert(d > 0);
+
+ two_N_minus_1 := aWord(1) shl (N-1);
+
+ magic_add := false;
+{$push}
+{$warnings off }
+ nc := aWord(-1) - (-d) mod d;
+{$pop}
+ p := N-1; { initialize p }
+ q1 := two_N_minus_1 div nc; { initialize q1 = 2p/nc }
+ r1 := two_N_minus_1 - q1*nc; { initialize r1 = rem(2p,nc) }
+ q2 := (two_N_minus_1-1) div d; { initialize q2 = (2p-1)/d }
+ r2 := (two_N_minus_1-1) - q2*d; { initialize r2 = rem((2p-1),d) }
+ repeat
+ inc(p);
+ if (r1 >= (nc - r1)) then begin
+ q1 := 2 * q1 + 1; { update q1 }
+ r1 := 2*r1 - nc; { update r1 }
+ end else begin
+ q1 := 2*q1; { update q1 }
+ r1 := 2*r1; { update r1 }
+ end;
+ if ((r2 + 1) >= (d - r2)) then begin
+ if (q2 >= (two_N_minus_1-1)) then
+ magic_add := true;
+ q2 := 2*q2 + 1; { update q2 }
+ r2 := 2*r2 + 1 - d; { update r2 }
+ end else begin
+ if (q2 >= two_N_minus_1) then
+ magic_add := true;
+ q2 := 2*q2; { update q2 }
+ r2 := 2*r2 + 1; { update r2 }
+ end;
+ delta := d - 1 - r2;
+ until not ((p < (2*N)) and ((q1 < delta) or ((q1 = delta) and (r1 = 0))));
+ magic_m := q2 + 1; { resulting magic number }
+ magic_shift := p - N; { resulting shift }
+end;
+
+{ helper function which calculate "magic" values for replacement of signed
+ division by constant operation by multiplication. See the PowerPC compiler
+ developer manual for more information }
+procedure getmagic_signedN(const N : byte; const d : aInt;
+ out magic_m : aInt; out magic_s : aInt);
+var
+ p : aInt;
+ ad, anc, delta, q1, r1, q2, r2, t : aWord;
+ two_N_minus_1 : aWord;
+
+begin
+ assert((d < -1) or (d > 1));
+
+ two_N_minus_1 := aWord(1) shl (N-1);
+
+ ad := abs(d);
+ t := two_N_minus_1 + (aWord(d) shr (N-1));
+ anc := t - 1 - t mod ad; { absolute value of nc }
+ p := (N-1); { initialize p }
+ q1 := two_N_minus_1 div anc; { initialize q1 = 2p/abs(nc) }
+ r1 := two_N_minus_1 - q1*anc; { initialize r1 = rem(2p,abs(nc)) }
+ q2 := two_N_minus_1 div ad; { initialize q2 = 2p/abs(d) }
+ r2 := two_N_minus_1 - q2*ad; { initialize r2 = rem(2p,abs(d)) }
+ repeat
+ inc(p);
+ q1 := 2*q1; { update q1 = 2p/abs(nc) }
+ r1 := 2*r1; { update r1 = rem(2p/abs(nc)) }
+ if (r1 >= anc) then begin { must be unsigned comparison }
+ inc(q1);
+ dec(r1, anc);
+ end;
+ q2 := 2*q2; { update q2 = 2p/abs(d) }
+ r2 := 2*r2; { update r2 = rem(2p/abs(d)) }
+ if (r2 >= ad) then begin { must be unsigned comparison }
+ inc(q2);
+ dec(r2, ad);
+ end;
+ delta := ad - r2;
+ until not ((q1 < delta) or ((q1 = delta) and (r1 = 0)));
+ magic_m := q2 + 1;
+ if (d < 0) then begin
+ magic_m := -magic_m; { resulting magic number }
+ end;
+ magic_s := p - N; { resulting shift }
+end;
+{$pop}
+
+{ finds positive and negative powers of two of the given value, returning the
+ power and whether it's a negative power or not in addition to the actual result
+ of the function }
+function ispowerof2(value : aInt; out power : byte; out neg : boolean) : boolean;
+var
+ i : longint;
+ hl : aInt;
+begin
+ neg := false;
+ { also try to find negative power of two's by negating if the
+ value is negative. low(aInt) is special because it can not be
+ negated. Simply return the appropriate values for it }
+ if (value < 0) then begin
+ neg := true;
+ if (value = low(aInt)) then begin
+ power := sizeof(aInt)*8-1;
+ result := true;
+ exit;
+ end;
+ value := -value;
+ end;
+
+ if ((value and (value-1)) <> 0) then begin
+ result := false;
+ exit;
+ end;
+ hl := 1;
+ for i := 0 to (sizeof(aInt)*8-1) do begin
+ if (hl = value) then begin
+ result := true;
+ power := i;
+ exit;
+ end;
+ hl := hl shl 1;
+ end;
+end;
+
+{ returns the number of instruction required to load the given integer into a register.
+ This is basically a stripped down version of a_load_const_reg, increasing a counter
+ instead of emitting instructions. }
+function getInstructionLength(a : aint) : longint;
+
+ function get32bitlength(a : longint; var length : longint) : boolean; inline;
+ var
+ is_half_signed : byte;
+ begin
+ { if the lower 16 bits are zero, do a single LIS }
+ if (smallint(a) = 0) and ((a shr 16) <> 0) then begin
+ inc(length);
+ get32bitlength := longint(a) < 0;
+ end else begin
+ is_half_signed := ord(smallint(lo(a)) < 0);
+ inc(length);
+ if smallint(hi(a) + is_half_signed) <> 0 then
+ inc(length);
+ get32bitlength := (smallint(a) < 0) or (a < 0);
+ end;
+ end;
+
+var
+ extendssign : boolean;
+
+begin
+ result := 0;
+ if (lo(a) = 0) and (hi(a) <> 0) then begin
+ get32bitlength(hi(a), result);
+ inc(result);
+ end else begin
+ extendssign := get32bitlength(lo(a), result);
+ if (extendssign) and (hi(a) = 0) then
+ inc(result)
+ else if (not
+ ((extendssign and (longint(hi(a)) = -1)) or
+ ((not extendssign) and (hi(a)=0)))
+ ) then begin
+ get32bitlength(hi(a), result);
+ inc(result);
+ end;
+ end;
+end;
+
+procedure tcgppc.init_register_allocators;
+begin
+ inherited init_register_allocators;
+ if (target_info.system <> system_powerpc64_darwin) then
+ // r13 is tls, do not use, r2 is not available
+ rg[R_INTREGISTER] := trgintcpu.create(R_INTREGISTER, R_SUBWHOLE,
+ [{$ifdef user0} RS_R0, {$endif} RS_R3, RS_R4, RS_R5, RS_R6, RS_R7, RS_R8,
+ RS_R9, RS_R10, RS_R11, RS_R12, RS_R31, RS_R30, RS_R29,
+ RS_R28, RS_R27, RS_R26, RS_R25, RS_R24, RS_R23, RS_R22,
+ RS_R21, RS_R20, RS_R19, RS_R18, RS_R17, RS_R16, RS_R15,
+ RS_R14], first_int_imreg, [])
+ else
+ { special for darwin/ppc64: r2 available volatile, r13 = tls }
+ rg[R_INTREGISTER] := trgintcpu.create(R_INTREGISTER, R_SUBWHOLE,
+ [{$ifdef user0} RS_R0, {$endif} RS_R2, RS_R3, RS_R4, RS_R5, RS_R6, RS_R7, RS_R8,
+ RS_R9, RS_R10, RS_R11, RS_R12, RS_R31, RS_R30, RS_R29,
+ RS_R28, RS_R27, RS_R26, RS_R25, RS_R24, RS_R23, RS_R22,
+ RS_R21, RS_R20, RS_R19, RS_R18, RS_R17, RS_R16, RS_R15,
+ RS_R14], first_int_imreg, []);
+ rg[R_FPUREGISTER] := trgcpu.create(R_FPUREGISTER, R_SUBNONE,
+ [RS_F0, RS_F1, RS_F2, RS_F3, RS_F4, RS_F5, RS_F6, RS_F7, RS_F8, RS_F9,
+ RS_F10, RS_F11, RS_F12, RS_F13, RS_F31, RS_F30, RS_F29, RS_F28, RS_F27,
+ RS_F26, RS_F25, RS_F24, RS_F23, RS_F22, RS_F21, RS_F20, RS_F19, RS_F18,
+ RS_F17, RS_F16, RS_F15, RS_F14], first_fpu_imreg, []);
+{ TODO: FIX ME}
+ rg[R_MMREGISTER] := trgcpu.create(R_MMREGISTER, R_SUBNONE,
+ [RS_M0, RS_M1, RS_M2], first_mm_imreg, []);
+end;
+
+procedure tcgppc.done_register_allocators;
+begin
+ rg[R_INTREGISTER].free;
+ rg[R_FPUREGISTER].free;
+ rg[R_MMREGISTER].free;
+ inherited done_register_allocators;
+end;
+
+procedure tcgppc.a_load_ref_cgpara(list: TAsmList; size: tcgsize; const r:
+ treference; const paraloc: tcgpara);
+
+var
+ tmpref, ref: treference;
+ location: pcgparalocation;
+ sizeleft: aint;
+ adjusttail : boolean;
+
+begin
+ location := paraloc.location;
+ tmpref := r;
+ sizeleft := paraloc.intsize;
+ adjusttail := false;
+ while assigned(location) do begin
+ paramanager.allocparaloc(list,location);
+ case location^.loc of
+ LOC_REGISTER, LOC_CREGISTER:
+ begin
+ if not(size in [OS_NO,OS_128,OS_S128]) then
+ a_load_ref_reg(list, size, location^.size, tmpref,
+ location^.register)
+ else begin
+ { load non-integral sized memory location into register. This
+ memory location be 1-sizeleft byte sized.
+ Always assume that this memory area is properly aligned, eg. start
+ loading the larger quantities for "odd" quantities first }
+ case sizeleft of
+ 1,2,4,8 :
+ a_load_ref_reg(list, int_cgsize(sizeleft), location^.size, tmpref,
+ location^.register);
+ 3 : begin
+ a_reg_alloc(list, NR_R12);
+ a_load_ref_reg(list, OS_16, location^.size, tmpref,
+ NR_R12);
+ inc(tmpref.offset, tcgsize2size[OS_16]);
+ a_load_ref_reg(list, OS_8, location^.size, tmpref,
+ location^.register);
+ list.concat(taicpu.op_reg_reg_const_const(A_RLDIMI, location^.register, NR_R12, 8, 40));
+ a_reg_dealloc(list, NR_R12);
+ end;
+ 5 : begin
+ a_reg_alloc(list, NR_R12);
+ a_load_ref_reg(list, OS_32, location^.size, tmpref, NR_R12);
+ inc(tmpref.offset, tcgsize2size[OS_32]);
+ a_load_ref_reg(list, OS_8, location^.size, tmpref, location^.register);
+ list.concat(taicpu.op_reg_reg_const_const(A_RLDIMI, location^.register, NR_R12, 8, 24));
+ a_reg_dealloc(list, NR_R12);
+ end;
+ 6 : begin
+ a_reg_alloc(list, NR_R12);
+ a_load_ref_reg(list, OS_32, location^.size, tmpref, NR_R12);
+ inc(tmpref.offset, tcgsize2size[OS_32]);
+ a_load_ref_reg(list, OS_16, location^.size, tmpref, location^.register);
+ list.concat(taicpu.op_reg_reg_const_const(A_RLDIMI, location^.register, NR_R12, 16, 16));
+ a_reg_dealloc(list, NR_R12);
+ end;
+ 7 : begin
+ a_reg_alloc(list, NR_R12);
+ a_reg_alloc(list, NR_R0);
+ a_load_ref_reg(list, OS_32, location^.size, tmpref, NR_R12);
+ inc(tmpref.offset, tcgsize2size[OS_32]);
+ a_load_ref_reg(list, OS_16, location^.size, tmpref, NR_R0);
+ inc(tmpref.offset, tcgsize2size[OS_16]);
+ a_load_ref_reg(list, OS_8, location^.size, tmpref, location^.register);
+ list.concat(taicpu.op_reg_reg_const_const(A_RLDIMI, NR_R0, NR_R12, 16, 16));
+ list.concat(taicpu.op_reg_reg_const_const(A_RLDIMI, location^.register, NR_R0, 8, 8));
+ a_reg_dealloc(list, NR_R0);
+ a_reg_dealloc(list, NR_R12);
+ end;
+ else begin
+ { still > 8 bytes to load, so load data single register now }
+ a_load_ref_reg(list, location^.size, location^.size, tmpref,
+ location^.register);
+ { the block is > 8 bytes, so we have to store any bytes not
+ a multiple of the register size beginning with the MSB }
+ adjusttail := true;
+ end;
+ end;
+ if (adjusttail) and (sizeleft < sizeof(pint)) then
+ a_op_const_reg(list, OP_SHL, OS_INT,
+ (sizeof(pint) - sizeleft) * sizeof(pint),
+ location^.register);
+ end;
+ end;
+ LOC_REFERENCE:
+ begin
+ reference_reset_base(ref, location^.reference.index,
+ location^.reference.offset,paraloc.alignment);
+ g_concatcopy(list, tmpref, ref, sizeleft);
+ if assigned(location^.next) then
+ internalerror(2005010710);
+ end;
+ LOC_FPUREGISTER, LOC_CFPUREGISTER:
+ case location^.size of
+ OS_F32, OS_F64:
+ a_loadfpu_ref_reg(list, location^.size, location^.size, tmpref, location^.register);
+ else
+ internalerror(2002072801);
+ end;
+ LOC_VOID:
+ { nothing to do }
+ ;
+ else
+ internalerror(2002081103);
+ end;
+ inc(tmpref.offset, tcgsize2size[location^.size]);
+ dec(sizeleft, tcgsize2size[location^.size]);
+ location := location^.next;
+ end;
+end;
+
+{ calling a procedure by name }
+
+procedure tcgppc.a_call_name(list: TAsmList; const s: string; weak: boolean);
+begin
+ if (target_info.system <> system_powerpc64_darwin) then
+ a_call_name_direct(list, s, weak, false, true)
+ else
+ begin
+ list.concat(taicpu.op_sym(A_BL,get_darwin_call_stub(s,weak)));
+ include(current_procinfo.flags,pi_do_call);
+ end;
+end;
+
+
+procedure tcgppc.a_call_name_direct(list: TAsmList; s: string; weak: boolean; prependDot : boolean; addNOP : boolean; includeCall : boolean);
+begin
+ if (prependDot) then
+ s := '.' + s;
+ if not(weak) then
+ list.concat(taicpu.op_sym(A_BL, current_asmdata.RefAsmSymbol(s)))
+ else
+ list.concat(taicpu.op_sym(A_BL, current_asmdata.WeakRefAsmSymbol(s)));
+ if (addNOP) then
+ list.concat(taicpu.op_none(A_NOP));
+
+ if (includeCall) then
+ include(current_procinfo.flags, pi_do_call);
+end;
+
+
+{ calling a procedure by address }
+
+procedure tcgppc.a_call_reg(list: TAsmList; reg: tregister);
+var
+ tmpref: treference;
+ tempreg : TRegister;
+begin
+ if (target_info.system = system_powerpc64_darwin) then
+ inherited a_call_reg(list,reg)
+ else if (not (cs_opt_size in current_settings.optimizerswitches)) then begin
+ tempreg := cg.getintregister(current_asmdata.CurrAsmList, OS_INT);
+ { load actual function entry (reg contains the reference to the function descriptor)
+ into tempreg }
+ reference_reset_base(tmpref, reg, 0, sizeof(pint));
+ a_load_ref_reg(list, OS_ADDR, OS_ADDR, tmpref, tempreg);
+
+ { save TOC pointer in stackframe }
+ reference_reset_base(tmpref, NR_STACK_POINTER_REG, LA_RTOC_ELF, 8);
+ a_load_reg_ref(list, OS_ADDR, OS_ADDR, NR_RTOC, tmpref);
+
+ { move actual function pointer to CTR register }
+ list.concat(taicpu.op_reg(A_MTCTR, tempreg));
+
+ { load new TOC pointer from function descriptor into RTOC register }
+ reference_reset_base(tmpref, reg, tcgsize2size[OS_ADDR], 8);
+ a_load_ref_reg(list, OS_ADDR, OS_ADDR, tmpref, NR_RTOC);
+
+ { load new environment pointer from function descriptor into R11 register }
+ reference_reset_base(tmpref, reg, 2*tcgsize2size[OS_ADDR], 8);
+ a_reg_alloc(list, NR_R11);
+ a_load_ref_reg(list, OS_ADDR, OS_ADDR, tmpref, NR_R11);
+ { call function }
+ list.concat(taicpu.op_none(A_BCTRL));
+ a_reg_dealloc(list, NR_R11);
+ end else begin
+ { call ptrgl helper routine which expects the pointer to the function descriptor
+ in R11 }
+ a_reg_alloc(list, NR_R11);
+ a_load_reg_reg(list, OS_ADDR, OS_ADDR, reg, NR_R11);
+ a_call_name_direct(list, '.ptrgl', false, false, false);
+ a_reg_dealloc(list, NR_R11);
+ end;
+
+ { we need to load the old RTOC from stackframe because we changed it}
+ reference_reset_base(tmpref, NR_STACK_POINTER_REG, LA_RTOC_ELF, 8);
+ a_load_ref_reg(list, OS_ADDR, OS_ADDR, tmpref, NR_RTOC);
+
+ include(current_procinfo.flags, pi_do_call);
+end;
+
+{********************** load instructions ********************}
+
+procedure tcgppc.a_load_const_reg(list: TAsmList; size: TCGSize; a: aint;
+ reg: TRegister);
+
+ { loads a 32 bit constant into the given register, using an optimal instruction sequence.
+ This is either LIS, LI or LI+ADDIS.
+ Returns true if during these operations the upper 32 bits were filled with 1 bits (e.g.
+ sign extension was performed) }
+ function load32bitconstant(list : TAsmList; size : TCGSize; a : longint;
+ reg : TRegister) : boolean;
+ var
+ is_half_signed : byte;
+ begin
+ { if the lower 16 bits are zero, do a single LIS }
+ if (smallint(a) = 0) and ((a shr 16) <> 0) then begin
+ list.concat(taicpu.op_reg_const(A_LIS, reg, smallint(hi(a))));
+ load32bitconstant := longint(a) < 0;
+ end else begin
+ is_half_signed := ord(smallint(lo(a)) < 0);
+ list.concat(taicpu.op_reg_const(A_LI, reg, smallint(a and $ffff)));
+ if smallint(hi(a) + is_half_signed) <> 0 then begin
+ list.concat(taicpu.op_reg_reg_const(A_ADDIS, reg, reg, smallint(hi(a) + is_half_signed)));
+ end;
+ load32bitconstant := (smallint(a) < 0) or (a < 0);
+ end;
+ end;
+
+ { loads a 32 bit constant into R0, using an optimal instruction sequence.
+ This is either LIS, LI or LI+ORIS.
+ Returns true if during these operations the upper 32 bits were filled with 1 bits (e.g.
+ sign extension was performed) }
+ function load32bitconstantR0(list : TAsmList; size : TCGSize; a : longint) : boolean;
+ begin
+ { if it's a value we can load with a single LI, do it }
+ if (a >= low(smallint)) and (a <= high(smallint)) then begin
+ list.concat(taicpu.op_reg_const(A_LI, NR_R0, smallint(a)));
+ end else begin
+ { if the lower 16 bits are zero, do a single LIS }
+ list.concat(taicpu.op_reg_const(A_LIS, NR_R0, smallint(a shr 16)));
+ if (smallint(a) <> 0) then begin
+ list.concat(taicpu.op_reg_reg_const(A_ORI, NR_R0, NR_R0, word(a)));
+ end;
+ end;
+ load32bitconstantR0 := a < 0;
+ end;
+
+
+ { emits the code to load a constant by emitting various instructions into the output
+ code}
+ procedure loadConstantNormal(list: TAsmList; size : TCgSize; a: aint; reg: TRegister);
+ var
+ extendssign : boolean;
+ instr : taicpu;
+ begin
+ if (lo(a) = 0) and (hi(a) <> 0) then begin
+ { load only upper 32 bits, and shift }
+ load32bitconstant(list, size, longint(hi(a)), reg);
+ list.concat(taicpu.op_reg_reg_const(A_SLDI, reg, reg, 32));
+ end else begin
+ { load lower 32 bits }
+ extendssign := load32bitconstant(list, size, longint(lo(a)), reg);
+ if (extendssign) and (hi(a) = 0) then
+ { if upper 32 bits are zero, but loading the lower 32 bit resulted in automatic
+ sign extension, clear those bits }
+ list.concat(taicpu.op_reg_reg_const_const(A_RLDICL, reg, reg, 0, 32))
+ else if (not
+ ((extendssign and (longint(hi(a)) = -1)) or
+ ((not extendssign) and (hi(a)=0)))
+ ) then begin
+ { only load the upper 32 bits, if the automatic sign extension is not okay,
+ that is, _not_ if
+ - loading the lower 32 bits resulted in -1 in the upper 32 bits, and the upper
+ 32 bits should contain -1
+ - loading the lower 32 bits resulted in 0 in the upper 32 bits, and the upper
+ 32 bits should contain 0 }
+ a_reg_alloc(list, NR_R0);
+ load32bitconstantR0(list, size, longint(hi(a)));
+ { combine both registers }
+ list.concat(taicpu.op_reg_reg_const_const(A_RLDIMI, reg, NR_R0, 32, 0));
+ a_reg_dealloc(list, NR_R0);
+ end;
+ end;
+ end;
+
+ {$IFDEF EXTDEBUG}
+var
+ astring : string;
+ {$ENDIF EXTDEBUG}
+
+begin
+ {$IFDEF EXTDEBUG}
+ astring := 'a_load_const_reg ' + inttostr(hi(a)) + ' ' + inttostr(lo(a)) + ' ' + inttostr(ord(size)) + ' ' + inttostr(tcgsize2size[size]) + ' ' + hexstr(a, 16);
+ list.concat(tai_comment.create(strpnew(astring)));
+ {$ENDIF EXTDEBUG}
+ if not (size in [OS_8, OS_S8, OS_16, OS_S16, OS_32, OS_S32, OS_64, OS_S64]) then
+ internalerror(2002090902);
+ { if PIC or basic optimizations are enabled, and the number of instructions which would be
+ required to load the value is greater than 2, store (and later load) the value from there }
+// if (((cs_opt_peephole in current_settings.optimizerswitches) or (cs_create_pic in current_settings.moduleswitches)) and
+// (getInstructionLength(a) > 2)) then
+// loadConstantPIC(list, size, a, reg)
+// else
+ loadConstantNormal(list, size, a, reg);
+end;
+
+
+procedure tcgppc.a_load_ref_reg(list: TAsmList; fromsize, tosize: tcgsize;
+ const ref: treference; reg: tregister);
+
+const
+ LoadInstr: array[OS_8..OS_S64, boolean, boolean] of TAsmOp =
+ { indexed? updating? }
+ (((A_LBZ, A_LBZU), (A_LBZX, A_LBZUX)),
+ ((A_LHZ, A_LHZU), (A_LHZX, A_LHZUX)),
+ ((A_LWZ, A_LWZU), (A_LWZX, A_LWZUX)),
+ ((A_LD, A_LDU), (A_LDX, A_LDUX)),
+ { 128bit stuff too }
+ ((A_NONE, A_NONE), (A_NONE, A_NONE)),
+ { there's no load-byte-with-sign-extend :( }
+ ((A_LBZ, A_LBZU), (A_LBZX, A_LBZUX)),
+ ((A_LHA, A_LHAU), (A_LHAX, A_LHAUX)),
+ { there's no load-word-arithmetic-indexed with update, simulate it in code :( }
+ ((A_LWA, A_NOP), (A_LWAX, A_LWAUX)),
+ ((A_LD, A_LDU), (A_LDX, A_LDUX))
+ );
+var
+ op: tasmop;
+ ref2: treference;
+ tmpreg: tregister;
+begin
+ {$IFDEF EXTDEBUG}
+ list.concat(tai_comment.create(strpnew('a_load_ref_reg ' + ref2string(ref))));
+ {$ENDIF EXTDEBUG}
+
+ if not (fromsize in [OS_8, OS_S8, OS_16, OS_S16, OS_32, OS_S32, OS_64, OS_S64]) then
+ internalerror(2002090904);
+
+ { the caller is expected to have adjusted the reference already
+ in this case }
+ if (TCGSize2Size[fromsize] >= TCGSize2Size[tosize]) then
+ fromsize := tosize;
+
+ ref2 := ref;
+ fixref(list, ref2);
+
+ op := loadinstr[fromsize, ref2.index <> NR_NO, false];
+ { there is no LWAU instruction, simulate using ADDI and LWA }
+ if (op = A_NOP) then begin
+ list.concat(taicpu.op_reg_reg_const(A_ADDI, reg, reg, ref2.offset));
+ ref2.offset := 0;
+ op := A_LWA;
+ end;
+ a_load_store(list, op, reg, ref2);
+ { sign extend shortint if necessary (because there is
+ no load instruction to sign extend an 8 bit value automatically)
+ and mask out extra sign bits when loading from a smaller
+ signed to a larger unsigned type (where it matters) }
+ if (fromsize = OS_S8) then begin
+ a_load_reg_reg(list, OS_8, OS_S8, reg, reg);
+ a_load_reg_reg(list, OS_S8, tosize, reg, reg);
+ end else if (fromsize = OS_S16) and (tosize = OS_32) then
+ a_load_reg_reg(list, fromsize, tosize, reg, reg);
+end;
+
+procedure tcgppc.a_load_reg_reg(list: TAsmList; fromsize, tosize: tcgsize;
+ reg1, reg2: tregister);
+var
+ instr: TAiCpu;
+ bytesize : byte;
+begin
+ {$ifdef extdebug}
+ list.concat(tai_comment.create(strpnew('a_load_reg_reg from : ' + cgsize2string(fromsize) + ' to ' + cgsize2string(tosize))));
+ {$endif}
+
+ if (tcgsize2size[fromsize] > tcgsize2size[tosize]) or
+ ((tcgsize2size[fromsize] = tcgsize2size[tosize]) and (fromsize <> tosize)) or
+ { do we need to mask out the sign when loading from smaller signed to larger unsigned type? }
+ ( is_signed_cgsize(fromsize) and (not is_signed_cgsize(tosize)) and
+ (tcgsize2size[fromsize] < tcgsize2size[tosize]) and (tcgsize2size[tosize] <> sizeof(pint)) ) then begin
+ case tosize of
+ OS_S8:
+ instr := taicpu.op_reg_reg(A_EXTSB,reg2,reg1);
+ OS_S16:
+ instr := taicpu.op_reg_reg(A_EXTSH,reg2,reg1);
+ OS_S32:
+ instr := taicpu.op_reg_reg(A_EXTSW,reg2,reg1);
+ OS_8, OS_16, OS_32:
+ instr := taicpu.op_reg_reg_const_const(A_RLDICL, reg2, reg1, 0, (8-tcgsize2size[tosize])*8);
+ OS_S64, OS_64:
+ instr := taicpu.op_reg_reg(A_MR, reg2, reg1);
+ end;
+ end else
+ instr := taicpu.op_reg_reg(A_MR, reg2, reg1);
+
+ list.concat(instr);
+ rg[R_INTREGISTER].add_move_instruction(instr);
+end;
+
+procedure tcgppc.a_load_subsetreg_reg(list : TAsmList; subsetsize, tosize: tcgsize; const sreg: tsubsetregister; destreg: tregister);
+begin
+ {$ifdef extdebug}
+ list.concat(tai_comment.create(strpnew('a_load_subsetreg_reg subsetregsize = ' + cgsize2string(sreg.subsetregsize) + ' subsetsize = ' + cgsize2string(subsetsize) + ' startbit = ' + intToStr(sreg.startbit) + ' tosize = ' + cgsize2string(tosize))));
+ {$endif}
+ { do the extraction if required and then extend the sign correctly. (The latter is actually required only for signed subsets
+ and if that subset is not >= the tosize). }
+ if (sreg.startbit <> 0) or
+ (sreg.bitlen <> tcgsize2size[subsetsize]*8) then begin
+ list.concat(taicpu.op_reg_reg_const_const(A_RLDICL, destreg, sreg.subsetreg, (64 - sreg.startbit) and 63, 64 - sreg.bitlen));
+ if (subsetsize in [OS_S8..OS_S128]) then
+ if ((sreg.bitlen mod 8) = 0) then begin
+ a_load_reg_reg(list, tcgsize2unsigned[subsetsize], subsetsize, destreg, destreg);
+ a_load_reg_reg(list, subsetsize, tosize, destreg, destreg);
+ end else begin
+ a_op_const_reg(list,OP_SHL,OS_INT,64-sreg.bitlen,destreg);
+ a_op_const_reg(list,OP_SAR,OS_INT,64-sreg.bitlen,destreg);
+ end;
+ end else begin
+ a_load_reg_reg(list, tcgsize2unsigned[sreg.subsetregsize], subsetsize, sreg.subsetreg, destreg);
+ a_load_reg_reg(list, subsetsize, tosize, destreg, destreg);
+ end;
+end;
+
+procedure tcgppc.a_load_regconst_subsetreg_intern(list : TAsmList; fromsize, subsetsize: tcgsize; fromreg: tregister; const sreg: tsubsetregister; slopt: tsubsetloadopt);
+begin
+ {$ifdef extdebug}
+ list.concat(tai_comment.create(strpnew('a_load_reg_subsetreg fromsize = ' + cgsize2string(fromsize) + ' subsetregsize = ' + cgsize2string(sreg.subsetregsize) + ' subsetsize = ' + cgsize2string(subsetsize) + ' startbit = ' + IntToStr(sreg.startbit))));
+ {$endif}
+ if (slopt in [SL_SETZERO,SL_SETMAX]) then
+ inherited a_load_regconst_subsetreg_intern(list,fromsize,subsetsize,fromreg,sreg,slopt)
+ else if (sreg.bitlen <> sizeof(aint)*8) then
+ { simply use the INSRDI instruction }
+ list.concat(taicpu.op_reg_reg_const_const(A_INSRDI, sreg.subsetreg, fromreg, sreg.bitlen, (64 - (sreg.startbit + sreg.bitlen)) and 63))
+ else
+ a_load_reg_reg(list, fromsize, subsetsize, fromreg, sreg.subsetreg);
+end;
+
+procedure tcgppc.a_load_const_subsetreg(list: TAsmlist; subsetsize: tcgsize;
+ a: aint; const sreg: tsubsetregister);
+var
+ tmpreg : TRegister;
+begin
+ {$ifdef extdebug}
+ list.concat(tai_comment.create(strpnew('a_load_const_subsetreg subsetregsize = ' + cgsize2string(sreg.subsetregsize) + ' subsetsize = ' + cgsize2string(subsetsize) + ' startbit = ' + intToStr(sreg.startbit) + ' a = ' + intToStr(a))));
+ {$endif}
+ { loading the constant into the lowest bits of a temp register and then inserting is
+ better than loading some usually large constants and do some masking and shifting on ppc64 }
+ tmpreg := getintregister(list,subsetsize);
+ a_load_const_reg(list,subsetsize,a,tmpreg);
+ a_load_reg_subsetreg(list, subsetsize, subsetsize, tmpreg, sreg);
+end;
+
+procedure tcgppc.a_op_const_reg(list: TAsmList; Op: TOpCG; size: TCGSize; a:
+ aint; reg: TRegister);
+begin
+ a_op_const_reg_reg(list, op, size, a, reg, reg);
+end;
+
+procedure tcgppc.a_op_reg_reg(list: TAsmList; Op: TOpCG; size: TCGSize; src,
+ dst: TRegister);
+begin
+ a_op_reg_reg_reg(list, op, size, src, dst, dst);
+end;
+
+procedure tcgppc.a_op_const_reg_reg(list: TAsmList; op: TOpCg;
+ size: tcgsize; a: aint; src, dst: tregister);
+var
+ useReg : boolean;
+
+ procedure do_lo_hi(loOp, hiOp : TAsmOp);
+ begin
+ { Optimization for logical ops (excluding AND), trying to do this as efficiently
+ as possible by only generating code for the affected halfwords. Note that all
+ the instructions handled here must have "X op 0 = X" for every halfword. }
+ usereg := false;
+ if (aword(a) > high(dword)) then begin
+ usereg := true;
+ end else begin
+ if (word(a) <> 0) then begin
+ list.concat(taicpu.op_reg_reg_const(loOp, dst, src, word(a)));
+ if (word(a shr 16) <> 0) then
+ list.concat(taicpu.op_reg_reg_const(hiOp, dst, dst, word(a shr 16)));
+ end else if (word(a shr 16) <> 0) then
+ list.concat(taicpu.op_reg_reg_const(hiOp, dst, src, word(a shr 16)));
+ end;
+ end;
+
+ procedure do_lo_hi_and;
+ begin
+ { optimization logical and with immediate: only use "andi." for 16 bit
+ ands, otherwise use register method. Doing this for 32 bit constants
+ would not give any advantage to the register method (via useReg := true),
+ requiring a scratch register and three instructions. }
+ usereg := false;
+ if (aword(a) > high(word)) then
+ usereg := true
+ else
+ list.concat(taicpu.op_reg_reg_const(A_ANDI_, dst, src, word(a)));
+ end;
+
+ procedure do_constant_div(list : TAsmList; size : TCgSize; a : aint; src, dst : TRegister;
+ signed : boolean);
+ const
+ negops : array[boolean] of tasmop = (A_NEG, A_NEGO);
+ var
+ magic, shift : int64;
+ u_magic : qword;
+ u_shift : byte;
+ u_add : boolean;
+ power : byte;
+ isNegPower : boolean;
+
+ divreg : tregister;
+ begin
+ if (a = 0) then begin
+ internalerror(2005061701);
+ end else if (a = 1) then begin
+ cg.a_load_reg_reg(current_asmdata.CurrAsmList, OS_INT, OS_INT, src, dst);
+ end else if (a = -1) and (signed) then begin
+ { note: only in the signed case possible..., may overflow }
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(negops[cs_check_overflow in current_settings.localswitches], dst, src));
+ end else if (ispowerof2(a, power, isNegPower)) then begin
+ if (signed) then begin
+ { From "The PowerPC Compiler Writer's Guide", pg. 52ff }
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_SAR, OS_INT, power,
+ src, dst);
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_ADDZE, dst, dst));
+ if (isNegPower) then
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_NEG, dst, dst));
+ end else begin
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_SHR, OS_INT, power, src, dst)
+ end;
+ end else begin
+ { replace division by multiplication, both implementations }
+ { from "The PowerPC Compiler Writer's Guide" pg. 53ff }
+ divreg := cg.getintregister(current_asmdata.CurrAsmList, OS_INT);
+ if (signed) then begin
+ getmagic_signedN(sizeof(aInt)*8, a, magic, shift);
+ { load magic value }
+ cg.a_load_const_reg(current_asmdata.CurrAsmList, OS_INT, magic, divreg);
+ { multiply }
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_MULHD, dst, src, divreg));
+ { add/subtract numerator }
+ if (a > 0) and (magic < 0) then begin
+ cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList, OP_ADD, OS_INT, src, dst, dst);
+ end else if (a < 0) and (magic > 0) then begin
+ cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList, OP_SUB, OS_INT, src, dst, dst);
+ end;
+ { shift shift places to the right (arithmetic) }
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_SAR, OS_INT, shift, dst, dst);
+ { extract and add sign bit }
+ if (a >= 0) then begin
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_SHR, OS_INT, 63, src, divreg);
+ end else begin
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_SHR, OS_INT, 63, dst, divreg);
+ end;
+ cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList, OP_ADD, OS_INT, dst, divreg, dst);
+ end else begin
+ getmagic_unsignedN(sizeof(aWord)*8, a, u_magic, u_add, u_shift);
+ { load magic in divreg }
+ cg.a_load_const_reg(current_asmdata.CurrAsmList, OS_INT, aint(u_magic), divreg);
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_MULHDU, dst, src, divreg));
+ if (u_add) then begin
+ cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList, OP_SUB, OS_INT, dst, src, divreg);
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_SHR, OS_INT, 1, divreg, divreg);
+ cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList, OP_ADD, OS_INT, divreg, dst, divreg);
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_SHR, OS_INT, u_shift-1, divreg, dst);
+ end else begin
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_SHR, OS_INT, u_shift, dst, dst);
+ end;
+ end;
+ end;
+ end;
+
+var
+ scratchreg: tregister;
+ shift : byte;
+ shiftmask : longint;
+ isneg : boolean;
+
+begin
+ { subtraction is the same as addition with negative constant }
+ if op = OP_SUB then begin
+ a_op_const_reg_reg(list, OP_ADD, size, -a, src, dst);
+ exit;
+ end;
+ {$IFDEF EXTDEBUG}
+ list.concat(tai_comment.create(strpnew('a_op_const_reg_reg ' + cgop2string(op))));
+ {$ENDIF EXTDEBUG}
+
+ { This case includes some peephole optimizations for the various operations,
+ (e.g. AND, OR, XOR, ..) - can't this be done at some higher level,
+ independent of architecture? }
+
+ { assume that we do not need a scratch register for the operation }
+ useReg := false;
+ case (op) of
+ OP_DIV, OP_IDIV:
+ if (cs_opt_level1 in current_settings.optimizerswitches) then
+ do_constant_div(list, size, a, src, dst, op = OP_IDIV)
+ else
+ usereg := true;
+ OP_IMUL, OP_MUL:
+ { idea: factorize constant multiplicands and use adds/shifts with few factors;
+ however, even a 64 bit multiply is already quite fast on PPC64 }
+ if (a = 0) then
+ a_load_const_reg(list, size, 0, dst)
+ else if (a = -1) then
+ list.concat(taicpu.op_reg_reg(A_NEG, dst, dst))
+ else if (a = 1) then
+ a_load_reg_reg(list, OS_INT, OS_INT, src, dst)
+ else if ispowerof2(a, shift, isneg) then begin
+ list.concat(taicpu.op_reg_reg_const(A_SLDI, dst, src, shift));
+ if (isneg) then
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_NEG, dst, dst));
+ end else if (a >= low(smallint)) and (a <= high(smallint)) then
+ list.concat(taicpu.op_reg_reg_const(A_MULLI, dst, src,
+ smallint(a)))
+ else
+ usereg := true;
+ OP_ADD:
+ if (a = 0) then
+ a_load_reg_reg(list, size, size, src, dst)
+ else if (a >= low(smallint)) and (a <= high(smallint)) then
+ list.concat(taicpu.op_reg_reg_const(A_ADDI, dst, src, smallint(a)))
+ else
+ useReg := true;
+ OP_OR:
+ if (a = 0) then
+ a_load_reg_reg(list, size, size, src, dst)
+ else if (a = -1) then
+ a_load_const_reg(list, size, -1, dst)
+ else
+ do_lo_hi(A_ORI, A_ORIS);
+ OP_AND:
+ if (a = 0) then
+ a_load_const_reg(list, size, 0, dst)
+ else if (a = -1) then
+ a_load_reg_reg(list, size, size, src, dst)
+ else
+ do_lo_hi_and;
+ OP_XOR:
+ if (a = 0) then
+ a_load_reg_reg(list, size, size, src, dst)
+ else if (a = -1) then
+ list.concat(taicpu.op_reg_reg(A_NOT, dst, src))
+ else
+ do_lo_hi(A_XORI, A_XORIS);
+ OP_ROL:
+ begin
+ if (size in [OS_64, OS_S64]) then begin
+ list.concat(taicpu.op_reg_reg_const_const(A_RLDICL, dst, src, a and 63, 0));
+ end else if (size in [OS_32, OS_S32]) then begin
+ list.concat(taicpu.op_reg_reg_const_const_const(A_RLWINM, dst, src, a and 31, 0, 31));
+ end else begin
+ internalerror(2008091303);
+ end;
+ end;
+ OP_ROR:
+ begin
+ if (size in [OS_64, OS_S64]) then begin
+ list.concat(taicpu.op_reg_reg_const_const(A_RLDICL, dst, src, ((64 - a) and 63), 0));
+ end else if (size in [OS_32, OS_S32]) then begin
+ list.concat(taicpu.op_reg_reg_const_const_const(A_RLWINM, dst, src, (32 - a) and 31, 0, 31));
+ end else begin
+ internalerror(2008091304);
+ end;
+ end;
+ OP_SHL, OP_SHR, OP_SAR:
+ begin
+ if (size in [OS_64, OS_S64]) then
+ shift := 6
+ else
+ shift := 5;
+
+ shiftmask := (1 shl shift)-1;
+ if (a and shiftmask) <> 0 then begin
+ list.concat(taicpu.op_reg_reg_const(
+ TShiftOpCG2AsmOpConst[size in [OS_64, OS_S64], op], dst, src, a and shiftmask));
+ end else
+ a_load_reg_reg(list, size, size, src, dst);
+ if ((a shr shift) <> 0) then
+ internalError(68991);
+ end
+ else
+ internalerror(200109091);
+ end;
+ { if all else failed, load the constant in a register and then
+ perform the operation }
+ if (useReg) then begin
+ scratchreg := rg[R_INTREGISTER].getregister(list, R_SUBWHOLE);
+ a_load_const_reg(list, size, a, scratchreg);
+ a_op_reg_reg_reg(list, op, size, scratchreg, src, dst);
+ end else
+ maybeadjustresult(list, op, size, dst);
+end;
+
+procedure tcgppc.a_op_reg_reg_reg(list: TAsmList; op: TOpCg;
+ size: tcgsize; src1, src2, dst: tregister);
+const
+ op_reg_reg_opcg2asmop32: array[TOpCG] of tasmop =
+ (A_NONE, A_MR, A_ADD, A_AND, A_DIVWU, A_DIVW, A_MULLW, A_MULLW, A_NEG, A_NOT, A_OR,
+ A_SRAW, A_SLW, A_SRW, A_SUB, A_XOR, A_NONE, A_NONE);
+ op_reg_reg_opcg2asmop64: array[TOpCG] of tasmop =
+ (A_NONE, A_MR, A_ADD, A_AND, A_DIVDU, A_DIVD, A_MULLD, A_MULLD, A_NEG, A_NOT, A_OR,
+ A_SRAD, A_SLD, A_SRD, A_SUB, A_XOR, A_NONE, A_NONE);
+var
+ tmpreg : TRegister;
+begin
+ case op of
+ OP_NEG, OP_NOT:
+ begin
+ list.concat(taicpu.op_reg_reg(op_reg_reg_opcg2asmop64[op], dst, src1));
+ if (op = OP_NOT) and not (size in [OS_64, OS_S64]) then
+ { zero/sign extend result again, fromsize is not important here }
+ a_load_reg_reg(list, OS_S64, size, dst, dst)
+ end;
+ OP_ROL:
+ begin
+ if (size in [OS_64, OS_S64]) then begin
+ list.concat(taicpu.op_reg_reg_reg_const(A_RLDCL, dst, src2, src1, 0));
+ end else if (size in [OS_32, OS_S32]) then begin
+ list.concat(taicpu.op_reg_reg_reg_const_const(A_RLWNM, dst, src2, src1, 0, 31));
+ end else begin
+ internalerror(2008091301);
+ end;
+ end;
+ OP_ROR:
+ begin
+ tmpreg := getintregister(current_asmdata.CurrAsmList, OS_INT);
+ list.concat(taicpu.op_reg_reg(A_NEG, tmpreg, src1));
+ if (size in [OS_64, OS_S64]) then begin
+ list.concat(taicpu.op_reg_reg_reg_const(A_RLDCL, dst, src2, tmpreg, 0));
+ end else if (size in [OS_32, OS_S32]) then begin
+ list.concat(taicpu.op_reg_reg_reg_const_const(A_RLWNM, dst, src2, tmpreg, 0, 31));
+ end else begin
+ internalerror(2008091302);
+ end;
+ end;
+ else
+ if (size in [OS_64, OS_S64]) then begin
+ list.concat(taicpu.op_reg_reg_reg(op_reg_reg_opcg2asmop64[op], dst, src2,
+ src1));
+ end else begin
+ list.concat(taicpu.op_reg_reg_reg(op_reg_reg_opcg2asmop32[op], dst, src2,
+ src1));
+ maybeadjustresult(list, op, size, dst);
+ end;
+ end;
+end;
+
+{*************** compare instructructions ****************}
+
+procedure tcgppc.a_cmp_const_reg_label(list: TAsmList; size: tcgsize;
+ cmp_op: topcmp; a: aint; reg: tregister; l: tasmlabel);
+const
+ { unsigned useconst 32bit-op }
+ cmpop_table : array[boolean, boolean, boolean] of TAsmOp = (
+ ((A_CMPD, A_CMPW), (A_CMPDI, A_CMPWI)),
+ ((A_CMPLD, A_CMPLW), (A_CMPLDI, A_CMPLWI))
+ );
+
+var
+ tmpreg : TRegister;
+ signed, useconst : boolean;
+ opsize : TCgSize;
+ op : TAsmOp;
+begin
+ {$IFDEF EXTDEBUG}
+ list.concat(tai_comment.create(strpnew('a_cmp_const_reg_label ' + cgsize2string(size) + ' ' + booltostr(cmp_op in [OC_GT, OC_LT, OC_GTE, OC_LTE]) + ' ' + inttostr(a) )));
+ {$ENDIF EXTDEBUG}
+
+ signed := cmp_op in [OC_GT, OC_LT, OC_GTE, OC_LTE];
+ { in the following case, we generate more efficient code when
+ signed is true }
+ if (cmp_op in [OC_EQ, OC_NE]) and
+ (aword(a) > $FFFF) then
+ signed := true;
+
+ opsize := size;
+
+ { do we need to change the operand size because ppc64 only supports 32 and
+ 64 bit compares? }
+ if (not (size in [OS_32, OS_S32, OS_64, OS_S64])) then begin
+ if (signed) then
+ opsize := OS_S32
+ else
+ opsize := OS_32;
+ a_load_reg_reg(current_asmdata.CurrAsmList, size, opsize, reg, reg);
+ end;
+
+ { can we use immediate compares? }
+ useconst := (signed and ( (a >= low(smallint)) and (a <= high(smallint)))) or
+ ((not signed) and (aword(a) <= $FFFF));
+
+ op := cmpop_table[not signed, useconst, opsize in [OS_32, OS_S32]];
+
+ if (useconst) then begin
+ list.concat(taicpu.op_reg_reg_const(op, NR_CR0, reg, a));
+ end else begin
+ tmpreg := getintregister(current_asmdata.CurrAsmList, OS_INT);
+ a_load_const_reg(current_asmdata.CurrAsmList, opsize, a, tmpreg);
+ list.concat(taicpu.op_reg_reg_reg(op, NR_CR0, reg, tmpreg));
+ end;
+
+ a_jmp(list, A_BC, TOpCmp2AsmCond[cmp_op], 0, l);
+end;
+
+procedure tcgppc.a_cmp_reg_reg_label(list: TAsmList; size: tcgsize;
+ cmp_op: topcmp; reg1, reg2: tregister; l: tasmlabel);
+var
+ op: tasmop;
+begin
+ {$IFDEF extdebug}
+ list.concat(tai_comment.create(strpnew('a_cmp_reg_reg_label, size ' + cgsize2string(size) + ' op ' + inttostr(ord(cmp_op)))));
+ {$ENDIF extdebug}
+
+ {$note Commented out below check because of compiler weirdness}
+ {
+ if (not (size in [OS_32, OS_S32, OS_64, OS_S64])) then
+ internalerror(200606041);
+ }
+
+ if cmp_op in [OC_GT, OC_LT, OC_GTE, OC_LTE] then
+ if (size in [OS_64, OS_S64]) then
+ op := A_CMPD
+ else
+ op := A_CMPW
+ else
+ if (size in [OS_64, OS_S64]) then
+ op := A_CMPLD
+ else
+ op := A_CMPLW;
+ list.concat(taicpu.op_reg_reg_reg(op, NR_CR0, reg2, reg1));
+ a_jmp(list, A_BC, TOpCmp2AsmCond[cmp_op], 0, l);
+end;
+
+procedure tcgppc.a_jmp_name_direct(list : TAsmList; s : string; prependDot : boolean);
+var
+ p: taicpu;
+begin
+ if (prependDot) then
+ s := '.' + s;
+ p := taicpu.op_sym(A_B, current_asmdata.RefAsmSymbol(s));
+ p.is_jmp := true;
+ list.concat(p)
+end;
+
+procedure tcgppc.a_jmp_name(list: TAsmList; const s: string);
+var
+ p: taicpu;
+begin
+ if (target_info.system = system_powerpc64_darwin) then
+ begin
+ p := taicpu.op_sym(A_B,get_darwin_call_stub(s,false));
+ p.is_jmp := true;
+ list.concat(p)
+ end
+ else
+ a_jmp_name_direct(list, s, true);
+end;
+
+procedure tcgppc.a_jmp_always(list: TAsmList; l: tasmlabel);
+
+begin
+ a_jmp(list, A_B, C_None, 0, l);
+end;
+
+procedure tcgppc.a_jmp_flags(list: TAsmList; const f: TResFlags; l:
+ tasmlabel);
+
+var
+ c: tasmcond;
+begin
+ c := flags_to_cond(f);
+ a_jmp(list, A_BC, c.cond, c.cr - RS_CR0, l);
+end;
+
+procedure tcgppc.g_flags2reg(list: TAsmList; size: TCgSize; const f:
+ TResFlags; reg: TRegister);
+var
+ testbit: byte;
+ bitvalue: boolean;
+begin
+ { get the bit to extract from the conditional register + its requested value (0 or 1) }
+ testbit := ((f.cr - RS_CR0) * 4);
+ case f.flag of
+ F_EQ, F_NE:
+ begin
+ inc(testbit, 2);
+ bitvalue := f.flag = F_EQ;
+ end;
+ F_LT, F_GE:
+ begin
+ bitvalue := f.flag = F_LT;
+ end;
+ F_GT, F_LE:
+ begin
+ inc(testbit);
+ bitvalue := f.flag = F_GT;
+ end;
+ else
+ internalerror(200112261);
+ end;
+ { load the conditional register in the destination reg }
+ list.concat(taicpu.op_reg(A_MFCR, reg));
+ { we will move the bit that has to be tested to bit 0 by rotating left }
+ testbit := (testbit + 1) and 31;
+ { extract bit }
+ list.concat(taicpu.op_reg_reg_const_const_const(
+ A_RLWINM,reg,reg,testbit,31,31));
+
+ { if we need the inverse, xor with 1 }
+ if not bitvalue then
+ list.concat(taicpu.op_reg_reg_const(A_XORI, reg, reg, 1));
+end;
+
+{ *********** entry/exit code and address loading ************ }
+
+procedure tcgppc.g_save_registers(list: TAsmList);
+begin
+ { this work is done in g_proc_entry; additionally it is not safe
+ to use it because it is called at some weird time }
+end;
+
+procedure tcgppc.g_restore_registers(list: TAsmList);
+begin
+ { this work is done in g_proc_exit; mainly because it is not safe to
+ put the register restore code here because it is called at some weird time }
+end;
+
+procedure tcgppc.calcFirstUsedFPR(out firstfpr : TSuperRegister; out fprcount : aint);
+var
+ reg : TSuperRegister;
+begin
+ fprcount := 0;
+ firstfpr := RS_F31;
+ if not (po_assembler in current_procinfo.procdef.procoptions) then
+ for reg := RS_F14 to RS_F31 do
+ if reg in rg[R_FPUREGISTER].used_in_proc then begin
+ fprcount := ord(RS_F31)-ord(reg)+1;
+ firstfpr := reg;
+ break;
+ end;
+end;
+
+procedure tcgppc.calcFirstUsedGPR(out firstgpr : TSuperRegister; out gprcount : aint);
+var
+ reg : TSuperRegister;
+begin
+ gprcount := 0;
+ firstgpr := RS_R31;
+ if not (po_assembler in current_procinfo.procdef.procoptions) then
+ for reg := RS_R14 to RS_R31 do
+ if reg in rg[R_INTREGISTER].used_in_proc then begin
+ gprcount := ord(RS_R31)-ord(reg)+1;
+ firstgpr := reg;
+ break;
+ end;
+end;
+
+procedure tcgppc.profilecode_savepara(para : tparavarsym; list : TAsmList);
+begin
+ case (para.paraloc[calleeside].location^.loc) of
+ LOC_REGISTER, LOC_CREGISTER:
+ a_load_reg_ref(list, OS_INT, para.paraloc[calleeside].Location^.size,
+ para.paraloc[calleeside].Location^.register, para.localloc.reference);
+ LOC_FPUREGISTER, LOC_CFPUREGISTER:
+ a_loadfpu_reg_ref(list, para.paraloc[calleeside].Location^.size,
+ para.paraloc[calleeside].Location^.size,
+ para.paraloc[calleeside].Location^.register, para.localloc.reference);
+ LOC_MMREGISTER, LOC_CMMREGISTER:
+ { not supported }
+ internalerror(2006041801);
+ end;
+end;
+
+procedure tcgppc.profilecode_restorepara(para : tparavarsym; list : TAsmList);
+begin
+ case (para.paraloc[calleeside].Location^.loc) of
+ LOC_REGISTER, LOC_CREGISTER:
+ a_load_ref_reg(list, para.paraloc[calleeside].Location^.size, OS_INT,
+ para.localloc.reference, para.paraloc[calleeside].Location^.register);
+ LOC_FPUREGISTER, LOC_CFPUREGISTER:
+ a_loadfpu_ref_reg(list, para.paraloc[calleeside].Location^.size,
+ para.paraloc[calleeside].Location^.size,
+ para.localloc.reference, para.paraloc[calleeside].Location^.register);
+ LOC_MMREGISTER, LOC_CMMREGISTER:
+ { not supported }
+ internalerror(2006041802);
+ end;
+end;
+
+procedure tcgppc.g_adjust_self_value(list:TAsmList;procdef: tprocdef;ioffset: aint);
+var
+ hsym : tsym;
+ href : treference;
+ paraloc : Pcgparalocation;
+begin
+ if ((ioffset >= low(smallint)) and (ioffset < high(smallint))) then begin
+ { the original method can handle this }
+ inherited g_adjust_self_value(list, procdef, ioffset);
+ exit;
+ end;
+ { calculate the parameter info for the procdef }
+ procdef.init_paraloc_info(callerside);
+ hsym:=tsym(procdef.parast.Find('self'));
+ if not(assigned(hsym) and
+ (hsym.typ=paravarsym)) then
+ internalerror(2010103101);
+ paraloc:=tparavarsym(hsym).paraloc[callerside].location;
+ while paraloc<>nil do
+ with paraloc^ do begin
+ case loc of
+ LOC_REGISTER:
+ begin
+ a_load_const_reg(list, size, ioffset, NR_R11);
+ a_op_reg_reg(list, OP_SUB, size, NR_R11, register);
+ end else
+ internalerror(2010103102);
+ end;
+ paraloc:=next;
+ end;
+end;
+
+procedure tcgppc.g_profilecode(list: TAsmList);
+begin
+ current_procinfo.procdef.paras.ForEachCall(TObjectListCallback(@profilecode_savepara), list);
+
+ a_call_name_direct(list, '_mcount', false, false, true);
+
+ current_procinfo.procdef.paras.ForEachCall(TObjectListCallback(@profilecode_restorepara), list);
+end;
+
+{ Generates the entry code of a procedure/function.
+
+ This procedure may be called before, as well as after g_return_from_proc
+ is called. localsize is the sum of the size necessary for local variables
+ and the maximum possible combined size of ALL the parameters of a procedure
+ called by the current one
+
+ IMPORTANT: registers are not to be allocated through the register
+ allocator here, because the register colouring has already occured !!
+}
+procedure tcgppc.g_proc_entry(list: TAsmList; localsize: longint;
+ nostackframe: boolean);
+var
+ firstregfpu, firstreggpr: TSuperRegister;
+ needslinkreg: boolean;
+
+ fprcount, gprcount : aint;
+
+ { Save standard registers, both FPR and GPR; does not support VMX/Altivec }
+ procedure save_standard_registers;
+ var
+ regcount : TSuperRegister;
+ href : TReference;
+ mayNeedLRStore : boolean;
+ begin
+ { there are two ways to do this: manually, by generating a few "std" instructions,
+ or via the restore helper functions. The latter are selected by the -Og switch,
+ i.e. "optimize for size" }
+ if (cs_opt_size in current_settings.optimizerswitches) and
+ (target_info.system <> system_powerpc64_darwin) then begin
+ mayNeedLRStore := false;
+ if ((fprcount > 0) and (gprcount > 0)) then begin
+ a_op_const_reg_reg(list, OP_SUB, OS_INT, 8 * fprcount, NR_R1, NR_R12);
+ a_call_name_direct(list, '_savegpr1_' + intToStr(32-gprcount), false, false, false, false);
+ a_call_name_direct(list, '_savefpr_' + intToStr(32-fprcount), false, false, false, false);
+ end else if (gprcount > 0) then
+ a_call_name_direct(list, '_savegpr0_' + intToStr(32-gprcount), false, false, false, false)
+ else if (fprcount > 0) then
+ a_call_name_direct(list, '_savefpr_' + intToStr(32-fprcount), false, false, false, false)
+ else
+ mayNeedLRStore := true;
+ end else begin
+ { save registers, FPU first, then GPR }
+ reference_reset_base(href, NR_STACK_POINTER_REG, -8, 8);
+ if (fprcount > 0) then
+ for regcount := RS_F31 downto firstregfpu do begin
+ a_loadfpu_reg_ref(list, OS_FLOAT, OS_FLOAT, newreg(R_FPUREGISTER,
+ regcount, R_SUBNONE), href);
+ dec(href.offset, tcgsize2size[OS_FLOAT]);
+ end;
+ if (gprcount > 0) then
+ for regcount := RS_R31 downto firstreggpr do begin
+ a_load_reg_ref(list, OS_INT, OS_INT, newreg(R_INTREGISTER, regcount,
+ R_SUBNONE), href);
+ dec(href.offset, sizeof(pint));
+ end;
+ { VMX registers not supported by FPC atm }
+
+ { in this branch we always need to store LR ourselves}
+ mayNeedLRStore := true;
+ end;
+
+ { we may need to store R0 (=LR) ourselves }
+ if ((cs_profile in init_settings.moduleswitches) or (mayNeedLRStore)) and (needslinkreg) then begin
+ reference_reset_base(href, NR_STACK_POINTER_REG, LA_LR_ELF, 8);
+ list.concat(taicpu.op_reg_ref(A_STD, NR_R0, href));
+ end;
+ end;
+
+var
+ href: treference;
+begin
+ calcFirstUsedFPR(firstregfpu, fprcount);
+ calcFirstUsedGPR(firstreggpr, gprcount);
+
+ { calculate real stack frame size }
+ localsize := tppcprocinfo(current_procinfo).calc_stackframe_size(
+ gprcount, fprcount);
+
+ { determine whether we need to save the link register }
+ needslinkreg :=
+ not(nostackframe) and
+ (save_lr_in_prologue or
+ ((cs_opt_size in current_settings.optimizerswitches) and
+ ((fprcount > 0) or
+ (gprcount > 0))));
+
+ a_reg_alloc(list, NR_STACK_POINTER_REG);
+ a_reg_alloc(list, NR_R0);
+
+ { move link register to r0 }
+ if (needslinkreg) then
+ list.concat(taicpu.op_reg(A_MFLR, NR_R0));
+
+ save_standard_registers;
+
+ { save old stack frame pointer }
+ if (tppcprocinfo(current_procinfo).needs_frame_pointer) then begin
+ a_reg_alloc(list, NR_OLD_STACK_POINTER_REG);
+ list.concat(taicpu.op_reg_reg(A_MR, NR_OLD_STACK_POINTER_REG, NR_STACK_POINTER_REG));
+ end;
+
+ { create stack frame }
+ if (not nostackframe) and (localsize > 0) and
+ tppcprocinfo(current_procinfo).needstackframe then begin
+ if (localsize <= high(smallint)) then begin
+ reference_reset_base(href, NR_STACK_POINTER_REG, -localsize, 8);
+ a_load_store(list, A_STDU, NR_STACK_POINTER_REG, href);
+ end else begin
+ reference_reset_base(href, NR_NO, -localsize, 8);
+
+ { Use R0 for loading the constant (which is definitely > 32k when entering
+ this branch).
+
+ Inlined at this position because it must not use temp registers because
+ register allocations have already been done }
+ { Code template:
+ lis r0,ofs@highest
+ ori r0,r0,ofs@higher
+ sldi r0,r0,32
+ oris r0,r0,ofs@h
+ ori r0,r0,ofs@l
+ }
+ list.concat(taicpu.op_reg_const(A_LIS, NR_R0, word(href.offset shr 48)));
+ list.concat(taicpu.op_reg_reg_const(A_ORI, NR_R0, NR_R0, word(href.offset shr 32)));
+ list.concat(taicpu.op_reg_reg_const(A_SLDI, NR_R0, NR_R0, 32));
+ list.concat(taicpu.op_reg_reg_const(A_ORIS, NR_R0, NR_R0, word(href.offset shr 16)));
+ list.concat(taicpu.op_reg_reg_const(A_ORI, NR_R0, NR_R0, word(href.offset)));
+
+ list.concat(taicpu.op_reg_reg_reg(A_STDUX, NR_R1, NR_R1, NR_R0));
+ end;
+ end;
+
+ { CR register not used by FPC atm }
+
+ { keep R1 allocated??? }
+ a_reg_dealloc(list, NR_R0);
+end;
+
+{ Generates the exit code for a method.
+
+ This procedure may be called before, as well as after g_stackframe_entry
+ is called.
+
+ IMPORTANT: registers are not to be allocated through the register
+ allocator here, because the register colouring has already occured !!
+}
+procedure tcgppc.g_proc_exit(list: TAsmList; parasize: longint; nostackframe:
+ boolean);
+var
+ firstregfpu, firstreggpr: TSuperRegister;
+ needslinkreg : boolean;
+ fprcount, gprcount: aint;
+
+ { Restore standard registers, both FPR and GPR; does not support VMX/Altivec }
+ procedure restore_standard_registers;
+ var
+ { flag indicating whether we need to manually add the exit code (e.g. blr instruction)
+ or not }
+ needsExitCode : Boolean;
+ href : treference;
+ regcount : TSuperRegister;
+ begin
+ { there are two ways to do this: manually, by generating a few "ld" instructions,
+ or via the restore helper functions. The latter are selected by the -Og switch,
+ i.e. "optimize for size" }
+ if (cs_opt_size in current_settings.optimizerswitches) then begin
+ needsExitCode := false;
+ if ((fprcount > 0) and (gprcount > 0)) then begin
+ a_op_const_reg_reg(list, OP_SUB, OS_INT, 8 * fprcount, NR_R1, NR_R12);
+ a_call_name_direct(list, '_restgpr1_' + intToStr(32-gprcount), false, false, false, false);
+ a_jmp_name_direct(list, '_restfpr_' + intToStr(32-fprcount), false);
+ end else if (gprcount > 0) then
+ a_jmp_name_direct(list, '_restgpr0_' + intToStr(32-gprcount), false)
+ else if (fprcount > 0) then
+ a_jmp_name_direct(list, '_restfpr_' + intToStr(32-fprcount), false)
+ else
+ needsExitCode := true;
+ end else begin
+ needsExitCode := true;
+ { restore registers, FPU first, GPR next }
+ reference_reset_base(href, NR_STACK_POINTER_REG, -tcgsize2size[OS_FLOAT], 8);
+ if (fprcount > 0) then
+ for regcount := RS_F31 downto firstregfpu do begin
+ a_loadfpu_ref_reg(list, OS_FLOAT, OS_FLOAT, href, newreg(R_FPUREGISTER, regcount,
+ R_SUBNONE));
+ dec(href.offset, tcgsize2size[OS_FLOAT]);
+ end;
+ if (gprcount > 0) then
+ for regcount := RS_R31 downto firstreggpr do begin
+ a_load_ref_reg(list, OS_INT, OS_INT, href, newreg(R_INTREGISTER, regcount,
+ R_SUBNONE));
+ dec(href.offset, sizeof(pint));
+ end;
+
+ { VMX not supported by FPC atm }
+ end;
+
+ if (needsExitCode) then begin
+
+ { restore LR (if needed) }
+ if (needslinkreg) then begin
+ reference_reset_base(href, NR_STACK_POINTER_REG, LA_LR_ELF, 8);
+ list.concat(taicpu.op_reg_ref(A_LD, NR_R0, href));
+ list.concat(taicpu.op_reg(A_MTLR, NR_R0));
+ end;
+
+ { generate return instruction }
+ list.concat(taicpu.op_none(A_BLR));
+ end;
+ end;
+
+var
+ href: treference;
+ localsize : aint;
+
+begin
+ calcFirstUsedFPR(firstregfpu, fprcount);
+ calcFirstUsedGPR(firstreggpr, gprcount);
+
+ { determine whether we need to restore the link register }
+ needslinkreg :=
+ not(nostackframe) and
+ (((not (po_assembler in current_procinfo.procdef.procoptions)) and
+ ((pi_do_call in current_procinfo.flags) or (cs_profile in init_settings.moduleswitches))) or
+ ((cs_opt_size in current_settings.optimizerswitches) and ((fprcount > 0) or (gprcount > 0))) or
+ ([cs_lineinfo, cs_debuginfo] * current_settings.moduleswitches <> []));
+
+ { calculate stack frame }
+ localsize := tppcprocinfo(current_procinfo).calc_stackframe_size(
+ gprcount, fprcount);
+ { CR register not supported }
+
+ { restore stack pointer }
+ if (not nostackframe) and (localsize > 0) and
+ tppcprocinfo(current_procinfo).needstackframe then begin
+ if (localsize <= high(smallint)) then begin
+ list.concat(taicpu.op_reg_reg_const(A_ADDI, NR_STACK_POINTER_REG, NR_STACK_POINTER_REG, localsize));
+ end else begin
+ reference_reset_base(href, NR_NO, localsize, 8);
+
+ { use R0 for loading the constant (which is definitely > 32k when entering
+ this branch)
+ Inlined because it must not use temp registers because register allocations
+ have already been done
+ }
+ { Code template:
+ lis r0,ofs@highest
+ ori r0,ofs@higher
+ sldi r0,r0,32
+ oris r0,r0,ofs@h
+ ori r0,r0,ofs@l
+ }
+ list.concat(taicpu.op_reg_const(A_LIS, NR_R0, word(href.offset shr 48)));
+ list.concat(taicpu.op_reg_reg_const(A_ORI, NR_R0, NR_R0, word(href.offset shr 32)));
+ list.concat(taicpu.op_reg_reg_const(A_SLDI, NR_R0, NR_R0, 32));
+ list.concat(taicpu.op_reg_reg_const(A_ORIS, NR_R0, NR_R0, word(href.offset shr 16)));
+ list.concat(taicpu.op_reg_reg_const(A_ORI, NR_R0, NR_R0, word(href.offset)));
+
+ list.concat(taicpu.op_reg_reg_reg(A_ADD, NR_R1, NR_R1, NR_R0));
+ end;
+ end;
+
+ restore_standard_registers;
+end;
+
+
+procedure tcgppc.a_loadaddr_ref_reg(list: TAsmList; const ref: treference; r:
+ tregister);
+
+var
+ ref2, tmpref: treference;
+ { register used to construct address }
+ tempreg : TRegister;
+
+begin
+ if (target_info.system = system_powerpc64_darwin) then
+ begin
+ inherited a_loadaddr_ref_reg(list,ref,r);
+ exit;
+ end;
+
+ ref2 := ref;
+ fixref(list, ref2);
+ { load a symbol }
+ if (assigned(ref2.symbol) or (hasLargeOffset(ref2))) then begin
+ { add the symbol's value to the base of the reference, and if the }
+ { reference doesn't have a base, create one }
+ reference_reset(tmpref, ref2.alignment);
+ tmpref.offset := ref2.offset;
+ tmpref.symbol := ref2.symbol;
+ tmpref.relsymbol := ref2.relsymbol;
+ { load 64 bit reference into r. If the reference already has a base register,
+ first load the 64 bit value into a temp register, then add it to the result
+ register rD }
+ if (ref2.base <> NR_NO) then begin
+ { already have a base register, so allocate a new one }
+ tempreg := rg[R_INTREGISTER].getregister(list, R_SUBWHOLE);
+ end else begin
+ tempreg := r;
+ end;
+
+ { code for loading a reference from a symbol into a register rD }
+ (*
+ lis rX,SYM@highest
+ ori rX,SYM@higher
+ sldi rX,rX,32
+ oris rX,rX,SYM@h
+ ori rX,rX,SYM@l
+ *)
+ {$IFDEF EXTDEBUG}
+ list.concat(tai_comment.create(strpnew('loadaddr_ref_reg ')));
+ {$ENDIF EXTDEBUG}
+ if (assigned(tmpref.symbol)) then begin
+ tmpref.refaddr := addr_highest;
+ list.concat(taicpu.op_reg_ref(A_LIS, tempreg, tmpref));
+ tmpref.refaddr := addr_higher;
+ list.concat(taicpu.op_reg_reg_ref(A_ORI, tempreg, tempreg, tmpref));
+ list.concat(taicpu.op_reg_reg_const(A_SLDI, tempreg, tempreg, 32));
+ tmpref.refaddr := addr_high;
+ list.concat(taicpu.op_reg_reg_ref(A_ORIS, tempreg, tempreg, tmpref));
+ tmpref.refaddr := addr_low;
+ list.concat(taicpu.op_reg_reg_ref(A_ORI, tempreg, tempreg, tmpref));
+ end else
+ a_load_const_reg(list, OS_ADDR, tmpref.offset, tempreg);
+
+ { if there's already a base register, add the temp register contents to
+ the base register }
+ if (ref2.base <> NR_NO) then begin
+ list.concat(taicpu.op_reg_reg_reg(A_ADD, r, tempreg, ref2.base));
+ end;
+ end else if (ref2.offset <> 0) then begin
+ { no symbol, but offset <> 0 }
+ if (ref2.base <> NR_NO) then begin
+ a_op_const_reg_reg(list, OP_ADD, OS_64, ref2.offset, ref2.base, r)
+ { FixRef makes sure that "(ref.index <> R_NO) and (ref.offset <> 0)" never
+ occurs, so now only ref.offset has to be loaded }
+ end else begin
+ a_load_const_reg(list, OS_64, ref2.offset, r);
+ end;
+ end else if (ref2.index <> NR_NO) then begin
+ list.concat(taicpu.op_reg_reg_reg(A_ADD, r, ref2.base, ref2.index))
+ end else if (ref2.base <> NR_NO) and
+ (r <> ref2.base) then begin
+ a_load_reg_reg(list, OS_ADDR, OS_ADDR, ref2.base, r)
+ end else begin
+ list.concat(taicpu.op_reg_const(A_LI, r, 0));
+ end;
+end;
+
+{ ************* concatcopy ************ }
+
+procedure tcgppc.g_concatcopy(list: TAsmList; const source, dest: treference;
+ len: aint);
+
+var
+ countreg, tempreg:TRegister;
+ src, dst: TReference;
+ lab: tasmlabel;
+ count, count2, step: longint;
+ size: tcgsize;
+
+begin
+{$IFDEF extdebug}
+ if len > high(aint) then
+ internalerror(2002072704);
+ list.concat(tai_comment.create(strpnew('g_concatcopy1 ' + inttostr(len) + ' bytes left ')));
+{$ENDIF extdebug}
+ { if the references are equal, exit, there is no need to copy anything }
+ if references_equal(source, dest) or
+ (len=0) then
+ exit;
+
+ { make sure short loads are handled as optimally as possible;
+ note that the data here never overlaps, so we can do a forward
+ copy at all times.
+ NOTE: maybe use some scratch registers to pair load/store instructions
+ }
+
+ if (len <= 8) then begin
+ src := source; dst := dest;
+ {$IFDEF extdebug}
+ list.concat(tai_comment.create(strpnew('g_concatcopy3 ' + inttostr(src.offset) + ' ' + inttostr(dst.offset))));
+ {$ENDIF extdebug}
+ while (len <> 0) do begin
+ if (len = 8) then begin
+ a_load_ref_ref(list, OS_64, OS_64, src, dst);
+ dec(len, 8);
+ end else if (len >= 4) then begin
+ a_load_ref_ref(list, OS_32, OS_32, src, dst);
+ inc(src.offset, 4); inc(dst.offset, 4);
+ dec(len, 4);
+ end else if (len >= 2) then begin
+ a_load_ref_ref(list, OS_16, OS_16, src, dst);
+ inc(src.offset, 2); inc(dst.offset, 2);
+ dec(len, 2);
+ end else begin
+ a_load_ref_ref(list, OS_8, OS_8, src, dst);
+ inc(src.offset, 1); inc(dst.offset, 1);
+ dec(len, 1);
+ end;
+ end;
+ exit;
+ end;
+{$IFDEF extdebug}
+ list.concat(tai_comment.create(strpnew('g_concatcopy2 ' + inttostr(len) + ' bytes left ')));
+{$ENDIF extdebug}
+
+
+ if not(source.alignment in [1,2]) and
+ not(dest.alignment in [1,2]) then
+ begin
+ count:=len div 8;
+ step:=8;
+ size:=OS_64;
+ end
+ else
+ begin
+ count:=len div 4;
+ step:=4;
+ size:=OS_32;
+ end;
+
+ tempreg:=getintregister(list,size);
+ reference_reset(src,source.alignment);
+ reference_reset(dst,dest.alignment);
+ { load the address of source into src.base }
+ if (count > 4) or
+ not issimpleref(source) or
+ ((source.index <> NR_NO) and
+ ((source.offset + len) > high(smallint))) then begin
+ src.base := getaddressregister(list);
+ a_loadaddr_ref_reg(list, source, src.base);
+ end else begin
+ src := source;
+ end;
+ { load the address of dest into dst.base }
+ if (count > 4) or
+ not issimpleref(dest) or
+ ((dest.index <> NR_NO) and
+ ((dest.offset + len) > high(smallint))) then begin
+ dst.base := getaddressregister(list);
+ a_loadaddr_ref_reg(list, dest, dst.base);
+ end else begin
+ dst := dest;
+ end;
+
+ { generate a loop }
+ if count > 4 then begin
+ { the offsets are zero after the a_loadaddress_ref_reg and just
+ have to be set to step. I put an Inc there so debugging may be
+ easier (should offset be different from zero here, it will be
+ easy to notice in the generated assembler }
+ inc(dst.offset, step);
+ inc(src.offset, step);
+ list.concat(taicpu.op_reg_reg_const(A_SUBI, src.base, src.base, step));
+ list.concat(taicpu.op_reg_reg_const(A_SUBI, dst.base, dst.base, step));
+ countreg := getintregister(list, OS_INT);
+ a_load_const_reg(list, OS_INT, count, countreg);
+ current_asmdata.getjumplabel(lab);
+ a_label(list, lab);
+ list.concat(taicpu.op_reg_reg_const(A_SUBIC_, countreg, countreg, 1));
+ if (size=OS_64) then
+ begin
+ list.concat(taicpu.op_reg_ref(A_LDU, tempreg, src));
+ list.concat(taicpu.op_reg_ref(A_STDU, tempreg, dst));
+ end
+ else
+ begin
+ list.concat(taicpu.op_reg_ref(A_LWZU, tempreg, src));
+ list.concat(taicpu.op_reg_ref(A_STWU, tempreg, dst));
+ end;
+ a_jmp(list, A_BC, C_NE, 0, lab);
+ a_reg_sync(list,src.base);
+ a_reg_sync(list,dst.base);
+ a_reg_sync(list,countreg);
+ len := len mod step;
+ count := 0;
+ end;
+
+ { unrolled loop }
+ if count > 0 then begin
+ for count2 := 1 to count do begin
+ a_load_ref_reg(list, size, size, src, tempreg);
+ a_load_reg_ref(list, size, size, tempreg, dst);
+ inc(src.offset, step);
+ inc(dst.offset, step);
+ end;
+ len := len mod step;
+ end;
+
+ if (len and 4) <> 0 then begin
+ a_load_ref_reg(list, OS_32, OS_32, src, tempreg);
+ a_load_reg_ref(list, OS_32, OS_32, tempreg, dst);
+ inc(src.offset, 4);
+ inc(dst.offset, 4);
+ end;
+ { copy the leftovers }
+ if (len and 2) <> 0 then begin
+ a_load_ref_reg(list, OS_16, OS_16, src, tempreg);
+ a_load_reg_ref(list, OS_16, OS_16, tempreg, dst);
+ inc(src.offset, 2);
+ inc(dst.offset, 2);
+ end;
+ if (len and 1) <> 0 then begin
+ a_load_ref_reg(list, OS_8, OS_8, src, tempreg);
+ a_load_reg_ref(list, OS_8, OS_8, tempreg, dst);
+ end;
+
+end;
+
+procedure tcgppc.g_external_wrapper(list: TAsmList; pd: TProcDef; const externalname: string);
+var
+ href : treference;
+begin
+ if (target_info.system <> system_powerpc64_linux) then begin
+ inherited;
+ exit;
+ end;
+
+ { for ppc64/linux emit correct code which sets up a stack frame and then calls the
+ external method normally to ensure that the GOT/TOC will be loaded correctly if
+ required.
+
+ It's not really advantageous to use cg methods here because they are too specialized.
+
+ I.e. the resulting code sequence looks as follows:
+
+ mflr r0
+ std r0, 16(r1)
+ stdu r1, -112(r1)
+ bl <external_method>
+ nop
+ addi r1, r1, 112
+ ld r0, 16(r1)
+ mtlr r0
+ blr
+
+ }
+ list.concat(taicpu.op_reg(A_MFLR, NR_R0));
+ reference_reset_base(href, NR_STACK_POINTER_REG, 16, 8);
+ list.concat(taicpu.op_reg_ref(A_STD, NR_R0, href));
+ reference_reset_base(href, NR_STACK_POINTER_REG, -MINIMUM_STACKFRAME_SIZE, 8);
+ list.concat(taicpu.op_reg_ref(A_STDU, NR_STACK_POINTER_REG, href));
+
+ list.concat(taicpu.op_sym(A_BL, current_asmdata.RefAsmSymbol(externalname)));
+ list.concat(taicpu.op_none(A_NOP));
+
+ list.concat(taicpu.op_reg_reg_const(A_ADDI, NR_STACK_POINTER_REG, NR_STACK_POINTER_REG, MINIMUM_STACKFRAME_SIZE));
+
+ reference_reset_base(href, NR_STACK_POINTER_REG, LA_LR_ELF, 8);
+ list.concat(taicpu.op_reg_ref(A_LD, NR_R0, href));
+ list.concat(taicpu.op_reg(A_MTLR, NR_R0));
+ list.concat(taicpu.op_none(A_BLR));
+end;
+
+{***************** This is private property, keep out! :) *****************}
+
+procedure tcgppc.maybeadjustresult(list: TAsmList; op: TOpCg; size: tcgsize; dst: tregister);
+const
+ overflowops = [OP_MUL,OP_SHL,OP_ADD,OP_SUB,OP_NOT,OP_NEG];
+begin
+ {$IFDEF EXTDEBUG}
+ list.concat(tai_comment.create(strpnew('maybeadjustresult op = ' + cgop2string(op) + ' size = ' + cgsize2string(size))));
+ {$ENDIF EXTDEBUG}
+
+ if (op in overflowops) and (size in [OS_8, OS_S8, OS_16, OS_S16, OS_32, OS_S32]) then
+ a_load_reg_reg(list, OS_64, size, dst, dst);
+end;
+
+function tcgppc.issimpleref(const ref: treference): boolean;
+
+begin
+ if (ref.base = NR_NO) and
+ (ref.index <> NR_NO) then
+ internalerror(200208101);
+ result :=
+ not (assigned(ref.symbol)) and
+ (((ref.index = NR_NO) and
+ (ref.offset >= low(smallint)) and
+ (ref.offset <= high(smallint))) or
+ ((ref.index <> NR_NO) and
+ (ref.offset = 0)));
+end;
+
+procedure tcgppc.a_load_store(list: TAsmList; op: tasmop; reg: tregister;
+ ref: treference);
+
+ procedure maybefixup64bitoffset;
+ var
+ tmpreg: tregister;
+ begin
+ { for some instructions we need to check that the offset is divisible by at
+ least four. If not, add the bytes which are "off" to the base register and
+ adjust the offset accordingly }
+ case op of
+ A_LD, A_LDU, A_STD, A_STDU, A_LWA :
+ if ((ref.offset mod 4) <> 0) then begin
+ tmpreg := rg[R_INTREGISTER].getregister(list, R_SUBWHOLE);
+
+ if (ref.base <> NR_NO) then begin
+ a_op_const_reg_reg(list, OP_ADD, OS_ADDR, ref.offset mod 4, ref.base, tmpreg);
+ ref.base := tmpreg;
+ end else begin
+ list.concat(taicpu.op_reg_const(A_LI, tmpreg, ref.offset mod 4));
+ ref.base := tmpreg;
+ end;
+ ref.offset := (ref.offset div 4) * 4;
+ end;
+ end;
+ end;
+
+var
+ tmpreg, tmpreg2: tregister;
+ tmpref: treference;
+ largeOffset: Boolean;
+begin
+ if (target_info.system = system_powerpc64_darwin) then
+ begin
+ { darwin/ppc64 works with 32 bit relocatable symbol addresses }
+ maybefixup64bitoffset;
+ inherited a_load_store(list,op,reg,ref);
+ exit
+ end;
+
+ { at this point there must not be a combination of values in the ref treference
+ which is not possible to directly map to instructions of the PowerPC architecture }
+ if (ref.index <> NR_NO) and ((ref.offset <> 0) or (assigned(ref.symbol))) then
+ internalerror(200310131);
+
+ { if this is a PIC'ed address, handle it and exit }
+ if (ref.refaddr = addr_pic) then begin
+ if (ref.offset <> 0) then
+ internalerror(2006010501);
+ if (ref.index <> NR_NO) then
+ internalerror(2006010502);
+ if (not assigned(ref.symbol)) then
+ internalerror(200601050);
+ list.concat(taicpu.op_reg_ref(op, reg, ref));
+ exit;
+ end;
+
+ maybefixup64bitoffset;
+ {$IFDEF EXTDEBUG}
+ list.concat(tai_comment.create(strpnew('a_load_store1 ' + BoolToStr(ref.refaddr = addr_pic))));
+ {$ENDIF EXTDEBUG}
+ { if we have to load/store from a symbol or large addresses, use a temporary register
+ containing the address }
+ if (assigned(ref.symbol) or (hasLargeOffset(ref))) then begin
+ tmpreg := rg[R_INTREGISTER].getregister(list, R_SUBWHOLE);
+
+ if (hasLargeOffset(ref) and (ref.base = NR_NO)) then begin
+ ref.base := rg[R_INTREGISTER].getregister(list, R_SUBWHOLE);
+ a_load_const_reg(list, OS_ADDR, ref.offset, ref.base);
+ ref.offset := 0;
+ end;
+
+ reference_reset(tmpref, ref.alignment);
+ tmpref.symbol := ref.symbol;
+ tmpref.relsymbol := ref.relsymbol;
+ tmpref.offset := ref.offset;
+
+ if (ref.base <> NR_NO) then begin
+ { As long as the TOC isn't working we try to achieve highest speed (in this
+ case by allowing instructions execute in parallel) as possible at the cost
+ of using another temporary register. So the code template when there is
+ a base register and an offset is the following:
+
+ lis rT1, SYM+offs@highest
+ ori rT1, rT1, SYM+offs@higher
+ lis rT2, SYM+offs@hi
+ ori rT2, SYM+offs@lo
+ rldimi rT2, rT1, 32
+
+ <op>X reg, base, rT2
+ }
+
+ tmpreg2 := rg[R_INTREGISTER].getregister(list, R_SUBWHOLE);
+ if (assigned(tmpref.symbol)) then begin
+ tmpref.refaddr := addr_highest;
+ list.concat(taicpu.op_reg_ref(A_LIS, tmpreg, tmpref));
+ tmpref.refaddr := addr_higher;
+ list.concat(taicpu.op_reg_reg_ref(A_ORI, tmpreg, tmpreg, tmpref));
+
+ tmpref.refaddr := addr_high;
+ list.concat(taicpu.op_reg_ref(A_LIS, tmpreg2, tmpref));
+ tmpref.refaddr := addr_low;
+ list.concat(taicpu.op_reg_reg_ref(A_ORI, tmpreg2, tmpreg2, tmpref));
+
+ list.concat(taicpu.op_reg_reg_const_const(A_RLDIMI, tmpreg2, tmpreg, 32, 0));
+ end else
+ a_load_const_reg(list, OS_ADDR, tmpref.offset, tmpreg2);
+
+ reference_reset(tmpref, ref.alignment);
+ tmpref.base := ref.base;
+ tmpref.index := tmpreg2;
+ case op of
+ { the code generator doesn't generate update instructions anyway, so
+ error out on those instructions }
+ A_LBZ : op := A_LBZX;
+ A_LHZ : op := A_LHZX;
+ A_LWZ : op := A_LWZX;
+ A_LD : op := A_LDX;
+ A_LHA : op := A_LHAX;
+ A_LWA : op := A_LWAX;
+ A_LFS : op := A_LFSX;
+ A_LFD : op := A_LFDX;
+
+ A_STB : op := A_STBX;
+ A_STH : op := A_STHX;
+ A_STW : op := A_STWX;
+ A_STD : op := A_STDX;
+
+ A_STFS : op := A_STFSX;
+ A_STFD : op := A_STFDX;
+ else
+ { unknown load/store opcode }
+ internalerror(2005101302);
+ end;
+ list.concat(taicpu.op_reg_ref(op, reg, tmpref));
+ end else begin
+ { when accessing value from a reference without a base register, use the
+ following code template:
+
+ lis rT,SYM+offs@highesta
+ ori rT,SYM+offs@highera
+ sldi rT,rT,32
+ oris rT,rT,SYM+offs@ha
+ ld rD,SYM+offs@l(rT)
+ }
+ tmpref.refaddr := addr_highesta;
+ list.concat(taicpu.op_reg_ref(A_LIS, tmpreg, tmpref));
+ tmpref.refaddr := addr_highera;
+ list.concat(taicpu.op_reg_reg_ref(A_ORI, tmpreg, tmpreg, tmpref));
+ list.concat(taicpu.op_reg_reg_const(A_SLDI, tmpreg, tmpreg, 32));
+ tmpref.refaddr := addr_higha;
+ list.concat(taicpu.op_reg_reg_ref(A_ORIS, tmpreg, tmpreg, tmpref));
+
+ tmpref.base := tmpreg;
+ tmpref.refaddr := addr_low;
+ list.concat(taicpu.op_reg_ref(op, reg, tmpref));
+ end;
+ end else begin
+ list.concat(taicpu.op_reg_ref(op, reg, ref));
+ end;
+end;
+
+procedure tcgppc.loadConstantPIC(list : TAsmList; size : TCGSize; a : aint; reg : TRegister);
+var
+ l: tasmsymbol;
+ ref: treference;
+ symname : string;
+begin
+ maybe_new_object_file(current_asmdata.asmlists[al_picdata]);
+ symname := '_$' + current_asmdata.name + '$toc$' + hexstr(a, sizeof(a)*2);
+ l:=current_asmdata.getasmsymbol(symname);
+ if not(assigned(l)) then begin
+ l:=current_asmdata.DefineAsmSymbol(symname,AB_GLOBAL, AT_DATA);
+ new_section(current_asmdata.asmlists[al_picdata],sec_toc, '.toc', 8);
+ current_asmdata.asmlists[al_picdata].concat(tai_symbol.create_global(l,0));
+ current_asmdata.asmlists[al_picdata].concat(tai_directive.create(asd_toc_entry, symname + '[TC], ' + inttostr(a)));
+ end;
+ reference_reset_symbol(ref,l,0, 8);
+ ref.base := NR_R2;
+ ref.refaddr := addr_no;
+
+ {$IFDEF EXTDEBUG}
+ list.concat(tai_comment.create(strpnew('loading value from TOC reference for ' + symname)));
+ {$ENDIF EXTDEBUG}
+ cg.a_load_ref_reg(list, OS_INT, OS_INT, ref, reg);
+end;
+
+
+procedure create_codegen;
+begin
+ cg := tcgppc.create;
+end;
+
+end.
diff --git a/closures/compiler/powerpc64/cpubase.pas b/closures/compiler/powerpc64/cpubase.pas
new file mode 100644
index 0000000000..ecdeba7398
--- /dev/null
+++ b/closures/compiler/powerpc64/cpubase.pas
@@ -0,0 +1,572 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Contains the base types for the PowerPC
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+{ This Unit contains the base types for the PowerPC64
+}
+unit cpubase;
+
+{$I fpcdefs.inc}
+
+interface
+
+uses
+ strings, globtype,
+ cutils, cclasses, aasmbase, cpuinfo, cgbase;
+
+{*****************************************************************************
+ Assembler Opcodes
+*****************************************************************************}
+
+type
+ TAsmOp = (A_None,
+ { normal opcodes }
+ a_add, a_add_, a_addo, a_addo_, a_addc, a_addc_, a_addco, a_addco_,
+ a_adde, a_adde_, a_addeo, a_addeo_, a_addi, a_addic, a_addic_, a_addis,
+ a_addme, a_addme_, a_addmeo, a_addmeo_, a_addze, a_addze_, a_addzeo,
+ a_addzeo_, a_and, a_and_, a_andc, a_andc_, a_andi_, a_andis_, a_b,
+ a_ba, a_bl, a_bla, a_bc, a_bca, a_bcl, a_bcla, a_bcctr, a_bcctrl, a_bclr,
+ a_bclrl, a_cmp, a_cmpi, a_cmpl, a_cmpli, a_cntlzw, a_cntlzw_, a_crand,
+ a_crandc, a_creqv, a_crnand, a_crnor, a_cror, a_crorc, a_crxor, a_dcba,
+ a_dcbf, a_dcbi, a_dcbst, a_dcbt, a_dcbtst, a_dcbz, a_divw, a_divw_, a_divwo,
+ a_divwo_,
+ a_divwu, a_divwu_, a_divwuo, a_divwuo_, a_eciwx, a_ecowx, a_eieio, a_eqv,
+ a_eqv_, a_extsb, a_extsb_, a_extsh, a_extsh_, a_fabs, a_fabs_, a_fadd,
+ a_fadd_, a_fadds, a_fadds_, a_fcmpo, a_fcmpu, a_fctiw, a_fctiw_, a_fctiwz,
+ a_fctwz_, a_fdiv, a_fdiv_, a_fdivs, a_fdivs_, a_fmadd, a_fmadd_, a_fmadds,
+ a_fmadds_, a_fmr, a_fmsub, a_fmsub_, a_fmsubs, a_fmsubs_, a_fmul, a_fmul_,
+ a_fmuls, a_fmuls_, a_fnabs, a_fnabs_, a_fneg, a_fneg_, a_fnmadd,
+ a_fnmadd_, a_fnmadds, a_fnmadds_, a_fnmsub, a_fnmsub_, a_fnmsubs,
+ a_fnmsubs_, a_fres, a_fres_, a_frsp, a_frsp_, a_frsqrte, a_frsqrte_,
+ a_fsel, a_fsel_, a_fsqrt, a_fsqrt_, a_fsqrts, a_fsqrts_, a_fsub, a_fsub_,
+ a_fsubs, a_fsubs_, a_icbi, a_isync, a_lbz, a_lbzu, a_lbzux, a_lbzx,
+ a_lfd, a_lfdu, a_lfdux, a_lfdx, a_lfs, a_lfsu, a_lfsux, a_lfsx, a_lha,
+ a_lhau, a_lhaux, a_lhax, a_lhbrx, a_lhz, a_lhzu, a_lhzux, a_lhzx, a_lmw,
+ a_lswi, a_lswx, a_lwarx, a_lwbrx, a_lwz, a_lwzu, a_lwzux, a_lwzx, a_mcrf,
+ a_mcrfs, a_mcrxr, a_mfcr, a_mffs, a_mffs_, a_mfmsr, a_mfspr, a_mfsr,
+ a_mfsrin, a_mftb, a_mtcrf, a_mtfsb0, a_mtfsb1, a_mtfsf, a_mtfsf_,
+ a_mtfsfi, a_mtfsfi_, a_mtmsr, a_mtspr, a_mtsr, a_mtsrin, a_mulhw,
+ a_mulhw_, a_mulhwu, a_mulhwu_, a_mulli, a_mullw, a_mullw_, a_mullwo,
+ a_mullwo_, a_nand, a_nand_, a_neg, a_neg_, a_nego, a_nego_, a_nor, a_nor_,
+ a_or, a_or_, a_orc, a_orc_, a_ori, a_oris, a_rfi, a_rlwimi, a_rlwimi_,
+ a_rlwinm, a_rlwinm_, a_rlwnm, a_sc, a_slw, a_slw_, a_sraw, a_sraw_,
+ a_srawi, a_srawi_, a_srw, a_srw_, a_stb, a_stbu, a_stbux, a_stbx, a_stfd,
+ a_stfdu, a_stfdux, a_stfdx, a_stfiwx, a_stfs, a_stfsu, a_stfsux, a_stfsx,
+ a_sth, a_sthbrx, a_sthu, a_sthux, a_sthx, a_stmw, a_stswi, a_stswx, a_stw,
+ a_stwbrx, a_stwcx_, a_stwu, a_stwux, a_stwx, a_subf, a_subf_, a_subfo,
+ a_subfo_, a_subfc, a_subfc_, a_subfco, a_subfco_, a_subfe, a_subfe_,
+ a_subfeo, a_subfeo_, a_subfic, a_subfme, a_subfme_, a_subfmeo, a_subfmeo_,
+ a_subfze, a_subfze_, a_subfzeo, a_subfzeo_, a_sync, a_tlbia, a_tlbie,
+ a_tlbsync, a_tw, a_twi, a_xor, a_xor_, a_xori, a_xoris,
+ { simplified mnemonics }
+ a_subi, a_subis, a_subic, a_subic_, a_sub, a_sub_, a_subo, a_subo_,
+ a_subc, a_subc_, a_subco, a_subco_, a_cmpwi, a_cmpw, a_cmplwi, a_cmplw,
+ a_extlwi, a_extlwi_, a_extrwi, a_extrwi_, a_inslwi, a_inslwi_, a_insrwi,
+ a_insrwi_, a_rotlwi, a_rotlwi_, a_rotlw, a_rotlw_, a_slwi, a_slwi_,
+ a_srwi, a_srwi_, a_clrlwi, a_clrlwi_, a_clrrwi, a_clrrwi_, a_clrslwi,
+ a_clrslwi_, a_bf, a_bt, a_blr, a_bctr, a_blrl, a_bctrl, a_crset, a_crclr, a_crmove,
+ a_crnot, a_mt {move to special prupose reg}, a_mf
+ {move from special purpose reg},
+ a_nop, a_li, a_lis, a_la, a_mr, a_mr_, a_not, a_mtcr, a_mtlr, a_mflr,
+ a_mtctr, a_mfctr,
+ A_EXTSW,
+ A_RLDIMI,
+ A_STD, A_STDU, A_STDX, A_STDUX,
+ A_LD, A_LDU, A_LDX, A_LDUX,
+ A_CMPD, A_CMPDI, A_CMPLD, A_CMPLDI,
+ A_SRDI, A_SRADI,
+ A_SLDI,
+ A_RLDCL, A_RLDICL,
+ A_DIVDU, A_DIVDU_, A_DIVD, A_DIVD_, A_MULLD, A_MULLD_, A_MULHD, A_MULHD_, A_SRAD, A_SLD, A_SRD,
+ A_DIVDUO_, A_DIVDO_,
+ A_LWA, A_LWAX, A_LWAUX,
+ A_FCFID,
+ A_LDARX, A_STDCX_, A_CNTLZD,
+ A_LVX, A_STVX,
+ A_MULLDO, A_MULLDO_, A_MULHDU, A_MULHDU_,
+ A_MFXER,
+ A_FCTID, A_FCTID_, A_FCTIDZ, A_FCTIDZ_,
+ A_EXTRDI, A_EXTRDI_, A_INSRDI, A_INSRDI_,
+ A_LWSYNC);
+
+ {# This should define the array of instructions as string }
+ op2strtable = array[tasmop] of string[8];
+
+const
+ {# First value of opcode enumeration }
+ firstop = low(tasmop);
+ {# Last value of opcode enumeration }
+ lastop = high(tasmop);
+
+ {*****************************************************************************
+ Registers
+ *****************************************************************************}
+
+type
+ { Number of registers used for indexing in tables }
+ tregisterindex = 0..{$I rppcnor.inc} - 1;
+ totherregisterset = set of tregisterindex;
+
+const
+ maxvarregs = 32 - 6;
+ { 32 int registers - r0 - stackpointer - r2 - 3 scratch registers }
+ maxfpuvarregs = 28; { 32 fpuregisters - some scratch registers (minimally 2) }
+ { Available Superregisters }
+{$I rppcsup.inc}
+
+ { No Subregisters }
+ R_SUBWHOLE = R_SUBNONE;
+
+ { Available Registers }
+{$I rppccon.inc}
+
+ { Integer Super registers first and last }
+ first_int_imreg = $20;
+
+ { Float Super register first and last }
+ first_fpu_imreg = $20;
+
+ { MM Super register first and last }
+ first_mm_imreg = $20;
+
+{ TODO: Calculate bsstart}
+ regnumber_count_bsstart = 64;
+
+ regnumber_table: array[tregisterindex] of tregister = (
+{$I rppcnum.inc}
+ );
+
+ regstabs_table: array[tregisterindex] of shortint = (
+{$I rppcstab.inc}
+ );
+
+ regdwarf_table: array[tregisterindex] of shortint = (
+{$I rppcdwrf.inc}
+ );
+
+ {*****************************************************************************
+ Conditions
+ *****************************************************************************}
+
+type
+ TAsmCondFlag = (C_None { unconditional jumps },
+ { conditions when not using ctr decrement etc }
+ C_LT, C_LE, C_EQ, C_GE, C_GT, C_NL, C_NE, C_NG, C_SO, C_NS, C_UN, C_NU,
+ { conditions when using ctr decrement etc }
+ C_T, C_F, C_DNZ, C_DNZT, C_DNZF, C_DZ, C_DZT, C_DZF);
+
+ TDirHint = (DH_None, DH_Minus, DH_Plus);
+
+const
+ { these are in the XER, but when moved to CR_x they correspond with the }
+ { bits below }
+ C_OV = C_GT;
+ C_CA = C_EQ;
+ C_NO = C_NG;
+ C_NC = C_NE;
+
+type
+ TAsmCond = packed record
+ dirhint: tdirhint;
+ case simple: boolean of
+ false: (BO, BI: byte);
+ true: (
+ cond: TAsmCondFlag;
+ case byte of
+ 0: ();
+ { specifies in which part of the cr the bit has to be }
+ { tested for blt,bgt,beq,..,bnu }
+ 1: (cr: RS_CR0..RS_CR7);
+ { specifies the bit to test for bt,bf,bdz,..,bdzf }
+ 2: (crbit: byte)
+ );
+ end;
+
+const
+ AsmCondFlag2BO: array[C_T..C_DZF] of Byte =
+ (12, 4, 16, 8, 0, 18, 10, 2);
+
+ AsmCondFlag2BOLT_NU: array[C_LT..C_NU] of Byte =
+ (12, 4, 12, 4, 12, 4, 4, 4, 12, 4, 12, 4);
+
+ AsmCondFlag2BI: array[C_LT..C_NU] of Byte =
+ (0, 1, 2, 0, 1, 0, 2, 1, 3, 3, 3, 3);
+
+ AsmCondFlagTF: array[TAsmCondFlag] of Boolean =
+ (false, true, false, true, false, true, false, false, false, true, false,
+ true, false,
+ true, false, false, true, false, false, true, false);
+
+ AsmCondFlag2Str : array[TAsmCondFlag] of string[4] = ({cf_none}'',
+ { conditions when not using ctr decrement etc}
+ 'lt', 'le', 'eq', 'ge', 'gt', 'nl', 'ne', 'ng', 'so', 'ns', 'un', 'nu',
+ 't', 'f', 'dnz', 'dnzt', 'dnzf', 'dz', 'dzt', 'dzf');
+
+ UpperAsmCondFlag2Str: array[TAsmCondFlag] of string[4] = ({cf_none}'',
+ { conditions when not using ctr decrement etc}
+ 'LT', 'LE', 'EQ', 'GE', 'GT', 'NL', 'NE', 'NG', 'SO', 'NS', 'UN', 'NU',
+ 'T', 'F', 'DNZ', 'DNZT', 'DNZF', 'DZ', 'DZT', 'DZF');
+
+const
+ CondAsmOps = 3;
+ CondAsmOp: array[0..CondAsmOps - 1] of TasmOp = (
+ A_BC, A_TW, A_TWI
+ );
+ CondAsmOpStr:array[0..CondAsmOps-1] of string[7]=(
+ 'B','TW','TWI'
+ );
+
+
+ {*****************************************************************************
+ Flags
+ *****************************************************************************}
+
+type
+ TResFlagsEnum = (F_EQ, F_NE, F_LT, F_LE, F_GT, F_GE, F_SO, F_FX, F_FEX, F_VX,
+ F_OX);
+ TResFlags = record
+ cr: RS_CR0..RS_CR7;
+ flag: TResFlagsEnum;
+ end;
+
+{*****************************************************************************
+ Reference
+*****************************************************************************}
+
+const
+ { MacOS only. Whether the direct data area (TOC) directly contain
+ global variables. Otherwise it contains pointers to global variables. }
+ macos_direct_globals = false;
+
+ {*****************************************************************************
+ Operand Sizes
+ *****************************************************************************}
+
+ {*****************************************************************************
+ Constants
+ *****************************************************************************}
+
+const
+ max_operands = 5;
+
+ {*****************************************************************************
+ Default generic sizes
+ *****************************************************************************}
+
+ {# Defines the default address size for a processor, }
+ OS_ADDR = OS_64;
+ {# the natural int size for a processor, }
+ OS_INT = OS_64;
+ OS_SINT = OS_S64;
+ {# the maximum float size for a processor, }
+ OS_FLOAT = OS_F64;
+ {# the size of a vector register for a processor }
+ OS_VECTOR = OS_M128;
+
+ {*****************************************************************************
+ GDB Information
+ *****************************************************************************}
+
+ {# Register indexes for stabs information, when some
+ parameters or variables are stored in registers.
+
+ Taken from rs6000.h (DBX_REGISTER_NUMBER)
+ from GCC 3.x source code. PowerPC has 1:1 mapping
+ according to the order of the registers defined
+ in GCC
+
+ }
+
+ stab_regindex: array[tregisterindex] of shortint = (
+{$I rppcstab.inc}
+ );
+
+ {*****************************************************************************
+ Generic Register names
+ *****************************************************************************}
+
+ // Stack pointer register
+ NR_STACK_POINTER_REG = NR_R1;
+ RS_STACK_POINTER_REG = RS_R1;
+ // old stack pointer register used during copying variables from the caller
+ // stack frame
+ NR_OLD_STACK_POINTER_REG = NR_R12;
+ // Frame pointer register
+ NR_FRAME_POINTER_REG = NR_STACK_POINTER_REG;
+ RS_FRAME_POINTER_REG = RS_STACK_POINTER_REG;
+ {# Register for addressing absolute data in a position independant way,
+ such as in PIC code. The exact meaning is ABI specific. For
+ further information look at GCC source : PIC_OFFSET_TABLE_REGNUM
+
+ Taken from GCC rs6000.h
+ }
+{ TODO: As indicated in rs6000.h, but can't find it anywhere else!}
+ NR_PIC_OFFSET_REG = NR_R30;
+ { Return address of a function }
+ NR_RETURN_ADDRESS_REG = NR_R0;
+ { Results are returned in this register (64-bit values) }
+ NR_FUNCTION_RETURN_REG = NR_R3;
+ RS_FUNCTION_RETURN_REG = RS_R3;
+ { The value returned from a function is available in this register }
+ NR_FUNCTION_RESULT_REG = NR_FUNCTION_RETURN_REG;
+ RS_FUNCTION_RESULT_REG = RS_FUNCTION_RETURN_REG;
+
+ NR_FPU_RESULT_REG = NR_F1;
+ NR_MM_RESULT_REG = NR_M0;
+
+ {*****************************************************************************
+ GCC /ABI linking information
+ *****************************************************************************}
+
+ {# Registers which must be saved when calling a routine declared as
+ cppdecl, cdecl, stdcall, safecall, palmossyscall. The registers
+ saved should be the ones as defined in the target ABI and / or GCC.
+
+ This value can be deduced from CALLED_USED_REGISTERS array in the
+ GCC source.
+ }
+ saved_standard_registers: array[0..17] of tsuperregister = (
+ RS_R14, RS_R15, RS_R16, RS_R17, RS_R18, RS_R19,
+ RS_R20, RS_R21, RS_R22, RS_R23, RS_R24, RS_R25,
+ RS_R26, RS_R27, RS_R28, RS_R29, RS_R30, RS_R31
+ );
+
+ { this is only for the generic code which is not used for this architecture }
+ saved_mm_registers : array[0..0] of tsuperregister = (RS_NO);
+
+ {# Required parameter alignment when calling a routine declared as
+ stdcall and cdecl. The alignment value should be the one defined
+ by GCC or the target ABI.
+ }
+ std_param_align = 8;
+ vmx_std_param_align = 16;
+
+ {*****************************************************************************
+ CPU Dependent Constants
+ *****************************************************************************}
+
+ LinkageAreaSizeELF = 48;
+ { offset in the linkage area for the saved stack pointer }
+ LA_SP = 0;
+ { offset in the linkage area for the saved conditional register}
+ LA_CR_ELF = 8;
+ { offset in the linkage area for the saved link register}
+ LA_LR_ELF = 16;
+ { offset in the linkage area for the saved RTOC register}
+ LA_RTOC_ELF = 40;
+
+ PARENT_FRAMEPOINTER_OFFSET = 24;
+
+ NR_RTOC = NR_R2;
+
+ ELF_STACK_ALIGN = 16;
+
+ { the size of the "red zone" which must not be changed by asynchronous calls
+ in the stack frame and can be used for storing temps }
+ RED_ZONE_SIZE = 288;
+
+ { minimum size of the stack frame if one exists }
+ MINIMUM_STACKFRAME_SIZE = 112;
+
+ maxfpuregs = 8;
+
+ {*****************************************************************************
+ Helpers
+ *****************************************************************************}
+
+function is_calljmp(o: tasmop): boolean;
+
+procedure inverse_flags(var r: TResFlags);
+function flags_to_cond(const f: TResFlags): TAsmCond;
+procedure create_cond_imm(BO, BI: byte; var r: TAsmCond);
+procedure create_cond_norm(cond: TAsmCondFlag; cr: byte; var r: TasmCond);
+
+function cgsize2subreg(regtype: tregistertype; s: Tcgsize): Tsubregister;
+{ Returns the tcgsize corresponding with the size of reg.}
+function reg_cgsize(const reg: tregister): tcgsize;
+
+function findreg_by_number(r: Tregister): tregisterindex;
+function std_regnum_search(const s: string): Tregister;
+function std_regname(r: Tregister): string;
+function is_condreg(r: tregister): boolean;
+
+function inverse_cond(const c: TAsmCond): Tasmcond;
+{$IFDEF USEINLINE}inline;{$ENDIF USEINLINE}
+function conditions_equal(const c1, c2: TAsmCond): boolean;
+function dwarf_reg(r:tregister):shortint;
+
+implementation
+
+uses
+ rgBase, verbose, itcpugas;
+
+const
+ std_regname_table: array[tregisterindex] of string[7] = (
+{$I rppcstd.inc}
+ );
+
+ regnumber_index: array[tregisterindex] of tregisterindex = (
+{$I rppcrni.inc}
+ );
+
+ std_regname_index: array[tregisterindex] of tregisterindex = (
+{$I rppcsri.inc}
+ );
+
+ {*****************************************************************************
+ Helpers
+ ***************** ************************************************************}
+
+function is_calljmp(o: tasmop): boolean;
+begin
+ is_calljmp := false;
+ case o of
+ A_B, A_BA, A_BL, A_BLA, A_BC, A_BCA, A_BCL, A_BCLA, A_BCCTR, A_BCCTRL,
+ A_BCLR, A_BF, A_BT,
+ A_BCLRL, A_TW, A_TWI: is_calljmp := true;
+ end;
+end;
+
+procedure inverse_flags(var r: TResFlags);
+const
+ inv_flags: array[F_EQ..F_GE] of TResFlagsEnum =
+ (F_NE, F_EQ, F_GE, F_GE, F_LE, F_LT);
+begin
+ r.flag := inv_flags[r.flag];
+end;
+
+function inverse_cond(const c: TAsmCond): Tasmcond;
+{$IFDEF USEINLINE}inline;
+{$ENDIF USEINLINE}
+const
+ inv_condflags: array[TAsmCondFlag] of TAsmCondFlag = (C_None,
+ C_GE, C_GT, C_NE, C_LT, C_LE, C_LT, C_EQ, C_GT, C_NS, C_SO, C_NU, C_UN,
+ C_F, C_T, C_DNZ, C_DNZF, C_DNZT, C_DZ, C_DZF, C_DZT);
+begin
+ if (c.cond in [C_DNZ, C_DZ]) then
+ internalerror(2005022501);
+ result := c;
+ result.cond := inv_condflags[c.cond];
+end;
+
+function conditions_equal(const c1, c2: TAsmCond): boolean;
+begin
+ result :=
+ (c1.simple and c2.simple) and
+ (c1.cond = c2.cond) and
+ ((not (c1.cond in [C_T..C_DZF]) and
+ (c1.cr = c2.cr)) or
+ (c1.crbit = c2.crbit));
+end;
+
+function flags_to_cond(const f: TResFlags): TAsmCond;
+const
+ flag_2_cond: array[F_EQ..F_SO] of TAsmCondFlag =
+ (C_EQ, C_NE, C_LT, C_LE, C_GT, C_GE, C_SO);
+begin
+ if f.flag > high(flag_2_cond) then
+ internalerror(200112301);
+ result.simple := true;
+ result.cr := f.cr;
+ result.cond := flag_2_cond[f.flag];
+end;
+
+procedure create_cond_imm(BO, BI: byte; var r: TAsmCond);
+begin
+ r.simple := false;
+ r.bo := bo;
+ r.bi := bi;
+end;
+
+procedure create_cond_norm(cond: TAsmCondFlag; cr: byte; var r: TasmCond);
+begin
+ r.simple := true;
+ r.cond := cond;
+ case cond of
+ C_NONE: ;
+ C_T..C_DZF: r.crbit := cr
+ else
+ r.cr := RS_CR0 + cr;
+ end;
+end;
+
+function is_condreg(r: tregister): boolean;
+var
+ supreg: tsuperregister;
+begin
+ result := false;
+ if (getregtype(r) = R_SPECIALREGISTER) then
+ begin
+ supreg := getsupreg(r);
+ result := (supreg >= RS_CR0) and (supreg <= RS_CR7);
+ end;
+end;
+
+function reg_cgsize(const reg: tregister): tcgsize;
+begin
+ case getregtype(reg) of
+ R_INTREGISTER:
+ result := OS_64;
+ R_MMREGISTER:
+ result := OS_M128;
+ R_FPUREGISTER:
+ result := OS_F64;
+ else
+ internalerror(200303181);
+ end;
+end;
+
+function cgsize2subreg(regtype: tregistertype; s: Tcgsize): Tsubregister;
+begin
+ cgsize2subreg := R_SUBWHOLE;
+end;
+
+function findreg_by_number(r: Tregister): tregisterindex;
+begin
+ result := rgBase.findreg_by_number_table(r, regnumber_index);
+end;
+
+function std_regnum_search(const s: string): Tregister;
+begin
+ result := regnumber_table[findreg_by_name_table(s, std_regname_table,
+ std_regname_index)];
+end;
+
+function std_regname(r: Tregister): string;
+var
+ p: tregisterindex;
+begin
+ p := findreg_by_number_table(r, regnumber_index);
+ if p <> 0 then
+ result := std_regname_table[p]
+ else
+ result := generic_regname(r);
+end;
+
+function dwarf_reg(r:tregister):shortint;
+begin
+ result:=regdwarf_table[findreg_by_number(r)];
+ if result=-1 then
+ internalerror(200603251);
+end;
+
+
+end.
+
diff --git a/closures/compiler/powerpc64/cpuinfo.pas b/closures/compiler/powerpc64/cpuinfo.pas
new file mode 100644
index 0000000000..7b845cc45d
--- /dev/null
+++ b/closures/compiler/powerpc64/cpuinfo.pas
@@ -0,0 +1,82 @@
+{
+ Copyright (c) 1998-2002 by the Free Pascal development team
+
+ Basic Processor information for the PowerPC
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+unit CPUInfo;
+
+interface
+
+uses
+ globtype;
+
+type
+ bestreal = double;
+ ts32real = single;
+ ts64real = double;
+ ts80real = extended;
+ ts128real = extended;
+ ts64comp = comp;
+
+ pbestreal = ^bestreal;
+
+ { possible supported processors for this target }
+ tcputype = (cpu_none,
+ cpu_ppc970
+ );
+
+ tfputype =
+ (fpu_none,
+ fpu_soft,
+ fpu_standard
+ );
+
+const
+ { calling conventions supported by the code generator }
+ supported_calling_conventions: tproccalloptions = [
+ pocall_internproc,
+ pocall_stdcall,
+ { the difference to stdcall is only the name mangling }
+ pocall_cdecl,
+ { the difference to stdcall is only the name mangling }
+ pocall_cppdecl,
+ { the difference with stdcall is that all const record
+ parameters are passed by reference }
+ pocall_mwpascal
+ ];
+
+ cputypestr: array[tcputype] of string[10] = ('',
+ '970'
+ );
+
+ fputypestr: array[tfputype] of string[8] = ('',
+ 'SOFT',
+ 'STANDARD'
+ );
+
+ { Supported optimizations, only used for information }
+ supported_optimizerswitches = genericlevel1optimizerswitches+
+ genericlevel2optimizerswitches+
+ genericlevel3optimizerswitches-
+ { no need to write info about those }
+ [cs_opt_level1,cs_opt_level2,cs_opt_level3]+
+ [cs_opt_regvar,cs_opt_loopunroll,cs_opt_nodecse,cs_opt_tailrecursion];
+
+ level1optimizerswitches = genericlevel1optimizerswitches;
+ level2optimizerswitches = genericlevel2optimizerswitches + level1optimizerswitches +
+ [cs_opt_regvar,cs_opt_stackframe,cs_opt_nodecse,cs_opt_tailrecursion];
+ level3optimizerswitches = genericlevel3optimizerswitches + level2optimizerswitches + [{,cs_opt_loopunroll}];
+
+implementation
+
+end.
+
diff --git a/closures/compiler/powerpc64/cpunode.pas b/closures/compiler/powerpc64/cpunode.pas
new file mode 100644
index 0000000000..0d4780e8ee
--- /dev/null
+++ b/closures/compiler/powerpc64/cpunode.pas
@@ -0,0 +1,52 @@
+{
+ Copyright (c) 2000-2002 by Florian Klaempfl
+
+ Includes the PowerPC64 code generator
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit cpunode;
+
+{$I fpcdefs.inc}
+
+interface
+
+implementation
+
+uses
+ { generic nodes }
+ ncgbas, ncgld, ncgflw, ncgcnv, ncgmem, ncgcon, ncgcal, ncgset, ncginl, ncgopt,
+ ncgobjc,
+ { to be able to only parts of the generic code,
+ the processor specific nodes must be included
+ after the generic one (FK)
+ }
+ nppcadd,
+ nppccal,
+ // nppccon,
+ // nppcflw,
+ // nppcmem,
+ ngppcset,
+ ngppcinl,
+ // nppcopt,
+ nppcmat,
+ nppccnv,
+ nppcld
+ ;
+
+end.
+
diff --git a/closures/compiler/powerpc64/cpupara.pas b/closures/compiler/powerpc64/cpupara.pas
new file mode 100644
index 0000000000..f856eac6a2
--- /dev/null
+++ b/closures/compiler/powerpc64/cpupara.pas
@@ -0,0 +1,526 @@
+{
+ Copyright (c) 2002 by Florian Klaempfl
+
+ PowerPC64 specific calling conventions
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ ****************************************************************************
+}
+unit cpupara;
+
+{$I fpcdefs.inc}
+
+interface
+
+uses
+ globtype,
+ aasmtai,aasmdata,
+ cpubase,
+ symconst, symtype, symdef, symsym,
+ paramgr, parabase, cgbase, cgutils;
+
+type
+ tppcparamanager = class(tparamanager)
+ function get_volatile_registers_int(calloption: tproccalloption):
+ tcpuregisterset; override;
+ function get_volatile_registers_fpu(calloption: tproccalloption):
+ tcpuregisterset; override;
+ function push_addr_param(varspez: tvarspez; def: tdef; calloption:
+ tproccalloption): boolean; override;
+
+ procedure getintparaloc(calloption: tproccalloption; nr: longint; var
+ cgpara: TCGPara); override;
+ function create_paraloc_info(p: tabstractprocdef; side: tcallercallee): longint; override;
+ function create_varargs_paraloc_info(p: tabstractprocdef; varargspara:
+ tvarargsparalist): longint; override;
+ function get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tcgpara;override;
+ procedure create_funcretloc_info(p: tabstractprocdef; side: tcallercallee);
+
+ private
+ procedure init_values(var curintreg, curfloatreg, curmmreg: tsuperregister;
+ var cur_stack_offset: aword);
+ function create_paraloc_info_intern(p: tabstractprocdef; side:
+ tcallercallee; paras: tparalist;
+ var curintreg, curfloatreg, curmmreg: tsuperregister; var
+ cur_stack_offset: aword; isVararg : boolean): longint;
+ function parseparaloc(p: tparavarsym; const s: string): boolean; override;
+ end;
+
+implementation
+
+uses
+ verbose, systems,
+ defutil,
+ procinfo, cpupi;
+
+function tppcparamanager.get_volatile_registers_int(calloption:
+ tproccalloption): tcpuregisterset;
+begin
+ result := [RS_R0,RS_R3..RS_R12];
+ if (target_info.system = system_powerpc64_darwin) then
+ include(result,RS_R2);
+end;
+
+function tppcparamanager.get_volatile_registers_fpu(calloption:
+ tproccalloption): tcpuregisterset;
+begin
+ result := [RS_F0..RS_F13];
+end;
+
+procedure tppcparamanager.getintparaloc(calloption: tproccalloption; nr:
+ longint; var cgpara: TCGPara);
+var
+ paraloc: pcgparalocation;
+begin
+ cgpara.reset;
+ cgpara.size := OS_ADDR;
+ cgpara.intsize := sizeof(pint);
+ cgpara.alignment := get_para_align(calloption);
+ paraloc := cgpara.add_location;
+ with paraloc^ do begin
+ size := OS_INT;
+ if (nr <= 8) then begin
+ if (nr = 0) then
+ internalerror(200309271);
+ loc := LOC_REGISTER;
+ register := newreg(R_INTREGISTER, RS_R2 + nr, R_SUBWHOLE);
+ end else begin
+ loc := LOC_REFERENCE;
+ paraloc^.reference.index := NR_STACK_POINTER_REG;
+ reference.offset := sizeof(aint) * (nr - 8);
+ end;
+ end;
+end;
+
+function getparaloc(p: tdef): tcgloc;
+
+begin
+ { Later, the LOC_REFERENCE is in most cases changed into LOC_REGISTER
+ if push_addr_param for the def is true
+ }
+ case p.typ of
+ orddef:
+ result := LOC_REGISTER;
+ floatdef:
+ result := LOC_FPUREGISTER;
+ enumdef:
+ result := LOC_REGISTER;
+ pointerdef:
+ result := LOC_REGISTER;
+ formaldef:
+ result := LOC_REGISTER;
+ classrefdef:
+ result := LOC_REGISTER;
+ procvardef,
+ recorddef:
+ result := LOC_REGISTER;
+ objectdef:
+ if is_object(p) then
+ result := LOC_REFERENCE
+ else
+ result := LOC_REGISTER;
+ stringdef:
+ if is_shortstring(p) or is_longstring(p) then
+ result := LOC_REFERENCE
+ else
+ result := LOC_REGISTER;
+ filedef:
+ result := LOC_REGISTER;
+ arraydef:
+ result := LOC_REFERENCE;
+ setdef:
+ if is_smallset(p) then
+ result := LOC_REGISTER
+ else
+ result := LOC_REFERENCE;
+ variantdef:
+ result := LOC_REFERENCE;
+ { avoid problems with errornous definitions }
+ errordef:
+ result := LOC_REGISTER;
+ else
+ internalerror(2002071001);
+ end;
+end;
+
+function tppcparamanager.push_addr_param(varspez: tvarspez; def: tdef;
+ calloption: tproccalloption): boolean;
+begin
+ result := false;
+ { var,out,constref always require address }
+ if varspez in [vs_var, vs_out, vs_constref] then
+ begin
+ result := true;
+ exit;
+ end;
+ case def.typ of
+ variantdef,
+ formaldef:
+ result := true;
+ procvardef,
+ recorddef:
+ result :=
+ ((varspez = vs_const) and
+ (
+ (not (calloption in [pocall_cdecl, pocall_cppdecl]) and
+ (def.size > 8))
+ ) or
+ (calloption = pocall_mwpascal)
+ );
+ arraydef:
+ result := (tarraydef(def).highrange >= tarraydef(def).lowrange) or
+ is_open_array(def) or
+ is_array_of_const(def) or
+ is_array_constructor(def);
+ objectdef:
+ result := is_object(def);
+ setdef:
+ result := not is_smallset(def);
+ stringdef:
+ result := tstringdef(def).stringtype in [st_shortstring, st_longstring];
+ end;
+end;
+
+procedure tppcparamanager.init_values(var curintreg, curfloatreg, curmmreg:
+ tsuperregister; var cur_stack_offset: aword);
+begin
+ { register parameter save area begins at 48(r2) }
+ cur_stack_offset := 48;
+ curintreg := RS_R3;
+ curfloatreg := RS_F1;
+ curmmreg := RS_M2;
+end;
+
+procedure tppcparamanager.create_funcretloc_info(p: tabstractprocdef; side:
+ tcallercallee);
+begin
+ p.funcretloc[side]:=get_funcretloc(p,side,p.returndef);
+end;
+
+function tppcparamanager.get_funcretloc(p : tabstractprocdef; side:
+ tcallercallee; def: tdef): tcgpara;
+var
+ paraloc : pcgparalocation;
+ retcgsize : tcgsize;
+begin
+ result.init;
+ result.alignment:=get_para_align(p.proccalloption);
+ { void has no location }
+ if is_void(def) then
+ begin
+ paraloc:=result.add_location;
+ result.size:=OS_NO;
+ result.intsize:=0;
+ paraloc^.size:=OS_NO;
+ paraloc^.loc:=LOC_VOID;
+ exit;
+ end;
+ { Constructors return self instead of a boolean }
+ if (p.proctypeoption=potype_constructor) then
+ begin
+ retcgsize:=OS_ADDR;
+ result.intsize:=sizeof(pint);
+ end
+ else
+ begin
+ retcgsize:=def_cgsize(def);
+ result.intsize:=def.size;
+ end;
+ result.size:=retcgsize;
+ { Return is passed as var parameter }
+ if ret_in_param(def,p.proccalloption) then
+ begin
+ paraloc:=result.add_location;
+ paraloc^.loc:=LOC_REFERENCE;
+ paraloc^.size:=retcgsize;
+ exit;
+ end;
+
+ paraloc:=result.add_location;
+ { Return in FPU register? }
+ if def.typ=floatdef then
+ begin
+ paraloc^.loc:=LOC_FPUREGISTER;
+ paraloc^.register:=NR_FPU_RESULT_REG;
+ paraloc^.size:=retcgsize;
+ end
+ else
+ { Return in register }
+ begin
+ paraloc^.loc:=LOC_REGISTER;
+ if side=callerside then
+ paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize))
+ else
+ paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(R_INTREGISTER,retcgsize));
+ paraloc^.size:=retcgsize;
+ end;
+end;
+
+function tppcparamanager.create_paraloc_info(p: tabstractprocdef; side:
+ tcallercallee): longint;
+var
+ cur_stack_offset: aword;
+ curintreg, curfloatreg, curmmreg : tsuperregister;
+begin
+ init_values(curintreg, curfloatreg, curmmreg, cur_stack_offset);
+
+ result := create_paraloc_info_intern(p, side, p.paras, curintreg, curfloatreg,
+ curmmreg, cur_stack_offset, false);
+
+ create_funcretloc_info(p, side);
+end;
+
+function tppcparamanager.create_paraloc_info_intern(p: tabstractprocdef; side:
+ tcallercallee; paras: tparalist;
+ var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset:
+ aword; isVararg : boolean): longint;
+var
+ stack_offset: longint;
+ paralen: aint;
+ nextintreg, nextfloatreg, nextmmreg : tsuperregister;
+ paradef: tdef;
+ paraloc: pcgparalocation;
+ i: integer;
+ hp: tparavarsym;
+ loc: tcgloc;
+ paracgsize: tcgsize;
+
+ parashift : byte;
+
+begin
+{$IFDEF extdebug}
+ if po_explicitparaloc in p.procoptions then
+ internalerror(200411141);
+{$ENDIF extdebug}
+
+ result := 0;
+ nextintreg := curintreg;
+ nextfloatreg := curfloatreg;
+ nextmmreg := curmmreg;
+ stack_offset := cur_stack_offset;
+
+ for i := 0 to paras.count - 1 do begin
+ parashift := 0;
+ hp := tparavarsym(paras[i]);
+
+ paradef := hp.vardef;
+ { Syscall for Morphos can have already a paraloc set; not supported on ppc64 }
+ if (vo_has_explicit_paraloc in hp.varoptions) then begin
+ internalerror(200412153);
+ end;
+ hp.paraloc[side].reset;
+ { currently only support C-style array of const }
+ if (p.proccalloption in [pocall_cdecl, pocall_cppdecl]) and
+ is_array_of_const(paradef) then begin
+ paraloc := hp.paraloc[side].add_location;
+ { hack: the paraloc must be valid, but is not actually used }
+ paraloc^.loc := LOC_REGISTER;
+ paraloc^.register := NR_R0;
+ paraloc^.size := OS_ADDR;
+ break;
+ end;
+
+ if (hp.varspez in [vs_var, vs_out]) or
+ push_addr_param(hp.varspez, paradef, p.proccalloption) or
+ is_open_array(paradef) or
+ is_array_of_const(paradef) then begin
+ paradef := voidpointertype;
+ loc := LOC_REGISTER;
+ paracgsize := OS_ADDR;
+ paralen := tcgsize2size[OS_ADDR];
+ end else begin
+ if not is_special_array(paradef) then
+ paralen := paradef.size
+ else
+ paralen := tcgsize2size[def_cgsize(paradef)];
+ if (paradef.typ = recorddef) and
+ (hp.varspez in [vs_value, vs_const]) then begin
+ { if a record has only one field and that field is }
+ { non-composite (not array or record), it must be }
+ { passed according to the rules of that type. }
+ if (trecorddef(hp.vardef).symtable.SymList.count = 1) and
+ (not trecorddef(hp.vardef).isunion) and
+ (tabstractvarsym(trecorddef(hp.vardef).symtable.SymList[0]).vardef.typ in [orddef, enumdef, floatdef]) then begin
+ paradef :=
+ tabstractvarsym(trecorddef(hp.vardef).symtable.SymList[0]).vardef;
+ loc := getparaloc(paradef);
+ paracgsize := def_cgsize(paradef);
+ end else begin
+ loc := LOC_REGISTER;
+ paracgsize := int_cgsize(paralen);
+ if (paralen in [3,5,6,7]) then
+ parashift := (8-paralen) * 8;
+ end;
+ end else begin
+ loc := getparaloc(paradef);
+ paracgsize := def_cgsize(paradef);
+ { for things like formaldef }
+ if (paracgsize = OS_NO) then begin
+ paracgsize := OS_ADDR;
+ paralen := tcgsize2size[OS_ADDR];
+ end;
+ end
+ end;
+
+ { patch FPU values into integer registers if we currently have
+ to pass them as vararg parameters
+ }
+ if (isVararg) and (paradef.typ = floatdef) then begin
+ loc := LOC_REGISTER;
+ if paracgsize = OS_F64 then
+ paracgsize := OS_64
+ else
+ paracgsize := OS_32;
+ end;
+
+ hp.paraloc[side].alignment := std_param_align;
+ hp.paraloc[side].size := paracgsize;
+ hp.paraloc[side].intsize := paralen;
+ if (paralen = 0) then
+ if (paradef.typ = recorddef) then begin
+ paraloc := hp.paraloc[side].add_location;
+ paraloc^.loc := LOC_VOID;
+ end else
+ internalerror(2005011310);
+ { can become < 0 for e.g. 3-byte records }
+
+ while (paralen > 0) do begin
+ paraloc := hp.paraloc[side].add_location;
+ { In case of po_delphi_nested_cc, the parent frame pointer
+ is always passed on the stack. }
+ if (loc = LOC_REGISTER) and
+ (nextintreg <= RS_R10) and
+ (not(vo_is_parentfp in hp.varoptions) or
+ not(po_delphi_nested_cc in p.procoptions)) then begin
+ paraloc^.loc := loc;
+ paraloc^.shiftval := parashift;
+
+ { make sure we don't lose whether or not the type is signed }
+ if (paracgsize <> OS_NO) and (paradef.typ <> orddef) then
+ paracgsize := int_cgsize(paralen);
+ if (paracgsize in [OS_NO,OS_128,OS_S128]) then
+ paraloc^.size := OS_INT
+ else
+ paraloc^.size := paracgsize;
+
+ paraloc^.register := newreg(R_INTREGISTER, nextintreg, R_SUBNONE);
+ inc(nextintreg);
+ dec(paralen, tcgsize2size[paraloc^.size]);
+
+ inc(stack_offset, sizeof(pint));
+ end else if (loc = LOC_FPUREGISTER) and
+ (nextfloatreg <= RS_F13) then begin
+ paraloc^.loc := loc;
+ paraloc^.size := paracgsize;
+ paraloc^.register := newreg(R_FPUREGISTER, nextfloatreg, R_SUBWHOLE);
+ { the PPC64 ABI says that the GPR index is increased for every parameter, no matter
+ which type it is stored in }
+ inc(nextintreg);
+ inc(nextfloatreg);
+ dec(paralen, tcgsize2size[paraloc^.size]);
+
+ inc(stack_offset, tcgsize2size[OS_FLOAT]);
+ end else if (loc = LOC_MMREGISTER) then begin
+ { Altivec not supported }
+ internalerror(200510192);
+ end else begin
+ { either LOC_REFERENCE, or one of the above which must be passed on the
+ stack because of insufficient registers }
+ paraloc^.loc := LOC_REFERENCE;
+ case loc of
+ LOC_FPUREGISTER:
+ paraloc^.size:=int_float_cgsize(paralen);
+ LOC_REGISTER,
+ LOC_REFERENCE:
+ paraloc^.size:=int_cgsize(paralen);
+ else
+ internalerror(2006011101);
+ end;
+ if (side = callerside) then
+ paraloc^.reference.index := NR_STACK_POINTER_REG
+ else begin
+ { during procedure entry, NR_OLD_STACK_POINTER_REG contains the old stack pointer }
+ paraloc^.reference.index := NR_OLD_STACK_POINTER_REG;
+ tppcprocinfo(current_procinfo).needs_frame_pointer := true;
+ end;
+ paraloc^.reference.offset := stack_offset;
+
+ { align temp contents to next register size }
+ inc(stack_offset, align(paralen, 8));
+ paralen := 0;
+ end;
+ end;
+ end;
+
+ curintreg := nextintreg;
+ curfloatreg := nextfloatreg;
+ curmmreg := nextmmreg;
+ cur_stack_offset := stack_offset;
+ result := stack_offset;
+end;
+
+function tppcparamanager.create_varargs_paraloc_info(p: tabstractprocdef;
+ varargspara: tvarargsparalist): longint;
+var
+ cur_stack_offset: aword;
+ parasize, l: longint;
+ curintreg, firstfloatreg, curfloatreg, curmmreg: tsuperregister;
+ i: integer;
+ hp: tparavarsym;
+ paraloc: pcgparalocation;
+begin
+ init_values(curintreg, curfloatreg, curmmreg, cur_stack_offset);
+ firstfloatreg := curfloatreg;
+
+ result := create_paraloc_info_intern(p, callerside, p.paras, curintreg,
+ curfloatreg, curmmreg, cur_stack_offset, false);
+ if (p.proccalloption in [pocall_cdecl, pocall_cppdecl]) then begin
+ { just continue loading the parameters in the registers }
+ result := create_paraloc_info_intern(p, callerside, varargspara, curintreg,
+ curfloatreg, curmmreg, cur_stack_offset, true);
+ { varargs routines have to reserve at least 64 bytes for the PPC64 ABI }
+ if (result < 64) then
+ result := 64;
+ end else begin
+ parasize := cur_stack_offset;
+ for i := 0 to varargspara.count - 1 do begin
+ hp := tparavarsym(varargspara[i]);
+ hp.paraloc[callerside].alignment := 8;
+ paraloc := hp.paraloc[callerside].add_location;
+ paraloc^.loc := LOC_REFERENCE;
+ paraloc^.size := def_cgsize(hp.vardef);
+ paraloc^.reference.index := NR_STACK_POINTER_REG;
+ l := push_size(hp.varspez, hp.vardef, p.proccalloption);
+ paraloc^.reference.offset := parasize;
+ parasize := parasize + l;
+ end;
+ result := parasize;
+ end;
+ if curfloatreg <> firstfloatreg then
+ include(varargspara.varargsinfo, va_uses_float_reg);
+end;
+
+function tppcparamanager.parseparaloc(p: tparavarsym; const s: string): boolean;
+begin
+ { not supported/required for PowerPC64-linux target }
+ internalerror(200404182);
+ result := true;
+end;
+
+
+begin
+ paramanager := tppcparamanager.create;
+end.
+
diff --git a/closures/compiler/powerpc64/cpupi.pas b/closures/compiler/powerpc64/cpupi.pas
new file mode 100644
index 0000000000..b5be0df730
--- /dev/null
+++ b/closures/compiler/powerpc64/cpupi.pas
@@ -0,0 +1,130 @@
+{
+ Copyright (c) 2002 by Florian Klaempfl
+
+ This unit contains the CPU specific part of tprocinfo
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+
+{ This unit contains the CPU specific part of tprocinfo. }
+unit cpupi;
+
+{$I fpcdefs.inc}
+
+interface
+
+uses
+ cutils,aasmdata,
+ procinfo, cpuinfo, psub;
+
+type
+ tppcprocinfo = class(tcgprocinfo)
+ needstackframe: boolean;
+
+ { offset where the frame pointer from the outer procedure is stored. }
+ parent_framepointer_offset: longint;
+
+ needs_frame_pointer : boolean;
+
+ constructor create(aparent: tprocinfo); override;
+ procedure set_first_temp_offset; override;
+ function calc_stackframe_size: longint; override;
+ function calc_stackframe_size(numgpr, numfpr : longint): longint;
+
+ procedure allocate_got_register(list: TAsmList); override;
+ end;
+
+implementation
+
+uses
+ globtype, globals, systems,
+ cpubase, cgbase,
+ aasmtai,
+ tgobj,cgobj,
+ symconst, symsym, paramgr, symutil, symtable,
+ verbose;
+
+constructor tppcprocinfo.create(aparent: tprocinfo);
+
+begin
+ inherited create(aparent);
+ maxpushedparasize := 0;
+ needs_frame_pointer := false;
+end;
+
+procedure tppcprocinfo.set_first_temp_offset;
+var
+ ofs: aword;
+begin
+ if not (po_assembler in procdef.procoptions) then begin
+ { align the stack properly }
+ ofs := align(maxpushedparasize + LinkageAreaSizeELF, ELF_STACK_ALIGN);
+
+ { the ABI specification says that it is required to always allocate space for 8 * 8 bytes
+ for registers R3-R10 and stack header if there's a stack frame, but GCC doesn't do that,
+ so we don't that too. Uncomment the next three lines if this is required }
+ if (cs_profile in init_settings.moduleswitches) and (ofs < MINIMUM_STACKFRAME_SIZE) then begin
+ ofs := MINIMUM_STACKFRAME_SIZE;
+ end;
+ tg.setfirsttemp(ofs);
+ end else begin
+ if (current_procinfo.procdef.localst.symtabletype=localsymtable) and
+ (tabstractlocalsymtable(current_procinfo.procdef.localst).count_locals <> 0) then
+ { at 0(r1), the previous value of r1 will be stored }
+ tg.setfirsttemp(8);
+ end;
+end;
+
+function tppcprocinfo.calc_stackframe_size: longint;
+begin
+ result := calc_stackframe_size(18, 18);
+end;
+
+function tppcprocinfo.calc_stackframe_size(numgpr, numfpr : longint) : longint;
+begin
+ { more or less copied from cgcpu.pas/g_stackframe_entry }
+ if not (po_assembler in procdef.procoptions) then begin
+ // no VMX support
+ result := align(numgpr * sizeof(pint) +
+ numfpr * tcgsize2size[OS_FLOAT], ELF_STACK_ALIGN);
+
+ if (pi_do_call in flags) or (tg.lasttemp <> tg.firsttemp) or
+ (result > RED_ZONE_SIZE) {or (cs_profile in init_settings.moduleswitches)} then begin
+ result := align(result + tg.lasttemp, ELF_STACK_ALIGN);
+ needstackframe:=true;
+ end else
+ needstackframe:=false;
+ end else begin
+ result := align(tg.lasttemp, ELF_STACK_ALIGN);
+ needstackframe:=result<>0;
+ end;
+end;
+
+
+procedure tppcprocinfo.allocate_got_register(list: TAsmList);
+ begin
+ if (target_info.system = system_powerpc64_darwin) and
+ (cs_create_pic in current_settings.moduleswitches) then
+ begin
+ got := cg.getaddressregister(list);
+ end;
+ end;
+
+begin
+ cprocinfo := tppcprocinfo;
+end.
+
diff --git a/closures/compiler/powerpc64/cputarg.pas b/closures/compiler/powerpc64/cputarg.pas
new file mode 100644
index 0000000000..1f2436889d
--- /dev/null
+++ b/closures/compiler/powerpc64/cputarg.pas
@@ -0,0 +1,83 @@
+{
+ Copyright (c) 2001-2002 by Peter Vreman
+
+ Includes the powerpc64 dependent target units
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit cputarg;
+
+{$i fpcdefs.inc}
+
+interface
+
+
+implementation
+
+ uses
+ systems { prevent a syntax error when nothing is included }
+
+{**************************************
+ Targets
+**************************************}
+
+ {$ifndef NOTARGETLINUX}
+ ,t_linux
+ {$endif}
+ {$ifndef NOTARGETBSD}
+ ,t_bsd
+ {$endif}
+
+{**************************************
+ Assemblers
+**************************************}
+
+ {$ifndef NOAGPPCGAS}
+ ,agppcgas
+ {$endif}
+
+{**************************************
+ Assembler Readers
+**************************************}
+
+ {$ifndef NoRaPPCGas}
+ ,rappcgas
+ {$endif NoRaPPCGas}
+
+{**************************************
+ Debuginfo
+**************************************}
+
+{ stabs debug info are not supported, so do not include them here}
+{ they are supported on darwin/ppc64 }
+ {$ifndef NoDbgDwarf}
+ ,dbgstabs
+ {$endif NoDbgDwarf}
+ {$ifndef NoDbgDwarf}
+ ,dbgdwarf
+ {$endif NoDbgDwarf}
+
+{**************************************
+ Optimizer
+**************************************}
+
+ {$ifndef NOOPT}
+ , aoptcpu
+ {$endif NOOPT}
+ ;
+
+end.
diff --git a/closures/compiler/powerpc64/itcpugas.pas b/closures/compiler/powerpc64/itcpugas.pas
new file mode 100644
index 0000000000..bc39c065fd
--- /dev/null
+++ b/closures/compiler/powerpc64/itcpugas.pas
@@ -0,0 +1,160 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit contains the PowerPC GAS instruction tables
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit itcpugas;
+
+{$I fpcdefs.inc}
+
+interface
+
+uses
+ cpubase, cgbase;
+
+const
+ gas_op2str: array[tasmop] of string[14] = ('<none>',
+ 'add', 'add.', 'addo', 'addo.', 'addc', 'addc.', 'addco', 'addco.',
+ 'adde', 'adde.', 'addeo', 'addeo.', 'addi', 'addic', 'addic.', 'addis',
+ 'addme', 'addme.', 'addmeo', 'addmeo.', 'addze', 'addze.', 'addzeo',
+ 'addzeo.', 'and', 'and.', 'andc', 'andc.', 'andi.', 'andis.', 'b',
+ 'ba', 'bl', 'bla', 'bc', 'bca', 'bcl', 'bcla', 'bcctr', 'bcctrl', 'bclr',
+ 'bclrl', 'cmp', 'cmpi', 'cmpl', 'cmpli', 'cntlzw', 'cntlzw.', 'crand',
+ 'crandc', 'creqv', 'crnand', 'crnor', 'cror', 'crorc', 'crxor', 'dcba',
+ 'dcbf', 'dcbi', 'dcbst', 'dcbt', 'dcbtst', 'dcbz', 'divw', 'divw.', 'divwo',
+ 'divwo.',
+ 'divwu', 'divwu.', 'divwuo', 'divwuo.', 'eciwx', 'ecowx', 'eieio', 'eqv',
+ 'eqv.', 'extsb', 'extsb.', 'extsh', 'extsh.', 'fabs', 'fabs.', 'fadd',
+ 'fadd.', 'fadds', 'fadds.', 'fcmpo', 'fcmpu', 'fctiw', 'fctiw.', 'fctiwz',
+ 'fctiwz.', 'fdiv', 'fdiv.', 'fdivs', 'fdivs.', 'fmadd', 'fmadd.', 'fmadds',
+ 'fmadds.', 'fmr', 'fmsub', 'fmsub.', 'fmsubs', 'fmsubs.', 'fmul', 'fmul.',
+ 'fmuls', 'fmuls.', 'fnabs', 'fnabs.', 'fneg', 'fneg.', 'fnmadd',
+ 'fnmadd.', 'fnmadds', 'fnmadds.', 'fnmsub', 'fnmsub.', 'fnmsubs',
+ 'fnmsubs.', 'fres', 'fres.', 'frsp', 'frsp.', 'frsqrte', 'frsqrte.',
+ 'fsel', 'fsel.', 'fsqrt', 'fsqrt.', 'fsqrts', 'fsqrts.', 'fsub', 'fsub.',
+ 'fsubs', 'fsubs.', 'icbi', 'isync', 'lbz', 'lbzu', 'lbzux', 'lbzx',
+ 'lfd', 'lfdu', 'lfdux', 'lfdx', 'lfs', 'lfsu', 'lfsux', 'lfsx', 'lha',
+ 'lhau', 'lhaux', 'lhax', 'lhbrx', 'lhz', 'lhzu', 'lhzux', 'lhzx', 'lmw',
+ 'lswi', 'lswx', 'lwarx', 'lwbrx', 'lwz', 'lwzu', 'lwzux', 'lwzx', 'mcrf',
+ 'mcrfs', 'mcrxr', 'mfcr', 'mffs', 'mffs.', 'mfmsr', 'mfspr', 'mfsr',
+ 'mfsrin', 'mftb', 'mtcrf', 'mtfsb0', 'mtfsb1', 'mtfsf', 'mtfsf.',
+ 'mtfsfi', 'mtfsfi.', 'mtmsr', 'mtspr', 'mtsr', 'mtsrin', 'mulhw',
+ 'mulhw.', 'mulhwu', 'mulhwu.', 'mulli', 'mullw', 'mullw.', 'mullwo',
+ 'mullwo.', 'nand', 'nand.', 'neg', 'neg.', 'nego', 'nego.', 'nor', 'nor.',
+ 'or', 'or.', 'orc', 'orc.', 'ori', 'oris', 'rfi', 'rlwimi', 'rlwimi.',
+ 'rlwinm', 'rlwinm.', 'rlwnm', 'sc', 'slw', 'slw.', 'sraw', 'sraw.',
+ 'srawi', 'srawi.', 'srw', 'srw.', 'stb', 'stbu', 'stbux', 'stbx', 'stfd',
+ 'stfdu', 'stfdux', 'stfdx', 'stfiwx', 'stfs', 'stfsu', 'stfsux', 'stfsx',
+ 'sth', 'sthbrx', 'sthu', 'sthux', 'sthx', 'stmw', 'stswi', 'stswx', 'stw',
+ 'stwbrx', 'stwcx.', 'stwu', 'stwux', 'stwx', 'subf', 'subf.', 'subfo',
+ 'subfo.', 'subfc', 'subc.', 'subfco', 'subfco.', 'subfe', 'subfe.',
+ 'subfeo', 'subfeo.', 'subfic', 'subfme', 'subfme.', 'subfmeo', 'subfmeo.',
+ 'subfze', 'subfze.', 'subfzeo', 'subfzeo.', 'sync', 'tlbia', 'tlbie',
+ 'tlbsync', 'tw', 'twi', 'xor', 'xor.', 'xori', 'xoris',
+ { some simplified mnemonics }
+ 'subi', 'subis', 'subic', 'subic.', 'sub', 'sub.', 'subo', 'subo.',
+ 'subc', 'subc.', 'subco', 'subco.', 'cmpwi', 'cmpw', 'cmplwi', 'cmplw',
+ 'extlwi', 'extlwi.', 'extrwi', 'extrwi.', 'inslwi', 'inslwi.', 'insrwi',
+ 'insrwi.', 'rotlwi', 'rotlwi.', 'rotlw', 'rotlw.', 'slwi', 'slwi.',
+ 'srwi', 'srwi.', 'clrlwi', 'clrlwi.', 'clrrwi', 'clrrwi.', 'clrslwi',
+ 'clrslwi.', 'bf', 'bt', 'blr', 'bctr', 'blrl', 'bctrl', 'crset', 'crclr', 'crmove',
+ 'crnot', 'mt', 'mf', 'nop', 'li', 'lis', 'la', 'mr', 'mr.', 'not', 'mtcr',
+ 'mtlr', 'mflr',
+ 'mtctr', 'mfctr',
+ 'extsw', 'rldimi',
+ 'std', 'stdu', 'stdx', 'stdux',
+ 'ld', 'ldu', 'ldx', 'ldux',
+ 'cmpd', 'cmpdi', 'cmpld', 'cmpldi',
+ 'srdi', 'sradi',
+ 'sldi',
+ 'rldcl', 'rldicl',
+ 'divdu', 'divdu.', 'divd', 'divd.', 'mulld', 'mulld.', 'mulhd', 'mulhd.', 'srad', 'sld', 'srd',
+ 'divduo.', 'divdo.',
+ 'lwa', 'lwax', 'lwaux',
+ 'fcfid',
+ 'ldarx', 'stdcx.', 'cntlzd',
+ 'lvx', 'stvx',
+ 'mulldo', 'mulldo.', 'mulhdu', 'mulhdu.',
+ 'mfxer',
+ 'fctid', 'fctid.', 'fctidz', 'fctidz.',
+ 'extrdi', 'extrdi.', 'insrdi', 'insrdi.',
+ 'lwsync');
+
+function gas_regnum_search(const s: string): Tregister;
+function gas_regname(r: Tregister): string;
+
+implementation
+
+uses
+ globtype, globals,aasmbase,
+ cutils, verbose, systems;
+
+const
+ gas_regname_table: array[tregisterindex] of string[7] = (
+{$I rppcgas.inc}
+ );
+
+ gas_regname_short_table: array[tregisterindex] of string[7] = (
+{$I rppcgss.inc}
+ );
+
+ gas_regname_index: array[tregisterindex] of tregisterindex = (
+{$I rppcgri.inc}
+ );
+
+function findreg_by_gasname(const s: string): tregisterindex;
+var
+ i, p: tregisterindex;
+begin
+ {Binary search.}
+ p := 0;
+ i := regnumber_count_bsstart;
+ repeat
+ if (p + i <= high(tregisterindex)) and (gas_regname_table[gas_regname_index[p + i]] <= s) then
+ p := p + i;
+ i := i shr 1;
+ until i = 0;
+ if gas_regname_table[gas_regname_index[p]] = s then
+ findreg_by_gasname := gas_regname_index[p]
+ else
+ findreg_by_gasname := 0;
+end;
+
+function gas_regnum_search(const s: string): Tregister;
+begin
+ result := regnumber_table[findreg_by_gasname(s)];
+end;
+
+function gas_regname(r: Tregister): string;
+var
+ p: longint;
+begin
+ p := findreg_by_number(r);
+ if p <> 0 then
+ if create_smartlink_library and
+ not(target_info.system = system_powerpc64_darwin) then
+ result := gas_regname_short_table[p]
+ else
+ result := gas_regname_table[p]
+ else
+ result := generic_regname(r);
+end;
+
+end.
+
diff --git a/closures/compiler/powerpc64/nppcadd.pas b/closures/compiler/powerpc64/nppcadd.pas
new file mode 100644
index 0000000000..7d11a78a6e
--- /dev/null
+++ b/closures/compiler/powerpc64/nppcadd.pas
@@ -0,0 +1,360 @@
+{
+ Copyright (c) 2000-2002 by Florian Klaempfl and Jonas Maebe
+
+ Code generation for add nodes on the PowerPC64
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit nppcadd;
+
+{$I fpcdefs.inc}
+
+interface
+
+uses
+ node, nadd, ncgadd, ngppcadd, cpubase;
+
+type
+ tppcaddnode = class(tgenppcaddnode)
+ procedure pass_generate_code override;
+ private
+ procedure emit_compare(unsigned: boolean); override;
+ end;
+
+implementation
+
+uses
+ sysutils,
+
+ globtype, systems,
+ cutils, verbose, globals,
+ symconst, symdef, paramgr,
+ aasmbase, aasmtai,aasmdata, aasmcpu, defutil, htypechk,
+ cgbase, cpuinfo, pass_1, pass_2, regvars,
+ cpupara, cgcpu, cgutils,procinfo,
+ ncon, nset,
+ ncgutil, tgobj, rgobj, rgcpu, cgobj;
+
+{*****************************************************************************
+ Helpers
+*****************************************************************************}
+
+procedure tppcaddnode.emit_compare(unsigned: boolean);
+const
+ { unsigned useconst 32bit-op }
+ cmpop_table : array[boolean, boolean, boolean] of TAsmOp = (
+ ((A_CMPD, A_CMPW), (A_CMPDI, A_CMPWI)),
+ ((A_CMPLD, A_CMPLW), (A_CMPLDI, A_CMPLWI))
+ );
+
+var
+ op: TAsmOp;
+ tmpreg: TRegister;
+ useconst: boolean;
+
+ opsize : TCgSize;
+begin
+ { get the constant on the right if there is one }
+ if (left.location.loc = LOC_CONSTANT) then
+ swapleftright;
+
+ opsize := def_cgsize(left.resultdef);
+
+ {$IFDEF EXTDEBUG}
+ current_asmdata.CurrAsmList.concat(tai_comment.create(strpnew('tppcaddnode.emit_compare ' + inttostr(ord(opsize)) + ' ' + inttostr(tcgsize2size[opsize]))));
+ {$ENDIF EXTDEBUG}
+
+ { can we use a signed comparison or not? In case of equal/unequal comparison
+ we can check whether this is possible because it does not matter. }
+ if (right.location.loc = LOC_CONSTANT) then
+ if (nodetype in [equaln,unequaln]) then
+ if (unsigned and (aword(right.location.value) > high(word))) or
+ (not unsigned and (aint(right.location.value) < low(smallint)) or
+ (aint(right.location.value) > high(smallint))) then
+ { we can then maybe use a constant in the 'othersigned' case
+ (the sign doesn't matter for equal/unequal) }
+ unsigned := not unsigned;
+
+ { calculate the size of the comparison because ppc64 only has 32 and 64
+ bit comparison opcodes; prefer 32 bits }
+ if (not (opsize in [OS_32, OS_S32, OS_64, OS_S64])) then begin
+ if (unsigned) then
+ opsize := OS_32
+ else
+ opsize := OS_S32;
+ cg.a_load_reg_reg(current_asmdata.CurrAsmList, def_cgsize(left.resultdef), opsize,
+ left.location.register, left.location.register);
+ end;
+
+ { can we use an immediate, or do we have to load the
+ constant in a register first? }
+ if (right.location.loc = LOC_CONSTANT) then begin
+ if (unsigned and
+ (aword(right.location.value) <= high(word))) or
+ (not (unsigned) and
+ (aint(right.location.value) >= low(smallint)) and (aint(right.location.value) <= high(smallint))) then
+ useconst := true
+ else begin
+ useconst := false;
+ tmpreg := cg.getintregister(current_asmdata.CurrAsmList, OS_INT);
+ cg.a_load_const_reg(current_asmdata.CurrAsmList, opsize, right.location.value, tmpreg);
+ end
+ end else
+ useconst := false;
+
+ location.loc := LOC_FLAGS;
+ location.resflags := getresflags;
+
+ op := cmpop_table[unsigned, useconst, opsize in [OS_S32, OS_32]];
+
+ { actually do the operation }
+ if (right.location.loc = LOC_CONSTANT) then begin
+ if useconst then
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(op, left.location.register,
+ longint(right.location.value)))
+ else
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op, left.location.register, tmpreg));
+ end else
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op, left.location.register,
+ right.location.register));
+end;
+
+{*****************************************************************************
+ pass_2
+*****************************************************************************}
+
+procedure tppcaddnode.pass_generate_code;
+{ is also being used for xor, and "mul", "sub, or and comparative }
+{ operators }
+var
+ cgop: topcg;
+ op: tasmop;
+ tmpreg: tregister;
+ hl: tasmlabel;
+ cmpop: boolean;
+ checkoverflow: boolean;
+
+ { true, if unsigned types are compared }
+ unsigned: boolean;
+
+begin
+ { to make it more readable, string and set (not smallset!) have their
+ own procedures }
+ case left.resultdef.typ of
+ orddef:
+ begin
+ { handling boolean expressions }
+ if is_boolean(left.resultdef) and
+ is_boolean(right.resultdef) then
+ begin
+ second_addboolean;
+ exit;
+ end;
+ end;
+ stringdef:
+ begin
+ internalerror(2002072402);
+ exit;
+ end;
+ setdef:
+ begin
+ { normalsets are already handled in pass1 }
+ if not is_smallset(left.resultdef) then
+ internalerror(200109041);
+ second_addsmallset;
+ exit;
+ end;
+ arraydef:
+ begin
+{$IFDEF SUPPORT_MMX}
+ if is_mmx_able_array(left.resultdef) then
+ begin
+ second_addmmx;
+ exit;
+ end;
+{$ENDIF SUPPORT_MMX}
+ end;
+ floatdef:
+ begin
+ second_addfloat;
+ exit;
+ end;
+ end;
+
+ { defaults }
+ cmpop := nodetype in [ltn, lten, gtn, gten, equaln, unequaln];
+ unsigned := not (is_signed(left.resultdef)) or
+ not (is_signed(right.resultdef));
+
+ pass_left_and_right;
+
+ { Convert flags to register first }
+ { can any of these things be in the flags actually?? (JM) }
+
+ if (left.location.loc = LOC_FLAGS) or
+ (right.location.loc = LOC_FLAGS) then
+ internalerror(2002072602);
+
+ { set result location }
+ if not cmpop then
+ location_reset(location, LOC_REGISTER, def_cgsize(resultdef))
+ else
+ location_reset(location, LOC_FLAGS, OS_NO);
+
+ checkoverflow:=
+ (nodetype in [addn,subn,muln]) and
+ (cs_check_overflow in current_settings.localswitches) and
+ (left.resultdef.typ<>pointerdef) and
+ (right.resultdef.typ<>pointerdef);
+
+ load_left_right(cmpop, checkoverflow);
+
+ if not (cmpop) then
+ location.register := cg.getintregister(current_asmdata.CurrAsmList, OS_INT);
+
+ if not (checkoverflow) then begin
+ case nodetype of
+ addn, muln, xorn, orn, andn:
+ begin
+ case nodetype of
+ addn:
+ cgop := OP_ADD;
+ muln:
+ if unsigned then
+ cgop := OP_MUL
+ else
+ cgop := OP_IMUL;
+ xorn:
+ cgop := OP_XOR;
+ orn:
+ cgop := OP_OR;
+ andn:
+ cgop := OP_AND;
+ end;
+ if (left.location.loc = LOC_CONSTANT) then
+ swapleftright;
+ if (right.location.loc <> LOC_CONSTANT) then
+ cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList, cgop, OS_INT,
+ left.location.register, right.location.register,
+ location.register)
+ else
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, cgop, OS_INT,
+ right.location.value, left.location.register,
+ location.register);
+ end;
+ subn:
+ begin
+ if (nf_swapped in flags) then
+ swapleftright;
+ if left.location.loc <> LOC_CONSTANT then
+ if right.location.loc <> LOC_CONSTANT then begin
+ cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList, OP_SUB, OS_INT,
+ right.location.register, left.location.register,
+ location.register);
+ end else begin
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_SUB, OS_INT,
+ right.location.value, left.location.register,
+ location.register);
+ end
+ else
+ begin
+ tmpreg := cg.getintregister(current_asmdata.CurrAsmList, OS_INT);
+ cg.a_load_const_reg(current_asmdata.CurrAsmList, OS_INT,
+ left.location.value, tmpreg);
+ cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList, OP_SUB, OS_INT,
+ right.location.register, tmpreg, location.register);
+ end;
+ end;
+ ltn, lten, gtn, gten, equaln, unequaln:
+ begin
+ {$ifdef extdebug}
+ current_asmdata.CurrAsmList.concat(tai_comment.create('tppcaddnode.pass2'));
+ {$endif extdebug}
+
+ emit_compare(unsigned);
+ end;
+ end;
+ end
+ else
+ // overflow checking is on and we have an addn, subn or muln
+ begin
+ if is_signed(resultdef) then
+ begin
+ case nodetype of
+ addn:
+ op := A_ADDO;
+ subn:
+ begin
+ op := A_SUBO;
+ if (nf_swapped in flags) then
+ swapleftright;
+ end;
+ muln:
+ op := A_MULLDO;
+ else
+ internalerror(2002072601);
+ end;
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(op, location.register,
+ left.location.register, right.location.register));
+ cg.g_overflowcheck(current_asmdata.CurrAsmList, location, resultdef);
+ end
+ else
+ begin
+ case nodetype of
+ addn:
+ begin
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_ADD, location.register,
+ left.location.register, right.location.register));
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CMPLD, location.register,
+ left.location.register));
+ cg.g_overflowcheck(current_asmdata.CurrAsmList, location, resultdef);
+ end;
+ subn:
+ begin
+ if (nf_swapped in flags) then
+ swapleftright;
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SUB, location.register,
+ left.location.register, right.location.register));
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CMPLD,
+ left.location.register, location.register));
+ cg.g_overflowcheck(current_asmdata.CurrAsmList, location, resultdef);
+ end;
+ muln:
+ begin
+ { calculate the upper 64 bits of the product, = 0 if no overflow }
+ cg.a_reg_alloc(current_asmdata.CurrAsmList, NR_R0);
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_MULHDU_, NR_R0,
+ left.location.register, right.location.register));
+ cg.a_reg_dealloc(current_asmdata.CurrAsmList, NR_R0);
+ { calculate the real result }
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_MULLD, location.register,
+ left.location.register, right.location.register));
+ { g_overflowcheck generates a OC_AE instead of OC_EQ :/ }
+ current_asmdata.getjumplabel(hl);
+ tcgppc(cg).a_jmp_cond(current_asmdata.CurrAsmList, OC_EQ, hl);
+ cg.a_call_name(current_asmdata.CurrAsmList, 'FPC_OVERFLOW',false);
+ cg.a_label(current_asmdata.CurrAsmList, hl);
+ end;
+ end;
+ end;
+ end;
+end;
+
+begin
+ caddnode := tppcaddnode;
+end.
+
diff --git a/closures/compiler/powerpc64/nppccal.pas b/closures/compiler/powerpc64/nppccal.pas
new file mode 100644
index 0000000000..8588fe43cd
--- /dev/null
+++ b/closures/compiler/powerpc64/nppccal.pas
@@ -0,0 +1,63 @@
+{
+ Copyright (c) 2002 by Florian Klaempfl
+
+ Implements the PowerPC specific part of call nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit nppccal;
+
+{$I fpcdefs.inc}
+
+interface
+
+uses
+ symdef, node, ncal, ncgcal;
+
+type
+
+ tppccallparanode = class(tcgcallparanode)
+ end;
+
+ tppccallnode = class(tcgcallnode)
+ procedure do_syscall; override;
+ end;
+
+implementation
+
+uses
+ globtype, systems,
+ cutils, verbose, globals,
+ symconst, symbase, symsym, symtable, defutil, paramgr, parabase,
+ cgbase, pass_2,
+ cpuinfo, cpubase, aasmbase, aasmtai,aasmdata, aasmcpu,
+ nmem, nld, ncnv,
+ ncgutil, cgutils, cgobj, tgobj, regvars, rgobj, rgcpu,
+ cgcpu, cpupi, procinfo;
+
+procedure tppccallnode.do_syscall;
+begin
+ { no MorphOS style syscalls supported. Only implemented to avoid abstract
+ method not implemented compiler warning. }
+ internalerror(2005120401);
+end;
+
+begin
+ ccallparanode:=tppccallparanode;
+ ccallnode := tppccallnode;
+end.
+
diff --git a/closures/compiler/powerpc64/nppccnv.pas b/closures/compiler/powerpc64/nppccnv.pas
new file mode 100644
index 0000000000..02dd630010
--- /dev/null
+++ b/closures/compiler/powerpc64/nppccnv.pas
@@ -0,0 +1,235 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate PowerPC assembler for type converting nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit nppccnv;
+
+{$I fpcdefs.inc}
+
+interface
+
+uses
+ node, ncnv, ncgcnv, ngppccnv;
+
+type
+ tppctypeconvnode = class(tgenppctypeconvnode)
+ protected
+ { procedure second_int_to_int;override; }
+ { procedure second_string_to_string;override; }
+ { procedure second_cstring_to_pchar;override; }
+ { procedure second_string_to_chararray;override; }
+ { procedure second_array_to_pointer;override; }
+ function first_int_to_real: tnode; override;
+ { procedure second_pointer_to_array;override; }
+ { procedure second_chararray_to_string;override; }
+ { procedure second_char_to_string;override; }
+ procedure second_int_to_real; override;
+ { procedure second_real_to_real; override;}
+ { procedure second_cord_to_pointer;override; }
+ { procedure second_proc_to_procvar;override; }
+ { procedure second_bool_to_int;override; }
+ { procedure second_int_to_bool; override; }
+ { procedure second_load_smallset;override; }
+ { procedure second_ansistring_to_pchar;override; }
+ { procedure second_pchar_to_string;override; }
+ { procedure second_class_to_intf;override; }
+ { procedure second_char_to_char;override; }
+ end;
+
+implementation
+
+uses
+ verbose, globtype, globals, systems,
+ symconst, symdef, aasmbase, aasmtai,aasmdata,
+ defutil,
+ cgbase, cgutils, pass_1, pass_2,
+ ncon, ncal,procinfo,
+ ncgutil,
+ cpubase, aasmcpu,
+ rgobj, tgobj, cgobj;
+
+{*****************************************************************************
+ FirstTypeConv
+*****************************************************************************}
+
+function tppctypeconvnode.first_int_to_real: tnode;
+begin
+ if (is_currency(left.resultdef)) then begin
+ // hack to avoid double division by 10000, as it's
+ // already done by typecheckpass.resultdef_int_to_real
+ left.resultdef := s64inttype;
+ end else begin
+ // everything that is less than 64 bits is converted to a 64 bit signed
+ // integer - because the int_to_real conversion is faster for 64 bit
+ // signed ints compared to 64 bit unsigned ints.
+ if (not (torddef(left.resultdef).ordtype in [s64bit, u64bit, scurrency])) then begin
+ inserttypeconv(left, s64inttype);
+ end;
+ end;
+ firstpass(left);
+ result := nil;
+ expectloc := LOC_FPUREGISTER;
+end;
+
+{*****************************************************************************
+ SecondTypeConv
+*****************************************************************************}
+
+procedure tppctypeconvnode.second_int_to_real;
+const
+ convconst : double = $100000000;
+var
+ tempconst : tnode;
+ disp, disp2: treference;
+ // temp registers for converting signed ints
+ valuereg, leftreg,
+ // additional temp registers for converting unsigned 64 bit ints
+ tmpintreg1, tmpintreg2, tmpfpureg, tmpfpuconst : tregister;
+ size: tcgsize;
+ signed: boolean;
+begin
+
+ location_reset(location, LOC_FPUREGISTER, def_cgsize(resultdef));
+
+ { the code here comes from the PowerPC Compiler Writer's Guide }
+ { * longint to double (works for all rounding modes) }
+ { std R3,disp(R1) # store doubleword }
+ { lfd FR1,disp(R1) # load float double }
+ { fcfid FR1,FR1 # convert to floating-point integer }
+
+ { * unsigned 64 bit int to fp value (works for all rounding modes) }
+ { rldicl rT1,rS,32,32 # isolate high half }
+ { rldicl rT2,rS,0,32 # isolate low half }
+ { std rT1,disp(R1) # store high half }
+ { std rT2,disp+8(R1) # store low half }
+ { lfd frT1,disp(R1) # load high half }
+ { lfd frD,disp+8(R1) # load low half }
+ { fcfid frT1,frT1 # convert each half to floating }
+ { fcfid frD,frD # point integer (no round) }
+ { fmadd frD,frC,frT1,frD # (2^32)*high + low }
+ { # (only add can round) }
+ tg.Gettemp(current_asmdata.CurrAsmList, 8, 8, tt_normal, disp);
+
+ { do the signed case for everything but 64 bit unsigned integers }
+ signed := (left.location.size <> OS_64);
+
+ { we need a certain constant for the conversion of unsigned 64 bit integers,
+ so create them here. Additonally another temporary location is neeted }
+ if (not signed) then begin
+ // allocate temp for constant value used for unsigned 64 bit ints
+ tempconst :=
+ crealconstnode.create(convconst, pbestrealtype^);
+ typecheckpass(tempconst);
+ firstpass(tempconst);
+ secondpass(tempconst);
+ if (tempconst.location.loc <> LOC_CREFERENCE) then
+ internalerror(200110011);
+
+ // allocate second temp memory
+ tg.Gettemp(current_asmdata.CurrAsmList, 8, 8, tt_normal, disp2);
+ end;
+
+ if not(left.location.loc in [LOC_REGISTER,LOC_CREGISTER,LOC_REFERENCE,LOC_CREFERENCE]) then
+ location_force_reg(current_asmdata.CurrAsmList,left.location,left.location.size,false);
+ case left.location.loc of
+ // the conversion algorithm does not modify the input register, so it can
+ // be used for both LOC_REGISTER and LOC_CREGISTER
+ LOC_REGISTER, LOC_CREGISTER:
+ begin
+ leftreg := left.location.register;
+ valuereg := leftreg;
+ end;
+ LOC_REFERENCE, LOC_CREFERENCE:
+ begin
+ leftreg := cg.getintregister(current_asmdata.CurrAsmList, OS_INT);
+ valuereg := leftreg;
+ if signed then
+ size := OS_S64
+ else
+ size := OS_64;
+ cg.a_load_ref_reg(current_asmdata.CurrAsmList, def_cgsize(left.resultdef),
+ size, left.location.reference, leftreg);
+ end
+ else
+ internalerror(200110012);
+ end;
+
+ if (signed) then begin
+ // std rS, disp(r1)
+ cg.a_load_reg_ref(current_asmdata.CurrAsmList, OS_S64, OS_S64, valuereg, disp);
+ // lfd frD, disp(r1)
+ location.register := cg.getfpuregister(current_asmdata.CurrAsmList,OS_F64);
+ cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,OS_F64, OS_F64, disp, location.register);
+ // fcfid frD, frD
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FCFID, location.register,
+ location.register));
+ end else begin
+ { ts:todo use TOC for this constant or at least schedule better }
+ // lfd frC, const
+ tmpfpuconst := cg.getfpuregister(current_asmdata.CurrAsmList,OS_F64);
+ cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,OS_F64,OS_F64,tempconst.location.reference,
+ tmpfpuconst);
+ tempconst.free;
+
+ tmpintreg1 := cg.getintregister(current_asmdata.CurrAsmList, OS_64);
+ // rldicl rT1, rS, 32, 32
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_const_const(A_RLDICL, tmpintreg1, valuereg, 32, 32));
+ // rldicl rT2, rS, 0, 32
+ tmpintreg2 := cg.getintregister(current_asmdata.CurrAsmList, OS_64);
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_const_const(A_RLDICL, tmpintreg2, valuereg, 0, 32));
+
+ // std rT1, disp(r1)
+ cg.a_load_reg_ref(current_asmdata.CurrAsmList, OS_S64, OS_S64, tmpintreg1, disp);
+ // std rT2, disp2(r1)
+ cg.a_load_reg_ref(current_asmdata.CurrAsmList, OS_S64, OS_S64, tmpintreg2, disp2);
+
+ // lfd frT1, disp(R1)
+ tmpfpureg := cg.getfpuregister(current_asmdata.CurrAsmList,OS_F64);
+ cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,OS_F64, OS_F64, disp, tmpfpureg);
+ // lfd frD, disp+8(R1)
+ location.register := cg.getfpuregister(current_asmdata.CurrAsmList,OS_F64);
+ cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,OS_F64, OS_F64, disp2, location.register);
+
+ // fcfid frT1, frT1
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FCFID, tmpfpureg,
+ tmpfpureg));
+ // fcfid frD, frD
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FCFID, location.register,
+ location.register));
+ // fmadd frD,frC,frT1,frD # (2^32)*high + low }
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg_reg(A_FMADD, location.register, tmpfpuconst,
+ tmpfpureg, location.register));
+
+ // free used temps
+ tg.ungetiftemp(current_asmdata.CurrAsmList, disp2);
+ end;
+ // free reference
+ tg.ungetiftemp(current_asmdata.CurrAsmList, disp);
+
+ // make sure the precision is correct
+ if (tfloatdef(resultdef).floattype = s32real) then
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FRSP,location.register,
+ location.register));
+end;
+
+begin
+ ctypeconvnode := tppctypeconvnode;
+end.
+
diff --git a/closures/compiler/powerpc64/nppcld.pas b/closures/compiler/powerpc64/nppcld.pas
new file mode 100644
index 0000000000..3c1324c686
--- /dev/null
+++ b/closures/compiler/powerpc64/nppcld.pas
@@ -0,0 +1,62 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate ppc assembler for nodes that handle loads and assignments
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit nppcld;
+
+{$I fpcdefs.inc}
+
+interface
+
+uses
+ node, ncgld;
+
+type
+ tppcloadnode = class(tcgloadnode)
+ procedure pass_generate_code override;
+ procedure generate_picvaraccess; override;
+ end;
+
+implementation
+
+uses
+ verbose,
+ systems,
+ cpubase,
+ cgutils, cgobj,
+ aasmbase, aasmtai,aasmdata,
+ symconst, symsym,
+ procinfo,
+ nld;
+
+procedure tppcloadnode.pass_generate_code;
+begin
+ inherited pass_generate_code;
+end;
+
+procedure tppcloadnode.generate_picvaraccess;
+begin
+ internalerror(200402291);
+end;
+
+begin
+ cloadnode := tppcloadnode;
+end.
+
diff --git a/closures/compiler/powerpc64/nppcmat.pas b/closures/compiler/powerpc64/nppcmat.pas
new file mode 100644
index 0000000000..b1a008188c
--- /dev/null
+++ b/closures/compiler/powerpc64/nppcmat.pas
@@ -0,0 +1,446 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate PowerPC assembler for math nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit nppcmat;
+
+{$I fpcdefs.inc}
+
+interface
+
+uses
+ node, nmat;
+
+type
+ tppcmoddivnode = class(tmoddivnode)
+ function pass_1: tnode; override;
+ procedure pass_generate_code override;
+ end;
+
+ tppcshlshrnode = class(tshlshrnode)
+ procedure pass_generate_code override;
+ end;
+
+ tppcunaryminusnode = class(tunaryminusnode)
+ procedure pass_generate_code override;
+ end;
+
+ tppcnotnode = class(tnotnode)
+ procedure pass_generate_code override;
+ end;
+
+implementation
+
+uses
+ sysutils,
+ globtype, systems,constexp,
+ cutils, verbose, globals,
+ symconst, symdef,
+ aasmbase, aasmcpu, aasmtai,aasmdata,
+ defutil,
+ cgbase, cgutils, cgobj, pass_1, pass_2,
+ ncon, procinfo, nbas, nld, nadd,
+ cpubase, cpuinfo,
+ ncgutil, cgcpu, rgobj;
+
+{*****************************************************************************
+ TPPCMODDIVNODE
+*****************************************************************************}
+
+function tppcmoddivnode.pass_1: tnode;
+var
+ statementnode : tstatementnode;
+ temp_left, temp_right : ttempcreatenode;
+ left_copy, right_copy : tnode;
+ block : tblocknode;
+begin
+ result := nil;
+ (*
+ // this code replaces all mod nodes by the equivalent div/mul/sub sequence
+ // on node level, which might be advantageous when doing CSE on that level
+ // However, optimal modulo code for some cases (in particular a 'x mod 2^n-1'
+ // operation) can not be expressed using nodes, so this is commented out for now
+ if (nodetype = modn) then begin
+ block := internalstatements(statementnode);
+
+ temp_left := ctempcreatenode.create(left.resultdef, left.resultdef.size, tt_persistent, true);
+ addstatement(statementnode, temp_left);
+ addstatement(statementnode, cassignmentnode.create(ctemprefnode.create(temp_left), left.getcopy));
+
+ if (right.nodetype <> ordconstn) then begin
+ // implementated optimization: use temps to store the right value, otherwise
+ // it is calculated twice when simply copying it which might result in side
+ // effects
+ temp_right := ctempcreatenode.create(right.resultdef, right.resultdef.size, tt_persistent, true);
+ addstatement(statementnode, temp_right);
+ addstatement(statementnode, cassignmentnode.create(ctemprefnode.create(temp_right), right.getcopy));
+
+ addstatement(statementnode, cassignmentnode.create(ctemprefnode.create(temp_left),
+ caddnode.create(subn, ctemprefnode.create(temp_left),
+ caddnode.create(muln, cmoddivnode.create(divn, ctemprefnode.create(temp_left), ctemprefnode.create(temp_right)),
+ ctemprefnode.create(temp_right)))));
+
+ addstatement(statementnode, ctempdeletenode.create(temp_right));
+ end else begin
+ // in case this is a modulo by a constant operation, do not use a temp for the
+ // right hand side, because otherwise the div optimization will not recognize this
+ // fact (and there is no constant propagator/recognizer in the compiler),
+ // resulting in suboptimal code.
+ addstatement(statementnode, cassignmentnode.create(ctemprefnode.create(temp_left),
+ caddnode.create(subn, ctemprefnode.create(temp_left),
+ caddnode.create(muln, cmoddivnode.create(divn, ctemprefnode.create(temp_left), right.getcopy),
+ right.getcopy))));
+ end;
+ addstatement(statementnode, ctempdeletenode.create_normal_temp(temp_left));
+ addstatement(statementnode, ctemprefnode.create(temp_left));
+ result := block;
+ end;
+ *)
+ if (not assigned(result)) then
+ result := inherited pass_1;
+ if not assigned(result) then
+ include(current_procinfo.flags, pi_do_call);
+end;
+
+procedure tppcmoddivnode.pass_generate_code;
+const { signed overflow }
+ divops: array[boolean, boolean] of tasmop =
+ ((A_DIVDU, A_DIVDU_),(A_DIVD, A_DIVDO_));
+ divcgops : array[boolean] of TOpCG = (OP_DIV, OP_IDIV);
+ zerocond: tasmcond = (dirhint: DH_Plus; simple: true; cond:C_NE; cr: RS_CR7);
+ tcgsize2native : array[OS_8..OS_S128] of tcgsize = (
+ OS_64, OS_64, OS_64, OS_64, OS_NO,
+ OS_S64, OS_S64, OS_S64, OS_S64, OS_NO
+ );
+var
+ power : longint;
+ op : tasmop;
+ numerator, divider,
+ resultreg : tregister;
+ size : TCgSize;
+ hl : tasmlabel;
+ done: boolean;
+
+ procedure genOrdConstNodeMod;
+ var
+ modreg, maskreg, tempreg : tregister;
+ isNegPower : boolean;
+ begin
+ if (tordconstnode(right).value = 0) then begin
+ internalerror(2005061702);
+ end else if (abs(tordconstnode(right).value.svalue) = 1) then begin
+ { x mod +/-1 is always zero }
+ cg.a_load_const_reg(current_asmdata.CurrAsmList, OS_INT, 0, resultreg);
+ end else if (ispowerof2(tordconstnode(right).value, power)) then begin
+ if (is_signed(right.resultdef)) then begin
+ tempreg := cg.getintregister(current_asmdata.CurrAsmList, OS_INT);
+ maskreg := cg.getintregister(current_asmdata.CurrAsmList, OS_INT);
+ modreg := cg.getintregister(current_asmdata.CurrAsmList, OS_INT);
+
+ cg.a_load_const_reg(current_asmdata.CurrAsmList, OS_INT, abs(tordconstnode(right).value.svalue)-1, modreg);
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_SAR, OS_INT, 63, numerator, maskreg);
+ cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList, OP_AND, OS_INT, numerator, modreg, tempreg);
+
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_ANDC, maskreg, maskreg, modreg));
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_const(A_SUBFIC, modreg, tempreg, 0));
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SUBFE, modreg, modreg, modreg));
+ cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList, OP_AND, OS_INT, modreg, maskreg, maskreg);
+ cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList, OP_OR, OS_INT, maskreg, tempreg, resultreg);
+ end else begin
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_AND, OS_INT, tordconstnode(right).value-1, numerator,
+ resultreg);
+ end;
+ end else begin
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, divCgOps[is_signed(right.resultdef)], OS_INT,
+ tordconstnode(right).value, numerator, resultreg);
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_MUL, OS_INT, tordconstnode(right).value.svalue, resultreg,
+ resultreg);
+ cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList, OP_SUB, OS_INT, resultreg, numerator, resultreg);
+ end;
+ end;
+
+
+begin
+ secondpass(left);
+ secondpass(right);
+ location_copy(location,left.location);
+
+ { put numerator in register }
+ size:=def_cgsize(left.resultdef);
+ location_force_reg(current_asmdata.CurrAsmList,left.location,
+ size,true);
+ location_copy(location,left.location);
+ numerator := location.register;
+ resultreg := location.register;
+ if (location.loc = LOC_CREGISTER) then begin
+ location.loc := LOC_REGISTER;
+ location.register := cg.getintregister(current_asmdata.CurrAsmList,size);
+ resultreg := location.register;
+ end else if (nodetype = modn) or (right.nodetype = ordconstn) then begin
+ { for a modulus op, and for const nodes we need the result register
+ to be an extra register }
+ resultreg := cg.getintregister(current_asmdata.CurrAsmList,size);
+ end;
+ done := false;
+ if (cs_opt_level1 in current_settings.optimizerswitches) and (right.nodetype = ordconstn) then begin
+ if (nodetype = divn) then
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, divCgOps[is_signed(right.resultdef)],
+ size, tordconstnode(right).value, numerator, resultreg)
+ else
+ genOrdConstNodeMod;
+ done := true;
+ end;
+
+ if (not done) then begin
+ { load divider in a register if necessary }
+ location_force_reg(current_asmdata.CurrAsmList,right.location,def_cgsize(right.resultdef),true);
+ if (right.nodetype <> ordconstn) then
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_const(A_CMPDI, NR_CR7,
+ right.location.register, 0))
+ else begin
+ if (tordconstnode(right).value = 0) then
+ internalerror(2005100301);
+ end;
+ divider := right.location.register;
+
+ { select the correct opcode according to the sign of the result, whether we need
+ overflow checking }
+ op := divops[is_signed(right.resultdef), cs_check_overflow in current_settings.localswitches];
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(op, resultreg, numerator,
+ divider));
+
+ if (nodetype = modn) then begin
+ { multiply with the divisor again, taking care of the correct size }
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_MULLD,resultreg,
+ divider,resultreg));
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SUB,location.register,
+ numerator,resultreg));
+ resultreg := location.register;
+ end;
+ end;
+ { set result location }
+ location.loc:=LOC_REGISTER;
+ location.register:=resultreg;
+ if right.nodetype <> ordconstn then begin
+ current_asmdata.getjumplabel(hl);
+ current_asmdata.CurrAsmList.concat(taicpu.op_cond_sym(A_BC,zerocond,hl));
+ cg.a_call_name(current_asmdata.CurrAsmList,'FPC_DIVBYZERO',false);
+ cg.a_label(current_asmdata.CurrAsmList,hl);
+ end;
+ { unsigned division/module can only overflow in case of division by zero
+ (but checking this overflow flag is more convoluted than performing a
+ simple comparison with 0) }
+ if is_signed(right.resultdef) then
+ cg.g_overflowcheck(current_asmdata.CurrAsmList,location,resultdef);
+end;
+
+{*****************************************************************************
+ TPPCSHLRSHRNODE
+*****************************************************************************}
+
+procedure tppcshlshrnode.pass_generate_code;
+
+var
+ resultreg, hregister1, hregister2 : tregister;
+
+ op: topcg;
+ asmop1, asmop2: tasmop;
+ shiftval: aint;
+
+begin
+ secondpass(left);
+ secondpass(right);
+
+ { load left operators in a register }
+ location_force_reg(current_asmdata.CurrAsmList, left.location,
+ def_cgsize(left.resultdef), true);
+ location_copy(location, left.location);
+ resultreg := location.register;
+ hregister1 := location.register;
+ if (location.loc = LOC_CREGISTER) then begin
+ location.loc := LOC_REGISTER;
+ resultreg := cg.getintregister(current_asmdata.CurrAsmList, OS_INT);
+ location.register := resultreg;
+ end;
+
+ { determine operator }
+ if nodetype = shln then
+ op := OP_SHL
+ else
+ op := OP_SHR;
+
+ { shifting by a constant directly coded: }
+ if (right.nodetype = ordconstn) then begin
+ // result types with size < 32 bits have their shift values masked
+ // differently... :/
+ shiftval := tordconstnode(right).value and (tcgsize2size[def_cgsize(resultdef)] * 8 -1);
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, op, def_cgsize(resultdef),
+ shiftval, hregister1, resultreg)
+ end else begin
+ { load shift count in a register if necessary }
+ location_force_reg(current_asmdata.CurrAsmList, right.location,
+ def_cgsize(right.resultdef), true);
+ hregister2 := right.location.register;
+ cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList, op, def_cgsize(resultdef), hregister2,
+ hregister1, resultreg);
+ end;
+end;
+
+{*****************************************************************************
+ TPPCUNARYMINUSNODE
+*****************************************************************************}
+
+procedure tppcunaryminusnode.pass_generate_code;
+
+var
+ src1: tregister;
+ op: tasmop;
+
+begin
+ secondpass(left);
+ begin
+ if left.location.loc in [LOC_SUBSETREG,LOC_CSUBSETREG,LOC_SUBSETREF,LOC_CSUBSETREF] then
+ location_force_reg(current_asmdata.CurrAsmList,left.location,left.location.size,true);
+ location_copy(location, left.location);
+ location.loc := LOC_REGISTER;
+ case left.location.loc of
+ LOC_FPUREGISTER, LOC_REGISTER:
+ begin
+ src1 := left.location.register;
+ location.register := src1;
+ end;
+ LOC_CFPUREGISTER, LOC_CREGISTER:
+ begin
+ src1 := left.location.register;
+ if left.location.loc = LOC_CREGISTER then
+ location.register := cg.getintregister(current_asmdata.CurrAsmList, OS_INT)
+ else
+ location.register := cg.getfpuregister(current_asmdata.CurrAsmList, location.size);
+ end;
+ LOC_REFERENCE, LOC_CREFERENCE:
+ begin
+ if (left.resultdef.typ = floatdef) then begin
+ src1 := cg.getfpuregister(current_asmdata.CurrAsmList,
+ left.location.size);
+ location.register := src1;
+ cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,
+ left.location.size,left.location.size,
+ left.location.reference, src1);
+ end else begin
+ src1 := cg.getintregister(current_asmdata.CurrAsmList, OS_64);
+ location.register := src1;
+ cg.a_load_ref_reg(current_asmdata.CurrAsmList, OS_64, OS_64,
+ left.location.reference, src1);
+ end;
+ end;
+ end;
+ { choose appropriate operand }
+ if left.resultdef.typ <> floatdef then begin
+ if not (cs_check_overflow in current_settings.localswitches) then
+ op := A_NEG
+ else
+ op := A_NEGO_;
+ location.loc := LOC_REGISTER;
+ end else begin
+ op := A_FNEG;
+ location.loc := LOC_FPUREGISTER;
+ end;
+ { emit operation }
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op, location.register, src1));
+ end;
+ cg.g_overflowcheck(current_asmdata.CurrAsmList, location, resultdef);
+end;
+
+{*****************************************************************************
+ TPPCNOTNODE
+*****************************************************************************}
+
+procedure tppcnotnode.pass_generate_code;
+
+var
+ hl: tasmlabel;
+
+begin
+ if is_boolean(resultdef) then
+ begin
+ { if the location is LOC_JUMP, we do the secondpass after the
+ labels are allocated
+ }
+ if left.expectloc = LOC_JUMP then
+ begin
+ hl := current_procinfo.CurrTrueLabel;
+ current_procinfo.CurrTrueLabel := current_procinfo.CurrFalseLabel;
+ current_procinfo.CurrFalseLabel := hl;
+ secondpass(left);
+ maketojumpbool(current_asmdata.CurrAsmList, left, lr_load_regvars);
+ hl := current_procinfo.CurrTrueLabel;
+ current_procinfo.CurrTrueLabel := current_procinfo.CurrFalseLabel;
+ current_procinfo.CurrFalseLabel := hl;
+ location.loc := LOC_JUMP;
+ end
+ else
+ begin
+ secondpass(left);
+ case left.location.loc of
+ LOC_FLAGS:
+ begin
+ location_copy(location, left.location);
+ inverse_flags(location.resflags);
+ end;
+ LOC_REGISTER, LOC_CREGISTER,
+ LOC_REFERENCE, LOC_CREFERENCE,
+ LOC_SUBSETREG, LOC_CSUBSETREG,
+ LOC_SUBSETREF, LOC_CSUBSETREF:
+ begin
+ location_force_reg(current_asmdata.CurrAsmList, left.location,
+ def_cgsize(left.resultdef), true);
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_CMPDI,
+ left.location.register, 0));
+ location_reset(location, LOC_FLAGS, OS_NO);
+ location.resflags.cr := RS_CR0;
+ location.resflags.flag := F_EQ;
+ end;
+ else
+ internalerror(2003042401);
+ end;
+ end;
+ end
+ else
+ begin
+ secondpass(left);
+ location_force_reg(current_asmdata.CurrAsmList, left.location,
+ def_cgsize(left.resultdef), true);
+ location_copy(location, left.location);
+ location.loc := LOC_REGISTER;
+ location.register := cg.getintregister(current_asmdata.CurrAsmList, OS_INT);
+ { perform the NOT operation }
+ cg.a_op_reg_reg(current_asmdata.CurrAsmList, OP_NOT, def_cgsize(resultdef),
+ left.location.register,
+ location.register);
+ end;
+end;
+
+begin
+ cmoddivnode := tppcmoddivnode;
+ cshlshrnode := tppcshlshrnode;
+ cunaryminusnode := tppcunaryminusnode;
+ cnotnode := tppcnotnode;
+end.
+
diff --git a/closures/compiler/powerpc64/ppcins.dat b/closures/compiler/powerpc64/ppcins.dat
new file mode 100644
index 0000000000..708b1f8c0d
--- /dev/null
+++ b/closures/compiler/powerpc64/ppcins.dat
@@ -0,0 +1,75 @@
+;****************************************************************************
+;
+; Copyright (c) 2002 by Florian Klaempfl
+;
+; Instruction template table for the PowerPC
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+;
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program; if not, write to the Free Software
+; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+;
+;****************************************************************************
+;
+add rD,rA,rB opcode=31,op22=266,oe=0,rc=0
+add_ rD,rA,rB opcode=31,op22=266,oe=0,rc=1
+addo rD,rA,rB opcode=31,op22=266,oe=1,rc=0
+addo_ rD,rA,rB opcode=31,op22=266,oe=1,rc=1
+addc rD,rA,rB opcode=31,op22=10,oe=0,rc=0
+addc_ rD,rA,rB opcode=31,op22=10,oe=0,rc=1
+addco rD,rA,rB opcode=31,op22=10,oe=1,rc=0
+addco_ rD,rA,rB opcode=31,op22=10,oe=1,rc=1
+adde rD,rA,rB opcode=31,op22=138,oe=0,rc=0
+adde_ rD,rA,rB opcode=31,op22=138,oe=0,rc=1
+addeo rD,rA,rB opcode=31,op22=138,oe=1,rc=0
+addeo_ rD,rA,rB opcode=31,op22=138,oe=1,rc=1
+addi rD,rA,SIMM opcode=14
+addic rD,rA,SIMM opcode=12
+addic_ rD,rA,SIMM opcode=13
+addis rD,rA,SIMM opcode=15
+addme rD,rA opcode=31,op22=234,oe=0,rc=0,reserved=$000f0000
+addme_ rD,rA opcode=31,op22=234,oe=0,rc=1,reserved=$000f0000
+addmeo rD,rA opcode=31,op22=234,oe=1,rc=0,reserved=$000f0000
+addmeo_ rD,rA opcode=31,op22=234,oe=1,rc=1,reserved=$000f0000
+addze rD,rA opcode=31,op22=202,oe=0,rc=0,reserved=$000f0000
+addze_ rD,rA opcode=31,op22=202,oe=0,rc=1,reserved=$000f0000
+addzeo rD,rA opcode=31,op22=202,oe=1,rc=0,reserved=$000f0000
+addzeo_ rD,rA opcode=31,op22=202,oe=1,rc=1,reserved=$000f0000
+and rA,rS,rB opcode=31,op21=28,rc=0
+and_ rA,rS,rB opcode=31,op21=28,rc=1
+andc rA,rS,rB opcode=31,op21=60,rc=0
+andc_ rA,rS,rB opcode=31,op21=60,rc=1
+andi_ rA,rS,UIMM opcode=28
+andis_ rA,rS,UIMM opcode=29
+b TA24 opcode=18,aa=0,lk=0
+ba TA24 opcode=18,aa=1,lk=0
+bl TA24 opcode=18,aa=0,lk=1
+bla TA24 opcode=18,aa=1,lk=1
+bc BO,BI,TA14 opcode=16,aa=0,lk=0
+bca BO,BI,TA14 opcode=16,aa=1,lk=0
+bcl BO,BI,TA14 opcode=16,aa=0,lk=1
+bcla BO,BI,TA14 opcode=16,aa=1,lk=1
+bcctr BO,BI opcode=19,op21=528,lk=0,reserved=$000f0000
+bcctrl BO,BI opcode=19,op21=528,lk=1,reserved=$000f0000
+bcltr BO,BI opcode=19,op21=16,lk=0,reserved=$000f0000
+bcltrl BO,BI opcode=19,op21=16,lk=1,reserved=$000f0000
+cmp crfD,L,rA,rB opcode=31,op21=0,reserved=$80000200
+cmpi crfD,L,rA,SIMM opcode=11,reserved=$00000200
+cmpl crfD,L,rA,rB opcode=31,op21=32,reserved=$80000200
+cmpli crfD,L,rA,UIMM opcode=10,reserved=$00000200
+
+;
+
+; Revision 1.1 2002/07/13 21:50:34 florian
+; + initial version, a lot of instructions need to be added
+;
+;
diff --git a/closures/compiler/powerpc64/ppcreg.dat b/closures/compiler/powerpc64/ppcreg.dat
new file mode 100644
index 0000000000..325143e679
--- /dev/null
+++ b/closures/compiler/powerpc64/ppcreg.dat
@@ -0,0 +1,143 @@
+;
+;
+; PowerPC registers
+;
+; layout
+; <name>,<value>,<stdname>,<gasname>,<gasshortname>,<motname>,<stabidx>
+;
+NO,$00,$00,INVALID,INVALID,INVALID,INVALID,-1,-1
+
+R0,$01,$00,r0,r0,0,r0,0,0
+R1,$01,$01,r1,r1,1,r1,1,1
+R2,$01,$02,r2,r2,2,r2,2,2
+R3,$01,$03,r3,r3,3,r3,3,3
+R4,$01,$04,r4,r4,4,r4,4,4
+R5,$01,$05,r5,r5,5,r5,5,5
+R6,$01,$06,r6,r6,6,r6,6,6
+R7,$01,$07,r7,r7,7,r7,7,7
+R8,$01,$08,r8,r8,8,r8,8,8
+R9,$01,$09,r9,r9,9,r9,9,9
+R10,$01,$0a,r10,r10,10,r10,10,10
+R11,$01,$0b,r11,r11,11,r11,11,11
+R12,$01,$0c,r12,r12,12,r12,12,12
+R13,$01,$0d,r13,r13,13,r13,13,13
+R14,$01,$0e,r14,r14,14,r14,14,14
+R15,$01,$0f,r15,r15,15,r15,15,15
+R16,$01,$10,r16,r16,16,r16,16,16
+R17,$01,$11,r17,r17,17,r17,17,17
+R18,$01,$12,r18,r18,18,r18,18,18
+R19,$01,$13,r19,r19,19,r19,19,19
+R20,$01,$14,r20,r20,20,r20,20,20
+R21,$01,$15,r21,r21,21,r21,21,21
+R22,$01,$16,r22,r22,22,r22,22,22
+R23,$01,$17,r23,r23,23,r23,23,23
+R24,$01,$18,r24,r24,24,r24,24,24
+R25,$01,$19,r25,r25,25,r25,25,25
+R26,$01,$1a,r26,r26,26,r26,26,26
+R27,$01,$1b,r27,r27,27,r27,27,27
+R28,$01,$1c,r28,r28,28,r28,28,28
+R29,$01,$1d,r29,r29,29,r29,29,29
+R30,$01,$1e,r30,r30,30,r30,30,30
+R31,$01,$1f,r31,r31,31,r31,31,31
+
+F0,$02,$00,F0,f0,0,F0,32,32
+F1,$02,$01,F1,f1,1,F1,33,33
+F2,$02,$02,F2,f2,2,F2,34,34
+F3,$02,$03,F3,f3,3,F3,35,35
+F4,$02,$04,F4,f4,4,F4,36,36
+F5,$02,$05,F5,f5,5,F5,37,37
+F6,$02,$06,F6,f6,6,F6,38,38
+F7,$02,$07,F7,f7,7,F7,39,39
+F8,$02,$08,F8,f8,8,F8,40,40
+F9,$02,$09,F9,f9,9,F9,41,41
+F10,$02,$0a,F10,f10,10,F10,42,42
+F11,$02,$0b,F11,f11,11,F11,43,43
+F12,$02,$0c,F12,f12,12,F12,44,44
+F13,$02,$0d,F13,f13,13,F13,45,45
+F14,$02,$0e,F14,f14,14,F14,46,46
+F15,$02,$0f,F15,f15,15,F15,47,47
+F16,$02,$10,F16,f16,16,F16,48,48
+F17,$02,$11,F17,f17,17,F17,49,49
+F18,$02,$12,F18,f18,18,F18,50,50
+F19,$02,$13,F19,f19,19,F19,51,51
+F20,$02,$14,F20,f20,20,F20,52,52
+F21,$02,$15,F21,f21,21,F21,53,53
+F22,$02,$16,F22,f22,22,F22,54,54
+F23,$02,$17,F23,f23,23,F23,55,55
+F24,$02,$18,F24,f24,24,F24,56,56
+F25,$02,$19,F25,f25,25,F25,57,57
+F26,$02,$1a,F26,f26,26,F26,58,58
+F27,$02,$1b,F27,f27,27,F27,59,59
+F28,$02,$1c,F28,f28,28,F28,60,60
+F29,$02,$1d,F29,f29,29,F29,61,61
+F30,$02,$1e,F30,f30,30,F30,62,62
+F31,$02,$1f,F31,f31,31,F31,63,63
+
+M0,$03,$00,M0,v0,0,M0,-1,-1
+M1,$03,$01,M1,v1,1,M1,-1,-1
+M2,$03,$02,M2,v2,2,M2,-1,-1
+M3,$03,$03,M3,v3,3,M3,-1,-1
+M4,$03,$04,M4,v4,4,M4,-1,-1
+M5,$03,$05,M5,v5,5,M5,-1,-1
+M6,$03,$06,M6,v6,6,M6,-1,-1
+M7,$03,$07,M7,v7,7,M7,-1,-1
+M8,$03,$08,M8,v8,8,M8,-1,-1
+M9,$03,$09,M9,v9,9,M9,-1,-1
+M10,$03,$0a,M10,v10,10,M10,-1,-1
+M11,$03,$0b,M11,v11,11,M11,-1,-1
+M12,$03,$0c,M12,v12,12,M12,-1,-1
+M13,$03,$0d,M13,v13,13,M13,-1,-1
+M14,$03,$0e,M14,v14,14,M14,-1,-1
+M15,$03,$0f,M15,v15,15,M15,-1,-1
+M16,$03,$10,M16,v16,16,M16,-1,-1
+M17,$03,$11,M17,v17,17,M17,-1,-1
+M18,$03,$12,M18,v18,18,M18,-1,-1
+M19,$03,$13,M19,v19,19,M19,-1,-1
+M20,$03,$14,M20,v20,20,M20,-1,-1
+M21,$03,$15,M21,v21,21,M21,-1,-1
+M22,$03,$16,M22,v22,22,M22,-1,-1
+M23,$03,$17,M23,v23,23,M23,-1,-1
+M24,$03,$18,M24,v24,24,M24,-1,-1
+M25,$03,$19,M25,v25,25,M25,-1,-1
+M26,$03,$1a,M26,v26,26,M26,-1,-1
+M27,$03,$1b,M27,v27,27,M27,-1,-1
+M28,$03,$1c,M28,v28,28,M28,-1,-1
+M29,$03,$1d,M29,v29,29,M29,-1,-1
+M30,$03,$1e,M30,v30,30,M30,-1,-1
+M31,$03,$1f,M31,v31,31,M31,-1,-1
+
+CR,$05,$00,CR,cr,cr,CR,-1,-1
+CR0,$05,$01,CR0,cr0,cr0,CR0,68,68
+CR1,$05,$02,CR1,cr1,cr1,CR1,69,69
+CR2,$05,$03,CR2,cr2,cr2,CR2,70,70
+CR3,$05,$04,CR3,cr3,cr3,CR3,71,71
+CR4,$05,$05,CR4,cr4,cr4,CR4,72,72
+CR5,$05,$06,CR5,cr5,cr5,CR5,73,73
+CR6,$05,$07,CR6,cr6,cr6,CR6,74,74
+CR7,$05,$08,CR7,cr7,cr7,CR7,75,75
+XER,$05,$09,XER,xer,xer,XER,76,76
+LR,$05,$0a,LR,lr,lr,LR,65,65
+CTR,$05,$0b,CTR,ctr,ctr,CTR,66,66
+FPSCR,$05,$0c,FPSCR,fpscr,fpscr,FPSCR,-1,-1
+
+;
+
+; Revision 1.6 2004/06/17 16:55:46 peter
+; * powerpc compiles again
+;
+; Revision 1.5 2003/12/10 22:19:27 florian
+; + short gas register names for smartlinking added
+;
+; Revision 1.4 2003/09/04 21:07:03 florian
+; * ARM compiler compiles again
+;
+; Revision 1.3 2003/09/03 19:35:24 peter
+; * powerpc compiles again
+;
+; Revision 1.2 2003/09/03 15:55:01 peter
+; * NEWRA branch merged
+;
+; Revision 1.1.2.1 2003/09/02 20:48:22 peter
+; * powerpc registers
+;
+;
diff --git a/closures/compiler/powerpc64/rappc.pas b/closures/compiler/powerpc64/rappc.pas
new file mode 100644
index 0000000000..b52553e9af
--- /dev/null
+++ b/closures/compiler/powerpc64/rappc.pas
@@ -0,0 +1,42 @@
+{
+ Copyright (c) 1998-2003 by Carl Eric Codere and Peter Vreman
+
+ Handles the common ppc assembler reader routines
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit rappc;
+
+{$I fpcdefs.inc}
+
+interface
+
+uses
+ aasmbase, aasmtai,aasmdata, aasmcpu,
+ cpubase, rautils, cclasses;
+
+type
+ TPPCOperand = class(TOperand)
+ end;
+
+ TPPCInstruction = class(TInstruction)
+ end;
+
+implementation
+
+end.
+
diff --git a/closures/compiler/powerpc64/rappcgas.pas b/closures/compiler/powerpc64/rappcgas.pas
new file mode 100644
index 0000000000..cc69533689
--- /dev/null
+++ b/closures/compiler/powerpc64/rappcgas.pas
@@ -0,0 +1,799 @@
+{
+ $Id: rappcgas.pas,v 1.19 2005/02/14 17:13:10 peter Exp $
+ Copyright (c) 1998-2002 by Carl Eric Codere and Peter Vreman
+
+ Does the parsing for the PowerPC GNU AS styled inline assembler.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit rappcgas;
+
+{$I fpcdefs.inc}
+
+interface
+
+uses
+ raatt, rappc;
+
+type
+ tppcattreader = class(tattreader)
+ function is_asmopcode(const s: string): boolean; override;
+ procedure handleopcode; override;
+ procedure BuildReference(oper: tppcoperand);
+ procedure BuildOperand(oper: tppcoperand);
+ procedure BuildOpCode(instr: tppcinstruction);
+ procedure ReadAt(oper: tppcoperand);
+ procedure ReadSym(oper: tppcoperand);
+ procedure ConvertCalljmp(instr: tppcinstruction);
+ end;
+
+implementation
+
+uses
+ { helpers }
+ cutils,
+ { global }
+ globtype, verbose,
+ systems,
+ { aasm }
+ cpubase, aasmbase, aasmtai,aasmdata, aasmcpu,
+ { symtable }
+ symconst, symsym,
+ { parser }
+ procinfo,
+ rabase, rautils,
+ cgbase, cgobj
+ ;
+
+procedure tppcattreader.ReadSym(oper: tppcoperand);
+var
+ tempstr, mangledname: string;
+ typesize, l, k: aint;
+begin
+ tempstr := actasmpattern;
+ Consume(AS_ID);
+ { typecasting? }
+ if (actasmtoken = AS_LPAREN) and
+ SearchType(tempstr, typesize) then
+ begin
+ oper.hastype := true;
+ Consume(AS_LPAREN);
+ BuildOperand(oper);
+ Consume(AS_RPAREN);
+ if oper.opr.typ in [OPR_REFERENCE, OPR_LOCAL] then
+ oper.SetSize(typesize, true);
+ end
+ else if not oper.SetupVar(tempstr, false) then
+ Message1(sym_e_unknown_id, tempstr);
+ { record.field ? }
+ if actasmtoken = AS_DOT then
+ begin
+ BuildRecordOffsetSize(tempstr, l, k, mangledname, false);
+ if (mangledname<>'') then
+ Message(asmr_e_invalid_reference_syntax);
+ inc(oper.opr.ref.offset, l);
+ end;
+end;
+
+procedure tppcattreader.ReadAt(oper: tppcoperand);
+begin
+ { check for ...@ }
+ if actasmtoken = AS_AT then
+ begin
+ if (oper.opr.ref.symbol = nil) and
+ (oper.opr.ref.offset = 0) then
+ Message(asmr_e_invalid_reference_syntax);
+ Consume(AS_AT);
+ if actasmtoken = AS_ID then
+ begin
+ if upper(actasmpattern) = 'L' then
+ oper.opr.ref.refaddr := addr_low
+ else if upper(actasmpattern) = 'HA' then
+ oper.opr.ref.refaddr := addr_higha
+ else if upper(actasmpattern) = 'H' then
+ oper.opr.ref.refaddr := addr_high
+ else if upper(actasmpattern) = 'HIGHERA' then
+ oper.opr.ref.refaddr := addr_highera
+ else if upper(actasmpattern) = 'HIGHESTA' then
+ oper.opr.ref.refaddr := addr_highesta
+ else if upper(actasmpattern) = 'HIGHER' then
+ oper.opr.ref.refaddr := addr_higher
+ else if upper(actasmpattern) = 'HIGHEST' then
+ oper.opr.ref.refaddr := addr_highest
+ else
+ Message(asmr_e_invalid_reference_syntax);
+
+ { darwin/ppc64's relocation symbols are 32 bits }
+ if (target_info.system = system_powerpc64_darwin) and
+ (not (oper.opr.ref.refaddr in [addr_no, addr_low, addr_higha])) then
+ Message(asmr_e_invalid_reference_syntax);
+
+ Consume(AS_ID);
+ end
+ else
+ Message(asmr_e_invalid_reference_syntax);
+ end;
+end;
+
+procedure tppcattreader.BuildReference(oper: tppcoperand);
+
+ procedure Consume_RParen;
+ begin
+ if actasmtoken <> AS_RPAREN then
+ begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(true);
+ end
+ else
+ begin
+ Consume(AS_RPAREN);
+ if not (actasmtoken in [AS_COMMA, AS_SEPARATOR, AS_END]) then
+ begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(true);
+ end;
+ end;
+ end;
+
+var
+ l: aint;
+ relsym: string;
+ asmsymtyp: tasmsymtype;
+
+begin
+ Consume(AS_LPAREN);
+ case actasmtoken of
+ AS_INTNUM,
+ AS_MINUS,
+ AS_PLUS:
+ begin
+ { offset(offset) is invalid }
+ if oper.opr.Ref.Offset <> 0 then
+ begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(true);
+ end
+ else
+ begin
+ oper.opr.Ref.Offset := BuildConstExpression(false, true);
+ Consume(AS_RPAREN);
+ if actasmtoken = AS_AT then
+ ReadAt(oper);
+ end;
+ exit;
+ end;
+ AS_REGISTER: { (reg ... }
+ begin
+ if ((oper.opr.typ = OPR_REFERENCE) and (oper.opr.ref.base <> NR_NO)) or
+ ((oper.opr.typ = OPR_LOCAL) and (oper.opr.localsym.localloc.loc <>
+ LOC_REGISTER)) then
+ message(asmr_e_cannot_index_relative_var);
+ oper.opr.ref.base := actasmregister;
+ Consume(AS_REGISTER);
+ { can either be a register or a right parenthesis }
+ { (reg) }
+ if actasmtoken = AS_RPAREN then
+ begin
+ Consume_RParen;
+ exit;
+ end;
+ { (reg,reg .. }
+ Consume(AS_COMMA);
+ if (actasmtoken = AS_REGISTER) and
+ (oper.opr.Ref.Offset = 0) then
+ begin
+ oper.opr.ref.index := actasmregister;
+ Consume(AS_REGISTER);
+ Consume_RParen;
+ end
+ else
+ begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(false);
+ end;
+ end; {end case }
+ AS_ID:
+ begin
+ ReadSym(oper);
+ case actasmtoken of
+ AS_PLUS:
+ begin
+ { add a constant expression? }
+ l:=BuildConstExpression(true,true);
+ case oper.opr.typ of
+ OPR_CONSTANT :
+ inc(oper.opr.val,l);
+ OPR_LOCAL :
+ inc(oper.opr.localsymofs,l);
+ OPR_REFERENCE :
+ inc(oper.opr.ref.offset,l);
+ else
+ internalerror(200309202);
+ end;
+ end;
+ AS_MINUS:
+ begin
+ Consume(AS_MINUS);
+ BuildConstSymbolExpression(false,true,false,l,relsym,asmsymtyp);
+ if (relsym<>'') then
+ begin
+ if (oper.opr.typ = OPR_REFERENCE) then
+ oper.opr.ref.relsymbol:=current_asmdata.RefAsmSymbol(relsym)
+ else
+ begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(false);
+ end
+ end
+ else
+ begin
+ case oper.opr.typ of
+ OPR_CONSTANT :
+ dec(oper.opr.val,l);
+ OPR_LOCAL :
+ dec(oper.opr.localsymofs,l);
+ OPR_REFERENCE :
+ dec(oper.opr.ref.offset,l);
+ else
+ internalerror(2007092601);
+ end;
+ end;
+ end;
+ end;
+ Consume(AS_RPAREN);
+ if actasmtoken = AS_AT then
+ ReadAt(oper);
+ end;
+ AS_COMMA: { (, ... can either be scaling, or index }
+ begin
+ Consume(AS_COMMA);
+ { Index }
+ if (actasmtoken = AS_REGISTER) then
+ begin
+ oper.opr.ref.index := actasmregister;
+ Consume(AS_REGISTER);
+ { check for scaling ... }
+ Consume_RParen;
+ end
+ else
+ begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(false);
+ end;
+ end;
+ else
+ begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(false);
+ end;
+ end;
+end;
+
+procedure tppcattreader.BuildOperand(oper: tppcoperand);
+var
+ expr: string;
+ typesize, l: aint;
+
+ procedure AddLabelOperand(hl: tasmlabel);
+ begin
+ if not (actasmtoken in [AS_PLUS, AS_MINUS, AS_LPAREN]) and
+ is_calljmp(actopcode) then
+ begin
+ oper.opr.typ := OPR_SYMBOL;
+ oper.opr.symbol := hl;
+ end
+ else
+ begin
+ oper.InitRef;
+ oper.opr.ref.symbol := hl;
+ end;
+ end;
+
+ procedure MaybeRecordOffset;
+ var
+ mangledname : string;
+ hasdot: boolean;
+ l,
+ toffset,
+ tsize: aint;
+ begin
+ if not (actasmtoken in [AS_DOT, AS_PLUS, AS_MINUS]) then
+ exit;
+ l := 0;
+ hasdot := (actasmtoken = AS_DOT);
+ if hasdot then
+ begin
+ if expr <> '' then
+ begin
+ BuildRecordOffsetSize(expr, toffset, tsize, mangledname, false);
+ if (oper.opr.typ<>OPR_CONSTANT) and
+ (mangledname<>'') then
+ Message(asmr_e_wrong_sym_type);
+ inc(l, toffset);
+ oper.SetSize(tsize, true);
+ end;
+ end;
+ if actasmtoken in [AS_PLUS, AS_MINUS] then
+ inc(l, BuildConstExpression(true, false));
+ case oper.opr.typ of
+ OPR_LOCAL:
+ begin
+ { don't allow direct access to fields of parameters, because that
+ will generate buggy code. Allow it only for explicit typecasting }
+ if hasdot and
+ (not oper.hastype) and
+ (tabstractvarsym(oper.opr.localsym).owner.symtabletype =
+ parasymtable) and
+ (current_procinfo.procdef.proccalloption <> pocall_register) then
+ Message(asmr_e_cannot_access_field_directly_for_parameters);
+ inc(oper.opr.localsymofs, l)
+ end;
+ OPR_CONSTANT:
+ if (mangledname<>'') then
+ begin
+ if (oper.opr.val<>0) then
+ Message(asmr_e_wrong_sym_type);
+ oper.opr.typ:=OPR_SYMBOL;
+ oper.opr.symbol:=current_asmdata.RefAsmSymbol(mangledname);
+ end
+ else
+ inc(oper.opr.val,l);
+ OPR_REFERENCE:
+ inc(oper.opr.ref.offset, l);
+ OPR_SYMBOL:
+ Message(asmr_e_invalid_symbol_ref);
+ else
+ internalerror(200309221);
+ end;
+ end;
+
+ function MaybeBuildReference: boolean;
+ { Try to create a reference, if not a reference is found then false
+ is returned }
+ begin
+ MaybeBuildReference := true;
+ case actasmtoken of
+ AS_INTNUM,
+ AS_MINUS,
+ AS_PLUS:
+ begin
+ oper.opr.ref.offset := BuildConstExpression(True, False);
+ if actasmtoken <> AS_LPAREN then
+ Message(asmr_e_invalid_reference_syntax)
+ else
+ BuildReference(oper);
+ end;
+ AS_LPAREN:
+ BuildReference(oper);
+ AS_ID: { only a variable is allowed ... }
+ begin
+ ReadSym(oper);
+ case actasmtoken of
+ AS_END,
+ AS_SEPARATOR,
+ AS_COMMA: ;
+ AS_LPAREN:
+ BuildReference(oper);
+ else
+ begin
+ Message(asmr_e_invalid_reference_syntax);
+ Consume(actasmtoken);
+ end;
+ end; {end case }
+ end;
+ else
+ MaybeBuildReference := false;
+ end; { end case }
+ end;
+
+var
+ tempreg: tregister;
+ hl: tasmlabel;
+ ofs: aint;
+begin
+ expr := '';
+ case actasmtoken of
+ AS_LPAREN: { Memory reference or constant expression }
+ begin
+ oper.InitRef;
+ BuildReference(oper);
+ end;
+
+ AS_INTNUM,
+ AS_MINUS,
+ AS_PLUS:
+ begin
+ { Constant memory offset }
+ { This must absolutely be followed by ( }
+ oper.InitRef;
+ oper.opr.ref.offset := BuildConstExpression(True, False);
+ if actasmtoken <> AS_LPAREN then
+ begin
+ ofs := oper.opr.ref.offset;
+ BuildConstantOperand(oper);
+ inc(oper.opr.val, ofs);
+ end
+ else
+ BuildReference(oper);
+ end;
+
+ AS_ID: { A constant expression, or a Variable ref. }
+ begin
+ { Local Label ? }
+ if is_locallabel(actasmpattern) then
+ begin
+ CreateLocalLabel(actasmpattern, hl, false);
+ Consume(AS_ID);
+ AddLabelOperand(hl);
+ end
+ else
+ { Check for label } if SearchLabel(actasmpattern, hl, false) then
+ begin
+ Consume(AS_ID);
+ AddLabelOperand(hl);
+ end
+ else
+ { probably a variable or normal expression }
+ { or a procedure (such as in CALL ID) }
+ begin
+ { is it a constant ? }
+ if SearchIConstant(actasmpattern, l) then
+ begin
+ if not (oper.opr.typ in [OPR_NONE, OPR_CONSTANT]) then
+ Message(asmr_e_invalid_operand_type);
+ BuildConstantOperand(oper);
+ end
+ else
+ begin
+ expr := actasmpattern;
+ Consume(AS_ID);
+ { typecasting? }
+ if (actasmtoken = AS_LPAREN) and
+ SearchType(expr, typesize) then
+ begin
+ oper.hastype := true;
+ Consume(AS_LPAREN);
+ BuildOperand(oper);
+ Consume(AS_RPAREN);
+ if oper.opr.typ in [OPR_REFERENCE, OPR_LOCAL] then
+ oper.SetSize(typesize, true);
+ end
+ else
+ begin
+ if oper.SetupVar(expr, false) then
+ ReadAt(oper)
+ else
+ begin
+ { look for special symbols ... }
+ if expr = '__HIGH' then
+ begin
+ consume(AS_LPAREN);
+ if not oper.setupvar('high' + actasmpattern, false) then
+ Message1(sym_e_unknown_id, 'high' + actasmpattern);
+ consume(AS_ID);
+ consume(AS_RPAREN);
+ end
+ else if expr = '__RESULT' then
+ oper.SetUpResult
+ else if expr = '__SELF' then
+ oper.SetupSelf
+ else if expr = '__OLDEBP' then
+ oper.SetupOldEBP
+ else
+ Message1(sym_e_unknown_id, expr);
+ end;
+ end;
+ end;
+ if actasmtoken = AS_DOT then
+ MaybeRecordOffset;
+ { add a constant expression? }
+ if (actasmtoken = AS_PLUS) then
+ begin
+ l := BuildConstExpression(true, false);
+ case oper.opr.typ of
+ OPR_CONSTANT:
+ inc(oper.opr.val, l);
+ OPR_LOCAL:
+ inc(oper.opr.localsymofs, l);
+ OPR_REFERENCE:
+ inc(oper.opr.ref.offset, l);
+ else
+ internalerror(200309202);
+ end;
+ end
+ end;
+ { Do we have a indexing reference, then parse it also }
+ if actasmtoken = AS_LPAREN then
+ BuildReference(oper);
+ end;
+
+ AS_REGISTER: { Register, a variable reference or a constant reference }
+ begin
+ { save the type of register used. }
+ tempreg := actasmregister;
+ Consume(AS_REGISTER);
+ if (actasmtoken in [AS_END, AS_SEPARATOR, AS_COMMA]) then
+ if is_condreg(tempreg) and
+ ((actopcode = A_BC) or
+ (actopcode = A_BCCTR) or
+ (actopcode = A_BCLR) or
+ (actopcode = A_TW) or
+ (actopcode = A_TWI)) then
+ begin
+ { it isn't a real operand, everything is stored in the condition }
+ oper.opr.typ := OPR_NONE;
+ actcondition.cr := getsupreg(tempreg);
+ end
+ else
+ begin
+ if not (oper.opr.typ in [OPR_NONE, OPR_REGISTER]) then
+ Message(asmr_e_invalid_operand_type);
+ oper.opr.typ := OPR_REGISTER;
+ oper.opr.reg := tempreg;
+ end
+ else if is_condreg(tempreg) then
+ begin
+ if not (actcondition.cond in [C_T..C_DZF]) then
+ Message(asmr_e_syn_operand);
+ if actasmtoken = AS_STAR then
+ begin
+ consume(AS_STAR);
+ if (actasmtoken = AS_INTNUM) then
+ begin
+ consume(AS_INTNUM);
+ if actasmtoken = AS_PLUS then
+ begin
+ consume(AS_PLUS);
+ if (actasmtoken = AS_ID) then
+ begin
+ oper.opr.typ := OPR_NONE;
+ if actasmpattern = 'LT' then
+ actcondition.crbit := (getsupreg(tempreg) - (RS_CR0)) * 4
+ else if actasmpattern = 'GT' then
+ actcondition.crbit := (getsupreg(tempreg) - (RS_CR0)) * 4 + 1
+ else if actasmpattern = 'EQ' then
+ actcondition.crbit := (getsupreg(tempreg) - (RS_CR0)) * 4 + 2
+ else if actasmpattern = 'SO' then
+ actcondition.crbit := (getsupreg(tempreg) - (RS_CR0)) * 4 + 3
+ else
+ Message(asmr_e_syn_operand);
+ consume(AS_ID);
+ end
+ else
+ Message(asmr_e_syn_operand);
+ end
+ else
+ Message(asmr_e_syn_operand);
+ end
+ else
+ Message(asmr_e_syn_operand);
+ end
+ else
+ Message(asmr_e_syn_operand);
+ end
+ else
+ Message(asmr_e_syn_operand);
+ end;
+ AS_END,
+ AS_SEPARATOR,
+ AS_COMMA: ;
+ else
+ begin
+ Message(asmr_e_syn_operand);
+ Consume(actasmtoken);
+ end;
+ end; { end case }
+end;
+
+{*****************************************************************************
+ tppcattreader
+*****************************************************************************}
+
+procedure tppcattreader.BuildOpCode(instr: tppcinstruction);
+var
+ operandnum: longint;
+begin
+ { opcode }
+ if (actasmtoken <> AS_OPCODE) then
+ begin
+ Message(asmr_e_invalid_or_missing_opcode);
+ RecoverConsume(true);
+ exit;
+ end;
+ { Fill the instr object with the current state }
+ with instr do
+ begin
+ Opcode := ActOpcode;
+ condition := ActCondition;
+ end;
+
+ { We are reading operands, so opcode will be an AS_ID }
+ operandnum := 1;
+ Consume(AS_OPCODE);
+ { Zero operand opcode ? }
+ if actasmtoken in [AS_SEPARATOR, AS_END] then
+ begin
+ operandnum := 0;
+ exit;
+ end;
+ { Read the operands }
+ repeat
+ case actasmtoken of
+ AS_COMMA: { Operand delimiter }
+ begin
+ if operandnum > Max_Operands then
+ Message(asmr_e_too_many_operands)
+ else
+ begin
+ { condition operands doesn't set the operand but write to the
+ condition field of the instruction
+ }
+ if instr.Operands[operandnum].opr.typ <> OPR_NONE then
+ Inc(operandnum);
+ end;
+ Consume(AS_COMMA);
+ end;
+ AS_SEPARATOR,
+ AS_END: { End of asm operands for this opcode }
+ begin
+ break;
+ end;
+ else
+ BuildOperand(instr.Operands[operandnum] as tppcoperand);
+ end; { end case }
+ until false;
+ if (operandnum = 1) and (instr.Operands[operandnum].opr.typ = OPR_NONE) then
+ dec(operandnum);
+ instr.Ops := operandnum;
+end;
+
+function tppcattreader.is_asmopcode(const s: string): boolean;
+var
+ cond: tasmcondflag;
+ hs: string;
+
+begin
+ { making s a value parameter would break other assembler readers }
+ hs := s;
+ is_asmopcode := false;
+
+ { clear op code }
+ actopcode := A_None;
+ { clear condition }
+ fillchar(actcondition, sizeof(actcondition), 0);
+
+ { check for direction hint }
+ if hs[length(s)] = '-' then
+ begin
+ dec(ord(hs[0]));
+ actcondition.dirhint := DH_Minus;
+ end
+ else if hs[length(s)] = '+' then
+ begin
+ dec(ord(hs[0]));
+ actcondition.dirhint := DH_Plus;
+ end;
+ actopcode := tasmop(ptruint(iasmops.Find(hs)));
+ if actopcode <> A_NONE then
+ begin
+ if actcondition.dirhint <> DH_None then
+ message1(asmr_e_unknown_opcode, actasmpattern);
+ actasmtoken := AS_OPCODE;
+ is_asmopcode := true;
+ exit;
+ end;
+ { not found, check branch instructions }
+ if hs[1] = 'B' then
+ begin
+ { we can search here without an extra table which is sorted by string length
+ because we take the whole remaining string without the leading B }
+ if copy(hs, length(s) - 1, 2) = 'LR' then
+ begin
+ actopcode := A_BCLR;
+ setlength(hs, length(hs) - 2)
+ end
+ else if copy(hs, length(s) - 2, 3) = 'CTR' then
+ begin
+ actopcode := A_BCCTR;
+ setlength(hs, length(hs) - 3)
+ end
+ else
+ actopcode := A_BC;
+ for cond := low(TAsmCondFlag) to high(TAsmCondFlag) do
+ if copy(hs, 2, length(s) - 1) = UpperAsmCondFlag2Str[cond] then
+ begin
+ actcondition.simple := true;
+ actcondition.cond := cond;
+ if (cond in [C_LT, C_LE, C_EQ, C_GE, C_GT, C_NL, C_NE, C_NG, C_SO, C_NS,
+ C_UN, C_NU]) then
+ actcondition.cr := RS_CR0;
+ actasmtoken := AS_OPCODE;
+ is_asmopcode := true;
+ exit;
+ end;
+ end;
+end;
+
+procedure tppcattreader.ConvertCalljmp(instr: tppcinstruction);
+begin
+ if instr.Operands[1].opr.typ = OPR_CONSTANT then begin
+ if (instr.operands[1].opr.val > 31) or
+ (instr.operands[2].opr.typ <> OPR_CONSTANT) or
+ (instr.operands[2].opr.val > 31) or
+ not(instr.operands[3].opr.typ in [OPR_REFERENCE,OPR_SYMBOL]) then
+ Message(asmr_e_syn_operand);
+ { BO/BI notation }
+ instr.condition.simple := false;
+ instr.condition.bo := instr.operands[1].opr.val;
+ instr.condition.bi := instr.operands[2].opr.val;
+ instr.operands[1].free;
+ instr.operands[2].free;
+ instr.operands[2] := nil;
+ instr.operands[1] := instr.operands[3];
+ instr.operands[3] := nil;
+ instr.ops := 1;
+ end;
+ if instr.Operands[1].opr.typ = OPR_REFERENCE then begin
+ instr.Operands[1].opr.ref.refaddr:=addr_full;
+ if (instr.Operands[1].opr.ref.base<>NR_NO) or
+ (instr.Operands[1].opr.ref.index<>NR_NO) then
+ Message(asmr_e_syn_operand);
+ end;
+end;
+
+procedure tppcattreader.handleopcode;
+var
+ instr: tppcinstruction;
+begin
+ instr := TPPCInstruction.Create(TPPCOperand);
+ BuildOpcode(instr);
+ instr.condition := actcondition;
+ if is_calljmp(instr.opcode) then
+ ConvertCalljmp(instr);
+ {
+ instr.AddReferenceSizes;
+ instr.SetInstructionOpsize;
+ instr.CheckOperandSizes;
+ }
+ instr.ConcatInstruction(curlist);
+ instr.Free;
+end;
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+const
+ asmmode_ppc_att_info: tasmmodeinfo =
+ (
+ id: asmmode_ppc_gas;
+ idtxt: 'GAS';
+ casmreader: tppcattreader;
+ );
+
+ asmmode_ppc_standard_info: tasmmodeinfo =
+ (
+ id: asmmode_standard;
+ idtxt: 'STANDARD';
+ casmreader: tppcattreader;
+ );
+
+initialization
+ RegisterAsmMode(asmmode_ppc_att_info);
+ RegisterAsmMode(asmmode_ppc_standard_info);
+end.
+
diff --git a/closures/compiler/powerpc64/rppccon.inc b/closures/compiler/powerpc64/rppccon.inc
new file mode 100644
index 0000000000..4ff6799228
--- /dev/null
+++ b/closures/compiler/powerpc64/rppccon.inc
@@ -0,0 +1,111 @@
+{ don't edit, this file is generated from ppcreg.dat }
+NR_NO = tregister($00000000);
+NR_R0 = tregister($01000000);
+NR_R1 = tregister($01000001);
+NR_R2 = tregister($01000002);
+NR_R3 = tregister($01000003);
+NR_R4 = tregister($01000004);
+NR_R5 = tregister($01000005);
+NR_R6 = tregister($01000006);
+NR_R7 = tregister($01000007);
+NR_R8 = tregister($01000008);
+NR_R9 = tregister($01000009);
+NR_R10 = tregister($0100000a);
+NR_R11 = tregister($0100000b);
+NR_R12 = tregister($0100000c);
+NR_R13 = tregister($0100000d);
+NR_R14 = tregister($0100000e);
+NR_R15 = tregister($0100000f);
+NR_R16 = tregister($01000010);
+NR_R17 = tregister($01000011);
+NR_R18 = tregister($01000012);
+NR_R19 = tregister($01000013);
+NR_R20 = tregister($01000014);
+NR_R21 = tregister($01000015);
+NR_R22 = tregister($01000016);
+NR_R23 = tregister($01000017);
+NR_R24 = tregister($01000018);
+NR_R25 = tregister($01000019);
+NR_R26 = tregister($0100001a);
+NR_R27 = tregister($0100001b);
+NR_R28 = tregister($0100001c);
+NR_R29 = tregister($0100001d);
+NR_R30 = tregister($0100001e);
+NR_R31 = tregister($0100001f);
+NR_F0 = tregister($02000000);
+NR_F1 = tregister($02000001);
+NR_F2 = tregister($02000002);
+NR_F3 = tregister($02000003);
+NR_F4 = tregister($02000004);
+NR_F5 = tregister($02000005);
+NR_F6 = tregister($02000006);
+NR_F7 = tregister($02000007);
+NR_F8 = tregister($02000008);
+NR_F9 = tregister($02000009);
+NR_F10 = tregister($0200000a);
+NR_F11 = tregister($0200000b);
+NR_F12 = tregister($0200000c);
+NR_F13 = tregister($0200000d);
+NR_F14 = tregister($0200000e);
+NR_F15 = tregister($0200000f);
+NR_F16 = tregister($02000010);
+NR_F17 = tregister($02000011);
+NR_F18 = tregister($02000012);
+NR_F19 = tregister($02000013);
+NR_F20 = tregister($02000014);
+NR_F21 = tregister($02000015);
+NR_F22 = tregister($02000016);
+NR_F23 = tregister($02000017);
+NR_F24 = tregister($02000018);
+NR_F25 = tregister($02000019);
+NR_F26 = tregister($0200001a);
+NR_F27 = tregister($0200001b);
+NR_F28 = tregister($0200001c);
+NR_F29 = tregister($0200001d);
+NR_F30 = tregister($0200001e);
+NR_F31 = tregister($0200001f);
+NR_M0 = tregister($03000000);
+NR_M1 = tregister($03000001);
+NR_M2 = tregister($03000002);
+NR_M3 = tregister($03000003);
+NR_M4 = tregister($03000004);
+NR_M5 = tregister($03000005);
+NR_M6 = tregister($03000006);
+NR_M7 = tregister($03000007);
+NR_M8 = tregister($03000008);
+NR_M9 = tregister($03000009);
+NR_M10 = tregister($0300000a);
+NR_M11 = tregister($0300000b);
+NR_M12 = tregister($0300000c);
+NR_M13 = tregister($0300000d);
+NR_M14 = tregister($0300000e);
+NR_M15 = tregister($0300000f);
+NR_M16 = tregister($03000010);
+NR_M17 = tregister($03000011);
+NR_M18 = tregister($03000012);
+NR_M19 = tregister($03000013);
+NR_M20 = tregister($03000014);
+NR_M21 = tregister($03000015);
+NR_M22 = tregister($03000016);
+NR_M23 = tregister($03000017);
+NR_M24 = tregister($03000018);
+NR_M25 = tregister($03000019);
+NR_M26 = tregister($0300001a);
+NR_M27 = tregister($0300001b);
+NR_M28 = tregister($0300001c);
+NR_M29 = tregister($0300001d);
+NR_M30 = tregister($0300001e);
+NR_M31 = tregister($0300001f);
+NR_CR = tregister($05000000);
+NR_CR0 = tregister($05000001);
+NR_CR1 = tregister($05000002);
+NR_CR2 = tregister($05000003);
+NR_CR3 = tregister($05000004);
+NR_CR4 = tregister($05000005);
+NR_CR5 = tregister($05000006);
+NR_CR6 = tregister($05000007);
+NR_CR7 = tregister($05000008);
+NR_XER = tregister($05000009);
+NR_LR = tregister($0500000a);
+NR_CTR = tregister($0500000b);
+NR_FPSCR = tregister($0500000c);
diff --git a/closures/compiler/powerpc64/rppcdwrf.inc b/closures/compiler/powerpc64/rppcdwrf.inc
new file mode 100644
index 0000000000..2c9c9942a8
--- /dev/null
+++ b/closures/compiler/powerpc64/rppcdwrf.inc
@@ -0,0 +1,111 @@
+{ don't edit, this file is generated from ppcreg.dat }
+-1,
+0,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+8,
+9,
+10,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+20,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+31,
+32,
+33,
+34,
+35,
+36,
+37,
+38,
+39,
+40,
+41,
+42,
+43,
+44,
+45,
+46,
+47,
+48,
+49,
+50,
+51,
+52,
+53,
+54,
+55,
+56,
+57,
+58,
+59,
+60,
+61,
+62,
+63,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+68,
+69,
+70,
+71,
+72,
+73,
+74,
+75,
+76,
+65,
+66,
+-1
diff --git a/closures/compiler/powerpc64/rppcgas.inc b/closures/compiler/powerpc64/rppcgas.inc
new file mode 100644
index 0000000000..3c68549ce1
--- /dev/null
+++ b/closures/compiler/powerpc64/rppcgas.inc
@@ -0,0 +1,111 @@
+{ don't edit, this file is generated from ppcreg.dat }
+'INVALID',
+'r0',
+'r1',
+'r2',
+'r3',
+'r4',
+'r5',
+'r6',
+'r7',
+'r8',
+'r9',
+'r10',
+'r11',
+'r12',
+'r13',
+'r14',
+'r15',
+'r16',
+'r17',
+'r18',
+'r19',
+'r20',
+'r21',
+'r22',
+'r23',
+'r24',
+'r25',
+'r26',
+'r27',
+'r28',
+'r29',
+'r30',
+'r31',
+'f0',
+'f1',
+'f2',
+'f3',
+'f4',
+'f5',
+'f6',
+'f7',
+'f8',
+'f9',
+'f10',
+'f11',
+'f12',
+'f13',
+'f14',
+'f15',
+'f16',
+'f17',
+'f18',
+'f19',
+'f20',
+'f21',
+'f22',
+'f23',
+'f24',
+'f25',
+'f26',
+'f27',
+'f28',
+'f29',
+'f30',
+'f31',
+'v0',
+'v1',
+'v2',
+'v3',
+'v4',
+'v5',
+'v6',
+'v7',
+'v8',
+'v9',
+'v10',
+'v11',
+'v12',
+'v13',
+'v14',
+'v15',
+'v16',
+'v17',
+'v18',
+'v19',
+'v20',
+'v21',
+'v22',
+'v23',
+'v24',
+'v25',
+'v26',
+'v27',
+'v28',
+'v29',
+'v30',
+'v31',
+'cr',
+'cr0',
+'cr1',
+'cr2',
+'cr3',
+'cr4',
+'cr5',
+'cr6',
+'cr7',
+'xer',
+'lr',
+'ctr',
+'fpscr'
diff --git a/closures/compiler/powerpc64/rppcgri.inc b/closures/compiler/powerpc64/rppcgri.inc
new file mode 100644
index 0000000000..b26f900caa
--- /dev/null
+++ b/closures/compiler/powerpc64/rppcgri.inc
@@ -0,0 +1,111 @@
+{ don't edit, this file is generated from ppcreg.dat }
+0,
+97,
+98,
+99,
+100,
+101,
+102,
+103,
+104,
+105,
+108,
+33,
+34,
+43,
+44,
+45,
+46,
+47,
+48,
+49,
+50,
+51,
+52,
+35,
+53,
+54,
+55,
+56,
+57,
+58,
+59,
+60,
+61,
+62,
+36,
+63,
+64,
+37,
+38,
+39,
+40,
+41,
+42,
+109,
+107,
+1,
+2,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+20,
+3,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+4,
+31,
+32,
+5,
+6,
+7,
+8,
+9,
+10,
+65,
+66,
+75,
+76,
+77,
+78,
+79,
+80,
+81,
+82,
+83,
+84,
+67,
+85,
+86,
+87,
+88,
+89,
+90,
+91,
+92,
+93,
+94,
+68,
+95,
+96,
+69,
+70,
+71,
+72,
+73,
+74,
+106
diff --git a/closures/compiler/powerpc64/rppcgss.inc b/closures/compiler/powerpc64/rppcgss.inc
new file mode 100644
index 0000000000..5d5aa809d8
--- /dev/null
+++ b/closures/compiler/powerpc64/rppcgss.inc
@@ -0,0 +1,111 @@
+{ don't edit, this file is generated from ppcreg.dat }
+'INVALID',
+'0',
+'1',
+'2',
+'3',
+'4',
+'5',
+'6',
+'7',
+'8',
+'9',
+'10',
+'11',
+'12',
+'13',
+'14',
+'15',
+'16',
+'17',
+'18',
+'19',
+'20',
+'21',
+'22',
+'23',
+'24',
+'25',
+'26',
+'27',
+'28',
+'29',
+'30',
+'31',
+'0',
+'1',
+'2',
+'3',
+'4',
+'5',
+'6',
+'7',
+'8',
+'9',
+'10',
+'11',
+'12',
+'13',
+'14',
+'15',
+'16',
+'17',
+'18',
+'19',
+'20',
+'21',
+'22',
+'23',
+'24',
+'25',
+'26',
+'27',
+'28',
+'29',
+'30',
+'31',
+'0',
+'1',
+'2',
+'3',
+'4',
+'5',
+'6',
+'7',
+'8',
+'9',
+'10',
+'11',
+'12',
+'13',
+'14',
+'15',
+'16',
+'17',
+'18',
+'19',
+'20',
+'21',
+'22',
+'23',
+'24',
+'25',
+'26',
+'27',
+'28',
+'29',
+'30',
+'31',
+'cr',
+'cr0',
+'cr1',
+'cr2',
+'cr3',
+'cr4',
+'cr5',
+'cr6',
+'cr7',
+'xer',
+'lr',
+'ctr',
+'fpscr'
diff --git a/closures/compiler/powerpc64/rppcmot.inc b/closures/compiler/powerpc64/rppcmot.inc
new file mode 100644
index 0000000000..4fc340afd7
--- /dev/null
+++ b/closures/compiler/powerpc64/rppcmot.inc
@@ -0,0 +1,111 @@
+{ don't edit, this file is generated from ppcreg.dat }
+'INVALID',
+'r0',
+'r1',
+'r2',
+'r3',
+'r4',
+'r5',
+'r6',
+'r7',
+'r8',
+'r9',
+'r10',
+'r11',
+'r12',
+'r13',
+'r14',
+'r15',
+'r16',
+'r17',
+'r18',
+'r19',
+'r20',
+'r21',
+'r22',
+'r23',
+'r24',
+'r25',
+'r26',
+'r27',
+'r28',
+'r29',
+'r30',
+'r31',
+'F0',
+'F1',
+'F2',
+'F3',
+'F4',
+'F5',
+'F6',
+'F7',
+'F8',
+'F9',
+'F10',
+'F11',
+'F12',
+'F13',
+'F14',
+'F15',
+'F16',
+'F17',
+'F18',
+'F19',
+'F20',
+'F21',
+'F22',
+'F23',
+'F24',
+'F25',
+'F26',
+'F27',
+'F28',
+'F29',
+'F30',
+'F31',
+'M0',
+'M1',
+'M2',
+'M3',
+'M4',
+'M5',
+'M6',
+'M7',
+'M8',
+'M9',
+'M10',
+'M11',
+'M12',
+'M13',
+'M14',
+'M15',
+'M16',
+'M17',
+'M18',
+'M19',
+'M20',
+'M21',
+'M22',
+'M23',
+'M24',
+'M25',
+'M26',
+'M27',
+'M28',
+'M29',
+'M30',
+'M31',
+'CR',
+'CR0',
+'CR1',
+'CR2',
+'CR3',
+'CR4',
+'CR5',
+'CR6',
+'CR7',
+'XER',
+'LR',
+'CTR',
+'FPSCR'
diff --git a/closures/compiler/powerpc64/rppcmri.inc b/closures/compiler/powerpc64/rppcmri.inc
new file mode 100644
index 0000000000..9a59178c7d
--- /dev/null
+++ b/closures/compiler/powerpc64/rppcmri.inc
@@ -0,0 +1,111 @@
+{ don't edit, this file is generated from ppcreg.dat }
+97,
+98,
+99,
+100,
+101,
+102,
+103,
+104,
+105,
+108,
+33,
+34,
+43,
+44,
+45,
+46,
+47,
+48,
+49,
+50,
+51,
+52,
+35,
+53,
+54,
+55,
+56,
+57,
+58,
+59,
+60,
+61,
+62,
+36,
+63,
+64,
+37,
+38,
+39,
+40,
+41,
+42,
+109,
+0,
+107,
+65,
+66,
+75,
+76,
+77,
+78,
+79,
+80,
+81,
+82,
+83,
+84,
+67,
+85,
+86,
+87,
+88,
+89,
+90,
+91,
+92,
+93,
+94,
+68,
+95,
+96,
+69,
+70,
+71,
+72,
+73,
+74,
+106,
+1,
+2,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+20,
+3,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+4,
+31,
+32,
+5,
+6,
+7,
+8,
+9,
+10
diff --git a/closures/compiler/powerpc64/rppcnor.inc b/closures/compiler/powerpc64/rppcnor.inc
new file mode 100644
index 0000000000..387be62acb
--- /dev/null
+++ b/closures/compiler/powerpc64/rppcnor.inc
@@ -0,0 +1,2 @@
+{ don't edit, this file is generated from ppcreg.dat }
+110
diff --git a/closures/compiler/powerpc64/rppcnum.inc b/closures/compiler/powerpc64/rppcnum.inc
new file mode 100644
index 0000000000..d612e34d8a
--- /dev/null
+++ b/closures/compiler/powerpc64/rppcnum.inc
@@ -0,0 +1,111 @@
+{ don't edit, this file is generated from ppcreg.dat }
+tregister($00000000),
+tregister($01000000),
+tregister($01000001),
+tregister($01000002),
+tregister($01000003),
+tregister($01000004),
+tregister($01000005),
+tregister($01000006),
+tregister($01000007),
+tregister($01000008),
+tregister($01000009),
+tregister($0100000a),
+tregister($0100000b),
+tregister($0100000c),
+tregister($0100000d),
+tregister($0100000e),
+tregister($0100000f),
+tregister($01000010),
+tregister($01000011),
+tregister($01000012),
+tregister($01000013),
+tregister($01000014),
+tregister($01000015),
+tregister($01000016),
+tregister($01000017),
+tregister($01000018),
+tregister($01000019),
+tregister($0100001a),
+tregister($0100001b),
+tregister($0100001c),
+tregister($0100001d),
+tregister($0100001e),
+tregister($0100001f),
+tregister($02000000),
+tregister($02000001),
+tregister($02000002),
+tregister($02000003),
+tregister($02000004),
+tregister($02000005),
+tregister($02000006),
+tregister($02000007),
+tregister($02000008),
+tregister($02000009),
+tregister($0200000a),
+tregister($0200000b),
+tregister($0200000c),
+tregister($0200000d),
+tregister($0200000e),
+tregister($0200000f),
+tregister($02000010),
+tregister($02000011),
+tregister($02000012),
+tregister($02000013),
+tregister($02000014),
+tregister($02000015),
+tregister($02000016),
+tregister($02000017),
+tregister($02000018),
+tregister($02000019),
+tregister($0200001a),
+tregister($0200001b),
+tregister($0200001c),
+tregister($0200001d),
+tregister($0200001e),
+tregister($0200001f),
+tregister($03000000),
+tregister($03000001),
+tregister($03000002),
+tregister($03000003),
+tregister($03000004),
+tregister($03000005),
+tregister($03000006),
+tregister($03000007),
+tregister($03000008),
+tregister($03000009),
+tregister($0300000a),
+tregister($0300000b),
+tregister($0300000c),
+tregister($0300000d),
+tregister($0300000e),
+tregister($0300000f),
+tregister($03000010),
+tregister($03000011),
+tregister($03000012),
+tregister($03000013),
+tregister($03000014),
+tregister($03000015),
+tregister($03000016),
+tregister($03000017),
+tregister($03000018),
+tregister($03000019),
+tregister($0300001a),
+tregister($0300001b),
+tregister($0300001c),
+tregister($0300001d),
+tregister($0300001e),
+tregister($0300001f),
+tregister($05000000),
+tregister($05000001),
+tregister($05000002),
+tregister($05000003),
+tregister($05000004),
+tregister($05000005),
+tregister($05000006),
+tregister($05000007),
+tregister($05000008),
+tregister($05000009),
+tregister($0500000a),
+tregister($0500000b),
+tregister($0500000c)
diff --git a/closures/compiler/powerpc64/rppcrni.inc b/closures/compiler/powerpc64/rppcrni.inc
new file mode 100644
index 0000000000..1a49189c1d
--- /dev/null
+++ b/closures/compiler/powerpc64/rppcrni.inc
@@ -0,0 +1,111 @@
+{ don't edit, this file is generated from ppcreg.dat }
+0,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+8,
+9,
+10,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+20,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+31,
+32,
+33,
+34,
+35,
+36,
+37,
+38,
+39,
+40,
+41,
+42,
+43,
+44,
+45,
+46,
+47,
+48,
+49,
+50,
+51,
+52,
+53,
+54,
+55,
+56,
+57,
+58,
+59,
+60,
+61,
+62,
+63,
+64,
+65,
+66,
+67,
+68,
+69,
+70,
+71,
+72,
+73,
+74,
+75,
+76,
+77,
+78,
+79,
+80,
+81,
+82,
+83,
+84,
+85,
+86,
+87,
+88,
+89,
+90,
+91,
+92,
+93,
+94,
+95,
+96,
+97,
+98,
+99,
+100,
+101,
+102,
+103,
+104,
+105,
+106,
+107,
+108,
+109
diff --git a/closures/compiler/powerpc64/rppcsri.inc b/closures/compiler/powerpc64/rppcsri.inc
new file mode 100644
index 0000000000..9a59178c7d
--- /dev/null
+++ b/closures/compiler/powerpc64/rppcsri.inc
@@ -0,0 +1,111 @@
+{ don't edit, this file is generated from ppcreg.dat }
+97,
+98,
+99,
+100,
+101,
+102,
+103,
+104,
+105,
+108,
+33,
+34,
+43,
+44,
+45,
+46,
+47,
+48,
+49,
+50,
+51,
+52,
+35,
+53,
+54,
+55,
+56,
+57,
+58,
+59,
+60,
+61,
+62,
+36,
+63,
+64,
+37,
+38,
+39,
+40,
+41,
+42,
+109,
+0,
+107,
+65,
+66,
+75,
+76,
+77,
+78,
+79,
+80,
+81,
+82,
+83,
+84,
+67,
+85,
+86,
+87,
+88,
+89,
+90,
+91,
+92,
+93,
+94,
+68,
+95,
+96,
+69,
+70,
+71,
+72,
+73,
+74,
+106,
+1,
+2,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+20,
+3,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+4,
+31,
+32,
+5,
+6,
+7,
+8,
+9,
+10
diff --git a/closures/compiler/powerpc64/rppcstab.inc b/closures/compiler/powerpc64/rppcstab.inc
new file mode 100644
index 0000000000..2c9c9942a8
--- /dev/null
+++ b/closures/compiler/powerpc64/rppcstab.inc
@@ -0,0 +1,111 @@
+{ don't edit, this file is generated from ppcreg.dat }
+-1,
+0,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+8,
+9,
+10,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+20,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+31,
+32,
+33,
+34,
+35,
+36,
+37,
+38,
+39,
+40,
+41,
+42,
+43,
+44,
+45,
+46,
+47,
+48,
+49,
+50,
+51,
+52,
+53,
+54,
+55,
+56,
+57,
+58,
+59,
+60,
+61,
+62,
+63,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+68,
+69,
+70,
+71,
+72,
+73,
+74,
+75,
+76,
+65,
+66,
+-1
diff --git a/closures/compiler/powerpc64/rppcstd.inc b/closures/compiler/powerpc64/rppcstd.inc
new file mode 100644
index 0000000000..4fc340afd7
--- /dev/null
+++ b/closures/compiler/powerpc64/rppcstd.inc
@@ -0,0 +1,111 @@
+{ don't edit, this file is generated from ppcreg.dat }
+'INVALID',
+'r0',
+'r1',
+'r2',
+'r3',
+'r4',
+'r5',
+'r6',
+'r7',
+'r8',
+'r9',
+'r10',
+'r11',
+'r12',
+'r13',
+'r14',
+'r15',
+'r16',
+'r17',
+'r18',
+'r19',
+'r20',
+'r21',
+'r22',
+'r23',
+'r24',
+'r25',
+'r26',
+'r27',
+'r28',
+'r29',
+'r30',
+'r31',
+'F0',
+'F1',
+'F2',
+'F3',
+'F4',
+'F5',
+'F6',
+'F7',
+'F8',
+'F9',
+'F10',
+'F11',
+'F12',
+'F13',
+'F14',
+'F15',
+'F16',
+'F17',
+'F18',
+'F19',
+'F20',
+'F21',
+'F22',
+'F23',
+'F24',
+'F25',
+'F26',
+'F27',
+'F28',
+'F29',
+'F30',
+'F31',
+'M0',
+'M1',
+'M2',
+'M3',
+'M4',
+'M5',
+'M6',
+'M7',
+'M8',
+'M9',
+'M10',
+'M11',
+'M12',
+'M13',
+'M14',
+'M15',
+'M16',
+'M17',
+'M18',
+'M19',
+'M20',
+'M21',
+'M22',
+'M23',
+'M24',
+'M25',
+'M26',
+'M27',
+'M28',
+'M29',
+'M30',
+'M31',
+'CR',
+'CR0',
+'CR1',
+'CR2',
+'CR3',
+'CR4',
+'CR5',
+'CR6',
+'CR7',
+'XER',
+'LR',
+'CTR',
+'FPSCR'
diff --git a/closures/compiler/powerpc64/rppcsup.inc b/closures/compiler/powerpc64/rppcsup.inc
new file mode 100644
index 0000000000..4e6f879355
--- /dev/null
+++ b/closures/compiler/powerpc64/rppcsup.inc
@@ -0,0 +1,111 @@
+{ don't edit, this file is generated from ppcreg.dat }
+RS_NO = $00;
+RS_R0 = $00;
+RS_R1 = $01;
+RS_R2 = $02;
+RS_R3 = $03;
+RS_R4 = $04;
+RS_R5 = $05;
+RS_R6 = $06;
+RS_R7 = $07;
+RS_R8 = $08;
+RS_R9 = $09;
+RS_R10 = $0a;
+RS_R11 = $0b;
+RS_R12 = $0c;
+RS_R13 = $0d;
+RS_R14 = $0e;
+RS_R15 = $0f;
+RS_R16 = $10;
+RS_R17 = $11;
+RS_R18 = $12;
+RS_R19 = $13;
+RS_R20 = $14;
+RS_R21 = $15;
+RS_R22 = $16;
+RS_R23 = $17;
+RS_R24 = $18;
+RS_R25 = $19;
+RS_R26 = $1a;
+RS_R27 = $1b;
+RS_R28 = $1c;
+RS_R29 = $1d;
+RS_R30 = $1e;
+RS_R31 = $1f;
+RS_F0 = $00;
+RS_F1 = $01;
+RS_F2 = $02;
+RS_F3 = $03;
+RS_F4 = $04;
+RS_F5 = $05;
+RS_F6 = $06;
+RS_F7 = $07;
+RS_F8 = $08;
+RS_F9 = $09;
+RS_F10 = $0a;
+RS_F11 = $0b;
+RS_F12 = $0c;
+RS_F13 = $0d;
+RS_F14 = $0e;
+RS_F15 = $0f;
+RS_F16 = $10;
+RS_F17 = $11;
+RS_F18 = $12;
+RS_F19 = $13;
+RS_F20 = $14;
+RS_F21 = $15;
+RS_F22 = $16;
+RS_F23 = $17;
+RS_F24 = $18;
+RS_F25 = $19;
+RS_F26 = $1a;
+RS_F27 = $1b;
+RS_F28 = $1c;
+RS_F29 = $1d;
+RS_F30 = $1e;
+RS_F31 = $1f;
+RS_M0 = $00;
+RS_M1 = $01;
+RS_M2 = $02;
+RS_M3 = $03;
+RS_M4 = $04;
+RS_M5 = $05;
+RS_M6 = $06;
+RS_M7 = $07;
+RS_M8 = $08;
+RS_M9 = $09;
+RS_M10 = $0a;
+RS_M11 = $0b;
+RS_M12 = $0c;
+RS_M13 = $0d;
+RS_M14 = $0e;
+RS_M15 = $0f;
+RS_M16 = $10;
+RS_M17 = $11;
+RS_M18 = $12;
+RS_M19 = $13;
+RS_M20 = $14;
+RS_M21 = $15;
+RS_M22 = $16;
+RS_M23 = $17;
+RS_M24 = $18;
+RS_M25 = $19;
+RS_M26 = $1a;
+RS_M27 = $1b;
+RS_M28 = $1c;
+RS_M29 = $1d;
+RS_M30 = $1e;
+RS_M31 = $1f;
+RS_CR = $00;
+RS_CR0 = $01;
+RS_CR1 = $02;
+RS_CR2 = $03;
+RS_CR3 = $04;
+RS_CR4 = $05;
+RS_CR5 = $06;
+RS_CR6 = $07;
+RS_CR7 = $08;
+RS_XER = $09;
+RS_LR = $0a;
+RS_CTR = $0b;
+RS_FPSCR = $0c;
diff --git a/closures/compiler/pp.lpi b/closures/compiler/pp.lpi
new file mode 100644
index 0000000000..8485cb2a9b
--- /dev/null
+++ b/closures/compiler/pp.lpi
@@ -0,0 +1,86 @@
+<?xml version="1.0"?>
+<CONFIG>
+ <ProjectOptions>
+ <Version Value="9"/>
+ <PathDelim Value="\"/>
+ <General>
+ <Flags>
+ <MainUnitHasUsesSectionForAllUnits Value="False"/>
+ <MainUnitHasCreateFormStatements Value="False"/>
+ <MainUnitHasTitleStatement Value="False"/>
+ <LRSInOutputDirectory Value="False"/>
+ </Flags>
+ <SessionStorage Value="InProjectDir"/>
+ <MainUnit Value="0"/>
+ <Title Value="pp"/>
+ </General>
+ <BuildModes Count="1">
+ <Item1 Name="default" Default="True"/>
+ </BuildModes>
+ <PublishOptions>
+ <Version Value="2"/>
+ <IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
+ <ExcludeFileFilter Value="*.(bak|ppu|ppw|o|so);*~;backup"/>
+ </PublishOptions>
+ <RunParams>
+ <local>
+ <FormatVersion Value="1"/>
+ <CommandLineParams Value="-MObjFPC -Scgi -O1 -gl -vewnhi -l -FiD:\programming\laz_svn\fpc_features\cpstr\lib\i386-win32\ -FuD:\programming\laz_svn\cpstr\cpstrnew\ -Fu. -FUD:\programming\laz_svn\fpc_features\cpstr\lib\i386-win32\ -oproject1.exe D:\programming\laz_svn\fpc_features\cpstr\project1.lpr"/>
+ <LaunchingApplication PathPlusParams="\usr\bin\xterm -T 'Lazarus Run Output' -e $(LazarusDir)\tools\runwait.sh $(TargetCmdLine)"/>
+ </local>
+ </RunParams>
+ <Units Count="2">
+ <Unit0>
+ <Filename Value="pp.pas"/>
+ <IsPartOfProject Value="True"/>
+ <UnitName Value="pp"/>
+ </Unit0>
+ <Unit1>
+ <Filename Value="x86\aasmcpu.pas"/>
+ <IsPartOfProject Value="True"/>
+ <UnitName Value="aasmcpu"/>
+ </Unit1>
+ </Units>
+ </ProjectOptions>
+ <CompilerOptions>
+ <Version Value="10"/>
+ <PathDelim Value="\"/>
+ <Target>
+ <Filename Value="i386\pp"/>
+ </Target>
+ <SearchPaths>
+ <IncludeFiles Value="i386"/>
+ <OtherUnitFiles Value="i386;x86;systems"/>
+ <UnitOutputDirectory Value="i386\lazbuild"/>
+ </SearchPaths>
+ <Parsing>
+ <SyntaxOptions>
+ <CStyleOperator Value="False"/>
+ <AllowLabel Value="False"/>
+ <CPPInline Value="False"/>
+ <UseAnsiStrings Value="False"/>
+ </SyntaxOptions>
+ </Parsing>
+ <Linking>
+ <Debugging>
+ <GenerateDebugInfo Value="True"/>
+ <DebugInfoType Value="dsStabs"/>
+ </Debugging>
+ </Linking>
+ <Other>
+ <Verbosity>
+ <ShowWarn Value="False"/>
+ <ShowNotes Value="False"/>
+ <ShowHints Value="False"/>
+ </Verbosity>
+ <ConfigFile>
+ <StopAfterErrCount Value="50"/>
+ </ConfigFile>
+ <CompilerMessages>
+ <UseMsgFile Value="True"/>
+ </CompilerMessages>
+ <CustomOptions Value="-di386"/>
+ <CompilerPath Value="$(CompPath)"/>
+ </Other>
+ </CompilerOptions>
+</CONFIG>
diff --git a/closures/compiler/pp.pas b/closures/compiler/pp.pas
new file mode 100644
index 0000000000..e3f613f726
--- /dev/null
+++ b/closures/compiler/pp.pas
@@ -0,0 +1,229 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Commandline compiler for Free Pascal
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+program pp;
+
+{
+ possible compiler switches:
+ -----------------------------------------------------------------
+ CMEM use cmem unit for better memory debugging
+ I386 generate a compiler for the Intel i386+
+ x86_64 generate a compiler for the AMD x86-64 architecture
+ M68K generate a compiler for the M68000
+ SPARC generate a compiler for SPARC
+ POWERPC generate a compiler for the PowerPC
+ POWERPC64 generate a compiler for the PowerPC64 architecture
+ VIS generate a compile for the VIS
+ DEBUG version with debug code is generated
+ EXTDEBUG some extra debug code is executed
+ SUPPORT_MMX only i386: releases the compiler switch
+ MMX which allows the compiler to generate
+ MMX instructions
+ EXTERN_MSG Don't compile the msgfiles in the compiler, always
+ use external messagefiles, default for TP
+ FPC_ARMEL create an arm eabi compiler
+ FPC_ARMEB create an arm big endian compiler
+ FPC_OARM create an arm oabi compiler, only needed when the host
+ compiler is ARMEL or ARMEB
+ -----------------------------------------------------------------
+ cpuflags The target processor has status flags (on by default)
+ cpufpemu The target compiler will also support emitting software
+ floating point operations
+ cpu64bitaddr Generate code for a 64-bit address space
+ cpu64bitalu The target cpu has 64-bit registers and a 64 bit alu
+ (required for cpu64bitaddr; optional with 32 bit addr space)
+ -----------------------------------------------------------------
+}
+
+{$i fpcdefs.inc}
+
+{ Require at least 2.0.2 }
+{$ifdef VER2_0}
+ {$if FPC_PATCH<2}
+ {$fatal At least FPC 2.0.2 is required to compile the compiler}
+ {$endif}
+{$endif VER2_0}
+
+{ exactly one target CPU must be defined }
+{$ifdef I386}
+ {$ifdef CPUDEFINED}
+ {$fatal ONLY one of the switches for the CPU type must be defined}
+ {$endif CPUDEFINED}
+ {$define CPUDEFINED}
+{$endif I386}
+{$ifdef x86_64}
+ {$ifdef CPUDEFINED}
+ {$fatal ONLY one of the switches for the CPU type must be defined}
+ {$endif CPUDEFINED}
+ {$define CPUDEFINED}
+{$endif x86_64}
+{$ifdef M68K}
+ {$ifdef CPUDEFINED}
+ {$fatal ONLY one of the switches for the CPU type must be defined}
+ {$endif CPUDEFINED}
+ {$define CPUDEFINED}
+{$endif M68K}
+{$ifdef vis}
+ {$ifdef CPUDEFINED}
+ {$fatal ONLY one of the switches for the CPU type must be defined}
+ {$endif CPUDEFINED}
+ {$define CPUDEFINED}
+{$endif}
+{$ifdef iA64}
+ {$ifdef CPUDEFINED}
+ {$fatal ONLY one of the switches for the CPU type must be defined}
+ {$endif CPUDEFINED}
+ {$define CPUDEFINED}
+{$endif iA64}
+{$ifdef POWERPC}
+ {$ifdef CPUDEFINED}
+ {$fatal ONLY one of the switches for the CPU type must be defined}
+ {$endif CPUDEFINED}
+ {$define CPUDEFINED}
+{$endif POWERPC}
+{$ifdef POWERPC64}
+ {$ifdef CPUDEFINED}
+ {$fatal ONLY one of the switches for the CPU type must be defined}
+ {$endif CPUDEFINED}
+ {$define CPUDEFINED}
+{$endif POWERPC64}
+{$ifdef ALPHA}
+ {$ifdef CPUDEFINED}
+ {$fatal ONLY one of the switches for the CPU type must be defined}
+ {$endif CPUDEFINED}
+ {$define CPUDEFINED}
+{$endif ALPHA}
+{$ifdef SPARC}
+ {$ifdef CPUDEFINED}
+ {$fatal ONLY one of the switches for the CPU type must be defined}
+ {$endif CPUDEFINED}
+ {$define CPUDEFINED}
+{$endif SPARC}
+{$ifdef ARM}
+ {$ifdef CPUDEFINED}
+ {$fatal ONLY one of the switches for the CPU type must be defined}
+ {$endif CPUDEFINED}
+ {$define CPUDEFINED}
+{$endif ARM}
+{$ifdef MIPS}
+ {$ifdef CPUDEFINED}
+ {$fatal ONLY one of the switches for the CPU type must be defined}
+ {$endif CPUDEFINED}
+ {$define CPUDEFINED}
+{$endif MIPS}
+{$ifdef AVR}
+ {$ifdef CPUDEFINED}
+ {$fatal ONLY one of the switches for the CPU type must be defined}
+ {$endif CPUDEFINED}
+ {$define CPUDEFINED}
+{$endif AVR}
+{$ifndef CPUDEFINED}
+ {$fatal A CPU type switch must be defined}
+{$endif CPUDEFINED}
+{$ifdef support_mmx}
+ {$ifndef i386}
+ {$fatal I386 switch must be on for MMX support}
+ {$endif i386}
+{$endif support_mmx}
+
+
+{ Don't care about minstacksize or maxstacksize not beeing supported by current OS }
+{$WARN 2077 OFF}
+{$WARN 2078 OFF}
+
+{$ifdef win32}
+ { 256 MB stack }
+ { under windows the stack can't grow }
+ {$MAXSTACKSIZE 256000000}
+{$else win32}
+ {$ifdef win64}
+ { 512 MB stack }
+ { under windows the stack can't grow }
+ {$MAXSTACKSIZE 512000000}
+ {$else win64}
+ { 1 MB stack }
+ {$MINSTACKSIZE 1000000}
+ {$endif win64}
+{$endif win32}
+
+uses
+{$ifdef cmem}
+ cmem,
+{$endif cmem}
+{$ifdef profile}
+ profile,
+{$endif profile}
+{$ifndef NOCATCH}
+ {$if defined(Unix) or defined(Go32v2) or defined(Watcom)}
+ catch,
+ {$endif}
+{$endif NOCATCH}
+ globals,compiler;
+
+var
+ oldexit : pointer;
+procedure myexit;
+begin
+ exitproc:=oldexit;
+{$ifdef nocatch}
+ exit;
+{$endif nocatch}
+{ Show Runtime error if there was an error }
+ if (erroraddr<>nil) then
+ begin
+ case exitcode of
+ 100:
+ begin
+ erroraddr:=nil;
+ writeln('Error while reading file');
+ end;
+ 101:
+ begin
+ erroraddr:=nil;
+ writeln('Error while writing file');
+ end;
+ 202:
+ begin
+ erroraddr:=nil;
+ writeln('Error: Stack Overflow');
+ end;
+ 203:
+ begin
+ erroraddr:=nil;
+ writeln('Error: Out of memory');
+ end;
+ end;
+ { we cannot use current_filepos.file because all memory might have been
+ freed already !
+ But we can use global parser_current_file var }
+ Writeln('Compilation aborted ',parser_current_file,':',current_filepos.line);
+ end;
+end;
+
+begin
+ oldexit:=exitproc;
+ exitproc:=@myexit;
+{$ifdef extheaptrc}
+ keepreleased:=true;
+{$endif extheaptrc}
+{ Call the compiler with empty command, so it will take the parameters }
+ Halt(compiler.Compile(''));
+end.
diff --git a/closures/compiler/ppc.cfg b/closures/compiler/ppc.cfg
new file mode 100644
index 0000000000..ff4473a418
--- /dev/null
+++ b/closures/compiler/ppc.cfg
@@ -0,0 +1,40 @@
+-$A8
+-$B-
+-$C-
+-$D+
+-$E-
+-$F-
+-$G+
+-$H-
+-$I+
+-$J+
+-$K-
+-$L+
+-$M-
+-$N+
+-$O-
+-$P+
+-$Q+
+-$R+
+-$S-
+-$T-
+-$U-
+-$V-
+-$W+
+-$X+
+-$YD
+-$Z1
+-cc
+-AWinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
+-H+
+-W+
+-M
+-$M16384,1048576
+-K$00400000
+-LE"e:\program files\borland\delphi6\Projects\Bpl"
+-LN"e:\program files\borland\delphi6\Projects\Bpl"
+-U"i386;x86;systems"
+-O"i386;x86;systems"
+-I"i386;x86;systems"
+-R"i386;x86;systems"
+-Ddelphi i386 gdb support_mmx cpu86 noopt
diff --git a/closures/compiler/ppc.conf b/closures/compiler/ppc.conf
new file mode 100644
index 0000000000..7d716c1679
--- /dev/null
+++ b/closures/compiler/ppc.conf
@@ -0,0 +1,39 @@
+-$A8
+-$B-
+-$C+
+-$D+
+-$E-
+-$F-
+-$G+
+-$H+
+-$I+
+-$J-
+-$K-
+-$L+
+-$M-
+-$N+
+-$O+
+-$P+
+-$Q-
+-$R-
+-$S-
+-$T-
+-$U-
+-$V+
+-$W-
+-$X+
+-$YD
+-$Z1
+-cg
+-H+
+-W+
+-M
+-$M16384,1048576
+-K$00400000
+-E"."
+-N"."
+-U"i386:targets"
+-O"i386:targets"
+-I"i386:targets"
+-R"i386:targets"
+-DDELPHI;i386
diff --git a/closures/compiler/ppc.dof b/closures/compiler/ppc.dof
new file mode 100644
index 0000000000..3c3966031f
--- /dev/null
+++ b/closures/compiler/ppc.dof
@@ -0,0 +1,95 @@
+[FileVersion]
+Version=6.0
+[Compiler]
+A=8
+B=0
+C=0
+D=1
+E=0
+F=0
+G=1
+H=0
+I=1
+J=1
+K=0
+L=1
+M=0
+N=1
+O=0
+P=1
+Q=1
+R=1
+S=0
+T=0
+U=0
+V=0
+W=1
+X=1
+Y=1
+Z=1
+ShowHints=1
+ShowWarnings=1
+UnitAliases=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
+[Linker]
+MapFile=0
+OutputObjs=0
+ConsoleApp=0
+DebugInfo=0
+RemoteSymbols=0
+MinStackSize=16384
+MaxStackSize=1048576
+ImageBase=4194304
+ExeDescription=
+[Directories]
+OutputDir=
+UnitOutputDir=
+PackageDLLOutputDir=
+PackageDCPOutputDir=
+SearchPath=i386;x86;systems
+Packages=VCL50;VCLX50;VCLSMP50;VCLDB50;VCLADO50;ibevnt50;VCLBDE50;VCLDBX50;QRPT50;TEEUI50;TEEDB50;TEE50;DSS50;TEEQR50;VCLIB50;VCLMID50;VCLIE50;INETDB50;INET50;NMFAST50;WEBMID50;dclocx50;dclaxserver50
+Conditionals=delphi i386 gdb support_mmx cpu86 noopt
+DebugSourceDirs=
+UsePackages=0
+[Parameters]
+RunParams=
+HostApplication=
+Launcher=
+UseLauncher=0
+DebugCWD=
+[Version Info]
+IncludeVerInfo=0
+AutoIncBuild=0
+MajorVer=1
+MinorVer=0
+Release=0
+Build=0
+Debug=0
+PreRelease=0
+Special=0
+Private=0
+DLL=0
+Locale=1043
+CodePage=1252
+[Version Info Keys]
+CompanyName=
+FileDescription=
+FileVersion=1.0.0.0
+InternalName=
+LegalCopyright=
+LegalTrademarks=
+OriginalFilename=
+ProductName=
+ProductVersion=1.0.0.0
+Comments=
+[HistoryLists\hlConditionals]
+Count=2
+Item0=delphi i386 gdb support_mmx cpu86 noopt
+Item1=delphi i386 gdb support_mmx cpu86
+[HistoryLists\hlUnitAliases]
+Count=1
+Item0=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
+[HistoryLists\hlSearchPath]
+Count=3
+Item0=i386;x86;systems
+Item1=i386;x86
+Item2=i386 x86
diff --git a/closures/compiler/ppc68k.lpi b/closures/compiler/ppc68k.lpi
new file mode 100644
index 0000000000..999a94a0cc
--- /dev/null
+++ b/closures/compiler/ppc68k.lpi
@@ -0,0 +1,79 @@
+<?xml version="1.0"?>
+<CONFIG>
+ <ProjectOptions>
+ <PathDelim Value="\"/>
+ <Version Value="7"/>
+ <General>
+ <Flags>
+ <MainUnitHasUsesSectionForAllUnits Value="False"/>
+ <MainUnitHasCreateFormStatements Value="False"/>
+ <MainUnitHasTitleStatement Value="False"/>
+ <LRSInOutputDirectory Value="False"/>
+ </Flags>
+ <SessionStorage Value="InProjectDir"/>
+ <MainUnit Value="0"/>
+ <TargetFileExt Value=".exe"/>
+ <Title Value="pp"/>
+ </General>
+ <PublishOptions>
+ <Version Value="2"/>
+ <IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
+ <ExcludeFileFilter Value="*.(bak|ppu|ppw|o|so);*~;backup"/>
+ </PublishOptions>
+ <RunParams>
+ <local>
+ <FormatVersion Value="1"/>
+ <LaunchingApplication PathPlusParams="/usr/X11R6/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/>
+ </local>
+ </RunParams>
+ <Units Count="2">
+ <Unit0>
+ <Filename Value="pp.pas"/>
+ <IsPartOfProject Value="True"/>
+ <UnitName Value="pp"/>
+ </Unit0>
+ <Unit1>
+ <Filename Value="m68k\aasmcpu.pas"/>
+ <IsPartOfProject Value="True"/>
+ <UnitName Value="aasmcpu"/>
+ </Unit1>
+ </Units>
+ </ProjectOptions>
+ <CompilerOptions>
+ <Version Value="8"/>
+ <PathDelim Value="\"/>
+ <Target>
+ <Filename Value="m68k\pp"/>
+ </Target>
+ <SearchPaths>
+ <IncludeFiles Value="m68k\"/>
+ <OtherUnitFiles Value="m68k\;systems\"/>
+ <UnitOutputDirectory Value="m68k\lazbuild"/>
+ </SearchPaths>
+ <Parsing>
+ <SyntaxOptions>
+ <CStyleOperator Value="False"/>
+ <AllowLabel Value="False"/>
+ <CPPInline Value="False"/>
+ </SyntaxOptions>
+ </Parsing>
+ <Linking>
+ <Debugging>
+ <GenerateDebugInfo Value="True"/>
+ </Debugging>
+ </Linking>
+ <Other>
+ <Verbosity>
+ <ShowWarn Value="False"/>
+ <ShowNotes Value="False"/>
+ <ShowHints Value="False"/>
+ </Verbosity>
+ <ConfigFile>
+ <StopAfterErrCount Value="50"/>
+ </ConfigFile>
+ <CustomOptions Value="-dm68k
+"/>
+ <CompilerPath Value="$(CompPath)"/>
+ </Other>
+ </CompilerOptions>
+</CONFIG>
diff --git a/closures/compiler/ppcarm.lpi b/closures/compiler/ppcarm.lpi
new file mode 100644
index 0000000000..aa78c5fafb
--- /dev/null
+++ b/closures/compiler/ppcarm.lpi
@@ -0,0 +1,93 @@
+<?xml version="1.0"?>
+<CONFIG>
+ <ProjectOptions>
+ <Version Value="9"/>
+ <PathDelim Value="\"/>
+ <General>
+ <Flags>
+ <MainUnitHasUsesSectionForAllUnits Value="False"/>
+ <MainUnitHasCreateFormStatements Value="False"/>
+ <MainUnitHasTitleStatement Value="False"/>
+ <LRSInOutputDirectory Value="False"/>
+ </Flags>
+ <SessionStorage Value="InProjectDir"/>
+ <MainUnit Value="0"/>
+ <Title Value="ppcarm"/>
+ </General>
+ <BuildModes Count="1">
+ <Item1 Name="default" Default="True"/>
+ </BuildModes>
+ <PublishOptions>
+ <Version Value="2"/>
+ <IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
+ <ExcludeFileFilter Value="*.(bak|ppu|ppw|o|so);*~;backup"/>
+ </PublishOptions>
+ <RunParams>
+ <local>
+ <FormatVersion Value="1"/>
+ <LaunchingApplication PathPlusParams="/usr/X11R6/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/>
+ </local>
+ </RunParams>
+ <Units Count="4">
+ <Unit0>
+ <Filename Value="pp.pas"/>
+ <IsPartOfProject Value="True"/>
+ <UnitName Value="pp"/>
+ </Unit0>
+ <Unit1>
+ <Filename Value="arm\aasmcpu.pas"/>
+ <IsPartOfProject Value="True"/>
+ <UnitName Value="aasmcpu"/>
+ </Unit1>
+ <Unit2>
+ <Filename Value="arm\aoptcpu.pas"/>
+ <IsPartOfProject Value="True"/>
+ <UnitName Value="aoptcpu"/>
+ </Unit2>
+ <Unit3>
+ <Filename Value="aopt.pas"/>
+ <IsPartOfProject Value="True"/>
+ </Unit3>
+ </Units>
+ </ProjectOptions>
+ <CompilerOptions>
+ <Version Value="10"/>
+ <PathDelim Value="\"/>
+ <Target>
+ <Filename Value="arm\pp"/>
+ </Target>
+ <SearchPaths>
+ <IncludeFiles Value="arm"/>
+ <OtherUnitFiles Value="arm;systems"/>
+ <UnitOutputDirectory Value="arm\lazbuild"/>
+ </SearchPaths>
+ <Parsing>
+ <SyntaxOptions>
+ <CStyleOperator Value="False"/>
+ <AllowLabel Value="False"/>
+ <CPPInline Value="False"/>
+ <UseAnsiStrings Value="False"/>
+ </SyntaxOptions>
+ </Parsing>
+ <Linking>
+ <Debugging>
+ <GenerateDebugInfo Value="True"/>
+ </Debugging>
+ </Linking>
+ <Other>
+ <Verbosity>
+ <ShowWarn Value="False"/>
+ <ShowNotes Value="False"/>
+ <ShowHints Value="False"/>
+ </Verbosity>
+ <ConfigFile>
+ <StopAfterErrCount Value="50"/>
+ </ConfigFile>
+ <CompilerMessages>
+ <UseMsgFile Value="True"/>
+ </CompilerMessages>
+ <CustomOptions Value="-darm"/>
+ <CompilerPath Value="$(CompPath)"/>
+ </Other>
+ </CompilerOptions>
+</CONFIG>
diff --git a/closures/compiler/ppcavr.lpi b/closures/compiler/ppcavr.lpi
new file mode 100644
index 0000000000..cc0cda1e1d
--- /dev/null
+++ b/closures/compiler/ppcavr.lpi
@@ -0,0 +1,84 @@
+<?xml version="1.0"?>
+<CONFIG>
+ <ProjectOptions>
+ <Version Value="9"/>
+ <PathDelim Value="\"/>
+ <General>
+ <Flags>
+ <MainUnitHasUsesSectionForAllUnits Value="False"/>
+ <MainUnitHasCreateFormStatements Value="False"/>
+ <MainUnitHasTitleStatement Value="False"/>
+ <LRSInOutputDirectory Value="False"/>
+ </Flags>
+ <SessionStorage Value="InProjectDir"/>
+ <MainUnit Value="0"/>
+ <Title Value="ppavr"/>
+ </General>
+ <BuildModes Count="1">
+ <Item1 Name="default" Default="True"/>
+ </BuildModes>
+ <PublishOptions>
+ <Version Value="2"/>
+ <IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
+ <ExcludeFileFilter Value="*.(bak|ppu|ppw|o|so);*~;backup"/>
+ </PublishOptions>
+ <RunParams>
+ <local>
+ <FormatVersion Value="1"/>
+ <LaunchingApplication PathPlusParams="/usr/X11R6/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/>
+ </local>
+ </RunParams>
+ <Units Count="2">
+ <Unit0>
+ <Filename Value="pp.pas"/>
+ <IsPartOfProject Value="True"/>
+ <UnitName Value="pp"/>
+ </Unit0>
+ <Unit1>
+ <Filename Value="avr\aasmcpu.pas"/>
+ <IsPartOfProject Value="True"/>
+ <UnitName Value="aasmcpu"/>
+ </Unit1>
+ </Units>
+ </ProjectOptions>
+ <CompilerOptions>
+ <Version Value="10"/>
+ <PathDelim Value="\"/>
+ <Target>
+ <Filename Value="avr\pp"/>
+ </Target>
+ <SearchPaths>
+ <IncludeFiles Value="avr"/>
+ <OtherUnitFiles Value="avr;systems"/>
+ <UnitOutputDirectory Value="avr\lazbuild"/>
+ </SearchPaths>
+ <Parsing>
+ <SyntaxOptions>
+ <CStyleOperator Value="False"/>
+ <AllowLabel Value="False"/>
+ <CPPInline Value="False"/>
+ <UseAnsiStrings Value="False"/>
+ </SyntaxOptions>
+ </Parsing>
+ <Linking>
+ <Debugging>
+ <GenerateDebugInfo Value="True"/>
+ </Debugging>
+ </Linking>
+ <Other>
+ <Verbosity>
+ <ShowWarn Value="False"/>
+ <ShowNotes Value="False"/>
+ <ShowHints Value="False"/>
+ </Verbosity>
+ <ConfigFile>
+ <StopAfterErrCount Value="50"/>
+ </ConfigFile>
+ <CompilerMessages>
+ <UseMsgFile Value="True"/>
+ </CompilerMessages>
+ <CustomOptions Value="-davr"/>
+ <CompilerPath Value="$(CompPath)"/>
+ </Other>
+ </CompilerOptions>
+</CONFIG>
diff --git a/closures/compiler/ppcgen/aasmcpu.pas b/closures/compiler/ppcgen/aasmcpu.pas
new file mode 100644
index 0000000000..5cf5b62355
--- /dev/null
+++ b/closures/compiler/ppcgen/aasmcpu.pas
@@ -0,0 +1,602 @@
+{
+ Copyright (c) 1999-2002 by Jonas Maebe and Thomas Schatzl
+
+ Contains the assembler object for the PowerPC 32 and PowerPC 64
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit aasmcpu;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ globtype,verbose,
+ aasmbase,aasmtai,aasmdata,aasmsym,
+ cpubase,cgbase,cgutils;
+
+ const
+ { "mov reg,reg" source operand number }
+ O_MOV_SOURCE = 1;
+ { "mov reg,reg" source operand number }
+ O_MOV_DEST = 0;
+
+
+ type
+ taicpu = class(tai_cpu_abstract_sym)
+ constructor op_none(op : tasmop);
+
+ constructor op_reg(op : tasmop;_op1 : tregister);
+ constructor op_const(op : tasmop;_op1 : aint);
+
+ constructor op_reg_reg(op : tasmop;_op1,_op2 : tregister);
+ constructor op_reg_ref(op : tasmop;_op1 : tregister;const _op2 : treference);
+ constructor op_reg_const(op:tasmop; _op1: tregister; _op2: aint);
+ constructor op_const_reg(op:tasmop; _op1: aint; _op2: tregister);
+
+ constructor op_const_const(op : tasmop;_op1,_op2 : aint);
+
+ constructor op_reg_reg_const_const(op: tasmop; _op1, _op2: tregister; _op3, _op4: aint);
+
+ constructor op_reg_reg_reg(op : tasmop;_op1,_op2,_op3 : tregister);
+ constructor op_reg_reg_const(op : tasmop;_op1,_op2 : tregister; _op3: aint);
+ constructor op_reg_reg_sym_ofs(op : tasmop;_op1,_op2 : tregister; _op3: tasmsymbol;_op3ofs: aint);
+ constructor op_reg_reg_ref(op : tasmop;_op1,_op2 : tregister; const _op3: treference);
+ constructor op_const_reg_reg(op : tasmop;_op1 : aint;_op2, _op3 : tregister);
+ constructor op_const_reg_const(op : tasmop;_op1 : aint;_op2 : tregister;_op3 : aint);
+ constructor op_const_const_const(op : tasmop;_op1 : aint;_op2 : aint;_op3 : aint);
+
+ constructor op_reg_reg_reg_reg(op : tasmop;_op1,_op2,_op3,_op4 : tregister);
+ constructor op_reg_bool_reg_reg(op : tasmop;_op1: tregister;_op2:boolean;_op3,_op4:tregister);
+ constructor op_reg_bool_reg_const(op : tasmop;_op1: tregister;_op2:boolean;_op3:tregister;_op4: aint);
+
+ constructor op_reg_reg_reg_const(op : tasmop; _op1, _op2, _op3 : tregister; _op4 : aint);
+ constructor op_reg_reg_reg_const_const(op : tasmop;_op1,_op2,_op3 : tregister;_op4,_op5 : aint);
+ constructor op_reg_reg_const_const_const(op : tasmop;_op1,_op2 : tregister;_op3,_op4,_op5 : aint);
+
+
+ { this is for Jmp instructions }
+ constructor op_cond_sym(op : tasmop;cond:TAsmCond;_op1 : tasmsymbol);
+ constructor op_const_const_sym(op : tasmop;_op1,_op2 : aint;_op3: tasmsymbol);
+
+
+ constructor op_sym(op : tasmop;_op1 : tasmsymbol);
+ constructor op_sym_ofs(op : tasmop;_op1 : tasmsymbol;_op1ofs:aint);
+ constructor op_reg_sym_ofs(op : tasmop;_op1 : tregister;_op2:tasmsymbol;_op2ofs : aint);
+ constructor op_sym_ofs_ref(op : tasmop;_op1 : tasmsymbol;_op1ofs:aint;const _op2 : treference);
+
+ procedure loadbool(opidx:aint;_b:boolean);
+
+ function is_same_reg_move(regtype: Tregistertype):boolean; override;
+
+ { register spilling code }
+ function spilling_get_operation_type(opnr: longint): topertype;override;
+ function spilling_get_operation_type_ref(opnr: longint; reg: tregister): topertype;override;
+ end;
+
+ tai_align = class(tai_align_abstract)
+ { nothing to add }
+ end;
+
+ procedure InitAsm;
+ procedure DoneAsm;
+
+
+ function spilling_create_load(const ref:treference;r:tregister):Taicpu;
+ function spilling_create_store(r:tregister; const ref:treference):Taicpu;
+
+ procedure fixup_jmps(list: TAsmList);
+
+implementation
+
+uses cutils, cclasses;
+
+{*****************************************************************************
+ taicpu Constructors
+*****************************************************************************}
+
+ procedure taicpu.loadbool(opidx:aint;_b:boolean);
+ begin
+ if opidx>=ops then
+ ops:=opidx+1;
+ with oper[opidx]^ do
+ begin
+ if typ=top_ref then
+ dispose(ref);
+ b:=_b;
+ typ:=top_bool;
+ end;
+ end;
+
+
+ constructor taicpu.op_none(op : tasmop);
+ begin
+ inherited create(op);
+ end;
+
+
+ constructor taicpu.op_reg(op : tasmop;_op1 : tregister);
+ begin
+ inherited create(op);
+ ops:=1;
+ loadreg(0,_op1);
+ end;
+
+
+ constructor taicpu.op_const(op : tasmop;_op1 : aint);
+ begin
+ inherited create(op);
+ ops:=1;
+ loadconst(0,_op1);
+ end;
+
+
+ constructor taicpu.op_reg_reg(op : tasmop;_op1,_op2 : tregister);
+ begin
+ inherited create(op);
+ ops:=2;
+ loadreg(0,_op1);
+ loadreg(1,_op2);
+ end;
+
+ constructor taicpu.op_reg_const(op:tasmop; _op1: tregister; _op2: aint);
+ begin
+ inherited create(op);
+ ops:=2;
+ loadreg(0,_op1);
+ loadconst(1,_op2);
+ end;
+
+ constructor taicpu.op_const_reg(op:tasmop; _op1: aint; _op2: tregister);
+ begin
+ inherited create(op);
+ ops:=2;
+ loadconst(0,_op1);
+ loadreg(1,_op2);
+ end;
+
+
+ constructor taicpu.op_reg_ref(op : tasmop;_op1 : tregister;const _op2 : treference);
+ begin
+ inherited create(op);
+ ops:=2;
+ loadreg(0,_op1);
+ loadref(1,_op2);
+ end;
+
+
+ constructor taicpu.op_const_const(op : tasmop;_op1,_op2 : aint);
+ begin
+ inherited create(op);
+ ops:=2;
+ loadconst(0,_op1);
+ loadconst(1,_op2);
+ end;
+
+
+ constructor taicpu.op_reg_reg_const_const(op: tasmop; _op1, _op2: tregister; _op3, _op4: aint);
+ begin
+ inherited create(op);
+ ops := 4;
+ loadreg(0, _op1);
+ loadreg(1, _op2);
+ loadconst(2, _op3);
+ loadconst(3, _op4);
+ end;
+
+
+ constructor taicpu.op_reg_reg_reg(op : tasmop;_op1,_op2,_op3 : tregister);
+ begin
+ inherited create(op);
+ ops:=3;
+ loadreg(0,_op1);
+ loadreg(1,_op2);
+ loadreg(2,_op3);
+ end;
+
+ constructor taicpu.op_reg_reg_const(op : tasmop;_op1,_op2 : tregister; _op3: aint);
+ begin
+ inherited create(op);
+ ops:=3;
+ loadreg(0,_op1);
+ loadreg(1,_op2);
+ loadconst(2,_op3);
+ end;
+
+ constructor taicpu.op_reg_reg_sym_ofs(op : tasmop;_op1,_op2 : tregister; _op3: tasmsymbol;_op3ofs: aint);
+ begin
+ inherited create(op);
+ ops:=3;
+ loadreg(0,_op1);
+ loadreg(1,_op2);
+ loadsymbol(0,_op3,_op3ofs);
+ end;
+
+ constructor taicpu.op_reg_reg_ref(op : tasmop;_op1,_op2 : tregister; const _op3: treference);
+ begin
+ inherited create(op);
+ ops:=3;
+ loadreg(0,_op1);
+ loadreg(1,_op2);
+ loadref(2,_op3);
+ end;
+
+ constructor taicpu.op_const_reg_reg(op : tasmop;_op1 : aint;_op2, _op3 : tregister);
+ begin
+ inherited create(op);
+ ops:=3;
+ loadconst(0,_op1);
+ loadreg(1,_op2);
+ loadreg(2,_op3);
+ end;
+
+ constructor taicpu.op_const_reg_const(op : tasmop;_op1 : aint;_op2 : tregister;_op3 : aint);
+ begin
+ inherited create(op);
+ ops:=3;
+ loadconst(0,_op1);
+ loadreg(1,_op2);
+ loadconst(2,_op3);
+ end;
+
+
+ constructor taicpu.op_const_const_const(op : tasmop;_op1 : aint;_op2 : aint;_op3 : aint);
+ begin
+ inherited create(op);
+ ops:=3;
+ loadconst(0,_op1);
+ loadconst(1,_op2);
+ loadconst(2,_op3);
+ end;
+
+
+ constructor taicpu.op_reg_reg_reg_reg(op : tasmop;_op1,_op2,_op3,_op4 : tregister);
+ begin
+ inherited create(op);
+ ops:=4;
+ loadreg(0,_op1);
+ loadreg(1,_op2);
+ loadreg(2,_op3);
+ loadreg(3,_op4);
+ end;
+
+ constructor taicpu.op_reg_bool_reg_reg(op : tasmop;_op1: tregister;_op2:boolean;_op3,_op4:tregister);
+ begin
+ inherited create(op);
+ ops:=4;
+ loadreg(0,_op1);
+ loadbool(1,_op2);
+ loadreg(2,_op3);
+ loadreg(3,_op4);
+ end;
+
+ constructor taicpu.op_reg_bool_reg_const(op : tasmop;_op1: tregister;_op2:boolean;_op3:tregister;_op4: aint);
+ begin
+ inherited create(op);
+ ops:=4;
+ loadreg(0,_op1);
+ loadbool(0,_op2);
+ loadreg(0,_op3);
+ loadconst(0,cardinal(_op4));
+ end;
+
+ constructor taicpu.op_reg_reg_reg_const(op : tasmop; _op1, _op2, _op3 : tregister; _op4 : aint);
+ begin
+ inherited create(op);
+ ops := 4;
+ loadreg(0, _op1);
+ loadreg(1, _op2);
+ loadreg(2, _op3);
+ loadconst(3, cardinal(_op4));
+ end;
+
+ constructor taicpu.op_reg_reg_reg_const_const(op : tasmop;_op1,_op2,_op3 : tregister;_op4,_op5 : aint);
+ begin
+ inherited create(op);
+ ops:=5;
+ loadreg(0,_op1);
+ loadreg(1,_op2);
+ loadreg(2,_op3);
+ loadconst(3,cardinal(_op4));
+ loadconst(4,cardinal(_op5));
+ end;
+
+ constructor taicpu.op_reg_reg_const_const_const(op : tasmop;_op1,_op2 : tregister;_op3,_op4,_op5 : aint);
+ begin
+ inherited create(op);
+ ops:=5;
+ loadreg(0,_op1);
+ loadreg(1,_op2);
+ loadconst(2,_op3);
+ loadconst(3,_op4);
+ loadconst(4,_op5);
+ end;
+
+ constructor taicpu.op_cond_sym(op : tasmop;cond:TAsmCond;_op1 : tasmsymbol);
+ begin
+ inherited create(op);
+ condition:=cond;
+ ops:=1;
+ loadsymbol(0,_op1,0);
+ end;
+
+ constructor taicpu.op_const_const_sym(op : tasmop;_op1,_op2 : aint; _op3: tasmsymbol);
+ begin
+ inherited create(op);
+ ops:=3;
+ loadconst(0,_op1);
+ loadconst(1,_op2);
+ loadsymbol(2,_op3,0);
+ end;
+
+
+ constructor taicpu.op_sym(op : tasmop;_op1 : tasmsymbol);
+ begin
+ inherited create(op);
+ ops:=1;
+ loadsymbol(0,_op1,0);
+ end;
+
+
+ constructor taicpu.op_sym_ofs(op : tasmop;_op1 : tasmsymbol;_op1ofs:aint);
+ begin
+ inherited create(op);
+ ops:=1;
+ loadsymbol(0,_op1,_op1ofs);
+ end;
+
+
+ constructor taicpu.op_reg_sym_ofs(op : tasmop;_op1 : tregister;_op2:tasmsymbol;_op2ofs : aint);
+ begin
+ inherited create(op);
+ ops:=2;
+ loadreg(0,_op1);
+ loadsymbol(1,_op2,_op2ofs);
+ end;
+
+
+ constructor taicpu.op_sym_ofs_ref(op : tasmop;_op1 : tasmsymbol;_op1ofs:aint;const _op2 : treference);
+ begin
+ inherited create(op);
+ ops:=2;
+ loadsymbol(0,_op1,_op1ofs);
+ loadref(1,_op2);
+ end;
+
+
+{ ****************************** newra stuff *************************** }
+
+ function taicpu.is_same_reg_move(regtype: Tregistertype):boolean;
+ begin
+ result :=
+ (((opcode=A_MR) and
+ (regtype = R_INTREGISTER)) or
+ ((opcode = A_FMR) and
+ (regtype = R_FPUREGISTER))) and
+ { these opcodes can only have registers as operands }
+ (oper[0]^.reg=oper[1]^.reg);
+ end;
+
+
+ function taicpu.spilling_get_operation_type(opnr: longint): topertype;
+ begin
+ result := operand_read;
+ case opcode of
+ A_STMW,A_LMW:
+ internalerror(2005021805);
+ A_STBU, A_STBUX, A_STHU, A_STHUX,
+ A_STWU, A_STWUX,
+ A_STFSU, A_STFSUX, A_STFDU, A_STFDUX,
+ A_STB, A_STBX, A_STH, A_STHX,
+ A_STW, A_STWX,
+ A_STFS, A_STFSX, A_STFD, A_STFDX, A_STFIWX, A_STHBRX, A_STWBRX, A_STWCX_,
+ A_CMP, A_CMPI, A_CMPL, A_CMPLI,
+ A_DCBA, A_DCBI, A_DCBST, A_DCBT, A_DCBTST, A_DCBZ, A_DCBF, A_ICBI,
+ A_ECOWX, A_FCMPO, A_FCMPU, A_MTMSR, A_TLBIE, A_TW, A_TWI,
+ A_CMPWI, A_CMPW, A_CMPLWI, A_CMPLW, A_MT, A_MTLR, A_MTCTR
+{$ifdef cpu64bitalu}
+ , A_STDU, A_STDUX,
+ A_STD, A_STDX,
+ A_STDCX_,
+ A_CMPD, A_CMPDI, A_CMPLD, A_CMPLDI,
+ A_MFXER
+{$endif cpu64bitalu}
+ : ;
+ A_RLWIMI, A_RLWIMI_
+{$ifdef cpu64bitalu}
+ , A_INSRDI, A_INSRDI_, A_RLDIMI
+{$endif not cpu64bitalu}
+ :
+ if opnr = 0 then
+ result := operand_readwrite;
+ else
+ if opnr = 0 then
+ result := operand_write;
+ end;
+ end;
+
+
+ function taicpu.spilling_get_operation_type_ref(opnr: longint; reg: tregister): topertype;
+ begin
+ result := operand_read;
+ case opcode of
+ A_STBU, A_STBUX, A_STHU, A_STHUX, A_STWU, A_STWUX,
+{$ifdef cpu64bitalu}
+ A_STDU, A_STDUX,
+{$endif cpu64bitalu}
+ A_STFSU, A_STFSUX, A_STFDU, A_STFDUX:
+ if (oper[opnr]^.ref^.base = reg) then
+ result := operand_readwrite;
+ end;
+ end;
+
+
+ function spilling_create_load(const ref:treference;r:tregister):Taicpu;
+ begin
+ case getregtype(r) of
+ R_INTREGISTER:
+{$ifdef cpu64bitalu}
+ result:=taicpu.op_reg_ref(A_LD,r,ref);
+{$else cpu64bitalu}
+ result:=taicpu.op_reg_ref(A_LWZ,r,ref);
+{$endif cpu64bitalu}
+ R_FPUREGISTER:
+ result:=taicpu.op_reg_ref(A_LFD,r,ref);
+ else
+ internalerror(2005123101);
+ end;
+ end;
+
+
+ function spilling_create_store(r:tregister; const ref:treference):Taicpu;
+ begin
+ case getregtype(r) of
+ R_INTREGISTER:
+{$ifdef cpu64bitalu}
+ result:=taicpu.op_reg_ref(A_STD,r,ref);
+{$else cpu64bitalu}
+ result:=taicpu.op_reg_ref(A_STW,r,ref);
+{$endif cpu64bitalu}
+ R_FPUREGISTER:
+ result:=taicpu.op_reg_ref(A_STFD,r,ref);
+ else
+ internalerror(2005123102);
+ end;
+ end;
+
+
+ procedure InitAsm;
+ begin
+ end;
+
+
+ procedure DoneAsm;
+ begin
+ end;
+
+
+ procedure fixup_jmps(list: TAsmList);
+ var
+ p: tai;
+ newjmp: taicpu;
+ labelpositions: TFPList;
+ instrpos: ptrint;
+ l: tasmlabel;
+ inserted_something: boolean;
+ begin
+ // if certainly not enough instructions to cause an overflow, don't bother
+ if (list.count <= (high(smallint) div 4)) then
+ exit;
+ labelpositions := TFPList.create;
+ p := tai(list.first);
+ instrpos := 1;
+ // record label positions
+ while assigned(p) do
+ begin
+ if p.typ = ait_label then
+ begin
+ if (tai_label(p).labsym.labelnr >= labelpositions.count) then
+ labelpositions.count := tai_label(p).labsym.labelnr * 2;
+ labelpositions[tai_label(p).labsym.labelnr] := pointer(instrpos);
+ end;
+ { ait_const is for jump tables }
+ case p.typ of
+ ait_instruction:
+ inc(instrpos);
+ ait_const:
+ begin
+ if (tai_const(p).consttype<>aitconst_32bit) then
+ internalerror(2008052101);
+ inc(instrpos);
+ end;
+ end;
+ p := tai(p.next);
+ end;
+
+ // check and fix distances
+ repeat
+ inserted_something := false;
+ p := tai(list.first);
+ instrpos := 1;
+ while assigned(p) do
+ begin
+ case p.typ of
+ ait_label:
+ // update labelposition in case it changed due to insertion
+ // of jumps
+ begin
+ // can happen because of newly inserted labels
+ if (tai_label(p).labsym.labelnr > labelpositions.count) then
+ labelpositions.count := tai_label(p).labsym.labelnr * 2;
+ labelpositions[tai_label(p).labsym.labelnr] := pointer(instrpos);
+ end;
+ ait_instruction:
+ begin
+ inc(instrpos);
+ case taicpu(p).opcode of
+ A_BC:
+ if (taicpu(p).oper[0]^.typ = top_ref) and
+ assigned(taicpu(p).oper[0]^.ref^.symbol) and
+ (taicpu(p).oper[0]^.ref^.symbol is tasmlabel) and
+ (labelpositions[tasmlabel(taicpu(p).oper[0]^.ref^.symbol).labelnr] <> NIL) and
+{$push}
+{$q-}
+ (ptruint(abs(ptrint(labelpositions[tasmlabel(taicpu(p).oper[0]^.ref^.symbol).labelnr]-instrpos)) - (low(smallint) div 4)) > ptruint((high(smallint) - low(smallint)) div 4)) then
+{$pop}
+ begin
+ // add a new label after this jump
+ current_asmdata.getjumplabel(l);
+ { new label -> may have to increase array size }
+ if (l.labelnr >= labelpositions.count) then
+ labelpositions.count := l.labelnr + 10;
+ { newjmp will be inserted before the label, and it's inserted after }
+ { the current jump -> instrpos+2 }
+ labelpositions[l.labelnr] := pointer(instrpos+2);
+ list.insertafter(tai_label.create(l),p);
+ // add a new unconditional jump between this jump and the label
+ newjmp := taicpu.op_sym(A_B,taicpu(p).oper[0]^.ref^.symbol);
+ newjmp.is_jmp := true;
+ newjmp.fileinfo := taicpu(p).fileinfo;
+ list.insertafter(newjmp,p);
+ inc(instrpos);
+ // change the conditional jump to point to the newly inserted label
+ tasmlabel(taicpu(p).oper[0]^.ref^.symbol).decrefs;
+ taicpu(p).oper[0]^.ref^.symbol := l;
+ l.increfs;
+ // and invert its condition code
+ taicpu(p).condition := inverse_cond(taicpu(p).condition);
+ // we inserted an instruction, so will have to check everything again
+ inserted_something := true;
+ end;
+ end;
+ end;
+ ait_const:
+ inc(instrpos);
+ end;
+ p := tai(p.next);
+ end;
+ until not inserted_something;
+ labelpositions.free;
+ end;
+
+
+begin
+ cai_align:=tai_align;
+ cai_cpu:=taicpu;
+end.
+
diff --git a/closures/compiler/ppcgen/agppcgas.pas b/closures/compiler/ppcgen/agppcgas.pas
new file mode 100644
index 0000000000..079d84edfc
--- /dev/null
+++ b/closures/compiler/ppcgen/agppcgas.pas
@@ -0,0 +1,456 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit the GAS asm writers for PowerPC/PowerPC64
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+
+{****************************************************************************}
+{ Helper routines for Instruction Writer }
+{****************************************************************************}
+
+unit agppcgas;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ aasmbase,
+ aasmtai,aasmdata,
+ aggas,
+ cpubase,cgutils,
+ globtype;
+
+ type
+ TPPCInstrWriter=class(TCPUInstrWriter)
+ procedure WriteInstruction(hp : tai);override;
+ end;
+
+ TPPCGNUAssembler=class(TGNUassembler)
+ constructor create(smart: boolean); override;
+ procedure WriteExtraHeader; override;
+ end;
+
+ TPPCAppleGNUAssembler=class(TAppleGNUassembler)
+ constructor create(smart: boolean); override;
+ function MakeCmdLine: TCmdStr; override;
+ end;
+
+ topstr = string[4];
+
+ function getreferencestring(var ref : treference) : string;
+ function getopstr_jmp(const o:toper) : string;
+ function getopstr(const o:toper) : string;
+ function branchmode(o: tasmop): topstr;
+ function cond2str(op: tasmop; c: tasmcond): string;
+
+ implementation
+
+ uses
+ cutils,globals,verbose,
+ cgbase,systems,
+ assemble,
+ itcpugas,cpuinfo,
+ aasmcpu;
+
+{$ifdef cpu64bitaddr}
+ const
+ refaddr2str: array[trefaddr] of string[9] = ('', '', '', '', '@l', '@h', '@higher', '@highest', '@ha', '@highera', '@highesta');
+ verbose_refaddrs = [addr_low, addr_high, addr_higher, addr_highest, addr_higha, addr_highera, addr_highesta];
+ refaddr2str_darwin: array[trefaddr] of string[4] = ('','','','','lo16', 'hi16', '@err', '@err', 'ha16', '@err', '@err');
+{$else cpu64bitaddr}
+ const
+ refaddr2str: array[trefaddr] of string[3] = ('','','','','@l','@h','@ha');
+ refaddr2str_darwin: array[trefaddr] of string[4] = ('','','','','lo16','hi16','ha16');
+ verbose_refaddrs = [addr_low,addr_high,addr_higha];
+{$endif cpu64bitaddr}
+
+
+ function getreferencestring(var ref : treference) : string;
+ var
+ s : string;
+ begin
+ with ref do
+ begin
+ if ((offset < -32768) or (offset > 32767)) and
+ (refaddr = addr_no) then
+ internalerror(2006052501);
+ if (refaddr = addr_no) then
+ s := ''
+ else
+ begin
+ if target_info.system in [system_powerpc_darwin,system_powerpc64_darwin] then
+ s := refaddr2str_darwin[refaddr]
+ else
+ s :='';
+ s := s+'(';
+ if assigned(symbol) then
+ begin
+ s:=s+symbol.name;
+ if assigned(relsymbol) then
+ s:=s+'-'+relsymbol.name;
+ end;
+ end;
+ if offset<0 then
+ s:=s+tostr(offset)
+ else
+ if (offset>0) then
+ begin
+ if assigned(symbol) then
+ s:=s+'+'+tostr(offset)
+ else
+ s:=s+tostr(offset);
+ end;
+
+ if (refaddr in verbose_refaddrs) then
+ begin
+ s := s+')';
+ if not(target_info.system in [system_powerpc_darwin,system_powerpc64_darwin]) then
+ s := s+refaddr2str[refaddr];
+ end;
+{$ifdef cpu64bitaddr}
+ if (refaddr = addr_pic) then
+ if (target_info.system <> system_powerpc64_linux) then
+ s := s + ')'
+ else
+ s := s + ')@got';
+{$endif cpu64bitaddr}
+
+ if (index=NR_NO) then
+ begin
+ if offset=0 then
+ begin
+ if not (assigned(symbol)) then
+ s:=s+'0';
+ end;
+ if (base<>NR_NO) then
+ s:=s+'('+gas_regname(base)+')'
+ else if not assigned(symbol) and
+ not(refaddr in verbose_refaddrs) then
+ s:=s+'(0)';
+ end
+ else if (index<>NR_NO) and (base<>NR_NO) then
+ begin
+ if (offset=0) then
+ s:=s+gas_regname(base)+','+gas_regname(index)
+ else
+ internalerror(2006052502);
+ end;
+ end;
+ getreferencestring:=s;
+ end;
+
+
+ function getopstr_jmp(const o:toper) : string;
+ var
+ hs : string;
+ begin
+ case o.typ of
+ top_reg :
+ getopstr_jmp:=gas_regname(o.reg);
+ { no top_ref jumping for powerpc }
+ top_const :
+ getopstr_jmp:=tostr(o.val);
+ top_ref :
+ begin
+ if o.ref^.refaddr<>addr_full then
+ internalerror(200402262);
+ hs:=o.ref^.symbol.name;
+ if o.ref^.offset>0 then
+ hs:=hs+'+'+tostr(o.ref^.offset)
+ else
+ if o.ref^.offset<0 then
+ hs:=hs+tostr(o.ref^.offset);
+ getopstr_jmp:=hs;
+ end;
+ top_none:
+ getopstr_jmp:='';
+ else
+ internalerror(2002070603);
+ end;
+ end;
+
+
+ function getopstr(const o:toper) : string;
+ var
+ hs : string;
+ begin
+ case o.typ of
+ top_reg:
+ getopstr:=gas_regname(o.reg);
+ top_const:
+ getopstr:=tostr(longint(o.val));
+ top_ref:
+ if o.ref^.refaddr=addr_full then
+ begin
+ hs:=o.ref^.symbol.name;
+ if o.ref^.offset>0 then
+ hs:=hs+'+'+tostr(o.ref^.offset)
+ else
+ if o.ref^.offset<0 then
+ hs:=hs+tostr(o.ref^.offset);
+ getopstr:=hs;
+ end
+ else
+ getopstr:=getreferencestring(o.ref^);
+ else
+ internalerror(2002070604);
+ end;
+ end;
+
+
+ function branchmode(o: tasmop): topstr;
+ var tempstr: topstr;
+ begin
+ tempstr := '';
+ case o of
+ A_BCCTR,A_BCCTRL: tempstr := 'ctr';
+ A_BCLR,A_BCLRL: tempstr := 'lr';
+ end;
+ case o of
+ A_BL,A_BLA,A_BCL,A_BCLA,A_BCCTRL,A_BCLRL: tempstr := tempstr+'l';
+ end;
+ case o of
+ A_BA,A_BLA,A_BCA,A_BCLA: tempstr:=tempstr+'a';
+ end;
+ branchmode := tempstr;
+ end;
+
+
+ function cond2str(op: tasmop; c: tasmcond): string;
+ { note: no checking is performed whether the given combination of }
+ { conditions is valid }
+ var
+ tempstr: string;
+ begin
+ tempstr:=#9;
+ case c.simple of
+ false:
+ begin
+ cond2str := tempstr+gas_op2str[op];
+ case c.dirhint of
+ DH_None:;
+ DH_Minus:
+ cond2str:=cond2str+'-';
+ DH_Plus:
+ cond2str:=cond2str+'+';
+ else
+ internalerror(2003112901);
+ end;
+ cond2str:=cond2str+#9+tostr(c.bo)+','+tostr(c.bi);
+ end;
+ true:
+ if (op >= A_B) and (op <= A_BCLRL) then
+ case c.cond of
+ { unconditional branch }
+ C_NONE:
+ cond2str := tempstr+gas_op2str[op];
+ { bdnzt etc }
+ else
+ begin
+ tempstr := tempstr+'b'+asmcondflag2str[c.cond]+
+ branchmode(op);
+ case c.dirhint of
+ DH_None:
+ tempstr:=tempstr+#9;
+ DH_Minus:
+ tempstr:=tempstr+('-'+#9);
+ DH_Plus:
+ tempstr:=tempstr+('+'+#9);
+ else
+ internalerror(2003112901);
+ end;
+ case c.cond of
+ C_LT..C_NU:
+ cond2str := tempstr+gas_regname(newreg(R_SPECIALREGISTER,c.cr,R_SUBWHOLE));
+ C_T,C_F,C_DNZT,C_DNZF,C_DZT,C_DZF:
+ cond2str := tempstr+tostr(c.crbit);
+ else
+ cond2str := tempstr;
+ end;
+ end;
+ end
+ { we have a trap instruction }
+ else
+ begin
+ internalerror(2002070601);
+ { not yet implemented !!!!!!!!!!!!!!!!!!!!! }
+ { case tempstr := 'tw';}
+ end;
+ end;
+ end;
+
+
+{****************************************************************************}
+{ PowerPC Instruction Writer }
+{****************************************************************************}
+
+ Procedure TPPCInstrWriter.WriteInstruction(hp : tai);
+ var op: TAsmOp;
+ s: string;
+ i: byte;
+ sep: string[3];
+ begin
+ op:=taicpu(hp).opcode;
+ if is_calljmp(op) then
+ begin
+ { direct BO/BI in op[0] and op[1] not supported, put them in condition! }
+ case op of
+ A_B,A_BA,A_BL,A_BLA:
+ s:=#9+gas_op2str[op]+#9;
+ A_BCTR,A_BCTRL,A_BLR,A_BLRL:
+ s:=#9+gas_op2str[op]
+ else
+ begin
+ s:=cond2str(op,taicpu(hp).condition);
+ if (s[length(s)] <> #9) and
+ (taicpu(hp).ops>0) then
+ s := s + ',';
+ end;
+ end;
+
+ if (taicpu(hp).ops>0) and (taicpu(hp).oper[0]^.typ<>top_none) then
+ begin
+ { first write the current contents of s, because the symbol }
+ { may be 255 characters }
+ owner.asmwrite(s);
+ s:=getopstr_jmp(taicpu(hp).oper[0]^);
+ end;
+ end
+ else
+ { process operands }
+ begin
+ s:=#9+gas_op2str[op];
+ if taicpu(hp).ops<>0 then
+ begin
+ {
+ if not is_calljmp(op) then
+ sep:=','
+ else
+ }
+ sep:=#9;
+ for i:=0 to taicpu(hp).ops-1 do
+ begin
+ // debug code
+ // writeln(s);
+ // writeln(taicpu(hp).fileinfo.line);
+ s:=s+sep+getopstr(taicpu(hp).oper[i]^);
+ sep:=',';
+ end;
+ end;
+ end;
+ owner.AsmWriteLn(s);
+ end;
+
+
+{****************************************************************************}
+{ GNU PPC Assembler writer }
+{****************************************************************************}
+
+ constructor TPPCGNUAssembler.create(smart: boolean);
+ begin
+ inherited create(smart);
+ InstrWriter := TPPCInstrWriter.create(self);
+ end;
+
+
+ procedure TPPCGNUAssembler.WriteExtraHeader;
+ var
+ i : longint;
+ begin
+ for i:=0 to 31 do
+ AsmWriteln(#9'.set'#9'r'+tostr(i)+','+tostr(i));
+ for i:=0 to 31 do
+ AsmWriteln(#9'.set'#9'f'+tostr(i)+','+tostr(i));
+ end;
+
+
+{****************************************************************************}
+{ GNU/Apple PPC Assembler writer }
+{****************************************************************************}
+
+ constructor TPPCAppleGNUAssembler.create(smart: boolean);
+ begin
+ inherited create(smart);
+ InstrWriter := TPPCInstrWriter.create(self);
+ end;
+
+
+ function TPPCAppleGNUAssembler.MakeCmdLine: TCmdStr;
+ begin
+ result := inherited MakeCmdLine;
+{$ifdef cpu64bitaddr}
+ Replace(result,'$ARCH','ppc64')
+{$else cpu64bitaddr}
+ case current_settings.cputype of
+ cpu_PPC7400:
+ Replace(result,'$ARCH','ppc7400');
+ cpu_PPC970:
+ Replace(result,'$ARCH','ppc970');
+ else
+ Replace(result,'$ARCH','ppc')
+ end;
+{$endif cpu64bitaddr}
+ end;
+
+
+
+
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+ const
+ as_ppc_gas_info : tasminfo =
+ (
+ id : as_gas;
+
+ idtxt : 'AS';
+ asmbin : 'as';
+{$ifdef cpu64bitaddr}
+ asmcmd : '-a64 -o $OBJ $ASM';
+{$else cpu64bitaddr}
+ asmcmd: '-o $OBJ $ASM';
+{$endif cpu64bitaddr}
+ supported_targets : [system_powerpc_linux,system_powerpc_netbsd,system_powerpc_openbsd,system_powerpc_MorphOS,system_powerpc_Amiga,system_powerpc64_linux,system_powerpc_embedded,system_powerpc64_embedded];
+ flags : [af_allowdirect,af_needar,af_smartlink_sections];
+ labelprefix : '.L';
+ comment : '# ';
+ );
+
+
+ as_ppc_gas_darwin_powerpc_info : tasminfo =
+ (
+ id : as_darwin;
+
+ idtxt : 'AS-Darwin';
+ asmbin : 'as';
+ asmcmd : '-o $OBJ $ASM -arch $ARCH';
+ supported_targets : [system_powerpc_darwin,system_powerpc64_darwin];
+ flags : [af_allowdirect,af_needar,af_smartlink_sections,af_supports_dwarf,af_stabs_use_function_absolute_addresses];
+ labelprefix : 'L';
+ comment : '# ';
+ );
+
+
+begin
+ RegisterAssembler(as_ppc_gas_info,TPPCGNUAssembler);
+ RegisterAssembler(as_ppc_gas_darwin_powerpc_info,TPPCAppleGNUAssembler);
+end.
diff --git a/closures/compiler/ppcgen/cgppc.pas b/closures/compiler/ppcgen/cgppc.pas
new file mode 100644
index 0000000000..4836b4d06c
--- /dev/null
+++ b/closures/compiler/ppcgen/cgppc.pas
@@ -0,0 +1,962 @@
+{
+ Copyright (c) 2006 by Florian Klaempfl
+
+ This unit implements the common part of the code generator for the PowerPC
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit cgppc;
+
+{$i fpcdefs.inc}
+ interface
+
+ uses
+ globtype,symtype,symdef,
+ cgbase,cgobj,
+ aasmbase,aasmcpu,aasmtai,aasmdata,
+ cpubase,cpuinfo,cgutils,rgcpu,
+ parabase;
+
+ type
+ tcgppcgen = class(tcg)
+ procedure a_load_const_cgpara(list: TAsmList; size: tcgsize; a: tcgint; const paraloc : tcgpara); override;
+ procedure a_loadaddr_ref_cgpara(list : TAsmList;const r : treference;const paraloc : tcgpara); override;
+
+ procedure a_call_reg(list : TAsmList;reg: tregister); override;
+
+ { stores the contents of register reg to the memory location described by
+ ref }
+ procedure a_load_reg_ref(list: TAsmList; fromsize, tosize: TCGSize;
+ reg: tregister; const ref: treference); override;
+
+ procedure a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);override;
+
+ { fpu move instructions }
+ procedure a_loadfpu_reg_reg(list: TAsmList; fromsize, tosize: tcgsize; reg1, reg2: tregister); override;
+ procedure a_loadfpu_ref_reg(list: TAsmList; fromsize, tosize: tcgsize; const ref: treference; reg: tregister); override;
+ procedure a_loadfpu_reg_ref(list: TAsmList; fromsize, tosize: tcgsize; reg: tregister; const ref: treference); override;
+
+ { overflow checking }
+ procedure g_overflowcheck(list: TAsmList; const l: tlocation; def: tdef);override;
+
+ { entry code }
+ procedure g_profilecode(list: TAsmList); override;
+
+ procedure a_jmp_cond(list : TAsmList;cond : TOpCmp;l: tasmlabel);
+
+ procedure g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);override;
+
+ procedure g_maybe_got_init(list: TAsmList); override;
+ { Transform unsupported methods into Internal errors }
+ procedure a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; size: TCGSize; src, dst: TRegister); override;
+ procedure g_stackpointer_alloc(list : TAsmList;localsize : longint);override;
+ protected
+ function get_darwin_call_stub(const s: string; weak: boolean): tasmsymbol;
+ procedure a_load_subsetref_regs_noindex(list: TAsmList; subsetsize: tcgsize; loadbitsize: byte; const sref: tsubsetreference; valuereg, extra_value_reg: tregister); override;
+ { Make sure ref is a valid reference for the PowerPC and sets the }
+ { base to the value of the index if (base = R_NO). }
+ { Returns true if the reference contained a base, index and an }
+ { offset or symbol, in which case the base will have been changed }
+ { to a tempreg (which has to be freed by the caller) containing }
+ { the sum of part of the original reference }
+ function fixref(list: TAsmList; var ref: treference): boolean;
+ { contains the common code of a_load_reg_ref and a_load_ref_reg }
+ procedure a_load_store(list:TAsmList;op: tasmop;reg:tregister;ref: treference);virtual;
+
+ { creates the correct branch instruction for a given combination }
+ { of asmcondflags and destination addressing mode }
+ procedure a_jmp(list: TAsmList; op: tasmop;
+ c: tasmcondflag; crval: longint; l: tasmlabel);
+
+ { returns true if the offset of the given reference can not be }
+ { represented by a 16 bit immediate as required by some PowerPC }
+ { instructions }
+ function hasLargeOffset(const ref : TReference) : Boolean; inline;
+
+ function save_lr_in_prologue: boolean;
+
+ function load_got_symbol(list : TAsmList; symbol : string) : tregister;
+ end;
+
+ const
+ TOpCmp2AsmCond: Array[topcmp] of TAsmCondFlag = (C_NONE,C_EQ,C_GT,
+ C_LT,C_GE,C_LE,C_NE,C_LE,C_LT,C_GE,C_GT);
+
+
+{$ifdef extdebug}
+ function ref2string(const ref : treference) : string;
+ function cgsize2string(const size : TCgSize) : string;
+ function cgop2string(const op : TOpCg) : String;
+{$endif extdebug}
+
+ implementation
+
+ uses
+ {$ifdef extdebug}sysutils,{$endif}
+ globals,verbose,systems,cutils,
+ symconst,symsym,fmodule,
+ rgobj,tgobj,cpupi,procinfo,paramgr;
+
+{ We know that macos_direct_globals is a const boolean
+ but we don't care about this warning }
+{$NOTE Is macos_direct_globals still useful?}
+{$WARN 6018 OFF}
+
+{$ifdef extdebug}
+ function ref2string(const ref : treference) : string;
+ begin
+ result := 'base : ' + inttostr(ord(ref.base)) + ' index : ' + inttostr(ord(ref.index)) + ' refaddr : ' + inttostr(ord(ref.refaddr)) + ' offset : ' + inttostr(ref.offset) + ' symbol : ';
+ if (assigned(ref.symbol)) then
+ result := result + ref.symbol.name;
+ end;
+
+ function cgsize2string(const size : TCgSize) : string;
+ const
+ cgsize_strings : array[TCgSize] of string[8] = (
+ 'OS_NO', 'OS_8', 'OS_16', 'OS_32', 'OS_64', 'OS_128', 'OS_S8', 'OS_S16', 'OS_S32',
+ 'OS_S64', 'OS_S128', 'OS_F32', 'OS_F64', 'OS_F80', 'OS_C64', 'OS_F128',
+ 'OS_M8', 'OS_M16', 'OS_M32', 'OS_M64', 'OS_M128', 'OS_MS8', 'OS_MS16', 'OS_MS32',
+ 'OS_MS64', 'OS_MS128');
+ begin
+ result := cgsize_strings[size];
+ end;
+
+ function cgop2string(const op : TOpCg) : String;
+ const
+ opcg_strings : array[TOpCg] of string[6] = (
+ 'None', 'Move', 'Add', 'And', 'Div', 'IDiv', 'IMul', 'Mul',
+ 'Neg', 'Not', 'Or', 'Sar', 'Shl', 'Shr', 'Sub', 'Xor', 'Rol', 'Ror'
+ );
+ begin
+ result := opcg_strings[op];
+ end;
+{$endif extdebug}
+
+
+ function tcgppcgen.hasLargeOffset(const ref : TReference) : Boolean;
+ begin
+ result := aword(ref.offset-low(smallint)) > high(smallint)-low(smallint);
+ end;
+
+
+ function tcgppcgen.save_lr_in_prologue: boolean;
+ begin
+ result:=
+ (not (po_assembler in current_procinfo.procdef.procoptions) and
+ ((pi_do_call in current_procinfo.flags) or
+ (cs_profile in init_settings.moduleswitches))) or
+ ([cs_lineinfo,cs_debuginfo] * current_settings.moduleswitches <> []);
+ end;
+
+
+ procedure tcgppcgen.a_load_const_cgpara(list: TAsmList; size: tcgsize; a: tcgint; const
+ paraloc: tcgpara);
+ var
+ ref: treference;
+ begin
+ paraloc.check_simple_location;
+ paramanager.allocparaloc(list,paraloc.location);
+ case paraloc.location^.loc of
+ LOC_REGISTER, LOC_CREGISTER:
+ a_load_const_reg(list, size, a, paraloc.location^.register);
+ LOC_REFERENCE:
+ begin
+ reference_reset(ref,paraloc.alignment);
+ ref.base := paraloc.location^.reference.index;
+ ref.offset := paraloc.location^.reference.offset;
+ a_load_const_ref(list, size, a, ref);
+ end;
+ else
+ internalerror(2002081101);
+ end;
+ end;
+
+
+ procedure tcgppcgen.a_loadaddr_ref_cgpara(list : TAsmList;const r : treference;const paraloc : tcgpara);
+ var
+ ref: treference;
+ tmpreg: tregister;
+
+ begin
+ paraloc.check_simple_location;
+ paramanager.allocparaloc(list,paraloc.location);
+ case paraloc.location^.loc of
+ LOC_REGISTER,LOC_CREGISTER:
+ a_loadaddr_ref_reg(list,r,paraloc.location^.register);
+ LOC_REFERENCE:
+ begin
+ reference_reset(ref,paraloc.alignment);
+ ref.base := paraloc.location^.reference.index;
+ ref.offset := paraloc.location^.reference.offset;
+ tmpreg := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
+ a_loadaddr_ref_reg(list,r,tmpreg);
+ a_load_reg_ref(list,OS_ADDR,OS_ADDR,tmpreg,ref);
+ end;
+ else
+ internalerror(2002080701);
+ end;
+ end;
+
+
+ procedure tcgppcgen.g_maybe_got_init(list: TAsmList);
+ var
+ instr: taicpu;
+ cond: tasmcond;
+ savedlr: boolean;
+ begin
+ if not(po_assembler in current_procinfo.procdef.procoptions) then
+ begin
+ if (cs_create_pic in current_settings.moduleswitches) and
+ (pi_needs_got in current_procinfo.flags) then
+ case target_info.system of
+ system_powerpc_darwin,
+ system_powerpc64_darwin:
+ begin
+ savedlr:=save_lr_in_prologue;
+ if not savedlr then
+ list.concat(taicpu.op_reg_reg(A_MFSPR,NR_R0,NR_LR));
+ fillchar(cond,sizeof(cond),0);
+ cond.simple:=false;
+ cond.bo:=20;
+ cond.bi:=31;
+ instr:=taicpu.op_sym(A_BCL,current_procinfo.CurrGOTLabel);
+ instr.setcondition(cond);
+ list.concat(instr);
+ a_label(list,current_procinfo.CurrGOTLabel);
+ a_reg_alloc(list,current_procinfo.got);
+ list.concat(taicpu.op_reg_reg(A_MFSPR,current_procinfo.got,NR_LR));
+ if not savedlr or
+ { in the following case lr is saved, but not restored }
+ { (happens e.g. when generating debug info for leaf }
+ { procedures) }
+ not(pi_do_call in current_procinfo.flags) then
+ list.concat(taicpu.op_reg_reg(A_MTSPR,NR_LR,NR_R0));
+ end;
+ end;
+ end;
+ end;
+
+
+ function tcgppcgen.get_darwin_call_stub(const s: string; weak: boolean): tasmsymbol;
+ var
+ stubname: string;
+ instr: taicpu;
+ href: treference;
+ l1: tasmsymbol;
+ localgotlab: tasmlabel;
+ cond: tasmcond;
+ stubalign: byte;
+ begin
+ { function declared in the current unit? }
+ { doesn't work correctly, because this will also return a hit if we }
+ { previously took the address of an external procedure. It doesn't }
+ { really matter, the linker will remove all unnecessary stubs. }
+ stubname := 'L'+s+'$stub';
+ result := current_asmdata.getasmsymbol(stubname);
+ if assigned(result) then
+ exit;
+
+ if current_asmdata.asmlists[al_imports]=nil then
+ current_asmdata.asmlists[al_imports]:=TAsmList.create;
+
+ if (cs_create_pic in current_settings.moduleswitches) then
+ stubalign:=32
+ else
+ stubalign:=16;
+ new_section(current_asmdata.asmlists[al_imports],sec_stub,'',stubalign);
+ result := current_asmdata.RefAsmSymbol(stubname);
+ current_asmdata.asmlists[al_imports].concat(Tai_symbol.Create(result,0));
+ { register as a weak symbol if necessary }
+ if weak then
+ current_asmdata.weakrefasmsymbol(s);
+ current_asmdata.asmlists[al_imports].concat(tai_directive.create(asd_indirect_symbol,s));
+ l1 := current_asmdata.RefAsmSymbol('L'+s+'$lazy_ptr');
+ reference_reset_symbol(href,l1,0,sizeof(pint));
+ href.refaddr := addr_higha;
+ if (cs_create_pic in current_settings.moduleswitches) then
+ begin
+ current_asmdata.getjumplabel(localgotlab);
+ href.relsymbol:=localgotlab;
+ fillchar(cond,sizeof(cond),0);
+ cond.simple:=false;
+ cond.bo:=20;
+ cond.bi:=31;
+ current_asmdata.asmlists[al_imports].concat(taicpu.op_reg(A_MFLR,NR_R0));
+ instr:=taicpu.op_sym(A_BCL,localgotlab);
+ instr.setcondition(cond);
+ current_asmdata.asmlists[al_imports].concat(instr);
+ a_label(current_asmdata.asmlists[al_imports],localgotlab);
+ current_asmdata.asmlists[al_imports].concat(taicpu.op_reg(A_MFLR,NR_R11));
+ current_asmdata.asmlists[al_imports].concat(taicpu.op_reg_reg_ref(A_ADDIS,NR_R11,NR_R11,href));
+ current_asmdata.asmlists[al_imports].concat(taicpu.op_reg(A_MTLR,NR_R0));
+ end
+ else
+ current_asmdata.asmlists[al_imports].concat(taicpu.op_reg_ref(A_LIS,NR_R11,href));
+ href.refaddr := addr_low;
+ href.base := NR_R11;
+{$ifndef cpu64bitaddr}
+ current_asmdata.asmlists[al_imports].concat(taicpu.op_reg_ref(A_LWZU,NR_R12,href));
+{$else cpu64bitaddr}
+ { darwin/ppc64 uses a 32 bit absolute address here, strange... }
+ current_asmdata.asmlists[al_imports].concat(taicpu.op_reg_ref(A_LDU,NR_R12,href));
+{$endif cpu64bitaddr}
+ current_asmdata.asmlists[al_imports].concat(taicpu.op_reg(A_MTCTR,NR_R12));
+ current_asmdata.asmlists[al_imports].concat(taicpu.op_none(A_BCTR));
+ new_section(current_asmdata.asmlists[al_imports],sec_data_lazy,'',sizeof(pint));
+ current_asmdata.asmlists[al_imports].concat(Tai_symbol.Create(l1,0));
+ current_asmdata.asmlists[al_imports].concat(tai_directive.create(asd_indirect_symbol,s));
+ current_asmdata.asmlists[al_imports].concat(tai_const.createname('dyld_stub_binding_helper',0));
+ end;
+
+
+ procedure tcgppcgen.a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);
+
+ var
+ ref2, tmpref: treference;
+
+ begin
+ ref2 := ref;
+ fixref(list,ref2);
+ if assigned(ref2.symbol) then
+ begin
+ if target_info.system = system_powerpc_macos then
+ begin
+ if macos_direct_globals then
+ begin
+ reference_reset(tmpref,ref2.alignment);
+ tmpref.offset := ref2.offset;
+ tmpref.symbol := ref2.symbol;
+ tmpref.base := NR_NO;
+ list.concat(taicpu.op_reg_reg_ref(A_ADDI,r,NR_RTOC,tmpref));
+ end
+ else
+ begin
+ reference_reset(tmpref,ref2.alignment);
+ tmpref.symbol := ref2.symbol;
+ tmpref.offset := 0;
+ tmpref.base := NR_RTOC;
+ list.concat(taicpu.op_reg_ref(A_LWZ,r,tmpref));
+
+ if ref2.offset <> 0 then
+ begin
+ reference_reset(tmpref,ref2.alignment);
+ tmpref.offset := ref2.offset;
+ tmpref.base:= r;
+ list.concat(taicpu.op_reg_ref(A_LA,r,tmpref));
+ end;
+ end;
+
+ if ref2.base <> NR_NO then
+ list.concat(taicpu.op_reg_reg_reg(A_ADD,r,r,ref2.base));
+
+ //list.concat(tai_comment.create(strpnew('*** a_loadaddr_ref_reg')));
+ end
+ else
+ begin
+
+ { add the symbol's value to the base of the reference, and if the }
+ { reference doesn't have a base, create one }
+ reference_reset(tmpref,ref2.alignment);
+ tmpref.offset := ref2.offset;
+ tmpref.symbol := ref2.symbol;
+ tmpref.relsymbol := ref2.relsymbol;
+ tmpref.refaddr := addr_higha;
+ if ref2.base<> NR_NO then
+ begin
+ list.concat(taicpu.op_reg_reg_ref(A_ADDIS,r,
+ ref2.base,tmpref));
+ end
+ else
+ list.concat(taicpu.op_reg_ref(A_LIS,r,tmpref));
+ tmpref.base := NR_NO;
+ tmpref.refaddr := addr_low;
+ { can be folded with one of the next instructions by the }
+ { optimizer probably }
+ list.concat(taicpu.op_reg_reg_ref(A_ADDI,r,r,tmpref));
+ end
+ end
+ else if ref2.offset <> 0 Then
+ if ref2.base <> NR_NO then
+ a_op_const_reg_reg(list,OP_ADD,OS_ADDR,ref2.offset,ref2.base,r)
+ { FixRef makes sure that "(ref.index <> R_NO) and (ref.offset <> 0)" never}
+ { occurs, so now only ref.offset has to be loaded }
+ else
+ a_load_const_reg(list,OS_ADDR,ref2.offset,r)
+ else if ref2.index <> NR_NO Then
+ list.concat(taicpu.op_reg_reg_reg(A_ADD,r,ref2.base,ref2.index))
+ else if (ref2.base <> NR_NO) and
+ (r <> ref2.base) then
+ a_load_reg_reg(list,OS_ADDR,OS_ADDR,ref2.base,r)
+ else
+ list.concat(taicpu.op_reg_const(A_LI,r,0));
+ end;
+
+
+
+ { calling a procedure by address }
+ procedure tcgppcgen.a_call_reg(list : TAsmList;reg: tregister);
+ begin
+ list.concat(taicpu.op_reg(A_MTCTR,reg));
+ list.concat(taicpu.op_none(A_BCTRL));
+ include(current_procinfo.flags,pi_do_call);
+ end;
+
+
+ procedure tcgppcgen.a_load_reg_ref(list: TAsmList; fromsize, tosize: TCGSize;
+ reg: tregister; const ref: treference);
+
+ const
+ StoreInstr: array[OS_8..OS_INT, boolean, boolean] of TAsmOp =
+ { indexed? updating?}
+ (((A_STB, A_STBU), (A_STBX, A_STBUX)),
+ ((A_STH, A_STHU), (A_STHX, A_STHUX)),
+ ((A_STW, A_STWU), (A_STWX, A_STWUX))
+{$ifdef cpu64bitalu}
+ ,
+ ((A_STD, A_STDU), (A_STDX, A_STDUX))
+{$endif cpu64bitalu}
+ );
+ var
+ ref2: TReference;
+ tmpreg: tregister;
+ op: TAsmOp;
+ begin
+ if not (fromsize in [OS_8..OS_INT,OS_S8..OS_SINT]) then
+ internalerror(2002090904);
+ if not (tosize in [OS_8..OS_INT,OS_S8..OS_SINT]) then
+ internalerror(2002090905);
+
+ if tosize in [OS_S8..OS_SINT] then
+ { storing is the same for signed and unsigned values }
+ tosize := tcgsize(ord(tosize) - (ord(OS_S8) - ord(OS_8)));
+
+ ref2 := ref;
+ fixref(list, ref2);
+
+ op := storeinstr[tcgsize2unsigned[tosize], ref2.index <> NR_NO, false];
+ a_load_store(list, op, reg, ref2);
+ end;
+
+
+
+ procedure tcgppcgen.a_loadfpu_reg_reg(list: TAsmList; fromsize, tosize: tcgsize; reg1, reg2: tregister);
+
+ var
+ op: tasmop;
+ instr: taicpu;
+ begin
+ if not(fromsize in [OS_F32,OS_F64]) or
+ not(tosize in [OS_F32,OS_F64]) then
+ internalerror(2006123110);
+ if (tosize < fromsize) then
+ op:=A_FRSP
+ else
+ op:=A_FMR;
+ instr := taicpu.op_reg_reg(op,reg2,reg1);
+ list.concat(instr);
+ if (op = A_FMR) then
+ rg[R_FPUREGISTER].add_move_instruction(instr);
+ end;
+
+
+ procedure tcgppcgen.a_loadfpu_ref_reg(list: TAsmList; fromsize, tosize: tcgsize; const ref: treference; reg: tregister);
+
+ const
+ FpuLoadInstr: Array[OS_F32..OS_F64,boolean, boolean] of TAsmOp =
+ { indexed? updating?}
+ (((A_LFS,A_LFSU),(A_LFSX,A_LFSUX)),
+ ((A_LFD,A_LFDU),(A_LFDX,A_LFDUX)));
+ var
+ op: tasmop;
+ ref2: treference;
+
+ begin
+ if not(fromsize in [OS_F32,OS_F64]) or
+ not(tosize in [OS_F32,OS_F64]) then
+ internalerror(200201121);
+ ref2 := ref;
+ fixref(list,ref2);
+ op := fpuloadinstr[fromsize,ref2.index <> NR_NO,false];
+ a_load_store(list,op,reg,ref2);
+ if (fromsize > tosize) then
+ a_loadfpu_reg_reg(list,fromsize,tosize,reg,reg);
+ end;
+
+
+ procedure tcgppcgen.a_loadfpu_reg_ref(list: TAsmList; fromsize, tosize: tcgsize; reg: tregister; const ref: treference);
+
+ const
+ FpuStoreInstr: Array[OS_F32..OS_F64,boolean, boolean] of TAsmOp =
+ { indexed? updating?}
+ (((A_STFS,A_STFSU),(A_STFSX,A_STFSUX)),
+ ((A_STFD,A_STFDU),(A_STFDX,A_STFDUX)));
+ var
+ op: tasmop;
+ ref2: treference;
+ reg2: tregister;
+
+ begin
+ if not(fromsize in [OS_F32,OS_F64]) or
+ not(tosize in [OS_F32,OS_F64]) then
+ internalerror(200201122);
+ ref2 := ref;
+ fixref(list,ref2);
+ op := fpustoreinstr[tosize,ref2.index <> NR_NO,false];
+
+ { some PPCs have a bug whereby storing a double to memory }
+ { as single corrupts the value -> convert double to single }
+ { first (bug confirmed on some G4s, but not on G5s) }
+ if (tosize < fromsize) and
+ (current_settings.cputype < cpu_PPC970) then
+ begin
+ reg2:=getfpuregister(list,tosize);
+ a_loadfpu_reg_reg(list,fromsize,tosize,reg,reg2);
+ reg:=reg2;
+ end;
+ a_load_store(list,op,reg,ref2);
+ end;
+
+
+ procedure tcgppcgen.g_stackpointer_alloc(list : TAsmList;localsize : longint);
+ begin
+ Comment(V_Error,'tcgppcgen.g_stackpointer_alloc method not implemented');
+ end;
+
+ procedure tcgppcgen.a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; size: TCGSize; src, dst: TRegister);
+ begin
+ Comment(V_Error,'tcgppcgen.a_bit_scan_reg_reg method not implemented');
+ end;
+
+ procedure tcgppcgen.a_load_subsetref_regs_noindex(list: TAsmList; subsetsize: tcgsize; loadbitsize: byte; const sref: tsubsetreference; valuereg, extra_value_reg: tregister);
+ var
+ fromsreg, tosreg: tsubsetregister;
+ restbits: byte;
+ begin
+ restbits := (sref.bitlen - (loadbitsize - sref.startbit));
+ if (subsetsize in [OS_S8..OS_S128]) then
+ begin
+ { sign extend }
+ a_op_const_reg(list,OP_SHL,OS_INT,AIntBits-loadbitsize+sref.startbit,valuereg);
+ a_op_const_reg(list,OP_SAR,OS_INT,AIntBits-sref.bitlen,valuereg);
+ end
+ else
+ begin
+ a_op_const_reg(list,OP_SHL,OS_INT,restbits,valuereg);
+ { mask other bits }
+ if (sref.bitlen <> AIntBits) then
+ a_op_const_reg(list,OP_AND,OS_INT,(aword(1) shl sref.bitlen)-1,valuereg);
+ end;
+ { use subsetreg routine, it may have been overridden with an optimized version }
+ fromsreg.subsetreg := extra_value_reg;
+ fromsreg.subsetregsize := OS_INT;
+ { subsetregs always count bits from right to left }
+ fromsreg.startbit := loadbitsize-restbits;
+ fromsreg.bitlen := restbits;
+
+ tosreg.subsetreg := valuereg;
+ tosreg.subsetregsize := OS_INT;
+ tosreg.startbit := 0;
+ tosreg.bitlen := restbits;
+
+ a_load_subsetreg_subsetreg(list,subsetsize,subsetsize,fromsreg,tosreg);
+ end;
+
+
+ procedure tcgppcgen.g_overflowcheck(list: TAsmList; const l: tlocation; def: tdef);
+ var
+ hl : tasmlabel;
+ flags : TResFlags;
+ begin
+ if not(cs_check_overflow in current_settings.localswitches) then
+ exit;
+ current_asmdata.getjumplabel(hl);
+ if not ((def.typ=pointerdef) or
+ ((def.typ=orddef) and
+ (torddef(def).ordtype in [u64bit,u16bit,u32bit,u8bit,uchar,
+ pasbool8,pasbool16,pasbool32,pasbool64]))) then
+ begin
+ if (current_settings.optimizecputype >= cpu_ppc970) or
+ (current_settings.cputype >= cpu_ppc970) then
+ begin
+ { ... instructions setting overflow flag ...
+ mfxerf R0
+ mtcrf 128, R0
+ ble cr0, label }
+ list.concat(taicpu.op_reg(A_MFXER, NR_R0));
+ list.concat(taicpu.op_const_reg(A_MTCRF, 128, NR_R0));
+ flags.cr := RS_CR0;
+ flags.flag := F_LE;
+ a_jmp_flags(list, flags, hl);
+ end
+ else
+ begin
+ list.concat(taicpu.op_reg(A_MCRXR,NR_CR7));
+ a_jmp(list,A_BC,C_NO,7,hl)
+ end;
+ end
+ else
+ a_jmp_cond(list,OC_AE,hl);
+ a_call_name(list,'FPC_OVERFLOW',false);
+ a_label(list,hl);
+ end;
+
+
+ procedure tcgppcgen.g_profilecode(list: TAsmList);
+ var
+ paraloc1 : tcgpara;
+ begin
+ if (target_info.system in [system_powerpc_darwin]) then
+ begin
+ paraloc1.init;
+ paramanager.getintparaloc(pocall_cdecl,1,paraloc1);
+ a_load_reg_cgpara(list,OS_ADDR,NR_R0,paraloc1);
+ paramanager.freecgpara(list,paraloc1);
+ paraloc1.done;
+ allocallcpuregisters(list);
+ a_call_name(list,'mcount',false);
+ deallocallcpuregisters(list);
+ a_reg_dealloc(list,NR_R0);
+ end;
+ end;
+
+
+ procedure tcgppcgen.a_jmp_cond(list : TAsmList;cond : TOpCmp; l: tasmlabel);
+ begin
+ a_jmp(list,A_BC,TOpCmp2AsmCond[cond],0,l);
+ end;
+
+
+ procedure tcgppcgen.a_jmp(list: TAsmList; op: tasmop; c: tasmcondflag;
+ crval: longint; l: tasmlabel);
+ var
+ p: taicpu;
+
+ begin
+ p := taicpu.op_sym(op,l);
+ if op <> A_B then
+ create_cond_norm(c,crval,p.condition);
+ p.is_jmp := true;
+ list.concat(p)
+ end;
+
+
+
+ procedure tcgppcgen.g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);
+
+ procedure loadvmttor11;
+ var
+ href : treference;
+ begin
+ reference_reset_base(href,NR_R3,0,sizeof(pint));
+ cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_R11);
+ end;
+
+
+ procedure op_onr11methodaddr;
+ var
+ href : treference;
+ begin
+ if (procdef.extnumber=$ffff) then
+ Internalerror(200006139);
+ { call/jmp vmtoffs(%eax) ; method offs }
+ reference_reset_base(href,NR_R11,tobjectdef(procdef.struct).vmtmethodoffset(procdef.extnumber),sizeof(pint));
+ if hasLargeOffset(href) then
+ begin
+{$ifdef cpu64}
+ if (longint(href.offset) <> href.offset) then
+ { add support for offsets > 32 bit }
+ internalerror(200510201);
+{$endif cpu64}
+ list.concat(taicpu.op_reg_reg_const(A_ADDIS,NR_R11,NR_R11,
+ smallint((href.offset shr 16)+ord(smallint(href.offset and $ffff) < 0))));
+ href.offset := smallint(href.offset and $ffff);
+ end;
+ a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_R11);
+ if (target_info.system = system_powerpc64_linux) then
+ begin
+ reference_reset_base(href, NR_R11, 0, sizeof(pint));
+ a_load_ref_reg(list, OS_ADDR, OS_ADDR, href, NR_R11);
+ end;
+ list.concat(taicpu.op_reg(A_MTCTR,NR_R11));
+ list.concat(taicpu.op_none(A_BCTR));
+ if (target_info.system = system_powerpc64_linux) then
+ list.concat(taicpu.op_none(A_NOP));
+ end;
+
+
+ var
+ make_global : boolean;
+ begin
+ if not(procdef.proctypeoption in [potype_function,potype_procedure]) then
+ Internalerror(200006137);
+ if not assigned(procdef.struct) or
+ (procdef.procoptions*[po_classmethod, po_staticmethod,
+ po_methodpointer, po_interrupt, po_iocheck]<>[]) then
+ Internalerror(200006138);
+ if procdef.owner.symtabletype<>ObjectSymtable then
+ Internalerror(200109191);
+
+ make_global:=false;
+ if (not current_module.is_unit) or
+ create_smartlink or
+ (procdef.owner.defowner.owner.symtabletype=globalsymtable) then
+ make_global:=true;
+
+ if make_global then
+ List.concat(Tai_symbol.Createname_global(labelname,AT_FUNCTION,0))
+ else
+ List.concat(Tai_symbol.Createname(labelname,AT_FUNCTION,0));
+
+ { set param1 interface to self }
+ g_adjust_self_value(list,procdef,ioffset);
+
+ { case 4 }
+ if (po_virtualmethod in procdef.procoptions) and
+ not is_objectpascal_helper(procdef.struct) then
+ begin
+ loadvmttor11;
+ op_onr11methodaddr;
+ end
+ { case 0 }
+ else
+ case target_info.system of
+ system_powerpc_darwin,
+ system_powerpc64_darwin:
+ list.concat(taicpu.op_sym(A_B,get_darwin_call_stub(procdef.mangledname,false)));
+ system_powerpc64_linux:
+ {$note ts:todo add GOT change?? - think not needed :) }
+ list.concat(taicpu.op_sym(A_B,current_asmdata.RefAsmSymbol('.' + procdef.mangledname)));
+ else
+ list.concat(taicpu.op_sym(A_B,current_asmdata.RefAsmSymbol(procdef.mangledname)))
+ end;
+ List.concat(Tai_symbol_end.Createname(labelname));
+ end;
+
+
+ function tcgppcgen.load_got_symbol(list: TAsmList; symbol : string) : tregister;
+ var
+ l: tasmsymbol;
+ ref: treference;
+ begin
+ if (target_info.system <> system_powerpc64_linux) then
+ internalerror(2007102010);
+ l:=current_asmdata.getasmsymbol(symbol);
+ reference_reset_symbol(ref,l,0,sizeof(pint));
+ ref.base := NR_R2;
+ ref.refaddr := addr_pic;
+
+ result := rg[R_INTREGISTER].getregister(list, R_SUBWHOLE);
+ {$IFDEF EXTDEBUG}
+ list.concat(tai_comment.create(strpnew('loading got reference for ' + symbol)));
+ {$ENDIF EXTDEBUG}
+ // cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,ref,result);
+
+{$ifdef cpu64bitaddr}
+ list.concat(taicpu.op_reg_ref(A_LD, result, ref));
+{$else cpu64bitaddr}
+ list.concat(taicpu.op_reg_ref(A_LWZ, result, ref));
+{$endif cpu64bitaddr}
+ end;
+
+
+ function tcgppcgen.fixref(list: TAsmList; var ref: treference): boolean;
+ var
+ tmpreg: tregister;
+ begin
+ result := false;
+
+ { Avoid recursion. }
+ if (ref.refaddr = addr_pic) then
+ exit;
+
+ {$IFDEF EXTDEBUG}
+ list.concat(tai_comment.create(strpnew('fixref0 ' + ref2string(ref))));
+ {$ENDIF EXTDEBUG}
+ if (target_info.system in [system_powerpc_darwin,system_powerpc64_darwin]) and
+ assigned(ref.symbol) and
+ not assigned(ref.relsymbol) and
+ ((ref.symbol.bind in [AB_EXTERNAL,AB_WEAK_EXTERNAL]) or
+ (cs_create_pic in current_settings.moduleswitches))then
+ begin
+ if (ref.symbol.bind in [AB_EXTERNAL,AB_WEAK_EXTERNAL]) or
+ ((cs_create_pic in current_settings.moduleswitches) and
+ (ref.symbol.bind in [AB_COMMON,AB_GLOBAL,AB_PRIVATE_EXTERN])) then
+ begin
+ tmpreg := g_indirect_sym_load(list,ref.symbol.name,ref.symbol.bind=AB_WEAK_EXTERNAL);
+ ref.symbol:=nil;
+ end
+ else
+ begin
+ include(current_procinfo.flags,pi_needs_got);
+ tmpreg := current_procinfo.got;
+ if assigned(ref.relsymbol) then
+ internalerror(2007093501);
+ ref.relsymbol := current_procinfo.CurrGOTLabel;
+ end;
+ if (ref.base = NR_NO) then
+ ref.base := tmpreg
+ else if (ref.index = NR_NO) then
+ ref.index := tmpreg
+ else
+ begin
+ list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.base,tmpreg));
+ ref.base := tmpreg;
+ end;
+ end;
+
+ { if we have to create PIC, add the symbol to the TOC/GOT }
+ if (target_info.system = system_powerpc64_linux) and
+ (cs_create_pic in current_settings.moduleswitches) and
+ (assigned(ref.symbol)) then
+ begin
+ tmpreg := load_got_symbol(list, ref.symbol.name);
+ if (ref.base = NR_NO) then
+ ref.base := tmpreg
+ else if (ref.index = NR_NO) then
+ ref.index := tmpreg
+ else begin
+ a_op_reg_reg_reg(list, OP_ADD, OS_ADDR, ref.base, tmpreg, tmpreg);
+ ref.base := tmpreg;
+ end;
+ ref.symbol := nil;
+ {$IFDEF EXTDEBUG}
+ list.concat(tai_comment.create(strpnew('fixref-pic ' + ref2string(ref))));
+ {$ENDIF EXTDEBUG}
+ end;
+
+ if (ref.base = NR_NO) then
+ begin
+ ref.base := ref.index;
+ ref.index := NR_NO;
+ end;
+ if (ref.base <> NR_NO) then
+ begin
+ if (ref.index <> NR_NO) and
+ ((ref.offset <> 0) or assigned(ref.symbol)) then
+ begin
+ result := true;
+ tmpreg := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
+ list.concat(taicpu.op_reg_reg_reg(
+ A_ADD,tmpreg,ref.base,ref.index));
+ ref.index := NR_NO;
+ ref.base := tmpreg;
+ end
+ end;
+ if (ref.index <> NR_NO) and
+ (assigned(ref.symbol) or
+ (ref.offset <> 0)) then
+ internalerror(200208102);
+ {$IFDEF EXTDEBUG}
+ list.concat(tai_comment.create(strpnew('fixref1 ' + ref2string(ref))));
+ {$ENDIF EXTDEBUG}
+ end;
+
+
+ procedure tcgppcgen.a_load_store(list:TAsmList;op: tasmop;reg:tregister;
+ ref: treference);
+
+ var
+ tmpreg: tregister;
+ tmpref: treference;
+ largeOffset: Boolean;
+
+ begin
+ tmpreg := NR_NO;
+ largeOffset:= hasLargeOffset(ref);
+
+ if target_info.system = system_powerpc_macos then
+ begin
+
+ if assigned(ref.symbol) then
+ begin {Load symbol's value}
+ tmpreg := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
+
+ reference_reset(tmpref,sizeof(pint));
+ tmpref.symbol := ref.symbol;
+ tmpref.base := NR_RTOC;
+
+ if macos_direct_globals then
+ list.concat(taicpu.op_reg_ref(A_LA,tmpreg,tmpref))
+ else
+ list.concat(taicpu.op_reg_ref(A_LWZ,tmpreg,tmpref));
+ end;
+
+ if largeOffset then
+ begin {Add hi part of offset}
+ reference_reset(tmpref,ref.alignment);
+
+ if Smallint(Lo(ref.offset)) < 0 then
+ tmpref.offset := Hi(ref.offset) + 1 {Compensate when lo part is negative}
+ else
+ tmpref.offset := Hi(ref.offset);
+
+ if (tmpreg <> NR_NO) then
+ list.concat(taicpu.op_reg_reg_ref(A_ADDIS,tmpreg, tmpreg,tmpref))
+ else
+ begin
+ tmpreg := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
+ list.concat(taicpu.op_reg_ref(A_LIS,tmpreg,tmpref));
+ end;
+ end;
+
+ if (tmpreg <> NR_NO) then
+ begin
+ {Add content of base register}
+ if ref.base <> NR_NO then
+ list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,
+ ref.base,tmpreg));
+
+ {Make ref ready to be used by op}
+ ref.symbol:= nil;
+ ref.base:= tmpreg;
+ if largeOffset then
+ ref.offset := Smallint(Lo(ref.offset));
+
+ list.concat(taicpu.op_reg_ref(op,reg,ref));
+ //list.concat(tai_comment.create(strpnew('*** a_load_store indirect global')));
+ end
+ else
+ list.concat(taicpu.op_reg_ref(op,reg,ref));
+ end
+ else {if target_info.system <> system_powerpc_macos}
+ begin
+ if assigned(ref.symbol) or
+ largeOffset then
+ begin
+ tmpreg := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
+ reference_reset(tmpref,ref.alignment);
+ tmpref.symbol := ref.symbol;
+ tmpref.relsymbol := ref.relsymbol;
+ tmpref.offset := ref.offset;
+ tmpref.refaddr := addr_higha;
+ if ref.base <> NR_NO then
+ list.concat(taicpu.op_reg_reg_ref(A_ADDIS,tmpreg,
+ ref.base,tmpref))
+ else
+ list.concat(taicpu.op_reg_ref(A_LIS,tmpreg,tmpref));
+ ref.base := tmpreg;
+ ref.refaddr := addr_low;
+ list.concat(taicpu.op_reg_ref(op,reg,ref));
+ end
+ else
+ list.concat(taicpu.op_reg_ref(op,reg,ref));
+ end;
+ end;
+
+
+end.
+
diff --git a/closures/compiler/ppcgen/ngppcadd.pas b/closures/compiler/ppcgen/ngppcadd.pas
new file mode 100644
index 0000000000..97895c59c3
--- /dev/null
+++ b/closures/compiler/ppcgen/ngppcadd.pas
@@ -0,0 +1,543 @@
+{
+ Copyright (c) 2000-2006 by Florian Klaempfl and Jonas Maebe
+
+ Code generation for add nodes on the PowerPC (32 and 64 bit generic)
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+
+unit ngppcadd;
+
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,nadd,ncgadd,cpubase;
+
+ type
+ tgenppcaddnode = class(tcgaddnode)
+ function pass_1: tnode; override;
+ protected
+ procedure pass_left_and_right;
+ procedure load_left_right(cmpop, load_constants: boolean);
+ function getresflags : tresflags;
+ procedure emit_compare(unsigned: boolean); virtual; abstract;
+ procedure second_addfloat;override;
+ procedure second_addboolean;override;
+ procedure second_addsmallset;override;
+ end;
+
+
+implementation
+
+{*****************************************************************************
+ Pass 1
+*****************************************************************************}
+
+ uses
+ globtype,systems,
+ cutils,verbose,globals,
+ symconst,symdef,paramgr,
+ aasmbase,aasmtai,aasmdata,aasmcpu,defutil,htypechk,
+ cgbase,cpuinfo,pass_1,pass_2,regvars,
+ cpupara,cgcpu,cgutils,procinfo,
+ ncon,nset,
+ ncgutil,tgobj,rgobj,rgcpu,cgobj;
+
+
+{*****************************************************************************
+ Pass 1
+*****************************************************************************}
+
+ function tgenppcaddnode.pass_1: tnode;
+ begin
+ typecheckpass(left);
+ if (nodetype in [equaln,unequaln]) and
+ (left.resultdef.typ = orddef) and
+ is_64bit(left.resultdef) then
+ begin
+ result := nil;
+ firstpass(left);
+ firstpass(right);
+ expectloc := LOC_FLAGS;
+ exit;
+ end;
+ result := inherited pass_1;
+ end;
+
+{*****************************************************************************
+ Helpers
+*****************************************************************************}
+
+ procedure tgenppcaddnode.pass_left_and_right;
+ begin
+ { calculate the operator which is more difficult }
+ firstcomplex(self);
+
+ { in case of constant put it to the left }
+ if (left.nodetype=ordconstn) then
+ swapleftright;
+
+ secondpass(left);
+ secondpass(right);
+ end;
+
+
+ procedure tgenppcaddnode.load_left_right(cmpop, load_constants: boolean);
+
+ procedure load_node(var n: tnode);
+ begin
+ case n.location.loc of
+ LOC_REGISTER,
+ LOC_CREGISTER:
+ ;
+ LOC_REFERENCE,LOC_CREFERENCE:
+ location_force_reg(current_asmdata.CurrAsmList,n.location,def_cgsize(n.resultdef),false);
+ LOC_CONSTANT:
+ begin
+ if load_constants then
+ location_force_reg(current_asmdata.CurrAsmList,n.location,def_cgsize(n.resultdef),false);
+ end;
+ else
+ location_force_reg(current_asmdata.CurrAsmList,n.location,def_cgsize(n.resultdef),false);
+ end;
+ end;
+
+ begin
+ load_node(left);
+ load_node(right);
+ if not(cmpop) then
+ begin
+ location.register := cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+{$ifndef cpu64bitalu}
+ if is_64bit(resultdef) then
+ location.register64.reghi := cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+{$endif not cpu64bitalu}
+ end;
+ end;
+
+
+ function tgenppcaddnode.getresflags : tresflags;
+ begin
+ if (left.resultdef.typ <> floatdef) then
+ result.cr := RS_CR0
+ else
+ result.cr := RS_CR1;
+ case nodetype of
+ equaln : result.flag:=F_EQ;
+ unequaln : result.flag:=F_NE;
+ else
+ if nf_swapped in flags then
+ case nodetype of
+ ltn : result.flag:=F_GT;
+ lten : result.flag:=F_GE;
+ gtn : result.flag:=F_LT;
+ gten : result.flag:=F_LE;
+ end
+ else
+ case nodetype of
+ ltn : result.flag:=F_LT;
+ lten : result.flag:=F_LE;
+ gtn : result.flag:=F_GT;
+ gten : result.flag:=F_GE;
+ end;
+ end
+ end;
+
+
+{*****************************************************************************
+ AddBoolean
+*****************************************************************************}
+
+ procedure tgenppcaddnode.second_addboolean;
+ var
+ cgop : TOpCg;
+ cgsize : TCgSize;
+ cmpop,
+ isjump : boolean;
+ otl,ofl : tasmlabel;
+ begin
+ { calculate the operator which is more difficult }
+ firstcomplex(self);
+
+ cmpop:=false;
+ if (torddef(left.resultdef).ordtype in [pasbool8,bool8bit]) or
+ (torddef(right.resultdef).ordtype in [pasbool8,bool8bit]) then
+ cgsize:=OS_8
+ else
+ if (torddef(left.resultdef).ordtype in [pasbool16,bool16bit]) or
+ (torddef(right.resultdef).ordtype in [pasbool16,bool16bit]) then
+ cgsize:=OS_16
+ else
+ cgsize:=OS_32;
+
+ if ((cs_full_boolean_eval in current_settings.localswitches) and
+ not(nf_short_bool in flags)) or
+ (nodetype in [unequaln,ltn,lten,gtn,gten,equaln,xorn]) then
+ begin
+ if left.nodetype in [ordconstn,realconstn] then
+ swapleftright;
+
+ isjump:=(left.expectloc=LOC_JUMP);
+ if isjump then
+ begin
+ otl:=current_procinfo.CurrTrueLabel;
+ current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
+ ofl:=current_procinfo.CurrFalseLabel;
+ current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel);
+ end;
+ secondpass(left);
+ if left.location.loc in [LOC_FLAGS,LOC_JUMP] then
+ location_force_reg(current_asmdata.CurrAsmList,left.location,cgsize,false);
+ if isjump then
+ begin
+ current_procinfo.CurrTrueLabel:=otl;
+ current_procinfo.CurrFalseLabel:=ofl;
+ end
+ else if left.location.loc=LOC_JUMP then
+ internalerror(2003122901);
+
+ isjump:=(right.expectloc=LOC_JUMP);
+ if isjump then
+ begin
+ otl:=current_procinfo.CurrTrueLabel;
+ current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
+ ofl:=current_procinfo.CurrFalseLabel;
+ current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel);
+ end;
+ secondpass(right);
+ if right.location.loc in [LOC_FLAGS,LOC_JUMP] then
+ location_force_reg(current_asmdata.CurrAsmList,right.location,cgsize,false);
+ if isjump then
+ begin
+ current_procinfo.CurrTrueLabel:=otl;
+ current_procinfo.CurrFalseLabel:=ofl;
+ end
+ else if right.location.loc=LOC_JUMP then
+ internalerror(200312292);
+
+ cmpop := nodetype in [ltn,lten,gtn,gten,equaln,unequaln];
+
+ { set result location }
+ if not cmpop then
+ location_reset(location,LOC_REGISTER,def_cgsize(resultdef))
+ else
+ location_reset(location,LOC_FLAGS,OS_NO);
+
+ load_left_right(cmpop,false);
+
+ if (left.location.loc = LOC_CONSTANT) then
+ swapleftright;
+
+ { compare the }
+ case nodetype of
+ ltn,lten,gtn,gten,
+ equaln,unequaln :
+ begin
+ if (right.location.loc <> LOC_CONSTANT) then
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CMPLW,
+ left.location.register,right.location.register))
+ else
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_CMPLWI,
+ left.location.register,longint(right.location.value)));
+ location.resflags := getresflags;
+ end;
+ else
+ begin
+ case nodetype of
+ xorn :
+ cgop:=OP_XOR;
+ orn :
+ cgop:=OP_OR;
+ andn :
+ cgop:=OP_AND;
+ else
+ internalerror(200203247);
+ end;
+
+ if right.location.loc <> LOC_CONSTANT then
+ cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,cgop,OS_INT,
+ left.location.register,right.location.register,
+ location.register)
+ else
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,cgop,OS_INT,
+ right.location.value,left.location.register,
+ location.register);
+ end;
+ end;
+ end
+ else
+ inherited second_addboolean;
+ end;
+
+
+{*****************************************************************************
+ AddFloat
+*****************************************************************************}
+
+ procedure tgenppcaddnode.second_addfloat;
+ var
+ op : TAsmOp;
+ cmpop,
+ singleprec : boolean;
+ begin
+ pass_left_and_right;
+
+ cmpop:=false;
+ singleprec:=tfloatdef(left.resultdef).floattype=s32real;
+ case nodetype of
+ addn :
+ if singleprec then
+ op:=A_FADDS
+ else
+ op:=A_FADD;
+ muln :
+ if singleprec then
+ op:=A_FMULS
+ else
+ op:=A_FMUL;
+ subn :
+ if singleprec then
+ op:=A_FSUBS
+ else
+ op:=A_FSUB;
+ slashn :
+ if singleprec then
+ op:=A_FDIVS
+ else
+ op:=A_FDIV;
+ ltn,lten,gtn,gten,
+ equaln,unequaln :
+ begin
+ op:=A_FCMPO;
+ cmpop:=true;
+ end;
+ else
+ internalerror(200403182);
+ end;
+
+ // get the operands in the correct order, there are no special cases
+ // here, everything is register-based
+ if nf_swapped in flags then
+ swapleftright;
+
+ // put both operands in a register
+ location_force_fpureg(current_asmdata.CurrAsmList,right.location,true);
+ location_force_fpureg(current_asmdata.CurrAsmList,left.location,true);
+
+ // initialize de result
+ if not cmpop then
+ begin
+ location_reset(location,LOC_FPUREGISTER,def_cgsize(resultdef));
+ location.register := cg.getfpuregister(current_asmdata.CurrAsmList,location.size);
+ end
+ else
+ begin
+ location_reset(location,LOC_FLAGS,OS_NO);
+ location.resflags := getresflags;
+ end;
+
+ // emit the actual operation
+ if not cmpop then
+ begin
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(op,
+ location.register,left.location.register,
+ right.location.register))
+ end
+ else
+ begin
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(op,
+ newreg(R_SPECIALREGISTER,location.resflags.cr,R_SUBNONE),left.location.register,right.location.register))
+ end;
+ end;
+
+
+{*****************************************************************************
+ AddSmallSet
+*****************************************************************************}
+
+ procedure tgenppcaddnode.second_addsmallset;
+ var
+ cgop : TOpCg;
+ setbase: aint;
+ tmpreg : tregister;
+ opdone,
+ cmpop : boolean;
+ begin
+ pass_left_and_right;
+
+ { when a setdef is passed, it has to be a smallset }
+ if (not(nf_swapped in flags) and
+ not is_smallset(left.resultdef) or
+ (not is_smallset(right.resultdef) and
+ (right.nodetype<>setelementn))) or
+ ((nf_swapped in flags) and
+ not is_smallset(right.resultdef) or
+ (not is_smallset(left.resultdef) and
+ (left.nodetype<>setelementn))) then
+ internalerror(200203359);
+
+ opdone := false;
+ cmpop:=nodetype in [equaln,unequaln,lten,gten];
+
+ { set result location }
+ if not cmpop then
+ location_reset(location,LOC_REGISTER,def_cgsize(resultdef))
+ else
+ location_reset(location,LOC_FLAGS,OS_NO);
+
+ load_left_right(cmpop,false);
+
+ if not(cmpop) then
+ location.register := cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+
+ if (left.resultdef.typ=setdef) then
+ setbase:=tsetdef(left.resultdef).setbase
+ else
+ setbase:=tsetdef(right.resultdef).setbase;
+ case nodetype of
+ addn :
+ begin
+ if (nf_swapped in flags) and (left.nodetype=setelementn) then
+ swapleftright;
+ { are we adding set elements ? }
+ if right.nodetype=setelementn then
+ begin
+ { no range support for smallsets! }
+ if assigned(tsetelementnode(right).right) then
+ internalerror(43244);
+ if (right.location.loc = LOC_CONSTANT) then
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_OR,OS_INT,
+ aint((aword(1) shl (resultdef.size*8-1)) shr aword(right.location.value-setbase)),
+ left.location.register,location.register)
+ else
+ begin
+ tmpreg := cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+ cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_INT,aint((aword(1) shl (resultdef.size*8-1))),tmpreg);
+ register_maybe_adjust_setbase(current_asmdata.CurrAsmList,right.location,setbase);
+ cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_SHR,OS_INT,
+ right.location.register,tmpreg);
+ if left.location.loc <> LOC_CONSTANT then
+ cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,OP_OR,OS_INT,tmpreg,
+ left.location.register,location.register)
+ else
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_OR,OS_INT,
+ left.location.value,tmpreg,location.register);
+ end;
+ opdone := true;
+ end
+ else
+ cgop := OP_OR;
+ end;
+ symdifn :
+ cgop:=OP_XOR;
+ muln :
+ cgop:=OP_AND;
+ subn :
+ begin
+ cgop:=OP_AND;
+ if (not(nf_swapped in flags)) then
+ if (right.location.loc=LOC_CONSTANT) then
+ right.location.value := not(right.location.value)
+ else
+ opdone := true
+ else if (left.location.loc=LOC_CONSTANT) then
+ left.location.value := not(left.location.value)
+ else
+ begin
+ swapleftright;
+ opdone := true;
+ end;
+ if opdone then
+ begin
+ if left.location.loc = LOC_CONSTANT then
+ begin
+ tmpreg := cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+ cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_INT,
+ left.location.value,tmpreg);
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_ANDC,
+ location.register,tmpreg,right.location.register));
+ end
+ else
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_ANDC,
+ location.register,left.location.register,
+ right.location.register));
+ end;
+ end;
+ equaln,
+ unequaln :
+ begin
+ emit_compare(true);
+ opdone := true;
+ end;
+ lten,gten:
+ begin
+ If (not(nf_swapped in flags) and
+ (nodetype = lten)) or
+ ((nf_swapped in flags) and
+ (nodetype = gten)) then
+ swapleftright;
+ // now we have to check whether left >= right
+ tmpreg := cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+ if left.location.loc = LOC_CONSTANT then
+ begin
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_AND,OS_INT,
+ not(left.location.value),right.location.register,tmpreg);
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_CMPWI,tmpreg,0));
+ // the two instructions above should be folded together by
+ // the peepholeoptimizer
+ end
+ else
+ begin
+ if right.location.loc = LOC_CONSTANT then
+ begin
+ cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_INT,
+ right.location.value,tmpreg);
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_ANDC_,tmpreg,
+ tmpreg,left.location.register));
+ end
+ else
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_ANDC_,tmpreg,
+ right.location.register,left.location.register));
+ end;
+ location.resflags.cr := RS_CR0;
+ location.resflags.flag := F_EQ;
+ opdone := true;
+ end;
+ else
+ internalerror(2002072701);
+ end;
+
+ if not opdone then
+ begin
+ // these are all commutative operations
+ if (left.location.loc = LOC_CONSTANT) then
+ swapleftright;
+ if (right.location.loc = LOC_CONSTANT) then
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,cgop,OS_INT,
+ right.location.value,left.location.register,
+ location.register)
+ else
+ cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,cgop,OS_INT,
+ right.location.register,left.location.register,
+ location.register);
+ end;
+ end;
+
+end.
diff --git a/closures/compiler/ppcgen/ngppccnv.pas b/closures/compiler/ppcgen/ngppccnv.pas
new file mode 100644
index 0000000000..f08031efb3
--- /dev/null
+++ b/closures/compiler/ppcgen/ngppccnv.pas
@@ -0,0 +1,208 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate PowerPC assembler for type converting nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit ngppccnv;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,ncnv,ncgcnv;
+
+ type
+ tgenppctypeconvnode = class(tcgtypeconvnode)
+ protected
+ { procedure second_int_to_int;override; }
+ { procedure second_string_to_string;override; }
+ { procedure second_cstring_to_pchar;override; }
+ { procedure second_string_to_chararray;override; }
+ { procedure second_array_to_pointer;override; }
+ { function first_int_to_real: tnode; override; }
+ { procedure second_pointer_to_array;override; }
+ { procedure second_chararray_to_string;override; }
+ { procedure second_char_to_string;override; }
+ { procedure second_int_to_real;override; }
+ { procedure second_real_to_real;override; }
+ { procedure second_cord_to_pointer;override; }
+ { procedure second_proc_to_procvar;override; }
+ { procedure second_bool_to_int;override; }
+ procedure second_int_to_bool;override;
+ { procedure second_load_smallset;override; }
+ { procedure second_ansistring_to_pchar;override; }
+ { procedure second_pchar_to_string;override; }
+ { procedure second_class_to_intf;override; }
+ { procedure second_char_to_char;override; }
+ end;
+
+
+implementation
+
+ uses
+ verbose,globtype,globals,systems,
+ symconst,symdef,aasmbase,aasmtai,aasmdata,
+ defutil,
+ cgbase,cgutils,pass_1,pass_2,
+ ncgutil,procinfo,
+ cpubase,aasmcpu,
+ rgobj,tgobj,cgobj;
+
+
+ procedure tgenppctypeconvnode.second_int_to_bool;
+ var
+ hreg1,
+ hreg2 : tregister;
+{$ifndef cpu64bitalu}
+ href : treference;
+{$endif not cpu64bitalu}
+ resflags : tresflags;
+ opsize : tcgsize;
+ hlabel, oldTrueLabel, oldFalseLabel : tasmlabel;
+ newsize : tcgsize;
+ begin
+ oldTrueLabel:=current_procinfo.CurrTrueLabel;
+ oldFalseLabel:=current_procinfo.CurrFalseLabel;
+ current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
+ current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel);
+ secondpass(left);
+ if codegenerror then
+ exit;
+
+ { Explicit typecasts from any ordinal type to a boolean type }
+ { must not change the ordinal value }
+ if (nf_explicit in flags) and
+ not(left.location.loc in [LOC_FLAGS,LOC_JUMP]) then
+ begin
+ location_copy(location,left.location);
+ newsize:=def_cgsize(resultdef);
+ { change of size? change sign only if location is LOC_(C)REGISTER? Then we have to sign/zero-extend }
+ if (tcgsize2size[newsize]<>tcgsize2size[left.location.size]) or
+ ((newsize<>left.location.size) and (location.loc in [LOC_REGISTER,LOC_CREGISTER])) then
+ location_force_reg(current_asmdata.CurrAsmList,location,newsize,true)
+ else
+ location.size:=newsize;
+ current_procinfo.CurrTrueLabel:=oldTrueLabel;
+ current_procinfo.CurrFalseLabel:=oldFalseLabel;
+ exit;
+ end;
+
+ location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
+ opsize := def_cgsize(left.resultdef);
+{$ifndef cpu64bitalu}
+ if (opsize in [OS_64,OS_S64]) then
+ opsize:=OS_32;
+{$endif not cpu64bitalu}
+ case left.location.loc of
+ LOC_CREFERENCE,LOC_REFERENCE,LOC_REGISTER,LOC_CREGISTER :
+ begin
+ if left.location.loc in [LOC_CREFERENCE,LOC_REFERENCE] then
+ begin
+ hreg1:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+{$ifndef cpu64bitalu}
+ if left.location.size in [OS_64,OS_S64] then
+ begin
+ cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_INT,OS_INT,left.location.reference,hreg1);
+ hreg2:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+ href:=left.location.reference;
+ inc(href.offset,4);
+ cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_INT,OS_INT,href,hreg2);
+ cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,OP_OR,OS_32,hreg1,hreg2,hreg1);
+ end
+ else
+{$endif not cpu64bitalu}
+ cg.a_load_ref_reg(current_asmdata.CurrAsmList,opsize,opsize,left.location.reference,hreg1);
+ end
+ else
+ begin
+ hreg1:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+{$ifndef cpu64bitalu}
+ if left.location.size in [OS_64,OS_S64] then
+ begin
+ hreg1:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
+ cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,OP_OR,OS_32,left.location.register64.reghi,left.location.register64.reglo,hreg1);
+ end
+ else
+{$endif not cpu64bitalu}
+ cg.a_load_reg_reg(current_asmdata.CurrAsmList,opsize,opsize,left.location.register,hreg1);
+ end;
+ hreg2 := cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+
+ if not(is_cbool(resultdef)) then
+ begin
+ { hreg2:=hreg1-1; carry:=hreg1=0 }
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_const(A_SUBIC,hreg2,hreg1,1));
+ { hreg1:=hreg1-hreg2+carry (= hreg1-(hreg1-1)-carry) }
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SUBFE,hreg1,hreg2,hreg1));
+ end
+ else
+ begin
+ { carry:=hreg1<>0 }
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_const(A_SUBFIC,hreg2,hreg1,0));
+ { hreg1:=hreg1-hreg1-carry }
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SUBFE,hreg1,hreg1,hreg1));
+ end;
+ end;
+ LOC_FLAGS :
+ begin
+ hreg1:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+ resflags:=left.location.resflags;
+ cg.g_flags2reg(current_asmdata.CurrAsmList,location.size,resflags,hreg1);
+ if (is_cbool(resultdef)) then
+ cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_NEG,location.size,hreg1,hreg1);
+ end;
+ LOC_JUMP :
+ begin
+ hreg1:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+ current_asmdata.getjumplabel(hlabel);
+ cg.a_label(current_asmdata.CurrAsmList,current_procinfo.CurrTrueLabel);
+ if not(is_cbool(resultdef)) then
+ cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_INT,1,hreg1)
+ else
+ cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_INT,-1,hreg1);
+ cg.a_jmp_always(current_asmdata.CurrAsmList,hlabel);
+ cg.a_label(current_asmdata.CurrAsmList,current_procinfo.CurrFalseLabel);
+ cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_INT,0,hreg1);
+ cg.a_label(current_asmdata.CurrAsmList,hlabel);
+ end;
+ else
+ internalerror(10062);
+ end;
+{$ifndef cpu64bitalu}
+ if (location.size in [OS_64,OS_S64]) then
+ begin
+ location.register64.reglo:=hreg1;
+ location.register64.reghi:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
+ if (is_cbool(resultdef)) then
+ { reglo is either 0 or -1 -> reghi has to become the same }
+ cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_32,OS_32,location.register64.reglo,location.register64.reghi)
+ else
+ { unsigned }
+ cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_32,0,location.register64.reghi);
+ end
+ else
+{$endif cpu64bitalu}
+ location.register:=hreg1;
+
+ current_procinfo.CurrTrueLabel:=oldTrueLabel;
+ current_procinfo.CurrFalseLabel:=oldFalseLabel;
+ end;
+
+end.
diff --git a/closures/compiler/ppcgen/ngppcinl.pas b/closures/compiler/ppcgen/ngppcinl.pas
new file mode 100644
index 0000000000..78b06e5708
--- /dev/null
+++ b/closures/compiler/ppcgen/ngppcinl.pas
@@ -0,0 +1,237 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate PowerPC32/64 inline nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit ngppcinl;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cpubase,
+ node,ninl,ncginl;
+
+ type
+ tgppcinlinenode = class(tcginlinenode)
+ { first pass override
+ so that the code generator will actually generate
+ these nodes.
+ }
+ function first_sqrt_real: tnode; override;
+ function first_abs_real: tnode; override;
+ function first_sqr_real: tnode; override;
+ function first_trunc_real: tnode; override;
+ function first_round_real: tnode; override;
+ procedure second_sqrt_real; override;
+ procedure second_abs_real; override;
+ procedure second_sqr_real; override;
+ procedure second_trunc_real; override;
+ procedure second_round_real; override;
+ procedure second_prefetch;override;
+ protected
+ procedure load_fpu_location;
+ procedure second_trunc_round_real(op: tasmop);
+ end;
+
+implementation
+
+ uses
+ cutils,globals,verbose,globtype,
+ aasmtai,aasmdata,aasmcpu,
+ symconst,symdef,
+ defutil,
+ cgbase,pass_2,
+ cpuinfo,ncgutil,
+ cgutils,cgobj,rgobj,tgobj;
+
+
+{*****************************************************************************
+ tgppcinlinenode
+*****************************************************************************}
+
+ function tgppcinlinenode.first_sqrt_real : tnode;
+ begin
+ if (current_settings.cputype >= cpu_PPC970) then
+ begin
+ expectloc:=LOC_FPUREGISTER;
+ first_sqrt_real := nil;
+ end
+ else
+ result:=inherited first_sqrt_real;
+ end;
+
+
+ function tgppcinlinenode.first_abs_real : tnode;
+ begin
+ expectloc:=LOC_FPUREGISTER;
+ first_abs_real := nil;
+ end;
+
+
+ function tgppcinlinenode.first_sqr_real : tnode;
+ begin
+ expectloc:=LOC_FPUREGISTER;
+ first_sqr_real := nil;
+ end;
+
+
+ function tgppcinlinenode.first_trunc_real : tnode;
+ begin
+ if (current_settings.cputype >= cpu_PPC970) then
+ begin
+ expectloc:=LOC_REFERENCE;
+ first_trunc_real := nil;
+ end
+ else
+ result:=inherited first_trunc_real;
+ end;
+
+
+ function tgppcinlinenode.first_round_real : tnode;
+ begin
+ if (current_settings.cputype >= cpu_PPC970) then
+ begin
+ expectloc:=LOC_REFERENCE;
+ first_round_real := nil;
+ end
+ else
+ result:=inherited first_round_real;
+ end;
+
+
+ { load the FPU into the an fpu register }
+ procedure tgppcinlinenode.load_fpu_location;
+ begin
+ location_reset(location,LOC_FPUREGISTER,def_cgsize(resultdef));
+ secondpass(left);
+ location_force_fpureg(current_asmdata.CurrAsmList,left.location,true);
+ location.loc := LOC_FPUREGISTER;
+ location.register := cg.getfpuregister(current_asmdata.CurrAsmList,OS_F64);
+ end;
+
+
+ procedure tgppcinlinenode.second_sqrt_real;
+ begin
+ if (current_settings.cputype < cpu_PPC970) then
+ internalerror(2007020910);
+ location.loc:=LOC_FPUREGISTER;
+ load_fpu_location;
+ case left.location.size of
+ OS_F32:
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FSQRTS,location.register,
+ left.location.register));
+ OS_F64:
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FSQRT,location.register,
+ left.location.register));
+ else
+ inherited;
+ end;
+ end;
+
+
+ procedure tgppcinlinenode.second_abs_real;
+ begin
+ location.loc:=LOC_FPUREGISTER;
+ load_fpu_location;
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FABS,location.register,
+ left.location.register));
+ end;
+
+
+ procedure tgppcinlinenode.second_sqr_real;
+ var
+ op: tasmop;
+ begin
+ location.loc:=LOC_FPUREGISTER;
+ load_fpu_location;
+ if (left.location.size = OS_F32) then
+ op := A_FMULS
+ else
+ op := A_FMUL;
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(op,location.register,
+ left.location.register,left.location.register));
+ end;
+
+
+ procedure tgppcinlinenode.second_trunc_round_real(op: tasmop);
+ var
+ tmpreg: tregister;
+ begin
+ if (current_settings.cputype < cpu_PPC970) then
+ internalerror(2007020910);
+ secondpass(left);
+ location_force_fpureg(current_asmdata.CurrAsmList,left.location,true);
+ tmpreg:=cg.getfpuregister(current_asmdata.CurrAsmList,OS_F64);
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op,tmpreg,
+ left.location.register));
+ location_reset_ref(location,LOC_REFERENCE,def_cgsize(resultdef),0);
+ tg.gettemptyped(current_asmdata.CurrAsmList,resultdef,tt_normal,
+ location.reference);
+ cg.a_loadfpu_reg_ref(current_asmdata.CurrAsmList,OS_F64,OS_F64,tmpreg,
+ location.reference);
+ end;
+
+
+ procedure tgppcinlinenode.second_trunc_real;
+ begin
+ second_trunc_round_real(A_FCTIDZ);
+ end;
+
+
+ procedure tgppcinlinenode.second_round_real;
+ begin
+ second_trunc_round_real(A_FCTID);
+ end;
+
+
+ procedure tgppcinlinenode.second_prefetch;
+ var
+ r: tregister;
+ begin
+ secondpass(left);
+ case left.location.loc of
+ LOC_CREFERENCE,
+ LOC_REFERENCE:
+ begin
+ r:=cg.getintregister(current_asmdata.CurrAsmList,OS_ADDR);
+ if (left.location.reference.offset = 0) and
+ not assigned(left.location.reference.symbol) then
+ begin
+ if (left.location.reference.index = NR_NO) then
+ current_asmdata.CurrAsmList.concat(taicpu.op_const_reg(A_DCBT,0,left.location.reference.base))
+ else
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_DCBT,left.location.reference.base,left.location.reference.index));
+ end
+ else
+ begin
+ cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,left.location.reference,r);
+ current_asmdata.CurrAsmList.concat(taicpu.op_const_reg(A_DCBT,0,r));
+ end;
+ end;
+ else
+ internalerror(200402021);
+ end;
+ end;
+
+
+begin
+ cinlinenode:=tgppcinlinenode;
+end.
diff --git a/closures/compiler/ppcgen/ngppcset.pas b/closures/compiler/ppcgen/ngppcset.pas
new file mode 100644
index 0000000000..0a846f6531
--- /dev/null
+++ b/closures/compiler/ppcgen/ngppcset.pas
@@ -0,0 +1,243 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl and Carl Eric Codere
+
+ Generate PowerPC32/64 assembler for in set/case nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit ngppcset;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,nset,ncgset,cpubase,cgbase,cgobj,aasmbase,aasmtai,aasmdata,globtype;
+
+ type
+ tgppccasenode = class(tcgcasenode)
+ protected
+ procedure optimizevalues(var max_linear_list : aint; var max_dist : aword);override;
+ function has_jumptable : boolean;override;
+ procedure genjumptable(hp : pcaselabel;min_,max_ : aint);override;
+ procedure genlinearlist(hp : pcaselabel); override;
+ end;
+
+
+implementation
+
+ uses
+ systems,
+ verbose,globals,constexp,
+ symconst,symdef,defutil,
+ paramgr,
+ cpuinfo,
+ pass_2,cgcpu,
+ ncon,
+ tgobj,ncgutil,regvars,rgobj,aasmcpu,
+ procinfo,
+ cgutils;
+
+{*****************************************************************************
+ TCGCASENODE
+*****************************************************************************}
+
+
+ procedure tgppccasenode.optimizevalues(var max_linear_list : aint; var max_dist : aword);
+ begin
+ max_linear_list := 10;
+ end;
+
+
+ function tgppccasenode.has_jumptable : boolean;
+ begin
+ has_jumptable:=true;
+ end;
+
+
+ procedure tgppccasenode.genjumptable(hp : pcaselabel;min_,max_ : aint);
+ var
+ table : tasmlabel;
+ last : TConstExprInt;
+ indexreg : tregister;
+ href : treference;
+ mulfactor: longint;
+
+ procedure genitem(list:TAsmList;t : pcaselabel);
+ var
+ i : TConstExprInt;
+ begin
+ if assigned(t^.less) then
+ genitem(list,t^.less);
+ { fill possible hole }
+ i:=last+1;
+ while i<=t^._low-1 do
+ begin
+ list.concat(Tai_const.Create_rel_sym(aitconst_32bit,table,elselabel));
+ i:=i+1;
+ end;
+ i:=t^._low;
+ while i<=t^._high do
+ begin
+ list.concat(Tai_const.Create_rel_sym(aitconst_32bit,table,blocklabel(t^.blockid)));
+ i:=i+1;
+ end;
+ last:=t^._high;
+ if assigned(t^.greater) then
+ genitem(list,t^.greater);
+ end;
+
+ begin
+ last:=min_;
+ { make it a 32bit register }
+ // allocate base and index registers register
+ indexreg:= cg.makeregsize(current_asmdata.CurrAsmList, hregister, OS_INT);
+ { indexreg := hregister; }
+ cg.a_load_reg_reg(current_asmdata.CurrAsmList, opsize, OS_INT, hregister, indexreg);
+ if not(jumptable_no_range) then
+ begin
+ { use aword(value-min)<aword(max-min) instead of two comparisons }
+ { case expr outside min_ .. max_ => goto elselabel }
+ cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_SUB,OS_INT,aint(min_),indexreg);
+ { this trick requires an unsigned comparison in all cases }
+ cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,OS_INT,OC_A,aint(max_)-aint(min_),indexreg,elselabel);
+ { already taken into account now }
+ min_:=0;
+ end;
+ current_asmdata.getjumplabel(table);
+ { create reference, indexreg := indexreg * sizeof(jtentry) (= 4) }
+ mulfactor:=4;
+ cg.a_op_const_reg(current_asmdata.CurrAsmList, OP_MUL, OS_INT, mulfactor, indexreg);
+ reference_reset_symbol(href, table, (-aint(min_)) * mulfactor, 4);
+
+ hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
+ cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,href,hregister);
+ reference_reset_base(href,hregister,0,4);
+ href.index:=indexreg;
+ indexreg:=cg.getaddressregister(current_asmdata.CurrAsmList);
+ cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_S32,OS_ADDR,href,indexreg);
+ cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_ADD,OS_ADDR,hregister,indexreg);
+
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg(A_MTCTR, indexreg));
+ current_asmdata.CurrAsmList.concat(taicpu.op_none(A_BCTR));
+
+ { generate jump table }
+ current_asmdata.CurrAsmList.concat(Tai_label.Create(table));
+ genitem(current_asmdata.CurrAsmList,hp);
+ end;
+
+
+ procedure tgppccasenode.genlinearlist(hp : pcaselabel);
+
+ var
+ first, lastrange : boolean;
+ last : TConstExprInt;
+
+ procedure genitem(t : pcaselabel);
+
+ procedure gensub(value:longint);
+ var
+ tmpreg: tregister;
+ begin
+ value := -value;
+ if (value >= low(smallint)) and
+ (value <= high(smallint)) then
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_const(A_ADDIC_,hregister,
+ hregister,value))
+ else
+ begin
+ tmpreg := cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+ cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_INT,value,tmpreg);
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_ADD_,hregister,
+ hregister,tmpreg));
+ end;
+ end;
+
+ begin
+ if (get_min_value(left.resultdef) >= int64(low(smallint))) and
+ (get_max_value(left.resultdef) <= int64(high(word))) then
+ begin
+ genlinearcmplist(hp);
+ exit;
+ end;
+ if assigned(t^.less) then
+ genitem(t^.less);
+ { need we to test the first value }
+ if first and (t^._low>get_min_value(left.resultdef)) then
+ begin
+ cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,OS_INT,jmp_lt,aword(t^._low.svalue),hregister,elselabel);
+ end;
+ if t^._low=t^._high then
+ begin
+ if t^._low-last=0 then
+ cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,OS_INT,OC_EQ,0,hregister,blocklabel(t^.blockid))
+ else
+ gensub(longint(int64(t^._low-last)));
+ tcgppc(cg).a_jmp_cond(current_asmdata.CurrAsmList,OC_EQ,blocklabel(t^.blockid));
+ last:=t^._low;
+ lastrange := false;
+ end
+ else
+ begin
+ { it begins with the smallest label, if the value }
+ { is even smaller then jump immediately to the }
+ { ELSE-label }
+ if first then
+ begin
+ { have we to ajust the first value ? }
+ if (t^._low>get_min_value(left.resultdef)) or (get_min_value(left.resultdef)<>0) then
+ gensub(longint(int64(t^._low)));
+ end
+ else
+ begin
+ { if there is no unused label between the last and the }
+ { present label then the lower limit can be checked }
+ { immediately. else check the range in between: }
+ gensub(longint(int64(t^._low-last)));
+ if ((t^._low-last) <> 1) or
+ (not lastrange) then
+ tcgppc(cg).a_jmp_cond(current_asmdata.CurrAsmList,jmp_lt,elselabel);
+ end;
+ gensub(longint(int64(t^._high-t^._low)));
+ tcgppc(cg).a_jmp_cond(current_asmdata.CurrAsmList,jmp_le,blocklabel(t^.blockid));
+ last:=t^._high;
+ lastrange := true;
+ end;
+ first:=false;
+ if assigned(t^.greater) then
+ genitem(t^.greater);
+ end;
+
+ begin
+ { do we need to generate cmps? }
+ if (with_sign and (min_label<0)) or
+ (opsize in [OS_32,OS_64,OS_S64]) then
+ genlinearcmplist(hp)
+ else
+ begin
+ last:=0;
+ lastrange:=false;
+ first:=true;
+ genitem(hp);
+ cg.a_jmp_always(current_asmdata.CurrAsmList,elselabel);
+ end;
+ end;
+
+
+begin
+ ccasenode:=tgppccasenode;
+end.
diff --git a/closures/compiler/ppcgen/rgcpu.pas b/closures/compiler/ppcgen/rgcpu.pas
new file mode 100644
index 0000000000..64b84bdd82
--- /dev/null
+++ b/closures/compiler/ppcgen/rgcpu.pas
@@ -0,0 +1,200 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit implements the powerpc specific class for the register
+ allocator
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+
+unit rgcpu;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ aasmbase,aasmtai,aasmdata,aasmcpu,
+ cgbase,cgutils,
+ cpubase,
+ rgobj;
+
+ type
+ trgcpu = class(trgobj)
+ procedure do_spill_read(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister);override;
+ procedure do_spill_written(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister);override;
+ end;
+
+ trgintcpu = class(trgcpu)
+{$ifdef user0}
+ procedure add_cpu_interferences(p : tai);override;
+{$endif user0}
+ end;
+
+ implementation
+
+ uses
+ verbose, cutils,globtype,
+ cgobj,
+ procinfo;
+
+
+ procedure trgcpu.do_spill_read(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister);
+ var
+ tmpref : treference;
+ helplist : TAsmList;
+ hreg : tregister;
+ ins : Taicpu;
+ begin
+ if (spilltemp.offset<low(smallint)) or
+ (spilltemp.offset>high(smallint)) then
+ begin
+ helplist:=TAsmList.create;
+
+ if (spilltemp.index<>NR_NO) then
+ internalerror(200704201);
+
+ if getregtype(tempreg)=R_INTREGISTER then
+ begin
+ hreg:=getregisterinline(helplist,[R_SUBWHOLE]);
+ {Done by add_cpu_interferences now.
+ add_edge(getsupreg(hreg),RS_R0);}
+ end
+ else
+ hreg:=cg.getintregister(helplist,OS_ADDR);
+
+ reference_reset(tmpref,sizeof(aint));
+ tmpref.offset:=spilltemp.offset;
+ tmpref.refaddr := addr_higha;
+ ins:=taicpu.op_reg_reg_ref(A_ADDIS,hreg,spilltemp.base,tmpref);
+ add_cpu_interferences(ins);
+ helplist.concat(ins);
+ tmpref:=spilltemp;
+ tmpref.refaddr := addr_low;
+ tmpref.base:=hreg;
+
+ ins:=spilling_create_load(tmpref,tempreg);
+ add_cpu_interferences(ins);
+
+
+ helplist.concat(ins);
+
+ if getregtype(tempreg)=R_INTREGISTER then
+ ungetregisterinline(helplist,hreg);
+
+ list.insertlistafter(pos,helplist);
+ helplist.free;
+ end
+ else
+ inherited do_spill_read(list,pos,spilltemp,tempreg);
+ end;
+
+
+ procedure trgcpu.do_spill_written(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister);
+ var
+ tmpref : treference;
+ helplist : TAsmList;
+ hreg : tregister;
+ ins : Taicpu;
+ begin
+ if (spilltemp.offset<low(smallint)) or
+ (spilltemp.offset>high(smallint)) then
+ begin
+ helplist:=TAsmList.create;
+
+ if (spilltemp.index<>NR_NO) then
+ internalerror(200704201);
+
+ if getregtype(tempreg)=R_INTREGISTER then
+ begin
+ hreg:=getregisterinline(helplist,[R_SUBWHOLE]);
+ {Done by add_cpu_interferences now.
+ add_edge(getsupreg(hreg),RS_R0);}
+ end
+ else
+ hreg:=cg.getintregister(helplist,OS_ADDR);
+ reference_reset(tmpref,sizeof(aint));
+ tmpref.offset:=spilltemp.offset;
+ tmpref.refaddr := addr_higha;
+ ins:=taicpu.op_reg_reg_ref(A_ADDIS,hreg,spilltemp.base,tmpref);
+ add_cpu_interferences(ins);
+ helplist.concat(ins);
+ tmpref:=spilltemp;
+ tmpref.refaddr := addr_low;
+ tmpref.base:=hreg;
+ ins:=spilling_create_store(tempreg,tmpref);
+ add_cpu_interferences(ins);
+ helplist.concat(ins);
+
+ if getregtype(tempreg)=R_INTREGISTER then
+ ungetregisterinline(helplist,hreg);
+
+ list.insertlistafter(pos,helplist);
+ helplist.free;
+ end
+ else
+ inherited do_spill_written(list,pos,spilltemp,tempreg);
+ end;
+
+{$ifdef user0}
+ procedure trgintcpu.add_cpu_interferences(p : tai);
+ var
+ r : tregister;
+ begin
+ if p.typ=ait_instruction then
+ begin
+ case taicpu(p).opcode of
+ A_ADDI, A_ADDIS,
+ A_STB, A_LBZ, A_STBX, A_LBZX, A_STH, A_LHZ, A_STHX, A_LHZX, A_LHA, A_LHAX,
+ A_STW, A_LWZ, A_STWX, A_LWZX,
+ A_STFS, A_LFS, A_STFSX, A_LFSX, A_STFD, A_LFD, A_STFDX, A_LFDX, A_STFIWX,
+ A_STHBRX, A_LHBRX, A_STWBRX, A_LWBRX, A_STWCX_, A_LWARX,
+ A_ECIWX, A_ECOWX,
+ A_LMW, A_STMW,A_LSWI,A_LSWX,A_STSWI,A_STSWX
+{$ifdef cpu64bitalu}
+ , A_STD, A_STDX,
+ A_LD, A_LDX,
+ A_LWA, A_LWAX,
+ A_STDCX_,A_LDARX
+{$endif cpu64bitalu}
+ :
+ begin
+ case taicpu(p).oper[1]^.typ of
+ top_reg:
+ add_edge(getsupreg(taicpu(p).oper[1]^.reg),RS_R0);
+ top_ref:
+ if (taicpu(p).oper[1]^.ref^.base <> NR_NO) then
+ add_edge(getsupreg(taicpu(p).oper[1]^.ref^.base),RS_R0);
+ end;
+ end;
+ A_DCBA, A_DCBI, A_DCBST, A_DCBT, A_DCBTST, A_DCBZ, A_DCBF, A_ICBI:
+ begin
+ case taicpu(p).oper[0]^.typ of
+ top_reg:
+ add_edge(getsupreg(taicpu(p).oper[0]^.reg),RS_R0);
+ top_ref:
+ if (taicpu(p).oper[0]^.ref^.base <> NR_NO) then
+ add_edge(getsupreg(taicpu(p).oper[1]^.ref^.base),RS_R0);
+ end;
+ end;
+ end;
+ end;
+ end;
+{$endif user0}
+
+
+end.
diff --git a/closures/compiler/ppcmipsel.lpi b/closures/compiler/ppcmipsel.lpi
new file mode 100644
index 0000000000..997493cb76
--- /dev/null
+++ b/closures/compiler/ppcmipsel.lpi
@@ -0,0 +1,95 @@
+<?xml version="1.0"?>
+<CONFIG>
+ <ProjectOptions>
+ <PathDelim Value="\"/>
+ <Version Value="7"/>
+ <General>
+ <Flags>
+ <MainUnitHasUsesSectionForAllUnits Value="False"/>
+ <MainUnitHasCreateFormStatements Value="False"/>
+ <MainUnitHasTitleStatement Value="False"/>
+ <AlwaysBuild Value="False"/>
+ <LRSInOutputDirectory Value="False"/>
+ </Flags>
+ <SessionStorage Value="InProjectDir"/>
+ <MainUnit Value="0"/>
+ <TargetFileExt Value=".exe"/>
+ <Title Value="pp"/>
+ </General>
+ <PublishOptions>
+ <Version Value="2"/>
+ <IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
+ <ExcludeFileFilter Value="*.(bak|ppu|ppw|o|so);*~;backup"/>
+ </PublishOptions>
+ <RunParams>
+ <local>
+ <FormatVersion Value="1"/>
+ <LaunchingApplication PathPlusParams="/usr/X11R6/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/>
+ </local>
+ </RunParams>
+ <RequiredPackages Count="1">
+ <Item1>
+ <PackageName Value="LCL"/>
+ <MinVersion Major="1" Valid="True"/>
+ </Item1>
+ </RequiredPackages>
+ <Units Count="4">
+ <Unit0>
+ <Filename Value="pp.pas"/>
+ <IsPartOfProject Value="True"/>
+ <UnitName Value="pp"/>
+ </Unit0>
+ <Unit1>
+ <Filename Value="mips\aasmcpu.pas"/>
+ <IsPartOfProject Value="True"/>
+ <UnitName Value="aasmcpu"/>
+ </Unit1>
+ <Unit2>
+ <Filename Value="mips\aoptcpu.pas"/>
+ <IsPartOfProject Value="True"/>
+ <UnitName Value="aoptcpu"/>
+ </Unit2>
+ <Unit3>
+ <Filename Value="aopt.pas"/>
+ <IsPartOfProject Value="True"/>
+ <UnitName Value="aopt"/>
+ </Unit3>
+ </Units>
+ </ProjectOptions>
+ <CompilerOptions>
+ <Version Value="8"/>
+ <PathDelim Value="\"/>
+ <Target>
+ <Filename Value="mips\pp"/>
+ </Target>
+ <SearchPaths>
+ <IncludeFiles Value="mips\"/>
+ <OtherUnitFiles Value="mips\;systems\"/>
+ <UnitOutputDirectory Value="mips\lazbuild"/>
+ </SearchPaths>
+ <Parsing>
+ <SyntaxOptions>
+ <CStyleOperator Value="False"/>
+ <AllowLabel Value="False"/>
+ <CPPInline Value="False"/>
+ </SyntaxOptions>
+ </Parsing>
+ <Linking>
+ <Debugging>
+ <GenerateDebugInfo Value="True"/>
+ </Debugging>
+ </Linking>
+ <Other>
+ <Verbosity>
+ <ShowWarn Value="False"/>
+ <ShowNotes Value="False"/>
+ <ShowHints Value="False"/>
+ </Verbosity>
+ <ConfigFile>
+ <StopAfterErrCount Value="50"/>
+ </ConfigFile>
+ <CustomOptions Value="-dmipsel"/>
+ <CompilerPath Value="$(CompPath)"/>
+ </Other>
+ </CompilerOptions>
+</CONFIG>
diff --git a/closures/compiler/ppcppc.lpi b/closures/compiler/ppcppc.lpi
new file mode 100644
index 0000000000..d9a0855dfe
--- /dev/null
+++ b/closures/compiler/ppcppc.lpi
@@ -0,0 +1,79 @@
+<?xml version="1.0"?>
+<CONFIG>
+ <ProjectOptions>
+ <PathDelim Value="\"/>
+ <Version Value="7"/>
+ <General>
+ <Flags>
+ <MainUnitHasUsesSectionForAllUnits Value="False"/>
+ <MainUnitHasCreateFormStatements Value="False"/>
+ <MainUnitHasTitleStatement Value="False"/>
+ <LRSInOutputDirectory Value="False"/>
+ </Flags>
+ <SessionStorage Value="InProjectDir"/>
+ <MainUnit Value="0"/>
+ <TargetFileExt Value=".exe"/>
+ <Title Value="pp"/>
+ </General>
+ <PublishOptions>
+ <Version Value="2"/>
+ <IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
+ <ExcludeFileFilter Value="*.(bak|ppu|ppw|o|so);*~;backup"/>
+ </PublishOptions>
+ <RunParams>
+ <local>
+ <FormatVersion Value="1"/>
+ <LaunchingApplication PathPlusParams="/usr/X11R6/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/>
+ </local>
+ </RunParams>
+ <Units Count="2">
+ <Unit0>
+ <Filename Value="pp.pas"/>
+ <IsPartOfProject Value="True"/>
+ <UnitName Value="pp"/>
+ </Unit0>
+ <Unit1>
+ <Filename Value="powerpc\cgcpu.pas"/>
+ <IsPartOfProject Value="True"/>
+ <UnitName Value="cgcpu"/>
+ </Unit1>
+ </Units>
+ </ProjectOptions>
+ <CompilerOptions>
+ <Version Value="8"/>
+ <PathDelim Value="\"/>
+ <Target>
+ <Filename Value="powerpc\pp"/>
+ </Target>
+ <SearchPaths>
+ <IncludeFiles Value="powerpc\"/>
+ <OtherUnitFiles Value="powerpc\;ppcgen\;systems\"/>
+ <UnitOutputDirectory Value="powerpc\lazbuild"/>
+ </SearchPaths>
+ <Parsing>
+ <SyntaxOptions>
+ <CStyleOperator Value="False"/>
+ <AllowLabel Value="False"/>
+ <CPPInline Value="False"/>
+ </SyntaxOptions>
+ </Parsing>
+ <Linking>
+ <Debugging>
+ <GenerateDebugInfo Value="True"/>
+ </Debugging>
+ </Linking>
+ <Other>
+ <Verbosity>
+ <ShowWarn Value="False"/>
+ <ShowNotes Value="False"/>
+ <ShowHints Value="False"/>
+ </Verbosity>
+ <ConfigFile>
+ <StopAfterErrCount Value="50"/>
+ </ConfigFile>
+ <CustomOptions Value="-dpowerpc
+"/>
+ <CompilerPath Value="$(CompPath)"/>
+ </Other>
+ </CompilerOptions>
+</CONFIG>
diff --git a/closures/compiler/ppcsparc.lpi b/closures/compiler/ppcsparc.lpi
new file mode 100644
index 0000000000..8dc8d7357c
--- /dev/null
+++ b/closures/compiler/ppcsparc.lpi
@@ -0,0 +1,79 @@
+<?xml version="1.0"?>
+<CONFIG>
+ <ProjectOptions>
+ <PathDelim Value="\"/>
+ <Version Value="7"/>
+ <General>
+ <Flags>
+ <MainUnitHasUsesSectionForAllUnits Value="False"/>
+ <MainUnitHasCreateFormStatements Value="False"/>
+ <MainUnitHasTitleStatement Value="False"/>
+ <LRSInOutputDirectory Value="False"/>
+ </Flags>
+ <SessionStorage Value="InProjectDir"/>
+ <MainUnit Value="0"/>
+ <TargetFileExt Value=".exe"/>
+ <Title Value="pp"/>
+ </General>
+ <PublishOptions>
+ <Version Value="2"/>
+ <IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
+ <ExcludeFileFilter Value="*.(bak|ppu|ppw|o|so);*~;backup"/>
+ </PublishOptions>
+ <RunParams>
+ <local>
+ <FormatVersion Value="1"/>
+ <LaunchingApplication PathPlusParams="/usr/X11R6/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/>
+ </local>
+ </RunParams>
+ <Units Count="2">
+ <Unit0>
+ <Filename Value="pp.pas"/>
+ <IsPartOfProject Value="True"/>
+ <UnitName Value="pp"/>
+ </Unit0>
+ <Unit1>
+ <Filename Value="sparc\aasmcpu.pas"/>
+ <IsPartOfProject Value="True"/>
+ <UnitName Value="aasmcpu"/>
+ </Unit1>
+ </Units>
+ </ProjectOptions>
+ <CompilerOptions>
+ <Version Value="8"/>
+ <PathDelim Value="\"/>
+ <Target>
+ <Filename Value="sparc\pp"/>
+ </Target>
+ <SearchPaths>
+ <IncludeFiles Value="sparc\"/>
+ <OtherUnitFiles Value="sparc\;systems\"/>
+ <UnitOutputDirectory Value="sparc\lazbuild"/>
+ </SearchPaths>
+ <Parsing>
+ <SyntaxOptions>
+ <CStyleOperator Value="False"/>
+ <AllowLabel Value="False"/>
+ <CPPInline Value="False"/>
+ </SyntaxOptions>
+ </Parsing>
+ <Linking>
+ <Debugging>
+ <GenerateDebugInfo Value="True"/>
+ </Debugging>
+ </Linking>
+ <Other>
+ <Verbosity>
+ <ShowWarn Value="False"/>
+ <ShowNotes Value="False"/>
+ <ShowHints Value="False"/>
+ </Verbosity>
+ <ConfigFile>
+ <StopAfterErrCount Value="50"/>
+ </ConfigFile>
+ <CustomOptions Value="-dsparc
+"/>
+ <CompilerPath Value="$(CompPath)"/>
+ </Other>
+ </CompilerOptions>
+</CONFIG>
diff --git a/closures/compiler/ppheap.pas b/closures/compiler/ppheap.pas
new file mode 100644
index 0000000000..6dfe60066c
--- /dev/null
+++ b/closures/compiler/ppheap.pas
@@ -0,0 +1,147 @@
+{
+ Copyright (c) 1998-2002 by Pierre Muller
+
+ Simple unit to add source line and column to each
+ memory allocation made with heaptrc unit
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************}
+unit ppheap;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses heaptrc;
+
+ { call this function before any memory allocation
+ in a unit initialization code (PM) }
+
+ procedure pp_heap_init;
+
+ procedure ppheap_register_file(name : string;index : longint);
+
+
+implementation
+
+ uses
+ cutils,globtype,globals,fmodule;
+
+{*****************************************************************************
+ Filename registration
+*****************************************************************************}
+
+ const
+ MaxFiles = 1024;
+ MaxNameLength = 39;
+
+ type
+ theapfileinfo = record
+ name : string[MaxNameLength];
+ index : longint;
+ end;
+
+ tfileinfoarray = array [1..MaxFiles] of theapfileinfo;
+
+ var
+ fileinfoarray : tfileinfoarray;
+ last_index : longint;
+
+
+ procedure ppheap_register_file(name : string;index : longint);
+ begin
+ inc(last_index);
+ if last_index <= MaxFiles then
+ begin
+ fileinfoarray[last_index].name:=copy(name,1,MaxNameLength);
+ fileinfoarray[last_index].index:=index;
+ end
+ else
+ writeln(stderr,'file',name,' has index ',index);
+ end;
+
+
+ function getfilename(index : longint) : string;
+ var
+ i : longint;
+ begin
+ for i:=1 to last_index do
+ begin
+ if fileinfoarray[i].index=index then
+ begin
+ getfilename:=fileinfoarray[i].name;
+ exit;
+ end;
+ end;
+ getfilename:=tostr(index);
+ end;
+
+
+{*****************************************************************************
+ Heaptrc callbacks
+*****************************************************************************}
+
+ type
+ pextra_info = ^textra_info;
+ textra_info = record
+ line,
+ col,
+ fileindex : longint;
+ end;
+
+ procedure set_extra_info(p : pointer);
+ begin
+ with pextra_info(p)^ do
+ begin
+ line:=current_filepos.line;
+ col:=current_filepos.column;
+ if assigned(current_module) then
+ fileindex:=current_module.unit_index*100000+current_filepos.fileindex
+ else
+ fileindex:=current_filepos.fileindex;
+ end;
+ end;
+
+
+ procedure show_extra_info(var t : text;p : pointer);
+ begin
+ with pextra_info(p)^ do
+ begin
+ writeln(t,getfilename(fileindex)+'('+tostr(line)+','+tostr(col)+') ');
+ end;
+ end;
+
+
+ const
+ pp_heap_inited : boolean = false;
+
+ procedure pp_heap_init;
+ begin
+ if not pp_heap_inited then
+ begin
+ keepreleased:=true;
+ SetHeapTraceOutput('heap.log');
+ SetHeapExtraInfo(sizeof(textra_info),
+ @set_extra_info,
+ @show_extra_info);
+ end;
+ pp_heap_inited:=true;
+ end;
+
+
+begin
+ pp_heap_init;
+end.
diff --git a/closures/compiler/ppu.pas b/closures/compiler/ppu.pas
new file mode 100644
index 0000000000..96d42a9296
--- /dev/null
+++ b/closures/compiler/ppu.pas
@@ -0,0 +1,1373 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Routines to read/write ppu files
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit ppu;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ systems,globtype,constexp,cstreams;
+
+{ Also write the ppu if only crc if done, this can be used with ppudump to
+ see the differences between the intf and implementation }
+{ define INTFPPU}
+
+{$ifdef Test_Double_checksum}
+var
+ CRCFile : text;
+const
+ CRC_array_Size = 200000;
+type
+ tcrc_array = array[0..crc_array_size] of longint;
+ pcrc_array = ^tcrc_array;
+{$endif Test_Double_checksum}
+
+const
+ CurrentPPUVersion = 141;
+
+{ buffer sizes }
+ maxentrysize = 1024;
+ ppubufsize = 16384;
+
+{ppu entries}
+ mainentryid = 1;
+ subentryid = 2;
+ {special}
+ iberror = 0;
+ ibstartdefs = 248;
+ ibenddefs = 249;
+ ibstartsyms = 250;
+ ibendsyms = 251;
+ ibendinterface = 252;
+ ibendimplementation = 253;
+// ibendbrowser = 254;
+ ibend = 255;
+ {general}
+ ibmodulename = 1;
+ ibsourcefiles = 2;
+ ibloadunit = 3;
+ ibinitunit = 4;
+ iblinkunitofiles = 5;
+ iblinkunitstaticlibs = 6;
+ iblinkunitsharedlibs = 7;
+ iblinkotherofiles = 8;
+ iblinkotherstaticlibs = 9;
+ iblinkothersharedlibs = 10;
+ ibImportSymbols = 11;
+ ibsymref = 12;
+ ibdefref = 13;
+// ibendsymtablebrowser = 14;
+// ibbeginsymtablebrowser = 15;
+{$IFDEF MACRO_DIFF_HINT}
+ ibusedmacros = 16;
+{$ENDIF}
+ ibderefdata = 17;
+ ibexportedmacros = 18;
+ ibderefmap = 19;
+ {syms}
+ ibtypesym = 20;
+ ibprocsym = 21;
+ ibstaticvarsym = 22;
+ ibconstsym = 23;
+ ibenumsym = 24;
+// ibtypedconstsym = 25;
+ ibabsolutevarsym = 26;
+ ibpropertysym = 27;
+ ibfieldvarsym = 28;
+ ibunitsym = 29;
+ iblabelsym = 30;
+ ibsyssym = 31;
+ ibnamespacesym = 32;
+ iblocalvarsym = 33;
+ ibparavarsym = 34;
+ ibmacrosym = 35;
+ {definitions}
+ iborddef = 40;
+ ibpointerdef = 41;
+ ibarraydef = 42;
+ ibprocdef = 43;
+ ibshortstringdef = 44;
+ ibrecorddef = 45;
+ ibfiledef = 46;
+ ibformaldef = 47;
+ ibobjectdef = 48;
+ ibenumdef = 49;
+ ibsetdef = 50;
+ ibprocvardef = 51;
+ ibfloatdef = 52;
+ ibclassrefdef = 53;
+ iblongstringdef = 54;
+ ibansistringdef = 55;
+ ibwidestringdef = 56;
+ ibvariantdef = 57;
+ ibundefineddef = 58;
+ ibunicodestringdef = 59;
+ {implementation/ObjData}
+ ibnodetree = 80;
+ ibasmsymbols = 81;
+ ibresources = 82;
+ ibcreatedobjtypes = 83;
+ ibwpofile = 84;
+ ibmoduleoptions = 85;
+
+ ibmainname = 90;
+ ibsymtableoptions = 91;
+ ibrecsymtableoptions = 91;
+ { target-specific things }
+ iblinkotherframeworks = 100;
+
+{ unit flags }
+ uf_init = $000001; { unit has initialization section }
+ uf_finalize = $000002; { unit has finalization section }
+ uf_big_endian = $000004;
+//uf_has_browser = $000010;
+ uf_in_library = $000020; { is the file in another file than <ppufile>.* ? }
+ uf_smart_linked = $000040; { the ppu can be smartlinked }
+ uf_static_linked = $000080; { the ppu can be linked static }
+ uf_shared_linked = $000100; { the ppu can be linked shared }
+//uf_local_browser = $000200;
+ uf_no_link = $000400; { unit has no .o generated, but can still have external linking! }
+ uf_has_resourcestrings = $000800; { unit has resource string section }
+ uf_little_endian = $001000;
+ uf_release = $002000; { unit was compiled with -Ur option }
+ uf_threadvars = $004000; { unit has threadvars }
+ uf_fpu_emulation = $008000; { this unit was compiled with fpu emulation on }
+ uf_has_stabs_debuginfo = $010000; { this unit has stabs debuginfo generated }
+ uf_local_symtable = $020000; { this unit has a local symtable stored }
+ uf_uses_variants = $040000; { this unit uses variants }
+ uf_has_resourcefiles = $080000; { this unit has external resources (using $R directive)}
+ uf_has_exports = $100000; { this module or a used unit has exports }
+ uf_has_dwarf_debuginfo = $200000; { this unit has dwarf debuginfo generated }
+ uf_wideinits = $400000; { this unit has winlike widestring typed constants }
+ uf_classinits = $800000; { this unit has class constructors/destructors }
+ uf_resstrinits = $1000000; { this unit has string consts referencing resourcestrings }
+
+{$ifdef generic_cpu}
+{ We need to use the correct size of aint and pint for
+ the target CPU }
+const
+ CpuAddrBitSize : array[tsystemcpu] of longint =
+ (
+ { 0 } 32 {'none'},
+ { 1 } 32 {'i386'},
+ { 2 } 32 {'m68k'},
+ { 3 } 32 {'alpha'},
+ { 4 } 32 {'powerpc'},
+ { 5 } 32 {'sparc'},
+ { 6 } 32 {'vis'},
+ { 7 } 64 {'ia64'},
+ { 8 } 64 {'x86_64'},
+ { 9 } 32 {'mips'},
+ { 10 } 32 {'arm'},
+ { 11 } 64 {'powerpc64'},
+ { 12 } 16 {'avr'},
+ { 13 } 32 {'mipsel'}
+ );
+ CpuAluBitSize : array[tsystemcpu] of longint =
+ (
+ { 0 } 32 {'none'},
+ { 1 } 32 {'i386'},
+ { 2 } 32 {'m68k'},
+ { 3 } 32 {'alpha'},
+ { 4 } 32 {'powerpc'},
+ { 5 } 32 {'sparc'},
+ { 6 } 32 {'vis'},
+ { 7 } 64 {'ia64'},
+ { 8 } 64 {'x86_64'},
+ { 9 } 32 {'mips'},
+ { 10 } 32 {'arm'},
+ { 11 } 64 {'powerpc64'},
+ { 12 } 8 {'avr'},
+ { 13 } 32 {'mipsel'}
+ );
+{$endif generic_cpu}
+
+type
+ { bestreal is defined based on the target architecture }
+ ppureal=bestreal;
+
+ tppuerror=(ppuentrytoobig,ppuentryerror);
+
+ tppuheader=record
+ id : array[1..3] of char; { = 'PPU' }
+ ver : array[1..3] of char;
+ compiler : word;
+ cpu : word;
+ target : word;
+ flags : longint;
+ size : longint; { size of the ppufile without header }
+ checksum : cardinal; { checksum for this ppufile }
+ interface_checksum : cardinal;
+ deflistsize,
+ symlistsize : longint;
+ indirect_checksum: cardinal;
+ end;
+
+ tppuentry=packed record
+ size : longint;
+ id : byte;
+ nr : byte;
+ end;
+
+ { tppufile }
+
+ tppufile=class
+ private
+ f : TCCustomFileStream;
+ mode : byte; {0 - Closed, 1 - Reading, 2 - Writing}
+ fname : string;
+ fsize : integer;
+{$ifdef Test_Double_checksum}
+ public
+ crcindex,
+ crc_index,
+ crcindex2,
+ crc_index2 : cardinal;
+ crc_test,
+ crc_test2 : pcrc_array;
+ private
+{$endif def Test_Double_checksum}
+ buf : pchar;
+ bufstart,
+ bufsize,
+ bufidx : integer;
+ entrybufstart,
+ entrystart,
+ entryidx : integer;
+ entry : tppuentry;
+ closed,
+ tempclosed : boolean;
+ closepos : integer;
+ public
+ entrytyp : byte;
+ header : tppuheader;
+ size : integer;
+ change_endian : boolean; { Used in ppudump util }
+ { crc for the entire unit }
+ crc,
+ { crc for the interface definitions in this unit }
+ interface_crc,
+ { crc of all object/class definitions in the interface of this unit, xor'ed
+ by the crc's of all object/class definitions in the interfaces of units
+ used by this unit. Reason: see mantis #13840 }
+ indirect_crc : cardinal;
+ error,
+{$ifdef generic_cpu}
+ has_more,
+{$endif not generic_cpu}
+ do_crc,
+ do_interface_crc,
+ do_indirect_crc : boolean;
+ crc_only : boolean; { used to calculate interface_crc before implementation }
+ constructor Create(const fn:string);
+ destructor Destroy;override;
+ procedure flush;
+ procedure closefile;
+ function CheckPPUId:boolean;
+ function GetPPUVersion:integer;
+ procedure NewHeader;
+ procedure NewEntry;
+ {read}
+ function openfile:boolean;
+ procedure reloadbuf;
+ procedure readdata(out b;len:integer);
+ procedure skipdata(len:integer);
+ function readentry:byte;
+ function EndOfEntry:boolean;
+ function entrysize:longint;
+ function entryleft:longint;
+ procedure getdatabuf(out b;len:integer;out res:integer);
+ procedure getdata(out b;len:integer);
+ function getbyte:byte;
+ function getword:word;
+ function getdword:dword;
+ function getlongint:longint;
+ function getint64:int64;
+ function getqword:qword;
+ function getaint:aint;
+ function getasizeint:asizeint;
+ function getaword:aword;
+ function getreal:ppureal;
+ function getrealsize(sizeofreal : longint):ppureal;
+ function getstring:string;
+ function getansistring:ansistring;
+ procedure getnormalset(out b);
+ procedure getsmallset(out b);
+ function skipuntilentry(untilb:byte):boolean;
+ {write}
+ function createfile:boolean;
+ procedure writeheader;
+ procedure writebuf;
+ procedure writedata(const b;len:integer);
+ procedure writeentry(ibnr:byte);
+ procedure putdata(const b;len:integer);
+ procedure putbyte(b:byte);
+ procedure putword(w:word);
+ procedure putdword(w:dword);
+ procedure putlongint(l:longint);
+ procedure putint64(i:int64);
+ procedure putqword(q:qword);
+ procedure putaint(i:aint);
+ procedure putasizeint(i:asizeint);
+ procedure putaword(i:aword);
+ procedure putreal(d:ppureal);
+ procedure putstring(const s:string);
+ procedure putansistring(const s:ansistring);
+ procedure putnormalset(const b);
+ procedure putsmallset(const b);
+ procedure tempclose; // MG: not used, obsolete?
+ function tempopen:boolean; // MG: not used, obsolete?
+ end;
+
+implementation
+
+ uses
+{$ifdef Test_Double_checksum}
+ comphook,
+{$endif def Test_Double_checksum}
+ fpccrc,
+ cutils;
+
+
+
+function swapendian_ppureal(d:ppureal):ppureal;
+
+type ppureal_bytes=array[0..sizeof(d)-1] of byte;
+
+var i:0..sizeof(d)-1;
+
+begin
+ for i:=low(ppureal_bytes) to high(ppureal_bytes) do
+ ppureal_bytes(swapendian_ppureal)[i]:=ppureal_bytes(d)[high(ppureal_bytes)-i];
+end;
+
+
+{*****************************************************************************
+ TPPUFile
+*****************************************************************************}
+
+constructor tppufile.Create(const fn:string);
+begin
+ fname:=fn;
+ change_endian:=false;
+ crc_only:=false;
+ Mode:=0;
+ NewHeader;
+ Error:=false;
+ closed:=true;
+ tempclosed:=false;
+ getmem(buf,ppubufsize);
+end;
+
+
+destructor tppufile.destroy;
+begin
+ closefile;
+ if assigned(buf) then
+ freemem(buf,ppubufsize);
+end;
+
+
+procedure tppufile.flush;
+begin
+ if Mode=2 then
+ writebuf;
+end;
+
+
+procedure tppufile.closefile;
+begin
+{$ifdef Test_Double_checksum}
+ if mode=2 then
+ begin
+ if assigned(crc_test) then
+ dispose(crc_test);
+ if assigned(crc_test2) then
+ dispose(crc_test2);
+ end;
+{$endif Test_Double_checksum}
+ if Mode<>0 then
+ begin
+ Flush;
+ f.Free;
+ Mode:=0;
+ closed:=true;
+ end;
+end;
+
+
+function tppufile.CheckPPUId:boolean;
+begin
+ CheckPPUId:=((Header.Id[1]='P') and (Header.Id[2]='P') and (Header.Id[3]='U'));
+end;
+
+
+function tppufile.GetPPUVersion:integer;
+var
+ l : integer;
+ code : integer;
+begin
+ Val(header.ver[1]+header.ver[2]+header.ver[3],l,code);
+ if code=0 then
+ GetPPUVersion:=l
+ else
+ GetPPUVersion:=0;
+end;
+
+
+procedure tppufile.NewHeader;
+var
+ s : string;
+begin
+ fillchar(header,sizeof(tppuheader),0);
+ str(currentppuversion,s);
+ while length(s)<3 do
+ s:='0'+s;
+ with header do
+ begin
+ Id[1]:='P';
+ Id[2]:='P';
+ Id[3]:='U';
+ Ver[1]:=s[1];
+ Ver[2]:=s[2];
+ Ver[3]:=s[3];
+ end;
+end;
+
+
+{*****************************************************************************
+ TPPUFile Reading
+*****************************************************************************}
+
+function tppufile.openfile:boolean;
+var
+ i : integer;
+begin
+ openfile:=false;
+ try
+ f:=CFileStreamClass.Create(fname,fmOpenRead)
+ except
+ exit;
+ end;
+ closed:=false;
+{read ppuheader}
+ fsize:=f.Size;
+ if fsize<sizeof(tppuheader) then
+ exit;
+ i:=f.Read(header,sizeof(tppuheader));
+ { The header is always stored in little endian order }
+ { therefore swap if on a big endian machine }
+{$IFDEF ENDIAN_BIG}
+ header.compiler := swapendian(header.compiler);
+ header.cpu := swapendian(header.cpu);
+ header.target := swapendian(header.target);
+ header.flags := swapendian(header.flags);
+ header.size := swapendian(header.size);
+ header.checksum := swapendian(header.checksum);
+ header.interface_checksum := swapendian(header.interface_checksum);
+ header.indirect_checksum := swapendian(header.indirect_checksum);
+ header.deflistsize:=swapendian(header.deflistsize);
+ header.symlistsize:=swapendian(header.symlistsize);
+{$ENDIF}
+ { the PPU DATA is stored in native order }
+ if (header.flags and uf_big_endian) = uf_big_endian then
+ Begin
+{$IFDEF ENDIAN_LITTLE}
+ change_endian := TRUE;
+{$ELSE}
+ change_endian := FALSE;
+{$ENDIF}
+ End
+ else if (header.flags and uf_little_endian) = uf_little_endian then
+ Begin
+{$IFDEF ENDIAN_BIG}
+ change_endian := TRUE;
+{$ELSE}
+ change_endian := FALSE;
+{$ENDIF}
+ End;
+{reset buffer}
+ bufstart:=i;
+ bufsize:=0;
+ bufidx:=0;
+ Mode:=1;
+ FillChar(entry,sizeof(tppuentry),0);
+ entryidx:=0;
+ entrystart:=0;
+ entrybufstart:=0;
+ Error:=false;
+ openfile:=true;
+end;
+
+
+procedure tppufile.reloadbuf;
+begin
+ inc(bufstart,bufsize);
+ bufsize:=f.Read(buf^,ppubufsize);
+ bufidx:=0;
+end;
+
+
+procedure tppufile.readdata(out b;len:integer);
+var
+ p,pbuf : pchar;
+ left : integer;
+begin
+ p:=pchar(@b);
+ pbuf:=@buf[bufidx];
+ repeat
+ left:=bufsize-bufidx;
+ if len<left then
+ break;
+ move(pbuf^,p^,left);
+ dec(len,left);
+ inc(p,left);
+ reloadbuf;
+ pbuf:=@buf[bufidx];
+ if bufsize=0 then
+ exit;
+ until false;
+ move(pbuf^,p^,len);
+ inc(bufidx,len);
+end;
+
+
+procedure tppufile.skipdata(len:integer);
+var
+ left : integer;
+begin
+ while len>0 do
+ begin
+ left:=bufsize-bufidx;
+ if len>left then
+ begin
+ dec(len,left);
+ reloadbuf;
+ if bufsize=0 then
+ exit;
+ end
+ else
+ begin
+ inc(bufidx,len);
+ exit;
+ end;
+ end;
+end;
+
+
+function tppufile.readentry:byte;
+begin
+ if entryidx<entry.size then
+ begin
+{$ifdef generic_cpu}
+ has_more:=true;
+{$endif not generic_cpu}
+ skipdata(entry.size-entryidx);
+ end;
+ readdata(entry,sizeof(tppuentry));
+ if change_endian then
+ entry.size:=swapendian(entry.size);
+ entrystart:=bufstart+bufidx;
+ entryidx:=0;
+{$ifdef generic_cpu}
+ has_more:=false;
+{$endif not generic_cpu}
+ if not(entry.id in [mainentryid,subentryid]) then
+ begin
+ readentry:=iberror;
+ error:=true;
+ exit;
+ end;
+ readentry:=entry.nr;
+end;
+
+
+function tppufile.endofentry:boolean;
+begin
+{$ifdef generic_cpu}
+ endofentry:=(entryidx=entry.size);
+{$else not generic_cpu}
+ endofentry:=(entryidx>=entry.size);
+{$endif not generic_cpu}
+end;
+
+
+function tppufile.entrysize:longint;
+begin
+ entrysize:=entry.size;
+end;
+
+function tppufile.entryleft:longint;
+begin
+ entryleft:=entry.size-entryidx;
+end;
+
+
+procedure tppufile.getdatabuf(out b;len:integer;out res:integer);
+begin
+ if entryidx+len>entry.size then
+ res:=entry.size-entryidx
+ else
+ res:=len;
+ readdata(b,res);
+ inc(entryidx,res);
+end;
+
+
+procedure tppufile.getdata(out b;len:integer);
+begin
+ if entryidx+len>entry.size then
+ begin
+ error:=true;
+ exit;
+ end;
+ readdata(b,len);
+ inc(entryidx,len);
+end;
+
+
+function tppufile.getbyte:byte;
+begin
+ if entryidx+1>entry.size then
+ begin
+ error:=true;
+ result:=0;
+ exit;
+ end;
+ if bufsize-bufidx>=1 then
+ begin
+ result:=pbyte(@buf[bufidx])^;
+ inc(bufidx);
+ end
+ else
+ readdata(result,1);
+ inc(entryidx);
+end;
+
+
+function tppufile.getword:word;
+begin
+ if entryidx+2>entry.size then
+ begin
+ error:=true;
+ result:=0;
+ exit;
+ end;
+ if bufsize-bufidx>=sizeof(word) then
+ begin
+ result:=Unaligned(pword(@buf[bufidx])^);
+ inc(bufidx,sizeof(word));
+ end
+ else
+ readdata(result,sizeof(word));
+ if change_endian then
+ result:=swapendian(result);
+ inc(entryidx,2);
+end;
+
+
+function tppufile.getlongint:longint;
+begin
+ if entryidx+4>entry.size then
+ begin
+ error:=true;
+ result:=0;
+ exit;
+ end;
+ if bufsize-bufidx>=sizeof(longint) then
+ begin
+ result:=Unaligned(plongint(@buf[bufidx])^);
+ inc(bufidx,sizeof(longint));
+ end
+ else
+ readdata(result,sizeof(longint));
+ if change_endian then
+ result:=swapendian(result);
+ inc(entryidx,4);
+end;
+
+
+function tppufile.getdword:dword;
+begin
+ if entryidx+4>entry.size then
+ begin
+ error:=true;
+ result:=0;
+ exit;
+ end;
+ if bufsize-bufidx>=sizeof(dword) then
+ begin
+ result:=Unaligned(plongint(@buf[bufidx])^);
+ inc(bufidx,sizeof(longint));
+ end
+ else
+ readdata(result,sizeof(dword));
+ if change_endian then
+ result:=swapendian(result);
+ inc(entryidx,4);
+end;
+
+
+function tppufile.getint64:int64;
+begin
+ if entryidx+8>entry.size then
+ begin
+ error:=true;
+ result:=0;
+ exit;
+ end;
+ if bufsize-bufidx>=sizeof(int64) then
+ begin
+ result:=Unaligned(pint64(@buf[bufidx])^);
+ inc(bufidx,sizeof(int64));
+ end
+ else
+ readdata(result,sizeof(int64));
+ if change_endian then
+ result:=swapendian(result);
+ inc(entryidx,8);
+end;
+
+
+function tppufile.getqword:qword;
+begin
+ if entryidx+8>entry.size then
+ begin
+ error:=true;
+ result:=0;
+ exit;
+ end;
+ if bufsize-bufidx>=sizeof(qword) then
+ begin
+ result:=Unaligned(pqword(@buf[bufidx])^);
+ inc(bufidx,sizeof(qword));
+ end
+ else
+ readdata(result,sizeof(qword));
+ if change_endian then
+ result:=swapendian(result);
+ inc(entryidx,8);
+end;
+
+
+function tppufile.getaint:aint;
+begin
+{$ifdef generic_cpu}
+ if CpuAluBitSize[tsystemcpu(header.cpu)]=64 then
+ result:=getint64
+ else if CpuAluBitSize[tsystemcpu(header.cpu)]=32 then
+ result:=getlongint
+ else if CpuAluBitSize[tsystemcpu(header.cpu)]=16 then
+ result:=smallint(getword)
+ else if CpuAluBitSize[tsystemcpu(header.cpu)]=8 then
+ result:=shortint(getbyte)
+ else
+ begin
+ error:=true;
+ result:=0;
+ end;
+{$else not generic_cpu}
+{$ifdef cpu64bitalu}
+ result:=getint64;
+{$else cpu64bitalu}
+ result:=getlongint;
+{$endif cpu64bitalu}
+{$endif not generic_cpu}
+end;
+
+
+function tppufile.getasizeint:asizeint;
+begin
+{$ifdef generic_cpu}
+ if CpuAddrBitSize[tsystemcpu(header.cpu)]=64 then
+ result:=getint64
+ else if CpuAddrBitSize[tsystemcpu(header.cpu)]=32 then
+ result:=getlongint
+ else if CpuAddrBitSize[tsystemcpu(header.cpu)]=16 then
+ result:=smallint(getword)
+ else
+ begin
+ error:=true;
+ result:=0;
+ end;
+{$else not generic_cpu}
+{$ifdef cpu64bitaddr}
+ result:=getint64;
+{$else cpu64bitaddr}
+ result:=getlongint;
+{$endif cpu32bitaddr}
+{$endif not generic_cpu}
+end;
+
+
+function tppufile.getaword:aword;
+begin
+{$ifdef generic_cpu}
+ if CpuAluBitSize[tsystemcpu(header.cpu)]=64 then
+ result:=getqword
+ else if CpuAluBitSize[tsystemcpu(header.cpu)]=32 then
+ result:=getdword
+ else if CpuAluBitSize[tsystemcpu(header.cpu)]=16 then
+ result:=getword
+ else if CpuAluBitSize[tsystemcpu(header.cpu)]=8 then
+ result:=getbyte
+ else
+ begin
+ error:=true;
+ result:=0;
+ end;
+{$else not generic_cpu}
+{$ifdef cpu64bitalu}
+ result:=getqword;
+{$else cpu64bitalu}
+ result:=getdword;
+{$endif cpu64bitalu}
+{$endif not generic_cpu}
+end;
+
+function tppufile.getrealsize(sizeofreal : longint):ppureal;
+var
+ e : ppureal;
+ d : double;
+ s : single;
+begin
+ if sizeofreal=sizeof(e) then
+ begin
+ if entryidx+sizeof(e)>entry.size then
+ begin
+ error:=true;
+ result:=0;
+ exit;
+ end;
+ readdata(e,sizeof(e));
+ if change_endian then
+ result:=swapendian_ppureal(e)
+ else
+ result:=e;
+ inc(entryidx,sizeof(e));
+ exit;
+ end;
+ if sizeofreal=sizeof(d) then
+ begin
+ if entryidx+sizeof(d)>entry.size then
+ begin
+ error:=true;
+ result:=0;
+ exit;
+ end;
+ readdata(d,sizeof(d));
+ if change_endian then
+ result:=swapendian(pqword(@d)^)
+ else
+ result:=d;
+ inc(entryidx,sizeof(d));
+ result:=d;
+ exit;
+ end;
+ if sizeofreal=sizeof(s) then
+ begin
+ if entryidx+sizeof(s)>entry.size then
+ begin
+ error:=true;
+ result:=0;
+ exit;
+ end;
+ readdata(s,sizeof(s));
+ if change_endian then
+ result:=swapendian(pdword(@s)^)
+ else
+ result:=s;
+ inc(entryidx,sizeof(s));
+ result:=s;
+ exit;
+ end;
+ error:=true;
+ result:=0.0;
+end;
+
+function tppufile.getreal:ppureal;
+var
+ d : ppureal;
+ hd : double;
+begin
+ if target_info.system=system_x86_64_win64 then
+ begin
+ hd:=getrealsize(sizeof(hd));
+ getreal:=hd;
+ end
+ else
+ begin
+ d:=getrealsize(sizeof(d));
+ getreal:=d;
+ end;
+end;
+
+
+function tppufile.getstring:string;
+begin
+ result[0]:=chr(getbyte);
+ if entryidx+length(result)>entry.size then
+ begin
+ error:=true;
+ exit;
+ end;
+ ReadData(result[1],length(result));
+ inc(entryidx,length(result));
+end;
+
+
+function tppufile.getansistring: ansistring;
+var
+ l : longint;
+begin
+ l:=getlongint;
+ if entryidx+l>entry.size then
+ begin
+ error:=true;
+ exit;
+ end;
+ if l>0 then
+ begin
+ SetLength(Result,l);
+ ReadData(result[1],l);
+ end
+ else
+ Result:='';
+ inc(entryidx,l);
+end;
+
+
+procedure tppufile.getsmallset(out b);
+var
+ i : longint;
+begin
+ getdata(b,4);
+ if change_endian then
+ for i:=0 to 3 do
+ Pbyte(@b)[i]:=reverse_byte(Pbyte(@b)[i]);
+end;
+
+
+procedure tppufile.getnormalset(out b);
+var
+ i : longint;
+begin
+ getdata(b,32);
+ if change_endian then
+ for i:=0 to 31 do
+ Pbyte(@b)[i]:=reverse_byte(Pbyte(@b)[i]);
+end;
+
+
+function tppufile.skipuntilentry(untilb:byte):boolean;
+var
+ b : byte;
+begin
+ repeat
+ b:=readentry;
+ until (b in [ibend,iberror]) or ((b=untilb) and (entry.id=mainentryid));
+ skipuntilentry:=(b=untilb);
+end;
+
+
+{*****************************************************************************
+ TPPUFile Writing
+*****************************************************************************}
+
+function tppufile.createfile:boolean;
+var
+ ok: boolean;
+begin
+ createfile:=false;
+{$ifdef INTFPPU}
+ if crc_only then
+ begin
+ fname:=fname+'.intf';
+ crc_only:=false;
+ end;
+{$endif}
+ if not crc_only then
+ begin
+ {$ifdef MACOS}
+ {FPas is FreePascal's creator code on MacOS. See systems/mac_crea.txt}
+ SetDefaultMacOSCreator('FPas');
+ SetDefaultMacOSFiletype('FPPU');
+ {$endif}
+ ok:=false;
+ try
+ f:=CFileStreamClass.Create(fname,fmCreate);
+ ok:=true;
+ except
+ end;
+ {$ifdef MACOS}
+ SetDefaultMacOSCreator('MPS ');
+ SetDefaultMacOSFiletype('TEXT');
+ {$endif}
+ if not ok then
+ exit;
+ Mode:=2;
+ {write header for sure}
+ f.Write(header,sizeof(tppuheader));
+ end;
+ bufsize:=ppubufsize;
+ bufstart:=sizeof(tppuheader);
+ bufidx:=0;
+{reset}
+ crc:=0;
+ interface_crc:=0;
+ indirect_crc:=0;
+ do_interface_crc:=true;
+ do_indirect_crc:=false;
+ Error:=false;
+ do_crc:=true;
+ size:=0;
+ entrytyp:=mainentryid;
+{start}
+ NewEntry;
+ createfile:=true;
+end;
+
+
+procedure tppufile.writeheader;
+var
+ opos : integer;
+begin
+ if crc_only then
+ exit;
+ { flush buffer }
+ writebuf;
+ { update size (w/o header!) in the header }
+ header.size:=bufstart-sizeof(tppuheader);
+ { set the endian flag }
+{$ifndef FPC_BIG_ENDIAN}
+ header.flags := header.flags or uf_little_endian;
+{$else not FPC_BIG_ENDIAN}
+ header.flags := header.flags or uf_big_endian;
+ { Now swap the header in the correct endian (always little endian) }
+ header.compiler := swapendian(header.compiler);
+ header.cpu := swapendian(header.cpu);
+ header.target := swapendian(header.target);
+ header.flags := swapendian(header.flags);
+ header.size := swapendian(header.size);
+ header.checksum := swapendian(header.checksum);
+ header.interface_checksum := swapendian(header.interface_checksum);
+ header.indirect_checksum := swapendian(header.indirect_checksum);
+ header.deflistsize:=swapendian(header.deflistsize);
+ header.symlistsize:=swapendian(header.symlistsize);
+{$endif not FPC_BIG_ENDIAN}
+{ write header and restore filepos after it }
+ opos:=f.Position;
+ f.Position:=0;
+ f.Write(header,sizeof(tppuheader));
+ f.Position:=opos;
+end;
+
+
+procedure tppufile.writebuf;
+begin
+ if not crc_only and
+ (bufidx <> 0) then
+ f.Write(buf^,bufidx);
+ inc(bufstart,bufidx);
+ bufidx:=0;
+end;
+
+
+procedure tppufile.writedata(const b;len:integer);
+var
+ p : pchar;
+ left,
+ idx : integer;
+begin
+ if crc_only then
+ exit;
+ p:=pchar(@b);
+ idx:=0;
+ while len>0 do
+ begin
+ left:=bufsize-bufidx;
+ if len>left then
+ begin
+ move(p[idx],buf[bufidx],left);
+ dec(len,left);
+ inc(idx,left);
+ inc(bufidx,left);
+ writebuf;
+ end
+ else
+ begin
+ move(p[idx],buf[bufidx],len);
+ inc(bufidx,len);
+ exit;
+ end;
+ end;
+end;
+
+
+procedure tppufile.NewEntry;
+begin
+ with entry do
+ begin
+ id:=entrytyp;
+ nr:=ibend;
+ size:=0;
+ end;
+{Reset Entry State}
+ entryidx:=0;
+ entrybufstart:=bufstart;
+ entrystart:=bufstart+bufidx;
+{Alloc in buffer}
+ writedata(entry,sizeof(tppuentry));
+end;
+
+
+procedure tppufile.writeentry(ibnr:byte);
+var
+ opos : integer;
+begin
+{create entry}
+ entry.id:=entrytyp;
+ entry.nr:=ibnr;
+ entry.size:=entryidx;
+{it's already been sent to disk ?}
+ if entrybufstart<>bufstart then
+ begin
+ if not crc_only then
+ begin
+ {flush to be sure}
+ WriteBuf;
+ {write entry}
+ opos:=f.Position;
+ f.Position:=entrystart;
+ f.write(entry,sizeof(tppuentry));
+ f.Position:=opos;
+ end;
+ entrybufstart:=bufstart;
+ end
+ else
+ move(entry,buf[entrystart-bufstart],sizeof(entry));
+{Add New Entry, which is ibend by default}
+ entrystart:=bufstart+bufidx; {next entry position}
+ NewEntry;
+end;
+
+
+procedure tppufile.putdata(const b;len:integer);
+begin
+ if do_crc then
+ begin
+ crc:=UpdateCrc32(crc,b,len);
+{$ifdef Test_Double_checksum}
+ if crc_only then
+ begin
+ crc_test2^[crc_index2]:=crc;
+{$ifdef Test_Double_checksum_write}
+ Writeln(CRCFile,crc);
+{$endif Test_Double_checksum_write}
+ if crc_index2<crc_array_size then
+ inc(crc_index2);
+ end
+ else
+ begin
+ if (crcindex2<crc_array_size) and (crcindex2<crc_index2) and
+ (crc_test2^[crcindex2]<>crc) then
+ Do_comment(V_Note,'impl CRC changed');
+{$ifdef Test_Double_checksum_write}
+ Writeln(CRCFile,crc);
+{$endif Test_Double_checksum_write}
+ inc(crcindex2);
+ end;
+{$endif def Test_Double_checksum}
+ if do_interface_crc then
+ begin
+ interface_crc:=UpdateCrc32(interface_crc,b,len);
+{$ifdef Test_Double_checksum}
+ if crc_only then
+ begin
+ crc_test^[crc_index]:=interface_crc;
+{$ifdef Test_Double_checksum_write}
+ Writeln(CRCFile,interface_crc);
+{$endif Test_Double_checksum_write}
+ if crc_index<crc_array_size then
+ inc(crc_index);
+ end
+ else
+ begin
+ if (crcindex<crc_array_size) and (crcindex<crc_index) and
+ (crc_test^[crcindex]<>interface_crc) then
+ Do_comment(V_Warning,'CRC changed');
+{$ifdef Test_Double_checksum_write}
+ Writeln(CRCFile,interface_crc);
+{$endif Test_Double_checksum_write}
+ inc(crcindex);
+ end;
+{$endif def Test_Double_checksum}
+ { indirect crc must only be calculated for the interface; changes
+ to a class in the implementation cannot require another unit to
+ be recompiled }
+ if do_indirect_crc then
+ indirect_crc:=UpdateCrc32(indirect_crc,b,len);
+ end;
+ end;
+ if not crc_only then
+ writedata(b,len);
+ inc(entryidx,len);
+end;
+
+
+procedure tppufile.putbyte(b:byte);
+begin
+ putdata(b,1);
+end;
+
+
+procedure tppufile.putword(w:word);
+begin
+ putdata(w,2);
+end;
+
+
+procedure tppufile.putdword(w:dword);
+begin
+ putdata(w,4);
+end;
+
+
+procedure tppufile.putlongint(l:longint);
+begin
+ putdata(l,4);
+end;
+
+
+procedure tppufile.putint64(i:int64);
+begin
+ putdata(i,8);
+end;
+
+
+procedure tppufile.putqword(q:qword);
+begin
+ putdata(q,sizeof(qword));
+end;
+
+
+procedure tppufile.putaint(i:aint);
+begin
+ putdata(i,sizeof(aint));
+end;
+
+
+procedure tppufile.putasizeint(i: asizeint);
+begin
+ putdata(i,sizeof(asizeint));
+end;
+
+
+procedure tppufile.putaword(i:aword);
+begin
+ putdata(i,sizeof(aword));
+end;
+
+
+procedure tppufile.putreal(d:ppureal);
+var
+ hd : double;
+begin
+ if target_info.system=system_x86_64_win64 then
+ begin
+ hd:=d;
+ putdata(hd,sizeof(hd));
+ end
+ else
+ putdata(d,sizeof(ppureal));
+end;
+
+
+procedure tppufile.putstring(const s:string);
+ begin
+ putdata(s,length(s)+1);
+ end;
+
+
+procedure tppufile.putansistring(const s: ansistring);
+ var
+ l : longint;
+ begin
+ l:=length(s);
+ putdata(l,4);
+ if l>0 then
+ putdata(s[1],l);
+ end;
+
+
+procedure tppufile.putsmallset(const b);
+ var
+ l : longint;
+ begin
+ l:=longint(b);
+ putlongint(l);
+ end;
+
+
+procedure tppufile.putnormalset(const b);
+ begin
+ putdata(b,32);
+ end;
+
+
+procedure tppufile.tempclose;
+ begin
+ if not closed then
+ begin
+ closepos:=f.Position;
+ f.Free;
+ f:=nil;
+ closed:=true;
+ tempclosed:=true;
+ end;
+ end;
+
+
+function tppufile.tempopen:boolean;
+ begin
+ tempopen:=false;
+ if not closed or not tempclosed then
+ exit;
+ { MG: not sure, if this is correct
+ f.position:=0;
+ No, f was freed in tempclose above, we need to
+ recreate it. PM 2011/06/06 }
+ try
+ f:=CFileStreamClass.Create(fname,fmOpenRead);
+ except
+ exit;
+ end;
+ closed:=false;
+ tempclosed:=false;
+
+ { restore state }
+ f.Position:=closepos;
+ tempopen:=true;
+ end;
+
+end.
diff --git a/closures/compiler/ppx86_64.lpi b/closures/compiler/ppx86_64.lpi
new file mode 100644
index 0000000000..7a64f54df6
--- /dev/null
+++ b/closures/compiler/ppx86_64.lpi
@@ -0,0 +1,82 @@
+<?xml version="1.0"?>
+<CONFIG>
+ <ProjectOptions>
+ <Version Value="9"/>
+ <PathDelim Value="\"/>
+ <General>
+ <Flags>
+ <MainUnitHasUsesSectionForAllUnits Value="False"/>
+ <MainUnitHasCreateFormStatements Value="False"/>
+ <MainUnitHasTitleStatement Value="False"/>
+ <LRSInOutputDirectory Value="False"/>
+ </Flags>
+ <SessionStorage Value="InProjectDir"/>
+ <MainUnit Value="0"/>
+ <Title Value="pp"/>
+ </General>
+ <BuildModes Count="1">
+ <Item1 Name="default" Default="True"/>
+ </BuildModes>
+ <PublishOptions>
+ <Version Value="2"/>
+ <DestinationDirectory Value="$(TestDir)\publishedproject\"/>
+ <IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
+ <ExcludeFileFilter Value="*.(bak|ppu|ppw|o|so);*~;backup"/>
+ </PublishOptions>
+ <RunParams>
+ <local>
+ <FormatVersion Value="1"/>
+ <LaunchingApplication PathPlusParams="/usr/X11R6/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/>
+ </local>
+ </RunParams>
+ <Units Count="2">
+ <Unit0>
+ <Filename Value="pp.pas"/>
+ <IsPartOfProject Value="True"/>
+ <UnitName Value="pp"/>
+ </Unit0>
+ <Unit1>
+ <Filename Value="x86\aasmcpu.pas"/>
+ <IsPartOfProject Value="True"/>
+ <UnitName Value="aasmcpu"/>
+ </Unit1>
+ </Units>
+ </ProjectOptions>
+ <CompilerOptions>
+ <Version Value="10"/>
+ <PathDelim Value="\"/>
+ <Target>
+ <Filename Value="x86_64\pp"/>
+ </Target>
+ <SearchPaths>
+ <IncludeFiles Value="x86_64"/>
+ <OtherUnitFiles Value="x86_64;x86;systems"/>
+ <UnitOutputDirectory Value="x86_64\lazbuild"/>
+ </SearchPaths>
+ <Parsing>
+ <SyntaxOptions>
+ <CStyleOperator Value="False"/>
+ <AllowLabel Value="False"/>
+ <CPPInline Value="False"/>
+ <UseAnsiStrings Value="False"/>
+ </SyntaxOptions>
+ </Parsing>
+ <Linking>
+ <Debugging>
+ <GenerateDebugInfo Value="True"/>
+ </Debugging>
+ </Linking>
+ <Other>
+ <Verbosity>
+ <ShowWarn Value="False"/>
+ <ShowNotes Value="False"/>
+ <ShowHints Value="False"/>
+ </Verbosity>
+ <ConfigFile>
+ <StopAfterErrCount Value="50"/>
+ </ConfigFile>
+ <CustomOptions Value="-dx86_64"/>
+ <CompilerPath Value="$(CompPath)"/>
+ </Other>
+ </CompilerOptions>
+</CONFIG>
diff --git a/closures/compiler/procinfo.pas b/closures/compiler/procinfo.pas
new file mode 100644
index 0000000000..e494b2d59d
--- /dev/null
+++ b/closures/compiler/procinfo.pas
@@ -0,0 +1,292 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Information about the current procedure that is being compiled
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit procinfo;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ { common }
+ cclasses,
+ { global }
+ globtype,globals,verbose,
+ { symtable }
+ symconst,symtype,symdef,symsym,
+ { aasm }
+ cpubase,cpuinfo,cgbase,cgutils,
+ aasmbase,aasmtai,aasmdata,
+ optutils
+ ;
+
+ const
+ inherited_inlining_flags : tprocinfoflags =
+ [pi_do_call,
+ { the stack frame can't be removed in this case }
+ pi_has_assembler_block,
+ pi_uses_exceptions];
+
+
+ type
+ tsavedlabels = array[Boolean] of TAsmLabel;
+
+ {# This object gives information on the current routine being
+ compiled.
+ }
+ tprocinfo = class(tlinkedlistitem)
+ private
+ { list to store the procinfo's of the nested procedures }
+ nestedprocs : tlinkedlist;
+ procedure addnestedproc(child: tprocinfo);
+ public
+ { pointer to parent in nested procedures }
+ parent : tprocinfo;
+ {# the definition of the routine itself }
+ procdef : tprocdef;
+ { procinfo of the main procedure that is inlining
+ the current function, only used in tcgcallnode.inlined_pass2 }
+ inlining_procinfo : tprocinfo;
+ { nested implicit finalzation procedure, used for platform-specific
+ exception handling }
+ finalize_procinfo : tprocinfo;
+ { file location of begin of procedure }
+ entrypos : tfileposinfo;
+ { file location of end of procedure }
+ exitpos : tfileposinfo;
+ { local switches at begin of procedure }
+ entryswitches : tlocalswitches;
+ { local switches at end of procedure }
+ exitswitches : tlocalswitches;
+
+ { Size of the parameters on the stack }
+ para_stack_size : pint;
+
+ { Offset of temp after para/local are allocated }
+ tempstart : longint;
+
+ {# some collected informations about the procedure
+ see pi_xxxx constants above
+ }
+ flags : tprocinfoflags;
+
+ { register used as frame pointer }
+ framepointer : tregister;
+
+ { register containing currently the got }
+ got : tregister;
+ CurrGOTLabel : tasmlabel;
+
+ { Holds the reference used to store all saved registers. }
+ save_regs_ref : treference;
+
+ { Last assembler instruction of procedure prologue }
+ endprologue_ai : tlinkedlistitem;
+
+ { Amount of stack adjustment after all alignments }
+ final_localsize : longint;
+
+ { Labels for TRUE/FALSE condition, BREAK and CONTINUE }
+ CurrBreakLabel,
+ CurrContinueLabel,
+ CurrTrueLabel,
+ CurrFalseLabel : tasmlabel;
+
+ { label to leave the sub routine }
+ CurrExitLabel : tasmlabel;
+
+ {# The code for the routine itself, excluding entry and
+ exit code. This is a linked list of tai classes.
+ }
+ aktproccode : TAsmList;
+ { Data (like jump tables) that belongs to this routine }
+ aktlocaldata : TAsmList;
+
+ { max. of space need for parameters }
+ maxpushedparasize : aint;
+
+ constructor create(aparent:tprocinfo);virtual;
+ destructor destroy;override;
+
+ procedure allocate_push_parasize(size:longint);
+
+ function calc_stackframe_size:longint;virtual;
+
+ { Set the address of the first temp, can be used to allocate
+ space for pushing parameters }
+ procedure set_first_temp_offset;virtual;
+
+ { Generate parameter information }
+ procedure generate_parameter_info;virtual;
+
+ { Allocate got register }
+ procedure allocate_got_register(list: TAsmList);virtual;
+
+ { Destroy the entire procinfo tree, starting from the outermost parent }
+ procedure destroy_tree;
+
+ { Store CurrTrueLabel and CurrFalseLabel to saved and generate new ones }
+ procedure save_jump_labels(out saved: tsavedlabels);
+
+ { Restore CurrTrueLabel and CurrFalseLabel from saved }
+ procedure restore_jump_labels(const saved: tsavedlabels);
+
+ function get_first_nestedproc: tprocinfo;
+ function has_nestedprocs: boolean;
+
+ { Add to parent's list of nested procedures even if parent is a 'main' procedure }
+ procedure force_nested;
+ end;
+ tcprocinfo = class of tprocinfo;
+
+ var
+ cprocinfo : tcprocinfo;
+ { information about the current sub routine being parsed (@var(pprocinfo))}
+ current_procinfo : tprocinfo;
+
+
+implementation
+
+ uses
+ cutils,systems,
+ tgobj,cgobj,
+ paramgr
+ ;
+
+
+{****************************************************************************
+ TProcInfo
+****************************************************************************}
+
+ constructor tprocinfo.create(aparent:tprocinfo);
+ begin
+ parent:=aparent;
+ procdef:=nil;
+ para_stack_size:=0;
+ flags:=[];
+ framepointer:=NR_FRAME_POINTER_REG;
+ maxpushedparasize:=0;
+ { asmlists }
+ aktproccode:=TAsmList.Create;
+ aktlocaldata:=TAsmList.Create;
+ reference_reset(save_regs_ref,sizeof(aint));
+ { labels }
+ current_asmdata.getjumplabel(CurrExitLabel);
+ current_asmdata.getjumplabel(CurrGOTLabel);
+ CurrBreakLabel:=nil;
+ CurrContinueLabel:=nil;
+ CurrTrueLabel:=nil;
+ CurrFalseLabel:=nil;
+ if Assigned(parent) and (parent.procdef.parast.symtablelevel>=normal_function_level) then
+ parent.addnestedproc(Self);
+ end;
+
+ procedure tprocinfo.force_nested;
+ begin
+ if Assigned(parent) and (parent.procdef.parast.symtablelevel<normal_function_level) then
+ parent.addnestedproc(Self);
+ end;
+
+ destructor tprocinfo.destroy;
+ begin
+ nestedprocs.free;
+ aktproccode.free;
+ aktlocaldata.free;
+ end;
+
+ procedure tprocinfo.destroy_tree;
+ var
+ hp: tprocinfo;
+ begin
+ hp:=Self;
+ while Assigned(hp.parent) do
+ hp:=hp.parent;
+ hp.Free;
+ end;
+
+ procedure tprocinfo.addnestedproc(child: tprocinfo);
+ begin
+ if nestedprocs=nil then
+ nestedprocs:=TLinkedList.Create;
+ nestedprocs.insert(child);
+ end;
+
+ function tprocinfo.get_first_nestedproc: tprocinfo;
+ begin
+ if assigned(nestedprocs) then
+ result:=tprocinfo(nestedprocs.first)
+ else
+ result:=nil;
+ end;
+
+ function tprocinfo.has_nestedprocs: boolean;
+ begin
+ result:=assigned(nestedprocs) and (nestedprocs.count>0);
+ end;
+
+ procedure tprocinfo.save_jump_labels(out saved: tsavedlabels);
+ begin
+ saved[false]:=CurrFalseLabel;
+ saved[true]:=CurrTrueLabel;
+ current_asmdata.getjumplabel(CurrTrueLabel);
+ current_asmdata.getjumplabel(CurrFalseLabel);
+ end;
+
+ procedure tprocinfo.restore_jump_labels(const saved: tsavedlabels);
+ begin
+ CurrFalseLabel:=saved[false];
+ CurrTrueLabel:=saved[true];
+ end;
+
+ procedure tprocinfo.allocate_push_parasize(size:longint);
+ begin
+ if size>maxpushedparasize then
+ maxpushedparasize:=size;
+ end;
+
+
+ function tprocinfo.calc_stackframe_size:longint;
+ begin
+ result:=Align(tg.direction*tg.lasttemp,current_settings.alignment.localalignmin);
+ end;
+
+
+ procedure tprocinfo.set_first_temp_offset;
+ begin
+ end;
+
+
+ procedure tprocinfo.generate_parameter_info;
+ begin
+ { generate callee paraloc register info, it initialises the size that
+ is allocated on the stack }
+ procdef.init_paraloc_info(calleeside);
+ para_stack_size:=procdef.calleeargareasize;
+ end;
+
+
+ procedure tprocinfo.allocate_got_register(list: TAsmList);
+ begin
+ { most os/cpu combo's don't use this yet, so not yet abstract }
+ end;
+
+
+end.
diff --git a/closures/compiler/pstatmnt.pas b/closures/compiler/pstatmnt.pas
new file mode 100644
index 0000000000..78eb251908
--- /dev/null
+++ b/closures/compiler/pstatmnt.pas
@@ -0,0 +1,1397 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Does the parsing of the statements
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit pstatmnt;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ tokens,node;
+
+
+ function statement_block(starttoken : ttoken) : tnode;
+
+ { reads an assembler block }
+ function assembler_block : tnode;
+
+
+implementation
+
+ uses
+ { common }
+ cutils,cclasses,
+ { global }
+ globtype,globals,verbose,constexp,
+ systems,
+ { aasm }
+ cpubase,aasmbase,aasmtai,aasmdata,
+ { symtable }
+ symconst,symbase,symtype,symdef,symsym,symtable,defutil,defcmp,
+ paramgr,symutil,
+ { pass 1 }
+ pass_1,htypechk,
+ nutils,nbas,nmat,nadd,ncal,nmem,nset,ncnv,ninl,ncon,nld,nflw,
+ { parser }
+ scanner,
+ pbase,pexpr,
+ { codegen }
+ procinfo,cgbase,
+ { assembler reader }
+ rabase,
+ { wide- and unicodestrings}
+ widestr
+ ;
+
+
+ function statement : tnode;forward;
+
+
+ function if_statement : tnode;
+ var
+ ex,if_a,else_a : tnode;
+ begin
+ consume(_IF);
+ ex:=comp_expr(true,false);
+ consume(_THEN);
+ if token<>_ELSE then
+ if_a:=statement
+ else
+ if_a:=nil;
+
+ if try_to_consume(_ELSE) then
+ else_a:=statement
+ else
+ else_a:=nil;
+ result:=cifnode.create(ex,if_a,else_a);
+ end;
+
+ { creates a block (list) of statements, til the next END token }
+ function statements_til_end : tnode;
+
+ var
+ first,last : tstatementnode;
+
+ begin
+ first:=nil;
+ while token<>_END do
+ begin
+ if first=nil then
+ begin
+ last:=cstatementnode.create(statement,nil);
+ first:=last;
+ end
+ else
+ begin
+ last.right:=cstatementnode.create(statement,nil);
+ last:=tstatementnode(last.right);
+ end;
+ if not try_to_consume(_SEMICOLON) then
+ break;
+ consume_emptystats;
+ end;
+ consume(_END);
+ statements_til_end:=cblocknode.create(first);
+ end;
+
+
+ function case_statement : tnode;
+ var
+ casedef : tdef;
+ caseexpr,p : tnode;
+ blockid : longint;
+ hl1,hl2 : TConstExprInt;
+ sl1,sl2 : tstringconstnode;
+ casedeferror, caseofstring : boolean;
+ casenode : tcasenode;
+ begin
+ consume(_CASE);
+ caseexpr:=comp_expr(true,false);
+ { determines result type }
+ do_typecheckpass(caseexpr);
+ { variants must be accepted, but first they must be converted to integer }
+ if caseexpr.resultdef.typ=variantdef then
+ begin
+ caseexpr:=ctypeconvnode.create_internal(caseexpr,sinttype);
+ do_typecheckpass(caseexpr);
+ end;
+ set_varstate(caseexpr,vs_read,[vsf_must_be_valid]);
+ casedeferror:=false;
+ casedef:=caseexpr.resultdef;
+ { case of string must be rejected in delphi-, }
+ { tp7/bp7-, mac-compatibility modes. }
+ caseofstring :=
+ ([m_delphi, m_mac, m_tp7] * current_settings.modeswitches = []) and
+ is_string(casedef);
+
+ if (not assigned(casedef)) or
+ ( not(is_ordinal(casedef)) and (not caseofstring) ) then
+ begin
+ CGMessage(type_e_ordinal_or_string_expr_expected);
+ { create a correct tree }
+ caseexpr.free;
+ caseexpr:=cordconstnode.create(0,u32inttype,false);
+ { set error flag so no rangechecks are done }
+ casedeferror:=true;
+ end;
+ { Create casenode }
+ casenode:=ccasenode.create(caseexpr);
+ consume(_OF);
+ { Parse all case blocks }
+ blockid:=0;
+ repeat
+ { maybe an instruction has more case labels }
+ repeat
+ p:=expr(true);
+ if is_widechar(casedef) then
+ begin
+ if (p.nodetype=rangen) then
+ begin
+ trangenode(p).left:=ctypeconvnode.create(trangenode(p).left,cwidechartype);
+ trangenode(p).right:=ctypeconvnode.create(trangenode(p).right,cwidechartype);
+ do_typecheckpass(trangenode(p).left);
+ do_typecheckpass(trangenode(p).right);
+ end
+ else
+ begin
+ p:=ctypeconvnode.create(p,cwidechartype);
+ do_typecheckpass(p);
+ end;
+ end
+ else
+ begin
+ if is_char(casedef) and is_widechar(p.resultdef) then
+ begin
+ if (p.nodetype=ordconstn) then
+ begin
+ p:=ctypeconvnode.create(p,cchartype);
+ do_typecheckpass(p);
+ end
+ else if (p.nodetype=rangen) then
+ begin
+ trangenode(p).left:=ctypeconvnode.create(trangenode(p).left,cchartype);
+ trangenode(p).right:=ctypeconvnode.create(trangenode(p).right,cchartype);
+ do_typecheckpass(trangenode(p).left);
+ do_typecheckpass(trangenode(p).right);
+ end;
+ end;
+ end;
+ hl1:=0;
+ hl2:=0;
+ sl1:=nil;
+ sl2:=nil;
+ if (p.nodetype=rangen) then
+ begin
+ { type check for string case statements }
+ if caseofstring and
+ is_conststring_or_constcharnode(trangenode(p).left) and
+ is_conststring_or_constcharnode(trangenode(p).right) then
+ begin
+ { we need stringconstnodes, even if expression contains single chars }
+ sl1 := get_string_value(trangenode(p).left, tstringdef(casedef));
+ sl2 := get_string_value(trangenode(p).right, tstringdef(casedef));
+ if sl1.fullcompare(sl2) > 0 then
+ CGMessage(parser_e_case_lower_less_than_upper_bound);
+ end
+ { type checking for ordinal case statements }
+ else if (not caseofstring) and
+ is_subequal(casedef, trangenode(p).left.resultdef) and
+ is_subequal(casedef, trangenode(p).right.resultdef) then
+ begin
+ hl1:=get_ordinal_value(trangenode(p).left);
+ hl2:=get_ordinal_value(trangenode(p).right);
+ if hl1>hl2 then
+ CGMessage(parser_e_case_lower_less_than_upper_bound);
+ if not casedeferror then
+ begin
+ testrange(casedef,hl1,false,false);
+ testrange(casedef,hl2,false,false);
+ end;
+ end
+ else
+ CGMessage(parser_e_case_mismatch);
+
+ if caseofstring then
+ casenode.addlabel(blockid,sl1,sl2)
+ else
+ casenode.addlabel(blockid,hl1,hl2);
+ end
+ else
+ begin
+ { type check for string case statements }
+ if (caseofstring and (not is_conststring_or_constcharnode(p))) or
+ { type checking for ordinal case statements }
+ ((not caseofstring) and (not is_subequal(casedef, p.resultdef))) then
+ CGMessage(parser_e_case_mismatch);
+
+ if caseofstring then
+ begin
+ sl1:=get_string_value(p, tstringdef(casedef));
+ casenode.addlabel(blockid,sl1,sl1);
+ end
+ else
+ begin
+ hl1:=get_ordinal_value(p);
+ if not casedeferror then
+ testrange(casedef,hl1,false,false);
+ casenode.addlabel(blockid,hl1,hl1);
+ end;
+ end;
+ p.free;
+ sl1.free;
+ sl2.free;
+
+ if token=_COMMA then
+ consume(_COMMA)
+ else
+ break;
+ until false;
+ consume(_COLON);
+
+ { add instruction block }
+ casenode.addblock(blockid,statement);
+
+ { next block }
+ inc(blockid);
+
+ if not(token in [_ELSE,_OTHERWISE,_END]) then
+ consume(_SEMICOLON);
+ until (token in [_ELSE,_OTHERWISE,_END]);
+
+ if (token in [_ELSE,_OTHERWISE]) then
+ begin
+ if not try_to_consume(_ELSE) then
+ consume(_OTHERWISE);
+ casenode.addelseblock(statements_til_end);
+ end
+ else
+ consume(_END);
+
+ result:=casenode;
+ end;
+
+
+ function repeat_statement : tnode;
+
+ var
+ first,last,p_e : tnode;
+
+ begin
+ consume(_REPEAT);
+ first:=nil;
+
+ while token<>_UNTIL do
+ begin
+ if first=nil then
+ begin
+ last:=cstatementnode.create(statement,nil);
+ first:=last;
+ end
+ else
+ begin
+ tstatementnode(last).right:=cstatementnode.create(statement,nil);
+ last:=tstatementnode(last).right;
+ end;
+ if not try_to_consume(_SEMICOLON) then
+ break;
+ consume_emptystats;
+ end;
+ consume(_UNTIL);
+
+ first:=cblocknode.create(first);
+ p_e:=comp_expr(true,false);
+ result:=cwhilerepeatnode.create(p_e,first,false,true);
+ end;
+
+
+ function while_statement : tnode;
+
+ var
+ p_e,p_a : tnode;
+
+ begin
+ consume(_WHILE);
+ p_e:=comp_expr(true,false);
+ consume(_DO);
+ p_a:=statement;
+ result:=cwhilerepeatnode.create(p_e,p_a,true,false);
+ end;
+
+
+ function for_statement : tnode;
+
+ procedure check_range(hp:tnode; fordef: tdef);
+ begin
+ if (hp.nodetype=ordconstn) and
+ (fordef.typ<>errordef) then
+ testrange(fordef,tordconstnode(hp).value,false,true);
+ end;
+
+ function for_loop_create(hloopvar: tnode): tnode;
+ var
+ hp,
+ hblock,
+ hto,hfrom : tnode;
+ backward : boolean;
+ loopvarsym : tabstractvarsym;
+ begin
+ { Check loop variable }
+ loopvarsym:=nil;
+
+ { variable must be an ordinal, int64 is not allowed for 32bit targets }
+ if not(is_ordinal(hloopvar.resultdef))
+ {$ifndef cpu64bitaddr}
+ or is_64bitint(hloopvar.resultdef)
+ {$endif not cpu64bitaddr}
+ then
+ MessagePos(hloopvar.fileinfo,type_e_ordinal_expr_expected);
+
+ hp:=hloopvar;
+ while assigned(hp) and
+ (
+ { record/object fields and array elements are allowed }
+ { in tp7 mode only }
+ (
+ (m_tp7 in current_settings.modeswitches) and
+ (
+ ((hp.nodetype=subscriptn) and
+ ((tsubscriptnode(hp).left.resultdef.typ=recorddef) or
+ is_object(tsubscriptnode(hp).left.resultdef))
+ ) or
+ { constant array index }
+ (
+ (hp.nodetype=vecn) and
+ is_constintnode(tvecnode(hp).right)
+ )
+ )
+ ) or
+ { equal typeconversions }
+ (
+ (hp.nodetype=typeconvn) and
+ (ttypeconvnode(hp).convtype=tc_equal)
+ )
+ ) do
+ begin
+ { Use the recordfield for loopvarsym }
+ if not assigned(loopvarsym) and
+ (hp.nodetype=subscriptn) then
+ loopvarsym:=tsubscriptnode(hp).vs;
+ hp:=tunarynode(hp).left;
+ end;
+
+ if assigned(hp) and
+ (hp.nodetype=loadn) then
+ begin
+ case tloadnode(hp).symtableentry.typ of
+ staticvarsym,
+ localvarsym,
+ paravarsym :
+ begin
+ { we need a simple loadn:
+ 1. The load must be in a global symtable or
+ in the same level as the para of the current proc.
+ 2. value variables (no const,out or var)
+ 3. No threadvar, readonly or typedconst
+ }
+ if (
+ (tloadnode(hp).symtable.symtablelevel=main_program_level) or
+ (tloadnode(hp).symtable.symtablelevel=current_procinfo.procdef.parast.symtablelevel)
+ ) and
+ (tabstractvarsym(tloadnode(hp).symtableentry).varspez=vs_value) and
+ ([vo_is_thread_var,vo_is_typed_const] * tabstractvarsym(tloadnode(hp).symtableentry).varoptions=[]) then
+ begin
+ { Assigning for-loop variable is only allowed in tp7 and macpas }
+ if ([m_tp7,m_mac] * current_settings.modeswitches = []) then
+ begin
+ if not assigned(loopvarsym) then
+ loopvarsym:=tabstractvarsym(tloadnode(hp).symtableentry);
+ include(loopvarsym.varoptions,vo_is_loop_counter);
+ end;
+ end
+ else
+ begin
+ { Typed const is allowed in tp7 }
+ if not(m_tp7 in current_settings.modeswitches) or
+ not(vo_is_typed_const in tabstractvarsym(tloadnode(hp).symtableentry).varoptions) then
+ MessagePos(hp.fileinfo,type_e_illegal_count_var);
+ end;
+ end;
+ else
+ MessagePos(hp.fileinfo,type_e_illegal_count_var);
+ end;
+ end
+ else
+ MessagePos(hloopvar.fileinfo,type_e_illegal_count_var);
+
+ hfrom:=comp_expr(true,false);
+
+ if try_to_consume(_DOWNTO) then
+ backward:=true
+ else
+ begin
+ consume(_TO);
+ backward:=false;
+ end;
+
+ hto:=comp_expr(true,false);
+ consume(_DO);
+
+ { Check if the constants fit in the range }
+ check_range(hfrom,hloopvar.resultdef);
+ check_range(hto,hloopvar.resultdef);
+
+ { first set the varstate for from and to, so
+ uses of loopvar in those expressions will also
+ trigger a warning when it is not used yet. This
+ needs to be done before the instruction block is
+ parsed to have a valid hloopvar }
+ typecheckpass(hfrom);
+ set_varstate(hfrom,vs_read,[vsf_must_be_valid]);
+ typecheckpass(hto);
+ set_varstate(hto,vs_read,[vsf_must_be_valid]);
+ typecheckpass(hloopvar);
+ { in two steps, because vs_readwritten may turn on vsf_must_be_valid }
+ { for some subnodes }
+ set_varstate(hloopvar,vs_written,[]);
+ set_varstate(hloopvar,vs_read,[vsf_must_be_valid]);
+
+ { ... now the instruction block }
+ hblock:=statement;
+
+ { variable is not used for loop counter anymore }
+ if assigned(loopvarsym) then
+ exclude(loopvarsym.varoptions,vo_is_loop_counter);
+
+ result:=cfornode.create(hloopvar,hfrom,hto,hblock,backward);
+ end;
+
+
+ function for_in_loop_create(hloopvar: tnode): tnode;
+ var
+ expr: tnode;
+ begin
+ expr:=comp_expr(true,false);
+
+ consume(_DO);
+
+ set_varstate(hloopvar,vs_written,[]);
+ set_varstate(hloopvar,vs_read,[vsf_must_be_valid]);
+
+ result:=create_for_in_loop(hloopvar,statement,expr);
+
+ expr.free;
+ end;
+
+
+ var
+ hloopvar: tnode;
+ begin
+ { parse loop header }
+ consume(_FOR);
+
+ hloopvar:=factor(false,false);
+ valid_for_loopvar(hloopvar,true);
+
+ if try_to_consume(_ASSIGNMENT) then
+ result:=for_loop_create(hloopvar)
+ else if try_to_consume(_IN) then
+ result:=for_in_loop_create(hloopvar)
+ else
+ consume(_ASSIGNMENT); // fail
+ end;
+
+
+ function _with_statement : tnode;
+
+ var
+ p : tnode;
+ i : longint;
+ st : TSymtable;
+ newblock : tblocknode;
+ newstatement : tstatementnode;
+ calltempnode,
+ tempnode : ttempcreatenode;
+ valuenode,
+ hp,
+ refnode : tnode;
+ hdef : tdef;
+ extendeddef : tabstractrecorddef;
+ helperdef : tobjectdef;
+ hasimplicitderef : boolean;
+ withsymtablelist : TFPObjectList;
+
+ procedure pushobjchild(withdef,obj:tobjectdef);
+ var
+ parenthelperdef : tobjectdef;
+ begin
+ if not assigned(obj) then
+ exit;
+ pushobjchild(withdef,obj.childof);
+ { we need to look for helpers that were defined for the parent
+ class as well }
+ search_last_objectpascal_helper(obj,current_structdef,parenthelperdef);
+ { push the symtables of the helper's parents in reverse order }
+ if assigned(parenthelperdef) then
+ pushobjchild(withdef,parenthelperdef.childof);
+ { keep the original tobjectdef as owner, because that is used for
+ visibility of the symtable }
+ st:=twithsymtable.create(withdef,obj.symtable.SymList,refnode.getcopy);
+ symtablestack.push(st);
+ withsymtablelist.add(st);
+ { push the symtable of the helper }
+ if assigned(parenthelperdef) then
+ begin
+ st:=twithsymtable.create(withdef,parenthelperdef.symtable.SymList,refnode.getcopy);
+ symtablestack.push(st);
+ withsymtablelist.add(st);
+ end;
+ end;
+
+
+ begin
+ p:=comp_expr(true,false);
+ do_typecheckpass(p);
+
+ if (p.nodetype=vecn) and
+ (nf_memseg in p.flags) then
+ CGMessage(parser_e_no_with_for_variable_in_other_segments);
+
+ { "with procvar" can never mean anything, so always try
+ to call it in case it returns a record/object/... }
+ maybe_call_procvar(p,false);
+
+ if (p.resultdef.typ in [objectdef,recorddef,classrefdef]) then
+ begin
+ newblock:=nil;
+ valuenode:=nil;
+ tempnode:=nil;
+
+ { ignore nodes that don't add instructions in the tree }
+ hp:=p;
+ while { equal type conversions }
+ (
+ (hp.nodetype=typeconvn) and
+ (ttypeconvnode(hp).convtype=tc_equal)
+ ) or
+ { constant array index }
+ (
+ (hp.nodetype=vecn) and
+ (tvecnode(hp).right.nodetype=ordconstn)
+ ) do
+ hp:=tunarynode(hp).left;
+ if (hp.nodetype=loadn) and
+ (
+ (tloadnode(hp).symtable=current_procinfo.procdef.localst) or
+ (tloadnode(hp).symtable=current_procinfo.procdef.parast) or
+ (tloadnode(hp).symtable.symtabletype in [staticsymtable,globalsymtable])
+ ) and
+ { MacPas objects are mapped to classes, and the MacPas compilers
+ interpret with-statements with MacPas objects the same way
+ as records (the object referenced by the with-statement
+ must remain constant)
+ }
+ not(is_class(hp.resultdef) and
+ (m_mac in current_settings.modeswitches)) then
+ begin
+ { simple load, we can reference direct }
+ refnode:=p;
+ end
+ else
+ begin
+ calltempnode:=nil;
+ { complex load, load in temp first }
+ newblock:=internalstatements(newstatement);
+ { when we can't take the address of p, load it in a temp }
+ { since we may need its address later on }
+ if not valid_for_addr(p,false) then
+ begin
+ calltempnode:=ctempcreatenode.create(p.resultdef,p.resultdef.size,tt_persistent,true);
+ addstatement(newstatement,calltempnode);
+ addstatement(newstatement,cassignmentnode.create(
+ ctemprefnode.create(calltempnode),
+ p));
+ p:=ctemprefnode.create(calltempnode);
+ typecheckpass(p);
+ end;
+ { several object types have implicit dereferencing }
+ hasimplicitderef:=is_implicit_pointer_object_type(p.resultdef) or
+ (p.resultdef.typ = classrefdef);
+ if hasimplicitderef then
+ hdef:=p.resultdef
+ else
+ hdef:=tpointerdef.create(p.resultdef);
+ { load address of the value in a temp }
+ tempnode:=ctempcreatenode.create_withnode(hdef,sizeof(pint),tt_persistent,true,p);
+ typecheckpass(tnode(tempnode));
+ valuenode:=p;
+ refnode:=ctemprefnode.create(tempnode);
+ fillchar(refnode.fileinfo,sizeof(tfileposinfo),0);
+ { add address call for valuenode and deref for refnode if this
+ is not done implicitly }
+ if not hasimplicitderef then
+ begin
+ valuenode:=caddrnode.create_internal_nomark(valuenode);
+ refnode:=cderefnode.create(refnode);
+ fillchar(refnode.fileinfo,sizeof(tfileposinfo),0);
+ end;
+ addstatement(newstatement,tempnode);
+ addstatement(newstatement,cassignmentnode.create(
+ ctemprefnode.create(tempnode),
+ valuenode));
+ typecheckpass(refnode);
+ end;
+
+ { do we have a helper for this type? }
+ if p.resultdef.typ=classrefdef then
+ extendeddef:=tobjectdef(tclassrefdef(p.resultdef).pointeddef)
+ else
+ extendeddef:=tabstractrecorddef(p.resultdef);
+ search_last_objectpascal_helper(extendeddef,current_structdef,helperdef);
+ { Note: the symtable of the helper is pushed after the following
+ "case", the symtables of the helper's parents are passed in
+ the "case" branches }
+
+ withsymtablelist:=TFPObjectList.create(true);
+ case p.resultdef.typ of
+ objectdef :
+ begin
+ { push symtables of all parents in reverse order }
+ pushobjchild(tobjectdef(p.resultdef),tobjectdef(p.resultdef).childof);
+ { push symtables of all parents of the helper in reverse order }
+ if assigned(helperdef) then
+ pushobjchild(helperdef,helperdef.childof);
+ { push object symtable }
+ st:=twithsymtable.Create(tobjectdef(p.resultdef),tobjectdef(p.resultdef).symtable.SymList,refnode);
+ symtablestack.push(st);
+ withsymtablelist.add(st);
+ end;
+ classrefdef :
+ begin
+ { push symtables of all parents in reverse order }
+ pushobjchild(tobjectdef(tclassrefdef(p.resultdef).pointeddef),tobjectdef(tclassrefdef(p.resultdef).pointeddef).childof);
+ { push symtables of all parents of the helper in reverse order }
+ if assigned(helperdef) then
+ pushobjchild(helperdef,helperdef.childof);
+ { push object symtable }
+ st:=twithsymtable.Create(tobjectdef(tclassrefdef(p.resultdef).pointeddef),tobjectdef(tclassrefdef(p.resultdef).pointeddef).symtable.SymList,refnode);
+ symtablestack.push(st);
+ withsymtablelist.add(st);
+ end;
+ recorddef :
+ begin
+ { push symtables of all parents of the helper in reverse order }
+ if assigned(helperdef) then
+ pushobjchild(helperdef,helperdef.childof);
+ { push record symtable }
+ st:=twithsymtable.create(trecorddef(p.resultdef),trecorddef(p.resultdef).symtable.SymList,refnode);
+ symtablestack.push(st);
+ withsymtablelist.add(st);
+ end;
+ else
+ internalerror(200601271);
+ end;
+
+ { push helper symtable }
+ if assigned(helperdef) then
+ begin
+ st:=twithsymtable.Create(helperdef,helperdef.symtable.SymList,refnode.getcopy);
+ symtablestack.push(st);
+ withsymtablelist.add(st);
+ end;
+
+ if try_to_consume(_COMMA) then
+ p:=_with_statement()
+ else
+ begin
+ consume(_DO);
+ if token<>_SEMICOLON then
+ p:=statement
+ else
+ p:=cnothingnode.create;
+ end;
+
+ { remove symtables in reverse order from the stack }
+ for i:=withsymtablelist.count-1 downto 0 do
+ symtablestack.pop(TSymtable(withsymtablelist[i]));
+ withsymtablelist.free;
+
+// p:=cwithnode.create(right,twithsymtable(withsymtable),levelcount,refnode);
+
+ { Finalize complex withnode with destroy of temp }
+ if assigned(newblock) then
+ begin
+ addstatement(newstatement,p);
+ if assigned(tempnode) then
+ addstatement(newstatement,ctempdeletenode.create(tempnode));
+ if assigned(calltempnode) then
+ addstatement(newstatement,ctempdeletenode.create(calltempnode));
+ p:=newblock;
+ end;
+ result:=p;
+ end
+ else
+ begin
+ p.free;
+ Message(parser_e_false_with_expr);
+ { try to recover from error }
+ if try_to_consume(_COMMA) then
+ begin
+ hp:=_with_statement();
+ if (hp=nil) then; { remove warning about unused }
+ end
+ else
+ begin
+ consume(_DO);
+ { ignore all }
+ if token<>_SEMICOLON then
+ statement;
+ end;
+ result:=nil;
+ end;
+ end;
+
+
+ function with_statement : tnode;
+ begin
+ consume(_WITH);
+ with_statement:=_with_statement();
+ end;
+
+
+ function raise_statement : tnode;
+ var
+ p,pobj,paddr,pframe : tnode;
+ begin
+ pobj:=nil;
+ paddr:=nil;
+ pframe:=nil;
+ consume(_RAISE);
+ if not(token in endtokens) then
+ begin
+ { object }
+ pobj:=comp_expr(true,false);
+ if try_to_consume(_AT) then
+ begin
+ paddr:=comp_expr(true,false);
+ if try_to_consume(_COMMA) then
+ pframe:=comp_expr(true,false);
+ end;
+ end
+ else
+ begin
+ if (block_type<>bt_except) then
+ Message(parser_e_no_reraise_possible);
+ end;
+ p:=craisenode.create(pobj,paddr,pframe);
+ raise_statement:=p;
+ end;
+
+
+ function try_statement : tnode;
+ var
+ p_try_block,p_finally_block,first,last,
+ p_default,p_specific,hp : tnode;
+ ot : tDef;
+ sym : tlocalvarsym;
+ old_block_type : tblock_type;
+ excepTSymtable : TSymtable;
+ objname,objrealname : TIDString;
+ srsym : tsym;
+ srsymtable : TSymtable;
+ t:ttoken;
+ unit_found:boolean;
+ oldcurrent_exceptblock: integer;
+ begin
+ p_default:=nil;
+ p_specific:=nil;
+
+ { read statements to try }
+ consume(_TRY);
+ first:=nil;
+ inc(exceptblockcounter);
+ oldcurrent_exceptblock := current_exceptblock;
+ current_exceptblock := exceptblockcounter;
+
+ while (token<>_FINALLY) and (token<>_EXCEPT) do
+ begin
+ if first=nil then
+ begin
+ last:=cstatementnode.create(statement,nil);
+ first:=last;
+ end
+ else
+ begin
+ tstatementnode(last).right:=cstatementnode.create(statement,nil);
+ last:=tstatementnode(last).right;
+ end;
+ if not try_to_consume(_SEMICOLON) then
+ break;
+ consume_emptystats;
+ end;
+ p_try_block:=cblocknode.create(first);
+
+ if try_to_consume(_FINALLY) then
+ begin
+ inc(exceptblockcounter);
+ current_exceptblock := exceptblockcounter;
+ p_finally_block:=statements_til_end;
+ try_statement:=ctryfinallynode.create(p_try_block,p_finally_block);
+ end
+ else
+ begin
+ consume(_EXCEPT);
+ old_block_type:=block_type;
+ block_type:=bt_except;
+ inc(exceptblockcounter);
+ current_exceptblock := exceptblockcounter;
+ ot:=generrordef;
+ p_specific:=nil;
+ if (idtoken=_ON) then
+ { catch specific exceptions }
+ begin
+ repeat
+ consume(_ON);
+ if token=_ID then
+ begin
+ objname:=pattern;
+ objrealname:=orgpattern;
+ { can't use consume_sym here, because we need already
+ to check for the colon }
+ searchsym(objname,srsym,srsymtable);
+ consume(_ID);
+ { is a explicit name for the exception given ? }
+ if try_to_consume(_COLON) then
+ begin
+ consume_sym(srsym,srsymtable);
+ if (srsym.typ=typesym) and
+ is_class(ttypesym(srsym).typedef) then
+ begin
+ ot:=ttypesym(srsym).typedef;
+ sym:=tlocalvarsym.create(objrealname,vs_value,ot,[]);
+ end
+ else
+ begin
+ sym:=tlocalvarsym.create(objrealname,vs_value,generrordef,[]);
+ if (srsym.typ=typesym) then
+ Message1(type_e_class_type_expected,ttypesym(srsym).typedef.typename)
+ else
+ Message1(type_e_class_type_expected,ot.typename);
+ end;
+ excepTSymtable:=tstt_excepTSymtable.create;
+ excepTSymtable.insert(sym);
+ symtablestack.push(excepTSymtable);
+ end
+ else
+ begin
+ { check if type is valid, must be done here because
+ with "e: Exception" the e is not necessary }
+
+ { support unit.identifier }
+ unit_found:=try_consume_unitsym(srsym,srsymtable,t,false);
+ if srsym=nil then
+ begin
+ identifier_not_found(orgpattern);
+ srsym:=generrorsym;
+ end;
+ if unit_found then
+ consume(t);
+ { check if type is valid, must be done here because
+ with "e: Exception" the e is not necessary }
+ if (srsym.typ=typesym) and
+ is_class(ttypesym(srsym).typedef) then
+ ot:=ttypesym(srsym).typedef
+ else
+ begin
+ ot:=generrordef;
+ if (srsym.typ=typesym) then
+ Message1(type_e_class_type_expected,ttypesym(srsym).typedef.typename)
+ else
+ Message1(type_e_class_type_expected,ot.typename);
+ end;
+ excepTSymtable:=nil;
+ end;
+ end
+ else
+ consume(_ID);
+ consume(_DO);
+ hp:=connode.create(nil,statement);
+ if ot.typ=errordef then
+ begin
+ hp.free;
+ hp:=cerrornode.create;
+ end;
+ if p_specific=nil then
+ begin
+ last:=hp;
+ p_specific:=last;
+ end
+ else
+ begin
+ tonnode(last).left:=hp;
+ last:=tonnode(last).left;
+ end;
+ { set the informations }
+ { only if the creation of the onnode was succesful, it's possible }
+ { that last and hp are errornodes (JM) }
+ if last.nodetype = onn then
+ begin
+ tonnode(last).excepttype:=tobjectdef(ot);
+ tonnode(last).excepTSymtable:=excepTSymtable;
+ end;
+ { remove exception symtable }
+ if assigned(excepTSymtable) then
+ begin
+ symtablestack.pop(excepTSymtable);
+ if last.nodetype <> onn then
+ excepTSymtable.free;
+ end;
+ if not try_to_consume(_SEMICOLON) then
+ break;
+ consume_emptystats;
+ until (token in [_END,_ELSE]);
+ if try_to_consume(_ELSE) then
+ begin
+ { catch the other exceptions }
+ p_default:=statements_til_end;
+ end
+ else
+ consume(_END);
+ end
+ else
+ begin
+ { catch all exceptions }
+ p_default:=statements_til_end;
+ end;
+
+ block_type:=old_block_type;
+ try_statement:=ctryexceptnode.create(p_try_block,p_specific,p_default);
+ end;
+ current_exceptblock := oldcurrent_exceptblock;
+ end;
+
+
+ function _asm_statement : tnode;
+ var
+ asmstat : tasmnode;
+ Marker : tai;
+ reg : tregister;
+ asmreader : tbaseasmreader;
+ begin
+ Inside_asm_statement:=true;
+ if assigned(asmmodeinfos[current_settings.asmmode]) then
+ begin
+ asmreader:=asmmodeinfos[current_settings.asmmode]^.casmreader.create;
+ asmstat:=casmnode.create(asmreader.assemble as TAsmList);
+ asmreader.free;
+ end
+ else
+ Message(parser_f_assembler_reader_not_supported);
+
+ { Mark procedure that it has assembler blocks }
+ include(current_procinfo.flags,pi_has_assembler_block);
+
+ { Read first the _ASM statement }
+ consume(_ASM);
+
+ { END is read, got a list of changed registers? }
+ if try_to_consume(_LECKKLAMMER) then
+ begin
+{$ifdef cpunofpu}
+ asmstat.used_regs_fpu:=[0..first_int_imreg-1];
+{$else cpunofpu}
+ asmstat.used_regs_fpu:=[0..first_fpu_imreg-1];
+{$endif cpunofpu}
+ if token<>_RECKKLAMMER then
+ begin
+ if po_assembler in current_procinfo.procdef.procoptions then
+ Message(parser_w_register_list_ignored);
+ repeat
+ { it's possible to specify the modified registers }
+ reg:=std_regnum_search(lower(cstringpattern));
+ if reg<>NR_NO then
+ begin
+ if (getregtype(reg)=R_INTREGISTER) and not(po_assembler in current_procinfo.procdef.procoptions) then
+ include(asmstat.used_regs_int,getsupreg(reg));
+ end
+ else
+ Message(asmr_e_invalid_register);
+ consume(_CSTRING);
+ if not try_to_consume(_COMMA) then
+ break;
+ until false;
+ end;
+ consume(_RECKKLAMMER);
+ end
+ else
+ begin
+ asmstat.used_regs_int:=paramanager.get_volatile_registers_int(current_procinfo.procdef.proccalloption);
+ asmstat.used_regs_fpu:=paramanager.get_volatile_registers_fpu(current_procinfo.procdef.proccalloption);
+ end;
+
+ { mark the start and the end of the assembler block
+ this is needed for the optimizer }
+ If Assigned(AsmStat.p_asm) Then
+ Begin
+ Marker := Tai_Marker.Create(mark_AsmBlockStart);
+ AsmStat.p_asm.Insert(Marker);
+ Marker := Tai_Marker.Create(mark_AsmBlockEnd);
+ AsmStat.p_asm.Concat(Marker);
+ End;
+ Inside_asm_statement:=false;
+ _asm_statement:=asmstat;
+ end;
+
+
+ function statement : tnode;
+ var
+ p,
+ code : tnode;
+ filepos : tfileposinfo;
+ srsym : tsym;
+ srsymtable : TSymtable;
+ s : TIDString;
+ begin
+ filepos:=current_tokenpos;
+ case token of
+ _GOTO :
+ begin
+ if not(cs_support_goto in current_settings.moduleswitches) then
+ Message(sym_e_goto_and_label_not_supported);
+ consume(_GOTO);
+ if (token<>_INTCONST) and (token<>_ID) then
+ begin
+ Message(sym_e_label_not_found);
+ code:=cerrornode.create;
+ end
+ else
+ begin
+ if token=_ID then
+ consume_sym(srsym,srsymtable)
+ else
+ begin
+ if token<>_INTCONST then
+ internalerror(201008021);
+
+ { strip leading 0's in iso mode }
+ if m_iso in current_settings.modeswitches then
+ while pattern[1]='0' do
+ delete(pattern,1,1);
+
+ searchsym(pattern,srsym,srsymtable);
+ if srsym=nil then
+ begin
+ identifier_not_found(pattern);
+ srsym:=generrorsym;
+ srsymtable:=nil;
+ end;
+ consume(token);
+ end;
+
+ if srsym.typ<>labelsym then
+ begin
+ Message(sym_e_id_is_no_label_id);
+ code:=cerrornode.create;
+ end
+ else
+ begin
+ { goto outside the current scope? }
+ if srsym.owner<>current_procinfo.procdef.localst then
+ begin
+ { allowed? }
+ if not(m_non_local_goto in current_settings.modeswitches) then
+ Message(parser_e_goto_outside_proc);
+ end;
+ code:=cgotonode.create(tlabelsym(srsym));
+ tgotonode(code).labelsym:=tlabelsym(srsym);
+ { set flag that this label is used }
+ tlabelsym(srsym).used:=true;
+ end;
+ end;
+ end;
+ _BEGIN :
+ code:=statement_block(_BEGIN);
+ _IF :
+ code:=if_statement;
+ _CASE :
+ code:=case_statement;
+ _REPEAT :
+ code:=repeat_statement;
+ _WHILE :
+ code:=while_statement;
+ _FOR :
+ code:=for_statement;
+ _WITH :
+ code:=with_statement;
+ _TRY :
+ code:=try_statement;
+ _RAISE :
+ code:=raise_statement;
+ { semicolons,else until and end are ignored }
+ _SEMICOLON,
+ _ELSE,
+ _UNTIL,
+ _END:
+ code:=cnothingnode.create;
+ _FAIL :
+ begin
+ if (current_procinfo.procdef.proctypeoption<>potype_constructor) then
+ Message(parser_e_fail_only_in_constructor);
+ consume(_FAIL);
+ code:=call_fail_node;
+ end;
+ _ASM :
+ code:=_asm_statement;
+ _EOF :
+ Message(scan_f_end_of_file);
+ else
+ begin
+ { don't typecheck yet, because that will also simplify, which may
+ result in not detecting certain kinds of syntax errors --
+ see mantis #15594 }
+ p:=expr(false);
+ { save the pattern here for latter usage, the label could be "000",
+ even if we read an expression, the pattern is still valid if it's really
+ a label (FK)
+ if you want to mess here, take care of
+ tests/webtbs/tw3546.pp
+ }
+ s:=pattern;
+
+ { When a colon follows a intconst then transform it into a label }
+ if (p.nodetype=ordconstn) and
+ try_to_consume(_COLON) then
+ begin
+ { in iso mode, 0003: is equal to 3: }
+ if m_iso in current_settings.modeswitches then
+ searchsym(tostr(tordconstnode(p).value),srsym,srsymtable)
+ else
+ searchsym(s,srsym,srsymtable);
+ p.free;
+
+ if assigned(srsym) and
+ (srsym.typ=labelsym) then
+ begin
+ if tlabelsym(srsym).defined then
+ Message(sym_e_label_already_defined);
+ if symtablestack.top.symtablelevel<>srsymtable.symtablelevel then
+ begin
+ tlabelsym(srsym).nonlocal:=true;
+ exclude(current_procinfo.procdef.procoptions,po_inline);
+ end;
+ if tlabelsym(srsym).nonlocal and
+ (current_procinfo.procdef.proctypeoption in [potype_unitinit,potype_unitfinalize]) then
+ Message(sym_e_interprocgoto_into_init_final_code_not_allowed);
+
+ tlabelsym(srsym).defined:=true;
+ p:=clabelnode.create(nil,tlabelsym(srsym));
+ tlabelsym(srsym).code:=p;
+ end
+ else
+ begin
+ Message1(sym_e_label_used_and_not_defined,s);
+ p:=cnothingnode.create;
+ end;
+ end;
+
+ if p.nodetype=labeln then
+ begin
+ { the pointer to the following instruction }
+ { isn't a very clean way }
+ if token in endtokens then
+ tlabelnode(p).left:=cnothingnode.create
+ else
+ tlabelnode(p).left:=statement();
+ { be sure to have left also typecheckpass }
+ typecheckpass(tlabelnode(p).left);
+ end
+ else
+
+ { change a load of a procvar to a call. this is also
+ supported in fpc mode }
+ if p.nodetype in [vecn,derefn,typeconvn,subscriptn,loadn] then
+ maybe_call_procvar(p,false);
+
+ { blockn support because a read/write is changed into a blocknode }
+ { with a separate statement for each read/write operation (JM) }
+ { the same is true for val() if the third parameter is not 32 bit }
+ if not(p.nodetype in [nothingn,errorn,calln,ifn,assignn,breakn,inlinen,
+ continuen,labeln,blockn,exitn]) or
+ ((p.nodetype=inlinen) and
+ not is_void(p.resultdef)) or
+ ((p.nodetype=calln) and
+ (assigned(tcallnode(p).procdefinition)) and
+ (tcallnode(p).procdefinition.proctypeoption=potype_operator)) then
+ Message(parser_e_illegal_expression);
+
+ if not assigned(p.resultdef) then
+ do_typecheckpass(p);
+
+ { Specify that we don't use the value returned by the call.
+ This is used for :
+ - dispose of temp stack space
+ - dispose on FPU stack
+ - extended syntax checking }
+ if (p.nodetype=calln) then
+ begin
+ exclude(tcallnode(p).callnodeflags,cnf_return_value_used);
+
+ { in $x- state, the function result must not be ignored }
+ if not(cs_extsyntax in current_settings.moduleswitches) and
+ not(is_void(p.resultdef)) and
+ { can be nil in case there was an error in the expression }
+ assigned(tcallnode(p).procdefinition) and
+ not((tcallnode(p).procdefinition.proctypeoption=potype_constructor) and
+ is_object(tprocdef(tcallnode(p).procdefinition).struct)) then
+ Message(parser_e_illegal_expression);
+ end;
+ code:=p;
+ end;
+ end;
+ if assigned(code) then
+ begin
+ typecheckpass(code);
+ code.fileinfo:=filepos;
+ end;
+ statement:=code;
+ end;
+
+
+ function statement_block(starttoken : ttoken) : tnode;
+
+ var
+ first,last : tnode;
+ filepos : tfileposinfo;
+
+ begin
+ first:=nil;
+ filepos:=current_tokenpos;
+ consume(starttoken);
+
+ while not(token in [_END,_FINALIZATION]) do
+ begin
+ if first=nil then
+ begin
+ last:=cstatementnode.create(statement,nil);
+ first:=last;
+ end
+ else
+ begin
+ tstatementnode(last).right:=cstatementnode.create(statement,nil);
+ last:=tstatementnode(last).right;
+ end;
+ if (token in [_END,_FINALIZATION]) then
+ break
+ else
+ begin
+ { if no semicolon, then error and go on }
+ if token<>_SEMICOLON then
+ begin
+ consume(_SEMICOLON);
+ consume_all_until(_SEMICOLON);
+ end;
+ consume(_SEMICOLON);
+ end;
+ consume_emptystats;
+ end;
+
+ { don't consume the finalization token, it is consumed when
+ reading the finalization block, but allow it only after
+ an initalization ! }
+ if (starttoken<>_INITIALIZATION) or (token<>_FINALIZATION) then
+ consume(_END);
+
+ last:=cblocknode.create(first);
+ last.fileinfo:=filepos;
+ statement_block:=last;
+ end;
+
+
+ function assembler_block : tnode;
+ var
+ p : tnode;
+{$ifndef arm}
+ locals : longint;
+{$endif arm}
+ srsym : tsym;
+ begin
+ { Rename the funcret so that recursive calls are possible }
+ if not is_void(current_procinfo.procdef.returndef) then
+ begin
+ srsym:=TSym(current_procinfo.procdef.localst.Find(current_procinfo.procdef.procsym.name));
+ if assigned(srsym) then
+ srsym.realname:='$hiddenresult';
+ end;
+
+ { delphi uses register calling for assembler methods }
+ if (m_delphi in current_settings.modeswitches) and
+ (po_assembler in current_procinfo.procdef.procoptions) and
+ not(po_hascallingconvention in current_procinfo.procdef.procoptions) then
+ current_procinfo.procdef.proccalloption:=pocall_register;
+
+ { force the asm statement }
+ if token<>_ASM then
+ consume(_ASM);
+ include(current_procinfo.flags,pi_is_assembler);
+ p:=_asm_statement;
+
+{$if not(defined(sparc)) and not(defined(arm)) and not(defined(avr))}
+ if (po_assembler in current_procinfo.procdef.procoptions) then
+ begin
+ { set the framepointer to esp for assembler functions when the
+ following conditions are met:
+ - if the are no local variables and parameters (except the allocated result)
+ - no reference to the result variable (refcount<=1)
+ - result is not stored as parameter
+ - target processor has optional frame pointer save
+ (vm, i386, vm only currently)
+ }
+ locals:=tabstractlocalsymtable(current_procinfo.procdef.parast).count_locals;
+ if (current_procinfo.procdef.localst.symtabletype=localsymtable) then
+ inc(locals,tabstractlocalsymtable(current_procinfo.procdef.localst).count_locals);
+ if (locals=0) and
+ not (current_procinfo.procdef.owner.symtabletype in [ObjectSymtable,recordsymtable]) and
+ (not assigned(current_procinfo.procdef.funcretsym) or
+ (tabstractvarsym(current_procinfo.procdef.funcretsym).refs<=1)) and
+ not(paramanager.ret_in_param(current_procinfo.procdef.returndef,current_procinfo.procdef.proccalloption)) then
+ begin
+ { Only need to set the framepointer, the locals will
+ be inserted with the correct reference in tcgasmnode.pass_generate_code }
+ current_procinfo.framepointer:=NR_STACK_POINTER_REG;
+ end;
+ end;
+{$endif not(defined(sparc)) and not(defined(arm)) and not(defined(avr))}
+
+ { Flag the result as assigned when it is returned in a
+ register.
+ }
+ if assigned(current_procinfo.procdef.funcretsym) and
+ (not paramanager.ret_in_param(current_procinfo.procdef.returndef,current_procinfo.procdef.proccalloption)) then
+ tabstractvarsym(current_procinfo.procdef.funcretsym).varstate:=vs_initialised;
+
+ { because the END is already read we need to get the
+ last_endtoken_filepos here (PFV) }
+ last_endtoken_filepos:=current_tokenpos;
+
+ assembler_block:=p;
+ end;
+
+end.
diff --git a/closures/compiler/psub.pas b/closures/compiler/psub.pas
new file mode 100644
index 0000000000..f3d681889e
--- /dev/null
+++ b/closures/compiler/psub.pas
@@ -0,0 +1,2073 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl, Daniel Mantione
+
+ Does the parsing and codegeneration at subroutine level
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit psub;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cclasses,globals,
+ node,nbas,
+ symdef,procinfo,optdfa;
+
+ type
+ tcgprocinfo = class(tprocinfo)
+ private
+ procedure maybe_add_constructor_wrapper(var tocode: tnode; withexceptblock: boolean);
+ procedure add_entry_exit_code;
+ procedure setup_tempgen;
+ public
+ { code for the subroutine as tree }
+ code : tnode;
+ { positions in the tree for init/final }
+ entry_asmnode,
+ loadpara_asmnode,
+ exitlabel_asmnode,
+ stackcheck_asmnode,
+ init_asmnode,
+ final_asmnode : tasmnode;
+ dfabuilder : TDFABuilder;
+ destructor destroy;override;
+ procedure printproc(pass:string);
+ procedure generate_code;
+ procedure generate_code_tree;
+ procedure generate_exceptfilter(nestedpi: tcgprocinfo);
+ procedure resetprocdef;
+ procedure add_to_symtablestack;
+ procedure remove_from_symtablestack;
+ procedure parse_body;
+
+ function has_assembler_child : boolean;
+ end;
+
+
+ procedure printnode_reset;
+
+ { reads the declaration blocks }
+ procedure read_declarations(islibrary : boolean);
+
+ { reads declarations in the interface part of a unit }
+ procedure read_interface_declarations;
+
+ procedure generate_specialization_procs;
+
+
+implementation
+
+ uses
+ sysutils,
+ { common }
+ cutils,
+ { global }
+ globtype,tokens,verbose,comphook,constexp,
+ systems,
+ { aasm }
+ cpuinfo,cpubase,aasmbase,aasmtai,aasmdata,
+ { symtable }
+ symconst,symbase,symsym,symtype,symtable,defutil,
+ paramgr,
+ ppu,fmodule,
+ { pass 1 }
+ nutils,nld,ncal,ncon,nflw,nadd,ncnv,nmem,
+ pass_1,
+ {$ifdef state_tracking}
+ nstate,
+ {$endif state_tracking}
+ { pass 2 }
+{$ifndef NOPASS2}
+ pass_2,
+{$endif}
+ { parser }
+ scanner,import,gendef,
+ pbase,pstatmnt,pdecl,pdecsub,pexports,
+ { codegen }
+ tgobj,cgbase,cgobj,cgcpu,dbgbase,
+ ncgutil,regvars,
+ optbase,
+ opttail,
+ optcse,optloop,
+ optutils
+{$if defined(arm) or defined(powerpc) or defined(powerpc64) or defined(avr)}
+ ,aasmcpu
+{$endif arm}
+ {$ifndef NOOPT}
+ {$ifdef i386}
+ ,aopt386
+ {$else i386}
+ ,aopt
+ {$endif i386}
+ {$endif}
+ ;
+
+{****************************************************************************
+ PROCEDURE/FUNCTION BODY PARSING
+****************************************************************************}
+
+ procedure initializevars(p:TObject;arg:pointer);
+ var
+ b : tblocknode;
+ begin
+ if not (tsym(p).typ in [localvarsym,staticvarsym]) then
+ exit;
+ with tabstractnormalvarsym(p) do
+ begin
+ if assigned(defaultconstsym) then
+ begin
+ b:=tblocknode(arg);
+ b.left:=cstatementnode.create(
+ cassignmentnode.create(
+ cloadnode.create(tsym(p),tsym(p).owner),
+ cloadnode.create(defaultconstsym,defaultconstsym.owner)),
+ b.left);
+ end;
+ end;
+ end;
+
+
+ procedure check_finalize_paras(p:TObject;arg:pointer);
+ begin
+ if (tsym(p).typ=paravarsym) and
+ tparavarsym(p).needs_finalization then
+ include(current_procinfo.flags,pi_needs_implicit_finally);
+ end;
+
+
+ procedure check_finalize_locals(p:TObject;arg:pointer);
+ begin
+ { include the result: it needs to be finalized in case an exception }
+ { occurs }
+ if (tsym(p).typ=localvarsym) and
+ (tlocalvarsym(p).refs>0) and
+ is_managed_type(tlocalvarsym(p).vardef) then
+ include(current_procinfo.flags,pi_needs_implicit_finally);
+ end;
+
+
+ function block(islibrary : boolean) : tnode;
+ var
+ oldfilepos: tfileposinfo;
+ begin
+ { parse const,types and vars }
+ read_declarations(islibrary);
+
+ { do we have an assembler block without the po_assembler?
+ we should allow this for Delphi compatibility (PFV) }
+ if (token=_ASM) and (m_delphi in current_settings.modeswitches) then
+ include(current_procinfo.procdef.procoptions,po_assembler);
+
+ { Handle assembler block different }
+ if (po_assembler in current_procinfo.procdef.procoptions) then
+ begin
+ block:=assembler_block;
+ exit;
+ end;
+
+ {Unit initialization?.}
+ if (
+ assigned(current_procinfo.procdef.localst) and
+ (current_procinfo.procdef.localst.symtablelevel=main_program_level) and
+ (current_module.is_unit or islibrary)
+ ) then
+ begin
+ if (token=_END) then
+ begin
+ consume(_END);
+ { We need at least a node, else the entry/exit code is not
+ generated and thus no PASCALMAIN symbol which we need (PFV) }
+ if islibrary then
+ block:=cnothingnode.create
+ else
+ block:=nil;
+ end
+ else
+ begin
+ if token=_INITIALIZATION then
+ begin
+ { The library init code is already called and does not
+ need to be in the initfinal table (PFV) }
+ block:=statement_block(_INITIALIZATION);
+ end
+ else if token=_FINALIZATION then
+ begin
+ { when a unit has only a finalization section, we can come to this
+ point when we try to read the nonh existing initalization section
+ so we've to check if we are really try to parse the finalization }
+ if current_procinfo.procdef.proctypeoption=potype_unitfinalize then
+ block:=statement_block(_FINALIZATION)
+ else
+ block:=nil;
+ end
+ else
+ block:=statement_block(_BEGIN);
+ end;
+ end
+ else
+ begin
+ block:=statement_block(_BEGIN);
+ if current_procinfo.procdef.localst.symtabletype=localsymtable then
+ begin
+ { initialization of local variables with their initial
+ values: part of function entry }
+ oldfilepos:=current_filepos;
+ current_filepos:=current_procinfo.entrypos;
+ current_procinfo.procdef.localst.SymList.ForEachCall(@initializevars,block);
+ current_filepos:=oldfilepos;
+ end;
+ end;
+ end;
+
+
+{****************************************************************************
+ PROCEDURE/FUNCTION COMPILING
+****************************************************************************}
+
+ procedure printnode_reset;
+ begin
+ assign(printnodefile,treelogfilename);
+ {$push}{$I-}
+ rewrite(printnodefile);
+ {$pop}
+ if ioresult<>0 then
+ begin
+ Comment(V_Error,'Error creating '+treelogfilename);
+ exit;
+ end;
+ close(printnodefile);
+ end;
+
+
+ procedure add_label_init(p:TObject;arg:pointer);
+ begin
+ if tstoredsym(p).typ=labelsym then
+ begin
+ addstatement(tstatementnode(arg^),
+ cifnode.create(caddnode.create(equaln,
+ ccallnode.createintern('fpc_setjmp',
+ ccallparanode.create(cloadnode.create(tlabelsym(p).jumpbuf,tlabelsym(p).jumpbuf.owner),nil)),
+ cordconstnode.create(1,sinttype,true))
+ ,cgotonode.create(tlabelsym(p)),nil)
+ );
+ end;
+ end;
+
+
+ function generate_bodyentry_block:tnode;
+ var
+ srsym : tsym;
+ para : tcallparanode;
+ newstatement : tstatementnode;
+ begin
+ result:=internalstatements(newstatement);
+
+ if assigned(current_structdef) then
+ begin
+ { a constructor needs a help procedure }
+ if (current_procinfo.procdef.proctypeoption=potype_constructor) then
+ begin
+ if is_class(current_structdef) then
+ begin
+ srsym:=search_struct_member(current_structdef,'NEWINSTANCE');
+ if assigned(srsym) and
+ (srsym.typ=procsym) then
+ begin
+ { if vmt>1 then newinstance }
+ addstatement(newstatement,cifnode.create(
+ caddnode.create(gtn,
+ ctypeconvnode.create_internal(
+ load_vmt_pointer_node,
+ voidpointertype),
+ cpointerconstnode.create(1,voidpointertype)),
+ cassignmentnode.create(
+ ctypeconvnode.create_internal(
+ load_self_pointer_node,
+ voidpointertype),
+ ccallnode.create(nil,tprocsym(srsym),srsym.owner,load_vmt_pointer_node,[])),
+ nil));
+ end
+ else
+ internalerror(200305108);
+ end
+ else
+ if is_object(current_structdef) then
+ begin
+ { parameter 3 : vmt_offset }
+ { parameter 2 : address of pointer to vmt,
+ this is required to allow setting the vmt to -1 to indicate
+ that memory was allocated }
+ { parameter 1 : self pointer }
+ para:=ccallparanode.create(
+ cordconstnode.create(tobjectdef(current_structdef).vmt_offset,s32inttype,false),
+ ccallparanode.create(
+ ctypeconvnode.create_internal(
+ load_vmt_pointer_node,
+ voidpointertype),
+ ccallparanode.create(
+ ctypeconvnode.create_internal(
+ load_self_pointer_node,
+ voidpointertype),
+ nil)));
+ addstatement(newstatement,cassignmentnode.create(
+ ctypeconvnode.create_internal(
+ load_self_pointer_node,
+ voidpointertype),
+ ccallnode.createintern('fpc_help_constructor',para)));
+ end
+ else
+ if not is_record(current_structdef) then
+ internalerror(200305103);
+ { if self=nil then exit
+ calling fail instead of exit is useless because
+ there is nothing to dispose (PFV) }
+ if is_class_or_object(current_structdef) then
+ addstatement(newstatement,cifnode.create(
+ caddnode.create(equaln,
+ load_self_pointer_node,
+ cnilnode.create),
+ cexitnode.create(nil),
+ nil));
+ end;
+
+ { maybe call BeforeDestruction for classes }
+ if (current_procinfo.procdef.proctypeoption=potype_destructor) and
+ is_class(current_structdef) then
+ begin
+ srsym:=search_struct_member(current_structdef,'BEFOREDESTRUCTION');
+ if assigned(srsym) and
+ (srsym.typ=procsym) then
+ begin
+ { if vmt>0 then beforedestruction }
+ addstatement(newstatement,cifnode.create(
+ caddnode.create(gtn,
+ ctypeconvnode.create_internal(
+ load_vmt_pointer_node,ptrsinttype),
+ ctypeconvnode.create_internal(
+ cnilnode.create,ptrsinttype)),
+ ccallnode.create(nil,tprocsym(srsym),srsym.owner,load_self_node,[]),
+ nil));
+ end
+ else
+ internalerror(200305104);
+ end;
+ end;
+ if m_non_local_goto in current_settings.modeswitches then
+ tsymtable(current_procinfo.procdef.localst).SymList.ForEachCall(@add_label_init,@newstatement);
+ end;
+
+
+ function generate_bodyexit_block:tnode;
+ var
+ srsym : tsym;
+ para : tcallparanode;
+ newstatement : tstatementnode;
+ oldlocalswitches: tlocalswitches;
+ begin
+ result:=internalstatements(newstatement);
+
+ if assigned(current_structdef) then
+ begin
+ { Don't test self and the vmt here. The reason is that }
+ { a constructor already checks whether these are valid }
+ { before. Further, in case of TThread the thread may }
+ { free the class instance right after AfterConstruction }
+ { has been called, so it may no longer be valid (JM) }
+ oldlocalswitches:=current_settings.localswitches;
+ current_settings.localswitches:=oldlocalswitches-[cs_check_object,cs_check_range];
+
+ { a destructor needs a help procedure }
+ if (current_procinfo.procdef.proctypeoption=potype_destructor) then
+ begin
+ if is_class(current_structdef) then
+ begin
+ srsym:=search_struct_member(current_structdef,'FREEINSTANCE');
+ if assigned(srsym) and
+ (srsym.typ=procsym) then
+ begin
+ { if self<>0 and vmt<>0 then freeinstance }
+ addstatement(newstatement,cifnode.create(
+ caddnode.create(andn,
+ caddnode.create(unequaln,
+ load_self_pointer_node,
+ cnilnode.create),
+ caddnode.create(unequaln,
+ ctypeconvnode.create(
+ load_vmt_pointer_node,
+ voidpointertype),
+ cpointerconstnode.create(0,voidpointertype))),
+ ccallnode.create(nil,tprocsym(srsym),srsym.owner,load_self_node,[]),
+ nil));
+ end
+ else
+ internalerror(200305108);
+ end
+ else
+ if is_object(current_structdef) then
+ begin
+ { finalize object data, but only if not in inherited call }
+ if is_managed_type(current_structdef) then
+ begin
+ addstatement(newstatement,cifnode.create(
+ caddnode.create(unequaln,
+ ctypeconvnode.create_internal(load_vmt_pointer_node,voidpointertype),
+ cnilnode.create),
+ finalize_data_node(load_self_node),
+ nil));
+ end;
+ { parameter 3 : vmt_offset }
+ { parameter 2 : pointer to vmt }
+ { parameter 1 : self pointer }
+ para:=ccallparanode.create(
+ cordconstnode.create(tobjectdef(current_structdef).vmt_offset,s32inttype,false),
+ ccallparanode.create(
+ ctypeconvnode.create_internal(
+ load_vmt_pointer_node,
+ voidpointertype),
+ ccallparanode.create(
+ ctypeconvnode.create_internal(
+ load_self_pointer_node,
+ voidpointertype),
+ nil)));
+ addstatement(newstatement,
+ ccallnode.createintern('fpc_help_destructor',para));
+ end
+ else
+ internalerror(200305105);
+ end;
+ current_settings.localswitches:=oldlocalswitches;
+ end;
+ end;
+
+
+ function generate_except_block:tnode;
+ var
+ newstatement : tstatementnode;
+ begin
+ generate_except_block:=internalstatements(newstatement);
+
+ { a constructor needs call destructor (if available) when it
+ is not inherited }
+ if not assigned(current_structdef) or
+ (current_procinfo.procdef.proctypeoption<>potype_constructor) then
+ begin
+ { no constructor }
+ { must be the return value finalized before reraising the exception? }
+ if (not is_void(current_procinfo.procdef.returndef)) and
+ is_managed_type(current_procinfo.procdef.returndef) and
+ (not paramanager.ret_in_param(current_procinfo.procdef.returndef, current_procinfo.procdef.proccalloption)) and
+ (not is_class(current_procinfo.procdef.returndef)) then
+ addstatement(newstatement,finalize_data_node(load_result_node));
+ end;
+ end;
+
+
+{****************************************************************************
+ TCGProcInfo
+****************************************************************************}
+
+ destructor tcgprocinfo.destroy;
+ begin
+ if assigned(code) then
+ code.free;
+ inherited destroy;
+ end;
+
+
+ procedure tcgprocinfo.printproc(pass:string);
+ begin
+ assign(printnodefile,treelogfilename);
+ {$push}{$I-}
+ append(printnodefile);
+ if ioresult<>0 then
+ rewrite(printnodefile);
+ {$pop}
+ if ioresult<>0 then
+ begin
+ Comment(V_Error,'Error creating '+treelogfilename);
+ exit;
+ end;
+ writeln(printnodefile);
+ writeln(printnodefile,'*******************************************************************************');
+ writeln(printnodefile, pass);
+ writeln(printnodefile,procdef.fullprocname(false));
+ writeln(printnodefile,'*******************************************************************************');
+ printnode(printnodefile,code);
+ close(printnodefile);
+ end;
+
+
+ procedure tcgprocinfo.maybe_add_constructor_wrapper(var tocode: tnode; withexceptblock: boolean);
+ var
+ oldlocalswitches: tlocalswitches;
+ srsym: tsym;
+ afterconstructionblock,
+ exceptblock,
+ newblock: tblocknode;
+ newstatement: tstatementnode;
+ pd: tprocdef;
+ begin
+ if assigned(procdef.struct) and
+ (procdef.proctypeoption=potype_constructor) then
+ begin
+ { Don't test self and the vmt here. See generate_bodyexit_block }
+ { why (JM) }
+ oldlocalswitches:=current_settings.localswitches;
+ current_settings.localswitches:=oldlocalswitches-[cs_check_object,cs_check_range];
+
+ { call AfterConstruction for classes }
+ if is_class(procdef.struct) then
+ begin
+ srsym:=search_struct_member(procdef.struct,'AFTERCONSTRUCTION');
+ if assigned(srsym) and
+ (srsym.typ=procsym) then
+ begin
+ current_filepos:=exitpos;
+ afterconstructionblock:=internalstatements(newstatement);
+ { first execute all constructor code. If no exception
+ occurred then we will execute afterconstruction,
+ otherwise we won't (the exception will jump over us) }
+ addstatement(newstatement,tocode);
+ { if implicit finally node wasn't created, then exit label and
+ finalization code must be handled here and placed before
+ afterconstruction }
+ if not ((pi_needs_implicit_finally in flags) and
+ (cs_implicit_exceptions in current_settings.moduleswitches)) then
+ begin
+ include(tocode.flags,nf_block_with_exit);
+ addstatement(newstatement,final_asmnode);
+ end;
+
+ { Self can be nil when fail is called }
+ { if self<>nil and vmt<>nil then afterconstruction }
+ addstatement(newstatement,cifnode.create(
+ caddnode.create(andn,
+ caddnode.create(unequaln,
+ load_self_node,
+ cnilnode.create),
+ caddnode.create(unequaln,
+ load_vmt_pointer_node,
+ cnilnode.create)),
+ ccallnode.create(nil,tprocsym(srsym),srsym.owner,load_self_node,[]),
+ nil));
+ tocode:=afterconstructionblock;
+ end
+ else
+ internalerror(200305106);
+ end;
+
+ if withexceptblock and (procdef.struct.typ=objectdef) then
+ begin
+ { Generate the implicit "fail" code for a constructor (destroy
+ in case an exception happened) }
+ pd:=tobjectdef(procdef.struct).find_destructor;
+ { this will always be the case for classes, since tobject has
+ a destructor }
+ if assigned(pd) then
+ begin
+ current_filepos:=exitpos;
+ exceptblock:=internalstatements(newstatement);
+ { first free the instance if non-nil }
+ { if vmt<>0 then call destructor }
+ addstatement(newstatement,cifnode.create(
+ caddnode.create(unequaln,
+ load_vmt_pointer_node,
+ cnilnode.create),
+ { cnf_create_failed -> don't call BeforeDestruction }
+ ccallnode.create(nil,tprocsym(pd.procsym),pd.procsym.owner,load_self_node,[cnf_create_failed]),
+ nil));
+ { then re-raise the exception }
+ addstatement(newstatement,craisenode.create(nil,nil,nil));
+ current_filepos:=entrypos;
+ newblock:=internalstatements(newstatement);
+ { try
+ tocode
+ except
+ exceptblock
+ end
+ }
+ addstatement(newstatement,ctryexceptnode.create(
+ tocode,
+ nil,
+ exceptblock));
+ tocode:=newblock;
+ end;
+ end;
+ current_settings.localswitches:=oldlocalswitches;
+ end;
+ end;
+
+
+ procedure tcgprocinfo.add_entry_exit_code;
+ var
+ finalcode,
+ bodyentrycode,
+ bodyexitcode,
+ exceptcode,
+ wrappedbody: tnode;
+ newblock : tblocknode;
+ codestatement,
+ newstatement : tstatementnode;
+ oldfilepos : tfileposinfo;
+ is_constructor: boolean;
+ begin
+ is_constructor:=assigned(procdef.struct) and
+ (procdef.proctypeoption=potype_constructor);
+
+ oldfilepos:=current_filepos;
+ { Generate code/locations used at start of proc }
+ current_filepos:=entrypos;
+ entry_asmnode:=casmnode.create_get_position;
+ loadpara_asmnode:=casmnode.create_get_position;
+ stackcheck_asmnode:=casmnode.create_get_position;
+ init_asmnode:=casmnode.create_get_position;
+ bodyentrycode:=generate_bodyentry_block;
+ { Generate code/locations used at end of proc }
+ current_filepos:=exitpos;
+ exitlabel_asmnode:=casmnode.create_get_position;
+ final_asmnode:=casmnode.create_get_position;
+ bodyexitcode:=generate_bodyexit_block;
+
+ { Generate procedure by combining init+body+final,
+ depending on the implicit finally we need to add
+ an try...finally...end wrapper }
+ newblock:=internalstatements(newstatement);
+ { initialization is common for all cases }
+ addstatement(newstatement,loadpara_asmnode);
+ addstatement(newstatement,stackcheck_asmnode);
+ addstatement(newstatement,entry_asmnode);
+ addstatement(newstatement,init_asmnode);
+ addstatement(newstatement,bodyentrycode);
+
+ if (cs_implicit_exceptions in current_settings.moduleswitches) and
+ (pi_needs_implicit_finally in flags) and
+ { but it's useless in init/final code of units }
+ not(procdef.proctypeoption in [potype_unitfinalize,potype_unitinit]) and
+ not(po_assembler in procdef.procoptions) then
+ begin
+ { Generate special exception block only needed when
+ implicit finaly is used }
+ current_filepos:=exitpos;
+ exceptcode:=generate_except_block;
+ { Generate code that will be in the try...finally }
+ finalcode:=internalstatements(codestatement);
+ addstatement(codestatement,final_asmnode);
+
+ current_filepos:=entrypos;
+ wrappedbody:=ctryfinallynode.create_implicit(
+ code,
+ finalcode,
+ exceptcode);
+ { afterconstruction must be called after final_asmnode, because it
+ has to execute after the temps have been finalised in case of a
+ refcounted class (afterconstruction decreases the refcount
+ without freeing the instance if the count becomes nil, while
+ the finalising of the temps can free the instance) }
+ maybe_add_constructor_wrapper(wrappedbody,true);
+ addstatement(newstatement,wrappedbody);
+ addstatement(newstatement,exitlabel_asmnode);
+ addstatement(newstatement,bodyexitcode);
+ { set flag the implicit finally has been generated }
+ include(flags,pi_has_implicit_finally);
+ end
+ else
+ begin
+ { constructors need destroy-on-exception code even if they don't
+ have managed variables/temps }
+ maybe_add_constructor_wrapper(code,
+ cs_implicit_exceptions in current_settings.moduleswitches);
+ addstatement(newstatement,code);
+ addstatement(newstatement,exitlabel_asmnode);
+ addstatement(newstatement,bodyexitcode);
+ if not is_constructor then
+ addstatement(newstatement,final_asmnode);
+ end;
+ do_firstpass(tnode(newblock));
+ code:=newblock;
+ current_filepos:=oldfilepos;
+ end;
+
+
+ procedure clearrefs(p:TObject;arg:pointer);
+ begin
+ if (tsym(p).typ in [localvarsym,paravarsym,staticvarsym]) then
+ if tabstractvarsym(p).refs>1 then
+ tabstractvarsym(p).refs:=1;
+ end;
+
+
+ procedure translate_registers(p:TObject;list:pointer);
+ begin
+ if (tsym(p).typ in [localvarsym,paravarsym,staticvarsym]) and
+ (tabstractnormalvarsym(p).localloc.loc in [LOC_REGISTER,LOC_CREGISTER,LOC_MMREGISTER,
+ LOC_CMMREGISTER,LOC_FPUREGISTER,LOC_CFPUREGISTER]) then
+ begin
+ if not(cs_no_regalloc in current_settings.globalswitches) then
+ cg.translate_register(tabstractnormalvarsym(p).localloc.register);
+ if cs_asm_source in current_settings.globalswitches then
+ TAsmList(list).concat(Tai_comment.Create(strpnew('Var '+tabstractnormalvarsym(p).realname+' located in register '+
+ std_regname(tabstractnormalvarsym(p).localloc.register))))
+ end;
+ end;
+
+ procedure tcgprocinfo.setup_tempgen;
+ begin
+ tg:=ttgobj.create;
+
+{$if defined(x86) or defined(arm)}
+ { try to strip the stack frame }
+ { set the framepointer to esp if:
+ - no assembler directive, those are handled in assembler_block
+ in pstatment.pas (for cases not caught by the Delphi
+ exception below)
+ - no exceptions are used
+ - no pushes are used/esp modifications, could be:
+ * outgoing parameters on the stack
+ * incoming parameters on the stack
+ * open arrays
+ - no inline assembler
+ or
+ - Delphi mode
+ - assembler directive
+ - no pushes are used/esp modifications, could be:
+ * outgoing parameters on the stack
+ * incoming parameters on the stack
+ * open arrays
+ - no local variables
+ }
+ if ((po_assembler in procdef.procoptions) and
+ (m_delphi in current_settings.modeswitches) and
+ { localst at main_program_level is a staticsymtable }
+ (procdef.localst.symtablelevel<>main_program_level) and
+ (tabstractlocalsymtable(procdef.localst).count_locals = 0)) or
+ ((cs_opt_stackframe in current_settings.optimizerswitches) and
+ not(cs_generate_stackframes in current_settings.localswitches) and
+ not(po_assembler in procdef.procoptions) and
+ ((flags*[pi_has_assembler_block,pi_uses_exceptions,pi_is_assembler,
+ pi_needs_implicit_finally,pi_has_implicit_finally,pi_has_stackparameter,
+ pi_needs_stackframe])=[])
+ )
+ then
+ begin
+ { we need the parameter info here to determine if the procedure gets
+ parameters on the stack
+
+ calling generate_parameter_info doesn't hurt but it costs time
+ (necessary to init para_stack_size)
+ }
+ generate_parameter_info;
+ if not(procdef.stack_tainting_parameter(calleeside)) and
+ not(has_assembler_child) and (para_stack_size=0) then
+ begin
+ { Only need to set the framepointer }
+ framepointer:=NR_STACK_POINTER_REG;
+ tg.direction:=1;
+ end;
+ end;
+
+{$endif}
+ { set the start offset to the start of the temp area in the stack }
+ set_first_temp_offset;
+ end;
+
+ function tcgprocinfo.has_assembler_child : boolean;
+ var
+ hp : tprocinfo;
+ begin
+ result:=false;
+ hp:=get_first_nestedproc;
+ while assigned(hp) do
+ begin
+ if (hp.flags*[pi_has_assembler_block,pi_is_assembler])<>[] then
+ begin
+ result:=true;
+ exit;
+ end;
+ hp:=tprocinfo(hp.next);
+ end;
+ end;
+
+ procedure tcgprocinfo.generate_code_tree;
+ var
+ hpi : tcgprocinfo;
+ begin
+ { generate code for this procedure }
+ generate_code;
+ { process nested procedures }
+ hpi:=tcgprocinfo(get_first_nestedproc);
+ while assigned(hpi) do
+ begin
+ hpi.generate_code_tree;
+ hpi:=tcgprocinfo(hpi.next);
+ end;
+ resetprocdef;
+ end;
+
+ procedure tcgprocinfo.generate_exceptfilter(nestedpi: tcgprocinfo);
+ var
+ saved_cg: tcg;
+ begin
+ if nestedpi.procdef.proctypeoption<>potype_exceptfilter then
+ InternalError(201201141);
+ { flush code generated this far }
+ aktproccode.concatlist(current_asmdata.CurrAsmList);
+ { save the codegen }
+ saved_cg:=cg;
+ cg:=nil;
+ nestedpi.generate_code;
+ { prevents generating code the second time when processing nested procedures }
+ nestedpi.resetprocdef;
+ cg:=saved_cg;
+ add_reg_instruction_hook:=@cg.add_reg_instruction;
+ end;
+
+ procedure tcgprocinfo.generate_code;
+ var
+ old_current_procinfo : tprocinfo;
+ oldmaxfpuregisters : longint;
+ oldfilepos : tfileposinfo;
+ old_current_structdef : tabstractrecorddef;
+ templist : TAsmList;
+ headertai : tai;
+ i : integer;
+ varsym : tabstractnormalvarsym;
+ {RedoDFA : boolean;}
+ begin
+ { the initialization procedure can be empty, then we
+ don't need to generate anything. When it was an empty
+ procedure there would be at least a blocknode }
+ if not assigned(code) then
+ exit;
+
+ { We need valid code }
+ if Errorcount<>0 then
+ exit;
+
+ { No code can be generated for generic template }
+ if (df_generic in procdef.defoptions) then
+ internalerror(200511152);
+
+ { For regular procedures the RA and Tempgen shall not be available yet,
+ but exception filters reuse Tempgen of parent }
+ if assigned(tg)<>(procdef.proctypeoption=potype_exceptfilter) then
+ internalerror(200309201);
+
+ old_current_procinfo:=current_procinfo;
+ oldfilepos:=current_filepos;
+ old_current_structdef:=current_structdef;
+ oldmaxfpuregisters:=current_settings.maxfpuregisters;
+
+ current_procinfo:=self;
+ current_filepos:=entrypos;
+ current_structdef:=procdef.struct;
+
+ templist:=TAsmList.create;
+
+ { add parast/localst to symtablestack }
+ add_to_symtablestack;
+
+ { clear register count }
+ procdef.localst.SymList.ForEachCall(@clearrefs,nil);
+ procdef.parast.SymList.ForEachCall(@clearrefs,nil);
+
+ { there's always a call to FPC_INITIALIZEUNITS/FPC_DO_EXIT in the main program }
+ if (procdef.localst.symtablelevel=main_program_level) and
+ (not current_module.is_unit) then
+ include(flags,pi_do_call);
+
+ { set implicit_finally flag when there are locals/paras to be finalized }
+ procdef.parast.SymList.ForEachCall(@check_finalize_paras,nil);
+ procdef.localst.SymList.ForEachCall(@check_finalize_locals,nil);
+
+{$if defined(x86) or defined(arm)}
+ { set implicit_finally flag for if procedure is safecall }
+ if (tf_safecall_exceptions in target_info.flags) and
+ (procdef.proccalloption=pocall_safecall) then
+ include(flags, pi_needs_implicit_finally);
+{$endif}
+ { firstpass everything }
+ flowcontrol:=[];
+ do_firstpass(code);
+{$ifdef i386}
+ procdef.fpu_used:=node_resources_fpu(code);
+ if procdef.fpu_used>0 then
+ include(flags,pi_uses_fpu);
+{$endif i386}
+
+ { Print the node to tree.log }
+ if paraprintnodetree=1 then
+ printproc( 'after the firstpass');
+
+ { do this before adding the entry code else the tail recursion recognition won't work,
+ if this causes troubles, it must be if'ed
+ }
+ if (cs_opt_tailrecursion in current_settings.optimizerswitches) and
+ (pi_is_recursive in flags) then
+ do_opttail(code,procdef);
+
+ if (cs_opt_nodedfa in current_settings.optimizerswitches) and
+ { creating dfa is not always possible }
+ ((flags*[pi_has_assembler_block,pi_uses_exceptions,pi_is_assembler,
+ pi_needs_implicit_finally,pi_has_implicit_finally])=[]) then
+ begin
+ dfabuilder:=TDFABuilder.Create;
+ dfabuilder.createdfainfo(code);
+ { when life info is available, we can give more sophisticated warning about unintialized
+ variables }
+
+ { iterate through life info of the first node }
+ for i:=0 to dfabuilder.nodemap.count-1 do
+ begin
+ if DFASetIn(code.optinfo^.life,i) then
+ case tnode(dfabuilder.nodemap[i]).nodetype of
+ loadn:
+ begin
+ varsym:=tabstractnormalvarsym(tloadnode(dfabuilder.nodemap[i]).symtableentry);
+
+ { Give warning/note for living locals }
+ if assigned(varsym.owner) and
+ not(vo_is_external in varsym.varoptions) then
+ begin
+ if (vo_is_funcret in varsym.varoptions) then
+ CGMessage(sym_w_function_result_uninitialized)
+ else
+ begin
+ if (varsym.owner=procdef.localst) and not (vo_is_typed_const in varsym.varoptions) then
+ CGMessage1(sym_w_uninitialized_local_variable,varsym.realname);
+ end;
+ end;
+ end;
+ end;
+ end;
+ include(flags,pi_dfaavailable);
+ end;
+
+ if (cs_opt_loopstrength in current_settings.optimizerswitches)
+ { our induction variable strength reduction doesn't like
+ for loops with more than one entry }
+ and not(pi_has_label in flags) then
+ begin
+ {RedoDFA:=}OptimizeInductionVariables(code);
+ end;
+
+ if cs_opt_nodecse in current_settings.optimizerswitches then
+ do_optcse(code);
+
+ { add implicit entry and exit code }
+ add_entry_exit_code;
+
+ { only do secondpass if there are no errors }
+ if (ErrorCount=0) then
+ begin
+ create_codegen;
+
+ if (procdef.proctypeoption<>potype_exceptfilter) then
+ setup_tempgen;
+
+ { Create register allocator, must come after framepointer is known }
+ cg.init_register_allocators;
+
+ generate_parameter_info;
+
+ { allocate got register if needed }
+ allocate_got_register(aktproccode);
+
+ { Allocate space in temp/registers for parast and localst }
+ current_filepos:=entrypos;
+ gen_alloc_symtable(aktproccode,procdef.parast);
+ gen_alloc_symtable(aktproccode,procdef.localst);
+
+ { Store temp offset for information about 'real' temps }
+ tempstart:=tg.lasttemp;
+
+ { Generate code to load register parameters in temps and insert local
+ copies for values parameters. This must be done before the code for the
+ body is generated because the localloc is updated.
+ Note: The generated code will be inserted after the code generation of
+ the body is finished, because only then the position is known }
+{$ifdef oldregvars}
+ assign_regvars(code);
+{$endif oldreg}
+ current_filepos:=entrypos;
+
+ gen_load_para_value(templist);
+
+ { caller paraloc info is also necessary in the stackframe_entry
+ code of the ppc (and possibly other processors) }
+ procdef.init_paraloc_info(callerside);
+
+ { generate code for the node tree }
+ do_secondpass(code);
+ aktproccode.concatlist(current_asmdata.CurrAsmList);
+
+ { The position of the loadpara_asmnode is now known }
+ aktproccode.insertlistafter(loadpara_asmnode.currenttai,templist);
+
+ { first generate entry and initialize code with the correct
+ position and switches }
+ current_filepos:=entrypos;
+ current_settings.localswitches:=entryswitches;
+
+ cg.set_regalloc_live_range_direction(rad_backwards);
+
+ gen_entry_code(templist);
+ aktproccode.insertlistafter(entry_asmnode.currenttai,templist);
+ gen_initialize_code(templist);
+ aktproccode.insertlistafter(init_asmnode.currenttai,templist);
+
+ { now generate finalize and exit code with the correct position
+ and switches }
+ current_filepos:=exitpos;
+ current_settings.localswitches:=exitswitches;
+
+ cg.set_regalloc_live_range_direction(rad_forward);
+
+ if assigned(finalize_procinfo) then
+ generate_exceptfilter(tcgprocinfo(finalize_procinfo))
+ else
+ begin
+ gen_finalize_code(templist);
+ { the finalcode must be concated if there was no position available,
+ using insertlistafter will result in an insert at the start
+ when currentai=nil }
+ if assigned(final_asmnode) and assigned(final_asmnode.currenttai) then
+ aktproccode.insertlistafter(final_asmnode.currenttai,templist)
+ else
+ aktproccode.concatlist(templist);
+ end;
+ { insert exit label at the correct position }
+ cg.a_label(templist,CurrExitLabel);
+ if assigned(exitlabel_asmnode.currenttai) then
+ aktproccode.insertlistafter(exitlabel_asmnode.currenttai,templist)
+ else
+ aktproccode.concatlist(templist);
+ { exit code }
+ gen_exit_code(templist);
+ aktproccode.concatlist(templist);
+
+{$ifdef OLDREGVARS}
+ { note: this must be done only after as much code as possible has }
+ { been generated. The result is that when you ungetregister() a }
+ { regvar, it will actually free the regvar (and alse free the }
+ { the regvars at the same time). Doing this too early will }
+ { confuse the register allocator, as the regvars will still be }
+ { used. It should be done before loading the result regs (so }
+ { they don't conflict with the regvars) and before }
+ { gen_entry_code (that one has to be able to allocate the }
+ { regvars again) (JM) }
+ free_regvars(aktproccode);
+{$endif OLDREGVARS}
+
+ { generate symbol and save end of header position }
+ current_filepos:=entrypos;
+ gen_proc_symbol(templist);
+ headertai:=tai(templist.last);
+ { insert symbol }
+ aktproccode.insertlist(templist);
+
+ { Free space in temp/registers for parast and localst, must be
+ done after gen_entry_code }
+ current_filepos:=exitpos;
+
+ { make sure the got/pic register doesn't get freed in the }
+ { middle of a loop }
+ if (cs_create_pic in current_settings.moduleswitches) and
+ (pi_needs_got in flags) and
+ (got<>NR_NO) then
+ cg.a_reg_sync(aktproccode,got);
+
+ gen_free_symtable(aktproccode,procdef.localst);
+ gen_free_symtable(aktproccode,procdef.parast);
+
+ { add code that will load the return value, this is not done
+ for assembler routines when they didn't reference the result
+ variable }
+ gen_load_return_value(templist);
+ aktproccode.concatlist(templist);
+
+ { Already reserve all registers for stack checking code and
+ generate the call to the helper function }
+ if not(tf_no_generic_stackcheck in target_info.flags) and
+ (cs_check_stack in entryswitches) and
+ not(po_assembler in procdef.procoptions) and
+ (procdef.proctypeoption<>potype_proginit) then
+ begin
+ current_filepos:=entrypos;
+ gen_stack_check_call(templist);
+ aktproccode.insertlistafter(stackcheck_asmnode.currenttai,templist)
+ end;
+
+ { this code (got loading) comes before everything which has }
+ { already been generated, so reset the info about already }
+ { backwards extended registers (so their live range can be }
+ { extended backwards even further if needed) }
+ { This code must be }
+ { a) generated after do_secondpass has been called }
+ { (because pi_needs_got may be set there) }
+ { b) generated before register allocation, because the }
+ { got/pic register can be a virtual one }
+ { c) inserted before the entry code, because the entry }
+ { code may need global symbols such as init rtti }
+ { d) inserted after the stackframe allocation, because }
+ { this register may have to be spilled }
+ cg.set_regalloc_live_range_direction(rad_backwards_reinit);
+ current_filepos:=entrypos;
+ { load got if necessary }
+ cg.g_maybe_got_init(templist);
+
+ aktproccode.insertlistafter(headertai,templist);
+
+ { re-enable if more code at the end is ever generated here
+ cg.set_regalloc_live_range_direction(rad_forward);
+ }
+
+ { The procedure body is finished, we can now
+ allocate the registers }
+ cg.do_register_allocation(aktproccode,headertai);
+
+ { translate imag. register to their real counter parts
+ this is necessary for debuginfo and verbose assembler output
+ when SSA will be implented, this will be more complicated because we've to
+ maintain location lists }
+ procdef.parast.SymList.ForEachCall(@translate_registers,templist);
+ procdef.localst.SymList.ForEachCall(@translate_registers,templist);
+ if (cs_create_pic in current_settings.moduleswitches) and
+ (pi_needs_got in flags) and
+ not(cs_no_regalloc in current_settings.globalswitches) and
+ (got<>NR_NO) then
+ cg.translate_register(got);
+
+ { Add save and restore of used registers }
+ current_filepos:=entrypos;
+ gen_save_used_regs(templist);
+ { Remember the last instruction of register saving block
+ (may be =nil for e.g. assembler procedures) }
+ endprologue_ai:=templist.last;
+ aktproccode.insertlistafter(headertai,templist);
+ current_filepos:=exitpos;
+ gen_restore_used_regs(aktproccode);
+ { We know the size of the stack, now we can generate the
+ parameter that is passed to the stack checking code }
+ if not(tf_no_generic_stackcheck in target_info.flags) and
+ (cs_check_stack in entryswitches) and
+ not(po_assembler in procdef.procoptions) and
+ (procdef.proctypeoption<>potype_proginit) then
+ begin
+ current_filepos:=entrypos;
+ gen_stack_check_size_para(templist);
+ aktproccode.insertlistafter(stackcheck_asmnode.currenttai,templist)
+ end;
+ { Add entry code (stack allocation) after header }
+ current_filepos:=entrypos;
+ gen_proc_entry_code(templist);
+ aktproccode.insertlistafter(headertai,templist);
+{$if defined(x86) or defined(arm)}
+ { Set return value of safecall procedure if implicit try/finally blocks are disabled }
+ if not (cs_implicit_exceptions in current_settings.moduleswitches) and
+ (tf_safecall_exceptions in target_info.flags) and
+ (procdef.proccalloption=pocall_safecall) then
+ cg.a_load_const_reg(aktproccode,OS_ADDR,0,NR_FUNCTION_RETURN_REG);
+{$endif}
+ { Add exit code at the end }
+ current_filepos:=exitpos;
+ gen_proc_exit_code(templist);
+ aktproccode.concatlist(templist);
+
+ { check if the implicit finally has been generated. The flag
+ should already be set in pass1 }
+ if (cs_implicit_exceptions in current_settings.moduleswitches) and
+ not(procdef.proctypeoption in [potype_unitfinalize,potype_unitinit]) and
+ (pi_needs_implicit_finally in flags) and
+ not(po_assembler in procdef.procoptions) and
+ not(pi_has_implicit_finally in flags) then
+ internalerror(200405231);
+
+{$ifndef NoOpt}
+ if not(cs_no_regalloc in current_settings.globalswitches) then
+ begin
+ if (cs_opt_level1 in current_settings.optimizerswitches) and
+ { do not optimize pure assembler procedures }
+ not(pi_is_assembler in flags) then
+ optimize(aktproccode);
+ end;
+{$endif NoOpt}
+
+
+{$ifdef ARM}
+ { because of the limited constant size of the arm, all data access is done pc relative }
+ finalizearmcode(aktproccode,aktlocaldata);
+{$endif ARM}
+
+{$ifdef AVR}
+ { because of the limited branch distance of cond. branches, they must be replaced
+ somtimes by normal jmps and an inverse branch }
+ finalizeavrcode(aktproccode);
+{$endif AVR}
+
+ { Add end symbol and debug info }
+ { this must be done after the pcrelativedata is appended else the distance calculation of
+ insertpcrelativedata will be wrong, further the pc indirect data is part of the procedure
+ so it should be inserted before the end symbol (FK)
+ }
+ current_filepos:=exitpos;
+ gen_proc_symbol_end(templist);
+ aktproccode.concatlist(templist);
+{$if defined(POWERPC) or defined(POWERPC64)}
+ fixup_jmps(aktproccode);
+{$endif}
+ { insert line debuginfo }
+ if (cs_debuginfo in current_settings.moduleswitches) or
+ (cs_use_lineinfo in current_settings.globalswitches) then
+ current_debuginfo.insertlineinfo(aktproccode);
+
+ { add the procedure to the al_procedures }
+ maybe_new_object_file(current_asmdata.asmlists[al_procedures]);
+ new_section(current_asmdata.asmlists[al_procedures],sec_code,lower(procdef.mangledname),getprocalign);
+ current_asmdata.asmlists[al_procedures].concatlist(aktproccode);
+ { save local data (casetable) also in the same file }
+ if assigned(aktlocaldata) and
+ (not aktlocaldata.empty) then
+ current_asmdata.asmlists[al_procedures].concatlist(aktlocaldata);
+
+ { only now we can remove the temps }
+ if (procdef.proctypeoption<>potype_exceptfilter) then
+ begin
+ tg.resettempgen;
+ tg.free;
+ tg:=nil;
+ end;
+ { stop tempgen and ra }
+ cg.done_register_allocators;
+ destroy_codegen;
+ end;
+
+ dfabuilder.free;
+
+ { restore symtablestack }
+ remove_from_symtablestack;
+
+ { restore }
+ templist.free;
+ current_settings.maxfpuregisters:=oldmaxfpuregisters;
+ current_filepos:=oldfilepos;
+ current_structdef:=old_current_structdef;
+ current_procinfo:=old_current_procinfo;
+ end;
+
+
+ procedure tcgprocinfo.add_to_symtablestack;
+ begin
+ { insert symtables for the class, but only if it is no nested function }
+ if assigned(procdef.struct) and
+ not(assigned(parent) and
+ assigned(parent.procdef) and
+ assigned(parent.procdef.struct)) then
+ push_nested_hierarchy(procdef.struct);
+
+ { insert parasymtable in symtablestack when parsing
+ a function }
+ if procdef.parast.symtablelevel>=normal_function_level then
+ symtablestack.push(procdef.parast);
+
+ { insert localsymtable, except for the main procedure
+ (in that case the localst is the unit's static symtable,
+ which is already on the stack) }
+ if procdef.localst.symtablelevel>=normal_function_level then
+ symtablestack.push(procdef.localst);
+ end;
+
+
+ procedure tcgprocinfo.remove_from_symtablestack;
+ begin
+ { remove localsymtable }
+ if procdef.localst.symtablelevel>=normal_function_level then
+ symtablestack.pop(procdef.localst);
+
+ { remove parasymtable }
+ if procdef.parast.symtablelevel>=normal_function_level then
+ symtablestack.pop(procdef.parast);
+
+ { remove symtables for the class, but only if it is no nested function }
+ if assigned(procdef.struct) and
+ not(assigned(parent) and
+ assigned(parent.procdef) and
+ assigned(parent.procdef.struct)) then
+ pop_nested_hierarchy(procdef.struct);
+ end;
+
+
+ procedure tcgprocinfo.resetprocdef;
+ begin
+ { remove code tree, if not inline procedure }
+ if assigned(code) then
+ begin
+ { the inline procedure has already got a copy of the tree
+ stored in procdef.inlininginfo }
+ code.free;
+ code:=nil;
+ end;
+ end;
+
+
+ function checknodeinlining(procdef: tprocdef): boolean;
+ var
+ i : integer;
+ currpara : tparavarsym;
+ begin
+ result := false;
+ if (pi_has_assembler_block in current_procinfo.flags) then
+ begin
+ Message1(parser_w_not_supported_for_inline,'assembler');
+ Message(parser_w_inlining_disabled);
+ exit;
+ end;
+ for i:=0 to procdef.paras.count-1 do
+ begin
+ currpara:=tparavarsym(procdef.paras[i]);
+ case currpara.vardef.typ of
+ formaldef :
+ begin
+ if (currpara.varspez in [vs_out,vs_var,vs_const,vs_constref]) then
+ begin
+ Message1(parser_w_not_supported_for_inline,'formal parameter');
+ Message(parser_w_inlining_disabled);
+ exit;
+ end;
+ end;
+ arraydef :
+ begin
+ if is_array_of_const(currpara.vardef) or
+ is_variant_array(currpara.vardef) then
+ begin
+ Message1(parser_w_not_supported_for_inline,'array of const');
+ Message(parser_w_inlining_disabled);
+ exit;
+ end;
+ { open arrays might need re-basing of the index, i.e. if you pass
+ an array[1..10] as open array, you have to add 1 to all index operations
+ if you directly inline it }
+ if is_open_array(currpara.vardef) then
+ begin
+ Message1(parser_w_not_supported_for_inline,'open array');
+ Message(parser_w_inlining_disabled);
+ exit;
+ end;
+ end;
+ end;
+ end;
+ result:=true;
+ end;
+
+
+ procedure tcgprocinfo.parse_body;
+ var
+ old_current_procinfo : tprocinfo;
+ old_block_type : tblock_type;
+ st : TSymtable;
+ old_current_structdef: tabstractrecorddef;
+ old_current_genericdef,
+ old_current_specializedef: tstoreddef;
+ old_parse_generic: boolean;
+ begin
+ old_current_procinfo:=current_procinfo;
+ old_block_type:=block_type;
+ old_current_structdef:=current_structdef;
+ old_current_genericdef:=current_genericdef;
+ old_current_specializedef:=current_specializedef;
+ old_parse_generic:=parse_generic;
+
+ current_procinfo:=self;
+ current_structdef:=procdef.struct;
+ if assigned(current_structdef) and (df_generic in current_structdef.defoptions) then
+ begin
+ current_genericdef:=current_structdef;
+ parse_generic:=true;
+ end;
+ if assigned(current_structdef) and (df_specialization in current_structdef.defoptions) then
+ current_specializedef:=current_structdef;
+
+ { calculate the lexical level }
+ if procdef.parast.symtablelevel>maxnesting then
+ Message(parser_e_too_much_lexlevel);
+ block_type:=bt_body;
+
+ {$ifdef state_tracking}
+{ aktstate:=Tstate_storage.create;}
+ {$endif state_tracking}
+
+ { allocate the symbol for this procedure }
+ alloc_proc_symbol(procdef);
+
+ { add parast/localst to symtablestack }
+ add_to_symtablestack;
+
+ { save entry info }
+ entrypos:=current_filepos;
+ entryswitches:=current_settings.localswitches;
+
+ if (df_generic in procdef.defoptions) then
+ begin
+ { start token recorder for generic template }
+ procdef.initgeneric;
+ current_scanner.startrecordtokens(procdef.generictokenbuf);
+ end;
+
+ { parse the code ... }
+ code:=block(current_module.islibrary);
+
+ if (df_generic in procdef.defoptions) then
+ begin
+ { stop token recorder for generic template }
+ current_scanner.stoprecordtokens;
+
+ { Give an error for accesses in the static symtable that aren't visible
+ outside the current unit }
+ st:=procdef.owner;
+ while (st.symtabletype=ObjectSymtable) do
+ st:=st.defowner.owner;
+ if (pi_uses_static_symtable in flags) and
+ (st.symtabletype<>staticsymtable) then
+ Comment(V_Error,'Global Generic template references static symtable');
+ end;
+
+ { save exit info }
+ exitswitches:=current_settings.localswitches;
+ exitpos:=last_endtoken_filepos;
+
+ { the procedure is now defined }
+ procdef.forwarddef:=false;
+
+ if assigned(code) then
+ begin
+ { get a better entry point }
+ entrypos:=code.fileinfo;
+
+ { Finish type checking pass }
+ do_typecheckpass(code);
+ end;
+
+ { Check for unused labels, forwards, symbols for procedures. Static
+ symtable is checked in pmodules.
+ The check must be done after the typecheckpass }
+ if (Errorcount=0) and
+ (tstoredsymtable(procdef.localst).symtabletype<>staticsymtable) then
+ begin
+ { check if forwards are resolved }
+ tstoredsymtable(procdef.localst).check_forwards;
+ { check if all labels are used }
+ tstoredsymtable(procdef.localst).checklabels;
+ { check for unused symbols, but only if there is no asm block }
+ if not(pi_has_assembler_block in flags) then
+ begin
+ tstoredsymtable(procdef.localst).allsymbolsused;
+ tstoredsymtable(procdef.parast).allsymbolsused;
+ end;
+ end;
+
+ if (po_inline in procdef.procoptions) then
+ begin
+ { Can we inline this procedure? }
+ if checknodeinlining(procdef) then
+ begin
+ new(procdef.inlininginfo);
+ include(procdef.procoptions,po_has_inlininginfo);
+ procdef.inlininginfo^.code:=code.getcopy;
+ procdef.inlininginfo^.flags:=flags;
+ { The blocknode needs to set an exit label }
+ if procdef.inlininginfo^.code.nodetype=blockn then
+ include(procdef.inlininginfo^.code.flags,nf_block_with_exit);
+ end;
+ end;
+
+ { Print the node to tree.log }
+ if paraprintnodetree=1 then
+ printproc( 'after parsing');
+
+ { ... remove symbol tables }
+ remove_from_symtablestack;
+
+ {$ifdef state_tracking}
+{ aktstate.destroy;}
+ {$endif state_tracking}
+
+ current_structdef:=old_current_structdef;
+ current_genericdef:=old_current_genericdef;
+ current_specializedef:=old_current_specializedef;
+ current_procinfo:=old_current_procinfo;
+ parse_generic:=old_parse_generic;
+
+ { Restore old state }
+ block_type:=old_block_type;
+ end;
+
+
+{****************************************************************************
+ PROCEDURE/FUNCTION PARSING
+****************************************************************************}
+
+
+ procedure check_init_paras(p:TObject;arg:pointer);
+ begin
+ if tsym(p).typ<>paravarsym then
+ exit;
+ with tparavarsym(p) do
+ if is_managed_type(vardef) and
+ (varspez in [vs_value,vs_out]) then
+ include(current_procinfo.flags,pi_do_call);
+ end;
+
+
+
+ procedure read_proc_body(old_current_procinfo:tprocinfo;pd:tprocdef);
+ {
+ Parses the procedure directives, then parses the procedure body, then
+ generates the code for it
+ }
+
+ var
+ oldfailtokenmode : tmodeswitch;
+ isnestedproc : boolean;
+ begin
+ Message1(parser_d_procedure_start,pd.fullprocname(false));
+
+ { create a new procedure }
+ current_procinfo:=cprocinfo.create(old_current_procinfo);
+ current_module.procinfo:=current_procinfo;
+ current_procinfo.procdef:=pd;
+ isnestedproc:=(current_procinfo.procdef.parast.symtablelevel>normal_function_level);
+
+ { Insert mangledname }
+ pd.aliasnames.insert(pd.mangledname);
+
+ { Handle Export of this procedure }
+ if (po_exports in pd.procoptions) and
+ (target_info.system in [system_i386_os2,system_i386_emx]) then
+ begin
+ pd.aliasnames.insert(pd.procsym.realname);
+ if cs_link_deffile in current_settings.globalswitches then
+ deffile.AddExport(pd.mangledname);
+ end;
+
+ { Insert result variables in the localst }
+ insert_funcret_local(pd);
+
+ { check if there are para's which require initing -> set }
+ { pi_do_call (if not yet set) }
+ if not(pi_do_call in current_procinfo.flags) then
+ pd.parast.SymList.ForEachCall(@check_init_paras,nil);
+
+ { set _FAIL as keyword if constructor }
+ if (pd.proctypeoption=potype_constructor) then
+ begin
+ oldfailtokenmode:=tokeninfo^[_FAIL].keyword;
+ tokeninfo^[_FAIL].keyword:=m_all;
+ end;
+
+ tcgprocinfo(current_procinfo).parse_body;
+
+ { We can't support inlining for procedures that have nested
+ procedures because the nested procedures use a fixed offset
+ for accessing locals in the parent procedure (PFV) }
+ if current_procinfo.has_nestedprocs then
+ begin
+ if (df_generic in current_procinfo.procdef.defoptions) then
+ Comment(V_Error,'Generic methods cannot have nested procedures')
+ else
+ if (po_inline in current_procinfo.procdef.procoptions) then
+ begin
+ Message1(parser_w_not_supported_for_inline,'nested procedures');
+ Message(parser_w_inlining_disabled);
+ exclude(current_procinfo.procdef.procoptions,po_inline);
+ end;
+ end;
+
+ { When it's a nested procedure then defer the code generation,
+ when back at normal function level then generate the code
+ for all defered nested procedures and the current procedure }
+ if not isnestedproc then
+ begin
+ if not(df_generic in current_procinfo.procdef.defoptions) then
+ tcgprocinfo(current_procinfo).generate_code_tree;
+ end;
+
+ { reset _FAIL as _SELF normal }
+ if (pd.proctypeoption=potype_constructor) then
+ tokeninfo^[_FAIL].keyword:=oldfailtokenmode;
+
+ { release procinfo }
+ if tprocinfo(current_module.procinfo)<>current_procinfo then
+ internalerror(200304274);
+ current_module.procinfo:=current_procinfo.parent;
+
+ { For specialization we didn't record the last semicolon. Moving this parsing
+ into the parse_body routine is not done because of having better file position
+ information available }
+ if not(df_specialization in current_procinfo.procdef.defoptions) then
+ consume(_SEMICOLON);
+
+ if not isnestedproc then
+ { current_procinfo is checked for nil later on }
+ freeandnil(current_procinfo);
+ end;
+
+
+ procedure read_proc(isclassmethod:boolean);
+ {
+ Parses the procedure directives, then parses the procedure body, then
+ generates the code for it
+ }
+
+ var
+ old_current_procinfo : tprocinfo;
+ old_current_structdef: tabstractrecorddef;
+ old_current_genericdef,
+ old_current_specializedef: tstoreddef;
+ pdflags : tpdflags;
+ pd,firstpd : tprocdef;
+ s : string;
+ begin
+ { save old state }
+ old_current_procinfo:=current_procinfo;
+ old_current_structdef:=current_structdef;
+ old_current_genericdef:=current_genericdef;
+ old_current_specializedef:=current_specializedef;
+
+ { reset current_procinfo.procdef to nil to be sure that nothing is writing
+ to another procdef }
+ current_procinfo:=nil;
+ current_structdef:=nil;
+ current_genericdef:=nil;
+ current_specializedef:=nil;
+
+ { parse procedure declaration }
+ pd:=parse_proc_dec(isclassmethod,old_current_structdef);
+
+ { set the default function options }
+ if parse_only then
+ begin
+ pd.forwarddef:=true;
+ { set also the interface flag, for better error message when the
+ implementation doesn't much this header }
+ pd.interfacedef:=true;
+ include(pd.procoptions,po_global);
+ pdflags:=[pd_interface];
+ end
+ else
+ begin
+ pdflags:=[pd_body];
+ if (not current_module.in_interface) then
+ include(pdflags,pd_implemen);
+ if (not current_module.is_unit) or
+ create_smartlink or
+ {
+ taking addresses of static procedures goes wrong
+ if they aren't global when pic is used (FK)
+ }
+ (cs_create_pic in current_settings.moduleswitches) then
+ include(pd.procoptions,po_global);
+ pd.forwarddef:=false;
+ end;
+
+ { parse the directives that may follow }
+ parse_proc_directives(pd,pdflags);
+
+ { hint directives, these can be separated by semicolons here,
+ that needs to be handled here with a loop (PFV) }
+ while try_consume_hintdirective(pd.symoptions,pd.deprecatedmsg) do
+ Consume(_SEMICOLON);
+
+ { Set calling convention }
+ handle_calling_convention(pd);
+
+ { search for forward declarations }
+ if not proc_add_definition(pd) then
+ begin
+ { A method must be forward defined (in the object declaration) }
+ if assigned(pd.struct) and
+ (not assigned(old_current_structdef)) then
+ begin
+ MessagePos1(pd.fileinfo,parser_e_header_dont_match_any_member,pd.fullprocname(false));
+ tprocsym(pd.procsym).write_parameter_lists(pd);
+ end
+ else
+ begin
+ { Give a better error if there is a forward def in the interface and only
+ a single implementation }
+ firstpd:=tprocdef(tprocsym(pd.procsym).ProcdefList[0]);
+ if (not pd.forwarddef) and
+ (not pd.interfacedef) and
+ (tprocsym(pd.procsym).ProcdefList.Count>1) and
+ firstpd.forwarddef and
+ firstpd.interfacedef and
+ not(tprocsym(pd.procsym).ProcdefList.Count>2) and
+ { don't give an error if it may be an overload }
+ not(m_fpc in current_settings.modeswitches) and
+ (not(po_overload in pd.procoptions) or
+ not(po_overload in firstpd.procoptions)) then
+ begin
+ MessagePos1(pd.fileinfo,parser_e_header_dont_match_forward,pd.fullprocname(false));
+ tprocsym(pd.procsym).write_parameter_lists(pd);
+ end;
+ end;
+ end;
+
+ { Set mangled name }
+ proc_set_mangledname(pd);
+
+ { compile procedure when a body is needed }
+ if (pd_body in pdflags) then
+ begin
+ read_proc_body(old_current_procinfo,pd);
+ end
+ else
+ begin
+ { Handle imports }
+ if (po_external in pd.procoptions) then
+ begin
+ { External declared in implementation, and there was already a
+ forward (or interface) declaration then we need to generate
+ a stub that calls the external routine }
+ if (not pd.forwarddef) and
+ (pd.hasforward)
+ { it is unclear to me what's the use of the following condition,
+ so commented out, see also issue #18371 (FK)
+ and
+ not(
+ assigned(pd.import_dll) and
+ (target_info.system in [system_i386_wdosx,
+ system_arm_wince,system_i386_wince])
+ ) } then
+ begin
+ s:=proc_get_importname(pd);
+ if s<>'' then
+ gen_external_stub(current_asmdata.asmlists[al_procedures],pd,s);
+ end;
+
+ { Import DLL specified? }
+ if assigned(pd.import_dll) then
+ begin
+ if assigned (pd.import_name) then
+ current_module.AddExternalImport(pd.import_dll^,
+ pd.import_name^,proc_get_importname(pd),
+ pd.import_nr,false,false)
+ else
+ current_module.AddExternalImport(pd.import_dll^,
+ proc_get_importname(pd),proc_get_importname(pd),
+ pd.import_nr,false,true);
+ end
+ else
+ begin
+ { add import name to external list for DLL scanning }
+ if tf_has_dllscanner in target_info.flags then
+ current_module.dllscannerinputlist.Add(proc_get_importname(pd),pd);
+ end;
+ end;
+ end;
+
+ { make sure that references to forward-declared functions are not }
+ { treated as references to external symbols, needed for darwin. }
+
+ { make sure we don't change the binding of real external symbols }
+ if not(po_external in pd.procoptions) then
+ begin
+ if (po_global in pd.procoptions) or
+ (cs_profile in current_settings.moduleswitches) then
+ current_asmdata.DefineAsmSymbol(pd.mangledname,AB_GLOBAL,AT_FUNCTION)
+ else
+ current_asmdata.DefineAsmSymbol(pd.mangledname,AB_LOCAL,AT_FUNCTION);
+ end;
+
+ current_structdef:=old_current_structdef;
+ current_genericdef:=old_current_genericdef;
+ current_specializedef:=old_current_specializedef;
+ current_procinfo:=old_current_procinfo;
+ end;
+
+
+{****************************************************************************
+ DECLARATION PARSING
+****************************************************************************}
+
+ { search in symtablestack for not complete classes }
+ procedure check_forward_class(p:TObject;arg:pointer);
+ begin
+ if (tsym(p).typ=typesym) and
+ (ttypesym(p).typedef.typ=objectdef) and
+ (oo_is_forward in tobjectdef(ttypesym(p).typedef).objectoptions) then
+ MessagePos1(tsym(p).fileinfo,sym_e_forward_type_not_resolved,tsym(p).realname);
+ end;
+
+
+ procedure read_declarations(islibrary : boolean);
+ var
+ is_classdef:boolean;
+ begin
+ is_classdef:=false;
+ repeat
+ if not assigned(current_procinfo) then
+ internalerror(200304251);
+ case token of
+ _LABEL:
+ label_dec;
+ _CONST:
+ const_dec;
+ _TYPE:
+ type_dec;
+ _VAR:
+ var_dec;
+ _THREADVAR:
+ threadvar_dec;
+ _CLASS:
+ begin
+ is_classdef:=false;
+ if try_to_consume(_CLASS) then
+ begin
+ { class modifier is only allowed for procedures, functions, }
+ { constructors, destructors, fields and properties }
+ if not(token in [_FUNCTION,_PROCEDURE,_PROPERTY,_VAR,_CONSTRUCTOR,_DESTRUCTOR,_OPERATOR]) and
+ not((token=_ID) and (idtoken=_OPERATOR)) then
+ Message(parser_e_procedure_or_function_expected);
+
+ if is_interface(current_structdef) then
+ Message(parser_e_no_static_method_in_interfaces)
+ else
+ { class methods are also allowed for Objective-C protocols }
+ is_classdef:=true;
+ end;
+ end;
+ _CONSTRUCTOR,
+ _DESTRUCTOR,
+ _FUNCTION,
+ _PROCEDURE,
+ _OPERATOR:
+ begin
+ read_proc(is_classdef);
+ is_classdef:=false;
+ end;
+ _EXPORTS:
+ begin
+ if (current_procinfo.procdef.localst.symtablelevel>main_program_level) then
+ begin
+ Message(parser_e_syntax_error);
+ consume_all_until(_SEMICOLON);
+ end
+ else if islibrary or
+ (target_info.system in systems_unit_program_exports) then
+ read_exports
+ else
+ begin
+ Message(parser_w_unsupported_feature);
+ consume(_BEGIN);
+ end;
+ end
+ else
+ begin
+ case idtoken of
+ _RESOURCESTRING:
+ begin
+ { m_class is needed, because the resourcestring
+ loading is in the ObjPas unit }
+{ if (m_class in current_settings.modeswitches) then}
+ resourcestring_dec
+{ else
+ break;}
+ end;
+ _OPERATOR:
+ begin
+ if is_classdef then
+ begin
+ read_proc(is_classdef);
+ is_classdef:=false;
+ end
+ else
+ break;
+ end;
+ _PROPERTY:
+ begin
+ if (m_fpc in current_settings.modeswitches) then
+ begin
+ property_dec(is_classdef);
+ is_classdef:=false;
+ end
+ else
+ break;
+ end;
+ else
+ break;
+ end;
+ end;
+ end;
+ until false;
+
+ { check for incomplete class definitions, this is only required
+ for fpc modes }
+ if (m_fpc in current_settings.modeswitches) then
+ current_procinfo.procdef.localst.SymList.ForEachCall(@check_forward_class,nil);
+ end;
+
+
+ procedure read_interface_declarations;
+ begin
+ repeat
+ case token of
+ _CONST :
+ const_dec;
+ _TYPE :
+ type_dec;
+ _VAR :
+ var_dec;
+ _THREADVAR :
+ threadvar_dec;
+ _FUNCTION,
+ _PROCEDURE,
+ _OPERATOR :
+ read_proc(false);
+ else
+ begin
+ case idtoken of
+ _RESOURCESTRING :
+ resourcestring_dec;
+ _PROPERTY:
+ begin
+ if (m_fpc in current_settings.modeswitches) then
+ property_dec(false)
+ else
+ break;
+ end;
+ else
+ break;
+ end;
+ end;
+ end;
+ until false;
+ { check for incomplete class definitions, this is only required
+ for fpc modes }
+ if (m_fpc in current_settings.modeswitches) then
+ symtablestack.top.SymList.ForEachCall(@check_forward_class,nil);
+ end;
+
+
+{****************************************************************************
+ SPECIALIZATION BODY GENERATION
+****************************************************************************}
+
+
+ procedure specialize_objectdefs(p:TObject;arg:pointer);
+ var
+ oldcurrent_filepos : tfileposinfo;
+ oldsymtablestack : tsymtablestack;
+ oldextendeddefs : TFPHashObjectList;
+ pu : tused_unit;
+ hmodule : tmodule;
+ specobj : tabstractrecorddef;
+
+ procedure process_abstractrecorddef(def:tabstractrecorddef);
+ var
+ i : longint;
+ hp : tdef;
+ begin
+ for i:=0 to def.symtable.DefList.Count-1 do
+ begin
+ hp:=tdef(def.symtable.DefList[i]);
+ if hp.typ=procdef then
+ begin
+ { only generate the code if we need a body }
+ if assigned(tprocdef(hp).struct) and not tprocdef(hp).forwarddef then
+ continue;
+ if assigned(tprocdef(hp).genericdef) and
+ (tprocdef(hp).genericdef.typ=procdef) and
+ assigned(tprocdef(tprocdef(hp).genericdef).generictokenbuf) then
+ begin
+ oldcurrent_filepos:=current_filepos;
+ current_filepos:=tprocdef(tprocdef(hp).genericdef).fileinfo;
+ { use the index the module got from the current compilation process }
+ current_filepos.moduleindex:=hmodule.unit_index;
+ current_tokenpos:=current_filepos;
+ current_scanner.startreplaytokens(tprocdef(tprocdef(hp).genericdef).generictokenbuf,
+ tprocdef(tprocdef(hp).genericdef).change_endian);
+ read_proc_body(nil,tprocdef(hp));
+ current_filepos:=oldcurrent_filepos;
+ end
+ else
+ MessagePos1(tprocdef(hp).fileinfo,sym_e_forward_not_resolved,tprocdef(hp).fullprocname(false));
+ end
+ else
+ if hp.typ in [objectdef,recorddef] then
+ { generate code for subtypes as well }
+ process_abstractrecorddef(tabstractrecorddef(hp));
+ end;
+ end;
+
+ begin
+ if not((tsym(p).typ=typesym) and
+ (ttypesym(p).typedef.typesym=tsym(p)) and
+ (ttypesym(p).typedef.typ in [objectdef,recorddef]) and
+ (df_specialization in ttypesym(p).typedef.defoptions)
+ ) then
+ exit;
+
+ { Setup symtablestack a definition time }
+ specobj:=tabstractrecorddef(ttypesym(p).typedef);
+
+ if not (is_class_or_object(specobj) or is_record(specobj)) then
+ exit;
+
+ oldsymtablestack:=symtablestack;
+ oldextendeddefs:=current_module.extendeddefs;
+ current_module.extendeddefs:=TFPHashObjectList.create(true);
+ symtablestack:=tdefawaresymtablestack.create;
+ if not assigned(specobj.genericdef) then
+ internalerror(200705151);
+ hmodule:=find_module_from_symtable(specobj.genericdef.owner);
+ if hmodule=nil then
+ internalerror(200705152);
+ pu:=tused_unit(hmodule.used_units.first);
+ while assigned(pu) do
+ begin
+ if not assigned(pu.u.globalsymtable) then
+ internalerror(200705153);
+ symtablestack.push(pu.u.globalsymtable);
+ pu:=tused_unit(pu.next);
+ end;
+ if assigned(hmodule.globalsymtable) then
+ symtablestack.push(hmodule.globalsymtable);
+ if assigned(hmodule.localsymtable) then
+ symtablestack.push(hmodule.localsymtable);
+
+ { procedure definitions for classes or objects }
+ process_abstractrecorddef(specobj);
+
+ { Restore symtablestack }
+ current_module.extendeddefs.free;
+ current_module.extendeddefs:=oldextendeddefs;
+ symtablestack.free;
+ symtablestack:=oldsymtablestack;
+ end;
+
+
+ procedure generate_specialization_procs;
+ begin
+ if assigned(current_module.globalsymtable) then
+ current_module.globalsymtable.SymList.ForEachCall(@specialize_objectdefs,nil);
+ if assigned(current_module.localsymtable) then
+ current_module.localsymtable.SymList.ForEachCall(@specialize_objectdefs,nil);
+ end;
+
+end.
diff --git a/closures/compiler/psystem.pas b/closures/compiler/psystem.pas
new file mode 100644
index 0000000000..393af3cb55
--- /dev/null
+++ b/closures/compiler/psystem.pas
@@ -0,0 +1,625 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Load the system unit, create required defs for systemunit
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit psystem;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ symbase;
+
+ procedure create_intern_symbols;
+ procedure create_intern_types;
+
+ procedure load_intern_types;
+
+ procedure registernodes;
+ procedure registertais;
+
+
+implementation
+
+ uses
+ globals,globtype,verbose,constexp,cpuinfo,
+ systems,
+ symconst,symtype,symsym,symdef,symtable,
+ aasmtai,aasmdata,aasmcpu,
+ ncgutil,ncgrtti,fmodule,
+ node,nbas,nflw,nset,ncon,ncnv,nld,nmem,ncal,nmat,nadd,ninl,nopt
+ ;
+
+
+ procedure create_intern_symbols;
+ {
+ all intern procedures for the system unit
+ }
+ begin
+ systemunit.insert(tsyssym.create('Concat',in_concat_x));
+ systemunit.insert(tsyssym.create('Write',in_write_x));
+ systemunit.insert(tsyssym.create('WriteLn',in_writeln_x));
+ systemunit.insert(tsyssym.create('WriteStr',in_writestr_x));
+ systemunit.insert(tsyssym.create('Assigned',in_assigned_x));
+ systemunit.insert(tsyssym.create('Read',in_read_x));
+ systemunit.insert(tsyssym.create('ReadLn',in_readln_x));
+ systemunit.insert(tsyssym.create('ReadStr',in_readstr_x));
+ systemunit.insert(tsyssym.create('Ofs',in_ofs_x));
+ systemunit.insert(tsyssym.create('SizeOf',in_sizeof_x));
+ systemunit.insert(tsyssym.create('BitSizeOf',in_bitsizeof_x));
+ systemunit.insert(tsyssym.create('TypeOf',in_typeof_x));
+ systemunit.insert(tsyssym.create('Low',in_low_x));
+ systemunit.insert(tsyssym.create('High',in_high_x));
+ systemunit.insert(tsyssym.create('Slice',in_slice_x));
+ systemunit.insert(tsyssym.create('Seg',in_seg_x));
+ systemunit.insert(tsyssym.create('Ord',in_ord_x));
+ systemunit.insert(tsyssym.create('Pred',in_pred_x));
+ systemunit.insert(tsyssym.create('Succ',in_succ_x));
+ systemunit.insert(tsyssym.create('Exclude',in_exclude_x_y));
+ systemunit.insert(tsyssym.create('Include',in_include_x_y));
+ systemunit.insert(tsyssym.create('Pack',in_pack_x_y_z));
+ systemunit.insert(tsyssym.create('Unpack',in_unpack_x_y_z));
+ systemunit.insert(tsyssym.create('Break',in_break));
+ systemunit.insert(tsyssym.create('Exit',in_exit));
+ systemunit.insert(tsyssym.create('Continue',in_continue));
+ systemunit.insert(tsyssym.create('Leave',in_leave)); {macpas only}
+ systemunit.insert(tsyssym.create('Cycle',in_cycle)); {macpas only}
+ systemunit.insert(tsyssym.create('Dec',in_dec_x));
+ systemunit.insert(tsyssym.create('Inc',in_inc_x));
+ systemunit.insert(tsyssym.create('Str',in_str_x_string));
+ systemunit.insert(tsyssym.create('Assert',in_assert_x_y));
+ systemunit.insert(tsyssym.create('Val',in_val_x));
+ systemunit.insert(tsyssym.create('Addr',in_addr_x));
+ systemunit.insert(tsyssym.create('TypeInfo',in_typeinfo_x));
+ systemunit.insert(tsyssym.create('SetLength',in_setlength_x));
+ systemunit.insert(tsyssym.create('Copy',in_copy_x));
+ systemunit.insert(tsyssym.create('Initialize',in_initialize_x));
+ systemunit.insert(tsyssym.create('Finalize',in_finalize_x));
+ systemunit.insert(tsyssym.create('Length',in_length_x));
+ systemunit.insert(tsyssym.create('New',in_new_x));
+ systemunit.insert(tsyssym.create('Dispose',in_dispose_x));
+{$if defined(x86) or defined(arm)}
+ systemunit.insert(tsyssym.create('Get_Frame',in_get_frame));
+{$endif defined(x86) or defined(arm)}
+ systemunit.insert(tsyssym.create('Unaligned',in_unaligned_x));
+ systemunit.insert(tsyssym.create('ObjCSelector',in_objc_selector_x)); { objc only }
+ systemunit.insert(tsyssym.create('ObjCEncode',in_objc_encode_x)); { objc only }
+ end;
+
+
+ procedure create_intern_types;
+ {
+ all the types inserted into the system unit
+ }
+
+ function addtype(const s:string;def:tdef):ttypesym;
+ begin
+ result:=ttypesym.create(s,def);
+ systemunit.insert(result);
+ end;
+
+ procedure addfield(recst:tabstractrecordsymtable;sym:tfieldvarsym);
+ begin
+ recst.insert(sym);
+ recst.addfield(sym,vis_hidden);
+ end;
+
+ procedure create_fpu_types;
+ begin
+ if init_settings.fputype<>fpu_none then
+ begin
+ s32floattype:=tfloatdef.create(s32real);
+ s64floattype:=tfloatdef.create(s64real);
+ s80floattype:=tfloatdef.create(s80real);
+ sc80floattype:=tfloatdef.create(sc80real);
+ end else begin
+ s32floattype:=nil;
+ s64floattype:=nil;
+ s80floattype:=nil;
+ sc80floattype:=nil;
+ end;
+ end;
+
+ var
+ hrecst : trecordsymtable;
+ begin
+ symtablestack.push(systemunit);
+ cundefinedtype:=tundefineddef.create;
+ cformaltype:=tformaldef.create(false);
+ ctypedformaltype:=tformaldef.create(true);
+ voidtype:=torddef.create(uvoid,0,0);
+ u8inttype:=torddef.create(u8bit,0,255);
+ s8inttype:=torddef.create(s8bit,int64(-128),127);
+ u16inttype:=torddef.create(u16bit,0,65535);
+ s16inttype:=torddef.create(s16bit,int64(-32768),32767);
+ u32inttype:=torddef.create(u32bit,0,high(longword));
+ s32inttype:=torddef.create(s32bit,int64(low(longint)),int64(high(longint)));
+ u64inttype:=torddef.create(u64bit,low(qword),high(qword));
+ s64inttype:=torddef.create(s64bit,low(int64),high(int64));
+ pasbool8type:=torddef.create(pasbool8,0,1);
+ pasbool16type:=torddef.create(pasbool16,0,1);
+ pasbool32type:=torddef.create(pasbool32,0,1);
+ pasbool64type:=torddef.create(pasbool64,0,1);
+ bool8type:=torddef.create(bool8bit,low(int64),high(int64));
+ bool16type:=torddef.create(bool16bit,low(int64),high(int64));
+ bool32type:=torddef.create(bool32bit,low(int64),high(int64));
+ bool64type:=torddef.create(bool64bit,low(int64),high(int64));
+ cchartype:=torddef.create(uchar,0,255);
+ cwidechartype:=torddef.create(uwidechar,0,65535);
+ cshortstringtype:=tstringdef.createshort(255);
+ { should we give a length to the default long and ansi string definition ?? }
+ clongstringtype:=tstringdef.createlong(-1);
+ cansistringtype:=tstringdef.createansi(0);
+ if target_info.system in systems_windows then
+ cwidestringtype:=tstringdef.createwide
+ else
+ cwidestringtype:=tstringdef.createunicode;
+ cunicodestringtype:=tstringdef.createunicode;
+ { length=0 for shortstring is open string (needed for readln(string) }
+ openshortstringtype:=tstringdef.createshort(0);
+ openchararraytype:=tarraydef.create(0,-1,s32inttype);
+ tarraydef(openchararraytype).elementdef:=cchartype;
+{$ifdef x86}
+ create_fpu_types;
+ if target_info.system<>system_x86_64_win64 then
+ s64currencytype:=tfloatdef.create(s64currency)
+ else
+ begin
+ s64currencytype:=torddef.create(scurrency,low(int64),high(int64));
+ pbestrealtype:=@s64floattype;
+ end;
+{$endif x86}
+{$ifdef powerpc}
+ create_fpu_types;
+ s64currencytype:=torddef.create(scurrency,low(int64),high(int64));
+{$endif powerpc}
+{$ifdef POWERPC64}
+ create_fpu_types;
+ s64currencytype:=torddef.create(scurrency,low(int64),high(int64));
+{$endif POWERPC64}
+{$ifdef sparc}
+ create_fpu_types;
+ s64currencytype:=torddef.create(scurrency,low(int64),high(int64));
+{$endif sparc}
+{$ifdef m68k}
+ create_fpu_types;
+ s64currencytype:=torddef.create(scurrency,low(int64),high(int64));
+{$endif}
+{$ifdef arm}
+ create_fpu_types;
+ s64currencytype:=torddef.create(scurrency,low(int64),high(int64));
+{$endif arm}
+{$ifdef avr}
+ s32floattype:=tfloatdef.create(s32real);
+ s64floattype:=tfloatdef.create(s64real);
+ s80floattype:=tfloatdef.create(s80real);
+ sc80floattype:=tfloatdef.create(sc80real);
+ s64currencytype:=torddef.create(scurrency,low(int64),high(int64));
+{$endif avr}
+{$ifdef cpu64bitaddr}
+ uinttype:=u64inttype;
+ sinttype:=s64inttype;
+ ptruinttype:=u64inttype;
+ ptrsinttype:=s64inttype;
+{$endif cpu64bitaddr}
+{$ifdef cpu32bitaddr}
+ ptruinttype:=u32inttype;
+ ptrsinttype:=s32inttype;
+{$endif cpu32bitaddr}
+{$ifdef cpu32bitalu}
+ uinttype:=u32inttype;
+ sinttype:=s32inttype;
+{$endif cpu32bitalu}
+{$ifdef cpu16bitaddr}
+ ptruinttype:=u16inttype;
+ ptrsinttype:=s16inttype;
+{$endif cpu16bitaddr}
+{$ifdef cpu16bitalu}
+ uinttype:=u16inttype;
+ sinttype:=s16inttype;
+{$endif cpu16bitalu}
+{$ifdef cpu8bitalu}
+ uinttype:=u8inttype;
+ sinttype:=s8inttype;
+{$endif cpu8bitalu}
+ { some other definitions }
+ voidpointertype:=tpointerdef.create(voidtype);
+ charpointertype:=tpointerdef.create(cchartype);
+ widecharpointertype:=tpointerdef.create(cwidechartype);
+ voidfarpointertype:=tpointerdef.createfar(voidtype);
+ cfiletype:=tfiledef.createuntyped;
+ cvarianttype:=tvariantdef.create(vt_normalvariant);
+ colevarianttype:=tvariantdef.create(vt_olevariant);
+
+{$ifdef cpufpemu}
+ { Normal types }
+ (* we use the same types as without emulator, the only
+ difference is that direct calls to the emulator are generated
+ if (cs_fp_emulation in current_settings.moduleswitches) then
+ begin
+ addtype('Single',s32floattype);
+ { extended size is the best real type for the target }
+ addtype('Real',s32floattype);
+ pbestrealtype:=@s32floattype;
+ { extended size is the best real type for the target }
+ addtype('Extended',pbestrealtype^);
+ end
+ else
+ *)
+{$endif cpufpemu}
+ if init_settings.fputype <> fpu_none then
+ begin
+ addtype('Single',s32floattype);
+ addtype('Double',s64floattype);
+ { extended size is the best real type for the target }
+ addtype('Extended',pbestrealtype^);
+ { CExtended corresponds to the C version of the Extended type
+ (either "long double" or "double") }
+ if tfloatdef(pbestrealtype^).floattype=s80real then
+ addtype('CExtended',sc80floattype)
+ else
+ addtype('CExtended',pbestrealtype^);
+ end;
+{$ifdef x86}
+ if target_info.system<>system_x86_64_win64 then
+ addtype('Comp',tfloatdef.create(s64comp));
+{$endif x86}
+ addtype('Currency',s64currencytype);
+ addtype('Pointer',voidpointertype);
+{$ifdef x86}
+ addtype('FarPointer',voidfarpointertype);
+{$endif x86}
+ addtype('ShortString',cshortstringtype);
+{$ifdef support_longstring}
+ addtype('LongString',clongstringtype);
+{$endif support_longstring}
+ addtype('AnsiString',cansistringtype);
+ addtype('WideString',cwidestringtype);
+ addtype('UnicodeString',cunicodestringtype);
+
+ addtype('OpenString',openshortstringtype);
+ addtype('Boolean',pasbool8type);
+ addtype('Boolean16',pasbool16type);
+ addtype('Boolean32',pasbool32type);
+ addtype('Boolean64',pasbool64type);
+ addtype('ByteBool',bool8type);
+ addtype('WordBool',bool16type);
+ addtype('LongBool',bool32type);
+ addtype('QWordBool',bool64type);
+ addtype('Byte',u8inttype);
+ addtype('ShortInt',s8inttype);
+ addtype('Word',u16inttype);
+ addtype('SmallInt',s16inttype);
+ addtype('LongWord',u32inttype);
+ addtype('LongInt',s32inttype);
+ addtype('QWord',u64inttype);
+ addtype('Int64',s64inttype);
+ addtype('Char',cchartype);
+ addtype('WideChar',cwidechartype);
+ addtype('Text',tfiledef.createtext);
+ addtype('TypedFile',tfiledef.createtyped(voidtype));
+ addtype('Variant',cvarianttype);
+ addtype('OleVariant',colevarianttype);
+ { Internal types }
+ addtype('$undefined',cundefinedtype);
+ addtype('$formal',cformaltype);
+ addtype('$typedformal',ctypedformaltype);
+ addtype('$void',voidtype);
+ addtype('$byte',u8inttype);
+ addtype('$shortint',s8inttype);
+ addtype('$word',u16inttype);
+ addtype('$smallint',s16inttype);
+ addtype('$ulong',u32inttype);
+ addtype('$longint',s32inttype);
+ addtype('$qword',u64inttype);
+ addtype('$int64',s64inttype);
+ addtype('$char',cchartype);
+ addtype('$widechar',cwidechartype);
+ addtype('$shortstring',cshortstringtype);
+ addtype('$longstring',clongstringtype);
+ addtype('$ansistring',cansistringtype);
+ addtype('$widestring',cwidestringtype);
+ addtype('$unicodestring',cunicodestringtype);
+ addtype('$openshortstring',openshortstringtype);
+ addtype('$boolean',pasbool8type);
+ addtype('$boolean16',pasbool16type);
+ addtype('$boolean32',pasbool32type);
+ addtype('$boolean64',pasbool64type);
+ addtype('$bytebool',bool8type);
+ addtype('$wordbool',bool16type);
+ addtype('$longbool',bool32type);
+ addtype('$qwordbool',bool64type);
+ addtype('$void_pointer',voidpointertype);
+ addtype('$char_pointer',charpointertype);
+ addtype('$widechar_pointer',widecharpointertype);
+ addtype('$void_farpointer',voidfarpointertype);
+ addtype('$openchararray',openchararraytype);
+ addtype('$file',cfiletype);
+ addtype('$variant',cvarianttype);
+ addtype('$olevariant',cvarianttype);
+ if init_settings.fputype<>fpu_none then
+ begin
+ addtype('$s32real',s32floattype);
+ addtype('$s64real',s64floattype);
+ addtype('$s80real',s80floattype);
+ addtype('$sc80real',sc80floattype);
+ end;
+ addtype('$s64currency',s64currencytype);
+ { Add a type for virtual method tables }
+ hrecst:=trecordsymtable.create('',current_settings.packrecords);
+ vmttype:=trecorddef.create('',hrecst);
+ pvmttype:=tpointerdef.create(vmttype);
+ { can't use addtype for pvmt because the rtti of the pointed
+ type is not available. The rtti for pvmt will be written implicitly
+ by thev tblarray below }
+ systemunit.insert(ttypesym.create('$pvmt',pvmttype));
+ addfield(hrecst,tfieldvarsym.create('$length',vs_value,ptrsinttype,[]));
+ addfield(hrecst,tfieldvarsym.create('$mlength',vs_value,ptrsinttype,[]));
+ addfield(hrecst,tfieldvarsym.create('$parent',vs_value,pvmttype,[]));
+ { it seems vmttype is used both for TP objects and Delphi classes,
+ so the next entry could either be the first virtual method (vm1)
+ (object) or the class name (class). We can't easily create separate
+ vtable formats for both, as gdb is hard coded to search for
+ __vtbl_ptr_type in all cases (JM) }
+ addfield(hrecst,tfieldvarsym.create('$vm1_or_classname',vs_value,tpointerdef.create(cshortstringtype),[]));
+ vmtarraytype:=tarraydef.create(0,0,s32inttype);
+ tarraydef(vmtarraytype).elementdef:=voidpointertype;
+ addfield(hrecst,tfieldvarsym.create('$__pfn',vs_value,vmtarraytype,[]));
+ addtype('$__vtbl_ptr_type',vmttype);
+ vmtarraytype:=tarraydef.create(0,1,s32inttype);
+ tarraydef(vmtarraytype).elementdef:=pvmttype;
+ addtype('$vtblarray',vmtarraytype);
+ { Add a type for methodpointers }
+ hrecst:=trecordsymtable.create('',1);
+ addfield(hrecst,tfieldvarsym.create('$proc',vs_value,voidpointertype,[]));
+ addfield(hrecst,tfieldvarsym.create('$self',vs_value,voidpointertype,[]));
+ methodpointertype:=trecorddef.create('',hrecst);
+ addtype('$methodpointer',methodpointertype);
+ symtablestack.pop(systemunit);
+ end;
+
+
+ procedure load_intern_types;
+ {
+ Load all default definitions for consts from the system unit
+ }
+
+ procedure loadtype(const s:string;var def:tdef);
+ var
+ srsym : ttypesym;
+ begin
+ srsym:=search_system_type(s);
+ def:=srsym.typedef;
+ end;
+
+ var
+ oldcurrentmodule : tmodule;
+ begin
+ if target_info.system=system_x86_64_win64 then
+ pbestrealtype:=@s64floattype;
+
+ oldcurrentmodule:=current_module;
+ set_current_module(nil);
+ loadtype('byte',u8inttype);
+ loadtype('shortint',s8inttype);
+ loadtype('word',u16inttype);
+ loadtype('smallint',s16inttype);
+ loadtype('ulong',u32inttype);
+ loadtype('longint',s32inttype);
+ loadtype('qword',u64inttype);
+ loadtype('int64',s64inttype);
+ loadtype('undefined',cundefinedtype);
+ loadtype('formal',cformaltype);
+ loadtype('typedformal',ctypedformaltype);
+ loadtype('void',voidtype);
+ loadtype('char',cchartype);
+ loadtype('widechar',cwidechartype);
+ loadtype('shortstring',cshortstringtype);
+ loadtype('longstring',clongstringtype);
+ loadtype('ansistring',cansistringtype);
+ loadtype('widestring',cwidestringtype);
+ loadtype('unicodestring',cunicodestringtype);
+ loadtype('openshortstring',openshortstringtype);
+ loadtype('openchararray',openchararraytype);
+ if init_settings.fputype <> fpu_none then
+ begin
+ loadtype('s32real',s32floattype);
+ loadtype('s64real',s64floattype);
+ loadtype('s80real',s80floattype);
+ loadtype('sc80real',sc80floattype);
+ end;
+ loadtype('s64currency',s64currencytype);
+ loadtype('boolean',pasbool8type);
+ loadtype('boolean16',pasbool16type);
+ loadtype('boolean32',pasbool32type);
+ loadtype('boolean64',pasbool64type);
+ loadtype('bytebool',bool8type);
+ loadtype('wordbool',bool16type);
+ loadtype('longbool',bool32type);
+ loadtype('qwordbool',bool64type);
+ loadtype('void_pointer',voidpointertype);
+ loadtype('char_pointer',charpointertype);
+ loadtype('widechar_pointer',widecharpointertype);
+ loadtype('void_farpointer',voidfarpointertype);
+ loadtype('file',cfiletype);
+ loadtype('pvmt',pvmttype);
+ loadtype('vtblarray',vmtarraytype);
+ loadtype('__vtbl_ptr_type',vmttype);
+ loadtype('variant',cvarianttype);
+ loadtype('olevariant',colevarianttype);
+ loadtype('methodpointer',methodpointertype);
+ loadtype('HRESULT',hresultdef);
+{$ifdef cpu64bitaddr}
+ uinttype:=u64inttype;
+ sinttype:=s64inttype;
+ ptruinttype:=u64inttype;
+ ptrsinttype:=s64inttype;
+{$endif cpu64bitaddr}
+{$ifdef cpu32bit}
+ uinttype:=u32inttype;
+ sinttype:=s32inttype;
+ ptruinttype:=u32inttype;
+ ptrsinttype:=s32inttype;
+{$endif cpu32bit}
+{$ifdef cpu16bit}
+ uinttype:=u16inttype;
+ sinttype:=s16inttype;
+ ptruinttype:=u16inttype;
+ ptrsinttype:=s16inttype;
+{$endif cpu16bit}
+ set_current_module(oldcurrentmodule);
+ end;
+
+
+ procedure registernodes;
+ {
+ Register all possible nodes in the nodeclass array that
+ will be used for loading the nodes from a ppu
+ }
+ begin
+ nodeclass[addn]:=caddnode;
+ nodeclass[muln]:=caddnode;
+ nodeclass[subn]:=caddnode;
+ nodeclass[divn]:=cmoddivnode;
+ nodeclass[symdifn]:=caddnode;
+ nodeclass[modn]:=cmoddivnode;
+ nodeclass[assignn]:=cassignmentnode;
+ nodeclass[loadn]:=cloadnode;
+ nodeclass[rangen]:=crangenode;
+ nodeclass[ltn]:=caddnode;
+ nodeclass[lten]:=caddnode;
+ nodeclass[gtn]:=caddnode;
+ nodeclass[gten]:=caddnode;
+ nodeclass[equaln]:=caddnode;
+ nodeclass[unequaln]:=caddnode;
+ nodeclass[inn]:=cinnode;
+ nodeclass[orn]:=caddnode;
+ nodeclass[xorn]:=caddnode;
+ nodeclass[shrn]:=cshlshrnode;
+ nodeclass[shln]:=cshlshrnode;
+ nodeclass[slashn]:=caddnode;
+ nodeclass[andn]:=caddnode;
+ nodeclass[subscriptn]:=csubscriptnode;
+ nodeclass[derefn]:=cderefnode;
+ nodeclass[addrn]:=caddrnode;
+ nodeclass[ordconstn]:=cordconstnode;
+ nodeclass[typeconvn]:=ctypeconvnode;
+ nodeclass[calln]:=ccallnode;
+ nodeclass[callparan]:=ccallparanode;
+ nodeclass[realconstn]:=crealconstnode;
+ nodeclass[unaryminusn]:=cunaryminusnode;
+ nodeclass[unaryplusn]:=cunaryplusnode;
+ nodeclass[asmn]:=casmnode;
+ nodeclass[vecn]:=cvecnode;
+ nodeclass[pointerconstn]:=cpointerconstnode;
+ nodeclass[stringconstn]:=cstringconstnode;
+ nodeclass[notn]:=cnotnode;
+ nodeclass[inlinen]:=cinlinenode;
+ nodeclass[niln]:=cnilnode;
+ nodeclass[errorn]:=cerrornode;
+ nodeclass[typen]:=ctypenode;
+ nodeclass[setelementn]:=csetelementnode;
+ nodeclass[setconstn]:=csetconstnode;
+ nodeclass[blockn]:=cblocknode;
+ nodeclass[statementn]:=cstatementnode;
+ nodeclass[ifn]:=cifnode;
+ nodeclass[breakn]:=cbreaknode;
+ nodeclass[continuen]:=ccontinuenode;
+ nodeclass[whilerepeatn]:=cwhilerepeatnode;
+ nodeclass[forn]:=cfornode;
+ nodeclass[exitn]:=cexitnode;
+ nodeclass[withn]:=cwithnode;
+ nodeclass[casen]:=ccasenode;
+ nodeclass[labeln]:=clabelnode;
+ nodeclass[goton]:=cgotonode;
+ nodeclass[tryexceptn]:=ctryexceptnode;
+ nodeclass[raisen]:=craisenode;
+ nodeclass[tryfinallyn]:=ctryfinallynode;
+ nodeclass[onn]:=connode;
+ nodeclass[isn]:=cisnode;
+ nodeclass[asn]:=casnode;
+ nodeclass[starstarn]:=caddnode;
+ nodeclass[arrayconstructorn]:=carrayconstructornode;
+ nodeclass[arrayconstructorrangen]:=carrayconstructorrangenode;
+ nodeclass[tempcreaten]:=ctempcreatenode;
+ nodeclass[temprefn]:=ctemprefnode;
+ nodeclass[tempdeleten]:=ctempdeletenode;
+ nodeclass[addoptn]:=caddnode;
+ nodeclass[nothingn]:=cnothingnode;
+ nodeclass[loadvmtaddrn]:=cloadvmtaddrnode;
+ nodeclass[guidconstn]:=cguidconstnode;
+ nodeclass[rttin]:=crttinode;
+ nodeclass[loadparentfpn]:=cloadparentfpnode;
+ end;
+
+
+ procedure registertais;
+ {
+ Register all possible tais in the taiclass array that
+ will be used for loading the tais from a ppu
+ }
+ begin
+ aiclass[ait_none]:=nil;
+ aiclass[ait_align]:=tai_align;
+ aiclass[ait_section]:=tai_section;
+ aiclass[ait_comment]:=tai_comment;
+ aiclass[ait_string]:=tai_string;
+ aiclass[ait_instruction]:=taicpu;
+ aiclass[ait_datablock]:=tai_datablock;
+ aiclass[ait_symbol]:=tai_symbol;
+ aiclass[ait_symbol_end]:=tai_symbol_end;
+ aiclass[ait_directive]:=tai_directive;
+ aiclass[ait_label]:=tai_label;
+ aiclass[ait_const]:=tai_const;
+ aiclass[ait_real_32bit]:=tai_real_32bit;
+ aiclass[ait_real_64bit]:=tai_real_64bit;
+ aiclass[ait_real_80bit]:=tai_real_80bit;
+ aiclass[ait_comp_64bit]:=tai_comp_64bit;
+ aiclass[ait_stab]:=tai_stab;
+ aiclass[ait_force_line]:=tai_force_line;
+ aiclass[ait_function_name]:=tai_function_name;
+{$ifdef alpha}
+ { the follow is for the DEC Alpha }
+ aiclass[ait_frame]:=tai_frame;
+ aiclass[ait_ent]:=tai_ent;
+{$endif alpha}
+{$ifdef m68k}
+{ TODO: FIXME: tai_labeled_instruction doesn't exists}
+// aiclass[ait_labeled_instruction]:=tai_labeled_instruction;
+{$endif m68k}
+{$ifdef ia64}
+ aiclass[ait_bundle]:=tai_bundle;
+ aiclass[ait_stop]:=tai_stop;
+{$endif ia64}
+{$ifdef SPARC}
+// aiclass[ait_labeled_instruction]:=tai_labeled_instruction;
+{$endif SPARC}
+{$ifdef arm}
+ aiclass[ait_thumb_func]:=tai_thumb_func;
+{$endif arm}
+ aiclass[ait_cutobject]:=tai_cutobject;
+ aiclass[ait_regalloc]:=tai_regalloc;
+ aiclass[ait_tempalloc]:=tai_tempalloc;
+ aiclass[ait_marker]:=tai_marker;
+ aiclass[ait_seh_directive]:=tai_seh_directive;
+ end;
+
+end.
diff --git a/closures/compiler/ptconst.pas b/closures/compiler/ptconst.pas
new file mode 100644
index 0000000000..51d0126472
--- /dev/null
+++ b/closures/compiler/ptconst.pas
@@ -0,0 +1,1570 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Reads typed constants
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit ptconst;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses symtype,symsym,aasmdata;
+
+ procedure read_typed_const(list:tasmlist;sym:tstaticvarsym;in_structure:boolean);
+
+
+implementation
+
+ uses
+ SysUtils,
+ globtype,systems,tokens,verbose,constexp,
+ cclasses,cutils,globals,widestr,scanner,
+ symconst,symbase,symdef,symtable,
+ aasmbase,aasmtai,aasmcpu,defutil,defcmp,
+ { pass 1 }
+ node,htypechk,procinfo,
+ nmat,nadd,ncal,nmem,nset,ncnv,ninl,ncon,nld,nflw,
+ { parser specific stuff }
+ pbase,pexpr,pdecvar,
+ { codegen }
+ cpuinfo,cgbase,dbgbase,
+ wpobase,asmutils
+ ;
+
+{$maxfpuregisters 0}
+
+{*****************************************************************************
+ Bitpacked value helpers
+*****************************************************************************}
+
+ type
+ tbitpackedval = record
+ curval, nextval: aword;
+ curbitoffset: smallint;
+ loadbitsize,packedbitsize: byte;
+ end;
+
+
+ procedure initbitpackval(out bp: tbitpackedval; packedbitsize: byte);
+ begin
+ bp.curval:=0;
+ bp.nextval:=0;
+ bp.curbitoffset:=0;
+ bp.packedbitsize:=packedbitsize;
+ bp.loadbitsize:=packedbitsloadsize(bp.packedbitsize)*8;
+ end;
+
+
+{$push}
+{$r-}
+{$q-}
+ { (values between quotes below refer to fields of bp; fields not }
+ { mentioned are unused by this routine) }
+ { bitpacks "value" as bitpacked value of bitsize "packedbitsize" into }
+ { "curval", which has already been filled up to "curbitoffset", and }
+ { stores the spillover if any into "nextval". It also updates }
+ { curbitoffset to reflect how many bits of currval are now used (can be }
+ { > AIntBits in case of spillover) }
+ procedure bitpackval(value: aword; var bp: tbitpackedval);
+ var
+ shiftcount: longint;
+ begin
+ if (target_info.endian=endian_big) then
+ begin
+ { bitpacked format: left-aligned (i.e., "big endian bitness") }
+ bp.curval:=bp.curval or ((value shl (AIntBits-bp.packedbitsize)) shr bp.curbitoffset);
+ shiftcount:=((AIntBits-bp.packedbitsize)-bp.curbitoffset);
+ { carry-over to the next element? }
+ if (shiftcount<0) then
+ bp.nextval:=(value and ((aword(1) shl (-shiftcount))-1)) shl
+ (AIntBits+shiftcount)
+ end
+ else
+ begin
+ { bitpacked format: right aligned (i.e., "little endian bitness") }
+ bp.curval:=bp.curval or (value shl bp.curbitoffset);
+ { carry-over to the next element? }
+ if (bp.curbitoffset+bp.packedbitsize>AIntBits) then
+ bp.nextval:=value shr (AIntBits-bp.curbitoffset)
+ end;
+ inc(bp.curbitoffset,bp.packedbitsize);
+ end;
+
+{$pop}
+
+ procedure flush_packed_value(list: tasmlist; var bp: tbitpackedval);
+ var
+ bitstowrite: longint;
+ writeval : byte;
+ begin
+ if (bp.curbitoffset < AIntBits) then
+ begin
+ { forced flush -> write multiple of loadsize }
+ bitstowrite:=align(bp.curbitoffset,bp.loadbitsize);
+ bp.curbitoffset:=0;
+ end
+ else
+ begin
+ bitstowrite:=AIntBits;
+ dec(bp.curbitoffset,AIntBits);
+ end;
+ while (bitstowrite>=8) do
+ begin
+ if (target_info.endian=endian_little) then
+ begin
+ { write lowest byte }
+ writeval:=byte(bp.curval);
+ bp.curval:=bp.curval shr 8;
+ end
+ else
+ begin
+ { write highest byte }
+ writeval:=bp.curval shr (AIntBits-8);
+ bp.curval:=(bp.curval and (not($ff shl (AIntBits-8)))) shl 8;
+ end;
+ list.concat(tai_const.create_8bit(writeval));
+ dec(bitstowrite,8);
+ end;
+ bp.curval:=bp.nextval;
+ bp.nextval:=0;
+ end;
+
+
+{*****************************************************************************
+ read typed const
+*****************************************************************************}
+
+ type
+ { context used for parsing complex types (arrays/records/objects) }
+ threc = record
+ list : tasmlist;
+ origsym: tstaticvarsym;
+ offset: asizeint;
+ origblock: tblock_type;
+ end;
+
+ { this procedure reads typed constants }
+ procedure read_typed_const_data(var hr:threc;def:tdef); forward;
+
+ procedure parse_orddef(list:tasmlist;def:torddef);
+ var
+ n : tnode;
+ intvalue : tconstexprint;
+
+ procedure do_error;
+ begin
+ if is_constnode(n) then
+ IncompatibleTypes(n.resultdef, def)
+ else
+ Message(parser_e_illegal_expression);
+ end;
+
+ begin
+ n:=comp_expr(true,false);
+ { for C-style booleans, true=-1 and false=0) }
+ if is_cbool(def) then
+ inserttypeconv(n,def);
+ case def.ordtype of
+ pasbool8,
+ bool8bit :
+ begin
+ if is_constboolnode(n) then
+ list.concat(Tai_const.Create_8bit(byte(tordconstnode(n).value.svalue)))
+ else
+ do_error;
+ end;
+ pasbool16,
+ bool16bit :
+ begin
+ if is_constboolnode(n) then
+ list.concat(Tai_const.Create_16bit(word(tordconstnode(n).value.svalue)))
+ else
+ do_error;
+ end;
+ pasbool32,
+ bool32bit :
+ begin
+ if is_constboolnode(n) then
+ list.concat(Tai_const.Create_32bit(longint(tordconstnode(n).value.svalue)))
+ else
+ do_error;
+ end;
+ pasbool64,
+ bool64bit :
+ begin
+ if is_constboolnode(n) then
+ list.concat(Tai_const.Create_64bit(int64(tordconstnode(n).value.svalue)))
+ else
+ do_error;
+ end;
+ uchar :
+ begin
+ if is_constwidecharnode(n) then
+ inserttypeconv(n,cchartype);
+ if is_constcharnode(n) or
+ ((m_delphi in current_settings.modeswitches) and
+ is_constwidecharnode(n) and
+ (tordconstnode(n).value <= 255)) then
+ list.concat(Tai_const.Create_8bit(byte(tordconstnode(n).value.svalue)))
+ else
+ do_error;
+ end;
+ uwidechar :
+ begin
+ if is_constcharnode(n) then
+ inserttypeconv(n,cwidechartype);
+ if is_constwidecharnode(n) then
+ list.concat(Tai_const.Create_16bit(word(tordconstnode(n).value.svalue)))
+ else
+ do_error;
+ end;
+ s8bit,u8bit,
+ u16bit,s16bit,
+ s32bit,u32bit,
+ s64bit,u64bit :
+ begin
+ if is_constintnode(n) then
+ begin
+ testrange(def,tordconstnode(n).value,false,false);
+ case def.size of
+ 1 :
+ list.concat(Tai_const.Create_8bit(byte(tordconstnode(n).value.svalue)));
+ 2 :
+ list.concat(Tai_const.Create_16bit(word(tordconstnode(n).value.svalue)));
+ 4 :
+ list.concat(Tai_const.Create_32bit(longint(tordconstnode(n).value.svalue)));
+ 8 :
+ list.concat(Tai_const.Create_64bit(tordconstnode(n).value.svalue));
+ end;
+ end
+ else
+ do_error;
+ end;
+ scurrency:
+ begin
+ if is_constintnode(n) then
+ intvalue := tordconstnode(n).value
+ { allow bootstrapping }
+ else if is_constrealnode(n) then
+ intvalue:=PInt64(@trealconstnode(n).value_currency)^
+ else
+ begin
+ intvalue:=0;
+ IncompatibleTypes(n.resultdef, def);
+ end;
+ list.concat(Tai_const.Create_64bit(intvalue));
+ end;
+ else
+ internalerror(200611052);
+ end;
+ n.free;
+ end;
+
+ procedure parse_floatdef(list:tasmlist;def:tfloatdef);
+ var
+ n : tnode;
+ value : bestreal;
+ begin
+ n:=comp_expr(true,false);
+ if is_constrealnode(n) then
+ value:=trealconstnode(n).value_real
+ else if is_constintnode(n) then
+ value:=tordconstnode(n).value
+ else if is_constnode(n) then
+ IncompatibleTypes(n.resultdef, def)
+ else
+ Message(parser_e_illegal_expression);
+
+ case def.floattype of
+ s32real :
+ list.concat(Tai_real_32bit.Create(ts32real(value)));
+ s64real :
+{$ifdef ARM}
+ if is_double_hilo_swapped then
+ list.concat(Tai_real_64bit.Create_hiloswapped(ts64real(value)))
+ else
+{$endif ARM}
+ list.concat(Tai_real_64bit.Create(ts64real(value)));
+ s80real :
+ list.concat(Tai_real_80bit.Create(value,s80floattype.size));
+ sc80real :
+ list.concat(Tai_real_80bit.Create(value,sc80floattype.size));
+ s64comp :
+ { the round is necessary for native compilers where comp isn't a float }
+ list.concat(Tai_comp_64bit.Create(round(value)));
+ s64currency:
+ list.concat(Tai_comp_64bit.Create(round(value*10000)));
+ s128real:
+ list.concat(Tai_real_128bit.Create(value));
+ else
+ internalerror(200611053);
+ end;
+ n.free;
+ end;
+
+ procedure parse_classrefdef(list:tasmlist;def:tclassrefdef);
+ var
+ n : tnode;
+ begin
+ n:=comp_expr(true,false);
+ case n.nodetype of
+ loadvmtaddrn:
+ begin
+ if not Tobjectdef(tclassrefdef(n.resultdef).pointeddef).is_related(tobjectdef(def.pointeddef)) then
+ IncompatibleTypes(n.resultdef, def);
+ list.concat(Tai_const.Create_sym(current_asmdata.RefAsmSymbol(Tobjectdef(tclassrefdef(n.resultdef).pointeddef).vmt_mangledname)));
+ { update wpo info }
+ if not assigned(current_procinfo) or
+ (po_inline in current_procinfo.procdef.procoptions) or
+ wpoinfomanager.symbol_live(current_procinfo.procdef.mangledname) then
+ tobjectdef(tclassrefdef(n.resultdef).pointeddef).register_maybe_created_object_type;
+ end;
+ niln:
+ list.concat(Tai_const.Create_sym(nil));
+ else if is_constnode(n) then
+ IncompatibleTypes(n.resultdef, def)
+ else
+ Message(parser_e_illegal_expression);
+ end;
+ n.free;
+ end;
+
+ procedure parse_pointerdef(list:tasmlist;def:tpointerdef);
+ var
+ hp,p : tnode;
+ srsym : tsym;
+ pd : tprocdef;
+ ca : pchar;
+ pw : pcompilerwidestring;
+ i,len : longint;
+ base,
+ offset : aint;
+ v : Tconstexprint;
+ ll : tasmlabel;
+ varalign : shortint;
+ begin
+ p:=comp_expr(true,false);
+ { remove equal typecasts for pointer/nil addresses }
+ if (p.nodetype=typeconvn) then
+ with Ttypeconvnode(p) do
+ if (left.nodetype in [addrn,niln]) and equal_defs(def,p.resultdef) then
+ begin
+ hp:=left;
+ left:=nil;
+ p.free;
+ p:=hp;
+ end;
+ { allows horrible ofs(typeof(TButton)^) code !! }
+ if (p.nodetype=addrn) then
+ with Taddrnode(p) do
+ if left.nodetype=derefn then
+ begin
+ hp:=tderefnode(left).left;
+ tderefnode(left).left:=nil;
+ p.free;
+ p:=hp;
+ end;
+ { const pointer ? }
+ if (p.nodetype = pointerconstn) then
+ begin
+ {$if sizeof(TConstPtrUInt)=8}
+ list.concat(Tai_const.Create_64bit(int64(tpointerconstnode(p).value)));
+ {$else}
+ {$if sizeof(TConstPtrUInt)=4}
+ list.concat(Tai_const.Create_32bit(longint(tpointerconstnode(p).value)));
+ {$else}
+ internalerror(200404122);
+ {$endif} {$endif}
+ end
+ { nil pointer ? }
+ else if p.nodetype=niln then
+ list.concat(Tai_const.Create_sym(nil))
+ { maybe pchar ? }
+ else
+ if is_char(def.pointeddef) and
+ (p.nodetype<>addrn) then
+ begin
+ current_asmdata.getdatalabel(ll);
+ list.concat(Tai_const.Create_sym(ll));
+ if p.nodetype=stringconstn then
+ varalign:=size_2_align(tstringconstnode(p).len)
+ else
+ varalign:=0;
+ varalign:=const_align(varalign);
+ new_section(current_asmdata.asmlists[al_const], sec_rodata, ll.name, varalign);
+ current_asmdata.asmlists[al_const].concat(Tai_label.Create(ll));
+ if p.nodetype=stringconstn then
+ begin
+ len:=tstringconstnode(p).len;
+ { For tp7 the maximum lentgh can be 255 }
+ if (m_tp7 in current_settings.modeswitches) and
+ (len>255) then
+ len:=255;
+ getmem(ca,len+2);
+ move(tstringconstnode(p).value_str^,ca^,len+1);
+ current_asmdata.asmlists[al_const].concat(Tai_string.Create_pchar(ca,len+1));
+ end
+ else
+ if is_constcharnode(p) then
+ current_asmdata.asmlists[al_const].concat(Tai_string.Create(char(byte(tordconstnode(p).value.svalue))+#0))
+ else
+ IncompatibleTypes(p.resultdef, def);
+ end
+ { maybe pwidechar ? }
+ else
+ if is_widechar(def.pointeddef) and
+ (p.nodetype<>addrn) then
+ begin
+ current_asmdata.getdatalabel(ll);
+ list.concat(Tai_const.Create_sym(ll));
+ current_asmdata.asmlists[al_typedconsts].concat(tai_align.create(const_align(sizeof(pint))));
+ current_asmdata.asmlists[al_typedconsts].concat(Tai_label.Create(ll));
+ if (p.nodetype in [stringconstn,ordconstn]) then
+ begin
+ { convert to widestring stringconstn }
+ inserttypeconv(p,cwidestringtype);
+ if (p.nodetype=stringconstn) and
+ (tstringconstnode(p).cst_type in [cst_widestring,cst_unicodestring]) then
+ begin
+ pw:=pcompilerwidestring(tstringconstnode(p).value_str);
+ for i:=0 to tstringconstnode(p).len-1 do
+ current_asmdata.asmlists[al_typedconsts].concat(Tai_const.Create_16bit(pw^.data[i]));
+ { ending #0 }
+ current_asmdata.asmlists[al_typedconsts].concat(Tai_const.Create_16bit(0))
+ end;
+ end
+ else
+ IncompatibleTypes(p.resultdef, def);
+ end
+ else
+ if (p.nodetype=addrn) or
+ is_proc2procvar_load(p,pd) then
+ begin
+ { insert typeconv }
+ inserttypeconv(p,def);
+ hp:=p;
+ while assigned(hp) and (hp.nodetype in [addrn,typeconvn,subscriptn,vecn]) do
+ hp:=tunarynode(hp).left;
+ if (hp.nodetype=loadn) then
+ begin
+ hp:=p;
+ offset:=0;
+ while assigned(hp) and (hp.nodetype<>loadn) do
+ begin
+ case hp.nodetype of
+ vecn :
+ begin
+ case tvecnode(hp).left.resultdef.typ of
+ stringdef :
+ begin
+ { this seems OK for shortstring and ansistrings PM }
+ { it is wrong for widestrings !! }
+ len:=1;
+ base:=0;
+ end;
+ arraydef :
+ begin
+ if not is_packed_array(tvecnode(hp).left.resultdef) then
+ begin
+ len:=tarraydef(tvecnode(hp).left.resultdef).elesize;
+ base:=tarraydef(tvecnode(hp).left.resultdef).lowrange;
+ end
+ else
+ begin
+ Message(parser_e_packed_dynamic_open_array);
+ len:=1;
+ base:=0;
+ end;
+ end
+ else
+ Message(parser_e_illegal_expression);
+ end;
+ if is_constintnode(tvecnode(hp).right) then
+ begin
+ {Prevent overflow.}
+ v:=get_ordinal_value(tvecnode(hp).right)-base;
+ if (v<int64(low(offset))) or (v>int64(high(offset))) then
+ message(parser_e_range_check_error);
+ if high(offset)-offset div len>v then
+ inc(offset,len*v.svalue)
+ else
+ message(parser_e_range_check_error);
+ end
+ else
+ Message(parser_e_illegal_expression);
+ end;
+ subscriptn :
+ inc(offset,tsubscriptnode(hp).vs.fieldoffset);
+ typeconvn :
+ begin
+ if not(ttypeconvnode(hp).convtype in [tc_equal,tc_proc_2_procvar]) then
+ Message(parser_e_illegal_expression);
+ end;
+ addrn :
+ ;
+ else
+ Message(parser_e_illegal_expression);
+ end;
+ hp:=tunarynode(hp).left;
+ end;
+ srsym:=tloadnode(hp).symtableentry;
+ case srsym.typ of
+ procsym :
+ begin
+ pd:=tprocdef(tprocsym(srsym).ProcdefList[0]);
+ if Tprocsym(srsym).ProcdefList.Count>1 then
+ Message(parser_e_no_overloaded_procvars);
+ if po_abstractmethod in pd.procoptions then
+ Message(type_e_cant_take_address_of_abstract_method)
+ else
+ list.concat(Tai_const.Createname(pd.mangledname,offset));
+ end;
+ staticvarsym :
+ list.concat(Tai_const.Createname(tstaticvarsym(srsym).mangledname,offset));
+ labelsym :
+ list.concat(Tai_const.Createname(tlabelsym(srsym).mangledname,offset));
+ constsym :
+ if tconstsym(srsym).consttyp=constresourcestring then
+ list.concat(Tai_const.Createname(make_mangledname('RESSTR',tconstsym(srsym).owner,tconstsym(srsym).name),sizeof(pint)))
+ else
+ Message(type_e_variable_id_expected);
+ else
+ Message(type_e_variable_id_expected);
+ end;
+ end
+ else
+ Message(parser_e_illegal_expression);
+ end
+ else
+ { allow typeof(Object type)}
+ if (p.nodetype=inlinen) and
+ (tinlinenode(p).inlinenumber=in_typeof_x) then
+ begin
+ if (tinlinenode(p).left.nodetype=typen) then
+ begin
+ list.concat(Tai_const.createname(
+ tobjectdef(tinlinenode(p).left.resultdef).vmt_mangledname,0));
+ end
+ else
+ Message(parser_e_illegal_expression);
+ end
+ else
+ Message(parser_e_illegal_expression);
+ p.free;
+ end;
+
+ procedure parse_setdef(list:tasmlist;def:tsetdef);
+ type
+ setbytes = array[0..31] of byte;
+ Psetbytes = ^setbytes;
+ var
+ p : tnode;
+ i : longint;
+ begin
+ p:=comp_expr(true,false);
+ if p.nodetype=setconstn then
+ begin
+ { be sure to convert to the correct result, else
+ it can generate smallset data instead of normalset (PFV) }
+ inserttypeconv(p,def);
+ { we only allow const sets }
+ if (p.nodetype<>setconstn) or
+ assigned(tsetconstnode(p).left) then
+ Message(parser_e_illegal_expression)
+ else
+ begin
+ tsetconstnode(p).adjustforsetbase;
+ { this writing is endian-dependant }
+ if source_info.endian = target_info.endian then
+ begin
+ for i:=0 to p.resultdef.size-1 do
+ list.concat(tai_const.create_8bit(Psetbytes(tsetconstnode(p).value_set)^[i]));
+ end
+ else
+ begin
+ for i:=0 to p.resultdef.size-1 do
+ list.concat(tai_const.create_8bit(reverse_byte(Psetbytes(tsetconstnode(p).value_set)^[i])));
+ end;
+ end;
+ end
+ else
+ Message(parser_e_illegal_expression);
+ p.free;
+ end;
+
+ procedure parse_enumdef(list:tasmlist;def:tenumdef);
+ var
+ p : tnode;
+ begin
+ p:=comp_expr(true,false);
+ if p.nodetype=ordconstn then
+ begin
+ if equal_defs(p.resultdef,def) or
+ is_subequal(p.resultdef,def) then
+ begin
+ case longint(p.resultdef.size) of
+ 1 : list.concat(Tai_const.Create_8bit(Byte(tordconstnode(p).value.svalue)));
+ 2 : list.concat(Tai_const.Create_16bit(Word(tordconstnode(p).value.svalue)));
+ 4 : list.concat(Tai_const.Create_32bit(Longint(tordconstnode(p).value.svalue)));
+ end;
+ end
+ else
+ IncompatibleTypes(p.resultdef,def);
+ end
+ else
+ Message(parser_e_illegal_expression);
+ p.free;
+ end;
+
+
+ procedure parse_stringdef(const hr:threc;def:tstringdef);
+ var
+ n : tnode;
+ strlength : aint;
+ strval : pchar;
+ strch : char;
+ ll : tasmlabel;
+ ca : pchar;
+ winlike : boolean;
+ hsym : tconstsym;
+ begin
+ n:=comp_expr(true,false);
+ { load strval and strlength of the constant tree }
+ if (n.nodetype=stringconstn) or is_wide_or_unicode_string(def) or is_constwidecharnode(n) or
+ ((n.nodetype=typen) and is_interfacecorba(ttypenode(n).typedef)) then
+ begin
+ { convert to the expected string type so that
+ for widestrings strval is a pcompilerwidestring }
+ inserttypeconv(n,def);
+ if (not codegenerror) and
+ (n.nodetype=stringconstn) then
+ begin
+ strlength:=tstringconstnode(n).len;
+ strval:=tstringconstnode(n).value_str;
+ end
+ else
+ begin
+ { an error occurred trying to convert the result to a string }
+ strlength:=-1;
+ { it's possible that the type conversion could not be
+ evaluated at compile-time }
+ if not codegenerror then
+ CGMessage(parser_e_widestring_to_ansi_compile_time);
+ end;
+ end
+ else if is_constcharnode(n) then
+ begin
+ { strval:=pchar(@tordconstnode(n).value);
+ THIS FAIL on BIG_ENDIAN MACHINES PM }
+ strch:=chr(tordconstnode(n).value.svalue and $ff);
+ strval:=@strch;
+ strlength:=1
+ end
+ else if is_constresourcestringnode(n) then
+ begin
+ hsym:=tconstsym(tloadnode(n).symtableentry);
+ strval:=pchar(hsym.value.valueptr);
+ strlength:=hsym.value.len;
+ { Delphi-compatible (mis)feature:
+ Link AnsiString constants to their initializing resourcestring,
+ enabling them to be (re)translated at runtime.
+ Wide/UnicodeString are currently rejected above (with incorrect error message).
+ ShortStrings cannot be handled unless another table is built for them;
+ considering this acceptable, because Delphi rejects them altogether.
+ }
+ if (not is_shortstring(def)) and
+ ((hr.origsym.owner.symtablelevel<=main_program_level) or
+ (hr.origblock=bt_const)) then
+ begin
+ current_asmdata.ResStrInits.Concat(
+ TTCInitItem.Create(hr.origsym,hr.offset,
+ current_asmdata.RefAsmSymbol(make_mangledname('RESSTR',hsym.owner,hsym.name)))
+ );
+ Include(hr.origsym.varoptions,vo_force_finalize);
+ end;
+ end
+ else
+ begin
+ Message(parser_e_illegal_expression);
+ strlength:=-1;
+ end;
+ if strlength>=0 then
+ begin
+ case def.stringtype of
+ st_shortstring:
+ begin
+ if strlength>=def.size then
+ begin
+ message2(parser_w_string_too_long,strpas(strval),tostr(def.size-1));
+ strlength:=def.size-1;
+ end;
+ hr.list.concat(Tai_const.Create_8bit(strlength));
+ { this can also handle longer strings }
+ getmem(ca,strlength+1);
+ move(strval^,ca^,strlength);
+ ca[strlength]:=#0;
+ hr.list.concat(Tai_string.Create_pchar(ca,strlength));
+ { fillup with spaces if size is shorter }
+ if def.size>strlength then
+ begin
+ getmem(ca,def.size-strlength);
+ { def.size contains also the leading length, so we }
+ { we have to subtract one }
+ fillchar(ca[0],def.size-strlength-1,' ');
+ ca[def.size-strlength-1]:=#0;
+ { this can also handle longer strings }
+ hr.list.concat(Tai_string.Create_pchar(ca,def.size-strlength-1));
+ end;
+ end;
+ st_ansistring:
+ begin
+ { an empty ansi string is nil! }
+ if (strlength=0) then
+ ll := nil
+ else
+ ll := emit_ansistring_const(current_asmdata.asmlists[al_const],strval,strlength,def.encoding);
+ hr.list.concat(Tai_const.Create_sym(ll));
+ end;
+ st_unicodestring,
+ st_widestring:
+ begin
+ { an empty wide/unicode string is nil! }
+ if (strlength=0) then
+ ll := nil
+ else
+ begin
+ winlike := (def.stringtype=st_widestring) and (tf_winlikewidestring in target_info.flags);
+ ll := emit_unicodestring_const(current_asmdata.asmlists[al_const],
+ strval,
+ def.encoding,
+ winlike);
+
+ { Collect Windows widestrings that need initialization at startup.
+ Local initialized vars are excluded because they are initialized
+ at function entry instead. }
+ if winlike and ((hr.origsym.owner.symtablelevel <= main_program_level) or
+ (hr.origblock=bt_const)) then
+ begin
+ current_asmdata.WideInits.Concat(
+ TTCInitItem.Create(hr.origsym, hr.offset, ll)
+ );
+ ll := nil;
+ Include(hr.origsym.varoptions, vo_force_finalize);
+ end;
+ end;
+ hr.list.concat(Tai_const.Create_sym(ll));
+ end;
+ else
+ internalerror(200107081);
+ end;
+ end;
+ n.free;
+ end;
+
+
+ { parse a single constant and add it to the packed const info }
+ { represented by curval etc (see explanation of bitpackval for }
+ { what the different parameters mean) }
+ function parse_single_packed_const(list: tasmlist; def: tdef; var bp: tbitpackedval): boolean;
+ var
+ n : tnode;
+ begin
+ result:=true;
+ n:=comp_expr(true,false);
+ if (n.nodetype <> ordconstn) or
+ (not equal_defs(n.resultdef,def) and
+ not is_subequal(n.resultdef,def)) then
+ begin
+ n.free;
+ incompatibletypes(n.resultdef,def);
+ consume_all_until(_SEMICOLON);
+ result:=false;
+ exit;
+ end;
+ if (Tordconstnode(n).value<qword(low(Aword))) or (Tordconstnode(n).value>qword(high(Aword))) then
+ message(parser_e_range_check_error)
+ else
+ bitpackval(Tordconstnode(n).value.uvalue,bp);
+ if (bp.curbitoffset>=AIntBits) then
+ flush_packed_value(list,bp);
+ n.free;
+ end;
+
+
+ { parses a packed array constant }
+ procedure parse_packed_array_def(list: tasmlist; def: tarraydef);
+ var
+ i : aint;
+ bp : tbitpackedval;
+ begin
+ if not(def.elementdef.typ in [orddef,enumdef]) then
+ internalerror(2007022010);
+ { begin of the array }
+ consume(_LKLAMMER);
+ initbitpackval(bp,def.elepackedbitsize);
+ i:=def.lowrange;
+ { can't use for-loop, fails when cross-compiling from }
+ { 32 to 64 bit because i is then 64 bit }
+ while (i<def.highrange) do
+ begin
+ { get next item of the packed array }
+ if not parse_single_packed_const(list,def.elementdef,bp) then
+ exit;
+ consume(_COMMA);
+ inc(i);
+ end;
+ { final item }
+ if not parse_single_packed_const(list,def.elementdef,bp) then
+ exit;
+ { flush final incomplete value if necessary }
+ if (bp.curbitoffset <> 0) then
+ flush_packed_value(list,bp);
+ consume(_RKLAMMER);
+ end;
+
+
+ procedure parse_arraydef(hr:threc;def:tarraydef);
+ var
+ n : tnode;
+ i : longint;
+ len : asizeint;
+ ch : array[0..1] of char;
+ ca : pbyte;
+ int_const: tai_const;
+ char_size: integer;
+ begin
+ { dynamic array nil }
+ if is_dynamic_array(def) then
+ begin
+ { Only allow nil initialization }
+ consume(_NIL);
+ hr.list.concat(Tai_const.Create_sym(nil));
+ end
+ { packed array constant }
+ else if is_packed_array(def) and
+ ((def.elepackedbitsize mod 8 <> 0) or
+ not ispowerof2(def.elepackedbitsize div 8,i)) then
+ begin
+ parse_packed_array_def(hr.list,def);
+ end
+ { normal array const between brackets }
+ else if try_to_consume(_LKLAMMER) then
+ begin
+ hr.offset:=0;
+ for i:=def.lowrange to def.highrange-1 do
+ begin
+ read_typed_const_data(hr,def.elementdef);
+ Inc(hr.offset,def.elementdef.size);
+ if token=_RKLAMMER then
+ begin
+ Message1(parser_e_more_array_elements_expected,tostr(def.highrange-i));
+ consume(_RKLAMMER);
+ exit;
+ end
+ else
+ consume(_COMMA);
+ end;
+ read_typed_const_data(hr,def.elementdef);
+ consume(_RKLAMMER);
+ end
+ { if array of char then we allow also a string }
+ else if is_anychar(def.elementdef) then
+ begin
+ char_size:=def.elementdef.size;
+ n:=comp_expr(true,false);
+ if n.nodetype=stringconstn then
+ begin
+ len:=tstringconstnode(n).len;
+ case char_size of
+ 1:
+ begin
+ if (tstringconstnode(n).cst_type in [cst_unicodestring,cst_widestring]) then
+ inserttypeconv(n,getansistringdef);
+ if n.nodetype<>stringconstn then
+ internalerror(2010033003);
+ ca:=pointer(tstringconstnode(n).value_str);
+ end;
+ 2:
+ begin
+ inserttypeconv(n,cwidestringtype);
+ if n.nodetype<>stringconstn then
+ internalerror(2010033003);
+ ca:=pointer(pcompilerwidestring(tstringconstnode(n).value_str)^.data)
+ end;
+ else
+ internalerror(2010033005);
+ end;
+ { For tp7 the maximum lentgh can be 255 }
+ if (m_tp7 in current_settings.modeswitches) and
+ (len>255) then
+ len:=255;
+ end
+ else if is_constcharnode(n) then
+ begin
+ case char_size of
+ 1:
+ ch[0]:=chr(tordconstnode(n).value.uvalue and $ff);
+ 2:
+ begin
+ inserttypeconv(n,cwidechartype);
+ if not is_constwidecharnode(n) then
+ internalerror(2010033001);
+ widechar(ch):=widechar(tordconstnode(n).value.uvalue and $ffff);
+ end;
+ else
+ internalerror(2010033002);
+ end;
+ ca:=@ch;
+ len:=1;
+ end
+ else if is_constwidecharnode(n) and (current_settings.sourcecodepage<>CP_UTF8) then
+ begin
+ case char_size of
+ 1:
+ begin
+ inserttypeconv(n,cchartype);
+ if not is_constcharnode(n) then
+ internalerror(2010033001);
+ ch[0]:=chr(tordconstnode(n).value.uvalue and $ff);
+ end;
+ 2:
+ widechar(ch):=widechar(tordconstnode(n).value.uvalue and $ffff);
+ else
+ internalerror(2010033002);
+ end;
+ ca:=@ch;
+ len:=1;
+ end
+ else
+ begin
+ Message(parser_e_illegal_expression);
+ len:=0;
+ end;
+ if len>(def.highrange-def.lowrange+1) then
+ Message(parser_e_string_larger_array);
+ for i:=0 to def.highrange-def.lowrange do
+ begin
+ if i<len then
+ begin
+ case char_size of
+ 1:
+ int_const:=Tai_const.Create_char(char_size,pbyte(ca)^);
+ 2:
+ int_const:=Tai_const.Create_char(char_size,pword(ca)^);
+ else
+ internalerror(2010033004);
+ end;
+ inc(ca, char_size);
+ end
+ else
+ {Fill the remaining positions with #0.}
+ int_const:=Tai_const.Create_char(char_size,0);
+ hr.list.concat(int_const)
+ end;
+ n.free;
+ end
+ else
+ begin
+ { we want the ( }
+ consume(_LKLAMMER);
+ end;
+ end;
+
+ procedure parse_procvardef(list:tasmlist;def:tprocvardef);
+ var
+ tmpn,n : tnode;
+ pd : tprocdef;
+ begin
+ { Procvars and pointers are no longer compatible. }
+ { under tp: =nil or =var under fpc: =nil or =@var }
+ if try_to_consume(_NIL) then
+ begin
+ list.concat(Tai_const.Create_sym(nil));
+ if not def.is_addressonly then
+ list.concat(Tai_const.Create_sym(nil));
+ exit;
+ end;
+ { you can't assign a value other than NIL to a typed constant }
+ { which is a "procedure of object", because this also requires }
+ { address of an object/class instance, which is not known at }
+ { compile time (JM) }
+ if (po_methodpointer in def.procoptions) then
+ Message(parser_e_no_procvarobj_const);
+ { parse the rest too, so we can continue with error checking }
+ getprocvardef:=def;
+ n:=comp_expr(true,false);
+ getprocvardef:=nil;
+ if codegenerror then
+ begin
+ n.free;
+ exit;
+ end;
+ { let type conversion check everything needed }
+ inserttypeconv(n,def);
+ if codegenerror then
+ begin
+ n.free;
+ exit;
+ end;
+ { remove typeconvs, that will normally insert a lea
+ instruction which is not necessary for us }
+ while n.nodetype=typeconvn do
+ begin
+ tmpn:=ttypeconvnode(n).left;
+ ttypeconvnode(n).left:=nil;
+ n.free;
+ n:=tmpn;
+ end;
+ { remove addrn which we also don't need here }
+ if n.nodetype=addrn then
+ begin
+ tmpn:=taddrnode(n).left;
+ taddrnode(n).left:=nil;
+ n.free;
+ n:=tmpn;
+ end;
+ { we now need to have a loadn with a procsym }
+ if (n.nodetype=loadn) and
+ (tloadnode(n).symtableentry.typ=procsym) then
+ begin
+ pd:=tloadnode(n).procdef;
+ list.concat(Tai_const.createname(pd.mangledname,0));
+ { nested procvar typed consts can only be initialised with nil
+ (checked above) or with a global procedure (checked here),
+ because in other cases we need a valid frame pointer }
+ if is_nested_pd(def) then
+ begin
+ if is_nested_pd(pd) then
+ Message(parser_e_no_procvarnested_const);
+ list.concat(Tai_const.Create_sym(nil));
+ end
+ end
+ else
+ Message(parser_e_illegal_expression);
+ n.free;
+ end;
+
+ procedure parse_recorddef(hr:threc;def:trecorddef);
+ var
+ n : tnode;
+ symidx : longint;
+ recsym,
+ srsym : tsym;
+ hs : string;
+ sorg,s : TIDString;
+ tmpguid : tguid;
+ curroffset,
+ fillbytes : aint;
+ bp : tbitpackedval;
+ error,
+ is_packed: boolean;
+ startoffset: aint;
+
+ procedure handle_stringconstn;
+ var
+ i : longint;
+ begin
+ hs:=strpas(tstringconstnode(n).value_str);
+ if string2guid(hs,tmpguid) then
+ begin
+ hr.list.concat(Tai_const.Create_32bit(longint(tmpguid.D1)));
+ hr.list.concat(Tai_const.Create_16bit(tmpguid.D2));
+ hr.list.concat(Tai_const.Create_16bit(tmpguid.D3));
+ for i:=Low(tmpguid.D4) to High(tmpguid.D4) do
+ hr.list.concat(Tai_const.Create_8bit(tmpguid.D4[i]));
+ end
+ else
+ Message(parser_e_improper_guid_syntax);
+ end;
+
+ function get_next_varsym(const SymList:TFPHashObjectList; var symidx:longint):tsym;inline;
+ begin
+ while symidx<SymList.Count do
+ begin
+ result:=tsym(def.symtable.SymList[symidx]);
+ inc(symidx);
+ if result.typ=fieldvarsym then
+ exit;
+ end;
+ result:=nil;
+ end;
+
+ var
+ i : longint;
+ SymList:TFPHashObjectList;
+ begin
+ { GUID }
+ if (def=rec_tguid) and (token=_ID) then
+ begin
+ n:=comp_expr(true,false);
+ if n.nodetype=stringconstn then
+ handle_stringconstn
+ else
+ begin
+ inserttypeconv(n,rec_tguid);
+ if n.nodetype=guidconstn then
+ begin
+ tmpguid:=tguidconstnode(n).value;
+ hr.list.concat(Tai_const.Create_32bit(longint(tmpguid.D1)));
+ hr.list.concat(Tai_const.Create_16bit(tmpguid.D2));
+ hr.list.concat(Tai_const.Create_16bit(tmpguid.D3));
+ for i:=Low(tmpguid.D4) to High(tmpguid.D4) do
+ hr.list.concat(Tai_const.Create_8bit(tmpguid.D4[i]));
+ end
+ else
+ Message(parser_e_illegal_expression);
+ end;
+ n.free;
+ exit;
+ end;
+ if (def=rec_tguid) and ((token=_CSTRING) or (token=_CCHAR)) then
+ begin
+ n:=comp_expr(true,false);
+ inserttypeconv(n,cshortstringtype);
+ if n.nodetype=stringconstn then
+ handle_stringconstn
+ else
+ Message(parser_e_illegal_expression);
+ n.free;
+ exit;
+ end;
+ { bitpacked record? }
+ is_packed:=is_packed_record_or_object(def);
+ if (is_packed) then
+ begin
+ { loadbitsize = 8, bitpacked records are always padded to }
+ { a multiple of a byte. packedbitsize will be set separately }
+ { for each field }
+ initbitpackval(bp,0);
+ bp.loadbitsize:=8;
+ end;
+ { normal record }
+ consume(_LKLAMMER);
+ curroffset:=0;
+ sorg:='';
+ symidx:=0;
+ symlist:=def.symtable.SymList;
+ srsym:=get_next_varsym(symlist,symidx);
+ recsym := nil;
+ startoffset:=hr.offset;
+ while token<>_RKLAMMER do
+ begin
+ s:=pattern;
+ sorg:=orgpattern;
+ consume(_ID);
+ consume(_COLON);
+ error := false;
+ recsym := tsym(def.symtable.Find(s));
+ if not assigned(recsym) then
+ begin
+ Message1(sym_e_illegal_field,sorg);
+ error := true;
+ end;
+ if (not error) and
+ (not assigned(srsym) or
+ (s <> srsym.name)) then
+ { possible variant record (JM) }
+ begin
+ { All parts of a variant start at the same offset }
+ { Also allow jumping from one variant part to another, }
+ { as long as the offsets match }
+ if (assigned(srsym) and
+ (tfieldvarsym(recsym).fieldoffset = tfieldvarsym(srsym).fieldoffset)) or
+ { srsym is not assigned after parsing w2 in the }
+ { typed const in the next example: }
+ { type tr = record case byte of }
+ { 1: (l1,l2: dword); }
+ { 2: (w1,w2: word); }
+ { end; }
+ { const r: tr = (w1:1;w2:1;l2:5); }
+ (tfieldvarsym(recsym).fieldoffset = curroffset) then
+ begin
+ srsym:=recsym;
+ { symidx should contain the next symbol id to search }
+ symidx:=SymList.indexof(srsym)+1;
+ end
+ { going backwards isn't allowed in any mode }
+ else if (tfieldvarsym(recsym).fieldoffset<curroffset) then
+ begin
+ Message(parser_e_invalid_record_const);
+ error := true;
+ end
+ { Delphi allows you to skip fields }
+ else if (m_delphi in current_settings.modeswitches) then
+ begin
+ Message1(parser_w_skipped_fields_before,sorg);
+ srsym := recsym;
+ end
+ { FPC and TP don't }
+ else
+ begin
+ Message1(parser_e_skipped_fields_before,sorg);
+ error := true;
+ end;
+ end;
+ if error then
+ consume_all_until(_SEMICOLON)
+ else
+ begin
+ { if needed fill (alignment) }
+ if tfieldvarsym(srsym).fieldoffset>curroffset then
+ begin
+ if not(is_packed) then
+ fillbytes:=tfieldvarsym(srsym).fieldoffset-curroffset
+ else
+ begin
+ flush_packed_value(hr.list,bp);
+ { curoffset is now aligned to the next byte }
+ curroffset:=align(curroffset,8);
+ { offsets are in bits in this case }
+ fillbytes:=(tfieldvarsym(srsym).fieldoffset-curroffset) div 8;
+ end;
+ for i:=1 to fillbytes do
+ hr.list.concat(Tai_const.Create_8bit(0))
+ end;
+
+ { new position }
+ curroffset:=tfieldvarsym(srsym).fieldoffset;
+ if not(is_packed) then
+ inc(curroffset,tfieldvarsym(srsym).vardef.size)
+ else
+ inc(curroffset,tfieldvarsym(srsym).vardef.packedbitsize);
+
+ { read the data }
+ if not(is_packed) or
+ { only orddefs and enumdefs are bitpacked, as in gcc/gpc }
+ not(tfieldvarsym(srsym).vardef.typ in [orddef,enumdef]) then
+ begin
+ if is_packed then
+ begin
+ flush_packed_value(hr.list,bp);
+ curroffset:=align(curroffset,8);
+ end;
+ hr.offset:=startoffset+tfieldvarsym(srsym).fieldoffset;
+ read_typed_const_data(hr,tfieldvarsym(srsym).vardef);
+ end
+ else
+ begin
+ bp.packedbitsize:=tfieldvarsym(srsym).vardef.packedbitsize;
+ parse_single_packed_const(hr.list,tfieldvarsym(srsym).vardef,bp);
+ end;
+
+ { keep previous field for checking whether whole }
+ { record was initialized (JM) }
+ recsym := srsym;
+ { goto next field }
+ srsym:=get_next_varsym(SymList,symidx);
+ if token=_SEMICOLON then
+ consume(_SEMICOLON)
+ else if (token=_COMMA) and (m_mac in current_settings.modeswitches) then
+ consume(_COMMA)
+ else
+ break;
+ end;
+ end;
+
+ { are there any fields left, but don't complain if there only
+ come other variant parts after the last initialized field }
+ if assigned(srsym) and
+ (
+ (recsym=nil) or
+ (tfieldvarsym(srsym).fieldoffset > tfieldvarsym(recsym).fieldoffset)
+ ) then
+ Message1(parser_w_skipped_fields_after,sorg);
+
+ if not(is_packed) then
+ fillbytes:=def.size-curroffset
+ else
+ begin
+ flush_packed_value(hr.list,bp);
+ curroffset:=align(curroffset,8);
+ fillbytes:=def.size-(curroffset div 8);
+ end;
+ for i:=1 to fillbytes do
+ hr.list.concat(Tai_const.Create_8bit(0));
+
+ consume(_RKLAMMER);
+ end;
+
+ { note: hr is passed by value }
+ procedure parse_objectdef(hr:threc;def:tobjectdef);
+ var
+ n : tnode;
+ i : longint;
+ obj : tobjectdef;
+ srsym : tsym;
+ st : tsymtable;
+ curroffset : aint;
+ s,sorg : TIDString;
+ vmtwritten : boolean;
+ startoffset:aint;
+ begin
+ { no support for packed object }
+ if is_packed_record_or_object(def) then
+ begin
+ Message(type_e_no_const_packed_record);
+ exit;
+ end;
+
+ { only allow nil for implicit pointer object types }
+ if is_implicit_pointer_object_type(def) then
+ begin
+ n:=comp_expr(true,false);
+ if n.nodetype<>niln then
+ begin
+ Message(parser_e_type_const_not_possible);
+ consume_all_until(_SEMICOLON);
+ end
+ else
+ hr.list.concat(Tai_const.Create_sym(nil));
+ n.free;
+ exit;
+ end;
+
+ { for objects we allow it only if it doesn't contain a vmt }
+ if (oo_has_vmt in def.objectoptions) and
+ (m_fpc in current_settings.modeswitches) then
+ begin
+ Message(parser_e_type_object_constants);
+ exit;
+ end;
+
+ consume(_LKLAMMER);
+ startoffset:=hr.offset;
+ curroffset:=0;
+ vmtwritten:=false;
+ while token<>_RKLAMMER do
+ begin
+ s:=pattern;
+ sorg:=orgpattern;
+ consume(_ID);
+ consume(_COLON);
+ srsym:=nil;
+ obj:=tobjectdef(def);
+ st:=obj.symtable;
+ while (srsym=nil) and assigned(st) do
+ begin
+ srsym:=tsym(st.Find(s));
+ if assigned(obj) then
+ obj:=obj.childof;
+ if assigned(obj) then
+ st:=obj.symtable
+ else
+ st:=nil;
+ end;
+
+ if (srsym=nil) or
+ (srsym.typ<>fieldvarsym) then
+ begin
+ if (srsym=nil) then
+ Message1(sym_e_id_not_found,sorg)
+ else
+ Message1(sym_e_illegal_field,sorg);
+ consume_all_until(_RKLAMMER);
+ break;
+ end
+ else
+ with tfieldvarsym(srsym) do
+ begin
+ { check position }
+ if fieldoffset<curroffset then
+ message(parser_e_invalid_record_const);
+
+ { check in VMT needs to be added for TP mode }
+ if not(vmtwritten) and
+ not(m_fpc in current_settings.modeswitches) and
+ (oo_has_vmt in def.objectoptions) and
+ (def.vmt_offset<fieldoffset) then
+ begin
+ for i:=1 to def.vmt_offset-curroffset do
+ hr.list.concat(tai_const.create_8bit(0));
+ hr.list.concat(tai_const.createname(def.vmt_mangledname,0));
+ { this is more general }
+ curroffset:=def.vmt_offset + sizeof(pint);
+ vmtwritten:=true;
+ end;
+
+ { if needed fill }
+ if fieldoffset>curroffset then
+ for i:=1 to fieldoffset-curroffset do
+ hr.list.concat(Tai_const.Create_8bit(0));
+
+ { new position }
+ curroffset:=fieldoffset+vardef.size;
+
+ { read the data }
+ hr.offset:=startoffset+fieldoffset;
+ read_typed_const_data(hr,vardef);
+
+ if not try_to_consume(_SEMICOLON) then
+ break;
+ end;
+ end;
+ if not(m_fpc in current_settings.modeswitches) and
+ (oo_has_vmt in def.objectoptions) and
+ (def.vmt_offset>=curroffset) then
+ begin
+ for i:=1 to def.vmt_offset-curroffset do
+ hr.list.concat(tai_const.create_8bit(0));
+ hr.list.concat(tai_const.createname(def.vmt_mangledname,0));
+ { this is more general }
+ curroffset:=def.vmt_offset + sizeof(pint);
+ end;
+ for i:=1 to def.size-curroffset do
+ hr.list.concat(Tai_const.Create_8bit(0));
+ consume(_RKLAMMER);
+ end;
+
+ procedure read_typed_const_data(var hr:threc;def:tdef);
+ var
+ old_block_type : tblock_type;
+ begin
+ old_block_type:=block_type;
+ block_type:=bt_const;
+ case def.typ of
+ orddef :
+ parse_orddef(hr.list,torddef(def));
+ floatdef :
+ parse_floatdef(hr.list,tfloatdef(def));
+ classrefdef :
+ parse_classrefdef(hr.list,tclassrefdef(def));
+ pointerdef :
+ parse_pointerdef(hr.list,tpointerdef(def));
+ setdef :
+ parse_setdef(hr.list,tsetdef(def));
+ enumdef :
+ parse_enumdef(hr.list,tenumdef(def));
+ stringdef :
+ parse_stringdef(hr,tstringdef(def));
+ arraydef :
+ parse_arraydef(hr,tarraydef(def));
+ procvardef:
+ parse_procvardef(hr.list,tprocvardef(def));
+ recorddef:
+ parse_recorddef(hr,trecorddef(def));
+ objectdef:
+ parse_objectdef(hr,tobjectdef(def));
+ errordef:
+ begin
+ { try to consume something useful }
+ if token=_LKLAMMER then
+ consume_all_until(_RKLAMMER)
+ else
+ consume_all_until(_SEMICOLON);
+ end;
+ else
+ Message(parser_e_type_const_not_possible);
+ end;
+ block_type:=old_block_type;
+ end;
+
+{$maxfpuregisters default}
+
+ procedure read_typed_const(list:tasmlist;sym:tstaticvarsym;in_structure:boolean);
+ var
+ storefilepos : tfileposinfo;
+ cursectype : TAsmSectionType;
+ hrec : threc;
+ section : ansistring;
+ begin
+ { mark the staticvarsym as typedconst }
+ include(sym.varoptions,vo_is_typed_const);
+ { The variable has a value assigned }
+ sym.varstate:=vs_initialised;
+ { the variable can't be placed in a register }
+ sym.varregable:=vr_none;
+
+ { generate data for typed const }
+ storefilepos:=current_filepos;
+ current_filepos:=sym.fileinfo;
+ if sym.varspez=vs_const then
+ cursectype:=sec_rodata
+ else
+ cursectype:=sec_data;
+ maybe_new_object_file(list);
+ hrec.list:=tasmlist.create;
+ hrec.origsym:=sym;
+ hrec.offset:=0;
+ hrec.origblock:=block_type;
+ read_typed_const_data(hrec,sym.vardef);
+
+ { Parse hints }
+ try_consume_hintdirective(sym.symoptions,sym.deprecatedmsg);
+
+ consume(_SEMICOLON);
+
+ { parse public/external/export/... }
+ if not in_structure and
+ (
+ (
+ (token = _ID) and
+ (idtoken in [_EXPORT,_EXTERNAL,_WEAKEXTERNAL,_PUBLIC,_CVAR]) and
+ (m_cvar_support in current_settings.modeswitches)
+ ) or
+ (
+ (m_mac in current_settings.modeswitches) and
+ (
+ (cs_external_var in current_settings.localswitches) or
+ (cs_externally_visible in current_settings.localswitches)
+ )
+ )
+ ) then
+ read_public_and_external(sym);
+
+ { try to parse a section directive }
+ if not in_structure and (target_info.system in systems_allow_section) and
+ (symtablestack.top.symtabletype in [staticsymtable,globalsymtable]) and
+ (idtoken=_SECTION) then
+ begin
+ try_consume_sectiondirective(section);
+ if section<>'' then
+ begin
+ if (sym.varoptions *[vo_is_external,vo_is_weak_external])<>[] then
+ Message(parser_e_externals_no_section);
+ if sym.typ<>staticvarsym then
+ Message(parser_e_section_no_locals);
+ tstaticvarsym(sym).section:=section;
+ include(sym.varoptions, vo_has_section);
+ end;
+ end;
+
+ { only now add items based on the symbolname, because it may }
+ { have been modified by the directives parsed above }
+ if vo_has_section in sym.varoptions then
+ new_section(list,sec_user,sym.section,const_align(sym.vardef.alignment))
+ else
+ new_section(list,cursectype,lower(sym.mangledname),const_align(sym.vardef.alignment));
+ if (sym.owner.symtabletype=globalsymtable) or
+ create_smartlink or
+ (assigned(current_procinfo) and
+ (po_inline in current_procinfo.procdef.procoptions)) or
+ DLLSource then
+ list.concat(Tai_symbol.Createname_global(sym.mangledname,AT_DATA,0))
+ else
+ list.concat(Tai_symbol.Createname(sym.mangledname,AT_DATA,0));
+
+ { add the parsed value }
+ list.concatlist(hrec.list);
+ hrec.list.free;
+ list.concat(tai_symbol_end.Createname(sym.mangledname));
+ current_filepos:=storefilepos;
+ end;
+
+end.
diff --git a/closures/compiler/ptype.pas b/closures/compiler/ptype.pas
new file mode 100644
index 0000000000..ab5fc03d2e
--- /dev/null
+++ b/closures/compiler/ptype.pas
@@ -0,0 +1,1590 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Does parsing types for Free Pascal
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit ptype;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ globtype,cclasses,
+ symtype,symdef,symbase;
+
+ type
+ TSingleTypeOption=(
+ stoIsForwardDef, { foward declaration }
+ stoAllowTypeDef, { allow type definitions }
+ stoAllowSpecialization, { allow type specialization }
+ stoParseClassParent { parse of parent class type }
+ );
+ TSingleTypeOptions=set of TSingleTypeOption;
+
+ procedure resolve_forward_types;
+
+ { reads a string, file type or a type identifier }
+ procedure single_type(var def:tdef;options:TSingleTypeOptions);
+
+ { reads any type declaration, where the resulting type will get name as type identifier }
+ procedure read_named_type(var def:tdef;const name : TIDString;genericdef:tstoreddef;genericlist:TFPObjectList;parseprocvardir:boolean);
+
+ { reads any type declaration }
+ procedure read_anon_type(var def : tdef;parseprocvardir:boolean);
+
+ { generate persistent type information like VMT, RTTI and inittables }
+ procedure write_persistent_type_info(st:tsymtable);
+
+implementation
+
+ uses
+ { common }
+ cutils,
+ { global }
+ globals,tokens,verbose,constexp,
+ systems,
+ { target }
+ paramgr,procinfo,
+ { symtable }
+ symconst,symsym,symtable,
+ defutil,defcmp,
+ { modules }
+ fmodule,
+ { pass 1 }
+ node,ncgrtti,nobj,
+ nmat,nadd,ncal,nset,ncnv,ninl,ncon,nld,nflw,
+ { parser }
+ scanner,
+ pbase,pexpr,pdecsub,pdecvar,pdecobj,pdecl,pgenutil;
+
+
+ procedure resolve_forward_types;
+ var
+ i: longint;
+ hpd,
+ def : tdef;
+ srsym : tsym;
+ srsymtable : TSymtable;
+ hs : string;
+ begin
+ for i:=0 to current_module.checkforwarddefs.Count-1 do
+ begin
+ def:=tdef(current_module.checkforwarddefs[i]);
+ case def.typ of
+ pointerdef,
+ classrefdef :
+ begin
+ { classrefdef inherits from pointerdef }
+ hpd:=tabstractpointerdef(def).pointeddef;
+ { still a forward def ? }
+ if hpd.typ=forwarddef then
+ begin
+ { try to resolve the forward }
+ if not assigned(tforwarddef(hpd).tosymname) then
+ internalerror(200211201);
+ hs:=tforwarddef(hpd).tosymname^;
+ searchsym(upper(hs),srsym,srsymtable);
+ { we don't need the forwarddef anymore, dispose it }
+ hpd.free;
+ tabstractpointerdef(def).pointeddef:=nil; { if error occurs }
+ { was a type sym found ? }
+ if assigned(srsym) and
+ (srsym.typ=typesym) then
+ begin
+ tabstractpointerdef(def).pointeddef:=ttypesym(srsym).typedef;
+ { avoid wrong unused warnings web bug 801 PM }
+ inc(ttypesym(srsym).refs);
+ { we need a class type for classrefdef }
+ if (def.typ=classrefdef) and
+ not(is_class(ttypesym(srsym).typedef)) and
+ not(is_objcclass(ttypesym(srsym).typedef)) then
+ MessagePos1(def.typesym.fileinfo,type_e_class_type_expected,ttypesym(srsym).typedef.typename);
+ end
+ else
+ begin
+ Message1(sym_e_forward_type_not_resolved,hs);
+ { try to recover }
+ tabstractpointerdef(def).pointeddef:=generrordef;
+ end;
+ end;
+ end;
+ objectdef :
+ begin
+ { give an error as the implementation may follow in an
+ other type block which is allowed by FPC modes }
+ if not(m_fpc in current_settings.modeswitches) and
+ (oo_is_forward in tobjectdef(def).objectoptions) then
+ MessagePos1(def.typesym.fileinfo,type_e_type_is_not_completly_defined,def.typename);
+ end;
+ else
+ internalerror(200811071);
+ end;
+ end;
+ current_module.checkforwarddefs.clear;
+ end;
+
+
+ procedure id_type(var def : tdef;isforwarddef,checkcurrentrecdef,allowgenericsyms:boolean;out srsym:tsym;out srsymtable:tsymtable); forward;
+
+
+ { def is the outermost type in which other types have to be searched
+
+ isforward indicates whether the current definition can be a forward definition
+
+ if assigned, currentstructstack is a list of tabstractrecorddefs that, from
+ last to first, are child types of def that are not yet visible via the
+ normal symtable searching routines because they are types that are currently
+ being parsed (so using id_type on them after pushing def on the
+ symtablestack would result in errors because they'd come back as errordef)
+ }
+ procedure parse_nested_types(var def: tdef; isforwarddef: boolean; currentstructstack: tfpobjectlist);
+ var
+ t2: tdef;
+ structstackindex: longint;
+ srsym: tsym;
+ srsymtable: tsymtable;
+ begin
+ if assigned(currentstructstack) then
+ structstackindex:=currentstructstack.count-1
+ else
+ structstackindex:=-1;
+ { handle types inside classes, e.g. TNode.TLongint }
+ while (token=_POINT) do
+ begin
+ if is_class_or_object(def) or is_record(def) then
+ begin
+ consume(_POINT);
+ if (structstackindex>=0) and
+ (tabstractrecorddef(currentstructstack[structstackindex]).objname^=pattern) then
+ begin
+ def:=tdef(currentstructstack[structstackindex]);
+ dec(structstackindex);
+ consume(_ID);
+ end
+ else
+ begin
+ structstackindex:=-1;
+ symtablestack.push(tabstractrecorddef(def).symtable);
+ t2:=generrordef;
+ id_type(t2,isforwarddef,false,false,srsym,srsymtable);
+ symtablestack.pop(tabstractrecorddef(def).symtable);
+ def:=t2;
+ end;
+ end
+ else
+ break;
+ end;
+ end;
+
+
+ function try_parse_structdef_nested_type(out def: tdef; basedef: tabstractrecorddef; isfowarddef: boolean): boolean;
+ var
+ structdef : tdef;
+ structdefstack : tfpobjectlist;
+ begin
+ def:=nil;
+ { use of current parsed object:
+ classes, objects, records can be used also in themself }
+ structdef:=basedef;
+ structdefstack:=nil;
+ while assigned(structdef) and (structdef.typ in [objectdef,recorddef]) do
+ begin
+ if (tabstractrecorddef(structdef).objname^=pattern) then
+ begin
+ consume(_ID);
+ def:=structdef;
+ { we found the top-most match, now check how far down we can
+ follow }
+ structdefstack:=tfpobjectlist.create(false);
+ structdef:=basedef;
+ while (structdef<>def) do
+ begin
+ structdefstack.add(structdef);
+ structdef:=tabstractrecorddef(structdef.owner.defowner);
+ end;
+ parse_nested_types(def,isfowarddef,structdefstack);
+ structdefstack.free;
+ result:=true;
+ exit;
+ end;
+ structdef:=tdef(tabstractrecorddef(structdef).owner.defowner);
+ end;
+ result:=false;
+ end;
+
+ procedure id_type(var def : tdef;isforwarddef,checkcurrentrecdef,allowgenericsyms:boolean;out srsym:tsym;out srsymtable:tsymtable);
+ { reads a type definition }
+ { to a appropriating tdef, s gets the name of }
+ { the type to allow name mangling }
+ var
+ is_unit_specific : boolean;
+ pos : tfileposinfo;
+ s,sorg : TIDString;
+ t : ttoken;
+ begin
+ srsym:=nil;
+ srsymtable:=nil;
+ s:=pattern;
+ sorg:=orgpattern;
+ pos:=current_tokenpos;
+ { use of current parsed object:
+ classes, objects, records can be used also in themself }
+ if checkcurrentrecdef and
+ try_parse_structdef_nested_type(def,current_structdef,isforwarddef) then
+ exit;
+ { Use the special searchsym_type that search only types }
+ searchsym_type(s,srsym,srsymtable);
+ { handle unit specification like System.Writeln }
+ is_unit_specific:=try_consume_unitsym(srsym,srsymtable,t,true);
+ consume(t);
+ { Types are first defined with an error def before assigning
+ the real type so check if it's an errordef. if so then
+ give an error. Only check for typesyms in the current symbol
+ table as forwarddef are not resolved directly }
+ if assigned(srsym) and
+ (srsym.typ=typesym) and
+ ((ttypesym(srsym).typedef.typ=errordef) or
+ (not allowgenericsyms and
+ (ttypesym(srsym).typedef.typ=undefineddef) and
+ not (sp_generic_para in srsym.symoptions))) then
+ begin
+ Message1(type_e_type_is_not_completly_defined,ttypesym(srsym).realname);
+ def:=generrordef;
+ exit;
+ end;
+ { are we parsing a possible forward def ? }
+ if isforwarddef and
+ not(is_unit_specific) then
+ begin
+ def:=tforwarddef.create(sorg,pos);
+ exit;
+ end;
+ { unknown sym ? }
+ if not assigned(srsym) then
+ begin
+ Message1(sym_e_id_not_found,sorg);
+ def:=generrordef;
+ exit;
+ end;
+ { type sym ? }
+ if (srsym.typ<>typesym) then
+ begin
+ Message(type_e_type_id_expected);
+ def:=generrordef;
+ exit;
+ end;
+ { Give an error when referring to an errordef }
+ if (ttypesym(srsym).typedef.typ=errordef) then
+ begin
+ Message(sym_e_error_in_type_def);
+ def:=generrordef;
+ exit;
+ end;
+ def:=ttypesym(srsym).typedef;
+ end;
+
+
+ procedure single_type(var def:tdef;options:TSingleTypeOptions);
+ var
+ t2 : tdef;
+ dospecialize,
+ again : boolean;
+ srsym : tsym;
+ srsymtable : tsymtable;
+ begin
+ dospecialize:=false;
+ repeat
+ again:=false;
+ case token of
+ _STRING:
+ string_dec(def,stoAllowTypeDef in options);
+
+ _FILE:
+ begin
+ consume(_FILE);
+ if (token=_OF) then
+ begin
+ if not(stoAllowTypeDef in options) then
+ Message(parser_e_no_local_para_def);
+ consume(_OF);
+ single_type(t2,[stoAllowTypeDef]);
+ if is_managed_type(t2) then
+ Message(parser_e_no_refcounted_typed_file);
+ def:=tfiledef.createtyped(t2);
+ end
+ else
+ def:=cfiletype;
+ end;
+
+ _ID:
+ begin
+ if try_to_consume(_SPECIALIZE) then
+ begin
+ if ([stoAllowSpecialization,stoAllowTypeDef] * options = []) then
+ begin
+ Message(parser_e_no_local_para_def);
+
+ { try to recover }
+ while token<>_SEMICOLON do
+ consume(token);
+ def:=generrordef;
+ end
+ else
+ begin
+ dospecialize:=true;
+ again:=true;
+ end;
+ end
+ else
+ begin
+ id_type(def,stoIsForwardDef in options,true,true,srsym,srsymtable);
+ parse_nested_types(def,stoIsForwardDef in options,nil);
+ end;
+ end;
+
+ else
+ begin
+ message(type_e_type_id_expected);
+ def:=generrordef;
+ end;
+ end;
+ until not again;
+ if ([stoAllowSpecialization,stoAllowTypeDef] * options <> []) and
+ (m_delphi in current_settings.modeswitches) then
+ dospecialize:=token in [_LSHARPBRACKET,_LT];
+ if dospecialize then
+ generate_specialization(def,stoParseClassParent in options,'',nil,'')
+ else
+ begin
+ if assigned(current_specializedef) and (def=current_specializedef.genericdef) then
+ begin
+ def:=current_specializedef
+ end
+ else if (def=current_genericdef) then
+ begin
+ def:=current_genericdef
+ end
+ else if (df_generic in def.defoptions) and
+ not
+ (
+ parse_generic and
+ (current_genericdef.typ in [recorddef,objectdef]) and
+ sym_is_owned_by(srsym,tabstractrecorddef(current_genericdef).symtable)
+ )
+ then
+ begin
+ Message(parser_e_no_generics_as_types);
+ def:=generrordef;
+ end
+ else if is_classhelper(def) and
+ not (stoParseClassParent in options) then
+ begin
+ Message(parser_e_no_category_as_types);
+ def:=generrordef
+ end
+ end;
+ end;
+
+ procedure parse_record_members;
+
+ procedure maybe_parse_hint_directives(pd:tprocdef);
+ var
+ dummysymoptions : tsymoptions;
+ deprecatedmsg : pshortstring;
+ begin
+ dummysymoptions:=[];
+ deprecatedmsg:=nil;
+ while try_consume_hintdirective(dummysymoptions,deprecatedmsg) do
+ Consume(_SEMICOLON);
+ if assigned(pd) then
+ begin
+ pd.symoptions:=pd.symoptions+dummysymoptions;
+ pd.deprecatedmsg:=deprecatedmsg;
+ end
+ else
+ stringdispose(deprecatedmsg);
+ end;
+
+ var
+ pd : tprocdef;
+ oldparse_only: boolean;
+ member_blocktype : tblock_type;
+ fields_allowed, is_classdef, classfields: boolean;
+ vdoptions: tvar_dec_options;
+ begin
+ { empty record declaration ? }
+ if (token=_SEMICOLON) then
+ Exit;
+
+ current_structdef.symtable.currentvisibility:=vis_public;
+ fields_allowed:=true;
+ is_classdef:=false;
+ classfields:=false;
+ member_blocktype:=bt_general;
+ repeat
+ case token of
+ _TYPE :
+ begin
+ consume(_TYPE);
+ member_blocktype:=bt_type;
+
+ { local and anonymous records can not have inner types. skip top record symtable }
+ if (current_structdef.objname^='') or
+ not(symtablestack.stack^.next^.symtable.symtabletype in [globalsymtable,staticsymtable,objectsymtable,recordsymtable]) then
+ Message(parser_e_no_types_in_local_anonymous_records);
+ end;
+ _VAR :
+ begin
+ consume(_VAR);
+ fields_allowed:=true;
+ member_blocktype:=bt_general;
+ classfields:=is_classdef;
+ is_classdef:=false;
+ end;
+ _CONST:
+ begin
+ consume(_CONST);
+ member_blocktype:=bt_const;
+ end;
+ _ID, _CASE, _OPERATOR :
+ begin
+ case idtoken of
+ _PRIVATE :
+ begin
+ consume(_PRIVATE);
+ current_structdef.symtable.currentvisibility:=vis_private;
+ include(current_structdef.objectoptions,oo_has_private);
+ fields_allowed:=true;
+ is_classdef:=false;
+ classfields:=false;
+ member_blocktype:=bt_general;
+ end;
+ _PROTECTED :
+ begin
+ consume(_PROTECTED);
+ current_structdef.symtable.currentvisibility:=vis_protected;
+ include(current_structdef.objectoptions,oo_has_protected);
+ fields_allowed:=true;
+ is_classdef:=false;
+ classfields:=false;
+ member_blocktype:=bt_general;
+ end;
+ _PUBLIC :
+ begin
+ consume(_PUBLIC);
+ current_structdef.symtable.currentvisibility:=vis_public;
+ fields_allowed:=true;
+ is_classdef:=false;
+ classfields:=false;
+ member_blocktype:=bt_general;
+ end;
+ _PUBLISHED :
+ begin
+ Message(parser_e_no_record_published);
+ consume(_PUBLISHED);
+ current_structdef.symtable.currentvisibility:=vis_published;
+ fields_allowed:=true;
+ is_classdef:=false;
+ classfields:=false;
+ member_blocktype:=bt_general;
+ end;
+ _STRICT :
+ begin
+ consume(_STRICT);
+ if token=_ID then
+ begin
+ case idtoken of
+ _PRIVATE:
+ begin
+ consume(_PRIVATE);
+ current_structdef.symtable.currentvisibility:=vis_strictprivate;
+ include(current_structdef.objectoptions,oo_has_strictprivate);
+ end;
+ _PROTECTED:
+ begin
+ consume(_PROTECTED);
+ current_structdef.symtable.currentvisibility:=vis_strictprotected;
+ include(current_structdef.objectoptions,oo_has_strictprotected);
+ end;
+ else
+ message(parser_e_protected_or_private_expected);
+ end;
+ end
+ else
+ message(parser_e_protected_or_private_expected);
+ fields_allowed:=true;
+ is_classdef:=false;
+ classfields:=false;
+ member_blocktype:=bt_general;
+ end
+ else
+ if is_classdef and (idtoken=_OPERATOR) then
+ begin
+ oldparse_only:=parse_only;
+ parse_only:=true;
+ pd:=parse_proc_dec(is_classdef,current_structdef);
+
+ { this is for error recovery as well as forward }
+ { interface mappings, i.e. mapping to a method }
+ { which isn't declared yet }
+ if assigned(pd) then
+ begin
+ parse_record_proc_directives(pd);
+
+ handle_calling_convention(pd);
+
+ { add definition to procsym }
+ proc_add_definition(pd);
+ end;
+
+ maybe_parse_hint_directives(pd);
+
+ parse_only:=oldparse_only;
+ fields_allowed:=false;
+ is_classdef:=false;
+ end
+ else
+ begin
+ if member_blocktype=bt_general then
+ begin
+ if (not fields_allowed)and(idtoken<>_CASE) then
+ Message(parser_e_field_not_allowed_here);
+ vdoptions:=[vd_record];
+ if classfields then
+ include(vdoptions,vd_class);
+ read_record_fields(vdoptions);
+ end
+ else if member_blocktype=bt_type then
+ types_dec(true)
+ else if member_blocktype=bt_const then
+ consts_dec(true)
+ else
+ internalerror(201001110);
+ end;
+ end;
+ end;
+ _PROPERTY :
+ begin
+ struct_property_dec(is_classdef);
+ fields_allowed:=false;
+ is_classdef:=false;
+ end;
+ _CLASS:
+ begin
+ is_classdef:=false;
+ { read class method/field/property }
+ consume(_CLASS);
+ { class modifier is only allowed for procedures, functions, }
+ { constructors, destructors, fields and properties }
+ if not(token in [_FUNCTION,_PROCEDURE,_PROPERTY,_VAR,_CONSTRUCTOR,_DESTRUCTOR,_OPERATOR]) and
+ not((token=_ID) and (idtoken=_OPERATOR)) then
+ Message(parser_e_procedure_or_function_expected);
+
+ is_classdef:=true;
+ end;
+ _PROCEDURE,
+ _FUNCTION:
+ begin
+ oldparse_only:=parse_only;
+ parse_only:=true;
+ pd:=parse_proc_dec(is_classdef,current_structdef);
+
+ { this is for error recovery as well as forward }
+ { interface mappings, i.e. mapping to a method }
+ { which isn't declared yet }
+ if assigned(pd) then
+ begin
+ parse_record_proc_directives(pd);
+
+ { since records have no inheritance don't allow non static
+ class methods. delphi do so. }
+ if is_classdef and not (po_staticmethod in pd.procoptions) then
+ MessagePos(pd.fileinfo, parser_e_class_methods_only_static_in_records);
+
+ handle_calling_convention(pd);
+
+ { add definition to procsym }
+ proc_add_definition(pd);
+ end;
+
+ maybe_parse_hint_directives(pd);
+
+ parse_only:=oldparse_only;
+ fields_allowed:=false;
+ is_classdef:=false;
+ end;
+ _CONSTRUCTOR :
+ begin
+ if not is_classdef then
+ Message(parser_e_no_constructor_in_records);
+ if not is_classdef and (current_structdef.symtable.currentvisibility <> vis_public) then
+ Message(parser_w_constructor_should_be_public);
+
+ { only 1 class constructor is allowed }
+ if is_classdef and (oo_has_class_constructor in current_structdef.objectoptions) then
+ Message1(parser_e_only_one_class_constructor_allowed, current_structdef.objrealname^);
+
+ oldparse_only:=parse_only;
+ parse_only:=true;
+ if is_classdef then
+ pd:=class_constructor_head
+ else
+ pd:=constructor_head;
+ parse_record_proc_directives(pd);
+ handle_calling_convention(pd);
+
+ { add definition to procsym }
+ proc_add_definition(pd);
+
+ maybe_parse_hint_directives(pd);
+
+ parse_only:=oldparse_only;
+ fields_allowed:=false;
+ is_classdef:=false;
+ end;
+ _DESTRUCTOR :
+ begin
+ if not is_classdef then
+ Message(parser_e_no_destructor_in_records);
+
+ { only 1 class destructor is allowed }
+ if is_classdef and (oo_has_class_destructor in current_structdef.objectoptions) then
+ Message1(parser_e_only_one_class_destructor_allowed, current_structdef.objrealname^);
+
+ oldparse_only:=parse_only;
+ parse_only:=true;
+ if is_classdef then
+ pd:=class_destructor_head
+ else
+ pd:=destructor_head;
+ parse_record_proc_directives(pd);
+ handle_calling_convention(pd);
+
+ { add definition to procsym }
+ proc_add_definition(pd);
+
+ maybe_parse_hint_directives(pd);
+
+ parse_only:=oldparse_only;
+ fields_allowed:=false;
+ is_classdef:=false;
+ end;
+ _END :
+ begin
+ consume(_END);
+ break;
+ end;
+ else
+ consume(_ID); { Give a ident expected message, like tp7 }
+ end;
+ until false;
+ end;
+
+ { reads a record declaration }
+ function record_dec(const n:tidstring;genericdef:tstoreddef;genericlist:TFPObjectList):tdef;
+ var
+ old_current_structdef: tabstractrecorddef;
+ old_current_genericdef,
+ old_current_specializedef: tstoreddef;
+ old_parse_generic: boolean;
+ recst: trecordsymtable;
+ begin
+ old_current_structdef:=current_structdef;
+ old_current_genericdef:=current_genericdef;
+ old_current_specializedef:=current_specializedef;
+ old_parse_generic:=parse_generic;
+
+ current_genericdef:=nil;
+ current_specializedef:=nil;
+ { create recdef }
+ recst:=trecordsymtable.create(n,current_settings.packrecords);
+ current_structdef:=trecorddef.create(n,recst);
+ result:=current_structdef;
+ { insert in symtablestack }
+ symtablestack.push(recst);
+
+ { usage of specialized type inside its generic template }
+ if assigned(genericdef) then
+ current_specializedef:=current_structdef
+ { reject declaration of generic class inside generic class }
+ else if assigned(genericlist) then
+ current_genericdef:=current_structdef;
+
+ { nested types of specializations are specializations as well }
+ if assigned(old_current_structdef) and
+ (df_specialization in old_current_structdef.defoptions) then
+ include(current_structdef.defoptions,df_specialization);
+
+ insert_generic_parameter_types(current_structdef,genericdef,genericlist);
+ { when we are parsing a generic already then this is a generic as
+ well }
+ if old_parse_generic then
+ include(current_structdef.defoptions, df_generic);
+ parse_generic:=(df_generic in current_structdef.defoptions);
+ if m_advanced_records in current_settings.modeswitches then
+ parse_record_members
+ else
+ begin
+ read_record_fields([vd_record]);
+ consume(_END);
+ end;
+ { make the record size aligned }
+ recst.addalignmentpadding;
+ { restore symtable stack }
+ symtablestack.pop(recst);
+ if trecorddef(current_structdef).is_packed and is_managed_type(current_structdef) then
+ Message(type_e_no_packed_inittable);
+ { restore old state }
+ parse_generic:=old_parse_generic;
+ current_structdef:=old_current_structdef;
+ current_genericdef:=old_current_genericdef;
+ current_specializedef:=old_current_specializedef;
+ end;
+
+
+ { reads a type definition and returns a pointer to it }
+ procedure read_named_type(var def : tdef;const name : TIDString;genericdef:tstoreddef;genericlist:TFPObjectList;parseprocvardir:boolean);
+ var
+ pt : tnode;
+ tt2 : tdef;
+ aktenumdef : tenumdef;
+ s : TIDString;
+ l,v : TConstExprInt;
+ oldpackrecords : longint;
+ defpos,storepos : tfileposinfo;
+
+ procedure expr_type;
+ var
+ pt1,pt2 : tnode;
+ lv,hv : TConstExprInt;
+ old_block_type : tblock_type;
+ dospecialize : boolean;
+ begin
+ old_block_type:=block_type;
+ dospecialize:=false;
+ { use of current parsed object:
+ classes, objects, records can be used also in themself }
+ if (token=_ID) then
+ if try_parse_structdef_nested_type(def,current_structdef,false) then
+ exit;
+ { Generate a specialization in FPC mode? }
+ dospecialize:=not(m_delphi in current_settings.modeswitches) and try_to_consume(_SPECIALIZE);
+ { we can't accept a equal in type }
+ pt1:=comp_expr(false,true);
+ if not dospecialize and
+ try_to_consume(_POINTPOINT) then
+ begin
+ { get high value of range }
+ pt2:=comp_expr(false,false);
+ { make both the same type or give an error. This is not
+ done when both are integer values, because typecasting
+ between -3200..3200 will result in a signed-unsigned
+ conflict and give a range check error (PFV) }
+ if not(is_integer(pt1.resultdef) and is_integer(pt2.resultdef)) then
+ inserttypeconv(pt1,pt2.resultdef);
+ { both must be evaluated to constants now }
+ if (pt1.nodetype=ordconstn) and
+ (pt2.nodetype=ordconstn) then
+ begin
+ lv:=tordconstnode(pt1).value;
+ hv:=tordconstnode(pt2).value;
+ { Check bounds }
+ if hv<lv then
+ message(parser_e_upper_lower_than_lower)
+ else if (lv.signed and (lv.svalue<0)) and (not hv.signed and (hv.uvalue>qword(high(int64)))) then
+ message(type_e_cant_eval_constant_expr)
+ else
+ begin
+ { All checks passed, create the new def }
+ case pt1.resultdef.typ of
+ enumdef :
+ def:=tenumdef.create_subrange(tenumdef(pt1.resultdef),lv.svalue,hv.svalue);
+ orddef :
+ begin
+ if is_char(pt1.resultdef) then
+ def:=torddef.create(uchar,lv,hv)
+ else
+ if is_boolean(pt1.resultdef) then
+ def:=torddef.create(pasbool8,lv,hv)
+ else if is_signed(pt1.resultdef) then
+ def:=torddef.create(range_to_basetype(lv,hv),lv,hv)
+ else
+ def:=torddef.create(range_to_basetype(lv,hv),lv,hv);
+ end;
+ end;
+ end;
+ end
+ else
+ Message(sym_e_error_in_type_def);
+ pt2.free;
+ end
+ else
+ begin
+ { a simple type renaming or generic specialization }
+ if (pt1.nodetype=typen) then
+ begin
+ def:=ttypenode(pt1).resultdef;
+ { Delphi mode specialization? }
+ if (m_delphi in current_settings.modeswitches) then
+ dospecialize:=token=_LSHARPBRACKET
+ else
+ { in non-Delphi modes we might get a inline specialization
+ without "specialize" or "<T>" of the same type we're
+ currently parsing, so we need to handle that special }
+ if not dospecialize and
+ assigned(ttypenode(pt1).typesym) and
+ (ttypenode(pt1).typesym.typ=typesym) and
+ (sp_generic_dummy in ttypenode(pt1).typesym.symoptions) and
+ assigned(current_structdef) and
+ (
+ (
+ not (m_delphi in current_settings.modeswitches) and
+ (ttypesym(ttypenode(pt1).typesym).typedef.typ=undefineddef) and
+ (df_generic in current_structdef.defoptions) and
+ (ttypesym(ttypenode(pt1).typesym).typedef.owner=current_structdef.owner) and
+ (upper(ttypenode(pt1).typesym.realname)=copy(current_structdef.objname^,1,pos('$',current_structdef.objname^)-1))
+ ) or (
+ (df_specialization in current_structdef.defoptions) and
+ (ttypesym(ttypenode(pt1).typesym).typedef=current_structdef.genericdef)
+ )
+ )
+ then
+ begin
+ def:=current_structdef;
+ { handle nested types }
+ post_comp_expr_gendef(def);
+ end;
+ if dospecialize then
+ begin
+ generate_specialization(def,false,name,nil,'');
+ { handle nested types }
+ post_comp_expr_gendef(def);
+ end
+ else
+ begin
+ if assigned(current_specializedef) and (def=current_specializedef.genericdef) then
+ begin
+ def:=current_specializedef
+ end
+ else if (def=current_genericdef) then
+ begin
+ def:=current_genericdef
+ end
+ else if (df_generic in def.defoptions) and
+ { TODO : check once nested generics are allowed }
+ not
+ (
+ parse_generic and
+ (current_genericdef.typ in [recorddef,objectdef]) and
+ (def.typ in [recorddef,objectdef]) and
+ (ttypenode(pt1).typesym<>nil) and
+ sym_is_owned_by(ttypenode(pt1).typesym,tabstractrecorddef(current_genericdef).symtable)
+ )
+ then
+ begin
+ Message(parser_e_no_generics_as_types);
+ def:=generrordef;
+ end
+ else if is_classhelper(def) then
+ begin
+ Message(parser_e_no_category_as_types);
+ def:=generrordef
+ end
+ end;
+ end
+ else
+ Message(sym_e_error_in_type_def);
+ end;
+ pt1.free;
+ block_type:=old_block_type;
+ end;
+
+
+ procedure set_dec;
+ begin
+ consume(_SET);
+ consume(_OF);
+ read_anon_type(tt2,true);
+ if assigned(tt2) then
+ begin
+ case tt2.typ of
+ { don't forget that min can be negativ PM }
+ enumdef :
+ if (tenumdef(tt2).min>=0) and
+ (tenumdef(tt2).max<=255) then
+ // !! def:=tsetdef.create(tt2,tenumdef(tt2.def).min,tenumdef(tt2.def).max))
+ def:=tsetdef.create(tt2,tenumdef(tt2).min,tenumdef(tt2).max)
+ else
+ Message(sym_e_ill_type_decl_set);
+ orddef :
+ begin
+ if (torddef(tt2).ordtype<>uvoid) and
+ (torddef(tt2).ordtype<>uwidechar) and
+ (torddef(tt2).low>=0) then
+ // !! def:=tsetdef.create(tt2,torddef(tt2.def).low,torddef(tt2.def).high))
+ if Torddef(tt2).high>int64(high(byte)) then
+ message(sym_e_ill_type_decl_set)
+ else
+ def:=tsetdef.create(tt2,torddef(tt2).low.svalue,torddef(tt2).high.svalue)
+ else
+ Message(sym_e_ill_type_decl_set);
+ end;
+ else
+ Message(sym_e_ill_type_decl_set);
+ end;
+ end
+ else
+ def:=generrordef;
+ end;
+
+
+ procedure array_dec(is_packed:boolean;genericdef:tstoreddef;genericlist:TFPObjectList);
+ var
+ lowval,
+ highval : TConstExprInt;
+ indexdef : tdef;
+ hdef : tdef;
+ arrdef : tarraydef;
+
+ procedure setdefdecl(def:tdef);
+ begin
+ case def.typ of
+ enumdef :
+ begin
+ lowval:=tenumdef(def).min;
+ highval:=tenumdef(def).max;
+ if (m_fpc in current_settings.modeswitches) and
+ (tenumdef(def).has_jumps) then
+ Message(type_e_array_index_enums_with_assign_not_possible);
+ indexdef:=def;
+ end;
+ orddef :
+ begin
+ if torddef(def).ordtype in [uchar,
+ u8bit,u16bit,
+ s8bit,s16bit,s32bit,
+{$ifdef cpu64bitaddr}
+ u32bit,s64bit,
+{$endif cpu64bitaddr}
+ pasbool8,pasbool16,pasbool32,pasbool64,
+ bool8bit,bool16bit,bool32bit,bool64bit,
+ uwidechar] then
+ begin
+ lowval:=torddef(def).low;
+ highval:=torddef(def).high;
+ indexdef:=def;
+ end
+ else
+ Message1(parser_e_type_cant_be_used_in_array_index,def.typename);
+ end;
+ else
+ Message(sym_e_error_in_type_def);
+ end;
+ end;
+
+ var
+ old_current_genericdef,
+ old_current_specializedef: tstoreddef;
+ old_parse_generic: boolean;
+ begin
+ old_current_genericdef:=current_genericdef;
+ old_current_specializedef:=current_specializedef;
+ old_parse_generic:=parse_generic;
+
+ current_genericdef:=nil;
+ current_specializedef:=nil;
+ arrdef:=nil;
+ consume(_ARRAY);
+ { open array? }
+ if try_to_consume(_LECKKLAMMER) then
+ begin
+ { defaults }
+ indexdef:=generrordef;
+ { use defaults which don't overflow the compiler }
+ lowval:=0;
+ highval:=0;
+ repeat
+ { read the expression and check it, check apart if the
+ declaration is an enum declaration because that needs to
+ be parsed by readtype (PFV) }
+ if token=_LKLAMMER then
+ begin
+ read_anon_type(hdef,true);
+ setdefdecl(hdef);
+ end
+ else
+ begin
+ pt:=expr(true);
+ if pt.nodetype=typen then
+ setdefdecl(pt.resultdef)
+ else
+ begin
+ if pt.nodetype=rangen then
+ begin
+ { check the expression only if we are not in a generic declaration }
+ if not(parse_generic) then
+ begin
+ if (trangenode(pt).left.nodetype=ordconstn) and
+ (trangenode(pt).right.nodetype=ordconstn) then
+ begin
+ { make both the same type or give an error. This is not
+ done when both are integer values, because typecasting
+ between -3200..3200 will result in a signed-unsigned
+ conflict and give a range check error (PFV) }
+ if not(is_integer(trangenode(pt).left.resultdef) and is_integer(trangenode(pt).left.resultdef)) then
+ inserttypeconv(trangenode(pt).left,trangenode(pt).right.resultdef);
+ lowval:=tordconstnode(trangenode(pt).left).value;
+ highval:=tordconstnode(trangenode(pt).right).value;
+ if highval<lowval then
+ begin
+ Message(parser_e_array_lower_less_than_upper_bound);
+ highval:=lowval;
+ end
+ else if (lowval<int64(low(asizeint))) or
+ (highval>high(asizeint)) then
+ begin
+ Message(parser_e_array_range_out_of_bounds);
+ lowval :=0;
+ highval:=0;
+ end;
+ if is_integer(trangenode(pt).left.resultdef) then
+ range_to_type(lowval,highval,indexdef)
+ else
+ indexdef:=trangenode(pt).left.resultdef;
+ end
+ else
+ Message(type_e_cant_eval_constant_expr);
+ end;
+ end
+ else
+ Message(sym_e_error_in_type_def)
+ end;
+ pt.free;
+ end;
+
+ { if the array is already created add the new arrray
+ as element of the existing array, otherwise create a new array }
+ if assigned(arrdef) then
+ begin
+ arrdef.elementdef:=tarraydef.create(lowval.svalue,highval.svalue,indexdef);
+ arrdef:=tarraydef(arrdef.elementdef);
+ end
+ else
+ begin
+ arrdef:=tarraydef.create(lowval.svalue,highval.svalue,indexdef);
+ def:=arrdef;
+ end;
+ if is_packed then
+ include(arrdef.arrayoptions,ado_IsBitPacked);
+
+ if token=_COMMA then
+ consume(_COMMA)
+ else
+ break;
+ until false;
+ consume(_RECKKLAMMER);
+ end
+ else
+ begin
+ if is_packed then
+ Message(parser_e_packed_dynamic_open_array);
+ arrdef:=tarraydef.create(0,-1,s32inttype);
+ include(arrdef.arrayoptions,ado_IsDynamicArray);
+ def:=arrdef;
+ end;
+ if assigned(arrdef) then
+ begin
+ { usage of specialized type inside its generic template }
+ if assigned(genericdef) then
+ current_specializedef:=arrdef
+ { reject declaration of generic class inside generic class }
+ else if assigned(genericlist) then
+ current_genericdef:=arrdef;
+ symtablestack.push(arrdef.symtable);
+ insert_generic_parameter_types(arrdef,genericdef,genericlist);
+ { there are two possibilties for the following to be true:
+ * the array declaration itself is generic
+ * the array is declared inside a generic
+ in both cases we need "parse_generic" and "current_genericdef"
+ so that e.g. specializations of another generic inside the
+ current generic can be used (either inline ones or "type" ones) }
+ parse_generic:=(df_generic in arrdef.defoptions) or old_parse_generic;
+ if parse_generic and not assigned(current_genericdef) then
+ current_genericdef:=old_current_genericdef;
+ end;
+ consume(_OF);
+ read_anon_type(tt2,true);
+ { set element type of the last array definition }
+ if assigned(arrdef) then
+ begin
+ symtablestack.pop(arrdef.symtable);
+ arrdef.elementdef:=tt2;
+ if is_packed and
+ is_managed_type(tt2) then
+ Message(type_e_no_packed_inittable);
+ end;
+ { restore old state }
+ parse_generic:=old_parse_generic;
+ current_genericdef:=old_current_genericdef;
+ current_specializedef:=old_current_specializedef;
+ end;
+
+ function procvar_dec(genericdef:tstoreddef;genericlist:TFPObjectList):tdef;
+ var
+ is_func:boolean;
+ pd:tabstractprocdef;
+ newtype:ttypesym;
+ old_current_genericdef,
+ old_current_specializedef: tstoreddef;
+ old_parse_generic: boolean;
+ begin
+ old_current_genericdef:=current_genericdef;
+ old_current_specializedef:=current_specializedef;
+ old_parse_generic:=parse_generic;
+
+ current_genericdef:=nil;
+ current_specializedef:=nil;
+
+ is_func:=(token=_FUNCTION);
+ consume(token);
+ pd:=tprocvardef.create(normal_function_level);
+
+ { usage of specialized type inside its generic template }
+ if assigned(genericdef) then
+ current_specializedef:=pd
+ { reject declaration of generic class inside generic class }
+ else if assigned(genericlist) then
+ current_genericdef:=pd;
+ symtablestack.push(pd.parast);
+ insert_generic_parameter_types(pd,genericdef,genericlist);
+ { there are two possibilties for the following to be true:
+ * the procvar declaration itself is generic
+ * the procvar is declared inside a generic
+ in both cases we need "parse_generic" and "current_genericdef"
+ so that e.g. specializations of another generic inside the
+ current generic can be used (either inline ones or "type" ones) }
+ parse_generic:=(df_generic in pd.defoptions) or old_parse_generic;
+ if parse_generic and not assigned(current_genericdef) then
+ current_genericdef:=old_current_genericdef;
+ { don't allow to add defs to the symtable - use it for type param search only }
+ tparasymtable(pd.parast).readonly:=true;
+
+ if token=_LKLAMMER then
+ parse_parameter_dec(pd);
+ if is_func then
+ begin
+ consume(_COLON);
+ single_type(pd.returndef,[]);
+ end;
+ if try_to_consume(_OF) then
+ begin
+ consume(_OBJECT);
+ include(pd.procoptions,po_methodpointer);
+ end
+ else if (m_nested_procvars in current_settings.modeswitches) and
+ try_to_consume(_IS) then
+ begin
+ consume(_NESTED);
+ pd.parast.symtablelevel:=normal_function_level+1;
+ pd.check_mark_as_nested;
+ end;
+ symtablestack.pop(pd.parast);
+ tparasymtable(pd.parast).readonly:=false;
+ result:=pd;
+ { possible proc directives }
+ if parseprocvardir then
+ begin
+ if check_proc_directive(true) then
+ begin
+ newtype:=ttypesym.create('unnamed',result);
+ parse_var_proc_directives(tsym(newtype));
+ newtype.typedef:=nil;
+ result.typesym:=nil;
+ newtype.free;
+ end;
+ { Add implicit hidden parameters and function result }
+ handle_calling_convention(pd);
+ end;
+ { restore old state }
+ parse_generic:=old_parse_generic;
+ current_genericdef:=old_current_genericdef;
+ current_specializedef:=old_current_specializedef;
+ end;
+
+ const
+ SingleTypeOptionsInTypeBlock:array[Boolean] of TSingleTypeOptions = ([],[stoIsForwardDef]);
+ var
+ p : tnode;
+ hdef : tdef;
+ enumdupmsg, first, is_specialize : boolean;
+ oldlocalswitches : tlocalswitches;
+ bitpacking: boolean;
+ stitem: psymtablestackitem;
+ sym: tsym;
+ st: tsymtable;
+ begin
+ def:=nil;
+ case token of
+ _STRING,_FILE:
+ begin
+ single_type(def,[stoAllowTypeDef]);
+ end;
+ _LKLAMMER:
+ begin
+ consume(_LKLAMMER);
+ first:=true;
+ { allow negativ value_str }
+ l:=int64(-1);
+ enumdupmsg:=false;
+ { check that we are not adding an enum from specialization
+ we can't just use current_specializedef because of inner types
+ like specialize array of record }
+ is_specialize:=false;
+ stitem:=symtablestack.stack;
+ while assigned(stitem) do
+ begin
+ { check records, classes and arrays because they can be specialized }
+ if stitem^.symtable.symtabletype in [recordsymtable,ObjectSymtable,arraysymtable] then
+ begin
+ is_specialize:=is_specialize or (df_specialization in tstoreddef(stitem^.symtable.defowner).defoptions);
+ stitem:=stitem^.next;
+ end
+ else
+ break;
+ end;
+ if not is_specialize then
+ aktenumdef:=tenumdef.create
+ else
+ aktenumdef:=nil;
+ repeat
+ { if it is a specialization then search the first enum member
+ and get the member owner instead of just created enumdef }
+ if not assigned(aktenumdef) then
+ begin
+ searchsym(pattern,sym,st);
+ if sym.typ=enumsym then
+ aktenumdef:=tenumsym(sym).definition
+ else
+ internalerror(201101021);
+ end;
+ s:=orgpattern;
+ defpos:=current_tokenpos;
+ consume(_ID);
+ { only allow assigning of specific numbers under fpc mode }
+ if not(m_tp7 in current_settings.modeswitches) and
+ (
+ { in fpc mode also allow := to be compatible
+ with previous 1.0.x versions }
+ ((m_fpc in current_settings.modeswitches) and
+ try_to_consume(_ASSIGNMENT)) or
+ try_to_consume(_EQ)
+ ) then
+ begin
+ oldlocalswitches:=current_settings.localswitches;
+ include(current_settings.localswitches,cs_allow_enum_calc);
+ p:=comp_expr(true,false);
+ current_settings.localswitches:=oldlocalswitches;
+ if (p.nodetype=ordconstn) then
+ begin
+ { we expect an integer or an enum of the
+ same type }
+ if is_integer(p.resultdef) or
+ is_char(p.resultdef) or
+ equal_defs(p.resultdef,aktenumdef) then
+ v:=tordconstnode(p).value
+ else
+ IncompatibleTypes(p.resultdef,s32inttype);
+ end
+ else
+ Message(parser_e_illegal_expression);
+ p.free;
+ { please leave that a note, allows type save }
+ { declarations in the win32 units ! }
+ if (not first) and (v<=l) and (not enumdupmsg) then
+ begin
+ Message(parser_n_duplicate_enum);
+ enumdupmsg:=true;
+ end;
+ l:=v;
+ end
+ else
+ inc(l.svalue);
+ first:=false;
+ { don't generate enum members is this is a specialization because aktenumdef is copied from the generic type }
+ if not is_specialize then
+ begin
+ storepos:=current_tokenpos;
+ current_tokenpos:=defpos;
+ tenumsymtable(aktenumdef.symtable).insert(tenumsym.create(s,aktenumdef,longint(l.svalue)));
+ if not (cs_scopedenums in current_settings.localswitches) then
+ tstoredsymtable(aktenumdef.owner).insert(tenumsym.create(s,aktenumdef,longint(l.svalue)));
+ current_tokenpos:=storepos;
+ end;
+ until not try_to_consume(_COMMA);
+ def:=aktenumdef;
+ consume(_RKLAMMER);
+ end;
+ _ARRAY:
+ begin
+ array_dec(false,genericdef,genericlist);
+ end;
+ _SET:
+ begin
+ set_dec;
+ end;
+ _CARET:
+ begin
+ consume(_CARET);
+ single_type(tt2,SingleTypeOptionsInTypeBlock[block_type=bt_type]);
+ def:=tpointerdef.create(tt2);
+ if tt2.typ=forwarddef then
+ current_module.checkforwarddefs.add(def);
+ end;
+ _RECORD:
+ begin
+ consume(token);
+ if (idtoken=_HELPER) and (m_advanced_records in current_settings.modeswitches) then
+ begin
+ consume(_HELPER);
+ def:=object_dec(odt_helper,name,genericdef,genericlist,nil,ht_record);
+ end
+ else
+ def:=record_dec(name,genericdef,genericlist);
+ end;
+ _PACKED,
+ _BITPACKED:
+ begin
+ bitpacking :=
+ (cs_bitpacking in current_settings.localswitches) or
+ (token = _BITPACKED);
+ consume(token);
+ if token=_ARRAY then
+ array_dec(bitpacking,genericdef,genericlist)
+ else if token=_SET then
+ set_dec
+ else if token=_FILE then
+ single_type(def,[stoAllowTypeDef])
+ else
+ begin
+ oldpackrecords:=current_settings.packrecords;
+ if (not bitpacking) or
+ (token in [_CLASS,_OBJECT]) then
+ current_settings.packrecords:=1
+ else
+ current_settings.packrecords:=bit_alignment;
+ case token of
+ _CLASS :
+ begin
+ consume(_CLASS);
+ def:=object_dec(odt_class,name,genericdef,genericlist,nil,ht_none);
+ end;
+ _OBJECT :
+ begin
+ consume(_OBJECT);
+ def:=object_dec(odt_object,name,genericdef,genericlist,nil,ht_none);
+ end;
+ else begin
+ consume(_RECORD);
+ def:=record_dec(name,genericdef,genericlist);
+ end;
+ end;
+ current_settings.packrecords:=oldpackrecords;
+ end;
+ end;
+ _DISPINTERFACE :
+ begin
+ { need extra check here since interface is a keyword
+ in all pascal modes }
+ if not(m_class in current_settings.modeswitches) then
+ Message(parser_f_need_objfpc_or_delphi_mode);
+ consume(token);
+ def:=object_dec(odt_dispinterface,name,genericdef,genericlist,nil,ht_none);
+ end;
+ _CLASS :
+ begin
+ consume(token);
+ { Delphi only allows class of in type blocks }
+ if (token=_OF) and
+ (
+ not(m_delphi in current_settings.modeswitches) or
+ (block_type=bt_type)
+ ) then
+ begin
+ consume(_OF);
+ single_type(hdef,SingleTypeOptionsInTypeBlock[block_type=bt_type]);
+ if is_class(hdef) or
+ is_objcclass(hdef) then
+ def:=tclassrefdef.create(hdef)
+ else
+ if hdef.typ=forwarddef then
+ begin
+ def:=tclassrefdef.create(hdef);
+ current_module.checkforwarddefs.add(def);
+ end
+ else
+ Message1(type_e_class_or_objcclass_type_expected,hdef.typename);
+ end
+ else
+ if (idtoken=_HELPER) then
+ begin
+ consume(_HELPER);
+ def:=object_dec(odt_helper,name,genericdef,genericlist,nil,ht_class);
+ end
+ else
+ def:=object_dec(odt_class,name,genericdef,genericlist,nil,ht_none);
+ end;
+ _CPPCLASS :
+ begin
+ consume(token);
+ def:=object_dec(odt_cppclass,name,genericdef,genericlist,nil,ht_none);
+ end;
+ _OBJCCLASS :
+ begin
+ if not(m_objectivec1 in current_settings.modeswitches) then
+ Message(parser_f_need_objc);
+
+ consume(token);
+ def:=object_dec(odt_objcclass,name,genericdef,genericlist,nil,ht_none);
+ end;
+ _INTERFACE :
+ begin
+ { need extra check here since interface is a keyword
+ in all pascal modes }
+ if not(m_class in current_settings.modeswitches) then
+ Message(parser_f_need_objfpc_or_delphi_mode);
+ consume(token);
+ if current_settings.interfacetype=it_interfacecom then
+ def:=object_dec(odt_interfacecom,name,genericdef,genericlist,nil,ht_none)
+ else {it_interfacecorba}
+ def:=object_dec(odt_interfacecorba,name,genericdef,genericlist,nil,ht_none);
+ end;
+ _OBJCPROTOCOL :
+ begin
+ if not(m_objectivec1 in current_settings.modeswitches) then
+ Message(parser_f_need_objc);
+
+ consume(token);
+ def:=object_dec(odt_objcprotocol,name,genericdef,genericlist,nil,ht_none);
+ end;
+ _OBJCCATEGORY :
+ begin
+ if not(m_objectivec1 in current_settings.modeswitches) then
+ Message(parser_f_need_objc);
+
+ consume(token);
+ def:=object_dec(odt_objccategory,name,genericdef,genericlist,nil,ht_none);
+ end;
+ _OBJECT :
+ begin
+ consume(token);
+ def:=object_dec(odt_object,name,genericdef,genericlist,nil,ht_none);
+ end;
+ _PROCEDURE,
+ _FUNCTION:
+ begin
+ def:=procvar_dec(genericdef,genericlist);
+ end;
+ else
+ if (token=_KLAMMERAFFE) and (m_iso in current_settings.modeswitches) then
+ begin
+ consume(_KLAMMERAFFE);
+ single_type(tt2,SingleTypeOptionsInTypeBlock[block_type=bt_type]);
+ def:=tpointerdef.create(tt2);
+ if tt2.typ=forwarddef then
+ current_module.checkforwarddefs.add(def);
+ end
+ else
+ expr_type;
+ end;
+
+ if def=nil then
+ def:=generrordef;
+ end;
+
+
+ procedure read_anon_type(var def : tdef;parseprocvardir:boolean);
+ begin
+ read_named_type(def,'',nil,nil,parseprocvardir);
+ end;
+
+
+ procedure write_persistent_type_info(st:tsymtable);
+ var
+ i : longint;
+ def : tdef;
+ vmtwriter : TVMTWriter;
+ begin
+ for i:=0 to st.DefList.Count-1 do
+ begin
+ def:=tdef(st.DefList[i]);
+ case def.typ of
+ recorddef :
+ write_persistent_type_info(trecorddef(def).symtable);
+ objectdef :
+ begin
+ { Skip generics and forward defs }
+ if (df_generic in def.defoptions) or
+ (oo_is_forward in tobjectdef(def).objectoptions) then
+ continue;
+ write_persistent_type_info(tobjectdef(def).symtable);
+ { Write also VMT if not done yet }
+ if not(ds_vmt_written in def.defstates) then
+ begin
+ vmtwriter:=TVMTWriter.create(tobjectdef(def));
+ if is_interface(tobjectdef(def)) then
+ vmtwriter.writeinterfaceids;
+ if (oo_has_vmt in tobjectdef(def).objectoptions) then
+ vmtwriter.writevmt;
+ vmtwriter.free;
+ include(def.defstates,ds_vmt_written);
+ end;
+ end;
+ procdef :
+ begin
+ if assigned(tprocdef(def).localst) and
+ (tprocdef(def).localst.symtabletype=localsymtable) then
+ write_persistent_type_info(tprocdef(def).localst);
+ if assigned(tprocdef(def).parast) then
+ write_persistent_type_info(tprocdef(def).parast);
+ end;
+ end;
+ { generate always persistent tables for types in the interface so it can
+ be reused in other units and give always the same pointer location. }
+ { Init }
+ if (
+ assigned(def.typesym) and
+ (st.symtabletype=globalsymtable) and
+ not is_objc_class_or_protocol(def)
+ ) or
+ is_managed_type(def) or
+ (ds_init_table_used in def.defstates) then
+ RTTIWriter.write_rtti(def,initrtti);
+ { RTTI }
+ if (
+ assigned(def.typesym) and
+ (st.symtabletype=globalsymtable) and
+ not is_objc_class_or_protocol(def)
+ ) or
+ (ds_rtti_table_used in def.defstates) then
+ RTTIWriter.write_rtti(def,fullrtti);
+ end;
+ end;
+
+end.
diff --git a/closures/compiler/raatt.pas b/closures/compiler/raatt.pas
new file mode 100644
index 0000000000..346d202db0
--- /dev/null
+++ b/closures/compiler/raatt.pas
@@ -0,0 +1,1645 @@
+{
+ Copyright (c) 1998-2002 by Carl Eric Codere and Peter Vreman
+
+ Does the parsing for the GAS styled inline assembler.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit raatt;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ { common }
+ cutils,cclasses,
+ { global }
+ globtype,
+ { aasm }
+ cpubase,cpuinfo,aasmbase,aasmtai,aasmdata,aasmcpu,
+ { assembler reader }
+ rabase,
+ rasm,
+ rautils,
+ { symtable }
+ symconst,
+ { cg }
+ cgbase;
+
+ type
+ tasmtoken = (
+ AS_NONE,AS_LABEL,AS_LLABEL,AS_STRING,AS_INTNUM,
+ AS_REALNUM,AS_COMMA,AS_LPAREN,
+ AS_RPAREN,AS_COLON,AS_DOT,AS_PLUS,AS_MINUS,AS_STAR,
+ AS_SEPARATOR,AS_ID,AS_REGISTER,AS_OPCODE,AS_SLASH,AS_DOLLAR,
+ AS_HASH,AS_LSBRACKET,AS_RSBRACKET,AS_LBRACKET,AS_RBRACKET,
+ {------------------ Assembler directives --------------------}
+ AS_DB,AS_DW,AS_DD,AS_DQ,AS_GLOBAL,
+ AS_ALIGN,AS_BALIGN,AS_P2ALIGN,AS_ASCII,
+ AS_ASCIIZ,AS_LCOMM,AS_COMM,AS_SINGLE,AS_DOUBLE,AS_EXTENDED,AS_CEXTENDED,
+ AS_DATA,AS_TEXT,AS_INIT,AS_FINI,AS_RVA,AS_END,
+ {------------------ Assembler Operators --------------------}
+ AS_TYPE,AS_SIZEOF,AS_VMTOFFSET,AS_MOD,AS_SHL,AS_SHR,AS_NOT,AS_AND,AS_OR,AS_XOR,AS_NOR,AS_AT,
+ AS_LO,AS_HI,
+ {------------------ Target-specific directive ---------------}
+ AS_TARGET_DIRECTIVE
+ );
+
+ tasmkeyword = string[10];
+
+ const
+ { These tokens should be modified accordingly to the modifications }
+ { in the different enumerations. }
+ firstdirective = AS_DB;
+ lastdirective = AS_END;
+
+ token2str : array[tasmtoken] of tasmkeyword=(
+ '','Label','LLabel','string','integer',
+ 'float',',','(',
+ ')',':','.','+','-','*',
+ ';','identifier','register','opcode','/','$',
+ '#','{','}','[',']',
+ '.byte','.word','.long','.quad','.globl',
+ '.align','.balign','.p2align','.ascii',
+ '.asciz','.lcomm','.comm','.single','.double','.tfloat','.tcfloat',
+ '.data','.text','.init','.fini','.rva','END',
+ 'TYPE','SIZEOF','VMTOFFSET','%','<<','>>','!','&','|','^','~','@','lo','hi',
+ 'directive');
+
+ type
+ tattreader = class(tasmreader)
+ actasmtoken : tasmtoken;
+ prevasmtoken : tasmtoken;
+ procedure SetupTables;
+ procedure BuildConstant(constsize: byte);
+ procedure BuildConstantOperand(oper : toperand);
+ procedure BuildRealConstant(typ : tfloattype);
+ procedure BuildStringConstant(asciiz: boolean);
+ procedure BuildRva;
+ procedure BuildRecordOffsetSize(const expr: string;var offset:aint;var size:aint; var mangledname: string; needvmtofs: boolean);
+ procedure BuildConstSymbolExpression(allowref,betweenbracket,needofs:boolean;var value:aint;var asmsym:string;var asmsymtyp:TAsmsymtype);
+ function BuildConstExpression(allowref,betweenbracket:boolean): aint;
+ function Assemble: tlinkedlist;override;
+ procedure handleopcode;virtual;abstract;
+ function is_asmopcode(const s: string) : boolean;virtual;abstract;
+ Function is_asmdirective(const s: string):boolean;
+ function is_register(const s:string):boolean;virtual;
+ function is_locallabel(const s: string):boolean;
+ function is_targetdirective(const s: string): boolean;virtual;
+ procedure GetToken;
+ function consume(t : tasmtoken):boolean;
+ procedure RecoverConsume(allowcomma:boolean);
+ procedure handlepercent;virtual;
+ procedure HandleTargetDirective;virtual;
+ end;
+ tcattreader = class of tattreader;
+
+ var
+ cattreader : tcattreader;
+
+ implementation
+
+ uses
+ { globals }
+ verbose,systems,
+ { input }
+ scanner,
+ { symtable }
+ symbase,symtype,symsym,symdef,symtable,
+{$ifdef x86}
+ rax86,
+{$endif x86}
+ itcpugas,
+ procinfo;
+
+
+ procedure tattreader.SetupTables;
+ var
+ i : tasmop;
+ Begin
+ iasmops:=TFPHashList.create;
+ for i:=firstop to lastop do
+ iasmops.Add(upper(gas_op2str[i]),Pointer(PtrInt(i)));
+ end;
+
+
+ function tattreader.is_asmdirective(const s: string):boolean;
+ var
+ i : tasmtoken;
+ hs : string;
+ Begin
+ { GNU as is also not casesensitive with this }
+ hs:=lower(s);
+ for i:=firstdirective to lastdirective do
+ if hs=token2str[i] then
+ begin
+ actasmtoken:=i;
+ is_asmdirective:=true;
+ exit;
+ end;
+ is_asmdirective:=false;
+ end;
+
+
+ function tattreader.is_register(const s:string):boolean;
+ begin
+ is_register:=false;
+ actasmregister:=gas_regnum_search(lower(s));
+ if actasmregister<>NR_NO then
+ begin
+ is_register:=true;
+ actasmtoken:=AS_REGISTER;
+ end;
+ end;
+
+
+ function tattreader.is_locallabel(const s: string):boolean;
+ begin
+ is_locallabel:=(length(s)>=2) and (s[1]='.') and (s[2]='L');
+ end;
+
+
+ procedure tattreader.handlepercent;
+ begin
+ c:=current_scanner.asmgetchar;
+ actasmtoken:=AS_MOD;
+ end;
+
+ function tattreader.is_targetdirective(const s: string): boolean;
+ begin
+ result:=false;
+ end;
+
+ procedure tattreader.handletargetdirective;
+ begin
+ end;
+
+ procedure tattreader.GetToken;
+ var
+ len : longint;
+ srsym : tsym;
+ srsymtable : TSymtable;
+ begin
+ { save old token and reset new token }
+ prevasmtoken:=actasmtoken;
+ actasmtoken:=AS_NONE;
+ { reset }
+ actasmpattern:='';
+ { while space and tab , continue scan... }
+ while c in [' ',#9] do
+ c:=current_scanner.asmgetchar;
+ { get token pos }
+ if not (c in [#10,#13,'{',';']) then
+ current_scanner.gettokenpos;
+ { Local Label, Label, Directive, Prefix or Opcode }
+ if firsttoken and not(c in [#10,#13,'{',';']) then
+ begin
+ firsttoken:=FALSE;
+ len:=0;
+ { directive or local label }
+ if c = '.' then
+ begin
+ inc(len);
+ actasmpattern[len]:=c;
+ { Let us point to the next character }
+ c:=current_scanner.asmgetchar;
+ while c in ['A'..'Z','a'..'z','0'..'9','_','$'] do
+ begin
+ inc(len);
+ actasmpattern[len]:=c;
+ c:=current_scanner.asmgetchar;
+ end;
+ actasmpattern[0]:=chr(len);
+ { this is a local label... }
+ if (c=':') and is_locallabel(actasmpattern) then
+ Begin
+ { local variables are case sensitive }
+ actasmtoken:=AS_LLABEL;
+ c:=current_scanner.asmgetchar;
+ firsttoken:=true;
+ exit;
+ end
+ { must be a directive }
+ else
+ Begin
+ { directives are case sensitive!! }
+ if is_asmdirective(actasmpattern) then
+ exit;
+ if is_targetdirective(actasmpattern) then
+ begin
+ actasmtoken:=AS_TARGET_DIRECTIVE;
+ exit;
+ end;
+ Message1(asmr_e_not_directive_or_local_symbol,actasmpattern);
+ end;
+ end;
+ { only opcodes and global labels are allowed now. }
+ while c in ['A'..'Z','a'..'z','0'..'9','_'] do
+ begin
+ inc(len);
+ actasmpattern[len]:=c;
+ c:=current_scanner.asmgetchar;
+ end;
+ actasmpattern[0]:=chr(len);
+ { Label ? }
+ if c = ':' then
+ begin
+ actasmtoken:=AS_LABEL;
+ { let us point to the next character }
+ c:=current_scanner.asmgetchar;
+ firsttoken:=true;
+ exit;
+ end;
+{$if defined(POWERPC) or defined(POWERPC64)}
+ { some PowerPC instructions can have the postfix -, + or .
+ this code could be moved to is_asmopcode but I think
+ it's better to ifdef it here (FK)
+ }
+ case c of
+ '.', '-', '+':
+ begin
+ actasmpattern:=actasmpattern+c;
+ c:=current_scanner.asmgetchar;
+ end
+ end;
+{$endif POWERPC}
+{$if defined(ARM)}
+ { Thumb-2 instructions can have a .W postfix to indicate 32bit instructions
+ }
+ case c of
+ '.':
+ begin
+ actasmpattern:=actasmpattern+c;
+ c:=current_scanner.asmgetchar;
+
+ if upcase(c) = 'W' then
+ begin
+ actasmpattern:=actasmpattern+c;
+ c:=current_scanner.asmgetchar;
+ end
+ else
+ internalerror(2010122301);
+ end
+ end;
+{$endif ARM}
+ { Opcode ? }
+ If is_asmopcode(upper(actasmpattern)) then
+ Begin
+ uppervar(actasmpattern);
+ exit;
+ end;
+ { End of assemblerblock ? }
+ if upper(actasmpattern) = 'END' then
+ begin
+ actasmtoken:=AS_END;
+ exit;
+ end;
+ message1(asmr_e_unknown_opcode,actasmpattern);
+ actasmtoken:=AS_NONE;
+ end
+ else { else firsttoken }
+ { Here we must handle all possible cases }
+ begin
+ case c of
+ '.' : { possiblities : - local label reference , such as in jmp @local1 }
+ { - field of object/record }
+ { - directive. }
+ begin
+ if (prevasmtoken in [AS_ID,AS_RPAREN]) then
+ begin
+ c:=current_scanner.asmgetchar;
+ actasmtoken:=AS_DOT;
+ exit;
+ end;
+ actasmpattern:=c;
+ c:=current_scanner.asmgetchar;
+ while c in ['A'..'Z','a'..'z','0'..'9','_','$'] do
+ begin
+ actasmpattern:=actasmpattern + c;
+ c:=current_scanner.asmgetchar;
+ end;
+ if is_asmdirective(actasmpattern) then
+ exit;
+ if is_targetdirective(actasmpattern) then
+ begin
+ actasmtoken:=AS_TARGET_DIRECTIVE;
+ exit;
+ end;
+ { local label references and directives }
+ { are case sensitive }
+ actasmtoken:=AS_ID;
+ exit;
+ end;
+
+ { identifier, register, prefix or directive }
+ '_','A'..'Z','a'..'z':
+ begin
+ len:=0;
+ while c in ['A'..'Z','a'..'z','0'..'9','_','$'] do
+ begin
+ inc(len);
+ actasmpattern[len]:=c;
+ c:=current_scanner.asmgetchar;
+ end;
+ actasmpattern[0]:=chr(len);
+ uppervar(actasmpattern);
+{$ifdef x86}
+ { only x86 architectures have instruction prefixes }
+
+ { Opcode, can only be when the previous was a prefix }
+ If is_prefix(actopcode) and is_asmopcode(actasmpattern) then
+ Begin
+ uppervar(actasmpattern);
+ exit;
+ end;
+{$endif x86}
+ { check for end which is a reserved word unlike the opcodes }
+ if actasmpattern = 'END' then
+ Begin
+ actasmtoken:=AS_END;
+ exit;
+ end;
+ if actasmpattern = 'TYPE' then
+ Begin
+ actasmtoken:=AS_TYPE;
+ exit;
+ end;
+ if actasmpattern = 'SIZEOF' then
+ Begin
+ actasmtoken:=AS_SIZEOF;
+ exit;
+ end;
+ if actasmpattern = 'VMTOFFSET' then
+ Begin
+ actasmtoken:=AS_VMTOFFSET;
+ exit;
+ end;
+ if is_register(actasmpattern) then
+ begin
+ actasmtoken:=AS_REGISTER;
+ exit;
+ end;
+ { if next is a '.' and this is a unitsym then we also need to
+ parse the identifier }
+ if (c='.') then
+ begin
+ searchsym(actasmpattern,srsym,srsymtable);
+ if assigned(srsym) and
+ (srsym.typ=unitsym) and
+ (srsym.owner.symtabletype in [staticsymtable,globalsymtable]) and
+ srsym.owner.iscurrentunit then
+ begin
+ actasmpattern:=actasmpattern+c;
+ c:=current_scanner.asmgetchar;
+ while c in ['A'..'Z','a'..'z','0'..'9','_','$'] do
+ begin
+ actasmpattern:=actasmpattern + upcase(c);
+ c:=current_scanner.asmgetchar;
+ end;
+ end;
+ end;
+ actasmtoken:=AS_ID;
+ exit;
+ end;
+
+ '%' : { register or modulo }
+ handlepercent;
+
+ '1'..'9': { integer number }
+ begin
+ len:=0;
+ while c in ['0'..'9'] do
+ Begin
+ inc(len);
+ actasmpattern[len]:=c;
+ c:=current_scanner.asmgetchar;
+ end;
+ actasmpattern[0]:=chr(len);
+ actasmpattern:=tostr(ParseVal(actasmpattern,10));
+ actasmtoken:=AS_INTNUM;
+ exit;
+ end;
+ '0' : { octal,hexa,real or binary number. }
+ begin
+ actasmpattern:=c;
+ c:=current_scanner.asmgetchar;
+ case upcase(c) of
+ 'B': { binary }
+ Begin
+ c:=current_scanner.asmgetchar;
+ while c in ['0','1'] do
+ Begin
+ actasmpattern:=actasmpattern + c;
+ c:=current_scanner.asmgetchar;
+ end;
+ actasmpattern:=tostr(ParseVal(actasmpattern,2));
+ actasmtoken:=AS_INTNUM;
+ exit;
+ end;
+ 'D': { real }
+ Begin
+ c:=current_scanner.asmgetchar;
+ { get ridd of the 0d }
+ if (c in ['+','-']) then
+ begin
+ actasmpattern:=c;
+ c:=current_scanner.asmgetchar;
+ end
+ else
+ actasmpattern:='';
+ while c in ['0'..'9'] do
+ Begin
+ actasmpattern:=actasmpattern + c;
+ c:=current_scanner.asmgetchar;
+ end;
+ if c='.' then
+ begin
+ actasmpattern:=actasmpattern + c;
+ c:=current_scanner.asmgetchar;
+ while c in ['0'..'9'] do
+ Begin
+ actasmpattern:=actasmpattern + c;
+ c:=current_scanner.asmgetchar;
+ end;
+ if upcase(c) = 'E' then
+ begin
+ actasmpattern:=actasmpattern + c;
+ c:=current_scanner.asmgetchar;
+ if (c in ['+','-']) then
+ begin
+ actasmpattern:=actasmpattern + c;
+ c:=current_scanner.asmgetchar;
+ end;
+ while c in ['0'..'9'] do
+ Begin
+ actasmpattern:=actasmpattern + c;
+ c:=current_scanner.asmgetchar;
+ end;
+ end;
+ actasmtoken:=AS_REALNUM;
+ exit;
+ end
+ else
+ begin
+ Message1(asmr_e_invalid_float_const,actasmpattern+c);
+ actasmtoken:=AS_NONE;
+ end;
+ end;
+ 'X': { hexadecimal }
+ Begin
+ c:=current_scanner.asmgetchar;
+ while c in ['0'..'9','a'..'f','A'..'F'] do
+ Begin
+ actasmpattern:=actasmpattern + c;
+ c:=current_scanner.asmgetchar;
+ end;
+ actasmpattern:=tostr(ParseVal(actasmpattern,16));
+ actasmtoken:=AS_INTNUM;
+ exit;
+ end;
+ '1'..'7': { octal }
+ begin
+ actasmpattern:=actasmpattern + c;
+ while c in ['0'..'7'] do
+ Begin
+ actasmpattern:=actasmpattern + c;
+ c:=current_scanner.asmgetchar;
+ end;
+ actasmpattern:=tostr(ParseVal(actasmpattern,8));
+ actasmtoken:=AS_INTNUM;
+ exit;
+ end;
+ else { octal number zero value...}
+ Begin
+ actasmpattern:=tostr(ParseVal(actasmpattern,8));
+ actasmtoken:=AS_INTNUM;
+ exit;
+ end;
+ end; { end case }
+ end;
+
+ '&' :
+ begin
+ c:=current_scanner.asmgetchar;
+ actasmtoken:=AS_AND;
+ end;
+
+ '''' : { char }
+ begin
+ current_scanner.in_asm_string:=true;
+ actasmpattern:='';
+ repeat
+ c:=current_scanner.asmgetchar;
+ case c of
+ '\' :
+ begin
+ { copy also the next char so \" is parsed correctly }
+ actasmpattern:=actasmpattern+c;
+ c:=current_scanner.asmgetchar;
+ actasmpattern:=actasmpattern+c;
+ end;
+ '''' :
+ begin
+ c:=current_scanner.asmgetchar;
+ break;
+ end;
+ #10,#13:
+ Message(scan_f_string_exceeds_line);
+ else
+ actasmpattern:=actasmpattern+c;
+ end;
+ until false;
+ actasmpattern:=EscapeToPascal(actasmpattern);
+ actasmtoken:=AS_STRING;
+ current_scanner.in_asm_string:=false;
+ exit;
+ end;
+
+ '"' : { string }
+ begin
+ current_scanner.in_asm_string:=true;
+ actasmpattern:='';
+ repeat
+ c:=current_scanner.asmgetchar;
+ case c of
+ '\' :
+ begin
+ { copy also the next char so \" is parsed correctly }
+ actasmpattern:=actasmpattern+c;
+ c:=current_scanner.asmgetchar;
+ actasmpattern:=actasmpattern+c;
+ end;
+ '"' :
+ begin
+ c:=current_scanner.asmgetchar;
+ break;
+ end;
+ #10,#13:
+ Message(scan_f_string_exceeds_line);
+ else
+ actasmpattern:=actasmpattern+c;
+ end;
+ until false;
+ actasmpattern:=EscapeToPascal(actasmpattern);
+ actasmtoken:=AS_STRING;
+ current_scanner.in_asm_string:=false;
+ exit;
+ end;
+
+ '$' :
+ begin
+ actasmtoken:=AS_DOLLAR;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+
+ '#' :
+ begin
+ actasmtoken:=AS_HASH;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+
+ '[' :
+ begin
+ actasmtoken:=AS_LBRACKET;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+
+ ']' :
+ begin
+ actasmtoken:=AS_RBRACKET;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+{$ifdef arm}
+ // the arm assembler uses { ... } for register sets
+ '{' :
+ begin
+ actasmtoken:=AS_LSBRACKET;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+
+ '}' :
+ begin
+ actasmtoken:=AS_RSBRACKET;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+{$endif arm}
+
+ ',' :
+ begin
+ actasmtoken:=AS_COMMA;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+
+ '<' :
+ begin
+ actasmtoken:=AS_SHL;
+ c:=current_scanner.asmgetchar;
+ if c = '<' then
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+
+ '>' :
+ begin
+ actasmtoken:=AS_SHL;
+ c:=current_scanner.asmgetchar;
+ if c = '>' then
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+
+ '|' :
+ begin
+ actasmtoken:=AS_OR;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+
+ '^' :
+ begin
+ actasmtoken:=AS_XOR;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+
+
+ '(' :
+ begin
+ actasmtoken:=AS_LPAREN;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+
+ ')' :
+ begin
+ actasmtoken:=AS_RPAREN;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+
+ ':' :
+ begin
+ actasmtoken:=AS_COLON;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+
+ '+' :
+ begin
+ actasmtoken:=AS_PLUS;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+
+ '-' :
+ begin
+ actasmtoken:=AS_MINUS;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+
+ '*' :
+ begin
+ actasmtoken:=AS_STAR;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+
+ '/' :
+ begin
+ actasmtoken:=AS_SLASH;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+
+ '!' :
+ begin
+ actasmtoken:=AS_NOT;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+
+ '@' :
+ begin
+ actasmtoken:=AS_AT;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+
+{$ifndef arm}
+ '{',
+{$endif arm}
+ #13,#10,';' :
+ begin
+ { the comment is read by asmgetchar }
+ c:=current_scanner.asmgetchar;
+ firsttoken:=TRUE;
+ actasmtoken:=AS_SEPARATOR;
+ exit;
+ end;
+
+ else
+ current_scanner.illegal_char(c);
+ end;
+ end;
+ end;
+
+
+ function tattreader.consume(t : tasmtoken):boolean;
+ begin
+ Consume:=true;
+ if t<>actasmtoken then
+ begin
+ Message2(scan_f_syn_expected,token2str[t],token2str[actasmtoken]);
+ Consume:=false;
+ end;
+ repeat
+ gettoken;
+ until actasmtoken<>AS_NONE;
+ end;
+
+
+ procedure tattreader.RecoverConsume(allowcomma:boolean);
+ begin
+ While not (actasmtoken in [AS_SEPARATOR,AS_END]) do
+ begin
+ if allowcomma and (actasmtoken=AS_COMMA) then
+ break;
+ Consume(actasmtoken);
+ end;
+ end;
+
+
+ Procedure tattreader.BuildConstant(constsize: byte);
+ var
+ asmsymtyp : TAsmSymType;
+ asmsym,
+ expr: string;
+ value : aint;
+ Begin
+ Repeat
+ Case actasmtoken of
+ AS_STRING:
+ Begin
+ expr:=actasmpattern;
+ if length(expr) > 1 then
+ Message(asmr_e_string_not_allowed_as_const);
+ Consume(AS_STRING);
+ Case actasmtoken of
+ AS_COMMA: Consume(AS_COMMA);
+ AS_END,
+ AS_SEPARATOR: ;
+ else
+ Message(asmr_e_invalid_string_expression);
+ end; { end case }
+ ConcatString(curlist,expr);
+ end;
+ AS_INTNUM,
+ AS_PLUS,
+ AS_MINUS,
+ AS_LPAREN,
+ AS_TYPE,
+ AS_SIZEOF,
+ AS_NOT,
+ AS_VMTOFFSET,
+ AS_ID :
+ Begin
+ BuildConstSymbolExpression(false,false,false,value,asmsym,asmsymtyp);
+ if asmsym<>'' then
+ begin
+ if constsize<>sizeof(pint) then
+ Message(asmr_w_32bit_const_for_address);
+ ConcatConstSymbol(curlist,asmsym,asmsymtyp,value)
+ end
+ else
+ ConcatConstant(curlist,value,constsize);
+ end;
+ AS_COMMA:
+ Consume(AS_COMMA);
+ AS_END,
+ AS_SEPARATOR:
+ break;
+ else
+ begin
+ Message(asmr_e_syn_constant);
+ RecoverConsume(false);
+ end
+ end; { end case }
+ Until false;
+ end;
+
+
+ Procedure tattreader.BuildRealConstant(typ : tfloattype);
+ var
+ expr : string;
+ r : bestreal;
+ code : integer;
+ negativ : boolean;
+ errorflag: boolean;
+ Begin
+ errorflag:=FALSE;
+ Repeat
+ negativ:=false;
+ expr:='';
+ if actasmtoken=AS_PLUS then
+ Consume(AS_PLUS)
+ else
+ if actasmtoken=AS_MINUS then
+ begin
+ negativ:=true;
+ consume(AS_MINUS);
+ end;
+ Case actasmtoken of
+ AS_INTNUM:
+ Begin
+ expr:=actasmpattern;
+ Consume(AS_INTNUM);
+ if negativ then
+ expr:='-'+expr;
+ val(expr,r,code);
+ if code<>0 then
+ Begin
+ r:=0;
+ Message(asmr_e_invalid_float_expr);
+ End;
+ ConcatRealConstant(curlist,r,typ);
+ end;
+ AS_REALNUM:
+ Begin
+ expr:=actasmpattern;
+ Consume(AS_REALNUM);
+ { in ATT syntax you have 0d in front of the real }
+ { should this be forced ? yes i think so, as to }
+ { conform to gas as much as possible. }
+ if (expr[1]='0') and (upper(expr[2])='D') then
+ Delete(expr,1,2);
+ if negativ then
+ expr:='-'+expr;
+ val(expr,r,code);
+ if code<>0 then
+ Begin
+ r:=0;
+ Message(asmr_e_invalid_float_expr);
+ End;
+ ConcatRealConstant(curlist,r,typ);
+ end;
+ AS_COMMA:
+ begin
+ Consume(AS_COMMA);
+ end;
+ AS_END,
+ AS_SEPARATOR:
+ begin
+ break;
+ end;
+ else
+ Begin
+ Consume(actasmtoken);
+ if not errorflag then
+ Message(asmr_e_invalid_float_expr);
+ errorflag:=TRUE;
+ end;
+ end;
+ Until false;
+ end;
+
+
+ Procedure tattreader.BuildStringConstant(asciiz: boolean);
+ var
+ expr: string;
+ errorflag : boolean;
+ Begin
+ errorflag:=FALSE;
+ Repeat
+ Case actasmtoken of
+ AS_STRING:
+ Begin
+ expr:=actasmpattern;
+ if asciiz then
+ expr:=expr+#0;
+ ConcatPasString(curlist,expr);
+ Consume(AS_STRING);
+ end;
+ AS_COMMA:
+ begin
+ Consume(AS_COMMA);
+ end;
+ AS_END,
+ AS_SEPARATOR:
+ begin
+ break;
+ end;
+ else
+ Begin
+ Consume(actasmtoken);
+ if not errorflag then
+ Message(asmr_e_invalid_string_expression);
+ errorflag:=TRUE;
+ end;
+ end;
+ Until false;
+ end;
+
+
+ Function tattreader.Assemble: tlinkedlist;
+ Var
+ hl : tasmlabel;
+ commname : string;
+ lasTSec : TAsmSectiontype;
+ l1,l2 : longint;
+ Begin
+ Message1(asmr_d_start_reading,'GNU AS');
+ firsttoken:=TRUE;
+ { sets up all opcode and register tables in uppercase }
+ if not _asmsorted then
+ Begin
+ SetupTables;
+ _asmsorted:=TRUE;
+ end;
+ curlist:=TAsmList.Create;
+ lasTSec:=sec_code;
+ { setup label linked list }
+ LocalLabelList:=TLocalLabelList.Create;
+ { start tokenizer }
+ c:=current_scanner.asmgetcharstart;
+ gettoken;
+ { main loop }
+ repeat
+ case actasmtoken of
+ AS_LLABEL:
+ Begin
+ if CreateLocalLabel(actasmpattern,hl,true) then
+ ConcatLabel(curlist,hl);
+ Consume(AS_LLABEL);
+ end;
+
+ AS_LABEL:
+ Begin
+ if SearchLabel(upper(actasmpattern),hl,true) then
+ ConcatLabel(curlist,hl)
+ else
+ Message1(asmr_e_unknown_label_identifier,actasmpattern);
+ Consume(AS_LABEL);
+ end;
+
+ AS_DW:
+ Begin
+ Consume(AS_DW);
+ BuildConstant(2);
+ end;
+
+ AS_DATA:
+ Begin
+ new_section(curList,sec_data,lower(current_procinfo.procdef.mangledname),0);
+ lasTSec:=sec_data;
+ Consume(AS_DATA);
+ end;
+
+ AS_TEXT:
+ Begin
+ new_section(curList,sec_code,lower(current_procinfo.procdef.mangledname),0);
+ lasTSec:=sec_code;
+ Consume(AS_TEXT);
+ end;
+
+ AS_INIT:
+ Begin
+ new_section(curList,sec_init,lower(current_procinfo.procdef.mangledname),0);
+ lasTSec:=sec_init;
+ Consume(AS_INIT);
+ end;
+
+ AS_FINI:
+ Begin
+ new_section(curList,sec_fini,lower(current_procinfo.procdef.mangledname),0);
+ lasTSec:=sec_fini;
+ Consume(AS_FINI);
+ end;
+
+ AS_DB:
+ Begin
+ Consume(AS_DB);
+ BuildConstant(1);
+ end;
+
+ AS_DD:
+ Begin
+ Consume(AS_DD);
+ BuildConstant(4);
+ end;
+
+ AS_DQ:
+ Begin
+ Consume(AS_DQ);
+{$ifdef cpu64bitaddr}
+ BuildConstant(8);
+{$else cpu64bitaddr}
+ BuildRealConstant(s64comp);
+{$endif cpu64bitaddr}
+ end;
+
+ AS_SINGLE:
+ Begin
+ Consume(AS_SINGLE);
+ BuildRealConstant(s32real);
+ end;
+
+ AS_DOUBLE:
+ Begin
+ Consume(AS_DOUBLE);
+ BuildRealConstant(s64real);
+ end;
+
+ AS_EXTENDED:
+ Begin
+ Consume(AS_EXTENDED);
+ BuildRealConstant(s80real);
+ end;
+
+ AS_CEXTENDED:
+ Begin
+ Consume(AS_CEXTENDED);
+ BuildRealConstant(sc80real);
+ end;
+
+ AS_GLOBAL:
+ Begin
+ Consume(AS_GLOBAL);
+ if actasmtoken=AS_ID then
+ ConcatPublic(curlist,actasmpattern);
+ Consume(AS_ID);
+ if actasmtoken<>AS_SEPARATOR then
+ Consume(AS_SEPARATOR);
+ end;
+
+ AS_ALIGN:
+ Begin
+ Consume(AS_ALIGN);
+ l1:=BuildConstExpression(false,false);
+ if (target_info.system in [system_i386_GO32V2]) then
+ begin
+ l2:=1;
+ if (l1>=0) and (l1<=16) then
+ while (l1>0) do
+ begin
+ l2:=2*l2;
+ dec(l1);
+ end;
+ l1:=l2;
+ end;
+ ConcatAlign(curlist,l1);
+ Message(asmr_n_align_is_target_specific);
+ if actasmtoken<>AS_SEPARATOR then
+ Consume(AS_SEPARATOR);
+ end;
+
+ AS_BALIGN:
+ Begin
+ Consume(AS_BALIGN);
+ ConcatAlign(curlist,BuildConstExpression(false,false));
+ if actasmtoken<>AS_SEPARATOR then
+ Consume(AS_SEPARATOR);
+ end;
+
+ AS_P2ALIGN:
+ Begin
+ Consume(AS_P2ALIGN);
+ l1:=BuildConstExpression(false,false);
+ l2:=1;
+ if (l1>=0) and (l1<=16) then
+ while (l1>0) do
+ begin
+ l2:=2*l2;
+ dec(l1);
+ end;
+ l1:=l2;
+ ConcatAlign(curlist,l1);
+ if actasmtoken<>AS_SEPARATOR then
+ Consume(AS_SEPARATOR);
+ end;
+
+ AS_ASCIIZ:
+ Begin
+ Consume(AS_ASCIIZ);
+ BuildStringConstant(TRUE);
+ end;
+
+ AS_ASCII:
+ Begin
+ Consume(AS_ASCII);
+ BuildStringConstant(FALSE);
+ end;
+
+ AS_LCOMM:
+ Begin
+ Consume(AS_LCOMM);
+ commname:=actasmpattern;
+ Consume(AS_ID);
+ Consume(AS_COMMA);
+ curList.concat(Tai_datablock.Create(commname,BuildConstExpression(false,false)));
+ if actasmtoken<>AS_SEPARATOR then
+ Consume(AS_SEPARATOR);
+ end;
+
+ AS_COMM:
+ Begin
+ Consume(AS_COMM);
+ commname:=actasmpattern;
+ Consume(AS_ID);
+ Consume(AS_COMMA);
+ curList.concat(Tai_datablock.Create_global(commname,BuildConstExpression(false,false)));
+ if actasmtoken<>AS_SEPARATOR then
+ Consume(AS_SEPARATOR);
+ end;
+
+ AS_OPCODE:
+ Begin
+ HandleOpCode;
+ end;
+
+ AS_SEPARATOR:
+ Begin
+ Consume(AS_SEPARATOR);
+ end;
+
+ AS_RVA:
+ begin
+ { .rva generally applies to systems with COFF output format,
+ not just Windows. }
+ if not (target_info.system in systems_all_windows) then
+ Message1(asmr_e_unsupported_directive,token2str[AS_RVA]);
+ Consume(AS_RVA);
+ BuildRva;
+ end;
+
+ AS_TARGET_DIRECTIVE:
+ HandleTargetDirective;
+
+ AS_END:
+ begin
+ break; { end assembly block }
+ end;
+
+ else
+ Begin
+ Message(asmr_e_syntax_error);
+ RecoverConsume(false);
+ end;
+ end;
+ until false;
+ { Check LocalLabelList }
+ LocalLabelList.CheckEmitted;
+ LocalLabelList.Free;
+ { are we back in the code section? }
+ if lasTSec<>sec_code then
+ begin
+ Message(asmr_w_assembler_code_not_returned_to_text);
+ new_section(curList,sec_code,lower(current_procinfo.procdef.mangledname),0);
+ end;
+ { Return the list in an asmnode }
+ assemble:=curlist;
+ Message1(asmr_d_finish_reading,'GNU AS');
+ end;
+
+
+{*****************************************************************************
+ Parsing Helpers
+*****************************************************************************}
+
+ Procedure tattreader.BuildRecordOffsetSize(const expr: string;var offset:aint;var size:aint; var mangledname: string; needvmtofs: boolean);
+ { Description: This routine builds up a record offset after a AS_DOT }
+ { token is encountered. }
+ { On entry actasmtoken should be equal to AS_DOT }
+ var
+ s : string;
+ Begin
+ offset:=0;
+ size:=0;
+ s:=expr;
+ while (actasmtoken=AS_DOT) do
+ begin
+ Consume(AS_DOT);
+ if actasmtoken=AS_ID then
+ s:=s+'.'+actasmpattern;
+ if not Consume(AS_ID) then
+ begin
+ RecoverConsume(true);
+ break;
+ end;
+ end;
+ if not GetRecordOffsetSize(s,offset,size,mangledname,needvmtofs) then
+ Message(asmr_e_building_record_offset);
+ end;
+
+
+ procedure tattreader.BuildConstSymbolExpression(allowref,betweenbracket,needofs:boolean;var value:aint;var asmsym:string;var asmsymtyp:TAsmsymtype);
+ var
+ hssymtyp : TAsmSymType;
+ hs,tempstr,expr,mangledname : string;
+ parenlevel : longint;
+ l,k : aint;
+ errorflag : boolean;
+ prevtok : tasmtoken;
+ sym : tsym;
+ srsymtable : TSymtable;
+ hl : tasmlabel;
+ Begin
+ asmsym:='';
+ asmsymtyp:=AT_DATA;
+ value:=0;
+ errorflag:=FALSE;
+ tempstr:='';
+ expr:='';
+ parenlevel:=0;
+ Repeat
+ Case actasmtoken of
+ AS_LPAREN:
+ Begin
+ { Exit if ref? }
+ if allowref and (prevasmtoken in [AS_INTNUM,AS_ID]) then
+ break;
+ Consume(AS_LPAREN);
+ expr:=expr + '(';
+ inc(parenlevel);
+ end;
+ AS_RBRACKET:
+ begin
+ if betweenbracket then
+ break;
+ { write error only once. }
+ if not errorflag then
+ Message(asmr_e_invalid_constant_expression);
+ { consume tokens until we find COMMA or SEPARATOR }
+ Consume(actasmtoken);
+ errorflag:=TRUE;
+ end;
+ AS_RPAREN:
+ Begin
+ { end of ref ? }
+ if (parenlevel=0) and betweenbracket then
+ break;
+ Consume(AS_RPAREN);
+ expr:=expr + ')';
+ dec(parenlevel);
+ end;
+ AS_SHL:
+ Begin
+ Consume(AS_SHL);
+ expr:=expr + '<';
+ end;
+ AS_SHR:
+ Begin
+ Consume(AS_SHR);
+ expr:=expr + '>';
+ end;
+ AS_SLASH:
+ Begin
+ Consume(AS_SLASH);
+ expr:=expr + '/';
+ end;
+ AS_MOD:
+ Begin
+ Consume(AS_MOD);
+ expr:=expr + '%';
+ end;
+ AS_STAR:
+ Begin
+ Consume(AS_STAR);
+ expr:=expr + '*';
+ end;
+ AS_PLUS:
+ Begin
+ Consume(AS_PLUS);
+ expr:=expr + '+';
+ end;
+ AS_MINUS:
+ Begin
+ Consume(AS_MINUS);
+ expr:=expr + '-';
+ end;
+ AS_AND:
+ Begin
+ Consume(AS_AND);
+ expr:=expr + '&';
+ end;
+ AS_NOT:
+ Begin
+ Consume(AS_NOT);
+ expr:=expr + '~';
+ end;
+ AS_XOR:
+ Begin
+ Consume(AS_XOR);
+ expr:=expr + '^';
+ end;
+ AS_OR:
+ Begin
+ Consume(AS_OR);
+ expr:=expr + '|';
+ end;
+ AS_INTNUM:
+ Begin
+ expr:=expr + actasmpattern;
+ Consume(AS_INTNUM);
+ end;
+ AS_DOLLAR:
+ begin
+ Consume(AS_DOLLAR);
+ if actasmtoken<>AS_ID then
+ Message(asmr_e_dollar_without_identifier);
+ end;
+ AS_STRING:
+ Begin
+ l:=0;
+ case Length(actasmpattern) of
+ 1 :
+ l:=ord(actasmpattern[1]);
+ 2 :
+ l:=ord(actasmpattern[2]) + ord(actasmpattern[1]) shl 8;
+ 3 :
+ l:=ord(actasmpattern[3]) +
+ Ord(actasmpattern[2]) shl 8 + ord(actasmpattern[1]) shl 16;
+ 4 :
+ l:=ord(actasmpattern[4]) + ord(actasmpattern[3]) shl 8 +
+ Ord(actasmpattern[2]) shl 16 + ord(actasmpattern[1]) shl 24;
+ else
+ Message1(asmr_e_invalid_string_as_opcode_operand,actasmpattern);
+ end;
+ str(l, tempstr);
+ expr:=expr + tempstr;
+ Consume(AS_STRING);
+ end;
+ AS_SIZEOF,
+ AS_TYPE:
+ begin
+ l:=0;
+ Consume(actasmtoken);
+ if actasmtoken<>AS_ID then
+ Message(asmr_e_type_without_identifier)
+ else
+ begin
+ tempstr:=actasmpattern;
+ Consume(AS_ID);
+ if actasmtoken=AS_DOT then
+ begin
+ BuildRecordOffsetSize(tempstr,k,l,mangledname,false);
+ if mangledname<>'' then
+ Message(asmr_e_wrong_sym_type);
+ end
+ else
+ begin
+ searchsym(tempstr,sym,srsymtable);
+ if assigned(sym) then
+ begin
+ case sym.typ of
+ staticvarsym,
+ localvarsym,
+ paravarsym :
+ l:=tabstractvarsym(sym).getsize;
+ typesym :
+ l:=ttypesym(sym).typedef.size;
+ else
+ Message(asmr_e_wrong_sym_type);
+ end;
+ end
+ else
+ Message1(sym_e_unknown_id,tempstr);
+ end;
+ end;
+ str(l, tempstr);
+ expr:=expr + tempstr;
+ end;
+ AS_VMTOFFSET:
+ begin
+ Consume(actasmtoken);
+ if actasmtoken<>AS_ID then
+ Message(asmr_e_type_without_identifier)
+ else
+ begin
+ tempstr:=actasmpattern;
+ consume(AS_ID);
+ BuildRecordOffsetSize(tempstr,k,l,mangledname,true);
+ if (mangledname <> '') then
+ Message(asmr_e_wrong_sym_type);
+ str(k,tempstr);
+ expr := expr + tempstr;
+ end
+ end;
+ AS_ID:
+ Begin
+ hs:='';
+ hssymtyp:=AT_DATA;
+ tempstr:=actasmpattern;
+ prevtok:=prevasmtoken;
+ consume(AS_ID);
+ if SearchIConstant(tempstr,l) then
+ begin
+ str(l, tempstr);
+ expr:=expr + tempstr;
+ end
+ else
+ begin
+ if is_locallabel(tempstr) then
+ begin
+ CreateLocalLabel(tempstr,hl,false);
+ hs:=hl.name;
+ hssymtyp:=AT_LABEL;
+ end
+ else
+ if SearchLabel(tempstr,hl,false) then
+ begin
+ hs:=hl.name;
+ hssymtyp:=AT_FUNCTION;
+ end
+ else
+ begin
+ searchsym(tempstr,sym,srsymtable);
+ if assigned(sym) then
+ begin
+ case sym.typ of
+ staticvarsym :
+ hs:=tstaticvarsym(sym).mangledname;
+ localvarsym,
+ paravarsym :
+ Message(asmr_e_no_local_or_para_allowed);
+ procsym :
+ begin
+ if Tprocsym(sym).ProcdefList.Count>1 then
+ Message(asmr_w_calling_overload_func);
+ hs:=tprocdef(tprocsym(sym).ProcdefList[0]).mangledname;
+ hssymtyp:=AT_FUNCTION;
+ end;
+ typesym :
+ begin
+ if not(ttypesym(sym).typedef.typ in [recorddef,objectdef]) then
+ Message(asmr_e_wrong_sym_type);
+ end;
+ else
+ Message(asmr_e_wrong_sym_type);
+ end;
+ end
+ else
+ Message1(sym_e_unknown_id,tempstr);
+ end;
+ { symbol found? }
+ if hs<>'' then
+ begin
+ if needofs and (prevtok<>AS_DOLLAR) then
+ Message(asmr_e_need_dollar);
+ if asmsym='' then
+ begin
+ asmsym:=hs;
+ asmsymtyp:=hssymtyp;
+ end
+ else
+ Message(asmr_e_cant_have_multiple_relocatable_symbols);
+ if (expr='') or (expr[length(expr)]='+') then
+ begin
+ { don't remove the + if there could be a record field }
+ if actasmtoken<>AS_DOT then
+ delete(expr,length(expr),1);
+ end
+ else
+ Message(asmr_e_only_add_relocatable_symbol);
+ end;
+ if actasmtoken=AS_DOT then
+ begin
+ BuildRecordOffsetSize(tempstr,l,k,hs,false);
+ if (hs<>'') then
+ hssymtyp:=AT_FUNCTION
+ else
+ begin
+ str(l, tempstr);
+ expr:=expr + tempstr;
+ end
+ end
+ else
+ begin
+ if (expr='') or (expr[length(expr)] in ['+','-','/','*']) then
+ delete(expr,length(expr),1);
+ end;
+ end;
+ { check if there are wrong operator used like / or mod etc. }
+ if (hs<>'') and
+ not(actasmtoken in [AS_MINUS,AS_PLUS,AS_COMMA,AS_SEPARATOR,
+ AS_LPAREN,AS_RPAREN,AS_RBRACKET,AS_END]) then
+ Message(asmr_e_only_add_relocatable_symbol);
+ end;
+ AS_END,
+ AS_SEPARATOR,
+ AS_COMMA:
+ break;
+ else
+ Begin
+ { write error only once. }
+ if not errorflag then
+ Message(asmr_e_invalid_constant_expression);
+ { consume tokens until we find COMMA or SEPARATOR }
+ Consume(actasmtoken);
+ errorflag:=TRUE;
+ end;
+ end;
+ Until false;
+ { calculate expression }
+ if not ErrorFlag then
+ value:=CalculateExpression(expr)
+ else
+ value:=0;
+ end;
+
+
+ function tattreader.BuildConstExpression(allowref,betweenbracket:boolean): aint;
+ var
+ l : aint;
+ hs : string;
+ hssymtyp : TAsmSymType;
+ begin
+ BuildConstSymbolExpression(allowref,betweenbracket,false,l,hs,hssymtyp);
+ if hs<>'' then
+ Message(asmr_e_relocatable_symbol_not_allowed);
+ BuildConstExpression:=l;
+ end;
+
+
+ Procedure tattreader.BuildConstantOperand(oper : toperand);
+ var
+ l : aint;
+ tempstr : string;
+ tempsymtyp : TAsmSymType;
+ begin
+ BuildConstSymbolExpression(false,false,true,l,tempstr,tempsymtyp);
+ if tempstr<>'' then
+ begin
+ oper.opr.typ:=OPR_SYMBOL;
+ oper.opr.symofs:=l;
+ oper.opr.symbol:=current_asmdata.RefAsmSymbol(tempstr);
+ end
+ else
+ begin
+ oper.opr.typ:=OPR_CONSTANT;
+ oper.opr.val:=l;
+ end;
+ end;
+
+ procedure tattreader.BuildRva;
+ var
+ asmsymtyp : TAsmSymType;
+ asmsym: string;
+ value : aint;
+ ai:tai_const;
+ begin
+ repeat
+ case actasmtoken of
+ AS_INTNUM,
+ AS_PLUS,
+ AS_MINUS,
+ AS_LPAREN,
+ AS_ID :
+ Begin
+ BuildConstSymbolExpression(false,false,false,value,asmsym,asmsymtyp);
+ if asmsym<>'' then
+ begin
+ ai:=tai_const.create_type_sym(aitconst_rva_symbol,current_asmdata.RefAsmSymbol(asmsym));
+ ai.value:=value;
+ curlist.concat(ai);
+ end
+ else
+ Message(asmr_e_invalid_symbol_ref);
+ end;
+ AS_COMMA:
+ Consume(AS_COMMA);
+ AS_END,
+ AS_SEPARATOR:
+ break;
+ else
+ begin
+ Message(asmr_e_syn_constant);
+ RecoverConsume(false);
+ end
+ end; { end case }
+ until false;
+ end;
+
+end.
diff --git a/closures/compiler/rabase.pas b/closures/compiler/rabase.pas
new file mode 100644
index 0000000000..0c7d8de2c9
--- /dev/null
+++ b/closures/compiler/rabase.pas
@@ -0,0 +1,107 @@
+{
+ Copyright (c) 1998-2003 by Peter Vreman, Florian Klaempfl and Carl Eric Codere
+
+ Basic stuff for assembler readers
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit rabase;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ cclasses,
+ systems;
+
+ type
+ tbaseasmreader = class
+ constructor create;virtual;
+ { the real return type is TAsmList, but this would introduce too much unit circles }
+ function Assemble: tlinkedlist;virtual;abstract;
+ end;
+ tcbaseasmreader = class of tbaseasmreader;
+
+ pasmmodeinfo = ^tasmmodeinfo;
+ tasmmodeinfo = record
+ id : tasmmode;
+ idtxt : string[12];
+ casmreader : tcbaseasmreader;
+ end;
+
+ var
+ asmmodeinfos : array[tasmmode] of pasmmodeinfo;
+
+ function SetAsmReadMode(const s:string;var t:tasmmode):boolean;
+ procedure RegisterAsmMode(const r:tasmmodeinfo);
+
+ implementation
+
+ uses
+ cutils;
+
+
+ procedure RegisterAsmmode(const r:tasmmodeinfo);
+ var
+ t : tasmmode;
+ begin
+ t:=r.id;
+ if assigned(asmmodeinfos[t]) then
+ writeln('Warning: Asmmode is already registered!')
+ else
+ Getmem(asmmodeinfos[t],sizeof(tasmmodeinfo));
+ asmmodeinfos[t]^:=r;
+ end;
+
+
+ function SetAsmReadMode(const s:string;var t:tasmmode):boolean;
+ var
+ hs : string;
+ ht : tasmmode;
+ begin
+ result:=false;
+ hs:=upper(s);
+ { Support Default as an alias for Standard }
+ if hs='DEFAULT' then
+ hs:='STANDARD';
+ for ht:=low(tasmmode) to high(tasmmode) do
+ if assigned(asmmodeinfos[ht]) and
+ (asmmodeinfos[ht]^.idtxt=hs) then
+ begin
+ t:=asmmodeinfos[ht]^.id;
+ result:=true;
+ end;
+ end;
+
+
+ constructor tbaseasmreader.create;
+ begin
+ inherited create;
+ end;
+
+var
+ asmmode : tasmmode;
+
+finalization
+ for asmmode:=low(tasmmode) to high(tasmmode) do
+ if assigned(asmmodeinfos[asmmode]) then
+ begin
+ freemem(asmmodeinfos[asmmode],sizeof(tasmmodeinfo));
+ asmmodeinfos[asmmode]:=nil;
+ end;
+end.
diff --git a/closures/compiler/rasm.pas b/closures/compiler/rasm.pas
new file mode 100644
index 0000000000..aab54005cb
--- /dev/null
+++ b/closures/compiler/rasm.pas
@@ -0,0 +1,68 @@
+{
+ Copyright (c) 1998-2003 by Peter Vreman, Florian Klaempfl and Carl Eric Codere
+
+ Basic stuff for assembler readers
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit rasm;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ cclasses,
+ rabase,
+ aasmtai,aasmdata,
+ systems,
+ cpubase,
+ cgbase;
+
+ type
+ tasmreader = class(tbaseasmreader)
+ firsttoken : boolean;
+ _asmsorted : boolean;
+ curlist : TAsmList;
+ c : char;
+ actasmpattern : string;
+ actopcode : tasmop;
+ actasmregister : tregister;
+ actcondition : tasmcond;
+ iasmops : TFPHashList;
+ constructor create;override;
+ destructor destroy;override;
+ end;
+
+ implementation
+
+ constructor tasmreader.create;
+ begin
+ inherited create;
+ firsttoken:=true;
+ end;
+
+
+ destructor tasmreader.destroy;
+ begin
+ if assigned(iasmops) then
+ iasmops.Free;
+ inherited destroy;
+ end;
+
+
+end.
diff --git a/closures/compiler/rautils.pas b/closures/compiler/rautils.pas
new file mode 100644
index 0000000000..d7c0999097
--- /dev/null
+++ b/closures/compiler/rautils.pas
@@ -0,0 +1,1640 @@
+{
+ Copyright (c) 1998-2002 by Carl Eric Codere and Peter Vreman
+
+ This unit implements some support routines for assembler parsing
+ independent of the processor
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ **********************************************************************}
+Unit RAUtils;
+
+{$i fpcdefs.inc}
+
+Interface
+
+Uses
+ cutils,cclasses,
+ globtype,aasmbase,aasmtai,aasmdata,cpubase,cpuinfo,cgbase,cgutils,
+ symconst,symbase,symtype,symdef,symsym;
+
+Const
+ RPNMax = 10; { I think you only need 4, but just to be safe }
+ OpMax = 25;
+
+{$if max_operands = 2}
+ {$define MAX_OPER_2}
+{$endif}
+{$if max_operands = 3}
+ {$define MAX_OPER_3}
+{$endif}
+
+{---------------------------------------------------------------------
+ Local Label Management
+---------------------------------------------------------------------}
+
+Type
+ { Each local label has this structure associated with it }
+ TLocalLabel = class(TFPHashObject)
+ Emitted : boolean;
+ constructor Create(AList:TFPHashObjectList;const n:string);
+ function Gettasmlabel:tasmlabel;
+ private
+ lab : tasmlabel;
+ end;
+
+ TLocalLabelList = class(TFPHashObjectList)
+ procedure CheckEmitted;
+ end;
+
+var
+ LocalLabelList : TLocalLabelList;
+
+function CreateLocalLabel(const s: string; var hl: tasmlabel; emit:boolean):boolean;
+Function SearchLabel(const s: string; var hl: tasmlabel;emit:boolean): boolean;
+
+
+{---------------------------------------------------------------------
+ Instruction management
+---------------------------------------------------------------------}
+
+type
+ TOprType=(OPR_NONE,OPR_CONSTANT,OPR_SYMBOL,OPR_LOCAL,
+ OPR_REFERENCE,OPR_REGISTER,OPR_REGLIST,OPR_COND,OPR_REGSET,OPR_SHIFTEROP,OPR_MODEFLAGS);
+
+ TOprRec = record
+ case typ:TOprType of
+ OPR_NONE : ();
+ OPR_CONSTANT : (val:aint);
+ OPR_SYMBOL : (symbol:tasmsymbol;symofs:aint);
+ OPR_REFERENCE : (ref:treference);
+ OPR_LOCAL : (localsym:tabstractnormalvarsym;localsymofs:aint;localindexreg:tregister;localscale:byte;localgetoffset,localforceref:boolean);
+ OPR_REGISTER : (reg:tregister);
+{$ifdef m68k}
+ OPR_REGLIST : (regset : tcpuregisterset);
+{$endif m68k}
+{$ifdef powerpc}
+ OPR_COND : (cond : tasmcond);
+{$endif powerpc}
+{$ifdef POWERPC64}
+ OPR_COND : (cond : tasmcond);
+{$endif POWERPC64}
+{$ifdef arm}
+ OPR_REGSET : (regset : tcpuregisterset; regtype: tregistertype; subreg: tsubregister);
+ OPR_SHIFTEROP : (shifterop : tshifterop);
+ OPR_COND : (cc : tasmcond);
+ OPR_MODEFLAGS : (flags : tcpumodeflags);
+{$endif arm}
+ end;
+
+ TOperand = class
+ opr : TOprRec;
+ typesize : byte;
+ hastype, { if the operand has typecasted variable }
+ hasvar : boolean; { if the operand is loaded with a variable }
+ size : TCGSize;
+ constructor create;virtual;
+ destructor destroy;override;
+ Procedure SetSize(_size:longint;force:boolean);virtual;
+ Procedure SetCorrectSize(opcode:tasmop);virtual;
+ Function SetupResult:boolean;virtual;
+ Function SetupSelf:boolean;
+ Function SetupOldEBP:boolean;
+ Function SetupVar(const s:string;GetOffset : boolean): Boolean;
+ Function CheckOperand: boolean; virtual;
+ Procedure InitRef;
+ end;
+ TCOperand = class of TOperand;
+
+ TInstruction = class
+ operands : array[1..max_operands] of toperand;
+ opcode : tasmop;
+ condition : tasmcond;
+ ops : byte;
+ labeled : boolean;
+ constructor create(optype : tcoperand);virtual;
+ destructor destroy;override;
+ { converts the instruction to an instruction how it's used by the assembler writer
+ and concats it to the passed list. The newly created item is returned if the
+ instruction was valid, otherwise nil is returned }
+ function ConcatInstruction(p:TAsmList) : tai;virtual;
+ Procedure Swapoperands;
+ end;
+
+ {---------------------------------------------------------------------}
+ { Expression parser types }
+ {---------------------------------------------------------------------}
+
+ TExprOperator = record
+ ch: char; { operator }
+ is_prefix: boolean; { was it a prefix, possible prefixes are +,- and not }
+ end;
+
+ {**********************************************************************}
+ { The following operators are supported: }
+ { '+' : addition }
+ { '-' : subtraction }
+ { '*' : multiplication }
+ { '/' : modulo division }
+ { '^' : exclusive or }
+ { '<' : shift left }
+ { '>' : shift right }
+ { '&' : bitwise and }
+ { '|' : bitwise or }
+ { '~' : bitwise complement }
+ { '%' : modulo division }
+ { nnn: longint numbers }
+ { ( and ) parenthesis }
+ {**********************************************************************}
+
+ TExprParse = class
+ public
+ Constructor create;
+ Destructor Destroy;override;
+ Function Evaluate(Expr: String): aint;
+ Function Priority(_Operator: Char): aint;
+ private
+ RPNStack : Array[1..RPNMax] of aint; { Stack For RPN calculator }
+ RPNTop : aint;
+ OpStack : Array[1..OpMax] of TExprOperator; { Operator stack For conversion }
+ OpTop : aint;
+ Procedure RPNPush(Num: aint);
+ Function RPNPop: aint;
+ Procedure RPNCalc(const token: String; prefix: boolean);
+ Procedure OpPush(_Operator: char; prefix: boolean);
+ { In reality returns TExprOperaotr }
+ Procedure OpPop(var _Operator:TExprOperator);
+ end;
+
+ { Evaluate an expression string to a aint }
+ Function CalculateExpression(const expression: string): aint;
+
+ {---------------------------------------------------------------------}
+ { String routines }
+ {---------------------------------------------------------------------}
+
+Function ParseVal(const S:String;base:byte):aint;
+Function PadZero(Var s: String; n: byte): Boolean;
+Function EscapeToPascal(const s:string): string;
+
+{---------------------------------------------------------------------
+ Symbol helper routines
+---------------------------------------------------------------------}
+
+procedure AsmSearchSym(const s:string;var srsym:tsym;var srsymtable:TSymtable);
+Function GetRecordOffsetSize(s:string;Var Offset: aint;var Size:aint; var mangledname: string; needvmtofs: boolean):boolean;
+Function SearchType(const hs:string;var size:aint): Boolean;
+Function SearchRecordType(const s:string): boolean;
+Function SearchIConstant(const s:string; var l:aint): boolean;
+
+
+{---------------------------------------------------------------------
+ Instruction generation routines
+---------------------------------------------------------------------}
+
+ Procedure ConcatPasString(p : TAsmList;s:string);
+ Procedure ConcatLabel(p: TAsmList;var l : tasmlabel);
+ Procedure ConcatConstant(p : TAsmList;value: aint; constsize:byte);
+ Procedure ConcatConstSymbol(p : TAsmList;const sym:string;symtyp:tasmsymtype;l:aint);
+ Procedure ConcatRealConstant(p : TAsmList;value: bestreal; real_typ : tfloattype);
+ Procedure ConcatString(p : TAsmList;s:string);
+ procedure ConcatAlign(p:TAsmList;l:aint);
+ Procedure ConcatPublic(p:TAsmList;const s : string);
+ Procedure ConcatLocal(p:TAsmList;const s : string);
+
+
+Implementation
+
+uses
+ SysUtils,
+ defutil,systems,verbose,globals,
+ symtable,paramgr,
+ aasmcpu,
+ procinfo;
+
+{*************************************************************************
+ TExprParse
+*************************************************************************}
+
+Constructor TExprParse.create;
+Begin
+end;
+
+
+Procedure TExprParse.RPNPush(Num : aint);
+{ Add an operand to the top of the RPN stack }
+begin
+ if RPNTop < RPNMax then
+ begin
+ Inc(RPNTop);
+ RPNStack[RPNTop]:=Num;
+ end
+ else
+ Message(asmr_e_expr_illegal);
+end;
+
+
+Function TExprParse.RPNPop : aint;
+{ Get the operand at the top of the RPN stack }
+begin
+ if RPNTop > 0 then
+ begin
+ RPNPop:=RPNStack[RPNTop];
+ Dec(RPNTop);
+ end
+ else
+ Message(asmr_e_expr_illegal);
+end;
+
+
+Procedure TExprParse.RPNCalc(const Token : String; prefix:boolean); { RPN Calculator }
+Var
+ Temp : aint;
+ n1,n2 : aint;
+ LocalError : Integer;
+begin
+ { Handle operators }
+ if (Length(Token) = 1) and (Token[1] in ['+', '-', '*', '/','&','|','%','^','~','<','>']) then
+ Case Token[1] of
+ '+' :
+ Begin
+ if not prefix then
+ RPNPush(RPNPop + RPNPop);
+ end;
+ '-' :
+ Begin
+ if prefix then
+ RPNPush(-(RPNPop))
+ else
+ begin
+ n1:=RPNPop;
+ n2:=RPNPop;
+ RPNPush(n2 - n1);
+ end;
+ end;
+ '*' : RPNPush(RPNPop * RPNPop);
+ '&' :
+ begin
+ n1:=RPNPop;
+ n2:=RPNPop;
+ RPNPush(n2 and n1);
+ end;
+ '|' :
+ begin
+ n1:=RPNPop;
+ n2:=RPNPop;
+ RPNPush(n2 or n1);
+ end;
+ '~' : RPNPush(NOT RPNPop);
+ '<' :
+ begin
+ n1:=RPNPop;
+ n2:=RPNPop;
+ RPNPush(n2 SHL n1);
+ end;
+ '>' :
+ begin
+ n1:=RPNPop;
+ n2:=RPNPop;
+ RPNPush(n2 SHR n1);
+ end;
+ '%' :
+ begin
+ Temp:=RPNPop;
+ if Temp <> 0 then
+ RPNPush(RPNPop mod Temp)
+ else
+ begin
+ Message(asmr_e_expr_zero_divide);
+ { push 1 for error recovery }
+ RPNPush(1);
+ end;
+ end;
+ '^' : RPNPush(RPNPop XOR RPNPop);
+ '/' :
+ begin
+ Temp:=RPNPop;
+ if Temp <> 0 then
+ RPNPush(RPNPop div Temp)
+ else
+ begin
+ Message(asmr_e_expr_zero_divide);
+ { push 1 for error recovery }
+ RPNPush(1);
+ end;
+ end;
+ end
+ else
+ begin
+ { Convert String to number and add to stack }
+ Val(Token, Temp, LocalError);
+ if LocalError = 0 then
+ RPNPush(Temp)
+ else
+ begin
+ Message(asmr_e_expr_illegal);
+ { push 1 for error recovery }
+ RPNPush(1);
+ end;
+ end;
+end;
+
+
+Procedure TExprParse.OpPush(_Operator : char;prefix: boolean);
+{ Add an operator onto top of the stack }
+begin
+ if OpTop < OpMax then
+ begin
+ Inc(OpTop);
+ OpStack[OpTop].ch:=_Operator;
+ OpStack[OpTop].is_prefix:=prefix;
+ end
+ else
+ Message(asmr_e_expr_illegal);
+end;
+
+
+Procedure TExprParse.OpPop(var _Operator:TExprOperator);
+{ Get operator at the top of the stack }
+begin
+ if OpTop > 0 then
+ begin
+ _Operator:=OpStack[OpTop];
+ Dec(OpTop);
+ end
+ else
+ Message(asmr_e_expr_illegal);
+end;
+
+
+Function TExprParse.Priority(_Operator : Char) : aint;
+{ Return priority of operator }
+{ The greater the priority, the higher the precedence }
+begin
+ Case _Operator OF
+ '(' :
+ Priority:=0;
+ '|','^','~' : // the lowest priority: OR, XOR, NOT
+ Priority:=0;
+ '&' : // bigger priority: AND
+ Priority:=1;
+ '+', '-' : // bigger priority: +, -
+ Priority:=2;
+ '*', '/','%','<','>' : // the highest priority: *, /, MOD, SHL, SHR
+ Priority:=3;
+ else
+ Message(asmr_e_expr_illegal);
+ end;
+end;
+
+
+Function TExprParse.Evaluate(Expr : String):aint;
+Var
+ I : longint;
+ Token : String;
+ opr : TExprOperator;
+begin
+ Evaluate:=0;
+ { Reset stacks }
+ OpTop :=0;
+ RPNTop:=0;
+ Token :='';
+ { nothing to do ? }
+ if Expr='' then
+ exit;
+ For I:=1 to Length(Expr) DO
+ begin
+ if Expr[I] in ['0'..'9'] then
+ begin { Build multi-digit numbers }
+ Token:=Token + Expr[I];
+ if I = Length(Expr) then { Send last one to calculator }
+ RPNCalc(Token,false);
+ end
+ else
+ if Expr[I] in ['+', '-', '*', '/', '(', ')','^','&','|','%','~','<','>'] then
+ begin
+ if Token <> '' then
+ begin { Send last built number to calc. }
+ RPNCalc(Token,false);
+ Token:='';
+ end;
+
+ Case Expr[I] OF
+ '(' : OpPush('(',false);
+ ')' : begin
+ While (OpTop>0) and (OpStack[OpTop].ch <> '(') DO
+ Begin
+ OpPop(opr);
+ RPNCalc(opr.ch,opr.is_prefix);
+ end;
+ OpPop(opr); { Pop off and ignore the '(' }
+ end;
+ '+','-','~' : Begin
+ { workaround for -2147483648 }
+ if (expr[I]='-') and (expr[i+1] in ['0'..'9']) then
+ begin
+ token:='-';
+ expr[i]:='+';
+ end;
+ { if start of expression then surely a prefix }
+ { or if previous char was also an operator }
+ if (I = 1) or (not (Expr[I-1] in ['0'..'9',')'])) then
+ OpPush(Expr[I],true)
+ else
+ Begin
+ { Evaluate all higher priority operators }
+ While (OpTop > 0) AND (Priority(Expr[I]) <= Priority(OpStack[OpTop].ch)) DO
+ Begin
+ OpPop(opr);
+ RPNCalc(opr.ch,opr.is_prefix);
+ end;
+ OpPush(Expr[I],false);
+ End;
+ end;
+ '*', '/',
+ '^','|','&',
+ '%','<','>' : begin
+ While (OpTop > 0) and (Priority(Expr[I]) <= Priority(OpStack[OpTop].ch)) DO
+ Begin
+ OpPop(opr);
+ RPNCalc(opr.ch,opr.is_prefix);
+ end;
+ OpPush(Expr[I],false);
+ end;
+ end; { Case }
+ end
+ else
+ Message(asmr_e_expr_illegal); { Handle bad input error }
+ end;
+
+{ Pop off the remaining operators }
+ While OpTop > 0 do
+ Begin
+ OpPop(opr);
+ RPNCalc(opr.ch,opr.is_prefix);
+ end;
+
+{ The result is stored on the top of the stack }
+ Evaluate:=RPNPop;
+end;
+
+
+Destructor TExprParse.Destroy;
+Begin
+end;
+
+
+Function CalculateExpression(const expression: string): aint;
+var
+ expr: TExprParse;
+Begin
+ expr:=TExprParse.create;
+ CalculateExpression:=expr.Evaluate(expression);
+ expr.Free;
+end;
+
+
+{*************************************************************************}
+{ String conversions/utils }
+{*************************************************************************}
+
+Function EscapeToPascal(const s:string): string;
+{ converts a C styled string - which contains escape }
+{ characters to a pascal style string. }
+var
+ i,len : aint;
+ hs : string;
+ temp : string;
+ c : char;
+Begin
+ hs:='';
+ len:=0;
+ i:=0;
+ while (i<length(s)) and (len<255) do
+ begin
+ Inc(i);
+ if (s[i]='\') and (i<length(s)) then
+ Begin
+ inc(i);
+ case s[i] of
+ '\' :
+ c:='\';
+ 'b':
+ c:=#8;
+ 'f':
+ c:=#12;
+ 'n':
+ c:=#10;
+ 'r':
+ c:=#13;
+ 't':
+ c:=#9;
+ '"':
+ c:='"';
+ '0'..'7':
+ Begin
+ temp:=s[i];
+ temp:=temp+s[i+1];
+ temp:=temp+s[i+2];
+ inc(i,2);
+ c:=chr(ParseVal(temp,8));
+ end;
+ 'x':
+ Begin
+ temp:=s[i+1];
+ temp:=temp+s[i+2];
+ inc(i,2);
+ c:=chr(ParseVal(temp,16));
+ end;
+ else
+ Begin
+ Message1(asmr_e_escape_seq_ignored,s[i]);
+ c:=s[i];
+ end;
+ end;
+ end
+ else
+ c:=s[i];
+ inc(len);
+ hs[len]:=c;
+ end;
+ hs[0]:=chr(len);
+ EscapeToPascal:=hs;
+end;
+
+
+Function ParseVal(const S:String;base:byte):aint;
+{ Converts a decimal string to aint }
+var
+ code : integer;
+ errmsg : word;
+ prefix : string[2];
+Begin
+ case base of
+ 2 :
+ begin
+ errmsg:=asmr_e_error_converting_binary;
+ prefix:='%';
+ end;
+ 8 :
+ begin
+ errmsg:=asmr_e_error_converting_octal;
+ prefix:='&';
+ end;
+ 10 :
+ begin
+ errmsg:=asmr_e_error_converting_decimal;
+ prefix:='';
+ end;
+ 16 :
+ begin
+ errmsg:=asmr_e_error_converting_hexadecimal;
+ prefix:='$';
+ end;
+ else
+ internalerror(200501202);
+ end;
+ val(prefix+s,result,code);
+ if code<>0 then
+ begin
+ val(prefix+s,aword(result),code);
+ if code<>0 then
+ begin
+ Message1(errmsg,s);
+ result:=0;
+ end;
+ end;
+end;
+
+
+Function PadZero(Var s: String; n: byte): Boolean;
+Begin
+ PadZero:=TRUE;
+ { Do some error checking first }
+ if Length(s) = n then
+ exit
+ else
+ if Length(s) > n then
+ Begin
+ PadZero:=FALSE;
+ delete(s,n+1,length(s));
+ exit;
+ end
+ else
+ PadZero:=TRUE;
+ { Fill it up with the specified character }
+ fillchar(s[length(s)+1],n-1,#0);
+ s[0]:=chr(n);
+end;
+
+
+{****************************************************************************
+ TOperand
+****************************************************************************}
+
+constructor TOperand.Create;
+begin
+ size:=OS_NO;
+ hastype:=false;
+ hasvar:=false;
+ FillChar(Opr,sizeof(Opr),0);
+end;
+
+
+destructor TOperand.destroy;
+begin
+end;
+
+
+Procedure TOperand.SetSize(_size:longint;force:boolean);
+begin
+ if force or
+ ((size = OS_NO) and (_size<=16)) then
+ Begin
+ case _size of
+ 1 : size:=OS_8;
+ 2 : size:=OS_16{ could be S_IS};
+ 4 : size:=OS_32{ could be S_IL or S_FS};
+ 8 : size:=OS_64{ could be S_D or S_FL};
+ 10 : size:=OS_F80;
+ 16 : size:=OS_128;
+ end;
+ end;
+end;
+
+
+Procedure TOperand.SetCorrectSize(opcode:tasmop);
+begin
+end;
+
+
+function TOperand.SetupResult:boolean;
+
+begin
+ SetupResult:=false;
+ { replace by correct offset. }
+ with current_procinfo.procdef do
+ if (not is_void(returndef)) then
+ begin
+ if (m_tp7 in current_settings.modeswitches) and
+ (not paramanager.ret_in_param(returndef,proccalloption)) then
+ begin
+ message(asmr_e_cannot_use_RESULT_here);
+ exit;
+ end;
+ SetupResult:=setupvar('result',false)
+ end
+ else
+ message(asmr_e_void_function);
+end;
+
+
+Function TOperand.SetupSelf:boolean;
+Begin
+ SetupSelf:=false;
+ if assigned(current_structdef) then
+ SetupSelf:=setupvar('self',false)
+ else
+ Message(asmr_e_cannot_use_SELF_outside_a_method);
+end;
+
+
+Function TOperand.SetupOldEBP:boolean;
+Begin
+ SetupOldEBP:=false;
+ if current_procinfo.procdef.parast.symtablelevel>normal_function_level then
+ SetupOldEBP:=setupvar('parentframe',false)
+ else
+ Message(asmr_e_cannot_use_OLDEBP_outside_nested_procedure);
+end;
+
+
+Function TOperand.SetupVar(const s:string;GetOffset : boolean): Boolean;
+
+ function symtable_has_localvarsyms(st:TSymtable):boolean;
+ var
+ sym : tsym;
+ i : longint;
+ begin
+ result:=false;
+ for i:=0 to st.SymList.Count-1 do
+ begin
+ sym:=tsym(st.SymList[i]);
+ if sym.typ=localvarsym then
+ begin
+ result:=true;
+ exit;
+ end;
+ end;
+ end;
+
+ procedure setconst(l:aint);
+ begin
+ { We return the address of the field, just like Delphi/TP }
+ case opr.typ of
+ OPR_NONE :
+ begin
+ opr.typ:=OPR_CONSTANT;
+ opr.val:=l;
+ end;
+ OPR_CONSTANT :
+ inc(opr.val,l);
+ OPR_REFERENCE :
+ inc(opr.ref.offset,l);
+ OPR_LOCAL :
+ inc(opr.localsymofs,l);
+ else
+ Message(asmr_e_invalid_operand_type);
+ end;
+ end;
+
+
+{ search and sets up the correct fields in the Instr record }
+{ for the NON-constant identifier passed to the routine. }
+{ if not found returns FALSE. }
+var
+ sym : tsym;
+ srsymtable : TSymtable;
+ harrdef : tarraydef;
+ indexreg : tregister;
+ l : aint;
+ plist : ppropaccesslistitem;
+Begin
+ SetupVar:=false;
+ asmsearchsym(s,sym,srsymtable);
+ if sym = nil then
+ exit;
+ if sym.typ=absolutevarsym then
+ begin
+ if (tabsolutevarsym(sym).abstyp=tovar) then
+ begin
+ { Only support simple loads }
+ plist:=tabsolutevarsym(sym).ref.firstsym;
+ if assigned(plist) and
+ (plist^.sltype=sl_load) then
+ sym:=plist^.sym
+ else
+ begin
+ Message(asmr_e_unsupported_symbol_type);
+ exit;
+ end;
+ end
+ else
+ begin
+ Message(asmr_e_unsupported_symbol_type);
+ exit;
+ end;
+ end;
+ case sym.typ of
+ fieldvarsym :
+ begin
+ if not tabstractrecordsymtable(sym.owner).is_packed then
+ setconst(tfieldvarsym(sym).fieldoffset)
+ else if tfieldvarsym(sym).fieldoffset mod 8 = 0 then
+ setconst(tfieldvarsym(sym).fieldoffset div 8)
+ else
+ Message(asmr_e_packed_element);
+ hasvar:=true;
+ SetupVar:=true;
+ end;
+ staticvarsym,
+ localvarsym,
+ paravarsym :
+ begin
+ { we always assume in asm statements that }
+ { that the variable is valid. }
+ tabstractvarsym(sym).varstate:=vs_readwritten;
+ inc(tabstractvarsym(sym).refs);
+ { variable can't be placed in a register }
+ tabstractvarsym(sym).varregable:=vr_none;
+ { and anything may happen with its address }
+ tabstractvarsym(sym).addr_taken:=true;
+ case sym.typ of
+ staticvarsym :
+ begin
+ initref;
+ opr.ref.symbol:=current_asmdata.RefAsmSymbol(tstaticvarsym(sym).mangledname);
+ end;
+ paravarsym,
+ localvarsym :
+ begin
+ if opr.typ=OPR_REFERENCE then
+ begin
+ indexreg:=opr.ref.base;
+ if opr.ref.index<>NR_NO then
+ begin
+ if indexreg=NR_NO then
+ indexreg:=opr.ref.index
+ else
+ Message(asmr_e_multiple_index);
+ end;
+ end
+ else
+ indexreg:=NR_NO;
+ opr.typ:=OPR_LOCAL;
+ if assigned(current_procinfo.parent) and
+ not(po_inline in current_procinfo.procdef.procoptions) and
+ (sym.owner<>current_procinfo.procdef.localst) and
+ (sym.owner<>current_procinfo.procdef.parast) and
+ (current_procinfo.procdef.localst.symtablelevel>normal_function_level) and
+ symtable_has_localvarsyms(current_procinfo.procdef.localst) then
+ message1(asmr_e_local_para_unreachable,s);
+ opr.localsym:=tabstractnormalvarsym(sym);
+ opr.localsymofs:=0;
+ opr.localindexreg:=indexreg;
+ opr.localscale:=0;
+ opr.localgetoffset:=GetOffset;
+ if paramanager.push_addr_param(tabstractvarsym(sym).varspez,tabstractvarsym(sym).vardef,current_procinfo.procdef.proccalloption) then
+ SetSize(sizeof(pint),false);
+ end;
+ end;
+ case tabstractvarsym(sym).vardef.typ of
+ orddef,
+ enumdef,
+ pointerdef,
+ floatdef :
+ SetSize(tabstractvarsym(sym).getsize,false);
+ arraydef :
+ begin
+ { for arrays try to get the element size, take care of
+ multiple indexes }
+ harrdef:=tarraydef(tabstractvarsym(sym).vardef);
+ while assigned(harrdef.elementdef) and
+ (harrdef.elementdef.typ=arraydef) do
+ harrdef:=tarraydef(harrdef.elementdef);
+ if not is_packed_array(harrdef) then
+ SetSize(harrdef.elesize,false)
+ else
+ begin
+ if (harrdef.elepackedbitsize mod 8) = 0 then
+ SetSize(harrdef.elepackedbitsize div 8,false)
+ end;
+ end;
+ end;
+ hasvar:=true;
+ SetupVar:=true;
+ Exit;
+ end;
+ constsym :
+ begin
+ if tconstsym(sym).consttyp=constord then
+ begin
+ setconst(tconstsym(sym).value.valueord.svalue);
+ SetupVar:=true;
+ Exit;
+ end;
+ end;
+ typesym :
+ begin
+ if ttypesym(sym).typedef.typ in [recorddef,objectdef] then
+ begin
+ setconst(0);
+ SetupVar:=TRUE;
+ Exit;
+ end;
+ end;
+ procsym :
+ begin
+ if opr.typ<>OPR_NONE then
+ Message(asmr_e_invalid_operand_type);
+ if Tprocsym(sym).ProcdefList.Count>1 then
+ Message(asmr_w_calling_overload_func);
+ l:=opr.ref.offset;
+ opr.typ:=OPR_SYMBOL;
+ opr.symbol:=current_asmdata.RefAsmSymbol(tprocdef(tprocsym(sym).ProcdefList[0]).mangledname);
+ opr.symofs:=l;
+ hasvar:=true;
+ SetupVar:=TRUE;
+ Exit;
+ end;
+ else
+ begin
+ Message(asmr_e_unsupported_symbol_type);
+ exit;
+ end;
+ end;
+end;
+
+
+procedure TOperand.InitRef;
+{*********************************************************************}
+{ Description: This routine first check if the opcode is of }
+{ type OPR_NONE, or OPR_REFERENCE , if not it gives out an error. }
+{ If the operandtype = OPR_NONE or <> OPR_REFERENCE then it sets up }
+{ the operand type to OPR_REFERENCE, as well as setting up the ref }
+{ to point to the default segment. }
+{*********************************************************************}
+var
+ l : aint;
+ hsymofs : aint;
+ hsymbol : tasmsymbol;
+ reg : tregister;
+Begin
+ case opr.typ of
+ OPR_REFERENCE :
+ exit;
+ OPR_CONSTANT :
+ begin
+ l:=opr.val;
+ opr.typ:=OPR_REFERENCE;
+ Fillchar(opr.ref,sizeof(treference),0);
+ opr.Ref.Offset:=l;
+ end;
+ OPR_NONE :
+ begin
+ opr.typ:=OPR_REFERENCE;
+ Fillchar(opr.ref,sizeof(treference),0);
+ end;
+ OPR_REGISTER :
+ begin
+ reg:=opr.reg;
+ opr.typ:=OPR_REFERENCE;
+ Fillchar(opr.ref,sizeof(treference),0);
+ opr.Ref.base:=reg;
+ end;
+ OPR_SYMBOL :
+ begin
+ hsymbol:=opr.symbol;
+ hsymofs:=opr.symofs;
+ opr.typ:=OPR_REFERENCE;
+ Fillchar(opr.ref,sizeof(treference),0);
+ opr.ref.symbol:=hsymbol;
+ opr.ref.offset:=hsymofs;
+ end;
+ else
+ begin
+ Message(asmr_e_invalid_operand_type);
+ { Recover }
+ opr.typ:=OPR_REFERENCE;
+ Fillchar(opr.ref,sizeof(treference),0);
+ end;
+ end;
+end;
+
+Function TOperand.CheckOperand: boolean;
+{*********************************************************************}
+{ Description: This routine checks if the operand is of }
+{ valid, and returns false if it isn't. Does nothing by default. }
+{*********************************************************************}
+begin
+ result:=true;
+end;
+
+
+{****************************************************************************
+ TInstruction
+****************************************************************************}
+
+constructor TInstruction.create(optype : tcoperand);
+ var
+ i : longint;
+ Begin
+ { these field are set to 0 anyways by the constructor helper (FK)
+ Opcode:=A_NONE;
+ Condition:=C_NONE;
+ Ops:=0;
+ }
+ for i:=1 to max_operands do
+ Operands[i]:=optype.create;
+ Labeled:=false;
+ end;
+
+
+destructor TInstruction.destroy;
+var
+ i : longint;
+Begin
+ for i:=1 to max_operands do
+ Operands[i].free;
+end;
+
+
+ Procedure TInstruction.Swapoperands;
+ Var
+ p : toperand;
+ Begin
+ case ops of
+ 0,1:
+ ;
+ 2 : begin
+ { 0,1 -> 1,0 }
+ p:=Operands[1];
+ Operands[1]:=Operands[2];
+ Operands[2]:=p;
+ end;
+{$ifndef MAX_OPER_2}
+ 3 : begin
+ { 0,1,2 -> 2,1,0 }
+ p:=Operands[1];
+ Operands[1]:=Operands[3];
+ Operands[3]:=p;
+ end;
+{$ifndef MAX_OPER_3}
+ 4 : begin
+ { 0,1,2,3 -> 3,2,1,0 }
+ p:=Operands[1];
+ Operands[1]:=Operands[4];
+ Operands[4]:=p;
+ p:=Operands[2];
+ Operands[2]:=Operands[3];
+ Operands[3]:=p;
+ end;
+{$endif}
+{$endif}
+ else
+ internalerror(201108142);
+ end;
+ end;
+
+
+ function TInstruction.ConcatInstruction(p:TAsmList) : tai;
+ var
+ ai : taicpu;
+ i : longint;
+ begin
+ for i:=1 to Ops do
+ operands[i].CheckOperand;
+
+ ai:=taicpu.op_none(opcode);
+ ai.Ops:=Ops;
+ ai.Allocate_oper(Ops);
+ for i:=1 to Ops do
+ with operands[i].opr do
+ begin
+ case typ of
+ OPR_CONSTANT :
+ ai.loadconst(i-1,val);
+ OPR_REGISTER:
+ ai.loadreg(i-1,reg);
+ OPR_SYMBOL:
+ ai.loadsymbol(i-1,symbol,symofs);
+ OPR_LOCAL :
+ ai.loadlocal(i-1,localsym,localsymofs,localindexreg,
+ localscale,localgetoffset,localforceref);
+ OPR_REFERENCE:
+ ai.loadref(i-1,ref);
+{$ifdef ARM}
+ OPR_REGSET:
+ ai.loadregset(i-1,regtype,subreg,regset);
+ OPR_SHIFTEROP:
+ ai.loadshifterop(i-1,shifterop);
+ OPR_COND:
+ ai.loadconditioncode(i-1,cc);
+ OPR_MODEFLAGS:
+ ai.loadmodeflags(i-1,flags);
+{$endif ARM}
+ { ignore wrong operand }
+ OPR_NONE:
+ ;
+ else
+ internalerror(200501051);
+ end;
+ end;
+ ai.SetCondition(condition);
+ { Concat the opcode or give an error }
+ if assigned(ai) then
+ p.concat(ai)
+ else
+ Message(asmr_e_invalid_opcode_and_operand);
+ result:=ai;
+ end;
+
+
+{***************************************************************************
+ TLocalLabel
+***************************************************************************}
+
+constructor TLocalLabel.create(AList:TFPHashObjectList;const n:string);
+begin
+ inherited Create(AList,n);
+ lab:=nil;
+ emitted:=false;
+end;
+
+
+function TLocalLabel.Gettasmlabel:tasmlabel;
+begin
+ if not assigned(lab) then
+ begin
+ current_asmdata.getjumplabel(lab);
+ { this label is forced to be used so it's always written }
+ lab.increfs;
+ end;
+ Gettasmlabel:=lab;
+end;
+
+
+{***************************************************************************
+ TLocalLabelList
+***************************************************************************}
+
+procedure TLocalLabelList.CheckEmitted;
+var
+ i : longint;
+ lab : TLocalLabel;
+begin
+ for i:=0 to LocalLabelList.Count-1 do
+ begin
+ lab:=TLocalLabel(LocalLabelList[i]);
+ if not lab.emitted then
+ Message1(asmr_e_unknown_label_identifier,lab.name);
+ end;
+end;
+
+
+function CreateLocalLabel(const s: string; var hl: tasmlabel; emit:boolean):boolean;
+var
+ lab : TLocalLabel;
+Begin
+ CreateLocalLabel:=true;
+{ Check if it already is defined }
+ lab:=TLocalLabel(LocalLabellist.Find(s));
+ if not assigned(lab) then
+ lab:=TLocalLabel.Create(LocalLabellist,s);
+{ set emitted flag and check for dup syms }
+ if emit then
+ begin
+ if lab.Emitted then
+ begin
+ Message1(asmr_e_dup_local_sym,lab.Name);
+ CreateLocalLabel:=false;
+ end;
+ lab.Emitted:=true;
+ end;
+ hl:=lab.Gettasmlabel;
+end;
+
+
+{****************************************************************************
+ Symbol table helper routines
+****************************************************************************}
+
+procedure AsmSearchSym(const s:string;var srsym:tsym;var srsymtable:TSymtable);
+var
+ i : integer;
+begin
+ i:=pos('.',s);
+ { allow unit.identifier }
+ if i>0 then
+ begin
+ searchsym(Copy(s,1,i-1),srsym,srsymtable);
+ if assigned(srsym) then
+ begin
+ if (srsym.typ=unitsym) and
+ (srsym.owner.symtabletype in [staticsymtable,globalsymtable]) and
+ srsym.owner.iscurrentunit then
+ searchsym_in_module(tunitsym(srsym).module,Copy(s,i+1,255),srsym,srsymtable)
+ else
+ begin
+ srsym:=nil;
+ srsymtable:=nil;
+ end;
+ end;
+ end
+ else
+ searchsym(s,srsym,srsymtable);
+end;
+
+
+Function SearchType(const hs:string;var size:aint): Boolean;
+var
+ srsym : tsym;
+ srsymtable : TSymtable;
+begin
+ result:=false;
+ size:=0;
+ asmsearchsym(hs,srsym,srsymtable);
+ if assigned(srsym) and
+ (srsym.typ=typesym) then
+ begin
+ size:=ttypesym(srsym).typedef.size;
+ result:=true;
+ end;
+end;
+
+
+
+Function SearchRecordType(const s:string): boolean;
+var
+ srsym : tsym;
+ srsymtable : TSymtable;
+Begin
+ SearchRecordType:=false;
+{ Check the constants in symtable }
+ asmsearchsym(s,srsym,srsymtable);
+ if srsym <> nil then
+ Begin
+ case srsym.typ of
+ typesym :
+ begin
+ if ttypesym(srsym).typedef.typ in [recorddef,objectdef] then
+ begin
+ SearchRecordType:=true;
+ exit;
+ end;
+ end;
+ fieldvarsym :
+ begin
+ if (tfieldvarsym(srsym).vardef.typ in [recorddef,objectdef]) then
+ begin
+ SearchRecordType:=true;
+ exit;
+ end;
+ end;
+ end;
+ end;
+end;
+
+
+Function SearchIConstant(const s:string; var l:aint): boolean;
+{**********************************************************************}
+{ Description: Searches for a CONSTANT of name s in either the local }
+{ symbol list, then in the global symbol list, and returns the value }
+{ of that constant in l. Returns TRUE if successfull, if not found, }
+{ or if the constant is not of correct type, then returns FALSE }
+{ Remarks: Also handle TRUE and FALSE returning in those cases 1 and 0 }
+{ respectively. }
+{**********************************************************************}
+var
+ srsym : tsym;
+ srsymtable : TSymtable;
+Begin
+ SearchIConstant:=false;
+{ check for TRUE or FALSE reserved words first }
+ if s = 'TRUE' then
+ Begin
+ SearchIConstant:=TRUE;
+ l:=1;
+ exit;
+ end;
+ if s = 'FALSE' then
+ Begin
+ SearchIConstant:=TRUE;
+ l:=0;
+ exit;
+ end;
+{ Check the constants in symtable }
+ asmsearchsym(s,srsym,srsymtable);
+ if srsym <> nil then
+ Begin
+ case srsym.typ of
+ constsym :
+ begin
+ if tconstsym(srsym).consttyp=constord then
+ Begin
+ l:=tconstsym(srsym).value.valueord.svalue;
+ SearchIConstant:=TRUE;
+ exit;
+ end;
+ end;
+ enumsym:
+ Begin
+ l:=tenumsym(srsym).value;
+ SearchIConstant:=TRUE;
+ exit;
+ end;
+ end;
+ end;
+end;
+
+
+Function GetRecordOffsetSize(s:string;Var Offset: aint;var Size:aint; var mangledname: string; needvmtofs: boolean):boolean;
+{ search and returns the offset and size of records/objects of the base }
+{ with field name setup in field. }
+{ returns FALSE if not found. }
+{ used when base is a variable or a typed constant name. }
+var
+ st : TSymtable;
+ harrdef : tarraydef;
+ sym : tsym;
+ srsymtable : TSymtable;
+ i : longint;
+ base : string;
+ procdef: tprocdef;
+Begin
+ GetRecordOffsetSize:=FALSE;
+ Offset:=0;
+ Size:=0;
+ mangledname:='';
+ i:=pos('.',s);
+ if i=0 then
+ i:=255;
+ base:=Copy(s,1,i-1);
+ delete(s,1,i);
+ if base='SELF' then
+ st:=current_structdef.symtable
+ else
+ begin
+ asmsearchsym(base,sym,srsymtable);
+ st:=nil;
+ { we can start with a var,type,typedconst }
+ if assigned(sym) then
+ case sym.typ of
+ staticvarsym,
+ localvarsym,
+ paravarsym :
+ st:=Tabstractvarsym(sym).vardef.GetSymtable(gs_record);
+ typesym :
+ st:=Ttypesym(sym).typedef.GetSymtable(gs_record);
+ end
+ else
+ s:='';
+ end;
+ { now walk all recordsymtables }
+ while assigned(st) and (s<>'') do
+ begin
+ { load next field in base }
+ i:=pos('.',s);
+ if i=0 then
+ i:=255;
+ base:=Copy(s,1,i-1);
+ delete(s,1,i);
+ sym:=search_struct_member(tabstractrecorddef(st.defowner),base);
+ if not assigned(sym) then
+ begin
+ GetRecordOffsetSize:=false;
+ exit;
+ end;
+ st:=nil;
+ case sym.typ of
+ fieldvarsym :
+ with Tfieldvarsym(sym) do
+ begin
+ if not tabstractrecordsymtable(sym.owner).is_packed then
+ inc(Offset,fieldoffset)
+ else if tfieldvarsym(sym).fieldoffset mod 8 = 0 then
+ inc(Offset,fieldoffset div 8)
+ else
+ Message(asmr_e_packed_element);
+ size:=getsize;
+ case vardef.typ of
+ arraydef :
+ begin
+ { for arrays try to get the element size, take care of
+ multiple indexes }
+ harrdef:=tarraydef(vardef);
+ while assigned(harrdef.elementdef) and
+ (harrdef.elementdef.typ=arraydef) do
+ harrdef:=tarraydef(harrdef.elementdef);
+ if not is_packed_array(harrdef) then
+ size:=harrdef.elesize
+ else
+ begin
+ if (harrdef.elepackedbitsize mod 8) <> 0 then
+ Message(asmr_e_packed_element);
+ size := (harrdef.elepackedbitsize + 7) div 8;
+ end;
+ end;
+ recorddef :
+ st:=trecorddef(vardef).symtable;
+ objectdef :
+ st:=tobjectdef(vardef).symtable;
+ end;
+ end;
+ procsym:
+ begin
+ st:=nil;
+ if Tprocsym(sym).ProcdefList.Count>1 then
+ Message(asmr_w_calling_overload_func);
+ procdef:=tprocdef(tprocsym(sym).ProcdefList[0]);
+ if (not needvmtofs) then
+ begin
+ mangledname:=procdef.mangledname;
+ end
+ else
+ begin
+ { can only get the vmtoffset of virtual methods }
+ if not(po_virtualmethod in procdef.procoptions) or
+ is_objectpascal_helper(procdef.struct) then
+ Message1(asmr_e_no_vmtoffset_possible,FullTypeName(procdef,nil))
+ else
+ begin
+ { size = sizeof(target_system_pointer) }
+ size:=sizeof(pint);
+ offset:=tobjectdef(procdef.struct).vmtmethodoffset(procdef.extnumber)
+ end;
+ end;
+ { if something comes after the procsym, it's invalid assembler syntax }
+ GetRecordOffsetSize:=(s='');
+ exit;
+ end;
+ end;
+ end;
+ { Support Field.Type as typecasting }
+ if (st=nil) and (s<>'') then
+ begin
+ asmsearchsym(s,sym,srsymtable);
+ if assigned(sym) and (sym.typ=typesym) then
+ begin
+ size:=ttypesym(sym).typedef.size;
+ s:=''
+ end;
+ end;
+ GetRecordOffsetSize:=(s='');
+end;
+
+
+Function SearchLabel(const s: string; var hl: tasmlabel;emit:boolean): boolean;
+var
+ sym : tsym;
+ srsymtable : TSymtable;
+ hs : string;
+Begin
+ hl:=nil;
+ SearchLabel:=false;
+{ Check for pascal labels, which are case insensetive }
+ hs:=upper(s);
+ asmsearchsym(hs,sym,srsymtable);
+ if sym=nil then
+ exit;
+ case sym.typ of
+ labelsym :
+ begin
+ if symtablestack.top.symtablelevel<>srsymtable.symtablelevel then
+ begin
+ Tlabelsym(sym).nonlocal:=true;
+ if emit then
+ exclude(current_procinfo.procdef.procoptions,po_inline);
+ end;
+ if not(assigned(tlabelsym(sym).asmblocklabel)) then
+ if Tlabelsym(sym).nonlocal then
+ current_asmdata.getglobaljumplabel(tlabelsym(sym).asmblocklabel)
+ else
+ current_asmdata.getjumplabel(tlabelsym(sym).asmblocklabel);
+ hl:=tlabelsym(sym).asmblocklabel;
+ if emit then
+ tlabelsym(sym).defined:=true
+ else
+ tlabelsym(sym).used:=true;
+ SearchLabel:=true;
+ end;
+ end;
+end;
+
+
+ {*************************************************************************}
+ { Instruction Generation Utilities }
+ {*************************************************************************}
+
+
+ Procedure ConcatString(p : TAsmList;s:string);
+ {*********************************************************************}
+ { PROCEDURE ConcatString(s:string); }
+ { Description: This routine adds the character chain pointed to in }
+ { s to the instruction linked list. }
+ {*********************************************************************}
+ Var
+ pc: PChar;
+ Begin
+ getmem(pc,length(s)+1);
+ p.concat(Tai_string.Create_pchar(strpcopy(pc,s),length(s)));
+ end;
+
+ Procedure ConcatPasString(p : TAsmList;s:string);
+ {*********************************************************************}
+ { PROCEDURE ConcatPasString(s:string); }
+ { Description: This routine adds the character chain pointed to in }
+ { s to the instruction linked list, contrary to ConcatString it }
+ { uses a pascal style string, so it conserves null characters. }
+ {*********************************************************************}
+ Begin
+ p.concat(Tai_string.Create(s));
+ end;
+
+
+Procedure ConcatConstant(p: TAsmList; value: aint; constsize:byte);
+{*********************************************************************}
+{ PROCEDURE ConcatConstant(value: aint; maxvalue: aint); }
+{ Description: This routine adds the value constant to the current }
+{ instruction linked list. }
+{ maxvalue -> indicates the size of the data to initialize: }
+{ $ff -> create a byte node. }
+{ $ffff -> create a word node. }
+{ $ffffffff -> create a dword node. }
+{*********************************************************************}
+var
+ rangelo,rangehi : int64;
+Begin
+ case constsize of
+ 1 :
+ begin
+ p.concat(Tai_const.Create_8bit(byte(value)));
+ rangelo:=low(shortint);
+ rangehi:=high(byte);
+ end;
+ 2 :
+ begin
+ p.concat(Tai_const.Create_16bit(word(value)));
+ rangelo:=low(smallint);
+ rangehi:=high(word);
+ end;
+ 4 :
+ begin
+ p.concat(Tai_const.Create_32bit(longint(value)));
+ rangelo:=low(longint);
+ rangehi:=high(cardinal);
+ end;
+ 8 :
+ begin
+ p.concat(Tai_const.Create_64bit(int64(value)));
+ rangelo:=0;
+ rangehi:=0;
+ end;
+ else
+ internalerror(200405011);
+ end;
+ { check for out of bounds }
+ if (rangelo<>0) and
+ ((value>rangehi) or (value<rangelo)) then
+ Message(asmr_e_constant_out_of_bounds);
+end;
+
+
+ Procedure ConcatConstSymbol(p : TAsmList;const sym:string;symtyp:tasmsymtype;l:aint);
+ begin
+ p.concat(Tai_const.Createname(sym,l));
+ end;
+
+
+ Procedure ConcatRealConstant(p : TAsmList;value: bestreal; real_typ : tfloattype);
+ {***********************************************************************}
+ { PROCEDURE ConcatRealConstant(value: bestreal; real_typ : tfloattype); }
+ { Description: This routine adds the value constant to the current }
+ { instruction linked list. }
+ { real_typ -> indicates the type of the real data to initialize: }
+ { s32real -> create a single node. }
+ { s64real -> create a double node. }
+ { s80real -> create an extended node. }
+ { s64bit -> create a comp node. }
+ { f32bit -> create a fixed node. (not used normally) }
+ {***********************************************************************}
+ Begin
+ case real_typ of
+ s32real : p.concat(Tai_real_32bit.Create(value));
+ s64real :
+{$ifdef ARM}
+ if is_double_hilo_swapped then
+ p.concat(Tai_real_64bit.Create_hiloswapped(value))
+ else
+{$endif ARM}
+ p.concat(Tai_real_64bit.Create(value));
+ s80real : p.concat(Tai_real_80bit.Create(value,s80floattype.size));
+ sc80real : p.concat(Tai_real_80bit.Create(value,sc80floattype.size));
+ s64comp : p.concat(Tai_comp_64bit.Create(trunc(value)));
+ end;
+ end;
+
+ Procedure ConcatLabel(p: TAsmList;var l : tasmlabel);
+ {*********************************************************************}
+ { PROCEDURE ConcatLabel }
+ { Description: This routine either emits a label or a labeled }
+ { instruction to the linked list of instructions. }
+ {*********************************************************************}
+ begin
+ p.concat(Tai_label.Create(l));
+ end;
+
+ procedure ConcatAlign(p:TAsmList;l:aint);
+ {*********************************************************************}
+ { PROCEDURE ConcatPublic }
+ { Description: This routine emits an global definition to the }
+ { linked list of instructions.(used by AT&T styled asm) }
+ {*********************************************************************}
+ begin
+ p.concat(Tai_align.Create(l));
+ end;
+
+ procedure ConcatPublic(p:TAsmList;const s : string);
+ {*********************************************************************}
+ { PROCEDURE ConcatPublic }
+ { Description: This routine emits an global definition to the }
+ { linked list of instructions.(used by AT&T styled asm) }
+ {*********************************************************************}
+ begin
+ p.concat(Tai_symbol.Createname_global(s,AT_LABEL,0));
+ end;
+
+ procedure ConcatLocal(p:TAsmList;const s : string);
+ {*********************************************************************}
+ { PROCEDURE ConcatLocal }
+ { Description: This routine emits an local definition to the }
+ { linked list of instructions. }
+ {*********************************************************************}
+ begin
+ p.concat(Tai_symbol.Createname(s,AT_LABEL,0));
+ end;
+
+
+end.
diff --git a/closures/compiler/regvars.pas b/closures/compiler/regvars.pas
new file mode 100644
index 0000000000..1576d25536
--- /dev/null
+++ b/closures/compiler/regvars.pas
@@ -0,0 +1,666 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl and Jonas Maebe
+
+ This unit handles register variable allocation
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit regvars;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ aasmbase,aasmtai,aasmdata,aasmcpu,
+ node,
+ symsym,
+ cpubase, cgbase, tgobj;
+
+{$ifdef OLDREGVARS}
+ procedure assign_regvars(p: tnode);
+ procedure load_regvars(asml: TAsmList; p: tnode);
+ procedure cleanup_regvars(asml: TAsmList);
+ procedure store_regvar(asml: TAsmList; reg: tregister);
+ procedure load_regvar(asml: TAsmList; vsym: tvarsym);
+ procedure load_regvar_reg(asml: TAsmList; reg: tregister);
+ procedure load_all_regvars(asml: TAsmList);
+ procedure free_regvars(list: TAsmList);
+{ procedure translate_regvars(list: TAsmList); }
+{$endif OLDREGVARS}
+
+{$ifdef i386}
+(*
+ procedure sync_regvars_other(list1, list2: TAsmList; const regvarsloaded1,
+ regvarsloaded2: regvarother_booleanarray);
+ procedure sync_regvars_int(list1, list2: TAsmList; const regvarsloaded1,
+ regvarsloaded2: Tsuperregisterset);
+*)
+{$endif i386}
+
+implementation
+
+ uses
+ globtype,systems,comphook,
+ cutils,cclasses,verbose,globals,
+ psub,
+ symconst,symbase,symtype,symdef,paramgr,defutil,
+ cpuinfo,cgobj,procinfo;
+
+{$ifdef OLDREGVARS}
+ procedure searchregvars(p : tnamedindexitem;arg:pointer);
+ var
+ i,j,k : longint;
+ parasym : boolean;
+ begin
+ parasym:=pboolean(arg)^;
+ if (tsym(p).typ=varsym) and ((tvarsym(p).varregable <> vr_none) or
+ ((tvarsym(p).varspez in [vs_var,vs_const,vs_out,vs_constref]) and
+ paramanager.push_addr_param(tvarsym(p).varspez,tvarsym(p).vardef,current_procinfo.procdef.proccalloption))) and
+ not tvarsym(p).vardef.needs_inittable then
+ begin
+ j:=tvarsym(p).refs;
+ { walk through all momentary register variables }
+ for i:=1 to maxvarregs do
+ begin
+ with pregvarinfo(current_procinfo.procdef.regvarinfo)^ do
+ if ((regvars[i]=nil) or (j>regvars_refs[i])) and (j>0) then
+ begin
+ for k:=maxvarregs-1 downto i do
+ begin
+ regvars[k+1]:=regvars[k];
+ regvars_para[k+1]:=regvars_para[k];
+ regvars_refs[k+1]:=regvars_refs[k];
+ end;
+ { calc the new refs
+ tvarsym(p).refs:=j; }
+ regvars[i]:=tsym(p);
+ regvars_para[i]:=parasym;
+ regvars_refs[i]:=j;
+ break;
+ end;
+ end;
+ end;
+ end;
+
+
+ procedure searchfpuregvars(p : tnamedindexitem;arg:pointer);
+ var
+ i,j,k : longint;
+ parasym : boolean;
+ begin
+ parasym:=pboolean(arg)^;
+ if (tsym(p).typ=varsym) and (tvarsym(p).varregable <> vr_none) then
+ begin
+ j:=tvarsym(p).refs;
+ { parameter get a less value }
+ { walk through all momentary register variables }
+ for i:=1 to maxfpuvarregs do
+ begin
+ with pregvarinfo(current_procinfo.procdef.regvarinfo)^ do
+ if ((fpuregvars[i]=nil) or (j>fpuregvars_refs[i])) and (j>0) then
+ begin
+ for k:=maxfpuvarregs-1 downto i do
+ begin
+ fpuregvars[k+1]:=fpuregvars[k];
+ fpuregvars_para[k+1]:=fpuregvars_para[k];
+ fpuregvars_refs[k+1]:=fpuregvars_refs[k];
+ end;
+ { calc the new refs
+ tvarsym(p).refs:=j; }
+ fpuregvars[i]:=tsym(p);
+ fpuregvars_para[i]:=parasym;
+ fpuregvars_refs[i]:=j;
+ break;
+ end;
+ end;
+ end;
+ end;
+
+ procedure assign_regvars(p: tnode);
+ { register variables }
+ var
+{$ifndef i386}
+ hp: tparaitem;
+{$endif i386}
+ regvarinfo: pregvarinfo;
+ i: longint;
+ parasym : boolean;
+ siz : tcgsize;
+ begin
+ { max. optimizations }
+ { only if no asm is used }
+ { and no try statement }
+ if (cs_opt_regvar in current_settings.optimizerswitches) and
+ { we have to store regvars back to memory in this case (the nested }
+ { procedures can access the variables of the parent) }
+ (not current_procinfo.has_nestedprocs) and
+ not(pi_has_assembler_block in current_procinfo.flags) and
+ not(pi_uses_exceptions in current_procinfo.flags) then
+ begin
+ new(regvarinfo);
+ fillchar(regvarinfo^,sizeof(regvarinfo^),0);
+ current_procinfo.procdef.regvarinfo := regvarinfo;
+ if (p.registersint<maxvarregs) then
+ begin
+ parasym:=false;
+ symtablestack.foreach_static(searchregvars,@parasym);
+ { copy parameter into a register ? }
+ parasym:=true;
+ symtablestack.next.foreach_static(searchregvars,@parasym);
+ { hold needed registers free }
+ for i:=maxvarregs downto maxvarregs-p.registersint+1 do
+ begin
+ regvarinfo^.regvars[i]:=nil;
+ regvarinfo^.regvars_para[i] := false;
+ end;
+ { now assign register }
+ for i:=1 to maxvarregs-p.registersint do
+ begin
+ if assigned(regvarinfo^.regvars[i]) and
+ { currently we assume we can use registers for all }
+ { regvars if procedure does no call }
+ (not(pi_do_call in current_procinfo.flags) or
+ { otherwise, demand some (arbitrary) minimum usage }
+ (tvarsym(regvarinfo^.regvars[i]).refs > 100)) then
+ begin
+ { register is no longer available for }
+ { expressions }
+ { search the register which is the most }
+ { unused }
+
+ { call by reference/const ? }
+ if paramanager.push_addr_param(tvarsym(regvarinfo^.regvars[i]).varspez,tvarsym(regvarinfo^.regvars[i]).vardef,current_procinfo.procdef.proccalloption) then
+ siz:=OS_32
+ else
+ if (tvarsym(regvarinfo^.regvars[i]).vardef.typ in [orddef,enumdef]) and
+ (tvarsym(regvarinfo^.regvars[i]).vardef.size=1) then
+ siz:=OS_8
+ else
+ if (tvarsym(regvarinfo^.regvars[i]).vardef.typ in [orddef,enumdef]) and
+ (tvarsym(regvarinfo^.regvars[i]).vardef.size=2) then
+ siz:=OS_16
+ else
+ siz:=OS_32;
+
+ { allocate a register for this regvar }
+ tvarsym(regvarinfo^.regvars[i]).localloc.register:=cg.getintregister(current_asmdata.CurrAsmList,siz);
+ tvarsym(regvarinfo^.regvars[i]).localloc.loc:=LOC_REGISTER;
+ { and make sure it can't be freed }
+{ rg.makeregvarint(getsupreg(regvarinfo^.regvars[i].localloc.register));}
+ end
+ else
+ begin
+ regvarinfo^.regvars[i] := nil;
+ regvarinfo^.regvars_para[i] := false;
+ end;
+ end;
+ end;
+ if ((p.registersfpu+1)<maxfpuvarregs) then
+ begin
+ parasym:=false;
+ symtablestack.foreach_static(searchfpuregvars,@parasym);
+{$ifndef i386}
+ { this code should be never enabled because }
+ { 1. the caller loads parameters into registers }
+ { 2. (later) the CSE loads a parameter into a }
+ { register, if necessary }
+ { (FK) }
+ { copy parameter into a register ? }
+ parasym:=true;
+ symtablestack.next.foreach_static(searchregvars,@parasym);
+{$endif i386}
+ { hold needed registers free }
+
+ { in non leaf procedures we must be very careful }
+ { with assigning registers }
+{$ifdef i386}
+ if current_settings.maxfpuregisters=-1 then
+ begin
+ if (pi_do_call in current_procinfo.flags) then
+ begin
+ for i:=maxfpuvarregs downto 2 do
+ regvarinfo^.fpuregvars[i]:=nil;
+ end
+ else
+{$endif i386}
+ begin
+ for i:=maxfpuvarregs downto maxfpuvarregs-p.registersfpu do
+ regvarinfo^.fpuregvars[i]:=nil;
+ end;
+{$ifdef i386}
+ end
+ else
+ begin
+ for i:=current_settings.maxfpuregisters+1 to maxfpuvarregs do
+ regvarinfo^.fpuregvars[i]:=nil;
+ end;
+{$endif i386}
+ { now assign register }
+ for i:=1 to maxfpuvarregs do
+ begin
+ if assigned(regvarinfo^.fpuregvars[i]) then
+ begin
+{$ifdef i386}
+ { reserve place on the FPU stack }
+ {$error fixme x86 fpuregvars}
+{ regvarinfo^.fpuregvars[i].localloc.register:=trgcpu(rg).correct_fpuregister(NR_ST0,i);}
+{$else i386}
+{$ifdef x86_64}
+{$endif x86_64}
+ begin
+ tvarsym(regvarinfo^.fpuregvars[i]).localloc.register:=cg.getfpuregister(current_asmdata.CurrAsmList,OS_F64);
+ tvarsym(regvarinfo^.fpuregvars[i]).localloc.loc:=LOC_FPUREGISTER;
+{ rg.makeregvarother(regvarinfo^.fpuregvars[i].localloc.register);}
+ end;
+{$endif i386}
+ end;
+ end;
+ end;
+ end;
+ end;
+
+
+
+ procedure store_regvar(asml: TAsmList; reg: tregister);
+ var
+ i: longint;
+ cgsize : tcgsize;
+ r : tregister;
+ hr: treference;
+ regvarinfo: pregvarinfo;
+ vsym: tvarsym;
+ regidx : tregisterindex;
+ supreg : tsuperregister;
+ begin
+{$ifdef i386}
+ regvarinfo := pregvarinfo(current_procinfo.procdef.regvarinfo);
+ if not assigned(regvarinfo) then
+ exit;
+ if getregtype(reg)=R_INTREGISTER then
+ begin
+ supreg:=getsupreg(reg);
+ for i := 1 to maxvarregs do
+ if assigned(regvarinfo^.regvars[i]) and
+ (getsupreg(tvarsym(regvarinfo^.regvars[i]).localloc.register)=supreg) then
+ begin
+ { TODO: fixme regvar_loaded_int}
+(* if supreg in rg.regvar_loaded_int then
+ begin
+ vsym := tvarsym(regvarinfo^.regvars[i]);
+ { we only have to store the regvar back to memory if it's }
+ { possible that it's been modified (JM) }
+ if not(vsym.varspez in [vs_const,vs_var,vs_out]) then
+ begin
+{ TODO: FIXME Check vsym.localloc for regvars}
+// reference_reset_base(hr,current_procinfo.framepointer,vsym.adjusted_address);
+ cgsize:=def_cgsize(vsym.vardef);
+ cg.a_load_reg_ref(asml,cgsize,cgsize,vsym.localloc.register,hr);
+ end;
+ asml.concat(tai_regalloc.dealloc(vsym.localloc.register));
+ exclude(rg.regvar_loaded_int,supreg);
+ end;
+*)
+ break;
+ end;
+ end
+ else
+ begin
+ for i := 1 to maxvarregs do
+ if assigned(regvarinfo^.regvars[i]) then
+ begin
+ { TODO: fixme regvars}
+(*
+ r:=rg.makeregsize(regvarinfo^.regvars[i].localloc.register,OS_INT);
+ if (r = reg) then
+ begin
+ regidx:=findreg_by_number(r);
+ if rg.regvar_loaded_other[regidx] then
+ begin
+ vsym := tvarsym(regvarinfo^.regvars[i]);
+ { we only have to store the regvar back to memory if it's }
+ { possible that it's been modified (JM) }
+ if not(vsym.varspez in [vs_const,vs_var,vs_out]) then
+ begin
+{ TODO: FIXME Check vsym.localloc for regvars}
+// reference_reset_base(hr,current_procinfo.framepointer,vsym.adjusted_address);
+ cgsize:=def_cgsize(vsym.vardef);
+ cg.a_load_reg_ref(asml,cgsize,cgsize,vsym.localloc.register,hr);
+ end;
+ asml.concat(tai_regalloc.dealloc(vsym.localloc.register));
+ rg.regvar_loaded_other[regidx] := false;
+ end;
+ break;
+ end;
+*)
+ end;
+ end;
+{$endif i386}
+ end;
+
+ procedure load_regvar(asml: TAsmList; vsym: tvarsym);
+ var
+ hr: treference;
+ opsize: tcgsize;
+ r,
+ reg : tregister;
+ regidx : tregisterindex;
+ begin
+{$ifndef i386}
+ exit;
+{$endif i386}
+ reg:=vsym.localloc.register;
+ { TODO: fixme regvars}
+(*
+ if getregtype(reg)=R_INTREGISTER then
+ begin
+
+ if not(getsupreg(reg) in rg.regvar_loaded_int) then
+ begin
+ asml.concat(tai_regalloc.alloc(reg));
+{ TODO: FIXME Check vsym.localloc for regvars}
+// reference_reset_base(hr,current_procinfo.framepointer,vsym.adjusted_address);
+ if paramanager.push_addr_param(vsym.varspez,vsym.vardef,current_procinfo.procdef.proccalloption) then
+ opsize := OS_ADDR
+ else
+ opsize := def_cgsize(vsym.vardef);
+ cg.a_load_ref_reg(asml,opsize,opsize,hr,reg);
+ include(rg.regvar_loaded_int,getsupreg(reg));
+ end;
+ end
+ else
+ begin
+ r:=rg.makeregsize(reg,OS_INT);
+ regidx:=findreg_by_number(r);
+ if not rg.regvar_loaded_other[regidx] then
+ begin
+ asml.concat(tai_regalloc.alloc(reg));
+{ TODO: FIXME Check vsym.localloc for regvars}
+// reference_reset_base(hr,current_procinfo.framepointer,vsym.adjusted_address);
+ if paramanager.push_addr_param(vsym.varspez,vsym.vardef,current_procinfo.procdef.proccalloption) then
+ opsize := OS_ADDR
+ else
+ opsize := def_cgsize(vsym.vardef);
+ cg.a_load_ref_reg(asml,opsize,opsize,hr,reg);
+ rg.regvar_loaded_other[regidx] := true;
+ end;
+ end;
+*)
+ end;
+
+ procedure load_regvar_reg(asml: TAsmList; reg: tregister);
+ var
+ i: longint;
+ regvarinfo: pregvarinfo;
+ reg_spare : tregister;
+ supreg : tsuperregister;
+ begin
+{
+ regvarinfo := pregvarinfo(current_procinfo.procdef.regvarinfo);
+ if not assigned(regvarinfo) then
+ exit;
+ if getregtype(reg)=R_INTREGISTER then
+ begin
+ supreg:=getsupreg(reg);
+ for i := 1 to maxvarregs do
+ if assigned(regvarinfo^.regvars[i]) and
+ (getsupreg(regvarinfo^.regvars[i].localloc.register) = supreg) then
+ load_regvar(asml,tvarsym(regvarinfo^.regvars[i]))
+ end
+ else
+ begin
+ reg_spare := cg.makeregsize(reg,OS_INT);
+ for i := 1 to maxvarregs do
+ if assigned(regvarinfo^.regvars[i]) and
+ (cg.makeregsize(regvarinfo^.regvars[i].localloc.register,OS_INT) = reg_spare) then
+ load_regvar(asml,tvarsym(regvarinfo^.regvars[i]))
+ end;
+}
+ end;
+
+ procedure load_all_regvars(asml: TAsmList);
+{
+ var
+ i: longint;
+ regvarinfo: pregvarinfo;
+}
+ begin
+{
+ regvarinfo := pregvarinfo(current_procinfo.procdef.regvarinfo);
+ if not assigned(regvarinfo) then
+ exit;
+ for i := 1 to maxvarregs do
+ if assigned(regvarinfo^.regvars[i]) then
+ load_regvar(asml,tvarsym(regvarinfo^.regvars[i]))
+}
+ end;
+
+
+ procedure load_regvars(asml: TAsmList; p: tnode);
+ var
+ i: longint;
+ regvarinfo: pregvarinfo;
+ begin
+ if (cs_opt_regvar in current_settings.optimizerswitches) and
+ not(pi_has_assembler_block in current_procinfo.flags) and
+ not(pi_uses_exceptions in current_procinfo.flags) then
+ begin
+ regvarinfo := pregvarinfo(current_procinfo.procdef.regvarinfo);
+ { can happen when inlining assembler procedures (JM) }
+ if not assigned(regvarinfo) then
+ exit;
+ for i:=1 to maxfpuvarregs do
+ begin
+ if assigned(regvarinfo^.fpuregvars[i]) then
+ begin
+{$ifdef i386}
+ { reserve place on the FPU stack }
+ { TODO: fixme fpustack}
+(*
+ regvarinfo^.fpuregvars[i].localloc.register:=trgcpu(rg).correct_fpuregister(NR_ST0,i-1);
+*)
+ asml.concat(Taicpu.op_none(A_FLDZ,S_NO));
+{$endif i386}
+ end;
+ end;
+{$ifdef i386}
+ if assigned(p) then
+ if cs_asm_source in current_settings.globalswitches then
+ asml.insert(tai_comment.Create(strpnew(tostr(p.registersfpu)+
+ ' registers on FPU stack used by temp. expressions')));
+{$endif i386}
+{
+ for i:=1 to maxfpuvarregs do
+ begin
+ if assigned(regvarinfo^.fpuregvars[i]) then
+ begin
+ if cs_asm_source in current_settings.globalswitches then
+ asml.insert(tai_comment.Create(strpnew(regvarinfo^.fpuregvars[i].name+
+ ' with weight '+tostr(regvarinfo^.fpuregvars[i].refs)+' assigned to register '+
+ std_regname(regvarinfo^.fpuregvars[i].localloc.register))));
+ if (status.verbosity and v_debug)=v_debug then
+ Message3(cg_d_register_weight,std_regname(regvarinfo^.fpuregvars[i].localloc.register),
+ tostr(regvarinfo^.fpuregvars[i].refs),regvarinfo^.fpuregvars[i].name);
+ end;
+ end;
+ if cs_asm_source in current_settings.globalswitches then
+ asml.insert(tai_comment.Create(strpnew('Register variable assignment:')));
+}
+ end;
+ end;
+
+{$ifdef i386}
+(*
+ procedure sync_regvars_other(list1, list2: TAsmList; const regvarsloaded1,
+ regvarsloaded2: regvarother_booleanarray);
+ var
+ counter: tregisterindex;
+ begin
+ for counter := low(rg.regvar_loaded_other) to high(rg.regvar_loaded_other) do
+ begin
+ rg.regvar_loaded_other[counter] := regvarsloaded1[counter] and
+ regvarsloaded2[counter];
+ if regvarsloaded1[counter] xor regvarsloaded2[counter] then
+ if regvarsloaded1[counter] then
+ load_regvar_reg(list2,counter)
+ else
+ load_regvar_reg(list1,counter);
+ end;
+ end;
+
+
+ procedure sync_regvars_int(list1, list2: TAsmList; const regvarsloaded1,
+ regvarsloaded2: Tsuperregisterset);
+ var
+ i : longint;
+ r : tregister;
+ begin
+ for i:=1 to maxvarregs do
+ begin
+ r:=newreg(R_INTREGISTER,varregs[i],R_SUBWHOLE);
+ if (varregs[i] in regvarsloaded1) and
+ not(varregs[i] in regvarsloaded2) then
+ load_regvar_reg(list2,r)
+ else
+ if (varregs[i] in regvarsloaded2) and
+ not(varregs[i] in regvarsloaded1) then
+ load_regvar_reg(list1,r);
+ end;
+ end;
+*)
+{$endif i386}
+
+
+ procedure cleanup_regvars(asml: TAsmList);
+ var
+ i: longint;
+ reg : tregister;
+ regidx : tregisterindex;
+ begin
+ { can happen when inlining assembler procedures (JM) }
+ if not assigned(current_procinfo.procdef.regvarinfo) then
+ exit;
+ if (cs_opt_regvar in current_settings.optimizerswitches) and
+ not(pi_has_assembler_block in current_procinfo.flags) and
+ not(pi_uses_exceptions in current_procinfo.flags) then
+ with pregvarinfo(current_procinfo.procdef.regvarinfo)^ do
+ begin
+{$ifdef i386}
+ for i:=1 to maxfpuvarregs do
+ if assigned(fpuregvars[i]) then
+ { ... and clean it up }
+ asml.concat(Taicpu.op_reg(A_FSTP,S_NO,NR_ST0));
+{$endif i386}
+(*
+ for i := 1 to maxvarregs do
+ begin
+ if assigned(regvars[i]) then
+ begin
+ reg:=regvars[i].localloc.register;
+ if getregtype(reg)=R_INTREGISTER then
+ begin
+ end
+ else
+ begin
+ reg:=cg.makeregsize(reg,OS_INT);
+ regidx:=findreg_by_number(reg);
+ { TODO: fixme regvar dealloc}
+{
+ if (rg.regvar_loaded_other[regidx]) then
+ asml.concat(tai_regalloc.dealloc(reg));
+}
+ end;
+ end;
+ end;
+*)
+ end;
+ end;
+
+{
+
+ Note: this one can't really be "fixed": register colouring happens after
+ stabs generation. It could still be useful to generate the "var X is
+ assigned to register Y with weight ZZZ" messages though
+
+ procedure translate_regvars(list: TAsmList);
+ var
+ i: longint;
+ r: tregister;
+ begin
+ if not assigned(current_procinfo.procdef.regvarinfo) then
+ exit;
+ with pregvarinfo(current_procinfo.procdef.regvarinfo)^ do
+ begin
+ for i := 1 to maxvarregs do
+ if assigned(regvars[i]) then
+ begin
+ cg.rg[R_INTREGISTER].translate_register(tvarsym(regvars[i]).localloc.register);
+ r:=tvarsym(regvars[i]).localloc.register;
+ if cs_asm_source in current_settings.globalswitches then
+ list.insert(tai_comment.Create(strpnew(tvarsym(regvars[i]).name+
+ ' with weight '+tostr(tvarsym(regvars[i]).refs)+' assigned to register '+
+ std_regname(r))));
+ Message3(cg_d_register_weight,std_regname(r),
+ tostr(tvarsym(regvars[i]).refs),tvarsym(regvars[i]).name);
+ end;
+ for i := 1 to maxfpuvarregs do
+ if assigned(fpuregvars[i]) then
+ begin
+ cg.rg[R_FPUREGISTER].translate_register(tvarsym(regvars[i]).localloc.register);
+ r:=tvarsym(fpuregvars[i]).localloc.register;
+ if cs_asm_source in current_settings.globalswitches then
+ list.insert(tai_comment.Create(strpnew(tvarsym(fpuregvars[i]).name+
+ ' with weight '+tostr(tvarsym(fpuregvars[i]).refs)+' assigned to register '+
+ std_regname(r))));
+ Message3(cg_d_register_weight,std_regname(r),
+ tostr(tvarsym(fpuregvars[i]).refs),tvarsym(fpuregvars[i]).name);
+ end;
+ end;
+ end;
+}
+
+ procedure free_regvars(list: TAsmList);
+ var
+ i: longint;
+ reg: tregister;
+ size: tcgsize;
+ begin
+ if not assigned(current_procinfo.procdef.regvarinfo) then
+ exit;
+ with pregvarinfo(current_procinfo.procdef.regvarinfo)^ do
+ begin
+ for i := 1 to maxvarregs do
+ if assigned(regvars[i]) then
+ begin
+ reg:=cg.makeregsize(list,tvarsym(regvars[i]).localloc.register,OS_INT);
+ cg.a_load_reg_reg(list,OS_INT,OS_INT,reg,reg);
+ end;
+ for i := 1 to maxfpuvarregs do
+ if assigned(fpuregvars[i]) then
+ begin
+ reg:=tvarsym(fpuregvars[i]).localloc.register;
+ size:=reg_cgsize(reg);
+ cg.a_loadfpu_reg_reg(list,size,reg,reg);
+ end;
+ end;
+ end;
+
+
+{$endif OLDREGVARS}
+
+
+end.
diff --git a/closures/compiler/rescmn.pas b/closures/compiler/rescmn.pas
new file mode 100644
index 0000000000..eee102d902
--- /dev/null
+++ b/closures/compiler/rescmn.pas
@@ -0,0 +1,59 @@
+{
+ Copyright (c) 2008 by Giulio Bernardi
+
+ Common resource target infos
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+
+unit rescmn;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ Systems;
+
+ const
+ res_elf_info : tresinfo =
+ (
+ id : res_elf;
+ resbin : 'fpcres';
+ rescmd : '-o $OBJ -a $ARCH -of elf $DBG';
+ { cross compiled windres can be used to compile .rc files on linux }
+ rcbin : 'windres';
+ rccmd : '--include $INC -O res -o $RES $RC';
+ resourcefileclass : nil;
+ resflags : [];
+ );
+
+ res_ext_info : tresinfo =
+ (
+ id : res_ext;
+ resbin : 'fpcres';
+ rescmd : '-o $OBJ -a $ENDIAN -of external $DBG';
+ rcbin : 'windres';
+ rccmd : '--include $INC -O res -o $RES $RC';
+ resourcefileclass : nil;
+ resflags : [res_external_file];
+ );
+
+
+implementation
+
+end.
diff --git a/closures/compiler/rgbase.pas b/closures/compiler/rgbase.pas
new file mode 100644
index 0000000000..a3224781ce
--- /dev/null
+++ b/closures/compiler/rgbase.pas
@@ -0,0 +1,80 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Helper routines for register allocator
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit rgbase;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cpuBase,cgBase;
+
+ type
+ TRegNameTable = array[tregisterindex] of string[7];
+ TRegisterIndexTable = array[tregisterindex] of tregisterindex;
+
+ function findreg_by_number_table(r:Tregister;const regnumber_index:TRegisterIndexTable):tregisterindex;
+ function findreg_by_name_table(const s:string;const regname_table:TRegNameTable;const regname_index:TRegisterIndexTable):byte;
+
+
+implementation
+
+ function findreg_by_name_table(const s:string;const regname_table:TRegNameTable;const regname_index:TRegisterIndexTable):byte;
+ var
+ i,p,q : tregisterindex;
+ begin
+ p:=Low(tregisterindex);
+ q:=high(tregisterindex);
+ repeat
+ i:=(p+q) shr 1;
+ if s>regname_table[regname_index[i]] then
+ p:=i+1
+ else
+ q:=i;
+ until p=q;
+ if regname_table[regname_index[p]]=s then
+ result:=regname_index[p]
+ else
+ result:=0;
+ end;
+
+
+ function findreg_by_number_table(r:Tregister;const regnumber_index:TRegisterIndexTable):tregisterindex;
+ var
+ i,p,q : longint;
+ begin
+ p:=Low(tregisterindex);
+ q:=high(tregisterindex);
+ repeat
+ i:=(p+q) shr 1;
+ if r>regnumber_table[regnumber_index[i]] then
+ p:=i+1
+ else
+ q:=i;
+ until p=q;
+ if regnumber_table[regnumber_index[p]]=r then
+ result:=regnumber_index[p]
+ else
+ result:=0;
+ end;
+
+end.
diff --git a/closures/compiler/rgobj.pas b/closures/compiler/rgobj.pas
new file mode 100644
index 0000000000..72612ff495
--- /dev/null
+++ b/closures/compiler/rgobj.pas
@@ -0,0 +1,2162 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit implements the base class for the register allocator
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ ****************************************************************************
+}
+
+{$i fpcdefs.inc}
+
+{ Allow duplicate allocations, can be used to get the .s file written }
+{ $define ALLOWDUPREG}
+
+
+unit rgobj;
+
+ interface
+
+ uses
+ cutils, cpubase,
+ aasmbase,aasmtai,aasmdata,aasmcpu,
+ cclasses,globtype,cgbase,cgutils,
+ cpuinfo
+ ;
+
+ type
+ {
+ The interference bitmap contains of 2 layers:
+ layer 1 - 256*256 blocks with pointers to layer 2 blocks
+ layer 2 - blocks of 32*256 (32 bytes = 256 bits)
+ }
+ Tinterferencebitmap2 = array[byte] of set of byte;
+ Pinterferencebitmap2 = ^Tinterferencebitmap2;
+ Tinterferencebitmap1 = array[byte] of Pinterferencebitmap2;
+ pinterferencebitmap1 = ^tinterferencebitmap1;
+
+ Tinterferencebitmap=class
+ private
+ maxx1,
+ maxy1 : byte;
+ fbitmap : pinterferencebitmap1;
+ function getbitmap(x,y:tsuperregister):boolean;
+ procedure setbitmap(x,y:tsuperregister;b:boolean);
+ public
+ constructor create;
+ destructor destroy;override;
+ property bitmap[x,y:tsuperregister]:boolean read getbitmap write setbitmap;default;
+ end;
+
+ Tmovelistheader=record
+ count,
+ maxcount,
+ sorted_until : cardinal;
+ end;
+
+ Tmovelist=record
+ header : Tmovelistheader;
+ data : array[tsuperregister] of Tlinkedlistitem;
+ end;
+ Pmovelist=^Tmovelist;
+
+ {In the register allocator we keep track of move instructions.
+ These instructions are moved between five linked lists. There
+ is also a linked list per register to keep track about the moves
+ it is associated with. Because we need to determine quickly in
+ which of the five lists it is we add anu enumeradtion to each
+ move instruction.}
+
+ Tmoveset=(ms_coalesced_moves,ms_constrained_moves,ms_frozen_moves,
+ ms_worklist_moves,ms_active_moves);
+ Tmoveins=class(Tlinkedlistitem)
+ moveset:Tmoveset;
+ x,y:Tsuperregister;
+ end;
+
+ Treginfoflag=(ri_coalesced,ri_selected);
+ Treginfoflagset=set of Treginfoflag;
+
+ Treginfo=record
+ live_start,
+ live_end : Tai;
+ subreg : tsubregister;
+ alias : Tsuperregister;
+ { The register allocator assigns each register a colour }
+ colour : Tsuperregister;
+ movelist : Pmovelist;
+ adjlist : Psuperregisterworklist;
+ degree : TSuperregister;
+ flags : Treginfoflagset;
+ weight : longint;
+ end;
+ Preginfo=^TReginfo;
+
+ tspillreginfo = record
+ { a single register may appear more than once in an instruction,
+ but with different subregister types -> store all subregister types
+ that occur, so we can add the necessary constraints for the inline
+ register that will have to replace it }
+ spillregconstraints : set of TSubRegister;
+ orgreg : tsuperregister;
+ tempreg : tregister;
+ regread,regwritten, mustbespilled: boolean;
+ end;
+ tspillregsinfo = array[0..3] of tspillreginfo;
+
+ Tspill_temp_list=array[tsuperregister] of Treference;
+
+ {#------------------------------------------------------------------
+
+ This class implements the default register allocator. It is used by the
+ code generator to allocate and free registers which might be valid
+ across nodes. It also contains utility routines related to registers.
+
+ Some of the methods in this class should be overridden
+ by cpu-specific implementations.
+
+ --------------------------------------------------------------------}
+ trgobj=class
+ preserved_by_proc : tcpuregisterset;
+ used_in_proc : tcpuregisterset;
+
+ constructor create(Aregtype:Tregistertype;
+ Adefaultsub:Tsubregister;
+ const Ausable:array of tsuperregister;
+ Afirst_imaginary:Tsuperregister;
+ Apreserved_by_proc:Tcpuregisterset);
+ destructor destroy;override;
+
+ {# Allocate a register. An internalerror will be generated if there is
+ no more free registers which can be allocated.}
+ function getregister(list:TAsmList;subreg:Tsubregister):Tregister;virtual;
+ {# Get the register specified.}
+ procedure getcpuregister(list:TAsmList;r:Tregister);virtual;
+ procedure ungetcpuregister(list:TAsmList;r:Tregister);virtual;
+ {# Get multiple registers specified.}
+ procedure alloccpuregisters(list:TAsmList;const r:Tcpuregisterset);virtual;
+ {# Free multiple registers specified.}
+ procedure dealloccpuregisters(list:TAsmList;const r:Tcpuregisterset);virtual;
+ function uses_registers:boolean;virtual;
+ procedure add_reg_instruction(instr:Tai;r:tregister;aweight:longint);
+ procedure add_move_instruction(instr:Taicpu);
+ {# Do the register allocation.}
+ procedure do_register_allocation(list:TAsmList;headertai:tai);virtual;
+ { Adds an interference edge.
+ don't move this to the protected section, the arm cg requires to access this (FK) }
+ procedure add_edge(u,v:Tsuperregister);
+ { translates a single given imaginary register to it's real register }
+ procedure translate_register(var reg : tregister);
+ protected
+ regtype : Tregistertype;
+ { default subregister used }
+ defaultsub : tsubregister;
+ live_registers:Tsuperregisterworklist;
+ { can be overridden to add cpu specific interferences }
+ procedure add_cpu_interferences(p : tai);virtual;
+ procedure add_constraints(reg:Tregister);virtual;
+ function get_alias(n:Tsuperregister):Tsuperregister;
+ function getregisterinline(list:TAsmList;const subregconstraints:Tsubregisterset):Tregister;
+ procedure ungetregisterinline(list:TAsmList;r:Tregister);
+ function get_spill_subreg(r : tregister) : tsubregister;virtual;
+ function do_spill_replace(list:TAsmList;instr:taicpu;orgreg:tsuperregister;const spilltemp:treference):boolean;virtual;
+ procedure do_spill_read(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister);virtual;
+ procedure do_spill_written(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister);virtual;
+
+ function instr_spill_register(list:TAsmList;
+ instr:taicpu;
+ const r:Tsuperregisterset;
+ const spilltemplist:Tspill_temp_list): boolean;virtual;
+ private
+ int_live_range_direction: TRADirection;
+ {# First imaginary register.}
+ first_imaginary : Tsuperregister;
+ {# Highest register allocated until now.}
+ reginfo : PReginfo;
+ maxreginfo,
+ maxreginfoinc,
+ maxreg : Tsuperregister;
+ usable_registers_cnt : word;
+ usable_registers : array[0..maxcpuregister-1] of tsuperregister;
+ ibitmap : Tinterferencebitmap;
+ spillednodes,
+ simplifyworklist,
+ freezeworklist,
+ spillworklist,
+ coalescednodes,
+ selectstack : tsuperregisterworklist;
+ worklist_moves,
+ active_moves,
+ frozen_moves,
+ coalesced_moves,
+ constrained_moves : Tlinkedlist;
+ extended_backwards,
+ backwards_was_first : tbitset;
+
+{$ifdef EXTDEBUG}
+ procedure writegraph(loopidx:longint);
+{$endif EXTDEBUG}
+ {# Disposes of the reginfo array.}
+ procedure dispose_reginfo;
+ {# Prepare the register colouring.}
+ procedure prepare_colouring;
+ {# Clean up after register colouring.}
+ procedure epilogue_colouring;
+ {# Colour the registers; that is do the register allocation.}
+ procedure colour_registers;
+ procedure insert_regalloc_info(list:TAsmList;u:tsuperregister);
+ procedure insert_regalloc_info_all(list:TAsmList);
+ procedure generate_interference_graph(list:TAsmList;headertai:tai);
+ { translates the registers in the given assembler list }
+ procedure translate_registers(list:TAsmList);
+ function spill_registers(list:TAsmList;headertai:tai):boolean;virtual;
+ function getnewreg(subreg:tsubregister):tsuperregister;
+ procedure add_edges_used(u:Tsuperregister);
+ procedure add_to_movelist(u:Tsuperregister;data:Tlinkedlistitem);
+ function move_related(n:Tsuperregister):boolean;
+ procedure make_work_list;
+ procedure sort_simplify_worklist;
+ procedure enable_moves(n:Tsuperregister);
+ procedure decrement_degree(m:Tsuperregister);
+ procedure simplify;
+ procedure add_worklist(u:Tsuperregister);
+ function adjacent_ok(u,v:Tsuperregister):boolean;
+ function conservative(u,v:Tsuperregister):boolean;
+ procedure combine(u,v:Tsuperregister);
+ procedure coalesce;
+ procedure freeze_moves(u:Tsuperregister);
+ procedure freeze;
+ procedure select_spill;
+ procedure assign_colours;
+ procedure clear_interferences(u:Tsuperregister);
+ procedure set_live_range_direction(dir: TRADirection);
+ public
+ property live_range_direction: TRADirection read int_live_range_direction write set_live_range_direction;
+ end;
+
+ const
+ first_reg = 0;
+ last_reg = high(tsuperregister)-1;
+ maxspillingcounter = 20;
+
+
+ implementation
+
+ uses
+ systems,fmodule,globals,
+ verbose,tgobj,procinfo;
+
+
+ procedure sort_movelist(ml:Pmovelist);
+
+ {Ok, sorting pointers is silly, but it does the job to make Trgobj.combine
+ faster.}
+
+ var h,i,p:longword;
+ t:Tlinkedlistitem;
+
+ begin
+ with ml^ do
+ begin
+ if header.count<2 then
+ exit;
+ p:=1;
+ while 2*cardinal(p)<header.count do
+ p:=2*p;
+ while p<>0 do
+ begin
+ for h:=p to header.count-1 do
+ begin
+ i:=h;
+ t:=data[i];
+ repeat
+ if ptruint(data[i-p])<=ptruint(t) then
+ break;
+ data[i]:=data[i-p];
+ dec(i,p);
+ until i<p;
+ data[i]:=t;
+ end;
+ p:=p shr 1;
+ end;
+ header.sorted_until:=header.count-1;
+ end;
+ end;
+
+{******************************************************************************
+ tinterferencebitmap
+******************************************************************************}
+
+ constructor tinterferencebitmap.create;
+ begin
+ inherited create;
+ maxx1:=1;
+ getmem(fbitmap,sizeof(tinterferencebitmap1)*2);
+ fillchar(fbitmap^,sizeof(tinterferencebitmap1)*2,0);
+ end;
+
+
+ destructor tinterferencebitmap.destroy;
+
+ var i,j:byte;
+
+ begin
+ for i:=0 to maxx1 do
+ for j:=0 to maxy1 do
+ if assigned(fbitmap[i,j]) then
+ dispose(fbitmap[i,j]);
+ freemem(fbitmap);
+ end;
+
+
+ function tinterferencebitmap.getbitmap(x,y:tsuperregister):boolean;
+ var
+ page : pinterferencebitmap2;
+ begin
+ result:=false;
+ if (x shr 8>maxx1) then
+ exit;
+ page:=fbitmap[x shr 8,y shr 8];
+ result:=assigned(page) and
+ ((x and $ff) in page^[y and $ff]);
+ end;
+
+
+ procedure tinterferencebitmap.setbitmap(x,y:tsuperregister;b:boolean);
+ var
+ x1,y1 : byte;
+ begin
+ x1:=x shr 8;
+ y1:=y shr 8;
+ if x1>maxx1 then
+ begin
+ reallocmem(fbitmap,sizeof(tinterferencebitmap1)*(x1+1));
+ fillchar(fbitmap[maxx1+1],sizeof(tinterferencebitmap1)*(x1-maxx1),0);
+ maxx1:=x1;
+ end;
+ if not assigned(fbitmap[x1,y1]) then
+ begin
+ if y1>maxy1 then
+ maxy1:=y1;
+ new(fbitmap[x1,y1]);
+ fillchar(fbitmap[x1,y1]^,sizeof(tinterferencebitmap2),0);
+ end;
+ if b then
+ include(fbitmap[x1,y1]^[y and $ff],(x and $ff))
+ else
+ exclude(fbitmap[x1,y1]^[y and $ff],(x and $ff));
+ end;
+
+
+{******************************************************************************
+ trgobj
+******************************************************************************}
+
+ constructor trgobj.create(Aregtype:Tregistertype;
+ Adefaultsub:Tsubregister;
+ const Ausable:array of tsuperregister;
+ Afirst_imaginary:Tsuperregister;
+ Apreserved_by_proc:Tcpuregisterset);
+ var
+ i : cardinal;
+ begin
+ { empty super register sets can cause very strange problems }
+ if high(Ausable)=-1 then
+ internalerror(200210181);
+ live_range_direction:=rad_forward;
+ first_imaginary:=Afirst_imaginary;
+ maxreg:=Afirst_imaginary;
+ regtype:=Aregtype;
+ defaultsub:=Adefaultsub;
+ preserved_by_proc:=Apreserved_by_proc;
+ // default value set by newinstance
+ // used_in_proc:=[];
+ live_registers.init;
+ { Get reginfo for CPU registers }
+ maxreginfo:=first_imaginary;
+ maxreginfoinc:=16;
+ worklist_moves:=Tlinkedlist.create;
+ reginfo:=allocmem(first_imaginary*sizeof(treginfo));
+ for i:=0 to first_imaginary-1 do
+ begin
+ reginfo[i].degree:=high(tsuperregister);
+ reginfo[i].alias:=RS_INVALID;
+ end;
+ { Usable registers }
+ // default value set by constructor
+ // fillchar(usable_registers,sizeof(usable_registers),0);
+ for i:=low(Ausable) to high(Ausable) do
+ usable_registers[i]:=Ausable[i];
+ usable_registers_cnt:=high(Ausable)+1;
+ { Initialize Worklists }
+ spillednodes.init;
+ simplifyworklist.init;
+ freezeworklist.init;
+ spillworklist.init;
+ coalescednodes.init;
+ selectstack.init;
+ end;
+
+ destructor trgobj.destroy;
+
+ begin
+ spillednodes.done;
+ simplifyworklist.done;
+ freezeworklist.done;
+ spillworklist.done;
+ coalescednodes.done;
+ selectstack.done;
+ live_registers.done;
+ worklist_moves.free;
+ dispose_reginfo;
+ extended_backwards.free;
+ backwards_was_first.free;
+ end;
+
+ procedure Trgobj.dispose_reginfo;
+
+ var i:cardinal;
+
+ begin
+ if reginfo<>nil then
+ begin
+ for i:=0 to maxreg-1 do
+ with reginfo[i] do
+ begin
+ if adjlist<>nil then
+ dispose(adjlist,done);
+ if movelist<>nil then
+ dispose(movelist);
+ end;
+ freemem(reginfo);
+ reginfo:=nil;
+ end;
+ end;
+
+ function trgobj.getnewreg(subreg:tsubregister):tsuperregister;
+ var
+ oldmaxreginfo : tsuperregister;
+ begin
+ result:=maxreg;
+ inc(maxreg);
+ if maxreg>=last_reg then
+ Message(parser_f_too_complex_proc);
+ if maxreg>=maxreginfo then
+ begin
+ oldmaxreginfo:=maxreginfo;
+ { Prevent overflow }
+ if maxreginfoinc>last_reg-maxreginfo then
+ maxreginfo:=last_reg
+ else
+ begin
+ inc(maxreginfo,maxreginfoinc);
+ if maxreginfoinc<256 then
+ maxreginfoinc:=maxreginfoinc*2;
+ end;
+ reallocmem(reginfo,maxreginfo*sizeof(treginfo));
+ { Do we really need it to clear it ? At least for 1.0.x (PFV) }
+ fillchar(reginfo[oldmaxreginfo],(maxreginfo-oldmaxreginfo)*sizeof(treginfo),0);
+ end;
+ reginfo[result].subreg:=subreg;
+ end;
+
+
+ function trgobj.getregister(list:TAsmList;subreg:Tsubregister):Tregister;
+ begin
+ {$ifdef EXTDEBUG}
+ if reginfo=nil then
+ InternalError(2004020901);
+ {$endif EXTDEBUG}
+ if defaultsub=R_SUBNONE then
+ result:=newreg(regtype,getnewreg(R_SUBNONE),R_SUBNONE)
+ else
+ result:=newreg(regtype,getnewreg(subreg),subreg);
+ end;
+
+
+ function trgobj.uses_registers:boolean;
+ begin
+ result:=(maxreg>first_imaginary);
+ end;
+
+
+ procedure trgobj.ungetcpuregister(list:TAsmList;r:Tregister);
+ begin
+ if (getsupreg(r)>=first_imaginary) then
+ InternalError(2004020901);
+ list.concat(Tai_regalloc.dealloc(r,nil));
+ end;
+
+
+ procedure trgobj.getcpuregister(list:TAsmList;r:Tregister);
+ var
+ supreg:Tsuperregister;
+ begin
+ supreg:=getsupreg(r);
+ if supreg>=first_imaginary then
+ internalerror(2003121503);
+ include(used_in_proc,supreg);
+ list.concat(Tai_regalloc.alloc(r,nil));
+ end;
+
+
+ procedure trgobj.alloccpuregisters(list:TAsmList;const r:Tcpuregisterset);
+
+ var i:cardinal;
+
+ begin
+ for i:=0 to first_imaginary-1 do
+ if i in r then
+ getcpuregister(list,newreg(regtype,i,defaultsub));
+ end;
+
+
+ procedure trgobj.dealloccpuregisters(list:TAsmList;const r:Tcpuregisterset);
+
+ var i:cardinal;
+
+ begin
+ for i:=0 to first_imaginary-1 do
+ if i in r then
+ ungetcpuregister(list,newreg(regtype,i,defaultsub));
+ end;
+
+
+ procedure trgobj.do_register_allocation(list:TAsmList;headertai:tai);
+ var
+ spillingcounter:byte;
+ endspill:boolean;
+ begin
+ { Insert regalloc info for imaginary registers }
+ insert_regalloc_info_all(list);
+ ibitmap:=tinterferencebitmap.create;
+ generate_interference_graph(list,headertai);
+ { Don't do the real allocation when -sr is passed }
+ if (cs_no_regalloc in current_settings.globalswitches) then
+ exit;
+ {Do register allocation.}
+ spillingcounter:=0;
+ repeat
+ prepare_colouring;
+ colour_registers;
+ epilogue_colouring;
+ endspill:=true;
+ if spillednodes.length<>0 then
+ begin
+ inc(spillingcounter);
+ if spillingcounter>maxspillingcounter then
+ begin
+{$ifdef EXTDEBUG}
+ { Only exit here so the .s file is still generated. Assembling
+ the file will still trigger an error }
+ exit;
+{$else}
+ internalerror(200309041);
+{$endif}
+ end;
+ endspill:=not spill_registers(list,headertai);
+ end;
+ until endspill;
+ ibitmap.free;
+ translate_registers(list);
+ { we need the translation table for debugging info and verbose assembler output (FK)
+ dispose_reginfo;
+ }
+ end;
+
+
+ procedure trgobj.add_constraints(reg:Tregister);
+
+ begin
+ end;
+
+
+ procedure trgobj.add_edge(u,v:Tsuperregister);
+
+ {This procedure will add an edge to the virtual interference graph.}
+
+ procedure addadj(u,v:Tsuperregister);
+
+ begin
+ with reginfo[u] do
+ begin
+ if adjlist=nil then
+ new(adjlist,init);
+ adjlist^.add(v);
+ end;
+ end;
+
+ begin
+ if (u<>v) and not(ibitmap[v,u]) then
+ begin
+ ibitmap[v,u]:=true;
+ ibitmap[u,v]:=true;
+ {Precoloured nodes are not stored in the interference graph.}
+ if (u>=first_imaginary) then
+ addadj(u,v);
+ if (v>=first_imaginary) then
+ addadj(v,u);
+ end;
+ end;
+
+
+ procedure trgobj.add_edges_used(u:Tsuperregister);
+
+ var i:cardinal;
+
+ begin
+ with live_registers do
+ if length>0 then
+ for i:=0 to length-1 do
+ add_edge(u,get_alias(buf^[i]));
+ end;
+
+{$ifdef EXTDEBUG}
+ procedure trgobj.writegraph(loopidx:longint);
+
+ {This procedure writes out the current interference graph in the
+ register allocator.}
+
+
+ var f:text;
+ i,j:cardinal;
+
+ begin
+ assign(f,'igraph'+tostr(loopidx));
+ rewrite(f);
+ writeln(f,'Interference graph');
+ writeln(f);
+ write(f,' ');
+ for i:=0 to 15 do
+ for j:=0 to 15 do
+ write(f,hexstr(i,1));
+ writeln(f);
+ write(f,' ');
+ for i:=0 to 15 do
+ write(f,'0123456789ABCDEF');
+ writeln(f);
+ for i:=0 to maxreg-1 do
+ begin
+ write(f,hexstr(i,2):4);
+ for j:=0 to maxreg-1 do
+ if ibitmap[i,j] then
+ write(f,'*')
+ else
+ write(f,'-');
+ writeln(f);
+ end;
+ close(f);
+ end;
+{$endif EXTDEBUG}
+
+ procedure trgobj.add_to_movelist(u:Tsuperregister;data:Tlinkedlistitem);
+ begin
+ with reginfo[u] do
+ begin
+ if movelist=nil then
+ begin
+ { don't use sizeof(tmovelistheader), because that ignores alignment }
+ getmem(movelist,ptruint(@movelist^.data)-ptruint(movelist)+60*sizeof(pointer));
+ movelist^.header.maxcount:=60;
+ movelist^.header.count:=0;
+ movelist^.header.sorted_until:=0;
+ end
+ else
+ begin
+ if movelist^.header.count>=movelist^.header.maxcount then
+ begin
+ movelist^.header.maxcount:=movelist^.header.maxcount*2;
+ { don't use sizeof(tmovelistheader), because that ignores alignment }
+ reallocmem(movelist,ptruint(@movelist^.data)-ptruint(movelist)+movelist^.header.maxcount*sizeof(pointer));
+ end;
+ end;
+ movelist^.data[movelist^.header.count]:=data;
+ inc(movelist^.header.count);
+ end;
+ end;
+
+
+ procedure trgobj.set_live_range_direction(dir: TRADirection);
+ begin
+ if (dir in [rad_backwards,rad_backwards_reinit]) then
+ begin
+ if not assigned(extended_backwards) then
+ begin
+ { create expects a "size", not a "max bit" parameter -> +1 }
+ backwards_was_first:=tbitset.create(maxreg+1);
+ extended_backwards:=tbitset.create(maxreg+1);
+ end
+ else
+ begin
+ if (dir=rad_backwards_reinit) then
+ extended_backwards.clear;
+ backwards_was_first.clear;
+ end;
+ int_live_range_direction:=rad_backwards;
+ end
+ else
+ int_live_range_direction:=rad_forward;
+ end;
+
+
+ procedure trgobj.add_reg_instruction(instr:Tai;r:tregister;aweight:longint);
+ var
+ supreg : tsuperregister;
+ begin
+ supreg:=getsupreg(r);
+{$ifdef extdebug}
+ if not (cs_no_regalloc in current_settings.globalswitches) and
+ (supreg>=maxreginfo) then
+ internalerror(200411061);
+{$endif extdebug}
+ if supreg>=first_imaginary then
+ with reginfo[supreg] do
+ begin
+ if aweight>weight then
+ weight:=aweight;
+ if (live_range_direction=rad_forward) then
+ begin
+ if not assigned(live_start) then
+ live_start:=instr;
+ live_end:=instr;
+ end
+ else
+ begin
+ if not extended_backwards.isset(supreg) then
+ begin
+ extended_backwards.include(supreg);
+ live_start := instr;
+ if not assigned(live_end) then
+ begin
+ backwards_was_first.include(supreg);
+ live_end := instr;
+ end;
+ end
+ else
+ begin
+ if backwards_was_first.isset(supreg) then
+ live_end := instr;
+ end
+ end
+ end;
+ end;
+
+
+ procedure trgobj.add_move_instruction(instr:Taicpu);
+
+ {This procedure notifies a certain as a move instruction so the
+ register allocator can try to eliminate it.}
+
+ var i:Tmoveins;
+ ssupreg,dsupreg:Tsuperregister;
+
+ begin
+ {$ifdef extdebug}
+ if (instr.oper[O_MOV_SOURCE]^.typ<>top_reg) or
+ (instr.oper[O_MOV_DEST]^.typ<>top_reg) then
+ internalerror(200311291);
+ {$endif}
+ i:=Tmoveins.create;
+ i.moveset:=ms_worklist_moves;
+ worklist_moves.insert(i);
+ ssupreg:=getsupreg(instr.oper[O_MOV_SOURCE]^.reg);
+ add_to_movelist(ssupreg,i);
+ dsupreg:=getsupreg(instr.oper[O_MOV_DEST]^.reg);
+ if ssupreg<>dsupreg then
+ {Avoid adding the same move instruction twice to a single register.}
+ add_to_movelist(dsupreg,i);
+ i.x:=ssupreg;
+ i.y:=dsupreg;
+ end;
+
+ function trgobj.move_related(n:Tsuperregister):boolean;
+
+ var i:cardinal;
+
+ begin
+ move_related:=false;
+ with reginfo[n] do
+ if movelist<>nil then
+ with movelist^ do
+ for i:=0 to header.count-1 do
+ if Tmoveins(data[i]).moveset in [ms_worklist_moves,ms_active_moves] then
+ begin
+ move_related:=true;
+ break;
+ end;
+ end;
+
+ procedure Trgobj.sort_simplify_worklist;
+
+ {Sorts the simplifyworklist by the number of interferences the
+ registers in it cause. This allows simplify to execute in
+ constant time.}
+
+ var p,h,i,leni,lent:longword;
+ t:Tsuperregister;
+ adji,adjt:Psuperregisterworklist;
+
+ begin
+ with simplifyworklist do
+ begin
+ if length<2 then
+ exit;
+ p:=1;
+ while 2*p<length do
+ p:=2*p;
+ while p<>0 do
+ begin
+ for h:=p to length-1 do
+ begin
+ i:=h;
+ t:=buf^[i];
+ adjt:=reginfo[buf^[i]].adjlist;
+ lent:=0;
+ if adjt<>nil then
+ lent:=adjt^.length;
+ repeat
+ adji:=reginfo[buf^[i-p]].adjlist;
+ leni:=0;
+ if adji<>nil then
+ leni:=adji^.length;
+ if leni<=lent then
+ break;
+ buf^[i]:=buf^[i-p];
+ dec(i,p)
+ until i<p;
+ buf^[i]:=t;
+ end;
+ p:=p shr 1;
+ end;
+ end;
+ end;
+
+ procedure trgobj.make_work_list;
+
+ var n:cardinal;
+
+ begin
+ {If we have 7 cpu registers, and the degree of a node is 7, we cannot
+ assign it to any of the registers, thus it is significant.}
+ for n:=first_imaginary to maxreg-1 do
+ with reginfo[n] do
+ begin
+ if adjlist=nil then
+ degree:=0
+ else
+ degree:=adjlist^.length;
+ if degree>=usable_registers_cnt then
+ spillworklist.add(n)
+ else if move_related(n) then
+ freezeworklist.add(n)
+ else
+ simplifyworklist.add(n);
+ end;
+ sort_simplify_worklist;
+ end;
+
+
+ procedure trgobj.prepare_colouring;
+ begin
+ make_work_list;
+ active_moves:=Tlinkedlist.create;
+ frozen_moves:=Tlinkedlist.create;
+ coalesced_moves:=Tlinkedlist.create;
+ constrained_moves:=Tlinkedlist.create;
+ selectstack.clear;
+ end;
+
+ procedure trgobj.enable_moves(n:Tsuperregister);
+
+ var m:Tlinkedlistitem;
+ i:cardinal;
+
+ begin
+ with reginfo[n] do
+ if movelist<>nil then
+ for i:=0 to movelist^.header.count-1 do
+ begin
+ m:=movelist^.data[i];
+ if Tmoveins(m).moveset in [ms_worklist_moves,ms_active_moves] then
+ if Tmoveins(m).moveset=ms_active_moves then
+ begin
+ {Move m from the set active_moves to the set worklist_moves.}
+ active_moves.remove(m);
+ Tmoveins(m).moveset:=ms_worklist_moves;
+ worklist_moves.concat(m);
+ end;
+ end;
+ end;
+
+ procedure Trgobj.decrement_degree(m:Tsuperregister);
+
+ var adj : Psuperregisterworklist;
+ n : tsuperregister;
+ d,i : cardinal;
+
+ begin
+ with reginfo[m] do
+ begin
+ d:=degree;
+ if d=0 then
+ internalerror(200312151);
+ dec(degree);
+ if d=usable_registers_cnt then
+ begin
+ {Enable moves for m.}
+ enable_moves(m);
+ {Enable moves for adjacent.}
+ adj:=adjlist;
+ if adj<>nil then
+ for i:=1 to adj^.length do
+ begin
+ n:=adj^.buf^[i-1];
+ if reginfo[n].flags*[ri_selected,ri_coalesced]<>[] then
+ enable_moves(n);
+ end;
+ {Remove the node from the spillworklist.}
+ if not spillworklist.delete(m) then
+ internalerror(200310145);
+
+ if move_related(m) then
+ freezeworklist.add(m)
+ else
+ simplifyworklist.add(m);
+ end;
+ end;
+ end;
+
+ procedure trgobj.simplify;
+
+ var adj : Psuperregisterworklist;
+ m,n : Tsuperregister;
+ i : cardinal;
+ begin
+ {We take the element with the least interferences out of the
+ simplifyworklist. Since the simplifyworklist is now sorted, we
+ no longer need to search, but we can simply take the first element.}
+ m:=simplifyworklist.get;
+
+ {Push it on the selectstack.}
+ selectstack.add(m);
+ with reginfo[m] do
+ begin
+ include(flags,ri_selected);
+ adj:=adjlist;
+ end;
+ if adj<>nil then
+ for i:=1 to adj^.length do
+ begin
+ n:=adj^.buf^[i-1];
+ if (n>=first_imaginary) and
+ (reginfo[n].flags*[ri_selected,ri_coalesced]=[]) then
+ decrement_degree(n);
+ end;
+ end;
+
+ function trgobj.get_alias(n:Tsuperregister):Tsuperregister;
+
+ begin
+ while ri_coalesced in reginfo[n].flags do
+ n:=reginfo[n].alias;
+ get_alias:=n;
+ end;
+
+ procedure trgobj.add_worklist(u:Tsuperregister);
+ begin
+ if (u>=first_imaginary) and
+ (not move_related(u)) and
+ (reginfo[u].degree<usable_registers_cnt) then
+ begin
+ if not freezeworklist.delete(u) then
+ internalerror(200308161); {must be found}
+ simplifyworklist.add(u);
+ end;
+ end;
+
+
+ function trgobj.adjacent_ok(u,v:Tsuperregister):boolean;
+
+ {Check wether u and v should be coalesced. u is precoloured.}
+
+ function ok(t,r:Tsuperregister):boolean;
+
+ begin
+ ok:=(t<first_imaginary) or
+ (reginfo[t].degree<usable_registers_cnt) or
+ ibitmap[r,t];
+ end;
+
+ var adj : Psuperregisterworklist;
+ i : cardinal;
+ n : tsuperregister;
+
+ begin
+ with reginfo[v] do
+ begin
+ adjacent_ok:=true;
+ adj:=adjlist;
+ if adj<>nil then
+ for i:=1 to adj^.length do
+ begin
+ n:=adj^.buf^[i-1];
+ if (flags*[ri_coalesced,ri_selected]=[]) and not ok(n,u) then
+ begin
+ adjacent_ok:=false;
+ break;
+ end;
+ end;
+ end;
+ end;
+
+ function trgobj.conservative(u,v:Tsuperregister):boolean;
+
+ var adj : Psuperregisterworklist;
+ done : Tsuperregisterset; {To prevent that we count nodes twice.}
+ i,k:cardinal;
+ n : tsuperregister;
+
+ begin
+ k:=0;
+ supregset_reset(done,false,maxreg);
+ with reginfo[u] do
+ begin
+ adj:=adjlist;
+ if adj<>nil then
+ for i:=1 to adj^.length do
+ begin
+ n:=adj^.buf^[i-1];
+ if flags*[ri_coalesced,ri_selected]=[] then
+ begin
+ supregset_include(done,n);
+ if reginfo[n].degree>=usable_registers_cnt then
+ inc(k);
+ end;
+ end;
+ end;
+ adj:=reginfo[v].adjlist;
+ if adj<>nil then
+ for i:=1 to adj^.length do
+ begin
+ n:=adj^.buf^[i-1];
+ if not supregset_in(done,n) and
+ (reginfo[n].degree>=usable_registers_cnt) and
+ (reginfo[u].flags*[ri_coalesced,ri_selected]=[]) then
+ inc(k);
+ end;
+ conservative:=(k<usable_registers_cnt);
+ end;
+
+
+ procedure trgobj.combine(u,v:Tsuperregister);
+
+ var adj : Psuperregisterworklist;
+ i,n,p,q:cardinal;
+ t : tsuperregister;
+ searched:Tlinkedlistitem;
+ found : boolean;
+
+ begin
+ if not freezeworklist.delete(v) then
+ spillworklist.delete(v);
+ coalescednodes.add(v);
+ include(reginfo[v].flags,ri_coalesced);
+ reginfo[v].alias:=u;
+
+ {Combine both movelists. Since the movelists are sets, only add
+ elements that are not already present. The movelists cannot be
+ empty by definition; nodes are only coalesced if there is a move
+ between them. To prevent quadratic time blowup (movelists of
+ especially machine registers can get very large because of moves
+ generated during calls) we need to go into disgusting complexity.
+
+ (See webtbs/tw2242 for an example that stresses this.)
+
+ We want to sort the movelist to be able to search logarithmically.
+ Unfortunately, sorting the movelist every time before searching
+ is counter-productive, since the movelist usually grows with a few
+ items at a time. Therefore, we split the movelist into a sorted
+ and an unsorted part and search through both. If the unsorted part
+ becomes too large, we sort.}
+ if assigned(reginfo[u].movelist) then
+ begin
+ {We have to weigh the cost of sorting the list against searching
+ the cost of the unsorted part. I use factor of 8 here; if the
+ number of items is less than 8 times the numer of unsorted items,
+ we'll sort the list.}
+ with reginfo[u].movelist^ do
+ if header.count<8*(header.count-header.sorted_until) then
+ sort_movelist(reginfo[u].movelist);
+ if assigned(reginfo[v].movelist) then
+ begin
+ for n:=0 to reginfo[v].movelist^.header.count-1 do
+ begin
+ {Binary search the sorted part of the list.}
+ searched:=reginfo[v].movelist^.data[n];
+ p:=0;
+ q:=reginfo[u].movelist^.header.sorted_until;
+ i:=0;
+ if q<>0 then
+ repeat
+ i:=(p+q) shr 1;
+ if ptruint(searched)>ptruint(reginfo[u].movelist^.data[i]) then
+ p:=i+1
+ else
+ q:=i;
+ until p=q;
+ with reginfo[u].movelist^ do
+ if searched<>data[i] then
+ begin
+ {Linear search the unsorted part of the list.}
+ found:=false;
+ for i:=header.sorted_until+1 to header.count-1 do
+ if searched=data[i] then
+ begin
+ found:=true;
+ break;
+ end;
+ if not found then
+ add_to_movelist(u,searched);
+ end;
+ end;
+ end;
+ end;
+
+ enable_moves(v);
+
+ adj:=reginfo[v].adjlist;
+ if adj<>nil then
+ for i:=1 to adj^.length do
+ begin
+ t:=adj^.buf^[i-1];
+ with reginfo[t] do
+ if not(ri_coalesced in flags) then
+ begin
+ {t has a connection to v. Since we are adding v to u, we
+ need to connect t to u. However, beware if t was already
+ connected to u...}
+ if (ibitmap[t,u]) and not (ri_selected in flags) then
+ {... because in that case, we are actually removing an edge
+ and the degree of t decreases.}
+ decrement_degree(t)
+ else
+ begin
+ add_edge(t,u);
+ {We have added an edge to t and u. So their degree increases.
+ However, v is added to u. That means its neighbours will
+ no longer point to v, but to u instead. Therefore, only the
+ degree of u increases.}
+ if (u>=first_imaginary) and not (ri_selected in flags) then
+ inc(reginfo[u].degree);
+ end;
+ end;
+ end;
+ if (reginfo[u].degree>=usable_registers_cnt) and freezeworklist.delete(u) then
+ spillworklist.add(u);
+ end;
+
+
+ procedure trgobj.coalesce;
+
+ var m:Tmoveins;
+ x,y,u,v:cardinal;
+
+ begin
+ m:=Tmoveins(worklist_moves.getfirst);
+ x:=get_alias(m.x);
+ y:=get_alias(m.y);
+ if (y<first_imaginary) then
+ begin
+ u:=y;
+ v:=x;
+ end
+ else
+ begin
+ u:=x;
+ v:=y;
+ end;
+ if (u=v) then
+ begin
+ m.moveset:=ms_coalesced_moves; {Already coalesced.}
+ coalesced_moves.insert(m);
+ add_worklist(u);
+ end
+ {Do u and v interfere? In that case the move is constrained. Two
+ precoloured nodes interfere allways. If v is precoloured, by the above
+ code u is precoloured, thus interference...}
+ else if (v<first_imaginary) or ibitmap[u,v] then
+ begin
+ m.moveset:=ms_constrained_moves; {Cannot coalesce yet...}
+ constrained_moves.insert(m);
+ add_worklist(u);
+ add_worklist(v);
+ end
+ {Next test: is it possible and a good idea to coalesce??}
+ else if ((u<first_imaginary) and adjacent_ok(u,v)) or
+ ((u>=first_imaginary) and conservative(u,v)) then
+ begin
+ m.moveset:=ms_coalesced_moves; {Move coalesced!}
+ coalesced_moves.insert(m);
+ combine(u,v);
+ add_worklist(u);
+ end
+ else
+ begin
+ m.moveset:=ms_active_moves;
+ active_moves.insert(m);
+ end;
+ end;
+
+ procedure trgobj.freeze_moves(u:Tsuperregister);
+
+ var i:cardinal;
+ m:Tlinkedlistitem;
+ v,x,y:Tsuperregister;
+
+ begin
+ if reginfo[u].movelist<>nil then
+ for i:=0 to reginfo[u].movelist^.header.count-1 do
+ begin
+ m:=reginfo[u].movelist^.data[i];
+ if Tmoveins(m).moveset in [ms_worklist_moves,ms_active_moves] then
+ begin
+ x:=Tmoveins(m).x;
+ y:=Tmoveins(m).y;
+ if get_alias(y)=get_alias(u) then
+ v:=get_alias(x)
+ else
+ v:=get_alias(y);
+ {Move m from active_moves/worklist_moves to frozen_moves.}
+ if Tmoveins(m).moveset=ms_active_moves then
+ active_moves.remove(m)
+ else
+ worklist_moves.remove(m);
+ Tmoveins(m).moveset:=ms_frozen_moves;
+ frozen_moves.insert(m);
+
+ if (v>=first_imaginary) and not(move_related(v)) and
+ (reginfo[v].degree<usable_registers_cnt) then
+ begin
+ freezeworklist.delete(v);
+ simplifyworklist.add(v);
+ end;
+ end;
+ end;
+ end;
+
+ procedure trgobj.freeze;
+
+ var n:Tsuperregister;
+
+ begin
+ { We need to take a random element out of the freezeworklist. We take
+ the last element. Dirty code! }
+ n:=freezeworklist.get;
+ {Add it to the simplifyworklist.}
+ simplifyworklist.add(n);
+ freeze_moves(n);
+ end;
+
+ procedure trgobj.select_spill;
+ var
+ n : tsuperregister;
+ adj : psuperregisterworklist;
+ max,p,i:word;
+ minweight: longint;
+ begin
+ { We must look for the element with the most interferences in the
+ spillworklist. This is required because those registers are creating
+ the most conflicts and keeping them in a register will not reduce the
+ complexity and even can cause the help registers for the spilling code
+ to get too much conflicts with the result that the spilling code
+ will never converge (PFV) }
+ max:=0;
+ minweight:=high(longint);
+ p:=0;
+ with spillworklist do
+ begin
+ {Safe: This procedure is only called if length<>0}
+ for i:=0 to length-1 do
+ begin
+ adj:=reginfo[buf^[i]].adjlist;
+ if assigned(adj) and
+ (
+ (adj^.length>max) or
+ ((adj^.length=max) and (reginfo[buf^[i]].weight<minweight))
+ ) then
+ begin
+ p:=i;
+ max:=adj^.length;
+ minweight:=reginfo[buf^[i]].weight;
+ end;
+ end;
+ n:=buf^[p];
+ deleteidx(p);
+ end;
+
+ simplifyworklist.add(n);
+ freeze_moves(n);
+ end;
+
+ procedure trgobj.assign_colours;
+
+ {Assign_colours assigns the actual colours to the registers.}
+
+ var adj : Psuperregisterworklist;
+ i,j,k : cardinal;
+ n,a,c : Tsuperregister;
+ colourednodes : Tsuperregisterset;
+ adj_colours:set of 0..255;
+ found : boolean;
+
+ begin
+ spillednodes.clear;
+ {Reset colours}
+ for n:=0 to maxreg-1 do
+ reginfo[n].colour:=n;
+ {Colour the cpu registers...}
+ supregset_reset(colourednodes,false,maxreg);
+ for n:=0 to first_imaginary-1 do
+ supregset_include(colourednodes,n);
+ {Now colour the imaginary registers on the select-stack.}
+ for i:=selectstack.length downto 1 do
+ begin
+ n:=selectstack.buf^[i-1];
+ {Create a list of colours that we cannot assign to n.}
+ adj_colours:=[];
+ adj:=reginfo[n].adjlist;
+ if adj<>nil then
+ for j:=0 to adj^.length-1 do
+ begin
+ a:=get_alias(adj^.buf^[j]);
+ if supregset_in(colourednodes,a) and (reginfo[a].colour<=255) then
+ include(adj_colours,reginfo[a].colour);
+ end;
+ if regtype=R_INTREGISTER then
+ include(adj_colours,RS_STACK_POINTER_REG);
+ {Assume a spill by default...}
+ found:=false;
+ {Search for a colour not in this list.}
+ for k:=0 to usable_registers_cnt-1 do
+ begin
+ c:=usable_registers[k];
+ if not(c in adj_colours) then
+ begin
+ reginfo[n].colour:=c;
+ found:=true;
+ supregset_include(colourednodes,n);
+ include(used_in_proc,c);
+ break;
+ end;
+ end;
+ if not found then
+ spillednodes.add(n);
+ end;
+ {Finally colour the nodes that were coalesced.}
+ for i:=1 to coalescednodes.length do
+ begin
+ n:=coalescednodes.buf^[i-1];
+ k:=get_alias(n);
+ reginfo[n].colour:=reginfo[k].colour;
+ if reginfo[k].colour<maxcpuregister then
+ include(used_in_proc,reginfo[k].colour);
+ end;
+ end;
+
+ procedure trgobj.colour_registers;
+
+ begin
+ repeat
+ if simplifyworklist.length<>0 then
+ simplify
+ else if not(worklist_moves.empty) then
+ coalesce
+ else if freezeworklist.length<>0 then
+ freeze
+ else if spillworklist.length<>0 then
+ select_spill;
+ until (simplifyworklist.length=0) and
+ worklist_moves.empty and
+ (freezeworklist.length=0) and
+ (spillworklist.length=0);
+ assign_colours;
+ end;
+
+ procedure trgobj.epilogue_colouring;
+ var
+ i : cardinal;
+ begin
+ worklist_moves.clear;
+ active_moves.destroy;
+ active_moves:=nil;
+ frozen_moves.destroy;
+ frozen_moves:=nil;
+ coalesced_moves.destroy;
+ coalesced_moves:=nil;
+ constrained_moves.destroy;
+ constrained_moves:=nil;
+ for i:=0 to maxreg-1 do
+ with reginfo[i] do
+ if movelist<>nil then
+ begin
+ dispose(movelist);
+ movelist:=nil;
+ end;
+ end;
+
+
+ procedure trgobj.clear_interferences(u:Tsuperregister);
+
+ {Remove node u from the interference graph and remove all collected
+ move instructions it is associated with.}
+
+ var i : word;
+ v : Tsuperregister;
+ adj,adj2 : Psuperregisterworklist;
+
+ begin
+ adj:=reginfo[u].adjlist;
+ if adj<>nil then
+ begin
+ for i:=1 to adj^.length do
+ begin
+ v:=adj^.buf^[i-1];
+ {Remove (u,v) and (v,u) from bitmap.}
+ ibitmap[u,v]:=false;
+ ibitmap[v,u]:=false;
+ {Remove (v,u) from adjacency list.}
+ adj2:=reginfo[v].adjlist;
+ if adj2<>nil then
+ begin
+ adj2^.delete(u);
+ if adj2^.length=0 then
+ begin
+ dispose(adj2,done);
+ reginfo[v].adjlist:=nil;
+ end;
+ end;
+ end;
+ {Remove ( u,* ) from adjacency list.}
+ dispose(adj,done);
+ reginfo[u].adjlist:=nil;
+ end;
+ end;
+
+
+ function trgobj.getregisterinline(list:TAsmList;const subregconstraints:Tsubregisterset):Tregister;
+ var
+ p : Tsuperregister;
+ subreg: tsubregister;
+ begin
+ for subreg:=high(tsubregister) downto low(tsubregister) do
+ if subreg in subregconstraints then
+ break;
+ p:=getnewreg(subreg);
+ live_registers.add(p);
+ result:=newreg(regtype,p,subreg);
+ add_edges_used(p);
+ add_constraints(result);
+ { also add constraints for other sizes used for this register }
+ if subreg<>low(tsubregister) then
+ for subreg:=pred(subreg) downto low(tsubregister) do
+ if subreg in subregconstraints then
+ add_constraints(newreg(regtype,getsupreg(result),subreg));
+ end;
+
+
+ procedure trgobj.ungetregisterinline(list:TAsmList;r:Tregister);
+ var
+ supreg:Tsuperregister;
+ begin
+ supreg:=getsupreg(r);
+ live_registers.delete(supreg);
+ insert_regalloc_info(list,supreg);
+ end;
+
+
+ procedure trgobj.insert_regalloc_info(list:TAsmList;u:tsuperregister);
+ var
+ p : tai;
+ r : tregister;
+ palloc,
+ pdealloc : tai_regalloc;
+ begin
+ { Insert regallocs for all imaginary registers }
+ with reginfo[u] do
+ begin
+ r:=newreg(regtype,u,subreg);
+ if assigned(live_start) then
+ begin
+ { Generate regalloc and bind it to an instruction, this
+ is needed to find all live registers belonging to an
+ instruction during the spilling }
+ if live_start.typ=ait_instruction then
+ palloc:=tai_regalloc.alloc(r,live_start)
+ else
+ palloc:=tai_regalloc.alloc(r,nil);
+ if live_end.typ=ait_instruction then
+ pdealloc:=tai_regalloc.dealloc(r,live_end)
+ else
+ pdealloc:=tai_regalloc.dealloc(r,nil);
+ { Insert live start allocation before the instruction/reg_a_sync }
+ list.insertbefore(palloc,live_start);
+ { Insert live end deallocation before reg allocations
+ to reduce conflicts }
+ p:=live_end;
+ while assigned(p) and
+ assigned(p.previous) and
+ (tai(p.previous).typ=ait_regalloc) and
+ (tai_regalloc(p.previous).ratype=ra_alloc) and
+ (tai_regalloc(p.previous).reg<>r) do
+ p:=tai(p.previous);
+ { , but add release after a reg_a_sync }
+ if assigned(p) and
+ (p.typ=ait_regalloc) and
+ (tai_regalloc(p).ratype=ra_sync) then
+ p:=tai(p.next);
+ if assigned(p) then
+ list.insertbefore(pdealloc,p)
+ else
+ list.concat(pdealloc);
+ end;
+ end;
+ end;
+
+
+ procedure trgobj.insert_regalloc_info_all(list:TAsmList);
+ var
+ supreg : tsuperregister;
+ begin
+ { Insert regallocs for all imaginary registers }
+ for supreg:=first_imaginary to maxreg-1 do
+ insert_regalloc_info(list,supreg);
+ end;
+
+
+ procedure trgobj.add_cpu_interferences(p : tai);
+ begin
+ end;
+
+
+ procedure trgobj.generate_interference_graph(list:TAsmList;headertai:tai);
+ var
+ p : tai;
+{$ifdef EXTDEBUG}
+ i : integer;
+{$endif EXTDEBUG}
+ supreg : tsuperregister;
+ begin
+ { All allocations are available. Now we can generate the
+ interference graph. Walk through all instructions, we can
+ start with the headertai, because before the header tai is
+ only symbols. }
+ live_registers.clear;
+ p:=headertai;
+ while assigned(p) do
+ begin
+ if p.typ=ait_regalloc then
+ with Tai_regalloc(p) do
+ begin
+ if (getregtype(reg)=regtype) then
+ begin
+ supreg:=getsupreg(reg);
+ case ratype of
+ ra_alloc :
+ begin
+ live_registers.add(supreg);
+ add_edges_used(supreg);
+ end;
+ ra_dealloc :
+ begin
+ live_registers.delete(supreg);
+ add_edges_used(supreg);
+ end;
+ end;
+ { constraints needs always to be updated }
+ add_constraints(reg);
+ end;
+ end;
+ add_cpu_interferences(p);
+ p:=Tai(p.next);
+ end;
+
+{$ifdef EXTDEBUG}
+ if live_registers.length>0 then
+ begin
+ for i:=0 to live_registers.length-1 do
+ begin
+ { Only report for imaginary registers }
+ if live_registers.buf^[i]>=first_imaginary then
+ Comment(V_Warning,'Register '+std_regname(newreg(R_INTREGISTER,live_registers.buf^[i],defaultsub))+' not released');
+ end;
+ end;
+{$endif}
+ end;
+
+
+ procedure trgobj.translate_register(var reg : tregister);
+ begin
+ if (getregtype(reg)=regtype) then
+ setsupreg(reg,reginfo[getsupreg(reg)].colour)
+ else
+ internalerror(200602021);
+ end;
+
+
+ procedure Trgobj.translate_registers(list:TAsmList);
+ var
+ hp,p,q:Tai;
+ i:shortint;
+{$ifdef arm}
+ so:pshifterop;
+{$endif arm}
+
+
+ begin
+ { Leave when no imaginary registers are used }
+ if maxreg<=first_imaginary then
+ exit;
+ p:=Tai(list.first);
+ while assigned(p) do
+ begin
+ case p.typ of
+ ait_regalloc:
+ with Tai_regalloc(p) do
+ begin
+ if (getregtype(reg)=regtype) then
+ begin
+ { Only alloc/dealloc is needed for the optimizer, remove
+ other regalloc }
+ if not(ratype in [ra_alloc,ra_dealloc]) then
+ begin
+ q:=Tai(next);
+ list.remove(p);
+ p.free;
+ p:=q;
+ continue;
+ end
+ else
+ begin
+ setsupreg(reg,reginfo[getsupreg(reg)].colour);
+ {
+ Remove sequences of release and
+ allocation of the same register like. Other combinations
+ of release/allocate need to stay in the list.
+
+ # Register X released
+ # Register X allocated
+ }
+ if assigned(previous) and
+ (ratype=ra_alloc) and
+ (Tai(previous).typ=ait_regalloc) and
+ (Tai_regalloc(previous).reg=reg) and
+ (Tai_regalloc(previous).ratype=ra_dealloc) then
+ begin
+ q:=Tai(next);
+ hp:=tai(previous);
+ list.remove(hp);
+ hp.free;
+ list.remove(p);
+ p.free;
+ p:=q;
+ continue;
+ end;
+ end;
+ end;
+ end;
+ ait_varloc:
+ begin
+ if (getregtype(tai_varloc(p).newlocation)=regtype) then
+ begin
+ if (cs_asm_source in current_settings.globalswitches) then
+ begin
+ setsupreg(tai_varloc(p).newlocation,reginfo[getsupreg(tai_varloc(p).newlocation)].colour);
+ if tai_varloc(p).newlocationhi<>NR_NO then
+ begin
+ setsupreg(tai_varloc(p).newlocationhi,reginfo[getsupreg(tai_varloc(p).newlocationhi)].colour);
+ hp:=Tai_comment.Create(strpnew('Var '+tai_varloc(p).varsym.realname+' located in register '+
+ std_regname(tai_varloc(p).newlocationhi)+':'+std_regname(tai_varloc(p).newlocation)));
+ end
+ else
+ hp:=Tai_comment.Create(strpnew('Var '+tai_varloc(p).varsym.realname+' located in register '+
+ std_regname(tai_varloc(p).newlocation)));
+ list.insertafter(hp,p);
+ end;
+ q:=tai(p.next);
+ list.remove(p);
+ p.free;
+ p:=q;
+ continue;
+ end;
+ end;
+
+ ait_instruction:
+ with Taicpu(p) do
+ begin
+ current_filepos:=fileinfo;
+ for i:=0 to ops-1 do
+ with oper[i]^ do
+ case typ of
+ Top_reg:
+ if (getregtype(reg)=regtype) then
+ setsupreg(reg,reginfo[getsupreg(reg)].colour);
+ Top_ref:
+ begin
+ if regtype in [R_INTREGISTER,R_ADDRESSREGISTER] then
+ with ref^ do
+ begin
+ if (base<>NR_NO) and
+ (getregtype(base)=regtype) then
+ setsupreg(base,reginfo[getsupreg(base)].colour);
+ if (index<>NR_NO) and
+ (getregtype(index)=regtype) then
+ setsupreg(index,reginfo[getsupreg(index)].colour);
+ end;
+ end;
+{$ifdef arm}
+ Top_shifterop:
+ begin
+ if regtype=R_INTREGISTER then
+ begin
+ so:=shifterop;
+ if (so^.rs<>NR_NO) and
+ (getregtype(so^.rs)=regtype) then
+ setsupreg(so^.rs,reginfo[getsupreg(so^.rs)].colour);
+ end;
+ end;
+{$endif arm}
+ end;
+
+ { Maybe the operation can be removed when
+ it is a move and both arguments are the same }
+ if is_same_reg_move(regtype) then
+ begin
+ q:=Tai(p.next);
+ list.remove(p);
+ p.free;
+ p:=q;
+ continue;
+ end;
+ end;
+ end;
+ p:=Tai(p.next);
+ end;
+ current_filepos:=current_procinfo.exitpos;
+ end;
+
+
+ function trgobj.spill_registers(list:TAsmList;headertai:tai):boolean;
+ { Returns true if any help registers have been used }
+ var
+ i : cardinal;
+ t : tsuperregister;
+ p,q : Tai;
+ regs_to_spill_set:Tsuperregisterset;
+ spill_temps : ^Tspill_temp_list;
+ supreg : tsuperregister;
+ templist : TAsmList;
+ size: ptrint;
+ begin
+ spill_registers:=false;
+ live_registers.clear;
+ for i:=first_imaginary to maxreg-1 do
+ exclude(reginfo[i].flags,ri_selected);
+ spill_temps:=allocmem(sizeof(treference)*maxreg);
+ supregset_reset(regs_to_spill_set,false,$ffff);
+ { Allocate temps and insert in front of the list }
+ templist:=TAsmList.create;
+ {Safe: this procedure is only called if there are spilled nodes.}
+ with spillednodes do
+ for i:=0 to length-1 do
+ begin
+ t:=buf^[i];
+ {Alternative representation.}
+ supregset_include(regs_to_spill_set,t);
+ {Clear all interferences of the spilled register.}
+ clear_interferences(t);
+ {Get a temp for the spilled register, the size must at least equal a complete register,
+ take also care of the fact that subreg can be larger than a single register like doubles
+ that occupy 2 registers }
+ { only force the whole register in case of integers. Storing a register that contains
+ a single precision value as a double can cause conversion errors on e.g. ARM VFP }
+ if (regtype=R_INTREGISTER) then
+ size:=max(tcgsize2size[reg_cgsize(newreg(regtype,t,R_SUBWHOLE))],
+ tcgsize2size[reg_cgsize(newreg(regtype,t,reginfo[t].subreg))])
+ else
+ size:=tcgsize2size[reg_cgsize(newreg(regtype,t,reginfo[t].subreg))];
+ tg.gettemp(templist,
+ size,size,
+ tt_noreuse,spill_temps^[t]);
+ end;
+ list.insertlistafter(headertai,templist);
+ templist.free;
+ { Walk through all instructions, we can start with the headertai,
+ because before the header tai is only symbols }
+ p:=headertai;
+ while assigned(p) do
+ begin
+ case p.typ of
+ ait_regalloc:
+ with Tai_regalloc(p) do
+ begin
+ if (getregtype(reg)=regtype) then
+ begin
+ {A register allocation of a spilled register can be removed.}
+ supreg:=getsupreg(reg);
+ if supregset_in(regs_to_spill_set,supreg) then
+ begin
+ q:=Tai(p.next);
+ list.remove(p);
+ p.free;
+ p:=q;
+ continue;
+ end
+ else
+ begin
+ case ratype of
+ ra_alloc :
+ live_registers.add(supreg);
+ ra_dealloc :
+ live_registers.delete(supreg);
+ end;
+ end;
+ end;
+ end;
+ ait_instruction:
+ with Taicpu(p) do
+ begin
+ current_filepos:=fileinfo;
+ if instr_spill_register(list,taicpu(p),regs_to_spill_set,spill_temps^) then
+ spill_registers:=true;
+ end;
+ end;
+ p:=Tai(p.next);
+ end;
+ current_filepos:=current_procinfo.exitpos;
+ {Safe: this procedure is only called if there are spilled nodes.}
+ with spillednodes do
+ for i:=0 to length-1 do
+ tg.ungettemp(list,spill_temps^[buf^[i]]);
+ freemem(spill_temps);
+ end;
+
+
+ function trgobj.do_spill_replace(list:TAsmList;instr:taicpu;orgreg:tsuperregister;const spilltemp:treference):boolean;
+ begin
+ result:=false;
+ end;
+
+
+ procedure trgobj.do_spill_read(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister);
+ var
+ ins:Taicpu;
+ begin
+ ins:=spilling_create_load(spilltemp,tempreg);
+ add_cpu_interferences(ins);
+ list.insertafter(ins,pos);
+ end;
+
+
+ procedure Trgobj.do_spill_written(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister);
+ var
+ ins:Taicpu;
+ begin
+ ins:=spilling_create_store(tempreg,spilltemp);
+ add_cpu_interferences(ins);
+ list.insertafter(ins,pos);
+ end;
+
+
+ function trgobj.get_spill_subreg(r : tregister) : tsubregister;
+ begin
+ result:=defaultsub;
+ end;
+
+
+ function trgobj.instr_spill_register(list:TAsmList;
+ instr:taicpu;
+ const r:Tsuperregisterset;
+ const spilltemplist:Tspill_temp_list): boolean;
+ var
+ counter, regindex: longint;
+ regs: tspillregsinfo;
+ spilled: boolean;
+
+ procedure addreginfo(reg: tregister; operation: topertype);
+ var
+ i, tmpindex: longint;
+ supreg : tsuperregister;
+ begin
+ tmpindex := regindex;
+ supreg:=get_alias(getsupreg(reg));
+ { did we already encounter this register? }
+ for i := 0 to pred(regindex) do
+ if (regs[i].orgreg = supreg) then
+ begin
+ tmpindex := i;
+ break;
+ end;
+ if tmpindex > high(regs) then
+ internalerror(2003120301);
+ regs[tmpindex].orgreg := supreg;
+ include(regs[tmpindex].spillregconstraints,get_spill_subreg(reg));
+ if supregset_in(r,supreg) then
+ begin
+ { add/update info on this register }
+ regs[tmpindex].mustbespilled := true;
+ case operation of
+ operand_read:
+ regs[tmpindex].regread := true;
+ operand_write:
+ regs[tmpindex].regwritten := true;
+ operand_readwrite:
+ begin
+ regs[tmpindex].regread := true;
+ regs[tmpindex].regwritten := true;
+ end;
+ end;
+ spilled := true;
+ end;
+ inc(regindex,ord(regindex=tmpindex));
+ end;
+
+
+ procedure tryreplacereg(var reg: tregister);
+ var
+ i: longint;
+ supreg: tsuperregister;
+ begin
+ supreg:=get_alias(getsupreg(reg));
+ for i:=0 to pred(regindex) do
+ if (regs[i].mustbespilled) and
+ (regs[i].orgreg=supreg) then
+ begin
+ { Only replace supreg }
+ setsupreg(reg,getsupreg(regs[i].tempreg));
+ break;
+ end;
+ end;
+
+
+ var
+ loadpos,
+ storepos : tai;
+ oldlive_registers : tsuperregisterworklist;
+ begin
+ result := false;
+ fillchar(regs,sizeof(regs),0);
+ for counter := low(regs) to high(regs) do
+ regs[counter].orgreg := RS_INVALID;
+ spilled := false;
+ regindex := 0;
+
+ { check whether and if so which and how (read/written) this instructions contains
+ registers that must be spilled }
+ for counter := 0 to instr.ops-1 do
+ with instr.oper[counter]^ do
+ begin
+ case typ of
+ top_reg:
+ begin
+ if (getregtype(reg) = regtype) then
+ addreginfo(reg,instr.spilling_get_operation_type(counter));
+ end;
+ top_ref:
+ begin
+ if regtype in [R_INTREGISTER,R_ADDRESSREGISTER] then
+ with ref^ do
+ begin
+ if (base <> NR_NO) then
+ addreginfo(base,instr.spilling_get_operation_type_ref(counter,base));
+ if (index <> NR_NO) then
+ addreginfo(index,instr.spilling_get_operation_type_ref(counter,index));
+ end;
+ end;
+{$ifdef ARM}
+ top_shifterop:
+ begin
+ if regtype in [R_INTREGISTER,R_ADDRESSREGISTER] then
+ if shifterop^.rs<>NR_NO then
+ addreginfo(shifterop^.rs,operand_read);
+ end;
+{$endif ARM}
+ end;
+ end;
+
+ { if no spilling for this instruction we can leave }
+ if not spilled then
+ exit;
+
+{$ifdef x86}
+ { Try replacing the register with the spilltemp. This is useful only
+ for the i386,x86_64 that support memory locations for several instructions }
+ for counter := 0 to pred(regindex) do
+ with regs[counter] do
+ begin
+ if mustbespilled then
+ begin
+ if do_spill_replace(list,instr,orgreg,spilltemplist[orgreg]) then
+ mustbespilled:=false;
+ end;
+ end;
+{$endif x86}
+
+ {
+ There are registers that need are spilled. We generate the
+ following code for it. The used positions where code need
+ to be inserted are marked using #. Note that code is always inserted
+ before the positions using pos.previous. This way the position is always
+ the same since pos doesn't change, but pos.previous is modified everytime
+ new code is inserted.
+
+ [
+ - reg_allocs load spills
+ - load spills
+ ]
+ [#loadpos
+ - reg_deallocs
+ - reg_allocs
+ ]
+ [
+ - reg_deallocs for load-only spills
+ - reg_allocs for store-only spills
+ ]
+ [#instr
+ - original instruction
+ ]
+ [
+ - store spills
+ - reg_deallocs store spills
+ ]
+ [#storepos
+ ]
+ }
+
+ result := true;
+ oldlive_registers.copyfrom(live_registers);
+
+ { Process all tai_regallocs belonging to this instruction, ignore explicit
+ inserted regallocs. These can happend for example in i386:
+ mov ref,ireg26
+ <regdealloc ireg26, instr=taicpu of lea>
+ <regalloc edi, insrt=nil>
+ lea [ireg26+ireg17],edi
+ All released registers are also added to the live_registers because
+ they can't be used during the spilling }
+ loadpos:=tai(instr.previous);
+ while assigned(loadpos) and
+ (loadpos.typ=ait_regalloc) and
+ ((tai_regalloc(loadpos).instr=nil) or
+ (tai_regalloc(loadpos).instr=instr)) do
+ begin
+ { Only add deallocs belonging to the instruction. Explicit inserted deallocs
+ belong to the previous instruction and not the current instruction }
+ if (tai_regalloc(loadpos).instr=instr) and
+ (tai_regalloc(loadpos).ratype=ra_dealloc) then
+ live_registers.add(getsupreg(tai_regalloc(loadpos).reg));
+ loadpos:=tai(loadpos.previous);
+ end;
+ loadpos:=tai(loadpos.next);
+
+ { Load the spilled registers }
+ for counter := 0 to pred(regindex) do
+ with regs[counter] do
+ begin
+ if mustbespilled and regread then
+ begin
+ tempreg:=getregisterinline(list,regs[counter].spillregconstraints);
+ do_spill_read(list,tai(loadpos.previous),spilltemplist[orgreg],tempreg);
+ end;
+ end;
+
+ { Release temp registers of read-only registers, and add reference of the instruction
+ to the reginfo }
+ for counter := 0 to pred(regindex) do
+ with regs[counter] do
+ begin
+ if mustbespilled and regread and (not regwritten) then
+ begin
+ { The original instruction will be the next that uses this register }
+ add_reg_instruction(instr,tempreg,1);
+ ungetregisterinline(list,tempreg);
+ end;
+ end;
+
+ { Allocate temp registers of write-only registers, and add reference of the instruction
+ to the reginfo }
+ for counter := 0 to pred(regindex) do
+ with regs[counter] do
+ begin
+ if mustbespilled and regwritten then
+ begin
+ { When the register is also loaded there is already a register assigned }
+ if (not regread) then
+ tempreg:=getregisterinline(list,regs[counter].spillregconstraints);
+ { The original instruction will be the next that uses this register, this
+ also needs to be done for read-write registers }
+ add_reg_instruction(instr,tempreg,1);
+ end;
+ end;
+
+ { store the spilled registers }
+ storepos:=tai(instr.next);
+ for counter := 0 to pred(regindex) do
+ with regs[counter] do
+ begin
+ if mustbespilled and regwritten then
+ begin
+ do_spill_written(list,tai(storepos.previous),spilltemplist[orgreg],tempreg);
+ ungetregisterinline(list,tempreg);
+ end;
+ end;
+
+ { now all spilling code is generated we can restore the live registers. This
+ must be done after the store because the store can need an extra register
+ that also needs to conflict with the registers of the instruction }
+ live_registers.done;
+ live_registers:=oldlive_registers;
+
+ { substitute registers }
+ for counter:=0 to instr.ops-1 do
+ with instr.oper[counter]^ do
+ case typ of
+ top_reg:
+ begin
+ if (getregtype(reg) = regtype) then
+ tryreplacereg(reg);
+ end;
+ top_ref:
+ begin
+ if regtype in [R_INTREGISTER,R_ADDRESSREGISTER] then
+ begin
+ tryreplacereg(ref^.base);
+ tryreplacereg(ref^.index);
+ end;
+ end;
+{$ifdef ARM}
+ top_shifterop:
+ begin
+ if regtype in [R_INTREGISTER,R_ADDRESSREGISTER] then
+ tryreplacereg(shifterop^.rs);
+ end;
+{$endif ARM}
+ end;
+ {We have modified the instruction; perhaps the new instruction has
+ certain constraints regarding which imaginary registers interfere
+ with certain physical registers.}
+ add_cpu_interferences(instr);
+ end;
+
+end.
diff --git a/closures/compiler/scandir.pas b/closures/compiler/scandir.pas
new file mode 100644
index 0000000000..980e786f14
--- /dev/null
+++ b/closures/compiler/scandir.pas
@@ -0,0 +1,1542 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ This unit implements directive parsing for the scanner
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit scandir;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ globtype;
+
+ const
+ switchesstatestackmax = 20;
+
+ type
+ tsavedswitchesstate = record
+ localsw: tlocalswitches;
+ verbosity: longint;
+ pmessage : pmessagestaterecord;
+ end;
+
+ type
+ tswitchesstatestack = array[0..switchesstatestackmax] of tsavedswitchesstate;
+
+ var
+ switchesstatestack:tswitchesstatestack;
+ switchesstatestackpos: Integer;
+
+ procedure InitScannerDirectives;
+
+ implementation
+
+ uses
+ SysUtils,
+ cutils,cfileutl,
+ globals,systems,widestr,cpuinfo,
+ verbose,comphook,ppu,
+ scanner,switches,
+ fmodule,
+ symconst,symtable,
+ rabase;
+
+{*****************************************************************************
+ Helpers
+*****************************************************************************}
+
+ procedure do_delphiswitch(sw:char);
+ var
+ state : char;
+ begin
+ { c contains the next char, a + or - would be fine }
+ state:=current_scanner.readstate;
+ if state in ['-','+'] then
+ HandleSwitch(sw,state);
+ end;
+
+
+ procedure do_setverbose(flag:char);
+ var
+ state : char;
+ begin
+ { support ON/OFF }
+ state:=current_scanner.ReadState;
+ recordpendingverbosityswitch(flag,state);
+ end;
+
+
+ procedure do_moduleswitch(sw:tmoduleswitch);
+ var
+ state : char;
+ begin
+ state:=current_scanner.readstate;
+ if (sw<>cs_modulenone) and (state in ['-','+']) then
+ begin
+ if state='-' then
+ exclude(current_settings.moduleswitches,sw)
+ else
+ include(current_settings.moduleswitches,sw);
+ end;
+ end;
+
+
+ procedure do_localswitch(sw:tlocalswitch);
+ var
+ state : char;
+ begin
+ state:=current_scanner.readstate;
+ if (sw<>cs_localnone) and (state in ['-','+']) then
+ recordpendinglocalswitch(sw,state);
+ end;
+
+ procedure do_localswitchdefault(sw:tlocalswitch);
+ var
+ state : char;
+ begin
+ state:=current_scanner.readstatedefault;
+ if (sw<>cs_localnone) and (state in ['-','+','*']) then
+ recordpendinglocalswitch(sw,state);
+ end;
+
+
+ procedure do_message(w:integer);
+ begin
+ current_scanner.skipspace;
+ Message1(w,current_scanner.readcomment);
+ end;
+
+{*****************************************************************************
+ Directive Callbacks
+*****************************************************************************}
+
+ procedure dir_align;
+ var
+ hs : string;
+ begin
+ current_scanner.skipspace;
+ if not(c in ['0'..'9']) then
+ begin
+ { Support also the ON and OFF as switch }
+ hs:=current_scanner.readid;
+ if (hs='ON') then
+ current_settings.packrecords:=4
+ else if (hs='OFF') then
+ current_settings.packrecords:=1
+ else if m_mac in current_settings.modeswitches then
+ begin
+ { Support switches used in Apples Universal Interfaces}
+ if (hs='MAC68K') then
+ current_settings.packrecords:=mac68k_alignment
+ { "power" alignment is the default C packrecords setting on
+ Mac OS X }
+ else if (hs='POWER') or (hs='POWERPC') then
+ current_settings.packrecords:=C_alignment
+ else if (hs='RESET') then
+ current_settings.packrecords:=0
+ else
+ Message1(scan_e_illegal_pack_records,hs);
+ end
+ else
+ Message1(scan_e_illegal_pack_records,hs);
+ end
+ else
+ begin
+ case current_scanner.readval of
+ 1 : current_settings.packrecords:=1;
+ 2 : current_settings.packrecords:=2;
+ 4 : current_settings.packrecords:=4;
+ 8 : current_settings.packrecords:=8;
+ 16 : current_settings.packrecords:=16;
+ 32 : current_settings.packrecords:=32;
+ else
+ Message1(scan_e_illegal_pack_records,hs);
+ end;
+ end;
+ end;
+
+ procedure dir_a1;
+ begin
+ current_settings.packrecords:=1;
+ end;
+
+ procedure dir_a2;
+ begin
+ current_settings.packrecords:=2;
+ end;
+
+ procedure dir_a4;
+ begin
+ current_settings.packrecords:=4;
+ end;
+
+ procedure dir_a8;
+ begin
+ current_settings.packrecords:=8;
+ end;
+
+ procedure dir_asmmode;
+ var
+ s : string;
+ begin
+ current_scanner.skipspace;
+ s:=current_scanner.readid;
+ If Inside_asm_statement then
+ Message1(scan_w_no_asm_reader_switch_inside_asm,s);
+ if s='DEFAULT' then
+ current_settings.asmmode:=init_settings.asmmode
+ else
+ if not SetAsmReadMode(s,current_settings.asmmode) then
+ Message1(scan_e_illegal_asmmode_specifier,s);
+ end;
+
+{$if defined(m68k) or defined(arm)}
+ procedure dir_appid;
+ begin
+ if target_info.system<>system_m68k_palmos then
+ Message(scan_w_appid_not_support);
+ { change description global var in all cases }
+ { it not used but in win32 and os2 }
+ current_scanner.skipspace;
+ palmos_applicationid:=current_scanner.readcomment;
+ end;
+
+ procedure dir_appname;
+ begin
+ if target_info.system<>system_m68k_palmos then
+ Message(scan_w_appname_not_support);
+ { change description global var in all cases }
+ { it not used but in win32 and os2 }
+ current_scanner.skipspace;
+ palmos_applicationname:=current_scanner.readcomment;
+ end;
+{$endif defined(m68k) or defined(arm)}
+
+ procedure dir_apptype;
+ var
+ hs : string;
+ begin
+ if not (target_info.system in systems_all_windows + [system_i386_os2,
+ system_i386_emx, system_powerpc_macos,
+ system_arm_nds] + systems_nativent) then
+ begin
+ if m_delphi in current_settings.modeswitches then
+ Message(scan_n_app_type_not_support)
+ else
+ Message(scan_w_app_type_not_support);
+ end
+ else
+ begin
+ if not current_module.in_global then
+ Message(scan_w_switch_is_global)
+ else
+ begin
+ current_scanner.skipspace;
+ hs:=current_scanner.readid;
+ if hs='GUI' then
+ apptype:=app_gui
+ else if hs='CONSOLE' then
+ apptype:=app_cui
+ else if (hs='NATIVE') and (target_info.system in systems_windows + systems_nativent) then
+ apptype:=app_native
+ else if (hs='FS') and (target_info.system in [system_i386_os2,
+ system_i386_emx]) then
+ apptype:=app_fs
+ else if (hs='TOOL') and (target_info.system in [system_powerpc_macos]) then
+ apptype:=app_tool
+ else if (hs='ARM9') and (target_info.system in [system_arm_nds]) then
+ apptype:=app_arm9
+ else if (hs='ARM7') and (target_info.system in [system_arm_nds]) then
+ apptype:=app_arm7
+ else
+ Message1(scan_w_unsupported_app_type,hs);
+ end;
+ end;
+ end;
+
+
+ procedure dir_calling;
+ var
+ hs : string;
+ begin
+ current_scanner.skipspace;
+ hs:=current_scanner.readid;
+ if (hs='') then
+ Message(parser_e_proc_directive_expected)
+ else
+ recordpendingcallingswitch(hs);
+ end;
+
+
+ procedure dir_checkpointer;
+ begin
+ do_localswitchdefault(cs_checkpointer);
+ end;
+
+
+ procedure dir_objectchecks;
+ begin
+ do_localswitch(cs_check_object);
+ end;
+
+
+ procedure dir_ieeeerrors;
+ begin
+ do_localswitch(cs_ieee_errors);
+ end;
+
+
+ procedure dir_assertions;
+ begin
+ do_delphiswitch('C');
+ end;
+
+
+ procedure dir_booleval;
+ begin
+ do_delphiswitch('B');
+ end;
+
+ procedure dir_debuginfo;
+ begin
+ do_delphiswitch('D');
+ end;
+
+ procedure dir_description;
+ begin
+ if not (target_info.system in systems_all_windows+[system_i386_os2,system_i386_emx,
+ system_i386_netware,system_i386_wdosx,system_i386_netwlibc]) then
+ Message(scan_w_description_not_support);
+ { change description global var in all cases }
+ { it not used but in win32, os2 and netware }
+ current_scanner.skipspace;
+ description:=current_scanner.readcomment;
+ DescriptionSetExplicity:=true;
+ end;
+
+ procedure dir_screenname; {ad}
+ begin
+ if not (target_info.system in [system_i386_netware,system_i386_netwlibc]) then
+ {Message(scan_w_decription_not_support);}
+ comment (V_Warning,'Screenname only supported for target netware');
+ current_scanner.skipspace;
+ nwscreenname:=current_scanner.readcomment;
+ end;
+
+ procedure dir_threadname; {ad}
+ begin
+ if not (target_info.system in [system_i386_netware,system_i386_netwlibc]) then
+ {Message(scan_w_decription_not_support);}
+ comment (V_Warning,'Threadname only supported for target netware');
+ current_scanner.skipspace;
+ nwthreadname:=current_scanner.readcomment;
+ end;
+
+ procedure dir_copyright; {ad}
+ begin
+ if not (target_info.system in [system_i386_netware,system_i386_netwlibc]) then
+ {Message(scan_w_decription_not_support);}
+ comment (V_Warning,'Copyright only supported for target netware');
+ current_scanner.skipspace;
+ nwcopyright:=current_scanner.readcomment;
+ end;
+
+ procedure dir_error;
+ begin
+ do_message(scan_e_user_defined);
+ end;
+
+ procedure dir_extendedsyntax;
+ begin
+ do_delphiswitch('X');
+ end;
+
+ procedure dir_fatal;
+ begin
+ do_message(scan_f_user_defined);
+ end;
+
+ procedure dir_fputype;
+ begin
+ current_scanner.skipspace;
+ undef_system_macro('FPU'+fputypestr[current_settings.fputype]);
+ if not(SetFPUType(upper(current_scanner.readcomment),current_settings.fputype)) then
+ comment(V_Error,'Illegal FPU type');
+ def_system_macro('FPU'+fputypestr[current_settings.fputype]);
+ end;
+
+ procedure dir_frameworkpath;
+ begin
+ if not current_module.in_global then
+ Message(scan_w_switch_is_global)
+ else if not(target_info.system in systems_darwin) then
+ begin
+ Message(scan_w_frameworks_darwin_only);
+ current_scanner.skipspace;
+ current_scanner.readcomment
+ end
+ else
+ begin
+ current_scanner.skipspace;
+ current_module.localframeworksearchpath.AddPath(current_scanner.readcomment,false);
+ end;
+ end;
+
+ procedure dir_goto;
+ begin
+ do_moduleswitch(cs_support_goto);
+ end;
+
+ procedure dir_hint;
+ begin
+ do_message(scan_h_user_defined);
+ end;
+
+ procedure dir_hints;
+ begin
+ do_setverbose('H');
+ end;
+
+ procedure dir_imagebase;
+ begin
+ if not (target_info.system in (systems_windows+systems_wince)) then
+ Message(scan_w_imagebase_not_support);
+ current_scanner.skipspace;
+ imagebase:=current_scanner.readval;
+ ImageBaseSetExplicity:=true
+ end;
+
+ procedure dir_implicitexceptions;
+ begin
+ do_moduleswitch(cs_implicit_exceptions);
+ end;
+
+ procedure dir_includepath;
+ begin
+ if not current_module.in_global then
+ Message(scan_w_switch_is_global)
+ else
+ begin
+ current_scanner.skipspace;
+ current_module.localincludesearchpath.AddPath(current_scanner.readcomment,false);
+ end;
+ end;
+
+ procedure dir_info;
+ begin
+ do_message(scan_i_user_defined);
+ end;
+
+ procedure dir_inline;
+ begin
+ do_localswitch(cs_do_inline);
+ end;
+
+ procedure dir_interfaces;
+ var
+ hs : string;
+ begin
+ {corba/com/default}
+ current_scanner.skipspace;
+ hs:=current_scanner.readid;
+ if (hs='CORBA') then
+ current_settings.interfacetype:=it_interfacecorba
+ else if (hs='COM') then
+ current_settings.interfacetype:=it_interfacecom
+ else if (hs='DEFAULT') then
+ current_settings.interfacetype:=init_settings.interfacetype
+ else
+ Message(scan_e_invalid_interface_type);
+ end;
+
+ procedure dir_iochecks;
+ begin
+ do_delphiswitch('I');
+ end;
+
+ procedure dir_libexport;
+ begin
+ {not implemented}
+ end;
+
+ procedure dir_librarypath;
+ begin
+ if not current_module.in_global then
+ Message(scan_w_switch_is_global)
+ else
+ begin
+ current_scanner.skipspace;
+ current_module.locallibrarysearchpath.AddPath(current_scanner.readcomment,false);
+ end;
+ end;
+
+ procedure dir_link;
+ var
+ s : string;
+ begin
+ current_scanner.skipspace;
+ if scanner.c = '''' then
+ begin
+ s:= current_scanner.readquotedstring;
+ current_scanner.readcomment
+ end
+ else
+ s:= trimspace(current_scanner.readcomment);
+ s:=FixFileName(s);
+ if ExtractFileExt(s)='' then
+ s:=ChangeFileExt(s,target_info.objext);
+ current_module.linkotherofiles.add(s,link_always);
+ end;
+
+ procedure dir_linkframework;
+ var
+ s : string;
+ begin
+ current_scanner.skipspace;
+ if scanner.c = '''' then
+ begin
+ s:= current_scanner.readquotedstring;
+ current_scanner.readcomment
+ end
+ else
+ s:= trimspace(current_scanner.readcomment);
+ s:=FixFileName(s);
+ if (target_info.system in systems_darwin) then
+ current_module.linkotherframeworks.add(s,link_always)
+ else
+ Message(scan_w_frameworks_darwin_only);
+ end;
+
+ procedure dir_linklib;
+ type
+ tLinkMode=(lm_shared,lm_static);
+ var
+ s : string;
+ quote : char;
+ libext,
+ libname,
+ linkmodestr : string;
+ p : longint;
+ linkMode : tLinkMode;
+ begin
+ current_scanner.skipspace;
+ if scanner.c = '''' then
+ begin
+ libname:= current_scanner.readquotedstring;
+ s:= current_scanner.readcomment;
+ p:=pos(',',s);
+ end
+ else
+ begin
+ s:= current_scanner.readcomment;
+ p:=pos(',',s);
+ if p=0 then
+ libname:=TrimSpace(s)
+ else
+ libname:=TrimSpace(copy(s,1,p-1));
+ end;
+ if p=0 then
+ linkmodeStr:=''
+ else
+ linkmodeStr:=Upper(TrimSpace(copy(s,p+1,255)));
+
+
+ if (libname='') or (libname='''''') or (libname='""') then
+ exit;
+ { create library name }
+ if libname[1] in ['''','"'] then
+ begin
+ quote:=libname[1];
+ Delete(libname,1,1);
+ p:=pos(quote,libname);
+ if p>0 then
+ Delete(libname,p,1);
+ end;
+ libname:=FixFileName(libname);
+
+ { get linkmode, default is to check the extension for
+ the static library, otherwise shared linking is assumed }
+ linkmode:=lm_shared;
+ if linkModeStr='' then
+ begin
+ libext:=ExtractFileExt(libname);
+ if libext=target_info.staticClibext then
+ linkMode:=lm_static;
+ end
+ else if linkModeStr='STATIC' then
+ linkmode:=lm_static
+ else if (LinkModeStr='SHARED') or (LinkModeStr='') then
+ linkmode:=lm_shared
+ else
+ Comment(V_Error,'Wrong link mode specified: "'+Linkmodestr+'"');
+
+ { add to the list of other libraries }
+ if linkMode=lm_static then
+ current_module.linkOtherStaticLibs.add(libname,link_always)
+ else
+ current_module.linkOtherSharedLibs.add(libname,link_always);
+ end;
+
+ procedure dir_localsymbols;
+ begin
+ do_delphiswitch('L');
+ end;
+
+ procedure dir_longstrings;
+ begin
+ do_delphiswitch('H');
+ end;
+
+ procedure dir_macro;
+ begin
+ do_moduleswitch(cs_support_macro);
+ end;
+
+ procedure dir_pascalmainname;
+ var
+ s: string;
+ begin
+ current_scanner.skipspace;
+ s:=trimspace(current_scanner.readcomment);
+ if assigned(current_module.mainname) and
+ (s<>current_module.mainname^) then
+ begin
+ Message1(scan_w_multiple_main_name_overrides,current_module.mainname^);
+ stringdispose(current_module.mainname)
+ end
+ else if (mainaliasname<>defaultmainaliasname) and
+ (mainaliasname<>s) then
+ Message1(scan_w_multiple_main_name_overrides,mainaliasname);
+ mainaliasname:=s;
+ if (mainaliasname<>defaultmainaliasname) then
+ current_module.mainname:=stringdup(mainaliasname);
+ end;
+
+ procedure dir_maxfpuregisters;
+ var
+ l : integer;
+ hs : string;
+ begin
+ current_scanner.skipspace;
+ if not(c in ['0'..'9']) then
+ begin
+ hs:=current_scanner.readid;
+ if (hs='NORMAL') or (hs='DEFAULT') then
+ current_settings.maxfpuregisters:=-1
+ else
+ Message(scan_e_invalid_maxfpureg_value);
+ end
+ else
+ begin
+ l:=current_scanner.readval;
+ case l of
+ 0..8:
+ current_settings.maxfpuregisters:=l;
+ else
+ Message(scan_e_invalid_maxfpureg_value);
+ end;
+ end;
+ end;
+
+ procedure dir_maxstacksize;
+ begin
+ if not (target_info.system in (systems_windows+systems_wince)) then
+ Message(scan_w_maxstacksize_not_support);
+ current_scanner.skipspace;
+ maxstacksize:=current_scanner.readval;
+ MaxStackSizeSetExplicity:=true;
+ end;
+
+ procedure dir_memory;
+ var
+ l : longint;
+ begin
+ current_scanner.skipspace;
+ l:=current_scanner.readval;
+ if l>1024 then
+ stacksize:=l;
+ if c=',' then
+ begin
+ current_scanner.readchar;
+ current_scanner.skipspace;
+ l:=current_scanner.readval;
+ if l>1024 then
+ heapsize:=l;
+ end;
+ end;
+
+
+ procedure dir_message;
+ var
+ hs : string;
+ w : longint;
+ begin
+ w:=0;
+ current_scanner.skipspace;
+ { Message level specified? }
+ if c='''' then
+ w:=scan_n_user_defined
+ else
+ begin
+ hs:=current_scanner.readid;
+ if (hs='WARN') or (hs='WARNING') then
+ w:=scan_w_user_defined
+ else
+ if (hs='ERROR') then
+ w:=scan_e_user_defined
+ else
+ if (hs='FATAL') then
+ w:=scan_f_user_defined
+ else
+ if (hs='HINT') then
+ w:=scan_h_user_defined
+ else
+ if (hs='NOTE') then
+ w:=scan_n_user_defined
+ else
+ Message1(scan_w_illegal_directive,hs);
+ end;
+ { Only print message when there was no error }
+ if w<>0 then
+ begin
+ current_scanner.skipspace;
+ if c='''' then
+ hs:=current_scanner.readquotedstring
+ else
+ hs:=current_scanner.readcomment;
+ Message1(w,hs);
+ end
+ else
+ current_scanner.readcomment;
+ end;
+
+
+ procedure dir_minstacksize;
+ begin
+ if not (target_info.system in (systems_windows+systems_wince)) then
+ Message(scan_w_minstacksize_not_support);
+ current_scanner.skipspace;
+ minstacksize:=current_scanner.readval;
+ MinStackSizeSetExplicity:=true;
+ end;
+
+
+ procedure dir_mode;
+
+ begin
+ if not current_module.in_global then
+ Message(scan_w_switch_is_global)
+ else
+ begin
+ current_scanner.skipspace;
+ current_scanner.readstring;
+ if not current_module.mode_switch_allowed and
+ not ((m_mac in current_settings.modeswitches) and (pattern='MACPAS')) then
+ Message1(scan_e_mode_switch_not_allowed,pattern)
+ else if not SetCompileMode(pattern,false) then
+ Message1(scan_w_illegal_switch,pattern)
+ end;
+ current_module.mode_switch_allowed:= false;
+ end;
+
+
+ procedure dir_modeswitch;
+ var
+ s : string;
+ begin
+ if not current_module.in_global then
+ Message(scan_w_switch_is_global)
+ else
+ begin
+ current_scanner.skipspace;
+ current_scanner.readstring;
+ s:=pattern;
+ if c in ['+','-'] then
+ s:=s+current_scanner.readstate;
+ if not SetCompileModeSwitch(s,false) then
+ Message1(scan_w_illegal_switch,s)
+ end;
+ end;
+
+
+ procedure dir_mmx;
+ begin
+ do_localswitch(cs_mmx);
+ end;
+
+ procedure dir_note;
+ begin
+ do_message(scan_n_user_defined);
+ end;
+
+ procedure dir_notes;
+ begin
+ do_setverbose('N');
+ end;
+
+ procedure dir_objectpath;
+ begin
+ if not current_module.in_global then
+ Message(scan_w_switch_is_global)
+ else
+ begin
+ current_scanner.skipspace;
+ current_module.localobjectsearchpath.AddPath(current_scanner.readcomment,false);
+ end;
+ end;
+
+ procedure dir_openstrings;
+ begin
+ do_delphiswitch('P');
+ end;
+
+ procedure dir_optimization;
+ var
+ hs : string;
+ begin
+ current_scanner.skipspace;
+ { Support also the ON and OFF as switch }
+ hs:=current_scanner.readid;
+ if (hs='ON') then
+ current_settings.optimizerswitches:=level2optimizerswitches
+ else if (hs='OFF') then
+ current_settings.optimizerswitches:=[]
+ else if (hs='DEFAULT') then
+ current_settings.optimizerswitches:=init_settings.optimizerswitches
+ else
+ begin
+ if not UpdateOptimizerStr(hs,current_settings.optimizerswitches) then
+ Message1(scan_e_illegal_optimization_specifier,hs);
+ end;
+ end;
+
+ procedure dir_overflowchecks;
+ begin
+ do_delphiswitch('Q');
+ end;
+
+ procedure dir_packenum;
+ var
+ hs : string;
+ begin
+ current_scanner.skipspace;
+ if not(c in ['0'..'9']) then
+ begin
+ hs:=current_scanner.readid;
+ if (hs='NORMAL') or (hs='DEFAULT') then
+ current_settings.packenum:=4
+ else
+ Message1(scan_e_illegal_pack_enum, hs);
+ end
+ else
+ begin
+ case current_scanner.readval of
+ 1 : current_settings.packenum:=1;
+ 2 : current_settings.packenum:=2;
+ 4 : current_settings.packenum:=4;
+ else
+ Message1(scan_e_illegal_pack_enum, pattern);
+ end;
+ end;
+ end;
+
+
+ procedure dir_minfpconstprec;
+ begin
+ current_scanner.skipspace;
+ if not SetMinFPConstPrec(current_scanner.readid,current_settings.minfpconstprec) then
+ Message1(scan_e_illegal_minfpconstprec, pattern);
+ end;
+
+
+ procedure dir_packrecords;
+ var
+ hs : string;
+ begin
+ current_scanner.skipspace;
+ if not(c in ['0'..'9']) then
+ begin
+ hs:=current_scanner.readid;
+ { C has the special recordalignmax of C_alignment }
+ if (hs='C') then
+ current_settings.packrecords:=C_alignment
+ else
+ if (hs='NORMAL') or (hs='DEFAULT') then
+ current_settings.packrecords:=0
+ else
+ Message1(scan_e_illegal_pack_records,hs);
+ end
+ else
+ begin
+ case current_scanner.readval of
+ 1 : current_settings.packrecords:=1;
+ 2 : current_settings.packrecords:=2;
+ 4 : current_settings.packrecords:=4;
+ 8 : current_settings.packrecords:=8;
+ 16 : current_settings.packrecords:=16;
+ 32 : current_settings.packrecords:=32;
+ else
+ Message1(scan_e_illegal_pack_records,pattern);
+ end;
+ end;
+ end;
+
+
+ procedure dir_packset;
+ var
+ hs : string;
+ begin
+ current_scanner.skipspace;
+ if not(c in ['1','2','4','8']) then
+ begin
+ hs:=current_scanner.readid;
+ if (hs='FIXED') or ((hs='DEFAULT') OR (hs='NORMAL')) then
+ current_settings.setalloc:=0 {Fixed mode, sets are 4 or 32 bytes}
+ else
+ Message(scan_e_only_packset);
+ end
+ else
+ begin
+ case current_scanner.readval of
+ 1 : current_settings.setalloc:=1;
+ 2 : current_settings.setalloc:=2;
+ 4 : current_settings.setalloc:=4;
+ 8 : current_settings.setalloc:=8;
+ else
+ Message(scan_e_only_packset);
+ end;
+ end;
+ end;
+
+
+ procedure dir_pic;
+ begin
+ { windows doesn't need/support pic }
+ if tf_no_pic_supported in target_info.flags then
+ message(scan_w_pic_ignored)
+ else
+ do_moduleswitch(cs_create_pic);
+ end;
+
+ procedure dir_pop;
+
+ begin
+ if switchesstatestackpos < 1 then
+ Message(scan_e_too_many_pop);
+
+ Dec(switchesstatestackpos);
+ recordpendinglocalfullswitch(switchesstatestack[switchesstatestackpos].localsw);
+ recordpendingverbosityfullswitch(switchesstatestack[switchesstatestackpos].verbosity);
+ pendingstate.nextmessagerecord:=switchesstatestack[switchesstatestackpos].pmessage;
+ { Reset verbosity and forget previous pmeesage }
+ RestoreLocalVerbosity(nil);
+ current_settings.pmessage:=nil;
+ flushpendingswitchesstate;
+ end;
+
+ procedure dir_pointermath;
+ begin
+ do_localswitch(cs_pointermath);
+ end;
+
+ procedure dir_profile;
+ begin
+ do_moduleswitch(cs_profile);
+ { defined/undefine FPC_PROFILE }
+ if cs_profile in current_settings.moduleswitches then
+ def_system_macro('FPC_PROFILE')
+ else
+ undef_system_macro('FPC_PROFILE');
+ end;
+
+ procedure dir_push;
+
+ begin
+ if switchesstatestackpos > switchesstatestackmax then
+ Message(scan_e_too_many_push);
+
+ flushpendingswitchesstate;
+
+ switchesstatestack[switchesstatestackpos].localsw:= current_settings.localswitches;
+ switchesstatestack[switchesstatestackpos].pmessage:= current_settings.pmessage;
+ switchesstatestack[switchesstatestackpos].verbosity:=status.verbosity;
+ Inc(switchesstatestackpos);
+ end;
+
+ procedure dir_rangechecks;
+ begin
+ do_delphiswitch('R');
+ end;
+
+ procedure dir_referenceinfo;
+ begin
+ do_delphiswitch('Y');
+ end;
+
+ procedure dir_resource;
+ var
+ s : string;
+ begin
+ current_scanner.skipspace;
+ if scanner.c = '''' then
+ begin
+ s:= current_scanner.readquotedstring;
+ current_scanner.readcomment
+ end
+ else
+ s:= trimspace(current_scanner.readcomment);
+
+ { replace * with the name of the main source.
+ This should always be defined. }
+ if s[1]='*' then
+ if Assigned(Current_Module) then
+ begin
+ delete(S,1,1);
+ insert(ChangeFileExt(ExtractFileName(current_module.mainsource^),''),S,1 );
+ end;
+ s:=FixFileName(s);
+ if ExtractFileExt(s)='' then
+ s:=ChangeFileExt(s,target_info.resext);
+ if target_info.res<>res_none then
+ begin
+ current_module.flags:=current_module.flags or uf_has_resourcefiles;
+ if (res_single_file in target_res.resflags) and
+ not (Current_module.ResourceFiles.Empty) then
+ Message(scan_w_only_one_resourcefile_supported)
+ else
+ current_module.resourcefiles.insert(FixFileName(s));
+ end
+ else
+ Message(scan_e_resourcefiles_not_supported);
+ end;
+
+ procedure dir_saturation;
+ begin
+ do_localswitch(cs_mmx_saturation);
+ end;
+
+ procedure dir_safefpuexceptions;
+ begin
+ do_localswitch(cs_fpu_fwait);
+ end;
+
+ procedure dir_scopedenums;
+ begin
+ do_localswitch(cs_scopedenums);
+ end;
+
+ procedure dir_setpeflags;
+ begin
+ if not (target_info.system in (systems_all_windows)) then
+ Message(scan_w_setpeflags_not_support);
+ current_scanner.skipspace;
+ peflags:=current_scanner.readval;
+ SetPEFlagsSetExplicity:=true;
+ end;
+
+ procedure dir_smartlink;
+ begin
+ do_moduleswitch(cs_create_smart);
+ if (paratargetdbg in [dbg_dwarf2,dbg_dwarf3]) and
+ not(target_info.system in systems_darwin) and
+ { smart linking does not yet work with DWARF debug info on most targets }
+ (cs_create_smart in current_settings.moduleswitches) and
+ not (af_outputbinary in target_asm.flags) then
+ begin
+ Message(option_dwarf_smart_linking);
+ Exclude(current_settings.moduleswitches,cs_create_smart);
+ end;
+ end;
+
+ procedure dir_stackframes;
+ begin
+ do_delphiswitch('W');
+ end;
+
+ procedure dir_stop;
+ begin
+ do_message(scan_f_user_defined);
+ end;
+
+ procedure dir_stringchecks;
+ begin
+ // Delphi adds checks that ansistring and unicodestring are correct in
+ // different places. Skip it for now.
+ end;
+
+{$ifdef powerpc}
+ procedure dir_syscall;
+ var
+ sctype : string;
+ begin
+ { not needed on amiga/m68k for now, because there's only one }
+ { syscall convention (legacy) (KB) }
+ { not needed on amiga/powerpc because there's only one }
+ { syscall convention (sysv) (KB) }
+ if not (target_info.system in [system_powerpc_morphos]) then
+ comment (V_Warning,'Syscall directive is useless on this target.');
+ current_scanner.skipspace;
+
+ sctype:=current_scanner.readid;
+ if (sctype='LEGACY') or (sctype='SYSV') or (sctype='SYSVBASE') or
+ (sctype='BASESYSV') or (sctype='R12BASE') then
+ syscall_convention:=sctype
+ else
+ comment (V_Warning,'Invalid Syscall directive ignored.');
+ end;
+{$endif}
+
+ procedure dir_typedaddress;
+ begin
+ do_delphiswitch('T');
+ end;
+
+ procedure dir_typeinfo;
+ begin
+ do_delphiswitch('M');
+ end;
+
+ procedure dir_unitpath;
+ begin
+ if not current_module.in_global then
+ Message(scan_w_switch_is_global)
+ else
+ with current_scanner,current_module,localunitsearchpath do
+ begin
+ skipspace;
+ AddPath(path^,readcomment,false);
+ end;
+ end;
+
+ procedure dir_varpropsetter;
+ begin
+ do_localswitch(cs_varpropsetter);
+ end;
+
+ procedure dir_varstringchecks;
+ begin
+ do_delphiswitch('V');
+ end;
+
+ procedure dir_version;
+ var
+ major, minor, revision : longint;
+ error : integer;
+ begin
+ if not (target_info.system in systems_all_windows+[system_i386_os2,system_i386_emx,
+ system_i386_netware,system_i386_wdosx,
+ system_i386_netwlibc]) then
+ begin
+ Message(scan_n_version_not_support);
+ exit;
+ end;
+ if (compile_level<>1) then
+ Message(scan_n_only_exe_version)
+ else
+ begin
+ { change description global var in all cases }
+ { it not used but in win32, os2 and netware }
+ current_scanner.skipspace;
+ { we should only accept Major.Minor format for win32 and os2 }
+ current_scanner.readnumber;
+ major:=0;
+ minor:=0;
+ revision:=0;
+ val(pattern,major,error);
+ if (error<>0) or (major > high(word)) or (major < 0) then
+ begin
+ Message1(scan_w_wrong_version_ignored,pattern);
+ exit;
+ end;
+ if c='.' then
+ begin
+ current_scanner.readchar;
+ current_scanner.readnumber;
+ val(pattern,minor,error);
+ if (error<>0) or (minor > high(word)) or (minor < 0) then
+ begin
+ Message1(scan_w_wrong_version_ignored,tostr(major)+'.'+pattern);
+ exit;
+ end;
+ if (c='.') and
+ (target_info.system in [system_i386_netware,system_i386_netwlibc]) then
+ begin
+ current_scanner.readchar;
+ current_scanner.readnumber;
+ val(pattern,revision,error);
+ if (error<>0) or (revision > high(word)) or (revision < 0) then
+ begin
+ Message1(scan_w_wrong_version_ignored,tostr(revision)+'.'+pattern);
+ exit;
+ end;
+ dllmajor:=word(major);
+ dllminor:=word(minor);
+ dllrevision:=word(revision);
+ dllversion:=tostr(major)+','+tostr(minor)+','+tostr(revision);
+ end
+ else
+ begin
+ dllmajor:=word(major);
+ dllminor:=word(minor);
+ dllversion:=tostr(major)+'.'+tostr(minor);
+ end;
+ end
+ else
+ dllversion:=tostr(major);
+ end;
+ end;
+
+ procedure dir_wait;
+ var
+ had_info : boolean;
+ begin
+ had_info:=(status.verbosity and V_Info)<>0;
+ { this message should allways appear !! }
+ status.verbosity:=status.verbosity or V_Info;
+ Message(scan_i_press_enter);
+ readln;
+ If not(had_info) then
+ status.verbosity:=status.verbosity and (not V_Info);
+ end;
+
+ { delphi compatible warn directive:
+ $warn <identifier> on
+ $warn <identifier> off
+ $warn <identifier> error
+ not implemented yet
+ }
+ procedure dir_warn;
+ var
+ ident : string;
+ state : string;
+ msgstate : tmsgstate;
+ i : integer;
+ begin
+ current_scanner.skipspace;
+ ident:=current_scanner.readid;
+ current_scanner.skipspace;
+ state:=current_scanner.readid;
+
+ { support both delphi and fpc switches }
+ { use local ms_on/off/error tmsgstate values }
+ if (state='ON') or (state='+') then
+ msgstate:=ms_on
+ else
+ if (state='OFF') or (state='-') then
+ msgstate:=ms_off
+ else
+ if (state='ERROR') then
+ msgstate:=ms_error
+ else
+ begin
+ Message1(scanner_e_illegal_warn_state,state);
+ exit;
+ end;
+
+ if ident='CONSTRUCTING_ABSTRACT' then
+ recordpendingmessagestate(type_w_instance_with_abstract, msgstate)
+ else
+ if ident='IMPLICIT_VARIANTS' then
+ recordpendingmessagestate(parser_w_implicit_uses_of_variants_unit, msgstate)
+ else
+ if ident='NO_RETVAL' then
+ recordpendingmessagestate(sym_w_function_result_not_set, msgstate)
+ else
+ if ident='SYMBOL_DEPRECATED' then
+ begin
+ recordpendingmessagestate(sym_w_deprecated_symbol, msgstate);
+ recordpendingmessagestate(sym_w_deprecated_symbol_with_msg, msgstate);
+ end
+ else
+ if ident='SYMBOL_EXPERIMENTAL' then
+ recordpendingmessagestate(sym_w_experimental_symbol, msgstate)
+ else
+ if ident='SYMBOL_LIBRARY' then
+ recordpendingmessagestate(sym_w_library_symbol, msgstate)
+ else
+ if ident='SYMBOL_PLATFORM' then
+ recordpendingmessagestate(sym_w_non_portable_symbol, msgstate)
+ else
+ if ident='SYMBOL_UNIMPLEMENTED' then
+ recordpendingmessagestate(sym_w_non_implemented_symbol, msgstate)
+ else
+ if ident='UNIT_DEPRECATED' then
+ begin
+ recordpendingmessagestate(sym_w_deprecated_unit, msgstate);
+ recordpendingmessagestate(sym_w_deprecated_unit_with_msg, msgstate);
+ end
+ else
+ if ident='UNIT_EXPERIMENTAL' then
+ recordpendingmessagestate(sym_w_experimental_unit, msgstate)
+ else
+ if ident='UNIT_LIBRARY' then
+ recordpendingmessagestate(sym_w_library_unit, msgstate)
+ else
+ if ident='UNIT_PLATFORM' then
+ recordpendingmessagestate(sym_w_non_portable_unit, msgstate)
+ else
+ if ident='UNIT_UNIMPLEMENTED' then
+ recordpendingmessagestate(sym_w_non_implemented_unit, msgstate)
+ else
+ if ident='ZERO_NIL_COMPAT' then
+ recordpendingmessagestate(type_w_zero_to_nil, msgstate)
+ else
+ if ident='IMPLICIT_STRING_CAST' then
+ recordpendingmessagestate(type_w_implicit_string_cast, msgstate)
+ else
+ if ident='IMPLICIT_STRING_CAST_LOSS' then
+ recordpendingmessagestate(type_w_implicit_string_cast_loss, msgstate)
+ else
+ if ident='EXPLICIT_STRING_CAST' then
+ recordpendingmessagestate(type_w_explicit_string_cast, msgstate)
+ else
+ if ident='EXPLICIT_STRING_CAST_LOSS' then
+ recordpendingmessagestate(type_w_explicit_string_cast_loss, msgstate)
+ else
+ if ident='CVT_NARROWING_STRING_LOST' then
+ recordpendingmessagestate(type_w_unicode_data_loss, msgstate)
+ else
+ begin
+ i:=0;
+ if not ChangeMessageVerbosity(ident,i,msgstate) then
+ Message1(scanner_w_illegal_warn_identifier,ident);
+ end;
+ end;
+
+ procedure dir_warning;
+ begin
+ do_message(scan_w_user_defined);
+ end;
+
+ procedure dir_warnings;
+ begin
+ do_setverbose('W');
+ end;
+
+ procedure dir_writeableconst;
+ begin
+ do_delphiswitch('J');
+ end;
+
+ procedure dir_z1;
+ begin
+ current_settings.packenum:=1;
+ end;
+
+ procedure dir_z2;
+ begin
+ current_settings.packenum:=2;
+ end;
+
+ procedure dir_z4;
+ begin
+ current_settings.packenum:=4;
+ end;
+
+ procedure dir_externalsym;
+ begin
+ end;
+
+ procedure dir_nodefine;
+ begin
+ end;
+
+ procedure dir_hppemit;
+ begin
+ end;
+
+ procedure dir_weakpackageunit;
+ begin
+ end;
+
+ procedure dir_codealign;
+ var
+ s : string;
+ begin
+ current_scanner.skipspace;
+ s:=current_scanner.readcomment;
+ if not(UpdateAlignmentStr(s,current_settings.alignment)) then
+ message(scanner_e_illegal_alignment_directive);
+ end;
+
+ procedure dir_codepage;
+ var
+ s : string;
+ begin
+ if not current_module.in_global then
+ Message(scan_w_switch_is_global)
+ else
+ begin
+ current_scanner.skipspace;
+ s:=current_scanner.readcomment;
+ if (upper(s)='UTF8') or (upper(s)='UTF-8') then
+ current_settings.sourcecodepage:=CP_UTF8
+ else if not(cpavailable(s)) then
+ Message1(option_code_page_not_available,s)
+ else
+ current_settings.sourcecodepage:=codepagebyname(s);
+ include(current_settings.moduleswitches,cs_explicit_codepage);
+ end;
+ end;
+
+ procedure dir_coperators;
+ begin
+ do_moduleswitch(cs_support_c_operators);
+ end;
+
+
+ procedure dir_bitpacking;
+ begin
+ do_localswitch(cs_bitpacking);
+ end;
+
+ procedure dir_region;
+ begin
+ end;
+
+ procedure dir_endregion;
+ begin
+ end;
+
+
+{****************************************************************************
+ Initialize Directives
+****************************************************************************}
+
+ procedure InitScannerDirectives;
+ begin
+ AddDirective('A1',directive_all, @dir_a1);
+ AddDirective('A2',directive_all, @dir_a2);
+ AddDirective('A4',directive_all, @dir_a4);
+ AddDirective('A8',directive_all, @dir_a8);
+ AddDirective('ALIGN',directive_all, @dir_align);
+{$ifdef m68k}
+ AddDirective('APPID',directive_all, @dir_appid);
+ AddDirective('APPNAME',directive_all, @dir_appname);
+{$endif m68k}
+ AddDirective('APPTYPE',directive_all, @dir_apptype);
+ AddDirective('ASMMODE',directive_all, @dir_asmmode);
+ AddDirective('ASSERTIONS',directive_all, @dir_assertions);
+ AddDirective('BOOLEVAL',directive_all, @dir_booleval);
+ AddDirective('BITPACKING',directive_all, @dir_bitpacking);
+ AddDirective('CALLING',directive_all, @dir_calling);
+ AddDirective('CHECKPOINTER',directive_all, @dir_checkpointer);
+ AddDirective('CODEALIGN',directive_all, @dir_codealign);
+ AddDirective('CODEPAGE',directive_all, @dir_codepage);
+ AddDirective('COPERATORS',directive_all, @dir_coperators);
+ AddDirective('COPYRIGHT',directive_all, @dir_copyright);
+ AddDirective('D',directive_all, @dir_description);
+ AddDirective('DEBUGINFO',directive_all, @dir_debuginfo);
+ AddDirective('DESCRIPTION',directive_all, @dir_description);
+ AddDirective('ENDREGION',directive_all, @dir_endregion);
+ AddDirective('ERROR',directive_all, @dir_error);
+ AddDirective('ERRORC',directive_mac, @dir_error);
+ AddDirective('EXTENDEDSYNTAX',directive_all, @dir_extendedsyntax);
+ AddDirective('EXTERNALSYM',directive_all, @dir_externalsym);
+ AddDirective('FATAL',directive_all, @dir_fatal);
+ AddDirective('FPUTYPE',directive_all, @dir_fputype);
+ AddDirective('FRAMEWORKPATH',directive_all, @dir_frameworkpath);
+ AddDirective('GOTO',directive_all, @dir_goto);
+ AddDirective('HINT',directive_all, @dir_hint);
+ AddDirective('HINTS',directive_all, @dir_hints);
+ AddDirective('HPPEMIT',directive_all, @dir_hppemit);
+ AddDirective('IEEEERRORS',directive_all,@dir_ieeeerrors);
+ AddDirective('IOCHECKS',directive_all, @dir_iochecks);
+ AddDirective('IMAGEBASE',directive_all, @dir_imagebase);
+ AddDirective('IMPLICITEXCEPTIONS',directive_all, @dir_implicitexceptions);
+ AddDirective('INCLUDEPATH',directive_all, @dir_includepath);
+ AddDirective('INFO',directive_all, @dir_info);
+ AddDirective('INLINE',directive_all, @dir_inline);
+ AddDirective('INTERFACES',directive_all, @dir_interfaces);
+ AddDirective('L',directive_all, @dir_link);
+ AddDirective('LIBEXPORT',directive_mac, @dir_libexport);
+ AddDirective('LIBRARYPATH',directive_all, @dir_librarypath);
+ AddDirective('LINK',directive_all, @dir_link);
+ AddDirective('LINKFRAMEWORK',directive_all, @dir_linkframework);
+ AddDirective('LINKLIB',directive_all, @dir_linklib);
+ AddDirective('LOCALSYMBOLS',directive_all, @dir_localsymbols);
+ AddDirective('LONGSTRINGS',directive_all, @dir_longstrings);
+ AddDirective('M',directive_all, @dir_memory);
+ AddDirective('MACRO',directive_all, @dir_macro);
+ AddDirective('MAXFPUREGISTERS',directive_all, @dir_maxfpuregisters);
+ AddDirective('MAXSTACKSIZE',directive_all, @dir_maxstacksize);
+ AddDirective('MEMORY',directive_all, @dir_memory);
+ AddDirective('MESSAGE',directive_all, @dir_message);
+ AddDirective('MINENUMSIZE',directive_all, @dir_packenum);
+ AddDirective('MINFPCONSTPREC',directive_all, @dir_minfpconstprec);
+ AddDirective('MINSTACKSIZE',directive_all, @dir_minstacksize);
+ AddDirective('MMX',directive_all, @dir_mmx);
+ AddDirective('MODE',directive_all, @dir_mode);
+ AddDirective('MODESWITCH',directive_all, @dir_modeswitch);
+ AddDirective('NODEFINE',directive_all, @dir_nodefine);
+ AddDirective('NOTE',directive_all, @dir_note);
+ AddDirective('NOTES',directive_all, @dir_notes);
+ AddDirective('OBJECTCHECKS',directive_all, @dir_objectchecks);
+ AddDirective('OBJECTPATH',directive_all, @dir_objectpath);
+ AddDirective('OPENSTRINGS',directive_all, @dir_openstrings);
+ AddDirective('OPTIMIZATION',directive_all, @dir_optimization);
+ AddDirective('OV',directive_mac, @dir_overflowchecks);
+ AddDirective('OVERFLOWCHECKS',directive_all, @dir_overflowchecks);
+ AddDirective('PACKENUM',directive_all, @dir_packenum);
+ AddDirective('PACKRECORDS',directive_all, @dir_packrecords);
+ AddDirective('PACKSET',directive_all, @dir_packset);
+ AddDirective('PASCALMAINNAME',directive_all, @dir_pascalmainname);
+ AddDirective('PIC',directive_all, @dir_pic);
+ AddDirective('POINTERMATH',directive_all, @dir_pointermath);
+ AddDirective('POP',directive_all, @dir_pop);
+ AddDirective('PROFILE',directive_all, @dir_profile);
+ AddDirective('PUSH',directive_all, @dir_push);
+ AddDirective('R',directive_all, @dir_resource);
+ AddDirective('RANGECHECKS',directive_all, @dir_rangechecks);
+ AddDirective('REFERENCEINFO',directive_all, @dir_referenceinfo);
+ AddDirective('REGION',directive_all, @dir_region);
+ AddDirective('RESOURCE',directive_all, @dir_resource);
+ AddDirective('SATURATION',directive_all, @dir_saturation);
+ AddDirective('SAFEFPUEXCEPTIONS',directive_all, @dir_safefpuexceptions);
+ AddDirective('SCOPEDENUMS',directive_all, @dir_scopedenums);
+ AddDirective('SETPEFLAGS', directive_all, @dir_setpeflags);
+ AddDirective('SCREENNAME',directive_all, @dir_screenname);
+ AddDirective('SMARTLINK',directive_all, @dir_smartlink);
+ AddDirective('STACKFRAMES',directive_all, @dir_stackframes);
+ AddDirective('STOP',directive_all, @dir_stop);
+ AddDirective('STRINGCHECKS', directive_all, @dir_stringchecks);
+{$ifdef powerpc}
+ AddDirective('SYSCALL',directive_all, @dir_syscall);
+{$endif powerpc}
+ AddDirective('THREADNAME',directive_all, @dir_threadname);
+ AddDirective('TYPEDADDRESS',directive_all, @dir_typedaddress);
+ AddDirective('TYPEINFO',directive_all, @dir_typeinfo);
+ AddDirective('UNITPATH',directive_all, @dir_unitpath);
+ AddDirective('VARPROPSETTER',directive_all, @dir_varpropsetter);
+ AddDirective('VARSTRINGCHECKS',directive_all, @dir_varstringchecks);
+ AddDirective('VERSION',directive_all, @dir_version);
+ AddDirective('WAIT',directive_all, @dir_wait);
+ AddDirective('WARN',directive_all, @dir_warn);
+ AddDirective('WARNING',directive_all, @dir_warning);
+ AddDirective('WARNINGS',directive_all, @dir_warnings);
+ AddDirective('WEAKPACKAGEUNIT',directive_all, @dir_weakpackageunit);
+ AddDirective('WRITEABLECONST',directive_all, @dir_writeableconst);
+ AddDirective('Z1',directive_all, @dir_z1);
+ AddDirective('Z2',directive_all, @dir_z2);
+ AddDirective('Z4',directive_all, @dir_z4);
+ end;
+
+end.
diff --git a/closures/compiler/scanner.pas b/closures/compiler/scanner.pas
new file mode 100644
index 0000000000..0eea92b0a7
--- /dev/null
+++ b/closures/compiler/scanner.pas
@@ -0,0 +1,4734 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit implements the scanner part and handling of the switches
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit scanner;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cclasses,
+ globtype,globals,constexp,version,tokens,
+ verbose,comphook,
+ finput,
+ widestr;
+
+ const
+ max_include_nesting=32;
+ max_macro_nesting=16;
+ preprocbufsize=32*1024;
+
+
+ type
+ tcommentstyle = (comment_none,comment_tp,comment_oldtp,comment_delphi,comment_c);
+
+ tscannerfile = class;
+
+ preproctyp = (pp_ifdef,pp_ifndef,pp_if,pp_ifopt,pp_else,pp_elseif);
+
+ tpreprocstack = class
+ typ : preproctyp;
+ accept : boolean;
+ next : tpreprocstack;
+ name : TIDString;
+ line_nb : longint;
+ owner : tscannerfile;
+ constructor Create(atyp:preproctyp;a:boolean;n:tpreprocstack);
+ end;
+
+ tdirectiveproc=procedure;
+
+ tdirectiveitem = class(TFPHashObject)
+ public
+ is_conditional : boolean;
+ proc : tdirectiveproc;
+ constructor Create(AList:TFPHashObjectList;const n:string;p:tdirectiveproc);
+ constructor CreateCond(AList:TFPHashObjectList;const n:string;p:tdirectiveproc);
+ end;
+
+ // stack for replay buffers
+ treplaystack = class
+ token : ttoken;
+ settings : tsettings;
+ tokenbuf : tdynamicarray;
+ next : treplaystack;
+ change_endian : boolean;
+ constructor Create(atoken: ttoken;asettings:tsettings;
+ atokenbuf:tdynamicarray;anext:treplaystack; achange_endian : boolean);
+ end;
+
+ tcompile_time_predicate = function(var valuedescr: String) : Boolean;
+
+ tspecialgenerictoken =
+ (ST_LOADSETTINGS,
+ ST_LINE,
+ ST_COLUMN,
+ ST_FILEINDEX,
+ ST_LOADMESSAGES);
+
+ { tscannerfile }
+
+ tscannerfile = class
+ private
+ procedure do_gettokenpos(out tokenpos: longint; out filepos: tfileposinfo);
+ procedure cachenexttokenpos;
+ procedure setnexttoken;
+ procedure savetokenpos;
+ procedure restoretokenpos;
+ procedure writetoken(t: ttoken);
+ function readtoken : ttoken;
+ public
+ inputfile : tinputfile; { current inputfile list }
+ inputfilecount : longint;
+
+ inputbuffer, { input buffer }
+ inputpointer : pchar;
+ inputstart : longint;
+
+ line_no, { line }
+ lastlinepos : longint;
+
+ lasttokenpos,
+ nexttokenpos : longint; { token }
+ lasttoken,
+ nexttoken : ttoken;
+
+ oldlasttokenpos : longint; { temporary saving/restoring tokenpos }
+ oldcurrent_filepos,
+ oldcurrent_tokenpos : tfileposinfo;
+
+
+ replaytokenbuf,
+ recordtokenbuf : tdynamicarray;
+ tokenbuf_change_endian : boolean;
+
+ { last settings we stored }
+ last_settings : tsettings;
+ last_message : pmessagestaterecord;
+ { last filepos we stored }
+ last_filepos,
+ { if nexttoken<>NOTOKEN, then nexttokenpos holds its filepos }
+ next_filepos : tfileposinfo;
+
+ comment_level,
+ yylexcount : longint;
+ lastasmgetchar : char;
+ ignoredirectives : TFPHashList; { ignore directives, used to give warnings only once }
+ preprocstack : tpreprocstack;
+ replaystack : treplaystack;
+ in_asm_string : boolean;
+
+ preproc_pattern : string;
+ preproc_token : ttoken;
+
+ constructor Create(const fn:string);
+ destructor Destroy;override;
+ { File buffer things }
+ function openinputfile:boolean;
+ procedure closeinputfile;
+ function tempopeninputfile:boolean;
+ procedure tempcloseinputfile;
+ procedure saveinputfile;
+ procedure restoreinputfile;
+ procedure firstfile;
+ procedure nextfile;
+ procedure addfile(hp:tinputfile);
+ procedure reload;
+ procedure insertmacro(const macname:string;p:pchar;len,line,fileindex:longint);
+ { Scanner things }
+ procedure gettokenpos;
+ procedure inc_comment_level;
+ procedure dec_comment_level;
+ procedure illegal_char(c:char);
+ procedure end_of_file;
+ procedure checkpreprocstack;
+ procedure poppreprocstack;
+ procedure ifpreprocstack(atyp : preproctyp;compile_time_predicate:tcompile_time_predicate;messid:longint);
+ procedure elseifpreprocstack(compile_time_predicate:tcompile_time_predicate);
+ procedure elsepreprocstack;
+ procedure popreplaystack;
+ procedure handleconditional(p:tdirectiveitem);
+ procedure handledirectives;
+ procedure linebreak;
+ procedure recordtoken;
+ procedure startrecordtokens(buf:tdynamicarray);
+ procedure stoprecordtokens;
+ procedure replaytoken;
+ procedure startreplaytokens(buf:tdynamicarray; achange_endian : boolean);
+ { bit length sizeint is target depend }
+ procedure tokenwritesizeint(val : sizeint);
+ function tokenreadsizeint : sizeint;
+ { longword/longint are 32 bits on all targets }
+ { word/smallint are 16-bits on all targest }
+ function tokenreadlongword : longword;
+ function tokenreadword : word;
+ function tokenreadlongint : longint;
+ function tokenreadsmallint : smallint;
+ { short int is one a signed byte }
+ function tokenreadshortint : shortint;
+ function tokenreadbyte : byte;
+ { This one takes the set size as an parameter }
+ procedure tokenreadset(var b;size : longint);
+ function tokenreadenum(size : longint) : longword;
+
+ procedure tokenreadsettings(var asettings : tsettings; expected_size : longint);
+ procedure readchar;
+ procedure readstring;
+ procedure readnumber;
+ function readid:string;
+ function readval:longint;
+ function readval_asstring:string;
+ function readcomment:string;
+ function readquotedstring:string;
+ function readstate:char;
+ function readstatedefault:char;
+ procedure skipspace;
+ procedure skipuntildirective;
+ procedure skipcomment;
+ procedure skipdelphicomment;
+ procedure skipoldtpcomment;
+ procedure readtoken(allowrecordtoken:boolean);
+ function readpreproc:ttoken;
+ function asmgetcharstart : char;
+ function asmgetchar:char;
+ end;
+
+{$ifdef PREPROCWRITE}
+ tpreprocfile=class
+ f : text;
+ buf : pointer;
+ spacefound,
+ eolfound : boolean;
+ constructor create(const fn:string);
+ destructor destroy;
+ procedure Add(const s:string);
+ procedure AddSpace;
+ end;
+{$endif PREPROCWRITE}
+
+ var
+ { read strings }
+ c : char;
+ orgpattern,
+ pattern : string;
+ cstringpattern : ansistring;
+ patternw : pcompilerwidestring;
+
+ { token }
+ token, { current token being parsed }
+ idtoken : ttoken; { holds the token if the pattern is a known word }
+
+ current_scanner : tscannerfile; { current scanner in use }
+
+ aktcommentstyle : tcommentstyle; { needed to use read_comment from directives }
+{$ifdef PREPROCWRITE}
+ preprocfile : tpreprocfile; { used with only preprocessing }
+{$endif PREPROCWRITE}
+
+ type
+ tdirectivemode = (directive_all, directive_turbo, directive_mac);
+
+ procedure AddDirective(const s:string; dm: tdirectivemode; p:tdirectiveproc);
+ procedure AddConditional(const s:string; dm: tdirectivemode; p:tdirectiveproc);
+
+ procedure InitScanner;
+ procedure DoneScanner;
+
+ { To be called when the language mode is finally determined }
+ Function SetCompileMode(const s:string; changeInit: boolean):boolean;
+ Function SetCompileModeSwitch(s:string; changeInit: boolean):boolean;
+
+
+implementation
+
+ uses
+ SysUtils,
+ cutils,cfileutl,
+ systems,
+ switches,
+ symbase,symtable,symtype,symsym,symconst,symdef,defutil,
+ { This is needed for tcputype }
+ cpuinfo,
+ fmodule
+{$if FPC_FULLVERSION<20700}
+ ,ccharset
+{$endif}
+ ;
+
+ var
+ { dictionaries with the supported directives }
+ turbo_scannerdirectives : TFPHashObjectList; { for other modes }
+ mac_scannerdirectives : TFPHashObjectList; { for mode mac }
+
+
+{*****************************************************************************
+ Helper routines
+*****************************************************************************}
+
+ const
+ { use any special name that is an invalid file name to avoid problems }
+ preprocstring : array [preproctyp] of string[7]
+ = ('$IFDEF','$IFNDEF','$IF','$IFOPT','$ELSE','$ELSEIF');
+
+ function is_keyword(const s:string):boolean;
+ var
+ low,high,mid : longint;
+ begin
+ if not (length(s) in [tokenlenmin..tokenlenmax]) or
+ not (s[1] in ['a'..'z','A'..'Z']) then
+ begin
+ is_keyword:=false;
+ exit;
+ end;
+ low:=ord(tokenidx^[length(s),s[1]].first);
+ high:=ord(tokenidx^[length(s),s[1]].last);
+ while low<high do
+ begin
+ mid:=(high+low+1) shr 1;
+ if pattern<tokeninfo^[ttoken(mid)].str then
+ high:=mid-1
+ else
+ low:=mid;
+ end;
+ is_keyword:=(pattern=tokeninfo^[ttoken(high)].str) and
+ (tokeninfo^[ttoken(high)].keyword in current_settings.modeswitches);
+ end;
+
+
+ Procedure HandleModeSwitches(changeInit: boolean);
+ begin
+ { turn ansistrings on by default ? }
+ if (m_default_ansistring in current_settings.modeswitches) then
+ begin
+ include(current_settings.localswitches,cs_ansistrings);
+ if changeinit then
+ include(init_settings.localswitches,cs_ansistrings);
+ end
+ else
+ begin
+ exclude(current_settings.localswitches,cs_ansistrings);
+ if changeinit then
+ exclude(init_settings.localswitches,cs_ansistrings);
+ end;
+
+ { turn inline on by default ? }
+ if (m_default_inline in current_settings.modeswitches) then
+ begin
+ include(current_settings.localswitches,cs_do_inline);
+ if changeinit then
+ include(init_settings.localswitches,cs_do_inline);
+ end
+ else
+ begin
+ exclude(current_settings.localswitches,cs_do_inline);
+ if changeinit then
+ exclude(init_settings.localswitches,cs_do_inline);
+ end;
+
+ { turn system codepage by default }
+ if m_systemcodepage in current_settings.modeswitches then
+ begin
+ current_settings.sourcecodepage:=DefaultSystemCodePage;
+ include(current_settings.moduleswitches,cs_explicit_codepage);
+ if changeinit then
+ begin
+ init_settings.sourcecodepage:=DefaultSystemCodePage;
+ include(init_settings.moduleswitches,cs_explicit_codepage);
+ end;
+ end
+ else
+ begin
+ exclude(current_settings.moduleswitches,cs_explicit_codepage);
+ if changeinit then
+ exclude(init_settings.moduleswitches,cs_explicit_codepage);
+ end;
+ end;
+
+
+ Function SetCompileMode(const s:string; changeInit: boolean):boolean;
+ var
+ b : boolean;
+ oldmodeswitches : tmodeswitches;
+ begin
+ oldmodeswitches:=current_settings.modeswitches;
+
+ b:=true;
+ if s='DEFAULT' then
+ current_settings.modeswitches:=fpcmodeswitches
+ else
+ if s='DELPHI' then
+ current_settings.modeswitches:=delphimodeswitches
+ else
+ if s='DELPHIUNICODE' then
+ current_settings.modeswitches:=delphiunicodemodeswitches
+ else
+ if s='TP' then
+ current_settings.modeswitches:=tpmodeswitches
+ else
+ if s='FPC' then begin
+ current_settings.modeswitches:=fpcmodeswitches;
+ { TODO: enable this for 2.3/2.9 }
+ // include(current_settings.localswitches, cs_typed_addresses);
+ end else
+ if s='OBJFPC' then begin
+ current_settings.modeswitches:=objfpcmodeswitches;
+ { TODO: enable this for 2.3/2.9 }
+ // include(current_settings.localswitches, cs_typed_addresses);
+ end
+{$ifdef gpc_mode}
+ else if s='GPC' then
+ current_settings.modeswitches:=gpcmodeswitches
+{$endif}
+ else
+ if s='MACPAS' then
+ current_settings.modeswitches:=macmodeswitches
+ else
+ if s='ISO' then
+ current_settings.modeswitches:=isomodeswitches
+ else
+ b:=false;
+
+ if b and changeInit then
+ init_settings.modeswitches := current_settings.modeswitches;
+
+ if b then
+ begin
+ { resolve all postponed switch changes }
+ flushpendingswitchesstate;
+
+ HandleModeSwitches(changeinit);
+
+ { turn on bitpacking for mode macpas and iso pascal }
+ if ([m_mac,m_iso] * current_settings.modeswitches <> []) then
+ begin
+ include(current_settings.localswitches,cs_bitpacking);
+ if changeinit then
+ include(init_settings.localswitches,cs_bitpacking);
+ end;
+
+ { support goto/label by default in delphi/tp7/mac modes }
+ if ([m_delphi,m_tp7,m_mac,m_iso] * current_settings.modeswitches <> []) then
+ begin
+ include(current_settings.moduleswitches,cs_support_goto);
+ if changeinit then
+ include(init_settings.moduleswitches,cs_support_goto);
+ end;
+
+ { support pointer math by default in fpc/objfpc modes }
+ if ([m_fpc,m_objfpc] * current_settings.modeswitches <> []) then
+ begin
+ include(current_settings.localswitches,cs_pointermath);
+ if changeinit then
+ include(init_settings.localswitches,cs_pointermath);
+ end
+ else
+ begin
+ exclude(current_settings.localswitches,cs_pointermath);
+ if changeinit then
+ exclude(init_settings.localswitches,cs_pointermath);
+ end;
+
+ { Default enum and set packing for delphi/tp7 }
+ if (m_tp7 in current_settings.modeswitches) or
+ (m_delphi in current_settings.modeswitches) then
+ begin
+ current_settings.packenum:=1;
+ current_settings.setalloc:=1;
+ end
+ else if (m_mac in current_settings.modeswitches) then
+ { compatible with Metrowerks Pascal }
+ current_settings.packenum:=2
+ else
+ current_settings.packenum:=4;
+ if changeinit then
+ init_settings.packenum:=current_settings.packenum;
+{$ifdef i386}
+ { Default to intel assembler for delphi/tp7 on i386 }
+ if (m_delphi in current_settings.modeswitches) or
+ (m_tp7 in current_settings.modeswitches) then
+ current_settings.asmmode:=asmmode_i386_intel;
+ if changeinit then
+ init_settings.asmmode:=current_settings.asmmode;
+{$endif i386}
+
+ { Exception support explicitly turned on (mainly for macpas, to }
+ { compensate for lack of interprocedural goto support) }
+ if (cs_support_exceptions in current_settings.globalswitches) then
+ include(current_settings.modeswitches,m_except);
+
+ { Default strict string var checking in TP/Delphi modes }
+ if ([m_delphi,m_tp7] * current_settings.modeswitches <> []) then
+ begin
+ include(current_settings.localswitches,cs_strict_var_strings);
+ if changeinit then
+ include(init_settings.localswitches,cs_strict_var_strings);
+ end;
+
+ { Undefine old symbol }
+ if (m_delphi in oldmodeswitches) then
+ undef_system_macro('FPC_DELPHI')
+ else if (m_tp7 in oldmodeswitches) then
+ undef_system_macro('FPC_TP')
+ else if (m_objfpc in oldmodeswitches) then
+ undef_system_macro('FPC_OBJFPC')
+{$ifdef gpc_mode}
+ else if (m_gpc in oldmodeswitches) then
+ undef_system_macro('FPC_GPC')
+{$endif}
+ else if (m_mac in oldmodeswitches) then
+ undef_system_macro('FPC_MACPAS');
+
+ { define new symbol in delphi,objfpc,tp,gpc,macpas mode }
+ if (m_delphi in current_settings.modeswitches) then
+ def_system_macro('FPC_DELPHI')
+ else if (m_tp7 in current_settings.modeswitches) then
+ def_system_macro('FPC_TP')
+ else if (m_objfpc in current_settings.modeswitches) then
+ def_system_macro('FPC_OBJFPC')
+{$ifdef gpc_mode}
+ else if (m_gpc in current_settings.modeswitches) then
+ def_system_macro('FPC_GPC')
+{$endif}
+ else if (m_mac in current_settings.modeswitches) then
+ def_system_macro('FPC_MACPAS');
+ end;
+
+ SetCompileMode:=b;
+ end;
+
+
+ Function SetCompileModeSwitch(s:string; changeInit: boolean):boolean;
+ var
+ i : tmodeswitch;
+ doinclude : boolean;
+ begin
+ s:=upper(s);
+
+ { on/off? }
+ doinclude:=true;
+ case s[length(s)] of
+ '+':
+ s:=copy(s,1,length(s)-1);
+ '-':
+ begin
+ s:=copy(s,1,length(s)-1);
+ doinclude:=false;
+ end;
+ end;
+
+ Result:=false;
+ for i:=m_class to high(tmodeswitch) do
+ if s=modeswitchstr[i] then
+ begin
+ { Objective-C is currently only supported for Darwin targets }
+ if doinclude and
+ (i in [m_objectivec1,m_objectivec2]) and
+ not(target_info.system in systems_objc_supported) then
+ begin
+ Message1(option_unsupported_target_for_feature,'Objective-C');
+ break;
+ end;
+
+ if changeInit then
+ current_settings.modeswitches:=init_settings.modeswitches;
+ Result:=true;
+ if doinclude then
+ begin
+ include(current_settings.modeswitches,i);
+ { Objective-C 2.0 support implies 1.0 support }
+ if (i=m_objectivec2) then
+ include(current_settings.modeswitches,m_objectivec1);
+ if (i in [m_objectivec1,m_objectivec2]) then
+ include(current_settings.modeswitches,m_class);
+ end
+ else
+ begin
+ exclude(current_settings.modeswitches,i);
+ { Objective-C 2.0 support implies 1.0 support }
+ if (i=m_objectivec2) then
+ exclude(current_settings.modeswitches,m_objectivec1);
+ if (i in [m_objectivec1,m_objectivec2]) and
+ ([m_delphi,m_objfpc]*current_settings.modeswitches=[]) then
+ exclude(current_settings.modeswitches,m_class);
+ end;
+
+ { set other switches depending on changed mode switch }
+ HandleModeSwitches(changeinit);
+
+ if changeInit then
+ init_settings.modeswitches:=current_settings.modeswitches;
+
+ break;
+ end;
+ end;
+
+{*****************************************************************************
+ Conditional Directives
+*****************************************************************************}
+
+ procedure dir_else;
+ begin
+ current_scanner.elsepreprocstack;
+ end;
+
+
+ procedure dir_endif;
+ begin
+ current_scanner.poppreprocstack;
+ end;
+
+ function isdef(var valuedescr: String): Boolean;
+ var
+ hs : string;
+ begin
+ current_scanner.skipspace;
+ hs:=current_scanner.readid;
+ valuedescr:= hs;
+ if hs='' then
+ Message(scan_e_error_in_preproc_expr);
+ isdef:=defined_macro(hs);
+ end;
+
+ procedure dir_ifdef;
+ begin
+ current_scanner.ifpreprocstack(pp_ifdef,@isdef,scan_c_ifdef_found);
+ end;
+
+ function isnotdef(var valuedescr: String): Boolean;
+ var
+ hs : string;
+ begin
+ current_scanner.skipspace;
+ hs:=current_scanner.readid;
+ valuedescr:= hs;
+ if hs='' then
+ Message(scan_e_error_in_preproc_expr);
+ isnotdef:=not defined_macro(hs);
+ end;
+
+ procedure dir_ifndef;
+ begin
+ current_scanner.ifpreprocstack(pp_ifndef,@isnotdef,scan_c_ifndef_found);
+ end;
+
+ function opt_check(var valuedescr: String): Boolean;
+ var
+ hs : string;
+ state : char;
+ begin
+ opt_check:= false;
+ current_scanner.skipspace;
+ hs:=current_scanner.readid;
+ valuedescr:= hs;
+ if (length(hs)>1) then
+ Message1(scan_w_illegal_switch,hs)
+ else
+ begin
+ state:=current_scanner.ReadState;
+ if state in ['-','+'] then
+ opt_check:=CheckSwitch(hs[1],state)
+ else
+ Message(scan_e_error_in_preproc_expr);
+ end;
+ end;
+
+ procedure dir_ifopt;
+ begin
+ flushpendingswitchesstate;
+ current_scanner.ifpreprocstack(pp_ifopt,@opt_check,scan_c_ifopt_found);
+ end;
+
+ procedure dir_libprefix;
+ var
+ s : string;
+ begin
+ current_scanner.skipspace;
+ if c <> '''' then
+ Message2(scan_f_syn_expected, '''', c);
+ s := current_scanner.readquotedstring;
+ stringdispose(outputprefix);
+ outputprefix := stringdup(s);
+ with current_module do
+ setfilename(paramfn^, paramallowoutput);
+ end;
+
+ procedure dir_libsuffix;
+ var
+ s : string;
+ begin
+ current_scanner.skipspace;
+ if c <> '''' then
+ Message2(scan_f_syn_expected, '''', c);
+ s := current_scanner.readquotedstring;
+ stringdispose(outputsuffix);
+ outputsuffix := stringdup(s);
+ with current_module do
+ setfilename(paramfn^, paramallowoutput);
+ end;
+
+ procedure dir_extension;
+ var
+ s : string;
+ begin
+ current_scanner.skipspace;
+ if c <> '''' then
+ Message2(scan_f_syn_expected, '''', c);
+ s := current_scanner.readquotedstring;
+ if OutputFileName='' then
+ OutputFileName:=InputFileName;
+ OutputFileName:=ChangeFileExt(OutputFileName,'.'+s);
+ with current_module do
+ setfilename(paramfn^, paramallowoutput);
+ end;
+
+{
+Compile time expression type check
+----------------------------------
+Each subexpression returns its type to the caller, which then can
+do type check. Since data types of compile time expressions is
+not well defined, the type system does a best effort. The drawback is
+that some errors might not be detected.
+
+Instead of returning a particular data type, a set of possible data types
+are returned. This way ambigouos types can be handled. For instance a
+value of 1 can be both a boolean and and integer.
+
+Booleans
+--------
+
+The following forms of boolean values are supported:
+* C coded, that is 0 is false, non-zero is true.
+* TRUE/FALSE for mac style compile time variables
+
+Thus boolean mac compile time variables are always stored as TRUE/FALSE.
+When a compile time expression is evaluated, they are then translated
+to C coded booleans (0/1), to simplify for the expression evaluator.
+
+Note that this scheme then also of support mac compile time variables which
+are 0/1 but with a boolean meaning.
+
+The TRUE/FALSE format is new from 22 august 2005, but the above scheme
+means that units which is not recompiled, and thus stores
+compile time variables as the old format (0/1), continue to work.
+
+Short circuit evaluation
+------------------------
+For this to work, the part of a compile time expression which is short
+circuited, should not be evaluated, while it still should be parsed.
+Therefor there is a parameter eval, telling whether evaluation is needed.
+In case not, the value returned can be arbitrary.
+}
+
+ type
+ {Compile time expression types}
+ TCTEType = (ctetBoolean, ctetInteger, ctetString, ctetSet);
+ TCTETypeSet = set of TCTEType;
+
+ const
+ cteTypeNames : array[TCTEType] of string[10] = (
+ 'BOOLEAN','INTEGER','STRING','SET');
+
+ {Subset of types which can be elements in sets.}
+ setelementdefs = [ctetBoolean, ctetInteger, ctetString];
+
+
+ function GetCTETypeName(t: TCTETypeSet): String;
+ var
+ i: TCTEType;
+ begin
+ result:= '';
+ for i:= Low(TCTEType) to High(TCTEType) do
+ if i in t then
+ if result = '' then
+ result:= cteTypeNames[i]
+ else
+ result:= result + ' or ' + cteTypeNames[i];
+ end;
+
+ procedure CTEError(actType, desiredExprType: TCTETypeSet; place: String);
+
+ begin
+ Message3(scan_e_compile_time_typeerror,
+ GetCTETypeName(desiredExprType),
+ GetCTETypeName(actType),
+ place
+ );
+ end;
+
+ function parse_compiler_expr(var compileExprType: TCTETypeSet):string;
+
+ function read_expr(var exprType: TCTETypeSet; eval : Boolean) : string; forward;
+
+ procedure preproc_consume(t : ttoken);
+ begin
+ if t<>current_scanner.preproc_token then
+ Message(scan_e_preproc_syntax_error);
+ current_scanner.preproc_token:=current_scanner.readpreproc;
+ end;
+
+ function preproc_substitutedtoken(var macroType: TCTETypeSet; eval : Boolean): string;
+ { Currently this parses identifiers as well as numbers.
+ The result from this procedure can either be that the token
+ itself is a value, or that it is a compile time variable/macro,
+ which then is substituted for another value (for macros
+ recursivelly substituted).}
+
+ var
+ hs: string;
+ mac : tmacro;
+ macrocount,
+ len : integer;
+ numres : longint;
+ w: word;
+ begin
+ result := current_scanner.preproc_pattern;
+ if not eval then
+ exit;
+
+ mac:= nil;
+ { Substitue macros and compiler variables with their content/value.
+ For real macros also do recursive substitution. }
+ macrocount:=0;
+ repeat
+ mac:=tmacro(search_macro(result));
+
+ inc(macrocount);
+ if macrocount>max_macro_nesting then
+ begin
+ Message(scan_w_macro_too_deep);
+ break;
+ end;
+
+ if assigned(mac) and mac.defined then
+ if assigned(mac.buftext) then
+ begin
+ if mac.buflen>255 then
+ begin
+ len:=255;
+ Message(scan_w_macro_cut_after_255_chars);
+ end
+ else
+ len:=mac.buflen;
+ hs[0]:=char(len);
+ move(mac.buftext^,hs[1],len);
+ result:=upcase(hs);
+ mac.is_used:=true;
+ end
+ else
+ begin
+ Message1(scan_e_error_macro_lacks_value, result);
+ break;
+ end
+ else
+ begin
+ break;
+ end;
+
+ if mac.is_compiler_var then
+ break;
+ until false;
+
+ { At this point, result do contain the value. Do some decoding and
+ determine the type.}
+ val(result,numres,w);
+ if (w=0) then {It is an integer}
+ begin
+ if (numres = 0) or (numres = 1) then
+ macroType := [ctetInteger, ctetBoolean]
+ else
+ macroType := [ctetInteger];
+ end
+ else if assigned(mac) and (m_mac in current_settings.modeswitches) and (result='FALSE') then
+ begin
+ result:= '0';
+ macroType:= [ctetBoolean];
+ end
+ else if assigned(mac) and (m_mac in current_settings.modeswitches) and (result='TRUE') then
+ begin
+ result:= '1';
+ macroType:= [ctetBoolean];
+ end
+ else if (m_mac in current_settings.modeswitches) and
+ (not assigned(mac) or not mac.defined) and
+ (macrocount = 1) then
+ begin
+ {Errors in mode mac is issued here. For non macpas modes there is
+ more liberty, but the error will eventually be caught at a later stage.}
+ Message1(scan_e_error_macro_undefined, result);
+ macroType:= [ctetString]; {Just to have something}
+ end
+ else
+ macroType:= [ctetString];
+ end;
+
+ function read_factor(var factorType: TCTETypeSet; eval : Boolean) : string;
+ var
+ hs : string;
+ mac: tmacro;
+ srsym : tsym;
+ srsymtable : TSymtable;
+ hdef : TDef;
+ l : longint;
+ w : integer;
+ hasKlammer: Boolean;
+ setElemType : TCTETypeSet;
+
+ begin
+ if current_scanner.preproc_token=_ID then
+ begin
+ if current_scanner.preproc_pattern='DEFINED' then
+ begin
+ factorType:= [ctetBoolean];
+ preproc_consume(_ID);
+ current_scanner.skipspace;
+ if current_scanner.preproc_token =_LKLAMMER then
+ begin
+ preproc_consume(_LKLAMMER);
+ current_scanner.skipspace;
+ hasKlammer:= true;
+ end
+ else if (m_mac in current_settings.modeswitches) then
+ hasKlammer:= false
+ else
+ Message(scan_e_error_in_preproc_expr);
+
+ if current_scanner.preproc_token =_ID then
+ begin
+ hs := current_scanner.preproc_pattern;
+ mac := tmacro(search_macro(hs));
+ if assigned(mac) and mac.defined then
+ begin
+ hs := '1';
+ mac.is_used:=true;
+ end
+ else
+ hs := '0';
+ read_factor := hs;
+ preproc_consume(_ID);
+ current_scanner.skipspace;
+ end
+ else
+ Message(scan_e_error_in_preproc_expr);
+
+ if hasKlammer then
+ if current_scanner.preproc_token =_RKLAMMER then
+ preproc_consume(_RKLAMMER)
+ else
+ Message(scan_e_error_in_preproc_expr);
+ end
+ else
+ if (m_mac in current_settings.modeswitches) and (current_scanner.preproc_pattern='UNDEFINED') then
+ begin
+ factorType:= [ctetBoolean];
+ preproc_consume(_ID);
+ current_scanner.skipspace;
+ if current_scanner.preproc_token =_ID then
+ begin
+ hs := current_scanner.preproc_pattern;
+ mac := tmacro(search_macro(hs));
+ if assigned(mac) then
+ begin
+ hs := '0';
+ mac.is_used:=true;
+ end
+ else
+ hs := '1';
+ read_factor := hs;
+ preproc_consume(_ID);
+ current_scanner.skipspace;
+ end
+ else
+ Message(scan_e_error_in_preproc_expr);
+ end
+ else
+ if (m_mac in current_settings.modeswitches) and (current_scanner.preproc_pattern='OPTION') then
+ begin
+ factorType:= [ctetBoolean];
+ preproc_consume(_ID);
+ current_scanner.skipspace;
+ if current_scanner.preproc_token =_LKLAMMER then
+ begin
+ preproc_consume(_LKLAMMER);
+ current_scanner.skipspace;
+ end
+ else
+ Message(scan_e_error_in_preproc_expr);
+
+ if not (current_scanner.preproc_token = _ID) then
+ Message(scan_e_error_in_preproc_expr);
+
+ hs:=current_scanner.preproc_pattern;
+ if (length(hs) > 1) then
+ {This is allowed in Metrowerks Pascal}
+ Message(scan_e_error_in_preproc_expr)
+ else
+ begin
+ if CheckSwitch(hs[1],'+') then
+ read_factor := '1'
+ else
+ read_factor := '0';
+ end;
+
+ preproc_consume(_ID);
+ current_scanner.skipspace;
+ if current_scanner.preproc_token =_RKLAMMER then
+ preproc_consume(_RKLAMMER)
+ else
+ Message(scan_e_error_in_preproc_expr);
+ end
+ else
+ if current_scanner.preproc_pattern='SIZEOF' then
+ begin
+ factorType:= [ctetInteger];
+ preproc_consume(_ID);
+ current_scanner.skipspace;
+ if current_scanner.preproc_token =_LKLAMMER then
+ begin
+ preproc_consume(_LKLAMMER);
+ current_scanner.skipspace;
+ end
+ else
+ Message(scan_e_preproc_syntax_error);
+
+ if eval then
+ if searchsym(current_scanner.preproc_pattern,srsym,srsymtable) then
+ begin
+ l:=0;
+ case srsym.typ of
+ staticvarsym,
+ localvarsym,
+ paravarsym :
+ l:=tabstractvarsym(srsym).getsize;
+ typesym:
+ l:=ttypesym(srsym).typedef.size;
+ else
+ Message(scan_e_error_in_preproc_expr);
+ end;
+ str(l,read_factor);
+ end
+ else
+ Message1(sym_e_id_not_found,current_scanner.preproc_pattern);
+
+ preproc_consume(_ID);
+ current_scanner.skipspace;
+
+ if current_scanner.preproc_token =_RKLAMMER then
+ preproc_consume(_RKLAMMER)
+ else
+ Message(scan_e_preproc_syntax_error);
+ end
+ else
+ if current_scanner.preproc_pattern='HIGH' then
+ begin
+ factorType:= [ctetInteger];
+ preproc_consume(_ID);
+ current_scanner.skipspace;
+ if current_scanner.preproc_token =_LKLAMMER then
+ begin
+ preproc_consume(_LKLAMMER);
+ current_scanner.skipspace;
+ end
+ else
+ Message(scan_e_preproc_syntax_error);
+
+ if eval then
+ if searchsym(current_scanner.preproc_pattern,srsym,srsymtable) then
+ begin
+ hdef:=nil;
+ hs:='';
+ l:=0;
+ case srsym.typ of
+ staticvarsym,
+ localvarsym,
+ paravarsym :
+ hdef:=tabstractvarsym(srsym).vardef;
+ typesym:
+ hdef:=ttypesym(srsym).typedef;
+ else
+ Message(scan_e_error_in_preproc_expr);
+ end;
+ if hdef<>nil then
+ begin
+ if hdef.typ=setdef then
+ hdef:=tsetdef(hdef).elementdef;
+ case hdef.typ of
+ orddef:
+ with torddef(hdef).high do
+ if signed then
+ str(svalue,hs)
+ else
+ str(uvalue,hs);
+ enumdef:
+ l:=tenumdef(hdef).maxval;
+ arraydef:
+ if is_open_array(hdef) or is_array_of_const(hdef) or is_dynamic_array(hdef) then
+ Message(type_e_mismatch)
+ else
+ l:=tarraydef(hdef).highrange;
+ stringdef:
+ if is_open_string(hdef) or is_ansistring(hdef) or is_wide_or_unicode_string(hdef) then
+ Message(type_e_mismatch)
+ else
+ l:=tstringdef(hdef).len;
+ else
+ Message(type_e_mismatch);
+ end;
+ end;
+ if hs='' then
+ str(l,read_factor)
+ else
+ read_factor:=hs;
+ end
+ else
+ Message1(sym_e_id_not_found,current_scanner.preproc_pattern);
+
+ preproc_consume(_ID);
+ current_scanner.skipspace;
+
+ if current_scanner.preproc_token =_RKLAMMER then
+ preproc_consume(_RKLAMMER)
+ else
+ Message(scan_e_preproc_syntax_error);
+ end
+ else
+ if current_scanner.preproc_pattern='DECLARED' then
+ begin
+ factorType:= [ctetBoolean];
+ preproc_consume(_ID);
+ current_scanner.skipspace;
+ if current_scanner.preproc_token =_LKLAMMER then
+ begin
+ preproc_consume(_LKLAMMER);
+ current_scanner.skipspace;
+ end
+ else
+ Message(scan_e_error_in_preproc_expr);
+ if current_scanner.preproc_token =_ID then
+ begin
+ hs := upper(current_scanner.preproc_pattern);
+ if searchsym(hs,srsym,srsymtable) then
+ hs := '1'
+ else
+ hs := '0';
+ read_factor := hs;
+ preproc_consume(_ID);
+ current_scanner.skipspace;
+ end
+ else
+ Message(scan_e_error_in_preproc_expr);
+ if current_scanner.preproc_token =_RKLAMMER then
+ preproc_consume(_RKLAMMER)
+ else
+ Message(scan_e_error_in_preproc_expr);
+ end
+ else
+ if current_scanner.preproc_pattern='NOT' then
+ begin
+ factorType:= [ctetBoolean];
+ preproc_consume(_ID);
+ hs:=read_factor(factorType, eval);
+ if eval then
+ begin
+ if not (ctetBoolean in factorType) then
+ CTEError(factorType, [ctetBoolean], 'NOT');
+ val(hs,l,w);
+ if l<>0 then
+ read_factor:='0'
+ else
+ read_factor:='1';
+ end
+ else
+ read_factor:='0'; {Just to have something}
+ end
+ else
+ if (m_mac in current_settings.modeswitches) and (current_scanner.preproc_pattern='TRUE') then
+ begin
+ factorType:= [ctetBoolean];
+ preproc_consume(_ID);
+ read_factor:='1';
+ end
+ else
+ if (m_mac in current_settings.modeswitches) and (current_scanner.preproc_pattern='FALSE') then
+ begin
+ factorType:= [ctetBoolean];
+ preproc_consume(_ID);
+ read_factor:='0';
+ end
+ else
+ begin
+ hs:=preproc_substitutedtoken(factorType, eval);
+
+ { Default is to return the original symbol }
+ read_factor:=hs;
+ if eval and ([m_delphi,m_objfpc]*current_settings.modeswitches<>[]) and (ctetString in factorType) then
+ if searchsym(current_scanner.preproc_pattern,srsym,srsymtable) then
+ begin
+ case srsym.typ of
+ constsym :
+ begin
+ with tconstsym(srsym) do
+ begin
+ case consttyp of
+ constord :
+ begin
+ case constdef.typ of
+ orddef:
+ begin
+ if is_integer(constdef) then
+ begin
+ read_factor:=tostr(value.valueord);
+ factorType:= [ctetInteger];
+ end
+ else if is_boolean(constdef) then
+ begin
+ read_factor:=tostr(value.valueord);
+ factorType:= [ctetBoolean];
+ end
+ else if is_char(constdef) then
+ begin
+ read_factor:=char(qword(value.valueord));
+ factorType:= [ctetString];
+ end
+ end;
+ enumdef:
+ begin
+ read_factor:=tostr(value.valueord);
+ factorType:= [ctetInteger];
+ end;
+ end;
+ end;
+ conststring :
+ begin
+ read_factor := upper(pchar(value.valueptr));
+ factorType:= [ctetString];
+ end;
+ constset :
+ begin
+ hs:=',';
+ for l:=0 to 255 do
+ if l in pconstset(tconstsym(srsym).value.valueptr)^ then
+ hs:=hs+tostr(l)+',';
+ read_factor := hs;
+ factorType:= [ctetSet];
+ end;
+ end;
+ end;
+ end;
+ enumsym :
+ begin
+ read_factor:=tostr(tenumsym(srsym).value);
+ factorType:= [ctetInteger];
+ end;
+ end;
+ end;
+ preproc_consume(_ID);
+ current_scanner.skipspace;
+ end
+ end
+ else if current_scanner.preproc_token =_LKLAMMER then
+ begin
+ preproc_consume(_LKLAMMER);
+ read_factor:=read_expr(factorType, eval);
+ preproc_consume(_RKLAMMER);
+ end
+ else if current_scanner.preproc_token = _LECKKLAMMER then
+ begin
+ preproc_consume(_LECKKLAMMER);
+ read_factor := ',';
+ while current_scanner.preproc_token = _ID do
+ begin
+ read_factor := read_factor+read_factor(setElemType, eval)+',';
+ if current_scanner.preproc_token = _COMMA then
+ preproc_consume(_COMMA);
+ end;
+ // TODO Add check of setElemType
+ preproc_consume(_RECKKLAMMER);
+ factorType:= [ctetSet];
+ end
+ else
+ Message(scan_e_error_in_preproc_expr);
+ end;
+
+ function read_term(var termType: TCTETypeSet; eval : Boolean) : string;
+ var
+ hs1,hs2 : string;
+ l1,l2 : longint;
+ w : integer;
+ termType2: TCTETypeSet;
+ begin
+ hs1:=read_factor(termType, eval);
+ repeat
+ if (current_scanner.preproc_token<>_ID) then
+ break;
+ if current_scanner.preproc_pattern<>'AND' then
+ break;
+
+ val(hs1,l1,w);
+ if l1=0 then
+ eval:= false; {Short circuit evaluation of OR}
+
+ if eval then
+ begin
+ {Check if first expr is boolean. Must be done here, after we know
+ it is an AND expression.}
+ if not (ctetBoolean in termType) then
+ CTEError(termType, [ctetBoolean], 'AND');
+ termType:= [ctetBoolean];
+ end;
+
+ preproc_consume(_ID);
+ hs2:=read_factor(termType2, eval);
+
+ if eval then
+ begin
+ if not (ctetBoolean in termType2) then
+ CTEError(termType2, [ctetBoolean], 'AND');
+
+ val(hs2,l2,w);
+ if (l1<>0) and (l2<>0) then
+ hs1:='1'
+ else
+ hs1:='0';
+ end;
+ until false;
+ read_term:=hs1;
+ end;
+
+
+ function read_simple_expr(var simpleExprType: TCTETypeSet; eval : Boolean) : string;
+ var
+ hs1,hs2 : string;
+ l1,l2 : longint;
+ w : integer;
+ simpleExprType2: TCTETypeSet;
+ begin
+ hs1:=read_term(simpleExprType, eval);
+ repeat
+ if (current_scanner.preproc_token<>_ID) then
+ break;
+ if current_scanner.preproc_pattern<>'OR' then
+ break;
+
+ val(hs1,l1,w);
+ if l1<>0 then
+ eval:= false; {Short circuit evaluation of OR}
+
+ if eval then
+ begin
+ {Check if first expr is boolean. Must be done here, after we know
+ it is an OR expression.}
+ if not (ctetBoolean in simpleExprType) then
+ CTEError(simpleExprType, [ctetBoolean], 'OR');
+ simpleExprType:= [ctetBoolean];
+ end;
+
+ preproc_consume(_ID);
+ hs2:=read_term(simpleExprType2, eval);
+
+ if eval then
+ begin
+ if not (ctetBoolean in simpleExprType2) then
+ CTEError(simpleExprType2, [ctetBoolean], 'OR');
+
+ val(hs2,l2,w);
+ if (l1<>0) or (l2<>0) then
+ hs1:='1'
+ else
+ hs1:='0';
+ end;
+ until false;
+ read_simple_expr:=hs1;
+ end;
+
+ function read_expr(var exprType: TCTETypeSet; eval : Boolean) : string;
+ var
+ hs1,hs2 : string;
+ b : boolean;
+ op : ttoken;
+ w : integer;
+ l1,l2 : longint;
+ exprType2: TCTETypeSet;
+ begin
+ hs1:=read_simple_expr(exprType, eval);
+ op:=current_scanner.preproc_token;
+ if (op = _ID) and (current_scanner.preproc_pattern = 'IN') then
+ op := _IN;
+ if not (op in [_IN,_EQ,_NE,_LT,_GT,_LTE,_GTE]) then
+ begin
+ read_expr:=hs1;
+ exit;
+ end;
+
+ if (op = _IN) then
+ preproc_consume(_ID)
+ else
+ preproc_consume(op);
+ hs2:=read_simple_expr(exprType2, eval);
+
+ if eval then
+ begin
+ if op = _IN then
+ begin
+ if exprType2 <> [ctetSet] then
+ CTEError(exprType2, [ctetSet], 'IN');
+ if exprType = [ctetSet] then
+ CTEError(exprType, setelementdefs, 'IN');
+
+ if is_number(hs1) and is_number(hs2) then
+ Message(scan_e_preproc_syntax_error)
+ else if hs2[1] = ',' then
+ b:=pos(','+hs1+',', hs2) > 0 { TODO For integer sets, perhaps check for numeric equivalence so that 0 = 00 }
+ else
+ Message(scan_e_preproc_syntax_error);
+ end
+ else
+ begin
+ if (exprType * exprType2) = [] then
+ CTEError(exprType2, exprType, '"'+hs1+' '+tokeninfo^[op].str+' '+hs2+'"');
+
+ if is_number(hs1) and is_number(hs2) then
+ begin
+ val(hs1,l1,w);
+ val(hs2,l2,w);
+ case op of
+ _EQ :
+ b:=l1=l2;
+ _NE :
+ b:=l1<>l2;
+ _LT :
+ b:=l1<l2;
+ _GT :
+ b:=l1>l2;
+ _GTE :
+ b:=l1>=l2;
+ _LTE :
+ b:=l1<=l2;
+ end;
+ end
+ else
+ begin
+ case op of
+ _EQ:
+ b:=hs1=hs2;
+ _NE :
+ b:=hs1<>hs2;
+ _LT :
+ b:=hs1<hs2;
+ _GT :
+ b:=hs1>hs2;
+ _GTE :
+ b:=hs1>=hs2;
+ _LTE :
+ b:=hs1<=hs2;
+ end;
+ end;
+ end;
+ end
+ else
+ b:= false; {Just to have something}
+
+ if b then
+ read_expr:='1'
+ else
+ read_expr:='0';
+ exprType:= [ctetBoolean];
+ end;
+
+ begin
+ current_scanner.skipspace;
+ { start preproc expression scanner }
+ current_scanner.preproc_token:=current_scanner.readpreproc;
+ parse_compiler_expr:=read_expr(compileExprType, true);
+ end;
+
+ function boolean_compile_time_expr(var valuedescr: String): Boolean;
+ var
+ hs : string;
+ exprType: TCTETypeSet;
+ begin
+ hs:=parse_compiler_expr(exprType);
+ if (exprType * [ctetBoolean]) = [] then
+ CTEError(exprType, [ctetBoolean], 'IF or ELSEIF');
+ boolean_compile_time_expr:= hs <> '0';
+ valuedescr:= hs;
+ end;
+
+ procedure dir_if;
+ begin
+ current_scanner.ifpreprocstack(pp_if,@boolean_compile_time_expr, scan_c_if_found);
+ end;
+
+ procedure dir_elseif;
+ begin
+ current_scanner.elseifpreprocstack(@boolean_compile_time_expr);
+ end;
+
+ procedure dir_define_impl(macstyle: boolean);
+ var
+ hs : string;
+ bracketcount : longint;
+ mac : tmacro;
+ macropos : longint;
+ macrobuffer : pmacrobuffer;
+ begin
+ current_scanner.skipspace;
+ hs:=current_scanner.readid;
+ mac:=tmacro(search_macro(hs));
+ if not assigned(mac) or (mac.owner <> current_module.localmacrosymtable) then
+ begin
+ mac:=tmacro.create(hs);
+ mac.defined:=true;
+ current_module.localmacrosymtable.insert(mac);
+ end
+ else
+ begin
+ mac.defined:=true;
+ mac.is_compiler_var:=false;
+ { delete old definition }
+ if assigned(mac.buftext) then
+ begin
+ freemem(mac.buftext,mac.buflen);
+ mac.buftext:=nil;
+ end;
+ end;
+ Message1(parser_c_macro_defined,mac.name);
+ mac.is_used:=true;
+ if (cs_support_macro in current_settings.moduleswitches) then
+ begin
+ current_scanner.skipspace;
+
+ if not macstyle then
+ begin
+ { may be a macro? }
+ if c <> ':' then
+ exit;
+ current_scanner.readchar;
+ if c <> '=' then
+ exit;
+ current_scanner.readchar;
+ current_scanner.skipspace;
+ end;
+
+ { key words are never substituted }
+ if is_keyword(hs) then
+ Message(scan_e_keyword_cant_be_a_macro);
+
+ new(macrobuffer);
+ macropos:=0;
+ { parse macro, brackets are counted so it's possible
+ to have a $ifdef etc. in the macro }
+ bracketcount:=0;
+ repeat
+ case c of
+ '}' :
+ if (bracketcount=0) then
+ break
+ else
+ dec(bracketcount);
+ '{' :
+ inc(bracketcount);
+ #10,#13 :
+ current_scanner.linebreak;
+ #26 :
+ current_scanner.end_of_file;
+ end;
+ macrobuffer^[macropos]:=c;
+ inc(macropos);
+ if macropos>=maxmacrolen then
+ Message(scan_f_macro_buffer_overflow);
+ current_scanner.readchar;
+ until false;
+
+ { free buffer of macro ?}
+ if assigned(mac.buftext) then
+ freemem(mac.buftext,mac.buflen);
+ { get new mem }
+ getmem(mac.buftext,macropos);
+ mac.buflen:=macropos;
+ { copy the text }
+ move(macrobuffer^,mac.buftext^,macropos);
+ dispose(macrobuffer);
+ end
+ else
+ begin
+ { check if there is an assignment, then we need to give a
+ warning }
+ current_scanner.skipspace;
+ if c=':' then
+ begin
+ current_scanner.readchar;
+ if c='=' then
+ Message(scan_w_macro_support_turned_off);
+ end;
+ end;
+ end;
+
+ procedure dir_define;
+ begin
+ dir_define_impl(false);
+ end;
+
+ procedure dir_definec;
+ begin
+ dir_define_impl(true);
+ end;
+
+ procedure dir_setc;
+ var
+ hs : string;
+ mac : tmacro;
+ exprType: TCTETypeSet;
+ l : longint;
+ w : integer;
+ begin
+ current_scanner.skipspace;
+ hs:=current_scanner.readid;
+ mac:=tmacro(search_macro(hs));
+ if not assigned(mac) or
+ (mac.owner <> current_module.localmacrosymtable) then
+ begin
+ mac:=tmacro.create(hs);
+ mac.defined:=true;
+ mac.is_compiler_var:=true;
+ current_module.localmacrosymtable.insert(mac);
+ end
+ else
+ begin
+ mac.defined:=true;
+ mac.is_compiler_var:=true;
+ { delete old definition }
+ if assigned(mac.buftext) then
+ begin
+ freemem(mac.buftext,mac.buflen);
+ mac.buftext:=nil;
+ end;
+ end;
+ Message1(parser_c_macro_defined,mac.name);
+ mac.is_used:=true;
+
+ { key words are never substituted }
+ if is_keyword(hs) then
+ Message(scan_e_keyword_cant_be_a_macro);
+
+ { macro assignment can be both := and = }
+ current_scanner.skipspace;
+ if c=':' then
+ current_scanner.readchar;
+ if c='=' then
+ begin
+ current_scanner.readchar;
+ hs:= parse_compiler_expr(exprType);
+ if (exprType * [ctetBoolean, ctetInteger]) = [] then
+ CTEError(exprType, [ctetBoolean, ctetInteger], 'SETC');
+
+ if length(hs) <> 0 then
+ begin
+ {If we are absolutely shure it is boolean, translate
+ to TRUE/FALSE to increase possibility to do future type check}
+ if exprType = [ctetBoolean] then
+ begin
+ val(hs,l,w);
+ if l<>0 then
+ hs:='TRUE'
+ else
+ hs:='FALSE';
+ end;
+ Message2(parser_c_macro_set_to,mac.name,hs);
+ { free buffer of macro ?}
+ if assigned(mac.buftext) then
+ freemem(mac.buftext,mac.buflen);
+ { get new mem }
+ getmem(mac.buftext,length(hs));
+ mac.buflen:=length(hs);
+ { copy the text }
+ move(hs[1],mac.buftext^,mac.buflen);
+ end
+ else
+ Message(scan_e_preproc_syntax_error);
+ end
+ else
+ Message(scan_e_preproc_syntax_error);
+ end;
+
+
+ procedure dir_undef;
+ var
+ hs : string;
+ mac : tmacro;
+ begin
+ current_scanner.skipspace;
+ hs:=current_scanner.readid;
+ mac:=tmacro(search_macro(hs));
+ if not assigned(mac) or
+ (mac.owner <> current_module.localmacrosymtable) then
+ begin
+ mac:=tmacro.create(hs);
+ mac.defined:=false;
+ current_module.localmacrosymtable.insert(mac);
+ end
+ else
+ begin
+ mac.defined:=false;
+ mac.is_compiler_var:=false;
+ { delete old definition }
+ if assigned(mac.buftext) then
+ begin
+ freemem(mac.buftext,mac.buflen);
+ mac.buftext:=nil;
+ end;
+ end;
+ Message1(parser_c_macro_undefined,mac.name);
+ mac.is_used:=true;
+ end;
+
+ procedure dir_include;
+
+ function findincludefile(const path,name:TCmdStr;var foundfile:TCmdStr):boolean;
+ var
+ found : boolean;
+ hpath : TCmdStr;
+ begin
+ (* look for the include file
+ If path was absolute and specified as part of {$I } then
+ 1. specified path
+ else
+ 1. path of current inputfile,current dir
+ 2. local includepath
+ 3. global includepath
+
+ -- Check mantis #13461 before changing this *)
+ found:=false;
+ foundfile:='';
+ hpath:='';
+ if path_absolute(path) then
+ begin
+ found:=FindFile(name,path,true,foundfile);
+ end
+ else
+ begin
+ hpath:=current_scanner.inputfile.path^+';'+CurDirRelPath(source_info);
+ found:=FindFile(path+name, hpath,true,foundfile);
+ if not found then
+ found:=current_module.localincludesearchpath.FindFile(path+name,true,foundfile);
+ if not found then
+ found:=includesearchpath.FindFile(path+name,true,foundfile);
+ end;
+ result:=found;
+ end;
+
+ var
+ foundfile : TCmdStr;
+ path,
+ name,
+ hs : tpathstr;
+ args : string;
+ hp : tinputfile;
+ found : boolean;
+ begin
+ current_scanner.skipspace;
+ args:=current_scanner.readcomment;
+ hs:=GetToken(args,' ');
+ if hs='' then
+ exit;
+ if (hs[1]='%') then
+ begin
+ { case insensitive }
+ hs:=upper(hs);
+ { remove %'s }
+ Delete(hs,1,1);
+ if hs[length(hs)]='%' then
+ Delete(hs,length(hs),1);
+ { save old }
+ path:=hs;
+ { first check for internal macros }
+ if hs='TIME' then
+ hs:=gettimestr
+ else
+ if hs='DATE' then
+ hs:=getdatestr
+ else
+ if hs='FILE' then
+ hs:=current_module.sourcefiles.get_file_name(current_filepos.fileindex)
+ else
+ if hs='LINE' then
+ hs:=tostr(current_filepos.line)
+ else
+ if hs='FPCVERSION' then
+ hs:=version_string
+ else
+ if hs='FPCDATE' then
+ hs:=date_string
+ else
+ if hs='FPCTARGET' then
+ hs:=target_cpu_string
+ else
+ if hs='FPCTARGETCPU' then
+ hs:=target_cpu_string
+ else
+ if hs='FPCTARGETOS' then
+ hs:=target_info.shortname
+ else
+ hs:=GetEnvironmentVariable(hs);
+ if hs='' then
+ Message1(scan_w_include_env_not_found,path);
+ { make it a stringconst }
+ hs:=''''+hs+'''';
+ current_scanner.insertmacro(path,@hs[1],length(hs),
+ current_scanner.line_no,current_scanner.inputfile.ref_index);
+ end
+ else
+ begin
+ hs:=FixFileName(hs);
+ path:=ExtractFilePath(hs);
+ name:=ExtractFileName(hs);
+ { Special case for Delphi compatibility: '*' has to be replaced
+ by the file name of the current source file. }
+ if (length(name)>=1) and
+ (name[1]='*') then
+ name:=ChangeFileExt(current_module.sourcefiles.get_file_name(current_filepos.fileindex),'')+ExtractFileExt(name);
+
+ { try to find the file }
+ found:=findincludefile(path,name,foundfile);
+ if (ExtractFileExt(name)='') then
+ begin
+ { try default extensions .inc , .pp and .pas }
+ if (not found) then
+ found:=findincludefile(path,ChangeFileExt(name,'.inc'),foundfile);
+ if (not found) then
+ found:=findincludefile(path,ChangeFileExt(name,sourceext),foundfile);
+ if (not found) then
+ found:=findincludefile(path,ChangeFileExt(name,pasext),foundfile);
+ end;
+ if current_scanner.inputfilecount<max_include_nesting then
+ begin
+ inc(current_scanner.inputfilecount);
+ { we need to reread the current char }
+ dec(current_scanner.inputpointer);
+ { shutdown current file }
+ current_scanner.tempcloseinputfile;
+ { load new file }
+ hp:=do_openinputfile(foundfile);
+ current_scanner.addfile(hp);
+ current_module.sourcefiles.register_file(hp);
+ if (not found) then
+ Message1(scan_f_cannot_open_includefile,hs);
+ if (not current_scanner.openinputfile) then
+ Message1(scan_f_cannot_open_includefile,hs);
+ Message1(scan_t_start_include_file,current_scanner.inputfile.path^+current_scanner.inputfile.name^);
+ current_scanner.reload;
+ end
+ else
+ Message(scan_f_include_deep_ten);
+ end;
+ end;
+
+
+{*****************************************************************************
+ Preprocessor writing
+*****************************************************************************}
+
+{$ifdef PREPROCWRITE}
+ constructor tpreprocfile.create(const fn:string);
+ begin
+ { open outputfile }
+ assign(f,fn);
+ {$push}{$I-}
+ rewrite(f);
+ {$pop}
+ if ioresult<>0 then
+ Comment(V_Fatal,'can''t create file '+fn);
+ getmem(buf,preprocbufsize);
+ settextbuf(f,buf^,preprocbufsize);
+ { reset }
+ eolfound:=false;
+ spacefound:=false;
+ end;
+
+
+ destructor tpreprocfile.destroy;
+ begin
+ close(f);
+ freemem(buf,preprocbufsize);
+ end;
+
+
+ procedure tpreprocfile.add(const s:string);
+ begin
+ write(f,s);
+ end;
+
+ procedure tpreprocfile.addspace;
+ begin
+ if eolfound then
+ begin
+ writeln(f,'');
+ eolfound:=false;
+ spacefound:=false;
+ end
+ else
+ if spacefound then
+ begin
+ write(f,' ');
+ spacefound:=false;
+ end;
+ end;
+{$endif PREPROCWRITE}
+
+
+{*****************************************************************************
+ TPreProcStack
+*****************************************************************************}
+
+ constructor tpreprocstack.create(atyp : preproctyp;a:boolean;n:tpreprocstack);
+ begin
+ accept:=a;
+ typ:=atyp;
+ next:=n;
+ end;
+
+{*****************************************************************************
+ TReplayStack
+*****************************************************************************}
+ constructor treplaystack.Create(atoken:ttoken;asettings:tsettings;
+ atokenbuf:tdynamicarray;anext:treplaystack;achange_endian : boolean);
+ begin
+ token:=atoken;
+ settings:=asettings;
+ tokenbuf:=atokenbuf;
+ change_endian:=achange_endian;
+ next:=anext;
+ end;
+
+{*****************************************************************************
+ TDirectiveItem
+*****************************************************************************}
+
+ constructor TDirectiveItem.Create(AList:TFPHashObjectList;const n:string;p:tdirectiveproc);
+ begin
+ inherited Create(AList,n);
+ is_conditional:=false;
+ proc:=p;
+ end;
+
+
+ constructor TDirectiveItem.CreateCond(AList:TFPHashObjectList;const n:string;p:tdirectiveproc);
+ begin
+ inherited Create(AList,n);
+ is_conditional:=true;
+ proc:=p;
+ end;
+
+{****************************************************************************
+ TSCANNERFILE
+ ****************************************************************************}
+
+ constructor tscannerfile.create(const fn:string);
+ begin
+ inputfile:=do_openinputfile(fn);
+ if assigned(current_module) then
+ current_module.sourcefiles.register_file(inputfile);
+ { reset localinput }
+ c:=#0;
+ inputbuffer:=nil;
+ inputpointer:=nil;
+ inputstart:=0;
+ { reset scanner }
+ preprocstack:=nil;
+ replaystack:=nil;
+ tokenbuf_change_endian:=false;
+ comment_level:=0;
+ yylexcount:=0;
+ block_type:=bt_general;
+ line_no:=0;
+ lastlinepos:=0;
+ lasttokenpos:=0;
+ nexttokenpos:=0;
+ lasttoken:=NOTOKEN;
+ nexttoken:=NOTOKEN;
+ lastasmgetchar:=#0;
+ ignoredirectives:=TFPHashList.Create;
+ in_asm_string:=false;
+ end;
+
+
+ procedure tscannerfile.firstfile;
+ begin
+ { load block }
+ if not openinputfile then
+ Message1(scan_f_cannot_open_input,inputfile.name^);
+ reload;
+ end;
+
+
+ destructor tscannerfile.destroy;
+ begin
+ if assigned(current_module) and
+ (current_module.state=ms_compiled) and
+ (status.errorcount=0) then
+ checkpreprocstack
+ else
+ begin
+ while assigned(preprocstack) do
+ poppreprocstack;
+ end;
+ while assigned(replaystack) do
+ popreplaystack;
+ if not inputfile.closed then
+ closeinputfile;
+ ignoredirectives.free;
+ end;
+
+
+ function tscannerfile.openinputfile:boolean;
+ begin
+ openinputfile:=inputfile.open;
+ { load buffer }
+ inputbuffer:=inputfile.buf;
+ inputpointer:=inputfile.buf;
+ inputstart:=inputfile.bufstart;
+ { line }
+ line_no:=0;
+ lastlinepos:=0;
+ lasttokenpos:=0;
+ nexttokenpos:=0;
+ end;
+
+
+ procedure tscannerfile.closeinputfile;
+ begin
+ inputfile.close;
+ { reset buffer }
+ inputbuffer:=nil;
+ inputpointer:=nil;
+ inputstart:=0;
+ { reset line }
+ line_no:=0;
+ lastlinepos:=0;
+ lasttokenpos:=0;
+ nexttokenpos:=0;
+ end;
+
+
+ function tscannerfile.tempopeninputfile:boolean;
+ begin
+ if inputfile.is_macro then
+ exit;
+ tempopeninputfile:=inputfile.tempopen;
+ { reload buffer }
+ inputbuffer:=inputfile.buf;
+ inputpointer:=inputfile.buf;
+ inputstart:=inputfile.bufstart;
+ end;
+
+
+ procedure tscannerfile.tempcloseinputfile;
+ begin
+ if inputfile.closed or inputfile.is_macro then
+ exit;
+ inputfile.setpos(inputstart+(inputpointer-inputbuffer));
+ inputfile.tempclose;
+ { reset buffer }
+ inputbuffer:=nil;
+ inputpointer:=nil;
+ inputstart:=0;
+ end;
+
+
+ procedure tscannerfile.saveinputfile;
+ begin
+ inputfile.saveinputpointer:=inputpointer;
+ inputfile.savelastlinepos:=lastlinepos;
+ inputfile.saveline_no:=line_no;
+ end;
+
+
+ procedure tscannerfile.restoreinputfile;
+ begin
+ inputbuffer:=inputfile.buf;
+ inputpointer:=inputfile.saveinputpointer;
+ lastlinepos:=inputfile.savelastlinepos;
+ line_no:=inputfile.saveline_no;
+ if not inputfile.is_macro then
+ parser_current_file:=inputfile.name^;
+ end;
+
+
+ procedure tscannerfile.nextfile;
+ var
+ to_dispose : tinputfile;
+ begin
+ if assigned(inputfile.next) then
+ begin
+ if inputfile.is_macro then
+ to_dispose:=inputfile
+ else
+ begin
+ to_dispose:=nil;
+ dec(inputfilecount);
+ end;
+ { we can allways close the file, no ? }
+ inputfile.close;
+ inputfile:=inputfile.next;
+ if assigned(to_dispose) then
+ to_dispose.free;
+ restoreinputfile;
+ end;
+ end;
+
+
+ procedure tscannerfile.startrecordtokens(buf:tdynamicarray);
+ begin
+ if not assigned(buf) then
+ internalerror(200511172);
+ if assigned(recordtokenbuf) then
+ internalerror(200511173);
+ recordtokenbuf:=buf;
+ fillchar(last_settings,sizeof(last_settings),0);
+ last_message:=nil;
+ fillchar(last_filepos,sizeof(last_filepos),0);
+ end;
+
+
+ procedure tscannerfile.stoprecordtokens;
+ begin
+ if not assigned(recordtokenbuf) then
+ internalerror(200511174);
+ recordtokenbuf:=nil;
+ end;
+
+
+ procedure tscannerfile.writetoken(t : ttoken);
+ var
+ b : byte;
+ begin
+ if ord(t)>$7f then
+ begin
+ b:=(ord(t) shr 8) or $80;
+ recordtokenbuf.write(b,1);
+ end;
+ b:=ord(t) and $ff;
+ recordtokenbuf.write(b,1);
+ end;
+
+ procedure tscannerfile.tokenwritesizeint(val : sizeint);
+ begin
+ recordtokenbuf.write(val,sizeof(sizeint));
+ end;
+
+ function tscannerfile.tokenreadsizeint : sizeint;
+ var
+ val : sizeint;
+ begin
+ replaytokenbuf.read(val,sizeof(sizeint));
+ if tokenbuf_change_endian then
+ val:=swapendian(val);
+ result:=val;
+ end;
+
+ function tscannerfile.tokenreadlongword : longword;
+ var
+ val : longword;
+ begin
+ replaytokenbuf.read(val,sizeof(longword));
+ if tokenbuf_change_endian then
+ val:=swapendian(val);
+ result:=val;
+ end;
+
+ function tscannerfile.tokenreadlongint : longint;
+ var
+ val : longint;
+ begin
+ replaytokenbuf.read(val,sizeof(longint));
+ if tokenbuf_change_endian then
+ val:=swapendian(val);
+ result:=val;
+ end;
+
+ function tscannerfile.tokenreadshortint : shortint;
+ var
+ val : shortint;
+ begin
+ replaytokenbuf.read(val,sizeof(shortint));
+ result:=val;
+ end;
+
+ function tscannerfile.tokenreadbyte : byte;
+ var
+ val : byte;
+ begin
+ replaytokenbuf.read(val,sizeof(byte));
+ result:=val;
+ end;
+
+ function tscannerfile.tokenreadsmallint : smallint;
+ var
+ val : smallint;
+ begin
+ replaytokenbuf.read(val,sizeof(smallint));
+ if tokenbuf_change_endian then
+ val:=swapendian(val);
+ result:=val;
+ end;
+
+ function tscannerfile.tokenreadword : word;
+ var
+ val : word;
+ begin
+ replaytokenbuf.read(val,sizeof(word));
+ if tokenbuf_change_endian then
+ val:=swapendian(val);
+ result:=val;
+ end;
+
+ function tscannerfile.tokenreadenum(size : longint) : longword;
+ begin
+ if size=1 then
+ result:=tokenreadbyte
+ else if size=2 then
+ result:=tokenreadword
+ else if size=4 then
+ result:=tokenreadlongword;
+ end;
+
+ procedure tscannerfile.tokenreadset(var b;size : longint);
+ var
+ i : longint;
+ begin
+ replaytokenbuf.read(b,size);
+ if tokenbuf_change_endian then
+ for i:=0 to size-1 do
+ Pbyte(@b)[i]:=reverse_byte(Pbyte(@b)[i]);
+ end;
+
+
+ procedure tscannerfile.tokenreadsettings(var asettings : tsettings; expected_size : longint);
+
+ { This procedure
+ needs to be changed whenever
+ globals.tsettings type is changed,
+ the problem is that no error will appear
+ before tests with generics are tested. PM }
+
+ var
+ startpos, endpos : longword;
+ begin
+ { WARNING all those fields need to be in the correct
+ order otherwise cross_endian PPU reading will fail }
+ startpos:=replaytokenbuf.pos;
+ with asettings do
+ begin
+ alignment.procalign:=tokenreadlongint;
+ alignment.loopalign:=tokenreadlongint;
+ alignment.jumpalign:=tokenreadlongint;
+ alignment.constalignmin:=tokenreadlongint;
+ alignment.constalignmax:=tokenreadlongint;
+ alignment.varalignmin:=tokenreadlongint;
+ alignment.varalignmax:=tokenreadlongint;
+ alignment.localalignmin:=tokenreadlongint;
+ alignment.localalignmax:=tokenreadlongint;
+ alignment.recordalignmin:=tokenreadlongint;
+ alignment.recordalignmax:=tokenreadlongint;
+ alignment.maxCrecordalign:=tokenreadlongint;
+ tokenreadset(globalswitches,sizeof(globalswitches));
+ tokenreadset(moduleswitches,sizeof(moduleswitches));
+ tokenreadset(localswitches,sizeof(localswitches));
+ tokenreadset(modeswitches,sizeof(modeswitches));
+ tokenreadset(optimizerswitches,sizeof(optimizerswitches));
+ tokenreadset(genwpoptimizerswitches,sizeof(genwpoptimizerswitches));
+ tokenreadset(dowpoptimizerswitches,sizeof(dowpoptimizerswitches));
+ tokenreadset(debugswitches,sizeof(debugswitches));
+ { 0: old behaviour for sets <=256 elements
+ >0: round to this size }
+ setalloc:=tokenreadshortint;
+ packenum:=tokenreadshortint;
+
+ packrecords:=tokenreadshortint;
+ maxfpuregisters:=tokenreadshortint;
+
+
+ cputype:=tcputype(tokenreadenum(sizeof(tcputype)));
+ optimizecputype:=tcputype(tokenreadenum(sizeof(tcputype)));
+ fputype:=tfputype(tokenreadenum(sizeof(tfputype)));
+ asmmode:=tasmmode(tokenreadenum(sizeof(tasmmode)));
+ interfacetype:=tinterfacetypes(tokenreadenum(sizeof(tinterfacetypes)));
+ defproccall:=tproccalloption(tokenreadenum(sizeof(tproccalloption)));
+ { tstringencoding is word type,
+ thus this should be OK here }
+ sourcecodepage:=tstringEncoding(tokenreadword);
+
+ minfpconstprec:=tfloattype(tokenreadenum(sizeof(tfloattype)));
+
+ disabledircache:=boolean(tokenreadbyte);
+{$if defined(ARM) or defined(AVR)}
+ controllertype:=tcontrollertype(tokenreadenum(sizeof(tcontrollertype)));
+{$endif defined(ARM) or defined(AVR)}
+ endpos:=replaytokenbuf.pos;
+ if endpos-startpos<>expected_size then
+ Comment(V_Error,'Wrong size of Settings read-in');
+ end;
+ end;
+
+
+ procedure tscannerfile.recordtoken;
+ var
+ t : ttoken;
+ s : tspecialgenerictoken;
+ len,val,msgnb,copy_size : sizeint;
+ b : byte;
+ pmsg : pmessagestaterecord;
+ begin
+ if not assigned(recordtokenbuf) then
+ internalerror(200511176);
+ t:=_GENERICSPECIALTOKEN;
+ { settings changed? }
+ { last field pmessage is handled separately below in
+ ST_LOADMESSAGES }
+ if CompareByte(current_settings,last_settings,
+ sizeof(current_settings)-sizeof(pointer))<>0 then
+ begin
+ { use a special token to record it }
+ s:=ST_LOADSETTINGS;
+ writetoken(t);
+ recordtokenbuf.write(s,1);
+ copy_size:=sizeof(current_settings)-sizeof(pointer);
+ tokenwritesizeint(copy_size);
+ recordtokenbuf.write(current_settings,copy_size);
+ last_settings:=current_settings;
+ end;
+
+ if current_settings.pmessage<>last_message then
+ begin
+ { use a special token to record it }
+ s:=ST_LOADMESSAGES;
+ writetoken(t);
+ recordtokenbuf.write(s,1);
+ msgnb:=0;
+ pmsg:=current_settings.pmessage;
+ while assigned(pmsg) do
+ begin
+ if msgnb=high(sizeint) then
+ { Too many messages }
+ internalerror(2011090401);
+ inc(msgnb);
+ pmsg:=pmsg^.next;
+ end;
+ tokenwritesizeint(msgnb);
+ pmsg:=current_settings.pmessage;
+ while assigned(pmsg) do
+ begin
+ { What about endianess here? }
+ val:=pmsg^.value;
+ tokenwritesizeint(val);
+ val:=ord(pmsg^.state);
+ tokenwritesizeint(val);
+ pmsg:=pmsg^.next;
+ end;
+ last_message:=current_settings.pmessage;
+ end;
+
+ { file pos changes? }
+ if current_tokenpos.line<>last_filepos.line then
+ begin
+ s:=ST_LINE;
+ writetoken(t);
+ recordtokenbuf.write(s,1);
+ recordtokenbuf.write(current_tokenpos.line,sizeof(current_tokenpos.line));
+ last_filepos.line:=current_tokenpos.line;
+ end;
+ if current_tokenpos.column<>last_filepos.column then
+ begin
+ s:=ST_COLUMN;
+ writetoken(t);
+ { can the column be written packed? }
+ if current_tokenpos.column<$80 then
+ begin
+ b:=$80 or current_tokenpos.column;
+ recordtokenbuf.write(b,1);
+ end
+ else
+ begin
+ recordtokenbuf.write(s,1);
+ recordtokenbuf.write(current_tokenpos.column,sizeof(current_tokenpos.column));
+ end;
+ last_filepos.column:=current_tokenpos.column;
+ end;
+ if current_tokenpos.fileindex<>last_filepos.fileindex then
+ begin
+ s:=ST_FILEINDEX;
+ writetoken(t);
+ recordtokenbuf.write(s,1);
+ recordtokenbuf.write(current_tokenpos.fileindex,sizeof(current_tokenpos.fileindex));
+ last_filepos.fileindex:=current_tokenpos.fileindex;
+ end;
+
+ writetoken(token);
+ if token<>_GENERICSPECIALTOKEN then
+ writetoken(idtoken);
+ case token of
+ _CWCHAR,
+ _CWSTRING :
+ begin
+ tokenwritesizeint(patternw^.len);
+ recordtokenbuf.write(patternw^.data^,patternw^.len*sizeof(tcompilerwidechar));
+ end;
+ _CSTRING:
+ begin
+ len:=length(cstringpattern);
+ tokenwritesizeint(len);
+ recordtokenbuf.write(cstringpattern[1],length(cstringpattern));
+ end;
+ _CCHAR,
+ _INTCONST,
+ _REALNUMBER :
+ begin
+ { pexpr.pas messes with pattern in case of negative integer consts,
+ see around line 2562 the comment of JM; remove the - before recording it
+ (FK)
+ }
+ if (token=_INTCONST) and (pattern[1]='-') then
+ delete(pattern,1,1);
+ recordtokenbuf.write(pattern[0],1);
+ recordtokenbuf.write(pattern[1],length(pattern));
+ end;
+ _ID :
+ begin
+ recordtokenbuf.write(orgpattern[0],1);
+ recordtokenbuf.write(orgpattern[1],length(orgpattern));
+ end;
+ end;
+ end;
+
+
+ procedure tscannerfile.startreplaytokens(buf:tdynamicarray; achange_endian : boolean);
+ begin
+ if not assigned(buf) then
+ internalerror(200511175);
+ { save current token }
+ if token in [_CWCHAR,_CWSTRING,_CCHAR,_CSTRING,_INTCONST,_REALNUMBER,_ID] then
+ internalerror(200511178);
+ replaystack:=treplaystack.create(token,current_settings,
+ replaytokenbuf,replaystack,tokenbuf_change_endian);
+ if assigned(inputpointer) then
+ dec(inputpointer);
+ { install buffer }
+ replaytokenbuf:=buf;
+ tokenbuf_change_endian:=achange_endian;
+
+ { reload next token }
+ replaytokenbuf.seek(0);
+ replaytoken;
+ end;
+
+
+ function tscannerfile.readtoken: ttoken;
+ var
+ b,b2 : byte;
+ begin
+ replaytokenbuf.read(b,1);
+ if (b and $80)<>0 then
+ begin
+ replaytokenbuf.read(b2,1);
+ result:=ttoken(((b and $7f) shl 8) or b2);
+ end
+ else
+ result:=ttoken(b);
+ end;
+
+
+ procedure tscannerfile.replaytoken;
+ var
+ wlen,mesgnb,copy_size : sizeint;
+ specialtoken : tspecialgenerictoken;
+ i : byte;
+ pmsg,prevmsg : pmessagestaterecord;
+ begin
+ if not assigned(replaytokenbuf) then
+ internalerror(200511177);
+ { End of replay buffer? Then load the next char from the file again }
+ if replaytokenbuf.pos>=replaytokenbuf.size then
+ begin
+ token:=replaystack.token;
+ replaytokenbuf:=replaystack.tokenbuf;
+ { restore compiler settings }
+ current_settings:=replaystack.settings;
+ popreplaystack;
+ if assigned(inputpointer) then
+ begin
+ c:=inputpointer^;
+ inc(inputpointer);
+ end;
+ exit;
+ end;
+ repeat
+ { load token from the buffer }
+ token:=readtoken;
+ if token<>_GENERICSPECIALTOKEN then
+ idtoken:=readtoken
+ else
+ idtoken:=_NOID;
+ case token of
+ _CWCHAR,
+ _CWSTRING :
+ begin
+ wlen:=tokenreadsizeint;
+ setlengthwidestring(patternw,wlen);
+ replaytokenbuf.read(patternw^.data^,patternw^.len*sizeof(tcompilerwidechar));
+ orgpattern:='';
+ pattern:='';
+ cstringpattern:='';
+ end;
+ _CSTRING:
+ begin
+ wlen:=tokenreadsizeint;
+ setlength(cstringpattern,wlen);
+ replaytokenbuf.read(cstringpattern[1],wlen);
+ orgpattern:='';
+ pattern:='';
+ end;
+ _CCHAR,
+ _INTCONST,
+ _REALNUMBER :
+ begin
+ replaytokenbuf.read(pattern[0],1);
+ replaytokenbuf.read(pattern[1],length(pattern));
+ orgpattern:='';
+ end;
+ _ID :
+ begin
+ replaytokenbuf.read(orgpattern[0],1);
+ replaytokenbuf.read(orgpattern[1],length(orgpattern));
+ pattern:=upper(orgpattern);
+ end;
+ _GENERICSPECIALTOKEN:
+ begin
+ replaytokenbuf.read(specialtoken,1);
+ { packed column? }
+ if (ord(specialtoken) and $80)<>0 then
+ begin
+ current_tokenpos.column:=ord(specialtoken) and $7f;
+
+ { don't generate invalid line info if no sources are available for the current module }
+ if not(get_module(current_filepos.moduleindex).sources_avail) then
+ current_tokenpos.column:=0;
+
+ current_filepos:=current_tokenpos;
+ end
+ else
+ case specialtoken of
+ ST_LOADSETTINGS:
+ begin
+ copy_size:=tokenreadsizeint;
+ if copy_size <> sizeof(current_settings)-sizeof(pointer) then
+ internalerror(2011090501);
+ {
+ replaytokenbuf.read(current_settings,copy_size);
+ }
+ tokenreadsettings(current_settings,copy_size);
+ end;
+ ST_LOADMESSAGES:
+ begin
+ current_settings.pmessage:=nil;
+ mesgnb:=tokenreadsizeint;
+ if mesgnb>0 then
+ Comment(V_Error,'Message recordind not yet supported');
+ for i:=1 to mesgnb do
+ begin
+ new(pmsg);
+ if i=1 then
+ begin
+ current_settings.pmessage:=pmsg;
+ prevmsg:=nil;
+ end
+ else
+ prevmsg^.next:=pmsg;
+ replaytokenbuf.read(pmsg^.value,sizeof(longint));
+ replaytokenbuf.read(pmsg^.state,sizeof(tmsgstate));
+ pmsg^.next:=nil;
+ prevmsg:=pmsg;
+ end;
+ end;
+ ST_LINE:
+ begin
+ current_tokenpos.line:=tokenreadlongint;
+
+ { don't generate invalid line info if no sources are available for the current module }
+ if not(get_module(current_filepos.moduleindex).sources_avail) then
+ current_tokenpos.line:=0;
+
+ current_filepos:=current_tokenpos;
+ end;
+ ST_COLUMN:
+ begin
+ current_tokenpos.column:=tokenreadword;
+ { don't generate invalid line info if no sources are available for the current module }
+ if not(get_module(current_filepos.moduleindex).sources_avail) then
+ current_tokenpos.column:=0;
+
+ current_filepos:=current_tokenpos;
+ end;
+ ST_FILEINDEX:
+ begin
+ current_tokenpos.fileindex:=tokenreadword;
+ { don't generate invalid line info if no sources are available for the current module }
+ if not(get_module(current_filepos.moduleindex).sources_avail) then
+ begin
+ current_tokenpos.column:=0;
+ current_tokenpos.line:=0;
+ end;
+
+ current_filepos:=current_tokenpos;
+ end;
+ else
+ internalerror(2006103010);
+ end;
+ continue;
+ end;
+ end;
+ break;
+ until false;
+ end;
+
+
+ procedure tscannerfile.addfile(hp:tinputfile);
+ begin
+ saveinputfile;
+ { add to list }
+ hp.next:=inputfile;
+ inputfile:=hp;
+ { load new inputfile }
+ restoreinputfile;
+ end;
+
+
+ procedure tscannerfile.reload;
+ begin
+ with inputfile do
+ begin
+ { when nothing more to read then leave immediatly, so we
+ don't change the current_filepos and leave it point to the last
+ char }
+ if (c=#26) and (not assigned(next)) then
+ exit;
+ repeat
+ { still more to read?, then change the #0 to a space so its seen
+ as a seperator, this can't be used for macro's which can change
+ the place of the #0 in the buffer with tempopen }
+ if (c=#0) and (bufsize>0) and
+ not(inputfile.is_macro) and
+ (inputpointer-inputbuffer<bufsize) then
+ begin
+ c:=' ';
+ inc(inputpointer);
+ exit;
+ end;
+ { can we read more from this file ? }
+ if (c<>#26) and (not endoffile) then
+ begin
+ readbuf;
+ inputpointer:=buf;
+ inputbuffer:=buf;
+ inputstart:=bufstart;
+ { first line? }
+ if line_no=0 then
+ begin
+ c:=inputpointer^;
+ { eat utf-8 signature? }
+ if (ord(inputpointer^)=$ef) and
+ (ord((inputpointer+1)^)=$bb) and
+ (ord((inputpointer+2)^)=$bf) then
+ begin
+ inc(inputpointer,3);
+ message(scan_c_switching_to_utf8);
+ current_settings.sourcecodepage:=CP_UTF8;
+ include(current_settings.moduleswitches,cs_explicit_codepage);
+ end;
+
+ line_no:=1;
+ if cs_asm_source in current_settings.globalswitches then
+ inputfile.setline(line_no,inputstart+inputpointer-inputbuffer);
+ end;
+ end
+ else
+ begin
+ { load eof position in tokenpos/current_filepos }
+ gettokenpos;
+ { close file }
+ closeinputfile;
+ { no next module, than EOF }
+ if not assigned(inputfile.next) then
+ begin
+ c:=#26;
+ exit;
+ end;
+ { load next file and reopen it }
+ nextfile;
+ tempopeninputfile;
+ { status }
+ Message1(scan_t_back_in,inputfile.name^);
+ end;
+ { load next char }
+ c:=inputpointer^;
+ inc(inputpointer);
+ until c<>#0; { if also end, then reload again }
+ end;
+ end;
+
+
+ procedure tscannerfile.insertmacro(const macname:string;p:pchar;len,line,fileindex:longint);
+ var
+ hp : tinputfile;
+ begin
+ { save old postion }
+ dec(inputpointer);
+ tempcloseinputfile;
+ { create macro 'file' }
+ { use special name to dispose after !! }
+ hp:=do_openinputfile('_Macro_.'+macname);
+ addfile(hp);
+ with inputfile do
+ begin
+ setmacro(p,len);
+ { local buffer }
+ inputbuffer:=buf;
+ inputpointer:=buf;
+ inputstart:=bufstart;
+ ref_index:=fileindex;
+ end;
+ { reset line }
+ line_no:=line;
+ lastlinepos:=0;
+ lasttokenpos:=0;
+ nexttokenpos:=0;
+ { load new c }
+ c:=inputpointer^;
+ inc(inputpointer);
+ end;
+
+
+ procedure tscannerfile.do_gettokenpos(out tokenpos: longint; out filepos: tfileposinfo);
+ begin
+ tokenpos:=inputstart+(inputpointer-inputbuffer);
+ filepos.line:=line_no;
+ filepos.column:=tokenpos-lastlinepos;
+ filepos.fileindex:=inputfile.ref_index;
+ filepos.moduleindex:=current_module.unit_index;
+ end;
+
+
+ procedure tscannerfile.gettokenpos;
+ { load the values of tokenpos and lasttokenpos }
+ begin
+ do_gettokenpos(lasttokenpos,current_tokenpos);
+ current_filepos:=current_tokenpos;
+ end;
+
+
+ procedure tscannerfile.cachenexttokenpos;
+ begin
+ do_gettokenpos(nexttokenpos,next_filepos);
+ end;
+
+
+ procedure tscannerfile.setnexttoken;
+ begin
+ token:=nexttoken;
+ nexttoken:=NOTOKEN;
+ lasttokenpos:=nexttokenpos;
+ current_tokenpos:=next_filepos;
+ current_filepos:=current_tokenpos;
+ nexttokenpos:=0;
+ end;
+
+
+ procedure tscannerfile.savetokenpos;
+ begin
+ oldlasttokenpos:=lasttokenpos;
+ oldcurrent_filepos:=current_filepos;
+ oldcurrent_tokenpos:=current_tokenpos;
+ end;
+
+
+ procedure tscannerfile.restoretokenpos;
+ begin
+ lasttokenpos:=oldlasttokenpos;
+ current_filepos:=oldcurrent_filepos;
+ current_tokenpos:=oldcurrent_tokenpos;
+ end;
+
+
+ procedure tscannerfile.inc_comment_level;
+ begin
+ if (m_nested_comment in current_settings.modeswitches) then
+ inc(comment_level)
+ else
+ comment_level:=1;
+ if (comment_level>1) then
+ begin
+ savetokenpos;
+ gettokenpos; { update for warning }
+ Message1(scan_w_comment_level,tostr(comment_level));
+ restoretokenpos;
+ end;
+ end;
+
+
+ procedure tscannerfile.dec_comment_level;
+ begin
+ if (m_nested_comment in current_settings.modeswitches) then
+ dec(comment_level)
+ else
+ comment_level:=0;
+ end;
+
+
+ procedure tscannerfile.linebreak;
+ var
+ cur : char;
+ begin
+ with inputfile do
+ begin
+ if (byte(inputpointer^)=0) and not(endoffile) then
+ begin
+ cur:=c;
+ reload;
+ if byte(cur)+byte(c)<>23 then
+ dec(inputpointer);
+ end
+ else
+ begin
+ { Support all combination of #10 and #13 as line break }
+ if (byte(inputpointer^)+byte(c)=23) then
+ inc(inputpointer);
+ end;
+ { Always return #10 as line break }
+ c:=#10;
+ { increase line counters }
+ lastlinepos:=inputstart+(inputpointer-inputbuffer);
+ inc(line_no);
+ { update linebuffer }
+ if cs_asm_source in current_settings.globalswitches then
+ inputfile.setline(line_no,lastlinepos);
+ { update for status and call the show status routine,
+ but don't touch current_filepos ! }
+ savetokenpos;
+ gettokenpos; { update for v_status }
+ inc(status.compiledlines);
+ ShowStatus;
+ restoretokenpos;
+ end;
+ end;
+
+
+ procedure tscannerfile.illegal_char(c:char);
+ var
+ s : string;
+ begin
+ if c in [#32..#255] then
+ s:=''''+c+''''
+ else
+ s:='#'+tostr(ord(c));
+ Message2(scan_f_illegal_char,s,'$'+hexstr(ord(c),2));
+ end;
+
+
+ procedure tscannerfile.end_of_file;
+ begin
+ checkpreprocstack;
+ Message(scan_f_end_of_file);
+ end;
+
+ {-------------------------------------------
+ IF Conditional Handling
+ -------------------------------------------}
+
+ procedure tscannerfile.checkpreprocstack;
+ begin
+ { check for missing ifdefs }
+ while assigned(preprocstack) do
+ begin
+ Message4(scan_e_endif_expected,preprocstring[preprocstack.typ],preprocstack.name,
+ preprocstack.owner.inputfile.name^,tostr(preprocstack.line_nb));
+ poppreprocstack;
+ end;
+ end;
+
+
+ procedure tscannerfile.poppreprocstack;
+ var
+ hp : tpreprocstack;
+ begin
+ if assigned(preprocstack) then
+ begin
+ Message1(scan_c_endif_found,preprocstack.name);
+ hp:=preprocstack.next;
+ preprocstack.free;
+ preprocstack:=hp;
+ end
+ else
+ Message(scan_e_endif_without_if);
+ end;
+
+
+ procedure tscannerfile.ifpreprocstack(atyp : preproctyp;compile_time_predicate:tcompile_time_predicate;messid:longint);
+ var
+ condition: Boolean;
+ valuedescr: String;
+ begin
+ if (preprocstack=nil) or preprocstack.accept then
+ condition:= compile_time_predicate(valuedescr)
+ else
+ begin
+ condition:= false;
+ valuedescr:= '';
+ end;
+ preprocstack:=tpreprocstack.create(atyp, condition, preprocstack);
+ preprocstack.name:=valuedescr;
+ preprocstack.line_nb:=line_no;
+ preprocstack.owner:=self;
+ if preprocstack.accept then
+ Message2(messid,preprocstack.name,'accepted')
+ else
+ Message2(messid,preprocstack.name,'rejected');
+ end;
+
+ procedure tscannerfile.elsepreprocstack;
+ begin
+ if assigned(preprocstack) and
+ (preprocstack.typ<>pp_else) then
+ begin
+ if (preprocstack.typ=pp_elseif) then
+ preprocstack.accept:=false
+ else
+ if (not(assigned(preprocstack.next)) or (preprocstack.next.accept)) then
+ preprocstack.accept:=not preprocstack.accept;
+ preprocstack.typ:=pp_else;
+ preprocstack.line_nb:=line_no;
+ if preprocstack.accept then
+ Message2(scan_c_else_found,preprocstack.name,'accepted')
+ else
+ Message2(scan_c_else_found,preprocstack.name,'rejected');
+ end
+ else
+ Message(scan_e_endif_without_if);
+ end;
+
+ procedure tscannerfile.elseifpreprocstack(compile_time_predicate:tcompile_time_predicate);
+ var
+ valuedescr: String;
+ begin
+ if assigned(preprocstack) and
+ (preprocstack.typ in [pp_if,pp_elseif]) then
+ begin
+ { when the branch is accepted we use pp_elseif so we know that
+ all the next branches need to be rejected. when this branch is still
+ not accepted then leave it at pp_if }
+ if (preprocstack.typ=pp_elseif) then
+ preprocstack.accept:=false
+ else if (preprocstack.typ=pp_if) and preprocstack.accept then
+ begin
+ preprocstack.accept:=false;
+ preprocstack.typ:=pp_elseif;
+ end
+ else if (not(assigned(preprocstack.next)) or (preprocstack.next.accept))
+ and compile_time_predicate(valuedescr) then
+ begin
+ preprocstack.name:=valuedescr;
+ preprocstack.accept:=true;
+ preprocstack.typ:=pp_elseif;
+ end;
+
+ preprocstack.line_nb:=line_no;
+ if preprocstack.accept then
+ Message2(scan_c_else_found,preprocstack.name,'accepted')
+ else
+ Message2(scan_c_else_found,preprocstack.name,'rejected');
+ end
+ else
+ Message(scan_e_endif_without_if);
+ end;
+
+
+ procedure tscannerfile.popreplaystack;
+ var
+ hp : treplaystack;
+ begin
+ if assigned(replaystack) then
+ begin
+ hp:=replaystack.next;
+ replaystack.free;
+ replaystack:=hp;
+ if assigned (replaystack) then
+ tokenbuf_change_endian:=replaystack.change_endian
+ else
+ tokenbuf_change_endian:=false;
+ end;
+ end;
+
+ procedure tscannerfile.handleconditional(p:tdirectiveitem);
+ begin
+ savetokenpos;
+ repeat
+ current_scanner.gettokenpos;
+ p.proc();
+ { accept the text ? }
+ if (current_scanner.preprocstack=nil) or current_scanner.preprocstack.accept then
+ break
+ else
+ begin
+ current_scanner.gettokenpos;
+ Message(scan_c_skipping_until);
+ repeat
+ current_scanner.skipuntildirective;
+ if not (m_mac in current_settings.modeswitches) then
+ p:=tdirectiveitem(turbo_scannerdirectives.Find(current_scanner.readid))
+ else
+ p:=tdirectiveitem(mac_scannerdirectives.Find(current_scanner.readid));
+ until assigned(p) and (p.is_conditional);
+ current_scanner.gettokenpos;
+ Message1(scan_d_handling_switch,'$'+p.name);
+ end;
+ until false;
+ restoretokenpos;
+ end;
+
+
+ procedure tscannerfile.handledirectives;
+ var
+ t : tdirectiveitem;
+ hs : string;
+ begin
+ gettokenpos;
+ readchar; {Remove the $}
+ hs:=readid;
+ { handle empty directive }
+ if hs='' then
+ begin
+ Message1(scan_w_illegal_switch,'$');
+ exit;
+ end;
+{$ifdef PREPROCWRITE}
+ if parapreprocess then
+ begin
+ t:=Get_Directive(hs);
+ if not(is_conditional(t) or (t=_DIR_DEFINE) or (t=_DIR_UNDEF)) then
+ begin
+ preprocfile^.AddSpace;
+ preprocfile^.Add('{$'+hs+current_scanner.readcomment+'}');
+ exit;
+ end;
+ end;
+{$endif PREPROCWRITE}
+ { skip this directive? }
+ if (ignoredirectives.find(hs)<>nil) then
+ begin
+ if (comment_level>0) then
+ readcomment;
+ { we've read the whole comment }
+ aktcommentstyle:=comment_none;
+ exit;
+ end;
+ { Check for compiler switches }
+ while (length(hs)=1) and (c in ['-','+']) do
+ begin
+ HandleSwitch(hs[1],c);
+ current_scanner.readchar; {Remove + or -}
+ if c=',' then
+ begin
+ current_scanner.readchar; {Remove , }
+ { read next switch, support $v+,$+}
+ hs:=current_scanner.readid;
+ if (hs='') then
+ begin
+ if (c='$') and (m_fpc in current_settings.modeswitches) then
+ begin
+ current_scanner.readchar; { skip $ }
+ hs:=current_scanner.readid;
+ end;
+ if (hs='') then
+ Message1(scan_w_illegal_directive,'$'+c);
+ end
+ else
+ Message1(scan_d_handling_switch,'$'+hs);
+ end
+ else
+ hs:='';
+ end;
+ { directives may follow switches after a , }
+ if hs<>'' then
+ begin
+ if not (m_mac in current_settings.modeswitches) then
+ t:=tdirectiveitem(turbo_scannerdirectives.Find(hs))
+ else
+ t:=tdirectiveitem(mac_scannerdirectives.Find(hs));
+
+ if assigned(t) then
+ begin
+ if t.is_conditional then
+ handleconditional(t)
+ else
+ begin
+ Message1(scan_d_handling_switch,'$'+hs);
+ t.proc();
+ end;
+ end
+ else
+ begin
+ current_scanner.ignoredirectives.Add(hs,nil);
+ Message1(scan_w_illegal_directive,'$'+hs);
+ end;
+ { conditionals already read the comment }
+ if (current_scanner.comment_level>0) then
+ current_scanner.readcomment;
+ { we've read the whole comment }
+ aktcommentstyle:=comment_none;
+ end;
+ end;
+
+
+ procedure tscannerfile.readchar;
+ begin
+ c:=inputpointer^;
+ if c=#0 then
+ reload
+ else
+ inc(inputpointer);
+ end;
+
+
+ procedure tscannerfile.readstring;
+ var
+ i : longint;
+ err : boolean;
+ begin
+ err:=false;
+ i:=0;
+ repeat
+ case c of
+ '_',
+ '0'..'9',
+ 'A'..'Z' :
+ begin
+ if i<255 then
+ begin
+ inc(i);
+ orgpattern[i]:=c;
+ pattern[i]:=c;
+ end
+ else
+ begin
+ if not err then
+ begin
+ Message(scan_e_string_exceeds_255_chars);
+ err:=true;
+ end;
+ end;
+ c:=inputpointer^;
+ inc(inputpointer);
+ end;
+ 'a'..'z' :
+ begin
+ if i<255 then
+ begin
+ inc(i);
+ orgpattern[i]:=c;
+ pattern[i]:=chr(ord(c)-32)
+ end
+ else
+ begin
+ if not err then
+ begin
+ Message(scan_e_string_exceeds_255_chars);
+ err:=true;
+ end;
+ end;
+ c:=inputpointer^;
+ inc(inputpointer);
+ end;
+ #0 :
+ reload;
+ else
+ break;
+ end;
+ until false;
+ orgpattern[0]:=chr(i);
+ pattern[0]:=chr(i);
+ end;
+
+
+ procedure tscannerfile.readnumber;
+ var
+ base,
+ i : longint;
+ begin
+ case c of
+ '%' :
+ begin
+ readchar;
+ base:=2;
+ pattern[1]:='%';
+ i:=1;
+ end;
+ '&' :
+ begin
+ readchar;
+ base:=8;
+ pattern[1]:='&';
+ i:=1;
+ end;
+ '$' :
+ begin
+ readchar;
+ base:=16;
+ pattern[1]:='$';
+ i:=1;
+ end;
+ else
+ begin
+ base:=10;
+ i:=0;
+ end;
+ end;
+ while ((base>=10) and (c in ['0'..'9'])) or
+ ((base=16) and (c in ['A'..'F','a'..'f'])) or
+ ((base=8) and (c in ['0'..'7'])) or
+ ((base=2) and (c in ['0'..'1'])) do
+ begin
+ if i<255 then
+ begin
+ inc(i);
+ pattern[i]:=c;
+ end;
+ readchar;
+ end;
+ pattern[0]:=chr(i);
+ end;
+
+
+ function tscannerfile.readid:string;
+ begin
+ readstring;
+ readid:=pattern;
+ end;
+
+
+ function tscannerfile.readval:longint;
+ var
+ l : longint;
+ w : integer;
+ begin
+ readnumber;
+ val(pattern,l,w);
+ readval:=l;
+ end;
+
+
+ function tscannerfile.readval_asstring:string;
+ begin
+ readnumber;
+ readval_asstring:=pattern;
+ end;
+
+
+ function tscannerfile.readcomment:string;
+ var
+ i : longint;
+ begin
+ i:=0;
+ repeat
+ case c of
+ '{' :
+ begin
+ if aktcommentstyle=comment_tp then
+ inc_comment_level;
+ end;
+ '}' :
+ begin
+ if aktcommentstyle=comment_tp then
+ begin
+ readchar;
+ dec_comment_level;
+ if comment_level=0 then
+ break
+ else
+ continue;
+ end;
+ end;
+ '*' :
+ begin
+ if aktcommentstyle=comment_oldtp then
+ begin
+ readchar;
+ if c=')' then
+ begin
+ readchar;
+ dec_comment_level;
+ break;
+ end
+ else
+ { Add both characters !!}
+ if (i<255) then
+ begin
+ inc(i);
+ readcomment[i]:='*';
+ if (i<255) then
+ begin
+ inc(i);
+ readcomment[i]:=c;
+ end;
+ end;
+ end
+ else
+ { Not old TP comment, so add...}
+ begin
+ if (i<255) then
+ begin
+ inc(i);
+ readcomment[i]:='*';
+ end;
+ end;
+ end;
+ #10,#13 :
+ linebreak;
+ #26 :
+ end_of_file;
+ else
+ begin
+ if (i<255) then
+ begin
+ inc(i);
+ readcomment[i]:=c;
+ end;
+ end;
+ end;
+ readchar;
+ until false;
+ readcomment[0]:=chr(i);
+ end;
+
+
+ function tscannerfile.readquotedstring:string;
+ var
+ i : longint;
+ msgwritten : boolean;
+ begin
+ i:=0;
+ msgwritten:=false;
+ if (c='''') then
+ begin
+ repeat
+ readchar;
+ case c of
+ #26 :
+ end_of_file;
+ #10,#13 :
+ Message(scan_f_string_exceeds_line);
+ '''' :
+ begin
+ readchar;
+ if c<>'''' then
+ break;
+ end;
+ end;
+ if i<255 then
+ begin
+ inc(i);
+ result[i]:=c;
+ end
+ else
+ begin
+ if not msgwritten then
+ begin
+ Message(scan_e_string_exceeds_255_chars);
+ msgwritten:=true;
+ end;
+ end;
+ until false;
+ end;
+ result[0]:=chr(i);
+ end;
+
+
+ function tscannerfile.readstate:char;
+ var
+ state : char;
+ begin
+ state:=' ';
+ if c=' ' then
+ begin
+ current_scanner.skipspace;
+ current_scanner.readid;
+ if pattern='ON' then
+ state:='+'
+ else
+ if pattern='OFF' then
+ state:='-';
+ end
+ else
+ state:=c;
+ if not (state in ['+','-']) then
+ Message(scan_e_wrong_switch_toggle);
+ readstate:=state;
+ end;
+
+
+ function tscannerfile.readstatedefault:char;
+ var
+ state : char;
+ begin
+ state:=' ';
+ if c=' ' then
+ begin
+ current_scanner.skipspace;
+ current_scanner.readid;
+ if pattern='ON' then
+ state:='+'
+ else
+ if pattern='OFF' then
+ state:='-'
+ else
+ if pattern='DEFAULT' then
+ state:='*';
+ end
+ else
+ state:=c;
+ if not (state in ['+','-','*']) then
+ Message(scan_e_wrong_switch_toggle_default);
+ readstatedefault:=state;
+ end;
+
+
+ procedure tscannerfile.skipspace;
+ begin
+ repeat
+ case c of
+ #26 :
+ begin
+ reload;
+ if (c=#26) and not assigned(inputfile.next) then
+ break;
+ continue;
+ end;
+ #10,
+ #13 :
+ linebreak;
+ #9,#11,#12,' ' :
+ ;
+ else
+ break;
+ end;
+ readchar;
+ until false;
+ end;
+
+
+ procedure tscannerfile.skipuntildirective;
+ var
+ found : longint;
+ next_char_loaded : boolean;
+ begin
+ found:=0;
+ next_char_loaded:=false;
+ repeat
+ case c of
+ #10,
+ #13 :
+ linebreak;
+ #26 :
+ begin
+ reload;
+ if (c=#26) and not assigned(inputfile.next) then
+ end_of_file;
+ continue;
+ end;
+ '{' :
+ begin
+ if (aktcommentstyle in [comment_tp,comment_none]) then
+ begin
+ aktcommentstyle:=comment_tp;
+ if (comment_level=0) then
+ found:=1;
+ inc_comment_level;
+ end;
+ end;
+ '*' :
+ begin
+ if (aktcommentstyle=comment_oldtp) then
+ begin
+ readchar;
+ if c=')' then
+ begin
+ dec_comment_level;
+ found:=0;
+ aktcommentstyle:=comment_none;
+ end
+ else
+ next_char_loaded:=true;
+ end
+ else
+ found := 0;
+ end;
+ '}' :
+ begin
+ if (aktcommentstyle=comment_tp) then
+ begin
+ dec_comment_level;
+ if (comment_level=0) then
+ aktcommentstyle:=comment_none;
+ found:=0;
+ end;
+ end;
+ '$' :
+ begin
+ if found=1 then
+ found:=2;
+ end;
+ '''' :
+ if (aktcommentstyle=comment_none) then
+ begin
+ repeat
+ readchar;
+ case c of
+ #26 :
+ end_of_file;
+ #10,#13 :
+ break;
+ '''' :
+ begin
+ readchar;
+ if c<>'''' then
+ begin
+ next_char_loaded:=true;
+ break;
+ end;
+ end;
+ end;
+ until false;
+ end;
+ '(' :
+ begin
+ if (aktcommentstyle=comment_none) then
+ begin
+ readchar;
+ if c='*' then
+ begin
+ readchar;
+ if c='$' then
+ begin
+ found:=2;
+ inc_comment_level;
+ aktcommentstyle:=comment_oldtp;
+ end
+ else
+ begin
+ skipoldtpcomment;
+ next_char_loaded:=true;
+ end;
+ end
+ else
+ next_char_loaded:=true;
+ end
+ else
+ found:=0;
+ end;
+ '/' :
+ begin
+ if (aktcommentstyle=comment_none) then
+ begin
+ readchar;
+ if c='/' then
+ skipdelphicomment;
+ next_char_loaded:=true;
+ end
+ else
+ found:=0;
+ end;
+ else
+ found:=0;
+ end;
+ if next_char_loaded then
+ next_char_loaded:=false
+ else
+ readchar;
+ until (found=2);
+ end;
+
+
+{****************************************************************************
+ Comment Handling
+****************************************************************************}
+
+ procedure tscannerfile.skipcomment;
+ begin
+ aktcommentstyle:=comment_tp;
+ readchar;
+ inc_comment_level;
+ { handle compiler switches }
+ if (c='$') then
+ handledirectives;
+ { handle_switches can dec comment_level, }
+ while (comment_level>0) do
+ begin
+ case c of
+ '{' :
+ inc_comment_level;
+ '}' :
+ dec_comment_level;
+ #10,#13 :
+ linebreak;
+ #26 :
+ begin
+ reload;
+ if (c=#26) and not assigned(inputfile.next) then
+ end_of_file;
+ continue;
+ end;
+ end;
+ readchar;
+ end;
+ aktcommentstyle:=comment_none;
+ end;
+
+
+ procedure tscannerfile.skipdelphicomment;
+ begin
+ aktcommentstyle:=comment_delphi;
+ inc_comment_level;
+ readchar;
+ { this is not supported }
+ if c='$' then
+ Message(scan_w_wrong_styled_switch);
+ { skip comment }
+ while not (c in [#10,#13,#26]) do
+ readchar;
+ dec_comment_level;
+ aktcommentstyle:=comment_none;
+ end;
+
+
+ procedure tscannerfile.skipoldtpcomment;
+ var
+ found : longint;
+ begin
+ aktcommentstyle:=comment_oldtp;
+ inc_comment_level;
+ { only load a char if last already processed,
+ was cause of bug1634 PM }
+ if c=#0 then
+ readchar;
+ { this is now supported }
+ if (c='$') then
+ handledirectives;
+ { skip comment }
+ while (comment_level>0) do
+ begin
+ found:=0;
+ repeat
+ case c of
+ #26 :
+ begin
+ reload;
+ if (c=#26) and not assigned(inputfile.next) then
+ end_of_file;
+ continue;
+ end;
+ #10,#13 :
+ begin
+ if found=4 then
+ inc_comment_level;
+ linebreak;
+ found:=0;
+ end;
+ '*' :
+ begin
+ if found=3 then
+ found:=4
+ else
+ found:=1;
+ end;
+ ')' :
+ begin
+ if found in [1,4] then
+ begin
+ dec_comment_level;
+ if comment_level=0 then
+ found:=2
+ else
+ found:=0;
+ end
+ else
+ found:=0;
+ end;
+ '(' :
+ begin
+ if found=4 then
+ inc_comment_level;
+ found:=3;
+ end;
+ else
+ begin
+ if found=4 then
+ inc_comment_level;
+ found:=0;
+ end;
+ end;
+ readchar;
+ until (found=2);
+ end;
+ aktcommentstyle:=comment_none;
+ end;
+
+
+
+{****************************************************************************
+ Token Scanner
+****************************************************************************}
+
+ procedure tscannerfile.readtoken(allowrecordtoken:boolean);
+ var
+ code : integer;
+ len,
+ low,high,mid : longint;
+ w : word;
+ m : longint;
+ mac : tmacro;
+ asciinr : string[33];
+ iswidestring : boolean;
+ label
+ exit_label;
+ begin
+ flushpendingswitchesstate;
+
+ { record tokens? }
+ if allowrecordtoken and
+ assigned(recordtokenbuf) then
+ recordtoken;
+
+ { replay tokens? }
+ if assigned(replaytokenbuf) then
+ begin
+ replaytoken;
+ goto exit_label;
+ end;
+
+ { was there already a token read, then return that token }
+ if nexttoken<>NOTOKEN then
+ begin
+ setnexttoken;
+ goto exit_label;
+ end;
+
+ { Skip all spaces and comments }
+ repeat
+ case c of
+ '{' :
+ skipcomment;
+ #26 :
+ begin
+ reload;
+ if (c=#26) and not assigned(inputfile.next) then
+ break;
+ end;
+ ' ',#9..#13 :
+ begin
+{$ifdef PREPROCWRITE}
+ if parapreprocess then
+ begin
+ if c=#10 then
+ preprocfile.eolfound:=true
+ else
+ preprocfile.spacefound:=true;
+ end;
+{$endif PREPROCWRITE}
+ skipspace;
+ end
+ else
+ break;
+ end;
+ until false;
+
+ { Save current token position, for EOF its already loaded }
+ if c<>#26 then
+ gettokenpos;
+
+ { Check first for a identifier/keyword, this is 20+% faster (PFV) }
+ if c in ['A'..'Z','a'..'z','_'] then
+ begin
+ readstring;
+ token:=_ID;
+ idtoken:=_ID;
+ { keyword or any other known token,
+ pattern is always uppercased }
+ if (pattern[1]<>'_') and (length(pattern) in [tokenlenmin..tokenlenmax]) then
+ begin
+ low:=ord(tokenidx^[length(pattern),pattern[1]].first);
+ high:=ord(tokenidx^[length(pattern),pattern[1]].last);
+ while low<high do
+ begin
+ mid:=(high+low+1) shr 1;
+ if pattern<tokeninfo^[ttoken(mid)].str then
+ high:=mid-1
+ else
+ low:=mid;
+ end;
+ with tokeninfo^[ttoken(high)] do
+ if pattern=str then
+ begin
+ if keyword in current_settings.modeswitches then
+ if op=NOTOKEN then
+ token:=ttoken(high)
+ else
+ token:=op;
+ idtoken:=ttoken(high);
+ end;
+ end;
+ { Only process identifiers and not keywords }
+ if token=_ID then
+ begin
+ { this takes some time ... }
+ if (cs_support_macro in current_settings.moduleswitches) then
+ begin
+ mac:=tmacro(search_macro(pattern));
+ if assigned(mac) and (not mac.is_compiler_var) and (assigned(mac.buftext)) then
+ begin
+ if yylexcount<max_macro_nesting then
+ begin
+ mac.is_used:=true;
+ inc(yylexcount);
+ insertmacro(pattern,mac.buftext,mac.buflen,
+ mac.fileinfo.line,mac.fileinfo.fileindex);
+ { handle empty macros }
+ if c=#0 then
+ reload;
+ readtoken(false);
+ { that's all folks }
+ dec(yylexcount);
+ exit;
+ end
+ else
+ Message(scan_w_macro_too_deep);
+ end;
+ end;
+ end;
+ { return token }
+ goto exit_label;
+ end
+ else
+ begin
+ idtoken:=_NOID;
+ case c of
+
+ '$' :
+ begin
+ readnumber;
+ token:=_INTCONST;
+ goto exit_label;
+ end;
+
+ '%' :
+ begin
+ if not(m_fpc in current_settings.modeswitches) then
+ Illegal_Char(c)
+ else
+ begin
+ readnumber;
+ token:=_INTCONST;
+ goto exit_label;
+ end;
+ end;
+
+ '&' :
+ begin
+ if [m_fpc,m_delphi] * current_settings.modeswitches <> [] then
+ begin
+ readnumber;
+ if length(pattern)=1 then
+ begin
+ readstring;
+ token:=_ID;
+ idtoken:=_ID;
+ end
+ else
+ token:=_INTCONST;
+ goto exit_label;
+ end
+ else if m_mac in current_settings.modeswitches then
+ begin
+ readchar;
+ token:=_AMPERSAND;
+ goto exit_label;
+ end
+ else
+ Illegal_Char(c);
+ end;
+
+ '0'..'9' :
+ begin
+ readnumber;
+ if (c in ['.','e','E']) then
+ begin
+ { first check for a . }
+ if c='.' then
+ begin
+ cachenexttokenpos;
+ readchar;
+ { is it a .. from a range? }
+ case c of
+ '.' :
+ begin
+ readchar;
+ token:=_INTCONST;
+ nexttoken:=_POINTPOINT;
+ goto exit_label;
+ end;
+ ')' :
+ begin
+ readchar;
+ token:=_INTCONST;
+ nexttoken:=_RECKKLAMMER;
+ goto exit_label;
+ end;
+ end;
+ { insert the number after the . }
+ pattern:=pattern+'.';
+ while c in ['0'..'9'] do
+ begin
+ pattern:=pattern+c;
+ readchar;
+ end;
+ end;
+ { E can also follow after a point is scanned }
+ if c in ['e','E'] then
+ begin
+ pattern:=pattern+'E';
+ readchar;
+ if c in ['-','+'] then
+ begin
+ pattern:=pattern+c;
+ readchar;
+ end;
+ if not(c in ['0'..'9']) then
+ Illegal_Char(c);
+ while c in ['0'..'9'] do
+ begin
+ pattern:=pattern+c;
+ readchar;
+ end;
+ end;
+ token:=_REALNUMBER;
+ goto exit_label;
+ end;
+ token:=_INTCONST;
+ goto exit_label;
+ end;
+
+ ';' :
+ begin
+ readchar;
+ token:=_SEMICOLON;
+ goto exit_label;
+ end;
+
+ '[' :
+ begin
+ readchar;
+ token:=_LECKKLAMMER;
+ goto exit_label;
+ end;
+
+ ']' :
+ begin
+ readchar;
+ token:=_RECKKLAMMER;
+ goto exit_label;
+ end;
+
+ '(' :
+ begin
+ readchar;
+ case c of
+ '*' :
+ begin
+ c:=#0;{Signal skipoldtpcomment to reload a char }
+ skipoldtpcomment;
+ readtoken(false);
+ exit;
+ end;
+ '.' :
+ begin
+ readchar;
+ token:=_LECKKLAMMER;
+ goto exit_label;
+ end;
+ end;
+ token:=_LKLAMMER;
+ goto exit_label;
+ end;
+
+ ')' :
+ begin
+ readchar;
+ token:=_RKLAMMER;
+ goto exit_label;
+ end;
+
+ '+' :
+ begin
+ readchar;
+ if (c='=') and (cs_support_c_operators in current_settings.moduleswitches) then
+ begin
+ readchar;
+ token:=_PLUSASN;
+ goto exit_label;
+ end;
+ token:=_PLUS;
+ goto exit_label;
+ end;
+
+ '-' :
+ begin
+ readchar;
+ if (c='=') and (cs_support_c_operators in current_settings.moduleswitches) then
+ begin
+ readchar;
+ token:=_MINUSASN;
+ goto exit_label;
+ end;
+ token:=_MINUS;
+ goto exit_label;
+ end;
+
+ ':' :
+ begin
+ readchar;
+ if c='=' then
+ begin
+ readchar;
+ token:=_ASSIGNMENT;
+ goto exit_label;
+ end;
+ token:=_COLON;
+ goto exit_label;
+ end;
+
+ '*' :
+ begin
+ readchar;
+ if (c='=') and (cs_support_c_operators in current_settings.moduleswitches) then
+ begin
+ readchar;
+ token:=_STARASN;
+ end
+ else
+ if c='*' then
+ begin
+ readchar;
+ token:=_STARSTAR;
+ end
+ else
+ token:=_STAR;
+ goto exit_label;
+ end;
+
+ '/' :
+ begin
+ readchar;
+ case c of
+ '=' :
+ begin
+ if (cs_support_c_operators in current_settings.moduleswitches) then
+ begin
+ readchar;
+ token:=_SLASHASN;
+ goto exit_label;
+ end;
+ end;
+ '/' :
+ begin
+ skipdelphicomment;
+ readtoken(false);
+ exit;
+ end;
+ end;
+ token:=_SLASH;
+ goto exit_label;
+ end;
+
+ '|' :
+ if m_mac in current_settings.modeswitches then
+ begin
+ readchar;
+ token:=_PIPE;
+ goto exit_label;
+ end
+ else
+ Illegal_Char(c);
+
+ '=' :
+ begin
+ readchar;
+ token:=_EQ;
+ goto exit_label;
+ end;
+
+ '.' :
+ begin
+ readchar;
+ case c of
+ '.' :
+ begin
+ readchar;
+ case c of
+ '.' :
+ begin
+ readchar;
+ token:=_POINTPOINTPOINT;
+ goto exit_label;
+ end;
+ else
+ begin
+ token:=_POINTPOINT;
+ goto exit_label;
+ end;
+ end;
+ end;
+ ')' :
+ begin
+ readchar;
+ token:=_RECKKLAMMER;
+ goto exit_label;
+ end;
+ end;
+ token:=_POINT;
+ goto exit_label;
+ end;
+
+ '@' :
+ begin
+ readchar;
+ token:=_KLAMMERAFFE;
+ goto exit_label;
+ end;
+
+ ',' :
+ begin
+ readchar;
+ token:=_COMMA;
+ goto exit_label;
+ end;
+
+ '''','#','^' :
+ begin
+ len:=0;
+ cstringpattern:='';
+ iswidestring:=false;
+ if c='^' then
+ begin
+ readchar;
+ c:=upcase(c);
+ if (block_type in [bt_type,bt_const_type,bt_var_type]) or
+ (lasttoken=_ID) or (lasttoken=_NIL) or (lasttoken=_OPERATOR) or
+ (lasttoken=_RKLAMMER) or (lasttoken=_RECKKLAMMER) or (lasttoken=_CARET) then
+ begin
+ token:=_CARET;
+ goto exit_label;
+ end
+ else
+ begin
+ inc(len);
+ setlength(cstringpattern,256);
+ if c<#64 then
+ cstringpattern[len]:=chr(ord(c)+64)
+ else
+ cstringpattern[len]:=chr(ord(c)-64);
+ readchar;
+ end;
+ end;
+ repeat
+ case c of
+ '#' :
+ begin
+ readchar; { read # }
+ case c of
+ '$':
+ begin
+ readchar; { read leading $ }
+ asciinr:='$';
+ while (upcase(c) in ['A'..'F','0'..'9']) and (length(asciinr)<=5) do
+ begin
+ asciinr:=asciinr+c;
+ readchar;
+ end;
+ end;
+ '&':
+ begin
+ readchar; { read leading $ }
+ asciinr:='&';
+ while (upcase(c) in ['0'..'7']) and (length(asciinr)<=7) do
+ begin
+ asciinr:=asciinr+c;
+ readchar;
+ end;
+ end;
+ '%':
+ begin
+ readchar; { read leading $ }
+ asciinr:='%';
+ while (upcase(c) in ['0','1']) and (length(asciinr)<=17) do
+ begin
+ asciinr:=asciinr+c;
+ readchar;
+ end;
+ end;
+ else
+ begin
+ asciinr:='';
+ while (c in ['0'..'9']) and (length(asciinr)<=5) do
+ begin
+ asciinr:=asciinr+c;
+ readchar;
+ end;
+ end;
+ end;
+ val(asciinr,m,code);
+ if (asciinr='') or (code<>0) then
+ Message(scan_e_illegal_char_const)
+ else if (m<0) or (m>255) or (length(asciinr)>3) then
+ begin
+ if (m>=0) and (m<=65535) then
+ begin
+ if not iswidestring then
+ begin
+ if len>0 then
+ ascii2unicode(@cstringpattern[1],len,current_settings.sourcecodepage,patternw)
+ else
+ ascii2unicode(nil,len,current_settings.sourcecodepage,patternw);
+ iswidestring:=true;
+ len:=0;
+ end;
+ concatwidestringchar(patternw,tcompilerwidechar(m));
+ end
+ else
+ Message(scan_e_illegal_char_const)
+ end
+ else if iswidestring then
+ concatwidestringchar(patternw,asciichar2unicode(char(m)))
+ else
+ begin
+ if len>=length(cstringpattern) then
+ setlength(cstringpattern,length(cstringpattern)+256);
+ inc(len);
+ cstringpattern[len]:=chr(m);
+ end;
+ end;
+ '''' :
+ begin
+ repeat
+ readchar;
+ case c of
+ #26 :
+ end_of_file;
+ #10,#13 :
+ Message(scan_f_string_exceeds_line);
+ '''' :
+ begin
+ readchar;
+ if c<>'''' then
+ break;
+ end;
+ end;
+ { interpret as utf-8 string? }
+ if (ord(c)>=$80) and (current_settings.sourcecodepage=CP_UTF8) then
+ begin
+ { convert existing string to an utf-8 string }
+ if not iswidestring then
+ begin
+ if len>0 then
+ ascii2unicode(@cstringpattern[1],len,current_settings.sourcecodepage,patternw)
+ else
+ ascii2unicode(nil,len,current_settings.sourcecodepage,patternw);
+ iswidestring:=true;
+ len:=0;
+ end;
+ { four or more chars aren't handled }
+ if (ord(c) and $f0)=$f0 then
+ message(scan_e_utf8_bigger_than_65535)
+ { three chars }
+ else if (ord(c) and $e0)=$e0 then
+ begin
+ w:=ord(c) and $f;
+ readchar;
+ if (ord(c) and $c0)<>$80 then
+ message(scan_e_utf8_malformed);
+ w:=(w shl 6) or (ord(c) and $3f);
+ readchar;
+ if (ord(c) and $c0)<>$80 then
+ message(scan_e_utf8_malformed);
+ w:=(w shl 6) or (ord(c) and $3f);
+ concatwidestringchar(patternw,w);
+ end
+ { two chars }
+ else if (ord(c) and $c0)<>0 then
+ begin
+ w:=ord(c) and $1f;
+ readchar;
+ if (ord(c) and $c0)<>$80 then
+ message(scan_e_utf8_malformed);
+ w:=(w shl 6) or (ord(c) and $3f);
+ concatwidestringchar(patternw,w);
+ end
+ { illegal }
+ else if (ord(c) and $80)<>0 then
+ message(scan_e_utf8_malformed)
+ else
+ concatwidestringchar(patternw,tcompilerwidechar(c))
+ end
+ else if iswidestring then
+ begin
+ if current_settings.sourcecodepage=CP_UTF8 then
+ concatwidestringchar(patternw,ord(c))
+ else
+ concatwidestringchar(patternw,asciichar2unicode(c))
+ end
+ else
+ begin
+ if len>=length(cstringpattern) then
+ setlength(cstringpattern,length(cstringpattern)+256);
+ inc(len);
+ cstringpattern[len]:=c;
+ end;
+ until false;
+ end;
+ '^' :
+ begin
+ readchar;
+ c:=upcase(c);
+ if c<#64 then
+ c:=chr(ord(c)+64)
+ else
+ c:=chr(ord(c)-64);
+
+ if iswidestring then
+ concatwidestringchar(patternw,asciichar2unicode(c))
+ else
+ begin
+ if len>=length(cstringpattern) then
+ setlength(cstringpattern,length(cstringpattern)+256);
+ inc(len);
+ cstringpattern[len]:=c;
+ end;
+
+ readchar;
+ end;
+ else
+ break;
+ end;
+ until false;
+ { strings with length 1 become const chars }
+ if iswidestring then
+ begin
+ if patternw^.len=1 then
+ token:=_CWCHAR
+ else
+ token:=_CWSTRING;
+ end
+ else
+ begin
+ setlength(cstringpattern,len);
+ if length(cstringpattern)=1 then
+ begin
+ token:=_CCHAR;
+ pattern:=cstringpattern;
+ end
+ else
+ token:=_CSTRING;
+ end;
+ goto exit_label;
+ end;
+
+ '>' :
+ begin
+ readchar;
+ if (block_type in [bt_type,bt_var_type,bt_const_type]) then
+ token:=_RSHARPBRACKET
+ else
+ begin
+ case c of
+ '=' :
+ begin
+ readchar;
+ token:=_GTE;
+ goto exit_label;
+ end;
+ '>' :
+ begin
+ readchar;
+ token:=_OP_SHR;
+ goto exit_label;
+ end;
+ '<' :
+ begin { >< is for a symetric diff for sets }
+ readchar;
+ token:=_SYMDIF;
+ goto exit_label;
+ end;
+ end;
+ token:=_GT;
+ end;
+ goto exit_label;
+ end;
+
+ '<' :
+ begin
+ readchar;
+ if (block_type in [bt_type,bt_var_type,bt_const_type]) then
+ token:=_LSHARPBRACKET
+ else
+ begin
+ case c of
+ '>' :
+ begin
+ readchar;
+ token:=_NE;
+ goto exit_label;
+ end;
+ '=' :
+ begin
+ readchar;
+ token:=_LTE;
+ goto exit_label;
+ end;
+ '<' :
+ begin
+ readchar;
+ token:=_OP_SHL;
+ goto exit_label;
+ end;
+ end;
+ token:=_LT;
+ end;
+ goto exit_label;
+ end;
+
+ #26 :
+ begin
+ token:=_EOF;
+ checkpreprocstack;
+ goto exit_label;
+ end;
+ else
+ Illegal_Char(c);
+ end;
+ end;
+exit_label:
+ lasttoken:=token;
+ end;
+
+
+ function tscannerfile.readpreproc:ttoken;
+ begin
+ skipspace;
+ case c of
+ '_',
+ 'A'..'Z',
+ 'a'..'z' :
+ begin
+ current_scanner.preproc_pattern:=readid;
+ readpreproc:=_ID;
+ end;
+ '0'..'9' :
+ begin
+ current_scanner.preproc_pattern:=readval_asstring;
+ { realnumber? }
+ if c='.' then
+ begin
+ readchar;
+ while c in ['0'..'9'] do
+ begin
+ current_scanner.preproc_pattern:=current_scanner.preproc_pattern+c;
+ readchar;
+ end;
+ end;
+ readpreproc:=_ID;
+ end;
+ '$','%','&' :
+ begin
+ current_scanner.preproc_pattern:=readval_asstring;
+ readpreproc:=_ID;
+ end;
+ ',' :
+ begin
+ readchar;
+ readpreproc:=_COMMA;
+ end;
+ '}' :
+ begin
+ readpreproc:=_END;
+ end;
+ '(' :
+ begin
+ readchar;
+ readpreproc:=_LKLAMMER;
+ end;
+ ')' :
+ begin
+ readchar;
+ readpreproc:=_RKLAMMER;
+ end;
+ '[' :
+ begin
+ readchar;
+ readpreproc:=_LECKKLAMMER;
+ end;
+ ']' :
+ begin
+ readchar;
+ readpreproc:=_RECKKLAMMER;
+ end;
+ '+' :
+ begin
+ readchar;
+ readpreproc:=_PLUS;
+ end;
+ '-' :
+ begin
+ readchar;
+ readpreproc:=_MINUS;
+ end;
+ '*' :
+ begin
+ readchar;
+ readpreproc:=_STAR;
+ end;
+ '/' :
+ begin
+ readchar;
+ readpreproc:=_SLASH;
+ end;
+ '=' :
+ begin
+ readchar;
+ readpreproc:=_EQ;
+ end;
+ '>' :
+ begin
+ readchar;
+ if c='=' then
+ begin
+ readchar;
+ readpreproc:=_GTE;
+ end
+ else
+ readpreproc:=_GT;
+ end;
+ '<' :
+ begin
+ readchar;
+ case c of
+ '>' :
+ begin
+ readchar;
+ readpreproc:=_NE;
+ end;
+ '=' :
+ begin
+ readchar;
+ readpreproc:=_LTE;
+ end;
+ else
+ readpreproc:=_LT;
+ end;
+ end;
+ #26 :
+ begin
+ readpreproc:=_EOF;
+ checkpreprocstack;
+ end;
+ else
+ Illegal_Char(c);
+ end;
+ end;
+
+
+ function tscannerfile.asmgetcharstart : char;
+ begin
+ { return first the character already
+ available in c }
+ lastasmgetchar:=c;
+ result:=asmgetchar;
+ end;
+
+
+ function tscannerfile.asmgetchar : char;
+ begin
+ if lastasmgetchar<>#0 then
+ begin
+ c:=lastasmgetchar;
+ lastasmgetchar:=#0;
+ end
+ else
+ readchar;
+ if in_asm_string then
+ begin
+ asmgetchar:=c;
+ exit;
+ end;
+ repeat
+ case c of
+ // the { ... } is used in ARM assembler to define register sets, so we can't used
+ // it as comment, either (* ... *), /* ... */ or // ... should be used instead.
+ // But compiler directives {$...} are allowed in ARM assembler.
+ '{' :
+ begin
+{$ifdef arm}
+ readchar;
+ dec(inputpointer);
+ if c<>'$' then
+ begin
+ asmgetchar:='{';
+ exit;
+ end
+ else
+{$endif arm}
+ skipcomment;
+ end;
+ #10,#13 :
+ begin
+ linebreak;
+ asmgetchar:=c;
+ exit;
+ end;
+ #26 :
+ begin
+ reload;
+ if (c=#26) and not assigned(inputfile.next) then
+ end_of_file;
+ continue;
+ end;
+ '/' :
+ begin
+ readchar;
+ if c='/' then
+ skipdelphicomment
+ else
+ begin
+ asmgetchar:='/';
+ lastasmgetchar:=c;
+ exit;
+ end;
+ end;
+ '(' :
+ begin
+ readchar;
+ if c='*' then
+ begin
+ c:=#0;{Signal skipoldtpcomment to reload a char }
+ skipoldtpcomment;
+ end
+ else
+ begin
+ asmgetchar:='(';
+ lastasmgetchar:=c;
+ exit;
+ end;
+ end;
+ else
+ begin
+ asmgetchar:=c;
+ exit;
+ end;
+ end;
+ until false;
+ end;
+
+
+{*****************************************************************************
+ Helpers
+*****************************************************************************}
+
+ procedure AddDirective(const s:string; dm: tdirectivemode; p:tdirectiveproc);
+ begin
+ if dm in [directive_all, directive_turbo] then
+ tdirectiveitem.create(turbo_scannerdirectives,s,p);
+ if dm in [directive_all, directive_mac] then
+ tdirectiveitem.create(mac_scannerdirectives,s,p);
+ end;
+
+ procedure AddConditional(const s:string; dm: tdirectivemode; p:tdirectiveproc);
+ begin
+ if dm in [directive_all, directive_turbo] then
+ tdirectiveitem.createcond(turbo_scannerdirectives,s,p);
+ if dm in [directive_all, directive_mac] then
+ tdirectiveitem.createcond(mac_scannerdirectives,s,p);
+ end;
+
+{*****************************************************************************
+ Initialization
+*****************************************************************************}
+
+ procedure InitScanner;
+ begin
+ InitWideString(patternw);
+ turbo_scannerdirectives:=TFPHashObjectList.Create;
+ mac_scannerdirectives:=TFPHashObjectList.Create;
+
+ { Common directives and conditionals }
+ AddDirective('I',directive_all, @dir_include);
+ AddDirective('DEFINE',directive_all, @dir_define);
+ AddDirective('UNDEF',directive_all, @dir_undef);
+
+ AddConditional('IF',directive_all, @dir_if);
+ AddConditional('IFDEF',directive_all, @dir_ifdef);
+ AddConditional('IFNDEF',directive_all, @dir_ifndef);
+ AddConditional('ELSE',directive_all, @dir_else);
+ AddConditional('ELSEIF',directive_all, @dir_elseif);
+ AddConditional('ENDIF',directive_all, @dir_endif);
+
+ { Directives and conditionals for all modes except mode macpas}
+ AddDirective('INCLUDE',directive_turbo, @dir_include);
+ AddDirective('LIBPREFIX',directive_turbo, @dir_libprefix);
+ AddDirective('LIBSUFFIX',directive_turbo, @dir_libsuffix);
+ AddDirective('EXTENSION',directive_turbo, @dir_extension);
+
+ AddConditional('IFEND',directive_turbo, @dir_endif);
+ AddConditional('IFOPT',directive_turbo, @dir_ifopt);
+
+ { Directives and conditionals for mode macpas: }
+ AddDirective('SETC',directive_mac, @dir_setc);
+ AddDirective('DEFINEC',directive_mac, @dir_definec);
+ AddDirective('UNDEFC',directive_mac, @dir_undef);
+
+ AddConditional('IFC',directive_mac, @dir_if);
+ AddConditional('ELSEC',directive_mac, @dir_else);
+ AddConditional('ELIFC',directive_mac, @dir_elseif);
+ AddConditional('ENDC',directive_mac, @dir_endif);
+ end;
+
+
+ procedure DoneScanner;
+ begin
+ turbo_scannerdirectives.Free;
+ mac_scannerdirectives.Free;
+ DoneWideString(patternw);
+ end;
+
+end.
diff --git a/closures/compiler/script.pas b/closures/compiler/script.pas
new file mode 100644
index 0000000000..eaeed314f0
--- /dev/null
+++ b/closures/compiler/script.pas
@@ -0,0 +1,526 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ This unit handles the writing of script files
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit script;
+
+{$i fpcdefs.inc}
+
+interface
+{$H+}
+uses
+ sysutils,
+ globtype,
+ cclasses;
+
+type
+ TScript=class
+ fn : TCmdStr;
+ data : TCmdStrList;
+ executable : boolean;
+ constructor Create(const s:TCmdStr);
+ constructor CreateExec(const s:TCmdStr);
+ destructor Destroy;override;
+ procedure AddStart(const s:TCmdStr);
+ procedure Add(const s:TCmdStr);
+ Function Empty:boolean;
+ procedure WriteToDisk;virtual;
+ end;
+
+ TAsmScript = class (TScript)
+ Constructor Create(Const ScriptName : TCmdStr); virtual;
+ Procedure AddAsmCommand (Const Command, Options,FileName : TCmdStr);virtual;abstract;
+ Procedure AddLinkCommand (Const Command, Options, FileName : TCmdStr);virtual;abstract;
+ Procedure AddDeleteCommand (Const FileName : TCmdStr);virtual;abstract;
+ Procedure AddDeleteDirCommand (Const FileName : TCmdStr);virtual;abstract;
+ end;
+
+ TAsmScriptDos = class (TAsmScript)
+ Constructor Create (Const ScriptName : TCmdStr); override;
+ Procedure AddAsmCommand (Const Command, Options,FileName : TCmdStr);override;
+ Procedure AddLinkCommand (Const Command, Options, FileName : TCmdStr);override;
+ Procedure AddDeleteCommand (Const FileName : TCmdStr);override;
+ Procedure AddDeleteDirCommand (Const FileName : TCmdStr);override;
+ Procedure WriteToDisk;override;
+ end;
+
+ TAsmScriptAmiga = class (TAsmScript)
+ Constructor Create (Const ScriptName : TCmdStr); override;
+ Procedure AddAsmCommand (Const Command, Options,FileName : TCmdStr);override;
+ Procedure AddLinkCommand (Const Command, Options, FileName : TCmdStr);override;
+ Procedure AddDeleteCommand (Const FileName : TCmdStr);override;
+ Procedure AddDeleteDirCommand (Const FileName : TCmdStr);override;
+ Procedure WriteToDisk;override;
+ end;
+
+ TAsmScriptUnix = class (TAsmScript)
+ Constructor Create (Const ScriptName : TCmdStr);override;
+ Procedure AddAsmCommand (Const Command, Options,FileName : TCmdStr);override;
+ Procedure AddLinkCommand (Const Command, Options, FileName : TCmdStr);override;
+ Procedure AddDeleteCommand (Const FileName : TCmdStr);override;
+ Procedure AddDeleteDirCommand (Const FileName : TCmdStr);override;
+ Procedure WriteToDisk;override;
+ end;
+
+ TAsmScriptMPW = class (TAsmScript)
+ Constructor Create (Const ScriptName : TCmdStr); override;
+ Procedure AddAsmCommand (Const Command, Options,FileName : TCmdStr);override;
+ Procedure AddLinkCommand (Const Command, Options, FileName : TCmdStr);override;
+ Procedure AddDeleteCommand (Const FileName : TCmdStr);override;
+ Procedure AddDeleteDirCommand (Const FileName : TCmdStr);override;
+ Procedure WriteToDisk;override;
+ end;
+
+ TLinkRes = Class (TScript)
+ section: string[30];
+ procedure Add(const s:TCmdStr);
+ procedure AddFileName(const s:TCmdStr);
+ procedure EndSection(const s:TCmdStr);
+ procedure StartSection(const s:TCmdStr);
+ end;
+
+var
+ AsmRes : TAsmScript;
+
+Function ScriptFixFileName(const s:TCmdStr):TCmdStr;
+Procedure GenerateAsmRes(const st : TCmdStr);
+
+
+implementation
+
+uses
+{$ifdef hasUnix}
+ BaseUnix,
+{$endif}
+ cutils,cfileutl,
+ globals,systems,verbose;
+
+
+{****************************************************************************
+ Helpers
+****************************************************************************}
+
+ Function ScriptFixFileName(const s:TCmdStr):TCmdStr;
+ begin
+ if cs_link_on_target in current_settings.globalswitches then
+ ScriptFixFileName:=TargetFixFileName(s)
+ else
+ ScriptFixFileName:=FixFileName(s);
+ end;
+
+{****************************************************************************
+ TScript
+****************************************************************************}
+
+constructor TScript.Create(const s: TCmdStr);
+begin
+ fn:=FixFileName(s);
+ executable:=false;
+ data:=TCmdStrList.Create;
+end;
+
+
+constructor TScript.CreateExec(const s:TCmdStr);
+begin
+ fn:=FixFileName(s);
+ if cs_link_on_target in current_settings.globalswitches then
+ fn:=ChangeFileExt(fn,target_info.scriptext)
+ else
+ fn:=ChangeFileExt(fn,source_info.scriptext);
+ executable:=true;
+ data:=TCmdStrList.Create;
+end;
+
+
+destructor TScript.Destroy;
+begin
+ data.Free;
+end;
+
+
+procedure TScript.AddStart(const s:TCmdStr);
+begin
+ data.Insert(s);
+end;
+
+
+procedure TScript.Add(const s:TCmdStr);
+begin
+ data.Concat(s);
+end;
+
+
+Function TScript.Empty:boolean;
+begin
+ Empty:=Data.Empty;
+end;
+
+procedure TScript.WriteToDisk;
+var
+ t : file;
+ i : longint;
+ s : TCmdStr;
+ le: string[2];
+
+begin
+ Assign(t,fn);
+ if cs_link_on_target in current_settings.globalswitches then
+ le:= target_info.newline
+ else
+ le:= source_info.newline;
+
+ {$push}{$I-}
+ Rewrite(t,1);
+ if ioresult<>0 then
+ exit;
+ while not data.Empty do
+ begin
+ s:=data.GetFirst;
+ Blockwrite(t,s[1],length(s),i);
+ Blockwrite(t,le[1],length(le),i);
+ end;
+ Close(t);
+ {$pop}
+ i:=ioresult;
+{$ifdef hasUnix}
+ if executable then
+ fpchmod(fn,493);
+{$endif}
+end;
+
+{****************************************************************************
+ Asm Response
+****************************************************************************}
+
+Constructor TAsmScript.Create (Const ScriptName : TCmdStr);
+begin
+ Inherited CreateExec(ScriptName);
+end;
+
+
+{****************************************************************************
+ DOS Asm Response
+****************************************************************************}
+
+Constructor TAsmScriptDos.Create (Const ScriptName : TCmdStr);
+begin
+ Inherited Create(ScriptName);
+end;
+
+
+Procedure TAsmScriptDos.AddAsmCommand (Const Command, Options,FileName : TCmdStr);
+begin
+ if FileName<>'' then
+ begin
+ Add('SET THEFILE='+ScriptFixFileName(FileName));
+ Add('echo Assembling %THEFILE%');
+ end;
+ Add(maybequoted(command)+' '+Options);
+ Add('if errorlevel 1 goto asmend');
+end;
+
+
+Procedure TAsmScriptDos.AddLinkCommand (Const Command, Options, FileName : TCmdStr);
+begin
+ if FileName<>'' then
+ begin
+ Add('SET THEFILE='+ScriptFixFileName(FileName));
+ Add('echo Linking %THEFILE%');
+ end;
+ Add(maybequoted(command)+' '+Options);
+ Add('if errorlevel 1 goto linkend');
+end;
+
+
+Procedure TAsmScriptDos.AddDeleteCommand (Const FileName : TCmdStr);
+begin
+ Add('Del ' + MaybeQuoted (ScriptFixFileName (FileName)));
+end;
+
+
+Procedure TAsmScriptDos.AddDeleteDirCommand (Const FileName : TCmdStr);
+begin
+ Add('Rmdir ' + MaybeQuoted (ScriptFixFileName (FileName)));
+end;
+
+
+Procedure TAsmScriptDos.WriteToDisk;
+Begin
+ AddStart('@echo off');
+ Add('goto end');
+ Add(':asmend');
+ Add('echo An error occured while assembling %THEFILE%');
+ Add('goto end');
+ Add(':linkend');
+ Add('echo An error occured while linking %THEFILE%');
+ Add(':end');
+ inherited WriteToDisk;
+end;
+
+{****************************************************************************
+ Amiga Asm Response
+****************************************************************************}
+
+
+Constructor TAsmScriptAmiga.Create (Const ScriptName : TCmdStr);
+begin
+ Inherited Create(ScriptName);
+end;
+
+
+Procedure TAsmScriptAmiga.AddAsmCommand (Const Command, Options,FileName : TCmdStr);
+begin
+ if FileName<>'' then
+ begin
+ Add('SET THEFILE '+ScriptFixFileName(FileName));
+ Add('echo Assembling $THEFILE');
+ end;
+ Add(maybequoted(command)+' '+Options);
+ { There is a problem here,
+ as always return with a non zero error value PM }
+ Add('if error');
+ Add('why');
+ Add('skip asmend');
+ Add('endif');
+end;
+
+
+Procedure TAsmScriptAmiga.AddLinkCommand (Const Command, Options, FileName : TCmdStr);
+begin
+ if FileName<>'' then
+ begin
+ Add('SET THEFILE '+ScriptFixFileName(FileName));
+ Add('echo Linking $THEFILE');
+ end;
+ Add(maybequoted(command)+' '+Options);
+ Add('if error');
+ Add('skip linkend');
+ Add('endif');
+end;
+
+
+Procedure TAsmScriptAmiga.AddDeleteCommand (Const FileName : TCmdStr);
+begin
+ Add('Delete ' + Unix2AmigaPath(MaybeQuoted(ScriptFixFileName(FileName))) + ' Quiet');
+end;
+
+
+Procedure TAsmScriptAmiga.AddDeleteDirCommand (Const FileName : TCmdStr);
+begin
+ Add('Delete ' + Unix2AmigaPath(MaybeQuoted(ScriptFixFileName(FileName))) + ' All Quiet');
+end;
+
+
+Procedure TAsmScriptAmiga.WriteToDisk;
+Begin
+ Add('skip end');
+ Add('lab asmend');
+ Add('why');
+ Add('echo An error occured while assembling $THEFILE');
+ Add('skip end');
+ Add('lab linkend');
+ Add('why');
+ Add('echo An error occured while linking $THEFILE');
+ Add('lab end');
+ inherited WriteToDisk;
+end;
+
+
+{****************************************************************************
+ Unix Asm Response
+****************************************************************************}
+
+Constructor TAsmScriptUnix.Create (Const ScriptName : TCmdStr);
+begin
+ Inherited Create(ScriptName);
+end;
+
+
+Procedure TAsmScriptUnix.AddAsmCommand (Const Command, Options,FileName : TCmdStr);
+begin
+ if FileName<>'' then
+ Add('echo Assembling '+ScriptFixFileName(FileName));
+ Add(maybequoted(command)+' '+Options);
+ Add('if [ $? != 0 ]; then DoExitAsm '+ScriptFixFileName(FileName)+'; fi');
+end;
+
+
+Procedure TAsmScriptUnix.AddLinkCommand (Const Command, Options, FileName : TCmdStr);
+begin
+ if FileName<>'' then
+ Add('echo Linking '+ScriptFixFileName(FileName));
+ Add('OFS=$IFS');
+ Add('IFS="');
+ Add('"');
+ Add(maybequoted(command)+' '+Options);
+ Add('if [ $? != 0 ]; then DoExitLink '+ScriptFixFileName(FileName)+'; fi');
+ Add('IFS=$OFS');
+end;
+
+
+Procedure TAsmScriptUnix.AddDeleteCommand (Const FileName : TCmdStr);
+begin
+ Add('rm ' + MaybeQuoted (ScriptFixFileName(FileName)));
+end;
+
+
+Procedure TAsmScriptUnix.AddDeleteDirCommand (Const FileName : TCmdStr);
+begin
+ Add('rmdir ' + MaybeQuoted (ScriptFixFileName(FileName)));
+end;
+
+
+Procedure TAsmScriptUnix.WriteToDisk;
+Begin
+ AddStart('{ echo "An error occurred while linking $1"; exit 1; }');
+ AddStart('DoExitLink ()');
+ AddStart('{ echo "An error occurred while assembling $1"; exit 1; }');
+ AddStart('DoExitAsm ()');
+ {$ifdef BEOS}
+ AddStart('#!/boot/beos/bin/sh');
+ {$else}
+ AddStart('#!/bin/sh');
+ {$endif}
+ inherited WriteToDisk;
+end;
+
+
+{****************************************************************************
+ MPW (MacOS) Asm Response
+****************************************************************************}
+
+Constructor TAsmScriptMPW.Create (Const ScriptName : TCmdStr);
+begin
+ Inherited Create(ScriptName);
+end;
+
+
+Procedure TAsmScriptMPW.AddAsmCommand (Const Command, Options,FileName : TCmdStr);
+begin
+ if FileName<>'' then
+ Add('Echo Assembling '+ScriptFixFileName(FileName));
+ Add(maybequoted(command)+' '+Options);
+ Add('Exit If "{Status}" != 0');
+end;
+
+
+Procedure TAsmScriptMPW.AddLinkCommand (Const Command, Options, FileName : TCmdStr);
+begin
+ if FileName<>'' then
+ Add('Echo Linking '+ScriptFixFileName(FileName));
+ Add(maybequoted(command)+' '+Options);
+ Add('Exit If "{Status}" != 0');
+
+ {Add resources}
+ if apptype = app_cui then {If SIOW}
+ begin
+ Add('Rez -append "{RIncludes}"SIOW.r -o '+ ScriptFixFileName(FileName));
+ Add('Exit If "{Status}" != 0');
+ end;
+end;
+
+
+Procedure TAsmScriptMPW.AddDeleteCommand (Const FileName : TCmdStr);
+begin
+ Add('Delete ' + MaybeQuoted (ScriptFixFileName(FileName)));
+end;
+
+
+Procedure TAsmScriptMPW.AddDeleteDirCommand (Const FileName : TCmdStr);
+begin
+ Add('Delete ' + MaybeQuoted (ScriptFixFileName (FileName)));
+end;
+
+
+Procedure TAsmScriptMPW.WriteToDisk;
+Begin
+ AddStart('# Script for assembling and linking a FreePascal program on MPW (MacOS)');
+ Add('Echo Done');
+ inherited WriteToDisk;
+end;
+
+
+
+Procedure GenerateAsmRes(const st : TCmdStr);
+var
+ scripttyp : tscripttype;
+begin
+ if cs_link_on_target in current_settings.globalswitches then
+ scripttyp := target_info.script
+ else
+ scripttyp := source_info.script;
+ case scripttyp of
+ script_unix :
+ AsmRes:=TAsmScriptUnix.Create(st);
+ script_dos :
+ AsmRes:=TAsmScriptDos.Create(st);
+ script_amiga :
+ AsmRes:=TAsmScriptAmiga.Create(st);
+ script_mpw :
+ AsmRes:=TAsmScriptMPW.Create(st);
+ end;
+end;
+
+
+{****************************************************************************
+ Link Response
+****************************************************************************}
+
+procedure TLinkRes.Add(const s:TCmdStr);
+begin
+ if s<>'' then
+ inherited Add(s);
+end;
+
+procedure TLinkRes.AddFileName(const s:TCmdStr);
+begin
+ if section<>'' then
+ begin
+ inherited Add(section);
+ section:='';
+ end;
+ if s<>'' then
+ begin
+ if not(s[1] in ['a'..'z','A'..'Z','/','\','.','"']) then
+ begin
+ if cs_link_on_target in current_settings.globalswitches then
+ inherited Add('.'+target_info.DirSep+s)
+ else
+ inherited Add('.'+source_info.DirSep+s);
+ end
+ else
+ inherited Add(s);
+ end;
+end;
+
+procedure TLinkRes.EndSection(const s:TCmdStr);
+begin
+ { only terminate if we started the section }
+ if section='' then
+ inherited Add(s);
+ section:='';
+end;
+
+procedure TLinkRes.StartSection(const s:TCmdStr);
+begin
+ section:=s;
+end;
+
+end.
diff --git a/closures/compiler/sparc/aasmcpu.pas b/closures/compiler/sparc/aasmcpu.pas
new file mode 100644
index 0000000000..6583b3d377
--- /dev/null
+++ b/closures/compiler/sparc/aasmcpu.pas
@@ -0,0 +1,318 @@
+{
+ Copyright (c) 1999-2002 by Mazen Neifer
+
+ Contains the assembler object for the SPARC
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit aasmcpu;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ cclasses,
+ globtype,globals,verbose,
+ aasmbase,aasmtai,aasmdata,aasmsym,
+ cgbase,cgutils,cpubase,cpuinfo;
+
+ const
+ { "mov reg,reg" source operand number }
+ O_MOV_SOURCE = 0;
+ { "mov reg,reg" source operand number }
+ O_MOV_DEST = 1;
+
+ type
+ taicpu = class(tai_cpu_abstract_sym)
+ delayslot_annulled : boolean; { conditinal opcode with ,a }
+ constructor op_none(op : tasmop);
+
+ constructor op_reg(op : tasmop;_op1 : tregister);
+ constructor op_const(op : tasmop;_op1 : LongInt);
+ constructor op_ref(op : tasmop;const _op1 : treference);
+
+ constructor op_reg_reg(op : tasmop;_op1,_op2 : tregister);
+ constructor op_reg_ref(op : tasmop;_op1 : tregister;const _op2 : treference);
+ constructor op_reg_const(op:tasmop; _op1: tregister; _op2: LongInt);
+ constructor op_const_reg(op:tasmop; _op1: LongInt; _op2: tregister);
+ constructor op_ref_reg(op : tasmop;const _op1 : treference;_op2 : tregister);
+
+ constructor op_reg_reg_reg(op : tasmop;_op1,_op2,_op3 : tregister);
+ constructor op_reg_ref_reg(op:tasmop;_op1:TRegister;_op2:TReference;_op3:tregister);
+ constructor op_reg_const_reg(op:tasmop;_op1:TRegister;_op2:aint;_op3:tregister);
+
+ { this is for Jmp instructions }
+ constructor op_cond_sym(op : tasmop;cond:TAsmCond;_op1 : tasmsymbol);
+ constructor op_sym(op : tasmop;_op1 : tasmsymbol);
+ constructor op_sym_ofs(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint);
+ procedure loadbool(opidx:longint;_b:boolean);
+ { register allocation }
+ function is_same_reg_move(regtype: Tregistertype):boolean; override;
+
+ { register spilling code }
+ function spilling_get_operation_type(opnr: longint): topertype;override;
+ end;
+
+ tai_align = class(tai_align_abstract)
+ { nothing to add }
+ end;
+
+ procedure InitAsm;
+ procedure DoneAsm;
+
+ function spilling_create_load(const ref:treference;r:tregister):Taicpu;
+ function spilling_create_store(r:tregister; const ref:treference):Taicpu;
+
+implementation
+
+{*****************************************************************************
+ taicpu Constructors
+*****************************************************************************}
+
+ procedure taicpu.loadbool(opidx:longint;_b:boolean);
+ begin
+ if opidx>=ops then
+ ops:=opidx+1;
+ with oper[opidx]^ do
+ begin
+ if typ=top_ref then
+ dispose(ref);
+ b:=_b;
+ typ:=top_bool;
+ end;
+ end;
+
+
+ constructor taicpu.op_none(op : tasmop);
+ begin
+ inherited create(op);
+ end;
+
+
+ constructor taicpu.op_reg(op : tasmop;_op1 : tregister);
+ begin
+ inherited create(op);
+ ops:=1;
+ loadreg(0,_op1);
+ end;
+
+
+ constructor taicpu.op_ref(op : tasmop;const _op1 : treference);
+ begin
+ inherited create(op);
+ ops:=1;
+ loadref(0,_op1);
+ end;
+
+
+ constructor taicpu.op_const(op : tasmop;_op1 : LongInt);
+ begin
+ inherited create(op);
+ ops:=1;
+ loadconst(0,_op1);
+ end;
+
+
+ constructor taicpu.op_reg_reg(op : tasmop;_op1,_op2 : tregister);
+ begin
+ inherited create(op);
+ ops:=2;
+ loadreg(0,_op1);
+ loadreg(1,_op2);
+ end;
+
+ constructor taicpu.op_reg_const(op:tasmop; _op1: tregister; _op2: LongInt);
+ begin
+ inherited create(op);
+ ops:=2;
+ loadreg(0,_op1);
+ loadconst(1,_op2);
+ end;
+
+ constructor taicpu.op_const_reg(op:tasmop; _op1: LongInt; _op2: tregister);
+ begin
+ inherited create(op);
+ ops:=2;
+ loadconst(0,_op1);
+ loadreg(1,_op2);
+ end;
+
+
+ constructor taicpu.op_reg_ref(op : tasmop;_op1 : tregister;const _op2 : treference);
+ begin
+ inherited create(op);
+ ops:=2;
+ loadreg(0,_op1);
+ loadref(1,_op2);
+ end;
+
+
+ constructor taicpu.op_ref_reg(op : tasmop;const _op1 : treference;_op2 : tregister);
+ begin
+ inherited create(op);
+ ops:=2;
+ loadref(0,_op1);
+ loadreg(1,_op2);
+ end;
+
+
+ constructor taicpu.op_reg_reg_reg(op : tasmop;_op1,_op2,_op3 : tregister);
+ begin
+ inherited create(op);
+ ops:=3;
+ loadreg(0,_op1);
+ loadreg(1,_op2);
+ loadreg(2,_op3);
+ end;
+
+
+ constructor taicpu.op_reg_ref_reg(op:tasmop;_op1:TRegister;_op2:TReference;_op3:tregister);
+ begin
+ inherited create(op);
+ { only allowed to load the address }
+ if not(_op2.refaddr in [addr_low,addr_high]) then
+ internalerror(200305311);
+ ops:=3;
+ loadreg(0,_op1);
+ loadref(1,_op2);
+ loadreg(2,_op3);
+ end;
+
+
+ constructor taicpu.op_reg_const_reg(op:tasmop;_op1:TRegister;_op2:aint;_op3:tregister);
+ begin
+ inherited create(op);
+ ops:=3;
+ loadreg(0,_op1);
+ loadconst(1,_op2);
+ loadreg(2,_op3);
+ end;
+
+
+ constructor taicpu.op_cond_sym(op : tasmop;cond:TAsmCond;_op1 : tasmsymbol);
+ begin
+ inherited create(op);
+ is_jmp:=op in [A_BA,A_Bxx];
+ condition:=cond;
+ ops:=1;
+ loadsymbol(0,_op1,0);
+ end;
+
+
+ constructor taicpu.op_sym(op : tasmop;_op1 : tasmsymbol);
+ begin
+ inherited create(op);
+ is_jmp:=op in [A_BA,A_Bxx];
+ ops:=1;
+ loadsymbol(0,_op1,0);
+ end;
+
+
+ constructor taicpu.op_sym_ofs(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint);
+ begin
+ inherited create(op);
+ ops:=1;
+ loadsymbol(0,_op1,_op1ofs);
+ end;
+
+
+ function taicpu.is_same_reg_move(regtype: Tregistertype):boolean;
+ begin
+ result:=(
+ ((opcode=A_MOV) and (regtype = R_INTREGISTER)) or
+ ((regtype = R_FPUREGISTER) and (opcode in [A_FMOVS,A_FMOVD]))
+ ) and
+ (ops=2) and
+ (oper[0]^.typ=top_reg) and
+ (oper[1]^.typ=top_reg) and
+ (oper[0]^.reg=oper[1]^.reg);
+ end;
+
+
+ function taicpu.spilling_get_operation_type(opnr: longint): topertype;
+ begin
+ result := operand_read;
+ case opcode of
+ A_FCMPs,A_FCMPd,A_FCMPq :
+ ;
+ else
+ begin
+ if opnr=ops-1 then
+ result := operand_write;
+ end;
+ end;
+ end;
+
+
+ function spilling_create_load(const ref:treference;r:tregister):Taicpu;
+ begin
+ case getregtype(r) of
+ R_INTREGISTER :
+ result:=taicpu.op_ref_reg(A_LD,ref,r);
+ R_FPUREGISTER :
+ begin
+ case getsubreg(r) of
+ R_SUBFS :
+ result:=taicpu.op_ref_reg(A_LDF,ref,r);
+ R_SUBFD :
+ result:=taicpu.op_ref_reg(A_LDD,ref,r);
+ else
+ internalerror(200401042);
+ end;
+ end
+ else
+ internalerror(200401041);
+ end;
+ end;
+
+
+ function spilling_create_store(r:tregister; const ref:treference):Taicpu;
+ begin
+ case getregtype(r) of
+ R_INTREGISTER :
+ result:=taicpu.op_reg_ref(A_ST,r,ref);
+ R_FPUREGISTER :
+ begin
+ case getsubreg(r) of
+ R_SUBFS :
+ result:=taicpu.op_reg_ref(A_STF,r,ref);
+ R_SUBFD :
+ result:=taicpu.op_reg_ref(A_STD,r,ref);
+ else
+ internalerror(200401042);
+ end;
+ end
+ else
+ internalerror(200401041);
+ end;
+ end;
+
+
+ procedure InitAsm;
+ begin
+ end;
+
+
+ procedure DoneAsm;
+ begin
+ end;
+
+begin
+ cai_cpu:=taicpu;
+ cai_align:=tai_align;
+end.
diff --git a/closures/compiler/sparc/aoptcpu.pas b/closures/compiler/sparc/aoptcpu.pas
new file mode 100644
index 0000000000..cb656af36e
--- /dev/null
+++ b/closures/compiler/sparc/aoptcpu.pas
@@ -0,0 +1,41 @@
+{
+ Copyright (c) 1998-2004 by Jonas Maebe
+
+ This unit calls the optimization procedures to optimize the assembler
+ code for sparc
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+
+unit aoptcpu;
+
+{$i fpcdefs.inc}
+
+ Interface
+
+ uses
+ cpubase, aoptobj, aoptcpub, aopt;
+
+ Type
+ TCpuAsmOptimizer = class(TAsmOptimizer)
+ End;
+
+ Implementation
+
+begin
+ casmoptimizer:=TCpuAsmOptimizer;
+end.
diff --git a/closures/compiler/sparc/aoptcpub.pas b/closures/compiler/sparc/aoptcpub.pas
new file mode 100644
index 0000000000..b6954875a2
--- /dev/null
+++ b/closures/compiler/sparc/aoptcpub.pas
@@ -0,0 +1,120 @@
+ {
+ Copyright (c) 1998-2004 by Jonas Maebe, member of the Free Pascal
+ Development Team
+
+ This unit contains several types and constants necessary for the
+ optimizer to work on the sparc architecture
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+Unit aoptcpub; { Assembler OPTimizer CPU specific Base }
+
+{$i fpcdefs.inc}
+
+{ enable the following define if memory references can have both a base and }
+{ index register in 1 operand }
+
+{$define RefsHaveIndexReg}
+
+{ enable the following define if memory references can have a scaled index }
+
+{ define RefsHaveScale}
+
+{ enable the following define if memory references can have a segment }
+{ override }
+
+{ define RefsHaveSegment}
+
+Interface
+
+Uses
+ cpubase,aasmcpu,AOptBase;
+
+Type
+
+{ type of a normal instruction }
+ TInstr = Taicpu;
+ PInstr = ^TInstr;
+
+{ ************************************************************************* }
+{ **************************** TCondRegs ********************************** }
+{ ************************************************************************* }
+{ Info about the conditional registers }
+ TCondRegs = Object
+ Constructor Init;
+ Destructor Done;
+ End;
+
+{ ************************************************************************* }
+{ **************************** TAoptBaseCpu ******************************* }
+{ ************************************************************************* }
+
+ TAoptBaseCpu = class(TAoptBase)
+ End;
+
+
+{ ************************************************************************* }
+{ ******************************* Constants ******************************* }
+{ ************************************************************************* }
+Const
+
+{ the maximum number of things (registers, memory, ...) a single instruction }
+{ changes }
+
+ MaxCh = 3;
+
+{ the maximum number of operands an instruction has }
+
+ MaxOps = 3;
+
+{Oper index of operand that contains the source (reference) with a load }
+{instruction }
+
+ LoadSrc = 0;
+
+{Oper index of operand that contains the destination (register) with a load }
+{instruction }
+
+ LoadDst = 1;
+
+{Oper index of operand that contains the source (register) with a store }
+{instruction }
+
+ StoreSrc = 0;
+
+{Oper index of operand that contains the destination (reference) with a load }
+{instruction }
+
+ StoreDst = 1;
+
+ aopt_uncondjmp = A_BA;
+ aopt_condjmp = A_Bxx;
+
+Implementation
+
+{ ************************************************************************* }
+{ **************************** TCondRegs ********************************** }
+{ ************************************************************************* }
+Constructor TCondRegs.init;
+Begin
+End;
+
+Destructor TCondRegs.Done; {$ifdef inl} inline; {$endif inl}
+Begin
+End;
+
+End.
diff --git a/closures/compiler/sparc/aoptcpud.pas b/closures/compiler/sparc/aoptcpud.pas
new file mode 100644
index 0000000000..cb8c5d319f
--- /dev/null
+++ b/closures/compiler/sparc/aoptcpud.pas
@@ -0,0 +1,36 @@
+{
+ Copyright (c) 1998-2004 by Jonas Maebe, member of the Free Pascal
+ Development Team
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+Unit aoptcpud;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ aoptda;
+
+ type
+ TAOptDFACpu = class(TAOptDFA)
+ end;
+
+ implementation
+
+end.
diff --git a/closures/compiler/sparc/cgcpu.pas b/closures/compiler/sparc/cgcpu.pas
new file mode 100644
index 0000000000..4da36945d7
--- /dev/null
+++ b/closures/compiler/sparc/cgcpu.pas
@@ -0,0 +1,1598 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit implements the code generator for the SPARC
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit cgcpu;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ globtype,parabase,
+ cgbase,cgutils,cgobj,cg64f32,
+ aasmbase,aasmtai,aasmdata,aasmcpu,
+ cpubase,cpuinfo,
+ node,symconst,SymType,symdef,
+ rgcpu;
+
+ type
+ TCgSparc=class(tcg)
+ protected
+ function IsSimpleRef(const ref:treference):boolean;
+ public
+ procedure init_register_allocators;override;
+ procedure done_register_allocators;override;
+ function getfpuregister(list:TAsmList;size:Tcgsize):Tregister;override;
+ { sparc special, needed by cg64 }
+ procedure make_simple_ref(list:TAsmList;var ref: treference);
+ procedure handle_load_store(list:TAsmList;isstore:boolean;op: tasmop;reg:tregister;ref: treference);
+ procedure handle_reg_const_reg(list:TAsmList;op:Tasmop;src:tregister;a:tcgint;dst:tregister);
+ { parameter }
+ procedure a_load_const_cgpara(list:TAsmList;size:tcgsize;a:tcgint;const paraloc:TCGPara);override;
+ procedure a_load_ref_cgpara(list:TAsmList;sz:tcgsize;const r:TReference;const paraloc:TCGPara);override;
+ procedure a_loadaddr_ref_cgpara(list:TAsmList;const r:TReference;const paraloc:TCGPara);override;
+ procedure a_loadfpu_reg_cgpara(list : TAsmList;size : tcgsize;const r : tregister;const paraloc : TCGPara);override;
+ procedure a_loadfpu_ref_cgpara(list : TAsmList;size : tcgsize;const ref : treference;const paraloc : TCGPara);override;
+ procedure a_call_name(list:TAsmList;const s:string; weak: boolean);override;
+ procedure a_call_reg(list:TAsmList;Reg:TRegister);override;
+ { General purpose instructions }
+ procedure maybeadjustresult(list: TAsmList; op: TOpCg; size: tcgsize; dst: tregister);
+ procedure a_op_const_reg(list:TAsmList;Op:TOpCG;size:tcgsize;a:tcgint;reg:TRegister);override;
+ procedure a_op_reg_reg(list:TAsmList;Op:TOpCG;size:TCGSize;src, dst:TRegister);override;
+ procedure a_op_const_reg_reg(list:TAsmList;op:TOpCg;size:tcgsize;a:tcgint;src, dst:tregister);override;
+ procedure a_op_reg_reg_reg(list:TAsmList;op:TOpCg;size:tcgsize;src1, src2, dst:tregister);override;
+ procedure a_op_const_reg_reg_checkoverflow(list: TAsmList; op: TOpCg; size: tcgsize; a: tcgint; src, dst: tregister;setflags : boolean;var ovloc : tlocation);override;
+ procedure a_op_reg_reg_reg_checkoverflow(list: TAsmList; op: TOpCg; size: tcgsize; src1, src2, dst: tregister;setflags : boolean;var ovloc : tlocation);override;
+ { move instructions }
+ procedure a_load_const_reg(list:TAsmList;size:tcgsize;a:tcgint;reg:tregister);override;
+ procedure a_load_const_ref(list:TAsmList;size:tcgsize;a:tcgint;const ref:TReference);override;
+ procedure a_load_reg_ref(list:TAsmList;FromSize,ToSize:TCgSize;reg:TRegister;const ref:TReference);override;
+ procedure a_load_ref_reg(list:TAsmList;FromSize,ToSize:TCgSize;const ref:TReference;reg:tregister);override;
+ procedure a_load_reg_reg(list:TAsmList;FromSize,ToSize:TCgSize;reg1,reg2:tregister);override;
+ procedure a_loadaddr_ref_reg(list:TAsmList;const ref:TReference;r:tregister);override;
+ { fpu move instructions }
+ procedure a_loadfpu_reg_reg(list:TAsmList;fromsize,tosize:tcgsize;reg1, reg2:tregister);override;
+ procedure a_loadfpu_ref_reg(list:TAsmList;fromsize,tosize:tcgsize;const ref:TReference;reg:tregister);override;
+ procedure a_loadfpu_reg_ref(list:TAsmList;fromsize,tosize:tcgsize;reg:tregister;const ref:TReference);override;
+ { comparison operations }
+ procedure a_cmp_const_reg_label(list:TAsmList;size:tcgsize;cmp_op:topcmp;a:tcgint;reg:tregister;l:tasmlabel);override;
+ procedure a_cmp_reg_reg_label(list:TAsmList;size:tcgsize;cmp_op:topcmp;reg1,reg2:tregister;l:tasmlabel);override;
+ procedure a_jmp_always(List:TAsmList;l:TAsmLabel);override;
+ procedure a_jmp_name(list : TAsmList;const s : string);override;
+ procedure a_jmp_cond(list:TAsmList;cond:TOpCmp;l:tasmlabel);{ override;}
+ procedure a_jmp_flags(list:TAsmList;const f:TResFlags;l:tasmlabel);override;
+ procedure g_flags2reg(list:TAsmList;Size:TCgSize;const f:tresflags;reg:TRegister);override;
+ procedure g_overflowCheck(List:TAsmList;const Loc:TLocation;def:TDef);override;
+ procedure g_overflowCheck_loc(List:TAsmList;const Loc:TLocation;def:TDef;ovloc : tlocation);override;
+ procedure g_proc_entry(list : TAsmList;localsize : longint;nostackframe:boolean);override;
+ procedure g_proc_exit(list : TAsmList;parasize:longint;nostackframe:boolean);override;
+ procedure g_restore_registers(list:TAsmList);override;
+ procedure g_save_registers(list : TAsmList);override;
+ procedure g_concatcopy(list : TAsmList;const source,dest : treference;len : tcgint);override;
+ procedure g_concatcopy_unaligned(list : TAsmList;const source,dest : treference;len : tcgint);override;
+ procedure g_concatcopy_move(list : TAsmList;const source,dest : treference;len : tcgint);
+ procedure g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);override;
+ { Transform unsupported methods into Internal errors }
+ procedure a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; size: TCGSize; src, dst: TRegister); override;
+ procedure g_stackpointer_alloc(list : TAsmList;localsize : longint);override;
+ private
+ g1_used : boolean;
+ end;
+
+ TCg64Sparc=class(tcg64f32)
+ private
+ procedure get_64bit_ops(op:TOpCG;var op1,op2:TAsmOp;checkoverflow : boolean);
+ public
+ procedure a_load64_reg_ref(list : TAsmList;reg : tregister64;const ref : treference);override;
+ procedure a_load64_ref_reg(list : TAsmList;const ref : treference;reg : tregister64);override;
+ procedure a_load64_ref_cgpara(list : TAsmList;const r : treference;const paraloc : tcgpara);override;
+ procedure a_op64_reg_reg(list:TAsmList;op:TOpCG;size : tcgsize;regsrc,regdst:TRegister64);override;
+ procedure a_op64_const_reg(list:TAsmList;op:TOpCG;size : tcgsize;value:int64;regdst:TRegister64);override;
+ procedure a_op64_const_reg_reg(list: TAsmList;op:TOpCG;size : tcgsize;value : int64;regsrc,regdst : tregister64);override;
+ procedure a_op64_reg_reg_reg(list: TAsmList;op:TOpCG;size : tcgsize;regsrc1,regsrc2,regdst : tregister64);override;
+ procedure a_op64_const_reg_reg_checkoverflow(list: TAsmList;op:TOpCG;size : tcgsize;value : int64;regsrc,regdst : tregister64;setflags : boolean;var ovloc : tlocation);override;
+ procedure a_op64_reg_reg_reg_checkoverflow(list: TAsmList;op:TOpCG;size : tcgsize;regsrc1,regsrc2,regdst : tregister64;setflags : boolean;var ovloc : tlocation);override;
+ end;
+
+ procedure create_codegen;
+
+ const
+ TOpCG2AsmOp : array[topcg] of TAsmOp=(
+ A_NONE,A_MOV,A_ADD,A_AND,A_UDIV,A_SDIV,A_SMUL,A_UMUL,A_NEG,A_NOT,A_OR,A_SRA,A_SLL,A_SRL,A_SUB,A_XOR,A_NONE,A_NONE
+ );
+ TOpCG2AsmOpWithFlags : array[topcg] of TAsmOp=(
+ A_NONE,A_MOV,A_ADDcc,A_ANDcc,A_UDIVcc,A_SDIVcc,A_SMULcc,A_UMULcc,A_NEG,A_NOT,A_ORcc,A_SRA,A_SLL,A_SRL,A_SUBcc,A_XORcc,A_NONE,A_NONE
+ );
+ TOpCmp2AsmCond : array[topcmp] of TAsmCond=(C_NONE,
+ C_E,C_G,C_L,C_GE,C_LE,C_NE,C_BE,C_B,C_AE,C_A
+ );
+
+
+implementation
+
+ uses
+ globals,verbose,systems,cutils,
+ paramgr,fmodule,
+ tgobj,
+ procinfo,cpupi;
+
+
+ function TCgSparc.IsSimpleRef(const ref:treference):boolean;
+ begin
+ if (ref.base=NR_NO) and (ref.index<>NR_NO) then
+ InternalError(2002100804);
+ result :=not(assigned(ref.symbol))and
+ (((ref.index = NR_NO) and
+ (ref.offset >= simm13lo) and
+ (ref.offset <= simm13hi)) or
+ ((ref.index <> NR_NO) and
+ (ref.offset = 0)));
+ end;
+
+
+ procedure tcgsparc.make_simple_ref(list:TAsmList;var ref: treference);
+ var
+ tmpreg : tregister;
+ tmpref : treference;
+ begin
+ tmpreg:=NR_NO;
+ { Be sure to have a base register }
+ if (ref.base=NR_NO) then
+ begin
+ ref.base:=ref.index;
+ ref.index:=NR_NO;
+ end;
+ if (cs_create_pic in current_settings.moduleswitches) and
+ assigned(ref.symbol) then
+ begin
+ tmpreg:=GetIntRegister(list,OS_INT);
+ reference_reset(tmpref,ref.alignment);
+ tmpref.symbol:=ref.symbol;
+ tmpref.refaddr:=addr_pic;
+ if not(pi_needs_got in current_procinfo.flags) then
+ internalerror(200501161);
+ tmpref.index:=current_procinfo.got;
+ list.concat(taicpu.op_ref_reg(A_LD,tmpref,tmpreg));
+ ref.symbol:=nil;
+ if (ref.index<>NR_NO) then
+ begin
+ list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.index,tmpreg));
+ ref.index:=tmpreg;
+ end
+ else
+ begin
+ if ref.base<>NR_NO then
+ ref.index:=tmpreg
+ else
+ ref.base:=tmpreg;
+ end;
+ end;
+ { When need to use SETHI, do it first }
+ if assigned(ref.symbol) or
+ (ref.offset<simm13lo) or
+ (ref.offset>simm13hi) then
+ begin
+ tmpreg:=GetIntRegister(list,OS_INT);
+ reference_reset(tmpref,ref.alignment);
+ tmpref.symbol:=ref.symbol;
+ tmpref.offset:=ref.offset;
+ tmpref.refaddr:=addr_high;
+ list.concat(taicpu.op_ref_reg(A_SETHI,tmpref,tmpreg));
+ if (ref.offset=0) and (ref.index=NR_NO) and
+ (ref.base=NR_NO) then
+ begin
+ ref.refaddr:=addr_low;
+ end
+ else
+ begin
+ { Load the low part is left }
+ tmpref.refaddr:=addr_low;
+ list.concat(taicpu.op_reg_ref_reg(A_OR,tmpreg,tmpref,tmpreg));
+ ref.offset:=0;
+ { symbol is loaded }
+ ref.symbol:=nil;
+ end;
+ if (ref.index<>NR_NO) then
+ begin
+ list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.index,tmpreg));
+ ref.index:=tmpreg;
+ end
+ else
+ begin
+ if ref.base<>NR_NO then
+ ref.index:=tmpreg
+ else
+ ref.base:=tmpreg;
+ end;
+ end;
+ if (ref.base<>NR_NO) then
+ begin
+ if (ref.index<>NR_NO) and
+ ((ref.offset<>0) or assigned(ref.symbol)) then
+ begin
+ if tmpreg=NR_NO then
+ tmpreg:=GetIntRegister(list,OS_INT);
+ list.concat(taicpu.op_reg_reg_reg(A_ADD,ref.base,ref.index,tmpreg));
+ ref.base:=tmpreg;
+ ref.index:=NR_NO;
+ end;
+ end;
+ end;
+
+
+ procedure tcgsparc.handle_load_store(list:TAsmList;isstore:boolean;op: tasmop;reg:tregister;ref: treference);
+ begin
+ make_simple_ref(list,ref);
+ if isstore then
+ list.concat(taicpu.op_reg_ref(op,reg,ref))
+ else
+ list.concat(taicpu.op_ref_reg(op,ref,reg));
+ end;
+
+
+ procedure tcgsparc.handle_reg_const_reg(list:TAsmList;op:Tasmop;src:tregister;a:tcgint;dst:tregister);
+ var
+ tmpreg : tregister;
+ begin
+ if (a<simm13lo) or
+ (a>simm13hi) then
+ begin
+ if g1_used then
+ GetIntRegister(list,OS_INT)
+ else
+ begin
+ tmpreg:=NR_G1;
+ g1_used:=true;
+ end;
+ a_load_const_reg(list,OS_INT,a,tmpreg);
+ list.concat(taicpu.op_reg_reg_reg(op,src,tmpreg,dst));
+ if tmpreg=NR_G1 then
+ g1_used:=false;
+ end
+ else
+ list.concat(taicpu.op_reg_const_reg(op,src,a,dst));
+ end;
+
+
+{****************************************************************************
+ Assembler code
+****************************************************************************}
+
+ procedure Tcgsparc.init_register_allocators;
+ begin
+ inherited init_register_allocators;
+
+ if (cs_create_pic in current_settings.moduleswitches) and
+ (pi_needs_got in current_procinfo.flags) then
+ begin
+ current_procinfo.got:=NR_L7;
+ rg[R_INTREGISTER]:=Trgcpu.create(R_INTREGISTER,R_SUBD,
+ [RS_O0,RS_O1,RS_O2,RS_O3,RS_O4,RS_O5,
+ RS_L0,RS_L1,RS_L2,RS_L3,RS_L4,RS_L5,RS_L6],
+ first_int_imreg,[]);
+ end
+ else
+ rg[R_INTREGISTER]:=Trgcpu.create(R_INTREGISTER,R_SUBD,
+ [RS_O0,RS_O1,RS_O2,RS_O3,RS_O4,RS_O5,
+ RS_L0,RS_L1,RS_L2,RS_L3,RS_L4,RS_L5,RS_L6,RS_L7],
+ first_int_imreg,[]);
+
+ rg[R_FPUREGISTER]:=trgcpu.create(R_FPUREGISTER,R_SUBFS,
+ [RS_F0,RS_F1,RS_F2,RS_F3,RS_F4,RS_F5,RS_F6,RS_F7,
+ RS_F8,RS_F9,RS_F10,RS_F11,RS_F12,RS_F13,RS_F14,RS_F15,
+ RS_F16,RS_F17,RS_F18,RS_F19,RS_F20,RS_F21,RS_F22,RS_F23,
+ RS_F24,RS_F25,RS_F26,RS_F27,RS_F28,RS_F29,RS_F30,RS_F31],
+ first_fpu_imreg,[]);
+ { needs at least one element for rgobj not to crash }
+ rg[R_MMREGISTER]:=trgcpu.create(R_MMREGISTER,R_SUBNONE,
+ [RS_L0],first_mm_imreg,[]);
+ end;
+
+
+ procedure Tcgsparc.done_register_allocators;
+ begin
+ rg[R_INTREGISTER].free;
+ rg[R_FPUREGISTER].free;
+ rg[R_MMREGISTER].free;
+ inherited done_register_allocators;
+ end;
+
+
+ function tcgsparc.getfpuregister(list:TAsmList;size:Tcgsize):Tregister;
+ begin
+ if size=OS_F64 then
+ result:=rg[R_FPUREGISTER].getregister(list,R_SUBFD)
+ else
+ result:=rg[R_FPUREGISTER].getregister(list,R_SUBFS);
+ end;
+
+
+ procedure TCgSparc.a_load_const_cgpara(list:TAsmList;size:tcgsize;a:tcgint;const paraloc:TCGPara);
+ var
+ Ref:TReference;
+ begin
+ paraloc.check_simple_location;
+ paramanager.alloccgpara(list,paraloc);
+ case paraloc.location^.loc of
+ LOC_REGISTER,LOC_CREGISTER:
+ a_load_const_reg(list,size,a,paraloc.location^.register);
+ LOC_REFERENCE:
+ begin
+ { Code conventions need the parameters being allocated in %o6+92 }
+ with paraloc.location^.Reference do
+ begin
+ if (Index=NR_SP) and (Offset<Target_info.first_parm_offset) then
+ InternalError(2002081104);
+ reference_reset_base(ref,index,offset,paraloc.alignment);
+ end;
+ a_load_const_ref(list,size,a,ref);
+ end;
+ else
+ InternalError(2002122200);
+ end;
+ end;
+
+
+ procedure TCgSparc.a_load_ref_cgpara(list:TAsmList;sz:TCgSize;const r:TReference;const paraloc:TCGPara);
+ var
+ ref: treference;
+ tmpreg:TRegister;
+ begin
+ paraloc.check_simple_location;
+ paramanager.alloccgpara(list,paraloc);
+ with paraloc.location^ do
+ begin
+ case loc of
+ LOC_REGISTER,LOC_CREGISTER :
+ a_load_ref_reg(list,sz,paraloc.location^.size,r,Register);
+ LOC_REFERENCE:
+ begin
+ { Code conventions need the parameters being allocated in %o6+92 }
+ with Reference do
+ begin
+ if (Index=NR_SP) and (Offset<Target_info.first_parm_offset) then
+ InternalError(2002081104);
+ reference_reset_base(ref,index,offset,paraloc.alignment);
+ end;
+ if g1_used then
+ GetIntRegister(list,OS_INT)
+ else
+ begin
+ tmpreg:=NR_G1;
+ g1_used:=true;
+ end;
+ a_load_ref_reg(list,sz,sz,r,tmpreg);
+ a_load_reg_ref(list,sz,sz,tmpreg,ref);
+ if tmpreg=NR_G1 then
+ g1_used:=false;
+ end;
+ else
+ internalerror(2002081103);
+ end;
+ end;
+ end;
+
+
+ procedure TCgSparc.a_loadaddr_ref_cgpara(list:TAsmList;const r:TReference;const paraloc:TCGPara);
+ var
+ Ref:TReference;
+ TmpReg:TRegister;
+ begin
+ paraloc.check_simple_location;
+ paramanager.alloccgpara(list,paraloc);
+ with paraloc.location^ do
+ begin
+ case loc of
+ LOC_REGISTER,LOC_CREGISTER:
+ a_loadaddr_ref_reg(list,r,register);
+ LOC_REFERENCE:
+ begin
+ reference_reset(ref,paraloc.alignment);
+ ref.base := reference.index;
+ ref.offset := reference.offset;
+ tmpreg:=GetAddressRegister(list);
+ a_loadaddr_ref_reg(list,r,tmpreg);
+ a_load_reg_ref(list,OS_ADDR,OS_ADDR,tmpreg,ref);
+ end;
+ else
+ internalerror(2002080701);
+ end;
+ end;
+ end;
+
+
+ procedure tcgsparc.a_loadfpu_ref_cgpara(list : TAsmList;size : tcgsize;const ref : treference;const paraloc : TCGPara);
+ var
+ href,href2 : treference;
+ hloc : pcgparalocation;
+ begin
+ href:=ref;
+ hloc:=paraloc.location;
+ while assigned(hloc) do
+ begin
+ paramanager.allocparaloc(list,hloc);
+ case hloc^.loc of
+ LOC_REGISTER,LOC_CREGISTER :
+ a_load_ref_reg(list,hloc^.size,hloc^.size,href,hloc^.register);
+ LOC_REFERENCE :
+ begin
+ reference_reset_base(href2,hloc^.reference.index,hloc^.reference.offset,paraloc.alignment);
+ a_load_ref_ref(list,hloc^.size,hloc^.size,href,href2);
+ end;
+ LOC_FPUREGISTER,LOC_CFPUREGISTER :
+ a_loadfpu_ref_reg(list,hloc^.size,hloc^.size,href,hloc^.register);
+ else
+ internalerror(200408241);
+ end;
+ inc(href.offset,tcgsize2size[hloc^.size]);
+ hloc:=hloc^.next;
+ end;
+ end;
+
+
+ procedure tcgsparc.a_loadfpu_reg_cgpara(list : TAsmList;size : tcgsize;const r : tregister;const paraloc : TCGPara);
+ var
+ href : treference;
+ begin
+ { happens for function result loc }
+ if paraloc.location^.loc in [LOC_FPUREGISTER,LOC_CFPUREGISTER] then
+ begin
+ paraloc.check_simple_location;
+ paramanager.allocparaloc(list,paraloc.location);
+ a_loadfpu_reg_reg(list,size,paraloc.location^.size,r,paraloc.location^.register);
+ end
+ else
+ begin
+ tg.GetTemp(list,TCGSize2Size[size],TCGSize2Size[size],tt_normal,href);
+ a_loadfpu_reg_ref(list,size,size,r,href);
+ a_loadfpu_ref_cgpara(list,size,href,paraloc);
+ tg.Ungettemp(list,href);
+ end;
+ end;
+
+
+ procedure TCgSparc.a_call_name(list:TAsmList;const s:string; weak: boolean);
+ begin
+ if not weak then
+ list.concat(taicpu.op_sym(A_CALL,current_asmdata.RefAsmSymbol(s)))
+ else
+ list.concat(taicpu.op_sym(A_CALL,current_asmdata.WeakRefAsmSymbol(s)));
+ { Delay slot }
+ list.concat(taicpu.op_none(A_NOP));
+ end;
+
+
+ procedure TCgSparc.a_call_reg(list:TAsmList;Reg:TRegister);
+ begin
+ list.concat(taicpu.op_reg(A_CALL,reg));
+ { Delay slot }
+ list.concat(taicpu.op_none(A_NOP));
+ end;
+
+
+ {********************** load instructions ********************}
+
+ procedure TCgSparc.a_load_const_reg(list : TAsmList;size : TCGSize;a : tcgint;reg : TRegister);
+ begin
+ { we don't use the set instruction here because it could be evalutated to two
+ instructions which would cause problems with the delay slot (FK) }
+ if (a=0) then
+ list.concat(taicpu.op_reg(A_CLR,reg))
+ { sethi allows to set the upper 22 bit, so we'll take full advantage of it }
+ else if (aint(a) and aint($1fff))=0 then
+ list.concat(taicpu.op_const_reg(A_SETHI,aint(a) shr 10,reg))
+ else if (a>=simm13lo) and (a<=simm13hi) then
+ list.concat(taicpu.op_const_reg(A_MOV,a,reg))
+ else
+ begin
+ list.concat(taicpu.op_const_reg(A_SETHI,aint(a) shr 10,reg));
+ list.concat(taicpu.op_reg_const_reg(A_OR,reg,aint(a) and aint($3ff),reg));
+ end;
+ end;
+
+
+ procedure TCgSparc.a_load_const_ref(list : TAsmList;size : tcgsize;a : tcgint;const ref : TReference);
+ begin
+ if a=0 then
+ a_load_reg_ref(list,size,size,NR_G0,ref)
+ else
+ inherited a_load_const_ref(list,size,a,ref);
+ end;
+
+
+ procedure TCgSparc.a_load_reg_ref(list:TAsmList;FromSize,ToSize:TCGSize;reg:tregister;const Ref:TReference);
+ var
+ op : tasmop;
+ begin
+ if (TCGSize2Size[fromsize] >= TCGSize2Size[tosize]) then
+ fromsize := tosize;
+ if (ref.alignment<>0) and
+ (ref.alignment<tcgsize2size[tosize]) then
+ begin
+ a_load_reg_ref_unaligned(list,FromSize,ToSize,reg,ref);
+ end
+ else
+ begin
+ case tosize of
+ { signed integer registers }
+ OS_8,
+ OS_S8:
+ Op:=A_STB;
+ OS_16,
+ OS_S16:
+ Op:=A_STH;
+ OS_32,
+ OS_S32:
+ Op:=A_ST;
+ else
+ InternalError(2002122100);
+ end;
+ handle_load_store(list,true,op,reg,ref);
+ end;
+ end;
+
+
+ procedure TCgSparc.a_load_ref_reg(list:TAsmList;FromSize,ToSize:TCgSize;const ref:TReference;reg:tregister);
+ var
+ op : tasmop;
+ begin
+ if (TCGSize2Size[fromsize] >= TCGSize2Size[tosize]) then
+ fromsize := tosize;
+ if (ref.alignment<>0) and
+ (ref.alignment<tcgsize2size[fromsize]) then
+ begin
+ a_load_ref_reg_unaligned(list,FromSize,ToSize,ref,reg);
+ end
+ else
+ begin
+ case fromsize of
+ OS_S8:
+ Op:=A_LDSB;{Load Signed Byte}
+ OS_8:
+ Op:=A_LDUB;{Load Unsigned Byte}
+ OS_S16:
+ Op:=A_LDSH;{Load Signed Halfword}
+ OS_16:
+ Op:=A_LDUH;{Load Unsigned Halfword}
+ OS_S32,
+ OS_32:
+ Op:=A_LD;{Load Word}
+ OS_S64,
+ OS_64:
+ Op:=A_LDD;{Load a Long Word}
+ else
+ InternalError(2002122101);
+ end;
+ handle_load_store(list,false,op,reg,ref);
+ if (fromsize=OS_S8) and
+ (tosize=OS_16) then
+ a_load_reg_reg(list,fromsize,tosize,reg,reg);
+ end;
+ end;
+
+
+ procedure TCgSparc.a_load_reg_reg(list:TAsmList;fromsize,tosize:tcgsize;reg1,reg2:tregister);
+ var
+ instr : taicpu;
+ begin
+ if (tcgsize2size[fromsize] > tcgsize2size[tosize]) or
+ ((tcgsize2size[fromsize] = tcgsize2size[tosize]) and
+ (fromsize <> tosize)) or
+ { needs to mask out the sign in the top 16 bits }
+ ((fromsize = OS_S8) and
+ (tosize = OS_16)) then
+ case tosize of
+ OS_8 :
+ a_op_const_reg_reg(list,OP_AND,tosize,$ff,reg1,reg2);
+ OS_16 :
+ a_op_const_reg_reg(list,OP_AND,tosize,$ffff,reg1,reg2);
+ OS_32,
+ OS_S32 :
+ begin
+ instr:=taicpu.op_reg_reg(A_MOV,reg1,reg2);
+ list.Concat(instr);
+ { Notify the register allocator that we have written a move instruction so
+ it can try to eliminate it. }
+ add_move_instruction(instr);
+ end;
+ OS_S8 :
+ begin
+ list.concat(taicpu.op_reg_const_reg(A_SLL,reg1,24,reg2));
+ list.concat(taicpu.op_reg_const_reg(A_SRA,reg2,24,reg2));
+ end;
+ OS_S16 :
+ begin
+ list.concat(taicpu.op_reg_const_reg(A_SLL,reg1,16,reg2));
+ list.concat(taicpu.op_reg_const_reg(A_SRA,reg2,16,reg2));
+ end;
+ else
+ internalerror(2002090901);
+ end
+ else
+ begin
+ instr:=taicpu.op_reg_reg(A_MOV,reg1,reg2);
+ list.Concat(instr);
+ { Notify the register allocator that we have written a move instruction so
+ it can try to eliminate it. }
+ add_move_instruction(instr);
+ end;
+ end;
+
+
+ procedure TCgSparc.a_loadaddr_ref_reg(list : TAsmList;const ref : TReference;r : tregister);
+ var
+ tmpref,href : treference;
+ hreg,tmpreg : tregister;
+ begin
+ href:=ref;
+ if (href.base=NR_NO) and (href.index<>NR_NO) then
+ internalerror(200306171);
+
+ if (cs_create_pic in current_settings.moduleswitches) and
+ assigned(href.symbol) then
+ begin
+ tmpreg:=GetIntRegister(list,OS_ADDR);
+ reference_reset(tmpref,href.alignment);
+ tmpref.symbol:=href.symbol;
+ tmpref.refaddr:=addr_pic;
+ if not(pi_needs_got in current_procinfo.flags) then
+ internalerror(200501161);
+ tmpref.base:=current_procinfo.got;
+ list.concat(taicpu.op_ref_reg(A_LD,tmpref,tmpreg));
+ href.symbol:=nil;
+ if (href.index<>NR_NO) then
+ begin
+ list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,href.index,tmpreg));
+ href.index:=tmpreg;
+ end
+ else
+ begin
+ if href.base<>NR_NO then
+ href.index:=tmpreg
+ else
+ href.base:=tmpreg;
+ end;
+ end;
+
+ { At least big offset (need SETHI), maybe base and maybe index }
+ if assigned(href.symbol) or
+ (href.offset<simm13lo) or
+ (href.offset>simm13hi) then
+ begin
+ hreg:=GetAddressRegister(list);
+ reference_reset(tmpref,href.alignment);
+ tmpref.symbol := href.symbol;
+ tmpref.offset := href.offset;
+ tmpref.refaddr := addr_high;
+ list.concat(taicpu.op_ref_reg(A_SETHI,tmpref,hreg));
+ { Only the low part is left }
+ tmpref.refaddr:=addr_low;
+ list.concat(taicpu.op_reg_ref_reg(A_OR,hreg,tmpref,hreg));
+ if href.base<>NR_NO then
+ begin
+ if href.index<>NR_NO then
+ begin
+ list.concat(taicpu.op_reg_reg_reg(A_ADD,hreg,href.base,hreg));
+ list.concat(taicpu.op_reg_reg_reg(A_ADD,hreg,href.index,r));
+ end
+ else
+ list.concat(taicpu.op_reg_reg_reg(A_ADD,hreg,href.base,r));
+ end
+ else
+ begin
+ if hreg<>r then
+ a_load_reg_reg(list,OS_ADDR,OS_ADDR,hreg,r);
+ end;
+ end
+ else
+ { At least small offset, maybe base and maybe index }
+ if href.offset<>0 then
+ begin
+ if href.base<>NR_NO then
+ begin
+ if href.index<>NR_NO then
+ begin
+ hreg:=GetAddressRegister(list);
+ list.concat(taicpu.op_reg_const_reg(A_ADD,href.base,href.offset,hreg));
+ list.concat(taicpu.op_reg_reg_reg(A_ADD,hreg,href.index,r));
+ end
+ else
+ list.concat(taicpu.op_reg_const_reg(A_ADD,href.base,href.offset,r));
+ end
+ else
+ list.concat(taicpu.op_const_reg(A_MOV,href.offset,r));
+ end
+ else
+ { Both base and index }
+ if href.index<>NR_NO then
+ list.concat(taicpu.op_reg_reg_reg(A_ADD,href.base,href.index,r))
+ else
+ { Only base }
+ if href.base<>NR_NO then
+ a_load_reg_reg(list,OS_ADDR,OS_ADDR,href.base,r)
+ else
+ { only offset, can be generated by absolute }
+ a_load_const_reg(list,OS_ADDR,href.offset,r);
+ end;
+
+
+ procedure TCgSparc.a_loadfpu_reg_reg(list:TAsmList;fromsize,tosize:tcgsize;reg1, reg2:tregister);
+ const
+ FpuMovInstr : Array[OS_F32..OS_F64,OS_F32..OS_F64] of TAsmOp =
+ ((A_FMOVS,A_FSTOD),(A_FDTOS,A_FMOVD));
+ var
+ op: TAsmOp;
+ instr : taicpu;
+ begin
+ op:=fpumovinstr[fromsize,tosize];
+ instr:=taicpu.op_reg_reg(op,reg1,reg2);
+ list.Concat(instr);
+ { Notify the register allocator that we have written a move instruction so
+ it can try to eliminate it. }
+ if (op = A_FMOVS) or
+ (op = A_FMOVD) then
+ add_move_instruction(instr);
+ end;
+
+
+ procedure TCgSparc.a_loadfpu_ref_reg(list:TAsmList;fromsize,tosize:tcgsize;const ref:TReference;reg:tregister);
+ const
+ FpuLoadInstr : Array[OS_F32..OS_F64] of TAsmOp =
+ (A_LDF,A_LDDF);
+ var
+ tmpreg: tregister;
+ begin
+ if (fromsize<>tosize) then
+ begin
+ tmpreg:=reg;
+ reg:=getfpuregister(list,fromsize);
+ end;
+ handle_load_store(list,false,fpuloadinstr[fromsize],reg,ref);
+ if (fromsize<>tosize) then
+ a_loadfpu_reg_reg(list,fromsize,tosize,reg,tmpreg);
+ end;
+
+
+ procedure TCgSparc.a_loadfpu_reg_ref(list:TAsmList;fromsize,tosize:tcgsize;reg:tregister;const ref:TReference);
+ const
+ FpuLoadInstr : Array[OS_F32..OS_F64] of TAsmOp =
+ (A_STF,A_STDF);
+ var
+ tmpreg: tregister;
+ begin
+ if (fromsize<>tosize) then
+ begin
+ tmpreg:=getfpuregister(list,tosize);
+ a_loadfpu_reg_reg(list,fromsize,tosize,reg,tmpreg);
+ reg:=tmpreg;
+ end;
+ handle_load_store(list,true,fpuloadinstr[tosize],reg,ref);
+ end;
+
+
+ procedure tcgsparc.maybeadjustresult(list: TAsmList; op: TOpCg; size: tcgsize; dst: tregister);
+ const
+ overflowops = [OP_MUL,OP_SHL,OP_ADD,OP_SUB,OP_NOT,OP_NEG];
+ begin
+ if (op in overflowops) and
+ (size in [OS_8,OS_S8,OS_16,OS_S16]) then
+ a_load_reg_reg(list,OS_32,size,dst,dst);
+ end;
+
+
+ procedure TCgSparc.a_op_const_reg(list:TAsmList;Op:TOpCG;size:tcgsize;a:tcgint;reg:TRegister);
+ begin
+ if Op in [OP_NEG,OP_NOT] then
+ internalerror(200306011);
+ if (a=0) then
+ list.concat(taicpu.op_reg_reg_reg(TOpCG2AsmOp[op],reg,NR_G0,reg))
+ else
+ handle_reg_const_reg(list,TOpCG2AsmOp[op],reg,a,reg);
+ maybeadjustresult(list,op,size,reg);
+ end;
+
+
+ procedure TCgSparc.a_op_reg_reg(list:TAsmList;Op:TOpCG;size:TCGSize;src, dst:TRegister);
+ var
+ a : aint;
+ begin
+ Case Op of
+ OP_NEG :
+ list.concat(taicpu.op_reg_reg(TOpCG2AsmOp[op],src,dst));
+ OP_NOT :
+ begin
+ case size of
+ OS_8 :
+ a:=aint($ffffff00);
+ OS_16 :
+ a:=aint($ffff0000);
+ else
+ a:=0;
+ end;
+ handle_reg_const_reg(list,A_XNOR,src,a,dst);
+ end;
+ else
+ list.concat(taicpu.op_reg_reg_reg(TOpCG2AsmOp[op],dst,src,dst));
+ end;
+ maybeadjustresult(list,op,size,dst);
+ end;
+
+
+ procedure TCgSparc.a_op_const_reg_reg(list:TAsmList;op:TOpCg;size:tcgsize;a:tcgint;src, dst:tregister);
+ var
+ power : longInt;
+ begin
+ case op of
+ OP_MUL,
+ OP_IMUL:
+ begin
+ if ispowerof2(a,power) then
+ begin
+ { can be done with a shift }
+ inherited a_op_const_reg_reg(list,op,size,a,src,dst);
+ exit;
+ end;
+ end;
+ OP_SUB,
+ OP_ADD :
+ begin
+ if (a=0) then
+ begin
+ a_load_reg_reg(list,size,size,src,dst);
+ exit;
+ end;
+ end;
+ end;
+ handle_reg_const_reg(list,TOpCG2AsmOp[op],src,a,dst);
+ maybeadjustresult(list,op,size,dst);
+ end;
+
+
+ procedure TCgSparc.a_op_reg_reg_reg(list:TAsmList;op:TOpCg;size:tcgsize;src1, src2, dst:tregister);
+ begin
+ list.concat(taicpu.op_reg_reg_reg(TOpCG2AsmOp[op],src2,src1,dst));
+ maybeadjustresult(list,op,size,dst);
+ end;
+
+
+ procedure tcgsparc.a_op_const_reg_reg_checkoverflow(list: TAsmList; op: TOpCg; size: tcgsize; a: tcgint; src, dst: tregister;setflags : boolean;var ovloc : tlocation);
+ var
+ power : longInt;
+ tmpreg1,tmpreg2 : tregister;
+ begin
+ ovloc.loc:=LOC_VOID;
+ case op of
+ OP_SUB,
+ OP_ADD :
+ begin
+ if (a=0) then
+ begin
+ a_load_reg_reg(list,size,size,src,dst);
+ exit;
+ end;
+ end;
+ end;
+ if setflags then
+ begin
+ handle_reg_const_reg(list,TOpCG2AsmOpWithFlags[op],src,a,dst);
+ case op of
+ OP_MUL:
+ begin
+ tmpreg1:=GetIntRegister(list,OS_INT);
+ list.concat(taicpu.op_reg_reg(A_MOV,NR_Y,tmpreg1));
+ list.concat(taicpu.op_reg_reg(A_CMP,NR_G0,tmpreg1));
+ ovloc.loc:=LOC_FLAGS;
+ ovloc.resflags:=F_NE;
+ end;
+ OP_IMUL:
+ begin
+ tmpreg1:=GetIntRegister(list,OS_INT);
+ tmpreg2:=GetIntRegister(list,OS_INT);
+ list.concat(taicpu.op_reg_reg(A_MOV,NR_Y,tmpreg1));
+ list.concat(taicpu.op_reg_const_reg(A_SRA,dst,31,tmpreg2));
+ list.concat(taicpu.op_reg_reg(A_CMP,tmpreg1,tmpreg2));
+ ovloc.loc:=LOC_FLAGS;
+ ovloc.resflags:=F_NE;
+ end;
+ end;
+ end
+ else
+ handle_reg_const_reg(list,TOpCG2AsmOp[op],src,a,dst);
+ maybeadjustresult(list,op,size,dst);
+ end;
+
+
+ procedure tcgsparc.a_op_reg_reg_reg_checkoverflow(list: TAsmList; op: TOpCg; size: tcgsize; src1, src2, dst: tregister;setflags : boolean;var ovloc : tlocation);
+ var
+ tmpreg1,tmpreg2 : tregister;
+ begin
+ ovloc.loc:=LOC_VOID;
+ if setflags then
+ begin
+ list.concat(taicpu.op_reg_reg_reg(TOpCG2AsmOpWithFlags[op],src2,src1,dst));
+ case op of
+ OP_MUL:
+ begin
+ tmpreg1:=GetIntRegister(list,OS_INT);
+ list.concat(taicpu.op_reg_reg(A_MOV,NR_Y,tmpreg1));
+ list.concat(taicpu.op_reg_reg(A_CMP,NR_G0,tmpreg1));
+ ovloc.loc:=LOC_FLAGS;
+ ovloc.resflags:=F_NE;
+ end;
+ OP_IMUL:
+ begin
+ tmpreg1:=GetIntRegister(list,OS_INT);
+ tmpreg2:=GetIntRegister(list,OS_INT);
+ list.concat(taicpu.op_reg_reg(A_MOV,NR_Y,tmpreg1));
+ list.concat(taicpu.op_reg_const_reg(A_SRL,dst,31,tmpreg2));
+ list.concat(taicpu.op_reg_reg(A_CMP,tmpreg1,tmpreg2));
+ ovloc.loc:=LOC_FLAGS;
+ ovloc.resflags:=F_NE;
+ end;
+ end;
+ end
+ else
+ list.concat(taicpu.op_reg_reg_reg(TOpCG2AsmOp[op],src2,src1,dst));
+ maybeadjustresult(list,op,size,dst);
+ end;
+
+
+
+ {*************** compare instructructions ****************}
+
+ procedure TCgSparc.a_cmp_const_reg_label(list:TAsmList;size:tcgsize;cmp_op:topcmp;a:tcgint;reg:tregister;l:tasmlabel);
+ begin
+ if (a=0) then
+ list.concat(taicpu.op_reg_reg_reg(A_SUBcc,reg,NR_G0,NR_G0))
+ else
+ handle_reg_const_reg(list,A_SUBcc,reg,a,NR_G0);
+ a_jmp_cond(list,cmp_op,l);
+ end;
+
+
+ procedure TCgSparc.a_cmp_reg_reg_label(list:TAsmList;size:tcgsize;cmp_op:topcmp;reg1,reg2:tregister;l:tasmlabel);
+ begin
+ list.concat(taicpu.op_reg_reg_reg(A_SUBcc,reg2,reg1,NR_G0));
+ a_jmp_cond(list,cmp_op,l);
+ end;
+
+
+ procedure TCgSparc.a_jmp_always(List:TAsmList;l:TAsmLabel);
+ begin
+ List.Concat(TAiCpu.op_sym(A_BA,current_asmdata.RefAsmSymbol(l.name)));
+ { Delay slot }
+ list.Concat(TAiCpu.Op_none(A_NOP));
+ end;
+
+
+ procedure tcgsparc.a_jmp_name(list : TAsmList;const s : string);
+ begin
+ List.Concat(TAiCpu.op_sym(A_BA,current_asmdata.RefAsmSymbol(s)));
+ { Delay slot }
+ list.Concat(TAiCpu.Op_none(A_NOP));
+ end;
+
+
+ procedure TCgSparc.a_jmp_cond(list:TAsmList;cond:TOpCmp;l:TAsmLabel);
+ var
+ ai:TAiCpu;
+ begin
+ ai:=TAiCpu.Op_sym(A_Bxx,l);
+ ai.SetCondition(TOpCmp2AsmCond[cond]);
+ list.Concat(ai);
+ { Delay slot }
+ list.Concat(TAiCpu.Op_none(A_NOP));
+ end;
+
+
+ procedure TCgSparc.a_jmp_flags(list:TAsmList;const f:TResFlags;l:tasmlabel);
+ var
+ ai : taicpu;
+ op : tasmop;
+ begin
+ if f in [F_FE,F_FNE,F_FG,F_FL,F_FGE,F_FLE] then
+ op:=A_FBxx
+ else
+ op:=A_Bxx;
+ ai := Taicpu.op_sym(op,l);
+ ai.SetCondition(flags_to_cond(f));
+ list.Concat(ai);
+ { Delay slot }
+ list.Concat(TAiCpu.Op_none(A_NOP));
+ end;
+
+
+ procedure TCgSparc.g_flags2reg(list:TAsmList;Size:TCgSize;const f:tresflags;reg:TRegister);
+ var
+ hl : tasmlabel;
+ begin
+ current_asmdata.getjumplabel(hl);
+ a_load_const_reg(list,size,1,reg);
+ a_jmp_flags(list,f,hl);
+ a_load_const_reg(list,size,0,reg);
+ a_label(list,hl);
+ end;
+
+
+ procedure tcgsparc.g_overflowCheck(List:TAsmList;const Loc:TLocation;def:TDef);
+ var
+ l : tlocation;
+ begin
+ l.loc:=LOC_VOID;
+ g_overflowCheck_loc(list,loc,def,l);
+ end;
+
+
+ procedure TCgSparc.g_overflowCheck_loc(List:TAsmList;const Loc:TLocation;def:TDef;ovloc : tlocation);
+ var
+ hl : tasmlabel;
+ ai:TAiCpu;
+ hflags : tresflags;
+ begin
+ if not(cs_check_overflow in current_settings.localswitches) then
+ exit;
+ current_asmdata.getjumplabel(hl);
+ case ovloc.loc of
+ LOC_VOID:
+ begin
+ if not((def.typ=pointerdef) or
+ ((def.typ=orddef) and
+ (torddef(def).ordtype in [u64bit,u16bit,u32bit,u8bit,uchar,
+ pasbool8,pasbool16,pasbool32,pasbool64]))) then
+ begin
+ ai:=TAiCpu.Op_sym(A_Bxx,hl);
+ ai.SetCondition(C_NO);
+ list.Concat(ai);
+ { Delay slot }
+ list.Concat(TAiCpu.Op_none(A_NOP));
+ end
+ else
+ a_jmp_cond(list,OC_AE,hl);
+ end;
+ LOC_FLAGS:
+ begin
+ hflags:=ovloc.resflags;
+ inverse_flags(hflags);
+ cg.a_jmp_flags(list,hflags,hl);
+ end;
+ else
+ internalerror(200409281);
+ end;
+
+ a_call_name(list,'FPC_OVERFLOW',false);
+ a_label(list,hl);
+ end;
+
+ { *********** entry/exit code and address loading ************ }
+
+ procedure TCgSparc.g_proc_entry(list : TAsmList;localsize : longint;nostackframe:boolean);
+ begin
+ if nostackframe then
+ exit;
+ { Althogh the SPARC architecture require only word alignment, software
+ convention and the operating system require every stack frame to be double word
+ aligned }
+ LocalSize:=align(LocalSize,8);
+ { Execute the SAVE instruction to get a new register window and create a new
+ stack frame. In the "SAVE %i6,size,%i6" the first %i6 is related to the state
+ before execution of the SAVE instrucion so it is the caller %i6, when the %i6
+ after execution of that instruction is the called function stack pointer}
+ { constant can be 13 bit signed, since it's negative, size can be max. 4096 }
+ if LocalSize>4096 then
+ begin
+ a_load_const_reg(list,OS_ADDR,-LocalSize,NR_G1);
+ g1_used:=true;
+ list.concat(Taicpu.Op_reg_reg_reg(A_SAVE,NR_STACK_POINTER_REG,NR_G1,NR_STACK_POINTER_REG));
+ g1_used:=false;
+ end
+ else
+ list.concat(Taicpu.Op_reg_const_reg(A_SAVE,NR_STACK_POINTER_REG,-LocalSize,NR_STACK_POINTER_REG));
+ if (cs_create_pic in current_settings.moduleswitches) and
+ (pi_needs_got in current_procinfo.flags) then
+ begin
+ current_procinfo.got:=NR_L7;
+ end;
+ end;
+
+
+ procedure TCgSparc.g_restore_registers(list:TAsmList);
+ begin
+ { The sparc port uses the sparc standard calling convetions so this function has no used }
+ end;
+
+
+ procedure TCgSparc.g_proc_exit(list : TAsmList;parasize:longint;nostackframe:boolean);
+ var
+ hr : treference;
+ begin
+ if paramanager.ret_in_param(current_procinfo.procdef.returndef,current_procinfo.procdef.proccalloption) then
+ begin
+ reference_reset(hr,sizeof(pint));
+ hr.offset:=12;
+ hr.refaddr:=addr_full;
+ if nostackframe then
+ begin
+ hr.base:=NR_O7;
+ list.concat(taicpu.op_ref_reg(A_JMPL,hr,NR_G0));
+ list.concat(Taicpu.op_none(A_NOP))
+ end
+ else
+ begin
+ { We use trivial restore in the delay slot of the JMPL instruction, as we
+ already set result onto %i0 }
+ hr.base:=NR_I7;
+ list.concat(taicpu.op_ref_reg(A_JMPL,hr,NR_G0));
+ list.concat(Taicpu.op_none(A_RESTORE));
+ end;
+ end
+ else
+ begin
+ if nostackframe then
+ begin
+ { Here we need to use RETL instead of RET so it uses %o7 }
+ list.concat(Taicpu.op_none(A_RETL));
+ list.concat(Taicpu.op_none(A_NOP))
+ end
+ else
+ begin
+ { We use trivial restore in the delay slot of the JMPL instruction, as we
+ already set result onto %i0 }
+ list.concat(Taicpu.op_none(A_RET));
+ list.concat(Taicpu.op_none(A_RESTORE));
+ end;
+ end;
+ end;
+
+
+ procedure TCgSparc.g_save_registers(list : TAsmList);
+ begin
+ { The sparc port uses the sparc standard calling convetions so this function has no used }
+ end;
+
+
+ { ************* concatcopy ************ }
+
+ procedure tcgsparc.g_concatcopy_move(list : TAsmList;const source,dest : treference;len : tcgint);
+ var
+ paraloc1,paraloc2,paraloc3 : TCGPara;
+ begin
+ paraloc1.init;
+ paraloc2.init;
+ paraloc3.init;
+ paramanager.getintparaloc(pocall_default,1,paraloc1);
+ paramanager.getintparaloc(pocall_default,2,paraloc2);
+ paramanager.getintparaloc(pocall_default,3,paraloc3);
+ a_load_const_cgpara(list,OS_INT,len,paraloc3);
+ a_loadaddr_ref_cgpara(list,dest,paraloc2);
+ a_loadaddr_ref_cgpara(list,source,paraloc1);
+ paramanager.freecgpara(list,paraloc3);
+ paramanager.freecgpara(list,paraloc2);
+ paramanager.freecgpara(list,paraloc1);
+ alloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
+ alloccpuregisters(list,R_FPUREGISTER,paramanager.get_volatile_registers_fpu(pocall_default));
+ a_call_name(list,'FPC_MOVE',false);
+ dealloccpuregisters(list,R_FPUREGISTER,paramanager.get_volatile_registers_fpu(pocall_default));
+ dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
+ paraloc3.done;
+ paraloc2.done;
+ paraloc1.done;
+ end;
+
+
+ procedure TCgSparc.g_concatcopy(list:TAsmList;const source,dest:treference;len:tcgint);
+ var
+ tmpreg1,
+ hreg,
+ countreg: TRegister;
+ src, dst: TReference;
+ lab: tasmlabel;
+ count, count2: aint;
+ begin
+ if len>high(longint) then
+ internalerror(2002072704);
+ { anybody wants to determine a good value here :)? }
+ if len>100 then
+ g_concatcopy_move(list,source,dest,len)
+ else
+ begin
+ reference_reset(src,source.alignment);
+ reference_reset(dst,dest.alignment);
+ { load the address of source into src.base }
+ src.base:=GetAddressRegister(list);
+ a_loadaddr_ref_reg(list,source,src.base);
+ { load the address of dest into dst.base }
+ dst.base:=GetAddressRegister(list);
+ a_loadaddr_ref_reg(list,dest,dst.base);
+ { generate a loop }
+ count:=len div 4;
+ if count>4 then
+ begin
+ { the offsets are zero after the a_loadaddress_ref_reg and just }
+ { have to be set to 8. I put an Inc there so debugging may be }
+ { easier (should offset be different from zero here, it will be }
+ { easy to notice in the generated assembler }
+ countreg:=GetIntRegister(list,OS_INT);
+ tmpreg1:=GetIntRegister(list,OS_INT);
+ a_load_const_reg(list,OS_INT,count,countreg);
+ { explicitely allocate R_O0 since it can be used safely here }
+ { (for holding date that's being copied) }
+ current_asmdata.getjumplabel(lab);
+ a_label(list, lab);
+ list.concat(taicpu.op_ref_reg(A_LD,src,tmpreg1));
+ list.concat(taicpu.op_reg_ref(A_ST,tmpreg1,dst));
+ list.concat(taicpu.op_reg_const_reg(A_ADD,src.base,4,src.base));
+ list.concat(taicpu.op_reg_const_reg(A_ADD,dst.base,4,dst.base));
+ list.concat(taicpu.op_reg_const_reg(A_SUBcc,countreg,1,countreg));
+ a_jmp_cond(list,OC_NE,lab);
+ list.concat(taicpu.op_none(A_NOP));
+ { keep the registers alive }
+ list.concat(taicpu.op_reg_reg(A_MOV,countreg,countreg));
+ list.concat(taicpu.op_reg_reg(A_MOV,src.base,src.base));
+ list.concat(taicpu.op_reg_reg(A_MOV,dst.base,dst.base));
+ len := len mod 4;
+ end;
+ { unrolled loop }
+ count:=len div 4;
+ if count>0 then
+ begin
+ tmpreg1:=GetIntRegister(list,OS_INT);
+ for count2 := 1 to count do
+ begin
+ list.concat(taicpu.op_ref_reg(A_LD,src,tmpreg1));
+ list.concat(taicpu.op_reg_ref(A_ST,tmpreg1,dst));
+ inc(src.offset,4);
+ inc(dst.offset,4);
+ end;
+ len := len mod 4;
+ end;
+ if (len and 4) <> 0 then
+ begin
+ hreg:=GetIntRegister(list,OS_INT);
+ a_load_ref_reg(list,OS_32,OS_32,src,hreg);
+ a_load_reg_ref(list,OS_32,OS_32,hreg,dst);
+ inc(src.offset,4);
+ inc(dst.offset,4);
+ end;
+ { copy the leftovers }
+ if (len and 2) <> 0 then
+ begin
+ hreg:=GetIntRegister(list,OS_INT);
+ a_load_ref_reg(list,OS_16,OS_16,src,hreg);
+ a_load_reg_ref(list,OS_16,OS_16,hreg,dst);
+ inc(src.offset,2);
+ inc(dst.offset,2);
+ end;
+ if (len and 1) <> 0 then
+ begin
+ hreg:=GetIntRegister(list,OS_INT);
+ a_load_ref_reg(list,OS_8,OS_8,src,hreg);
+ a_load_reg_ref(list,OS_8,OS_8,hreg,dst);
+ end;
+ end;
+ end;
+
+
+ procedure tcgsparc.g_concatcopy_unaligned(list : TAsmList;const source,dest : treference;len : tcgint);
+ var
+ src, dst: TReference;
+ tmpreg1,
+ countreg: TRegister;
+ i : aint;
+ lab: tasmlabel;
+ begin
+ if len>31 then
+ g_concatcopy_move(list,source,dest,len)
+ else
+ begin
+ reference_reset(src,source.alignment);
+ reference_reset(dst,dest.alignment);
+ { load the address of source into src.base }
+ src.base:=GetAddressRegister(list);
+ a_loadaddr_ref_reg(list,source,src.base);
+ { load the address of dest into dst.base }
+ dst.base:=GetAddressRegister(list);
+ a_loadaddr_ref_reg(list,dest,dst.base);
+ { generate a loop }
+ if len>4 then
+ begin
+ { the offsets are zero after the a_loadaddress_ref_reg and just }
+ { have to be set to 8. I put an Inc there so debugging may be }
+ { easier (should offset be different from zero here, it will be }
+ { easy to notice in the generated assembler }
+ countreg:=GetIntRegister(list,OS_INT);
+ tmpreg1:=GetIntRegister(list,OS_INT);
+ a_load_const_reg(list,OS_INT,len,countreg);
+ { explicitely allocate R_O0 since it can be used safely here }
+ { (for holding date that's being copied) }
+ current_asmdata.getjumplabel(lab);
+ a_label(list, lab);
+ list.concat(taicpu.op_ref_reg(A_LDUB,src,tmpreg1));
+ list.concat(taicpu.op_reg_ref(A_STB,tmpreg1,dst));
+ list.concat(taicpu.op_reg_const_reg(A_ADD,src.base,1,src.base));
+ list.concat(taicpu.op_reg_const_reg(A_ADD,dst.base,1,dst.base));
+ list.concat(taicpu.op_reg_const_reg(A_SUBcc,countreg,1,countreg));
+ a_jmp_cond(list,OC_NE,lab);
+ list.concat(taicpu.op_none(A_NOP));
+ { keep the registers alive }
+ list.concat(taicpu.op_reg_reg(A_MOV,countreg,countreg));
+ list.concat(taicpu.op_reg_reg(A_MOV,src.base,src.base));
+ list.concat(taicpu.op_reg_reg(A_MOV,dst.base,dst.base));
+ end
+ else
+ begin
+ { unrolled loop }
+ tmpreg1:=GetIntRegister(list,OS_INT);
+ for i:=1 to len do
+ begin
+ list.concat(taicpu.op_ref_reg(A_LDUB,src,tmpreg1));
+ list.concat(taicpu.op_reg_ref(A_STB,tmpreg1,dst));
+ inc(src.offset);
+ inc(dst.offset);
+ end;
+ end;
+ end;
+ end;
+
+
+ procedure tcgsparc.g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);
+ var
+ make_global : boolean;
+ href : treference;
+ begin
+ if not(procdef.proctypeoption in [potype_function,potype_procedure]) then
+ Internalerror(200006137);
+ if not assigned(procdef.struct) or
+ (procdef.procoptions*[po_classmethod, po_staticmethod,
+ po_methodpointer, po_interrupt, po_iocheck]<>[]) then
+ Internalerror(200006138);
+ if procdef.owner.symtabletype<>ObjectSymtable then
+ Internalerror(200109191);
+
+ make_global:=false;
+ if (not current_module.is_unit) or create_smartlink or
+ (procdef.owner.defowner.owner.symtabletype=globalsymtable) then
+ make_global:=true;
+
+ if make_global then
+ List.concat(Tai_symbol.Createname_global(labelname,AT_FUNCTION,0))
+ else
+ List.concat(Tai_symbol.Createname(labelname,AT_FUNCTION,0));
+
+ { set param1 interface to self }
+ g_adjust_self_value(list,procdef,ioffset);
+
+ if (po_virtualmethod in procdef.procoptions) and
+ not is_objectpascal_helper(procdef.struct) then
+ begin
+ if (procdef.extnumber=$ffff) then
+ Internalerror(200006139);
+ { mov 0(%rdi),%rax ; load vmt}
+ reference_reset_base(href,NR_O0,0,sizeof(pint));
+ cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_G1);
+ g1_used:=true;
+ { jmp *vmtoffs(%eax) ; method offs }
+ reference_reset_base(href,NR_G1,tobjectdef(procdef.struct).vmtmethodoffset(procdef.extnumber),sizeof(pint));
+ list.concat(taicpu.op_ref_reg(A_LD,href,NR_G1));
+ list.concat(taicpu.op_reg(A_JMP,NR_G1));
+ g1_used:=false;
+ end
+ else
+ begin
+ reference_reset_symbol(href,current_asmdata.RefAsmSymbol(procdef.mangledname),0,sizeof(pint));
+ href.refaddr := addr_high;
+ list.concat(taicpu.op_ref_reg(A_SETHI,href,NR_G1));
+ g1_used:=true;
+ href.refaddr := addr_low;
+ list.concat(taicpu.op_reg_ref_reg(A_OR,NR_G1,href,NR_G1));
+ list.concat(taicpu.op_reg(A_JMP,NR_G1));
+ g1_used:=false;
+ end;
+ { Delay slot }
+ list.Concat(TAiCpu.Op_none(A_NOP));
+
+ List.concat(Tai_symbol_end.Createname(labelname));
+ end;
+
+ procedure tcgsparc.g_stackpointer_alloc(list : TAsmList;localsize : longint);
+ begin
+ Comment(V_Error,'tcgsparc.g_stackpointer_alloc method not implemented');
+ end;
+
+ procedure tcgsparc.a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; size: TCGSize; src, dst: TRegister);
+ begin
+ Comment(V_Error,'tcgsparc.a_bit_scan_reg_reg method not implemented');
+ end;
+
+{****************************************************************************
+ TCG64Sparc
+****************************************************************************}
+
+
+ procedure tcg64sparc.a_load64_reg_ref(list : TAsmList;reg : tregister64;const ref : treference);
+ var
+ tmpref: treference;
+ begin
+ { Override this function to prevent loading the reference twice }
+ tmpref:=ref;
+ cg.a_load_reg_ref(list,OS_32,OS_32,reg.reghi,tmpref);
+ inc(tmpref.offset,4);
+ cg.a_load_reg_ref(list,OS_32,OS_32,reg.reglo,tmpref);
+ end;
+
+
+ procedure tcg64sparc.a_load64_ref_reg(list : TAsmList;const ref : treference;reg : tregister64);
+ var
+ tmpref: treference;
+ begin
+ { Override this function to prevent loading the reference twice }
+ tmpref:=ref;
+ cg.a_load_ref_reg(list,OS_32,OS_32,tmpref,reg.reghi);
+ inc(tmpref.offset,4);
+ cg.a_load_ref_reg(list,OS_32,OS_32,tmpref,reg.reglo);
+ end;
+
+
+ procedure tcg64sparc.a_load64_ref_cgpara(list : TAsmList;const r : treference;const paraloc : tcgpara);
+ var
+ hreg64 : tregister64;
+ begin
+ { Override this function to prevent loading the reference twice.
+ Use here some extra registers, but those are optimized away by the RA }
+ hreg64.reglo:=cg.GetIntRegister(list,OS_32);
+ hreg64.reghi:=cg.GetIntRegister(list,OS_32);
+ a_load64_ref_reg(list,r,hreg64);
+ a_load64_reg_cgpara(list,hreg64,paraloc);
+ end;
+
+
+ procedure TCg64Sparc.get_64bit_ops(op:TOpCG;var op1,op2:TAsmOp;checkoverflow : boolean);
+ begin
+ case op of
+ OP_ADD :
+ begin
+ op1:=A_ADDCC;
+ if checkoverflow then
+ op2:=A_ADDXCC
+ else
+ op2:=A_ADDX;
+ end;
+ OP_SUB :
+ begin
+ op1:=A_SUBCC;
+ if checkoverflow then
+ op2:=A_SUBXCC
+ else
+ op2:=A_SUBX;
+ end;
+ OP_XOR :
+ begin
+ op1:=A_XOR;
+ op2:=A_XOR;
+ end;
+ OP_OR :
+ begin
+ op1:=A_OR;
+ op2:=A_OR;
+ end;
+ OP_AND :
+ begin
+ op1:=A_AND;
+ op2:=A_AND;
+ end;
+ else
+ internalerror(200203241);
+ end;
+ end;
+
+
+ procedure TCg64Sparc.a_op64_reg_reg(list:TAsmList;op:TOpCG;size : tcgsize;regsrc,regdst:TRegister64);
+ var
+ op1,op2 : TAsmOp;
+ begin
+ case op of
+ OP_NEG :
+ begin
+ { Use the simple code: y=0-z }
+ list.concat(taicpu.op_reg_reg_reg(A_SUBcc,NR_G0,regsrc.reglo,regdst.reglo));
+ list.concat(taicpu.op_reg_reg_reg(A_SUBX,NR_G0,regsrc.reghi,regdst.reghi));
+ exit;
+ end;
+ OP_NOT :
+ begin
+ list.concat(taicpu.op_reg_reg_reg(A_XNOR,regsrc.reglo,NR_G0,regdst.reglo));
+ list.concat(taicpu.op_reg_reg_reg(A_XNOR,regsrc.reghi,NR_G0,regdst.reghi));
+ exit;
+ end;
+ end;
+ get_64bit_ops(op,op1,op2,false);
+ list.concat(taicpu.op_reg_reg_reg(op1,regdst.reglo,regsrc.reglo,regdst.reglo));
+ list.concat(taicpu.op_reg_reg_reg(op2,regdst.reghi,regsrc.reghi,regdst.reghi));
+ end;
+
+
+ procedure TCg64Sparc.a_op64_const_reg(list:TAsmList;op:TOpCG;size : tcgsize;value:int64;regdst:TRegister64);
+ var
+ op1,op2:TAsmOp;
+ begin
+ case op of
+ OP_NEG,
+ OP_NOT :
+ internalerror(200306017);
+ end;
+ get_64bit_ops(op,op1,op2,false);
+ tcgsparc(cg).handle_reg_const_reg(list,op1,regdst.reglo,tcgint(lo(value)),regdst.reglo);
+ tcgsparc(cg).handle_reg_const_reg(list,op2,regdst.reghi,tcgint(hi(value)),regdst.reghi);
+ end;
+
+
+ procedure tcg64sparc.a_op64_const_reg_reg(list: TAsmList;op:TOpCG;size : tcgsize;value : int64; regsrc,regdst : tregister64);
+ var
+ l : tlocation;
+ begin
+ a_op64_const_reg_reg_checkoverflow(list,op,size,value,regsrc,regdst,false,l);
+ end;
+
+
+ procedure tcg64sparc.a_op64_reg_reg_reg(list: TAsmList;op:TOpCG;size : tcgsize;regsrc1,regsrc2,regdst : tregister64);
+ var
+ l : tlocation;
+ begin
+ a_op64_reg_reg_reg_checkoverflow(list,op,size,regsrc1,regsrc2,regdst,false,l);
+ end;
+
+
+ procedure tcg64sparc.a_op64_const_reg_reg_checkoverflow(list: TAsmList;op:TOpCG;size : tcgsize;value : int64;regsrc,regdst : tregister64;setflags : boolean;var ovloc : tlocation);
+ var
+ op1,op2:TAsmOp;
+ begin
+ case op of
+ OP_NEG,
+ OP_NOT :
+ internalerror(200306017);
+ end;
+ get_64bit_ops(op,op1,op2,setflags);
+ tcgsparc(cg).handle_reg_const_reg(list,op1,regsrc.reglo,tcgint(lo(value)),regdst.reglo);
+ tcgsparc(cg).handle_reg_const_reg(list,op2,regsrc.reghi,tcgint(hi(value)),regdst.reghi);
+ end;
+
+
+ procedure tcg64sparc.a_op64_reg_reg_reg_checkoverflow(list: TAsmList;op:TOpCG;size : tcgsize;regsrc1,regsrc2,regdst : tregister64;setflags : boolean;var ovloc : tlocation);
+ var
+ op1,op2:TAsmOp;
+ begin
+ case op of
+ OP_NEG,
+ OP_NOT :
+ internalerror(200306017);
+ end;
+ get_64bit_ops(op,op1,op2,setflags);
+ list.concat(taicpu.op_reg_reg_reg(op1,regsrc2.reglo,regsrc1.reglo,regdst.reglo));
+ list.concat(taicpu.op_reg_reg_reg(op2,regsrc2.reghi,regsrc1.reghi,regdst.reghi));
+ end;
+
+
+ procedure create_codegen;
+ begin
+ cg:=TCgSparc.Create;
+ cg64:=TCg64Sparc.Create;
+ end;
+
+end.
diff --git a/closures/compiler/sparc/cpubase.pas b/closures/compiler/sparc/cpubase.pas
new file mode 100644
index 0000000000..0e658ed74b
--- /dev/null
+++ b/closures/compiler/sparc/cpubase.pas
@@ -0,0 +1,455 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Contains the base types for the SPARC
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit cpubase;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ globtype,strings,cutils,cclasses,aasmbase,cpuinfo,cgbase;
+
+
+{*****************************************************************************
+ Assembler Opcodes
+*****************************************************************************}
+
+ type
+{ TODO: CPU32 opcodes do not fully include the Ultra SPRAC instruction set.}
+ { don't change the order of these opcodes! }
+ TAsmOp=({$i opcode.inc});
+
+ {# This should define the array of instructions as string }
+ op2strtable=array[tasmop] of string[11];
+
+ Const
+ {# First value of opcode enumeration }
+ firstop = low(tasmop);
+ {# Last value of opcode enumeration }
+ lastop = high(tasmop);
+
+ std_op2str:op2strtable=({$i strinst.inc});
+
+{*****************************************************************************
+ Registers
+*****************************************************************************}
+
+ type
+ { Number of registers used for indexing in tables }
+ tregisterindex=0..{$i rspnor.inc}-1;
+ totherregisterset = set of tregisterindex;
+
+ const
+ { Available Superregisters }
+ {$i rspsup.inc}
+
+ { No Subregisters }
+ R_SUBWHOLE = R_SUBD;
+
+ { Available Registers }
+ {$i rspcon.inc}
+
+ first_int_imreg = $20;
+ first_fpu_imreg = $20;
+
+ { MM Super register first and last }
+ first_mm_supreg = 0;
+ first_mm_imreg = 1;
+
+{ TODO: Calculate bsstart}
+ regnumber_count_bsstart = 128;
+
+ regnumber_table : array[tregisterindex] of tregister = (
+ {$i rspnum.inc}
+ );
+
+ regstabs_table : array[tregisterindex] of ShortInt = (
+ {$i rspstab.inc}
+ );
+
+ regdwarf_table : array[tregisterindex] of ShortInt = (
+ {$i rspdwrf.inc}
+ );
+
+
+{*****************************************************************************
+ Conditions
+*****************************************************************************}
+
+ type
+ TAsmCond=(C_None,
+ C_A,C_AE,C_B,C_BE,C_C,C_E,C_G,C_GE,C_L,C_LE,C_NA,C_NAE,
+ C_NB,C_NBE,C_NC,C_NE,C_NG,C_NGE,C_NL,C_NLE,C_NO,C_NP,
+ C_NS,C_NZ,C_O,C_P,C_PE,C_PO,C_S,C_Z,
+ C_FE,C_FG,C_FL,C_FGE,C_FLE,C_FNE
+ );
+
+ const
+ cond2str:array[TAsmCond] of string[3]=('',
+ 'gu','cc','cs','leu','cs','e','g','ge','l','le','leu','cs',
+ 'cc','gu','cc','ne','le','l','ge','g','vc','XX',
+ 'pos','ne','vs','XX','XX','XX','vs','e',
+ 'e','g','l','ge','le','ne'
+ );
+
+ const
+ CondAsmOps=2;
+ CondAsmOp:array[0..CondAsmOps-1] of TAsmOp=(
+ A_Bxx,A_FBxx
+ );
+ CondAsmOpStr:array[0..CondAsmOps-1] of string[7]=(
+ 'B','FB'
+ );
+
+
+{*****************************************************************************
+ Flags
+*****************************************************************************}
+
+ type
+ TResFlags=(
+ { Integer results }
+ F_E, {Equal}
+ F_NE, {Not Equal}
+ F_G, {Greater}
+ F_L, {Less}
+ F_GE, {Greater or Equal}
+ F_LE, {Less or Equal}
+ F_A, {Above}
+ F_AE, {Above or Equal}
+ F_B, {Below}
+ F_BE, {Below or Equal}
+ F_C, {Carry}
+ F_NC, {Not Carry}
+ { Floating point results }
+ F_FE, {Equal}
+ F_FNE, {Not Equal}
+ F_FG, {Greater}
+ F_FL, {Less}
+ F_FGE, {Greater or Equal}
+ F_FLE {Less or Equal}
+ );
+
+{*****************************************************************************
+ Operand Sizes
+*****************************************************************************}
+
+
+{*****************************************************************************
+ Constants
+*****************************************************************************}
+
+ const
+ max_operands = 3;
+
+ maxintregs = 8;
+ maxfpuregs = 8;
+ maxaddrregs = 0;
+
+ maxvarregs = 8;
+ varregs : Array [1..maxvarregs] of Tsuperregister =
+ (RS_L0,RS_L1,RS_L2,RS_L3,RS_L4,RS_L5,RS_L6,RS_L7);
+
+ maxfpuvarregs = 1;
+ fpuvarregs : Array [1..maxfpuvarregs] of TsuperRegister =
+ (RS_F2);
+
+
+
+{*****************************************************************************
+ Default generic sizes
+*****************************************************************************}
+
+ {# Defines the default address size for a processor, }
+ OS_ADDR = OS_32;
+ {# the natural int size for a processor, }
+ OS_INT = OS_32;
+ OS_SINT = OS_S32;
+ {# the maximum float size for a processor, }
+ OS_FLOAT = OS_F64;
+ {# the size of a vector register for a processor }
+ OS_VECTOR = OS_M64;
+
+{*****************************************************************************
+ Generic Register names
+*****************************************************************************}
+
+ {# Stack pointer register }
+ NR_STACK_POINTER_REG = NR_O6;
+ RS_STACK_POINTER_REG = RS_O6;
+ {# Frame pointer register }
+ NR_FRAME_POINTER_REG = NR_I6;
+ RS_FRAME_POINTER_REG = RS_I6;
+ {# Register for addressing absolute data in a position independant way,
+ such as in PIC code. The exact meaning is ABI specific. For
+ further information look at GCC source : PIC_OFFSET_TABLE_REGNUM
+
+ Taken from GCC rs6000.h
+ }
+{ TODO: As indicated in rs6000.h, but can't find it anywhere else!}
+ {PIC_OFFSET_REG = R_30;}
+ { Return address for DWARF }
+ NR_RETURN_ADDRESS_REG = NR_I7;
+ { the return_result_reg, is used inside the called function to store its return
+ value when that is a scalar value otherwise a pointer to the address of the
+ result is placed inside it }
+ { Results are returned in this register (32-bit values) }
+ NR_FUNCTION_RETURN_REG = NR_I0;
+ RS_FUNCTION_RETURN_REG = RS_I0;
+ { Low part of 64bit return value }
+ NR_FUNCTION_RETURN64_LOW_REG = NR_I1;
+ RS_FUNCTION_RETURN64_LOW_REG = RS_I1;
+ { High part of 64bit return value }
+ NR_FUNCTION_RETURN64_HIGH_REG = NR_I0;
+ RS_FUNCTION_RETURN64_HIGH_REG = RS_I0;
+ { The value returned from a function is available in this register }
+ NR_FUNCTION_RESULT_REG = NR_O0;
+ RS_FUNCTION_RESULT_REG = RS_O0;
+ { The lowh part of 64bit value returned from a function }
+ NR_FUNCTION_RESULT64_LOW_REG = NR_O1;
+ RS_FUNCTION_RESULT64_LOW_REG = RS_O1;
+ { The high part of 64bit value returned from a function }
+ NR_FUNCTION_RESULT64_HIGH_REG = NR_O0;
+ RS_FUNCTION_RESULT64_HIGH_REG = RS_O0;
+
+ NR_FPU_RESULT_REG = NR_F0;
+ NR_MM_RESULT_REG = NR_NO;
+
+ PARENT_FRAMEPOINTER_OFFSET = 68; { o0 }
+
+
+{*****************************************************************************
+ GCC /ABI linking information
+*****************************************************************************}
+
+ {# Registers which must be saved when calling a routine declared as
+ cppdecl, cdecl, stdcall, safecall, palmossyscall. The registers
+ saved should be the ones as defined in the target ABI and / or GCC.
+
+ This value can be deduced from CALLED_USED_REGISTERS array in the
+ GCC source.
+ }
+ saved_standard_registers : array[0..0] of tsuperregister = (RS_NO);
+
+ { this is only for the generic code which is not used for this architecture }
+ saved_mm_registers : array[0..0] of tsuperregister = (RS_NO);
+
+ {# Required parameter alignment when calling a routine declared as
+ stdcall and cdecl. The alignment value should be the one defined
+ by GCC or the target ABI.
+
+ The value of this constant is equal to the constant
+ PARM_BOUNDARY / BITS_PER_UNIT in the GCC source.
+ }
+ std_param_align = 4; { for 32-bit version only }
+
+
+{*****************************************************************************
+ CPU Dependent Constants
+*****************************************************************************}
+
+ const
+ simm13lo=-4096;
+ simm13hi=4095;
+
+{*****************************************************************************
+ Helpers
+*****************************************************************************}
+
+ function is_calljmp(o:tasmop):boolean;
+
+ procedure inverse_flags(var f: TResFlags);
+ function inverse_cond(const c: TAsmCond): TAsmCond; {$ifdef USEINLINE}inline;{$endif USEINLINE}
+ function conditions_equal(const c1, c2: TAsmCond): boolean; {$ifdef USEINLINE}inline;{$endif USEINLINE}
+
+ function flags_to_cond(const f: TResFlags) : TAsmCond;
+ function cgsize2subreg(regtype: tregistertype; s:Tcgsize):Tsubregister;
+ function reg_cgsize(const reg: tregister): tcgsize;
+ function std_regname(r:Tregister):string;
+ function std_regnum_search(const s:string):Tregister;
+ function findreg_by_number(r:Tregister):tregisterindex;
+ function dwarf_reg(r:tregister):shortint;
+
+
+implementation
+
+ uses
+ rgBase,verbose;
+
+ const
+ std_regname_table : TRegNameTAble = (
+ {$i rspstd.inc}
+ );
+
+ regnumber_index : TRegisterIndexTable = (
+ {$i rsprni.inc}
+ );
+
+ std_regname_index : TRegisterIndexTable = (
+ {$i rspsri.inc}
+ );
+
+
+{*****************************************************************************
+ Helpers
+*****************************************************************************}
+
+ function is_calljmp(o:tasmop):boolean;
+ const
+ CallJmpOp=[A_JMPL..A_CBccc];
+ begin
+ is_calljmp:=(o in CallJmpOp);
+ end;
+
+
+ procedure inverse_flags(var f: TResFlags);
+ const
+ inv_flags: array[TResFlags] of TResFlags =
+ (F_NE,F_E,F_LE,F_GE,F_L,F_G,F_BE,F_B,F_AE,F_A,F_NC,F_C,
+ F_FNE,F_FE,F_FLE,F_FGE,F_FL,F_FG);
+ begin
+ f:=inv_flags[f];
+ end;
+
+
+ function flags_to_cond(const f:TResFlags):TAsmCond;
+ const
+ flags_2_cond:array[TResFlags] of TAsmCond=
+ (C_E,C_NE,C_G,C_L,C_GE,C_LE,C_A,C_AE,C_B,C_BE,C_C,C_NC,
+ C_FE,C_FNE,C_FG,C_FL,C_FGE,C_FLE);
+ begin
+ result:=flags_2_cond[f];
+ end;
+
+
+ function cgsize2subreg(regtype: tregistertype; s:Tcgsize):Tsubregister;
+ begin
+ case regtype of
+ R_FPUREGISTER:
+ case s of
+ OS_F32:
+ cgsize2subreg:=R_SUBFS;
+ OS_F64:
+ cgsize2subreg:=R_SUBFD;
+ OS_F128:
+ cgsize2subreg:=R_SUBFQ;
+ else
+ internalerror(2009071903);
+ end;
+ else
+ begin
+ if s in [OS_64,OS_S64] then
+ cgsize2subreg:=R_SUBQ
+ else
+ cgsize2subreg:=R_SUBWHOLE;
+ end;
+ end;
+ end;
+
+
+ function reg_cgsize(const reg: tregister): tcgsize;
+ begin
+ case getregtype(reg) of
+ R_INTREGISTER :
+ result:=OS_32;
+ R_FPUREGISTER :
+ begin
+ if getsubreg(reg)=R_SUBFD then
+ result:=OS_F64
+ else
+ result:=OS_F32;
+ end;
+ else
+ internalerror(200303181);
+ end;
+ end;
+
+
+ function findreg_by_number(r:Tregister):tregisterindex;
+ begin
+ result:=findreg_by_number_table(r,regnumber_index);
+ end;
+
+
+ function std_regname(r:Tregister):string;
+ var
+ p : tregisterindex;
+ begin
+ { For double floats show a pair like %f0:%f1 }
+ if (getsubreg(r)=R_SUBFD) and
+ (getsupreg(r)<first_fpu_imreg) then
+ begin
+ setsubreg(r,R_SUBFS);
+ p:=findreg_by_number(r);
+ if p<>0 then
+ result:=std_regname_table[p]
+ else
+ result:=generic_regname(r);
+ setsupreg(r,getsupreg(r)+1);
+ p:=findreg_by_number(r);
+ if p<>0 then
+ result:=result+':'+std_regname_table[p]
+ else
+ result:=result+':'+generic_regname(r);
+ end
+ else
+ begin
+ p:=findreg_by_number(r);
+ if p<>0 then
+ result:=std_regname_table[p]
+ else
+ result:=generic_regname(r);
+ end;
+ end;
+
+
+ function std_regnum_search(const s:string):Tregister;
+ begin
+ result:=regnumber_table[findreg_by_name_table(s,std_regname_table,std_regname_index)];
+ end;
+
+
+ function inverse_cond(const c: TAsmCond): TAsmCond; {$ifdef USEINLINE}inline;{$endif USEINLINE}
+ const
+ inverse: array[TAsmCond] of TAsmCond=(C_None,
+ C_NA,C_NAE,C_NB,C_NBE,C_NC,C_NE,C_NG,C_NGE,C_NL,C_NLE,C_A,C_AE,
+ C_B,C_BE,C_C,C_E,C_G,C_GE,C_L,C_LE,C_O,C_P,
+ C_S,C_Z,C_NO,C_NP,C_NP,C_P,C_NS,C_NZ,
+ C_FNE,C_FLE,C_FGE,C_FL,C_FG,C_FE
+ );
+ begin
+ result := inverse[c];
+ end;
+
+ function conditions_equal(const c1, c2: TAsmCond): boolean; {$ifdef USEINLINE}inline;{$endif USEINLINE}
+ begin
+ result := c1 = c2;
+ end;
+
+ function dwarf_reg(r:tregister):shortint;
+ begin
+ result:=regdwarf_table[findreg_by_number(r)];
+ if result=-1 then
+ internalerror(200603251);
+ end;
+
+end.
diff --git a/closures/compiler/sparc/cpugas.pas b/closures/compiler/sparc/cpugas.pas
new file mode 100644
index 0000000000..a5ce410b42
--- /dev/null
+++ b/closures/compiler/sparc/cpugas.pas
@@ -0,0 +1,237 @@
+{
+ Copyright (c) 1999-2003 by Florian Klaempfl
+
+ This unit implements an asmoutput class for SPARC AT&T syntax
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit cpugas;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cpubase,
+ aasmtai,aasmdata,aasmcpu,assemble,aggas;
+
+ type
+ TGasSPARC=class(TGnuAssembler)
+ constructor create(smart: boolean); override;
+ end;
+
+ TSPARCInstrWriter=class(TCPUInstrWriter)
+ procedure WriteInstruction(hp:Tai);override;
+ end;
+
+implementation
+
+ uses
+ cutils,systems,
+ verbose,itcpugas,cgbase,cgutils;
+
+
+{****************************************************************************}
+{ GNU PPC Assembler writer }
+{****************************************************************************}
+
+ constructor TGasSPARC.create(smart: boolean);
+ begin
+ inherited create(smart);
+ InstrWriter := TSPARCInstrWriter.create(self);
+ end;
+
+
+ function GetReferenceString(var ref:TReference):string;
+ begin
+ GetReferenceString:='';
+ with ref do
+ begin
+ if (base=NR_NO) and (index=NR_NO) then
+ begin
+ if assigned(symbol) then
+ GetReferenceString:=symbol.name;
+ if offset>0 then
+ GetReferenceString:=GetReferenceString+'+'+ToStr(offset)
+ else if offset<0 then
+ GetReferenceString:=GetReferenceString+ToStr(offset);
+ case refaddr of
+ addr_high:
+ GetReferenceString:='%hi('+GetReferenceString+')';
+ addr_low:
+ GetReferenceString:='%lo('+GetReferenceString+')';
+ end;
+ end
+ else
+ begin
+{$ifdef extdebug}
+ if assigned(symbol) and
+ not(refaddr in [addr_pic,addr_low]) then
+ internalerror(2003052601);
+{$endif extdebug}
+ if base<>NR_NO then
+ GetReferenceString:=GetReferenceString+gas_regname(base);
+ if index=NR_NO then
+ begin
+ { if (Offset<simm13lo) or (Offset>simm13hi) then
+ internalerror(2003053008); }
+ if offset>0 then
+ GetReferenceString:=GetReferenceString+'+'+ToStr(offset)
+ else if offset<0 then
+ GetReferenceString:=GetReferenceString+ToStr(offset);
+ {
+ else if (offset=0) and not(assigned(symbol)) then
+ GetReferenceString:=GetReferenceString+ToStr(offset);
+ }
+ if assigned(symbol) then
+ begin
+ if refaddr=addr_low then
+ GetReferenceString:='%lo('+symbol.name+')+'+GetReferenceString
+ else
+ GetReferenceString:=symbol.name+'+'+GetReferenceString;
+ end;
+ end
+ else
+ begin
+{$ifdef extdebug}
+ if (Offset<>0) or assigned(symbol) then
+ internalerror(2003052603);
+{$endif extdebug}
+ GetReferenceString:=GetReferenceString+'+'+gas_regname(index);
+ end;
+ end;
+ end;
+ end;
+
+
+ function getopstr(const Oper:TOper):string;
+ begin
+ with Oper do
+ case typ of
+ top_reg:
+ getopstr:=gas_regname(reg);
+ top_const:
+ getopstr:=tostr(longint(val));
+ top_ref:
+ if (oper.ref^.refaddr in [addr_no,addr_pic]) or ((oper.ref^.refaddr=addr_low) and ((oper.ref^.base<>NR_NO) or
+ (oper.ref^.index<>NR_NO))) then
+ getopstr:='['+getreferencestring(ref^)+']'
+ else
+ getopstr:=getreferencestring(ref^);
+ else
+ internalerror(10001);
+ end;
+ end;
+
+
+ procedure TSPARCInstrWriter.WriteInstruction(hp:Tai);
+ var
+ Op:TAsmOp;
+ s:String;
+ i:Integer;
+ begin
+ if hp.typ<>ait_instruction then
+ exit;
+ op:=taicpu(hp).opcode;
+ { translate pseudoops, this should be move to a separate pass later, so it's done before
+ peephole optimization }
+ case op of
+ A_FABSd:
+ begin
+ if (taicpu(hp).ops<>2) or
+ (taicpu(hp).oper[0]^.typ<>top_reg) or
+ (taicpu(hp).oper[1]^.typ<>top_reg) then
+ internalerror(200401045);
+ { FABSs %f<even>,%f<even> }
+ s:=#9+std_op2str[A_FABSs]+#9+getopstr(taicpu(hp).oper[0]^)+','+getopstr(taicpu(hp).oper[1]^);
+ owner.AsmWriteLn(s);
+ { FMOVs %f<odd>,%f<odd> }
+ inc(taicpu(hp).oper[0]^.reg);
+ inc(taicpu(hp).oper[1]^.reg);
+ s:=#9+std_op2str[A_FMOVs]+#9+getopstr(taicpu(hp).oper[0]^)+','+getopstr(taicpu(hp).oper[1]^);
+ dec(taicpu(hp).oper[0]^.reg);
+ dec(taicpu(hp).oper[1]^.reg);
+ owner.AsmWriteLn(s);
+ end;
+ A_FMOVd:
+ begin
+ if (taicpu(hp).ops<>2) or
+ (taicpu(hp).oper[0]^.typ<>top_reg) or
+ (taicpu(hp).oper[1]^.typ<>top_reg) then
+ internalerror(200401045);
+ { FMOVs %f<even>,%f<even> }
+ s:=#9+std_op2str[A_FMOVs]+#9+getopstr(taicpu(hp).oper[0]^)+','+getopstr(taicpu(hp).oper[1]^);
+ owner.AsmWriteLn(s);
+ { FMOVs %f<odd>,%f<odd> }
+ inc(taicpu(hp).oper[0]^.reg);
+ inc(taicpu(hp).oper[1]^.reg);
+ s:=#9+std_op2str[A_FMOVs]+#9+getopstr(taicpu(hp).oper[0]^)+','+getopstr(taicpu(hp).oper[1]^);
+ dec(taicpu(hp).oper[0]^.reg);
+ dec(taicpu(hp).oper[1]^.reg);
+ owner.AsmWriteLn(s);
+ end
+ else
+ begin
+ { call maybe not translated to call }
+ s:=#9+std_op2str[op]+cond2str[taicpu(hp).condition];
+ if taicpu(hp).delayslot_annulled then
+ s:=s+',a';
+ if taicpu(hp).ops>0 then
+ begin
+ s:=s+#9+getopstr(taicpu(hp).oper[0]^);
+ for i:=1 to taicpu(hp).ops-1 do
+ s:=s+','+getopstr(taicpu(hp).oper[i]^);
+ end;
+ owner.AsmWriteLn(s);
+ end;
+ end;
+ end;
+
+
+ const
+ as_sparc_as_info : tasminfo =
+ (
+ id : as_gas;
+ idtxt : 'AS';
+ asmbin : 'as';
+{$ifdef FPC_SPARC_V8_ONLY}
+ asmcmd : '-o $OBJ $ASM';
+{$else}
+ asmcmd : '-Av9 -o $OBJ $ASM';
+{$endif}
+ supported_targets : [system_sparc_solaris,system_sparc_linux,system_sparc_embedded];
+ flags : [af_allowdirect,af_needar,af_smartlink_sections];
+ labelprefix : '.L';
+ comment : '# ';
+ );
+
+ as_sparc_gas_info : tasminfo =
+ (
+ id : as_ggas;
+ idtxt : 'GAS';
+ asmbin : 'gas';
+ asmcmd : '-Av9 -o $OBJ $ASM';
+ supported_targets : [system_sparc_solaris,system_sparc_linux,system_sparc_embedded];
+ flags : [af_allowdirect,af_needar,af_smartlink_sections];
+ labelprefix : '.L';
+ comment : '# ';
+ );
+
+begin
+ RegisterAssembler(as_SPARC_as_info,TGasSPARC);
+ RegisterAssembler(as_SPARC_gas_info,TGasSPARC);
+end.
diff --git a/closures/compiler/sparc/cpuinfo.pas b/closures/compiler/sparc/cpuinfo.pas
new file mode 100644
index 0000000000..41fb3d8608
--- /dev/null
+++ b/closures/compiler/sparc/cpuinfo.pas
@@ -0,0 +1,89 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Basic Processor information for the SPARC
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit cpuinfo;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ globtype;
+
+type
+ bestreal = double;
+ ts32real = single;
+ ts64real = double;
+ ts80real = extended;
+ ts128real = type extended;
+ ts64comp = type extended;
+ pbestreal=^bestreal;
+
+ { possible supported processors for this target }
+ tcputype=(cpu_none,
+ cpu_SPARC_V7,
+ cpu_SPARC_V8,
+ cpu_SPARC_V9
+ );
+
+ tfputype =(fpu_none,
+ fpu_soft,
+ fpu_hard
+ );
+
+
+const
+ { calling conventions supported by the code generator }
+ supported_calling_conventions : tproccalloptions = [
+ pocall_internproc,
+ pocall_stdcall,
+ pocall_cdecl,
+ pocall_cppdecl
+ ];
+
+ cputypestr : array[tcputype] of string[10] = ('',
+ 'SPARC V7',
+ 'SPARC V8',
+ 'SPARC V9'
+ );
+
+ fputypestr : array[tfputype] of string[6] = ('',
+ 'SOFT',
+ 'HARD'
+ );
+
+ { Supported optimizations, only used for information }
+ supported_optimizerswitches = genericlevel1optimizerswitches+
+ genericlevel2optimizerswitches+
+ genericlevel3optimizerswitches-
+ { no need to write info about those }
+ [cs_opt_level1,cs_opt_level2,cs_opt_level3]+
+ [cs_opt_regvar,cs_opt_loopunroll,
+ cs_opt_tailrecursion,cs_opt_nodecse];
+
+ level1optimizerswitches = genericlevel1optimizerswitches;
+ level2optimizerswitches = genericlevel2optimizerswitches + level1optimizerswitches +
+ [cs_opt_regvar,cs_opt_tailrecursion,cs_opt_nodecse];
+ level3optimizerswitches = genericlevel3optimizerswitches + level2optimizerswitches + [{,cs_opt_loopunroll}];
+
+implementation
+
+end.
diff --git a/closures/compiler/sparc/cpunode.pas b/closures/compiler/sparc/cpunode.pas
new file mode 100644
index 0000000000..63fdb77d6f
--- /dev/null
+++ b/closures/compiler/sparc/cpunode.pas
@@ -0,0 +1,38 @@
+{******************************************************************************
+ Copyright (c) 2000 by Florian Klaempfl
+
+ Includes the iSPARC code generator
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ *****************************************************************************}
+unit CpuNode;
+
+{$I fpcdefs.inc}
+
+interface
+{ This unit is used to define the specific CPU implementations. All needed
+actions are included in the INITALIZATION part of these units. This explains
+the behaviour of such a unit having just a USES clause! }
+
+implementation
+
+ uses
+ ncgbas,ncgflw,ncgcnv,ncgld,ncgmem,ncgcon,ncgset,
+ ncpuadd,ncpucall,ncpumat,ncpuinln,ncpucnv,ncpuset,
+ { this not really a node }
+ rgcpu;
+
+end.
diff --git a/closures/compiler/sparc/cpupara.pas b/closures/compiler/sparc/cpupara.pas
new file mode 100644
index 0000000000..aca3bec939
--- /dev/null
+++ b/closures/compiler/sparc/cpupara.pas
@@ -0,0 +1,357 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Calling conventions for the SPARC
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *****************************************************************************}
+unit cpupara;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ globtype,
+ cclasses,
+ aasmtai,aasmdata,
+ cpubase,cpuinfo,
+ symconst,symbase,symsym,symtype,symdef,paramgr,parabase,cgbase,cgutils;
+
+ type
+ TSparcParaManager=class(TParaManager)
+ function push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override;
+ function get_volatile_registers_int(calloption : tproccalloption):TCpuRegisterSet;override;
+ function get_volatile_registers_fpu(calloption : tproccalloption):TCpuRegisterSet;override;
+ {Returns a structure giving the information on the storage of the parameter
+ (which must be an integer parameter)
+ @param(nr Parameter number of routine, starting from 1)}
+ procedure getintparaloc(calloption : tproccalloption; nr : longint;var cgpara : TCGPara);override;
+ function create_paraloc_info(p : TAbstractProcDef; side: tcallercallee):longint;override;
+ function create_varargs_paraloc_info(p : TAbstractProcDef; varargspara:tvarargsparalist):longint;override;
+ function get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tcgpara;override;
+ private
+ procedure create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
+ procedure create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras: tparalist;
+ var intparareg,parasize:longint);
+ end;
+
+implementation
+
+ uses
+ cutils,verbose,systems,
+ defutil,
+ cgobj;
+
+ type
+ tparasupregs = array[0..5] of tsuperregister;
+ pparasupregs = ^tparasupregs;
+ const
+ paraoutsupregs : tparasupregs = (RS_O0,RS_O1,RS_O2,RS_O3,RS_O4,RS_O5);
+ parainsupregs : tparasupregs = (RS_I0,RS_I1,RS_I2,RS_I3,RS_I4,RS_I5);
+
+
+ function TSparcParaManager.get_volatile_registers_int(calloption : tproccalloption):TCpuRegisterSet;
+ begin
+ result:=[RS_G1,RS_O0,RS_O1,RS_O2,RS_O3,RS_O4,RS_O5,RS_O6,RS_O7];
+ end;
+
+
+ function tsparcparamanager.get_volatile_registers_fpu(calloption : tproccalloption):TCpuRegisterSet;
+ begin
+ result:=[RS_F0..RS_F31];
+ end;
+
+
+ procedure TSparcParaManager.GetIntParaLoc(calloption : tproccalloption; nr : longint;var cgpara : tcgpara);
+ var
+ paraloc : pcgparalocation;
+ begin
+ if nr<1 then
+ InternalError(2002100806);
+ cgpara.reset;
+ cgpara.size:=OS_ADDR;
+ cgpara.intsize:=sizeof(pint);
+ cgpara.alignment:=std_param_align;
+ paraloc:=cgpara.add_location;
+ with paraloc^ do
+ begin
+ { The six first parameters are passed into registers }
+ dec(nr);
+ if nr<6 then
+ begin
+ loc:=LOC_REGISTER;
+ register:=newreg(R_INTREGISTER,(RS_O0+nr),R_SUBWHOLE);
+ end
+ else
+ begin
+ { The other parameters are passed on the stack }
+ loc:=LOC_REFERENCE;
+ reference.index:=NR_STACK_POINTER_REG;
+ reference.offset:=92+(nr-6)*4;
+ end;
+ size:=OS_INT;
+ end;
+ end;
+
+
+ { true if a parameter is too large to copy and only the address is pushed }
+ function tsparcparamanager.push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;
+ begin
+ result:=false;
+ { var,out,constref always require address }
+ if varspez in [vs_var,vs_out,vs_constref] then
+ begin
+ result:=true;
+ exit;
+ end;
+ case def.typ of
+ arraydef:
+ result:=(tarraydef(def).highrange>=tarraydef(def).lowrange) or
+ is_open_array(def) or
+ is_array_of_const(def) or
+ is_array_constructor(def);
+ recorddef,
+ variantdef,
+ formaldef :
+ result:=true;
+ objectdef :
+ result:=is_object(def);
+ stringdef :
+ result:=(tstringdef(def).stringtype in [st_shortstring,st_longstring]);
+ procvardef :
+ result:=not tprocvardef(def).is_addressonly;
+ setdef :
+ result:=not is_smallset(def);
+ end;
+ end;
+
+
+ procedure tsparcparamanager.create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
+ begin
+ p.funcretloc[side]:=get_funcretloc(p,side,p.returndef);
+ end;
+
+
+ function tsparcparamanager.get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tcgpara;
+ var
+ paraloc : pcgparalocation;
+ retcgsize : tcgsize;
+ begin
+ result.init;
+ result.alignment:=get_para_align(p.proccalloption);
+ { void has no location }
+ if is_void(def) then
+ begin
+ paraloc:=result.add_location;
+ result.size:=OS_NO;
+ result.intsize:=0;
+ paraloc^.size:=OS_NO;
+ paraloc^.loc:=LOC_VOID;
+ exit;
+ end;
+ { Constructors return self instead of a boolean }
+ if (p.proctypeoption=potype_constructor) then
+ begin
+ retcgsize:=OS_ADDR;
+ result.intsize:=sizeof(pint);
+ end
+ else
+ begin
+ retcgsize:=def_cgsize(def);
+ result.intsize:=def.size;
+ end;
+ result.size:=retcgsize;
+ { Return is passed as var parameter }
+ if ret_in_param(def,p.proccalloption) then
+ begin
+ paraloc:=result.add_location;
+ paraloc^.loc:=LOC_REFERENCE;
+ paraloc^.size:=retcgsize;
+ exit;
+ end;
+
+ paraloc:=result.add_location;
+ { Return in FPU register? }
+ if def.typ=floatdef then
+ begin
+ paraloc^.loc:=LOC_FPUREGISTER;
+ paraloc^.register:=NR_FPU_RESULT_REG;
+ if retcgsize=OS_F64 then
+ setsubreg(paraloc^.register,R_SUBFD);
+ paraloc^.size:=retcgsize;
+ end
+ else
+ { Return in register }
+ begin
+{$ifndef cpu64bitaddr}
+ if retcgsize in [OS_64,OS_S64] then
+ begin
+ paraloc^.loc:=LOC_REGISTER;
+ { high }
+ if side=callerside then
+ paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG
+ else
+ paraloc^.register:=NR_FUNCTION_RETURN64_HIGH_REG;
+ paraloc^.size:=OS_32;
+ { low }
+ paraloc:=result.add_location;
+ paraloc^.loc:=LOC_REGISTER;
+ if side=callerside then
+ paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG
+ else
+ paraloc^.register:=NR_FUNCTION_RETURN64_LOW_REG;
+ paraloc^.size:=OS_32;
+ end
+ else
+{$endif not cpu64bitaddr}
+ begin
+ paraloc^.loc:=LOC_REGISTER;
+ paraloc^.size:=retcgsize;
+ if (side=callerside) then
+ paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize))
+ else
+ paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(R_INTREGISTER,retcgsize));
+ end;
+ end;
+ end;
+
+
+ procedure tsparcparamanager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee;paras:tparalist;
+ var intparareg,parasize:longint);
+ var
+ paraloc : pcgparalocation;
+ i : integer;
+ hp : tparavarsym;
+ paracgsize : tcgsize;
+ hparasupregs : pparasupregs;
+ paralen : longint;
+ begin
+ if side=callerside then
+ hparasupregs:=@paraoutsupregs
+ else
+ hparasupregs:=@parainsupregs;
+ for i:=0 to paras.count-1 do
+ begin
+ hp:=tparavarsym(paras[i]);
+ { currently only support C-style array of const,
+ there should be no location assigned to the vararg array itself }
+ if (p.proccalloption in [pocall_cdecl,pocall_cppdecl]) and
+ is_array_of_const(hp.vardef) then
+ begin
+ paraloc:=hp.paraloc[side].add_location;
+ { hack: the paraloc must be valid, but is not actually used }
+ paraloc^.loc:=LOC_REGISTER;
+ paraloc^.register:=NR_G0;
+ paraloc^.size:=OS_ADDR;
+ break;
+ end;
+
+ if push_addr_param(hp.varspez,hp.vardef,p.proccalloption) then
+ paracgsize:=OS_ADDR
+ else
+ begin
+ paracgsize:=def_cgSize(hp.vardef);
+ if paracgsize=OS_NO then
+ paracgsize:=OS_ADDR;
+ end;
+ hp.paraloc[side].reset;
+ hp.paraloc[side].size:=paracgsize;
+ if (side = callerside) then
+ hp.paraloc[side].Alignment:=std_param_align
+ else
+ hp.paraloc[side].Alignment:=hp.vardef.alignment;
+ paralen:=tcgsize2size[paracgsize];
+ hp.paraloc[side].intsize:=paralen;
+ while paralen>0 do
+ begin
+ paraloc:=hp.paraloc[side].add_location;
+ { Floats are passed in int registers,
+ We can allocate at maximum 32 bits per register }
+ if paracgsize in [OS_64,OS_S64,OS_F32,OS_F64] then
+ paraloc^.size:=OS_32
+ else
+ paraloc^.size:=paracgsize;
+ { ret in param? }
+ if vo_is_funcret in hp.varoptions then
+ begin
+ paraloc^.loc:=LOC_REFERENCE;
+ if side=callerside then
+ paraloc^.reference.index:=NR_STACK_POINTER_REG
+ else
+ paraloc^.reference.index:=NR_FRAME_POINTER_REG;
+ paraloc^.reference.offset:=64;
+ end
+ { In case of po_delphi_nested_cc, the parent frame pointer
+ is always passed on the stack. }
+ else if (intparareg<=high(tparasupregs)) and
+ (not(vo_is_parentfp in hp.varoptions) or
+ not(po_delphi_nested_cc in p.procoptions)) then
+ begin
+ paraloc^.loc:=LOC_REGISTER;
+ paraloc^.register:=newreg(R_INTREGISTER,hparasupregs^[intparareg],R_SUBWHOLE);
+ inc(intparareg);
+ end
+ else
+ begin
+ paraloc^.loc:=LOC_REFERENCE;
+ if side=callerside then
+ paraloc^.reference.index:=NR_STACK_POINTER_REG
+ else
+ paraloc^.reference.index:=NR_FRAME_POINTER_REG;
+ paraloc^.reference.offset:=target_info.first_parm_offset+parasize;
+ { Parameters are aligned at 4 bytes }
+ inc(parasize,align(tcgsize2size[paraloc^.size],sizeof(pint)));
+ end;
+ dec(paralen,tcgsize2size[paraloc^.size]);
+ end;
+ end;
+ end;
+
+
+ function TSparcParaManager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;
+ var
+ intparareg,
+ parasize : longint;
+ begin
+ intparareg:=0;
+ parasize:=0;
+ { calculate the registers for the normal parameters }
+ create_paraloc_info_intern(p,callerside,p.paras,intparareg,parasize);
+ { append the varargs }
+ create_paraloc_info_intern(p,callerside,varargspara,intparareg,parasize);
+ result:=parasize;
+ end;
+
+
+
+ function tsparcparamanager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;
+ var
+ intparareg,
+ parasize : longint;
+ begin
+ intparareg:=0;
+ parasize:=0;
+ create_paraloc_info_intern(p,side,p.paras,intparareg,parasize);
+ { Create Function result paraloc }
+ create_funcretloc_info(p,side);
+ { We need to return the size allocated on the stack }
+ result:=parasize;
+ end;
+
+
+begin
+ ParaManager:=TSparcParaManager.create;
+end.
diff --git a/closures/compiler/sparc/cpupi.pas b/closures/compiler/sparc/cpupi.pas
new file mode 100644
index 0000000000..489e7cb62c
--- /dev/null
+++ b/closures/compiler/sparc/cpupi.pas
@@ -0,0 +1,76 @@
+{
+ Copyright (c) 2002 by Florian Klaempfl
+
+ This unit contains the CPU specific part of tprocinfo
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit cpupi;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cutils,
+ procinfo,cpuinfo,
+ psub;
+
+ type
+ TSparcProcInfo=class(tcgprocinfo)
+ public
+ constructor create(aparent:tprocinfo);override;
+ function calc_stackframe_size:longint;override;
+ end;
+
+implementation
+
+ uses
+ systems,globals,
+ tgobj,paramgr,symconst;
+
+ constructor tsparcprocinfo.create(aparent:tprocinfo);
+ begin
+ inherited create(aparent);
+ maxpushedparasize:=0;
+ end;
+
+
+ function TSparcProcInfo.calc_stackframe_size:longint;
+ begin
+ {
+ Stackframe layout:
+ %fp
+ <locals>
+ <temp>
+ <arguments 6-n for calling>
+ %sp+92
+ <space for arguments 0-5> \
+ <return pointer for calling> | included in first_parm_offset
+ <register window save area for calling> /
+ %sp
+
+ Alignment must be the max available, as doubles require
+ 8 byte alignment
+ }
+ result:=Align(tg.direction*tg.lasttemp+maxpushedparasize+target_info.first_parm_offset,current_settings.alignment.localalignmax);
+ end;
+
+
+begin
+ cprocinfo:=TSparcProcInfo;
+end.
diff --git a/closures/compiler/sparc/cputarg.pas b/closures/compiler/sparc/cputarg.pas
new file mode 100644
index 0000000000..a7b77c8467
--- /dev/null
+++ b/closures/compiler/sparc/cputarg.pas
@@ -0,0 +1,76 @@
+{
+ Copyright (c) 2001 by Peter Vreman
+
+ Includes the i386 dependent target units
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit cputarg;
+
+{$i fpcdefs.inc}
+
+interface
+
+
+implementation
+
+ uses
+ systems { prevent a syntax error when nothing is included }
+
+{$ifndef NOOPT}
+ ,aoptcpu
+{$endif NOOPT}
+
+{**************************************
+ Targets
+**************************************}
+
+ {$ifndef NOTARGETLINUX}
+ ,t_linux
+ {$endif}
+ {$ifndef NOTARGETSUNOS}
+ ,t_sunos
+ {$endif}
+
+{**************************************
+ Assemblers
+**************************************}
+
+ ,CpuGas
+
+{**************************************
+ Assembler Readers
+**************************************}
+
+ {$ifndef NoSparcgas}
+ ,racpugas
+ {$endif NoSparcgas}
+
+{**************************************
+ Debuginfo
+**************************************}
+
+ {$ifndef NoDbgStabs}
+ ,dbgstabs
+ {$endif NoDbgStabs}
+ {$ifndef NoDbgDwarf}
+ ,dbgdwarf
+ {$endif NoDbgDwarf}
+
+ ;
+
+end.
diff --git a/closures/compiler/sparc/itcpugas.pas b/closures/compiler/sparc/itcpugas.pas
new file mode 100644
index 0000000000..c3a1ae4599
--- /dev/null
+++ b/closures/compiler/sparc/itcpugas.pas
@@ -0,0 +1,98 @@
+{
+ Copyright (c) 1998-2002 by Mazen NEIFER
+
+ This unit contains the SPARC GAS instruction tables
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit itcpugas;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cpubase,cgbase;
+
+ const
+ gas_op2str : array[tasmop] of string[14] = ({$INCLUDE strinst.inc});
+
+ function gas_regnum_search(const s:string):Tregister;
+ function gas_regname(r:Tregister):string;
+
+
+implementation
+
+ uses
+ cutils,verbose;
+
+ const
+ gas_regname_table : array[tregisterindex] of string[7] = (
+ {$i rspstd.inc}
+ );
+
+ gas_regname_index : array[tregisterindex] of tregisterindex = (
+ {$i rspsri.inc}
+ );
+
+
+ function findreg_by_gasname(const s:string):tregisterindex;
+ var
+ i,p : tregisterindex;
+ begin
+ {Binary search.}
+ p:=0;
+ i:=regnumber_count_bsstart;
+ repeat
+ if (p+i<=high(tregisterindex)) and (gas_regname_table[gas_regname_index[p+i]]<=s) then
+ p:=p+i;
+ i:=i shr 1;
+ until i=0;
+ if gas_regname_table[gas_regname_index[p]]=s then
+ findreg_by_gasname:=gas_regname_index[p]
+ else
+ findreg_by_gasname:=0;
+ end;
+
+
+ function gas_regnum_search(const s:string):Tregister;
+ begin
+ result:=regnumber_table[findreg_by_gasname(s)];
+ end;
+
+
+ function gas_regname(r:Tregister):string;
+ var
+ hr : tregister;
+ p : longint;
+ begin
+ { Double uses the same table as single }
+ hr:=r;
+ case getsubreg(hr) of
+ R_SUBFD:
+ setsubreg(hr,R_SUBFS);
+ R_SUBL,R_SUBW,R_SUBD,R_SUBQ:
+ setsubreg(hr,R_SUBD);
+ end;
+ p:=findreg_by_number(hr);
+ if p<>0 then
+ result:=gas_regname_table[p]
+ else
+ result:=generic_regname(r);
+ end;
+
+end.
diff --git a/closures/compiler/sparc/ncpuadd.pas b/closures/compiler/sparc/ncpuadd.pas
new file mode 100644
index 0000000000..09e26444cd
--- /dev/null
+++ b/closures/compiler/sparc/ncpuadd.pas
@@ -0,0 +1,376 @@
+{
+ Copyright (c) 2000-2002 by Florian Klaempfl
+
+ Code generation for add nodes on the SPARC
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit ncpuadd;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,ncgadd,cpubase;
+
+ type
+ tsparcaddnode = class(tcgaddnode)
+ private
+ function GetResFlags(unsigned:Boolean):TResFlags;
+ function GetFPUResFlags:TResFlags;
+ protected
+ procedure second_addfloat;override;
+ procedure second_cmpfloat;override;
+ procedure second_cmpboolean;override;
+ procedure second_cmpsmallset;override;
+ procedure second_cmp64bit;override;
+ procedure second_cmpordinal;override;
+ end;
+
+ implementation
+
+ uses
+ systems,
+ cutils,verbose,
+ paramgr,procinfo,
+ aasmtai,aasmdata,aasmcpu,defutil,
+ cgbase,cgcpu,cgutils,
+ cpupara,
+ ncon,nset,nadd,
+ ncgutil,cgobj;
+
+{*****************************************************************************
+ TSparcAddNode
+*****************************************************************************}
+
+ function TSparcAddNode.GetResFlags(unsigned:Boolean):TResFlags;
+ begin
+ case NodeType of
+ equaln:
+ GetResFlags:=F_E;
+ unequaln:
+ GetResFlags:=F_NE;
+ else
+ if not(unsigned) then
+ begin
+ if nf_swapped in flags then
+ case NodeType of
+ ltn:
+ GetResFlags:=F_G;
+ lten:
+ GetResFlags:=F_GE;
+ gtn:
+ GetResFlags:=F_L;
+ gten:
+ GetResFlags:=F_LE;
+ end
+ else
+ case NodeType of
+ ltn:
+ GetResFlags:=F_L;
+ lten:
+ GetResFlags:=F_LE;
+ gtn:
+ GetResFlags:=F_G;
+ gten:
+ GetResFlags:=F_GE;
+ end;
+ end
+ else
+ begin
+ if nf_swapped in Flags then
+ case NodeType of
+ ltn:
+ GetResFlags:=F_A;
+ lten:
+ GetResFlags:=F_AE;
+ gtn:
+ GetResFlags:=F_B;
+ gten:
+ GetResFlags:=F_BE;
+ end
+ else
+ case NodeType of
+ ltn:
+ GetResFlags:=F_B;
+ lten:
+ GetResFlags:=F_BE;
+ gtn:
+ GetResFlags:=F_A;
+ gten:
+ GetResFlags:=F_AE;
+ end;
+ end;
+ end;
+ end;
+
+
+ function TSparcAddNode.GetFPUResFlags:TResFlags;
+ begin
+ case NodeType of
+ equaln:
+ result:=F_FE;
+ unequaln:
+ result:=F_FNE;
+ else
+ begin
+ if nf_swapped in Flags then
+ case NodeType of
+ ltn:
+ result:=F_FG;
+ lten:
+ result:=F_FGE;
+ gtn:
+ result:=F_FL;
+ gten:
+ result:=F_FLE;
+ end
+ else
+ case NodeType of
+ ltn:
+ result:=F_FL;
+ lten:
+ result:=F_FLE;
+ gtn:
+ result:=F_FG;
+ gten:
+ result:=F_FGE;
+ end;
+ end;
+ end;
+ end;
+
+
+ procedure tsparcaddnode.second_addfloat;
+ var
+ op : TAsmOp;
+ begin
+ pass_left_right;
+ if (nf_swapped in flags) then
+ swapleftright;
+
+ { force fpureg as location, left right doesn't matter
+ as both will be in a fpureg }
+ location_force_fpureg(current_asmdata.CurrAsmList,left.location,true);
+ location_force_fpureg(current_asmdata.CurrAsmList,right.location,(left.location.loc<>LOC_CFPUREGISTER));
+
+ location_reset(location,LOC_FPUREGISTER,def_cgsize(resultdef));
+ if left.location.loc<>LOC_CFPUREGISTER then
+ location.register:=left.location.register
+ else
+ location.register:=right.location.register;
+
+ case nodetype of
+ addn :
+ begin
+ if location.size=OS_F64 then
+ op:=A_FADDd
+ else
+ op:=A_FADDs;
+ end;
+ muln :
+ begin
+ if location.size=OS_F64 then
+ op:=A_FMULd
+ else
+ op:=A_FMULs;
+ end;
+ subn :
+ begin
+ if location.size=OS_F64 then
+ op:=A_FSUBd
+ else
+ op:=A_FSUBs;
+ end;
+ slashn :
+ begin
+ if location.size=OS_F64 then
+ op:=A_FDIVd
+ else
+ op:=A_FDIVs;
+ end;
+ else
+ internalerror(200306014);
+ end;
+
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(op,
+ left.location.register,right.location.register,location.register));
+ end;
+
+
+ procedure tsparcaddnode.second_cmpfloat;
+ var
+ op : tasmop;
+ begin
+ pass_left_right;
+ if (nf_swapped in flags) then
+ swapleftright;
+
+ { force fpureg as location, left right doesn't matter
+ as both will be in a fpureg }
+ location_force_fpureg(current_asmdata.CurrAsmList,left.location,true);
+ location_force_fpureg(current_asmdata.CurrAsmList,right.location,true);
+
+ location_reset(location,LOC_FLAGS,OS_NO);
+ location.resflags:=getfpuresflags;
+
+ if left.location.size=OS_F64 then
+ op:=A_FCMPd
+ else
+ op:=A_FCMPs;
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op,
+ left.location.register,right.location.register));
+ { Delay slot (can only contain integer operation) }
+ current_asmdata.CurrAsmList.concat(taicpu.op_none(A_NOP));
+ end;
+
+
+ procedure tsparcaddnode.second_cmpboolean;
+ begin
+ pass_left_right;
+ force_reg_left_right(true,true);
+
+ if right.location.loc = LOC_CONSTANT then
+ tcgsparc(cg).handle_reg_const_reg(current_asmdata.CurrAsmList,A_SUBcc,left.location.register,right.location.value,NR_G0)
+ else
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SUBcc,left.location.register,right.location.register,NR_G0));
+
+ location_reset(location,LOC_FLAGS,OS_NO);
+ location.resflags:=getresflags(true);
+ end;
+
+
+ procedure tsparcaddnode.second_cmpsmallset;
+ begin
+ pass_left_right;
+ force_reg_left_right(true,true);
+
+ if right.location.loc = LOC_CONSTANT then
+ tcgsparc(cg).handle_reg_const_reg(current_asmdata.CurrAsmList,A_SUBcc,left.location.register,right.location.value,NR_G0)
+ else
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SUBcc,left.location.register,right.location.register,NR_G0));
+
+ location_reset(location,LOC_FLAGS,OS_NO);
+ location.resflags:=getresflags(true);
+ end;
+
+
+ procedure tsparcaddnode.second_cmp64bit;
+ var
+ unsigned : boolean;
+
+ procedure firstjmp64bitcmp;
+ var
+ oldnodetype : tnodetype;
+ begin
+ { the jump the sequence is a little bit hairy }
+ case nodetype of
+ ltn,gtn:
+ begin
+ cg.a_jmp_flags(current_asmdata.CurrAsmList,getresflags(unsigned),current_procinfo.CurrTrueLabel);
+ { cheat a little bit for the negative test }
+ toggleflag(nf_swapped);
+ cg.a_jmp_flags(current_asmdata.CurrAsmList,getresflags(unsigned),current_procinfo.CurrFalseLabel);
+ toggleflag(nf_swapped);
+ end;
+ lten,gten:
+ begin
+ oldnodetype:=nodetype;
+ if nodetype=lten then
+ nodetype:=ltn
+ else
+ nodetype:=gtn;
+ cg.a_jmp_flags(current_asmdata.CurrAsmList,getresflags(unsigned),current_procinfo.CurrTrueLabel);
+ { cheat for the negative test }
+ if nodetype=ltn then
+ nodetype:=gtn
+ else
+ nodetype:=ltn;
+ cg.a_jmp_flags(current_asmdata.CurrAsmList,getresflags(unsigned),current_procinfo.CurrFalseLabel);
+ nodetype:=oldnodetype;
+ end;
+ equaln:
+ cg.a_jmp_flags(current_asmdata.CurrAsmList,F_NE,current_procinfo.CurrFalseLabel);
+ unequaln:
+ cg.a_jmp_flags(current_asmdata.CurrAsmList,F_NE,current_procinfo.CurrTrueLabel);
+ end;
+ end;
+
+ procedure secondjmp64bitcmp;
+
+ begin
+ { the jump the sequence is a little bit hairy }
+ case nodetype of
+ ltn,gtn,lten,gten:
+ begin
+ { the comparisaion of the low dword have to be }
+ { always unsigned! }
+ cg.a_jmp_flags(current_asmdata.CurrAsmList,getresflags(true),current_procinfo.CurrTrueLabel);
+ cg.a_jmp_always(current_asmdata.CurrAsmList,current_procinfo.CurrFalseLabel);
+ end;
+ equaln:
+ begin
+ cg.a_jmp_flags(current_asmdata.CurrAsmList,F_NE,current_procinfo.CurrFalseLabel);
+ cg.a_jmp_always(current_asmdata.CurrAsmList,current_procinfo.CurrTrueLabel);
+ end;
+ unequaln:
+ begin
+ cg.a_jmp_flags(current_asmdata.CurrAsmList,F_NE,current_procinfo.CurrTrueLabel);
+ cg.a_jmp_always(current_asmdata.CurrAsmList,current_procinfo.CurrFalseLabel);
+ end;
+ end;
+ end;
+
+ begin
+ pass_left_right;
+ force_reg_left_right(false,false);
+
+ unsigned:=not(is_signed(left.resultdef)) or
+ not(is_signed(right.resultdef));
+
+ location_reset(location,LOC_JUMP,OS_NO);
+
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CMP,left.location.register64.reghi,right.location.register64.reghi));
+ firstjmp64bitcmp;
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CMP,left.location.register64.reglo,right.location.register64.reglo));
+ secondjmp64bitcmp;
+ end;
+
+
+ procedure tsparcaddnode.second_cmpordinal;
+ var
+ unsigned : boolean;
+ begin
+ pass_left_right;
+ force_reg_left_right(true,true);
+
+ unsigned:=not(is_signed(left.resultdef)) or
+ not(is_signed(right.resultdef));
+
+ if right.location.loc = LOC_CONSTANT then
+ tcgsparc(cg).handle_reg_const_reg(current_asmdata.CurrAsmList,A_SUBcc,left.location.register,right.location.value,NR_G0)
+ else
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SUBcc,left.location.register,right.location.register,NR_G0));
+
+ location_reset(location,LOC_FLAGS,OS_NO);
+ location.resflags:=getresflags(unsigned);
+ end;
+
+begin
+ caddnode:=tsparcaddnode;
+end.
diff --git a/closures/compiler/sparc/ncpucall.pas b/closures/compiler/sparc/ncpucall.pas
new file mode 100644
index 0000000000..53ef3f8250
--- /dev/null
+++ b/closures/compiler/sparc/ncpucall.pas
@@ -0,0 +1,56 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate sparc assembler for in call nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit ncpucall;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ ncgcal;
+
+ type
+ tsparccallnode = class(tcgcallnode)
+ procedure extra_post_call_code;override;
+ end;
+
+
+implementation
+
+ uses
+ cpubase,
+ aasmtai,aasmdata,
+ aasmcpu,
+ paramgr,
+ ncal;
+
+
+ procedure tsparccallnode.extra_post_call_code;
+ begin
+ if paramanager.ret_in_param(procdefinition.returndef,procdefinition.proccalloption) then
+ current_asmdata.CurrAsmList.concat(taicpu.op_const(A_UNIMP,procdefinition.returndef.size and $fff));
+ end;
+
+
+begin
+ ccallnode:=TSparcCallNode;
+end.
diff --git a/closures/compiler/sparc/ncpucnv.pas b/closures/compiler/sparc/ncpucnv.pas
new file mode 100644
index 0000000000..d39bf89ea7
--- /dev/null
+++ b/closures/compiler/sparc/ncpucnv.pas
@@ -0,0 +1,336 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate SPARC assembler for type converting nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************}
+unit ncpucnv;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,ncnv,ncgcnv,defcmp;
+
+ type
+ tsparctypeconvnode = class(TCgTypeConvNode)
+ protected
+ { procedure second_int_to_int;override; }
+ { procedure second_string_to_string;override; }
+ { procedure second_cstring_to_pchar;override; }
+ { procedure second_string_to_chararray;override; }
+ { procedure second_array_to_pointer;override; }
+ function first_int_to_real: tnode; override;
+ { procedure second_pointer_to_array;override; }
+ { procedure second_chararray_to_string;override; }
+ { procedure second_char_to_string;override; }
+ procedure second_int_to_real;override;
+ { procedure second_real_to_real;override; }
+ { procedure second_cord_to_pointer;override; }
+ { procedure second_proc_to_procvar;override; }
+ { procedure second_bool_to_int;override; }
+ procedure second_int_to_bool;override;
+ { procedure second_load_smallset;override; }
+ { procedure second_ansistring_to_pchar;override; }
+ { procedure second_pchar_to_string;override; }
+ { procedure second_class_to_intf;override; }
+ { procedure second_char_to_char;override; }
+ end;
+
+implementation
+
+ uses
+ verbose,globals,systems,globtype,
+ symconst,symdef,aasmbase,aasmtai,aasmdata,
+ defutil,
+ cgbase,cgutils,pass_1,pass_2,
+ ncon,ncal,procinfo,
+ ncgutil,
+ cpubase,aasmcpu,
+ tgobj,cgobj;
+
+
+{*****************************************************************************
+ FirstTypeConv
+*****************************************************************************}
+
+ function tsparctypeconvnode.first_int_to_real: tnode;
+ var
+ fname: string[19];
+ begin
+ { converting a 64bit integer to a float requires a helper }
+ if is_64bitint(left.resultdef) or
+ is_currency(left.resultdef) then
+ begin
+ result:=inherited first_int_to_real;
+ exit;
+ end
+ else
+ { other integers are supposed to be 32 bit }
+ begin
+ if is_signed(left.resultdef) then
+ inserttypeconv(left,s32inttype)
+ else
+ inserttypeconv(left,u32inttype);
+ firstpass(left);
+ end;
+ result := nil;
+ expectloc:=LOC_FPUREGISTER;
+ end;
+
+
+{*****************************************************************************
+ SecondTypeConv
+*****************************************************************************}
+
+ procedure tsparctypeconvnode.second_int_to_real;
+
+ procedure loadsigned;
+ begin
+ location_force_mem(current_asmdata.CurrAsmList,left.location);
+ { Load memory in fpu register }
+ cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,OS_F32,OS_F32,left.location.reference,location.register);
+ tg.ungetiftemp(current_asmdata.CurrAsmList,left.location.reference);
+ { Convert value in fpu register from integer to float }
+ case tfloatdef(resultdef).floattype of
+ s32real:
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FiTOs,location.register,location.register));
+ s64real:
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FiTOd,location.register,location.register));
+ s128real:
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FiTOq,location.register,location.register));
+ else
+ internalerror(200408011);
+ end;
+ end;
+
+ var
+ href : treference;
+ hregister : tregister;
+ l1,l2 : tasmlabel;
+
+ begin
+ location_reset(location,LOC_FPUREGISTER,def_cgsize(resultdef));
+ if is_signed(left.resultdef) then
+ begin
+ location.register:=cg.getfpuregister(current_asmdata.CurrAsmList,location.size);
+ loadsigned;
+ end
+ else
+ begin
+ current_asmdata.getdatalabel(l1);
+ current_asmdata.getjumplabel(l2);
+ reference_reset_symbol(href,l1,0,8);
+ hregister:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
+ cg.a_load_loc_reg(current_asmdata.CurrAsmList,OS_32,left.location,hregister);
+
+ { here we need always an 64 bit register }
+ location.register:=cg.getfpuregister(current_asmdata.CurrAsmList,OS_F64);
+ location_force_mem(current_asmdata.CurrAsmList,left.location);
+ { Load memory in fpu register }
+ cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,OS_F32,OS_F32,left.location.reference,location.register);
+ tg.ungetiftemp(current_asmdata.CurrAsmList,left.location.reference);
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FiTOd,location.register,location.register));
+
+ current_asmdata.CurrAsmList.concat(Taicpu.op_reg_reg(A_CMP,hregister,NR_G0));
+ cg.a_jmp_flags(current_asmdata.CurrAsmList,F_GE,l2);
+
+ case tfloatdef(resultdef).floattype of
+ { converting dword to s64real first and cut off at the end avoids precision loss }
+ s32real,
+ s64real:
+ begin
+ hregister:=cg.getfpuregister(current_asmdata.CurrAsmList,OS_F64);
+ new_section(current_asmdata.asmlists[al_typedconsts],sec_rodata_norel,l1.name,const_align(8));
+ current_asmdata.asmlists[al_typedconsts].concat(Tai_label.Create(l1));
+ { I got this constant from a test program (FK) }
+ current_asmdata.asmlists[al_typedconsts].concat(Tai_const.Create_32bit($41f00000));
+ current_asmdata.asmlists[al_typedconsts].concat(Tai_const.Create_32bit(0));
+
+ cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,OS_F64,OS_F64,href,hregister);
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_FADDD,location.register,hregister,location.register));
+ cg.a_label(current_asmdata.CurrAsmList,l2);
+
+ { cut off if we should convert to single }
+ if tfloatdef(resultdef).floattype=s32real then
+ begin
+ hregister:=location.register;
+ location.register:=cg.getfpuregister(current_asmdata.CurrAsmList,location.size);
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FDTOS,hregister,location.register));
+ end;
+ end;
+ else
+ internalerror(200410031);
+ end;
+ end;
+ end;
+
+
+(*
+ procedure tsparctypeconvnode.second_real_to_real;
+ const
+ conv_op : array[tfloattype,tfloattype] of tasmop = (
+ { from: s32 s64 s80 sc80 c64 cur f128 }
+ { s32 } ( A_FMOVS,A_FDTOS,A_NONE, A_NONE, A_NONE, A_NONE, A_NONE ),
+ { s64 } ( A_FSTOD,A_FMOVD,A_NONE, A_NONE, A_NONE, A_NONE, A_NONE ),
+ { s80 } ( A_NONE, A_NONE, A_NONE, A_NONE, A_NONE, A_NONE, A_NONE ),
+ { sc80 } ( A_NONE, A_NONE, A_NONE, A_NONE, A_NONE, A_NONE, A_NONE ),
+ { c64 } ( A_NONE, A_NONE, A_NONE, A_NONE, A_NONE, A_NONE, A_NONE ),
+ { cur } ( A_NONE, A_NONE, A_NONE, A_NONE, A_NONE, A_NONE, A_NONE ),
+ { f128 } ( A_NONE, A_NONE, A_NONE, A_NONE, A_NONE, A_NONE, A_NONE )
+ );
+ var
+ op : tasmop;
+ begin
+ location_reset(location,LOC_FPUREGISTER,def_cgsize(resultdef));
+ location_force_fpureg(current_asmdata.CurrAsmList,left.location,false);
+ { Convert value in fpu register from integer to float }
+ op:=conv_op[tfloatdef(resultdef).floattype,tfloatdef(left.resultdef).floattype];
+ if op=A_NONE then
+ internalerror(200401121);
+ location.register:=cg.getfpuregister(current_asmdata.CurrAsmList,location.size);
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op,left.location.register,location.register));
+ end;
+*)
+
+ procedure tsparctypeconvnode.second_int_to_bool;
+ var
+ href: treference;
+ hreg1,hreg2 : tregister;
+ resflags : tresflags;
+ opsize : tcgsize;
+ hlabel,oldTrueLabel,oldFalseLabel : tasmlabel;
+ newsize : tcgsize;
+ begin
+ oldTrueLabel:=current_procinfo.CurrTrueLabel;
+ oldFalseLabel:=current_procinfo.CurrFalseLabel;
+ current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
+ current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel);
+ secondpass(left);
+ if codegenerror then
+ exit;
+
+ { Explicit typecasts from any ordinal type to a boolean type }
+ { must not change the ordinal value }
+ if (nf_explicit in flags) and
+ not(left.location.loc in [LOC_FLAGS,LOC_JUMP]) then
+ begin
+ location_copy(location,left.location);
+ newsize:=def_cgsize(resultdef);
+ { change of size? change sign only if location is LOC_(C)REGISTER? Then we have to sign/zero-extend }
+ if (tcgsize2size[newsize]<>tcgsize2size[left.location.size]) or
+ ((newsize<>left.location.size) and (location.loc in [LOC_REGISTER,LOC_CREGISTER])) then
+ location_force_reg(current_asmdata.CurrAsmList,location,newsize,true)
+ else
+ location.size:=newsize;
+ current_procinfo.CurrTrueLabel:=oldTrueLabel;
+ current_procinfo.CurrFalseLabel:=oldFalseLabel;
+ exit;
+ end;
+
+ location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
+ opsize:=def_cgsize(left.resultdef);
+ case left.location.loc of
+ LOC_CREFERENCE,LOC_REFERENCE,LOC_REGISTER,LOC_CREGISTER:
+ begin
+ if left.location.loc in [LOC_CREFERENCE,LOC_REFERENCE] then
+ begin
+ hreg2:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+{$ifndef cpu64bitalu}
+ if left.location.size in [OS_64,OS_S64] then
+ begin
+ cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_INT,OS_INT,left.location.reference,hreg2);
+ hreg1:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+ href:=left.location.reference;
+ inc(href.offset,4);
+ cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_INT,OS_INT,href,hreg1);
+ cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,OP_OR,OS_32,hreg1,hreg2,hreg2);
+ end
+ else
+{$endif not cpu64bitalu}
+ cg.a_load_ref_reg(current_asmdata.CurrAsmList,opsize,opsize,left.location.reference,hreg2);
+ end
+ else
+ begin
+ hreg2:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+{$ifndef cpu64bitalu}
+ if left.location.size in [OS_64,OS_S64] then
+ begin
+ hreg2:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
+ cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,OP_OR,OS_32,left.location.register64.reghi,left.location.register64.reglo,hreg2);
+ end
+ else
+{$endif not cpu64bitalu}
+ cg.a_load_reg_reg(current_asmdata.CurrAsmList,opsize,opsize,left.location.register,hreg2);
+ end;
+ hreg1:=cg.getintregister(current_asmdata.CurrAsmList,opsize);
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SUBCC,NR_G0,hreg2,NR_G0));
+ if is_pasbool(resultdef) then
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_ADDX,NR_G0,NR_G0,hreg1))
+ else
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SUBX,NR_G0,NR_G0,hreg1));
+ end;
+ LOC_FLAGS :
+ begin
+ hreg1:=cg.GetIntRegister(current_asmdata.CurrAsmList,location.size);
+ resflags:=left.location.resflags;
+ cg.g_flags2reg(current_asmdata.CurrAsmList,location.size,resflags,hreg1);
+ if (is_cbool(resultdef)) then
+ cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_NEG,location.size,hreg1,hreg1);
+ end;
+ LOC_JUMP :
+ begin
+ hreg1:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+ current_asmdata.getjumplabel(hlabel);
+ cg.a_label(current_asmdata.CurrAsmList,current_procinfo.CurrTrueLabel);
+ if not(is_cbool(resultdef)) then
+ cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_INT,1,hreg1)
+ else
+ cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_INT,-1,hreg1);
+ cg.a_jmp_always(current_asmdata.CurrAsmList,hlabel);
+ cg.a_label(current_asmdata.CurrAsmList,current_procinfo.CurrFalseLabel);
+ cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_INT,0,hreg1);
+ cg.a_label(current_asmdata.CurrAsmList,hlabel);
+ end;
+ else
+ internalerror(10062);
+ end;
+{$ifndef cpu64bitalu}
+ if (location.size in [OS_64,OS_S64]) then
+ begin
+ location.register64.reglo:=hreg1;
+ location.register64.reghi:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
+ if (is_cbool(resultdef)) then
+ { reglo is either 0 or -1 -> reghi has to become the same }
+ cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_32,OS_32,location.register64.reglo,location.register64.reghi)
+ else
+ { unsigned }
+ cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_32,0,location.register64.reghi);
+ end
+ else
+{$endif not cpu64bitalu}
+ location.register:=hreg1;
+
+ current_procinfo.CurrTrueLabel:=oldTrueLabel;
+ current_procinfo.CurrFalseLabel:=oldFalseLabel;
+ end;
+
+
+begin
+ ctypeconvnode:=tsparctypeconvnode;
+end.
diff --git a/closures/compiler/sparc/ncpuinln.pas b/closures/compiler/sparc/ncpuinln.pas
new file mode 100644
index 0000000000..2d81e05da8
--- /dev/null
+++ b/closures/compiler/sparc/ncpuinln.pas
@@ -0,0 +1,143 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate SPARC inline nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit ncpuinln;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,ninl,ncginl;
+
+ type
+ tsparcinlinenode = class(tcgInlineNode)
+ function first_abs_real: tnode; override;
+ function first_sqr_real: tnode; override;
+ function first_sqrt_real: tnode; override;
+ procedure second_abs_real; override;
+ procedure second_sqr_real; override;
+ procedure second_sqrt_real; override;
+ private
+ procedure load_fpu_location;
+ end;
+
+
+implementation
+
+ uses
+ systems,globtype,
+ cutils,verbose,
+ symconst,symdef,
+ aasmtai,aasmdata,aasmcpu,
+ cgbase,pass_2,
+ cpubase,paramgr,
+ nbas,ncon,ncal,ncnv,nld,
+ ncgutil,cgobj,cgutils;
+
+{*****************************************************************************
+ tsparcinlinenode
+*****************************************************************************}
+
+ procedure tsparcinlinenode.load_fpu_location;
+ begin
+ secondpass(left);
+ location_force_fpureg(current_asmdata.CurrAsmList,left.location,true);
+ location_copy(location,left.location);
+ if left.location.loc=LOC_CFPUREGISTER then
+ begin
+ location.register:=cg.getfpuregister(current_asmdata.CurrAsmList,location.size);
+ location.loc := LOC_FPUREGISTER;
+ end;
+ end;
+
+
+ function tsparcinlinenode.first_abs_real : tnode;
+ begin
+ expectloc:=LOC_FPUREGISTER;
+ first_abs_real := nil;
+ end;
+
+
+ function tsparcinlinenode.first_sqr_real : tnode;
+ begin
+ expectloc:=LOC_FPUREGISTER;
+ first_sqr_real:=nil;
+ end;
+
+
+ function tsparcinlinenode.first_sqrt_real : tnode;
+ begin
+ expectloc:=LOC_FPUREGISTER;
+ first_sqrt_real := nil;
+ end;
+
+
+ procedure tsparcinlinenode.second_abs_real;
+ begin
+ load_fpu_location;
+ case tfloatdef(left.resultdef).floattype of
+ s32real:
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FABSs,left.location.register,location.register));
+ s64real:
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FABSd,left.location.register,location.register));
+ s128real:
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FABSq,left.location.register,location.register));
+ else
+ internalerror(200410031);
+ end;
+ end;
+
+
+ procedure tsparcinlinenode.second_sqr_real;
+ begin
+ load_fpu_location;
+ case tfloatdef(left.resultdef).floattype of
+ s32real:
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_FMULs,left.location.register,left.location.register,location.register));
+ s64real:
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_FMULd,left.location.register,left.location.register,location.register));
+ s128real:
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_FMULq,left.location.register,left.location.register,location.register));
+ else
+ internalerror(200410032);
+ end;
+ end;
+
+
+ procedure tsparcinlinenode.second_sqrt_real;
+ begin
+ load_fpu_location;
+ case tfloatdef(left.resultdef).floattype of
+ s32real:
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FSQRTs,left.location.register,location.register));
+ s64real:
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FSQRTd,left.location.register,location.register));
+ s128real:
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FSQRTq,left.location.register,location.register));
+ else
+ internalerror(200410033);
+ end;
+ end;
+
+begin
+ cInlineNode:=tsparcinlinenode;
+end.
diff --git a/closures/compiler/sparc/ncpumat.pas b/closures/compiler/sparc/ncpumat.pas
new file mode 100644
index 0000000000..3793c968d4
--- /dev/null
+++ b/closures/compiler/sparc/ncpumat.pas
@@ -0,0 +1,332 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate SPARC assembler for math nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit ncpumat;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,nmat,ncgmat;
+
+ type
+ tSparcmoddivnode = class(tmoddivnode)
+ procedure pass_generate_code;override;
+ end;
+
+ tSparcshlshrnode = class(tshlshrnode)
+ procedure pass_generate_code;override;
+ { everything will be handled in pass_2 }
+ function first_shlshr64bitint: tnode; override;
+ end;
+
+ tSparcnotnode = class(tcgnotnode)
+ procedure second_boolean;override;
+ end;
+
+implementation
+
+ uses
+ globtype,systems,constexp,
+ cutils,verbose,globals,
+ symconst,
+ aasmbase,aasmcpu,aasmtai,aasmdata,
+ defutil,
+ cgbase,cgobj,pass_2,procinfo,
+ ncon,
+ cpubase,
+ ncgutil,cgcpu,cgutils;
+
+{*****************************************************************************
+ TSparcMODDIVNODE
+*****************************************************************************}
+
+ procedure tSparcmoddivnode.pass_generate_code;
+ const
+ { signed overflow }
+ divops: array[boolean, boolean] of tasmop =
+ ((A_UDIV,A_UDIVcc),(A_SDIV,A_SDIVcc));
+ var
+ power : longint;
+ op : tasmop;
+ tmpreg,
+ numerator,
+ divider,
+ resultreg : tregister;
+ overflowlabel : tasmlabel;
+ ai : taicpu;
+ begin
+ secondpass(left);
+ secondpass(right);
+ location_copy(location,left.location);
+
+ { put numerator in register }
+ location_force_reg(current_asmdata.CurrAsmList,left.location,def_cgsize(left.resultdef),true);
+ location_copy(location,left.location);
+ numerator := location.register;
+
+ if (nodetype = modn) then
+ resultreg := cg.GetIntRegister(current_asmdata.CurrAsmList,OS_INT)
+ else
+ begin
+ if (location.loc = LOC_CREGISTER) then
+ begin
+ location.loc := LOC_REGISTER;
+ location.register := cg.GetIntRegister(current_asmdata.CurrAsmList,OS_INT);
+ end;
+ resultreg := location.register;
+ end;
+
+ if (nodetype = divn) and
+ (right.nodetype = ordconstn) and
+ ispowerof2(tordconstnode(right).value.svalue,power) then
+ begin
+ if is_signed(left.resultdef) Then
+ begin
+ tmpreg:=cg.GetIntRegister(current_asmdata.CurrAsmList,OS_INT);
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SAR,OS_INT,31,numerator,tmpreg);
+ { if signed, tmpreg=right value-1, otherwise 0 }
+ cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_AND,OS_INT,tordconstnode(right).value.svalue-1,tmpreg);
+ { add to the left value }
+ cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_ADD,OS_INT,numerator,tmpreg);
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SAR,OS_INT,aword(power),tmpreg,resultreg);
+ end
+ else
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SHR,OS_INT,aword(power),numerator,resultreg);
+ end
+ else
+ begin
+ { load divider in a register if necessary }
+ location_force_reg(current_asmdata.CurrAsmList,right.location,
+ def_cgsize(right.resultdef),true);
+ divider := right.location.register;
+
+ { needs overflow checking, (-maxlongint-1) div (-1) overflows! }
+ { And on Sparc, the only way to catch a div-by-0 is by checking }
+ { the overflow flag (JM) }
+
+ { Fill %y with the -1 or 0 depending on the highest bit }
+ if is_signed(left.resultdef) then
+ begin
+ tmpreg:=cg.GetIntRegister(current_asmdata.CurrAsmList,OS_INT);
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_const_reg(A_SRA,numerator,31,tmpreg));
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_MOV,tmpreg,NR_Y));
+ end
+ else
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_MOV,NR_G0,NR_Y));
+ { wait 3 instructions slots before we can read %y }
+ current_asmdata.CurrAsmList.concat(taicpu.op_none(A_NOP));
+ current_asmdata.CurrAsmList.concat(taicpu.op_none(A_NOP));
+ current_asmdata.CurrAsmList.concat(taicpu.op_none(A_NOP));
+
+ op := divops[is_signed(right.resultdef),
+ cs_check_overflow in current_settings.localswitches];
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(op,numerator,divider,resultreg));
+
+ if (nodetype = modn) then
+ begin
+ current_asmdata.getjumplabel(overflowlabel);
+ ai:=taicpu.op_cond_sym(A_Bxx,C_O,overflowlabel);
+ ai.delayslot_annulled:=true;
+ current_asmdata.CurrAsmList.concat(ai);
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg(A_NOT,resultreg));
+ cg.a_label(current_asmdata.CurrAsmList,overflowlabel);
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SMUL,resultreg,divider,resultreg));
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SUB,numerator,resultreg,resultreg));
+ end;
+ end;
+ { set result location }
+ location.loc:=LOC_REGISTER;
+ location.register:=resultreg;
+ cg.g_overflowcheck(current_asmdata.CurrAsmList,Location,resultdef);
+ end;
+
+
+{*****************************************************************************
+ TSparcSHLRSHRNODE
+*****************************************************************************}
+
+ function TSparcShlShrNode.first_shlshr64bitint:TNode;
+ begin
+ { 64bit without constants need a helper }
+ if is_64bit(left.resultdef) and
+ (right.nodetype<>ordconstn) then
+ begin
+ result:=inherited first_shlshr64bitint;
+ exit;
+ end;
+
+ result := nil;
+ end;
+
+
+ procedure tSparcshlshrnode.pass_generate_code;
+ var
+ hregister,resultreg,hregister1,
+ hreg64hi,hreg64lo : tregister;
+ op : topcg;
+ shiftval: aword;
+ begin
+ { 64bit without constants need a helper, and is
+ already replaced in pass1 }
+ if is_64bit(left.resultdef) and
+ (right.nodetype<>ordconstn) then
+ internalerror(200405301);
+
+ secondpass(left);
+ secondpass(right);
+ if is_64bit(left.resultdef) then
+ begin
+ location_reset(location,LOC_REGISTER,OS_64);
+
+ { load left operator in a register }
+ location_force_reg(current_asmdata.CurrAsmList,left.location,OS_64,false);
+ hreg64hi:=left.location.register64.reghi;
+ hreg64lo:=left.location.register64.reglo;
+
+ shiftval := tordconstnode(right).value.svalue and 63;
+ if shiftval > 31 then
+ begin
+ if nodetype = shln then
+ begin
+ cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_32,0,hreg64hi);
+ if (shiftval and 31) <> 0 then
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SHL,OS_32,shiftval and 31,hreg64lo,hreg64lo);
+ end
+ else
+ begin
+ cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_32,0,hreg64lo);
+ if (shiftval and 31) <> 0 then
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SHR,OS_32,shiftval and 31,hreg64hi,hreg64hi);
+ end;
+ location.register64.reglo:=hreg64hi;
+ location.register64.reghi:=hreg64lo;
+ end
+ else
+ begin
+ hregister:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
+ if nodetype = shln then
+ begin
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SHR,OS_32,32-shiftval,hreg64lo,hregister);
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SHL,OS_32,shiftval,hreg64hi,hreg64hi);
+ cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,OP_OR,OS_32,hregister,hreg64hi,hreg64hi);
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SHL,OS_32,shiftval,hreg64lo,hreg64lo);
+ end
+ else
+ begin
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SHL,OS_32,32-shiftval,hreg64hi,hregister);
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SHR,OS_32,shiftval,hreg64lo,hreg64lo);
+ cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,OP_OR,OS_32,hregister,hreg64lo,hreg64lo);
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SHR,OS_32,shiftval,hreg64hi,hreg64hi);
+ end;
+ location.register64.reghi:=hreg64hi;
+ location.register64.reglo:=hreg64lo;
+ end;
+ end
+ else
+ begin
+ { load left operators in a register }
+ location_force_reg(current_asmdata.CurrAsmList,left.location,def_cgsize(left.resultdef),true);
+ location_copy(location,left.location);
+ resultreg := location.register;
+ hregister1 := location.register;
+ if (location.loc = LOC_CREGISTER) then
+ begin
+ location.loc := LOC_REGISTER;
+ resultreg := cg.GetIntRegister(current_asmdata.CurrAsmList,OS_INT);
+ location.register := resultreg;
+ end;
+ { determine operator }
+ if nodetype=shln then
+ op:=OP_SHL
+ else
+ op:=OP_SHR;
+ { shifting by a constant directly coded: }
+ if (right.nodetype=ordconstn) then
+ begin
+ if tordconstnode(right).value and 31<>0 then
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,op,OS_32,tordconstnode(right).value.svalue and 31,hregister1,resultreg)
+ end
+ else
+ begin
+ { load shift count in a register if necessary }
+ location_force_reg(current_asmdata.CurrAsmList,right.location,def_cgsize(right.resultdef),true);
+ cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,op,OS_32,right.location.register,hregister1,resultreg);
+ end;
+ end;
+ end;
+
+
+{*****************************************************************************
+ TSPARCNOTNODE
+*****************************************************************************}
+
+ procedure tsparcnotnode.second_boolean;
+ var
+ hl : tasmlabel;
+ begin
+ { if the location is LOC_JUMP, we do the secondpass after the
+ labels are allocated
+ }
+ if left.expectloc=LOC_JUMP then
+ begin
+ hl:=current_procinfo.CurrTrueLabel;
+ current_procinfo.CurrTrueLabel:=current_procinfo.CurrFalseLabel;
+ current_procinfo.CurrFalseLabel:=hl;
+ secondpass(left);
+ maketojumpbool(current_asmdata.CurrAsmList,left,lr_load_regvars);
+ hl:=current_procinfo.CurrTrueLabel;
+ current_procinfo.CurrTrueLabel:=current_procinfo.CurrFalseLabel;
+ current_procinfo.CurrFalseLabel:=hl;
+ location.loc:=LOC_JUMP;
+ end
+ else
+ begin
+ secondpass(left);
+ case left.location.loc of
+ LOC_FLAGS :
+ begin
+ location_copy(location,left.location);
+ inverse_flags(location.resflags);
+ end;
+ LOC_REGISTER, LOC_CREGISTER,
+ LOC_REFERENCE, LOC_CREFERENCE,
+ LOC_SUBSETREG, LOC_CSUBSETREG,
+ LOC_SUBSETREF, LOC_CSUBSETREF:
+ begin
+ location_force_reg(current_asmdata.CurrAsmList,left.location,def_cgsize(left.resultdef),true);
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_const_reg(A_SUBcc,left.location.register,0,NR_G0));
+ location_reset(location,LOC_FLAGS,OS_NO);
+ location.resflags:=F_E;
+ end;
+ else
+ internalerror(2003042401);
+ end;
+ end;
+ end;
+
+
+begin
+ cmoddivnode:=tSparcmoddivnode;
+ cshlshrnode:=tSparcshlshrnode;
+ cnotnode:=tSparcnotnode;
+end.
diff --git a/closures/compiler/sparc/ncpuset.pas b/closures/compiler/sparc/ncpuset.pas
new file mode 100644
index 0000000000..ef562c62c1
--- /dev/null
+++ b/closures/compiler/sparc/ncpuset.pas
@@ -0,0 +1,126 @@
+{
+ Copyright (c) 1998-2004 by Florian Klaempfl
+
+ Generate sparc assembler for in set/case nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit ncpuset;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ globtype,
+ nset,
+ ncgset;
+
+ type
+ tcpucasenode = class(tcgcasenode)
+ protected
+ procedure optimizevalues(var max_linear_list:aint;var max_dist:aword);override;
+ function has_jumptable : boolean;override;
+ procedure genjumptable(hp : pcaselabel;min_,max_ : aint);override;
+ end;
+
+
+ implementation
+
+ uses
+ globals,constexp,
+ systems,
+ cpubase,
+ aasmbase,aasmtai,aasmdata,aasmcpu,
+ cgbase,cgutils,cgobj,
+ procinfo;
+
+ procedure tcpucasenode.optimizevalues(var max_linear_list:aint;var max_dist:aword);
+ begin
+ { give the jump table a higher priority }
+ max_dist:=(max_dist*3) div 2;
+ end;
+
+
+ function tcpucasenode.has_jumptable : boolean;
+ begin
+ has_jumptable:=true;
+ end;
+
+
+ procedure tcpucasenode.genjumptable(hp : pcaselabel;min_,max_ : aint);
+ var
+ table : tasmlabel;
+ last : TConstExprInt;
+ indexreg,jmpreg,basereg : tregister;
+ href : treference;
+
+ procedure genitem(list:TAsmList;t : pcaselabel);
+ var
+ i : aint;
+ begin
+ if assigned(t^.less) then
+ genitem(list,t^.less);
+ { fill possible hole }
+ for i:=last.svalue+1 to t^._low.svalue-1 do
+ list.concat(Tai_const.Create_sym(elselabel));
+ for i:=t^._low.svalue to t^._high.svalue do
+ list.concat(Tai_const.Create_sym(blocklabel(t^.blockid)));
+ last:=t^._high;
+ if assigned(t^.greater) then
+ genitem(list,t^.greater);
+ end;
+
+ begin
+ if not(jumptable_no_range) then
+ begin
+ { case expr less than min_ => goto elselabel }
+ cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,opsize,jmp_lt,aint(min_),hregister,elselabel);
+ { case expr greater than max_ => goto elselabel }
+ cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,opsize,jmp_gt,aint(max_),hregister,elselabel);
+ end;
+ current_asmdata.getjumplabel(table);
+ indexreg:=cg.getaddressregister(current_asmdata.CurrAsmList);
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SHL,OS_ADDR,2,hregister,indexreg);
+ { create reference }
+ reference_reset_symbol(href,table,0,sizeof(pint));
+ href.offset:=(-aint(min_))*4;
+ basereg:=cg.getaddressregister(current_asmdata.CurrAsmList);
+ cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,href,basereg);
+
+ jmpreg:=cg.getaddressregister(current_asmdata.CurrAsmList);
+
+ reference_reset(href,sizeof(pint));
+ href.index:=indexreg;
+ href.base:=basereg;
+ cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,href,jmpreg);
+
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg(A_JMP,jmpreg));
+ { Delay slot }
+ current_asmdata.CurrAsmList.concat(taicpu.op_none(A_NOP));
+ { generate jump table }
+ new_section(current_procinfo.aktlocaldata,sec_data,current_procinfo.procdef.mangledname,sizeof(pint));
+ current_procinfo.aktlocaldata.concat(Tai_label.Create(table));
+ last:=min_;
+ genitem(current_procinfo.aktlocaldata,hp);
+ end;
+
+
+
+begin
+ ccasenode:=tcpucasenode;
+end.
diff --git a/closures/compiler/sparc/opcode.inc b/closures/compiler/sparc/opcode.inc
new file mode 100644
index 0000000000..d0d29b24f5
--- /dev/null
+++ b/closures/compiler/sparc/opcode.inc
@@ -0,0 +1,75 @@
+{******************************************************************************
+ *****************************************************************************}
+A_NONE,
+A_ABCD,
+A_ADD,A_ADDcc,A_ADDX,A_ADDXcc,
+A_AND,A_ANDcc,A_ANDN,A_ANDNcc,
+{Branching instructions}
+A_JMP,
+A_JMPL,
+A_CALL,
+A_BA,A_Bxx,A_FBA,A_FBxx,
+A_CBccc,
+A_FLUSH,
+{Load instructions}
+A_LDSB,A_LDSH,A_LDSTUB,
+A_LDUB,A_LDUH,A_LD,A_LDD,A_LDF,A_LDFSR,A_LDDF,A_LDC,A_LDCSR,A_LDDC,
+A_LDSBA,A_LDSHA,A_LDUBA,A_LDUHA,A_LDA,A_LDDA,
+A_LDSTUBA,
+A_MULScc,
+A_NOP,
+A_OR,A_ORcc,A_ORN,A_ORNcc,
+A_RDASR,A_RDY,A_RDPSR,A_RDWIM,A_RDTBR,
+A_RESTORE,
+A_RET,A_RETL,
+A_SAVE,
+A_SDIV,A_SDIVcc,
+A_SMUL,A_SMULcc,
+A_SETHI,
+A_SLL,A_SRL,A_SRA,
+A_STB,A_STH,A_ST,A_STD,A_STF,A_STDF,A_STFSR,A_STDFQ,
+A_STC,A_STDC,A_STCSR,A_STDCQ,
+A_STBA,A_STHA,A_STA,A_STDA,
+A_SUB,A_SUBcc,A_SUBX,A_SUBXcc,
+A_SWAP,A_SWAPA,A_Ticc,A_TADDcc,A_TSUBcc,A_TADDccTV,A_TSUBccTV,
+A_TA,A_Txx,
+A_UDIV,A_UDIVcc,
+A_UMUL,A_UMULcc,
+A_UNIMP,
+A_WRASR,A_WRY,A_WRPSR,A_WRWIM,A_WRTBR,
+A_XNOR,A_XNORcc,
+A_XOR,A_XORcc,
+ {Floating-point instructions}
+A_FiTOs,A_FiTOd,A_FiTOq,
+A_FsTOi,A_FdTOi,A_FqTOi,
+A_FsTOd,A_FsTOq,
+A_FdTOs,A_FdTOq,
+A_FqTOd,A_FqTOs,
+A_FMOVs,A_FNEGs,A_FABSs,
+A_FSQRTs,A_FSQRTd,A_FSQRTq,
+A_FADDs,A_FADDd,A_FADDq,
+A_FSUBs,A_FSUBd,A_FSUBq,
+A_FMULs,A_FMULd,A_FMULQ,
+A_FdMULq,A_FsMULd,
+A_FDIVs,A_FDIVd,A_FDIVq,
+A_FCMPs,A_FCMPd,A_FCMPq,
+A_FCPop1,A_CPop2,
+ {Synthetic instructions}
+A_btst,A_bset,A_bclr,A_btog,
+A_clr,A_clrb,A_clrh,
+A_cmp,
+A_dec,A_deccc,
+A_inc,A_inccc,
+A_MOV,
+A_NEG,
+A_not,
+A_set,
+A_skipz,A_skipnz,
+A_tst,
+{ Internal instructions }
+A_FMOVd,
+A_FABSd,
+A_FABSq,
+{ Memory barrier instructions }
+A_STBAR,
+A_MEMBAR
diff --git a/closures/compiler/sparc/racpu.pas b/closures/compiler/sparc/racpu.pas
new file mode 100644
index 0000000000..aa56288442
--- /dev/null
+++ b/closures/compiler/sparc/racpu.pas
@@ -0,0 +1,54 @@
+{
+ Copyright (c) 1998-2003 by Mazen NEIFER
+
+ Handles the common Sparc assembler reader routines
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit racpu;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ aasmbase,aasmtai,aasmdata,aasmcpu,
+ cpubase,rautils,cclasses;
+
+ type
+ TSparcOperand=class(TOperand)
+ end;
+
+ TSparcInstruction=class(TInstruction)
+ delayslot_annulled : boolean;
+ { opcode adding }
+ function ConcatInstruction(p : TAsmList) : tai;override;
+ end;
+
+implementation
+
+ function TSparcInstruction.ConcatInstruction(p : TAsmList) : tai;
+ begin
+ result:=inherited ConcatInstruction(p);
+ { delay slot annulled support }
+ if assigned(result) and
+ (result.typ=ait_instruction) and
+ delayslot_annulled then
+ taicpu(result).delayslot_annulled:=true;
+ end;
+
+end.
diff --git a/closures/compiler/sparc/racpugas.pas b/closures/compiler/sparc/racpugas.pas
new file mode 100644
index 0000000000..4bf644893e
--- /dev/null
+++ b/closures/compiler/sparc/racpugas.pas
@@ -0,0 +1,688 @@
+{
+ Copyright (c) 1998-2002 by Mazen NEIFER
+
+ Does the parsing for the i386 GNU AS styled inline assembler.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+Unit racpugas;
+
+{$i fpcdefs.inc}
+
+Interface
+
+ uses
+ raatt,racpu;
+
+ type
+ tSparcReader = class(tattreader)
+ function is_asmopcode(const s: string):boolean;override;
+ procedure handleopcode;override;
+ procedure BuildReference(oper : tSparcoperand);
+ procedure BuildOperand(oper : tSparcoperand);
+ procedure BuildOpCode(instr : tSparcinstruction);
+ procedure ReadPercent(oper : tSparcoperand);
+ procedure ReadSym(oper : tSparcoperand);
+ procedure ConvertCalljmp(instr : tSparcinstruction);
+ procedure handlepercent;override;
+ end;
+
+
+ Implementation
+
+ uses
+ { helpers }
+ cutils,
+ { global }
+ globtype,verbose,
+ systems,
+ { aasm }
+ cpubase,aasmbase,aasmtai,aasmdata,aasmcpu,
+ { symtable }
+ symconst,symsym,
+ { parser }
+ scanner,
+ procinfo,
+ rabase,rautils,
+ cgbase,cgobj
+ ;
+
+ procedure TSparcReader.ReadSym(oper : tSparcoperand);
+ var
+ tempstr, mangledname : string;
+ typesize,l,k : aint;
+ begin
+ tempstr:=actasmpattern;
+ Consume(AS_ID);
+ { typecasting? }
+ if (actasmtoken=AS_LPAREN) and
+ SearchType(tempstr,typesize) then
+ begin
+ oper.hastype:=true;
+ Consume(AS_LPAREN);
+ BuildOperand(oper);
+ Consume(AS_RPAREN);
+ if oper.opr.typ in [OPR_REFERENCE,OPR_LOCAL] then
+ oper.SetSize(typesize,true);
+ end
+ else
+ if not oper.SetupVar(tempstr,false) then
+ Message1(sym_e_unknown_id,tempstr);
+ { record.field ? }
+ if actasmtoken=AS_DOT then
+ begin
+ BuildRecordOffsetSize(tempstr,l,k,mangledname,false);
+ if (mangledname<>'') then
+ Message(asmr_e_invalid_reference_syntax);
+ inc(oper.opr.ref.offset,l);
+ end;
+ end;
+
+
+ procedure TSparcReader.ReadPercent(oper : tSparcoperand);
+ begin
+ { check for ...@ }
+ if actasmtoken=AS_AT then
+ begin
+ if (oper.opr.ref.symbol=nil) and
+ (oper.opr.ref.offset = 0) then
+ Message(asmr_e_invalid_reference_syntax);
+ Consume(AS_AT);
+ if actasmtoken=AS_ID then
+ begin
+ if upper(actasmpattern)='LO' then
+ oper.opr.ref.refaddr:=addr_low
+ else if upper(actasmpattern)='HI' then
+ oper.opr.ref.refaddr:=addr_high
+ else
+ Message(asmr_e_invalid_reference_syntax);
+ Consume(AS_ID);
+ end
+ else
+ Message(asmr_e_invalid_reference_syntax);
+ end;
+ end;
+
+
+ Procedure TSparcReader.BuildReference(oper : tSparcoperand);
+ var
+ l : aint;
+ regs : byte;
+ hasimm : boolean;
+ begin
+ oper.initref;
+ regs:=0;
+ hasimm:=false;
+ Consume(AS_LBRACKET);
+ repeat
+ Case actasmtoken of
+ AS_INTNUM,
+ AS_MINUS,
+ AS_PLUS:
+ Begin
+ if hasimm or (regs>1) then
+ Begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(true);
+ break;
+ End;
+ oper.opr.Ref.Offset:=BuildConstExpression(false,true);
+ hasimm:=true;
+ End;
+
+ AS_REGISTER:
+ Begin
+ if regs<2 then
+ begin
+ if regs=0 then
+ oper.opr.ref.base:=actasmregister
+ else
+ oper.opr.ref.index:=actasmregister;
+ inc(regs);
+ end
+ else
+ begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(true);
+ break;
+ end;
+ Consume(AS_REGISTER);
+ end;
+
+ AS_ID:
+ Begin
+ l:=BuildConstExpression(true,true);
+ inc(oper.opr.ref.offset,l);
+ End;
+
+ AS_RBRACKET:
+ begin
+ if (regs=0) and (not hasimm) then
+ Message(asmr_e_invalid_reference_syntax);
+ Consume(AS_RBRACKET);
+ break;
+ end;
+
+ else
+ Begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(false);
+ break;
+ end;
+ end;
+ until false;
+ end;
+
+
+ procedure TSparcReader.handlepercent;
+ var
+ len : longint;
+ begin
+ len:=1;
+ actasmpattern[len]:='%';
+ c:=current_scanner.asmgetchar;
+ { to be a register there must be a letter and not a number }
+ while c in ['a'..'z','A'..'Z','0'..'9'] do
+ Begin
+ inc(len);
+ actasmpattern[len]:=c;
+ c:=current_scanner.asmgetchar;
+ end;
+ actasmpattern[0]:=chr(len);
+ uppervar(actasmpattern);
+ if is_register(actasmpattern) then
+ exit;
+ if (actasmpattern='%HI') then
+ actasmtoken:=AS_HI
+ else if (actasmpattern='%LO')then
+ actasmtoken:=AS_LO
+ else
+ Message(asmr_e_invalid_register);
+ end;
+
+
+ Procedure TSparcReader.BuildOperand(oper : tSparcoperand);
+ var
+ expr : string;
+ typesize,l : aint;
+
+ procedure AddLabelOperand(hl:tasmlabel);
+ begin
+ if not(actasmtoken in [AS_PLUS,AS_MINUS,AS_LPAREN]) and
+ is_calljmp(actopcode) then
+ begin
+ oper.opr.typ:=OPR_SYMBOL;
+ oper.opr.symbol:=hl;
+ end
+ else
+ begin
+ oper.InitRef;
+ oper.opr.ref.symbol:=hl;
+ end;
+ end;
+
+
+ procedure MaybeRecordOffset;
+ var
+ mangledname: string;
+ hasdot : boolean;
+ l,
+ toffset,
+ tsize : aint;
+ begin
+ if not(actasmtoken in [AS_DOT,AS_PLUS,AS_MINUS]) then
+ exit;
+ l:=0;
+ hasdot:=(actasmtoken=AS_DOT);
+ if hasdot then
+ begin
+ if expr<>'' then
+ begin
+ BuildRecordOffsetSize(expr,toffset,tsize,mangledname,false);
+ if (oper.opr.typ<>OPR_CONSTANT) and
+ (mangledname<>'') then
+ Message(asmr_e_wrong_sym_type);
+ inc(l,toffset);
+ oper.SetSize(tsize,true);
+ end;
+ end;
+ if actasmtoken in [AS_PLUS,AS_MINUS] then
+ inc(l,BuildConstExpression(true,false));
+ case oper.opr.typ of
+ OPR_LOCAL :
+ begin
+ { don't allow direct access to fields of parameters, because that
+ will generate buggy code. Allow it only for explicit typecasting }
+ if hasdot and
+ (not oper.hastype) and
+ (tabstractnormalvarsym(oper.opr.localsym).owner.symtabletype=parasymtable) and
+ (current_procinfo.procdef.proccalloption<>pocall_register) then
+ Message(asmr_e_cannot_access_field_directly_for_parameters);
+ inc(oper.opr.localsymofs,l)
+ end;
+ OPR_CONSTANT :
+ if (mangledname<>'') then
+ begin
+ if (oper.opr.val<>0) then
+ Message(asmr_e_wrong_sym_type);
+ oper.opr.typ:=OPR_SYMBOL;
+ oper.opr.symbol:=current_asmdata.RefAsmSymbol(mangledname);
+ end
+ else
+ inc(oper.opr.val,l);
+ OPR_REFERENCE :
+ inc(oper.opr.ref.offset,l);
+ OPR_SYMBOL:
+ Message(asmr_e_invalid_symbol_ref);
+ else
+ internalerror(200309221);
+ end;
+ end;
+
+ var
+ tempreg : tregister;
+ tempstr : string;
+ tempsymtyp : TAsmSymType;
+ hl : tasmlabel;
+ gotplus,
+ negative : boolean;
+ Begin
+ expr:='';
+ gotplus:=true;
+ negative:=false;
+ repeat
+ case actasmtoken of
+ AS_MINUS :
+ begin
+ consume(AS_MINUS);
+ negative:=true;
+ gotplus:=true;
+ end;
+
+ AS_PLUS :
+ begin
+ consume(AS_PLUS);
+ negative:=false;
+ gotplus:=true;
+ end;
+
+ AS_INTNUM,
+ AS_MOD:
+ Begin
+ if not gotplus then
+ Message(asmr_e_invalid_reference_syntax);
+ l:=BuildConstExpression(True,False);
+ if negative then
+ l:=-l;
+ { Constant memory offset }
+ oper.InitRef;
+ oper.opr.ref.refaddr:=addr_full;
+ oper.opr.ref.offset:=l;
+ GotPlus:=(prevasmtoken=AS_PLUS) or
+ (prevasmtoken=AS_MINUS);
+ if GotPlus then
+ negative:=(prevasmtoken=AS_MINUS);
+ end;
+
+ AS_LBRACKET :
+ begin
+ { memory reference }
+ BuildReference(oper);
+ gotplus:=false;
+ end;
+
+ AS_HI,
+ AS_LO:
+ begin
+ { Low or High part of a constant (or constant
+ memory location) }
+ oper.InitRef;
+ if actasmtoken=AS_LO then
+ oper.opr.ref.refaddr:=addr_low
+ else
+ oper.opr.ref.refaddr:=addr_high;
+ Consume(actasmtoken);
+ Consume(AS_LPAREN);
+ BuildConstSymbolExpression(false, true,false,l,tempstr,tempsymtyp);
+ if not assigned(oper.opr.ref.symbol) then
+ oper.opr.ref.symbol:=current_asmdata.RefAsmSymbol(tempstr)
+ else
+ Message(asmr_e_cant_have_multiple_relocatable_symbols);
+ case oper.opr.typ of
+ OPR_CONSTANT :
+ inc(oper.opr.val,l);
+ OPR_LOCAL :
+ inc(oper.opr.localsymofs,l);
+ OPR_REFERENCE :
+ inc(oper.opr.ref.offset,l);
+ else
+ internalerror(200309202);
+ end;
+ Consume(AS_RPAREN);
+ gotplus:=false;
+ end;
+
+ AS_ID: { A constant expression, or a Variable ref. }
+ Begin
+ { Local Label ? }
+ if is_locallabel(actasmpattern) then
+ begin
+ CreateLocalLabel(actasmpattern,hl,false);
+ Consume(AS_ID);
+ AddLabelOperand(hl);
+ end
+ else
+ { Check for label }
+ if SearchLabel(actasmpattern,hl,false) then
+ begin
+ Consume(AS_ID);
+ AddLabelOperand(hl);
+ end
+ else
+ { probably a variable or normal expression }
+ { or a procedure (such as in CALL ID) }
+ Begin
+ { is it a constant ? }
+ if SearchIConstant(actasmpattern,l) then
+ Begin
+ if not (oper.opr.typ in [OPR_NONE,OPR_CONSTANT]) then
+ Message(asmr_e_invalid_operand_type);
+ BuildConstantOperand(oper);
+ end
+ else
+ begin
+ expr:=actasmpattern;
+ Consume(AS_ID);
+ { typecasting? }
+ if (actasmtoken=AS_LPAREN) and
+ SearchType(expr,typesize) then
+ begin
+ oper.hastype:=true;
+ Consume(AS_LPAREN);
+ BuildOperand(oper);
+ Consume(AS_RPAREN);
+ if oper.opr.typ in [OPR_REFERENCE,OPR_LOCAL] then
+ oper.SetSize(typesize,true);
+ end
+ else
+ begin
+ if oper.SetupVar(expr,false) then
+ ReadPercent(oper)
+ else
+ Begin
+ { look for special symbols ... }
+ if expr= '__HIGH' then
+ begin
+ consume(AS_LPAREN);
+ if not oper.setupvar('high'+actasmpattern,false) then
+ Message1(sym_e_unknown_id,'high'+actasmpattern);
+ consume(AS_ID);
+ consume(AS_RPAREN);
+ end
+ else
+ if expr = '__RESULT' then
+ oper.SetUpResult
+ else
+ if expr = '__SELF' then
+ oper.SetupSelf
+ else
+ if expr = '__OLDEBP' then
+ oper.SetupOldEBP
+ else
+ Message1(sym_e_unknown_id,expr);
+ end;
+ end;
+ end;
+ if actasmtoken=AS_DOT then
+ MaybeRecordOffset;
+ { add a constant expression? }
+ if (actasmtoken=AS_PLUS) then
+ begin
+ l:=BuildConstExpression(true,false);
+ case oper.opr.typ of
+ OPR_CONSTANT :
+ inc(oper.opr.val,l);
+ OPR_LOCAL :
+ inc(oper.opr.localsymofs,l);
+ OPR_REFERENCE :
+ inc(oper.opr.ref.offset,l);
+ else
+ internalerror(200309202);
+ end;
+ end
+ end;
+ gotplus:=false;
+ end;
+
+ AS_REGISTER: { Register, a variable reference or a constant reference }
+ Begin
+ { save the type of register used. }
+ tempreg:=actasmregister;
+ Consume(AS_REGISTER);
+ if (oper.opr.typ in [OPR_REGISTER,OPR_REFERENCE]) and gotplus then
+ begin
+ oper.initref;
+ oper.opr.ref.refaddr:=addr_full;
+ if oper.opr.ref.base<>NR_NO then
+ oper.opr.ref.base:=tempreg
+ else
+ if oper.opr.ref.index<>NR_NO then
+ oper.opr.ref.index:=tempreg
+ else
+ Message(asmr_e_multiple_index);
+ end
+ else
+ begin
+ if (oper.opr.typ<>OPR_NONE) then
+ Message(asmr_e_invalid_operand_type);
+ oper.opr.typ:=OPR_REGISTER;
+ oper.opr.reg:=tempreg;
+ end;
+ gotplus:=false;
+ end;
+
+ AS_END,
+ AS_SEPARATOR,
+ AS_COMMA:
+ break;
+ else
+ Begin
+ Message(asmr_e_syn_operand);
+ Consume(actasmtoken);
+ end;
+ end; { end case }
+ until false;
+ end;
+
+
+{*****************************************************************************
+ TSparcReader
+*****************************************************************************}
+
+ procedure TSparcReader.BuildOpCode(instr : tSparcinstruction);
+ var
+ operandnum : longint;
+ Begin
+ { opcode }
+ if (actasmtoken<>AS_OPCODE) then
+ Begin
+ Message(asmr_e_invalid_or_missing_opcode);
+ RecoverConsume(true);
+ exit;
+ end;
+ { Fill the instr object with the current state }
+ with instr do
+ begin
+ Opcode:=ActOpcode;
+ condition:=ActCondition;
+ end;
+
+ { We are reading operands, so opcode will be an AS_ID }
+ operandnum:=1;
+ Consume(AS_OPCODE);
+ { Zero operand opcode ? }
+ if actasmtoken in [AS_SEPARATOR,AS_END] then
+ begin
+ operandnum:=0;
+ exit;
+ end;
+
+ { delayslot annulled? }
+ if (actasmtoken=AS_COMMA) then
+ begin
+ consume(AS_COMMA);
+ if actasmpattern='A' then
+ instr.delayslot_annulled:=true;
+ { force reading of AS_COMMA instead of AS_ID, otherwise
+ a label .L0 will first read a AS_DOT instead of AS_ID }
+ actasmtoken:=AS_COMMA;
+ consume(AS_COMMA);
+ end;
+
+ { Read the operands }
+ repeat
+ case actasmtoken of
+ AS_COMMA: { Operand delimiter }
+ Begin
+ if operandnum>Max_Operands then
+ Message(asmr_e_too_many_operands)
+ else
+ begin
+ { condition operands doesn't set the operand but write to the
+ condition field of the instruction
+ }
+ if instr.Operands[operandnum].opr.typ<>OPR_NONE then
+ Inc(operandnum);
+ end;
+ Consume(AS_COMMA);
+ end;
+ AS_SEPARATOR,
+ AS_END : { End of asm operands for this opcode }
+ begin
+ break;
+ end;
+ else
+ BuildOperand(instr.Operands[operandnum] as tSparcoperand);
+ end; { end case }
+ until false;
+ if (operandnum=1) and (instr.Operands[operandnum].opr.typ=OPR_NONE) then
+ dec(operandnum);
+ instr.Ops:=operandnum;
+ end;
+
+
+ function TSparcReader.is_asmopcode(const s: string):boolean;
+ var
+ cond:TAsmCond;
+ Begin
+ { making s a value parameter would break other assembler readers }
+ is_asmopcode:=false;
+
+ { clear op code }
+ actopcode:=A_None;
+ { clear condition }
+ fillchar(actcondition,sizeof(actcondition),0);
+
+ { Search opcodes }
+ actopcode:=tasmop(PtrUInt(iasmops.Find(s)));
+ if actopcode<>A_NONE then
+ begin
+ actasmtoken:=AS_OPCODE;
+ result:=TRUE;
+ exit;
+ end;
+
+ { not found, check branch instructions }
+ if (Upcase(s[1])='B') or
+ ((Upcase(s[1])='F') and (Upcase(s[2])='B')) then
+ begin
+ { we can search here without an extra table which is sorted by string length
+ because we take the whole remaining string without the leading B }
+ if (Upcase(s[1])='F') then
+ actopcode := A_FBxx
+ else
+ actopcode := A_Bxx;
+ for cond:=low(TAsmCond) to high(TAsmCond) do
+ if (Upper(copy(s,2,length(s)-1))=Upper(Cond2Str[cond])) then
+ begin
+ actasmtoken:=AS_OPCODE;
+ actcondition:=cond;
+ is_asmopcode:=true;
+ end;
+ end;
+ end;
+
+
+ procedure TSparcReader.ConvertCalljmp(instr : tSparcinstruction);
+ var
+ newopr : toprrec;
+ begin
+ if instr.Operands[1].opr.typ=OPR_REFERENCE then
+ with newopr do
+ begin
+ typ:=OPR_SYMBOL;
+ symbol:=instr.Operands[1].opr.ref.symbol;
+ symofs:=instr.Operands[1].opr.ref.offset;
+ if (instr.Operands[1].opr.ref.base<>NR_NO) or
+ (instr.Operands[1].opr.ref.index<>NR_NO) or
+ (instr.Operands[1].opr.ref.refaddr<>addr_full) then
+ Message(asmr_e_syn_operand);
+ instr.Operands[1].opr:=newopr;
+ end;
+ end;
+
+
+ procedure TSparcReader.handleopcode;
+ var
+ instr : tSparcinstruction;
+ begin
+ instr:=TSparcInstruction.Create(TSparcOperand);
+ BuildOpcode(instr);
+ with instr do
+ begin
+ condition := actcondition;
+ if is_calljmp(opcode) then
+ ConvertCalljmp(instr);
+ ConcatInstruction(curlist);
+ Free;
+ end;
+ end;
+
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+const
+ asmmode_Sparc_att_info : tasmmodeinfo =
+ (
+ id : asmmode_Sparc_gas;
+ idtxt : 'GAS';
+ casmreader : TSparcReader;
+ );
+
+ asmmode_Sparc_standard_info : tasmmodeinfo =
+ (
+ id : asmmode_standard;
+ idtxt : 'STANDARD';
+ casmreader : TSparcReader;
+ );
+
+initialization
+ RegisterAsmMode(asmmode_Sparc_att_info);
+ RegisterAsmMode(asmmode_Sparc_standard_info);
+end.
diff --git a/closures/compiler/sparc/rgcpu.pas b/closures/compiler/sparc/rgcpu.pas
new file mode 100644
index 0000000000..5297337ecf
--- /dev/null
+++ b/closures/compiler/sparc/rgcpu.pas
@@ -0,0 +1,164 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit implements the SPARC specific class for the register
+ allocator
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************}
+unit rgcpu;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ aasmbase,aasmcpu,aasmtai,aasmdata,
+ cgbase,cgutils,
+ cpubase,
+ rgobj;
+
+ type
+ trgcpu=class(trgobj)
+ procedure add_constraints(reg:tregister);override;
+ function get_spill_subreg(r : tregister) : tsubregister;override;
+ procedure do_spill_read(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister);override;
+ procedure do_spill_written(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister);override;
+ end;
+
+
+implementation
+
+ uses
+ verbose,cutils,
+ globtype,
+ cgobj;
+
+ procedure trgcpu.add_constraints(reg:tregister);
+ var
+ supreg,i : Tsuperregister;
+ begin
+ case getsubreg(reg) of
+ { Let 64bit floats conflict with all odd float regs }
+ R_SUBFD:
+ begin
+ supreg:=getsupreg(reg);
+ i:=RS_F1;
+ while (i<=RS_F31) do
+ begin
+ add_edge(supreg,i);
+ inc(i,2);
+ end;
+ end;
+ { Let 64bit ints conflict with all odd int regs }
+ R_SUBQ:
+ begin
+ supreg:=getsupreg(reg);
+ i:=RS_G1;
+ while (i<=RS_I7) do
+ begin
+ add_edge(supreg,i);
+ inc(i,2);
+ end;
+ end;
+ end;
+ end;
+
+
+ function trgcpu.get_spill_subreg(r : tregister) : tsubregister;
+ begin
+ if getregtype(r)=R_FPUREGISTER then
+ result:=getsubreg(r)
+ else
+ result:=defaultsub;
+ end;
+
+
+ procedure trgcpu.do_spill_read(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister);
+ var
+ helpins : tai;
+ tmpref : treference;
+ helplist : TAsmList;
+ hreg : tregister;
+ begin
+ if abs(spilltemp.offset)>4095 then
+ begin
+ helplist:=TAsmList.create;
+
+ if getregtype(tempreg)=R_INTREGISTER then
+ hreg:=tempreg
+ else
+ hreg:=cg.getintregister(helplist,OS_ADDR);
+
+ reference_reset(tmpref,sizeof(pint));
+ tmpref.offset:=spilltemp.offset;
+ tmpref.refaddr:=addr_high;
+ helplist.concat(taicpu.op_ref_reg(A_SETHI,tmpref,hreg));
+
+ tmpref.refaddr:=addr_low;
+ helplist.concat(taicpu.op_reg_ref_reg(A_OR,hreg,tmpref,hreg));
+
+ reference_reset_base(tmpref,hreg,0,sizeof(aint));
+ tmpref.index:=spilltemp.base;
+
+ helpins:=spilling_create_load(tmpref,tempreg);
+ helplist.concat(helpins);
+ list.insertlistafter(pos,helplist);
+ helplist.free;
+ end
+ else
+ inherited do_spill_read(list,pos,spilltemp,tempreg);
+ end;
+
+
+ procedure trgcpu.do_spill_written(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister);
+ var
+ tmpref : treference;
+ helplist : TAsmList;
+ hreg : tregister;
+ begin
+ if abs(spilltemp.offset)>4095 then
+ begin
+ helplist:=TAsmList.create;
+
+ if getregtype(tempreg)=R_INTREGISTER then
+ hreg:=getregisterinline(helplist,[R_SUBWHOLE])
+ else
+ hreg:=cg.getintregister(helplist,OS_ADDR);
+
+ reference_reset(tmpref,sizeof(aint));
+ tmpref.offset:=spilltemp.offset;
+ tmpref.refaddr:=addr_high;
+ helplist.concat(taicpu.op_ref_reg(A_SETHI,tmpref,hreg));
+
+ tmpref.refaddr:=addr_low;
+ helplist.concat(taicpu.op_reg_ref_reg(A_OR,hreg,tmpref,hreg));
+
+ reference_reset_base(tmpref,hreg,0,sizeof(aint));
+ tmpref.index:=spilltemp.base;
+
+ helplist.concat(spilling_create_store(tempreg,tmpref));
+ if getregtype(tempreg)=R_INTREGISTER then
+ ungetregisterinline(helplist,hreg);
+
+ list.insertlistafter(pos,helplist);
+ helplist.free;
+ end
+ else
+ inherited do_spill_written(list,pos,spilltemp,tempreg);
+ end;
+
+end.
diff --git a/closures/compiler/sparc/rspcon.inc b/closures/compiler/sparc/rspcon.inc
new file mode 100644
index 0000000000..5a84a0ba4e
--- /dev/null
+++ b/closures/compiler/sparc/rspcon.inc
@@ -0,0 +1,140 @@
+{ don't edit, this file is generated from spreg.dat }
+NR_NO = tregister($00000000);
+NR_G0 = tregister($01040000);
+NR_G1 = tregister($01040001);
+NR_G2 = tregister($01040002);
+NR_G3 = tregister($01040003);
+NR_G4 = tregister($01040004);
+NR_G5 = tregister($01040005);
+NR_G6 = tregister($01040006);
+NR_G7 = tregister($01040007);
+NR_O0 = tregister($01040008);
+NR_O1 = tregister($01040009);
+NR_O2 = tregister($0104000a);
+NR_O3 = tregister($0104000b);
+NR_O4 = tregister($0104000c);
+NR_O5 = tregister($0104000d);
+NR_O6 = tregister($0104000e);
+NR_O7 = tregister($0104000f);
+NR_L0 = tregister($01040010);
+NR_L1 = tregister($01040011);
+NR_L2 = tregister($01040012);
+NR_L3 = tregister($01040013);
+NR_L4 = tregister($01040014);
+NR_L5 = tregister($01040015);
+NR_L6 = tregister($01040016);
+NR_L7 = tregister($01040017);
+NR_I0 = tregister($01040018);
+NR_I1 = tregister($01040019);
+NR_I2 = tregister($0104001a);
+NR_I3 = tregister($0104001b);
+NR_I4 = tregister($0104001c);
+NR_I5 = tregister($0104001d);
+NR_I6 = tregister($0104001e);
+NR_I7 = tregister($0104001f);
+NR_FP = tregister($0104001e);
+NR_SP = tregister($0104000e);
+NR_F0 = tregister($02060000);
+NR_F1 = tregister($02060001);
+NR_F2 = tregister($02060002);
+NR_F3 = tregister($02060003);
+NR_F4 = tregister($02060004);
+NR_F5 = tregister($02060005);
+NR_F6 = tregister($02060006);
+NR_F7 = tregister($02060007);
+NR_F8 = tregister($02060008);
+NR_F9 = tregister($02060009);
+NR_F10 = tregister($0206000a);
+NR_F11 = tregister($0206000b);
+NR_F12 = tregister($0206000c);
+NR_F13 = tregister($0206000d);
+NR_F14 = tregister($0206000e);
+NR_F15 = tregister($0206000f);
+NR_F16 = tregister($02060010);
+NR_F17 = tregister($02060011);
+NR_F18 = tregister($02060012);
+NR_F19 = tregister($02060013);
+NR_F20 = tregister($02060014);
+NR_F21 = tregister($02060015);
+NR_F22 = tregister($02060016);
+NR_F23 = tregister($02060017);
+NR_F24 = tregister($02060018);
+NR_F25 = tregister($02060019);
+NR_F26 = tregister($0206001a);
+NR_F27 = tregister($0206001b);
+NR_F28 = tregister($0206001c);
+NR_F29 = tregister($0206001d);
+NR_F30 = tregister($0206001e);
+NR_F31 = tregister($0206001f);
+NR_C0 = tregister($03000000);
+NR_C1 = tregister($03000001);
+NR_C2 = tregister($03000002);
+NR_C3 = tregister($03000003);
+NR_C4 = tregister($03000004);
+NR_C5 = tregister($03000005);
+NR_C6 = tregister($03000006);
+NR_C7 = tregister($03000007);
+NR_C8 = tregister($03000008);
+NR_C9 = tregister($03000009);
+NR_C10 = tregister($0300000a);
+NR_C11 = tregister($0300000b);
+NR_C12 = tregister($0300000c);
+NR_C13 = tregister($0300000d);
+NR_C14 = tregister($0300000e);
+NR_C15 = tregister($0300000f);
+NR_C16 = tregister($03000010);
+NR_C17 = tregister($03000011);
+NR_C18 = tregister($03000012);
+NR_C19 = tregister($03000013);
+NR_C20 = tregister($03000014);
+NR_C21 = tregister($03000015);
+NR_C22 = tregister($03000016);
+NR_C23 = tregister($03000017);
+NR_C24 = tregister($03000018);
+NR_C25 = tregister($03000019);
+NR_C26 = tregister($0300001a);
+NR_C27 = tregister($0300001b);
+NR_C28 = tregister($0300001c);
+NR_C29 = tregister($0300001d);
+NR_C30 = tregister($0300001e);
+NR_C31 = tregister($0300001f);
+NR_FSR = tregister($05000000);
+NR_FQ = tregister($05000001);
+NR_CSR = tregister($05000002);
+NR_CQ = tregister($05000003);
+NR_PSR = tregister($05000004);
+NR_TBR = tregister($05000005);
+NR_WIM = tregister($05000006);
+NR_Y = tregister($05000007);
+NR_ASR0 = tregister($04000000);
+NR_ASR1 = tregister($04000001);
+NR_ASR2 = tregister($04000002);
+NR_ASR3 = tregister($04000003);
+NR_ASR4 = tregister($04000004);
+NR_ASR5 = tregister($04000005);
+NR_ASR6 = tregister($04000006);
+NR_ASR7 = tregister($04000007);
+NR_ASR8 = tregister($04000008);
+NR_ASR9 = tregister($04000009);
+NR_ASR10 = tregister($0400000a);
+NR_ASR11 = tregister($0400000b);
+NR_ASR12 = tregister($0400000c);
+NR_ASR13 = tregister($0400000d);
+NR_ASR14 = tregister($0400000e);
+NR_ASR15 = tregister($0400000f);
+NR_ASR16 = tregister($04000010);
+NR_ASR17 = tregister($04000011);
+NR_ASR18 = tregister($04000012);
+NR_ASR19 = tregister($04000013);
+NR_ASR20 = tregister($04000014);
+NR_ASR21 = tregister($04000015);
+NR_ASR22 = tregister($04000016);
+NR_ASR23 = tregister($04000017);
+NR_ASR24 = tregister($04000018);
+NR_ASR25 = tregister($04000019);
+NR_ASR26 = tregister($0400001a);
+NR_ASR27 = tregister($0400001b);
+NR_ASR28 = tregister($0400001c);
+NR_ASR29 = tregister($0400001d);
+NR_ASR30 = tregister($0400001e);
+NR_ASR31 = tregister($0400001f);
diff --git a/closures/compiler/sparc/rspdwrf.inc b/closures/compiler/sparc/rspdwrf.inc
new file mode 100644
index 0000000000..8bee9c4af9
--- /dev/null
+++ b/closures/compiler/sparc/rspdwrf.inc
@@ -0,0 +1,140 @@
+{ don't edit, this file is generated from spreg.dat }
+-1,
+0,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+8,
+9,
+10,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+20,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+31,
+30,
+14,
+32,
+33,
+34,
+35,
+36,
+37,
+38,
+39,
+40,
+41,
+42,
+43,
+44,
+45,
+46,
+47,
+48,
+49,
+50,
+51,
+52,
+53,
+54,
+55,
+56,
+57,
+58,
+59,
+60,
+61,
+62,
+63,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+70,
+65,
+71,
+65,
+65,
+67,
+66,
+64,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32
diff --git a/closures/compiler/sparc/rspnor.inc b/closures/compiler/sparc/rspnor.inc
new file mode 100644
index 0000000000..b6f96d936f
--- /dev/null
+++ b/closures/compiler/sparc/rspnor.inc
@@ -0,0 +1,2 @@
+{ don't edit, this file is generated from spreg.dat }
+139
diff --git a/closures/compiler/sparc/rspnum.inc b/closures/compiler/sparc/rspnum.inc
new file mode 100644
index 0000000000..b268537c8b
--- /dev/null
+++ b/closures/compiler/sparc/rspnum.inc
@@ -0,0 +1,140 @@
+{ don't edit, this file is generated from spreg.dat }
+NR_NO,
+NR_G0,
+NR_G1,
+NR_G2,
+NR_G3,
+NR_G4,
+NR_G5,
+NR_G6,
+NR_G7,
+NR_O0,
+NR_O1,
+NR_O2,
+NR_O3,
+NR_O4,
+NR_O5,
+NR_O6,
+NR_O7,
+NR_L0,
+NR_L1,
+NR_L2,
+NR_L3,
+NR_L4,
+NR_L5,
+NR_L6,
+NR_L7,
+NR_I0,
+NR_I1,
+NR_I2,
+NR_I3,
+NR_I4,
+NR_I5,
+NR_I6,
+NR_I7,
+NR_FP,
+NR_SP,
+NR_F0,
+NR_F1,
+NR_F2,
+NR_F3,
+NR_F4,
+NR_F5,
+NR_F6,
+NR_F7,
+NR_F8,
+NR_F9,
+NR_F10,
+NR_F11,
+NR_F12,
+NR_F13,
+NR_F14,
+NR_F15,
+NR_F16,
+NR_F17,
+NR_F18,
+NR_F19,
+NR_F20,
+NR_F21,
+NR_F22,
+NR_F23,
+NR_F24,
+NR_F25,
+NR_F26,
+NR_F27,
+NR_F28,
+NR_F29,
+NR_F30,
+NR_F31,
+NR_C0,
+NR_C1,
+NR_C2,
+NR_C3,
+NR_C4,
+NR_C5,
+NR_C6,
+NR_C7,
+NR_C8,
+NR_C9,
+NR_C10,
+NR_C11,
+NR_C12,
+NR_C13,
+NR_C14,
+NR_C15,
+NR_C16,
+NR_C17,
+NR_C18,
+NR_C19,
+NR_C20,
+NR_C21,
+NR_C22,
+NR_C23,
+NR_C24,
+NR_C25,
+NR_C26,
+NR_C27,
+NR_C28,
+NR_C29,
+NR_C30,
+NR_C31,
+NR_FSR,
+NR_FQ,
+NR_CSR,
+NR_CQ,
+NR_PSR,
+NR_TBR,
+NR_WIM,
+NR_Y,
+NR_ASR0,
+NR_ASR1,
+NR_ASR2,
+NR_ASR3,
+NR_ASR4,
+NR_ASR5,
+NR_ASR6,
+NR_ASR7,
+NR_ASR8,
+NR_ASR9,
+NR_ASR10,
+NR_ASR11,
+NR_ASR12,
+NR_ASR13,
+NR_ASR14,
+NR_ASR15,
+NR_ASR16,
+NR_ASR17,
+NR_ASR18,
+NR_ASR19,
+NR_ASR20,
+NR_ASR21,
+NR_ASR22,
+NR_ASR23,
+NR_ASR24,
+NR_ASR25,
+NR_ASR26,
+NR_ASR27,
+NR_ASR28,
+NR_ASR29,
+NR_ASR30,
+NR_ASR31
diff --git a/closures/compiler/sparc/rsprni.inc b/closures/compiler/sparc/rsprni.inc
new file mode 100644
index 0000000000..578709e2a8
--- /dev/null
+++ b/closures/compiler/sparc/rsprni.inc
@@ -0,0 +1,140 @@
+{ don't edit, this file is generated from spreg.dat }
+0,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+8,
+9,
+10,
+11,
+12,
+13,
+14,
+15,
+34,
+16,
+17,
+18,
+19,
+20,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+31,
+33,
+32,
+35,
+36,
+37,
+38,
+39,
+40,
+41,
+42,
+43,
+44,
+45,
+46,
+47,
+48,
+49,
+50,
+51,
+52,
+53,
+54,
+55,
+56,
+57,
+58,
+59,
+60,
+61,
+62,
+63,
+64,
+65,
+66,
+67,
+68,
+69,
+70,
+71,
+72,
+73,
+74,
+75,
+76,
+77,
+78,
+79,
+80,
+81,
+82,
+83,
+84,
+85,
+86,
+87,
+88,
+89,
+90,
+91,
+92,
+93,
+94,
+95,
+96,
+97,
+98,
+107,
+108,
+109,
+110,
+111,
+112,
+113,
+114,
+115,
+116,
+117,
+118,
+119,
+120,
+121,
+122,
+123,
+124,
+125,
+126,
+127,
+128,
+129,
+130,
+131,
+132,
+133,
+134,
+135,
+136,
+137,
+138,
+99,
+100,
+101,
+102,
+103,
+104,
+105,
+106
diff --git a/closures/compiler/sparc/rspsri.inc b/closures/compiler/sparc/rspsri.inc
new file mode 100644
index 0000000000..da5ec0a078
--- /dev/null
+++ b/closures/compiler/sparc/rspsri.inc
@@ -0,0 +1,140 @@
+{ don't edit, this file is generated from spreg.dat }
+107,
+108,
+117,
+118,
+119,
+120,
+121,
+122,
+123,
+124,
+125,
+126,
+109,
+127,
+128,
+129,
+130,
+131,
+132,
+133,
+134,
+135,
+136,
+110,
+137,
+138,
+111,
+112,
+113,
+114,
+115,
+116,
+67,
+68,
+77,
+78,
+79,
+80,
+81,
+82,
+83,
+84,
+85,
+86,
+69,
+87,
+88,
+89,
+90,
+91,
+92,
+93,
+94,
+95,
+96,
+70,
+97,
+98,
+71,
+72,
+73,
+74,
+75,
+76,
+102,
+101,
+35,
+36,
+45,
+46,
+47,
+48,
+49,
+50,
+51,
+52,
+53,
+54,
+37,
+55,
+56,
+57,
+58,
+59,
+60,
+61,
+62,
+63,
+64,
+38,
+65,
+66,
+39,
+40,
+41,
+42,
+43,
+44,
+33,
+100,
+99,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+8,
+25,
+26,
+27,
+28,
+29,
+30,
+31,
+32,
+17,
+18,
+19,
+20,
+21,
+22,
+23,
+24,
+9,
+10,
+11,
+12,
+13,
+14,
+15,
+16,
+103,
+34,
+104,
+105,
+106,
+0
diff --git a/closures/compiler/sparc/rspstab.inc b/closures/compiler/sparc/rspstab.inc
new file mode 100644
index 0000000000..8bee9c4af9
--- /dev/null
+++ b/closures/compiler/sparc/rspstab.inc
@@ -0,0 +1,140 @@
+{ don't edit, this file is generated from spreg.dat }
+-1,
+0,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+8,
+9,
+10,
+11,
+12,
+13,
+14,
+15,
+16,
+17,
+18,
+19,
+20,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+31,
+30,
+14,
+32,
+33,
+34,
+35,
+36,
+37,
+38,
+39,
+40,
+41,
+42,
+43,
+44,
+45,
+46,
+47,
+48,
+49,
+50,
+51,
+52,
+53,
+54,
+55,
+56,
+57,
+58,
+59,
+60,
+61,
+62,
+63,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+70,
+65,
+71,
+65,
+65,
+67,
+66,
+64,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32,
+32
diff --git a/closures/compiler/sparc/rspstd.inc b/closures/compiler/sparc/rspstd.inc
new file mode 100644
index 0000000000..189ed36a2f
--- /dev/null
+++ b/closures/compiler/sparc/rspstd.inc
@@ -0,0 +1,140 @@
+{ don't edit, this file is generated from spreg.dat }
+'INVALID',
+'%g0',
+'%g1',
+'%g2',
+'%g3',
+'%g4',
+'%g5',
+'%g6',
+'%g7',
+'%o0',
+'%o1',
+'%o2',
+'%o3',
+'%o4',
+'%o5',
+'%o6',
+'%o7',
+'%l0',
+'%l1',
+'%l2',
+'%l3',
+'%l4',
+'%l5',
+'%l6',
+'%l7',
+'%i0',
+'%i1',
+'%i2',
+'%i3',
+'%i4',
+'%i5',
+'%i6',
+'%i7',
+'%fp',
+'%sp',
+'%f0',
+'%f1',
+'%f2',
+'%f3',
+'%f4',
+'%f5',
+'%f6',
+'%f7',
+'%f8',
+'%f9',
+'%f10',
+'%f11',
+'%f12',
+'%f13',
+'%f14',
+'%f15',
+'%f16',
+'%f17',
+'%f18',
+'%f19',
+'%f20',
+'%f21',
+'%f22',
+'%f23',
+'%f24',
+'%f25',
+'%f26',
+'%f27',
+'%f28',
+'%f29',
+'%f30',
+'%f31',
+'%c0',
+'%c1',
+'%c2',
+'%c3',
+'%c4',
+'%c5',
+'%c6',
+'%c7',
+'%c8',
+'%c9',
+'%c10',
+'%c11',
+'%c12',
+'%c13',
+'%c14',
+'%c15',
+'%c16',
+'%c17',
+'%c18',
+'%c19',
+'%c20',
+'%c21',
+'%c22',
+'%c23',
+'%c24',
+'%c25',
+'%c26',
+'%c27',
+'%c28',
+'%c29',
+'%c30',
+'%c31',
+'%fsr',
+'%fq',
+'%csr',
+'%cq',
+'%psr',
+'%tbr',
+'%wim',
+'%y',
+'%asr0',
+'%asr1',
+'%asr2',
+'%asr3',
+'%asr4',
+'%asr5',
+'%asr6',
+'%asr7',
+'%asr8',
+'%asr9',
+'%asr10',
+'%asr11',
+'%asr12',
+'%asr13',
+'%asr14',
+'%asr15',
+'%asr16',
+'%asr17',
+'%asr18',
+'%asr19',
+'%asr20',
+'%asr21',
+'%asr22',
+'%asr23',
+'%asr24',
+'%asr25',
+'%asr26',
+'%asr27',
+'%asr28',
+'%asr29',
+'%asr30',
+'%asr31'
diff --git a/closures/compiler/sparc/rspsup.inc b/closures/compiler/sparc/rspsup.inc
new file mode 100644
index 0000000000..68600f52a6
--- /dev/null
+++ b/closures/compiler/sparc/rspsup.inc
@@ -0,0 +1,140 @@
+{ don't edit, this file is generated from spreg.dat }
+RS_NO = $00;
+RS_G0 = $00;
+RS_G1 = $01;
+RS_G2 = $02;
+RS_G3 = $03;
+RS_G4 = $04;
+RS_G5 = $05;
+RS_G6 = $06;
+RS_G7 = $07;
+RS_O0 = $08;
+RS_O1 = $09;
+RS_O2 = $0a;
+RS_O3 = $0b;
+RS_O4 = $0c;
+RS_O5 = $0d;
+RS_O6 = $0e;
+RS_O7 = $0f;
+RS_L0 = $10;
+RS_L1 = $11;
+RS_L2 = $12;
+RS_L3 = $13;
+RS_L4 = $14;
+RS_L5 = $15;
+RS_L6 = $16;
+RS_L7 = $17;
+RS_I0 = $18;
+RS_I1 = $19;
+RS_I2 = $1a;
+RS_I3 = $1b;
+RS_I4 = $1c;
+RS_I5 = $1d;
+RS_I6 = $1e;
+RS_I7 = $1f;
+RS_FP = $1e;
+RS_SP = $0e;
+RS_F0 = $00;
+RS_F1 = $01;
+RS_F2 = $02;
+RS_F3 = $03;
+RS_F4 = $04;
+RS_F5 = $05;
+RS_F6 = $06;
+RS_F7 = $07;
+RS_F8 = $08;
+RS_F9 = $09;
+RS_F10 = $0a;
+RS_F11 = $0b;
+RS_F12 = $0c;
+RS_F13 = $0d;
+RS_F14 = $0e;
+RS_F15 = $0f;
+RS_F16 = $10;
+RS_F17 = $11;
+RS_F18 = $12;
+RS_F19 = $13;
+RS_F20 = $14;
+RS_F21 = $15;
+RS_F22 = $16;
+RS_F23 = $17;
+RS_F24 = $18;
+RS_F25 = $19;
+RS_F26 = $1a;
+RS_F27 = $1b;
+RS_F28 = $1c;
+RS_F29 = $1d;
+RS_F30 = $1e;
+RS_F31 = $1f;
+RS_C0 = $00;
+RS_C1 = $01;
+RS_C2 = $02;
+RS_C3 = $03;
+RS_C4 = $04;
+RS_C5 = $05;
+RS_C6 = $06;
+RS_C7 = $07;
+RS_C8 = $08;
+RS_C9 = $09;
+RS_C10 = $0a;
+RS_C11 = $0b;
+RS_C12 = $0c;
+RS_C13 = $0d;
+RS_C14 = $0e;
+RS_C15 = $0f;
+RS_C16 = $10;
+RS_C17 = $11;
+RS_C18 = $12;
+RS_C19 = $13;
+RS_C20 = $14;
+RS_C21 = $15;
+RS_C22 = $16;
+RS_C23 = $17;
+RS_C24 = $18;
+RS_C25 = $19;
+RS_C26 = $1a;
+RS_C27 = $1b;
+RS_C28 = $1c;
+RS_C29 = $1d;
+RS_C30 = $1e;
+RS_C31 = $1f;
+RS_FSR = $00;
+RS_FQ = $01;
+RS_CSR = $02;
+RS_CQ = $03;
+RS_PSR = $04;
+RS_TBR = $05;
+RS_WIM = $06;
+RS_Y = $07;
+RS_ASR0 = $00;
+RS_ASR1 = $01;
+RS_ASR2 = $02;
+RS_ASR3 = $03;
+RS_ASR4 = $04;
+RS_ASR5 = $05;
+RS_ASR6 = $06;
+RS_ASR7 = $07;
+RS_ASR8 = $08;
+RS_ASR9 = $09;
+RS_ASR10 = $0a;
+RS_ASR11 = $0b;
+RS_ASR12 = $0c;
+RS_ASR13 = $0d;
+RS_ASR14 = $0e;
+RS_ASR15 = $0f;
+RS_ASR16 = $10;
+RS_ASR17 = $11;
+RS_ASR18 = $12;
+RS_ASR19 = $13;
+RS_ASR20 = $14;
+RS_ASR21 = $15;
+RS_ASR22 = $16;
+RS_ASR23 = $17;
+RS_ASR24 = $18;
+RS_ASR25 = $19;
+RS_ASR26 = $1a;
+RS_ASR27 = $1b;
+RS_ASR28 = $1c;
+RS_ASR29 = $1d;
+RS_ASR30 = $1e;
+RS_ASR31 = $1f;
diff --git a/closures/compiler/sparc/spreg.dat b/closures/compiler/sparc/spreg.dat
new file mode 100644
index 0000000000..45b03fb046
--- /dev/null
+++ b/closures/compiler/sparc/spreg.dat
@@ -0,0 +1,173 @@
+;
+; Sparc registers
+;
+; layout
+; <name>,<regtype>,<regnum>,<stdname>,<stabidx>,<dwarfidx>
+;
+NO,$00,$00,$00,INVALID,-1,-1
+; Integer registers
+G0,$01,$04,$00,%g0,0,0
+G1,$01,$04,$01,%g1,1,1
+G2,$01,$04,$02,%g2,2,2
+G3,$01,$04,$03,%g3,3,3
+G4,$01,$04,$04,%g4,4,4
+G5,$01,$04,$05,%g5,5,5
+G6,$01,$04,$06,%g6,6,6
+G7,$01,$04,$07,%g7,7,7
+O0,$01,$04,$08,%o0,8,8
+O1,$01,$04,$09,%o1,9,9
+O2,$01,$04,$0a,%o2,10,10
+O3,$01,$04,$0b,%o3,11,11
+O4,$01,$04,$0c,%o4,12,12
+O5,$01,$04,$0d,%o5,13,13
+O6,$01,$04,$0e,%o6,14,14
+O7,$01,$04,$0f,%o7,15,15
+L0,$01,$04,$10,%l0,16,16
+L1,$01,$04,$11,%l1,17,17
+L2,$01,$04,$12,%l2,18,18
+L3,$01,$04,$13,%l3,19,19
+L4,$01,$04,$14,%l4,20,20
+L5,$01,$04,$15,%l5,21,21
+L6,$01,$04,$16,%l6,22,22
+L7,$01,$04,$17,%l7,23,23
+I0,$01,$04,$18,%i0,24,24
+I1,$01,$04,$19,%i1,25,25
+I2,$01,$04,$1a,%i2,26,26
+I3,$01,$04,$1b,%i3,27,27
+I4,$01,$04,$1c,%i4,28,28
+I5,$01,$04,$1d,%i5,29,29
+I6,$01,$04,$1e,%i6,30,30
+I7,$01,$04,$1f,%i7,31,31
+; Aliases for stackpointer (%o6) and framepointer (%i6)
+FP,$01,$04,$1e,%fp,30,30
+SP,$01,$04,$0e,%sp,14,14
+; Float registers, single use
+F0,$02,$06,$00,%f0,32,32
+F1,$02,$06,$01,%f1,33,33
+F2,$02,$06,$02,%f2,34,34
+F3,$02,$06,$03,%f3,35,35
+F4,$02,$06,$04,%f4,36,36
+F5,$02,$06,$05,%f5,37,37
+F6,$02,$06,$06,%f6,38,38
+F7,$02,$06,$07,%f7,39,39
+F8,$02,$06,$08,%f8,40,40
+F9,$02,$06,$09,%f9,41,41
+F10,$02,$06,$0a,%f10,42,42
+F11,$02,$06,$0b,%f11,43,43
+F12,$02,$06,$0c,%f12,44,44
+F13,$02,$06,$0d,%f13,45,45
+F14,$02,$06,$0e,%f14,46,46
+F15,$02,$06,$0f,%f15,47,47
+F16,$02,$06,$10,%f16,48,48
+F17,$02,$06,$11,%f17,49,49
+F18,$02,$06,$12,%f18,50,50
+F19,$02,$06,$13,%f19,51,51
+F20,$02,$06,$14,%f20,52,52
+F21,$02,$06,$15,%f21,53,53
+F22,$02,$06,$16,%f22,54,54
+F23,$02,$06,$17,%f23,55,55
+F24,$02,$06,$18,%f24,56,56
+F25,$02,$06,$19,%f25,57,57
+F26,$02,$06,$1a,%f26,58,58
+F27,$02,$06,$1b,%f27,59,59
+F28,$02,$06,$1c,%f28,60,60
+F29,$02,$06,$1d,%f29,61,61
+F30,$02,$06,$1e,%f30,62,62
+F31,$02,$06,$1f,%f31,63,63
+; Float registers, double use
+; Not enabled for now Pierre
+; D0,$02,$07,$00,%d0,72,72
+; D2,$02,$07,$02,%d2,73,73
+; D4,$02,$07,$04,%d4,74,74
+; D6,$02,$07,$06,%d6,75,75
+; D8,$02,$07,$08,%d8,76,76
+; D10,$02,$07,$0a,%d10,77,77
+; D12,$02,$07,$0c,%d12,78,78
+; D14,$02,$07,$0e,%d14,79,79
+; D16,$02,$07,$10,%d16,80,80
+; D18,$02,$07,$12,%d18,81,81
+; D20,$02,$07,$14,%d20,82,82
+; D22,$02,$07,$16,%d22,83,83
+; D24,$02,$07,$18,%d24,84,84
+; D26,$02,$07,$1a,%d26,85,85
+; D28,$02,$07,$1c,%d28,86,86
+; D30,$02,$07,$1e,%d30,87,87
+
+
+; Coprocessor registers
+C0,$03,$00,$00,%c0,32,32
+C1,$03,$00,$01,%c1,32,32
+C2,$03,$00,$02,%c2,32,32
+C3,$03,$00,$03,%c3,32,32
+C4,$03,$00,$04,%c4,32,32
+C5,$03,$00,$05,%c5,32,32
+C6,$03,$00,$06,%c6,32,32
+C7,$03,$00,$07,%c7,32,32
+C8,$03,$00,$08,%c8,32,32
+C9,$03,$00,$09,%c9,32,32
+C10,$03,$00,$0a,%c10,32,32
+C11,$03,$00,$0b,%c11,32,32
+C12,$03,$00,$0c,%c12,32,32
+C13,$03,$00,$0d,%c13,32,32
+C14,$03,$00,$0e,%c14,32,32
+C15,$03,$00,$0f,%c15,32,32
+C16,$03,$00,$10,%c16,32,32
+C17,$03,$00,$11,%c17,32,32
+C18,$03,$00,$12,%c18,32,32
+C19,$03,$00,$13,%c19,32,32
+C20,$03,$00,$14,%c20,32,32
+C21,$03,$00,$15,%c21,32,32
+C22,$03,$00,$16,%c22,32,32
+C23,$03,$00,$17,%c23,32,32
+C24,$03,$00,$18,%c24,32,32
+C25,$03,$00,$19,%c25,32,32
+C26,$03,$00,$1a,%c26,32,32
+C27,$03,$00,$1b,%c27,32,32
+C28,$03,$00,$1c,%c28,32,32
+C29,$03,$00,$1d,%c29,32,32
+C30,$03,$00,$1e,%c30,32,32
+C31,$03,$00,$1f,%c31,32,32
+
+; Special registers
+FSR,$05,$00,$00,%fsr,70,70
+FQ,$05,$00,$01,%fq,65,65
+CSR,$05,$00,$02,%csr,71,71
+CQ,$05,$00,$03,%cq,65,65
+PSR,$05,$00,$04,%psr,65,65
+TBR,$05,$00,$05,%tbr,67,67
+WIM,$05,$00,$06,%wim,66,66
+Y,$05,$00,$07,%y,64,64
+
+; Ancillary State Registers
+ASR0,$04,$00,$00,%asr0,32,32
+ASR1,$04,$00,$01,%asr1,32,32
+ASR2,$04,$00,$02,%asr2,32,32
+ASR3,$04,$00,$03,%asr3,32,32
+ASR4,$04,$00,$04,%asr4,32,32
+ASR5,$04,$00,$05,%asr5,32,32
+ASR6,$04,$00,$06,%asr6,32,32
+ASR7,$04,$00,$07,%asr7,32,32
+ASR8,$04,$00,$08,%asr8,32,32
+ASR9,$04,$00,$09,%asr9,32,32
+ASR10,$04,$00,$0a,%asr10,32,32
+ASR11,$04,$00,$0b,%asr11,32,32
+ASR12,$04,$00,$0c,%asr12,32,32
+ASR13,$04,$00,$0d,%asr13,32,32
+ASR14,$04,$00,$0e,%asr14,32,32
+ASR15,$04,$00,$0f,%asr15,32,32
+ASR16,$04,$00,$10,%asr16,32,32
+ASR17,$04,$00,$11,%asr17,32,32
+ASR18,$04,$00,$12,%asr18,32,32
+ASR19,$04,$00,$13,%asr19,32,32
+ASR20,$04,$00,$14,%asr20,32,32
+ASR21,$04,$00,$15,%asr21,32,32
+ASR22,$04,$00,$16,%asr22,32,32
+ASR23,$04,$00,$17,%asr23,32,32
+ASR24,$04,$00,$18,%asr24,32,32
+ASR25,$04,$00,$19,%asr25,32,32
+ASR26,$04,$00,$1a,%asr26,32,32
+ASR27,$04,$00,$1b,%asr27,32,32
+ASR28,$04,$00,$1c,%asr28,32,32
+ASR29,$04,$00,$1d,%asr29,32,32
+ASR30,$04,$00,$1e,%asr30,32,32
+ASR31,$04,$00,$1f,%asr31,32,32
diff --git a/closures/compiler/sparc/strinst.inc b/closures/compiler/sparc/strinst.inc
new file mode 100644
index 0000000000..2728e33b0a
--- /dev/null
+++ b/closures/compiler/sparc/strinst.inc
@@ -0,0 +1,72 @@
+{******************************************************************************
+ *****************************************************************************}
+ 'none',
+ 'abcd',
+ 'add','addcc','addx','addxcc',
+ 'and','andcc','andn','andncc',
+ 'jmp',
+ 'jmpl',
+ 'call',
+ 'ba','b','fba','fb',
+ 'cbccc',
+ 'flush',
+ 'ldsb','ldsh','ldstub',
+ 'ldub','lduh','ld','ldd','ld','ldfsr','ldd','ldc','ldcsr','lddc',
+ 'ldsba','ldsha','lduba','lduha','lda','ldda',
+ 'ldstuba',
+ 'mulscc',
+ 'nop',
+ 'or','orcc','orn','orncc',
+ 'rd','rd','rd','rd','rd',
+ 'restore',
+ 'ret','retl',
+ 'save',
+ 'sdiv','sdivcc',
+ 'smul','smulcc',
+ 'sethi',
+ 'sll','srl','sra',
+ 'stb','sth','st','std','st','std','stfsr','stdfq',
+ 'stc','stdc','stcsr','stdcq',
+ 'stba','stha','sta','stda',
+ 'sub','subcc','subx','subxcc',
+ 'swap','swapa','ticc','taddcc','tsubcc','taddcctv','tsubcctv',
+ 'ta','t',
+ 'udiv','udivcc',
+ 'umul','umulcc',
+ 'unimp',
+ 'wrasr','wry','wrpsr','wrwim','wrtbr',
+ 'xnor','xnorcc',
+ 'xor','xorcc',
+ {floating-point instructions}
+ 'fitos','fitod','fitoq',
+ 'fstoi','fdtoi','fqtoi',
+ 'fstod','fstoq',
+ 'fdtos','fdtoq',
+ 'fqtod','fqtos',
+ 'fmovs','fnegs','fabss',
+ 'fsqrts','fsqrtd','fsqrtq',
+ 'fadds','faddd','faddq',
+ 'fsubs','fsubd','fsubq',
+ 'fmuls','fmuld','fmulq',
+ 'fdmulq','fsmuld',
+ 'fdivs','fdivd','fdivq',
+ 'fcmps','fcmpd','fcmpq',
+ 'fcpop1','cpop2',
+ {synthetic instructions}
+ 'btst','bset','bclr','btog',
+ 'clr','clrb','clrh',
+ 'cmp',
+ 'dec','deccc',
+ 'inc','inccc',
+ 'mov',
+ 'neg',
+ 'not',
+ 'set',
+ 'skipz','skipnz',
+ 'tst',
+ { internal instructions }
+ 'fmovd',
+ 'fabsd','fabsq',
+ { memory barrier instructions }
+ 'stbar',
+ 'membar'
diff --git a/closures/compiler/switches.pas b/closures/compiler/switches.pas
new file mode 100644
index 0000000000..5dc58c8ce2
--- /dev/null
+++ b/closures/compiler/switches.pas
@@ -0,0 +1,369 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ This unit implements the parsing of the switches like $I-
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit switches;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ globtype;
+
+procedure HandleSwitch(switch,state:char);
+function CheckSwitch(switch,state:char):boolean;
+
+procedure recordpendingverbosityswitch(sw: char; state: char);
+procedure recordpendingmessagestate(msg: longint; state: tmsgstate);
+procedure recordpendinglocalswitch(sw: tlocalswitch; state: char);
+procedure recordpendinglocalfullswitch(const switches: tlocalswitches);
+procedure recordpendingverbosityfullswitch(verbosity: longint);
+procedure recordpendingcallingswitch(const str: shortstring);
+procedure flushpendingswitchesstate;
+
+implementation
+uses
+ systems,cpuinfo,
+ globals,verbose,comphook,
+ fmodule;
+
+{****************************************************************************
+ Main Switches Parsing
+****************************************************************************}
+
+type
+ TSwitchType=(ignoredsw,localsw,modulesw,globalsw,illegalsw,unsupportedsw,alignsw,optimizersw,packenumsw,pentiumfdivsw);
+ SwitchRec=record
+ typesw : TSwitchType;
+ setsw : byte;
+ end;
+ SwitchRecTable = array['A'..'Z'] of SwitchRec;
+
+const
+ turboSwitchTable: SwitchRecTable =(
+ {A} (typesw:alignsw; setsw:ord(cs_localnone)),
+ {B} (typesw:localsw; setsw:ord(cs_full_boolean_eval)),
+ {C} (typesw:localsw; setsw:ord(cs_do_assertion)),
+ {D} (typesw:modulesw; setsw:ord(cs_debuginfo)),
+ {E} (typesw:modulesw; setsw:ord(cs_fp_emulation)),
+ {F} (typesw:ignoredsw; setsw:ord(cs_localnone)),
+ {G} (typesw:ignoredsw; setsw:ord(cs_localnone)),
+ {H} (typesw:localsw; setsw:ord(cs_ansistrings)),
+ {I} (typesw:localsw; setsw:ord(cs_check_io)),
+ {J} (typesw:localsw; setsw:ord(cs_typed_const_writable)),
+ {K} (typesw:unsupportedsw; setsw:ord(cs_localnone)),
+ {L} (typesw:unsupportedsw; setsw:ord(cs_localnone)),
+ {M} (typesw:localsw; setsw:ord(cs_generate_rtti)),
+ {N} (typesw:unsupportedsw; setsw:ord(cs_localnone)),
+ {O} (typesw:optimizersw; setsw:ord(cs_opt_none)),
+ {P} (typesw:modulesw; setsw:ord(cs_openstring)),
+ {Q} (typesw:localsw; setsw:ord(cs_check_overflow)),
+ {R} (typesw:localsw; setsw:ord(cs_check_range)),
+ {S} (typesw:localsw; setsw:ord(cs_check_stack)),
+ {T} (typesw:localsw; setsw:ord(cs_typed_addresses)),
+ {U} (typesw:pentiumfdivsw; setsw:ord(cs_localnone)),
+ {V} (typesw:localsw; setsw:ord(cs_strict_var_strings)),
+ {W} (typesw:localsw; setsw:ord(cs_generate_stackframes)),
+ {X} (typesw:modulesw; setsw:ord(cs_extsyntax)),
+ {Y} (typesw:unsupportedsw; setsw:ord(cs_localnone)),
+ {Z} (typesw:packenumsw; setsw:ord(cs_localnone))
+ );
+
+
+ macSwitchTable: SwitchRecTable =(
+ {A} (typesw:unsupportedsw; setsw:ord(cs_localnone)),
+ {B} (typesw:localsw; setsw:ord(cs_full_boolean_eval)),
+ {C} (typesw:localsw; setsw:ord(cs_do_assertion)),
+ {D} (typesw:modulesw; setsw:ord(cs_debuginfo)),
+ {E} (typesw:modulesw; setsw:ord(cs_fp_emulation)),
+ {F} (typesw:ignoredsw; setsw:ord(cs_localnone)),
+ {G} (typesw:ignoredsw; setsw:ord(cs_localnone)),
+ {H} (typesw:localsw; setsw:ord(cs_ansistrings)),
+ {I} (typesw:localsw; setsw:ord(cs_check_io)),
+ {J} (typesw:localsw; setsw:ord(cs_external_var)),
+ {K} (typesw:unsupportedsw; setsw:ord(cs_localnone)),
+ {L} (typesw:unsupportedsw; setsw:ord(cs_localnone)),
+ {M} (typesw:localsw; setsw:ord(cs_generate_rtti)),
+ {N} (typesw:unsupportedsw; setsw:ord(cs_localnone)),
+ {O} (typesw:optimizersw; setsw:ord(cs_opt_none)),
+ {P} (typesw:modulesw; setsw:ord(cs_openstring)),
+ {Q} (typesw:localsw; setsw:ord(cs_check_overflow)),
+ {R} (typesw:localsw; setsw:ord(cs_check_range)),
+ {S} (typesw:localsw; setsw:ord(cs_check_stack)),
+ {T} (typesw:localsw; setsw:ord(cs_typed_addresses)),
+ {U} (typesw:illegalsw; setsw:ord(cs_localnone)),
+ {V} (typesw:localsw; setsw:ord(cs_strict_var_strings)),
+ {W} (typesw:localsw; setsw:ord(cs_generate_stackframes)),
+ {X} (typesw:modulesw; setsw:ord(cs_extsyntax)),
+ {Y} (typesw:unsupportedsw; setsw:ord(cs_localnone)),
+ {Z} (typesw:localsw; setsw:ord(cs_externally_visible))
+ );
+
+procedure HandleSwitch(switch,state:char);
+
+var
+ switchTablePtr: ^SwitchRecTable;
+
+begin
+ switch:=upcase(switch);
+{ Is the Switch in the letters ? }
+ if not ((switch in ['A'..'Z']) and (state in ['-','+'])) then
+ begin
+ Message(scan_w_illegal_switch);
+ exit;
+ end;
+
+{ Select switch table }
+ if m_mac in current_settings.modeswitches then
+ switchTablePtr:= @macSwitchTable
+ else
+ switchTablePtr:= @turboSwitchTable;
+
+{ Handle the switch }
+ with switchTablePtr^[switch] do
+ begin
+ case typesw of
+ alignsw:
+ if state='+' then
+ current_settings.packrecords:=4
+ else
+ current_settings.packrecords:=1;
+ optimizersw :
+ begin
+ if state='+' then
+ current_settings.optimizerswitches:=level2optimizerswitches
+ else
+ current_settings.optimizerswitches:=[];
+ end;
+ ignoredsw :
+ Message1(scan_n_ignored_switch,'$'+switch);
+ illegalsw :
+ Message1(scan_w_illegal_switch,'$'+switch);
+ unsupportedsw :
+ Message1(scan_w_unsupported_switch,'$'+switch);
+ localsw :
+ recordpendinglocalswitch(tlocalswitch(setsw),state);
+ modulesw :
+ begin
+ if current_module.in_global then
+ begin
+{$ifndef cpufpemu}
+ if tmoduleswitch(setsw)=cs_fp_emulation then
+ begin
+ Message1(scan_w_unsupported_switch_by_target,'$'+switch);
+ end
+ else
+{$endif cpufpemu}
+ begin
+ if state='+' then
+ include(current_settings.moduleswitches,tmoduleswitch(setsw))
+ else
+ begin
+ { Turning off debuginfo when lineinfo is requested
+ is not possible }
+ if not((cs_use_lineinfo in current_settings.globalswitches) and
+ (tmoduleswitch(setsw)=cs_debuginfo)) then
+ exclude(current_settings.moduleswitches,tmoduleswitch(setsw));
+ end;
+ end;
+ end
+ else
+ Message(scan_w_switch_is_global);
+ end;
+ globalsw :
+ begin
+ if current_module.in_global and (current_module=main_module) then
+ begin
+ if state='+' then
+ include(current_settings.globalswitches,tglobalswitch(setsw))
+ else
+ exclude(current_settings.globalswitches,tglobalswitch(setsw));
+ end
+ else
+ Message(scan_w_switch_is_global);
+ end;
+ packenumsw:
+ begin
+ if state='-' then
+ current_settings.packenum:=1
+ else
+ current_settings.packenum:=4;
+ end;
+ pentiumfdivsw:
+ begin
+ { Switch u- means pentium-safe fdiv off -> fpc default. We don't }
+ { support u+ }
+ if state='+' then
+ Message1(scan_w_unsupported_switch,'$'+switch);
+ end;
+ end;
+ end;
+end;
+
+
+function CheckSwitch(switch,state:char):boolean;
+
+var
+ found : boolean;
+ switchTablePtr: ^SwitchRecTable;
+
+begin
+ switch:=upcase(switch);
+{ Is the Switch in the letters ? }
+ if not ((switch in ['A'..'Z']) and (state in ['-','+'])) then
+ begin
+ Message(scan_w_illegal_switch);
+ CheckSwitch:=false;
+ exit;
+ end;
+
+{ Select switch table }
+ if m_mac in current_settings.modeswitches then
+ switchTablePtr:= @macSwitchTable
+ else
+ switchTablePtr:= @turboSwitchTable;
+
+{ Check the switch }
+ with switchTablePtr^[switch] do
+ begin
+ case typesw of
+ localsw : found:=(tlocalswitch(setsw) in current_settings.localswitches);
+ modulesw : found:=(tmoduleswitch(setsw) in current_settings.moduleswitches);
+ globalsw : found:=(tglobalswitch(setsw) in current_settings.globalswitches);
+ packenumsw : found := (current_settings.packenum = 4);
+ else
+ found:=false;
+ end;
+ if state='-' then
+ found:=not found;
+ CheckSwitch:=found;
+ end;
+end;
+
+
+procedure recordpendingverbosityswitch(sw: char; state: char);
+ begin
+ pendingstate.nextverbositystr:=pendingstate.nextverbositystr+sw+state;
+ end;
+
+procedure recordpendingmessagestate(msg: longint; state: tmsgstate);
+ var
+ pstate : pmessagestaterecord;
+ begin
+ new(pstate);
+ pstate^.next:=pendingstate.nextmessagerecord;
+ pstate^.value:=msg;
+ pstate^.state:=state;
+ pendingstate.nextmessagerecord:=pstate;
+ end;
+
+procedure recordpendinglocalswitch(sw: tlocalswitch; state: char);
+ begin
+ if not pendingstate.localswitcheschanged then
+ pendingstate.nextlocalswitches:=current_settings.localswitches;
+ if state='-' then
+ exclude(pendingstate.nextlocalswitches,sw)
+ else if state='+' then
+ include(pendingstate.nextlocalswitches,sw)
+ else { state = '*' }
+ begin
+ if sw in init_settings.localswitches then
+ include(pendingstate.nextlocalswitches,sw)
+ else
+ exclude(pendingstate.nextlocalswitches,sw);
+ end;
+ pendingstate.localswitcheschanged:=true;
+ end;
+
+
+procedure recordpendinglocalfullswitch(const switches: tlocalswitches);
+ begin
+ pendingstate.nextlocalswitches:=switches;
+ pendingstate.localswitcheschanged:=true;
+ end;
+
+
+procedure recordpendingverbosityfullswitch(verbosity: longint);
+ begin
+ pendingstate.nextverbositystr:='';
+ pendingstate.nextverbosityfullswitch:=verbosity;
+ pendingstate.verbosityfullswitched:=true;
+ end;
+
+procedure recordpendingcallingswitch(const str: shortstring);
+ begin
+ pendingstate.nextcallingstr:=str;
+ end;
+
+
+procedure flushpendingswitchesstate;
+ var
+ tmpproccal: tproccalloption;
+ fstate, pstate : pmessagestaterecord;
+ begin
+ { process pending localswitches (range checking, etc) }
+ if pendingstate.localswitcheschanged then
+ begin
+ current_settings.localswitches:=pendingstate.nextlocalswitches;
+ pendingstate.localswitcheschanged:=false;
+ end;
+ { process pending verbosity changes (warnings on, etc) }
+ if pendingstate.verbosityfullswitched then
+ begin
+ status.verbosity:=pendingstate.nextverbosityfullswitch;
+ pendingstate.verbosityfullswitched:=false;
+ end;
+ if pendingstate.nextverbositystr<>'' then
+ begin
+ setverbosity(pendingstate.nextverbositystr);
+ pendingstate.nextverbositystr:='';
+ end;
+ fstate:=pendingstate.nextmessagerecord;
+ pstate:=pendingstate.nextmessagerecord;
+ while assigned(pstate) do
+ begin
+ pendingstate.nextmessagerecord:=pstate^.next;
+ SetMessageVerbosity(pstate^.value,pstate^.state);
+ if not assigned(pstate^.next) then
+ begin
+ pstate^.next:=current_settings.pmessage;
+ current_settings.pmessage:=fstate;
+ pstate:=nil;
+ end
+ else
+ pstate:=pstate^.next;
+ pendingstate.nextmessagerecord:=nil;
+ end;
+ { process pending calling convention changes (calling x) }
+ if pendingstate.nextcallingstr<>'' then
+ begin
+ if not SetAktProcCall(pendingstate.nextcallingstr,tmpproccal) then
+ Message1(parser_w_unknown_proc_directive_ignored,pendingstate.nextcallingstr)
+ else if not(tmpproccal in supported_calling_conventions) then
+ Message1(parser_e_illegal_calling_convention,pendingstate.nextcallingstr)
+ else
+ current_settings.defproccall:=tmpproccal;
+ pendingstate.nextcallingstr:='';
+ end;
+ end;
+
+
+end.
diff --git a/closures/compiler/symbase.pas b/closures/compiler/symbase.pas
new file mode 100644
index 0000000000..bb984dc350
--- /dev/null
+++ b/closures/compiler/symbase.pas
@@ -0,0 +1,441 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl, Pierre Muller
+
+ This unit handles the symbol tables
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ ****************************************************************************
+}
+unit symbase;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ { common }
+ cutils,cclasses,
+ { global }
+ globtype,globals,
+ { symtable }
+ symconst
+ ;
+
+{************************************************
+ Needed forward pointers
+************************************************}
+
+ type
+ TSymtable = class;
+
+ { THashedIDString }
+
+ THashedIDString=object
+ private
+ FId : TIDString;
+ FHash : Longword;
+ procedure SetId(const s:TIDString);
+ public
+ property Id:TIDString read FId write SetId;
+ property Hash:longword read FHash;
+ end;
+
+
+{************************************************
+ TDefEntry
+************************************************}
+
+ TDefEntry = class
+ typ : tdeftyp;
+ defid : longint;
+ owner : TSymtable;
+ end;
+
+
+{************************************************
+ TSymEntry
+************************************************}
+
+ { this object is the base for all symbol objects }
+ TSymEntry = class(TFPHashObject)
+ private
+ FRealName : pshortstring;
+ function GetRealname:shortstring;
+ procedure SetRealname(const ANewName:shortstring);
+ public
+ typ : tsymtyp;
+ SymId : longint;
+ Owner : TSymtable;
+ destructor destroy;override;
+ property RealName:shortstring read GetRealName write SetRealName;
+ end;
+
+{************************************************
+ TSymtable
+************************************************}
+
+ TSymtable = class
+ public
+ name : pshortstring;
+ realname : pshortstring;
+ DefList : TFPObjectList;
+ SymList : TFPHashObjectList;
+ defowner : TDefEntry; { for records and objects }
+ moduleid : longint;
+ refcount : smallint;
+ currentvisibility : tvisibility;
+ currentlyoptional : boolean;
+ tableoptions : tsymtableoptions;
+ { level of symtable, used for nested procedures }
+ symtablelevel : byte;
+ symtabletype : TSymtabletype;
+ constructor Create(const s:string);
+ destructor destroy;override;
+ procedure freeinstance;override;
+ function getcopy:TSymtable;
+ procedure clear;virtual;
+ function checkduplicate(var s:THashedIDString;sym:TSymEntry):boolean;virtual;
+ procedure insert(sym:TSymEntry;checkdup:boolean=true);virtual;
+ procedure Delete(sym:TSymEntry);virtual;
+ function Find(const s:TIDString) : TSymEntry;
+ function FindWithHash(const s:THashedIDString) : TSymEntry;virtual;
+ procedure insertdef(def:TDefEntry);virtual;
+ procedure deletedef(def:TDefEntry);
+ function iscurrentunit:boolean;virtual;
+ { includes the flag in this symtable and all parent symtables; if
+ it's already set the flag is not set again }
+ procedure includeoption(option:tsymtableoption);
+ end;
+
+ psymtablestackitem = ^TSymtablestackitem;
+ TSymtablestackitem = record
+ symtable : TSymtable;
+ next : psymtablestackitem;
+ end;
+
+ TSymtablestack = class
+ stack : psymtablestackitem;
+ constructor create;
+ destructor destroy;override;
+ procedure clear;
+ procedure push(st:TSymtable); virtual;
+ procedure pop(st:TSymtable); virtual;
+ function top:TSymtable;
+ end;
+
+
+ var
+ initialmacrosymtable: TSymtable; { macros initially defined by the compiler or
+ given on the command line. Is common
+ for all files compiled and do not change. }
+ macrosymtablestack,
+ symtablestack : TSymtablestack;
+
+{$ifdef MEMDEBUG}
+ var
+ memrealnames : tmemdebug;
+{$endif MEMDEBUG}
+
+
+implementation
+
+ uses
+ verbose;
+
+{****************************************************************************
+ THashedIDString
+****************************************************************************}
+
+ procedure THashedIDString.SetId(const s:TIDString);
+ begin
+ FId:=s;
+ FHash:=FPHash(s);
+ end;
+
+
+{****************************************************************************
+ TSymEntry
+****************************************************************************}
+
+ destructor TSymEntry.destroy;
+ begin
+{$ifdef MEMDEBUG}
+ memrealnames.start;
+{$endif MEMDEBUG}
+ stringdispose(Frealname);
+{$ifdef MEMDEBUG}
+ memrealnames.stop;
+{$endif MEMDEBUG}
+ inherited destroy;
+ end;
+
+
+ function TSymEntry.GetRealname:shortstring;
+ begin
+ if not assigned(FRealname) then
+ internalerror(200611011);
+ result:=FRealname^;
+ end;
+
+
+ procedure TSymEntry.SetRealname(const ANewName:shortstring);
+ begin
+ stringdispose(FRealname);
+ FRealname:=stringdup(ANewName);
+ if Hash<>$ffffffff then
+ begin
+ if FRealname^[1]='$' then
+ Rename(Copy(FRealname^,2,255))
+ else
+ Rename(Upper(FRealname^));
+ end;
+ end;
+
+
+{****************************************************************************
+ TSymtable
+****************************************************************************}
+
+ constructor TSymtable.Create(const s:string);
+ begin
+ if s<>'' then
+ begin
+ name:=stringdup(upper(s));
+ realname:=stringdup(s);
+ end
+ else
+ begin
+ name:=nil;
+ realname:=nil;
+ end;
+ symtabletype:=abstractsymtable;
+ symtablelevel:=0;
+ defowner:=nil;
+ DefList:=TFPObjectList.Create(true);
+ SymList:=TFPHashObjectList.Create(true);
+ refcount:=1;
+ currentvisibility:=vis_public;
+ currentlyoptional:=false;
+ end;
+
+
+ destructor TSymtable.destroy;
+ begin
+ { freeinstance decreases refcount }
+ if refcount>1 then
+ exit;
+ Clear;
+ DefList.Free;
+ { SymList can already be disposed or set to nil for withsymtable, }
+ { but in that case Free does nothing }
+ SymList.Free;
+ stringdispose(name);
+ stringdispose(realname);
+ end;
+
+
+ procedure TSymtable.freeinstance;
+ begin
+ dec(refcount);
+ if refcount=0 then
+ inherited freeinstance;
+ end;
+
+
+ function TSymtable.getcopy:TSymtable;
+ begin
+ inc(refcount);
+ result:=self;
+ end;
+
+
+ function TSymtable.iscurrentunit:boolean;
+ begin
+ result:=false;
+ end;
+
+ procedure TSymtable.includeoption(option: tsymtableoption);
+ var
+ st: tsymtable;
+ begin
+ if option in tableoptions then
+ exit;
+ include(tableoptions,option);
+ { iterative approach should be faster than recursion based on calls }
+ st:=self;
+ while assigned(st.defowner) do
+ begin
+ st:=st.defowner.owner;
+ { the flag is already set, so by definition it is set in the
+ owning symtables as well }
+ if option in st.tableoptions then
+ break;
+ include(st.tableoptions,option);
+ end;
+ end;
+
+
+ procedure TSymtable.clear;
+ var
+ i : integer;
+ begin
+ SymList.Clear;
+ { Prevent recursive calls between TDef.destroy and TSymtable.Remove }
+ if DefList.OwnsObjects then
+ begin
+ for i := 0 to DefList.Count-1 do
+ TDefEntry(DefList[i]).Owner:=nil;
+ end;
+ DefList.Clear;
+ end;
+
+
+ function TSymtable.checkduplicate(var s:THashedIDString;sym:TSymEntry):boolean;
+ begin
+ result:=(FindWithHash(s)<>nil);
+ end;
+
+
+ procedure TSymtable.insert(sym:TSymEntry;checkdup:boolean=true);
+ var
+ hashedid : THashedIDString;
+ begin
+ if checkdup then
+ begin
+ if sym.realname[1]='$' then
+ hashedid.id:=Copy(sym.realname,2,255)
+ else
+ hashedid.id:=Upper(sym.realname);
+ { First check for duplicates, this can change the symbol name
+ in case of a duplicate entry }
+ checkduplicate(hashedid,sym);
+ end;
+ { Now we can insert the symbol, any duplicate entries
+ are renamed to an unique (and for users unaccessible) name }
+ if sym.realname[1]='$' then
+ sym.ChangeOwnerAndName(SymList,Copy(sym.realname,2,255))
+ else
+ sym.ChangeOwnerAndName(SymList,Upper(sym.realname));
+ sym.Owner:=self;
+ end;
+
+
+ procedure TSymtable.Delete(sym:TSymEntry);
+ begin
+ if sym.Owner<>self then
+ internalerror(200611121);
+ SymList.Remove(sym);
+ end;
+
+
+ procedure TSymtable.insertdef(def:TDefEntry);
+ begin
+ DefList.Add(def);
+ def.owner:=self;
+ end;
+
+
+ procedure TSymtable.deletedef(def:TDefEntry);
+ begin
+ if def.Owner<>self then
+ internalerror(200611122);
+ def.Owner:=nil;
+ DefList.Remove(def);
+ end;
+
+
+ function TSymtable.Find(const s : TIDString) : TSymEntry;
+ begin
+ result:=TSymEntry(SymList.Find(s));
+ end;
+
+
+ function TSymtable.FindWithHash(const s:THashedIDString) : TSymEntry;
+ begin
+ result:=TSymEntry(SymList.FindWithHash(s.id,s.hash));
+ end;
+
+
+{****************************************************************************
+ Symtable Stack
+****************************************************************************}
+
+ constructor TSymtablestack.create;
+ begin
+ stack:=nil;
+ end;
+
+
+ destructor TSymtablestack.destroy;
+ begin
+ clear;
+ end;
+
+
+ procedure TSymtablestack.clear;
+ var
+ hp : psymtablestackitem;
+ begin
+ while assigned(stack) do
+ begin
+ hp:=stack;
+ stack:=hp^.next;
+ dispose(hp);
+ end;
+ end;
+
+
+ procedure TSymtablestack.push(st:TSymtable);
+ var
+ hp : psymtablestackitem;
+ begin
+ new(hp);
+ hp^.symtable:=st;
+ hp^.next:=stack;
+ stack:=hp;
+ end;
+
+
+ procedure TSymtablestack.pop(st:TSymtable);
+ var
+ hp : psymtablestackitem;
+ begin
+ if not assigned(stack) then
+ internalerror(200601231);
+ if stack^.symtable<>st then
+ internalerror(200601232);
+ hp:=stack;
+ stack:=hp^.next;
+ dispose(hp);
+ end;
+
+
+ function TSymtablestack.top:TSymtable;
+ begin
+ if not assigned(stack) then
+ internalerror(200601233);
+ result:=stack^.symtable;
+ end;
+
+
+{$ifdef MEMDEBUG}
+initialization
+ memrealnames:=TMemDebug.create('Realnames');
+ memrealnames.stop;
+
+finalization
+ memrealnames.free;
+{$endif MEMDEBUG}
+end.
diff --git a/closures/compiler/symconst.pas b/closures/compiler/symconst.pas
new file mode 100644
index 0000000000..3c40411871
--- /dev/null
+++ b/closures/compiler/symconst.pas
@@ -0,0 +1,660 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl, Pierre Muller
+
+ Symbol table constants
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ ****************************************************************************
+}
+unit symconst;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ globtype;
+
+const
+ def_alignment = 4;
+
+ C_alignment = -1;
+ bit_alignment = -2;
+ mac68k_alignment = -3;
+
+ { if you change one of the following contants, }
+ { you have also to change the typinfo unit}
+ { and the rtl/i386,template/rttip.inc files }
+ tkUnknown = 0;
+ tkInteger = 1;
+ tkChar = 2;
+ tkEnumeration = 3;
+ tkFloat = 4;
+ tkSet = 5;
+ tkMethod = 6;
+ tkSString = 7;
+ tkString = tkSString;
+ tkLString = 8;
+ tkAString = 9;
+ tkWString = 10;
+ tkVariant = 11;
+ tkArray = 12;
+ tkRecord = 13;
+ tkInterface= 14;
+ tkClass = 15;
+ tkObject = 16;
+ tkWChar = 17;
+ tkBool = 18;
+ tkInt64 = 19;
+ tkQWord = 20;
+ tkDynArray = 21;
+ tkInterfaceCorba = 22;
+ tkProcVar = 23;
+ tkUString = 24;
+ tkUChar = 25;
+ tkHelper = 26;
+ tkFile = 27;
+
+ otSByte = 0;
+ otUByte = 1;
+ otSWord = 2;
+ otUWord = 3;
+ otSLong = 4;
+ otULong = 5;
+ otSLongLong = 6;
+ otULongLong = 7;
+
+ ftSingle = 0;
+ ftDouble = 1;
+ ftExtended = 2;
+ ftComp = 3;
+ ftCurr = 4;
+ ftFloat128 = 5;
+
+ mkProcedure = 0;
+ mkFunction = 1;
+ mkConstructor = 2;
+ mkDestructor = 3;
+ mkClassProcedure = 4;
+ mkClassFunction = 5;
+ mkClassConstructor = 6;
+ mkClassDestructor = 7;
+ mkOperatorOverload = 8;
+// delphi has the next too:
+//mkSafeProcedure = 9;
+//mkSafeFunction = 10;
+
+ pfvar = 1;
+ pfConst = 2;
+ pfArray = 4;
+ pfAddress = 8;
+ pfReference= 16;
+ pfOut = 32;
+ pfConstRef = 64;
+
+ unknown_level = 0;
+ main_program_level = 1;
+ normal_function_level = 2;
+
+ { implicit parameter positions, normal parameters start at 10
+ and will increase with 10 for each parameter. The high parameters
+ will be inserted with n+1 }
+ paranr_parentfp = 1;
+ paranr_parentfp_delphi_cc_leftright = 1;
+ paranr_self = 2;
+ paranr_result = 3;
+ paranr_vmt = 4;
+
+ { the implicit parameters for Objective-C methods need to come
+ after the hidden result parameter }
+ paranr_objc_self = 4;
+ paranr_objc_cmd = 5;
+ { Required to support variations of syscalls on MorphOS }
+ paranr_syscall_basesysv = 9;
+ paranr_syscall_sysvbase = high(word)-5;
+ paranr_syscall_r12base = high(word)-4;
+ paranr_syscall_legacy = high(word)-3;
+ paranr_result_leftright = high(word)-2;
+ paranr_parentfp_delphi_cc = high(word)-1;
+
+ { prefix for names of class helper procsyms added to regular symtables }
+ class_helper_prefix = 'CH$';
+
+
+type
+ { keep this in sync with TIntfFlag in rtl/objpas/typinfo.pp }
+ TCompilerIntfFlag = (ifHasGuid,ifDispInterface,ifDispatch,ifHasStrGUID);
+
+ { Deref entry options }
+ tdereftype = (deref_nil,
+ deref_unit,
+ deref_symid,
+ deref_defid
+ );
+
+ { symbol visibility }
+ tvisibility=(
+ vis_hidden,
+ vis_strictprivate,
+ vis_private,
+ vis_strictprotected,
+ vis_protected,
+ vis_public,
+ vis_published
+ );
+
+ { symbol options }
+ tsymoption=(sp_none,
+ sp_static, { static symbol in class/object/record }
+ sp_hint_deprecated,
+ sp_hint_platform,
+ sp_hint_library,
+ sp_hint_unimplemented,
+ sp_has_overloaded,
+ sp_internal, { internal symbol, not reported as unused }
+ sp_implicitrename,
+ sp_hint_experimental,
+ sp_generic_para,
+ sp_has_deprecated_msg,
+ sp_generic_dummy { this is used for symbols that are generated when a
+ generic is encountered to ease inline
+ specializations, etc; those symbols can be
+ "overridden" with a completely different symbol }
+ );
+ tsymoptions=set of tsymoption;
+
+ { flags for a definition }
+ tdefoption=(df_none,
+ { type is unique, i.e. declared with type = type <tdef>; }
+ df_unique,
+ { type is a generic }
+ df_generic,
+ { type is a specialization of a generic type }
+ df_specialization,
+ { def has been copied from another def so symtable is not owned }
+ df_copied_def
+ );
+ tdefoptions=set of tdefoption;
+
+ tdefstate=(ds_none,
+ ds_vmt_written,
+ ds_rtti_table_used,
+ ds_init_table_used,
+ ds_rtti_table_written,
+ ds_init_table_written,
+ ds_dwarf_dbg_info_used,
+ ds_dwarf_dbg_info_written
+ );
+ tdefstates=set of tdefstate;
+
+ { tsymlist entry types }
+ tsltype = (sl_none,
+ sl_load,
+ sl_call,
+ sl_subscript,
+ sl_vec,
+ sl_typeconv,
+ sl_absolutetype
+ );
+
+ { base types for orddef }
+ tordtype = (
+ uvoid,
+ u8bit,u16bit,u32bit,u64bit,
+ s8bit,s16bit,s32bit,s64bit,
+ pasbool8,pasbool16,pasbool32,pasbool64,
+ bool8bit,bool16bit,bool32bit,bool64bit,
+ uchar,uwidechar,scurrency
+ );
+
+ { string types }
+ tstringtype = (
+ st_shortstring,
+ st_longstring,
+ st_ansistring,
+ st_widestring,
+ st_unicodestring
+ );
+
+ tvarianttype = (
+ vt_normalvariant,vt_olevariant
+ );
+
+ tcallercallee = (callnoside,callerside,calleeside,callbothsides);
+
+ { basic type for tprocdef and tprocvardef }
+ tproctypeoption=(potype_none,
+ potype_proginit, { Program initialization }
+ potype_unitinit, { unit initialization }
+ potype_unitfinalize, { unit finalization }
+ potype_constructor, { Procedure is a constructor }
+ potype_destructor, { Procedure is a destructor }
+ potype_operator, { Procedure defines an operator }
+ potype_procedure,
+ potype_function,
+ potype_class_constructor, { class constructor }
+ potype_class_destructor, { class destructor }
+ potype_propgetter, { Dispinterface property accessors }
+ potype_propsetter,
+ potype_exceptfilter { SEH exception filter or termination handler }
+ );
+ tproctypeoptions=set of tproctypeoption;
+
+ { other options for tprocdef and tprocvardef }
+ tprocoption=(po_none,
+ po_classmethod, { class method }
+ po_virtualmethod, { Procedure is a virtual method }
+ po_abstractmethod, { Procedure is an abstract method }
+ po_finalmethod, { Procedure is a final method }
+ po_staticmethod, { static method }
+ po_overridingmethod, { method with override directive }
+ po_methodpointer, { method pointer, only in procvardef, also used for 'with object do' }
+ po_interrupt, { Procedure is an interrupt handler }
+ po_iocheck, { IO checking should be done after a call to the procedure }
+ po_assembler, { Procedure is written in assembler }
+ po_msgstr, { method for string message handling }
+ po_msgint, { method for int message handling }
+ po_exports, { Procedure has export directive (needed for OS/2) }
+ po_external, { Procedure is external (in other object or lib)}
+ po_overload, { procedure is declared with overload directive }
+ po_varargs, { printf like arguments }
+ po_internconst, { procedure has constant evaluator intern }
+ { flag that only the address of a method is returned and not a full methodpointer }
+ po_addressonly,
+ { procedure is exported }
+ po_public,
+ { calling convention is specified explicitly }
+ po_hascallingconvention,
+ { reintroduce flag }
+ po_reintroduce,
+ { location of parameters is given explicitly as it is necessary for some syscall
+ conventions like that one of MorphOS }
+ po_explicitparaloc,
+ { no stackframe will be generated, used by lowlevel assembler like get_frame }
+ po_nostackframe,
+ po_has_mangledname,
+ po_has_public_name,
+ po_forward,
+ po_global,
+ po_has_inlininginfo,
+ { The different kind of syscalls on MorphOS }
+ po_syscall_legacy,
+ po_syscall_sysv,
+ po_syscall_basesysv,
+ po_syscall_sysvbase,
+ po_syscall_r12base,
+ { Procedure can be inlined }
+ po_inline,
+ { Procedure is used for internal compiler calls }
+ po_compilerproc,
+ { importing }
+ po_has_importdll,
+ po_has_importname,
+ po_kylixlocal,
+ po_dispid,
+ { weakly linked (i.e., may or may not exist at run time) }
+ po_weakexternal,
+ { Objective-C method }
+ po_objc,
+ { enumerator support }
+ po_enumerator_movenext,
+ { optional Objective-C protocol method }
+ po_optional,
+ { nested procedure that uses Delphi-style calling convention for passing
+ the frame pointer (pushed on the stack, always the last parameter,
+ removed by the caller). Required for nested procvar compatibility,
+ because such procvars can hold both regular and nested procedures
+ (when calling a regular procedure using the above convention, it will
+ simply not see the frame pointer parameter, and since the caller cleans
+ up the stack will also remain balanced) }
+ po_delphi_nested_cc,
+ po_rtlproc
+ );
+ tprocoptions=set of tprocoption;
+
+ { options for objects and classes }
+ tobjecttyp = (odt_none,
+ odt_class,
+ odt_object,
+ odt_interfacecom,
+ odt_interfacecom_property,
+ odt_interfacecom_function,
+ odt_interfacecorba,
+ odt_cppclass,
+ odt_dispinterface,
+ odt_objcclass,
+ odt_objcprotocol,
+ odt_objccategory, { note that these are changed into odt_class afterwards }
+ odt_helper
+ );
+
+ { defines the type of the extended "structure"; only used for parsing }
+ thelpertype=(ht_none,
+ ht_class,
+ ht_record
+ );
+
+ { Variations in interfaces implementation }
+ { Beware, this data is duplicated in the compiler and rtl. }
+ { Do not change the order of the fields. }
+ tinterfaceentrytype = (etStandard,
+ etVirtualMethodResult,
+ etStaticMethodResult,
+ etFieldValue,
+ etVirtualMethodClass,
+ etStaticMethodClass,
+ etFieldValueClass
+ );
+
+ { options for objects and classes }
+ tobjectoption=(oo_none,
+ oo_is_forward, { the class is only a forward declared yet }
+ oo_is_abstract, { the class is abstract - only descendants can be used }
+ oo_is_sealed, { the class is sealed - can't have descendants }
+ oo_has_virtual, { the object/class has virtual methods }
+ oo_has_private,
+ oo_has_protected,
+ oo_has_strictprivate,
+ oo_has_strictprotected,
+ oo_has_constructor, { the object/class has a constructor }
+ oo_has_destructor, { the object/class has a destructor }
+ oo_has_vmt, { the object/class has a vmt }
+ oo_has_msgstr,
+ oo_has_msgint,
+ oo_can_have_published,{ the class has rtti, i.e. you can publish properties }
+ oo_has_default_property,
+ oo_has_valid_guid,
+ oo_has_enumerator_movenext,
+ oo_has_enumerator_current,
+ oo_is_external, { the class is externally implemented (objcclass, cppclass) }
+ oo_is_formal, { the class is only formally defined in this module (x = objcclass; external [name 'x'];) }
+ oo_is_classhelper, { objcclasses that represent categories, and Delpi-style class helpers, are marked like this }
+ oo_has_class_constructor, { the object/class has a class constructor }
+ oo_has_class_destructor { the object/class has a class destructor }
+ );
+ tobjectoptions=set of tobjectoption;
+
+ tarraydefoption=(ado_none,
+ ado_IsConvertedPointer,
+ ado_IsDynamicArray,
+ ado_IsVariant,
+ ado_IsConstructor,
+ ado_IsArrayOfConst,
+ ado_IsConstString,
+ ado_IsBitPacked
+ );
+ tarraydefoptions=set of tarraydefoption;
+
+ { options for properties }
+ tpropertyoption=(ppo_none,
+ ppo_indexed, { delcared wwith "index" keyword }
+ ppo_defaultproperty,
+ ppo_stored,
+ ppo_hasparameters, { has parameters: prop[param1, param2: type] }
+ ppo_implements,
+ ppo_enumerator_current, { implements current property for enumerator }
+ ppo_overrides, { overrides ancestor property }
+ ppo_dispid_write { no longer used }
+ );
+ tpropertyoptions=set of tpropertyoption;
+
+ { options for variables }
+ tvaroption=(vo_none,
+ vo_is_external,
+ vo_is_dll_var,
+ vo_is_thread_var,
+ vo_has_local_copy,
+ vo_is_const, { variable is declared as const (parameter) and can't be written to }
+ vo_is_public,
+ vo_is_high_para,
+ vo_is_funcret,
+ vo_is_self,
+ vo_is_vmt,
+ vo_is_result, { special result variable }
+ vo_is_parentfp,
+ vo_is_loop_counter, { used to detect assignments to loop counter }
+ vo_is_hidden_para,
+ vo_has_explicit_paraloc,
+ vo_is_syscall_lib,
+ vo_has_mangledname,
+ vo_is_typed_const,
+ vo_is_range_check,
+ vo_is_overflow_check,
+ vo_is_typinfo_para,
+ vo_is_weak_external,
+ { Objective-C message selector parameter }
+ vo_is_msgsel,
+ { first field of variant part of a record }
+ vo_is_first_field,
+ vo_volatile,
+ vo_has_section,
+ { variable contains a winlike WideString which should be finalized
+ even in $J- state }
+ vo_force_finalize
+ );
+ tvaroptions=set of tvaroption;
+
+ { register variable }
+ tvarregable=(vr_none,
+ vr_intreg,
+ vr_fpureg,
+ vr_mmreg,
+ { does not mean "needs address register", but "if it's a parameter which is }
+ { passed by reference, then its address can be put in a register }
+ vr_addr
+ );
+
+ { types of the symtables }
+ TSymtabletype = (
+ abstractsymtable, { not a real symtable }
+ globalsymtable, { unit interface symtable }
+ staticsymtable, { unit implementation symtable }
+ ObjectSymtable, { object symtable }
+ recordsymtable, { record symtable }
+ localsymtable, { subroutine symtable }
+ parasymtable, { arguments symtable }
+ withsymtable, { with operator symtable }
+ stt_excepTSymtable, { try/except symtable }
+ exportedmacrosymtable, { }
+ localmacrosymtable, { }
+ enumsymtable, { symtable for enum members }
+ arraysymtable { used to store parameterised type
+ in array }
+ );
+
+ { options for symtables }
+ tsymtableoption = (
+ sto_has_helper { contains at least one helper symbol }
+ );
+ tsymtableoptions = set of tsymtableoption;
+
+ { definition contains the informations about a type }
+ tdeftyp = (abstractdef,
+ arraydef,recorddef,pointerdef,orddef,
+ stringdef,enumdef,procdef,objectdef,errordef,
+ filedef,formaldef,setdef,procvardef,floatdef,
+ classrefdef,forwarddef,variantdef,undefineddef
+ );
+
+ { possible types for symtable entries }
+ tsymtyp = (abstractsym,
+ staticvarsym,localvarsym,paravarsym,fieldvarsym,
+ typesym,procsym,unitsym,constsym,enumsym,
+ errorsym,syssym,labelsym,absolutevarsym,propertysym,
+ macrosym,namespacesym
+ );
+
+ { State of the variable:
+ vs_declared: variable has been declared, not initialised
+ (e.g. normal variable, out parameter)
+ vs_initialised: variable has been declared and is valid
+ (e.g. typed constant, var/const parameter)
+ vs_read: variable has been read and the read was checked for validity
+ (so a warning has been given if necessary)
+ vs_read_not_warned: variable has been read, but we didn't warn about
+ whether or not the variable was valid
+ (e.g. read of global variable -> warn at end of compilation unit if
+ the state is vs_read_not_warned, since that means it's only read and
+ never written)
+ vs_referred_not_inited: variable has been used in length/low/high/@/...
+ expression, was not yet initialised and needn't be at that time
+ (e.g. length() of a statically allocated array, or sizeof(variable))
+ vs_written: variable has been assigned/written to, but not yet read
+ (e.g. assigning something to a variable/parameter)
+ vs_readwritten: variable has been written to and read from }
+ tvarstate=(vs_none,
+ vs_declared,vs_initialised,vs_read,vs_read_not_warned,
+ vs_referred_not_inited,vs_written,vs_readwritten
+ );
+
+ tvarspez = (vs_value,vs_const,vs_var,vs_out,vs_constref);
+
+ absolutetyp = (tovar,toasm,toaddr);
+
+ tconsttyp = (constnone,
+ constord,conststring,constreal,
+ constset,constpointer,constnil,
+ constresourcestring,constwstring,constguid
+ );
+
+ { RTTI information to store }
+ trttitype = (
+ fullrtti,initrtti,
+ { Objective-C }
+ objcmetartti,objcmetarortti,
+ objcclassrtti,objcclassrortti
+ );
+
+ { The order is from low priority to high priority,
+ Note: the operators > and < are used on this list }
+ tequaltype = (
+ te_incompatible,
+ te_convert_operator,
+ te_convert_l5, { ad infinitum... }
+ te_convert_l4, { and yet even less preferred conversion }
+ te_convert_l3, { even less preferred conversion (possibly with loss of data) }
+ te_convert_l2, { compatible less preferred conversion }
+ te_convert_l1, { compatible conversion }
+ te_equal, { the definitions are equal }
+ te_exact
+ );
+
+ tvariantequaltype = (
+ tve_incompatible,
+ tve_chari64,
+ tve_ustring,
+ tve_wstring,
+ tve_astring,
+ tve_sstring,
+ tve_boolformal,
+ tve_extended,
+ tve_dblcurrency,
+ tve_single,
+ tve_cardinal,
+ tve_longint,
+ tve_smallint,
+ tve_word,
+ tve_shortint,
+ tve_byte
+ );
+ tvariantequaltypes = set of tvariantequaltype;
+
+ tdefdbgstatus = (
+ dbg_state_unused,
+ dbg_state_used,
+ dbg_state_writing,
+ dbg_state_written,
+ dbg_state_queued
+ );
+
+var
+ clearstack_pocalls : tproccalloptions;
+ cdecl_pocalls : tproccalloptions;
+
+const
+ inherited_objectoptions : tobjectoptions = [oo_has_virtual,oo_has_private,oo_has_protected,
+ oo_has_strictprotected,oo_has_strictprivate,oo_has_constructor,oo_has_destructor,
+ oo_can_have_published];
+
+{$ifdef i386}
+ { we only take this into account on i386, on other platforms we always
+ push in the same order
+ }
+ pushleftright_pocalls : tproccalloptions = [pocall_register,pocall_pascal];
+{$endif}
+
+ SymTypeName : array[tsymtyp] of string[12] = (
+ 'abstractsym','globalvar','localvar','paravar','fieldvar',
+ 'type','proc','unit','const','enum',
+ 'errorsym','system sym','label','absolutevar','property',
+ 'macrosym','namespace'
+ );
+
+ typName : array[tdeftyp] of string[12] = (
+ 'abstractdef','arraydef','recorddef','pointerdef','orddef',
+ 'stringdef','enumdef','procdef','objectdef','errordef',
+ 'filedef','formaldef','setdef','procvardef','floatdef',
+ 'classrefdef','forwarddef','variantdef','undefineddef'
+ );
+
+ EqualTypeName : array[tequaltype] of string[16] = (
+ 'incompatible','convert_operator','convert_l5','convert_l4','convert_l3','convert_l2',
+ 'convert_l1','equal','exact'
+ );
+
+ visibilityName : array[tvisibility] of string[16] = (
+ 'hidden','strict private','private','strict protected','protected',
+ 'public','published'
+ );
+
+
+{ !! Be sure to keep these in sync with ones in rtl/inc/varianth.inc }
+ varempty = 0;
+ varnull = 1;
+ varsmallint = 2;
+ varinteger = 3;
+ varsingle = 4;
+ vardouble = 5;
+ varcurrency = 6;
+ vardate = 7;
+ varolestr = 8;
+ vardispatch = 9;
+ varerror = 10;
+ varboolean = 11;
+ varvariant = 12;
+ varunknown = 13;
+ vardecimal = 14;
+ varshortint = 16;
+ varbyte = 17;
+ varword = 18;
+ varlongword = 19;
+ varint64 = 20;
+ varqword = 21;
+
+ varUndefined = -1;
+
+ varstrarg = $48;
+ varustrarg = $49;
+
+ varstring = $100;
+ varany = $101;
+ varustring = $102;
+ vardefmask = $fff;
+ vararray = $2000;
+ varbyref = $4000;
+
+implementation
+
+end.
diff --git a/closures/compiler/symdef.pas b/closures/compiler/symdef.pas
new file mode 100644
index 0000000000..6b9852fc52
--- /dev/null
+++ b/closures/compiler/symdef.pas
@@ -0,0 +1,5947 @@
+{
+ Symbol table implementation for the definitions
+
+ Copyright (c) 1998-2005 by Florian Klaempfl, Pierre Muller
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ ****************************************************************************
+}
+unit symdef;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ { common }
+ cclasses,
+ { global }
+ globtype,globals,tokens,constexp,
+ { symtable }
+ symconst,symbase,symtype,
+ { ppu }
+ ppu,
+ { node }
+ node,
+ { aasm }
+ aasmbase,aasmtai,aasmdata,
+ cpubase,cpuinfo,
+ cgbase,cgutils,
+ parabase
+ ;
+
+
+ type
+{************************************************
+ TDef
+************************************************}
+
+ { tstoreddef }
+
+ tstoreddef = class(tdef)
+ protected
+ typesymderef : tderef;
+ public
+{$ifdef EXTDEBUG}
+ fileinfo : tfileposinfo;
+{$endif}
+ { generic support }
+ genericdef : tstoreddef;
+ genericdefderef : tderef;
+ generictokenbuf : tdynamicarray;
+ { Set if PPU was generated with another
+ endianess as current compiler or ppudump utils }
+ change_endian : boolean;
+ constructor create(dt:tdeftyp);
+ constructor ppuload(dt:tdeftyp;ppufile:tcompilerppufile);
+ destructor destroy;override;
+ function getcopy : tstoreddef;virtual;
+ procedure ppuwrite(ppufile:tcompilerppufile);virtual;
+ procedure buildderef;override;
+ procedure buildderefimpl;override;
+ procedure deref;override;
+ procedure derefimpl;override;
+ function size:asizeint;override;
+ function getvardef:longint;override;
+ function alignment:shortint;override;
+ function is_publishable : boolean;override;
+ function needs_inittable : boolean;override;
+ function rtti_mangledname(rt:trttitype):string;override;
+ function OwnerHierarchyName: string; override;
+ function in_currentunit: boolean;
+ { regvars }
+ function is_intregable : boolean;
+ function is_fpuregable : boolean;
+ { generics }
+ procedure initgeneric;
+ private
+ savesize : asizeuint;
+ end;
+
+ tfiletyp = (ft_text,ft_typed,ft_untyped);
+
+ tfiledef = class(tstoreddef)
+ filetyp : tfiletyp;
+ typedfiledef : tdef;
+ typedfiledefderef : tderef;
+ constructor createtext;
+ constructor createuntyped;
+ constructor createtyped(def : tdef);
+ constructor ppuload(ppufile:tcompilerppufile);
+ function getcopy : tstoreddef;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderef;override;
+ procedure deref;override;
+ function GetTypeName:string;override;
+ function getmangledparaname:string;override;
+ procedure setsize;
+ end;
+
+ tvariantdef = class(tstoreddef)
+ varianttype : tvarianttype;
+ constructor create(v : tvarianttype);
+ constructor ppuload(ppufile:tcompilerppufile);
+ function getcopy : tstoreddef;override;
+ function GetTypeName:string;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ function getvardef:longint;override;
+ procedure setsize;
+ function is_publishable : boolean;override;
+ function needs_inittable : boolean;override;
+ end;
+
+ tformaldef = class(tstoreddef)
+ typed:boolean;
+ constructor create(Atyped:boolean);
+ constructor ppuload(ppufile:tcompilerppufile);
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ function GetTypeName:string;override;
+ end;
+
+ tforwarddef = class(tstoreddef)
+ tosymname : pshortstring;
+ forwardpos : tfileposinfo;
+ constructor create(const s:string;const pos:tfileposinfo);
+ destructor destroy;override;
+ function getcopy:tstoreddef;override;
+ function GetTypeName:string;override;
+ end;
+
+ tundefineddef = class(tstoreddef)
+ constructor create;
+ constructor ppuload(ppufile:tcompilerppufile);
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ function GetTypeName:string;override;
+ end;
+
+ terrordef = class(tstoreddef)
+ constructor create;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ function GetTypeName:string;override;
+ function getmangledparaname : string;override;
+ end;
+
+ tabstractpointerdef = class(tstoreddef)
+ pointeddef : tdef;
+ pointeddefderef : tderef;
+ constructor create(dt:tdeftyp;def:tdef);
+ constructor ppuload(dt:tdeftyp;ppufile:tcompilerppufile);
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderef;override;
+ procedure deref;override;
+ end;
+
+ tpointerdef = class(tabstractpointerdef)
+ is_far : boolean;
+ has_pointer_math : boolean;
+ constructor create(def:tdef);
+ constructor createfar(def:tdef);
+ function getcopy:tstoreddef;override;
+ constructor ppuload(ppufile:tcompilerppufile);
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ function GetTypeName:string;override;
+ end;
+
+ tprocdef = class;
+ { tabstractrecorddef }
+
+ tabstractrecorddef= class(tstoreddef)
+ objname,
+ objrealname : PShortString;
+ symtable : TSymtable;
+ cloneddef : tabstractrecorddef;
+ cloneddefderef : tderef;
+ objectoptions : tobjectoptions;
+ constructor create(const n:string; dt:tdeftyp);
+ constructor ppuload(dt:tdeftyp;ppufile:tcompilerppufile);
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ destructor destroy; override;
+ procedure check_forwards; virtual;
+ function find_procdef_bytype(pt:tproctypeoption): tprocdef;
+ function GetSymtable(t:tGetSymtable):TSymtable;override;
+ function is_packed:boolean;
+ function RttiName: string;
+ { enumerator support }
+ function search_enumerator_get: tprocdef; virtual;
+ function search_enumerator_move: tprocdef; virtual;
+ function search_enumerator_current: tsym; virtual;
+ end;
+
+ trecorddef = class(tabstractrecorddef)
+ public
+ isunion : boolean;
+ constructor create(const n:string; p:TSymtable);
+ constructor ppuload(ppufile:tcompilerppufile);
+ destructor destroy;override;
+ function getcopy : tstoreddef;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderef;override;
+ procedure deref;override;
+ function size:asizeint;override;
+ function alignment : shortint;override;
+ function padalignment: shortint;
+ function GetTypeName:string;override;
+ { debug }
+ function needs_inittable : boolean;override;
+ end;
+
+ tobjectdef = class;
+
+ { TImplementedInterface }
+
+ TImplementedInterface = class
+ IntfDef : tobjectdef;
+ IntfDefDeref : tderef;
+ IType : tinterfaceentrytype;
+ IOffset : longint;
+ VtblImplIntf : TImplementedInterface;
+ NameMappings : TFPHashList;
+ ProcDefs : TFPObjectList;
+ ImplementsGetter : tsym;
+ constructor create(aintf: tobjectdef);
+ constructor create_deref(d:tderef);
+ destructor destroy; override;
+ function getcopy:TImplementedInterface;
+ procedure buildderef;
+ procedure deref;
+ procedure AddMapping(const origname, newname: string);
+ function GetMapping(const origname: string):string;
+ procedure AddImplProc(pd:tprocdef);
+ function IsImplMergePossible(MergingIntf:TImplementedInterface;out weight: longint): boolean;
+ end;
+
+ { tvmtentry }
+ tvmtentry = record
+ procdef : tprocdef;
+ procdefderef : tderef;
+ visibility : tvisibility;
+ end;
+ pvmtentry = ^tvmtentry;
+
+ { tobjectdef }
+
+ tvmcallstatic = (vmcs_default, vmcs_yes, vmcs_no, vmcs_unreachable);
+ pmvcallstaticinfo = ^tmvcallstaticinfo;
+ tmvcallstaticinfo = array[0..1024*1024-1] of tvmcallstatic;
+ tobjectdef = class(tabstractrecorddef)
+ private
+ fcurrent_dispid: longint;
+ public
+ dwarf_struct_lab : tasmsymbol;
+ childof : tobjectdef;
+ childofderef : tderef;
+
+ { for Object Pascal helpers }
+ extendeddef : tdef;
+ extendeddefderef: tderef;
+ { for C++ classes: name of the library this class is imported from }
+ import_lib,
+ { for Objective-C: protocols and classes can have the same name there }
+ objextname : pshortstring;
+ { to be able to have a variable vmt position }
+ { and no vmt field for objects without virtuals }
+ vmtentries : TFPList;
+ vmcallstaticinfo : pmvcallstaticinfo;
+ vmt_offset : longint;
+ iidguid : pguid;
+ iidstr : pshortstring;
+ { store implemented interfaces defs and name mappings }
+ ImplementedInterfaces : TFPObjectList;
+ writing_class_record_dbginfo,
+ { a class of this type has been created in this module }
+ created_in_current_module,
+ { a loadvmtnode for this class has been created in this
+ module, so if a classrefdef variable of this or a parent
+ class is used somewhere to instantiate a class, then this
+ class may be instantiated
+ }
+ maybe_created_in_current_module,
+ { a "class of" this particular class has been created in
+ this module
+ }
+ classref_created_in_current_module : boolean;
+ objecttype : tobjecttyp;
+ constructor create(ot:tobjecttyp;const n:string;c:tobjectdef);
+ constructor ppuload(ppufile:tcompilerppufile);
+ destructor destroy;override;
+ function getcopy : tstoreddef;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ function GetTypeName:string;override;
+ procedure buildderef;override;
+ procedure deref;override;
+ procedure buildderefimpl;override;
+ procedure derefimpl;override;
+ procedure resetvmtentries;
+ procedure copyvmtentries(objdef:tobjectdef);
+ function getparentdef:tdef;override;
+ function size : asizeint;override;
+ function alignment:shortint;override;
+ function vmtmethodoffset(index:longint):longint;
+ function members_need_inittable : boolean;
+ function find_implemented_interface(aintfdef:tobjectdef):TImplementedInterface;
+ { this should be called when this class implements an interface }
+ procedure prepareguid;
+ function is_publishable : boolean;override;
+ function is_related(d : tdef) : boolean;override;
+ function needs_inittable : boolean;override;
+ function rtti_mangledname(rt:trttitype):string;override;
+ function vmt_mangledname : string;
+ procedure check_forwards; override;
+ procedure insertvmt;
+ procedure set_parent(c : tobjectdef);
+ function find_destructor: tprocdef;
+ function implements_any_interfaces: boolean;
+ { dispinterface support }
+ function get_next_dispid: longint;
+ { enumerator support }
+ function search_enumerator_get: tprocdef; override;
+ function search_enumerator_move: tprocdef; override;
+ function search_enumerator_current: tsym; override;
+ { WPO }
+ procedure register_created_object_type;override;
+ procedure register_maybe_created_object_type;
+ procedure register_created_classref_type;
+ procedure register_vmt_call(index:longint);
+ { ObjC }
+ procedure finish_objc_data;
+ function check_objc_types: boolean;
+ { C++ }
+ procedure finish_cpp_data;
+ end;
+
+ tclassrefdef = class(tabstractpointerdef)
+ constructor create(def:tdef);
+ constructor ppuload(ppufile:tcompilerppufile);
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ function getcopy:tstoreddef;override;
+ function GetTypeName:string;override;
+ function is_publishable : boolean;override;
+ function rtti_mangledname(rt:trttitype):string;override;
+ procedure register_created_object_type;override;
+ end;
+
+ tarraydef = class(tstoreddef)
+ lowrange,
+ highrange : asizeint;
+ rangedef : tdef;
+ rangedefderef : tderef;
+ arrayoptions : tarraydefoptions;
+ symtable : TSymtable;
+ protected
+ _elementdef : tdef;
+ _elementdefderef : tderef;
+ procedure setelementdef(def:tdef);
+ public
+ function elesize : asizeint;
+ function elepackedbitsize : asizeint;
+ function elecount : asizeuint;
+ constructor create_from_pointer(def:tdef);
+ constructor create(l,h:asizeint;def:tdef);
+ constructor ppuload(ppufile:tcompilerppufile);
+ destructor destroy; override;
+ function getcopy : tstoreddef;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ function GetTypeName:string;override;
+ function getmangledparaname : string;override;
+ procedure buildderef;override;
+ procedure deref;override;
+ function size : asizeint;override;
+ function alignment : shortint;override;
+ { returns the label of the range check string }
+ function needs_inittable : boolean;override;
+ property elementdef : tdef read _elementdef write setelementdef;
+ function is_publishable : boolean;override;
+ end;
+
+ torddef = class(tstoreddef)
+ low,high : TConstExprInt;
+ ordtype : tordtype;
+ constructor create(t : tordtype;v,b : TConstExprInt);
+ constructor ppuload(ppufile:tcompilerppufile);
+ function getcopy : tstoreddef;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ function is_publishable : boolean;override;
+ function GetTypeName:string;override;
+ function alignment:shortint;override;
+ procedure setsize;
+ function packedbitsize: asizeint; override;
+ function getvardef : longint;override;
+ end;
+
+ tfloatdef = class(tstoreddef)
+ floattype : tfloattype;
+ constructor create(t : tfloattype);
+ constructor ppuload(ppufile:tcompilerppufile);
+ function getcopy : tstoreddef;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ function GetTypeName:string;override;
+ function is_publishable : boolean;override;
+ function alignment:shortint;override;
+ procedure setsize;
+ function getvardef:longint;override;
+ end;
+
+ { tabstractprocdef }
+
+ tabstractprocdef = class(tstoreddef)
+ { saves a definition to the return type }
+ returndef : tdef;
+ returndefderef : tderef;
+ parast : TSymtable;
+ paras : tparalist;
+ proctypeoption : tproctypeoption;
+ proccalloption : tproccalloption;
+ procoptions : tprocoptions;
+ callerargareasize,
+ calleeargareasize: pint;
+{$ifdef m68k}
+ exp_funcretloc : tregister; { explicit funcretloc for AmigaOS }
+{$endif}
+ funcretloc : array[tcallercallee] of TCGPara;
+ has_paraloc_info : tcallercallee; { paraloc info is available }
+ { number of user visible parameters }
+ maxparacount,
+ minparacount : byte;
+ constructor create(dt:tdeftyp;level:byte);
+ constructor ppuload(dt:tdeftyp;ppufile:tcompilerppufile);
+ destructor destroy;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderef;override;
+ procedure deref;override;
+ procedure calcparas;
+ function typename_paras(showhidden:boolean): string;
+ function is_methodpointer:boolean;virtual;
+ function is_addressonly:boolean;virtual;
+ function no_self_node:boolean;
+ procedure check_mark_as_nested;
+ procedure init_paraloc_info(side: tcallercallee);
+ function stack_tainting_parameter(side: tcallercallee): boolean;
+ private
+ procedure count_para(p:TObject;arg:pointer);
+ procedure insert_para(p:TObject;arg:pointer);
+ end;
+
+ tprocvardef = class(tabstractprocdef)
+ constructor create(level:byte);
+ constructor ppuload(ppufile:tcompilerppufile);
+ function getcopy : tstoreddef;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ function GetSymtable(t:tGetSymtable):TSymtable;override;
+ function size : asizeint;override;
+ function GetTypeName:string;override;
+ function is_publishable : boolean;override;
+ function is_methodpointer:boolean;override;
+ function is_addressonly:boolean;override;
+ function getmangledparaname:string;override;
+ end;
+
+ tmessageinf = record
+ case integer of
+ 0 : (str : pshortstring);
+ 1 : (i : longint);
+ end;
+
+ tinlininginfo = record
+ { node tree }
+ code : tnode;
+ flags : tprocinfoflags;
+ end;
+ pinlininginfo = ^tinlininginfo;
+
+
+{$ifdef oldregvars}
+ { register variables }
+ pregvarinfo = ^tregvarinfo;
+ tregvarinfo = record
+ regvars : array[1..maxvarregs] of tsym;
+ regvars_para : array[1..maxvarregs] of boolean;
+ regvars_refs : array[1..maxvarregs] of longint;
+
+ fpuregvars : array[1..maxfpuvarregs] of tsym;
+ fpuregvars_para : array[1..maxfpuvarregs] of boolean;
+ fpuregvars_refs : array[1..maxfpuvarregs] of longint;
+ end;
+{$endif oldregvars}
+
+ { tprocdef }
+
+ tprocdef = class(tabstractprocdef)
+ private
+ _mangledname : pshortstring;
+ public
+ messageinf : tmessageinf;
+ dispid : longint;
+{$ifndef EXTDEBUG}
+ { where is this function defined and what were the symbol
+ flags, needed here because there
+ is only one symbol for all overloaded functions
+ EXTDEBUG has fileinfo in tdef (PFV) }
+ fileinfo : tfileposinfo;
+{$endif}
+ symoptions : tsymoptions;
+ deprecatedmsg : pshortstring;
+ { symbol owning this definition }
+ procsym : tsym;
+ procsymderef : tderef;
+ { alias names }
+ aliasnames : TCmdStrList;
+ { symtables }
+ localst : TSymtable;
+ funcretsym : tsym;
+ funcretsymderef : tderef;
+ struct : tabstractrecorddef;
+ structderef : tderef;
+{$if defined(powerpc) or defined(m68k)}
+ { library symbol for AmigaOS/MorphOS }
+ libsym : tsym;
+ libsymderef : tderef;
+{$endif powerpc or m68k}
+ { name of the result variable to insert in the localsymtable }
+ resultname : pshortstring;
+ { import info }
+ import_dll,
+ import_name : pshortstring;
+ { info for inlining the subroutine, if this pointer is nil,
+ the procedure can't be inlined }
+ inlininginfo : pinlininginfo;
+{$ifdef oldregvars}
+ regvarinfo: pregvarinfo;
+{$endif oldregvars}
+ { interrupt vector }
+ interruptvector : longint;
+ { First/last assembler symbol/instruction in aasmoutput list.
+ Note: initialised after compiling the code for the procdef, but
+ not saved to/restored from ppu. Used when inserting debug info }
+ procstarttai,
+ procendtai : tai;
+ import_nr : word;
+ extnumber : word;
+{$ifdef i386}
+ fpu_used : byte;
+{$endif i386}
+ visibility : tvisibility;
+ { true, if the procedure is only declared
+ (forward procedure) }
+ forwarddef,
+ { true if the procedure is declared in the interface }
+ interfacedef : boolean;
+ { true if the procedure has a forward declaration }
+ hasforward : boolean;
+ constructor create(level:byte);
+ constructor ppuload(ppufile:tcompilerppufile);
+ destructor destroy;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderef;override;
+ procedure buildderefimpl;override;
+ procedure deref;override;
+ procedure derefimpl;override;
+ function GetSymtable(t:tGetSymtable):TSymtable;override;
+ function GetTypeName : string;override;
+ function mangledname : string;
+ procedure setmangledname(const s : string);
+ function fullprocname(showhidden:boolean):string;
+ function cplusplusmangledname : string;
+ function objcmangledname : string;
+ function is_methodpointer:boolean;override;
+ function is_addressonly:boolean;override;
+ procedure make_external;
+ end;
+
+ { single linked list of overloaded procs }
+ pprocdeflist = ^tprocdeflist;
+ tprocdeflist = record
+ def : tprocdef;
+ defderef : tderef;
+ next : pprocdeflist;
+ end;
+
+ tstringdef = class(tstoreddef)
+ encoding : tstringencoding;
+ stringtype : tstringtype;
+ len : asizeint;
+ constructor createshort(l : byte);
+ constructor loadshort(ppufile:tcompilerppufile);
+ constructor createlong(l : asizeint);
+ constructor loadlong(ppufile:tcompilerppufile);
+ constructor createansi(aencoding:tstringencoding);
+ constructor loadansi(ppufile:tcompilerppufile);
+ constructor createwide;
+ constructor loadwide(ppufile:tcompilerppufile);
+ constructor createunicode;
+ constructor loadunicode(ppufile:tcompilerppufile);
+ function getcopy : tstoreddef;override;
+ function stringtypname:string;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ function GetTypeName:string;override;
+ function getmangledparaname:string;override;
+ function is_publishable : boolean;override;
+ function alignment : shortint;override;
+ function needs_inittable : boolean;override;
+ function getvardef:longint;override;
+ end;
+
+ { tenumdef }
+
+ tenumdef = class(tstoreddef)
+ minval,
+ maxval : asizeint;
+ basedef : tenumdef;
+ basedefderef : tderef;
+ symtable : TSymtable;
+ has_jumps : boolean;
+ constructor create;
+ constructor create_subrange(_basedef:tenumdef;_min,_max:asizeint);
+ constructor ppuload(ppufile:tcompilerppufile);
+ destructor destroy;override;
+ function getcopy : tstoreddef;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderef;override;
+ procedure deref;override;
+ function GetTypeName:string;override;
+ function is_publishable : boolean;override;
+ procedure calcsavesize;
+ function packedbitsize: asizeint; override;
+ procedure setmax(_max:asizeint);
+ procedure setmin(_min:asizeint);
+ function min:asizeint;
+ function max:asizeint;
+ function getfirstsym:tsym;
+ end;
+
+ tsetdef = class(tstoreddef)
+ elementdef : tdef;
+ elementdefderef : tderef;
+ setbase,
+ setmax : aword;
+ constructor create(def:tdef;low, high : asizeint);
+ constructor ppuload(ppufile:tcompilerppufile);
+ function getcopy : tstoreddef;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderef;override;
+ procedure deref;override;
+ function GetTypeName:string;override;
+ function is_publishable : boolean;override;
+ end;
+
+ tdefawaresymtablestack = class(TSymtablestack)
+ private
+ procedure addhelpers(st: TSymtable);
+ procedure removehelpers(st: TSymtable);
+ public
+ procedure push(st: TSymtable); override;
+ procedure pop(st: TSymtable); override;
+ end;
+
+ var
+ current_structdef: tabstractrecorddef; { used for private functions check !! }
+ current_genericdef: tstoreddef; { used to reject declaration of generic class inside generic class }
+ current_specializedef: tstoreddef; { used to implement usage of generic class in itself }
+
+ { default types }
+ generrordef, { error in definition }
+ voidpointertype, { pointer for Void-pointeddef }
+ charpointertype, { pointer for Char-pointeddef }
+ widecharpointertype, { pointer for WideChar-pointeddef }
+ voidfarpointertype,
+ cundefinedtype,
+ cformaltype, { unique formal definition }
+ ctypedformaltype, { unique typed formal definition }
+ voidtype, { Void (procedure) }
+ cchartype, { Char }
+ cwidechartype, { WideChar }
+ pasbool8type, { boolean type }
+ pasbool16type,
+ pasbool32type,
+ pasbool64type,
+ bool8type,
+ bool16type,
+ bool32type,
+ bool64type, { implement me }
+ u8inttype, { 8-Bit unsigned integer }
+ s8inttype, { 8-Bit signed integer }
+ u16inttype, { 16-Bit unsigned integer }
+ s16inttype, { 16-Bit signed integer }
+ u32inttype, { 32-Bit unsigned integer }
+ s32inttype, { 32-Bit signed integer }
+ u64inttype, { 64-bit unsigned integer }
+ s64inttype, { 64-bit signed integer }
+ s32floattype, { 32 bit floating point number }
+ s64floattype, { 64 bit floating point number }
+ s80floattype, { 80 bit floating point number }
+ sc80floattype, { 80 bit floating point number but stored like in C }
+ s64currencytype, { pointer to a currency type }
+ cshortstringtype, { pointer to type of short string const }
+ clongstringtype, { pointer to type of long string const }
+ cansistringtype, { pointer to type of ansi string const }
+ cwidestringtype, { pointer to type of wide string const }
+ cunicodestringtype,
+ openshortstringtype, { pointer to type of an open shortstring,
+ needed for readln() }
+ openchararraytype, { pointer to type of an open array of char,
+ needed for readln() }
+ cfiletype, { get the same definition for all file }
+ { used for stabs }
+ methodpointertype, { typecasting of methodpointers to extract self }
+ hresultdef,
+ { we use only one variant def for every variant class }
+ cvarianttype,
+ colevarianttype,
+ { default integer type s32inttype on 32 bit systems, s64bittype on 64 bit systems }
+ sinttype,
+ uinttype,
+ { unsigned and signed ord type with the same size as a pointer }
+ ptruinttype,
+ ptrsinttype,
+ { several types to simulate more or less C++ objects for GDB }
+ vmttype,
+ vmtarraytype,
+ pvmttype : tdef; { type of classrefs, used for stabs }
+
+ { pointer to the anchestor of all classes }
+ class_tobject : tobjectdef;
+ { pointer to the ancestor of all COM interfaces }
+ interface_iunknown : tobjectdef;
+ { pointer to the ancestor of all dispinterfaces }
+ interface_idispatch : tobjectdef;
+ { pointer to the TGUID type
+ of all interfaces }
+ rec_tguid : trecorddef;
+
+ { pointer to jump buffer }
+ rec_jmp_buf : trecorddef;
+
+ { Objective-C base types }
+ objc_metaclasstype,
+ objc_superclasstype,
+ objc_idtype,
+ objc_seltype : tpointerdef;
+ objc_objecttype : trecorddef;
+ { base type of @protocol(protocolname) Objective-C statements }
+ objc_protocoltype : tobjectdef;
+ { helper types for for-in "fast enumeration" support in Objective-C 2.0 }
+ objc_fastenumeration : tobjectdef;
+ objc_fastenumerationstate : trecorddef;
+
+ const
+{$ifdef i386}
+ pbestrealtype : ^tdef = @s80floattype;
+{$endif}
+{$ifdef x86_64}
+ pbestrealtype : ^tdef = @s80floattype;
+{$endif}
+{$ifdef m68k}
+ pbestrealtype : ^tdef = @s64floattype;
+{$endif}
+{$ifdef alpha}
+ pbestrealtype : ^tdef = @s64floattype;
+{$endif}
+{$ifdef powerpc}
+ pbestrealtype : ^tdef = @s64floattype;
+{$endif}
+{$ifdef POWERPC64}
+ pbestrealtype : ^tdef = @s64floattype;
+{$endif}
+{$ifdef ia64}
+ pbestrealtype : ^tdef = @s64floattype;
+{$endif}
+{$ifdef SPARC}
+ pbestrealtype : ^tdef = @s64floattype;
+{$endif SPARC}
+{$ifdef vis}
+ pbestrealtype : ^tdef = @s64floattype;
+{$endif vis}
+{$ifdef ARM}
+ pbestrealtype : ^tdef = @s64floattype;
+{$endif ARM}
+{$ifdef MIPS}
+ pbestrealtype : ^tdef = @s64floattype;
+{$endif MIPS}
+{$ifdef AVR}
+ pbestrealtype : ^tdef = @s64floattype;
+{$endif AVR}
+
+ function make_mangledname(const typeprefix:string;st:TSymtable;const suffix:string):string;
+ function make_dllmangledname(const dllname,importname:string;
+ import_nr : word; pco : tproccalloption):string;
+
+ { should be in the types unit, but the types unit uses the node stuff :( }
+ function is_interfacecom(def: tdef): boolean;
+ function is_interfacecom_or_dispinterface(def: tdef): boolean;
+ function is_interfacecorba(def: tdef): boolean;
+ function is_interface(def: tdef): boolean;
+ function is_dispinterface(def: tdef): boolean;
+ function is_object(def: tdef): boolean;
+ function is_class(def: tdef): boolean;
+ function is_cppclass(def: tdef): boolean;
+ function is_objectpascal_helper(def: tdef): boolean;
+ function is_objcclass(def: tdef): boolean;
+ function is_objcclassref(def: tdef): boolean;
+ function is_objcprotocol(def: tdef): boolean;
+ function is_objccategory(def: tdef): boolean;
+ function is_objc_class_or_protocol(def: tdef): boolean;
+ function is_objc_protocol_or_category(def: tdef): boolean;
+ function is_classhelper(def: tdef): boolean;
+ function is_class_or_interface(def: tdef): boolean;
+ function is_class_or_interface_or_objc(def: tdef): boolean;
+ function is_class_or_interface_or_object(def: tdef): boolean;
+ function is_class_or_interface_or_dispinterface(def: tdef): boolean;
+ function is_implicit_pointer_object_type(def: tdef): boolean;
+ function is_class_or_object(def: tdef): boolean;
+ function is_record(def: tdef): boolean;
+
+ procedure loadobjctypes;
+ procedure maybeloadcocoatypes;
+
+ function use_vectorfpu(def : tdef) : boolean;
+
+ function getansistringcodepage:tstringencoding; inline;
+ function getansistringdef:tstringdef; inline;
+ function getparaencoding(def:tdef):tstringencoding; inline;
+
+implementation
+
+ uses
+ SysUtils,
+ cutils,
+ { global }
+ verbose,
+ { target }
+ systems,aasmcpu,paramgr,
+ { symtable }
+ symsym,symtable,symutil,defutil,objcdef,
+ { module }
+ fmodule,
+ { other }
+ gendef,
+ fpccrc
+ ;
+
+{****************************************************************************
+ Helpers
+****************************************************************************}
+
+ function getansistringcodepage:tstringencoding; inline;
+ begin
+ if cs_explicit_codepage in current_settings.moduleswitches then
+ result:=current_settings.sourcecodepage
+ else
+ result:=0;
+ end;
+
+ function getansistringdef:tstringdef; inline;
+ var
+ symtable:tsymtable;
+ begin
+ { if codepage is explicitly defined in this mudule we need to return
+ a replacement for ansistring def }
+ if cs_explicit_codepage in current_settings.moduleswitches then
+ begin
+ if not assigned(current_module) then
+ internalerror(2011101301);
+ { codepage can be redeclared only once per unit so we don't need a list of
+ redefined ansistring but only one pointer }
+ if not assigned(current_module.ansistrdef) then
+ begin
+ { if we did not create it yet we need to do this now }
+ if current_module.is_unit then
+ symtable:=current_module.globalsymtable
+ else
+ symtable:=current_module.localsymtable;
+ symtablestack.push(symtable);
+ current_module.ansistrdef:=tstringdef.createansi(current_settings.sourcecodepage);
+ symtablestack.pop(symtable);
+ end;
+ result:=tstringdef(current_module.ansistrdef);
+ end
+ else
+ result:=tstringdef(cansistringtype);
+ end;
+
+ function getparaencoding(def:tdef):tstringencoding; inline;
+ begin
+ { don't pass CP_NONE encoding to internal functions
+ they expect 0 encoding instead }
+ result:=tstringdef(def).encoding;
+ if result=CP_NONE then
+ result:=0
+ end;
+
+ function make_mangledname(const typeprefix:string;st:TSymtable;const suffix:string):string;
+ var
+ s,hs,
+ prefix : string;
+ oldlen,
+ newlen,
+ i : longint;
+ crc : dword;
+ hp : tparavarsym;
+ begin
+ prefix:='';
+ if not assigned(st) then
+ internalerror(200204212);
+ { sub procedures }
+ while (st.symtabletype=localsymtable) do
+ begin
+ if st.defowner.typ<>procdef then
+ internalerror(200204173);
+ { Add the full mangledname of procedure to prevent
+ conflicts with 2 overloads having both a nested procedure
+ with the same name, see tb0314 (PFV) }
+ s:=tprocdef(st.defowner).procsym.name;
+ oldlen:=length(s);
+ for i:=0 to tprocdef(st.defowner).paras.count-1 do
+ begin
+ hp:=tparavarsym(tprocdef(st.defowner).paras[i]);
+ if not(vo_is_hidden_para in hp.varoptions) then
+ s:=s+'$'+hp.vardef.mangledparaname;
+ end;
+ if not is_void(tprocdef(st.defowner).returndef) then
+ s:=s+'$$'+tprocdef(st.defowner).returndef.mangledparaname;
+ newlen:=length(s);
+ { Replace with CRC if the parameter line is very long }
+ if (newlen-oldlen>12) and
+ ((newlen+length(prefix)>100) or (newlen-oldlen>32)) then
+ begin
+ crc:=0;
+ for i:=0 to tprocdef(st.defowner).paras.count-1 do
+ begin
+ hp:=tparavarsym(tprocdef(st.defowner).paras[i]);
+ if not(vo_is_hidden_para in hp.varoptions) then
+ begin
+ hs:=hp.vardef.mangledparaname;
+ crc:=UpdateCrc32(crc,hs[1],length(hs));
+ end;
+ end;
+ hs:=hp.vardef.mangledparaname;
+ crc:=UpdateCrc32(crc,hs[1],length(hs));
+ s:=Copy(s,1,oldlen)+'$crc'+hexstr(crc,8);
+ end;
+ if prefix<>'' then
+ prefix:=s+'_'+prefix
+ else
+ prefix:=s;
+ if length(prefix)>100 then
+ begin
+ crc:=0;
+ crc:=UpdateCrc32(crc,prefix[1],length(prefix));
+ prefix:='$CRC'+hexstr(crc,8);
+ end;
+ st:=st.defowner.owner;
+ end;
+ { object/classes symtable, nested type definitions in classes require the while loop }
+ while st.symtabletype in [ObjectSymtable,recordsymtable] do
+ begin
+ if not (st.defowner.typ in [objectdef,recorddef]) then
+ internalerror(200204174);
+ prefix:=tabstractrecorddef(st.defowner).objname^+'_$_'+prefix;
+ st:=st.defowner.owner;
+ end;
+ { symtable must now be static or global }
+ if not(st.symtabletype in [staticsymtable,globalsymtable]) then
+ internalerror(200204175);
+
+ { The mangled name is made out of at most 4 parts:
+ 1) Optional typeprefix given as first parameter
+ with '_$' appended if not empty
+ 2) Unit name or 'P$'+program name (never empty)
+ 3) optional prefix variable that contains a unique
+ name for the local symbol table (prepended with '$_$'
+ if not empty)
+ 4) suffix as given as third parameter,
+ also optional (i.e. can be empty)
+ prepended by '_$$_' if not empty }
+ result:='';
+ if typeprefix<>'' then
+ result:=result+typeprefix+'_$';
+ { Add P$ for program, which can have the same name as
+ a unit }
+ if (TSymtable(main_module.localsymtable)=st) and
+ (not main_module.is_unit) then
+ result:=result+'P$'+st.name^
+ else
+ result:=result+st.name^;
+ if prefix<>'' then
+ result:=result+'$_$'+prefix;
+ if suffix<>'' then
+ result:=result+'_$$_'+suffix;
+ { the Darwin assembler assumes that all symbols starting with 'L' are local }
+ { Further, the Mac OS X 10.5 linker does not consider symbols which do not }
+ { start with '_' as regular symbols (it does not generate N_GSYM entries }
+ { those in the debug map, leading to troubles with dsymutil). So always }
+ { add an underscore on darwin. }
+ if (target_info.system in systems_darwin) then
+ result := '_' + result;
+ end;
+
+ function make_dllmangledname(const dllname,importname:string;import_nr : word; pco : tproccalloption):string;
+ var
+ crc : cardinal;
+ i : longint;
+ use_crc : boolean;
+ dllprefix : string;
+ begin
+ if (target_info.system in (systems_all_windows + systems_nativent +
+ [system_i386_emx, system_i386_os2]))
+ and (dllname <> '') then
+ begin
+ dllprefix:=lower(ExtractFileName(dllname));
+ { Remove .dll suffix if present }
+ if copy(dllprefix,length(dllprefix)-3,length(dllprefix))='.dll' then
+ dllprefix:=copy(dllprefix,1,length(dllprefix)-4);
+ use_crc:=false;
+ for i:=1 to length(dllprefix) do
+ if not (dllprefix[i] in ['a'..'z','A'..'Z','_','0'..'9']) then
+ begin
+ use_crc:=true;
+ break;
+ end;
+ if use_crc then
+ begin
+ crc:=0;
+ crc:=UpdateCrc32(crc,dllprefix[1],length(dllprefix));
+ dllprefix:='_$dll$crc$'+hexstr(crc,8)+'$';
+ end
+ else
+ dllprefix:='_$dll$'+dllprefix+'$';
+
+ if importname<>'' then
+ result:=dllprefix+importname
+ else
+ result:=dllprefix+'_index_'+tostr(import_nr);
+ { Replace ? and @ in import name, since GNU AS does not allow these characters in symbol names. }
+ { This allows to import VC++ mangled names from DLLs. }
+ { Do not perform replacement, if external symbol is not imported from DLL. }
+ if (dllname<>'') then
+ begin
+ Replace(result,'?','__q$$');
+ {$ifdef arm}
+ { @ symbol is not allowed in ARM assembler only }
+ Replace(result,'@','__a$$');
+ {$endif arm}
+ end;
+ end
+ else
+ begin
+ if importname<>'' then
+ begin
+ if not(pco in [pocall_cdecl,pocall_cppdecl]) then
+ result:=importname
+ else
+ result:=target_info.Cprefix+importname;
+ end
+ else
+ result:='_index_'+tostr(import_nr);
+ end;
+
+ end;
+
+{****************************************************************************
+ TDEFAWARESYMTABLESTACK
+ (symtablestack descendant that does some special actions on
+ the pushed/popped symtables)
+****************************************************************************}
+
+ procedure tdefawaresymtablestack.addhelpers(st: TSymtable);
+ var
+ i: integer;
+ s: string;
+ list: TFPObjectList;
+ def: tdef;
+ begin
+ { search the symtable from first to last; the helper to use will be the
+ last one in the list }
+ for i:=0 to st.symlist.count-1 do
+ begin
+ if not (st.symlist[i] is ttypesym) then
+ continue;
+ def:=ttypesym(st.SymList[i]).typedef;
+ if is_objectpascal_helper(def) and
+ (tobjectdef(def).extendeddef.typ in [recorddef,objectdef]) then
+ begin
+ s:=make_mangledname('',tabstractrecorddef(tobjectdef(def).extendeddef).symtable,'');
+ list:=TFPObjectList(current_module.extendeddefs.Find(s));
+ if not assigned(list) then
+ begin
+ list:=TFPObjectList.Create(false);
+ current_module.extendeddefs.Add(s,list);
+ end;
+ list.Add(def);
+ end
+ else
+ { add nested helpers as well }
+ if def.typ in [recorddef,objectdef] then
+ addhelpers(tabstractrecorddef(def).symtable);
+ end;
+ end;
+
+ procedure tdefawaresymtablestack.removehelpers(st: TSymtable);
+ var
+ i, j: integer;
+ tmpst: TSymtable;
+ list: TFPObjectList;
+ begin
+ for i:=current_module.extendeddefs.count-1 downto 0 do
+ begin
+ list:=TFPObjectList(current_module.extendeddefs[i]);
+ for j:=list.count-1 downto 0 do
+ begin
+ if not (list[j] is tobjectdef) then
+ Internalerror(2011031501);
+ tmpst:=tobjectdef(list[j]).owner;
+ repeat
+ if tmpst=st then
+ begin
+ list.delete(j);
+ break;
+ end
+ else
+ begin
+ if assigned(tmpst.defowner) then
+ tmpst:=tmpst.defowner.owner
+ else
+ tmpst:=nil;
+ end;
+ until not assigned(tmpst) or (tmpst.symtabletype in [globalsymtable,staticsymtable]);
+ end;
+ if list.count=0 then
+ current_module.extendeddefs.delete(i);
+ end;
+ end;
+
+ procedure tdefawaresymtablestack.push(st: TSymtable);
+ begin
+ { nested helpers will be added as well }
+ if (st.symtabletype in [globalsymtable,staticsymtable]) and
+ (sto_has_helper in st.tableoptions) then
+ addhelpers(st);
+ inherited push(st);
+ end;
+
+ procedure tdefawaresymtablestack.pop(st: TSymtable);
+ begin
+ inherited pop(st);
+ { nested helpers will be removed as well }
+ if (st.symtabletype in [globalsymtable,staticsymtable]) and
+ (sto_has_helper in st.tableoptions) then
+ removehelpers(st);
+ end;
+
+
+{****************************************************************************
+ TDEF (base class for definitions)
+****************************************************************************}
+
+ constructor tstoreddef.create(dt:tdeftyp);
+ var
+ insertstack : psymtablestackitem;
+ begin
+ inherited create(dt);
+ savesize := 0;
+{$ifdef EXTDEBUG}
+ fileinfo := current_filepos;
+{$endif}
+ generictokenbuf:=nil;
+ genericdef:=nil;
+ change_endian:=false;
+
+ { Don't register forwarddefs, they are disposed at the
+ end of an type block }
+ if (dt=forwarddef) then
+ exit;
+ { Register in current_module }
+ if assigned(current_module) then
+ begin
+ current_module.deflist.Add(self);
+ DefId:=current_module.deflist.Count-1;
+ end;
+ { Register in symtable stack }
+ if assigned(symtablestack) then
+ begin
+ insertstack:=symtablestack.stack;
+ while assigned(insertstack) and
+ (insertstack^.symtable.symtabletype=withsymtable) do
+ insertstack:=insertstack^.next;
+ if not assigned(insertstack) then
+ internalerror(200602044);
+ insertstack^.symtable.insertdef(self);
+ end;
+ end;
+
+
+ destructor tstoreddef.destroy;
+ begin
+ { Direct calls are not allowed, use symtable.deletedef() }
+ if assigned(owner) then
+ internalerror(200612311);
+ if assigned(generictokenbuf) then
+ begin
+ generictokenbuf.free;
+ generictokenbuf:=nil;
+ end;
+ inherited destroy;
+ end;
+
+
+ constructor tstoreddef.ppuload(dt:tdeftyp;ppufile:tcompilerppufile);
+ var
+ sizeleft,i : longint;
+ buf : array[0..255] of byte;
+ begin
+ inherited create(dt);
+ DefId:=ppufile.getlongint;
+ current_module.deflist[DefId]:=self;
+{$ifdef EXTDEBUG}
+ fillchar(fileinfo,sizeof(fileinfo),0);
+{$endif}
+ { load }
+ ppufile.getderef(typesymderef);
+ ppufile.getsmallset(defoptions);
+ ppufile.getsmallset(defstates);
+ if df_generic in defoptions then
+ begin
+ sizeleft:=ppufile.getlongint;
+ change_endian:=ppufile.change_endian;
+ initgeneric;
+ while sizeleft>0 do
+ begin
+ if sizeleft>sizeof(buf) then
+ i:=sizeof(buf)
+ else
+ i:=sizeleft;
+ ppufile.getdata(buf,i);
+ generictokenbuf.write(buf,i);
+ dec(sizeleft,i);
+ end;
+ end;
+ if df_specialization in defoptions then
+ ppufile.getderef(genericdefderef);
+ end;
+
+
+ function Tstoreddef.rtti_mangledname(rt:trttitype):string;
+ var
+ prefix : string[4];
+ begin
+ if rt=fullrtti then
+ begin
+ prefix:='RTTI';
+ include(defstates,ds_rtti_table_used);
+ end
+ else
+ begin
+ prefix:='INIT';
+ include(defstates,ds_init_table_used);
+ end;
+ if assigned(typesym) and
+ (owner.symtabletype in [staticsymtable,globalsymtable]) then
+ result:=make_mangledname(prefix,owner,typesym.name)
+ else
+ result:=make_mangledname(prefix,findunitsymtable(owner),'DEF'+tostr(DefId))
+ end;
+
+
+ function tstoreddef.OwnerHierarchyName: string;
+ var
+ tmp: tdef;
+ begin
+ tmp:=self;
+ result:='';
+ repeat
+ if tmp.owner.symtabletype in [ObjectSymtable,recordsymtable] then
+ tmp:=tdef(tmp.owner.defowner)
+ else
+ break;
+ result:=tabstractrecorddef(tmp).objrealname^+'.'+result;
+ until tmp=nil;
+ end;
+
+
+ function tstoreddef.in_currentunit: boolean;
+ var
+ st: tsymtable;
+ begin
+ st:=owner;
+ while not(st.symtabletype in [globalsymtable,staticsymtable]) do
+ st:=st.defowner.owner;
+ result:=st.iscurrentunit;
+ end;
+
+
+ function tstoreddef.getcopy : tstoreddef;
+ begin
+ Message(sym_e_cant_create_unique_type);
+ getcopy:=terrordef.create;
+ end;
+
+
+ procedure tstoreddef.ppuwrite(ppufile:tcompilerppufile);
+ var
+ sizeleft,i : longint;
+ buf : array[0..255] of byte;
+ oldintfcrc : boolean;
+ begin
+ ppufile.putlongint(DefId);
+ ppufile.putderef(typesymderef);
+ ppufile.putsmallset(defoptions);
+ oldintfcrc:=ppufile.do_crc;
+ ppufile.do_crc:=false;
+ ppufile.putsmallset(defstates);
+ if df_generic in defoptions then
+ begin
+ if assigned(generictokenbuf) then
+ begin
+ sizeleft:=generictokenbuf.size;
+ generictokenbuf.seek(0);
+ end
+ else
+ sizeleft:=0;
+ ppufile.putlongint(sizeleft);
+ while sizeleft>0 do
+ begin
+ if sizeleft>sizeof(buf) then
+ i:=sizeof(buf)
+ else
+ i:=sizeleft;
+ generictokenbuf.read(buf,i);
+ ppufile.putdata(buf,i);
+ dec(sizeleft,i);
+ end;
+ end;
+ ppufile.do_crc:=oldintfcrc;
+ if df_specialization in defoptions then
+ ppufile.putderef(genericdefderef);
+ end;
+
+
+ procedure tstoreddef.buildderef;
+ begin
+ typesymderef.build(typesym);
+ genericdefderef.build(genericdef);
+ end;
+
+
+ procedure tstoreddef.buildderefimpl;
+ begin
+ end;
+
+
+ procedure tstoreddef.deref;
+ begin
+ typesym:=ttypesym(typesymderef.resolve);
+ if df_specialization in defoptions then
+ genericdef:=tstoreddef(genericdefderef.resolve);
+ end;
+
+
+ procedure tstoreddef.derefimpl;
+ begin
+ end;
+
+
+ function tstoreddef.size : asizeint;
+ begin
+ size:=savesize;
+ end;
+
+
+ function tstoreddef.getvardef:longint;
+ begin
+ result:=varUndefined;
+ end;
+
+
+ function tstoreddef.alignment : shortint;
+ begin
+ { natural alignment by default }
+ alignment:=size_2_align(savesize);
+ { can happen if savesize = 0, e.g. for voiddef or
+ an empty record
+ }
+ if (alignment=0) then
+ alignment:=1;
+ end;
+
+
+ { returns true, if the definition can be published }
+ function tstoreddef.is_publishable : boolean;
+ begin
+ is_publishable:=false;
+ end;
+
+
+ { needs an init table }
+ function tstoreddef.needs_inittable : boolean;
+ begin
+ needs_inittable:=false;
+ end;
+
+
+ function tstoreddef.is_intregable : boolean;
+ var
+ recsize,temp: longint;
+ begin
+ is_intregable:=false;
+ case typ of
+ orddef,
+ pointerdef,
+ enumdef,
+ classrefdef:
+ is_intregable:=true;
+ procvardef :
+ is_intregable:=tprocvardef(self).is_addressonly;
+ objectdef:
+ is_intregable:=(is_implicit_pointer_object_type(self)) and not needs_inittable;
+ setdef:
+ is_intregable:=is_smallset(self);
+ recorddef:
+ begin
+ recsize:=size;
+ is_intregable:=
+ ispowerof2(recsize,temp) and
+ (recsize <= sizeof(asizeint));
+ end;
+ end;
+ end;
+
+
+ function tstoreddef.is_fpuregable : boolean;
+ begin
+{$ifdef x86}
+ result:=use_vectorfpu(self);
+{$else x86}
+ result:=(typ=floatdef) and not(cs_fp_emulation in current_settings.moduleswitches);
+{$endif x86}
+ end;
+
+
+ procedure tstoreddef.initgeneric;
+ begin
+ if assigned(generictokenbuf) then
+ internalerror(200512131);
+ generictokenbuf:=tdynamicarray.create(256);
+ end;
+
+
+{****************************************************************************
+ Tstringdef
+****************************************************************************}
+
+ constructor tstringdef.createshort(l : byte);
+ begin
+ inherited create(stringdef);
+ stringtype:=st_shortstring;
+ encoding:=0;
+ len:=l;
+ savesize:=len+1;
+ end;
+
+
+ constructor tstringdef.loadshort(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(stringdef,ppufile);
+ stringtype:=st_shortstring;
+ encoding:=0;
+ len:=ppufile.getbyte;
+ savesize:=len+1;
+ end;
+
+
+ constructor tstringdef.createlong(l : asizeint);
+ begin
+ inherited create(stringdef);
+ stringtype:=st_longstring;
+ encoding:=0;
+ len:=l;
+ savesize:=sizeof(pint);
+ end;
+
+
+ constructor tstringdef.loadlong(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(stringdef,ppufile);
+ stringtype:=st_longstring;
+ encoding:=0;
+ len:=ppufile.getasizeint;
+ savesize:=sizeof(pint);
+ end;
+
+
+ constructor tstringdef.createansi(aencoding:tstringencoding);
+ begin
+ inherited create(stringdef);
+ stringtype:=st_ansistring;
+ encoding:=aencoding;
+ len:=-1;
+ savesize:=sizeof(pint);
+ end;
+
+
+ constructor tstringdef.loadansi(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(stringdef,ppufile);
+ stringtype:=st_ansistring;
+ len:=ppufile.getaint;
+ encoding:=ppufile.getword;
+ savesize:=sizeof(pint);
+ end;
+
+
+ constructor tstringdef.createwide;
+ begin
+ inherited create(stringdef);
+ stringtype:=st_widestring;
+ encoding:=CP_UTF16;
+ len:=-1;
+ savesize:=sizeof(pint);
+ end;
+
+
+ constructor tstringdef.loadwide(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(stringdef,ppufile);
+ stringtype:=st_widestring;
+ encoding:=CP_UTF16;
+ len:=ppufile.getaint;
+ savesize:=sizeof(pint);
+ end;
+
+
+ constructor tstringdef.createunicode;
+ begin
+ inherited create(stringdef);
+ stringtype:=st_unicodestring;
+ encoding:=CP_UTF16;
+ len:=-1;
+ savesize:=sizeof(pint);
+ end;
+
+
+ constructor tstringdef.loadunicode(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(stringdef,ppufile);
+ stringtype:=st_unicodestring;
+ len:=ppufile.getaint;
+ encoding:=ppufile.getword;
+ savesize:=sizeof(pint);
+ end;
+
+
+ function tstringdef.getcopy : tstoreddef;
+ begin
+ result:=tstringdef.create(typ);
+ result.typ:=stringdef;
+ tstringdef(result).stringtype:=stringtype;
+ tstringdef(result).encoding:=encoding;
+ tstringdef(result).len:=len;
+ tstringdef(result).savesize:=savesize;
+ end;
+
+
+ function tstringdef.stringtypname:string;
+ const
+ typname:array[tstringtype] of string[10]=(
+ 'shortstr','longstr','ansistr','widestr','unicodestr'
+ );
+ begin
+ stringtypname:=typname[stringtype];
+ end;
+
+
+ procedure tstringdef.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ if stringtype=st_shortstring then
+ begin
+{$ifdef extdebug}
+ if len > 255 then internalerror(12122002);
+{$endif}
+ ppufile.putbyte(byte(len))
+ end
+ else
+ ppufile.putaint(len);
+ if stringtype in [st_ansistring,st_unicodestring] then
+ ppufile.putword(encoding);
+ case stringtype of
+ st_shortstring : ppufile.writeentry(ibshortstringdef);
+ st_longstring : ppufile.writeentry(iblongstringdef);
+ st_ansistring : ppufile.writeentry(ibansistringdef);
+ st_widestring : ppufile.writeentry(ibwidestringdef);
+ st_unicodestring : ppufile.writeentry(ibunicodestringdef);
+ end;
+ end;
+
+
+ function tstringdef.needs_inittable : boolean;
+ begin
+ needs_inittable:=stringtype in [st_ansistring,st_widestring,st_unicodestring];
+ end;
+
+
+ function tstringdef.GetTypeName : string;
+ const
+ names : array[tstringtype] of string[15] = (
+ 'ShortString','LongString','AnsiString','WideString','UnicodeString');
+ begin
+ GetTypeName:=names[stringtype];
+ end;
+
+
+ function tstringdef.getvardef : longint;
+ const
+ vardef : array[tstringtype] of longint = (
+ varUndefined,varUndefined,varString,varOleStr,varUString);
+ begin
+ result:=vardef[stringtype];
+ end;
+
+
+ function tstringdef.alignment : shortint;
+ begin
+ case stringtype of
+ st_unicodestring,
+ st_widestring,
+ st_ansistring:
+ alignment:=size_2_align(savesize);
+ st_longstring,
+ st_shortstring:
+ { char to string accesses byte 0 and 1 with one word access }
+ if (tf_requires_proper_alignment in target_info.flags) or
+ { macpas needs an alignment of 2 (MetroWerks compatible) }
+ (m_mac in current_settings.modeswitches) then
+ alignment:=size_2_align(2)
+ else
+ alignment:=size_2_align(1);
+ else
+ internalerror(200412301);
+ end;
+ end;
+
+
+ function tstringdef.getmangledparaname : string;
+ begin
+ getmangledparaname:='STRING';
+ end;
+
+
+ function tstringdef.is_publishable : boolean;
+ begin
+ is_publishable:=true;
+ end;
+
+
+{****************************************************************************
+ TENUMDEF
+****************************************************************************}
+
+ constructor tenumdef.create;
+ begin
+ inherited create(enumdef);
+ minval:=0;
+ maxval:=0;
+ calcsavesize;
+ has_jumps:=false;
+ basedef:=nil;
+ symtable:=tenumsymtable.create(self);
+ end;
+
+
+ constructor tenumdef.create_subrange(_basedef:tenumdef;_min,_max:asizeint);
+ begin
+ inherited create(enumdef);
+ minval:=_min;
+ maxval:=_max;
+ basedef:=_basedef;
+ calcsavesize;
+ has_jumps:=false;
+ symtable:=basedef.symtable.getcopy;
+ include(defoptions, df_copied_def);
+ end;
+
+
+ constructor tenumdef.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(enumdef,ppufile);
+ minval:=ppufile.getaint;
+ maxval:=ppufile.getaint;
+ savesize:=ppufile.getaint;
+ has_jumps:=false;
+ if df_copied_def in defoptions then
+ begin
+ symtable:=nil;
+ ppufile.getderef(basedefderef);
+ end
+ else
+ begin
+ // create with nil defowner first to prevent values changes on insert
+ symtable:=tenumsymtable.create(nil);
+ tenumsymtable(symtable).ppuload(ppufile);
+ symtable.defowner:=self;
+ end;
+ end;
+
+ destructor tenumdef.destroy;
+ begin
+ symtable.free;
+ symtable:=nil;
+ inherited destroy;
+ end;
+
+
+ function tenumdef.getcopy : tstoreddef;
+ begin
+ if assigned(basedef) then
+ result:=tenumdef.create_subrange(basedef,minval,maxval)
+ else
+ begin
+ result:=tenumdef.create;
+ tenumdef(result).minval:=minval;
+ tenumdef(result).maxval:=maxval;
+ tenumdef(result).symtable.free;
+ tenumdef(result).symtable:=symtable.getcopy;
+ tenumdef(result).basedef:=self;
+ end;
+ tenumdef(result).has_jumps:=has_jumps;
+ tenumdef(result).basedefderef:=basedefderef;
+ include(tenumdef(result).defoptions,df_copied_def);
+ end;
+
+
+ procedure tenumdef.calcsavesize;
+ begin
+{$IFNDEF cpu64bitaddr} {$push}{$warnings off} {$ENDIF} //comparison always false warning
+ if (current_settings.packenum=8) or (min<low(longint)) or (int64(max)>high(cardinal)) then
+ savesize:=8
+{$IFDEF not cpu64bitaddr} {$pop} {$ENDIF}
+ else
+ if (current_settings.packenum=4) or (min<low(smallint)) or (max>high(word)) then
+ savesize:=4
+ else
+ if (current_settings.packenum=2) or (min<low(shortint)) or (max>high(byte)) then
+ savesize:=2
+ else
+ savesize:=1;
+ end;
+
+
+ function tenumdef.packedbitsize: asizeint;
+ var
+ sizeval: tconstexprint;
+ power: longint;
+ begin
+ result := 0;
+ if (minval >= 0) and
+ (maxval <= 1) then
+ result := 1
+ else
+ begin
+ if (minval>=0) then
+ sizeval:=maxval
+ else
+ { don't count 0 twice }
+ sizeval:=(cutils.max(-minval,maxval)*2)-1;
+ { 256 must become 512 etc. }
+ nextpowerof2(sizeval+1,power);
+ result := power;
+ end;
+ end;
+
+
+ procedure tenumdef.setmax(_max:asizeint);
+ begin
+ maxval:=_max;
+ calcsavesize;
+ end;
+
+
+ procedure tenumdef.setmin(_min:asizeint);
+ begin
+ minval:=_min;
+ calcsavesize;
+ end;
+
+
+ function tenumdef.min:asizeint;
+ begin
+ min:=minval;
+ end;
+
+
+ function tenumdef.max:asizeint;
+ begin
+ max:=maxval;
+ end;
+
+ function tenumdef.getfirstsym: tsym;
+ var
+ i:integer;
+ begin
+ for i := 0 to symtable.SymList.Count - 1 do
+ begin
+ result:=tsym(symtable.SymList[i]);
+ if tenumsym(result).value=minval then
+ exit;
+ end;
+ result:=nil;
+ end;
+
+
+ procedure tenumdef.buildderef;
+ begin
+ inherited buildderef;
+ if df_copied_def in defoptions then
+ basedefderef.build(basedef)
+ else
+ tenumsymtable(symtable).buildderef;
+ end;
+
+
+ procedure tenumdef.deref;
+ begin
+ inherited deref;
+ if df_copied_def in defoptions then
+ begin
+ basedef:=tenumdef(basedefderef.resolve);
+ symtable:=basedef.symtable.getcopy;
+ end
+ else
+ tenumsymtable(symtable).deref;
+ end;
+
+
+ procedure tenumdef.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putaint(min);
+ ppufile.putaint(max);
+ ppufile.putaint(savesize);
+ if df_copied_def in defoptions then
+ ppufile.putderef(basedefderef);
+ ppufile.writeentry(ibenumdef);
+ if not (df_copied_def in defoptions) then
+ tenumsymtable(symtable).ppuwrite(ppufile);
+ end;
+
+
+ function tenumdef.is_publishable : boolean;
+ begin
+ is_publishable:=true;
+ end;
+
+
+ function tenumdef.GetTypeName : string;
+ begin
+ GetTypeName:='<enumeration type>';
+ end;
+
+
+{****************************************************************************
+ TORDDEF
+****************************************************************************}
+
+ constructor torddef.create(t : tordtype;v,b : TConstExprInt);
+ begin
+ inherited create(orddef);
+ low:=v;
+ high:=b;
+ ordtype:=t;
+ setsize;
+ end;
+
+
+ constructor torddef.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(orddef,ppufile);
+ ordtype:=tordtype(ppufile.getbyte);
+ low:=ppufile.getexprint;
+ high:=ppufile.getexprint;
+ setsize;
+ end;
+
+
+ function torddef.getcopy : tstoreddef;
+ begin
+ result:=torddef.create(ordtype,low,high);
+ result.typ:=orddef;
+ torddef(result).low:=low;
+ torddef(result).high:=high;
+ torddef(result).ordtype:=ordtype;
+ torddef(result).savesize:=savesize;
+ end;
+
+
+ function torddef.alignment:shortint;
+ begin
+ if (target_info.system in [system_i386_darwin,system_i386_iphonesim,system_arm_darwin]) and
+ (ordtype in [s64bit,u64bit]) then
+ result := 4
+ else
+ result := inherited alignment;
+ end;
+
+
+ procedure torddef.setsize;
+ const
+ sizetbl : array[tordtype] of longint = (
+ 0,
+ 1,2,4,8,
+ 1,2,4,8,
+ 1,2,4,8,
+ 1,2,4,8,
+ 1,2,8
+ );
+ begin
+ savesize:=sizetbl[ordtype];
+ end;
+
+
+ function torddef.packedbitsize: asizeint;
+ var
+ sizeval: tconstexprint;
+ power: longint;
+ begin
+ result := 0;
+ if ordtype = uvoid then
+ exit;
+
+{$ifndef cpu64bitalu}
+ if (ordtype in [s64bit,u64bit]) then
+{$else not cpu64bitalu}
+ if (ordtype = u64bit) or
+ ((ordtype = s64bit) and
+ ((low <= (system.low(int64) div 2)) or
+ (high > (system.high(int64) div 2)))) then
+{$endif cpu64bitalu}
+ result := 64
+ else if (low >= 0) and
+ (high <= 1) then
+ result := 1
+ else
+ begin
+ if (low>=0) then
+ sizeval:=high
+ else
+ { don't count 0 twice }
+ sizeval:=(cutils.max(-low,high)*2)-1;
+ { 256 must become 512 etc. }
+ nextpowerof2(sizeval+1,power);
+ result := power;
+ end;
+ end;
+
+
+ function torddef.getvardef : longint;
+ const
+ basetype2vardef : array[tordtype] of longint = (
+ varUndefined,
+ varbyte,varword,varlongword,varqword,
+ varshortint,varsmallint,varinteger,varint64,
+ varboolean,varboolean,varboolean,varboolean,
+ varboolean,varboolean,varUndefined,varUndefined,
+ varUndefined,varUndefined,varCurrency);
+ begin
+ result:=basetype2vardef[ordtype];
+ end;
+
+
+ procedure torddef.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putbyte(byte(ordtype));
+ ppufile.putexprint(low);
+ ppufile.putexprint(high);
+ ppufile.writeentry(iborddef);
+ end;
+
+
+ function torddef.is_publishable : boolean;
+ begin
+ is_publishable:=(ordtype<>uvoid);
+ end;
+
+
+ function torddef.GetTypeName : string;
+ const
+ names : array[tordtype] of string[20] = (
+ 'untyped',
+ 'Byte','Word','DWord','QWord',
+ 'ShortInt','SmallInt','LongInt','Int64',
+ 'Boolean','Boolean16','Boolean32','Boolean64',
+ 'ByteBool','WordBool','LongBool','QWordBool',
+ 'Char','WideChar','Currency');
+
+ begin
+ GetTypeName:=names[ordtype];
+ end;
+
+
+{****************************************************************************
+ TFLOATDEF
+****************************************************************************}
+
+ constructor tfloatdef.create(t : tfloattype);
+ begin
+ inherited create(floatdef);
+ floattype:=t;
+ setsize;
+ end;
+
+
+ constructor tfloatdef.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(floatdef,ppufile);
+ floattype:=tfloattype(ppufile.getbyte);
+ setsize;
+ end;
+
+
+ function tfloatdef.getcopy : tstoreddef;
+ begin
+ result:=tfloatdef.create(floattype);
+ result.typ:=floatdef;
+ tfloatdef(result).savesize:=savesize;
+ end;
+
+
+ function tfloatdef.alignment:shortint;
+ begin
+ if (target_info.system in [system_i386_darwin,system_i386_iphonesim,system_arm_darwin]) then
+ case floattype of
+ sc80real,
+ s80real: result:=16;
+ s64real,
+ s64currency,
+ s64comp : result:=4;
+ else
+ result := inherited alignment;
+ end
+ else
+ result := inherited alignment;
+ end;
+
+
+ procedure tfloatdef.setsize;
+ begin
+ case floattype of
+ s32real : savesize:=4;
+ s80real : savesize:=10;
+ sc80real:
+ if target_info.system in [system_i386_darwin,system_i386_iphonesim,system_x86_64_darwin,
+ system_x86_64_linux,system_x86_64_freebsd,
+ system_x86_64_solaris,system_x86_64_embedded] then
+ savesize:=16
+ else
+ savesize:=12;
+ s64real,
+ s64currency,
+ s64comp : savesize:=8;
+ else
+ savesize:=0;
+ end;
+ end;
+
+
+ function tfloatdef.getvardef : longint;
+ const
+ floattype2vardef : array[tfloattype] of longint = (
+ varSingle,varDouble,varUndefined,varUndefined,
+ varUndefined,varCurrency,varUndefined);
+ begin
+ if (upper(typename)='TDATETIME') and
+ assigned(owner) and
+ assigned(owner.name) and
+ (owner.name^='SYSTEM') then
+ result:=varDate
+ else
+ result:=floattype2vardef[floattype];
+ end;
+
+
+ procedure tfloatdef.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putbyte(byte(floattype));
+ ppufile.writeentry(ibfloatdef);
+ end;
+
+
+ function tfloatdef.is_publishable : boolean;
+ begin
+ is_publishable:=true;
+ end;
+
+
+ function tfloatdef.GetTypeName : string;
+ const
+ names : array[tfloattype] of string[20] = (
+ 'Single','Double','Extended','CExtended','Comp','Currency','Float128');
+ begin
+ GetTypeName:=names[floattype];
+ end;
+
+
+{****************************************************************************
+ TFILEDEF
+****************************************************************************}
+
+ constructor tfiledef.createtext;
+ begin
+ inherited create(filedef);
+ filetyp:=ft_text;
+ typedfiledef:=nil;
+ setsize;
+ end;
+
+
+ constructor tfiledef.createuntyped;
+ begin
+ inherited create(filedef);
+ filetyp:=ft_untyped;
+ typedfiledef:=nil;
+ setsize;
+ end;
+
+
+ constructor tfiledef.createtyped(def:tdef);
+ begin
+ inherited create(filedef);
+ filetyp:=ft_typed;
+ typedfiledef:=def;
+ setsize;
+ end;
+
+
+ constructor tfiledef.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(filedef,ppufile);
+ filetyp:=tfiletyp(ppufile.getbyte);
+ if filetyp=ft_typed then
+ ppufile.getderef(typedfiledefderef)
+ else
+ typedfiledef:=nil;
+ setsize;
+ end;
+
+
+ function tfiledef.getcopy : tstoreddef;
+ begin
+ case filetyp of
+ ft_typed:
+ result:=tfiledef.createtyped(typedfiledef);
+ ft_untyped:
+ result:=tfiledef.createuntyped;
+ ft_text:
+ result:=tfiledef.createtext;
+ else
+ internalerror(2004121201);
+ end;
+ end;
+
+
+ procedure tfiledef.buildderef;
+ begin
+ inherited buildderef;
+ if filetyp=ft_typed then
+ typedfiledefderef.build(typedfiledef);
+ end;
+
+
+ procedure tfiledef.deref;
+ begin
+ inherited deref;
+ if filetyp=ft_typed then
+ typedfiledef:=tdef(typedfiledefderef.resolve);
+ end;
+
+
+ procedure tfiledef.setsize;
+ begin
+{$ifdef cpu64bitaddr}
+ case filetyp of
+ ft_text :
+ if target_info.system in [system_x86_64_win64,system_ia64_win64] then
+ savesize:=634{+8}
+ else
+ savesize:=630{+8};
+ ft_typed,
+ ft_untyped :
+ if target_info.system in [system_x86_64_win64,system_ia64_win64] then
+ savesize:=372
+ else
+ savesize:=368;
+ end;
+{$endif cpu64bitaddr}
+{$ifdef cpu32bitaddr}
+ case filetyp of
+ ft_text :
+ savesize:=594{+4};
+ ft_typed,
+ ft_untyped :
+ savesize:=332;
+ end;
+{$endif cpu32bitaddr}
+{$ifdef cpu8bitaddr}
+ case filetyp of
+ ft_text :
+ savesize:=127;
+ ft_typed,
+ ft_untyped :
+ savesize:=127;
+ end;
+{$endif cpu8bitaddr}
+ end;
+
+
+ procedure tfiledef.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putbyte(byte(filetyp));
+ if filetyp=ft_typed then
+ ppufile.putderef(typedfiledefderef);
+ ppufile.writeentry(ibfiledef);
+ end;
+
+
+ function tfiledef.GetTypeName : string;
+ begin
+ case filetyp of
+ ft_untyped:
+ GetTypeName:='File';
+ ft_typed:
+ GetTypeName:='File Of '+typedfiledef.typename;
+ ft_text:
+ GetTypeName:='Text'
+ end;
+ end;
+
+
+ function tfiledef.getmangledparaname : string;
+ begin
+ case filetyp of
+ ft_untyped:
+ getmangledparaname:='FILE';
+ ft_typed:
+ getmangledparaname:='FILE$OF$'+typedfiledef.mangledparaname;
+ ft_text:
+ getmangledparaname:='TEXT'
+ end;
+ end;
+
+
+{****************************************************************************
+ TVARIANTDEF
+****************************************************************************}
+
+ constructor tvariantdef.create(v : tvarianttype);
+ begin
+ inherited create(variantdef);
+ varianttype:=v;
+ setsize;
+ end;
+
+
+ constructor tvariantdef.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(variantdef,ppufile);
+ varianttype:=tvarianttype(ppufile.getbyte);
+ setsize;
+ end;
+
+
+ function tvariantdef.getcopy : tstoreddef;
+ begin
+ result:=tvariantdef.create(varianttype);
+ end;
+
+
+ procedure tvariantdef.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putbyte(byte(varianttype));
+ ppufile.writeentry(ibvariantdef);
+ end;
+
+
+ function tvariantdef.getvardef : longint;
+ begin
+ Result:=varVariant;
+ end;
+
+
+ procedure tvariantdef.setsize;
+ begin
+{$ifdef cpu64bitaddr}
+ savesize:=24;
+{$else cpu64bitaddr}
+ savesize:=16;
+{$endif cpu64bitaddr}
+ end;
+
+
+ function tvariantdef.GetTypeName : string;
+ begin
+ case varianttype of
+ vt_normalvariant:
+ GetTypeName:='Variant';
+ vt_olevariant:
+ GetTypeName:='OleVariant';
+ end;
+ end;
+
+
+ function tvariantdef.needs_inittable : boolean;
+ begin
+ needs_inittable:=true;
+ end;
+
+
+ function tvariantdef.is_publishable : boolean;
+ begin
+ is_publishable:=true;
+ end;
+
+
+{****************************************************************************
+ TABSTRACtpointerdef
+****************************************************************************}
+
+ constructor tabstractpointerdef.create(dt:tdeftyp;def:tdef);
+ begin
+ inherited create(dt);
+ pointeddef:=def;
+ savesize:=sizeof(pint);
+ end;
+
+
+ constructor tabstractpointerdef.ppuload(dt:tdeftyp;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(dt,ppufile);
+ ppufile.getderef(pointeddefderef);
+ savesize:=sizeof(pint);
+ end;
+
+
+ procedure tabstractpointerdef.buildderef;
+ begin
+ inherited buildderef;
+ pointeddefderef.build(pointeddef);
+ end;
+
+
+ procedure tabstractpointerdef.deref;
+ begin
+ inherited deref;
+ pointeddef:=tdef(pointeddefderef.resolve);
+ end;
+
+
+ procedure tabstractpointerdef.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putderef(pointeddefderef);
+ end;
+
+
+{****************************************************************************
+ tpointerdef
+****************************************************************************}
+
+ constructor tpointerdef.create(def:tdef);
+ begin
+ inherited create(pointerdef,def);
+ is_far:=false;
+ has_pointer_math:=cs_pointermath in current_settings.localswitches;
+ end;
+
+
+ constructor tpointerdef.createfar(def:tdef);
+ begin
+ inherited create(pointerdef,def);
+ is_far:=true;
+ has_pointer_math:=cs_pointermath in current_settings.localswitches;
+ end;
+
+
+ constructor tpointerdef.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(pointerdef,ppufile);
+ is_far:=(ppufile.getbyte<>0);
+ has_pointer_math:=(ppufile.getbyte<>0);
+ end;
+
+
+ function tpointerdef.getcopy : tstoreddef;
+ begin
+ { don't use direct pointeddef if it is a forwarddef because in other case
+ one of them will be destroyed on forward type resolve and the second will
+ point to garbage }
+ if pointeddef.typ=forwarddef then
+ result:=tpointerdef.create(tforwarddef(pointeddef).getcopy)
+ else
+ result:=tpointerdef.create(pointeddef);
+ tpointerdef(result).is_far:=is_far;
+ tpointerdef(result).has_pointer_math:=has_pointer_math;
+ tpointerdef(result).savesize:=savesize;
+ end;
+
+
+ procedure tpointerdef.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putbyte(byte(is_far));
+ ppufile.putbyte(byte(has_pointer_math));
+ ppufile.writeentry(ibpointerdef);
+ end;
+
+
+ function tpointerdef.GetTypeName : string;
+ begin
+ if is_far then
+ GetTypeName:='^'+pointeddef.typename+';far'
+ else
+ GetTypeName:='^'+pointeddef.typename;
+ end;
+
+
+{****************************************************************************
+ TCLASSREFDEF
+****************************************************************************}
+
+ constructor tclassrefdef.create(def:tdef);
+ begin
+ inherited create(classrefdef,def);
+ end;
+
+
+ constructor tclassrefdef.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(classrefdef,ppufile);
+ end;
+
+
+ procedure tclassrefdef.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.writeentry(ibclassrefdef);
+ end;
+
+
+ function tclassrefdef.getcopy:tstoreddef;
+ begin
+ if pointeddef.typ=forwarddef then
+ result:=tclassrefdef.create(tforwarddef(pointeddef).getcopy)
+ else
+ result:=tclassrefdef.create(pointeddef);
+ tclassrefdef(result).savesize:=savesize;
+ end;
+
+
+ function tclassrefdef.GetTypeName : string;
+ begin
+ GetTypeName:='Class Of '+pointeddef.typename;
+ end;
+
+
+ function tclassrefdef.is_publishable : boolean;
+ begin
+ result:=true;
+ end;
+
+
+ function tclassrefdef.rtti_mangledname(rt: trttitype): string;
+ begin
+ if (tobjectdef(pointeddef).objecttype<>odt_objcclass) then
+ result:=inherited rtti_mangledname(rt)
+ else
+ result:=tobjectdef(pointeddef).rtti_mangledname(objcmetartti);
+ end;
+
+
+ procedure tclassrefdef.register_created_object_type;
+ begin
+ tobjectdef(pointeddef).register_created_classref_type;
+ end;
+
+{***************************************************************************
+ TSETDEF
+***************************************************************************}
+
+ constructor tsetdef.create(def:tdef;low, high : asizeint);
+ var
+ setallocbits: aint;
+ packedsavesize: aint;
+ begin
+ inherited create(setdef);
+ elementdef:=def;
+ setmax:=high;
+ if (current_settings.setalloc=0) then
+ begin
+ setbase:=0;
+ if (high<32) then
+ savesize:=Sizeof(longint)
+ else if (high<256) then
+ savesize:=32
+ else
+ savesize:=(high+7) div 8
+ end
+ else
+ begin
+ setallocbits:=current_settings.setalloc*8;
+ setbase:=low and not(setallocbits-1);
+ packedsavesize:=current_settings.setalloc*((((high+setallocbits)-setbase)) DIV setallocbits);
+ savesize:=packedsavesize;
+ if savesize=3 then
+ savesize:=4;
+ end;
+ end;
+
+
+ constructor tsetdef.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(setdef,ppufile);
+ ppufile.getderef(elementdefderef);
+ savesize:=ppufile.getaint;
+ setbase:=ppufile.getaint;
+ setmax:=ppufile.getaint;
+ end;
+
+
+ function tsetdef.getcopy : tstoreddef;
+ begin
+ result:=tsetdef.create(elementdef,setbase,setmax);
+ { the copy might have been created with a different setalloc setting }
+ tsetdef(result).savesize:=savesize;
+ end;
+
+
+ procedure tsetdef.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putderef(elementdefderef);
+ ppufile.putaint(savesize);
+ ppufile.putaint(setbase);
+ ppufile.putaint(setmax);
+ ppufile.writeentry(ibsetdef);
+ end;
+
+
+ procedure tsetdef.buildderef;
+ begin
+ inherited buildderef;
+ elementdefderef.build(elementdef);
+ end;
+
+
+ procedure tsetdef.deref;
+ begin
+ inherited deref;
+ elementdef:=tdef(elementdefderef.resolve);
+ end;
+
+
+ function tsetdef.is_publishable : boolean;
+ begin
+ is_publishable:=savesize in [1,2,4];
+ end;
+
+
+ function tsetdef.GetTypeName : string;
+ begin
+ if assigned(elementdef) then
+ GetTypeName:='Set Of '+elementdef.typename
+ else
+ GetTypeName:='Empty Set';
+ end;
+
+
+{***************************************************************************
+ TFORMALDEF
+***************************************************************************}
+
+ constructor tformaldef.create(Atyped:boolean);
+ begin
+ inherited create(formaldef);
+ typed:=Atyped;
+ savesize:=0;
+ end;
+
+
+ constructor tformaldef.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(formaldef,ppufile);
+ typed:=boolean(ppufile.getbyte);
+ savesize:=0;
+ end;
+
+
+ procedure tformaldef.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putbyte(byte(typed));
+ ppufile.writeentry(ibformaldef);
+ end;
+
+
+ function tformaldef.GetTypeName : string;
+ begin
+ if typed then
+ GetTypeName:='<Typed formal type>'
+ else
+ GetTypeName:='<Formal type>';
+ end;
+
+
+{***************************************************************************
+ TARRAYDEF
+***************************************************************************}
+
+ constructor tarraydef.create(l,h:asizeint;def:tdef);
+ begin
+ inherited create(arraydef);
+ lowrange:=l;
+ highrange:=h;
+ rangedef:=def;
+ _elementdef:=nil;
+ arrayoptions:=[];
+ symtable:=tarraysymtable.create(self);
+ end;
+
+ destructor tarraydef.destroy;
+ begin
+ symtable.free;
+ symtable:=nil;
+ inherited;
+ end;
+
+ constructor tarraydef.create_from_pointer(def:tdef);
+ begin
+ { use -1 so that the elecount will not overflow }
+ self.create(0,high(aint)-1,ptrsinttype);
+ arrayoptions:=[ado_IsConvertedPointer];
+ setelementdef(def);
+ end;
+
+
+ constructor tarraydef.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(arraydef,ppufile);
+ { the addresses are calculated later }
+ ppufile.getderef(_elementdefderef);
+ ppufile.getderef(rangedefderef);
+ lowrange:=ppufile.getaint;
+ highrange:=ppufile.getaint;
+ ppufile.getsmallset(arrayoptions);
+ symtable:=tarraysymtable.create(self);
+ tarraysymtable(symtable).ppuload(ppufile)
+ end;
+
+
+ function tarraydef.getcopy : tstoreddef;
+ begin
+ result:=tarraydef.create(lowrange,highrange,rangedef);
+ tarraydef(result).arrayoptions:=arrayoptions;
+ tarraydef(result)._elementdef:=_elementdef;
+ end;
+
+
+ procedure tarraydef.buildderef;
+ begin
+ inherited buildderef;
+ tarraysymtable(symtable).buildderef;
+ _elementdefderef.build(_elementdef);
+ rangedefderef.build(rangedef);
+ end;
+
+
+ procedure tarraydef.deref;
+ begin
+ inherited deref;
+ tarraysymtable(symtable).deref;
+ _elementdef:=tdef(_elementdefderef.resolve);
+ rangedef:=tdef(rangedefderef.resolve);
+ end;
+
+
+ procedure tarraydef.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putderef(_elementdefderef);
+ ppufile.putderef(rangedefderef);
+ ppufile.putaint(lowrange);
+ ppufile.putaint(highrange);
+ ppufile.putsmallset(arrayoptions);
+ ppufile.writeentry(ibarraydef);
+ tarraysymtable(symtable).ppuwrite(ppufile);
+ end;
+
+
+ function tarraydef.elesize : asizeint;
+ begin
+ if (ado_IsBitPacked in arrayoptions) then
+ internalerror(2006080101);
+ if assigned(_elementdef) then
+ result:=_elementdef.size
+ else
+ result:=0;
+ end;
+
+
+ function tarraydef.elepackedbitsize : asizeint;
+ begin
+ if not(ado_IsBitPacked in arrayoptions) then
+ internalerror(2006080102);
+ if assigned(_elementdef) then
+ result:=_elementdef.packedbitsize
+ else
+ result:=0;
+ end;
+
+
+ function tarraydef.elecount : asizeuint;
+ var
+ qhigh,qlow : qword;
+ begin
+ if ado_IsDynamicArray in arrayoptions then
+ begin
+ result:=0;
+ exit;
+ end;
+ if (highrange>0) and (lowrange<0) then
+ begin
+ qhigh:=highrange;
+ qlow:=qword(-lowrange);
+ { prevent overflow, return 0 to indicate overflow }
+ if qhigh+qlow>qword(high(asizeint)-1) then
+ result:=0
+ else
+ result:=qhigh+qlow+1;
+ end
+ else
+ result:=int64(highrange)-lowrange+1;
+ end;
+
+
+ function tarraydef.size : asizeint;
+ var
+ cachedelecount : asizeuint;
+ cachedelesize : asizeint;
+ begin
+ if ado_IsDynamicArray in arrayoptions then
+ begin
+ size:=sizeof(pint);
+ exit;
+ end;
+
+ { Tarraydef.size may never be called for an open array! }
+ if highrange<lowrange then
+ internalerror(99080501);
+ if not (ado_IsBitPacked in arrayoptions) then
+ cachedelesize:=elesize
+ else
+ cachedelesize := elepackedbitsize;
+ cachedelecount:=elecount;
+
+ if (cachedelesize = 0) then
+ begin
+ size := 0;
+ exit;
+ end;
+
+ if (cachedelecount = 0) then
+ begin
+ size := -1;
+ exit;
+ end;
+
+ { prevent overflow, return -1 to indicate overflow }
+ { also make sure we don't need 64/128 bit arithmetic to calculate offsets }
+ if (cachedelecount > asizeuint(high(asizeint))) or
+ ((high(asizeint) div cachedelesize) < asizeint(cachedelecount)) or
+ { also lowrange*elesize must be < high(asizeint) to prevent overflow when
+ accessing the array, see ncgmem (PFV) }
+ ((high(asizeint) div cachedelesize) < abs(lowrange)) then
+ begin
+ result:=-1;
+ exit;
+ end;
+
+ result:=cachedelesize*asizeint(cachedelecount);
+ if (ado_IsBitPacked in arrayoptions) then
+ { can't just add 7 and divide by 8, because that may overflow }
+ result:=result div 8 + ord((result mod 8)<>0);
+ end;
+
+
+ procedure tarraydef.setelementdef(def:tdef);
+ begin
+ _elementdef:=def;
+ if not(
+ (ado_IsDynamicArray in arrayoptions) or
+ (ado_IsConvertedPointer in arrayoptions) or
+ (highrange<lowrange)
+ ) and
+ (size=-1) then
+ Message(sym_e_segment_too_large);
+ end;
+
+
+ function tarraydef.alignment : shortint;
+ begin
+ { alignment of dyn. arrays doesn't depend on the element size }
+ if (ado_IsDynamicArray in arrayoptions) then
+ alignment:=size_2_align(sizeof(pint))
+ { alignment is the alignment of the elements }
+ else if (elementdef.typ in [arraydef,recorddef,orddef,enumdef,floatdef]) or
+ ((elementdef.typ=objectdef) and
+ is_object(elementdef)) then
+ alignment:=elementdef.alignment
+ { alignment is the size of the elements }
+ else if not (ado_IsBitPacked in arrayoptions) then
+ alignment:=size_2_align(elesize)
+ else
+ alignment:=packedbitsloadsize(elepackedbitsize);
+ end;
+
+
+ function tarraydef.needs_inittable : boolean;
+ begin
+ needs_inittable:=(ado_IsDynamicArray in arrayoptions) or elementdef.needs_inittable;
+ end;
+
+
+ function tarraydef.GetTypeName : string;
+ begin
+ if (ado_IsConstString in arrayoptions) then
+ result:='Constant String'
+ else if (ado_isarrayofconst in arrayoptions) or
+ (ado_isConstructor in arrayoptions) then
+ begin
+ if (ado_isvariant in arrayoptions) or ((highrange=-1) and (lowrange=0)) then
+ GetTypeName:='Array Of Const'
+ else
+ GetTypeName:='Array Of Const/Constant Open Array of '+elementdef.typename;
+ end
+ else if (ado_IsDynamicArray in arrayoptions) then
+ GetTypeName:='Dynamic Array Of '+elementdef.typename
+ else if ((highrange=-1) and (lowrange=0)) then
+ GetTypeName:='Open Array Of '+elementdef.typename
+ else
+ begin
+ result := '';
+ if (ado_IsBitPacked in arrayoptions) then
+ result:='Packed ';
+ if rangedef.typ=enumdef then
+ result:=result+'Array['+rangedef.typename+'] Of '+elementdef.typename
+ else
+ result:=result+'Array['+tostr(lowrange)+'..'+
+ tostr(highrange)+'] Of '+elementdef.typename
+ end;
+ end;
+
+
+ function tarraydef.getmangledparaname : string;
+ begin
+ if ado_isarrayofconst in arrayoptions then
+ getmangledparaname:='array_of_const'
+ else
+ if ((highrange=-1) and (lowrange=0)) then
+ getmangledparaname:='array_of_'+elementdef.mangledparaname
+ else
+ internalerror(200204176);
+ end;
+
+
+ function tarraydef.is_publishable : boolean;
+ begin
+ Result:=ado_IsDynamicArray in arrayoptions;
+ end;
+
+{***************************************************************************
+ tabstractrecorddef
+***************************************************************************}
+
+ constructor tabstractrecorddef.create(const n:string; dt:tdeftyp);
+ begin
+ inherited create(dt);
+ objname:=stringdup(upper(n));
+ objrealname:=stringdup(n);
+ objectoptions:=[];
+ end;
+
+ constructor tabstractrecorddef.ppuload(dt:tdeftyp;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(dt,ppufile);
+ objrealname:=stringdup(ppufile.getstring);
+ objname:=stringdup(upper(objrealname^));
+ ppufile.getsmallset(objectoptions);
+ end;
+
+ procedure tabstractrecorddef.ppuwrite(ppufile: tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putstring(objrealname^);
+ ppufile.putsmallset(objectoptions);
+ end;
+
+ destructor tabstractrecorddef.destroy;
+ begin
+ stringdispose(objname);
+ stringdispose(objrealname);
+ inherited destroy;
+ end;
+
+ procedure tabstractrecorddef.check_forwards;
+ begin
+ tstoredsymtable(symtable).check_forwards;
+ end;
+
+ function tabstractrecorddef.find_procdef_bytype(pt:tproctypeoption): tprocdef;
+ var
+ i: longint;
+ sym: tsym;
+ begin
+ for i:=0 to symtable.SymList.Count-1 do
+ begin
+ sym:=tsym(symtable.SymList[i]);
+ if sym.typ=procsym then
+ begin
+ result:=tprocsym(sym).find_procdef_bytype(pt);
+ if assigned(result) then
+ exit;
+ end;
+ end;
+ result:=nil;
+ end;
+
+ function tabstractrecorddef.GetSymtable(t:tGetSymtable):TSymtable;
+ begin
+ if t=gs_record then
+ GetSymtable:=symtable
+ else
+ GetSymtable:=nil;
+ end;
+
+
+ function tabstractrecorddef.is_packed:boolean;
+ begin
+ result:=tabstractrecordsymtable(symtable).is_packed;
+ end;
+
+ function tabstractrecorddef.RttiName: string;
+ begin
+ Result:=OwnerHierarchyName+objrealname^;
+ end;
+
+ function tabstractrecorddef.search_enumerator_get: tprocdef;
+ var
+ sym : tsym;
+ i : integer;
+ pd : tprocdef;
+ hashedid : THashedIDString;
+ begin
+ result:=nil;
+ hashedid.id:='GETENUMERATOR';
+ sym:=tsym(symtable.FindWithHash(hashedid));
+ if assigned(sym) and (sym.typ=procsym) then
+ begin
+ for i := 0 to Tprocsym(sym).ProcdefList.Count - 1 do
+ begin
+ pd := tprocdef(Tprocsym(sym).ProcdefList[i]);
+ if (pd.proctypeoption = potype_function) and
+ (is_class_or_interface_or_object(pd.returndef) or is_record(pd.returndef)) and
+ (pd.visibility >= vis_public) then
+ begin
+ result:=pd;
+ exit;
+ end;
+ end;
+ end;
+ end;
+
+ function tabstractrecorddef.search_enumerator_move: tprocdef;
+ var
+ sym : tsym;
+ i : integer;
+ pd : tprocdef;
+ hashedid : THashedIDString;
+ begin
+ result:=nil;
+ // first search for po_enumerator_movenext method modifier
+ // then search for public function MoveNext: Boolean
+ for i:=0 to symtable.SymList.Count-1 do
+ begin
+ sym:=TSym(symtable.SymList[i]);
+ if (sym.typ=procsym) then
+ begin
+ pd:=Tprocsym(sym).find_procdef_byoptions([po_enumerator_movenext]);
+ if assigned(pd) then
+ begin
+ result:=pd;
+ exit;
+ end;
+ end;
+ end;
+ hashedid.id:='MOVENEXT';
+ sym:=tsym(symtable.FindWithHash(hashedid));
+ if assigned(sym) and (sym.typ=procsym) then
+ begin
+ for i:=0 to Tprocsym(sym).ProcdefList.Count-1 do
+ begin
+ pd := tprocdef(Tprocsym(sym).ProcdefList[i]);
+ if (pd.proctypeoption = potype_function) and
+ is_boolean(pd.returndef) and
+ (pd.minparacount = 0) and
+ (pd.visibility >= vis_public) then
+ begin
+ result:=pd;
+ exit;
+ end;
+ end;
+ end;
+ end;
+
+ function tabstractrecorddef.search_enumerator_current: tsym;
+ var
+ sym: tsym;
+ i: integer;
+ hashedid : THashedIDString;
+ begin
+ result:=nil;
+ // first search for ppo_enumerator_current property modifier
+ // then search for public property Current
+ for i:=0 to symtable.SymList.Count-1 do
+ begin
+ sym:=TSym(symtable.SymList[i]);
+ if (sym.typ=propertysym) and (ppo_enumerator_current in tpropertysym(sym).propoptions) then
+ begin
+ result:=sym;
+ exit;
+ end;
+ end;
+ hashedid.id:='CURRENT';
+ sym:=tsym(symtable.FindWithHash(hashedid));
+ if assigned(sym) and (sym.typ=propertysym) and
+ (sym.visibility >= vis_public) and not tpropertysym(sym).propaccesslist[palt_read].empty then
+ begin
+ result:=sym;
+ exit;
+ end;
+ end;
+
+{***************************************************************************
+ trecorddef
+***************************************************************************}
+
+ constructor trecorddef.create(const n:string; p:TSymtable);
+ begin
+ inherited create(n,recorddef);
+ symtable:=p;
+ { we can own the symtable only if nobody else owns a copy so far }
+ if symtable.refcount=1 then
+ symtable.defowner:=self;
+ isunion:=false;
+ end;
+
+
+ constructor trecorddef.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(recorddef,ppufile);
+ if df_copied_def in defoptions then
+ ppufile.getderef(cloneddefderef)
+ else
+ begin
+ symtable:=trecordsymtable.create(objrealname^,0);
+ trecordsymtable(symtable).fieldalignment:=shortint(ppufile.getbyte);
+ trecordsymtable(symtable).recordalignment:=shortint(ppufile.getbyte);
+ trecordsymtable(symtable).padalignment:=shortint(ppufile.getbyte);
+ trecordsymtable(symtable).usefieldalignment:=shortint(ppufile.getbyte);
+ trecordsymtable(symtable).datasize:=ppufile.getasizeint;
+ trecordsymtable(symtable).paddingsize:=ppufile.getword;
+ trecordsymtable(symtable).ppuload(ppufile);
+ { requires usefieldalignment to be set }
+ symtable.defowner:=self;
+ end;
+ isunion:=false;
+ end;
+
+
+ destructor trecorddef.destroy;
+ begin
+ if assigned(symtable) then
+ begin
+ symtable.free;
+ symtable:=nil;
+ end;
+ inherited destroy;
+ end;
+
+
+ function trecorddef.getcopy : tstoreddef;
+ begin
+ result:=trecorddef.create(objrealname^,symtable.getcopy);
+ trecorddef(result).isunion:=isunion;
+ include(trecorddef(result).defoptions,df_copied_def);
+ end;
+
+
+ function trecorddef.needs_inittable : boolean;
+ begin
+ needs_inittable:=trecordsymtable(symtable).needs_init_final
+ end;
+
+
+ procedure trecorddef.buildderef;
+ begin
+ inherited buildderef;
+ if df_copied_def in defoptions then
+ cloneddefderef.build(symtable.defowner)
+ else
+ tstoredsymtable(symtable).buildderef;
+ end;
+
+
+ procedure trecorddef.deref;
+ begin
+ inherited deref;
+ { now dereference the definitions }
+ if df_copied_def in defoptions then
+ begin
+ cloneddef:=trecorddef(cloneddefderef.resolve);
+ symtable:=cloneddef.symtable.getcopy;
+ end
+ else
+ tstoredsymtable(symtable).deref;
+
+ { assign TGUID? load only from system unit }
+ if not(assigned(rec_tguid)) and
+ (upper(typename)='TGUID') and
+ assigned(owner) and
+ assigned(owner.name) and
+ (owner.name^='SYSTEM') then
+ rec_tguid:=self;
+
+ { assign JMP_BUF? load only from system unit }
+ if not(assigned(rec_jmp_buf)) and
+ (upper(typename)='JMP_BUF') and
+ assigned(owner) and
+ assigned(owner.name) and
+ (owner.name^='SYSTEM') then
+ rec_jmp_buf:=self;
+ end;
+
+
+ procedure trecorddef.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ if df_copied_def in defoptions then
+ ppufile.putderef(cloneddefderef)
+ else
+ begin
+ ppufile.putbyte(byte(trecordsymtable(symtable).fieldalignment));
+ ppufile.putbyte(byte(trecordsymtable(symtable).recordalignment));
+ ppufile.putbyte(byte(trecordsymtable(symtable).padalignment));
+ ppufile.putbyte(byte(trecordsymtable(symtable).usefieldalignment));
+ ppufile.putasizeint(trecordsymtable(symtable).datasize);
+ ppufile.putword(trecordsymtable(symtable).paddingsize);
+ end;
+
+ ppufile.writeentry(ibrecorddef);
+
+ if not(df_copied_def in defoptions) then
+ trecordsymtable(symtable).ppuwrite(ppufile);
+ end;
+
+
+ function trecorddef.size:asizeint;
+ begin
+ result:=trecordsymtable(symtable).datasize;
+ end;
+
+
+ function trecorddef.alignment:shortint;
+ begin
+ alignment:=trecordsymtable(symtable).recordalignment;
+ end;
+
+
+ function trecorddef.padalignment:shortint;
+ begin
+ padalignment := trecordsymtable(symtable).padalignment;
+ end;
+
+
+ function trecorddef.GetTypeName : string;
+ begin
+ GetTypeName:='<record type>'
+ end;
+
+
+{***************************************************************************
+ TABSTRACTPROCDEF
+***************************************************************************}
+
+ constructor tabstractprocdef.create(dt:tdeftyp;level:byte);
+ begin
+ inherited create(dt);
+ parast:=tparasymtable.create(self,level);
+ paras:=nil;
+ minparacount:=0;
+ maxparacount:=0;
+ proctypeoption:=potype_none;
+ proccalloption:=pocall_none;
+ procoptions:=[];
+ returndef:=voidtype;
+ savesize:=sizeof(pint);
+ callerargareasize:=0;
+ calleeargareasize:=0;
+ has_paraloc_info:=callnoside;
+ funcretloc[callerside].init;
+ funcretloc[calleeside].init;
+ check_mark_as_nested;
+ end;
+
+
+ destructor tabstractprocdef.destroy;
+ begin
+ if assigned(paras) then
+ begin
+{$ifdef MEMDEBUG}
+ memprocpara.start;
+{$endif MEMDEBUG}
+ paras.free;
+ paras:=nil;
+{$ifdef MEMDEBUG}
+ memprocpara.stop;
+{$endif MEMDEBUG}
+ end;
+ if assigned(parast) then
+ begin
+{$ifdef MEMDEBUG}
+ memprocparast.start;
+{$endif MEMDEBUG}
+ parast.free;
+ parast:=nil;
+{$ifdef MEMDEBUG}
+ memprocparast.stop;
+{$endif MEMDEBUG}
+ end;
+ funcretloc[callerside].done;
+ funcretloc[calleeside].done;
+ inherited destroy;
+ end;
+
+
+ procedure tabstractprocdef.count_para(p:TObject;arg:pointer);
+ begin
+ if (tsym(p).typ<>paravarsym) then
+ exit;
+ inc(plongint(arg)^);
+ if not(vo_is_hidden_para in tparavarsym(p).varoptions) then
+ begin
+ if not assigned(tparavarsym(p).defaultconstsym) then
+ inc(minparacount);
+ inc(maxparacount);
+ end;
+ end;
+
+
+ procedure tabstractprocdef.insert_para(p:TObject;arg:pointer);
+ begin
+ if (tsym(p).typ<>paravarsym) then
+ exit;
+ paras.add(p);
+ end;
+
+
+ procedure tabstractprocdef.calcparas;
+ var
+ paracount : longint;
+ begin
+ { This can already be assigned when
+ we need to reresolve this unit (PFV) }
+ if assigned(paras) then
+ paras.free;
+ paras:=tparalist.create(false);
+ paracount:=0;
+ minparacount:=0;
+ maxparacount:=0;
+ parast.SymList.ForEachCall(@count_para,@paracount);
+ paras.capacity:=paracount;
+ { Insert parameters in table }
+ parast.SymList.ForEachCall(@insert_para,nil);
+ { Order parameters }
+ paras.sortparas;
+ end;
+
+
+ procedure tabstractprocdef.buildderef;
+ begin
+ { released procdef? }
+ if not assigned(parast) then
+ exit;
+ inherited buildderef;
+ returndefderef.build(returndef);
+ { parast }
+ tparasymtable(parast).buildderef;
+ end;
+
+
+ procedure tabstractprocdef.deref;
+ begin
+ inherited deref;
+ returndef:=tdef(returndefderef.resolve);
+ { parast }
+ tparasymtable(parast).deref;
+ { recalculated parameters }
+ calcparas;
+ end;
+
+
+ constructor tabstractprocdef.ppuload(dt:tdeftyp;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(dt,ppufile);
+ parast:=nil;
+ Paras:=nil;
+ minparacount:=0;
+ maxparacount:=0;
+ ppufile.getderef(returndefderef);
+{ TODO: remove fpu_used loading}
+ ppufile.getbyte;
+ proctypeoption:=tproctypeoption(ppufile.getbyte);
+ proccalloption:=tproccalloption(ppufile.getbyte);
+ ppufile.getnormalset(procoptions);
+
+ funcretloc[callerside].init;
+ if po_explicitparaloc in procoptions then
+ funcretloc[callerside].ppuload(ppufile);
+
+ savesize:=sizeof(pint);
+ if (po_explicitparaloc in procoptions) then
+ has_paraloc_info:=callerside;
+ end;
+
+
+ procedure tabstractprocdef.ppuwrite(ppufile:tcompilerppufile);
+ var
+ oldintfcrc : boolean;
+ begin
+ { released procdef? }
+ if not assigned(parast) then
+ exit;
+ inherited ppuwrite(ppufile);
+ ppufile.putderef(returndefderef);
+ oldintfcrc:=ppufile.do_interface_crc;
+ ppufile.do_interface_crc:=false;
+ ppufile.putbyte(0);
+ ppufile.putbyte(ord(proctypeoption));
+ ppufile.putbyte(ord(proccalloption));
+ ppufile.putnormalset(procoptions);
+ ppufile.do_interface_crc:=oldintfcrc;
+
+ if (po_explicitparaloc in procoptions) then
+ funcretloc[callerside].ppuwrite(ppufile);
+ end;
+
+
+ function tabstractprocdef.typename_paras(showhidden:boolean) : string;
+ var
+ hs,s : string;
+ hp : TParavarsym;
+ hpc : tconstsym;
+ first : boolean;
+ i : integer;
+ begin
+ s:='';
+ first:=true;
+ for i:=0 to paras.count-1 do
+ begin
+ hp:=tparavarsym(paras[i]);
+ if not(vo_is_hidden_para in hp.varoptions) or
+ (showhidden) then
+ begin
+ if first then
+ begin
+ s:=s+'(';
+ first:=false;
+ end
+ else
+ s:=s+',';
+ if vo_is_hidden_para in hp.varoptions then
+ s:=s+'<';
+ case hp.varspez of
+ vs_var :
+ s:=s+'var ';
+ vs_const :
+ s:=s+'const ';
+ vs_out :
+ s:=s+'out ';
+ vs_constref :
+ s:=s+'constref ';
+ end;
+ if hp.univpara then
+ s:=s+'univ ';
+ if assigned(hp.vardef.typesym) then
+ begin
+ hs:=hp.vardef.typesym.realname;
+ if hs[1]<>'$' then
+ s:=s+hs
+ else
+ s:=s+hp.vardef.GetTypeName;
+ end
+ else
+ s:=s+hp.vardef.GetTypeName;
+ { default value }
+ if assigned(hp.defaultconstsym) then
+ begin
+ hpc:=tconstsym(hp.defaultconstsym);
+ hs:='';
+ case hpc.consttyp of
+ conststring,
+ constresourcestring :
+ begin
+ If hpc.value.len>0 then
+ begin
+ setLength(hs,hpc.value.len);
+ { don't write past the end of hs if the constant
+ is > 255 chars }
+ move(hpc.value.valueptr^,hs[1],length(hs));
+ { make sure that constant strings with newline chars
+ don't create a linebreak in the assembler code,
+ since comments are line-based. Also remove nulls
+ because the comments are written as a pchar. }
+ ReplaceCase(hs,#0,'.');
+ ReplaceCase(hs,#10,'.');
+ ReplaceCase(hs,#13,'.');
+ end;
+ end;
+ constreal :
+ str(pbestreal(hpc.value.valueptr)^,hs);
+ constpointer :
+ hs:=tostr(hpc.value.valueordptr);
+ constord :
+ begin
+ if is_boolean(hpc.constdef) then
+ begin
+ if hpc.value.valueord<>0 then
+ hs:='TRUE'
+ else
+ hs:='FALSE';
+ end
+ else
+ hs:=tostr(hpc.value.valueord);
+ end;
+ constnil :
+ hs:='nil';
+ constset :
+ hs:='<set>';
+ end;
+ if hs<>'' then
+ s:=s+'="'+hs+'"';
+ end;
+ if vo_is_hidden_para in hp.varoptions then
+ s:=s+'>';
+ end;
+ end;
+ if not first then
+ s:=s+')';
+ if (po_varargs in procoptions) then
+ s:=s+';VarArgs';
+ typename_paras:=s;
+ end;
+
+
+ function tabstractprocdef.is_methodpointer:boolean;
+ begin
+ result:=false;
+ end;
+
+
+ function tabstractprocdef.is_addressonly:boolean;
+ begin
+ result:=true;
+ end;
+
+ function tabstractprocdef.no_self_node: boolean;
+ begin
+ Result:=([po_staticmethod,po_classmethod]<=procoptions)or
+ (proctypeoption in [potype_class_constructor,potype_class_destructor,potype_operator]);
+ end;
+
+
+ procedure tabstractprocdef.check_mark_as_nested;
+ begin
+ { nested procvars require that nested functions use the Delphi-style
+ nested procedure calling convention }
+ if (parast.symtablelevel>normal_function_level) and
+ (m_nested_procvars in current_settings.modeswitches) then
+ include(procoptions,po_delphi_nested_cc);
+ end;
+
+
+ procedure tabstractprocdef.init_paraloc_info(side: tcallercallee);
+ begin
+ if (side in [callerside,callbothsides]) and
+ not(has_paraloc_info in [callerside,callbothsides]) then
+ begin
+ callerargareasize:=paramanager.create_paraloc_info(self,callerside);
+ if has_paraloc_info in [calleeside,callbothsides] then
+ has_paraloc_info:=callbothsides
+ else
+ has_paraloc_info:=callerside;
+ end;
+ if (side in [calleeside,callbothsides]) and
+ not(has_paraloc_info in [calleeside,callbothsides]) then
+ begin
+ calleeargareasize:=paramanager.create_paraloc_info(self,calleeside);
+ if has_paraloc_info in [callerside,callbothsides] then
+ has_paraloc_info:=callbothsides
+ else
+ has_paraloc_info:=calleeside;
+ end;
+ end;
+
+
+ function tabstractprocdef.stack_tainting_parameter(side: tcallercallee): boolean;
+ var
+ p: tparavarsym;
+ ploc: PCGParalocation;
+ i: longint;
+ begin
+ result:=false;
+ init_paraloc_info(side);
+ for i:=0 to parast.SymList.Count-1 do
+ if tsym(parast.SymList[i]).typ=paravarsym then
+ begin
+ p:=tparavarsym(parast.SymList[i]);
+ { check if no parameter is located on the stack }
+ if is_open_array(p.vardef) or
+ is_array_of_const(p.vardef) then
+ begin
+ result:=true;
+ exit;
+ end;
+ ploc:=p.paraloc[side].location;
+ while assigned(ploc) do
+ begin
+ if (ploc^.loc=LOC_REFERENCE) then
+ begin
+ result:=true;
+ exit
+ end;
+ ploc:=ploc^.next;
+ end;
+ end;
+ end;
+
+
+
+
+{***************************************************************************
+ TPROCDEF
+***************************************************************************}
+
+ constructor tprocdef.create(level:byte);
+ begin
+ inherited create(procdef,level);
+ localst:=tlocalsymtable.create(self,parast.symtablelevel);
+ _mangledname:=nil;
+ fileinfo:=current_filepos;
+ extnumber:=$ffff;
+ aliasnames:=TCmdStrList.create;
+ funcretsym:=nil;
+ forwarddef:=true;
+ interfacedef:=false;
+ hasforward:=false;
+ struct := nil;
+ import_dll:=nil;
+ import_name:=nil;
+ import_nr:=0;
+ inlininginfo:=nil;
+ deprecatedmsg:=nil;
+{$ifdef i386}
+ fpu_used:=maxfpuregs;
+{$endif i386}
+ interruptvector:=-1;
+ end;
+
+
+ constructor tprocdef.ppuload(ppufile:tcompilerppufile);
+ var
+ i,aliasnamescount : longint;
+ level : byte;
+ begin
+ inherited ppuload(procdef,ppufile);
+ if po_has_mangledname in procoptions then
+ _mangledname:=stringdup(ppufile.getstring)
+ else
+ _mangledname:=nil;
+ extnumber:=ppufile.getword;
+ level:=ppufile.getbyte;
+ ppufile.getderef(structderef);
+ ppufile.getderef(procsymderef);
+ ppufile.getposinfo(fileinfo);
+ visibility:=tvisibility(ppufile.getbyte);
+ ppufile.getsmallset(symoptions);
+ if sp_has_deprecated_msg in symoptions then
+ deprecatedmsg:=stringdup(ppufile.getstring)
+ else
+ deprecatedmsg:=nil;
+{$ifdef powerpc}
+ { library symbol for AmigaOS/MorphOS }
+ ppufile.getderef(libsymderef);
+{$endif powerpc}
+ { import stuff }
+ if po_has_importdll in procoptions then
+ import_dll:=stringdup(ppufile.getstring)
+ else
+ import_dll:=nil;
+ if po_has_importname in procoptions then
+ import_name:=stringdup(ppufile.getstring)
+ else
+ import_name:=nil;
+ import_nr:=ppufile.getword;
+{$ifdef FPC_HAS_SYSTEMS_INTERRUPT_TABLE}
+ if target_info.system in systems_interrupt_table then
+ interruptvector:=ppufile.getlongint;
+{$endif FPC_HAS_SYSTEMS_INTERRUPT_TABLE}
+ if (po_msgint in procoptions) then
+ messageinf.i:=ppufile.getlongint;
+ if (po_msgstr in procoptions) then
+ messageinf.str:=stringdup(ppufile.getstring);
+ if (po_dispid in procoptions) then
+ dispid:=ppufile.getlongint;
+ { inline stuff }
+ if (po_has_inlininginfo in procoptions) then
+ begin
+ ppufile.getderef(funcretsymderef);
+ new(inlininginfo);
+ ppufile.getsmallset(inlininginfo^.flags);
+ end
+ else
+ begin
+ inlininginfo:=nil;
+ funcretsym:=nil;
+ end;
+
+ aliasnames:=TCmdStrList.create;
+ { count alias names }
+ aliasnamescount:=ppufile.getbyte;
+ for i:=1 to aliasnamescount do
+ aliasnames.insert(ppufile.getstring);
+
+ { load para symtable }
+ parast:=tparasymtable.create(self,level);
+ tparasymtable(parast).ppuload(ppufile);
+ { load local symtable }
+ if (po_has_inlininginfo in procoptions) then
+ begin
+ localst:=tlocalsymtable.create(self,level);
+ tlocalsymtable(localst).ppuload(ppufile);
+ end
+ else
+ localst:=nil;
+ { inline stuff }
+ if (po_has_inlininginfo in procoptions) then
+ inlininginfo^.code:=ppuloadnodetree(ppufile);
+ { default values for no persistent data }
+ if (cs_link_deffile in current_settings.globalswitches) and
+ (tf_need_export in target_info.flags) and
+ (po_exports in procoptions) then
+ deffile.AddExport(mangledname);
+ forwarddef:=false;
+ interfacedef:=false;
+ hasforward:=false;
+ { Disable po_has_inlining until the derefimpl is done }
+ exclude(procoptions,po_has_inlininginfo);
+{$ifdef i386}
+ fpu_used:=maxfpuregs;
+{$endif i386}
+ end;
+
+
+ destructor tprocdef.destroy;
+ begin
+ aliasnames.free;
+ aliasnames:=nil;
+ if assigned(localst) and
+ (localst.symtabletype<>staticsymtable) then
+ begin
+{$ifdef MEMDEBUG}
+ memproclocalst.start;
+{$endif MEMDEBUG}
+ localst.free;
+ localst:=nil;
+{$ifdef MEMDEBUG}
+ memproclocalst.start;
+{$endif MEMDEBUG}
+ end;
+ if assigned(inlininginfo) then
+ begin
+{$ifdef MEMDEBUG}
+ memprocnodetree.start;
+{$endif MEMDEBUG}
+ tnode(inlininginfo^.code).free;
+{$ifdef MEMDEBUG}
+ memprocnodetree.start;
+{$endif MEMDEBUG}
+ dispose(inlininginfo);
+ inlininginfo:=nil;
+ end;
+ stringdispose(resultname);
+ stringdispose(import_dll);
+ stringdispose(import_name);
+ stringdispose(deprecatedmsg);
+ if (po_msgstr in procoptions) then
+ stringdispose(messageinf.str);
+ if assigned(_mangledname) then
+ begin
+{$ifdef MEMDEBUG}
+ memmanglednames.start;
+{$endif MEMDEBUG}
+ stringdispose(_mangledname);
+{$ifdef MEMDEBUG}
+ memmanglednames.stop;
+{$endif MEMDEBUG}
+ end;
+ inherited destroy;
+ end;
+
+
+ procedure tprocdef.ppuwrite(ppufile:tcompilerppufile);
+ var
+ oldintfcrc : boolean;
+ aliasnamescount : longint;
+ item : TCmdStrListItem;
+ begin
+ { released procdef? }
+ if not assigned(parast) then
+ exit;
+
+ inherited ppuwrite(ppufile);
+ if po_has_mangledname in procoptions then
+ ppufile.putstring(_mangledname^);
+
+ ppufile.putword(extnumber);
+ ppufile.putbyte(parast.symtablelevel);
+ ppufile.putderef(structderef);
+ ppufile.putderef(procsymderef);
+ ppufile.putposinfo(fileinfo);
+ ppufile.putbyte(byte(visibility));
+ ppufile.putsmallset(symoptions);
+ if sp_has_deprecated_msg in symoptions then
+ ppufile.putstring(deprecatedmsg^);
+{$ifdef powerpc}
+ { library symbol for AmigaOS/MorphOS }
+ ppufile.putderef(libsymderef);
+{$endif powerpc}
+ { import }
+ if po_has_importdll in procoptions then
+ ppufile.putstring(import_dll^);
+ if po_has_importname in procoptions then
+ ppufile.putstring(import_name^);
+ ppufile.putword(import_nr);
+{$ifdef FPC_HAS_SYSTEMS_INTERRUPT_TABLE}
+ if target_info.system in systems_interrupt_table then
+ ppufile.putlongint(interruptvector);
+{$endif FPC_HAS_SYSTEMS_INTERRUPT_TABLE}
+ if (po_msgint in procoptions) then
+ ppufile.putlongint(messageinf.i);
+ if (po_msgstr in procoptions) then
+ ppufile.putstring(messageinf.str^);
+ if (po_dispid in procoptions) then
+ ppufile.putlongint(dispid);
+ { inline stuff }
+ oldintfcrc:=ppufile.do_crc;
+ ppufile.do_crc:=false;
+ if (po_has_inlininginfo in procoptions) then
+ begin
+ ppufile.putderef(funcretsymderef);
+ ppufile.putsmallset(inlininginfo^.flags);
+ end;
+
+ { count alias names }
+ aliasnamescount:=0;
+ item:=TCmdStrListItem(aliasnames.first);
+ while assigned(item) do
+ begin
+ inc(aliasnamescount);
+ item:=TCmdStrListItem(item.next);
+ end;
+ if aliasnamescount>255 then
+ internalerror(200711021);
+ ppufile.putbyte(aliasnamescount);
+ item:=TCmdStrListItem(aliasnames.first);
+ while assigned(item) do
+ begin
+ ppufile.putstring(item.str);
+ item:=TCmdStrListItem(item.next);
+ end;
+
+ ppufile.do_crc:=oldintfcrc;
+
+ { write this entry }
+ ppufile.writeentry(ibprocdef);
+
+ { Save the para symtable, this is taken from the interface }
+ tparasymtable(parast).ppuwrite(ppufile);
+
+ { save localsymtable for inline procedures or when local
+ browser info is requested, this has no influence on the crc }
+ if (po_has_inlininginfo in procoptions) then
+ begin
+ oldintfcrc:=ppufile.do_crc;
+ ppufile.do_crc:=false;
+ tlocalsymtable(localst).ppuwrite(ppufile);
+ ppufile.do_crc:=oldintfcrc;
+ end;
+
+ { node tree for inlining }
+ oldintfcrc:=ppufile.do_crc;
+ ppufile.do_crc:=false;
+ if (po_has_inlininginfo in procoptions) then
+ ppuwritenodetree(ppufile,inlininginfo^.code);
+ ppufile.do_crc:=oldintfcrc;
+ end;
+
+
+ function tprocdef.fullprocname(showhidden:boolean):string;
+ var
+ s : string;
+ t : ttoken;
+ begin
+{$ifdef EXTDEBUG}
+ showhidden:=true;
+{$endif EXTDEBUG}
+ s:='';
+ if assigned(struct) then
+ begin
+ s:=struct.RttiName+'.';
+ if (po_classmethod in procoptions) and
+ not (proctypeoption in [potype_class_constructor,potype_class_destructor]) then
+ s:='class ' + s;
+ end;
+ if proctypeoption=potype_operator then
+ begin
+ for t:=NOTOKEN to last_overloaded do
+ if procsym.realname='$'+overloaded_names[t] then
+ begin
+ s:='operator '+arraytokeninfo[t].str+typename_paras(showhidden);
+ break;
+ end;
+ end
+ else
+ s:=s+procsym.realname+typename_paras(showhidden);
+ case proctypeoption of
+ potype_constructor:
+ s:='constructor '+s;
+ potype_destructor:
+ s:='destructor '+s;
+ potype_class_constructor:
+ s:='class constructor '+s;
+ potype_class_destructor:
+ s:='class destructor '+s;
+ else
+ if assigned(returndef) and
+ not(is_void(returndef)) then
+ s:=s+':'+returndef.GetTypeName;
+ end;
+ if owner.symtabletype=localsymtable then
+ s:=s+' is nested';
+ s:=s+';';
+ { forced calling convention? }
+ if (po_hascallingconvention in procoptions) then
+ s:=s+' '+ProcCallOptionStr[proccalloption]+';';
+ if (po_staticmethod in procoptions) and
+ not (proctypeoption in [potype_class_constructor,potype_class_destructor]) then
+ s:=s+' Static;';
+ fullprocname:=s;
+ end;
+
+
+ function tprocdef.is_methodpointer:boolean;
+ begin
+ { don't check assigned(_class), that's also the case for nested
+ procedures inside methods }
+ result:=owner.symtabletype=ObjectSymtable;
+ end;
+
+
+ function tprocdef.is_addressonly:boolean;
+ begin
+ result:=assigned(owner) and
+ (owner.symtabletype<>ObjectSymtable) and
+ (not(m_nested_procvars in current_settings.modeswitches) or
+ not is_nested_pd(self));
+ end;
+
+
+ procedure tprocdef.make_external;
+ begin
+ include(procoptions,po_external);
+ forwarddef:=false;
+ end;
+
+
+ function tprocdef.GetSymtable(t:tGetSymtable):TSymtable;
+ begin
+ case t of
+ gs_local :
+ GetSymtable:=localst;
+ gs_para :
+ GetSymtable:=parast;
+ else
+ GetSymtable:=nil;
+ end;
+ end;
+
+
+ procedure tprocdef.buildderef;
+ begin
+ inherited buildderef;
+ structderef.build(struct);
+ { procsym that originaly defined this definition, should be in the
+ same symtable }
+ procsymderef.build(procsym);
+{$ifdef powerpc}
+ { library symbol for AmigaOS/MorphOS }
+ libsymderef.build(libsym);
+{$endif powerpc}
+ end;
+
+
+ procedure tprocdef.buildderefimpl;
+ begin
+ inherited buildderefimpl;
+
+ { Localst is not available for main/unit init }
+ if assigned(localst) then
+ begin
+ tlocalsymtable(localst).buildderef;
+ tlocalsymtable(localst).buildderefimpl;
+ end;
+
+ { inline tree }
+ if (po_has_inlininginfo in procoptions) then
+ begin
+ funcretsymderef.build(funcretsym);
+ inlininginfo^.code.buildderefimpl;
+ end;
+ end;
+
+
+ procedure tprocdef.deref;
+ begin
+ inherited deref;
+ struct:=tabstractrecorddef(structderef.resolve);
+ { procsym that originaly defined this definition, should be in the
+ same symtable }
+ procsym:=tprocsym(procsymderef.resolve);
+{$ifdef powerpc}
+ { library symbol for AmigaOS/MorphOS }
+ libsym:=tsym(libsymderef.resolve);
+{$endif powerpc}
+ end;
+
+
+ procedure tprocdef.derefimpl;
+ begin
+ { Enable has_inlininginfo when the inlininginfo
+ structure is available. The has_inlininginfo was disabled
+ after the load, since the data was invalid }
+ if assigned(inlininginfo) then
+ include(procoptions,po_has_inlininginfo);
+
+ { Locals }
+ if assigned(localst) then
+ begin
+ tlocalsymtable(localst).deref;
+ tlocalsymtable(localst).derefimpl;
+ end;
+
+ { Inline }
+ if (po_has_inlininginfo in procoptions) then
+ begin
+ inlininginfo^.code.derefimpl;
+ { funcretsym, this is always located in the localst }
+ funcretsym:=tsym(funcretsymderef.resolve);
+ end
+ else
+ begin
+ { safety }
+ { Not safe! A unit may be reresolved after its interface has been
+ parsed but before its implementation has been parsed, and in that
+ case the funcretsym is still required!
+ funcretsym:=nil; }
+ end;
+ end;
+
+
+ function tprocdef.GetTypeName : string;
+ begin
+ GetTypeName := FullProcName(false);
+ end;
+
+
+ function tprocdef.mangledname : string;
+ var
+ hp : TParavarsym;
+ hs : string;
+ crc : dword;
+ newlen,
+ oldlen,
+ i : integer;
+ begin
+ if assigned(_mangledname) then
+ begin
+ {$ifdef compress}
+ mangledname:=minilzw_decode(_mangledname^);
+ {$else}
+ mangledname:=_mangledname^;
+ {$endif}
+ exit;
+ end;
+ { we need to use the symtable where the procsym is inserted,
+ because that is visible to the world }
+ mangledname:=make_mangledname('',procsym.owner,procsym.name);
+ oldlen:=length(mangledname);
+ { add parameter types }
+ for i:=0 to paras.count-1 do
+ begin
+ hp:=tparavarsym(paras[i]);
+ if not(vo_is_hidden_para in hp.varoptions) then
+ mangledname:=mangledname+'$'+hp.vardef.mangledparaname;
+ end;
+ { add resultdef, add $$ as separator to make it unique from a
+ parameter separator }
+ if not is_void(returndef) then
+ mangledname:=mangledname+'$$'+returndef.mangledparaname;
+ newlen:=length(mangledname);
+ { Replace with CRC if the parameter line is very long }
+ if (newlen-oldlen>12) and
+ ((newlen>100) or (newlen-oldlen>64)) then
+ begin
+ crc:=0;
+ for i:=0 to paras.count-1 do
+ begin
+ hp:=tparavarsym(paras[i]);
+ if not(vo_is_hidden_para in hp.varoptions) then
+ begin
+ hs:=hp.vardef.mangledparaname;
+ crc:=UpdateCrc32(crc,hs[1],length(hs));
+ end;
+ end;
+ hs:=hp.vardef.mangledparaname;
+ crc:=UpdateCrc32(crc,hs[1],length(hs));
+ mangledname:=Copy(mangledname,1,oldlen)+'$crc'+hexstr(crc,8);
+ end;
+ {$ifdef compress}
+ _mangledname:=stringdup(minilzw_encode(mangledname));
+ {$else}
+ _mangledname:=stringdup(mangledname);
+ {$endif}
+ end;
+
+
+ function tprocdef.cplusplusmangledname : string;
+
+ function getcppparaname(p : tdef) : string;
+
+ const
+{$ifdef NAMEMANGLING_GCC2}
+ ordtype2str : array[tordtype] of string[2] = (
+ '',
+ 'Uc','Us','Ui','Us',
+ 'Sc','s','i','x',
+ 'b','b','b','b','b',
+ 'c','w','x');
+{$else NAMEMANGLING_GCC2}
+ ordtype2str : array[tordtype] of string[1] = (
+ 'v',
+ 'h','t','j','y',
+ 'a','s','i','x',
+ 'b','b','b','b',
+ 'b','b','b','b',
+ 'c','w','x');
+
+ floattype2str : array[tfloattype] of string[1] = (
+ 'f','d','e','e',
+ 'd','d','g');
+{$endif NAMEMANGLING_GCC2}
+
+ var
+ s : string;
+
+ begin
+ case p.typ of
+ orddef:
+ s:=ordtype2str[torddef(p).ordtype];
+ pointerdef:
+ s:='P'+getcppparaname(tpointerdef(p).pointeddef);
+{$ifndef NAMEMANGLING_GCC2}
+ floatdef:
+ s:=floattype2str[tfloatdef(p).floattype];
+{$endif NAMEMANGLING_GCC2}
+ else
+ internalerror(2103001);
+ end;
+ getcppparaname:=s;
+ end;
+
+ var
+ s,s2 : string;
+ hp : TParavarsym;
+ i : integer;
+
+ begin
+{$ifdef NAMEMANGLING_GCC2}
+
+ { outdated gcc 2.x name mangling scheme }
+ s := procsym.realname;
+ if procsym.owner.symtabletype=ObjectSymtable then
+ begin
+ s2:=upper(tobjectdef(procsym.owner.defowner).objrealname^);
+ case proctypeoption of
+ potype_destructor:
+ s:='_$_'+tostr(length(s2))+s2;
+ potype_constructor:
+ s:='___'+tostr(length(s2))+s2;
+ else
+ s:='_'+s+'__'+tostr(length(s2))+s2;
+ end;
+
+ end
+ else s:=s+'__';
+
+ s:=s+'F';
+
+ { concat modifiers }
+ { !!!!! }
+
+ { now we handle the parameters }
+ if maxparacount>0 then
+ begin
+ for i:=0 to paras.count-1 do
+ begin
+ hp:=tparavarsym(paras[i]);
+ { no hidden parameters form part of a C++ mangled name:
+ a) self is not included
+ b) there are no "high" or other hidden parameters
+ }
+ if vo_is_hidden_para in hp.varoptions then
+ continue;
+ s2:=getcppparaname(hp.vardef);
+ if hp.varspez in [vs_var,vs_out] then
+ s2:='R'+s2;
+ s:=s+s2;
+ end;
+ end
+ else
+ s:=s+'v';
+ cplusplusmangledname:=s;
+{$else NAMEMANGLING_GCC2}
+
+ { gcc 3.x and 4.x name mangling scheme }
+ { see http://www.codesourcery.com/public/cxx-abi/abi.html#mangling }
+ if procsym.owner.symtabletype=ObjectSymtable then
+ begin
+ s:='_ZN';
+
+ s2:=tobjectdef(procsym.owner.defowner).objextname^;
+ s:=s+tostr(length(s2))+s2;
+ case proctypeoption of
+ potype_constructor:
+ s:=s+'C1';
+ potype_destructor:
+ s:=s+'D1';
+ else
+ s:=s+tostr(length(procsym.realname))+procsym.realname;
+ end;
+
+ s:=s+'E';
+ end
+ else
+ s:=procsym.realname;
+
+ { now we handle the parameters }
+ if maxparacount>0 then
+ begin
+ for i:=0 to paras.count-1 do
+ begin
+ hp:=tparavarsym(paras[i]);
+ { no hidden parameters form part of a C++ mangled name:
+ a) self is not included
+ b) there are no "high" or other hidden parameters
+ }
+ if vo_is_hidden_para in hp.varoptions then
+ continue;
+ s2:=getcppparaname(hp.vardef);
+ if hp.varspez in [vs_var,vs_out] then
+ s2:='R'+s2;
+ s:=s+s2;
+ end;
+ end
+ else
+ s:=s+'v';
+ cplusplusmangledname:=s;
+{$endif NAMEMANGLING_GCC2}
+ end;
+
+
+ function tprocdef.objcmangledname : string;
+ var
+ manglednamelen: longint;
+ iscatmethod : boolean;
+ begin
+ if not (po_msgstr in procoptions) then
+ internalerror(2009030901);
+ { we may very well need longer strings to handle these... }
+ manglednamelen:=length(tobjectdef(procsym.owner.defowner).objextname^)+
+ length('+"[ ]"')+length(messageinf.str^);
+ iscatmethod:=oo_is_classhelper in tobjectdef(procsym.owner.defowner).objectoptions;
+ if (iscatmethod) then
+ inc(manglednamelen,length(tobjectdef(procsym.owner.defowner).childof.objextname^)+length('()'));
+ if manglednamelen>255 then
+ Message1(parser_e_objc_message_name_too_long,messageinf.str^);
+ if not(po_classmethod in procoptions) then
+ result:='"-['
+ else
+ result:='"+[';
+ { quotes are necessary because the +/- otherwise confuse the assembler
+ into expecting a number
+ }
+ if iscatmethod then
+ result:=result+tobjectdef(procsym.owner.defowner).childof.objextname^+'(';
+ result:=result+tobjectdef(procsym.owner.defowner).objextname^;
+ if iscatmethod then
+ result:=result+')';
+ result:=result+' '+messageinf.str^+']"';
+ end;
+
+
+ procedure tprocdef.setmangledname(const s : string);
+ begin
+ { This is not allowed anymore, the forward declaration
+ already needs to create the correct mangledname, no changes
+ afterwards are allowed (PFV) }
+ { Exception: interface definitions in mode macpas, since in that }
+ { case no reference to the old name can exist yet (JM) }
+ if assigned(_mangledname) then
+ if ((m_mac in current_settings.modeswitches) and
+ (interfacedef)) then
+ stringdispose(_mangledname)
+ else
+ internalerror(200411171);
+ {$ifdef compress}
+ _mangledname:=stringdup(minilzw_encode(s));
+ {$else}
+ _mangledname:=stringdup(s);
+ {$endif}
+ include(procoptions,po_has_mangledname);
+ end;
+
+
+{***************************************************************************
+ TPROCVARDEF
+***************************************************************************}
+
+ constructor tprocvardef.create(level:byte);
+ begin
+ inherited create(procvardef,level);
+ end;
+
+
+ constructor tprocvardef.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(procvardef,ppufile);
+ { load para symtable }
+ parast:=tparasymtable.create(self,ppufile.getbyte);
+ tparasymtable(parast).ppuload(ppufile);
+ end;
+
+
+ function tprocvardef.getcopy : tstoreddef;
+ var
+ i : tcallercallee;
+ j : longint;
+ begin
+ result:=tprocvardef.create(parast.symtablelevel);
+ tprocvardef(result).returndef:=returndef;
+ tprocvardef(result).returndefderef:=returndefderef;
+ tprocvardef(result).parast:=parast.getcopy;
+ tprocvardef(result).savesize:=savesize;
+
+ { create paralist copy }
+ tprocvardef(result).paras:=tparalist.create(false);
+ tprocvardef(result).paras.count:=paras.count;
+ for j:=0 to paras.count-1 do
+ tprocvardef(result).paras[j]:=paras[j];
+
+ tprocvardef(result).proctypeoption:=proctypeoption;
+ tprocvardef(result).proccalloption:=proccalloption;
+ tprocvardef(result).procoptions:=procoptions;
+ tprocvardef(result).callerargareasize:=callerargareasize;
+ tprocvardef(result).calleeargareasize:=calleeargareasize;
+ tprocvardef(result).maxparacount:=maxparacount;
+ tprocvardef(result).minparacount:=minparacount;
+ for i:=low(tcallercallee) to high(tcallercallee) do
+ tprocvardef(result).funcretloc[i]:=funcretloc[i].getcopy;
+ tprocvardef(result).has_paraloc_info:=has_paraloc_info;
+{$ifdef m68k}
+ tprocvardef(result).exp_funcretloc:=exp_funcretloc;
+{$endif}
+ end;
+
+
+ procedure tprocvardef.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+
+ { Save the para symtable level (necessary to distinguish nested
+ procvars) }
+ ppufile.putbyte(parast.symtablelevel);
+
+ { Write this entry }
+ ppufile.writeentry(ibprocvardef);
+
+ { Save the para symtable, this is taken from the interface }
+ tparasymtable(parast).ppuwrite(ppufile);
+ end;
+
+
+ function tprocvardef.GetSymtable(t:tGetSymtable):TSymtable;
+ begin
+ case t of
+ gs_para :
+ GetSymtable:=parast;
+ else
+ GetSymtable:=nil;
+ end;
+ end;
+
+
+ function tprocvardef.size : asizeint;
+ begin
+ if ((po_methodpointer in procoptions) or
+ is_nested_pd(self)) and
+ not(po_addressonly in procoptions) then
+ size:=2*sizeof(pint)
+ else
+ size:=sizeof(pint);
+ end;
+
+
+ function tprocvardef.is_methodpointer:boolean;
+ begin
+ result:=(po_methodpointer in procoptions);
+ end;
+
+
+ function tprocvardef.is_addressonly:boolean;
+ begin
+ result:=(not(po_methodpointer in procoptions) and
+ not is_nested_pd(self)) or
+ (po_addressonly in procoptions);
+ end;
+
+
+ function tprocvardef.getmangledparaname:string;
+ begin
+ if not(po_methodpointer in procoptions) then
+ if not is_nested_pd(self) then
+ result:='procvar'
+ else
+ result:='nestedprovar'
+ else
+ result:='procvarofobj'
+ end;
+
+
+ function tprocvardef.is_publishable : boolean;
+ begin
+ is_publishable:=(po_methodpointer in procoptions);
+ end;
+
+
+ function tprocvardef.GetTypeName : string;
+ var
+ s: string;
+ showhidden : boolean;
+ begin
+{$ifdef EXTDEBUG}
+ showhidden:=true;
+{$else EXTDEBUG}
+ showhidden:=false;
+{$endif EXTDEBUG}
+ s:='<';
+ if po_classmethod in procoptions then
+ s := s+'class method type of'
+ else
+ if po_addressonly in procoptions then
+ s := s+'address of'
+ else
+ s := s+'procedure variable type of';
+ if assigned(returndef) and
+ (returndef<>voidtype) then
+ s:=s+' function'+typename_paras(showhidden)+':'+returndef.GetTypeName
+ else
+ s:=s+' procedure'+typename_paras(showhidden);
+ if po_methodpointer in procoptions then
+ s := s+' of object';
+ if is_nested_pd(self) then
+ s := s+' is nested';
+ GetTypeName := s+';'+ProcCallOptionStr[proccalloption]+'>';
+ end;
+
+
+{***************************************************************************
+ TOBJECTDEF
+***************************************************************************}
+
+ constructor tobjectdef.create(ot:tobjecttyp;const n:string;c:tobjectdef);
+ begin
+ inherited create(n,objectdef);
+ fcurrent_dispid:=0;
+ objecttype:=ot;
+ childof:=nil;
+ if objecttype=odt_helper then
+ owner.includeoption(sto_has_helper);
+ symtable:=tObjectSymtable.create(self,n,current_settings.packrecords);
+ { create space for vmt !! }
+ vmtentries:=TFPList.Create;
+ vmt_offset:=0;
+ set_parent(c);
+ if objecttype in [odt_interfacecorba,odt_interfacecom,odt_dispinterface] then
+ prepareguid;
+ { setup implemented interfaces }
+ if objecttype in [odt_class,odt_objcclass,odt_objcprotocol] then
+ ImplementedInterfaces:=TFPObjectList.Create(true)
+ else
+ ImplementedInterfaces:=nil;
+ writing_class_record_dbginfo:=false;
+ end;
+
+
+ constructor tobjectdef.ppuload(ppufile:tcompilerppufile);
+ var
+ i,
+ implintfcount : longint;
+ d : tderef;
+ ImplIntf : TImplementedInterface;
+ vmtentry : pvmtentry;
+ begin
+ inherited ppuload(objectdef,ppufile);
+ objecttype:=tobjecttyp(ppufile.getbyte);
+ objextname:=stringdup(ppufile.getstring);
+ { only used for external Objective-C classes/protocols }
+ if (objextname^='') then
+ stringdispose(objextname);
+ import_lib:=stringdup(ppufile.getstring);
+ { only used for external C++ classes }
+ if (import_lib^='') then
+ stringdispose(import_lib);
+ symtable:=tObjectSymtable.create(self,objrealname^,0);
+ tObjectSymtable(symtable).datasize:=ppufile.getasizeint;
+ tObjectSymtable(symtable).paddingsize:=ppufile.getword;
+ tObjectSymtable(symtable).fieldalignment:=shortint(ppufile.getbyte);
+ tObjectSymtable(symtable).recordalignment:=shortint(ppufile.getbyte);
+ vmt_offset:=ppufile.getlongint;
+ ppufile.getderef(childofderef);
+
+ { load guid }
+ iidstr:=nil;
+ if objecttype in [odt_interfacecom,odt_interfacecorba,odt_dispinterface] then
+ begin
+ new(iidguid);
+ ppufile.getguid(iidguid^);
+ iidstr:=stringdup(ppufile.getstring);
+ end;
+
+ if objecttype=odt_helper then
+ ppufile.getderef(extendeddefderef);
+
+ vmtentries:=TFPList.Create;
+ vmtentries.count:=ppufile.getlongint;
+ for i:=0 to vmtentries.count-1 do
+ begin
+ ppufile.getderef(d);
+ new(vmtentry);
+ vmtentry^.procdef:=nil;
+ vmtentry^.procdefderef:=d;
+ vmtentry^.visibility:=tvisibility(ppufile.getbyte);
+ vmtentries[i]:=vmtentry;
+ end;
+
+ { load implemented interfaces }
+ if objecttype in [odt_class,odt_objcclass,odt_objcprotocol] then
+ begin
+ ImplementedInterfaces:=TFPObjectList.Create(true);
+ implintfcount:=ppufile.getlongint;
+ for i:=0 to implintfcount-1 do
+ begin
+ ppufile.getderef(d);
+ ImplIntf:=TImplementedInterface.Create_deref(d);
+ ImplIntf.IOffset:=ppufile.getlongint;
+ ImplementedInterfaces.Add(ImplIntf);
+ end;
+ end
+ else
+ ImplementedInterfaces:=nil;
+
+ if df_copied_def in defoptions then
+ ppufile.getderef(cloneddefderef)
+ else
+ tObjectSymtable(symtable).ppuload(ppufile);
+
+ { handles the predefined class tobject }
+ { the last TOBJECT which is loaded gets }
+ { it ! }
+ if (childof=nil) and
+ (objecttype=odt_class) and
+ (objname^='TOBJECT') then
+ class_tobject:=self;
+ if (childof=nil) and
+ (objecttype=odt_interfacecom) then
+ if (objname^='IUNKNOWN') then
+ interface_iunknown:=self
+ else
+ if (objname^='IDISPATCH') then
+ interface_idispatch:=self;
+ if (childof=nil) and
+ (objecttype=odt_objcclass) and
+ (objname^='PROTOCOL') then
+ objc_protocoltype:=self;
+ writing_class_record_dbginfo:=false;
+ end;
+
+
+ destructor tobjectdef.destroy;
+ begin
+ if assigned(symtable) then
+ begin
+ symtable.free;
+ symtable:=nil;
+ end;
+ stringdispose(objextname);
+ stringdispose(import_lib);
+ stringdispose(iidstr);
+ if assigned(ImplementedInterfaces) then
+ begin
+ ImplementedInterfaces.free;
+ ImplementedInterfaces:=nil;
+ end;
+ if assigned(iidguid) then
+ begin
+ dispose(iidguid);
+ iidguid:=nil;
+ end;
+ if assigned(vmtentries) then
+ begin
+ resetvmtentries;
+ vmtentries.free;
+ vmtentries:=nil;
+ end;
+ if assigned(vmcallstaticinfo) then
+ begin
+ freemem(vmcallstaticinfo);
+ vmcallstaticinfo:=nil;
+ end;
+ inherited destroy;
+ end;
+
+
+ function tobjectdef.getcopy : tstoreddef;
+ var
+ i : longint;
+ begin
+ result:=tobjectdef.create(objecttype,objrealname^,childof);
+ { the constructor allocates a symtable which we release to avoid memory leaks }
+ tobjectdef(result).symtable.free;
+ tobjectdef(result).symtable:=symtable.getcopy;
+ if assigned(objextname) then
+ tobjectdef(result).objextname:=stringdup(objextname^);
+ if assigned(import_lib) then
+ tobjectdef(result).import_lib:=stringdup(import_lib^);
+ tobjectdef(result).objectoptions:=objectoptions;
+ include(tobjectdef(result).defoptions,df_copied_def);
+ tobjectdef(result).extendeddef:=extendeddef;
+ tobjectdef(result).vmt_offset:=vmt_offset;
+ if assigned(iidguid) then
+ begin
+ new(tobjectdef(result).iidguid);
+ move(iidguid^,tobjectdef(result).iidguid^,sizeof(iidguid^));
+ end;
+ if assigned(iidstr) then
+ tobjectdef(result).iidstr:=stringdup(iidstr^);
+ if assigned(ImplementedInterfaces) then
+ begin
+ for i:=0 to ImplementedInterfaces.count-1 do
+ tobjectdef(result).ImplementedInterfaces.Add(TImplementedInterface(ImplementedInterfaces[i]).Getcopy);
+ end;
+ if assigned(vmtentries) then
+ begin
+ tobjectdef(result).vmtentries:=TFPList.Create;
+ tobjectdef(result).copyvmtentries(self);
+ end;
+ end;
+
+
+ procedure tobjectdef.ppuwrite(ppufile:tcompilerppufile);
+ var
+ i : longint;
+ vmtentry : pvmtentry;
+ ImplIntf : TImplementedInterface;
+ old_do_indirect_crc: boolean;
+ begin
+ { if class1 in unit A changes, and class2 in unit B inherits from it
+ (so unit B uses unit A), then unit B with class2 will be recompiled.
+ However, if there is also a class3 in unit C that only depends on
+ unit B, then unit C will not be recompiled because nothing changed
+ to the interface of unit B. Nevertheless, unit C can indirectly
+ depend on unit A via derefs, and these must be updated -> the
+ indirect crc keeps track of such changes. }
+ old_do_indirect_crc:=ppufile.do_indirect_crc;
+ ppufile.do_indirect_crc:=true;
+ inherited ppuwrite(ppufile);
+ ppufile.putbyte(byte(objecttype));
+ if assigned(objextname) then
+ ppufile.putstring(objextname^)
+ else
+ ppufile.putstring('');
+ if assigned(import_lib) then
+ ppufile.putstring(import_lib^)
+ else
+ ppufile.putstring('');
+ ppufile.putasizeint(tObjectSymtable(symtable).datasize);
+ ppufile.putword(tObjectSymtable(symtable).paddingsize);
+ ppufile.putbyte(byte(tObjectSymtable(symtable).fieldalignment));
+ ppufile.putbyte(byte(tObjectSymtable(symtable).recordalignment));
+ ppufile.putlongint(vmt_offset);
+ ppufile.putderef(childofderef);
+ if objecttype in [odt_interfacecom,odt_interfacecorba,odt_dispinterface] then
+ begin
+ ppufile.putguid(iidguid^);
+ ppufile.putstring(iidstr^);
+ end;
+ if objecttype=odt_helper then
+ ppufile.putderef(extendeddefderef);
+
+ ppufile.putlongint(vmtentries.count);
+ for i:=0 to vmtentries.count-1 do
+ begin
+ vmtentry:=pvmtentry(vmtentries[i]);
+ ppufile.putderef(vmtentry^.procdefderef);
+ ppufile.putbyte(byte(vmtentry^.visibility));
+ end;
+
+
+ if assigned(ImplementedInterfaces) then
+ begin
+ ppufile.putlongint(ImplementedInterfaces.Count);
+ for i:=0 to ImplementedInterfaces.Count-1 do
+ begin
+ ImplIntf:=TImplementedInterface(ImplementedInterfaces[i]);
+ ppufile.putderef(ImplIntf.intfdefderef);
+ ppufile.putlongint(ImplIntf.Ioffset);
+ end;
+ end;
+
+ if df_copied_def in defoptions then
+ ppufile.putderef(cloneddefderef);
+
+ ppufile.writeentry(ibobjectdef);
+
+ if not(df_copied_def in defoptions) then
+ tObjectSymtable(symtable).ppuwrite(ppufile);
+
+ ppufile.do_indirect_crc:=old_do_indirect_crc;
+ end;
+
+
+ function tobjectdef.GetTypeName:string;
+ begin
+ { in this case we will go in endless recursion, because then }
+ { there is no tsym associated yet with the def. It can occur }
+ { (tests/webtbf/tw4757.pp), so for now give a generic name }
+ { instead of the actual type name }
+ if not assigned(typesym) then
+ result:='<Currently Parsed Class>'
+ else
+ result:=typesymbolprettyname;
+ end;
+
+
+ procedure tobjectdef.buildderef;
+ var
+ i : longint;
+ vmtentry : pvmtentry;
+ begin
+ inherited buildderef;
+ childofderef.build(childof);
+ if df_copied_def in defoptions then
+ cloneddefderef.build(symtable.defowner)
+ else
+ tstoredsymtable(symtable).buildderef;
+
+ if objecttype=odt_helper then
+ extendeddefderef.build(extendeddef);
+
+ for i:=0 to vmtentries.count-1 do
+ begin
+ vmtentry:=pvmtentry(vmtentries[i]);
+ vmtentry^.procdefderef.build(vmtentry^.procdef);
+ end;
+
+ if assigned(ImplementedInterfaces) then
+ begin
+ for i:=0 to ImplementedInterfaces.count-1 do
+ TImplementedInterface(ImplementedInterfaces[i]).buildderef;
+ end;
+ end;
+
+
+ procedure tobjectdef.deref;
+ var
+ i : longint;
+ vmtentry : pvmtentry;
+ begin
+ inherited deref;
+ childof:=tobjectdef(childofderef.resolve);
+ if df_copied_def in defoptions then
+ begin
+ cloneddef:=tobjectdef(cloneddefderef.resolve);
+ symtable:=cloneddef.symtable.getcopy;
+ end
+ else
+ tstoredsymtable(symtable).deref;
+ if objecttype=odt_helper then
+ extendeddef:=tdef(extendeddefderef.resolve);
+ for i:=0 to vmtentries.count-1 do
+ begin
+ vmtentry:=pvmtentry(vmtentries[i]);
+ vmtentry^.procdef:=tprocdef(vmtentry^.procdefderef.resolve);
+ end;
+ if assigned(ImplementedInterfaces) then
+ begin
+ for i:=0 to ImplementedInterfaces.count-1 do
+ TImplementedInterface(ImplementedInterfaces[i]).deref;
+ end;
+ end;
+
+
+ procedure create_class_helper_for_procdef(def: tobject; arg: pointer);
+ var
+ pd: tprocdef absolute def;
+ st: tsymtable;
+ psym: tsym;
+ nname: TIDString;
+ begin
+ if (tdef(def).typ<>procdef) then
+ exit;
+ { pd.owner = objcclass symtable -> defowner = objcclassdef ->
+ owner = symtable in which objcclassdef is defined
+ }
+ st:=pd.owner.defowner.owner;
+ nname:=class_helper_prefix+tprocsym(pd.procsym).name;
+ { check for an existing procsym with our special name }
+ psym:=tsym(st.find(nname));
+ if not assigned(psym) then
+ begin
+ psym:=tprocsym.create(nname);
+ { avoid warning about this symbol being unused }
+ psym.IncRefCount;
+ { don't check for duplicates:
+ a) we checked above
+ b) in case we are in the implementation section of a unit, this
+ will also check for this symbol in the interface section
+ (since you normally cannot have symbols with the same name
+ both interface and implementation), and it's possible to
+ have class helpers for the same class in the interface and
+ in the implementation, and they cannot be merged since only
+ the once in the interface must be saved to the ppu/visible
+ from other units }
+ st.insert(psym,false);
+ end
+ else if (psym.typ<>procsym) then
+ internalerror(2009111501);
+ { add ourselves to this special procsym }
+ tprocsym(psym).procdeflist.add(def);
+ end;
+
+
+ procedure tobjectdef.buildderefimpl;
+ begin
+ inherited buildderefimpl;
+ if not (df_copied_def in defoptions) then
+ tstoredsymtable(symtable).buildderefimpl;
+ end;
+
+
+ procedure tobjectdef.derefimpl;
+ begin
+ inherited derefimpl;
+ if not (df_copied_def in defoptions) then
+ tstoredsymtable(symtable).derefimpl;
+ { the procdefs are not owned by the class helper procsyms, so they
+ are not stored/restored either -> re-add them here }
+ if (objecttype=odt_objcclass) or
+ (oo_is_classhelper in objectoptions) then
+ symtable.DefList.ForEachCall(@create_class_helper_for_procdef,nil);
+ end;
+
+
+ procedure tobjectdef.resetvmtentries;
+ var
+ i : longint;
+ begin
+ for i:=0 to vmtentries.Count-1 do
+ Dispose(pvmtentry(vmtentries[i]));
+ vmtentries.clear;
+ end;
+
+
+ procedure tobjectdef.copyvmtentries(objdef:tobjectdef);
+ var
+ i : longint;
+ vmtentry : pvmtentry;
+ begin
+ resetvmtentries;
+ vmtentries.count:=objdef.vmtentries.count;
+ for i:=0 to objdef.vmtentries.count-1 do
+ begin
+ new(vmtentry);
+ vmtentry^:=pvmtentry(objdef.vmtentries[i])^;
+ vmtentries[i]:=vmtentry;
+ end;
+ end;
+
+
+ function tobjectdef.getparentdef:tdef;
+ begin
+{ TODO: Remove getparentdef hack}
+ { With 2 forward declared classes with the child class before the
+ parent class the child class is written earlier to the ppu. Leaving it
+ possible to have a reference to the parent class for property overriding,
+ but the parent class still has the childof not resolved yet (PFV) }
+ if childof=nil then
+ childof:=tobjectdef(childofderef.resolve);
+ result:=childof;
+ end;
+
+
+ procedure tobjectdef.prepareguid;
+ begin
+ { set up guid }
+ if not assigned(iidguid) then
+ begin
+ new(iidguid);
+ fillchar(iidguid^,sizeof(iidguid^),0); { default null guid }
+ end;
+ { setup iidstring }
+ if not assigned(iidstr) then
+ iidstr:=stringdup(''); { default is empty string }
+ end;
+
+
+ procedure tobjectdef.set_parent( c : tobjectdef);
+ begin
+ if assigned(childof) then
+ exit;
+ childof:=c;
+ if not assigned(c) then
+ exit;
+ { inherit options and status }
+ objectoptions:=objectoptions+(c.objectoptions*inherited_objectoptions);
+ { add the data of the anchestor class/object }
+ if (objecttype in [odt_class,odt_object,odt_objcclass]) then
+ begin
+ tObjectSymtable(symtable).datasize:=tObjectSymtable(symtable).datasize+tObjectSymtable(c.symtable).datasize;
+ { inherit recordalignment }
+ tObjectSymtable(symtable).recordalignment:=tObjectSymtable(c.symtable).recordalignment;
+ { if both the parent and this record use C-alignment, also inherit
+ the current field alignment }
+ if (tObjectSymtable(c.symtable).usefieldalignment=C_alignment) and
+ (tObjectSymtable(symtable).usefieldalignment=C_alignment) then
+ tObjectSymtable(symtable).fieldalignment:=tObjectSymtable(c.symtable).fieldalignment;
+ { the padding is not inherited for Objective-C classes (maybe not
+ for cppclass either?) }
+ if objecttype=odt_objcclass then
+ tObjectSymtable(symtable).datasize:=tObjectSymtable(symtable).datasize-tObjectSymtable(c.symtable).paddingsize;
+ if (oo_has_vmt in objectoptions) and
+ (oo_has_vmt in c.objectoptions) then
+ tObjectSymtable(symtable).datasize:=tObjectSymtable(symtable).datasize-sizeof(pint);
+ { if parent has a vmt field then the offset is the same for the child PM }
+ if (oo_has_vmt in c.objectoptions) or is_class(self) then
+ begin
+ vmt_offset:=c.vmt_offset;
+ include(objectoptions,oo_has_vmt);
+ end;
+ end;
+ end;
+
+
+ procedure tobjectdef.insertvmt;
+ var
+ vs: tfieldvarsym;
+ begin
+ if objecttype in [odt_interfacecom,odt_interfacecorba,odt_dispinterface,odt_objcclass,odt_objcprotocol] then
+ exit;
+ if (oo_has_vmt in objectoptions) then
+ internalerror(12345)
+ else
+ begin
+ tObjectSymtable(symtable).datasize:=align(tObjectSymtable(symtable).datasize,
+ tObjectSymtable(symtable).fieldalignment);
+
+ if (tf_requires_proper_alignment in target_info.flags) then
+ begin
+ { Align VMT pointer and whole object instance if target CPU requires alignment. }
+ tObjectSymtable(symtable).datasize:=align(tObjectSymtable(symtable).datasize,sizeof(pint));
+ tObjectSymtable(symtable).alignrecord(tObjectSymtable(symtable).datasize,sizeof(pint));
+ end;
+ vs:=tfieldvarsym.create('_vptr$'+objname^,vs_value,voidpointertype,[]);
+ hidesym(vs);
+ tObjectSymtable(symtable).insert(vs);
+ tObjectSymtable(symtable).addfield(vs,vis_hidden);
+ if (tObjectSymtable(symtable).usefieldalignment<>bit_alignment) then
+ vmt_offset:=vs.fieldoffset
+ else
+ vmt_offset:=vs.fieldoffset div 8;
+ include(objectoptions,oo_has_vmt);
+ end;
+ end;
+
+
+
+ procedure tobjectdef.check_forwards;
+ begin
+ if not(objecttype in [odt_interfacecom,odt_interfacecorba,odt_dispinterface,odt_objcprotocol]) then
+ inherited;
+ if (oo_is_forward in objectoptions) then
+ begin
+ { ok, in future, the forward can be resolved }
+ Message1(sym_e_class_forward_not_resolved,objrealname^);
+ exclude(objectoptions,oo_is_forward);
+ end;
+ end;
+
+
+ { true if prot implements d (or if they are equal) }
+ function is_related_protocol(prot: tobjectdef; d : tdef) : boolean;
+ var
+ i : longint;
+ begin
+ { objcprotocols have multiple inheritance, all protocols from which
+ the current protocol inherits are stored in implementedinterfaces }
+ result:=prot=d;
+ if result then
+ exit;
+
+ for i:=0 to prot.ImplementedInterfaces.count-1 do
+ begin
+ result:=is_related_protocol(TImplementedInterface(prot.ImplementedInterfaces[i]).intfdef,d);
+ if result then
+ exit;
+ end;
+ end;
+
+
+ { true, if self inherits from d (or if they are equal) }
+ function tobjectdef.is_related(d : tdef) : boolean;
+ var
+ hp : tobjectdef;
+ begin
+ if self=d then
+ begin
+ is_related:=true;
+ exit;
+ end;
+
+ if (d.typ<>objectdef) then
+ begin
+ is_related:=false;
+ exit;
+ end;
+
+ { Objective-C protocols can use multiple inheritance }
+ if (objecttype=odt_objcprotocol) then
+ begin
+ is_related:=is_related_protocol(self,d);
+ exit
+ end;
+
+ { formally declared Objective-C classes match Objective-C classes with
+ the same name }
+ if (objecttype=odt_objcclass) and
+ (tobjectdef(d).objecttype=odt_objcclass) and
+ ((oo_is_formal in objectoptions) or
+ (oo_is_formal in tobjectdef(d).objectoptions)) and
+ (objrealname^=tobjectdef(d).objrealname^) then
+ begin
+ is_related:=true;
+ exit;
+ end;
+
+ hp:=childof;
+ while assigned(hp) do
+ begin
+ if hp=d then
+ begin
+ is_related:=true;
+ exit;
+ end;
+ hp:=hp.childof;
+ end;
+ is_related:=false;
+ end;
+
+ function tobjectdef.find_destructor: tprocdef;
+ var
+ objdef: tobjectdef;
+ begin
+ objdef:=self;
+ while assigned(objdef) do
+ begin
+ result:=objdef.find_procdef_bytype(potype_destructor);
+ if assigned(result) then
+ exit;
+ objdef:=objdef.childof;
+ end;
+ result:=nil;
+ end;
+
+ function tobjectdef.implements_any_interfaces: boolean;
+ begin
+ result := (ImplementedInterfaces.Count > 0) or
+ (assigned(childof) and childof.implements_any_interfaces);
+ end;
+
+ function tobjectdef.size : asizeint;
+ begin
+ if objecttype in [odt_class,odt_interfacecom,odt_interfacecorba,odt_dispinterface,odt_objcclass,odt_objcprotocol,odt_helper] then
+ result:=sizeof(pint)
+ else
+ result:=tObjectSymtable(symtable).datasize;
+ end;
+
+
+ function tobjectdef.alignment:shortint;
+ begin
+ if objecttype in [odt_class,odt_interfacecom,odt_interfacecorba,odt_dispinterface,odt_objcclass,odt_objcprotocol,odt_helper] then
+ alignment:=sizeof(pint)
+ else
+ alignment:=tObjectSymtable(symtable).recordalignment;
+ end;
+
+
+ function tobjectdef.vmtmethodoffset(index:longint):longint;
+ begin
+ { for offset of methods for classes, see rtl/inc/objpash.inc }
+ case objecttype of
+ odt_class:
+ { the +2*sizeof(pint) is size and -size }
+ vmtmethodoffset:=(index+10)*sizeof(pint)+2*sizeof(pint);
+ odt_helper,
+ odt_objcclass,
+ odt_objcprotocol:
+ vmtmethodoffset:=0;
+ odt_interfacecom,odt_interfacecorba,odt_dispinterface:
+ vmtmethodoffset:=index*sizeof(pint);
+ else
+{$ifdef WITHDMT}
+ vmtmethodoffset:=(index+4)*sizeof(pint);
+{$else WITHDMT}
+ vmtmethodoffset:=(index+3)*sizeof(pint);
+{$endif WITHDMT}
+ end;
+ end;
+
+
+ function tobjectdef.vmt_mangledname : string;
+ begin
+ if not(oo_has_vmt in objectoptions) then
+ Message1(parser_n_object_has_no_vmt,objrealname^);
+ vmt_mangledname:=make_mangledname('VMT',owner,objname^);
+ end;
+
+
+ function tobjectdef.needs_inittable : boolean;
+ begin
+ case objecttype of
+ odt_helper,
+ odt_class :
+ needs_inittable:=false;
+ odt_dispinterface,
+ odt_interfacecom:
+ needs_inittable:=true;
+ odt_interfacecorba:
+ needs_inittable:=is_related(interface_iunknown);
+ odt_object:
+ needs_inittable:=tObjectSymtable(symtable).needs_init_final;
+ odt_cppclass,
+ odt_objcclass,
+ odt_objcprotocol:
+ needs_inittable:=false;
+ else
+ internalerror(200108267);
+ end;
+ end;
+
+
+ function tobjectdef.rtti_mangledname(rt: trttitype): string;
+ begin
+ if not(objecttype in [odt_objcclass,odt_objcprotocol]) then
+ result:=inherited rtti_mangledname(rt)
+ else
+ begin
+ { necessary in case of a dynamic array of nsobject, or
+ if an nsobject field appears in a record that needs
+ init/finalisation }
+ if rt=initrtti then
+ begin
+ result:=voidpointertype.rtti_mangledname(rt);
+ exit;
+ end;
+
+ if not(target_info.system in systems_objc_nfabi) then
+ begin
+ result:=target_asm.labelprefix;
+ case objecttype of
+ odt_objcclass:
+ begin
+ case rt of
+ objcclassrtti:
+ if not(oo_is_classhelper in objectoptions) then
+ result:=result+'_OBJC_CLASS_'
+ else
+ result:=result+'_OBJC_CATEGORY_';
+ objcmetartti:
+ if not(oo_is_classhelper in objectoptions) then
+ result:=result+'_OBJC_METACLASS_'
+ else
+ internalerror(2009111511);
+ else
+ internalerror(2009092302);
+ end;
+ end;
+ odt_objcprotocol:
+ result:=result+'_OBJC_PROTOCOL_';
+ end;
+ end
+ else
+ begin
+ case objecttype of
+ odt_objcclass:
+ begin
+ if (oo_is_classhelper in objectoptions) and
+ (rt<>objcclassrtti) then
+ internalerror(2009111512);
+ case rt of
+ objcclassrtti:
+ if not(oo_is_classhelper in objectoptions) then
+ result:='_OBJC_CLASS_$_'
+ else
+ result:='_OBJC_$_CATEGORY_';
+ objcmetartti:
+ result:='_OBJC_METACLASS_$_';
+ objcclassrortti:
+ result:=lower(target_asm.labelprefix)+'_OBJC_CLASS_RO_$_';
+ objcmetarortti:
+ result:=lower(target_asm.labelprefix)+'_OBJC_METACLASS_RO_$_';
+ else
+ internalerror(2009092303);
+ end;
+ end;
+ odt_objcprotocol:
+ begin
+ result:=lower(target_asm.labelprefix);
+ case rt of
+ objcclassrtti:
+ result:=result+'_OBJC_PROTOCOL_$_';
+ objcmetartti:
+ result:=result+'_OBJC_LABEL_PROTOCOL_$_';
+ else
+ internalerror(2009092501);
+ end;
+ end;
+ end;
+ end;
+ result:=result+objextname^;
+ end;
+ end;
+
+
+ function tobjectdef.members_need_inittable : boolean;
+ begin
+ members_need_inittable:=tObjectSymtable(symtable).needs_init_final;
+ end;
+
+
+ function tobjectdef.find_implemented_interface(aintfdef:tobjectdef):TImplementedInterface;
+ var
+ ImplIntf : TImplementedInterface;
+ i : longint;
+ begin
+ result:=nil;
+ if not assigned(ImplementedInterfaces) then
+ exit;
+ for i:=0 to ImplementedInterfaces.Count-1 do
+ begin
+ ImplIntf:=TImplementedInterface(ImplementedInterfaces[i]);
+ if ImplIntf.intfdef=aintfdef then
+ begin
+ result:=ImplIntf;
+ exit;
+ end;
+ end;
+ end;
+
+
+ function tobjectdef.is_publishable : boolean;
+ begin
+ is_publishable:=objecttype in [odt_class,odt_interfacecom,odt_interfacecorba,odt_dispinterface];
+ end;
+
+
+ function tobjectdef.get_next_dispid: longint;
+ begin
+ inc(fcurrent_dispid);
+ result:=fcurrent_dispid;
+ end;
+
+ function tobjectdef.search_enumerator_get: tprocdef;
+ begin
+ result:=inherited;
+ if not assigned(result) and assigned(childof) then
+ result:=childof.search_enumerator_get;
+ end;
+
+ function tobjectdef.search_enumerator_move: tprocdef;
+ begin
+ result:=inherited;
+ if not assigned(result) and assigned(childof) then
+ result:=childof.search_enumerator_move;
+ end;
+
+ function tobjectdef.search_enumerator_current: tsym;
+ begin
+ result:=inherited;
+ if not assigned(result) and assigned(childof) then
+ result:=childof.search_enumerator_current;
+ end;
+
+ procedure tobjectdef.register_created_classref_type;
+ begin
+ if not classref_created_in_current_module then
+ begin
+ classref_created_in_current_module:=true;
+ current_module.wpoinfo.addcreatedobjtypeforclassref(self);
+ end;
+ end;
+
+
+ procedure tobjectdef.register_created_object_type;
+ begin
+ if not created_in_current_module then
+ begin
+ created_in_current_module:=true;
+ current_module.wpoinfo.addcreatedobjtype(self);
+ end;
+ end;
+
+
+ procedure tobjectdef.register_maybe_created_object_type;
+ begin
+ { if we know it has been created for sure, no need
+ to also record that it maybe can be created in
+ this module
+ }
+ if not (created_in_current_module) and
+ not (maybe_created_in_current_module) then
+ begin
+ maybe_created_in_current_module:=true;
+ current_module.wpoinfo.addmaybecreatedbyclassref(self);
+ end;
+ end;
+
+
+ procedure tobjectdef.register_vmt_call(index: longint);
+ begin
+ if (is_object(self) or is_class(self)) then
+ current_module.wpoinfo.addcalledvmtentry(self,index);
+ end;
+
+
+ procedure check_and_finish_msg(data: tobject; arg: pointer);
+ var
+ def: tdef absolute data;
+ pd: tprocdef absolute data;
+ i,
+ paracount: longint;
+ begin
+ if (def.typ=procdef) then
+ begin
+ { add all messages also under a dummy name to the symtable in
+ which the objcclass/protocol/category is declared, so they can
+ be called via id.<name>
+ }
+ create_class_helper_for_procdef(pd,nil);
+
+ { we have to wait until now to set the mangled name because it
+ depends on the (possibly external) class name, which is defined
+ at the very end. }
+ if not(po_msgstr in pd.procoptions) then
+ begin
+ CGMessagePos(pd.fileinfo,parser_e_objc_requires_msgstr);
+ { recover to avoid internalerror later on }
+ include(pd.procoptions,po_msgstr);
+ pd.messageinf.str:=stringdup('MissingDeclaration');
+ end;
+ { Mangled name is already set in case this is a copy of
+ another type. }
+ if not(po_has_mangledname in pd.procoptions) then
+ begin
+ { check whether the number of formal parameters is correct,
+ and whether they have valid Objective-C types }
+ paracount:=0;
+ for i:=1 to length(pd.messageinf.str^) do
+ if pd.messageinf.str^[i]=':' then
+ inc(paracount);
+ for i:=0 to pd.paras.count-1 do
+ if not(vo_is_hidden_para in tparavarsym(pd.paras[i]).varoptions) and
+ not is_array_of_const(tparavarsym(pd.paras[i]).vardef) then
+ dec(paracount);
+ if (paracount<>0) then
+ MessagePos(pd.fileinfo,sym_e_objc_para_mismatch);
+
+ pd.setmangledname(pd.objcmangledname);
+ end
+ else
+ { all checks already done }
+ exit;
+ if not(oo_is_external in pd.struct.objectoptions) then
+ begin
+ if (po_varargs in pd.procoptions) then
+ MessagePos(pd.fileinfo,parser_e_varargs_need_cdecl_and_external)
+ else
+ begin
+ { check for "array of const" parameters }
+ for i:=0 to pd.parast.symlist.count-1 do
+ begin
+ if (tsym(pd.parast.symlist[i]).typ=paravarsym) and
+ is_array_of_const(tparavarsym(pd.parast.symlist[i]).vardef) then
+ MessagePos(pd.fileinfo,parser_e_varargs_need_cdecl_and_external);
+ end;
+ end;
+ end;
+ end;
+ end;
+
+
+ procedure mark_private_fields_used(data: tobject; arg: pointer);
+ var
+ sym: tsym absolute data;
+ begin
+ if (sym.typ=fieldvarsym) and
+ (tfieldvarsym(sym).visibility in [vis_private,vis_strictprivate]) then
+ sym.IncRefCount;
+ end;
+
+
+ procedure tobjectdef.finish_objc_data;
+ begin
+ self.symtable.DefList.foreachcall(@check_and_finish_msg,nil);
+ if (oo_is_external in objectoptions) then
+ self.symtable.SymList.ForEachCall(@mark_private_fields_used,nil);
+ end;
+
+
+ procedure verify_objc_vardef(data: tobject; arg: pointer);
+ var
+ sym: tabstractvarsym absolute data;
+ res: pboolean absolute arg;
+ founderrordef: tdef;
+ begin
+ if not(tsym(data).typ in [paravarsym,fieldvarsym]) then
+ exit;
+ if (sym.typ=paravarsym) and
+ ((vo_is_hidden_para in tparavarsym(sym).varoptions) or
+ is_array_of_const(tparavarsym(sym).vardef)) then
+ exit;
+ if not objcchecktype(sym.vardef,founderrordef) then
+ begin
+ MessagePos1(sym.fileinfo,type_e_objc_type_unsupported,founderrordef.typename);
+ res^:=false;
+ end;
+ end;
+
+
+ procedure verify_objc_procdef_paras(data: tobject; arg: pointer);
+ var
+ def: tdef absolute data;
+ res: pboolean absolute arg;
+ founderrordef: tdef;
+ begin
+ if (def.typ<>procdef) then
+ exit;
+ { check parameter types for validity }
+ tprocdef(def).paras.foreachcall(@verify_objc_vardef,arg);
+ { check the result type for validity }
+ if not objcchecktype(tprocdef(def).returndef,founderrordef) then
+ begin
+ MessagePos1(tprocdef(def).funcretsym.fileinfo,type_e_objc_type_unsupported,founderrordef.typename);
+ res^:=false;
+ end;
+ end;
+
+
+ function tobjectdef.check_objc_types: boolean;
+ begin
+ { done in separate step from finish_objc_data, because when
+ finish_objc_data is called, not all forwarddefs have been resolved
+ yet and we need to know all types here }
+ result:=true;
+ self.symtable.symlist.foreachcall(@verify_objc_vardef,@result);
+ self.symtable.deflist.foreachcall(@verify_objc_procdef_paras,@result);
+ end;
+
+
+ procedure do_cpp_import_info(data: tobject; arg: pointer);
+ var
+ def: tdef absolute data;
+ pd: tprocdef absolute data;
+ begin
+ if (def.typ=procdef) then
+ begin
+ pd.setmangledname(target_info.Cprefix+pd.cplusplusmangledname);
+ if (oo_is_external in pd.struct.objectoptions) then
+ begin
+ { copied from psub.read_proc }
+ if assigned(tobjectdef(pd.struct).import_lib) then
+ current_module.AddExternalImport(tobjectdef(pd.struct).import_lib^,pd.mangledname,pd.mangledname,0,false,false)
+ else
+ begin
+ { add import name to external list for DLL scanning }
+ if tf_has_dllscanner in target_info.flags then
+ current_module.dllscannerinputlist.Add(pd.mangledname,pd);
+ end;
+
+ end;
+ end;
+ end;
+
+
+ procedure tobjectdef.finish_cpp_data;
+ begin
+ self.symtable.DefList.ForEachCall(@do_cpp_import_info,nil);
+ end;
+
+{****************************************************************************
+ TImplementedInterface
+****************************************************************************}
+
+ constructor TImplementedInterface.create(aintf: tobjectdef);
+ begin
+ inherited create;
+ intfdef:=aintf;
+ IOffset:=-1;
+ IType:=etStandard;
+ NameMappings:=nil;
+ procdefs:=nil;
+ end;
+
+
+ constructor TImplementedInterface.create_deref(d:tderef);
+ begin
+ inherited create;
+ intfdef:=nil;
+ intfdefderef:=d;
+ IOffset:=-1;
+ IType:=etStandard;
+ NameMappings:=nil;
+ procdefs:=nil;
+ end;
+
+
+ destructor TImplementedInterface.destroy;
+ var
+ i : longint;
+ mappedname : pshortstring;
+ begin
+ if assigned(NameMappings) then
+ begin
+ for i:=0 to NameMappings.Count-1 do
+ begin
+ mappedname:=pshortstring(NameMappings[i]);
+ stringdispose(mappedname);
+ end;
+ NameMappings.free;
+ NameMappings:=nil;
+ end;
+ if assigned(procdefs) then
+ begin
+ procdefs.free;
+ procdefs:=nil;
+ end;
+ inherited destroy;
+ end;
+
+
+ procedure TImplementedInterface.buildderef;
+ begin
+ intfdefderef.build(intfdef);
+ end;
+
+
+ procedure TImplementedInterface.deref;
+ begin
+ intfdef:=tobjectdef(intfdefderef.resolve);
+ end;
+
+
+ procedure TImplementedInterface.AddMapping(const origname,newname: string);
+ begin
+ if not assigned(NameMappings) then
+ NameMappings:=TFPHashList.Create;
+ NameMappings.Add(origname,stringdup(newname));
+ end;
+
+
+ function TImplementedInterface.GetMapping(const origname: string):string;
+ var
+ mappedname : pshortstring;
+ begin
+ result:='';
+ if not assigned(NameMappings) then
+ exit;
+ mappedname:=PShortstring(NameMappings.Find(origname));
+ if assigned(mappedname) then
+ result:=mappedname^;
+ end;
+
+
+ procedure TImplementedInterface.AddImplProc(pd:tprocdef);
+ begin
+ if not assigned(procdefs) then
+ procdefs:=TFPObjectList.Create(false);
+ { duplicate entries must be stored, because multiple }
+ { interfaces can declare methods with the same name }
+ { and all of these get their own VMT entry }
+ procdefs.Add(pd);
+ end;
+
+
+ function TImplementedInterface.IsImplMergePossible(MergingIntf:TImplementedInterface;out weight: longint): boolean;
+ var
+ i : longint;
+ begin
+ result:=false;
+ { interfaces being implemented through delegation are not mergable (FK) }
+ if (IType<>etStandard) or (MergingIntf.IType<>etStandard) or not(assigned(ProcDefs)) or not(assigned(MergingIntf.ProcDefs)) then
+ exit;
+ weight:=0;
+ { empty interface is mergeable }
+ if ProcDefs.Count=0 then
+ begin
+ result:=true;
+ exit;
+ end;
+ { The interface to merge must at least the number of
+ procedures of this interface }
+ if MergingIntf.ProcDefs.Count<ProcDefs.Count then
+ exit;
+ for i:=0 to ProcDefs.Count-1 do
+ begin
+ if MergingIntf.ProcDefs[i]<>ProcDefs[i] then
+ exit;
+ end;
+ weight:=ProcDefs.Count;
+ result:=true;
+ end;
+
+
+ function TImplementedInterface.getcopy:TImplementedInterface;
+ begin
+ Result:=TImplementedInterface.Create(nil);
+ { 1) the procdefs list will be freed once for each copy
+ 2) since the procdefs list owns its elements, those will also be freed for each copy
+ 3) idem for the name mappings
+ }
+ { warning: this is completely wrong on so many levels...
+ Move(pointer(self)^,pointer(result)^,InstanceSize);
+ We need to make clean copies of the different fields
+ this is not implemented yet, and thus we generate an internal
+ error instead PM 2011-06-14 }
+ internalerror(2011061401);
+ end;
+
+{****************************************************************************
+ TFORWARDDEF
+****************************************************************************}
+
+ constructor tforwarddef.create(const s:string;const pos:tfileposinfo);
+ begin
+ inherited create(forwarddef);
+ tosymname:=stringdup(s);
+ forwardpos:=pos;
+ end;
+
+
+ function tforwarddef.GetTypeName:string;
+ begin
+ GetTypeName:='unresolved forward to '+tosymname^;
+ end;
+
+
+ destructor tforwarddef.destroy;
+ begin
+ stringdispose(tosymname);
+ inherited destroy;
+ end;
+
+ function tforwarddef.getcopy:tstoreddef;
+ begin
+ result:=tforwarddef.create(tosymname^, forwardpos);
+ end;
+
+{****************************************************************************
+ TUNDEFINEDDEF
+****************************************************************************}
+
+ constructor tundefineddef.create;
+ begin
+ inherited create(undefineddef);
+ end;
+
+
+ constructor tundefineddef.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(undefineddef,ppufile);
+ end;
+
+ function tundefineddef.GetTypeName:string;
+ begin
+ GetTypeName:='<undefined type>';
+ end;
+
+
+ procedure tundefineddef.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.writeentry(ibundefineddef);
+ end;
+
+
+{****************************************************************************
+ TERRORDEF
+****************************************************************************}
+
+ constructor terrordef.create;
+ begin
+ inherited create(errordef);
+ { prevent consecutive faults }
+ savesize:=1;
+ end;
+
+
+ procedure terrordef.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ { Can't write errordefs to ppu }
+ internalerror(200411063);
+ end;
+
+
+ function terrordef.GetTypeName:string;
+ begin
+ GetTypeName:='<erroneous type>';
+ end;
+
+
+ function terrordef.getmangledparaname:string;
+ begin
+ getmangledparaname:='error';
+ end;
+
+
+{****************************************************************************
+ Definition Helpers
+****************************************************************************}
+
+ function is_interfacecom(def: tdef): boolean;
+ begin
+ is_interfacecom:=
+ assigned(def) and
+ (def.typ=objectdef) and
+ (tobjectdef(def).objecttype=odt_interfacecom);
+ end;
+
+ function is_interfacecom_or_dispinterface(def: tdef): boolean;
+ begin
+ is_interfacecom_or_dispinterface:=
+ assigned(def) and
+ (def.typ=objectdef) and
+ (tobjectdef(def).objecttype in [odt_interfacecom,odt_dispinterface]);
+ end;
+
+ function is_interfacecorba(def: tdef): boolean;
+ begin
+ is_interfacecorba:=
+ assigned(def) and
+ (def.typ=objectdef) and
+ (tobjectdef(def).objecttype=odt_interfacecorba);
+ end;
+
+ function is_interface(def: tdef): boolean;
+ begin
+ is_interface:=
+ assigned(def) and
+ (def.typ=objectdef) and
+ (tobjectdef(def).objecttype in [odt_interfacecom,odt_interfacecorba]);
+ end;
+
+
+ function is_dispinterface(def: tdef): boolean;
+ begin
+ result:=
+ assigned(def) and
+ (def.typ=objectdef) and
+ (tobjectdef(def).objecttype=odt_dispinterface);
+ end;
+
+
+ function is_class(def: tdef): boolean;
+ begin
+ is_class:=
+ assigned(def) and
+ (def.typ=objectdef) and
+ (tobjectdef(def).objecttype=odt_class);
+ end;
+
+
+ function is_object(def: tdef): boolean;
+ begin
+ is_object:=
+ assigned(def) and
+ (def.typ=objectdef) and
+ (tobjectdef(def).objecttype=odt_object);
+ end;
+
+
+ function is_cppclass(def: tdef): boolean;
+ begin
+ is_cppclass:=
+ assigned(def) and
+ (def.typ=objectdef) and
+ (tobjectdef(def).objecttype=odt_cppclass);
+ end;
+
+
+ function is_objcclass(def: tdef): boolean;
+ begin
+ is_objcclass:=
+ assigned(def) and
+ (def.typ=objectdef) and
+ (tobjectdef(def).objecttype=odt_objcclass);
+ end;
+
+
+ function is_objectpascal_helper(def: tdef): boolean;
+ begin
+ result:=
+ assigned(def) and
+ (def.typ=objectdef) and
+ (tobjectdef(def).objecttype=odt_helper);
+ end;
+
+
+ function is_objcclassref(def: tdef): boolean;
+ begin
+ is_objcclassref:=
+ assigned(def) and
+ (def.typ=classrefdef) and
+ is_objcclass(tclassrefdef(def).pointeddef);
+ end;
+
+
+ function is_objcprotocol(def: tdef): boolean;
+ begin
+ result:=
+ assigned(def) and
+ (def.typ=objectdef) and
+ (tobjectdef(def).objecttype=odt_objcprotocol);
+ end;
+
+
+ function is_objccategory(def: tdef): boolean;
+ begin
+ result:=
+ assigned(def) and
+ (def.typ=objectdef) and
+ { if used as a forward type }
+ ((tobjectdef(def).objecttype=odt_objccategory) or
+ { if used as after it has been resolved }
+ ((tobjectdef(def).objecttype=odt_objcclass) and
+ (oo_is_classhelper in tobjectdef(def).objectoptions)));
+ end;
+
+ function is_objc_class_or_protocol(def: tdef): boolean;
+ begin
+ result:=
+ assigned(def) and
+ (def.typ=objectdef) and
+ (tobjectdef(def).objecttype in [odt_objcclass,odt_objcprotocol]);
+ end;
+
+
+ function is_objc_protocol_or_category(def: tdef): boolean;
+ begin
+ result:=
+ assigned(def) and
+ (def.typ=objectdef) and
+ ((tobjectdef(def).objecttype = odt_objcprotocol) or
+ ((tobjectdef(def).objecttype = odt_objcclass) and
+ (oo_is_classhelper in tobjectdef(def).objectoptions)));
+ end;
+
+ function is_classhelper(def: tdef): boolean;
+ begin
+ result:=
+ is_objectpascal_helper(def) or
+ is_objccategory(def);
+ end;
+
+ function is_class_or_interface(def: tdef): boolean;
+ begin
+ result:=
+ assigned(def) and
+ (def.typ=objectdef) and
+ (tobjectdef(def).objecttype in [odt_class,odt_interfacecom,odt_interfacecorba]);
+ end;
+
+
+ function is_class_or_interface_or_objc(def: tdef): boolean;
+ begin
+ result:=
+ assigned(def) and
+ (def.typ=objectdef) and
+ (tobjectdef(def).objecttype in [odt_class,odt_interfacecom,odt_interfacecorba,odt_objcclass,odt_objcprotocol]);
+ end;
+
+
+ function is_class_or_interface_or_object(def: tdef): boolean;
+ begin
+ result:=
+ assigned(def) and
+ (def.typ=objectdef) and
+ (tobjectdef(def).objecttype in [odt_class,odt_interfacecom,odt_interfacecorba,odt_object]);
+ end;
+
+
+ function is_class_or_interface_or_dispinterface(def: tdef): boolean;
+ begin
+ result:=
+ assigned(def) and
+ (def.typ=objectdef) and
+ (tobjectdef(def).objecttype in [odt_class,odt_interfacecom,odt_interfacecorba,odt_dispinterface]);
+ end;
+
+
+ function is_implicit_pointer_object_type(def: tdef): boolean;
+ begin
+ result:=
+ assigned(def) and
+ (def.typ=objectdef) and
+ (tobjectdef(def).objecttype in [odt_class,odt_interfacecom,odt_interfacecorba,odt_dispinterface,odt_objcclass,odt_objcprotocol,odt_helper]);
+ end;
+
+ function is_class_or_object(def: tdef): boolean;
+ begin
+ result:=
+ assigned(def) and
+ (def.typ=objectdef) and
+ (tobjectdef(def).objecttype in [odt_class,odt_object]);
+ end;
+
+ function is_record(def: tdef): boolean;
+ begin
+ result:=
+ assigned(def) and
+ (def.typ=recorddef);
+ end;
+
+ procedure loadobjctypes;
+ begin
+ objc_metaclasstype:=tpointerdef(search_named_unit_globaltype('OBJC','POBJC_CLASS',true).typedef);
+ objc_superclasstype:=tpointerdef(search_named_unit_globaltype('OBJC','POBJC_SUPER',true).typedef);
+ objc_idtype:=tpointerdef(search_named_unit_globaltype('OBJC','ID',true).typedef);
+ objc_seltype:=tpointerdef(search_named_unit_globaltype('OBJC','SEL',true).typedef);
+ objc_objecttype:=trecorddef(search_named_unit_globaltype('OBJC','OBJC_OBJECT',true).typedef);
+ end;
+
+
+ procedure maybeloadcocoatypes;
+ var
+ tsym: ttypesym;
+ begin
+ if assigned(objc_fastenumeration) then
+ exit;
+ tsym:=search_named_unit_globaltype('COCOAALL','NSFASTENUMERATIONPROTOCOL',false);
+ if assigned(tsym) then
+ objc_fastenumeration:=tobjectdef(tsym.typedef)
+ else
+ objc_fastenumeration:=nil;
+ tsym:=search_named_unit_globaltype('COCOAALL','NSFASTENUMERATIONSTATE',false);
+ if assigned(tsym) then
+ objc_fastenumerationstate:=trecorddef(tsym.typedef)
+ else
+ objc_fastenumerationstate:=nil;
+ end;
+
+
+ function use_vectorfpu(def : tdef) : boolean;
+ begin
+{$ifdef x86}
+{$define use_vectorfpuimplemented}
+ use_vectorfpu:=(is_single(def) and (current_settings.fputype in sse_singlescalar)) or
+ (is_double(def) and (current_settings.fputype in sse_doublescalar));
+{$endif x86}
+{$ifdef arm}
+{$define use_vectorfpuimplemented}
+ use_vectorfpu:=(current_settings.fputype in vfp_scalar);
+{$endif arm}
+{$ifndef use_vectorfpuimplemented}
+ use_vectorfpu:=false;
+{$endif}
+ end;
+
+end.
diff --git a/closures/compiler/symnot.pas b/closures/compiler/symnot.pas
new file mode 100644
index 0000000000..198bc43063
--- /dev/null
+++ b/closures/compiler/symnot.pas
@@ -0,0 +1,63 @@
+{
+ Copyright (c) 2002 by Daniel Mantione
+
+ This unit contains support routines for the variable access
+ notifier.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+
+unit symnot;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses cclasses,symtype;
+
+type Tnotification_flag=(vn_onread,vn_onwrite,vn_unknown);
+ Tnotification_flags=set of Tnotification_flag;
+
+ Tnotification_callback=procedure(not_type:Tnotification_flag;
+ symbol:Tsym) of object;
+
+ Tnotification=class(Tlinkedlistitem)
+ flags:Tnotification_flags;
+ callback:Tnotification_callback;
+ id:cardinal;
+ constructor create(Aflags:Tnotification_flags;
+ Acallback:Tnotification_callback);
+ end;
+
+implementation
+
+var notification_counter:cardinal;
+
+constructor Tnotification.create(Aflags:Tnotification_flags;
+ Acallback:Tnotification_callback);
+
+begin
+ inherited create;
+ flags:=Aflags;
+ callback:=Acallback;
+ id:=notification_counter;
+ inc(notification_counter);
+end;
+
+begin
+ notification_counter:=0;
+end.
diff --git a/closures/compiler/symsym.pas b/closures/compiler/symsym.pas
new file mode 100644
index 0000000000..c91d3e5d80
--- /dev/null
+++ b/closures/compiler/symsym.pas
@@ -0,0 +1,2109 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl, Pierre Muller
+
+ Implementation for the symbols types of the symtable
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ ****************************************************************************
+}
+unit symsym;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ { common }
+ cutils,
+ { target }
+ globtype,globals,widestr,constexp,
+ { symtable }
+ symconst,symbase,symtype,symdef,defcmp,
+ { ppu }
+ ppu,finput,
+ cclasses,symnot,
+ { aasm }
+ aasmbase,
+ cpuinfo,cpubase,cgbase,cgutils,parabase
+ ;
+
+ type
+ { this class is the base for all symbol objects }
+ tstoredsym = class(tsym)
+ public
+ constructor create(st:tsymtyp;const n : string);
+ constructor ppuload(st:tsymtyp;ppufile:tcompilerppufile);
+ destructor destroy;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);virtual;
+ end;
+
+ tlabelsym = class(tstoredsym)
+ used,
+ defined,
+ nonlocal : boolean;
+ { points to the matching node, only valid resultdef pass is run and
+ the goto<->label relation in the node tree is created, should
+ be a tnode }
+ code : pointer;
+
+ { points to the jump buffer }
+ jumpbuf : tstoredsym;
+
+ { when the label is defined in an asm block, this points to the
+ generated asmlabel }
+ asmblocklabel : tasmlabel;
+ constructor create(const n : string);
+ constructor ppuload(ppufile:tcompilerppufile);
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ function mangledname:string;override;
+ end;
+
+ tunitsym = class(Tstoredsym)
+ module : tobject; { tmodule }
+ constructor create(const n : string;amodule : tobject);
+ constructor ppuload(ppufile:tcompilerppufile);
+ destructor destroy;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ end;
+
+ tnamespacesym = class(Tstoredsym)
+ unitsym:tsym;
+ unitsymderef:tderef;
+ constructor create(const n : string);
+ constructor ppuload(ppufile:tcompilerppufile);
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderef;override;
+ procedure deref;override;
+ end;
+
+ terrorsym = class(Tsym)
+ constructor create;
+ end;
+
+ { tprocsym }
+
+ tprocsym = class(tstoredsym)
+ protected
+ FProcdefList : TFPObjectList;
+ FProcdefDerefList : TFPList;
+ public
+ constructor create(const n : string);
+ constructor ppuload(ppufile:tcompilerppufile);
+ destructor destroy;override;
+ { writes all declarations except the specified one }
+ procedure write_parameter_lists(skipdef:tprocdef);
+ { tests, if all procedures definitions are defined and not }
+ { only forward }
+ procedure check_forward;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderef;override;
+ procedure deref;override;
+ function find_procdef_bytype(pt:Tproctypeoption):Tprocdef;
+ function find_procdef_bypara(para:TFPObjectList;retdef:tdef;cpoptions:tcompare_paras_options):Tprocdef;
+ function find_procdef_byoptions(ops:tprocoptions): Tprocdef;
+ function find_procdef_byprocvardef(d:Tprocvardef):Tprocdef;
+ function find_procdef_assignment_operator(fromdef,todef:tdef;var besteq:tequaltype):Tprocdef;
+ function find_procdef_enumerator_operator(fromdef,todef:tdef;var besteq:tequaltype):Tprocdef;
+ property ProcdefList:TFPObjectList read FProcdefList;
+ end;
+
+ ttypesym = class(Tstoredsym)
+ public
+ typedef : tdef;
+ typedefderef : tderef;
+ fprettyname : ansistring;
+ constructor create(const n : string;def:tdef);
+ constructor ppuload(ppufile:tcompilerppufile);
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderef;override;
+ procedure deref;override;
+ function prettyname : string;override;
+ end;
+
+ tabstractvarsym = class(tstoredsym)
+ varoptions : tvaroptions;
+ notifications : Tlinkedlist;
+ varspez : tvarspez; { sets the type of access }
+ varregable : tvarregable;
+ varstate : tvarstate;
+ { Has the address of this variable potentially escaped the }
+ { block in which is was declared? }
+ { could also be part of tabstractnormalvarsym, but there's }
+ { one byte left here till the next 4 byte alignment }
+ addr_taken : boolean;
+ constructor create(st:tsymtyp;const n : string;vsp:tvarspez;def:tdef;vopts:tvaroptions);
+ constructor ppuload(st:tsymtyp;ppufile:tcompilerppufile);
+ destructor destroy;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderef;override;
+ procedure deref;override;
+ function getsize : asizeint;
+ function getpackedbitsize : longint;
+ function is_regvar(refpara: boolean):boolean;
+ procedure trigger_notifications(what:Tnotification_flag);
+ function register_notification(flags:Tnotification_flags;
+ callback:Tnotification_callback):cardinal;
+ procedure unregister_notification(id:cardinal);
+ private
+ _vardef : tdef;
+ vardefderef : tderef;
+
+ procedure setvardef(def:tdef);
+ public
+ property vardef: tdef read _vardef write setvardef;
+ end;
+
+ tfieldvarsym = class(tabstractvarsym)
+ fieldoffset : asizeint; { offset in record/object }
+ objcoffsetmangledname: pshortstring; { mangled name of offset, calculated as needed }
+ constructor create(const n : string;vsp:tvarspez;def:tdef;vopts:tvaroptions);
+ constructor ppuload(ppufile:tcompilerppufile);
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ function mangledname:string;override;
+ destructor destroy;override;
+ end;
+
+ tabstractnormalvarsym = class(tabstractvarsym)
+ defaultconstsym : tsym;
+ defaultconstsymderef : tderef;
+ localloc : TLocation; { register/reference for local var }
+ initialloc : TLocation; { initial location so it can still be initialized later after the location was changed by SSA }
+ constructor create(st:tsymtyp;const n : string;vsp:tvarspez;def:tdef;vopts:tvaroptions);
+ constructor ppuload(st:tsymtyp;ppufile:tcompilerppufile);
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderef;override;
+ procedure deref;override;
+ end;
+
+ tlocalvarsym = class(tabstractnormalvarsym)
+ constructor create(const n : string;vsp:tvarspez;def:tdef;vopts:tvaroptions);
+ constructor ppuload(ppufile:tcompilerppufile);
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ end;
+
+ tparavarsym = class(tabstractnormalvarsym)
+ paraloc : array[tcallercallee] of TCGPara;
+ paranr : word; { position of this parameter }
+ { in MacPas mode, "univ" parameters mean that type checking should
+ be disabled, except that the size of the passed parameter must
+ match the size of the formal parameter }
+ univpara : boolean;
+{$ifdef EXTDEBUG}
+ eqval : tequaltype;
+{$endif EXTDEBUG}
+ constructor create(const n : string;nr:word;vsp:tvarspez;def:tdef;vopts:tvaroptions);
+ constructor ppuload(ppufile:tcompilerppufile);
+ destructor destroy;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ function needs_finalization: boolean;
+ end;
+
+ tstaticvarsym = class(tabstractnormalvarsym)
+ private
+ _mangledname : pshortstring;
+ public
+ section : ansistring;
+ constructor create(const n : string;vsp:tvarspez;def:tdef;vopts:tvaroptions);
+ constructor create_dll(const n : string;vsp:tvarspez;def:tdef);
+ constructor create_C(const n,mangled : string;vsp:tvarspez;def:tdef);
+ constructor ppuload(ppufile:tcompilerppufile);
+ destructor destroy;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ function mangledname:string;override;
+ procedure set_mangledname(const s:string);
+ end;
+
+ tabsolutevarsym = class(tabstractvarsym)
+ public
+ abstyp : absolutetyp;
+{$ifdef i386}
+ absseg : boolean;
+{$endif i386}
+ asmname : pshortstring;
+ addroffset : aword;
+ ref : tpropaccesslist;
+ constructor create(const n : string;def:tdef);
+ constructor create_ref(const n : string;def:tdef;_ref:tpropaccesslist);
+ destructor destroy;override;
+ constructor ppuload(ppufile:tcompilerppufile);
+ procedure buildderef;override;
+ procedure deref;override;
+ function mangledname : string;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ end;
+
+ tpropaccesslisttypes=(palt_none,palt_read,palt_write,palt_stored);
+
+ tpropertysym = class(Tstoredsym)
+ propoptions : tpropertyoptions;
+ overriddenpropsym : tpropertysym;
+ overriddenpropsymderef : tderef;
+ propdef : tdef;
+ propdefderef : tderef;
+ indexdef : tdef;
+ indexdefderef : tderef;
+ index,
+ default : longint;
+ dispid : longint;
+ propaccesslist: array[tpropaccesslisttypes] of tpropaccesslist;
+ parast : tsymtable;
+ constructor create(const n : string);
+ destructor destroy;override;
+ constructor ppuload(ppufile:tcompilerppufile);
+ function getsize : asizeint;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderef;override;
+ procedure deref;override;
+ end;
+
+ tconstvalue = record
+ case integer of
+ 0: (valueord : tconstexprint);
+ 1: (valueordptr : tconstptruint);
+ 2: (valueptr : pointer; len : longint);
+ end;
+
+ tconstsym = class(tstoredsym)
+ constdef : tdef;
+ constdefderef : tderef;
+ consttyp : tconsttyp;
+ value : tconstvalue;
+ constructor create_ord(const n : string;t : tconsttyp;v : tconstexprint;def:tdef);
+ constructor create_ordptr(const n : string;t : tconsttyp;v : tconstptruint;def:tdef);
+ constructor create_ptr(const n : string;t : tconsttyp;v : pointer;def:tdef);
+ constructor create_string(const n : string;t : tconsttyp;str:pchar;l:longint);
+ constructor create_wstring(const n : string;t : tconsttyp;pw:pcompilerwidestring);
+ constructor ppuload(ppufile:tcompilerppufile);
+ destructor destroy;override;
+ procedure buildderef;override;
+ procedure deref;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ end;
+
+ tenumsym = class(Tstoredsym)
+ value : longint;
+ definition : tenumdef;
+ definitionderef : tderef;
+ constructor create(const n : string;def : tenumdef;v : longint);
+ constructor ppuload(ppufile:tcompilerppufile);
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderef;override;
+ procedure deref;override;
+ end;
+
+ tsyssym = class(Tstoredsym)
+ number : longint;
+ constructor create(const n : string;l : longint);
+ constructor ppuload(ppufile:tcompilerppufile);
+ destructor destroy;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ end;
+
+ const
+ maxmacrolen=16*1024;
+
+ type
+ pmacrobuffer = ^tmacrobuffer;
+ tmacrobuffer = array[0..maxmacrolen-1] of char;
+
+ tmacro = class(tstoredsym)
+ {Normally true, but false when a previously defined macro is undef-ed}
+ defined : boolean;
+ {True if this is a mac style compiler variable, in which case no macro
+ substitutions shall be done.}
+ is_compiler_var : boolean;
+ {Whether the macro was used. NOTE: A use of a macro which was never defined}
+ {e. g. an IFDEF which returns false, will not be registered as used,}
+ {since there is no place to register its use. }
+ is_used : boolean;
+ buftext : pchar;
+ buflen : longint;
+ constructor create(const n : string);
+ constructor ppuload(ppufile:tcompilerppufile);
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ destructor destroy;override;
+ function GetCopy:tmacro;
+ end;
+
+ var
+ generrorsym : tsym;
+
+implementation
+
+ uses
+ { global }
+ verbose,
+ { target }
+ systems,
+ { symtable }
+ defutil,symtable,
+ fmodule,
+ { tree }
+ node,
+ { aasm }
+ aasmtai,aasmdata,
+ { codegen }
+ paramgr,
+ procinfo
+ ;
+
+{****************************************************************************
+ Helpers
+****************************************************************************}
+
+{****************************************************************************
+ TSYM (base for all symtypes)
+****************************************************************************}
+
+ constructor tstoredsym.create(st:tsymtyp;const n : string);
+ begin
+ inherited create(st,n);
+ { Register in current_module }
+ if assigned(current_module) then
+ begin
+ current_module.symlist.Add(self);
+ SymId:=current_module.symlist.Count-1;
+ end;
+ end;
+
+
+ constructor tstoredsym.ppuload(st:tsymtyp;ppufile:tcompilerppufile);
+ begin
+ SymId:=ppufile.getlongint;
+ inherited Create(st,ppufile.getstring);
+ { Register symbol }
+ current_module.symlist[SymId]:=self;
+ ppufile.getposinfo(fileinfo);
+ visibility:=tvisibility(ppufile.getbyte);
+ ppufile.getsmallset(symoptions);
+ if sp_has_deprecated_msg in symoptions then
+ deprecatedmsg:=stringdup(ppufile.getstring)
+ else
+ deprecatedmsg:=nil;
+ end;
+
+
+ procedure tstoredsym.ppuwrite(ppufile:tcompilerppufile);
+ var
+ oldintfcrc : boolean;
+ begin
+ ppufile.putlongint(SymId);
+ ppufile.putstring(realname);
+ ppufile.putposinfo(fileinfo);
+ ppufile.putbyte(byte(visibility));
+ { symoptions can differ between interface and implementation, except
+ for overload (this is checked in pdecsub.proc_add_definition() )
+
+ These differences can lead to compiler crashes, so ignore them.
+ This does mean that changing e.g. the "deprecated" state of a symbol
+ by itself will not trigger a recompilation of dependent units.
+ }
+ oldintfcrc:=ppufile.do_interface_crc;
+ ppufile.do_interface_crc:=false;
+ ppufile.putsmallset(symoptions);
+ if sp_has_deprecated_msg in symoptions then
+ ppufile.putstring(deprecatedmsg^);
+ ppufile.do_interface_crc:=oldintfcrc;
+ end;
+
+
+ destructor tstoredsym.destroy;
+ begin
+ inherited destroy;
+ end;
+
+
+{****************************************************************************
+ TLABELSYM
+****************************************************************************}
+
+ constructor tlabelsym.create(const n : string);
+ begin
+ inherited create(labelsym,n);
+ used:=false;
+ defined:=false;
+ nonlocal:=false;
+ code:=nil;
+ end;
+
+
+ constructor tlabelsym.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(labelsym,ppufile);
+ code:=nil;
+ used:=false;
+ nonlocal:=false;
+ defined:=true;
+ end;
+
+
+ procedure tlabelsym.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ if owner.symtabletype=globalsymtable then
+ Message(sym_e_ill_label_decl)
+ else
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.writeentry(iblabelsym);
+ end;
+ end;
+
+
+ function tlabelsym.mangledname:string;
+ begin
+ if not(defined) then
+ begin
+ defined:=true;
+ if nonlocal then
+ current_asmdata.getglobaljumplabel(asmblocklabel)
+ else
+ current_asmdata.getjumplabel(asmblocklabel);
+ end;
+ result:=asmblocklabel.name;
+ end;
+
+{****************************************************************************
+ TUNITSYM
+****************************************************************************}
+
+ constructor tunitsym.create(const n : string;amodule : tobject);
+ begin
+ inherited create(unitsym,n);
+ module:=amodule;
+ end;
+
+ constructor tunitsym.ppuload(ppufile:tcompilerppufile);
+
+ begin
+ inherited ppuload(unitsym,ppufile);
+ module:=nil;
+ end;
+
+ destructor tunitsym.destroy;
+ begin
+ inherited destroy;
+ end;
+
+ procedure tunitsym.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.writeentry(ibunitsym);
+ end;
+
+{****************************************************************************
+ TNAMESPACESYM
+****************************************************************************}
+
+ constructor tnamespacesym.create(const n : string);
+ begin
+ inherited create(namespacesym,n);
+ unitsym:=nil;
+ end;
+
+ constructor tnamespacesym.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(namespacesym,ppufile);
+ ppufile.getderef(unitsymderef);
+ end;
+
+ procedure tnamespacesym.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putderef(unitsymderef);
+ ppufile.writeentry(ibnamespacesym);
+ end;
+
+ procedure tnamespacesym.buildderef;
+ begin
+ inherited buildderef;
+ unitsymderef.build(unitsym);
+ end;
+
+ procedure tnamespacesym.deref;
+ begin
+ inherited deref;
+ unitsym:=tsym(unitsymderef.resolve);
+ end;
+
+
+{****************************************************************************
+ TPROCSYM
+****************************************************************************}
+
+ constructor tprocsym.create(const n : string);
+ begin
+ inherited create(procsym,n);
+ FProcdefList:=TFPObjectList.Create(false);
+ FProcdefderefList:=nil;
+ { the tprocdef have their own symoptions, make the procsym
+ always visible }
+ visibility:=vis_public;
+ end;
+
+
+ constructor tprocsym.ppuload(ppufile:tcompilerppufile);
+ var
+ pdderef : tderef;
+ i,
+ pdcnt : longint;
+ begin
+ inherited ppuload(procsym,ppufile);
+ FProcdefList:=TFPObjectList.Create(false);
+ FProcdefDerefList:=TFPList.Create;
+ pdcnt:=ppufile.getword;
+ for i:=1 to pdcnt do
+ begin
+ ppufile.getderef(pdderef);
+ FProcdefDerefList.Add(Pointer(PtrInt(pdderef.dataidx)));
+ end;
+ end;
+
+
+ destructor tprocsym.destroy;
+ begin
+ FProcdefList.Free;
+ if assigned(FProcdefDerefList) then
+ FProcdefDerefList.Free;
+ inherited destroy;
+ end;
+
+
+ procedure tprocsym.ppuwrite(ppufile:tcompilerppufile);
+ var
+ i : longint;
+ d : tderef;
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putword(FProcdefDerefList.Count);
+ for i:=0 to FProcdefDerefList.Count-1 do
+ begin
+ d.dataidx:=PtrInt(FProcdefDerefList[i]);
+ ppufile.putderef(d);
+ end;
+ ppufile.writeentry(ibprocsym);
+ end;
+
+
+ procedure tprocsym.write_parameter_lists(skipdef:tprocdef);
+ var
+ i : longint;
+ pd : tprocdef;
+ begin
+ for i:=0 to ProcdefList.Count-1 do
+ begin
+ pd:=tprocdef(ProcdefList[i]);
+ if pd<>skipdef then
+ MessagePos1(pd.fileinfo,sym_h_param_list,pd.fullprocname(false));
+ end;
+ end;
+
+
+ procedure tprocsym.check_forward;
+ var
+ i : longint;
+ pd : tprocdef;
+ begin
+ for i:=0 to ProcdefList.Count-1 do
+ begin
+ pd:=tprocdef(ProcdefList[i]);
+ if (pd.owner=owner) and (pd.forwarddef) then
+ begin
+ { For mode macpas. Make implicit externals (procedures declared in the interface
+ section which do not have a counterpart in the implementation)
+ to be an imported procedure }
+ if (m_mac in current_settings.modeswitches) and
+ (pd.interfacedef) then
+ begin
+ pd.setmangledname(target_info.CPrefix+tprocdef(pd).procsym.realname);
+ if (not current_module.interface_only) then
+ MessagePos1(pd.fileinfo,sym_w_forward_not_resolved,pd.fullprocname(false));
+ end
+ else
+ begin
+ MessagePos1(pd.fileinfo,sym_e_forward_not_resolved,pd.fullprocname(false));
+ end;
+ { Turn further error messages off }
+ pd.forwarddef:=false;
+ end;
+ end;
+ end;
+
+
+ procedure tprocsym.buildderef;
+ var
+ i : longint;
+ pd : tprocdef;
+ d : tderef;
+ begin
+ if not assigned(FProcdefDerefList) then
+ FProcdefDerefList:=TFPList.Create
+ else
+ FProcdefDerefList.Clear;
+ for i:=0 to ProcdefList.Count-1 do
+ begin
+ pd:=tprocdef(ProcdefList[i]);
+ { only write the proc definitions that belong
+ to this procsym and are in the global symtable }
+ if pd.owner=owner then
+ begin
+ d.build(pd);
+ FProcdefDerefList.Add(Pointer(PtrInt(d.dataidx)));
+ end;
+ end;
+ end;
+
+
+ procedure tprocsym.deref;
+ var
+ i : longint;
+ pd : tprocdef;
+ d : tderef;
+ begin
+ { Clear all procdefs }
+ ProcdefList.Clear;
+ if not assigned(FProcdefDerefList) then
+ internalerror(200611031);
+ for i:=0 to FProcdefDerefList.Count-1 do
+ begin
+ d.dataidx:=PtrInt(FProcdefDerefList[i]);
+ pd:=tprocdef(d.resolve);
+ ProcdefList.Add(pd);
+ end;
+ end;
+
+
+ function Tprocsym.Find_procdef_bytype(pt:Tproctypeoption):Tprocdef;
+ var
+ i : longint;
+ pd : tprocdef;
+ begin
+ result:=nil;
+ for i:=0 to ProcdefList.Count-1 do
+ begin
+ pd:=tprocdef(ProcdefList[i]);
+ if pd.proctypeoption=pt then
+ begin
+ result:=pd;
+ exit;
+ end;
+ end;
+ end;
+
+
+ function Tprocsym.Find_procdef_bypara(para:TFPObjectList;retdef:tdef;
+ cpoptions:tcompare_paras_options):Tprocdef;
+ var
+ i : longint;
+ pd : tprocdef;
+ eq : tequaltype;
+ begin
+ result:=nil;
+ for i:=0 to ProcdefList.Count-1 do
+ begin
+ pd:=tprocdef(ProcdefList[i]);
+ if assigned(retdef) then
+ eq:=compare_defs(retdef,pd.returndef,nothingn)
+ else
+ eq:=te_equal;
+ if (eq>=te_equal) or
+ ((cpo_allowconvert in cpoptions) and (eq>te_incompatible)) then
+ begin
+ eq:=compare_paras(para,pd.paras,cp_value_equal_const,cpoptions);
+ if (eq>=te_equal) or
+ ((cpo_allowconvert in cpoptions) and (eq>te_incompatible)) then
+ begin
+ result:=pd;
+ exit;
+ end;
+ end;
+ end;
+ end;
+
+ function tprocsym.find_procdef_byoptions(ops: tprocoptions): Tprocdef;
+ var
+ i : longint;
+ pd : tprocdef;
+ begin
+ result:=nil;
+ for i:=0 to ProcdefList.Count-1 do
+ begin
+ pd:=tprocdef(ProcdefList[i]);
+ if ops * pd.procoptions = ops then
+ begin
+ result:=pd;
+ exit;
+ end;
+ end;
+ end;
+
+ function Tprocsym.Find_procdef_byprocvardef(d:Tprocvardef):Tprocdef;
+ var
+ i : longint;
+ bestpd,
+ pd : tprocdef;
+ eq,besteq : tequaltype;
+ sym: tsym;
+ ps: tprocsym;
+ begin
+ { This function will return the pprocdef of pprocsym that
+ is the best match for procvardef. When there are multiple
+ matches it returns nil.}
+ result:=nil;
+ bestpd:=nil;
+ besteq:=te_incompatible;
+ ps:=self;
+ repeat
+ for i:=0 to ps.ProcdefList.Count-1 do
+ begin
+ pd:=tprocdef(ps.ProcdefList[i]);
+ eq:=proc_to_procvar_equal(pd,d,false);
+ if eq>=te_convert_l1 then
+ begin
+ { multiple procvars with the same equal level }
+ if assigned(bestpd) and
+ (besteq=eq) then
+ exit;
+ if eq>besteq then
+ begin
+ besteq:=eq;
+ bestpd:=pd;
+ end;
+ end;
+ end;
+ { maybe TODO: also search class helpers? -- this code is similar to
+ what happens in htypechk in
+ tcallcandidates.collect_overloads_in_struct: keep searching in
+ parent types in case the currently found procdef is marked as
+ "overload" and we haven't found a proper match yet }
+ if assigned(ps.owner.defowner) and
+ (ps.owner.defowner.typ=objectdef) and
+ assigned(tobjectdef(ps.owner.defowner).childof) and
+ (not assigned(bestpd) or
+ (po_overload in bestpd.procoptions)) then
+ begin
+ sym:=tsym(tobjectdef(ps.owner.defowner).childof.symtable.find(ps.name));
+ if assigned(sym) and
+ (sym.typ=procsym) then
+ ps:=tprocsym(sym)
+ else
+ ps:=nil;
+ end
+ else
+ ps:=nil;
+ until (besteq>=te_equal) or
+ not assigned(ps);
+ result:=bestpd;
+ end;
+
+
+ function Tprocsym.Find_procdef_assignment_operator(fromdef,todef:tdef;var besteq:tequaltype):Tprocdef;
+ var
+ paraidx, realparamcount,
+ i, j : longint;
+ bestpd,
+ hpd,
+ pd : tprocdef;
+ convtyp : tconverttype;
+ eq : tequaltype;
+ begin
+ { This function will return the pprocdef of pprocsym that
+ is the best match for fromdef and todef. }
+ result:=nil;
+ bestpd:=nil;
+ besteq:=te_incompatible;
+ for i:=0 to ProcdefList.Count-1 do
+ begin
+ pd:=tprocdef(ProcdefList[i]);
+ if (pd.owner.symtabletype=staticsymtable) and not pd.owner.iscurrentunit then
+ continue;
+ if (equal_defs(todef,pd.returndef) or
+ { shortstrings of different lengths are ok as result }
+ (is_shortstring(todef) and is_shortstring(pd.returndef))) and
+ { the result type must be always really equal and not an alias,
+ if you mess with this code, check tw4093 }
+ ((todef=pd.returndef) or
+ (
+ not(df_unique in todef.defoptions) and
+ not(df_unique in pd.returndef.defoptions)
+ )
+ ) then
+ begin
+ paraidx:=0;
+ { ignore vs_hidden parameters }
+ while (paraidx<pd.paras.count) and
+ assigned(pd.paras[paraidx]) and
+ (vo_is_hidden_para in tparavarsym(pd.paras[paraidx]).varoptions) do
+ inc(paraidx);
+ realparamcount:=0;
+ for j := 0 to pd.paras.Count-1 do
+ if assigned(pd.paras[j]) and not (vo_is_hidden_para in tparavarsym(pd.paras[j]).varoptions) then
+ inc(realparamcount);
+ if (paraidx<pd.paras.count) and
+ assigned(pd.paras[paraidx]) and
+ (realparamcount = 1) then
+ begin
+ eq:=compare_defs_ext(fromdef,tparavarsym(pd.paras[paraidx]).vardef,nothingn,convtyp,hpd,[]);
+
+ { alias? if yes, only l1 choice,
+ if you mess with this code, check tw4093 }
+ if (eq=te_exact) and
+ (fromdef<>tparavarsym(pd.paras[paraidx]).vardef) and
+ ((df_unique in fromdef.defoptions) or
+ (df_unique in tparavarsym(pd.paras[paraidx]).vardef.defoptions)) then
+ eq:=te_convert_l1;
+
+ if eq=te_exact then
+ begin
+ besteq:=eq;
+ result:=pd;
+ exit;
+ end;
+ if eq>besteq then
+ begin
+ bestpd:=pd;
+ besteq:=eq;
+ end;
+ end;
+ end;
+ end;
+ result:=bestpd;
+ end;
+
+ function Tprocsym.find_procdef_enumerator_operator(fromdef,todef:tdef;var besteq:tequaltype):Tprocdef;
+ var
+ paraidx, realparamcount,
+ i, j : longint;
+ bestpd,
+ hpd,
+ pd : tprocdef;
+ current : tpropertysym;
+ convtyp : tconverttype;
+ eq : tequaltype;
+ begin
+ { This function will return the pprocdef of pprocsym that
+ is the best match for fromdef and todef. }
+ result:=nil;
+ bestpd:=nil;
+ besteq:=te_incompatible;
+ for i:=0 to ProcdefList.Count-1 do
+ begin
+ pd:=tprocdef(ProcdefList[i]);
+ if (pd.owner.symtabletype=staticsymtable) and not pd.owner.iscurrentunit then
+ continue;
+ if not (is_class_or_interface_or_object(pd.returndef) or is_record(pd.returndef)) then
+ continue;
+ current := tpropertysym(tabstractrecorddef(pd.returndef).search_enumerator_current);
+ if (current = nil) then
+ continue;
+ // compare current result def with the todef
+ if (equal_defs(todef, current.propdef) or
+ { shortstrings of different lengths are ok as result }
+ (is_shortstring(todef) and is_shortstring(current.propdef))) and
+ { the result type must be always really equal and not an alias,
+ if you mess with this code, check tw4093 }
+ ((todef=current.propdef) or
+ (
+ not(df_unique in todef.defoptions) and
+ not(df_unique in current.propdef.defoptions)
+ )
+ ) then
+ begin
+ paraidx:=0;
+ { ignore vs_hidden parameters }
+ while (paraidx<pd.paras.count) and
+ assigned(pd.paras[paraidx]) and
+ (vo_is_hidden_para in tparavarsym(pd.paras[paraidx]).varoptions) do
+ inc(paraidx);
+ realparamcount:=0;
+ for j := 0 to pd.paras.Count-1 do
+ if assigned(pd.paras[j]) and not (vo_is_hidden_para in tparavarsym(pd.paras[j]).varoptions) then
+ inc(realparamcount);
+ if (paraidx<pd.paras.count) and
+ assigned(pd.paras[paraidx]) and
+ (realparamcount = 1) then
+ begin
+ eq:=compare_defs_ext(fromdef,tparavarsym(pd.paras[paraidx]).vardef,nothingn,convtyp,hpd,[]);
+
+ { alias? if yes, only l1 choice,
+ if you mess with this code, check tw4093 }
+ if (eq=te_exact) and
+ (fromdef<>tparavarsym(pd.paras[paraidx]).vardef) and
+ ((df_unique in fromdef.defoptions) or
+ (df_unique in tparavarsym(pd.paras[paraidx]).vardef.defoptions)) then
+ eq:=te_convert_l1;
+
+ if eq=te_exact then
+ begin
+ besteq:=eq;
+ result:=pd;
+ exit;
+ end;
+ if eq>besteq then
+ begin
+ bestpd:=pd;
+ besteq:=eq;
+ end;
+ end;
+ end;
+ end;
+ result:=bestpd;
+ end;
+
+
+{****************************************************************************
+ TERRORSYM
+****************************************************************************}
+
+ constructor terrorsym.create;
+ begin
+ inherited create(errorsym,'');
+ end;
+
+{****************************************************************************
+ TPROPERTYSYM
+****************************************************************************}
+
+ constructor tpropertysym.create(const n : string);
+ var
+ pap : tpropaccesslisttypes;
+ begin
+ inherited create(propertysym,n);
+ propoptions:=[];
+ index:=0;
+ default:=0;
+ propdef:=nil;
+ indexdef:=nil;
+ parast:=nil;
+ for pap:=low(tpropaccesslisttypes) to high(tpropaccesslisttypes) do
+ propaccesslist[pap]:=tpropaccesslist.create;
+ end;
+
+
+ constructor tpropertysym.ppuload(ppufile:tcompilerppufile);
+ var
+ pap : tpropaccesslisttypes;
+ begin
+ inherited ppuload(propertysym,ppufile);
+ ppufile.getsmallset(propoptions);
+ if ppo_overrides in propoptions then
+ ppufile.getderef(overriddenpropsymderef);
+ ppufile.getderef(propdefderef);
+ index:=ppufile.getlongint;
+ default:=ppufile.getlongint;
+ ppufile.getderef(indexdefderef);
+ for pap:=low(tpropaccesslisttypes) to high(tpropaccesslisttypes) do
+ propaccesslist[pap]:=ppufile.getpropaccesslist;
+ if [ppo_hasparameters,ppo_overrides]*propoptions=[ppo_hasparameters] then
+ begin
+ parast:=tparasymtable.create(nil,0);
+ tparasymtable(parast).ppuload(ppufile);
+ end
+ else
+ parast:=nil;
+ end;
+
+
+ destructor tpropertysym.destroy;
+ var
+ pap : tpropaccesslisttypes;
+ begin
+ for pap:=low(tpropaccesslisttypes) to high(tpropaccesslisttypes) do
+ propaccesslist[pap].free;
+ parast.free;
+ inherited destroy;
+ end;
+
+
+ procedure tpropertysym.buildderef;
+ var
+ pap : tpropaccesslisttypes;
+ begin
+ propdefderef.build(propdef);
+ indexdefderef.build(indexdef);
+ for pap:=low(tpropaccesslisttypes) to high(tpropaccesslisttypes) do
+ propaccesslist[pap].buildderef;
+ if ppo_overrides in propoptions then
+ overriddenpropsymderef.build(overriddenpropsym)
+ else
+ if ppo_hasparameters in propoptions then
+ tparasymtable(parast).buildderef;
+ end;
+
+
+ procedure tpropertysym.deref;
+ var
+ pap : tpropaccesslisttypes;
+ begin
+ indexdef:=tdef(indexdefderef.resolve);
+ propdef:=tdef(propdefderef.resolve);
+ for pap:=low(tpropaccesslisttypes) to high(tpropaccesslisttypes) do
+ propaccesslist[pap].resolve;
+
+ if ppo_overrides in propoptions then
+ begin
+ overriddenpropsym:=tpropertysym(overriddenpropsymderef.resolve);
+ if ppo_hasparameters in propoptions then
+ parast:=overriddenpropsym.parast.getcopy;
+ end
+ else
+ if ppo_hasparameters in propoptions then
+ tparasymtable(parast).deref
+ end;
+
+
+ function tpropertysym.getsize : asizeint;
+ begin
+ getsize:=0;
+ end;
+
+
+ procedure tpropertysym.ppuwrite(ppufile:tcompilerppufile);
+ var
+ pap : tpropaccesslisttypes;
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putsmallset(propoptions);
+ if ppo_overrides in propoptions then
+ ppufile.putderef(overriddenpropsymderef);
+ ppufile.putderef(propdefderef);
+ ppufile.putlongint(index);
+ ppufile.putlongint(default);
+ ppufile.putderef(indexdefderef);
+ for pap:=low(tpropaccesslisttypes) to high(tpropaccesslisttypes) do
+ ppufile.putpropaccesslist(propaccesslist[pap]);
+ ppufile.writeentry(ibpropertysym);
+ if [ppo_hasparameters,ppo_overrides]*propoptions=[ppo_hasparameters] then
+ tparasymtable(parast).ppuwrite(ppufile);
+ end;
+
+
+{****************************************************************************
+ TABSTRACTVARSYM
+****************************************************************************}
+
+ constructor tabstractvarsym.create(st:tsymtyp;const n : string;vsp:tvarspez;def:tdef;vopts:tvaroptions);
+ begin
+ inherited create(st,n);
+ vardef:=def;
+ varspez:=vsp;
+ varstate:=vs_declared;
+ varoptions:=vopts;
+ end;
+
+
+ constructor tabstractvarsym.ppuload(st:tsymtyp;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(st,ppufile);
+ varstate:=vs_readwritten;
+ varspez:=tvarspez(ppufile.getbyte);
+ varregable:=tvarregable(ppufile.getbyte);
+ addr_taken:=boolean(ppufile.getbyte);
+ ppufile.getderef(vardefderef);
+ ppufile.getsmallset(varoptions);
+ end;
+
+
+ destructor tabstractvarsym.destroy;
+ begin
+ if assigned(notifications) then
+ notifications.destroy;
+ inherited destroy;
+ end;
+
+
+ procedure tabstractvarsym.buildderef;
+ begin
+ vardefderef.build(vardef);
+ end;
+
+
+ procedure tabstractvarsym.deref;
+ var
+ oldvarregable: tvarregable;
+ begin
+ { setting the vardef also updates varregable. We just loaded this }
+ { value from a ppu, so it must not be changed (e.g. tw7817a.pp/ }
+ { tw7817b.pp: the address is taken of a local variable in an }
+ { inlined procedure -> must remain non-regable when inlining) }
+ oldvarregable:=varregable;
+ vardef:=tdef(vardefderef.resolve);
+ varregable:=oldvarregable;
+ end;
+
+
+ procedure tabstractvarsym.ppuwrite(ppufile:tcompilerppufile);
+ var
+ oldintfcrc : boolean;
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putbyte(byte(varspez));
+ oldintfcrc:=ppufile.do_crc;
+ ppufile.do_crc:=false;
+ ppufile.putbyte(byte(varregable));
+ ppufile.putbyte(byte(addr_taken));
+ ppufile.do_crc:=oldintfcrc;
+ ppufile.putderef(vardefderef);
+ ppufile.putsmallset(varoptions);
+ end;
+
+
+ function tabstractvarsym.getsize : asizeint;
+ begin
+ if assigned(vardef) and
+ ((vardef.typ<>arraydef) or
+ is_dynamic_array(vardef) or
+ (tarraydef(vardef).highrange>=tarraydef(vardef).lowrange)) then
+ result:=vardef.size
+ else
+ result:=0;
+ end;
+
+
+ function tabstractvarsym.getpackedbitsize : longint;
+ begin
+ { bitpacking is only done for ordinals }
+ if not is_ordinal(vardef) then
+ internalerror(2006082010);
+ result:=vardef.packedbitsize;
+ end;
+
+
+ function tabstractvarsym.is_regvar(refpara: boolean):boolean;
+ begin
+ { Register variables are not allowed in the following cases:
+ - regvars are disabled
+ - exceptions are used (after an exception is raised the contents of the
+ registers is not valid anymore)
+ - it has a local copy
+ - the value needs to be in memory (i.e. reference counted) }
+ result:=(cs_opt_regvar in current_settings.optimizerswitches) and
+ not(pi_has_assembler_block in current_procinfo.flags) and
+ not(pi_uses_exceptions in current_procinfo.flags) and
+ not(pi_has_interproclabel in current_procinfo.flags) and
+ not(vo_has_local_copy in varoptions) and
+ ((refpara and
+ (varregable <> vr_none)) or
+ (not refpara and
+ not(varregable in [vr_none,vr_addr])))
+{$if not defined(powerpc) and not defined(powerpc64)}
+ and ((vardef.typ <> recorddef) or
+ (varregable = vr_addr) or
+ not(varstate in [vs_written,vs_readwritten]));
+{$endif}
+ end;
+
+
+ procedure tabstractvarsym.trigger_notifications(what:Tnotification_flag);
+
+ var n:Tnotification;
+
+ begin
+ if assigned(notifications) then
+ begin
+ n:=Tnotification(notifications.first);
+ while assigned(n) do
+ begin
+ if what in n.flags then
+ n.callback(what,self);
+ n:=Tnotification(n.next);
+ end;
+ end;
+ end;
+
+ function Tabstractvarsym.register_notification(flags:Tnotification_flags;callback:
+ Tnotification_callback):cardinal;
+
+ var n:Tnotification;
+
+ begin
+ if not assigned(notifications) then
+ notifications:=Tlinkedlist.create;
+ n:=Tnotification.create(flags,callback);
+ register_notification:=n.id;
+ notifications.concat(n);
+ end;
+
+ procedure Tabstractvarsym.unregister_notification(id:cardinal);
+
+ var n:Tnotification;
+
+ begin
+ if not assigned(notifications) then
+ internalerror(200212311)
+ else
+ begin
+ n:=Tnotification(notifications.first);
+ while assigned(n) do
+ begin
+ if n.id=id then
+ begin
+ notifications.remove(n);
+ n.destroy;
+ exit;
+ end;
+ n:=Tnotification(n.next);
+ end;
+ internalerror(200212311)
+ end;
+ end;
+
+ procedure tabstractvarsym.setvardef(def:tdef);
+ begin
+ _vardef := def;
+ { can we load the value into a register ? }
+ if not assigned(owner) or
+ (owner.symtabletype in [localsymtable,parasymtable]) or
+ (
+ (owner.symtabletype=staticsymtable) and
+ not(cs_create_pic in current_settings.moduleswitches)
+ ) then
+ begin
+ if tstoreddef(vardef).is_intregable then
+ varregable:=vr_intreg
+ else
+{ $warning TODO: no fpu regvar in staticsymtable yet, need initialization with 0 }
+ if {(
+ not assigned(owner) or
+ (owner.symtabletype<>staticsymtable)
+ ) and }
+ tstoreddef(vardef).is_fpuregable then
+ begin
+ if use_vectorfpu(vardef) then
+ varregable:=vr_mmreg
+ else
+ varregable:=vr_fpureg;
+ end;
+ end;
+ end;
+
+
+{****************************************************************************
+ TFIELDVARSYM
+****************************************************************************}
+
+ constructor tfieldvarsym.create(const n : string;vsp:tvarspez;def:tdef;vopts:tvaroptions);
+ begin
+ inherited create(fieldvarsym,n,vsp,def,vopts);
+ fieldoffset:=-1;
+ end;
+
+
+ constructor tfieldvarsym.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(fieldvarsym,ppufile);
+ fieldoffset:=ppufile.getaint;
+ end;
+
+
+ procedure tfieldvarsym.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putaint(fieldoffset);
+ ppufile.writeentry(ibfieldvarsym);
+ end;
+
+
+ function tfieldvarsym.mangledname:string;
+ var
+ srsym : tsym;
+ srsymtable : tsymtable;
+ begin
+ if sp_static in symoptions then
+ begin
+ if searchsym(lower(owner.name^)+'_'+name,srsym,srsymtable) then
+ result:=srsym.mangledname
+ { when generating the debug info for the module in which the }
+ { symbol is defined, the localsymtable of that module is }
+ { already popped from the symtablestack }
+ else if searchsym_in_module(current_module,lower(owner.name^)+'_'+name,srsym,srsymtable) then
+ result:=srsym.mangledname
+ else
+ internalerror(2007012501);
+ end
+ else if is_objcclass(tdef(owner.defowner)) then
+ begin
+ if assigned(objcoffsetmangledname) then
+ result:=objcoffsetmangledname^
+ else
+ begin
+ result:=target_info.cprefix+'OBJC_IVAR_$_'+tobjectdef(owner.defowner).objextname^+'.'+RealName;
+ objcoffsetmangledname:=stringdup(result);
+ end;
+ end
+ else
+ result:=inherited mangledname;
+ end;
+
+
+ destructor tfieldvarsym.destroy;
+ begin
+ stringdispose(objcoffsetmangledname);
+ inherited destroy;
+ end;
+
+
+{****************************************************************************
+ TABSTRACTNORMALVARSYM
+****************************************************************************}
+
+ constructor tabstractnormalvarsym.create(st:tsymtyp;const n : string;vsp:tvarspez;def:tdef;vopts:tvaroptions);
+ begin
+ inherited create(st,n,vsp,def,vopts);
+ fillchar(localloc,sizeof(localloc),0);
+ fillchar(initialloc,sizeof(initialloc),0);
+ defaultconstsym:=nil;
+ end;
+
+
+ constructor tabstractnormalvarsym.ppuload(st:tsymtyp;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(st,ppufile);
+ fillchar(localloc,sizeof(localloc),0);
+ fillchar(initialloc,sizeof(initialloc),0);
+ ppufile.getderef(defaultconstsymderef);
+ end;
+
+
+ procedure tabstractnormalvarsym.buildderef;
+ begin
+ inherited buildderef;
+ defaultconstsymderef.build(defaultconstsym);
+ end;
+
+
+ procedure tabstractnormalvarsym.deref;
+ begin
+ inherited deref;
+ defaultconstsym:=tsym(defaultconstsymderef.resolve);
+ end;
+
+
+ procedure tabstractnormalvarsym.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putderef(defaultconstsymderef);
+ end;
+
+
+{****************************************************************************
+ Tstaticvarsym
+****************************************************************************}
+
+ constructor tstaticvarsym.create(const n : string;vsp:tvarspez;def:tdef;vopts:tvaroptions);
+ begin
+ inherited create(staticvarsym,n,vsp,def,vopts);
+ _mangledname:=nil;
+ end;
+
+
+ constructor tstaticvarsym.create_dll(const n : string;vsp:tvarspez;def:tdef);
+ begin
+ tstaticvarsym(self).create(n,vsp,def,[vo_is_dll_var]);
+ end;
+
+
+ constructor tstaticvarsym.create_C(const n,mangled : string;vsp:tvarspez;def:tdef);
+ begin
+ tstaticvarsym(self).create(n,vsp,def,[]);
+ set_mangledname(mangled);
+ end;
+
+
+ constructor tstaticvarsym.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(staticvarsym,ppufile);
+ if vo_has_mangledname in varoptions then
+ _mangledname:=stringdup(ppufile.getstring)
+ else
+ _mangledname:=nil;
+ if vo_has_section in varoptions then
+ section:=ppufile.getansistring;
+ end;
+
+
+ destructor tstaticvarsym.destroy;
+ begin
+ if assigned(_mangledname) then
+ begin
+{$ifdef MEMDEBUG}
+ memmanglednames.start;
+{$endif MEMDEBUG}
+ stringdispose(_mangledname);
+{$ifdef MEMDEBUG}
+ memmanglednames.stop;
+{$endif MEMDEBUG}
+ end;
+ inherited destroy;
+ end;
+
+
+ procedure tstaticvarsym.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ if vo_has_mangledname in varoptions then
+ ppufile.putstring(_mangledname^);
+ if vo_has_section in varoptions then
+ ppufile.putansistring(section);
+ ppufile.writeentry(ibstaticvarsym);
+ end;
+
+
+ function tstaticvarsym.mangledname:string;
+ var
+ prefix : string[2];
+ begin
+ if not assigned(_mangledname) then
+ begin
+ if (vo_is_typed_const in varoptions) then
+ prefix:='TC'
+ else
+ prefix:='U';
+ {$ifdef compress}
+ _mangledname:=stringdup(minilzw_encode(make_mangledname(prefix,owner,name)));
+ {$else}
+ _mangledname:=stringdup(make_mangledname(prefix,owner,name));
+ {$endif}
+ end;
+ result:=_mangledname^;
+ end;
+
+
+ procedure tstaticvarsym.set_mangledname(const s:string);
+ begin
+ stringdispose(_mangledname);
+ {$ifdef compress}
+ _mangledname:=stringdup(minilzw_encode(s));
+ {$else}
+ _mangledname:=stringdup(s);
+ {$endif}
+ include(varoptions,vo_has_mangledname);
+ end;
+
+
+{****************************************************************************
+ TLOCALVARSYM
+****************************************************************************}
+
+ constructor tlocalvarsym.create(const n : string;vsp:tvarspez;def:tdef;vopts:tvaroptions);
+ begin
+ inherited create(localvarsym,n,vsp,def,vopts);
+ end;
+
+
+ constructor tlocalvarsym.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(localvarsym,ppufile);
+ end;
+
+
+ procedure tlocalvarsym.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.writeentry(iblocalvarsym);
+ end;
+
+
+{****************************************************************************
+ TPARAVARSYM
+****************************************************************************}
+
+ constructor tparavarsym.create(const n : string;nr:word;vsp:tvarspez;def:tdef;vopts:tvaroptions);
+ begin
+ inherited create(paravarsym,n,vsp,def,vopts);
+ if (vsp in [vs_var,vs_value,vs_const,vs_constref]) then
+ varstate := vs_initialised;
+ paranr:=nr;
+ paraloc[calleeside].init;
+ paraloc[callerside].init;
+ end;
+
+
+ destructor tparavarsym.destroy;
+ begin
+ paraloc[calleeside].done;
+ paraloc[callerside].done;
+ inherited destroy;
+ end;
+
+
+ constructor tparavarsym.ppuload(ppufile:tcompilerppufile);
+ var
+ b : byte;
+ begin
+ inherited ppuload(paravarsym,ppufile);
+ paranr:=ppufile.getword;
+ univpara:=boolean(ppufile.getbyte);
+
+ { The var state of parameter symbols is fixed after writing them so
+ we write them to the unit file.
+ This enables constant folding for inline procedures loaded from units
+ }
+ varstate:=tvarstate(ppufile.getbyte);
+
+ paraloc[calleeside].init;
+ paraloc[callerside].init;
+ if vo_has_explicit_paraloc in varoptions then
+ begin
+ paraloc[callerside].alignment:=ppufile.getbyte;
+ b:=ppufile.getbyte;
+ if b<>sizeof(paraloc[callerside].location^) then
+ internalerror(200411154);
+ ppufile.getdata(paraloc[callerside].add_location^,sizeof(paraloc[callerside].location^));
+ paraloc[callerside].size:=paraloc[callerside].location^.size;
+ paraloc[callerside].intsize:=tcgsize2size[paraloc[callerside].size];
+ end;
+ end;
+
+
+ procedure tparavarsym.ppuwrite(ppufile:tcompilerppufile);
+ var
+ oldintfcrc : boolean;
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putword(paranr);
+ ppufile.putbyte(byte(univpara));
+
+ { The var state of parameter symbols is fixed after writing them so
+ we write them to the unit file.
+ This enables constant folding for inline procedures loaded from units
+ }
+ oldintfcrc:=ppufile.do_crc;
+ ppufile.do_crc:=false;
+ ppufile.putbyte(ord(varstate));
+ ppufile.do_crc:=oldintfcrc;
+
+ if vo_has_explicit_paraloc in varoptions then
+ begin
+ paraloc[callerside].check_simple_location;
+ ppufile.putbyte(sizeof(paraloc[callerside].alignment));
+ ppufile.putbyte(sizeof(paraloc[callerside].location^));
+ ppufile.putdata(paraloc[callerside].location^,sizeof(paraloc[callerside].location^));
+ end;
+ ppufile.writeentry(ibparavarsym);
+ end;
+
+ function tparavarsym.needs_finalization:boolean;
+ begin
+ result:=(varspez=vs_value) and
+ (is_managed_type(vardef) or
+ (
+ (not (tabstractprocdef(owner.defowner).proccalloption in cdecl_pocalls)) and
+ (not paramanager.use_stackalloc) and
+ (is_open_array(vardef) or is_array_of_const(vardef))
+ )
+ );
+ end;
+
+{****************************************************************************
+ TABSOLUTEVARSYM
+****************************************************************************}
+
+ constructor tabsolutevarsym.create(const n : string;def:tdef);
+ begin
+ inherited create(absolutevarsym,n,vs_value,def,[]);
+ ref:=nil;
+ end;
+
+
+ constructor tabsolutevarsym.create_ref(const n : string;def:tdef;_ref:tpropaccesslist);
+ begin
+ inherited create(absolutevarsym,n,vs_value,def,[]);
+ ref:=_ref;
+ end;
+
+
+ destructor tabsolutevarsym.destroy;
+ begin
+ if assigned(ref) then
+ ref.free;
+ inherited destroy;
+ end;
+
+
+ constructor tabsolutevarsym.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(absolutevarsym,ppufile);
+ ref:=nil;
+ asmname:=nil;
+ abstyp:=absolutetyp(ppufile.getbyte);
+{$ifdef i386}
+ absseg:=false;
+{$endif i386}
+ case abstyp of
+ tovar :
+ ref:=ppufile.getpropaccesslist;
+ toasm :
+ asmname:=stringdup(ppufile.getstring);
+ toaddr :
+ begin
+ addroffset:=ppufile.getaword;
+{$ifdef i386}
+ absseg:=boolean(ppufile.getbyte);
+{$endif i386}
+ end;
+ end;
+ end;
+
+
+ procedure tabsolutevarsym.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putbyte(byte(abstyp));
+ case abstyp of
+ tovar :
+ ppufile.putpropaccesslist(ref);
+ toasm :
+ ppufile.putstring(asmname^);
+ toaddr :
+ begin
+ ppufile.putaword(addroffset);
+{$ifdef i386}
+ ppufile.putbyte(byte(absseg));
+{$endif i386}
+ end;
+ end;
+ ppufile.writeentry(ibabsolutevarsym);
+ end;
+
+
+ procedure tabsolutevarsym.buildderef;
+ begin
+ inherited buildderef;
+ if (abstyp=tovar) then
+ ref.buildderef;
+ end;
+
+
+ procedure tabsolutevarsym.deref;
+ begin
+ inherited deref;
+ { own absolute deref }
+ if (abstyp=tovar) then
+ ref.resolve;
+ end;
+
+
+ function tabsolutevarsym.mangledname : string;
+ begin
+ case abstyp of
+ toasm :
+ mangledname:=asmname^;
+ toaddr :
+ mangledname:='$'+tostr(addroffset);
+ else
+ internalerror(200411062);
+ end;
+ end;
+
+
+{****************************************************************************
+ TCONSTSYM
+****************************************************************************}
+
+ constructor tconstsym.create_ord(const n : string;t : tconsttyp;v : tconstexprint;def:tdef);
+ begin
+ inherited create(constsym,n);
+ fillchar(value, sizeof(value), #0);
+ consttyp:=t;
+ value.valueord:=v;
+ constdef:=def;
+ end;
+
+
+ constructor tconstsym.create_ordptr(const n : string;t : tconsttyp;v : tconstptruint;def:tdef);
+ begin
+ inherited create(constsym,n);
+ fillchar(value, sizeof(value), #0);
+ consttyp:=t;
+ value.valueordptr:=v;
+ constdef:=def;
+ end;
+
+
+ constructor tconstsym.create_ptr(const n : string;t : tconsttyp;v : pointer;def:tdef);
+ begin
+ inherited create(constsym,n);
+ fillchar(value, sizeof(value), #0);
+ consttyp:=t;
+ value.valueptr:=v;
+ constdef:=def;
+ end;
+
+
+ constructor tconstsym.create_string(const n : string;t : tconsttyp;str:pchar;l:longint);
+ begin
+ inherited create(constsym,n);
+ fillchar(value, sizeof(value), #0);
+ consttyp:=t;
+ value.valueptr:=str;
+ constdef:=nil;
+ value.len:=l;
+ end;
+
+
+ constructor tconstsym.create_wstring(const n : string;t : tconsttyp;pw:pcompilerwidestring);
+ begin
+ inherited create(constsym,n);
+ fillchar(value, sizeof(value), #0);
+ consttyp:=t;
+ pcompilerwidestring(value.valueptr):=pw;
+ constdef:=nil;
+ value.len:=getlengthwidestring(pw);
+ end;
+
+
+ constructor tconstsym.ppuload(ppufile:tcompilerppufile);
+ var
+ pd : pbestreal;
+ ps : pnormalset;
+ pc : pchar;
+ pw : pcompilerwidestring;
+ i : longint;
+ begin
+ inherited ppuload(constsym,ppufile);
+ constdef:=nil;
+ consttyp:=tconsttyp(ppufile.getbyte);
+ fillchar(value, sizeof(value), #0);
+ case consttyp of
+ constord :
+ begin
+ ppufile.getderef(constdefderef);
+ value.valueord:=ppufile.getexprint;
+ end;
+ constpointer :
+ begin
+ ppufile.getderef(constdefderef);
+ value.valueordptr:=ppufile.getptruint;
+ end;
+ constwstring :
+ begin
+ initwidestring(pw);
+ setlengthwidestring(pw,ppufile.getlongint);
+ { don't use getdata, because the compilerwidechars may have to
+ be byteswapped
+ }
+{$if sizeof(tcompilerwidechar) = 2}
+ for i:=0 to pw^.len-1 do
+ pw^.data[i]:=ppufile.getword;
+{$elseif sizeof(tcompilerwidechar) = 4}
+ for i:=0 to pw^.len-1 do
+ pw^.data[i]:=cardinal(ppufile.getlongint);
+{$else}
+ {$error Unsupported tcompilerwidechar size}
+{$endif}
+ pcompilerwidestring(value.valueptr):=pw;
+ end;
+ conststring,
+ constresourcestring :
+ begin
+ value.len:=ppufile.getlongint;
+ getmem(pc,value.len+1);
+ ppufile.getdata(pc^,value.len);
+ pc[value.len]:=#0;
+ value.valueptr:=pc;
+ end;
+ constreal :
+ begin
+ new(pd);
+ pd^:=ppufile.getreal;
+ value.valueptr:=pd;
+ end;
+ constset :
+ begin
+ ppufile.getderef(constdefderef);
+ new(ps);
+ ppufile.getnormalset(ps^);
+ value.valueptr:=ps;
+ end;
+ constguid :
+ begin
+ new(pguid(value.valueptr));
+ ppufile.getdata(value.valueptr^,sizeof(tguid));
+ end;
+ constnil : ;
+ else
+ Message1(unit_f_ppu_invalid_entry,tostr(ord(consttyp)));
+ end;
+ end;
+
+
+ destructor tconstsym.destroy;
+ begin
+ case consttyp of
+ conststring,
+ constresourcestring :
+ freemem(pchar(value.valueptr),value.len+1);
+ constwstring :
+ donewidestring(pcompilerwidestring(value.valueptr));
+ constreal :
+ dispose(pbestreal(value.valueptr));
+ constset :
+ dispose(pnormalset(value.valueptr));
+ constguid :
+ dispose(pguid(value.valueptr));
+ end;
+ inherited destroy;
+ end;
+
+
+ procedure tconstsym.buildderef;
+ begin
+ if consttyp in [constord,constpointer,constset] then
+ constdefderef.build(constdef);
+ end;
+
+
+ procedure tconstsym.deref;
+ begin
+ if consttyp in [constord,constpointer,constset] then
+ constdef:=tdef(constdefderef.resolve);
+ end;
+
+
+ procedure tconstsym.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putbyte(byte(consttyp));
+ case consttyp of
+ constnil : ;
+ constord :
+ begin
+ ppufile.putderef(constdefderef);
+ ppufile.putexprint(value.valueord);
+ end;
+ constpointer :
+ begin
+ ppufile.putderef(constdefderef);
+ ppufile.putptruint(value.valueordptr);
+ end;
+ constwstring :
+ begin
+ ppufile.putlongint(getlengthwidestring(pcompilerwidestring(value.valueptr)));
+ ppufile.putdata(pcompilerwidestring(value.valueptr)^.data^,pcompilerwidestring(value.valueptr)^.len*sizeof(tcompilerwidechar));
+ end;
+ conststring,
+ constresourcestring :
+ begin
+ ppufile.putlongint(value.len);
+ ppufile.putdata(pchar(value.valueptr)^,value.len);
+ end;
+ constreal :
+ ppufile.putreal(pbestreal(value.valueptr)^);
+ constset :
+ begin
+ ppufile.putderef(constdefderef);
+ ppufile.putnormalset(value.valueptr^);
+ end;
+ constguid :
+ ppufile.putdata(value.valueptr^,sizeof(tguid));
+ else
+ internalerror(13);
+ end;
+ ppufile.writeentry(ibconstsym);
+ end;
+
+
+{****************************************************************************
+ TENUMSYM
+****************************************************************************}
+
+ constructor tenumsym.create(const n : string;def : tenumdef;v : longint);
+ begin
+ inherited create(enumsym,n);
+ definition:=def;
+ value:=v;
+ end;
+
+
+ constructor tenumsym.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(enumsym,ppufile);
+ ppufile.getderef(definitionderef);
+ value:=ppufile.getlongint;
+ end;
+
+
+ procedure tenumsym.buildderef;
+ begin
+ definitionderef.build(definition);
+ end;
+
+
+ procedure tenumsym.deref;
+ begin
+ definition:=tenumdef(definitionderef.resolve);
+ end;
+
+ procedure tenumsym.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putderef(definitionderef);
+ ppufile.putlongint(value);
+ ppufile.writeentry(ibenumsym);
+ end;
+
+
+{****************************************************************************
+ TTYPESYM
+****************************************************************************}
+
+ constructor ttypesym.create(const n : string;def:tdef);
+
+ begin
+ inherited create(typesym,n);
+ typedef:=def;
+ { register the typesym for the definition }
+ if assigned(typedef) and
+ (typedef.typ<>errordef) and
+ not(assigned(typedef.typesym)) then
+ typedef.typesym:=self;
+ end;
+
+
+ constructor ttypesym.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(typesym,ppufile);
+ ppufile.getderef(typedefderef);
+ fprettyname:=ppufile.getansistring;
+ end;
+
+
+ procedure ttypesym.buildderef;
+ begin
+ typedefderef.build(typedef);
+ end;
+
+
+ procedure ttypesym.deref;
+ begin
+ typedef:=tdef(typedefderef.resolve);
+ end;
+
+
+ procedure ttypesym.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putderef(typedefderef);
+ ppufile.putansistring(fprettyname);
+ ppufile.writeentry(ibtypesym);
+ end;
+
+
+ function ttypesym.prettyname : string;
+ begin
+ if fprettyname<>'' then
+ result:=fprettyname
+ else
+ result:=inherited prettyname;
+ end;
+
+
+{****************************************************************************
+ TSYSSYM
+****************************************************************************}
+
+ constructor tsyssym.create(const n : string;l : longint);
+ begin
+ inherited create(syssym,n);
+ number:=l;
+ end;
+
+ constructor tsyssym.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(syssym,ppufile);
+ number:=ppufile.getlongint;
+ end;
+
+ destructor tsyssym.destroy;
+ begin
+ inherited destroy;
+ end;
+
+ procedure tsyssym.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putlongint(number);
+ ppufile.writeentry(ibsyssym);
+ end;
+
+
+{*****************************************************************************
+ TMacro
+*****************************************************************************}
+
+ constructor tmacro.create(const n : string);
+ begin
+ inherited create(macrosym,n);
+ owner:=nil;
+ defined:=false;
+ is_used:=false;
+ is_compiler_var:=false;
+ buftext:=nil;
+ buflen:=0;
+ end;
+
+ constructor tmacro.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(macrosym,ppufile);
+ defined:=boolean(ppufile.getbyte);
+ is_compiler_var:=boolean(ppufile.getbyte);
+ is_used:=false;
+ buflen:= ppufile.getlongint;
+ if buflen > 0 then
+ begin
+ getmem(buftext, buflen);
+ ppufile.getdata(buftext^, buflen)
+ end
+ else
+ buftext:=nil;
+ end;
+
+ destructor tmacro.destroy;
+ begin
+ if assigned(buftext) then
+ freemem(buftext);
+ inherited destroy;
+ end;
+
+ procedure tmacro.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putbyte(byte(defined));
+ ppufile.putbyte(byte(is_compiler_var));
+ ppufile.putlongint(buflen);
+ if buflen > 0 then
+ ppufile.putdata(buftext^,buflen);
+ ppufile.writeentry(ibmacrosym);
+ end;
+
+
+ function tmacro.GetCopy:tmacro;
+ var
+ p : tmacro;
+ begin
+ p:=tmacro.create(realname);
+ p.defined:=defined;
+ p.is_used:=is_used;
+ p.is_compiler_var:=is_compiler_var;
+ p.buflen:=buflen;
+ if assigned(buftext) then
+ begin
+ getmem(p.buftext,buflen);
+ move(buftext^,p.buftext^,buflen);
+ end;
+ Result:=p;
+ end;
+
+end.
diff --git a/closures/compiler/symtable.pas b/closures/compiler/symtable.pas
new file mode 100644
index 0000000000..9f382ae279
--- /dev/null
+++ b/closures/compiler/symtable.pas
@@ -0,0 +1,3217 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl, Pierre Muller
+
+ This unit handles the symbol tables
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ ****************************************************************************
+}
+unit symtable;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ { common }
+ cutils,cclasses,
+ { global }
+ cpuinfo,globtype,tokens,
+ { symtable }
+ symconst,symbase,symtype,symdef,symsym,
+ { ppu }
+ ppu,
+ { assembler }
+ aasmtai,aasmdata
+ ;
+
+
+{****************************************************************************
+ Symtable types
+****************************************************************************}
+
+ type
+ tstoredsymtable = class(TSymtable)
+ private
+ b_needs_init_final : boolean;
+ procedure _needs_init_final(sym:TObject;arg:pointer);
+ procedure check_forward(sym:TObject;arg:pointer);
+ procedure labeldefined(sym:TObject;arg:pointer);
+ procedure varsymbolused(sym:TObject;arg:pointer);
+ procedure TestPrivate(sym:TObject;arg:pointer);
+ procedure objectprivatesymbolused(sym:TObject;arg:pointer);
+ procedure loaddefs(ppufile:tcompilerppufile);
+ procedure loadsyms(ppufile:tcompilerppufile);
+ procedure writedefs(ppufile:tcompilerppufile);
+ procedure writesyms(ppufile:tcompilerppufile);
+ public
+ procedure insert(sym:TSymEntry;checkdup:boolean=true);override;
+ procedure delete(sym:TSymEntry);override;
+ { load/write }
+ procedure ppuload(ppufile:tcompilerppufile);virtual;
+ procedure ppuwrite(ppufile:tcompilerppufile);virtual;
+ procedure buildderef;virtual;
+ procedure buildderefimpl;virtual;
+ procedure deref;virtual;
+ procedure derefimpl;virtual;
+ function checkduplicate(var hashedid:THashedIDString;sym:TSymEntry):boolean;override;
+ procedure allsymbolsused;
+ procedure allprivatesused;
+ procedure check_forwards;
+ procedure checklabels;
+ function needs_init_final : boolean;
+ procedure testfordefaultproperty(sym:TObject;arg:pointer);
+ end;
+
+ tabstractrecordsymtable = class(tstoredsymtable)
+ public
+ usefieldalignment, { alignment to use for fields (PACKRECORDS value), C_alignment is C style }
+ recordalignment, { alignment desired when inserting this record }
+ fieldalignment, { alignment current alignment used when fields are inserted }
+ padalignment : shortint; { size to a multiple of which the symtable has to be rounded up }
+ constructor create(const n:string;usealign:shortint);
+ procedure ppuload(ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure alignrecord(fieldoffset:asizeint;varalign:shortint);
+ procedure addfield(sym:tfieldvarsym;vis:tvisibility);
+ procedure addalignmentpadding;
+ procedure insertdef(def:TDefEntry);override;
+ function is_packed: boolean;
+ function has_single_field(out sym:tfieldvarsym): boolean;
+ function get_unit_symtable: tsymtable;
+ protected
+ { size in bytes including padding }
+ _datasize : asizeint;
+ { size in bits of the data in case of bitpacked record. Only important during construction, }
+ { no need to save in/restore from ppu file. datasize is always (databitsize+7) div 8. }
+ databitsize : asizeint;
+ { size in bytes of padding }
+ _paddingsize : word;
+ procedure setdatasize(val: asizeint);
+ public
+ function iscurrentunit: boolean; override;
+ property datasize : asizeint read _datasize write setdatasize;
+ property paddingsize: word read _paddingsize write _paddingsize;
+ end;
+
+ trecordsymtable = class(tabstractrecordsymtable)
+ public
+ constructor create(const n:string;usealign:shortint);
+ procedure insertunionst(unionst : trecordsymtable;offset : longint);
+ end;
+
+ tObjectSymtable = class(tabstractrecordsymtable)
+ public
+ constructor create(adefowner:tdef;const n:string;usealign:shortint);
+ function checkduplicate(var hashedid:THashedIDString;sym:TSymEntry):boolean;override;
+ end;
+
+ { tabstractlocalsymtable }
+
+ tabstractlocalsymtable = class(tstoredsymtable)
+ public
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ function count_locals:longint;
+ end;
+
+ tlocalsymtable = class(tabstractlocalsymtable)
+ public
+ constructor create(adefowner:tdef;level:byte);
+ function checkduplicate(var hashedid:THashedIDString;sym:TSymEntry):boolean;override;
+ end;
+
+ { tparasymtable }
+
+ tparasymtable = class(tabstractlocalsymtable)
+ public
+ readonly: boolean;
+ constructor create(adefowner:tdef;level:byte);
+ function checkduplicate(var hashedid:THashedIDString;sym:TSymEntry):boolean;override;
+ procedure insertdef(def:TDefEntry);override;
+ end;
+
+ tabstractuniTSymtable = class(tstoredsymtable)
+ public
+ constructor create(const n : string;id:word);
+ function checkduplicate(var hashedid:THashedIDString;sym:TSymEntry):boolean;override;
+ function iscurrentunit:boolean;override;
+ procedure insertunit(sym:TSymEntry);
+ end;
+
+ tglobalsymtable = class(tabstractuniTSymtable)
+ public
+ unittypecount : word;
+ constructor create(const n : string;id:word);
+ procedure ppuload(ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ end;
+
+ tstaticsymtable = class(tabstractuniTSymtable)
+ public
+ constructor create(const n : string;id:word);
+ procedure ppuload(ppufile:tcompilerppufile);override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ function checkduplicate(var hashedid:THashedIDString;sym:TSymEntry):boolean;override;
+ end;
+
+ tspecializesymtable = class(tglobalsymtable)
+ public
+ function iscurrentunit:boolean;override;
+ end;
+
+ twithsymtable = class(TSymtable)
+ withrefnode : tobject; { tnode }
+ constructor create(aowner:tdef;ASymList:TFPHashObjectList;refnode:tobject{tnode});
+ destructor destroy;override;
+ procedure clear;override;
+ procedure insertdef(def:TDefEntry);override;
+ end;
+
+ tstt_excepTSymtable = class(TSymtable)
+ public
+ constructor create;
+ end;
+
+ tmacrosymtable = class(tstoredsymtable)
+ public
+ constructor create(exported: boolean);
+ end;
+
+ { tenumsymtable }
+
+ tenumsymtable = class(tstoredsymtable)
+ public
+ procedure insert(sym: TSymEntry; checkdup: boolean = true); override;
+ constructor create(adefowner:tdef);
+ end;
+
+ { tarraysymtable }
+
+ tarraysymtable = class(tstoredsymtable)
+ public
+ procedure insertdef(def:TDefEntry);override;
+ constructor create(adefowner:tdef);
+ end;
+
+ var
+ systemunit : tglobalsymtable; { pointer to the system unit }
+
+
+{****************************************************************************
+ Functions
+****************************************************************************}
+
+{*** Misc ***}
+ function FullTypeName(def,otherdef:tdef):string;
+ function generate_nested_name(symtable:tsymtable;delimiter:string):string;
+ procedure incompatibletypes(def1,def2:tdef);
+ procedure hidesym(sym:TSymEntry);
+ procedure duplicatesym(var hashedid:THashedIDString;dupsym,origsym:TSymEntry);
+ function handle_generic_dummysym(sym:TSymEntry;var symoptions:tsymoptions):boolean;
+
+{*** Search ***}
+ procedure addsymref(sym:tsym);
+ function is_owned_by(childdef,ownerdef:tdef):boolean;
+ function sym_is_owned_by(childsym:tsym;symtable:tsymtable):boolean;
+ function is_visible_for_object(symst:tsymtable;symvisibility:tvisibility;contextobjdef:tabstractrecorddef):boolean;
+ function is_visible_for_object(pd:tprocdef;contextobjdef:tabstractrecorddef):boolean;
+ function is_visible_for_object(sym:tsym;contextobjdef:tabstractrecorddef):boolean;
+ function searchsym(const s : TIDString;out srsym:tsym;out srsymtable:TSymtable):boolean;
+ function searchsym_maybe_with_symoption(const s : TIDString;out srsym:tsym;out srsymtable:TSymtable;searchoption:boolean;option:tsymoption):boolean;
+ { searches for a symbol with the given name that has the given option in
+ symoptions set }
+ function searchsym_with_symoption(const s : TIDString;out srsym:tsym;out srsymtable:TSymtable;option:tsymoption):boolean;
+ function searchsym_type(const s : TIDString;out srsym:tsym;out srsymtable:TSymtable):boolean;
+ function searchsym_in_module(pm:pointer;const s : TIDString;out srsym:tsym;out srsymtable:TSymtable):boolean;
+ function searchsym_in_named_module(const unitname, symname: TIDString; out srsym: tsym; out srsymtable: tsymtable): boolean;
+ function searchsym_in_class(classh,contextclassh:tobjectdef;const s : TIDString;out srsym:tsym;out srsymtable:TSymtable;searchhelper:boolean):boolean;
+ function searchsym_in_record(recordh:tabstractrecorddef;const s : TIDString;out srsym:tsym;out srsymtable:TSymtable):boolean;
+ function searchsym_in_class_by_msgint(classh:tobjectdef;msgid:longint;out srdef : tdef;out srsym:tsym;out srsymtable:TSymtable):boolean;
+ function searchsym_in_class_by_msgstr(classh:tobjectdef;const s:string;out srsym:tsym;out srsymtable:TSymtable):boolean;
+ { searches symbols inside of a helper's implementation }
+ function searchsym_in_helper(classh,contextclassh:tobjectdef;const s: TIDString;out srsym:tsym;out srsymtable:TSymtable;aHasInherited:boolean):boolean;
+ function search_system_type(const s: TIDString): ttypesym;
+ function try_search_system_type(const s: TIDString): ttypesym;
+ function search_named_unit_globaltype(const unitname, typename: TIDString; throwerror: boolean): ttypesym;
+ function search_struct_member(pd : tabstractrecorddef;const s : string):tsym;
+ function search_assignment_operator(from_def,to_def:Tdef;explicit:boolean):Tprocdef;
+ function search_enumerator_operator(from_def,to_def:Tdef):Tprocdef;
+ { searches for the helper definition that's currently active for pd }
+ function search_last_objectpascal_helper(pd,contextclassh : tabstractrecorddef;out odef : tobjectdef):boolean;
+ { searches whether the symbol s is available in the currently active }
+ { helper for pd }
+ function search_objectpascal_helper(pd,contextclassh : tabstractrecorddef;const s : string; out srsym: tsym; out srsymtable: tsymtable):boolean;
+ function search_objc_helper(pd : tobjectdef;const s : string; out srsym: tsym; out srsymtable: tsymtable):boolean;
+ function search_objc_method(const s : string; out srsym: tsym; out srsymtable: tsymtable):boolean;
+ {Looks for macro s (must be given in upper case) in the macrosymbolstack, }
+ {and returns it if found. Returns nil otherwise.}
+ function search_macro(const s : string):tsym;
+ { Additionally to searching for a macro, also checks whether it's still }
+ { actually defined (could be disable using "undef") }
+ function defined_macro(const s : string):boolean;
+
+{*** Object Helpers ***}
+ function search_default_property(pd : tabstractrecorddef) : tpropertysym;
+ function find_real_objcclass_definition(pd: tobjectdef; erroronfailure: boolean): tobjectdef;
+
+{*** Macro Helpers ***}
+ {If called initially, the following procedures manipulate macros in }
+ {initialmacrotable, otherwise they manipulate system macros local to a module.}
+ {Name can be given in any case (it will be converted to upper case).}
+ procedure def_system_macro(const name : string);
+ procedure set_system_macro(const name, value : string);
+ procedure set_system_compvar(const name, value : string);
+ procedure undef_system_macro(const name : string);
+
+{*** symtable stack ***}
+{ $ifdef DEBUG
+ procedure test_symtablestack;
+ procedure list_symtablestack;
+ $endif DEBUG}
+
+{$ifdef UNITALIASES}
+ type
+ punit_alias = ^tunit_alias;
+ tunit_alias = object(TNamedIndexItem)
+ newname : pshortstring;
+ constructor init(const n:string);
+ destructor done;virtual;
+ end;
+ var
+ unitaliases : pdictionary;
+
+ procedure addunitalias(const n:string);
+ function getunitalias(const n:string):string;
+{$endif UNITALIASES}
+
+{*** Init / Done ***}
+ procedure IniTSymtable;
+ procedure DoneSymtable;
+
+ const
+ overloaded_names : array [NOTOKEN..last_overloaded] of string[16] = (
+ { NOTOKEN } 'error',
+ { _PLUS } 'plus',
+ { _MINUS } 'minus',
+ { _STAR } 'star',
+ { _SLASH } 'slash',
+ { _EQ } 'equal',
+ { _GT } 'greater',
+ { _LT } 'lower',
+ { _GTE } 'greater_or_equal',
+ { _LTE } 'lower_or_equal',
+ { _NE } 'not_equal',
+ { _SYMDIF } 'sym_diff',
+ { _STARSTAR } 'starstar',
+ { _OP_AS } 'as',
+ { _OP_IN } 'in',
+ { _OP_IS } 'is',
+ { _OP_OR } 'or',
+ { _OP_AND } 'and',
+ { _OP_DIV } 'div',
+ { _OP_MOD } 'mod',
+ { _OP_NOT } 'not',
+ { _OP_SHL } 'shl',
+ { _OP_SHR } 'shr',
+ { _OP_XOR } 'xor',
+ { _ASSIGNMENT } 'assign',
+ { _OP_EXPLICIT } 'explicit',
+ { _OP_ENUMERATOR } 'enumerator',
+ { _OP_INC } 'inc',
+ { _OP_DEC } 'dec');
+
+
+
+implementation
+
+ uses
+ { global }
+ verbose,globals,
+ { target }
+ systems,
+ { symtable }
+ symutil,defcmp,defutil,
+ { module }
+ fmodule,
+ { codegen }
+ procinfo
+ ;
+
+
+ var
+ dupnr : longint; { unique number for duplicate symbols }
+
+{*****************************************************************************
+ TStoredSymtable
+*****************************************************************************}
+
+ procedure tstoredsymtable.insert(sym:TSymEntry;checkdup:boolean=true);
+ begin
+ inherited insert(sym,checkdup);
+ end;
+
+
+ procedure tstoredsymtable.delete(sym:TSymEntry);
+ begin
+ inherited delete(sym);
+ end;
+
+
+ procedure tstoredsymtable.ppuload(ppufile:tcompilerppufile);
+ begin
+ { load the table's flags }
+ if ppufile.readentry<>ibsymtableoptions then
+ Message(unit_f_ppu_read_error);
+ ppufile.getsmallset(tableoptions);
+
+ { load definitions }
+ loaddefs(ppufile);
+
+ { load symbols }
+ loadsyms(ppufile);
+ end;
+
+
+ procedure tstoredsymtable.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ { write the table's flags }
+ ppufile.putsmallset(tableoptions);
+ ppufile.writeentry(ibsymtableoptions);
+
+ { write definitions }
+ writedefs(ppufile);
+
+ { write symbols }
+ writesyms(ppufile);
+ end;
+
+
+ procedure tstoredsymtable.loaddefs(ppufile:tcompilerppufile);
+ var
+ def : tdef;
+ b : byte;
+ begin
+ { load start of definition section, which holds the amount of defs }
+ if ppufile.readentry<>ibstartdefs then
+ Message(unit_f_ppu_read_error);
+ { read definitions }
+ repeat
+ b:=ppufile.readentry;
+ case b of
+ ibpointerdef : def:=tpointerdef.ppuload(ppufile);
+ ibarraydef : def:=tarraydef.ppuload(ppufile);
+ iborddef : def:=torddef.ppuload(ppufile);
+ ibfloatdef : def:=tfloatdef.ppuload(ppufile);
+ ibprocdef : def:=tprocdef.ppuload(ppufile);
+ ibshortstringdef : def:=tstringdef.loadshort(ppufile);
+ iblongstringdef : def:=tstringdef.loadlong(ppufile);
+ ibansistringdef : def:=tstringdef.loadansi(ppufile);
+ ibwidestringdef : def:=tstringdef.loadwide(ppufile);
+ ibunicodestringdef : def:=tstringdef.loadunicode(ppufile);
+ ibrecorddef : def:=trecorddef.ppuload(ppufile);
+ ibobjectdef : def:=tobjectdef.ppuload(ppufile);
+ ibenumdef : def:=tenumdef.ppuload(ppufile);
+ ibsetdef : def:=tsetdef.ppuload(ppufile);
+ ibprocvardef : def:=tprocvardef.ppuload(ppufile);
+ ibfiledef : def:=tfiledef.ppuload(ppufile);
+ ibclassrefdef : def:=tclassrefdef.ppuload(ppufile);
+ ibformaldef : def:=tformaldef.ppuload(ppufile);
+ ibvariantdef : def:=tvariantdef.ppuload(ppufile);
+ ibundefineddef : def:=tundefineddef.ppuload(ppufile);
+ ibenddefs : break;
+ ibend : Message(unit_f_ppu_read_error);
+ else
+ Message1(unit_f_ppu_invalid_entry,tostr(b));
+ end;
+ InsertDef(def);
+ until false;
+ end;
+
+
+ procedure tstoredsymtable.loadsyms(ppufile:tcompilerppufile);
+ var
+ b : byte;
+ sym : tsym;
+ begin
+ { load start of definition section, which holds the amount of defs }
+ if ppufile.readentry<>ibstartsyms then
+ Message(unit_f_ppu_read_error);
+ { now read the symbols }
+ repeat
+ b:=ppufile.readentry;
+ case b of
+ ibtypesym : sym:=ttypesym.ppuload(ppufile);
+ ibprocsym : sym:=tprocsym.ppuload(ppufile);
+ ibconstsym : sym:=tconstsym.ppuload(ppufile);
+ ibstaticvarsym : sym:=tstaticvarsym.ppuload(ppufile);
+ iblocalvarsym : sym:=tlocalvarsym.ppuload(ppufile);
+ ibparavarsym : sym:=tparavarsym.ppuload(ppufile);
+ ibfieldvarsym : sym:=tfieldvarsym.ppuload(ppufile);
+ ibabsolutevarsym : sym:=tabsolutevarsym.ppuload(ppufile);
+ ibenumsym : sym:=tenumsym.ppuload(ppufile);
+ ibpropertysym : sym:=tpropertysym.ppuload(ppufile);
+ ibunitsym : sym:=tunitsym.ppuload(ppufile);
+ iblabelsym : sym:=tlabelsym.ppuload(ppufile);
+ ibsyssym : sym:=tsyssym.ppuload(ppufile);
+ ibmacrosym : sym:=tmacro.ppuload(ppufile);
+ ibnamespacesym : sym:=tnamespacesym.ppuload(ppufile);
+ ibendsyms : break;
+ ibend : Message(unit_f_ppu_read_error);
+ else
+ Message1(unit_f_ppu_invalid_entry,tostr(b));
+ end;
+ Insert(sym,false);
+ until false;
+ end;
+
+
+ procedure tstoredsymtable.writedefs(ppufile:tcompilerppufile);
+ var
+ i : longint;
+ def : tstoreddef;
+ begin
+ { each definition get a number, write then the amount of defs to the
+ ibstartdef entry }
+ ppufile.putlongint(DefList.count);
+ ppufile.writeentry(ibstartdefs);
+ { now write the definition }
+ for i:=0 to DefList.Count-1 do
+ begin
+ def:=tstoreddef(DefList[i]);
+ def.ppuwrite(ppufile);
+ end;
+ { write end of definitions }
+ ppufile.writeentry(ibenddefs);
+ end;
+
+
+ procedure tstoredsymtable.writesyms(ppufile:tcompilerppufile);
+ var
+ i : longint;
+ sym : Tstoredsym;
+ begin
+ { each definition get a number, write then the amount of syms and the
+ datasize to the ibsymdef entry }
+ ppufile.putlongint(SymList.count);
+ ppufile.writeentry(ibstartsyms);
+ { foreach is used to write all symbols }
+ for i:=0 to SymList.Count-1 do
+ begin
+ sym:=tstoredsym(SymList[i]);
+ sym.ppuwrite(ppufile);
+ end;
+ { end of symbols }
+ ppufile.writeentry(ibendsyms);
+ end;
+
+
+ procedure tstoredsymtable.buildderef;
+ var
+ i : longint;
+ def : tstoreddef;
+ sym : tstoredsym;
+ begin
+ { interface definitions }
+ for i:=0 to DefList.Count-1 do
+ begin
+ def:=tstoreddef(DefList[i]);
+ def.buildderef;
+ end;
+ { interface symbols }
+ for i:=0 to SymList.Count-1 do
+ begin
+ sym:=tstoredsym(SymList[i]);
+ sym.buildderef;
+ end;
+ end;
+
+
+ procedure tstoredsymtable.buildderefimpl;
+ var
+ i : longint;
+ def : tstoreddef;
+ begin
+ { implementation definitions }
+ for i:=0 to DefList.Count-1 do
+ begin
+ def:=tstoreddef(DefList[i]);
+ def.buildderefimpl;
+ end;
+ end;
+
+
+ procedure tstoredsymtable.deref;
+ var
+ i : longint;
+ def : tstoreddef;
+ sym : tstoredsym;
+ begin
+ { first deref the interface ttype symbols. This is needs
+ to be done before the interface defs are derefed, because
+ the interface defs can contain references to the type symbols
+ which then already need to contain a resolved typedef field (PFV) }
+ for i:=0 to SymList.Count-1 do
+ begin
+ sym:=tstoredsym(SymList[i]);
+ if sym.typ=typesym then
+ sym.deref;
+ end;
+ { interface definitions }
+ for i:=0 to DefList.Count-1 do
+ begin
+ def:=tstoreddef(DefList[i]);
+ def.deref;
+ end;
+ { interface symbols }
+ for i:=0 to SymList.Count-1 do
+ begin
+ sym:=tstoredsym(SymList[i]);
+ if sym.typ<>typesym then
+ sym.deref;
+ end;
+ end;
+
+
+ procedure tstoredsymtable.derefimpl;
+ var
+ i : longint;
+ def : tstoreddef;
+ begin
+ { implementation definitions }
+ for i:=0 to DefList.Count-1 do
+ begin
+ def:=tstoreddef(DefList[i]);
+ def.derefimpl;
+ end;
+ end;
+
+
+ function tstoredsymtable.checkduplicate(var hashedid:THashedIDString;sym:TSymEntry):boolean;
+ var
+ hsym : tsym;
+ begin
+ hsym:=tsym(FindWithHash(hashedid));
+ if assigned(hsym) then
+ DuplicateSym(hashedid,sym,hsym);
+ result:=assigned(hsym);
+ end;
+
+
+{**************************************
+ Callbacks
+**************************************}
+
+ procedure TStoredSymtable.check_forward(sym:TObject;arg:pointer);
+ begin
+ if tsym(sym).typ=procsym then
+ tprocsym(sym).check_forward
+ { check also object method table }
+ { we needn't to test the def list }
+ { because each object has to have a type sym,
+ only test objects declarations, not type renamings }
+ else
+ if (tsym(sym).typ=typesym) and
+ assigned(ttypesym(sym).typedef) and
+ (ttypesym(sym).typedef.typesym=ttypesym(sym)) and
+ (ttypesym(sym).typedef.typ in [objectdef,recorddef]) then
+ tabstractrecorddef(ttypesym(sym).typedef).check_forwards;
+ end;
+
+
+ procedure TStoredSymtable.labeldefined(sym:TObject;arg:pointer);
+ begin
+ if (tsym(sym).typ=labelsym) and
+ not(tlabelsym(sym).defined) then
+ begin
+ if tlabelsym(sym).used then
+ Message1(sym_e_label_used_and_not_defined,tlabelsym(sym).realname)
+ else
+ Message1(sym_w_label_not_defined,tlabelsym(sym).realname);
+ end;
+ end;
+
+
+ procedure TStoredSymtable.varsymbolused(sym:TObject;arg:pointer);
+ begin
+ if (tsym(sym).typ in [staticvarsym,localvarsym,paravarsym,fieldvarsym]) and
+ ((tsym(sym).owner.symtabletype in
+ [parasymtable,localsymtable,ObjectSymtable,recordsymtable,staticsymtable])) then
+ begin
+ { unused symbol should be reported only if no }
+ { error is reported }
+ { if the symbol is in a register it is used }
+ { also don't count the value parameters which have local copies }
+ { also don't claim for high param of open parameters (PM) }
+ { also don't complain about unused symbols in generic procedures }
+ { and methods }
+ if (Errorcount<>0) or
+ ([vo_is_hidden_para,vo_is_funcret] * tabstractvarsym(sym).varoptions = [vo_is_hidden_para]) or
+ (sp_internal in tsym(sym).symoptions) or
+ ((assigned(tsym(sym).owner.defowner) and
+ (tsym(sym).owner.defowner.typ=procdef) and
+ (df_generic in tprocdef(tsym(sym).owner.defowner).defoptions))) then
+ exit;
+ if (tstoredsym(sym).refs=0) then
+ begin
+ if (vo_is_funcret in tabstractvarsym(sym).varoptions) then
+ begin
+ { don't warn about the result of constructors }
+ if ((tsym(sym).owner.symtabletype<>localsymtable) or
+ (tprocdef(tsym(sym).owner.defowner).proctypeoption<>potype_constructor)) and
+ not(cs_opt_nodedfa in current_settings.optimizerswitches) then
+ MessagePos(tsym(sym).fileinfo,sym_w_function_result_not_set)
+ end
+ else if (tsym(sym).owner.symtabletype=parasymtable) then
+ MessagePos1(tsym(sym).fileinfo,sym_h_para_identifier_not_used,tsym(sym).prettyname)
+ else if (tsym(sym).owner.symtabletype in [ObjectSymtable,recordsymtable]) then
+ MessagePos2(tsym(sym).fileinfo,sym_n_private_identifier_not_used,tabstractrecorddef(tsym(sym).owner.defowner).GetTypeName,tsym(sym).prettyname)
+ else
+ MessagePos1(tsym(sym).fileinfo,sym_n_local_identifier_not_used,tsym(sym).prettyname);
+ end
+ else if tabstractvarsym(sym).varstate in [vs_written,vs_initialised] then
+ begin
+ if (tsym(sym).owner.symtabletype=parasymtable) then
+ begin
+ if not(tabstractvarsym(sym).varspez in [vs_var,vs_out,vs_constref]) and
+ not(vo_is_funcret in tabstractvarsym(sym).varoptions) then
+ MessagePos1(tsym(sym).fileinfo,sym_h_para_identifier_only_set,tsym(sym).prettyname)
+ end
+ else if (tsym(sym).owner.symtabletype in [ObjectSymtable,recordsymtable]) then
+ MessagePos2(tsym(sym).fileinfo,sym_n_private_identifier_only_set,tabstractrecorddef(tsym(sym).owner.defowner).GetTypeName,tsym(sym).prettyname)
+ else if tabstractvarsym(sym).varoptions*[vo_is_funcret,vo_is_public,vo_is_external]=[] then
+ MessagePos1(tsym(sym).fileinfo,sym_n_local_identifier_only_set,tsym(sym).prettyname);
+ end
+ else if (tabstractvarsym(sym).varstate = vs_read_not_warned) and
+ ([vo_is_public,vo_is_external] * tabstractvarsym(sym).varoptions = []) then
+ MessagePos1(tsym(sym).fileinfo,sym_w_identifier_only_read,tsym(sym).prettyname)
+ end
+ else if ((tsym(sym).owner.symtabletype in
+ [ObjectSymtable,parasymtable,localsymtable,staticsymtable,recordsymtable])) then
+ begin
+ if (Errorcount<>0) or
+ (sp_internal in tsym(sym).symoptions) then
+ exit;
+ { do not claim for inherited private fields !! }
+ if (tsym(sym).refs=0) and (tsym(sym).owner.symtabletype in [ObjectSymtable,recordsymtable]) then
+ case tsym(sym).typ of
+ typesym:
+ MessagePos2(tsym(sym).fileinfo,sym_n_private_type_not_used,tabstractrecorddef(tsym(sym).owner.defowner).GetTypeName,tsym(sym).prettyname);
+ constsym:
+ MessagePos2(tsym(sym).fileinfo,sym_n_private_const_not_used,tabstractrecorddef(tsym(sym).owner.defowner).GetTypeName,tsym(sym).prettyname);
+ propertysym:
+ MessagePos2(tsym(sym).fileinfo,sym_n_private_property_not_used,tabstractrecorddef(tsym(sym).owner.defowner).GetTypeName,tsym(sym).prettyname);
+ else
+ MessagePos2(tsym(sym).fileinfo,sym_n_private_method_not_used,tabstractrecorddef(tsym(sym).owner.defowner).GetTypeName,tsym(sym).prettyname);
+ end
+ { units references are problematic }
+ else
+ begin
+ if (tsym(sym).refs=0) and
+ not(tsym(sym).typ in [enumsym,unitsym,namespacesym]) and
+ not(is_funcret_sym(tsym(sym))) and
+ { don't complain about compiler generated syms for specializations, see also #13405 }
+ not((tsym(sym).typ=typesym) and (df_specialization in ttypesym(sym).typedef.defoptions) and
+ (pos('$',ttypesym(sym).Realname)<>0)) and
+ (
+ (tsym(sym).typ<>procsym) or
+ ((tsym(sym).owner.symtabletype=staticsymtable) and
+ not current_module.is_unit)
+ ) and
+ { don't complain about alias for hidden _cmd parameter to
+ obj-c methods }
+ not((tsym(sym).typ in [localvarsym,paravarsym,absolutevarsym]) and
+ (vo_is_msgsel in tabstractvarsym(sym).varoptions)) then
+ MessagePos2(tsym(sym).fileinfo,sym_h_local_symbol_not_used,SymTypeName[tsym(sym).typ],tsym(sym).prettyname);
+ end;
+ end;
+ end;
+
+
+ procedure TStoredSymtable.TestPrivate(sym:TObject;arg:pointer);
+ begin
+ if tsym(sym).visibility in [vis_private,vis_strictprivate] then
+ varsymbolused(sym,arg);
+ end;
+
+
+ procedure TStoredSymtable.objectprivatesymbolused(sym:TObject;arg:pointer);
+ begin
+ {
+ Don't test simple object aliases PM
+ }
+ if (tsym(sym).typ=typesym) and
+ (ttypesym(sym).typedef.typ in [objectdef,recorddef]) and
+ (ttypesym(sym).typedef.typesym=tsym(sym)) then
+ tabstractrecorddef(ttypesym(sym).typedef).symtable.SymList.ForEachCall(@TestPrivate,nil);
+ end;
+
+
+ procedure tstoredsymtable.testfordefaultproperty(sym:TObject;arg:pointer);
+ begin
+ if (tsym(sym).typ=propertysym) and
+ (ppo_defaultproperty in tpropertysym(sym).propoptions) then
+ ppointer(arg)^:=sym;
+ end;
+
+
+{***********************************************
+ Process all entries
+***********************************************}
+
+ { checks, if all procsyms and methods are defined }
+ procedure tstoredsymtable.check_forwards;
+ begin
+ SymList.ForEachCall(@check_forward,nil);
+ end;
+
+
+ procedure tstoredsymtable.checklabels;
+ begin
+ SymList.ForEachCall(@labeldefined,nil);
+ end;
+
+
+ procedure tstoredsymtable.allsymbolsused;
+ begin
+ SymList.ForEachCall(@varsymbolused,nil);
+ end;
+
+
+ procedure tstoredsymtable.allprivatesused;
+ begin
+ SymList.ForEachCall(@objectprivatesymbolused,nil);
+ end;
+
+
+ procedure TStoredSymtable._needs_init_final(sym:TObject;arg:pointer);
+ begin
+ if b_needs_init_final then
+ exit;
+ { don't check static symbols - they can be present in structures only and
+ always have a reference to a symbol defined on unit level }
+ if sp_static in tsym(sym).symoptions then
+ exit;
+ case tsym(sym).typ of
+ fieldvarsym,
+ staticvarsym,
+ localvarsym,
+ paravarsym :
+ begin
+ if is_managed_type(tabstractvarsym(sym).vardef) then
+ b_needs_init_final:=true;
+ end;
+ end;
+ end;
+
+
+ { returns true, if p contains data which needs init/final code }
+ function tstoredsymtable.needs_init_final : boolean;
+ begin
+ b_needs_init_final:=false;
+ SymList.ForEachCall(@_needs_init_final,nil);
+ needs_init_final:=b_needs_init_final;
+ end;
+
+
+{****************************************************************************
+ TAbstractRecordSymtable
+****************************************************************************}
+
+ constructor tabstractrecordsymtable.create(const n:string;usealign:shortint);
+ begin
+ inherited create(n);
+ moduleid:=current_module.moduleid;
+ _datasize:=0;
+ databitsize:=0;
+ recordalignment:=1;
+ usefieldalignment:=usealign;
+ padalignment:=1;
+ { recordalign C_alignment means C record packing, that starts
+ with an alignment of 1 }
+ case usealign of
+ C_alignment,
+ bit_alignment:
+ fieldalignment:=1;
+ mac68k_alignment:
+ fieldalignment:=2;
+ else
+ fieldalignment:=usealign;
+ end;
+ end;
+
+
+ procedure tabstractrecordsymtable.ppuload(ppufile:tcompilerppufile);
+ begin
+ if ppufile.readentry<>ibrecsymtableoptions then
+ Message(unit_f_ppu_read_error);
+ recordalignment:=shortint(ppufile.getbyte);
+ usefieldalignment:=shortint(ppufile.getbyte);
+ if (usefieldalignment=C_alignment) then
+ fieldalignment:=shortint(ppufile.getbyte);
+ inherited ppuload(ppufile);
+ end;
+
+
+ procedure tabstractrecordsymtable.ppuwrite(ppufile:tcompilerppufile);
+ var
+ oldtyp : byte;
+ begin
+ oldtyp:=ppufile.entrytyp;
+ ppufile.entrytyp:=subentryid;
+ { in case of classes using C alignment, the alignment of the parent
+ affects the alignment of fields of the childs }
+ ppufile.putbyte(byte(recordalignment));
+ ppufile.putbyte(byte(usefieldalignment));
+ if (usefieldalignment=C_alignment) then
+ ppufile.putbyte(byte(fieldalignment));
+ ppufile.writeentry(ibrecsymtableoptions);
+
+ inherited ppuwrite(ppufile);
+
+ ppufile.entrytyp:=oldtyp;
+ end;
+
+
+ function field2recordalignment(fieldoffs, fieldalign: asizeint): asizeint;
+ begin
+ { optimal alignment of the record when declaring a variable of this }
+ { type is independent of the packrecords setting }
+ if (fieldoffs mod fieldalign) = 0 then
+ result:=fieldalign
+ else if (fieldalign >= 16) and
+ ((fieldoffs mod 16) = 0) and
+ ((fieldalign mod 16) = 0) then
+ result:=16
+ else if (fieldalign >= 8) and
+ ((fieldoffs mod 8) = 0) and
+ ((fieldalign mod 8) = 0) then
+ result:=8
+ else if (fieldalign >= 4) and
+ ((fieldoffs mod 4) = 0) and
+ ((fieldalign mod 4) = 0) then
+ result:=4
+ else if (fieldalign >= 2) and
+ ((fieldoffs mod 2) = 0) and
+ ((fieldalign mod 2) = 0) then
+ result:=2
+ else
+ result:=1;
+ end;
+
+ procedure tabstractrecordsymtable.alignrecord(fieldoffset:asizeint;varalign:shortint);
+ var
+ varalignrecord: shortint;
+ begin
+ case usefieldalignment of
+ C_alignment:
+ varalignrecord:=used_align(varalign,current_settings.alignment.recordalignmin,current_settings.alignment.maxCrecordalign);
+ mac68k_alignment:
+ varalignrecord:=2;
+ else
+ varalignrecord:=field2recordalignment(fieldoffset,varalign);
+ end;
+ recordalignment:=max(recordalignment,varalignrecord);
+ end;
+
+ procedure tabstractrecordsymtable.addfield(sym:tfieldvarsym;vis:tvisibility);
+ var
+ l : asizeint;
+ varalignfield,
+ varalign : shortint;
+ vardef : tdef;
+ begin
+ if (sym.owner<>self) then
+ internalerror(200602031);
+ if sym.fieldoffset<>-1 then
+ internalerror(200602032);
+ { set visibility for the symbol }
+ sym.visibility:=vis;
+ { this symbol can't be loaded to a register }
+ sym.varregable:=vr_none;
+ { Calculate field offset }
+ l:=sym.getsize;
+ vardef:=sym.vardef;
+ varalign:=vardef.alignment;
+
+ case usefieldalignment of
+ bit_alignment:
+ begin
+ { bitpacking only happens for ordinals, the rest is aligned at }
+ { 1 byte (compatible with GPC/GCC) }
+ if is_ordinal(vardef) then
+ begin
+ sym.fieldoffset:=databitsize;
+ l:=sym.getpackedbitsize;
+ end
+ else
+ begin
+ databitsize:=_datasize*8;
+ sym.fieldoffset:=databitsize;
+ if (l>high(asizeint) div 8) then
+ Message(sym_e_segment_too_large);
+ l:=l*8;
+ end;
+ if varalign=0 then
+ varalign:=size_2_align(l);
+ recordalignment:=max(recordalignment,field2recordalignment(databitsize mod 8,varalign));
+ { bit packed records are limited to high(aint) bits }
+ { instead of bytes to avoid double precision }
+ { arithmetic in offset calculations }
+ if int64(l)>high(asizeint)-sym.fieldoffset then
+ begin
+ Message(sym_e_segment_too_large);
+ _datasize:=high(asizeint);
+ databitsize:=high(asizeint);
+ end
+ else
+ begin
+ databitsize:=sym.fieldoffset+l;
+ _datasize:=(databitsize+7) div 8;
+ end;
+ { rest is not applicable }
+ exit;
+ end;
+ { Calc the alignment size for C style records }
+ C_alignment:
+ begin
+ if (varalign>4) and
+ ((varalign mod 4)<>0) and
+ (vardef.typ=arraydef) then
+ Message1(sym_w_wrong_C_pack,vardef.typename);
+ if varalign=0 then
+ varalign:=l;
+ if (fieldalignment<current_settings.alignment.maxCrecordalign) then
+ begin
+ if (varalign>16) and (fieldalignment<32) then
+ fieldalignment:=32
+ else if (varalign>12) and (fieldalignment<16) then
+ fieldalignment:=16
+ { 12 is needed for long double }
+ else if (varalign>8) and (fieldalignment<12) then
+ fieldalignment:=12
+ else if (varalign>4) and (fieldalignment<8) then
+ fieldalignment:=8
+ else if (varalign>2) and (fieldalignment<4) then
+ fieldalignment:=4
+ else if (varalign>1) and (fieldalignment<2) then
+ fieldalignment:=2;
+ end;
+ fieldalignment:=min(fieldalignment,current_settings.alignment.maxCrecordalign);
+ end;
+ mac68k_alignment:
+ begin
+ { mac68k alignment (C description):
+ * char is aligned to 1 byte
+ * everything else (except vector) is aligned to 2 bytes
+ * vector is aligned to 16 bytes
+ }
+ if l>1 then
+ fieldalignment:=2
+ else
+ fieldalignment:=1;
+ varalign:=2;
+ end;
+ end;
+ if varalign=0 then
+ varalign:=size_2_align(l);
+ varalignfield:=used_align(varalign,current_settings.alignment.recordalignmin,fieldalignment);
+
+ sym.fieldoffset:=align(_datasize,varalignfield);
+ if l>high(asizeint)-sym.fieldoffset then
+ begin
+ Message(sym_e_segment_too_large);
+ _datasize:=high(aint);
+ end
+ else
+ _datasize:=sym.fieldoffset+l;
+ { Calc alignment needed for this record }
+ alignrecord(sym.fieldoffset,varalign);
+ end;
+
+
+ procedure tabstractrecordsymtable.addalignmentpadding;
+ var
+ padded_datasize: asizeint;
+ begin
+ { make the record size aligned correctly so it can be
+ used as elements in an array. For C records we
+ use the fieldalignment, because that is updated with the
+ used alignment. }
+ if (padalignment = 1) then
+ case usefieldalignment of
+ C_alignment:
+ padalignment:=fieldalignment;
+ { bitpacked }
+ bit_alignment:
+ padalignment:=1;
+ { mac68k: always round to multiple of 2 }
+ mac68k_alignment:
+ padalignment:=2;
+ { default/no packrecords specified }
+ 0:
+ padalignment:=recordalignment
+ { specific packrecords setting -> use as upper limit }
+ else
+ padalignment:=min(recordalignment,usefieldalignment);
+ end;
+ padded_datasize:=align(_datasize,padalignment);
+ _paddingsize:=padded_datasize-_datasize;
+ _datasize:=padded_datasize;
+ end;
+
+
+ procedure tabstractrecordsymtable.insertdef(def:TDefEntry);
+ begin
+ { Enums must also be available outside the record scope,
+ insert in the owner of this symtable }
+ if def.typ=enumdef then
+ defowner.owner.insertdef(def)
+ else
+ inherited insertdef(def);
+ end;
+
+
+ function tabstractrecordsymtable.is_packed: boolean;
+ begin
+ result:=usefieldalignment=bit_alignment;
+ end;
+
+
+ function tabstractrecordsymtable.has_single_field(out sym: tfieldvarsym): boolean;
+ var
+ i: longint;
+ begin
+ result:=false;
+ { If a record contains a union, it does not contain a "single
+ non-composite field" in the context of certain ABIs requiring
+ special treatment for such records }
+ if (defowner.typ=recorddef) and
+ trecorddef(defowner).isunion then
+ exit;
+ { a record/object can contain other things than fields }
+ for i:=0 to SymList.Count-1 do
+ begin
+ if tsym(symlist[i]).typ=fieldvarsym then
+ begin
+ if result then
+ begin
+ result:=false;
+ exit;
+ end;
+ result:=true;
+ sym:=tfieldvarsym(symlist[i])
+ end;
+ end;
+ end;
+
+ function tabstractrecordsymtable.get_unit_symtable: tsymtable;
+ begin
+ result:=defowner.owner;
+ while assigned(result) and (result.symtabletype in [ObjectSymtable,recordsymtable]) do
+ result:=result.defowner.owner;
+ end;
+
+ procedure tabstractrecordsymtable.setdatasize(val: asizeint);
+ begin
+ _datasize:=val;
+ if (usefieldalignment=bit_alignment) then
+ { can overflow in non bitpacked records }
+ databitsize:=val*8;
+ end;
+
+ function tabstractrecordsymtable.iscurrentunit: boolean;
+ begin
+ Result := Assigned(current_module) and (current_module.moduleid=moduleid);
+ end;
+
+{****************************************************************************
+ TRecordSymtable
+****************************************************************************}
+
+ constructor trecordsymtable.create(const n:string;usealign:shortint);
+ begin
+ inherited create(n,usealign);
+ symtabletype:=recordsymtable;
+ end;
+
+
+ { this procedure is reserved for inserting case variant into
+ a record symtable }
+ { the offset is the location of the start of the variant
+ and datasize and dataalignment corresponds to
+ the complete size (see code in pdecl unit) PM }
+ procedure trecordsymtable.insertunionst(unionst : trecordsymtable;offset : longint);
+ var
+ sym : tsym;
+ def : tdef;
+ i : integer;
+ varalignrecord,varalign,
+ storesize,storealign : aint;
+ bitsize: tcgint;
+ begin
+ storesize:=_datasize;
+ storealign:=fieldalignment;
+ _datasize:=offset;
+ if (usefieldalignment=bit_alignment) then
+ databitsize:=offset*8;
+
+ { We move the ownership of the defs and symbols to the new recordsymtable.
+ The old unionsymtable keeps the references, but doesn't own the
+ objects anymore }
+ unionst.DefList.OwnsObjects:=false;
+ unionst.SymList.OwnsObjects:=false;
+
+ { copy symbols }
+ for i:=0 to unionst.SymList.Count-1 do
+ begin
+ sym:=TSym(unionst.SymList[i]);
+ if sym.typ<>fieldvarsym then
+ internalerror(200601272);
+ if tfieldvarsym(sym).fieldoffset=0 then
+ include(tfieldvarsym(sym).varoptions,vo_is_first_field);
+
+ { add to this record symtable }
+// unionst.SymList.List.List^[i].Data:=nil;
+ sym.ChangeOwner(self);
+ varalign:=tfieldvarsym(sym).vardef.alignment;
+ if varalign=0 then
+ varalign:=size_2_align(tfieldvarsym(sym).getsize);
+ { retrieve size }
+ if (usefieldalignment=bit_alignment) then
+ begin
+ { bit packed records are limited to high(aint) bits }
+ { instead of bytes to avoid double precision }
+ { arithmetic in offset calculations }
+ if is_ordinal(tfieldvarsym(sym).vardef) then
+ bitsize:=tfieldvarsym(sym).getpackedbitsize
+ else
+ begin
+ bitsize:=tfieldvarsym(sym).getsize;
+ if (bitsize>high(asizeint) div 8) then
+ Message(sym_e_segment_too_large);
+ bitsize:=bitsize*8;
+ end;
+ if bitsize>high(asizeint)-databitsize then
+ begin
+ Message(sym_e_segment_too_large);
+ _datasize:=high(aint);
+ databitsize:=high(aint);
+ end
+ else
+ begin
+ databitsize:=tfieldvarsym(sym).fieldoffset+offset*8;
+ _datasize:=(databitsize+7) div 8;
+ end;
+ tfieldvarsym(sym).fieldoffset:=databitsize;
+ varalignrecord:=field2recordalignment(tfieldvarsym(sym).fieldoffset div 8,varalign);
+ end
+ else
+ begin
+ if tfieldvarsym(sym).getsize>high(asizeint)-_datasize then
+ begin
+ Message(sym_e_segment_too_large);
+ _datasize:=high(aint);
+ end
+ else
+ _datasize:=tfieldvarsym(sym).fieldoffset+offset;
+ { update address }
+ tfieldvarsym(sym).fieldoffset:=_datasize;
+ varalignrecord:=field2recordalignment(tfieldvarsym(sym).fieldoffset,varalign);
+ end;
+ { update alignment of this record }
+ if (usefieldalignment<>C_alignment) and
+ (usefieldalignment<>mac68k_alignment) then
+ recordalignment:=max(recordalignment,varalignrecord);
+ end;
+ { update alignment for C records }
+ if (usefieldalignment=C_alignment) and
+ (usefieldalignment<>mac68k_alignment) then
+ recordalignment:=max(recordalignment,unionst.recordalignment);
+ { Register defs in the new record symtable }
+ for i:=0 to unionst.DefList.Count-1 do
+ begin
+ def:=TDef(unionst.DefList[i]);
+ def.ChangeOwner(self);
+ end;
+ _datasize:=storesize;
+ fieldalignment:=storealign;
+ { If a record contains a union, it does not contain a "single
+ non-composite field" in the context of certain ABIs requiring
+ special treatment for such records }
+ if defowner.typ=recorddef then
+ trecorddef(defowner).isunion:=true;
+ end;
+
+
+{****************************************************************************
+ TObjectSymtable
+****************************************************************************}
+
+ constructor tObjectSymtable.create(adefowner:tdef;const n:string;usealign:shortint);
+ begin
+ inherited create(n,usealign);
+ symtabletype:=ObjectSymtable;
+ defowner:=adefowner;
+ end;
+
+
+ function tObjectSymtable.checkduplicate(var hashedid:THashedIDString;sym:TSymEntry):boolean;
+ var
+ hsym : tsym;
+ begin
+ result:=false;
+ if not assigned(defowner) then
+ internalerror(200602061);
+
+ { procsym and propertysym have special code
+ to override values in inherited classes. For other
+ symbols check for duplicates }
+ if not(sym.typ in [procsym,propertysym]) then
+ begin
+ { but private ids can be reused }
+ hsym:=search_struct_member(tobjectdef(defowner),hashedid.id);
+ if assigned(hsym) and
+ (
+ (
+ not(m_delphi in current_settings.modeswitches) and
+ is_visible_for_object(hsym,tobjectdef(defowner))
+ ) or
+ (
+ { In Delphi, you can repeat members of a parent class. You can't }
+ { do this for objects however, and you (obviouly) can't }
+ { declare two fields with the same name in a single class }
+ (m_delphi in current_settings.modeswitches) and
+ (
+ is_object(tdef(defowner)) or
+ (hsym.owner = self)
+ )
+ )
+ ) then
+ begin
+ DuplicateSym(hashedid,sym,hsym);
+ result:=true;
+ end;
+ end
+ else
+ result:=inherited checkduplicate(hashedid,sym);
+ end;
+
+
+{****************************************************************************
+ TAbstractLocalSymtable
+****************************************************************************}
+
+ procedure tabstractlocalsymtable.ppuwrite(ppufile:tcompilerppufile);
+ var
+ oldtyp : byte;
+ begin
+ oldtyp:=ppufile.entrytyp;
+ ppufile.entrytyp:=subentryid;
+
+ inherited ppuwrite(ppufile);
+
+ ppufile.entrytyp:=oldtyp;
+ end;
+
+
+ function tabstractlocalsymtable.count_locals:longint;
+ var
+ i : longint;
+ sym : tsym;
+ begin
+ result:=0;
+ for i:=0 to SymList.Count-1 do
+ begin
+ sym:=tsym(SymList[i]);
+ { Count only varsyms, but ignore the funcretsym }
+ if (tsym(sym).typ in [localvarsym,paravarsym]) and
+ (tsym(sym)<>current_procinfo.procdef.funcretsym) and
+ (not(vo_is_parentfp in tabstractvarsym(sym).varoptions) or
+ (tstoredsym(sym).refs>0)) then
+ inc(result);
+ end;
+ end;
+
+
+{****************************************************************************
+ TLocalSymtable
+****************************************************************************}
+
+ constructor tlocalsymtable.create(adefowner:tdef;level:byte);
+ begin
+ inherited create('');
+ defowner:=adefowner;
+ symtabletype:=localsymtable;
+ symtablelevel:=level;
+ end;
+
+
+ function tlocalsymtable.checkduplicate(var hashedid:THashedIDString;sym:TSymEntry):boolean;
+ var
+ hsym : tsym;
+ begin
+ if not assigned(defowner) or
+ (defowner.typ<>procdef) then
+ internalerror(200602042);
+
+ result:=false;
+ hsym:=tsym(FindWithHash(hashedid));
+ if assigned(hsym) then
+ begin
+ { a local and the function can have the same
+ name in TP and Delphi, but RESULT not }
+ if (m_duplicate_names in current_settings.modeswitches) and
+ (hsym.typ in [absolutevarsym,localvarsym]) and
+ (vo_is_funcret in tabstractvarsym(hsym).varoptions) and
+ not((m_result in current_settings.modeswitches) and
+ (vo_is_result in tabstractvarsym(hsym).varoptions)) then
+ HideSym(hsym)
+ else
+ DuplicateSym(hashedid,sym,hsym);
+ result:=true;
+ exit;
+ end;
+
+ { check also parasymtable, this needs to be done here because
+ of the special situation with the funcret sym that needs to be
+ hidden for tp and delphi modes }
+ hsym:=tsym(tabstractprocdef(defowner).parast.FindWithHash(hashedid));
+ if assigned(hsym) then
+ begin
+ { a local and the function can have the same
+ name in TP and Delphi, but RESULT not }
+ if (m_duplicate_names in current_settings.modeswitches) and
+ (sym.typ in [absolutevarsym,localvarsym]) and
+ (vo_is_funcret in tabstractvarsym(sym).varoptions) and
+ not((m_result in current_settings.modeswitches) and
+ (vo_is_result in tabstractvarsym(sym).varoptions)) then
+ Hidesym(sym)
+ else
+ DuplicateSym(hashedid,sym,hsym);
+ result:=true;
+ exit;
+ end;
+
+ { check ObjectSymtable, skip this for funcret sym because
+ that will always be positive because it has the same name
+ as the procsym }
+ if not is_funcret_sym(sym) and
+ (defowner.typ=procdef) and
+ assigned(tprocdef(defowner).struct) and
+ (tprocdef(defowner).owner.defowner=tprocdef(defowner).struct) and
+ (
+ not(m_delphi in current_settings.modeswitches) or
+ is_object(tprocdef(defowner).struct)
+ ) then
+ result:=tprocdef(defowner).struct.symtable.checkduplicate(hashedid,sym);
+ end;
+
+
+{****************************************************************************
+ TParaSymtable
+****************************************************************************}
+
+ constructor tparasymtable.create(adefowner:tdef;level:byte);
+ begin
+ inherited create('');
+ readonly:=false;
+ defowner:=adefowner;
+ symtabletype:=parasymtable;
+ symtablelevel:=level;
+ end;
+
+
+ function tparasymtable.checkduplicate(var hashedid:THashedIDString;sym:TSymEntry):boolean;
+ begin
+ result:=inherited checkduplicate(hashedid,sym);
+ if result then
+ exit;
+ if not(m_duplicate_names in current_settings.modeswitches) and
+ assigned(defowner) and (defowner.typ=procdef) and
+ assigned(tprocdef(defowner).struct) and
+ (tprocdef(defowner).owner.defowner=tprocdef(defowner).struct) and
+ (
+ not(m_delphi in current_settings.modeswitches) or
+ is_object(tprocdef(defowner).struct)
+ ) then
+ result:=tprocdef(defowner).struct.symtable.checkduplicate(hashedid,sym);
+ end;
+
+ procedure tparasymtable.insertdef(def: TDefEntry);
+ begin
+ if readonly then
+ defowner.owner.insertdef(def)
+ else
+ inherited insertdef(def);
+ end;
+
+
+{****************************************************************************
+ TAbstractUniTSymtable
+****************************************************************************}
+
+ constructor tabstractuniTSymtable.create(const n : string;id:word);
+ begin
+ inherited create(n);
+ moduleid:=id;
+ end;
+
+
+ function tabstractuniTSymtable.checkduplicate(var hashedid:THashedIDString;sym:TSymEntry):boolean;
+ var
+ hsym : tsym;
+ begin
+ result:=false;
+ hsym:=tsym(FindWithHash(hashedid));
+ if assigned(hsym) then
+ begin
+ if (sym is tstoredsym) and handle_generic_dummysym(hsym,tstoredsym(sym).symoptions) then
+ exit;
+ if hsym.typ=symconst.namespacesym then
+ begin
+ case sym.typ of
+ symconst.namespacesym:;
+ symconst.unitsym:
+ begin
+ HideSym(sym); { if we add a unit and there is a namespace with the same name then hide the unit name and not the namespace }
+ tnamespacesym(hsym).unitsym:=tsym(sym);
+ end
+ else
+ HideSym(hsym);
+ end;
+ end
+ else
+ { In delphi (contrary to TP) you can have a symbol with the same name as the
+ unit, the unit can then not be accessed anymore using
+ <unit>.<id>, so we can hide the symbol.
+ Do the same if we add a namespace and there is a unit with the same name }
+ if (hsym.typ=symconst.unitsym) and
+ ((m_delphi in current_settings.modeswitches) or (sym.typ=symconst.namespacesym)) then
+ begin
+ HideSym(hsym);
+ if sym.typ=symconst.namespacesym then
+ tnamespacesym(sym).unitsym:=tsym(hsym);
+ end
+ else
+ DuplicateSym(hashedid,sym,hsym);
+ result:=true;
+ exit;
+ end;
+ end;
+
+ function tabstractuniTSymtable.iscurrentunit:boolean;
+ begin
+ result:=assigned(current_module) and
+ (
+ (current_module.globalsymtable=self) or
+ (current_module.localsymtable=self)
+ );
+ end;
+
+ procedure tabstractuniTSymtable.insertunit(sym:TSymEntry);
+ var
+ p:integer;
+ n,ns:string;
+ oldsym:TSymEntry;
+ begin
+ insert(sym);
+ n:=sym.realname;
+ p:=pos('.',n);
+ ns:='';
+ while p>0 do
+ begin
+ if ns='' then
+ ns:=copy(n,1,p-1)
+ else
+ ns:=ns+'.'+copy(n,1,p-1);
+ system.delete(n,1,p);
+ oldsym:=Find(upper(ns));
+ if not Assigned(oldsym) or (oldsym.typ<>namespacesym) then
+ insert(tnamespacesym.create(ns));
+ p:=pos('.',n);
+ end;
+ end;
+
+{****************************************************************************
+ TStaticSymtable
+****************************************************************************}
+
+ constructor tstaticsymtable.create(const n : string;id:word);
+ begin
+ inherited create(n,id);
+ symtabletype:=staticsymtable;
+ symtablelevel:=main_program_level;
+ end;
+
+
+ procedure tstaticsymtable.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(ppufile);
+
+ { now we can deref the syms and defs }
+ deref;
+ end;
+
+
+ procedure tstaticsymtable.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ end;
+
+
+ function tstaticsymtable.checkduplicate(var hashedid:THashedIDString;sym:TSymEntry):boolean;
+ begin
+ result:=inherited checkduplicate(hashedid,sym);
+
+ if not result and
+ (current_module.localsymtable=self) and
+ assigned(current_module.globalsymtable) then
+ result:=tglobalsymtable(current_module.globalsymtable).checkduplicate(hashedid,sym);
+ end;
+
+
+{****************************************************************************
+ TGlobalSymtable
+****************************************************************************}
+
+ constructor tglobalsymtable.create(const n : string;id:word);
+ begin
+ inherited create(n,id);
+ symtabletype:=globalsymtable;
+ symtablelevel:=main_program_level;
+ end;
+
+
+ procedure tglobalsymtable.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(ppufile);
+
+ { now we can deref the syms and defs }
+ deref;
+ end;
+
+
+ procedure tglobalsymtable.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ { write the symtable entries }
+ inherited ppuwrite(ppufile);
+ end;
+
+
+{*****************************************************************************
+ tspecializesymtable
+*****************************************************************************}
+
+ function tspecializesymtable.iscurrentunit: boolean;
+ begin
+ Result := true;
+ end;
+
+
+{****************************************************************************
+ TWITHSYMTABLE
+****************************************************************************}
+
+ constructor twithsymtable.create(aowner:tdef;ASymList:TFPHashObjectList;refnode:tobject{tnode});
+ begin
+ inherited create('');
+ symtabletype:=withsymtable;
+ withrefnode:=refnode;
+ { Replace SymList with the passed symlist }
+ SymList.free;
+ SymList:=ASymList;
+ defowner:=aowner;
+ end;
+
+
+ destructor twithsymtable.destroy;
+ begin
+ withrefnode.free;
+ { Disable SymList because we don't Own it }
+ SymList:=nil;
+ inherited destroy;
+ end;
+
+
+ procedure twithsymtable.clear;
+ begin
+ { remove no entry from a withsymtable as it is only a pointer to the
+ recorddef or objectdef symtable }
+ end;
+
+
+ procedure twithsymtable.insertdef(def:TDefEntry);
+ begin
+ { Definitions can't be registered in the withsymtable
+ because the withsymtable is removed after the with block.
+ We can't easily solve it here because the next symtable in the
+ stack is not known. }
+ internalerror(200602046);
+ end;
+
+{****************************************************************************
+ TSTT_ExceptionSymtable
+****************************************************************************}
+
+ constructor tstt_excepTSymtable.create;
+ begin
+ inherited create('');
+ symtabletype:=stt_excepTSymtable;
+ end;
+
+
+{****************************************************************************
+ TMacroSymtable
+****************************************************************************}
+
+ constructor tmacrosymtable.create(exported: boolean);
+ begin
+ inherited create('');
+ if exported then
+ symtabletype:=exportedmacrosymtable
+ else
+ symtabletype:=localmacrosymtable;
+ symtablelevel:=main_program_level;
+ end;
+
+{****************************************************************************
+ TEnumSymtable
+****************************************************************************}
+
+ procedure tenumsymtable.insert(sym: TSymEntry; checkdup: boolean);
+ var
+ value: longint;
+ def: tenumdef;
+ begin
+ // defowner = nil only when we are loading from ppu
+ if defowner<>nil then
+ begin
+ { First entry? Then we need to set the minval }
+ value:=tenumsym(sym).value;
+ def:=tenumdef(defowner);
+ if SymList.count=0 then
+ begin
+ if value>0 then
+ def.has_jumps:=true;
+ def.setmin(value);
+ def.setmax(value);
+ end
+ else
+ begin
+ { check for jumps }
+ if value>def.max+1 then
+ def.has_jumps:=true;
+ { update low and high }
+ if def.min>value then
+ def.setmin(value);
+ if def.max<value then
+ def.setmax(value);
+ end;
+ end;
+ inherited insert(sym, checkdup);
+ end;
+
+ constructor tenumsymtable.create(adefowner: tdef);
+ begin
+ inherited Create('');
+ symtabletype:=enumsymtable;
+ defowner:=adefowner;
+ end;
+
+{****************************************************************************
+ TArraySymtable
+****************************************************************************}
+
+ procedure tarraysymtable.insertdef(def: TDefEntry);
+ begin
+ { Enums must also be available outside the record scope,
+ insert in the owner of this symtable }
+ if def.typ=enumdef then
+ defowner.owner.insertdef(def)
+ else
+ inherited insertdef(def);
+ end;
+
+ constructor tarraysymtable.create(adefowner: tdef);
+ begin
+ inherited Create('');
+ symtabletype:=arraysymtable;
+ defowner:=adefowner;
+ end;
+
+{*****************************************************************************
+ Helper Routines
+*****************************************************************************}
+
+ function FullTypeName(def,otherdef:tdef):string;
+ var
+ s1,s2 : string;
+ begin
+ if def.typ in [objectdef,recorddef] then
+ s1:=tabstractrecorddef(def).RttiName
+ else
+ s1:=def.typename;
+ { When the names are the same try to include the unit name }
+ if assigned(otherdef) and
+ (def.owner.symtabletype in [globalsymtable,staticsymtable]) then
+ begin
+ s2:=otherdef.typename;
+ if upper(s1)=upper(s2) then
+ s1:=def.owner.realname^+'.'+s1;
+ end;
+ FullTypeName:=s1;
+ end;
+
+ function generate_nested_name(symtable:tsymtable;delimiter:string):string;
+ begin
+ result:='';
+ while assigned(symtable) and (symtable.symtabletype in [ObjectSymtable,recordsymtable]) do
+ begin
+ if (result='') then
+ result:=symtable.name^
+ else
+ result:=symtable.name^+delimiter+result;
+ symtable:=symtable.defowner.owner;
+ end;
+ end;
+
+ procedure incompatibletypes(def1,def2:tdef);
+ begin
+ { When there is an errordef there is already an error message show }
+ if (def2.typ=errordef) or
+ (def1.typ=errordef) then
+ exit;
+ CGMessage2(type_e_incompatible_types,FullTypeName(def1,def2),FullTypeName(def2,def1));
+ end;
+
+
+ procedure hidesym(sym:TSymEntry);
+ begin
+ sym.realname:='$hidden'+sym.realname;
+ tsym(sym).visibility:=vis_hidden;
+ end;
+
+
+ procedure duplicatesym(var hashedid:THashedIDString;dupsym,origsym:TSymEntry);
+ var
+ st : TSymtable;
+ begin
+ Message1(sym_e_duplicate_id,tsym(origsym).realname);
+ { Write hint where the original symbol was found }
+ st:=finduniTSymtable(origsym.owner);
+ with tsym(origsym).fileinfo do
+ begin
+ if assigned(st) and
+ (st.symtabletype=globalsymtable) and
+ st.iscurrentunit then
+ Message2(sym_h_duplicate_id_where,current_module.sourcefiles.get_file_name(fileindex),tostr(line))
+ else if assigned(st.name) then
+ Message2(sym_h_duplicate_id_where,'unit '+st.name^,tostr(line));
+ end;
+ { Rename duplicate sym to an unreachable name, but it can be
+ inserted in the symtable without errors }
+ inc(dupnr);
+ hashedid.id:='dup'+tostr(dupnr)+hashedid.id;
+ if assigned(dupsym) then
+ include(tsym(dupsym).symoptions,sp_implicitrename);
+ end;
+
+ function handle_generic_dummysym(sym:TSymEntry;var symoptions:tsymoptions):boolean;
+ begin
+ result:=false;
+ if not assigned(sym) or not (sym is tstoredsym) then
+ Internalerror(2011081101);
+ { For generics a dummy symbol without the parameter count is created
+ if such a symbol not yet exists so that different parts of the
+ parser can find that symbol. If that symbol is still a
+ undefineddef we replace the generic dummy symbol's
+ name with a "dup" name and use the new symbol as the generic dummy
+ symbol }
+ if (sp_generic_dummy in tstoredsym(sym).symoptions) and
+ (sym.typ=typesym) and (ttypesym(sym).typedef.typ=undefineddef) and
+ (m_delphi in current_settings.modeswitches) then
+ begin
+ inc(dupnr);
+ sym.Owner.SymList.Rename(upper(sym.realname),'dup_'+tostr(dupnr)+sym.realname);
+ include(tsym(sym).symoptions,sp_implicitrename);
+ { we need to find the new symbol now if checking for a dummy }
+ include(symoptions,sp_generic_dummy);
+ result:=true;
+ end;
+ end;
+
+{*****************************************************************************
+ Search
+*****************************************************************************}
+
+ procedure addsymref(sym:tsym);
+ begin
+ { symbol uses count }
+ sym.IncRefCount;
+ { unit uses count }
+ if assigned(current_module) and
+ (sym.owner.symtabletype=globalsymtable) then
+ begin
+ if tglobalsymtable(sym.owner).moduleid>=current_module.unitmapsize then
+ internalerror(200501152);
+ inc(current_module.unitmap[tglobalsymtable(sym.owner).moduleid].refs);
+ end;
+ end;
+
+
+ function is_owned_by(childdef,ownerdef:tdef):boolean;
+ begin
+ result:=childdef=ownerdef;
+ if not result and assigned(childdef.owner.defowner) then
+ result:=is_owned_by(tdef(childdef.owner.defowner),ownerdef);
+ end;
+
+ function sym_is_owned_by(childsym:tsym;symtable:tsymtable):boolean;
+ begin
+ result:=childsym.owner=symtable;
+ if not result and (childsym.owner.symtabletype in [objectsymtable,recordsymtable]) then
+ result:=sym_is_owned_by(tabstractrecorddef(childsym.owner.defowner).typesym,symtable);
+ end;
+
+ function is_visible_for_object(symst:tsymtable;symvisibility:tvisibility;contextobjdef:tabstractrecorddef):boolean;
+ var
+ symownerdef : tabstractrecorddef;
+ begin
+ result:=false;
+
+ { Get objdectdef owner of the symtable for the is_related checks }
+ if not assigned(symst) or
+ not (symst.symtabletype in [objectsymtable,recordsymtable]) then
+ internalerror(200810285);
+ symownerdef:=tabstractrecorddef(symst.defowner);
+ case symvisibility of
+ vis_private :
+ begin
+ { private symbols are allowed when we are in the same
+ module as they are defined }
+ result:=(
+ (symownerdef.owner.symtabletype in [globalsymtable,staticsymtable]) and
+ (symownerdef.owner.iscurrentunit)
+ ) or
+ ( // the case of specialize inside the generic declaration and nested types
+ (symownerdef.owner.symtabletype in [objectsymtable,recordsymtable]) and
+ (
+ assigned(current_structdef) and
+ (
+ (current_structdef=symownerdef) or
+ (current_structdef.owner.iscurrentunit)
+ )
+ ) or
+ (
+ not assigned(current_structdef) and
+ (symownerdef.owner.iscurrentunit)
+ )
+ );
+ end;
+ vis_strictprivate :
+ begin
+ result:=assigned(current_structdef) and
+ is_owned_by(current_structdef,symownerdef);
+ end;
+ vis_strictprotected :
+ begin
+ result:=(
+ assigned(current_structdef) and
+ (current_structdef.is_related(symownerdef) or
+ is_owned_by(current_structdef,symownerdef))
+ ) or
+ (
+ { helpers can access strict protected symbols }
+ is_objectpascal_helper(contextobjdef) and
+ tobjectdef(contextobjdef).extendeddef.is_related(symownerdef)
+ );
+ end;
+ vis_protected :
+ begin
+ { protected symbols are visible in the module that defines them and
+ also visible to related objects. The related object must be defined
+ in the current module }
+ result:=(
+ (
+ (symownerdef.owner.symtabletype in [globalsymtable,staticsymtable]) and
+ (symownerdef.owner.iscurrentunit)
+ ) or
+ (
+ assigned(contextobjdef) and
+ (contextobjdef.owner.symtabletype in [globalsymtable,staticsymtable,ObjectSymtable]) and
+ (contextobjdef.owner.iscurrentunit) and
+ contextobjdef.is_related(symownerdef)
+ ) or
+ ( // the case of specialize inside the generic declaration and nested types
+ (symownerdef.owner.symtabletype in [objectsymtable,recordsymtable]) and
+ (
+ assigned(current_structdef) and
+ (
+ (current_structdef=symownerdef) or
+ (current_structdef.owner.iscurrentunit)
+ )
+ ) or
+ (
+ not assigned(current_structdef) and
+ (symownerdef.owner.iscurrentunit)
+ ) or
+ (
+ { helpers can access protected symbols }
+ is_objectpascal_helper(contextobjdef) and
+ tobjectdef(contextobjdef).extendeddef.is_related(symownerdef)
+ )
+ )
+ );
+ end;
+ vis_public,
+ vis_published :
+ result:=true;
+ end;
+ end;
+
+
+ function is_visible_for_object(pd:tprocdef;contextobjdef:tabstractrecorddef):boolean;
+ begin
+ result:=is_visible_for_object(pd.owner,pd.visibility,contextobjdef);
+ end;
+
+
+ function is_visible_for_object(sym:tsym;contextobjdef:tabstractrecorddef):boolean;
+ var
+ i : longint;
+ pd : tprocdef;
+ begin
+ if sym.typ=procsym then
+ begin
+ { A procsym is visible, when there is at least one of the procdefs visible }
+ result:=false;
+ for i:=0 to tprocsym(sym).ProcdefList.Count-1 do
+ begin
+ pd:=tprocdef(tprocsym(sym).ProcdefList[i]);
+ if (pd.owner=sym.owner) and
+ is_visible_for_object(pd,contextobjdef) then
+ begin
+ result:=true;
+ exit;
+ end;
+ end;
+ end
+ else
+ result:=is_visible_for_object(sym.owner,sym.visibility,contextobjdef);
+ end;
+
+
+ function searchsym(const s : TIDString;out srsym:tsym;out srsymtable:TSymtable):boolean;
+ begin
+ result:=searchsym_maybe_with_symoption(s,srsym,srsymtable,false,sp_none);
+ end;
+
+ function searchsym_maybe_with_symoption(const s : TIDString;out srsym:tsym;out srsymtable:TSymtable;searchoption:boolean;option:tsymoption):boolean;
+ var
+ hashedid : THashedIDString;
+ contextstructdef : tabstractrecorddef;
+ stackitem : psymtablestackitem;
+ begin
+ result:=false;
+ hashedid.id:=s;
+ stackitem:=symtablestack.stack;
+ while assigned(stackitem) do
+ begin
+ srsymtable:=stackitem^.symtable;
+ if (srsymtable.symtabletype=objectsymtable) then
+ begin
+ { TODO : implement the search for an option in classes as well }
+ if searchoption then
+ begin
+ result:=false;
+ exit;
+ end;
+ if searchsym_in_class(tobjectdef(srsymtable.defowner),tobjectdef(srsymtable.defowner),s,srsym,srsymtable,true) then
+ begin
+ result:=true;
+ exit;
+ end;
+ end
+ else
+ begin
+ srsym:=tsym(srsymtable.FindWithHash(hashedid));
+ if assigned(srsym) then
+ begin
+ { use the class from withsymtable only when it is
+ defined in this unit }
+ if (srsymtable.symtabletype=withsymtable) and
+ assigned(srsymtable.defowner) and
+ (srsymtable.defowner.typ in [recorddef,objectdef]) and
+ (srsymtable.defowner.owner.symtabletype in [globalsymtable,staticsymtable,objectsymtable,recordsymtable]) and
+ (srsymtable.defowner.owner.iscurrentunit) then
+ contextstructdef:=tabstractrecorddef(srsymtable.defowner)
+ else
+ contextstructdef:=current_structdef;
+ if not (srsym.owner.symtabletype in [objectsymtable,recordsymtable]) or
+ is_visible_for_object(srsym,contextstructdef) and
+ (not searchoption or (option in srsym.symoptions)) then
+ begin
+ { we need to know if a procedure references symbols
+ in the static symtable, because then it can't be
+ inlined from outside this unit }
+ if assigned(current_procinfo) and
+ (srsym.owner.symtabletype=staticsymtable) then
+ include(current_procinfo.flags,pi_uses_static_symtable);
+ addsymref(srsym);
+ result:=true;
+ exit;
+ end;
+ end;
+ end;
+ stackitem:=stackitem^.next;
+ end;
+ srsym:=nil;
+ srsymtable:=nil;
+ end;
+
+ function searchsym_with_symoption(const s: TIDString;out srsym:tsym;out
+ srsymtable:TSymtable;option:tsymoption):boolean;
+ begin
+ result:=searchsym_maybe_with_symoption(s,srsym,srsymtable,true,option);
+ end;
+
+ function searchsym_type(const s : TIDString;out srsym:tsym;out srsymtable:TSymtable):boolean;
+ var
+ hashedid : THashedIDString;
+ stackitem : psymtablestackitem;
+ classh : tobjectdef;
+ begin
+ result:=false;
+ hashedid.id:=s;
+ stackitem:=symtablestack.stack;
+ while assigned(stackitem) do
+ begin
+ {
+ It is not possible to have type symbols in:
+ parameters
+ Exception are classes, objects, records, generic definitions and specializations
+ that have the parameterized types inserted in the symtable.
+ }
+ srsymtable:=stackitem^.symtable;
+ if (srsymtable.symtabletype=ObjectSymtable) then
+ begin
+ classh:=tobjectdef(srsymtable.defowner);
+ while assigned(classh) do
+ begin
+ srsymtable:=classh.symtable;
+ srsym:=tsym(srsymtable.FindWithHash(hashedid));
+ if assigned(srsym) and
+ not(srsym.typ in [fieldvarsym,paravarsym,propertysym,procsym,labelsym]) and
+ is_visible_for_object(srsym,current_structdef) then
+ begin
+ addsymref(srsym);
+ result:=true;
+ exit;
+ end;
+ classh:=classh.childof;
+ end;
+ end
+ else
+ begin
+ srsym:=tsym(srsymtable.FindWithHash(hashedid));
+ if assigned(srsym) and
+ not(srsym.typ in [fieldvarsym,paravarsym,propertysym,procsym,labelsym]) and
+ (not (srsym.owner.symtabletype in [objectsymtable,recordsymtable]) or is_visible_for_object(srsym,current_structdef)) then
+ begin
+ { we need to know if a procedure references symbols
+ in the static symtable, because then it can't be
+ inlined from outside this unit }
+ if assigned(current_procinfo) and
+ (srsym.owner.symtabletype=staticsymtable) then
+ include(current_procinfo.flags,pi_uses_static_symtable);
+ addsymref(srsym);
+ result:=true;
+ exit;
+ end;
+ end;
+ stackitem:=stackitem^.next;
+ end;
+ result:=false;
+ srsym:=nil;
+ srsymtable:=nil;
+ end;
+
+
+ function searchsym_in_module(pm:pointer;const s : TIDString;out srsym:tsym;out srsymtable:TSymtable):boolean;
+ var
+ pmod : tmodule;
+ begin
+ pmod:=tmodule(pm);
+ result:=false;
+ if assigned(pmod.globalsymtable) then
+ begin
+ srsym:=tsym(pmod.globalsymtable.Find(s));
+ if assigned(srsym) then
+ begin
+ srsymtable:=pmod.globalsymtable;
+ addsymref(srsym);
+ result:=true;
+ exit;
+ end;
+ end;
+ { If the module is the current unit we also need
+ to search the local symtable }
+ if (pmod=current_module) and
+ assigned(pmod.localsymtable) then
+ begin
+ srsym:=tsym(pmod.localsymtable.Find(s));
+ if assigned(srsym) then
+ begin
+ srsymtable:=pmod.localsymtable;
+ addsymref(srsym);
+ result:=true;
+ exit;
+ end;
+ end;
+ srsym:=nil;
+ srsymtable:=nil;
+ end;
+
+
+ function searchsym_in_named_module(const unitname, symname: TIDString; out srsym: tsym; out srsymtable: tsymtable): boolean;
+ var
+ stackitem : psymtablestackitem;
+ begin
+ result:=false;
+ stackitem:=symtablestack.stack;
+ while assigned(stackitem) do
+ begin
+ srsymtable:=stackitem^.symtable;
+ if (srsymtable.symtabletype=globalsymtable) and
+ (srsymtable.name^=unitname) then
+ begin
+ srsym:=tsym(srsymtable.find(symname));
+ if not assigned(srsym) then
+ break;
+ result:=true;
+ exit;
+ end;
+ stackitem:=stackitem^.next;
+ end;
+
+ { If the module is the current unit we also need
+ to search the local symtable }
+ if (current_module.globalsymtable=srsymtable) and
+ assigned(current_module.localsymtable) then
+ begin
+ srsymtable:=current_module.localsymtable;
+ srsym:=tsym(srsymtable.find(symname));
+ if assigned(srsym) then
+ begin
+ result:=true;
+ exit;
+ end;
+ end;
+ end;
+
+
+ function find_real_objcclass_definition(pd: tobjectdef; erroronfailure: boolean): tobjectdef;
+ var
+ hashedid : THashedIDString;
+ stackitem : psymtablestackitem;
+ srsymtable : tsymtable;
+ srsym : tsym;
+ begin
+ { not a formal definition -> return it }
+ if not(oo_is_formal in pd.objectoptions) then
+ begin
+ result:=pd;
+ exit;
+ end;
+ hashedid.id:=pd.typesym.name;
+ stackitem:=symtablestack.stack;
+ while assigned(stackitem) do
+ begin
+ srsymtable:=stackitem^.symtable;
+ { ObjC classes can't appear in generics or as nested class
+ definitions }
+ if not(srsymtable.symtabletype in [recordsymtable,ObjectSymtable,parasymtable]) then
+ begin
+ srsym:=tsym(srsymtable.FindWithHash(hashedid));
+ if assigned(srsym) and
+ (srsym.typ=typesym) and
+ is_objcclass(ttypesym(srsym).typedef) and
+ not(oo_is_formal in tobjectdef(ttypesym(srsym).typedef).objectoptions) then
+ begin
+ { the external name for the formal and the real definition must match }
+ if tobjectdef(ttypesym(srsym).typedef).objextname^<>pd.objextname^ then
+ begin
+ Message2(sym_e_external_class_name_mismatch1,pd.objextname^,pd.typename);
+ MessagePos1(srsym.fileinfo,sym_e_external_class_name_mismatch2,tobjectdef(ttypesym(srsym).typedef).objextname^);
+ end;
+ result:=tobjectdef(ttypesym(srsym).typedef);
+ if assigned(current_procinfo) and
+ (srsym.owner.symtabletype=staticsymtable) then
+ include(current_procinfo.flags,pi_uses_static_symtable);
+ addsymref(srsym);
+ exit;
+ end;
+ end;
+ stackitem:=stackitem^.next;
+ end;
+ { nothing found: optionally give an error and return the original
+ (empty) one }
+ if erroronfailure then
+ Message1(sym_e_objc_formal_class_not_resolved,pd.objrealname^);
+ result:=pd;
+ end;
+
+
+ function searchsym_in_class(classh,contextclassh:tobjectdef;const s : TIDString;out srsym:tsym;out srsymtable:TSymtable;searchhelper:boolean):boolean;
+ var
+ hashedid : THashedIDString;
+ orgclass : tobjectdef;
+ i : longint;
+ begin
+ orgclass:=classh;
+ { in case this is a formal objcclass, first find the real definition }
+ if assigned(classh) then
+ begin
+ if (oo_is_formal in classh.objectoptions) then
+ classh:=find_real_objcclass_definition(classh,true);
+ { The contextclassh is used for visibility. The classh must be equal to
+ or be a parent of contextclassh. E.g. for inherited searches the classh is the
+ parent or a class helper. }
+ if not (contextclassh.is_related(classh) or
+ (assigned(contextclassh.extendeddef) and
+ (contextclassh.extendeddef.typ=objectdef) and
+ contextclassh.extendeddef.is_related(classh))) then
+ internalerror(200811161);
+ end;
+ result:=false;
+ hashedid.id:=s;
+ { an Objective-C protocol can inherit from multiple other protocols
+ -> uses ImplementedInterfaces instead }
+ if is_objcprotocol(classh) then
+ begin
+ srsymtable:=classh.symtable;
+ srsym:=tsym(srsymtable.FindWithHash(hashedid));
+ if assigned(srsym) and
+ is_visible_for_object(srsym,contextclassh) then
+ begin
+ addsymref(srsym);
+ result:=true;
+ exit;
+ end;
+ for i:=0 to classh.ImplementedInterfaces.count-1 do
+ begin
+ if searchsym_in_class(TImplementedInterface(classh.ImplementedInterfaces[i]).intfdef,contextclassh,s,srsym,srsymtable,false) then
+ begin
+ result:=true;
+ exit;
+ end;
+ end;
+ end
+ else
+ if is_objectpascal_helper(classh) then
+ begin
+ { helpers have their own obscure search logic... }
+ result:=searchsym_in_helper(classh,contextclassh,s,srsym,srsymtable,false);
+ if result then
+ exit;
+ end
+ else
+ begin
+ while assigned(classh) do
+ begin
+ { search for a class helper method first if this is an Object
+ Pascal class }
+ if is_class(classh) and searchhelper then
+ begin
+ result:=search_objectpascal_helper(classh,contextclassh,s,srsym,srsymtable);
+ if result then
+ { if the procsym is overloaded we need to use the
+ "original" symbol; the helper symbol will be found when
+ searching for overloads }
+ if (srsym.typ<>procsym) or
+ not (sp_has_overloaded in tprocsym(srsym).symoptions) then
+ exit;
+ end;
+ srsymtable:=classh.symtable;
+ srsym:=tsym(srsymtable.FindWithHash(hashedid));
+ if assigned(srsym) and
+ is_visible_for_object(srsym,contextclassh) then
+ begin
+ addsymref(srsym);
+ result:=true;
+ exit;
+ end;
+ classh:=classh.childof;
+ end;
+ end;
+ if is_objcclass(orgclass) then
+ result:=search_objc_helper(orgclass,s,srsym,srsymtable)
+ else
+ begin
+ srsym:=nil;
+ srsymtable:=nil;
+ end;
+ end;
+
+ function searchsym_in_record(recordh:tabstractrecorddef;const s : TIDString;out srsym:tsym;out srsymtable:TSymtable):boolean;
+ var
+ hashedid : THashedIDString;
+ begin
+ result:=false;
+ hashedid.id:=s;
+ { search for a record helper method first }
+ result:=search_objectpascal_helper(recordh,recordh,s,srsym,srsymtable);
+ if result then
+ { if the procsym is overloaded we need to use the
+ "original" symbol; the helper symbol will be found when
+ searching for overloads }
+ if (srsym.typ<>procsym) or
+ not (sp_has_overloaded in tprocsym(srsym).symoptions) then
+ exit;
+ srsymtable:=recordh.symtable;
+ srsym:=tsym(srsymtable.FindWithHash(hashedid));
+ if assigned(srsym) and is_visible_for_object(srsym,recordh) then
+ begin
+ addsymref(srsym);
+ result:=true;
+ exit;
+ end;
+ srsym:=nil;
+ srsymtable:=nil;
+ end;
+
+ function searchsym_in_class_by_msgint(classh:tobjectdef;msgid:longint;out srdef : tdef;out srsym:tsym;out srsymtable:TSymtable):boolean;
+ var
+ def : tdef;
+ i : longint;
+ begin
+ { in case this is a formal objcclass, first find the real definition }
+ if assigned(classh) and
+ (oo_is_formal in classh.objectoptions) then
+ classh:=find_real_objcclass_definition(classh,true);
+ result:=false;
+ def:=nil;
+ while assigned(classh) do
+ begin
+ for i:=0 to classh.symtable.DefList.Count-1 do
+ begin
+ def:=tstoreddef(classh.symtable.DefList[i]);
+ { Find also all hidden private methods to
+ be compatible with delphi, see tw6203 (PFV) }
+ if (def.typ=procdef) and
+ (po_msgint in tprocdef(def).procoptions) and
+ (tprocdef(def).messageinf.i=msgid) then
+ begin
+ srdef:=def;
+ srsym:=tprocdef(def).procsym;
+ srsymtable:=classh.symtable;
+ addsymref(srsym);
+ result:=true;
+ exit;
+ end;
+ end;
+ classh:=classh.childof;
+ end;
+ srdef:=nil;
+ srsym:=nil;
+ srsymtable:=nil;
+ end;
+
+
+ function searchsym_in_class_by_msgstr(classh:tobjectdef;const s:string;out srsym:tsym;out srsymtable:TSymtable):boolean;
+ var
+ def : tdef;
+ i : longint;
+ begin
+ { in case this is a formal objcclass, first find the real definition }
+ if assigned(classh) and
+ (oo_is_formal in classh.objectoptions) then
+ classh:=find_real_objcclass_definition(classh,true);
+ result:=false;
+ def:=nil;
+ while assigned(classh) do
+ begin
+ for i:=0 to classh.symtable.DefList.Count-1 do
+ begin
+ def:=tstoreddef(classh.symtable.DefList[i]);
+ { Find also all hidden private methods to
+ be compatible with delphi, see tw6203 (PFV) }
+ if (def.typ=procdef) and
+ (po_msgstr in tprocdef(def).procoptions) and
+ (tprocdef(def).messageinf.str^=s) then
+ begin
+ srsym:=tprocdef(def).procsym;
+ srsymtable:=classh.symtable;
+ addsymref(srsym);
+ result:=true;
+ exit;
+ end;
+ end;
+ classh:=classh.childof;
+ end;
+ srsym:=nil;
+ srsymtable:=nil;
+ end;
+
+ function searchsym_in_helper(classh,contextclassh:tobjectdef;const s: TIDString;out srsym:tsym;out srsymtable:TSymtable;aHasInherited:boolean):boolean;
+ var
+ hashedid : THashedIDString;
+ parentclassh : tobjectdef;
+ begin
+ result:=false;
+ if not is_objectpascal_helper(classh) then
+ Internalerror(2011030101);
+ hashedid.id:=s;
+ { in a helper things are a bit more complex:
+ 1. search the symbol in the helper (if not "inherited")
+ 2. search the symbol in the extended type
+ 3. search the symbol in the parent helpers
+ 4. only classes: search the symbol in the parents of the extended type
+ }
+ if not aHasInherited then
+ begin
+ { search in the helper itself }
+ srsymtable:=classh.symtable;
+ srsym:=tsym(srsymtable.FindWithHash(hashedid));
+ if assigned(srsym) and
+ is_visible_for_object(srsym,contextclassh) then
+ begin
+ addsymref(srsym);
+ result:=true;
+ exit;
+ end;
+ end;
+ { now search in the extended type itself }
+ if classh.extendeddef.typ in [recorddef,objectdef] then
+ begin
+ srsymtable:=tabstractrecorddef(classh.extendeddef).symtable;
+ srsym:=tsym(srsymtable.FindWithHash(hashedid));
+ if assigned(srsym) and
+ is_visible_for_object(srsym,contextclassh) then
+ begin
+ addsymref(srsym);
+ result:=true;
+ exit;
+ end;
+ end;
+ { now search in the parent helpers }
+ parentclassh:=classh.childof;
+ while assigned(parentclassh) do
+ begin
+ srsymtable:=parentclassh.symtable;
+ srsym:=tsym(srsymtable.FindWithHash(hashedid));
+ if assigned(srsym) and
+ is_visible_for_object(srsym,contextclassh) then
+ begin
+ addsymref(srsym);
+ result:=true;
+ exit;
+ end;
+ parentclassh:=parentclassh.childof;
+ end;
+ if is_class(classh.extendeddef) then
+ { now search in the parents of the extended class (with helpers!) }
+ result:=searchsym_in_class(tobjectdef(classh.extendeddef).childof,contextclassh,s,srsym,srsymtable,true);
+ { addsymref is already called by searchsym_in_class }
+ end;
+
+ function search_specific_assignment_operator(assignment_type:ttoken;from_def,to_def:Tdef):Tprocdef;
+ var
+ sym : Tprocsym;
+ hashedid : THashedIDString;
+ curreq,
+ besteq : tequaltype;
+ currpd,
+ bestpd : tprocdef;
+ stackitem : psymtablestackitem;
+ begin
+ hashedid.id:=overloaded_names[assignment_type];
+ besteq:=te_incompatible;
+ bestpd:=nil;
+ stackitem:=symtablestack.stack;
+ while assigned(stackitem) do
+ begin
+ sym:=Tprocsym(stackitem^.symtable.FindWithHash(hashedid));
+ if sym<>nil then
+ begin
+ if sym.typ<>procsym then
+ internalerror(200402031);
+ { if the source type is an alias then this is only the second choice,
+ if you mess with this code, check tw4093 }
+ currpd:=sym.find_procdef_assignment_operator(from_def,to_def,curreq);
+ if curreq>besteq then
+ begin
+ besteq:=curreq;
+ bestpd:=currpd;
+ if (besteq=te_exact) then
+ break;
+ end;
+ end;
+ stackitem:=stackitem^.next;
+ end;
+ result:=bestpd;
+ end;
+
+
+ function search_assignment_operator(from_def,to_def:Tdef;explicit:boolean):Tprocdef;
+ begin
+ { search record/object symtable first for a suitable operator }
+ if from_def.typ in [recorddef,objectdef] then
+ symtablestack.push(tabstractrecorddef(from_def).symtable);
+ if to_def.typ in [recorddef,objectdef] then
+ symtablestack.push(tabstractrecorddef(to_def).symtable);
+
+ { if type conversion is explicit then search first for explicit
+ operator overload and if not found then use implicit operator }
+ if explicit then
+ result:=search_specific_assignment_operator(_OP_EXPLICIT,from_def,to_def)
+ else
+ result:=nil;
+ if result=nil then
+ result:=search_specific_assignment_operator(_ASSIGNMENT,from_def,to_def);
+
+ { restore symtable stack }
+ if to_def.typ in [recorddef,objectdef] then
+ symtablestack.pop(tabstractrecorddef(to_def).symtable);
+ if from_def.typ in [recorddef,objectdef] then
+ symtablestack.pop(tabstractrecorddef(from_def).symtable);
+ end;
+
+
+ function search_enumerator_operator(from_def,to_def:Tdef): Tprocdef;
+ var
+ sym : Tprocsym;
+ hashedid : THashedIDString;
+ curreq,
+ besteq : tequaltype;
+ currpd,
+ bestpd : tprocdef;
+ stackitem : psymtablestackitem;
+ begin
+ hashedid.id:='enumerator';
+ besteq:=te_incompatible;
+ bestpd:=nil;
+ stackitem:=symtablestack.stack;
+ while assigned(stackitem) do
+ begin
+ sym:=Tprocsym(stackitem^.symtable.FindWithHash(hashedid));
+ if sym<>nil then
+ begin
+ if sym.typ<>procsym then
+ internalerror(200910241);
+ { if the source type is an alias then this is only the second choice,
+ if you mess with this code, check tw4093 }
+ currpd:=sym.find_procdef_enumerator_operator(from_def,to_def,curreq);
+ if curreq>besteq then
+ begin
+ besteq:=curreq;
+ bestpd:=currpd;
+ if (besteq=te_exact) then
+ break;
+ end;
+ end;
+ stackitem:=stackitem^.next;
+ end;
+ result:=bestpd;
+ end;
+
+
+ function search_system_type(const s: TIDString): ttypesym;
+ var
+ sym : tsym;
+ begin
+ sym:=tsym(systemunit.Find(s));
+ if not assigned(sym) or
+ (sym.typ<>typesym) then
+ cgmessage1(cg_f_unknown_system_type,s);
+ result:=ttypesym(sym);
+ end;
+
+
+ function try_search_system_type(const s: TIDString): ttypesym;
+ var
+ sym : tsym;
+ begin
+ sym:=tsym(systemunit.Find(s));
+ if not assigned(sym) then
+ result:=nil
+ else
+ begin
+ if sym.typ<>typesym then
+ cgmessage1(cg_f_unknown_system_type,s);
+ result:=ttypesym(sym);
+ end;
+ end;
+
+
+ function search_named_unit_globaltype(const unitname, typename: TIDString; throwerror: boolean): ttypesym;
+ var
+ srsymtable: tsymtable;
+ sym: tsym;
+ begin
+ if searchsym_in_named_module(unitname,typename,sym,srsymtable) and
+ (sym.typ=typesym) then
+ begin
+ result:=ttypesym(sym);
+ exit;
+ end
+ else
+ begin
+ if throwerror then
+ cgmessage2(cg_f_unknown_type_in_unit,typename,unitname);
+ result:=nil;
+ end;
+ end;
+
+ function search_last_objectpascal_helper(pd,contextclassh : tabstractrecorddef;out odef : tobjectdef):boolean;
+ var
+ s: string;
+ list: TFPObjectList;
+ i: integer;
+ st: tsymtable;
+ begin
+ result:=false;
+ odef:=nil;
+ { when there are no helpers active currently then we don't need to do
+ anything }
+ if current_module.extendeddefs.count=0 then
+ exit;
+ { no helpers for anonymous types }
+ if not assigned(pd.objrealname) or (pd.objrealname^='') then
+ exit;
+ { if pd is defined inside a procedure we must not use make_mangledname
+ (as a helper may not be defined in a procedure this is no problem...)}
+ st:=pd.owner;
+ while st.symtabletype in [objectsymtable,recordsymtable] do
+ st:=st.defowner.owner;
+ if st.symtabletype=localsymtable then
+ exit;
+ { the mangled name is used as the key for tmodule.extendeddefs }
+ s:=make_mangledname('',pd.symtable,'');
+ list:=TFPObjectList(current_module.extendeddefs.Find(s));
+ if assigned(list) and (list.count>0) then
+ begin
+ i:=list.count-1;
+ repeat
+ odef:=tobjectdef(list[list.count-1]);
+ result:=(odef.owner.symtabletype in [staticsymtable,globalsymtable]) or
+ is_visible_for_object(tobjectdef(list[i]).typesym,contextclassh);
+ dec(i);
+ until result or (i<0);
+ if not result then
+ { just to be sure that noone uses odef }
+ odef:=nil;
+ end;
+ end;
+
+ function search_objectpascal_helper(pd,contextclassh : tabstractrecorddef;const s: string; out srsym: tsym; out srsymtable: tsymtable):boolean;
+
+ var
+ hashedid : THashedIDString;
+ classh : tobjectdef;
+ i : integer;
+ pdef : tprocdef;
+ begin
+ result:=false;
+
+ { if there is no class helper for the class then there is no need to
+ search further }
+ if not search_last_objectpascal_helper(pd,contextclassh,classh) then
+ exit;
+
+ hashedid.id:=s;
+
+ repeat
+ srsymtable:=classh.symtable;
+ srsym:=tsym(srsymtable.FindWithHash(hashedid));
+
+ if srsym<>nil then
+ begin
+ if srsym.typ=propertysym then
+ begin
+ result:=true;
+ exit;
+ end;
+ for i:=0 to tprocsym(srsym).procdeflist.count-1 do
+ begin
+ pdef:=tprocdef(tprocsym(srsym).procdeflist[i]);
+ if not is_visible_for_object(pdef.owner,pdef.visibility,contextclassh) then
+ continue;
+ { we need to know if a procedure references symbols
+ in the static symtable, because then it can't be
+ inlined from outside this unit }
+ if assigned(current_procinfo) and
+ (srsym.owner.symtabletype=staticsymtable) then
+ include(current_procinfo.flags,pi_uses_static_symtable);
+ { the first found method wins }
+ srsym:=tprocdef(tprocsym(srsym).procdeflist[i]).procsym;
+ srsymtable:=srsym.owner;
+ addsymref(srsym);
+ result:=true;
+ exit;
+ end;
+ end;
+
+ { try the helper parent if available }
+ classh:=classh.childof;
+ until classh=nil;
+
+ srsym:=nil;
+ srsymtable:=nil;
+ end;
+
+ function search_objc_helper(pd : tobjectdef;const s : string; out srsym: tsym; out srsymtable: tsymtable):boolean;
+ var
+ hashedid : THashedIDString;
+ stackitem : psymtablestackitem;
+ i : longint;
+ defowner : tobjectdef;
+ begin
+ hashedid.id:=class_helper_prefix+s;
+ stackitem:=symtablestack.stack;
+ while assigned(stackitem) do
+ begin
+ srsymtable:=stackitem^.symtable;
+ srsym:=tsym(srsymtable.FindWithHash(hashedid));
+ if assigned(srsym) then
+ begin
+ if not(srsymtable.symtabletype in [globalsymtable,staticsymtable]) or
+ not(srsym.owner.symtabletype in [globalsymtable,staticsymtable]) or
+ (srsym.typ<>procsym) then
+ internalerror(2009111505);
+ { check whether this procsym includes a helper for this particular class }
+ for i:=0 to tprocsym(srsym).procdeflist.count-1 do
+ begin
+ { does pd inherit from (or is the same as) the class
+ that this method's category extended?
+
+ Warning: this list contains both category and objcclass methods
+ (for id.randommethod), so only check category methods here
+ }
+ defowner:=tobjectdef(tprocdef(tprocsym(srsym).procdeflist[i]).owner.defowner);
+ if (oo_is_classhelper in defowner.objectoptions) and
+ pd.is_related(defowner.childof) then
+ begin
+ { we need to know if a procedure references symbols
+ in the static symtable, because then it can't be
+ inlined from outside this unit }
+ if assigned(current_procinfo) and
+ (srsym.owner.symtabletype=staticsymtable) then
+ include(current_procinfo.flags,pi_uses_static_symtable);
+ { no need to keep looking. There might be other
+ categories that extend this, a parent or child
+ class with a method with the same name (either
+ overriding this one, or overridden by this one),
+ but that doesn't matter as far as the basic
+ procsym is concerned.
+ }
+ srsym:=tprocdef(tprocsym(srsym).procdeflist[i]).procsym;
+ srsymtable:=srsym.owner;
+ addsymref(srsym);
+ result:=true;
+ exit;
+ end;
+ end;
+ end;
+ stackitem:=stackitem^.next;
+ end;
+ srsym:=nil;
+ srsymtable:=nil;
+ result:=false;
+ end;
+
+
+ function search_objc_method(const s : string; out srsym: tsym; out srsymtable: tsymtable):boolean;
+ var
+ hashedid : THashedIDString;
+ stackitem : psymtablestackitem;
+ i : longint;
+ begin
+ hashedid.id:=class_helper_prefix+s;
+ stackitem:=symtablestack.stack;
+ while assigned(stackitem) do
+ begin
+ srsymtable:=stackitem^.symtable;
+ srsym:=tsym(srsymtable.FindWithHash(hashedid));
+ if assigned(srsym) then
+ begin
+ if not(srsymtable.symtabletype in [globalsymtable,staticsymtable]) or
+ not(srsym.owner.symtabletype in [globalsymtable,staticsymtable]) or
+ (srsym.typ<>procsym) then
+ internalerror(2009112005);
+ { check whether this procsym includes a helper for this particular class }
+ for i:=0 to tprocsym(srsym).procdeflist.count-1 do
+ begin
+ { we need to know if a procedure references symbols
+ in the static symtable, because then it can't be
+ inlined from outside this unit }
+ if assigned(current_procinfo) and
+ (srsym.owner.symtabletype=staticsymtable) then
+ include(current_procinfo.flags,pi_uses_static_symtable);
+ { no need to keep looking. There might be other
+ methods with the same name, but that doesn't matter
+ as far as the basic procsym is concerned.
+ }
+ srsym:=tprocdef(tprocsym(srsym).procdeflist[i]).procsym;
+ { We need the symtable in which the classhelper-like sym
+ is located, not the objectdef. The reason is that the
+ callnode will climb the symtablestack until it encounters
+ this symtable to start looking for overloads (and it won't
+ find the objectsymtable in which this method sym is
+ located
+
+ srsymtable:=srsym.owner;
+ }
+ addsymref(srsym);
+ result:=true;
+ exit;
+ end;
+ end;
+ stackitem:=stackitem^.next;
+ end;
+ srsym:=nil;
+ srsymtable:=nil;
+ result:=false;
+ end;
+
+
+ function search_struct_member(pd : tabstractrecorddef;const s : string):tsym;
+ { searches n in symtable of pd and all anchestors }
+ var
+ hashedid : THashedIDString;
+ srsym : tsym;
+ orgpd : tabstractrecorddef;
+ srsymtable : tsymtable;
+ begin
+ { in case this is a formal objcclass, first find the real definition }
+ if (oo_is_formal in pd.objectoptions) then
+ pd:=find_real_objcclass_definition(tobjectdef(pd),true);
+ if search_objectpascal_helper(pd, pd, s, result, srsymtable) then
+ exit;
+ hashedid.id:=s;
+ orgpd:=pd;
+ while assigned(pd) do
+ begin
+ srsym:=tsym(pd.symtable.FindWithHash(hashedid));
+ if assigned(srsym) then
+ begin
+ search_struct_member:=srsym;
+ exit;
+ end;
+ if pd.typ=objectdef then
+ pd:=tobjectdef(pd).childof
+ else
+ pd:=nil;
+ end;
+
+ { not found, now look for class helpers }
+ if is_objcclass(pd) then
+ search_objc_helper(tobjectdef(orgpd),s,result,srsymtable)
+ else
+ result:=nil;
+ end;
+
+
+ function search_macro(const s : string):tsym;
+ var
+ stackitem : psymtablestackitem;
+ hashedid : THashedIDString;
+ srsym : tsym;
+ begin
+ hashedid.id:=s;
+
+ { First search the localmacrosymtable before searching the
+ global macrosymtables from the units }
+ if assigned(current_module) then
+ begin
+ srsym:=tsym(current_module.localmacrosymtable.FindWithHash(hashedid));
+ if assigned(srsym) then
+ begin
+ result:= srsym;
+ exit;
+ end;
+ end;
+
+ stackitem:=macrosymtablestack.stack;
+ while assigned(stackitem) do
+ begin
+ srsym:=tsym(stackitem^.symtable.FindWithHash(hashedid));
+ if assigned(srsym) then
+ begin
+ result:= srsym;
+ exit;
+ end;
+ stackitem:=stackitem^.next;
+ end;
+ result:= nil;
+ end;
+
+
+ function defined_macro(const s : string):boolean;
+ var
+ mac: tmacro;
+ begin
+ mac:=tmacro(search_macro(s));
+ if assigned(mac) then
+ begin
+ mac.is_used:=true;
+ defined_macro:=mac.defined;
+ end
+ else
+ defined_macro:=false;
+ end;
+
+
+{****************************************************************************
+ Object Helpers
+****************************************************************************}
+
+ function search_default_property(pd : tabstractrecorddef) : tpropertysym;
+ { returns the default property of a class, searches also anchestors }
+ var
+ _defaultprop : tpropertysym;
+ helperpd : tobjectdef;
+ begin
+ _defaultprop:=nil;
+ { first search in helper's hierarchy }
+ if search_last_objectpascal_helper(pd,nil,helperpd) then
+ while assigned(helperpd) do
+ begin
+ helperpd.symtable.SymList.ForEachCall(@tstoredsymtable(helperpd.symtable).testfordefaultproperty,@_defaultprop);
+ if assigned(_defaultprop) then
+ break;
+ helperpd:=helperpd.childof;
+ end;
+ if assigned(_defaultprop) then
+ begin
+ search_default_property:=_defaultprop;
+ exit;
+ end;
+ { now search in the type's hierarchy itself }
+ while assigned(pd) do
+ begin
+ pd.symtable.SymList.ForEachCall(@tstoredsymtable(pd.symtable).testfordefaultproperty,@_defaultprop);
+ if assigned(_defaultprop) then
+ break;
+ if (pd.typ=objectdef) then
+ pd:=tobjectdef(pd).childof
+ else
+ break;
+ end;
+ search_default_property:=_defaultprop;
+ end;
+
+
+{****************************************************************************
+ Macro Helpers
+****************************************************************************}
+
+ procedure def_system_macro(const name : string);
+ var
+ mac : tmacro;
+ s: string;
+ begin
+ if name = '' then
+ internalerror(2004121202);
+ s:= upper(name);
+ mac:=tmacro(search_macro(s));
+ if not assigned(mac) then
+ begin
+ mac:=tmacro.create(s);
+ if assigned(current_module) then
+ current_module.localmacrosymtable.insert(mac)
+ else
+ initialmacrosymtable.insert(mac);
+ end;
+ Message1(parser_c_macro_defined,mac.name);
+ mac.defined:=true;
+ end;
+
+
+ procedure set_system_macro(const name, value : string);
+ var
+ mac : tmacro;
+ s: string;
+ begin
+ if name = '' then
+ internalerror(2004121203);
+ s:= upper(name);
+ mac:=tmacro(search_macro(s));
+ if not assigned(mac) then
+ begin
+ mac:=tmacro.create(s);
+ if assigned(current_module) then
+ current_module.localmacrosymtable.insert(mac)
+ else
+ initialmacrosymtable.insert(mac);
+ end
+ else
+ begin
+ mac.is_compiler_var:=false;
+ if assigned(mac.buftext) then
+ freemem(mac.buftext,mac.buflen);
+ end;
+ Message2(parser_c_macro_set_to,mac.name,value);
+ mac.buflen:=length(value);
+ getmem(mac.buftext,mac.buflen);
+ move(value[1],mac.buftext^,mac.buflen);
+ mac.defined:=true;
+ end;
+
+
+ procedure set_system_compvar(const name, value : string);
+ var
+ mac : tmacro;
+ s: string;
+ begin
+ if name = '' then
+ internalerror(2004121204);
+ s:= upper(name);
+ mac:=tmacro(search_macro(s));
+ if not assigned(mac) then
+ begin
+ mac:=tmacro.create(s);
+ mac.is_compiler_var:=true;
+ if assigned(current_module) then
+ current_module.localmacrosymtable.insert(mac)
+ else
+ initialmacrosymtable.insert(mac);
+ end
+ else
+ begin
+ mac.is_compiler_var:=true;
+ if assigned(mac.buftext) then
+ freemem(mac.buftext,mac.buflen);
+ end;
+ Message2(parser_c_macro_set_to,mac.name,value);
+ mac.buflen:=length(value);
+ getmem(mac.buftext,mac.buflen);
+ move(value[1],mac.buftext^,mac.buflen);
+ mac.defined:=true;
+ end;
+
+
+ procedure undef_system_macro(const name : string);
+ var
+ mac : tmacro;
+ s: string;
+ begin
+ if name = '' then
+ internalerror(2004121205);
+ s:= upper(name);
+ mac:=tmacro(search_macro(s));
+ if not assigned(mac) then
+ {If not found, then it's already undefined.}
+ else
+ begin
+ Message1(parser_c_macro_undefined,mac.name);
+ mac.defined:=false;
+ mac.is_compiler_var:=false;
+ { delete old definition }
+ if assigned(mac.buftext) then
+ begin
+ freemem(mac.buftext,mac.buflen);
+ mac.buftext:=nil;
+ end;
+ end;
+ end;
+
+
+{$ifdef UNITALIASES}
+{****************************************************************************
+ TUNIT_ALIAS
+ ****************************************************************************}
+
+ constructor tunit_alias.create(const n:string);
+ var
+ i : longint;
+ begin
+ i:=pos('=',n);
+ if i=0 then
+ fail;
+ inherited createname(Copy(n,1,i-1));
+ newname:=stringdup(Copy(n,i+1,255));
+ end;
+
+
+ destructor tunit_alias.destroy;
+ begin
+ stringdispose(newname);
+ inherited destroy;
+ end;
+
+
+ procedure addunitalias(const n:string);
+ begin
+ unitaliases^.insert(tunit_alias,init(Upper(n))));
+ end;
+
+
+ function getunitalias(const n:string):string;
+ var
+ p : punit_alias;
+ begin
+ p:=punit_alias(unitaliases^.Find(Upper(n)));
+ if assigned(p) then
+ getunitalias:=punit_alias(p).newname^
+ else
+ getunitalias:=n;
+ end;
+{$endif UNITALIASES}
+
+
+{****************************************************************************
+ Init/Done Symtable
+****************************************************************************}
+
+ procedure InitSymtable;
+ begin
+ { Reset symbolstack }
+ symtablestack:=nil;
+ systemunit:=nil;
+ { create error syms and def }
+ generrorsym:=terrorsym.create;
+ generrordef:=terrordef.create;
+ { macros }
+ initialmacrosymtable:=tmacrosymtable.create(false);
+ macrosymtablestack:=TSymtablestack.create;
+ macrosymtablestack.push(initialmacrosymtable);
+{$ifdef UNITALIASES}
+ { unit aliases }
+ unitaliases:=TFPHashObjectList.create;
+{$endif}
+ { set some global vars to nil, might be important for the ide }
+ class_tobject:=nil;
+ interface_iunknown:=nil;
+ interface_idispatch:=nil;
+ rec_tguid:=nil;
+ dupnr:=0;
+ end;
+
+
+ procedure DoneSymtable;
+ begin
+ generrorsym.owner:=nil;
+ generrorsym.free;
+ generrordef.owner:=nil;
+ generrordef.free;
+ initialmacrosymtable.free;
+ macrosymtablestack.free;
+{$ifdef UNITALIASES}
+ unitaliases.free;
+{$endif}
+ end;
+
+end.
diff --git a/closures/compiler/symtype.pas b/closures/compiler/symtype.pas
new file mode 100644
index 0000000000..9b0a70beb1
--- /dev/null
+++ b/closures/compiler/symtype.pas
@@ -0,0 +1,1034 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl, Pierre Muller
+
+ This unit handles the symbol tables
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ ****************************************************************************
+}
+unit symtype;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ { common }
+ cutils,
+ cclasses,
+ { global }
+ globtype,globals,constexp,
+ { symtable }
+ symconst,symbase,
+ { aasm }
+ aasmbase,ppu,cpuinfo
+ ;
+
+ type
+{************************************************
+ Required Forwards
+************************************************}
+
+ tsym = class;
+ Tcompilerppufile=class;
+
+
+{************************************************
+ TDef
+************************************************}
+
+ tgeTSymtable = (gs_none,gs_record,gs_local,gs_para);
+
+ tdef = class(TDefEntry)
+ typesym : tsym; { which type the definition was generated this def }
+ { maybe it's useful to merge the dwarf and stabs debugging info with some hacking }
+ { dwarf debugging }
+ dwarf_lab : tasmsymbol;
+ dwarf_ref_lab : tasmsymbol;
+ { stabs debugging }
+ stab_number : word;
+ dbg_state : tdefdbgstatus;
+ defoptions : tdefoptions;
+ defstates : tdefstates;
+ constructor create(dt:tdeftyp);
+ procedure buildderef;virtual;abstract;
+ procedure buildderefimpl;virtual;abstract;
+ procedure deref;virtual;abstract;
+ procedure derefimpl;virtual;abstract;
+ function typename:string;
+ function GetTypeName:string;virtual;
+ function typesymbolprettyname:string;virtual;
+ function mangledparaname:string;
+ function getmangledparaname:string;virtual;
+ function rtti_mangledname(rt:trttitype):string;virtual;abstract;
+ function OwnerHierarchyName: string; virtual; abstract;
+ function size:asizeint;virtual;abstract;
+ function packedbitsize:asizeint;virtual;
+ function alignment:shortint;virtual;abstract;
+ function getvardef:longint;virtual;abstract;
+ function getparentdef:tdef;virtual;
+ function geTSymtable(t:tgeTSymtable):TSymtable;virtual;
+ function is_publishable:boolean;virtual;abstract;
+ function needs_inittable:boolean;virtual;abstract;
+ function is_related(def:tdef):boolean;virtual;
+ procedure ChangeOwner(st:TSymtable);
+ procedure register_created_object_type;virtual;
+ end;
+
+{************************************************
+ TSym
+************************************************}
+
+ { this object is the base for all symbol objects }
+
+ { tsym }
+
+ tsym = class(TSymEntry)
+ protected
+ public
+ fileinfo : tfileposinfo;
+ { size of fileinfo is 10 bytes, so if a >word aligned type would follow,
+ two bytes of memory would be wasted, so we put two one byte fields over here }
+ visibility : tvisibility;
+ isdbgwritten : boolean;
+ symoptions : tsymoptions;
+ refs : longint;
+ reflist : TLinkedList;
+ { deprecated optionally can have a message }
+ deprecatedmsg: pshortstring;
+ constructor create(st:tsymtyp;const aname:string);
+ destructor destroy;override;
+ function mangledname:string; virtual;
+ function prettyname:string; virtual;
+ procedure buildderef;virtual;
+ procedure deref;virtual;
+ procedure ChangeOwner(st:TSymtable);
+ procedure IncRefCount;
+ procedure IncRefCountBy(AValue : longint);
+ procedure MaybeCreateRefList;
+ procedure AddRef;
+ end;
+
+ tsymarr = array[0..maxlongint div sizeof(pointer)-1] of tsym;
+ psymarr = ^tsymarr;
+
+{************************************************
+ TDeref
+************************************************}
+
+ tderef = object
+ dataidx : longint;
+ procedure reset;
+ procedure build(s:TObject);
+ function resolve:TObject;
+ end;
+
+{************************************************
+ tpropaccesslist
+************************************************}
+
+ ppropaccesslistitem = ^tpropaccesslistitem;
+ tpropaccesslistitem = record
+ sltype : tsltype;
+ next : ppropaccesslistitem;
+ case byte of
+ 0 : (sym : tsym; symderef : tderef);
+ 1 : (value : TConstExprInt; valuedef: tdef; valuedefderef:tderef);
+ 2 : (def: tdef; defderef:tderef);
+ end;
+
+ tpropaccesslist = class
+ procdef : tdef;
+ procdefderef : tderef;
+ firstsym,
+ lastsym : ppropaccesslistitem;
+ constructor create;
+ destructor destroy;override;
+ function empty:boolean;
+ procedure addsym(slt:tsltype;p:tsym);
+ procedure addconst(slt:tsltype;v:TConstExprInt;d:tdef);
+ procedure addtype(slt:tsltype;d:tdef);
+ procedure addsymderef(slt:tsltype;d:tderef);
+ procedure addconstderef(slt:tsltype;v:TConstExprInt;d:tderef);
+ procedure addtypederef(slt:tsltype;d:tderef);
+ procedure clear;
+ procedure resolve;
+ procedure buildderef;
+ end;
+
+{************************************************
+ Tcompilerppufile
+************************************************}
+ tcompilerppufile=class(tppufile)
+ public
+ procedure checkerror;
+ procedure getguid(var g: tguid);
+ function getexprint:Tconstexprint;
+ function getptruint:TConstPtrUInt;
+ procedure getposinfo(var p:tfileposinfo);
+ procedure getderef(var d:tderef);
+ function getpropaccesslist:tpropaccesslist;
+ function getasmsymbol:tasmsymbol;
+ procedure putguid(const g: tguid);
+ procedure putexprint(const v:tconstexprint);
+ procedure PutPtrUInt(v:TConstPtrUInt);
+ procedure putposinfo(const p:tfileposinfo);
+ procedure putderef(const d:tderef);
+ procedure putpropaccesslist(p:tpropaccesslist);
+ procedure putasmsymbol(s:tasmsymbol);
+ end;
+
+{$ifdef MEMDEBUG}
+ var
+ memmanglednames,
+ memprocpara,
+ memprocparast,
+ memproclocalst,
+ memprocnodetree : tmemdebug;
+{$endif MEMDEBUG}
+
+ function FindUnitSymtable(st:TSymtable):TSymtable;
+
+
+implementation
+
+ uses
+ crefs,
+ verbose,
+ fmodule
+ ;
+
+{****************************************************************************
+ Utils
+****************************************************************************}
+
+ function FindUnitSymtable(st:TSymtable):TSymtable;
+ begin
+ result:=nil;
+ repeat
+ if not assigned(st) then
+ internalerror(200602034);
+ case st.symtabletype of
+ localmacrosymtable,
+ exportedmacrosymtable,
+ staticsymtable,
+ globalsymtable :
+ begin
+ result:=st;
+ exit;
+ end;
+ recordsymtable,
+ enumsymtable,
+ arraysymtable,
+ localsymtable,
+ parasymtable,
+ ObjectSymtable :
+ st:=st.defowner.owner;
+ else
+ internalerror(200602035);
+ end;
+ until false;
+ end;
+
+
+{****************************************************************************
+ Tdef
+****************************************************************************}
+
+ constructor tdef.create(dt:tdeftyp);
+ begin
+ inherited create;
+ typ:=dt;
+ owner := nil;
+ typesym := nil;
+ defoptions:=[];
+ dbg_state:=dbg_state_unused;
+ stab_number:=0;
+ end;
+
+
+ function tdef.typename:string;
+ begin
+ result:=OwnerHierarchyName;
+ if assigned(typesym) and
+ not(typ in [procvardef,procdef]) and
+ (typesym.realname[1]<>'$') then
+ result:=result+typesym.realname
+ else
+ result:=result+GetTypeName;
+ end;
+
+
+ function tdef.GetTypeName : string;
+ begin
+ GetTypeName:='<unknown type>'
+ end;
+
+
+ function tdef.typesymbolprettyname:string;
+ begin
+ result:=OwnerHierarchyName;
+ if assigned(typesym) then
+ result:=result+typesym.prettyname
+ else
+ result:=result+'<no type symbol>'
+ end;
+
+
+ function tdef.mangledparaname:string;
+ begin
+ if assigned(typesym) then
+ mangledparaname:=typesym.name
+ else
+ mangledparaname:=getmangledparaname;
+ end;
+
+
+ function tdef.getmangledparaname:string;
+ begin
+ result:='<unknown type>';
+ end;
+
+
+ function tdef.getparentdef:tdef;
+ begin
+ result:=nil;
+ end;
+
+
+ function tdef.geTSymtable(t:tgeTSymtable):TSymtable;
+ begin
+ result:=nil;
+ end;
+
+
+ function tdef.is_related(def:tdef):boolean;
+ begin
+ result:=false;
+ end;
+
+
+ function tdef.packedbitsize:asizeint;
+ begin
+ result:=size * 8;
+ end;
+
+
+ procedure tdef.ChangeOwner(st:TSymtable);
+ begin
+// if assigned(Owner) then
+// Owner.DefList.List[i]:=nil;
+ Owner:=st;
+ Owner.DefList.Add(self);
+ end;
+
+
+ procedure tdef.register_created_object_type;
+ begin
+ end;
+
+{****************************************************************************
+ TSYM (base for all symtypes)
+****************************************************************************}
+
+ constructor tsym.create(st:tsymtyp;const aname:string);
+ begin
+ inherited CreateNotOwned;
+ realname:=aname;
+ typ:=st;
+ RefList:=nil;
+ symoptions:=[];
+ fileinfo:=current_tokenpos;
+ isdbgwritten := false;
+ visibility:=vis_public;
+ deprecatedmsg:=nil;
+ end;
+
+ destructor Tsym.destroy;
+ begin
+ stringdispose(deprecatedmsg);
+ if assigned(RefList) then
+ RefList.Free;
+ inherited Destroy;
+ end;
+
+ procedure Tsym.IncRefCount;
+ begin
+ inc(refs);
+ if cs_browser in current_settings.moduleswitches then
+ begin
+ MaybeCreateRefList;
+ AddRef;
+ end;
+ end;
+
+ procedure Tsym.IncRefCountBy(AValue : longint);
+ begin
+ inc(refs,AValue);
+ end;
+
+ procedure Tsym.MaybeCreateRefList;
+ begin
+ if not assigned(reflist) then
+ reflist:=TRefLinkedList.create;
+ end;
+
+ procedure Tsym.AddRef;
+ var
+ RefItem: TRefItem;
+ begin
+ RefItem:=TRefItem.Create(current_tokenpos);
+ RefList.Concat(RefItem);
+ end;
+
+ procedure Tsym.buildderef;
+ begin
+ end;
+
+
+ procedure Tsym.deref;
+ begin
+ end;
+
+
+ function tsym.mangledname : string;
+ begin
+ internalerror(200204171);
+ result:='';
+ end;
+
+
+ function tsym.prettyname : string;
+ begin
+ result:=realname;
+ end;
+
+
+ procedure tsym.ChangeOwner(st:TSymtable);
+ begin
+ Owner:=st;
+ inherited ChangeOwner(Owner.SymList);
+ end;
+
+
+{****************************************************************************
+ tpropaccesslist
+****************************************************************************}
+
+ constructor tpropaccesslist.create;
+ begin
+ procdef:=nil; { needed for procedures }
+ firstsym:=nil;
+ lastsym:=nil;
+ end;
+
+
+ destructor tpropaccesslist.destroy;
+ begin
+ clear;
+ end;
+
+
+ function tpropaccesslist.empty:boolean;
+ begin
+ empty:=(firstsym=nil);
+ end;
+
+
+ procedure tpropaccesslist.clear;
+ var
+ hp : ppropaccesslistitem;
+ begin
+ while assigned(firstsym) do
+ begin
+ hp:=firstsym;
+ firstsym:=firstsym^.next;
+ dispose(hp);
+ end;
+ firstsym:=nil;
+ lastsym:=nil;
+ procdef:=nil;
+ end;
+
+
+ procedure tpropaccesslist.addsym(slt:tsltype;p:tsym);
+ var
+ hp : ppropaccesslistitem;
+ begin
+ new(hp);
+ fillchar(hp^,sizeof(tpropaccesslistitem),0);
+ hp^.sltype:=slt;
+ hp^.sym:=p;
+ hp^.symderef.reset;
+ if assigned(lastsym) then
+ lastsym^.next:=hp
+ else
+ firstsym:=hp;
+ lastsym:=hp;
+ end;
+
+
+ procedure tpropaccesslist.addconst(slt:tsltype;v:TConstExprInt;d:tdef);
+ var
+ hp : ppropaccesslistitem;
+ begin
+ new(hp);
+ fillchar(hp^,sizeof(tpropaccesslistitem),0);
+ hp^.sltype:=slt;
+ hp^.value:=v;
+ hp^.valuedef:=d;
+ hp^.valuedefderef.reset;
+ if assigned(lastsym) then
+ lastsym^.next:=hp
+ else
+ firstsym:=hp;
+ lastsym:=hp;
+ end;
+
+
+ procedure tpropaccesslist.addtype(slt:tsltype;d:tdef);
+ var
+ hp : ppropaccesslistitem;
+ begin
+ new(hp);
+ fillchar(hp^,sizeof(tpropaccesslistitem),0);
+ hp^.sltype:=slt;
+ hp^.def:=d;
+ hp^.defderef.reset;
+ if assigned(lastsym) then
+ lastsym^.next:=hp
+ else
+ firstsym:=hp;
+ lastsym:=hp;
+ end;
+
+
+ procedure tpropaccesslist.addsymderef(slt:tsltype;d:tderef);
+ begin
+ addsym(slt,nil);
+ lastsym^.symderef:=d;
+ end;
+
+
+ procedure tpropaccesslist.addconstderef(slt:tsltype;v:TConstExprInt;d:tderef);
+ begin
+ addconst(slt,v,nil);
+ lastsym^.valuedefderef:=d;
+ end;
+
+
+ procedure tpropaccesslist.addtypederef(slt:tsltype;d:tderef);
+ begin
+ addtype(slt,nil);
+ lastsym^.defderef:=d;
+ end;
+
+
+ procedure tpropaccesslist.resolve;
+ var
+ hp : ppropaccesslistitem;
+ begin
+ procdef:=tdef(procdefderef.resolve);
+ hp:=firstsym;
+ while assigned(hp) do
+ begin
+ case hp^.sltype of
+ sl_call,
+ sl_load,
+ sl_subscript :
+ hp^.sym:=tsym(hp^.symderef.resolve);
+ sl_absolutetype,
+ sl_typeconv :
+ hp^.def:=tdef(hp^.defderef.resolve);
+ sl_vec:
+ hp^.valuedef:=tdef(hp^.valuedefderef.resolve);
+ else
+ internalerror(200110205);
+ end;
+ hp:=hp^.next;
+ end;
+ end;
+
+
+ procedure tpropaccesslist.buildderef;
+ var
+ hp : ppropaccesslistitem;
+ begin
+ procdefderef.build(procdef);
+ hp:=firstsym;
+ while assigned(hp) do
+ begin
+ case hp^.sltype of
+ sl_call,
+ sl_load,
+ sl_subscript :
+ hp^.symderef.build(hp^.sym);
+ sl_absolutetype,
+ sl_typeconv :
+ hp^.defderef.build(hp^.def);
+ sl_vec:
+ hp^.valuedefderef.build(hp^.valuedef);
+ else
+ internalerror(200110205);
+ end;
+ hp:=hp^.next;
+ end;
+ end;
+
+
+{****************************************************************************
+ Tderef
+****************************************************************************}
+
+
+ procedure tderef.reset;
+ begin
+ dataidx:=-1;
+ end;
+
+
+ procedure tderef.build(s:TObject);
+ var
+ len : byte;
+ st : TSymtable;
+ data : array[0..255] of byte;
+ idx : word;
+ begin
+ { skip length byte }
+ len:=1;
+
+ if assigned(s) then
+ begin
+{ TODO: ugly hack}
+ if s is tsym then
+ st:=FindUnitSymtable(tsym(s).owner)
+ else
+ st:=FindUnitSymtable(tdef(s).owner);
+ if not st.iscurrentunit then
+ begin
+ { register that the unit is needed for resolving }
+ data[len]:=ord(deref_unit);
+ idx:=current_module.derefidx_unit(st.moduleid);
+ data[len+1]:=idx shr 8 and $ff;
+ data[len+2]:=idx and $ff;
+ inc(len,3);
+ end;
+ if s is tsym then
+ begin
+ data[len]:=ord(deref_symid);
+ data[len+1]:=tsym(s).symid shr 24 and $ff;
+ data[len+2]:=tsym(s).symid shr 16 and $ff;
+ data[len+3]:=tsym(s).symid shr 8 and $ff;
+ data[len+4]:=tsym(s).symid and $ff;
+ inc(len,5);
+ end
+ else
+ begin
+ data[len]:=ord(deref_defid);
+ data[len+1]:=tdef(s).defid shr 24 and $ff;
+ data[len+2]:=tdef(s).defid shr 16 and $ff;
+ data[len+3]:=tdef(s).defid shr 8 and $ff;
+ data[len+4]:=tdef(s).defid and $ff;
+ inc(len,5);
+ end;
+ end
+ else
+ begin
+ { nil pointer }
+ data[len]:=ord(deref_nil);
+ inc(len);
+ end;
+
+ { store data length in first byte }
+ data[0]:=len-1;
+
+ { store index and write to derefdata }
+ dataidx:=current_module.derefdata.size;
+ current_module.derefdata.write(data,len);
+ end;
+
+
+ function tderef.resolve:TObject;
+ var
+ pm : tmodule;
+ typ : tdereftype;
+ idx : longint;
+ i : aint;
+ len : byte;
+ data : array[0..255] of byte;
+ begin
+ result:=nil;
+ { not initialized or error }
+ if dataidx<0 then
+ internalerror(200306067);
+ { read data }
+ current_module.derefdata.seek(dataidx);
+ if current_module.derefdata.read(len,1)<>1 then
+ internalerror(200310221);
+ if len>0 then
+ begin
+ if current_module.derefdata.read(data,len)<>len then
+ internalerror(200310222);
+ end;
+ { process data }
+ pm:=current_module;
+ i:=0;
+ while (i<len) do
+ begin
+ typ:=tdereftype(data[i]);
+ inc(i);
+ case typ of
+ deref_unit :
+ begin
+ idx:=(data[i] shl 8) or data[i+1];
+ inc(i,2);
+ pm:=current_module.resolve_unit(idx);
+ end;
+ deref_defid :
+ begin
+ idx:=longint((data[i] shl 24) or (data[i+1] shl 16) or (data[i+2] shl 8) or data[i+3]);
+ inc(i,4);
+ result:=tdef(pm.deflist[idx]);
+ end;
+ deref_symid :
+ begin
+ idx:=longint((data[i] shl 24) or (data[i+1] shl 16) or (data[i+2] shl 8) or data[i+3]);
+ inc(i,4);
+ result:=tsym(pm.symlist[idx]);
+ end;
+ deref_nil :
+ begin
+ result:=nil;
+ { Only allowed when no other deref is available }
+ if len<>1 then
+ internalerror(200306232);
+ end;
+ else
+ internalerror(200212277);
+ end;
+ end;
+ end;
+
+
+{*****************************************************************************
+ TCompilerPPUFile
+*****************************************************************************}
+
+ procedure tcompilerppufile.checkerror;
+ begin
+ if error then
+ Message(unit_f_ppu_read_error);
+ end;
+
+
+ procedure tcompilerppufile.getguid(var g: tguid);
+ begin
+ longint(g.d1):=getlongint;
+ g.d2:=getword;
+ g.d3:=getword;
+ getdata(g.d4,sizeof(g.d4));
+ end;
+
+
+ function tcompilerppufile.getexprint:Tconstexprint;
+
+ begin
+ getexprint.overflow:=false;
+ getexprint.signed:=boolean(getbyte);
+ getexprint.svalue:=getint64;
+ end;
+
+
+ function tcompilerppufile.getPtrUInt:TConstPtrUInt;
+ begin
+ {$if sizeof(TConstPtrUInt)=8}
+ result:=tconstptruint(getint64);
+ {$else}
+ result:=TConstPtrUInt(getlongint);
+ {$endif}
+ end;
+
+
+ procedure tcompilerppufile.getposinfo(var p:tfileposinfo);
+ var
+ info : byte;
+ begin
+ {
+ info byte layout in bits:
+ 0-1 - amount of bytes for fileindex
+ 2-3 - amount of bytes for line
+ 4-5 - amount of bytes for column
+ }
+ info:=getbyte;
+ case (info and $03) of
+ 0 : p.fileindex:=getbyte;
+ 1 : p.fileindex:=getword;
+ 2 : p.fileindex:=(getbyte shl 16) or getword;
+ 3 : p.fileindex:=getlongint;
+ end;
+ case ((info shr 2) and $03) of
+ 0 : p.line:=getbyte;
+ 1 : p.line:=getword;
+ 2 : p.line:=(getbyte shl 16) or getword;
+ 3 : p.line:=getlongint;
+ end;
+ case ((info shr 4) and $03) of
+ 0 : p.column:=getbyte;
+ 1 : p.column:=getword;
+ 2 : p.column:=(getbyte shl 16) or getword;
+ 3 : p.column:=getlongint;
+ end;
+ p.moduleindex:=current_module.unit_index;
+ end;
+
+
+ procedure tcompilerppufile.getderef(var d:tderef);
+ begin
+ d.dataidx:=getlongint;
+ end;
+
+
+ function tcompilerppufile.getpropaccesslist:tpropaccesslist;
+ var
+ hderef : tderef;
+ slt : tsltype;
+ idx : longint;
+ p : tpropaccesslist;
+ begin
+ p:=tpropaccesslist.create;
+ getderef(p.procdefderef);
+ repeat
+ slt:=tsltype(getbyte);
+ case slt of
+ sl_none :
+ break;
+ sl_call,
+ sl_load,
+ sl_subscript :
+ begin
+ getderef(hderef);
+ p.addsymderef(slt,hderef);
+ end;
+ sl_absolutetype,
+ sl_typeconv :
+ begin
+ getderef(hderef);
+ p.addtypederef(slt,hderef);
+ end;
+ sl_vec :
+ begin
+ idx:=getlongint;
+ getderef(hderef);
+ p.addconstderef(slt,idx,hderef);
+ end;
+ else
+ internalerror(200110204);
+ end;
+ until false;
+ getpropaccesslist:=tpropaccesslist(p);
+ end;
+
+
+ function tcompilerppufile.getasmsymbol:tasmsymbol;
+ begin
+ getlongint;
+ getasmsymbol:=nil;
+ end;
+
+
+ procedure tcompilerppufile.putposinfo(const p:tfileposinfo);
+ var
+ oldcrc : boolean;
+ info : byte;
+ begin
+ { posinfo is not relevant for changes in PPU }
+ oldcrc:=do_crc;
+ do_crc:=false;
+ {
+ info byte layout in bits:
+ 0-1 - amount of bytes for fileindex
+ 2-3 - amount of bytes for line
+ 4-5 - amount of bytes for column
+ }
+ info:=0;
+ { calculate info byte }
+ if (p.fileindex>$ff) then
+ begin
+ info:=info or $1;
+ { uncomment this code if tfileposinfo.fileindex type was changed
+ if (p.fileindex<=$ffff) then
+ info:=info or $1
+ else
+ if (p.fileindex<=$ffffff) then
+ info:=info or $2
+ else
+ info:=info or $3;
+ }
+ end;
+ if (p.line>$ff) then
+ begin
+ if (p.line<=$ffff) then
+ info:=info or $4
+ else
+ if (p.line<=$ffffff) then
+ info:=info or $8
+ else
+ info:=info or $c;
+ end;
+ if (p.column>$ff) then
+ begin
+ info:=info or $10;
+ { uncomment this code if tfileposinfo.column type was changed
+ if (p.column<=$ffff) then
+ info:=info or $10
+ else
+ if (p.column<=$ffffff) then
+ info:=info or $20
+ else
+ info:=info or $30;
+ }
+ end;
+ { write data }
+ putbyte(info);
+ case (info and $03) of
+ 0 : putbyte(p.fileindex);
+ 1 : putword(p.fileindex);
+ 2 : begin
+ putbyte(p.fileindex shr 16);
+ putword(p.fileindex and $ffff);
+ end;
+ 3 : putlongint(p.fileindex);
+ end;
+ case ((info shr 2) and $03) of
+ 0 : putbyte(p.line);
+ 1 : putword(p.line);
+ 2 : begin
+ putbyte(p.line shr 16);
+ putword(p.line and $ffff);
+ end;
+ 3 : putlongint(p.line);
+ end;
+ case ((info shr 4) and $03) of
+ 0 : putbyte(p.column);
+ 1 : putword(p.column);
+ 2 : begin
+ putbyte(p.column shr 16);
+ putword(p.column and $ffff);
+ end;
+ 3 : putlongint(p.column);
+ end;
+ do_crc:=oldcrc;
+ end;
+
+
+ procedure tcompilerppufile.putguid(const g: tguid);
+ begin
+ putlongint(longint(g.d1));
+ putword(g.d2);
+ putword(g.d3);
+ putdata(g.d4,sizeof(g.d4));
+ end;
+
+
+ procedure Tcompilerppufile.putexprint(const v:Tconstexprint);
+
+ begin
+ if v.overflow then
+ internalerror(200706102);
+ putbyte(byte(v.signed));
+ putint64(v.svalue);
+ end;
+
+
+ procedure tcompilerppufile.PutPtrUInt(v:TConstPtrUInt);
+ begin
+ {$if sizeof(TConstPtrUInt)=8}
+ putint64(int64(v));
+ {$else}
+ putlongint(longint(v));
+ {$endif}
+ end;
+
+
+ procedure tcompilerppufile.putderef(const d:tderef);
+ var
+ oldcrc : boolean;
+ begin
+ oldcrc:=do_crc;
+ do_crc:=false;
+ putlongint(d.dataidx);
+ do_crc:=oldcrc;
+ end;
+
+
+ procedure tcompilerppufile.putpropaccesslist(p:tpropaccesslist);
+ var
+ hp : ppropaccesslistitem;
+ begin
+ putderef(p.procdefderef);
+ hp:=p.firstsym;
+ while assigned(hp) do
+ begin
+ putbyte(byte(hp^.sltype));
+ case hp^.sltype of
+ sl_call,
+ sl_load,
+ sl_subscript :
+ putderef(hp^.symderef);
+ sl_absolutetype,
+ sl_typeconv :
+ putderef(hp^.defderef);
+ sl_vec :
+ begin
+ putlongint(int64(hp^.value));
+ putderef(hp^.valuedefderef);
+ end;
+ else
+ internalerror(200110205);
+ end;
+ hp:=hp^.next;
+ end;
+ putbyte(byte(sl_none));
+ end;
+
+
+ procedure tcompilerppufile.putasmsymbol(s:tasmsymbol);
+ begin
+ putlongint(0);
+ end;
+
+{$ifdef MEMDEBUG}
+initialization
+ memmanglednames:=TMemDebug.create('Manglednames');
+ memmanglednames.stop;
+ memprocpara:=TMemDebug.create('ProcPara');
+ memprocpara.stop;
+ memprocparast:=TMemDebug.create('ProcParaSt');
+ memprocparast.stop;
+ memproclocalst:=TMemDebug.create('ProcLocalSt');
+ memproclocalst.stop;
+ memprocnodetree:=TMemDebug.create('ProcNodeTree');
+ memprocnodetree.stop;
+
+finalization
+ memmanglednames.free;
+ memprocpara.free;
+ memprocparast.free;
+ memproclocalst.free;
+ memprocnodetree.free;
+{$endif MEMDEBUG}
+
+end.
+
diff --git a/closures/compiler/symutil.pas b/closures/compiler/symutil.pas
new file mode 100644
index 0000000000..ec560824e8
--- /dev/null
+++ b/closures/compiler/symutil.pas
@@ -0,0 +1,97 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit provides some help routines for symbol handling
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit symutil;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ symbase,symtype,symsym;
+
+ function is_funcret_sym(p:TSymEntry):boolean;
+
+ function equal_constsym(sym1,sym2:tconstsym):boolean;
+
+
+implementation
+
+ uses
+ cclasses,
+ globtype,cpuinfo,procinfo,constexp,
+ symconst,widestr;
+
+
+ function is_funcret_sym(p:TSymEntry):boolean;
+ begin
+ is_funcret_sym:=(p.typ in [absolutevarsym,localvarsym,paravarsym]) and
+ (vo_is_funcret in tabstractvarsym(p).varoptions);
+ end;
+
+
+ function equal_constsym(sym1,sym2:tconstsym):boolean;
+ var
+ p1,p2,pend : pchar;
+ begin
+ equal_constsym:=false;
+ if sym1.consttyp<>sym2.consttyp then
+ exit;
+ case sym1.consttyp of
+ constord :
+ equal_constsym:=(sym1.value.valueord=sym2.value.valueord);
+ constpointer :
+ equal_constsym:=(sym1.value.valueordptr=sym2.value.valueordptr);
+ conststring,constresourcestring :
+ begin
+ if sym1.value.len=sym2.value.len then
+ begin
+ p1:=pchar(sym1.value.valueptr);
+ p2:=pchar(sym2.value.valueptr);
+ pend:=p1+sym1.value.len;
+ while (p1<pend) do
+ begin
+ if p1^<>p2^ then
+ break;
+ inc(p1);
+ inc(p2);
+ end;
+ if (p1=pend) then
+ equal_constsym:=true;
+ end;
+ end;
+ constwstring :
+ begin
+ if (sym1.value.len=sym2.value.len) and
+ (comparewidestrings(sym1.value.valueptr,sym2.value.valueptr)=0) then
+ equal_constsym:=true;
+ end;
+ constreal :
+ equal_constsym:=(pbestreal(sym1.value.valueptr)^=pbestreal(sym2.value.valueptr)^);
+ constset :
+ equal_constsym:=(pnormalset(sym1.value.valueptr)^=pnormalset(sym2.value.valueptr)^);
+ constnil :
+ equal_constsym:=true;
+ end;
+ end;
+
+end.
+
diff --git a/closures/compiler/systems.inc b/closures/compiler/systems.inc
new file mode 100644
index 0000000000..6bcbfff07f
--- /dev/null
+++ b/closures/compiler/systems.inc
@@ -0,0 +1,216 @@
+{
+ Copyright (c) 1998-2008 by Florian Klaempfl
+
+ This include contains the enumeration
+ information about the target systems supported
+ (these are not processor specific)
+
+ This program is free software; you can redistribute it and/or modify
+ iu under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge- MA 02139, USA.
+
+ ****************************************************************************
+}
+ type
+ tendian = (endian_little,endian_big);
+
+ (*
+ IMPORTANT NOTE:
+ The value of this enumeration is stored in PPU files.
+ Therefore adding new CPU targets should not change the
+ values of the pre-existing targets. (CEC)
+ FURTHERMORE : Make sure that this branch values, are
+ consistant with the main branch version always.
+ *)
+ tsystemcpu=
+ (
+ cpu_no, { 0 }
+ cpu_i386, { 1 }
+ cpu_m68k, { 2 }
+ cpu_alpha, { 3 }
+ cpu_powerpc, { 4 }
+ cpu_sparc, { 5 }
+ cpu_vm, { 6 }
+ cpu_iA64, { 7 }
+ cpu_x86_64, { 8 }
+ cpu_mips, { 9 }
+ cpu_arm, { 10 }
+ cpu_powerpc64, { 11 }
+ cpu_avr, { 12 }
+ cpu_mipsel { 13 }
+ );
+
+ tasmmode= (asmmode_none
+ { standard assembler (cpu dependant) with full parsing }
+ ,asmmode_standard
+ ,asmmode_i386_att
+ ,asmmode_i386_intel
+ ,asmmode_ppc_gas
+ ,asmmode_ppc_motorola
+ ,asmmode_arm_gas
+ ,asmmode_sparc_gas
+ ,asmmode_x86_64_gas
+ ,asmmode_m68k_mot
+ ,asmmode_x86_64_intel
+ ,asmmode_x86_64_att
+ ,asmmode_avr_gas
+ );
+
+ (* IMPORTANT NOTE:
+ the integer value of this enum is stored in PPU
+ files to recognize the target, so if you add new targets
+ allways add them at end PM
+ FURTHERMORE : Make sure that this branch values are
+ consistant with the main branch version always. (CEC)
+ *)
+ type
+ tsystem =
+ (
+ system_none, { 0 }
+ obsolete_system_i386_GO32V1,{ 1 }
+ system_i386_GO32V2, { 2 }
+ system_i386_linux, { 3 }
+ system_i386_OS2, { 4 }
+ system_i386_Win32, { 5 }
+ system_i386_freebsd, { 6 }
+ system_m68k_Amiga, { 7 }
+ system_m68k_Atari, { 8 }
+ system_m68k_Mac, { 9 }
+ system_m68k_linux, { 10 }
+ system_m68k_PalmOS, { 11 }
+ system_alpha_linux, { 12 }
+ system_powerpc_linux, { 13 }
+ system_powerpc_macos, { 14 }
+ system_i386_solaris, { 15 }
+ system_i386_beos, { 16 }
+ system_i386_netbsd, { 17 }
+ system_m68k_netbsd, { 18 }
+ system_i386_Netware, { 19 }
+ system_i386_qnx, { 20 }
+ system_i386_wdosx, { 21 }
+ system_sparc_solaris, { 22 }
+ system_sparc_linux, { 23 }
+ system_i386_openbsd, { 24 }
+ system_m68k_openbsd, { 25 }
+ system_x86_64_linux, { 26 }
+ system_powerpc_darwin, { 27 }
+ system_i386_EMX, { 28 }
+ system_powerpc_netbsd, { 29 }
+ system_powerpc_openbsd, { 30 }
+ system_arm_linux, { 31 }
+ system_i386_watcom, { 32 }
+ system_powerpc_MorphOS, { 33 }
+ system_x86_64_freebsd, { 34 }
+ system_i386_netwlibc, { 35 }
+ system_powerpc_Amiga, { 36 }
+ system_x86_64_win64, { 37 }
+ system_arm_wince, { 38 }
+ system_ia64_win64, { 39 }
+ system_i386_wince, { 40 }
+ system_x86_6432_linux, { 41 }
+ system_arm_gba, { 42 }
+ system_powerpc64_linux, { 43 }
+ system_i386_darwin, { 44 }
+ system_arm_palmos, { 45 }
+ system_powerpc64_darwin, { 46 }
+ system_arm_nds, { 47 }
+ system_i386_embedded, { 48 }
+ system_m68k_embedded, { 49 }
+ system_alpha_embedded, { 50 }
+ system_powerpc_embedded, { 51 }
+ system_sparc_embedded, { 52 }
+ system_vm_embedded, { 53 }
+ system_iA64_embedded, { 54 }
+ system_x86_64_embedded, { 55 }
+ system_mips_embedded, { 56 }
+ system_arm_embedded, { 57 }
+ system_powerpc64_embedded, { 58 }
+ system_i386_symbian, { 59 }
+ system_arm_symbian, { 60 }
+ system_x86_64_darwin, { 61 }
+ system_avr_embedded, { 62 }
+ system_i386_haiku, { 63 }
+ system_arm_darwin, { 64 }
+ system_x86_64_solaris, { 65 }
+ system_mips_linux, { 66 }
+ system_mipsel_linux, { 67 }
+ system_i386_nativent, { 68 }
+ system_i386_iphonesim, { 69 }
+ system_powerpc_wii { 70 }
+ );
+
+ type
+ tasm = (as_none
+ ,as_gas { standard gnu assembler }
+ ,as_i386_as_aout
+ ,as_i386_nasmcoff
+ ,as_i386_nasmwin32
+ ,as_i386_nasmwdosx
+ ,as_i386_nasmelf
+ ,as_i386_nasmobj
+ ,as_i386_nasmbeos
+ ,as_i386_tasm
+ ,as_i386_masm
+ ,as_i386_wasm
+ ,as_i386_coff
+ ,as_i386_pecoff
+ ,as_i386_elf32
+ ,as_i386_pecoffwdosx
+ ,as_m68k_mit
+ ,as_powerpc_mpw
+ ,as_darwin
+ ,as_i386_macho
+ ,as_x86_64_masm
+ ,as_x86_64_pecoff
+ ,as_i386_pecoffwince
+ ,as_arm_pecoffwince
+ ,as_x86_64_elf64
+ ,as_sparc_elf32
+ ,as_ggas { gnu assembler called "gas" instead of "as" }
+ ,as_i386_nasmhaiku
+ ,as_powerpc_vasm
+ ,as_i386_nlmcoff
+ );
+
+ tar = (ar_none
+ ,ar_gnu_ar
+ ,ar_mpw_ar
+ ,ar_gnu_ar_scripted
+ ,ar_gnu_gar
+ );
+
+ tres = (res_none
+ ,res_gnu_windres,res_watcom_wrc_os2
+ ,res_m68k_palmos,res_m68k_mpw
+ ,res_powerpc_mpw,res_elf
+ ,res_win64_gorc, res_macho, res_ext
+ );
+
+ tresinfoflags = (res_external_file,res_arch_in_file_name
+ ,res_single_file);
+
+ tdbg = (dbg_none
+ ,dbg_stabs,dbg_dwarf2,dbg_dwarf3,dbg_dwarf4
+ );
+
+ tscripttype = (script_none
+ ,script_dos,script_unix,script_amiga,
+ script_mpw
+ );
+
+ tabi = (abi_default
+ ,abi_powerpc_sysv,abi_powerpc_aix
+ ,abi_eabi,abi_armeb
+ );
+
+
diff --git a/closures/compiler/systems.pas b/closures/compiler/systems.pas
new file mode 100644
index 0000000000..63aaa9cab2
--- /dev/null
+++ b/closures/compiler/systems.pas
@@ -0,0 +1,872 @@
+{
+ Copyright (c) 1998-2008 by Florian Klaempfl
+
+ This unit contains information about the target systems supported
+ (these are not processor specific)
+
+ This program is free software; you can redistribute it and/or modify
+ iu under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge- MA 02139, USA.
+
+ ****************************************************************************
+}
+unit systems;
+
+{$i fpcdefs.inc}
+
+interface
+
+{$i systems.inc}
+
+{*****************************************************************************
+ Structures
+*****************************************************************************}
+
+ type
+ { Abstract linker class which is implemented in link module }
+ TAbstractLinker = class
+ end;
+
+ TAbstractLinkerClass = class of TAbstractLinker;
+
+
+ { Abstract assembler class which is implemented in assemble module }
+ TAbstractAssembler = class
+ end;
+
+ TAbstractAssemblerClass = class of TAbstractAssembler;
+
+
+ TAbstractResourceFile = class
+ constructor create(const fn : ansistring);virtual;abstract;
+ end;
+ TAbstractResourceFileClass = class of TAbstractResourceFile;
+
+
+ palignmentinfo = ^talignmentinfo;
+ { this is written to ppus during token recording for generics so it must be packed }
+ talignmentinfo = packed record
+ procalign,
+ loopalign,
+ jumpalign,
+ constalignmin,
+ constalignmax,
+ varalignmin,
+ varalignmax,
+ localalignmin,
+ localalignmax,
+ recordalignmin,
+ recordalignmax,
+ maxCrecordalign : longint;
+ end;
+
+ tasmflags = (af_none,
+ af_outputbinary,af_allowdirect,
+ af_needar,af_smartlink_sections,
+ af_labelprefix_only_inside_procedure,
+ af_supports_dwarf,
+ af_no_debug,
+ af_stabs_use_function_absolute_addresses
+ );
+
+ pasminfo = ^tasminfo;
+ tasminfo = record
+ id : tasm;
+ idtxt : string[12];
+ asmbin : string[8];
+ asmcmd : string[50];
+ supported_targets : set of tsystem;
+ flags : set of tasmflags;
+ labelprefix : string[3];
+ comment : string[3];
+ end;
+
+ parinfo = ^tarinfo;
+ tarinfo = record
+ id : tar;
+ arcmd : string[50];
+ arfinishcmd : string[10];
+ end;
+
+ presinfo = ^tresinfo;
+ tresinfo = record
+ id : tres;
+ { Compiler for resource (.rc or .res) to obj }
+ resbin : string[10];
+ rescmd : string[50];
+ { Optional compiler for resource script (.rc) to binary resource (.res). }
+ { If it is not provided resbin and rescmd will be used. }
+ rcbin : string[10];
+ rccmd : string[50];
+ resourcefileclass : TAbstractResourceFileClass;
+ resflags : set of tresinfoflags;
+ end;
+
+ pdbginfo = ^tdbginfo;
+ tdbginfo = record
+ id : tdbg;
+ idtxt : string[12];
+ end;
+
+ tsystemflags = (tf_none,
+ tf_under_development,
+ tf_need_export,
+ tf_needs_isconsole,
+ tf_code_small,
+ tf_static_reg_based,
+ tf_needs_symbol_size,
+ tf_smartlink_sections,
+ tf_smartlink_library,
+ tf_needs_dwarf_cfi,
+ tf_use_8_3,
+ tf_pic_uses_got,
+ tf_library_needs_pic,
+ tf_needs_symbol_type,
+ tf_section_threadvars,
+ tf_files_case_sensitive,
+ tf_files_case_aware,
+ tf_p_ext_support,
+ tf_has_dllscanner,
+ tf_use_function_relative_addresses,
+ tf_winlikewidestring,
+ tf_dwarf_relative_addresses, // use offsets where the Dwarf spec requires this instead of absolute addresses (the latter is needed by Linux binutils)
+ tf_dwarf_only_local_labels, // only use local labels inside the Dwarf debug_info section (needed for e.g. Darwin)
+ tf_requires_proper_alignment,
+ tf_no_pic_supported,
+ tf_pic_default,
+ { the os does some kind of stack checking and it can be converted into a rte 202 }
+ tf_no_generic_stackcheck,
+ tf_has_winlike_resources,
+ tf_safecall_clearstack, // With this flag set, after safecall calls the caller cleans up the stack
+ tf_safecall_exceptions, // Exceptions in safecall calls are not raised, but passed to the caller as an ordinal (hresult) in the function result.
+ // The original result (if it exists) is passed as an extra parameter
+ tf_no_backquote_support
+ );
+
+ psysteminfo = ^tsysteminfo;
+ { using packed causes bus errors on processors which require alignment }
+ tsysteminfo = record
+ system : tsystem;
+ name : string[34];
+ shortname : string[9];
+ flags : set of tsystemflags;
+ cpu : tsystemcpu;
+ unit_env : string[16];
+ extradefines : string[40];
+ exeext,
+ defext,
+ scriptext,
+ smartext,
+ unitext,
+ unitlibext,
+ asmext,
+ objext,
+ resext : string[4];
+ resobjext : string[7];
+ sharedlibext : string[10];
+ staticlibext,
+ staticlibprefix : string[4];
+ sharedlibprefix : string[4];
+ sharedClibext : string[10];
+ staticClibext,
+ staticClibprefix : string[4];
+ sharedClibprefix : string[4];
+ importlibprefix : string[10];
+ importlibext : string[4];
+ Cprefix : string[2];
+ newline : string[2];
+ dirsep : char;
+ assem : tasm;
+ assemextern : tasm; { external assembler, used by -a }
+ link : tabstractlinkerclass;
+ linkextern : tabstractlinkerclass; { external linker, used by -s }
+ ar : tar;
+ res : tres;
+ dbg : tdbg;
+ script : tscripttype;
+ endian : tendian;
+ alignment : talignmentinfo;
+ {
+ Offset from the argument pointer register to the first
+ argument's address. On some machines it may depend on
+ the data type of the function.
+ (see also FIRST_PARM_OFFSET in GCC source)
+ }
+ first_parm_offset : longint;
+ stacksize : longint;
+ abi : tabi;
+ end;
+
+ const
+ { alias for supported_target field in tasminfo }
+ system_any = system_none;
+
+ systems_wince = [system_arm_wince,system_i386_wince];
+ systems_linux = [system_i386_linux,system_x86_64_linux,system_powerpc_linux,system_powerpc64_linux,
+ system_arm_linux,system_sparc_linux,system_alpha_linux,system_m68k_linux,
+ system_x86_6432_linux,system_mips_linux,system_mipsel_linux];
+ systems_freebsd = [system_i386_freebsd,
+ system_x86_64_freebsd];
+ systems_netbsd = [system_i386_netbsd,
+ system_m68k_netbsd,
+ system_powerpc_netbsd];
+ systems_openbsd = [system_i386_openbsd];
+
+ systems_bsd = systems_freebsd + systems_netbsd + systems_openbsd;
+
+ { all real windows systems, no cripple ones like wince, wdosx et. al. }
+ systems_windows = [system_i386_win32,system_x86_64_win64,system_ia64_win64];
+
+ { all windows systems }
+ systems_all_windows = [system_i386_win32,system_x86_64_win64,system_ia64_win64,
+ system_arm_wince,system_i386_wince];
+
+ { all darwin systems }
+ systems_darwin = [system_powerpc_darwin,system_i386_darwin,
+ system_powerpc64_darwin,system_x86_64_darwin,
+ system_arm_darwin,system_i386_iphonesim];
+
+ {all solaris systems }
+ systems_solaris = [system_sparc_solaris, system_i386_solaris,
+ system_x86_64_solaris];
+
+ { all embedded systems }
+ systems_embedded = [system_i386_embedded,system_m68k_embedded,
+ system_alpha_embedded,system_powerpc_embedded,
+ system_sparc_embedded,system_vm_embedded,
+ system_iA64_embedded,system_x86_64_embedded,
+ system_mips_embedded,system_arm_embedded,
+ system_powerpc64_embedded,system_avr_embedded];
+
+ { all systems that allow section directive }
+ systems_allow_section = systems_embedded;
+
+ systems_allow_section_no_semicolon = systems_allow_section
+{$ifndef DISABLE_TLS_DIRECTORY}
+ + systems_windows
+{$endif not DISABLE_TLS_DIRECTORY}
+ ;
+
+ { all symbian systems }
+ systems_symbian = [system_i386_symbian,system_arm_symbian];
+
+ { all classic Mac OS targets }
+ systems_macos = [system_m68k_Mac,system_powerpc_Macos];
+
+ { all OS/2 targets }
+ systems_os2 = [system_i386_OS2,system_i386_emx];
+
+ { all native nt systems }
+ systems_nativent = [system_i386_nativent];
+
+ { systems supporting Objective-C }
+ systems_objc_supported = systems_darwin;
+
+ { systems using the non-fragile Objective-C ABI }
+ systems_objc_nfabi = [system_powerpc64_darwin,system_x86_64_darwin,system_arm_darwin,system_i386_iphonesim];
+
+ { all systems supporting exports from programs or units }
+ systems_unit_program_exports = [system_i386_win32,
+ system_i386_wdosx,
+ system_i386_Netware,
+ system_i386_netwlibc,
+ system_arm_wince,
+ system_x86_64_win64,
+ system_ia64_win64]+systems_linux;
+
+ { all systems for which weak linking has been tested/is supported }
+ systems_weak_linking = systems_darwin + systems_solaris;
+
+ systems_internal_sysinit = [system_i386_linux,system_i386_win32];
+
+ {$ifdef FPC_HAS_SYSTEMS_INTERRUPT_TABLE}
+ { If anyone wants to use interrupt for
+ a specific target, add a
+ $define FPC_HAS_SYSTEMS_INTERRUPT_TABLE
+ to fpcdefs.inc to reactivate
+ the corresponding code }
+ systems_interrupt_table = [{system_arm_embedded}];
+ {$endif FPC_HAS_SYSTEMS_INTERRUPT_TABLE}
+
+ { all systems for which istack must be at a 16 byte boundary
+ when calling a function }
+ systems_need_16_byte_stack_alignment = [
+ system_i386_darwin,
+ system_i386_iphonesim,
+ system_x86_64_darwin,
+ system_x86_64_win64,
+ system_x86_64_linux,
+ system_x86_64_freebsd,
+ system_x86_64_solaris];
+
+ cpu2str : array[TSystemCpu] of string[10] =
+ ('','i386','m68k','alpha','powerpc','sparc','vm','ia64','x86_64',
+ 'mips','arm', 'powerpc64', 'avr', 'mipsel');
+
+ abi2str : array[tabi] of string[10] =
+ ('DEFAULT','SYSV','AIX','EABI','ARMEB');
+
+ var
+ targetinfos : array[tsystem] of psysteminfo;
+ arinfos : array[tar] of parinfo;
+ resinfos : array[tres] of presinfo;
+ asminfos : array[tasm] of pasminfo;
+ dbginfos : array[tdbg] of pdbginfo;
+
+ source_info : tsysteminfo;
+ target_cpu : tsystemcpu;
+ target_info : tsysteminfo;
+ target_asm : tasminfo;
+ target_ar : tarinfo;
+ target_res : tresinfo;
+ target_dbg : tdbginfo;
+ target_cpu_string,
+ target_os_string : string[12]; { for rtl/<X>/,fcl/<X>/, etc. }
+ target_full_string : string[24];
+
+ function set_target(t:tsystem):boolean;
+ function set_target_asm(t:tasm):boolean;
+ function set_target_ar(t:tar):boolean;
+ function set_target_res(t:tres):boolean;
+ function set_target_dbg(t:tdbg):boolean;
+
+ function find_system_by_string(const s : string) : tsystem;
+ function find_asm_by_string(const s : string) : tasm;
+ function find_dbg_by_string(const s : string) : tdbg;
+
+ procedure set_source_info(const ti : tsysteminfo);
+
+ function UpdateAlignment(var d:talignmentinfo;const s:talignmentinfo) : boolean;
+
+ procedure RegisterTarget(const r:tsysteminfo);
+ procedure RegisterRes(const r:tresinfo; rcf : TAbstractResourceFileClass);
+ procedure RegisterAr(const r:tarinfo);
+ { Register the external linker. This routine is called to setup the
+ class to use for the linker. It returns the tsysteminfo structure
+ updated with the correct linker class for external linking.
+ }
+ procedure RegisterExternalLinker(var system_info: tsysteminfo; c:TAbstractLinkerClass);
+ { Register the internal linker. This routine is called to setup the
+ class to use for the linker. It returns the tsysteminfo structure
+ updated with the correct linker class for internal linking.
+
+ If internal linking is not supported, this class can be set
+ to nil.
+ }
+ procedure RegisterInternalLinker(var system_info : tsysteminfo; c:TAbstractLinkerClass);
+
+ procedure InitSystems;
+
+ {$ifdef FreeBSD}
+ function GetOSRelDate:Longint;
+ {$endif}
+
+implementation
+
+ uses
+ cutils{$ifdef FreeBSD},SysCtl,BaseUnix{$endif};
+
+{****************************************************************************
+ OS runtime version detection utility routine
+****************************************************************************}
+
+{$ifdef FreeBSD}
+function GetOSRelDate:Longint;
+
+var
+ mib : array[0..1] of cint;
+ rval : cint;
+ len : size_t;
+ i : longint;
+ v : longint;
+ oerrno : cint;
+ S : AnsiString;
+
+Begin
+ s:='ab';
+ SetLength(S,50);
+ mib[0] := CTL_KERN;
+ mib[1] := KERN_OSRELDATE;
+ len := 4;
+ oerrno:= fpgeterrno;
+ if (FPsysctl(pChar(@mib), 2, pchar(@v), @len, NIL, 0) = -1) Then
+ Begin
+ if (fpgeterrno = ESysENOMEM) Then
+ fpseterrno(oerrno);
+ GetOSRelDate:=0;
+ End
+ else
+ GetOSRelDate:=v;
+End;
+{$endif}
+
+
+{****************************************************************************
+ Target setting
+****************************************************************************}
+
+function set_target(t:tsystem):boolean;
+begin
+ set_target:=false;
+ if assigned(targetinfos[t]) then
+ begin
+ target_info:=targetinfos[t]^;
+ set_target_asm(target_info.assem);
+ set_target_ar(target_info.ar);
+ set_target_res(target_info.res);
+ set_target_dbg(target_info.dbg);
+ target_cpu:=target_info.cpu;
+ target_os_string:=lower(target_info.shortname);
+ target_cpu_string:=cpu2str[target_cpu];
+ target_full_string:=target_cpu_string+'-'+target_os_string;
+ set_target:=true;
+ exit;
+ end;
+end;
+
+
+function set_target_asm(t:tasm):boolean;
+begin
+ set_target_asm:=false;
+ if assigned(asminfos[t]) and
+ ((target_info.system in asminfos[t]^.supported_targets) or
+ (system_any in asminfos[t]^.supported_targets)) then
+ begin
+ target_asm:=asminfos[t]^;
+ set_target_asm:=true;
+ exit;
+ end;
+end;
+
+
+function set_target_ar(t:tar):boolean;
+begin
+ result:=false;
+ if assigned(arinfos[t]) then
+ begin
+ target_ar:=arinfos[t]^;
+ result:=true;
+ exit;
+ end;
+end;
+
+
+function set_target_res(t:tres):boolean;
+begin
+ result:=false;
+ if assigned(resinfos[t]) then
+ begin
+ target_res:=resinfos[t]^;
+ result:=true;
+ exit;
+ end
+ else
+ FillByte(target_res,sizeof(target_res),0);
+end;
+
+
+function set_target_dbg(t:tdbg):boolean;
+begin
+ result:=false;
+ if assigned(dbginfos[t]) then
+ begin
+ target_dbg:=dbginfos[t]^;
+ result:=true;
+ exit;
+ end;
+end;
+
+
+function find_system_by_string(const s : string) : tsystem;
+var
+ hs : string;
+ t : tsystem;
+begin
+ result:=system_none;
+ hs:=upper(s);
+ for t:=low(tsystem) to high(tsystem) do
+ if assigned(targetinfos[t]) and
+ (upper(targetinfos[t]^.shortname)=hs) then
+ begin
+ result:=t;
+ exit;
+ end;
+end;
+
+
+function find_asm_by_string(const s : string) : tasm;
+var
+ hs : string;
+ t : tasm;
+begin
+ result:=as_none;
+ hs:=upper(s);
+ for t:=low(tasm) to high(tasm) do
+ if assigned(asminfos[t]) and
+ (asminfos[t]^.idtxt=hs) then
+ begin
+ result:=t;
+ exit;
+ end;
+end;
+
+
+function find_dbg_by_string(const s : string) : tdbg;
+var
+ hs : string;
+ t : tdbg;
+begin
+ result:=dbg_none;
+ hs:=upper(s);
+ for t:=low(tdbg) to high(tdbg) do
+ if assigned(dbginfos[t]) and
+ (dbginfos[t]^.idtxt=hs) then
+ begin
+ result:=t;
+ exit;
+ end;
+end;
+
+
+function UpdateAlignment(var d:talignmentinfo;const s:talignmentinfo) : boolean;
+begin
+ result:=true;
+ with d do
+ begin
+ if (s.procalign in [1,2,4,8,16,32,64,128]) or (s.procalign=256) then
+ procalign:=s.procalign
+ else if s.procalign<>0 then
+ result:=false;
+ if (s.loopalign in [1,2,4,8,16,32,64,128]) or (s.loopalign=256) then
+ loopalign:=s.loopalign
+ else if s.loopalign<>0 then
+ result:=false;
+ if (s.jumpalign in [1,2,4,8,16,32,64,128]) or (s.jumpalign=256) then
+ jumpalign:=s.jumpalign
+ else if s.jumpalign<>0 then
+ result:=false;
+ { general update rules:
+ minimum: if higher then update
+ maximum: if lower then update or if undefined then update }
+ if s.constalignmin>constalignmin then
+ constalignmin:=s.constalignmin;
+ if (constalignmax=0) or
+ ((s.constalignmax>0) and (s.constalignmax<constalignmax)) then
+ constalignmax:=s.constalignmax;
+ if s.varalignmin>varalignmin then
+ varalignmin:=s.varalignmin;
+ if (varalignmax=0) or
+ ((s.varalignmax>0) and (s.varalignmax<varalignmax)) then
+ varalignmax:=s.varalignmax;
+ if s.localalignmin>localalignmin then
+ localalignmin:=s.localalignmin;
+ if (localalignmax=0) or
+ ((s.localalignmax>0) and (s.localalignmax<localalignmax)) then
+ localalignmax:=s.localalignmax;
+ if s.recordalignmin>recordalignmin then
+ recordalignmin:=s.recordalignmin;
+ if (recordalignmax=0) or
+ ((s.recordalignmax>0) and (s.recordalignmax<recordalignmax)) then
+ recordalignmax:=s.recordalignmax;
+ if (maxCrecordalign=0) or
+ ((s.maxCrecordalign>0) and (s.maxCrecordalign<maxCrecordalign)) then
+ maxCrecordalign:=s.maxCrecordalign;
+ end;
+end;
+
+
+{****************************************************************************
+ Target registration
+****************************************************************************}
+
+procedure RegisterTarget(const r:tsysteminfo);
+var
+ t : tsystem;
+begin
+ t:=r.system;
+ if assigned(targetinfos[t]) then
+ writeln('Warning: Target is already registered!')
+ else
+ Getmem(targetinfos[t],sizeof(tsysteminfo));
+ targetinfos[t]^:=r;
+end;
+
+
+procedure RegisterRes(const r:tresinfo; rcf : TAbstractResourceFileClass);
+var
+ t : tres;
+begin
+ t:=r.id;
+ if not assigned(resinfos[t]) then
+ Getmem(resinfos[t],sizeof(tresinfo));
+ resinfos[t]^:=r;
+ resinfos[t]^.resourcefileclass:=rcf;
+end;
+
+
+procedure RegisterAr(const r:tarinfo);
+var
+ t : tar;
+begin
+ t:=r.id;
+ if assigned(arinfos[t]) then
+ writeln('Warning: ar is already registered!')
+ else
+ Getmem(arinfos[t],sizeof(tarinfo));
+ arinfos[t]^:=r;
+end;
+
+procedure RegisterExternalLinker(var system_info: tsysteminfo; c:TAbstractLinkerClass);
+begin
+ system_info.linkextern := c;
+end;
+
+procedure RegisterInternalLinker(var system_info : tsysteminfo; c:TAbstractLinkerClass);
+begin
+ system_info.link := c;
+end;
+
+
+
+procedure DeregisterInfos;
+var
+ assem : tasm;
+ target : tsystem;
+ ar : tar;
+ res : tres;
+ dbg : tdbg;
+begin
+ for target:=low(tsystem) to high(tsystem) do
+ if assigned(targetinfos[target]) then
+ begin
+ freemem(targetinfos[target],sizeof(tsysteminfo));
+ targetinfos[target]:=nil;
+ end;
+ for assem:=low(tasm) to high(tasm) do
+ if assigned(asminfos[assem]) then
+ begin
+ freemem(asminfos[assem],sizeof(tasminfo));
+ asminfos[assem]:=nil;
+ end;
+ for ar:=low(tar) to high(tar) do
+ if assigned(arinfos[ar]) then
+ begin
+ freemem(arinfos[ar],sizeof(tarinfo));
+ arinfos[ar]:=nil;
+ end;
+ for res:=low(tres) to high(tres) do
+ if assigned(resinfos[res]) then
+ begin
+ freemem(resinfos[res],sizeof(tresinfo));
+ resinfos[res]:=nil;
+ end;
+ for dbg:=low(tdbg) to high(tdbg) do
+ if assigned(dbginfos[dbg]) then
+ begin
+ freemem(dbginfos[dbg],sizeof(tdbginfo));
+ dbginfos[dbg]:=nil;
+ end;
+end;
+
+
+{****************************************************************************
+ Initialization of default target
+****************************************************************************}
+
+procedure default_target(t:tsystem);
+begin
+ set_target(t);
+ if source_info.name='' then
+ source_info:=target_info;
+end;
+
+
+procedure set_source_info(const ti : tsysteminfo);
+begin
+{ can't use message() here (PFV) }
+ if source_info.name<>'' then
+ Writeln('Warning: Source OS Redefined!');
+ source_info:=ti;
+end;
+
+
+procedure InitSystems;
+begin
+{ Now default target, this is dependent on the target cpu define,
+ when the define is the same as the source cpu then we use the source
+ os, else we pick a default }
+{$ifdef i386}
+ {$ifdef cpu86}
+ default_target(source_info.system);
+ {$define default_target_set}
+ {$else cpu86}
+ {$ifdef linux}
+ default_target(system_i386_linux);
+ {$define default_target_set}
+ {$endif}
+ {$ifdef freebsd}
+ default_target(system_i386_freebsd);
+ {$define default_target_set}
+ {$endif}
+ {$ifdef openbsd}
+ default_target(system_i386_openbsd);
+ {$define default_target_set}
+ {$endif}
+ {$ifdef darwin}
+ default_target(system_i386_darwin);
+ {$define default_target_set}
+ {$endif}
+ {$endif cpu86}
+ { default is linux }
+ {$ifndef default_target_set}
+ default_target(system_i386_linux);
+ {$endif default_target_set}
+{$endif i386}
+
+{$ifdef x86_64}
+ {$ifdef cpux86_64}
+ default_target(source_info.system);
+ {$define default_target_set}
+ {$else cpux86_64}
+ {$ifdef MSWindows}
+ default_target(system_x86_64_win64);
+ {$define default_target_set}
+ {$endif}
+ {$ifdef linux}
+ default_target(system_x86_64_linux);
+ {$define default_target_set}
+ {$endif}
+ {$ifdef freebsd}
+ default_target(system_x86_64_freebsd);
+ {$define default_target_set}
+ {$endif}
+ {$ifdef solaris}
+ default_target(system_x86_64_solaris);
+ {$define default_target_set}
+ {$endif}
+ {$ifdef darwin}
+ default_target(system_x86_64_darwin);
+ {$define default_target_set}
+ {$endif}
+ {$endif cpux86_64}
+ { default is linux }
+ {$ifndef default_target_set}
+ default_target(system_x86_64_linux);
+ {$endif default_target_set}
+{$endif x86_64}
+
+{$ifdef m68k}
+ {$ifdef cpu68}
+ default_target(source_info.target);
+ {$else cpu68}
+ default_target(system_m68k_linux);
+ {$endif cpu68}
+{$endif m68k}
+
+{$ifdef alpha}
+ {$ifdef cpualpha}
+ default_target(source_info.system);
+ {$else cpualpha}
+ default_target(system_alpha_linux);
+ {$endif cpualpha}
+{$endif alpha}
+
+{$ifdef powerpc}
+ {$ifdef cpupowerpc}
+ default_target(source_info.system);
+ {$define default_target_set}
+ {$else cpupowerpc}
+ {$ifdef linux}
+ default_target(system_powerpc_linux);
+ {$define default_target_set}
+ {$endif}
+ {$ifdef darwin}
+ default_target(system_powerpc_darwin);
+ {$define default_target_set}
+ {$endif}
+ {$endif cpupowerpc}
+ {$ifndef default_target_set}
+ default_target(system_powerpc_linux);
+ {$endif default_target_set}
+{$endif powerpc}
+
+{$ifdef POWERPC64}
+ {$ifdef cpupowerpc64}
+ default_target(source_info.system);
+ {$define default_target_set}
+ {$else cpupowerpc64}
+ {$ifdef darwin}
+ default_target(system_powerpc64_darwin);
+ {$define default_target_set}
+ {$endif}
+ {$ifdef linux}
+ default_target(system_powerpc64_linux);
+ {$define default_target_set}
+ {$endif}
+ {$endif cpupowerpc64}
+ {$ifndef default_target_set}
+ default_target(system_powerpc64_linux);
+ {$define default_target_set}
+ {$endif}
+{$endif POWERPC64}
+
+{$ifdef sparc}
+ {$ifdef cpusparc}
+ default_target(source_info.system);
+ {$else cpusparc}
+ default_target(system_sparc_linux);
+ {$endif cpusparc}
+{$endif sparc}
+
+{$ifdef arm}
+ {$ifdef cpuarm}
+ default_target(source_info.system);
+ {$else cpuarm}
+ {$ifdef WINDOWS}
+ {$define default_target_set}
+ default_target(system_arm_wince);
+ {$endif}
+ {$ifdef linux}
+ {$define default_target_set}
+ default_target(system_arm_linux);
+ {$endif}
+ {$ifdef darwin}
+ {$define default_target_set}
+ default_target(system_arm_darwin);
+ {$endif}
+ {$ifndef default_target_set}
+ default_target(system_arm_linux);
+ {$define default_target_set}
+ {$endif}
+ {$endif cpuarm}
+{$endif arm}
+
+{$ifdef avr}
+ default_target(system_avr_embedded);
+{$endif avr}
+
+{$ifdef mips}
+{$ifdef mipsel}
+ default_target(system_mipsel_linux);
+{$else mipsel}
+ default_target(system_mips_linux);
+{$endif mipsel}
+{$endif mips}
+end;
+
+
+initialization
+ source_info.name:='';
+finalization
+ DeregisterInfos;
+end.
diff --git a/closures/compiler/systems/i_amiga.pas b/closures/compiler/systems/i_amiga.pas
new file mode 100644
index 0000000000..4a1c58ae1f
--- /dev/null
+++ b/closures/compiler/systems/i_amiga.pas
@@ -0,0 +1,167 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ This unit implements support information structures for AmigaOS
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ ****************************************************************************
+}
+{ This unit implements support information structures for the AmigaOS. }
+unit i_amiga;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ systems;
+
+ const
+ system_m68k_amiga_info : tsysteminfo =
+ (
+ system : system_m68k_Amiga;
+ name : 'Commodore Amiga';
+ shortname : 'amiga';
+ flags : [tf_files_case_aware];
+ cpu : cpu_m68k;
+ unit_env : '';
+ extradefines : '';
+ exeext : '';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.library';
+ staticlibext : '.a';
+ staticlibprefix : 'lib';
+ sharedlibprefix : '';
+ sharedClibext : '.library';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : '';
+ importlibprefix : 'libimp';
+ importlibext : '.a';
+ Cprefix : '';
+ newline : #10;
+ dirsep : '/';
+ assem : as_gas;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_none;
+ dbg : dbg_stabs;
+ script : script_amiga;
+ endian : endian_big;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 4;
+ varalignmin : 0;
+ varalignmax : 4;
+ localalignmin : 0;
+ localalignmax : 4;
+ recordalignmin : 0;
+ recordalignmax : 2;
+ maxCrecordalign : 4
+ );
+ first_parm_offset : 8;
+ stacksize : 262144;
+ abi : abi_default;
+ );
+
+ system_powerpc_amiga_info : tsysteminfo =
+ (
+ system : system_powerpc_Amiga;
+ name : 'AmigaOS for PowerPC';
+ shortname : 'amiga';
+ flags : [tf_files_case_aware];
+ cpu : cpu_powerpc;
+ unit_env : '';
+ extradefines : 'PPC603';
+ exeext : '';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.library';
+ staticlibext : '.a';
+ staticlibprefix : 'lib';
+ sharedlibprefix : '';
+ sharedClibext : '.library';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : '';
+ importlibprefix : 'libimp';
+ importlibext : '.a';
+ Cprefix : '';
+ newline : #10;
+ dirsep : '/';
+ assem : as_gas;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_none;
+ dbg : dbg_stabs;
+ script : script_amiga;
+ endian : endian_big;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 4;
+ varalignmin : 0;
+ varalignmax : 4;
+ localalignmin : 0;
+ localalignmax : 4;
+ recordalignmin : 0;
+ recordalignmax : 4;
+ maxCrecordalign : 4
+ );
+ first_parm_offset : 8;
+ stacksize : 262144;
+ abi : abi_powerpc_sysv;
+ );
+
+ implementation
+
+initialization
+{$ifdef CPU68}
+ {$ifdef AMIGA}
+ set_source_info(system_m68k_Amiga_info);
+ {$endif AMIGA}
+{$endif CPU68}
+{$ifdef CPUPOWERPC}
+ {$ifdef AMIGA}
+ set_source_info(system_powerpc_Amiga_info);
+ {$endif AMIGA}
+{$endif CPUPOWERPC}
+end.
diff --git a/closures/compiler/systems/i_atari.pas b/closures/compiler/systems/i_atari.pas
new file mode 100644
index 0000000000..2c9fe60665
--- /dev/null
+++ b/closures/compiler/systems/i_atari.pas
@@ -0,0 +1,91 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ This unit implements support information structures for atari
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ ****************************************************************************
+}
+{ This unit implements support information structures for atari. }
+unit i_atari;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ systems;
+
+ const
+ system_m68k_atari_info : tsysteminfo =
+ (
+ system : target_m68k_Atari;
+ name : 'Atari ST/STE';
+ shortname : 'atari';
+ flags : [tf_use_8_3];
+ cpu : cpu_m68k;
+ short_name : 'ATARI';
+ unit_env : '';
+ extradefines : '';
+ exeext : '.tpp';
+ defext : '';
+ scriptext : '';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.dll';
+ staticlibext : '.a';
+ staticlibprefix : '';
+ sharedlibprefix : '';
+ sharedClibext : '.dll';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : '';
+ importlibprefix : 'libimp';
+ importlibext : '.a';
+ p_ext_support : false;
+ Cprefix : '_';
+ newline : #10;
+ dirsep : '/';
+ files_case_relevent : true;
+ assem : as_gas;
+ assemextern : as_gas;
+ link : ld_m68k_atari;
+ linkextern : ld_m68k_atari;
+ ar : ar_m68k_ar;
+ res : res_none;
+ dbg : dbg_stabs;
+ script : script_unix;
+ endian : endian_big;
+ stackalignment : 2;
+ maxCrecordalignment : 4;
+ stacksize : 8192;
+ DllScanSupported:false;
+ use_function_relative_addresses : false
+ );
+
+ implementation
+
+initialization
+{$ifdef cpu68}
+ {$ifdef atari}
+ set_source_info(system_m68k_atari_info);
+ {$endif atari}
+{$endif cpu68}
+end.
diff --git a/closures/compiler/systems/i_beos.pas b/closures/compiler/systems/i_beos.pas
new file mode 100644
index 0000000000..53933b1900
--- /dev/null
+++ b/closures/compiler/systems/i_beos.pas
@@ -0,0 +1,114 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ This unit implements support information structures for BeOS
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ ****************************************************************************
+}
+{ This unit implements support information structures for BeOS. }
+unit i_beos;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ systems;
+
+ const
+ system_i386_beos_info : tsysteminfo =
+ (
+ system : system_i386_BeOS;
+ name : 'Beos for i386';
+ shortname : 'Beos';
+ flags : [tf_under_development,tf_needs_symbol_size,tf_files_case_sensitive,
+ tf_smartlink_sections, tf_smartlink_library];
+ cpu : cpu_i386;
+ unit_env : 'BEOSUNITS';
+ extradefines : 'UNIX;HASUNIX';
+ exeext : '';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.so';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : 'lib';
+ sharedClibext : '.so';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : 'lib';
+ importlibprefix : 'libimp';
+ importlibext : '.a';
+ Cprefix : '';
+ newline : #10;
+ dirsep : '/';
+ assem : as_i386_elf32;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_none;
+ dbg : dbg_stabs;
+ script : script_unix;
+ endian : endian_little;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 4;
+ varalignmin : 0;
+ varalignmax : 4;
+ localalignmin : 0;
+ localalignmax : 4;
+ recordalignmin : 0;
+ recordalignmax : 2;
+ maxCrecordalign : 4
+ );
+ first_parm_offset : 8;
+ { Stack size used to be 256 K under BeOS. So, it was the value
+ used in previous version of FPC for BeOS (but lost in the road
+ to 2.* ;-).
+ According to buildtools/gcc/gcc/config/i386/beos-elf.h in the
+ Haiku's repository, this value was increased to 1Mb since r4.1b3.
+ Under R5, this value is even greater. listarea report a default
+ size of 16 Mb for the user stack of the main thread.
+ People who still use BeOS nowadays should use R5 (or Haiku),
+ so i use this new value.
+ }
+ stacksize : 16 * 1024 * 1024;
+ abi : abi_default
+ );
+
+ implementation
+
+initialization
+{$ifdef cpu86}
+ {$ifdef beos}
+ {$ifndef haiku}
+ set_source_info(system_i386_beos_info);
+ {$endif haiku}
+ {$endif beos}
+{$endif cpu86}
+end.
diff --git a/closures/compiler/systems/i_bsd.pas b/closures/compiler/systems/i_bsd.pas
new file mode 100644
index 0000000000..9d8fbf239f
--- /dev/null
+++ b/closures/compiler/systems/i_bsd.pas
@@ -0,0 +1,858 @@
+{
+ Copyright (c) 1998-2008 by Peter Vreman
+
+ This unit implements support information structures for FreeBSD/NetBSD,
+ OpenBSD and Darwin (Mac OS X)
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ ****************************************************************************
+}
+{ This unit implements support information structures for FreeBSD/NetBSD.
+ OpenBSD is only added for i386 for now, though it exists for most
+ other common CPU's too}
+
+unit i_bsd;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ systems, rescmn;
+
+ const
+ res_macho_info : tresinfo =
+ (
+ id : res_macho;
+ resbin : 'fpcres';
+ rescmd : '-o $OBJ -a $ARCH -s $SUBARCH -of mach-o $DBG';
+ rcbin : 'windres';
+ rccmd : '--include $INC -O res -o $RES $RC';
+ resourcefileclass : nil;
+ resflags : [];
+ );
+ res_macosx_ext_info : tresinfo =
+ (
+ id : res_ext;
+ resbin : 'fpcres';
+ rescmd : '-o $OBJ -a $ENDIAN -of external $DBG';
+ rcbin : 'windres';
+ rccmd : '--include $INC -O res -o $RES $RC';
+ resourcefileclass : nil;
+ resflags : [res_external_file,res_arch_in_file_name];
+ );
+
+ system_i386_freebsd_info : tsysteminfo =
+ (
+ system : system_i386_FreeBSD;
+ name : 'FreeBSD/ELF for i386';
+ shortname : 'FreeBSD';
+ flags : [tf_pic_uses_got,tf_files_case_sensitive,
+{$ifdef segment_threadvars}
+ tf_section_threadvars,
+{$endif segment_threadvars}
+ tf_needs_symbol_type,tf_needs_symbol_size,tf_smartlink_library
+ {,tf_smartlink_sections},tf_has_winlike_resources];
+ cpu : cpu_i386;
+ unit_env : 'BSDUNITS';
+ extradefines : 'UNIX;BSD;HASUNIX';
+ exeext : '';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.so';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : 'lib';
+ sharedClibext : '.so';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : 'lib';
+ importlibprefix : 'libimp';
+ importlibext : '.a';
+ Cprefix : '';
+ newline : #10;
+ dirsep : '/';
+ assem : as_i386_elf32;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_elf;
+ dbg : dbg_stabs;
+ script : script_unix;
+ endian : endian_little;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 4;
+ varalignmin : 0;
+ varalignmax : 4;
+ localalignmin : 0;
+ localalignmax : 4;
+ recordalignmin : 0;
+ recordalignmax : 2;
+ maxCrecordalign : 4
+ );
+ first_parm_offset : 8;
+ stacksize : 262144;
+ abi : abi_default;
+ );
+
+
+ system_x86_64_freebsd_info : tsysteminfo =
+ (
+ system : system_x86_64_freebsd;
+ name : 'FreeBSD for x86-64';
+ shortname : 'FreeBSD';
+ flags : [tf_needs_symbol_size,tf_needs_dwarf_cfi,tf_library_needs_pic,tf_needs_symbol_type,
+ tf_files_case_sensitive,tf_smartlink_library,
+ tf_dwarf_only_local_labels
+ { tf_pic_uses_got,tf_smartlink_sections},tf_has_winlike_resources];
+ cpu : cpu_x86_64;
+ unit_env : 'BSDUNITS';
+ extradefines : 'UNIX;HASUNIX;BSD';
+ exeext : '';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.so';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : 'lib';
+ sharedClibext : '.so';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : 'lib';
+ importlibprefix : 'libimp';
+ importlibext : '.a';
+ Cprefix : '';
+ newline : #10;
+ dirsep : '/';
+ assem : as_x86_64_elf64;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_elf;
+ dbg : dbg_dwarf2; //dbg_stabs;
+ script : script_unix;
+ endian : endian_little;
+ alignment :
+ (
+ procalign : 8;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 8;
+ varalignmin : 0;
+ varalignmax : 16;
+ localalignmin : 4;
+ localalignmax : 16;
+ recordalignmin : 0;
+ recordalignmax : 16;
+ maxCrecordalign : 16
+ );
+ first_parm_offset : 16;
+ stacksize : 256*1024;
+ abi : abi_default;
+ );
+
+
+ system_i386_netbsd_info : tsysteminfo =
+ (
+ system : system_i386_NetBSD;
+ name : 'NetBSD for i386';
+ shortname : 'NetBSD';
+ flags : [tf_under_development,tf_files_case_sensitive,tf_smartlink_library,tf_has_winlike_resources];
+ cpu : cpu_i386;
+ unit_env : 'BSDUNITS';
+ extradefines : 'UNIX;BSD;HASUNIX';
+ exeext : '';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.so';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : 'lib';
+ sharedClibext : '.so';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : 'lib';
+ importlibprefix : 'libimp';
+ importlibext : '.a';
+ Cprefix : '_';
+ newline : #10;
+ dirsep : '/';
+ assem : as_gas;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_elf;
+ dbg : dbg_stabs;
+ script : script_unix;
+ endian : endian_little;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 1;
+ varalignmin : 0;
+ varalignmax : 1;
+ localalignmin : 0;
+ localalignmax : 1;
+ recordalignmin : 0;
+ recordalignmax : 2;
+ maxCrecordalign : 4
+ );
+ first_parm_offset : 8;
+ stacksize : 262144;
+ abi : abi_default;
+ );
+
+ system_i386_openbsd_info : tsysteminfo =
+ (
+ system : system_i386_OpenBSD;
+ name : 'OpenBSD for i386';
+ shortname : 'OpenBSD';
+ flags : [tf_pic_uses_got,tf_under_development,tf_files_case_sensitive,tf_smartlink_library,tf_has_winlike_resources];
+ cpu : cpu_i386;
+ unit_env : 'BSDUNITS';
+ extradefines : 'UNIX;BSD;HASUNIX';
+ exeext : '';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.so';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : 'lib';
+ sharedClibext : '.so';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : 'lib';
+ importlibprefix : 'libimp';
+ importlibext : '.a';
+ Cprefix : '';
+ newline : #10;
+ dirsep : '/';
+ assem : as_gas;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_elf;
+ dbg : dbg_stabs;
+ script : script_unix;
+ endian : endian_little;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 1;
+ varalignmin : 0;
+ varalignmax : 1;
+ localalignmin : 0;
+ localalignmax : 1;
+ recordalignmin : 0;
+ recordalignmax : 2;
+ maxCrecordalign : 4
+ );
+ first_parm_offset : 8;
+ stacksize : 262144;
+ abi : abi_default;
+ );
+
+ system_m68k_netbsd_info : tsysteminfo =
+ (
+ system : system_m68k_NetBSD;
+ name : 'NetBSD for m68k';
+ shortname : 'NetBSD';
+ flags : [tf_under_development,tf_files_case_sensitive,tf_smartlink_library,tf_has_winlike_resources];
+ cpu : cpu_m68k;
+ unit_env : 'BSDUNITS';
+ extradefines : 'UNIX;BSD;HASUNIX';
+ exeext : '';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.so';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : 'lib';
+ sharedClibext : '.so';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : 'lib';
+ importlibprefix : 'libimp';
+ importlibext : '.a';
+ Cprefix : '';
+ newline : #10;
+ dirsep : '/';
+ assem : as_gas;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_elf;
+ dbg : dbg_stabs;
+ script : script_unix;
+ endian : endian_big;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 1;
+ varalignmin : 0;
+ varalignmax : 1;
+ localalignmin : 0;
+ localalignmax : 1;
+ recordalignmin : 0;
+ recordalignmax : 2;
+ maxCrecordalign : 4
+ );
+ first_parm_offset : 8;
+ stacksize : 262144;
+ abi : abi_default;
+ );
+
+ system_powerpc_netbsd_info : tsysteminfo =
+ (
+ system : system_powerpc_netbsd;
+ name : 'NetBSD for PowerPC';
+ shortname : 'NetBSD';
+ flags : [tf_under_development,tf_files_case_sensitive,tf_smartlink_library,tf_has_winlike_resources];
+ cpu : cpu_powerpc;
+ unit_env : '';
+ extradefines : 'UNIX;BSD;HASUNIX';
+ exeext : '';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.so';
+ staticlibext : '.s';
+ staticlibprefix : 'libp';
+ sharedlibprefix : 'lib';
+ sharedClibext : '.so';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : 'lib';
+ importlibprefix : 'libimp';
+ importlibext : '.a';
+ Cprefix : '';
+ newline : #10;
+ dirsep : '/';
+ assem : as_gas;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_elf;
+ dbg : dbg_stabs;
+ script : script_unix;
+ endian : endian_big;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 4;
+ varalignmin : 0;
+ varalignmax : 4;
+ localalignmin : 0;
+ localalignmax : 4;
+ recordalignmin : 0;
+ recordalignmax : 2;
+ maxCrecordalign : 4 // should be 8 probably
+ );
+ first_parm_offset : 8;
+ stacksize : 32*1024*1024;
+ { abi_powerpc_sysv doesn't work yet }
+ abi : abi_powerpc_aix;
+ );
+
+
+ system_powerpc_darwin_info : tsysteminfo =
+ (
+ system : system_powerpc_darwin;
+ name : 'Darwin for PowerPC';
+ shortname : 'Darwin';
+ flags : [tf_p_ext_support,tf_files_case_sensitive,tf_smartlink_sections,tf_dwarf_relative_addresses,tf_dwarf_only_local_labels,tf_pic_default,tf_has_winlike_resources];
+ cpu : cpu_powerpc;
+ unit_env : 'BSDUNITS';
+ extradefines : 'UNIX;BSD;HASUNIX';
+ exeext : '';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.dylib';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : 'lib';
+ sharedClibext : '.dylib';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : 'lib';
+ importlibprefix : 'libimp';
+ importlibext : '.a';
+ Cprefix : '_';
+ newline : #10;
+ dirsep : '/';
+ assem : as_darwin;
+ assemextern : as_darwin;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_macho;
+ dbg : dbg_stabs;
+ script : script_unix;
+ endian : endian_big;
+ alignment :
+ (
+ procalign : 16;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 4;
+ varalignmin : 0;
+ varalignmax : 4;
+ localalignmin : 0;
+ localalignmax : 4;
+ recordalignmin : 0;
+ recordalignmax : 4;
+ maxCrecordalign : 4
+ );
+ first_parm_offset : 24;
+ stacksize : 262144;
+ abi : abi_powerpc_aix;
+ );
+
+
+
+ system_i386_darwin_info : tsysteminfo =
+ (
+ system : system_i386_darwin;
+ name : 'Darwin for i386';
+ shortname : 'Darwin';
+ flags : [tf_p_ext_support,tf_files_case_sensitive,tf_smartlink_sections,tf_dwarf_relative_addresses,tf_dwarf_only_local_labels,tf_pic_uses_got,tf_pic_default,tf_has_winlike_resources];
+ cpu : cpu_i386;
+ unit_env : 'BSDUNITS';
+ extradefines : 'UNIX;BSD;HASUNIX';
+ exeext : '';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.dylib';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : 'lib';
+ sharedClibext : '.dylib';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : 'lib';
+ importlibprefix : 'libimp';
+ importlibext : '.a';
+ Cprefix : '_';
+ newline : #10;
+ dirsep : '/';
+ assem : as_darwin;
+ assemextern : as_darwin;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_macho;
+ dbg : dbg_stabs;
+ script : script_unix;
+ endian : endian_little;
+ alignment :
+ (
+ procalign : 16;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 8;
+ varalignmin : 0;
+ varalignmax : 16;
+ localalignmin : 0;
+ localalignmax : 8;
+ recordalignmin : 0;
+ recordalignmax : 16;
+ maxCrecordalign : 16
+ );
+ first_parm_offset : 8;
+ stacksize : 262144;
+ abi : abi_default;
+ );
+
+
+
+ system_i386_iphonesim_info : tsysteminfo =
+ (
+ system : system_i386_iphonesim;
+ name : 'Darwin/iPhoneSim for i386';
+ shortname : 'iPhoneSim';
+ flags : [tf_p_ext_support,tf_files_case_sensitive,tf_smartlink_sections,tf_dwarf_relative_addresses,tf_dwarf_only_local_labels,tf_pic_uses_got,tf_pic_default,tf_has_winlike_resources];
+ cpu : cpu_i386;
+ unit_env : 'BSDUNITS';
+ extradefines : 'UNIX;BSD;HASUNIX;DARWIN'; // also define darwin for code compatibility
+ exeext : '';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.dylib';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : 'lib';
+ sharedClibext : '.dylib';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : 'lib';
+ importlibprefix : 'libimp';
+ importlibext : '.a';
+ Cprefix : '_';
+ newline : #10;
+ dirsep : '/';
+ assem : as_darwin;
+ assemextern : as_darwin;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_macho;
+ dbg : dbg_dwarf2;
+ script : script_unix;
+ endian : endian_little;
+ alignment :
+ (
+ procalign : 16;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 8;
+ varalignmin : 0;
+ varalignmax : 16;
+ localalignmin : 0;
+ localalignmax : 8;
+ recordalignmin : 0;
+ recordalignmax : 16;
+ maxCrecordalign : 16
+ );
+ first_parm_offset : 8;
+ stacksize : 262144;
+ abi : abi_default;
+ );
+
+
+
+ system_powerpc64_darwin_info : tsysteminfo =
+ (
+ system : system_powerpc64_darwin;
+ name : 'Darwin for PowerPC64';
+ shortname : 'Darwin';
+ flags : [tf_p_ext_support,tf_files_case_sensitive,tf_smartlink_sections,tf_dwarf_relative_addresses,tf_dwarf_only_local_labels,tf_pic_default,tf_has_winlike_resources];
+ cpu : cpu_powerpc64;
+ unit_env : 'BSDUNITS';
+ extradefines : 'UNIX;BSD;HASUNIX';
+ exeext : '';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.dylib';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : 'lib';
+ sharedClibext : '.dylib';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : 'lib';
+ importlibprefix : 'libimp';
+ importlibext : '.a';
+ Cprefix : '_';
+ newline : #10;
+ dirsep : '/';
+ assem : as_darwin;
+ assemextern : as_darwin;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_macho;
+ dbg : dbg_dwarf2;
+ script : script_unix;
+ endian : endian_big;
+ alignment :
+ (
+ procalign : 16;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 4;
+ constalignmax : 8;
+ varalignmin : 4;
+ varalignmax : 8;
+ localalignmin : 4;
+ localalignmax : 8;
+ recordalignmin : 0;
+ recordalignmax : 8;
+ maxCrecordalign : 4
+ );
+ first_parm_offset : 48;
+ stacksize : 262144;
+ abi : abi_powerpc_aix;
+ );
+
+
+
+ system_x86_64_darwin_info : tsysteminfo =
+ (
+ system : system_x86_64_darwin;
+ name : 'Darwin for x86_64';
+ shortname : 'Darwin';
+ flags : [tf_p_ext_support,tf_files_case_sensitive,tf_smartlink_sections,tf_dwarf_relative_addresses,tf_dwarf_only_local_labels,tf_pic_default,tf_has_winlike_resources];
+ cpu : cpu_x86_64;
+ unit_env : 'BSDUNITS';
+ extradefines : 'UNIX;BSD;HASUNIX';
+ exeext : '';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.dylib';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : 'lib';
+ sharedClibext : '.dylib';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : 'lib';
+ importlibprefix : 'libimp';
+ importlibext : '.a';
+ Cprefix : '_';
+ newline : #10;
+ dirsep : '/';
+ assem : as_darwin;
+ assemextern : as_darwin;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_macho;
+ dbg : dbg_dwarf2;
+ script : script_unix;
+ endian : endian_little;
+ alignment :
+ (
+ procalign : 8;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 8;
+ varalignmin : 0;
+ varalignmax : 16;
+ localalignmin : 4;
+ localalignmax : 16;
+ recordalignmin : 0;
+ recordalignmax : 16;
+ maxCrecordalign : 16
+ );
+ first_parm_offset : 16;
+ stacksize : 262144;
+ abi : abi_default;
+ );
+
+
+ system_arm_darwin_info : tsysteminfo =
+ (
+ system : system_arm_darwin;
+ name : 'Darwin for ARM';
+ shortname : 'Darwin';
+ flags : [tf_p_ext_support,tf_requires_proper_alignment,tf_files_case_sensitive,tf_smartlink_sections,tf_dwarf_relative_addresses,tf_dwarf_only_local_labels,tf_has_winlike_resources];
+ cpu : cpu_arm;
+ unit_env : 'BSDUNITS';
+ extradefines : 'UNIX;BSD;HASUNIX;CPUARMEL';
+ exeext : '';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.dylib';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : 'lib';
+ sharedClibext : '.dylib';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : 'lib';
+ importlibprefix : 'libimp';
+ importlibext : '.a';
+ Cprefix : '_';
+ newline : #10;
+ dirsep : '/';
+ assem : as_darwin;
+ assemextern : as_darwin;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_macho;
+ dbg : dbg_dwarf2;
+ script : script_unix;
+ endian : endian_little;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 8;
+ varalignmin : 0;
+ varalignmax : 8;
+ localalignmin : 4;
+ localalignmax : 8;
+ recordalignmin : 0;
+ recordalignmax : 8;
+ maxCrecordalign : 8
+ );
+ first_parm_offset : 8;
+ stacksize : 262144;
+ abi : abi_default
+ );
+
+ implementation
+
+initialization
+{$ifdef cpu86}
+ {$ifdef FreeBSD}
+ set_source_info(system_i386_FreeBSD_info);
+ {$endif}
+ {$ifdef NetBSD}
+ set_source_info(system_i386_NetBSD_info);
+ {$endif}
+ {$ifdef OpenBSD}
+ set_source_info(system_i386_OpenBSD_info);
+ {$endif}
+ {$ifdef Darwin}
+ set_source_info(system_i386_Darwin_info);
+ {$endif Darwin}
+{$endif cpu86}
+{$ifdef cpux86_64}
+ {$ifdef FreeBSD}
+ set_source_info(system_x86_64_FreeBSD_info);
+ {$endif}
+ {$ifdef Darwin}
+ set_source_info(system_x86_64_darwin_info);
+ {$endif}
+{$endif}
+{$ifdef cpu68}
+ {$ifdef NetBSD}
+ set_source_info(system_m68k_NetBSD_info);
+ {$endif NetBSD}
+{$endif cpu68}
+{$ifdef cpupowerpc32}
+ {$ifdef Darwin}
+ set_source_info(system_powerpc_darwin_info);
+ {$endif Darwin}
+ {$ifdef NetBSD}
+ set_source_info(system_powerpc_netbsd_info);
+ {$endif}
+{$endif cpupowerpc32}
+{$ifdef cpupowerpc64}
+ {$ifdef Darwin}
+ set_source_info(system_powerpc64_darwin_info);
+ {$endif Darwin}
+{$ifdef cpuarm}
+ {$ifdef Darwin}
+ set_source_info(system_arm_darwin_info);
+ {$endif Darwin}
+{$endif cpuarm}
+{$endif powerpc64}
+end.
diff --git a/closures/compiler/systems/i_embed.pas b/closures/compiler/systems/i_embed.pas
new file mode 100644
index 0000000000..da9a39b011
--- /dev/null
+++ b/closures/compiler/systems/i_embed.pas
@@ -0,0 +1,235 @@
+{
+ This unit implements support information structures for the FPC Embedded target
+
+ Copyright (c) 1998-2006 by Peter Vreman
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ ****************************************************************************
+}
+unit i_embed;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ systems;
+
+ const
+ system_arm_embedded_info : tsysteminfo =
+ (
+ system : system_arm_embedded;
+ name : 'Embedded';
+ shortname : 'embedded';
+ flags : [tf_needs_symbol_size,tf_files_case_sensitive,
+ tf_smartlink_sections];
+ cpu : cpu_arm;
+ unit_env : '';
+ extradefines : '';
+ exeext : '';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.so';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : 'lib';
+ sharedClibext : '.so';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : 'lib';
+ importlibprefix : 'libimp';
+ importlibext : '.a';
+ Cprefix : '';
+ newline : #10;
+ dirsep : '/';
+ assem : as_gas;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_none;
+ dbg : dbg_stabs;
+ script : script_unix;
+ endian : endian_little;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 4;
+ varalignmin : 0;
+ varalignmax : 4;
+ localalignmin : 4;
+ localalignmax : 8;
+ recordalignmin : 0;
+ recordalignmax : 4;
+ maxCrecordalign : 4
+ );
+ first_parm_offset : 8;
+ stacksize : 262144;
+ abi : abi_default
+ );
+
+ system_avr_embedded_info : tsysteminfo =
+ (
+ system : system_avr_embedded;
+ name : 'Embedded';
+ shortname : 'embedded';
+ flags : [tf_needs_symbol_size,tf_files_case_sensitive
+ ,tf_smartlink_sections];
+ cpu : cpu_avr;
+ unit_env : '';
+ extradefines : '';
+ exeext : '';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.so';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : 'lib';
+ sharedClibext : '.so';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : 'lib';
+ importlibprefix : 'libimp';
+ importlibext : '.a';
+ Cprefix : '';
+ newline : #10;
+ dirsep : '/';
+ assem : as_gas;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_none;
+ dbg : dbg_dwarf2;
+ script : script_unix;
+ endian : endian_little;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 4;
+ varalignmin : 0;
+ varalignmax : 4;
+ localalignmin : 4;
+ localalignmax : 8;
+ recordalignmin : 0;
+ recordalignmax : 4;
+ maxCrecordalign : 4
+ );
+ first_parm_offset : 0;
+ stacksize : 1024;
+ abi : abi_default
+ );
+
+ system_i386_embedded_info : tsysteminfo =
+ (
+ system : system_i386_embedded;
+ name : 'Embedded';
+ shortname : 'embedded';
+ flags : [tf_needs_symbol_size,tf_files_case_sensitive
+ ,tf_smartlink_sections];
+ cpu : cpu_i386;
+ unit_env : '';
+ extradefines : '';
+ exeext : '';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.so';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : 'lib';
+ sharedClibext : '.so';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : 'lib';
+ importlibprefix : 'libimp';
+ importlibext : '.a';
+ Cprefix : '';
+ newline : #10;
+ dirsep : '/';
+ assem : as_i386_elf32;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_none;
+ dbg : dbg_stabs;
+ script : script_unix;
+ endian : endian_little;
+ alignment :
+ (
+ procalign : 16;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 8;
+ varalignmin : 0;
+ varalignmax : 16;
+ localalignmin : 4;
+ localalignmax : 8;
+ recordalignmin : 0;
+ recordalignmax : 16;
+ maxCrecordalign : 4
+ );
+ first_parm_offset : 8;
+ stacksize : 4096;
+ abi : abi_default
+ );
+
+ implementation
+
+initialization
+{$ifdef CPUARM}
+ {$ifdef embedded}
+ set_source_info(system_arm_embedded_info);
+ {$endif embedded}
+{$endif CPUARM}
+{$ifdef CPUAVR}
+ {$ifdef embedded}
+ set_source_info(system_avr_embedded_info);
+ {$endif embedded}
+{$endif CPUAVR}
+{$ifdef CPUI386}
+ {$ifdef embedded}
+ set_source_info(system_i386_embedded_info);
+ {$endif embedded}
+{$endif CPUI386}
+end.
diff --git a/closures/compiler/systems/i_emx.pas b/closures/compiler/systems/i_emx.pas
new file mode 100644
index 0000000000..f192ec09d5
--- /dev/null
+++ b/closures/compiler/systems/i_emx.pas
@@ -0,0 +1,118 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ This unit implements support information structures for OS/2 via EMX
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ ****************************************************************************
+}
+{ This unit implements support information structures for OS/2 via EMX. }
+unit i_emx;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ systems;
+
+ const
+ res_wrc_os2_info : tresinfo =
+ (
+ id : res_watcom_wrc_os2;
+ resbin : '';
+ rescmd : '';
+ rcbin : 'wrc';
+ rccmd : '-r -zm -q -bt=os2 -fo=$RES $RC';
+ resourcefileclass : nil;
+ resflags : [res_single_file];
+ );
+
+ system_i386_emx_info : tsysteminfo =
+ (
+ system : system_i386_EMX;
+ name : 'OS/2 via EMX';
+ shortname : 'EMX';
+ flags : [tf_need_export,tf_use_8_3];
+ cpu : cpu_i386;
+ unit_env : 'EMXUNITS';
+ extradefines : 'OS2';
+ exeext : '.exe';
+ defext : '.def';
+ scriptext : '.cmd';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.dll';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : '';
+ sharedClibext : '.dll';
+ staticClibext : '.a';
+ staticClibprefix : '';
+ sharedClibprefix : '';
+ importlibprefix : '';
+ importlibext : '.a';
+ Cprefix : '_';
+ newline : #13#10;
+ dirsep : '\';
+ assem : as_i386_as_aout;
+ assemextern : as_i386_as_aout;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_watcom_wrc_os2;
+ dbg : dbg_stabs;
+ script : script_dos;
+ endian : endian_little;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 4;
+ varalignmin : 0;
+ varalignmax : 4;
+ localalignmin : 0;
+ localalignmax : 4;
+ recordalignmin : 0;
+ recordalignmax : 2;
+ maxCrecordalign : 4
+ );
+ first_parm_offset : 8;
+ stacksize : 256*1024;
+ abi : abi_default;
+ );
+
+
+ implementation
+
+initialization
+{$ifdef CPU86}
+ {$ifdef EMX}
+ {$IFNDEF VER1_0}
+ set_source_info(system_i386_emx_info);
+ { OS/2 via EMX can be run under DOS as well }
+ if (OS_Mode=osDOS) or (OS_Mode=osDPMI) then
+ source_info.scriptext := '.bat';
+ {$ENDIF VER1_0}
+ {$endif EMX}
+{$endif CPU86}
+end.
diff --git a/closures/compiler/systems/i_gba.pas b/closures/compiler/systems/i_gba.pas
new file mode 100644
index 0000000000..aa4480d933
--- /dev/null
+++ b/closures/compiler/systems/i_gba.pas
@@ -0,0 +1,102 @@
+{
+ This unit implements support information structures for GameBoy Advance
+
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ ****************************************************************************
+}
+{ This unit implements support information structures for gba. }
+unit i_gba;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ systems;
+
+ const
+ system_arm_gba_info : tsysteminfo =
+ (
+ system : system_arm_gba;
+ name : 'GameBoy Advance';
+ shortname : 'gba';
+ flags : [tf_needs_symbol_size,tf_files_case_sensitive,
+ tf_requires_proper_alignment,tf_smartlink_sections];
+ cpu : cpu_arm;
+ unit_env : '';
+ extradefines : '';
+ exeext : '.gba';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.so';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : 'lib';
+ sharedClibext : '.so';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : 'lib';
+ importlibprefix : 'libimp';
+ importlibext : '.a';
+ Cprefix : '';
+ newline : #10;
+ dirsep : '/';
+ assem : as_gas;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_none;
+ dbg : dbg_stabs;
+ script : script_unix;
+ endian : endian_little;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 8;
+ varalignmin : 0;
+ varalignmax : 8;
+ localalignmin : 4;
+ localalignmax : 8;
+ recordalignmin : 0;
+ recordalignmax : 8;
+ maxCrecordalign : 8
+ );
+ first_parm_offset : 8;
+ stacksize : 16384;
+ abi : abi_eabi
+ );
+
+ implementation
+
+initialization
+{$ifdef arm}
+ {$ifdef gba}
+ set_source_info(system_arm_gba_info);
+ {$endif gba}
+{$endif arm}
+end.
diff --git a/closures/compiler/systems/i_go32v2.pas b/closures/compiler/systems/i_go32v2.pas
new file mode 100644
index 0000000000..8b0121e804
--- /dev/null
+++ b/closures/compiler/systems/i_go32v2.pas
@@ -0,0 +1,101 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ This unit implements support information structures for go32v2
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ ****************************************************************************
+}
+{ This unit implements support information structures for go32v2. }
+unit i_go32v2;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ systems;
+
+ const
+ system_i386_go32v2_info : tsysteminfo =
+ (
+ system : system_i386_GO32V2;
+ name : 'GO32 V2 DOS extender';
+ shortname : 'Go32v2';
+ flags : [tf_use_8_3,tf_smartlink_library];
+ cpu : cpu_i386;
+ unit_env : 'GO32V2UNITS';
+ extradefines : 'DPMI';
+ exeext : '.exe';
+ defext : '.def';
+ scriptext : '.bat';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.dll';
+ staticlibext : '.a';
+ staticlibprefix : '';
+ sharedlibprefix : '';
+ sharedClibext : '.dll';
+ staticClibext : '.a';
+ staticClibprefix : '';
+ sharedClibprefix : '';
+ importlibprefix : '';
+ importlibext : '.al';
+ Cprefix : '_';
+ newline : #13#10;
+ dirsep : '\';
+ assem : as_i386_coff;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_none;
+ dbg : dbg_stabs;
+ script : script_dos;
+ endian : endian_little;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 4;
+ varalignmin : 0;
+ varalignmax : 4;
+ localalignmin : 0;
+ localalignmax : 4;
+ recordalignmin : 0;
+ recordalignmax : 2;
+ maxCrecordalign : 4
+ );
+ first_parm_offset : 8;
+ stacksize : 262144;
+ abi : abi_default;
+ );
+
+ implementation
+
+initialization
+{$ifdef cpu86}
+ {$ifdef go32v2}
+ set_source_info(system_i386_go32v2_info);
+ {$endif go32v2}
+{$endif cpu86}
+end.
diff --git a/closures/compiler/systems/i_haiku.pas b/closures/compiler/systems/i_haiku.pas
new file mode 100644
index 0000000000..daf303acf6
--- /dev/null
+++ b/closures/compiler/systems/i_haiku.pas
@@ -0,0 +1,113 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman
+ Copyright (c) 2008-2008 by Olivier Coursière
+
+ This unit implements support information structures for Haiku
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ ****************************************************************************
+}
+{ This unit implements support information structures for Haiku. }
+unit i_haiku;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ systems;
+
+ const
+ system_i386_haiku_info : tsysteminfo =
+ (
+ system : system_i386_Haiku;
+ name : 'Haiku for i386';
+ shortname : 'Haiku';
+ flags : [tf_under_development,tf_needs_symbol_size,tf_files_case_sensitive,
+ tf_smartlink_sections, tf_smartlink_library, tf_has_winlike_resources];
+ cpu : cpu_i386;
+ unit_env : 'HAIKUUNITS';
+ extradefines : 'BEOS;UNIX;HASUNIX';
+ exeext : '';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.so';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : 'lib';
+ sharedClibext : '.so';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : 'lib';
+ importlibprefix : 'libimp';
+ importlibext : '.a';
+ Cprefix : '';
+ newline : #10;
+ dirsep : '/';
+ assem : as_i386_elf32;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_elf;
+ dbg : dbg_stabs;
+ script : script_unix;
+ endian : endian_little;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 4;
+ varalignmin : 0;
+ varalignmax : 4;
+ localalignmin : 0;
+ localalignmax : 4;
+ recordalignmin : 0;
+ recordalignmax : 2;
+ maxCrecordalign : 4
+ );
+ first_parm_offset : 8;
+ { Stack size used to be 256 K under BeOS. So, it was the value
+ used in previous version of FPC for BeOS (but lost in the road
+ to 2.* ;-).
+ According to buildtools/gcc/gcc/config/i386/beos-elf.h in the
+ Haiku's repository, this value was increased to 1Mb since r4.1b3.
+ Under R5, this value is even greater. listarea report a default
+ size of 16 Mb for the user stack of the main thread.
+ People who still use BeOS nowadays should use R5 (or Haiku),
+ so i use this new value.
+ }
+ stacksize : 16 * 1024 * 1024;
+ abi : abi_default
+ );
+
+ implementation
+
+initialization
+{$ifdef cpu86}
+ {$ifdef haiku}
+ set_source_info(system_i386_haiku_info);
+ {$endif haiku}
+{$endif cpu86}
+end.
diff --git a/closures/compiler/systems/i_linux.pas b/closures/compiler/systems/i_linux.pas
new file mode 100644
index 0000000000..703ddcaf93
--- /dev/null
+++ b/closures/compiler/systems/i_linux.pas
@@ -0,0 +1,909 @@
+{
+ Copyright (c) 1998-2008 by Peter Vreman
+
+ This unit implements support information structures for linux
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ ****************************************************************************
+}
+{ This unit implements support information structures for linux. }
+unit i_linux;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ systems, rescmn;
+
+ const
+ system_i386_linux_info : tsysteminfo =
+ (
+ system : system_i386_LINUX;
+ name : 'Linux for i386';
+ shortname : 'Linux';
+ flags : [tf_needs_symbol_size,tf_pic_uses_got{,tf_smartlink_sections}{,tf_winlikewidestring},
+{$ifdef segment_threadvars}
+ tf_section_threadvars,
+{$endif segment_threadvars}
+ tf_needs_symbol_type,tf_files_case_sensitive,
+ tf_smartlink_library,tf_needs_dwarf_cfi,tf_has_winlike_resources,
+ tf_safecall_exceptions, tf_safecall_clearstack];
+ cpu : cpu_i386;
+ unit_env : 'LINUXUNITS';
+ extradefines : 'UNIX;HASUNIX';
+ exeext : '';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.so';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : 'lib';
+ sharedClibext : '.so';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : 'lib';
+ importlibprefix : 'libimp';
+ importlibext : '.a';
+ Cprefix : '';
+ newline : #10;
+ dirsep : '/';
+ assem : as_i386_elf32;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_elf;
+ dbg : dbg_stabs;
+ script : script_unix;
+ endian : endian_little;
+ alignment :
+ (
+ procalign : 16;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 8;
+ varalignmin : 0;
+ varalignmax : 16;
+ localalignmin : 4;
+ localalignmax : 8;
+ recordalignmin : 0;
+ recordalignmax : 16;
+ maxCrecordalign : 4
+ );
+ first_parm_offset : 8;
+ stacksize : 8*1024*1024;
+ abi : abi_default
+ );
+
+ system_x86_6432_linux_info : tsysteminfo =
+ (
+ system : system_x86_6432_LINUX;
+ name : 'Linux for x64_6432';
+ shortname : 'Linux6432';
+ flags : [tf_needs_symbol_size,tf_needs_symbol_type,tf_files_case_sensitive,
+ tf_pic_uses_got{,tf_smartlink_sections},
+ tf_smartlink_library,tf_has_winlike_resources];
+ cpu : cpu_x86_64;
+ unit_env : 'LINUXUNITS';
+ extradefines : 'UNIX;HASUNIX';
+ exeext : '';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.so';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : 'lib';
+ sharedClibext : '.so';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : 'lib';
+ importlibprefix : 'libimp';
+ importlibext : '.a';
+ Cprefix : '';
+ newline : #10;
+ dirsep : '/';
+ assem : as_i386_elf32;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_elf;
+ dbg : dbg_stabs;
+ script : script_unix;
+ endian : endian_little;
+ alignment :
+ (
+ procalign : 16;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 16;
+ varalignmin : 0;
+ varalignmax : 16;
+ localalignmin : 4;
+ localalignmax : 8;
+ recordalignmin : 0;
+ recordalignmax : 16;
+ maxCrecordalign : 4
+ );
+ first_parm_offset : 8;
+ stacksize : 8*1024*1024;
+ abi : abi_default
+ );
+
+ system_m68k_linux_info : tsysteminfo =
+ (
+ system : system_m68k_linux;
+ name : 'Linux for m68k';
+ shortname : 'Linux';
+ flags : [tf_needs_symbol_size,tf_needs_symbol_type,tf_files_case_sensitive,
+ tf_smartlink_library,tf_has_winlike_resources];
+ cpu : cpu_m68k;
+ unit_env : 'LINUXUNITS';
+ extradefines : 'UNIX;HASUNIX';
+ exeext : '';
+ defext : '';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.so';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : 'lib';
+ sharedClibext : '.so';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : 'lib';
+ importlibprefix : 'libimp';
+ importlibext : '.a';
+ Cprefix : '';
+ newline : #10;
+ dirsep : '/';
+ assem : as_gas;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_elf;
+ dbg : dbg_stabs;
+ script : script_unix;
+ endian : endian_big;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 4;
+ varalignmin : 0;
+ varalignmax : 4;
+ localalignmin : 4;
+ localalignmax : 4;
+ recordalignmin : 0;
+ recordalignmax : 2;
+ maxCrecordalign : 4
+ );
+ first_parm_offset : 8;
+ stacksize : 32*1024*1024;
+ abi : abi_default
+ );
+
+ system_powerpc_linux_info : tsysteminfo =
+ (
+ system : system_powerpc_LINUX;
+ name : 'Linux for PowerPC';
+ shortname : 'Linux';
+ flags : [tf_needs_symbol_size,tf_needs_symbol_type,tf_files_case_sensitive,
+ tf_smartlink_library,tf_has_winlike_resources];
+ cpu : cpu_powerpc;
+ unit_env : '';
+ extradefines : 'UNIX;HASUNIX';
+ exeext : '';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.so';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : 'lib';
+ sharedClibext : '.so';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : 'lib';
+ importlibprefix : 'libimp';
+ importlibext : '.a';
+ Cprefix : '';
+ newline : #10;
+ dirsep : '/';
+ assem : as_gas;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_elf;
+ dbg : dbg_stabs;
+ script : script_unix;
+ endian : endian_big;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 4;
+ varalignmin : 0;
+ varalignmax : 4;
+ localalignmin : 4;
+ localalignmax : 4;
+ recordalignmin : 0;
+ recordalignmax : 4;
+ maxCrecordalign : 8
+ );
+ first_parm_offset : 8;
+ stacksize : 32*1024*1024;
+ abi : abi_powerpc_sysv;
+ );
+
+ system_powerpc64_linux_info : tsysteminfo =
+ (
+ system : system_powerpc64_LINUX;
+ name : 'Linux for PowerPC64';
+ shortname : 'Linux';
+ flags : [tf_needs_symbol_size,tf_needs_symbol_type,tf_files_case_sensitive,
+ tf_requires_proper_alignment,tf_smartlink_sections,tf_has_winlike_resources];
+ cpu : cpu_powerpc64;
+ unit_env : '';
+ extradefines : 'UNIX;HASUNIX';
+ exeext : '';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.so';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : 'lib';
+ sharedClibext : '.so';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : 'lib';
+ importlibprefix : 'libimp';
+ importlibext : '.a';
+ Cprefix : '';
+ newline : #10;
+ dirsep : '/';
+ assem : as_gas;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_elf;
+ dbg : dbg_dwarf2;
+ script : script_unix;
+ endian : endian_big;
+ alignment :
+ (
+ procalign : 8;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 4;
+ constalignmax : 16;
+ varalignmin : 4;
+ varalignmax : 16;
+ localalignmin : 0;
+ localalignmax : 16;
+ recordalignmin : 0;
+ recordalignmax : 16;
+ maxCrecordalign : 16
+ );
+ first_parm_offset : 8;
+ stacksize : 10*1024*1024;
+ abi : abi_powerpc_sysv
+ );
+
+ system_alpha_linux_info : tsysteminfo =
+ (
+ system : system_alpha_LINUX;
+ name : 'Linux for Alpha';
+ shortname : 'Linux';
+ flags : [tf_needs_symbol_size,tf_needs_symbol_type,tf_files_case_sensitive,
+ tf_smartlink_library,tf_has_winlike_resources];
+ cpu : cpu_alpha;
+ unit_env : 'LINUXUNITS';
+ extradefines : 'UNIX;HASUNIX';
+ exeext : '';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.so';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : 'lib';
+ sharedClibext : '.so';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : 'lib';
+ importlibprefix : 'libimp';
+ importlibext : '.a';
+ Cprefix : '';
+ newline : #10;
+ dirsep : '/';
+ assem : as_gas;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_elf;
+ dbg : dbg_stabs;
+ script : script_unix;
+ endian : endian_little;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 4;
+ varalignmin : 0;
+ varalignmax : 4;
+ localalignmin : 4;
+ localalignmax : 4;
+ recordalignmin : 0;
+ recordalignmax : 2;
+ maxCrecordalign : 4
+ );
+ first_parm_offset : 8;
+ stacksize : 32*1024*1024;
+ abi : abi_default
+ );
+
+ system_x86_64_linux_info : tsysteminfo =
+ (
+ system : system_x86_64_LINUX;
+ name : 'Linux for x86-64';
+ shortname : 'Linux';
+ flags : [tf_needs_symbol_size,tf_needs_dwarf_cfi,tf_smartlink_library,
+ tf_library_needs_pic,tf_needs_symbol_type,tf_files_case_sensitive,
+ tf_has_winlike_resources,tf_safecall_exceptions,tf_safecall_clearstack];
+ cpu : cpu_x86_64;
+ unit_env : 'LINUXUNITS';
+ extradefines : 'UNIX;HASUNIX';
+ exeext : '';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.so';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : 'lib';
+ sharedClibext : '.so';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : 'lib';
+ importlibprefix : 'libimp';
+ importlibext : '.a';
+ Cprefix : '';
+ newline : #10;
+ dirsep : '/';
+ assem : as_x86_64_elf64;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_elf;
+ dbg : dbg_dwarf2;
+ script : script_unix;
+ endian : endian_little;
+ alignment :
+ (
+ procalign : 8;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 8;
+ varalignmin : 0;
+ varalignmax : 16;
+ localalignmin : 4;
+ localalignmax : 16;
+ recordalignmin : 0;
+ recordalignmax : 16;
+ maxCrecordalign : 16
+ );
+ first_parm_offset : 16;
+ stacksize : 8*1024*1024;
+ abi : abi_default
+ );
+
+ system_sparc_linux_info : tsysteminfo =
+ (
+ system : system_SPARC_Linux;
+ name : 'Linux for SPARC';
+ shortname : 'Linux';
+ flags : [tf_needs_symbol_size,tf_library_needs_pic,tf_smartlink_sections,
+ tf_needs_symbol_type,tf_files_case_sensitive,tf_smartlink_library,
+ tf_requires_proper_alignment,
+ tf_has_winlike_resources];
+ cpu : cpu_SPARC;
+ unit_env : 'LINUXUNITS';
+ extradefines : 'UNIX;HASUNIX';
+ exeext : '';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.so';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : 'lib';
+ sharedClibext : '.so';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : 'lib';
+ importlibprefix : 'libimp';
+ importlibext : '.a';
+ Cprefix : '';
+ newline : #10;
+ dirsep : '/';
+ assem : as_gas;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_elf;
+ dbg : dbg_stabs;
+ script : script_unix;
+ endian : endian_big;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 4;
+ constalignmax : 8;
+ varalignmin : 4;
+ varalignmax : 8;
+ localalignmin : 4;
+ localalignmax : 8;
+ recordalignmin : 0;
+ recordalignmax : 8;
+ maxCrecordalign : 8
+ );
+ first_parm_offset : 92;
+ stacksize : 8*1024*1024;
+ abi : abi_default
+ );
+
+{$ifdef FPC_ARMEL}
+ system_arm_linux_info : tsysteminfo =
+ (
+ system : system_arm_Linux;
+ name : 'Linux for ARMEL';
+ shortname : 'Linux';
+ flags : [tf_needs_symbol_size,tf_needs_symbol_type,tf_files_case_sensitive,
+ tf_requires_proper_alignment,
+ tf_smartlink_sections,tf_smartlink_library,tf_has_winlike_resources];
+ cpu : cpu_arm;
+ unit_env : 'LINUXUNITS';
+ extradefines : 'UNIX;HASUNIX;CPUARMEL';
+ exeext : '';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.so';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : 'lib';
+ sharedClibext : '.so';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : 'lib';
+ importlibprefix : 'libimp';
+ importlibext : '.a';
+ Cprefix : '';
+ newline : #10;
+ dirsep : '/';
+ assem : as_gas;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_elf;
+ dbg : dbg_stabs;
+ script : script_unix;
+ endian : endian_little;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 8;
+ varalignmin : 0;
+ varalignmax : 8;
+ localalignmin : 4;
+ localalignmax : 8;
+ recordalignmin : 0;
+ recordalignmax : 8;
+ maxCrecordalign : 8
+ );
+ first_parm_offset : 8;
+ stacksize : 8*1024*1024;
+ abi : abi_eabi
+ );
+{$else FPC_ARMEL}
+{$ifdef FPC_ARMEB}
+ system_arm_linux_info : tsysteminfo =
+ (
+ system : system_arm_Linux;
+ name : 'Linux for ARMEB';
+ shortname : 'Linux';
+ flags : [tf_needs_symbol_size,tf_needs_symbol_type,tf_files_case_sensitive,
+ tf_requires_proper_alignment,
+ tf_smartlink_sections,tf_smartlink_library,tf_has_winlike_resources];
+ cpu : cpu_arm;
+ unit_env : 'LINUXUNITS';
+ extradefines : 'UNIX;HASUNIX;CPUARMEB';
+ exeext : '';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.so';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : 'lib';
+ sharedClibext : '.so';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : 'lib';
+ importlibprefix : 'libimp';
+ importlibext : '.a';
+ Cprefix : '';
+ newline : #10;
+ dirsep : '/';
+ assem : as_gas;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_elf;
+ dbg : dbg_stabs;
+ script : script_unix;
+ endian : endian_big;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 4;
+ varalignmin : 0;
+ varalignmax : 4;
+ localalignmin : 4;
+ localalignmax : 8;
+ recordalignmin : 0;
+ recordalignmax : 4;
+ maxCrecordalign : 4
+ );
+ first_parm_offset : 8;
+ stacksize : 8*1024*1024;
+ abi : abi_default
+ );
+{$else FPC_ARMEB}
+ system_arm_linux_info : tsysteminfo =
+ (
+ system : system_arm_Linux;
+ name : 'Linux for ARM';
+ shortname : 'Linux';
+ flags : [tf_needs_symbol_size,tf_needs_symbol_type,tf_files_case_sensitive,
+ tf_requires_proper_alignment,
+ tf_smartlink_sections,tf_smartlink_library,tf_has_winlike_resources];
+ cpu : cpu_arm;
+ unit_env : 'LINUXUNITS';
+ extradefines : 'UNIX;HASUNIX';
+ exeext : '';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.so';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : 'lib';
+ sharedClibext : '.so';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : 'lib';
+ importlibprefix : 'libimp';
+ importlibext : '.a';
+ Cprefix : '';
+ newline : #10;
+ dirsep : '/';
+ assem : as_gas;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_elf;
+ dbg : dbg_stabs;
+ script : script_unix;
+ endian : endian_little;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 4;
+ varalignmin : 0;
+ varalignmax : 4;
+ localalignmin : 4;
+ localalignmax : 4;
+ recordalignmin : 0;
+ recordalignmax : 4;
+ maxCrecordalign : 4
+ );
+ first_parm_offset : 8;
+ stacksize : 8*1024*1024;
+ abi : abi_default
+ );
+{$endif FPC_ARMEB}
+{$endif FPC_ARMEL}
+
+ system_mips_linux_info : tsysteminfo =
+ (
+ system : system_mips_LINUX;
+ name : 'Linux for MIPS';
+ shortname : 'Linux';
+ flags : [tf_needs_symbol_size,tf_needs_symbol_type,tf_files_case_sensitive,
+ tf_requires_proper_alignment,
+ tf_smartlink_sections,tf_smartlink_library,tf_has_winlike_resources];
+ cpu : cpu_mips;
+ unit_env : 'LINUXUNITS';
+ extradefines : 'UNIX;HASUNIX';
+ exeext : '';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.so';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : 'lib';
+ sharedClibext : '.so';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : 'lib';
+ importlibprefix : 'libimp';
+ importlibext : '.a';
+// p_ext_support : false;
+ Cprefix : '';
+ newline : #10;
+ dirsep : '/';
+ assem : as_gas;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_none;
+ dbg : dbg_stabs;
+ script : script_unix;
+ endian : endian_big;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 8;
+ varalignmin : 0;
+ varalignmax : 8;
+ localalignmin : 4;
+ localalignmax : 8;
+ recordalignmin : 0;
+ recordalignmax : 2;
+ maxCrecordalign : 4
+ );
+ first_parm_offset : 8;
+ stacksize : 32*1024*1024;
+ abi : abi_default
+ );
+
+ system_mipsel_linux_info : tsysteminfo =
+ (
+ system : system_mipsel_LINUX;
+ name : 'Linux for MIPSEL';
+ shortname : 'Linux';
+ flags : [tf_needs_symbol_size,tf_needs_symbol_type,tf_files_case_sensitive,
+ tf_requires_proper_alignment,
+ tf_smartlink_sections,tf_smartlink_library,tf_has_winlike_resources];
+ cpu : cpu_mipsel;
+ unit_env : 'LINUXUNITS';
+ extradefines : 'UNIX;HASUNIX;MIPSEL';
+ exeext : '';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.so';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : 'lib';
+ sharedClibext : '.so';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : 'lib';
+ importlibprefix : 'libimp';
+ importlibext : '.a';
+// p_ext_support : false;
+ Cprefix : '';
+ newline : #10;
+ dirsep : '/';
+ assem : as_gas;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_none;
+ dbg : dbg_stabs;
+ script : script_unix;
+ endian : endian_little;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 8;
+ varalignmin : 0;
+ varalignmax : 8;
+ localalignmin : 4;
+ localalignmax : 8;
+ recordalignmin : 0;
+ recordalignmax : 2;
+ maxCrecordalign : 4
+ );
+ first_parm_offset : 8;
+ stacksize : 32*1024*1024;
+ abi : abi_default
+ );
+
+ implementation
+
+initialization
+{$ifdef CPU86}
+ {$ifdef linux}
+ { some FreeBSD versions define linux as well }
+ {$ifndef FreeBSD}
+ set_source_info(system_i386_linux_info);
+ {$endif FreeBSD}
+ {$endif}
+{$endif CPU86}
+{$ifdef CPU68}
+ {$ifdef linux}
+ set_source_info(system_m68k_linux_info);
+ {$endif linux}
+{$endif CPU68}
+{$ifdef CPUX86_64}
+ {$ifdef linux}
+ set_source_info(system_x86_64_linux_info);
+ {$endif linux}
+{$endif CPUX86_64}
+{$ifdef CPUALPHA}
+ {$ifdef linux}
+ set_source_info(system_alpha_linux_info);
+ {$endif linux}
+{$endif CPUALPHA}
+{$ifdef CPUSPARC}
+ {$ifdef linux}
+ set_source_info(system_sparc_linux_info);
+ {$endif linux}
+{$endif CPUSPARC}
+{$ifdef CPUPOWERPC32}
+ {$ifdef linux}
+ set_source_info(system_powerpc_linux_info);
+ {$endif linux}
+{$endif CPUPOWERPC32}
+{$ifdef CPUPOWERPC64}
+ {$ifdef linux}
+ set_source_info(system_powerpc64_linux_info);
+ {$endif linux}
+{$endif CPUPOWERPC64}
+{$ifdef CPUARM}
+ {$ifdef linux}
+ set_source_info(system_arm_linux_info);
+ {$endif linux}
+{$endif CPUARM}
+{$ifdef CPUMIPS}
+ {$ifdef linux}
+ set_source_info(system_mipsel_linux_info);
+ {$endif linux}
+{$endif CPUMIPS}
+end.
diff --git a/closures/compiler/systems/i_macos.pas b/closures/compiler/systems/i_macos.pas
new file mode 100644
index 0000000000..4ab18d0c07
--- /dev/null
+++ b/closures/compiler/systems/i_macos.pas
@@ -0,0 +1,100 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ This unit implements support information structures for MacOS
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ ****************************************************************************
+}
+{ This unit implements support information structures for MacOS. }
+unit i_macos;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ systems;
+ const
+ system_powerpc_macos_info : tsysteminfo =
+ (
+ system : system_powerpc_MACOS;
+ name : 'Mac OS for PowerPC';
+ shortname : 'MacOS';
+ flags : [tf_p_ext_support,tf_files_case_aware];
+ cpu : cpu_powerpc;
+ unit_env : '';
+ extradefines : '';
+ exeext : '';
+ defext : '';
+ scriptext : '';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : 'Lib';
+ staticlibext : 'Lib';
+ staticlibprefix : '';
+ sharedlibprefix : '';
+ sharedClibext : 'Lib';
+ staticClibext : 'Lib';
+ staticClibprefix : '';
+ sharedClibprefix : '';
+ importlibprefix : 'imp';
+ importlibext : 'Lib';
+ Cprefix : '';
+ newline : #13;
+ dirsep : ':';
+ assem : as_powerpc_mpw;
+ assemextern : as_powerpc_mpw;
+ link : nil;
+ linkextern : nil;
+ ar : ar_mpw_ar;
+ res : res_powerpc_mpw;
+ dbg : dbg_stabs;
+ script : script_mpw;
+ endian : endian_big;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 4;
+ varalignmin : 0;
+ varalignmax : 4;
+ localalignmin : 8;
+ localalignmax : 8;
+ recordalignmin : 0;
+ recordalignmax : 2;
+ maxCrecordalign : 16
+ );
+ first_parm_offset : 8;
+ stacksize : 262144;
+ abi : abi_powerpc_aix;
+ );
+
+ implementation
+
+initialization
+{$ifdef cpupowerpc}
+ {$ifdef macos}
+ set_source_info(system_powerpc_macos_info);
+ {$endif macos}
+{$endif cpupowerpc}
+end.
diff --git a/closures/compiler/systems/i_morph.pas b/closures/compiler/systems/i_morph.pas
new file mode 100644
index 0000000000..f6de90967b
--- /dev/null
+++ b/closures/compiler/systems/i_morph.pas
@@ -0,0 +1,101 @@
+{
+ Copyright (c) 2004 by Free Pascal Development Team
+
+ This unit implements support information structures for MorphOS
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ ****************************************************************************
+}
+{ This unit implements support information structures for the MorphOS. }
+unit i_morph;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ systems;
+
+ const
+ system_powerpc_MorphOS_info : tsysteminfo =
+ (
+ system : system_powerpc_MorphOS;
+ name : 'MorphOS';
+ shortname : 'MorphOS';
+ flags : [tf_files_case_aware,tf_smartlink_library];
+ cpu : cpu_powerpc;
+ unit_env : '';
+ extradefines : '';
+ exeext : '';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.library';
+ staticlibext : '.a';
+ staticlibprefix : 'lib';
+ sharedlibprefix : '';
+ sharedClibext : '.library';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : '';
+ importlibprefix : 'libimp';
+ importlibext : '.a';
+ Cprefix : '';
+ newline : #10;
+ dirsep : '/';
+ assem : as_gas;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_none;
+ dbg : dbg_stabs;
+ script : script_amiga;
+ endian : endian_big;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 4;
+ varalignmin : 0;
+ varalignmax : 4;
+ localalignmin : 0;
+ localalignmax : 4;
+ recordalignmin : 0;
+ recordalignmax : 4;
+ maxCrecordalign : 4
+ );
+ first_parm_offset : 8;
+ stacksize : 262144;
+ abi : abi_powerpc_sysv;
+ );
+
+ implementation
+
+initialization
+{$ifdef CPUPOWERPC}
+ {$ifdef MORPHOS}
+ set_source_info(system_powerpc_MorphOS_info);
+ {$endif MORPHOS}
+{$endif CPUPOWERPC}
+end.
diff --git a/closures/compiler/systems/i_nativent.pas b/closures/compiler/systems/i_nativent.pas
new file mode 100644
index 0000000000..a9bf61b0eb
--- /dev/null
+++ b/closures/compiler/systems/i_nativent.pas
@@ -0,0 +1,106 @@
+{
+ Copyright (c) 2009 by Sven Barth
+
+ This unit implements support information structures for nativent
+ Based on Peter Vreman's i_win
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ ****************************************************************************
+}
+{ This unit implements support information structures for nativent. }
+unit i_nativent;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ systems;
+
+ const
+ system_i386_nativent_info : tsysteminfo =
+ (
+ system : system_i386_NATIVENT;
+ name : 'Native NT for i386';
+ shortname : 'NativeNT';
+ flags : [tf_files_case_aware,tf_use_function_relative_addresses,tf_smartlink_library
+ ,tf_smartlink_sections{,tf_section_threadvars}{,tf_needs_dwarf_cfi},
+ tf_no_pic_supported,
+ tf_no_generic_stackcheck{,tf_has_winlike_resources},tf_under_development,
+ tf_dwarf_only_local_labels];
+ cpu : cpu_i386;
+ unit_env : 'NTUNITS';
+ extradefines : 'NATIVENT,UNICODE';
+ exeext : '.exe';
+ defext : '.def';
+ scriptext : '.bat';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.dll';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : '';
+ sharedClibext : '.dll';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : '';
+ importlibprefix : 'libimp';
+ importlibext : '.a';
+ Cprefix : '_';
+ newline : #13#10;
+ dirsep : '\';
+ assem : as_i386_pecoff;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_gnu_windres;
+ dbg : dbg_stabs;
+ script : script_dos;
+ endian : endian_little;
+ alignment :
+ (
+ procalign : 16;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 16;
+ varalignmin : 0;
+ varalignmax : 16;
+ localalignmin : 4;
+ localalignmax : 8;
+ recordalignmin : 0;
+ recordalignmax : 4;
+ maxCrecordalign : 16
+ );
+ first_parm_offset : 8;
+ stacksize : 16*1024*1024;
+ abi : abi_default;
+ );
+
+ implementation
+
+initialization
+{$ifdef CPU86}
+ {$ifdef NATIVENT}
+ set_source_info(system_i386_nativent_info);
+ {$endif NATIVENT}
+{$endif CPU86}
+end.
diff --git a/closures/compiler/systems/i_nds.pas b/closures/compiler/systems/i_nds.pas
new file mode 100644
index 0000000000..245fe7b6c9
--- /dev/null
+++ b/closures/compiler/systems/i_nds.pas
@@ -0,0 +1,102 @@
+{
+ This unit implements support information structures for Nintendo DS
+
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ ****************************************************************************
+}
+{ This unit implements support information structures for nds. }
+unit i_nds;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ systems;
+
+ const
+ system_arm_nds_info : tsysteminfo =
+ (
+ system : system_arm_nds;
+ name : 'Nintendo DS';
+ shortname : 'nds';
+ flags : [tf_needs_symbol_size,tf_files_case_sensitive,
+ tf_requires_proper_alignment,tf_smartlink_sections];
+ cpu : cpu_arm;
+ unit_env : '';
+ extradefines : '';
+ exeext : '.bin';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.so';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : 'lib';
+ sharedClibext : '.so';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : 'lib';
+ importlibprefix : 'libimp';
+ importlibext : '.a';
+ Cprefix : '';
+ newline : #10;
+ dirsep : '/';
+ assem : as_gas;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_none;
+ dbg : dbg_stabs;
+ script : script_unix;
+ endian : endian_little;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 8;//4;
+ varalignmin : 0;
+ varalignmax : 8;//4;
+ localalignmin : 4;
+ localalignmax : 8;
+ recordalignmin : 0;
+ recordalignmax : 8;//4;
+ maxCrecordalign : 8//4
+ );
+ first_parm_offset : 8;
+ stacksize : $3CFF; //15615? or 16384?;
+ abi : abi_eabi
+ );
+
+ implementation
+
+initialization
+{$ifdef arm}
+ {$ifdef nds}
+ set_source_info(system_arm_nds_info);
+ {$endif nds}
+{$endif arm}
+end.
diff --git a/closures/compiler/systems/i_nwl.pas b/closures/compiler/systems/i_nwl.pas
new file mode 100644
index 0000000000..b2c47219c0
--- /dev/null
+++ b/closures/compiler/systems/i_nwl.pas
@@ -0,0 +1,101 @@
+{
+ Copyright (c) 1998-2004 by Peter Vreman
+
+ This unit implements support information structures for Netware (libc) modules
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ ****************************************************************************}
+
+{ This unit implements support information structures for Netware libc modules. }
+unit i_nwl;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ systems;
+
+ const
+ system_i386_netwlibc_info : tsysteminfo =
+ (
+ system : system_i386_netwlibc;
+ name : 'Netware for i386(libc)';
+ shortname : 'Netwlibc';
+ flags : [tf_smartlink_library];
+ cpu : cpu_i386;
+ unit_env : 'NETWLIBCUNITS';
+ extradefines : 'NETWARE;NETWARE_LIBC';
+ exeext : '.nlm';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.nlm';
+ staticlibext : '.a';
+ staticlibprefix : '';
+ sharedlibprefix : '';
+ sharedClibext : '.nlm';
+ staticClibext : '.a';
+ staticClibprefix : '';
+ sharedClibprefix : '';
+ importlibprefix : 'imp';
+ importlibext : '.a';
+ Cprefix : '';
+ newline : #13#10;
+ dirsep : '/';
+ assem : as_i386_elf32;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_none;
+ dbg : dbg_stabs;
+ script : script_unix;
+ endian : endian_little;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 4;
+ varalignmin : 0;
+ varalignmax : 4;
+ localalignmin : 4;
+ localalignmax : 4;
+ recordalignmin : 0;
+ recordalignmax : 4;
+ maxCrecordalign : 4
+ );
+ first_parm_offset : 8;
+ stacksize : 16384;
+ abi : abi_default
+ );
+
+ implementation
+
+initialization
+{$ifdef CPU86}
+ {$ifdef netwlibc}
+ set_source_info(system_i386_netwlibc_info);
+ {$endif netwlibc}
+{$endif CPU86}
+end.
diff --git a/closures/compiler/systems/i_nwm.pas b/closures/compiler/systems/i_nwm.pas
new file mode 100644
index 0000000000..307f2fee8f
--- /dev/null
+++ b/closures/compiler/systems/i_nwm.pas
@@ -0,0 +1,101 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ This unit implements support information structures for Netware modules
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ ****************************************************************************
+}
+{ This unit implements support information structures for Netware modules. }
+unit i_nwm;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ systems;
+
+ const
+ system_i386_netware_info : tsysteminfo =
+ (
+ system : system_i386_netware;
+ name : 'Netware for i386(clib)';
+ shortname : 'Netware';
+ flags : [tf_smartlink_library,tf_smartlink_sections,tf_dwarf_only_local_labels];
+ cpu : cpu_i386;
+ unit_env : 'NETWAREUNITS';
+ extradefines : 'NETWARE_CLIB';
+ exeext : '.nlm';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.nlm';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : '';
+ sharedClibext : '.nlm';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : '';
+ importlibprefix : 'libimp';
+ importlibext : '.a';
+ Cprefix : '';
+ newline : #13#10;
+ dirsep : '/';
+ assem : as_i386_nlmcoff; // as_i386_elf32;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_none;
+ dbg : dbg_stabs;
+ script : script_unix;
+ endian : endian_little;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 4;
+ varalignmin : 0;
+ varalignmax : 4;
+ localalignmin : 4;
+ localalignmax : 4;
+ recordalignmin : 0;
+ recordalignmax : 4;
+ maxCrecordalign : 4
+ );
+ first_parm_offset : 8;
+ stacksize : 16384;
+ abi : abi_default
+ );
+
+ implementation
+
+initialization
+{$ifdef CPU86}
+ {$ifdef netware}
+ set_source_info(system_i386_netware_info);
+ {$endif netware}
+{$endif CPU86}
+end.
diff --git a/closures/compiler/systems/i_os2.pas b/closures/compiler/systems/i_os2.pas
new file mode 100644
index 0000000000..83a0a1445a
--- /dev/null
+++ b/closures/compiler/systems/i_os2.pas
@@ -0,0 +1,118 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ This unit implements support information structures for OS/2
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ ****************************************************************************
+}
+{ This unit implements support information structures for OS/2. }
+unit i_os2;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ systems;
+
+ const
+ res_wrc_os2_info : tresinfo =
+ (
+ id : res_watcom_wrc_os2;
+ resbin : '';
+ rescmd : '';
+ rcbin : 'wrc';
+ rccmd : '-r -zm -q -bt=os2 -fo=$RES $RC';
+ resourcefileclass : nil;
+ resflags : [res_single_file];
+ );
+
+ system_i386_os2_info : tsysteminfo =
+ (
+ system : system_i386_OS2;
+ name : 'OS/2';
+ shortname : 'OS2';
+ flags : [tf_need_export,tf_files_case_aware,tf_use_8_3];
+ cpu : cpu_i386;
+ unit_env : 'OS2UNITS';
+ extradefines : '';
+ exeext : '.exe';
+ defext : '.def';
+ scriptext : '.cmd';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.dll';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : '';
+ sharedClibext : '.dll';
+ staticClibext : '.a';
+ staticClibprefix : '';
+ sharedClibprefix : '';
+ importlibprefix : '';
+ importlibext : '.a';
+ Cprefix : '_';
+ newline : #13#10;
+ dirsep : '\';
+ assem : as_i386_as_aout;
+ assemextern : as_i386_as_aout;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_watcom_wrc_os2;
+ dbg : dbg_stabs;
+ script : script_dos;
+ endian : endian_little;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 4;
+ varalignmin : 0;
+ varalignmax : 4;
+ localalignmin : 0;
+ localalignmax : 4;
+ recordalignmin : 0;
+ recordalignmax : 2;
+ maxCrecordalign : 4
+ );
+ first_parm_offset : 8;
+ stacksize : 256*1024;
+ abi : abi_default;
+ );
+
+
+ implementation
+
+initialization
+{$ifdef CPU86}
+ {$ifdef os2}
+ {$IFNDEF EMX}
+ set_source_info(system_i386_os2_info);
+ {$ENDIF EMX}
+ {$IFDEF VER1_0}
+ set_source_info(system_i386_os2_info);
+ {$ENDIF VER1_0}
+ {$endif os2}
+{$endif CPU86}
+end.
diff --git a/closures/compiler/systems/i_palmos.pas b/closures/compiler/systems/i_palmos.pas
new file mode 100644
index 0000000000..fd819e2fb6
--- /dev/null
+++ b/closures/compiler/systems/i_palmos.pas
@@ -0,0 +1,189 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ This unit implements support information structures for PalmOS
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ ****************************************************************************
+}
+{ This unit implements support information structures for PalmOS. }
+unit i_palmos;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ systems;
+
+ const
+ system_m68k_palmos_info : tsysteminfo =
+ (
+ system : system_m68k_PalmOS;
+ name : 'PalmOS';
+ shortname : 'PalmOS';
+ flags : [tf_code_small,tf_static_reg_based,tf_smartlink_sections];
+ cpu : cpu_m68k;
+ unit_env : 'PALMUNITS';
+ extradefines : '';
+ exeext : '';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.so';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : 'lib';
+ sharedClibext : '.so';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : 'lib';
+ importlibprefix : 'libimp';
+ importlibext : '.a';
+ Cprefix : '_';
+ newline : #10;
+ dirsep : '/';
+ assem : as_gas;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_none;
+ dbg : dbg_stabs;
+ script : script_unix;
+ endian : endian_big;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 4;
+ varalignmin : 0;
+ varalignmax : 4;
+ localalignmin : 0;
+ localalignmax : 4;
+ recordalignmin : 0;
+ recordalignmax : 2;
+ maxCrecordalign : 4
+ );
+ first_parm_offset : 8;
+ stacksize : 8192;
+ abi : abi_default;
+ );
+
+ res_m68k_palmos_info : tresinfo =
+ (
+ id : res_m68k_palmos;
+ resbin : 'pilrc';
+ rescmd : '-I $INC $RES';
+ rcbin : '';
+ rccmd : '';
+ resourcefileclass : nil;
+ resflags : [];
+ );
+
+ system_arm_palmos_info : tsysteminfo =
+ (
+ system : system_arm_PalmOS;
+ name : 'PalmOS';
+ shortname : 'PalmOS';
+ flags : [tf_code_small,tf_static_reg_based,tf_smartlink_sections,tf_requires_proper_alignment];
+ cpu : cpu_arm;
+ unit_env : 'PALMUNITS';
+ extradefines : '';
+ exeext : '';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.so';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : 'lib';
+ sharedClibext : '.so';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : 'lib';
+ importlibprefix : 'libimp';
+ importlibext : '.a';
+ Cprefix : '_';
+ newline : #10;
+ dirsep : '/';
+ assem : as_gas;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_none;
+ dbg : dbg_stabs;
+ script : script_unix;
+ endian : endian_big;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 4;
+ varalignmin : 0;
+ varalignmax : 4;
+ localalignmin : 0;
+ localalignmax : 4;
+ recordalignmin : 0;
+ recordalignmax : 2;
+ maxCrecordalign : 4
+ );
+ first_parm_offset : 8;
+ stacksize : 8192;
+ abi : abi_default;
+ );
+
+ res_arm_palmos_info : tresinfo =
+ (
+ id : res_m68k_palmos;
+ resbin : 'pilrc';
+ rescmd : '-I $INC $RES';
+ rcbin : '';
+ rccmd : '';
+ resourcefileclass : nil;
+ resflags : [];
+ );
+
+implementation
+
+initialization
+{$ifdef cpu68}
+ {$ifdef palmos}
+ set_source_info(system_m68k_palmos_info);
+ {$endif palmos}
+{$endif cpu68}
+{$ifdef cpuarm}
+ {$ifdef palmos}
+ set_source_info(system_arm_palmos_info);
+ {$endif palmos}
+{$endif cpuarm}
+end.
diff --git a/closures/compiler/systems/i_sunos.pas b/closures/compiler/systems/i_sunos.pas
new file mode 100644
index 0000000000..4e84ee8f79
--- /dev/null
+++ b/closures/compiler/systems/i_sunos.pas
@@ -0,0 +1,245 @@
+{
+ Copyright (c) 1998-2008 by Peter Vreman
+
+ This unit implements support information structures for solaris
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ ****************************************************************************
+}
+{ This unit implements support information structures for solaris. }
+unit i_sunos;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ systems;
+
+ const
+ system_i386_solaris_info : tsysteminfo =
+ (
+ system : system_i386_solaris;
+ name : 'Solaris for i386';
+ shortname : 'solaris';
+ flags : [tf_under_development,tf_needs_symbol_size,
+ tf_files_case_sensitive,tf_requires_proper_alignment,
+ tf_smartlink_library,tf_has_winlike_resources];
+ cpu : cpu_i386;
+ unit_env : 'SOLARISUNITS';
+ extradefines : 'UNIX;LIBC;SUNOS;HASUNIX';
+ exeext : '';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.so';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : 'lib';
+ sharedClibext : '.so';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : 'lib';
+ importlibprefix : 'libimp';
+ importlibext : '.a';
+ Cprefix : '';
+ newline : #10;
+ dirsep : '/';
+ assem : as_i386_elf32;
+ assemextern : as_ggas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_gar;
+ res : res_elf;
+ dbg : dbg_stabs;
+ script : script_unix;
+ endian : endian_little;
+ alignment :
+ (
+ procalign : 16;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 8;
+ varalignmin : 0;
+ varalignmax : 16;
+ localalignmin : 4;
+ localalignmax : 8;
+ recordalignmin : 0;
+ recordalignmax : 16;
+ maxCrecordalign : 4
+ );
+ first_parm_offset : 8;
+ stacksize : 262144;
+ abi : abi_default;
+ );
+
+
+ system_x86_64_solaris_info : tsysteminfo =
+ (
+ system : system_x86_64_solaris;
+ name : 'Solaris for x86-64';
+ shortname : 'solaris';
+ flags : [tf_needs_symbol_size,tf_needs_symbol_type,
+ tf_under_development,
+ tf_files_case_sensitive,
+ tf_requires_proper_alignment,tf_smartlink_library,tf_library_needs_pic,
+ tf_has_winlike_resources];
+ cpu : cpu_x86_64;
+ unit_env : 'SOLARISUNITS';
+ extradefines : 'UNIX;LIBC;SUNOS;HASUNIX';
+ exeext : '';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.so';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : 'lib';
+ sharedClibext : '.so';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : 'lib';
+ importlibprefix : 'libimp';
+ importlibext : '.a';
+ Cprefix : '';
+ newline : #10;
+ dirsep : '/';
+ assem : as_ggas{as_x86_64_elf64};
+ assemextern : as_ggas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_elf;
+ dbg : dbg_dwarf2;
+ script : script_unix;
+ endian : endian_little;
+ alignment :
+ (
+ procalign : 8;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 8;
+ varalignmin : 0;
+ varalignmax : 16;
+ localalignmin : 4;
+ localalignmax : 16;
+ recordalignmin : 0;
+ recordalignmax : 16;
+ maxCrecordalign : 16
+ );
+ first_parm_offset : 16;
+ stacksize : 8*1024*1024;
+ abi : abi_default
+ );
+
+
+ system_sparc_solaris_info : tsysteminfo =
+ (
+ system : system_sparc_solaris;
+ name : 'Solaris for SPARC';
+ shortname : 'solaris';
+ flags : [tf_needs_symbol_size,tf_under_development,
+ tf_files_case_sensitive,
+ tf_requires_proper_alignment,tf_smartlink_library,
+ tf_has_winlike_resources];
+ cpu : cpu_SPARC;
+ unit_env : 'SOLARISUNITS';
+ extradefines : 'UNIX;LIBC;SUNOS;HASUNIX';
+ exeext : '';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.so';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : 'lib';
+ sharedClibext : '.so';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : 'lib';
+ importlibprefix : 'libimp';
+ importlibext : '.a';
+ Cprefix : '';
+ newline : #10;
+ dirsep : '/';
+ assem : as_ggas;
+ assemextern : as_ggas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_gar;
+ res : res_elf;
+ dbg : dbg_stabs;
+ script : script_unix;
+ endian : endian_big;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 4;
+ constalignmax : 8;
+ varalignmin : 4;
+ varalignmax : 8;
+ localalignmin : 4;
+ localalignmax : 8;
+ recordalignmin : 0;
+ recordalignmax : 8;
+ maxCrecordalign : 8
+ );
+ first_parm_offset : 92;
+ stacksize : 262144;
+ abi : abi_default;
+ );
+
+ implementation
+
+initialization
+{$ifdef CPU86}
+ {$ifdef solaris}
+ set_source_info(system_i386_solaris_info);
+ {$endif solaris}
+{$endif CPU86}
+{$ifdef CPUX86_64}
+ {$ifdef solaris}
+ set_source_info(system_x86_64_solaris_info);
+ {$endif solaris}
+{$endif CPUX86_64}
+{$ifdef CPUSparc}
+ {$ifdef solaris}
+ set_source_info(system_sparc_solaris_info);
+ {$endif solaris}
+{$endif CPUSparc}
+
+end.
diff --git a/closures/compiler/systems/i_symbian.pas b/closures/compiler/systems/i_symbian.pas
new file mode 100644
index 0000000000..f2cf1bf585
--- /dev/null
+++ b/closures/compiler/systems/i_symbian.pas
@@ -0,0 +1,174 @@
+{
+ This file is part of the Free Pascal run time library.
+ Copyright (c) 2007 by contributors of the Free Pascal Compiler
+
+ This unit implements support information structures for symbian os
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ ****************************************************************************
+}
+{ This unit implements support information structures for win32. }
+unit i_symbian;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ systems;
+
+ const
+ system_i386_symbian_info : tsysteminfo =
+ (
+ system : system_i386_symbian;
+ name : 'Symbian OS for i386';
+ shortname : 'Symbian';
+ flags : [tf_files_case_aware, tf_has_dllscanner,
+ tf_smartlink_library];
+ cpu : cpu_i386;
+ unit_env : 'SYMBIANUNITS';
+ extradefines : 'SYMBIAN';
+ exeext : '.exe';
+ defext : '.def';
+ scriptext : '.bat';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.dll';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : '';
+ sharedClibext : '.dll';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : '';
+ importlibprefix : 'libimp';
+ importlibext : '.a';
+ Cprefix : '_';
+ newline : #13#10;
+ dirsep : '\';
+ assem : as_gas;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_gnu_windres;
+ dbg : dbg_stabs;
+ script : script_dos;
+ endian : endian_little;
+ alignment :
+ (
+ procalign : 16;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 16;
+ varalignmin : 0;
+ varalignmax : 16;
+ localalignmin : 4;
+ localalignmax : 8;
+ recordalignmin : 0;
+ recordalignmax : 4;
+ maxCrecordalign : 16
+ );
+ first_parm_offset : 8;
+ stacksize : 262144;
+ abi : abi_default;
+ );
+
+ system_arm_symbian_info : tsysteminfo =
+ (
+ system : system_arm_symbian;
+ name : 'Symbian OS for ARM';
+ shortname : 'Symbian';
+ flags : [tf_files_case_aware, tf_has_dllscanner,
+ tf_requires_proper_alignment,tf_no_pic_supported];
+ cpu : cpu_arm;
+ unit_env : 'SYMBIANUNITS';
+ extradefines : 'SYMBIAN';
+ exeext : '.exe';
+ defext : '.def';
+ scriptext : '.bat';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.dll';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : '';
+ sharedClibext : '.dll';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : '';
+ importlibprefix : 'libimp';
+ importlibext : '.a';
+ Cprefix : '_';
+ newline : #13#10;
+ dirsep : '\';
+ assem : as_gas;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_none;
+ dbg : dbg_stabs;
+ script : script_dos;
+ endian : endian_little;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 4;
+ varalignmin : 0;
+ varalignmax : 4;
+ localalignmin : 0;
+ localalignmax : 4;
+ recordalignmin : 0;
+ recordalignmax : 4;
+ maxCrecordalign : 4
+ );
+ first_parm_offset : 8;
+ stacksize : 262144;
+ abi : abi_default;
+ );
+
+
+implementation
+
+initialization
+
+{$ifdef CPU86}
+ {$ifdef Symbian}
+ set_source_info(system_i386_symbian_info);
+ {$endif Symbian}
+{$endif CPU86}
+
+{$ifdef CPUARM}
+ {$ifdef Symbian}
+ set_source_info(system_arm_symbian_info);
+ {$endif Symbian}
+{$endif CPUARM}
+
+end.
diff --git a/closures/compiler/systems/i_watcom.pas b/closures/compiler/systems/i_watcom.pas
new file mode 100644
index 0000000000..8ca9087033
--- /dev/null
+++ b/closures/compiler/systems/i_watcom.pas
@@ -0,0 +1,101 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ This unit implements support information structures for Watcom
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ ****************************************************************************
+}
+{ This unit implements support information structures for Watcom. }
+unit i_watcom;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ systems;
+
+ const
+ system_i386_watcom_info : tsysteminfo =
+ (
+ system : system_i386_Watcom;
+ name : 'Watcom compatible DOS extenders';
+ shortname : 'WATCOM';
+ flags : [tf_use_8_3];
+ cpu : cpu_i386;
+ unit_env : 'WATCOMUNITS';
+ extradefines : 'DPMI';
+ exeext : '.exe';
+ defext : '.def';
+ scriptext : '.bat';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.asm';
+ objext : '.obj';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.dll';
+ staticlibext : '.a';
+ staticlibprefix : '';
+ sharedlibprefix : '';
+ sharedClibext : '.dll';
+ staticClibext : '.a';
+ staticClibprefix : '';
+ sharedClibprefix : '';
+ importlibprefix : 'imp';
+ importlibext : '.a';
+ Cprefix : '_';
+ newline : #13#10;
+ dirsep : '\';
+ assem : as_i386_wasm;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_none;
+ dbg : dbg_stabs;
+ script : script_dos;
+ endian : endian_little;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 4;
+ varalignmin : 0;
+ varalignmax : 4;
+ localalignmin : 0;
+ localalignmax : 4;
+ recordalignmin : 0;
+ recordalignmax : 2;
+ maxCrecordalign : 4
+ );
+ first_parm_offset : 8;
+ stacksize : 16384;
+ abi : abi_default;
+ );
+
+ implementation
+
+initialization
+{$ifdef cpu86}
+ {$ifdef watcom}
+ set_source_info(system_i386_watcom_info);
+ {$endif watcom}
+{$endif cpu86}
+end.
diff --git a/closures/compiler/systems/i_wdosx.pas b/closures/compiler/systems/i_wdosx.pas
new file mode 100644
index 0000000000..1ff54bddf0
--- /dev/null
+++ b/closures/compiler/systems/i_wdosx.pas
@@ -0,0 +1,103 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ This unit implements support information structures for win32
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ ****************************************************************************
+}
+{ This unit implements support information structures for wdosx. }
+unit i_wdosx;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ systems;
+
+ const
+ system_i386_wdosx_info : tsysteminfo =
+ (
+ system : system_i386_wdosx;
+ name : 'WDOSX DOS extender';
+ shortname : 'WDOSX';
+ flags : [tf_use_8_3,tf_has_dllscanner];
+ cpu : cpu_i386;
+ unit_env : 'WDOSXUNITS';
+ extradefines : 'MSWINDOWS';
+ exeext : '.exe';
+ defext : '.def';
+ scriptext : '.bat';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.rc';
+ resobjext : '.or';
+ sharedlibext : '.dll';
+ staticlibext : '.a';
+ staticlibprefix : '';
+ sharedlibprefix : '';
+ sharedClibext : '.dll';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : '';
+ importlibprefix : 'libimp';
+ importlibext : '.a';
+ Cprefix : '_';
+ newline : #13#10;
+ dirsep : '\';
+ assem : as_i386_pecoffwdosx;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_gnu_windres;
+ dbg : dbg_stabs;
+ script : script_dos;
+ endian : endian_little;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 4;
+ varalignmin : 0;
+ varalignmax : 4;
+ localalignmin : 0;
+ localalignmax : 4;
+ recordalignmin : 0;
+ recordalignmax : 2;
+ maxCrecordalign : 16
+ );
+ first_parm_offset : 8;
+ stacksize : 32*1024*1024;
+ abi : abi_default;
+ );
+
+ implementation
+
+initialization
+{$ifdef CPU86}
+ {$ifdef WIN32}
+ {$ifdef WDOSX}
+ set_source_info(system_i386_wdosx_info);
+ {$endif WDOSX}
+ {$endif WIN32}
+{$endif CPU86}
+end.
diff --git a/closures/compiler/systems/i_wii.pas b/closures/compiler/systems/i_wii.pas
new file mode 100644
index 0000000000..c9c7a8c1cd
--- /dev/null
+++ b/closures/compiler/systems/i_wii.pas
@@ -0,0 +1,101 @@
+{
+ Copyright (c) 2011 by Francesco Lombardi
+
+ This unit implements support information structures for Wii
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ ****************************************************************************
+}
+{ This unit implements support information structures for the Nintendo Wii. }
+unit i_wii;
+
+ interface
+
+ uses
+ systems;
+
+ const
+ system_powerpc_wii_info : tsysteminfo =
+ (
+ system : system_powerpc_wii;
+ name : 'Wii';
+ shortname : 'Wii';
+ flags : [tf_under_development,tf_needs_symbol_size,tf_files_case_aware,
+ tf_use_function_relative_addresses,tf_needs_symbol_type,
+ tf_smartlink_library];
+ cpu : cpu_powerpc;
+ unit_env : '';
+ extradefines : '';
+ exeext : '.dol';
+ defext : '.def';
+ scriptext : '.sh';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.so';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : 'lib';
+ sharedClibext : '.so';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : 'lib';
+ importlibprefix : 'libimp';
+ importlibext : '.a';
+ Cprefix : '';
+ newline : #10;
+ dirsep : '/';
+ assem : as_gas;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_none;
+ dbg : dbg_stabs;
+ script : script_unix;
+ endian : endian_big;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 4;
+ varalignmin : 0;
+ varalignmax : 4;
+ localalignmin : 4;
+ localalignmax : 4;
+ recordalignmin : 0;
+ recordalignmax : 4;
+ maxCrecordalign : 8
+ );
+ first_parm_offset : 8;
+ stacksize : 131072; // 128 kb
+ abi : abi_powerpc_sysv;
+ );
+
+ implementation
+
+initialization
+{$ifdef CPUPOWERPC}
+ {$ifdef WII}
+ set_source_info(system_powerpc_wii_info);
+ {$endif WII}
+{$endif CPUPOWERPC}
+end.
diff --git a/closures/compiler/systems/i_win.pas b/closures/compiler/systems/i_win.pas
new file mode 100644
index 0000000000..8fc96d2bc8
--- /dev/null
+++ b/closures/compiler/systems/i_win.pas
@@ -0,0 +1,320 @@
+{
+ Copyright (c) 1998-2008 by Peter Vreman
+
+ This unit implements support information structures for win32
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ ****************************************************************************
+}
+{ This unit implements support information structures for win32. }
+unit i_win;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ systems;
+
+ const
+ system_i386_win32_info : tsysteminfo =
+ (
+ system : system_i386_WIN32;
+ name : 'Win32 for i386';
+ shortname : 'Win32';
+ flags : [tf_files_case_aware,tf_has_dllscanner,tf_smartlink_library
+ ,tf_smartlink_sections{,tf_section_threadvars}{,tf_needs_dwarf_cfi},
+ tf_winlikewidestring,tf_no_pic_supported,
+ tf_no_generic_stackcheck,tf_has_winlike_resources,
+ tf_dwarf_only_local_labels,
+ tf_safecall_exceptions,tf_no_backquote_support];
+ cpu : cpu_i386;
+ unit_env : 'WIN32UNITS';
+ extradefines : 'MSWINDOWS;WINDOWS';
+ exeext : '.exe';
+ defext : '.def';
+ scriptext : '.bat';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.dll';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : '';
+ sharedClibext : '.dll';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : '';
+ importlibprefix : 'libimp';
+ importlibext : '.a';
+ Cprefix : '_';
+ newline : #13#10;
+ dirsep : '\';
+ assem : as_i386_pecoff;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_gnu_windres;
+ dbg : dbg_stabs;
+ script : script_dos;
+ endian : endian_little;
+ alignment :
+ (
+ procalign : 16;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 16;
+ varalignmin : 0;
+ varalignmax : 16;
+ localalignmin : 4;
+ localalignmax : 8;
+ recordalignmin : 0;
+ recordalignmax : 4;
+ maxCrecordalign : 16
+ );
+ first_parm_offset : 8;
+ stacksize : 16*1024*1024;
+ abi : abi_default;
+ );
+
+ system_x64_win64_info : tsysteminfo =
+ (
+ system : system_x86_64_win64;
+ name : 'Win64 for x64';
+ shortname : 'Win64';
+ flags : [tf_files_case_aware,tf_has_dllscanner,
+ tf_smartlink_sections,tf_smartlink_library,
+ tf_winlikewidestring,tf_no_pic_supported,
+ tf_dwarf_only_local_labels,
+ tf_no_generic_stackcheck,tf_has_winlike_resources,
+ tf_safecall_exceptions,tf_no_backquote_support];
+ cpu : cpu_x86_64;
+ unit_env : 'WIN64UNITS';
+ extradefines : 'MSWINDOWS;WINDOWS';
+ exeext : '.exe';
+ defext : '.def';
+ scriptext : '.bat';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.obj';
+ sharedlibext : '.dll';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : '';
+ sharedClibext : '.dll';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : '';
+ importlibprefix : 'libimp';
+ importlibext : '.a';
+ Cprefix : '';
+ newline : #13#10;
+ dirsep : '\';
+ assem : as_x86_64_pecoff;
+ assemextern : as_x86_64_masm;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar;
+ res : res_win64_gorc;
+ dbg : dbg_stabs;
+ script : script_dos;
+ endian : endian_little;
+ alignment :
+ (
+ procalign : 16;
+ loopalign : 8;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 16;
+ varalignmin : 0;
+ varalignmax : 16;
+ localalignmin : 8;
+ localalignmax : 16;
+ recordalignmin : 0;
+ recordalignmax : 8;
+ maxCrecordalign : 16
+ );
+ first_parm_offset : 16;
+ stacksize : 16*1024*1024;
+ abi : abi_default;
+ );
+
+ system_arm_wince_info : tsysteminfo =
+ (
+ system : system_arm_wince;
+ name : 'WinCE for ARM';
+ shortname : 'WinCE';
+ flags : [tf_files_case_aware{,tf_winlikewidestring},
+ tf_smartlink_sections,tf_requires_proper_alignment,tf_no_pic_supported,
+ tf_has_winlike_resources,
+ tf_safecall_exceptions,tf_no_backquote_support];
+ cpu : cpu_arm;
+ unit_env : '';
+ extradefines : 'UNDER_CE;WINDOWS;UNICODE';
+ exeext : '.exe';
+ defext : '.def';
+ scriptext : '.bat';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.dll';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : '';
+ sharedClibext : '.dll';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : '';
+ importlibprefix : 'libimp';
+ importlibext : '.a';
+ Cprefix : '';
+ newline : #13#10;
+ dirsep : '\';
+ assem : as_gas;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar_scripted;
+ res : res_gnu_windres;
+ dbg : dbg_stabs;
+ script : script_dos;
+ endian : endian_little;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 4;
+ varalignmin : 0;
+ varalignmax : 4;
+ localalignmin : 0;
+ localalignmax : 4;
+ recordalignmin : 0;
+ recordalignmax : 4;
+ maxCrecordalign : 4
+ );
+ first_parm_offset : 8;
+ stacksize : 262144;
+ abi : abi_default;
+ );
+
+ system_i386_wince_info : tsysteminfo =
+ (
+ system : system_i386_wince;
+ name : 'WinCE for i386';
+ shortname : 'WinCE';
+ flags : [tf_files_case_aware
+ {,tf_winlikewidestring},tf_smartlink_sections,tf_no_pic_supported,
+ tf_has_winlike_resources,
+ tf_safecall_exceptions,tf_no_backquote_support];
+ cpu : cpu_i386;
+ unit_env : '';
+ extradefines : 'UNDER_CE;WINDOWS;UNICODE';
+ exeext : '.exe';
+ defext : '.def';
+ scriptext : '.bat';
+ smartext : '.sl';
+ unitext : '.ppu';
+ unitlibext : '.ppl';
+ asmext : '.s';
+ objext : '.o';
+ resext : '.res';
+ resobjext : '.or';
+ sharedlibext : '.dll';
+ staticlibext : '.a';
+ staticlibprefix : 'libp';
+ sharedlibprefix : '';
+ sharedClibext : '.dll';
+ staticClibext : '.a';
+ staticClibprefix : 'lib';
+ sharedClibprefix : '';
+ importlibprefix : 'libimp';
+ importlibext : '.a';
+ Cprefix : '_';
+ newline : #13#10;
+ dirsep : '\';
+ assem : as_i386_pecoffwince;
+ assemextern : as_gas;
+ link : nil;
+ linkextern : nil;
+ ar : ar_gnu_ar_scripted;
+ res : res_gnu_windres;
+ dbg : dbg_stabs;
+ script : script_dos;
+ endian : endian_little;
+ alignment :
+ (
+ procalign : 4;
+ loopalign : 4;
+ jumpalign : 0;
+ constalignmin : 0;
+ constalignmax : 4;
+ varalignmin : 0;
+ varalignmax : 4;
+ localalignmin : 4;
+ localalignmax : 4;
+ recordalignmin : 0;
+ recordalignmax : 4;
+ maxCrecordalign : 16
+ );
+ first_parm_offset : 8;
+ stacksize : 262144;
+ abi : abi_default;
+ );
+
+
+ implementation
+
+initialization
+{$ifdef CPU86}
+ {$ifdef WIN32}
+ {$ifndef WDOSX}
+ set_source_info(system_i386_win32_info);
+ {$endif WDOSX}
+ {$endif WIN32}
+ {$ifdef WINCE}
+ set_source_info(system_i386_wince_info);
+ {$endif WINCE}
+{$endif CPU86}
+
+{$ifdef CPUX86_64}
+ {$ifdef WIN64}
+ {$ifndef WDOSX}
+ set_source_info(system_x64_win64_info);
+ {$endif WDOSX}
+ {$endif WIN64}
+{$endif CPUX86_64}
+
+{$ifdef CPUARM}
+ {$ifdef WINCE}
+ set_source_info(system_arm_wince_info);
+ {$endif WINCE}
+{$endif CPUARM}
+end.
diff --git a/closures/compiler/systems/mac_crea.txt b/closures/compiler/systems/mac_crea.txt
new file mode 100644
index 0000000000..5372652cbc
--- /dev/null
+++ b/closures/compiler/systems/mac_crea.txt
@@ -0,0 +1,71 @@
+FrŒn: devprograms@apple.com
+Till: <olle.raab@freepascal.org>
+Datum: mŒndag 10 januari 2005 22.33
+€mne: Re: Creator Registration Request
+
+Please include the line below in follow-up emails for this request.
+
+Follow-up: 6855616
+
+Re: Creator Registration Request
+
+Dear Olle Raab,
+
+Thank you for registering your application creator information. We appreciate your continued product development and support of Apple Computer! The following product information has been registered:
+
+Company: Free Pascal Team
+Contact: Olle Raab
+Address: VikingavŠgen 28 A
+S-224 77 Lund
+Sweden
+
+
+Application: Free Pascal Compiler
+Phone: +46-46-120053
+EMail Address: olle.raab@freepascal.org
+
+Application Signatures:
+FPas (Hex) 46506173
+
+This letter serves as your confirmation. Please keep it on file. Additionally, you should review the information for accuracy. If you locate discrepancies, please contact Developer Support at devprograms@apple.com with your corrections.
+
+Thanks for supporting Apple!
+
+Best regards,
+
+Elisa Molson
+Apple Developer Connection
+-----------------------------------
+Spotlight, 64-bit Support, Dashboard, Automator, and more.
+Start developing today with the powerful new technologies in Mac OS X Tiger.
+
+REQUEST ------------------------------------------------------------------------
+
+WEB CREATOR/FILE TYPE Registration Request
+==========================================
+%UNIQUE REGISTRATION%:
+%NAME%: Olle Raab
+%COMPANY%: Free Pascal Team
+%ADDRESS%: VikingavŠgen 28 A
+S-224 77 Lund
+Sweden
+%TELEPHONE%: +46-46-120053
+%E-MAIL%: olle.raab@freepascal.org
+%PRODUCT NAME%: Free Pascal Compiler
+%DEVICE DRIVER%:
+%SIGNATURE (HEX)%: 46506173
+%END
+
+
+DB REFERENCE -------------------------------------------------------------------
+
+TIME IN: 10-Jan-2005 10:45 PST
+TIME OUT: 10-Jan-2005 13:16 PST
+
+Copyright 2005, Apple Computer, Inc.
+
+SECURITY: NON-DISCLOSURE USE ONLY
+
+
+
+
diff --git a/closures/compiler/systems/t_amiga.pas b/closures/compiler/systems/t_amiga.pas
new file mode 100644
index 0000000000..14eb3cba4e
--- /dev/null
+++ b/closures/compiler/systems/t_amiga.pas
@@ -0,0 +1,273 @@
+{
+ Copyright (c) 2004-2006 by Free Pascal Development Team
+
+ This unit implements support import, export, link routines
+ for the Amiga targets (AmigaOS/m68k, AmigaOS/PPC)
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit t_amiga;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ link;
+
+
+type
+ PLinkerAmiga = ^TLinkerAmiga;
+ TLinkerAmiga = class(texternallinker)
+ private
+ function WriteResponseFile(isdll: boolean): boolean;
+ procedure SetAmiga68kInfo;
+ procedure SetAmigaPPCInfo;
+ function MakeAmiga68kExe: boolean;
+ function MakeAmigaPPCExe: boolean;
+ public
+ constructor Create; override;
+ procedure SetDefaultInfo; override;
+ function MakeExecutable: boolean; override;
+ end;
+
+
+implementation
+
+ uses
+ SysUtils,
+ cutils,cfileutl,cclasses,
+ globtype,globals,systems,verbose,script,fmodule,i_amiga;
+
+
+
+{****************************************************************************
+ TLinkerAmiga
+****************************************************************************}
+
+constructor TLinkerAmiga.Create;
+begin
+ Inherited Create;
+ { allow duplicated libs (PM) }
+ SharedLibFiles.doubles:=true;
+ StaticLibFiles.doubles:=true;
+end;
+
+procedure TLinkerAmiga.SetAmiga68kInfo;
+begin
+ with Info do begin
+ ExeCmd[1]:='m68k-amiga-ld $OPT -d -n -o $EXE $RES';
+ end;
+end;
+
+procedure TLinkerAmiga.SetAmigaPPCInfo;
+begin
+ with Info do begin
+ ExeCmd[1]:='ld $OPT -defsym=__amigaos4__=1 -d -q -n -o $EXE $RES';
+ end;
+end;
+
+procedure TLinkerAmiga.SetDefaultInfo;
+begin
+ case (target_info.system) of
+ system_m68k_amiga: SetAmiga68kInfo;
+ system_powerpc_amiga: SetAmigaPPCInfo;
+ end;
+end;
+
+
+function TLinkerAmiga.WriteResponseFile(isdll: boolean): boolean;
+var
+ linkres : TLinkRes;
+ i : longint;
+ HPath : TCmdStrListItem;
+ s : string;
+ linklibc : boolean;
+begin
+ WriteResponseFile:=False;
+
+ { Open link.res file }
+ LinkRes:=TLinkRes.Create(outputexedir+Info.ResName);
+
+ { Write path to search libraries }
+ HPath:=TCmdStrListItem(current_module.locallibrarysearchpath.First);
+ while assigned(HPath) do
+ begin
+ s:=HPath.Str;
+ if (cs_link_on_target in current_settings.globalswitches) then
+ s:=ScriptFixFileName(s);
+ LinkRes.Add('-L'+s);
+ HPath:=TCmdStrListItem(HPath.Next);
+ end;
+ HPath:=TCmdStrListItem(LibrarySearchPath.First);
+ while assigned(HPath) do
+ begin
+ s:=HPath.Str;
+ if s<>'' then
+ LinkRes.Add('SEARCH_DIR('+Unix2AmigaPath(maybequoted(s))+')');
+ HPath:=TCmdStrListItem(HPath.Next);
+ end;
+
+ LinkRes.Add('INPUT (');
+ { add objectfiles, start with prt0 always }
+ s:=FindObjectFile('prt0','',false);
+ LinkRes.AddFileName(s);
+ while not ObjectFiles.Empty do
+ begin
+ s:=ObjectFiles.GetFirst;
+ if s<>'' then
+ begin
+ LinkRes.AddFileName(Unix2AmigaPath(maybequoted(s)));
+ end;
+ end;
+
+ { Write staticlibraries }
+ if not StaticLibFiles.Empty then
+ begin
+ LinkRes.Add(')');
+ LinkRes.Add('GROUP(');
+ while not StaticLibFiles.Empty do
+ begin
+ S:=StaticLibFiles.GetFirst;
+ LinkRes.AddFileName(Unix2AmigaPath(maybequoted(s)));
+ end;
+ end;
+
+ if (cs_link_on_target in current_settings.globalswitches) then
+ begin
+ LinkRes.Add(')');
+
+ { Write sharedlibraries like -l<lib>, also add the needed dynamic linker
+ here to be sure that it gets linked this is needed for glibc2 systems (PFV) }
+ linklibc:=false;
+ while not SharedLibFiles.Empty do
+ begin
+ S:=SharedLibFiles.GetFirst;
+ if s<>'c' then
+ begin
+ i:=Pos(target_info.sharedlibext,S);
+ if i>0 then
+ Delete(S,i,255);
+ LinkRes.Add('-l'+s);
+ end
+ else
+ begin
+ LinkRes.Add('-l'+s);
+ linklibc:=true;
+ end;
+ end;
+ { be sure that libc&libgcc is the last lib }
+ if linklibc then
+ begin
+ LinkRes.Add('-lc');
+ LinkRes.Add('-lgcc');
+ end;
+ end
+ else
+ begin
+ while not SharedLibFiles.Empty do
+ begin
+ S:=SharedLibFiles.GetFirst;
+ LinkRes.Add('lib'+s+target_info.staticlibext);
+ end;
+ LinkRes.Add(')');
+ end;
+
+{ Write and Close response }
+ linkres.writetodisk;
+ linkres.free;
+
+ WriteResponseFile:=True;
+end;
+
+
+function TLinkerAmiga.MakeAmiga68kExe: boolean;
+var
+ BinStr,
+ CmdStr : TCmdStr;
+ StripStr: string[40];
+begin
+ StripStr:='';
+ if (cs_link_strip in current_settings.globalswitches) then StripStr:='-s';
+
+ { Call linker }
+ SplitBinCmd(Info.ExeCmd[1],BinStr,CmdStr);
+ Replace(cmdstr,'$OPT',Info.ExtraOptions);
+ Replace(cmdstr,'$EXE',Unix2AmigaPath(maybequoted(ScriptFixFileName(current_module.exefilename^))));
+ Replace(cmdstr,'$RES',Unix2AmigaPath(maybequoted(ScriptFixFileName(outputexedir+Info.ResName))));
+ Replace(cmdstr,'$STRIP',StripStr);
+ MakeAmiga68kExe:=DoExec(FindUtil(BinStr),CmdStr,true,false);
+end;
+
+
+function TLinkerAmiga.MakeAmigaPPCExe: boolean;
+var
+ BinStr,
+ CmdStr : TCmdStr;
+ StripStr: string[40];
+begin
+ StripStr:='';
+ if (cs_link_strip in current_settings.globalswitches) then StripStr:='-s';
+
+ { Call linker }
+ SplitBinCmd(Info.ExeCmd[1],BinStr,CmdStr);
+ Replace(cmdstr,'$OPT',Info.ExtraOptions);
+ Replace(cmdstr,'$EXE',Unix2AmigaPath(maybequoted(ScriptFixFileName(current_module.exefilename^))));
+ Replace(cmdstr,'$RES',Unix2AmigaPath(maybequoted(ScriptFixFileName(outputexedir+Info.ResName))));
+ Replace(cmdstr,'$STRIP',StripStr);
+ MakeAmigaPPCExe:=DoExec(FindUtil(BinStr),CmdStr,true,false);
+end;
+
+
+function TLinkerAmiga.MakeExecutable:boolean;
+var
+ success : boolean;
+begin
+ if not(cs_link_nolink in current_settings.globalswitches) then
+ Message1(exec_i_linking,current_module.exefilename^);
+
+ { Write used files and libraries }
+ WriteResponseFile(false);
+
+ case (target_info.system) of
+ system_m68k_amiga: success:=MakeAmiga68kExe;
+ system_powerpc_amiga: success:=MakeAmigaPPCExe;
+ end;
+
+ { Remove ReponseFile }
+ if (success) and not(cs_link_nolink in current_settings.globalswitches) then
+ DeleteFile(outputexedir+Info.ResName);
+
+ MakeExecutable:=success; { otherwise a recursive call to link method }
+end;
+
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+initialization
+{$ifdef m68k}
+{ TODO: No executable creation support for m68k yet!}
+ RegisterExternalLinker(system_m68k_Amiga_info,TLinkerAmiga);
+ RegisterTarget(system_m68k_Amiga_info);
+{$endif m68k}
+{$ifdef powerpc}
+ RegisterExternalLinker(system_powerpc_Amiga_info,TLinkerAmiga);
+ RegisterTarget(system_powerpc_Amiga_info);
+{$endif powerpc}
+end.
diff --git a/closures/compiler/systems/t_atari.pas b/closures/compiler/systems/t_atari.pas
new file mode 100644
index 0000000000..5833ac8129
--- /dev/null
+++ b/closures/compiler/systems/t_atari.pas
@@ -0,0 +1,43 @@
+{
+ Copyright (c) 2001-2002 by Peter Vreman
+
+ This unit implements support import,export,link routines
+ for the (i386) Amiga target
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit t_atari;
+
+{$i fpcdefs.inc}
+
+interface
+
+
+implementation
+
+ uses
+ link,
+ cutils,cclasses,
+ globtype,globals,systems,verbose,script,fmodule,i_atari;
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+initialization
+ RegisterTarget(system_m68k_atari_info);
+end.
diff --git a/closures/compiler/systems/t_beos.pas b/closures/compiler/systems/t_beos.pas
new file mode 100644
index 0000000000..ebcb3e6136
--- /dev/null
+++ b/closures/compiler/systems/t_beos.pas
@@ -0,0 +1,500 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ This unit implements support import,export,link routines
+ for the (i386) BeOS target.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit t_beos;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ symsym,symdef,
+ import,export,link;
+
+ type
+ timportlibbeos=class(timportlib)
+ procedure generatelib;override;
+ end;
+
+ texportlibbeos=class(texportlib)
+ procedure preparelib(const s : string);override;
+ procedure exportprocedure(hp : texported_item);override;
+ procedure exportvar(hp : texported_item);override;
+ procedure generatelib;override;
+ end;
+
+ tlinkerbeos=class(texternallinker)
+ private
+ Function WriteResponseFile(isdll:boolean;makelib:boolean) : Boolean;
+ public
+ constructor Create;override;
+ procedure SetDefaultInfo;override;
+ function MakeExecutable:boolean;override;
+ function MakeSharedLibrary:boolean;override;
+ end;
+
+
+implementation
+
+ uses
+ SysUtils,
+ cutils,cfileutl,cclasses,
+ verbose,systems,globtype,globals,
+ symconst,script,
+ fmodule,aasmbase,aasmtai,aasmdata,aasmcpu,cpubase,i_beos,ogbase;
+
+{*****************************************************************************
+ TIMPORTLIBBEOS
+*****************************************************************************}
+
+ procedure timportlibbeos.generatelib;
+ var
+ i : longint;
+ ImportLibrary : TImportLibrary;
+ begin
+ for i:=0 to current_module.ImportLibraryList.Count-1 do
+ begin
+ ImportLibrary:=TImportLibrary(current_module.ImportLibraryList[i]);
+ current_module.linkothersharedlibs.add(ImportLibrary.Name,link_always);
+ end;
+ end;
+
+
+{*****************************************************************************
+ TEXPORTLIBBEOS
+*****************************************************************************}
+
+procedure texportlibbeos.preparelib(const s:string);
+begin
+end;
+
+
+procedure texportlibbeos.exportprocedure(hp : texported_item);
+var
+ hp2 : texported_item;
+begin
+ { first test the index value }
+ if (hp.options and eo_index)<>0 then
+ begin
+ Message1(parser_e_no_export_with_index_for_target,'beos');
+ exit;
+ end;
+ { now place in correct order }
+ hp2:=texported_item(current_module._exports.first);
+ while assigned(hp2) and
+ (hp.name^>hp2.name^) do
+ hp2:=texported_item(hp2.next);
+ { insert hp there !! }
+ if assigned(hp2) and (hp2.name^=hp.name^) then
+ begin
+ { this is not allowed !! }
+ Message1(parser_e_export_name_double,hp.name^);
+ exit;
+ end;
+ if hp2=texported_item(current_module._exports.first) then
+ current_module._exports.concat(hp)
+ else if assigned(hp2) then
+ begin
+ hp.next:=hp2;
+ hp.previous:=hp2.previous;
+ if assigned(hp2.previous) then
+ hp2.previous.next:=hp;
+ hp2.previous:=hp;
+ end
+ else
+ current_module._exports.concat(hp);
+end;
+
+
+procedure texportlibbeos.exportvar(hp : texported_item);
+begin
+ hp.is_var:=true;
+ exportprocedure(hp);
+end;
+
+
+procedure texportlibbeos.generatelib;
+var
+ hp2 : texported_item;
+ pd : tprocdef;
+begin
+ hp2:=texported_item(current_module._exports.first);
+ while assigned(hp2) do
+ begin
+ if (not hp2.is_var) and
+ (hp2.sym.typ=procsym) then
+ begin
+ { the manglednames can already be the same when the procedure
+ is declared with cdecl }
+ pd:=tprocdef(tprocsym(hp2.sym).ProcdefList[0]);
+ if pd.mangledname<>hp2.name^ then
+ begin
+{$ifdef i386}
+ { place jump in al_procedures }
+ current_asmdata.asmlists[al_procedures].concat(Tai_align.Create_op(4,$90));
+ current_asmdata.asmlists[al_procedures].concat(Tai_symbol.Createname_global(hp2.name^,AT_FUNCTION,0));
+ current_asmdata.asmlists[al_procedures].concat(Taicpu.Op_sym(A_JMP,S_NO,current_asmdata.RefAsmSymbol(pd.mangledname)));
+ current_asmdata.asmlists[al_procedures].concat(Tai_symbol_end.Createname(hp2.name^));
+{$endif i386}
+ end;
+ end
+ else
+ Message1(parser_e_no_export_of_variables_for_target,'beos');
+ hp2:=texported_item(hp2.next);
+ end;
+end;
+
+
+{*****************************************************************************
+ TLINKERBEOS
+*****************************************************************************}
+
+Constructor TLinkerBeos.Create;
+var
+ s : string;
+ i : integer;
+begin
+ Inherited Create;
+ s:=GetEnvironmentVariable('BELIBRARIES');
+ { convert to correct format in case under unix system }
+ for i:=1 to length(s) do
+ if s[i] = ':' then
+ s[i] := ';';
+ { just in case we have a single path : add the ending ; }
+ { since that is what the compiler expects. }
+ if pos(';',s) = 0 then
+ s:=s+';';
+ LibrarySearchPath.AddPath(sysrootpath,s,true); {format:'path1;path2;...'}
+end;
+
+
+procedure TLinkerBeOS.SetDefaultInfo;
+begin
+ with Info do
+ begin
+ ExeCmd[1]:='ld $OPT $DYNLINK $STATIC $STRIP -L. -o $EXE $CATRES';
+ DllCmd[1]:='ld $OPT $INIT $FINI $SONAME -shared -L. -o $EXE $CATRES';
+ DllCmd[2]:='strip --strip-unneeded $EXE';
+(*
+ ExeCmd[1]:='sh $RES $EXE $OPT $STATIC $STRIP -L.';
+{ ExeCmd[1]:='sh $RES $EXE $OPT $DYNLINK $STATIC $STRIP -L.';}
+ DllCmd[1]:='sh $RES $EXE $OPT -L.';
+
+{ DllCmd[1]:='sh $RES $EXE $OPT -L. -g -nostart -soname=$EXE';
+ } DllCmd[2]:='strip --strip-unneeded $EXE';
+{ DynamicLinker:='/lib/ld-beos.so.2';}
+*)
+ end;
+end;
+
+
+function TLinkerBeOS.WriteResponseFile(isdll:boolean;makelib:boolean) : Boolean;
+Var
+ linkres : TLinkRes;
+ i : integer;
+ cprtobj,
+ prtobj : string[80];
+ HPath : TCmdStrListItem;
+ s : TCmdStr;
+ linklibc : boolean;
+begin
+ WriteResponseFile:=False;
+{ set special options for some targets }
+ linklibc:=(SharedLibFiles.Find('root')<>nil);
+
+ prtobj:='prt0';
+ cprtobj:='cprt0';
+ if (cs_profile in current_settings.moduleswitches) or
+ (not SharedLibFiles.Empty) then
+ begin
+ AddSharedLibrary('root');
+ linklibc:=true;
+ end;
+
+ if (not linklibc) and makelib then
+ begin
+ linklibc:=true;
+ cprtobj:='dllprt.o';
+ end;
+
+ if linklibc then
+ prtobj:=cprtobj;
+
+ { Open link.res file }
+ LinkRes:=TLinkRes.Create(outputexedir+Info.ResName);
+ {
+ if not isdll then
+ LinkRes.Add('ld -o $1 $2 $3 $4 $5 $6 $7 $8 $9 \')
+ else
+ LinkRes.Add('ld -o $1 -e 0 $2 $3 $4 $5 $6 $7 $8 $9\');
+ }
+ LinkRes.Add('-m');
+// LinkRes.Add('elf_i386_be');
+ LinkRes.Add('elf_i386_haiku');
+ LinkRes.Add('-shared');
+ LinkRes.Add('-Bsymbolic');
+
+ { Write path to search libraries }
+ HPath:=TCmdStrListItem(current_module.locallibrarysearchpath.First);
+ while assigned(HPath) do
+ begin
+ LinkRes.Add('-L'+HPath.Str);
+ HPath:=TCmdStrListItem(HPath.Next);
+ end;
+ HPath:=TCmdStrListItem(LibrarySearchPath.First);
+ while assigned(HPath) do
+ begin
+ LinkRes.Add('-L'+HPath.Str);
+ HPath:=TCmdStrListItem(HPath.Next);
+ end;
+
+ { try to add crti and crtbegin if linking to C }
+ if linklibc then
+ begin
+ if librarysearchpath.FindFile('crti.o',false,s) then
+ LinkRes.AddFileName(s);
+ if librarysearchpath.FindFile('crtbegin.o',false,s) then
+ LinkRes.AddFileName(s);
+{ s:=librarysearchpath.FindFile('start_dyn.o',found)+'start_dyn.o';
+ if found then LinkRes.AddFileName(s+' \');}
+
+ if prtobj<>'' then
+ LinkRes.AddFileName(FindObjectFile(prtobj,'',false));
+
+// if isdll then
+// LinkRes.AddFileName(FindObjectFile('func.o','',false));
+
+ if librarysearchpath.FindFile('init_term_dyn.o',false,s) then
+ LinkRes.AddFileName(s);
+ end
+ else
+ begin
+ if prtobj<>'' then
+ LinkRes.AddFileName(FindObjectFile(prtobj,'',false));
+ end;
+
+ { main objectfiles }
+ while not ObjectFiles.Empty do
+ begin
+ s:=ObjectFiles.GetFirst;
+ if s<>'' then
+ LinkRes.AddFileName(s);
+ end;
+
+{ LinkRes.Add('-lroot \');
+ LinkRes.Add('/boot/develop/tools/gnupro/lib/gcc-lib/i586-beos/2.9-beos-991026/crtend.o \');
+ LinkRes.Add('/boot/develop/lib/x86/crtn.o \');}
+
+ { Write staticlibraries }
+ if not StaticLibFiles.Empty then
+ begin
+ While not StaticLibFiles.Empty do
+ begin
+ S:=StaticLibFiles.GetFirst;
+ LinkRes.AddFileName(s)
+ end;
+ end;
+
+ { Write sharedlibraries like -l<lib> }
+ if not SharedLibFiles.Empty then
+ begin
+ While not SharedLibFiles.Empty do
+ begin
+ S:=SharedLibFiles.GetFirst;
+ if s<>'c' then
+ begin
+ i:=Pos(target_info.sharedlibext,S);
+ if i>0 then
+ Delete(S,i,255);
+ LinkRes.Add('-l'+s);
+ end
+ else
+ begin
+ linklibc:=true;
+ end;
+ end;
+ { be sure that libc is the last lib }
+{ if linklibc then
+ LinkRes.Add('-lroot');}
+{ if linkdynamic and (Info.DynamicLinker<>'') then
+ LinkRes.AddFileName(Info.DynamicLinker);}
+ end;
+ if isdll then
+ LinkRes.Add('-lroot');
+
+ { objects which must be at the end }
+ if linklibc then
+ begin
+ if librarysearchpath.FindFile('crtend.o',false,s) then
+ LinkRes.AddFileName(s);
+ if librarysearchpath.FindFile('crtn.o',false,s) then
+ LinkRes.AddFileName(s);
+ end;
+
+{ Write and Close response }
+ linkres.writetodisk;
+ linkres.free;
+
+ WriteResponseFile:=True;
+end;
+
+
+function TLinkerBeOS.MakeExecutable:boolean;
+var
+ binstr,
+ cmdstr : TCmdStr;
+ success,
+ useshell : boolean;
+ DynLinkStr : string[60];
+ GCSectionsStr,
+ StaticStr,
+ StripStr : string[40];
+begin
+ if not(cs_link_nolink in current_settings.globalswitches) then
+ Message1(exec_i_linking,current_module.exefilename^);
+
+{ Create some replacements }
+ StaticStr:='';
+ StripStr:='';
+ DynLinkStr:='';
+ GCSectionsStr:='';
+ if (cs_link_staticflag in current_settings.globalswitches) then
+ StaticStr:='-static';
+ if (cs_link_strip in current_settings.globalswitches) then
+ StripStr:='-s';
+
+ if (cs_link_smart in current_settings.globalswitches) and
+ (tf_smartlink_sections in target_info.flags) then
+ GCSectionsStr:='--gc-sections';
+
+ If (cs_profile in current_settings.moduleswitches) or
+ ((Info.DynamicLinker<>'') and (not SharedLibFiles.Empty)) then
+ begin
+ DynLinkStr:='-dynamic-linker='+Info.DynamicLinker;
+ if cshared Then
+ DynLinkStr:='--shared ' + DynLinkStr;
+ if rlinkpath<>'' Then
+ DynLinkStr:='--rpath-link '+rlinkpath + ' '+ DynLinkStr;
+ End;
+
+{ Write used files and libraries }
+ WriteResponseFile(false,false);
+
+{ Call linker }
+ SplitBinCmd(Info.ExeCmd[1],binstr,cmdstr);
+ Replace(cmdstr,'$EXE',maybequoted(current_module.exefilename^));
+ Replace(cmdstr,'$OPT',Info.ExtraOptions);
+ Replace(cmdstr,'$CATRES',CatFileContent(outputexedir+Info.ResName));
+ Replace(cmdstr,'$RES',maybequoted(outputexedir+Info.ResName));
+ Replace(cmdstr,'$STATIC',StaticStr);
+ Replace(cmdstr,'$STRIP',StripStr);
+ Replace(cmdstr,'$GCSECTIONS',GCSectionsStr);
+ Replace(cmdstr,'$DYNLINK',DynLinkStr);
+ useshell:=not (tf_no_backquote_support in source_info.flags);
+ success:=DoExec(FindUtil(utilsprefix+BinStr),CmdStr,true,useshell);
+
+{ Remove ReponseFile }
+ if (success) and not(cs_link_nolink in current_settings.globalswitches) then
+ DeleteFile(outputexedir+Info.ResName);
+
+ MakeExecutable:=success; { otherwise a recursive call to link method }
+end;
+
+
+Function TLinkerBeOS.MakeSharedLibrary:boolean;
+var
+ binstr,
+ cmdstr,
+ SoNameStr : TCmdStr;
+ success : boolean;
+ DynLinkStr : string[60];
+ StaticStr,
+ StripStr : string[40];
+
+ begin
+ MakeSharedLibrary:=false;
+ if not(cs_link_nolink in current_settings.globalswitches) then
+ Message1(exec_i_linking,current_module.sharedlibfilename^);
+
+{ Create some replacements }
+ StaticStr:='';
+ StripStr:='';
+ DynLinkStr:='';
+ if (cs_link_staticflag in current_settings.globalswitches) then
+ StaticStr:='-static';
+ if (cs_link_strip in current_settings.globalswitches) then
+ StripStr:='-s';
+ If (cs_profile in current_settings.moduleswitches) or
+ ((Info.DynamicLinker<>'') and (not SharedLibFiles.Empty)) then
+ begin
+ DynLinkStr:='-dynamic-linker='+Info.DynamicLinker;
+ if cshared Then
+ DynLinkStr:='--shared ' + DynLinkStr;
+ if rlinkpath<>'' Then
+ DynLinkStr:='--rpath-link '+rlinkpath + ' '+ DynLinkStr;
+ End;
+{ Write used files and libraries }
+ WriteResponseFile(true,true);
+
+ SoNameStr:='-soname '+ExtractFileName(current_module.sharedlibfilename^);
+
+{ Call linker }
+ SplitBinCmd(Info.DllCmd[1],binstr,cmdstr);
+ Replace(cmdstr,'$EXE',maybequoted(current_module.sharedlibfilename^));
+ Replace(cmdstr,'$OPT',Info.ExtraOptions);
+ Replace(cmdstr,'$CATRES',CatFileContent(outputexedir+Info.ResName));
+ Replace(cmdstr,'$RES',maybequoted(outputexedir+Info.ResName));
+ Replace(cmdstr,'$STATIC',StaticStr);
+ Replace(cmdstr,'$STRIP',StripStr);
+ Replace(cmdstr,'$DYNLINK',DynLinkStr);
+ Replace(cmdstr,'$SONAME',SoNameStr);
+
+ success:=DoExec(FindUtil(utilsprefix+binstr),cmdstr,true,true);
+
+{ Strip the library ? }
+ if success and (cs_link_strip in current_settings.globalswitches) then
+ begin
+ SplitBinCmd(Info.DllCmd[2],binstr,cmdstr);
+ Replace(cmdstr,'$EXE',maybequoted(current_module.sharedlibfilename^));
+ success:=DoExec(FindUtil(utilsprefix+binstr),cmdstr,true,false);
+ end;
+
+{ Remove ReponseFile }
+ if (success) and not(cs_link_nolink in current_settings.globalswitches) then
+ DeleteFile(outputexedir+Info.ResName);
+
+ MakeSharedLibrary:=success; { otherwise a recursive call to link method }
+end;
+
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+initialization
+{$ifdef i386}
+ RegisterExternalLinker(system_i386_beos_info,TLinkerbeos);
+ RegisterImport(system_i386_beos,timportlibbeos);
+ RegisterExport(system_i386_beos,texportlibbeos);
+ RegisterTarget(system_i386_beos_info);
+{$endif i386}
+end.
diff --git a/closures/compiler/systems/t_bsd.pas b/closures/compiler/systems/t_bsd.pas
new file mode 100644
index 0000000000..8011dadeff
--- /dev/null
+++ b/closures/compiler/systems/t_bsd.pas
@@ -0,0 +1,855 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman (original Linux)
+ (c) 2000 by Marco van de Voort (FreeBSD mods)
+
+ This unit implements support import,export,link routines
+ for the (i386)FreeBSD target
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit t_bsd;
+
+{$i fpcdefs.inc}
+
+interface
+
+
+implementation
+
+ uses
+ sysutils,
+ cutils,cfileutl,cclasses,
+ verbose,systems,globtype,globals,
+ symconst,script,
+ fmodule,aasmbase,aasmtai,aasmdata,aasmcpu,cpubase,symsym,symdef,
+ import,export,link,comprsrc,rescmn,i_bsd,expunix,
+ cgutils,cgbase,cgobj,cpuinfo,ogbase;
+
+ type
+ timportlibdarwin=class(timportlib)
+ procedure generatelib;override;
+ end;
+
+ timportlibbsd=class(timportlib)
+ procedure generatelib;override;
+ end;
+
+ texportlibbsd=class(texportlibunix)
+ end;
+
+ texportlibdarwin=class(texportlibbsd)
+ procedure setinitname(list: TAsmList; const s: string); override;
+ procedure setfininame(list: TAsmList; const s: string); override;
+ end;
+
+ tlinkerbsd=class(texternallinker)
+ private
+ LdSupportsNoResponseFile : boolean;
+ LibrarySuffix : Char;
+ Function WriteResponseFile(isdll:boolean) : Boolean;
+ Function GetDarwinPrtobjName(isdll: boolean): TCmdStr;
+ public
+ constructor Create;override;
+ procedure SetDefaultInfo;override;
+ function MakeExecutable:boolean;override;
+ function MakeSharedLibrary:boolean;override;
+ procedure LoadPredefinedLibraryOrder; override;
+ end;
+
+
+
+{*****************************************************************************
+ TIMPORTLIBDARWIN
+*****************************************************************************}
+
+ procedure timportlibdarwin.generatelib;
+ begin
+ end;
+
+
+{*****************************************************************************
+ TEXPORTLIBDARWIN
+*****************************************************************************}
+
+ procedure texportlibdarwin.setinitname(list: TAsmList; const s: string);
+ begin
+ new_section(list,sec_init_func,'',sizeof(pint));
+ list.concat(Tai_const.Createname(s,0));
+ end;
+
+
+ procedure texportlibdarwin.setfininame(list: TAsmList; const s: string);
+ begin
+ new_section(list,sec_term_func,'',sizeof(pint));
+ list.concat(Tai_const.Createname(s,0));
+ end;
+
+
+{*****************************************************************************
+ TIMPORTLIBBSD
+*****************************************************************************}
+
+ procedure timportlibbsd.generatelib;
+ var
+ i : longint;
+ ImportLibrary : TImportLibrary;
+ begin
+ for i:=0 to current_module.ImportLibraryList.Count-1 do
+ begin
+ ImportLibrary:=TImportLibrary(current_module.ImportLibraryList[i]);
+ current_module.linkothersharedlibs.add(ImportLibrary.Name,link_always);
+ end;
+ end;
+
+
+{*****************************************************************************
+ TLINKERBSD
+*****************************************************************************}
+
+Constructor TLinkerBSD.Create;
+begin
+ Inherited Create;
+ if not Dontlinkstdlibpath Then
+ if not(target_info.system in systems_darwin) then
+ LibrarySearchPath.AddPath(sysrootpath,'/lib;/usr/lib;/usr/X11R6/lib',true)
+ else
+ { Mac OS X doesn't have a /lib }
+ LibrarySearchPath.AddPath(sysrootpath,'/usr/lib',true)
+end;
+
+
+procedure TLinkerBSD.SetDefaultInfo;
+{
+ This will also detect which libc version will be used
+}
+begin
+ LibrarySuffix:=' ';
+ LdSupportsNoResponseFile := (target_info.system in ([system_m68k_netbsd]+systems_darwin));
+ with Info do
+ begin
+ if LdSupportsNoResponseFile then
+ begin
+ if not(target_info.system in systems_darwin) then
+ begin
+ ExeCmd[1]:='ld $OPT $DYNLINK $STATIC $GCSECTIONS $STRIP -L. -o $EXE $CATRES';
+ DllCmd[1]:='ld $OPT -shared -L. -o $EXE $CATRES'
+ end
+ else
+ begin
+{$ifndef cpu64bitaddr}
+ { Set the size of the page at address zero to 64kb, so nothing
+ is loaded below that address. This avoids problems with the
+ strange Windows-compatible resource handling that assumes
+ that addresses below 64kb do not exist.
+
+ On 64bit systems, page zero is 4GB by default, so no problems
+ there.
+ }
+ { In case of valgrind, don't do that, because it cannot deal with
+ a custom pagezero size -- in general, this should not cause any
+ problems because the resources are added at the end and most
+ programs with problems that require Valgrind will have more
+ than 60KB of data (first 4KB of address space is always invalid)
+ }
+ ExeCmd[1]:='ld $PRTOBJ $OPT $DYNLINK $STATIC $GCSECTIONS $STRIP -multiply_defined suppress -L. -o $EXE $CATRES';
+ if not(cs_gdb_valgrind in current_settings.globalswitches) then
+ ExeCmd[1]:=ExeCmd[1]+' -pagezero_size 0x10000';
+{$else ndef cpu64bitaddr}
+ ExeCmd[1]:='ld $PRTOBJ $OPT $DYNLINK $STATIC $GCSECTIONS $STRIP -multiply_defined suppress -L. -o $EXE $CATRES';
+{$endif ndef cpu64bitaddr}
+ if (apptype<>app_bundle) then
+ DllCmd[1]:='ld $PRTOBJ $OPT $GCSECTIONS -dynamic -dylib -multiply_defined suppress -L. -o $EXE $CATRES'
+ else
+ DllCmd[1]:='ld $PRTOBJ $OPT $GCSECTIONS -dynamic -bundle -multiply_defined suppress -L. -o $EXE $CATRES'
+ end
+ end
+ else
+ begin
+ ExeCmd[1]:='ld $OPT $DYNLINK $STATIC $GCSECTIONS $STRIP -L. -o $EXE $RES';
+ DllCmd[1]:='ld $OPT $INIT $FINI $SONAME -shared -L. -o $EXE $RES';
+ end;
+ if not(target_info.system in systems_darwin) then
+ DllCmd[2]:='strip --strip-unneeded $EXE'
+ else
+ DllCmd[2]:='strip -x $EXE';
+ { OpenBSD seems to use a wrong dynamic linker by default }
+ if target_info.system = system_i386_openbsd then
+ DynamicLinker:='/usr/libexec/ld.so'
+ else
+ DynamicLinker:='';
+ end;
+end;
+
+procedure TLinkerBSD.LoadPredefinedLibraryOrder;
+// put your linkorder/linkalias overrides here.
+// Note: assumes only called when reordering/aliasing is used.
+Begin
+ if not(target_info.system in systems_darwin) then
+ begin
+ if (target_info.system =system_i386_freebsd) and
+ not (cs_link_no_default_lib_order in current_settings.globalswitches) Then
+ Begin
+ LinkLibraryOrder.add('gcc','',15);
+ LinkLibraryOrder.add('c','',50); // c and c_p mutual. excl?
+ LinkLibraryOrder.add('c_p','',55);
+ LinkLibraryOrder.add('pthread','',75); // pthread and c_r should be mutually exclusive
+ LinkLibraryOrder.add('c_r','',76);
+ LinkLibraryOrder.add('kvm','',80); // must be before ncurses
+ if (cs_link_pthread in current_settings.globalswitches) Then // convert libpthread to libc_r.
+ LinkLibraryAliases.add('pthread','c_r');
+ end;
+ end
+else
+ begin
+ LinkLibraryOrder.add('gcc','',15);
+ LinkLibraryOrder.add('c','',50);
+ end;
+End;
+
+
+Function TLinkerBSD.GetDarwinPrtobjName(isdll: boolean): TCmdStr;
+begin
+ if not(isdll) then
+ if not(cs_profile in current_settings.moduleswitches) then
+ begin
+ if not librarysearchpath.FindFile('crt1.o',false,result) then
+ result:='/usr/lib/crt1.o';
+ end
+ else
+ begin
+ if not librarysearchpath.FindFile('gcrt1.o',false,result) then
+ result:='/usr/lib/gcrt1.o';
+ end
+ else
+ begin
+ if (apptype=app_bundle) then
+ begin
+ if not librarysearchpath.FindFile('bundle1.o',false,result) then
+ result:='/usr/lib/bundle1.o'
+ end
+ else
+ begin
+ if not librarysearchpath.FindFile('dylib1.o',false,result) then
+ result:='/usr/lib/dylib1.o'
+ end;
+ end;
+ result:=maybequoted(result);
+end;
+
+
+Function TLinkerBSD.WriteResponseFile(isdll:boolean) : Boolean;
+Var
+ linkres : TLinkRes;
+ i : longint;
+ cprtobj,
+ gprtobj,
+ prtobj : string[80];
+ HPath : TCmdStrListItem;
+ s,s1,s2 : TCmdStr;
+ linkdynamic,
+ linklibc : boolean;
+ Fl1,Fl2 : Boolean;
+ IsDarwin : Boolean;
+ ReOrder : Boolean;
+
+begin
+ WriteResponseFile:=False;
+ ReOrder:=False;
+ IsDarwin:=target_info.system in systems_darwin;
+{ set special options for some targets }
+ if not IsDarwin Then
+ begin
+ if isdll and (target_info.system in systems_freebsd) then
+ begin
+ prtobj:='dllprt0';
+ cprtobj:='dllprt0';
+ gprtobj:='dllprt0';
+ end
+ else
+ begin
+ prtobj:='prt0';
+ cprtobj:='cprt0';
+ gprtobj:='gprt0';
+ end;
+ linkdynamic:=not(SharedLibFiles.empty);
+ linklibc:=(SharedLibFiles.Find('c')<>nil);
+ // this one is a bit complex.
+ // Only reorder for now if -XL or -XO params are given
+ // or when -Xf.
+ reorder:= linklibc and
+ (
+ ReorderEntries
+ or
+ (cs_link_pthread in current_settings.globalswitches));
+ if cs_profile in current_settings.moduleswitches then
+ begin
+ prtobj:=gprtobj;
+ AddSharedLibrary('c');
+ LibrarySuffix:='p';
+ linklibc:=true;
+ end
+ else
+ begin
+ if linklibc then
+ prtobj:=cprtobj;
+ end;
+ // after this point addition of shared libs not allowed.
+ end
+ else
+ begin
+ { for darwin: always link dynamically against libc }
+ linklibc := true;
+{$ifdef MACOSX104ORHIGHER}
+ { not sure what this is for, but gcc always links against it }
+ if not(cs_profile in current_settings.moduleswitches) then
+ AddSharedLibrary('SystemStubs')
+ else
+ AddSharedLibrary('SystemStubs_profile');
+{$endif MACOSX104ORHIGHER}
+ reorder:=reorderentries;
+ prtobj:='';
+ end;
+
+ if reorder Then
+ ExpandAndApplyOrder(SharedLibFiles);
+
+ { Open link.res file }
+ LinkRes:=TLinkRes.Create(outputexedir+Info.ResName);
+
+ if (target_info.system in systems_darwin) and
+ (sysrootpath<>'') then
+ begin
+ LinkRes.Add('-syslibroot');
+ LinkRes.Add(sysrootpath);
+ end;
+
+ if (not isdll) or
+ (apptype=app_bundle) then
+ begin
+ if (target_info.system in systems_darwin) then
+ begin
+ LinkRes.Add('-arch');
+ case target_info.system of
+ system_powerpc_darwin:
+ LinkRes.Add('ppc');
+ system_i386_darwin,
+ system_i386_iphonesim:
+ LinkRes.Add('i386');
+ system_powerpc64_darwin:
+ LinkRes.Add('ppc64');
+ system_x86_64_darwin:
+ LinkRes.Add('x86_64');
+ system_arm_darwin:
+ { current versions of the linker require the sub-architecture type
+ to be specified }
+ LinkRes.Add(lower(cputypestr[current_settings.cputype]));
+ end;
+ end;
+ end;
+ { Write path to search libraries }
+ HPath:=TCmdStrListItem(current_module.locallibrarysearchpath.First);
+ while assigned(HPath) do
+ begin
+ if LdSupportsNoResponseFile then
+ LinkRes.Add('-L'+HPath.Str)
+ else
+ LinkRes.Add('SEARCH_DIR('+maybequoted(HPath.Str)+')');
+ HPath:=TCmdStrListItem(HPath.Next);
+ end;
+ HPath:=TCmdStrListItem(LibrarySearchPath.First);
+ while assigned(HPath) do
+ begin
+ if LdSupportsNoResponseFile then
+ LinkRes.Add('-L'+HPath.Str)
+ else
+ LinkRes.Add('SEARCH_DIR('+maybequoted(HPath.Str)+')');
+ HPath:=TCmdStrListItem(HPath.Next);
+ end;
+
+ if (target_info.system in systems_darwin) then
+ begin
+ HPath:=TCmdStrListItem(current_module.localframeworksearchpath.First);
+ while assigned(HPath) do
+ begin
+ LinkRes.Add('-F'+HPath.Str);
+ HPath:=TCmdStrListItem(HPath.Next);
+ end;
+ HPath:=TCmdStrListItem(FrameworkSearchPath.First);
+ while assigned(HPath) do
+ begin
+ LinkRes.Add('-F'+HPath.Str);
+ HPath:=TCmdStrListItem(HPath.Next);
+ end;
+ end;
+ { force local symbol resolution (i.e., inside the shared }
+ { library itself) for all non-exorted symbols, otherwise }
+ { several RTL symbols of FPC-compiled shared libraries }
+ { will be bound to those of a single shared library or }
+ { to the main program }
+ if (isdll) and (target_info.system in systems_freebsd) then
+ begin
+ LinkRes.add('VERSION');
+ LinkRes.add('{');
+ LinkRes.add(' {');
+ if not texportlibunix(exportlib).exportedsymnames.empty then
+ begin
+ LinkRes.add(' global:');
+ repeat
+ LinkRes.add(' '+texportlibunix(exportlib).exportedsymnames.getfirst+';');
+ until texportlibunix(exportlib).exportedsymnames.empty;
+ end;
+ LinkRes.add(' local:');
+ LinkRes.add(' *;');
+ LinkRes.add(' };');
+ LinkRes.add('}');
+ end;
+
+ if not LdSupportsNoResponseFile then
+ LinkRes.Add('INPUT(');
+ { add objectfiles, start with prt0 always }
+ if prtobj<>'' then
+ LinkRes.AddFileName(FindObjectFile(prtobj,'',false));
+ { try to add crti and crtbegin if linking to C }
+ if linklibc and
+ not IsDarwin Then
+ begin
+ if librarysearchpath.FindFile('crtbegin.o',false,s) then
+ LinkRes.AddFileName(s);
+ if librarysearchpath.FindFile('crti.o',false,s) then
+ LinkRes.AddFileName(s);
+ end;
+ { main objectfiles }
+ while not ObjectFiles.Empty do
+ begin
+ s:=ObjectFiles.GetFirst;
+ if s<>'' then
+ if LdSupportsNoResponseFile then
+ LinkRes.AddFileName(s)
+ else
+ LinkRes.AddFileName(maybequoted(s));
+ end;
+ if not LdSupportsNoResponseFile then
+ LinkRes.Add(')');
+
+ { Write staticlibraries }
+ if not StaticLibFiles.Empty then
+ begin
+ if not LdSupportsNoResponseFile then
+ LinkRes.Add('GROUP(');
+ While not StaticLibFiles.Empty do
+ begin
+ S:=StaticLibFiles.GetFirst;
+ if LdSupportsNoResponseFile then
+ LinkRes.AddFileName(s)
+ else
+ LinkRes.AddFileName(maybequoted(s))
+ end;
+ if not LdSupportsNoResponseFile then
+ LinkRes.Add(')');
+ end;
+
+ { Write sharedlibraries like -l<lib>, also add the needed dynamic linker
+ here to be sure that it gets linked this is needed for glibc2 systems (PFV) }
+ if not SharedLibFiles.Empty then
+ begin
+ if not LdSupportsNoResponseFile then
+ LinkRes.Add('INPUT(');
+ While not SharedLibFiles.Empty do
+ begin
+ S:=SharedLibFiles.GetFirst;
+ if (s<>'c') or reorder then
+ begin
+ i:=Pos(target_info.sharedlibext,S);
+ if i>0 then
+ Delete(S,i,255);
+ LinkRes.Add('-l'+s);
+ end
+ else
+ begin
+ linklibc:=true;
+ linkdynamic:=false; { libc will include the ld-* for us }
+ end;
+ end;
+ { be sure that libc is the last lib }
+ if linklibc and not reorder then
+ Begin
+ If LibrarySuffix=' ' Then
+ LinkRes.Add('-lc')
+ else
+ LinkRes.Add('-lc_'+LibrarySuffix);
+ If LibrarySuffix='r' Then
+ LinkRes.Add('-lc');
+ end;
+ { when we have -static for the linker the we also need libgcc }
+ if (cs_link_staticflag in current_settings.globalswitches) then
+ LinkRes.Add('-lgcc');
+ if linkdynamic and (Info.DynamicLinker<>'') then
+ LinkRes.AddFileName(Info.DynamicLinker);
+ if not LdSupportsNoResponseFile then
+ LinkRes.Add(')');
+ end;
+
+ { frameworks for Darwin }
+ if IsDarwin then
+ while not FrameworkFiles.empty do
+ begin
+ LinkRes.Add('-framework');
+ LinkRes.Add(FrameworkFiles.GetFirst);
+ end;
+
+ { objects which must be at the end }
+ if linklibc and
+ not IsDarwin Then
+ begin
+ Fl1:=librarysearchpath.FindFile('crtend.o',false,s1);
+ Fl2:=librarysearchpath.FindFile('crtn.o',false,s2);
+ if Fl1 or Fl2 then
+ begin
+ LinkRes.Add('INPUT(');
+ If Fl1 Then
+ LinkRes.AddFileName(s1);
+ If Fl2 Then
+ LinkRes.AddFileName(s2);
+ LinkRes.Add(')');
+ end;
+ end;
+{ Write and Close response }
+ linkres.writetodisk;
+ linkres.Free;
+
+ WriteResponseFile:=True;
+end;
+
+
+function TLinkerBSD.MakeExecutable:boolean;
+var
+ binstr,
+ cmdstr,
+ extdbgbinstr,
+ extdbgcmdstr: TCmdStr;
+ linkscript: TAsmScript;
+ DynLinkStr : string[60];
+ GCSectionsStr,
+ StaticStr,
+ StripStr : string[63];
+ success,
+ useshell : boolean;
+begin
+ if not(cs_link_nolink in current_settings.globalswitches) then
+ Message1(exec_i_linking,current_module.exefilename^);
+
+{ Create some replacements }
+ StaticStr:='';
+ StripStr:='';
+ DynLinkStr:='';
+ GCSectionsStr:='';
+ if (cs_link_staticflag in current_settings.globalswitches) then
+ begin
+ if (target_info.system=system_m68k_netbsd) and
+ ((cs_link_on_target in current_settings.globalswitches) or
+ (target_info.system=source_info.system)) then
+ StaticStr:='-Bstatic'
+ else
+ StaticStr:='-static';
+ end;
+ if (cs_link_strip in current_settings.globalswitches) then
+ if (target_info.system in systems_darwin) then
+ StripStr:='-x'
+ else
+ StripStr:='-s';
+
+ if (cs_link_smart in current_settings.globalswitches) and
+ (tf_smartlink_sections in target_info.flags) then
+ if not(target_info.system in systems_darwin) then
+ GCSectionsStr:='--gc-sections'
+ else
+ GCSectionsStr:='-dead_strip -no_dead_strip_inits_and_terms';
+
+ if(not(target_info.system in systems_darwin) and
+ (cs_profile in current_settings.moduleswitches)) or
+ ((Info.DynamicLinker<>'') and (not SharedLibFiles.Empty)) then
+ DynLinkStr:='-dynamic-linker='+Info.DynamicLinker;
+
+ if CShared Then
+ begin
+ if not(target_info.system in systems_darwin) then
+ DynLinKStr:=DynLinkStr+' --shared'
+ else
+ DynLinKStr:=DynLinkStr+' -dynamic'; // one dash!
+ end;
+{ Write used files and libraries }
+ WriteResponseFile(false);
+
+{ Call linker }
+ SplitBinCmd(Info.ExeCmd[1],binstr,cmdstr);
+ Replace(cmdstr,'$EXE',maybequoted(current_module.exefilename^));
+ Replace(cmdstr,'$OPT',Info.ExtraOptions);
+ Replace(cmdstr,'$CATRES',CatFileContent(outputexedir+Info.ResName));
+ Replace(cmdstr,'$RES',maybequoted(outputexedir+Info.ResName));
+ Replace(cmdstr,'$STATIC',StaticStr);
+ Replace(cmdstr,'$STRIP',StripStr);
+ Replace(cmdstr,'$GCSECTIONS',GCSectionsStr);
+ Replace(cmdstr,'$DYNLINK',DynLinkStr);
+ if (target_info.system in systems_darwin) then
+ Replace(cmdstr,'$PRTOBJ',GetDarwinPrtobjName(false));
+ BinStr:=FindUtil(utilsprefix+BinStr);
+
+ { create dsym file? }
+ extdbgbinstr:='';
+ extdbgcmdstr:='';
+ if (target_info.system in systems_darwin) and
+ (target_dbg.id in [dbg_dwarf2,dbg_dwarf3]) and
+ (cs_link_separate_dbg_file in current_settings.globalswitches) then
+ begin
+ extdbgbinstr:=FindUtil(utilsprefix+'dsymutil');
+ extdbgcmdstr:=maybequoted(current_module.exefilename^);
+ end;
+
+ if (LdSupportsNoResponseFile) and
+ not(cs_link_nolink in current_settings.globalswitches) then
+ begin
+ { we have to use a script to use the IFS hack }
+ linkscript:=TAsmScriptUnix.create(outputexedir+'ppaslink');
+ linkscript.AddLinkCommand(BinStr,CmdStr,'');
+ if (extdbgcmdstr<>'') then
+ linkscript.AddLinkCommand(extdbgbinstr,extdbgcmdstr,'');
+ linkscript.WriteToDisk;
+ BinStr:=linkscript.fn;
+ if not path_absolute(BinStr) then
+ BinStr:='./'+BinStr;
+ CmdStr:='';
+ end;
+
+ useshell:=not (tf_no_backquote_support in source_info.flags);
+ success:=DoExec(BinStr,CmdStr,true,LdSupportsNoResponseFile or useshell);
+ if (success and
+ (extdbgbinstr<>'') and
+ (cs_link_nolink in current_settings.globalswitches)) then
+ success:=DoExec(extdbgbinstr,extdbgcmdstr,false,LdSupportsNoResponseFile);
+
+{ Remove ReponseFile }
+ if (success) and not(cs_link_nolink in current_settings.globalswitches) then
+ begin
+ DeleteFile(outputexedir+Info.ResName);
+ if LdSupportsNoResponseFile Then
+ begin
+ DeleteFile(linkscript.fn);
+ linkscript.free
+ end;
+ end;
+
+ MakeExecutable:=success; { otherwise a recursive call to link method }
+end;
+
+
+Function TLinkerBSD.MakeSharedLibrary:boolean;
+var
+ InitStr,
+ FiniStr,
+ SoNameStr : string[80];
+ linkscript: TAsmScript;
+ binstr,
+ cmdstr,
+ extdbgbinstr,
+ extdbgcmdstr : TCmdStr;
+ GCSectionsStr : string[63];
+ exportedsyms: text;
+ success : boolean;
+begin
+ MakeSharedLibrary:=false;
+ GCSectionsStr:='';
+ if not(cs_link_nolink in current_settings.globalswitches) then
+ Message1(exec_i_linking,current_module.sharedlibfilename^);
+
+{ Write used files and libraries }
+ WriteResponseFile(true);
+
+ if (cs_link_smart in current_settings.globalswitches) and
+ (tf_smartlink_sections in target_info.flags) then
+ if not(target_info.system in systems_darwin) then
+ { disabled because not tested
+ GCSectionsStr:='--gc-sections' }
+ else
+ GCSectionsStr:='-dead_strip -no_dead_strip_inits_and_terms';
+
+ InitStr:='-init FPC_LIB_START';
+ FiniStr:='-fini FPC_LIB_EXIT';
+ SoNameStr:='-soname '+ExtractFileName(current_module.sharedlibfilename^);
+
+{ Call linker }
+ SplitBinCmd(Info.DllCmd[1],binstr,cmdstr);
+{$ifndef darwin}
+ Replace(cmdstr,'$EXE',maybequoted(current_module.sharedlibfilename^));
+{$else darwin}
+ Replace(cmdstr,'$EXE',maybequoted(ExpandFileName(current_module.sharedlibfilename^)));
+{$endif darwin}
+ Replace(cmdstr,'$OPT',Info.ExtraOptions);
+ Replace(cmdstr,'$CATRES',CatFileContent(outputexedir+Info.ResName));
+ Replace(cmdstr,'$RES',maybequoted(outputexedir+Info.ResName));
+ Replace(cmdstr,'$INIT',InitStr);
+ Replace(cmdstr,'$FINI',FiniStr);
+ Replace(cmdstr,'$GCSECTIONS',GCSectionsStr);
+ Replace(cmdstr,'$SONAME',SoNameStr);
+ if (target_info.system in systems_darwin) then
+ Replace(cmdstr,'$PRTOBJ',GetDarwinPrtobjName(true));
+ BinStr:=FindUtil(utilsprefix+BinStr);
+
+ { create dsym file? }
+ extdbgbinstr:='';
+ extdbgcmdstr:='';
+ if (target_info.system in systems_darwin) and
+ (target_dbg.id in [dbg_dwarf2,dbg_dwarf3]) and
+ (cs_link_separate_dbg_file in current_settings.globalswitches) then
+ begin
+ extdbgbinstr:=FindUtil(utilsprefix+'dsymutil');
+ extdbgcmdstr:=maybequoted(current_module.sharedlibfilename^);
+ end;
+
+ if (target_info.system in systems_darwin) then
+ begin
+ { exported symbols for darwin }
+ if not texportlibunix(exportlib).exportedsymnames.empty then
+ begin
+ assign(exportedsyms,outputexedir+'linksyms.fpc');
+ rewrite(exportedsyms);
+ repeat
+ writeln(exportedsyms,texportlibunix(exportlib).exportedsymnames.getfirst);
+ until texportlibunix(exportlib).exportedsymnames.empty;
+ close(exportedsyms);
+ cmdstr:=cmdstr+' -exported_symbols_list '+maybequoted(outputexedir)+'linksyms.fpc';
+ end;
+ end;
+
+ if (LdSupportsNoResponseFile) and
+ not(cs_link_nolink in current_settings.globalswitches) then
+ begin
+ { we have to use a script to use the IFS hack }
+ linkscript:=TAsmScriptUnix.create(outputexedir+'ppaslink');
+ linkscript.AddLinkCommand(BinStr,CmdStr,'');
+ if (extdbgbinstr<>'') then
+ linkscript.AddLinkCommand(extdbgbinstr,extdbgcmdstr,'');
+ linkscript.WriteToDisk;
+ BinStr:=linkscript.fn;
+ if not path_absolute(BinStr) then
+ BinStr:='./'+BinStr;
+ CmdStr:='';
+ end;
+
+ success:=DoExec(BinStr,cmdstr,true,LdSupportsNoResponseFile);
+ if (success and
+ (extdbgbinstr<>'') and
+ (cs_link_nolink in current_settings.globalswitches)) then
+ success:=DoExec(extdbgbinstr,extdbgcmdstr,false,LdSupportsNoResponseFile);
+
+{ Strip the library ? }
+ if success and (cs_link_strip in current_settings.globalswitches) then
+ begin
+ SplitBinCmd(Info.DllCmd[2],binstr,cmdstr);
+ Replace(cmdstr,'$EXE',maybequoted(current_module.sharedlibfilename^));
+ success:=DoExec(FindUtil(utilsprefix+binstr),cmdstr,false,false);
+ end;
+
+{ Remove ReponseFile }
+ if (success) and not(cs_link_nolink in current_settings.globalswitches) then
+ begin
+ DeleteFile(outputexedir+Info.ResName);
+ if LdSupportsNoResponseFile Then
+ begin
+ DeleteFile(linkscript.fn);
+ linkscript.free
+ end;
+ if (target_info.system in systems_darwin) then
+ DeleteFile(outputexedir+'linksyms.fpc');
+ end;
+
+ MakeSharedLibrary:=success; { otherwise a recursive call to link method }
+end;
+
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+initialization
+{$ifdef x86_64}
+ RegisterExternalLinker(system_x86_64_FreeBSD_info,TLinkerBSD);
+ RegisterImport(system_x86_64_freebsd,timportlibbsd);
+ RegisterExport(system_x86_64_freebsd,texportlibbsd);
+ RegisterTarget(system_x86_64_freebsd_info);
+
+ RegisterExternalLinker(system_x86_64_darwin_info,TLinkerBSD);
+ RegisterImport(system_x86_64_darwin,timportlibdarwin);
+ RegisterExport(system_x86_64_darwin,texportlibdarwin);
+ RegisterTarget(system_x86_64_darwin_info);
+{$endif}
+{$ifdef i386}
+ RegisterExternalLinker(system_i386_FreeBSD_info,TLinkerBSD);
+ RegisterExternalLinker(system_i386_NetBSD_info,TLinkerBSD);
+ RegisterExternalLinker(system_i386_OpenBSD_info,TLinkerBSD);
+ RegisterImport(system_i386_freebsd,timportlibbsd);
+ RegisterExport(system_i386_freebsd,texportlibbsd);
+ RegisterTarget(system_i386_freebsd_info);
+ RegisterImport(system_i386_netbsd,timportlibbsd);
+ RegisterExport(system_i386_netbsd,texportlibbsd);
+ RegisterTarget(system_i386_netbsd_info);
+ RegisterImport(system_i386_openbsd,timportlibbsd);
+ RegisterExport(system_i386_openbsd,texportlibbsd);
+ RegisterTarget(system_i386_openbsd_info);
+ RegisterExternalLinker(system_i386_darwin_info,TLinkerBSD);
+ RegisterImport(system_i386_darwin,timportlibdarwin);
+ RegisterExport(system_i386_darwin,texportlibdarwin);
+ RegisterTarget(system_i386_darwin_info);
+ RegisterExternalLinker(system_i386_iphonesim_info,TLinkerBSD);
+ RegisterImport(system_i386_iphonesim,timportlibdarwin);
+ RegisterExport(system_i386_iphonesim,texportlibdarwin);
+ RegisterTarget(system_i386_iphonesim_info);
+{$endif i386}
+{$ifdef m68k}
+// RegisterExternalLinker(system_m68k_FreeBSD_info,TLinkerBSD);
+ RegisterExternalLinker(system_m68k_NetBSD_info,TLinkerBSD);
+ RegisterImport(system_m68k_netbsd,timportlibbsd);
+ RegisterExport(system_m68k_netbsd,texportlibbsd);
+ RegisterTarget(system_m68k_netbsd_info);
+{$endif m68k}
+{$ifdef powerpc}
+// RegisterExternalLinker(system_m68k_FreeBSD_info,TLinkerBSD);
+ RegisterExternalLinker(system_powerpc_darwin_info,TLinkerBSD);
+ RegisterImport(system_powerpc_darwin,timportlibdarwin);
+ RegisterExport(system_powerpc_darwin,texportlibdarwin);
+ RegisterTarget(system_powerpc_darwin_info);
+
+ RegisterExternalLinker(system_powerpc_netbsd_info,TLinkerBSD);
+ RegisterImport(system_powerpc_netbsd,timportlibbsd);
+ RegisterExport(system_powerpc_netbsd,texportlibbsd);
+ RegisterTarget(system_powerpc_netbsd_info);
+{$endif powerpc}
+{$ifdef powerpc64}
+ RegisterExternalLinker(system_powerpc64_darwin_info,TLinkerBSD);
+ RegisterImport(system_powerpc64_darwin,timportlibdarwin);
+ RegisterExport(system_powerpc64_darwin,texportlibdarwin);
+ RegisterTarget(system_powerpc64_darwin_info);
+{$endif powerpc64}
+{$ifdef arm}
+ RegisterExternalLinker(system_arm_darwin_info,TLinkerBSD);
+ RegisterImport(system_arm_darwin,timportlibdarwin);
+ RegisterExport(system_arm_darwin,texportlibdarwin);
+ RegisterTarget(system_arm_darwin_info);
+{$endif arm}
+
+ RegisterRes(res_elf_info,TWinLikeResourceFile);
+ RegisterRes(res_macho_info,TWinLikeResourceFile);
+end.
diff --git a/closures/compiler/systems/t_embed.pas b/closures/compiler/systems/t_embed.pas
new file mode 100644
index 0000000000..30c79df7ad
--- /dev/null
+++ b/closures/compiler/systems/t_embed.pas
@@ -0,0 +1,910 @@
+{
+ This unit implements support import,export,link routines
+ for the (arm) GameBoy Advance target
+
+ Copyright (c) 2001-2002 by Peter Vreman
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit t_embed;
+
+{$i fpcdefs.inc}
+
+interface
+
+
+implementation
+
+ uses
+ SysUtils,
+ cutils,cfileutl,cclasses,
+ globtype,globals,systems,verbose,comphook,script,fmodule,i_embed,link,
+ cpuinfo;
+
+ type
+ TlinkerEmbedded=class(texternallinker)
+ private
+ Function WriteResponseFile: Boolean;
+ public
+ constructor Create; override;
+ procedure SetDefaultInfo; override;
+ function MakeExecutable:boolean; override;
+ function postprocessexecutable(const fn : string;isdll:boolean):boolean;
+ end;
+
+
+
+{*****************************************************************************
+ TlinkerEmbedded
+*****************************************************************************}
+
+Constructor TlinkerEmbedded.Create;
+begin
+ Inherited Create;
+ SharedLibFiles.doubles:=true;
+ StaticLibFiles.doubles:=true;
+end;
+
+
+procedure TlinkerEmbedded.SetDefaultInfo;
+begin
+ with Info do
+ begin
+ ExeCmd[1]:='ld -g $OPT $DYNLINK $STATIC $GCSECTIONS $STRIP -L. -o $EXE -T $RES';
+ end;
+end;
+
+
+Function TlinkerEmbedded.WriteResponseFile: Boolean;
+Var
+ linkres : TLinkRes;
+ i : longint;
+ HPath : TCmdStrListItem;
+ s,s1,s2 : TCmdStr;
+ prtobj,
+ cprtobj : string[80];
+ linklibc : boolean;
+ found1,
+ found2 : boolean;
+{$ifdef ARM}
+ LinkStr : string;
+{$endif}
+begin
+ WriteResponseFile:=False;
+ linklibc:=(SharedLibFiles.Find('c')<>nil);
+{$if defined(ARM) or defined(i386) or defined(AVR)}
+ prtobj:='';
+{$else}
+ prtobj:='prt0';
+{$endif}
+ cprtobj:='cprt0';
+ if linklibc then
+ prtobj:=cprtobj;
+
+ { Open link.res file }
+ LinkRes:=TLinkRes.Create(outputexedir+Info.ResName);
+
+ { Write path to search libraries }
+ HPath:=TCmdStrListItem(current_module.locallibrarysearchpath.First);
+ while assigned(HPath) do
+ begin
+ s:=HPath.Str;
+ if (cs_link_on_target in current_settings.globalswitches) then
+ s:=ScriptFixFileName(s);
+ LinkRes.Add('-L'+s);
+ HPath:=TCmdStrListItem(HPath.Next);
+ end;
+ HPath:=TCmdStrListItem(LibrarySearchPath.First);
+ while assigned(HPath) do
+ begin
+ s:=HPath.Str;
+ if s<>'' then
+ LinkRes.Add('SEARCH_DIR('+(maybequoted(s))+')');
+ HPath:=TCmdStrListItem(HPath.Next);
+ end;
+
+ LinkRes.Add('INPUT (');
+ { add objectfiles, start with prt0 always }
+ //s:=FindObjectFile('prt0','',false);
+ if prtobj<>'' then
+ begin
+ s:=FindObjectFile(prtobj,'',false);
+ LinkRes.AddFileName(s);
+ end;
+ { try to add crti and crtbegin if linking to C }
+ if linklibc then
+ begin
+ if librarysearchpath.FindFile('crtbegin.o',false,s) then
+ LinkRes.AddFileName(s);
+ if librarysearchpath.FindFile('crti.o',false,s) then
+ LinkRes.AddFileName(s);
+ end;
+
+ while not ObjectFiles.Empty do
+ begin
+ s:=ObjectFiles.GetFirst;
+ if s<>'' then
+ begin
+ { vlink doesn't use SEARCH_DIR for object files }
+ if not(cs_link_on_target in current_settings.globalswitches) then
+ s:=FindObjectFile(s,'',false);
+ LinkRes.AddFileName((maybequoted(s)));
+ end;
+ end;
+
+ { Write staticlibraries }
+ if not StaticLibFiles.Empty then
+ begin
+ { vlink doesn't need, and doesn't support GROUP }
+ if (cs_link_on_target in current_settings.globalswitches) then
+ begin
+ LinkRes.Add(')');
+ LinkRes.Add('GROUP(');
+ end;
+ while not StaticLibFiles.Empty do
+ begin
+ S:=StaticLibFiles.GetFirst;
+ LinkRes.AddFileName((maybequoted(s)));
+ end;
+ end;
+
+ if (cs_link_on_target in current_settings.globalswitches) then
+ begin
+ LinkRes.Add(')');
+
+ { Write sharedlibraries like -l<lib>, also add the needed dynamic linker
+ here to be sure that it gets linked this is needed for glibc2 systems (PFV) }
+ linklibc:=false;
+ while not SharedLibFiles.Empty do
+ begin
+ S:=SharedLibFiles.GetFirst;
+ if s<>'c' then
+ begin
+ i:=Pos(target_info.sharedlibext,S);
+ if i>0 then
+ Delete(S,i,255);
+ LinkRes.Add('-l'+s);
+ end
+ else
+ begin
+ LinkRes.Add('-l'+s);
+ linklibc:=true;
+ end;
+ end;
+ { be sure that libc&libgcc is the last lib }
+ if linklibc then
+ begin
+ LinkRes.Add('-lc');
+ LinkRes.Add('-lgcc');
+ end;
+ end
+ else
+ begin
+ while not SharedLibFiles.Empty do
+ begin
+ S:=SharedLibFiles.GetFirst;
+ LinkRes.Add('lib'+s+target_info.staticlibext);
+ end;
+ LinkRes.Add(')');
+ end;
+
+ { objects which must be at the end }
+ if linklibc then
+ begin
+ found1:=librarysearchpath.FindFile('crtend.o',false,s1);
+ found2:=librarysearchpath.FindFile('crtn.o',false,s2);
+ if found1 or found2 then
+ begin
+ LinkRes.Add('INPUT(');
+ if found1 then
+ LinkRes.AddFileName(s1);
+ if found2 then
+ LinkRes.AddFileName(s2);
+ LinkRes.Add(')');
+ end;
+ end;
+
+{$ifdef ARM}
+ case current_settings.controllertype of
+ ct_none:
+ begin
+ end;
+ ct_lpc2114,
+ ct_lpc2124,
+ ct_lpc2194,
+ ct_lpc1768,
+ ct_at91sam7s256,
+ ct_at91sam7se256,
+ ct_at91sam7x256,
+ ct_at91sam7xc256,
+
+ ct_stm32f103rb,
+ ct_stm32f103re,
+ ct_stm32f103c4t,
+
+ { TI - 64 K Flash, 16 K SRAM Devices }
+ ct_lm3s1110,
+ ct_lm3s1133,
+ ct_lm3s1138,
+ ct_lm3s1150,
+ ct_lm3s1162,
+ ct_lm3s1165,
+ ct_lm3s1166,
+ ct_lm3s2110,
+ ct_lm3s2139,
+ ct_lm3s6100,
+ ct_lm3s6110,
+
+ { TI 128 K Flash, 32 K SRAM devices - Fury Class }
+ ct_lm3s1601,
+ ct_lm3s1608,
+ ct_lm3s1620,
+ ct_lm3s1635,
+ ct_lm3s1636,
+ ct_lm3s1637,
+ ct_lm3s1651,
+ ct_lm3s2601,
+ ct_lm3s2608,
+ ct_lm3s2620,
+ ct_lm3s2637,
+ ct_lm3s2651,
+ ct_lm3s6610,
+ ct_lm3s6611,
+ ct_lm3s6618,
+ ct_lm3s6633,
+ ct_lm3s6637,
+ ct_lm3s8630,
+
+ { TI 256 K Flase, 32 K SRAM devices - Fury Class }
+ ct_lm3s1911,
+ ct_lm3s1918,
+ ct_lm3s1937,
+ ct_lm3s1958,
+ ct_lm3s1960,
+ ct_lm3s1968,
+ ct_lm3s1969,
+ ct_lm3s2911,
+ ct_lm3s2918,
+ ct_lm3s2919,
+ ct_lm3s2939,
+ ct_lm3s2948,
+ ct_lm3s2950,
+ ct_lm3s2965,
+ ct_lm3s6911,
+ ct_lm3s6918,
+ ct_lm3s6938,
+ ct_lm3s6950,
+ ct_lm3s6952,
+ ct_lm3s6965,
+ ct_lm3s8930,
+ ct_lm3s8933,
+ ct_lm3s8938,
+ ct_lm3s8962,
+ ct_lm3s8970,
+ ct_lm3s8971,
+
+ { TI - Tempest Tempest - 256 K Flash, 64 K SRAM }
+ ct_lm3s5951,
+ ct_lm3s5956,
+ ct_lm3s1b21,
+ ct_lm3s2b93,
+ ct_lm3s5b91,
+ ct_lm3s9b81,
+ ct_lm3s9b90,
+ ct_lm3s9b92,
+ ct_lm3s9b95,
+ ct_lm3s9b96,
+ ct_sc32442b,
+ ct_thumb2bare:
+ begin
+ with embedded_controllers[current_settings.controllertype] do
+ with linkres do
+ begin
+ Add('ENTRY(_START)');
+ Add('MEMORY');
+ Add('{');
+ if flashsize<>0 then
+ begin
+ LinkStr := ' flash : ORIGIN = 0x' + IntToHex(flashbase,8)
+ + ', LENGTH = 0x' + IntToHex(flashsize,8);
+ Add(LinkStr);
+ end;
+
+ LinkStr := ' ram : ORIGIN = 0x' + IntToHex(srambase,8)
+ + ', LENGTH = 0x' + IntToHex(sramsize,8);
+ Add(LinkStr);
+
+ Add('}');
+ Add('_stack_top = 0x' + IntToHex(sramsize+srambase,8) + ';');
+ end;
+ end
+ else
+ if not (cs_link_nolink in current_settings.globalswitches) then
+ internalerror(200902011);
+ end;
+
+ with linkres do
+ begin
+ Add('SECTIONS');
+ Add('{');
+ Add(' .text :');
+ Add(' {');
+ Add(' KEEP(*(.init, .init.*))');
+ Add(' *(.text, .text.*)');
+ Add(' *(.strings)');
+ Add(' *(.rodata, .rodata.*)');
+ Add(' *(.comment)');
+ Add(' _etext = .;');
+ if embedded_controllers[current_settings.controllertype].flashsize<>0 then
+ begin
+ Add(' } >flash');
+ end
+ else
+ begin
+ Add(' } >ram');
+ end;
+ Add(' .data :');
+ Add(' {');
+ Add(' _data = .;');
+ Add(' *(.data, .data.*)');
+ Add(' KEEP (*(.fpc .fpc.n_version .fpc.n_links))');
+ Add(' _edata = .;');
+ if embedded_controllers[current_settings.controllertype].flashsize<>0 then
+ begin
+ Add(' } >ram AT >flash');
+ end
+ else
+ begin
+ Add(' } >ram');
+ end;
+ Add(' .bss :');
+ Add(' {');
+ Add(' _bss_start = .;');
+ Add(' *(.bss, .bss.*)');
+ Add(' *(COMMON)');
+ Add(' } >ram');
+ Add('. = ALIGN(4);');
+ Add('_bss_end = . ;');
+ Add('}');
+ Add('_end = .;');
+ end;
+{$endif ARM}
+
+{$ifdef i386}
+ with linkres do
+ begin
+ Add('ENTRY(_START)');
+ Add('SECTIONS');
+ Add('{');
+ Add(' . = 0x100000;');
+ Add(' .text ALIGN (0x1000) :');
+ Add(' {');
+ Add(' KEEP(*(.init, .init.*))');
+ Add(' *(.text, .text.*)');
+ Add(' *(.strings)');
+ Add(' *(.rodata, .rodata.*)');
+ Add(' *(.comment)');
+ Add(' _etext = .;');
+ Add(' }');
+ Add(' .data ALIGN (0x1000) :');
+ Add(' {');
+ Add(' _data = .;');
+ Add(' *(.data, .data.*)');
+ Add(' KEEP (*(.fpc .fpc.n_version .fpc.n_links))');
+ Add(' _edata = .;');
+ Add(' }');
+ Add(' . = ALIGN(4);');
+ Add(' .bss :');
+ Add(' {');
+ Add(' _bss_start = .;');
+ Add(' *(.bss, .bss.*)');
+ Add(' *(COMMON)');
+ Add(' }');
+ Add('_bss_end = . ;');
+ Add('}');
+ Add('_end = .;');
+ end;
+{$endif i386}
+
+{$ifdef AVR}
+ with linkres do
+ begin
+ { linker script from ld 2.19 }
+ Add('ENTRY(_START)');
+ Add('OUTPUT_FORMAT("elf32-avr","elf32-avr","elf32-avr")');
+ Add('OUTPUT_ARCH(avr:2)');
+ Add('MEMORY');
+ Add('{');
+ Add(' text (rx) : ORIGIN = 0, LENGTH = 8K');
+ Add(' data (rw!x) : ORIGIN = 0x800060, LENGTH = 0xffa0');
+ Add(' eeprom (rw!x) : ORIGIN = 0x810000, LENGTH = 64K');
+ Add(' fuse (rw!x) : ORIGIN = 0x820000, LENGTH = 1K');
+ Add(' lock (rw!x) : ORIGIN = 0x830000, LENGTH = 1K');
+ Add(' signature (rw!x) : ORIGIN = 0x840000, LENGTH = 1K');
+ Add('}');
+ Add('SECTIONS');
+ Add('{');
+ Add(' /* Read-only sections, merged into text segment: */');
+ Add(' .hash : { *(.hash) }');
+ Add(' .dynsym : { *(.dynsym) }');
+ Add(' .dynstr : { *(.dynstr) }');
+ Add(' .gnu.version : { *(.gnu.version) }');
+ Add(' .gnu.version_d : { *(.gnu.version_d) }');
+ Add(' .gnu.version_r : { *(.gnu.version_r) }');
+ Add(' .rel.init : { *(.rel.init) }');
+ Add(' .rela.init : { *(.rela.init) }');
+ Add(' .rel.text :');
+ Add(' {');
+ Add(' *(.rel.text)');
+ Add(' *(.rel.text.*)');
+ Add(' *(.rel.gnu.linkonce.t*)');
+ Add(' }');
+ Add(' .rela.text :');
+ Add(' {');
+ Add(' *(.rela.text)');
+ Add(' *(.rela.text.*)');
+ Add(' *(.rela.gnu.linkonce.t*)');
+ Add(' }');
+ Add(' .rel.fini : { *(.rel.fini) }');
+ Add(' .rela.fini : { *(.rela.fini) }');
+ Add(' .rel.rodata :');
+ Add(' {');
+ Add(' *(.rel.rodata)');
+ Add(' *(.rel.rodata.*)');
+ Add(' *(.rel.gnu.linkonce.r*)');
+ Add(' }');
+ Add(' .rela.rodata :');
+ Add(' {');
+ Add(' *(.rela.rodata)');
+ Add(' *(.rela.rodata.*)');
+ Add(' *(.rela.gnu.linkonce.r*)');
+ Add(' }');
+ Add(' .rel.data :');
+ Add(' {');
+ Add(' *(.rel.data)');
+ Add(' *(.rel.data.*)');
+ Add(' *(.rel.gnu.linkonce.d*)');
+ Add(' }');
+ Add(' .rela.data :');
+ Add(' {');
+ Add(' *(.rela.data)');
+ Add(' *(.rela.data.*)');
+ Add(' *(.rela.gnu.linkonce.d*)');
+ Add(' }');
+ Add(' .rel.ctors : { *(.rel.ctors) }');
+ Add(' .rela.ctors : { *(.rela.ctors) }');
+ Add(' .rel.dtors : { *(.rel.dtors) }');
+ Add(' .rela.dtors : { *(.rela.dtors) }');
+ Add(' .rel.got : { *(.rel.got) }');
+ Add(' .rela.got : { *(.rela.got) }');
+ Add(' .rel.bss : { *(.rel.bss) }');
+ Add(' .rela.bss : { *(.rela.bss) }');
+ Add(' .rel.plt : { *(.rel.plt) }');
+ Add(' .rela.plt : { *(.rela.plt) }');
+ Add(' /* Internal text space or external memory. */');
+ Add(' .text :');
+ Add(' {');
+ Add(' *(.vectors)');
+ Add(' KEEP(*(.vectors))');
+ Add(' /* For data that needs to reside in the lower 64k of progmem. */');
+ Add(' *(.progmem.gcc*)');
+ Add(' *(.progmem*)');
+ Add(' . = ALIGN(2);');
+ Add(' __trampolines_start = . ;');
+ Add(' /* The jump trampolines for the 16-bit limited relocs will reside here. */');
+ Add(' *(.trampolines)');
+ Add(' *(.trampolines*)');
+ Add(' __trampolines_end = . ;');
+ Add(' /* For future tablejump instruction arrays for 3 byte pc devices.');
+ Add(' We don''t relax jump/call instructions within these sections. */');
+ Add(' *(.jumptables)');
+ Add(' *(.jumptables*)');
+ Add(' /* For code that needs to reside in the lower 128k progmem. */');
+ Add(' *(.lowtext)');
+ Add(' *(.lowtext*)');
+ Add(' __ctors_start = . ;');
+ Add(' *(.ctors)');
+ Add(' __ctors_end = . ;');
+ Add(' __dtors_start = . ;');
+ Add(' *(.dtors)');
+ Add(' __dtors_end = . ;');
+ Add(' KEEP(SORT(*)(.ctors))');
+ Add(' KEEP(SORT(*)(.dtors))');
+ Add(' /* From this point on, we don''t bother about wether the insns are');
+ Add(' below or above the 16 bits boundary. */');
+ Add(' *(.init0) /* Start here after reset. */');
+ Add(' KEEP (*(.init0))');
+ Add(' *(.init1)');
+ Add(' KEEP (*(.init1))');
+ Add(' *(.init2) /* Clear __zero_reg__, set up stack pointer. */');
+ Add(' KEEP (*(.init2))');
+ Add(' *(.init3)');
+ Add(' KEEP (*(.init3))');
+ Add(' *(.init4) /* Initialize data and BSS. */');
+ Add(' KEEP (*(.init4))');
+ Add(' *(.init5)');
+ Add(' KEEP (*(.init5))');
+ Add(' *(.init6) /* C++ constructors. */');
+ Add(' KEEP (*(.init6))');
+ Add(' *(.init7)');
+ Add(' KEEP (*(.init7))');
+ Add(' *(.init8)');
+ Add(' KEEP (*(.init8))');
+ Add(' *(.init9) /* Call main(). */');
+ Add(' KEEP (*(.init9))');
+ Add(' *(.text)');
+ Add(' . = ALIGN(2);');
+ Add(' *(.text.*)');
+ Add(' . = ALIGN(2);');
+ Add(' *(.fini9) /* _exit() starts here. */');
+ Add(' KEEP (*(.fini9))');
+ Add(' *(.fini8)');
+ Add(' KEEP (*(.fini8))');
+ Add(' *(.fini7)');
+ Add(' KEEP (*(.fini7))');
+ Add(' *(.fini6) /* C++ destructors. */');
+ Add(' KEEP (*(.fini6))');
+ Add(' *(.fini5)');
+ Add(' KEEP (*(.fini5))');
+ Add(' *(.fini4)');
+ Add(' KEEP (*(.fini4))');
+ Add(' *(.fini3)');
+ Add(' KEEP (*(.fini3))');
+ Add(' *(.fini2)');
+ Add(' KEEP (*(.fini2))');
+ Add(' *(.fini1)');
+ Add(' KEEP (*(.fini1))');
+ Add(' *(.fini0) /* Infinite loop after program termination. */');
+ Add(' KEEP (*(.fini0))');
+ Add(' _etext = . ;');
+ Add(' } > text');
+ Add(' .data : AT (ADDR (.text) + SIZEOF (.text))');
+ Add(' {');
+ Add(' PROVIDE (__data_start = .) ;');
+ Add(' *(.data)');
+ Add(' *(.data*)');
+ Add(' *(.rodata) /* We need to include .rodata here if gcc is used */');
+ Add(' *(.rodata*) /* with -fdata-sections. */');
+ Add(' *(.gnu.linkonce.d*)');
+ Add(' . = ALIGN(2);');
+ Add(' _edata = . ;');
+ Add(' PROVIDE (__data_end = .) ;');
+ Add(' } > data');
+ Add(' .bss : AT (ADDR (.bss))');
+ Add(' {');
+ Add(' PROVIDE (__bss_start = .) ;');
+ Add(' *(.bss)');
+ Add(' *(.bss*)');
+ Add(' *(COMMON)');
+ Add(' PROVIDE (__bss_end = .) ;');
+ Add(' } > data');
+ Add(' __data_load_start = LOADADDR(.data);');
+ Add(' __data_load_end = __data_load_start + SIZEOF(.data);');
+ Add(' /* Global data not cleared after reset. */');
+ Add(' .noinit :');
+ Add(' {');
+ Add(' PROVIDE (__noinit_start = .) ;');
+ Add(' *(.noinit*)');
+ Add(' PROVIDE (__noinit_end = .) ;');
+ Add(' _end = . ;');
+ Add(' PROVIDE (__heap_start = .) ;');
+ Add(' } > data');
+ Add(' .eeprom :');
+ Add(' {');
+ Add(' *(.eeprom*)');
+ Add(' __eeprom_end = . ;');
+ Add(' } > eeprom');
+ Add(' .fuse :');
+ Add(' {');
+ Add(' KEEP(*(.fuse))');
+ Add(' KEEP(*(.lfuse))');
+ Add(' KEEP(*(.hfuse))');
+ Add(' KEEP(*(.efuse))');
+ Add(' } > fuse');
+ Add(' .lock :');
+ Add(' {');
+ Add(' KEEP(*(.lock*))');
+ Add(' } > lock');
+ Add(' .signature :');
+ Add(' {');
+ Add(' KEEP(*(.signature*))');
+ Add(' } > signature');
+ Add(' /* Stabs debugging sections. */');
+ Add(' .stab 0 : { *(.stab) }');
+ Add(' .stabstr 0 : { *(.stabstr) }');
+ Add(' .stab.excl 0 : { *(.stab.excl) }');
+ Add(' .stab.exclstr 0 : { *(.stab.exclstr) }');
+ Add(' .stab.index 0 : { *(.stab.index) }');
+ Add(' .stab.indexstr 0 : { *(.stab.indexstr) }');
+ Add(' .comment 0 : { *(.comment) }');
+ Add(' /* DWARF debug sections.');
+ Add(' Symbols in the DWARF debugging sections are relative to the beginning');
+ Add(' of the section so we begin them at 0. */');
+ Add(' /* DWARF 1 */');
+ Add(' .debug 0 : { *(.debug) }');
+ Add(' .line 0 : { *(.line) }');
+ Add(' /* GNU DWARF 1 extensions */');
+ Add(' .debug_srcinfo 0 : { *(.debug_srcinfo) }');
+ Add(' .debug_sfnames 0 : { *(.debug_sfnames) }');
+ Add(' /* DWARF 1.1 and DWARF 2 */');
+ Add(' .debug_aranges 0 : { *(.debug_aranges) }');
+ Add(' .debug_pubnames 0 : { *(.debug_pubnames) }');
+ Add(' /* DWARF 2 */');
+ Add(' .debug_info 0 : { *(.debug_info) *(.gnu.linkonce.wi.*) }');
+ Add(' .debug_abbrev 0 : { *(.debug_abbrev) }');
+ Add(' .debug_line 0 : { *(.debug_line) }');
+ Add(' .debug_frame 0 : { *(.debug_frame) }');
+ Add(' .debug_str 0 : { *(.debug_str) }');
+ Add(' .debug_loc 0 : { *(.debug_loc) }');
+ Add(' .debug_macinfo 0 : { *(.debug_macinfo) }');
+ Add('}');
+ { last address of ram on an atmega128 }
+ Add('_stack_top = 0x0fff;');
+ end;
+{$endif AVR}
+
+ { Write and Close response }
+ linkres.writetodisk;
+ linkres.free;
+
+ WriteResponseFile:=True;
+
+end;
+
+
+function TlinkerEmbedded.MakeExecutable:boolean;
+var
+ binstr,
+ cmdstr : TCmdStr;
+ success : boolean;
+ StaticStr,
+ GCSectionsStr,
+ DynLinkStr,
+ StripStr: string;
+begin
+ { for future use }
+ StaticStr:='';
+ StripStr:='';
+ DynLinkStr:='';
+
+ GCSectionsStr:='--gc-sections';
+ //if not(cs_link_extern in current_settings.globalswitches) then
+ if not(cs_link_nolink in current_settings.globalswitches) then
+ Message1(exec_i_linking,current_module.exefilename^);
+
+{ Write used files and libraries }
+ WriteResponseFile();
+
+{ Call linker }
+ SplitBinCmd(Info.ExeCmd[1],binstr,cmdstr);
+ Replace(cmdstr,'$OPT',Info.ExtraOptions);
+ if not(cs_link_on_target in current_settings.globalswitches) then
+ begin
+ Replace(cmdstr,'$EXE',(maybequoted(ScriptFixFileName(ChangeFileExt(current_module.exefilename^,'.elf')))));
+ Replace(cmdstr,'$RES',(maybequoted(ScriptFixFileName(outputexedir+Info.ResName))));
+ Replace(cmdstr,'$STATIC',StaticStr);
+ Replace(cmdstr,'$STRIP',StripStr);
+ Replace(cmdstr,'$GCSECTIONS',GCSectionsStr);
+ Replace(cmdstr,'$DYNLINK',DynLinkStr);
+ end
+ else
+ begin
+ Replace(cmdstr,'$EXE',maybequoted(ScriptFixFileName(ChangeFileExt(current_module.exefilename^,'.elf'))));
+ Replace(cmdstr,'$RES',maybequoted(ScriptFixFileName(outputexedir+Info.ResName)));
+ Replace(cmdstr,'$STATIC',StaticStr);
+ Replace(cmdstr,'$STRIP',StripStr);
+ Replace(cmdstr,'$GCSECTIONS',GCSectionsStr);
+ Replace(cmdstr,'$DYNLINK',DynLinkStr);
+ end;
+ success:=DoExec(FindUtil(utilsprefix+BinStr),cmdstr,true,false);
+
+{ Remove ReponseFile }
+ if success and not(cs_link_nolink in current_settings.globalswitches) then
+ DeleteFile(outputexedir+Info.ResName);
+
+{ Post process }
+ if success then
+ success:=PostProcessExecutable(current_module.exefilename^+'.elf',false);
+
+ if success and (target_info.system in [system_arm_embedded,system_avr_embedded]) then
+ begin
+ success:=DoExec(FindUtil(utilsprefix+'objcopy'),'-O ihex '+
+ ChangeFileExt(current_module.exefilename^,'.elf')+' '+
+ ChangeFileExt(current_module.exefilename^,'.hex'),true,false);
+ end;
+
+ MakeExecutable:=success; { otherwise a recursive call to link method }
+end;
+
+
+function TLinkerEmbedded.postprocessexecutable(const fn : string;isdll:boolean):boolean;
+ type
+ TElf32header=packed record
+ magic0123 : longint;
+ file_class : byte;
+ data_encoding : byte;
+ file_version : byte;
+ padding : array[$07..$0f] of byte;
+
+ e_type : word;
+ e_machine : word;
+ e_version : longint;
+ e_entry : longint; { entrypoint }
+ e_phoff : longint; { program header offset }
+
+ e_shoff : longint; { sections header offset }
+ e_flags : longint;
+ e_ehsize : word; { elf header size in bytes }
+ e_phentsize : word; { size of an entry in the program header array }
+ e_phnum : word; { 0..e_phnum-1 of entrys }
+ e_shentsize : word; { size of an entry in sections header array }
+ e_shnum : word; { 0..e_shnum-1 of entrys }
+ e_shstrndx : word; { index of string section header }
+ end;
+ TElf32sechdr=packed record
+ sh_name : longint;
+ sh_type : longint;
+ sh_flags : longint;
+ sh_addr : longint;
+
+ sh_offset : longint;
+ sh_size : longint;
+ sh_link : longint;
+ sh_info : longint;
+
+ sh_addralign : longint;
+ sh_entsize : longint;
+ end;
+
+ function MayBeSwapHeader(h : telf32header) : telf32header;
+ begin
+ result:=h;
+ if source_info.endian<>target_info.endian then
+ with h do
+ begin
+ result.e_type:=swapendian(e_type);
+ result.e_machine:=swapendian(e_machine);
+ result.e_version:=swapendian(e_version);
+ result.e_entry:=swapendian(e_entry);
+ result.e_phoff:=swapendian(e_phoff);
+ result.e_shoff:=swapendian(e_shoff);
+ result.e_flags:=swapendian(e_flags);
+ result.e_ehsize:=swapendian(e_ehsize);
+ result.e_phentsize:=swapendian(e_phentsize);
+ result.e_phnum:=swapendian(e_phnum);
+ result.e_shentsize:=swapendian(e_shentsize);
+ result.e_shnum:=swapendian(e_shnum);
+ result.e_shstrndx:=swapendian(e_shstrndx);
+ end;
+ end;
+
+ function MaybeSwapSecHeader(h : telf32sechdr) : telf32sechdr;
+ begin
+ result:=h;
+ if source_info.endian<>target_info.endian then
+ with h do
+ begin
+ result.sh_name:=swapendian(sh_name);
+ result.sh_type:=swapendian(sh_type);
+ result.sh_flags:=swapendian(sh_flags);
+ result.sh_addr:=swapendian(sh_addr);
+ result.sh_offset:=swapendian(sh_offset);
+ result.sh_size:=swapendian(sh_size);
+ result.sh_link:=swapendian(sh_link);
+ result.sh_info:=swapendian(sh_info);
+ result.sh_addralign:=swapendian(sh_addralign);
+ result.sh_entsize:=swapendian(sh_entsize);
+ end;
+ end;
+
+ var
+ f : file;
+
+ function ReadSectionName(pos : longint) : String;
+ var
+ oldpos : longint;
+ c : char;
+ begin
+ oldpos:=filepos(f);
+ seek(f,pos);
+ Result:='';
+ while true do
+ begin
+ blockread(f,c,1);
+ if c=#0 then
+ break;
+ Result:=Result+c;
+ end;
+ seek(f,oldpos);
+ end;
+
+ var
+ elfheader : TElf32header;
+ secheader : TElf32sechdr;
+ i : longint;
+ stringoffset : longint;
+ secname : string;
+ begin
+ postprocessexecutable:=false;
+ { open file }
+ assign(f,fn);
+ {$push}{$I-}
+ reset(f,1);
+ if ioresult<>0 then
+ Message1(execinfo_f_cant_open_executable,fn);
+ { read header }
+ blockread(f,elfheader,sizeof(tElf32header));
+ elfheader:=MayBeSwapHeader(elfheader);
+ seek(f,elfheader.e_shoff);
+ { read string section header }
+ seek(f,elfheader.e_shoff+sizeof(TElf32sechdr)*elfheader.e_shstrndx);
+ blockread(f,secheader,sizeof(secheader));
+ secheader:=MaybeSwapSecHeader(secheader);
+ stringoffset:=secheader.sh_offset;
+
+ seek(f,elfheader.e_shoff);
+ status.datasize:=0;
+ for i:=0 to elfheader.e_shnum-1 do
+ begin
+ blockread(f,secheader,sizeof(secheader));
+ secheader:=MaybeSwapSecHeader(secheader);
+ secname:=ReadSectionName(stringoffset+secheader.sh_name);
+ if secname='.text' then
+ begin
+ Message1(execinfo_x_codesize,tostr(secheader.sh_size));
+ status.codesize:=secheader.sh_size;
+ end
+ else if secname='.data' then
+ begin
+ Message1(execinfo_x_initdatasize,tostr(secheader.sh_size));
+ inc(status.datasize,secheader.sh_size);
+ end
+ else if secname='.bss' then
+ begin
+ Message1(execinfo_x_uninitdatasize,tostr(secheader.sh_size));
+ inc(status.datasize,secheader.sh_size);
+ end;
+
+ end;
+ close(f);
+ {$pop}
+ if ioresult<>0 then
+ ;
+ postprocessexecutable:=true;
+ end;
+
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+initialization
+{$ifdef arm}
+ RegisterExternalLinker(system_arm_embedded_info,TlinkerEmbedded);
+ RegisterTarget(system_arm_embedded_info);
+{$endif arm}
+
+{$ifdef avr}
+ RegisterExternalLinker(system_avr_embedded_info,TlinkerEmbedded);
+ RegisterTarget(system_avr_embedded_info);
+{$endif avr}
+
+{$ifdef i386}
+ RegisterExternalLinker(system_i386_embedded_info,TlinkerEmbedded);
+ RegisterTarget(system_i386_embedded_info);
+{$endif i386}
+end.
diff --git a/closures/compiler/systems/t_emx.pas b/closures/compiler/systems/t_emx.pas
new file mode 100644
index 0000000000..3ea0c134b9
--- /dev/null
+++ b/closures/compiler/systems/t_emx.pas
@@ -0,0 +1,531 @@
+{
+ Copyright (c) 1998-2002 by Daniel Mantione
+ Portions Copyright (c) 1998-2002 Eberhard Mattes
+
+ Unit to write out import libraries and def files for OS/2 via EMX
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+{
+ A lot of code in this unit has been ported from C to Pascal from the
+ emximp utility, part of the EMX development system. Emximp is copyrighted
+ by Eberhard Mattes. Note: Eberhard doesn't know much about the Pascal
+ port, please send questions to Tomas Hajny <hajny@freepascal.org> or
+ Daniel Mantione <daniel@freepascal.org>.
+}
+unit t_emx;
+
+{$i fpcdefs.inc}
+
+interface
+
+
+implementation
+
+ uses
+ sysutils,
+ cutils,cfileutl,cclasses,
+ globtype,comphook,systems,symconst,symsym,symdef,
+ globals,verbose,fmodule,script,ogbase,
+ comprsrc,import,link,i_emx,ppu;
+
+ type
+ TImportLibEMX=class(timportlib)
+
+ procedure generatelib;override;
+ end;
+
+ TLinkerEMX=class(texternallinker)
+ private
+ Function WriteResponseFile(isdll:boolean) : Boolean;
+ public
+ constructor Create;override;
+ procedure SetDefaultInfo;override;
+ function MakeExecutable:boolean;override;
+ end;
+
+
+const profile_flag:boolean=false;
+
+const n_ext = 1;
+ n_abs = 2;
+ n_text = 4;
+ n_data = 6;
+ n_bss = 8;
+ n_imp1 = $68;
+ n_imp2 = $6a;
+
+type reloc=packed record {This is the layout of a relocation table
+ entry.}
+ address:longint; {Fixup location}
+ remaining:longint;
+ {Meaning of bits for remaining:
+ 0..23: Symbol number or segment
+ 24: Self-relative fixup if non-zero
+ 25..26: Fixup size (0: 1 byte, 1: 2, 2: 4 bytes)
+ 27: Reference to symbol or segment
+ 28..31 Not used}
+ end;
+
+ nlist=packed record {This is the layout of a symbol table entry.}
+ strofs:longint; {Offset in string table}
+ typ:byte; {Type of the symbol}
+ other:byte; {Other information}
+ desc:word; {More information}
+ value:longint; {Value (address)}
+ end;
+
+ a_out_header=packed record
+ magic:word; {Magic word, must be $0107}
+ machtype:byte; {Machine type}
+ flags:byte; {Flags}
+ text_size:longint; {Length of text, in bytes}
+ data_size:longint; {Length of initialized data, in bytes}
+ bss_size:longint; {Length of uninitialized data, in bytes}
+ sym_size:longint; {Length of symbol table, in bytes}
+ entry:longint; {Start address (entry point)}
+ trsize:longint; {Length of relocation info for text, bytes}
+ drsize:longint; {Length of relocation info for data, bytes}
+ end;
+
+ ar_hdr=packed record
+ ar_name:array[0..15] of char;
+ ar_date:array[0..11] of char;
+ ar_uid:array[0..5] of char;
+ ar_gid:array[0..5] of char;
+ ar_mode:array[0..7] of char;
+ ar_size:array[0..9] of char;
+ ar_fmag:array[0..1] of char;
+ end;
+
+var aout_str_size:longint;
+ aout_str_tab:array[0..2047] of char;
+ aout_sym_count:longint;
+ aout_sym_tab:array[0..5] of nlist;
+
+ aout_text:array[0..63] of byte;
+ aout_text_size:longint;
+
+ aout_treloc_tab:array[0..1] of reloc;
+ aout_treloc_count:longint;
+
+ aout_size:longint;
+ seq_no:longint;
+
+ ar_member_size:longint;
+
+ out_file:file;
+
+
+procedure PackTime (var T: TSystemTime; var P: longint);
+
+var zs:longint;
+
+begin
+ p:=-1980;
+ p:=p+t.year and 127;
+ p:=p shl 4;
+ p:=p+t.month;
+ p:=p shl 5;
+ p:=p+t.day;
+ p:=p shl 16;
+ zs:=t.hour;
+ zs:=zs shl 6;
+ zs:=zs+t.minute;
+ zs:=zs shl 5;
+ zs:=zs+t.second div 2;
+ p:=p+(zs and $ffff);
+end;
+
+
+procedure write_ar(const name:string;size:longint);
+
+var ar:ar_hdr; {PackTime is platform independent}
+ time:TSystemTime;
+ numtime:longint;
+ tmp:string[19];
+begin
+ ar_member_size:=size;
+ fillchar(ar.ar_name,sizeof(ar.ar_name),' ');
+ move(name[1],ar.ar_name,length(name));
+ GetLocalTime(time);
+ packtime(time,numtime);
+ str(numtime,tmp);
+ fillchar(ar.ar_date,sizeof(ar.ar_date),' ');
+ move(tmp[1],ar.ar_date,length(tmp));
+ ar.ar_uid:='0 ';
+ ar.ar_gid:='0 ';
+ ar.ar_mode:='100666'#0#0;
+ str(size,tmp);
+ fillchar(ar.ar_size,sizeof(ar.ar_size),' ');
+ move(tmp[1],ar.ar_size,length(tmp));
+ ar.ar_fmag:='`'#10;
+ blockwrite(out_file,ar,sizeof(ar));
+end;
+
+procedure finish_ar;
+
+var a:byte;
+
+begin
+ a:=0;
+ if odd(ar_member_size) then
+ blockwrite(out_file,a,1);
+end;
+
+procedure aout_init;
+
+begin
+ aout_str_size:=sizeof(longint);
+ aout_sym_count:=0;
+ aout_text_size:=0;
+ aout_treloc_count:=0;
+end;
+
+function aout_sym(const name:string;typ,other:byte;desc:word;
+ value:longint):longint;
+
+begin
+ if aout_str_size+length(name)+1>sizeof(aout_str_tab) then
+ internalerror(200504241);
+ if aout_sym_count>=sizeof(aout_sym_tab) div sizeof(aout_sym_tab[0]) then
+ internalerror(200504242);
+ aout_sym_tab[aout_sym_count].strofs:=aout_str_size;
+ aout_sym_tab[aout_sym_count].typ:=typ;
+ aout_sym_tab[aout_sym_count].other:=other;
+ aout_sym_tab[aout_sym_count].desc:=desc;
+ aout_sym_tab[aout_sym_count].value:=value;
+ strPcopy(@aout_str_tab[aout_str_size],name);
+ aout_str_size:=aout_str_size+length(name)+1;
+ aout_sym:=aout_sym_count;
+ inc(aout_sym_count);
+end;
+
+procedure aout_text_byte(b:byte);
+
+begin
+ if aout_text_size>=sizeof(aout_text) then
+ internalerror(200504243);
+ aout_text[aout_text_size]:=b;
+ inc(aout_text_size);
+end;
+
+procedure aout_text_dword(d:longint);
+
+type li_ar=array[0..3] of byte;
+
+begin
+ aout_text_byte(li_ar(d)[0]);
+ aout_text_byte(li_ar(d)[1]);
+ aout_text_byte(li_ar(d)[2]);
+ aout_text_byte(li_ar(d)[3]);
+end;
+
+procedure aout_treloc(address,symbolnum,pcrel,len,ext:longint);
+
+begin
+ if aout_treloc_count>=sizeof(aout_treloc_tab) div sizeof(reloc) then
+ internalerror(200504244);
+ aout_treloc_tab[aout_treloc_count].address:=address;
+ aout_treloc_tab[aout_treloc_count].remaining:=symbolnum+pcrel shl 24+
+ len shl 25+ext shl 27;
+ inc(aout_treloc_count);
+end;
+
+procedure aout_finish;
+
+begin
+ while (aout_text_size and 3)<>0 do
+ aout_text_byte ($90);
+ aout_size:=sizeof(a_out_header)+aout_text_size+aout_treloc_count*
+ sizeof(reloc)+aout_sym_count*sizeof(aout_sym_tab[0])+aout_str_size;
+end;
+
+procedure aout_write;
+
+var ao:a_out_header;
+
+begin
+ ao.magic:=$0107;
+ ao.machtype:=0;
+ ao.flags:=0;
+ ao.text_size:=aout_text_size;
+ ao.data_size:=0;
+ ao.bss_size:=0;
+ ao.sym_size:=aout_sym_count*sizeof(aout_sym_tab[0]);
+ ao.entry:=0;
+ ao.trsize:=aout_treloc_count*sizeof(reloc);
+ ao.drsize:=0;
+ blockwrite(out_file,ao,sizeof(ao));
+ blockwrite(out_file,aout_text,aout_text_size);
+ blockwrite(out_file,aout_treloc_tab,sizeof(reloc)*aout_treloc_count);
+ blockwrite(out_file,aout_sym_tab,sizeof(aout_sym_tab[0])*aout_sym_count);
+ plongint(@aout_str_tab)^:=aout_str_size;
+ blockwrite(out_file,aout_str_tab,aout_str_size);
+end;
+
+
+procedure AddImport(const module:string;index:longint;const name,mangledname:string);
+{func = Name of function to import.
+ module = Name of DLL to import from.
+ index = Index of function in DLL. Use 0 to import by name.
+ name = Name of function in DLL. Ignored when index=0;}
+var tmp1,tmp2,tmp3:string;
+ sym_mcount,sym_import:longint;
+ fixup_mcount,fixup_import:longint;
+ func : string;
+begin
+ aout_init;
+ func:=mangledname;
+ tmp2:=func;
+ if profile_flag and not (copy(func,1,4)='_16_') then
+ begin
+ {sym_entry:=aout_sym(func,n_text+n_ext,0,0,aout_text_size);}
+ sym_mcount:=aout_sym('__mcount',n_ext,0,0,0);
+ {Use, say, "_$U_DosRead" for "DosRead" to import the
+ non-profiled function.}
+ tmp2:='__$U_'+func;
+ sym_import:=aout_sym(tmp2,n_ext,0,0,0);
+ aout_text_byte($55); {push ebp}
+ aout_text_byte($89); {mov ebp, esp}
+ aout_text_byte($e5);
+ aout_text_byte($e8); {call _mcount}
+ fixup_mcount:=aout_text_size;
+ aout_text_dword(0-(aout_text_size+4));
+ aout_text_byte($5d); {pop ebp}
+ aout_text_byte($e9); {jmp _$U_DosRead}
+ fixup_import:=aout_text_size;
+ aout_text_dword(0-(aout_text_size+4));
+
+ aout_treloc(fixup_mcount,sym_mcount,1,2,1);
+ aout_treloc (fixup_import, sym_import,1,2,1);
+ end;
+ str(seq_no,tmp1);
+ tmp1:='IMPORT#'+tmp1;
+ if name='' then
+ begin
+ str(index,tmp3);
+ tmp3:=func+'='+module+'.'+tmp3;
+ end
+ else
+ tmp3:=func+'='+module+'.'+name;
+ aout_sym(tmp2,n_imp1+n_ext,0,0,0);
+ aout_sym(tmp3,n_imp2+n_ext,0,0,0);
+ aout_finish;
+ write_ar(tmp1,aout_size);
+ aout_write;
+ finish_ar;
+ inc(seq_no);
+end;
+
+ procedure TImportLibEMX.GenerateLib;
+ const
+ ar_magic:array[1..8] of char='!<arch>'#10;
+ var
+ libname : string;
+ i,j : longint;
+ ImportLibrary : TImportLibrary;
+ ImportSymbol : TImportSymbol;
+ begin
+ for i:=0 to current_module.ImportLibraryList.Count-1 do
+ begin
+ ImportLibrary:=TImportLibrary(current_module.ImportLibraryList[i]);
+ LibName:=FixFileName(ImportLibrary.Name + Target_Info.StaticCLibExt);
+ seq_no:=1;
+ current_module.linkotherstaticlibs.add(libname,link_always);
+ assign(out_file,current_module.outputpath^+libname);
+ rewrite(out_file,1);
+ blockwrite(out_file,ar_magic,sizeof(ar_magic));
+ for j:=0 to ImportLibrary.ImportSymbolList.Count-1 do
+ begin
+ ImportSymbol:=TImportSymbol(ImportLibrary.ImportSymbolList[j]);
+ AddImport(ImportLibrary.Name,ImportSymbol.OrdNr,
+ ImportSymbol.Name,ImportSymbol.MangledName);
+ end;
+ close(out_file);
+ end;
+ end;
+
+
+{****************************************************************************
+ TLinkerEMX
+****************************************************************************}
+
+Constructor TLinkerEMX.Create;
+begin
+ Inherited Create;
+ { allow duplicated libs (PM) }
+ SharedLibFiles.doubles:=true;
+ StaticLibFiles.doubles:=true;
+end;
+
+
+procedure TLinkerEMX.SetDefaultInfo;
+begin
+ with Info do
+ begin
+ ExeCmd[1]:='ld $OPT -o $OUT @$RES';
+ ExeCmd[2]:='emxbind -b $STRIP $APPTYPE $RSRC -k$STACKKB -h$HEAPMB -o $EXE $OUT -aim -s$DOSHEAPKB';
+ if source_info.script = script_dos then
+ ExeCmd[3]:='del $OUT';
+ end;
+end;
+
+
+Function TLinkerEMX.WriteResponseFile(isdll:boolean) : Boolean;
+Var
+ linkres : TLinkRes;
+ i : longint;
+ HPath : TCmdStrListItem;
+ s : string;
+begin
+ WriteResponseFile:=False;
+
+ { Open link.res file }
+ LinkRes:=TLinkRes.Create(outputexedir+Info.ResName);
+
+ { Write path to search libraries }
+ HPath:=TCmdStrListItem(current_module.locallibrarysearchpath.First);
+ while assigned(HPath) do
+ begin
+ LinkRes.Add('-L'+HPath.Str);
+ HPath:=TCmdStrListItem(HPath.Next);
+ end;
+ HPath:=TCmdStrListItem(LibrarySearchPath.First);
+ while assigned(HPath) do
+ begin
+ LinkRes.Add('-L'+HPath.Str);
+ HPath:=TCmdStrListItem(HPath.Next);
+ end;
+
+ { add objectfiles, start with prt0 always }
+ LinkRes.AddFileName(FindObjectFile('prt0','',false));
+ while not ObjectFiles.Empty do
+ begin
+ s:=ObjectFiles.GetFirst;
+ if s<>'' then
+ LinkRes.AddFileName(s);
+ end;
+
+ { Write staticlibraries }
+ { No group !! This will not work correctly PM }
+ While not StaticLibFiles.Empty do
+ begin
+ S:=StaticLibFiles.GetFirst;
+ LinkRes.AddFileName(s)
+ end;
+
+ { Write sharedlibraries like -l<lib>, also add the needed dynamic linker
+ here to be sure that it gets linked this is needed for glibc2 systems (PFV) }
+ While not SharedLibFiles.Empty do
+ begin
+ S:=SharedLibFiles.GetFirst;
+ i:=Pos(target_info.sharedlibext,S);
+ if i>0 then
+ Delete(S,i,255);
+ LinkRes.Add('-l'+s);
+ end;
+
+{ Write and Close response }
+ linkres.writetodisk;
+ LinkRes.Free;
+
+ WriteResponseFile:=True;
+end;
+
+
+function TLinkerEMX.MakeExecutable:boolean;
+var
+ binstr,
+ cmdstr : TCmdStr;
+ success : boolean;
+ i : longint;
+ AppTypeStr,
+ StripStr: string[40];
+ RsrcStr : string;
+ OutName: string;
+begin
+ if not(cs_link_nolink in current_settings.globalswitches) then
+ Message1(exec_i_linking,current_module.exefilename^);
+
+{ Create some replacements }
+ OutName := ChangeFileExt(current_module.exefilename^,'.out');
+ if (cs_link_strip in current_settings.globalswitches) then
+ StripStr := '-s'
+ else
+ StripStr := '';
+ if (usewindowapi) or (AppType = app_gui) then
+ AppTypeStr := '-p'
+ else if AppType = app_fs then
+ AppTypeStr := '-f'
+ else AppTypeStr := '-w';
+ if not (Current_module.ResourceFiles.Empty) then
+ RsrcStr := '-r ' + Current_module.ResourceFiles.GetFirst
+ else
+ RsrcStr := '';
+(* Only one resource file supported, discard everything else
+ (should be already empty anyway, though). *)
+ Current_module.ResourceFiles.Clear;
+{ Write used files and libraries }
+ WriteResponseFile(false);
+
+{ Call linker }
+ success:=false;
+ for i:=1 to 3 do
+ begin
+ SplitBinCmd(Info.ExeCmd[i],binstr,cmdstr);
+ if binstr<>'' then
+ begin
+ { Is this really required? Not anymore according to my EMX docs }
+ Replace(cmdstr,'$HEAPMB',tostr((1048575) shr 20));
+ {Size of the stack when an EMX program runs in OS/2.}
+ Replace(cmdstr,'$STACKKB',tostr((stacksize+1023) shr 10));
+ {When an EMX program runs in DOS, the heap and stack share the
+ same memory pool. The heap grows upwards, the stack grows downwards.}
+ Replace(cmdstr,'$DOSHEAPKB',tostr((stacksize+1023) shr 10));
+ Replace(cmdstr,'$STRIP',StripStr);
+ Replace(cmdstr,'$APPTYPE',AppTypeStr);
+ Replace(cmdstr,'$RES',maybequoted(outputexedir+Info.ResName));
+ Replace(cmdstr,'$OPT',Info.ExtraOptions);
+ Replace(cmdstr,'$RSRC',RsrcStr);
+ Replace(cmdstr,'$OUT',maybequoted(OutName));
+ Replace(cmdstr,'$EXE',maybequoted(current_module.exefilename^));
+ if i<>3 then
+ success:=DoExec(FindUtil(utilsprefix+binstr),cmdstr,(i=1),false)
+ else
+ success:=DoExec(binstr,cmdstr,(i=1),true);
+ end;
+ end;
+
+{ Remove ReponseFile }
+ if (success) and not(cs_link_nolink in current_settings.globalswitches) then
+ DeleteFile(outputexedir+Info.ResName);
+
+ MakeExecutable:=success; { otherwise a recursive call to link method }
+end;
+
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+initialization
+ RegisterExternalLinker(system_i386_emx_info,TLinkerEMX);
+ RegisterImport(system_i386_emx,TImportLibEMX);
+ RegisterRes(res_wrc_os2_info,TResourceFile);
+ RegisterTarget(system_i386_emx_info);
+end.
diff --git a/closures/compiler/systems/t_gba.pas b/closures/compiler/systems/t_gba.pas
new file mode 100644
index 0000000000..390a8ecab4
--- /dev/null
+++ b/closures/compiler/systems/t_gba.pas
@@ -0,0 +1,632 @@
+{
+ This unit implements support import,export,link routines
+ for the (arm) GameBoy Advance target
+
+ Copyright (c) 2001-2002 by Peter Vreman
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit t_gba;
+
+{$i fpcdefs.inc}
+
+interface
+
+
+implementation
+
+ uses
+ aasmbase,
+ SysUtils,
+ cutils,cfileutl,cclasses,
+ globtype,globals,systems,verbose,script,fmodule,i_gba,link;
+
+ type
+ TlinkerGBA=class(texternallinker)
+ private
+ Function WriteResponseFile: Boolean;
+ public
+ constructor Create; override;
+ procedure SetDefaultInfo; override;
+ function MakeExecutable:boolean; override;
+ end;
+
+
+
+{*****************************************************************************
+ TLINKERGBA
+*****************************************************************************}
+
+Constructor TLinkerGba.Create;
+begin
+ Inherited Create;
+ SharedLibFiles.doubles:=true;
+ StaticLibFiles.doubles:=true;
+end;
+
+
+procedure TLinkerGba.SetDefaultInfo;
+begin
+ with Info do
+ begin
+ ExeCmd[1]:='ld -g $OPT $DYNLINK $STATIC $GCSECTIONS $STRIP -L. -o $EXE -T $RES';
+ end;
+end;
+
+
+Function TLinkerGba.WriteResponseFile: Boolean;
+Var
+ linkres : TLinkRes;
+ i : longint;
+ HPath : TCmdStrListItem;
+ s,s1,s2 : TCmdStr;
+ prtobj,
+ cprtobj : string[80];
+ linklibc,
+ linklibgcc : boolean;
+ found1,
+ found2 : boolean;
+begin
+ WriteResponseFile:=False;
+ linklibc:=(SharedLibFiles.Find('c')<>nil);
+ linklibgcc:=(SharedLibFiles.Find('gcc')<>nil);
+ prtobj:='prt0';
+ cprtobj:='cprt0';
+ if (linklibc or linklibgcc) then
+ prtobj:=cprtobj;
+
+ { Open link.res file }
+ LinkRes:=TLinkRes.Create(outputexedir+Info.ResName);
+
+ { Write path to search libraries }
+ HPath:=TCmdStrListItem(current_module.locallibrarysearchpath.First);
+ while assigned(HPath) do
+ begin
+ s:=HPath.Str;
+ if (cs_link_on_target in current_settings.globalswitches) then
+ s:=ScriptFixFileName(s);
+ LinkRes.Add('-L'+s);
+ HPath:=TCmdStrListItem(HPath.Next);
+ end;
+ HPath:=TCmdStrListItem(LibrarySearchPath.First);
+ while assigned(HPath) do
+ begin
+ s:=HPath.Str;
+ if s<>'' then
+ LinkRes.Add('SEARCH_DIR('+(maybequoted(s))+')');
+ HPath:=TCmdStrListItem(HPath.Next);
+ end;
+
+ LinkRes.Add('INPUT (');
+ { add objectfiles, start with prt0 always }
+ //s:=FindObjectFile('prt0','',false);
+ if prtobj<>'' then
+ s:=FindObjectFile(prtobj,'',false);
+ LinkRes.AddFileName(s);
+ { try to add crti and crtbegin if linking to C }
+ if linklibc then
+ begin
+ if librarysearchpath.FindFile('crti.o',false,s) then
+ LinkRes.AddFileName(s);
+ end;
+ if linklibgcc then
+ begin
+ if librarysearchpath.FindFile('crtbegin.o',false,s) then
+ LinkRes.AddFileName(s);
+ end;
+
+
+ while not ObjectFiles.Empty do
+ begin
+ s:=ObjectFiles.GetFirst;
+ if s<>'' then
+ begin
+ { vlink doesn't use SEARCH_DIR for object files }
+ if not(cs_link_on_target in current_settings.globalswitches) then
+ s:=FindObjectFile(s,'',false);
+ LinkRes.AddFileName((maybequoted(s)));
+ end;
+ end;
+
+ { Write staticlibraries }
+ if not StaticLibFiles.Empty then
+ begin
+ { vlink doesn't need, and doesn't support GROUP }
+ if (cs_link_on_target in current_settings.globalswitches) then
+ begin
+ LinkRes.Add(')');
+ LinkRes.Add('GROUP(');
+ end;
+ while not StaticLibFiles.Empty do
+ begin
+ S:=StaticLibFiles.GetFirst;
+ LinkRes.AddFileName((maybequoted(s)));
+ end;
+ end;
+
+ if (cs_link_on_target in current_settings.globalswitches) then
+ begin
+ LinkRes.Add(')');
+
+ { Write sharedlibraries like -l<lib>, also add the needed dynamic linker
+ here to be sure that it gets linked this is needed for glibc2 systems (PFV) }
+ linklibc:=false;
+ linklibgcc:=false;
+ while not SharedLibFiles.Empty do
+ begin
+ S:=SharedLibFiles.GetFirst;
+ if s<>'c' then
+ begin
+ i:=Pos(target_info.sharedlibext,S);
+ if i>0 then
+ Delete(S,i,255);
+ LinkRes.Add('-l'+s);
+ end
+ else
+ begin
+ LinkRes.Add('-l'+s);
+ linklibc:=true;
+ linklibgcc:=true;
+ end;
+ end;
+ { be sure that libc&libgcc is the last lib }
+ if linklibgcc then
+ begin
+ LinkRes.Add('-lgcc');
+ end;
+ if linklibc then
+ begin
+ LinkRes.Add('-lc');
+ end;
+
+ end
+ else
+ begin
+ while not SharedLibFiles.Empty do
+ begin
+ S:=SharedLibFiles.GetFirst;
+ LinkRes.Add('lib'+s+target_info.staticlibext);
+ end;
+ LinkRes.Add(')');
+ end;
+
+ { objects which must be at the end }
+ if linklibgcc then
+ begin
+ found1:=librarysearchpath.FindFile('crtend.o',false,s1);
+ if found1 then
+ begin
+ LinkRes.Add('INPUT(');
+ if found1 then
+ LinkRes.AddFileName(s1);
+ LinkRes.Add(')');
+ end;
+ end;
+ if linklibc then
+ begin
+ found2:=librarysearchpath.FindFile('crtn.o',false,s2);
+ if found2 then
+ begin
+ LinkRes.Add('INPUT(');
+ if found2 then
+ LinkRes.AddFileName(s2);
+ LinkRes.Add(')');
+ end;
+ end;
+
+ with linkres do
+ begin
+ add('/* Linker Script Original v1.3 by Jeff Frohwein */');
+ add('/* v1.0 - Original release */');
+ add('/* v1.1 - Added proper .data section support */');
+ add('/* v1.2 - Added support for c++ & iwram overlays */');
+ add('/* - Major contributions by Jason Wilkins. */');
+ add('/* v1.3 - .ewram section now can be used when */');
+ add('/* compiling for MULTIBOOT mode. This fixes */');
+ add('/* malloc() in DevKitAdvance which depends */');
+ add('/* on __eheap_start instead of end to define*/');
+ add('/* the starting location of heap space. */');
+ add('/* External global variable __gba_iwram_heap*/');
+ add('/* support added to allow labels end, _end, */');
+ add('/* & __end__ to point to end of iwram or */');
+ add('/* the end of ewram. */');
+ add('/* Additions by WinterMute */');
+ add('/* v1.4 - .sbss section added for unitialised */');
+ add('/* data in ewram */');
+ add('/* v1.5 - padding section added to stop EZF */');
+ add('/* stripping important data */');
+ add('');
+ add('/* This file is released into the public domain */');
+ add('/* for commercial or non-commercial use with no */');
+ add('/* restrictions placed upon it. */');
+ add('');
+ add('/* NOTE!!!: This linker script defines the RAM & */');
+ add('/* ROM start addresses. In order for it to work */');
+ add('/* properly, remove -Ttext and -Tbss linker */');
+ add('/* options from your makefile if they are */');
+ add('/* present. */');
+ add('');
+ add('/* You can use the following to view section */');
+ add('/* addresses in your .elf file: */');
+ add('/* objdump -h file.elf */');
+ add('/* Please note that empty sections may incorrectly*/');
+ add('/* list the lma address as the vma address for */');
+ add('/* some versions of objdump. */');
+ add('');
+ add('OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")');
+ add('OUTPUT_ARCH(arm)');
+ add('ENTRY(_start)');
+ add('/* SEARCH_DIR(/bin/arm); */');
+ add('');
+ add('/* The linker script function "var1 += var2;" sometimes */');
+ add('/* reports incorrect values in the *.map file but the */');
+ add('/* actual value it calculates is usually, if not always, */');
+ add('/* correct. If you leave out the ". = ALIGN(4);" at the */');
+ add('/* end of each section then the return value of SIZEOF() */');
+ add('/* is sometimes incorrect and "var1 += var2;" appears to */');
+ add('/* not work as well. "var1 += var2" style functions are */');
+ add('/* avoided below as a result. */');
+ add('');
+ add('MEMORY {');
+ add('');
+ add(' rom : ORIGIN = 0x08000000, LENGTH = 32M');
+ add(' iwram : ORIGIN = 0x03000000, LENGTH = 32K');
+ add(' ewram : ORIGIN = 0x02000000, LENGTH = 256K');
+ add('}');
+ add('');
+ add('__text_start = ORIGIN(rom);');
+ add('__eheap_end = ORIGIN(ewram) + LENGTH(ewram);');
+ add('__iwram_start = ORIGIN(iwram);');
+ add('__iwram_top = ORIGIN(iwram) + LENGTH(iwram);;');
+ add('__sp_irq = __iwram_top - 0x060;');
+ add('__sp_usr = __sp_irq - 0x0a0;');
+ add('__irq_flags = 0x03007ff8;');
+ add('');
+ add('SECTIONS');
+ add('{');
+ add(' . = __text_start;');
+ add(' .init :');
+ add(' {');
+ add(' KEEP (*(.init))');
+ add(' . = ALIGN(4);');
+ add(' } >rom =0xff');
+ add('');
+ add(' .plt :');
+ add(' {');
+ add(' *(.plt)');
+ add(' . = ALIGN(4); /* REQUIRED. LD is flaky without it. */');
+ add(' } >rom');
+ add('');
+ add(' .text : /* ALIGN (4): */');
+ add(' {');
+ add(' *(EXCLUDE_FILE (*.iwram*) .text)');
+ add(' *(.text .stub .text.* .gnu.linkonce.t.*)');
+ add(' KEEP (*(.text.*personality*))');
+ add(' /* .gnu.warning sections are handled specially by elf32.em. */');
+ add(' *(.gnu.warning)');
+ add(' *(.glue_7t) *(.glue_7) *(.vfp11_veneer)');
+ add(' . = ALIGN(4); /* REQUIRED. LD is flaky without it. */');
+ add(' } >rom = 0xff');
+ add('');
+ add(' __text_end = .;');
+ add(' .fini :');
+ add(' {');
+ add(' KEEP (*(.fini))');
+ add(' . = ALIGN(4); /* REQUIRED. LD is flaky without it. */');
+ add(' } >rom =0');
+ add('');
+ add(' .rodata :');
+ add(' {');
+ add(' *(.rodata)');
+ add(' *all.rodata*(*)');
+ add(' *(.roda)');
+ add(' *(.rodata.*)');
+ add(' *(.gnu.linkonce.r*)');
+ add(' SORT(CONSTRUCTORS)');
+ add(' . = ALIGN(4); /* REQUIRED. LD is flaky without it. */');
+ add(' } >rom = 0xff');
+ add(' .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >rom');
+ add(' __exidx_start = .;');
+ add(' .ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) } >rom');
+ add(' __exidx_end = .;');
+ add('');
+ add(' .ctors :');
+ add(' {');
+ add(' /* gcc uses crtbegin.o to find the start of the constructors, so');
+ add(' we make sure it is first. Because this is a wildcard, it');
+ add(' doesn''t matter if the user does not actually link against');
+ add(' crtbegin.o; the linker won''t look for a file to match a');
+ add(' wildcard. The wildcard also means that it doesn''t matter which');
+ add(' directory crtbegin.o is in. */');
+ add(' KEEP (*crtbegin.o(.ctors))');
+ add(' KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))');
+ add(' KEEP (*(SORT(.ctors.*)))');
+ add(' KEEP (*(.ctors))');
+ add(' . = ALIGN(4); /* REQUIRED. LD is flaky without it. */');
+ add(' } >rom = 0');
+ add('');
+ add(' .dtors :');
+ add(' {');
+ add(' KEEP (*crtbegin.o(.dtors))');
+ add(' KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))');
+ add(' KEEP (*(SORT(.dtors.*)))');
+ add(' KEEP (*(.dtors))');
+ add(' . = ALIGN(4); /* REQUIRED. LD is flaky without it. */');
+ add(' } >rom = 0');
+ add('');
+ add('');
+ add(' .eh_frame :');
+ add(' {');
+ add(' KEEP (*(.eh_frame))');
+ add(' . = ALIGN(4); /* REQUIRED. LD is flaky without it. */');
+ add(' } >rom = 0');
+ add('');
+ add(' .gcc_except_table :');
+ add(' {');
+ add(' *(.gcc_except_table)');
+ add(' . = ALIGN(4); /* REQUIRED. LD is flaky without it. */');
+ add(' } >rom = 0');
+ add('');
+ add(' __iwram_lma = .;');
+ add('');
+ add(' .iwram __iwram_start : AT (__iwram_lma)');
+ add(' {');
+ add(' __iwram_start = ABSOLUTE(.) ;');
+ add(' *(.iwram)');
+ add(' *iwram.*(.text)');
+ add(' . = ALIGN(4); /* REQUIRED. LD is flaky without it. */');
+ add(' __iwram_end = ABSOLUTE(.) ;');
+ add(' } >iwram = 0xff');
+ add('');
+ add(' __data_lma = __iwram_lma + SIZEOF(.iwram) ;');
+ add('');
+ add(' .bss ALIGN(4) (NOLOAD) :');
+ add(' {');
+ add(' __bss_start = ABSOLUTE(.);');
+ add(' __bss_start__ = ABSOLUTE(.);');
+ add(' *(.dynbss)');
+ add(' *(.gnu.linkonce.b*)');
+ add(' *(.bss*)');
+ add(' *(COMMON)');
+ add(' . = ALIGN(4); /* REQUIRED. LD is flaky without it. */');
+ add(' __bss_end = ABSOLUTE(.) ;');
+ add('');
+ add(' } AT>iwram');
+ add('');
+ add(' __bss_end__ = __bss_end ;');
+ add('');
+ add(' .data ALIGN(4) : AT (__data_lma)');
+ add(' {');
+ add(' __data_start = ABSOLUTE(.);');
+ add(' *(.data)');
+ add(' *(.data.*)');
+ add(' *(.gnu.linkonce.d*)');
+ add(' *(.fpc*)');
+ add(' CONSTRUCTORS');
+ add(' . = ALIGN(4);');
+ add(' } >iwram = 0xff');
+ add('');
+ add(' __preinit_lma = __data_lma + SIZEOF(.data);');
+ add('');
+ add(' PROVIDE (__preinit_array_start = .);');
+ add(' .preinit_array : AT (__preinit_lma) { KEEP (*(.preinit_array)) } >iwram');
+ add(' PROVIDE (__preinit_array_end = .);');
+ add('');
+ add(' __init_lma = __preinit_lma + SIZEOF(.preinit_array);');
+ add('');
+ add(' PROVIDE (__init_array_start = .);');
+ add(' .init_array : AT (__init_lma)');
+ add(' {');
+ add(' KEEP (*(SORT(.init_array.*)))');
+ add(' KEEP (*(.init_array))');
+ add(' } >iwram');
+ add(' PROVIDE (__init_array_end = .);');
+ add(' PROVIDE (__fini_array_start = .);');
+ add('');
+ add(' __fini_lma = __init_lma + SIZEOF(.init_array);');
+ add('');
+ add(' .fini_array : AT (__fini_lma)');
+ add(' {');
+ add(' KEEP (*(SORT(.fini_array.*)))');
+ add(' KEEP (*(.fini_array))');
+ add(' } >iwram');
+ add(' PROVIDE (__fini_array_end = .);');
+ add('');
+ add(' __jcr_lma = __fini_lma + SIZEOF(.fini_array);');
+ add(' .jcr : AT (__jcr_lma) { KEEP (*(.jcr)) } >iwram');
+ add('');
+ add(' __data_end = ABSOLUTE(.);');
+ add(' __iwram_overlay_lma = __jcr_lma + SIZEOF(.jcr);');
+ add('');
+ add(' __iwram_overlay_start = . ;');
+ add('');
+ add(' OVERLAY ALIGN(4) : NOCROSSREFS AT (__iwram_overlay_lma)');
+ add(' {');
+ add(' .iwram0 { *(.iwram0) . = ALIGN(4);}');
+ add(' .iwram1 { *(.iwram1) . = ALIGN(4);}');
+ add(' .iwram2 { *(.iwram2) . = ALIGN(4);}');
+ add(' .iwram3 { *(.iwram3) . = ALIGN(4);}');
+ add(' .iwram4 { *(.iwram4) . = ALIGN(4);}');
+ add(' .iwram5 { *(.iwram5) . = ALIGN(4);}');
+ add(' .iwram6 { *(.iwram6) . = ALIGN(4);}');
+ add(' .iwram7 { *(.iwram7) . = ALIGN(4);}');
+ add(' .iwram8 { *(.iwram8) . = ALIGN(4);}');
+ add(' .iwram9 { *(.iwram9) . = ALIGN(4);}');
+ add(' }>iwram = 0xff');
+ add('');
+ add(' __iwram_overlay_end = . ;');
+ add(' __ewram_lma = __iwram_overlay_lma + (__iwram_overlay_end - __iwram_overlay_start) ;');
+ add('');
+ add(' __iheap_start = . ;');
+ add('');
+ add(' __ewram_start = ORIGIN(ewram);');
+ add(' .ewram __ewram_start : AT (__ewram_lma)');
+ add(' {');
+ add(' *(.ewram)');
+ add(' . = ALIGN(4); /* REQUIRED. LD is flaky without it. */');
+ add(' }>ewram = 0xff');
+ add('');
+ add(' __pad_lma = __ewram_lma + SIZEOF(.ewram);');
+ add('');
+ add(' .sbss ALIGN(4)(NOLOAD):');
+ add(' {');
+ add(' __sbss_start = ABSOLUTE(.);');
+ add(' *(.sbss)');
+ add(' . = ALIGN(4);');
+ add(' __sbss_end = ABSOLUTE(.);');
+ add(' } AT>ewram');
+ add('');
+ add('');
+ add(' __ewram_end = __sbss_end ;');
+ add(' __eheap_start = __sbss_end;');
+ add(' __end__ = __sbss_end;');
+ add('');
+ add(' /* EZF Advance strips trailing 0xff bytes, add a pad section so nothing important is removed */');
+ add(' .pad ALIGN(4) : AT (__pad_lma)');
+ add(' {');
+ add(' LONG(0x52416b64)');
+ add(' LONG(0x4d)');
+ add(' . = ALIGN(4); /* REQUIRED. LD is flaky without it. */');
+ add(' } = 0xff');
+ add(' __rom_end__ = __pad_lma + SIZEOF(.pad);');
+ add('');
+ add('');
+ add(' /* Stabs debugging sections. */');
+ add(' .stab 0 : { *(.stab) }');
+ add(' .stabstr 0 : { *(.stabstr) }');
+ add(' .stab.excl 0 : { *(.stab.excl) }');
+ add(' .stab.exclstr 0 : { *(.stab.exclstr) }');
+ add(' .stab.index 0 : { *(.stab.index) }');
+ add(' .stab.indexstr 0 : { *(.stab.indexstr) }');
+ add(' .comment 0 : { *(.comment) }');
+ add(' /* DWARF debug sections.');
+ add(' Symbols in the DWARF debugging sections are relative to the beginning');
+ add(' of the section so we begin them at 0. */');
+ add(' /* DWARF 1 */');
+ add(' .debug 0 : { *(.debug) }');
+ add(' .line 0 : { *(.line) }');
+ add(' /* GNU DWARF 1 extensions */');
+ add(' .debug_srcinfo 0 : { *(.debug_srcinfo) }');
+ add(' .debug_sfnames 0 : { *(.debug_sfnames) }');
+ add(' /* DWARF 1.1 and DWARF 2 */');
+ add(' .debug_aranges 0 : { *(.debug_aranges) }');
+ add(' .debug_pubnames 0 : { *(.debug_pubnames) }');
+ add(' /* DWARF 2 */');
+ add(' .debug_info 0 : { *(.debug_info) }');
+ add(' .debug_abbrev 0 : { *(.debug_abbrev) }');
+ add(' .debug_line 0 : { *(.debug_line) }');
+ add(' .debug_frame 0 : { *(.debug_frame) }');
+ add(' .debug_str 0 : { *(.debug_str) }');
+ add(' .debug_loc 0 : { *(.debug_loc) }');
+ add(' .debug_macinfo 0 : { *(.debug_macinfo) }');
+ add(' /* SGI/MIPS DWARF 2 extensions */');
+ add(' .debug_weaknames 0 : { *(.debug_weaknames) }');
+ add(' .debug_funcnames 0 : { *(.debug_funcnames) }');
+ add(' .debug_typenames 0 : { *(.debug_typenames) }');
+ add(' .debug_varnames 0 : { *(.debug_varnames) }');
+ add(' .stack 0x80000 : { _stack = .; *(.stack) }');
+ add(' /* These must appear regardless of . */');
+ add(' .note.gnu.arm.ident 0 : { KEEP (*(.note.gnu.arm.ident)) }');
+ add(' .ARM.attributes 0 : { KEEP (*(.ARM.attributes)) }');
+ add(' /DISCARD/ : { *(.note.GNU-stack) }');
+ add('}');
+ end;
+
+{ Write and Close response }
+ linkres.writetodisk;
+ linkres.free;
+
+ WriteResponseFile:=True;
+
+end;
+
+
+function TLinkerGba.MakeExecutable:boolean;
+var
+ binstr,
+ cmdstr : TCmdStr;
+ success : boolean;
+ StaticStr,
+ GCSectionsStr,
+ DynLinkStr,
+ MapStr,
+ StripStr: string;
+begin
+ { for future use }
+ StaticStr:='';
+ StripStr:='';
+ DynLinkStr:='';
+ MapStr:='';
+
+ if (cs_link_strip in current_settings.globalswitches) and
+ not(cs_link_separate_dbg_file in current_settings.globalswitches) then
+ StripStr:='-s';
+ if (cs_link_map in current_settings.globalswitches) then
+ StripStr:='-Map '+maybequoted(ChangeFileExt(current_module.exefilename^,'.map'));
+ if create_smartlink_sections then
+ GCSectionsStr:='--gc-sections';
+ //if not(cs_link_extern in current_settings.globalswitches) then
+ if not(cs_link_nolink in current_settings.globalswitches) then
+ Message1(exec_i_linking,current_module.exefilename^);
+
+{ Write used files and libraries }
+ WriteResponseFile();
+
+{ Call linker }
+ SplitBinCmd(Info.ExeCmd[1],binstr,cmdstr);
+ Replace(cmdstr,'$OPT',Info.ExtraOptions);
+
+ Replace(cmdstr,'$EXE',(maybequoted(ScriptFixFileName(ChangeFileExt(current_module.exefilename^,'.elf')))));
+ Replace(cmdstr,'$RES',(maybequoted(ScriptFixFileName(outputexedir+Info.ResName))));
+ Replace(cmdstr,'$STATIC',StaticStr);
+ Replace(cmdstr,'$STRIP',StripStr);
+ Replace(cmdstr,'$GCSECTIONS',GCSectionsStr);
+ Replace(cmdstr,'$MAP',MapStr);
+ Replace(cmdstr,'$DYNLINK',DynLinkStr);
+
+ success:=DoExec(FindUtil(utilsprefix+BinStr),cmdstr,true,false);
+
+{ Remove ReponseFile }
+ if (success) and not(cs_link_nolink in current_settings.globalswitches) then
+ DeleteFile(outputexedir+Info.ResName);
+
+{ Post process }
+ if success then
+ begin
+ success:=DoExec(FindUtil(utilsprefix+'objcopy'),'-O binary '+
+ ChangeFileExt(current_module.exefilename^,'.elf')+' '+
+ current_module.exefilename^,true,false);
+ end;
+
+ if success then
+ begin
+ success:=DoExec(FindUtil('gbafix'), current_module.exefilename^,true,false);
+ end;
+
+
+ MakeExecutable:=success; { otherwise a recursive call to link method }
+end;
+
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+initialization
+ RegisterExternalLinker(system_arm_gba_info,TLinkerGba);
+ RegisterTarget(system_arm_gba_info);
+end.
diff --git a/closures/compiler/systems/t_go32v2.pas b/closures/compiler/systems/t_go32v2.pas
new file mode 100644
index 0000000000..f6c4adc496
--- /dev/null
+++ b/closures/compiler/systems/t_go32v2.pas
@@ -0,0 +1,407 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ This unit implements support import,export,link routines
+ for the (i386) Go32v2 target
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit t_go32v2;
+
+{$i fpcdefs.inc}
+
+interface
+
+
+implementation
+
+ uses
+ SysUtils,
+ cutils,cfileutl,cclasses,
+ globtype,globals,systems,verbose,script,
+ fmodule,i_go32v2,
+ link,ogcoff;
+
+ type
+ TInternalLinkerGo32v2=class(TInternallinker)
+ constructor create;override;
+ procedure DefaultLinkScript;override;
+ end;
+
+ TExternalLinkerGo32v2=class(texternallinker)
+ private
+ Function WriteResponseFile(isdll:boolean) : Boolean;
+ Function WriteScript(isdll:boolean) : Boolean;
+ public
+ constructor Create;override;
+ procedure SetDefaultInfo;override;
+ function MakeExecutable:boolean;override;
+ end;
+
+
+{****************************************************************************
+ TCoffLinker
+****************************************************************************}
+
+ constructor TInternalLinkerGo32v2.Create;
+ begin
+ inherited Create;
+ CExeoutput:=TDJCoffexeoutput;
+ CObjInput:=TDJCoffObjInput;
+ end;
+
+
+ procedure TInternalLinkerGo32v2.DefaultLinkScript;
+ begin
+ end;
+
+
+{****************************************************************************
+ TExternalLinkerGo32v2
+****************************************************************************}
+
+Constructor TExternalLinkerGo32v2.Create;
+begin
+ Inherited Create;
+ { allow duplicated libs (PM) }
+ SharedLibFiles.doubles:=true;
+ StaticLibFiles.doubles:=true;
+end;
+
+
+procedure TExternalLinkerGo32v2.SetDefaultInfo;
+begin
+ with Info do
+ begin
+ ExeCmd[1]:='ld $RES';
+ end;
+end;
+
+
+Function TExternalLinkerGo32v2.WriteResponseFile(isdll:boolean) : Boolean;
+Var
+ linkres : TLinkRes;
+ i : longint;
+ s : string;
+ linklibc : boolean;
+begin
+ WriteResponseFile:=False;
+
+ { Open link.res file }
+ LinkRes:=TLinkRes.Create(outputexedir+Info.ResName);
+
+ { Add all options to link.res instead of passing them via command line:
+ DOS command line is limited to 126 characters! }
+ LinkRes.Add('--script='+maybequoted(outputexedir+Info.ScriptName));
+ if info.ExtraOptions<>'' then
+ LinkRes.Add(Info.ExtraOptions);
+(* Potential issues with older ld version??? *)
+ if (cs_link_strip in current_settings.globalswitches) then
+ LinkRes.Add('-s');
+ LinkRes.Add('-o '+maybequoted(current_module.exefilename^));
+
+ { Write staticlibraries }
+ if not StaticLibFiles.Empty then
+ begin
+ LinkRes.Add('-(');
+ While not StaticLibFiles.Empty do
+ begin
+ S:=StaticLibFiles.GetFirst;
+ LinkRes.AddFileName(GetShortName(s))
+ end;
+ LinkRes.Add('-)');
+ end;
+
+ { Write sharedlibraries like -l<lib>, also add the needed dynamic linker
+ here to be sure that it gets linked this is needed for glibc2 systems (PFV) }
+ linklibc:=false;
+ While not SharedLibFiles.Empty do
+ begin
+ S:=SharedLibFiles.GetFirst;
+ if s<>'c' then
+ begin
+ i:=Pos(target_info.sharedlibext,S);
+ if i>0 then
+ Delete(S,i,255);
+ LinkRes.Add('-l'+s);
+ end
+ else
+ begin
+ LinkRes.Add('-l'+s);
+ linklibc:=true;
+ end;
+ end;
+ { be sure that libc&libgcc is the last lib }
+ if linklibc then
+ begin
+ LinkRes.Add('-lc');
+ LinkRes.Add('-lgcc');
+ end;
+
+{ Write and Close response }
+ linkres.writetodisk;
+ LinkRes.Free;
+
+ WriteResponseFile:=True;
+end;
+
+
+Function TExternalLinkerGo32v2.WriteScript(isdll:boolean) : Boolean;
+Var
+ scriptres : TLinkRes;
+ HPath : TCmdStrListItem;
+ s : string;
+begin
+ WriteScript:=False;
+
+ { Open link.res file }
+ ScriptRes:=TLinkRes.Create(outputexedir+Info.ScriptName);
+ ScriptRes.Add('OUTPUT_FORMAT("coff-go32-exe")');
+ ScriptRes.Add('ENTRY(start)');
+
+ ScriptRes.Add('SECTIONS');
+ ScriptRes.Add('{');
+ ScriptRes.Add(' .text 0x1000+SIZEOF_HEADERS : {');
+ ScriptRes.Add(' . = ALIGN(16);');
+ { add objectfiles, start with prt0 always }
+ ScriptRes.Add(' '+GetShortName(FindObjectFile('prt0','',false))+'(.text)');
+ while not ObjectFiles.Empty do
+ begin
+ s:=ObjectFiles.GetFirst;
+ if s<>'' then
+ begin
+ ScriptRes.Add(' . = ALIGN(16);');
+ ScriptRes.Add(' '+GetShortName(s)+'(.text)');
+ end;
+ end;
+ ScriptRes.Add(' *(.text)');
+ ScriptRes.Add(' etext = . ;');
+ ScriptRes.Add(' PROVIDE(_etext = .);');
+ ScriptRes.Add(' . = ALIGN(0x200);');
+ ScriptRes.Add(' }');
+ ScriptRes.Add(' .data ALIGN(0x200) : {');
+ ScriptRes.Add(' djgpp_first_ctor = . ;');
+ ScriptRes.Add(' *(SORT(.ctors.*))');
+ ScriptRes.Add(' *(.ctor)');
+ ScriptRes.Add(' *(.ctors)');
+ ScriptRes.Add(' djgpp_last_ctor = . ;');
+ ScriptRes.Add(' djgpp_first_dtor = . ;');
+ ScriptRes.Add(' *(SORT(.dtors.*))');
+ ScriptRes.Add(' *(.dtor)');
+ ScriptRes.Add(' *(.dtors)');
+ ScriptRes.Add(' djgpp_last_dtor = . ;');
+ ScriptRes.Add(' __environ = . ;');
+ ScriptRes.Add(' PROVIDE(_environ = .);');
+ ScriptRes.Add(' LONG(0)');
+ ScriptRes.Add(' *(.data)');
+ ScriptRes.Add(' *(.fpc*)');
+ ScriptRes.Add(' *(.gcc_exc)');
+ ScriptRes.Add(' ___EH_FRAME_BEGIN__ = . ;');
+ ScriptRes.Add(' *(.eh_fram*)');
+ ScriptRes.Add(' ___EH_FRAME_END__ = . ;');
+ ScriptRes.Add(' LONG(0)');
+ ScriptRes.Add(' edata = . ; _edata = .;');
+ ScriptRes.Add(' . = ALIGN(0x200);');
+ ScriptRes.Add(' }');
+ ScriptRes.Add(' .bss SIZEOF(.data) + ADDR(.data) :');
+ ScriptRes.Add(' {');
+ ScriptRes.Add(' _object.2 = . ;');
+ ScriptRes.Add(' . += 32 ;');
+ ScriptRes.Add(' *(.bss)');
+ ScriptRes.Add(' *(COMMON)');
+ ScriptRes.Add(' end = . ; _end = .;');
+ ScriptRes.Add(' . = ALIGN(0x200);');
+ ScriptRes.Add(' }');
+ ScriptRes.Add(' /* Stabs debugging sections. */');
+ ScriptRes.Add(' .stab 0 : { *(.stab) }');
+ ScriptRes.Add(' .stabstr 0 : { *(.stabstr) }');
+ ScriptRes.Add(' /* DWARF 2 */');
+ ScriptRes.Add(' .debug_aranges 0 : { *(.debug_aranges) }');
+ ScriptRes.Add(' .debug_pubnames 0 : { *(.debug_pubnames) }');
+ ScriptRes.Add(' .debug_info 0 : { *(.debug_info) *(.gnu.linkonce.wi.*) }');
+ ScriptRes.Add(' .debug_abbrev 0 : { *(.debug_abbrev) }');
+ ScriptRes.Add(' .debug_line 0 : { *(.debug_line) }');
+ ScriptRes.Add(' .debug_frame 0 : { *(.debug_frame) }');
+ ScriptRes.Add(' .debug_str 0 : { *(.debug_str) }');
+ ScriptRes.Add(' .debug_loc 0 : { *(.debug_loc) }');
+ ScriptRes.Add(' .debug_macinfo 0 : { *(.debug_macinfo) }');
+ ScriptRes.Add(' }');
+
+ { Write path to search libraries }
+ HPath:=TCmdStrListItem(current_module.locallibrarysearchpath.First);
+ while assigned(HPath) do
+ begin
+ ScriptRes.Add('SEARCH_DIR("'+GetShortName(HPath.Str)+'")');
+ HPath:=TCmdStrListItem(HPath.Next);
+ end;
+ HPath:=TCmdStrListItem(LibrarySearchPath.First);
+ while assigned(HPath) do
+ begin
+ ScriptRes.Add('SEARCH_DIR("'+GetShortName(HPath.Str)+'")');
+ HPath:=TCmdStrListItem(HPath.Next);
+ end;
+
+{ Write and Close response }
+ ScriptRes.WriteToDisk;
+ ScriptRes.Free;
+
+ WriteScript:=True;
+end;
+
+
+
+function TExternalLinkerGo32v2.MakeExecutable:boolean;
+var
+ binstr,
+ cmdstr : TCmdStr;
+ success : boolean;
+begin
+ if not(cs_link_nolink in current_settings.globalswitches) then
+ Message1(exec_i_linking,current_module.exefilename^);
+
+ { Write used files and libraries and our own ld script }
+ WriteScript(false);
+ WriteResponsefile(false);
+
+{ Call linker }
+ SplitBinCmd(Info.ExeCmd[1],binstr,cmdstr);
+ Replace(cmdstr,'$RES','@'+maybequoted(outputexedir+Info.ResName));
+ success:=DoExec(FindUtil(utilsprefix+BinStr),cmdstr,true,false);
+
+{ Remove ReponseFile }
+ if (success) and not(cs_link_nolink in current_settings.globalswitches) then
+ begin
+ DeleteFile(outputexedir+Info.ResName);
+ DeleteFile(outputexedir+Info.ScriptName);
+ end;
+
+ MakeExecutable:=success; { otherwise a recursive call to link method }
+end;
+
+
+{$ifdef notnecessary}
+procedure TExternalLinkerGo32v2.postprocessexecutable(const n : string);
+type
+ tcoffheader=packed record
+ mach : word;
+ nsects : word;
+ time : longint;
+ sympos : longint;
+ syms : longint;
+ opthdr : word;
+ flag : word;
+ end;
+ tcoffsechdr=packed record
+ name : array[0..7] of char;
+ vsize : longint;
+ rvaofs : longint;
+ datalen : longint;
+ datapos : longint;
+ relocpos : longint;
+ lineno1 : longint;
+ nrelocs : word;
+ lineno2 : word;
+ flags : longint;
+ end;
+ psecfill=^TSecfill;
+ TSecfill=record
+ fillpos,
+ fillsize : longint;
+ next : psecfill;
+ end;
+var
+ f : file;
+ coffheader : tcoffheader;
+ firstsecpos,
+ maxfillsize,
+ l : longint;
+ coffsec : tcoffsechdr;
+ secroot,hsecroot : psecfill;
+ zerobuf : pointer;
+begin
+ { when -s is used quit, because there is no .exe }
+ if cs_link_nolink in current_settings.globalswitches then
+ exit;
+ { open file }
+ assign(f,n);
+ {$push}{$I-}
+ reset(f,1);
+ if ioresult<>0 then
+ Message1(execinfo_f_cant_open_executable,n);
+ { read headers }
+ seek(f,2048);
+ blockread(f,coffheader,sizeof(tcoffheader));
+ { read section info }
+ maxfillsize:=0;
+ firstsecpos:=0;
+ secroot:=nil;
+ for l:=1to coffheader.nSects do
+ begin
+ blockread(f,coffsec,sizeof(tcoffsechdr));
+ if coffsec.datapos>0 then
+ begin
+ if secroot=nil then
+ firstsecpos:=coffsec.datapos;
+ new(hsecroot);
+ hsecroot^.fillpos:=coffsec.datapos+coffsec.vsize;
+ hsecroot^.fillsize:=coffsec.datalen-coffsec.vsize;
+ hsecroot^.next:=secroot;
+ secroot:=hsecroot;
+ if secroot^.fillsize>maxfillsize then
+ maxfillsize:=secroot^.fillsize;
+ end;
+ end;
+ if firstsecpos>0 then
+ begin
+ l:=firstsecpos-filepos(f);
+ if l>maxfillsize then
+ maxfillsize:=l;
+ end
+ else
+ l:=0;
+ { get zero buffer }
+ getmem(zerobuf,maxfillsize);
+ fillchar(zerobuf^,maxfillsize,0);
+ { zero from sectioninfo until first section }
+ blockwrite(f,zerobuf^,l);
+ { zero section alignments }
+ while assigned(secroot) do
+ begin
+ seek(f,secroot^.fillpos);
+ blockwrite(f,zerobuf^,secroot^.fillsize);
+ hsecroot:=secroot;
+ secroot:=secroot^.next;
+ dispose(hsecroot);
+ end;
+ freemem(zerobuf,maxfillsize);
+ close(f);
+ {$pop}
+ i:=ioresult;
+ postprocessexecutable:=true;
+end;
+{$endif}
+
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+initialization
+ RegisterExternalLinker(system_i386_go32v2_info,TExternalLinkerGo32v2);
+// RegisterInternalLinker(system_i386_go32v2_info,TInternalLinkerGo32v2);
+ RegisterTarget(system_i386_go32v2_info);
+end.
diff --git a/closures/compiler/systems/t_haiku.pas b/closures/compiler/systems/t_haiku.pas
new file mode 100644
index 0000000000..dae060e5ae
--- /dev/null
+++ b/closures/compiler/systems/t_haiku.pas
@@ -0,0 +1,500 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman
+ Copyright (c) 2008-2008 by Olivier Coursiere
+
+ This unit implements support import,export,link routines
+ for the (i386) Haiku target.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit t_haiku;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ symsym,symdef,
+ import,export,link;
+
+ type
+ timportlibhaiku=class(timportlib)
+ procedure generatelib;override;
+ end;
+
+ texportlibhaiku=class(texportlib)
+ procedure preparelib(const s : string);override;
+ procedure exportprocedure(hp : texported_item);override;
+ procedure exportvar(hp : texported_item);override;
+ procedure generatelib;override;
+ end;
+
+ tlinkerhaiku=class(texternallinker)
+ private
+ Function WriteResponseFile(isdll:boolean;makelib:boolean) : Boolean;
+ public
+ constructor Create;override;
+ procedure SetDefaultInfo;override;
+ function MakeExecutable:boolean;override;
+ function MakeSharedLibrary:boolean;override;
+ end;
+
+
+implementation
+
+ uses
+ SysUtils,
+ cutils,cfileutl,cclasses,
+ verbose,systems,globtype,globals,
+ symconst,script,
+ fmodule,aasmbase,aasmtai,aasmdata,aasmcpu,cpubase,i_haiku,ogbase;
+
+{*****************************************************************************
+ TIMPORTLIBHAIKU
+*****************************************************************************}
+
+ procedure timportlibhaiku.generatelib;
+ var
+ i : longint;
+ ImportLibrary : TImportLibrary;
+ begin
+ for i:=0 to current_module.ImportLibraryList.Count-1 do
+ begin
+ ImportLibrary:=TImportLibrary(current_module.ImportLibraryList[i]);
+ current_module.linkothersharedlibs.add(ImportLibrary.Name,link_always);
+ end;
+ end;
+
+
+{*****************************************************************************
+ TEXPORTLIBHAIKU
+*****************************************************************************}
+
+procedure texportlibhaiku.preparelib(const s:string);
+begin
+end;
+
+
+procedure texportlibhaiku.exportprocedure(hp : texported_item);
+var
+ hp2 : texported_item;
+begin
+ { first test the index value }
+ if (hp.options and eo_index)<>0 then
+ begin
+ Message1(parser_e_no_export_with_index_for_target,'haiku');
+ exit;
+ end;
+ { now place in correct order }
+ hp2:=texported_item(current_module._exports.first);
+ while assigned(hp2) and
+ (hp.name^>hp2.name^) do
+ hp2:=texported_item(hp2.next);
+ { insert hp there !! }
+ if assigned(hp2) and (hp2.name^=hp.name^) then
+ begin
+ { this is not allowed !! }
+ Message1(parser_e_export_name_double,hp.name^);
+ exit;
+ end;
+ if hp2=texported_item(current_module._exports.first) then
+ current_module._exports.concat(hp)
+ else if assigned(hp2) then
+ begin
+ hp.next:=hp2;
+ hp.previous:=hp2.previous;
+ if assigned(hp2.previous) then
+ hp2.previous.next:=hp;
+ hp2.previous:=hp;
+ end
+ else
+ current_module._exports.concat(hp);
+end;
+
+
+procedure texportlibhaiku.exportvar(hp : texported_item);
+begin
+ hp.is_var:=true;
+ exportprocedure(hp);
+end;
+
+
+procedure texportlibhaiku.generatelib;
+var
+ hp2 : texported_item;
+ pd : tprocdef;
+begin
+ hp2:=texported_item(current_module._exports.first);
+ while assigned(hp2) do
+ begin
+ if (not hp2.is_var) and
+ (hp2.sym.typ=procsym) then
+ begin
+ { the manglednames can already be the same when the procedure
+ is declared with cdecl }
+ pd:=tprocdef(tprocsym(hp2.sym).ProcdefList[0]);
+ if pd.mangledname<>hp2.name^ then
+ begin
+{$ifdef i386}
+ { place jump in al_procedures }
+ current_asmdata.asmlists[al_procedures].concat(Tai_align.Create_op(4,$90));
+ current_asmdata.asmlists[al_procedures].concat(Tai_symbol.Createname_global(hp2.name^,AT_FUNCTION,0));
+ current_asmdata.asmlists[al_procedures].concat(Taicpu.Op_sym(A_JMP,S_NO,current_asmdata.RefAsmSymbol(pd.mangledname)));
+ current_asmdata.asmlists[al_procedures].concat(Tai_symbol_end.Createname(hp2.name^));
+{$endif i386}
+ end;
+ end
+ else
+ Message1(parser_e_no_export_of_variables_for_target,'haiku');
+ hp2:=texported_item(hp2.next);
+ end;
+end;
+
+
+{*****************************************************************************
+ TLINKERHAIKU
+*****************************************************************************}
+
+Constructor TLinkerHaiku.Create;
+var
+ s : string;
+ i : integer;
+begin
+ Inherited Create;
+ s:=GetEnvironmentVariable('BELIBRARIES');
+ { convert to correct format in case under unix system }
+ for i:=1 to length(s) do
+ if s[i] = ':' then
+ s[i] := ';';
+ { just in case we have a single path : add the ending ; }
+ { since that is what the compiler expects. }
+ if pos(';',s) = 0 then
+ s:=s+';';
+ LibrarySearchPath.AddPath(sysrootpath,s,true); {format:'path1;path2;...'}
+end;
+
+
+procedure TLinkerHaiku.SetDefaultInfo;
+begin
+ with Info do
+ begin
+ ExeCmd[1]:='ld $OPT $DYNLINK $STATIC $STRIP -L. -o $EXE $CATRES';
+ DllCmd[1]:='ld $OPT $INIT $FINI $SONAME -shared -L. -o $EXE $CATRES';
+ DllCmd[2]:='strip --strip-unneeded $EXE';
+(*
+ ExeCmd[1]:='sh $RES $EXE $OPT $STATIC $STRIP -L.';
+{ ExeCmd[1]:='sh $RES $EXE $OPT $DYNLINK $STATIC $STRIP -L.';}
+ DllCmd[1]:='sh $RES $EXE $OPT -L.';
+
+{ DllCmd[1]:='sh $RES $EXE $OPT -L. -g -nostart -soname=$EXE';
+ } DllCmd[2]:='strip --strip-unneeded $EXE';
+{ DynamicLinker:='/lib/ld-beos.so.2';}
+*)
+ end;
+end;
+
+
+function TLinkerHaiku.WriteResponseFile(isdll:boolean;makelib:boolean) : Boolean;
+Var
+ linkres : TLinkRes;
+ i : integer;
+ cprtobj,
+ prtobj : string[80];
+ HPath : TCmdStrListItem;
+ s : TCmdStr;
+ linklibc : boolean;
+begin
+ WriteResponseFile:=False;
+{ set special options for some targets }
+ linklibc:=(SharedLibFiles.Find('root')<>nil);
+
+ prtobj:='prt0';
+ cprtobj:='cprt0';
+ if (cs_profile in current_settings.moduleswitches) or
+ (not SharedLibFiles.Empty) then
+ begin
+ AddSharedLibrary('root');
+ linklibc:=true;
+ end;
+
+ if (not linklibc) and makelib then
+ begin
+ linklibc:=true;
+ cprtobj:='dllprt.o';
+ end;
+
+ if linklibc then
+ prtobj:=cprtobj;
+
+ { Open link.res file }
+ LinkRes:=TLinkRes.Create(outputexedir+Info.ResName);
+ {
+ if not isdll then
+ LinkRes.Add('ld -o $1 $2 $3 $4 $5 $6 $7 $8 $9 \')
+ else
+ LinkRes.Add('ld -o $1 -e 0 $2 $3 $4 $5 $6 $7 $8 $9\');
+ }
+ LinkRes.Add('-m');
+ LinkRes.Add('elf_i386_haiku');
+ LinkRes.Add('-shared');
+ LinkRes.Add('-Bsymbolic');
+
+ { Write path to search libraries }
+ HPath:=TCmdStrListItem(current_module.locallibrarysearchpath.First);
+ while assigned(HPath) do
+ begin
+ LinkRes.Add('-L'+HPath.Str);
+ HPath:=TCmdStrListItem(HPath.Next);
+ end;
+ HPath:=TCmdStrListItem(LibrarySearchPath.First);
+ while assigned(HPath) do
+ begin
+ LinkRes.Add('-L'+HPath.Str);
+ HPath:=TCmdStrListItem(HPath.Next);
+ end;
+
+ { try to add crti and crtbegin if linking to C }
+ if linklibc then
+ begin
+ if librarysearchpath.FindFile('crti.o',false,s) then
+ LinkRes.AddFileName(s);
+ if librarysearchpath.FindFile('crtbegin.o',false,s) then
+ LinkRes.AddFileName(s);
+{ s:=librarysearchpath.FindFile('start_dyn.o',found)+'start_dyn.o';
+ if found then LinkRes.AddFileName(s+' \');}
+
+ if prtobj<>'' then
+ LinkRes.AddFileName(FindObjectFile(prtobj,'',false));
+
+// if isdll then
+// LinkRes.AddFileName(FindObjectFile('func.o','',false));
+
+ if librarysearchpath.FindFile('init_term_dyn.o',false,s) then
+ LinkRes.AddFileName(s);
+ end
+ else
+ begin
+ if prtobj<>'' then
+ LinkRes.AddFileName(FindObjectFile(prtobj,'',false));
+ end;
+
+ { main objectfiles }
+ while not ObjectFiles.Empty do
+ begin
+ s:=ObjectFiles.GetFirst;
+ if s<>'' then
+ LinkRes.AddFileName(s);
+ end;
+
+{ LinkRes.Add('-lroot \');
+ LinkRes.Add('/boot/develop/tools/gnupro/lib/gcc-lib/i586-beos/2.9-beos-991026/crtend.o \');
+ LinkRes.Add('/boot/develop/lib/x86/crtn.o \');}
+
+ { Write staticlibraries }
+ if not StaticLibFiles.Empty then
+ begin
+ While not StaticLibFiles.Empty do
+ begin
+ S:=StaticLibFiles.GetFirst;
+ LinkRes.AddFileName(s)
+ end;
+ end;
+
+ { Write sharedlibraries like -l<lib> }
+ if not SharedLibFiles.Empty then
+ begin
+ While not SharedLibFiles.Empty do
+ begin
+ S:=SharedLibFiles.GetFirst;
+ if s<>'c' then
+ begin
+ i:=Pos(target_info.sharedlibext,S);
+ if i>0 then
+ Delete(S,i,255);
+ LinkRes.Add('-l'+s);
+ end
+ else
+ begin
+ linklibc:=true;
+ end;
+ end;
+ { be sure that libc is the last lib }
+{ if linklibc then
+ LinkRes.Add('-lroot');}
+{ if linkdynamic and (Info.DynamicLinker<>'') then
+ LinkRes.AddFileName(Info.DynamicLinker);}
+ end;
+ if isdll then
+ LinkRes.Add('-lroot');
+
+ { objects which must be at the end }
+ if linklibc then
+ begin
+ if librarysearchpath.FindFile('crtend.o',false,s) then
+ LinkRes.AddFileName(s);
+ if librarysearchpath.FindFile('crtn.o',false,s) then
+ LinkRes.AddFileName(s);
+ end;
+
+{ Write and Close response }
+ linkres.writetodisk;
+ linkres.free;
+
+ WriteResponseFile:=True;
+end;
+
+
+function TLinkerHaiku.MakeExecutable:boolean;
+var
+ binstr,
+ cmdstr : TCmdStr;
+ success,
+ useshell : boolean;
+ DynLinkStr : string[60];
+ GCSectionsStr,
+ StaticStr,
+ StripStr : string[40];
+begin
+ if not(cs_link_nolink in current_settings.globalswitches) then
+ Message1(exec_i_linking,current_module.exefilename^);
+
+{ Create some replacements }
+ StaticStr:='';
+ StripStr:='';
+ DynLinkStr:='';
+ GCSectionsStr:='';
+ if (cs_link_staticflag in current_settings.globalswitches) then
+ StaticStr:='-static';
+ if (cs_link_strip in current_settings.globalswitches) then
+ StripStr:='-s';
+
+ if (cs_link_smart in current_settings.globalswitches) and
+ (tf_smartlink_sections in target_info.flags) then
+ GCSectionsStr:='--gc-sections';
+
+ If (cs_profile in current_settings.moduleswitches) or
+ ((Info.DynamicLinker<>'') and (not SharedLibFiles.Empty)) then
+ begin
+ DynLinkStr:='-dynamic-linker='+Info.DynamicLinker;
+ if cshared Then
+ DynLinkStr:='--shared ' + DynLinkStr;
+ if rlinkpath<>'' Then
+ DynLinkStr:='--rpath-link '+rlinkpath + ' '+ DynLinkStr;
+ End;
+
+{ Write used files and libraries }
+ WriteResponseFile(false,false);
+
+{ Call linker }
+ SplitBinCmd(Info.ExeCmd[1],binstr,cmdstr);
+ Replace(cmdstr,'$EXE',maybequoted(current_module.exefilename^));
+ Replace(cmdstr,'$OPT',Info.ExtraOptions);
+ Replace(cmdstr,'$CATRES',CatFileContent(outputexedir+Info.ResName));
+ Replace(cmdstr,'$RES',maybequoted(outputexedir+Info.ResName));
+ Replace(cmdstr,'$STATIC',StaticStr);
+ Replace(cmdstr,'$STRIP',StripStr);
+ Replace(cmdstr,'$GCSECTIONS',GCSectionsStr);
+ Replace(cmdstr,'$DYNLINK',DynLinkStr);
+ useshell:=not (tf_no_backquote_support in source_info.flags);
+ success:=DoExec(FindUtil(utilsprefix+BinStr),CmdStr,true,useshell);
+
+{ Remove ReponseFile }
+ if (success) and not(cs_link_nolink in current_settings.globalswitches) then
+ DeleteFile(outputexedir+Info.ResName);
+
+ MakeExecutable:=success; { otherwise a recursive call to link method }
+end;
+
+
+Function TLinkerHaiku.MakeSharedLibrary:boolean;
+var
+ binstr,
+ cmdstr,
+ SoNameStr : TCmdStr;
+ success : boolean;
+ DynLinkStr : string[60];
+ StaticStr,
+ StripStr : string[40];
+
+ begin
+ MakeSharedLibrary:=false;
+ if not(cs_link_nolink in current_settings.globalswitches) then
+ Message1(exec_i_linking,current_module.sharedlibfilename^);
+
+{ Create some replacements }
+ StaticStr:='';
+ StripStr:='';
+ DynLinkStr:='';
+ if (cs_link_staticflag in current_settings.globalswitches) then
+ StaticStr:='-static';
+ if (cs_link_strip in current_settings.globalswitches) then
+ StripStr:='-s';
+ If (cs_profile in current_settings.moduleswitches) or
+ ((Info.DynamicLinker<>'') and (not SharedLibFiles.Empty)) then
+ begin
+ DynLinkStr:='-dynamic-linker='+Info.DynamicLinker;
+ if cshared Then
+ DynLinkStr:='--shared ' + DynLinkStr;
+ if rlinkpath<>'' Then
+ DynLinkStr:='--rpath-link '+rlinkpath + ' '+ DynLinkStr;
+ End;
+{ Write used files and libraries }
+ WriteResponseFile(true,true);
+
+ SoNameStr:='-soname '+ExtractFileName(current_module.sharedlibfilename^);
+
+{ Call linker }
+ SplitBinCmd(Info.DllCmd[1],binstr,cmdstr);
+ Replace(cmdstr,'$EXE',maybequoted(current_module.sharedlibfilename^));
+ Replace(cmdstr,'$OPT',Info.ExtraOptions);
+ Replace(cmdstr,'$CATRES',CatFileContent(outputexedir+Info.ResName));
+ Replace(cmdstr,'$RES',maybequoted(outputexedir+Info.ResName));
+ Replace(cmdstr,'$STATIC',StaticStr);
+ Replace(cmdstr,'$STRIP',StripStr);
+ Replace(cmdstr,'$DYNLINK',DynLinkStr);
+ Replace(cmdstr,'$SONAME',SoNameStr);
+
+ success:=DoExec(FindUtil(utilsprefix+binstr),cmdstr,true,true);
+
+{ Strip the library ? }
+ if success and (cs_link_strip in current_settings.globalswitches) then
+ begin
+ SplitBinCmd(Info.DllCmd[2],binstr,cmdstr);
+ Replace(cmdstr,'$EXE',maybequoted(current_module.sharedlibfilename^));
+ success:=DoExec(FindUtil(utilsprefix+binstr),cmdstr,true,false);
+ end;
+
+{ Remove ReponseFile }
+ if (success) and not(cs_link_nolink in current_settings.globalswitches) then
+ DeleteFile(outputexedir+Info.ResName);
+
+ MakeSharedLibrary:=success; { otherwise a recursive call to link method }
+end;
+
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+initialization
+{$ifdef i386}
+ RegisterExternalLinker(system_i386_haiku_info,TLinkerhaiku);
+ RegisterImport(system_i386_haiku,timportlibhaiku);
+ RegisterExport(system_i386_haiku,texportlibhaiku);
+ RegisterTarget(system_i386_haiku_info);
+{$endif i386}
+end.
diff --git a/closures/compiler/systems/t_linux.pas b/closures/compiler/systems/t_linux.pas
new file mode 100644
index 0000000000..4977a116a0
--- /dev/null
+++ b/closures/compiler/systems/t_linux.pas
@@ -0,0 +1,1188 @@
+{
+ Copyright (c) 1998-2008 by Peter Vreman
+
+ This unit implements support import,export,link routines
+ for the (i386) Linux target
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit t_linux;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ aasmdata,
+ symsym,symdef,ppu,
+ import,export,expunix,link;
+
+ type
+ timportliblinux=class(timportlib)
+ procedure generatelib;override;
+ end;
+
+ texportliblinux=class(texportlibunix)
+ procedure setfininame(list: TAsmList; const s: string); override;
+ end;
+
+ tlinkerlinux=class(texternallinker)
+ private
+ libctype:(libc5,glibc2,glibc21,uclibc);
+ cprtobj,
+ gprtobj,
+ prtobj : string[80];
+ reorder : boolean;
+ linklibc: boolean;
+ Function WriteResponseFile(isdll:boolean) : Boolean;
+ public
+ constructor Create;override;
+ procedure SetDefaultInfo;override;
+ procedure InitSysInitUnitName;override;
+ function MakeExecutable:boolean;override;
+ function MakeSharedLibrary:boolean;override;
+ procedure LoadPredefinedLibraryOrder; override;
+ end;
+
+
+implementation
+
+ uses
+ SysUtils,
+ cutils,cfileutl,cclasses,
+ verbose,systems,globtype,globals,
+ symconst,script,
+ fmodule,
+ aasmbase,aasmtai,aasmcpu,cpubase,
+ cgbase,cgobj,cgutils,ogbase,ncgutil,
+ comprsrc,
+ rescmn, i_linux
+ ;
+
+{*****************************************************************************
+ TIMPORTLIBLINUX
+*****************************************************************************}
+
+ procedure timportliblinux.generatelib;
+ var
+ i : longint;
+ ImportLibrary : TImportLibrary;
+ begin
+ for i:=0 to current_module.ImportLibraryList.Count-1 do
+ begin
+ ImportLibrary:=TImportLibrary(current_module.ImportLibraryList[i]);
+ current_module.linkothersharedlibs.add(ImportLibrary.Name,link_always);
+ end;
+ end;
+
+
+{*****************************************************************************
+ TEXPORTLIBLINUX
+*****************************************************************************}
+
+ procedure texportliblinux.setfininame(list: TAsmList; const s: string);
+ begin
+ { the problem with not having a .fini section is that a finalization
+ routine in regular code can get "smart" linked away -> reference it
+ just like the debug info }
+ new_section(list,sec_fpc,'links',0);
+ list.concat(Tai_const.Createname(s,0));
+ inherited setfininame(list,s);
+ end;
+
+{*****************************************************************************
+ TLINKERLINUX
+*****************************************************************************}
+
+Constructor TLinkerLinux.Create;
+begin
+ Inherited Create;
+ if not Dontlinkstdlibpath Then
+{$ifdef x86_64}
+ LibrarySearchPath.AddPath(sysrootpath,'/lib64;/usr/lib64;/usr/X11R6/lib64',true);
+{$else}
+{$ifdef powerpc64}
+ LibrarySearchPath.AddPath(sysrootpath,'/lib64;/usr/lib64;/usr/X11R6/lib64',true);
+{$else powerpc64}
+ LibrarySearchPath.AddPath(sysrootpath,'/lib;/usr/lib;/usr/X11R6/lib',true);
+{$endif powerpc64}
+{$endif x86_64}
+end;
+
+
+procedure TLinkerLinux.SetDefaultInfo;
+{
+ This will also detect which libc version will be used
+}
+
+const
+{$ifdef i386} platform_select='-b elf32-i386 -m elf_i386';{$endif}
+{$ifdef x86_64} platform_select='-b elf64-x86-64 -m elf_x86_64';{$endif}
+{$ifdef powerpc} platform_select='-b elf32-powerpc -m elf32ppclinux';{$endif}
+{$ifdef POWERPC64} platform_select='-b elf64-powerpc -m elf64ppc';{$endif}
+{$ifdef sparc} platform_select='-b elf32-sparc -m elf32_sparc';{$endif}
+{$ifdef arm} platform_select='';{$endif} {unknown :( }
+{$ifdef m68k} platform_select='';{$endif} {unknown :( }
+{$ifdef mips}
+ {$ifdef mipsel} platform_select='-EL';{$else}
+ platform_select='-EB';{$endif}
+{$endif}
+
+
+var
+ defdynlinker: string;
+begin
+ with Info do
+ begin
+ ExeCmd[1]:='ld '+platform_select+' $OPT $DYNLINK $STATIC $GCSECTIONS $STRIP -L. -o $EXE';
+ { when we want to cross-link we need to override default library paths }
+ if length(sysrootpath) > 0 then
+ ExeCmd[1]:=ExeCmd[1]+' -T';
+ ExeCmd[1]:=ExeCmd[1]+' $RES';
+ DllCmd[1]:='ld '+platform_select+' $OPT $INIT $FINI $SONAME -shared -L. -o $EXE $RES';
+ DllCmd[2]:='strip --strip-unneeded $EXE';
+ ExtDbgCmd[1]:='objcopy --only-keep-debug $EXE $DBG';
+ ExtDbgCmd[2]:='objcopy --add-gnu-debuglink=$DBG $EXE';
+ ExtDbgCmd[3]:='strip --strip-unneeded $EXE';
+
+{$ifdef m68k}
+ { experimental, is this correct? }
+ defdynlinker:='/lib/ld-linux.so.2';
+{$endif m68k}
+
+{$ifdef i386}
+ defdynlinker:='/lib/ld-linux.so.2';
+{$endif}
+
+{$ifdef x86_64}
+ defdynlinker:='/lib64/ld-linux-x86-64.so.2';
+{$endif x86_64}
+
+{$ifdef sparc}
+ defdynlinker:='/lib/ld-linux.so.2';
+{$endif sparc}
+
+{$ifdef powerpc}
+ defdynlinker:='/lib/ld.so.1';
+{$endif powerpc}
+
+{$ifdef powerpc64}
+ defdynlinker:='/lib64/ld64.so.1';
+{$endif powerpc64}
+
+{$ifdef arm}
+{$ifdef FPC_ARMEL}
+ defdynlinker:='/lib/ld-linux.so.3';
+{$else FPC_ARMEL}
+ defdynlinker:='/lib/ld-linux.so.2';
+{$endif FPC_ARMEL}
+{$endif arm}
+
+{$ifdef mips}
+ defdynlinker:='/lib/ld.so.1';
+{$endif mips}
+ {
+ Search order:
+ glibc 2.1+
+ uclibc
+ glibc 2.0
+ If none is found (e.g. when cross compiling) glibc21 is assumed
+ }
+ if fileexists(sysrootpath+defdynlinker,false) then
+ begin
+ DynamicLinker:=defdynlinker;
+{$ifdef i386}
+ libctype:=glibc21;
+{$else i386}
+ libctype:=glibc2;
+{$endif i386}
+ end
+ else if fileexists(sysrootpath+'/lib/ld-uClibc.so.0',false) then
+ begin
+ dynamiclinker:='/lib/ld-uClibc.so.0';
+ libctype:=uclibc;
+ end
+{$ifdef i386}
+ else if FileExists(sysrootpath+'/lib/ld-linux.so.1',false) then
+ begin
+ DynamicLinker:='/lib/ld-linux.so.1';
+ libctype:=glibc2;
+ end
+{$endif i386}
+ else
+ begin
+ { when no dyn. linker is found, we are probably
+ cross compiling, so use the default dyn. linker }
+ DynamicLinker:=defdynlinker;
+ {
+ the default c startup script is gcrt0.as on all platforms
+ except i386
+ }
+{$ifdef i386}
+ libctype:=glibc21;
+{$else i386}
+ libctype:=glibc2;
+{$endif i386}
+ end;
+ end;
+end;
+
+
+procedure TLinkerLinux.LoadPredefinedLibraryOrder;
+// put your linkorder/linkalias overrides here.
+// Note: assumes only called when reordering/aliasing is used.
+Begin
+ if not (cs_link_no_default_lib_order in current_settings.globalswitches) Then
+ Begin
+ LinkLibraryOrder.add('gcc','',15);
+ LinkLibraryOrder.add('c','',100);
+ LinkLibraryOrder.add('gmon','',120);
+ LinkLibraryOrder.add('dl','',140);
+ LinkLibraryOrder.add('pthread','',160);
+ end;
+End;
+
+Procedure TLinkerLinux.InitSysInitUnitName;
+var
+ csysinitunit,
+ gsysinitunit : string[20];
+ hp : tmodule;
+begin
+ hp:=tmodule(loaded_units.first);
+ while assigned(hp) do
+ begin
+ linklibc := hp.linkothersharedlibs.find('c');
+ if linklibc then break;
+ hp:=tmodule(hp.next);
+ end;
+ reorder := linklibc and ReOrderEntries;
+ if current_module.islibrary then
+ begin
+ sysinitunit:='dll';
+ csysinitunit:='dll';
+ gsysinitunit:='dll';
+ prtobj:='dllprt0';
+ cprtobj:='dllprt0';
+ gprtobj:='dllprt0';
+ end
+ else
+ begin
+ prtobj:='prt0';
+ sysinitunit:='prc';
+ case libctype of
+ glibc21:
+ begin
+ cprtobj:='cprt21';
+ gprtobj:='gprt21';
+ csysinitunit:='c21';
+ gsysinitunit:='c21g';
+ end;
+ uclibc:
+ begin
+ cprtobj:='ucprt0';
+ gprtobj:='ugprt0';
+ csysinitunit:='uc';
+ gsysinitunit:='ucg';
+ end
+ else
+ cprtobj:='cprt0';
+ gprtobj:='gprt0';
+ csysinitunit:='c';
+ gsysinitunit:='g';
+ end;
+ end;
+ if cs_profile in current_settings.moduleswitches then
+ begin
+ prtobj:=gprtobj;
+ sysinitunit:=gsysinitunit;
+ linklibc:=true;
+ end
+ else
+ begin
+ if linklibc then
+ begin
+ prtobj:=cprtobj;
+ sysinitunit:=csysinitunit;
+ end;
+ end;
+ sysinitunit:='si_'+sysinitunit;
+end;
+
+Function TLinkerLinux.WriteResponseFile(isdll:boolean) : Boolean;
+Var
+ linkres : TLinkRes;
+ i : longint;
+ HPath : TCmdStrListItem;
+ s,s1,s2 : TCmdStr;
+ found1,
+ found2 : boolean;
+ linksToSharedLibFiles : boolean;
+begin
+ result:=False;
+{ set special options for some targets }
+ if cs_profile in current_settings.moduleswitches then
+ begin
+ if not(libctype in [glibc2,glibc21]) then
+ AddSharedLibrary('gmon');
+ AddSharedLibrary('c');
+ end;
+
+ { Open link.res file }
+ LinkRes:=TLinkRes.Create(outputexedir+Info.ResName);
+ with linkres do
+ begin
+ { Write path to search libraries }
+ HPath:=TCmdStrListItem(current_module.locallibrarysearchpath.First);
+ while assigned(HPath) do
+ begin
+ Add('SEARCH_DIR('+maybequoted(HPath.Str)+')');
+ HPath:=TCmdStrListItem(HPath.Next);
+ end;
+ HPath:=TCmdStrListItem(LibrarySearchPath.First);
+ while assigned(HPath) do
+ begin
+ Add('SEARCH_DIR('+maybequoted(HPath.Str)+')');
+ HPath:=TCmdStrListItem(HPath.Next);
+ end;
+
+ { force local symbol resolution (i.e., inside the shared }
+ { library itself) for all non-exorted symbols, otherwise }
+ { several RTL symbols of FPC-compiled shared libraries }
+ { will be bound to those of a single shared library or }
+ { to the main program }
+ if (isdll) then
+ begin
+ add('VERSION');
+ add('{');
+ add(' {');
+ if not texportlibunix(exportlib).exportedsymnames.empty then
+ begin
+ add(' global:');
+ repeat
+ add(' '+texportlibunix(exportlib).exportedsymnames.getfirst+';');
+ until texportlibunix(exportlib).exportedsymnames.empty;
+ end;
+ add(' local:');
+ add(' *;');
+ add(' };');
+ add('}');
+ end;
+
+ StartSection('INPUT(');
+ { add objectfiles, start with prt0 always }
+ if not (target_info.system in systems_internal_sysinit) and (prtobj<>'') then
+ AddFileName(maybequoted(FindObjectFile(prtobj,'',false)));
+ { try to add crti and crtbegin if linking to C }
+ if linklibc and (libctype<>uclibc) then
+ begin
+ { crti.o must come first }
+ if librarysearchpath.FindFile('crti.o',false,s) then
+ AddFileName(s);
+ { then the crtbegin* }
+ if cs_create_pic in current_settings.moduleswitches then
+ begin
+ if librarysearchpath.FindFile('crtbeginS.o',false,s) then
+ AddFileName(s);
+ end
+ else
+ if (cs_link_staticflag in current_settings.globalswitches) and
+ librarysearchpath.FindFile('crtbeginT.o',false,s) then
+ AddFileName(s)
+ else if librarysearchpath.FindFile('crtbegin.o',false,s) then
+ AddFileName(s);
+ end;
+ { main objectfiles }
+ while not ObjectFiles.Empty do
+ begin
+ s:=ObjectFiles.GetFirst;
+ if s<>'' then
+ AddFileName(maybequoted(s));
+ end;
+ EndSection(')');
+
+ { Write staticlibraries }
+ if not StaticLibFiles.Empty then
+ begin
+ Add('GROUP(');
+ While not StaticLibFiles.Empty do
+ begin
+ S:=StaticLibFiles.GetFirst;
+ AddFileName(maybequoted(s))
+ end;
+ Add(')');
+ end;
+
+ // we must reorder here because the result could empty sharedlibfiles
+ if reorder Then
+ ExpandAndApplyOrder(SharedLibFiles);
+ // after this point addition of shared libs not allowed.
+
+ { Write sharedlibraries like -l<lib>, also add the needed dynamic linker
+ here to be sure that it gets linked this is needed for glibc2 systems (PFV) }
+ if (isdll) then
+ begin
+ Add('INPUT(');
+ Add(info.DynamicLinker);
+ Add(')');
+ end;
+ linksToSharedLibFiles := not SharedLibFiles.Empty;
+
+ if not SharedLibFiles.Empty then
+ begin
+
+ if (SharedLibFiles.Count<>1) or
+ (TCmdStrListItem(SharedLibFiles.First).Str<>'c') or
+ reorder then
+ begin
+ Add('INPUT(');
+ While not SharedLibFiles.Empty do
+ begin
+ S:=SharedLibFiles.GetFirst;
+ if (s<>'c') or reorder then
+ begin
+ i:=Pos(target_info.sharedlibext,S);
+ if i>0 then
+ Delete(S,i,255);
+ Add('-l'+s);
+ end
+ else
+ begin
+ linklibc:=true;
+ end;
+ end;
+ Add(')');
+ end
+ else
+ linklibc:=true;
+ if (cs_link_staticflag in current_settings.globalswitches) or
+ (linklibc and not reorder) then
+ begin
+ Add('GROUP(');
+ { when we have -static for the linker the we also need libgcc }
+ if (cs_link_staticflag in current_settings.globalswitches) then
+ begin
+ Add('-lgcc');
+ if librarysearchpath.FindFile('libgcc_eh.a',false,s1) then
+ Add('-lgcc_eh');
+ end;
+ { be sure that libc is the last lib }
+ if linklibc and not reorder then
+ Add('-lc');
+ Add(')');
+ end;
+ end;
+
+ { objects which must be at the end }
+ if linklibc and (libctype<>uclibc) then
+ begin
+ if cs_create_pic in current_settings.moduleswitches then
+ found1:=librarysearchpath.FindFile('crtendS.o',false,s1)
+ else
+ found1:=librarysearchpath.FindFile('crtend.o',false,s1);
+ found2:=librarysearchpath.FindFile('crtn.o',false,s2);
+ if found1 or found2 then
+ begin
+ Add('INPUT(');
+ if found1 then
+ AddFileName(s1);
+ if found2 then
+ AddFileName(s2);
+ Add(')');
+ end;
+ end;
+
+ {Entry point. Only needed for executables, set on the linker command line for
+ shared libraries. }
+ if (not isdll) then
+ if (linksToSharedLibFiles and not linklibc) then
+ add('ENTRY(_dynamic_start)')
+ else
+ add('ENTRY(_start)');
+
+{$ifdef x86_64}
+{$define LINKERSCRIPT_INCLUDED}
+ add('SECTIONS');
+ add('{');
+ {Read-only sections, merged into text segment:}
+ if current_module.islibrary then
+ add(' . = 0 + SIZEOF_HEADERS;')
+ else
+ add(' PROVIDE (__executable_start = 0x0400000); . = 0x0400000 + SIZEOF_HEADERS;');
+ add(' . = 0 + SIZEOF_HEADERS;');
+ add(' .interp : { *(.interp) }');
+ add(' .hash : { *(.hash) }');
+ add(' .dynsym : { *(.dynsym) }');
+ add(' .dynstr : { *(.dynstr) }');
+ add(' .gnu.version : { *(.gnu.version) }');
+ add(' .gnu.version_d : { *(.gnu.version_d) }');
+ add(' .gnu.version_r : { *(.gnu.version_r) }');
+ add(' .rel.dyn :');
+ add(' {');
+ add(' *(.rel.init)');
+ add(' *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*)');
+ add(' *(.rel.fini)');
+ add(' *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*)');
+ add(' *(.rel.data.rel.ro*)');
+ add(' *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*)');
+ add(' *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*)');
+ add(' *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*)');
+ add(' *(.rel.got)');
+ add(' *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*)');
+ add(' }');
+ add(' .rela.dyn :');
+ add(' {');
+ add(' *(.rela.init)');
+ add(' *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)');
+ add(' *(.rela.fini)');
+ add(' *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)');
+ add(' *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)');
+ add(' *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)');
+ add(' *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)');
+ add(' *(.rela.got)');
+ add(' *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)');
+ add(' }');
+ add(' .rel.plt : { *(.rel.plt) }');
+ add(' .rela.plt : { *(.rela.plt) }');
+ add(' .init :');
+ add(' {');
+ add(' KEEP (*(.init))');
+ add(' } =0x90909090');
+ add(' .plt : { *(.plt) }');
+ add(' .text :');
+ add(' {');
+ add(' *(.text .stub .text.* .gnu.linkonce.t.*)');
+ add(' KEEP (*(.text.*personality*))');
+ {.gnu.warning sections are handled specially by elf32.em.}
+ add(' *(.gnu.warning)');
+ add(' } =0x90909090');
+ add(' .fini :');
+ add(' {');
+ add(' KEEP (*(.fini))');
+ add(' } =0x90909090');
+ add(' PROVIDE (_etext = .);');
+ add(' .rodata :');
+ add(' {');
+ add(' *(.rodata .rodata.* .gnu.linkonce.r.*)');
+ add(' }');
+ {Adjust the address for the data segment. We want to adjust up to
+ the same address within the page on the next page up.}
+ add(' . = ALIGN (0x1000) - ((0x1000 - .) & (0x1000 - 1));');
+ add(' .dynamic : { *(.dynamic) }');
+ add(' .got : { *(.got .toc) }');
+ add(' .got.plt : { *(.got.plt .toc.plt) }');
+ add(' .data :');
+ add(' {');
+ add(' *(.data .data.* .gnu.linkonce.d.*)');
+ add(' KEEP (*(.fpc .fpc.n_version .fpc.n_links))');
+ add(' KEEP (*(.gnu.linkonce.d.*personality*))');
+ add(' }');
+ add(' PROVIDE (_edata = .);');
+ add(' PROVIDE (edata = .);');
+ {$ifdef zsegment_threadvars}
+ add(' _z = .;');
+ add(' .threadvar 0 : AT (_z) { *(.threadvar .threadvar.* .gnu.linkonce.tv.*) }');
+ add(' PROVIDE (_threadvar_size = SIZEOF(.threadvar));');
+ add(' . = _z + SIZEOF (.threadvar);');
+ {$else}
+ add(' .threadvar : { *(.threadvar .threadvar.* .gnu.linkonce.tv.*) }');
+ {$endif}
+ add(' __bss_start = .;');
+ add(' .bss :');
+ add(' {');
+ add(' *(.dynbss)');
+ add(' *(.bss .bss.* .gnu.linkonce.b.*)');
+ add(' *(COMMON)');
+ {Align here to ensure that the .bss section occupies space up to
+ _end. Align after .bss to ensure correct alignment even if the
+ .bss section disappears because there are no input sections.}
+ add(' . = ALIGN(32 / 8);');
+ add(' }');
+ add(' . = ALIGN(32 / 8);');
+ add(' PROVIDE (_end = .);');
+ add(' PROVIDE (end = .);');
+ {Stabs debugging sections.}
+ add(' .stab 0 : { *(.stab) }');
+ add(' .stabstr 0 : { *(.stabstr) }');
+ add(' /* DWARF debug sections.');
+ add(' Symbols in the DWARF debugging sections are relative to the beginning');
+ add(' of the section so we begin them at 0. */');
+ add(' /* DWARF 1 */');
+ add(' .debug 0 : { *(.debug) }');
+ add(' .line 0 : { *(.line) }');
+ add(' /* GNU DWARF 1 extensions */');
+ add(' .debug_srcinfo 0 : { *(.debug_srcinfo) }');
+ add(' .debug_sfnames 0 : { *(.debug_sfnames) }');
+ add(' /* DWARF 1.1 and DWARF 2 */');
+ add(' .debug_aranges 0 : { *(.debug_aranges) }');
+ add(' .debug_pubnames 0 : { *(.debug_pubnames) }');
+ add(' /* DWARF 2 */');
+ add(' .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }');
+ add(' .debug_abbrev 0 : { *(.debug_abbrev) }');
+ add(' .debug_line 0 : { *(.debug_line) }');
+ add(' .debug_frame 0 : { *(.debug_frame) }');
+ add(' .debug_str 0 : { *(.debug_str) }');
+ add(' .debug_loc 0 : { *(.debug_loc) }');
+ add(' .debug_macinfo 0 : { *(.debug_macinfo) }');
+ add(' /* SGI/MIPS DWARF 2 extensions */');
+ add(' .debug_weaknames 0 : { *(.debug_weaknames) }');
+ add(' .debug_funcnames 0 : { *(.debug_funcnames) }');
+ add(' .debug_typenames 0 : { *(.debug_typenames) }');
+ add(' .debug_varnames 0 : { *(.debug_varnames) }');
+ add(' /DISCARD/ : { *(.note.GNU-stack) }');
+ add('}');
+{$endif x86_64}
+
+{$ifdef ARM}
+ if target_info.abi=abi_eabi then
+ begin
+ { from GNU ld (CodeSourcery Sourcery G++ Lite 2007q3-53) 2.18.50.20070820 }
+ add('/* Script for -z combreloc: combine and sort reloc sections */');
+ add('OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm",');
+ add(' "elf32-littlearm")');
+ add('OUTPUT_ARCH(arm)');
+ add('SEARCH_DIR("=/usr/local/lib"); SEARCH_DIR("=/lib"); SEARCH_DIR("=/usr/lib");');
+ add('SECTIONS');
+ add('{');
+ add(' /* Read-only sections, merged into text segment: */');
+ add(' PROVIDE (__executable_start = 0x8000); . = 0x8000 + SIZEOF_HEADERS;');
+ add(' .interp : { *(.interp) }');
+ add(' .note.gnu.build-id : { *(.note.gnu.build-id) }');
+ add(' .hash : { *(.hash) }');
+ add(' .gnu.hash : { *(.gnu.hash) }');
+ add(' .dynsym : { *(.dynsym) }');
+ add(' .dynstr : { *(.dynstr) }');
+ add(' .gnu.version : { *(.gnu.version) }');
+ add(' .gnu.version_d : { *(.gnu.version_d) }');
+ add(' .gnu.version_r : { *(.gnu.version_r) }');
+ add(' .rel.dyn :');
+ add(' {');
+ add(' *(.rel.init)');
+ add(' *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*)');
+ add(' *(.rel.fini)');
+ add(' *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*)');
+ add(' *(.rel.data.rel.ro* .rel.gnu.linkonce.d.rel.ro.*)');
+ add(' *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*)');
+ add(' *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*)');
+ add(' *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*)');
+ add(' *(.rel.ctors)');
+ add(' *(.rel.dtors)');
+ add(' *(.rel.got)');
+ add(' *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*)');
+ add(' }');
+ add(' .rela.dyn :');
+ add(' {');
+ add(' *(.rela.init)');
+ add(' *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)');
+ add(' *(.rela.fini)');
+ add(' *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)');
+ add(' *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)');
+ add(' *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)');
+ add(' *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)');
+ add(' *(.rela.ctors)');
+ add(' *(.rela.dtors)');
+ add(' *(.rela.got)');
+ add(' *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)');
+ add(' }');
+ add(' .rel.plt : { *(.rel.plt) }');
+ add(' .rela.plt : { *(.rela.plt) }');
+ add(' .init :');
+ add(' {');
+ add(' KEEP (*(.init))');
+ add(' } =0');
+ add(' .plt : { *(.plt) }');
+ add(' .text :');
+ add(' {');
+ add(' *(.text .stub .text.* .gnu.linkonce.t.*)');
+ add(' KEEP (*(.text.*personality*))');
+ add(' /* .gnu.warning sections are handled specially by elf32.em. */');
+ add(' *(.gnu.warning)');
+ add(' *(.glue_7t) *(.glue_7) *(.vfp11_veneer)');
+ add(' } =0');
+ add(' .fini :');
+ add(' {');
+ add(' KEEP (*(.fini))');
+ add(' } =0');
+ add(' PROVIDE (__etext = .);');
+ add(' PROVIDE (_etext = .);');
+ add(' PROVIDE (etext = .);');
+ add(' .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }');
+ add(' .rodata1 : { *(.rodata1) }');
+ add(' .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) }');
+ add(' __exidx_start = .;');
+ add(' .ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) }');
+ add(' __exidx_end = .;');
+ add(' .eh_frame_hdr : { *(.eh_frame_hdr) }');
+ add(' .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) }');
+ add(' .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) }');
+ add(' /* Adjust the address for the data segment. We want to adjust up to');
+ add(' the same address within the page on the next page up. */');
+ add(' . = ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1));');
+ add(' /* Exception handling */');
+ add(' .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) }');
+ add(' .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }');
+ add(' /* Thread Local Storage sections */');
+ add(' .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) }');
+ add(' .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }');
+ add(' .preinit_array :');
+ add(' {');
+ add(' PROVIDE_HIDDEN (__preinit_array_start = .);');
+ add(' KEEP (*(.preinit_array))');
+ add(' PROVIDE_HIDDEN (__preinit_array_end = .);');
+ add(' }');
+ add(' .init_array :');
+ add(' {');
+ add(' PROVIDE_HIDDEN (__init_array_start = .);');
+ add(' KEEP (*(SORT(.init_array.*)))');
+ add(' KEEP (*(.init_array))');
+ add(' PROVIDE_HIDDEN (__init_array_end = .);');
+ add(' }');
+ add(' .fini_array :');
+ add(' {');
+ add(' PROVIDE_HIDDEN (__fini_array_start = .);');
+ add(' KEEP (*(.fini_array))');
+ add(' KEEP (*(SORT(.fini_array.*)))');
+ add(' PROVIDE_HIDDEN (__fini_array_end = .);');
+ add(' }');
+ add(' .ctors :');
+ add(' {');
+ add(' /* gcc uses crtbegin.o to find the start of');
+ add(' the constructors, so we make sure it is');
+ add(' first. Because this is a wildcard, it');
+ add(' doesn''t matter if the user does not');
+ add(' actually link against crtbegin.o; the');
+ add(' linker won''t look for a file to match a');
+ add(' wildcard. The wildcard also means that it');
+ add(' doesn''t matter which directory crtbegin.o');
+ add(' is in. */');
+ add(' KEEP (*crtbegin.o(.ctors))');
+ add(' KEEP (*crtbegin?.o(.ctors))');
+ add(' /* We don''t want to include the .ctor section from');
+ add(' the crtend.o file until after the sorted ctors.');
+ add(' The .ctor section from the crtend file contains the');
+ add(' end of ctors marker and it must be last */');
+ add(' KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))');
+ add(' KEEP (*(SORT(.ctors.*)))');
+ add(' KEEP (*(.ctors))');
+ add(' }');
+ add(' .dtors :');
+ add(' {');
+ add(' KEEP (*crtbegin.o(.dtors))');
+ add(' KEEP (*crtbegin?.o(.dtors))');
+ add(' KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))');
+ add(' KEEP (*(SORT(.dtors.*)))');
+ add(' KEEP (*(.dtors))');
+ add(' }');
+ add(' .jcr : { KEEP (*(.jcr)) }');
+ add(' .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*) }');
+ add(' .dynamic : { *(.dynamic) }');
+ add(' .got : { *(.got.plt) *(.got) }');
+ add(' .data :');
+ add(' {');
+ add(' __data_start = . ;');
+ add(' *(.data .data.* .gnu.linkonce.d.*)');
+
+ { extra by FPC }
+ add(' KEEP (*(.fpc .fpc.n_version .fpc.n_links))');
+
+ add(' KEEP (*(.gnu.linkonce.d.*personality*))');
+ add(' SORT(CONSTRUCTORS)');
+ add(' }');
+ add(' .data1 : { *(.data1) }');
+ add(' _edata = .; PROVIDE (edata = .);');
+ add(' __bss_start = .;');
+ add(' __bss_start__ = .;');
+ add(' .bss :');
+ add(' {');
+ add(' *(.dynbss)');
+ add(' *(.bss .bss.* .gnu.linkonce.b.*)');
+ add(' *(COMMON)');
+ add(' /* Align here to ensure that the .bss section occupies space up to');
+ add(' _end. Align after .bss to ensure correct alignment even if the');
+ add(' .bss section disappears because there are no input sections.');
+ add(' FIXME: Why do we need it? When there is no .bss section, we don''t');
+ add(' pad the .data section. */');
+ add(' . = ALIGN(. != 0 ? 32 / 8 : 1);');
+ add(' }');
+ add(' _bss_end__ = . ; __bss_end__ = . ;');
+ add(' . = ALIGN(32 / 8);');
+ add(' . = ALIGN(32 / 8);');
+ add(' __end__ = . ;');
+ add(' _end = .; PROVIDE (end = .);');
+ add(' /* Stabs debugging sections. */');
+ add(' .stab 0 : { *(.stab) }');
+ add(' .stabstr 0 : { *(.stabstr) }');
+ add(' .stab.excl 0 : { *(.stab.excl) }');
+ add(' .stab.exclstr 0 : { *(.stab.exclstr) }');
+ add(' .stab.index 0 : { *(.stab.index) }');
+ add(' .stab.indexstr 0 : { *(.stab.indexstr) }');
+ add(' .comment 0 : { *(.comment) }');
+ add(' /* DWARF debug sections.');
+ add(' Symbols in the DWARF debugging sections are relative to the beginning');
+ add(' of the section so we begin them at 0. */');
+ add(' /* DWARF 1 */');
+ add(' .debug 0 : { *(.debug) }');
+ add(' .line 0 : { *(.line) }');
+ add(' /* GNU DWARF 1 extensions */');
+ add(' .debug_srcinfo 0 : { *(.debug_srcinfo) }');
+ add(' .debug_sfnames 0 : { *(.debug_sfnames) }');
+ add(' /* DWARF 1.1 and DWARF 2 */');
+ add(' .debug_aranges 0 : { *(.debug_aranges) }');
+ add(' .debug_pubnames 0 : { *(.debug_pubnames) }');
+ add(' /* DWARF 2 */');
+ add(' .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }');
+ add(' .debug_abbrev 0 : { *(.debug_abbrev) }');
+ add(' .debug_line 0 : { *(.debug_line) }');
+ add(' .debug_frame 0 : { *(.debug_frame) }');
+ add(' .debug_str 0 : { *(.debug_str) }');
+ add(' .debug_loc 0 : { *(.debug_loc) }');
+ add(' .debug_macinfo 0 : { *(.debug_macinfo) }');
+ add(' /* SGI/MIPS DWARF 2 extensions */');
+ add(' .debug_weaknames 0 : { *(.debug_weaknames) }');
+ add(' .debug_funcnames 0 : { *(.debug_funcnames) }');
+ add(' .debug_typenames 0 : { *(.debug_typenames) }');
+ add(' .debug_varnames 0 : { *(.debug_varnames) }');
+ add(' /* DWARF 3 */');
+ add(' .debug_pubtypes 0 : { *(.debug_pubtypes) }');
+ add(' .debug_ranges 0 : { *(.debug_ranges) }');
+ add(' .stack 0x80000 :');
+ add(' {');
+ add(' _stack = .;');
+ add(' *(.stack)');
+ add(' }');
+ add(' .ARM.attributes 0 : { KEEP (*(.ARM.attributes)) KEEP (*(.gnu.attributes)) }');
+ add(' .note.gnu.arm.ident 0 : { KEEP (*(.note.gnu.arm.ident)) }');
+ add(' /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) }');
+ add('}');
+ end
+ else
+{$endif ARM}
+
+{$ifndef LINKERSCRIPT_INCLUDED}
+ begin
+ {Sections.}
+ add('SECTIONS');
+ add('{');
+ {Read-only sections, merged into text segment:}
+ add(' PROVIDE (__executable_start = 0x010000); . = 0x010000 + SIZEOF_HEADERS;');
+ add(' .interp : { *(.interp) }');
+ add(' .hash : { *(.hash) }');
+ add(' .dynsym : { *(.dynsym) }');
+ add(' .dynstr : { *(.dynstr) }');
+ add(' .gnu.version : { *(.gnu.version) }');
+ add(' .gnu.version_d : { *(.gnu.version_d) }');
+ add(' .gnu.version_r : { *(.gnu.version_r) }');
+ add(' .rel.dyn :');
+ add(' {');
+ add(' *(.rel.init)');
+ add(' *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*)');
+ add(' *(.rel.fini)');
+ add(' *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*)');
+ add(' *(.rel.data.rel.ro*)');
+ add(' *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*)');
+ add(' *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*)');
+ add(' *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*)');
+ add(' *(.rel.got)');
+ add(' *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*)');
+ add(' }');
+ add(' .rela.dyn :');
+ add(' {');
+ add(' *(.rela.init)');
+ add(' *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)');
+ add(' *(.rela.fini)');
+ add(' *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)');
+ add(' *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)');
+ add(' *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)');
+ add(' *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)');
+ add(' *(.rela.got)');
+ add(' *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)');
+ add(' }');
+ add(' .rel.plt : { *(.rel.plt) }');
+ add(' .rela.plt : { *(.rela.plt) }');
+ add(' .init :');
+ add(' {');
+ add(' KEEP (*(.init))');
+ add(' } =0x90909090');
+ add(' .plt : { *(.plt) }');
+ add(' .text :');
+ add(' {');
+ add(' *(.text .stub .text.* .gnu.linkonce.t.*)');
+ add(' KEEP (*(.text.*personality*))');
+ {.gnu.warning sections are handled specially by elf32.em.}
+ add(' *(.gnu.warning)');
+ add(' } =0x90909090');
+ add(' .fini :');
+ add(' {');
+ add(' KEEP (*(.fini))');
+ add(' } =0x90909090');
+ add(' PROVIDE (_etext = .);');
+ add(' .rodata :');
+ add(' {');
+ add(' *(.rodata .rodata.* .gnu.linkonce.r.*)');
+ add(' }');
+ {Adjust the address for the data segment. We want to adjust up to
+ the same address within the page on the next page up.}
+ add(' . = ALIGN (0x1000) - ((0x1000 - .) & (0x1000 - 1));');
+ add(' .dynamic : { *(.dynamic) }');
+ add(' .got : { *(.got) }');
+ add(' .got.plt : { *(.got.plt) }');
+ add(' .data :');
+ add(' {');
+ add(' *(.data .data.* .gnu.linkonce.d.*)');
+ add(' KEEP (*(.fpc .fpc.n_version .fpc.n_links))');
+ add(' KEEP (*(.gnu.linkonce.d.*personality*))');
+ add(' }');
+ add(' PROVIDE (_edata = .);');
+ add(' PROVIDE (edata = .);');
+ {$ifdef zsegment_threadvars}
+ add(' _z = .;');
+ add(' .threadvar 0 : AT (_z) { *(.threadvar .threadvar.* .gnu.linkonce.tv.*) }');
+ add(' PROVIDE (_threadvar_size = SIZEOF(.threadvar));');
+ add(' . = _z + SIZEOF (.threadvar);');
+ {$else}
+ add(' .threadvar : { *(.threadvar .threadvar.* .gnu.linkonce.tv.*) }');
+ {$endif}
+ add(' __bss_start = .;');
+ add(' .bss :');
+ add(' {');
+ add(' *(.dynbss)');
+ add(' *(.bss .bss.* .gnu.linkonce.b.*)');
+ add(' *(COMMON)');
+ {Align here to ensure that the .bss section occupies space up to
+ _end. Align after .bss to ensure correct alignment even if the
+ .bss section disappears because there are no input sections.}
+ add(' . = ALIGN(32 / 8);');
+ add(' }');
+ add(' . = ALIGN(32 / 8);');
+ add(' PROVIDE (_end = .);');
+ add(' PROVIDE (end = .);');
+ {Stabs debugging sections.}
+ add(' .stab 0 : { *(.stab) }');
+ add(' .stabstr 0 : { *(.stabstr) }');
+ add('}');
+ end;
+{$endif LINKERSCRIPT_INCLUDED}
+ { Write and Close response }
+ writetodisk;
+ Free;
+ end;
+
+ WriteResponseFile:=True;
+end;
+
+
+function TLinkerLinux.MakeExecutable:boolean;
+var
+ i : longint;
+ binstr,
+ cmdstr : TCmdStr;
+ success : boolean;
+ DynLinkStr : string;
+ GCSectionsStr,
+ StaticStr,
+ StripStr : string[40];
+begin
+ if not(cs_link_nolink in current_settings.globalswitches) then
+ Message1(exec_i_linking,current_module.exefilename^);
+
+{ Create some replacements }
+ StaticStr:='';
+ StripStr:='';
+ GCSectionsStr:='';
+ DynLinkStr:='';
+ if (cs_link_staticflag in current_settings.globalswitches) then
+ StaticStr:='-static';
+ if (cs_link_strip in current_settings.globalswitches) and
+ not(cs_link_separate_dbg_file in current_settings.globalswitches) then
+ StripStr:='-s';
+ if (cs_link_map in current_settings.globalswitches) then
+ StripStr:='-Map '+maybequoted(ChangeFileExt(current_module.exefilename^,'.map'));
+ if create_smartlink_sections then
+ GCSectionsStr:='--gc-sections';
+ If (cs_profile in current_settings.moduleswitches) or
+ ((Info.DynamicLinker<>'') and (not SharedLibFiles.Empty)) then
+ begin
+ DynLinkStr:='--dynamic-linker='+Info.DynamicLinker;
+ if cshared then
+ DynLinkStr:=DynLinkStr+' --shared ';
+ if rlinkpath<>'' then
+ DynLinkStr:=DynLinkStr+' --rpath-link '+rlinkpath;
+ End;
+
+{ Write used files and libraries }
+ WriteResponseFile(false);
+
+{ Call linker }
+ SplitBinCmd(Info.ExeCmd[1],binstr,cmdstr);
+ Replace(cmdstr,'$EXE',maybequoted(current_module.exefilename^));
+ Replace(cmdstr,'$OPT',Info.ExtraOptions);
+ Replace(cmdstr,'$RES',maybequoted(outputexedir+Info.ResName));
+ Replace(cmdstr,'$STATIC',StaticStr);
+ Replace(cmdstr,'$STRIP',StripStr);
+ Replace(cmdstr,'$GCSECTIONS',GCSectionsStr);
+ Replace(cmdstr,'$DYNLINK',DynLinkStr);
+
+ { create dynamic symbol table? }
+ if HasExports then
+ cmdstr:=cmdstr+' -E';
+
+ success:=DoExec(FindUtil(utilsprefix+BinStr),CmdStr,true,false);
+
+ { Create external .dbg file with debuginfo }
+ if success and (cs_link_separate_dbg_file in current_settings.globalswitches) then
+ begin
+ for i:=1 to 3 do
+ begin
+ SplitBinCmd(Info.ExtDbgCmd[i],binstr,cmdstr);
+ Replace(cmdstr,'$EXE',maybequoted(current_module.exefilename^));
+ Replace(cmdstr,'$DBGFN',maybequoted(extractfilename(current_module.dbgfilename^)));
+ Replace(cmdstr,'$DBG',maybequoted(current_module.dbgfilename^));
+ success:=DoExec(FindUtil(utilsprefix+BinStr),CmdStr,true,false);
+ if not success then
+ break;
+ end;
+ end;
+
+ { Remove ReponseFile }
+ if (success) and not(cs_link_nolink in current_settings.globalswitches) then
+ DeleteFile(outputexedir+Info.ResName);
+
+ MakeExecutable:=success; { otherwise a recursive call to link method }
+end;
+
+
+Function TLinkerLinux.MakeSharedLibrary:boolean;
+var
+ InitStr,
+ FiniStr,
+ SoNameStr : string[80];
+ binstr,
+ cmdstr : TCmdStr;
+ success : boolean;
+begin
+ MakeSharedLibrary:=false;
+ if not(cs_link_nolink in current_settings.globalswitches) then
+ Message1(exec_i_linking,current_module.sharedlibfilename^);
+
+{ Write used files and libraries }
+ WriteResponseFile(true);
+
+ { Create some replacements }
+ { note: linux does not use exportlib.initname/fininame due to the custom startup code }
+ InitStr:='-init FPC_SHARED_LIB_START';
+ FiniStr:='-fini FPC_LIB_EXIT';
+ SoNameStr:='-soname '+ExtractFileName(current_module.sharedlibfilename^);
+
+{ Call linker }
+ SplitBinCmd(Info.DllCmd[1],binstr,cmdstr);
+ Replace(cmdstr,'$EXE',maybequoted(current_module.sharedlibfilename^));
+ Replace(cmdstr,'$OPT',Info.ExtraOptions);
+ Replace(cmdstr,'$RES',maybequoted(outputexedir+Info.ResName));
+ Replace(cmdstr,'$INIT',InitStr);
+ Replace(cmdstr,'$FINI',FiniStr);
+ Replace(cmdstr,'$SONAME',SoNameStr);
+ success:=DoExec(FindUtil(utilsprefix+binstr),cmdstr,true,false);
+
+{ Strip the library ? }
+ if success and (cs_link_strip in current_settings.globalswitches) then
+ begin
+ { only remove non global symbols and debugging info for a library }
+ Info.DllCmd[2]:='strip --discard-all --strip-debug $EXE';
+ SplitBinCmd(Info.DllCmd[2],binstr,cmdstr);
+ Replace(cmdstr,'$EXE',maybequoted(current_module.sharedlibfilename^));
+ success:=DoExec(FindUtil(utilsprefix+binstr),cmdstr,true,false);
+ end;
+
+{ Remove ReponseFile }
+ if (success) and not(cs_link_nolink in current_settings.globalswitches) then
+ DeleteFile(outputexedir+Info.ResName);
+
+ MakeSharedLibrary:=success; { otherwise a recursive call to link method }
+end;
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+initialization
+{$ifdef i386}
+ RegisterExternalLinker(system_i386_linux_info,TLinkerLinux);
+ RegisterImport(system_i386_linux,timportliblinux);
+ RegisterExport(system_i386_linux,texportliblinux);
+ RegisterTarget(system_i386_linux_info);
+
+ RegisterExternalLinker(system_x86_6432_linux_info,TLinkerLinux);
+ RegisterImport(system_x86_6432_linux,timportliblinux);
+ RegisterExport(system_x86_6432_linux,texportliblinux);
+ RegisterTarget(system_x86_6432_linux_info);
+{$endif i386}
+{$ifdef m68k}
+ RegisterExternalLinker(system_m68k_linux_info,TLinkerLinux);
+ RegisterImport(system_m68k_linux,timportliblinux);
+ RegisterExport(system_m68k_linux,texportliblinux);
+ RegisterTarget(system_m68k_linux_info);
+{$endif m68k}
+{$ifdef powerpc}
+ RegisterExternalLinker(system_powerpc_linux_info,TLinkerLinux);
+ RegisterImport(system_powerpc_linux,timportliblinux);
+ RegisterExport(system_powerpc_linux,texportliblinux);
+ RegisterTarget(system_powerpc_linux_info);
+{$endif powerpc}
+{$ifdef powerpc64}
+ RegisterExternalLinker(system_powerpc64_linux_info,TLinkerLinux);
+ RegisterImport(system_powerpc64_linux,timportliblinux);
+ RegisterExport(system_powerpc64_linux,texportliblinux);
+ RegisterTarget(system_powerpc64_linux_info);
+{$endif powerpc64}
+{$ifdef alpha}
+ RegisterExternalLinker(system_alpha_linux_info,TLinkerLinux);
+ RegisterImport(system_alpha_linux,timportliblinux);
+ RegisterExport(system_alpha_linux,texportliblinux);
+ RegisterTarget(system_alpha_linux_info);
+{$endif alpha}
+{$ifdef x86_64}
+ RegisterExternalLinker(system_x86_64_linux_info,TLinkerLinux);
+ RegisterImport(system_x86_64_linux,timportliblinux);
+ RegisterExport(system_x86_64_linux,texportliblinux);
+ RegisterTarget(system_x86_64_linux_info);
+{$endif x86_64}
+{$ifdef SPARC}
+ RegisterExternalLinker(system_sparc_linux_info,TLinkerLinux);
+ RegisterImport(system_SPARC_linux,timportliblinux);
+ RegisterExport(system_SPARC_linux,texportliblinux);
+ RegisterTarget(system_SPARC_linux_info);
+{$endif SPARC}
+{$ifdef ARM}
+ RegisterExternalLinker(system_arm_linux_info,TLinkerLinux);
+ RegisterImport(system_arm_linux,timportliblinux);
+ RegisterExport(system_arm_linux,texportliblinux);
+ RegisterTarget(system_arm_linux_info);
+{$endif ARM}
+{$ifdef MIPS}
+{$ifdef MIPSEL}
+ RegisterExternalLinker(system_mipsel_linux_info,TLinkerLinux);
+ RegisterImport(system_mipsel_linux,timportliblinux);
+ RegisterExport(system_mipsel_linux,texportliblinux);
+ RegisterTarget(system_mipsel_linux_info);
+{$else MIPS}
+ RegisterExternalLinker(system_mips_linux_info,TLinkerLinux);
+ RegisterImport(system_mips_linux,timportliblinux);
+ RegisterExport(system_mips_linux,texportliblinux);
+ RegisterTarget(system_mips_linux_info);
+{$endif MIPSEL}
+{$endif MIPS}
+ RegisterRes(res_elf_info,TWinLikeResourceFile);
+end.
diff --git a/closures/compiler/systems/t_macos.pas b/closures/compiler/systems/t_macos.pas
new file mode 100644
index 0000000000..1e195b4c42
--- /dev/null
+++ b/closures/compiler/systems/t_macos.pas
@@ -0,0 +1,255 @@
+{
+ Copyright (c) 2001-2002 by Peter Vreman
+
+ This unit implements support import,export,link routines for MacOS.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit t_macos;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ import,symsym,symdef,link;
+
+ type
+ timportlibmacos=class(timportlib)
+ procedure generatelib;override;
+ end;
+
+ tlinkermpw=class(texternallinker)
+ private
+ Function WriteResponseFile(isdll:boolean) : Boolean;
+ public
+ constructor Create;override;
+ procedure SetDefaultInfo;override;
+ function MakeExecutable:boolean;override;
+ end;
+
+implementation
+
+ uses
+ SysUtils,
+ cutils,cfileutl,cclasses,
+ globtype,globals,systems,verbose,script,fmodule,i_macos,
+ ogbase,
+ symconst;
+
+{*****************************************************************************
+ TIMPORTLIBMACOS
+*****************************************************************************}
+
+ procedure timportlibmacos.generatelib;
+ var
+ i : longint;
+ ImportLibrary : TImportLibrary;
+ begin
+ for i:=0 to current_module.ImportLibraryList.Count-1 do
+ begin
+ ImportLibrary:=TImportLibrary(current_module.ImportLibraryList[i]);
+ current_module.linkothersharedlibs.add(ImportLibrary.Name,link_always);
+ end;
+ end;
+
+{*****************************************************************************
+ TLINKERMPW
+*****************************************************************************}
+
+Constructor TLinkerMPW.Create;
+begin
+ Inherited Create;
+ //LibrarySearchPath.AddPath(sysrootpath,'/lib;/usr/lib;/usr/X11R6/lib',true);
+end;
+
+
+procedure TLinkerMPW.SetDefaultInfo;
+
+begin
+ with Info do
+ begin
+ ExeCmd[1]:='Execute $RES'; {The link.res file contains the whole link command.}
+ //ExeCmd[1]:='PPCLink $OPT $DYNLINK $STATIC $STRIP -tocdataref off -dead on -o $EXE -@filelist $RES';
+ //DllCmd[1]:='PPCLink $OPT $INIT $FINI $SONAME -shared -o $EXE -@filelist $RES';
+ end;
+end;
+
+
+Function TLinkerMPW.WriteResponseFile(isdll:boolean) : Boolean;
+Var
+ linkres : TLinkRes;
+ s,heapsizestr: string;
+
+begin
+ WriteResponseFile:=False;
+ { Open link.res file }
+ linkRes:=TLinkRes.Create(outputexedir+Info.ResName);
+
+ with linkRes do
+ begin
+ {#182 is escape char in MPW (analog to backslash in unix). The space}
+ {ensures there is whitespace separating items.}
+ Add('PPCLink '#182);
+
+ { Add MPW standard libraries}
+ if apptype = app_cui then
+ Add('"{PPCLibraries}PPCSIOW.o" '#182);
+
+ {Even GUI apps must link to PPCToolLibs, because of the System unit
+ which can be used by MPW tools as well as by GUI apps.}
+ Add('"{PPCLibraries}PPCToolLibs.o" '#182);
+ Add('"{SharedLibraries}InterfaceLib" '#182);
+ Add('"{SharedLibraries}StdCLib" '#182);
+ Add('"{SharedLibraries}MathLib" '#182);
+ Add('"{PPCLibraries}StdCRuntime.o" '#182);
+ Add('"{PPCLibraries}PPCCRuntime.o" '#182);
+
+ {Add main objectfiles}
+ while not ObjectFiles.Empty do
+ begin
+ s:=ObjectFiles.GetFirst;
+ if s<>'' then
+ Add(s+' '#182);
+ end;
+
+ {Add last lines of the link command}
+ if apptype = app_tool then
+ Add('-t "MPST" -c "MPS " '#182);
+
+ if apptype = app_cui then {If SIOW, to avoid some warnings.}
+ Add('-ignoredups __start -ignoredups .__start -ignoredups main -ignoredups .main -ignoredups qd '#182);
+
+ Add('-tocdataref off -sym on -dead on -o '+ ScriptFixFileName(current_module.exefilename^));
+
+ Add('Exit If "{Status}" != 0');
+
+ if heapsize = 0 then
+ heapsizestr:= HexStr(384000, 8)
+ else
+ heapsizestr:= HexStr(heapsize, 8);
+
+ {Add a SIZE resource on the fly. It controls:
+ * backgrounding is enabled, to facilitate debuging with Power Mac Debugger
+ * it is signaled it is a 32 bit app. (perhaps not nessecary on PowerPC)
+ * heapsize }
+ if apptype <> app_tool then
+ begin
+ Add('Echo "data ''SIZE'' (-1) '#182'{ $'#182'"1080 ' + heapsizestr + ' ' + heapsizestr +
+ #182'" '#182'};" | Rez -a -o ' + ScriptFixFileName(current_module.exefilename^));
+ Add('Exit If "{Status}" != 0');
+ end;
+
+ {Add mac resources}
+ if apptype = app_cui then
+ begin
+ Add('Rez -a "{RIncludes}"SIOW.r -o ' + ScriptFixFileName(current_module.exefilename^));
+ Add('Exit If "{Status}" != 0');
+ end;
+
+ while not (current_module.ResourceFiles.Empty) do
+ begin
+ s := Current_module.ResourceFiles.GetFirst;
+ if Copy(s,Length(s)-1,Length(s)) = '.r' then
+ Add('Rez -a ' + s + ' -o ' + ScriptFixFileName(current_module.exefilename^))
+ else
+ Add('DeRez ' + s + ' | Rez -a -o ' + ScriptFixFileName(current_module.exefilename^));
+ Add('Exit If "{Status}" != 0');
+ end;
+
+ end;
+
+ { Write and Close response }
+ linkres.writetodisk;
+ linkres.Free;
+
+ WriteResponseFile:=True;
+end;
+
+
+function TLinkerMPW.MakeExecutable:boolean;
+var
+ binstr,
+ cmdstr : TCmdStr;
+ success : boolean;
+ DynLinkStr : string[60];
+ StaticStr,
+ StripStr : string[40];
+begin
+ //TODO Only external link in MPW is possible, otherwise yell.
+
+ if not(cs_link_nolink in current_settings.globalswitches) then
+ Message1(exec_i_linking,current_module.exefilename^);
+
+{ Create some replacements }
+ StripStr:='';
+ StaticStr:='';
+ DynLinkStr:='';
+(*
+ if (cs_link_staticflag in current_settings.globalswitches) then
+ StaticStr:='-static';
+ if (cs_link_strip in current_settings.globalswitches) then
+ StripStr:='-s';
+ If (cs_profile in current_settings.moduleswitches) or
+ ((Info.DynamicLinker<>'') and (not SharedLibFiles.Empty)) then
+ DynLinkStr:='-dynamic-linker='+Info.DynamicLinker;
+*)
+
+{ Prepare linking }
+ SplitBinCmd(Info.ExeCmd[1],binstr,cmdstr);
+ Replace(cmdstr,'$EXE',maybequoted(ScriptFixFileName(current_module.exefilename^)));
+ Replace(cmdstr,'$OPT',Info.ExtraOptions);
+ Replace(cmdstr,'$RES',maybequoted(ScriptFixFileName(outputexedir+Info.ResName)));
+ Replace(cmdstr,'$STATIC',StaticStr);
+ Replace(cmdstr,'$STRIP',StripStr);
+ Replace(cmdstr,'$DYNLINK',DynLinkStr);
+
+ WriteResponseFile(false);
+
+ success:= true;
+ if cs_link_on_target in current_settings.globalswitches then
+ success:=DoExec('SetFile', ' -c ''MPS '' -t ''TEXT'' ' +
+ ScriptFixFileName(outputexedir+Info.ResName),true,false);
+
+{ Call linker }
+ if success then
+ success:=DoExec('Execute',CmdStr,true,false);
+
+{ Remove ReponseFile }
+ if (success) and not(cs_link_nolink in current_settings.globalswitches) then
+ DeleteFile(outputexedir+Info.ResName);
+
+ MakeExecutable:=success; { otherwise a recursive call to link method }
+end;
+
+
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+initialization
+{$ifdef m68k}
+ RegisterTarget(system_m68k_macos_info);
+ RegisterImport(system_m68k_macos,timportlibmacos);
+{$endif m68k}
+{$ifdef powerpc}
+ RegisterExternalLinker(system_powerpc_macos_info,TLinkerMPW);
+ RegisterTarget(system_powerpc_macos_info);
+ RegisterImport(system_powerpc_macos,timportlibmacos);
+{$endif powerpc}
+end.
diff --git a/closures/compiler/systems/t_morph.pas b/closures/compiler/systems/t_morph.pas
new file mode 100644
index 0000000000..8409ba1eeb
--- /dev/null
+++ b/closures/compiler/systems/t_morph.pas
@@ -0,0 +1,260 @@
+{
+ Copyright (c) 2004 by Free Pascal Development Team
+
+ This unit implements support import, export, link routines
+ for the MorphOS (PowerPC) target
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit t_morph;
+
+{$i fpcdefs.inc}
+
+interface
+
+
+implementation
+
+ uses
+ SysUtils,
+ cutils,cfileutl,cclasses,
+ globtype,globals,systems,verbose,script,fmodule,i_morph,link;
+
+ type
+ PlinkerMorphOS=^TlinkerMorphOS;
+ TlinkerMorphOS=class(texternallinker)
+ private
+ Function WriteResponseFile(isdll:boolean) : Boolean;
+ public
+ constructor Create; override;
+ procedure SetDefaultInfo; override;
+ function MakeExecutable:boolean; override;
+ end;
+
+
+{****************************************************************************
+ TLinkerMorphOS
+****************************************************************************}
+
+Constructor TLinkerMorphOS.Create;
+begin
+ Inherited Create;
+ { allow duplicated libs (PM) }
+ SharedLibFiles.doubles:=true;
+ StaticLibFiles.doubles:=true;
+end;
+
+
+procedure TLinkerMorphOS.SetDefaultInfo;
+begin
+ with Info do
+ begin
+ if (cs_link_on_target in current_settings.globalswitches) then
+ begin
+ ExeCmd[1]:='ld $OPT -o $EXE $RES';
+ ExeCmd[2]:='strip --strip-unneeded --remove-section .comment $EXE';
+ end
+ else
+ begin
+ ExeCmd[1]:='fpcvlink -b elf32amiga $OPT $STRIP -o $EXE -T $RES';
+ end;
+ end;
+end;
+
+
+Function TLinkerMorphOS.WriteResponseFile(isdll:boolean) : Boolean;
+Var
+ linkres : TLinkRes;
+ i : longint;
+ HPath : TCmdStrListItem;
+ s : string;
+ linklibc : boolean;
+begin
+ WriteResponseFile:=False;
+
+ { Open link.res file }
+ LinkRes:=TLinkRes.Create(outputexedir+Info.ResName);
+
+ { Write path to search libraries }
+ HPath:=TCmdStrListItem(current_module.locallibrarysearchpath.First);
+ while assigned(HPath) do
+ begin
+ s:=HPath.Str;
+ if (cs_link_on_target in current_settings.globalswitches) then
+ s:=ScriptFixFileName(s);
+ LinkRes.Add('-L'+s);
+ HPath:=TCmdStrListItem(HPath.Next);
+ end;
+ HPath:=TCmdStrListItem(LibrarySearchPath.First);
+ while assigned(HPath) do
+ begin
+ s:=HPath.Str;
+ if s<>'' then
+ LinkRes.Add('SEARCH_DIR('+Unix2AmigaPath(maybequoted(s))+')');
+ HPath:=TCmdStrListItem(HPath.Next);
+ end;
+
+ LinkRes.Add('INPUT (');
+ { add objectfiles, start with prt0 always }
+ s:=FindObjectFile('prt0','',false);
+ LinkRes.AddFileName(s);
+ while not ObjectFiles.Empty do
+ begin
+ s:=ObjectFiles.GetFirst;
+ if s<>'' then
+ begin
+ { vlink doesn't use SEARCH_DIR for object files }
+ if not(cs_link_on_target in current_settings.globalswitches) then
+ s:=FindObjectFile(s,'',false);
+ LinkRes.AddFileName(Unix2AmigaPath(maybequoted(s)));
+ end;
+ end;
+
+ { Write staticlibraries }
+ if not StaticLibFiles.Empty then
+ begin
+ { vlink doesn't need, and doesn't support GROUP }
+ if (cs_link_on_target in current_settings.globalswitches) then
+ begin
+ LinkRes.Add(')');
+ LinkRes.Add('GROUP(');
+ end;
+ while not StaticLibFiles.Empty do
+ begin
+ S:=StaticLibFiles.GetFirst;
+ LinkRes.AddFileName(Unix2AmigaPath(maybequoted(s)));
+ end;
+ end;
+
+ if (cs_link_on_target in current_settings.globalswitches) then
+ begin
+ LinkRes.Add(')');
+
+ { Write sharedlibraries like -l<lib>, also add the needed dynamic linker
+ here to be sure that it gets linked this is needed for glibc2 systems (PFV) }
+ linklibc:=false;
+ while not SharedLibFiles.Empty do
+ begin
+ S:=SharedLibFiles.GetFirst;
+ if s<>'c' then
+ begin
+ i:=Pos(target_info.sharedlibext,S);
+ if i>0 then
+ Delete(S,i,255);
+ LinkRes.Add('-l'+s);
+ end
+ else
+ begin
+ LinkRes.Add('-l'+s);
+ linklibc:=true;
+ end;
+ end;
+ { be sure that libc&libgcc is the last lib }
+ if linklibc then
+ begin
+ LinkRes.Add('-lc');
+ LinkRes.Add('-lgcc');
+ end;
+ end
+ else
+ begin
+ while not SharedLibFiles.Empty do
+ begin
+ S:=SharedLibFiles.GetFirst;
+ LinkRes.Add('lib'+s+target_info.staticlibext);
+ end;
+ LinkRes.Add(')');
+ end;
+
+
+{ Write and Close response }
+ linkres.writetodisk;
+ linkres.free;
+
+ WriteResponseFile:=True;
+
+end;
+
+
+function TLinkerMorphOS.MakeExecutable:boolean;
+var
+ binstr,
+ cmdstr : TCmdStr;
+ success : boolean;
+ StripStr: string[40];
+begin
+
+ if not(cs_link_nolink in current_settings.globalswitches) then
+ Message1(exec_i_linking,current_module.exefilename^);
+
+ if not (cs_link_on_target in current_settings.globalswitches) then
+ begin
+ StripStr:='';
+ if (cs_link_strip in current_settings.globalswitches) then
+ StripStr:='-s -P __abox__';
+ end;
+
+{ Write used files and libraries }
+ WriteResponseFile(false);
+
+{ Call linker }
+ SplitBinCmd(Info.ExeCmd[1],binstr,cmdstr);
+ Replace(cmdstr,'$OPT',Info.ExtraOptions);
+ if not(cs_link_on_target in current_settings.globalswitches) then
+ begin
+ Replace(cmdstr,'$EXE',Unix2AmigaPath(maybequoted(ScriptFixFileName(current_module.exefilename^))));
+ Replace(cmdstr,'$RES',Unix2AmigaPath(maybequoted(ScriptFixFileName(outputexedir+Info.ResName))));
+ Replace(cmdstr,'$STRIP',StripStr);
+ end
+ else
+ begin
+ Replace(cmdstr,'$EXE',maybequoted(ScriptFixFileName(current_module.exefilename^)));
+ Replace(cmdstr,'$RES',maybequoted(ScriptFixFileName(outputexedir+Info.ResName)));
+ end;
+ success:=DoExec(FindUtil(BinStr),cmdstr,true,false);
+
+{ Stripping Enabled? }
+ { For MorphOS a separate strip command is needed, to avoid stripping }
+ { __abox__ symbol, which is required to be present in current MorphOS }
+ { executables. }
+ if (cs_link_on_target in current_settings.globalswitches) then
+ begin
+ if success and (cs_link_strip in current_settings.globalswitches) then
+ begin
+ SplitBinCmd(Info.ExeCmd[2],binstr,cmdstr);
+ Replace(cmdstr,'$EXE',maybequoted(current_module.exefilename^));
+ success:=DoExec(FindUtil(utilsprefix+binstr),cmdstr,true,false);
+ end;
+ end;
+
+{ Remove ReponseFile }
+ if (success) and not(cs_link_nolink in current_settings.globalswitches) then
+ DeleteFile(outputexedir+Info.ResName);
+
+ MakeExecutable:=success; { otherwise a recursive call to link method }
+
+end;
+
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+initialization
+ RegisterExternalLinker(system_powerpc_morphos_info,TLinkerMorphOS);
+ RegisterTarget(system_powerpc_morphos_info);
+end.
diff --git a/closures/compiler/systems/t_nativent.pas b/closures/compiler/systems/t_nativent.pas
new file mode 100644
index 0000000000..e4b8fc1329
--- /dev/null
+++ b/closures/compiler/systems/t_nativent.pas
@@ -0,0 +1,94 @@
+{
+ Copyright (c) 2009 by Sven Barth
+
+ This unit implements support import,export,link routines
+ for the Native NT Target
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ ****************************************************************************
+}
+unit t_nativent;
+
+{$i fpcdefs.inc}
+
+interface
+
+
+implementation
+
+ uses
+ SysUtils,
+ cutils,
+ ogbase,ogcoff,
+ globtype,globals,systems,verbose,
+ import,export,link,t_win,i_nativent;
+
+
+ type
+ TImportLibNativeNT=class(TImportLibWin)
+ end;
+
+ TExportLibNativeNT=class(TExportLibWin)
+ end;
+
+ TInternalLinkerNativeNT = class(TInternalLinkerWin)
+ constructor create;override;
+ procedure ConcatEntryName; override;
+ end;
+
+{****************************************************************************
+ TInternalLinkerNativeNT
+****************************************************************************}
+
+ constructor TInternalLinkerNativeNT.create;
+ begin
+ inherited create;
+ CExeoutput:=TPECoffexeoutput;
+ CObjInput:=TPECoffObjInput;
+ end;
+
+ procedure TInternalLinkerNativeNT.ConcatEntryName;
+ begin
+ with LinkScript do
+ begin
+ if IsSharedLibrary then
+ begin
+ // for now we use {$apptype native} for kernel mode code
+ if apptype=app_native then
+ Concat('ENTRYNAME _NtDriverEntry')
+ else
+ Concat('ENTRYNAME _DLLMainStartup')
+ end
+ else
+ Concat('ENTRYNAME _NtProcessStartup');
+ end;
+ end;
+
+
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+initialization
+{$ifdef i386}
+ { NativeNT }
+ RegisterInternalLinker(system_i386_nativent_info,TInternalLinkerNativeNT);
+ RegisterImport(system_i386_nativent,TImportLibNativeNT);
+ RegisterExport(system_i386_nativent,TExportLibNativeNT);
+// RegisterRes(res_gnu_windres_info,TWinLikeResourceFile);
+ RegisterTarget(system_i386_nativent_info);
+{$endif i386}
+end.
diff --git a/closures/compiler/systems/t_nds.pas b/closures/compiler/systems/t_nds.pas
new file mode 100644
index 0000000000..93350dd8b4
--- /dev/null
+++ b/closures/compiler/systems/t_nds.pas
@@ -0,0 +1,780 @@
+{
+ This unit implements support import,export,link routines
+ for the (arm) Nintendo DS target
+
+ Copyright (c) 2001-2002 by Peter Vreman
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit t_nds;
+
+{$i fpcdefs.inc}
+
+interface
+
+
+implementation
+
+ uses
+ aasmbase,
+ SysUtils,
+ cutils,cfileutl,cclasses,
+ globtype,globals,systems,verbose,script,fmodule,i_nds,link;
+
+ type
+ TlinkerNDS=class(texternallinker)
+ private
+ Function WriteResponseFile: Boolean;
+ public
+ constructor Create; override;
+ procedure SetDefaultInfo; override;
+ function MakeExecutable:boolean; override;
+ end;
+
+
+
+{*****************************************************************************
+ TLINKERNDS
+*****************************************************************************}
+
+Constructor TLinkerNDS.Create;
+begin
+ Inherited Create;
+ SharedLibFiles.doubles:=true;
+ StaticLibFiles.doubles:=true;
+ // set arm9 as default apptype
+ if (apptype <> app_arm9) or (apptype <> app_arm7) then
+ apptype := app_arm9;
+end;
+
+
+procedure TLinkerNDS.SetDefaultInfo;
+begin
+ with Info do
+ begin
+ ExeCmd[1]:='ld -g $OPT $DYNLINK $STATIC $GCSECTIONS $STRIP -L. -o $EXE -T $RES';
+ end;
+end;
+
+
+Function TLinkerNDS.WriteResponseFile: Boolean;
+Var
+ linkres : TLinkRes;
+ i : longint;
+ HPath : TCmdStrListItem;
+ s,s1,s2 : TCmdStr;
+ prtobj,
+ cprtobj : string[80];
+ linklibc,
+ linklibgcc : boolean;
+ found1,
+ found2 : boolean;
+begin
+ WriteResponseFile:=False;
+ linklibc:=(SharedLibFiles.Find('c')<>nil);
+ linklibgcc:=(SharedLibFiles.Find('gcc')<>nil);
+
+ case apptype of
+ app_arm9:
+ begin
+ prtobj:='prt09';
+ cprtobj:='cprt09';
+ end;
+ app_arm7:
+ begin
+ prtobj:='prt07';
+ cprtobj:='cprt07';
+ end;
+ end;
+
+ if (linklibc or linklibgcc) then
+ prtobj:=cprtobj;
+
+ { Open link.res file }
+ LinkRes:=TLinkRes.Create(outputexedir+Info.ResName);
+
+ { Write path to search libraries }
+ HPath:=TCmdStrListItem(current_module.locallibrarysearchpath.First);
+ while assigned(HPath) do
+ begin
+ s:=HPath.Str;
+ if (cs_link_on_target in current_settings.globalswitches) then
+ s:=ScriptFixFileName(s);
+ LinkRes.Add('-L'+s);
+ HPath:=TCmdStrListItem(HPath.Next);
+ end;
+ HPath:=TCmdStrListItem(LibrarySearchPath.First);
+ while assigned(HPath) do
+ begin
+ s:=HPath.Str;
+ if s<>'' then
+ LinkRes.Add('SEARCH_DIR('+(maybequoted(s))+')');
+ HPath:=TCmdStrListItem(HPath.Next);
+ end;
+
+ LinkRes.Add('INPUT (');
+ { add objectfiles, start with prt0 always }
+ if prtobj<>'' then
+ s:=FindObjectFile(prtobj,'',false);
+ LinkRes.AddFileName(s);
+ { try to add crti and crtbegin if linking to C }
+ if linklibc then
+ begin
+ if librarysearchpath.FindFile('crti.o',false,s) then
+ LinkRes.AddFileName(s);
+ end;
+ if linklibgcc then
+ begin
+ if librarysearchpath.FindFile('crtbegin.o',false,s) then
+ LinkRes.AddFileName(s);
+ end;
+ while not ObjectFiles.Empty do
+ begin
+ s:=ObjectFiles.GetFirst;
+ if s<>'' then
+ begin
+ { vlink doesn't use SEARCH_DIR for object files }
+ if not(cs_link_on_target in current_settings.globalswitches) then
+ s:=FindObjectFile(s,'',false);
+ LinkRes.AddFileName((maybequoted(s)));
+ end;
+ end;
+
+ { Write staticlibraries }
+ if not StaticLibFiles.Empty then
+ begin
+ { vlink doesn't need, and doesn't support GROUP }
+ if (cs_link_on_target in current_settings.globalswitches) then
+ begin
+ LinkRes.Add(')');
+ LinkRes.Add('GROUP(');
+ end;
+ while not StaticLibFiles.Empty do
+ begin
+ S:=StaticLibFiles.GetFirst;
+ LinkRes.AddFileName((maybequoted(s)));
+ end;
+ end;
+
+ if (cs_link_on_target in current_settings.globalswitches) then
+ begin
+ LinkRes.Add(')');
+
+ { Write sharedlibraries like -l<lib>, also add the needed dynamic linker
+ here to be sure that it gets linked this is needed for glibc2 systems (PFV) }
+ linklibc:=false;
+ linklibgcc:=false;
+ while not SharedLibFiles.Empty do
+ begin
+ S:=SharedLibFiles.GetFirst;
+ if s<>'c' then
+ begin
+ i:=Pos(target_info.sharedlibext,S);
+ if i>0 then
+ Delete(S,i,255);
+ LinkRes.Add('-l'+s);
+ end
+ else
+ begin
+ LinkRes.Add('-l'+s);
+ linklibc:=true;
+ linklibgcc:=true;
+ end;
+ end;
+ { be sure that libc&libgcc is the last lib }
+ if linklibgcc then
+ begin
+ LinkRes.Add('-lgcc');
+ end;
+ if linklibc then
+ begin
+ LinkRes.Add('-lc');
+ end;
+ end
+ else
+ begin
+ while not SharedLibFiles.Empty do
+ begin
+ S:=SharedLibFiles.GetFirst;
+ LinkRes.Add('lib'+s+target_info.staticlibext);
+ end;
+ LinkRes.Add(')');
+ end;
+
+ { objects which must be at the end }
+ if linklibgcc then
+ begin
+ found1:=librarysearchpath.FindFile('crtend.o',false,s1);
+ if found1 then
+ begin
+ LinkRes.Add('INPUT(');
+ if found1 then
+ LinkRes.AddFileName(s1);
+ LinkRes.Add(')');
+ end;
+ end;
+ if linklibc then
+ begin
+ found2:=librarysearchpath.FindFile('crtn.o',false,s2);
+ if found2 then
+ begin
+ LinkRes.Add('INPUT(');
+ if found2 then
+ LinkRes.AddFileName(s2);
+ LinkRes.Add(')');
+ end;
+ end;
+
+ with linkres do
+ begin
+ if apptype=app_arm9 then //ARM9
+ begin
+ add('OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")');
+ add('OUTPUT_ARCH(arm)');
+ add('ENTRY(_start)');
+ add('');
+ add('MEMORY {');
+ add('');
+ add(' rom : ORIGIN = 0x08000000, LENGTH = 32M');
+ add(' ewram : ORIGIN = 0x02000000, LENGTH = 4M - 4k');
+ add(' dtcm : ORIGIN = 0x0b000000, LENGTH = 16K');
+ add(' vectors : ORIGIN = 0x01000000, LENGTH = 256');
+ add(' itcm : ORIGIN = 0x01000100, LENGTH = 32K - 256');
+ add('}');
+ add('');
+ add('__vectors_start = ORIGIN(vectors);');
+ add('__itcm_start = ORIGIN(itcm);');
+ add('__ewram_end = ORIGIN(ewram) + LENGTH(ewram);');
+ add('__eheap_end = ORIGIN(ewram) + LENGTH(ewram);');
+ add('__dtcm_start = ORIGIN(dtcm);');
+ add('__dtcm_top = ORIGIN(dtcm) + LENGTH(dtcm);');
+ add('__irq_flags = __dtcm_top - 0x08;');
+ add('__irq_vector = __dtcm_top - 0x04;');
+ add('');
+ add('__sp_svc = __dtcm_top - 0x100;');
+ add('__sp_irq = __sp_svc - 0x100;');
+ add('__sp_usr = __sp_irq - 0x100;');
+ add('');
+ add('SECTIONS');
+ add('{');
+ add(' .init :');
+ add(' {');
+ add(' __text_start = . ;');
+ add(' KEEP (*(.init))');
+ add(' . = ALIGN(4); /* REQUIRED. LD is flaky without it. */');
+ add(' } >ewram = 0xff');
+ add('');
+ add(' .plt : { *(.plt) } >ewram = 0xff');
+ add('');
+ add(' .text : /* ALIGN (4): */');
+ add(' {');
+ add(' *(EXCLUDE_FILE (*.itcm*) .text)');
+ add('');
+ add(' *(.text.*)');
+ add(' *(.stub)');
+ add(' /* .gnu.warning sections are handled specially by elf32.em. */');
+ add(' *(.gnu.warning)');
+ add(' *(.gnu.linkonce.t*)');
+ add(' *(.glue_7)');
+ add(' *(.glue_7t)');
+ add(' . = ALIGN(4); /* REQUIRED. LD is flaky without it. */');
+ add(' } >ewram = 0xff');
+ add('');
+ add(' .fini :');
+ add(' {');
+ add(' KEEP (*(.fini))');
+ add(' } >ewram =0xff');
+ add('');
+ add(' __text_end = . ;');
+ add('');
+ add(' .rodata :');
+ add(' {');
+ add(' *(.rodata)');
+ add(' *all.rodata*(*)');
+ add(' *(.roda)');
+ add(' *(.rodata.*)');
+ add(' *(.gnu.linkonce.r*)');
+ add(' SORT(CONSTRUCTORS)');
+ add(' . = ALIGN(4); /* REQUIRED. LD is flaky without it. */');
+ add(' } >ewram = 0xff');
+ add('');
+ add(' .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >ewram');
+ add(' __exidx_start = .;');
+ add(' .ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) } >ewram');
+ add(' __exidx_end = .;');
+ add(' /* Ensure the __preinit_array_start label is properly aligned. We');
+ add(' could instead move the label definition inside the section, but');
+ add(' the linker would then create the section even if it turns out to');
+ add(' be empty, which isn''t pretty. */');
+ add(' . = ALIGN(32 / 8);');
+ add(' PROVIDE (__preinit_array_start = .);');
+ add(' .preinit_array : { KEEP (*(.preinit_array)) } >ewram = 0xff');
+ add(' PROVIDE (__preinit_array_end = .);');
+ add(' PROVIDE (__init_array_start = .);');
+ add(' .init_array :');
+ add(' {');
+ add(' KEEP (*(SORT(.init_array.*)))');
+ add(' KEEP (*(.init_array))');
+ add(' } >ewram = 0xff');
+ add(' PROVIDE (__init_array_end = .);');
+ add(' PROVIDE (__fini_array_start = .);');
+ add(' .fini_array :');
+ add(' {');
+ add(' KEEP (*(.fini_array))');
+ add(' KEEP (*(SORT(.fini_array.*)))');
+ add(' } >ewram = 0xff');
+ add(' PROVIDE (__fini_array_end = .);');
+ add('');
+ add(' .ctors :');
+ add(' {');
+ add(' /* gcc uses crtbegin.o to find the start of the constructors, so');
+ add(' we make sure it is first. Because this is a wildcard, it');
+ add(' doesn''t matter if the user does not actually link against');
+ add(' crtbegin.o; the linker won''t look for a file to match a');
+ add(' wildcard. The wildcard also means that it doesn''t matter which');
+ add(' directory crtbegin.o is in. */');
+ add(' KEEP (*crtbegin.o(.ctors))');
+ add(' KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))');
+ add(' KEEP (*(SORT(.ctors.*)))');
+ add(' KEEP (*(.ctors))');
+ add(' . = ALIGN(4); /* REQUIRED. LD is flaky without it. */');
+ add(' } >ewram = 0xff');
+ add('');
+ add(' .dtors :');
+ add(' {');
+ add(' KEEP (*crtbegin.o(.dtors))');
+ add(' KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))');
+ add(' KEEP (*(SORT(.dtors.*)))');
+ add(' KEEP (*(.dtors))');
+ add(' . = ALIGN(4); /* REQUIRED. LD is flaky without it. */');
+ add(' } >ewram = 0xff');
+ add('');
+ add(' .eh_frame :');
+ add(' {');
+ add(' KEEP (*(.eh_frame))');
+ add(' . = ALIGN(4); /* REQUIRED. LD is flaky without it. */');
+ add(' } >ewram = 0xff');
+ add('');
+ add(' .gcc_except_table :');
+ add(' {');
+ add(' *(.gcc_except_table)');
+ add(' . = ALIGN(4); /* REQUIRED. LD is flaky without it. */');
+ add(' } >ewram = 0xff');
+ add(' .jcr : { KEEP (*(.jcr)) } >ewram = 0');
+ add(' .got : { *(.got.plt) *(.got) *(.rel.got) } >ewram = 0');
+ add('');
+ add(' .ewram ALIGN(4) : ');
+ add(' {');
+ add(' __ewram_start = ABSOLUTE(.) ;');
+ add(' *(.ewram)');
+ add(' *ewram.*(.text)');
+ add(' . = ALIGN(4); /* REQUIRED. LD is flaky without it. */');
+ add(' } >ewram = 0xff');
+ add('');
+ add('');
+ add(' .data ALIGN(4) :');
+ add(' {');
+ add(' __data_start = ABSOLUTE(.);');
+ add(' *(.data)');
+ add(' *(.data.*)');
+ add(' *(.gnu.linkonce.d*)');
+ add(' *(.fpc*)');
+ add(' CONSTRUCTORS');
+ add(' . = ALIGN(4);');
+ add(' __data_end = ABSOLUTE(.) ;');
+ add(' } >ewram = 0xff');
+ add('');
+ add('');
+ add(' __dtcm_lma = . ;');
+ add(' __bss_vma = . ;');
+ add('');
+ add(' .dtcm __dtcm_start : AT (__dtcm_lma)');
+ add(' {');
+ add(' *(.dtcm)');
+ add(' *(.dtcm.*)');
+ add(' . = ALIGN(4);');
+ add(' __dtcm_end = ABSOLUTE(.);');
+ add(' } >dtcm = 0xff');
+ add('');
+ add('');
+ add(' __itcm_lma = __dtcm_lma + SIZEOF(.dtcm);');
+ add('');
+ add(' .itcm __itcm_start : AT (__itcm_lma)');
+ add(' {');
+ add(' *(.itcm)');
+ add(' *itcm.*(.text)');
+ add(' . = ALIGN(4);');
+ add(' __itcm_end = ABSOLUTE(.);');
+ add(' } >itcm = 0xff');
+ add('');
+
+ add(' __vectors_lma = __itcm_lma + SIZEOF(.itcm);');
+ add(' .vectors __vectors_start : AT (__vectors_lma)');
+ add(' {');
+ add(' *(.vectors)');
+ add(' *vectors.*(.text)');
+ add(' . = ALIGN(4);');
+ add(' __vectors_end = ABSOLUTE(.);');
+ add(' } >vectors = 0xff');
+ add('');
+ add(' .sbss __dtcm_end (NOLOAD):');
+ add(' {');
+ add(' __sbss_start = ABSOLUTE(.);');
+ add(' __sbss_start__ = ABSOLUTE(.);');
+ add(' *(.sbss)');
+ add(' . = ALIGN(4); /* REQUIRED. LD is flaky without it. */');
+ add(' __sbss_end = ABSOLUTE(.);');
+ add(' } >dtcm');
+ add('');
+ add('');
+ add('');
+ add(' .bss __bss_vma (NOLOAD):');
+ add(' {');
+ add(' __bss_start = ABSOLUTE(.);');
+ add(' __bss_start__ = ABSOLUTE(.);');
+ add(' *(.dynbss)');
+ add(' *(.gnu.linkonce.b*)');
+ add(' *(.bss*)');
+ add(' *(COMMON)');
+ add(' . = ALIGN(4); /* REQUIRED. LD is flaky without it. */');
+ add(' __bss_end__ = ABSOLUTE(.) ;');
+ add(' __end__ = ABSOLUTE(.) ;');
+ add(' } AT>ewram');
+ add('');
+ add('');
+ add(' /* Stabs debugging sections. */');
+ add(' .stab 0 : { *(.stab) }');
+ add(' .stabstr 0 : { *(.stabstr) }');
+ add(' .stab.excl 0 : { *(.stab.excl) }');
+ add(' .stab.exclstr 0 : { *(.stab.exclstr) }');
+ add(' .stab.index 0 : { *(.stab.index) }');
+ add(' .stab.indexstr 0 : { *(.stab.indexstr) }');
+ add(' .comment 0 : { *(.comment) }');
+ add(' /* DWARF debug sections.');
+ add(' Symbols in the DWARF debugging sections are relative to the beginning');
+ add(' of the section so we begin them at 0. */');
+ add(' /* DWARF 1 */');
+ add(' .debug 0 : { *(.debug) }');
+ add(' .line 0 : { *(.line) }');
+ add(' /* GNU DWARF 1 extensions */');
+ add(' .debug_srcinfo 0 : { *(.debug_srcinfo) }');
+ add(' .debug_sfnames 0 : { *(.debug_sfnames) }');
+ add(' /* DWARF 1.1 and DWARF 2 */');
+ add(' .debug_aranges 0 : { *(.debug_aranges) }');
+ add(' .debug_pubnames 0 : { *(.debug_pubnames) }');
+ add(' /* DWARF 2 */');
+ add(' .debug_info 0 : { *(.debug_info) }');
+ add(' .debug_abbrev 0 : { *(.debug_abbrev) }');
+ add(' .debug_line 0 : { *(.debug_line) }');
+ add(' .debug_frame 0 : { *(.debug_frame) }');
+ add(' .debug_str 0 : { *(.debug_str) }');
+ add(' .debug_loc 0 : { *(.debug_loc) }');
+ add(' .debug_macinfo 0 : { *(.debug_macinfo) }');
+ add(' /* SGI/MIPS DWARF 2 extensions */');
+ add(' .debug_weaknames 0 : { *(.debug_weaknames) }');
+ add(' .debug_funcnames 0 : { *(.debug_funcnames) }');
+ add(' .debug_typenames 0 : { *(.debug_typenames) }');
+ add(' .debug_varnames 0 : { *(.debug_varnames) }');
+ add(' .stack 0x80000 : { _stack = .; *(.stack) }');
+ add(' /* These must appear regardless of . */');
+ add('}');
+ end;
+ if apptype=app_arm7 then
+ begin
+ add('OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")');
+ add('OUTPUT_ARCH(arm)');
+ add('ENTRY(_start)');
+ add('');
+ add('MEMORY {');
+ add('');
+ add(' rom : ORIGIN = 0x08000000, LENGTH = 32M');
+ add(' iwram : ORIGIN = 0x037f8000, LENGTH = 96K');
+ add('}');
+ add('');
+ add('__iwram_start = ORIGIN(iwram);');
+ add('__iwram_top = ORIGIN(iwram)+ LENGTH(iwram);');
+ add('__sp_irq = __iwram_top - 0x100;');
+ add('__sp_svc = __sp_irq - 0x100;');
+ add('__sp_usr = __sp_svc - 0x100;');
+ add('');
+ add('__irq_flags = 0x04000000 - 8;');
+ add('__irq_flagsaux = 0x04000000 - 0x40;');
+ add('__irq_vector = 0x04000000 - 4;');
+ add('');
+ add('SECTIONS');
+ add('{');
+ add(' .init :');
+ add(' {');
+ add(' __text_start = . ;');
+ add(' KEEP (*(.init))');
+ add(' . = ALIGN(4); /* REQUIRED. LD is flaky without it. */');
+ add(' } >iwram = 0xff');
+ add(' .plt : { *(.plt) } >iwram = 0xff');
+ add('');
+ add(' .text : /* ALIGN (4): */');
+ add(' {');
+ add('');
+ add(' *(.text .stub .text.* .gnu.linkonce.t.*)');
+ add(' KEEP (*(.text.*personality*))');
+ add(' /* .gnu.warning sections are handled specially by elf32.em. */');
+ add(' *(.gnu.warning)');
+ add(' *(.glue_7t) *(.glue_7) *(.vfp11_veneer)');
+ add(' . = ALIGN(4); /* REQUIRED. LD is flaky without it. */');
+ add(' } >iwram = 0xff');
+ add('');
+ add(' .fini :');
+ add(' {');
+ add(' KEEP (*(.fini))');
+ add(' } >iwram =0xff');
+ add('');
+ add(' __text_end = . ;');
+ add('');
+ add(' .rodata :');
+ add(' {');
+ add(' *(.rodata)');
+ add(' *all.rodata*(*)');
+ add(' *(.roda)');
+ add(' *(.rodata.*)');
+ add(' *(.gnu.linkonce.r*)');
+ add(' SORT(CONSTRUCTORS)');
+ add(' . = ALIGN(4); /* REQUIRED. LD is flaky without it. */');
+ add(' } >iwram = 0xff');
+ add('');
+ add(' .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >iwram');
+ add(' __exidx_start = .;');
+ add(' .ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) } >iwram');
+ add(' __exidx_end = .;');
+ add('');
+ add('/* Ensure the __preinit_array_start label is properly aligned. We');
+ add(' could instead move the label definition inside the section, but');
+ add(' the linker would then create the section even if it turns out to');
+ add(' be empty, which isn''t pretty. */');
+ add(' . = ALIGN(32 / 8);');
+ add(' PROVIDE (__preinit_array_start = .);');
+ add(' .preinit_array : { KEEP (*(.preinit_array)) } >iwram = 0xff');
+ add(' PROVIDE (__preinit_array_end = .);');
+ add(' PROVIDE (__init_array_start = .);');
+ add(' .init_array : { KEEP (*(.init_array)) } >iwram = 0xff');
+ add(' PROVIDE (__init_array_end = .);');
+ add(' PROVIDE (__fini_array_start = .);');
+ add(' .fini_array : { KEEP (*(.fini_array)) } >iwram = 0xff');
+ add(' PROVIDE (__fini_array_end = .);');
+ add('');
+ add(' .ctors :');
+ add(' {');
+ add(' /* gcc uses crtbegin.o to find the start of the constructors, so');
+ add(' we make sure it is first. Because this is a wildcard, it');
+ add(' doesn''t matter if the user does not actually link against');
+ add(' crtbegin.o; the linker won''t look for a file to match a');
+ add(' wildcard. The wildcard also means that it doesn''t matter which');
+ add(' directory crtbegin.o is in. */');
+ add(' KEEP (*crtbegin.o(.ctors))');
+ add(' KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))');
+ add(' KEEP (*(SORT(.ctors.*)))');
+ add(' KEEP (*(.ctors))');
+ add(' . = ALIGN(4); /* REQUIRED. LD is flaky without it. */');
+ add(' } >iwram = 0xff');
+ add('');
+ add(' .dtors :');
+ add(' {');
+ add(' KEEP (*crtbegin.o(.dtors))');
+ add(' KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))');
+ add(' KEEP (*(SORT(.dtors.*)))');
+ add(' KEEP (*(.dtors))');
+ add(' . = ALIGN(4); /* REQUIRED. LD is flaky without it. */');
+ add(' } >iwram = 0xff');
+ add('');
+ add(' .eh_frame :');
+ add(' {');
+ add(' KEEP (*(.eh_frame))');
+ add(' . = ALIGN(4); /* REQUIRED. LD is flaky without it. */');
+ add(' } >iwram = 0xff');
+ add('');
+ add(' .gcc_except_table :');
+ add(' {');
+ add(' *(.gcc_except_table)');
+ add(' . = ALIGN(4); /* REQUIRED. LD is flaky without it. */');
+ add(' } >iwram = 0xff');
+ add(' .jcr : { KEEP (*(.jcr)) } >iwram = 0');
+ add(' .got : { *(.got.plt) *(.got) } >iwram = 0');
+ add('');
+ add('');
+ add(' .iwram ALIGN(4) :');
+ add(' {');
+ add(' __iwram_start = ABSOLUTE(.) ;');
+ add(' *(.iwram)');
+ add(' *iwram.*(.text)');
+ add(' . = ALIGN(4); /* REQUIRED. LD is flaky without it. */');
+ add(' __iwram_end = ABSOLUTE(.) ;');
+ add(' } >iwram = 0xff');
+ add('');
+ add('');
+ add(' .data ALIGN(4) : {');
+ add(' __data_start = ABSOLUTE(.);');
+ add(' *(.data)');
+ add(' *(.data.*)');
+ add(' *(.gnu.linkonce.d*)');
+ add(' *(.fpc*)');
+ add(' CONSTRUCTORS');
+ add(' . = ALIGN(4);');
+ add(' __data_end = ABSOLUTE(.) ;');
+ add(' } >iwram = 0xff');
+ add('');
+ add('');
+ add('');
+ add(' .bss ALIGN(4) :');
+ add(' {');
+ add(' __bss_start = ABSOLUTE(.);');
+ add(' __bss_start__ = ABSOLUTE(.);');
+ add(' *(.dynbss)');
+ add(' *(.gnu.linkonce.b*)');
+ add(' *(.bss*)');
+ add(' *(COMMON)');
+ add(' . = ALIGN(4); /* REQUIRED. LD is flaky without it. */');
+ add(' __bss_end__ = ABSOLUTE(.);');
+ add(' __end__ = ABSOLUTE(.);');
+ add(' } >iwram');
+ add('');
+ add(' /* Stabs debugging sections. */');
+ add(' .stab 0 : { *(.stab) }');
+ add(' .stabstr 0 : { *(.stabstr) }');
+ add(' .stab.excl 0 : { *(.stab.excl) }');
+ add(' .stab.exclstr 0 : { *(.stab.exclstr) }');
+ add(' .stab.index 0 : { *(.stab.index) }');
+ add(' .stab.indexstr 0 : { *(.stab.indexstr) }');
+ add(' .comment 0 : { *(.comment) }');
+ add(' /* DWARF debug sections.');
+ add(' Symbols in the DWARF debugging sections are relative to the beginning');
+ add(' of the section so we begin them at 0. */');
+ add(' /* DWARF 1 */');
+ add(' .debug 0 : { *(.debug) }');
+ add(' .line 0 : { *(.line) }');
+ add(' /* GNU DWARF 1 extensions */');
+ add(' .debug_srcinfo 0 : { *(.debug_srcinfo) }');
+ add(' .debug_sfnames 0 : { *(.debug_sfnames) }');
+ add(' /* DWARF 1.1 and DWARF 2 */');
+ add(' .debug_aranges 0 : { *(.debug_aranges) }');
+ add(' .debug_pubnames 0 : { *(.debug_pubnames) }');
+ add(' /* DWARF 2 */');
+ add(' .debug_info 0 : { *(.debug_info) }');
+ add(' .debug_abbrev 0 : { *(.debug_abbrev) }');
+ add(' .debug_line 0 : { *(.debug_line) }');
+ add(' .debug_frame 0 : { *(.debug_frame) }');
+ add(' .debug_str 0 : { *(.debug_str) }');
+ add(' .debug_loc 0 : { *(.debug_loc) }');
+ add(' .debug_macinfo 0 : { *(.debug_macinfo) }');
+ add(' /* SGI/MIPS DWARF 2 extensions */');
+ add(' .debug_weaknames 0 : { *(.debug_weaknames) }');
+ add(' .debug_funcnames 0 : { *(.debug_funcnames) }');
+ add(' .debug_typenames 0 : { *(.debug_typenames) }');
+ add(' .debug_varnames 0 : { *(.debug_varnames) }');
+ add(' .stack 0x80000 : { _stack = .; *(.stack) }');
+ add(' /* These must appear regardless of . */');
+ add('}');
+ end;
+ end;
+
+{ Write and Close response }
+ linkres.writetodisk;
+ linkres.free;
+
+ WriteResponseFile:=True;
+
+end;
+
+
+function TLinkerNDS.MakeExecutable:boolean;
+var
+ binstr,
+ cmdstr : TCmdStr;
+ success : boolean;
+ StaticStr,
+ GCSectionsStr,
+ DynLinkStr,
+ MapStr,
+ StripStr: string;
+ preName: string;
+begin
+ { for future use }
+ StaticStr:='';
+ StripStr:='';
+ MapStr:='';
+ DynLinkStr:='';
+ case apptype of
+ app_arm9: preName:='.nef';
+ app_arm7: preName:='.nlf';
+ end;
+
+ if (cs_link_strip in current_settings.globalswitches) and
+ not(cs_link_separate_dbg_file in current_settings.globalswitches) then
+ StripStr:='-s';
+ if (cs_link_map in current_settings.globalswitches) then
+ StripStr:='-Map '+maybequoted(ChangeFileExt(current_module.exefilename^,'.map'));
+ if create_smartlink_sections then
+ GCSectionsStr:='--gc-sections';
+ if not(cs_link_nolink in current_settings.globalswitches) then
+ Message1(exec_i_linking,current_module.exefilename^);
+
+{ Write used files and libraries }
+ WriteResponseFile();
+
+{ Call linker }
+ SplitBinCmd(Info.ExeCmd[1],binstr,cmdstr);
+ Replace(cmdstr,'$OPT',Info.ExtraOptions);
+
+ Replace(cmdstr,'$EXE',(maybequoted(ScriptFixFileName(ChangeFileExt(current_module.exefilename^,preName)))));
+ Replace(cmdstr,'$RES',(maybequoted(ScriptFixFileName(outputexedir+Info.ResName))));
+ Replace(cmdstr,'$STATIC',StaticStr);
+ Replace(cmdstr,'$STRIP',StripStr);
+ Replace(cmdstr,'$GCSECTIONS',GCSectionsStr);
+ Replace(cmdstr,'$MAP',MapStr);
+ Replace(cmdstr,'$DYNLINK',DynLinkStr);
+
+ success:=DoExec(FindUtil(utilsprefix+BinStr),cmdstr,true,false);
+
+{ Remove ReponseFile }
+ if (success) and not(cs_link_nolink in current_settings.globalswitches) then
+ DeleteFile(outputexedir+Info.ResName);
+
+{ Post process }
+ if success then
+ begin
+ success:=DoExec(FindUtil(utilsprefix + 'objcopy'), '-O binary '+
+ ChangeFileExt(current_module.exefilename^, preName) + ' ' +
+ ChangeFileExt(current_module.exefilename^, preName+target_info.exeext),
+ true,false);
+ end;
+
+ if success and (apptype=app_arm9) then
+ begin
+ success:=DoExec(FindUtil('ndstool'), '-c ' +
+ ChangeFileExt(current_module.exefilename^, '.nds') + ' -9 ' +
+ ChangeFileExt(current_module.exefilename^, preName+target_info.exeext),
+ true,false);
+ end;
+ MakeExecutable:=success; { otherwise a recursive call to link method }
+end;
+
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+initialization
+ RegisterExternalLinker(system_arm_nds_info,TLinkerNDS);
+ RegisterTarget(system_arm_nds_info);
+end.
diff --git a/closures/compiler/systems/t_nwl.pas b/closures/compiler/systems/t_nwl.pas
new file mode 100644
index 0000000000..0cc59bf5ac
--- /dev/null
+++ b/closures/compiler/systems/t_nwl.pas
@@ -0,0 +1,631 @@
+{
+ Copyright (c) 1998-2004 by Peter Vreman
+
+ This unit implements support import,export,link routines
+ for the (i386) Netware libc target
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Currently generating NetWare-NLM's only work under Linux and win32.
+ (see http://home.arcor.de/armin.diehl/fpcnw for binutils working
+ with win32) while not included in fpc-releases.
+
+ The following compiler-swiches are supported for NetWare:
+ $DESCRIPTION : NLM-Description, will be displayed at load-time
+ $M : For Stack-Size, Heap-Size will be ignored
+ 32K is the accepted minimum
+ $VERSION x.x.x : Sets Major, Minor and Revision
+ $SCREENNAME : Sets the ScreenName
+ $THREADNAME : Sets current threadname
+
+ Additional parameters for the nlmvonv-inputfile can be passed with
+ -k, i.e. -kREENTRANT will add the option REENTRANT to the nlmconv
+ inputfile. A ; will be converted into a newline
+
+ Exports will be handled like in win32:
+ procedure bla; cdecl;
+ begin
+ end;
+
+ exports foo name 'Bar';
+
+ The path to the import-Files must be specified by the library-path.
+ All external modules are defined as autoload. (Note: the import-files have
+ to be in unix-format for exe2nlm)
+ By default, the most import files are included in freepascal.
+
+ e.g. function getgrnam(name:Pchar):Pgroup;cdecl;external 'libc' 'getgrnam';
+ sets IMPORT @libc.imp and MODULE libc.
+ To avoid setting the autoload, use ! in the name, e.g.
+ procedure EnterDebugger;cdecl;external '!netware' name 'EnterDebugger';
+
+ Function simply defined as external work without generating autoload and
+ IMPORT but you will get a warning from nlmconv.
+
+ If you dont have nlmconv, compile gnu-binutils with
+ ./configure --enable-targets=i386-netware
+ make all
+
+ Debugging is possible with gdb and a converter from gdb to ndi available
+ at http://home.arcor.de/armin.diehl/gdbnw
+
+ A sample program:
+
+ Program Hello;
+ (*$DESCRIPTION HelloWorldNlm*)
+ (*$VERSION 1.2.3*)
+ (*$ScreenName Hello*)
+ (*$M 60000,60000*)
+ begin
+ writeLn ('hello world');
+ end.
+
+ compile with:
+ ppc386 -Tnetwlibc hello
+
+ Libraries are supported but this needs at least netware 5.1 sp6,
+ 6.0 sp3 or netware 6.5
+
+ In case there is a xdc file with the same name as the nlm name,
+ this file will be used for nlmconv. Otherwise a temp xdc will
+ be created and used.
+
+****************************************************************************
+}
+unit t_nwl;
+
+{$i fpcdefs.inc}
+
+interface
+
+
+implementation
+
+{$ifdef netwlibc}
+{$define netware}
+{$endif}
+
+ uses
+ SysUtils,
+ cutils,cfileutl,
+ verbose,systems,globtype,globals,
+ symconst,script,
+ fmodule,aasmbase,aasmtai,aasmdata,aasmcpu,cpubase,symsym,symdef,
+ import,export,link,i_nwl,ogbase
+ {$ifdef netware} ,dos {$endif}
+ ;
+
+ type
+ timportlibnetwlibc=class(timportlib)
+ procedure generatelib;override;
+ end;
+
+ texportlibnetwlibc=class(texportlib)
+ procedure preparelib(const s : string);override;
+ procedure exportprocedure(hp : texported_item);override;
+ procedure exportvar(hp : texported_item);override;
+ procedure generatelib;override;
+ end;
+
+ tlinkernetwlibc=class(texternallinker)
+ private
+ NLMConvLinkFile: TLinkRes; {for second pass, fist pass is ld}
+ Function WriteResponseFile(isdll:boolean) : Boolean;
+ public
+ constructor Create;override;
+ procedure SetDefaultInfo;override;
+ function MakeNetwareLoadableModule (isLib : boolean):boolean;
+ function MakeExecutable:boolean;override;
+ function MakeSharedLibrary:boolean;override;
+ end;
+
+Const tmpLinkFileName = '~link~tmp.o';
+ minStackSize = 32768;
+
+{*****************************************************************************
+ TIMPORTLIBNETWARE
+*****************************************************************************}
+
+ procedure timportlibnetwlibc.generatelib;
+ var
+ i : longint;
+ ImportLibrary : TImportLibrary;
+ begin
+ for i:=0 to current_module.ImportLibraryList.Count-1 do
+ begin
+ ImportLibrary:=TImportLibrary(current_module.ImportLibraryList[i]);
+ current_module.linkothersharedlibs.add(ImportLibrary.Name,link_always);
+ end;
+ end;
+
+
+{*****************************************************************************
+ TEXPORTLIBNETWARE
+*****************************************************************************}
+
+procedure texportlibnetwlibc.preparelib(const s:string);
+begin
+end;
+
+
+procedure texportlibnetwlibc.exportprocedure(hp : texported_item);
+var
+ hp2 : texported_item;
+begin
+ { first test the index value }
+ if (hp.options and eo_index)<>0 then
+ begin
+ Comment(V_Error,'can''t export with index under netware');
+ exit;
+ end;
+ { use pascal name is none specified }
+ if (hp.options and eo_name)=0 then
+ begin
+ hp.name:=stringdup(hp.sym.name);
+ hp.options:=hp.options or eo_name;
+ end;
+ { now place in correct order }
+ hp2:=texported_item(current_module._exports.first);
+ while assigned(hp2) and
+ (hp.name^>hp2.name^) do
+ hp2:=texported_item(hp2.next);
+ { insert hp there !! }
+ if assigned(hp2) and (hp2.name^=hp.name^) then
+ begin
+ { this is not allowed !! }
+ Message1(parser_e_export_name_double,hp.name^);
+ exit;
+ end;
+ if hp2=texported_item(current_module._exports.first) then
+ current_module._exports.insert(hp)
+ else if assigned(hp2) then
+ begin
+ hp.next:=hp2;
+ hp.previous:=hp2.previous;
+ if assigned(hp2.previous) then
+ hp2.previous.next:=hp;
+ hp2.previous:=hp;
+ end
+ else
+ current_module._exports.concat(hp);
+end;
+
+
+procedure texportlibnetwlibc.exportvar(hp : texported_item);
+begin
+ hp.is_var:=true;
+ exportprocedure(hp);
+end;
+
+
+procedure texportlibnetwlibc.generatelib;
+var
+ hp2 : texported_item;
+ pd : tprocdef;
+begin
+ hp2:=texported_item(current_module._exports.first);
+ while assigned(hp2) do
+ begin
+ if (not hp2.is_var) and
+ (hp2.sym.typ=procsym) then
+ begin
+ { the manglednames can already be the same when the procedure
+ is declared with cdecl }
+ pd:=tprocdef(tprocsym(hp2.sym).ProcdefList[0]);
+ if pd.mangledname<>hp2.name^ then
+ begin
+{$ifdef i386}
+ { place jump in al_procedures }
+ current_asmdata.asmlists[al_procedures].concat(Tai_align.Create_op(4,$90));
+ current_asmdata.asmlists[al_procedures].concat(Tai_symbol.Createname_global(hp2.name^,AT_FUNCTION,0));
+ current_asmdata.asmlists[al_procedures].concat(Taicpu.Op_sym(A_JMP,S_NO,current_asmdata.RefAsmSymbol(pd.mangledname)));
+ current_asmdata.asmlists[al_procedures].concat(Tai_symbol_end.Createname(hp2.name^));
+{$endif i386}
+ end;
+ end
+ else
+ //Comment(V_Error,'Exporting of variables is not supported under netware');
+ Message1(parser_e_no_export_of_variables_for_target,'netware');
+ hp2:=texported_item(hp2.next);
+ end;
+end;
+
+
+{*****************************************************************************
+ TLINKERNETWARE
+*****************************************************************************}
+
+Constructor TLinkerNetwlibc.Create;
+begin
+ Inherited Create;
+end;
+
+
+procedure TLinkerNetwlibc.SetDefaultInfo;
+begin
+ with Info do
+ begin
+ {$ifndef netware}
+ ExeCmd[1]:= FindUtil(utilsprefix+'ld') + ' -Ur -T $RES $STRIP -o $TMPOBJ';
+ ExeCmd[2]:= FindUtil(utilsprefix+'nlmconv') + ' -T$RES';
+ {$else}
+ {for running on netware we need absolute pathes since ld has another working directory}
+ ExeCmd[1]:= FindUtil(utilsprefix+'ld') + ' -Ur -T '+FExpand(outputexedir+Info.ResName)+' $STRIP -o '+Fexpand(outputexedir+tmpLinkFileName);
+ ExeCmd[2]:= FindUtil(utilsprefix+'nlmconv') + ' -T'+FExpand(outputexedir+'n'+Info.ResName);
+ {$endif}
+ end;
+end;
+
+
+Function TLinkerNetwlibc.WriteResponseFile(isdll:boolean) : Boolean;
+Var
+ linkres : TLinkRes;
+ i : longint;
+ s,s2,s3 : TCmdStr;
+ ProgNam : string [80];
+ NlmNam : string [80];
+ hp2 : texported_item; { for exports }
+ p : byte;
+begin
+ WriteResponseFile:=False;
+
+ ProgNam := current_module.exefilename^;
+ i:=Pos(target_info.exeext,ProgNam);
+ if i>0 then
+ Delete(ProgNam,i,255);
+ NlmNam := ProgNam + target_info.exeext;
+
+ { Open link.res file }
+ LinkRes:=TLinkRes.Create(outputexedir+Info.ResName); {for ld}
+ NLMConvLinkFile:=TLinkRes.Create(outputexedir+'n'+Info.ResName); {for nlmconv, written in CreateExeFile}
+
+ p := Pos ('"', Description);
+ while (p > 0) do
+ begin
+ delete (Description,p,1);
+ p := Pos ('"', Description);
+ end;
+ if Description <> '' then
+ NLMConvLinkFile.Add('DESCRIPTION "' + Description + '"');
+ NLMConvLinkFile.Add('VERSION '+tostr(dllmajor)+','+tostr(dllminor)+','+tostr(dllrevision));
+
+ p := Pos ('"', nwscreenname);
+ while (p > 0) do
+ begin
+ delete (nwscreenname,p,1);
+ p := Pos ('"', nwscreenname);
+ end;
+ p := Pos ('"', nwthreadname);
+ while (p > 0) do
+ begin
+ delete (nwthreadname,p,1);
+ p := Pos ('"', nwthreadname);
+ end;
+ p := Pos ('"', nwcopyright);
+ while (p > 0) do
+ begin
+ delete (nwcopyright,p,1);
+ p := Pos ('"', nwcopyright);
+ end;
+
+ if nwscreenname <> '' then
+ NLMConvLinkFile.Add('SCREENNAME "' + nwscreenname + '"');
+ if nwthreadname <> '' then
+ NLMConvLinkFile.Add('THREADNAME "' + nwthreadname + '"');
+ if nwcopyright <> '' then
+ NLMConvLinkFile.Add('COPYRIGHT "' + nwcopyright + '"');
+
+ if stacksize < minStackSize then stacksize := minStackSize;
+ str (stacksize, s);
+ NLMConvLinkFile.Add ('STACKSIZE '+s);
+ {$ifndef netware}
+ NLMConvLinkFile.Add ('INPUT '+outputexedir+tmpLinkFileName);
+ {$else}
+ NLMConvLinkFile.Add ('INPUT '+FExpand(outputexedir+tmpLinkFileName));
+ {$endif}
+
+ { add objectfiles, start with nwpre always }
+ LinkRes.Add ('INPUT(');
+ s2 := FindObjectFile('nwplibc','',false);
+ if s2 = '' then
+ s2 := FindObjectFile('libcpre.gcc','',false);
+ Comment (V_Debug,'adding Object File '+s2);
+ {$ifndef netware} LinkRes.Add (s2); {$else} LinkRes.Add (FExpand(s2)); {$endif}
+
+ if isDll then {needed to provide main}
+ s2 := FindObjectFile('nwl_dlle','',false)
+ else
+ s2 := FindObjectFile('nwl_main','',false);
+ Comment (V_Debug,'adding Object File '+s2);
+ {$ifndef netware} LinkRes.Add (s2); {$else} LinkRes.Add (FExpand(s2)); {$endif}
+
+ { main objectfiles, add to linker input }
+ while not ObjectFiles.Empty do
+ begin
+ s:=ObjectFiles.GetFirst;
+ if s<>'' then
+ begin
+ s2 := FindObjectFile (s,'',false);
+ Comment (V_Debug,'adding Object File '+s2);
+ {$ifndef netware} LinkRes.Add (s2); {$else} LinkRes.Add (FExpand(s2)); {$endif}
+ end;
+ end;
+ LinkRes.Add (')');
+
+ { output file (nlm), add to nlmconv }
+ {$ifndef netware}
+ NLMConvLinkFile.Add ('OUTPUT ' + NlmNam);
+ {$else}
+ NLMConvLinkFile.Add ('OUTPUT ' + FExpand(NlmNam));
+ {$endif}
+
+ { start and stop-procedures }
+ NLMConvLinkFile.Add ('START _LibCPrelude');
+ NLMConvLinkFile.Add ('EXIT _LibCPostlude');
+ NLMConvLinkFile.Add ('CHECK _LibCCheckUnload');
+ NLMConvLinkFile.Add ('REENTRANT'); { needed by older libc versions }
+
+ if not (cs_link_strip in current_settings.globalswitches) then
+ begin
+ NLMConvLinkFile.Add ('DEBUG');
+ Comment(V_Debug,'DEBUG');
+ end;
+
+ { Write staticlibraries }
+ if not StaticLibFiles.Empty then
+ begin
+ LinkRes.Add ('GROUP(');
+ While not StaticLibFiles.Empty do
+ begin
+ S:=lower (StaticLibFiles.GetFirst);
+ if s<>'' then
+ begin
+ {ad: that's a hack !
+ whith -XX we get the .a files as static libs (in addition to the
+ imported libraries}
+ if (pos ('.a',s) <> 0) OR (pos ('.A', s) <> 0) then
+ begin
+ S2 := FindObjectFile(s,'',false);
+ {$ifndef netware} LinkRes.Add (s2); {$else} LinkRes.Add (FExpand(s2)); {$endif}
+ Comment(V_Debug,'adding Object File (StaticLibFiles) '+S2);
+ end else
+ begin
+ i:=Pos(target_info.staticlibext,S);
+ if i>0 then
+ Delete(S,i,255);
+ S := S + '.imp'; S2 := '';
+ librarysearchpath.FindFile(S,false,S2);
+ {$ifdef netware}
+ Comment(V_Debug,'IMPORT @'+s2);
+ s2 := FExpand (S2);
+ {$endif}
+ NLMConvLinkFile.Add('IMPORT @'+S2);
+ Comment(V_Debug,'IMPORT @'+s2);
+ end;
+ end
+ end;
+ LinkRes.Add (')');
+ end;
+
+ if not SharedLibFiles.Empty then
+ begin
+ While not SharedLibFiles.Empty do
+ begin
+ {because of upper/lower case mix, we may get duplicate
+ names but nlmconv ignores that.
+ Here we are setting the import-files for nlmconv. I.e. for
+ the module libc or libc.nlm we add IMPORT @libc.imp and also
+ the module libc.nlm (autoload)
+ If a lib name begins with !, only the IMPORT will be generated
+ ? may it be better to set autoload's via StaticLibFiles ? }
+ S:=lower (SharedLibFiles.GetFirst);
+ if s<>'' then
+ begin
+ s2:=s;
+ i:=Pos(target_info.sharedlibext,S);
+ if i>0 then
+ Delete(S,i,255);
+ if s[1] = '!' then
+ begin // special, with ! only the imp will be included but no module is autoloaded, needed i.e. for netware.imp inlcuded in libc ndk
+ delete (s,1,1);
+ S := S + '.imp';
+ librarysearchpath.FindFile(S,false,S3);
+ {$ifdef netware}
+ Comment(V_Debug,'IMPORT @'+S3);
+ S3 := FExpand (S3);
+ {$endif}
+ NLMConvLinkFile.Add('IMPORT @'+S3);
+ Comment(V_Debug,'IMPORT @'+S3);
+ end else
+ begin
+ S := S + '.imp';
+ librarysearchpath.FindFile(S,false,S3);
+ {$ifdef netware}
+ Comment(V_Debug,'IMPORT @'+S3);
+ S3 := FExpand (S3);
+ {$endif}
+ NLMConvLinkFile.Add('IMPORT @'+S3);
+ NLMConvLinkFile.Add('MODULE '+s2);
+ Comment(V_Debug,'MODULE '+S2);
+ Comment(V_Debug,'IMPORT @'+S3);
+ end;
+ end
+ end;
+ end;
+
+ { write exports }
+ hp2:=texported_item(current_module._exports.first);
+ while assigned(hp2) do
+ begin
+ if not hp2.is_var then
+ begin
+ { Export the Symbol }
+ Comment(V_Debug,'EXPORT '+hp2.name^);
+ NLMConvLinkFile.Add ('EXPORT '+hp2.name^);
+ end
+ else
+ { really, i think it is possible }
+ {Comment(V_Error,'Exporting of variables is not supported under netware');}
+ Message1(parser_e_no_export_of_variables_for_target,'netware');
+ hp2:=texported_item(hp2.next);
+ end;
+
+{ Write and Close response for ld, response for nlmconv is in NLMConvLinkFile(not written) }
+ linkres.writetodisk;
+ LinkRes.Free;
+
+{ pass options from -k to nlmconv, ; is interpreted as newline }
+ s := ParaLinkOptions;
+ while(Length(s) > 0) and (s[1] = ' ') do
+ delete (s,1,1);
+ p := pos ('"',s);
+ while p > 0 do
+ begin
+ delete (s,p,1);
+ p := pos ('"',s);
+ end;
+
+ p := pos (';',s);
+ while p > 0 do
+ begin
+ s2 := copy(s,1,p-1);
+ comment (V_Debug,'adding "'+s2+'" to nlmvonv input');
+ NLMConvLinkFile.Add(s2);
+ delete (s,1,p);
+ p := pos (';',s);
+ end;
+ if s <> '' then
+ begin
+ comment (V_Debug,'adding "'+s+'" to nlmvonv input');
+ NLMConvLinkFile.Add(s);
+ end;
+
+ WriteResponseFile:=True;
+end;
+
+Const
+ xdc : Array[0..127] of char = (
+ 'B','A','G','F',#2,#0,#0,#0,#1,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,
+ #0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#2,#0,#0,#0,#0,#0,#0,#0,#16,#0,#0,
+ #0,#7,'M','P','K','_','B','a','g',#0,#0,#0,#0,#0,#0,#0,#0,#11,'M','T',
+ ' ','S','a','f','e',' ','N','L','M',#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,
+ #0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,
+ #0,#0,#0,#0,#0,#0,#1,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0);
+
+
+function TLinkerNetwlibc.MakeNetwareLoadableModule (isLib : boolean):boolean;
+var
+ binstr,
+ cmdstr : TCmdStr;
+ xdcname : string;
+ success : boolean;
+ StripStr : string[2];
+ xdcpresent,usexdc : boolean;
+ f : file;
+begin
+ if not(cs_link_nolink in current_settings.globalswitches) then
+ Message1(exec_i_linking,current_module.exefilename^);
+
+{ Create some replacements }
+ StripStr:='';
+
+ if (cs_link_strip in current_settings.globalswitches) then
+ StripStr:='-s';
+
+{ Write used files and libraries and create Headerfile for
+ nlmconv in NLMConvLinkFile }
+ WriteResponseFile(isLib);
+ if isLib then
+ NLMConvLinkFile.Add('FLAG_ON 1024'); {0x400 Specifies whether the NLM is a shared library.}
+
+{ if we have a xdc file, dont touch it, otherwise create a new
+ one and remove it after nlmconv }
+ xdcname := ChangeFileExt(current_module.exefilename^,'.xdc');
+ xdcpresent := FileExists (xdcname,false);
+ if not xdcpresent then
+ begin
+ assign (f,xdcname);
+ rewrite(f,1);
+ if ioresult = 0 then
+ begin
+ blockwrite (f,xdc,sizeof(xdc));
+ close(f);
+ usexdc := (IOResult = 0);
+ end else
+ usexdc := false;
+ end else
+ usexdc := true;
+
+ if usexdc then
+ NLMConvLinkFile.Add('XDCDATA '+xdcname);
+
+{ Call linker, this will generate a new object file that will be passed
+ to nlmconv. Otherwise we could not create nlms without debug info }
+ SplitBinCmd(Info.ExeCmd[1],binstr,cmdstr);
+ Replace(cmdstr,'$EXE',maybequoted(current_module.exefilename^));
+ Replace(cmdstr,'$RES',maybequoted(outputexedir+Info.ResName));
+ Replace(cmdstr,'$STRIP',StripStr);
+ Replace(cmdstr,'$TMPOBJ',maybequoted(outputexedir+tmpLinkFileName));
+ Comment (v_debug,'Executing '+BinStr+' '+cmdstr);
+ success:=DoExec(BinStr,CmdStr,true,false);
+
+ { Remove ReponseFile }
+ if (success) and not(cs_link_nolink in current_settings.globalswitches) then
+ DeleteFile(outputexedir+Info.ResName);
+
+{ Call nlmconv }
+ if success then
+ begin
+ NLMConvLinkFile.writetodisk;
+ NLMConvLinkFile.Free;
+ SplitBinCmd(Info.ExeCmd[2],binstr,cmdstr);
+ Replace(cmdstr,'$RES',maybequoted(outputexedir+'n'+Info.ResName));
+ Comment (v_debug,'Executing '+BinStr+' '+cmdstr);
+ success:=DoExec(BinStr,CmdStr,true,false);
+ if (success) and not(cs_link_nolink in current_settings.globalswitches) then
+ begin
+ DeleteFile(outputexedir+'n'+Info.ResName);
+ DeleteFile(outputexedir+tmpLinkFileName);
+ if not xdcpresent then
+ if usexdc then
+ DeleteFile (xdcname);
+ end;
+ end;
+
+ MakeNetwareLoadableModule:=success; { otherwise a recursive call to link method }
+end;
+
+function TLinkerNetwlibc.MakeExecutable:boolean;
+begin
+ MakeExecutable := MakeNetwareLoadableModule (false);
+end;
+
+
+function TLinkerNetwlibc.MakeSharedLibrary:boolean;
+begin
+ MakeSharedLibrary := MakeNetwareLoadableModule (true);
+end;
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+
+initialization
+ RegisterExternalLinker(system_i386_netwlibc_info,TLinkerNetwlibc);
+ RegisterImport(system_i386_netwlibc,TImportLibNetwlibc);
+ RegisterExport(system_i386_netwlibc,TExportLibNetwlibc);
+ RegisterTarget(system_i386_netwlibc_info);
+end.
diff --git a/closures/compiler/systems/t_nwm.pas b/closures/compiler/systems/t_nwm.pas
new file mode 100644
index 0000000000..e8fdbf62bc
--- /dev/null
+++ b/closures/compiler/systems/t_nwm.pas
@@ -0,0 +1,988 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ This unit implements support import,export,link routines
+ for the (i386) Netware target
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Currently generating NetWare-NLM's only work under Linux and win32.
+ (see http://home.arcor.de/armin.diehl/fpcnw for binutils working
+ with win32) while not included in fpc-releases.
+
+ The following compiler-swiches are supported for NetWare:
+ $DESCRIPTION : NLM-Description, will be displayed at load-time
+ $M : For Stack-Size, Heap-Size will be ignored
+ 32K is the accepted minimum
+ $VERSION x.x.x : Sets Major, Minor and Revision
+ $SCREENNAME : Sets the ScreenName
+ $THREADNAME : Sets current threadname
+
+ Displaying copyright does not work with nlmconv from gnu bunutils
+ version less that 2.13
+
+ Additional parameters for the nlmvonv-inputfile can be passed with
+ -k, i.e. -kREENTRANT will add the option REENTRANT to the nlmconv
+ inputfile. A ; will be converted into a newline
+
+ Exports will be handled like in win32:
+ procedure bla;
+ begin
+ end;
+
+ exports foo name 'Bar';
+
+ The path to the import-Files must be specified by the library-path.
+ All external modules are defined as autoload. (Note: the import-files have
+ to be in unix-format for exe2nlm)
+ By default, the most import files are included in freepascal.
+
+ i.e. Procedure ConsolePrintf (p:pchar); cdecl; external 'clib.nlm';
+ sets IMPORT @clib.imp and MODULE clib.
+
+ Function simply defined as external work without generating autoload but
+ you will get a warnung from nlmconv.
+
+ If you dont have nlmconv, compile gnu-binutils with
+ ./configure --enable-targets=i386-linux,i386-netware
+ make all
+
+ Debugging is possible with gdb and a converter from gdb to ndi available
+ at http://home.arcor.de/armin.diehl/gdbnw
+
+ A sample program:
+
+ Program Hello;
+ (*$DESCRIPTION HelloWorldNlm*)
+ (*$VERSION 1.2.3*)
+ (*$ScreenName Hello*)
+ (*$M 60000,60000*)
+ begin
+ writeLn ('hello world');
+ end.
+
+ compile with:
+ ppc386 -Tnetware hello
+
+ ToDo:
+ - No duplicate imports and autoloads
+ - libc support (needs new target)
+
+****************************************************************************
+}
+unit t_nwm;
+
+{$i fpcdefs.inc}
+
+interface
+
+
+implementation
+
+ uses
+ SysUtils,
+ cutils,cfileutl,
+ verbose,systems,globtype,globals,
+ symconst,script,
+ fmodule,aasmbase,aasmtai,aasmdata,aasmcpu,cpubase,symsym,symdef,
+ import,export,link,i_nwm,ogbase, ogcoff, ognlm, cclasses
+ {$ifdef netware} ,dos {$endif}
+ ;
+
+ type
+ timportlibnetware=class(timportlib)
+ procedure generatelib;override;
+ end;
+
+ texportlibnetware=class(texportlib)
+ procedure preparelib(const s : string);override;
+ procedure exportprocedure(hp : texported_item);override;
+ procedure exportvar(hp : texported_item);override;
+ procedure generatelib;override;
+ end;
+
+ tlinkernetware=class(texternallinker)
+ private
+ NLMConvLinkFile: TLinkRes; {for second pass, fist pass is ld}
+ Function WriteResponseFile(isdll:boolean) : Boolean;
+ public
+ constructor Create;override;
+ procedure SetDefaultInfo;override;
+ function MakeExecutable:boolean;override;
+ end;
+
+ TInternalLinkerNetware = class(TInternalLinker)
+ prelude : string;
+ constructor create;override;
+ destructor destroy;override;
+ procedure DefaultLinkScript;override;
+ procedure InitSysInitUnitName;override;
+ procedure ConcatEntryName; virtual;
+ Function MakeSharedLibrary:boolean;override;
+ end;
+
+Const tmpLinkFileName = 'link~tmp._o_';
+ minStackSize = 32768;
+
+{*****************************************************************************
+ TIMPORTLIBNETWARE
+*****************************************************************************}
+
+ procedure timportlibnetware.generatelib;
+ var
+ i : longint;
+ ImportLibrary : TImportLibrary;
+ begin
+ for i:=0 to current_module.ImportLibraryList.Count-1 do
+ begin
+ ImportLibrary:=TImportLibrary(current_module.ImportLibraryList[i]);
+ current_module.linkothersharedlibs.add(ImportLibrary.Name,link_always);
+ end;
+ end;
+
+
+{*****************************************************************************
+ TEXPORTLIBNETWARE
+*****************************************************************************}
+
+procedure texportlibnetware.preparelib(const s:string);
+begin
+end;
+
+
+procedure texportlibnetware.exportprocedure(hp : texported_item);
+var
+ hp2 : texported_item;
+begin
+ { first test the index value }
+ if (hp.options and eo_index)<>0 then
+ begin
+ Comment(V_Error,'can''t export with index under netware');
+ exit;
+ end;
+ { use pascal name is none specified }
+ if (hp.options and eo_name)=0 then
+ begin
+ hp.name:=stringdup(hp.sym.name);
+ hp.options:=hp.options or eo_name;
+ end;
+ { now place in correct order }
+ hp2:=texported_item(current_module._exports.first);
+ while assigned(hp2) and
+ (hp.name^>hp2.name^) do
+ hp2:=texported_item(hp2.next);
+ { insert hp there !! }
+ if assigned(hp2) and (hp2.name^=hp.name^) then
+ begin
+ { this is not allowed !! }
+ Message1(parser_e_export_name_double,hp.name^);
+ exit;
+ end;
+ if hp2=texported_item(current_module._exports.first) then
+ current_module._exports.insert(hp)
+ else if assigned(hp2) then
+ begin
+ hp.next:=hp2;
+ hp.previous:=hp2.previous;
+ if assigned(hp2.previous) then
+ hp2.previous.next:=hp;
+ hp2.previous:=hp;
+ end
+ else
+ current_module._exports.concat(hp);
+end;
+
+
+procedure texportlibnetware.exportvar(hp : texported_item);
+begin
+ hp.is_var:=true;
+ exportprocedure(hp);
+end;
+
+
+procedure texportlibnetware.generatelib;
+var
+ hp2 : texported_item;
+ pd : tprocdef;
+begin
+ hp2:=texported_item(current_module._exports.first);
+ while assigned(hp2) do
+ begin
+ if (not hp2.is_var) and
+ (hp2.sym.typ=procsym) then
+ begin
+ { the manglednames can already be the same when the procedure
+ is declared with cdecl }
+ pd:=tprocdef(tprocsym(hp2.sym).ProcdefList[0]);
+ if pd.mangledname<>hp2.name^ then
+ begin
+{$ifdef i386}
+ { place jump in al_procedures }
+ current_asmdata.asmlists[al_procedures].concat(Tai_align.Create_op(4,$90));
+ current_asmdata.asmlists[al_procedures].concat(Tai_symbol.Createname_global(hp2.name^,AT_FUNCTION,0));
+ current_asmdata.asmlists[al_procedures].concat(Taicpu.Op_sym(A_JMP,S_NO,current_asmdata.RefAsmSymbol(pd.mangledname)));
+ current_asmdata.asmlists[al_procedures].concat(Tai_symbol_end.Createname(hp2.name^));
+{$endif i386}
+ end;
+ end
+ else
+ //Comment(V_Error,'Exporting of variables is not supported under netware');
+ Message1(parser_e_no_export_of_variables_for_target,'netware');
+ hp2:=texported_item(hp2.next);
+ end;
+end;
+
+
+{*****************************************************************************
+ TLINKERNETWARE
+*****************************************************************************}
+
+Constructor TLinkerNetware.Create;
+begin
+ Inherited Create;
+end;
+
+
+procedure TLinkerNetware.SetDefaultInfo;
+begin
+ with Info do
+ begin
+ {$ifndef netware}
+ ExeCmd[1]:= FindUtil(utilsprefix+'ld') + ' -Ur -T $RES $STRIP -o $TMPOBJ';
+ ExeCmd[2]:= FindUtil(utilsprefix+'nlmconv') + ' -T$RES';
+ {$else}
+ {for running on netware we need absolute pathes since ld has another working directory}
+ ExeCmd[1]:= FindUtil(utilsprefix+'ld') + ' -Ur -T '+FExpand(outputexedir+Info.ResName)+' $STRIP -o '+Fexpand(outputexedir+tmpLinkFileName);
+ ExeCmd[2]:= FindUtil(utilsprefix+'nlmconv') + ' -T'+FExpand(outputexedir+'n'+Info.ResName);
+ {$endif}
+ end;
+end;
+
+
+Function TLinkerNetware.WriteResponseFile(isdll:boolean) : Boolean;
+Var
+ linkres : TLinkRes;
+ i : longint;
+ s,s2,s3 : TCmdStr;
+ ProgNam : string [80];
+ NlmNam : string [80];
+ hp2 : texported_item; { for exports }
+ p : byte;
+begin
+ WriteResponseFile:=False;
+
+ ProgNam := current_module.exefilename^;
+ i:=Pos(target_info.exeext,ProgNam);
+ if i>0 then
+ Delete(ProgNam,i,255);
+ NlmNam := ProgNam + target_info.exeext;
+
+ { Open link.res file }
+ LinkRes:=TLinkRes.Create(outputexedir+Info.ResName); {for ld}
+ NLMConvLinkFile:=TLinkRes.Create(outputexedir+'n'+Info.ResName); {for nlmconv, written in CreateExeFile}
+
+ p := Pos ('"', Description);
+ while (p > 0) do
+ begin
+ delete (Description,p,1);
+ p := Pos ('"', Description);
+ end;
+ if Description <> '' then
+ NLMConvLinkFile.Add('DESCRIPTION "' + Description + '"');
+ NLMConvLinkFile.Add('VERSION '+tostr(dllmajor)+','+tostr(dllminor)+','+tostr(dllrevision));
+
+ p := Pos ('"', nwscreenname);
+ while (p > 0) do
+ begin
+ delete (nwscreenname,p,1);
+ p := Pos ('"', nwscreenname);
+ end;
+ p := Pos ('"', nwthreadname);
+ while (p > 0) do
+ begin
+ delete (nwthreadname,p,1);
+ p := Pos ('"', nwthreadname);
+ end;
+ p := Pos ('"', nwcopyright);
+ while (p > 0) do
+ begin
+ delete (nwcopyright,p,1);
+ p := Pos ('"', nwcopyright);
+ end;
+
+ if nwscreenname <> '' then
+ NLMConvLinkFile.Add('SCREENNAME "' + nwscreenname + '"');
+ if nwthreadname <> '' then
+ NLMConvLinkFile.Add('THREADNAME "' + nwthreadname + '"');
+ if nwcopyright <> '' then
+ NLMConvLinkFile.Add('COPYRIGHT "' + nwcopyright + '"');
+
+ if stacksize < minStackSize then stacksize := minStackSize;
+ str (stacksize, s);
+ NLMConvLinkFile.Add ('STACKSIZE '+s);
+ {$ifndef netware}
+ NLMConvLinkFile.Add ('INPUT '+outputexedir+tmpLinkFileName);
+ {$else}
+ NLMConvLinkFile.Add ('INPUT '+FExpand(outputexedir+tmpLinkFileName));
+ {$endif}
+
+ { add objectfiles, start with nwpre always }
+ LinkRes.Add ('INPUT(');
+ if target_info.system = system_i386_netwlibc then
+ begin
+ s2 := FindObjectFile('nwplibc','',false);
+ if s2 = '' then
+ s2 := FindObjectFile('libcpre.gcc','',false);
+ end else
+ s2 := FindObjectFile('nwpre','',false);
+ Comment (V_Debug,'adding Object File '+s2);
+ {$ifndef netware} LinkRes.Add (s2); {$else} LinkRes.Add (FExpand(s2)); {$endif}
+
+ if target_info.system = system_i386_netwlibc then
+ begin
+ if isDll then {needed to provide main}
+ s2 := FindObjectFile('nwl_dlle','',false)
+ else
+ s2 := FindObjectFile('nwl_main','',false);
+ Comment (V_Debug,'adding Object File '+s2);
+ {$ifndef netware} LinkRes.Add (s2); {$else} LinkRes.Add (FExpand(s2)); {$endif}
+ end;
+
+ { main objectfiles, add to linker input }
+ while not ObjectFiles.Empty do
+ begin
+ s:=ObjectFiles.GetFirst;
+ if s<>'' then
+ begin
+ s2 := FindObjectFile (s,'',false);
+ Comment (V_Debug,'adding Object File '+s2);
+ {$ifndef netware} LinkRes.Add (s2); {$else} LinkRes.Add (FExpand(s2)); {$endif}
+ end;
+ end;
+ LinkRes.Add (')');
+
+ { output file (nlm), add to nlmconv }
+ {$ifndef netware}
+ NLMConvLinkFile.Add ('OUTPUT ' + NlmNam);
+ {$else}
+ NLMConvLinkFile.Add ('OUTPUT ' + FExpand(NlmNam));
+ {$endif}
+
+ { start and stop-procedures }
+
+ if target_info.system = system_i386_netwlibc then
+ begin
+ NLMConvLinkFile.Add ('START _LibCPrelude');
+ NLMConvLinkFile.Add ('EXIT _LibCPostlude');
+ NLMConvLinkFile.Add ('CHECK _LibCCheckUnload');
+ NLMConvLinkFile.Add ('REENTRANT'); { needed by older libc versions }
+ end else
+ begin
+ NLMConvLinkFile.Add ('START _Prelude'); { defined in rtl/netware/nwpre.as }
+ NLMConvLinkFile.Add ('EXIT _Stop'); { nwpre.as }
+ NLMConvLinkFile.Add ('CHECK FPC_NW_CHECKFUNCTION'); { system.pp }
+ end;
+
+
+ if not (cs_link_strip in current_settings.globalswitches) then
+ begin
+ NLMConvLinkFile.Add ('DEBUG');
+ Comment(V_Debug,'DEBUG');
+ end;
+
+ { Write staticlibraries }
+ if not StaticLibFiles.Empty then
+ begin
+ LinkRes.Add ('GROUP(');
+ While not StaticLibFiles.Empty do
+ begin
+ S:=lower (StaticLibFiles.GetFirst);
+ if s<>'' then
+ begin
+ {ad: that's a hack !
+ whith -XX we get the .a files as static libs (in addition to the
+ imported libraries}
+ if (pos ('.a',s) <> 0) OR (pos ('.A', s) <> 0) then
+ begin
+ S2 := FindObjectFile(s,'',false);
+ {$ifndef netware} LinkRes.Add (s2); {$else} LinkRes.Add (FExpand(s2)); {$endif}
+ Comment(V_Debug,'adding Object File (StaticLibFiles) '+S2);
+ end else
+ begin
+ i:=Pos(target_info.staticlibext,S);
+ if i>0 then
+ Delete(S,i,255);
+ S := S + '.imp'; S2 := '';
+ librarysearchpath.FindFile(S,false,S2);
+ {$ifdef netware}
+ Comment(V_Debug,'IMPORT @'+s2);
+ s2 := FExpand (S2);
+ {$endif}
+ NLMConvLinkFile.Add('IMPORT @'+S2);
+ Comment(V_Debug,'IMPORT @'+s2);
+ end;
+ end
+ end;
+ LinkRes.Add (')');
+ end;
+
+ if not SharedLibFiles.Empty then
+ begin
+ While not SharedLibFiles.Empty do
+ begin
+ {because of upper/lower case mix, we may get duplicate
+ names but nlmconv ignores that.
+ Here we are setting the import-files for nlmconv. I.e. for
+ the module clib or clib.nlm we add IMPORT @clib.imp and also
+ the module clib.nlm (autoload)
+ ? may it be better to set autoload's via StaticLibFiles ? }
+ S:=lower (SharedLibFiles.GetFirst);
+ if s<>'' then
+ begin
+ s2:=s;
+ i:=Pos(target_info.sharedlibext,S);
+ if i>0 then
+ Delete(S,i,255);
+ if s[1] = '!' then
+ begin // special, with ! only the imp will be included but no module is autoloaded, needed i.e. for netware.imp
+ S := copy(S,2,255) + '.imp';
+ librarysearchpath.FindFile(S,false,S3);
+ {$ifdef netware}
+ Comment(V_Debug,'IMPORT @'+S3);
+ S3 := FExpand (S3);
+ {$endif}
+ NLMConvLinkFile.Add('IMPORT @'+S3);
+ Comment(V_Debug,'IMPORT @'+S3);
+ end else
+ begin
+ S := S + '.imp';
+ librarysearchpath.FindFile(S,false,S3);
+ {$ifdef netware}
+ Comment(V_Debug,'IMPORT @'+S3);
+ S3 := FExpand (S3);
+ {$endif}
+ NLMConvLinkFile.Add('IMPORT @'+S3);
+ NLMConvLinkFile.Add('MODULE '+s2);
+ Comment(V_Debug,'MODULE '+S2);
+ Comment(V_Debug,'IMPORT @'+S3);
+ end;
+ end;
+ end;
+ end;
+
+ { write exports }
+ hp2:=texported_item(current_module._exports.first);
+ while assigned(hp2) do
+ begin
+ if not hp2.is_var then
+ begin
+ { Export the Symbol }
+ Comment(V_Debug,'EXPORT '+hp2.name^);
+ NLMConvLinkFile.Add ('EXPORT '+hp2.name^);
+ end
+ else
+ { really, i think it is possible }
+ Message1(parser_e_no_export_of_variables_for_target,'netware');
+ hp2:=texported_item(hp2.next);
+ end;
+
+{ Write and Close response for ld, response for nlmconv is in NLMConvLinkFile(not written) }
+ linkres.writetodisk;
+ LinkRes.Free;
+
+{ pass options from -k to nlmconv, ; is interpreted as newline }
+ s := ParaLinkOptions;
+ while(Length(s) > 0) and (s[1] = ' ') do
+ delete (s,1,1);
+ p := pos ('"',s);
+ while p > 0 do
+ begin
+ delete (s,p,1);
+ p := pos ('"',s);
+ end;
+
+ p := pos (';',s);
+ while p > 0 do
+ begin
+ s2 := copy(s,1,p-1);
+ comment (V_Debug,'adding "'+s2+'" to nlmvonv input');
+ NLMConvLinkFile.Add(s2);
+ delete (s,1,p);
+ p := pos (';',s);
+ end;
+ if s <> '' then
+ begin
+ comment (V_Debug,'adding "'+s+'" to nlmvonv input');
+ NLMConvLinkFile.Add(s);
+ end;
+
+ WriteResponseFile:=True;
+end;
+
+
+function TLinkerNetware.MakeExecutable:boolean;
+var
+ binstr,
+ cmdstr : TCmdStr;
+ success : boolean;
+ StripStr : string[2];
+begin
+ if not(cs_link_nolink in current_settings.globalswitches) then
+ Message1(exec_i_linking,current_module.exefilename^);
+
+{ Create some replacements }
+ StripStr:='';
+
+ if (cs_link_strip in current_settings.globalswitches) then
+ StripStr:='-s';
+
+{ Write used files and libraries and create Headerfile for
+ nlmconv in NLMConvLinkFile }
+ WriteResponseFile(false);
+
+{ Call linker, this will generate a new object file that will be passed
+ to nlmconv. Otherwise we could not create nlms without debug info }
+ SplitBinCmd(Info.ExeCmd[1],binstr,cmdstr);
+ Replace(cmdstr,'$EXE',maybequoted(current_module.exefilename^));
+ Replace(cmdstr,'$RES',maybequoted(outputexedir+Info.ResName));
+ Replace(cmdstr,'$STRIP',StripStr);
+ Replace(cmdstr,'$TMPOBJ',maybequoted(outputexedir+tmpLinkFileName));
+ Comment (v_debug,'Executing '+BinStr+' '+cmdstr);
+ success:=DoExec(BinStr,CmdStr,true,false);
+
+ { Remove ReponseFile }
+ if (success) and not(cs_link_nolink in current_settings.globalswitches) then
+ DeleteFile(outputexedir+Info.ResName);
+
+{ Call nlmconv }
+ if success then
+ begin
+ NLMConvLinkFile.writetodisk;
+ NLMConvLinkFile.Free;
+ SplitBinCmd(Info.ExeCmd[2],binstr,cmdstr);
+ Replace(cmdstr,'$RES',maybequoted(outputexedir+'n'+Info.ResName));
+ Comment (v_debug,'Executing '+BinStr+' '+cmdstr);
+ success:=DoExec(BinStr,CmdStr,true,false);
+ if (success) and not(cs_link_nolink in current_settings.globalswitches) then
+ begin
+ DeleteFile(outputexedir+'n'+Info.ResName);
+ DeleteFile(outputexedir+tmpLinkFileName);
+ end;
+ end;
+
+ MakeExecutable:=success; { otherwise a recursive call to link method }
+end;
+
+
+{****************************************************************************
+ TInternalLinkerNetware
+****************************************************************************}
+
+ constructor TInternalLinkerNetware.Create;
+ begin
+ inherited Create;
+ CExeoutput:=TNLMexeoutput;
+ CObjInput:=TNLMCoffObjInput;
+ nlmSpecialSymbols_Segments := TFPHashList.create;
+ end;
+
+ destructor TInternalLinkerNetware.destroy;
+ begin
+ if assigned(nlmSpecialSymbols_Segments) then
+ begin
+ nlmSpecialSymbols_Segments.Free;
+ nlmSpecialSymbols_Segments := nil;
+ end;
+ inherited destroy;
+ end;
+
+ procedure TInternalLinkerNetware.DefaultLinkScript;
+ var
+ s,s2 : TCmdStr;
+ secname,
+ secnames : string;
+ hasCopyright,
+ hasScreenname,
+ hasThreadname,
+ hasVersion,
+ hasDescription,
+ hasStacksize: boolean;
+ t : text;
+
+
+
+ procedure addLinkerOption(s : string);
+ var op : string;
+ begin
+ if s = '' then exit;
+ if s[1] = '#' then exit;
+ LinkScript.Concat(s);
+ op := upper(GetToken(s,' '));
+ {check for options via -k that can also be specified vie
+ compiler directives in source, -k options will override
+ options in source}
+ if op = 'COPYRIGHT' then hasCopyright := true else
+ if op = 'SCREENNAME' then hasScreenname := true else
+ if op = 'THREADNAME' then hasThreadname := true else
+ if op = 'VERSION' then hasVersion := true else
+ if op = 'DESCRIPTION' then hasDescription := true else
+ if (op = 'STACK') or (op = 'STACKSIZE') then hasStacksize := true;
+ end;
+
+ { add linker scropt specified by -k@FileName }
+ procedure addLinkerOptionsFile (fileName : string);
+ var
+ t : text;
+ option : string;
+ fn : TCmdStr;
+ begin
+ fn := fileName;
+ if not sysutils.fileExists(fn) then
+ if not includesearchpath.FindFile(fileName,true,fn) then
+ begin
+ comment(v_error,'linker options file "'+fileName+'" not found');
+ exit;
+ end;
+ assign(t,fn); reset(t);
+ while not eof(t) do
+ begin
+ readln(t,option);
+ addLinkerOption(option);
+ end;
+ close(t);
+ end;
+
+ { add linker options specified by command line parameter -k }
+ procedure addLinkerOptions;
+ var
+ s,option : string;
+ begin
+ s := ParaLinkOptions;
+ option := GetToken(s,';');
+ while option <> '' do
+ begin
+ if copy(option,1,1)='@' then
+ begin
+ delete(option,1,1);
+ addLinkerOptionsFile(option);
+ end else
+ addLinkerOption(option);
+ option := GetToken(s,';');
+ end;
+ end;
+
+ { default: nwpre but can be specified via linker options
+ bacuse this has to be the first object, we have to scan
+ linker options before adding other options }
+
+ function findPreludeInFile (fileName : string):string;
+ var
+ t : text;
+ option,s : string;
+ fn : TCmdStr;
+ begin
+ result := '';
+ fn := fileName;
+ if not sysutils.fileExists(fn) then
+ if not includesearchpath.FindFile(fileName,true,fn) then
+ begin
+ comment(v_error,'linker options file "'+fileName+'" not found');
+ exit;
+ end;
+ assign(t,fn); reset(t);
+ while not eof(t) do
+ begin
+ readln(t,option);
+ option := upper(GetToken(s,' '));
+ if option='PRELUDE' then
+ begin
+ result := getToken(s,' ');
+ close(t);
+ exit;
+ end;
+ end;
+ close(t);
+ end;
+
+ function findPrelude : string;
+ var
+ s,option,keyword : string;
+ begin
+ s := ParaLinkOptions;
+ option := GetToken(s,';');
+ while option <> '' do
+ begin
+ if copy(option,1,1)='@' then
+ begin
+ delete(option,1,1);
+ result := findPreludeInFile(option);
+ if result <> '' then exit;
+ end else
+ begin
+ keyword := GetToken(option,' ');
+ if keyword = 'PRELUDE' then
+ begin
+ result := GetToken(option,' ');
+ exit;
+ end;
+ end;
+ option := GetToken(s,';');
+ end;
+ if target_info.system = system_i386_netwlibc then
+ result := 'libcpre'
+ else
+ result := 'nwpre';
+ end;
+
+ begin
+ with LinkScript do
+ begin
+ prelude := findPrelude; // needs to be first object, can be specified by -k"PRELUDE ObjFileName"
+ if prelude = '' then internalerror(201103271);
+ if pos ('.',prelude) = 0 then prelude := prelude + '.o';
+ s2 := FindObjectFile(prelude,'',false);
+ Comment (V_Debug,'adding init Object File '+s2);
+ Concat('READOBJECT '+MaybeQuoted(s2));
+ while not ObjectFiles.Empty do
+ begin
+ s:=ObjectFiles.GetFirst;
+ if s<>'' then
+ begin
+ Concat('READOBJECT '+MaybeQuoted(s));
+ Comment (V_Debug,'adding Object File '+s);
+ end;
+ end;
+ while not StaticLibFiles.Empty do
+ begin
+ s:=StaticLibFiles.GetFirst;
+ if s<>'' then
+ begin
+ Comment (V_Debug,'adding StaticLibFile '+s);
+ Concat('READSTATICLIBRARY '+MaybeQuoted(s));
+ end;
+ end;
+ { While not SharedLibFiles.Empty do
+ begin
+ S:=SharedLibFiles.GetFirst;
+ if FindLibraryFile(s,target_info.staticClibprefix,target_info.importlibext,s2) then
+ begin
+ Comment (V_Debug,'adding LibraryFile '+s);
+ Concat('READSTATICLIBRARY '+MaybeQuoted(s2));
+ end else
+ Comment(V_Error,'Import library not found for '+S);
+ end;}
+ if IsSharedLibrary then
+ Concat('ISSHAREDLIBRARY');
+ ConcatEntryName;
+ Concat('IMAGEBASE $' + hexStr(0, SizeOf(imagebase)*2));
+ Concat('HEADER');
+ Concat('EXESECTION .text');
+ Concat(' SYMBOL __text_start__'); nlmSpecialSymbols_Segments.Add('__text_start__',pointer(ptruint(Section_text)));
+ Concat(' OBJSECTION .text*');
+ Concat(' SYMBOL ___CTOR_LIST__'); nlmSpecialSymbols_Segments.Add('___CTOR_LIST__',pointer(ptruint(Section_text)));
+ Concat(' SYMBOL __CTOR_LIST__'); nlmSpecialSymbols_Segments.Add('__CTOR_LIST__',pointer(ptruint(Section_text)));
+ Concat(' LONG -1');
+ Concat(' OBJSECTION .ctor*');
+ Concat(' LONG 0');
+ Concat(' SYMBOL ___DTOR_LIST__'); nlmSpecialSymbols_Segments.Add('___DTOR_LIST__',pointer(ptruint(Section_text)));
+ Concat(' SYMBOL __DTOR_LIST__'); nlmSpecialSymbols_Segments.Add('__DTOR_LIST__',pointer(ptruint(Section_text)));
+ Concat(' LONG -1');
+ Concat(' OBJSECTION .dtor*');
+ Concat(' LONG 0');
+ Concat(' SYMBOL etext'); nlmSpecialSymbols_Segments.Add('etext',pointer(ptruint(Section_text)));
+ Concat('ENDEXESECTION');
+
+ Concat('EXESECTION .data');
+ Concat(' SYMBOL __data_start__'); nlmSpecialSymbols_Segments.Add('__data_start__',pointer(ptruint(Section_data)));
+ Concat(' OBJSECTION .data*');
+ Concat(' OBJSECTION .fpc*');
+ Concat(' SYMBOL edata'); nlmSpecialSymbols_Segments.Add('edata',pointer(ptruint(Section_data)));
+ Concat(' SYMBOL __data_end__'); nlmSpecialSymbols_Segments.Add('__data_end__',pointer(ptruint(Section_data)));
+ Concat('ENDEXESECTION');
+
+ Concat('EXESECTION .bss');
+ Concat(' SYMBOL __bss_start__'); nlmSpecialSymbols_Segments.Add('__bss_start__',pointer(ptruint(Section_data)));
+ Concat(' OBJSECTION .bss*');
+ Concat(' SYMBOL __bss_end__'); nlmSpecialSymbols_Segments.Add('__bss_end__',pointer(ptruint(Section_data)));
+ Concat('ENDEXESECTION');
+
+ Concat('EXESECTION .imports');
+ Concat(' SYMBOL __imports_start__');
+ Concat(' OBJSECTION .imports*');
+ Concat(' SYMBOL __imports_end__');
+ Concat('ENDEXESECTION');
+
+ Concat('EXESECTION .modules');
+ Concat(' SYMBOL __modules_start__');
+ Concat(' OBJSECTION .modules*');
+ Concat(' SYMBOL __modules_end__');
+ Concat('ENDEXESECTION');
+
+ Concat('EXESECTION .exports');
+ Concat(' SYMBOL __exports_start__');
+ Concat(' OBJSECTION .exports*');
+ Concat(' SYMBOL __exports_end__');
+ Concat('ENDEXESECTION');
+
+ Concat('EXESECTION .reloc');
+ Concat(' SYMBOL __reloc_start__');
+ Concat(' OBJSECTION .reloc*');
+ Concat(' SYMBOL __reloc_end__');
+ Concat('ENDEXESECTION');
+
+ Concat('EXESECTION .xdc');
+ Concat(' OBJSECTION .xdc*');
+ Concat('ENDEXESECTION');
+
+ Concat('EXESECTION .custom');
+ Concat(' OBJSECTION .custom*');
+ Concat('ENDEXESECTION');
+
+ Concat('EXESECTION .messages');
+ Concat(' OBJSECTION .messages*');
+ Concat('ENDEXESECTION');
+
+ Concat('EXESECTION .help');
+ Concat(' OBJSECTION .help*');
+ Concat('ENDEXESECTION');
+
+ Concat('EXESECTION .rdata');
+ Concat(' SYMBOL ___RUNTIME_PSEUDO_RELOC_LIST__');
+ Concat(' SYMBOL __RUNTIME_PSEUDO_RELOC_LIST__');
+ Concat(' OBJSECTION .rdata_runtime_pseudo_reloc');
+ Concat(' SYMBOL ___RUNTIME_PSEUDO_RELOC_LIST_END__');
+ Concat(' SYMBOL __RUNTIME_PSEUDO_RELOC_LIST_END__');
+ Concat(' OBJSECTION .rdata*');
+ Concat(' OBJSECTION .rodata*');
+ Concat('ENDEXESECTION');
+ Concat('EXESECTION .pdata');
+ Concat(' OBJSECTION .pdata');
+ Concat('ENDEXESECTION');
+ secnames:='.edata,.rsrc,.gnu_debuglink,'+
+ '.debug_aranges,.debug_pubnames,.debug_info,.debug_abbrev,.debug_line,.debug_frame,.debug_str,.debug_loc,'+
+ '.debug_macinfo,.debug_weaknames,.debug_funcnames,.debug_typenames,.debug_varnames,.debug_ranges';
+ repeat
+ secname:=gettoken(secnames,',');
+ if secname='' then
+ break;
+ Concat('EXESECTION '+secname);
+ Concat(' OBJSECTION '+secname+'*');
+ Concat('ENDEXESECTION');
+ until false;
+ { Can't use the generic rules, because that will add also .stabstr to .stab }
+ Concat('EXESECTION .stab');
+ Concat(' OBJSECTION .stab');
+ Concat('ENDEXESECTION');
+ Concat('EXESECTION .stabstr');
+ Concat(' OBJSECTION .stabstr');
+ Concat('ENDEXESECTION');
+ Concat('STABS');
+ Concat('SYMBOLS');
+ Concat('');
+
+ hasCopyright := false;
+ hasScreenname := false;
+ hasThreadname := false;
+ hasVersion := false;
+ hasDescription := false;
+ hasStacksize := false;
+ addLinkerOptions;
+ if not hasCopyright then
+ if nwcopyright <> '' then
+ Concat('COPYRIGHT "'+nwCopyright+'"');
+ if not hasScreenname then
+ if nwscreenname <> '' then
+ Concat('SCREENNAME "'+nwscreenname+'"');
+ if not hasThreadname then
+ if nwthreadname <> '' then
+ Concat('THREADNAME "'+nwthreadname+'"');
+ if not hasVersion then
+ Concat('VERSION '+tostr(dllmajor)+' '+tostr(dllminor)+' '+tostr(dllrevision));
+ if not hasDescription then
+ if description <> '' then
+ Concat ('DESCRIPTION "'+description+'"');
+ if not hasStacksize then
+ if MaxStackSizeSetExplicity then
+ begin
+ if stacksize < minStackSize then stacksize := minStackSize;
+ Concat ('STACKSIZE '+tostr(stacksize));
+ end else
+ Concat ('STACKSIZE '+tostr(minStackSize));
+ if target_info.system = system_i386_netwlibc then
+ Concat ('REENTRANT'); { needed by older libc versions }
+ end;
+
+ // add symbols needed by nwpre. We have not loaded the ppu,
+ // therefore we do not know the externals so read it from nwpre.imp
+ s := ChangeFileExt(prelude,'.imp'); // nwpre.imp
+ if not librarysearchpath.FindFile(s,true,s2) then
+ begin
+ comment(v_error,s+' not found');
+ exit;
+ end;
+ assign(t,s2); reset(t);
+ while not eof(t) do
+ begin
+ readln(t,s);
+ s := trimspace(s);
+ if (length(s) > 0) then
+ if copy(s,1,1) <> '#' then
+ AddImportSymbol('!clib',s,s,0,false);
+ end;
+ close(t);
+ end;
+
+
+ procedure TInternalLinkerNetware.InitSysInitUnitName;
+ begin
+ //if target_info.system=system_i386_netware then
+ // GlobalInitSysInitUnitName(self);
+ end;
+
+ procedure TInternalLinkerNetware.ConcatEntryName;
+ begin
+ with LinkScript do
+ begin
+ if IsSharedLibrary then
+ begin
+ Concat('ISSHAREDLIBRARY');
+ Concat('ENTRYNAME _Prelude')
+ end
+ else
+ begin
+ Concat('ENTRYNAME _Prelude')
+ end;
+ end;
+ end;
+
+
+ Function TInternalLinkerNetware.MakeSharedLibrary:boolean;
+ begin
+ Comment(V_Error,'Make shared library not supported for netware');
+ MakeSharedLibrary := false;
+ end;
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+
+initialization
+ RegisterExternalLinker(system_i386_netware_info,TLinkerNetware);
+ RegisterInternalLinker(system_i386_netware_info,TInternalLinkerNetware);
+ RegisterImport(system_i386_netware,TImportLibNetware);
+ RegisterExport(system_i386_netware,TExportLibNetware);
+ RegisterTarget(system_i386_netware_info);
+end.
diff --git a/closures/compiler/systems/t_os2.pas b/closures/compiler/systems/t_os2.pas
new file mode 100644
index 0000000000..ff0ca20106
--- /dev/null
+++ b/closures/compiler/systems/t_os2.pas
@@ -0,0 +1,556 @@
+{
+ Copyright (c) 1998-2002 by Daniel Mantione
+ Portions Copyright (c) 1998-2002 Eberhard Mattes
+
+ Unit to write out import libraries and def files for OS/2
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+{
+ A lot of code in this unit has been ported from C to Pascal from the
+ emximp utility, part of the EMX development system. Emximp is copyrighted
+ by Eberhard Mattes. Note: Eberhard doesn't know much about the Pascal
+ port, please send questions to Tomas Hajny <hajny@freepascal.org> or
+ Daniel Mantione <daniel@freepascal.org>.
+}
+unit t_os2;
+
+{$i fpcdefs.inc}
+
+interface
+
+
+implementation
+
+ uses
+ SysUtils,
+ cutils,cfileutl,cclasses,
+ globtype,systems,symconst,symdef,
+ globals,verbose,fmodule,script,
+ import,link,i_os2,ogbase;
+
+ type
+ timportlibos2=class(timportlib)
+ procedure generatelib;override;
+ end;
+
+ tlinkeros2=class(texternallinker)
+ private
+ Function WriteResponseFile(isdll:boolean) : Boolean;
+ public
+ constructor Create;override;
+ procedure SetDefaultInfo;override;
+ function MakeExecutable:boolean;override;
+ end;
+
+
+const profile_flag:boolean=false;
+
+const n_ext = 1;
+ n_abs = 2;
+ n_text = 4;
+ n_data = 6;
+ n_bss = 8;
+ n_imp1 = $68;
+ n_imp2 = $6a;
+
+type reloc=packed record {This is the layout of a relocation table
+ entry.}
+ address:longint; {Fixup location}
+ remaining:longint;
+ {Meaning of bits for remaining:
+ 0..23: Symbol number or segment
+ 24: Self-relative fixup if non-zero
+ 25..26: Fixup size (0: 1 byte, 1: 2, 2: 4 bytes)
+ 27: Reference to symbol or segment
+ 28..31 Not used}
+ end;
+
+ nlist=packed record {This is the layout of a symbol table entry.}
+ strofs:longint; {Offset in string table}
+ typ:byte; {Type of the symbol}
+ other:byte; {Other information}
+ desc:word; {More information}
+ value:longint; {Value (address)}
+ end;
+
+ a_out_header=packed record
+ magic:word; {Magic word, must be $0107}
+ machtype:byte; {Machine type}
+ flags:byte; {Flags}
+ text_size:longint; {Length of text, in bytes}
+ data_size:longint; {Length of initialized data, in bytes}
+ bss_size:longint; {Length of uninitialized data, in bytes}
+ sym_size:longint; {Length of symbol table, in bytes}
+ entry:longint; {Start address (entry point)}
+ trsize:longint; {Length of relocation info for text, bytes}
+ drsize:longint; {Length of relocation info for data, bytes}
+ end;
+
+ ar_hdr=packed record
+ ar_name:array[0..15] of char;
+ ar_date:array[0..11] of char;
+ ar_uid:array[0..5] of char;
+ ar_gid:array[0..5] of char;
+ ar_mode:array[0..7] of char;
+ ar_size:array[0..9] of char;
+ ar_fmag:array[0..1] of char;
+ end;
+
+var aout_str_size:longint;
+ aout_str_tab:array[0..2047] of char;
+ aout_sym_count:longint;
+ aout_sym_tab:array[0..5] of nlist;
+
+ aout_text:array[0..63] of byte;
+ aout_text_size:longint;
+
+ aout_treloc_tab:array[0..1] of reloc;
+ aout_treloc_count:longint;
+
+ aout_size:longint;
+ seq_no:longint;
+
+ ar_member_size:longint;
+
+ out_file:file;
+
+procedure PackTime (var T: TSystemTime; var P: longint);
+
+var zs:longint;
+
+begin
+ p:=-1980;
+ p:=p+t.year and 127;
+ p:=p shl 4;
+ p:=p+t.month;
+ p:=p shl 5;
+ p:=p+t.day;
+ p:=p shl 16;
+ zs:=t.hour;
+ zs:=zs shl 6;
+ zs:=zs+t.minute;
+ zs:=zs shl 5;
+ zs:=zs+t.second div 2;
+ p:=p+(zs and $ffff);
+end;
+
+
+procedure write_ar(const name:string;size:longint);
+
+var ar:ar_hdr;
+ time:TSystemTime;
+ numtime:longint;
+ tmp:string[19];
+
+
+begin
+ ar_member_size:=size;
+ fillchar(ar.ar_name,sizeof(ar.ar_name),' ');
+ move(name[1],ar.ar_name,length(name));
+ GetLocalTime(time);
+ packtime(time,numtime);
+ str(numtime,tmp);
+ fillchar(ar.ar_date,sizeof(ar.ar_date),' ');
+ move(tmp[1],ar.ar_date,length(tmp));
+ ar.ar_uid:='0 ';
+ ar.ar_gid:='0 ';
+ ar.ar_mode:='100666'#0#0;
+ str(size,tmp);
+ fillchar(ar.ar_size,sizeof(ar.ar_size),' ');
+ move(tmp[1],ar.ar_size,length(tmp));
+ ar.ar_fmag:='`'#10;
+ blockwrite(out_file,ar,sizeof(ar));
+end;
+
+procedure finish_ar;
+
+var a:byte;
+
+begin
+ a:=0;
+ if odd(ar_member_size) then
+ blockwrite(out_file,a,1);
+end;
+
+procedure aout_init;
+
+begin
+ aout_str_size:=sizeof(longint);
+ aout_sym_count:=0;
+ aout_text_size:=0;
+ aout_treloc_count:=0;
+end;
+
+function aout_sym(const name:string;typ,other:byte;desc:word;
+ value:longint):longint;
+
+begin
+ if aout_str_size+length(name)+1>sizeof(aout_str_tab) then
+ internalerror(200504245);
+ if aout_sym_count>=sizeof(aout_sym_tab) div sizeof(aout_sym_tab[0]) then
+ internalerror(200504246);
+ aout_sym_tab[aout_sym_count].strofs:=aout_str_size;
+ aout_sym_tab[aout_sym_count].typ:=typ;
+ aout_sym_tab[aout_sym_count].other:=other;
+ aout_sym_tab[aout_sym_count].desc:=desc;
+ aout_sym_tab[aout_sym_count].value:=value;
+ strPcopy(@aout_str_tab[aout_str_size],name);
+ aout_str_size:=aout_str_size+length(name)+1;
+ aout_sym:=aout_sym_count;
+ inc(aout_sym_count);
+end;
+
+procedure aout_text_byte(b:byte);
+
+begin
+ if aout_text_size>=sizeof(aout_text) then
+ internalerror(200504247);
+ aout_text[aout_text_size]:=b;
+ inc(aout_text_size);
+end;
+
+procedure aout_text_dword(d:longint);
+
+type li_ar=array[0..3] of byte;
+
+begin
+ aout_text_byte(li_ar(d)[0]);
+ aout_text_byte(li_ar(d)[1]);
+ aout_text_byte(li_ar(d)[2]);
+ aout_text_byte(li_ar(d)[3]);
+end;
+
+procedure aout_treloc(address,symbolnum,pcrel,len,ext:longint);
+
+begin
+ if aout_treloc_count>=sizeof(aout_treloc_tab) div sizeof(reloc) then
+ internalerror(200504248);
+ aout_treloc_tab[aout_treloc_count].address:=address;
+ aout_treloc_tab[aout_treloc_count].remaining:=symbolnum+pcrel shl 24+
+ len shl 25+ext shl 27;
+ inc(aout_treloc_count);
+end;
+
+procedure aout_finish;
+
+begin
+ while (aout_text_size and 3)<>0 do
+ aout_text_byte ($90);
+ aout_size:=sizeof(a_out_header)+aout_text_size+aout_treloc_count*
+ sizeof(reloc)+aout_sym_count*sizeof(aout_sym_tab[0])+aout_str_size;
+end;
+
+procedure aout_write;
+
+var ao:a_out_header;
+
+begin
+ ao.magic:=$0107;
+ ao.machtype:=0;
+ ao.flags:=0;
+ ao.text_size:=aout_text_size;
+ ao.data_size:=0;
+ ao.bss_size:=0;
+ ao.sym_size:=aout_sym_count*sizeof(aout_sym_tab[0]);
+ ao.entry:=0;
+ ao.trsize:=aout_treloc_count*sizeof(reloc);
+ ao.drsize:=0;
+ blockwrite(out_file,ao,sizeof(ao));
+ blockwrite(out_file,aout_text,aout_text_size);
+ blockwrite(out_file,aout_treloc_tab,sizeof(reloc)*aout_treloc_count);
+ blockwrite(out_file,aout_sym_tab,sizeof(aout_sym_tab[0])*aout_sym_count);
+ plongint(@aout_str_tab)^:=aout_str_size;
+ blockwrite(out_file,aout_str_tab,aout_str_size);
+end;
+
+
+procedure AddImport(const module:string;index:longint;const name,mangledname:string);
+{mangledname= Assembler label of the function to import.
+ module = Name of DLL to import from.
+ index = Index of function in DLL. Use 0 to import by name.
+ name = Name of function in DLL. Ignored when index=0;}
+(*
+var tmp1,tmp2,tmp3:string;
+*)
+var tmp1,tmp2,tmp3:string;
+ sym_mcount,sym_import:longint;
+ fixup_mcount,fixup_import:longint;
+begin
+ aout_init;
+ tmp2:=mangledname;
+(*
+ tmp2:=func;
+ if profile_flag and not (copy(func,1,4)='_16_') then
+*)
+ if profile_flag and not (copy(tmp2,1,4)='_16_') then
+ begin
+ {sym_entry:=aout_sym(func,n_text+n_ext,0,0,aout_text_size);}
+ sym_mcount:=aout_sym('__mcount',n_ext,0,0,0);
+ {Use, say, "_$U_DosRead" for "DosRead" to import the
+ non-profiled function.}
+(*
+ tmp2:='__$U_'+func;
+ sym_import:=aout_sym(tmp2,n_ext,0,0,0);
+*)
+ sym_import:=aout_sym(tmp2,n_ext,0,0,0);
+ aout_text_byte($55); {push ebp}
+ aout_text_byte($89); {mov ebp, esp}
+ aout_text_byte($e5);
+ aout_text_byte($e8); {call _mcount}
+ fixup_mcount:=aout_text_size;
+ aout_text_dword(0-(aout_text_size+4));
+ aout_text_byte($5d); {pop ebp}
+ aout_text_byte($e9); {jmp _$U_DosRead}
+ fixup_import:=aout_text_size;
+ aout_text_dword(0-(aout_text_size+4));
+
+ aout_treloc(fixup_mcount,sym_mcount,1,2,1);
+ aout_treloc (fixup_import, sym_import,1,2,1);
+ end;
+ str(seq_no,tmp1);
+ tmp1:='IMPORT#'+tmp1;
+(*
+ if name='' then
+*)
+ if index<>0 then
+ begin
+ str(index,tmp3);
+(*
+ tmp3:=func+'='+module+'.'+tmp3;
+*)
+ tmp3:=Name+'='+module+'.'+tmp3;
+ end
+ else
+ tmp3:=Name+'='+module+'.'+name;
+(*
+ tmp3:=func+'='+module+'.'+name;
+ aout_sym(tmp2,n_imp1+n_ext,0,0,0);
+*)
+ aout_sym(tmp2,n_imp1+n_ext,0,0,0);
+ aout_sym(tmp3,n_imp2+n_ext,0,0,0);
+ aout_finish;
+ write_ar(tmp1,aout_size);
+ aout_write;
+ finish_ar;
+ inc(seq_no);
+end;
+
+ procedure timportlibos2.generatelib;
+ const
+ ar_magic:array[1..8] of char='!<arch>'#10;
+ var
+ i,j : longint;
+ ImportLibrary : TImportLibrary;
+ ImportSymbol : TImportSymbol;
+ begin
+ seq_no:=1;
+ current_module.linkotherstaticlibs.add(Current_Module.ImportLibFilename^,link_always);
+ assign(out_file,Current_Module.ImportLibFilename^);
+ rewrite(out_file,1);
+ blockwrite(out_file,ar_magic,sizeof(ar_magic));
+
+ for i:=0 to current_module.ImportLibraryList.Count-1 do
+ begin
+ ImportLibrary:=TImportLibrary(current_module.ImportLibraryList[i]);
+ for j:=0 to ImportLibrary.ImportSymbolList.Count-1 do
+ begin
+ ImportSymbol:=TImportSymbol(ImportLibrary.ImportSymbolList[j]);
+ AddImport(ChangeFileExt(ExtractFileName(ImportLibrary.Name),''),
+ ImportSymbol.OrdNr,ImportSymbol.Name,ImportSymbol.MangledName);
+ end;
+ end;
+ close(out_file);
+ end;
+
+
+{****************************************************************************
+ TLinkeros2
+****************************************************************************}
+
+Constructor TLinkeros2.Create;
+begin
+ Inherited Create;
+ { allow duplicated libs (PM) }
+ SharedLibFiles.doubles:=true;
+ StaticLibFiles.doubles:=true;
+end;
+
+
+procedure TLinkeros2.SetDefaultInfo;
+begin
+ with Info do
+ begin
+ ExeCmd[1]:='ld $OPT -o $OUT @$RES';
+ ExeCmd[2]:='emxbind -b $STRIP $APPTYPE $RSRC -k$STACKKB -h1 -o $EXE $OUT -ai -s8';
+ if Source_Info.Script = script_dos then
+ ExeCmd[3]:='del $OUT';
+ end;
+end;
+
+
+Function TLinkeros2.WriteResponseFile(isdll:boolean) : Boolean;
+Var
+ linkres : TLinkRes;
+ i : longint;
+ HPath : TCmdStrListItem;
+ s : string;
+begin
+ WriteResponseFile:=False;
+
+ { Open link.res file }
+ LinkRes:=TLinkRes.Create(outputexedir+Info.ResName);
+
+ { Write path to search libraries }
+ HPath:=TCmdStrListItem(current_module.locallibrarysearchpath.First);
+ while assigned(HPath) do
+ begin
+ LinkRes.Add('-L'+HPath.Str);
+ HPath:=TCmdStrListItem(HPath.Next);
+ end;
+ HPath:=TCmdStrListItem(LibrarySearchPath.First);
+ while assigned(HPath) do
+ begin
+ LinkRes.Add('-L'+HPath.Str);
+ HPath:=TCmdStrListItem(HPath.Next);
+ end;
+
+ { add objectfiles, start with prt0 always }
+ LinkRes.AddFileName(FindObjectFile('prt0','',false));
+ while not ObjectFiles.Empty do
+ begin
+ s:=ObjectFiles.GetFirst;
+ if s<>'' then
+ LinkRes.AddFileName(s);
+ end;
+
+ { Write staticlibraries }
+ { No group !! This will not work correctly PM }
+ While not StaticLibFiles.Empty do
+ begin
+ S:=StaticLibFiles.GetFirst;
+ LinkRes.AddFileName(s)
+ end;
+
+ { Write sharedlibraries like -l<lib>, also add the needed dynamic linker
+ here to be sure that it gets linked this is needed for glibc2 systems (PFV) }
+ While not SharedLibFiles.Empty do
+ begin
+ S:=SharedLibFiles.GetFirst;
+ i:=Pos(target_info.sharedlibext,S);
+ if i>0 then
+ Delete(S,i,255);
+ LinkRes.Add('-l'+s);
+ end;
+
+{ Write and Close response }
+ linkres.writetodisk;
+ LinkRes.Free;
+
+ WriteResponseFile:=True;
+end;
+
+
+function TLinkeros2.MakeExecutable:boolean;
+var
+ binstr,
+ cmdstr : TCmdStr;
+ success : boolean;
+ i : longint;
+ AppTypeStr,
+ StripStr: string[40];
+ RsrcStr : string;
+ OutName: TPathStr;
+begin
+ if not(cs_link_nolink in current_settings.globalswitches) then
+ Message1(exec_i_linking,current_module.exefilename^);
+
+{ Create some replacements }
+ OutName := ChangeFileExt(current_module.exefilename^,'.out');
+ if (cs_link_strip in current_settings.globalswitches) then
+ StripStr := '-s'
+ else
+ StripStr := '';
+ if (usewindowapi) or (AppType = app_gui) then
+ AppTypeStr := '-p'
+ else if AppType = app_fs then
+ AppTypeStr := '-f'
+ else AppTypeStr := '-w';
+ if not (Current_module.ResourceFiles.Empty) then
+ RsrcStr := '-r ' + Current_module.ResourceFiles.GetFirst
+ else
+ RsrcStr := '';
+(* Only one resource file supported, discard everything else
+ (should be already empty anyway, though). *)
+ Current_module.ResourceFiles.Clear;
+{ Write used files and libraries }
+ WriteResponseFile(false);
+
+{ Call linker }
+ success:=false;
+ for i:=1 to 3 do
+ begin
+ SplitBinCmd(Info.ExeCmd[i],binstr,cmdstr);
+ if binstr<>'' then
+ begin
+ { Is this really required? Not anymore according to my EMX docs }
+ Replace(cmdstr,'$HEAPMB',tostr((1048575) shr 20));
+ {Size of the stack when an EMX program runs in OS/2.}
+ Replace(cmdstr,'$STACKKB',tostr((stacksize+1023) shr 10));
+ {When an EMX program runs in DOS, the heap and stack share the
+ same memory pool. The heap grows upwards, the stack grows downwards.}
+ Replace(cmdstr,'$DOSHEAPKB',tostr((stacksize+1023) shr 10));
+ Replace(cmdstr,'$STRIP',StripStr);
+ Replace(cmdstr,'$APPTYPE',AppTypeStr);
+(*
+ Arrgh!!! The ancient EMX LD.EXE simply dies without saying anything
+ if the full pathname to link.res is quoted!!!!! @#$@@^%@#$^@#$^@^#$
+ This means that name of the output directory cannot contain spaces,
+ but at least it works otherwise...
+
+ Replace(cmdstr,'$RES',maybequoted(outputexedir+Info.ResName));
+*)
+ Replace(cmdstr,'$RES',outputexedir+Info.ResName);
+ Replace(cmdstr,'$OPT',Info.ExtraOptions);
+ Replace(cmdstr,'$RSRC',RsrcStr);
+ Replace(cmdstr,'$OUT',maybequoted(OutName));
+ Replace(cmdstr,'$EXE',maybequoted(current_module.exefilename^));
+ if i<>3 then
+ success:=DoExec(FindUtil(utilsprefix+binstr),cmdstr,(i=1),false)
+ else
+ success:=DoExec(binstr,cmdstr,(i=1),true);
+ end;
+ end;
+
+{ Remove ReponseFile }
+ if (success) and not(cs_link_nolink in current_settings.globalswitches) then
+ DeleteFile(outputexedir+Info.ResName);
+
+ MakeExecutable:=success; { otherwise a recursive call to link method }
+end;
+
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+initialization
+ RegisterExternalLinker(system_i386_os2_info,TLinkerOS2);
+ RegisterImport(system_i386_os2,TImportLibOS2);
+{ RegisterRes(res_wrc_os2_info,TResourceFile);}
+ RegisterTarget(system_i386_os2_info);
+end.
diff --git a/closures/compiler/systems/t_palmos.pas b/closures/compiler/systems/t_palmos.pas
new file mode 100644
index 0000000000..2d112851c4
--- /dev/null
+++ b/closures/compiler/systems/t_palmos.pas
@@ -0,0 +1,218 @@
+{
+ Copyright (c) 2001-2002 by Peter Vreman
+
+ This unit implements support import,export,link routines
+ for the (i386) Amiga target
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit t_palmos;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ link;
+
+ type
+ tlinkerPalmOS=class(texternallinker)
+ private
+ Function WriteResponseFile : Boolean;
+ public
+ constructor Create;override;
+ procedure SetDefaultInfo;override;
+ function MakeExecutable:boolean;override;
+ end;
+
+
+implementation
+
+ uses
+ SysUtils,
+ cutils,cfileutl,cclasses,
+ globtype,globals,systems,verbose,script,fmodule,i_palmos,
+ comprsrc;
+
+{****************************************************************************
+ TLinkerPalmOS
+****************************************************************************}
+
+Constructor TLinkerPalmOS.Create;
+begin
+ Inherited Create;
+ { allow duplicated libs (PM) }
+ SharedLibFiles.doubles:=true;
+ StaticLibFiles.doubles:=true;
+end;
+
+
+procedure TLinkerPalmOS.SetDefaultInfo;
+begin
+ with Info do
+ begin
+ ExeCmd[1]:='ldpalm $OPT $STRIP -N -dy -T $SCRIPT -o $EXE @$RES';
+ ExeCmd[2]:='build-prc $EXE.prc "$APPNAME" $APPID $EXE *.bin';
+ end;
+end;
+
+
+Function TLinkerPalmOS.WriteResponseFile : Boolean;
+Var
+ linkres : TLinkRes;
+ i : longint;
+ HPath : TCmdStrListItem;
+ s : string;
+ linklibc : boolean;
+begin
+ WriteResponseFile:=False;
+
+ { Open link.res file }
+ LinkRes:=TLinkRes.Create(outputexedir+Info.ResName);
+
+ { Write path to search libraries }
+ HPath:=TCmdStrListItem(current_module.locallibrarysearchpath.First);
+ while assigned(HPath) do
+ begin
+ LinkRes.Add('-L'+HPath.Str);
+ HPath:=TCmdStrListItem(HPath.Next);
+ end;
+ HPath:=TCmdStrListItem(LibrarySearchPath.First);
+ while assigned(HPath) do
+ begin
+ LinkRes.Add('-L'+HPath.Str);
+ HPath:=TCmdStrListItem(HPath.Next);
+ end;
+
+ { add objectfiles, start with crt0 always }
+ { using crt0, we should stick C compatible }
+ LinkRes.AddFileName(FindObjectFile('crt0','',false));
+
+ { main objectfiles }
+ while not ObjectFiles.Empty do
+ begin
+ s:=ObjectFiles.GetFirst;
+ if s<>'' then
+ LinkRes.AddFileName(s);
+ end;
+
+ { Write staticlibraries }
+ if not StaticLibFiles.Empty then
+ begin
+ LinkRes.Add('-(');
+ While not StaticLibFiles.Empty do
+ begin
+ S:=StaticLibFiles.GetFirst;
+ LinkRes.AddFileName(s)
+ end;
+ LinkRes.Add('-)');
+ end;
+
+ { currently the PalmOS target must be linked always against the C lib }
+ LinkRes.Add('-lcrt');
+
+ { Write sharedlibraries like -l<lib>, also add the needed dynamic linker
+ here to be sure that it gets linked this is needed for glibc2 systems (PFV) }
+ linklibc:=false;
+ While not SharedLibFiles.Empty do
+ begin
+ S:=SharedLibFiles.GetFirst;
+ if s<>'c' then
+ begin
+ i:=Pos(target_info.sharedlibext,S);
+ if i>0 then
+ Delete(S,i,255);
+ LinkRes.Add('-l'+s);
+ end
+ else
+ linklibc:=true;
+ end;
+ { be sure that libc is the last lib }
+ if linklibc then
+ begin
+ LinkRes.Add('-lc');
+ LinkRes.Add('-lgcc');
+ end;
+
+{ Write and Close response }
+ linkres.writetodisk;
+ linkres.Free;
+
+ WriteResponseFile:=True;
+end;
+
+
+function TLinkerPalmOS.MakeExecutable:boolean;
+var
+ binstr,
+ cmdstr : TCmdStr;
+ success : boolean;
+ StripStr : string[40];
+ i : longint;
+begin
+ if not(cs_link_nolink in current_settings.globalswitches) then
+ Message1(exec_i_linking,current_module.exefilename^);
+
+ { Create some replacements }
+ StripStr:='';
+ if (cs_link_strip in current_settings.globalswitches) then
+ StripStr:='-s';
+
+ { Write used files and libraries }
+ WriteResponseFile;
+
+{ Call linker }
+ success:=false;
+ for i:=1 to 2 do
+ begin
+ SplitBinCmd(Info.ExeCmd[i],binstr,cmdstr);
+ if binstr<>'' then
+ begin
+ Replace(cmdstr,'$EXE',MaybeQuoted(current_module.exefilename^));
+ Replace(cmdstr,'$OPT',Info.ExtraOptions);
+ Replace(cmdstr,'$RES',MaybeQuoted(outputexedir+Info.ResName));
+ Replace(cmdstr,'$STRIP',StripStr);
+ Replace(cmdstr,'$SCRIPT',FindUtil('palm.ld'));
+ Replace(cmdstr,'$APPNAME',palmos_applicationname);
+ Replace(cmdstr,'$APPID',palmos_applicationid);
+ success:=DoExec(FindUtil(binstr),cmdstr,(i=1),false);
+ if not success then
+ break;
+ end;
+ end;
+
+ { Remove ReponseFile }
+ if (success) and not(cs_link_nolink in current_settings.globalswitches) then
+ DeleteFile(outputexedir+Info.ResName);
+
+ MakeExecutable:=success; { otherwise a recursive call to link method }
+end;
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+initialization
+{$ifdef m68k}
+ RegisterTarget(system_m68k_palmos_info);
+ RegisterRes(res_m68k_palmos_info,TResourceFile);
+{$endif m68k}
+{$ifdef arm}
+ RegisterTarget(system_arm_palmos_info);
+ RegisterRes(res_arm_palmos_info,TResourceFile);
+{$endif arm}
+end.
diff --git a/closures/compiler/systems/t_sunos.pas b/closures/compiler/systems/t_sunos.pas
new file mode 100644
index 0000000000..77632e43ea
--- /dev/null
+++ b/closures/compiler/systems/t_sunos.pas
@@ -0,0 +1,666 @@
+{
+ Copyright (c) 1998-2008 by Peter Vreman
+
+ This unit implements support import,export,link routines
+ for the (i386) solaris target
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit t_sunos;
+
+{$i fpcdefs.inc}
+
+interface
+
+{ copy from t_linux
+// Up to now we use gld since the solaris ld seems not support .res-files}
+{-$DEFINE LinkTest} { DON't del link.res and write Info }
+{$DEFINE GnuLd}{The other is not implemented }
+
+implementation
+
+ uses
+ sysutils,
+ cutils,cfileutl,cclasses,
+ verbose,systems,globtype,globals,
+ symconst,script,
+ fmodule,aasmbase,aasmtai,aasmdata,aasmcpu,cpubase,symsym,symdef,
+ cgobj,
+ import,export,expunix,link,comprsrc,rescmn,i_sunos,ogbase;
+
+ type
+ timportlibsolaris=class(timportlib)
+ procedure generatelib;override;
+ end;
+
+ texportlibsolaris=class(texportlibunix)
+(*
+ procedure setinitname(list: TAsmList; const s: string); override;
+ procedure setfininame(list: TAsmList; const s: string); override;
+*)
+ end;
+
+ tlinkersolaris=class(texternallinker)
+ private
+ Glibc2,
+ Glibc21 : boolean;
+ use_gnu_ld : boolean;
+ linkres : TLinkRes;
+ Function WriteResponseFile(isdll:boolean) : Boolean;
+ public
+ constructor Create;override;
+ procedure SetDefaultInfo;override;
+ function MakeExecutable:boolean;override;
+ function MakeSharedLibrary:boolean;override;
+ end;
+
+
+{*****************************************************************************
+ TIMPORTLIBsolaris
+*****************************************************************************}
+
+ procedure timportlibsolaris.generatelib;
+ var
+ i : longint;
+ ImportLibrary : TImportLibrary;
+ begin
+ for i:=0 to current_module.ImportLibraryList.Count-1 do
+ begin
+ ImportLibrary:=TImportLibrary(current_module.ImportLibraryList[i]);
+ current_module.linkothersharedlibs.add(ImportLibrary.Name,link_always);
+ end;
+ end;
+
+
+{*****************************************************************************
+ TEXPORTLIBsolaris
+*****************************************************************************}
+(*
+ procedure texportlibsolaris.setinitname(list: TAsmList; const s: string);
+ begin
+ inherited setinitname(list,s);
+{$ifdef sparc}
+ new_section(list,sec_init,'',4);
+ list.concat(tai_symbol.createname_global('_init',AT_FUNCTION,0));
+ list.concat(taicpu.op_reg_const_reg(A_SAVE,NR_STACK_POINTER_REG,-96,NR_STACK_POINTER_REG));
+{$endif sparc}
+ end;
+
+
+ procedure texportlibsolaris.setfininame(list: TAsmList; const s: string);
+ begin
+ inherited setfininame(list,s);
+{$ifdef sparc}
+ new_section(list,sec_fini,'',4);
+ list.concat(tai_symbol.createname_global('_fini',AT_FUNCTION,0));
+ list.concat(taicpu.op_reg_const_reg(A_SAVE,NR_STACK_POINTER_REG,-96,NR_STACK_POINTER_REG));
+{$endif sparc}
+ end;
+*)
+{*****************************************************************************
+ TLINKERsolaris
+*****************************************************************************}
+
+Constructor TLinkersolaris.Create;
+begin
+ Inherited Create;
+
+ if cs_link_native in init_settings.globalswitches then
+ use_gnu_ld:=false
+ else
+ use_gnu_ld:=true;
+ if NOT Dontlinkstdlibpath Then
+{$ifdef x86_64}
+ LibrarySearchPath.AddPath(sysrootpath,'/lib/64;/usr/lib/64;/usr/X11R6/lib/64;/opt/sfw/lib/64',true);
+{$else not x86_64}
+ LibrarySearchPath.AddPath(sysrootpath,'/lib;/usr/lib;/usr/X11R6/lib;/opt/sfw/lib',true);
+{$endif not x86_64}
+{$ifdef LinkTest}
+ if (cs_link_staticflag in current_settings.globalswitches) then WriteLN('ForceLinkStaticFlag');
+ if (cs_link_static in current_settings.globalswitches) then WriteLN('LinkStatic-Flag');
+ if (cs_link_shared in current_settings.globalswitches) then WriteLN('LinkSynamicFlag');
+{$EndIf}
+end;
+
+
+procedure TLinkersolaris.SetDefaultInfo;
+{
+ This will also detect which libc version will be used
+}
+{$ifdef x86_64}
+const
+ gld = 'gld -m elf_x86_64 ';
+ solaris_ld = '/usr/bin/ld -64 ';
+{$endif}
+{$ifdef i386}
+const
+ gld = 'gld ';
+ solaris_ld = '/usr/bin/ld ';
+{$endif }
+{$ifdef sparc}
+const
+ gld = 'gld ';
+ solaris_ld = 'ld ';
+{$endif}
+begin
+ Glibc2:=false;
+ Glibc21:=false;
+ with Info do
+ begin
+{$IFDEF GnuLd}
+ ExeCmd[1]:=gld + '$OPT $DYNLINK $STATIC $STRIP -L. -o $EXE $RES';
+ ExeCmd[2]:=solaris_ld + '$OPT $DYNLINK $STATIC $STRIP -L . -o $EXE $RESDATA';
+ DllCmd[1]:=gld + '$OPT $INITFINI -shared -L. -o $EXE $RES';
+ DllCmd[2]:='gstrip --strip-unneeded $EXE';
+ DllCmd[3]:=solaris_ld + '$OPT $INITFINI -M $VERSIONFILE -G -Bdynamic -L. -o $EXE $RESDATA';
+ DynamicLinker:=''; { Gnu uses the default }
+ Glibc21:=false;
+{$ELSE}
+ Not Implememted
+{$ENDIF}
+ end;
+
+end;
+
+
+Function TLinkersolaris.WriteResponseFile(isdll:boolean) : Boolean;
+Var
+ i : longint;
+{ cprtobj,
+ gprtobj,
+ prtobj : string[80];}
+ HPath : TCmdStrListItem;
+ s,s2 : TCmdStr;
+ linkdynamic,
+ linklibc : boolean;
+ LinkRes2 : TLinkRes;
+begin
+ WriteResponseFile:=False;
+{ set special options for some targets }
+ linkdynamic:=not(SharedLibFiles.empty);
+{ linkdynamic:=false; // da nicht getestet }
+ linklibc:=(SharedLibFiles.Find('c')<>nil);
+{ prtobj:='prt0';
+ cprtobj:='cprt0';
+ gprtobj:='gprt0';}
+ if cs_profile in current_settings.moduleswitches then
+ begin
+{ prtobj:=gprtobj;}
+ if not glibc2 then
+ AddSharedLibrary('gmon');
+ AddSharedLibrary('c');
+ linklibc:=true;
+ end
+ else
+ begin
+ if linklibc then
+ begin
+{ prtobj:=cprtobj;}
+ end
+ else
+ AddSharedLibrary('c'); { quick hack: this solaris implementation needs alwys libc }
+ end;
+
+ if use_gnu_ld then
+ begin
+ { Open link.res file }
+ LinkRes:=TLinkRes.Create(outputexedir+Info.ResName);
+
+ { Write path to search libraries }
+ HPath:=TCmdStrListItem(current_module.locallibrarysearchpath.First);
+ while assigned(HPath) do
+ begin
+ LinkRes.Add('SEARCH_DIR('+maybequoted(HPath.Str)+')');
+ HPath:=TCmdStrListItem(HPath.Next);
+ end;
+ HPath:=TCmdStrListItem(LibrarySearchPath.First);
+ while assigned(HPath) do
+ begin
+ LinkRes.Add('SEARCH_DIR('+maybequoted(HPath.Str)+')');
+ HPath:=TCmdStrListItem(HPath.Next);
+ end;
+
+ { force local symbol resolution (i.e., inside the shared }
+ { library itself) for all non-exorted symbols, otherwise }
+ { several RTL symbols of FPC-compiled shared libraries }
+ { will be bound to those of a single shared library or }
+ { to the main program }
+ if (isdll) then
+ begin
+ LinkRes.add('VERSION');
+ LinkRes.add('{');
+ LinkRes.add(' {');
+ if not texportlibunix(exportlib).exportedsymnames.empty then
+ begin
+ LinkRes.add(' global:');
+ repeat
+ LinkRes.add(' '+texportlibunix(exportlib).exportedsymnames.getfirst+';');
+ until texportlibunix(exportlib).exportedsymnames.empty;
+ end;
+ LinkRes.add(' local:');
+ LinkRes.add(' *;');
+ LinkRes.add(' };');
+ LinkRes.add('}');
+ end;
+
+ LinkRes.Add('INPUT(');
+ { add objectfiles, start with prt0 always }
+ { solaris port contains _start inside the system unit, it
+ needs only one entry because it is linked always against libc
+ if prtobj<>'' then
+ LinkRes.AddFileName(FindObjectFile(prtobj,'',false));
+ }
+ { try to add crti and crtbegin if linking to C }
+ if linklibc then { Needed in solaris? }
+ begin
+{ if librarysearchpath.FindFile('crtbegin.o',s) then
+ LinkRes.AddFileName(s);}
+ if librarysearchpath.FindFile('crti.o',false,s) then
+ LinkRes.AddFileName(s);
+ end;
+ { main objectfiles }
+ while not ObjectFiles.Empty do
+ begin
+ s:=ObjectFiles.GetFirst;
+ if s<>'' then
+ LinkRes.AddFileName(maybequoted(s));
+ end;
+ LinkRes.Add(')');
+
+ { Write staticlibraries }
+ if not StaticLibFiles.Empty then
+ begin
+ LinkRes.Add('GROUP(');
+ While not StaticLibFiles.Empty do
+ begin
+ S:=StaticLibFiles.GetFirst;
+ LinkRes.AddFileName(maybequoted(s))
+ end;
+ LinkRes.Add(')');
+ end;
+
+ { Write sharedlibraries like -l<lib>, also add the needed dynamic linker
+ here to be sure that it gets linked this is needed for glibc2 systems (PFV) }
+ if not SharedLibFiles.Empty then
+ begin
+ LinkRes.Add('INPUT(');
+ While not SharedLibFiles.Empty do
+ begin
+ S:=SharedLibFiles.GetFirst;
+ if s<>'c' then
+ begin
+ i:=Pos(target_info.sharedlibext,S);
+ if i>0 then
+ Delete(S,i,255);
+ LinkRes.Add('-l'+s);
+ end
+ else
+ begin
+ linklibc:=true;
+ linkdynamic:=false; { libc will include the ld-solaris (war ld-linux) for us }
+ end;
+ end;
+ { be sure that libc is the last lib }
+ if linklibc then
+ LinkRes.Add('-lc');
+ { when we have -static for the linker the we also need libgcc }
+ if (cs_link_staticflag in current_settings.globalswitches) then begin
+ LinkRes.Add('-lgcc');
+ end;
+ if linkdynamic and (Info.DynamicLinker<>'') then { gld has a default, DynamicLinker is not set in solaris }
+ LinkRes.AddFileName(Info.DynamicLinker);
+ LinkRes.Add(')');
+ end;
+ { objects which must be at the end }
+ if linklibc then {needed in solaris ? }
+ begin
+ if {librarysearchpath.FindFile('crtend.o',s1) or}
+ librarysearchpath.FindFile('crtn.o',false,s2) then
+ begin
+ LinkRes.Add('INPUT(');
+{ LinkRes.AddFileName(s1);}
+ LinkRes.AddFileName(s2);
+ LinkRes.Add(')');
+ end;
+ end;
+{ Write and Close response }
+ linkres.writetodisk;
+ LinkRes.Free;
+ end
+ else { not use_gnu_ld }
+ begin
+ { Open TlinkRes, will not be written to disk }
+ LinkRes:=TLinkRes.Create(outputexedir+Info.ResName+'2');
+
+ { Write path to search libraries }
+ HPath:=TCmdStrListItem(current_module.locallibrarysearchpath.First);
+ while assigned(HPath) do
+ begin
+ LinkRes.Add('-L '+maybequoted(HPath.Str));
+ HPath:=TCmdStrListItem(HPath.Next);
+ end;
+ HPath:=TCmdStrListItem(LibrarySearchPath.First);
+ while assigned(HPath) do
+ begin
+ LinkRes.Add('-L '+maybequoted(HPath.Str));
+ HPath:=TCmdStrListItem(HPath.Next);
+ end;
+ { force local symbol resolution (i.e., inside the shared }
+ { library itself) for all non-exorted symbols, otherwise }
+ { several RTL symbols of FPC-compiled shared libraries }
+ { will be bound to those of a single shared library or }
+ { to the main program }
+ if (isdll) then
+ begin
+ LinkRes2:=TLinkRes.Create(outputexedir+Info.ResName);
+ // LinkRes2.add('VERSION'); not needed for now
+ LinkRes2.add(' {');
+ if not texportlibunix(exportlib).exportedsymnames.empty then
+ begin
+ LinkRes2.add(' global:');
+ repeat
+ LinkRes2.add(' '+texportlibunix(exportlib).exportedsymnames.getfirst+';');
+ until texportlibunix(exportlib).exportedsymnames.empty;
+ end;
+ LinkRes2.add(' local:');
+ LinkRes2.add(' *;');
+ LinkRes2.add(' };');
+ LinkRes2.writetodisk;
+ LinkRes2.Free;
+ end;
+
+
+ { add objectfiles, start with prt0 always }
+ { solaris port contains _start inside the system unit, it
+ needs only one entry because it is linked always against libc
+ if prtobj<>'' then
+ LinkRes.AddFileName(FindObjectFile(prtobj,'',false));
+ }
+ { try to add crti and crtbegin if linking to C }
+ if linklibc then { Needed in solaris? }
+ begin
+{ if librarysearchpath.FindFile('crtbegin.o',s) then
+ LinkRes.AddFileName(s);}
+ if librarysearchpath.FindFile('crti.o',false,s) then
+ LinkRes.AddFileName(s);
+ end;
+ { main objectfiles }
+ while not ObjectFiles.Empty do
+ begin
+ s:=ObjectFiles.GetFirst;
+ if s<>'' then
+ LinkRes.AddFileName(maybequoted(s));
+ end;
+
+ { Write staticlibraries }
+ if not StaticLibFiles.Empty then
+ begin
+ linkres.add('-(');
+ While not StaticLibFiles.Empty do
+ begin
+ S:=StaticLibFiles.GetFirst;
+ LinkRes.AddFileName(maybequoted(s))
+ end;
+ linkres.add('-)');
+ end;
+
+ { Write sharedlibraries like -l<lib>, also add the needed dynamic linker
+ here to be sure that it gets linked this is needed for glibc2 systems (PFV) }
+ if not SharedLibFiles.Empty then
+ begin
+ While not SharedLibFiles.Empty do
+ begin
+ S:=SharedLibFiles.GetFirst;
+ if s<>'c' then
+ begin
+ i:=Pos(target_info.sharedlibext,S);
+ if i>0 then
+ Delete(S,i,255);
+ LinkRes.Add('-l'+s);
+ end
+ else
+ begin
+ linklibc:=true;
+ linkdynamic:=false; { libc will include the ld-solaris (war ld-linux) for us }
+ end;
+ end;
+ { be sure that libc is the last lib }
+ if linklibc then
+ LinkRes.Add('-lc');
+ { when we have -static for the linker the we also need libgcc }
+ if (cs_link_staticflag in current_settings.globalswitches) then begin
+ LinkRes.Add('-lgcc');
+ end;
+ if linkdynamic and (Info.DynamicLinker<>'') then { gld has a default, DynamicLinker is not set in solaris }
+ LinkRes.AddFileName(Info.DynamicLinker);
+ end;
+ { objects which must be at the end }
+ if linklibc then {needed in solaris ? }
+ begin
+ if {librarysearchpath.FindFile('crtend.o',s1) or}
+ librarysearchpath.FindFile('crtn.o',false,s2) then
+ begin
+{ LinkRes.AddFileName(s1);}
+ LinkRes.AddFileName(s2);
+ end;
+ end;
+{ Write and Close response }
+ //linkres.writetodisk;
+ //LinkRes.Free;
+
+ end;
+ WriteResponseFile:=True;
+end;
+
+
+function TLinkersolaris.MakeExecutable:boolean;
+var
+ binstr,
+ s, linkstr,
+ cmdstr : TCmdStr;
+ success : boolean;
+ DynLinkStr : string[60];
+ StaticStr,
+ StripStr : string[40];
+begin
+ if not(cs_link_nolink in current_settings.globalswitches) then
+ Message1(exec_i_linking,current_module.exefilename^);
+
+{ Create some replacements }
+ StaticStr:='';
+ StripStr:='';
+ DynLinkStr:='';
+ if (cs_link_staticflag in current_settings.globalswitches) then
+ StaticStr:='-Bstatic';
+ if (cs_link_strip in current_settings.globalswitches) then
+ StripStr:='-s';
+ If (cs_profile in current_settings.moduleswitches) or
+ ((Info.DynamicLinker<>'') and (not SharedLibFiles.Empty)) then
+ DynLinkStr:='-dynamic-linker='+Info.DynamicLinker;
+ if rlinkpath<>'' then
+ if use_gnu_ld then
+ DynLinkStr:=DynLinkStr+' --rpath-link '+rlinkpath
+ else
+ DynLinkStr:=DynLinkStr+' -R '+rlinkpath;
+
+ { solaris sets DynamicLinker, but gld will (hopefully) defaults to -Bdynamic and add the default-linker }
+{ Write used files and libraries }
+ WriteResponseFile(false);
+
+{ Call linker }
+ if use_gnu_ld then
+ SplitBinCmd(Info.ExeCmd[1],binstr,cmdstr)
+ else
+ SplitBinCmd(Info.ExeCmd[2],binstr,cmdstr);
+ Replace(cmdstr,'$EXE',maybequoted(current_module.exefilename^));
+ Replace(cmdstr,'$OPT',Info.ExtraOptions);
+ if use_gnu_ld then
+ Replace(cmdstr,'$RES',maybequoted(outputexedir+Info.ResName))
+ else
+ begin
+ linkstr:='';
+ while not linkres.data.Empty do
+ begin
+ s:=linkres.data.GetFirst;
+ if s<>'' then
+ linkstr:=linkstr+' '+s;
+ end;
+ linkres.free;
+ Replace(cmdstr,'$RESDATA',linkstr);
+ end;
+ Replace(cmdstr,'$STATIC',StaticStr);
+ Replace(cmdstr,'$STRIP',StripStr);
+ Replace(cmdstr,'$DYNLINK',DynLinkStr);
+ if BinStr[1]<>'/' then
+ success:=DoExec(FindUtil(utilsprefix+BinStr),CmdStr,true,false)
+ else { Using utilsprefix has no sense on /usr/bin/ld }
+ success:=DoExec(BinStr,Trim(CmdStr),true,false);
+
+{ Remove ReponseFile }
+{$IFNDEF LinkTest}
+ if (success) and use_gnu_ld and
+ not(cs_link_nolink in current_settings.globalswitches) then
+ DeleteFile(outputexedir+Info.ResName);
+{$ENDIF}
+ MakeExecutable:=success; { otherwise a recursive call to link method }
+end;
+
+
+Function TLinkersolaris.MakeSharedLibrary:boolean;
+var
+ InitFiniStr : string;
+ binstr,
+ s, linkstr,
+ cmdstr : TCmdStr;
+ success : boolean;
+begin
+ MakeSharedLibrary:=false;
+ if not(cs_link_nolink in current_settings.globalswitches) then
+ Message1(exec_i_linking,current_module.sharedlibfilename^);
+
+{ Write used files and libraries }
+ WriteResponseFile(true);
+
+{ Create some replacements }
+{ initname and fininame may contain $, which can be wrongly interpreted
+ in a link script, thus we surround them with single quotes
+ in cs_link_nolink is in globalswitches }
+ if use_gnu_ld then
+ begin
+ InitFiniStr:='-init ';
+ if cs_link_nolink in current_settings.globalswitches then
+ InitFiniStr:=InitFiniStr+''''+exportlib.initname+''''
+ else
+ InitFiniStr:=InitFiniStr+exportlib.initname;
+ if (exportlib.fininame<>'') then
+ begin
+ if cs_link_nolink in current_settings.globalswitches then
+ InitFiniStr:=InitFiniStr+' -fini '''+exportlib.initname+''''
+ else
+ InitFiniStr:=InitFiniStr+' -fini '+exportlib.fininame;
+ end;
+ end
+ else
+ begin
+ InitFiniStr:='-z initarray=';
+ if cs_link_nolink in current_settings.globalswitches then
+ InitFiniStr:=InitFiniStr+''''+exportlib.initname+''''
+ else
+ InitFiniStr:=InitFiniStr+exportlib.initname;
+ if (exportlib.fininame<>'') then
+ begin
+ if cs_link_nolink in current_settings.globalswitches then
+ InitFiniStr:=InitFiniStr+' -z finiarray='''+exportlib.initname+''''
+ else
+ InitFiniStr:=InitFiniStr+' -z finiarray='+exportlib.fininame;
+ end;
+ end;
+
+{ Call linker }
+ if use_gnu_ld then
+ SplitBinCmd(Info.DllCmd[1],binstr,cmdstr)
+ else
+ SplitBinCmd(Info.DllCmd[3],binstr,cmdstr);
+ Replace(cmdstr,'$EXE',maybequoted(current_module.sharedlibfilename^));
+ Replace(cmdstr,'$OPT',Info.ExtraOptions);
+ Replace(cmdstr,'$INITFINI',InitFiniStr);
+ if use_gnu_ld then
+ Replace(cmdstr,'$RES',maybequoted(outputexedir+Info.ResName))
+ else
+ begin
+ Replace(cmdstr,'$VERSIONFILE',maybequoted(outputexedir+Info.ResName));
+ linkstr:='';
+ while not linkres.data.Empty do
+ begin
+ s:=linkres.data.GetFirst;
+ if s<>'' then
+ linkstr:=linkstr+' '+s;
+ end;
+ linkres.free;
+ Replace(cmdstr,'$RESDATA',linkstr);
+ end;
+ if BinStr[1]<>'/' then
+ success:=DoExec(FindUtil(utilsprefix+BinStr),CmdStr,true,false)
+ else { Using utilsprefix has no sense on /usr/bin/ld }
+ success:=DoExec(BinStr,Trim(CmdStr),true,false);
+
+
+{ Strip the library ? }
+ if success and (cs_link_strip in current_settings.globalswitches) then
+ begin
+ SplitBinCmd(Info.DllCmd[2],binstr,cmdstr);
+ Replace(cmdstr,'$EXE',maybequoted(current_module.sharedlibfilename^));
+ success:=DoExec(utilsprefix+FindUtil(binstr),cmdstr,true,false);
+ end;
+
+{ Remove ReponseFile }
+{$IFNDEF LinkTest}
+ if (success) and not(cs_link_nolink in current_settings.globalswitches) then
+ DeleteFile(outputexedir+Info.ResName);
+{$ENDIF}
+ MakeSharedLibrary:=success; { otherwise a recursive call to link method }
+end;
+
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+initialization
+{$ifdef i386}
+ RegisterExternalLinker(system_i386_solaris_info,TLinkersolaris);
+ RegisterImport(system_i386_solaris,TImportLibsolaris);
+ RegisterExport(system_i386_solaris,TExportLibsolaris);
+ RegisterTarget(system_i386_solaris_info);
+{$endif i386}
+
+{$ifdef x86_64}
+ RegisterExternalLinker(system_x86_64_solaris_info,TLinkersolaris);
+ RegisterImport(system_x86_64_solaris,TImportLibsolaris);
+ RegisterExport(system_x86_64_solaris,TExportLibsolaris);
+ RegisterTarget(system_x86_64_solaris_info);
+{$endif x86_64}
+
+{$ifdef sparc}
+ RegisterExternalLinker(system_sparc_solaris_info,TLinkersolaris);
+ RegisterImport(system_sparc_solaris,TImportLibsolaris);
+ RegisterExport(system_sparc_solaris,TExportLibsolaris);
+ RegisterTarget(system_sparc_solaris_info);
+{$endif sparc}
+
+ RegisterRes(res_elf_info,TWinLikeResourceFile);
+end.
diff --git a/closures/compiler/systems/t_symbian.pas b/closures/compiler/systems/t_symbian.pas
new file mode 100644
index 0000000000..a11ba00eda
--- /dev/null
+++ b/closures/compiler/systems/t_symbian.pas
@@ -0,0 +1,199 @@
+{
+ This file is part of the Free Pascal run time library.
+ Copyright (c) 2007 by contributors of the Free Pascal Compiler
+
+ This unit implements support import,export,link routines
+ for the Symbian OS target
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ ****************************************************************************
+}
+unit t_symbian;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cutils,cclasses,
+ aasmbase,aasmtai,aasmdata,aasmcpu,fmodule,globtype,globals,systems,verbose,
+ symconst,symdef,symsym,
+ script,gendef,
+ cpubase,
+ import,export,link,cgobj, i_symbian;
+
+ type
+ TInternalLinkerSymbian = class(TInternalLinker)
+ constructor create; override;
+ procedure DefaultLinkScript; override;
+ procedure InitSysInitUnitName; override;
+ end;
+
+implementation
+
+ uses
+ SysUtils,
+ cfileutl,
+ cpuinfo,cgutils,dbgbase,
+ owar,ogbase,ogcoff, t_win;
+
+{****************************************************************************
+ TInternalLinkerSymbian
+****************************************************************************}
+
+ constructor TInternalLinkerSymbian.Create;
+ begin
+ inherited Create;
+ CExeoutput:=TPECoffexeoutput;
+ CObjInput:=TPECoffObjInput;
+ end;
+
+
+ procedure TInternalLinkerSymbian.DefaultLinkScript;
+ var
+ s,s2,
+ ibase : TCmdStr;
+ begin
+ with LinkScript do
+ begin
+ while not ObjectFiles.Empty do
+ begin
+ s:=ObjectFiles.GetFirst;
+ if s<>'' then
+ Concat('READOBJECT '+MaybeQuoted(s));
+ end;
+ while not StaticLibFiles.Empty do
+ begin
+ s:=StaticLibFiles.GetFirst;
+ if s<>'' then
+ Concat('READSTATICLIBRARY '+MaybeQuoted(s));
+ end;
+ While not SharedLibFiles.Empty do
+ begin
+ S:=SharedLibFiles.GetFirst;
+ if FindLibraryFile(s,target_info.staticClibprefix,target_info.staticClibext,s2) then
+ Concat('READSTATICLIBRARY '+MaybeQuoted(s2))
+ else
+ Comment(V_Error,'Import library not found for '+S);
+ end;
+ if IsSharedLibrary then
+ begin
+ Concat('ISSHAREDLIBRARY');
+ Concat('ENTRYNAME _E32DLL');
+ end
+ else
+ begin
+ Concat('ENTRYNAME _E32Startup')
+ end;
+ if IsSharedLibrary then
+ ibase:='10000000'
+ else
+ ibase:='400000';
+ Concat('IMAGEBASE $' + ibase);
+ Concat('HEADER');
+ Concat('EXESECTION .text');
+ Concat(' OBJSECTION .text*');
+ Concat(' SYMBOL ___CTOR_LIST__');
+ Concat(' SYMBOL __CTOR_LIST__');
+ Concat(' LONG -1');
+ Concat(' OBJSECTION .ctor*');
+ Concat(' LONG 0');
+ Concat(' SYMBOL ___DTOR_LIST__');
+ Concat(' SYMBOL __DTOR_LIST__');
+ Concat(' LONG -1');
+ Concat(' OBJSECTION .dtor*');
+ Concat(' LONG 0');
+ Concat(' SYMBOL etext');
+ Concat('ENDEXESECTION');
+ Concat('EXESECTION .data');
+ Concat(' SYMBOL __data_start__');
+ Concat(' OBJSECTION .data*');
+ Concat(' OBJSECTION .fpc*');
+ Concat(' SYMBOL edata');
+ Concat(' SYMBOL __data_end__');
+ Concat('ENDEXESECTION');
+ Concat('EXESECTION .rdata');
+ Concat(' SYMBOL ___RUNTIME_PSEUDO_RELOC_LIST__');
+ Concat(' SYMBOL __RUNTIME_PSEUDO_RELOC_LIST__');
+ Concat(' OBJSECTION .rdata_runtime_pseudo_reloc');
+ Concat(' SYMBOL ___RUNTIME_PSEUDO_RELOC_LIST_END__');
+ Concat(' SYMBOL __RUNTIME_PSEUDO_RELOC_LIST_END__');
+ Concat(' OBJSECTION .rdata*');
+ Concat(' OBJSECTION .rodata*');
+ Concat('ENDEXESECTION');
+ Concat('EXESECTION .pdata');
+ Concat(' OBJSECTION .pdata');
+ Concat('ENDEXESECTION');
+ Concat('EXESECTION .bss');
+ Concat(' SYMBOL __bss_start__');
+ Concat(' OBJSECTION .bss*');
+ Concat(' SYMBOL __bss_end__');
+ Concat('ENDEXESECTION');
+ Concat('EXESECTION .idata');
+ Concat(' OBJSECTION .idata$2*');
+ Concat(' OBJSECTION .idata$3*');
+ Concat(' ZEROS 20');
+ Concat(' OBJSECTION .idata$4*');
+ Concat(' OBJSECTION .idata$5*');
+ Concat(' OBJSECTION .idata$6*');
+ Concat(' OBJSECTION .idata$7*');
+ Concat('ENDEXESECTION');
+ Concat('EXESECTION .edata');
+ Concat(' OBJSECTION .edata*');
+ Concat('ENDEXESECTION');
+ Concat('EXESECTION .rsrc');
+ Concat(' OBJSECTION .rsrc*');
+ Concat('ENDEXESECTION');
+ Concat('EXESECTION .reloc');
+ Concat(' OBJSECTION .reloc');
+ Concat('ENDEXESECTION');
+ Concat('EXESECTION .stab');
+ Concat(' OBJSECTION .stab');
+ Concat('ENDEXESECTION');
+ Concat('EXESECTION .stabstr');
+ Concat(' OBJSECTION .stabstr');
+ Concat('ENDEXESECTION');
+ Concat('STABS');
+ Concat('SYMBOLS');
+ end;
+ end;
+
+
+ procedure TInternalLinkerSymbian.InitSysInitUnitName;
+ begin
+ sysinitunit := 'sysinitpas';
+ end;
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+initialization
+{$ifdef i386}
+ RegisterInternalLinker(system_i386_symbian_info,TExternalLinkerWin);
+ RegisterImport(system_i386_symbian,TImportLibWin);
+ RegisterExport(system_i386_symbian,TExportLibWin);
+ RegisterDLLScanner(system_i386_symbian,TDLLScannerWin);
+// RegisterRes(res_gnu_windres_info);
+ RegisterTarget(system_i386_symbian_info);
+{$endif i386}
+{$ifdef arm}
+// RegisterExternalLinker(system_arm_symbian_info,TExternalLinkerWin);
+ RegisterInternalLinker(system_arm_symbian_info,TInternalLinkerWin);
+ RegisterImport(system_arm_symbian,TImportLibWin);
+ RegisterExport(system_arm_symbian,TExportLibWin);
+ RegisterTarget(system_arm_symbian_info);
+{$endif arm}
+end.
diff --git a/closures/compiler/systems/t_watcom.pas b/closures/compiler/systems/t_watcom.pas
new file mode 100644
index 0000000000..bcf92d24fc
--- /dev/null
+++ b/closures/compiler/systems/t_watcom.pas
@@ -0,0 +1,179 @@
+{
+ Copyright (c) 2003 by Wiktor Sywula
+
+ This unit implements support import, export, link routines
+ for the (i386) Watcom target
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit t_watcom;
+
+{$i fpcdefs.inc}
+
+interface
+
+
+implementation
+
+ uses
+ link,
+ SysUtils,
+ cclasses,cutils,cfileutl,globtype,globals,
+ systems,verbose,script,fmodule,i_watcom;
+
+
+ type
+ tlinkerwatcom=class(texternallinker)
+ private
+ Function WriteResponseFile(isdll:boolean) : Boolean;
+ public
+ constructor Create;override;
+ procedure SetDefaultInfo;override;
+ function MakeExecutable:boolean;override;
+{ function MakeSharedLibrary:boolean;override;}
+ end;
+
+
+{****************************************************************************
+ TLinkerWatcom
+****************************************************************************}
+
+Constructor TLinkerWatcom.Create;
+begin
+ Inherited Create;
+ SharedLibFiles.doubles:=true;
+ StaticLibFiles.doubles:=true;
+end;
+
+
+procedure TLinkerWatcom.SetDefaultInfo;
+begin
+ with Info do
+ ExeCmd[1]:='wlink system causeway option quiet option nocaseexact $OPT $STRIP name $EXE @$RES';
+end;
+
+Function TLinkerWatcom.WriteResponseFile(isdll:boolean) : Boolean;
+Var
+ linkres : TLinkRes;
+ {i : longint;}
+ s : string;
+ {linklibc : boolean;}
+begin
+ WriteResponseFile:=False;
+
+ { Open link.res file }
+ LinkRes:=TLinkRes.Create(outputexedir+Info.ResName);
+
+ { Write object files, start with prt0 }
+ LinkRes.Add('file '+GetShortName(FindObjectFile('prt0','',false)));
+ if not ObjectFiles.Empty then
+ While not ObjectFiles.Empty do
+ begin
+ S:=ObjectFiles.GetFirst;
+ LinkRes.AddFileName('file '+GetShortName(s));
+ end;
+
+ { Write staticlibraries }
+ if not StaticLibFiles.Empty then
+ While not StaticLibFiles.Empty do
+ begin
+ S:=StaticLibFiles.GetFirst;
+ LinkRes.AddFileName('file '+GetShortName(s));
+ end;
+
+(*
+
+ { Write sharedlibraries like -l<lib>, also add the needed dynamic linker
+ here to be sure that it gets linked this is needed for glibc2 systems (PFV) }
+ linklibc:=false;
+ While not SharedLibFiles.Empty do
+ begin
+ S:=SharedLibFiles.Get;
+ if s<>'c' then
+ begin
+ i:=Pos(target_os.sharedlibext,S);
+ if i>0 then
+ Delete(S,i,255);
+ LinkRes.Add('-l'+s);
+ end
+ else
+ begin
+ LinkRes.Add('-l'+s);
+ linklibc:=true;
+ end;
+ end;
+ { be sure that libc&libgcc is the last lib }
+ if linklibc then
+ begin
+ LinkRes.Add('-lc');
+ LinkRes.Add('-lgcc');
+ end;
+*)
+{ Write and Close response }
+ linkres.writetodisk;
+ linkres.free;
+
+ WriteResponseFile:=True;
+end;
+
+
+function TLinkerWatcom.MakeExecutable:boolean;
+var
+ binstr,
+ cmdstr : TCmdStr;
+ success : boolean;
+ StripStr : string[40];
+begin
+ if not(cs_link_nolink in current_settings.globalswitches) then
+ Message1(exec_i_linking,current_module.exefilename^);
+
+{ Create some replacements }
+ StripStr:='debug dwarf all';
+ if (cs_link_strip in current_settings.globalswitches) then
+ StripStr:='';
+
+{ Write used files and libraries }
+ WriteResponseFile(false);
+
+{ Call linker }
+ SplitBinCmd(Info.ExeCmd[1],binstr,cmdstr);
+ Replace(cmdstr,'$EXE',maybequoted(current_module.exefilename^));
+ Replace(cmdstr,'$OPT',Info.ExtraOptions);
+ Replace(cmdstr,'$RES',maybequoted(outputexedir+Info.ResName));
+ Replace(cmdstr,'$STRIP',StripStr);
+ success:=DoExec(FindUtil(utilsprefix+BinStr),cmdstr,true,false);
+
+{ Remove ReponseFile }
+ if (success) and not(cs_link_nolink in current_settings.globalswitches) then
+ DeleteFile(outputexedir+Info.ResName);
+
+ MakeExecutable:=success; { otherwise a recursive call to link method }
+end;
+
+{function TLinkerWatcom.MakeSharedLibrary:boolean;
+begin
+ MakeSharedLibrary:=false;
+end;}
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+initialization
+ RegisterExternalLinker(system_i386_watcom_info,TLinkerWatcom);
+ RegisterTarget(system_i386_watcom_info);
+end.
diff --git a/closures/compiler/systems/t_wdosx.pas b/closures/compiler/systems/t_wdosx.pas
new file mode 100644
index 0000000000..f350e10b36
--- /dev/null
+++ b/closures/compiler/systems/t_wdosx.pas
@@ -0,0 +1,84 @@
+{
+ Copyright (c) 2001-2002 Pavel ??????
+
+ This unit implements support import,export,link routines
+ for the (i386) WDOSX target
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ ****************************************************************************
+}
+unit t_wdosx;
+
+{$i fpcdefs.inc}
+
+interface
+
+
+implementation
+
+ uses
+ cutils,
+ fmodule,globals,systems,
+ import,export,link,t_win,i_wdosx;
+
+ type
+ timportlibwdosx=class(TImportLibWin)
+ end;
+
+ texportlibwdosx=TExportLibWin;
+
+ TExternalLinkerwdosx=class(TExternalLinkerWin)
+ public
+ function MakeExecutable:boolean;override;
+ end;
+
+ tDLLScannerWdosx=class(TDLLScannerWin)
+ end;
+
+
+{*****************************************************************************
+ TIMPORTLIBWDOSX
+*****************************************************************************}
+
+{*****************************************************************************
+ TExternalLinkerWDOSX
+*****************************************************************************}
+function TExternalLinkerWdosx.MakeExecutable:boolean;
+var
+ b: boolean;
+begin
+ b := Inherited MakeExecutable;
+ if b then
+ DoExec(FindUtil('stubit'),current_module.exefilename^,false,false);
+ Result := b;
+end;
+
+{****************************************************************************
+ TDLLScannerWdosx
+****************************************************************************}
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+initialization
+ RegisterExternalLinker(system_i386_wdosx_info,TExternalLinkerWdosx);
+ RegisterImport(system_i386_wdosx,TImportLibWdosx);
+ RegisterExport(system_i386_wdosx,TExportLibWdosx);
+ RegisterDLLScanner(system_i386_wdosx,TDLLScannerWdosx);
+ {RegisterAr(ar_gnu_arw_info);}
+ {RegisterRes(res_gnu_windres_info);}
+ RegisterTarget(system_i386_wdosx_info);
+end.
diff --git a/closures/compiler/systems/t_wii.pas b/closures/compiler/systems/t_wii.pas
new file mode 100644
index 0000000000..485eb5bc89
--- /dev/null
+++ b/closures/compiler/systems/t_wii.pas
@@ -0,0 +1,597 @@
+{
+ Copyright (c) 2011 by Francesco Lombardi
+
+ This unit implements support import, export, link routines
+ for the Wii (PowerPC) target
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit t_wii;
+
+{$i fpcdefs.inc}
+
+interface
+
+
+implementation
+
+ uses
+ aasmbase,
+ SysUtils,
+ cutils,cfileutl,cclasses,
+ globtype,globals,systems,verbose,script,fmodule,i_wii,link;
+
+ type
+ TlinkerWii=class(texternallinker)
+ private
+ Function WriteResponseFile: Boolean;
+ public
+ constructor Create; override;
+ procedure SetDefaultInfo; override;
+ function MakeExecutable:boolean; override;
+ end;
+
+
+
+{****************************************************************************
+ TLinkerWii
+****************************************************************************}
+
+Constructor TLinkerWii.Create;
+begin
+ Inherited Create;
+ SharedLibFiles.doubles:=true;
+ StaticLibFiles.doubles:=true;
+end;
+
+
+procedure TLinkerWii.SetDefaultInfo;
+begin
+ with Info do
+ begin
+ ExeCmd[1]:='ld -g $OPT $DYNLINK $STATIC $GCSECTIONS $STRIP -L. -o $EXE -T $RES';
+ end;
+end;
+
+
+Function TLinkerWii.WriteResponseFile : Boolean;
+Var
+ linkres : TLinkRes;
+ i : longint;
+ HPath : TCmdStrListItem;
+ s,s1,s2 : TCmdStr;
+ linklibc,
+ linklibgcc : boolean;
+ found1,
+ found2 : boolean;
+begin
+ WriteResponseFile:=False;
+ linklibc:=(SharedLibFiles.Find('c')<>nil);
+ linklibgcc:=(SharedLibFiles.Find('gcc')<>nil);
+ LinkRes:=TLinkRes.Create(outputexedir+Info.ResName);
+
+ { Write path to search libraries }
+ HPath:=TCmdStrListItem(current_module.locallibrarysearchpath.First);
+ while assigned(HPath) do
+ begin
+ s:=HPath.Str;
+ if (cs_link_on_target in current_settings.globalswitches) then
+ s:=ScriptFixFileName(s);
+ LinkRes.Add('-L'+s);
+ HPath:=TCmdStrListItem(HPath.Next);
+ end;
+ HPath:=TCmdStrListItem(LibrarySearchPath.First);
+ while assigned(HPath) do
+ begin
+ s:=HPath.Str;
+ if s<>'' then
+ LinkRes.Add('SEARCH_DIR('+(maybequoted(s))+')');
+ HPath:=TCmdStrListItem(HPath.Next);
+ end;
+
+ LinkRes.Add('INPUT (');
+ { add objectfiles, start with prt0 always }
+// s:=FindObjectFile('prt0','',false);
+// LinkRes.AddFileName(s);
+ { try to add crti and crtbegin if linking to C }
+ if linklibc then
+ begin
+ if librarysearchpath.FindFile('ecrti.o',false,s) then
+ LinkRes.AddFileName(s);
+ end;
+ if linklibgcc then
+ begin
+ if librarysearchpath.FindFile('crtbegin.o',false,s) then
+ LinkRes.AddFileName(s);
+ end;
+ if linklibc or linklibgcc then
+ begin
+ if librarysearchpath.FindFile('crtmain.o',false,s) then
+ LinkRes.AddFileName(s);
+ end;
+
+
+ while not ObjectFiles.Empty do
+ begin
+ s:=ObjectFiles.GetFirst;
+ if s<>'' then
+ begin
+ { vlink doesn't use SEARCH_DIR for object files }
+ if not(cs_link_on_target in current_settings.globalswitches) then
+ s:=FindObjectFile(s,'',false);
+ LinkRes.AddFileName((maybequoted(s)));
+ end;
+ end;
+
+ { Write staticlibraries }
+ if not StaticLibFiles.Empty then
+ begin
+ { vlink doesn't need, and doesn't support GROUP }
+ if (cs_link_on_target in current_settings.globalswitches) then
+ begin
+ LinkRes.Add(')');
+ LinkRes.Add('GROUP(');
+ end;
+ while not StaticLibFiles.Empty do
+ begin
+ S:=StaticLibFiles.GetFirst;
+ LinkRes.AddFileName((maybequoted(s)));
+ end;
+ end;
+
+ if (cs_link_on_target in current_settings.globalswitches) then
+ begin
+ LinkRes.Add(')');
+
+ { Write sharedlibraries like -l<lib>, also add the needed dynamic linker
+ here to be sure that it gets linked this is needed for glibc2 systems (PFV) }
+ linklibc:=false;
+ linklibgcc:=false;
+ while not SharedLibFiles.Empty do
+ begin
+ S:=SharedLibFiles.GetFirst;
+ if s<>'c' then
+ begin
+ i:=Pos(target_info.sharedlibext,S);
+ if i>0 then
+ Delete(S,i,255);
+ LinkRes.Add('-l'+s);
+ end
+ else
+ begin
+ LinkRes.Add('-l'+s);
+ linklibc:=true;
+ linklibgcc:=true;
+ end;
+ end;
+ { be sure that libc&libgcc is the last lib }
+ if linklibgcc then
+ begin
+ LinkRes.Add('-lgcc');
+ end;
+ if linklibc then
+ begin
+ LinkRes.Add('-lc');
+ end;
+
+ end
+ else
+ begin
+ while not SharedLibFiles.Empty do
+ begin
+ S:=SharedLibFiles.GetFirst;
+ LinkRes.Add('lib'+s+target_info.staticlibext);
+ end;
+ LinkRes.Add(')');
+ end;
+
+ { objects which must be at the end }
+ if linklibgcc then
+ begin
+ found1:=librarysearchpath.FindFile('crtend.o',false,s1);
+ if found1 then
+ begin
+ LinkRes.Add('INPUT(');
+ if found1 then
+ LinkRes.AddFileName(s1);
+ LinkRes.Add(')');
+ end;
+ end;
+ if linklibc then
+ begin
+ found2:=librarysearchpath.FindFile('ecrtn.o',false,s2);
+ if found2 then
+ begin
+ LinkRes.Add('INPUT(');
+ if found2 then
+ LinkRes.AddFileName(s2);
+ LinkRes.Add(')');
+ end;
+ end;
+ with linkres do
+ begin
+ Add('/*');
+ Add(' * Linkscript for Wii');
+ Add(' */');
+ Add('');
+ Add('OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", "elf32-powerpc");');
+ Add('OUTPUT_ARCH(powerpc:common);');
+ Add('EXTERN(_start);');
+ Add('ENTRY(_start);');
+ Add('');
+ Add('PHDRS');
+ Add('{');
+ Add(' stub PT_LOAD FLAGS(5);');
+ Add(' text PT_LOAD FLAGS(5);');
+ Add(' data PT_LOAD FLAGS(6);');
+ Add('}');
+ Add('');
+ Add('SECTIONS');
+ Add('{');
+ Add(' /* stub is loaded at physical address 0x00003400 (though both 0x80003400 and 0x00003400 are equivalent for IOS) */');
+ Add(' /* This can also be used to load an arbitrary standalone stub at an arbitrary address in memory, for any purpose */');
+ Add(' /* Use -Wl,--section-start,.stub=0xADDRESS to change */');
+ Add(' . = 0x00003400;');
+ Add('');
+ Add(' .stub :');
+ Add(' {');
+ Add(' KEEP(*(.stub))');
+ Add(' } :stub = 0');
+ Add('');
+ Add(' /* default base address */');
+ Add(' /* use -Wl,--section-start,.init=0xADDRESS to change */');
+ Add(' . = 0x80004000;');
+ Add('');
+ Add(' /* Program */');
+ Add(' .init :');
+ Add(' {');
+ Add(' KEEP (*crt0.o(*.init))');
+ Add(' KEEP (*(.init))');
+ Add(' } :text = 0');
+ Add(' .plt : { *(.plt) }');
+ Add(' .interp : { *(.interp) }');
+ Add(' .hash : { *(.hash) }');
+ Add(' .dynsym : { *(.dynsym) }');
+ Add(' .dynstr : { *(.dynstr) }');
+ Add(' .gnu.version : { *(.gnu.version) }');
+ Add(' .gnu.version_d : { *(.gnu.version_d) }');
+ Add(' .gnu.version_r : { *(.gnu.version_r) }');
+ Add(' .rel.init : { *(.rel.init) }');
+ Add(' .rela.init : { *(.rela.init) }');
+ Add(' .rel.text : { *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) }');
+ Add(' .rela.text : { *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) }');
+ Add(' .rel.fini : { *(.rel.fini) }');
+ Add(' .rela.fini : { *(.rela.fini) }');
+ Add(' .rel.rodata : { *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) }');
+ Add(' .rela.rodata : { *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) }');
+ Add(' .rel.data : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) }');
+ Add(' .rela.data : { *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) }');
+ Add(' .rel.tdata : { *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) }');
+ Add(' .rela.tdata : { *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) }');
+ Add(' .rel.tbss : { *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) }');
+ Add(' .rela.tbss : { *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) }');
+ Add(' .rel.ctors : { *(.rel.ctors) }');
+ Add(' .rela.ctors : { *(.rela.ctors) }');
+ Add(' .rel.dtors : { *(.rel.dtors) }');
+ Add(' .rela.dtors : { *(.rela.dtors) }');
+ Add(' .rel.got : { *(.rel.got) }');
+ Add(' .rela.got : { *(.rela.got) }');
+ Add(' .rela.got1 : { *(.rela.got1) }');
+ Add(' .rela.got2 : { *(.rela.got2) }');
+ Add(' .rel.sdata : { *(.rel.sdata .rel.sdata.* .rel.gnu.linkonce.s.*) }');
+ Add(' .rela.sdata : { *(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.*) }');
+ Add(' .rel.sbss : { *(.rel.sbss .rel.sbss.* .rel.gnu.linkonce.sb.*) }');
+ Add(' .rela.sbss : { *(.rela.sbss .rela.sbss.* .rel.gnu.linkonce.sb.*) }');
+ Add(' .rel.sdata2 : { *(.rel.sdata2 .rel.sdata2.* .rel.gnu.linkonce.s2.*) }');
+ Add(' .rela.sdata2 : { *(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*) }');
+ Add(' .rel.sbss2 : { *(.rel.sbss2 .rel.sbss2.* .rel.gnu.linkonce.sb2.*) }');
+ Add(' .rela.sbss2 : { *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*) }');
+ Add(' .rel.bss : { *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) }');
+ Add(' .rela.bss : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) }');
+ Add(' .rel.plt : { *(.rel.plt) }');
+ Add(' .rela.plt : { *(.rela.plt) }');
+ Add('');
+ Add(' .text :');
+ Add(' {');
+ Add(' *(.text)');
+ Add(' *(.text.*)');
+ Add(' /* .gnu.warning sections are handled specially by elf32.em. */');
+ Add(' *(.gnu.warning)');
+ Add(' *(.gnu.linkonce.t.*)');
+ Add(' . = ALIGN(32); /* REQUIRED. LD is flaky without it. */');
+ Add(' } = 0');
+ Add('');
+ Add(' .fini :');
+ Add(' {');
+ Add(' KEEP (*(.fini))');
+ Add(' . = ALIGN(32); /* REQUIRED. LD is flaky without it. */');
+ Add(' } = 0');
+ Add(' ');
+ Add(' PROVIDE (__etext = .);');
+ Add(' PROVIDE (_etext = .);');
+ Add(' PROVIDE (etext = .);');
+ Add('');
+ Add(' .rodata : { *(.rodata) *(.rodata.*) *(.gnu.linkonce.r.*) } :data');
+ Add(' .rodata1 : { *(.rodata1) }');
+ Add(' .sdata2 : { *(.sdata2) *(.sdata2.*) *(.gnu.linkonce.s2.*) }');
+ Add(' .sbss2 : { *(.sbss2) *(.sbss2.*) *(.gnu.linkonce.sb2.*) }');
+ Add(' /* Adjust the address for the data segment. We want to adjust up to');
+ Add(' the same address within the page on the next page up. */');
+ Add(' /* Ensure the __preinit_array_start label is properly aligned. We');
+ Add(' could instead move the label definition inside the section, but');
+ Add(' the linker would then create the section even if it turns out to');
+ Add(' be empty, which isn''t pretty. */');
+ Add(' . = ALIGN(32 / 8);');
+ Add(' PROVIDE (__preinit_array_start = .);');
+ Add(' .preinit_array : { *(.preinit_array) }');
+ Add(' PROVIDE (__preinit_array_end = .);');
+ Add(' PROVIDE (__init_array_start = .);');
+ Add(' .init_array : { *(.init_array) }');
+ Add(' PROVIDE (__init_array_end = .);');
+ Add(' PROVIDE (__fini_array_start = .);');
+ Add(' .fini_array : { *(.fini_array) }');
+ Add(' PROVIDE (__fini_array_end = .);');
+ Add(' .data :');
+ Add(' {');
+ Add(' *(.data)');
+ Add(' *(.data.*)');
+ Add(' *(.gnu.linkonce.d.*)');
+ Add(' SORT(CONSTRUCTORS)');
+ Add(' . = ALIGN(32); /* REQUIRED. LD is flaky without it. */');
+ Add(' }');
+ Add('');
+ Add(' .data1 : { *(.data1) }');
+ Add(' .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) }');
+ Add(' .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }');
+ Add(' .eh_frame : { KEEP (*(.eh_frame)) }');
+ Add(' .gcc_except_table : { *(.gcc_except_table) }');
+ Add(' .fixup : { *(.fixup) }');
+ Add(' .got1 : { *(.got1) }');
+ Add(' .got2 : { *(.got2) }');
+ Add(' .dynamic : { *(.dynamic) }');
+ Add('');
+ Add(' .ctors :');
+ Add(' {');
+ Add(' /* gcc uses crtbegin.o to find the start of');
+ Add(' the constructors, so we make sure it is');
+ Add(' first. Because this is a wildcard, it');
+ Add(' doesn''t matter if the user does not');
+ Add(' actually link against crtbegin.o; the');
+ Add(' linker won''t look for a file to match a');
+ Add(' wildcard. The wildcard also means that it');
+ Add(' doesn''t matter which directory crtbegin.o');
+ Add(' is in. */');
+ Add('');
+ Add(' KEEP (*crtbegin.o(.ctors))');
+ Add('');
+ Add(' /* We don''t want to include the .ctor section from');
+ Add(' from the crtend.o file until after the sorted ctors.');
+ Add(' The .ctor section from the crtend file contains the');
+ Add(' end of ctors marker and it must be last */');
+ Add('');
+ Add(' KEEP (*(EXCLUDE_FILE (*crtend.o ) .ctors))');
+ Add(' KEEP (*(SORT(.ctors.*)))');
+ Add(' KEEP (*(.ctors))');
+ Add(' . = ALIGN(32); /* REQUIRED. LD is flaky without it. */');
+ Add(' }');
+ Add('');
+ Add(' .dtors :');
+ Add(' {');
+ Add(' KEEP (*crtbegin.o(.dtors))');
+ Add(' KEEP (*(EXCLUDE_FILE (*crtend.o ) .dtors))');
+ Add(' KEEP (*(SORT(.dtors.*)))');
+ Add(' KEEP (*(.dtors))');
+ Add(' . = ALIGN(32); /* REQUIRED. LD is flaky without it. */');
+ Add(' }');
+ Add('');
+ Add(' .jcr : { KEEP (*(.jcr)) }');
+ Add(' .got : { *(.got.plt) *(.got) }');
+ Add('');
+ Add('');
+ Add(' /* We want the small data sections together, so single-instruction offsets');
+ Add(' can access them all, and initialized data all before uninitialized, so');
+ Add(' we can shorten the on-disk segment size. */');
+ Add('');
+ Add(' .sdata :');
+ Add(' {');
+ Add(' *(.sdata)');
+ Add(' *(.sdata.*)');
+ Add(' *(.gnu.linkonce.s.*)');
+ Add(' . = ALIGN(32); /* REQUIRED. LD is flaky without it. */');
+ Add(' }');
+ Add('');
+ Add(' _edata = .;');
+ Add(' PROVIDE (edata = .);');
+ Add(' ');
+ Add(' .sbss :');
+ Add(' {');
+ Add(' __sbss_start = .;');
+ Add(' PROVIDE (__sbss_start = .);');
+ Add(' PROVIDE (___sbss_start = .);');
+ Add(' *(.dynsbss)');
+ Add(' *(.sbss)');
+ Add(' *(.sbss.*)');
+ Add(' *(.gnu.linkonce.sb.*)');
+ Add(' *(.scommon)');
+ Add(' PROVIDE (__sbss_end = .);');
+ Add(' PROVIDE (___sbss_end = .);');
+ Add(' . = ALIGN(32); /* REQUIRED. LD is flaky without it. */');
+ Add(' __sbss_end = .;');
+ Add(' }');
+ Add('');
+ Add(' .bss :');
+ Add(' {');
+ Add(' __bss_start = .;');
+ Add(' PROVIDE (__bss_start = .);');
+ Add(' *(.dynbss)');
+ Add(' *(.bss)');
+ Add(' *(.bss.*)');
+ Add(' *(.gnu.linkonce.b.*)');
+ Add(' *(COMMON)');
+ Add(' /* Align here to ensure that the .bss section occupies space up to');
+ Add(' _end. Align after .bss to ensure correct alignment even if the');
+ Add(' .bss section disappears because there are no input sections. */');
+ Add('');
+ Add(' . = ALIGN(32);');
+ Add('');
+ Add(' PROVIDE (__bss_end = .);');
+ Add(' __bss_end = .;');
+ Add(' }');
+ Add('');
+ Add(' _end = .;');
+ Add(' PROVIDE(end = .);');
+ Add(' /* Stabs debugging sections. */');
+ Add(' .stab 0 : { *(.stab) }');
+ Add(' .stabstr 0 : { *(.stabstr) }');
+ Add(' .stab.excl 0 : { *(.stab.excl) }');
+ Add(' .stab.exclstr 0 : { *(.stab.exclstr) }');
+ Add(' .stab.index 0 : { *(.stab.index) }');
+ Add(' .stab.indexstr 0 : { *(.stab.indexstr) }');
+ Add(' .comment 0 : { *(.comment) }');
+ Add(' /* DWARF debug sections.');
+ Add(' Symbols in the DWARF debugging sections are relative to the beginning');
+ Add(' of the section so we begin them at 0. */');
+ Add(' /* DWARF 1 */');
+ Add(' .debug 0 : { *(.debug) }');
+ Add(' .line 0 : { *(.line) }');
+ Add(' /* GNU DWARF 1 extensions */');
+ Add(' .debug_srcinfo 0 : { *(.debug_srcinfo) }');
+ Add(' .debug_sfnames 0 : { *(.debug_sfnames) }');
+ Add(' /* DWARF 1.1 and DWARF 2 */');
+ Add(' .debug_aranges 0 : { *(.debug_aranges) }');
+ Add(' .debug_pubnames 0 : { *(.debug_pubnames) }');
+ Add(' /* DWARF 2 */');
+ Add(' .debug_info 0 : { *(.debug_info) }');
+ Add(' .debug_abbrev 0 : { *(.debug_abbrev) }');
+ Add(' .debug_line 0 : { *(.debug_line) }');
+ Add(' .debug_frame 0 : { *(.debug_frame) }');
+ Add(' .debug_str 0 : { *(.debug_str) }');
+ Add(' .debug_loc 0 : { *(.debug_loc) }');
+ Add(' .debug_macinfo 0 : { *(.debug_macinfo) }');
+ Add(' /* SGI/MIPS DWARF 2 extensions */');
+ Add(' .debug_weaknames 0 : { *(.debug_weaknames) }');
+ Add(' .debug_funcnames 0 : { *(.debug_funcnames) }');
+ Add(' .debug_typenames 0 : { *(.debug_typenames) }');
+ Add(' .debug_varnames 0 : { *(.debug_varnames) }');
+ Add(' /* These must appear regardless of . */');
+ Add('}');
+ Add('');
+ Add('__isIPL = 0;');
+ Add('__stack_addr = (__bss_start + SIZEOF(.bss) + 0x20000 + 7) & (-8);');
+ Add('__stack_end = (__bss_start + SIZEOF(.bss));');
+ Add('__intrstack_addr = (__stack_addr + 0x4000);');
+ Add('__intrstack_end = (__stack_addr);');
+ Add('__Arena1Lo = (__intrstack_addr + 31) & (-32);');
+ Add('__Arena1Hi = (0x817FEFF0);');
+ Add('__Arena2Lo = (0x90002000);');
+ Add('__Arena2Hi = (0x933E0000);');
+ Add('');
+ Add('__gxregs = (__Arena1Hi + 31) & (-32);');
+ Add('__ipcbufferLo = (0x933e0000);');
+ Add('__ipcbufferHi = (0x93400000);');
+ Add('');
+ Add('/* for backward compatibility with old crt0 */');
+ Add('PROVIDE (__stack = (0x817FEFF0));');
+ Add('');
+ Add('PROVIDE(__isIPL = __isIPL);');
+ Add('PROVIDE(__stack_addr = __stack_addr);');
+ Add('PROVIDE(__stack_end = __stack_end);');
+ Add('PROVIDE(__intrstack_addr = __intrstack_addr);');
+ Add('PROVIDE(__intrstack_end = __intrstack_end);');
+ Add('PROVIDE(__Arena1Lo = __Arena1Lo);');
+ Add('PROVIDE(__Arena1Hi = __Arena1Hi);');
+ Add('PROVIDE(__Arena2Lo = __Arena2Lo);');
+ Add('PROVIDE(__Arena2Hi = __Arena2Hi);');
+ Add('PROVIDE(__ipcbufferLo = __ipcbufferLo);');
+ Add('PROVIDE(__ipcbufferHi = __ipcbufferHi);');
+ Add('PROVIDE(__gxregs = __gxregs);');
+ end;
+
+
+{ Write and Close response }
+ linkres.writetodisk;
+ linkres.free;
+
+ WriteResponseFile:=True;
+
+end;
+
+
+function TLinkerWii.MakeExecutable:boolean;
+var
+ binstr,
+ cmdstr : TCmdStr;
+ success : boolean;
+ StaticStr,
+ GCSectionsStr,
+ DynLinkStr,
+ StripStr: string;
+begin
+ StaticStr:='';
+ StripStr:='';
+ GCSectionsStr:='';
+ DynLinkStr:='';
+
+ if (cs_link_strip in current_settings.globalswitches) and
+ not(cs_link_separate_dbg_file in current_settings.globalswitches) then
+ StripStr:='-s';
+ if (cs_link_map in current_settings.globalswitches) then
+ StripStr:='-Map '+maybequoted(ChangeFileExt(current_module.exefilename^,'.map'));
+ if create_smartlink_sections then
+ GCSectionsStr:='--gc-sections';
+ if not(cs_link_nolink in current_settings.globalswitches) then
+ Message1(exec_i_linking,current_module.exefilename^);
+
+
+{ Write used files and libraries }
+ WriteResponseFile();
+
+{ Call linker }
+ SplitBinCmd(Info.ExeCmd[1],binstr,cmdstr);
+ Replace(cmdstr,'$EXE',(maybequoted(ScriptFixFileName(ChangeFileExt(current_module.exefilename^,'.elf')))));
+ Replace(cmdstr,'$OPT',Info.ExtraOptions);
+ Replace(cmdstr,'$RES',(maybequoted(ScriptFixFileName(outputexedir+Info.ResName))));
+ Replace(cmdstr,'$STATIC',StaticStr);
+ Replace(cmdstr,'$STRIP',StripStr);
+ Replace(cmdstr,'$GCSECTIONS',GCSectionsStr);
+ Replace(cmdstr,'$DYNLINK',DynLinkStr);
+
+ success:=DoExec(FindUtil(utilsprefix+BinStr),cmdstr,true,false);
+
+{ Remove ReponseFile }
+ if (success) and not(cs_link_nolink in current_settings.globalswitches) then
+ DeleteFile(outputexedir+Info.ResName);
+
+{ Post process }
+
+ if success then
+ begin
+ success:=DoExec(FindUtil('elf2dol'),ChangeFileExt(current_module.exefilename^,'.elf')+' '+
+ current_module.exefilename^,true,false);
+ end;
+ MakeExecutable:=success; { otherwise a recursive call to link method }
+end;
+
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+initialization
+ RegisterExternalLinker(system_powerpc_wii_info,TLinkerWii);
+ RegisterTarget(system_powerpc_wii_info);
+end.
diff --git a/closures/compiler/systems/t_win.pas b/closures/compiler/systems/t_win.pas
new file mode 100644
index 0000000000..f0ed350df2
--- /dev/null
+++ b/closures/compiler/systems/t_win.pas
@@ -0,0 +1,1882 @@
+{
+ Copyright (c) 1998-2008 by Peter Vreman
+
+ This unit implements support import,export,link routines
+ for the (i386) Win32 target
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ ****************************************************************************
+}
+unit t_win;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cutils,cclasses,
+ aasmbase,aasmtai,aasmdata,aasmcpu,fmodule,globtype,globals,systems,verbose,
+ symconst,symdef,symsym,
+ script,gendef,
+ cpubase,
+ import,export,link,comprsrc,cgobj,i_win;
+
+
+ const
+ MAX_DEFAULT_EXTENSIONS = 3;
+
+ type
+ tStr4=array[1..MAX_DEFAULT_EXTENSIONS] of string[4];
+ pStr4=^tStr4;
+
+ TImportLibWin=class(timportlib)
+ private
+ procedure generateimportlib;
+ procedure generateidatasection;
+ public
+ procedure generatelib;override;
+ end;
+
+ TExportLibWin=class(texportlib)
+ private
+ st : string;
+ EList_indexed:TFPList;
+ EList_nonindexed:TFPList;
+ public
+ destructor Destroy;override;
+ procedure preparelib(const s:string);override;
+ procedure exportprocedure(hp : texported_item);override;
+ procedure exportvar(hp : texported_item);override;
+ procedure exportfromlist(hp : texported_item);
+ procedure generatelib;override;
+ procedure generatenasmlib;virtual;
+ end;
+
+ TInternalLinkerWin = class(tinternallinker)
+ constructor create;override;
+ procedure DefaultLinkScript;override;
+ procedure InitSysInitUnitName;override;
+ procedure ConcatEntryName; virtual;
+ end;
+
+ TExternalLinkerWin=class(texternallinker)
+ private
+ Function WriteResponseFile(isdll:boolean) : Boolean;
+ Function PostProcessExecutable(const fn:string;isdll:boolean) : Boolean;
+ public
+ Constructor Create;override;
+ Procedure SetDefaultInfo;override;
+ function MakeExecutable:boolean;override;
+ function MakeSharedLibrary:boolean;override;
+ procedure InitSysInitUnitName;override;
+ end;
+
+ TDLLScannerWin=class(tDLLScanner)
+ private
+ importfound : boolean;
+ procedure CheckDLLFunc(const dllname,funcname:string);
+ public
+ function Scan(const binname:string):boolean;override;
+ end;
+
+implementation
+
+ uses
+ SysUtils,
+ cfileutl,
+ cpuinfo,cgutils,dbgbase,
+ owar,ogbase,ogcoff;
+
+
+ const
+{$ifndef x86_64}
+ res_gnu_windres_info : tresinfo =
+ (
+ id : res_gnu_windres;
+ resbin : 'fpcres';
+ rescmd : '-o $OBJ -a $ARCH -of coff $DBG';
+ rcbin : 'windres';
+ rccmd : '--include $INC -O res -o $RES $RC';
+ resourcefileclass : nil;
+ resflags : [];
+ );
+{$else x86_64}
+ res_win64_gorc_info : tresinfo =
+ (
+ id : res_win64_gorc;
+ resbin : 'fpcres';
+ rescmd : '-o $OBJ -a $ARCH -of coff $DBG';
+ rcbin : 'gorc';
+ rccmd : '/machine x64 /nw /ni /r /fo $RES $RC';
+ resourcefileclass : nil;
+ resflags : [];
+ );
+{$endif x86_64}
+
+
+ Procedure GlobalInitSysInitUnitName(Linker : TLinker);
+ var
+ hp : tmodule;
+ linkcygwin : boolean;
+ begin
+ hp:=tmodule(loaded_units.first);
+ while assigned(hp) do
+ begin
+ linkcygwin := hp.linkothersharedlibs.find('cygwin') or hp.linkotherstaticlibs.find('cygwin');
+ if linkcygwin then
+ break;
+ hp:=tmodule(hp.next);
+ end;
+ if cs_profile in current_settings.moduleswitches then
+ linker.sysinitunit:='sysinitgprof'
+ else if linkcygwin or (Linker.SharedLibFiles.Find('cygwin')<>nil) or (Linker.StaticLibFiles.Find('cygwin')<>nil) then
+ linker.sysinitunit:='sysinitcyg'
+ else
+ linker.sysinitunit:='sysinitpas';
+ end;
+
+
+{*****************************************************************************
+ TImportLibWin
+*****************************************************************************}
+
+ procedure TImportLibWin.generateimportlib;
+ var
+ ObjWriter : tarobjectwriter;
+ ObjOutput : TPECoffObjOutput;
+ basedllname : string;
+ AsmPrefix : string;
+ idatalabnr,
+ SmartFilesCount,
+ SmartHeaderCount : longint;
+
+ function CreateObjData(place:tcutplace):TObjData;
+ var
+ s : string;
+ begin
+ s:='';
+ case place of
+ cut_begin :
+ begin
+ inc(SmartHeaderCount);
+ s:=asmprefix+tostr(SmartHeaderCount)+'h';
+ end;
+ cut_normal :
+ s:=asmprefix+tostr(SmartHeaderCount)+'s';
+ cut_end :
+ s:=asmprefix+tostr(SmartHeaderCount)+'t';
+ end;
+ inc(SmartFilesCount);
+ result:=ObjOutput.NewObjData(FixFileName(s+tostr(SmartFilesCount)+target_info.objext));
+ ObjOutput.startobjectfile(Result.Name);
+ end;
+
+ procedure WriteObjData(objdata:TObjData);
+ begin
+ ObjOutput.writeobjectfile(ObjData);
+ end;
+
+ procedure StartImport(const dllname:string);
+ var
+ headlabel,
+ idata4label,
+ idata5label,
+ idata7label : TObjSymbol;
+ emptyint : longint;
+ objdata : TObjData;
+ idata2objsection,
+ idata4objsection,
+ idata5objsection : TObjSection;
+ begin
+ objdata:=CreateObjData(cut_begin);
+ idata2objsection:=objdata.createsection(sec_idata2,'');
+ idata4objsection:=objdata.createsection(sec_idata4,'');
+ idata5objsection:=objdata.createsection(sec_idata5,'');
+ emptyint:=0;
+ basedllname:=ExtractFileName(dllname);
+ { idata4 }
+ objdata.SetSection(idata4objsection);
+ idata4label:=objdata.SymbolDefine(asmprefix+'_names_'+basedllname,AB_GLOBAL,AT_DATA);
+ { idata5 }
+ objdata.SetSection(idata5objsection);
+ idata5label:=objdata.SymbolDefine(asmprefix+'_fixup_'+basedllname,AB_GLOBAL,AT_DATA);
+ { idata2 }
+ objdata.SetSection(idata2objsection);
+ headlabel:=objdata.SymbolDefine(asmprefix+'_head_'+basedllname,AB_GLOBAL,AT_DATA);
+ ObjOutput.exportsymbol(headlabel);
+ objdata.writereloc(0,sizeof(longint),idata4label,RELOC_RVA);
+ objdata.writebytes(emptyint,sizeof(emptyint));
+ objdata.writebytes(emptyint,sizeof(emptyint));
+ idata7label:=objdata.SymbolRef(asmprefix+'_dll_'+basedllname);
+ objdata.writereloc(0,sizeof(longint),idata7label,RELOC_RVA);
+ objdata.writereloc(0,sizeof(longint),idata5label,RELOC_RVA);
+ WriteObjData(objdata);
+ objdata.free;
+ end;
+
+ procedure EndImport;
+ var
+ idata7label : TObjSymbol;
+ emptyint : longint;
+ objdata : TObjData;
+ idata4objsection,
+ idata5objsection,
+ idata7objsection : TObjSection;
+ begin
+ objdata:=CreateObjData(cut_end);
+ idata4objsection:=objdata.createsection(sec_idata4,'');
+ idata5objsection:=objdata.createsection(sec_idata5,'');
+ idata7objsection:=objdata.createsection(sec_idata7,'');
+ emptyint:=0;
+ { idata4 }
+ objdata.SetSection(idata4objsection);
+ objdata.writebytes(emptyint,sizeof(emptyint));
+ if target_info.system=system_x86_64_win64 then
+ objdata.writebytes(emptyint,sizeof(emptyint));
+ { idata5 }
+ objdata.SetSection(idata5objsection);
+ objdata.writebytes(emptyint,sizeof(emptyint));
+ if target_info.system=system_x86_64_win64 then
+ objdata.writebytes(emptyint,sizeof(emptyint));
+ { idata7 }
+ objdata.SetSection(idata7objsection);
+ idata7label:=objdata.SymbolDefine(asmprefix+'_dll_'+basedllname,AB_GLOBAL,AT_DATA);
+ objoutput.exportsymbol(idata7label);
+ objdata.writebytes(basedllname[1],length(basedllname));
+ objdata.writebytes(emptyint,1);
+ WriteObjData(objdata);
+ objdata.free;
+ end;
+
+ procedure AddImport(const afuncname,mangledname:string;ordnr:longint;isvar:boolean);
+ const
+{$ifdef x86_64}
+ jmpopcode : array[0..1] of byte = (
+ $ff,$25 // jmp qword [rip + offset32]
+ );
+{$else x86_64}
+ {$ifdef arm}
+ jmpopcode : array[0..7] of byte = (
+ $00,$c0,$9f,$e5, // ldr ip, [pc, #0]
+ $00,$f0,$9c,$e5 // ldr pc, [ip]
+ );
+ {$else arm}
+ jmpopcode : array[0..1] of byte = (
+ $ff,$25
+ );
+ {$endif arm}
+{$endif x86_64}
+ nopopcodes : array[0..1] of byte = (
+ $90,$90
+ );
+ var
+ implabel,
+ idata2label,
+ idata5label,
+ idata6label : TObjSymbol;
+ emptyint : longint;
+ objdata : TObjData;
+ textobjsection,
+ idata4objsection,
+ idata5objsection,
+ idata6objsection,
+ idata7objsection : TObjSection;
+ absordnr: word;
+
+ procedure WriteTableEntry;
+ var
+ ordint: dword;
+ begin
+ if ordnr <= 0 then
+ begin
+ { import by name }
+ objdata.writereloc(0,sizeof(longint),idata6label,RELOC_RVA);
+ if target_info.system=system_x86_64_win64 then
+ objdata.writebytes(emptyint,sizeof(emptyint));
+ end
+ else
+ begin
+ { import by ordinal }
+ ordint:=ordnr;
+ if target_info.system=system_x86_64_win64 then
+ begin
+ objdata.writebytes(ordint,sizeof(ordint));
+ ordint:=$80000000;
+ objdata.writebytes(ordint,sizeof(ordint));
+ end
+ else
+ begin
+ ordint:=ordint or $80000000;
+ objdata.writebytes(ordint,sizeof(ordint));
+ end;
+ end;
+ end;
+
+ begin
+ objdata:=CreateObjData(cut_normal);
+ if not isvar then
+ textobjsection:=objdata.createsection(sec_code,'');
+ idata4objsection:=objdata.createsection(sec_idata4,'');
+ idata5objsection:=objdata.createsection(sec_idata5,'');
+ idata6objsection:=objdata.createsection(sec_idata6,'');
+ idata7objsection:=objdata.createsection(sec_idata7,'');
+ emptyint:=0;
+ { idata7, link to head }
+ objdata.SetSection(idata7objsection);
+ idata2label:=objdata.SymbolRef(asmprefix+'_head_'+basedllname);
+ objdata.writereloc(0,sizeof(longint),idata2label,RELOC_RVA);
+ { idata6, import data (ordnr+name) }
+ objdata.SetSection(idata6objsection);
+ inc(idatalabnr);
+ idata6label:=objdata.SymbolDefine(asmprefix+'_'+tostr(idatalabnr),AB_LOCAL,AT_DATA);
+ absordnr:=Abs(ordnr);
+ { write index hint }
+ objdata.writebytes(absordnr,2);
+ if ordnr <= 0 then
+ objdata.writebytes(afuncname[1],length(afuncname));
+ objdata.writebytes(emptyint,1);
+ objdata.writebytes(emptyint,align(objdata.CurrObjSec.size,2)-objdata.CurrObjSec.size);
+ { idata4, import lookup table }
+ objdata.SetSection(idata4objsection);
+ WriteTableEntry;
+ { idata5, import address table }
+ objdata.SetSection(idata5objsection);
+ if isvar then
+ implabel:=objdata.SymbolDefine(mangledname,AB_GLOBAL,AT_DATA)
+ else
+ idata5label:=objdata.SymbolDefine(asmprefix+'_'+mangledname,AB_LOCAL,AT_DATA);
+ WriteTableEntry;
+ { text, jmp }
+ if not isvar then
+ begin
+ objdata.SetSection(textobjsection);
+ if mangledname <> '' then
+ implabel:=objdata.SymbolDefine(mangledname,AB_GLOBAL,AT_FUNCTION)
+ else
+ implabel:=objdata.SymbolDefine(basedllname+'_index_'+tostr(ordnr),AB_GLOBAL,AT_FUNCTION);
+ objdata.writebytes(jmpopcode,sizeof(jmpopcode));
+{$ifdef x86_64}
+ objdata.writereloc(0,sizeof(longint),idata5label,RELOC_RELATIVE);
+{$else}
+ objdata.writereloc(0,sizeof(longint),idata5label,RELOC_ABSOLUTE32);
+{$endif x86_64}
+ objdata.writebytes(nopopcodes,align(objdata.CurrObjSec.size,sizeof(nopopcodes))-objdata.CurrObjSec.size);
+ end;
+ ObjOutput.exportsymbol(implabel);
+ WriteObjData(objdata);
+ objdata.free;
+ end;
+
+ var
+ i,j : longint;
+ ImportLibrary : TImportLibrary;
+ ImportSymbol : TImportSymbol;
+ begin
+ AsmPrefix:='imp'+Lower(current_module.modulename^);
+ idatalabnr:=0;
+ SmartFilesCount:=0;
+ SmartHeaderCount:=0;
+ current_module.linkotherstaticlibs.add(current_module.importlibfilename^,link_always);
+ ObjWriter:=TARObjectWriter.create(current_module.importlibfilename^);
+ ObjOutput:=TPECoffObjOutput.Create(ObjWriter);
+ for i:=0 to current_module.ImportLibraryList.Count-1 do
+ begin
+ ImportLibrary:=TImportLibrary(current_module.ImportLibraryList[i]);
+ StartImport(ImportLibrary.Name);
+ for j:=0 to ImportLibrary.ImportSymbolList.Count-1 do
+ begin
+ ImportSymbol:=TImportSymbol(ImportLibrary.ImportSymbolList[j]);
+ AddImport(ImportSymbol.Name,ImportSymbol.MangledName,ImportSymbol.OrdNr,ImportSymbol.IsVar);
+ end;
+ EndImport;
+ end;
+ ObjOutput.Free;
+ ObjWriter.Free;
+ end;
+
+
+ procedure TImportLibWin.generateidatasection;
+ var
+ templab,
+ l1,l2,l3,l4 {$ifdef ARM} ,l5 {$endif ARM} : tasmlabel;
+ importname : string;
+ suffix : integer;
+ href : treference;
+ i,j : longint;
+ ImportLibrary : TImportLibrary;
+ ImportSymbol : TImportSymbol;
+ ImportLabels : TFPList;
+ begin
+ if current_asmdata.asmlists[al_imports]=nil then
+ current_asmdata.asmlists[al_imports]:=TAsmList.create;
+
+ if (target_asm.id in [as_i386_masm,as_i386_tasm,as_i386_nasmwin32]) then
+ begin
+ new_section(current_asmdata.asmlists[al_imports],sec_code,'',0);
+ for i:=0 to current_module.ImportLibraryList.Count-1 do
+ begin
+ ImportLibrary:=TImportLibrary(current_module.ImportLibraryList[i]);
+ for j:=0 to ImportLibrary.ImportSymbolList.Count-1 do
+ begin
+ ImportSymbol:=TImportSymbol(ImportLibrary.ImportSymbolList[j]);
+ current_asmdata.asmlists[al_imports].concat(tai_directive.create(asd_extern,ImportSymbol.Name));
+ current_asmdata.asmlists[al_imports].concat(tai_directive.create(asd_nasm_import,ImportSymbol.Name+' '+ImportLibrary.Name+' '+ImportSymbol.Name));
+ end;
+ end;
+ exit;
+ end;
+
+ for i:=0 to current_module.ImportLibraryList.Count-1 do
+ begin
+ ImportLibrary:=TImportLibrary(current_module.ImportLibraryList[i]);
+ { align al_procedures for the jumps }
+ new_section(current_asmdata.asmlists[al_imports],sec_code,'',sizeof(aint));
+ { Get labels for the sections }
+ current_asmdata.getjumplabel(l1);
+ current_asmdata.getjumplabel(l2);
+ current_asmdata.getjumplabel(l3);
+ new_section(current_asmdata.asmlists[al_imports],sec_idata2,'',0);
+ { pointer to procedure names }
+ current_asmdata.asmlists[al_imports].concat(Tai_const.Create_rva_sym(l2));
+ { two empty entries follow }
+ current_asmdata.asmlists[al_imports].concat(Tai_const.Create_32bit(0));
+ current_asmdata.asmlists[al_imports].concat(Tai_const.Create_32bit(0));
+ { pointer to dll name }
+ current_asmdata.asmlists[al_imports].concat(Tai_const.Create_rva_sym(l1));
+ { pointer to fixups }
+ current_asmdata.asmlists[al_imports].concat(Tai_const.Create_rva_sym(l3));
+
+ { only create one section for each else it will
+ create a lot of idata* }
+
+ { first write the name references }
+ new_section(current_asmdata.asmlists[al_imports],sec_idata4,'',0);
+ current_asmdata.asmlists[al_imports].concat(Tai_label.Create(l2));
+
+ ImportLabels:=TFPList.Create;
+ ImportLabels.Count:=ImportLibrary.ImportSymbolList.Count;
+ for j:=0 to ImportLibrary.ImportSymbolList.Count-1 do
+ begin
+ ImportSymbol:=TImportSymbol(ImportLibrary.ImportSymbolList[j]);
+
+ current_asmdata.getjumplabel(templab);
+ ImportLabels[j]:=templab;
+ if ImportSymbol.Name<>'' then
+ begin
+ current_asmdata.asmlists[al_imports].concat(Tai_const.Create_rva_sym(TAsmLabel(ImportLabels[j])));
+ if target_info.system=system_x86_64_win64 then
+ current_asmdata.asmlists[al_imports].concat(Tai_const.Create_32bit(0));
+ end
+ else
+ begin
+ if target_info.system=system_x86_64_win64 then
+ current_asmdata.asmlists[al_imports].concat(Tai_const.Create_64bit(int64($8000000000000000) or ImportSymbol.ordnr))
+ else
+ current_asmdata.asmlists[al_imports].concat(Tai_const.Create_32bit(longint($80000000) or ImportSymbol.ordnr));
+ end;
+ end;
+ { finalize the names ... }
+ current_asmdata.asmlists[al_imports].concat(Tai_const.Create_32bit(0));
+ if target_info.system=system_x86_64_win64 then
+ current_asmdata.asmlists[al_imports].concat(Tai_const.Create_32bit(0));
+
+ { then the addresses and create also the indirect jump }
+ new_section(current_asmdata.asmlists[al_imports],sec_idata5,'',0);
+ current_asmdata.asmlists[al_imports].concat(Tai_label.Create(l3));
+
+ for j:=0 to ImportLibrary.ImportSymbolList.Count-1 do
+ begin
+ ImportSymbol:=TImportSymbol(ImportLibrary.ImportSymbolList[j]);
+ if not ImportSymbol.IsVar then
+ begin
+ current_asmdata.getjumplabel(l4);
+ {$ifdef ARM}
+ current_asmdata.getjumplabel(l5);
+ {$endif ARM}
+ { create indirect jump and }
+ { place jump in al_procedures }
+ new_section(current_asmdata.asmlists[al_imports],sec_code,'',0);
+ if ImportSymbol.Name <> '' then
+ current_asmdata.asmlists[al_imports].concat(Tai_symbol.Createname_global(ImportSymbol.MangledName,AT_FUNCTION,0))
+ else
+ current_asmdata.asmlists[al_imports].concat(Tai_symbol.Createname_global(ExtractFileName(ImportLibrary.Name)+'_index_'+tostr(ImportSymbol.ordnr),AT_FUNCTION,0));
+ current_asmdata.asmlists[al_imports].concat(tai_function_name.create(''));
+ {$ifdef ARM}
+ reference_reset_symbol(href,l5,0,sizeof(pint));
+ current_asmdata.asmlists[al_imports].concat(Taicpu.op_reg_ref(A_LDR,NR_R12,href));
+ reference_reset_base(href,NR_R12,0,sizeof(pint));
+ current_asmdata.asmlists[al_imports].concat(Taicpu.op_reg_ref(A_LDR,NR_R15,href));
+ current_asmdata.asmlists[al_imports].concat(Tai_label.Create(l5));
+ reference_reset_symbol(href,l4,0,sizeof(pint));
+ current_asmdata.asmlists[al_imports].concat(tai_const.create_sym_offset(href.symbol,href.offset));
+ {$else ARM}
+ reference_reset_symbol(href,l4,0,sizeof(pint));
+{$ifdef X86_64}
+ href.base:=NR_RIP;
+{$endif X86_64}
+
+ current_asmdata.asmlists[al_imports].concat(Taicpu.Op_ref(A_JMP,S_NO,href));
+ current_asmdata.asmlists[al_imports].concat(Tai_align.Create_op(4,$90));
+ {$endif ARM}
+ { add jump field to al_imports }
+ new_section(current_asmdata.asmlists[al_imports],sec_idata5,'',0);
+ if (cs_debuginfo in current_settings.moduleswitches) then
+ begin
+ if ImportSymbol.MangledName<>'' then
+ begin
+ importname:='__imp_'+ImportSymbol.MangledName;
+ suffix:=0;
+ while assigned(current_asmdata.getasmsymbol(importname)) do
+ begin
+ inc(suffix);
+ importname:='__imp_'+ImportSymbol.MangledName+'_'+tostr(suffix);
+ end;
+ current_asmdata.asmlists[al_imports].concat(tai_symbol.createname(importname,AT_FUNCTION,4));
+ end
+ else
+ begin
+ importname:='__imp_by_ordinal'+tostr(ImportSymbol.ordnr);
+ suffix:=0;
+ while assigned(current_asmdata.getasmsymbol(importname)) do
+ begin
+ inc(suffix);
+ importname:='__imp_by_ordinal'+tostr(ImportSymbol.ordnr)+'_'+tostr(suffix);
+ end;
+ current_asmdata.asmlists[al_imports].concat(tai_symbol.createname(importname,AT_FUNCTION,4));
+ end;
+ end;
+ current_asmdata.asmlists[al_imports].concat(Tai_label.Create(l4));
+ end
+ else
+ current_asmdata.asmlists[al_imports].concat(Tai_symbol.Createname_global(ImportSymbol.MangledName,AT_DATA,0));
+ current_asmdata.asmlists[al_imports].concat(Tai_const.Create_rva_sym(TAsmLabel(Importlabels[j])));
+ if target_info.system=system_x86_64_win64 then
+ current_asmdata.asmlists[al_imports].concat(Tai_const.Create_32bit(0));
+ end;
+ { finalize the addresses }
+ current_asmdata.asmlists[al_imports].concat(Tai_const.Create_32bit(0));
+ if target_info.system=system_x86_64_win64 then
+ current_asmdata.asmlists[al_imports].concat(Tai_const.Create_32bit(0));
+
+ { finally the import information }
+ new_section(current_asmdata.asmlists[al_imports],sec_idata6,'',0);
+ for j:=0 to ImportLibrary.ImportSymbolList.Count-1 do
+ begin
+ ImportSymbol:=TImportSymbol(ImportLibrary.ImportSymbolList[j]);
+ current_asmdata.asmlists[al_imports].concat(Tai_label.Create(TAsmLabel(ImportLabels[j])));
+ { the ordinal number }
+ current_asmdata.asmlists[al_imports].concat(Tai_const.Create_16bit(ImportSymbol.ordnr));
+ current_asmdata.asmlists[al_imports].concat(Tai_string.Create(ImportSymbol.Name+#0));
+ current_asmdata.asmlists[al_imports].concat(Tai_align.Create_op(2,0));
+ end;
+ { create import dll name }
+ new_section(current_asmdata.asmlists[al_imports],sec_idata7,'',0);
+ current_asmdata.asmlists[al_imports].concat(Tai_label.Create(l1));
+ current_asmdata.asmlists[al_imports].concat(Tai_string.Create(ImportLibrary.Name+#0));
+ ImportLabels.Free;
+ ImportLabels:=nil;
+ end;
+ end;
+
+
+ procedure TImportLibWin.generatelib;
+ begin
+ if GenerateImportSection then
+ generateidatasection
+ else
+ generateimportlib;
+ end;
+
+
+{*****************************************************************************
+ TExportLibWin
+*****************************************************************************}
+
+ destructor TExportLibWin.Destroy;
+ begin
+ EList_indexed.Free;
+ EList_nonindexed.Free;
+ inherited;
+ end;
+
+
+ procedure TExportLibWin.preparelib(const s:string);
+ begin
+ if current_asmdata.asmlists[al_exports]=nil then
+ current_asmdata.asmlists[al_exports]:=TAsmList.create;
+ if EList_indexed=nil then
+ EList_indexed:=tFPList.Create;
+ if EList_nonindexed=nil then
+ EList_nonindexed:=tFPList.Create;
+ end;
+
+
+ procedure TExportLibWin.exportvar(hp : texported_item);
+ begin
+ { same code used !! PM }
+ exportprocedure(hp);
+ end;
+
+ var
+ Gl_DoubleIndex:boolean;
+ Gl_DoubleIndexValue:longint;
+
+ function IdxCompare(Item1, Item2: Pointer): Integer;
+ var
+ I1:texported_item absolute Item1;
+ I2:texported_item absolute Item2;
+ begin
+ Result:=I1.index-I2.index;
+ if(Result=0)and(Item1<>Item2)then
+ begin
+ Gl_DoubleIndex:=true;
+ Gl_DoubleIndexValue:=I1.index;
+ end;
+ end;
+
+
+ procedure TExportLibWin.exportprocedure(hp : texported_item);
+ begin
+ if ((hp.options and eo_index)<>0) and ((hp.index<=0) or (hp.index>$ffff)) then
+ begin
+ message1(parser_e_export_invalid_index,tostr(hp.index));
+ exit;
+ end;
+ if hp.options and eo_index=eo_index then
+ EList_indexed.Add(hp)
+ else
+ EList_nonindexed.Add(hp);
+ end;
+
+
+ procedure TExportLibWin.exportfromlist(hp : texported_item);
+ //formerly TExportLibWin.exportprocedure
+ { must be ordered at least for win32 !! }
+ var
+ hp2 : texported_item;
+ begin
+ hp2:=texported_item(current_module._exports.first);
+ while assigned(hp2) and
+ (hp.name^>hp2.name^) do
+ hp2:=texported_item(hp2.next);
+ { insert hp there !! }
+ if hp2=nil then
+ current_module._exports.concat(hp)
+ else
+ begin
+ if hp2.name^=hp.name^ then
+ begin
+ { this is not allowed !! }
+ message1(parser_e_export_name_double,hp.name^);
+ exit;
+ end;
+ current_module._exports.insertbefore(hp,hp2);
+ end;
+ end;
+
+
+ procedure TExportLibWin.generatelib;
+ var
+ ordinal_base,ordinal_max,ordinal_min : longint;
+ current_index : longint;
+ entries,named_entries : longint;
+ name_label,dll_name_label,export_address_table : tasmlabel;
+ export_name_table_pointers,export_ordinal_table : tasmlabel;
+ hp,hp2 : texported_item;
+ temtexport : TLinkedList;
+ address_table,name_table_pointers,
+ name_table,ordinal_table : TAsmList;
+ i,autoindex,ni_high : longint;
+ hole : boolean;
+ asmsym : TAsmSymbol;
+ begin
+ Gl_DoubleIndex:=false;
+ ELIst_indexed.Sort(@IdxCompare);
+
+ if Gl_DoubleIndex then
+ begin
+ message1(parser_e_export_ordinal_double,tostr(Gl_DoubleIndexValue));
+ FreeAndNil(EList_indexed);
+ FreeAndNil(EList_nonindexed);
+ exit;
+ end;
+
+ autoindex:=1;
+ while EList_nonindexed.Count>0 do
+ begin
+ hole:=(EList_indexed.Count>0) and (texported_item(EList_indexed.Items[0]).index>1);
+ if not hole then
+ for i:=autoindex to pred(EList_indexed.Count) do
+ if texported_item(EList_indexed.Items[i]).index-texported_item(EList_indexed.Items[pred(i)]).index>1 then
+ begin
+ autoindex:=succ(texported_item(EList_indexed.Items[pred(i)]).index);
+ hole:=true;
+ break;
+ end;
+ ni_high:=pred(EList_nonindexed.Count);
+ if not hole then
+ begin
+ autoindex:=succ(EList_indexed.Count);
+ EList_indexed.Add(EList_nonindexed.Items[ni_high]);
+ end
+ else
+ EList_indexed.Insert(pred(AutoIndex),EList_nonindexed.Items[ni_high]);
+ EList_nonindexed.Delete(ni_high);
+ texported_item(EList_indexed.Items[pred(AutoIndex)]).index:=autoindex;
+ end;
+ FreeAndNil(EList_nonindexed);
+ for i:=0 to pred(EList_indexed.Count) do
+ exportfromlist(texported_item(EList_indexed.Items[i]));
+ FreeAndNil(EList_indexed);
+
+ if (target_asm.id in [as_i386_masm,as_i386_tasm,as_i386_nasmwin32]) then
+ begin
+ generatenasmlib;
+ exit;
+ end;
+
+ hp:=texported_item(current_module._exports.first);
+ if not assigned(hp) then
+ exit;
+
+ ordinal_max:=0;
+ ordinal_min:=$7FFFFFFF;
+ entries:=0;
+ named_entries:=0;
+ current_asmdata.getjumplabel(dll_name_label);
+ current_asmdata.getjumplabel(export_address_table);
+ current_asmdata.getjumplabel(export_name_table_pointers);
+ current_asmdata.getjumplabel(export_ordinal_table);
+
+ { count entries }
+ while assigned(hp) do
+ begin
+ inc(entries);
+ if (hp.index>ordinal_max) then
+ ordinal_max:=hp.index;
+ if (hp.index>0) and (hp.index<ordinal_min) then
+ ordinal_min:=hp.index;
+ if assigned(hp.name) then
+ inc(named_entries);
+ hp:=texported_item(hp.next);
+ end;
+
+ { no support for higher ordinal base yet !! }
+ ordinal_base:=1;
+ current_index:=ordinal_base;
+ { we must also count the holes !! }
+ entries:=ordinal_max-ordinal_base+1;
+
+ new_section(current_asmdata.asmlists[al_exports],sec_edata,'',0);
+ { create label to reference from main so smartlink will include
+ the .edata section }
+ current_asmdata.asmlists[al_exports].concat(Tai_symbol.Createname_global(make_mangledname('EDATA',current_module.localsymtable,''),AT_DATA,0));
+ { export flags }
+ current_asmdata.asmlists[al_exports].concat(Tai_const.Create_32bit(0));
+ { date/time stamp }
+ current_asmdata.asmlists[al_exports].concat(Tai_const.Create_32bit(0));
+ { major version }
+ current_asmdata.asmlists[al_exports].concat(Tai_const.Create_16bit(0));
+ { minor version }
+ current_asmdata.asmlists[al_exports].concat(Tai_const.Create_16bit(0));
+ { pointer to dll name }
+ current_asmdata.asmlists[al_exports].concat(Tai_const.Create_rva_sym(dll_name_label));
+ { ordinal base normally set to 1 }
+ current_asmdata.asmlists[al_exports].concat(Tai_const.Create_32bit(ordinal_base));
+ { number of entries }
+ current_asmdata.asmlists[al_exports].concat(Tai_const.Create_32bit(entries));
+ { number of named entries }
+ current_asmdata.asmlists[al_exports].concat(Tai_const.Create_32bit(named_entries));
+ { address of export address table }
+ current_asmdata.asmlists[al_exports].concat(Tai_const.Create_rva_sym(export_address_table));
+ { address of name pointer pointers }
+ current_asmdata.asmlists[al_exports].concat(Tai_const.Create_rva_sym(export_name_table_pointers));
+ { address of ordinal number pointers }
+ current_asmdata.asmlists[al_exports].concat(Tai_const.Create_rva_sym(export_ordinal_table));
+ { the name }
+ current_asmdata.asmlists[al_exports].concat(Tai_label.Create(dll_name_label));
+ if st='' then
+ current_asmdata.asmlists[al_exports].concat(Tai_string.Create(current_module.modulename^+target_info.sharedlibext+#0))
+ else
+ current_asmdata.asmlists[al_exports].concat(Tai_string.Create(st+target_info.sharedlibext+#0));
+
+ { export address table }
+ address_table:=TAsmList.create;
+ address_table.concat(Tai_align.Create_op(4,0));
+ address_table.concat(Tai_label.Create(export_address_table));
+ name_table_pointers:=TAsmList.create;
+ name_table_pointers.concat(Tai_align.Create_op(4,0));
+ name_table_pointers.concat(Tai_label.Create(export_name_table_pointers));
+ ordinal_table:=TAsmList.create;
+ ordinal_table.concat(Tai_align.Create_op(4,0));
+ ordinal_table.concat(Tai_label.Create(export_ordinal_table));
+ name_table:=TAsmList.Create;
+ name_table.concat(Tai_align.Create_op(4,0));
+ { write each address }
+ hp:=texported_item(current_module._exports.first);
+ while assigned(hp) do
+ begin
+ if (hp.options and eo_name)<>0 then
+ begin
+ current_asmdata.getjumplabel(name_label);
+ name_table_pointers.concat(Tai_const.Create_rva_sym(name_label));
+ ordinal_table.concat(Tai_const.Create_16bit(hp.index-ordinal_base));
+ name_table.concat(Tai_align.Create_op(2,0));
+ name_table.concat(Tai_label.Create(name_label));
+ name_table.concat(Tai_string.Create(hp.name^+#0));
+ end;
+ hp:=texported_item(hp.next);
+ end;
+ { order in increasing ordinal values }
+ { into temtexport list }
+ temtexport:=TLinkedList.Create;
+ hp:=texported_item(current_module._exports.first);
+ while assigned(hp) do
+ begin
+ current_module._exports.remove(hp);
+ hp2:=texported_item(temtexport.first);
+ while assigned(hp2) and (hp.index>hp2.index) do
+ hp2:=texported_item(hp2.next);
+ if hp2=nil then
+ temtexport.concat(hp)
+ else
+ temtexport.insertbefore(hp,hp2);
+ hp:=texported_item(current_module._exports.first);
+ end;
+
+ { write the export adress table }
+ current_index:=ordinal_base;
+ hp:=texported_item(temtexport.first);
+ while assigned(hp) do
+ begin
+ { fill missing values }
+ while current_index<hp.index do
+ begin
+ address_table.concat(Tai_const.Create_32bit(0));
+ inc(current_index);
+ end;
+
+ { symbol known? then get a new name }
+ if assigned(hp.sym) then
+ case hp.sym.typ of
+ staticvarsym :
+ asmsym:=current_asmdata.RefAsmSymbol(tstaticvarsym(hp.sym).mangledname);
+ procsym :
+ asmsym:=current_asmdata.RefAsmSymbol(tprocdef(tprocsym(hp.sym).ProcdefList[0]).mangledname)
+ else
+ internalerror(200709272);
+ end
+ else
+ asmsym:=current_asmdata.RefAsmSymbol(hp.name^);
+ address_table.concat(Tai_const.Create_rva_sym(asmsym));
+ inc(current_index);
+ hp:=texported_item(hp.next);
+ end;
+
+ current_asmdata.asmlists[al_exports].concatlist(address_table);
+ current_asmdata.asmlists[al_exports].concatlist(name_table_pointers);
+ current_asmdata.asmlists[al_exports].concatlist(ordinal_table);
+ current_asmdata.asmlists[al_exports].concatlist(name_table);
+ address_table.Free;
+ name_table_pointers.free;
+ ordinal_table.free;
+ name_table.free;
+
+ { the package support needs this data later on
+ to create the import library }
+ current_module._exports.concatlist(temtexport);
+ temtexport.free;
+ end;
+
+
+ procedure TExportLibWin.generatenasmlib;
+ var
+ hp : texported_item;
+ {p : pchar;
+ s : string;}
+ begin
+ new_section(current_asmdata.asmlists[al_exports],sec_code,'',0);
+ hp:=texported_item(current_module._exports.first);
+ while assigned(hp) do
+ begin
+{ case hp.sym.typ of
+ staticvarsym :
+ s:=tstaticvarsym(hp.sym).mangledname;
+ procsym :
+ s:=tprocdef(tprocsym(hp.sym).ProcdefList[0]).mangledname;
+ else
+ s:='';
+ end;
+ p:=strpnew(#9+'export '+s+' '+hp.Name^+' '+tostr(hp.index));
+ current_asmdata.asmlists[al_exports].concat(tai_direct.create(p));}
+ hp:=texported_item(hp.next);
+ end;
+ end;
+
+
+{****************************************************************************
+ TInternalLinkerWin
+****************************************************************************}
+
+ constructor TInternalLinkerWin.Create;
+ begin
+ inherited Create;
+ CExeoutput:=TPECoffexeoutput;
+ CObjInput:=TPECoffObjInput;
+ end;
+
+
+ procedure TInternalLinkerWin.DefaultLinkScript;
+ var
+ s,s2 : TCmdStr;
+ secname,
+ secnames : string;
+ begin
+ with LinkScript do
+ begin
+ while not ObjectFiles.Empty do
+ begin
+ s:=ObjectFiles.GetFirst;
+ if s<>'' then
+ Concat('READOBJECT '+MaybeQuoted(s));
+ end;
+ while not StaticLibFiles.Empty do
+ begin
+ s:=StaticLibFiles.GetFirst;
+ if s<>'' then
+ Concat('READSTATICLIBRARY '+MaybeQuoted(s));
+ end;
+ While not SharedLibFiles.Empty do
+ begin
+ S:=SharedLibFiles.GetFirst;
+ if FindLibraryFile(s,target_info.staticClibprefix,target_info.staticClibext,s2) then
+ Concat('READSTATICLIBRARY '+MaybeQuoted(s2))
+ else
+ Comment(V_Error,'Import library not found for '+S);
+ end;
+ if IsSharedLibrary then
+ Concat('ISSHAREDLIBRARY');
+ ConcatEntryName;
+ if not ImageBaseSetExplicity then
+ begin
+ if IsSharedLibrary then
+ imagebase:={$ifdef cpu64bitaddr} $110000000 {$else} $10000000 {$endif}
+ else
+ if target_info.system in systems_wince then
+ imagebase:=$10000
+ else
+{$ifdef cpu64bitaddr}
+ if (paratargetdbg = dbg_stabs) then
+ imagebase:=$400000
+ else
+ imagebase:= $100000000;
+{$else}
+ imagebase:=$400000;
+{$endif}
+ end;
+ Concat('IMAGEBASE $' + hexStr(imagebase, SizeOf(imagebase)*2));
+ Concat('HEADER');
+ Concat('EXESECTION .text');
+ Concat(' SYMBOL __text_start__');
+ Concat(' OBJSECTION .text*');
+ Concat(' SYMBOL ___CTOR_LIST__');
+ Concat(' SYMBOL __CTOR_LIST__');
+ Concat(' LONG -1');
+{$ifdef x86_64}
+ Concat(' LONG -1');
+{$endif x86_64}
+ Concat(' OBJSECTION .ctor*');
+ Concat(' LONG 0');
+{$ifdef x86_64}
+ Concat(' LONG 0');
+{$endif x86_64}
+ Concat(' SYMBOL ___DTOR_LIST__');
+ Concat(' SYMBOL __DTOR_LIST__');
+ Concat(' LONG -1');
+{$ifdef x86_64}
+ Concat(' LONG -1');
+{$endif x86_64}
+ Concat(' OBJSECTION .dtor*');
+ Concat(' LONG 0');
+{$ifdef x86_64}
+ Concat(' LONG 0');
+{$endif x86_64}
+ Concat(' SYMBOL etext');
+ Concat('ENDEXESECTION');
+ Concat('EXESECTION .data');
+ Concat(' SYMBOL __data_start__');
+ Concat(' OBJSECTION .data*');
+ Concat(' OBJSECTION .fpc*');
+ Concat(' PROVIDE '+target_info.Cprefix+'_tls_index');
+ Concat(' LONG 0');
+ Concat(' SYMBOL edata');
+ Concat(' SYMBOL __data_end__');
+ Concat('ENDEXESECTION');
+ Concat('EXESECTION .rdata');
+ Concat(' SYMBOL ___RUNTIME_PSEUDO_RELOC_LIST__');
+ Concat(' SYMBOL __RUNTIME_PSEUDO_RELOC_LIST__');
+ Concat(' OBJSECTION .rdata_runtime_pseudo_reloc');
+ Concat(' SYMBOL ___RUNTIME_PSEUDO_RELOC_LIST_END__');
+ Concat(' SYMBOL __RUNTIME_PSEUDO_RELOC_LIST_END__');
+ Concat(' OBJSECTION .rdata*');
+ Concat(' OBJSECTION .rodata*');
+ Concat(' OBJSECTION .xdata*');
+ Concat('ENDEXESECTION');
+ Concat('EXESECTION .pdata');
+ Concat(' OBJSECTION .pdata*');
+ Concat('ENDEXESECTION');
+ Concat('EXESECTION .bss');
+ Concat(' SYMBOL __bss_start__');
+ Concat(' OBJSECTION .bss*');
+ Concat(' SYMBOL __bss_end__');
+ Concat('ENDEXESECTION');
+ Concat('EXESECTION .tls');
+ Concat(' SYMBOL ___tls_start__');
+ Concat(' OBJSECTION .tls*');
+ Concat(' SYMBOL ___tls_end__');
+ Concat('ENDEXESECTION');
+ Concat('EXESECTION .CRT');
+ Concat(' SYMBOL ___crt_xc_start__');
+ Concat(' OBJSECTION .CRT$XC*');{ /* C initialization */');}
+ Concat(' SYMBOL ___crt_xc_end__');
+ Concat(' SYMBOL ___crt_xi_start__');
+ Concat(' OBJSECTION .CRT$XI*');{ /* C++ initialization */');}
+ Concat(' SYMBOL ___crt_xi_end__');
+ Concat(' SYMBOL ___crt_xl_start__');
+ Concat(' OBJSECTION .CRT$XL*'); { /* TLS callbacks */'); }
+ { In GNU ld, this is defined in the TLS Directory support code }
+ Concat(' PROVIDE ___crt_xl_end__');
+ { Add a nil pointer as last element }
+ Concat(' LONG 0');
+{$ifdef x86_64}
+ Concat(' LONG 0');
+{$endif x86_64}
+ Concat(' SYMBOL ___crt_xp_start__');
+ Concat(' OBJSECTION .CRT$XP*'); { /* Pre-termination */');}
+ Concat(' SYMBOL ___crt_xp_end__');
+ Concat(' SYMBOL ___crt_xt_start__');
+ Concat(' OBJSECTION .CRT$XT*');{ /* Termination */');}
+ Concat(' SYMBOL ___crt_xt_end__');
+ Concat('ENDEXESECTION');
+ Concat('EXESECTION .idata');
+ Concat(' OBJSECTION .idata$2*');
+ Concat(' OBJSECTION .idata$3*');
+ Concat(' ZEROS 20');
+ Concat(' OBJSECTION .idata$4*');
+ Concat(' SYMBOL __IAT_start__');
+ Concat(' OBJSECTION .idata$5*');
+ Concat(' SYMBOL __IAT_end__');
+ Concat(' OBJSECTION .idata$6*');
+ Concat(' OBJSECTION .idata$7*');
+ Concat('ENDEXESECTION');
+ secnames:='.edata,.rsrc,.reloc,.gnu_debuglink,'+
+ '.debug_aranges,.debug_pubnames,.debug_info,.debug_abbrev,.debug_line,.debug_frame,.debug_str,.debug_loc,'+
+ '.debug_macinfo,.debug_weaknames,.debug_funcnames,.debug_typenames,.debug_varnames,.debug_ranges';
+ repeat
+ secname:=gettoken(secnames,',');
+ if secname='' then
+ break;
+ Concat('EXESECTION '+secname);
+ Concat(' OBJSECTION '+secname+'*');
+ Concat('ENDEXESECTION');
+ until false;
+ { Can't use the generic rules, because that will add also .stabstr to .stab }
+ Concat('EXESECTION .stab');
+ Concat(' OBJSECTION .stab');
+ Concat('ENDEXESECTION');
+ Concat('EXESECTION .stabstr');
+ Concat(' OBJSECTION .stabstr');
+ Concat('ENDEXESECTION');
+ Concat('STABS');
+ Concat('SYMBOLS');
+ end;
+ end;
+
+
+ procedure TInternalLinkerWin.InitSysInitUnitName;
+ begin
+ if target_info.system=system_i386_win32 then
+ GlobalInitSysInitUnitName(self);
+ end;
+
+ procedure TInternalLinkerWin.ConcatEntryName;
+ begin
+ with LinkScript do
+ begin
+ if IsSharedLibrary then
+ begin
+ Concat('ISSHAREDLIBRARY');
+ if apptype=app_gui then
+ Concat('ENTRYNAME _DLLWinMainCRTStartup')
+ else
+ Concat('ENTRYNAME _DLLMainCRTStartup');
+ end
+ else
+ begin
+ if apptype=app_gui then
+ Concat('ENTRYNAME _WinMainCRTStartup')
+ else
+ Concat('ENTRYNAME _mainCRTStartup');
+ end;
+ end;
+ end;
+
+
+{****************************************************************************
+ TExternalLinkerWin
+****************************************************************************}
+
+ Constructor TExternalLinkerWin.Create;
+ begin
+ Inherited Create;
+ { allow duplicated libs (PM) }
+ SharedLibFiles.doubles:=true;
+ StaticLibFiles.doubles:=true;
+ end;
+
+
+ Procedure TExternalLinkerWin.SetDefaultInfo;
+ var
+ targetopts: string;
+ begin
+ with Info do
+ begin
+{$ifdef x86_64}
+ targetopts:='-b pei-x86-64';
+{$else x86_64}
+ if target_info.system=system_arm_wince then
+ targetopts:='-m arm_wince_pe'
+ else
+ targetopts:='-b pei-i386 -m i386pe';
+{$endif not x86_64}
+ ExeCmd[1]:='ld '+targetopts+' $OPT $GCSECTIONS $MAP $STRIP $APPTYPE $ENTRY $IMAGEBASE $RELOC -o $EXE $RES';
+ DllCmd[1]:='ld '+targetopts+' $OPT $GCSECTIONS $MAP $STRIP --dll $APPTYPE $ENTRY $IMAGEBASE $RELOC -o $EXE $RES';
+ { ExeCmd[2]:='dlltool --as $ASBIN --dllname $EXE --output-exp exp.$$$ $RELOC $DEF';
+ use short forms to avoid 128 char limitation problem }
+ ExeCmd[2]:='dlltool -S $ASBIN -D $EXE -e exp.$$$ $RELOC $DEF';
+ ExeCmd[3]:='ld '+targetopts+' $OPT $STRIP $APPTYPE $ENTRY $IMAGEBASE -o $EXE $RES exp.$$$';
+ { DllCmd[2]:='dlltool --as $ASBIN --dllname $EXE --output-exp exp.$$$ $RELOC $DEF'; }
+ DllCmd[2]:='dlltool -S $ASBIN -D $EXE -e exp.$$$ $RELOC $DEF';
+ DllCmd[3]:='ld '+targetopts+' $OPT $STRIP --dll $APPTYPE $ENTRY $IMAGEBASE -o $EXE $RES exp.$$$';
+ end;
+ end;
+
+
+
+ Function TExternalLinkerWin.WriteResponseFile(isdll:boolean) : Boolean;
+ Var
+ linkres : TLinkRes;
+ HPath : TCmdStrListItem;
+ s,s2 : TCmdStr;
+ i : integer;
+ begin
+ WriteResponseFile:=False;
+
+ if (cs_profile in current_settings.moduleswitches) then
+ begin
+ SharedLibFiles.Concat('gmon');
+ SharedLibFiles.Concat('c');
+ SharedLibFiles.Concat('gcc');
+ SharedLibFiles.Concat('kernel32');
+ end;
+
+ { Open link.res file }
+ LinkRes:=TLinkres.Create(outputexedir+Info.ResName);
+ with linkres do
+ begin
+ { Write path to search libraries }
+ HPath:=TCmdStrListItem(current_module.locallibrarysearchpath.First);
+ while assigned(HPath) do
+ begin
+ Add('SEARCH_DIR('+MaybeQuoted(HPath.Str)+')');
+ HPath:=TCmdStrListItem(HPath.Next);
+ end;
+ HPath:=TCmdStrListItem(LibrarySearchPath.First);
+ while assigned(HPath) do
+ begin
+ Add('SEARCH_DIR('+MaybeQuoted(HPath.Str)+')');
+ HPath:=TCmdStrListItem(HPath.Next);
+ end;
+
+ { add objectfiles, start with prt0 always }
+ { profiling of shared libraries is currently not supported }
+ if not ObjectFiles.Empty then
+ begin
+ Add('INPUT(');
+ while not ObjectFiles.Empty do
+ begin
+ s:=ObjectFiles.GetFirst;
+ if s<>'' then
+ AddFileName(MaybeQuoted(s));
+ end;
+ Add(')');
+ end;
+
+ { Write staticlibraries }
+ if (not StaticLibFiles.Empty) then
+ begin
+ Add('GROUP(');
+ While not StaticLibFiles.Empty do
+ begin
+ S:=StaticLibFiles.GetFirst;
+ AddFileName(MaybeQuoted(s));
+ end;
+ Add(')');
+ end;
+
+ { Write sharedlibraries (=import libraries) }
+ if not SharedLibFiles.Empty then
+ begin
+ Add('INPUT(') ;
+ While not SharedLibFiles.Empty do
+ begin
+ S:=SharedLibFiles.GetFirst;
+ if FindLibraryFile(s,target_info.staticClibprefix,target_info.staticClibext,s2) then
+ begin
+ Add(MaybeQuoted(s2));
+ continue;
+ end;
+ if pos(target_info.sharedlibprefix,s)=1 then
+ s:=copy(s,length(target_info.sharedlibprefix)+1,255);
+ i:=Pos(target_info.sharedlibext,S);
+ if i>0 then
+ Delete(S,i,255);
+ Add('-l'+s);
+ end;
+ Add(')');
+ end;
+
+ Add('SEARCH_DIR("/usr/i686-pc-cygwin/lib"); SEARCH_DIR("/usr/lib"); SEARCH_DIR("/usr/lib/w32api");');
+{$ifdef x86_64}
+ Add('OUTPUT_FORMAT(pei-x86-64)');
+{$else not 86_64}
+ Add('OUTPUT_FORMAT(pei-i386)');
+{$endif not x86_64}
+ Add('ENTRY(_mainCRTStartup)');
+ Add('SECTIONS');
+ Add('{');
+ Add(' . = SIZEOF_HEADERS;');
+ Add(' . = ALIGN(__section_alignment__);');
+ Add(' .text __image_base__ + ( __section_alignment__ < 0x1000 ? . : __section_alignment__ ) :');
+ Add(' {');
+ Add(' *(.init)');
+ add(' *(.text .stub .text.* .gnu.linkonce.t.*)');
+ Add(' *(SORT(.text$*))');
+ Add(' *(.glue_7t)');
+ Add(' *(.glue_7)');
+ Add(' . = ALIGN(8);');
+ Add(' ___CTOR_LIST__ = .; __CTOR_LIST__ = . ;');
+ Add(' LONG (-1);');
+{$ifdef x86_64}
+ Add(' LONG (-1);');
+{$endif x86_64}
+ Add(' *(.ctors); *(.ctor); *(SORT(.ctors.*)); LONG (0);');
+{$ifdef x86_64}
+ Add(' LONG (0);');
+{$endif x86_64}
+ Add(' ___DTOR_LIST__ = .; __DTOR_LIST__ = . ;');
+ Add(' LONG (-1);');
+{$ifdef x86_64}
+ Add(' LONG (-1);');
+{$endif x86_64}
+ Add(' *(.dtors); *(.dtor); *(SORT(.dtors.*)); LONG (0);');
+{$ifdef x86_64}
+ Add(' LONG (0);');
+{$endif x86_64}
+ Add(' *(.fini)');
+ Add(' PROVIDE (etext = .);');
+ Add(' *(.gcc_except_table)');
+ Add(' }');
+ Add(' .data BLOCK(__section_alignment__) :');
+ Add(' {');
+ Add(' __data_start__ = . ;');
+ add(' *(.data .data.* .gnu.linkonce.d.* .fpc*)');
+ Add(' *(.data2)');
+ Add(' *(SORT(.data$*))');
+ Add(' *(.jcr)');
+ Add(' PROVIDE ('+target_info.Cprefix+'_tls_index = .);');
+ Add(' LONG (0);');
+ Add(' __data_end__ = . ;');
+ Add(' *(.data_cygwin_nocopy)');
+ Add(' }');
+ Add(' .rdata BLOCK(__section_alignment__) :');
+ Add(' {');
+ Add(' *(.rdata)');
+ add(' *(.rodata .rodata.* .gnu.linkonce.r.*)');
+ Add(' *(SORT(.rdata$*))');
+ Add(' *(.eh_frame)');
+ Add(' ___RUNTIME_PSEUDO_RELOC_LIST__ = .;');
+ Add(' __RUNTIME_PSEUDO_RELOC_LIST__ = .;');
+ Add(' *(.rdata_runtime_pseudo_reloc)');
+ Add(' ___RUNTIME_PSEUDO_RELOC_LIST_END__ = .;');
+ Add(' __RUNTIME_PSEUDO_RELOC_LIST_END__ = .;');
+ Add(' }');
+ Add(' .pdata BLOCK(__section_alignment__) : { *(.pdata) }');
+ Add(' .bss BLOCK(__section_alignment__) :');
+ Add(' {');
+ Add(' __bss_start__ = . ;');
+ Add(' *(.bss .bss.* .gnu.linkonce.b.*)');
+ Add(' *(SORT(.bss$*))');
+ Add(' *(COMMON)');
+ Add(' __bss_end__ = . ;');
+ Add(' }');
+ Add(' .edata BLOCK(__section_alignment__) : { *(.edata) }');
+ Add(' .idata BLOCK(__section_alignment__) :');
+ Add(' {');
+ Add(' SORT(*)(.idata$2)');
+ Add(' SORT(*)(.idata$3)');
+ Add(' /* These zeroes mark the end of the import list. */');
+ Add(' LONG (0); LONG (0); LONG (0); LONG (0); LONG (0);');
+ Add(' SORT(*)(.idata$4)');
+ Add(' SORT(*)(.idata$5)');
+ Add(' SORT(*)(.idata$6)');
+ Add(' SORT(*)(.idata$7)');
+ Add(' }');
+ Add(' .CRT BLOCK(__section_alignment__) :');
+ Add(' {');
+ Add(' ___crt_xc_start__ = . ;');
+ Add(' *(SORT(.CRT$XC*)) /* C initialization */');
+ Add(' ___crt_xc_end__ = . ;');
+ Add(' ___crt_xi_start__ = . ;');
+ Add(' *(SORT(.CRT$XI*)) /* C++ initialization */');
+ Add(' ___crt_xi_end__ = . ;');
+ Add(' ___crt_xl_start__ = . ;');
+ Add(' *(SORT(.CRT$XL*)) /* TLS callbacks */');
+ Add(' /* ___crt_xl_end__ is defined in the TLS Directory support code */');
+ Add(' PROVIDE (___crt_xl_end__ = .);');
+ Add(' ___crt_xp_start__ = . ;');
+ Add(' *(SORT(.CRT$XP*)) /* Pre-termination */');
+ Add(' ___crt_xp_end__ = . ;');
+ Add(' ___crt_xt_start__ = . ;');
+ Add(' *(SORT(.CRT$XT*)) /* Termination */');
+ Add(' ___crt_xt_end__ = . ;');
+ Add(' }');
+ Add(' .tls BLOCK(__section_alignment__) :');
+ Add(' {');
+ Add(' ___tls_start__ = . ;');
+ Add(' *(.tls .tls.*)');
+ Add(' *(.tls$)');
+ Add(' *(SORT(.tls$*))');
+ Add(' ___tls_end__ = . ;');
+ Add(' }');
+ Add(' .rsrc BLOCK(__section_alignment__) :');
+ Add(' {');
+ Add(' *(.rsrc)');
+ Add(' *(SORT(.rsrc$*))');
+ Add(' }');
+ Add(' .reloc BLOCK(__section_alignment__) : { *(.reloc) }');
+ Add(' .stab BLOCK(__section_alignment__) (NOLOAD) : { *(.stab) }');
+ Add(' .stabstr BLOCK(__section_alignment__) (NOLOAD) : { *(.stabstr) }');
+ Add(' .debug_aranges BLOCK(__section_alignment__) (NOLOAD) : { *(.debug_aranges) }');
+ Add(' .debug_pubnames BLOCK(__section_alignment__) (NOLOAD) : { *(.debug_pubnames) }');
+ Add(' .debug_info BLOCK(__section_alignment__) (NOLOAD) : { *(.debug_info) *(.gnu.linkonce.wi.*) }');
+ Add(' .debug_abbrev BLOCK(__section_alignment__) (NOLOAD) : { *(.debug_abbrev) }');
+ Add(' .debug_line BLOCK(__section_alignment__) (NOLOAD) : { *(.debug_line) }');
+ Add(' .debug_frame BLOCK(__section_alignment__) (NOLOAD) : { *(.debug_frame) }');
+ Add(' .debug_str BLOCK(__section_alignment__) (NOLOAD) : { *(.debug_str) }');
+ Add(' .debug_loc BLOCK(__section_alignment__) (NOLOAD) : { *(.debug_loc) }');
+ Add(' .debug_macinfo BLOCK(__section_alignment__) (NOLOAD) : { *(.debug_macinfo) }');
+ Add(' .debug_weaknames BLOCK(__section_alignment__) (NOLOAD) : { *(.debug_weaknames) }');
+ Add(' .debug_funcnames BLOCK(__section_alignment__) (NOLOAD) : { *(.debug_funcnames) }');
+ Add(' .debug_typenames BLOCK(__section_alignment__) (NOLOAD) : { *(.debug_typenames) }');
+ Add(' .debug_varnames BLOCK(__section_alignment__) (NOLOAD) : { *(.debug_varnames) }');
+ Add(' .debug_ranges BLOCK(__section_alignment__) (NOLOAD) : { *(.debug_ranges) }');
+ Add('}');
+
+ { Write and Close response }
+ writetodisk;
+ Free;
+ end;
+
+ WriteResponseFile:=True;
+ end;
+
+
+ function TExternalLinkerWin.MakeExecutable:boolean;
+ var
+ MapStr,
+ binstr,
+ cmdstr : TCmdStr;
+ success : boolean;
+ cmds,i : longint;
+ AsBinStr : string[80];
+ GCSectionsStr,
+ StripStr,
+ RelocStr,
+ AppTypeStr,
+ EntryStr,
+ ImageBaseStr : string[40];
+ begin
+ if not(cs_link_nolink in current_settings.globalswitches) then
+ Message1(exec_i_linking,current_module.exefilename^);
+
+ { Create some replacements }
+ RelocStr:='';
+ AppTypeStr:='';
+ EntryStr:='';
+ ImageBaseStr:='';
+ StripStr:='';
+ MapStr:='';
+ GCSectionsStr:='';
+ AsBinStr:=FindUtil(utilsprefix+'as');
+ if RelocSection then
+ RelocStr:='--base-file base.$$$';
+ if create_smartlink_sections then
+ GCSectionsStr:='--gc-sections';
+ if target_info.system in systems_wince then
+ AppTypeStr:='--subsystem wince'
+ else
+ begin
+ if apptype=app_gui then
+ AppTypeStr:='--subsystem windows';
+ end;
+ if apptype=app_gui then
+ EntryStr:='--entry=_WinMainCRTStartup'
+ else
+ EntryStr:='--entry=_mainCRTStartup';
+ if ImageBaseSetExplicity then
+ ImageBaseStr:='--image-base=0x'+hexStr(imagebase, SizeOf(imagebase)*2);
+ if (cs_link_strip in current_settings.globalswitches) then
+ StripStr:='-s';
+ if (cs_link_map in current_settings.globalswitches) then
+ MapStr:='-Map '+maybequoted(ChangeFileExt(current_module.exefilename^,'.map'));
+
+ { Write used files and libraries }
+ WriteResponseFile(false);
+
+ { Call linker }
+ success:=false;
+ if RelocSection or (not Deffile.empty) then
+ cmds:=3
+ else
+ cmds:=1;
+ for i:=1 to cmds do
+ begin
+ SplitBinCmd(Info.ExeCmd[i],binstr,cmdstr);
+ if binstr<>'' then
+ begin
+ Replace(cmdstr,'$EXE',maybequoted(current_module.exefilename^));
+ Replace(cmdstr,'$OPT',Info.ExtraOptions);
+ Replace(cmdstr,'$RES',maybequoted(outputexedir+Info.ResName));
+ Replace(cmdstr,'$APPTYPE',AppTypeStr);
+ Replace(cmdstr,'$ENTRY',EntryStr);
+ Replace(cmdstr,'$ASBIN',AsbinStr);
+ Replace(cmdstr,'$RELOC',RelocStr);
+ Replace(cmdstr,'$IMAGEBASE',ImageBaseStr);
+ Replace(cmdstr,'$GCSECTIONS',GCSectionsStr);
+ Replace(cmdstr,'$STRIP',StripStr);
+ Replace(cmdstr,'$MAP',MapStr);
+ if not DefFile.Empty then
+ begin
+ DefFile.WriteFile;
+ Replace(cmdstr,'$DEF','-d '+maybequoted(deffile.fname));
+ end
+ else
+ Replace(cmdstr,'$DEF','');
+ success:=DoExec(FindUtil(utilsprefix+binstr),cmdstr,(i=1),false);
+ if not success then
+ break;
+ end;
+ end;
+
+ { Post process }
+ if success then
+ success:=PostProcessExecutable(current_module.exefilename^,false);
+
+ { Remove ReponseFile }
+ if (success) and not(cs_link_nolink in current_settings.globalswitches) then
+ begin
+ DeleteFile(outputexedir+Info.ResName);
+ DeleteFile('base.$$$');
+ DeleteFile('exp.$$$');
+ DeleteFile('deffile.$$$');
+ end;
+
+ MakeExecutable:=success; { otherwise a recursive call to link method }
+ end;
+
+
+ Function TExternalLinkerWin.MakeSharedLibrary:boolean;
+ var
+ MapStr,
+ binstr,
+ cmdstr : TCmdStr;
+ success : boolean;
+ cmds,
+ i : longint;
+ AsBinStr : string[80];
+ StripStr,
+ GCSectionsStr,
+ RelocStr,
+ AppTypeStr,
+ EntryStr,
+ ImageBaseStr : string[40];
+ begin
+ MakeSharedLibrary:=false;
+ if not(cs_link_nolink in current_settings.globalswitches) then
+ Message1(exec_i_linking,current_module.sharedlibfilename^);
+
+ { Create some replacements }
+ RelocStr:='';
+ AppTypeStr:='';
+ EntryStr:='';
+ ImageBaseStr:='';
+ StripStr:='';
+ MapStr:='';
+ GCSectionsStr:='';
+ AsBinStr:=FindUtil(utilsprefix+'as');
+ if RelocSection then
+ RelocStr:='--base-file base.$$$';
+ if create_smartlink_sections then
+ GCSectionsStr:='--gc-sections';
+ if apptype=app_gui then
+ begin
+ AppTypeStr:='--subsystem windows';
+ EntryStr:='--entry _DLLWinMainCRTStartup'
+ end
+ else
+ EntryStr:='--entry _DLLMainCRTStartup';
+ if ImageBaseSetExplicity then
+ ImageBaseStr:='--image-base=0x'+hexStr(imagebase, SizeOf(imagebase)*2);
+ if (cs_link_strip in current_settings.globalswitches) then
+ StripStr:='-s';
+ if (cs_link_map in current_settings.globalswitches) then
+ MapStr:='-Map '+maybequoted(ChangeFileExt(current_module.exefilename^,'.map'));
+
+ { Write used files and libraries }
+ WriteResponseFile(true);
+
+ { Call linker }
+ success:=false;
+ if RelocSection or (not Deffile.empty) then
+ cmds:=3
+ else
+ cmds:=1;
+ for i:=1 to cmds do
+ begin
+ SplitBinCmd(Info.DllCmd[i],binstr,cmdstr);
+ if binstr<>'' then
+ begin
+ Replace(cmdstr,'$EXE',maybequoted(current_module.sharedlibfilename^));
+ Replace(cmdstr,'$OPT',Info.ExtraOptions);
+ Replace(cmdstr,'$RES',maybequoted(outputexedir+Info.ResName));
+ Replace(cmdstr,'$APPTYPE',AppTypeStr);
+ Replace(cmdstr,'$ENTRY',EntryStr);
+ Replace(cmdstr,'$ASBIN',AsbinStr);
+ Replace(cmdstr,'$RELOC',RelocStr);
+ Replace(cmdstr,'$IMAGEBASE',ImageBaseStr);
+ Replace(cmdstr,'$STRIP',StripStr);
+ Replace(cmdstr,'$GCSECTIONS',GCSectionsStr);
+ Replace(cmdstr,'$MAP',MapStr);
+ if not DefFile.Empty then
+ begin
+ DefFile.WriteFile;
+ Replace(cmdstr,'$DEF','-d '+maybequoted(deffile.fname));
+ end
+ else
+ Replace(cmdstr,'$DEF','');
+ success:=DoExec(FindUtil(utilsprefix+binstr),cmdstr,(i=1),false);
+ if not success then
+ break;
+ end;
+ end;
+
+ { Post process }
+ if success then
+ success:=PostProcessExecutable(current_module.sharedlibfilename^,true);
+
+ { Remove ReponseFile }
+ if (success) and not(cs_link_nolink in current_settings.globalswitches) then
+ begin
+ DeleteFile(outputexedir+Info.ResName);
+ DeleteFile('base.$$$');
+ DeleteFile('exp.$$$');
+ DeleteFile('deffile.$$$');
+ end;
+ MakeSharedLibrary:=success; { otherwise a recursive call to link method }
+ end;
+
+
+ function TExternalLinkerWin.postprocessexecutable(const fn : string;isdll:boolean):boolean;
+ type
+ tdosheader = packed record
+ e_magic : word;
+ e_cblp : word;
+ e_cp : word;
+ e_crlc : word;
+ e_cparhdr : word;
+ e_minalloc : word;
+ e_maxalloc : word;
+ e_ss : word;
+ e_sp : word;
+ e_csum : word;
+ e_ip : word;
+ e_cs : word;
+ e_lfarlc : word;
+ e_ovno : word;
+ e_res : array[0..3] of word;
+ e_oemid : word;
+ e_oeminfo : word;
+ e_res2 : array[0..9] of word;
+ e_lfanew : longint;
+ end;
+ psecfill=^TSecfill;
+ TSecfill=record
+ fillpos,
+ fillsize : longint;
+ next : psecfill;
+ end;
+ var
+ f : file;
+ cmdstr : string;
+ dosheader : tdosheader;
+ peheader : tcoffheader;
+ peoptheader : tcoffpeoptheader;
+ firstsecpos,
+ maxfillsize,
+ l,peheaderpos : longint;
+ coffsec : tcoffsechdr;
+ secroot,hsecroot : psecfill;
+ zerobuf : pointer;
+ begin
+ postprocessexecutable:=false;
+ { when -s is used or it's a dll then quit }
+ if (cs_link_nolink in current_settings.globalswitches) then
+ begin
+ case apptype of
+ app_native :
+ cmdstr:='--subsystem native';
+ app_gui :
+ cmdstr:='--subsystem gui';
+ app_cui :
+ cmdstr:='--subsystem console';
+ end;
+ if dllversion<>'' then
+ cmdstr:=cmdstr+' --version '+dllversion;
+ cmdstr:=cmdstr+' --input '+maybequoted(fn);
+ cmdstr:=cmdstr+' --stack '+tostr(stacksize);
+ if target_info.system in [system_i386_win32, system_i386_wdosx] then
+ DoExec(FindUtil(utilsprefix+'postw32'),cmdstr,false,false);
+ postprocessexecutable:=true;
+ exit;
+ end;
+ { open file }
+ assign(f,fn);
+ {$push}{$I-}
+ reset(f,1);
+ if ioresult<>0 then
+ Message1(execinfo_f_cant_open_executable,fn);
+ { read headers }
+ blockread(f,dosheader,sizeof(tdosheader));
+ peheaderpos:=dosheader.e_lfanew;
+ { skip to headerpos and skip pe magic }
+ seek(f,peheaderpos+4);
+ blockread(f,peheader,sizeof(tcoffheader));
+ blockread(f,peoptheader,sizeof(tcoffpeoptheader));
+ { write info }
+ Message1(execinfo_x_codesize,tostr(peoptheader.tsize));
+ Message1(execinfo_x_initdatasize,tostr(peoptheader.dsize));
+ Message1(execinfo_x_uninitdatasize,tostr(peoptheader.bsize));
+ { change stack size (PM) }
+ { I am not sure that the default value is adequate !! }
+ peoptheader.SizeOfStackReserve:=stacksize;
+ if SetPEFlagsSetExplicity then
+ peoptheader.LoaderFlags:=peflags;
+ if ImageBaseSetExplicity then
+ peoptheader.ImageBase:=imagebase;
+ if MinStackSizeSetExplicity then
+ peoptheader.SizeOfStackCommit:=minstacksize;
+ if MaxStackSizeSetExplicity then
+ peoptheader.SizeOfStackReserve:=maxstacksize;
+ { change the header }
+ { sub system }
+ { gui=2 }
+ { cui=3 }
+ { wincegui=9 }
+ if target_info.system in systems_wince then
+ peoptheader.Subsystem:=9
+ else
+ case apptype of
+ app_native :
+ peoptheader.Subsystem:=1;
+ app_gui :
+ peoptheader.Subsystem:=2;
+ app_cui :
+ peoptheader.Subsystem:=3;
+ end;
+ if dllversion<>'' then
+ begin
+ peoptheader.MajorImageVersion:=dllmajor;
+ peoptheader.MinorImageVersion:=dllminor;
+ end;
+ { reset timestamp }
+ peheader.time:=0;
+ { write header back, skip pe magic }
+ seek(f,peheaderpos+4);
+ blockwrite(f,peheader,sizeof(tcoffheader));
+ if ioresult<>0 then
+ Message1(execinfo_f_cant_process_executable,fn);
+ blockwrite(f,peoptheader,sizeof(tcoffpeoptheader));
+ if ioresult<>0 then
+ Message1(execinfo_f_cant_process_executable,fn);
+ { skip to headerpos and skip pe magic }
+ seek(f,peheaderpos+4);
+ blockread(f,peheader,sizeof(tcoffheader));
+ blockread(f,peoptheader,sizeof(tcoffpeoptheader));
+ { write the value after the change }
+ Message1(execinfo_x_stackreserve,tostr(peoptheader.SizeOfStackReserve));
+ Message1(execinfo_x_stackcommit,tostr(peoptheader.SizeOfStackCommit));
+ { read section info }
+ maxfillsize:=0;
+ firstsecpos:=0;
+ secroot:=nil;
+ for l:=1 to peheader.nsects do
+ begin
+ blockread(f,coffsec,sizeof(tcoffsechdr));
+ if coffsec.datapos>0 then
+ begin
+ if secroot=nil then
+ firstsecpos:=coffsec.datapos;
+ new(hsecroot);
+ hsecroot^.fillpos:=coffsec.datapos+coffsec.vsize;
+ hsecroot^.fillsize:=coffsec.datasize-coffsec.vsize;
+ hsecroot^.next:=secroot;
+ secroot:=hsecroot;
+ if secroot^.fillsize>maxfillsize then
+ maxfillsize:=secroot^.fillsize;
+ end;
+ end;
+ if firstsecpos>0 then
+ begin
+ l:=firstsecpos-filepos(f);
+ if l>maxfillsize then
+ maxfillsize:=l;
+ end
+ else
+ l:=0;
+ { get zero buffer }
+ getmem(zerobuf,maxfillsize);
+ fillchar(zerobuf^,maxfillsize,0);
+ { zero from sectioninfo until first section }
+ blockwrite(f,zerobuf^,l);
+ { zero section alignments }
+ while assigned(secroot) do
+ begin
+ seek(f,secroot^.fillpos);
+ blockwrite(f,zerobuf^,secroot^.fillsize);
+ hsecroot:=secroot;
+ secroot:=secroot^.next;
+ dispose(hsecroot);
+ end;
+ freemem(zerobuf,maxfillsize);
+ close(f);
+ {$pop}
+ if ioresult<>0 then;
+ postprocessexecutable:=true;
+ end;
+
+
+ procedure TExternalLinkerWin.InitSysInitUnitName;
+ begin
+ if target_info.system=system_i386_win32 then
+ GlobalInitSysInitUnitName(self);
+ end;
+
+
+{****************************************************************************
+ TDLLScannerWin
+****************************************************************************}
+
+ procedure TDLLScannerWin.CheckDLLFunc(const dllname,funcname:string);
+ var
+ i : longint;
+ ExtName : string;
+ begin
+ for i:=0 to current_module.dllscannerinputlist.count-1 do
+ begin
+ ExtName:=current_module.dllscannerinputlist.NameOfIndex(i);
+ if (ExtName=funcname) then
+ begin
+ current_module.AddExternalImport(dllname,funcname,funcname,0,false,false);
+ importfound:=true;
+ current_module.dllscannerinputlist.Delete(i);
+ exit;
+ end;
+ end;
+ end;
+
+
+ function TDLLScannerWin.scan(const binname:string):boolean;
+ var
+ hs,
+ dllname : TCmdStr;
+ begin
+ result:=false;
+ { is there already an import library the we will use that one }
+ if FindLibraryFile(binname,target_info.staticClibprefix,target_info.staticClibext,hs) then
+ exit;
+ { check if we can find the dll }
+ hs:=binname;
+ if ExtractFileExt(hs)='' then
+ hs:=ChangeFileExt(hs,target_info.sharedlibext);
+ if not FindDll(hs,dllname) then
+ exit;
+ importfound:=false;
+ ReadDLLImports(dllname,@CheckDLLFunc);
+ if importfound then
+ current_module.dllscannerinputlist.Pack;
+ result:=importfound;
+ end;
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+initialization
+{$ifdef i386}
+ { Win32 }
+ RegisterExternalLinker(system_i386_win32_info,TExternalLinkerWin);
+ RegisterInternalLinker(system_i386_win32_info,TInternalLinkerWin);
+ RegisterImport(system_i386_win32,TImportLibWin);
+ RegisterExport(system_i386_win32,TExportLibWin);
+ RegisterDLLScanner(system_i386_win32,TDLLScannerWin);
+ RegisterRes(res_gnu_windres_info,TWinLikeResourceFile);
+ RegisterTarget(system_i386_win32_info);
+ { WinCE }
+ RegisterExternalLinker(system_i386_wince_info,TExternalLinkerWin);
+ RegisterInternalLinker(system_i386_wince_info,TInternalLinkerWin);
+ RegisterImport(system_i386_wince,TImportLibWin);
+ RegisterExport(system_i386_wince,TExportLibWin);
+ RegisterDLLScanner(system_i386_wince,TDLLScannerWin);
+ RegisterTarget(system_i386_wince_info);
+{$endif i386}
+{$ifdef x86_64}
+ RegisterExternalLinker(system_x64_win64_info,TExternalLinkerWin);
+ RegisterInternalLinker(system_x64_win64_info,TInternalLinkerWin);
+ RegisterImport(system_x86_64_win64,TImportLibWin);
+ RegisterExport(system_x86_64_win64,TExportLibWin);
+ RegisterDLLScanner(system_x86_64_win64,TDLLScannerWin);
+ RegisterRes(res_win64_gorc_info,TWinLikeResourceFile);
+ RegisterTarget(system_x64_win64_info);
+{$endif x86_64}
+{$ifdef arm}
+ RegisterExternalLinker(system_arm_wince_info,TExternalLinkerWin);
+ RegisterInternalLinker(system_arm_wince_info,TInternalLinkerWin);
+ RegisterImport(system_arm_wince,TImportLibWin);
+ RegisterExport(system_arm_wince,TExportLibWin);
+ RegisterRes(res_gnu_windres_info,TWinLikeResourceFile);
+ RegisterTarget(system_arm_wince_info);
+{$endif arm}
+end.
diff --git a/closures/compiler/tgobj.pas b/closures/compiler/tgobj.pas
new file mode 100644
index 0000000000..761d4f20c1
--- /dev/null
+++ b/closures/compiler/tgobj.pas
@@ -0,0 +1,663 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit implements the base object for temp. generator
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+{#@abstract(Temporary reference allocator unit)
+ Temporary reference allocator unit. This unit contains
+ all which is related to allocating temporary memory
+ space on the stack, as required, by the code generator.
+}
+
+unit tgobj;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ cclasses,
+ globals,globtype,
+ symtype,
+ cpubase,cpuinfo,cgbase,cgutils,
+ aasmbase,aasmtai,aasmdata;
+
+ type
+ ptemprecord = ^ttemprecord;
+ ttemprecord = record
+ temptype : ttemptype;
+ pos : longint;
+ size : longint;
+ def : tdef;
+ next : ptemprecord;
+ nextfree : ptemprecord; { for faster freeblock checking }
+{$ifdef EXTDEBUG}
+ posinfo,
+ releaseposinfo : tfileposinfo;
+{$endif}
+ end;
+
+
+ {# Generates temporary variables }
+ ttgobj = class
+ private
+ { contains all free temps using nextfree links }
+ tempfreelist : ptemprecord;
+ function alloctemp(list: TAsmList; size,alignment : longint; temptype : ttemptype; def:tdef) : longint;
+ procedure freetemp(list: TAsmList; pos:longint;temptypes:ttemptypeset);
+ public
+ { contains all temps }
+ templist : ptemprecord;
+ { Offsets of the first/last temp }
+ firsttemp,
+ lasttemp : longint;
+ direction : shortint;
+ constructor create;
+ {# Clear and free the complete linked list of temporary memory
+ locations. The list is set to nil.}
+ procedure resettempgen;
+ {# Sets the first offset from the frame pointer or stack pointer where
+ the temporary references will be allocated. It is to note that this
+ value should always be negative.
+
+ @param(l start offset where temps will start in stack)
+ }
+ procedure setfirsttemp(l : longint);
+
+ procedure gettemp(list: TAsmList; size, alignment : longint;temptype:ttemptype;out ref : treference);
+ procedure gettemptyped(list: TAsmList; def:tdef;temptype:ttemptype;out ref : treference);
+ procedure ungettemp(list: TAsmList; const ref : treference);
+
+ function sizeoftemp(list: TAsmList; const ref: treference): longint;
+ function changetemptype(list: TAsmList; const ref:treference;temptype:ttemptype):boolean;
+ function gettypeoftemp(const ref:treference): ttemptype;
+
+ {# Returns TRUE if the reference ref is allocated in temporary volatile memory space,
+ otherwise returns FALSE.
+
+ @param(ref reference to verify)
+ }
+ function istemp(const ref : treference) : boolean;
+ {# Frees a reference @var(ref) which was allocated in the volatile temporary memory space.
+ The freed space can later be reallocated and reused. If this reference
+ is not in the temporary memory, it is simply not freed.
+ }
+ procedure ungetiftemp(list: TAsmList; const ref : treference);
+
+ { Allocate space for a local }
+ procedure getlocal(list: TAsmList; size : longint;def:tdef;var ref : treference);
+ procedure getlocal(list: TAsmList; size : longint; alignment : shortint; def:tdef;var ref : treference);
+ procedure UnGetLocal(list: TAsmList; const ref : treference);
+ end;
+
+ var
+ tg: ttgobj;
+
+ procedure location_freetemp(list:TAsmList; const l : tlocation);
+
+
+implementation
+
+ uses
+ cutils,
+ systems,verbose,
+ procinfo,
+ symconst
+ ;
+
+
+ const
+ FreeTempTypes = [tt_free,tt_freenoreuse];
+
+{$ifdef EXTDEBUG}
+ TempTypeStr : array[ttemptype] of string[18] = (
+ '<none>',
+ 'free','normal','persistant',
+ 'noreuse','freenoreuse'
+ );
+{$endif EXTDEBUG}
+
+ Used2Free : array[ttemptype] of ttemptype = (
+ tt_none,
+ tt_none,tt_free,tt_free,
+ tt_freenoreuse,tt_none
+ );
+
+
+{*****************************************************************************
+ Helpers
+*****************************************************************************}
+
+ procedure location_freetemp(list:TAsmList; const l : tlocation);
+ begin
+ if (l.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
+ tg.ungetiftemp(list,l.reference);
+ end;
+
+
+{*****************************************************************************
+ TTGOBJ
+*****************************************************************************}
+
+ constructor ttgobj.create;
+
+ begin
+ tempfreelist:=nil;
+ templist:=nil;
+ { we could create a new child class for this but I don't if it is worth the effort (FK) }
+{$if defined(powerpc) or defined(powerpc64) or defined(avr)}
+ direction:=1;
+{$else}
+ direction:=-1;
+{$endif}
+ end;
+
+
+ procedure ttgobj.resettempgen;
+ var
+ hp : ptemprecord;
+ begin
+ { Clear the old templist }
+ while assigned(templist) do
+ begin
+{$ifdef EXTDEBUG}
+ if not(templist^.temptype in FreeTempTypes) then
+ begin
+ Comment(V_Warning,'tgobj: (ResetTempgen) temp at pos '+tostr(templist^.pos)+
+ ' with size '+tostr(templist^.size)+' and type '+TempTypeStr[templist^.temptype]+
+ ' from pos '+tostr(templist^.posinfo.line)+':'+tostr(templist^.posinfo.column)+
+ ' not freed at the end of the procedure');
+ end;
+{$endif EXTDEBUG}
+ hp:=templist;
+ templist:=hp^.next;
+ dispose(hp);
+ end;
+ templist:=nil;
+ tempfreelist:=nil;
+ firsttemp:=0;
+ lasttemp:=0;
+ end;
+
+
+ procedure ttgobj.setfirsttemp(l : longint);
+ begin
+ { this is a negative value normally }
+ if l*direction>=0 then
+ begin
+ if odd(l) then
+ inc(l,direction);
+ end
+ else
+ internalerror(200204221);
+ firsttemp:=l;
+ lasttemp:=l;
+ end;
+
+
+ function ttgobj.AllocTemp(list: TAsmList; size,alignment : longint; temptype : ttemptype;def : tdef) : longint;
+ var
+ tl,htl,
+ bestslot,bestprev,
+ hprev,hp : ptemprecord;
+ freetype : ttemptype;
+ bestatend,
+ fitatbegin,
+ fitatend : boolean;
+ begin
+ AllocTemp:=0;
+ bestprev:=nil;
+ bestslot:=nil;
+ tl:=nil;
+ bestatend:=false;
+
+ if size=0 then
+ begin
+{$ifdef EXTDEBUG}
+ Comment(V_Warning,'tgobj: (AllocTemp) temp of size 0 requested, allocating 4 bytes');
+{$endif}
+ size:=4;
+ end;
+
+ freetype:=Used2Free[temptype];
+ if freetype=tt_none then
+ internalerror(200208201);
+ size:=align(size,alignment);
+ { First check the tmpfreelist, but not when
+ we don't want to reuse an already allocated block }
+ if assigned(tempfreelist) and
+ (temptype<>tt_noreuse) then
+ begin
+ hprev:=nil;
+ hp:=tempfreelist;
+ while assigned(hp) do
+ begin
+{$ifdef EXTDEBUG}
+ if not(hp^.temptype in FreeTempTypes) then
+ Comment(V_Warning,'tgobj: (AllocTemp) temp at pos '+tostr(hp^.pos)+ ' in freelist is not set to tt_free !');
+{$endif}
+ { Check only slots that are
+ - free
+ - share the same type
+ - contain enough space
+ - has a correct alignment }
+ if (hp^.temptype=freetype) and
+ (hp^.def=def) and
+ (hp^.size>=size) and
+ ((hp^.pos=align(hp^.pos,alignment)) or
+ (hp^.pos+hp^.size-size = align(hp^.pos+hp^.size-size,alignment))) then
+ begin
+ { Slot is the same size then leave immediatly }
+ if (hp^.size=size) then
+ begin
+ bestprev:=hprev;
+ bestslot:=hp;
+ break;
+ end
+ else
+ begin
+ { we can fit a smaller block either at the begin or at }
+ { the end of a block. For direction=-1 we prefer the }
+ { end, for direction=1 we prefer the begin (i.e., }
+ { always closest to the source). We also try to use }
+ { the block with the worst possible alignment that }
+ { still suffices. And we pick the block which will }
+ { have the best alignmenment after this new block is }
+ { substracted from it. }
+ fitatend:=(hp^.pos+hp^.size-size)=align(hp^.pos+hp^.size-size,alignment);
+ fitatbegin:=hp^.pos=align(hp^.pos,alignment);
+ if assigned(bestslot) then
+ begin
+ fitatend:=fitatend and
+ ((not bestatend and
+ (direction=-1)) or
+ (bestatend and
+ isbetteralignedthan(abs(bestslot^.pos+hp^.size-size),abs(hp^.pos+hp^.size-size),current_settings.alignment.localalignmax)));
+ fitatbegin:=fitatbegin and
+ (not bestatend or
+ (direction=1)) and
+ isbetteralignedthan(abs(hp^.pos+size),abs(bestslot^.pos+size),current_settings.alignment.localalignmax);
+ end;
+ if fitatend and
+ fitatbegin then
+ if isbetteralignedthan(abs(hp^.pos+hp^.size-size),abs(hp^.pos+size),current_settings.alignment.localalignmax) then
+ fitatbegin:=false
+ else if isbetteralignedthan(abs(hp^.pos+size),abs(hp^.pos+hp^.size-size),current_settings.alignment.localalignmax) then
+ fitatend:=false
+ else if (direction=1) then
+ fitatend:=false
+ else
+ fitatbegin:=false;
+ if fitatend or
+ fitatbegin then
+ begin
+ bestprev:=hprev;
+ bestslot:=hp;
+ bestatend:=fitatend;
+ end;
+ end;
+ end;
+ hprev:=hp;
+ hp:=hp^.nextfree;
+ end;
+ end;
+ { Reuse an old temp ? }
+ if assigned(bestslot) then
+ begin
+ if bestslot^.size=size then
+ begin
+ tl:=bestslot;
+ { Remove from the tempfreelist }
+ if assigned(bestprev) then
+ bestprev^.nextfree:=tl^.nextfree
+ else
+ tempfreelist:=tl^.nextfree;
+ end
+ else
+ begin
+ { Duplicate bestlost and the block in the list }
+ new(tl);
+ move(bestslot^,tl^,sizeof(ttemprecord));
+ tl^.next:=bestslot^.next;
+ bestslot^.next:=tl;
+ { Now we split the block in 2 parts. Depending on the direction
+ we need to resize the newly inserted block or the old reused block.
+ For direction=1 we can use tl for the new block. For direction=-1 we
+ will be reusing bestslot and resize the new block, that means we need
+ to swap the pointers }
+ if (direction=-1) xor
+ bestatend then
+ begin
+ htl:=tl;
+ tl:=bestslot;
+ bestslot:=htl;
+ { Update the tempfreelist to point to the new block }
+ if assigned(bestprev) then
+ bestprev^.nextfree:=bestslot
+ else
+ tempfreelist:=bestslot;
+ end;
+
+ if not bestatend then
+ inc(bestslot^.pos,size)
+ else
+ inc(tl^.pos,tl^.size-size);
+
+ { Create new block and resize the old block }
+ tl^.size:=size;
+ tl^.nextfree:=nil;
+ { Resize the old block }
+ dec(bestslot^.size,size);
+ end;
+ tl^.temptype:=temptype;
+ tl^.def:=def;
+ tl^.nextfree:=nil;
+ end
+ else
+ begin
+ { now we can create the templist entry }
+ new(tl);
+ tl^.temptype:=temptype;
+ tl^.def:=def;
+
+ { Extend the temp }
+ if direction=-1 then
+ begin
+ lasttemp:=(-align(-lasttemp,alignment))-size;
+ tl^.pos:=lasttemp;
+ end
+ else
+ begin
+ tl^.pos:=align(lasttemp,alignment);
+ lasttemp:=tl^.pos+size;
+ end;
+
+ tl^.size:=size;
+ tl^.next:=templist;
+ tl^.nextfree:=nil;
+ templist:=tl;
+ end;
+{$ifdef EXTDEBUG}
+ tl^.posinfo:=current_filepos;
+ if assigned(tl^.def) then
+ list.concat(tai_tempalloc.allocinfo(tl^.pos,tl^.size,'allocated with type '+TempTypeStr[tl^.temptype]+' for def '+tl^.def.typename))
+ else
+ list.concat(tai_tempalloc.allocinfo(tl^.pos,tl^.size,'allocated with type '+TempTypeStr[tl^.temptype]));
+{$else}
+ list.concat(tai_tempalloc.alloc(tl^.pos,tl^.size));
+{$endif}
+ AllocTemp:=tl^.pos;
+ end;
+
+
+ procedure ttgobj.FreeTemp(list: TAsmList; pos:longint;temptypes:ttemptypeset);
+ var
+ hp,hnext,hprev,hprevfree : ptemprecord;
+ begin
+ hp:=templist;
+ hprev:=nil;
+ hprevfree:=nil;
+ while assigned(hp) do
+ begin
+ if (hp^.pos=pos) then
+ begin
+ { check if already freed }
+ if hp^.temptype in FreeTempTypes then
+ begin
+{$ifdef EXTDEBUG}
+ Comment(V_Warning,'tgobj: (FreeTemp) temp at pos '+tostr(pos)+ ' is already free !');
+ list.concat(tai_tempalloc.allocinfo(hp^.pos,hp^.size,'temp is already freed'));
+{$endif}
+ exit;
+ end;
+ { check type that are allowed to be released }
+ if not(hp^.temptype in temptypes) then
+ begin
+{$ifdef EXTDEBUG}
+ Comment(V_Debug,'tgobj: (Freetemp) temp at pos '+tostr(pos)+ ' has different type ('+TempTypeStr[hp^.temptype]+'), not releasing');
+ list.concat(tai_tempalloc.allocinfo(hp^.pos,hp^.size,'temp has wrong type ('+TempTypeStr[hp^.temptype]+') not releasing'));
+{$endif}
+ exit;
+ end;
+ list.concat(tai_tempalloc.dealloc(hp^.pos,hp^.size));
+ { set this block to free }
+ hp^.temptype:=Used2Free[hp^.temptype];
+ { Update tempfreelist }
+ if assigned(hprevfree) then
+ begin
+ { Concat blocks when the previous block is free and
+ there is no block assigned for a tdef }
+ if assigned(hprev) and
+ (hp^.temptype=tt_free) and
+ not assigned(hp^.def) and
+ (hprev^.temptype=tt_free) and
+ not assigned(hprev^.def) then
+ begin
+ inc(hprev^.size,hp^.size);
+ if direction=1 then
+ hprev^.pos:=hp^.pos;
+ hprev^.next:=hp^.next;
+ dispose(hp);
+ hp:=hprev;
+ end
+ else
+ hprevfree^.nextfree:=hp;
+ end
+ else
+ begin
+ hp^.nextfree:=tempfreelist;
+ tempfreelist:=hp;
+ end;
+ { Concat blocks when the next block is free and
+ there is no block assigned for a tdef }
+ hnext:=hp^.next;
+ if assigned(hnext) and
+ (hp^.temptype=tt_free) and
+ not assigned(hp^.def) and
+ (hnext^.temptype=tt_free) and
+ not assigned(hnext^.def) then
+ begin
+ inc(hp^.size,hnext^.size);
+ if direction=1 then
+ hp^.pos:=hnext^.pos;
+ hp^.nextfree:=hnext^.nextfree;
+ hp^.next:=hnext^.next;
+ dispose(hnext);
+ end;
+ { Stop }
+ exit;
+ end;
+ if (hp^.temptype=tt_free) then
+ hprevfree:=hp;
+ hprev:=hp;
+ hp:=hp^.next;
+ end;
+ end;
+
+
+ procedure ttgobj.gettemp(list: TAsmList; size, alignment : longint;temptype:ttemptype;out ref : treference);
+ var
+ varalign : shortint;
+ begin
+ varalign:=used_align(alignment,current_settings.alignment.localalignmin,current_settings.alignment.localalignmax);
+ { can't use reference_reset_base, because that will let tgobj depend
+ on cgobj (PFV) }
+ fillchar(ref,sizeof(ref),0);
+ ref.base:=current_procinfo.framepointer;
+ ref.offset:=alloctemp(list,size,varalign,temptype,nil);
+ ref.alignment:=varalign;
+ end;
+
+
+ procedure ttgobj.gettemptyped(list: TAsmList; def:tdef;temptype:ttemptype;out ref : treference);
+ var
+ varalign : shortint;
+ begin
+ varalign:=def.alignment;
+ varalign:=used_align(varalign,current_settings.alignment.localalignmin,current_settings.alignment.localalignmax);
+ { can't use reference_reset_base, because that will let tgobj depend
+ on cgobj (PFV) }
+ fillchar(ref,sizeof(ref),0);
+ ref.base:=current_procinfo.framepointer;
+ ref.offset:=alloctemp(list,def.size,varalign,temptype,def);
+ ref.alignment:=varalign;
+ end;
+
+
+ function ttgobj.istemp(const ref : treference) : boolean;
+ begin
+ { ref.index = R_NO was missing
+ led to problems with local arrays
+ with lower bound > 0 (PM) }
+ if direction = 1 then
+ begin
+ istemp:=(ref.base=current_procinfo.framepointer) and
+ (ref.index=NR_NO) and
+ (ref.offset>=firsttemp);
+ end
+ else
+ begin
+ istemp:=(ref.base=current_procinfo.framepointer) and
+ (ref.index=NR_NO) and
+ (ref.offset<firsttemp);
+ end;
+ end;
+
+
+ function ttgobj.sizeoftemp(list: TAsmList; const ref: treference): longint;
+ var
+ hp : ptemprecord;
+ begin
+ SizeOfTemp := -1;
+ hp:=templist;
+ while assigned(hp) do
+ begin
+ if (hp^.pos=ref.offset) then
+ begin
+ sizeoftemp := hp^.size;
+ exit;
+ end;
+ hp := hp^.next;
+ end;
+{$ifdef EXTDEBUG}
+ comment(v_debug,'tgobj: (SizeOfTemp) temp at pos '+tostr(ref.offset)+' not found !');
+ list.concat(tai_tempalloc.allocinfo(ref.offset,0,'temp not found'));
+{$endif}
+ end;
+
+
+ function ttgobj.changetemptype(list: tasmList; const ref:treference; temptype:ttemptype):boolean;
+ var
+ hp : ptemprecord;
+ begin
+ ChangeTempType:=false;
+ hp:=templist;
+ while assigned(hp) do
+ begin
+ if (hp^.pos=ref.offset) then
+ begin
+ if hp^.temptype<>tt_free then
+ begin
+{$ifdef EXTDEBUG}
+ if hp^.temptype=temptype then
+ Comment(V_Warning,'tgobj: (ChangeTempType) temp'+
+ ' at pos '+tostr(ref.offset)+ ' is already of the correct type !');
+ list.concat(tai_tempalloc.allocinfo(hp^.pos,hp^.size,'type changed to '+TempTypeStr[temptype]));
+{$endif}
+ ChangeTempType:=true;
+ hp^.temptype:=temptype;
+ end
+ else
+ begin
+{$ifdef EXTDEBUG}
+ Comment(V_Warning,'tgobj: (ChangeTempType) temp'+
+ ' at pos '+tostr(ref.offset)+ ' is already freed !');
+ list.concat(tai_tempalloc.allocinfo(hp^.pos,hp^.size,'temp is already freed'));
+{$endif}
+ end;
+ exit;
+ end;
+ hp:=hp^.next;
+ end;
+{$ifdef EXTDEBUG}
+ Comment(V_Warning,'tgobj: (ChangeTempType) temp'+
+ ' at pos '+tostr(ref.offset)+ ' not found !');
+ list.concat(tai_tempalloc.allocinfo(ref.offset,0,'temp not found'));
+{$endif}
+ end;
+
+
+ function ttgobj.gettypeoftemp(const ref:treference): ttemptype;
+ var
+ hp : ptemprecord;
+ begin
+ hp:=templist;
+ while assigned(hp) do
+ begin
+ if (hp^.pos=ref.offset) then
+ begin
+ if hp^.temptype<>tt_free then
+ result:=hp^.temptype
+ else
+ internalerror(2007020810);
+ exit;
+ end;
+ hp:=hp^.next;
+ end;
+ result:=tt_none;
+ end;
+
+
+ procedure ttgobj.UnGetTemp(list: TAsmList; const ref : treference);
+ begin
+ FreeTemp(list,ref.offset,[tt_normal,tt_noreuse,tt_persistent]);
+ end;
+
+
+ procedure ttgobj.UnGetIfTemp(list: TAsmList; const ref : treference);
+ begin
+ if istemp(ref) then
+ FreeTemp(list,ref.offset,[tt_normal]);
+ end;
+
+
+ procedure ttgobj.getlocal(list: TAsmList; size : longint;def:tdef;var ref : treference);
+ begin
+ getlocal(list, size, def.alignment, def, ref);
+ end;
+
+
+ procedure ttgobj.getlocal(list: TAsmList; size : longint; alignment : shortint; def:tdef;var ref : treference);
+ begin
+ alignment:=used_align(alignment,current_settings.alignment.localalignmin,current_settings.alignment.localalignmax);
+ { can't use reference_reset_base, because that will let tgobj depend
+ on cgobj (PFV) }
+ fillchar(ref,sizeof(ref),0);
+ ref.base:=current_procinfo.framepointer;
+ ref.offset:=alloctemp(list,size,alignment,tt_persistent,nil);
+ ref.alignment:=alignment;
+ end;
+
+
+ procedure ttgobj.UnGetLocal(list: TAsmList; const ref : treference);
+ begin
+ FreeTemp(list,ref.offset,[tt_persistent]);
+ end;
+
+end.
diff --git a/closures/compiler/tokens.pas b/closures/compiler/tokens.pas
new file mode 100644
index 0000000000..404e20602d
--- /dev/null
+++ b/closures/compiler/tokens.pas
@@ -0,0 +1,651 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl, Pierre Muller
+
+ Tokens used by the compiler
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ ****************************************************************************
+}
+unit tokens;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ globtype;
+
+type
+ ttoken=(NOTOKEN,
+ { operators, which can also be overloaded }
+ _PLUS,
+ _MINUS,
+ _STAR,
+ _SLASH,
+ _EQ,
+ _GT,
+ _LT,
+ _GTE,
+ _LTE,
+ _NE,
+ _SYMDIF,
+ _STARSTAR,
+ _OP_AS,
+ _OP_IN,
+ _OP_IS,
+ _OP_OR,
+ _OP_AND,
+ _OP_DIV,
+ _OP_MOD,
+ _OP_NOT,
+ _OP_SHL,
+ _OP_SHR,
+ _OP_XOR,
+ _ASSIGNMENT,
+ _OP_EXPLICIT,
+ _OP_ENUMERATOR,
+ _OP_INC,
+ _OP_DEC,
+ { special chars }
+ _CARET,
+ _LECKKLAMMER,
+ _RECKKLAMMER,
+ _POINT,
+ _COMMA,
+ _LKLAMMER,
+ _RKLAMMER,
+ _COLON,
+ _SEMICOLON,
+ _KLAMMERAFFE,
+ _POINTPOINT,
+ _POINTPOINTPOINT,
+ _PIPE,
+ _AMPERSAND,
+ _EOF,
+ _ID,
+ _NOID,
+ _REALNUMBER,
+ _INTCONST,
+ _CSTRING,
+ _CCHAR,
+ _CWSTRING,
+ _CWCHAR,
+ _LSHARPBRACKET,
+ _RSHARPBRACKET,
+ { C like operators }
+ _PLUSASN,
+ _MINUSASN,
+ _ANDASN,
+ _ORASN,
+ _STARASN,
+ _SLASHASN,
+ _MODASN,
+ _DIVASN,
+ _NOTASN,
+ _XORASN,
+ _GENERICSPECIALTOKEN,
+ { Normal words -- ATTENTION: These words must be sorted: }
+ { first in length order, then in alphabetical order. }
+ _C,
+ _AS,
+ _AT,
+ _DO,
+ _IF,
+ _IN,
+ _IS,
+ _OF,
+ _ON,
+ _OR,
+ _TO,
+ _ADD,
+ _AND,
+ _ASM,
+ _DEC,
+ _DIV,
+ _END,
+ _FAR,
+ _FOR,
+ _INC,
+ _MOD,
+ _NIL,
+ _NOT,
+ _OUT,
+ _SET,
+ _SHL,
+ _SHR,
+ _TRY,
+ _VAR,
+ _XOR,
+ _CASE,
+ _CVAR,
+ _ELSE,
+ _EXIT,
+ _FAIL,
+ _FILE,
+ _GOTO,
+ _NAME,
+ _NEAR,
+ _READ,
+ _SELF,
+ _SYSV,
+ _THEN,
+ _TRUE,
+ _TYPE,
+ _UNIT,
+ _UNIV,
+ _USES,
+ _WITH,
+ _ALIAS,
+ _ARRAY,
+ _BEGIN,
+ _BREAK,
+ _CDECL,
+ _CLASS,
+ _CONST,
+ _EQUAL,
+ _FALSE,
+ _FAR16,
+ _FINAL,
+ _INDEX,
+ _LABEL,
+ _LOCAL,
+ _RAISE,
+ _UNTIL,
+ _WHILE,
+ _WRITE,
+ _DISPID,
+ _DIVIDE,
+ _DOWNTO,
+ _EXCEPT,
+ _EXPORT,
+ _HELPER,
+ _INLINE,
+ _LEGACY,
+ _NESTED,
+ _OBJECT,
+ _PACKED,
+ _PASCAL,
+ _PUBLIC,
+ _RECORD,
+ _REPEAT,
+ _RESULT,
+ _RETURN,
+ _SEALED,
+ _STATIC,
+ _STORED,
+ _STRICT,
+ _STRING,
+ _SYSTEM,
+ _ASMNAME,
+ _CPPDECL,
+ _DEFAULT,
+ _DYNAMIC,
+ _EXPORTS,
+ _FINALLY,
+ _FORWARD,
+ _GENERIC,
+ _IOCHECK,
+ _LIBRARY,
+ _MESSAGE,
+ _MODULUS,
+ _PACKAGE,
+ _PRIVATE,
+ _PROGRAM,
+ _R12BASE,
+ _RTLPROC,
+ _SECTION,
+ _STDCALL,
+ _SYSCALL,
+ _VARARGS,
+ _VIRTUAL,
+ _ABSOLUTE,
+ _ABSTRACT,
+ _BASESYSV,
+ _CONSTREF,
+ _CONTAINS,
+ _CONTINUE,
+ _CPPCLASS,
+ _EXPLICIT,
+ _EXTERNAL,
+ _FUNCTION,
+ _IMPLICIT,
+ _LESSTHAN,
+ _LOCATION,
+ _MULTIPLY,
+ _MWPASCAL,
+ _NEGATIVE,
+ _NOTEQUAL,
+ _OPERATOR,
+ _OPTIONAL,
+ _OVERLOAD,
+ _OVERRIDE,
+ _PLATFORM,
+ _POSITIVE,
+ _PROPERTY,
+ _READONLY,
+ _REGISTER,
+ _REQUIRED,
+ _REQUIRES,
+ _RESIDENT,
+ _SAFECALL,
+ _SUBTRACT,
+ _SYSVBASE,
+ _ASSEMBLER,
+ _BITPACKED,
+ _BITWISEOR,
+ _INHERITED,
+ _INTDIVIDE,
+ _INTERFACE,
+ _INTERRUPT,
+ _LEFTSHIFT,
+ _LOGICALOR,
+ _NODEFAULT,
+ _OBJCCLASS,
+ _OTHERWISE,
+ _PROCEDURE,
+ _PROTECTED,
+ _PUBLISHED,
+ _SOFTFLOAT,
+ _THREADVAR,
+ _WRITEONLY,
+ _BITWISEAND,
+ _BITWISEXOR,
+ _DEPRECATED,
+ _DESTRUCTOR,
+ _ENUMERATOR,
+ _IMPLEMENTS,
+ _INTERNPROC,
+ _LOGICALAND,
+ _LOGICALNOT,
+ _LOGICALXOR,
+ _OLDFPCCALL,
+ _OPENSTRING,
+ _RIGHTSHIFT,
+ _SPECIALIZE,
+ _CONSTRUCTOR,
+ _GREATERTHAN,
+ _INTERNCONST,
+ _REINTRODUCE,
+ _SHORTSTRING,
+ _COMPILERPROC,
+ _EXPERIMENTAL,
+ _FINALIZATION,
+ _NOSTACKFRAME,
+ _OBJCCATEGORY,
+ _OBJCPROTOCOL,
+ _WEAKEXTERNAL,
+ _DISPINTERFACE,
+ _UNIMPLEMENTED,
+ _IMPLEMENTATION,
+ _INITIALIZATION,
+ _RESOURCESTRING,
+ _LESSTHANOREQUAL,
+ _GREATERTHANOREQUAL
+ );
+
+const
+ tokenlenmin = 1;
+ tokenlenmax = 18;
+
+ { last operator which can be overloaded, the first_overloaded should
+ be declared directly after NOTOKEN }
+ first_overloaded = succ(NOTOKEN);
+ last_overloaded = _OP_DEC;
+ last_operator = _GENERICSPECIALTOKEN;
+
+type
+ tokenrec=record
+ str : string[tokenlenmax];
+ special : boolean;
+ keyword : tmodeswitch;
+ op : ttoken;
+ end;
+
+ ttokenarray=array[ttoken] of tokenrec;
+ ptokenarray=^ttokenarray;
+
+ tokenidxrec=record
+ first,last : ttoken;
+ end;
+
+ ptokenidx=^ttokenidx;
+ ttokenidx=array[tokenlenmin..tokenlenmax,'A'..'Z'] of tokenidxrec;
+
+const
+ arraytokeninfo : ttokenarray =(
+ (str:'' ;special:true ;keyword:m_none;op:NOTOKEN),
+ { Operators which can be overloaded }
+ (str:'+' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'-' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'*' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'/' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'=' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'>' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'<' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'>=' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'<=' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'<>' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'><' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'**' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'as' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'in' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'is' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'or' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'and' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'div' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'mod' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'not' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'shl' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'shr' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'xor' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:':=' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'explicit' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'enumerator' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'inc' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'dec' ;special:true ;keyword:m_none;op:NOTOKEN),
+ { Special chars }
+ (str:'^' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'[' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:']' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'.' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:',' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'(' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:')' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:':' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:';' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'@' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'..' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'...' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'|' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'&' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'end of file' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'identifier' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'non identifier';special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'const real' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'ordinal const' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'const string' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'const char' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'const wstring' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'const wchar' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'<' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'>' ;special:true ;keyword:m_none;op:NOTOKEN),
+ { C like operators }
+ (str:'+=' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'-=' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'&=' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'|=' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'*=' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'/=' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'' ;special:true ;keyword:m_none;op:NOTOKEN),
+ (str:'gen. spec.' ;special:true ;keyword:m_none;op:NOTOKEN),
+ { Normal words -- ATTENTION: These words must be sorted: }
+ { first in length order, then in alphabetical order. }
+ (str:'C' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'AS' ;special:false;keyword:m_class;op:_OP_AS),
+ (str:'AT' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'DO' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'IF' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'IN' ;special:false;keyword:m_all;op:_OP_IN),
+ (str:'IS' ;special:false;keyword:m_class;op:_OP_IS),
+ (str:'OF' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'ON' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'OR' ;special:false;keyword:m_all;op:_OP_OR),
+ (str:'TO' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'ADD' ;special:false;keyword:m_none;op:NOTOKEN), { delphi operator name }
+ (str:'AND' ;special:false;keyword:m_all;op:_OP_AND),
+ (str:'ASM' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'DEC' ;special:false;keyword:m_none;op:NOTOKEN), { delphi operator name }
+ (str:'DIV' ;special:false;keyword:m_all;op:_OP_DIV),
+ (str:'END' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'FAR' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'FOR' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'INC' ;special:false;keyword:m_none;op:NOTOKEN), { delphi operator name }
+ (str:'MOD' ;special:false;keyword:m_all;op:_OP_MOD),
+ (str:'NIL' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'NOT' ;special:false;keyword:m_all;op:_OP_NOT),
+ (str:'OUT' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'SET' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'SHL' ;special:false;keyword:m_all;op:_OP_SHL),
+ (str:'SHR' ;special:false;keyword:m_all;op:_OP_SHR),
+ (str:'TRY' ;special:false;keyword:m_except;op:NOTOKEN),
+ (str:'VAR' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'XOR' ;special:false;keyword:m_all;op:_OP_XOR),
+ (str:'CASE' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'CVAR' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'ELSE' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'EXIT' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'FAIL' ;special:false;keyword:m_none;op:NOTOKEN), { only set within constructors PM }
+ (str:'FILE' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'GOTO' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'NAME' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'NEAR' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'READ' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'SELF' ;special:false;keyword:m_none;op:NOTOKEN), {set inside methods only PM }
+ (str:'SYSV' ;special:false;keyword:m_none;op:NOTOKEN), { Syscall variation on MorphOS }
+ (str:'THEN' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'TRUE' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'TYPE' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'UNIT' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'UNIV' ;special:false;keyword:m_mac;op:NOTOKEN),
+ (str:'USES' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'WITH' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'ALIAS' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'ARRAY' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'BEGIN' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'BREAK' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'CDECL' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'CLASS' ;special:false;keyword:m_class;op:NOTOKEN),
+ (str:'CONST' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'EQUAL' ;special:false;keyword:m_none;op:NOTOKEN), { delphi operator name }
+ (str:'FALSE' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'FAR16' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'FINAL' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'INDEX' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'LABEL' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'LOCAL' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'RAISE' ;special:false;keyword:m_except;op:NOTOKEN),
+ (str:'UNTIL' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'WHILE' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'WRITE' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'DISPID' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'DIVIDE' ;special:false;keyword:m_none;op:NOTOKEN), { delphi operator name }
+ (str:'DOWNTO' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'EXCEPT' ;special:false;keyword:m_except;op:NOTOKEN),
+ (str:'EXPORT' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'HELPER' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'INLINE' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'LEGACY' ;special:false;keyword:m_none;op:NOTOKEN), { Syscall variation on MorphOS }
+ (str:'NESTED' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'OBJECT' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'PACKED' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'PASCAL' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'PUBLIC' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'RECORD' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'REPEAT' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'RESULT' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'RETURN' ;special:false;keyword:m_mac;op:NOTOKEN),
+ (str:'SEALED' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'STATIC' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'STORED' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'STRICT' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'STRING' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'SYSTEM' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'ASMNAME' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'CPPDECL' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'DEFAULT' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'DYNAMIC' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'EXPORTS' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'FINALLY' ;special:false;keyword:m_except;op:NOTOKEN),
+ (str:'FORWARD' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'GENERIC' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'IOCHECK' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'LIBRARY' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'MESSAGE' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'MODULUS' ;special:false;keyword:m_none;op:NOTOKEN), { delphi operator name }
+ (str:'PACKAGE' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'PRIVATE' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'PROGRAM' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'R12BASE' ;special:false;keyword:m_none;op:NOTOKEN), { Syscall variation on MorphOS }
+ (str:'RTLPROC' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'SECTION' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'STDCALL' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'SYSCALL' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'VARARGS' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'VIRTUAL' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'ABSOLUTE' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'ABSTRACT' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'BASESYSV' ;special:false;keyword:m_none;op:NOTOKEN), { Syscall variation on MorphOS }
+ (str:'CONSTREF' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'CONTAINS' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'CONTINUE' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'CPPCLASS' ;special:false;keyword:m_fpc;op:NOTOKEN),
+ (str:'EXPLICIT' ;special:false;keyword:m_none;op:NOTOKEN), { delphi operator name }
+ (str:'EXTERNAL' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'FUNCTION' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'IMPLICIT' ;special:false;keyword:m_none;op:NOTOKEN), { delphi operator name }
+ (str:'LESSTHAN' ;special:false;keyword:m_none;op:NOTOKEN), { delphi operator name }
+ (str:'LOCATION' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'MULTIPLY' ;special:false;keyword:m_none;op:NOTOKEN), { delphi operator name }
+ (str:'MWPASCAL' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'NEGATIVE' ;special:false;keyword:m_none;op:NOTOKEN), { delphi operator name }
+ (str:'NOTEQUAL' ;special:false;keyword:m_none;op:NOTOKEN), { delphi operator name }
+ (str:'OPERATOR' ;special:false;keyword:m_fpc;op:NOTOKEN),
+ (str:'OPTIONAL' ;special:false;keyword:m_none;op:NOTOKEN), { optional methods in an Objective-C protocol }
+ (str:'OVERLOAD' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'OVERRIDE' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'PLATFORM' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'POSITIVE' ;special:false;keyword:m_none;op:NOTOKEN), { delphi operator name }
+ (str:'PROPERTY' ;special:false;keyword:m_property;op:NOTOKEN),
+ (str:'READONLY' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'REGISTER' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'REQUIRED' ;special:false;keyword:m_none;op:NOTOKEN), { required methods in an Objective-C protocol }
+ (str:'REQUIRES' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'RESIDENT' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'SAFECALL' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'SUBTRACT' ;special:false;keyword:m_none;op:NOTOKEN), { delphi operator name }
+ (str:'SYSVBASE' ;special:false;keyword:m_none;op:NOTOKEN), { Syscall variation on MorphOS }
+ (str:'ASSEMBLER' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'BITPACKED' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'BITWISEOR' ;special:false;keyword:m_none;op:NOTOKEN), { delphi operator name }
+ (str:'INHERITED' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'INTDIVIDE' ;special:false;keyword:m_none;op:NOTOKEN), { delphi operator name }
+ (str:'INTERFACE' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'INTERRUPT' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'LEFTSHIFT' ;special:false;keyword:m_none;op:NOTOKEN), { delphi operator name }
+ (str:'LOGICALOR' ;special:false;keyword:m_none;op:NOTOKEN), { delphi operator name }
+ (str:'NODEFAULT' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'OBJCCLASS' ;special:false;keyword:m_objectivec1;op:NOTOKEN),
+ (str:'OTHERWISE' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'PROCEDURE' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'PROTECTED' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'PUBLISHED' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'SOFTFLOAT' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'THREADVAR' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'WRITEONLY' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'BITWISEAND' ;special:false;keyword:m_none;op:NOTOKEN), { delphi operator name }
+ (str:'BITWISEXOR' ;special:false;keyword:m_none;op:NOTOKEN), { delphi operator name }
+ (str:'DEPRECATED' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'DESTRUCTOR' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'ENUMERATOR' ;special:false;keyword:m_none;op:_OP_ENUMERATOR),
+ (str:'IMPLEMENTS' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'INTERNPROC' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'LOGICALAND' ;special:false;keyword:m_none;op:NOTOKEN), { delphi operator name }
+ (str:'LOGICALNOT' ;special:false;keyword:m_none;op:NOTOKEN), { delphi operator name }
+ (str:'LOGICALXOR' ;special:false;keyword:m_none;op:NOTOKEN), { delphi operator name }
+ (str:'OLDFPCCALL' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'OPENSTRING' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'RIGHTSHIFT' ;special:false;keyword:m_none;op:NOTOKEN), { delphi operator name }
+ (str:'SPECIALIZE' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'CONSTRUCTOR' ;special:false;keyword:m_all;op:NOTOKEN),
+ (str:'GREATERTHAN' ;special:false;keyword:m_none;op:NOTOKEN), { delphi operator name }
+ (str:'INTERNCONST' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'REINTRODUCE' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'SHORTSTRING' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'COMPILERPROC' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'EXPERIMENTAL' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'FINALIZATION' ;special:false;keyword:m_initfinal;op:NOTOKEN),
+ (str:'NOSTACKFRAME' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'OBJCCATEGORY' ;special:false;keyword:m_objectivec1;op:NOTOKEN), { Objective-C category }
+ (str:'OBJCPROTOCOL' ;special:false;keyword:m_objectivec1;op:NOTOKEN), { Objective-C protocol }
+ (str:'WEAKEXTERNAL' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'DISPINTERFACE' ;special:false;keyword:m_class;op:NOTOKEN),
+ (str:'UNIMPLEMENTED' ;special:false;keyword:m_none;op:NOTOKEN),
+ (str:'IMPLEMENTATION';special:false;keyword:m_all;op:NOTOKEN),
+ (str:'INITIALIZATION';special:false;keyword:m_initfinal;op:NOTOKEN),
+ (str:'RESOURCESTRING';special:false;keyword:m_all;op:NOTOKEN),
+ (str:'LESSTHANOREQUAL';special:false;keyword:m_none;op:NOTOKEN), { delphi operator name }
+ (str:'GREATERTHANOREQUAL';special:false;keyword:m_none;op:NOTOKEN) { delphi operator name }
+ );
+
+
+var
+ tokeninfo:ptokenarray;
+ tokenidx:ptokenidx;
+
+procedure inittokens;
+procedure donetokens;
+procedure create_tokenidx;
+
+
+implementation
+
+procedure create_tokenidx;
+{ create an index with the first and last token for every possible token
+ length, so a search only will be done in that small part }
+var
+ t : ttoken;
+ i : longint;
+ c : char;
+begin
+ fillchar(tokenidx^,sizeof(tokenidx^),0);
+ for t:=low(ttoken) to high(ttoken) do
+ begin
+ if not arraytokeninfo[t].special then
+ begin
+ i:=length(arraytokeninfo[t].str);
+ c:=arraytokeninfo[t].str[1];
+ if ord(tokenidx^[i,c].first)=0 then
+ tokenidx^[i,c].first:=t;
+ tokenidx^[i,c].last:=t;
+ end;
+ end;
+end;
+
+
+procedure inittokens;
+begin
+ if tokenidx = nil then
+ begin
+ tokeninfo:=@arraytokeninfo;
+ new(tokenidx);
+ create_tokenidx;
+ end;
+end;
+
+
+procedure donetokens;
+begin
+ if tokenidx <> nil then
+ begin
+ tokeninfo:=nil;
+ dispose(tokenidx);
+ tokenidx:=nil;
+ end;
+end;
+
+end.
diff --git a/closures/compiler/utils/Makefile b/closures/compiler/utils/Makefile
new file mode 100644
index 0000000000..68e846c595
--- /dev/null
+++ b/closures/compiler/utils/Makefile
@@ -0,0 +1,2469 @@
+#
+# Don't edit, this file is generated by FPCMake Version 2.0.0 [2011/12/04]
+#
+default: all
+MAKEFILETARGETS=i386-linux i386-go32v2 i386-win32 i386-os2 i386-freebsd i386-beos i386-haiku i386-netbsd i386-solaris i386-qnx i386-netware i386-openbsd i386-wdosx i386-darwin i386-emx i386-watcom i386-netwlibc i386-wince i386-embedded i386-symbian i386-nativent i386-iphonesim m68k-linux m68k-freebsd m68k-netbsd m68k-amiga m68k-atari m68k-openbsd m68k-palmos m68k-embedded powerpc-linux powerpc-netbsd powerpc-amiga powerpc-macos powerpc-darwin powerpc-morphos powerpc-embedded powerpc-wii sparc-linux sparc-netbsd sparc-solaris sparc-embedded x86_64-linux x86_64-freebsd x86_64-solaris x86_64-darwin x86_64-win64 x86_64-embedded arm-linux arm-palmos arm-darwin arm-wince arm-gba arm-nds arm-embedded arm-symbian powerpc64-linux powerpc64-darwin powerpc64-embedded avr-embedded armeb-linux armeb-embedded mipsel-linux
+BSDs = freebsd netbsd openbsd darwin
+UNIXs = linux $(BSDs) solaris qnx haiku
+LIMIT83fs = go32v2 os2 emx watcom
+OSNeedsComspecToRunBatch = go32v2 watcom
+FORCE:
+.PHONY: FORCE
+override PATH:=$(patsubst %/,%,$(subst \,/,$(PATH)))
+ifneq ($(findstring darwin,$(OSTYPE)),)
+inUnix=1 #darwin
+SEARCHPATH:=$(filter-out .,$(subst :, ,$(PATH)))
+else
+ifeq ($(findstring ;,$(PATH)),)
+inUnix=1
+SEARCHPATH:=$(filter-out .,$(subst :, ,$(PATH)))
+else
+SEARCHPATH:=$(subst ;, ,$(PATH))
+endif
+endif
+SEARCHPATH+=$(patsubst %/,%,$(subst \,/,$(dir $(MAKE))))
+PWD:=$(strip $(wildcard $(addsuffix /pwd.exe,$(SEARCHPATH))))
+ifeq ($(PWD),)
+PWD:=$(strip $(wildcard $(addsuffix /pwd,$(SEARCHPATH))))
+ifeq ($(PWD),)
+$(error You need the GNU utils package to use this Makefile)
+else
+PWD:=$(firstword $(PWD))
+SRCEXEEXT=
+endif
+else
+PWD:=$(firstword $(PWD))
+SRCEXEEXT=.exe
+endif
+ifndef inUnix
+ifeq ($(OS),Windows_NT)
+inWinNT=1
+else
+ifdef OS2_SHELL
+inOS2=1
+endif
+endif
+else
+ifneq ($(findstring cygdrive,$(PATH)),)
+inCygWin=1
+endif
+endif
+ifdef inUnix
+SRCBATCHEXT=.sh
+else
+ifdef inOS2
+SRCBATCHEXT=.cmd
+else
+SRCBATCHEXT=.bat
+endif
+endif
+ifdef COMSPEC
+ifneq ($(findstring $(OS_SOURCE),$(OSNeedsComspecToRunBatch)),)
+ifndef RUNBATCH
+RUNBATCH=$(COMSPEC) /C
+endif
+endif
+endif
+ifdef inUnix
+PATHSEP=/
+else
+PATHSEP:=$(subst /,\,/)
+ifdef inCygWin
+PATHSEP=/
+endif
+endif
+ifdef PWD
+BASEDIR:=$(subst \,/,$(shell $(PWD)))
+ifdef inCygWin
+ifneq ($(findstring /cygdrive/,$(BASEDIR)),)
+BASENODIR:=$(patsubst /cygdrive%,%,$(BASEDIR))
+BASEDRIVE:=$(firstword $(subst /, ,$(BASENODIR)))
+BASEDIR:=$(subst /cygdrive/$(BASEDRIVE)/,$(BASEDRIVE):/,$(BASEDIR))
+endif
+endif
+else
+BASEDIR=.
+endif
+ifdef inOS2
+ifndef ECHO
+ECHO:=$(strip $(wildcard $(addsuffix /gecho$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(ECHO),)
+ECHO:=$(strip $(wildcard $(addsuffix /echo$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(ECHO),)
+ECHO=echo
+else
+ECHO:=$(firstword $(ECHO))
+endif
+else
+ECHO:=$(firstword $(ECHO))
+endif
+endif
+export ECHO
+endif
+override DEFAULT_FPCDIR=../..
+ifndef FPC
+ifdef PP
+FPC=$(PP)
+endif
+endif
+ifndef FPC
+FPCPROG:=$(strip $(wildcard $(addsuffix /fpc$(SRCEXEEXT),$(SEARCHPATH))))
+ifneq ($(FPCPROG),)
+FPCPROG:=$(firstword $(FPCPROG))
+ifneq ($(CPU_TARGET),)
+FPC:=$(shell $(FPCPROG) -P$(CPU_TARGET) -PB)
+else
+FPC:=$(shell $(FPCPROG) -PB)
+endif
+ifneq ($(findstring Error,$(FPC)),)
+override FPC=$(firstword $(strip $(wildcard $(addsuffix /ppc386$(SRCEXEEXT),$(SEARCHPATH)))))
+else
+ifeq ($(strip $(wildcard $(FPC))),)
+FPC:=$(firstword $(FPCPROG))
+endif
+endif
+else
+override FPC=$(firstword $(strip $(wildcard $(addsuffix /ppc386$(SRCEXEEXT),$(SEARCHPATH)))))
+endif
+endif
+override FPC:=$(subst $(SRCEXEEXT),,$(FPC))
+override FPC:=$(subst \,/,$(FPC))$(SRCEXEEXT)
+FOUNDFPC:=$(strip $(wildcard $(FPC)))
+ifeq ($(FOUNDFPC),)
+FOUNDFPC=$(strip $(wildcard $(addsuffix /$(FPC),$(SEARCHPATH))))
+ifeq ($(FOUNDFPC),)
+$(error Compiler $(FPC) not found)
+endif
+endif
+ifndef FPC_COMPILERINFO
+FPC_COMPILERINFO:=$(shell $(FPC) -iVSPTPSOTO)
+endif
+ifndef FPC_VERSION
+FPC_VERSION:=$(word 1,$(FPC_COMPILERINFO))
+endif
+export FPC FPC_VERSION FPC_COMPILERINFO
+unexport CHECKDEPEND ALLDEPENDENCIES
+ifndef CPU_TARGET
+ifdef CPU_TARGET_DEFAULT
+CPU_TARGET=$(CPU_TARGET_DEFAULT)
+endif
+endif
+ifndef OS_TARGET
+ifdef OS_TARGET_DEFAULT
+OS_TARGET=$(OS_TARGET_DEFAULT)
+endif
+endif
+ifndef CPU_SOURCE
+CPU_SOURCE:=$(word 2,$(FPC_COMPILERINFO))
+endif
+ifndef CPU_TARGET
+CPU_TARGET:=$(word 3,$(FPC_COMPILERINFO))
+endif
+ifndef OS_SOURCE
+OS_SOURCE:=$(word 4,$(FPC_COMPILERINFO))
+endif
+ifndef OS_TARGET
+OS_TARGET:=$(word 5,$(FPC_COMPILERINFO))
+endif
+FULL_TARGET=$(CPU_TARGET)-$(OS_TARGET)
+FULL_SOURCE=$(CPU_SOURCE)-$(OS_SOURCE)
+ifeq ($(CPU_TARGET),armeb)
+ARCH=arm
+override FPCOPT+=-Cb
+else
+ifeq ($(CPU_TARGET),armel)
+ARCH=arm
+override FPCOPT+=-CaEABI
+else
+ARCH=$(CPU_TARGET)
+endif
+endif
+ifeq ($(FULL_TARGET),arm-embedded)
+ifeq ($(SUBARCH),)
+$(error When compiling for arm-embedded, a sub-architecture (e.g. SUBARCH=armv4t or SUBARCH=armv7m) must be defined)
+endif
+override FPCOPT+=-Cp$(SUBARCH)
+endif
+ifneq ($(findstring $(OS_SOURCE),$(LIMIT83fs)),)
+TARGETSUFFIX=$(OS_TARGET)
+SOURCESUFFIX=$(OS_SOURCE)
+else
+ifneq ($(findstring $(OS_TARGET),$(LIMIT83fs)),)
+TARGETSUFFIX=$(OS_TARGET)
+else
+TARGETSUFFIX=$(FULL_TARGET)
+endif
+SOURCESUFFIX=$(FULL_SOURCE)
+endif
+ifneq ($(FULL_TARGET),$(FULL_SOURCE))
+CROSSCOMPILE=1
+endif
+ifeq ($(findstring makefile,$(MAKECMDGOALS)),)
+ifeq ($(findstring $(FULL_TARGET),$(MAKEFILETARGETS)),)
+$(error The Makefile doesn't support target $(FULL_TARGET), please run fpcmake first)
+endif
+endif
+ifneq ($(findstring $(OS_TARGET),$(BSDs)),)
+BSDhier=1
+endif
+ifeq ($(OS_TARGET),linux)
+linuxHier=1
+endif
+export OS_TARGET OS_SOURCE ARCH CPU_TARGET CPU_SOURCE FULL_TARGET FULL_SOURCE TARGETSUFFIX SOURCESUFFIX CROSSCOMPILE
+ifdef FPCDIR
+override FPCDIR:=$(subst \,/,$(FPCDIR))
+ifeq ($(wildcard $(addprefix $(FPCDIR)/,rtl units)),)
+override FPCDIR=wrong
+endif
+else
+override FPCDIR=wrong
+endif
+ifdef DEFAULT_FPCDIR
+ifeq ($(FPCDIR),wrong)
+override FPCDIR:=$(subst \,/,$(DEFAULT_FPCDIR))
+ifeq ($(wildcard $(addprefix $(FPCDIR)/,rtl units)),)
+override FPCDIR=wrong
+endif
+endif
+endif
+ifeq ($(FPCDIR),wrong)
+ifdef inUnix
+override FPCDIR=/usr/local/lib/fpc/$(FPC_VERSION)
+ifeq ($(wildcard $(FPCDIR)/units),)
+override FPCDIR=/usr/lib/fpc/$(FPC_VERSION)
+endif
+else
+override FPCDIR:=$(subst /$(FPC),,$(firstword $(strip $(wildcard $(addsuffix /$(FPC),$(SEARCHPATH))))))
+override FPCDIR:=$(FPCDIR)/..
+ifeq ($(wildcard $(addprefix $(FPCDIR)/,rtl units)),)
+override FPCDIR:=$(FPCDIR)/..
+ifeq ($(wildcard $(addprefix $(FPCDIR)/,rtl units)),)
+override FPCDIR:=$(BASEDIR)
+ifeq ($(wildcard $(addprefix $(FPCDIR)/,rtl units)),)
+override FPCDIR=c:/pp
+endif
+endif
+endif
+endif
+endif
+ifndef CROSSBINDIR
+CROSSBINDIR:=$(wildcard $(FPCDIR)/bin/$(TARGETSUFFIX))
+endif
+ifneq ($(findstring $(OS_TARGET),darwin iphonesim),)
+ifeq ($(OS_SOURCE),darwin)
+DARWIN2DARWIN=1
+endif
+endif
+ifndef BINUTILSPREFIX
+ifndef CROSSBINDIR
+ifdef CROSSCOMPILE
+ifndef DARWIN2DARWIN
+BINUTILSPREFIX=$(CPU_TARGET)-$(OS_TARGET)-
+endif
+endif
+endif
+endif
+UNITSDIR:=$(wildcard $(FPCDIR)/units/$(TARGETSUFFIX))
+ifeq ($(UNITSDIR),)
+UNITSDIR:=$(wildcard $(FPCDIR)/units/$(OS_TARGET))
+endif
+PACKAGESDIR:=$(wildcard $(FPCDIR) $(FPCDIR)/packages $(FPCDIR)/packages/base $(FPCDIR)/packages/extra)
+ifndef FPCFPMAKE
+ifdef CROSSCOMPILE
+ifeq ($(strip $(wildcard $(addsuffix /compiler/ppc$(SRCEXEEXT),$(FPCDIR)))),)
+FPCPROG:=$(strip $(wildcard $(addsuffix /fpc$(SRCEXEEXT),$(SEARCHPATH))))
+ifneq ($(FPCPROG),)
+FPCPROG:=$(firstword $(FPCPROG))
+FPCFPMAKE:=$(shell $(FPCPROG) -PB)
+ifeq ($(strip $(wildcard $(FPCFPMAKE))),)
+FPCFPMAKE:=$(firstword $(FPCPROG))
+endif
+else
+override FPCFPMAKE=$(firstword $(strip $(wildcard $(addsuffix /ppc386$(SRCEXEEXT),$(SEARCHPATH)))))
+endif
+else
+FPCFPMAKE=$(strip $(wildcard $(addsuffix /compiler/ppc$(SRCEXEEXT),$(FPCDIR))))
+FPMAKE_SKIP_CONFIG=-n
+export FPCFPMAKE
+export FPMAKE_SKIP_CONFIG
+endif
+else
+FPMAKE_SKIP_CONFIG=-n
+FPCFPMAKE=$(FPC)
+endif
+endif
+ifeq ($(FULL_TARGET),i386-linux)
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins
+endif
+ifeq ($(FULL_TARGET),i386-go32v2)
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins
+endif
+ifeq ($(FULL_TARGET),i386-win32)
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins
+endif
+ifeq ($(FULL_TARGET),i386-os2)
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins
+endif
+ifeq ($(FULL_TARGET),i386-freebsd)
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins
+endif
+ifeq ($(FULL_TARGET),i386-beos)
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins
+endif
+ifeq ($(FULL_TARGET),i386-haiku)
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins
+endif
+ifeq ($(FULL_TARGET),i386-netbsd)
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins
+endif
+ifeq ($(FULL_TARGET),i386-solaris)
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins
+endif
+ifeq ($(FULL_TARGET),i386-qnx)
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins
+endif
+ifeq ($(FULL_TARGET),i386-netware)
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins
+endif
+ifeq ($(FULL_TARGET),i386-openbsd)
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins
+endif
+ifeq ($(FULL_TARGET),i386-wdosx)
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins
+endif
+ifeq ($(FULL_TARGET),i386-darwin)
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins
+endif
+ifeq ($(FULL_TARGET),i386-emx)
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins
+endif
+ifeq ($(FULL_TARGET),i386-watcom)
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins
+endif
+ifeq ($(FULL_TARGET),i386-netwlibc)
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins
+endif
+ifeq ($(FULL_TARGET),i386-wince)
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins
+endif
+ifeq ($(FULL_TARGET),i386-embedded)
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins
+endif
+ifeq ($(FULL_TARGET),i386-symbian)
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins
+endif
+ifeq ($(FULL_TARGET),i386-nativent)
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins
+endif
+ifeq ($(FULL_TARGET),i386-iphonesim)
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins
+endif
+ifeq ($(FULL_TARGET),m68k-linux)
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins
+endif
+ifeq ($(FULL_TARGET),m68k-freebsd)
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins
+endif
+ifeq ($(FULL_TARGET),m68k-netbsd)
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins
+endif
+ifeq ($(FULL_TARGET),m68k-amiga)
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins
+endif
+ifeq ($(FULL_TARGET),m68k-atari)
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins
+endif
+ifeq ($(FULL_TARGET),m68k-openbsd)
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins
+endif
+ifeq ($(FULL_TARGET),m68k-palmos)
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins
+endif
+ifeq ($(FULL_TARGET),m68k-embedded)
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins
+endif
+ifeq ($(FULL_TARGET),powerpc-linux)
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins
+endif
+ifeq ($(FULL_TARGET),powerpc-netbsd)
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins
+endif
+ifeq ($(FULL_TARGET),powerpc-amiga)
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins
+endif
+ifeq ($(FULL_TARGET),powerpc-macos)
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins
+endif
+ifeq ($(FULL_TARGET),powerpc-darwin)
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins
+endif
+ifeq ($(FULL_TARGET),powerpc-morphos)
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins
+endif
+ifeq ($(FULL_TARGET),powerpc-embedded)
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins
+endif
+ifeq ($(FULL_TARGET),powerpc-wii)
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins
+endif
+ifeq ($(FULL_TARGET),sparc-linux)
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins
+endif
+ifeq ($(FULL_TARGET),sparc-netbsd)
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins
+endif
+ifeq ($(FULL_TARGET),sparc-solaris)
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins
+endif
+ifeq ($(FULL_TARGET),sparc-embedded)
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins
+endif
+ifeq ($(FULL_TARGET),x86_64-linux)
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins
+endif
+ifeq ($(FULL_TARGET),x86_64-freebsd)
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins
+endif
+ifeq ($(FULL_TARGET),x86_64-solaris)
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins
+endif
+ifeq ($(FULL_TARGET),x86_64-darwin)
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins
+endif
+ifeq ($(FULL_TARGET),x86_64-win64)
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins
+endif
+ifeq ($(FULL_TARGET),x86_64-embedded)
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins
+endif
+ifeq ($(FULL_TARGET),arm-linux)
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins
+endif
+ifeq ($(FULL_TARGET),arm-palmos)
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins
+endif
+ifeq ($(FULL_TARGET),arm-darwin)
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins
+endif
+ifeq ($(FULL_TARGET),arm-wince)
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins
+endif
+ifeq ($(FULL_TARGET),arm-gba)
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins
+endif
+ifeq ($(FULL_TARGET),arm-nds)
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins
+endif
+ifeq ($(FULL_TARGET),arm-embedded)
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins
+endif
+ifeq ($(FULL_TARGET),arm-symbian)
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins
+endif
+ifeq ($(FULL_TARGET),powerpc64-linux)
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins
+endif
+ifeq ($(FULL_TARGET),powerpc64-darwin)
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins
+endif
+ifeq ($(FULL_TARGET),powerpc64-embedded)
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins
+endif
+ifeq ($(FULL_TARGET),avr-embedded)
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins
+endif
+ifeq ($(FULL_TARGET),armeb-linux)
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins
+endif
+ifeq ($(FULL_TARGET),armeb-embedded)
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins
+endif
+ifeq ($(FULL_TARGET),mipsel-linux)
+override TARGET_PROGRAMS+=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins
+endif
+ifeq ($(FULL_TARGET),i386-linux)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),i386-go32v2)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),i386-win32)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),i386-os2)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),i386-freebsd)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),i386-beos)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),i386-haiku)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),i386-netbsd)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),i386-solaris)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),i386-qnx)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),i386-netware)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),i386-openbsd)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),i386-wdosx)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),i386-darwin)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),i386-emx)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),i386-watcom)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),i386-netwlibc)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),i386-wince)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),i386-embedded)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),i386-symbian)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),i386-nativent)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),i386-iphonesim)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),m68k-linux)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),m68k-freebsd)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),m68k-netbsd)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),m68k-amiga)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),m68k-atari)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),m68k-openbsd)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),m68k-palmos)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),m68k-embedded)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),powerpc-linux)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),powerpc-netbsd)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),powerpc-amiga)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),powerpc-macos)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),powerpc-darwin)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),powerpc-morphos)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),powerpc-embedded)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),powerpc-wii)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),sparc-linux)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),sparc-netbsd)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),sparc-solaris)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),sparc-embedded)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),x86_64-linux)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),x86_64-freebsd)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),x86_64-solaris)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),x86_64-darwin)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),x86_64-win64)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),x86_64-embedded)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),arm-linux)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),arm-palmos)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),arm-darwin)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),arm-wince)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),arm-gba)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),arm-nds)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),arm-embedded)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),arm-symbian)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),powerpc64-linux)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),powerpc64-darwin)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),powerpc64-embedded)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),avr-embedded)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),armeb-linux)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),armeb-embedded)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+ifeq ($(FULL_TARGET),mipsel-linux)
+override CLEAN_UNITS+=ppu crc usubst
+endif
+override INSTALL_FPCPACKAGE=y
+ifeq ($(FULL_TARGET),i386-linux)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-go32v2)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-win32)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-os2)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-freebsd)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-beos)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-haiku)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-netbsd)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-solaris)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-qnx)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-netware)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-openbsd)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-wdosx)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-darwin)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-emx)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-watcom)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-netwlibc)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-wince)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-embedded)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-symbian)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-nativent)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-iphonesim)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),m68k-linux)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),m68k-freebsd)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),m68k-netbsd)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),m68k-amiga)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),m68k-atari)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),m68k-openbsd)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),m68k-palmos)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),m68k-embedded)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),powerpc-linux)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),powerpc-netbsd)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),powerpc-amiga)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),powerpc-macos)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),powerpc-darwin)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),powerpc-morphos)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),powerpc-embedded)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),powerpc-wii)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),sparc-linux)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),sparc-netbsd)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),sparc-solaris)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),sparc-embedded)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),x86_64-linux)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),x86_64-freebsd)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),x86_64-solaris)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),x86_64-darwin)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),x86_64-win64)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),x86_64-embedded)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),arm-linux)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),arm-palmos)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),arm-darwin)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),arm-wince)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),arm-gba)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),arm-nds)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),arm-embedded)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),arm-symbian)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),powerpc64-linux)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),powerpc64-darwin)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),powerpc64-embedded)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),avr-embedded)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),armeb-linux)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),armeb-embedded)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),mipsel-linux)
+override COMPILER_UNITDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-linux)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-go32v2)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-win32)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-os2)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-freebsd)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-beos)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-haiku)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-netbsd)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-solaris)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-qnx)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-netware)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-openbsd)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-wdosx)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-darwin)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-emx)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-watcom)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-netwlibc)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-wince)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-embedded)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-symbian)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-nativent)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),i386-iphonesim)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),m68k-linux)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),m68k-freebsd)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),m68k-netbsd)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),m68k-amiga)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),m68k-atari)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),m68k-openbsd)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),m68k-palmos)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),m68k-embedded)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),powerpc-linux)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),powerpc-netbsd)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),powerpc-amiga)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),powerpc-macos)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),powerpc-darwin)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),powerpc-morphos)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),powerpc-embedded)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),powerpc-wii)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),sparc-linux)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),sparc-netbsd)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),sparc-solaris)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),sparc-embedded)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),x86_64-linux)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),x86_64-freebsd)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),x86_64-solaris)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),x86_64-darwin)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),x86_64-win64)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),x86_64-embedded)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),arm-linux)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),arm-palmos)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),arm-darwin)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),arm-wince)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),arm-gba)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),arm-nds)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),arm-embedded)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),arm-symbian)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),powerpc64-linux)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),powerpc64-darwin)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),powerpc64-embedded)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),avr-embedded)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),armeb-linux)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),armeb-embedded)
+override COMPILER_SOURCEDIR+=..
+endif
+ifeq ($(FULL_TARGET),mipsel-linux)
+override COMPILER_SOURCEDIR+=..
+endif
+override SHARED_BUILD=n
+override SHARED_BUILD=n
+ifdef REQUIRE_UNITSDIR
+override UNITSDIR+=$(REQUIRE_UNITSDIR)
+endif
+ifdef REQUIRE_PACKAGESDIR
+override PACKAGESDIR+=$(REQUIRE_PACKAGESDIR)
+endif
+ifdef ZIPINSTALL
+ifneq ($(findstring $(OS_TARGET),$(UNIXs)),)
+UNIXHier=1
+endif
+else
+ifneq ($(findstring $(OS_SOURCE),$(UNIXs)),)
+UNIXHier=1
+endif
+endif
+ifndef INSTALL_PREFIX
+ifdef PREFIX
+INSTALL_PREFIX=$(PREFIX)
+endif
+endif
+ifndef INSTALL_PREFIX
+ifdef UNIXHier
+INSTALL_PREFIX=/usr/local
+else
+ifdef INSTALL_FPCPACKAGE
+INSTALL_BASEDIR:=/pp
+else
+INSTALL_BASEDIR:=/$(PACKAGE_NAME)
+endif
+endif
+endif
+export INSTALL_PREFIX
+ifdef INSTALL_FPCSUBDIR
+export INSTALL_FPCSUBDIR
+endif
+ifndef DIST_DESTDIR
+DIST_DESTDIR:=$(BASEDIR)
+endif
+export DIST_DESTDIR
+ifndef COMPILER_UNITTARGETDIR
+ifdef PACKAGEDIR_MAIN
+COMPILER_UNITTARGETDIR=$(PACKAGEDIR_MAIN)/units/$(TARGETSUFFIX)
+else
+COMPILER_UNITTARGETDIR=units/$(TARGETSUFFIX)
+endif
+endif
+ifndef COMPILER_TARGETDIR
+COMPILER_TARGETDIR=.
+endif
+ifndef INSTALL_BASEDIR
+ifdef UNIXHier
+ifdef INSTALL_FPCPACKAGE
+INSTALL_BASEDIR:=$(INSTALL_PREFIX)/lib/fpc/$(FPC_VERSION)
+else
+INSTALL_BASEDIR:=$(INSTALL_PREFIX)/lib/$(PACKAGE_NAME)
+endif
+else
+INSTALL_BASEDIR:=$(INSTALL_PREFIX)
+endif
+endif
+ifndef INSTALL_BINDIR
+ifdef UNIXHier
+INSTALL_BINDIR:=$(INSTALL_PREFIX)/bin
+else
+INSTALL_BINDIR:=$(INSTALL_BASEDIR)/bin
+ifdef INSTALL_FPCPACKAGE
+ifdef CROSSCOMPILE
+ifdef CROSSINSTALL
+INSTALL_BINDIR:=$(INSTALL_BINDIR)/$(SOURCESUFFIX)
+else
+INSTALL_BINDIR:=$(INSTALL_BINDIR)/$(TARGETSUFFIX)
+endif
+else
+INSTALL_BINDIR:=$(INSTALL_BINDIR)/$(TARGETSUFFIX)
+endif
+endif
+endif
+endif
+ifndef INSTALL_UNITDIR
+INSTALL_UNITDIR:=$(INSTALL_BASEDIR)/units/$(TARGETSUFFIX)
+ifdef INSTALL_FPCPACKAGE
+ifdef PACKAGE_NAME
+INSTALL_UNITDIR:=$(INSTALL_UNITDIR)/$(PACKAGE_NAME)
+endif
+endif
+endif
+ifndef INSTALL_LIBDIR
+ifdef UNIXHier
+INSTALL_LIBDIR:=$(INSTALL_PREFIX)/lib
+else
+INSTALL_LIBDIR:=$(INSTALL_UNITDIR)
+endif
+endif
+ifndef INSTALL_SOURCEDIR
+ifdef UNIXHier
+ifdef BSDhier
+SRCPREFIXDIR=share/src
+else
+ifdef linuxHier
+SRCPREFIXDIR=share/src
+else
+SRCPREFIXDIR=src
+endif
+endif
+ifdef INSTALL_FPCPACKAGE
+ifdef INSTALL_FPCSUBDIR
+INSTALL_SOURCEDIR:=$(INSTALL_PREFIX)/$(SRCPREFIXDIR)/fpc-$(FPC_VERSION)/$(INSTALL_FPCSUBDIR)/$(PACKAGE_NAME)
+else
+INSTALL_SOURCEDIR:=$(INSTALL_PREFIX)/$(SRCPREFIXDIR)/fpc-$(FPC_VERSION)/$(PACKAGE_NAME)
+endif
+else
+INSTALL_SOURCEDIR:=$(INSTALL_PREFIX)/$(SRCPREFIXDIR)/$(PACKAGE_NAME)-$(PACKAGE_VERSION)
+endif
+else
+ifdef INSTALL_FPCPACKAGE
+ifdef INSTALL_FPCSUBDIR
+INSTALL_SOURCEDIR:=$(INSTALL_BASEDIR)/source/$(INSTALL_FPCSUBDIR)/$(PACKAGE_NAME)
+else
+INSTALL_SOURCEDIR:=$(INSTALL_BASEDIR)/source/$(PACKAGE_NAME)
+endif
+else
+INSTALL_SOURCEDIR:=$(INSTALL_BASEDIR)/source
+endif
+endif
+endif
+ifndef INSTALL_DOCDIR
+ifdef UNIXHier
+ifdef BSDhier
+DOCPREFIXDIR=share/doc
+else
+ifdef linuxHier
+DOCPREFIXDIR=share/doc
+else
+DOCPREFIXDIR=doc
+endif
+endif
+ifdef INSTALL_FPCPACKAGE
+INSTALL_DOCDIR:=$(INSTALL_PREFIX)/$(DOCPREFIXDIR)/fpc-$(FPC_VERSION)/$(PACKAGE_NAME)
+else
+INSTALL_DOCDIR:=$(INSTALL_PREFIX)/$(DOCPREFIXDIR)/$(PACKAGE_NAME)-$(PACKAGE_VERSION)
+endif
+else
+ifdef INSTALL_FPCPACKAGE
+INSTALL_DOCDIR:=$(INSTALL_BASEDIR)/doc/$(PACKAGE_NAME)
+else
+INSTALL_DOCDIR:=$(INSTALL_BASEDIR)/doc
+endif
+endif
+endif
+ifndef INSTALL_EXAMPLEDIR
+ifdef UNIXHier
+ifdef INSTALL_FPCPACKAGE
+ifdef BSDhier
+INSTALL_EXAMPLEDIR:=$(INSTALL_PREFIX)/share/examples/fpc-$(FPC_VERSION)/$(PACKAGE_NAME)
+else
+ifdef linuxHier
+INSTALL_EXAMPLEDIR:=$(INSTALL_DOCDIR)/examples
+else
+INSTALL_EXAMPLEDIR:=$(INSTALL_PREFIX)/doc/fpc-$(FPC_VERSION)/examples/$(PACKAGE_NAME)
+endif
+endif
+else
+ifdef BSDhier
+INSTALL_EXAMPLEDIR:=$(INSTALL_PREFIX)/share/examples/$(PACKAGE_NAME)-$(PACKAGE_VERSION)
+else
+ifdef linuxHier
+INSTALL_EXAMPLEDIR:=$(INSTALL_DOCDIR)/examples/$(PACKAGE_NAME)-$(PACKAGE_VERSION)
+else
+INSTALL_EXAMPLEDIR:=$(INSTALL_PREFIX)/doc/$(PACKAGE_NAME)-$(PACKAGE_VERSION)
+endif
+endif
+endif
+else
+ifdef INSTALL_FPCPACKAGE
+INSTALL_EXAMPLEDIR:=$(INSTALL_BASEDIR)/examples/$(PACKAGE_NAME)
+else
+INSTALL_EXAMPLEDIR:=$(INSTALL_BASEDIR)/examples
+endif
+endif
+endif
+ifndef INSTALL_DATADIR
+INSTALL_DATADIR=$(INSTALL_BASEDIR)
+endif
+ifndef INSTALL_SHAREDDIR
+INSTALL_SHAREDDIR=$(INSTALL_PREFIX)/lib
+endif
+ifdef CROSSCOMPILE
+ifndef CROSSBINDIR
+CROSSBINDIR:=$(wildcard $(CROSSTARGETDIR)/bin/$(SOURCESUFFIX))
+ifeq ($(CROSSBINDIR),)
+CROSSBINDIR:=$(wildcard $(INSTALL_BASEDIR)/cross/$(TARGETSUFFIX)/bin/$(FULL_SOURCE))
+endif
+endif
+else
+CROSSBINDIR=
+endif
+BATCHEXT=.bat
+LOADEREXT=.as
+EXEEXT=.exe
+PPLEXT=.ppl
+PPUEXT=.ppu
+OEXT=.o
+ASMEXT=.s
+SMARTEXT=.sl
+STATICLIBEXT=.a
+SHAREDLIBEXT=.so
+SHAREDLIBPREFIX=libfp
+STATICLIBPREFIX=libp
+IMPORTLIBPREFIX=libimp
+RSTEXT=.rst
+EXEDBGEXT=.dbg
+ifeq ($(OS_TARGET),go32v1)
+STATICLIBPREFIX=
+SHORTSUFFIX=v1
+endif
+ifeq ($(OS_TARGET),go32v2)
+STATICLIBPREFIX=
+SHORTSUFFIX=dos
+IMPORTLIBPREFIX=
+endif
+ifeq ($(OS_TARGET),watcom)
+STATICLIBPREFIX=
+OEXT=.obj
+ASMEXT=.asm
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=wat
+IMPORTLIBPREFIX=
+endif
+ifeq ($(OS_TARGET),linux)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=lnx
+endif
+ifeq ($(OS_TARGET),freebsd)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=fbs
+endif
+ifeq ($(OS_TARGET),netbsd)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=nbs
+endif
+ifeq ($(OS_TARGET),openbsd)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=obs
+endif
+ifeq ($(OS_TARGET),win32)
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=w32
+endif
+ifeq ($(OS_TARGET),os2)
+BATCHEXT=.cmd
+AOUTEXT=.out
+STATICLIBPREFIX=
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=os2
+ECHO=echo
+IMPORTLIBPREFIX=
+endif
+ifeq ($(OS_TARGET),emx)
+BATCHEXT=.cmd
+AOUTEXT=.out
+STATICLIBPREFIX=
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=emx
+ECHO=echo
+IMPORTLIBPREFIX=
+endif
+ifeq ($(OS_TARGET),amiga)
+EXEEXT=
+SHAREDLIBEXT=.library
+SHORTSUFFIX=amg
+endif
+ifeq ($(OS_TARGET),morphos)
+EXEEXT=
+SHAREDLIBEXT=.library
+SHORTSUFFIX=mos
+endif
+ifeq ($(OS_TARGET),atari)
+EXEEXT=.ttp
+SHORTSUFFIX=ata
+endif
+ifeq ($(OS_TARGET),beos)
+BATCHEXT=.sh
+EXEEXT=
+SHORTSUFFIX=be
+endif
+ifeq ($(OS_TARGET),haiku)
+BATCHEXT=.sh
+EXEEXT=
+SHORTSUFFIX=hai
+endif
+ifeq ($(OS_TARGET),solaris)
+BATCHEXT=.sh
+EXEEXT=
+SHORTSUFFIX=sun
+endif
+ifeq ($(OS_TARGET),qnx)
+BATCHEXT=.sh
+EXEEXT=
+SHORTSUFFIX=qnx
+endif
+ifeq ($(OS_TARGET),netware)
+EXEEXT=.nlm
+STATICLIBPREFIX=
+SHORTSUFFIX=nw
+IMPORTLIBPREFIX=imp
+endif
+ifeq ($(OS_TARGET),netwlibc)
+EXEEXT=.nlm
+STATICLIBPREFIX=
+SHORTSUFFIX=nwl
+IMPORTLIBPREFIX=imp
+endif
+ifeq ($(OS_TARGET),macos)
+BATCHEXT=
+EXEEXT=
+DEBUGSYMEXT=.xcoff
+SHORTSUFFIX=mac
+IMPORTLIBPREFIX=imp
+endif
+ifneq ($(findstring $(OS_TARGET),darwin iphonesim),)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=dwn
+EXEDBGEXT=.dSYM
+endif
+ifeq ($(OS_TARGET),gba)
+EXEEXT=.gba
+SHAREDLIBEXT=.so
+SHORTSUFFIX=gba
+endif
+ifeq ($(OS_TARGET),symbian)
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=symbian
+endif
+ifeq ($(OS_TARGET),NativeNT)
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=nativent
+endif
+ifeq ($(OS_TARGET),wii)
+EXEEXT=.dol
+SHAREDLIBEXT=.so
+SHORTSUFFIX=wii
+endif
+ifneq ($(findstring $(OS_SOURCE),$(LIMIT83fs)),)
+FPCMADE=fpcmade.$(SHORTSUFFIX)
+ZIPSUFFIX=$(SHORTSUFFIX)
+ZIPCROSSPREFIX=
+ZIPSOURCESUFFIX=src
+ZIPEXAMPLESUFFIX=exm
+else
+FPCMADE=fpcmade.$(TARGETSUFFIX)
+ZIPSOURCESUFFIX=.source
+ZIPEXAMPLESUFFIX=.examples
+ifdef CROSSCOMPILE
+ZIPSUFFIX=.$(SOURCESUFFIX)
+ZIPCROSSPREFIX=$(TARGETSUFFIX)-
+else
+ZIPSUFFIX=.$(TARGETSUFFIX)
+ZIPCROSSPREFIX=
+endif
+endif
+ifndef ECHO
+ECHO:=$(strip $(wildcard $(addsuffix /gecho$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(ECHO),)
+ECHO:=$(strip $(wildcard $(addsuffix /echo$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(ECHO),)
+ECHO= __missing_command_ECHO
+else
+ECHO:=$(firstword $(ECHO))
+endif
+else
+ECHO:=$(firstword $(ECHO))
+endif
+endif
+export ECHO
+ifndef DATE
+DATE:=$(strip $(wildcard $(addsuffix /gdate$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(DATE),)
+DATE:=$(strip $(wildcard $(addsuffix /date$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(DATE),)
+DATE= __missing_command_DATE
+else
+DATE:=$(firstword $(DATE))
+endif
+else
+DATE:=$(firstword $(DATE))
+endif
+endif
+export DATE
+ifndef GINSTALL
+GINSTALL:=$(strip $(wildcard $(addsuffix /ginstall$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(GINSTALL),)
+GINSTALL:=$(strip $(wildcard $(addsuffix /install$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(GINSTALL),)
+GINSTALL= __missing_command_GINSTALL
+else
+GINSTALL:=$(firstword $(GINSTALL))
+endif
+else
+GINSTALL:=$(firstword $(GINSTALL))
+endif
+endif
+export GINSTALL
+ifndef CPPROG
+CPPROG:=$(strip $(wildcard $(addsuffix /cp$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(CPPROG),)
+CPPROG= __missing_command_CPPROG
+else
+CPPROG:=$(firstword $(CPPROG))
+endif
+endif
+export CPPROG
+ifndef RMPROG
+RMPROG:=$(strip $(wildcard $(addsuffix /rm$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(RMPROG),)
+RMPROG= __missing_command_RMPROG
+else
+RMPROG:=$(firstword $(RMPROG))
+endif
+endif
+export RMPROG
+ifndef MVPROG
+MVPROG:=$(strip $(wildcard $(addsuffix /mv$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(MVPROG),)
+MVPROG= __missing_command_MVPROG
+else
+MVPROG:=$(firstword $(MVPROG))
+endif
+endif
+export MVPROG
+ifndef MKDIRPROG
+MKDIRPROG:=$(strip $(wildcard $(addsuffix /gmkdir$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(MKDIRPROG),)
+MKDIRPROG:=$(strip $(wildcard $(addsuffix /mkdir$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(MKDIRPROG),)
+MKDIRPROG= __missing_command_MKDIRPROG
+else
+MKDIRPROG:=$(firstword $(MKDIRPROG))
+endif
+else
+MKDIRPROG:=$(firstword $(MKDIRPROG))
+endif
+endif
+export MKDIRPROG
+ifndef ECHOREDIR
+ifndef inUnix
+ECHOREDIR=echo
+else
+ECHOREDIR=$(ECHO)
+endif
+endif
+ifndef COPY
+COPY:=$(CPPROG) -fp
+endif
+ifndef COPYTREE
+COPYTREE:=$(CPPROG) -Rfp
+endif
+ifndef MKDIRTREE
+MKDIRTREE:=$(MKDIRPROG) -p
+endif
+ifndef MOVE
+MOVE:=$(MVPROG) -f
+endif
+ifndef DEL
+DEL:=$(RMPROG) -f
+endif
+ifndef DELTREE
+DELTREE:=$(RMPROG) -rf
+endif
+ifndef INSTALL
+ifdef inUnix
+INSTALL:=$(GINSTALL) -c -m 644
+else
+INSTALL:=$(COPY)
+endif
+endif
+ifndef INSTALLEXE
+ifdef inUnix
+INSTALLEXE:=$(GINSTALL) -c -m 755
+else
+INSTALLEXE:=$(COPY)
+endif
+endif
+ifndef MKDIR
+MKDIR:=$(GINSTALL) -m 755 -d
+endif
+export ECHOREDIR COPY COPYTREE MOVE DEL DELTREE INSTALL INSTALLEXE MKDIR
+ifndef PPUMOVE
+PPUMOVE:=$(strip $(wildcard $(addsuffix /ppumove$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(PPUMOVE),)
+PPUMOVE= __missing_command_PPUMOVE
+else
+PPUMOVE:=$(firstword $(PPUMOVE))
+endif
+endif
+export PPUMOVE
+ifndef FPCMAKE
+FPCMAKE:=$(strip $(wildcard $(addsuffix /fpcmake$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(FPCMAKE),)
+FPCMAKE= __missing_command_FPCMAKE
+else
+FPCMAKE:=$(firstword $(FPCMAKE))
+endif
+endif
+export FPCMAKE
+ifndef ZIPPROG
+ZIPPROG:=$(strip $(wildcard $(addsuffix /zip$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(ZIPPROG),)
+ZIPPROG= __missing_command_ZIPPROG
+else
+ZIPPROG:=$(firstword $(ZIPPROG))
+endif
+endif
+export ZIPPROG
+ifndef TARPROG
+TARPROG:=$(strip $(wildcard $(addsuffix /gtar$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(TARPROG),)
+TARPROG:=$(strip $(wildcard $(addsuffix /tar$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(TARPROG),)
+TARPROG= __missing_command_TARPROG
+else
+TARPROG:=$(firstword $(TARPROG))
+endif
+else
+TARPROG:=$(firstword $(TARPROG))
+endif
+endif
+export TARPROG
+ASNAME=$(BINUTILSPREFIX)as
+LDNAME=$(BINUTILSPREFIX)ld
+ARNAME=$(BINUTILSPREFIX)ar
+RCNAME=$(BINUTILSPREFIX)rc
+ifndef ASPROG
+ifdef CROSSBINDIR
+ASPROG=$(CROSSBINDIR)/$(ASNAME)$(SRCEXEEXT)
+else
+ASPROG=$(ASNAME)
+endif
+endif
+ifndef LDPROG
+ifdef CROSSBINDIR
+LDPROG=$(CROSSBINDIR)/$(LDNAME)$(SRCEXEEXT)
+else
+LDPROG=$(LDNAME)
+endif
+endif
+ifndef RCPROG
+ifdef CROSSBINDIR
+RCPROG=$(CROSSBINDIR)/$(RCNAME)$(SRCEXEEXT)
+else
+RCPROG=$(RCNAME)
+endif
+endif
+ifndef ARPROG
+ifdef CROSSBINDIR
+ARPROG=$(CROSSBINDIR)/$(ARNAME)$(SRCEXEEXT)
+else
+ARPROG=$(ARNAME)
+endif
+endif
+AS=$(ASPROG)
+LD=$(LDPROG)
+RC=$(RCPROG)
+AR=$(ARPROG)
+PPAS=ppas$(SRCBATCHEXT)
+ifdef inUnix
+LDCONFIG=ldconfig
+else
+LDCONFIG=
+endif
+ifdef DATE
+DATESTR:=$(shell $(DATE) +%Y%m%d)
+else
+DATESTR=
+endif
+ifndef UPXPROG
+ifeq ($(OS_TARGET),go32v2)
+UPXPROG:=1
+endif
+ifeq ($(OS_TARGET),win32)
+UPXPROG:=
+endif
+ifdef UPXPROG
+UPXPROG:=$(strip $(wildcard $(addsuffix /upx$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(UPXPROG),)
+UPXPROG=
+else
+UPXPROG:=$(firstword $(UPXPROG))
+endif
+else
+UPXPROG=
+endif
+endif
+export UPXPROG
+ZIPOPT=-9
+ZIPEXT=.zip
+ifeq ($(USETAR),bz2)
+TAROPT=vj
+TAREXT=.tar.bz2
+else
+TAROPT=vz
+TAREXT=.tar.gz
+endif
+override REQUIRE_PACKAGES=rtl
+ifeq ($(FULL_TARGET),i386-linux)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-go32v2)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-win32)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-os2)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-freebsd)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-beos)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-haiku)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-netbsd)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-solaris)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-qnx)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-netware)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-openbsd)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-wdosx)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-darwin)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-emx)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-watcom)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-netwlibc)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-wince)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-embedded)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-symbian)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-nativent)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),i386-iphonesim)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),m68k-linux)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),m68k-freebsd)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),m68k-netbsd)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),m68k-amiga)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),m68k-atari)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),m68k-openbsd)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),m68k-palmos)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),m68k-embedded)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),powerpc-linux)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),powerpc-netbsd)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),powerpc-amiga)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),powerpc-macos)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),powerpc-darwin)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),powerpc-morphos)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),powerpc-embedded)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),powerpc-wii)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),sparc-linux)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),sparc-netbsd)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),sparc-solaris)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),sparc-embedded)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),x86_64-linux)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),x86_64-freebsd)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),x86_64-solaris)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),x86_64-darwin)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),x86_64-win64)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),x86_64-embedded)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),arm-linux)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),arm-palmos)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),arm-darwin)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),arm-wince)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),arm-gba)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),arm-nds)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),arm-embedded)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),arm-symbian)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),powerpc64-linux)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),powerpc64-darwin)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),powerpc64-embedded)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),avr-embedded)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),armeb-linux)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),armeb-embedded)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifeq ($(FULL_TARGET),mipsel-linux)
+REQUIRE_PACKAGES_RTL=1
+endif
+ifdef REQUIRE_PACKAGES_RTL
+PACKAGEDIR_RTL:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /rtl/Makefile.fpc,$(PACKAGESDIR))))))
+ifneq ($(PACKAGEDIR_RTL),)
+ifneq ($(wildcard $(PACKAGEDIR_RTL)/units/$(TARGETSUFFIX)),)
+UNITDIR_RTL=$(PACKAGEDIR_RTL)/units/$(TARGETSUFFIX)
+else
+UNITDIR_RTL=$(PACKAGEDIR_RTL)
+endif
+ifneq ($(wildcard $(PACKAGEDIR_RTL)/units/$(SOURCESUFFIX)),)
+UNITDIR_FPMAKE_RTL=$(PACKAGEDIR_RTL)/units/$(SOURCESUFFIX)
+else
+ifneq ($(wildcard $(PACKAGEDIR_RTL)/units_bs/$(SOURCESUFFIX)),)
+UNITDIR_FPMAKE_RTL=$(PACKAGEDIR_RTL)/units_bs/$(SOURCESUFFIX)
+else
+UNITDIR_FPMAKE_RTL=$(PACKAGEDIR_RTL)
+endif
+endif
+ifdef CHECKDEPEND
+$(PACKAGEDIR_RTL)/$(OS_TARGET)/$(FPCMADE):
+ $(MAKE) -C $(PACKAGEDIR_RTL)/$(OS_TARGET) $(FPCMADE)
+override ALLDEPENDENCIES+=$(PACKAGEDIR_RTL)/$(OS_TARGET)/$(FPCMADE)
+endif
+else
+PACKAGEDIR_RTL=
+UNITDIR_RTL:=$(subst /Package.fpc,,$(strip $(wildcard $(addsuffix /rtl/Package.fpc,$(UNITSDIR)))))
+ifneq ($(UNITDIR_RTL),)
+UNITDIR_RTL:=$(firstword $(UNITDIR_RTL))
+else
+UNITDIR_RTL=
+endif
+endif
+ifdef UNITDIR_RTL
+override COMPILER_UNITDIR+=$(UNITDIR_RTL)
+endif
+ifdef UNITDIR_FPMAKE_RTL
+override COMPILER_FPMAKE_UNITDIR+=$(UNITDIR_FPMAKE_RTL)
+endif
+endif
+ifndef NOCPUDEF
+override FPCOPTDEF=$(ARCH)
+endif
+ifneq ($(OS_TARGET),$(OS_SOURCE))
+override FPCOPT+=-T$(OS_TARGET)
+endif
+ifneq ($(CPU_TARGET),$(CPU_SOURCE))
+override FPCOPT+=-P$(ARCH)
+endif
+ifeq ($(OS_SOURCE),openbsd)
+override FPCOPT+=-FD$(NEW_BINUTILS_PATH)
+override FPCMAKEOPT+=-FD$(NEW_BINUTILS_PATH)
+endif
+ifndef CROSSBOOTSTRAP
+ifneq ($(BINUTILSPREFIX),)
+override FPCOPT+=-XP$(BINUTILSPREFIX)
+override FPCMAKEOPT+=-XP$(BINUTILSPREFIX)
+endif
+ifneq ($(BINUTILSPREFIX),)
+override FPCOPT+=-Xr$(RLINKPATH)
+endif
+endif
+ifdef UNITDIR
+override FPCOPT+=$(addprefix -Fu,$(UNITDIR))
+endif
+ifdef LIBDIR
+override FPCOPT+=$(addprefix -Fl,$(LIBDIR))
+endif
+ifdef OBJDIR
+override FPCOPT+=$(addprefix -Fo,$(OBJDIR))
+endif
+ifdef INCDIR
+override FPCOPT+=$(addprefix -Fi,$(INCDIR))
+endif
+ifdef LINKSMART
+override FPCOPT+=-XX
+endif
+ifdef CREATESMART
+override FPCOPT+=-CX
+endif
+ifdef DEBUG
+override FPCOPT+=-gl
+override FPCOPTDEF+=DEBUG
+endif
+ifdef RELEASE
+ifneq ($(findstring 2.0.,$(FPC_VERSION)),)
+ifeq ($(CPU_TARGET),i386)
+FPCCPUOPT:=-OG2p3
+endif
+ifeq ($(CPU_TARGET),powerpc)
+FPCCPUOPT:=-O1r
+endif
+else
+FPCCPUOPT:=-O2
+endif
+override FPCOPT+=-Ur -Xs $(FPCCPUOPT) -n
+override FPCOPTDEF+=RELEASE
+endif
+ifdef STRIP
+override FPCOPT+=-Xs
+endif
+ifdef OPTIMIZE
+override FPCOPT+=-O2
+endif
+ifdef VERBOSE
+override FPCOPT+=-vwni
+endif
+ifdef COMPILER_OPTIONS
+override FPCOPT+=$(COMPILER_OPTIONS)
+endif
+ifdef COMPILER_UNITDIR
+override FPCOPT+=$(addprefix -Fu,$(COMPILER_UNITDIR))
+endif
+ifdef COMPILER_LIBRARYDIR
+override FPCOPT+=$(addprefix -Fl,$(COMPILER_LIBRARYDIR))
+endif
+ifdef COMPILER_OBJECTDIR
+override FPCOPT+=$(addprefix -Fo,$(COMPILER_OBJECTDIR))
+endif
+ifdef COMPILER_INCLUDEDIR
+override FPCOPT+=$(addprefix -Fi,$(COMPILER_INCLUDEDIR))
+endif
+ifdef CROSSBINDIR
+override FPCOPT+=-FD$(CROSSBINDIR)
+endif
+ifdef COMPILER_TARGETDIR
+override FPCOPT+=-FE$(COMPILER_TARGETDIR)
+ifeq ($(COMPILER_TARGETDIR),.)
+override TARGETDIRPREFIX=
+else
+override TARGETDIRPREFIX=$(COMPILER_TARGETDIR)/
+endif
+endif
+ifdef COMPILER_UNITTARGETDIR
+override FPCOPT+=-FU$(COMPILER_UNITTARGETDIR)
+ifeq ($(COMPILER_UNITTARGETDIR),.)
+override UNITTARGETDIRPREFIX=
+else
+override UNITTARGETDIRPREFIX=$(COMPILER_UNITTARGETDIR)/
+endif
+else
+ifdef COMPILER_TARGETDIR
+override COMPILER_UNITTARGETDIR=$(COMPILER_TARGETDIR)
+override UNITTARGETDIRPREFIX=$(TARGETDIRPREFIX)
+endif
+endif
+ifdef CREATESHARED
+override FPCOPT+=-Cg
+ifeq ($(CPU_TARGET),i386)
+override FPCOPT+=-Aas
+endif
+endif
+ifeq ($(findstring 2.0.,$(FPC_VERSION)),)
+ifneq ($(findstring $(OS_TARGET),freebsd openbsd netbsd linux solaris),)
+ifeq ($(CPU_TARGET),x86_64)
+override FPCOPT+=-Cg
+endif
+endif
+endif
+ifdef LINKSHARED
+endif
+ifdef OPT
+override FPCOPT+=$(OPT)
+endif
+ifdef FPCOPTDEF
+override FPCOPT+=$(addprefix -d,$(FPCOPTDEF))
+endif
+ifdef CFGFILE
+override FPCOPT+=@$(CFGFILE)
+endif
+ifdef USEENV
+override FPCEXTCMD:=$(FPCOPT)
+override FPCOPT:=!FPCEXTCMD
+export FPCEXTCMD
+endif
+override AFULL_TARGET=$(CPU_TARGET)-$(OS_TARGET)
+override AFULL_SOURCE=$(CPU_SOURCE)-$(OS_SOURCE)
+ifneq ($(AFULL_TARGET),$(AFULL_SOURCE))
+override ACROSSCOMPILE=1
+endif
+ifdef ACROSSCOMPILE
+override FPCOPT+=$(CROSSOPT)
+endif
+override COMPILER:=$(FPC) $(FPCOPT)
+ifeq (,$(findstring -s ,$(COMPILER)))
+EXECPPAS=
+else
+ifeq ($(FULL_SOURCE),$(FULL_TARGET))
+ifdef RUNBATCH
+EXECPPAS:=@$(RUNBATCH) $(PPAS)
+else
+EXECPPAS:=@$(PPAS)
+endif
+endif
+endif
+.PHONY: fpc_exes
+ifndef CROSSINSTALL
+ifneq ($(TARGET_PROGRAMS),)
+override EXEFILES=$(addsuffix $(EXEEXT),$(TARGET_PROGRAMS))
+override EXEOFILES:=$(addsuffix $(OEXT),$(TARGET_PROGRAMS)) $(addprefix $(STATICLIBPREFIX),$(addsuffix $(STATICLIBEXT),$(TARGET_PROGRAMS))) $(addprefix $(IMPORTLIBPREFIX),$(addsuffix $(STATICLIBEXT),$(TARGET_PROGRAMS)))
+override EXEDBGFILES:=$(addsuffix $(EXEDBGEXT),$(TARGET_PROGRAMS))
+override ALLTARGET+=fpc_exes
+override INSTALLEXEFILES+=$(EXEFILES)
+override CLEANEXEFILES+=$(EXEFILES) $(EXEOFILES)
+override CLEANEXEDBGFILES+=$(EXEDBGFILES)
+ifeq ($(OS_TARGET),os2)
+override CLEANEXEFILES+=$(addsuffix $(AOUTEXT),$(TARGET_PROGRAMS))
+endif
+ifeq ($(OS_TARGET),emx)
+override CLEANEXEFILES+=$(addsuffix $(AOUTEXT),$(TARGET_PROGRAMS))
+endif
+endif
+endif
+fpc_exes: $(COMPILER_TARGETDIR) $(COMPILER_UNITTARGETDIR) $(EXEFILES)
+ifdef TARGET_RSTS
+override RSTFILES=$(addsuffix $(RSTEXT),$(TARGET_RSTS))
+override CLEANRSTFILES+=$(RSTFILES)
+endif
+.PHONY: fpc_all fpc_smart fpc_debug fpc_release fpc_shared
+$(FPCMADE): $(ALLDEPENDENCIES) $(ALLTARGET)
+ @$(ECHOREDIR) Compiled > $(FPCMADE)
+fpc_all: $(FPCMADE)
+fpc_smart:
+ $(MAKE) all LINKSMART=1 CREATESMART=1
+fpc_debug:
+ $(MAKE) all DEBUG=1
+fpc_release:
+ $(MAKE) all RELEASE=1
+.SUFFIXES: $(EXEEXT) $(PPUEXT) $(OEXT) .pas .lpr .dpr .pp .rc .res
+$(COMPILER_UNITTARGETDIR):
+ $(MKDIRTREE) $(COMPILER_UNITTARGETDIR)
+$(COMPILER_TARGETDIR):
+ $(MKDIRTREE) $(COMPILER_TARGETDIR)
+%$(PPUEXT): %.pp
+ $(COMPILER) $<
+ $(EXECPPAS)
+%$(PPUEXT): %.pas
+ $(COMPILER) $<
+ $(EXECPPAS)
+%$(EXEEXT): %.pp
+ $(COMPILER) $<
+ $(EXECPPAS)
+%$(EXEEXT): %.pas
+ $(COMPILER) $<
+ $(EXECPPAS)
+%$(EXEEXT): %.lpr
+ $(COMPILER) $<
+ $(EXECPPAS)
+%$(EXEEXT): %.dpr
+ $(COMPILER) $<
+ $(EXECPPAS)
+%.res: %.rc
+ windres -i $< -o $@
+vpath %.pp $(COMPILER_SOURCEDIR) $(COMPILER_INCLUDEDIR)
+vpath %.pas $(COMPILER_SOURCEDIR) $(COMPILER_INCLUDEDIR)
+vpath %.lpr $(COMPILER_SOURCEDIR) $(COMPILER_INCLUDEDIR)
+vpath %.dpr $(COMPILER_SOURCEDIR) $(COMPILER_INCLUDEDIR)
+vpath %.inc $(COMPILER_INCLUDEDIR)
+vpath %$(OEXT) $(COMPILER_UNITTARGETDIR)
+vpath %$(PPUEXT) $(COMPILER_UNITTARGETDIR)
+.PHONY: fpc_shared
+override INSTALLTARGET+=fpc_shared_install
+ifndef SHARED_LIBVERSION
+SHARED_LIBVERSION=$(FPC_VERSION)
+endif
+ifndef SHARED_LIBNAME
+SHARED_LIBNAME=$(PACKAGE_NAME)
+endif
+ifndef SHARED_FULLNAME
+SHARED_FULLNAME=$(SHAREDLIBPREFIX)$(SHARED_LIBNAME)-$(SHARED_LIBVERSION)$(SHAREDLIBEXT)
+endif
+ifndef SHARED_LIBUNITS
+SHARED_LIBUNITS:=$(TARGET_UNITS) $(TARGET_IMPLICITUNITS)
+override SHARED_LIBUNITS:=$(filter-out $(INSTALL_BUILDUNIT),$(SHARED_LIBUNITS))
+endif
+fpc_shared:
+ifdef HASSHAREDLIB
+ $(MAKE) all CREATESHARED=1 LINKSHARED=1 CREATESMART=1
+ifneq ($(SHARED_BUILD),n)
+ $(PPUMOVE) -q $(SHARED_LIBUNITS) -i$(COMPILER_UNITTARGETDIR) -o$(SHARED_FULLNAME) -d$(COMPILER_UNITTARGETDIR)
+endif
+else
+ @$(ECHO) Shared Libraries not supported
+endif
+fpc_shared_install:
+ifneq ($(SHARED_BUILD),n)
+ifneq ($(SHARED_LIBUNITS),)
+ifneq ($(wildcard $(COMPILER_UNITTARGETDIR)/$(SHARED_FULLNAME)),)
+ $(INSTALL) $(COMPILER_UNITTARGETDIR)/$(SHARED_FULLNAME) $(INSTALL_SHAREDDIR)
+endif
+endif
+endif
+.PHONY: fpc_install fpc_sourceinstall fpc_exampleinstall
+ifdef INSTALL_UNITS
+override INSTALLPPUFILES+=$(addsuffix $(PPUEXT),$(INSTALL_UNITS))
+endif
+ifdef INSTALL_BUILDUNIT
+override INSTALLPPUFILES:=$(filter-out $(INSTALL_BUILDUNIT)$(PPUEXT),$(INSTALLPPUFILES))
+endif
+ifdef INSTALLPPUFILES
+override INSTALLPPULINKFILES:=$(subst $(PPUEXT),$(OEXT),$(INSTALLPPUFILES)) $(addprefix $(STATICLIBPREFIX),$(subst $(PPUEXT),$(STATICLIBEXT),$(INSTALLPPUFILES))) $(addprefix $(IMPORTLIBPREFIX),$(subst $(PPUEXT),$(STATICLIBEXT),$(INSTALLPPUFILES)))
+ifneq ($(UNITTARGETDIRPREFIX),)
+override INSTALLPPUFILES:=$(addprefix $(UNITTARGETDIRPREFIX),$(notdir $(INSTALLPPUFILES)))
+override INSTALLPPULINKFILES:=$(wildcard $(addprefix $(UNITTARGETDIRPREFIX),$(notdir $(INSTALLPPULINKFILES))))
+endif
+override INSTALL_CREATEPACKAGEFPC=1
+endif
+ifdef INSTALLEXEFILES
+ifneq ($(TARGETDIRPREFIX),)
+override INSTALLEXEFILES:=$(addprefix $(TARGETDIRPREFIX),$(notdir $(INSTALLEXEFILES)))
+endif
+endif
+fpc_install: all $(INSTALLTARGET)
+ifdef INSTALLEXEFILES
+ $(MKDIR) $(INSTALL_BINDIR)
+ifdef UPXPROG
+ -$(UPXPROG) $(INSTALLEXEFILES)
+endif
+ $(INSTALLEXE) $(INSTALLEXEFILES) $(INSTALL_BINDIR)
+endif
+ifdef INSTALL_CREATEPACKAGEFPC
+ifdef FPCMAKE
+ifdef PACKAGE_VERSION
+ifneq ($(wildcard Makefile.fpc),)
+ $(FPCMAKE) -p -T$(CPU_TARGET)-$(OS_TARGET) Makefile.fpc
+ $(MKDIR) $(INSTALL_UNITDIR)
+ $(INSTALL) Package.fpc $(INSTALL_UNITDIR)
+endif
+endif
+endif
+endif
+ifdef INSTALLPPUFILES
+ $(MKDIR) $(INSTALL_UNITDIR)
+ $(INSTALL) $(INSTALLPPUFILES) $(INSTALL_UNITDIR)
+ifneq ($(INSTALLPPULINKFILES),)
+ $(INSTALL) $(INSTALLPPULINKFILES) $(INSTALL_UNITDIR)
+endif
+ifneq ($(wildcard $(LIB_FULLNAME)),)
+ $(MKDIR) $(INSTALL_LIBDIR)
+ $(INSTALL) $(LIB_FULLNAME) $(INSTALL_LIBDIR)
+ifdef inUnix
+ ln -sf $(LIB_FULLNAME) $(INSTALL_LIBDIR)/$(LIB_NAME)
+endif
+endif
+endif
+ifdef INSTALL_FILES
+ $(MKDIR) $(INSTALL_DATADIR)
+ $(INSTALL) $(INSTALL_FILES) $(INSTALL_DATADIR)
+endif
+fpc_sourceinstall: distclean
+ $(MKDIR) $(INSTALL_SOURCEDIR)
+ $(COPYTREE) $(BASEDIR)/* $(INSTALL_SOURCEDIR)
+fpc_exampleinstall: $(addsuffix _distclean,$(TARGET_EXAMPLEDIRS))
+ifdef HASEXAMPLES
+ $(MKDIR) $(INSTALL_EXAMPLEDIR)
+endif
+ifdef EXAMPLESOURCEFILES
+ $(COPY) $(EXAMPLESOURCEFILES) $(INSTALL_EXAMPLEDIR)
+endif
+ifdef TARGET_EXAMPLEDIRS
+ $(COPYTREE) $(addsuffix /*,$(TARGET_EXAMPLEDIRS)) $(INSTALL_EXAMPLEDIR)
+endif
+.PHONY: fpc_clean fpc_cleanall fpc_distclean
+ifdef EXEFILES
+override CLEANEXEFILES:=$(addprefix $(TARGETDIRPREFIX),$(CLEANEXEFILES))
+override CLEANEXEDBGFILES:=$(addprefix $(TARGETDIRPREFIX),$(CLEANEXEDBGFILES))
+endif
+ifdef CLEAN_PROGRAMS
+override CLEANEXEFILES+=$(addprefix $(TARGETDIRPREFIX),$(addsuffix $(EXEEXT), $(CLEAN_PROGRAMS)))
+override CLEANEXEDBGFILES+=$(addprefix $(TARGETDIRPREFIX),$(addsuffix $(EXEDBGEXT), $(CLEAN_PROGRAMS)))
+endif
+ifdef CLEAN_UNITS
+override CLEANPPUFILES+=$(addsuffix $(PPUEXT),$(CLEAN_UNITS))
+endif
+ifdef CLEANPPUFILES
+override CLEANPPULINKFILES:=$(subst $(PPUEXT),$(OEXT),$(CLEANPPUFILES)) $(addprefix $(STATICLIBPREFIX),$(subst $(PPUEXT),$(STATICLIBEXT),$(CLEANPPUFILES))) $(addprefix $(IMPORTLIBPREFIX),$(subst $(PPUEXT),$(STATICLIBEXT),$(CLEANPPUFILES)))
+ifdef DEBUGSYMEXT
+override CLEANPPULINKFILES+=$(subst $(PPUEXT),$(DEBUGSYMEXT),$(CLEANPPUFILES))
+endif
+override CLEANPPUFILES:=$(addprefix $(UNITTARGETDIRPREFIX),$(CLEANPPUFILES))
+override CLEANPPULINKFILES:=$(wildcard $(addprefix $(UNITTARGETDIRPREFIX),$(CLEANPPULINKFILES)))
+endif
+fpc_clean: $(CLEANTARGET)
+ifdef CLEANEXEFILES
+ -$(DEL) $(CLEANEXEFILES)
+endif
+ifdef CLEANEXEDBGFILES
+ -$(DELTREE) $(CLEANEXEDBGFILES)
+endif
+ifdef CLEANPPUFILES
+ -$(DEL) $(CLEANPPUFILES)
+endif
+ifneq ($(CLEANPPULINKFILES),)
+ -$(DEL) $(CLEANPPULINKFILES)
+endif
+ifdef CLEANRSTFILES
+ -$(DEL) $(addprefix $(UNITTARGETDIRPREFIX),$(CLEANRSTFILES))
+endif
+ifdef CLEAN_FILES
+ -$(DEL) $(CLEAN_FILES)
+endif
+ifdef LIB_NAME
+ -$(DEL) $(LIB_NAME) $(LIB_FULLNAME)
+endif
+ -$(DEL) $(FPCMADE) Package.fpc $(PPAS) script.res link.res $(FPCEXTFILE) $(REDIRFILE)
+ -$(DEL) *$(ASMEXT) *_ppas$(BATCHEXT)
+fpc_cleanall: $(CLEANTARGET)
+ifdef CLEANEXEFILES
+ -$(DEL) $(CLEANEXEFILES)
+endif
+ifdef COMPILER_UNITTARGETDIR
+ifdef CLEANPPUFILES
+ -$(DEL) $(CLEANPPUFILES)
+endif
+ifneq ($(CLEANPPULINKFILES),)
+ -$(DEL) $(CLEANPPULINKFILES)
+endif
+ifdef CLEANRSTFILES
+ -$(DEL) $(addprefix $(UNITTARGETDIRPREFIX),$(CLEANRSTFILES))
+endif
+endif
+ifdef CLEAN_FILES
+ -$(DEL) $(CLEAN_FILES)
+endif
+ -$(DELTREE) units
+ -$(DEL) *$(OEXT) *$(PPUEXT) *$(RSTEXT) *$(ASMEXT) *$(STATICLIBEXT) *$(SHAREDLIBEXT) *$(PPLEXT)
+ifneq ($(PPUEXT),.ppu)
+ -$(DEL) *.o *.ppu *.a
+endif
+ -$(DELTREE) *$(SMARTEXT)
+ -$(DEL) fpcmade.* Package.fpc $(PPAS) script.res link.res $(FPCEXTFILE) $(REDIRFILE)
+ -$(DEL) *_ppas$(BATCHEXT)
+ifdef AOUTEXT
+ -$(DEL) *$(AOUTEXT)
+endif
+ifdef DEBUGSYMEXT
+ -$(DEL) *$(DEBUGSYMEXT)
+endif
+fpc_distclean: cleanall
+.PHONY: fpc_baseinfo
+override INFORULES+=fpc_baseinfo
+fpc_baseinfo:
+ @$(ECHO)
+ @$(ECHO) == Package info ==
+ @$(ECHO) Package Name..... $(PACKAGE_NAME)
+ @$(ECHO) Package Version.. $(PACKAGE_VERSION)
+ @$(ECHO)
+ @$(ECHO) == Configuration info ==
+ @$(ECHO)
+ @$(ECHO) FPC.......... $(FPC)
+ @$(ECHO) FPC Version.. $(FPC_VERSION)
+ @$(ECHO) Source CPU... $(CPU_SOURCE)
+ @$(ECHO) Target CPU... $(CPU_TARGET)
+ @$(ECHO) Source OS.... $(OS_SOURCE)
+ @$(ECHO) Target OS.... $(OS_TARGET)
+ @$(ECHO) Full Source.. $(FULL_SOURCE)
+ @$(ECHO) Full Target.. $(FULL_TARGET)
+ @$(ECHO) SourceSuffix. $(SOURCESUFFIX)
+ @$(ECHO) TargetSuffix. $(TARGETSUFFIX)
+ @$(ECHO) FPC fpmake... $(FPCFPMAKE)
+ @$(ECHO)
+ @$(ECHO) == Directory info ==
+ @$(ECHO)
+ @$(ECHO) Required pkgs... $(REQUIRE_PACKAGES)
+ @$(ECHO)
+ @$(ECHO) Basedir......... $(BASEDIR)
+ @$(ECHO) FPCDir.......... $(FPCDIR)
+ @$(ECHO) CrossBinDir..... $(CROSSBINDIR)
+ @$(ECHO) UnitsDir........ $(UNITSDIR)
+ @$(ECHO) PackagesDir..... $(PACKAGESDIR)
+ @$(ECHO)
+ @$(ECHO) GCC library..... $(GCCLIBDIR)
+ @$(ECHO) Other library... $(OTHERLIBDIR)
+ @$(ECHO)
+ @$(ECHO) == Tools info ==
+ @$(ECHO)
+ @$(ECHO) As........ $(AS)
+ @$(ECHO) Ld........ $(LD)
+ @$(ECHO) Ar........ $(AR)
+ @$(ECHO) Rc........ $(RC)
+ @$(ECHO)
+ @$(ECHO) Mv........ $(MVPROG)
+ @$(ECHO) Cp........ $(CPPROG)
+ @$(ECHO) Rm........ $(RMPROG)
+ @$(ECHO) GInstall.. $(GINSTALL)
+ @$(ECHO) Echo...... $(ECHO)
+ @$(ECHO) Shell..... $(SHELL)
+ @$(ECHO) Date...... $(DATE)
+ @$(ECHO) FPCMake... $(FPCMAKE)
+ @$(ECHO) PPUMove... $(PPUMOVE)
+ @$(ECHO) Upx....... $(UPXPROG)
+ @$(ECHO) Zip....... $(ZIPPROG)
+ @$(ECHO)
+ @$(ECHO) == Object info ==
+ @$(ECHO)
+ @$(ECHO) Target Loaders........ $(TARGET_LOADERS)
+ @$(ECHO) Target Units.......... $(TARGET_UNITS)
+ @$(ECHO) Target Implicit Units. $(TARGET_IMPLICITUNITS)
+ @$(ECHO) Target Programs....... $(TARGET_PROGRAMS)
+ @$(ECHO) Target Dirs........... $(TARGET_DIRS)
+ @$(ECHO) Target Examples....... $(TARGET_EXAMPLES)
+ @$(ECHO) Target ExampleDirs.... $(TARGET_EXAMPLEDIRS)
+ @$(ECHO)
+ @$(ECHO) Clean Units......... $(CLEAN_UNITS)
+ @$(ECHO) Clean Files......... $(CLEAN_FILES)
+ @$(ECHO)
+ @$(ECHO) Install Units....... $(INSTALL_UNITS)
+ @$(ECHO) Install Files....... $(INSTALL_FILES)
+ @$(ECHO)
+ @$(ECHO) == Install info ==
+ @$(ECHO)
+ @$(ECHO) DateStr.............. $(DATESTR)
+ @$(ECHO) ZipName.............. $(ZIPNAME)
+ @$(ECHO) ZipPrefix............ $(ZIPPREFIX)
+ @$(ECHO) ZipCrossPrefix....... $(ZIPCROSSPREFIX)
+ @$(ECHO) ZipSuffix............ $(ZIPSUFFIX)
+ @$(ECHO) FullZipName.......... $(FULLZIPNAME)
+ @$(ECHO) Install FPC Package.. $(INSTALL_FPCPACKAGE)
+ @$(ECHO)
+ @$(ECHO) Install base dir..... $(INSTALL_BASEDIR)
+ @$(ECHO) Install binary dir... $(INSTALL_BINDIR)
+ @$(ECHO) Install library dir.. $(INSTALL_LIBDIR)
+ @$(ECHO) Install units dir.... $(INSTALL_UNITDIR)
+ @$(ECHO) Install source dir... $(INSTALL_SOURCEDIR)
+ @$(ECHO) Install doc dir...... $(INSTALL_DOCDIR)
+ @$(ECHO) Install example dir.. $(INSTALL_EXAMPLEDIR)
+ @$(ECHO) Install data dir..... $(INSTALL_DATADIR)
+ @$(ECHO)
+ @$(ECHO) Dist destination dir. $(DIST_DESTDIR)
+ @$(ECHO) Dist zip name........ $(DIST_ZIPNAME)
+ @$(ECHO)
+.PHONY: fpc_info
+fpc_info: $(INFORULES)
+.PHONY: fpc_makefile fpc_makefiles fpc_makefile_sub1 fpc_makefile_sub2 \
+ fpc_makefile_dirs
+fpc_makefile:
+ $(FPCMAKE) -w -T$(OS_TARGET) Makefile.fpc
+fpc_makefile_sub1:
+ifdef TARGET_DIRS
+ $(FPCMAKE) -w -T$(OS_TARGET) $(addsuffix /Makefile.fpc,$(TARGET_DIRS))
+endif
+ifdef TARGET_EXAMPLEDIRS
+ $(FPCMAKE) -w -T$(OS_TARGET) $(addsuffix /Makefile.fpc,$(TARGET_EXAMPLEDIRS))
+endif
+fpc_makefile_sub2: $(addsuffix _makefile_dirs,$(TARGET_DIRS) $(TARGET_EXAMPLEDIRS))
+fpc_makefile_dirs: fpc_makefile_sub1 fpc_makefile_sub2
+fpc_makefiles: fpc_makefile fpc_makefile_dirs
+ifndef DATA2INC
+DATA2INC:=$(strip $(wildcard $(addsuffix /data2inc$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(DATA2INC),)
+DATA2INC= __missing_command_DATA2INC
+else
+DATA2INC:=$(firstword $(DATA2INC))
+endif
+endif
+export DATA2INC
+all: fpc_all
+debug: fpc_debug
+smart: fpc_smart
+release: fpc_release
+units: fpc_units
+examples:
+shared: fpc_shared
+install: fpc_install
+sourceinstall: fpc_sourceinstall
+exampleinstall: fpc_exampleinstall
+distinstall:
+zipinstall:
+zipsourceinstall:
+zipexampleinstall:
+zipdistinstall:
+clean: fpc_clean
+distclean: fpc_distclean
+cleanall: fpc_cleanall
+info: fpc_info
+makefiles: fpc_makefiles
+.PHONY: all debug smart release units examples shared install sourceinstall exampleinstall distinstall zipinstall zipsourceinstall zipexampleinstall zipdistinstall clean distclean cleanall info makefiles
+ifneq ($(wildcard fpcmake.loc),)
+include fpcmake.loc
+endif
+.NOTPARALLEL:
+REG_SOURCES=$(wildcard *reg.pp)
+REG_EXES=$(subst .pp,$(EXEEXT),$(REG_SOURCES))
+ifndef NOCPUDEF
+ppu$(PPUEXT): ../ppu.pas
+ $(MAKE) ppu$(PPUEXT) NOCPUDEF=1
+ppudump$(EXEEXT): ppudump.pp ppu$(PPUEXT)
+ $(MAKE) ppudump$(EXEEXT) NOCPUDEF=1
+ppufiles$(EXEEXT): ppufiles.pp ppu$(PPUEXT)
+ $(MAKE) ppufiles$(EXEEXT) NOCPUDEF=1
+ppumove$(EXEEXT): ppumove.pp ppu$(PPUEXT)
+ $(MAKE) ppumove$(EXEEXT) NOCPUDEF=1
+else
+ppu$(PPUEXT): ../ppu.pas
+ $(COMPILER) ../ppu.pas -Fu../generic -dGENERIC_CPU -Fi..
+ppudump$(EXEEXT): ppudump.pp ppu$(PPUEXT)
+ $(COMPILER) ppudump.pp -Fu../generic -dGENERIC_CPU -Fi..
+ppufiles$(EXEEXT): ppufiles.pp ppu$(PPUEXT)
+ $(COMPILER) ppufiles.pp -Fu../generic -dGENERIC_CPU -Fi..
+ppumove$(EXEEXT): ppumove.pp ppu$(PPUEXT)
+ $(COMPILER) ppumove.pp -Fu../generic -dGENERIC_CPU -Fi..
+endif
+msg2inc$(EXEEXT): $(COMPILER_UNITTARGETDIR) msg2inc.pp
+fpcsubst$(EXEEXT): fpcsubst.pp usubst.pp
+fpcmkcfg$(EXEEXT): fpcmkcfg.pp usubst.pp fpccfg.inc fpcfg.inc fpini.inc
+ifneq ($(DATA2INC),)
+fpccfg.inc: fpc.cft
+ $(DATA2INC) -b -s fpc.cft fpccfg.inc DefaultConfig
+fpcfg.inc : fpinc.cfg
+ $(DATA2INC) -b -s fpinc.cfg fpcfg.inc fpcfg
+fpini.inc : fpinc.ini
+ $(DATA2INC) -b -s fpinc.ini fpini.inc fpini
+endif
+reg_exes: $(COMPILER_UNITTARGETDIR)
+ $(MAKE) $(REG_EXES)
+unexport PPUFILES PPUMOVE
diff --git a/closures/compiler/utils/Makefile.fpc b/closures/compiler/utils/Makefile.fpc
new file mode 100644
index 0000000000..4073cc61f1
--- /dev/null
+++ b/closures/compiler/utils/Makefile.fpc
@@ -0,0 +1,93 @@
+#
+# Makefile.fpc for Free Pascal Compiler Utils
+#
+
+[target]
+programs=fpc ppufiles ppudump ppumove fpcsubst mkarmins mkx86ins
+rst=fpcsubst
+
+[clean]
+units=ppu crc usubst
+
+[compiler]
+unitdir=..
+sourcedir=..
+
+[install]
+fpcpackage=y
+
+[require]
+tools=data2inc
+
+[default]
+fpcdir=../..
+
+[shared]
+build=n
+
+[rules]
+#
+# PPU Tools
+#
+
+# not parallel because systems using an external linker will get conflicts
+# due to overwriting each other's link.res file
+.NOTPARALLEL:
+
+REG_SOURCES=$(wildcard *reg.pp)
+REG_EXES=$(subst .pp,$(EXEEXT),$(REG_SOURCES))
+
+ifndef NOCPUDEF
+ppu$(PPUEXT): ../ppu.pas
+ $(MAKE) ppu$(PPUEXT) NOCPUDEF=1
+
+ppudump$(EXEEXT): ppudump.pp ppu$(PPUEXT)
+ $(MAKE) ppudump$(EXEEXT) NOCPUDEF=1
+
+ppufiles$(EXEEXT): ppufiles.pp ppu$(PPUEXT)
+ $(MAKE) ppufiles$(EXEEXT) NOCPUDEF=1
+
+ppumove$(EXEEXT): ppumove.pp ppu$(PPUEXT)
+ $(MAKE) ppumove$(EXEEXT) NOCPUDEF=1
+
+else
+ppu$(PPUEXT): ../ppu.pas
+ $(COMPILER) ../ppu.pas -Fu../generic -dGENERIC_CPU -Fi..
+
+ppudump$(EXEEXT): ppudump.pp ppu$(PPUEXT)
+ $(COMPILER) ppudump.pp -Fu../generic -dGENERIC_CPU -Fi..
+
+ppufiles$(EXEEXT): ppufiles.pp ppu$(PPUEXT)
+ $(COMPILER) ppufiles.pp -Fu../generic -dGENERIC_CPU -Fi..
+
+ppumove$(EXEEXT): ppumove.pp ppu$(PPUEXT)
+ $(COMPILER) ppumove.pp -Fu../generic -dGENERIC_CPU -Fi..
+
+endif
+
+msg2inc$(EXEEXT): $(COMPILER_UNITTARGETDIR) msg2inc.pp
+
+fpcsubst$(EXEEXT): fpcsubst.pp usubst.pp
+
+fpcmkcfg$(EXEEXT): fpcmkcfg.pp usubst.pp fpccfg.inc fpcfg.inc fpini.inc
+
+ifneq ($(DATA2INC),)
+fpccfg.inc: fpc.cft
+ $(DATA2INC) -b -s fpc.cft fpccfg.inc DefaultConfig
+
+fpcfg.inc : fpinc.cfg
+ $(DATA2INC) -b -s fpinc.cfg fpcfg.inc fpcfg
+
+fpini.inc : fpinc.ini
+ $(DATA2INC) -b -s fpinc.ini fpini.inc fpini
+endif
+
+reg_exes: $(COMPILER_UNITTARGETDIR)
+ $(MAKE) $(REG_EXES)
+
+#
+# Don't export some tools, which are found in the current dir if it's in
+# the path, so are not valid for the subdirs
+#
+
+unexport PPUFILES PPUMOVE
diff --git a/closures/compiler/utils/README.txt b/closures/compiler/utils/README.txt
new file mode 100644
index 0000000000..4c9cc52948
--- /dev/null
+++ b/closures/compiler/utils/README.txt
@@ -0,0 +1,20 @@
+This directory contains some utilities that are used during the
+development of the Free Pascal Compiler.
+
+msg2inc : Convert a compiler message file (errorX.msg) to .inc files to
+ include it as the default language in the compiler. It can
+ also convert the .msg to .tex for inclusion the documentation
+
+nasmconv : Convert a Nasm insns.dat to i386tab.inc so it can be used with
+ the compiler
+
+makecfg : This script will make the samplecfg for linux installations
+
+msgdif : analyzes the differences between two msg files
+ msgdif errore.msg errord.msg
+ will print out new error msg, removed old ones
+ and will create a new file new.msg that will
+ contain the new error messages (supposing TeX comment is after
+ the message line itself)
+ removed messages are prepended by "%%% "
+ (they can be useful in case on error enum renaming !)
diff --git a/closures/compiler/utils/dummyas.pp b/closures/compiler/utils/dummyas.pp
new file mode 100644
index 0000000000..922acc3091
--- /dev/null
+++ b/closures/compiler/utils/dummyas.pp
@@ -0,0 +1,112 @@
+{
+ This file is part of the Free Pascal run time library.
+ Copyright (c) 2007 by Pierre Muller
+ member of the Free Pascal development team.
+
+ Dummy assembler program to be able to easily test
+ all FPC targets even without cross tools.
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+program dummyas;
+
+var
+ assembler_name : string;
+ object_name : string;
+ ofile : text;
+
+function RemoveSuffix(const st : string) : string;
+var
+ i,last : longint;
+begin
+ last:=length(st);
+ for i:=length(st) downto 1 do
+ begin
+ if st[i]='.' then
+ begin
+ last:=i-1;
+ break;
+ end;
+ end;
+ RemoveSuffix:=Copy(st,1,last);
+end;
+
+var
+ i : longint;
+ param : string;
+ skipnext : boolean;
+begin
+ object_name:='';
+ skipnext:=false;
+ for i:=1 to ParamCount do
+ begin
+ param:=Paramstr(i);
+ if skipnext or (length(Param)=0) then
+ begin
+ skipnext:=false;
+ continue;
+ end;
+ if Param='-o' then
+ begin
+ skipnext:=true;
+ object_name:=ParamStr(i+1);
+ end
+ else if (Param[1]='-') then
+ begin
+ { option Param not handled }
+ { Shouldn't be a real problem }
+ end
+ else
+ begin
+ if assembler_name='' then
+ assembler_name:=ParamStr(i)
+ else
+ begin
+ Writeln(stderr,'two non option param found!');
+ Writeln(stderr,'first non option param =',assembler_name);
+ Writeln(stderr,'second non option param =',Param);
+ Writeln(stderr,'Don''t know how to handle this!');
+ halt(1);
+ end;
+ end;
+ end;
+
+ if assembler_name='' then
+ begin
+ Writeln(stderr,'Dummyas, no source file specified');
+ halt(1);
+ end;
+ Assign(ofile,assembler_name);
+{$push}{$I-}
+ Reset(ofile);
+ if IOResult<>0 then
+ begin
+ Writeln(stderr,'Dummyas, source file not found ',assembler_name);
+ halt(1);
+ end;
+ Close(ofile);
+ if object_name='' then
+ object_name:=RemoveSuffix(assembler_name)+'.o';
+ Assign(ofile,object_name);
+ Rewrite(ofile);
+ if IOResult<>0 then
+ begin
+ Writeln(stderr,'Dummyas, object file not writable ',object_name);
+ halt(1);
+ end;
+ Writeln(ofile,'Dummy as called');
+ for i:=0 to Paramcount do
+ Write(ofile,ParamStr(i),' ');
+ Writeln(ofile);
+ Writeln(ofile,'assembler file=',assembler_name);
+ Writeln(ofile,'object file=',object_name);
+ Close(ofile);
+{$pop}
+end.
diff --git a/closures/compiler/utils/fixlog.pp b/closures/compiler/utils/fixlog.pp
new file mode 100644
index 0000000000..750b628878
--- /dev/null
+++ b/closures/compiler/utils/fixlog.pp
@@ -0,0 +1,174 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ Remove all revision logs from source files after X revisions or
+ older than date X
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+program fixlog;
+
+{$mode objfpc}
+{$H+}
+
+uses
+ sysutils;
+
+const
+ bufsize = 32*1024;
+
+var
+ maxrevs,myear,mmonth,mday : integer;
+
+procedure Date2Int(const date:string;var year,month,day:integer);
+begin
+ year:=StrToInt(Copy(date,1,4));
+ month:=StrToInt(Copy(date,6,2));
+ day:=StrToInt(Copy(date,9,2));
+ if (year=0) or (month=0) or (day=0) then
+ begin
+ writeln('wrong date "',date,'", use yyyy/mm/dd');
+ halt(2);
+ end;
+end;
+
+
+procedure dofile(const fn:string);
+var
+ t,f : text;
+ s : string;
+ skip, truncated : boolean;
+ year,month,day,
+ found,revs,i : integer;
+ fbuf,tbuf : pointer;
+begin
+ getmem(fbuf,bufsize);
+ getmem(tbuf,bufsize);
+ write('processing ',fn,': ');
+ assign(t,fn);
+ assign(f,'fixlog.tmp');
+ {$push}{$I-}
+ reset(t);
+ {$pop}
+ if ioresult<>0 then
+ begin
+ writeln('error!');
+ exit;
+ end;
+ rewrite(f);
+ settextbuf(t,tbuf^,bufsize);
+ settextbuf(f,fbuf^,bufsize);
+ found:=0;
+ revs:=0;
+ skip:=false;
+ truncated:=false;
+ while not eof(t) do
+ begin
+ readln(t,s);
+ case found of
+ 0 :
+ begin
+ if pos('$Log: ',s)>0 then
+ found:=1;
+ skip:=false;
+ writeln(f,s);
+ end;
+ 1 :
+ begin
+ i:=pos('Revision',s);
+ if i>0 then
+ begin
+ inc(revs);
+ if revs>maxrevs then
+ begin
+ skip:=true;
+ truncated:=true;
+ found:=2;
+ end
+ else
+ begin
+ inc(i,10);
+ while (i<length(s)) and (s[i]<>' ') do
+ inc(i);
+ while (i<length(s)) and (s[i]=' ') do
+ inc(i);
+ if (i<length(s)) and (s[i] in ['0'..'9']) then
+ begin
+ Date2Int(Copy(s,i,10),year,month,day);
+ if (year<Myear) or
+ ((year=MYear) and (month<Mmonth)) or
+ ((year=MYear) and (month=Mmonth) and (day<Mday)) then
+ begin
+ skip:=true;
+ truncated:=true;
+ found:=2;
+// write(year,'/',month,'/',day,' date');
+ end;
+ end;
+ end;
+ end
+ else
+ if pos('}',s)>0 then
+ begin
+ skip:=false;
+ found:=0;
+ end;
+ if not skip then
+ writeln(f,s);
+ end;
+ 2 :
+ begin
+ if pos('}',s)>0 then
+ begin
+ skip:=false;
+ found:=0;
+ end;
+ if not skip then
+ writeln(f,s);
+ end;
+ end;
+ end;
+ close(t);
+ close(f);
+ if revs=0 then
+ writeln(' no log found')
+ else
+ if truncated then
+ writeln(revs-1,' revisions')
+ else
+ writeln(revs,' revisions');
+ erase(t);
+ rename(f,fn);
+ freemem(tbuf);
+ freemem(fbuf);
+end;
+
+var
+ dir : tsearchrec;
+ i : integer;
+ path : string;
+begin
+ writeln('fixlog v1.01 (C) 1999-2002 Peter Vreman');
+ if paramcount<3 then
+ begin
+ writeln('usage: fixlog <revisions> <yyyy-mm-dd> <files> [files]');
+ halt(1);
+ end;
+ MaxRevs:=StrToInt(ParamStr(1));
+ Date2Int(ParamStr(2),MYear,MMonth,MDay);
+ for i:=3 to paramcount do
+ begin
+ path:=ExtractFilePath(paramstr(i));
+ if findfirst(paramstr(i),faAnyFile,dir)=0 then
+ repeat
+ dofile(path+dir.name);
+ until findnext(dir)<>0;
+ findclose(dir);
+ end;
+end.
diff --git a/closures/compiler/utils/fixmsg.pp b/closures/compiler/utils/fixmsg.pp
new file mode 100644
index 0000000000..6bd1cfbe2c
--- /dev/null
+++ b/closures/compiler/utils/fixmsg.pp
@@ -0,0 +1,66 @@
+type
+ trtabrec=record
+ name : string[12];
+ idx : longint;
+ end;
+
+const
+ trtab : array[0..10] of trtabrec=(
+ (name:'general';idx:1000),
+ (name:'scan';idx:2000),
+ (name:'parser';idx:3000),
+ (name:'type';idx:4000),
+ (name:'sym';idx:5000),
+ (name:'cg';idx:6000),
+ (name:'asmr';idx:7000),
+ (name:'asmw';idx:8000),
+ (name:'exec';idx:9000),
+ (name:'unit';idx:10000),
+ (name:'option';idx:11000)
+ );
+
+var
+ t,f : text;
+ s,hs : string;
+ i,j,k : longint;
+begin
+ assign(t,paramstr(1));
+ reset(t);
+ assign(f,'New.msg');
+ rewrite(f);
+ while not eof(t) do
+ begin
+ readln(t,s);
+ if (s<>'') and not(s[1] in ['#','%']) then
+ begin
+ for i:=0 to 10 do
+ if Copy(s,1,length(trtab[i].name))=trtab[i].name then
+ begin
+ j:=pos('=',s);
+ if j>0 then
+ begin
+ inc(j);
+ if s[j] in ['0'..'9'] then
+ begin
+ k:=j;
+ while (s[k] in ['0'..'9']) do
+ inc(k);
+ if s[k]='_' then
+ inc(k);
+ delete(s,j,k-j);
+ end;
+ str(trtab[i].idx,hs);
+ while length(hs)<5 do
+ hs:='0'+hs;
+ hs:=hs+'_';
+ inc(trtab[i].idx);
+ insert(hs,s,j);
+ end;
+ break;
+ end;
+ end;
+ writeln(f,s);
+ end;
+ close(f);
+ close(t);
+end.
diff --git a/closures/compiler/utils/fixnasm.pp b/closures/compiler/utils/fixnasm.pp
new file mode 100644
index 0000000000..4dfe67f815
--- /dev/null
+++ b/closures/compiler/utils/fixnasm.pp
@@ -0,0 +1,76 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ Convert insns.dat from Nasm to an i386ins.dat for usage with
+ the Free pascal compiler
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+program fixnasm;
+
+const
+ spaces=' ';
+var
+ t,f : text;
+ para,bytes,flags,
+ opcode,lastop,
+ s : string;
+ i,j : longint;
+begin
+ writeln('Fixing insns.dat -> i386ins.dat');
+ assign(t,'insns.dat');
+ reset(t);
+ assign(f,'insns.new');
+ rewrite(f);
+ lastop:='';
+ while not eof(t) do
+ begin
+ readln(t,s);
+ if (s<>'') and (s[1]<>';') then
+ begin
+ i:=pos(' ',s);
+ j:=pos(',',s);
+ if (j>0) and (j<i) then
+ opcode:=Copy(s,1,j-1)
+ else
+ opcode:=Copy(s,1,i-1);
+ if opcode<>lastop then
+ begin
+ writeln(f,'');
+ writeln(f,'[',Copy(s,1,i-1),']');
+ writeln(f,'(Ch_All, Ch_None, Ch_None)');
+ lastop:=opcode;
+ end;
+ while (i<length(s)) and (s[i+1]=' ') do
+ inc(i);
+ Delete(s,1,i);
+ i:=pos(' ',s);
+ para:=Copy(s,1,i-1);
+ para:=para+Copy(spaces,1,22-length(para));
+ while (i<length(s)) and (s[i+1]=' ') do
+ inc(i);
+ Delete(s,1,i);
+ i:=pos(' ',s);
+ bytes:=Copy(s,1,i-1);
+ bytes:=bytes+Copy(spaces,1,32-length(bytes));
+ while (i<length(s)) and (s[i+1]=' ') do
+ inc(i);
+ Delete(s,1,i);
+ i:=pos(' ',s);
+ if i=0 then
+ i:=255;
+ flags:=Copy(s,1,i-1);
+ writeln(f,para,bytes,flags);
+ end
+ else
+ writeln(f,s);
+ end;
+ close(f);
+ close(t);
+end.
diff --git a/closures/compiler/utils/fixtab.pp b/closures/compiler/utils/fixtab.pp
new file mode 100644
index 0000000000..4e6c14f27c
--- /dev/null
+++ b/closures/compiler/utils/fixtab.pp
@@ -0,0 +1,367 @@
+program FixTab;
+uses Dos;
+
+const
+ {Files}
+ InputExt='';
+ OutputExt='*';
+
+
+var
+{General}
+ InFile,
+ OutFile : string[80];
+ ParaFile : word;
+{Specific}
+const
+ TabSize : longint=8;
+ DosEol : boolean=false;
+ Verbose : boolean=false;
+
+{****************************************************************************
+ Routines
+****************************************************************************}
+
+const
+{$IFDEF LINUX}
+ PathCh='/';
+{$ELSE}
+ PathCh='\';
+{$ENDIF}
+
+Function SplitPath(Const HStr:String):String;
+var
+ i : byte;
+begin
+ i:=Length(Hstr);
+ while (i>0) and (Hstr[i]<>PathCh) do
+ dec(i);
+ SplitPath:=Copy(Hstr,1,i);
+end;
+
+
+
+Function SplitFileName(Const HStr:String):String;
+var
+ i : byte;
+begin
+ i:=Length(Hstr);
+ while (i>0) and (Hstr[i]<>PathCh) do
+ dec(i);
+ SplitFileName:=Copy(Hstr,i+1,255);
+end;
+
+
+
+Function SplitName(Const HStr:String):String;
+var
+ i,j : byte;
+begin
+ i:=Length(Hstr);
+ j:=i;
+ while (i>0) and (Hstr[i]<>PathCh) do
+ dec(i);
+ while (j>0) and (Hstr[j]<>'.') do
+ dec(j);
+ if j<=i then
+ j:=255;
+ SplitName:=Copy(Hstr,i+1,j-(i+1));
+end;
+
+
+
+Function SplitExtension(Const HStr:String):String;
+var
+ j,i : byte;
+begin
+ i:=Length(Hstr);
+ j:=i;
+ while (i>0) and (Hstr[i]<>PathCh) do
+ dec(i);
+ while (j>0) and (Hstr[j]<>'.') do
+ dec(j);
+ if j<=i then
+ j:=254;
+ SplitExtension:=Copy(Hstr,j+1,255);
+end;
+
+
+
+Function ChangeFileExt(Const HStr,ext:String):String;
+begin
+ if (Ext<>'') and (SplitExtension(HStr)='') then
+ ChangeFileExt:=Hstr+'.'+Ext
+ else
+ ChangeFileExt:=Hstr;
+end;
+
+
+
+Function ForceExtension(Const HStr,ext:String):String;
+var
+ j : byte;
+begin
+ j:=length(Hstr);
+ while (j>0) and (Hstr[j]<>'.') do
+ dec(j);
+ if j=0 then
+ j:=255;
+ ForceExtension:=Copy(Hstr,1,j-1)+'.'+Ext;
+end;
+
+
+function UCase(Const Hstr:string):string;
+var
+ i : byte;
+begin
+ for i:=1to Length(Hstr) do
+ UCase[i]:=Upcase(Hstr[i]);
+ UCase[0]:=chr(Length(Hstr));
+end;
+
+
+
+Function ESpace(HStr:String;len:byte):String;
+begin
+ while length(Hstr)<Len do
+ begin
+ inc(byte(Hstr[0]));
+ Hstr[Length(Hstr)]:=' ';
+ end;
+ ESpace:=Hstr;
+end;
+
+{****************************************************************************
+ Main Stuff
+****************************************************************************}
+
+var
+ Done : array[0..1023] of string[32];
+ Total : word;
+Function FileDone(const fn:string):boolean;
+var
+ i : word;
+begin
+ i:=0;
+ while (i<Total) and (Done[i]<>fn) do
+ inc(i);
+ if Done[i]=fn then
+ FileDone:=true
+ else
+ begin
+ Done[Total]:=fn;
+ inc(Total);
+ FileDone:=false;
+ end;
+end;
+
+
+
+procedure Convert(fn,nfn:string);
+type
+ inbuftype=array[0..31999] of char;
+ outbuftype=array[0..63999] of char;
+var
+ f,g : file;
+ inbuf : ^inbuftype;
+ outbuf : ^outbuftype;
+ Curr,
+ TabCol,
+ col,
+ i,last,
+ innum,
+ outnum : longint;
+
+ procedure WriteBuf;
+ begin
+ if i>last then
+ begin
+ move(InBuf^[last],OutBuf^[OutNum],i-last);
+ inc(OutNum,(i-last));
+ end;
+ Last:=i+1;
+ end;
+
+begin
+{Create New FileName}
+ if SplitExtension(nfn)='*' then
+ nfn:=ChangeFileExt(SplitPath(nfn)+SplitName(nfn),SplitExtension(fn));
+ if SplitName(nfn)='*' then
+ begin
+ if SplitPath(nfn)='' then
+ nfn:=ChangeFileExt(SplitPath(fn)+SplitName(fn),SplitExtension(nfn))
+ else
+ nfn:=ChangeFileExt(SplitPath(nfn)+SplitName(fn),SplitExtension(nfn));
+ end;
+{Done?}
+ if FileDone(nfn) then
+ exit;
+{Open Files}
+ Write('Converting '+ESpace(fn,30)+' ');
+ if fn=nfn then
+ assign(g,ForceExtension(fn,'$T$'))
+ else
+ begin
+ Write('-> '+ESpace(nfn,30)+' ');
+ assign(g,nfn);
+ end;
+ new(inbuf);
+ new(outbuf);
+ assign(f,fn);
+ {$push}{$I-}
+ reset(f,1);
+ {$pop}
+ if ioresult<>0 then
+ exit;
+ {$push}{$I-}
+ rewrite(g,1);
+ {$pop}
+ if ioresult<>0 then
+ begin
+ close(f);
+ exit;
+ end;
+ Curr:=0;
+ col:=1;
+ last:=0;
+ repeat
+ blockread(f,InBuf^,sizeof(InBufType),innum);
+ outnum:=0;
+ if innum>0 then
+ begin
+ i:=0;
+ while (i<innum) do
+ begin
+ case InBuf^[i] of
+ #9 : begin
+ WriteBuf;
+ OutBuf^[OutNum]:=' ';
+ inc(OutNum);
+ inc(Col);
+ TabCol:=(((Col-1) div TabSize)+1)*TabSize;
+ while (Col<TabCol) do
+ begin
+ OutBuf^[OutNum]:=' ';
+ inc(OutNum);
+ inc(Col);
+ end;
+ end;
+ #13 : begin
+ WriteBuf;
+ while (outnum>0) and (outbuf^[outnum-1] in [' ',#9]) do
+ dec(outnum);
+ end;
+ #10 : begin
+ WriteBuf;
+ while (outnum>0) and (outbuf^[outnum-1] in [' ',#9]) do
+ dec(outnum);
+ if DosEol then
+ begin
+ OutBuf^[OutNum]:=#13;
+ inc(OutNum);
+ end;
+ OutBuf^[OutNum]:=#10;
+ inc(OutNum);
+ col:=0;
+ inc(Curr);
+ if (curr and 31)=0 then
+ Write(Curr:5,#8#8#8#8#8);
+ end;
+ else
+ inc(col);
+ end;
+ inc(i);
+ end;
+ WriteBuf;
+ last:=0;
+ end;
+ blockwrite(g,OutBuf^,outnum);
+ until innum=0;
+ WriteLn(Curr,' Lines');
+ close(g);
+ close(f);
+ if fn=nfn then
+ begin
+ erase(f);
+ rename(g,fn);
+ end;
+ dispose(outbuf);
+ dispose(inbuf);
+end;
+
+
+{****************************************************************************
+ General Stuff
+****************************************************************************}
+
+procedure getpara;
+var
+ ch : char;
+ para : string[128];
+ i,j : word;
+
+ procedure helpscreen;
+ begin
+ writeln('Usage : '+SplitName(ParamStr(0))+' [Options] <InFile(s)>'#10);
+ writeln('<Options> can be : -O<OutFile> Specify OutFile Mask');
+ WriteLn(' -D Use MsDos #13#10 Eols');
+ writeln(' -T<size> Set Size of Tabs');
+ writeln(' -V be more verbose');
+ writeln(' -? or -H This HelpScreen');
+ halt(1);
+ end;
+
+begin
+ for i:=1to paramcount do
+ begin
+ para:=ucase(paramstr(i));
+ if (para[1]='-') then
+ begin
+ ch:=para[2];
+ delete(para,1,2);
+ case ch of
+ 'O' : OutFile:=ChangeFileExt(Para,OutputExt);
+ 'D' : DosEol:=true;
+ 'T' : Val(Para,TabSize,j);
+ 'V' : verbose:=true;
+ '?','H' : helpscreen;
+ end;
+ end
+ else
+ begin
+ if ParaFile=0 then
+ ParaFile:=i;
+ end;
+ end;
+ if (ParaFile=0) then
+ HelpScreen;
+ if OutFile='' then
+ OutFile:=ForceExtension('*',OutPutExt);
+end;
+
+
+
+var
+ Dir : SearchRec;
+ i : word;
+begin
+ GetPara;
+{Main}
+ if Verbose then
+ begin
+ Writeln('fixtab v1.01 (C) 1999-2002 Peter Vreman');
+ Writeln('TabSize ',TabSize);
+ if DosEol then
+ WriteLn('Using MsDos Eols');
+ end;
+ for i:=ParaFile to ParamCount do
+ begin
+ InFile:=ChangeFileExt(ParamStr(i),InputExt);
+ FindFirst(InFile,$20,Dir);
+ while (DosError=0) do
+ begin
+ Convert(SplitPath(InFile)+Dir.Name,OutFile);
+ FindNext(Dir);
+ end;
+ end;
+end.
diff --git a/closures/compiler/utils/fpc.mpw b/closures/compiler/utils/fpc.mpw
new file mode 100644
index 0000000000..8ae99a7ee6
--- /dev/null
+++ b/closures/compiler/utils/fpc.mpw
@@ -0,0 +1,2 @@
+# MPW script which mimics the fpc wrapper application
+ppcppc {Parameters}
diff --git a/closures/compiler/utils/fpc.pp b/closures/compiler/utils/fpc.pp
new file mode 100644
index 0000000000..c214262f10
--- /dev/null
+++ b/closures/compiler/utils/fpc.pp
@@ -0,0 +1,267 @@
+{
+ Copyright (c) 2000-2002 by Florian Klaempfl
+
+ This file is the "loader" for the Free Pascal compiler
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************}
+program fpc;
+
+{$mode objfpc}{$H+}
+
+ uses
+ Sysutils;
+
+ const
+{$ifdef UNIX}
+ exeext='';
+{$else UNIX}
+ {$ifdef AMIGA}
+ exeext='';
+ {$else}
+ {$ifdef MORPHOS}
+ exeext='';
+ {$else}
+ {$ifdef NETWARE}
+ exeext='.nlm';
+ {$else}
+ exeext='.exe';
+ {$endif NETWARE}
+ {$endif MORPHOS}
+ {$endif AMIGA}
+{$endif UNIX}
+
+
+ procedure error(const s : string);
+ begin
+ writeln('Error: ',s);
+ halt(1);
+ end;
+
+
+ function SplitPath(Const HStr:String):String;
+ var
+ i : longint;
+ begin
+ i:=Length(Hstr);
+ while (i>0) and not(Hstr[i] in ['\','/']) do
+ dec(i);
+ SplitPath:=Copy(Hstr,1,i);
+ end;
+
+
+ function FileExists ( Const F : String) : Boolean;
+ var
+ Info : TSearchRec;
+ begin
+ FileExists:= findfirst(F,fareadonly+faarchive+fahidden,info)=0;
+ findclose(Info);
+ end;
+
+ var
+ extrapath : ansistring;
+
+ function findexe(var ppcbin:string): boolean;
+ var
+ path : string;
+ begin
+ { add .exe extension }
+ findexe:=false;
+ ppcbin:=ppcbin+exeext;
+
+ if (extrapath<>'') and (extrapath[length(extrapath)]<>DirectorySeparator) then
+ extrapath:=extrapath+DirectorySeparator;
+ { get path of fpc.exe }
+ path:=splitpath(paramstr(0));
+ { don't try with an empty extra patch, this might have strange results
+ if the current directory contains a compiler
+ }
+ if (extrapath<>'') and FileExists(extrapath+ppcbin) then
+ begin
+ ppcbin:=extrapath+ppcbin;
+ findexe:=true;
+ end
+ else if FileExists(path+ppcbin) then
+ begin
+ ppcbin:=path+ppcbin;
+ findexe:=true;
+ end
+ else
+ begin
+ path:=ExeSearch(ppcbin,getenvironmentvariable('PATH'));
+ if path<>'' then
+ begin
+ ppcbin:=path;
+ findexe:=true;
+ end
+ end;
+ end;
+
+ var
+ s : ansistring;
+ cpusuffix,
+ processorname,
+ ppcbin,
+ versionStr,
+ processorstr : string;
+ ppccommandline : array of ansistring;
+ ppccommandlinelen : longint;
+ i : longint;
+ errorvalue : Longint;
+ begin
+ setlength(ppccommandline,paramcount);
+ ppccommandlinelen:=0;
+ cpusuffix :=''; // if not empty, signals attempt at cross
+ // compiler.
+ extrapath :='';
+{$ifdef i386}
+ ppcbin:='ppc386';
+ processorname:='i386';
+{$endif i386}
+{$ifdef m68k}
+ ppcbin:='ppc68k';
+ processorname:='m68k';
+{$endif m68k}
+{$ifdef alpha}
+ ppcbin:='ppcapx';
+ processorname:='alpha';
+{$endif alpha}
+{$ifdef powerpc}
+ ppcbin:='ppcppc';
+ processorname:='powerpc';
+{$endif powerpc}
+{$ifdef powerpc64}
+ ppcbin:='ppcppc64';
+ processorname:='powerpc64';
+{$endif powerpc64}
+{$ifdef arm}
+ ppcbin:='ppcarm';
+ processorname:='arm';
+{$endif arm}
+{$ifdef sparc}
+ ppcbin:='ppcsparc';
+ processorname:='sparc';
+{$endif sparc}
+{$ifdef x86_64}
+ ppcbin:='ppcx64';
+ processorname:='x86_64';
+{$endif x86_64}
+{$ifdef ia64}
+ ppcbin:='ppcia64';
+ processorname:='ia64';
+{$endif ia64}
+ versionstr:=''; { Default is just the name }
+ for i:=1 to paramcount do
+ begin
+ s:=paramstr(i);
+ if pos('-V',s)=1 then
+ versionstr:=copy(s,3,length(s)-2)
+ else
+ begin
+ if pos('-P',s)=1 then
+ begin
+ processorstr:=copy(s,3,length(s)-2);
+ { -PB is a special code that will show the
+ default compiler and exit immediatly. It's
+ main usage is for Makefile }
+ if processorstr='B' then
+ begin
+ { report the full name of the ppcbin }
+ findexe(ppcbin);
+ writeln(ppcbin);
+ halt(0);
+ end
+ { -PP is a special code that will show the
+ processor and exit immediatly. It's
+ main usage is for Makefile }
+ else if processorstr='P' then
+ begin
+ { report the processor }
+ writeln(processorname);
+ halt(0);
+ end
+ else
+ if processorstr <> processorname then
+ begin
+ if processorstr='i386' then
+ cpusuffix:='386'
+ else if processorstr='m68k' then
+ cpusuffix:='68k'
+ else if processorstr='alpha' then
+ cpusuffix:='apx'
+ else if processorstr='powerpc' then
+ cpusuffix:='ppc'
+ else if processorstr='powerpc64' then
+ cpusuffix:='ppc64'
+ else if processorstr='arm' then
+ cpusuffix:='arm'
+ else if processorstr='sparc' then
+ cpusuffix:='sparc'
+ else if processorstr='ia64' then
+ cpusuffix:='ia64'
+ else if processorstr='x86_64' then
+ cpusuffix:='x64'
+ else
+ error('Illegal processor type "'+processorstr+'"');
+
+{$ifndef darwin}
+ ppcbin:='ppcross'+cpusuffix;
+{$else not darwin}
+ { the mach-o format supports "fat" binaries whereby }
+ { a single executable contains machine code for }
+ { several architectures -> it is counter-intuitive }
+ { and non-standard to use different binary names }
+ { for cross-compilers vs. native compilers }
+ ppcbin:='ppc'+cpusuffix;
+{$endif not darwin}
+ end;
+ end
+ else if pos('-Xp',s)=1 then
+ extrapath:=copy(s,4,length(s)-3)
+ else
+ begin
+ ppccommandline[ppccommandlinelen]:=s;
+ inc(ppccommandlinelen);
+ end;
+ end;
+ end;
+ SetLength(ppccommandline,ppccommandlinelen);
+
+ if versionstr<>'' then
+ ppcbin:=ppcbin+'-'+versionstr;
+ { find the full path to the specified exe }
+ if not findexe(ppcbin) then
+ begin
+ if cpusuffix<>'' Then
+ begin
+ ppcbin:='ppc'+cpusuffix;
+ if versionstr<>'' then
+ ppcbin:=ppcbin+'-'+versionstr;
+ findexe(ppcbin);
+ end;
+ end;
+
+ { call ppcXXX }
+ try
+ errorvalue:=ExecuteProcess(ppcbin,ppccommandline);
+ except
+ on e : exception do
+ error(ppcbin+' can''t be executed, error message: '+e.message);
+ end;
+ if errorvalue<>0 then
+ error(ppcbin+' returned an error exitcode (normal if you did not specify a source file to be compiled)');
+ halt(errorvalue);
+ end.
diff --git a/closures/compiler/utils/fpcsubst.pp b/closures/compiler/utils/fpcsubst.pp
new file mode 100644
index 0000000000..df4456c6ef
--- /dev/null
+++ b/closures/compiler/utils/fpcsubst.pp
@@ -0,0 +1,243 @@
+{$Mode objfpc}
+{$H+}
+program fpcsubst;
+
+uses SysUtils,Classes,Usubst;
+
+Const
+ BuildVersion={$I %FPCVERSION%};
+ BuildTarget={$I %FPCTARGET%};
+
+Resourcestring
+ SUsage00 = 'Usage: %s [options]';
+ SUsage10 = 'Where options is one or more of';
+ SUSage20 = ' -i filename Set input file. Default is standard input';
+ SUSage30 = ' -o filename Set output file. Default is standard output.';
+ SUsage40 = ' -d name=value define name=value pair.';
+ SUsage50 = ' -h show this help and exit.';
+ SUsage60 = ' -u name remove name from list of name/value pairs.';
+ SUsage70 = ' -l filename read name/value pairs from filename';
+ SUsage80 = ' -b show builtin list and exit.';
+ SUsage90 = ' -v be verbose.';
+ SErrUnknownOption = 'Error: Unknown option.';
+ SErrArgExpected = 'Error: Option "%s" requires an argument.';
+ SErrNoSuchFile = 'Error: File "%s" does not exist.';
+ SErrBackupFailed = 'Error: Backup of file "%s" to "%s" failed.';
+ SErrDelBackupFailed = 'Error: Delete of old backup file "%s" failed.';
+ SWarnIgnoringFile = 'Warning: Ignoring non-existent file: ';
+ SWarnIgnoringPair = 'Warning: ignoring wrong name/value pair: ';
+ SStats = 'Replaced %d placeholders in %d lines.';
+ SSubstInLine = 'Replaced %s placeholders in line %d.';
+ SWarningDeprecated = 'Warning: This utility is deprecated and will be removed from fpc in the future. Please use fpcmkcfg instead.';
+
+
+Var
+ List : TStringList;
+ InputFileName : String;
+ OutputFileName : String;
+ Verbose : Boolean;
+ SkipBackup : Boolean;
+
+
+
+
+
+procedure Init;
+
+begin
+ Verbose:=False;
+ List:=TStringList.Create;
+ AddToList(List,'FPCVERSION',BuildVersion);
+ AddToList(List,'FPCTARGET',BuildTarget);
+ AddToList(List,'PWD',GetCurrentDir);
+ AddToList(List,'BUILDDATE',DateToStr(Date));
+ AddToList(List,'BUILDTIME',TimeToStr(Time));
+end;
+
+Procedure Done;
+
+begin
+ FreeAndNil(List);
+end;
+
+Procedure Usage;
+
+begin
+ Writeln(Format(SUsage00,[ExtractFileName(Paramstr(0))]));
+ Writeln(SUsage10);
+ Writeln(SUsage20);
+ Writeln(SUsage30);
+ Writeln(SUsage40);
+ Writeln(SUsage50);
+ Writeln(SUsage60);
+ Writeln(SUsage70);
+ Writeln(SUsage80);
+ Writeln(SUsage90);
+ Halt(1);
+end;
+
+Procedure ShowBuiltIns;
+
+var
+ I : Integer;
+
+begin
+ for I:=0 to List.Count-1 do
+ Writeln(List[i]);
+end;
+
+
+
+
+Procedure AddFromFile(FN : String);
+
+Var
+ F : Text;
+ S : String;
+
+begin
+ If Not FileExists(FN) then
+ begin
+ Writeln(StdErr,SWarnIgnoringFile,FN);
+ Exit;
+ end;
+ Assign(F,FN);
+ Reset(F);
+ Try
+ While not EOF(F) do
+ begin
+ ReadLn(F,S);
+ If (Length(S)>0) and (not (S[1] in ['#',';'])) then
+ If not AddPair(List,S) then
+ If Verbose then
+ Writeln(StdErr,SWarnIgnoringPair,S)
+ end;
+ finally
+ Close(F);
+ end;
+end;
+
+Procedure UnknownOption(Const S : String);
+
+begin
+ Writeln(SErrUnknownOption,S);
+ Usage;
+end;
+
+Procedure ProcessCommandline;
+
+Var
+ I : Integer;
+ S : String;
+
+ Function GetOptArg : String;
+
+ begin
+ If I=ParamCount then
+ begin
+ Writeln(StdErr,Format(SErrArgExpected,[S]));
+ Halt(1);
+ end;
+ inc(I);
+ Result:=ParamStr(I);
+ end;
+
+begin
+ I:=1;
+ While( I<=ParamCount) do
+ begin
+ S:=Paramstr(i);
+ If (Length(S)<=1) or (S[1]<>'-') then
+ UnknownOption(S)
+ else
+ case S[2] of
+ 'v' : Verbose:=True;
+ 'h' : Usage;
+ 'b' : begin
+ ShowBuiltins;
+ halt(0);
+ end;
+ 'l' : AddFromFile(GetOptArg);
+ 'd' : AddPair(List,GetOptArg);
+ 'u' : AddPair(List,GetOptArg+'=');
+ 'i' : InputFileName:=GetOptArg;
+ 'o' : OutputFileName:=GetoptArg;
+ 's' : SkipBackup:=True;
+ else
+ UnknownOption(S);
+ end;
+ Inc(I);
+ end;
+end;
+
+
+
+Procedure DoFile;
+
+Var
+ Fin,Fout : Text;
+ S,BFN : String;
+ N,LCount,RCount : Integer;
+
+
+begin
+ If (InputFileName<>'') and not FileExists(InputFIleName) then
+ begin
+ Writeln(StdErr,Format(SErrNoSuchFile,[InputFileName]));
+ Halt(1)
+ end;
+ If (OutputFileName<>'')
+ and FileExists(OutputFileName)
+ and not SkipBackup then
+ begin
+ BFN:=ChangeFileExt(OutputFileName,'.bak');
+ If FileExists(BFN) and not DeleteFile(BFN) then
+ begin
+ Writeln(StdErr,Format(SErrDelBackupFailed,[BFN]));
+ Halt(1);
+ end;
+ If not RenameFile(OutputFileName,BFN) then
+ begin
+ Writeln(StdErr,Format(SErrBackupFailed,[OutputFileName,BFN]));
+ Halt(1);
+ end;
+ end;
+ Assign(Fin,InputFileName);
+ Assign(Fout,OutputFileName);
+ Reset(Fin);
+ Try
+ Rewrite(FOut);
+ Try
+ LCount:=0;
+ RCount:=0;
+ While Not EOF(Fin) do
+ begin
+ Inc(LCount);
+ ReadLn(Fin,S);
+ N:=DoSubstitutions(List,S);
+ If Verbose and (N>0) then
+ Writeln(StdErr,Format(SSubstInLine,[N,LCount]));
+ Inc(RCount,N);
+ Writeln(Fout,S);
+ end;
+ If Verbose then
+ Writeln(StdErr,Format(SStats,[RCount,LCount]));
+ Finally
+ Close(Fout);
+ end;
+ Finally
+ Close(Fin);
+ end;
+
+end;
+
+begin
+ WriteLn(StdErr,SWarningDeprecated);
+ Init;
+ Try
+ ProcessCommandLine;
+ DoFile;
+ Finally
+ Done;
+ end;
+end.
diff --git a/closures/compiler/utils/fpimpdef.pp b/closures/compiler/utils/fpimpdef.pp
new file mode 100644
index 0000000000..c5ad40bfd8
--- /dev/null
+++ b/closures/compiler/utils/fpimpdef.pp
@@ -0,0 +1,92 @@
+{$APPTYPE CONSOLE}
+program FPimpdef;
+{$DEFINE STANDALONE}
+uses
+ DOS,
+ ImpDef;
+var
+binname:string;
+function Ofound(const short,full:string):longint;
+var
+ i:longint;
+begin
+ Ofound:=-1;
+ for i:=1 to ParamCount do
+ if(paramstr(i)=short)or(paramstr(i)=full)then
+ begin
+ Ofound:=i;
+ exit;
+ end;
+end;
+function GetOption(const short,full:string):string;
+var
+ i:longint;
+begin
+ i:=Ofound(short,full);
+ if i>0 then
+ GetOption:=paramstr(succ(i))
+ else
+ GetOption:='';
+end;
+procedure help_info;
+var
+ fn:string[255];
+ jj:cardinal;
+begin
+ fn:=paramstr(0);
+ for jj:=length(fn)downto 1 do
+ if fn[jj] in [':','\','/']then
+ begin
+ fn:=copy(fn,succ(jj),255);
+ break;
+ end;
+ writeln('Usage: ',fn,' [options]');
+ writeln('Options:');
+ writeln('-i | --input <file> - set input file;');
+ writeln('-o | --output <file> - set output .def file');
+ writeln('-l | --library <file> - set output static library');
+ writeln('-s | --assembler <name> - use <name> for assembler (default asw)');
+ writeln('-r | --archiver <name> - use <name> for archiver (default arw)');
+ writeln('-h | --help - show this screen');
+ halt;
+end;
+{$ifndef UNIX}
+procedure AddExt(var s:string);
+ var
+ s1:string;
+ i:longint;
+ begin
+ s1:=copy(s,length(s)-3,4);
+ for i:=1 to length(s1)do
+ s1[i]:=upcase(s1[i]);
+ if s1<>'.EXE'then
+ s:=s+'.EXE';
+ end;
+{$endif}
+var
+ EnvPath:string;
+begin
+binname:=GetOption('-i','--input');
+if(binname='')or(Ofound('-h','--help')>0)then
+ help_info;
+ as_name:=GetOption('-s','--assembler');
+ if as_name='' then
+ as_name:='as';
+ ar_name:=GetOption('-r','--archiver');
+ if ar_name='' then
+ ar_name:='ar';
+{$ifndef UNIX}
+ AddExt(as_name);
+ AddExt(ar_name);
+{$endif}
+ EnvPath:=GetEnv('Path');
+ if EnvPath='' then
+ EnvPath:=GetEnv('PATH');
+ as_name:=FSearch(as_name,EnvPath);
+ ar_name:=FSearch(ar_name,EnvPath);
+if not makedef(binname,GetOption('-o','--output'),GetOption('-l','--library'))then
+ begin
+ writeln('Export names not found');
+ halt(1);
+ end;
+end.
diff --git a/closures/compiler/utils/gia64reg.pp b/closures/compiler/utils/gia64reg.pp
new file mode 100644
index 0000000000..1f84bb36b5
--- /dev/null
+++ b/closures/compiler/utils/gia64reg.pp
@@ -0,0 +1,14 @@
+{ generates iA-64 register dat templates }
+
+uses
+ sysutils;
+var
+ i : longint;
+begin
+ { generate int registers }
+ for i:=0 to 127 do
+ writeln(format('R%d,$01,%d,r%d,r%d',[i,i,i,i]));
+ { generate fp registers }
+ for i:=0 to 127 do
+ writeln(format('F%d,$02,%d,r%d,r%d',[i,i,i,i]));
+end.
diff --git a/closures/compiler/utils/gppc386.pp b/closures/compiler/utils/gppc386.pp
new file mode 100644
index 0000000000..380012822d
--- /dev/null
+++ b/closures/compiler/utils/gppc386.pp
@@ -0,0 +1,195 @@
+{
+ Copyright (c) 2000-2002 by Pierre Muller
+
+ This program allows to run the Makefiles
+ with the compiler running inside GDB
+
+ GDB only stops if there is something special
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************}
+
+program fpc_with_gdb;
+
+{
+ This program uses several files :
+
+ -- 'gdb4fpc.ini' contains the standard breakpoints (see below)
+
+ -- 'gdb.fpc' is an optional file that can contain any other
+ instruction that GDB should do before starting.
+ Note that if gdb.fpc is present, no "run" command is
+ inserted if gdb4fpc.ini is found
+ but it can be inserted in gdb.fpc itself.
+
+ Use EXTDEBUG conditional to get debug information.
+}
+
+uses
+ dos;
+
+const
+{$ifdef Unix}
+ GDBExeName : String = 'gdbpas';
+ GDBAltExeName = 'gdb';
+ GDBIniName = '.gdbinit';
+ DefaultCompilerName = 'ppc386';
+ PathSep=':';
+ DirSep = '/';
+{$else}
+ GDBExeName : String = 'gdbpas.exe';
+ GDBAltExeName = 'gdb.exe';
+ GDBIniName = 'gdb.ini';
+ DefaultCompilerName = 'ppc386.exe';
+ PathSep=';';
+ DirSep = '\';
+{$endif not linux}
+
+ { If you add a gdb.fpc file in a given directory }
+ { GDB will read it; this allows you to add }
+ { special tests in specific directories PM }
+ FpcGDBIniName = 'gdb.fpc';
+ GDBIniTempName : string = 'gdb4fpc.ini';
+
+
+{ Dos/Windows GDB still need forward slashes }
+procedure AdaptToGDB(var filename : string);
+var
+ i : longint;
+begin
+ for i:=1 to length(filename) do
+ if filename[i]='\' then
+ filename[i]:='/';
+end;
+
+var
+ fpcgdbini : text;
+ CompilerName,Dir,Name,Ext : String;
+ GDBError,GDBExitCode,i : longint;
+
+begin
+
+ fsplit(paramstr(0),Dir,Name,Ext);
+ if (length(Name)>3) and (UpCase(Name[1])='G') then
+ CompilerName:=Copy(Name,2,255)+Ext
+ else
+ CompilerName:=DefaultCompilerName;
+
+ CompilerName:=fsearch(CompilerName,Dir+PathSep+GetEnv('PATH'));
+
+ { support for info functions directly : used in makefiles }
+ if (paramcount=1) and (pos('-i',Paramstr(1))=1) then
+ begin
+ Exec(CompilerName,Paramstr(1));
+ exit;
+ end;
+
+ {$ifdef EXTDEBUG}
+ writeln(stderr,'Using compiler "',CompilerName,'"');
+ flush(stderr);
+ {$endif}
+ if fsearch(GDBIniTempName,'.')<>'' then
+ begin
+ Assign(fpcgdbini,GDBIniTempName);
+ {$ifdef EXTDEBUG}
+ writeln(stderr,'Erasing file "',GDBIniTempName,'"');
+ flush(stderr);
+ {$endif}
+ erase(fpcgdbini);
+ end;
+ GDBIniTempName:=fexpand('.'+DirSep+GDBIniTempName);
+ Assign(fpcgdbini,GdbIniTempName);
+ {$ifdef EXTDEBUG}
+ writeln(stderr,'Creating file "',GDBIniTempName,'"');
+ flush(stderr);
+ {$endif}
+ Rewrite(fpcgdbini);
+
+ Writeln(fpcgdbini,'set language pascal');
+ Write(fpcgdbini,'set args');
+
+ { this will not work correctly if there are " or '' inside the command line :( }
+ for i:=1 to Paramcount do
+ begin
+ if pos(' ',Paramstr(i))>0 then
+ Write(fpcgdbini,' "'+ParamStr(i)+'"')
+ else
+ Write(fpcgdbini,' '+ParamStr(i));
+ end;
+ Writeln(fpcgdbini);
+ Writeln(fpcgdbini,'b SYSTEM_EXIT');
+ Writeln(fpcgdbini,'cond 1 EXITCODE <> 0');
+ Writeln(fpcgdbini,'set $_exitcode := -1');
+ { b INTERNALERROR sometimes fails ... Don't know why. PM 2010-08-28 }
+ Writeln(fpcgdbini,'info fun INTERNALERROR');
+ Writeln(fpcgdbini,'b INTERNALERROR');
+ Writeln(fpcgdbini,'b HANDLEERRORADDRFRAME');
+ { This one will fail unless sysutils unit is also loaded }
+ Writeln(fpcgdbini,'b RUNERRORTOEXCEPT');
+ if fsearch(FpcGDBIniName,'./')<>'' then
+ begin
+ Writeln(fpcgdbini,'source '+FpcGDBIniName);
+ end
+ else
+ Writeln(fpcgdbini,'run');
+ Writeln(fpcgdbini,'if ($_exitcode = -1)');
+ Writeln(fpcgdbini,' echo Program not completed');
+ Writeln(fpcgdbini,'else');
+ Writeln(fpcgdbini,' quit');
+ Writeln(fpcgdbini,'end');
+ Close(fpcgdbini);
+ {$ifdef EXTDEBUG}
+ writeln(stderr,'Closing file "',GDBIniTempName,'"');
+ flush(stderr);
+ {$endif}
+
+ GDBExeName:=fsearch(GDBExeName,Dir+PathSep+GetEnv('PATH'));
+ if GDBExeName='' then
+ GDBExeName:=fsearch(GDBAltExeName,Dir+PathSep+GetEnv('PATH'));
+
+ AdaptToGDB(CompilerName);
+ AdaptToGDB(GDBIniTempName);
+ {$ifdef EXTDEBUG}
+ Writeln(stderr,'Starting ',GDBExeName,
+{$ifdef win32}
+ '--nw '+
+{$endif win32}
+ '--nx --command='+GDBIniTempName+' '+CompilerName);
+ flush(stderr);
+ {$endif}
+ DosError:=0;
+ Exec(GDBExeName,
+{$ifdef win32}
+ '--nw '+
+{$endif win32}
+ '--nx --command='+GDBIniTempName+' '+CompilerName);
+ GDBError:=DosError;
+ GDBExitCode:=DosExitCode;
+ if (GDBError<>0) or (GDBExitCode<>0) then
+ begin
+ Writeln('Error running GDB');
+ if (GDBError<>0) then
+ Writeln('DosError = ',GDBError);
+ if (GDBExitCode<>0) then
+ Writeln('DosExitCode = ',GDBExitCode);
+ if GDBExitCode<>0 then
+ RunError(GDBExitCode)
+ else
+ RunError(GDBError);
+ end
+ else
+ Erase(fpcgdbini);
+end.
diff --git a/closures/compiler/utils/mk68kreg.pp b/closures/compiler/utils/mk68kreg.pp
new file mode 100644
index 0000000000..20538decdd
--- /dev/null
+++ b/closures/compiler/utils/mk68kreg.pp
@@ -0,0 +1,308 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman and Florian Klaempfl
+
+ Convert spreg.dat to several .inc files for usage with
+ the Free pascal compiler
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+{$mode objfpc}
+program mkspreg;
+
+const Version = '1.00';
+ max_regcount = 200;
+
+var s : string;
+ i : longint;
+ line : longint;
+ regcount:byte;
+ regcount_bsstart:byte;
+ names,
+ regtypes,
+ supregs,
+ numbers,
+ stdnames,
+ gasnames,
+ stabs : array[0..max_regcount-1] of string[63];
+ regnumber_index,
+ std_regname_index,gas_regname_index : array[0..max_regcount-1] of byte;
+
+function tostr(l : longint) : string;
+
+begin
+ str(l,tostr);
+end;
+
+function readstr : string;
+
+ begin
+ result:='';
+ while (s[i]<>',') and (i<=length(s)) do
+ begin
+ result:=result+s[i];
+ inc(i);
+ end;
+ end;
+
+
+procedure readcomma;
+ begin
+ if s[i]<>',' then
+ begin
+ writeln('Missing "," at line ',line);
+ writeln('Line: "',s,'"');
+ halt(1);
+ end;
+ inc(i);
+ end;
+
+
+procedure skipspace;
+
+ begin
+ while (s[i] in [' ',#9]) do
+ inc(i);
+ end;
+
+procedure openinc(out f:text;const fn:string);
+begin
+ writeln('creating ',fn);
+ assign(f,fn);
+ rewrite(f);
+ writeln(f,'{ don''t edit, this file is generated from m68kreg.dat }');
+end;
+
+
+procedure closeinc(var f:text);
+begin
+ writeln(f);
+ close(f);
+end;
+
+procedure build_regnum_index;
+
+var h,i,j,p,t:byte;
+
+begin
+ {Build the registernumber2regindex index.
+ Step 1: Fill.}
+ for i:=0 to regcount-1 do
+ regnumber_index[i]:=i;
+ {Step 2: Sort. We use a Shell-Metzner sort.}
+ p:=regcount_bsstart;
+ repeat
+ for h:=0 to regcount-p-1 do
+ begin
+ i:=h;
+ repeat
+ j:=i+p;
+ if numbers[regnumber_index[j]]>=numbers[regnumber_index[i]] then
+ break;
+ t:=regnumber_index[i];
+ regnumber_index[i]:=regnumber_index[j];
+ regnumber_index[j]:=t;
+ if i<p then
+ break;
+ dec(i,p);
+ until false;
+ end;
+ p:=p shr 1;
+ until p=0;
+end;
+
+procedure build_std_regname_index;
+
+var h,i,j,p,t:byte;
+
+begin
+ {Build the registernumber2regindex index.
+ Step 1: Fill.}
+ for i:=0 to regcount-1 do
+ std_regname_index[i]:=i;
+ {Step 2: Sort. We use a Shell-Metzner sort.}
+ p:=regcount_bsstart;
+ repeat
+ for h:=0 to regcount-p-1 do
+ begin
+ i:=h;
+ repeat
+ j:=i+p;
+ if stdnames[std_regname_index[j]]>=stdnames[std_regname_index[i]] then
+ break;
+ t:=std_regname_index[i];
+ std_regname_index[i]:=std_regname_index[j];
+ std_regname_index[j]:=t;
+ if i<p then
+ break;
+ dec(i,p);
+ until false;
+ end;
+ p:=p shr 1;
+ until p=0;
+end;
+
+procedure build_gas_regname_index;
+
+var h,i,j,p,t:byte;
+
+begin
+ {Build the registernumber2regindex index.
+ Step 1: Fill.}
+ for i:=0 to regcount-1 do
+ gas_regname_index[i]:=i;
+ {Step 2: Sort. We use a Shell-Metzner sort.}
+ p:=regcount_bsstart;
+ repeat
+ for h:=0 to regcount-p-1 do
+ begin
+ i:=h;
+ repeat
+ j:=i+p;
+ if gasnames[gas_regname_index[j]]>=gasnames[gas_regname_index[i]] then
+ break;
+ t:=gas_regname_index[i];
+ gas_regname_index[i]:=gas_regname_index[j];
+ gas_regname_index[j]:=t;
+ if i<p then
+ break;
+ dec(i,p);
+ until false;
+ end;
+ p:=p shr 1;
+ until p=0;
+end;
+
+procedure read_spreg_file;
+
+var infile:text;
+
+begin
+ { open dat file }
+ assign(infile,'m68kreg.dat');
+ reset(infile);
+ while not(eof(infile)) do
+ begin
+ { handle comment }
+ readln(infile,s);
+ inc(line);
+ while (s[1]=' ') do
+ delete(s,1,1);
+ if (s='') or (s[1]=';') then
+ continue;
+
+ i:=1;
+ names[regcount]:=readstr;
+ readcomma;
+ regtypes[regcount]:=readstr;
+ readcomma;
+ supregs[regcount]:=readstr;
+ readcomma;
+ stdnames[regcount]:=readstr;
+ readcomma;
+ gasnames[regcount]:=readstr;
+ readcomma;
+ stabs[regcount]:=readstr;
+ { Create register number }
+ if supregs[regcount][1]<>'$' then
+ begin
+ writeln('Missing $ before number, at line ',line);
+ writeln('Line: "',s,'"');
+ halt(1);
+ end;
+ numbers[regcount]:=regtypes[regcount]+'0000'+copy(supregs[regcount],2,255);
+ if i<length(s) then
+ begin
+ writeln('Extra chars at end of line, at line ',line);
+ writeln('Line: "',s,'"');
+ halt(1);
+ end;
+ inc(regcount);
+ if regcount>max_regcount then
+ begin
+ writeln('Error: Too much registers, please increase maxregcount in source');
+ halt(2);
+ end;
+ end;
+ close(infile);
+end;
+
+procedure write_inc_files;
+
+var
+ norfile,stdfile,gasfile,supfile,
+ numfile,stabfile,confile,
+ rnifile,srifile,grifile:text;
+ first:boolean;
+
+begin
+ { create inc files }
+ openinc(confile,'r68kcon.inc');
+ openinc(supfile,'r68ksup.inc');
+ openinc(numfile,'r68knum.inc');
+ openinc(stdfile,'r68kstd.inc');
+ openinc(gasfile,'r68kgas.inc');
+ openinc(stabfile,'r68ksta.inc');
+ openinc(norfile,'r68knor.inc');
+ openinc(rnifile,'r68krni.inc');
+ openinc(srifile,'r68ksri.inc');
+ openinc(grifile,'r68kgri.inc');
+ first:=true;
+ for i:=0 to regcount-1 do
+ begin
+ if not first then
+ begin
+ writeln(numfile,',');
+ writeln(stdfile,',');
+ writeln(gasfile,',');
+ writeln(stabfile,',');
+ writeln(rnifile,',');
+ writeln(srifile,',');
+ writeln(grifile,',');
+ end
+ else
+ first:=false;
+ writeln(supfile,'RS_',names[i],' = ',supregs[i],';');
+ writeln(confile,'NR_'+names[i],' = ','tregister(',numbers[i],')',';');
+ write(numfile,'tregister(',numbers[i],')');
+ write(stdfile,'''',stdnames[i],'''');
+ write(gasfile,'''',gasnames[i],'''');
+ write(stabfile,stabs[i]);
+ write(rnifile,regnumber_index[i]);
+ write(srifile,std_regname_index[i]);
+ write(grifile,gas_regname_index[i]);
+ end;
+ write(norfile,regcount);
+ close(confile);
+ close(supfile);
+ closeinc(numfile);
+ closeinc(stdfile);
+ closeinc(gasfile);
+ closeinc(stabfile);
+ closeinc(norfile);
+ closeinc(rnifile);
+ closeinc(srifile);
+ closeinc(grifile);
+ writeln('Done!');
+ writeln(regcount,' registers procesed');
+end;
+
+
+begin
+ writeln('Register Table Converter Version ',Version);
+ line:=0;
+ regcount:=0;
+ read_spreg_file;
+ regcount_bsstart:=1;
+ while 2*regcount_bsstart<regcount do
+ regcount_bsstart:=regcount_bsstart*2;
+ build_regnum_index;
+ build_std_regname_index;
+ build_gas_regname_index;
+ write_inc_files;
+end.
diff --git a/closures/compiler/utils/mkarmins.pp b/closures/compiler/utils/mkarmins.pp
new file mode 100644
index 0000000000..a9fd0a4c57
--- /dev/null
+++ b/closures/compiler/utils/mkarmins.pp
@@ -0,0 +1,404 @@
+{
+ Copyright (c) 1998-2005 by Peter Vreman and Florian Klaempfl
+
+ Convert i386ins.dat from Nasm to a .inc file for usage with
+ the Free pascal compiler
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+{$mode objfpc}
+
+program mkarmins;
+
+const
+ Version = '0.9';
+
+var
+ s : string;
+ i : longint;
+
+ function lower(const s : string) : string;
+ {
+ return lowercased string of s
+ }
+ var
+ i : longint;
+ begin
+ for i:=1 to length(s) do
+ if s[i] in ['A'..'Z'] then
+ lower[i]:=char(byte(s[i])+32)
+ else
+ lower[i]:=s[i];
+ lower[0]:=s[0];
+ end;
+
+ function Replace(var s:string;const s1,s2:string):boolean;
+ var
+ i : longint;
+ begin
+ i:=pos(s1,s);
+ if i>0 then
+ begin
+ Delete(s,i,length(s1));
+ Insert(s2,s,i);
+ Replace:=true;
+ end
+ else
+ Replace:=false;
+ end;
+
+
+function formatop(s:string):string;
+ const
+ replaces=19;
+ replacetab : array[1..replaces,1..2] of string[32]=(
+ (':',' or ot_colon'),
+ ('mem8','mem or ot_bits8'),
+ ('mem16','mem or ot_bits16'),
+ ('mem32','mem or ot_bits32'),
+ ('mem64','mem or ot_bits64'),
+ ('mem80','mem or ot_bits80'),
+ ('mem','memory'),
+ ('memory_offs','mem_offs'),
+ ('imm8','imm or ot_bits8'),
+ ('imm16','imm or ot_bits16'),
+ ('imm32','imm or ot_bits32'),
+ ('imm64','imm or ot_bits64'),
+ ('imm80','imm or ot_bits80'),
+ ('imm','immediate'),
+ ('rm8','regmem or ot_bits8'),
+ ('rm16','regmem or ot_bits16'),
+ ('rm32','regmem or ot_bits32'),
+ ('rm64','regmem or ot_bits64'),
+ ('rm80','regmem or ot_bits80')
+ );
+ var
+ i : longint;
+ begin
+ for i:=1to replaces do
+ replace(s,replacetab[i,1],replacetab[i,2]);
+ formatop:=s;
+ end;
+
+
+function readnumber : longint;
+
+ var
+ base : longint;
+
+ begin
+ result:=0;
+ if s[i]='\' then
+ begin
+ base:=8;
+ inc(i);
+ if s[i]='x' then
+ begin
+ base:=16;
+ inc(i);
+ end;
+ end
+ else
+ base:=10;
+ s[i]:=upcase(s[i]);
+ while s[i] in ['0'..'9','A'..'F'] do
+ begin
+ case s[i] of
+ '0'..'9':
+ result:=result*base+ord(s[i])-ord('0');
+
+ 'A'..'F':
+ result:=result*base+ord(s[i])-ord('A')+10;
+ end;
+ inc(i);
+ end;
+ end;
+
+function tostr(l : longint) : string;
+
+ var
+ hs : string;
+
+ begin
+ str(l,hs);
+ tostr:=hs;
+ end;
+
+function readstr : string;
+
+ begin
+ result:='';
+ while (s[i] in ['0'..'9','A'..'Z','a'..'z','_']) and (i<=length(s)) do
+ begin
+ result:=result+s[i];
+ inc(i);
+ end;
+ end;
+
+procedure skipspace;
+
+ begin
+ while (s[i] in [' ',#9]) do
+ inc(i);
+ end;
+
+procedure openinc(out f:text;const fn:string);
+begin
+ writeln('creating ',fn);
+ assign(f,fn);
+ rewrite(f);
+ writeln(f,'{ don''t edit, this file is generated from armins.dat }');
+ writeln(f,'(');
+end;
+
+
+procedure closeinc(var f:text);
+begin
+ writeln(f);
+ writeln(f,');');
+ close(f);
+end;
+
+
+var
+ attsuffix,
+ hs : string;
+ j : longint;
+ firstopcode,
+ first : boolean;
+ maxinfolen,
+ code : byte;
+ insns : longint;
+ attsuffile,{propfile,}opfile,
+ nopfile,attfile,
+ infile,insfile : text;
+ { instruction fields }
+ skip : boolean;
+ {last,}
+ ops : longint;
+ attopcode,
+ opcode,
+ codes,
+ flags : string;
+ optypes : array[1..4] of string;
+begin
+ writeln('Narm Instruction Table Converter Version ',Version);
+ insns:=0;
+ maxinfolen:=0;
+ { open dat file }
+ assign(infile,'../arm/armins.dat');
+ { create inc files }
+ openinc(insfile,'armtab.inc');
+ openinc(opfile,'armop.inc');
+ assign(nopfile,'armnop.inc');
+ openinc(attfile,'armatt.inc');
+ openinc(attsuffile,'armatts.inc');
+ {
+ openinc(intfile,'i386int.inc');
+ openinc(propfile,'i386prop.inc');
+ }
+ rewrite(nopfile);
+ writeln(nopfile,'{ don''t edit, this file is generated from armins.dat }');
+ reset(infile);
+ first:=true;
+ opcode:='';
+ firstopcode:=true;
+ while not(eof(infile)) do
+ begin
+ { handle comment }
+ readln(infile,s);
+ while (s[1]=' ') do
+ delete(s,1,1);
+ if (s='') or (s[1]=';') then
+ continue;
+ if (s[1]='[') then
+ begin
+ i:=pos(',',s);
+ j:=pos(']',s);
+ if i=0 then
+ begin
+ opcode:='A_'+Copy(s,2,j-2);
+ attopcode:=Copy(s,2,j-2);
+ { Conditional }
+ if (attopcode[length(attopcode)]='c') and
+ (attopcode[length(attopcode)-1]='c') then
+ begin
+ dec(byte(attopcode[0]),2);
+ dec(byte(opcode[0]),2);
+ end;
+ attsuffix:='attsufNONE';
+ end
+ else
+ begin
+ opcode:='A_'+Copy(s,2,i-2);
+ { intel conditional }
+ if (opcode[length(attopcode)]='c') and
+ (opcode[length(attopcode)-1]='c') then
+ dec(byte(opcode[0]),2);
+ attopcode:=Copy(s,i+1,j-i-1);
+ { att Suffix }
+ case attopcode[length(attopcode)] of
+ 'X' :
+ begin
+ dec(attopcode[0]);
+ attsuffix:='attsufINT';
+ end;
+ 'F' :
+ begin
+ dec(attopcode[0]);
+ attsuffix:='attsufFPU';
+ end;
+ 'R' :
+ begin
+ dec(attopcode[0]);
+ attsuffix:='attsufFPUint';
+ end;
+ else
+ attsuffix:='attsufNONE';
+ end;
+ { att Conditional }
+ if (attopcode[length(attopcode)]='C') and
+ (attopcode[length(attopcode)-1]='C') then
+ dec(byte(attopcode[0]),2);
+ end;
+ attopcode:=Lower(attopcode);
+ if firstopcode then
+ firstopcode:=false
+ else
+ begin
+ writeln(opfile,',');
+ writeln(attfile,',');
+ writeln(attsuffile,',');
+{ writeln(propfile,','); }
+ end;
+ write(opfile,opcode);
+ write(attfile,'''',attopcode,'''');
+ write(attsuffile,attsuffix);
+ { read the next line which contains the Change options }
+ {
+ repeat
+ readln(infile,s);
+ until eof(infile) or ((s<>'') and (s[1]<>';'));
+ write(propfile,'(Ch: ',s,')');
+ }
+ continue;
+ end;
+ { we must have an opcode }
+ if opcode='' then
+ runerror(234);
+ { clear }
+ ops:=0;
+ optypes[1]:='';
+ optypes[2]:='';
+ optypes[3]:='';
+ optypes[4]:='';
+ codes:='';
+ flags:='';
+ skip:=false;
+ { ops and optypes }
+ i:=1;
+ repeat
+ hs:=readstr;
+ if (hs='void') or (hs='ignore') then
+ break;
+ inc(ops);
+ optypes[ops]:=optypes[ops]+'ot_'+formatop(hs);
+{ if s[i]=':' then
+ begin
+ inc(i);
+ optypes[ops]:=optypes[ops]+' or ot_'+formatop(readstr);
+ end;}
+ while s[i]='|' do
+ begin
+ inc(i);
+ optypes[ops]:=optypes[ops]+' or ot_'+formatop(readstr);
+ end;
+ if s[i] in [',',':'] then
+ inc(i)
+ else
+ break;
+ until false;
+ for j:=1 to 4-ops do
+ optypes[4-j+1]:='ot_none';
+ { codes }
+ skipspace;
+ j:=0;
+(* last:=0;*)
+ if s[i] in ['\','0'..'9'] then
+ begin
+ while not(s[i] in [' ',#9]) do
+ begin
+ code:=readnumber;
+(*
+ { for some codes we want also to change the optypes, but not
+ if the last byte was a 1 then this byte belongs to a direct
+ copy }
+ if last<>1 then
+ begin
+ case code of
+ 12,13,14 :
+ optypes[code-11]:=optypes[code-11]+' or ot_signed';
+ end;
+ end;
+*)
+ codes:=codes+'#'+tostr(code);
+(* last:=code;*)
+ inc(j);
+ end;
+ end
+ else
+ begin
+ readstr;
+ codes:='#0';
+ end;
+ if j>maxinfolen then
+ maxinfolen:=j;
+ { flags }
+ skipspace;
+ while not(s[i] in [' ',#9,#13,#10]) and (i<=length(s)) do
+ begin
+ hs:=readstr;
+ if hs<>'ND' then
+ begin
+ if flags<>'' then
+ flags:=flags+' or ';
+ flags:=flags+'if_'+lower(hs);
+ end;
+ if (s[i]=',') and (i<=length(s)) then
+ inc(i)
+ else
+ break;
+ end;
+ { write instruction }
+ if not skip then
+ begin
+ if not(first) then
+ writeln(insfile,',')
+ else
+ first:=false;
+ writeln(insfile,' (');
+ writeln(insfile,' opcode : ',opcode,';');
+ writeln(insfile,' ops : ',ops,';');
+ writeln(insfile,' optypes : (',optypes[1],',',optypes[2],',',optypes[3],',',optypes[4],');');
+ writeln(insfile,' code : ',codes,';');
+ writeln(insfile,' flags : ',flags);
+ write(insfile,' )');
+ inc(insns);
+ end;
+ end;
+ close(infile);
+ closeinc(insfile);
+ closeinc(attfile);
+ closeinc(attsuffile);
+ closeinc(opfile);
+ writeln(nopfile,insns,';');
+ close(nopfile);
+{ closeinc(propfile); }
+ writeln(insns,' nodes procesed (maxinfolen=',maxinfolen,')');
+end.
diff --git a/closures/compiler/utils/mkarmreg.pp b/closures/compiler/utils/mkarmreg.pp
new file mode 100644
index 0000000000..8095eb37e8
--- /dev/null
+++ b/closures/compiler/utils/mkarmreg.pp
@@ -0,0 +1,276 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman and Florian Klaempfl
+
+ Convert spreg.dat to several .inc files for usage with
+ the Free pascal compiler
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+{$mode objfpc}
+
+program mkspreg;
+
+const Version = '1.00';
+ max_regcount = 200;
+
+var s : string;
+ i : longint;
+ line : longint;
+ regcount:byte;
+ regcount_bsstart:byte;
+ names,
+ regtypes,
+ subtypes,
+ supregs,
+ numbers,
+ stdnames,
+ stabs,dwarf : array[0..max_regcount-1] of string[63];
+ regnumber_index,
+ std_regname_index : array[0..max_regcount-1] of byte;
+
+function tostr(l : longint) : string;
+
+begin
+ str(l,tostr);
+end;
+
+function readstr : string;
+
+ begin
+ result:='';
+ while (s[i]<>',') and (i<=length(s)) do
+ begin
+ result:=result+s[i];
+ inc(i);
+ end;
+ end;
+
+
+procedure readcomma;
+ begin
+ if s[i]<>',' then
+ begin
+ writeln('Missing "," at line ',line);
+ writeln('Line: "',s,'"');
+ halt(1);
+ end;
+ inc(i);
+ end;
+
+
+procedure skipspace;
+
+ begin
+ while (s[i] in [' ',#9]) do
+ inc(i);
+ end;
+
+procedure openinc(out f:text;const fn:string);
+begin
+ writeln('creating ',fn);
+ assign(f,fn);
+ rewrite(f);
+ writeln(f,'{ don''t edit, this file is generated from armreg.dat }');
+end;
+
+
+procedure closeinc(var f:text);
+begin
+ writeln(f);
+ close(f);
+end;
+
+procedure build_regnum_index;
+
+var h,i,j,p,t:byte;
+
+begin
+ {Build the registernumber2regindex index.
+ Step 1: Fill.}
+ for i:=0 to regcount-1 do
+ regnumber_index[i]:=i;
+ {Step 2: Sort. We use a Shell-Metzner sort.}
+ p:=regcount_bsstart;
+ repeat
+ for h:=0 to regcount-p-1 do
+ begin
+ i:=h;
+ repeat
+ j:=i+p;
+ if numbers[regnumber_index[j]]>=numbers[regnumber_index[i]] then
+ break;
+ t:=regnumber_index[i];
+ regnumber_index[i]:=regnumber_index[j];
+ regnumber_index[j]:=t;
+ if i<p then
+ break;
+ dec(i,p);
+ until false;
+ end;
+ p:=p shr 1;
+ until p=0;
+end;
+
+procedure build_std_regname_index;
+
+var h,i,j,p,t:byte;
+
+begin
+ {Build the registernumber2regindex index.
+ Step 1: Fill.}
+ for i:=0 to regcount-1 do
+ std_regname_index[i]:=i;
+ {Step 2: Sort. We use a Shell-Metzner sort.}
+ p:=regcount_bsstart;
+ repeat
+ for h:=0 to regcount-p-1 do
+ begin
+ i:=h;
+ repeat
+ j:=i+p;
+ if stdnames[std_regname_index[j]]>=stdnames[std_regname_index[i]] then
+ break;
+ t:=std_regname_index[i];
+ std_regname_index[i]:=std_regname_index[j];
+ std_regname_index[j]:=t;
+ if i<p then
+ break;
+ dec(i,p);
+ until false;
+ end;
+ p:=p shr 1;
+ until p=0;
+end;
+
+
+procedure read_spreg_file;
+
+var infile:text;
+
+begin
+ { open dat file }
+ assign(infile,'armreg.dat');
+ reset(infile);
+ while not(eof(infile)) do
+ begin
+ { handle comment }
+ readln(infile,s);
+ inc(line);
+ while (s[1]=' ') do
+ delete(s,1,1);
+ if (s='') or (s[1]=';') then
+ continue;
+
+ i:=1;
+ names[regcount]:=readstr;
+ readcomma;
+ regtypes[regcount]:=readstr;
+ readcomma;
+ subtypes[regcount]:=readstr;
+ readcomma;
+ supregs[regcount]:=readstr;
+ readcomma;
+ stdnames[regcount]:=readstr;
+ readcomma;
+ stabs[regcount]:=readstr;
+ readcomma;
+ dwarf[regcount]:=readstr;
+ { Create register number }
+ if supregs[regcount][1]<>'$' then
+ begin
+ writeln('Missing $ before number, at line ',line);
+ writeln('Line: "',s,'"');
+ halt(1);
+ end;
+ numbers[regcount]:=regtypes[regcount]+copy(subtypes[regcount],2,255)+'00'+copy(supregs[regcount],2,255);
+ if i<length(s) then
+ begin
+ writeln('Extra chars at end of line, at line ',line);
+ writeln('Line: "',s,'"');
+ halt(1);
+ end;
+ inc(regcount);
+ if regcount>max_regcount then
+ begin
+ writeln('Error: Too much registers, please increase maxregcount in source');
+ halt(2);
+ end;
+ end;
+ close(infile);
+end;
+
+procedure write_inc_files;
+
+var
+ norfile,stdfile,supfile,
+ numfile,stabfile,dwarffile,confile,
+ rnifile,srifile:text;
+ first:boolean;
+
+begin
+ { create inc files }
+ openinc(confile,'rarmcon.inc');
+ openinc(supfile,'rarmsup.inc');
+ openinc(numfile,'rarmnum.inc');
+ openinc(stdfile,'rarmstd.inc');
+ openinc(stabfile,'rarmsta.inc');
+ openinc(dwarffile,'rarmdwa.inc');
+ openinc(norfile,'rarmnor.inc');
+ openinc(rnifile,'rarmrni.inc');
+ openinc(srifile,'rarmsri.inc');
+ first:=true;
+ for i:=0 to regcount-1 do
+ begin
+ if not first then
+ begin
+ writeln(numfile,',');
+ writeln(stdfile,',');
+ writeln(stabfile,',');
+ writeln(dwarffile,',');
+ writeln(rnifile,',');
+ writeln(srifile,',');
+ end
+ else
+ first:=false;
+ writeln(supfile,'RS_',names[i],' = ',supregs[i],';');
+ writeln(confile,'NR_'+names[i],' = ','tregister(',numbers[i],')',';');
+ write(numfile,'tregister(',numbers[i],')');
+ write(stdfile,'''',stdnames[i],'''');
+ write(stabfile,stabs[i]);
+ write(dwarffile,dwarf[i]);
+ write(rnifile,regnumber_index[i]);
+ write(srifile,std_regname_index[i]);
+ end;
+ write(norfile,regcount);
+ close(confile);
+ close(supfile);
+ closeinc(numfile);
+ closeinc(stdfile);
+ closeinc(stabfile);
+ closeinc(dwarffile);
+ closeinc(norfile);
+ closeinc(rnifile);
+ closeinc(srifile);
+ writeln('Done!');
+ writeln(regcount,' registers procesed');
+end;
+
+
+begin
+ writeln('Register Table Converter Version ',Version);
+ line:=0;
+ regcount:=0;
+ read_spreg_file;
+ regcount_bsstart:=1;
+ while 2*regcount_bsstart<regcount do
+ regcount_bsstart:=regcount_bsstart*2;
+ build_regnum_index;
+ build_std_regname_index;
+ write_inc_files;
+end.
diff --git a/closures/compiler/utils/mkavrreg.pp b/closures/compiler/utils/mkavrreg.pp
new file mode 100644
index 0000000000..78105af293
--- /dev/null
+++ b/closures/compiler/utils/mkavrreg.pp
@@ -0,0 +1,272 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman and Florian Klaempfl
+
+ Convert spreg.dat to several .inc files for usage with
+ the Free pascal compiler
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+{$mode objfpc}
+program mkspreg;
+
+const Version = '1.00';
+ max_regcount = 200;
+
+var s : string;
+ i : longint;
+ line : longint;
+ regcount:byte;
+ regcount_bsstart:byte;
+ names,
+ regtypes,
+ supregs,
+ numbers,
+ stdnames,
+ stabs,dwarf : array[0..max_regcount-1] of string[63];
+ regnumber_index,
+ std_regname_index : array[0..max_regcount-1] of byte;
+
+function tostr(l : longint) : string;
+
+begin
+ str(l,tostr);
+end;
+
+function readstr : string;
+
+ begin
+ result:='';
+ while (s[i]<>',') and (i<=length(s)) do
+ begin
+ result:=result+s[i];
+ inc(i);
+ end;
+ end;
+
+
+procedure readcomma;
+ begin
+ if s[i]<>',' then
+ begin
+ writeln('Missing "," at line ',line);
+ writeln('Line: "',s,'"');
+ halt(1);
+ end;
+ inc(i);
+ end;
+
+
+procedure skipspace;
+
+ begin
+ while (s[i] in [' ',#9]) do
+ inc(i);
+ end;
+
+procedure openinc(out f:text;const fn:string);
+begin
+ writeln('creating ',fn);
+ assign(f,fn);
+ rewrite(f);
+ writeln(f,'{ don''t edit, this file is generated from avrreg.dat }');
+end;
+
+
+procedure closeinc(var f:text);
+begin
+ writeln(f);
+ close(f);
+end;
+
+procedure build_regnum_index;
+
+var h,i,j,p,t:byte;
+
+begin
+ {Build the registernumber2regindex index.
+ Step 1: Fill.}
+ for i:=0 to regcount-1 do
+ regnumber_index[i]:=i;
+ {Step 2: Sort. We use a Shell-Metzner sort.}
+ p:=regcount_bsstart;
+ repeat
+ for h:=0 to regcount-p-1 do
+ begin
+ i:=h;
+ repeat
+ j:=i+p;
+ if numbers[regnumber_index[j]]>=numbers[regnumber_index[i]] then
+ break;
+ t:=regnumber_index[i];
+ regnumber_index[i]:=regnumber_index[j];
+ regnumber_index[j]:=t;
+ if i<p then
+ break;
+ dec(i,p);
+ until false;
+ end;
+ p:=p shr 1;
+ until p=0;
+end;
+
+procedure build_std_regname_index;
+
+var h,i,j,p,t:byte;
+
+begin
+ {Build the registernumber2regindex index.
+ Step 1: Fill.}
+ for i:=0 to regcount-1 do
+ std_regname_index[i]:=i;
+ {Step 2: Sort. We use a Shell-Metzner sort.}
+ p:=regcount_bsstart;
+ repeat
+ for h:=0 to regcount-p-1 do
+ begin
+ i:=h;
+ repeat
+ j:=i+p;
+ if stdnames[std_regname_index[j]]>=stdnames[std_regname_index[i]] then
+ break;
+ t:=std_regname_index[i];
+ std_regname_index[i]:=std_regname_index[j];
+ std_regname_index[j]:=t;
+ if i<p then
+ break;
+ dec(i,p);
+ until false;
+ end;
+ p:=p shr 1;
+ until p=0;
+end;
+
+
+procedure read_spreg_file;
+
+var infile:text;
+
+begin
+ { open dat file }
+ assign(infile,'avrreg.dat');
+ reset(infile);
+ while not(eof(infile)) do
+ begin
+ { handle comment }
+ readln(infile,s);
+ inc(line);
+ while (s[1]=' ') do
+ delete(s,1,1);
+ if (s='') or (s[1]=';') then
+ continue;
+
+ i:=1;
+ names[regcount]:=readstr;
+ readcomma;
+ regtypes[regcount]:=readstr;
+ readcomma;
+ supregs[regcount]:=readstr;
+ readcomma;
+ stdnames[regcount]:=readstr;
+ readcomma;
+ stabs[regcount]:=readstr;
+ readcomma;
+ dwarf[regcount]:=readstr;
+ { Create register number }
+ if supregs[regcount][1]<>'$' then
+ begin
+ writeln('Missing $ before number, at line ',line);
+ writeln('Line: "',s,'"');
+ halt(1);
+ end;
+ numbers[regcount]:=regtypes[regcount]+'0000'+copy(supregs[regcount],2,255);
+ if i<length(s) then
+ begin
+ writeln('Extra chars at end of line, at line ',line);
+ writeln('Line: "',s,'"');
+ halt(1);
+ end;
+ inc(regcount);
+ if regcount>max_regcount then
+ begin
+ writeln('Error: Too much registers, please increase maxregcount in source');
+ halt(2);
+ end;
+ end;
+ close(infile);
+end;
+
+procedure write_inc_files;
+
+var
+ norfile,stdfile,supfile,
+ numfile,stabfile,dwarffile,confile,
+ rnifile,srifile:text;
+ first:boolean;
+
+begin
+ { create inc files }
+ openinc(confile,'ravrcon.inc');
+ openinc(supfile,'ravrsup.inc');
+ openinc(numfile,'ravrnum.inc');
+ openinc(stdfile,'ravrstd.inc');
+ openinc(stabfile,'ravrsta.inc');
+ openinc(dwarffile,'ravrdwa.inc');
+ openinc(norfile,'ravrnor.inc');
+ openinc(rnifile,'ravrrni.inc');
+ openinc(srifile,'ravrsri.inc');
+ first:=true;
+ for i:=0 to regcount-1 do
+ begin
+ if not first then
+ begin
+ writeln(numfile,',');
+ writeln(stdfile,',');
+ writeln(stabfile,',');
+ writeln(dwarffile,',');
+ writeln(rnifile,',');
+ writeln(srifile,',');
+ end
+ else
+ first:=false;
+ writeln(supfile,'RS_',names[i],' = ',supregs[i],';');
+ writeln(confile,'NR_'+names[i],' = ','tregister(',numbers[i],')',';');
+ write(numfile,'tregister(',numbers[i],')');
+ write(stdfile,'''',stdnames[i],'''');
+ write(stabfile,stabs[i]);
+ write(dwarffile,dwarf[i]);
+ write(rnifile,regnumber_index[i]);
+ write(srifile,std_regname_index[i]);
+ end;
+ write(norfile,regcount);
+ close(confile);
+ close(supfile);
+ closeinc(numfile);
+ closeinc(stdfile);
+ closeinc(stabfile);
+ closeinc(dwarffile);
+ closeinc(norfile);
+ closeinc(rnifile);
+ closeinc(srifile);
+ writeln('Done!');
+ writeln(regcount,' registers procesed');
+end;
+
+
+begin
+ writeln('Register Table Converter Version ',Version);
+ line:=0;
+ regcount:=0;
+ read_spreg_file;
+ regcount_bsstart:=1;
+ while 2*regcount_bsstart<regcount do
+ regcount_bsstart:=regcount_bsstart*2;
+ build_regnum_index;
+ build_std_regname_index;
+ write_inc_files;
+end.
diff --git a/closures/compiler/utils/mkmpsreg.pp b/closures/compiler/utils/mkmpsreg.pp
new file mode 100644
index 0000000000..b3494a50c4
--- /dev/null
+++ b/closures/compiler/utils/mkmpsreg.pp
@@ -0,0 +1,318 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman and Florian Klaempfl
+
+ Convert mipsreg.dat to several .inc files for usage with
+ the Free pascal compiler
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+{$mode objfpc}
+program mkmipsreg;
+
+const Version = '1.00';
+ max_regcount = 200;
+
+var s : string;
+ i : longint;
+ line : longint;
+ regcount:byte;
+ regcount_bsstart:byte;
+ names,
+ regtypes,
+ supregs,
+ numbers,
+ stdnames,
+ gasnames,
+ dwarfs,
+ stabs : array[0..max_regcount-1] of string[63];
+ regnumber_index,
+ std_regname_index,
+ gas_regname_index : array[0..max_regcount-1] of byte;
+
+function tostr(l : longint) : string;
+
+begin
+ str(l,tostr);
+end;
+
+function readstr : string;
+
+ begin
+ result:='';
+ while (s[i]<>',') and (i<=length(s)) do
+ begin
+ result:=result+s[i];
+ inc(i);
+ end;
+ end;
+
+
+procedure readcomma;
+ begin
+ if s[i]<>',' then
+ begin
+ writeln('Missing "," at line ',line);
+ writeln('Line: "',s,'"');
+ halt(1);
+ end;
+ inc(i);
+ end;
+
+
+procedure skipspace;
+
+ begin
+ while (s[i] in [' ',#9]) do
+ inc(i);
+ end;
+
+procedure openinc(out f:text;const fn:string);
+begin
+ writeln('creating ',fn);
+ assign(f,fn);
+ rewrite(f);
+ writeln(f,'{ don''t edit, this file is generated from mipsreg.dat }');
+end;
+
+
+procedure closeinc(var f:text);
+begin
+ writeln(f);
+ close(f);
+end;
+
+procedure build_regnum_index;
+
+var h,i,j,p,t:byte;
+
+begin
+ {Build the registernumber2regindex index.
+ Step 1: Fill.}
+ for i:=0 to regcount-1 do
+ regnumber_index[i]:=i;
+ {Step 2: Sort. We use a Shell-Metzner sort.}
+ p:=regcount_bsstart;
+ repeat
+ for h:=0 to regcount-p-1 do
+ begin
+ i:=h;
+ repeat
+ j:=i+p;
+ if numbers[regnumber_index[j]]>=numbers[regnumber_index[i]] then
+ break;
+ t:=regnumber_index[i];
+ regnumber_index[i]:=regnumber_index[j];
+ regnumber_index[j]:=t;
+ if i<p then
+ break;
+ dec(i,p);
+ until false;
+ end;
+ p:=p shr 1;
+ until p=0;
+end;
+
+procedure build_std_regname_index;
+
+var h,i,j,p,t:byte;
+
+begin
+ {Build the registernumber2regindex index.
+ Step 1: Fill.}
+ for i:=0 to regcount-1 do
+ std_regname_index[i]:=i;
+ {Step 2: Sort. We use a Shell-Metzner sort.}
+ p:=regcount_bsstart;
+ repeat
+ for h:=0 to regcount-p-1 do
+ begin
+ i:=h;
+ repeat
+ j:=i+p;
+ if stdnames[std_regname_index[j]]>=stdnames[std_regname_index[i]] then
+ break;
+ t:=std_regname_index[i];
+ std_regname_index[i]:=std_regname_index[j];
+ std_regname_index[j]:=t;
+ if i<p then
+ break;
+ dec(i,p);
+ until false;
+ end;
+ p:=p shr 1;
+ until p=0;
+end;
+
+
+procedure build_gas_regname_index;
+
+var h,i,j,p,t:byte;
+
+begin
+ {Build the registernumber2regindex index.
+ Step 1: Fill.}
+ for i:=0 to regcount-1 do
+ gas_regname_index[i]:=i;
+ {Step 2: Sort. We use a Shell-Metzner sort.}
+ p:=regcount_bsstart;
+ repeat
+ for h:=0 to regcount-p-1 do
+ begin
+ i:=h;
+ repeat
+ j:=i+p;
+ if gasnames[gas_regname_index[j]]>=gasnames[gas_regname_index[i]] then
+ break;
+ t:=gas_regname_index[i];
+ gas_regname_index[i]:=gas_regname_index[j];
+ gas_regname_index[j]:=t;
+ if i<p then
+ break;
+ dec(i,p);
+ until false;
+ end;
+ p:=p shr 1;
+ until p=0;
+end;
+
+
+procedure read_mipsreg_file;
+
+var infile:text;
+
+begin
+ { open dat file }
+ assign(infile,'mipsreg.dat');
+ reset(infile);
+ while not(eof(infile)) do
+ begin
+ { handle comment }
+ readln(infile,s);
+ inc(line);
+ while (s[1]=' ') do
+ delete(s,1,1);
+ if (s='') or (s[1]=';') then
+ continue;
+
+ i:=1;
+ names[regcount]:=readstr;
+ readcomma;
+ regtypes[regcount]:=readstr;
+ readcomma;
+ supregs[regcount]:=readstr;
+ readcomma;
+ stdnames[regcount]:=readstr;
+ readcomma;
+ gasnames[regcount]:=readstr;
+ readcomma;
+ stabs[regcount]:=readstr;
+ readcomma;
+ dwarfs[regcount]:=readstr;
+ { Create register number }
+ if supregs[regcount][1]<>'$' then
+ begin
+ writeln('Missing $ before number, at line ',line);
+ writeln('Line: "',s,'"');
+ halt(1);
+ end;
+ numbers[regcount]:=regtypes[regcount]+'0000'+copy(supregs[regcount],2,255);
+ if i<length(s) then
+ begin
+ writeln('Extra chars at end of line, at line ',line);
+ writeln('Line: "',s,'"');
+ halt(1);
+ end;
+ inc(regcount);
+ if regcount>max_regcount then
+ begin
+ writeln('Error: Too much registers, please increase maxregcount in source');
+ halt(2);
+ end;
+ end;
+ close(infile);
+end;
+
+procedure write_inc_files;
+
+var
+ norfile,stdfile,supfile,
+ numfile,stabfile,confile,gasfile,dwarffile,
+ rnifile,srifile,grifile : text;
+ first:boolean;
+
+begin
+ { create inc files }
+ openinc(confile,'rmipscon.inc');
+ openinc(supfile,'rmipssup.inc');
+ openinc(numfile,'rmipsnum.inc');
+ openinc(stdfile,'rmipsstd.inc');
+ openinc(gasfile,'rmipsgas.inc');
+ openinc(stabfile,'rmipssta.inc');
+ openinc(dwarffile,'rmipsdwf.inc');
+ openinc(norfile,'rmipsnor.inc');
+ openinc(rnifile,'rmipsrni.inc');
+ openinc(srifile,'rmipssri.inc');
+ openinc(grifile,'rmipsgri.inc');
+ first:=true;
+ for i:=0 to regcount-1 do
+ begin
+ if not first then
+ begin
+ writeln(numfile,',');
+ writeln(stdfile,',');
+ writeln(gasfile,',');
+ writeln(stabfile,',');
+ writeln(dwarffile,',');
+ writeln(rnifile,',');
+ writeln(srifile,',');
+ writeln(grifile,',');
+ end
+ else
+ first:=false;
+ writeln(supfile,'RS_',names[i],' = ',supregs[i],';');
+ writeln(confile,'NR_'+names[i],' = ','tregister(',numbers[i],')',';');
+ write(numfile,'tregister(',numbers[i],')');
+ write(stdfile,'''',stdnames[i],'''');
+ write(gasfile,'''',gasnames[i],'''');
+ write(stabfile,stabs[i]);
+ write(dwarffile,dwarfs[i]);
+ write(rnifile,regnumber_index[i]);
+ write(srifile,std_regname_index[i]);
+ write(grifile,gas_regname_index[i]);
+ end;
+ write(norfile,regcount);
+ close(confile);
+ close(supfile);
+ closeinc(numfile);
+ closeinc(stdfile);
+ closeinc(gasfile);
+ closeinc(stabfile);
+ closeinc(dwarffile);
+ closeinc(norfile);
+ closeinc(rnifile);
+ closeinc(srifile);
+ closeinc(grifile);
+ writeln('Done!');
+ writeln(regcount,' registers procesed');
+end;
+
+
+begin
+ writeln('Register Table Converter Version ',Version);
+ line:=0;
+ regcount:=0;
+ read_mipsreg_file;
+ regcount_bsstart:=1;
+ while 2*regcount_bsstart<regcount do
+ regcount_bsstart:=regcount_bsstart*2;
+ build_regnum_index;
+ build_std_regname_index;
+ build_gas_regname_index;
+ write_inc_files;
+end.
diff --git a/closures/compiler/utils/mkppcreg.pp b/closures/compiler/utils/mkppcreg.pp
new file mode 100644
index 0000000000..7a35f1d78d
--- /dev/null
+++ b/closures/compiler/utils/mkppcreg.pp
@@ -0,0 +1,370 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman and Florian Klaempfl
+
+ Convert ppcreg.dat to several .inc files for usage with
+ the Free pascal compiler
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+{$mode objfpc}
+program mkppcreg;
+
+const Version = '1.00';
+ max_regcount = 200;
+
+var s : string;
+ i : longint;
+ line : longint;
+ regcount:byte;
+ regcount_bsstart:byte;
+ names,
+ regtypes,
+ supregs,
+ numbers,
+ stdnames,
+ gasnames,
+ gssnames,
+ motnames,
+ dwarfs,
+ stabs : array[0..max_regcount-1] of string[63];
+ regnumber_index,
+ std_regname_index,
+ gas_regname_index,
+ mot_regname_index : array[0..max_regcount-1] of byte;
+
+function tostr(l : longint) : string;
+
+begin
+ str(l,tostr);
+end;
+
+function readstr : string;
+
+ begin
+ result:='';
+ while (s[i]<>',') and (i<=length(s)) do
+ begin
+ result:=result+s[i];
+ inc(i);
+ end;
+ end;
+
+
+procedure readcomma;
+ begin
+ if s[i]<>',' then
+ begin
+ writeln('Missing "," at line ',line);
+ writeln('Line: "',s,'"');
+ halt(1);
+ end;
+ inc(i);
+ end;
+
+
+procedure skipspace;
+
+ begin
+ while (s[i] in [' ',#9]) do
+ inc(i);
+ end;
+
+procedure openinc(out f:text;const fn:string);
+begin
+ writeln('creating ',fn);
+ assign(f,fn);
+ rewrite(f);
+ writeln(f,'{ don''t edit, this file is generated from ppcreg.dat }');
+end;
+
+
+procedure closeinc(var f:text);
+begin
+ writeln(f);
+ close(f);
+end;
+
+procedure build_regnum_index;
+
+var h,i,j,p,t:byte;
+
+begin
+ {Build the registernumber2regindex index.
+ Step 1: Fill.}
+ for i:=0 to regcount-1 do
+ regnumber_index[i]:=i;
+ {Step 2: Sort. We use a Shell-Metzner sort.}
+ p:=regcount_bsstart;
+ repeat
+ for h:=0 to regcount-p-1 do
+ begin
+ i:=h;
+ repeat
+ j:=i+p;
+ if numbers[regnumber_index[j]]>=numbers[regnumber_index[i]] then
+ break;
+ t:=regnumber_index[i];
+ regnumber_index[i]:=regnumber_index[j];
+ regnumber_index[j]:=t;
+ if i<p then
+ break;
+ dec(i,p);
+ until false;
+ end;
+ p:=p shr 1;
+ until p=0;
+end;
+
+procedure build_std_regname_index;
+
+var h,i,j,p,t:byte;
+
+begin
+ {Build the registernumber2regindex index.
+ Step 1: Fill.}
+ for i:=0 to regcount-1 do
+ std_regname_index[i]:=i;
+ {Step 2: Sort. We use a Shell-Metzner sort.}
+ p:=regcount_bsstart;
+ repeat
+ for h:=0 to regcount-p-1 do
+ begin
+ i:=h;
+ repeat
+ j:=i+p;
+ if stdnames[std_regname_index[j]]>=stdnames[std_regname_index[i]] then
+ break;
+ t:=std_regname_index[i];
+ std_regname_index[i]:=std_regname_index[j];
+ std_regname_index[j]:=t;
+ if i<p then
+ break;
+ dec(i,p);
+ until false;
+ end;
+ p:=p shr 1;
+ until p=0;
+end;
+
+
+procedure build_gas_regname_index;
+
+var h,i,j,p,t:byte;
+
+begin
+ {Build the registernumber2regindex index.
+ Step 1: Fill.}
+ for i:=0 to regcount-1 do
+ gas_regname_index[i]:=i;
+ {Step 2: Sort. We use a Shell-Metzner sort.}
+ p:=regcount_bsstart;
+ repeat
+ for h:=0 to regcount-p-1 do
+ begin
+ i:=h;
+ repeat
+ j:=i+p;
+ if gasnames[gas_regname_index[j]]>=gasnames[gas_regname_index[i]] then
+ break;
+ t:=gas_regname_index[i];
+ gas_regname_index[i]:=gas_regname_index[j];
+ gas_regname_index[j]:=t;
+ if i<p then
+ break;
+ dec(i,p);
+ until false;
+ end;
+ p:=p shr 1;
+ until p=0;
+end;
+
+
+procedure build_mot_regname_index;
+
+var h,i,j,p,t:byte;
+
+begin
+ {Build the registernumber2regindex index.
+ Step 1: Fill.}
+ for i:=0 to regcount-1 do
+ mot_regname_index[i]:=i;
+ {Step 2: Sort. We use a Shell-Metzner sort.}
+ p:=regcount_bsstart;
+ repeat
+ for h:=0 to regcount-p-1 do
+ begin
+ i:=h;
+ repeat
+ j:=i+p;
+ if motnames[mot_regname_index[j]]>=motnames[mot_regname_index[i]] then
+ break;
+ t:=mot_regname_index[i];
+ mot_regname_index[i]:=mot_regname_index[j];
+ mot_regname_index[j]:=t;
+ if i<p then
+ break;
+ dec(i,p);
+ until false;
+ end;
+ p:=p shr 1;
+ until p=0;
+end;
+
+
+procedure read_ppcreg_file;
+
+var infile:text;
+
+begin
+ { open dat file }
+ assign(infile,'ppcreg.dat');
+ reset(infile);
+ while not(eof(infile)) do
+ begin
+ { handle comment }
+ readln(infile,s);
+ inc(line);
+ while (s[1]=' ') do
+ delete(s,1,1);
+ if (s='') or (s[1]=';') then
+ continue;
+
+ i:=1;
+ names[regcount]:=readstr;
+ readcomma;
+ regtypes[regcount]:=readstr;
+ readcomma;
+ supregs[regcount]:=readstr;
+ readcomma;
+ stdnames[regcount]:=readstr;
+ readcomma;
+ gasnames[regcount]:=readstr;
+ readcomma;
+ gssnames[regcount]:=readstr;
+ readcomma;
+ motnames[regcount]:=readstr;
+ readcomma;
+ stabs[regcount]:=readstr;
+ readcomma;
+ dwarfs[regcount]:=readstr;
+ { Create register number }
+ if supregs[regcount][1]<>'$' then
+ begin
+ writeln('Missing $ before number, at line ',line);
+ writeln('Line: "',s,'"');
+ halt(1);
+ end;
+ numbers[regcount]:=regtypes[regcount]+'0000'+copy(supregs[regcount],2,255);
+ if i<length(s) then
+ begin
+ writeln('Extra chars at end of line, at line ',line);
+ writeln('Line: "',s,'"');
+ halt(1);
+ end;
+ inc(regcount);
+ if regcount>max_regcount then
+ begin
+ writeln('Error: Too much registers, please increase maxregcount in source');
+ halt(2);
+ end;
+ end;
+ close(infile);
+end;
+
+procedure write_inc_files;
+
+var
+ norfile,stdfile,motfile,supfile,
+ numfile,stabfile,confile,gasfile,gssfile,dwarffile,
+ rnifile,srifile,mrifile,grifile : text;
+ first:boolean;
+
+begin
+ { create inc files }
+ openinc(confile,'rppccon.inc');
+ openinc(supfile,'rppcsup.inc');
+ openinc(numfile,'rppcnum.inc');
+ openinc(stdfile,'rppcstd.inc');
+ openinc(gasfile,'rppcgas.inc');
+ openinc(gssfile,'rppcgss.inc');
+ openinc(motfile,'rppcmot.inc');
+ openinc(stabfile,'rppcstab.inc');
+ openinc(dwarffile,'rppcdwrf.inc');
+ openinc(norfile,'rppcnor.inc');
+ openinc(rnifile,'rppcrni.inc');
+ openinc(srifile,'rppcsri.inc');
+ openinc(grifile,'rppcgri.inc');
+ openinc(mrifile,'rppcmri.inc');
+ first:=true;
+ for i:=0 to regcount-1 do
+ begin
+ if not first then
+ begin
+ writeln(numfile,',');
+ writeln(stdfile,',');
+ writeln(gasfile,',');
+ writeln(gssfile,',');
+ writeln(motfile,',');
+ writeln(stabfile,',');
+ writeln(dwarffile,',');
+ writeln(rnifile,',');
+ writeln(srifile,',');
+ writeln(grifile,',');
+ writeln(mrifile,',');
+ end
+ else
+ first:=false;
+ writeln(supfile,'RS_',names[i],' = ',supregs[i],';');
+ writeln(confile,'NR_'+names[i],' = ','tregister(',numbers[i],')',';');
+ write(numfile,'tregister(',numbers[i],')');
+ write(stdfile,'''',stdnames[i],'''');
+ write(gasfile,'''',gasnames[i],'''');
+ write(gssfile,'''',gssnames[i],'''');
+ write(motfile,'''',motnames[i],'''');
+ write(stabfile,stabs[i]);
+ write(dwarffile,dwarfs[i]);
+ write(rnifile,regnumber_index[i]);
+ write(srifile,std_regname_index[i]);
+ write(grifile,gas_regname_index[i]);
+ write(mrifile,mot_regname_index[i]);
+ end;
+ write(norfile,regcount);
+ close(confile);
+ close(supfile);
+ closeinc(numfile);
+ closeinc(stdfile);
+ closeinc(gasfile);
+ closeinc(gssfile);
+ closeinc(motfile);
+ closeinc(stabfile);
+ closeinc(dwarffile);
+ closeinc(norfile);
+ closeinc(rnifile);
+ closeinc(srifile);
+ closeinc(grifile);
+ closeinc(mrifile);
+ writeln('Done!');
+ writeln(regcount,' registers procesed');
+end;
+
+
+begin
+ writeln('Register Table Converter Version ',Version);
+ line:=0;
+ regcount:=0;
+ read_ppcreg_file;
+ regcount_bsstart:=1;
+ while 2*regcount_bsstart<regcount do
+ regcount_bsstart:=regcount_bsstart*2;
+ build_regnum_index;
+ build_std_regname_index;
+ build_gas_regname_index;
+ build_mot_regname_index;
+ write_inc_files;
+end.
diff --git a/closures/compiler/utils/mkspreg.pp b/closures/compiler/utils/mkspreg.pp
new file mode 100644
index 0000000000..668c152408
--- /dev/null
+++ b/closures/compiler/utils/mkspreg.pp
@@ -0,0 +1,275 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman and Florian Klaempfl
+
+ Convert spreg.dat to several .inc files for usage with
+ the Free pascal compiler
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+{$mode objfpc}
+program mkspreg;
+
+const Version = '1.00';
+ max_regcount = 200;
+
+var s : string;
+ i : longint;
+ line : longint;
+ regcount:byte;
+ regcount_bsstart:byte;
+ supregs,
+ subregs,
+ names,
+ regtypes,
+ numbers,
+ stdnames,
+ stabs,
+ dwarfs : array[0..max_regcount-1] of string[63];
+ regnumber_index,
+ std_regname_index : array[0..max_regcount-1] of byte;
+
+function tostr(l : longint) : string;
+
+begin
+ str(l,tostr);
+end;
+
+function readstr : string;
+
+ begin
+ result:='';
+ while (s[i]<>',') and (i<=length(s)) do
+ begin
+ result:=result+s[i];
+ inc(i);
+ end;
+ end;
+
+
+procedure readcomma;
+ begin
+ if s[i]<>',' then
+ begin
+ writeln('Missing "," at line ',line);
+ writeln('Line: "',s,'"');
+ halt(1);
+ end;
+ inc(i);
+ end;
+
+
+procedure skipspace;
+
+ begin
+ while (s[i] in [' ',#9]) do
+ inc(i);
+ end;
+
+procedure openinc(out f:text;const fn:string);
+begin
+ writeln('creating ',fn);
+ assign(f,fn);
+ rewrite(f);
+ writeln(f,'{ don''t edit, this file is generated from spreg.dat }');
+end;
+
+
+procedure closeinc(var f:text);
+begin
+ writeln(f);
+ close(f);
+end;
+
+procedure build_regnum_index;
+
+var h,i,j,p,t:byte;
+
+begin
+ {Build the registernumber2regindex index.
+ Step 1: Fill.}
+ for i:=0 to regcount-1 do
+ regnumber_index[i]:=i;
+ {Step 2: Sort. We use a Shell-Metzner sort.}
+ p:=regcount_bsstart;
+ repeat
+ for h:=0 to regcount-p-1 do
+ begin
+ i:=h;
+ repeat
+ j:=i+p;
+ if numbers[regnumber_index[j]]>=numbers[regnumber_index[i]] then
+ break;
+ t:=regnumber_index[i];
+ regnumber_index[i]:=regnumber_index[j];
+ regnumber_index[j]:=t;
+ if i<p then
+ break;
+ dec(i,p);
+ until false;
+ end;
+ p:=p shr 1;
+ until p=0;
+end;
+
+procedure build_std_regname_index;
+
+var h,i,j,p,t:byte;
+
+begin
+ {Build the registernumber2regindex index.
+ Step 1: Fill.}
+ for i:=0 to regcount-1 do
+ std_regname_index[i]:=i;
+ {Step 2: Sort. We use a Shell-Metzner sort.}
+ p:=regcount_bsstart;
+ repeat
+ for h:=0 to regcount-p-1 do
+ begin
+ i:=h;
+ repeat
+ j:=i+p;
+ if stdnames[std_regname_index[j]]>=stdnames[std_regname_index[i]] then
+ break;
+ t:=std_regname_index[i];
+ std_regname_index[i]:=std_regname_index[j];
+ std_regname_index[j]:=t;
+ if i<p then
+ break;
+ dec(i,p);
+ until false;
+ end;
+ p:=p shr 1;
+ until p=0;
+end;
+
+
+procedure read_spreg_file;
+var
+ infile:text;
+begin
+ { open dat file }
+ assign(infile,'spreg.dat');
+ reset(infile);
+ while not(eof(infile)) do
+ begin
+ { handle comment }
+ readln(infile,s);
+ inc(line);
+ while (s[1]=' ') do
+ delete(s,1,1);
+ if (s='') or (s[1]=';') then
+ continue;
+
+ i:=1;
+ names[regcount]:=readstr;
+ readcomma;
+ regtypes[regcount]:=readstr;
+ readcomma;
+ subregs[regcount]:=readstr;
+ readcomma;
+ supregs[regcount]:=readstr;
+ readcomma;
+ stdnames[regcount]:=readstr;
+ readcomma;
+ stabs[regcount]:=readstr;
+ readcomma;
+ dwarfs[regcount]:=readstr;
+ { Create register number }
+ if supregs[regcount][1]<>'$' then
+ begin
+ writeln('Missing $ before number, at line ',line);
+ writeln('Line: "',s,'"');
+ halt(1);
+ end;
+ numbers[regcount]:=regtypes[regcount]+copy(subregs[regcount],2,255)+'00'+copy(supregs[regcount],2,255);
+ if i<length(s) then
+ begin
+ writeln('Extra chars at end of line, at line ',line);
+ writeln('Line: "',s,'"');
+ halt(1);
+ end;
+ inc(regcount);
+ if regcount>max_regcount then
+ begin
+ writeln('Error: Too much registers, please increase maxregcount in source');
+ halt(2);
+ end;
+ end;
+ close(infile);
+end;
+
+procedure write_inc_files;
+
+var
+ norfile,stdfile,supfile,
+ numfile,stabfile,dwarffile,confile,
+ rnifile,srifile:text;
+ first:boolean;
+
+begin
+ { create inc files }
+ openinc(confile,'rspcon.inc');
+ openinc(supfile,'rspsup.inc');
+ openinc(numfile,'rspnum.inc');
+ openinc(stdfile,'rspstd.inc');
+ openinc(stabfile,'rspstab.inc');
+ openinc(dwarffile,'rspdwrf.inc');
+ openinc(norfile,'rspnor.inc');
+ openinc(rnifile,'rsprni.inc');
+ openinc(srifile,'rspsri.inc');
+ first:=true;
+ for i:=0 to regcount-1 do
+ begin
+ if not first then
+ begin
+ writeln(numfile,',');
+ writeln(stdfile,',');
+ writeln(stabfile,',');
+ writeln(dwarffile,',');
+ writeln(rnifile,',');
+ writeln(srifile,',');
+ end
+ else
+ first:=false;
+ writeln(confile,'NR_',names[i],' = tregister(',numbers[i],');');
+ writeln(supfile,'RS_',names[i],' = ',supregs[i],';');
+ write(numfile,'NR_',names[i]);
+ write(stdfile,'''',stdnames[i],'''');
+ write(stabfile,stabs[i]);
+ write(dwarffile,dwarfs[i]);
+ write(rnifile,regnumber_index[i]);
+ write(srifile,std_regname_index[i]);
+ end;
+ write(norfile,regcount);
+ close(confile);
+ close(supfile);
+ closeinc(numfile);
+ closeinc(stdfile);
+ closeinc(stabfile);
+ closeinc(dwarffile);
+ closeinc(norfile);
+ closeinc(rnifile);
+ closeinc(srifile);
+ writeln('Done!');
+ writeln(regcount,' registers procesed');
+end;
+
+
+begin
+ writeln('Register Table Converter Version ',Version);
+ line:=0;
+ regcount:=0;
+ read_spreg_file;
+ regcount_bsstart:=1;
+ while 2*regcount_bsstart<regcount do
+ regcount_bsstart:=regcount_bsstart*2;
+ build_regnum_index;
+ build_std_regname_index;
+ write_inc_files;
+end.
diff --git a/closures/compiler/utils/mkx86ins.pp b/closures/compiler/utils/mkx86ins.pp
new file mode 100644
index 0000000000..72cbc8b5cb
--- /dev/null
+++ b/closures/compiler/utils/mkx86ins.pp
@@ -0,0 +1,442 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman and Florian Klaempfl
+
+ Convert i386ins.dat from Nasm to a .inc file for usage with
+ the Free pascal compiler
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+{$mode objfpc}
+program mkx86ins;
+
+const
+ Version = '1.6.0';
+ max_operands = 4;
+var
+ s : string;
+ i : longint;
+ x86_64 : boolean;
+
+ function lower(const s : string) : string;
+ {
+ return lowercased string of s
+ }
+ var
+ i : longint;
+ begin
+ for i:=1 to length(s) do
+ if s[i] in ['A'..'Z'] then
+ lower[i]:=char(byte(s[i])+32)
+ else
+ lower[i]:=s[i];
+ lower[0]:=s[0];
+ end;
+
+ function Replace(var s:string;const s1,s2:string):boolean;
+ var
+ i : longint;
+ begin
+ i:=pos(s1,s);
+ if i>0 then
+ begin
+ Delete(s,i,length(s1));
+ Insert(s2,s,i);
+ Replace:=true;
+ end
+ else
+ Replace:=false;
+ end;
+
+
+function formatop(s:string;allowsizeonly:boolean):string;
+ const
+ replaces=26;
+ replacetab : array[1..replaces,1..2] of string[32]=(
+ (':',' or ot_colon'),
+ ('reg','regnorm'),
+ ('regmem','rm_gpr'),
+ ('rm8','rm_gpr or ot_bits8'),
+ ('rm16','rm_gpr or ot_bits16'),
+ ('rm32','rm_gpr or ot_bits32'),
+ ('rm64','rm_gpr or ot_bits64'),
+ ('rm80','rm_gpr or ot_bits80'),
+ ('mem8','memory or ot_bits8'),
+ ('mem16','memory or ot_bits16'),
+ ('mem32','memory or ot_bits32'),
+ ('mem64','memory or ot_bits64'),
+ ('mem80','memory or ot_bits80'),
+ ('mem','memory'),
+ ('memory_offs','mem_offs'),
+ ('imm8','immediate or ot_bits8'),
+ ('imm16','immediate or ot_bits16'),
+ ('imm32','immediate or ot_bits32'),
+ ('imm64','immediate or ot_bits64'),
+ ('imm80','immediate or ot_bits80'),
+ ('imm','immediate'),
+ ('8','bits8'),
+ ('16','bits16'),
+ ('32','bits32'),
+ ('64','bits64'),
+ ('80','bits80')
+ );
+ var
+ i : longint;
+ begin
+ for i:=1to replaces do
+ begin
+ if s=replacetab[i,1] then
+ begin
+ s:=replacetab[i,2];
+ break;
+ end;
+ end;
+ formatop:=s;
+ end;
+
+
+function readnumber : longint;
+
+ var
+ base : longint;
+ begin
+ result:=0;
+ if s[i]='\' then
+ begin
+ base:=8;
+ inc(i);
+ if s[i]='x' then
+ begin
+ base:=16;
+ inc(i);
+ end;
+ end
+ else
+ base:=10;
+ s[i]:=upcase(s[i]);
+ while s[i] in ['0'..'9','A'..'F'] do
+ begin
+ case s[i] of
+ '0'..'9':
+ result:=result*base+ord(s[i])-ord('0');
+
+ 'A'..'F':
+ result:=result*base+ord(s[i])-ord('A')+10;
+ end;
+ inc(i);
+ end;
+ end;
+
+function tostr(l : longint) : string;
+
+ var
+ hs : string;
+
+ begin
+ str(l,hs);
+ tostr:=hs;
+ end;
+
+function readstr : string;
+
+ begin
+ result:='';
+ while (s[i] in ['0'..'9','A'..'Z','a'..'z','_']) and (i<=length(s)) do
+ begin
+ result:=result+s[i];
+ inc(i);
+ end;
+ end;
+
+procedure skipspace;
+
+ begin
+ while (s[i] in [' ',#9]) do
+ inc(i);
+ end;
+
+procedure openinc(out f:text;const fn:string);
+begin
+ writeln('creating ',fn);
+ assign(f,fn);
+ rewrite(f);
+ writeln(f,'{ don''t edit, this file is generated from x86ins.dat }');
+ writeln(f,'(');
+end;
+
+
+procedure closeinc(var f:text);
+begin
+ writeln(f);
+ writeln(f,');');
+ close(f);
+end;
+
+
+var
+ attsuffix,
+ hs : string;
+ j : longint;
+ firstopcode,
+ first : boolean;
+ maxinfolen,
+ code : byte;
+ insns : longint;
+ attsuffile,propfile,opfile,
+ nopfile,attfile,intfile,
+ infile,insfile : text;
+ { instruction fields }
+ skip : boolean;
+ literalcount,
+ ops : longint;
+ intopcode,
+ attopcode,
+ opcode,
+ codes,
+ flags : string;
+ optypes : array[1..max_operands] of string;
+begin
+ writeln('Nasm Instruction Table Converter Version ',Version);
+ x86_64:=paramstr(1)='x86_64';
+ insns:=0;
+ maxinfolen:=0;
+ { open dat file }
+ assign(infile,'../x86/x86ins.dat');
+ if x86_64 then
+ begin
+ { create inc files }
+ openinc(insfile,'x8664tab.inc');
+ openinc(opfile,'x8664op.inc');
+ assign(nopfile,'x8664nop.inc');
+ openinc(attfile,'x8664att.inc');
+ openinc(attsuffile,'x8664ats.inc');
+ openinc(intfile,'x8664int.inc');
+ openinc(propfile,'x8664pro.inc');
+ end
+ else
+ begin
+ { create inc files }
+ openinc(insfile,'i386tab.inc');
+ openinc(opfile,'i386op.inc');
+ assign(nopfile,'i386nop.inc');
+ openinc(attfile,'i386att.inc');
+ openinc(attsuffile,'i386atts.inc');
+ openinc(intfile,'i386int.inc');
+ openinc(propfile,'i386prop.inc');
+ end;
+ rewrite(nopfile);
+ writeln(nopfile,'{ don''t edit, this file is generated from x86ins.dat }');
+ reset(infile);
+ first:=true;
+ opcode:='';
+ firstopcode:=true;
+ while not(eof(infile)) do
+ begin
+ { handle comment }
+ readln(infile,s);
+ while (s[1]=' ') do
+ delete(s,1,1);
+ if (s='') or (s[1]=';') then
+ continue;
+ if (s[1]='[') then
+ begin
+ i:=pos(',',s);
+ j:=pos(']',s);
+ if i=0 then
+ begin
+ opcode:='A_'+Copy(s,2,j-2);
+ intopcode:=Copy(s,2,j-2);
+ { Conditional }
+ if (intopcode[length(intopcode)]='c') and
+ (intopcode[length(intopcode)-1]='c') then
+ dec(byte(intopcode[0]),2);
+ attopcode:=intopcode;
+ attsuffix:='attsufNONE';
+ end
+ else
+ begin
+ opcode:='A_'+Copy(s,2,i-2);
+ intopcode:=Copy(s,2,i-2);
+ { intel conditional }
+ if (intopcode[length(intopcode)]='c') and
+ (intopcode[length(intopcode)-1]='c') then
+ dec(byte(intopcode[0]),2);
+ attopcode:=Copy(s,i+1,j-i-1);
+ { att Suffix }
+ case attopcode[length(attopcode)] of
+ 'X' :
+ begin
+ dec(attopcode[0]);
+ attsuffix:='attsufINT';
+ end;
+ 'Y' :
+ begin
+ dec(attopcode[0]);
+ attsuffix:='attsufINTdual';
+ end;
+ 'F' :
+ begin
+ dec(attopcode[0]);
+ attsuffix:='attsufFPU';
+ end;
+ 'R' :
+ begin
+ dec(attopcode[0]);
+ attsuffix:='attsufFPUint';
+ end;
+ else
+ attsuffix:='attsufNONE';
+ end;
+ { att Conditional }
+ if (attopcode[length(attopcode)]='C') and
+ (attopcode[length(attopcode)-1]='C') then
+ dec(byte(attopcode[0]),2);
+ end;
+ intopcode:=Lower(intopcode);
+ attopcode:=Lower(attopcode);
+ if firstopcode then
+ firstopcode:=false
+ else
+ begin
+ writeln(opfile,',');
+ writeln(attfile,',');
+ writeln(attsuffile,',');
+ writeln(intfile,',');
+ writeln(propfile,',');
+ end;
+ write(opfile,opcode);
+ write(intfile,'''',intopcode,'''');
+ write(attfile,'''',attopcode,'''');
+ write(attsuffile,attsuffix);
+ { read the next line which contains the Change options }
+ repeat
+ readln(infile,s);
+ until eof(infile) or ((s<>'') and (s[1]<>';'));
+ write(propfile,'(Ch: ',s,')');
+ continue;
+ end;
+ { we must have an opcode }
+ if opcode='' then
+ runerror(234);
+ { clear }
+ ops:=0;
+ for i:=low(optypes) to high(optypes) do
+ optypes[i]:='';
+ codes:='';
+ flags:='';
+ skip:=false;
+ { ops and optypes }
+ i:=1;
+ repeat
+ hs:=readstr;
+ if (hs='void') or (hs='ignore') then
+ break;
+ inc(ops);
+ optypes[ops]:=optypes[ops]+'ot_'+formatop(hs,false);
+ while s[i]='|' do
+ begin
+ inc(i);
+ optypes[ops]:=optypes[ops]+' or ot_'+formatop(readstr,true);
+ end;
+ if s[i] in [',',':'] then
+ inc(i)
+ else
+ break;
+ until false;
+ for j:=1 to max_operands-ops do
+ optypes[max_operands-j+1]:='ot_none';
+ { codes }
+ skipspace;
+ j:=0;
+ literalcount:=0;
+ if s[i] in ['\','0'..'9'] then
+ begin
+ while not(s[i] in [' ',#9]) do
+ begin
+ code:=readnumber;
+ { for some codes we want also to change the optypes, but not
+ if the code belongs to a literal sequence }
+ if (literalcount=0) and (code>=1) and (code<=3) then
+ literalcount:=code
+ else
+ begin
+ if literalcount>0 then
+ dec(literalcount)
+ else
+ begin
+ case code of
+ 12,13,14 :
+ optypes[code-11]:=optypes[code-11]+' or ot_signed';
+ end;
+ end;
+ end;
+ codes:=codes+'#'+tostr(code);
+ inc(j);
+ end;
+ end
+ else
+ begin
+ readstr;
+ codes:='#0';
+ end;
+ if j>maxinfolen then
+ maxinfolen:=j;
+ { flags }
+ skipspace;
+ while not(s[i] in [' ',#9,#13,#10]) and (i<=length(s)) do
+ begin
+ hs:=readstr;
+ if x86_64 then
+ begin
+ if (upcase(hs)='NOX86_64') then
+ skip:=true;
+ end
+ else
+ begin
+ if (upcase(hs)='X86_64') then
+ skip:=true;
+ end;
+ if hs<>'ND' then
+ begin
+ if flags<>'' then
+ flags:=flags+' or ';
+ flags:=flags+'if_'+lower(hs);
+ end;
+ if (s[i]=',') and (i<=length(s)) then
+ inc(i)
+ else
+ break;
+ end;
+ { write instruction }
+ if not skip then
+ begin
+ if not(first) then
+ writeln(insfile,',')
+ else
+ first:=false;
+ writeln(insfile,' (');
+ writeln(insfile,' opcode : ',opcode,';');
+ writeln(insfile,' ops : ',ops,';');
+ writeln(insfile,' optypes : (',optypes[1],',',optypes[2],',',optypes[3],',',optypes[4],');');
+ writeln(insfile,' code : ',codes,';');
+ writeln(insfile,' flags : ',flags);
+ write(insfile,' )');
+ inc(insns);
+ end;
+ end;
+ close(infile);
+ closeinc(insfile);
+ closeinc(intfile);
+ closeinc(attfile);
+ closeinc(attsuffile);
+ closeinc(opfile);
+ writeln(nopfile,insns,';');
+ close(nopfile);
+ closeinc(propfile);
+ writeln(insns,' nodes processed (maxinfolen=',maxinfolen,')');
+end.
diff --git a/closures/compiler/utils/mkx86reg.pp b/closures/compiler/utils/mkx86reg.pp
new file mode 100644
index 0000000000..2a9e208c79
--- /dev/null
+++ b/closures/compiler/utils/mkx86reg.pp
@@ -0,0 +1,443 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman and Florian Klaempfl
+
+ Convert i386reg.dat to several .inc files for usage with
+ the Free pascal compiler
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+{$mode objfpc}
+{$i+}
+program mkx86reg;
+
+const Version = '1.00';
+ max_regcount = 128;
+
+var s : string;
+ i : longint;
+ line : longint;
+ regcount:byte;
+ regcount_bsstart:byte;
+ names,numbers,stdnames,intnames,nasmnames,attnames,stabs,dwarf32,dwarf64,ots,ops:
+ array[0..max_regcount-1] of string[63];
+ regnumber_index,std_regname_index,int_regname_index,att_regname_index,
+ nasm_regname_index:array[0..max_regcount-1] of byte;
+ x86_64 : boolean;
+ fileprefix : string;
+
+function tostr(l : longint) : string;
+
+begin
+ str(l,tostr);
+end;
+
+function readstr : string;
+ begin
+ result:='';
+ while (s[i]<>',') and (i<=length(s)) do
+ begin
+ result:=result+s[i];
+ inc(i);
+ end;
+ readstr:=result;
+ end;
+
+
+procedure readcomma;
+ begin
+ if s[i]<>',' then
+ begin
+ writeln('Missing "," at line ',line);
+ writeln('Line: "',s,'"');
+ halt(1);
+ end;
+ inc(i);
+ end;
+
+
+procedure skipspace;
+
+ begin
+ while (s[i] in [' ',#9]) do
+ inc(i);
+ end;
+
+procedure openinc(out f:text;const fn:string);
+begin
+ writeln('creating ',fn);
+ assign(f,fn);
+ rewrite(f);
+ writeln(f,'{ don''t edit, this file is generated from x86reg.dat }');
+end;
+
+
+procedure closeinc(var f:text);
+begin
+ writeln(f);
+ close(f);
+end;
+
+procedure build_regnum_index;
+
+var h,i,j,p,t:byte;
+
+begin
+ {Build the registernumber2regindex index.
+ Step 1: Fill.}
+ for i:=0 to regcount-1 do
+ regnumber_index[i]:=i;
+ {Step 2: Sort. We use a Shell-Metzner sort.}
+ p:=regcount_bsstart;
+ repeat
+ for h:=0 to regcount-p-1 do
+ begin
+ i:=h;
+ repeat
+ j:=i+p;
+ if numbers[regnumber_index[j]]>=numbers[regnumber_index[i]] then
+ break;
+ t:=regnumber_index[i];
+ regnumber_index[i]:=regnumber_index[j];
+ regnumber_index[j]:=t;
+ if i<p then
+ break;
+ dec(i,p);
+ until false;
+ end;
+ p:=p shr 1;
+ until p=0;
+end;
+
+procedure build_std_regname_index;
+
+var h,i,j,p,t:byte;
+
+begin
+ {Build the registernumber2regindex index.
+ Step 1: Fill.}
+ for i:=0 to regcount-1 do
+ std_regname_index[i]:=i;
+ {Step 2: Sort. We use a Shell-Metzner sort.}
+ p:=regcount_bsstart;
+ repeat
+ for h:=0 to regcount-p-1 do
+ begin
+ i:=h;
+ repeat
+ j:=i+p;
+ if stdnames[std_regname_index[j]]>=stdnames[std_regname_index[i]] then
+ break;
+ t:=std_regname_index[i];
+ std_regname_index[i]:=std_regname_index[j];
+ std_regname_index[j]:=t;
+ if i<p then
+ break;
+ dec(i,p);
+ until false;
+ end;
+ p:=p shr 1;
+ until p=0;
+end;
+
+procedure build_int_regname_index;
+
+var h,i,j,p,t:byte;
+
+begin
+ {Build the registernumber2regindex index.
+ Step 1: Fill.}
+ for i:=0 to regcount-1 do
+ int_regname_index[i]:=i;
+ {Step 2: Sort. We use a Shell-Metzner sort.}
+ p:=regcount_bsstart;
+ repeat
+ for h:=0 to regcount-p-1 do
+ begin
+ i:=h;
+ repeat
+ j:=i+p;
+ if intnames[int_regname_index[j]]>=intnames[int_regname_index[i]] then
+ break;
+ t:=int_regname_index[i];
+ int_regname_index[i]:=int_regname_index[j];
+ int_regname_index[j]:=t;
+ if i<p then
+ break;
+ dec(i,p);
+ until false;
+ end;
+ p:=p shr 1;
+ until p=0;
+end;
+
+procedure build_att_regname_index;
+
+var h,i,j,p,t:byte;
+
+begin
+ {Build the registernumber2regindex index.
+ Step 1: Fill.}
+ for i:=0 to regcount-1 do
+ att_regname_index[i]:=i;
+ {Step 2: Sort. We use a Shell-Metzner sort.}
+ p:=regcount_bsstart;
+ repeat
+ for h:=0 to regcount-p-1 do
+ begin
+ i:=h;
+ repeat
+ j:=i+p;
+ if attnames[att_regname_index[j]]>=attnames[att_regname_index[i]] then
+ break;
+ t:=att_regname_index[i];
+ att_regname_index[i]:=att_regname_index[j];
+ att_regname_index[j]:=t;
+ if i<p then
+ break;
+ dec(i,p);
+ until false;
+ end;
+ p:=p shr 1;
+ until p=0;
+end;
+
+procedure build_nasm_regname_index;
+
+var h,i,j,p,t:byte;
+
+begin
+ {Build the registernumber2regindex index.
+ Step 1: Fill.}
+ for i:=0 to regcount-1 do
+ nasm_regname_index[i]:=i;
+ {Step 2: Sort. We use a Shell-Metzner sort.}
+ p:=regcount_bsstart;
+ repeat
+ for h:=0 to regcount-p-1 do
+ begin
+ i:=h;
+ repeat
+ j:=i+p;
+ if nasmnames[nasm_regname_index[j]]>=nasmnames[nasm_regname_index[i]] then
+ break;
+ t:=nasm_regname_index[i];
+ nasm_regname_index[i]:=nasm_regname_index[j];
+ nasm_regname_index[j]:=t;
+ if i<p then
+ break;
+ dec(i,p);
+ until false;
+ end;
+ p:=p shr 1;
+ until p=0;
+end;
+
+procedure read_x86reg_file;
+
+var infile:text;
+ cpustr:string;
+
+begin
+ { open dat file }
+ assign(infile,'x86reg.dat');
+ reset(infile);
+ while not(eof(infile)) do
+ begin
+ { handle comment }
+ readln(infile,s);
+ inc(line);
+ while (s[1]=' ') do
+ delete(s,1,1);
+ if (s='') or (s[1]=';') then
+ continue;
+
+ i:=1;
+ names[regcount]:=readstr;
+ readcomma;
+ numbers[regcount]:=readstr;
+ readcomma;
+ stdnames[regcount]:=readstr;
+ readcomma;
+ attnames[regcount]:=readstr;
+ readcomma;
+ intnames[regcount]:=readstr;
+ readcomma;
+ nasmnames[regcount]:=readstr;
+ readcomma;
+ stabs[regcount]:=readstr;
+ readcomma;
+ dwarf32[regcount]:=readstr;
+ readcomma;
+ dwarf64[regcount]:=readstr;
+ readcomma;
+ ots[regcount]:=readstr;
+ readcomma;
+ ops[regcount]:=readstr;
+ if s[i]=',' then
+ begin
+ readcomma;
+ cpustr:=readstr;
+ end
+ else
+ cpustr:='';
+ if i<length(s) then
+ begin
+ writeln('Extra chars at end of line, at line ',line);
+ writeln('Line: "',s,'"');
+ halt(1);
+ end;
+ if (cpustr<>'64') or x86_64 then
+ begin
+ inc(regcount);
+ if regcount>max_regcount then
+ begin
+ writeln('Error: Too much registers, please increase maxregcount in source');
+ halt(2);
+ end;
+ end;
+ end;
+ close(infile);
+end;
+
+procedure write_inc_files;
+
+var attfile,intfile,otfile,opfile,
+ norfile,nasmfile,stdfile,
+ numfile,stabfile,dwrffile,confile,
+ rnifile,irifile,srifile,
+ arifile,nrifile:text;
+ first:boolean;
+
+begin
+ { create inc files }
+ openinc(confile,fileprefix+'con.inc');
+ openinc(numfile,fileprefix+'num.inc');
+ openinc(stdfile,fileprefix+'std.inc');
+ openinc(attfile,fileprefix+'att.inc');
+ openinc(intfile,fileprefix+'int.inc');
+ openinc(nasmfile,fileprefix+'nasm.inc');
+ openinc(stabfile,fileprefix+'stab.inc');
+ openinc(dwrffile,fileprefix+'dwrf.inc');
+ openinc(otfile,fileprefix+'ot.inc');
+ openinc(opfile,fileprefix+'op.inc');
+ openinc(norfile,fileprefix+'nor.inc');
+ openinc(rnifile,fileprefix+'rni.inc');
+ openinc(srifile,fileprefix+'sri.inc');
+ openinc(arifile,fileprefix+'ari.inc');
+ openinc(irifile,fileprefix+'iri.inc');
+ openinc(nrifile,fileprefix+'nri.inc');
+ first:=true;
+ for i:=0 to regcount-1 do
+ begin
+ if not first then
+ begin
+ writeln(numfile,',');
+ writeln(stdfile,',');
+ writeln(attfile,',');
+ writeln(intfile,',');
+ writeln(nasmfile,',');
+ writeln(stabfile,',');
+ writeln(dwrffile,',');
+ writeln(otfile,',');
+ writeln(opfile,',');
+ writeln(rnifile,',');
+ writeln(srifile,',');
+ writeln(arifile,',');
+ writeln(irifile,',');
+ writeln(nrifile,',');
+ end
+ else
+ first:=false;
+ writeln(confile,names[i],' = ','tregister(',numbers[i],')',';');
+ write(numfile,'tregister(',numbers[i],')');
+ write(stdfile,'''',stdnames[i],'''');
+ write(attfile,'''',attnames[i],'''');
+ write(intfile,'''',intnames[i],'''');
+ write(nasmfile,'''',nasmnames[i],'''');
+ { stabs uses the same register numbering as dwarf
+ for x86_64 CPU }
+ if x86_64 then
+ write(stabfile,dwarf64[i])
+ else
+ write(stabfile,stabs[i]);
+ if x86_64 then
+ write(dwrffile,dwarf64[i])
+ else
+ write(dwrffile,dwarf32[i]);
+ write(otfile,ots[i]);
+ write(opfile,ops[i]);
+ write(rnifile,regnumber_index[i]);
+ write(srifile,std_regname_index[i]);
+ write(arifile,att_regname_index[i]);
+ write(irifile,int_regname_index[i]);
+ write(nrifile,nasm_regname_index[i]);
+ end;
+ write(norfile,regcount);
+ close(confile);
+ closeinc(numfile);
+ closeinc(attfile);
+ closeinc(stdfile);
+ closeinc(intfile);
+ closeinc(nasmfile);
+ closeinc(stabfile);
+ closeinc(dwrffile);
+ closeinc(otfile);
+ closeinc(opfile);
+ closeinc(norfile);
+ closeinc(rnifile);
+ closeinc(srifile);
+ closeinc(arifile);
+ closeinc(irifile);
+ closeinc(nrifile);
+ writeln('Done!');
+ writeln(regcount,' registers procesed');
+end;
+
+
+begin
+ writeln('Register Table Converter Version ',Version);
+ if paramcount=0 then
+ begin
+ x86_64:=false;
+ end
+ else
+ begin
+ x86_64:=paramstr(1)='x86_64';
+ if (paramcount<>1) or
+ ((paramstr(1)<>'i386') and (paramstr(1)<>'x86_64')) then
+ begin
+ writeln('Usage: ',paramstr(0));
+ writeln('Only one optional parameter is allowed: i386 or x86_64');
+ halt(1);
+ end;
+ end;
+ if x86_64 then
+ begin
+ fileprefix:='r8664';
+ writeln('Processing for CPU x86_64');
+ end
+ else
+ begin
+ fileprefix:='r386';
+ writeln('Processing for CPU i386');
+ end;
+ line:=0;
+ regcount:=0;
+ read_x86reg_file;
+ regcount_bsstart:=1;
+ while 2*regcount_bsstart<regcount do
+ regcount_bsstart:=regcount_bsstart*2;
+ build_regnum_index;
+ build_int_regname_index;
+ if not(x86_64) then
+ build_nasm_regname_index;
+ build_std_regname_index;
+ build_att_regname_index;
+ write_inc_files;
+end.
diff --git a/closures/compiler/utils/msg2inc.pp b/closures/compiler/utils/msg2inc.pp
new file mode 100644
index 0000000000..ec624bb5ca
--- /dev/null
+++ b/closures/compiler/utils/msg2inc.pp
@@ -0,0 +1,823 @@
+{
+ This program is part of the Free Pascal run time library.
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ Convert a .msg file to an .inc file with a const array of char
+ And for the lazy docwriters it can also generate some TeX output
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+program msg2inc;
+uses
+ strings;
+
+{$ifdef unix}
+ {$define EOL_ONE_CHAR}
+{$endif unix}
+{$ifdef amiga}
+ {$define EOL_ONE_CHAR}
+{$endif amiga}
+{$ifdef morphos}
+ {$define EOL_ONE_CHAR}
+{$endif}
+{$ifdef macos}
+ {$define EOL_ONE_CHAR}
+{$endif}
+
+const
+ version='1.00';
+{$ifdef EOL_ONE_CHAR}
+ eollen=1;
+{$else}
+ eollen=2;
+{$endif}
+ msgparts = 20;
+
+type
+ TMode=(M_Char,M_Tex,M_Intel,M_String,M_Renumber);
+var
+ InFile,
+ OutFile,
+ OutName : string;
+ Mode : TMode;
+ TexHeader : boolean;
+
+ MsgTxt : pchar;
+ EnumTxt : pchar;
+ enumsize,
+ msgsize : longint;
+
+ msgidxmax : array[1..msgparts] of longint;
+ msgs : array[0..msgparts,0..999] of boolean;
+
+procedure LoadMsgFile(const fn:string);
+var
+ f : text;
+ error,
+ multiline : boolean;
+ code : word;
+ numpart,numidx,
+ line,i,j,num : longint;
+ ptxt,
+ penum : pchar;
+ number,
+ s,s1 : string;
+
+ procedure err(const msgstr:string);
+ begin
+ writeln('error in line ',line,': ',msgstr);
+ error:=true;
+ end;
+
+begin
+ Writeln('Loading messagefile ',fn);
+{Read the message file}
+ assign(f,fn);
+ {$push} {$I-}
+ reset(f);
+ {$pop}
+ if ioresult<>0 then
+ begin
+ WriteLn('fatal error: '+fn+' not found');
+ halt(1);
+ end;
+{ First parse the file and count bytes needed }
+ fillchar(msgidxmax,sizeof(msgidxmax),0);
+ fillchar(msgs,sizeof(msgs),0);
+ error:=false;
+ line:=0;
+ multiline:=false;
+ msgsize:=0;
+ while not eof(f) do
+ begin
+ readln(f,s);
+ inc(line);
+ if multiline then
+ begin
+ if s=']' then
+ multiline:=false
+ else
+ inc(msgsize,length(s)+1); { +1 for linebreak }
+ end
+ else
+ begin
+ if (s<>'') and not(s[1] in ['#',';','%']) then
+ begin
+ i:=pos('=',s);
+ if i>0 then
+ begin
+ j:=i+1;
+ if not(s[j] in ['0'..'9']) then
+ err('no number found')
+ else
+ begin
+ while (s[j] in ['0'..'9']) do
+ inc(j);
+ end;
+ if j-i-1<>5 then
+ err('number length is not 5');
+ number:=Copy(s,i+1,j-i-1);
+ { update the max index }
+ val(number,num,code);
+ numpart:=num div 1000;
+ if numpart=0 then
+ err('number should be > 1000');
+ numidx:=num mod 1000;
+ { duplicate ? }
+ if msgs[numpart,numidx] then
+ err('duplicate number found');
+ msgs[numpart,numidx]:=true;
+ { check range }
+ if numpart > msgparts then
+ err('number is to large')
+ else
+ if numidx > msgidxmax[numpart] then
+ msgidxmax[numpart]:=numidx;
+ if s[j+1]='[' then
+ begin
+ inc(msgsize,j-i);
+ multiline:=true
+ end
+ else
+ inc(msgsize,length(s)-i+1);
+ inc(enumsize,j);
+ end
+ else
+ err('no = found');
+ end;
+ end;
+ end;
+ if multiline then
+ err('still in multiline mode');
+ if error then
+ begin
+ close(f);
+ writeln('aborting');
+ halt(1);
+ end;
+{ alloc memory }
+ getmem(msgtxt,msgsize);
+{ no linebreak after last entry }
+ dec(msgsize);
+ ptxt:=msgtxt;
+ getmem(enumtxt,enumsize);
+ penum:=enumtxt;
+{ now read the buffer in mem }
+ reset(f);
+ while not eof(f) do
+ begin
+ readln(f,s);
+ if multiline then
+ begin
+ if s=']' then
+ begin
+ multiline:=false;
+ { overwrite last eol }
+ dec(ptxt);
+ ptxt^:=#0;
+ inc(ptxt);
+ end
+ else
+ begin
+ move(s[1],ptxt^,length(s));
+ inc(ptxt,length(s));
+ ptxt^:=#10;
+ inc(ptxt);
+ end;
+ end
+ else
+ begin
+ if (s<>'') and not(s[1] in ['#',';','%']) then
+ begin
+ i:=pos('=',s);
+ if i>0 then
+ begin
+ j:=i+1;
+ while (s[j] in ['0'..'9']) do
+ inc(j);
+ {enum}
+ move(s[1],penum^,i-1);
+ inc(penum,i-1);
+ penum^:='=';
+ inc(penum);
+ number:=Copy(s,i+1,j-i-1);
+ move(number[1],penum^,length(number));
+ inc(penum,length(number));
+ penum^:=#0;
+ inc(penum);
+ { multiline start then no txt }
+ if s[j+1]='[' then
+ begin
+ s1:=Copy(s,i+1,j-i);
+ move(s1[1],ptxt^,length(s1));
+ inc(ptxt,length(s1));
+ multiline:=true;
+ end
+ else
+ begin
+ { txt including number }
+ s1:=Copy(s,i+1,255);
+ move(s1[1],ptxt^,length(s1));
+ inc(ptxt,length(s1));
+ ptxt^:=#0;
+ inc(ptxt);
+ end;
+ end;
+ end;
+ end;
+ end;
+ close(f);
+end;
+
+
+{*****************************************************************************
+ WriteEnumFile
+*****************************************************************************}
+
+procedure WriteEnumFile(const fn,typename:string);
+var
+ t : text;
+ i : longint;
+ p : pchar;
+ start : boolean;
+begin
+ writeln('Writing enumfile '+fn);
+{Open textfile}
+ assign(t,fn);
+ rewrite(t);
+ writeln(t,'const');
+{Parse buffer in msgbuf and create indexs}
+ p:=enumtxt;
+ start:=true;
+ for i:=1 to enumsize do
+ begin
+ if start then
+ begin
+ write(t,' ');
+ start:=false;
+ end;
+ if p^=#0 then
+ begin
+ writeln(t,';');
+ start:=true;
+ end
+ else
+ begin
+ write(t,p^);
+ end;
+ inc(p);
+ end;
+ writeln(t,'');
+ { msgtxt size }
+ writeln(t,' MsgTxtSize = ',msgsize,';');
+ writeln(t,'');
+ { max msg idx table }
+ writeln(t,' MsgIdxMax : array[1..20] of longint=(');
+ write(t,' ');
+ for i:=1 to 20 do
+ begin
+ write(t,msgidxmax[i]+1);
+ if i<20 then
+ write(t,',');
+ if i=10 then
+ begin
+ writeln(t,'');
+ write(t,' ');
+ end;
+ end;
+ writeln(t,'');
+ writeln(t,' );');
+ close(t);
+end;
+
+
+{*****************************************************************************
+ WriteStringFile
+*****************************************************************************}
+
+procedure WriteStringFile(const fn,constname:string);
+const
+ maxslen=240; { to overcome aligning problems }
+
+ function l0(l:longint):string;
+ var
+ s : string[16];
+ begin
+ str(l,s);
+ while (length(s)<5) do
+ s:='0'+s;
+ l0:=s;
+ end;
+
+var
+ t : text;
+ f : file;
+ slen,
+ len,i : longint;
+ p : pchar;
+ s : string;
+ start,
+ quote : boolean;
+begin
+ writeln('Writing stringfile ',fn);
+{Open textfile}
+ assign(t,fn);
+ rewrite(t);
+ writeln(t,'{$ifdef Delphi}');
+ writeln(t,'const '+constname+' : array[0..000000] of string[',maxslen,']=(');
+ writeln(t,'{$else Delphi}');
+ writeln(t,'const '+constname+' : array[0..000000,1..',maxslen,'] of char=(');
+ write(t,'{$endif Delphi}');
+{Parse buffer in msgbuf and create indexs}
+ p:=msgtxt;
+ slen:=0;
+ len:=0;
+ quote:=false;
+ start:=true;
+ for i:=1 to msgsize do
+ begin
+ if slen>=maxslen then
+ begin
+ if quote then
+ begin
+ write(t,'''');
+ quote:=false;
+ end;
+ write(t,',');
+ slen:=0;
+ inc(len);
+ end;
+ if (len>70) or (start) then
+ begin
+ if quote then
+ begin
+ write(t,'''');
+ quote:=false;
+ end;
+ if slen>0 then
+ writeln(t,'+')
+ else
+ writeln(t);
+ len:=0;
+ start:=false;
+ end;
+ if (len=0) then
+ write(t,' ');
+ if (ord(p^)>=32) and (p^<>#39) then
+ begin
+ if not quote then
+ begin
+ write(t,'''');
+ quote:=true;
+ inc(len);
+ end;
+ write(t,p^);
+ inc(len);
+ end
+ else
+ begin
+ if quote then
+ begin
+ write(t,'''');
+ inc(len);
+ quote:=false;
+ end;
+ write(t,'#'+chr(ord(p^) div 100+48)+chr((ord(p^) mod 100) div 10+48)+chr(ord(p^) mod 10+48));
+ inc(len,3);
+ end;
+ if p^ in [#0,#10] then
+ start:=true;
+ inc(slen);
+ inc(p);
+ end;
+ if quote then
+ write(t,'''');
+ writeln(t,'');
+ writeln(t,');');
+ close(t);
+{update arraysize}
+ s:=l0(msgsize div maxslen); { we start with 0 }
+ assign(f,fn);
+ reset(f,1);
+ seek(f,34+eollen+length(constname));
+ blockwrite(f,s[1],5);
+ seek(f,90+3*eollen+2*length(constname));
+ blockwrite(f,s[1],5);
+ close(f);
+end;
+
+
+{*****************************************************************************
+ WriteCharFile
+*****************************************************************************}
+
+procedure WriteCharFile(const fn,constname:string);
+
+ function l0(l:longint):string;
+ var
+ s : string[16];
+ begin
+ str(l,s);
+ while (length(s)<5) do
+ s:='0'+s;
+ l0:=s;
+ end;
+
+ function createconst(b:byte):string;
+ begin
+ if (b in [32..127]) and (b<>39) then
+ createconst:=''''+chr(b)+''''
+ else
+ createconst:='#'+chr(b div 100+48)+chr((b mod 100) div 10+48)+chr(b mod 10+48)
+ end;
+
+var
+ t : text;
+ f : file;
+ cidx,i : longint;
+ p : pchar;
+ s : string;
+begin
+ writeln('Writing charfile '+fn);
+{Open textfile}
+ assign(t,fn);
+ rewrite(t);
+ writeln(t,'const ',constname,' : array[1..00000] of char=(');
+{Parse buffer in msgbuf and create indexs}
+ p:=msgtxt;
+ cidx:=0;
+ for i:=1to msgsize do
+ begin
+ if cidx=15 then
+ begin
+ if cidx>0 then
+ writeln(t,',')
+ else
+ writeln(t,'');
+ write(t,' ');
+ cidx:=0;
+ end
+ else
+ if cidx>0 then
+ write(t,',')
+ else
+ write(t,' ');
+ write(t,createconst(ord(p^)));
+ inc(cidx);
+ inc(p);
+ end;
+ writeln(t,');');
+ close(t);
+{update arraysize}
+ s:=l0(msgsize);
+ assign(f,fn);
+ reset(f,1);
+ seek(f,18+length(constname));
+ blockwrite(f,s[1],5);
+ close(f);
+end;
+
+
+{*****************************************************************************
+ WriteIntelFile
+*****************************************************************************}
+
+procedure WriteIntelFile(const fn,constname:string);
+var
+ t : text;
+ len,i : longint;
+ p : pchar;
+ start,
+ quote : boolean;
+begin
+ writeln('Writing Intelfile ',fn);
+{Open textfile}
+ assign(t,fn);
+ rewrite(t);
+ writeln(t,'procedure '+constname+';assembler;');
+ writeln(t,'asm');
+{Parse buffer in msgbuf and create indexs}
+ p:=msgtxt;
+ len:=0;
+ start:=true;
+ quote:=false;
+ for i:=1to msgsize do
+ begin
+ if len>70 then
+ begin
+ if quote then
+ begin
+ write(t,'''');
+ quote:=false;
+ end;
+ writeln(t,'');
+ start:=true;
+ end;
+ if start then
+ begin
+ write(t,' db ''');
+ len:=0;
+ quote:=true;
+ end;
+ if (ord(p^)>=32) and (p^<>#39) then
+ begin
+ if not quote then
+ begin
+ write(t,',''');
+ quote:=true;
+ inc(len);
+ end;
+ write(t,p^);
+ inc(len);
+ end
+ else
+ begin
+ if quote then
+ begin
+ write(t,'''');
+ inc(len);
+ quote:=false;
+ end;
+ write(t,','+chr(ord(p^) div 100+48)+chr((ord(p^) mod 100) div 10+48)+chr(ord(p^) mod 10+48));
+ inc(len,4);
+ end;
+ inc(p);
+ end;
+ if quote then
+ write(t,'''');
+ writeln(t,'');
+ writeln(t,'end;');
+ close(t);
+end;
+
+
+{*****************************************************************************
+ RenumberFile
+*****************************************************************************}
+
+procedure RenumberFile(const fn,name:string);
+var
+ f,t : text;
+ i : longint;
+ s,s1 : string;
+begin
+ Writeln('Renumbering ',fn);
+{Read the message file}
+ assign(f,fn);
+ {$push} {$I-}
+ reset(f);
+ {$pop}
+ if ioresult<>0 then
+ begin
+ WriteLn('*** message file '+fn+' not found ***');
+ exit;
+ end;
+ assign(t,'msg2inc.$$$');
+ rewrite(t);
+ i:=0;
+ while not eof(f) do
+ begin
+ readln(f,s);
+ if (copy(s,1,length(Name))=Name) and (s[3] in ['0'..'9']) then
+ begin
+ inc(i);
+ str(i,s1);
+ while length(s1)<3 do
+ s1:='0'+s1;
+ writeln(t,Name+s1+Copy(s,6,255));
+ end
+ else
+ writeln(t,s);
+ end;
+ close(t);
+ close(f);
+{ rename new file }
+ erase(f);
+ rename(t,fn);
+end;
+
+
+{*****************************************************************************
+ WriteTexFile
+*****************************************************************************}
+
+Function EscapeString (Const S : String) : String;
+Var
+ I : longint;
+ hs : string;
+begin
+ hs:='';
+ for i:=1 to length(s) do
+ case S[i] of
+ '$' :
+ if (s[i+1] in ['0'..'9']) then
+ hs:=hs+'arg'
+ else
+ hs:=hs+'\$';
+ '&','{','}','#','_','%': // Escape these characters
+ hs := hs + '\' + S[i];
+ '~','^':
+ hs := hs + '\'+S[i]+' ';
+ '\':
+ hs:=hs+'$\backslash$'
+ else
+ hs := hs + S[i];
+ end;
+ EscapeString:=hs;
+end;
+
+procedure WriteTexFile(const infn,outfn:string);
+var
+ t,f : text;
+ line,
+ i,k : longint;
+ s,s1 : string;
+ texoutput : boolean;
+begin
+ Writeln('Loading messagefile ',infn);
+ writeln('Writing TeXfile ',outfn);
+{ Open infile }
+ assign(f,infn);
+ {$push} {$I-}
+ reset(f);
+ {$pop}
+ if ioresult<>0 then
+ begin
+ WriteLn('*** message file '+infn+' not found ***');
+ exit;
+ end;
+{ Open outfile }
+ assign(t,outfn);
+ rewrite(t);
+ If texheader then
+ begin
+ writeln (t,'\documentclass{article}');
+ writeln (t,'\usepackage{html}');
+ writeln (t,'\usepackage{fpc}');
+ writeln (t,'\begin{document}');
+ end;
+{ Parse }
+ line:=0;
+ TexOutput:=False;
+ while not eof(f) do
+ begin
+ readln(f,s);
+ inc(line);
+ If Pos ('# BeginOfTeX',S)=1 then
+ TexOutPut:=True
+ else if pos ('# EndOfTeX',S)=1 then
+ TexOutPut:=False;
+ if (s<>'') and not(s[1] in ['#',';']) and TeXOutPut then
+ begin
+ if s[1]='%' then
+ begin
+ Delete(s,1,1);
+ writeln(t,s);
+ end
+ else
+ begin
+ i:=pos('=',s);
+ if i>0 then
+ begin
+ inc(i);
+ while s[i] in ['0'..'9'] do
+ inc(i);
+ inc(i);
+ s1:='';
+ k:=0;
+ while (k<5) and (s[i+k]<>'_') do
+ begin
+ case s[i+k] of
+ 'W' : s1:='Warning: ';
+ 'E' : s1:='Error: ';
+ 'F' : s1:='Fatal: ';
+ 'N' : s1:='Note: ';
+ 'I' : s1:='Info: ';
+ 'H' : s1:='Hint: ';
+ end;
+ inc(k);
+ end;
+ if s[i+k]='_' then
+ inc(i,k+1);
+ writeln(t,'\item ['+s1+escapestring(Copy(s,i,255))+']');
+ end
+ else
+ writeln('error in line: ',line,' skipping');
+ end;
+ end;
+ end;
+ If TexHeader then
+ writeln (t,'\end{document}');
+ close(t);
+ close(f);
+end;
+
+
+{*****************************************************************************
+ Main Program
+*****************************************************************************}
+
+procedure getpara;
+var
+ ch : char;
+ para : string;
+ files,i : word;
+
+ procedure helpscreen;
+ begin
+ writeln('usage : msg2inc [Options] <msgfile> <incfile> <constname>');
+ writeln('<Options> can be : -T Create .doc TeX file');
+ writeln(' -TS Create .doc TeX file (stand-alone)');
+ writeln(' -I Intel style asm output');
+ writeln(' -S array of string');
+ writeln(' -C array of char');
+ writeln(' -R renumber section <incfile>');
+ writeln(' -V Show version');
+ writeln(' -? or -H This HelpScreen');
+ halt(1);
+ end;
+
+begin
+ Mode:=M_String;
+ FIles:=0;
+ for i:=1to paramcount do
+ begin
+ para:=paramstr(i);
+ if (para[1]='-') then
+ begin
+ ch:=upcase(para[2]);
+ delete(para,1,2);
+ case ch of
+ 'T' : begin
+ case upcase(para[1]) of
+ 'S' : TexHeader:=True;
+ end;
+ Mode:=M_Tex;
+ end;
+ 'I' : Mode:=M_Intel;
+ 'S' : Mode:=M_String;
+ 'C' : Mode:=M_Char;
+ 'R' : Mode:=M_Renumber;
+ 'V' : begin
+ Writeln('Msg2Inc ',version,' for Free Pascal (C) 1998-2002 Peter Vreman');
+ Writeln;
+ Halt;
+ end;
+ '?','H' : helpscreen;
+ end;
+ end
+ else
+ begin
+ inc(Files);
+ if Files>3 then
+ HelpScreen;
+ case Files of
+ 1 : InFile:=Para;
+ 2 : OutFile:=Para;
+ 3 : OutName:=Para;
+ end;
+ end;
+ end;
+ case Mode of
+ M_Renumber,
+ M_Tex : if Files<2 then
+ Helpscreen;
+ else
+ if FIles<3 then
+ HelpScreen;
+ end;
+end;
+
+
+begin
+ GetPara;
+ case Mode of
+ M_Renumber : begin
+ Renumberfile(Infile,OutFile);
+ end;
+ M_Tex : begin
+ WriteTexFile(InFile,Outfile);
+ end;
+ M_Intel : begin
+ Loadmsgfile(InFile);
+ WriteEnumFile(OutFile+'idx.inc',OutName+'const');
+ WriteIntelFile(OutFile+'txt.inc',OutName+'txt');
+ end;
+ M_String : begin
+ Loadmsgfile(InFile);
+ WriteEnumFile(OutFile+'idx.inc',OutName+'const');
+ WriteStringFile(OutFile+'txt.inc',OutName+'txt');
+ end;
+ M_Char : begin
+ Loadmsgfile(InFile);
+ WriteEnumFile(OutFile+'idx.inc',OutName+'const');
+ WriteCharFile(OutFile+'txt.inc',OutName+'txt');
+ end;
+ end;
+end.
diff --git a/closures/compiler/utils/msgdif.pp b/closures/compiler/utils/msgdif.pp
new file mode 100644
index 0000000000..4b49775bfb
--- /dev/null
+++ b/closures/compiler/utils/msgdif.pp
@@ -0,0 +1,529 @@
+{
+ This program is part of the Free Pascal run time library.
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ Show the differences between two .msg files
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+{ May be we need to compare a prefixes of option_help_pages too?
+ Currently this is not performed }
+
+Program messagedif;
+
+{$h+} {Huge strings}
+
+Uses
+ Strings;
+
+Type
+ TEnum = String;
+ TText = String;
+
+ PMsg = ^TMsg;
+ TMsg = Record
+ Line, ctxt, cnb : Longint;
+ enum : TEnum;
+ text : TText;
+ comment : pchar;
+ Next,Prev : PMsg;
+ FileNext,
+ Equivalent : PMsg;
+ end;
+Var
+ OrgFileName,DiffFileName : String;
+ OrgRoot,DiffRoot : PMsg;
+ OrgFirst,DiffFirst : PMsg;
+ Last : PMsg;
+
+const
+ NewFileName = 'new.msg';
+ Is_interactive : boolean = false;
+ Auto_verbosity : boolean = false;
+
+
+Procedure GetTranslation( p : PMsg);
+var
+ s : string;
+ i,j,k : longint;
+begin
+ i:=pos('_',p^.text);
+ if i>0 then
+ for j:=i+1 to Length(p^.text) do
+ if p^.text[j]='_' then
+ begin
+ i:=j;
+ break;
+ end;
+ if (i>0) and (i<=15) then
+ Writeln(P^.Enum,' type "',copy(p^.text,1,i-1),'" "',copy(p^.text,i+1,255),'"')
+ else
+ Writeln(P^.enum,' "',p^.text,'"');
+ Writeln('Type translated error message in,');
+ Writeln('Press return to keep it unchanged, or "q" to finish interactive mode');
+ Readln(s);
+ if s='' then
+ exit;
+ if s='q' then
+ begin
+ Is_interactive:=false;
+ exit;
+ end;
+ j:=pos('_',s);
+ if j>0 then
+ for k:=j+1 to Length(s) do
+ if s[j]='_' then
+ begin
+ j:=k;
+ break;
+ end;
+ if (j>0) then
+ begin
+ if copy(p^.text,1,i)<>copy(s,1,j) then
+ Writeln('Warning : different verbosity !!');
+ p^.text:=s;
+ end
+ else
+ p^.text:=copy(p^.text,1,i)+s;
+end;
+
+Function NewMsg (Var RM : PMsg; L : Longint; Const E : TEnum;Const T : TText;C : pchar;NbLn,TxtLn : longint) : PMsg;
+
+Var
+ P,R : PMsg;
+
+begin
+ New(P);
+ with P^ do
+ begin
+ Line:=L;
+ Text:=T;
+ enum:=E;
+ comment:=c;
+ cnb:=NbLn;
+ ctxt:=TxtLn;
+ next:=Nil;
+ prev:=Nil;
+ filenext:=nil;
+ equivalent:=nil;
+ if assigned(last) then
+ last^.FileNext:=P;
+ last:=P;
+ end;
+ R:=RM;
+ While (R<>Nil) and (UpCase(R^.enum)>UpCase(P^.Enum)) do
+ begin
+ P^.Prev:=R;
+ R:=R^.next;
+ end;
+ if assigned(R) and (UpCase(R^.Enum)=UpCase(P^.Enum)) then
+ Writeln('Error ',R^.Enum,' duplicate');
+ P^.Next:=R;
+ If R<>Nil then
+ R^.Prev:=P;
+ If P^.Prev<>Nil then
+ P^.Prev^.Next:=P
+ else
+ RM:=P;
+ NewMsg:=P;
+end;
+
+Procedure PrintList(const name : string;R : PMsg);
+var
+ P : PMsg;
+ f : text;
+begin
+ P:=R;
+ Assign(f,name);
+ Rewrite(f);
+ while assigned(P) do
+ begin
+ Writeln(f,UpCase(P^.Enum));
+ P:=P^.Next;
+ end;
+ Close(f);
+end;
+
+Procedure Usage;
+
+begin
+ Writeln('Usage : msgdif [options] <org-file> <dif-file>');
+ Writeln('Options:');
+ Writeln(' -i allow to enter translated messages interactively');
+ Writeln(' -y1 use <org-file> verbosity (do not query acknowledge)');
+ Writeln('');
+ Writeln('Generates "',NewFileName,'" that contain the messages from <dif-file>');
+ Writeln('with a new messages from <org-file>');
+ Writeln('');
+ Writeln('Example:');
+ Writeln(' msgdif errore.msg errorr.msg');
+ halt(1)
+end;
+
+Procedure ProcessOptions;
+var
+ i,count : longint;
+begin
+ Is_interactive:=false;
+ Auto_verbosity:=false;
+
+ count:=paramcount; i:=1;
+ while (count>0) and (Paramstr(i)[1]='-') do
+ case UpCase(Paramstr(i)[2]) of
+ 'I': begin
+ Is_interactive:=true;
+ dec(count); Inc(i);
+ end;
+ 'Y': case Paramstr(i)[3] of
+ '1': begin
+ Auto_verbosity:=true;
+ dec(count); Inc(i);
+ end;
+ else
+ Writeln ('Error: unknown option ', Paramstr(i));
+ Usage;
+ end;
+ else
+ Writeln ('Error: unknown option ', Paramstr(i));
+ Usage;
+ end;
+ If Count<>2 then begin
+ Writeln ('Error: there must be exactly two message files');
+ Usage;
+ end;
+
+ OrgfileName:=Paramstr(i);
+ DiffFileName:=Paramstr(i+1);
+ if (OrgFileName=NewFileName) or (DiffFileName=NewFileName) then
+ begin
+ Writeln('The file names must be different from ',NewFileName);
+ Halt(1);
+ end;
+end;
+
+Procedure ProcessFile (FileName : String; Var Root,First : PMsg);
+
+Const
+ ArrayLength = 65500;
+Var F : Text;
+ S,prevS : String;
+ J,LineNo,Count,NbLn,TxtLn : Longint;
+ chararray : array[0..ArrayLength] of char;
+ currentindex : longint;
+ c : pchar;
+ multiline : boolean;
+begin
+ Assign(F,FileName);
+ Reset(F);
+ Write ('Processing: ',Filename,'...');
+ LineNo:=0;
+ NbLn:=0;
+ TxtLn:=0;
+ Count:=0;
+ currentindex:=0;
+ Root:=Nil;
+ First:=nil;
+ Last:=nil;
+ PrevS:='';
+ multiline:=false;
+ While not eof(f) do
+ begin
+ Readln(F,S);
+ Inc(LineNo);
+ If multiline then
+ begin
+ PrevS:=PrevS+#10+S; Inc(TxtLn);
+ if (Length(S)<>0) and (S[1]=']') then
+ multiline:=false;
+ end
+ else
+ if (length(S)>0) and Not (S[1] in ['%','#']) Then
+ begin
+ J:=Pos('=',S);
+ If j<1 then
+ writeln (Filename,'(',LineNo,') : Invalid entry')
+ else
+ begin
+ chararray[currentindex]:=#0;
+ c:=strnew(@chararray);
+ if PrevS<>'' then
+ NewMsg(Root,LineNo,Copy(PrevS,1,Pos('=',PrevS)-1),
+ Copy(PrevS,Pos('=',PrevS)+1,Length(PrevS)),c,NbLn,TxtLn)
+ else
+ StrDispose(c);
+ currentindex:=0;
+ NbLn:=0; TxtLn:=0;
+ PrevS:=S; Inc(TxtLn);
+ if S[j+7]='[' then multiline:=true;
+ if First=nil then
+ First:=Root;
+ Inc(Count);
+ end;
+ end
+ else
+ begin
+ if currentindex+length(s)+1>ArrayLength then
+ Writeln('Comment too long : over ',ArrayLength,' chars')
+ else
+ begin
+ strpcopy(@chararray[currentindex],s+#10);
+ inc(currentindex,length(s)+1);
+ inc(NbLn);
+ end;
+ end;
+ end;
+ chararray[currentindex]:=#0;
+ c:=strnew(@chararray);
+ if PrevS<>'' then
+ NewMsg(Root,LineNo,Copy(PrevS,1,Pos('=',PrevS)-1),
+ Copy(PrevS,Pos('=',PrevS)+1,Length(PrevS)),c,NbLn,TxtLn);
+ Writeln (' Done. Read ',LineNo,' lines, got ',Count,' constants.');
+ Close(f);
+end;
+
+Procedure ShowDiff (POrg,PDiff : PMsg);
+
+Var
+ count,orgcount,diffcount : longint;
+
+Procedure NotFound (Org : Boolean; P : PMsg);
+
+begin
+ With P^ do
+ If Org Then
+ Writeln ('Not found in ',DiffFileName,' : ',Enum,' ',OrgFileName,'(',Line,')')
+ else
+ Writeln ('Extra in ',DiffFileName,'(',line,') : ',enum);
+ if org then
+ inc(orgcount)
+ else
+ inc(diffcount);
+end;
+
+begin
+ orgcount:=0;
+ diffcount:=0;
+ count:=0;
+ While (Porg<>Nil) and (PDiff<>Nil) do
+ begin
+// Writeln (POrg^.enum,'<=>',PDiff^.Enum);
+ If UpCase(Porg^.Enum)>UpCase(PDiff^.Enum) then
+ begin
+ NotFound (True,Porg);
+ POrg:=POrg^.Next
+ end
+ else If UpCase(POrg^.enum)=UpCase(PDiff^.Enum) then
+ begin
+ inc(count);
+ POrg^.Equivalent:=PDiff;
+ PDiff^.Equivalent:=POrg;
+ POrg:=POrg^.Next;
+ PDiff:=PDiff^.Next;
+ end
+ else
+ begin
+ NotFound (False,PDiff);
+ PDiff:=PDiff^.Next
+ end;
+ end;
+ While POrg<>Nil do
+ begin
+ NotFound(True,Porg);
+ POrg:=pOrg^.Next;
+ end;
+ While PDiff<>Nil do
+ begin
+ NotFound(False,PDiff);
+ PDiff:=PDiff^.Next;
+ end;
+ Writeln(count,' messages found in common to both files');
+ Writeln(orgcount,' messages only in ',OrgFileName);
+ Writeln(diffcount,' messages only in ',DiffFileName);
+end;
+
+type TArgSet = set of 0..31;
+
+function MsgToSet(const Msg, FileName: string; var R: TArgSet): Boolean;
+ var
+ i, j,l, num : integer;
+ code : word;
+ begin
+ R:=[];
+ MsgToSet:=false;
+ for i:=1 to Length(Msg) do
+ if Msg[i]='$' then
+ begin
+ j:=i+1; l:=length(msg)+1;
+ while (j<l) and (Msg[j] in ['0'..'9']) do Inc(j);
+ if j > (i+1) then
+ begin
+ val(copy(Msg,i+1,j-i-1),num,code);
+ if num > high(TArgSet) then begin
+ WriteLn('Error in ', FileName,': ', Msg);
+ WriteLn(' number at position ', i);
+ WriteLn(' must be LE ', high(TArgSet));
+ Exit;
+ end;
+ R:=R+[num];
+ end;
+ end;
+ MsgToSet:=true;
+ end;
+
+
+procedure CheckParm(const s1, s2: string);
+ var
+ R1, R2: TArgSet;
+ begin
+ if MsgToSet(s1,OrgFileName, R1) <> true then Exit;
+ if MsgToSet(s2,DiffFileName,R2) <> true then Exit;
+ if R1<>R2 then begin
+ WriteLn('Error: set of arguments is different');
+ WriteLn(' ',s1);
+ WriteLn(' ',s2);
+ end;
+ end;
+
+procedure WriteReorderedFile(FileName : string;orgnext,diffnext : PMsg);
+ var t,t2,t3 : text;
+ i,ntcount : longint;
+ j : integer;
+ s,s2,s3 : string;
+ is_msg : boolean;
+ nextdiffkept : pmsg;
+ begin
+ ntcount:=0;
+ Assign(t,FileName);
+ Rewrite(t);
+ Writeln(t,'%%% Reordering of ',DiffFileName,' respective to ',OrgFileName);
+ Writeln(t,'%%% Contains all comments from ',DiffFileName);
+ Assign(t2,DiffFileName);
+ Reset(t2);
+ Assign(t3,OrgFileName);
+ Reset(t3);
+ i:=2;
+ s:='';s3:='';
+ nextdiffkept:=diffnext;
+ while assigned(nextdiffkept) and (nextdiffkept^.equivalent=nil) do
+ nextdiffkept:=nextdiffkept^.filenext;
+ { First write the header of diff }
+ repeat
+ Readln(t2,s);
+ is_msg:=(pos('=',s)>1) and (s[1]<>'%') and (s[1]<>'#');
+ if not is_msg then
+ begin
+ Writeln(t,s);
+ inc(i);
+ end;
+ until is_msg;
+ { Write all messages in Org order }
+ while assigned(orgnext) do
+ begin
+ if not assigned(orgnext^.equivalent) then
+ begin
+ { Insert a new error msg with the english comments }
+ Writeln('New error ',orgnext^.enum,' added');
+ If Is_interactive then
+ GetTranslation(orgnext);
+ Writeln(t,orgnext^.enum,'=',orgnext^.text);
+ inc(i,orgnext^.ctxt);
+ Write(t,orgnext^.comment);
+ inc(i,orgnext^.cnb);
+ end
+ else
+ begin
+ inc(i);
+ if orgnext^.text=orgnext^.equivalent^.text then
+ begin
+ Writeln(FileName,'(',i,') ',orgnext^.enum,' not translated');
+ If Is_interactive then
+ GetTranslation(orgnext^.equivalent);
+ if orgnext^.text=orgnext^.equivalent^.text then
+ inc(ntcount);
+ end;
+ s2:=orgnext^.text;
+ j:=pos('_',copy(s2,7,20)) + 6;
+ s2:=upcase(copy(s2,1,j));
+ s3:=orgnext^.equivalent^.text;
+ j:=pos('_',copy(s3,7,20)) + 6;
+ s3:=upcase(copy(s3,1,j));
+ { that are the conditions in verbose unit }
+ if (length(s3)<12) and (s2<>s3) then
+ begin
+ Writeln('Warning: different options for ',orgnext^.enum);
+ Writeln(' ',orgnext^.text);
+ Writeln(' ',orgnext^.equivalent^.text);
+ s:='N';
+ if Auto_verbosity then
+ s:='Y'
+ else
+ If Is_interactive then
+ begin
+ Write('Use ',s2,' verbosity ? [y/n] ');
+ Readln(s);
+ end;
+ if UpCase(s[1])='Y' then
+ begin
+ orgnext^.equivalent^.text:=s2+copy(orgnext^.equivalent^.text,
+ length(s3)+1,Length(orgnext^.equivalent^.text));
+ WriteLn(' Using ', s2);
+ end;
+ end;
+
+ CheckParm(orgnext^.text, orgnext^.equivalent^.text);
+
+ Writeln(t,orgnext^.enum,'=',orgnext^.equivalent^.text);
+ Dec(i); Inc(i,orgnext^.equivalent^.ctxt);
+ if assigned(orgnext^.equivalent^.comment) and
+ (strlen(orgnext^.equivalent^.comment)>0) then
+ begin
+ Write(t,orgnext^.equivalent^.comment);
+ inc(i,orgnext^.equivalent^.cnb);
+ end
+ else if assigned(orgnext^.comment) and
+ (strlen(orgnext^.comment)>0) then
+ begin
+ Writeln('Comment from ',OrgFileName,' for enum ',orgnext^.enum,' added');
+ Write(t,orgnext^.comment);
+ inc(i,orgnext^.cnb);
+ end;
+ end;
+ orgnext:=orgnext^.filenext;
+ end;
+
+ while assigned(diffnext) do
+ begin
+ if not assigned(diffnext^.Equivalent) then
+ begin
+ { Skip removed enum in errore.msg}
+ { maybe a renaming of an enum !}
+ Writeln(diffnext^.enum,' commented out');
+ Writeln(t,'%%% ',diffnext^.enum,'=',diffnext^.text);
+ inc(i,diffnext^.ctxt);
+ Write(t,diffnext^.comment);
+ inc(i,diffnext^.cnb);
+ end;
+ diffnext:=diffnext^.filenext;
+ end;
+ Close(t);
+ Close(t2);
+ Close(t3);
+ Writeln(ntcount,' not translated items found');
+ end;
+
+begin
+ ProcessOptions;
+ ProcessFile(OrgFileName,orgroot,orgfirst);
+ ProcessFile(DiffFileName,diffRoot,difffirst);
+ PrintList('org.lst',OrgRoot);
+ PrintList('diff.lst',DiffRoot);
+ ShowDiff (OrgRoot,DiffRoot);
+ WriteReorderedFile(NewFileName,orgfirst,difffirst);
+end.
diff --git a/closures/compiler/utils/msgused.pl b/closures/compiler/utils/msgused.pl
new file mode 100644
index 0000000000..6ac46d655b
--- /dev/null
+++ b/closures/compiler/utils/msgused.pl
@@ -0,0 +1,42 @@
+#!/usr/bin/perl
+#
+# find not used messages
+
+unlink("./msgidx.inc");
+unlink("./msgtxt.inc");
+@compiler_src = (glob("./*.inc"),
+ glob("./*.pas"));
+
+open(MESSAGE_FILE, "< ./msg/errore.msg") or
+ die "Couldn't open <./msg/errore.msg> for reading: $!\n";
+
+open(FOUND, "> MSG-OK.TXT") or
+ die "Couldn't open <MSG-OK.TXT> for writing: $!\n";
+
+select FOUND; $| = 1;
+
+open(NOT_FOUND, "> MSG_BAD.TXT") or
+ die "Couldn't open <MSG_BAD.TXT> for writing: $!\n";
+
+select NOT_FOUND; $| = 1;
+
+while (<MESSAGE_FILE>)
+{
+ if (/^(\w\w\w*?_\w\w*?_\w\w*?)=/)
+ {
+ $msg = $1;
+ $found = `grep -il $msg @compiler_src`;
+ if ($found) {
+ print stderr "$msg\n";
+ print FOUND $msg . "\n";
+ }
+ else {
+ print stderr "NOT FOUND \t $msg\n";
+ print NOT_FOUND $msg . "\n";
+ }
+ }
+}
+
+close(IN);
+close(FOUND);
+close(NOT_FOUND);
diff --git a/closures/compiler/utils/ppudump.pp b/closures/compiler/utils/ppudump.pp
new file mode 100644
index 0000000000..a5a8c9e3c3
--- /dev/null
+++ b/closures/compiler/utils/ppudump.pp
@@ -0,0 +1,3034 @@
+{
+ Copyright (c) 1998-2002 by the FPC Development Team
+
+ Dumps the contents of a FPC unit file (PPU File)
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************}
+program ppudump;
+
+{$mode objfpc}
+{$H+}
+
+{$define IN_PPUDUMP}
+uses
+ { do NOT add symconst or globtype to make merging easier }
+ { do include symconst and globtype now before splitting 2.5 PM 2011-06-15 }
+ SysUtils,
+ constexp,
+ symconst,
+ ppu,
+ systems,
+ globals,
+ globtype,
+ widestr,
+ tokens;
+
+const
+ Version = 'Version 2.5.1';
+ Title = 'PPU-Analyser';
+ Copyright = 'Copyright (c) 1998-2010 by the Free Pascal Development Team';
+
+{ verbosity }
+ v_none = $0;
+ v_header = $1;
+ v_defs = $2;
+ v_syms = $4;
+ v_interface = $8;
+ v_implementation = $10;
+// v_browser = $20;
+ v_all = $ff;
+
+{ not needed anymore $i systems.inc }
+
+{ List of all supported cpus }
+const
+ CpuTxt : array[tsystemcpu] of string[9]=
+ (
+ { 0 } 'none',
+ { 1 } 'i386',
+ { 2 } 'm68k',
+ { 3 } 'alpha',
+ { 4 } 'powerpc',
+ { 5 } 'sparc',
+ { 6 } 'vis',
+ { 7 } 'ia64',
+ { 8 } 'x86_64',
+ { 9 } 'mips',
+ { 10 } 'arm',
+ { 11 } 'powerpc64',
+ { 12 } 'avr',
+ { 13 } 'mipsel'
+ );
+
+{ List of all supported system-cpu couples }
+const
+ Targets : array[tsystem] of string[18]=(
+ { 0 } 'none',
+ { 1 } 'GO32V1 (obsolete)',
+ { 2 } 'GO32V2',
+ { 3 } 'Linux-i386',
+ { 4 } 'OS/2',
+ { 5 } 'Win32',
+ { 6 } 'FreeBSD-i386',
+ { 7 } 'Amiga',
+ { 8 } 'Atari',
+ { 9 } 'MacOS-m68k',
+ { 10 } 'Linux-m68k',
+ { 11 } 'PalmOS-m68k',
+ { 12 } 'Linux-alpha',
+ { 13 } 'Linux-ppc',
+ { 14 } 'MacOS-ppc',
+ { 15 } 'Solaris-i386',
+ { 16 } 'BeOS-i386',
+ { 17 } 'NetBSD-i386',
+ { 18 } 'NetBSD-m68k',
+ { 19 } 'Netware-i386-clib',
+ { 20 } 'Qnx-i386',
+ { 21 } 'WDOSX-i386',
+ { 22 } 'Solaris-sparc',
+ { 23 } 'Linux-sparc',
+ { 24 } 'OpenBSD-i386',
+ { 25 } 'OpenBSD-m68k',
+ { 26 } 'Linux-x86-64',
+ { 27 } 'MacOSX-ppc',
+ { 28 } 'OS/2 via EMX',
+ { 29 } 'NetBSD-powerpc',
+ { 30 } 'OpenBSD-powerpc',
+ { 31 } 'Linux-arm',
+ { 32 } 'Watcom-i386',
+ { 33 } 'MorphOS-powerpc',
+ { 34 } 'FreeBSD-x86-64',
+ { 35 } 'Netware-i386-libc',
+ { 36 } 'Amiga-PowerPC',
+ { 37 } 'Win64-x64',
+ { 38 } 'WinCE-ARM',
+ { 39 } 'Win64-iA64',
+ { 40 } 'WinCE-i386',
+ { 41 } 'Linux-x64',
+ { 42 } 'GBA-arm',
+ { 43 } 'Linux-powerpc64',
+ { 44 } 'Darwin-i386',
+ { 45 } 'PalmOS-arm',
+ { 46 } 'MacOSX-powerpc64',
+ { 47 } 'NDS-arm',
+ { 48 } 'Embedded-i386',
+ { 49 } 'Embedded-m68k',
+ { 50 } 'Embedded-alpha',
+ { 51 } 'Embedded-powerpc',
+ { 52 } 'Embedded-sparc',
+ { 53 } 'Embedded-vm',
+ { 54 } 'Embedded-iA64',
+ { 55 } 'Embedded-x64',
+ { 56 } 'Embedded-mips',
+ { 57 } 'Embedded-arm',
+ { 58 } 'Embedded-powerpc64',
+ { 59 } 'Symbian-i386',
+ { 60 } 'Symbian-arm',
+ { 61 } 'MacOSX-x64',
+ { 62 } 'Embedded-avr',
+ { 63 } 'Haiku-i386',
+ { 64 } 'Darwin-ARM',
+ { 65 } 'Solaris-x86-64',
+ { 66 } 'Linux-MIPS',
+ { 67 } 'Linux-MIPSel',
+ { 68 } 'NativeNT-i386',
+ { 69 } 'iPhoneSim-i386',
+ { 70 } 'Wii-powerpc'
+ );
+
+const
+{ in widestr, we have the following definition
+ type
+ tcompilerwidechar = word;
+ thus widecharsize seems to always be 2 bytes }
+
+ widecharsize : longint = 2;
+ cpu : tsystemcpu = cpu_no;
+
+{ This type is defined in scanner.pas unit }
+type
+ tspecialgenerictoken = (
+ ST_LOADSETTINGS,
+ ST_LINE,
+ ST_COLUMN,
+ ST_FILEINDEX,
+ ST_LOADMESSAGES);
+
+
+var
+ ppufile : tppufile;
+ ppuversion : dword;
+ space : string;
+ verbose : longint;
+ derefdata : pbyte;
+ derefdatalen : longint;
+
+
+{****************************************************************************
+ Helper Routines
+****************************************************************************}
+
+{****************************************************************************
+ Routine to read 80-bit reals
+****************************************************************************
+}
+type
+ TSplit80bitReal = packed record
+ case byte of
+ 0: (bytes: Array[0..9] of byte);
+ 1: (words: Array[0..4] of word);
+ 2: (cards: Array[0..1] of cardinal; w: word);
+ end;
+const
+ maxDigits = 17;
+ function Real80bitToStr(var e : TSplit80bitReal) : string;
+ var
+ Temp : string;
+ new : TSplit80bitReal;
+ fraczero, expmaximal, sign, outside_double : boolean;
+ exp : smallint;
+ ext : extended;
+ d : double;
+ i : longint;
+ mantval : qword;
+ begin
+ if ppufile.change_endian then
+ begin
+ for i:=0 to 9 do
+ new.bytes[i]:=e.bytes[9-i];
+ e:=new;
+ end;
+ if sizeof(ext)=10 then
+ begin
+ ext:=pextended(@e)^;
+ str(ext,result);
+ exit;
+ end;
+ { extended, format (MSB): 1 Sign bit, 15 bit exponent, 64 bit mantissa }
+ sign := (e.w and $8000) <> 0;
+ expMaximal := (e.w and $7fff) = 32767;
+ exp:=(e.w and $7fff) - 16383 - 63;
+ fraczero := (e.cards[0] = 0) and
+ ((e.cards[1] and $7fffffff) = 0);
+ mantval := qword(e.cards[0]) or (qword(e.cards[1]) shl 32);
+ if expMaximal then
+ if fraczero then
+ if sign then
+ temp := '-Inf'
+ else temp := '+Inf'
+ else temp := 'Nan'
+ else
+ begin
+ d:=double(mantval);
+ if sign then
+ d:=-d;
+ outside_double:=false;
+ Try
+ if exp > 0 then
+ begin
+ for i:=1 to exp do
+ d:=d *2.0;
+ end
+ else if exp < 0 then
+ begin
+ for i:=1 to -exp do
+ d:=d /2.0;
+ end;
+ Except
+ outside_double:=true;
+ end;
+ if (mantval<>0) and (d=0.0) then
+ outside_double:=true;
+ if outside_double then
+ Temp:='Extended value outside double bound'
+ else
+ system.str(d,temp);
+
+ end;
+
+ result:=temp;
+ end;
+
+const has_errors : boolean = false;
+ has_more_infos : boolean = false;
+
+Procedure HasMoreInfos;
+begin
+ Writeln('!! Entry has more information stored');
+ has_more_infos:=true;
+end;
+
+Procedure WriteError(const S : string);
+Begin
+ Writeln(S);
+ has_errors:=true;
+End;
+
+function Unknown(const st : string; val :longint) : string;
+Begin
+ Unknown:='<!! Unknown'+st+' value '+tostr(val)+'>';
+ has_errors:=true;
+end;
+
+function ToStr(w:longint):String;
+begin
+ Str(w,ToStr);
+end;
+
+Function Target2Str(w:longint):string;
+begin
+ if w<=ord(high(tsystem)) then
+ Target2Str:=Targets[tsystem(w)]
+ else
+ Target2Str:=Unknown('target',w);
+end;
+
+
+Function Cpu2Str(w:longint):string;
+begin
+ if w<=ord(high(tsystemcpu)) then
+ begin
+ cpu:=tsystemcpu(w);
+ Cpu2Str:=CpuTxt[cpu];
+ end
+ else
+ Cpu2Str:=Unknown('cpu',w);
+end;
+
+
+Function Varspez2Str(w:longint):string;
+const
+ { in symconst unit
+ tvarspez = (vs_value,vs_const,vs_var,vs_out,vs_constref); }
+ varspezstr : array[tvarspez] of string[6]=('Value','Const','Var','Out','Hidden');
+begin
+ if w<=ord(high(varspezstr)) then
+ Varspez2Str:=varspezstr[tvarspez(w)]
+ else
+ Varspez2Str:=Unknown('varspez',w);
+end;
+
+Function VarRegable2Str(w:longint):string;
+ { tvarregable type is defined in symconst unit }
+const
+ varregableStr : array[tvarregable] of string[6]=('None','IntReg','FPUReg','MMReg','Addr');
+begin
+ if w<=ord(high(varregablestr)) then
+ Varregable2Str:=varregablestr[tvarregable(w)]
+ else
+ Varregable2Str:=Unknown('regable',w);
+end;
+
+
+Function Visibility2Str(w:longint):string;
+const
+ { tvisibility type is defined in symconst unit }
+
+ visibilityName : array[tvisibility] of string[16] = (
+ 'hidden','strict private','private','strict protected','protected',
+ 'public','published'
+ );
+begin
+ if w<=ord(high(visibilityName)) then
+ result:=visibilityName[tvisibility(w)]
+ else
+ result:=Unknown('visibility',w);
+end;
+
+
+function PPUFlags2Str(flags:longint):string;
+type
+ tflagopt=record
+ mask : longint;
+ str : string[30];
+ end;
+const
+ flagopts=24;
+ flagopt : array[1..flagopts] of tflagopt=(
+ (mask: $1 ;str:'init'),
+ (mask: $2 ;str:'final'),
+ (mask: $4 ;str:'big_endian'),
+ (mask: $8 ;str:'dbx'),
+// (mask: $10 ;str:'browser'),
+ (mask: $20 ;str:'in_library'),
+ (mask: $40 ;str:'smart_linked'),
+ (mask: $80 ;str:'static_linked'),
+ (mask: $100 ;str:'shared_linked'),
+// (mask: $200 ;str:'local_browser'),
+ (mask: $400 ;str:'no_link'),
+ (mask: $800 ;str:'has_resources'),
+ (mask: $1000 ;str:'little_endian'),
+ (mask: $2000 ;str:'release'),
+ (mask: $4000 ;str:'local_threadvars'),
+ (mask: $8000 ;str:'fpu_emulation_on'),
+ (mask: $210000 ;str:'has_debug_info'),
+ (mask: $10000 ;str:'stabs_debug_info'),
+ (mask: $200000 ;str:'dwarf_debug_info'),
+ (mask: $20000 ;str:'local_symtable'),
+ (mask: $40000 ;str:'uses_variants'),
+ (mask: $80000 ;str:'has_resourcefiles'),
+ (mask: $100000 ;str:'has_exports'),
+ (mask: $400000 ;str:'has_wideinits'),
+ (mask: $800000 ;str:'has_classinits'),
+ (mask: $1000000 ;str:'has_resstrinits')
+ );
+var
+ i,ntflags : longint;
+ first : boolean;
+ s : string;
+begin
+ s:='';
+ if flags<>0 then
+ begin
+ ntflags:=flags;
+ first:=true;
+ for i:=1to flagopts do
+ if (flags and flagopt[i].mask)<>0 then
+ begin
+ if first then
+ first:=false
+ else
+ s:=s+', ';
+ s:=s+flagopt[i].str;
+ ntflags:=ntflags and (not flagopt[i].mask);
+ end;
+ end
+ else
+ s:='none';
+ if ntflags<>0 then
+ begin
+ s:=s+' unknown '+hexstr(ntflags,8);
+ has_errors:=true;
+ end;
+ PPUFlags2Str:=s;
+end;
+
+
+ Function L0(l:longint):string;
+ {
+ return the string of value l, if l<10 then insert a zero, so
+ the string is always at least 2 chars '01','02',etc
+ }
+ var
+ s : string;
+ begin
+ Str(l,s);
+ if l<10 then
+ s:='0'+s;
+ L0:=s;
+ end;
+
+
+ function filetimestring( t : longint) : string;
+ {
+ convert dos datetime t to a string YY/MM/DD HH:MM:SS
+ }
+ var
+ DT : TDateTime;
+ hsec : word;
+ Year,Month,Day: Word;
+ hour,min,sec : word;
+ begin
+ if t=-1 then
+ begin
+ Result := 'Not Found';
+ has_errors:=true;
+ exit;
+ end;
+ DT := FileDateToDateTime(t);
+ DecodeTime(DT,hour,min,sec,hsec);
+ DecodeDate(DT,year,month,day);
+ Result := L0(Year)+'/'+L0(Month)+'/'+L0(Day)+' '+L0(Hour)+':'+L0(min)+':'+L0(sec);
+ end;
+
+
+{****************************************************************************
+ Read Routines
+****************************************************************************}
+
+procedure readrecsymtableoptions;
+var
+ usefieldalignment : shortint;
+begin
+ if ppufile.readentry<>ibrecsymtableoptions then
+ begin
+ has_errors:=true;
+ exit;
+ end;
+ writeln(space,' recordalignment: ',shortint(ppufile.getbyte));
+ usefieldalignment:=shortint(ppufile.getbyte);
+ writeln(space,' usefieldalignment: ',usefieldalignment);
+ if (usefieldalignment=C_alignment) then
+ writeln(space,' fieldalignment: ',shortint(ppufile.getbyte));
+end;
+
+procedure readsymtableoptions(const s: string);
+type
+ tsymtblopt=record
+ mask : tsymtableoption;
+ str : string[30];
+ end;
+const
+ symtblopts=ord(high(tsymtableoption)) + 1;
+ symtblopt : array[1..symtblopts] of tsymtblopt=(
+ (mask:sto_has_helper; str:'Has helper')
+ );
+var
+ options : tsymtableoptions;
+ first : boolean;
+ i : integer;
+begin
+ if ppufile.readentry<>ibsymtableoptions then
+ begin
+ has_errors:=true;
+ exit;
+ end;
+ ppufile.getsmallset(options);
+ if space<>'' then
+ writeln(space,'------ ',s,' ------');
+ write(space,'Symtable options: ');
+ if options<>[] then
+ begin
+ first:=true;
+ for i:=1 to symtblopts do
+ if (symtblopt[i].mask in options) then
+ begin
+ if first then
+ first:=false
+ else
+ write(', ');
+ write(symtblopt[i].str);
+ end;
+ end
+ else
+ write('none');
+ writeln;
+end;
+
+procedure readdefinitions(const s:string); forward;
+procedure readsymbols(const s:string); forward;
+
+procedure readsymtable(const s: string);
+begin
+ readsymtableoptions(s);
+ readdefinitions(s);
+ readsymbols(s);
+end;
+
+Procedure ReadLinkContainer(const prefix:string);
+{
+ Read a serie of strings and write to the screen starting every line
+ with prefix
+}
+ function maskstr(m:longint):string;
+ { link options are in globtype unit
+ const
+ link_none = $0;
+ link_always = $1;
+ link_static = $2;
+ link_smart = $4;
+ link_shared = $8; }
+ var
+ s : string;
+ begin
+ s:='';
+ if (m and link_always)<>0 then
+ s:=s+'always ';
+ if (m and link_static)<>0 then
+ s:=s+'static ';
+ if (m and link_smart)<>0 then
+ s:=s+'smart ';
+ if (m and link_shared)<>0 then
+ s:=s+'shared ';
+ maskstr:=s;
+ end;
+
+var
+ s : string;
+ m : longint;
+begin
+ while not ppufile.endofentry do
+ begin
+ s:=ppufile.getstring;
+ m:=ppufile.getlongint;
+ WriteLn(prefix,s,' (',maskstr(m),')');
+ end;
+end;
+
+
+Procedure ReadContainer(const prefix:string);
+{
+ Read a serie of strings and write to the screen starting every line
+ with prefix
+}
+begin
+ while not ppufile.endofentry do
+ WriteLn(prefix,ppufile.getstring);
+end;
+
+
+procedure ReadLoadUnit;
+var
+ ucrc,uintfcrc, indcrc : cardinal;
+begin
+ while not ppufile.EndOfEntry do
+ begin
+ write('Uses unit: ',ppufile.getstring);
+ ucrc:=cardinal(ppufile.getlongint);
+ uintfcrc:=cardinal(ppufile.getlongint);
+ indcrc:=cardinal(ppufile.getlongint);
+ writeln(' (Crc: ',hexstr(ucrc,8),', IntfcCrc: ',hexstr(uintfcrc,8),', IndCrc: ',hexstr(indcrc,8),')');
+ end;
+end;
+
+
+Procedure ReadDerefmap;
+var
+ i,mapsize : longint;
+begin
+ mapsize:=ppufile.getlongint;
+ writeln('DerefMapsize: ',mapsize);
+ for i:=0 to mapsize-1 do
+ writeln('DerefMap[',i,'] = ',ppufile.getstring);
+end;
+
+
+Procedure ReadImportSymbols;
+var
+ extlibname : string;
+ j,
+ extsymcnt : longint;
+ extsymname : string;
+ extsymmangledname : string;
+ extsymordnr : longint;
+ extsymisvar : boolean;
+begin
+ while not ppufile.endofentry do
+ begin
+ extlibname:=ppufile.getstring;
+ extsymcnt:=ppufile.getlongint;
+ writeln('External Library: ',extlibname,' (',extsymcnt,' imports)');
+ for j:=0 to extsymcnt-1 do
+ begin
+ extsymname:=ppufile.getstring;
+ if ppuversion>130 then
+ extsymmangledname:=ppufile.getstring
+ else
+ extsymmangledname:=extsymname;
+ extsymordnr:=ppufile.getlongint;
+ extsymisvar:=ppufile.getbyte<>0;
+ writeln(' ',extsymname,' as ',extsymmangledname,
+ '(OrdNr: ',extsymordnr,' IsVar: ',extsymisvar,')');
+ end;
+ end;
+end;
+
+
+Procedure ReadDerefdata;
+begin
+ derefdatalen:=ppufile.entrysize;
+ if derefdatalen=0 then
+ begin
+ WriteError('!! Error: derefdatalen=0');
+ exit;
+ end;
+ Writeln('Derefdata length: ',derefdatalen);
+ derefdata:=allocmem(derefdatalen);
+ ppufile.getdata(derefdata^,derefdatalen);
+end;
+
+Procedure FreeDerefdata;
+begin
+ if assigned(derefdata) then
+ begin
+ FreeMem(derefdata);
+ derefdata:=nil;
+ derefdatalen:=0;
+ end;
+end;
+
+
+Procedure ReadWpoFileInfo;
+begin
+ Writeln('Compiled with input whole-program optimisation from ',ppufile.getstring,' ',filetimestring(ppufile.getlongint));
+end;
+
+
+Procedure ReadAsmSymbols;
+type
+ { Copied from aasmbase.pas }
+ TAsmsymbind=(
+ AB_NONE,AB_EXTERNAL,AB_COMMON,AB_LOCAL,AB_GLOBAL,AB_WEAK_EXTERNAL,
+ { global in the current program/library, but not visible outside it }
+ AB_PRIVATE_EXTERN,AB_LAZY,AB_IMPORT);
+
+ TAsmsymtype=(
+ AT_NONE,AT_FUNCTION,AT_DATA,AT_SECTION,AT_LABEL,
+ {
+ the address of this code label is taken somewhere in the code
+ so it must be taken care of it when creating pic
+ }
+ AT_ADDR
+ );
+
+var
+ s,
+ bindstr,
+ typestr : string;
+ i : longint;
+begin
+ writeln(space,'Number of AsmSymbols: ',ppufile.getlongint);
+ i:=0;
+ while (not ppufile.endofentry) and (not ppufile.error) do
+ begin
+ s:=ppufile.getstring;
+ case tasmsymbind(ppufile.getbyte) of
+ AB_EXTERNAL :
+ bindstr:='External';
+ AB_COMMON :
+ bindstr:='Common';
+ AB_LOCAL :
+ bindstr:='Local';
+ AB_GLOBAL :
+ bindstr:='Global';
+ AB_WEAK_EXTERNAL :
+ bindstr:='Weak external';
+ AB_PRIVATE_EXTERN :
+ bindstr:='Private extern';
+ AB_LAZY :
+ bindstr:='Lazy';
+ AB_IMPORT :
+ bindstr:='Import';
+ else
+ begin
+ bindstr:='<Error !!>';
+ has_errors:=true;
+ end;
+ end;
+ case tasmsymtype(ppufile.getbyte) of
+ AT_FUNCTION :
+ typestr:='Function';
+ AT_DATA :
+ typestr:='Data';
+ AT_SECTION :
+ typestr:='Section';
+ AT_LABEL :
+ typestr:='Label';
+ AT_ADDR :
+ typestr:='Label (with address taken)';
+ else
+ begin
+ typestr:='<Error !!>';
+ has_errors:=true;
+ end;
+ end;
+ Writeln(space,' ',i,' : ',s,' [',bindstr,',',typestr,']');
+ inc(i);
+ end;
+end;
+
+function getexprint:Tconstexprint;
+
+begin
+ getexprint.overflow:=false;
+ getexprint.signed:=boolean(ppufile.getbyte);
+ getexprint.svalue:=ppufile.getint64;
+end;
+
+Procedure ReadPosInfo;
+var
+ info : byte;
+ fileindex,line,column : longint;
+begin
+ with ppufile do
+ begin
+ {
+ info byte layout in bits:
+ 0-1 - amount of bytes for fileindex
+ 2-3 - amount of bytes for line
+ 4-5 - amount of bytes for column
+ }
+ info:=getbyte;
+ case (info and $03) of
+ 0 : fileindex:=getbyte;
+ 1 : fileindex:=getword;
+ 2 : fileindex:=(getbyte shl 16) or getword;
+ 3 : fileindex:=getlongint;
+ end;
+ case ((info shr 2) and $03) of
+ 0 : line:=getbyte;
+ 1 : line:=getword;
+ 2 : line:=(getbyte shl 16) or getword;
+ 3 : line:=getlongint;
+ end;
+ case ((info shr 4) and $03) of
+ 0 : column:=getbyte;
+ 1 : column:=getword;
+ 2 : column:=(getbyte shl 16) or getword;
+ 3 : column:=getlongint;
+ end;
+ Writeln(fileindex,' (',line,',',column,')');
+ end;
+end;
+
+
+procedure readderef(const derefspace: string);
+var
+ b : tdereftype;
+ first : boolean;
+ idx : longint;
+ i,n : byte;
+ pdata : pbyte;
+begin
+ if not assigned(derefdata) then
+ exit;
+ first:=true;
+ idx:=ppufile.getlongint;
+ if (idx>derefdatalen) then
+ begin
+ writeln('!! Error: Deref idx ',idx,' > ',derefdatalen);
+ has_errors:=true;
+ exit;
+ end;
+ write(derefspace,'(',idx,') ');
+ pdata:=@derefdata[idx];
+ i:=0;
+ n:=pdata[i];
+ inc(i);
+ if n<1 then
+ begin
+ WriteError('!! Error: Deref len < 1');
+ exit;
+ end;
+ while (i<=n) do
+ begin
+ if not first then
+ write(', ')
+ else
+ first:=false;
+ b:=tdereftype(pdata[i]);
+ inc(i);
+ case b of
+ deref_nil :
+ write('Nil');
+ deref_symid :
+ begin
+ idx:=pdata[i] shl 24 or pdata[i+1] shl 16 or pdata[i+2] shl 8 or pdata[i+3];
+ inc(i,4);
+ write('SymId ',idx);
+ end;
+ deref_defid :
+ begin
+ idx:=pdata[i] shl 24 or pdata[i+1] shl 16 or pdata[i+2] shl 8 or pdata[i+3];
+ inc(i,4);
+ write('DefId ',idx);
+ end;
+ deref_unit :
+ begin
+ idx:=pdata[i] shl 8 or pdata[i+1];
+ inc(i,2);
+ write('Unit ',idx);
+ end;
+ else
+ begin
+ writeln('!! unsupported dereftyp: ',ord(b));
+ has_errors:=true;
+ break;
+ end;
+ end;
+ end;
+ writeln;
+end;
+
+
+procedure readpropaccesslist(const s:string);
+{ type tsltype is in symconst unit }
+const
+ slstr : array[tsltype] of string[12] = (
+ '',
+ 'load',
+ 'call',
+ 'subscript',
+ 'vec',
+ 'typeconv',
+ 'absolutetype'
+ );
+var
+ sl : tsltype;
+begin
+ readderef('');
+ repeat
+ sl:=tsltype(ppufile.getbyte);
+ if sl=sl_none then
+ break;
+ write(s,'(',slstr[sl],') ');
+ case sl of
+ sl_call,
+ sl_load,
+ sl_subscript :
+ readderef('');
+ sl_absolutetype,
+ sl_typeconv :
+ readderef('');
+ sl_vec :
+ begin
+ writeln(ppufile.getlongint);
+ readderef('');
+ end;
+ end;
+ until false;
+end;
+
+(*
+ talignmentinfo = packed record
+ procalign,
+ loopalign,
+ jumpalign,
+ constalignmin,
+ constalignmax,
+ varalignmin,
+ varalignmax,
+ localalignmin,
+ localalignmax,
+ recordalignmin,
+ recordalignmax,
+ maxCrecordalign : longint;
+ end;
+
+
+ tsettings = packed record
+ alignment : talignmentinfo;
+ globalswitches : tglobalswitches;
+ moduleswitches : tmoduleswitches;
+ localswitches : tlocalswitches;
+ modeswitches : tmodeswitches;
+ optimizerswitches : toptimizerswitches;
+ { generate information necessary to perform these wpo's during a subsequent compilation }
+ genwpoptimizerswitches: twpoptimizerswitches;
+ { perform these wpo's using information generated during a previous compilation }
+ dowpoptimizerswitches: twpoptimizerswitches;
+ debugswitches : tdebugswitches;
+ { 0: old behaviour for sets <=256 elements
+ >0: round to this size }
+ setalloc,
+ packenum : shortint;
+
+ packrecords : shortint;
+ maxfpuregisters : shortint;
+
+ cputype,
+ optimizecputype : tcputype;
+ fputype : tfputype;
+ asmmode : tasmmode;
+ interfacetype : tinterfacetypes;
+ defproccall : tproccalloption;
+ sourcecodepage : tcodepagestring;
+
+ minfpconstprec : tfloattype;
+
+ disabledircache : boolean;
+
+ { CPU targets with microcontroller support can add a controller specific unit }
+{$if defined(ARM) or defined(AVR)}
+ controllertype : tcontrollertype;
+{$endif defined(ARM) or defined(AVR)}
+ { WARNING: this pointer cannot be written as such in record token }
+ pmessage : pmessagestaterecord;
+ end;
+
+*)
+procedure readprocinfooptions(space : string);
+(*
+ tprocinfoflag=(
+ { procedure has at least one assembler block }
+ pi_has_assembler_block,
+ { procedure does a call }
+ pi_do_call,
+ { procedure has a try statement = no register optimization }
+ pi_uses_exceptions,
+ { procedure is declared as @var(assembler), don't optimize}
+ pi_is_assembler,
+ { procedure contains data which needs to be finalized }
+ pi_needs_implicit_finally,
+ { procedure has the implicit try..finally generated }
+ pi_has_implicit_finally,
+ { procedure uses fpu}
+ pi_uses_fpu,
+ { procedure uses GOT for PIC code }
+ pi_needs_got,
+ { references var/proc/type/const in static symtable,
+ i.e. not allowed for inlining from other units }
+ pi_uses_static_symtable,
+ { set if the procedure has to push parameters onto the stack }
+ pi_has_stackparameter,
+ { set if the procedure has at least one label }
+ pi_has_label,
+ { calls itself recursive }
+ pi_is_recursive,
+ { stack frame optimization not possible (only on x86 probably) }
+ pi_needs_stackframe,
+ { set if the procedure has at least one register saved on the stack }
+ pi_has_saved_regs,
+ { dfa was generated for this proc }
+ pi_dfaavailable,
+ { subroutine contains interprocedural used labels }
+ pi_has_interproclabel
+ ); *)
+
+type
+ tprocinfoopt=record
+ mask : tprocinfoflag;
+ str : string[80];
+ end;
+const
+ procinfoopts=ord(high(tprocinfoflag)) - ord(low(tprocinfoflag));
+ procinfoopt : array[0..procinfoopts] of tprocinfoopt=(
+ (mask:pi_has_assembler_block;
+ str:' has at least one assembler block'),
+ (mask:pi_do_call;
+ str:' does a call'),
+ (mask:pi_uses_exceptions;
+ str:' has a try statement = no register optimization '),
+ (mask:pi_is_assembler;
+ str:' is declared as @var(assembler), don''t optimize'),
+ (mask:pi_needs_implicit_finally;
+ str:' contains data which needs to be finalized '),
+ (mask:pi_has_implicit_finally;
+ str:' has the implicit try..finally generated '),
+ (mask:pi_uses_fpu;
+ str:' uses fpu'),
+ (mask:pi_needs_got;
+ str:' uses GOT for PIC code '),
+ (mask:pi_uses_static_symtable;
+ str:' references var/proc/type/const in static symtable'),
+ (mask:pi_has_stackparameter;
+ str:' set if the procedure has to push parameters onto the stack '),
+ (mask:pi_has_label;
+ str:' set if the procedure has at least one label '),
+ (mask:pi_is_recursive;
+ str:' calls itself recursive '),
+ (mask:pi_needs_stackframe;
+ str:' stack frame optimization not possible (only on x86 probably) '),
+ (mask:pi_has_saved_regs;
+ str:' set if the procedure has at least one register saved on the stack '),
+ (mask:pi_dfaavailable;
+ str:' dfa was generated for this proc '),
+ (mask:pi_has_interproclabel;
+ str:' subroutine contains interprocedural used labels '),
+ (mask:pi_has_unwind_info;
+ str:' unwinding info was generated for this proc ')
+ );
+var
+ procinfooptions : tprocinfoflags;
+ i : longint;
+ first : boolean;
+begin
+ ppufile.getsmallset(procinfooptions);
+ if procinfooptions<>[] then
+ begin
+ first:=true;
+ for i:=0 to procinfoopts do
+ if (procinfoopt[i].mask in procinfooptions) then
+ begin
+ if first then
+ first:=false
+ else
+ write(', ');
+ write(procinfoopt[i].str);
+ end;
+ end;
+ writeln;
+end;
+
+procedure readsymoptions(space : string);
+type
+ tsymopt=record
+ mask : tsymoption;
+ str : string[30];
+ end;
+const
+ symopts=ord(high(tsymoption)) - ord(low(tsymoption));
+ { sp_none = 0 corresponds to nothing }
+ symopt : array[1..symopts] of tsymopt=(
+ (mask:sp_static; str:'Static'),
+ (mask:sp_hint_deprecated; str:'Hint Deprecated'),
+ (mask:sp_hint_platform; str:'Hint Platform'),
+ (mask:sp_hint_library; str:'Hint Library'),
+ (mask:sp_hint_unimplemented; str:'Hint Unimplemented'),
+ (mask:sp_hint_experimental; str:'Hint Experimental'),
+ (mask:sp_has_overloaded; str:'Has overloaded'),
+ (mask:sp_internal; str:'Internal'),
+ (mask:sp_implicitrename; str:'Implicit Rename'),
+ (mask:sp_generic_para; str:'Generic Parameter'),
+ (mask:sp_has_deprecated_msg; str:'Has Deprecated Message'),
+ (mask:sp_generic_dummy; str:'Generic Dummy')
+ );
+var
+ symoptions : tsymoptions;
+ i : longint;
+ first : boolean;
+begin
+ ppufile.getsmallset(symoptions);
+ if symoptions<>[] then
+ begin
+ first:=true;
+ for i:=1to symopts do
+ if (symopt[i].mask in symoptions) then
+ begin
+ if first then
+ first:=false
+ else
+ write(', ');
+ write(symopt[i].str);
+ end;
+ end;
+ writeln;
+ if sp_has_deprecated_msg in symoptions then
+ writeln(space,'Deprecated : ', ppufile.getstring);
+end;
+
+
+procedure readcommonsym(const s:string);
+begin
+ writeln(space,'** Symbol Id ',ppufile.getlongint,' **');
+ writeln(space,s,ppufile.getstring);
+ write (space,' File Pos : ');
+ readposinfo;
+ writeln(space,' Visibility : ',Visibility2Str(ppufile.getbyte));
+ write (space,' SymOptions : ');
+ readsymoptions(space+' ');
+end;
+
+
+
+var
+ { needed during tobjectdef parsing... }
+ current_defoptions : tdefoptions;
+ current_objectoptions : tobjectoptions;
+
+procedure readcommondef(const s:string; out defoptions: tdefoptions);
+type
+ tdefopt=record
+ mask : tdefoption;
+ str : string[30];
+ end;
+ tdefstateinfo=record
+ mask : tdefstate;
+ str : string[30];
+ end;
+ ptoken=^ttoken;
+ pmsgstate =^tmsgstate;
+const
+ defopt : array[1..ord(high(tdefoption))] of tdefopt=(
+ (mask:df_unique; str:'Unique Type'),
+ (mask:df_generic; str:'Generic'),
+ (mask:df_specialization; str:'Specialization'),
+ (mask:df_copied_def; str:'Copied Typedef')
+ );
+ defstate : array[1..ord(high(tdefstate))] of tdefstateinfo=(
+ (mask:ds_vmt_written; str:'VMT Written'),
+ (mask:ds_rtti_table_used; str:'RTTITable Used'),
+ (mask:ds_init_table_used; str:'InitTable Used'),
+ (mask:ds_rtti_table_written; str:'RTTITable Written'),
+ (mask:ds_init_table_written; str:'InitTable Written'),
+ (mask:ds_dwarf_dbg_info_used; str:'Dwarf DbgInfo Used'),
+ (mask:ds_dwarf_dbg_info_written;str:'Dwarf DbgInfo Written')
+ );
+var
+ defstates : tdefstates;
+ i, nb, msgvalue, mesgnb : longint;
+ first : boolean;
+ copy_size, min_size, tokenbufsize : longint;
+ tokenbuf : pbyte;
+ idtoken,
+ token : ttoken;
+ state : tmsgstate;
+ new_settings : Tsettings;
+ len : sizeint;
+ wstring : widestring;
+ astring : ansistring;
+
+ function readtoken: ttoken;
+ var
+ b,b2 : byte;
+ begin
+ b:=tokenbuf[i];
+ inc(i);
+ if (b and $80)<>0 then
+ begin
+ b2:=tokenbuf[i];
+ inc(i);
+ result:=ttoken(((b and $7f) shl 8) or b2);
+ end
+ else
+ result:=ttoken(b);
+ end;
+
+ function gettokenbufdword : dword;
+ var
+ var32 : dword;
+ begin
+ var32:=pdword(@tokenbuf[i])^;
+ inc(i,sizeof(dword));
+ if ppufile.change_endian then
+ var32:=swapendian(var32);
+ result:=var32;
+ end;
+
+ function gettokenbufword : word;
+ var
+ var16 : word;
+ begin
+ var16:=pword(@tokenbuf[i])^;
+ inc(i,sizeof(word));
+ if ppufile.change_endian then
+ var16:=swapendian(var16);
+ result:=var16;
+ end;
+
+
+ function gettokenbufsizeint : int64;
+ var
+ var64 : int64;
+ var32 : longint;
+ var16 : smallint;
+
+ begin
+ if CpuAddrBitSize[cpu]=64 then
+ begin
+ var64:=pint64(@tokenbuf[i])^;
+ inc(i,sizeof(int64));
+ if ppufile.change_endian then
+ var64:=swapendian(var64);
+ result:=var64;
+ end
+ else if CpuAddrBitSize[cpu]=32 then
+ begin
+ var32:=plongint(@tokenbuf[i])^;
+ inc(i,sizeof(longint));
+ if ppufile.change_endian then
+ var32:=swapendian(var32);
+ result:=var32;
+ end
+ else if CpuAddrBitSize[cpu]=16 then
+ begin
+ var16:=psmallint(@tokenbuf[i])^;
+ inc(i,sizeof(smallint));
+ if ppufile.change_endian then
+ var16:=swapendian(var16);
+ result:=var16;
+ end
+ else
+ begin
+ WriteError('Wrong CpuAddrBitSize');
+ result:=0;
+ end;
+ end;
+
+begin
+ writeln(space,'** Definition Id ',ppufile.getlongint,' **');
+ writeln(space,s);
+ write (space,' Type symbol : ');
+ readderef('');
+ write (space,' DefOptions : ');
+ ppufile.getsmallset(defoptions);
+ if defoptions<>[] then
+ begin
+ first:=true;
+ for i:=1to high(defopt) do
+ if (defopt[i].mask in defoptions) then
+ begin
+ if first then
+ first:=false
+ else
+ write(', ');
+ write(defopt[i].str);
+ end;
+ end;
+ writeln;
+
+ write (space,' DefStates : ');
+ ppufile.getsmallset(defstates);
+ if defstates<>[] then
+ begin
+ first:=true;
+ for i:=1 to high(defstate) do
+ if (defstate[i].mask in defstates) then
+ begin
+ if first then
+ first:=false
+ else
+ write(', ');
+ write(defstate[i].str);
+ end;
+ end;
+ writeln;
+
+ if df_generic in defoptions then
+ begin
+ tokenbufsize:=ppufile.getlongint;
+ writeln(space,' Tokenbuffer size : ',tokenbufsize);
+ tokenbuf:=allocmem(tokenbufsize);
+ ppufile.getdata(tokenbuf^,tokenbufsize);
+ i:=0;
+ write(space,' Tokens: ');
+ while i<tokenbufsize do
+ begin
+ token:=readtoken;
+ if token<>_GENERICSPECIALTOKEN then
+ begin
+ if token <= high(ttoken) then
+ write(arraytokeninfo[token].str)
+ else
+ begin
+ HasMoreInfos;
+ write('Error in Token List');
+ break;
+ end;
+ idtoken:=readtoken;
+ end;
+ case token of
+ _CWCHAR,
+ _CWSTRING :
+ begin
+ len:=gettokenbufsizeint;
+ setlength(wstring,len);
+ move(tokenbuf[i],wstring[1],len*2);
+ write(' ',wstring);
+ inc(i,len*2);
+ end;
+ _CSTRING:
+ begin
+ len:=gettokenbufsizeint;
+ setlength(astring,len);
+ move(tokenbuf[i],astring[1],len);
+ write(' ',astring);
+ inc(i,len);
+ end;
+ _CCHAR,
+ _INTCONST,
+ _REALNUMBER :
+ begin
+ write(' ',pshortstring(@tokenbuf[i])^);
+ inc(i,tokenbuf[i]+1);
+ end;
+ _ID :
+ begin
+ write(' ',pshortstring(@tokenbuf[i])^);
+ inc(i,tokenbuf[i]+1);
+ end;
+ _GENERICSPECIALTOKEN:
+ begin
+ { Short version of column change,
+ byte or $80 used }
+ if (tokenbuf[i] and $80)<>0 then
+ begin
+ write('Col: ',tokenbuf[i] and $7f);
+ inc(i);
+ end
+ else
+ case tspecialgenerictoken(tokenbuf[i]) of
+ ST_LOADSETTINGS:
+ begin
+ inc(i);
+ write('Settings');
+ { This does not load pmessage pointer }
+ new_settings.pmessage:=nil;
+ { TSettings size depends in target...
+ We first read the size of the copied part }
+ { Still not cross endian ready :( }
+ copy_size:=gettokenbufsizeint;
+ if copy_size < sizeof(tsettings)-sizeof(pointer) then
+ min_size:=copy_size
+ else
+ min_size:= sizeof(tsettings)-sizeof(pointer);
+ move(tokenbuf[i],new_settings, min_size);
+ inc(i,copy_size);
+ end;
+ ST_LOADMESSAGES:
+ begin
+ inc(i);
+ write('Messages:');
+ mesgnb:=tokenbuf[i];
+ inc(i);
+ for nb:=1 to mesgnb do
+ begin
+ msgvalue:=gettokenbufsizeint;
+ inc(i,sizeof(sizeint));
+ state:=tmsgstate(gettokenbufsizeint);
+ end;
+ end;
+ ST_LINE:
+ begin
+ inc(i);
+ write('Line: ',gettokenbufdword);
+ end;
+ ST_COLUMN:
+ begin
+ inc(i);
+ write('Col: ',gettokenbufword);
+ end;
+ ST_FILEINDEX:
+ begin
+ inc(i);
+ write('File: ',gettokenbufword);
+ end;
+ end;
+ end;
+ end;
+
+ if i<tokenbufsize then
+ write(',');
+ end;
+ writeln;
+ freemem(tokenbuf);
+ end;
+ if df_specialization in defoptions then
+ begin
+ write (space,' Orig. GenericDef : ');
+ readderef('');
+ end;
+ current_defoptions:=defoptions;
+end;
+
+
+{ Read abstract procdef and return if inline procdef }
+{ type tproccalloption is in globtype unit }
+{ type tproctypeoption is in globtype unit }
+{ type tprocoption is in globtype unit }
+
+procedure read_abstract_proc_def(var proccalloption:tproccalloption;var procoptions:tprocoptions);
+type
+ tproccallopt=record
+ mask : tproccalloption;
+ str : string[30];
+ end;
+ tproctypeopt=record
+ mask : tproctypeoption;
+ str : string[30];
+ end;
+ tprocopt=record
+ mask : tprocoption;
+ str : string[30];
+ end;
+const
+ {proccalloptionStr is also in globtype unit }
+ proctypeopt : array[1..ord(high(tproctypeoption))] of tproctypeopt=(
+ (mask:potype_proginit; str:'ProgInit'),
+ (mask:potype_unitinit; str:'UnitInit'),
+ (mask:potype_unitfinalize; str:'UnitFinalize'),
+ (mask:potype_constructor; str:'Constructor'),
+ (mask:potype_destructor; str:'Destructor'),
+ (mask:potype_operator; str:'Operator'),
+ (mask:potype_procedure; str:'Procedure'),
+ (mask:potype_function; str:'Function'),
+ (mask:potype_class_constructor; str:'Class Constructor'),
+ (mask:potype_class_destructor; str:'Class Destructor'),
+ { Dispinterface property accessors }
+ (mask:potype_propgetter; str:'Property Getter'),
+ (mask:potype_propsetter; str:'Property Setter'),
+ (mask:potype_exceptfilter; str:'SEH filter')
+ );
+ procopt : array[1..ord(high(tprocoption))] of tprocopt=(
+ (mask:po_classmethod; str:'ClassMethod'),
+ (mask:po_virtualmethod; str:'VirtualMethod'),
+ (mask:po_abstractmethod; str:'AbstractMethod'),
+ (mask:po_finalmethod; str:'FinalMethod'),
+ (mask:po_staticmethod; str:'StaticMethod'),
+ (mask:po_overridingmethod;str:'OverridingMethod'),
+ (mask:po_methodpointer; str:'MethodPointer'),
+ (mask:po_interrupt; str:'Interrupt'),
+ (mask:po_iocheck; str:'IOCheck'),
+ (mask:po_assembler; str:'Assembler'),
+ (mask:po_msgstr; str:'MsgStr'),
+ (mask:po_msgint; str:'MsgInt'),
+ (mask:po_exports; str:'Exports'),
+ (mask:po_external; str:'External'),
+ (mask:po_overload; str:'Overload'),
+ (mask:po_varargs; str:'VarArgs'),
+ (mask:po_internconst; str:'InternConst'),
+ (mask:po_addressonly; str:'AddressOnly'),
+ (mask:po_public; str:'Public'),
+ (mask:po_hascallingconvention;str:'HasCallingConvention'),
+ (mask:po_reintroduce; str:'ReIntroduce'),
+ (mask:po_explicitparaloc; str:'ExplicitParaloc'),
+ (mask:po_nostackframe; str:'NoStackFrame'),
+ (mask:po_has_mangledname; str:'HasMangledName'),
+ (mask:po_has_public_name; str:'HasPublicName'),
+ (mask:po_forward; str:'Forward'),
+ (mask:po_global; str:'Global'),
+ (mask:po_has_inlininginfo;str:'HasInliningInfo'),
+ (mask:po_syscall_legacy; str:'SyscallLegacy'),
+ (mask:po_syscall_sysv; str:'SyscallSysV'),
+ (mask:po_syscall_basesysv;str:'SyscallBaseSysV'),
+ (mask:po_syscall_sysvbase;str:'SyscallSysVBase'),
+ (mask:po_syscall_r12base; str:'SyscallR12Base'),
+ (mask:po_inline; str:'Inline'),
+ (mask:po_compilerproc; str:'CompilerProc'),
+ (mask:po_has_importdll; str:'HasImportDLL'),
+ (mask:po_has_importname; str:'HasImportName'),
+ (mask:po_kylixlocal; str:'KylixLocal'),
+ (mask:po_dispid; str:'DispId'),
+ (mask:po_weakexternal; str:'WeakExternal'),
+ (mask:po_objc; str:'ObjC'),
+ (mask:po_enumerator_movenext; str:'EnumeratorMoveNext'),
+ (mask:po_optional; str: 'Optional'),
+ (mask:po_delphi_nested_cc;str: 'Delphi-style nested frameptr'),
+ (mask:po_rtlproc; str: 'RTL procedure')
+ );
+var
+ proctypeoption : tproctypeoption;
+ i : longint;
+ first : boolean;
+ tempbuf : array[0..255] of byte;
+begin
+ write(space,' Return type : ');
+ readderef('');
+ writeln(space,' Fpu used : ',ppufile.getbyte);
+ proctypeoption:=tproctypeoption(ppufile.getbyte);
+ write(space,' TypeOption : ');
+ first:=true;
+ for i:=1 to high(proctypeopt) do
+ if (proctypeopt[i].mask=proctypeoption) then
+ begin
+ if first then
+ first:=false
+ else
+ write(', ');
+ write(proctypeopt[i].str);
+ end;
+ writeln;
+ proccalloption:=tproccalloption(ppufile.getbyte);
+ writeln(space,' CallOption : ',proccalloptionStr[proccalloption]);
+ ppufile.getnormalset(procoptions);
+ if procoptions<>[] then
+ begin
+ write(space,' Options : ');
+ first:=true;
+ for i:=1 to high(procopt) do
+ if (procopt[i].mask in procoptions) then
+ begin
+ if first then
+ first:=false
+ else
+ write(', ');
+ write(procopt[i].str);
+ end;
+ writeln;
+ end;
+ if (po_explicitparaloc in procoptions) then
+ begin
+ i:=ppufile.getbyte;
+ ppufile.getdata(tempbuf,i);
+ end;
+end;
+
+
+{ type tvaroption is in unit symconst }
+ { register variable }
+{ type tvarregable is in unit symconst }
+procedure readabstractvarsym(const s:string;var varoptions:tvaroptions);
+type
+ tvaropt=record
+ mask : tvaroption;
+ str : string[30];
+ end;
+const
+ varopt : array[1..ord(high(tvaroption))] of tvaropt=(
+ (mask:vo_is_external; str:'External'),
+ (mask:vo_is_dll_var; str:'DLLVar'),
+ (mask:vo_is_thread_var; str:'ThreadVar'),
+ (mask:vo_has_local_copy; str:'HasLocalCopy'),
+ (mask:vo_is_const; str:'Constant'),
+ (mask:vo_is_public; str:'Public'),
+ (mask:vo_is_high_para; str:'HighValue'),
+ (mask:vo_is_funcret; str:'Funcret'),
+ (mask:vo_is_self; str:'Self'),
+ (mask:vo_is_vmt; str:'VMT'),
+ (mask:vo_is_result; str:'Result'),
+ (mask:vo_is_parentfp; str:'ParentFP'),
+ (mask:vo_is_loop_counter; str:'LoopCounter'),
+ (mask:vo_is_hidden_para; str:'Hidden'),
+ (mask:vo_has_explicit_paraloc;str:'ExplicitParaloc'),
+ (mask:vo_is_syscall_lib; str:'SysCallLib'),
+ (mask:vo_has_mangledname; str:'HasMangledName'),
+ (mask:vo_is_typed_const; str:'TypedConst'),
+ (mask:vo_is_range_check; str:'RangeCheckSwitch'),
+ (mask:vo_is_overflow_check; str:'OverflowCheckSwitch'),
+ (mask:vo_is_typinfo_para; str:'TypeInfo'),
+ (mask:vo_is_msgsel;str:'MsgSel'),
+ (mask:vo_is_weak_external;str:'WeakExternal'),
+ (mask:vo_is_first_field;str:'IsFirstField'),
+ (mask:vo_volatile;str:'Volatile'),
+ (mask:vo_has_section;str:'HasSection'),
+ (mask:vo_force_finalize;str:'ForceFinalize')
+ );
+var
+ i : longint;
+ first : boolean;
+begin
+ readcommonsym(s);
+ writeln(space,' Spez : ',Varspez2Str(ppufile.getbyte));
+ writeln(space,' Regable : ',Varregable2Str(ppufile.getbyte));
+ writeln(space,' Addr Taken : ',(ppufile.getbyte<>0));
+ write (space,' Var Type : ');
+ readderef('');
+ ppufile.getsmallset(varoptions);
+ if varoptions<>[] then
+ begin
+ write(space,' Options : ');
+ first:=true;
+ for i:=1 to high(varopt) do
+ if (varopt[i].mask in varoptions) then
+ begin
+ if first then
+ first:=false
+ else
+ write(', ');
+ write(varopt[i].str);
+ if varopt[i].mask = vo_has_section then
+ writeln('Section name:',ppufile.getansistring);
+ end;
+ writeln;
+ end;
+end;
+
+
+procedure readobjectdefoptions;
+type
+ tsymopt=record
+ mask : tobjectoption;
+ str : string[30];
+ end;
+const
+ symopt : array[1..ord(high(tobjectoption))] of tsymopt=(
+ (mask:oo_is_forward; str:'IsForward'),
+ (mask:oo_is_abstract; str:'IsAbstract'),
+ (mask:oo_is_sealed; str:'IsSealed'),
+ (mask:oo_has_virtual; str:'HasVirtual'),
+ (mask:oo_has_private; str:'HasPrivate'),
+ (mask:oo_has_protected; str:'HasProtected'),
+ (mask:oo_has_strictprivate; str:'HasStrictPrivate'),
+ (mask:oo_has_strictprotected;str:'HasStrictProtected'),
+ (mask:oo_has_constructor; str:'HasConstructor'),
+ (mask:oo_has_destructor; str:'HasDestructor'),
+ (mask:oo_has_vmt; str:'HasVMT'),
+ (mask:oo_has_msgstr; str:'HasMsgStr'),
+ (mask:oo_has_msgint; str:'HasMsgInt'),
+ (mask:oo_can_have_published; str:'CanHavePublished'),
+ (mask:oo_has_default_property;str:'HasDefaultProperty'),
+ (mask:oo_has_valid_guid; str:'HasValidGUID'),
+ (mask:oo_has_enumerator_movenext; str:'HasEnumeratorMoveNext'),
+ (mask:oo_has_enumerator_current; str:'HasEnumeratorCurrent'),
+ (mask:oo_is_external; str:'External'),
+ (mask:oo_is_formal; str:'Formal'),
+ (mask:oo_is_classhelper; str:'Class Helper/Category'),
+ (mask:oo_has_class_constructor; str:'HasClassConstructor'),
+ (mask:oo_has_class_destructor; str:'HasClassDestructor')
+ );
+var
+ i : longint;
+ first : boolean;
+begin
+ ppufile.getsmallset(current_objectoptions);
+ if current_objectoptions<>[] then
+ begin
+ first:=true;
+ for i:=1 to high(symopt) do
+ if (symopt[i].mask in current_objectoptions) then
+ begin
+ if first then
+ first:=false
+ else
+ write(', ');
+ write(symopt[i].str);
+ end;
+ end;
+ writeln;
+end;
+
+
+procedure readarraydefoptions;
+{ type tarraydefoption is in unit symconst }
+type
+ tsymopt=record
+ mask : tarraydefoption;
+ str : string[30];
+ end;
+const
+ symopt : array[1..ord(high(tarraydefoption))] of tsymopt=(
+ (mask:ado_IsConvertedPointer;str:'ConvertedPointer'),
+ (mask:ado_IsDynamicArray; str:'IsDynamicArray'),
+ (mask:ado_IsVariant; str:'IsVariant'),
+ (mask:ado_IsConstructor; str:'IsConstructor'),
+ (mask:ado_IsArrayOfConst; str:'ArrayOfConst'),
+ (mask:ado_IsConstString; str:'ConstString'),
+ (mask:ado_IsBitPacked; str:'BitPacked')
+ );
+var
+ symoptions : tarraydefoptions;
+ i : longint;
+ first : boolean;
+begin
+ ppufile.getsmallset(symoptions);
+ if symoptions<>[] then
+ begin
+ first:=true;
+ for i:=1 to high(symopt) do
+ if (symopt[i].mask in symoptions) then
+ begin
+ if first then
+ first:=false
+ else
+ write(', ');
+ write(symopt[i].str);
+ end;
+ end;
+ writeln;
+end;
+
+(* options for properties
+ tpropertyoption=(ppo_none,
+ ppo_indexed,
+ ppo_defaultproperty,
+ ppo_stored,
+ ppo_hasparameters,
+ ppo_implements,
+ ppo_enumerator_current,
+ ppo_overrides,
+ ppo_dispid_write { no longer used }
+ );
+ tpropertyoptions=set of tpropertyoption;
+*)
+function readpropertyoptions:tpropertyoptions;
+{ type tarraydefoption is in unit symconst }
+type
+ tpropopt=record
+ mask : tpropertyoption;
+ str : string[30];
+ end;
+const
+ symopt : array[1..ord(high(tpropertyoption))] of tpropopt=(
+ (mask:ppo_indexed;str:'indexed'),
+ (mask:ppo_defaultproperty;str:'default'),
+ (mask:ppo_stored;str:'stored'),
+ (mask:ppo_hasparameters;str:'has parameters'),
+ (mask:ppo_implements;str:'implements'),
+ (mask:ppo_enumerator_current;str:'enumerator current'),
+ (mask:ppo_overrides;str:'overrides'),
+ (mask:ppo_dispid_write;str:'dispid write') { no longer used }
+ );
+var
+ i : longint;
+ first : boolean;
+begin
+ ppufile.getsmallset(result);
+ if result<>[] then
+ begin
+ first:=true;
+ for i:=1 to high(symopt) do
+ if (symopt[i].mask in result) then
+ begin
+ if first then
+ first:=false
+ else
+ write(', ');
+ write(symopt[i].str);
+ end;
+ end;
+ writeln;
+end;
+
+
+procedure readnodetree;
+var
+ l : longint;
+ p : pointer;
+begin
+ with ppufile do
+ begin
+ if space<>'' then
+ Writeln(space,'------ nodetree ------');
+ if readentry=ibnodetree then
+ begin
+ l:=entrysize;
+ Writeln(space,'Tree size : ',l);
+ { Read data to prevent error that entry is not completly read }
+ getmem(p,l);
+ getdata(p^,l);
+ freemem(p);
+ end
+ else
+ begin
+ WriteError('!! ibnodetree not found');
+ end;
+ end;
+end;
+
+
+procedure ReadCreatedObjTypes;
+var
+ i,j,
+ len,
+ bssize: longint;
+ bs: pbyte;
+begin
+ if ppufile.readentry<>ibcreatedobjtypes then
+ begin
+ writeln('!! ibcreatedobjtypes entry not found');
+ ppufile.skipdata(ppufile.entrysize);
+ has_errors:=true;
+ exit
+ end;
+ writeln;
+ writeln(space,'WPO info');
+ writeln(space,'--------');
+
+ len:=ppufile.getlongint;
+ writeln(space,'** Instantiated Object/Class types: ',len,' **');
+ space:=space+' ';
+ for i:=0 to len-1 do
+ readderef(space);
+ setlength(space,length(space)-2);
+
+ len:=ppufile.getlongint;
+ writeln(space,'** Instantiated ClassRef types: ',len,' **');
+ space:=space+' ';
+ for i:=0 to len-1 do
+ readderef(space);
+ setlength(space,length(space)-2);
+
+ len:=ppufile.getlongint;
+ writeln(space,'** Possibly instantiated ClassRef types : ',len,' **');
+ space:=space+' ';
+ for i:=0 to len-1 do
+ readderef(space);
+ setlength(space,length(space)-2);
+
+ len:=ppufile.getlongint;
+ writeln(space,'** Class types with called virtual methods info : ',len,' **');
+ space:=space+' ';
+ for i:=0 to len-1 do
+ begin
+ write(space,'Class def : ');
+ readderef('');
+ write(space+' ','Called vmtentries : ');
+ bssize:=ppufile.getlongint;
+ getmem(bs,bssize);
+ ppufile.readdata(bs^,bssize);
+ for j:=0 to bssize*8-1 do
+ if (((bs+j shr 3)^ shr (j and 7)) and 1) <> 0 then
+ write(j,', ');
+ writeln;
+ freemem(bs);
+ end;
+ setlength(space,length(space)-2);
+end;
+
+{****************************************************************************
+ Read Symbols Part
+****************************************************************************}
+
+procedure readsymbols(const s:string);
+type
+ pguid = ^tguid;
+ tguid = packed record
+ D1: LongWord;
+ D2: Word;
+ D3: Word;
+ D4: array[0..7] of Byte;
+ end;
+
+var
+ b : byte;
+ pc : pchar;
+ ch : dword;
+ startnewline : boolean;
+ i,j,len : longint;
+ prettyname : ansistring;
+ guid : tguid;
+ realvalue : ppureal;
+ doublevalue : double;
+ singlevalue : single;
+ extended : TSplit80bitReal;
+ tempbuf : array[0..127] of char;
+ pw : pcompilerwidestring;
+ varoptions : tvaroptions;
+ propoptions : tpropertyoptions;
+begin
+ with ppufile do
+ begin
+ if space<>'' then
+ Writeln(space,'------ ',s,' ------');
+ if readentry=ibstartsyms then
+ begin
+ Writeln(space,'Symtable datasize : ',getlongint);
+ Writeln(space,'Symtable alignment: ',getlongint);
+ end
+ else
+ Writeln('!! ibstartsym not found');
+ repeat
+ b:=readentry;
+ case b of
+
+ ibunitsym :
+ readcommonsym('Unit symbol ');
+
+ ibnamespacesym :
+ begin
+ readcommonsym('NameSpace symbol ');
+ write(space,' Hidden Unit : ');
+ readderef('');
+ end;
+
+ iblabelsym :
+ readcommonsym('Label symbol ');
+
+ ibtypesym :
+ begin
+ readcommonsym('Type symbol ');
+ write(space,' Result Type : ');
+ readderef('');
+ prettyname:=getansistring;
+ if prettyname<>'' then
+ begin
+ write(space,' Pretty Name : ');
+ Writeln(prettyname);
+ end;
+ end;
+
+ ibprocsym :
+ begin
+ readcommonsym('Procedure symbol ');
+ len:=ppufile.getword;
+ for i:=1 to len do
+ begin
+ write(space,' Definition : ');
+ readderef('');
+ end;
+ end;
+
+ ibconstsym :
+ begin
+ readcommonsym('Constant symbol ');
+ b:=getbyte;
+ case tconsttyp(b) of
+ constord :
+ begin
+ write (space,' OrdinalType : ');
+ readderef('');
+ writeln(space,' Value : ',constexp.tostr(getexprint));
+ end;
+ constpointer :
+ begin
+ write (space,' PointerType : ');
+ readderef('');
+ writeln(space,' Value : ',getaint)
+ end;
+ conststring,
+ constresourcestring :
+ begin
+ len:=getlongint;
+ getmem(pc,len+1);
+ getdata(pc^,len);
+ (pc+len)^:= #0;
+ writeln(space,' Length : ',len);
+ writeln(space,' Value : "',pc,'"');
+ freemem(pc,len+1);
+ end;
+ constreal :
+ begin
+ write(space,' Value : ');
+ if entryleft=sizeof(ppureal) then
+ begin
+ realvalue:=getrealsize(sizeof(ppureal));
+ writeln(realvalue);
+ end
+ else if entryleft=sizeof(double) then
+ begin
+ doublevalue:=getrealsize(sizeof(double));
+ writeln(doublevalue);
+ end
+ else if entryleft=sizeof(single) then
+ begin
+ singlevalue:=getrealsize(sizeof(single));
+ writeln(singlevalue);
+ end
+ else if entryleft=10 then
+ begin
+ getdata(extended,entryleft);
+ writeln(Real80bitToStr(extended));
+ end
+ else
+ begin
+ realvalue:=0.0;
+ writeln(realvalue,' Error reading real value');
+ has_errors:=true;
+ end;
+ end;
+ constset :
+ begin
+ write (space,' Set Type : ');
+ readderef('');
+ for i:=1to 4 do
+ begin
+ write (space,' Value : ');
+ for j:=1to 8 do
+ begin
+ if j>1 then
+ write(',');
+ write(hexstr(getbyte,2));
+ end;
+ writeln;
+ end;
+ end;
+ constnil:
+ writeln(space,' NIL pointer.');
+ constwstring :
+ begin
+ initwidestring(pw);
+ setlengthwidestring(pw,getlongint);
+ if widecharsize=2 then
+ { don't use getdata, because the compilerwidechars may have to
+ be byteswapped
+ }
+ begin
+ for i:=0 to pw^.len-1 do
+ pw^.data[i]:=ppufile.getword;
+ end
+ else if widecharsize=4 then
+ begin
+ for i:=0 to pw^.len-1 do
+ pw^.data[i]:=cardinal(ppufile.getlongint);
+ end
+ else
+ begin
+ WriteError('Unsupported tcompilerwidechar size');
+ end;
+ Writeln(space,'Wide string type');
+ startnewline:=true;
+ for i:=0 to pw^.len-1 do
+ begin
+ if startnewline then
+ begin
+ write(space);
+ startnewline:=false;
+ end;
+ ch:=pw^.data[i];
+ if widecharsize=2 then
+ write(hexstr(ch,4))
+ else
+ write(hexstr(ch,8));
+ if (i mod 8)= 0 then
+ startnewline:=true
+ else
+ write(', ');
+ end;
+ donewidestring(pw);
+ end;
+ constguid:
+ begin
+ getdata(guid,sizeof(guid));
+ write (space,' IID String: {',hexstr(guid.d1,8),'-',hexstr(guid.d2,4),'-',hexstr(guid.d3,4),'-');
+ for i:=0 to 7 do
+ begin
+ write(hexstr(guid.d4[i],2));
+ if i=1 then write('-');
+ end;
+ writeln('}');
+ end
+ else
+ Writeln ('!! Invalid unit format : Invalid const type encountered: ',b);
+ end;
+ end;
+
+ ibabsolutevarsym :
+ begin
+ readabstractvarsym('Absolute variable symbol ',varoptions);
+ Write (space,' Relocated to ');
+ b:=getbyte;
+ case absolutetyp(b) of
+ tovar :
+ readpropaccesslist(space+' Sym : ');
+ toasm :
+ Writeln('Assembler name : ',getstring);
+ toaddr :
+ begin
+ Write('Address : ',getlongint);
+ if tsystemcpu(ppufile.header.cpu)=cpu_i386 then
+ WriteLn(' (Far: ',getbyte<>0,')');
+ end;
+ else
+ Writeln ('!! Invalid unit format : Invalid absolute type encountered: ',b);
+ end;
+ end;
+
+ ibfieldvarsym :
+ begin
+ readabstractvarsym('Field Variable symbol ',varoptions);
+ writeln(space,' Address : ',getaint);
+ end;
+
+ ibstaticvarsym :
+ begin
+ readabstractvarsym('Global Variable symbol ',varoptions);
+ write (space,' DefaultConst : ');
+ readderef('');
+ if (vo_has_mangledname in varoptions) then
+ writeln(space,' Mangledname : ',getstring);
+ end;
+
+ iblocalvarsym :
+ begin
+ readabstractvarsym('Local Variable symbol ',varoptions);
+ write (space,' DefaultConst : ');
+ readderef('');
+ end;
+
+ ibparavarsym :
+ begin
+ readabstractvarsym('Parameter Variable symbol ',varoptions);
+ write (space,' DefaultConst : ');
+ readderef('');
+ writeln(space,' ParaNr : ',getword);
+ writeln(space,' Univ : ',boolean(getbyte));
+ writeln(space,' VarState : ',getbyte);
+ if (vo_has_explicit_paraloc in varoptions) then
+ begin
+ i:=getbyte;
+ getdata(tempbuf,i);
+ end;
+ end;
+
+ ibenumsym :
+ begin
+ readcommonsym('Enumeration symbol ');
+ write (space,' Definition : ');
+ readderef('');
+ writeln(space,' Value : ',getlongint);
+ end;
+
+ ibsyssym :
+ begin
+ readcommonsym('Internal system symbol ');
+ writeln(space,' Internal Nr : ',getlongint);
+ end;
+
+ ibmacrosym :
+ begin
+ readcommonsym('Macro symbol ');
+ writeln(space,' Name: ',getstring);
+ writeln(space,' Defined: ',getbyte);
+ writeln(space,' Compiler var: ',getbyte);
+ len:=getlongint;
+ writeln(space,' Value length: ',len);
+ if len > 0 then
+ begin
+ getmem(pc,len+1);
+ getdata(pc^,len);
+ (pc+len)^:= #0;
+ writeln(space,' Value: "',pc,'"');
+ freemem(pc,len+1);
+ end;
+ end;
+
+ ibpropertysym :
+ begin
+ readcommonsym('Property ');
+ propoptions:=readpropertyoptions;
+ if ppo_overrides in propoptions then
+ begin
+ write (space,' OverrideProp : ');
+ readderef('');
+ end;
+ write (space,' Prop Type : ');
+ readderef('');
+ writeln(space,' Index : ',getlongint);
+ writeln(space,' Default : ',getlongint);
+ write (space,' Index Type : ');
+ readderef('');
+ { palt_none }
+ readpropaccesslist('');
+ write (space,' Readaccess : ');
+ readpropaccesslist(space+' Sym: ');
+ write (space,' Writeaccess : ');
+ readpropaccesslist(space+' Sym: ');
+ write (space,' Storedaccess : ');
+ readpropaccesslist(space+' Sym: ');
+ if [ppo_hasparameters,ppo_overrides]*propoptions=[ppo_hasparameters] then
+ begin
+ space:=' '+space;
+ readsymtable('parast');
+ delete(space,1,4);
+ end;
+ end;
+
+ iberror :
+ begin
+ WriteError('!! Error in PPU');
+ exit;
+ end;
+
+ ibendsyms :
+ break;
+
+ else
+ begin
+ WriteLn('!! Skipping unsupported PPU Entry in Symbols: ',b);
+ has_errors:=true;
+ end;
+ end;
+ if not EndOfEntry then
+ HasMoreInfos;
+ until false;
+ end;
+end;
+
+
+{****************************************************************************
+ Read defintions Part
+****************************************************************************}
+
+procedure readdefinitions(const s:string);
+{ type tordtype is in symconst unit }
+{
+ uvoid,
+ u8bit,u16bit,u32bit,u64bit,
+ s8bit,s16bit,s32bit,s64bit,
+ bool8bit,bool16bit,bool32bit,bool64bit,
+ uchar,uwidechar,scurrency
+ ); }
+
+{ type tobjecttyp is in symconst unit }
+{ type tvarianttype is in symconst unit }
+var
+ b : byte;
+ l,j : longint;
+ calloption : tproccalloption;
+ procoptions : tprocoptions;
+ defoptions: tdefoptions;
+begin
+ with ppufile do
+ begin
+ if space<>'' then
+ Writeln(space,'------ ',s,' ------');
+ if readentry<>ibstartdefs then
+ Writeln('!! ibstartdefs not found');
+ repeat
+ b:=readentry;
+ case b of
+
+ ibpointerdef :
+ begin
+ readcommondef('Pointer definition',defoptions);
+ write (space,' Pointed Type : ');
+ readderef('');
+ writeln(space,' Is Far : ',(getbyte<>0));
+ writeln(space,' Has Pointer Math : ',(getbyte<>0));
+ end;
+
+ iborddef :
+ begin
+ readcommondef('Ordinal definition',defoptions);
+ write (space,' Base type : ');
+ b:=getbyte;
+ case tordtype(b) of
+ uvoid : writeln('uvoid');
+ u8bit : writeln('u8bit');
+ u16bit : writeln('u16bit');
+ u32bit : writeln('s32bit');
+ u64bit : writeln('u64bit');
+ s8bit : writeln('s8bit');
+ s16bit : writeln('s16bit');
+ s32bit : writeln('s32bit');
+ s64bit : writeln('s64bit');
+ bool8bit : writeln('bool8bit');
+ bool16bit : writeln('bool16bit');
+ bool32bit : writeln('bool32bit');
+ bool64bit : writeln('bool64bit');
+ uchar : writeln('uchar');
+ uwidechar : writeln('uwidechar');
+ scurrency : writeln('ucurrency');
+ else writeln('!! Warning: Invalid base type ',b);
+ end;
+ writeln(space,' Range : ',constexp.tostr(getexprint),' to ',constexp.tostr(getexprint));
+ end;
+
+ ibfloatdef :
+ begin
+ readcommondef('Float definition',defoptions);
+ writeln(space,' Float type : ',getbyte);
+ end;
+
+ ibarraydef :
+ begin
+ readcommondef('Array definition',defoptions);
+ write (space,' Element type : ');
+ readderef('');
+ write (space,' Range Type : ');
+ readderef('');
+ writeln(space,' Range : ',getaint,' to ',getaint);
+ write (space,' Options : ');
+ readarraydefoptions;
+ readsymtable('symbols');
+ end;
+
+ ibprocdef :
+ begin
+ readcommondef('Procedure definition',defoptions);
+ read_abstract_proc_def(calloption,procoptions);
+ if (po_has_mangledname in procoptions) then
+ writeln(space,' Mangled name : ',getstring);
+ writeln(space,' Number : ',getword);
+ writeln(space,' Level : ',getbyte);
+ write (space,' Class : ');
+ readderef('');
+ write (space,' Procsym : ');
+ readderef('');
+ write (space,' File Pos : ');
+ readposinfo;
+ writeln(space,' Visibility : ',Visibility2Str(ppufile.getbyte));
+ write (space,' SymOptions : ');
+ readsymoptions(space+' ');
+ if tsystemcpu(ppufile.header.cpu)=cpu_powerpc then
+ begin
+ { library symbol for AmigaOS/MorphOS }
+ write (space,' Library symbol : ');
+ readderef('');
+ end;
+ if (po_has_importdll in procoptions) then
+ writeln(space,' Import DLL : ',getstring);
+ if (po_has_importname in procoptions) then
+ writeln(space,' Import Name : ',getstring);
+ writeln(space,' Import Nr : ',getword);
+ if (po_msgint in procoptions) then
+ writeln(space,' MsgInt : ',getlongint);
+ if (po_msgstr in procoptions) then
+ writeln(space,' MsgStr : ',getstring);
+ if (po_dispid in procoptions) then
+ writeln(space,' DispID: ',ppufile.getlongint);
+ if (po_has_inlininginfo in procoptions) then
+ begin
+ write (space,' FuncretSym : ');
+ readderef('');
+ readprocinfooptions(space);
+ end;
+ b:=ppufile.getbyte;
+ if b<>0 then
+ begin
+ write (space,' Alias names : ');
+ for j:=1 to b do
+ begin
+ write(ppufile.getstring);
+ if j<b then
+ write(', ');
+ end;
+ writeln;
+ end;
+ if not EndOfEntry then
+ HasMoreInfos;
+ space:=' '+space;
+ { parast }
+ readsymtable('parast');
+ { localst }
+ if (po_has_inlininginfo in procoptions) then
+ readsymtable('localst');
+ if (po_has_inlininginfo in procoptions) then
+ readnodetree;
+ delete(space,1,4);
+ end;
+
+ ibprocvardef :
+ begin
+ readcommondef('Procedural type (ProcVar) definition',defoptions);
+ read_abstract_proc_def(calloption,procoptions);
+ writeln(space,' Symtable level :',ppufile.getbyte);
+ if not EndOfEntry then
+ HasMoreInfos;
+ space:=' '+space;
+ { parast }
+ readsymtable('parast');
+ delete(space,1,4);
+ end;
+
+ ibshortstringdef :
+ begin
+ readcommondef('ShortString definition',defoptions);
+ writeln(space,' Length : ',getbyte);
+ end;
+
+ ibwidestringdef :
+ begin
+ readcommondef('WideString definition',defoptions);
+ writeln(space,' Length : ',getaint);
+ end;
+
+ ibunicodestringdef :
+ begin
+ readcommondef('UnicodeString definition',defoptions);
+ writeln(space,' Length : ',getaint);
+ end;
+
+ ibansistringdef :
+ begin
+ readcommondef('AnsiString definition',defoptions);
+ writeln(space,' Length : ',getaint);
+ end;
+
+ iblongstringdef :
+ begin
+ readcommondef('Longstring definition',defoptions);
+ writeln(space,' Length : ',getaint);
+ end;
+
+ ibrecorddef :
+ begin
+ readcommondef('Record definition',defoptions);
+ writeln(space,' Name of Record : ',getstring);
+ write (space,' Options : ');
+ readobjectdefoptions;
+ writeln(space,' FieldAlign : ',shortint(getbyte));
+ writeln(space,' RecordAlign : ',shortint(getbyte));
+ writeln(space,' PadAlign : ',shortint(getbyte));
+ writeln(space,'UseFieldAlignment : ',shortint(getbyte));
+ writeln(space,' DataSize : ',getasizeint);
+ writeln(space,' PaddingSize : ',getword);
+ if df_copied_def in current_defoptions then
+ begin
+ writeln(' Copy of def: ');
+ readderef('');
+ end;
+
+ if not EndOfEntry then
+ HasMoreInfos;
+ {read the record definitions and symbols}
+ if not(df_copied_def in current_defoptions) then
+ begin
+ space:=' '+space;
+ readrecsymtableoptions;
+ readsymtable('fields');
+ Delete(space,1,4);
+ end;
+ end;
+
+ ibobjectdef :
+ begin
+ readcommondef('Object/Class definition',defoptions);
+ writeln(space,' Name of Class : ',getstring);
+ write (space,' Options : ');
+ readobjectdefoptions;
+ b:=getbyte;
+ write (space,' Type : ');
+ case tobjecttyp(b) of
+ odt_class : writeln('class');
+ odt_object : writeln('object');
+ odt_interfacecom : writeln('interfacecom');
+ odt_interfacecorba : writeln('interfacecorba');
+ odt_cppclass : writeln('cppclass');
+ odt_dispinterface : writeln('dispinterface');
+ odt_objcclass : writeln('objcclass');
+ odt_objcprotocol : writeln('objcprotocol');
+ odt_helper : writeln('helper');
+ else writeln('!! Warning: Invalid object type ',b);
+ end;
+ writeln(space,' External name : ',getstring);
+ writeln(space,' Import lib : ',getstring);
+ writeln(space,' DataSize : ',getasizeint);
+ writeln(space,' PaddingSize : ',getword);
+ writeln(space,' FieldAlign : ',shortint(getbyte));
+ writeln(space,' RecordAlign : ',shortint(getbyte));
+ writeln(space,' Vmt offset : ',getlongint);
+ write (space, ' Ancestor Class : ');
+ readderef('');
+
+ if tobjecttyp(b) in [odt_interfacecom,odt_interfacecorba,odt_dispinterface] then
+ begin
+ { IIDGUID }
+ for j:=1to 16 do
+ getbyte;
+ writeln(space,' IID String : ',getstring);
+ end;
+
+ if (tobjecttyp(b)=odt_helper) or
+ (oo_is_classhelper in current_objectoptions) then
+ begin
+ write(space,' Helper parent : ');
+ readderef('');
+ end;
+
+ l:=getlongint;
+ writeln(space,' VMT entries: ',l);
+ for j:=1 to l do
+ begin
+ write(space,' ');
+ readderef('');
+ writeln(space,' Visibility: ',Visibility2Str(getbyte));
+ end;
+
+ if tobjecttyp(b) in [odt_class,odt_interfacecorba,odt_objcclass,odt_objcprotocol] then
+ begin
+ l:=getlongint;
+ writeln(space,' Impl Intf Count : ',l);
+ for j:=1 to l do
+ begin
+ write (space,' - Definition : ');
+ readderef('');
+ writeln(space,' IOffset : ',getlongint);
+ end;
+ end;
+
+ if df_copied_def in current_defoptions then
+ begin
+ writeln(' Copy of def: ');
+ readderef('');
+ end;
+
+ if not EndOfEntry then
+ HasMoreInfos;
+ if not(df_copied_def in current_defoptions) then
+ begin
+ {read the record definitions and symbols}
+ space:=' '+space;
+ readrecsymtableoptions;
+ readsymtable('fields');
+ Delete(space,1,4);
+ end;
+ end;
+
+ ibfiledef :
+ begin
+ ReadCommonDef('File definition',defoptions);
+ write (space,' Type : ');
+ case getbyte of
+ 0 : writeln('Text');
+ 1 : begin
+ writeln('Typed');
+ write (space,' File of Type : ');
+ readderef('');
+ end;
+ 2 : writeln('Untyped');
+ end;
+ end;
+
+ ibformaldef :
+ begin
+ readcommondef('Generic definition (void-typ)',defoptions);
+ writeln(space,' Is Typed : ',(getbyte<>0));
+ end;
+
+ ibundefineddef :
+ readcommondef('Undefined definition (generic parameter)',defoptions);
+
+ ibenumdef :
+ begin
+ readcommondef('Enumeration type definition',defoptions);
+ writeln(space,' Smallest element : ',getaint);
+ writeln(space,' Largest element : ',getaint);
+ writeln(space,' Size : ',getaint);
+ if df_copied_def in defoptions then
+ begin
+ write(space,'Base enumeration type : ');
+ readderef('');
+ end
+ else
+ begin
+ space:=' '+space;
+ readsymtable('elements');
+ delete(space,1,4);
+ end;
+ end;
+
+ ibclassrefdef :
+ begin
+ readcommondef('Class reference definition',defoptions);
+ write (space,' Pointed Type : ');
+ readderef('');
+ end;
+
+ ibsetdef :
+ begin
+ readcommondef('Set definition',defoptions);
+ write (space,' Element type : ');
+ readderef('');
+ writeln(space,' Size : ',getaint);
+ writeln(space,' Set Base : ',getaint);
+ writeln(space,' Set Max : ',getaint);
+ end;
+
+ ibvariantdef :
+ begin
+ readcommondef('Variant definition',defoptions);
+ write (space,' Varianttype : ');
+ b:=getbyte;
+ case tvarianttype(b) of
+ vt_normalvariant :
+ writeln('Normal');
+ vt_olevariant :
+ writeln('OLE');
+ else
+ writeln('!! Warning: Invalid varianttype ',b);
+ end;
+
+ end;
+
+ iberror :
+ begin
+ WriteError('!! Error in PPU');
+ exit;
+ end;
+
+ ibenddefs :
+ break;
+
+ else
+ begin
+ WriteLn('!! Skipping unsupported PPU Entry in definitions: ',b);
+ has_errors:=true;
+ end;
+ end;
+ if not EndOfEntry then
+ HasMoreInfos;
+ until false;
+ end;
+end;
+
+procedure readmoduleoptions(space : string);
+type
+{ tmoduleoption type is in unit fmodule }
+ tmoduleoption = (mo_none,
+ mo_hint_deprecated,
+ mo_hint_platform,
+ mo_hint_library,
+ mo_hint_unimplemented,
+ mo_hint_experimental,
+ mo_has_deprecated_msg
+ );
+ tmoduleoptions = set of tmoduleoption;
+ tmoduleopt=record
+ mask : tmoduleoption;
+ str : string[30];
+ end;
+const
+ moduleopts=ord(high(tmoduleoption));
+ moduleopt : array[1..moduleopts] of tmoduleopt=(
+ (mask:mo_hint_deprecated; str:'Hint Deprecated'),
+ (mask:mo_hint_platform; str:'Hint Platform'),
+ (mask:mo_hint_library; str:'Hint Library'),
+ (mask:mo_hint_unimplemented; str:'Hint Unimplemented'),
+ (mask:mo_hint_experimental; str:'Hint Experimental'),
+ (mask:mo_has_deprecated_msg; str:'Has Deprecated Message')
+ );
+var
+ moduleoptions : tmoduleoptions;
+ i : longint;
+ first : boolean;
+begin
+ ppufile.getsmallset(moduleoptions);
+ if moduleoptions<>[] then
+ begin
+ first:=true;
+ for i:=1to moduleopts do
+ if (moduleopt[i].mask in moduleoptions) then
+ begin
+ if first then
+ first:=false
+ else
+ write(', ');
+ write(moduleopt[i].str);
+ end;
+ end;
+ writeln;
+ if mo_has_deprecated_msg in moduleoptions then
+ writeln(space,'Deprecated : ', ppufile.getstring);
+end;
+
+{****************************************************************************
+ Read General Part
+****************************************************************************}
+
+procedure readinterface;
+var
+ b : byte;
+ sourcenumber : longint;
+begin
+ with ppufile do
+ begin
+ repeat
+ b:=readentry;
+ case b of
+
+ ibmodulename :
+ Writeln('Module Name: ',getstring);
+
+ ibmoduleoptions:
+ readmoduleoptions(' ');
+
+ ibsourcefiles :
+ begin
+ sourcenumber:=1;
+ while not EndOfEntry do
+ begin
+ Writeln('Source file ',sourcenumber,' : ',getstring,' ',filetimestring(getlongint));
+ inc(sourcenumber);
+ end;
+ end;
+{$IFDEF MACRO_DIFF_HINT}
+ ibusedmacros :
+ begin
+ while not EndOfEntry do
+ begin
+ Write('Conditional ',getstring);
+ b:=getbyte;
+ if boolean(b)=true then
+ write(' defined at startup')
+ else
+ write(' not defined at startup');
+ b:=getbyte;
+ if boolean(b)=true then
+ writeln(' was used')
+ else
+ writeln;
+ end;
+ end;
+{$ENDIF}
+ ibloadunit :
+ ReadLoadUnit;
+
+ iblinkunitofiles :
+ ReadLinkContainer('Link unit object file: ');
+
+ iblinkunitstaticlibs :
+ ReadLinkContainer('Link unit static lib: ');
+
+ iblinkunitsharedlibs :
+ ReadLinkContainer('Link unit shared lib: ');
+
+ iblinkotherofiles :
+ ReadLinkContainer('Link other object file: ');
+
+ iblinkotherstaticlibs :
+ ReadLinkContainer('Link other static lib: ');
+
+ iblinkothersharedlibs :
+ ReadLinkContainer('Link other shared lib: ');
+
+ iblinkotherframeworks:
+ ReadLinkContainer('Link framework: ');
+
+ ibmainname:
+ Writeln('Specified main program symbol name: ',getstring);
+
+ ibImportSymbols :
+ ReadImportSymbols;
+
+ ibderefdata :
+ ReadDerefData;
+
+ ibderefmap :
+ ReadDerefMap;
+
+ ibwpofile :
+ ReadWpoFileInfo;
+
+ ibresources :
+ ReadLinkContainer('Resource file: ');
+
+ iberror :
+ begin
+ WriteError('Error in PPU');
+ exit;
+ end;
+
+ ibendinterface :
+ break;
+
+ else
+ begin
+ WriteLn('!! Skipping unsupported PPU Entry in General Part: ',b);
+ has_errors:=true;
+ end;
+ end;
+ until false;
+ end;
+end;
+
+
+
+{****************************************************************************
+ Read Implementation Part
+****************************************************************************}
+
+procedure readimplementation;
+var
+ b : byte;
+begin
+ with ppufile do
+ begin
+ repeat
+ b:=readentry;
+ case b of
+ ibasmsymbols :
+ ReadAsmSymbols;
+
+ ibloadunit :
+ ReadLoadUnit;
+
+ iberror :
+ begin
+ WriteError('Error in PPU');
+ exit;
+ end;
+ ibendimplementation :
+ break;
+ else
+ begin
+ WriteLn('!! Skipping unsupported PPU Entry in Implementation: ',b);
+ has_errors:=true;
+ end;
+ end;
+ until false;
+ end;
+end;
+
+
+procedure dofile (filename : string);
+begin
+{ reset }
+ space:='';
+{ fix filename }
+ if pos('.',filename)=0 then
+ filename:=filename+'.ppu';
+ ppufile:=tppufile.create(filename);
+ if not ppufile.openfile then
+ begin
+ WriteError('IO-Error when opening : '+filename+', Skipping');
+ exit;
+ end;
+{ PPU File is open, check for PPU Id }
+ if not ppufile.CheckPPUID then
+ begin
+ writeln(Filename,' : Not a valid PPU file, Skipping');
+ has_errors:=true;
+ exit;
+ end;
+{ Check PPU Version }
+ ppuversion:=ppufile.GetPPUVersion;
+
+ Writeln('Analyzing ',filename,' (v',PPUVersion,')');
+ if PPUVersion<16 then
+ begin
+ writeln(Filename,' : Old PPU Formats (<v16) are not supported, Skipping');
+ has_errors:=true;
+ exit;
+ end;
+{ Write PPU Header Information }
+ if (verbose and v_header)<>0 then
+ begin
+ Writeln;
+ Writeln('Header');
+ Writeln('-------');
+ with ppufile.header do
+ begin
+ Writeln('Compiler version : ',ppufile.header.compiler shr 14,'.',
+ (ppufile.header.compiler shr 7) and $7f,'.',
+ ppufile.header.compiler and $7f);
+ WriteLn('Target processor : ',Cpu2Str(cpu));
+ WriteLn('Target operating system : ',Target2Str(target));
+ Writeln('Unit flags : ',PPUFlags2Str(flags));
+ Writeln('FileSize (w/o header) : ',size);
+ Writeln('Checksum : ',hexstr(checksum,8));
+ Writeln('Interface Checksum : ',hexstr(interface_checksum,8));
+ Writeln('Indirect Checksum : ',hexstr(indirect_checksum,8));
+ Writeln('Definitions stored : ',tostr(deflistsize));
+ Writeln('Symbols stored : ',tostr(symlistsize));
+ end;
+ end;
+{read the general stuff}
+ if (verbose and v_interface)<>0 then
+ begin
+ Writeln;
+ Writeln('Interface section');
+ Writeln('------------------');
+ readinterface;
+ end
+ else
+ ppufile.skipuntilentry(ibendinterface);
+ Writeln;
+ Writeln('Interface symtable');
+ Writeln('----------------------');
+ readsymtableoptions('interface');
+{read the definitions}
+ if (verbose and v_defs)<>0 then
+ begin
+ Writeln;
+ Writeln('Interface definitions');
+ Writeln('----------------------');
+ readdefinitions('interface');
+ end
+ else
+ ppufile.skipuntilentry(ibenddefs);
+{read the symbols}
+ if (verbose and v_syms)<>0 then
+ begin
+ Writeln;
+ Writeln('Interface Symbols');
+ Writeln('------------------');
+ readsymbols('interface');
+ end
+ else
+ ppufile.skipuntilentry(ibendsyms);
+
+{read the macro symbols}
+ if (verbose and v_syms)<>0 then
+ begin
+ Writeln;
+ Writeln('Interface Macro Symbols');
+ Writeln('-----------------------');
+ end;
+ if ppufile.readentry<>ibexportedmacros then
+ begin
+ WriteError('!! Error in PPU');
+ exit;
+ end;
+ if boolean(ppufile.getbyte) then
+ begin
+ readsymtableoptions('interface macro');
+ {skip the definition section for macros (since they are never used) }
+ ppufile.skipuntilentry(ibenddefs);
+ {read the macro symbols}
+ if (verbose and v_syms)<>0 then
+ readsymbols('interface macro')
+ else
+ ppufile.skipuntilentry(ibendsyms);
+ end
+ else
+ Writeln('(no exported macros)');
+
+{read the implementation stuff}
+ if (verbose and v_implementation)<>0 then
+ begin
+ Writeln;
+ Writeln('Implementation section');
+ Writeln('-----------------------');
+ readimplementation;
+ end
+ else
+ ppufile.skipuntilentry(ibendimplementation);
+ {read the static symtable}
+ Writeln;
+ Writeln('Implementation symtable');
+ Writeln('----------------------');
+ readsymtableoptions('implementation');
+ if (ppufile.header.flags and uf_local_symtable)<>0 then
+ begin
+ if (verbose and v_defs)<>0 then
+ begin
+ Writeln;
+ Writeln('Static definitions');
+ Writeln('----------------------');
+ readdefinitions('implementation');
+ end
+ else
+ ppufile.skipuntilentry(ibenddefs);
+ {read the symbols}
+ if (verbose and v_syms)<>0 then
+ begin
+ Writeln;
+ Writeln('Static Symbols');
+ Writeln('------------------');
+ readsymbols('implementation');
+ end
+ else
+ ppufile.skipuntilentry(ibendsyms);
+ end;
+ ReadCreatedObjTypes;
+ FreeDerefdata;
+{shutdown ppufile}
+ ppufile.closefile;
+ ppufile.free;
+ Writeln;
+end;
+
+
+
+procedure help;
+begin
+ writeln('usage: ppudump [options] <filename1> <filename2>...');
+ writeln;
+ writeln('[options] can be:');
+ writeln(' -M Exit with ExitCode=2 if more information is available');
+ writeln(' -V<verbose> Set verbosity to <verbose>');
+ writeln(' H - Show header info');
+ writeln(' I - Show interface');
+ writeln(' M - Show implementation');
+ writeln(' S - Show interface symbols');
+ writeln(' D - Show interface definitions');
+// writeln(' B - Show browser info');
+ writeln(' A - Show all');
+ writeln(' -h, -? This helpscreen');
+ halt;
+end;
+
+var
+ startpara,
+ nrfile,i : longint;
+ para : string;
+const
+ error_on_more : boolean = false;
+begin
+ writeln(Title+' '+Version);
+ writeln(Copyright);
+ writeln;
+ if paramcount<1 then
+ begin
+ writeln('usage: dumpppu [options] <filename1> <filename2>...');
+ halt(1);
+ end;
+{ turn verbose on by default }
+ verbose:=v_all;
+{ read options }
+ startpara:=1;
+ while copy(paramstr(startpara),1,1)='-' do
+ begin
+ para:=paramstr(startpara);
+ case upcase(para[2]) of
+ 'M' : error_on_more:=true;
+ 'V' : begin
+ verbose:=0;
+ for i:=3 to length(para) do
+ case upcase(para[i]) of
+ 'H' : verbose:=verbose or v_header;
+ 'I' : verbose:=verbose or v_interface;
+ 'M' : verbose:=verbose or v_implementation;
+ 'D' : verbose:=verbose or v_defs;
+ 'S' : verbose:=verbose or v_syms;
+ 'A' : verbose:=verbose or v_all;
+ end;
+ end;
+ 'H' : help;
+ '?' : help;
+ end;
+ inc(startpara);
+ end;
+{ process files }
+ for nrfile:=startpara to paramcount do
+ dofile (paramstr(nrfile));
+ if has_errors then
+ Halt(1);
+ if error_on_more and has_more_infos then
+ Halt(2);
+end.
diff --git a/closures/compiler/utils/ppufiles.pp b/closures/compiler/utils/ppufiles.pp
new file mode 100644
index 0000000000..f2d164cedf
--- /dev/null
+++ b/closures/compiler/utils/ppufiles.pp
@@ -0,0 +1,246 @@
+{
+ Copyright (c) 1999-2002 by Peter Vreman
+
+ List files needed by PPU
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************}
+Program ppufiles;
+
+uses
+ dos,
+ ppu;
+
+const
+ Version = 'Version 1.00';
+ Title = 'PPU-Files';
+ Copyright = 'Copyright (c) 1999-2002 by the Free Pascal Development Team';
+
+ PPUExt = 'ppu';
+
+type
+ poutfile = ^toutfile;
+ toutfile = record
+ name : string;
+ next : poutfile;
+ end;
+
+var
+ skipdup,
+ showstatic,
+ showshared,
+ showobjects : boolean;
+
+ OutFiles : poutfile;
+
+
+{*****************************************************************************
+ Helpers
+*****************************************************************************}
+
+Procedure Error(const s:string;stop:boolean);
+{
+ Write an error message to stderr
+}
+begin
+ writeln(stderr,s);
+ if stop then
+ halt(1);
+end;
+
+
+Function ChangeFileExt(Const HStr,ext:String):String;
+{
+ Return a filename which will have extension ext added if no
+ extension is found
+}
+var
+ j : longint;
+begin
+ j:=length(Hstr);
+ while (j>0) and (Hstr[j]<>'.') do
+ dec(j);
+ if j=0 then
+ ChangeFileExt:=Hstr+'.'+Ext
+ else
+ ChangeFileExt:=HStr;
+end;
+
+
+Function SplitPath(Const HStr:String):String;
+var
+ i : longint;
+begin
+ i:=Length(Hstr);
+ while (i>0) and not(Hstr[i] in ['\','/']) do
+ dec(i);
+ SplitPath:=Copy(Hstr,1,i);
+end;
+
+
+Procedure AddFile(const s:string);
+var
+ p : poutfile;
+begin
+ p:=nil;
+ if skipdup then
+ begin
+ p:=outfiles;
+ while assigned(p) do
+ begin
+ if s=p^.name then
+ break;
+ p:=p^.next;
+ end;
+ end;
+ if not assigned(p) then
+ begin
+ new(p);
+ p^.name:=s;
+ p^.next:=outfiles;
+ outfiles:=p;
+ end;
+end;
+
+
+Function DoPPU(const PPUFn:String):Boolean;
+{
+ Convert one file (in Filename) to library format.
+ Return true if successful, false otherwise.
+}
+Var
+ inppu : tppufile;
+ b : byte;
+
+ procedure showfiles;
+ begin
+ while not inppu.endofentry do
+ begin
+ AddFile(inppu.getstring);
+ inppu.getlongint;
+ end;
+ end;
+
+begin
+ DoPPU:=false;
+ inppu:=tppufile.create(PPUFn);
+ if not inppu.openfile then
+ begin
+ inppu.free;
+ Error('Error: Could not open : '+PPUFn,false);
+ Exit;
+ end;
+{ Check the ppufile }
+ if not inppu.CheckPPUId then
+ begin
+ inppu.free;
+ Error('Error: Not a PPU File : '+PPUFn,false);
+ Exit;
+ end;
+ if inppu.GetPPUVersion<CurrentPPUVersion then
+ begin
+ inppu.free;
+ Error('Error: Wrong PPU Version : '+PPUFn,false);
+ Exit;
+ end;
+{ read until the object files are found }
+ repeat
+ b:=inppu.readentry;
+ case b of
+ ibendinterface,
+ ibend :
+ break;
+ iblinkunitstaticlibs :
+ if showstatic then
+ showfiles;
+ iblinkunitsharedlibs :
+ if showshared then
+ showfiles;
+ iblinkunitofiles :
+ if showobjects then
+ showfiles;
+ end;
+ until false;
+ inppu.free;
+ DoPPU:=True;
+end;
+
+
+
+var
+ i,parafile : longint;
+ dir : SearchRec;
+ s,InFile : String;
+ p : poutfile;
+begin
+{ defaults }
+ skipdup:=true;
+{ options }
+ i:=1;
+ while (i<=paramcount) do
+ begin
+ s:=paramstr(i);
+ if s[1]<>'-' then
+ break;
+ case upcase(s[2]) of
+ 'L' : showshared:=true;
+ 'S' : showstatic:=true;
+ 'O' : showobjects:=true;
+ 'A' : skipdup:=false;
+ '?','H' :
+ begin
+ writeln('usage: ppufiles [options] <files>');
+ writeln('options:');
+ writeln(' -A Show all files (don''t remove duplicates)');
+ writeln(' -L Show only shared libraries');
+ writeln(' -S Show only static libraries');
+ writeln(' -O Show only object files');
+ writeln(' -H This helpscreen');
+ end;
+ end;
+ inc(i);
+ end;
+ { default shows everything }
+ if i=1 then
+ begin
+ showshared:=true;
+ showstatic:=true;
+ showobjects:=true;
+ end;
+{ files }
+ parafile:=i;
+ for i:=parafile to ParamCount do
+ begin
+ InFile:=ChangeFileExt(ParamStr(i),PPUExt);
+ FindFirst(InFile,$20,Dir);
+ while (DosError=0) do
+ begin
+ DoPPU(SplitPath(InFile)+Dir.Name);
+ FindNext(Dir);
+ end;
+ FindClose(Dir);
+ end;
+{ Display the files }
+ while assigned(outfiles) do
+ begin
+ p:=outfiles;
+ write(outfiles^.name);
+ outfiles:=outfiles^.next;
+ dispose(p);
+ if assigned(outfiles) then
+ write(' ');
+ end;
+end.
diff --git a/closures/compiler/utils/ppumove.pp b/closures/compiler/utils/ppumove.pp
new file mode 100644
index 0000000000..3d11400655
--- /dev/null
+++ b/closures/compiler/utils/ppumove.pp
@@ -0,0 +1,651 @@
+{
+ Copyright (c) 1999-2002 by the FPC Development Team
+
+ Add multiple FPC units into a static/shared library
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************}
+{$ifndef TP}
+ {$H+}
+{$endif}
+Program ppumove;
+uses
+
+{$IFDEF MACOS}
+{$DEFINE USE_FAKE_SYSUTILS}
+{$ENDIF MACOS}
+
+{$IFNDEF USE_FAKE_SYSUTILS}
+ sysutils,
+{$ELSE}
+ fksysutl,
+{$ENDIF}
+
+{$ifdef unix}
+ Baseunix,Unix, UnixUtil,
+{$else unix}
+ dos,
+{$endif unix}
+ cutils,ppu,systems,
+ getopts;
+
+const
+ Version = 'Version 2.1.1';
+ Title = 'PPU-Mover';
+ Copyright = 'Copyright (c) 1998-2007 by the Free Pascal Development Team';
+
+ ShortOpts = 'o:e:d:i:qhsvb';
+ BufSize = 4096;
+ PPUExt = 'ppu';
+ ObjExt = 'o';
+ StaticLibExt ='a';
+{$ifdef unix}
+ SharedLibExt ='so';
+ BatchExt ='.sh';
+{$else}
+ SharedLibExt ='dll';
+ BatchExt ='.bat';
+{$endif unix}
+
+ { link options }
+ link_none = $0;
+ link_always = $1;
+ link_static = $2;
+ link_smart = $4;
+ link_shared = $8;
+
+Type
+ PLinkOEnt = ^TLinkOEnt;
+ TLinkOEnt = record
+ Name : string;
+ Next : PLinkOEnt;
+ end;
+
+Var
+ ArBin,LDBin,StripBin,
+ OutputFileForPPU,
+ OutputFile,
+ OutputFileForLink, { the name of the output file needed when linking }
+ InputPath,
+ DestPath,
+ PPLExt,
+ LibExt : string;
+ DoStrip,
+ Batch,
+ Quiet,
+ MakeStatic : boolean;
+ Buffer : Pointer;
+ ObjFiles : PLinkOEnt;
+ BatchFile : Text;
+ Libs : ansistring;
+
+{*****************************************************************************
+ Helpers
+*****************************************************************************}
+
+Procedure Error(const s:string;stop:boolean);
+{
+ Write an error message to stderr
+}
+begin
+ writeln(stderr,s);
+ if stop then
+ halt(1);
+end;
+
+
+function Shell(const s:string):longint;
+{
+ Run a shell commnad and return the exitcode
+}
+begin
+ if Batch then
+ begin
+ Writeln(BatchFile,s);
+ Shell:=0;
+ exit;
+ end;
+{$ifdef unix}
+ Shell:=unix.fpsystem(s);
+{$else}
+ exec(getenv('COMSPEC'),'/C '+s);
+ Shell:=DosExitCode;
+{$endif}
+end;
+
+
+Function FileExists (Const F : String) : Boolean;
+{
+ Returns True if the file exists, False if not.
+}
+Var
+{$ifdef unix}
+ info : Stat;
+{$else}
+ info : searchrec;
+{$endif}
+begin
+{$ifdef unix}
+ FileExists:=FpStat(F,Info)=0;
+{$else}
+ FindFirst (F,anyfile,Info);
+ FileExists:=DosError=0;
+{$endif}
+end;
+
+
+Function ChangeFileExt(Const HStr,ext:String):String;
+{
+ Return a filename which will have extension ext added if no
+ extension is found
+}
+var
+ j : longint;
+begin
+ j:=length(Hstr);
+ while (j>0) and (Hstr[j]<>'.') do
+ dec(j);
+ if j=0 then
+ ChangeFileExt:=Hstr+'.'+Ext
+ else
+ ChangeFileExt:=HStr;
+end;
+
+
+Function ForceExtension(Const HStr,ext:String):String;
+{
+ Return a filename which certainly has the extension ext
+}
+var
+ j : longint;
+begin
+ j:=length(Hstr);
+ while (j>0) and (Hstr[j]<>'.') do
+ dec(j);
+ if j=0 then
+ j:=255;
+ ForceExtension:=Copy(Hstr,1,j-1)+'.'+Ext;
+end;
+
+
+Procedure AddToLinkFiles(const S : String);
+{
+ Adds a filename to a list of object files to link to.
+ No duplicates allowed.
+}
+Var
+ P : PLinKOEnt;
+begin
+ P:=ObjFiles;
+ { Don't add files twice }
+ While (P<>nil) and (p^.name<>s) do
+ p:=p^.next;
+ if p=nil then
+ begin
+ new(p);
+ p^.next:=ObjFiles;
+ p^.name:=s;
+ ObjFiles:=P;
+ end;
+end;
+
+
+Function ExtractLib(const libfn:string):string;
+{
+ Extract a static library libfn and return the files with a
+ wildcard
+}
+var
+ n : namestr;
+ d : dirstr;
+ e : extstr;
+begin
+{ create the temp dir first }
+ fsplit(libfn,d,n,e);
+ {$push}{$I-}
+ mkdir(n+'.sl');
+ {$pop}
+ if ioresult<>0 then;
+{ Extract }
+ if Shell(arbin+' x '+libfn)<>0 then
+ Error('Fatal: Error running '+arbin,true);
+{ Remove the lib file, it's extracted so it can be created with ease }
+ if PPLExt=PPUExt then
+ Shell('rm '+libfn);
+{$ifdef unix}
+ ExtractLib:=n+'.sl/*';
+{$else}
+ ExtractLib:=n+'.sl\*';
+{$endif}
+end;
+
+
+Function DoPPU(const PPUFn,PPLFn:String):Boolean;
+{
+ Convert one file (in Filename) to library format.
+ Return true if successful, false otherwise.
+}
+Var
+ inppu,
+ outppu : tppufile;
+ b,
+ untilb : byte;
+ l,m : longint;
+ f : file;
+ ext,
+ s : string;
+ ppuversion : dword;
+begin
+ DoPPU:=false;
+ If Not Quiet then
+ Write ('Processing ',PPUFn,'...');
+ inppu:=tppufile.create(PPUFn);
+ if not inppu.openfile then
+ begin
+ inppu.free;
+ Error('Error: Could not open : '+PPUFn,false);
+ Exit;
+ end;
+{ Check the ppufile }
+ if not inppu.CheckPPUId then
+ begin
+ inppu.free;
+ Error('Error: Not a PPU File : '+PPUFn,false);
+ Exit;
+ end;
+ ppuversion:=inppu.GetPPUVersion;
+ if ppuversion<CurrentPPUVersion then
+ begin
+ inppu.free;
+ Error('Error: Wrong PPU Version '+tostr(ppuversion)+' in '+PPUFn,false);
+ Exit;
+ end;
+{ No .o file generated for this ppu, just skip }
+ if (inppu.header.flags and uf_no_link)<>0 then
+ begin
+ inppu.free;
+ If Not Quiet then
+ Writeln (' No files.');
+ DoPPU:=true;
+ Exit;
+ end;
+{ Already a lib? }
+ if (inppu.header.flags and uf_in_library)<>0 then
+ begin
+ inppu.free;
+ Error('Error: PPU is already in a library : '+PPUFn,false);
+ Exit;
+ end;
+{ We need a static linked unit }
+ if (inppu.header.flags and uf_static_linked)=0 then
+ begin
+ inppu.free;
+ Error('Error: PPU is not static linked : '+PPUFn,false);
+ Exit;
+ end;
+{ Check if shared is allowed }
+ if tsystem(inppu.header.target) in [system_i386_go32v2] then
+ begin
+ Writeln('Warning: shared library not supported for ppu target, switching to static library');
+ MakeStatic:=true;
+ end;
+{ Create the new ppu }
+ if PPUFn=PPLFn then
+ outppu:=tppufile.create('ppumove.$$$')
+ else
+ outppu:=tppufile.create(PPLFn);
+ outppu.createfile;
+{ Create new header, with the new flags }
+ outppu.header:=inppu.header;
+ outppu.header.flags:=outppu.header.flags or uf_in_library;
+ if MakeStatic then
+ outppu.header.flags:=outppu.header.flags or uf_static_linked
+ else
+ outppu.header.flags:=outppu.header.flags or uf_shared_linked;
+{ read until the object files are found }
+ untilb:=iblinkunitofiles;
+ repeat
+ b:=inppu.readentry;
+ if b in [ibendinterface,ibend] then
+ begin
+ inppu.free;
+ outppu.free;
+ Error('Error: No files to be linked found : '+PPUFn,false);
+ Exit;
+ end;
+ if b<>untilb then
+ begin
+ repeat
+ inppu.getdatabuf(buffer^,bufsize,l);
+ outppu.putdata(buffer^,l);
+ until l<bufsize;
+ outppu.writeentry(b);
+ end;
+ until (b=untilb);
+{ we have now reached the section for the files which need to be added,
+ now add them to the list }
+ case b of
+ iblinkunitofiles :
+ begin
+ { add all o files, and save the entry when not creating a static
+ library to keep staticlinking possible }
+ while not inppu.endofentry do
+ begin
+ s:=inppu.getstring;
+ m:=inppu.getlongint;
+ if not MakeStatic then
+ begin
+ outppu.putstring(s);
+ outppu.putlongint(m);
+ end;
+ AddToLinkFiles(s);
+ end;
+ if not MakeStatic then
+ outppu.writeentry(b);
+ end;
+{ iblinkunitstaticlibs :
+ begin
+ AddToLinkFiles(ExtractLib(inppu.getstring));
+ if not inppu.endofentry then
+ begin
+ repeat
+ inppu.getdatabuf(buffer^,bufsize,l);
+ outppu.putdata(buffer^,l);
+ until l<bufsize;
+ outppu.writeentry(b);
+ end;
+ end; }
+ end;
+{ just add a new entry with the new lib }
+ if MakeStatic then
+ begin
+ outppu.putstring(OutputfileForPPU);
+ outppu.putlongint(link_static);
+ outppu.writeentry(iblinkunitstaticlibs)
+ end
+ else
+ begin
+ outppu.putstring(OutputfileForPPU);
+ outppu.putlongint(link_shared);
+ outppu.writeentry(iblinkunitsharedlibs);
+ end;
+{ read all entries until the end and write them also to the new ppu }
+ repeat
+ b:=inppu.readentry;
+ { don't write ibend, that's written automatically }
+ if b<>ibend then
+ begin
+ if b=iblinkothersharedlibs then
+ begin
+ while not inppu.endofentry do
+ begin
+ s:=inppu.getstring;
+ m:=inppu.getlongint;
+
+ outppu.putstring(s);
+
+ { strip lib prefix }
+ if copy(s,1,3)='lib' then
+ delete(s,1,3);
+
+ { strip lib prefix }
+ if copy(s,1,3)='lib' then
+ delete(s,1,3);
+ ext:=ExtractFileExt(s);
+ if ext<>'' then
+ delete(s,length(s)-length(ext)+1,length(ext));
+
+ libs:=libs+' -l'+s;
+
+ outppu.putlongint(m);
+ end;
+ end
+ else
+ repeat
+ inppu.getdatabuf(buffer^,bufsize,l);
+ outppu.putdata(buffer^,l);
+ until l<bufsize;
+ outppu.writeentry(b);
+ end;
+ until b=ibend;
+{ write the last stuff and close }
+ outppu.flush;
+ outppu.writeheader;
+ outppu.free;
+ inppu.free;
+{ rename }
+ if PPUFn=PPLFn then
+ begin
+ {$push}{$I-}
+ assign(f,PPUFn);
+ erase(f);
+ assign(f,'ppumove.$$$');
+ rename(f,PPUFn);
+ {$pop}
+ if ioresult<>0 then;
+ end;
+{ the end }
+ If Not Quiet then
+ Writeln (' Done.');
+ DoPPU:=True;
+end;
+
+
+Function DoFile(const FileName:String):Boolean;
+{
+ Process a file, mainly here for wildcard support under Dos
+}
+{$ifndef unix}
+var
+ dir : searchrec;
+{$endif}
+begin
+{$ifdef unix}
+ DoFile:=DoPPU(InputPath+FileName,InputPath+ForceExtension(FileName,PPLExt));
+{$else}
+ DoFile:=false;
+ findfirst(filename,$20,dir);
+ while doserror=0 do
+ begin
+ if not DoPPU(InputPath+Dir.Name,InputPath+ForceExtension(Dir.Name,PPLExt)) then
+ exit;
+ findnext(dir);
+ end;
+ findclose(dir);
+ DoFile:=true;
+{$endif}
+end;
+
+
+Procedure DoLink;
+{
+ Link the object files together to form a (shared) library
+}
+Var
+ Names : ansistring;
+ f : file;
+ Err : boolean;
+ P : PLinkOEnt;
+begin
+ if not Quiet then
+ Write ('Linking ');
+ P:=ObjFiles;
+ names:='';
+ While p<>nil do
+ begin
+ if Names<>'' then
+ Names:=Names+' '+InputPath+P^.name
+ else
+ Names:=InputPath+p^.Name;
+ p:=p^.next;
+ end;
+ if Names='' then
+ begin
+ If not Quiet then
+ Writeln('Error: no files found to be linked');
+ exit;
+ end;
+ If not Quiet then
+ WriteLn(names+Libs);
+{ Run ar or ld to create the lib }
+ If MakeStatic then
+ Err:=Shell(arbin+' rs '+outputfile+' '+names)<>0
+ else
+ begin
+ Err:=Shell(ldbin+' -shared -E -o '+OutputFile+' '+names+' '+libs)<>0;
+ if (not Err) and dostrip then
+ Shell(stripbin+' --strip-unneeded '+OutputFile);
+ end;
+ If Err then
+ Error('Fatal: Library building stage failed.',true);
+{ fix permission to 644, so it's not 755 }
+{$ifdef unix}
+ FPChmod(OutputFile,420);
+{$endif}
+{ Rename to the destpath }
+ if DestPath<>'' then
+ begin
+ Assign(F, OutputFile);
+ Rename(F,DestPath+DirectorySeparator+OutputFile);
+ end;
+end;
+
+
+Procedure usage;
+{
+ Print usage and exit.
+}
+begin
+ Writeln(paramstr(0),': [-qhvbsS] [-e ext] [-o name] [-d path] file [file ...]');
+ Halt(0);
+end;
+
+
+
+Procedure processopts;
+{
+ Process command line opions, and checks if command line options OK.
+}
+var
+ C : char;
+begin
+ if paramcount=0 then
+ usage;
+{ Reset }
+ ObjFiles:=Nil;
+ Quiet:=False;
+ Batch:=False;
+ DoStrip:=False;
+ OutputFile:='';
+ PPLExt:='ppu';
+ ArBin:='ar';
+ LdBin:='ld';
+ StripBin:='strip';
+ repeat
+ c:=Getopt (ShortOpts);
+ Case C of
+ EndOfOptions : break;
+ 'S' : MakeStatic:=True;
+ 'o' : OutputFile:=OptArg;
+ 'd' : DestPath:=OptArg;
+ 'i' : begin
+ InputPath:=OptArg;
+ if InputPath[length(InputPath)]<>DirectorySeparator then
+ InputPath:=InputPath+DirectorySeparator;
+ end;
+ 'e' : PPLext:=OptArg;
+ 'q' : Quiet:=True;
+ 'b' : Batch:=true;
+ 's' : DoStrip:=true;
+ '?' : Usage;
+ 'h' : Usage;
+ end;
+ until false;
+{ Test filenames on the commandline }
+ if (OptInd>Paramcount) then
+ Error('Error: no input files',true);
+ if (OptInd<ParamCount) and (OutputFile='') then
+ Error('Error: when moving multiple units, specify an output name.',true);
+{ alloc a buffer }
+ GetMem (Buffer,Bufsize);
+ If Buffer=Nil then
+ Error('Error: could not allocate memory for buffer.',true);
+end;
+
+
+var
+ i : longint;
+begin
+ Libs:='';
+ ProcessOpts;
+{ Write Header }
+ if not Quiet then
+ begin
+ Writeln(Title+' '+Version);
+ Writeln(Copyright);
+ Writeln;
+ end;
+{ fix the libext and outputfilename }
+ if Makestatic then
+ LibExt:=StaticLibExt
+ else
+ LibExt:=SharedLibExt;
+ if OutputFile='' then
+ OutputFile:=Paramstr(OptInd);
+ OutputFileForPPU:=OutputFile;
+{ fix filename }
+{$ifdef unix}
+ if Copy(OutputFile,1,3)<>'lib' then
+ OutputFile:='lib'+OutputFile;
+ { For unix skip replacing the extension if a full .so.X.X if specified }
+ i:=pos('.so.',Outputfile);
+ if i<>0 then
+ OutputFileForLink:=Copy(Outputfile,4,i-4)
+ else
+ begin
+ OutputFile:=ForceExtension(OutputFile,LibExt);
+ OutputFileForLink:=Copy(Outputfile,4,length(Outputfile)-length(LibExt)-4);
+ end;
+{$else}
+ OutputFile:=ForceExtension(OutputFile,LibExt);
+ OutputFileForLink:=OutputFile;
+{$endif}
+{ Open BatchFile }
+ if Batch then
+ begin
+ Assign(BatchFile,'pmove'+BatchExt);
+ Rewrite(BatchFile);
+ end;
+{ Process Files }
+ i:=OptInd;
+ While (i<=ParamCount) and Dofile(ChangeFileExt(Paramstr(i),PPUExt)) do
+ Inc(i);
+{ Do Linking stage }
+ DoLink;
+{ Close BatchFile }
+ if Batch then
+ begin
+ if Not Quiet then
+ Writeln('Writing pmove'+BatchExt);
+ Close(BatchFile);
+{$ifdef unix}
+ FPChmod('pmove'+BatchExt,493);
+{$endif}
+ end;
+{ The End }
+ if Not Quiet then
+ Writeln('Done.');
+end.
diff --git a/closures/compiler/utils/samplecfg b/closures/compiler/utils/samplecfg
new file mode 100644
index 0000000000..93dc2c04e0
--- /dev/null
+++ b/closures/compiler/utils/samplecfg
@@ -0,0 +1,101 @@
+#!/bin/sh
+#
+# $Id: samplecfg,v 1.13 2005/02/19 18:50:20 florian Exp $
+#
+# Generate Sample Free Pascal configuration file
+#
+
+HOSTOS=`uname -s | tr A-Z a-z`
+echo Running on $HOSTOS
+
+if [ $# = 0 ]; then
+ echo 'Usage :'
+ echo 'samplecfg fpcdir confdir'
+ echo 'fpcdir = Path where FPC is installed'
+ echo 'confdir = Path to /etc'
+ exit 1
+fi
+if [ "$2" ]; then
+ sysdir="$2"
+ [ -d "$sysdir" ] || mkdir "$sysdir"
+else
+ sysdir=/etc
+fi
+FPCBIN=`dirname "$1"`/../../bin/fpc
+FPBIN=`dirname "$1"`/../../bin/fp
+FPPKGBIN=`dirname "$1"`/../../bin/fppkg
+FPCMKCFGBIN=`dirname "$1"`/../../bin/fpcmkcfg
+# Look for one in the PATH, if no new one was installed.
+if [ ! -f $FPCMKCFGBIN ]; then
+ FPCMKCFGBIN=fpcmkcfg
+fi
+
+sysfpdirbase=`dirname "$1"`/`"$FPCBIN" -iV`
+sysfpdirbase2=$sysfpdirbase/ide
+sysfpdir=$sysfpdirbase2/text
+
+# Detect if we have write permission in sysdir.
+if [ -w "$sysdir" ] ; then
+ echo Write permission in $sysdir.
+ fpccfgfile="$sysdir"/fpc.cfg
+ fppkgfile="$sysdir"/fppkg.cfg
+ defaultfile="$sysdir"/fppkg/default
+ compilerconfigdir="-d CompilerConfigDir=$sysdir/fppkg"
+else
+ echo No write premission in $sysdir.
+ fpccfgfile="$HOME"/.fpc.cfg
+ fppkgfile="$HOME"/.config/fppkg.cfg
+ defaultfile="$HOME"/.fppkg/config/default
+fi
+#
+
+# Don't mess with IDE configuration if fp binary does not exist
+if [ -f "$FPBIN" ] ; then
+
+# Assume local FP IDE configuration unless writing system-wide version possible
+ fpinifile="$HOME"/.fp/fp.ini
+ fpcfgfile="$HOME"/.fp/fp.cfg
+
+# Detect if we have write permission in sysfpdir, or that the directory can be made
+ if ( [ -d "$sysfpdirbase" ] && [ -w "$sysfpdirbase" ] && ! [ -d "$sysfpdirbase2" ] ) ||
+ ( [ -d "$sysfpdirbase2" ] && [ -w "$sysfpdirbase2" ] && ! [ -d "$sysfpdir" ] ) ||
+ ( [ -d "$sysfpdir" ] && [ -w "$sysfpdir" ] ) ; then
+ fpinifile="$sysfpdir"/fp.ini
+ fpcfgfile="$sysfpdir"/fp.cfg
+ fi
+#
+fi
+
+# set right path to FPC with $fpcversion
+FPCPATH=`dirname "$1"`/\$fpcversion
+# set right prefix to FPC
+FPCGLOBALPREFIX=`dirname "$1"`/../../
+
+# Write (.)fpc.cfg
+echo Writing sample configuration file to $fpccfgfile
+${FPCMKCFGBIN} -d "basepath=$FPCPATH" -o $fpccfgfile
+
+if ! [ -f "$FPBIN" ] ; then
+ exit
+fi
+
+# Write fp.cfg
+echo Writing sample configuration file to $fpcfgfile
+${FPCMKCFGBIN} -p -1 -d "basepath=$FPCPATH" -o $fpcfgfile
+
+# Write fp.ini
+echo Writing sample configuration file to $fpinifile
+${FPCMKCFGBIN} -p -2 -o $fpinifile
+
+# Do not write fppkg configuration when fppkg is not available
+if ! [ -f "$FPPKGBIN" ] ; then
+ exit
+fi
+
+# Write fppkg.cfg
+echo Writing sample configuration file to $fppkgfile
+${FPCMKCFGBIN} -p -3 $compilerconfigdir -o $fppkgfile
+
+# Write default
+echo Writing sample configuration file to $defaultfile
+${FPCMKCFGBIN} -p -4 -d "GlobalPrefix=$FPCGLOBALPREFIX" -o $defaultfile
diff --git a/closures/compiler/utils/usubst.pp b/closures/compiler/utils/usubst.pp
new file mode 100644
index 0000000000..cf553ae373
--- /dev/null
+++ b/closures/compiler/utils/usubst.pp
@@ -0,0 +1,109 @@
+{$mode objfpc}
+{$H+}
+{
+ This file is part of Free Pascal build tools
+ Copyright (c) 2005 by Michael Van Canneyt
+
+ Implements string substitutions
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+unit usubst;
+
+interface
+
+uses SysUtils,Classes;
+
+// Add N=V pair to list.
+Procedure AddToList(List : TStrings; Const N,V : String);
+// Split NV to N/V and call AddToList
+Function AddPair(List : TStrings; Const NV : String) : Boolean;
+// Perform substitutions in S, from List.
+Function DoSubStitutions(List : TStrings; Var S : String) : Integer;
+
+implementation
+
+Procedure AddToList(List : TStrings; Const N,V : String);
+
+var
+ I : Integer;
+
+begin
+ I:=List.IndexOfName(N);
+ If (V='') then
+ begin
+ If (I<>-1) then
+ List.Delete(I)
+ end
+ else
+ begin
+ If (I=-1) then
+ List.Add(N+'='+V)
+ else
+ List[I]:=N+'='+V;
+ end;
+end;
+
+Function AddPair(List : TStrings; Const NV : String) : Boolean;
+
+Var
+ P : Integer;
+ N,V : string;
+
+begin
+ P:=Pos('=',NV);
+ Result:=(P<>0);
+ If Result then
+ begin
+ V:=NV;
+ N:=Copy(V,1,P-1);
+ Delete(V,1,P);
+ AddToList(List,N,V);
+ end;
+end;
+
+Function DoSubstitutions(List : TStrings; Var S : String) : Integer;
+
+Var
+ N,T : String;
+ P : Integer;
+
+begin
+ Result:=0;
+ T:=S;
+ S:='';
+ P:=Pos('%',T);
+ While (P>0) do
+ begin
+ S:=S+Copy(T,1,P-1);
+ Delete(T,1,P);
+ If (Length(T)>0) then
+ if (T[1]='%') then
+ begin
+ S:=S+'%';
+ Delete(T,1,1);
+ end
+ else
+ begin
+ P:=Pos('%',T);
+ If (P=0) then
+ S:=S+'%'
+ else
+ begin
+ N:=Copy(T,1,P-1);
+ Delete(T,1,P);
+ S:=S+List.Values[N];
+ end;
+ end;
+ P:=Pos('%',T);
+ end;
+ S:=S+T;
+end;
+
+end.
diff --git a/closures/compiler/verbose.pas b/closures/compiler/verbose.pas
new file mode 100644
index 0000000000..12f013ef60
--- /dev/null
+++ b/closures/compiler/verbose.pas
@@ -0,0 +1,987 @@
+{
+ Copyright (c) 1998-2002 by Peter Vreman
+
+ This unit handles the verbose management
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit verbose;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+{$IFNDEF USE_FAKE_SYSUTILS}
+ sysutils,
+{$ELSE}
+ fksysutl,
+{$ENDIF}
+ cutils,
+ globtype,finput,
+ cmsgs;
+
+{$ifndef EXTERN_MSG}
+ {$i msgtxt.inc}
+{$endif}
+
+{$i msgidx.inc}
+
+ Const
+ { Levels }
+ V_None = $0;
+ V_Fatal = $1;
+ V_Error = $2;
+ V_Normal = $4; { doesn't show a text like Error: }
+ V_Warning = $8;
+ V_Note = $10;
+ V_Hint = $20;
+ V_LineInfoMask = $fff;
+ { From here by default no line info }
+ V_Info = $1000;
+ V_Status = $2000;
+ V_Used = $4000;
+ V_Tried = $8000;
+ V_Conditional = $10000;
+ V_Debug = $20000;
+ V_Executable = $40000;
+ V_LevelMask = $fffffff;
+ V_All = V_LevelMask;
+ V_Default = V_Fatal + V_Error + V_Normal;
+ { Flags }
+ V_LineInfo = $10000000;
+
+ var
+ msg : pmessage;
+ paraprintnodetree : byte;
+
+ type
+ tmsgqueueevent = procedure(const s:TMsgStr;v,w:longint) of object;
+
+ const
+ msgfilename : string = '';
+
+ procedure SetRedirectFile(const fn:string);
+ function SetVerbosity(const s:string):boolean;
+ procedure PrepareReport;
+
+ function CheckVerbosity(v:longint):boolean;
+ function SetMessageVerbosity(v:longint;state:tmsgstate):boolean;
+ procedure RestoreLocalVerbosity(pstate : pmessagestaterecord);
+ procedure FreeLocalVerbosity(var fstate : pmessagestaterecord);
+
+ function ChangeMessageVerbosity(s: string; var i: integer;state:tmsgstate): boolean;
+ procedure ShowStatus;
+ function ErrorCount:longint;
+ procedure SetErrorFlags(const s:string);
+ procedure GenerateError;
+ procedure Internalerror(i:longint);
+ procedure Comment(l:longint;s:ansistring);
+ function MessagePchar(w:longint):pchar;
+ procedure Message(w:longint;onqueue:tmsgqueueevent=nil);
+ procedure Message1(w:longint;const s1:TMsgStr;onqueue:tmsgqueueevent=nil);
+ procedure Message2(w:longint;const s1,s2:TMsgStr;onqueue:tmsgqueueevent=nil);
+ procedure Message3(w:longint;const s1,s2,s3:TMsgStr;onqueue:tmsgqueueevent=nil);
+ procedure Message4(w:longint;const s1,s2,s3,s4:TMsgStr;onqueue:tmsgqueueevent=nil);
+ procedure MessagePos(const pos:tfileposinfo;w:longint;onqueue:tmsgqueueevent=nil);
+ procedure MessagePos1(const pos:tfileposinfo;w:longint;const s1:TMsgStr;onqueue:tmsgqueueevent=nil);
+ procedure MessagePos2(const pos:tfileposinfo;w:longint;const s1,s2:TMsgStr;onqueue:tmsgqueueevent=nil);
+ procedure MessagePos3(const pos:tfileposinfo;w:longint;const s1,s2,s3:TMsgStr;onqueue:tmsgqueueevent=nil);
+ procedure MessagePos4(const pos:tfileposinfo;w:longint;const s1,s2,s3,s4:TMsgStr;onqueue:tmsgqueueevent=nil);
+
+ { message calls with codegenerror support }
+ procedure cgmessage(t : longint);
+ procedure cgmessage1(t : longint;const s : TMsgStr);
+ procedure cgmessage2(t : longint;const s1,s2 : TMsgStr);
+ procedure cgmessage3(t : longint;const s1,s2,s3 : TMsgStr);
+ procedure CGMessagePos(const pos:tfileposinfo;t:longint);
+ procedure CGMessagePos1(const pos:tfileposinfo;t:longint;const s1:TMsgStr);
+ procedure CGMessagePos2(const pos:tfileposinfo;t:longint;const s1,s2:TMsgStr);
+ procedure CGMessagePos3(const pos:tfileposinfo;t:longint;const s1,s2,s3:TMsgStr);
+
+ procedure FlushOutput;
+
+ procedure InitVerbose;
+ procedure DoneVerbose;
+
+
+
+implementation
+
+ uses
+ comphook,fmodule,constexp,globals,cfileutl,switches;
+
+{****************************************************************************
+ Extra Handlers for default compiler
+****************************************************************************}
+
+ procedure DoneRedirectFile;
+ begin
+ if status.use_redir then
+ begin
+ close(status.redirfile);
+ status.use_redir:=false;
+ end;
+ if status.use_bugreport then
+ begin
+ close(status.reportbugfile);
+ status.use_bugreport:=false;
+ end;
+ end;
+
+
+ procedure SetRedirectFile(const fn:string);
+ begin
+ { close old redirection file because FileRedirection is handled in both passes }
+ if status.use_redir then
+ close(status.redirfile);
+
+ assign(status.redirfile,fn);
+ {$push}{$I-}
+ append(status.redirfile);
+ if ioresult <> 0 then
+ begin
+ assign(status.redirfile,fn);
+ rewrite(status.redirfile);
+ end;
+ {$pop}
+ status.use_redir:=(ioresult=0);
+ end;
+
+
+ procedure PrepareReport;
+ var
+ fn : string;
+ begin
+ if status.use_bugreport then
+ exit;
+ fn:='fpcdebug.txt';
+ assign(status.reportbugfile,fn);
+ {$push}{$I-}
+ append(status.reportbugfile);
+ if ioresult <> 0 then
+ rewrite(status.reportbugfile);
+ {$pop}
+ status.use_bugreport:=(ioresult=0);
+ if status.use_bugreport then
+ writeln(status.reportbugfile,'FPC bug report file');
+ end;
+
+ procedure RestoreLocalVerbosity(pstate : pmessagestaterecord);
+ begin
+ msg^.ResetStates;
+ while assigned(pstate) do
+ begin
+ SetMessageVerbosity(pstate^.value,pstate^.state);
+ pstate:=pstate^.next;
+ end;
+ end;
+
+ procedure FreeLocalVerbosity(var fstate : pmessagestaterecord);
+ var pstate : pmessagestaterecord;
+ begin
+ pstate:=unaligned(fstate);
+ while assigned(pstate) do
+ begin
+ unaligned(fstate):=pstate^.next;
+ freemem(pstate);
+ pstate:=unaligned(fstate);
+ end;
+ end;
+
+ function ChangeMessageVerbosity(s: string; var i : integer;state:tmsgstate): boolean;
+ var
+ tok : string;
+ msgnr, code : longint;
+ begin
+ { delete everything up to and including 'm' }
+ delete(s,1,i);
+ { the rest of the string must be message numbers }
+ inc(i,length(s)+1);
+ result:=false;
+ repeat
+ tok:=GetToken(s,',');
+ if (tok='') then
+ break;
+ val(tok, msgnr, code);
+ if (code<>0) then
+ exit;
+ if not msg^.setverbosity(msgnr,state) then
+ exit
+ else
+ recordpendingmessagestate(msgnr, state);
+ until false;
+ result:=true;
+ end;
+
+ function SetMessageVerbosity(v:longint;state:tmsgstate):boolean;
+ begin
+ result:=msg^.setverbosity(v,state);
+ end;
+
+ function CheckVerbosity(v:longint):boolean;
+ begin
+ result:=do_checkverbosity(v);
+ end;
+
+
+ function SetVerbosity(const s:string):boolean;
+ const
+ message_verbosity:array[boolean] of tmsgstate=(ms_off_global,ms_on_global);
+ var
+ m : Longint;
+ i : Integer;
+ inverse : boolean;
+ c : char;
+ begin
+ Setverbosity:=false;
+ val(s,m,i);
+ if (i=0) and (s<>'') then
+ status.verbosity:=m
+ else
+ begin
+ i:=1;
+ while i<=length(s) do
+ begin
+ c:=upcase(s[i]);
+ inverse:=false;
+ { on/off ? }
+ if (i<length(s)) then
+ case s[i+1] of
+ '-' : begin
+ inc(i);
+ inverse:=true;
+ end;
+ '+' : inc(i);
+ end;
+ { handle switch }
+ case c of
+ { Special cases }
+ '0' : status.verbosity:=V_Default;
+ 'A' : status.verbosity:=V_All;
+ 'B' : begin
+ if inverse then
+ status.print_source_path:=false
+ else
+ status.print_source_path:=true;
+ end;
+ 'M' : if not ChangeMessageVerbosity(s,i,message_verbosity[inverse]) then
+ begin
+ result:=false;
+ exit
+ end;
+ 'P' : begin
+ if inverse then
+ paraprintnodetree:=0
+ else
+ paraprintnodetree:=1;
+ end;
+ 'Q' : begin
+ if inverse then
+ status.showmsgnrs:=false
+ else
+ status.showmsgnrs:=true;
+ end;
+ 'R' : begin
+ if inverse then
+ begin
+ status.use_gccoutput:=false;
+ status.use_stderr:=false;
+ end
+ else
+ begin
+ status.use_gccoutput:=true;
+ status.use_stderr:=true;
+ end;
+ end;
+ 'V' : PrepareReport;
+ 'Z' : begin
+ if inverse then
+ status.use_stderr:=false
+ else
+ status.use_stderr:=true;
+ end;
+ { Normal cases - do an or }
+ 'C' : if inverse then
+ status.verbosity:=status.verbosity and (not V_Conditional)
+ else
+ status.verbosity:=status.verbosity or V_Conditional;
+ 'D' : if inverse then
+ status.verbosity:=status.verbosity and (not V_Debug)
+ else
+ status.verbosity:=status.verbosity or V_Debug;
+ 'E' : if inverse then
+ status.verbosity:=status.verbosity and (not V_Error)
+ else
+ status.verbosity:=status.verbosity or V_Error;
+ 'H' : if inverse then
+ status.verbosity:=status.verbosity and (not V_Hint)
+ else
+ status.verbosity:=status.verbosity or V_Hint;
+ 'I' : if inverse then
+ status.verbosity:=status.verbosity and (not V_Info)
+ else
+ status.verbosity:=status.verbosity or V_Info;
+ 'L' : if inverse then
+ status.verbosity:=status.verbosity and (not V_Status)
+ else
+ status.verbosity:=status.verbosity or V_Status;
+ 'N' : if inverse then
+ status.verbosity:=status.verbosity and (not V_Note)
+ else
+ status.verbosity:=status.verbosity or V_Note;
+ 'S' : if inverse then
+ status.verbosity:=status.verbosity and (not V_TimeStamps)
+ else
+ status.verbosity:=status.verbosity or V_TimeStamps;
+ 'T' : if inverse then
+ status.verbosity:=status.verbosity and (not V_Tried)
+ else
+ status.verbosity:=status.verbosity or V_Tried;
+ 'U' : if inverse then
+ status.verbosity:=status.verbosity and (not V_Used)
+ else
+ status.verbosity:=status.verbosity or V_Used;
+ 'W' : if inverse then
+ status.verbosity:=status.verbosity and (not V_Warning)
+ else
+ status.verbosity:=status.verbosity or V_Warning;
+ 'X' : if inverse then
+ status.verbosity:=status.verbosity and (not V_Executable)
+ else
+ status.verbosity:=status.verbosity or V_Executable;
+ end;
+ inc(i);
+ end;
+ end;
+ if status.verbosity=0 then
+ status.verbosity:=V_Default;
+ setverbosity:=true;
+ end;
+
+
+ procedure Loadprefixes;
+
+ function loadprefix(w:longint):string;
+ var
+ s : string;
+ idx : longint;
+ begin
+ s:=msg^.get(w,[]);
+ idx:=pos('_',s);
+ if idx>0 then
+ Loadprefix:=Copy(s,idx+1,255)
+ else
+ Loadprefix:=s;
+ end;
+
+ begin
+ { Load the prefixes }
+ fatalstr:=Loadprefix(general_i_fatal);
+ errorstr:=Loadprefix(general_i_error);
+ warningstr:=Loadprefix(general_i_warning);
+ notestr:=Loadprefix(general_i_note);
+ hintstr:=Loadprefix(general_i_hint);
+ end;
+
+
+ procedure LoadMsgFile(const fn:string);
+ begin
+ { reload the internal messages if not already loaded }
+{$ifndef EXTERN_MSG}
+ if not msg^.msgintern then
+ msg^.LoadIntern(@msgtxt,msgtxtsize);
+{$endif}
+ if not msg^.LoadExtern(fn) then
+ begin
+{$ifdef EXTERN_MSG}
+ writeln('Fatal: Cannot find error message file.');
+ halt(3);
+{$else}
+ msg^.LoadIntern(@msgtxt,msgtxtsize);
+{$endif}
+ end;
+ { reload the prefixes using the new messages }
+ Loadprefixes;
+ end;
+
+
+ procedure MaybeLoadMessageFile;
+ begin
+ { Load new message file }
+ if (msgfilename<>'') then
+ begin
+ LoadMsgFile(msgfilename);
+ msgfilename:='';
+ end;
+ end;
+
+
+ var
+ lastfileidx,
+ lastmoduleidx : longint;
+
+
+ Procedure UpdateStatus;
+ var
+ module : tmodulebase;
+ begin
+ { fix status }
+ status.currentline:=current_filepos.line;
+ status.currentcolumn:=current_filepos.column;
+ if (current_filepos.moduleindex <> lastmoduleidx) or
+ (current_filepos.fileindex <> lastfileidx) then
+ begin
+ module:=get_module(current_filepos.moduleindex);
+ if assigned(module) and assigned(module.sourcefiles) then
+ begin
+ { update status record }
+ status.currentmodule:=module.modulename^;
+ status.currentmodulestate:=ModuleStateStr[module.state];
+ status.currentsource:=module.sourcefiles.get_file_name(current_filepos.fileindex);
+ status.currentsourcepath:=module.sourcefiles.get_file_path(current_filepos.fileindex);
+ { if currentsourcepath is relative, make it absolute }
+ if not path_absolute(status.currentsourcepath) then
+ status.currentsourcepath:=GetCurrentDir+status.currentsourcepath;
+
+ { update lastfileidx only if name known PM }
+ if status.currentsource<>'' then
+ lastfileidx:=current_filepos.fileindex
+ else
+ lastfileidx:=0;
+
+ lastmoduleidx:=module.unit_index;
+ end;
+ end;
+ end;
+
+
+ procedure ShowStatus;
+ begin
+ UpdateStatus;
+ if do_status() then
+ raise ECompilerAbort.Create;
+ end;
+
+
+ function ErrorCount:longint;
+ begin
+ ErrorCount:=status.errorcount;
+ end;
+
+
+ procedure SetErrorFlags(const s:string);
+ var
+ code : integer;
+ i,j,l : longint;
+ begin
+ { empty string means error count = 1 for backward compatibility (PFV) }
+ if s='' then
+ begin
+ status.maxerrorcount:=1;
+ exit;
+ end;
+ i:=0;
+ while (i<length(s)) do
+ begin
+ inc(i);
+ case s[i] of
+ '0'..'9' :
+ begin
+ j:=i;
+ while (j<=length(s)) and (s[j] in ['0'..'9']) do
+ inc(j);
+ val(copy(s,i,j-i),l,code);
+ if code<>0 then
+ l:=1;
+ status.maxerrorcount:=l;
+ i:=j-1;
+ end;
+ 'w','W' :
+ status.errorwarning:=true;
+ 'n','N' :
+ status.errornote:=true;
+ 'h','H' :
+ status.errorhint:=true;
+ end;
+ end;
+ end;
+
+
+ procedure GenerateError;
+ begin
+ inc(status.errorcount);
+ end;
+
+
+ procedure internalerror(i : longint);
+ begin
+ UpdateStatus;
+ do_internalerror(i);
+ inc(status.errorcount);
+ raise ECompilerAbort.Create;
+ end;
+
+
+ procedure Comment(l:longint;s:ansistring);
+ var
+ dostop : boolean;
+ begin
+ dostop:=((l and V_Fatal)<>0);
+ if ((l and V_Error)<>0) or
+ ((l and V_Fatal)<>0) or
+ (status.errorwarning and ((l and V_Warning)<>0)) or
+ (status.errornote and ((l and V_Note)<>0)) or
+ (status.errorhint and ((l and V_Hint)<>0)) then
+ inc(status.errorcount)
+ else
+ if l and V_Warning <> 0 then
+ inc(status.countWarnings)
+ else
+ if l and V_Note <> 0 then
+ inc(status.countNotes)
+ else
+ if l and V_Hint <> 0 then
+ inc(status.countHints);
+ { check verbosity level }
+ if not CheckVerbosity(l) then
+ exit;
+ if (l and V_LineInfoMask)<>0 then
+ l:=l or V_LineInfo;
+ { Create status info }
+ UpdateStatus;
+ { Fix replacements }
+ DefaultReplacements(s);
+ { show comment }
+ if do_comment(l,s) or dostop then
+ raise ECompilerAbort.Create;
+ if (status.errorcount>=status.maxerrorcount) and not status.skip_error then
+ begin
+ Message1(unit_f_errors_in_unit,tostr(status.errorcount));
+ status.skip_error:=true;
+ raise ECompilerAbort.Create;
+ end;
+ end;
+
+ function GetMessageState(m:longint):tmsgstate;
+ var
+ i: integer;
+ begin
+ i:=m div 1000;
+ { get the default state }
+ Result:=msg^.msgstates[i]^[m mod 1000];
+
+ { and search at the current unit settings }
+ { todo }
+ end;
+
+ Procedure Msg2Comment(s:ansistring;w:longint;onqueue:tmsgqueueevent);
+ var
+ idx,i,v : longint;
+ dostop : boolean;
+ doqueue : boolean;
+ st : tmsgstate;
+ ch : char;
+ begin
+ {Reset}
+ dostop:=false;
+ doqueue:=false;
+ v:=0;
+ {Parse options}
+ idx:=pos('_',s);
+ if idx=0 then
+ v:=V_None
+ else
+ if (idx >= 1) And (idx <= 5) then
+ begin
+ for i:=1 to idx do
+ begin
+ ch:=upcase(s[i]);
+ case ch of
+ 'F' :
+ begin
+ v:=v or V_Fatal;
+ inc(status.errorcount);
+ dostop:=true;
+ end;
+ 'E','W','N','H':
+ begin
+ if ch='E' then
+ st:=ms_error
+ else
+ st:=GetMessageState(w);
+ { We only want to know about local value }
+ st:= tmsgstate(ord(st) and ms_local_mask);
+ if st=ms_error then
+ begin
+ v:=v or V_Error;
+ inc(status.errorcount);
+ end
+ else if st<>ms_off then
+ case ch of
+ 'W':
+ begin
+ v:=v or V_Warning;
+ if CheckVerbosity(V_Warning) then
+ if status.errorwarning then
+ inc(status.errorcount)
+ else
+ inc(status.countWarnings);
+ end;
+ 'N' :
+ begin
+ v:=v or V_Note;
+ if CheckVerbosity(V_Note) then
+ if status.errornote then
+ inc(status.errorcount)
+ else
+ inc(status.countNotes);
+ end;
+ 'H' :
+ begin
+ v:=v or V_Hint;
+ if CheckVerbosity(V_Hint) then
+ if status.errorhint then
+ inc(status.errorcount)
+ else
+ inc(status.countHints);
+ end;
+ end;
+ end;
+ 'O' :
+ v:=v or V_Normal;
+ 'I' :
+ v:=v or V_Info;
+ 'L' :
+ v:=v or V_LineInfo;
+ 'U' :
+ v:=v or V_Used;
+ 'T' :
+ v:=v or V_Tried;
+ 'C' :
+ v:=v or V_Conditional;
+ 'D' :
+ v:=v or V_Debug;
+ 'X' :
+ v:=v or V_Executable;
+ 'S' :
+ dostop:=true;
+ '_' : ;
+ end;
+ end;
+ end;
+ Delete(s,1,idx);
+ { check verbosity level }
+ if not CheckVerbosity(v) then
+ begin
+ doqueue := onqueue <> nil;
+ if not doqueue then
+ exit;
+ end;
+ if (v and V_LineInfoMask)<>0 then
+ v:=v or V_LineInfo;
+ { fix status }
+ UpdateStatus;
+ { Fix replacements }
+ DefaultReplacements(s);
+ if status.showmsgnrs then
+ s:='('+tostr(w)+') '+s;
+ if doqueue then
+ begin
+ onqueue(s,v,w);
+ exit;
+ end;
+ { show comment }
+ if do_comment(v,s) or dostop then
+ raise ECompilerAbort.Create;
+ if (status.errorcount>=status.maxerrorcount) and not status.skip_error then
+ begin
+ Message1(unit_f_errors_in_unit,tostr(status.errorcount));
+ status.skip_error:=true;
+ raise ECompilerAbort.Create;
+ end;
+ end;
+
+
+ function MessagePchar(w:longint):pchar;
+ begin
+ MaybeLoadMessageFile;
+ MessagePchar:=msg^.GetPchar(w)
+ end;
+
+
+ procedure Message(w:longint;onqueue:tmsgqueueevent=nil);
+ begin
+ MaybeLoadMessageFile;
+ Msg2Comment(msg^.Get(w,[]),w,onqueue);
+ end;
+
+
+ procedure Message1(w:longint;const s1:TMsgStr;onqueue:tmsgqueueevent=nil);
+
+ begin
+ MaybeLoadMessageFile;
+ Msg2Comment(msg^.Get(w,[s1]),w,onqueue);
+ end;
+
+
+ procedure Message2(w:longint;const s1,s2:TMsgStr;onqueue:tmsgqueueevent=nil);
+ begin
+ MaybeLoadMessageFile;
+ Msg2Comment(msg^.Get(w,[s1,s2]),w,onqueue);
+ end;
+
+
+ procedure Message3(w:longint;const s1,s2,s3:TMsgStr;onqueue:tmsgqueueevent=nil);
+ begin
+ MaybeLoadMessageFile;
+ Msg2Comment(msg^.Get(w,[s1,s2,s3]),w,onqueue);
+ end;
+
+
+ procedure Message4(w:longint;const s1,s2,s3,s4:TMsgStr;onqueue:tmsgqueueevent=nil);
+ begin
+ MaybeLoadMessageFile;
+ Msg2Comment(msg^.Get(w,[s1,s2,s3,s4]),w,onqueue);
+ end;
+
+
+ procedure MessagePos(const pos:tfileposinfo;w:longint;onqueue:tmsgqueueevent=nil);
+ var
+ oldpos : tfileposinfo;
+ begin
+ oldpos:=current_filepos;
+ current_filepos:=pos;
+ MaybeLoadMessageFile;
+ Msg2Comment(msg^.Get(w,[]),w,onqueue);
+ current_filepos:=oldpos;
+ end;
+
+
+ procedure MessagePos1(const pos:tfileposinfo;w:longint;const s1:TMsgStr;onqueue:tmsgqueueevent=nil);
+ var
+ oldpos : tfileposinfo;
+ begin
+ oldpos:=current_filepos;
+ current_filepos:=pos;
+ MaybeLoadMessageFile;
+ Msg2Comment(msg^.Get(w,[s1]),w,onqueue);
+ current_filepos:=oldpos;
+ end;
+
+
+ procedure MessagePos2(const pos:tfileposinfo;w:longint;const s1,s2:TMsgStr;onqueue:tmsgqueueevent=nil);
+ var
+ oldpos : tfileposinfo;
+ begin
+ oldpos:=current_filepos;
+ current_filepos:=pos;
+ MaybeLoadMessageFile;
+ Msg2Comment(msg^.Get(w,[s1,s2]),w,onqueue);
+ current_filepos:=oldpos;
+ end;
+
+
+ procedure MessagePos3(const pos:tfileposinfo;w:longint;const s1,s2,s3:TMsgStr;onqueue:tmsgqueueevent=nil);
+ var
+ oldpos : tfileposinfo;
+ begin
+ oldpos:=current_filepos;
+ current_filepos:=pos;
+ MaybeLoadMessageFile;
+ Msg2Comment(msg^.Get(w,[s1,s2,s3]),w,onqueue);
+ current_filepos:=oldpos;
+ end;
+
+
+ procedure MessagePos4(const pos:tfileposinfo;w:longint;const s1,s2,s3,s4:TMsgStr;onqueue:tmsgqueueevent=nil);
+ var
+ oldpos : tfileposinfo;
+ begin
+ oldpos:=current_filepos;
+ current_filepos:=pos;
+ MaybeLoadMessageFile;
+ Msg2Comment(msg^.Get(w,[s1,s2,s3,s4]),w,onqueue);
+ current_filepos:=oldpos;
+ end;
+
+
+{*****************************************************************************
+ override the message calls to set codegenerror
+*****************************************************************************}
+
+ procedure cgmessage(t : longint);
+ var
+ olderrorcount : longint;
+ begin
+ if not(codegenerror) then
+ begin
+ olderrorcount:=Errorcount;
+ verbose.Message(t);
+ codegenerror:=olderrorcount<>Errorcount;
+ end;
+ end;
+
+ procedure cgmessage1(t : longint;const s : TMsgStr);
+ var
+ olderrorcount : longint;
+ begin
+ if not(codegenerror) then
+ begin
+ olderrorcount:=Errorcount;
+ verbose.Message1(t,s);
+ codegenerror:=olderrorcount<>Errorcount;
+ end;
+ end;
+
+ procedure cgmessage2(t : longint;const s1,s2 : TMsgStr);
+ var
+ olderrorcount : longint;
+ begin
+ if not(codegenerror) then
+ begin
+ olderrorcount:=Errorcount;
+ verbose.Message2(t,s1,s2);
+ codegenerror:=olderrorcount<>Errorcount;
+ end;
+ end;
+
+ procedure cgmessage3(t : longint;const s1,s2,s3 : TMsgStr);
+ var
+ olderrorcount : longint;
+ begin
+ if not(codegenerror) then
+ begin
+ olderrorcount:=Errorcount;
+ verbose.Message3(t,s1,s2,s3);
+ codegenerror:=olderrorcount<>Errorcount;
+ end;
+ end;
+
+
+ procedure cgmessagepos(const pos:tfileposinfo;t : longint);
+ var
+ olderrorcount : longint;
+ begin
+ if not(codegenerror) then
+ begin
+ olderrorcount:=Errorcount;
+ verbose.MessagePos(pos,t);
+ codegenerror:=olderrorcount<>Errorcount;
+ end;
+ end;
+
+ procedure cgmessagepos1(const pos:tfileposinfo;t : longint;const s1 : TMsgStr);
+ var
+ olderrorcount : longint;
+ begin
+ if not(codegenerror) then
+ begin
+ olderrorcount:=Errorcount;
+ verbose.MessagePos1(pos,t,s1);
+ codegenerror:=olderrorcount<>Errorcount;
+ end;
+ end;
+
+ procedure cgmessagepos2(const pos:tfileposinfo;t : longint;const s1,s2 : TMsgStr);
+ var
+ olderrorcount : longint;
+ begin
+ if not(codegenerror) then
+ begin
+ olderrorcount:=Errorcount;
+ verbose.MessagePos2(pos,t,s1,s2);
+ codegenerror:=olderrorcount<>Errorcount;
+ end;
+ end;
+
+ procedure cgmessagepos3(const pos:tfileposinfo;t : longint;const s1,s2,s3 : TMsgStr);
+ var
+ olderrorcount : longint;
+ begin
+ if not(codegenerror) then
+ begin
+ olderrorcount:=Errorcount;
+ verbose.MessagePos3(pos,t,s1,s2,s3);
+ codegenerror:=olderrorcount<>Errorcount;
+ end;
+ end;
+
+
+ procedure FlushOutput;
+ begin
+ if not (Status.Use_StdErr) then (* StdErr is flushed after every line *)
+ begin
+ if Status.Use_Redir then
+ Flush(Status.RedirFile)
+ else
+ Flush(Output);
+ end;
+ end;
+
+
+{*****************************************************************************
+ Initialization
+*****************************************************************************}
+
+ procedure InitVerbose;
+ begin
+ { Init }
+ msg:=new(pmessage,Init(20,msgidxmax));
+ if msg=nil then
+ begin
+ writeln('Fatal: MsgIdx Wrong');
+ halt(3);
+ end;
+{$ifndef EXTERN_MSG}
+ msg^.LoadIntern(@msgtxt,msgtxtsize);
+{$else EXTERN_MSG}
+ LoadMsgFile(exepath+'errore.msg');
+{$endif EXTERN_MSG}
+ FillChar(Status,sizeof(TCompilerStatus),0);
+ status.verbosity:=V_Default;
+ Status.MaxErrorCount:=50;
+ Status.codesize:=aword(-1);
+ Status.datasize:=aword(-1);
+ Loadprefixes;
+ lastfileidx:=-1;
+ lastmoduleidx:=-1;
+ status.currentmodule:='';
+ status.currentsource:='';
+ status.currentsourcepath:='';
+ { Register internalerrorproc for cutils/cclasses }
+ internalerrorproc:=@internalerror;
+ end;
+
+
+ procedure DoneVerbose;
+ begin
+ if assigned(msg) then
+ begin
+ dispose(msg,Done);
+ msg:=nil;
+ end;
+ DoneRedirectFile;
+ end;
+
+
+initialization
+ constexp.internalerror:=@internalerror;
+finalization
+ { Be sure to close the redirect files to flush all data }
+ DoneRedirectFile;
+end.
diff --git a/closures/compiler/version.pas b/closures/compiler/version.pas
new file mode 100644
index 0000000000..e4f7442967
--- /dev/null
+++ b/closures/compiler/version.pas
@@ -0,0 +1,96 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Version/target constants
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit version;
+
+{$i fpcdefs.inc}
+
+interface
+
+ const
+ { version string }
+ version_nr = '2';
+ release_nr = '7';
+ patch_nr = '1';
+ minorpatch = '';
+
+ { word version for ppu file }
+ wordversion = ((ord(version_nr)-ord('0')) shl 14)+
+ ((ord(release_nr)-ord('0')) shl 7)+
+ (ord(patch_nr)-ord('0'));
+
+ { date string }
+ date_string = {$I %DATE%};
+
+ { source cpu string }
+{$ifdef cpu86}
+ source_cpu_string = 'i386';
+{$endif cpu86}
+{$ifdef cpupowerpc32}
+ source_cpu_string = 'powerpc';
+{$endif cpupowerpc32}
+{$ifdef cpupowerpc64}
+ source_cpu_string = 'powerpc64';
+{$endif cpupowerpc64}
+{$ifdef cpum68k}
+ source_cpu_string = 'm68k';
+{$endif cpum68k}
+{$ifdef cpuia64}
+ source_cpu_string = 'ia64';
+{$endif cpuia64}
+{$ifdef cpux86_64}
+ source_cpu_string = 'x86_64';
+{$endif cpux86_64}
+{$ifdef cpusparc}
+ source_cpu_string = 'sparc';
+{$endif cpusparc}
+{$ifdef cpusalpha}
+ source_cpu_string = 'alpha';
+{$endif cpualpha}
+{$ifdef cpuvis}
+ source_cpu_string = 'vis';
+{$endif cpuvis}
+{$ifdef cpuarm}
+ source_cpu_string = 'arm';
+{$endif cpuarm}
+
+function version_string:string;
+function full_version_string:string;
+
+
+implementation
+
+function version_string:string;
+begin
+ version_string := version_nr+'.'+release_nr+'.'+patch_nr;
+end;
+
+
+function full_version_string:string;
+begin
+ full_version_string := version_nr+'.'+release_nr+'.'+patch_nr+minorpatch
+{$ifdef REVINC}
+ +'-r'+{$i revision.inc}
+{$endif REVINC}
+ ;
+end;
+
+end.
diff --git a/closures/compiler/vis/aasmcpu.pas b/closures/compiler/vis/aasmcpu.pas
new file mode 100644
index 0000000000..18cfae02d6
--- /dev/null
+++ b/closures/compiler/vis/aasmcpu.pas
@@ -0,0 +1,248 @@
+{
+ Copyright (c) 1998-2001 by Florian Klaempfl and Pierre Muller
+
+ virtual instruction set family assembler instructions
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit aasmcpu;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ cclasses,aasmtai,aasmdata,
+ aasmbase,globals,verbose,
+ cpubase,cpuinfo;
+
+
+type
+
+ taicpu = class(taicpu_abstract)
+ opsize : topsize;
+ constructor op_none(op : tasmop;_size : topsize);
+
+ constructor op_reg(op : tasmop;_size : topsize;_op1 : tregister);
+ constructor op_const(op : tasmop;_size : topsize;_op1 : longint);
+ constructor op_ref(op : tasmop;_size : topsize;_op1 : treference);
+
+ constructor op_reg_reg(op : tasmop;_size : topsize;_op1,_op2 : tregister);
+ constructor op_reg_ref(op : tasmop;_size : topsize;_op1 : tregister;_op2 : treference);
+ constructor op_ref_reg(op : tasmop;_size : topsize;_op1 : treference;_op2 : tregister);
+
+ constructor op_const_reg(op : tasmop;_size : topsize;_op1 : longint;_op2 : tregister);
+ constructor op_const_ref(op : tasmop;_size : topsize;_op1 : longint;_op2 : treference);
+
+
+ { this is for Jmp instructions }
+ constructor op_cond_sym(op : tasmop;cond:TAsmCond;_size : topsize;_op1 : tasmsymbol);
+
+ constructor op_sym(op : tasmop;_size : topsize;_op1 : tasmsymbol);
+ { for DBxx opcodes }
+ constructor op_reg_sym(op: tasmop; _size : topsize; _op1: tregister; _op2 :tasmsymbol);
+ constructor op_sym_ofs_reg(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint;_op2 : tregister);
+
+ constructor op_sym_ofs(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint);
+ constructor op_sym_ofs_ref(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint;const _op2 : treference);
+
+ private
+ procedure init(_size : topsize); { this need to be called by all constructor }
+ end;
+
+
+ tai_align = class(tai_align_abstract)
+ { nothing to add }
+ end;
+
+ procedure InitAsm;
+ procedure DoneAsm;
+
+
+implementation
+
+
+{*****************************************************************************
+ Taicpu Constructors
+*****************************************************************************}
+
+
+
+
+ procedure taicpu.init(_size : topsize);
+ begin
+ typ:=ait_instruction;
+ is_jmp:=false;
+ opsize:=_size;
+ ops:=0;
+ end;
+
+
+ constructor taicpu.op_none(op : tasmop;_size : topsize);
+ begin
+ inherited create(op);;
+ init(_size);
+ end;
+
+
+ constructor taicpu.op_reg(op : tasmop;_size : topsize;_op1 : tregister);
+ begin
+ inherited create(op);;
+ init(_size);
+ ops:=1;
+ loadreg(0,_op1);
+ end;
+
+
+ constructor taicpu.op_const(op : tasmop;_size : topsize;_op1 : longint);
+ begin
+ inherited create(op);;
+ init(_size);
+ ops:=1;
+ loadconst(0,aword(_op1));
+ end;
+
+
+ constructor taicpu.op_ref(op : tasmop;_size : topsize;_op1 : treference);
+ begin
+ inherited create(op);;
+ init(_size);
+ ops:=1;
+ loadref(0,_op1);
+ end;
+
+
+ constructor taicpu.op_reg_reg(op : tasmop;_size : topsize;_op1,_op2 : tregister);
+ begin
+ inherited create(op);;
+ init(_size);
+ ops:=2;
+ loadreg(0,_op1);
+ loadreg(1,_op2);
+ end;
+
+
+
+ constructor taicpu.op_reg_ref(op : tasmop;_size : topsize;_op1 : tregister;_op2 : treference);
+ begin
+ inherited create(op);;
+ init(_size);
+ ops:=2;
+ loadreg(0,_op1);
+ loadref(1,_op2);
+ end;
+
+
+ constructor taicpu.op_const_reg(op : tasmop;_size : topsize;_op1 : longint;_op2 : tregister);
+ begin
+ inherited create(op);;
+ init(_size);
+ ops:=2;
+ loadconst(0,aword(_op1));
+ loadreg(1,_op2);
+ end;
+
+
+
+ constructor taicpu.op_const_ref(op : tasmop;_size : topsize;_op1 : longint;_op2 : treference);
+ begin
+ inherited create(op);;
+ init(_size);
+ ops:=2;
+ loadconst(0,aword(_op1));
+ loadref(1,_op2);
+ end;
+
+
+ constructor taicpu.op_ref_reg(op : tasmop;_size : topsize;_op1 : treference;_op2 : tregister);
+ begin
+ inherited create(op);;
+ init(_size);
+ ops:=2;
+ loadref(0,_op1);
+ loadreg(1,_op2);
+ end;
+
+
+ constructor taicpu.op_sym(op : tasmop;_size : topsize;_op1 : tasmsymbol);
+ begin
+ inherited create(op);;
+ init(_size);
+ ops:=1;
+ loadsymbol(0,_op1,0);
+ end;
+
+
+ constructor taicpu.op_reg_sym(op: tasmop; _size : topsize; _op1: tregister; _op2 :tasmsymbol);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=2;
+ loadreg(0,_op1);
+ loadsymbol(1,_op2,0);
+ end;
+
+
+ constructor taicpu.op_sym_ofs_ref(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint;const _op2 : treference);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=2;
+ loadsymbol(0,_op1,_op1ofs);
+ loadref(1,_op2);
+ end;
+
+
+ constructor taicpu.op_sym_ofs(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=1;
+ loadsymbol(0,_op1,_op1ofs);
+ end;
+
+ constructor taicpu.op_sym_ofs_reg(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint;_op2 : tregister);
+ begin
+ inherited create(op);;
+ init(_size);
+ ops:=2;
+ loadreg(0,_op2);
+ loadsymbol(1,_op1,_op1ofs);
+ end;
+
+
+ constructor taicpu.op_cond_sym(op : tasmop;cond:TAsmCond;_size : topsize;_op1 : tasmsymbol);
+ begin
+ inherited create(op);
+ init(_size);
+ condition:=cond;
+ ops:=1;
+ loadsymbol(0,_op1,0);
+ end;
+
+
+
+ procedure InitAsm;
+ begin
+ end;
+
+
+ procedure DoneAsm;
+ begin
+ end;
+
+end.
diff --git a/closures/compiler/vis/cpubase.pas b/closures/compiler/vis/cpubase.pas
new file mode 100644
index 0000000000..a701cf006a
--- /dev/null
+++ b/closures/compiler/vis/cpubase.pas
@@ -0,0 +1,608 @@
+{
+ Copyright (c) 1998-2002 by the Free Pascal dev. team
+
+ Contains the base types for the virtual instruction set
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+{ This Unit contains the base types for the Virtual Instruction machine
+}
+unit cpubase;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ strings,cutils,cclasses,aasmbase,cpuinfo,cginfo;
+
+
+{*****************************************************************************
+ Assembler Opcodes
+*****************************************************************************}
+
+ type
+ TAsmOp=(a_none,a_beqs,a_bges,a_bgts,a_bles,a_blts,a_bnes,
+ a_bras,a_rets,a_bccs,a_bcss,a_bvcs,a_bvss,a_bbss,
+ a_bass,a_bats,a_bbts,a_beql,a_bgel,a_bgtl,a_blel,
+ a_bltl,a_bnel,a_bral,a_bsrl,a_bbsl,a_basl,a_batl,
+ a_bbtl,a_add,a_addc,a_and,a_asr,a_lsl,a_lsr,a_cmp,
+ a_sub,a_subb,a_divs,a_divu,a_mod,a_move,a_muls,a_mulu,
+ a_neg,a_not,a_or,a_xor,a_fadd,a_fcmp,a_fdiv,a_fmove,
+ a_fmul,a_fneg,a_fsub,a_fldd,a_flds,a_lbzx,a_lbsx,a_llsx,
+ a_llzx,a_lwsx,a_lwzx,a_fstd,a_fsts,a_stb,a_stl,a_stw,
+ a_syscall,a_nop,a_lims,a_orhi,a_lilo,a_call,a_popl,
+ a_pushl,
+ { these are simplified mnemonics }
+ a_lea,a_limm,a_bxx
+ );
+
+ {# This should define the array of instructions as string }
+ op2strtable=array[tasmop] of string[8];
+
+ Const
+ {# First value of opcode enumeration }
+ firstop = low(tasmop);
+ {# Last value of opcode enumeration }
+ lastop = high(tasmop);
+
+{*****************************************************************************
+ Registers
+*****************************************************************************}
+
+ type
+ toldregister = (R_NO,R_R0,R_R1,R_R2,R_R3,
+ R_R4,R_R5,R_R6,R_R7,
+ R_R8,R_R9,R_R10,R_R11,
+ R_CCR,R_SP,R_FP,R_PC,
+ R_FP0,R_FP1,R_FP2,R_FP3,
+ R_FP4,R_FP5,R_FP6,R_FP7,
+ R_FP8,R_FP9,R_FP10,R_FP11,
+ R_FP12,R_FP13,R_FP14,R_FP15,
+ R_INTREGISTER,R_FPUREGISTER
+ );
+
+ {# Set type definition for registers }
+ tregisterset = set of Toldregister;
+ Tnewregister=word;
+
+ tregister=record
+ enum:toldregister;
+ number:Tnewregister;
+ end;
+
+ { A type to store register locations for 64 Bit values. }
+ tregister64 = packed record
+ reglo,reghi : tregister;
+ end;
+
+ Tsuperregister=byte;
+ Tsubregister=byte;
+
+ Tsupregset=set of Tsuperregister;
+
+ { alias for compact code }
+ treg64 = tregister64;
+
+ {# Type definition for the array of string of register nnames }
+ treg2strtable = array[toldregister] of string[5];
+
+ Const
+
+ {Special registers:}
+ NR_NO = $0000; {Invalid register}
+
+ {Normal registers:}
+
+ {General purpose registers:}
+ NR_R0 = $0100; NR_R1 = $0200; NR_R2 = $0300;
+ NR_R3 = $0400; NR_R4 = $0500; NR_R5 = $0600;
+ NR_R6 = $0700; NR_R7 = $0800; NR_R8 = $0900;
+ NR_R9 = $0A00; NR_R10 = $0B00; NR_R11 = $0C00;
+ NR_SP = $0D00; NR_FP = $0E00;
+
+ {Super registers:}
+ RS_R0 = $01; RS_R1 = $02; RS_R2 = $03;
+ RS_R3 = $04; RS_R4 = $05; RS_R5 = $06;
+ RS_R6 = $07; RS_R7 = $08; RS_R8 = $09;
+ RS_R9 = $0A; RS_R10 = $0B; RS_R11 = $0C;
+ RS_SP = $0D; RS_FP = $0E;
+
+ {Subregisters:}
+ R_SUBL = $00;
+ R_SUBW = $01;
+ R_SUBD = $02;
+
+ {# First register in the tregister enumeration }
+ firstreg = low(toldregister);
+ {# Last register in the tregister enumeration }
+ lastreg = high(toldregister);
+
+ first_supreg = $01;
+ last_supreg = $0c;
+
+
+ std_reg2str : treg2strtable = ('',
+ 'r0','r1','r2','r3','r4','r5','r6','r7','r8','r9','r10','r11','ccr',
+ 'sp','fp','pc','fp0','fp1','fp2','fp3','fp4','fp5','fp6','fp7',
+ 'fp8','fp9','fp10','fp11','fp12','fp13','fp14','fp15','',''
+ );
+
+
+{*****************************************************************************
+ Conditions
+*****************************************************************************}
+
+ type
+ TAsmCond=(C_None,
+ C_EQ, { equal }
+ C_NE, { not equal }
+ C_GE, { greater or equal (signed) }
+ C_GT, { greater than (signed) }
+ C_LE, { less or equal (signed) }
+ C_LT, { less than (signed) }
+ C_LS, { lower or same (unordered) }
+ C_AS, { above or same (unordered) }
+ C_AT, { above than (unordered) }
+ C_BT, { below than (unordered) }
+ C_CC, { carry clear }
+ C_CS { carry set }
+ );
+
+
+ const
+ cond2str:array[TAsmCond] of string[3]=('',
+ 'eq','ne','ge','gt','le','lt','ls','as',
+ 'at','bt','cc','cs');
+
+
+{*****************************************************************************
+ Flags
+*****************************************************************************}
+
+ type
+ TResFlags = (
+ F_E, { zero flag = equal }
+ F_NE, { !zero_flag = not equal }
+ F_G, { greater (signed) }
+ F_L, { less (signed) }
+ F_GE,
+ F_LE,
+ F_C, { carry flag }
+ F_NC, { !carry flag }
+ F_A, { greater (unsigned) }
+ F_AE,
+ F_B, { less (unsigned) }
+ F_BE
+ );
+
+{*****************************************************************************
+ Reference
+*****************************************************************************}
+
+ type
+ trefoptions=(ref_none,ref_parafixup,ref_localfixup,ref_selffixup);
+
+ { reference record }
+ preference = ^treference;
+ treference = packed record
+ base,
+ index : tregister;
+ offset : longint;
+ symbol : tasmsymbol;
+ offsetfixup : longint;
+ options : trefoptions;
+ alignment : byte;
+ end;
+
+ { reference record }
+ pparareference = ^tparareference;
+ tparareference = packed record
+ index : tregister;
+ offset : aword;
+ end;
+
+
+{*****************************************************************************
+ Operand
+*****************************************************************************}
+
+ type
+ toptype=(top_none,top_reg,top_ref,top_const,top_symbol,top_bool);
+
+ toper=record
+ ot : longint;
+ case typ : toptype of
+ top_none : ();
+ top_reg : (reg:tregister);
+ top_ref : (ref:^treference);
+ top_const : (val:aword);
+ top_symbol : (sym:tasmsymbol;symofs:longint);
+ top_bool : (b: boolean);
+ end;
+
+{*****************************************************************************
+ Operand Sizes
+*****************************************************************************}
+ { S_NO = No Size of operand }
+ { S_B = 8-bit size operand }
+ { S_W = 16-bit size operand }
+ { S_L = 32-bit size operand }
+ { Floating point types }
+ { S_FS = single type (32 bit) }
+ { S_FD = double/64bit integer }
+ { S_FX = Extended type }
+ topsize = (S_NO,S_B,S_W,S_L,S_FS,S_FD,S_FX,S_IQ);
+
+
+{*****************************************************************************
+ Generic Location
+*****************************************************************************}
+
+ type
+ TLoc=(
+ { added for tracking problems}
+ LOC_INVALID,
+ { ordinal constant }
+ LOC_CONSTANT,
+ { in a processor register }
+ LOC_REGISTER,
+ { Constant register which shouldn't be modified }
+ LOC_CREGISTER,
+ { FPU register}
+ LOC_FPUREGISTER,
+ { Constant FPU register which shouldn't be modified }
+ LOC_CFPUREGISTER,
+ { multimedia register }
+ LOC_MMREGISTER,
+ { Constant multimedia reg which shouldn't be modified }
+ LOC_CMMREGISTER,
+ { in memory }
+ LOC_REFERENCE,
+ { in memory (constant) }
+ LOC_CREFERENCE,
+ { boolean results only, jump to false or true label }
+ LOC_JUMP,
+ { boolean results only, flags are set }
+ LOC_FLAGS
+ );
+
+ { tparamlocation describes where a parameter for a procedure is stored.
+ References are given from the caller's point of view. The usual
+ TLocation isn't used, because contains a lot of unnessary fields.
+ }
+ tparalocation = packed record
+ size : TCGSize;
+ { The location type where the parameter is passed, usually
+ LOC_REFERENCE,LOC_REGISTER or LOC_FPUREGISTER
+ }
+ loc : TLoc;
+ { The stack pointer must be decreased by this value before
+ the parameter is copied to the given destination.
+ This allows to "encode" pushes with tparalocation.
+ On the PowerPC, this field is unsed but it is there
+ because several generic code accesses it.
+ }
+ sp_fixup : longint;
+ case TLoc of
+ LOC_REFERENCE : (reference : tparareference);
+ LOC_FPUREGISTER, LOC_CFPUREGISTER, LOC_MMREGISTER, LOC_CMMREGISTER,
+ LOC_REGISTER,LOC_CREGISTER : (
+ case longint of
+ 1 : (register,register64.reghi : tregister);
+ { overlay a register64.reglo }
+ 2 : (register64.reglo : tregister);
+ { overlay a 64 Bit register type }
+ 3 : (reg64 : tregister64);
+ 4 : (register64 : tregister64);
+ );
+ end;
+
+ treglocation = packed record
+ case longint of
+ 1 : (register,register64.reghi : tregister);
+ { overlay a register64.reglo }
+ 2 : (register64.reglo : tregister);
+ { overlay a 64 Bit register type }
+ 3 : (reg64 : tregister64);
+ 4 : (register64 : tregister64);
+ end;
+
+
+ tlocation = packed record
+ size : TCGSize;
+ loc : tloc;
+ case tloc of
+ LOC_CREFERENCE,LOC_REFERENCE : (reference : treference);
+ LOC_CONSTANT : (
+ case longint of
+ 1 : (value : AWord);
+ { can't do this, this layout depends on the host cpu. Use }
+ { lo(valueqword)/hi(valueqword) instead (JM) }
+ { 2 : (valuelow, valuehigh:AWord); }
+ { overlay a complete 64 Bit value }
+ 3 : (valueqword : qword);
+ );
+ LOC_FPUREGISTER, LOC_CFPUREGISTER, LOC_MMREGISTER, LOC_CMMREGISTER,
+ LOC_REGISTER,LOC_CREGISTER : (
+ case longint of
+ 1 : (register64.reglo,register64.reghi : tregister);
+ 2 : (register : tregister);
+ { overlay a 64 Bit register type }
+ 3 : (reg64 : tregister64);
+ 4 : (register64 : tregister64);
+ );
+ LOC_FLAGS : (resflags : tresflags);
+ end;
+
+{*****************************************************************************
+ Constants
+*****************************************************************************}
+
+ const
+ max_operands = 2;
+
+ lvaluelocations = [LOC_REFERENCE, LOC_CREGISTER, LOC_CFPUREGISTER,
+ LOC_CMMREGISTER];
+
+ {# Constant defining possibly all registers which might require saving }
+ ALL_REGISTERS = [R_FP0..R_FP15];
+
+ general_registers = [R_R0..R_R11];
+
+ {# low and high of the available maximum width integer general purpose }
+ { registers }
+ LoGPReg = R_R0;
+ HiGPReg = R_R11;
+
+ {# low and high of every possible width general purpose register (same as }
+ { above on most architctures apart from the 80x86) }
+ LoReg = R_R0;
+ HiReg = R_R11;
+
+ maxintregs = 12;
+ maxfpuregs = 16;
+ maxaddrregs = 0;
+
+ maxvarregs = 10;
+ varregs : Array [1..maxvarregs] of toldregister =
+ (R_R2,R_R3,R_R4,R_R5,R_R6,R_R7,R_R8,R_R9,R_R10,R_R11);
+
+ maxfpuvarregs = 15;
+ fpuvarregs : Array [1..maxfpuvarregs] of toldregister =
+ (R_FP1,R_FP2,R_FP3,
+ R_FP4,R_FP5,R_FP6,
+ R_FP7,R_FP8,R_FP9,
+ R_FP10,R_FP11,R_FP12,
+ R_FP13,R_FP14,R_FP15);
+
+
+ max_param_regs_int = 0;
+
+ max_param_regs_fpu = 0;
+
+ max_param_regs_mm = 0;
+
+ {# Registers which are defined as scratch and no need to save across
+ routine calls or in assembler blocks.
+ }
+ max_scratch_regs = 2;
+ scratch_regs: Array[1..max_scratch_regs] of Tsuperregister = (RS_R0,RS_R1);
+
+{*****************************************************************************
+ Default generic sizes
+*****************************************************************************}
+
+ {# Defines the default address size for a processor, }
+ OS_ADDR = OS_32;
+ {# the natural int size for a processor, }
+ OS_INT = OS_32;
+ {# the maximum float size for a processor, }
+ OS_FLOAT = OS_F64;
+ {# the size of a vector register for a processor }
+ OS_VECTOR = OS_NO;
+
+{*****************************************************************************
+ GDB Information
+*****************************************************************************}
+
+ {# Register indexes for stabs information, when some
+ parameters or variables are stored in registers.
+
+ Currently unsupported by abstract machine
+ }
+
+ stab_regindex : array[toldregister] of shortint =
+ (-1,
+ { r0..r11 }
+ -1,-1,-1,-1,-1,-1,
+ -1,-1,-1,-1,-1,-1,
+ { sp,fp,ccr,pc }
+ -1,-1,-1,-1,
+ { FP0..FP7 }
+ -1,-1,-1,-1,-1,-1,-1,-1,
+ { FP8..FP15 }
+ -1,-1,-1,-1,-1,-1,-1,-1,
+ { invalid }
+ -1,-1
+ );
+
+
+{*****************************************************************************
+ Generic Register names
+*****************************************************************************}
+
+ {# Stack pointer register }
+ stack_pointer_reg = R_SP;
+ NR_STACK_POINTER_REG = NR_SP;
+ RS_STACK_POINTER_REG = RS_SP;
+ {# Frame pointer register }
+ frame_pointer_reg = R_FP;
+ NR_FRAME_POINTER_REG = NR_FP;
+ RS_FRAME_POINTER_REG = RS_FP;
+ {# Self pointer register : contains the instance address of an
+ object or class. }
+ self_pointer_reg = R_R11;
+ NR_SELF_POINTER_REG = NR_R11;
+ RS_SELF_POINTER_REG = RS_R11;
+ {# Register for addressing absolute data in a position independant way,
+ such as in PIC code. The exact meaning is ABI specific.
+ }
+ pic_offset_reg = R_R10;
+ {# Results are returned in this register (32-bit values) }
+ accumulator = R_R0;
+ NR_ACCUMULATOR = NR_R0;
+ RS_ACCUMULATOR = RS_R0;
+ {the return_result_reg, is used inside the called function to store its return
+ value when that is a scalar value otherwise a pointer to the address of the
+ result is placed inside it}
+ return_result_reg = accumulator;
+
+ {the function_result_reg contains the function result after a call to a scalar
+ function othewise it contains a pointer to the returned result}
+ function_result_reg = accumulator;
+ {# Hi-Results are returned in this register (64-bit value high register) }
+ accumulatorhigh = R_R1;
+ NR_ACCUMULATORHIGH = NR_R1;
+ RS_ACCUMULATORHIGH = RS_R1;
+ fpu_result_reg = R_FP0;
+ mmresultreg = R_NO;
+
+{*****************************************************************************
+ GCC /ABI linking information
+*****************************************************************************}
+
+ {# Registers which must be saved when calling a routine declared as
+ cppdecl, cdecl, stdcall, safecall, palmossyscall. The registers
+ saved should be the ones as defined in the target ABI and / or GCC.
+
+ This value can be deduced from CALLED_USED_REGISTERS array in the
+ GCC source.
+ }
+ std_saved_registers = [RS_R0,RS_R1,RS_R10,RS_R11];
+ {# Required parameter alignment when calling a routine declared as
+ stdcall and cdecl. The alignment value should be the one defined
+ by GCC or the target ABI.
+
+ The value of this constant is equal to the constant
+ PARM_BOUNDARY / BITS_PER_UNIT in the GCC source.
+ }
+ std_param_align = 4; { for 32-bit version only }
+
+
+{*****************************************************************************
+ Helpers
+*****************************************************************************}
+
+ function is_calljmp(o:tasmop):boolean;
+
+ procedure inverse_flags(var r : TResFlags);
+ function flags_to_cond(const f: TResFlags) : TAsmCond;
+ procedure convert_register_to_enum(var r:Tregister);
+ function cgsize2subreg(s:Tcgsize):Tsubregister;
+
+
+implementation
+
+ uses
+ verbose;
+
+{*****************************************************************************
+ Helpers
+*****************************************************************************}
+
+ function is_calljmp(o:tasmop):boolean;
+ begin
+ is_calljmp := false;
+ if o in [a_bxx,a_call,a_beqs..a_bbtl] then
+ is_calljmp := true;
+ end;
+
+ procedure inverse_flags(var r: TResFlags);
+ const flagsinvers : array[F_E..F_BE] of tresflags =
+ (F_NE,F_E,
+ F_LE,F_GE,
+ F_L,F_G,
+ F_NC,F_C,
+ F_BE,F_B,
+ F_AE,F_A);
+ begin
+ r:=flagsinvers[r];
+ end;
+
+
+
+ function flags_to_cond(const f: TResFlags) : TAsmCond;
+ const flags2cond : array[tresflags] of tasmcond =
+ (
+ {F_E} C_EQ,
+ {F_NE} C_NE,
+ {F_G } C_GT,
+ {F_L } C_LT,
+ {F_GE} C_GE,
+ {F_LE} C_LE,
+ {F_C} C_CS,
+ {F_NC} C_CC,
+ {F_A} C_AT,
+ {F_AE} C_AS,
+ {F_B} C_BT,
+ {F_BE} C_LS);
+ begin
+ flags_to_cond := flags2cond[f];
+ end;
+
+
+ procedure convert_register_to_enum(var r:Tregister);
+
+ begin
+ if r.enum = R_INTREGISTER then
+ case r.number of
+ NR_NO: r.enum:= R_NO;
+ NR_R0: r.enum:= R_R0;
+ NR_R1: r.enum:= R_R1;
+ NR_R2: r.enum:= R_R2;
+ NR_R3: r.enum:= R_R3;
+ NR_R4: r.enum:= R_R4;
+ NR_R5: r.enum:= R_R5;
+ NR_R6: r.enum:= R_R6;
+ NR_R7: r.enum:= R_R7;
+ NR_R8: r.enum:= R_R8;
+ NR_R9: r.enum:= R_R9;
+ NR_R10: r.enum:= R_R10;
+ NR_R11: r.enum:= R_R11;
+ else
+ internalerror(200301082);
+ end;
+ end;
+
+ function cgsize2subreg(s:Tcgsize):Tsubregister;
+
+ begin
+ case s of
+ OS_8,OS_S8:
+ cgsize2subreg:=R_SUBL;
+ OS_16,OS_S16:
+ cgsize2subreg:=R_SUBW;
+ OS_32,OS_S32:
+ cgsize2subreg:=R_SUBD;
+ else
+ internalerror(200301231);
+ end;
+ end;
+
+
+end.
diff --git a/closures/compiler/vis/cpuinfo.pas b/closures/compiler/vis/cpuinfo.pas
new file mode 100644
index 0000000000..ef0fa47113
--- /dev/null
+++ b/closures/compiler/vis/cpuinfo.pas
@@ -0,0 +1,56 @@
+{
+ Copyright (c) 1998-2002 by the Free Pascal development team
+
+ Basic Processor information for the virtual instruction set
+
+ See the file COPYING.FPC, included in this distribution,
+ for details about the copyright.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+Unit CPUInfo;
+
+Interface
+
+Type
+ { Architecture word - Native unsigned type }
+ AWord = Longword;
+ PAWord = ^AWord;
+
+ { this must be an ordinal type with the same size as a pointer }
+ { to allow some dirty type casts for example when using }
+ { tconstsym.value }
+ { Note: must be unsigned!! Otherwise, ugly code like }
+ { pointer(-1) will result in a pointer with the value }
+ { $fffffffffffffff on a 32bit machine if the compiler uses }
+ { int64 constants internally (JM) }
+ TConstPtrUInt = Longword;
+
+ bestreal = double;
+ ts32real = single;
+ ts64real = double;
+ ts80real = extended;
+ ts64comp = comp;
+
+ pbestreal=^bestreal;
+
+ { possible supported processors for this target }
+ tcputype = (cpu_none);
+
+Const
+ {# Size of native extended floating point type }
+ extended_size = 8;
+ {# Size of a pointer }
+ sizeof(aint) = 4;
+ {# Size of a multimedia register }
+ mmreg_size = 8;
+ { target cpu string (used by compiler options) }
+ target_cpu_string = 'vis';
+
+Implementation
+
+end.
diff --git a/closures/compiler/vis/cpunode.pas b/closures/compiler/vis/cpunode.pas
new file mode 100644
index 0000000000..010879c0e5
--- /dev/null
+++ b/closures/compiler/vis/cpunode.pas
@@ -0,0 +1,47 @@
+{
+ Copyright (c) 2000-2002 by Florian Klaempfl
+
+ Includes the Virtual instrution set code generator
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit cpunode;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ implementation
+
+ uses
+ { generic nodes }
+ ncgbas,ncgld,ncgflw,ncgcnv,ncgmem,ncgcon,ncgcal,ncgset,ncginl,
+ { to be able to only parts of the generic code,
+ the processor specific nodes must be included
+ after the generic one (FK)
+ }
+// nvisadd,
+// nviscal,
+// nviscon,
+// nvisflw,
+// nvismem,
+// nvisinl,
+// nvismat,
+// nviscnv
+ ;
+
+end.
diff --git a/closures/compiler/vis/cpupara.pas b/closures/compiler/vis/cpupara.pas
new file mode 100644
index 0000000000..f55a93ced6
--- /dev/null
+++ b/closures/compiler/vis/cpupara.pas
@@ -0,0 +1,74 @@
+{
+ Copyright (c) 2002 by Florian Klaempfl
+
+ Generates the argument location information for the
+ virtual instruction set machine
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+{ Generates the argument location information for 680x0.
+}
+unit cpupara;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ cpubase,
+ symdef,paramgr;
+
+ type
+ { Returns the location for the nr-st 32 Bit int parameter
+ if every parameter before is an 32 Bit int parameter as well
+ and if the calling conventions for the helper routines of the
+ rtl are used.
+ }
+ tcpuparamanager = class(tparamanager)
+ function getintparaloc(nr : longint) : tparalocation;override;
+ procedure create_param_loc_info(p : tabstractprocdef);override;
+ function getselflocation(p : tabstractprocdef) : tparalocation;override;
+ end;
+
+ implementation
+
+ uses
+ verbose,
+ globals,
+ globtype,
+ systems,
+ cpuinfo,cginfo,cgbase,
+ defutil;
+
+ function tcpuparamanager.getintparaloc(nr : longint) : tparalocation;
+ begin
+ end;
+
+ procedure tcpuparamanager.create_param_loc_info(p : tabstractprocdef);
+ var
+ param_offset : integer;
+ hp : tparaitem;
+ begin
+ end;
+
+ function tcpuparamanager.getselflocation(p : tabstractprocdef) : tparalocation;
+ begin
+ end;
+
+begin
+ paramanager:=tcpuparamanager.create;
+end.
diff --git a/closures/compiler/widestr.pas b/closures/compiler/widestr.pas
new file mode 100644
index 0000000000..a1be761dec
--- /dev/null
+++ b/closures/compiler/widestr.pas
@@ -0,0 +1,326 @@
+{
+ Copyright (c) 2000-2002 by Florian Klaempfl
+
+ This unit contains basic functions for unicode support in the
+ compiler, this unit is mainly necessary to bootstrap widestring
+ support ...
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit widestr;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ {$if FPC_FULLVERSION<20700}ccharset{$else}charset{$endif},globtype;
+
+
+ type
+ tcompilerwidechar = word;
+ tcompilerwidecharptr = ^tcompilerwidechar;
+ pcompilerwidechar = ^tcompilerwidechar;
+
+ pcompilerwidestring = ^_tcompilerwidestring;
+ _tcompilerwidestring = record
+ data : pcompilerwidechar;
+ maxlen,len : SizeInt;
+ end;
+
+ procedure initwidestring(out r : pcompilerwidestring);
+ procedure donewidestring(var r : pcompilerwidestring);
+ procedure setlengthwidestring(r : pcompilerwidestring;l : SizeInt);
+ function getlengthwidestring(r : pcompilerwidestring) : SizeInt;
+ procedure concatwidestringchar(r : pcompilerwidestring;c : tcompilerwidechar);
+ procedure concatwidestrings(s1,s2 : pcompilerwidestring);
+ function comparewidestrings(s1,s2 : pcompilerwidestring) : SizeInt;
+ procedure copywidestring(s,d : pcompilerwidestring);
+ function asciichar2unicode(c : char) : tcompilerwidechar;
+ function unicode2asciichar(c : tcompilerwidechar) : char;
+ procedure ascii2unicode(p : pchar;l : SizeInt;cp : tstringencoding;r : pcompilerwidestring);
+ procedure unicode2ascii(r : pcompilerwidestring;p : pchar;cp : tstringencoding);
+ function hasnonasciichars(const p: pcompilerwidestring): boolean;
+ function getcharwidestring(r : pcompilerwidestring;l : SizeInt) : tcompilerwidechar;
+ function cpavailable(const s : string) : boolean;
+ function cpavailable(cp : word) : boolean;
+ procedure changecodepage(
+ s : pchar; l : SizeInt; scp : tstringencoding;
+ d : pchar; dcp : tstringencoding
+ );
+ function codepagebyname(const s : string) : tstringencoding;
+
+ implementation
+
+ uses
+ cp8859_1,cp850,cp437,cp1252,
+ { cyrillic code pages }
+ cp1251,cp866,cp8859_5,
+ globals,cutils;
+
+
+ procedure initwidestring(out r : pcompilerwidestring);
+
+ begin
+ new(r);
+ r^.data:=nil;
+ r^.len:=0;
+ r^.maxlen:=0;
+ end;
+
+ procedure donewidestring(var r : pcompilerwidestring);
+
+ begin
+ if assigned(r^.data) then
+ freemem(r^.data);
+ dispose(r);
+ r:=nil;
+ end;
+
+ function getcharwidestring(r : pcompilerwidestring;l : SizeInt) : tcompilerwidechar;
+
+ begin
+ getcharwidestring:=r^.data[l];
+ end;
+
+ function getlengthwidestring(r : pcompilerwidestring) : SizeInt;
+
+ begin
+ getlengthwidestring:=r^.len;
+ end;
+
+ procedure growwidestring(r : pcompilerwidestring;l : SizeInt);
+
+ begin
+ if r^.maxlen>=l then
+ exit;
+ if assigned(r^.data) then
+ reallocmem(r^.data,sizeof(tcompilerwidechar)*l)
+ else
+ getmem(r^.data,sizeof(tcompilerwidechar)*l);
+ r^.maxlen:=l;
+ end;
+
+ procedure setlengthwidestring(r : pcompilerwidestring;l : SizeInt);
+
+ begin
+ r^.len:=l;
+ if l>r^.maxlen then
+ growwidestring(r,l);
+ end;
+
+ procedure concatwidestringchar(r : pcompilerwidestring;c : tcompilerwidechar);
+
+ begin
+ if r^.len>=r^.maxlen then
+ growwidestring(r,r^.len+16);
+ r^.data[r^.len]:=c;
+ inc(r^.len);
+ end;
+
+ procedure concatwidestrings(s1,s2 : pcompilerwidestring);
+ begin
+ growwidestring(s1,s1^.len+s2^.len);
+ move(s2^.data^,s1^.data[s1^.len],s2^.len*sizeof(tcompilerwidechar));
+ inc(s1^.len,s2^.len);
+ end;
+
+ procedure copywidestring(s,d : pcompilerwidestring);
+
+ begin
+ setlengthwidestring(d,s^.len);
+ move(s^.data^,d^.data^,s^.len*sizeof(tcompilerwidechar));
+ end;
+
+ function comparewidestrings(s1,s2 : pcompilerwidestring) : SizeInt;
+ var
+ maxi,temp : SizeInt;
+ begin
+ if pointer(s1)=pointer(s2) then
+ begin
+ comparewidestrings:=0;
+ exit;
+ end;
+ maxi:=s1^.len;
+ temp:=s2^.len;
+ if maxi>temp then
+ maxi:=Temp;
+ temp:=compareword(s1^.data^,s2^.data^,maxi);
+ if temp=0 then
+ temp:=s1^.len-s2^.len;
+ comparewidestrings:=temp;
+ end;
+
+ function asciichar2unicode(c : char) : tcompilerwidechar;
+ var
+ m : punicodemap;
+ begin
+ if (current_settings.sourcecodepage <> CP_UTF8) then
+ begin
+ m:=getmap(current_settings.sourcecodepage);
+ asciichar2unicode:=getunicode(c,m);
+ end
+ else
+ result:=tcompilerwidechar(c);
+ end;
+
+ function unicode2asciichar(c : tcompilerwidechar) : char;
+ {begin
+ if word(c)<128 then
+ unicode2asciichar:=char(word(c))
+ else
+ unicode2asciichar:='?';
+ end;}
+ begin
+ Result := getascii(c,getmap(current_settings.sourcecodepage))[1];
+ end;
+
+ procedure ascii2unicode(p : pchar;l : SizeInt;cp : tstringencoding;r : pcompilerwidestring);
+ var
+ source : pchar;
+ dest : tcompilerwidecharptr;
+ i : SizeInt;
+ m : punicodemap;
+ begin
+ m:=getmap(cp);
+ setlengthwidestring(r,l);
+ source:=p;
+ dest:=tcompilerwidecharptr(r^.data);
+ if (current_settings.sourcecodepage <> CP_UTF8) then
+ begin
+ for i:=1 to l do
+ begin
+ dest^:=getunicode(source^,m);
+ inc(dest);
+ inc(source);
+ end;
+ end
+ else
+ begin
+ for i:=1 to l do
+ begin
+ dest^:=tcompilerwidechar(source^);
+ inc(dest);
+ inc(source);
+ end;
+ end;
+ end;
+
+ procedure unicode2ascii(r : pcompilerwidestring;p:pchar;cp : tstringencoding);
+ var
+ m : punicodemap;
+ source : tcompilerwidecharptr;
+ dest : pchar;
+ i : longint;
+ begin
+ if (cp = 0) or (cp=CP_NONE) then
+ m:=getmap(current_settings.sourcecodepage)
+ else
+ m:=getmap(cp);
+ // !!!! MBCS
+ source:=tcompilerwidecharptr(r^.data);
+ dest:=p;
+ for i:=1 to r^.len do
+ begin
+ dest^ := getascii(source^,m)[1];
+ inc(dest);
+ inc(source);
+ end;
+ end;
+(*
+ var
+ source : tcompilerwidecharptr;
+ dest : pchar;
+ i : longint;
+ begin
+ { This routine must work the same as the
+ the routine in the RTL to have the same compile time (for constant strings)
+ and runtime conversion (for variables) }
+ source:=tcompilerwidecharptr(r^.data);
+ dest:=p;
+ for i:=1 to r^.len do
+ begin
+ if word(source^)<128 then
+ dest^:=char(word(source^))
+ else
+ dest^:='?';
+ inc(dest);
+ inc(source);
+ end;
+ end;
+*)
+
+ function hasnonasciichars(const p: pcompilerwidestring): boolean;
+ var
+ source : tcompilerwidecharptr;
+ i : longint;
+ begin
+ source:=tcompilerwidecharptr(p^.data);
+ result:=true;
+ for i:=1 to p^.len do
+ begin
+ if word(source^)>=128 then
+ exit;
+ inc(source);
+ end;
+ result:=false;
+ end;
+
+
+ function cpavailable(const s : string) : boolean;
+ begin
+ cpavailable:=mappingavailable(lower(s));
+ end;
+
+ function cpavailable(cp : word) : boolean;
+ begin
+ cpavailable:=mappingavailable(cp);
+ end;
+
+ procedure changecodepage(
+ s : pchar; l : SizeInt; scp : tstringencoding;
+ d : pchar; dcp : tstringencoding
+ );
+ var
+ ms, md : punicodemap;
+ source : pchar;
+ dest : pchar;
+ i : longint;
+ begin
+ ms:=getmap(scp);
+ md:=getmap(dcp);
+ source:=s;
+ dest:=d;
+ for i:=1 to l do
+ begin
+ dest^ := getascii(getunicode(source^,ms),md)[1];
+ inc(dest);
+ inc(source);
+ end;
+ end;
+
+ function codepagebyname(const s : string) : tstringencoding;
+ var
+ p : punicodemap;
+ begin
+ Result:=0;
+ p:=getmap(s);
+ if (p<>nil) then
+ Result:=p^.cp;
+ end;
+
+end.
diff --git a/closures/compiler/wpo.pas b/closures/compiler/wpo.pas
new file mode 100644
index 0000000000..1d3cf4d6e4
--- /dev/null
+++ b/closures/compiler/wpo.pas
@@ -0,0 +1,79 @@
+{
+ Copyright (c) 2008 by Jonas Maebe
+
+ Collects all whole program optimization plugin untits
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+
+unit wpo;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ { all units with whole program optimisation components }
+ optvirt,optdead;
+
+
+ procedure InitWpo;
+ procedure DoneWpo;
+
+implementation
+
+ uses
+ globals,
+ comphook,
+ wpobase, wpoinfo;
+
+ { called after command line parameters have been parsed }
+ procedure InitWpo;
+ begin
+ { always create so we don't have to litter the source with if-tests }
+ wpoinfomanager:=twpoinfomanager.create;
+
+ { register the classes we can/should potentially use }
+ wpoinfomanager.registerwpocomponentclass(tprogdevirtinfo);
+ wpoinfomanager.registerwpocomponentclass(twpodeadcodeinfofromexternallinker);
+
+ { assign input/output feedback files }
+ if (wpofeedbackinput<>'') then
+ wpoinfomanager.setwpoinputfile(wpofeedbackinput);
+ if (wpofeedbackoutput<>'') then
+ wpoinfomanager.setwpooutputfile(wpofeedbackoutput);
+
+ { parse input }
+ wpoinfomanager.parseandcheckwpoinfo;
+
+ { abort if error }
+ if (codegenerror) then
+ raise ECompilerAbort.Create;
+ end;
+
+
+ procedure DoneWpo;
+ begin
+ wpoinfomanager.free;
+ wpoinfomanager:=nil;
+ wpofeedbackinput:='';
+ wpofeedbackoutput:='';
+ end;
+
+
+end.
+
diff --git a/closures/compiler/wpobase.pas b/closures/compiler/wpobase.pas
new file mode 100644
index 0000000000..8e637540d6
--- /dev/null
+++ b/closures/compiler/wpobase.pas
@@ -0,0 +1,829 @@
+{
+ Copyright (c) 2008 by Jonas Maebe
+
+ Whole program optimisation information collection base class
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ ****************************************************************************
+}
+
+unit wpobase;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ globtype,
+ cclasses,
+ symtype;
+
+type
+ { the types of available whole program optimization }
+ twpotype = (wpo_devirtualization_context_insensitive,wpo_live_symbol_information);
+const
+ wpo2str: array[twpotype] of string[16] = ('devirtualization','symbol liveness');
+
+type
+ { ************************************************************************* }
+ { ******************** General base classes/interfaces ******************** }
+ { ************************************************************************* }
+
+ { interface to reading a section from a file with wpo info }
+ twposectionreaderintf = interface
+ ['{51BE3F89-C9C5-4965-9C83-AE7490C92E3E}']
+ function sectiongetnextline(out s: string): boolean;
+ end;
+
+
+ { interface to writing sections to a file with wpoinfo }
+ twposectionwriterintf = interface
+ ['{C056F0DD-62B1-4612-86C7-2D39944C4437}']
+ procedure startsection(const name: string);
+ procedure sectionputline(const s: string);
+ end;
+
+
+ { base class for wpo information stores }
+
+ { twpocomponentbase }
+
+ twpocomponentbase = class
+ public
+ constructor create; reintroduce; virtual;
+
+ { type of whole program optimization information collected/provided by
+ this class
+ }
+ class function getwpotype: twpotype; virtual; abstract;
+
+ { whole program optimizations for which this class generates information }
+ class function generatesinfoforwposwitches: twpoptimizerswitches; virtual; abstract;
+
+ { whole program optimizations performed by this class }
+ class function performswpoforswitches: twpoptimizerswitches; virtual; abstract;
+
+ { returns the name of the section parsed by this class }
+ class function sectionname: shortstring; virtual; abstract;
+
+ { checks whether the compiler options are compatible with this
+ optimization (default: don't check anything)
+ }
+ class procedure checkoptions; virtual;
+
+ { loads the information pertinent to this whole program optimization from
+ the current section being processed by reader
+ }
+ procedure loadfromwpofilesection(reader: twposectionreaderintf); virtual; abstract;
+
+ { stores the information of this component to a file in a format that can
+ be loaded again using loadfromwpofilesection()
+ }
+ procedure storewpofilesection(writer: twposectionwriterintf); virtual; abstract;
+
+ { extracts the information pertinent to this whole program optimization
+ from the current compiler state (loaded units, ...)
+ }
+ procedure constructfromcompilerstate; virtual; abstract;
+ end;
+
+ twpocomponentbaseclass = class of twpocomponentbase;
+
+
+ { forward declaration of overall wpo info manager class }
+
+ twpoinfomanagerbase = class;
+
+ { ************************************************************************* }
+ { ** Information created per unit for use during subsequent compilation *** }
+ { ************************************************************************* }
+
+ { information about called vmt entries for a class }
+ tcalledvmtentries = class
+ protected
+ { the class }
+ fobjdef: tdef;
+ fobjdefderef: tderef;
+ { the vmt entries }
+ fcalledentries: tbitset;
+ public
+ constructor create(_objdef: tdef; nentries: longint);
+ constructor ppuload(ppufile: tcompilerppufile);
+ destructor destroy; override;
+ procedure ppuwrite(ppufile: tcompilerppufile);
+
+ procedure buildderef;
+ procedure buildderefimpl;
+ procedure deref;
+ procedure derefimpl;
+
+ property objdef: tdef read fobjdef write fobjdef;
+ property objdefderef: tderef read fobjdefderef write fobjdefderef;
+ property calledentries: tbitset read fcalledentries write fcalledentries;
+ end;
+
+
+ { base class of information collected per unit. Still needs to be
+ generalised for different kinds of wpo information, currently specific
+ to devirtualization.
+ }
+
+ tunitwpoinfobase = class
+ protected
+ { created object types }
+ fcreatedobjtypes: tfpobjectlist;
+ { objectdefs pointed to by created classrefdefs }
+ fcreatedclassrefobjtypes: tfpobjectlist;
+ { objtypes potentially instantiated by fcreatedclassrefobjtypes
+ (objdectdefs pointed to by classrefdefs that are
+ passed as a regular parameter, loaded in a variable, ...
+ so they can end up in a classrefdef var and be instantiated)
+ }
+ fmaybecreatedbyclassrefdeftypes: tfpobjectlist;
+
+ { called virtual methods for all classes (hashed by mangled classname,
+ entries bitmaps indicating which vmt entries per class are called --
+ tcalledvmtentries)
+ }
+ fcalledvmtentries: tfphashlist;
+ public
+ constructor create; reintroduce; virtual;
+ destructor destroy; override;
+
+ property createdobjtypes: tfpobjectlist read fcreatedobjtypes;
+ property createdclassrefobjtypes: tfpobjectlist read fcreatedclassrefobjtypes;
+ property maybecreatedbyclassrefdeftypes: tfpobjectlist read fmaybecreatedbyclassrefdeftypes;
+ property calledvmtentries: tfphashlist read fcalledvmtentries;
+
+ procedure addcreatedobjtype(def: tdef);
+ procedure addcreatedobjtypeforclassref(def: tdef);
+ procedure addmaybecreatedbyclassref(def: tdef);
+ procedure addcalledvmtentry(def: tdef; index: longint);
+
+ { resets the "I've been registered with wpo" flags for all defs in the
+ above lists }
+ procedure resetdefs;
+ end;
+
+ { ************************************************************************* }
+ { **** Total information created for use during subsequent compilation **** }
+ { ************************************************************************* }
+
+ { class to create a file with wpo information }
+
+ { tavailablewpofilewriter }
+
+ twpofilewriter = class(tobject,twposectionwriterintf)
+ private
+ { array of class *instances* that wish to be written out to the
+ whole program optimization feedback file
+ }
+ fsectioncontents: tfpobjectlist;
+
+ ffilename: tcmdstr;
+ foutputfile: text;
+
+ public
+ constructor create(const fn: tcmdstr);
+ destructor destroy; override;
+
+ procedure writefile;
+
+ { starts a new section with name "name" }
+ procedure startsection(const name: string);
+ { writes s to the wpo file }
+ procedure sectionputline(const s: string);
+
+ { register a component instance that needs to be written
+ to the wpo feedback file
+ }
+ procedure registerwpocomponent(component: twpocomponentbase);
+ end;
+
+ { ************************************************************************* }
+ { ************ Information for use during current compilation ************* }
+ { ************************************************************************* }
+
+ { class to read a file with wpo information }
+ twpofilereader = class(tobject,twposectionreaderintf)
+ private
+ ffilename: tcmdstr;
+ flinenr: longint;
+ finputfile: text;
+ fcurline: string;
+ fusecurline: boolean;
+
+ { destination for the read information }
+ fdest: twpoinfomanagerbase;
+
+ function getnextnoncommentline(out s: string): boolean;
+ public
+
+ constructor create(const fn: tcmdstr; dest: twpoinfomanagerbase);
+ destructor destroy; override;
+
+ { processes the wpo info in the file }
+ procedure processfile;
+
+ { returns next line of the current section in s, and false if no more
+ lines in the current section
+ }
+ function sectiongetnextline(out s: string): boolean;
+ end;
+
+
+ { ************************************************************************* }
+ { ******* Specific kinds of whole program optimization components ********* }
+ { ************************************************************************* }
+
+ { method devirtualisation }
+ twpodevirtualisationhandler = class(twpocomponentbase)
+ { checks whether procdef (a procdef for a virtual method) can be replaced with
+ a static call when it's called as objdef.procdef, and if so returns the
+ mangled name in staticname.
+ }
+ function staticnameforcallingvirtualmethod(objdef, procdef: tdef; out staticname: string): boolean; virtual; abstract;
+ { checks whether procdef (a procdef for a virtual method) can be replaced with
+ a different procname in the vmt of objdef, and if so returns the new
+ mangledname in staticname
+ }
+ function staticnameforvmtentry(objdef, procdef: tdef; out staticname: string): boolean; virtual; abstract;
+ end;
+
+ twpodeadcodehandler = class(twpocomponentbase)
+ { checks whether a mangledname was removed as dead code from the final
+ binary (WARNING: must *not* be called for functions marked as inline,
+ since if all call sites are inlined, it won't appear in the final
+ binary but nevertheless is still necessary!)
+ }
+ function symbolinfinalbinary(const s: shortstring): boolean; virtual; abstract;
+ end;
+
+
+ { ************************************************************************* }
+ { ************ Collection of all instances of wpo components ************** }
+ { ************************************************************************* }
+
+ { class doing all the bookkeeping for everything }
+
+ twpoinfomanagerbase = class
+ private
+ { array of classrefs of handler classes for the various kinds of whole
+ program optimizations that we support
+ }
+ fwpocomponents: tfphashlist;
+
+ freader: twpofilereader;
+ fwriter: twpofilewriter;
+ public
+ { instances of the various optimizers/information collectors (for
+ information used during this compilation)
+ }
+ wpoinfouse: array[twpotype] of twpocomponentbase;
+
+ { register a whole program optimization class type }
+ procedure registerwpocomponentclass(wpocomponent: twpocomponentbaseclass);
+
+ { get the program optimization class type that can parse the contents
+ of the section with name "secname" in the wpo feedback file
+ }
+ function gethandlerforsection(const secname: string): twpocomponentbaseclass;
+
+ { tell all instantiated wpo component classes to collect the information
+ from the global compiler state that they need (done at the very end of
+ the compilation process)
+ }
+ procedure extractwpoinfofromprogram;
+
+ { set the name of the feedback file from which all whole-program information
+ to be used during the current compilation will be read
+ }
+ procedure setwpoinputfile(const fn: tcmdstr);
+
+ { set the name of the feedback file to which all whole-program information
+ collected during the current compilation will be written
+ }
+ procedure setwpooutputfile(const fn: tcmdstr);
+
+ { check whether the specified wpo options (-FW/-Fw/-OW/-Ow) are complete
+ and sensical, and parse the wpo feedback file specified with
+ setwpoinputfile
+ }
+ procedure parseandcheckwpoinfo;
+
+ { routines accessing the optimizer information }
+ { 1) devirtualization at the symbol name level }
+ function can_be_devirtualized(objdef, procdef: tdef; out name: shortstring): boolean; virtual; abstract;
+ { 2) optimal replacement method name in vmt }
+ function optimized_name_for_vmt(objdef, procdef: tdef; out name: shortstring): boolean; virtual; abstract;
+ { 3) does a symbol appear in the final binary (i.e., not removed by dead code stripping/smart linking).
+ WARNING: do *not* call for inline functions/procedures/methods/...
+ }
+ function symbol_live(const name: shortstring): boolean; virtual; abstract;
+
+ constructor create; reintroduce;
+ destructor destroy; override;
+ end;
+
+
+ var
+ wpoinfomanager: twpoinfomanagerbase;
+
+implementation
+
+ uses
+ globals,
+ cutils,
+ sysutils,
+ symdef,
+ verbose;
+
+
+ { tcreatedwpoinfobase }
+
+ constructor tunitwpoinfobase.create;
+ begin
+ fcreatedobjtypes:=tfpobjectlist.create(false);
+ fcreatedclassrefobjtypes:=tfpobjectlist.create(false);
+ fmaybecreatedbyclassrefdeftypes:=tfpobjectlist.create(false);
+ fcalledvmtentries:=tfphashlist.create;
+ end;
+
+
+ destructor tunitwpoinfobase.destroy;
+ var
+ i: longint;
+ begin
+ { don't call resetdefs here, because the defs may have been freed
+ already }
+ fcreatedobjtypes.free;
+ fcreatedobjtypes:=nil;
+ fcreatedclassrefobjtypes.free;
+ fcreatedclassrefobjtypes:=nil;
+ fmaybecreatedbyclassrefdeftypes.free;
+ fmaybecreatedbyclassrefdeftypes:=nil;
+
+ { may not be assigned in case the info was loaded from a ppu and we
+ are not generating a wpo feedback file (see tunitwpoinfo.ppuload)
+ }
+ if assigned(fcalledvmtentries) then
+ begin
+ for i:=0 to fcalledvmtentries.count-1 do
+ tcalledvmtentries(fcalledvmtentries[i]).free;
+ fcalledvmtentries.free;
+ fcalledvmtentries:=nil;
+ end;
+
+ inherited destroy;
+ end;
+
+
+ procedure tunitwpoinfobase.resetdefs;
+ var
+ i: ptrint;
+ begin
+ if assigned(fcreatedobjtypes) then
+ for i:=0 to fcreatedobjtypes.count-1 do
+ tobjectdef(fcreatedobjtypes[i]).created_in_current_module:=false;
+ if assigned(fcreatedclassrefobjtypes) then
+ for i:=0 to fcreatedclassrefobjtypes.count-1 do
+ tobjectdef(fcreatedclassrefobjtypes[i]).classref_created_in_current_module:=false;
+ if assigned(fmaybecreatedbyclassrefdeftypes) then
+ for i:=0 to fmaybecreatedbyclassrefdeftypes.count-1 do
+ tobjectdef(fmaybecreatedbyclassrefdeftypes[i]).maybe_created_in_current_module:=false;
+ end;
+
+
+ procedure tunitwpoinfobase.addcreatedobjtype(def: tdef);
+ begin
+ fcreatedobjtypes.add(def);
+ end;
+
+
+ procedure tunitwpoinfobase.addcreatedobjtypeforclassref(def: tdef);
+ begin
+ fcreatedclassrefobjtypes.add(def);
+ end;
+
+
+ procedure tunitwpoinfobase.addmaybecreatedbyclassref(def: tdef);
+ begin
+ fmaybecreatedbyclassrefdeftypes.add(def);
+ end;
+
+
+ procedure tunitwpoinfobase.addcalledvmtentry(def: tdef; index: longint);
+ var
+ entries: tcalledvmtentries;
+ key: shortstring;
+ begin
+ key:=tobjectdef(def).vmt_mangledname;
+ entries:=tcalledvmtentries(fcalledvmtentries.find(key));
+ if not assigned(entries) then
+ begin
+ entries:=tcalledvmtentries.create(def,tobjectdef(def).vmtentries.count);
+ fcalledvmtentries.add(key,entries);
+ end;
+ entries.calledentries.include(index);
+ end;
+
+
+ { twpofilereader }
+
+ function twpofilereader.getnextnoncommentline(out s: string):
+ boolean;
+ begin
+ if (fusecurline) then
+ begin
+ s:=fcurline;
+ fusecurline:=false;
+ result:=true;
+ exit;
+ end;
+ repeat
+ readln(finputfile,s);
+ if (s='') and
+ eof(finputfile) then
+ begin
+ result:=false;
+ exit;
+ end;
+ inc(flinenr);
+ until (s='') or
+ (s[1]<>'#');
+ result:=true;
+ end;
+
+ constructor twpofilereader.create(const fn: tcmdstr; dest: twpoinfomanagerbase);
+ begin
+ if not FileExists(fn) or
+ { FileExists also returns true for directories }
+ DirectoryExists(fn) then
+ begin
+ cgmessage1(wpo_cant_find_file,fn);
+ exit;
+ end;
+ assign(finputfile,fn);
+ ffilename:=fn;
+
+ fdest:=dest;
+ end;
+
+ destructor twpofilereader.destroy;
+ begin
+ inherited destroy;
+ end;
+
+ procedure twpofilereader.processfile;
+ var
+ sectionhandler: twpocomponentbaseclass;
+ i: longint;
+ wpotype: twpotype;
+ s,
+ sectionname: string;
+ begin
+ cgmessage1(wpo_begin_processing,ffilename);
+ reset(finputfile);
+ flinenr:=0;
+ while getnextnoncommentline(s) do
+ begin
+ if (s='') then
+ continue;
+ { format: "% sectionname" }
+ if (s[1]<>'%') then
+ begin
+ cgmessage2(wpo_expected_section,tostr(flinenr),s);
+ break;
+ end;
+ for i:=2 to length(s) do
+ if (s[i]<>' ') then
+ break;
+ sectionname:=copy(s,i,255);
+
+ { find handler for section and process }
+ sectionhandler:=fdest.gethandlerforsection(sectionname);
+ if assigned(sectionhandler) then
+ begin
+ wpotype:=sectionhandler.getwpotype;
+ cgmessage2(wpo_found_section,sectionname,wpo2str[wpotype]);
+ { do we need this information? }
+ if ((sectionhandler.performswpoforswitches * init_settings.dowpoptimizerswitches) <> []) then
+ begin
+ { did some other section already generate this type of information? }
+ if assigned(fdest.wpoinfouse[wpotype]) then
+ begin
+ cgmessage2(wpo_duplicate_wpotype,wpo2str[wpotype],sectionname);
+ fdest.wpoinfouse[wpotype].free;
+ end;
+ { process the section }
+ fdest.wpoinfouse[wpotype]:=sectionhandler.create;
+ twpocomponentbase(fdest.wpoinfouse[wpotype]).loadfromwpofilesection(self);
+ end
+ else
+ begin
+ cgmessage1(wpo_skipping_unnecessary_section,sectionname);
+ { skip the current section }
+ while sectiongetnextline(s) do
+ ;
+ end;
+ end
+ else
+ begin
+ cgmessage1(wpo_no_section_handler,sectionname);
+ { skip the current section }
+ while sectiongetnextline(s) do
+ ;
+ end;
+ end;
+ close(finputfile);
+ cgmessage1(wpo_end_processing,ffilename);
+ end;
+
+ function twpofilereader.sectiongetnextline(out s: string): boolean;
+ begin
+ result:=getnextnoncommentline(s);
+ if not result then
+ exit;
+ { start of new section? }
+ if (s<>'') and
+ (s[1]='%') then
+ begin
+ { keep read line for next call to getnextnoncommentline() }
+ fcurline:=s;
+ fusecurline:=true;
+ result:=false;
+ end;
+ end;
+
+
+ { twpocomponentbase }
+
+ constructor twpocomponentbase.create;
+ begin
+ { do nothing }
+ end;
+
+
+ class procedure twpocomponentbase.checkoptions;
+ begin
+ { do nothing }
+ end;
+
+ { twpofilewriter }
+
+ constructor twpofilewriter.create(const fn: tcmdstr);
+ begin
+ assign(foutputfile,fn);
+ ffilename:=fn;
+ fsectioncontents:=tfpobjectlist.create(true);
+ end;
+
+ destructor twpofilewriter.destroy;
+ begin
+ fsectioncontents.free;
+ inherited destroy;
+ end;
+
+ procedure twpofilewriter.writefile;
+ var
+ i: longint;
+ begin
+ {$push}{$i-}
+ rewrite(foutputfile);
+ {$pop}
+ if (ioresult <> 0) then
+ begin
+ cgmessage1(wpo_cant_create_feedback_file,ffilename);
+ exit;
+ end;
+ for i:=0 to fsectioncontents.count-1 do
+ twpocomponentbase(fsectioncontents[i]).storewpofilesection(self);
+ close(foutputfile);
+ end;
+
+ procedure twpofilewriter.startsection(const name: string);
+ begin
+ writeln(foutputfile,'% ',name);
+ end;
+
+ procedure twpofilewriter.sectionputline(const s: string);
+ begin
+ writeln(foutputfile,s);
+ end;
+
+ procedure twpofilewriter.registerwpocomponent(
+ component: twpocomponentbase);
+ begin
+ fsectioncontents.add(component);
+ end;
+
+{ twpoinfomanagerbase }
+
+ procedure twpoinfomanagerbase.registerwpocomponentclass(wpocomponent: twpocomponentbaseclass);
+ begin
+ fwpocomponents.add(wpocomponent.sectionname,wpocomponent);
+ end;
+
+
+ function twpoinfomanagerbase.gethandlerforsection(const secname: string
+ ): twpocomponentbaseclass;
+ begin
+ result:=twpocomponentbaseclass(fwpocomponents.find(secname));
+ end;
+
+ procedure twpoinfomanagerbase.setwpoinputfile(const fn: tcmdstr);
+ begin
+ freader:=twpofilereader.create(fn,self);
+ end;
+
+ procedure twpoinfomanagerbase.setwpooutputfile(const fn: tcmdstr);
+ begin
+ fwriter:=twpofilewriter.create(fn);
+ end;
+
+ procedure twpoinfomanagerbase.parseandcheckwpoinfo;
+ var
+ i: longint;
+ begin
+ { error if we don't have to optimize yet have an input feedback file }
+ if (init_settings.dowpoptimizerswitches=[]) and
+ assigned(freader) then
+ begin
+ cgmessage(wpo_input_without_info_use);
+ exit;
+ end;
+
+ { error if we have to optimize yet don't have an input feedback file }
+ if (init_settings.dowpoptimizerswitches<>[]) and
+ not assigned(freader) then
+ begin
+ cgmessage(wpo_no_input_specified);
+ exit;
+ end;
+
+ { if we have to generate wpo information, check that a file has been
+ specified and that we have something to write to it
+ }
+ if (init_settings.genwpoptimizerswitches<>[]) and
+ not assigned(fwriter) then
+ begin
+ cgmessage(wpo_no_output_specified);
+ exit;
+ end;
+
+ if (init_settings.genwpoptimizerswitches=[]) and
+ assigned(fwriter) then
+ begin
+ cgmessage(wpo_output_without_info_gen);
+ exit;
+ end;
+
+ { now read the input feedback file }
+ if assigned(freader) then
+ begin
+ freader.processfile;
+ freader.free;
+ freader:=nil;
+ end;
+
+ { and for each specified optimization check whether the input feedback
+ file contained the necessary information
+ }
+ if (([cs_wpo_devirtualize_calls,cs_wpo_optimize_vmts] * init_settings.dowpoptimizerswitches) <> []) and
+ not assigned(wpoinfouse[wpo_devirtualization_context_insensitive]) then
+ begin
+ cgmessage1(wpo_not_enough_info,wpo2str[wpo_devirtualization_context_insensitive]);
+ exit;
+ end;
+
+ if (cs_wpo_symbol_liveness in init_settings.dowpoptimizerswitches) and
+ not assigned(wpoinfouse[wpo_live_symbol_information]) then
+ begin
+ cgmessage1(wpo_not_enough_info,wpo2str[wpo_live_symbol_information]);
+ exit;
+ end;
+
+ { perform pre-checking to ensure there are no known incompatibilities between
+ the selected optimizations and other switches
+ }
+ for i:=0 to fwpocomponents.count-1 do
+ if (twpocomponentbaseclass(fwpocomponents[i]).generatesinfoforwposwitches*init_settings.genwpoptimizerswitches)<>[] then
+ twpocomponentbaseclass(fwpocomponents[i]).checkoptions
+ end;
+
+ procedure twpoinfomanagerbase.extractwpoinfofromprogram;
+ var
+ i: longint;
+ info: twpocomponentbase;
+ begin
+ { if don't have to write anything, fwriter has not been created }
+ if not assigned(fwriter) then
+ exit;
+
+ { let all wpo components gather the necessary info from the compiler state }
+ for i:=0 to fwpocomponents.count-1 do
+ if (twpocomponentbaseclass(fwpocomponents[i]).generatesinfoforwposwitches*current_settings.genwpoptimizerswitches)<>[] then
+ begin
+ info:=twpocomponentbaseclass(fwpocomponents[i]).create;
+ info.constructfromcompilerstate;
+ fwriter.registerwpocomponent(info);
+ end;
+ { and write their info to disk }
+ fwriter.writefile;
+ fwriter.free;
+ fwriter:=nil;
+ end;
+
+ constructor twpoinfomanagerbase.create;
+ begin
+ inherited create;
+ fwpocomponents:=tfphashlist.create;
+ end;
+
+ destructor twpoinfomanagerbase.destroy;
+ var
+ i: twpotype;
+ begin
+ freader.free;
+ freader:=nil;
+ fwriter.free;
+ fwriter:=nil;
+ fwpocomponents.free;
+ fwpocomponents:=nil;
+ for i:=low(wpoinfouse) to high(wpoinfouse) do
+ if assigned(wpoinfouse[i]) then
+ wpoinfouse[i].free;
+ inherited destroy;
+ end;
+
+ { tcalledvmtentries }
+
+ constructor tcalledvmtentries.create(_objdef: tdef; nentries: longint);
+ begin
+ objdef:=_objdef;
+ calledentries:=tbitset.create(nentries);
+ end;
+
+
+ constructor tcalledvmtentries.ppuload(ppufile: tcompilerppufile);
+ var
+ len: longint;
+ begin
+ ppufile.getderef(fobjdefderef);
+ len:=ppufile.getlongint;
+ calledentries:=tbitset.create_bytesize(len);
+ if (len <> calledentries.datasize) then
+ internalerror(2009060301);
+ ppufile.readdata(calledentries.data^,len);
+ end;
+
+
+ destructor tcalledvmtentries.destroy;
+ begin
+ fcalledentries.free;
+ inherited destroy;
+ end;
+
+
+ procedure tcalledvmtentries.ppuwrite(ppufile: tcompilerppufile);
+ begin
+ ppufile.putderef(objdefderef);
+ ppufile.putlongint(calledentries.datasize);
+ ppufile.putdata(calledentries.data^,calledentries.datasize);
+ end;
+
+
+ procedure tcalledvmtentries.buildderef;
+ begin
+ objdefderef.build(objdef);
+ end;
+
+
+ procedure tcalledvmtentries.buildderefimpl;
+ begin
+ end;
+
+
+ procedure tcalledvmtentries.deref;
+ begin
+ objdef:=tdef(objdefderef.resolve);
+ end;
+
+
+ procedure tcalledvmtentries.derefimpl;
+ begin
+ end;
+
+end.
diff --git a/closures/compiler/wpoinfo.pas b/closures/compiler/wpoinfo.pas
new file mode 100644
index 0000000000..d43da1bf63
--- /dev/null
+++ b/closures/compiler/wpoinfo.pas
@@ -0,0 +1,329 @@
+{
+ Copyright (c) 2008 by Jonas Maebe
+
+ Whole program optimisation information collection
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ ****************************************************************************
+}
+
+unit wpoinfo;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ cclasses,
+ symtype,
+ wpobase,
+ ppu;
+
+type
+ pderefarray = ^tderefarray;
+ tderefarray = array[0..1024*1024-1] of tderef;
+
+ tunitwpoinfo = class(tunitwpoinfobase)
+ { devirtualisation information -- begin }
+ private
+ fcreatedobjtypesderefs: pderefarray;
+ fcreatedclassrefobjtypesderefs: pderefarray;
+ fmaybecreatedbyclassrefdeftypesderefs: pderefarray;
+ fcalledvmtentriestemplist: tfpobjectlist;
+ { devirtualisation information -- end }
+
+ procedure clearderefinfo;
+ public
+
+ destructor destroy; override;
+
+ procedure ppuwrite(ppufile:tcompilerppufile);
+ constructor ppuload(ppufile:tcompilerppufile);
+
+ procedure deref;
+ procedure derefimpl;
+ procedure buildderef;
+ procedure buildderefimpl;
+ end;
+
+
+ { twpoinfomanager }
+
+ twpoinfomanager = class(twpoinfomanagerbase)
+ function can_be_devirtualized(objdef, procdef: tdef; out name: shortstring): boolean; override;
+ function optimized_name_for_vmt(objdef, procdef: tdef; out name: shortstring): boolean; override;
+ function symbol_live(const name: shortstring): boolean; override;
+ end;
+
+
+implementation
+
+ uses
+ globtype,
+ globals,
+ symdef,
+ verbose;
+
+ procedure tunitwpoinfo.clearderefinfo;
+ begin
+ if assigned(fcreatedobjtypesderefs) then
+ begin
+ freemem(fcreatedobjtypesderefs);
+ fcreatedobjtypesderefs:=nil;
+ end;
+ if assigned(fcreatedclassrefobjtypesderefs) then
+ begin
+ freemem(fcreatedclassrefobjtypesderefs);
+ fcreatedclassrefobjtypesderefs:=nil;
+ end;
+ if assigned(fmaybecreatedbyclassrefdeftypesderefs) then
+ begin
+ freemem(fmaybecreatedbyclassrefdeftypesderefs);
+ fmaybecreatedbyclassrefdeftypesderefs:=nil;
+ end;
+
+ if assigned(fcalledvmtentriestemplist) then
+ begin
+ fcalledvmtentriestemplist.free;
+ fcalledvmtentriestemplist:=nil;
+ end;
+ end;
+
+ destructor tunitwpoinfo.destroy;
+ begin
+ clearderefinfo;
+ inherited destroy;
+ end;
+
+
+ procedure tunitwpoinfo.ppuwrite(ppufile:tcompilerppufile);
+ var
+ i: longint;
+ begin
+ { write the number of instantiated object types in this module,
+ followed by the derefs of those types
+ }
+ ppufile.putlongint(fcreatedobjtypes.count);
+ for i:=0 to fcreatedobjtypes.count-1 do
+ ppufile.putderef(fcreatedobjtypesderefs^[i]);
+ ppufile.putlongint(fcreatedclassrefobjtypes.count);
+ for i:=0 to fcreatedclassrefobjtypes.count-1 do
+ ppufile.putderef(fcreatedclassrefobjtypesderefs^[i]);
+ ppufile.putlongint(fmaybecreatedbyclassrefdeftypes.count);
+ for i:=0 to fmaybecreatedbyclassrefdeftypes.count-1 do
+ ppufile.putderef(fmaybecreatedbyclassrefdeftypesderefs^[i]);
+
+ ppufile.putlongint(fcalledvmtentriestemplist.count);
+ for i:=0 to fcalledvmtentriestemplist.count-1 do
+ tcalledvmtentries(fcalledvmtentriestemplist[i]).ppuwrite(ppufile);
+
+ ppufile.writeentry(ibcreatedobjtypes);
+
+ { don't free deref arrays immediately after use, as the types may need
+ re-resolving in case a unit needs to be reloaded
+ }
+ end;
+
+
+ constructor tunitwpoinfo.ppuload(ppufile:tcompilerppufile);
+ var
+ i, len: longint;
+ begin
+ { load start of definition section, which holds the amount of defs }
+ if ppufile.readentry<>ibcreatedobjtypes then
+ cgmessage(unit_f_ppu_read_error);
+
+ { don't load the wpo info from the units if we are not generating
+ a wpo feedback file (that would just take time and memory)
+ }
+ if (init_settings.genwpoptimizerswitches=[]) then
+ ppufile.skipdata(ppufile.entrysize)
+ else
+ begin
+ len:=ppufile.getlongint;
+ fcreatedobjtypes:=tfpobjectlist.create(false);
+ fcreatedobjtypes.count:=len;
+ getmem(fcreatedobjtypesderefs,len*sizeof(tderef));
+ for i:=0 to len-1 do
+ ppufile.getderef(fcreatedobjtypesderefs^[i]);
+
+ len:=ppufile.getlongint;
+ fcreatedclassrefobjtypes:=tfpobjectlist.create(false);
+ fcreatedclassrefobjtypes.count:=len;
+ getmem(fcreatedclassrefobjtypesderefs,len*sizeof(tderef));
+ for i:=0 to len-1 do
+ ppufile.getderef(fcreatedclassrefobjtypesderefs^[i]);
+
+ len:=ppufile.getlongint;
+ fmaybecreatedbyclassrefdeftypes:=tfpobjectlist.create(false);
+ fmaybecreatedbyclassrefdeftypes.count:=len;
+ getmem(fmaybecreatedbyclassrefdeftypesderefs,len*sizeof(tderef));
+ for i:=0 to len-1 do
+ ppufile.getderef(fmaybecreatedbyclassrefdeftypesderefs^[i]);
+
+ len:=ppufile.getlongint;
+ fcalledvmtentriestemplist:=tfpobjectlist.create(false);
+ fcalledvmtentriestemplist.count:=len;
+ fcalledvmtentries:=tfphashlist.create;
+ for i:=0 to len-1 do
+ fcalledvmtentriestemplist[i]:=tcalledvmtentries.ppuload(ppufile);
+ end;
+ end;
+
+
+ procedure tunitwpoinfo.buildderef;
+ var
+ i: longint;
+ begin
+ { ppuload may have already been called before -> deref info structures
+ may already have been allocated }
+ clearderefinfo;
+
+ getmem(fcreatedobjtypesderefs,fcreatedobjtypes.count*sizeof(tderef));
+ for i:=0 to fcreatedobjtypes.count-1 do
+ fcreatedobjtypesderefs^[i].build(fcreatedobjtypes[i]);
+
+ getmem(fcreatedclassrefobjtypesderefs,fcreatedclassrefobjtypes.count*sizeof(tderef));
+ for i:=0 to fcreatedclassrefobjtypes.count-1 do
+ fcreatedclassrefobjtypesderefs^[i].build(fcreatedclassrefobjtypes[i]);
+
+ getmem(fmaybecreatedbyclassrefdeftypesderefs,fmaybecreatedbyclassrefdeftypes.count*sizeof(tderef));
+ for i:=0 to fmaybecreatedbyclassrefdeftypes.count-1 do
+ fmaybecreatedbyclassrefdeftypesderefs^[i].build(fmaybecreatedbyclassrefdeftypes[i]);
+
+ fcalledvmtentriestemplist:=tfpobjectlist.create(false);
+ fcalledvmtentriestemplist.count:=fcalledvmtentries.count;
+ for i:=0 to fcalledvmtentries.count-1 do
+ begin
+ tcalledvmtentries(fcalledvmtentries[i]).buildderef;
+ { necessary in case we have unit1 loads unit2, unit2 is recompiled,
+ then unit1 derefs unit2 -> in this case we have buildderef for unit2
+ -> ppuwrite for unit2 -> deref for unit2 (without a load) -> ensure
+ that the fcalledvmtentriestemplist, normally constructed by ppuload,
+ is created here as well since deref needs it }
+ fcalledvmtentriestemplist[i]:=tobject(fcalledvmtentries[i]);
+ end;
+ end;
+
+
+ procedure tunitwpoinfo.buildderefimpl;
+ var
+ i: longint;
+ begin
+ for i:=0 to fcalledvmtentriestemplist.count-1 do
+ begin
+ tcalledvmtentries(fcalledvmtentriestemplist[i]).buildderefimpl;
+ end;
+ end;
+
+
+ procedure tunitwpoinfo.deref;
+ var
+ i: longint;
+
+ begin
+ if (init_settings.genwpoptimizerswitches=[]) or
+ not assigned(fcalledvmtentriestemplist) then
+ exit;
+
+ { don't free deref arrays immediately after use, as the types may need
+ re-resolving in case a unit needs to be reloaded
+ }
+ for i:=0 to fcreatedobjtypes.count-1 do
+ fcreatedobjtypes[i]:=fcreatedobjtypesderefs^[i].resolve;
+
+ for i:=0 to fcreatedclassrefobjtypes.count-1 do
+ fcreatedclassrefobjtypes[i]:=fcreatedclassrefobjtypesderefs^[i].resolve;
+
+ for i:=0 to fmaybecreatedbyclassrefdeftypes.count-1 do
+ fmaybecreatedbyclassrefdeftypes[i]:=fmaybecreatedbyclassrefdeftypesderefs^[i].resolve;
+
+ { in case we are re-resolving, free previous batch }
+ if (fcalledvmtentries.count<>0) then
+ fcalledvmtentries.clear;
+ { allocate enough internal memory in one go }
+ fcalledvmtentries.capacity:=fcalledvmtentriestemplist.count;
+ { now resolve all items in the list and add them to the hash table }
+ for i:=0 to fcalledvmtentriestemplist.count-1 do
+ begin
+ with tcalledvmtentries(fcalledvmtentriestemplist[i]) do
+ begin
+ deref;
+ fcalledvmtentries.add(tobjectdef(objdef).vmt_mangledname,
+ fcalledvmtentriestemplist[i]);
+ end;
+ end;
+ end;
+
+
+ procedure tunitwpoinfo.derefimpl;
+ var
+ i: longint;
+ begin
+ if (init_settings.genwpoptimizerswitches=[]) or
+ not assigned(fcalledvmtentriestemplist) then
+ exit;
+
+ for i:=0 to fcalledvmtentriestemplist.count-1 do
+ begin
+ tcalledvmtentries(fcalledvmtentriestemplist[i]).derefimpl;
+ end;
+ end;
+
+
+ { twpoinfomanager }
+
+ { devirtualisation }
+
+ function twpoinfomanager.can_be_devirtualized(objdef, procdef: tdef; out name: shortstring): boolean;
+ begin
+ if not assigned(wpoinfouse[wpo_devirtualization_context_insensitive]) or
+ not(cs_wpo_devirtualize_calls in current_settings.dowpoptimizerswitches) then
+ begin
+ result:=false;
+ exit;
+ end;
+ result:=twpodevirtualisationhandler(wpoinfouse[wpo_devirtualization_context_insensitive]).staticnameforcallingvirtualmethod(objdef,procdef,name);
+ end;
+
+
+ function twpoinfomanager.optimized_name_for_vmt(objdef, procdef: tdef; out name: shortstring): boolean;
+ begin
+ if not assigned(wpoinfouse[wpo_devirtualization_context_insensitive]) or
+ not(cs_wpo_optimize_vmts in current_settings.dowpoptimizerswitches) then
+ begin
+ result:=false;
+ exit;
+ end;
+ result:=twpodevirtualisationhandler(wpoinfouse[wpo_devirtualization_context_insensitive]).staticnameforvmtentry(objdef,procdef,name);
+ end;
+
+
+ { symbol liveness }
+
+ function twpoinfomanager.symbol_live(const name: shortstring): boolean;
+ begin
+ if not assigned(wpoinfouse[wpo_live_symbol_information]) or
+ not(cs_wpo_symbol_liveness in current_settings.dowpoptimizerswitches) then
+ begin
+ { if we don't know, say that the symbol is live }
+ result:=true;
+ exit;
+ end;
+ result:=twpodeadcodehandler(wpoinfouse[wpo_live_symbol_information]).symbolinfinalbinary(name);
+ end;
+
+
+end.
diff --git a/closures/compiler/x86/aasmcpu.pas b/closures/compiler/x86/aasmcpu.pas
new file mode 100644
index 0000000000..dc7d7cee8a
--- /dev/null
+++ b/closures/compiler/x86/aasmcpu.pas
@@ -0,0 +1,2626 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl and Peter Vreman
+
+ Contains the abstract assembler implementation for the i386
+
+ * Portions of this code was inspired by the NASM sources
+ The Netwide Assembler is Copyright (c) 1996 Simon Tatham and
+ Julian Hall. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit aasmcpu;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ globtype,verbose,
+ cpubase,
+ cgbase,cgutils,
+ symtype,
+ aasmbase,aasmtai,aasmdata,aasmsym,
+ ogbase;
+
+ const
+ { "mov reg,reg" source operand number }
+ O_MOV_SOURCE = 0;
+ { "mov reg,reg" destination operand number }
+ O_MOV_DEST = 1;
+
+ { Operand types }
+ OT_NONE = $00000000;
+
+ { Bits 0..7: sizes }
+ OT_BITS8 = $00000001;
+ OT_BITS16 = $00000002;
+ OT_BITS32 = $00000004;
+ OT_BITS64 = $00000008; { x86_64 and FPU }
+ OT_BITS80 = $00000010; { FPU only }
+ OT_FAR = $00000020; { this means 16:16 or 16:32, like in CALL/JMP }
+ OT_NEAR = $00000040;
+ OT_SHORT = $00000080;
+
+ { TODO: FAR/NEAR/SHORT are sizes too, they should be included into size mask,
+ but this requires adjusting the opcode table }
+ OT_SIZE_MASK = $0000001F; { all the size attributes }
+ OT_NON_SIZE = longint(not OT_SIZE_MASK);
+
+ { Bits 8..11: modifiers }
+ OT_SIGNED = $00000100; { the operand need to be signed -128-127 }
+ OT_TO = $00000200; { reverse effect in FADD, FSUB &c }
+ OT_COLON = $00000400; { operand is followed by a colon }
+ OT_MODIFIER_MASK = $00000F00;
+
+ { Bits 12..15: type of operand }
+ OT_REGISTER = $00001000;
+ OT_IMMEDIATE = $00002000;
+ OT_MEMORY = $0000C000; { always includes 'OT_REGMEM' bit as well }
+ OT_REGMEM = $00008000; { for r/m, ie EA, operands }
+ OT_TYPE_MASK = OT_REGISTER or OT_IMMEDIATE or OT_MEMORY or OT_REGMEM;
+
+ OT_REGNORM = OT_REGISTER or OT_REGMEM; { 'normal' reg, qualifies as EA }
+
+ { Bits 20..22, 24..26: register classes
+ otf_* consts are not used alone, only to build other constants. }
+ otf_reg_cdt = $00100000;
+ otf_reg_gpr = $00200000;
+ otf_reg_sreg = $00400000;
+ otf_reg_fpu = $01000000;
+ otf_reg_mmx = $02000000;
+ otf_reg_xmm = $04000000;
+ { Bits 16..19: subclasses, meaning depends on classes field }
+ otf_sub0 = $00010000;
+ otf_sub1 = $00020000;
+ otf_sub2 = $00040000;
+ otf_sub3 = $00080000;
+ OT_REG_SMASK = otf_sub0 or otf_sub1 or otf_sub2 or otf_sub3;
+
+ { register class 0: CRx, DRx and TRx }
+{$ifdef x86_64}
+ OT_REG_CDT = OT_REGISTER or otf_reg_cdt or OT_BITS64;
+{$else x86_64}
+ OT_REG_CDT = OT_REGISTER or otf_reg_cdt or OT_BITS32;
+{$endif x86_64}
+ OT_REG_CREG = OT_REG_CDT or otf_sub0; { CRn }
+ OT_REG_DREG = OT_REG_CDT or otf_sub1; { DRn }
+ OT_REG_TREG = OT_REG_CDT or otf_sub2; { TRn }
+ OT_REG_CR4 = OT_REG_CDT or otf_sub3; { CR4 (Pentium only) }
+
+ { register class 1: general-purpose registers }
+ OT_REG_GPR = OT_REGNORM or otf_reg_gpr;
+ OT_RM_GPR = OT_REGMEM or otf_reg_gpr;
+ OT_REG8 = OT_REG_GPR or OT_BITS8; { 8-bit GPR }
+ OT_REG16 = OT_REG_GPR or OT_BITS16;
+ OT_REG32 = OT_REG_GPR or OT_BITS32;
+ OT_REG64 = OT_REG_GPR or OT_BITS64;
+
+ { GPR subclass 0: accumulator: AL, AX, EAX or RAX }
+ OT_REG_ACCUM = OT_REG_GPR or otf_sub0;
+ OT_REG_AL = OT_REG_ACCUM or OT_BITS8;
+ OT_REG_AX = OT_REG_ACCUM or OT_BITS16;
+ OT_REG_EAX = OT_REG_ACCUM or OT_BITS32;
+{$ifdef x86_64}
+ OT_REG_RAX = OT_REG_ACCUM or OT_BITS64;
+{$endif x86_64}
+ { GPR subclass 1: counter: CL, CX, ECX or RCX }
+ OT_REG_COUNT = OT_REG_GPR or otf_sub1;
+ OT_REG_CL = OT_REG_COUNT or OT_BITS8;
+ OT_REG_CX = OT_REG_COUNT or OT_BITS16;
+ OT_REG_ECX = OT_REG_COUNT or OT_BITS32;
+{$ifdef x86_64}
+ OT_REG_RCX = OT_REG_COUNT or OT_BITS64;
+{$endif x86_64}
+ { GPR subclass 2: data register: DL, DX, EDX or RDX }
+ OT_REG_DX = OT_REG_GPR or otf_sub2 or OT_BITS16;
+ OT_REG_EDX = OT_REG_GPR or otf_sub2 or OT_BITS32;
+
+ { register class 2: Segment registers }
+ OT_REG_SREG = OT_REGISTER or otf_reg_sreg or OT_BITS16;
+ OT_REG_CS = OT_REG_SREG or otf_sub0; { CS }
+ OT_REG_DESS = OT_REG_SREG or otf_sub1; { DS, ES, SS (non-CS 86 registers) }
+ OT_REG_FSGS = OT_REG_SREG or otf_sub2; { FS, GS (386 extended registers) }
+
+ { register class 3: FPU registers }
+ OT_FPUREG = OT_REGISTER or otf_reg_fpu;
+ OT_FPU0 = OT_FPUREG or otf_sub0; { FPU stack register zero }
+
+ { register class 4: MMX (both reg and r/m) }
+ OT_MMXREG = OT_REGNORM or otf_reg_mmx;
+ OT_MMXRM = OT_REGMEM or otf_reg_mmx;
+
+ { register class 5: XMM (both reg and r/m) }
+ OT_XMMREG = OT_REGNORM or otf_reg_xmm;
+ OT_XMMRM = OT_REGMEM or otf_reg_xmm;
+
+ { Memory operands }
+ OT_MEM8 = OT_MEMORY or OT_BITS8;
+ OT_MEM16 = OT_MEMORY or OT_BITS16;
+ OT_MEM32 = OT_MEMORY or OT_BITS32;
+ OT_MEM64 = OT_MEMORY or OT_BITS64;
+ OT_MEM80 = OT_MEMORY or OT_BITS80;
+
+ OT_MEM_OFFS = OT_MEMORY or otf_sub0; { special type of EA }
+ { simple [address] offset }
+
+ { Matches any type of r/m operand }
+ OT_MEMORY_ANY = OT_MEMORY or OT_RM_GPR or OT_XMMRM or OT_MMXRM;
+
+ { Immediate operands }
+ OT_IMM8 = OT_IMMEDIATE or OT_BITS8;
+ OT_IMM16 = OT_IMMEDIATE or OT_BITS16;
+ OT_IMM32 = OT_IMMEDIATE or OT_BITS32;
+ OT_IMM64 = OT_IMMEDIATE or OT_BITS64;
+
+ OT_ONENESS = otf_sub0; { special type of immediate operand }
+ OT_UNITY = OT_IMMEDIATE or OT_ONENESS; { for shift/rotate instructions }
+
+ { Size of the instruction table converted by nasmconv.pas }
+{$ifdef x86_64}
+ instabentries = {$i x8664nop.inc}
+{$else x86_64}
+ instabentries = {$i i386nop.inc}
+{$endif x86_64}
+ maxinfolen = 8;
+ MaxInsChanges = 3; { Max things a instruction can change }
+
+ type
+ { What an instruction can change. Needed for optimizer and spilling code.
+
+ Note: The order of this enumeration is should not be changed! }
+ TInsChange = (Ch_None,
+ {Read from a register}
+ Ch_REAX, Ch_RECX, Ch_REDX, Ch_REBX, Ch_RESP, Ch_REBP, Ch_RESI, Ch_REDI,
+ {write from a register}
+ Ch_WEAX, Ch_WECX, Ch_WEDX, Ch_WEBX, Ch_WESP, Ch_WEBP, Ch_WESI, Ch_WEDI,
+ {read and write from/to a register}
+ Ch_RWEAX, Ch_RWECX, Ch_RWEDX, Ch_RWEBX, Ch_RWESP, Ch_RWEBP, Ch_RWESI, Ch_RWEDI,
+ {modify the contents of a register with the purpose of using
+ this changed content afterwards (add/sub/..., but e.g. not rep
+ or movsd)}
+ Ch_MEAX, Ch_MECX, Ch_MEDX, Ch_MEBX, Ch_MESP, Ch_MEBP, Ch_MESI, Ch_MEDI,
+ Ch_CDirFlag {clear direction flag}, Ch_SDirFlag {set dir flag},
+ Ch_RFlags, Ch_WFlags, Ch_RWFlags, Ch_FPU,
+ Ch_Rop1, Ch_Wop1, Ch_RWop1,Ch_Mop1,
+ Ch_Rop2, Ch_Wop2, Ch_RWop2,Ch_Mop2,
+ Ch_Rop3, Ch_WOp3, Ch_RWOp3,Ch_Mop3,
+ Ch_WMemEDI,
+ Ch_All,
+ { x86_64 registers }
+ Ch_RRAX, Ch_RRCX, Ch_RRDX, Ch_RRBX, Ch_RRSP, Ch_RRBP, Ch_RRSI, Ch_RRDI,
+ Ch_WRAX, Ch_WRCX, Ch_WRDX, Ch_WRBX, Ch_WRSP, Ch_WRBP, Ch_WRSI, Ch_WRDI,
+ Ch_RWRAX, Ch_RWRCX, Ch_RWRDX, Ch_RWRBX, Ch_RWRSP, Ch_RWRBP, Ch_RWRSI, Ch_RWRDI,
+ Ch_MRAX, Ch_MRCX, Ch_MRDX, Ch_MRBX, Ch_MRSP, Ch_MRBP, Ch_MRSI, Ch_MRDI
+ );
+
+ TInsProp = packed record
+ Ch : Array[1..MaxInsChanges] of TInsChange;
+ end;
+
+ const
+ InsProp : array[tasmop] of TInsProp =
+{$ifdef x86_64}
+ {$i x8664pro.inc}
+{$else x86_64}
+ {$i i386prop.inc}
+{$endif x86_64}
+
+ type
+ TOperandOrder = (op_intel,op_att);
+
+ tinsentry=packed record
+ opcode : tasmop;
+ ops : byte;
+ optypes : array[0..max_operands-1] of longint;
+ code : array[0..maxinfolen] of char;
+ flags : cardinal;
+ end;
+ pinsentry=^tinsentry;
+
+ { alignment for operator }
+ tai_align = class(tai_align_abstract)
+ reg : tregister;
+ constructor create(b:byte);override;
+ constructor create_op(b: byte; _op: byte);override;
+ function calculatefillbuf(var buf : tfillbuffer;executable : boolean):pchar;override;
+ end;
+
+ taicpu = class(tai_cpu_abstract_sym)
+ opsize : topsize;
+ constructor op_none(op : tasmop);
+ constructor op_none(op : tasmop;_size : topsize);
+
+ constructor op_reg(op : tasmop;_size : topsize;_op1 : tregister);
+ constructor op_const(op : tasmop;_size : topsize;_op1 : aint);
+ constructor op_ref(op : tasmop;_size : topsize;const _op1 : treference);
+
+ constructor op_reg_reg(op : tasmop;_size : topsize;_op1,_op2 : tregister);
+ constructor op_reg_ref(op : tasmop;_size : topsize;_op1 : tregister;const _op2 : treference);
+ constructor op_reg_const(op:tasmop; _size: topsize; _op1: tregister; _op2: aint);
+
+ constructor op_const_reg(op : tasmop;_size : topsize;_op1 : aint;_op2 : tregister);
+ constructor op_const_const(op : tasmop;_size : topsize;_op1,_op2 : aint);
+ constructor op_const_ref(op : tasmop;_size : topsize;_op1 : aint;const _op2 : treference);
+
+ constructor op_ref_reg(op : tasmop;_size : topsize;const _op1 : treference;_op2 : tregister);
+
+ constructor op_reg_reg_reg(op : tasmop;_size : topsize;_op1,_op2,_op3 : tregister);
+ constructor op_const_reg_reg(op : tasmop;_size : topsize;_op1 : aint;_op2 : tregister;_op3 : tregister);
+ constructor op_const_ref_reg(op : tasmop;_size : topsize;_op1 : aint;const _op2 : treference;_op3 : tregister);
+ constructor op_reg_reg_ref(op : tasmop;_size : topsize;_op1,_op2 : tregister; const _op3 : treference);
+ constructor op_const_reg_ref(op : tasmop;_size : topsize;_op1 : aint;_op2 : tregister;const _op3 : treference);
+
+ { this is for Jmp instructions }
+ constructor op_cond_sym(op : tasmop;cond:TAsmCond;_size : topsize;_op1 : tasmsymbol);
+
+ constructor op_sym(op : tasmop;_size : topsize;_op1 : tasmsymbol);
+ constructor op_sym_ofs(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint);
+ constructor op_sym_ofs_reg(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint;_op2 : tregister);
+ constructor op_sym_ofs_ref(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint;const _op2 : treference);
+
+ procedure changeopsize(siz:topsize);
+
+ function GetString:string;
+ procedure CheckNonCommutativeOpcodes;
+ private
+ FOperandOrder : TOperandOrder;
+ procedure init(_size : topsize); { this need to be called by all constructor }
+ public
+ { the next will reset all instructions that can change in pass 2 }
+ procedure ResetPass1;override;
+ procedure ResetPass2;override;
+ function CheckIfValid:boolean;
+ function Pass1(objdata:TObjData):longint;override;
+ procedure Pass2(objdata:TObjData);override;
+ procedure SetOperandOrder(order:TOperandOrder);
+ function is_same_reg_move(regtype: Tregistertype):boolean;override;
+ { register spilling code }
+ function spilling_get_operation_type(opnr: longint): topertype;override;
+ private
+ { next fields are filled in pass1, so pass2 is faster }
+ insentry : PInsEntry;
+ insoffset : longint;
+ LastInsOffset : longint; { need to be public to be reset }
+ inssize : shortint;
+{$ifdef x86_64}
+ rex : byte;
+{$endif x86_64}
+ function InsEnd:longint;
+ procedure create_ot(objdata:TObjData);
+ function Matches(p:PInsEntry):boolean;
+ function calcsize(p:PInsEntry):shortint;
+ procedure gencode(objdata:TObjData);
+ function NeedAddrPrefix(opidx:byte):boolean;
+ procedure Swapoperands;
+ function FindInsentry(objdata:TObjData):boolean;
+ end;
+
+ function spilling_create_load(const ref:treference;r:tregister):Taicpu;
+ function spilling_create_store(r:tregister; const ref:treference):Taicpu;
+
+ procedure InitAsm;
+ procedure DoneAsm;
+
+
+implementation
+
+ uses
+ cutils,
+ globals,
+ systems,
+ procinfo,
+ itcpugas,
+ symsym;
+
+{*****************************************************************************
+ Instruction table
+*****************************************************************************}
+
+ const
+ {Instruction flags }
+ IF_NONE = $00000000;
+ IF_SM = $00000001; { size match first two operands }
+ IF_SM2 = $00000002;
+ IF_SB = $00000004; { unsized operands can't be non-byte }
+ IF_SW = $00000008; { unsized operands can't be non-word }
+ IF_SD = $00000010; { unsized operands can't be nondword }
+ IF_SMASK = $0000001f;
+ IF_AR0 = $00000020; { SB, SW, SD applies to argument 0 }
+ IF_AR1 = $00000040; { SB, SW, SD applies to argument 1 }
+ IF_AR2 = $00000060; { SB, SW, SD applies to argument 2 }
+ IF_ARMASK = $00000060; { mask for unsized argument spec }
+ IF_ARSHIFT = 5; { LSB of IF_ARMASK }
+ IF_PRIV = $00000100; { it's a privileged instruction }
+ IF_SMM = $00000200; { it's only valid in SMM }
+ IF_PROT = $00000400; { it's protected mode only }
+ IF_NOX86_64 = $00000800; { removed instruction in x86_64 }
+ IF_UNDOC = $00001000; { it's an undocumented instruction }
+ IF_FPU = $00002000; { it's an FPU instruction }
+ IF_MMX = $00004000; { it's an MMX instruction }
+ { it's a 3DNow! instruction }
+ IF_3DNOW = $00008000;
+ { it's a SSE (KNI, MMX2) instruction }
+ IF_SSE = $00010000;
+ { SSE2 instructions }
+ IF_SSE2 = $00020000;
+ { SSE3 instructions }
+ IF_SSE3 = $00040000;
+ { SSE64 instructions }
+ IF_SSE64 = $00080000;
+ { the mask for processor types }
+ {IF_PMASK = longint($FF000000);}
+ { the mask for disassembly "prefer" }
+ {IF_PFMASK = longint($F001FF00);}
+ { SVM instructions }
+ IF_SVM = $00100000;
+ { SSE4 instructions }
+ IF_SSE4 = $00200000;
+ { TODO: These flags were added to make x86ins.dat more readable.
+ Values must be reassigned to make any other use of them. }
+ IF_SSSE3 = $00200000;
+ IF_SSE41 = $00200000;
+ IF_SSE42 = $00200000;
+
+ IF_8086 = $00000000; { 8086 instruction }
+ IF_186 = $01000000; { 186+ instruction }
+ IF_286 = $02000000; { 286+ instruction }
+ IF_386 = $03000000; { 386+ instruction }
+ IF_486 = $04000000; { 486+ instruction }
+ IF_PENT = $05000000; { Pentium instruction }
+ IF_P6 = $06000000; { P6 instruction }
+ IF_KATMAI = $07000000; { Katmai instructions }
+ { Willamette instructions }
+ IF_WILLAMETTE = $08000000;
+ { Prescott instructions }
+ IF_PRESCOTT = $09000000;
+ IF_X86_64 = $0a000000;
+ IF_CYRIX = $0b000000; { Cyrix-specific instruction }
+ IF_AMD = $0c000000; { AMD-specific instruction }
+ IF_CENTAUR = $0d000000; { centaur-specific instruction }
+ { added flags }
+ IF_PRE = $40000000; { it's a prefix instruction }
+ IF_PASS2 = $80000000; { if the instruction can change in a second pass }
+
+ type
+ TInsTabCache=array[TasmOp] of longint;
+ PInsTabCache=^TInsTabCache;
+
+ const
+{$ifdef x86_64}
+ InsTab:array[0..instabentries-1] of TInsEntry={$i x8664tab.inc}
+{$else x86_64}
+ InsTab:array[0..instabentries-1] of TInsEntry={$i i386tab.inc}
+{$endif x86_64}
+ var
+ InsTabCache : PInsTabCache;
+
+ const
+{$ifdef x86_64}
+ { Intel style operands ! }
+ opsize_2_type:array[0..2,topsize] of longint=(
+ (OT_NONE,
+ OT_BITS8,OT_BITS16,OT_BITS32,OT_BITS64,OT_BITS16,OT_BITS32,OT_BITS32,OT_BITS64,OT_BITS64,OT_BITS64,
+ OT_BITS16,OT_BITS32,OT_BITS64,
+ OT_BITS32,OT_BITS64,OT_BITS80,OT_BITS64,OT_NONE,
+ OT_BITS64,
+ OT_NEAR,OT_FAR,OT_SHORT,
+ OT_NONE,
+ OT_NONE
+ ),
+ (OT_NONE,
+ OT_BITS8,OT_BITS16,OT_BITS32,OT_BITS64,OT_BITS8,OT_BITS8,OT_BITS16,OT_BITS8,OT_BITS16,OT_BITS32,
+ OT_BITS16,OT_BITS32,OT_BITS64,
+ OT_BITS32,OT_BITS64,OT_BITS80,OT_BITS64,OT_NONE,
+ OT_BITS64,
+ OT_NEAR,OT_FAR,OT_SHORT,
+ OT_NONE,
+ OT_NONE
+ ),
+ (OT_NONE,
+ OT_BITS8,OT_BITS16,OT_BITS32,OT_BITS64,OT_NONE,OT_NONE,OT_NONE,OT_NONE,OT_NONE,OT_NONE,
+ OT_BITS16,OT_BITS32,OT_BITS64,
+ OT_BITS32,OT_BITS64,OT_BITS80,OT_BITS64,OT_NONE,
+ OT_BITS64,
+ OT_NEAR,OT_FAR,OT_SHORT,
+ OT_NONE,
+ OT_NONE
+ )
+ );
+
+ reg_ot_table : array[tregisterindex] of longint = (
+ {$i r8664ot.inc}
+ );
+{$else x86_64}
+ { Intel style operands ! }
+ opsize_2_type:array[0..2,topsize] of longint=(
+ (OT_NONE,
+ OT_BITS8,OT_BITS16,OT_BITS32,OT_BITS64,OT_BITS16,OT_BITS32,OT_BITS32,
+ OT_BITS16,OT_BITS32,OT_BITS64,
+ OT_BITS32,OT_BITS64,OT_BITS80,OT_BITS64,OT_NONE,
+ OT_BITS64,
+ OT_NEAR,OT_FAR,OT_SHORT,
+ OT_NONE,
+ OT_NONE
+ ),
+ (OT_NONE,
+ OT_BITS8,OT_BITS16,OT_BITS32,OT_BITS64,OT_BITS8,OT_BITS8,OT_BITS16,
+ OT_BITS16,OT_BITS32,OT_BITS64,
+ OT_BITS32,OT_BITS64,OT_BITS80,OT_BITS64,OT_NONE,
+ OT_BITS64,
+ OT_NEAR,OT_FAR,OT_SHORT,
+ OT_NONE,
+ OT_NONE
+ ),
+ (OT_NONE,
+ OT_BITS8,OT_BITS16,OT_BITS32,OT_BITS64,OT_NONE,OT_NONE,OT_NONE,
+ OT_BITS16,OT_BITS32,OT_BITS64,
+ OT_BITS32,OT_BITS64,OT_BITS80,OT_BITS64,OT_NONE,
+ OT_BITS64,
+ OT_NEAR,OT_FAR,OT_SHORT,
+ OT_NONE,
+ OT_NONE
+ )
+ );
+
+ reg_ot_table : array[tregisterindex] of longint = (
+ {$i r386ot.inc}
+ );
+{$endif x86_64}
+
+ { Operation type for spilling code }
+ type
+ toperation_type_table=array[tasmop,0..Max_Operands] of topertype;
+ var
+ operation_type_table : ^toperation_type_table;
+
+
+{****************************************************************************
+ TAI_ALIGN
+ ****************************************************************************}
+
+ constructor tai_align.create(b: byte);
+ begin
+ inherited create(b);
+ reg:=NR_ECX;
+ end;
+
+
+ constructor tai_align.create_op(b: byte; _op: byte);
+ begin
+ inherited create_op(b,_op);
+ reg:=NR_NO;
+ end;
+
+
+ function tai_align.calculatefillbuf(var buf : tfillbuffer;executable : boolean):pchar;
+ const
+{$ifdef x86_64}
+ alignarray:array[0..3] of string[4]=(
+ #$66#$66#$66#$90,
+ #$66#$66#$90,
+ #$66#$90,
+ #$90
+ );
+{$else x86_64}
+ alignarray:array[0..5] of string[8]=(
+ #$8D#$B4#$26#$00#$00#$00#$00,
+ #$8D#$B6#$00#$00#$00#$00,
+ #$8D#$74#$26#$00,
+ #$8D#$76#$00,
+ #$89#$F6,
+ #$90);
+{$endif x86_64}
+ var
+ bufptr : pchar;
+ j : longint;
+ localsize: byte;
+ begin
+ inherited calculatefillbuf(buf,executable);
+ if not(use_op) and executable then
+ begin
+ bufptr:=pchar(@buf);
+ { fillsize may still be used afterwards, so don't modify }
+ { e.g. writebytes(hp.calculatefillbuf(buf)^,hp.fillsize) }
+ localsize:=fillsize;
+ while (localsize>0) do
+ begin
+ for j:=low(alignarray) to high(alignarray) do
+ if (localsize>=length(alignarray[j])) then
+ break;
+ move(alignarray[j][1],bufptr^,length(alignarray[j]));
+ inc(bufptr,length(alignarray[j]));
+ dec(localsize,length(alignarray[j]));
+ end;
+ end;
+ calculatefillbuf:=pchar(@buf);
+ end;
+
+
+{*****************************************************************************
+ Taicpu Constructors
+*****************************************************************************}
+
+ procedure taicpu.changeopsize(siz:topsize);
+ begin
+ opsize:=siz;
+ end;
+
+
+ procedure taicpu.init(_size : topsize);
+ begin
+ { default order is att }
+ FOperandOrder:=op_att;
+ segprefix:=NR_NO;
+ opsize:=_size;
+ insentry:=nil;
+ LastInsOffset:=-1;
+ InsOffset:=0;
+ InsSize:=0;
+ end;
+
+
+ constructor taicpu.op_none(op : tasmop);
+ begin
+ inherited create(op);
+ init(S_NO);
+ end;
+
+
+ constructor taicpu.op_none(op : tasmop;_size : topsize);
+ begin
+ inherited create(op);
+ init(_size);
+ end;
+
+
+ constructor taicpu.op_reg(op : tasmop;_size : topsize;_op1 : tregister);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=1;
+ loadreg(0,_op1);
+ end;
+
+
+ constructor taicpu.op_const(op : tasmop;_size : topsize;_op1 : aint);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=1;
+ loadconst(0,_op1);
+ end;
+
+
+ constructor taicpu.op_ref(op : tasmop;_size : topsize;const _op1 : treference);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=1;
+ loadref(0,_op1);
+ end;
+
+
+ constructor taicpu.op_reg_reg(op : tasmop;_size : topsize;_op1,_op2 : tregister);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=2;
+ loadreg(0,_op1);
+ loadreg(1,_op2);
+ end;
+
+
+ constructor taicpu.op_reg_const(op:tasmop; _size: topsize; _op1: tregister; _op2: aint);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=2;
+ loadreg(0,_op1);
+ loadconst(1,_op2);
+ end;
+
+
+ constructor taicpu.op_reg_ref(op : tasmop;_size : topsize;_op1 : tregister;const _op2 : treference);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=2;
+ loadreg(0,_op1);
+ loadref(1,_op2);
+ end;
+
+
+ constructor taicpu.op_const_reg(op : tasmop;_size : topsize;_op1 : aint;_op2 : tregister);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=2;
+ loadconst(0,_op1);
+ loadreg(1,_op2);
+ end;
+
+
+ constructor taicpu.op_const_const(op : tasmop;_size : topsize;_op1,_op2 : aint);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=2;
+ loadconst(0,_op1);
+ loadconst(1,_op2);
+ end;
+
+
+ constructor taicpu.op_const_ref(op : tasmop;_size : topsize;_op1 : aint;const _op2 : treference);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=2;
+ loadconst(0,_op1);
+ loadref(1,_op2);
+ end;
+
+
+ constructor taicpu.op_ref_reg(op : tasmop;_size : topsize;const _op1 : treference;_op2 : tregister);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=2;
+ loadref(0,_op1);
+ loadreg(1,_op2);
+ end;
+
+
+ constructor taicpu.op_reg_reg_reg(op : tasmop;_size : topsize;_op1,_op2,_op3 : tregister);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=3;
+ loadreg(0,_op1);
+ loadreg(1,_op2);
+ loadreg(2,_op3);
+ end;
+
+
+ constructor taicpu.op_const_reg_reg(op : tasmop;_size : topsize;_op1 : aint;_op2 : tregister;_op3 : tregister);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=3;
+ loadconst(0,_op1);
+ loadreg(1,_op2);
+ loadreg(2,_op3);
+ end;
+
+
+ constructor taicpu.op_reg_reg_ref(op : tasmop;_size : topsize;_op1,_op2 : tregister;const _op3 : treference);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=3;
+ loadreg(0,_op1);
+ loadreg(1,_op2);
+ loadref(2,_op3);
+ end;
+
+
+ constructor taicpu.op_const_ref_reg(op : tasmop;_size : topsize;_op1 : aint;const _op2 : treference;_op3 : tregister);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=3;
+ loadconst(0,_op1);
+ loadref(1,_op2);
+ loadreg(2,_op3);
+ end;
+
+
+ constructor taicpu.op_const_reg_ref(op : tasmop;_size : topsize;_op1 : aint;_op2 : tregister;const _op3 : treference);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=3;
+ loadconst(0,_op1);
+ loadreg(1,_op2);
+ loadref(2,_op3);
+ end;
+
+
+ constructor taicpu.op_cond_sym(op : tasmop;cond:TAsmCond;_size : topsize;_op1 : tasmsymbol);
+ begin
+ inherited create(op);
+ init(_size);
+ condition:=cond;
+ ops:=1;
+ loadsymbol(0,_op1,0);
+ end;
+
+
+ constructor taicpu.op_sym(op : tasmop;_size : topsize;_op1 : tasmsymbol);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=1;
+ loadsymbol(0,_op1,0);
+ end;
+
+
+ constructor taicpu.op_sym_ofs(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=1;
+ loadsymbol(0,_op1,_op1ofs);
+ end;
+
+
+ constructor taicpu.op_sym_ofs_reg(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint;_op2 : tregister);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=2;
+ loadsymbol(0,_op1,_op1ofs);
+ loadreg(1,_op2);
+ end;
+
+
+ constructor taicpu.op_sym_ofs_ref(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint;const _op2 : treference);
+ begin
+ inherited create(op);
+ init(_size);
+ ops:=2;
+ loadsymbol(0,_op1,_op1ofs);
+ loadref(1,_op2);
+ end;
+
+
+ function taicpu.GetString:string;
+ var
+ i : longint;
+ s : string;
+ addsize : boolean;
+ begin
+ s:='['+std_op2str[opcode];
+ for i:=0 to ops-1 do
+ begin
+ with oper[i]^ do
+ begin
+ if i=0 then
+ s:=s+' '
+ else
+ s:=s+',';
+ { type }
+ addsize:=false;
+ if (ot and OT_XMMREG)=OT_XMMREG then
+ s:=s+'xmmreg'
+ else
+ if (ot and OT_MMXREG)=OT_MMXREG then
+ s:=s+'mmxreg'
+ else
+ if (ot and OT_FPUREG)=OT_FPUREG then
+ s:=s+'fpureg'
+ else
+ if (ot and OT_REGISTER)=OT_REGISTER then
+ begin
+ s:=s+'reg';
+ addsize:=true;
+ end
+ else
+ if (ot and OT_IMMEDIATE)=OT_IMMEDIATE then
+ begin
+ s:=s+'imm';
+ addsize:=true;
+ end
+ else
+ if (ot and OT_MEMORY)=OT_MEMORY then
+ begin
+ s:=s+'mem';
+ addsize:=true;
+ end
+ else
+ s:=s+'???';
+ { size }
+ if addsize then
+ begin
+ if (ot and OT_BITS8)<>0 then
+ s:=s+'8'
+ else
+ if (ot and OT_BITS16)<>0 then
+ s:=s+'16'
+ else
+ if (ot and OT_BITS32)<>0 then
+ s:=s+'32'
+ else
+ if (ot and OT_BITS64)<>0 then
+ s:=s+'64'
+ else
+ s:=s+'??';
+ { signed }
+ if (ot and OT_SIGNED)<>0 then
+ s:=s+'s';
+ end;
+ end;
+ end;
+ GetString:=s+']';
+ end;
+
+
+ procedure taicpu.Swapoperands;
+ var
+ p : POper;
+ begin
+ { Fix the operands which are in AT&T style and we need them in Intel style }
+ case ops of
+ 0,1:
+ ;
+ 2 : begin
+ { 0,1 -> 1,0 }
+ p:=oper[0];
+ oper[0]:=oper[1];
+ oper[1]:=p;
+ end;
+ 3 : begin
+ { 0,1,2 -> 2,1,0 }
+ p:=oper[0];
+ oper[0]:=oper[2];
+ oper[2]:=p;
+ end;
+ 4 : begin
+ { 0,1,2,3 -> 3,2,1,0 }
+ p:=oper[0];
+ oper[0]:=oper[3];
+ oper[3]:=p;
+ p:=oper[1];
+ oper[1]:=oper[2];
+ oper[2]:=p;
+ end;
+ else
+ internalerror(201108141);
+ end;
+ end;
+
+
+ procedure taicpu.SetOperandOrder(order:TOperandOrder);
+ begin
+ if FOperandOrder<>order then
+ begin
+ Swapoperands;
+ FOperandOrder:=order;
+ end;
+ end;
+
+
+ procedure taicpu.CheckNonCommutativeOpcodes;
+ begin
+ { we need ATT order }
+ SetOperandOrder(op_att);
+
+ if (
+ (ops=2) and
+ (oper[0]^.typ=top_reg) and
+ (oper[1]^.typ=top_reg) and
+ { if the first is ST and the second is also a register
+ it is necessarily ST1 .. ST7 }
+ ((oper[0]^.reg=NR_ST) or
+ (oper[0]^.reg=NR_ST0))
+ ) or
+ { ((ops=1) and
+ (oper[0]^.typ=top_reg) and
+ (oper[0]^.reg in [R_ST1..R_ST7])) or}
+ (ops=0) then
+ begin
+ if opcode=A_FSUBR then
+ opcode:=A_FSUB
+ else if opcode=A_FSUB then
+ opcode:=A_FSUBR
+ else if opcode=A_FDIVR then
+ opcode:=A_FDIV
+ else if opcode=A_FDIV then
+ opcode:=A_FDIVR
+ else if opcode=A_FSUBRP then
+ opcode:=A_FSUBP
+ else if opcode=A_FSUBP then
+ opcode:=A_FSUBRP
+ else if opcode=A_FDIVRP then
+ opcode:=A_FDIVP
+ else if opcode=A_FDIVP then
+ opcode:=A_FDIVRP;
+ end;
+ if (
+ (ops=1) and
+ (oper[0]^.typ=top_reg) and
+ (getregtype(oper[0]^.reg)=R_FPUREGISTER) and
+ (oper[0]^.reg<>NR_ST)
+ ) then
+ begin
+ if opcode=A_FSUBRP then
+ opcode:=A_FSUBP
+ else if opcode=A_FSUBP then
+ opcode:=A_FSUBRP
+ else if opcode=A_FDIVRP then
+ opcode:=A_FDIVP
+ else if opcode=A_FDIVP then
+ opcode:=A_FDIVRP;
+ end;
+ end;
+
+
+{*****************************************************************************
+ Assembler
+*****************************************************************************}
+
+ type
+ ea = packed record
+ sib_present : boolean;
+ bytes : byte;
+ size : byte;
+ modrm : byte;
+ sib : byte;
+{$ifdef x86_64}
+ rex : byte;
+{$endif x86_64}
+ end;
+
+ procedure taicpu.create_ot(objdata:TObjData);
+ {
+ this function will also fix some other fields which only needs to be once
+ }
+ var
+ i,l,relsize : longint;
+ currsym : TObjSymbol;
+ begin
+ if ops=0 then
+ exit;
+ { update oper[].ot field }
+ for i:=0 to ops-1 do
+ with oper[i]^ do
+ begin
+ case typ of
+ top_reg :
+ begin
+ ot:=reg_ot_table[findreg_by_number(reg)];
+ end;
+ top_ref :
+ begin
+ if (ref^.refaddr=addr_no)
+{$ifdef i386}
+ or (
+ (ref^.refaddr in [addr_pic]) and
+ { allow any base for assembler blocks }
+ ((assigned(current_procinfo) and
+ (pi_has_assembler_block in current_procinfo.flags) and
+ (ref^.base<>NR_NO)) or (ref^.base=NR_EBX))
+ )
+{$endif i386}
+{$ifdef x86_64}
+ or (
+ (ref^.refaddr in [addr_pic,addr_pic_no_got]) and
+ (ref^.base<>NR_NO)
+ )
+{$endif x86_64}
+ then
+ begin
+ { create ot field }
+ if (ot and OT_SIZE_MASK)=0 then
+ ot:=OT_MEMORY_ANY or opsize_2_type[i,opsize]
+ else
+ ot:=OT_MEMORY_ANY or (ot and OT_SIZE_MASK);
+ if (ref^.base=NR_NO) and (ref^.index=NR_NO) then
+ ot:=ot or OT_MEM_OFFS;
+ { fix scalefactor }
+ if (ref^.index=NR_NO) then
+ ref^.scalefactor:=0
+ else
+ if (ref^.scalefactor=0) then
+ ref^.scalefactor:=1;
+ end
+ else
+ begin
+ { Jumps use a relative offset which can be 8bit,
+ for other opcodes we always need to generate the full
+ 32bit address }
+ if assigned(objdata) and
+ is_jmp then
+ begin
+ currsym:=objdata.symbolref(ref^.symbol);
+ l:=ref^.offset;
+ if assigned(currsym) then
+ inc(l,currsym.address);
+ { when it is a forward jump we need to compensate the
+ offset of the instruction since the previous time,
+ because the symbol address is then still using the
+ 'old-style' addressing.
+ For backwards jumps this is not required because the
+ address of the symbol is already adjusted to the
+ new offset }
+ if (l>InsOffset) and (LastInsOffset<>-1) then
+ inc(l,InsOffset-LastInsOffset);
+ { instruction size will then always become 2 (PFV) }
+ relsize:=(InsOffset+2)-l;
+ if (relsize>=-128) and (relsize<=127) and
+ (
+ not assigned(currsym) or
+ (currsym.objsection=objdata.currobjsec)
+ ) then
+ ot:=OT_IMM8 or OT_SHORT
+ else
+ ot:=OT_IMM32 or OT_NEAR;
+ end
+ else
+ ot:=OT_IMM32 or OT_NEAR;
+ end;
+ end;
+ top_local :
+ begin
+ if (ot and OT_SIZE_MASK)=0 then
+ ot:=OT_MEMORY or opsize_2_type[i,opsize]
+ else
+ ot:=OT_MEMORY or (ot and OT_SIZE_MASK);
+ end;
+ top_const :
+ begin
+ { allow 2nd, 3rd or 4th operand being a constant and expect no size for shuf* etc. }
+ { further, allow AAD and AAM with imm. operand }
+ if (opsize=S_NO) and not((i in [1,2,3]) or ((i=0) and (opcode in [A_AAD,A_AAM]))) then
+ message(asmr_e_invalid_opcode_and_operand);
+ if (opsize<>S_W) and (aint(val)>=-128) and (val<=127) then
+ ot:=OT_IMM8 or OT_SIGNED
+ else
+ ot:=OT_IMMEDIATE or opsize_2_type[i,opsize];
+ if (val=1) and (i=1) then
+ ot := ot or OT_ONENESS;
+ end;
+ top_none :
+ begin
+ { generated when there was an error in the
+ assembler reader. It never happends when generating
+ assembler }
+ end;
+ else
+ internalerror(200402261);
+ end;
+ end;
+ end;
+
+
+ function taicpu.InsEnd:longint;
+ begin
+ InsEnd:=InsOffset+InsSize;
+ end;
+
+
+ function taicpu.Matches(p:PInsEntry):boolean;
+ { * IF_SM stands for Size Match: any operand whose size is not
+ * explicitly specified by the template is `really' intended to be
+ * the same size as the first size-specified operand.
+ * Non-specification is tolerated in the input instruction, but
+ * _wrong_ specification is not.
+ *
+ * IF_SM2 invokes Size Match on only the first _two_ operands, for
+ * three-operand instructions such as SHLD: it implies that the
+ * first two operands must match in size, but that the third is
+ * required to be _unspecified_.
+ *
+ * IF_SB invokes Size Byte: operands with unspecified size in the
+ * template are really bytes, and so no non-byte specification in
+ * the input instruction will be tolerated. IF_SW similarly invokes
+ * Size Word, and IF_SD invokes Size Doubleword.
+ *
+ * (The default state if neither IF_SM nor IF_SM2 is specified is
+ * that any operand with unspecified size in the template is
+ * required to have unspecified size in the instruction too...)
+ }
+ var
+ insot,
+ currot,
+ i,j,asize,oprs : longint;
+ insflags:cardinal;
+ siz : array[0..max_operands-1] of longint;
+ begin
+ result:=false;
+
+ { Check the opcode and operands }
+ if (p^.opcode<>opcode) or (p^.ops<>ops) then
+ exit;
+
+ for i:=0 to p^.ops-1 do
+ begin
+ insot:=p^.optypes[i];
+ currot:=oper[i]^.ot;
+ { Check the operand flags }
+ if (insot and (not currot) and OT_NON_SIZE)<>0 then
+ exit;
+ { Check if the passed operand size matches with one of
+ the supported operand sizes }
+ if ((insot and OT_SIZE_MASK)<>0) and
+ ((insot and currot and OT_SIZE_MASK)<>(currot and OT_SIZE_MASK)) then
+ exit;
+ end;
+
+ { Check operand sizes }
+ insflags:=p^.flags;
+ if insflags and IF_SMASK<>0 then
+ begin
+ { as default an untyped size can get all the sizes, this is different
+ from nasm, but else we need to do a lot checking which opcodes want
+ size or not with the automatic size generation }
+ asize:=-1;
+ if (insflags and IF_SB)<>0 then
+ asize:=OT_BITS8
+ else if (insflags and IF_SW)<>0 then
+ asize:=OT_BITS16
+ else if (insflags and IF_SD)<>0 then
+ asize:=OT_BITS32;
+ if (insflags and IF_ARMASK)<>0 then
+ begin
+ siz[0]:=-1;
+ siz[1]:=-1;
+ siz[2]:=-1;
+ siz[((insflags and IF_ARMASK) shr IF_ARSHIFT)-1]:=asize;
+ end
+ else
+ begin
+ siz[0]:=asize;
+ siz[1]:=asize;
+ siz[2]:=asize;
+ end;
+
+ if (insflags and (IF_SM or IF_SM2))<>0 then
+ begin
+ if (insflags and IF_SM2)<>0 then
+ oprs:=2
+ else
+ oprs:=p^.ops;
+ for i:=0 to oprs-1 do
+ if ((p^.optypes[i] and OT_SIZE_MASK) <> 0) then
+ begin
+ for j:=0 to oprs-1 do
+ siz[j]:=p^.optypes[i] and OT_SIZE_MASK;
+ break;
+ end;
+ end
+ else
+ oprs:=2;
+
+ { Check operand sizes }
+ for i:=0 to p^.ops-1 do
+ begin
+ insot:=p^.optypes[i];
+ currot:=oper[i]^.ot;
+ if ((insot and OT_SIZE_MASK)=0) and
+ ((currot and OT_SIZE_MASK and (not siz[i]))<>0) and
+ { Immediates can always include smaller size }
+ ((currot and OT_IMMEDIATE)=0) and
+ (((insot and OT_SIZE_MASK) or siz[i])<(currot and OT_SIZE_MASK)) then
+ exit;
+ end;
+ end;
+
+ result:=true;
+ end;
+
+
+ procedure taicpu.ResetPass1;
+ begin
+ { we need to reset everything here, because the choosen insentry
+ can be invalid for a new situation where the previously optimized
+ insentry is not correct }
+ InsEntry:=nil;
+ InsSize:=0;
+ LastInsOffset:=-1;
+ end;
+
+
+ procedure taicpu.ResetPass2;
+ begin
+ { we are here in a second pass, check if the instruction can be optimized }
+ if assigned(InsEntry) and
+ ((InsEntry^.flags and IF_PASS2)<>0) then
+ begin
+ InsEntry:=nil;
+ InsSize:=0;
+ end;
+ LastInsOffset:=-1;
+ end;
+
+
+ function taicpu.CheckIfValid:boolean;
+ begin
+ result:=FindInsEntry(nil);
+ end;
+
+
+ function taicpu.FindInsentry(objdata:TObjData):boolean;
+ var
+ i : longint;
+ begin
+ result:=false;
+ { Things which may only be done once, not when a second pass is done to
+ optimize }
+ if (Insentry=nil) or ((InsEntry^.flags and IF_PASS2)<>0) then
+ begin
+ current_filepos:=fileinfo;
+ { We need intel style operands }
+ SetOperandOrder(op_intel);
+ { create the .ot fields }
+ create_ot(objdata);
+ { set the file postion }
+ end
+ else
+ begin
+ { we've already an insentry so it's valid }
+ result:=true;
+ exit;
+ end;
+ { Lookup opcode in the table }
+ InsSize:=-1;
+ i:=instabcache^[opcode];
+ if i=-1 then
+ begin
+ Message1(asmw_e_opcode_not_in_table,gas_op2str[opcode]);
+ exit;
+ end;
+ insentry:=@instab[i];
+ while (insentry^.opcode=opcode) do
+ begin
+ if matches(insentry) then
+ begin
+ result:=true;
+ exit;
+ end;
+ inc(insentry);
+ end;
+ Message1(asmw_e_invalid_opcode_and_operands,GetString);
+ { No instruction found, set insentry to nil and inssize to -1 }
+ insentry:=nil;
+ inssize:=-1;
+ end;
+
+
+ function taicpu.Pass1(objdata:TObjData):longint;
+ begin
+ Pass1:=0;
+ { Save the old offset and set the new offset }
+ InsOffset:=ObjData.CurrObjSec.Size;
+ { Error? }
+ if (Insentry=nil) and (InsSize=-1) then
+ exit;
+ { set the file postion }
+ current_filepos:=fileinfo;
+ { Get InsEntry }
+ if FindInsEntry(ObjData) then
+ begin
+ { Calculate instruction size }
+ InsSize:=calcsize(insentry);
+ if segprefix<>NR_NO then
+ inc(InsSize);
+ { Fix opsize if size if forced }
+ if (insentry^.flags and (IF_SB or IF_SW or IF_SD))<>0 then
+ begin
+ if (insentry^.flags and IF_ARMASK)=0 then
+ begin
+ if (insentry^.flags and IF_SB)<>0 then
+ begin
+ if opsize=S_NO then
+ opsize:=S_B;
+ end
+ else if (insentry^.flags and IF_SW)<>0 then
+ begin
+ if opsize=S_NO then
+ opsize:=S_W;
+ end
+ else if (insentry^.flags and IF_SD)<>0 then
+ begin
+ if opsize=S_NO then
+ opsize:=S_L;
+ end;
+ end;
+ end;
+ LastInsOffset:=InsOffset;
+ Pass1:=InsSize;
+ exit;
+ end;
+ LastInsOffset:=-1;
+ end;
+
+ const
+ segprefixes: array[NR_CS..NR_GS] of Byte=(
+ //cs ds es ss fs gs
+ $2E, $3E, $26, $36, $64, $65
+ );
+
+ procedure taicpu.Pass2(objdata:TObjData);
+ begin
+ { error in pass1 ? }
+ if insentry=nil then
+ exit;
+ current_filepos:=fileinfo;
+ { Segment override }
+ if (segprefix>=NR_CS) and (segprefix<=NR_GS) then
+ begin
+ objdata.writebytes(segprefixes[segprefix],1);
+ { fix the offset for GenNode }
+ inc(InsOffset);
+ end
+ else if segprefix<>NR_NO then
+ InternalError(201001071);
+ { Generate the instruction }
+ GenCode(objdata);
+ end;
+
+
+ function taicpu.needaddrprefix(opidx:byte):boolean;
+ begin
+ result:=(oper[opidx]^.typ=top_ref) and
+ (oper[opidx]^.ref^.refaddr=addr_no) and
+ {$ifdef x86_64}
+ (oper[opidx]^.ref^.base<>NR_RIP) and
+ {$endif x86_64}
+ (
+ (
+ (oper[opidx]^.ref^.index<>NR_NO) and
+ (getsubreg(oper[opidx]^.ref^.index)<>R_SUBADDR)
+ ) or
+ (
+ (oper[opidx]^.ref^.base<>NR_NO) and
+ (getsubreg(oper[opidx]^.ref^.base)<>R_SUBADDR)
+ )
+ );
+ end;
+
+
+ function regval(r:Tregister):byte;
+ const
+ {$ifdef x86_64}
+ opcode_table:array[tregisterindex] of tregisterindex = (
+ {$i r8664op.inc}
+ );
+ {$else x86_64}
+ opcode_table:array[tregisterindex] of tregisterindex = (
+ {$i r386op.inc}
+ );
+ {$endif x86_64}
+ var
+ regidx : tregisterindex;
+ begin
+ regidx:=findreg_by_number(r);
+ if regidx<>0 then
+ result:=opcode_table[regidx]
+ else
+ begin
+ Message1(asmw_e_invalid_register,generic_regname(r));
+ result:=0;
+ end;
+ end;
+
+
+{$ifdef x86_64}
+ function rexbits(r: tregister): byte;
+ begin
+ result:=0;
+ case getregtype(r) of
+ R_INTREGISTER:
+ if (getsupreg(r)>=RS_R8) then
+ { Either B,X or R bits can be set, depending on register role in instruction.
+ Set all three bits here, caller will discard unnecessary ones. }
+ result:=result or $47
+ else if (getsubreg(r)=R_SUBL) and
+ (getsupreg(r) in [RS_RDI,RS_RSI,RS_RBP,RS_RSP]) then
+ result:=result or $40
+ else if (getsubreg(r)=R_SUBH) then
+ { Not an actual REX bit, used to detect incompatible usage of
+ AH/BH/CH/DH }
+ result:=result or $80;
+ R_MMREGISTER:
+ if getsupreg(r)>=RS_XMM8 then
+ result:=result or $47;
+ end;
+ end;
+
+ function process_ea(const input:toper;out output:ea;rfield:longint):boolean;
+ var
+ sym : tasmsymbol;
+ md,s,rv : byte;
+ base,index,scalefactor,
+ o : longint;
+ ir,br : Tregister;
+ isub,bsub : tsubregister;
+ begin
+ process_ea:=false;
+ fillchar(output,sizeof(output),0);
+ {Register ?}
+ if (input.typ=top_reg) then
+ begin
+ rv:=regval(input.reg);
+ output.modrm:=$c0 or (rfield shl 3) or rv;
+ output.size:=1;
+ output.rex:=output.rex or (rexbits(input.reg) and $F1);
+ process_ea:=true;
+
+ exit;
+ end;
+ {No register, so memory reference.}
+ if input.typ<>top_ref then
+ internalerror(200409263);
+ ir:=input.ref^.index;
+ br:=input.ref^.base;
+ isub:=getsubreg(ir);
+ bsub:=getsubreg(br);
+ s:=input.ref^.scalefactor;
+ o:=input.ref^.offset;
+ sym:=input.ref^.symbol;
+ if ((ir<>NR_NO) and (getregtype(ir)<>R_INTREGISTER)) or
+ ((br<>NR_NO) and (br<>NR_RIP) and (getregtype(br)<>R_INTREGISTER)) then
+ internalerror(200301081);
+ { it's direct address }
+ if (br=NR_NO) and (ir=NR_NO) then
+ begin
+ output.sib_present:=true;
+ output.bytes:=4;
+ output.modrm:=4 or (rfield shl 3);
+ output.sib:=$25;
+ end
+ else if (br=NR_RIP) and (ir=NR_NO) then
+ begin
+ { rip based }
+ output.sib_present:=false;
+ output.bytes:=4;
+ output.modrm:=5 or (rfield shl 3);
+ end
+ else
+ { it's an indirection }
+ begin
+ { 16 bit or 32 bit address? }
+ if ((ir<>NR_NO) and (isub<>R_SUBADDR)) or
+ ((br<>NR_NO) and (bsub<>R_SUBADDR)) then
+ message(asmw_e_16bit_32bit_not_supported);
+ { wrong, for various reasons }
+ if (ir=NR_ESP) or ((s<>1) and (s<>2) and (s<>4) and (s<>8) and (ir<>NR_NO)) then
+ exit;
+
+ output.rex:=output.rex or (rexbits(br) and $F1) or (rexbits(ir) and $F2);
+ process_ea:=true;
+
+
+ { base }
+ case br of
+ NR_R8,
+ NR_RAX : base:=0;
+ NR_R9,
+ NR_RCX : base:=1;
+ NR_R10,
+ NR_RDX : base:=2;
+ NR_R11,
+ NR_RBX : base:=3;
+ NR_R12,
+ NR_RSP : base:=4;
+ NR_R13,
+ NR_NO,
+ NR_RBP : base:=5;
+ NR_R14,
+ NR_RSI : base:=6;
+ NR_R15,
+ NR_RDI : base:=7;
+ else
+ exit;
+ end;
+ { index }
+ case ir of
+ NR_R8,
+ NR_RAX : index:=0;
+ NR_R9,
+ NR_RCX : index:=1;
+ NR_R10,
+ NR_RDX : index:=2;
+ NR_R11,
+ NR_RBX : index:=3;
+ NR_R12,
+ NR_NO : index:=4;
+ NR_R13,
+ NR_RBP : index:=5;
+ NR_R14,
+ NR_RSI : index:=6;
+ NR_R15,
+ NR_RDI : index:=7;
+ else
+ exit;
+ end;
+ case s of
+ 0,
+ 1 : scalefactor:=0;
+ 2 : scalefactor:=1;
+ 4 : scalefactor:=2;
+ 8 : scalefactor:=3;
+ else
+ exit;
+ end;
+ { If rbp or r13 is used we must always include an offset }
+ if (br=NR_NO) or
+ ((br<>NR_RBP) and (br<>NR_R13) and (o=0) and (sym=nil)) then
+ md:=0
+ else
+ if ((o>=-128) and (o<=127) and (sym=nil)) then
+ md:=1
+ else
+ md:=2;
+ if (br=NR_NO) or (md=2) then
+ output.bytes:=4
+ else
+ output.bytes:=md;
+ { SIB needed ? }
+ if (ir=NR_NO) and (br<>NR_RSP) and (br<>NR_R12) then
+ begin
+ output.sib_present:=false;
+ output.modrm:=(md shl 6) or (rfield shl 3) or base;
+ end
+ else
+ begin
+ output.sib_present:=true;
+ output.modrm:=(md shl 6) or (rfield shl 3) or 4;
+ output.sib:=(scalefactor shl 6) or (index shl 3) or base;
+ end;
+ end;
+ output.size:=1+ord(output.sib_present)+output.bytes;
+ process_ea:=true;
+ end;
+
+
+{$else x86_64}
+
+ function process_ea(const input:toper;out output:ea;rfield:longint):boolean;
+ var
+ sym : tasmsymbol;
+ md,s,rv : byte;
+ base,index,scalefactor,
+ o : longint;
+ ir,br : Tregister;
+ isub,bsub : tsubregister;
+ begin
+ process_ea:=false;
+ fillchar(output,sizeof(output),0);
+ {Register ?}
+ if (input.typ=top_reg) then
+ begin
+ rv:=regval(input.reg);
+ output.modrm:=$c0 or (rfield shl 3) or rv;
+ output.size:=1;
+ process_ea:=true;
+ exit;
+ end;
+ {No register, so memory reference.}
+ if (input.typ<>top_ref) then
+ internalerror(200409262);
+ if ((input.ref^.index<>NR_NO) and (getregtype(input.ref^.index)<>R_INTREGISTER)) or
+ ((input.ref^.base<>NR_NO) and (getregtype(input.ref^.base)<>R_INTREGISTER)) then
+ internalerror(200301081);
+ ir:=input.ref^.index;
+ br:=input.ref^.base;
+ isub:=getsubreg(ir);
+ bsub:=getsubreg(br);
+ s:=input.ref^.scalefactor;
+ o:=input.ref^.offset;
+ sym:=input.ref^.symbol;
+ { it's direct address }
+ if (br=NR_NO) and (ir=NR_NO) then
+ begin
+ { it's a pure offset }
+ output.sib_present:=false;
+ output.bytes:=4;
+ output.modrm:=5 or (rfield shl 3);
+ end
+ else
+ { it's an indirection }
+ begin
+ { 16 bit address? }
+ if ((ir<>NR_NO) and (isub<>R_SUBADDR)) or
+ ((br<>NR_NO) and (bsub<>R_SUBADDR)) then
+ message(asmw_e_16bit_not_supported);
+{$ifdef OPTEA}
+ { make single reg base }
+ if (br=NR_NO) and (s=1) then
+ begin
+ br:=ir;
+ ir:=NR_NO;
+ end;
+ { convert [3,5,9]*EAX to EAX+[2,4,8]*EAX }
+ if (br=NR_NO) and
+ (((s=2) and (ir<>NR_ESP)) or
+ (s=3) or (s=5) or (s=9)) then
+ begin
+ br:=ir;
+ dec(s);
+ end;
+ { swap ESP into base if scalefactor is 1 }
+ if (s=1) and (ir=NR_ESP) then
+ begin
+ ir:=br;
+ br:=NR_ESP;
+ end;
+{$endif OPTEA}
+ { wrong, for various reasons }
+ if (ir=NR_ESP) or ((s<>1) and (s<>2) and (s<>4) and (s<>8) and (ir<>NR_NO)) then
+ exit;
+ { base }
+ case br of
+ NR_EAX : base:=0;
+ NR_ECX : base:=1;
+ NR_EDX : base:=2;
+ NR_EBX : base:=3;
+ NR_ESP : base:=4;
+ NR_NO,
+ NR_EBP : base:=5;
+ NR_ESI : base:=6;
+ NR_EDI : base:=7;
+ else
+ exit;
+ end;
+ { index }
+ case ir of
+ NR_EAX : index:=0;
+ NR_ECX : index:=1;
+ NR_EDX : index:=2;
+ NR_EBX : index:=3;
+ NR_NO : index:=4;
+ NR_EBP : index:=5;
+ NR_ESI : index:=6;
+ NR_EDI : index:=7;
+ else
+ exit;
+ end;
+ case s of
+ 0,
+ 1 : scalefactor:=0;
+ 2 : scalefactor:=1;
+ 4 : scalefactor:=2;
+ 8 : scalefactor:=3;
+ else
+ exit;
+ end;
+ if (br=NR_NO) or
+ ((br<>NR_EBP) and (o=0) and (sym=nil)) then
+ md:=0
+ else
+ if ((o>=-128) and (o<=127) and (sym=nil)) then
+ md:=1
+ else
+ md:=2;
+ if (br=NR_NO) or (md=2) then
+ output.bytes:=4
+ else
+ output.bytes:=md;
+ { SIB needed ? }
+ if (ir=NR_NO) and (br<>NR_ESP) then
+ begin
+ output.sib_present:=false;
+ output.modrm:=(longint(md) shl 6) or (rfield shl 3) or base;
+ end
+ else
+ begin
+ output.sib_present:=true;
+ output.modrm:=(longint(md) shl 6) or (rfield shl 3) or 4;
+ output.sib:=(scalefactor shl 6) or (index shl 3) or base;
+ end;
+ end;
+ if output.sib_present then
+ output.size:=2+output.bytes
+ else
+ output.size:=1+output.bytes;
+ process_ea:=true;
+ end;
+{$endif x86_64}
+
+ function taicpu.calcsize(p:PInsEntry):shortint;
+ var
+ codes : pchar;
+ c : byte;
+ len : shortint;
+ ea_data : ea;
+{$ifdef x86_64}
+ omit_rexw : boolean;
+{$endif x86_64}
+ begin
+ len:=0;
+ codes:=@p^.code[0];
+{$ifdef x86_64}
+ rex:=0;
+ omit_rexw:=false;
+{$endif x86_64}
+ repeat
+ c:=ord(codes^);
+ inc(codes);
+ case c of
+ 0 :
+ break;
+ 1,2,3 :
+ begin
+ inc(codes,c);
+ inc(len,c);
+ end;
+ 8,9,10 :
+ begin
+{$ifdef x86_64}
+ rex:=rex or (rexbits(oper[c-8]^.reg) and $F1);
+{$endif x86_64}
+ inc(codes);
+ inc(len);
+ end;
+ 11 :
+ begin
+ inc(codes);
+ inc(len);
+ end;
+ 4,5,6,7 :
+ begin
+ if opsize=S_W then
+ inc(len,2)
+ else
+ inc(len);
+ end;
+ 12,13,14,
+ 16,17,18,
+ 20,21,22,23,
+ 40,41,42 :
+ inc(len);
+ 24,25,26,
+ 31,
+ 48,49,50 :
+ inc(len,2);
+ 28,29,30:
+ begin
+ if opsize=S_Q then
+ inc(len,8)
+ else
+ inc(len,4);
+ end;
+ 36,37,38:
+ inc(len,sizeof(pint));
+ 44,45,46:
+ inc(len,8);
+ 32,33,34,
+ 52,53,54,
+ 56,57,58,
+ 172,173,174 :
+ inc(len,4);
+ 208,209,210 :
+ begin
+ case (oper[c-208]^.ot and OT_SIZE_MASK) of
+ OT_BITS16:
+ inc(len);
+{$ifdef x86_64}
+ OT_BITS64:
+ begin
+ rex:=rex or $48;
+ end;
+{$endif x86_64}
+ end;
+ end;
+ 200 :
+{$ifndef x86_64}
+ inc(len);
+{$else x86_64}
+ { every insentry with code 0310 must be marked with NOX86_64 }
+ InternalError(2011051301);
+{$endif x86_64}
+ 201 :
+{$ifdef x86_64}
+ inc(len)
+{$endif x86_64}
+ ;
+ 212 :
+ inc(len);
+ 214 :
+ begin
+{$ifdef x86_64}
+ rex:=rex or $48;
+{$endif x86_64}
+ end;
+ 202,
+ 211,
+ 213,
+ 215,
+ 217,218: ;
+ 219,220,241 :
+ inc(len);
+ 221:
+{$ifdef x86_64}
+ omit_rexw:=true
+{$endif x86_64}
+ ;
+ 64..151 :
+ begin
+{$ifdef x86_64}
+ if (c<127) then
+ begin
+ if (oper[c and 7]^.typ=top_reg) then
+ begin
+ rex:=rex or (rexbits(oper[c and 7]^.reg) and $F4);
+ end;
+ end;
+
+{$endif x86_64}
+ if not process_ea(oper[(c shr 3) and 7]^, ea_data, 0) then
+ Message(asmw_e_invalid_effective_address)
+ else
+ inc(len,ea_data.size);
+{$ifdef x86_64}
+ rex:=rex or ea_data.rex;
+{$endif x86_64}
+
+ end;
+ else
+ InternalError(200603141);
+ end;
+ until false;
+{$ifdef x86_64}
+ if ((rex and $80)<>0) and ((rex and $4F)<>0) then
+ Message(asmw_e_bad_reg_with_rex);
+ rex:=rex and $4F; { reset extra bits in upper nibble }
+ if omit_rexw then
+ begin
+ if rex=$48 then { remove rex entirely? }
+ rex:=0
+ else
+ rex:=rex and $F7;
+ end;
+ if rex<>0 then
+ Inc(len);
+{$endif}
+ calcsize:=len;
+ end;
+
+
+ procedure taicpu.GenCode(objdata:TObjData);
+ {
+ * the actual codes (C syntax, i.e. octal):
+ * \0 - terminates the code. (Unless it's a literal of course.)
+ * \1, \2, \3 - that many literal bytes follow in the code stream
+ * \4, \6 - the POP/PUSH (respectively) codes for CS, DS, ES, SS
+ * (POP is never used for CS) depending on operand 0
+ * \5, \7 - the second byte of POP/PUSH codes for FS, GS, depending
+ * on operand 0
+ * \10, \11, \12 - a literal byte follows in the code stream, to be added
+ * to the register value of operand 0, 1 or 2
+ * \13 - a literal byte follows in the code stream, to be added
+ * to the condition code value of the instruction.
+ * \14, \15, \16 - a signed byte immediate operand, from operand 0, 1 or 2
+ * \20, \21, \22 - a byte immediate operand, from operand 0, 1 or 2
+ * \24, \25, \26, \27 - an unsigned byte immediate operand, from operand 0, 1, 2 or 3
+ * \30, \31, \32 - a word immediate operand, from operand 0, 1 or 2
+ * \34, \35, \36 - select between \3[012] and \4[012] depending on 16/32 bit
+ * assembly mode or the address-size override on the operand
+ * \37 - a word constant, from the _segment_ part of operand 0
+ * \40, \41, \42 - a long immediate operand, from operand 0, 1 or 2
+ * \44, \45, \46 - select between \3[012], \4[012] or \5[456] depending
+ on the address size of instruction
+ * \50, \51, \52 - a byte relative operand, from operand 0, 1 or 2
+ * \54, \55, \56 - a qword immediate, from operand 0, 1 or 2
+ * \60, \61, \62 - a word relative operand, from operand 0, 1 or 2
+ * \64, \65, \66 - select between \6[012] and \7[012] depending on 16/32 bit
+ * assembly mode or the address-size override on the operand
+ * \70, \71, \72 - a long relative operand, from operand 0, 1 or 2
+ * \1ab - a ModRM, calculated on EA in operand a, with the spare
+ * field the register value of operand b.
+ * \2ab - a ModRM, calculated on EA in operand a, with the spare
+ * field equal to digit b.
+ * \254,\255,\256 - a signed 32-bit immediate to be extended to 64 bits
+ * \300,\301,\302 - might be an 0x67, depending on the address size of
+ * the memory reference in operand x.
+ * \310 - indicates fixed 16-bit address size, i.e. optional 0x67.
+ * \311 - indicates fixed 32-bit address size, i.e. optional 0x67.
+ * \312 - (disassembler only) invalid with non-default address size.
+ * \320,\321,\322 - might be an 0x66 or 0x48 byte, depending on the operand
+ * size of operand x.
+ * \324 - indicates fixed 16-bit operand size, i.e. optional 0x66.
+ * \325 - indicates fixed 32-bit operand size, i.e. optional 0x66.
+ * \326 - indicates fixed 64-bit operand size, i.e. optional 0x48.
+ * \327 - indicates that this instruction is only valid when the
+ * operand size is the default (instruction to disassembler,
+ * generates no code in the assembler)
+ * \331 - instruction not valid with REP prefix. Hint for
+ * disassembler only; for SSE instructions.
+ * \332 - disassemble a rep (0xF3 byte) prefix as repe not rep.
+ * \333 - 0xF3 prefix for SSE instructions
+ * \334 - 0xF2 prefix for SSE instructions
+ * \335 - Indicates 64-bit operand size with REX.W not necessary
+ * \361 - 0x66 prefix for SSE instructions
+ }
+
+ var
+ currval : aint;
+ currsym : tobjsymbol;
+ currrelreloc,
+ currabsreloc,
+ currabsreloc32 : TObjRelocationType;
+{$ifdef x86_64}
+ rexwritten : boolean;
+{$endif x86_64}
+
+ procedure getvalsym(opidx:longint);
+ begin
+ case oper[opidx]^.typ of
+ top_ref :
+ begin
+ currval:=oper[opidx]^.ref^.offset;
+ currsym:=ObjData.symbolref(oper[opidx]^.ref^.symbol);
+{$ifdef i386}
+ if (oper[opidx]^.ref^.refaddr=addr_pic) and
+ (tf_pic_uses_got in target_info.flags) then
+ begin
+ currrelreloc:=RELOC_PLT32;
+ currabsreloc:=RELOC_GOT32;
+ currabsreloc32:=RELOC_GOT32;
+ end
+ else
+{$endif i386}
+{$ifdef x86_64}
+ if oper[opidx]^.ref^.refaddr=addr_pic then
+ begin
+ currrelreloc:=RELOC_PLT32;
+ currabsreloc:=RELOC_GOTPCREL;
+ currabsreloc32:=RELOC_GOTPCREL;
+ end
+ else if oper[opidx]^.ref^.refaddr=addr_pic_no_got then
+ begin
+ currrelreloc:=RELOC_RELATIVE;
+ currabsreloc:=RELOC_RELATIVE;
+ currabsreloc32:=RELOC_RELATIVE;
+ end
+ else
+{$endif x86_64}
+ begin
+ currrelreloc:=RELOC_RELATIVE;
+ currabsreloc:=RELOC_ABSOLUTE;
+ currabsreloc32:=RELOC_ABSOLUTE32;
+ end;
+ end;
+ top_const :
+ begin
+ currval:=aint(oper[opidx]^.val);
+ currsym:=nil;
+ currabsreloc:=RELOC_ABSOLUTE;
+ currabsreloc32:=RELOC_ABSOLUTE32;
+ end;
+ else
+ Message(asmw_e_immediate_or_reference_expected);
+ end;
+ end;
+
+{$ifdef x86_64}
+ procedure maybewriterex;
+ begin
+ if (rex<>0) and not(rexwritten) then
+ begin
+ rexwritten:=true;
+ objdata.writebytes(rex,1);
+ end;
+ end;
+{$endif x86_64}
+ procedure objdata_writereloc(Data:aint;len:aword;p:TObjSymbol;Reloctype:TObjRelocationType);
+ begin
+{$ifdef i386}
+ { Special case of '_GLOBAL_OFFSET_TABLE_'
+ which needs a special relocation type R_386_GOTPC }
+ if assigned (p) and
+ (p.name='_GLOBAL_OFFSET_TABLE_') and
+ (tf_pic_uses_got in target_info.flags) then
+ begin
+ { nothing else than a 4 byte relocation should occur
+ for GOT }
+ if len<>4 then
+ Message1(asmw_e_invalid_opcode_and_operands,GetString);
+ Reloctype:=RELOC_GOTPC;
+ { We need to add the offset of the relocation
+ of _GLOBAL_OFFSET_TABLE symbol within
+ the current instruction }
+ inc(data,objdata.currobjsec.size-insoffset);
+ end;
+{$endif i386}
+ objdata.writereloc(data,len,p,Reloctype);
+ end;
+
+
+ const
+ CondVal:array[TAsmCond] of byte=($0,
+ $7, $3, $2, $6, $2, $4, $F, $D, $C, $E, $6, $2,
+ $3, $7, $3, $5, $E, $C, $D, $F, $1, $B, $9, $5,
+ $0, $A, $A, $B, $8, $4);
+ var
+ c : byte;
+ pb : pbyte;
+ codes : pchar;
+ bytes : array[0..3] of byte;
+ rfield,
+ data,s,opidx : longint;
+ ea_data : ea;
+ relsym : TObjSymbol;
+ begin
+ { safety check }
+ if objdata.currobjsec.size<>longword(insoffset) then
+ internalerror(200130121);
+ { load data to write }
+ codes:=insentry^.code;
+{$ifdef x86_64}
+ rexwritten:=false;
+{$endif x86_64}
+ { Force word push/pop for registers }
+ if (opsize=S_W) and ((codes[0]=#4) or (codes[0]=#6) or
+ ((codes[0]=#1) and ((codes[2]=#5) or (codes[2]=#7)))) then
+ begin
+ bytes[0]:=$66;
+ objdata.writebytes(bytes,1);
+ end;
+ repeat
+ c:=ord(codes^);
+ inc(codes);
+ case c of
+ 0 :
+ break;
+ 1,2,3 :
+ begin
+{$ifdef x86_64}
+ maybewriterex;
+{$endif x86_64}
+ objdata.writebytes(codes^,c);
+ inc(codes,c);
+ end;
+ 4,6 :
+ begin
+ case oper[0]^.reg of
+ NR_CS:
+ bytes[0]:=$e;
+ NR_NO,
+ NR_DS:
+ bytes[0]:=$1e;
+ NR_ES:
+ bytes[0]:=$6;
+ NR_SS:
+ bytes[0]:=$16;
+ else
+ internalerror(777004);
+ end;
+ if c=4 then
+ inc(bytes[0]);
+ objdata.writebytes(bytes,1);
+ end;
+ 5,7 :
+ begin
+ case oper[0]^.reg of
+ NR_FS:
+ bytes[0]:=$a0;
+ NR_GS:
+ bytes[0]:=$a8;
+ else
+ internalerror(777005);
+ end;
+ if c=5 then
+ inc(bytes[0]);
+ objdata.writebytes(bytes,1);
+ end;
+ 8,9,10 :
+ begin
+{$ifdef x86_64}
+ maybewriterex;
+{$endif x86_64}
+ bytes[0]:=ord(codes^)+regval(oper[c-8]^.reg);
+ inc(codes);
+ objdata.writebytes(bytes,1);
+ end;
+ 11 :
+ begin
+ bytes[0]:=ord(codes^)+condval[condition];
+ inc(codes);
+ objdata.writebytes(bytes,1);
+ end;
+ 12,13,14 :
+ begin
+ getvalsym(c-12);
+ if (currval<-128) or (currval>127) then
+ Message2(asmw_e_value_exceeds_bounds,'signed byte',tostr(currval));
+ if assigned(currsym) then
+ objdata_writereloc(currval,1,currsym,currabsreloc)
+ else
+ objdata.writebytes(currval,1);
+ end;
+ 16,17,18 :
+ begin
+ getvalsym(c-16);
+ if (currval<-256) or (currval>255) then
+ Message2(asmw_e_value_exceeds_bounds,'byte',tostr(currval));
+ if assigned(currsym) then
+ objdata_writereloc(currval,1,currsym,currabsreloc)
+ else
+ objdata.writebytes(currval,1);
+ end;
+ 20,21,22,23 :
+ begin
+ getvalsym(c-20);
+ if (currval<0) or (currval>255) then
+ Message2(asmw_e_value_exceeds_bounds,'unsigned byte',tostr(currval));
+ if assigned(currsym) then
+ objdata_writereloc(currval,1,currsym,currabsreloc)
+ else
+ objdata.writebytes(currval,1);
+ end;
+ 24,25,26 : // 030..032
+ begin
+ getvalsym(c-24);
+ if (currval<-65536) or (currval>65535) then
+ Message2(asmw_e_value_exceeds_bounds,'word',tostr(currval));
+ if assigned(currsym) then
+ objdata_writereloc(currval,2,currsym,currabsreloc)
+ else
+ objdata.writebytes(currval,2);
+ end;
+ 28,29,30 : // 034..036
+ { !!! These are intended (and used in opcode table) to select depending
+ on address size, *not* operand size. Works by coincidence only. }
+ begin
+ getvalsym(c-28);
+ if opsize=S_Q then
+ begin
+ if assigned(currsym) then
+ objdata_writereloc(currval,8,currsym,currabsreloc)
+ else
+ objdata.writebytes(currval,8);
+ end
+ else
+ begin
+ if assigned(currsym) then
+ objdata_writereloc(currval,4,currsym,currabsreloc32)
+ else
+ objdata.writebytes(currval,4);
+ end
+ end;
+ 32,33,34 : // 040..042
+ begin
+ getvalsym(c-32);
+ if assigned(currsym) then
+ objdata_writereloc(currval,4,currsym,currabsreloc32)
+ else
+ objdata.writebytes(currval,4);
+ end;
+ 36,37,38 : // 044..046 - select between word/dword/qword depending on
+ begin // address size (we support only default address sizes).
+ getvalsym(c-36);
+{$ifdef x86_64}
+ if assigned(currsym) then
+ objdata_writereloc(currval,8,currsym,currabsreloc)
+ else
+ objdata.writebytes(currval,8);
+{$else x86_64}
+ if assigned(currsym) then
+ objdata_writereloc(currval,4,currsym,currabsreloc32)
+ else
+ objdata.writebytes(currval,4);
+{$endif x86_64}
+ end;
+ 40,41,42 : // 050..052 - byte relative operand
+ begin
+ getvalsym(c-40);
+ data:=currval-insend;
+ if assigned(currsym) then
+ inc(data,currsym.address);
+ if (data>127) or (data<-128) then
+ Message1(asmw_e_short_jmp_out_of_range,tostr(data));
+ objdata.writebytes(data,1);
+ end;
+ 44,45,46: // 054..056 - qword immediate operand
+ begin
+ getvalsym(c-44);
+ if assigned(currsym) then
+ objdata_writereloc(currval,8,currsym,currabsreloc)
+ else
+ objdata.writebytes(currval,8);
+ end;
+ 52,53,54 : // 064..066 - select between 16/32 address mode, but we support only 32
+ begin
+ getvalsym(c-52);
+ if assigned(currsym) then
+ objdata_writereloc(currval,4,currsym,currrelreloc)
+ else
+ objdata_writereloc(currval-insend,4,nil,currabsreloc32)
+ end;
+ 56,57,58 : // 070..072 - long relative operand
+ begin
+ getvalsym(c-56);
+ if assigned(currsym) then
+ objdata_writereloc(currval,4,currsym,currrelreloc)
+ else
+ objdata_writereloc(currval-insend,4,nil,currabsreloc32)
+ end;
+ 172,173,174 : // 0254..0256 - dword implicitly sign-extended to 64-bit (x86_64 only)
+ begin
+ getvalsym(c-172);
+{$ifdef x86_64}
+ { for i386 as aint type is longint the
+ following test is useless }
+ if (currval<low(longint)) or (currval>high(longint)) then
+ Message2(asmw_e_value_exceeds_bounds,'signed dword',tostr(currval));
+{$endif x86_64}
+
+ if assigned(currsym) then
+ objdata_writereloc(currval,4,currsym,currabsreloc32)
+ else
+ objdata.writebytes(currval,4);
+ end;
+ 200 : { fixed 16-bit addr }
+{$ifndef x86_64}
+ begin
+ bytes[0]:=$67;
+ objdata.writebytes(bytes,1);
+ end;
+{$else x86_64}
+ { every insentry having code 0310 must be marked with NOX86_64 }
+ InternalError(2011051302);
+{$endif}
+ 201 : { fixed 32-bit addr }
+{$ifdef x86_64}
+ begin
+ bytes[0]:=$67;
+ objdata.writebytes(bytes,1);
+ end
+{$endif x86_64}
+ ;
+ 208,209,210 :
+ begin
+ case oper[c-208]^.ot and OT_SIZE_MASK of
+ OT_BITS16 :
+ begin
+ bytes[0]:=$66;
+ objdata.writebytes(bytes,1);
+ end;
+{$ifndef x86_64}
+ OT_BITS64 :
+ Message(asmw_e_64bit_not_supported);
+{$endif x86_64}
+ end;
+ end;
+ 211,
+ 213 : {no action needed};
+
+ 212, 241 :
+ begin
+ bytes[0]:=$66;
+ objdata.writebytes(bytes,1);
+ end;
+ 214 :
+ begin
+{$ifndef x86_64}
+ Message(asmw_e_64bit_not_supported);
+{$endif x86_64}
+ end;
+ 219 :
+ begin
+ bytes[0]:=$f3;
+ objdata.writebytes(bytes,1);
+ end;
+ 220 :
+ begin
+ bytes[0]:=$f2;
+ objdata.writebytes(bytes,1);
+ end;
+ 221:
+ ;
+ 202,
+ 215,
+ 217,218 :
+ begin
+ { these are dissambler hints or 32 bit prefixes which
+ are not needed }
+ end;
+ 31,
+ 48,49,50 :
+ begin
+ InternalError(777006);
+ end
+ else
+ begin
+ { rex should be written at this point }
+{$ifdef x86_64}
+ if (rex<>0) and not(rexwritten) then
+ internalerror(200603191);
+{$endif x86_64}
+ if (c>=64) and (c<=151) then // 0100..0227
+ begin
+ if (c<127) then // 0177
+ begin
+ if (oper[c and 7]^.typ=top_reg) then
+ rfield:=regval(oper[c and 7]^.reg)
+ else
+ rfield:=regval(oper[c and 7]^.ref^.base);
+ end
+ else
+ rfield:=c and 7;
+ opidx:=(c shr 3) and 7;
+ if not process_ea(oper[opidx]^,ea_data,rfield) then
+ Message(asmw_e_invalid_effective_address);
+
+ pb:=@bytes[0];
+ pb^:=ea_data.modrm;
+ inc(pb);
+ if ea_data.sib_present then
+ begin
+ pb^:=ea_data.sib;
+ inc(pb);
+ end;
+
+ s:=pb-@bytes[0];
+ objdata.writebytes(bytes,s);
+
+ case ea_data.bytes of
+ 0 : ;
+ 1 :
+ begin
+ if (oper[opidx]^.ot and OT_MEMORY)=OT_MEMORY then
+ begin
+ currsym:=objdata.symbolref(oper[opidx]^.ref^.symbol);
+{$ifdef i386}
+ if (oper[opidx]^.ref^.refaddr=addr_pic) and
+ (tf_pic_uses_got in target_info.flags) then
+ currabsreloc:=RELOC_GOT32
+ else
+{$endif i386}
+{$ifdef x86_64}
+ if oper[opidx]^.ref^.refaddr=addr_pic then
+ currabsreloc:=RELOC_GOTPCREL
+ else
+{$endif x86_64}
+ currabsreloc:=RELOC_ABSOLUTE;
+ objdata_writereloc(oper[opidx]^.ref^.offset,1,currsym,currabsreloc);
+ end
+ else
+ begin
+ bytes[0]:=oper[opidx]^.ref^.offset;
+ objdata.writebytes(bytes,1);
+ end;
+ inc(s);
+ end;
+ 2,4 :
+ begin
+ currsym:=objdata.symbolref(oper[opidx]^.ref^.symbol);
+ currval:=oper[opidx]^.ref^.offset;
+{$ifdef x86_64}
+ if oper[opidx]^.ref^.refaddr=addr_pic then
+ currabsreloc:=RELOC_GOTPCREL
+ else
+ if oper[opidx]^.ref^.base=NR_RIP then
+ begin
+ currabsreloc:=RELOC_RELATIVE;
+ { Adjust reloc value by number of bytes following the displacement,
+ but not if displacement is specified by literal constant }
+ if Assigned(currsym) then
+ Dec(currval,InsEnd-objdata.CurrObjSec.Size-ea_data.bytes);
+ end
+ else
+{$endif x86_64}
+{$ifdef i386}
+ if (oper[opidx]^.ref^.refaddr=addr_pic) and
+ (tf_pic_uses_got in target_info.flags) then
+ currabsreloc:=RELOC_GOT32
+ else
+{$endif i386}
+ currabsreloc:=RELOC_ABSOLUTE32;
+
+ if (currabsreloc=RELOC_ABSOLUTE32) and
+ (Assigned(oper[opidx]^.ref^.relsymbol)) then
+ begin
+ relsym:=objdata.symbolref(oper[opidx]^.ref^.relsymbol);
+ currabsreloc:=RELOC_PIC_PAIR;
+ currval:=relsym.offset;
+ end;
+ objdata_writereloc(currval,ea_data.bytes,currsym,currabsreloc);
+ inc(s,ea_data.bytes);
+ end;
+ end;
+ end
+ else
+ InternalError(777007);
+ end;
+ end;
+ until false;
+ end;
+
+
+ function taicpu.is_same_reg_move(regtype: Tregistertype):boolean;
+ begin
+ result:=(((opcode=A_MOV) or (opcode=A_XCHG)) and
+ (regtype = R_INTREGISTER) and
+ (ops=2) and
+ (oper[0]^.typ=top_reg) and
+ (oper[1]^.typ=top_reg) and
+ (oper[0]^.reg=oper[1]^.reg)
+ ) or
+ (((opcode=A_MOVSS) or (opcode=A_MOVSD) or (opcode=A_MOVQ) or
+ (opcode=A_MOVAPS) or (OPCODE=A_MOVAPD)) and
+ (regtype = R_MMREGISTER) and
+ (ops=2) and
+ (oper[0]^.typ=top_reg) and
+ (oper[1]^.typ=top_reg) and
+ (oper[0]^.reg=oper[1]^.reg)
+ );
+ end;
+
+
+ procedure build_spilling_operation_type_table;
+ var
+ opcode : tasmop;
+ i : integer;
+ begin
+ new(operation_type_table);
+ fillchar(operation_type_table^,sizeof(toperation_type_table),byte(operand_read));
+ for opcode:=low(tasmop) to high(tasmop) do
+ begin
+ for i:=1 to MaxInsChanges do
+ begin
+ case InsProp[opcode].Ch[i] of
+ Ch_Rop1 :
+ operation_type_table^[opcode,0]:=operand_read;
+ Ch_Wop1 :
+ operation_type_table^[opcode,0]:=operand_write;
+ Ch_RWop1,
+ Ch_Mop1 :
+ operation_type_table^[opcode,0]:=operand_readwrite;
+ Ch_Rop2 :
+ operation_type_table^[opcode,1]:=operand_read;
+ Ch_Wop2 :
+ operation_type_table^[opcode,1]:=operand_write;
+ Ch_RWop2,
+ Ch_Mop2 :
+ operation_type_table^[opcode,1]:=operand_readwrite;
+ Ch_Rop3 :
+ operation_type_table^[opcode,2]:=operand_read;
+ Ch_Wop3 :
+ operation_type_table^[opcode,2]:=operand_write;
+ Ch_RWop3,
+ Ch_Mop3 :
+ operation_type_table^[opcode,2]:=operand_readwrite;
+ end;
+ end;
+ end;
+ { Special cases that can't be decoded from the InsChanges flags }
+ operation_type_table^[A_IMUL,1]:=operand_readwrite;
+ end;
+
+
+ function taicpu.spilling_get_operation_type(opnr: longint): topertype;
+ begin
+ { the information in the instruction table is made for the string copy
+ operation MOVSD so hack here (FK)
+ }
+ if (opcode=A_MOVSD) and (ops=2) then
+ begin
+ case opnr of
+ 0:
+ result:=operand_read;
+ 1:
+ result:=operand_write;
+ else
+ internalerror(200506055);
+ end
+ end
+ else
+ result:=operation_type_table^[opcode,opnr];
+ end;
+
+
+ function spilling_create_load(const ref:treference;r:tregister):Taicpu;
+ begin
+ case getregtype(r) of
+ R_INTREGISTER :
+ { we don't need special code here for 32 bit loads on x86_64, since
+ those will automatically zero-extend the upper 32 bits. }
+ result:=taicpu.op_ref_reg(A_MOV,reg2opsize(r),ref,r);
+ R_MMREGISTER :
+ case getsubreg(r) of
+ R_SUBMMD:
+ result:=taicpu.op_ref_reg(A_MOVSD,reg2opsize(r),ref,r);
+ R_SUBMMS:
+ result:=taicpu.op_ref_reg(A_MOVSS,reg2opsize(r),ref,r);
+ R_SUBMMWHOLE:
+ result:=taicpu.op_ref_reg(A_MOVQ,S_NO,ref,r);
+ else
+ internalerror(200506043);
+ end;
+ else
+ internalerror(200401041);
+ end;
+ end;
+
+
+ function spilling_create_store(r:tregister; const ref:treference):Taicpu;
+ var
+ size: topsize;
+ begin
+ case getregtype(r) of
+ R_INTREGISTER :
+ begin
+ size:=reg2opsize(r);
+{$ifdef x86_64}
+ { even if it's a 32 bit reg, we still have to spill 64 bits
+ because we often perform 64 bit operations on them }
+ if (size=S_L) then
+ begin
+ size:=S_Q;
+ r:=newreg(getregtype(r),getsupreg(r),R_SUBWHOLE);
+ end;
+{$endif x86_64}
+ result:=taicpu.op_reg_ref(A_MOV,size,r,ref);
+ end;
+ R_MMREGISTER :
+ case getsubreg(r) of
+ R_SUBMMD:
+ result:=taicpu.op_reg_ref(A_MOVSD,reg2opsize(r),r,ref);
+ R_SUBMMS:
+ result:=taicpu.op_reg_ref(A_MOVSS,reg2opsize(r),r,ref);
+ R_SUBMMWHOLE:
+ result:=taicpu.op_reg_ref(A_MOVQ,S_NO,r,ref);
+ else
+ internalerror(200506042);
+ end;
+ else
+ internalerror(200401041);
+ end;
+ end;
+
+
+{*****************************************************************************
+ Instruction table
+*****************************************************************************}
+
+ procedure BuildInsTabCache;
+ var
+ i : longint;
+ begin
+ new(instabcache);
+ FillChar(instabcache^,sizeof(tinstabcache),$ff);
+ i:=0;
+ while (i<InsTabEntries) do
+ begin
+ if InsTabCache^[InsTab[i].OPcode]=-1 then
+ InsTabCache^[InsTab[i].OPcode]:=i;
+ inc(i);
+ end;
+ end;
+
+
+ procedure InitAsm;
+ begin
+ build_spilling_operation_type_table;
+ if not assigned(instabcache) then
+ BuildInsTabCache;
+ end;
+
+
+ procedure DoneAsm;
+ begin
+ if assigned(operation_type_table) then
+ begin
+ dispose(operation_type_table);
+ operation_type_table:=nil;
+ end;
+ if assigned(instabcache) then
+ begin
+ dispose(instabcache);
+ instabcache:=nil;
+ end;
+ end;
+
+
+begin
+ cai_align:=tai_align;
+ cai_cpu:=taicpu;
+end.
diff --git a/closures/compiler/x86/agx86att.pas b/closures/compiler/x86/agx86att.pas
new file mode 100644
index 0000000000..0599eaee8a
--- /dev/null
+++ b/closures/compiler/x86/agx86att.pas
@@ -0,0 +1,437 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit implements an asmoutput class for i386 AT&T syntax
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+{ This unit implements an asmoutput class for i386 AT&T syntax
+}
+unit agx86att;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cclasses,cpubase,
+ globals,cgutils,
+ aasmbase,aasmtai,aasmdata,assemble,aggas;
+
+ type
+ Tx86ATTAssembler=class(TGNUassembler)
+ constructor create(smart: boolean); override;
+ end;
+
+ Tx86AppleGNUAssembler=class(TAppleGNUassembler)
+ constructor create(smart: boolean); override;
+ end;
+
+ Tx86AoutGNUAssembler=class(TAoutGNUassembler)
+ constructor create(smart: boolean); override;
+ end;
+
+
+ Tx86InstrWriter=class(TCPUInstrWriter)
+ private
+ procedure WriteReference(var ref : treference);
+ procedure WriteOper(const o:toper);
+ procedure WriteOper_jmp(const o:toper);
+ public
+ procedure WriteInstruction(hp: tai);override;
+ end;
+
+
+
+ implementation
+
+ uses
+ globtype,
+ cutils,systems,
+ verbose,
+ itcpugas,
+ cgbase,
+ aasmcpu;
+
+
+{****************************************************************************
+ Tx86ATTAssembler
+ ****************************************************************************}
+
+ constructor Tx86ATTAssembler.create(smart: boolean);
+ begin
+ inherited create(smart);
+ InstrWriter := Tx86InstrWriter.create(self);
+ end;
+
+{****************************************************************************
+ Tx86AppleGNUAssembler
+ ****************************************************************************}
+
+ constructor Tx86AppleGNUAssembler.create(smart: boolean);
+ begin
+ inherited create(smart);
+ InstrWriter := Tx86InstrWriter.create(self);
+ end;
+
+{****************************************************************************
+ Tx86AoutGNUAssembler
+ ****************************************************************************}
+
+ constructor Tx86AoutGNUAssembler.create(smart: boolean);
+ begin
+ inherited create(smart);
+ InstrWriter := Tx86InstrWriter.create(self);
+ end;
+
+{****************************************************************************
+ Tx86InstrWriter
+ ****************************************************************************}
+
+ procedure Tx86InstrWriter.WriteReference(var ref : treference);
+ begin
+ with ref do
+ begin
+ { do we have a segment prefix ? }
+ { These are probably not correctly handled under GAS }
+ { should be replaced by coding the segment override }
+ { directly! - DJGPP FAQ }
+ if segment<>NR_NO then
+ owner.AsmWrite(gas_regname(segment)+':');
+ if assigned(symbol) then
+ owner.AsmWrite(symbol.name);
+ if assigned(relsymbol) then
+ owner.AsmWrite('-'+relsymbol.name);
+ if ref.refaddr=addr_pic then
+{$ifdef x86_64}
+ begin
+ { local symbols don't have to (and in case of Mac OS X: cannot)
+ be accessed via the GOT
+ }
+ if not assigned(ref.symbol) or
+ (ref.symbol.bind<>AB_LOCAL) then
+ owner.AsmWrite('@GOTPCREL');
+ end;
+{$else x86_64}
+ owner.AsmWrite('@GOT');
+{$endif x86_64}
+ if offset<0 then
+ owner.AsmWrite(tostr(offset))
+ else
+ if (offset>0) then
+ begin
+ if assigned(symbol) then
+ owner.AsmWrite('+'+tostr(offset))
+ else
+ owner.AsmWrite(tostr(offset));
+ end
+ else if (index=NR_NO) and (base=NR_NO) and (not assigned(symbol)) then
+ owner.AsmWrite('0');
+ if (index<>NR_NO) and (base=NR_NO) then
+ begin
+ owner.AsmWrite('(,'+gas_regname(index));
+ if scalefactor<>0 then
+ owner.AsmWrite(','+tostr(scalefactor)+')')
+ else
+ owner.AsmWrite(')');
+ end
+ else
+ if (index=NR_NO) and (base<>NR_NO) then
+ owner.AsmWrite('('+gas_regname(base)+')')
+ else
+ if (index<>NR_NO) and (base<>NR_NO) then
+ begin
+ owner.AsmWrite('('+gas_regname(base)+','+gas_regname(index));
+ if scalefactor<>0 then
+ owner.AsmWrite(','+tostr(scalefactor));
+ owner.AsmWrite(')');
+ end;
+ end;
+ end;
+
+
+ procedure Tx86InstrWriter.WriteOper(const o:toper);
+ begin
+ case o.typ of
+ top_reg :
+ owner.AsmWrite(gas_regname(o.reg));
+ top_ref :
+ if o.ref^.refaddr in [addr_no,addr_pic,addr_pic_no_got] then
+ WriteReference(o.ref^)
+ else
+ begin
+ owner.AsmWrite('$');
+ if assigned(o.ref^.symbol) then
+ owner.AsmWrite(o.ref^.symbol.name);
+ if o.ref^.offset>0 then
+ owner.AsmWrite('+'+tostr(o.ref^.offset))
+ else
+ if o.ref^.offset<0 then
+ owner.AsmWrite(tostr(o.ref^.offset))
+ else
+ if not(assigned(o.ref^.symbol)) then
+ owner.AsmWrite('0');
+ end;
+ top_const :
+ owner.AsmWrite('$'+tostr(o.val));
+ else
+ internalerror(10001);
+ end;
+ end;
+
+
+ procedure Tx86InstrWriter.WriteOper_jmp(const o:toper);
+ begin
+ case o.typ of
+ top_reg :
+ owner.AsmWrite('*'+gas_regname(o.reg));
+ top_ref :
+ begin
+ if o.ref^.refaddr in [addr_no,addr_pic_no_got] then
+ begin
+ owner.AsmWrite('*');
+ WriteReference(o.ref^);
+ end
+ else
+ begin
+ owner.AsmWrite(o.ref^.symbol.name);
+ if o.ref^.refaddr=addr_pic then
+ owner.AsmWrite('@PLT');
+ if o.ref^.offset>0 then
+ owner.AsmWrite('+'+tostr(o.ref^.offset))
+ else
+ if o.ref^.offset<0 then
+ owner.AsmWrite(tostr(o.ref^.offset));
+ end;
+ end;
+ top_const :
+ owner.AsmWrite(tostr(o.val));
+ else
+ internalerror(10001);
+ end;
+ end;
+
+
+ procedure Tx86InstrWriter.WriteInstruction(hp: tai);
+ var
+ op : tasmop;
+{$ifdef x86_64}
+ val : aint;
+{$endif}
+ calljmp : boolean;
+ need_second_mov : boolean;
+ i : integer;
+ begin
+ if hp.typ <> ait_instruction then
+ exit;
+ taicpu(hp).SetOperandOrder(op_att);
+ op:=taicpu(hp).opcode;
+ calljmp:=is_calljmp(op);
+ { constant values in the 32 bit range are sign-extended to
+ 64 bits, but this is not what we want. PM 2010-09-02
+ the fix consists of simply setting only the 4-byte register
+ as the upper 4-bytes will be zeroed at the same time. }
+ need_second_mov:=false;
+{$ifdef x86_64}
+ if (op=A_MOV) and (taicpu(hp).opsize=S_Q) and
+ (taicpu(hp).oper[0]^.typ = top_const) then
+ begin
+ val := taicpu(hp).oper[0]^.val;
+ if (val > int64($7fffffff)) and (val < int64($100000000)) then
+ begin
+ owner.AsmWrite(target_asm.comment);
+ owner.AsmWritePChar('Fix for Win64-GAS bug');
+ owner.AsmLn;
+ taicpu(hp).opsize:=S_L;
+ if taicpu(hp).oper[1]^.typ = top_reg then
+ setsubreg(taicpu(hp).oper[1]^.reg,R_SUBD)
+ else if taicpu(hp).oper[1]^.typ = top_ref then
+ need_second_mov:=true
+ else
+ internalerror(20100902);
+ end;
+ end;
+{$endif x86_64}
+ owner.AsmWrite(#9);
+ { movsd should not be translated to movsl when there
+ are (xmm) arguments }
+ if (op=A_MOVSD) and (taicpu(hp).ops>0) then
+ owner.AsmWrite('movsd')
+ else
+ owner.AsmWrite(gas_op2str[op]);
+ owner.AsmWrite(cond2str[taicpu(hp).condition]);
+ { suffix needed ? fnstsw,fldcw don't support suffixes
+ with binutils 2.9.5 under linux }
+{ if (Taicpu(hp).oper[0]^.typ=top_reg) and
+ (Taicpu(hp).oper[0]^.reg.enum>lastreg) then
+ internalerror(200301081);}
+
+ if (not calljmp) and
+ (gas_needsuffix[op]<>AttSufNONE) and
+ (op<>A_FNSTSW) and
+ (op<>A_FSTSW) and
+ (op<>A_FNSTCW) and
+ (op<>A_FSTCW) and
+ (op<>A_FLDCW) and
+ not(
+ (taicpu(hp).ops<>0) and
+ (taicpu(hp).oper[0]^.typ=top_reg) and
+ (getregtype(taicpu(hp).oper[0]^.reg)=R_FPUREGISTER)
+ ) then
+ owner.AsmWrite(gas_opsize2str[taicpu(hp).opsize]);
+ { process operands }
+ if taicpu(hp).ops<>0 then
+ begin
+ if calljmp then
+ begin
+ owner.AsmWrite(#9);
+ WriteOper_jmp(taicpu(hp).oper[0]^);
+ end
+ else
+ begin
+ for i:=0 to taicpu(hp).ops-1 do
+ begin
+ if i=0 then
+ owner.AsmWrite(#9)
+ else
+ owner.AsmWrite(',');
+ WriteOper(taicpu(hp).oper[i]^);
+ end;
+ end;
+ end;
+ owner.AsmLn;
+ if need_second_mov then
+ begin
+ taicpu(hp).oper[0]^.val:=0;
+ inc(taicpu(hp).oper[1]^.ref^.offset,4);
+ WriteInstruction(hp);
+ end;
+ end;
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+ const
+{$ifdef x86_64}
+ as_x86_64_as_info : tasminfo =
+ (
+ id : as_gas;
+ idtxt : 'AS';
+ asmbin : 'as';
+ asmcmd : '--64 -o $OBJ $ASM';
+ supported_targets : [system_x86_64_linux,system_x86_64_freebsd,system_x86_64_win64,system_x86_64_embedded];
+ flags : [af_allowdirect,af_needar,af_smartlink_sections,af_supports_dwarf];
+ labelprefix : '.L';
+ comment : '# ';
+ );
+
+ as_x86_64_gas_info : tasminfo =
+ (
+ id : as_ggas;
+ idtxt : 'GAS';
+ asmbin : 'gas';
+ asmcmd : '--64 -o $OBJ $ASM';
+ supported_targets : [system_x86_64_solaris];
+ flags : [af_allowdirect,af_needar,af_smartlink_sections,af_supports_dwarf];
+ labelprefix : '.L';
+ comment : '# ';
+ );
+
+
+
+ as_x86_64_gas_darwin_info : tasminfo =
+ (
+ id : as_darwin;
+ idtxt : 'AS-Darwin';
+ asmbin : 'as';
+ asmcmd : '-o $OBJ $ASM -arch x86_64';
+ supported_targets : [system_x86_64_darwin];
+ flags : [af_allowdirect,af_needar,af_smartlink_sections,af_supports_dwarf];
+ labelprefix : 'L';
+ comment : '# ';
+ );
+
+{$else x86_64}
+ as_i386_as_info : tasminfo =
+ (
+ id : as_gas;
+ idtxt : 'AS';
+ asmbin : 'as';
+ asmcmd : '--32 -o $OBJ $ASM';
+ supported_targets : [system_i386_GO32V2,system_i386_linux,system_i386_Win32,system_i386_freebsd,system_i386_solaris,system_i386_beos,
+ system_i386_netbsd,system_i386_Netware,system_i386_qnx,system_i386_wdosx,system_i386_openbsd,
+ system_i386_netwlibc,system_i386_wince,system_i386_embedded,system_i386_symbian,system_i386_haiku,system_x86_6432_linux,
+ system_i386_nativent];
+ flags : [af_allowdirect,af_needar,af_smartlink_sections,af_supports_dwarf];
+ labelprefix : '.L';
+ comment : '# ';
+ );
+
+
+ as_i386_as_aout_info : tasminfo =
+ (
+ id : as_i386_as_aout;
+ idtxt : 'AS_AOUT';
+ asmbin : 'as';
+ asmcmd : '-o $OBJ $ASM';
+ supported_targets : [system_i386_linux,system_i386_OS2,system_i386_freebsd,system_i386_netbsd,system_i386_openbsd,system_i386_EMX,system_i386_embedded];
+ flags : [af_allowdirect,af_needar,af_stabs_use_function_absolute_addresses];
+ labelprefix : 'L';
+ comment : '# ';
+ );
+
+
+ as_i386_gas_darwin_info : tasminfo =
+ (
+ id : as_darwin;
+ idtxt : 'AS-Darwin';
+ asmbin : 'as';
+ asmcmd : '-o $OBJ $ASM -arch i386';
+ supported_targets : [system_i386_darwin,system_i386_iphonesim];
+ flags : [af_allowdirect,af_needar,af_smartlink_sections,af_supports_dwarf,af_stabs_use_function_absolute_addresses];
+ labelprefix : 'L';
+ comment : '# ';
+ );
+
+ as_i386_gas_info : tasminfo =
+ (
+ id : as_ggas;
+ idtxt : 'GAS';
+ asmbin : 'gas';
+ asmcmd : '--32 -o $OBJ $ASM';
+ supported_targets : [system_i386_GO32V2,system_i386_linux,system_i386_Win32,system_i386_freebsd,system_i386_solaris,system_i386_beos,
+ system_i386_netbsd,system_i386_Netware,system_i386_qnx,system_i386_wdosx,system_i386_openbsd,
+ system_i386_netwlibc,system_i386_wince,system_i386_embedded,system_i386_symbian,system_i386_haiku,system_x86_6432_linux];
+ flags : [af_allowdirect,af_needar,af_smartlink_sections,af_supports_dwarf];
+ labelprefix : '.L';
+ comment : '# ';
+ );
+{$endif x86_64}
+
+initialization
+{$ifdef x86_64}
+ RegisterAssembler(as_x86_64_as_info,Tx86ATTAssembler);
+ RegisterAssembler(as_x86_64_gas_info,Tx86ATTAssembler);
+ RegisterAssembler(as_x86_64_gas_darwin_info,Tx86AppleGNUAssembler);
+{$else x86_64}
+ RegisterAssembler(as_i386_as_info,Tx86ATTAssembler);
+ RegisterAssembler(as_i386_gas_info,Tx86ATTAssembler);
+ RegisterAssembler(as_i386_gas_darwin_info,Tx86AppleGNUAssembler);
+ RegisterAssembler(as_i386_as_aout_info,Tx86AoutGNUAssembler);
+{$endif x86_64}
+end.
diff --git a/closures/compiler/x86/agx86int.pas b/closures/compiler/x86/agx86int.pas
new file mode 100644
index 0000000000..3b9661ccdf
--- /dev/null
+++ b/closures/compiler/x86/agx86int.pas
@@ -0,0 +1,1018 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit implements an asmoutput class for Intel syntax with Intel i386+
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+{
+ This unit implements an asmoutput class for Intel syntax with Intel i386+
+}
+unit agx86int;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cpubase,
+ aasmbase,aasmtai,aasmdata,aasmcpu,assemble,cgutils;
+
+ type
+ Tx86IntelAssembler = class(TExternalAssembler)
+ private
+ procedure WriteReference(var ref : treference);
+ procedure WriteOper(const o:toper;s : topsize; opcode: tasmop;dest : boolean);
+ procedure WriteOper_jmp(const o:toper;s : topsize);
+ public
+ procedure WriteTree(p:TAsmList);override;
+ procedure WriteAsmList;override;
+ Function DoAssemble:boolean;override;
+ procedure WriteExternals;
+ end;
+
+
+implementation
+
+ uses
+ SysUtils,
+ cutils,globtype,globals,systems,cclasses,
+ verbose,finput,fmodule,script,cpuinfo,
+ itx86int,
+ cgbase
+ ;
+
+ const
+ line_length = 70;
+
+ secnames : array[TAsmSectiontype] of string[4] = ('','',
+ 'CODE','DATA','DATA','DATA','BSS','TLS',
+ '','','','','','',
+ '','','','',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '','','','',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ ''
+ );
+
+ secnamesml64 : array[TAsmSectiontype] of string[7] = ('','',
+ '_TEXT','_DATA','_DATA','_DATA','_BSS','_TLS',
+ '','','','',
+ 'idata$2','idata$4','idata$5','idata$6','idata$7','edata',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '','','','',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ ''
+ );
+
+ function single2str(d : single) : string;
+ var
+ hs : string;
+ p : byte;
+ begin
+ str(d,hs);
+ { nasm expects a lowercase e }
+ p:=pos('E',hs);
+ if p>0 then
+ hs[p]:='e';
+ p:=pos('+',hs);
+ if p>0 then
+ delete(hs,p,1);
+ single2str:=lower(hs);
+ end;
+
+ function double2str(d : double) : string;
+ var
+ hs : string;
+ p : byte;
+ begin
+ str(d,hs);
+ { nasm expects a lowercase e }
+ p:=pos('E',hs);
+ if p>0 then
+ hs[p]:='e';
+ p:=pos('+',hs);
+ if p>0 then
+ delete(hs,p,1);
+ double2str:=lower(hs);
+ end;
+
+ function extended2str(e : extended) : string;
+ var
+ hs : string;
+ p : byte;
+ begin
+ str(e,hs);
+ { nasm expects a lowercase e }
+ p:=pos('E',hs);
+ if p>0 then
+ hs[p]:='e';
+ p:=pos('+',hs);
+ if p>0 then
+ delete(hs,p,1);
+ extended2str:=lower(hs);
+ end;
+
+
+ function comp2str(d : bestreal) : string;
+ type
+ pdouble = ^double;
+ var
+ c : comp;
+ dd : pdouble;
+ begin
+ c:=comp(d);
+ dd:=pdouble(@c); { this makes a bitwise copy of c into a double }
+ comp2str:=double2str(dd^);
+ end;
+
+ { MASM supports aligns up to 8192 }
+ function alignstr(b : integer) : string;
+ begin
+ case b of
+ 1: result:='BYTE';
+ 2: result:='WORD';
+ 4: result:='DWORD';
+ 16: result:='PARA';
+ 256: result:='PAGE';
+ else
+ result:='ALIGN('+tostr(b)+')';
+ end;
+ end;
+
+{****************************************************************************
+ tx86IntelAssembler
+ ****************************************************************************}
+
+ procedure tx86IntelAssembler.WriteReference(var ref : treference);
+ var
+ first : boolean;
+ begin
+ with ref do
+ begin
+ first:=true;
+ if segment<>NR_NO then
+ AsmWrite(masm_regname(segment)+':[')
+ else
+ AsmWrite('[');
+ if assigned(symbol) then
+ begin
+ if (target_asm.id = as_i386_tasm) then
+ AsmWrite('dword ptr ');
+ AsmWrite(symbol.name);
+ first:=false;
+ end;
+ if (base<>NR_NO) then
+ begin
+ if not(first) then
+ AsmWrite('+')
+ else
+ first:=false;
+{$ifdef x86_64}
+ { ml64 needs [$+foo] instead of [rip+foo] }
+ if (base=NR_RIP) and (target_asm.id=as_x86_64_masm) then
+ AsmWrite('$')
+ else
+{$endif x86_64}
+ AsmWrite(masm_regname(base));
+ end;
+ if (index<>NR_NO) then
+ begin
+ if not(first) then
+ AsmWrite('+')
+ else
+ first:=false;
+ AsmWrite(masm_regname(index));
+ if scalefactor<>0 then
+ AsmWrite('*'+tostr(scalefactor));
+ end;
+ if offset<0 then
+ begin
+ AsmWrite(tostr(offset));
+ first:=false;
+ end
+ else if (offset>0) then
+ begin
+ AsmWrite('+'+tostr(offset));
+ first:=false;
+ end;
+ if first then
+ AsmWrite('0');
+ AsmWrite(']');
+ end;
+ end;
+
+
+ procedure tx86IntelAssembler.WriteOper(const o:toper;s : topsize; opcode: tasmop;dest : boolean);
+ begin
+ case o.typ of
+ top_reg :
+ AsmWrite(masm_regname(o.reg));
+ top_const :
+ AsmWrite(tostr(o.val));
+ top_ref :
+ begin
+ if o.ref^.refaddr in [addr_no,addr_pic,addr_pic_no_got] then
+ begin
+ if ((opcode <> A_LGS) and (opcode <> A_LSS) and
+ (opcode <> A_LFS) and (opcode <> A_LDS) and
+ (opcode <> A_LES)) then
+ Begin
+ case s of
+ S_B : AsmWrite('byte ptr ');
+ S_W : AsmWrite('word ptr ');
+ S_L : AsmWrite('dword ptr ');
+ S_Q : AsmWrite('qword ptr ');
+ S_IS : AsmWrite('word ptr ');
+ S_IL : AsmWrite('dword ptr ');
+ S_IQ : AsmWrite('qword ptr ');
+ S_FS : AsmWrite('dword ptr ');
+ S_FL : AsmWrite('qword ptr ');
+ S_T,
+ S_FX : AsmWrite('tbyte ptr ');
+ S_BW : if dest then
+ AsmWrite('word ptr ')
+ else
+ AsmWrite('byte ptr ');
+ S_BL : if dest then
+ AsmWrite('dword ptr ')
+ else
+ AsmWrite('byte ptr ');
+ S_WL : if dest then
+ AsmWrite('dword ptr ')
+ else
+ AsmWrite('word ptr ');
+{$ifdef x86_64}
+ S_BQ : if dest then
+ AsmWrite('qword ptr ')
+ else
+ AsmWrite('byte ptr ');
+ S_WQ : if dest then
+ AsmWrite('qword ptr ')
+ else
+ AsmWrite('word ptr ');
+ S_LQ : if dest then
+ AsmWrite('qword ptr ')
+ else
+ AsmWrite('dword ptr ');
+ S_XMM: AsmWrite('xmmword ptr ');
+
+{$endif x86_64}
+ end;
+ end;
+ WriteReference(o.ref^);
+ end
+ else
+ begin
+ AsmWrite('offset ');
+ if assigned(o.ref^.symbol) then
+ AsmWrite(o.ref^.symbol.name);
+ if o.ref^.offset>0 then
+ AsmWrite('+'+tostr(o.ref^.offset))
+ else
+ if o.ref^.offset<0 then
+ AsmWrite(tostr(o.ref^.offset))
+ else
+ if not(assigned(o.ref^.symbol)) then
+ AsmWrite('0');
+ end;
+ end;
+ else
+ internalerror(2005060510);
+ end;
+ end;
+
+
+ procedure tx86IntelAssembler.WriteOper_jmp(const o:toper;s : topsize);
+ begin
+ case o.typ of
+ top_reg :
+ AsmWrite(masm_regname(o.reg));
+ top_const :
+ AsmWrite(tostr(o.val));
+ top_ref :
+ { what about lcall or ljmp ??? }
+ begin
+ if o.ref^.refaddr=addr_no then
+ begin
+ if (target_asm.id <> as_i386_tasm) then
+ begin
+ if s=S_FAR then
+ AsmWrite('far ptr ')
+ else
+{$ifdef x86_64}
+ AsmWrite('qword ptr ');
+{$else x86_64}
+ AsmWrite('dword ptr ');
+{$endif x86_64}
+ end;
+ WriteReference(o.ref^);
+ end
+ else
+ begin
+ AsmWrite(o.ref^.symbol.name);
+ if o.ref^.offset>0 then
+ AsmWrite('+'+tostr(o.ref^.offset))
+ else
+ if o.ref^.offset<0 then
+ AsmWrite(tostr(o.ref^.offset));
+ end;
+ end;
+ else
+ internalerror(2005060511);
+ end;
+ end;
+
+ const
+ ait_const2str : array[aitconst_128bit..aitconst_secrel32_symbol] of string[20]=(
+ #9''#9,#9'DQ'#9,#9'DD'#9,#9'DW'#9,#9'DB'#9,
+ #9'FIXMESLEB',#9'FIXEMEULEB',
+ #9'DD RVA'#9,#9'DD SECREL32'#9
+ );
+
+ Function PadTabs(const p:string;addch:char):string;
+ var
+ s : string;
+ i : longint;
+ begin
+ i:=length(p);
+ if addch<>#0 then
+ begin
+ inc(i);
+ s:=p+addch;
+ end
+ else
+ s:=p;
+ if i<8 then
+ PadTabs:=s+#9#9
+ else
+ PadTabs:=s+#9;
+ end;
+
+ procedure tx86IntelAssembler.WriteTree(p:TAsmList);
+ var
+ s,
+ prefix,
+ suffix : string;
+ hp : tai;
+ counter,
+ lines,
+ InlineLevel : longint;
+ i,j,l : longint;
+ consttype : taiconst_type;
+ do_line,DoNotSplitLine,
+ quoted : boolean;
+ begin
+ if not assigned(p) then
+ exit;
+ { lineinfo is only needed for al_procedures (PFV) }
+ do_line:=((cs_asm_source in current_settings.globalswitches) or
+ (cs_lineinfo in current_settings.moduleswitches))
+ and (p=current_asmdata.asmlists[al_procedures]);
+ InlineLevel:=0;
+ DoNotSplitLine:=false;
+ hp:=tai(p.first);
+ while assigned(hp) do
+ begin
+ prefetch(pointer(hp.next)^);
+ if not(hp.typ in SkipLineInfo) then
+ begin
+ current_filepos:=tailineinfo(hp).fileinfo;
+ { no line info for inlined code }
+ if do_line and (inlinelevel=0) and not DoNotSplitLine then
+ WriteSourceLine(hp as tailineinfo);
+ end;
+ DoNotSplitLine:=false;
+
+ case hp.typ of
+ ait_comment :
+ Begin
+ AsmWrite(target_asm.comment);
+ AsmWritePChar(tai_comment(hp).str);
+ AsmLn;
+ End;
+
+ ait_regalloc :
+ begin
+ if (cs_asm_regalloc in current_settings.globalswitches) then
+ AsmWriteLn(target_asm.comment+'Register '+masm_regname(tai_regalloc(hp).reg)+
+ regallocstr[tai_regalloc(hp).ratype]);
+ end;
+
+ ait_tempalloc :
+ begin
+ if (cs_asm_tempalloc in current_settings.globalswitches) then
+ WriteTempalloc(tai_tempalloc(hp));
+ end;
+
+ ait_section :
+ begin
+ if tai_section(hp).sectype<>sec_none then
+ begin
+ if target_asm.id=as_x86_64_masm then
+ begin
+ if LasTSecType<>sec_none then
+ AsmWriteLn(secnamesml64[LasTSecType]+#9#9'ENDS');
+ AsmLn;
+ AsmWriteLn(secnamesml64[tai_section(hp).sectype]+#9+'SEGMENT')
+ end
+ else
+ begin
+ if LasTSecType<>sec_none then
+ AsmWriteLn('_'+secnames[LasTSecType]+#9#9'ENDS');
+ AsmLn;
+ AsmWriteLn('_'+secnames[tai_section(hp).sectype]+#9#9+
+ 'SEGMENT'#9+alignstr(tai_section(hp).secalign)+' PUBLIC USE32 '''+
+ secnames[tai_section(hp).sectype]+'''');
+ end;
+ end;
+ LasTSecType:=tai_section(hp).sectype;
+ end;
+ ait_align :
+ begin
+ { CAUSES PROBLEMS WITH THE SEGMENT DEFINITION }
+ { SEGMENT DEFINITION SHOULD MATCH TYPE OF ALIGN }
+ { HERE UNDER TASM! }
+ if tai_align_abstract(hp).aligntype>1 then
+ AsmWriteLn(#9'ALIGN '+tostr(tai_align_abstract(hp).aligntype));
+ end;
+ ait_datablock :
+ begin
+ if tai_datablock(hp).is_global then
+ AsmWriteLn(#9'PUBLIC'#9+tai_datablock(hp).sym.name);
+ AsmWriteLn(PadTabs(tai_datablock(hp).sym.name,#0)+'DB'#9+tostr(tai_datablock(hp).size)+' DUP(?)');
+ end;
+ ait_const:
+ begin
+ consttype:=tai_const(hp).consttype;
+ case consttype of
+ aitconst_uleb128bit,
+ aitconst_sleb128bit,
+ aitconst_128bit,
+ aitconst_64bit,
+ aitconst_32bit,
+ aitconst_16bit,
+ aitconst_8bit,
+ aitconst_rva_symbol,
+ aitconst_secrel32_symbol :
+ begin
+ AsmWrite(ait_const2str[consttype]);
+ l:=0;
+ repeat
+ if assigned(tai_const(hp).sym) then
+ begin
+ if assigned(tai_const(hp).endsym) then
+ s:=tai_const(hp).endsym.name+'-'+tai_const(hp).sym.name
+ else
+ s:=tai_const(hp).sym.name;
+ if tai_const(hp).value<>0 then
+ s:=s+tostr_with_plus(tai_const(hp).value);
+ end
+ else
+ s:=tostr(tai_const(hp).value);
+ AsmWrite(s);
+ inc(l,length(s));
+ if (l>line_length) or
+ (hp.next=nil) or
+ (tai(hp.next).typ<>ait_const) or
+ (tai_const(hp.next).consttype<>consttype) then
+ break;
+ hp:=tai(hp.next);
+ AsmWrite(',');
+ until false;
+ AsmLn;
+ end;
+ else
+ internalerror(200704253);
+ end;
+ end;
+
+ ait_real_32bit :
+ AsmWriteLn(#9#9'DD'#9+single2str(tai_real_32bit(hp).value));
+ ait_real_64bit :
+ AsmWriteLn(#9#9'DQ'#9+double2str(tai_real_64bit(hp).value));
+ ait_real_80bit :
+ AsmWriteLn(#9#9'DT'#9+extended2str(tai_real_80bit(hp).value));
+ ait_comp_64bit :
+ AsmWriteLn(#9#9'DQ'#9+extended2str(tai_comp_64bit(hp).value));
+ ait_string :
+ begin
+ counter := 0;
+ lines := tai_string(hp).len div line_length;
+ { separate lines in different parts }
+ if tai_string(hp).len > 0 then
+ Begin
+ for j := 0 to lines-1 do
+ begin
+ AsmWrite(#9#9'DB'#9);
+ quoted:=false;
+ for i:=counter to counter+line_length-1 do
+ begin
+ { it is an ascii character. }
+ if (ord(tai_string(hp).str[i])>31) and
+ (ord(tai_string(hp).str[i])<128) and
+ (tai_string(hp).str[i]<>'"') then
+ begin
+ if not(quoted) then
+ begin
+ if i>counter then
+ AsmWrite(',');
+ AsmWrite('"');
+ end;
+ AsmWrite(tai_string(hp).str[i]);
+ quoted:=true;
+ end { if > 31 and < 128 and ord('"') }
+ else
+ begin
+ if quoted then
+ AsmWrite('"');
+ if i>counter then
+ AsmWrite(',');
+ quoted:=false;
+ AsmWrite(tostr(ord(tai_string(hp).str[i])));
+ end;
+ end; { end for i:=0 to... }
+ if quoted then AsmWrite('"');
+ AsmWrite(target_info.newline);
+ counter := counter+line_length;
+ end; { end for j:=0 ... }
+ { do last line of lines }
+ if counter<tai_string(hp).len then
+ AsmWrite(#9#9'DB'#9);
+ quoted:=false;
+ for i:=counter to tai_string(hp).len-1 do
+ begin
+ { it is an ascii character. }
+ if (ord(tai_string(hp).str[i])>31) and
+ (ord(tai_string(hp).str[i])<128) and
+ (tai_string(hp).str[i]<>'"') then
+ begin
+ if not(quoted) then
+ begin
+ if i>counter then
+ AsmWrite(',');
+ AsmWrite('"');
+ end;
+ AsmWrite(tai_string(hp).str[i]);
+ quoted:=true;
+ end { if > 31 and < 128 and " }
+ else
+ begin
+ if quoted then
+ AsmWrite('"');
+ if i>counter then
+ AsmWrite(',');
+ quoted:=false;
+ AsmWrite(tostr(ord(tai_string(hp).str[i])));
+ end;
+ end; { end for i:=0 to... }
+ if quoted then
+ AsmWrite('"');
+ end;
+ AsmLn;
+ end;
+ ait_label :
+ begin
+ if tai_label(hp).labsym.is_used then
+ begin
+ AsmWrite(tai_label(hp).labsym.name);
+ if assigned(hp.next) and not(tai(hp.next).typ in
+ [ait_const,
+ ait_real_32bit,ait_real_64bit,ait_real_80bit,ait_comp_64bit,ait_string]) then
+ AsmWriteLn(':')
+ else
+ DoNotSplitLine:=true;
+ end;
+ end;
+ ait_symbol :
+ begin
+ if tai_symbol(hp).has_value then
+ internalerror(2009090802);
+ if tai_symbol(hp).is_global then
+ AsmWriteLn(#9'PUBLIC'#9+tai_symbol(hp).sym.name);
+ AsmWrite(tai_symbol(hp).sym.name);
+ if assigned(hp.next) and not(tai(hp.next).typ in
+ [ait_const,
+ ait_real_32bit,ait_real_64bit,ait_real_80bit,ait_comp_64bit,ait_string]) then
+ AsmWriteLn(':')
+ end;
+ ait_symbol_end :
+ begin
+ end;
+ ait_instruction :
+ begin
+ taicpu(hp).CheckNonCommutativeOpcodes;
+ taicpu(hp).SetOperandOrder(op_intel);
+ { Reset }
+ suffix:='';
+ prefix:= '';
+ { We need to explicitely set
+ word prefix to get selectors
+ to be pushed in 2 bytes PM }
+ if (taicpu(hp).opsize=S_W) and
+ (
+ (
+ (taicpu(hp).opcode=A_PUSH) or
+ (taicpu(hp).opcode=A_POP)
+ ) and
+ (taicpu(hp).oper[0]^.typ=top_reg) and
+ is_segment_reg(taicpu(hp).oper[0]^.reg)
+ ) then
+ AsmWriteln(#9#9'DB'#9'066h');
+
+ { added prefix instructions, must be on same line as opcode }
+ if (taicpu(hp).ops = 0) and
+ ((taicpu(hp).opcode = A_REP) or
+ (taicpu(hp).opcode = A_LOCK) or
+ (taicpu(hp).opcode = A_REPE) or
+ (taicpu(hp).opcode = A_REPNZ) or
+ (taicpu(hp).opcode = A_REPZ) or
+ (taicpu(hp).opcode = A_REPNE)) then
+ Begin
+ prefix:=std_op2str[taicpu(hp).opcode]+#9;
+ { there can be a stab inbetween when the opcode was on
+ a different line in the source code }
+ repeat
+ hp:=tai(hp.next);
+ until (hp=nil) or (hp.typ=ait_instruction);
+ { this is theorically impossible... }
+ if hp=nil then
+ begin
+ AsmWriteLn(#9#9+prefix);
+ break;
+ end;
+ { nasm prefers prefix on a line alone
+ AsmWriteln(#9#9+prefix); but not masm PM
+ prefix:=''; }
+ if target_asm.id in [as_i386_nasmcoff,as_i386_nasmwin32,as_i386_nasmwdosx,
+ as_i386_nasmelf,as_i386_nasmobj,as_i386_nasmbeos,as_i386_nasmhaiku] then
+ begin
+ AsmWriteln(prefix);
+ prefix:='';
+ end;
+ end
+ else
+ prefix:= '';
+ if (target_asm.id = as_i386_wasm) and
+ (taicpu(hp).opsize=S_W) and
+ (taicpu(hp).opcode=A_PUSH) and
+ (taicpu(hp).oper[0]^.typ=top_const) then
+ begin
+ AsmWriteln(#9#9'DB 66h,68h ; pushw imm16');
+ AsmWrite(#9#9'DW');
+ end
+ else if (target_asm.id=as_x86_64_masm) and
+ (taicpu(hp).opcode=A_MOVQ) then
+ AsmWrite(#9#9'mov')
+ else
+ AsmWrite(#9#9+prefix+std_op2str[taicpu(hp).opcode]+cond2str[taicpu(hp).condition]+suffix);
+ if taicpu(hp).ops<>0 then
+ begin
+ if is_calljmp(taicpu(hp).opcode) then
+ begin
+ AsmWrite(#9);
+ WriteOper_jmp(taicpu(hp).oper[0]^,taicpu(hp).opsize);
+ end
+ else
+ begin
+ for i:=0to taicpu(hp).ops-1 do
+ begin
+ if i=0 then
+ AsmWrite(#9)
+ else
+ AsmWrite(',');
+ WriteOper(taicpu(hp).oper[i]^,taicpu(hp).opsize,taicpu(hp).opcode,(i=2));
+ end;
+ end;
+ end;
+ AsmLn;
+ end;
+
+ ait_stab,
+ ait_force_line,
+ ait_function_name : ;
+
+ ait_cutobject :
+ begin
+ { only reset buffer if nothing has changed }
+ if AsmSize=AsmStartSize then
+ AsmClear
+ else
+ begin
+ if LasTSecType<>sec_none then
+ AsmWriteLn('_'+secnames[LasTSecType]+#9#9'ENDS');
+ AsmLn;
+ AsmWriteLn(#9'END');
+ AsmClose;
+ DoAssemble;
+ AsmCreate(tai_cutobject(hp).place);
+ end;
+ { avoid empty files }
+ while assigned(hp.next) and (tai(hp.next).typ in [ait_cutobject,ait_section,ait_comment]) do
+ begin
+ if tai(hp.next).typ=ait_section then
+ lasTSecType:=tai_section(hp.next).sectype;
+ hp:=tai(hp.next);
+ end;
+ AsmWriteLn(#9'.386p');
+ AsmWriteLn('DGROUP'#9'GROUP'#9'_BSS,_DATA');
+ AsmWriteLn(#9'ASSUME'#9'CS:_CODE,ES:DGROUP,DS:DGROUP,SS:DGROUP');
+ { I was told that this isn't necesarry because }
+ { the labels generated by FPC are unique (FK) }
+ { AsmWriteLn(#9'LOCALS '+target_asm.labelprefix); }
+ { TODO: PARA is incorrect, must use actual section align }
+ if lasTSectype<>sec_none then
+ AsmWriteLn('_'+secnames[lasTSectype]+#9#9+
+ 'SEGMENT'#9'PARA PUBLIC USE32 '''+
+ secnames[lasTSectype]+'''');
+ AsmStartSize:=AsmSize;
+ end;
+ ait_marker :
+ begin
+ if tai_marker(hp).kind=mark_NoLineInfoStart then
+ inc(InlineLevel)
+ else if tai_marker(hp).kind=mark_NoLineInfoEnd then
+ dec(InlineLevel);
+ end;
+
+ ait_directive :
+ begin
+ case tai_directive(hp).directive of
+ asd_nasm_import :
+ AsmWrite('import ');
+ asd_extern :
+ AsmWrite('EXTRN ');
+ else
+ internalerror(200509192);
+ end;
+ if assigned(tai_directive(hp).name) then
+ AsmWrite(tai_directive(hp).name^);
+ AsmLn;
+ end;
+ ait_seh_directive :
+ { Ignore for now };
+ else
+ internalerror(10000);
+ end;
+ hp:=tai(hp.next);
+ end;
+ end;
+
+
+ procedure tx86intelassembler.WriteExternals;
+ var
+ sym : TAsmSymbol;
+ i : longint;
+ begin
+ for i:=0 to current_asmdata.AsmSymbolDict.Count-1 do
+ begin
+ sym:=TAsmSymbol(current_asmdata.AsmSymbolDict[i]);
+ if sym.bind=AB_EXTERNAL then
+ begin
+ case target_asm.id of
+ as_i386_masm,
+ as_i386_wasm :
+ AsmWriteln(#9'EXTRN'#9+sym.name+': NEAR');
+ as_x86_64_masm :
+ AsmWriteln(#9'EXTRN'#9+sym.name+': PROC');
+ else
+ AsmWriteln(#9'EXTRN'#9+sym.name);
+ end;
+ end;
+ end;
+ end;
+
+
+ function tx86intelassembler.DoAssemble : boolean;
+ var
+ masmobjfn : string;
+ begin
+ DoAssemble:=Inherited DoAssemble;
+ { masm does not seem to recognize specific extensions and uses .obj allways PM }
+ if (target_asm.id in [as_i386_masm,as_i386_wasm]) then
+ begin
+ masmobjfn:=ChangeFileExt(objfilename,'.obj');
+ if not(cs_asm_extern in current_settings.globalswitches) then
+ begin
+ if Not FileExists(objfilename) and
+ FileExists(masmobjfn) then
+ RenameFile(masmobjfn,objfilename);
+ end
+ else
+ AsmRes.AddAsmCommand('mv',masmobjfn+' '+objfilename,objfilename);
+ end;
+ end;
+
+
+ procedure tx86IntelAssembler.WriteAsmList;
+ var
+ hal : tasmlisttype;
+ begin
+{$ifdef EXTDEBUG}
+ if assigned(current_module.mainsource) then
+ comment(v_info,'Start writing intel-styled assembler output for '+current_module.mainsource^);
+{$endif}
+ if target_asm.id<>as_x86_64_masm then
+ begin
+ AsmWriteLn(#9'.386p');
+ { masm 6.11 does not seem to like LOCALS PM }
+ if (target_asm.id = as_i386_tasm) then
+ begin
+ AsmWriteLn(#9'LOCALS '+target_asm.labelprefix);
+ end;
+ AsmWriteLn('DGROUP'#9'GROUP'#9'_BSS,_DATA');
+ AsmWriteLn(#9'ASSUME'#9'CS:_CODE,ES:DGROUP,DS:DGROUP,SS:DGROUP');
+ AsmLn;
+ end;
+
+ WriteExternals;
+
+ for hal:=low(TasmlistType) to high(TasmlistType) do
+ begin
+ AsmWriteLn(target_asm.comment+'Begin asmlist '+AsmListTypeStr[hal]);
+ writetree(current_asmdata.asmlists[hal]);
+ AsmWriteLn(target_asm.comment+'End asmlist '+AsmListTypeStr[hal]);
+ end;
+
+ { better do this at end of WriteTree, but then there comes a trouble with
+ al_const which does not have leading ait_section and thus goes out of segment }
+
+ if LastSecType <> sec_none then
+ begin
+ if target_asm.id=as_x86_64_masm then
+ AsmWriteLn(secnamesml64[LasTSecType]+#9#9'ENDS')
+ else
+ AsmWriteLn('_'+secnames[LasTSecType]+#9#9'ENDS');
+ end;
+ LastSecType := sec_none;
+
+ AsmWriteLn(#9'END');
+ AsmLn;
+
+{$ifdef EXTDEBUG}
+ if assigned(current_module.mainsource) then
+ comment(v_info,'Done writing intel-styled assembler output for '+current_module.mainsource^);
+{$endif EXTDEBUG}
+ end;
+
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+ const
+{$ifdef i386}
+ as_i386_tasm_info : tasminfo =
+ (
+ id : as_i386_tasm;
+ idtxt : 'TASM';
+ asmbin : 'tasm';
+ asmcmd : '/m2 /ml $ASM $OBJ';
+ supported_targets : [system_i386_GO32V2,system_i386_Win32,system_i386_wdosx,system_i386_watcom,system_i386_wince];
+ flags : [af_allowdirect,af_needar,af_labelprefix_only_inside_procedure];
+ labelprefix : '@@';
+ comment : '; ';
+ );
+
+ as_i386_masm_info : tasminfo =
+ (
+ id : as_i386_masm;
+ idtxt : 'MASM';
+ asmbin : 'masm';
+ asmcmd : '/c /Cp $ASM /Fo$OBJ';
+ supported_targets : [system_i386_GO32V2,system_i386_Win32,system_i386_wdosx,system_i386_watcom,system_i386_wince];
+ flags : [af_allowdirect,af_needar];
+ labelprefix : '@@';
+ comment : '; ';
+ );
+
+ as_i386_wasm_info : tasminfo =
+ (
+ id : as_i386_wasm;
+ idtxt : 'WASM';
+ asmbin : 'wasm';
+ asmcmd : '$ASM -6s -fp6 -ms -zq -Fo=$OBJ';
+ supported_targets : [system_i386_watcom];
+ flags : [af_allowdirect,af_needar];
+ labelprefix : '@@';
+ comment : '; ';
+ );
+{$endif i386}
+{$ifdef x86_64}
+ as_x86_64_masm_info : tasminfo =
+ (
+ id : as_x86_64_masm;
+ idtxt : 'MASM';
+ asmbin : 'ml64';
+ asmcmd : '/c /Cp $ASM /Fo$OBJ';
+ supported_targets : [system_x86_64_win64];
+ flags : [af_allowdirect,af_needar];
+ labelprefix : '@@';
+ comment : '; ';
+ );
+{$endif x86_64}
+
+initialization
+{$ifdef x86_64}
+ RegisterAssembler(as_x86_64_masm_info,tx86IntelAssembler);
+{$endif x86_64}
+{$ifdef i386}
+ RegisterAssembler(as_i386_tasm_info,tx86IntelAssembler);
+ RegisterAssembler(as_i386_masm_info,tx86IntelAssembler);
+ RegisterAssembler(as_i386_wasm_info,tx86IntelAssembler);
+{$endif i386}
+end.
diff --git a/closures/compiler/x86/agx86nsm.pas b/closures/compiler/x86/agx86nsm.pas
new file mode 100644
index 0000000000..70c96e7493
--- /dev/null
+++ b/closures/compiler/x86/agx86nsm.pas
@@ -0,0 +1,1145 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit implements an asmoutput class for the Nasm assembler with
+ Intel syntax for the i386+
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit agx86nsm;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cpubase,
+ aasmbase,aasmtai,aasmdata,aasmcpu,assemble,cgutils;
+
+ type
+ T386NasmAssembler = class(texternalassembler)
+ private
+ procedure WriteReference(var ref : treference);
+ procedure WriteOper(const o:toper;s : topsize; opcode: tasmop;ops:longint;dest : boolean);
+ procedure WriteOper_jmp(const o:toper; op : tasmop);
+ procedure WriteSection(atype:TAsmSectiontype;const aname:string);
+ public
+ procedure WriteTree(p:TAsmList);override;
+ procedure WriteAsmList;override;
+ procedure WriteExternals;
+ procedure WriteSmartExternals;
+ end;
+
+
+
+ implementation
+
+ uses
+ cutils,globtype,globals,systems,cclasses,
+ fmodule,finput,verbose,cpuinfo,cgbase
+ ;
+
+ type
+{$ifdef cpuextended}
+ t80bitarray = array[0..9] of byte;
+{$endif cpuextended}
+ t64bitarray = array[0..7] of byte;
+ t32bitarray = array[0..3] of byte;
+ const
+ line_length = 64;
+
+ nasm_regname_table : array[tregisterindex] of string[7] = (
+ {r386nasm.inc contains the Nasm name of each register.}
+ {$i r386nasm.inc}
+ );
+
+ function nasm_regname(r:Tregister):string;
+ var
+ p : tregisterindex;
+ begin
+ p:=findreg_by_number(r);
+ if p<>0 then
+ result:=nasm_regname_table[p]
+ else
+ result:=generic_regname(r);
+ end;
+
+ function single2str(d : single) : string;
+ var
+ hs : string;
+ p : longint;
+ begin
+ str(d,hs);
+ { nasm expects a lowercase e }
+ p:=pos('E',hs);
+ if p>0 then
+ hs[p]:='e';
+ p:=pos('+',hs);
+ if p>0 then
+ delete(hs,p,1);
+ single2str:=lower(hs);
+ end;
+
+ function double2str(d : double) : string;
+ var
+ hs : string;
+ p : longint;
+ begin
+ str(d,hs);
+ { nasm expects a lowercase e }
+ p:=pos('E',hs);
+ if p>0 then
+ hs[p]:='e';
+ p:=pos('+',hs);
+ if p>0 then
+ delete(hs,p,1);
+ double2str:=lower(hs);
+ end;
+
+ function extended2str(e : extended) : string;
+ var
+ hs : string;
+ p : longint;
+ begin
+ str(e,hs);
+ { nasm expects a lowercase e }
+ p:=pos('E',hs);
+ if p>0 then
+ hs[p]:='e';
+ p:=pos('+',hs);
+ if p>0 then
+ delete(hs,p,1);
+ extended2str:=lower(hs);
+ end;
+
+
+ { convert floating point values }
+ { to correct endian }
+ procedure swap64bitarray(var t: t64bitarray);
+ var
+ b: byte;
+ begin
+ b:= t[7];
+ t[7] := t[0];
+ t[0] := b;
+
+ b := t[6];
+ t[6] := t[1];
+ t[1] := b;
+
+ b:= t[5];
+ t[5] := t[2];
+ t[2] := b;
+
+ b:= t[4];
+ t[4] := t[3];
+ t[3] := b;
+ end;
+
+
+ procedure swap32bitarray(var t: t32bitarray);
+ var
+ b: byte;
+ begin
+ b:= t[1];
+ t[1]:= t[2];
+ t[2]:= b;
+
+ b:= t[0];
+ t[0]:= t[3];
+ t[3]:= b;
+ end;
+
+
+ function comp2str(d : bestreal) : string;
+ type
+ pdouble = ^double;
+ var
+ c : comp;
+ dd : pdouble;
+ begin
+ c:=comp(d);
+ dd:=pdouble(@c); { this makes a bitwise copy of c into a double }
+ comp2str:=double2str(dd^);
+ end;
+
+
+ function sizestr(s:topsize;dest:boolean):string;
+ begin
+ case s of
+ S_B : sizestr:='byte ';
+ S_W : sizestr:='word ';
+ S_L : sizestr:='dword ';
+ S_Q : sizestr:='qword ';
+ S_IS : sizestr:='word ';
+ S_IL : sizestr:='dword ';
+ S_IQ : sizestr:='qword ';
+ S_FS : sizestr:='dword ';
+ S_FL : sizestr:='qword ';
+ S_FX : sizestr:='tword ';
+ S_BW : if dest then
+ sizestr:='word '
+ else
+ sizestr:='byte ';
+ S_BL : if dest then
+ sizestr:='dword '
+ else
+ sizestr:='byte ';
+ S_WL : if dest then
+ sizestr:='dword '
+ else
+ sizestr:='word ';
+ else { S_NO }
+ sizestr:='';
+ end;
+ end;
+
+
+ Function PadTabs(const p:string;addch:char):string;
+ var
+ s : string;
+ i : longint;
+ begin
+ i:=length(p);
+ if addch<>#0 then
+ begin
+ inc(i);
+ s:=p+addch;
+ end
+ else
+ s:=p;
+ if i<8 then
+ PadTabs:=s+#9#9
+ else
+ PadTabs:=s+#9;
+ end;
+
+
+ type
+ PExternChain = ^TExternChain;
+
+ TExternChain = Record
+ psym : pshortstring;
+ is_defined : boolean;
+ next : PExternChain;
+ end;
+
+ const
+ FEC : PExternChain = nil;
+
+ procedure AddSymbol(symname : string; defined : boolean);
+ var
+ EC : PExternChain;
+ begin
+ EC:=FEC;
+ while assigned(EC) do
+ begin
+ if EC^.psym^=symname then
+ begin
+ if defined then
+ EC^.is_defined:=true;
+ exit;
+ end;
+ EC:=EC^.next;
+ end;
+ New(EC);
+ EC^.next:=FEC;
+ FEC:=EC;
+ FEC^.psym:=stringdup(symname);
+ FEC^.is_defined := defined;
+ end;
+
+ procedure FreeExternChainList;
+ var
+ EC : PExternChain;
+ begin
+ EC:=FEC;
+ while assigned(EC) do
+ begin
+ FEC:=EC^.next;
+ stringdispose(EC^.psym);
+ Dispose(EC);
+ EC:=FEC;
+ end;
+ end;
+
+{****************************************************************************
+ T386NasmAssembler
+ ****************************************************************************}
+
+ procedure T386NasmAssembler.WriteReference(var ref : treference);
+ var
+ first : boolean;
+ begin
+ with ref do
+ begin
+ AsmWrite('[');
+ first:=true;
+ if (segment<>NR_NO) then
+ AsmWrite(nasm_regname(segment)+':');
+ if assigned(symbol) then
+ begin
+ AsmWrite(symbol.name);
+ if SmartAsm then
+ AddSymbol(symbol.name,false);
+ first:=false;
+ end;
+ if (base<>NR_NO) then
+ begin
+ if not(first) then
+ AsmWrite('+')
+ else
+ first:=false;
+ AsmWrite(nasm_regname(base))
+ end;
+ if (index<>NR_NO) then
+ begin
+ if not(first) then
+ AsmWrite('+')
+ else
+ first:=false;
+ AsmWrite(nasm_regname(index));
+ if scalefactor<>0 then
+ AsmWrite('*'+tostr(scalefactor));
+ end;
+ if offset<0 then
+ begin
+ AsmWrite(tostr(offset));
+ first:=false;
+ end
+ else if (offset>0) then
+ begin
+ AsmWrite('+'+tostr(offset));
+ first:=false;
+ end;
+ if first then
+ AsmWrite('0');
+ AsmWrite(']');
+ end;
+ end;
+
+
+ procedure T386NasmAssembler.WriteOper(const o:toper;s : topsize; opcode: tasmop;ops:longint;dest : boolean);
+ begin
+ case o.typ of
+ top_reg :
+ AsmWrite(nasm_regname(o.reg));
+ top_const :
+ begin
+ if (ops=1) and (opcode<>A_RET) then
+ AsmWrite(sizestr(s,dest));
+ AsmWrite(tostr(longint(o.val)));
+ end;
+ top_ref :
+ begin
+ if o.ref^.refaddr=addr_no then
+ begin
+ if not ((opcode = A_LEA) or (opcode = A_LGS) or
+ (opcode = A_LSS) or (opcode = A_LFS) or
+ (opcode = A_LES) or (opcode = A_LDS) or
+ // (opcode = A_SHR) or (opcode = A_SHL) or
+ (opcode = A_SAR) or (opcode = A_SAL) or
+ (opcode = A_OUT) or (opcode = A_IN)) then
+ AsmWrite(sizestr(s,dest));
+ WriteReference(o.ref^);
+ end
+ else
+ begin
+ asmwrite('dword ');
+ if assigned(o.ref^.symbol) then
+ begin
+ if SmartAsm then
+ AddSymbol(o.ref^.symbol.name,false);
+ asmwrite(o.ref^.symbol.name);
+ if o.ref^.offset=0 then
+ exit;
+ end;
+ if o.ref^.offset>0 then
+ asmwrite('+');
+ asmwrite(tostr(o.ref^.offset));
+ end;
+ end;
+ else
+ internalerror(10001);
+ end;
+ end;
+
+
+ procedure T386NasmAssembler.WriteOper_jmp(const o:toper; op : tasmop);
+ begin
+ case o.typ of
+ top_reg :
+ AsmWrite(nasm_regname(o.reg));
+ top_ref :
+ if o.ref^.refaddr=addr_no then
+ WriteReference(o.ref^)
+ else
+ begin
+ if not(
+ (op=A_JCXZ) or (op=A_JECXZ) or
+{$ifdef x86_64}
+ (op=A_JRCXZ) or
+{$endif x86_64}
+ (op=A_LOOP) or (op=A_LOOPE) or
+ (op=A_LOOPNE) or (op=A_LOOPNZ) or
+ (op=A_LOOPZ)
+ ) then
+ AsmWrite('NEAR ');
+ AsmWrite(o.ref^.symbol.name);
+ if SmartAsm then
+ AddSymbol(o.ref^.symbol.name,false);
+ if o.ref^.offset>0 then
+ AsmWrite('+'+tostr(o.ref^.offset))
+ else
+ if o.ref^.offset<0 then
+ AsmWrite(tostr(o.ref^.offset));
+ end;
+ top_const :
+ AsmWrite(tostr(aint(o.val)));
+ else
+ internalerror(10001);
+ end;
+ end;
+
+
+ const
+ ait_const2str : array[aitconst_128bit..aitconst_secrel32_symbol] of string[20]=(
+ #9'FIXME_128BIT'#9,#9'FIXME_64BIT'#9,#9'DD'#9,#9'DW'#9,#9'DB'#9,
+ #9'FIXME_SLEB128BIT'#9,#9'FIXME_ULEB128BIT'#9,
+ #9'RVA'#9,#9'SECREL32'#9
+ );
+
+ procedure T386NasmAssembler.WriteSection(atype:TAsmSectiontype;const aname:string);
+ const
+ secnames : array[TAsmSectiontype] of string[length('__DATA, __datacoal_nt,coalesced')] = ('','',
+ '.text',
+ '.data',
+ '.data',
+ '.rodata',
+ '.bss',
+ '.tbss',
+ '.pdata',
+ '.text','.data','.data','.data','.data',
+ '.stab',
+ '.stabstr',
+ '.idata2','.idata4','.idata5','.idata6','.idata7','.edata',
+ '.eh_frame',
+ '.debug_frame','.debug_info','.debug_line','.debug_abbrev',
+ '.fpc',
+ '',
+ '.init',
+ '.fini',
+ '.objc_class',
+ '.objc_meta_class',
+ '.objc_cat_cls_meth',
+ '.objc_cat_inst_meth',
+ '.objc_protocol',
+ '.objc_string_object',
+ '.objc_cls_meth',
+ '.objc_inst_meth',
+ '.objc_cls_refs',
+ '.objc_message_refs',
+ '.objc_symbols',
+ '.objc_category',
+ '.objc_class_vars',
+ '.objc_instance_vars',
+ '.objc_module_info',
+ '.objc_class_names',
+ '.objc_meth_var_types',
+ '.objc_meth_var_names',
+ '.objc_selector_strs',
+ '.objc_protocol_ext',
+ '.objc_class_ext',
+ '.objc_property',
+ '.objc_image_info',
+ '.objc_cstring_object',
+ '.objc_sel_fixup',
+ '__DATA,__objc_data',
+ '__DATA,__objc_const',
+ '.objc_superrefs',
+ '__DATA, __datacoal_nt,coalesced',
+ '.objc_classlist',
+ '.objc_nlclasslist',
+ '.objc_catlist',
+ '.obcj_nlcatlist',
+ '.objc_protolist'
+ );
+ begin
+ AsmLn;
+ AsmWrite('SECTION ');
+ { go32v2 stub only loads .text and .data sections, and allocates space for .bss.
+ Thus, data which normally goes into .rodata and .rodata_norel sections must
+ end up in .data section }
+ if (atype in [sec_rodata,sec_rodata_norel]) and
+ (target_info.system=system_i386_go32v2) then
+ AsmWrite('.data')
+ else
+ AsmWrite(secnames[atype]);
+ if create_smartlink_sections and
+ (atype<>sec_bss) and
+ (aname<>'') then
+ begin
+ AsmWrite('.');
+ AsmWrite(aname);
+ end;
+ AsmLn;
+ LasTSecType:=atype;
+ end;
+
+ procedure T386NasmAssembler.WriteTree(p:TAsmList);
+{$ifdef cpuextended}
+ type
+ t80bitarray = array[0..9] of byte;
+{$endif cpuextended}
+ var
+ s : string;
+ hp : tai;
+ counter,
+ lines,
+ i,j,l : longint;
+ InlineLevel : longint;
+ consttype : taiconst_type;
+ do_line,
+ quoted : boolean;
+ co : comp;
+ sin : single;
+ d : double;
+{$ifdef cpuextended}
+ e : extended;
+{$endif cpuextended}
+ begin
+ if not assigned(p) then
+ exit;
+ InlineLevel:=0;
+ { lineinfo is only needed for al_procedures (PFV) }
+ do_line:=(cs_asm_source in current_settings.globalswitches) or
+ ((cs_lineinfo in current_settings.moduleswitches)
+ and (p=current_asmdata.asmlists[al_procedures]));
+ hp:=tai(p.first);
+ while assigned(hp) do
+ begin
+ prefetch(pointer(hp.next)^);
+ if not(hp.typ in SkipLineInfo) then
+ begin
+ current_filepos:=tailineinfo(hp).fileinfo;
+ { no line info for inlined code }
+ if do_line and (inlinelevel=0) then
+ WriteSourceLine(hp as tailineinfo);
+ end;
+
+ case hp.typ of
+ ait_comment :
+ Begin
+ AsmWrite(target_asm.comment);
+ AsmWritePChar(tai_comment(hp).str);
+ AsmLn;
+ End;
+
+ ait_regalloc :
+ begin
+ if (cs_asm_regalloc in current_settings.globalswitches) then
+ AsmWriteLn(#9#9+target_asm.comment+'Register '+nasm_regname(tai_regalloc(hp).reg)+
+ regallocstr[tai_regalloc(hp).ratype]);
+ end;
+
+ ait_tempalloc :
+ begin
+ if (cs_asm_tempalloc in current_settings.globalswitches) then
+ WriteTempalloc(tai_tempalloc(hp));
+ end;
+
+ ait_section :
+ begin
+ if tai_section(hp).sectype<>sec_none then
+ WriteSection(tai_section(hp).sectype,tai_section(hp).name^);
+ LasTSecType:=tai_section(hp).sectype;
+ end;
+
+ ait_align :
+ begin
+ { nasm gives warnings when it finds align in bss as it
+ wants to store data }
+ if (lastsectype<>sec_bss) and
+ (tai_align(hp).aligntype>1) then
+ AsmWriteLn(#9'ALIGN '+tostr(tai_align(hp).aligntype));
+ end;
+
+ ait_datablock :
+ begin
+ if tai_datablock(hp).is_global then
+ begin
+ AsmWrite(#9'GLOBAL ');
+ AsmWriteLn(tai_datablock(hp).sym.name);
+ end;
+ AsmWrite(PadTabs(tai_datablock(hp).sym.name,':'));
+ if SmartAsm then
+ AddSymbol(tai_datablock(hp).sym.name,true);
+ AsmWriteLn('RESB'#9+tostr(tai_datablock(hp).size));
+ end;
+
+ ait_const:
+ begin
+ consttype:=tai_const(hp).consttype;
+ case consttype of
+ aitconst_64bit :
+ begin
+ if assigned(tai_const(hp).sym) then
+ internalerror(200404292);
+ AsmWrite(ait_const2str[aitconst_32bit]);
+ AsmWrite(tostr(longint(lo(tai_const(hp).value))));
+ AsmWrite(',');
+ AsmWrite(tostr(longint(hi(tai_const(hp).value))));
+ AsmLn;
+ end;
+ aitconst_uleb128bit,
+ aitconst_sleb128bit,
+ aitconst_128bit:
+ begin
+ end;
+ aitconst_32bit,
+ aitconst_16bit,
+ aitconst_8bit,
+ aitconst_rva_symbol,
+ aitconst_secrel32_symbol :
+ begin
+ AsmWrite(ait_const2str[tai_const(hp).consttype]);
+ l:=0;
+ repeat
+ if assigned(tai_const(hp).sym) then
+ begin
+ if SmartAsm then
+ begin
+ AddSymbol(tai_const(hp).sym.name,false);
+ if assigned(tai_const(hp).endsym) then
+ AddSymbol(tai_const(hp).endsym.name,false);
+ end;
+ if assigned(tai_const(hp).endsym) then
+ s:=tai_const(hp).endsym.name+'-'+tai_const(hp).sym.name
+ else
+ s:=tai_const(hp).sym.name;
+ if tai_const(hp).value<>0 then
+ s:=s+tostr_with_plus(tai_const(hp).value);
+ end
+ else
+ s:=tostr(tai_const(hp).value);
+ AsmWrite(s);
+ inc(l,length(s));
+ if (l>line_length) or
+ (hp.next=nil) or
+ (tai(hp.next).typ<>ait_const) or
+ (tai_const(hp.next).consttype<>consttype) then
+ break;
+ hp:=tai(hp.next);
+ AsmWrite(',');
+ until false;
+ AsmLn;
+ end;
+ else
+ internalerror(200704252);
+ end;
+ end;
+
+{$if defined(cpuextended) and defined(FPC_HAS_TYPE_EXTENDED)}
+ ait_real_80bit :
+ begin
+ if do_line then
+ AsmWriteLn(target_asm.comment+'value: '+extended2str(tai_real_80bit(hp).value));
+ { Make sure e is a extended type, bestreal could be
+ a different type (bestreal) !! (PFV) }
+ e:=tai_real_80bit(hp).value;
+ AsmWrite(#9#9'DB'#9);
+ for i:=0 to 9 do
+ begin
+ if i<>0 then
+ AsmWrite(',');
+ AsmWrite(tostr(t80bitarray(e)[i]));
+ end;
+ for i:=11 to tai_real_80bit(hp).savesize do
+ AsmWrite(',0');
+ AsmLn;
+ end;
+{$else cpuextended}
+ ait_real_80bit :
+ AsmWriteLn(#9#9'DT'#9+extended2str(tai_real_80bit(hp).value));
+{$endif cpuextended}
+
+ // ait_real_64bit :
+ // AsmWriteLn(#9#9'DQ'#9+double2str(tai_real_64bit(hp).value));
+ ait_real_64bit :
+ begin
+ if do_line then
+ AsmWriteLn(target_asm.comment+'value: '+double2str(tai_real_64bit(hp).value));
+ d:=tai_real_64bit(hp).value;
+ { swap the values to correct endian if required }
+ if source_info.endian <> target_info.endian then
+ swap64bitarray(t64bitarray(d));
+ AsmWrite(#9#9'DB'#9);
+{$ifdef arm}
+ if tai_real_64bit(hp).formatoptions=fo_hiloswapped then
+ begin
+ for i:=4 to 7 do
+ begin
+ if i<>4 then
+ AsmWrite(',');
+ AsmWrite(tostr(t64bitarray(d)[i]));
+ end;
+ for i:=0 to 3 do
+ begin
+ AsmWrite(',');
+ AsmWrite(tostr(t64bitarray(d)[i]));
+ end;
+ end
+ else
+{$endif arm}
+ begin
+ for i:=0 to 7 do
+ begin
+ if i<>0 then
+ AsmWrite(',');
+ AsmWrite(tostr(t64bitarray(d)[i]));
+ end;
+ end;
+ AsmLn;
+ end;
+ // ait_real_32bit :
+ // AsmWriteLn(#9#9'DD'#9+single2str(tai_real_32bit(hp).value));
+ ait_real_32bit :
+ begin
+ if do_line then
+ AsmWriteLn(target_asm.comment+'value: '+single2str(tai_real_32bit(hp).value));
+ sin:=tai_real_32bit(hp).value;
+ { swap the values to correct endian if required }
+ if source_info.endian <> target_info.endian then
+ swap32bitarray(t32bitarray(sin));
+ AsmWrite(#9#9'DB'#9);
+ for i:=0 to 3 do
+ begin
+ if i<>0 then
+ AsmWrite(',');
+ AsmWrite(tostr(t32bitarray(sin)[i]));
+ end;
+ AsmLn;
+ end;
+ // ait_comp_64bit :
+ // AsmWriteLn(#9#9'DQ'#9+comp2str(tai_real_80bit(hp).value));
+ ait_comp_64bit :
+ begin
+ if do_line then
+ AsmWriteLn(target_asm.comment+'value: '+extended2str(tai_comp_64bit(hp).value));
+ AsmWrite(#9#9'DB'#9);
+ co:=comp(tai_comp_64bit(hp).value);
+ { swap the values to correct endian if required }
+ if source_info.endian <> target_info.endian then
+ swap64bitarray(t64bitarray(co));
+ for i:=0 to 7 do
+ begin
+ if i<>0 then
+ AsmWrite(',');
+ AsmWrite(tostr(t64bitarray(co)[i]));
+ end;
+ AsmLn;
+ end;
+
+ ait_string :
+ begin
+ counter := 0;
+ lines := tai_string(hp).len div line_length;
+ { separate lines in different parts }
+ if tai_string(hp).len > 0 then
+ Begin
+ for j := 0 to lines-1 do
+ begin
+ AsmWrite(#9#9'DB'#9);
+ quoted:=false;
+ for i:=counter to counter+line_length-1 do
+ begin
+ { it is an ascii character. }
+ if (ord(tai_string(hp).str[i])>31) and
+ (ord(tai_string(hp).str[i])<128) and
+ (tai_string(hp).str[i]<>'"') then
+ begin
+ if not(quoted) then
+ begin
+ if i>counter then
+ AsmWrite(',');
+ AsmWrite('"');
+ end;
+ AsmWrite(tai_string(hp).str[i]);
+ quoted:=true;
+ end { if > 31 and < 128 and ord('"') }
+ else
+ begin
+ if quoted then
+ AsmWrite('"');
+ if i>counter then
+ AsmWrite(',');
+ quoted:=false;
+ AsmWrite(tostr(ord(tai_string(hp).str[i])));
+ end;
+ end; { end for i:=0 to... }
+ if quoted then AsmWrite('"');
+ AsmWrite(target_info.newline);
+ inc(counter,line_length);
+ end; { end for j:=0 ... }
+ { do last line of lines }
+ if counter<tai_string(hp).len then
+ AsmWrite(#9#9'DB'#9);
+ quoted:=false;
+ for i:=counter to tai_string(hp).len-1 do
+ begin
+ { it is an ascii character. }
+ if (ord(tai_string(hp).str[i])>31) and
+ (ord(tai_string(hp).str[i])<128) and
+ (tai_string(hp).str[i]<>'"') then
+ begin
+ if not(quoted) then
+ begin
+ if i>counter then
+ AsmWrite(',');
+ AsmWrite('"');
+ end;
+ AsmWrite(tai_string(hp).str[i]);
+ quoted:=true;
+ end { if > 31 and < 128 and " }
+ else
+ begin
+ if quoted then
+ AsmWrite('"');
+ if i>counter then
+ AsmWrite(',');
+ quoted:=false;
+ AsmWrite(tostr(ord(tai_string(hp).str[i])));
+ end;
+ end; { end for i:=0 to... }
+ if quoted then
+ AsmWrite('"');
+ end;
+ AsmLn;
+ end;
+
+ ait_label :
+ begin
+ if tai_label(hp).labsym.is_used then
+ AsmWriteLn(tai_label(hp).labsym.name+':');
+ if SmartAsm then
+ AddSymbol(tai_label(hp).labsym.name,true);
+ end;
+
+ ait_symbol :
+ begin
+ if tai_symbol(hp).has_value then
+ internalerror(2009090803);
+ if tai_symbol(hp).is_global then
+ begin
+ AsmWrite(#9'GLOBAL ');
+ AsmWriteLn(tai_symbol(hp).sym.name);
+ end;
+ AsmWrite(tai_symbol(hp).sym.name);
+ if SmartAsm then
+ AddSymbol(tai_symbol(hp).sym.name,true);
+ if assigned(hp.next) and not(tai(hp.next).typ in
+ [ait_const,
+ ait_real_32bit,ait_real_64bit,ait_real_80bit,ait_comp_64bit,ait_string]) then
+ AsmWriteLn(':')
+ end;
+
+ ait_symbol_end : ;
+
+ ait_instruction :
+ begin
+ taicpu(hp).CheckNonCommutativeOpcodes;
+ { We need intel order, no At&t }
+ taicpu(hp).SetOperandOrder(op_intel);
+ s:='';
+ if ((taicpu(hp).opcode=A_FADDP) or
+ (taicpu(hp).opcode=A_FMULP))
+ and (taicpu(hp).ops=0) then
+ begin
+ taicpu(hp).allocate_oper(2);
+ taicpu(hp).oper[0]^.typ:=top_reg;
+ taicpu(hp).oper[0]^.reg:=NR_ST1;
+ taicpu(hp).oper[1]^.typ:=top_reg;
+ taicpu(hp).oper[1]^.reg:=NR_ST;
+ end;
+ if taicpu(hp).opcode=A_FWAIT then
+ AsmWriteln(#9#9'DB'#9'09bh')
+ else
+ begin
+ { We need to explicitely set
+ word prefix to get selectors
+ to be pushed in 2 bytes PM }
+ if (taicpu(hp).opsize=S_W) and
+ ((taicpu(hp).opcode=A_PUSH) or
+ (taicpu(hp).opcode=A_POP)) and
+ (taicpu(hp).oper[0]^.typ=top_reg) and
+ (is_segment_reg(taicpu(hp).oper[0]^.reg)) then
+ AsmWriteln(#9#9'DB'#9'066h');
+ AsmWrite(#9#9+std_op2str[taicpu(hp).opcode]+cond2str[taicpu(hp).condition]);
+ if taicpu(hp).ops<>0 then
+ begin
+ if is_calljmp(taicpu(hp).opcode) then
+ begin
+ AsmWrite(#9);
+ WriteOper_jmp(taicpu(hp).oper[0]^,taicpu(hp).opcode);
+ end
+ else
+ begin
+ for i:=0 to taicpu(hp).ops-1 do
+ begin
+ if i=0 then
+ AsmWrite(#9)
+ else
+ AsmWrite(',');
+ WriteOper(taicpu(hp).oper[i]^,taicpu(hp).opsize,taicpu(hp).opcode,taicpu(hp).ops,(i=2));
+ end;
+ end;
+ end;
+ AsmLn;
+ end;
+ end;
+
+ ait_stab,
+ ait_force_line,
+ ait_function_name : ;
+
+ ait_cutobject :
+ begin
+ if SmartAsm then
+ begin
+ { only reset buffer if nothing has changed }
+ if AsmSize=AsmStartSize then
+ AsmClear
+ else
+ begin
+ if SmartAsm then
+ begin
+ WriteSmartExternals;
+ FreeExternChainList;
+ end;
+ AsmClose;
+ DoAssemble;
+ AsmCreate(tai_cutobject(hp).place);
+ end;
+ { avoid empty files }
+ while assigned(hp.next) and (tai(hp.next).typ in [ait_cutobject,ait_section,ait_comment]) do
+ begin
+ if tai(hp.next).typ=ait_section then
+ lasTSectype:=tai_section(hp.next).sectype;
+ hp:=tai(hp.next);
+ end;
+ if lasTSectype<>sec_none then
+ WriteSection(lasTSectype,'');
+ AsmStartSize:=AsmSize;
+ end;
+ end;
+
+ ait_marker :
+ if tai_marker(hp).kind=mark_NoLineInfoStart then
+ inc(InlineLevel)
+ else if tai_marker(hp).kind=mark_NoLineInfoEnd then
+ dec(InlineLevel);
+
+ ait_directive :
+ begin
+ case tai_directive(hp).directive of
+ asd_nasm_import :
+ AsmWrite('import ');
+ asd_extern :
+ AsmWrite('EXTERN ');
+ else
+ internalerror(200509191);
+ end;
+ if assigned(tai_directive(hp).name) then
+ begin
+
+ if SmartAsm then
+ AddSymbol(tai_directive(hp).name^,false);
+
+ AsmWrite(tai_directive(hp).name^);
+ end;
+ AsmLn;
+ end;
+ ait_seh_directive :
+ { Ignore for now };
+ else
+ internalerror(10000);
+ end;
+ hp:=tai(hp.next);
+ end;
+ end;
+
+
+ procedure T386NasmAssembler.WriteExternals;
+ var
+ sym : TAsmSymbol;
+ i : longint;
+ begin
+ for i:=0 to current_asmdata.AsmSymbolDict.Count-1 do
+ begin
+ sym:=TAsmSymbol(current_asmdata.AsmSymbolDict[i]);
+ if sym.bind=AB_EXTERNAL then
+ AsmWriteln('EXTERN'#9+sym.name);
+ end;
+ end;
+
+ procedure T386NasmAssembler.WriteSmartExternals;
+ var
+ EC : PExternChain;
+ begin
+ EC:=FEC;
+ while assigned(EC) do
+ begin
+ if not EC^.is_defined then
+ AsmWriteln('EXTERN'#9+EC^.psym^);
+ EC:=EC^.next;
+ end;
+ end;
+
+
+ procedure T386NasmAssembler.WriteAsmList;
+ var
+ hal : tasmlisttype;
+ begin
+{$ifdef EXTDEBUG}
+ if assigned(current_module.mainsource) then
+ comment(v_info,'Start writing nasm-styled assembler output for '+current_module.mainsource^);
+{$endif}
+ AsmWriteLn('BITS 32');
+ AsmLn;
+
+ WriteExternals;
+
+ for hal:=low(TasmlistType) to high(TasmlistType) do
+ begin
+ AsmWriteLn(target_asm.comment+'Begin asmlist '+AsmListTypeStr[hal]);
+ writetree(current_asmdata.asmlists[hal]);
+ AsmWriteLn(target_asm.comment+'End asmlist '+AsmListTypeStr[hal]);
+ end;
+
+ AsmLn;
+ if SmartAsm then
+ begin
+ WriteSmartExternals;
+ FreeExternChainList;
+ end;
+{$ifdef EXTDEBUG}
+ if assigned(current_module.mainsource) then
+ comment(v_info,'Done writing nasm-styled assembler output for '+current_module.mainsource^);
+{$endif EXTDEBUG}
+ end;
+
+
+{*****************************************************************************
+ Initialize
+*****************************************************************************}
+
+ const
+ as_i386_nasmcoff_info : tasminfo =
+ (
+ id : as_i386_nasmcoff;
+ idtxt : 'NASMCOFF';
+ asmbin : 'nasm';
+ asmcmd : '-f coff -o $OBJ $ASM';
+ supported_targets : [system_i386_go32v2];
+ flags : [af_allowdirect,af_needar,af_no_debug];
+ labelprefix : '..@';
+ comment : '; ';
+ );
+
+ as_i386_nasmwin32_info : tasminfo =
+ (
+ id : as_i386_nasmwin32;
+ idtxt : 'NASMWIN32';
+ asmbin : 'nasm';
+ asmcmd : '-f win32 -o $OBJ $ASM';
+ supported_targets : [system_i386_win32];
+ flags : [af_allowdirect,af_needar,af_no_debug];
+ labelprefix : '..@';
+ comment : '; ';
+ );
+
+ as_i386_nasmobj_info : tasminfo =
+ (
+ id : as_i386_nasmobj;
+ idtxt : 'NASMOBJ';
+ asmbin : 'nasm';
+ asmcmd : '-f obj -o $OBJ $ASM';
+ supported_targets : [system_i386_embedded];
+ flags : [af_allowdirect,af_needar,af_no_debug];
+ labelprefix : '..@';
+ comment : '; ';
+ );
+
+ as_i386_nasmwdosx_info : tasminfo =
+ (
+ id : as_i386_nasmwdosx;
+ idtxt : 'NASMWDOSX';
+ asmbin : 'nasm';
+ asmcmd : '-f win32 -o $OBJ $ASM';
+ supported_targets : [system_i386_wdosx];
+ flags : [af_allowdirect,af_needar,af_no_debug];
+ labelprefix : '..@';
+ comment : '; ';
+ );
+
+
+ as_i386_nasmelf_info : tasminfo =
+ (
+ id : as_i386_nasmelf;
+ idtxt : 'NASMELF';
+ asmbin : 'nasm';
+ asmcmd : '-f elf -o $OBJ $ASM';
+ supported_targets : [system_i386_linux];
+ flags : [af_allowdirect,af_needar,af_no_debug];
+ labelprefix : '..@';
+ comment : '; ';
+ );
+
+ as_i386_nasmbeos_info : tasminfo =
+ (
+ id : as_i386_nasmbeos;
+ idtxt : 'NASMELF';
+ asmbin : 'nasm';
+ asmcmd : '-f elf -o $OBJ $ASM';
+ supported_targets : [system_i386_beos];
+ flags : [af_allowdirect,af_needar,af_no_debug];
+ labelprefix : '..@';
+ comment : '; ';
+ );
+
+ as_i386_nasmhaiku_info : tasminfo =
+ (
+ id : as_i386_nasmhaiku;
+ idtxt : 'NASMELF';
+ asmbin : 'nasm';
+ asmcmd : '-f elf -o $OBJ $ASM';
+ supported_targets : [system_i386_haiku];
+ flags : [af_allowdirect,af_needar,af_no_debug];
+ labelprefix : '..@';
+ comment : '; ';
+ );
+
+
+initialization
+ RegisterAssembler(as_i386_nasmcoff_info,T386NasmAssembler);
+ RegisterAssembler(as_i386_nasmwin32_info,T386NasmAssembler);
+ RegisterAssembler(as_i386_nasmwdosx_info,T386NasmAssembler);
+ RegisterAssembler(as_i386_nasmobj_info,T386NasmAssembler);
+ RegisterAssembler(as_i386_nasmbeos_info,T386NasmAssembler);
+ RegisterAssembler(as_i386_nasmhaiku_info,T386NasmAssembler);
+ RegisterAssembler(as_i386_nasmelf_info,T386NasmAssembler);
+end.
diff --git a/closures/compiler/x86/cga.pas b/closures/compiler/x86/cga.pas
new file mode 100644
index 0000000000..5eb62b49e4
--- /dev/null
+++ b/closures/compiler/x86/cga.pas
@@ -0,0 +1,132 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Helper routines for the i386 code generator
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+
+unit cga;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ globtype,
+ cpuinfo,cpubase,cgbase,cgutils,
+ symconst,symtype,symdef,aasmbase,aasmtai,aasmdata,aasmcpu;
+
+ procedure emit_none(i : tasmop;s : topsize);
+
+ procedure emit_reg(i : tasmop;s : topsize;reg : tregister);
+ procedure emit_ref(i : tasmop;s : topsize;ref : treference);
+
+ procedure emit_const_reg(i : tasmop;s : topsize;c : aint;reg : tregister);
+ procedure emit_const_ref(i : tasmop;s : topsize;c : aint;ref : treference);
+ procedure emit_ref_reg(i : tasmop;s : topsize;ref : treference;reg : tregister);
+ procedure emit_reg_ref(i : tasmop;s : topsize;reg : tregister;ref : treference);
+ procedure emit_reg_reg(i : tasmop;s : topsize;reg1,reg2 : tregister);
+
+ procedure emit_const_reg_reg(i : tasmop;s : topsize;c : longint;reg1,reg2 : tregister);
+ procedure emit_reg_reg_reg(i : tasmop;s : topsize;reg1,reg2,reg3 : tregister);
+
+
+ procedure emit_sym(i : tasmop;s : topsize;op : tasmsymbol);
+
+
+implementation
+
+ uses
+ cutils,
+ systems,verbose,
+ cgobj,cgx86;
+
+
+{*****************************************************************************
+ Emit Assembler
+*****************************************************************************}
+
+ procedure emit_none(i : tasmop;s : topsize);
+ begin
+ current_asmdata.CurrAsmList.concat(Taicpu.Op_none(i,s));
+ end;
+
+ procedure emit_reg(i : tasmop;s : topsize;reg : tregister);
+ begin
+ current_asmdata.CurrAsmList.concat(Taicpu.Op_reg(i,s,reg));
+ end;
+
+ procedure emit_ref(i : tasmop;s : topsize;ref : treference);
+ begin
+ tcgx86(cg).make_simple_ref(current_asmdata.CurrAsmList,ref);
+ current_asmdata.CurrAsmList.concat(Taicpu.Op_ref(i,s,ref));
+ end;
+
+ procedure emit_const_reg(i : tasmop;s : topsize;c : aint;reg : tregister);
+ begin
+ current_asmdata.CurrAsmList.concat(Taicpu.Op_const_reg(i,s,c,reg));
+ end;
+
+ procedure emit_const_ref(i : tasmop;s : topsize;c : aint;ref : treference);
+ begin
+ tcgx86(cg).make_simple_ref(current_asmdata.CurrAsmList,ref);
+ current_asmdata.CurrAsmList.concat(Taicpu.Op_const_ref(i,s,c,ref));
+ end;
+
+ procedure emit_ref_reg(i : tasmop;s : topsize;ref : treference;reg : tregister);
+ begin
+ tcgx86(cg).make_simple_ref(current_asmdata.CurrAsmList,ref);
+ current_asmdata.CurrAsmList.concat(Taicpu.Op_ref_reg(i,s,ref,reg));
+ end;
+
+ procedure emit_reg_ref(i : tasmop;s : topsize;reg : tregister;ref : treference);
+ begin
+ tcgx86(cg).make_simple_ref(current_asmdata.CurrAsmList,ref);
+ current_asmdata.CurrAsmList.concat(Taicpu.Op_reg_ref(i,s,reg,ref));
+ end;
+
+ procedure emit_reg_reg(i : tasmop;s : topsize;reg1,reg2 : tregister);
+
+ var instr:Taicpu;
+
+ begin
+ if not ((reg1=reg2) and (i=A_MOV)) then
+ begin
+ instr:=Taicpu.op_reg_reg(i,s,reg1,reg2);
+ current_asmdata.CurrAsmList.concat(instr);
+ if i=A_MOV then
+ cg.add_move_instruction(instr);
+ end;
+ end;
+
+ procedure emit_const_reg_reg(i : tasmop;s : topsize;c : longint;reg1,reg2 : tregister);
+ begin
+ current_asmdata.CurrAsmList.concat(Taicpu.Op_const_reg_reg(i,s,c,reg1,reg2));
+ end;
+
+ procedure emit_reg_reg_reg(i : tasmop;s : topsize;reg1,reg2,reg3 : tregister);
+ begin
+ current_asmdata.CurrAsmList.concat(Taicpu.Op_reg_reg_reg(i,s,reg1,reg2,reg3));
+ end;
+
+ procedure emit_sym(i : tasmop;s : topsize;op : tasmsymbol);
+ begin
+ current_asmdata.CurrAsmList.concat(Taicpu.Op_sym(i,s,op));
+ end;
+
+end.
diff --git a/closures/compiler/x86/cgx86.pas b/closures/compiler/x86/cgx86.pas
new file mode 100644
index 0000000000..03a32f3faa
--- /dev/null
+++ b/closures/compiler/x86/cgx86.pas
@@ -0,0 +1,2299 @@
+{
+ Copyright (c) 1998-2005 by Florian Klaempfl
+
+ This unit implements the common parts of the code generator for the i386 and the x86-64.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+{ This unit implements the common parts of the code generator for the i386 and the x86-64.
+}
+unit cgx86;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ globtype,
+ cgbase,cgutils,cgobj,
+ aasmbase,aasmtai,aasmdata,aasmcpu,
+ cpubase,cpuinfo,rgobj,rgx86,rgcpu,
+ symconst,symtype,symdef;
+
+ type
+ tcgx86 = class(tcg)
+ rgfpu : Trgx86fpu;
+ procedure done_register_allocators;override;
+
+ function getfpuregister(list:TAsmList;size:Tcgsize):Tregister;override;
+ function getmmxregister(list:TAsmList):Tregister;
+ function getmmregister(list:TAsmList;size:Tcgsize):Tregister;override;
+
+ procedure getcpuregister(list:TAsmList;r:Tregister);override;
+ procedure ungetcpuregister(list:TAsmList;r:Tregister);override;
+ procedure alloccpuregisters(list:TAsmList;rt:Tregistertype;const r:Tcpuregisterset);override;
+ procedure dealloccpuregisters(list:TAsmList;rt:Tregistertype;const r:Tcpuregisterset);override;
+ function uses_registers(rt:Tregistertype):boolean;override;
+ procedure add_reg_instruction(instr:Tai;r:tregister);override;
+ procedure dec_fpu_stack;
+ procedure inc_fpu_stack;
+
+ procedure a_call_name(list : TAsmList;const s : string; weak: boolean);override;
+ procedure a_call_reg(list : TAsmList;reg : tregister);override;
+ procedure a_call_ref(list : TAsmList;ref : treference);override;
+ procedure a_call_name_static(list : TAsmList;const s : string);override;
+
+ procedure a_op_const_reg(list : TAsmList; Op: TOpCG; size: TCGSize; a: tcgint; reg: TRegister); override;
+ procedure a_op_const_ref(list : TAsmList; Op: TOpCG; size: TCGSize; a: tcgint; const ref: TReference); override;
+ procedure a_op_reg_reg(list : TAsmList; Op: TOpCG; size: TCGSize; src, dst: TRegister); override;
+ procedure a_op_ref_reg(list : TAsmList; Op: TOpCG; size: TCGSize; const ref: TReference; reg: TRegister); override;
+ procedure a_op_reg_ref(list : TAsmList; Op: TOpCG; size: TCGSize;reg: TRegister; const ref: TReference); override;
+
+ { move instructions }
+ procedure a_load_const_reg(list : TAsmList; tosize: tcgsize; a : tcgint;reg : tregister);override;
+ procedure a_load_const_ref(list : TAsmList; tosize: tcgsize; a : tcgint;const ref : treference);override;
+ procedure a_load_reg_ref(list : TAsmList;fromsize,tosize: tcgsize; reg : tregister;const ref : treference);override;
+ procedure a_load_ref_reg(list : TAsmList;fromsize,tosize: tcgsize;const ref : treference;reg : tregister);override;
+ procedure a_load_reg_reg(list : TAsmList;fromsize,tosize: tcgsize;reg1,reg2 : tregister);override;
+ procedure a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);override;
+
+ { bit scan instructions }
+ procedure a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; size: TCGSize; src, dst: TRegister); override;
+
+ { fpu move instructions }
+ procedure a_loadfpu_reg_reg(list: TAsmList; fromsize, tosize: tcgsize; reg1, reg2: tregister); override;
+ procedure a_loadfpu_ref_reg(list: TAsmList; fromsize, tosize: tcgsize; const ref: treference; reg: tregister); override;
+ procedure a_loadfpu_reg_ref(list: TAsmList; fromsize, tosize: tcgsize; reg: tregister; const ref: treference); override;
+
+ { vector register move instructions }
+ procedure a_loadmm_reg_reg(list: TAsmList; fromsize, tosize : tcgsize;reg1, reg2: tregister;shuffle : pmmshuffle); override;
+ procedure a_loadmm_ref_reg(list: TAsmList; fromsize, tosize : tcgsize;const ref: treference; reg: tregister;shuffle : pmmshuffle); override;
+ procedure a_loadmm_reg_ref(list: TAsmList; fromsize, tosize : tcgsize;reg: tregister; const ref: treference;shuffle : pmmshuffle); override;
+ procedure a_opmm_ref_reg(list: TAsmList; Op: TOpCG; size : tcgsize;const ref: treference; reg: tregister;shuffle : pmmshuffle); override;
+ procedure a_opmm_reg_reg(list: TAsmList; Op: TOpCG; size : tcgsize;src,dst: tregister;shuffle : pmmshuffle);override;
+
+ { comparison operations }
+ procedure a_cmp_const_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;a : tcgint;reg : tregister;
+ l : tasmlabel);override;
+ procedure a_cmp_const_ref_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;a : tcgint;const ref : treference;
+ l : tasmlabel);override;
+ procedure a_cmp_reg_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel); override;
+ procedure a_cmp_ref_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;const ref: treference; reg : tregister; l : tasmlabel); override;
+ procedure a_cmp_reg_ref_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;reg : tregister; const ref: treference; l : tasmlabel); override;
+
+ procedure a_jmp_name(list : TAsmList;const s : string);override;
+ procedure a_jmp_always(list : TAsmList;l: tasmlabel); override;
+ procedure a_jmp_flags(list : TAsmList;const f : TResFlags;l: tasmlabel); override;
+
+ procedure g_flags2reg(list: TAsmList; size: TCgSize; const f: tresflags; reg: TRegister); override;
+ procedure g_flags2ref(list: TAsmList; size: TCgSize; const f: tresflags; const ref: TReference); override;
+
+ procedure g_concatcopy(list : TAsmList;const source,dest : treference;len : tcgint);override;
+
+ { entry/exit code helpers }
+ procedure g_profilecode(list : TAsmList);override;
+ procedure g_stackpointer_alloc(list : TAsmList;localsize : longint);override;
+ procedure g_proc_entry(list : TAsmList;localsize : longint;nostackframe:boolean);override;
+
+ procedure g_overflowcheck(list: TAsmList; const l:tlocation;def:tdef);override;
+
+ procedure g_external_wrapper(list: TAsmList; procdef: tprocdef; const externalname: string); override;
+
+ procedure make_simple_ref(list:TAsmList;var ref: treference);
+ protected
+ procedure a_jmp_cond(list : TAsmList;cond : TOpCmp;l: tasmlabel);
+ procedure check_register_size(size:tcgsize;reg:tregister);
+
+ procedure opmm_loc_reg(list: TAsmList; Op: TOpCG; size : tcgsize;loc : tlocation;dst: tregister; shuffle : pmmshuffle);
+
+ function get_darwin_call_stub(const s: string; weak: boolean): tasmsymbol;
+ private
+ procedure sizes2load(s1,s2 : tcgsize;var op: tasmop; var s3: topsize);
+
+ procedure floatload(list: TAsmList; t : tcgsize;const ref : treference);
+ procedure floatstore(list: TAsmList; t : tcgsize;const ref : treference);
+ procedure floatloadops(t : tcgsize;var op : tasmop;var s : topsize);
+ procedure floatstoreops(t : tcgsize;var op : tasmop;var s : topsize);
+
+ end;
+
+ const
+{$ifdef x86_64}
+ TCGSize2OpSize: Array[tcgsize] of topsize =
+ (S_NO,S_B,S_W,S_L,S_Q,S_T,S_B,S_W,S_L,S_Q,S_Q,
+ S_FS,S_FL,S_FX,S_IQ,S_FXX,
+ S_NO,S_NO,S_NO,S_MD,S_T,
+ S_NO,S_NO,S_NO,S_NO,S_T);
+{$else x86_64}
+ TCGSize2OpSize: Array[tcgsize] of topsize =
+ (S_NO,S_B,S_W,S_L,S_L,S_T,S_B,S_W,S_L,S_L,S_L,
+ S_FS,S_FL,S_FX,S_IQ,S_FXX,
+ S_NO,S_NO,S_NO,S_MD,S_T,
+ S_NO,S_NO,S_NO,S_NO,S_T);
+{$endif x86_64}
+
+{$ifndef NOTARGETWIN}
+ winstackpagesize = 4096;
+{$endif NOTARGETWIN}
+
+ implementation
+
+ uses
+ globals,verbose,systems,cutils,
+ defutil,paramgr,procinfo,
+ tgobj,ncgutil,
+ fmodule,symsym;
+
+ const
+ TOpCG2AsmOp: Array[topcg] of TAsmOp = (A_NONE,A_MOV,A_ADD,A_AND,A_DIV,
+ A_IDIV,A_IMUL,A_MUL,A_NEG,A_NOT,A_OR,
+ A_SAR,A_SHL,A_SHR,A_SUB,A_XOR,A_ROL,A_ROR);
+
+ TOpCmp2AsmCond: Array[topcmp] of TAsmCond = (C_NONE,
+ C_E,C_G,C_L,C_GE,C_LE,C_NE,C_BE,C_B,C_AE,C_A);
+
+ procedure Tcgx86.done_register_allocators;
+ begin
+ rg[R_INTREGISTER].free;
+ rg[R_MMREGISTER].free;
+ rg[R_MMXREGISTER].free;
+ rgfpu.free;
+ inherited done_register_allocators;
+ end;
+
+
+ function Tcgx86.getfpuregister(list:TAsmList;size:Tcgsize):Tregister;
+ begin
+ result:=rgfpu.getregisterfpu(list);
+ end;
+
+
+ function Tcgx86.getmmxregister(list:TAsmList):Tregister;
+ begin
+ if not assigned(rg[R_MMXREGISTER]) then
+ internalerror(2003121214);
+ result:=rg[R_MMXREGISTER].getregister(list,R_SUBNONE);
+ end;
+
+
+ function Tcgx86.getmmregister(list:TAsmList;size:Tcgsize):Tregister;
+ begin
+ if not assigned(rg[R_MMREGISTER]) then
+ internalerror(2003121234);
+ case size of
+ OS_F64:
+ result:=rg[R_MMREGISTER].getregister(list,R_SUBMMD);
+ OS_F32:
+ result:=rg[R_MMREGISTER].getregister(list,R_SUBMMS);
+ OS_M64,
+ OS_M128:
+ result:=rg[R_MMREGISTER].getregister(list,R_SUBMMWHOLE);
+ else
+ internalerror(200506041);
+ end;
+ end;
+
+
+ procedure Tcgx86.getcpuregister(list:TAsmList;r:Tregister);
+ begin
+ if getregtype(r)=R_FPUREGISTER then
+ internalerror(2003121210)
+ else
+ inherited getcpuregister(list,r);
+ end;
+
+
+ procedure tcgx86.ungetcpuregister(list:TAsmList;r:Tregister);
+ begin
+ if getregtype(r)=R_FPUREGISTER then
+ rgfpu.ungetregisterfpu(list,r)
+ else
+ inherited ungetcpuregister(list,r);
+ end;
+
+
+ procedure Tcgx86.alloccpuregisters(list:TAsmList;rt:Tregistertype;const r:Tcpuregisterset);
+ begin
+ if rt<>R_FPUREGISTER then
+ inherited alloccpuregisters(list,rt,r);
+ end;
+
+
+ procedure Tcgx86.dealloccpuregisters(list:TAsmList;rt:Tregistertype;const r:Tcpuregisterset);
+ begin
+ if rt<>R_FPUREGISTER then
+ inherited dealloccpuregisters(list,rt,r);
+ end;
+
+
+ function Tcgx86.uses_registers(rt:Tregistertype):boolean;
+ begin
+ if rt=R_FPUREGISTER then
+ result:=false
+ else
+ result:=inherited uses_registers(rt);
+ end;
+
+
+ procedure tcgx86.add_reg_instruction(instr:Tai;r:tregister);
+ begin
+ if getregtype(r)<>R_FPUREGISTER then
+ inherited add_reg_instruction(instr,r);
+ end;
+
+
+ procedure tcgx86.dec_fpu_stack;
+ begin
+ if rgfpu.fpuvaroffset<=0 then
+ internalerror(200604201);
+ dec(rgfpu.fpuvaroffset);
+ end;
+
+
+ procedure tcgx86.inc_fpu_stack;
+ begin
+ inc(rgfpu.fpuvaroffset);
+ end;
+
+
+{****************************************************************************
+ This is private property, keep out! :)
+****************************************************************************}
+
+ procedure tcgx86.sizes2load(s1,s2 : tcgsize; var op: tasmop; var s3: topsize);
+
+ begin
+ { ensure to have always valid sizes }
+ if s1=OS_NO then
+ s1:=s2;
+ if s2=OS_NO then
+ s2:=s1;
+ case s2 of
+ OS_8,OS_S8 :
+ if S1 in [OS_8,OS_S8] then
+ s3 := S_B
+ else
+ internalerror(200109221);
+ OS_16,OS_S16:
+ case s1 of
+ OS_8,OS_S8:
+ s3 := S_BW;
+ OS_16,OS_S16:
+ s3 := S_W;
+ else
+ internalerror(200109222);
+ end;
+ OS_32,OS_S32:
+ case s1 of
+ OS_8,OS_S8:
+ s3 := S_BL;
+ OS_16,OS_S16:
+ s3 := S_WL;
+ OS_32,OS_S32:
+ s3 := S_L;
+ else
+ internalerror(200109223);
+ end;
+{$ifdef x86_64}
+ OS_64,OS_S64:
+ case s1 of
+ OS_8:
+ s3 := S_BL;
+ OS_S8:
+ s3 := S_BQ;
+ OS_16:
+ s3 := S_WL;
+ OS_S16:
+ s3 := S_WQ;
+ OS_32:
+ s3 := S_L;
+ OS_S32:
+ s3 := S_LQ;
+ OS_64,OS_S64:
+ s3 := S_Q;
+ else
+ internalerror(200304302);
+ end;
+{$endif x86_64}
+ else
+ internalerror(200109227);
+ end;
+ if s3 in [S_B,S_W,S_L,S_Q] then
+ op := A_MOV
+ else if s1 in [OS_8,OS_16,OS_32,OS_64] then
+ op := A_MOVZX
+ else
+{$ifdef x86_64}
+ if s3 in [S_LQ] then
+ op := A_MOVSXD
+ else
+{$endif x86_64}
+ op := A_MOVSX;
+ end;
+
+
+ procedure tcgx86.make_simple_ref(list:TAsmList;var ref: treference);
+ var
+ hreg : tregister;
+ href : treference;
+{$ifndef x86_64}
+ add_hreg: boolean;
+{$endif not x86_64}
+ begin
+ { make_simple_ref() may have already been called earlier, and in that
+ case make sure we don't perform the PIC-simplifications twice }
+ if (ref.refaddr in [addr_pic,addr_pic_no_got]) then
+ exit;
+
+{$ifdef x86_64}
+ { Only 32bit is allowed }
+ if ((ref.offset<low(longint)) or (ref.offset>high(longint))) then
+ begin
+ { Load constant value to register }
+ hreg:=GetAddressRegister(list);
+ list.concat(taicpu.op_const_reg(A_MOV,S_Q,ref.offset,hreg));
+ ref.offset:=0;
+ {if assigned(ref.symbol) then
+ begin
+ list.concat(taicpu.op_sym_ofs_reg(A_ADD,S_Q,ref.symbol,0,hreg));
+ ref.symbol:=nil;
+ end;}
+ { Add register to reference }
+ if ref.index=NR_NO then
+ ref.index:=hreg
+ else
+ begin
+ { don't use add, as the flags may contain a value }
+ reference_reset_base(href,ref.base,0,8);
+ href.index:=hreg;
+ if ref.scalefactor<>0 then
+ begin
+ reference_reset_base(href,ref.base,0,8);
+ href.index:=hreg;
+ list.concat(taicpu.op_ref_reg(A_LEA,S_Q,href,hreg));
+ ref.base:=hreg;
+ end
+ else
+ begin
+ reference_reset_base(href,ref.index,0,8);
+ href.index:=hreg;
+ list.concat(taicpu.op_reg_reg(A_ADD,S_Q,ref.index,hreg));
+ ref.index:=hreg;
+ end;
+ end;
+ end;
+
+ if assigned(ref.symbol) and not((ref.symbol.bind=AB_LOCAL) and (ref.symbol.typ in [AT_LABEL,AT_FUNCTION])) then
+ begin
+ if cs_create_pic in current_settings.moduleswitches then
+ begin
+ { Local data symbols must not be accessed via the GOT on
+ darwin/x86_64 under certain circumstances (and do not
+ have to be in other cases); however, linux/x86_64 does
+ require it; don't know about others, so do use GOT for
+ safety reasons
+ }
+ if (ref.symbol.bind=AB_LOCAL) and
+ (ref.symbol.typ=AT_DATA) then
+ begin
+ { unfortunately, RIP-based addresses don't support an index }
+ if (ref.base<>NR_NO) or
+ (ref.index<>NR_NO) then
+ begin
+ reference_reset_symbol(href,ref.symbol,0,ref.alignment);
+ hreg:=getaddressregister(list);
+ href.refaddr:=addr_pic_no_got;
+ href.base:=NR_RIP;
+ list.concat(taicpu.op_ref_reg(A_LEA,S_Q,href,hreg));
+ ref.symbol:=nil;
+ end
+ else
+ begin
+ ref.refaddr:=addr_pic_no_got;
+ hreg:=NR_NO;
+ ref.base:=NR_RIP;
+ end;
+ end
+ else
+ begin
+ reference_reset_symbol(href,ref.symbol,0,ref.alignment);
+ hreg:=getaddressregister(list);
+ href.refaddr:=addr_pic;
+ href.base:=NR_RIP;
+ list.concat(taicpu.op_ref_reg(A_MOV,S_Q,href,hreg));
+
+ ref.symbol:=nil;
+ end;
+
+ if ref.base=NR_NO then
+ ref.base:=hreg
+ else if ref.index=NR_NO then
+ begin
+ ref.index:=hreg;
+ ref.scalefactor:=1;
+ end
+ else
+ begin
+ { don't use add, as the flags may contain a value }
+ reference_reset_base(href,ref.base,0,8);
+ href.index:=hreg;
+ list.concat(taicpu.op_ref_reg(A_LEA,S_Q,href,hreg));
+ ref.base:=hreg;
+ end;
+ end
+ else
+ { Always use RIP relative symbol addressing for Windows and Darwin targets. }
+ if (target_info.system in (systems_all_windows+[system_x86_64_darwin])) and (ref.base<>NR_RIP) then
+ begin
+ if (ref.refaddr=addr_no) and (ref.base=NR_NO) and (ref.index=NR_NO) then
+ begin
+ { Set RIP relative addressing for simple symbol references }
+ ref.base:=NR_RIP;
+ ref.refaddr:=addr_pic_no_got
+ end
+ else
+ begin
+ { Use temp register to load calculated 64-bit symbol address for complex references }
+ reference_reset_symbol(href,ref.symbol,0,sizeof(pint));
+ href.base:=NR_RIP;
+ href.refaddr:=addr_pic_no_got;
+ hreg:=GetAddressRegister(list);
+ list.concat(taicpu.op_ref_reg(A_LEA,S_Q,href,hreg));
+ ref.symbol:=nil;
+ if ref.base=NR_NO then
+ ref.base:=hreg
+ else if ref.index=NR_NO then
+ begin
+ ref.index:=hreg;
+ ref.scalefactor:=0;
+ end
+ else
+ begin
+ { don't use add, as the flags may contain a value }
+ reference_reset_base(href,ref.base,0,8);
+ href.index:=hreg;
+ list.concat(taicpu.op_ref_reg(A_LEA,S_Q,href,hreg));
+ ref.base:=hreg;
+ end;
+ end;
+
+ end;
+ end;
+{$else x86_64}
+ add_hreg:=false;
+ if (target_info.system in [system_i386_darwin,system_i386_iphonesim]) then
+ begin
+ if assigned(ref.symbol) and
+ not(assigned(ref.relsymbol)) and
+ ((ref.symbol.bind in [AB_EXTERNAL,AB_WEAK_EXTERNAL]) or
+ (cs_create_pic in current_settings.moduleswitches)) then
+ begin
+ if (ref.symbol.bind in [AB_EXTERNAL,AB_WEAK_EXTERNAL]) or
+ ((cs_create_pic in current_settings.moduleswitches) and
+ (ref.symbol.bind in [AB_COMMON,AB_GLOBAL,AB_PRIVATE_EXTERN])) then
+ begin
+ hreg:=g_indirect_sym_load(list,ref.symbol.name,ref.symbol.bind=AB_WEAK_EXTERNAL);
+ ref.symbol:=nil;
+ end
+ else
+ begin
+ include(current_procinfo.flags,pi_needs_got);
+ hreg:=current_procinfo.got;
+ ref.relsymbol:=current_procinfo.CurrGOTLabel;
+ end;
+ add_hreg:=true
+ end
+ end
+ else if (cs_create_pic in current_settings.moduleswitches) and
+ assigned(ref.symbol) and
+ not((ref.symbol.bind=AB_LOCAL) and
+ (ref.symbol.typ in [AT_LABEL,AT_FUNCTION])) then
+ begin
+ reference_reset_symbol(href,ref.symbol,0,sizeof(pint));
+ href.base:=current_procinfo.got;
+ href.refaddr:=addr_pic;
+ include(current_procinfo.flags,pi_needs_got);
+ hreg:=cg.getaddressregister(list);
+ list.concat(taicpu.op_ref_reg(A_MOV,S_L,href,hreg));
+ ref.symbol:=nil;
+ add_hreg:=true;
+ end;
+
+ if add_hreg then
+ begin
+ if ref.base=NR_NO then
+ ref.base:=hreg
+ else if ref.index=NR_NO then
+ begin
+ ref.index:=hreg;
+ ref.scalefactor:=1;
+ end
+ else
+ begin
+ { don't use add, as the flags may contain a value }
+ reference_reset_base(href,ref.base,0,8);
+ href.index:=hreg;
+ list.concat(taicpu.op_ref_reg(A_LEA,S_L,href,hreg));
+ ref.base:=hreg;
+ end;
+ end;
+{$endif x86_64}
+ end;
+
+
+ procedure tcgx86.floatloadops(t : tcgsize;var op : tasmop;var s : topsize);
+ begin
+ case t of
+ OS_F32 :
+ begin
+ op:=A_FLD;
+ s:=S_FS;
+ end;
+ OS_F64 :
+ begin
+ op:=A_FLD;
+ s:=S_FL;
+ end;
+ OS_F80 :
+ begin
+ op:=A_FLD;
+ s:=S_FX;
+ end;
+ OS_C64 :
+ begin
+ op:=A_FILD;
+ s:=S_IQ;
+ end;
+ else
+ internalerror(200204043);
+ end;
+ end;
+
+
+ procedure tcgx86.floatload(list: TAsmList; t : tcgsize;const ref : treference);
+
+ var
+ op : tasmop;
+ s : topsize;
+ tmpref : treference;
+ begin
+ tmpref:=ref;
+ make_simple_ref(list,tmpref);
+ floatloadops(t,op,s);
+ list.concat(Taicpu.Op_ref(op,s,tmpref));
+ inc_fpu_stack;
+ end;
+
+
+ procedure tcgx86.floatstoreops(t : tcgsize;var op : tasmop;var s : topsize);
+
+ begin
+ case t of
+ OS_F32 :
+ begin
+ op:=A_FSTP;
+ s:=S_FS;
+ end;
+ OS_F64 :
+ begin
+ op:=A_FSTP;
+ s:=S_FL;
+ end;
+ OS_F80 :
+ begin
+ op:=A_FSTP;
+ s:=S_FX;
+ end;
+ OS_C64 :
+ begin
+ op:=A_FISTP;
+ s:=S_IQ;
+ end;
+ else
+ internalerror(200204042);
+ end;
+ end;
+
+
+ procedure tcgx86.floatstore(list: TAsmList; t : tcgsize;const ref : treference);
+
+ var
+ op : tasmop;
+ s : topsize;
+ tmpref : treference;
+ begin
+ tmpref:=ref;
+ make_simple_ref(list,tmpref);
+ floatstoreops(t,op,s);
+ list.concat(Taicpu.Op_ref(op,s,tmpref));
+ { storing non extended floats can cause a floating point overflow }
+ if (t<>OS_F80) and
+ (cs_fpu_fwait in current_settings.localswitches) then
+ list.concat(Taicpu.Op_none(A_FWAIT,S_NO));
+ dec_fpu_stack;
+ end;
+
+
+ procedure tcgx86.check_register_size(size:tcgsize;reg:tregister);
+ begin
+ if TCGSize2OpSize[size]<>TCGSize2OpSize[reg_cgsize(reg)] then
+ internalerror(200306031);
+ end;
+
+
+{****************************************************************************
+ Assembler code
+****************************************************************************}
+
+ procedure tcgx86.a_jmp_name(list : TAsmList;const s : string);
+ var
+ r: treference;
+ begin
+ if (target_info.system <> system_i386_darwin) then
+ list.concat(taicpu.op_sym(A_JMP,S_NO,current_asmdata.RefAsmSymbol(s)))
+ else
+ begin
+ reference_reset_symbol(r,get_darwin_call_stub(s,false),0,sizeof(pint));
+ r.refaddr:=addr_full;
+ list.concat(taicpu.op_ref(A_JMP,S_NO,r));
+ end;
+ end;
+
+
+ procedure tcgx86.a_jmp_always(list : TAsmList;l: tasmlabel);
+ begin
+ a_jmp_cond(list, OC_NONE, l);
+ end;
+
+
+ function tcgx86.get_darwin_call_stub(const s: string; weak: boolean): tasmsymbol;
+ var
+ stubname: string;
+ begin
+ stubname := 'L'+s+'$stub';
+ result := current_asmdata.getasmsymbol(stubname);
+ if assigned(result) then
+ exit;
+
+ if current_asmdata.asmlists[al_imports]=nil then
+ current_asmdata.asmlists[al_imports]:=TAsmList.create;
+
+ new_section(current_asmdata.asmlists[al_imports],sec_stub,'',0);
+ result := current_asmdata.RefAsmSymbol(stubname);
+ current_asmdata.asmlists[al_imports].concat(Tai_symbol.Create(result,0));
+ { register as a weak symbol if necessary }
+ if weak then
+ current_asmdata.weakrefasmsymbol(s);
+ current_asmdata.asmlists[al_imports].concat(tai_directive.create(asd_indirect_symbol,s));
+ current_asmdata.asmlists[al_imports].concat(taicpu.op_none(A_HLT));
+ current_asmdata.asmlists[al_imports].concat(taicpu.op_none(A_HLT));
+ current_asmdata.asmlists[al_imports].concat(taicpu.op_none(A_HLT));
+ current_asmdata.asmlists[al_imports].concat(taicpu.op_none(A_HLT));
+ current_asmdata.asmlists[al_imports].concat(taicpu.op_none(A_HLT));
+ end;
+
+
+ procedure tcgx86.a_call_name(list : TAsmList;const s : string; weak: boolean);
+ var
+ sym : tasmsymbol;
+ r : treference;
+ begin
+
+ if (target_info.system <> system_i386_darwin) then
+ begin
+ if not(weak) then
+ sym:=current_asmdata.RefAsmSymbol(s)
+ else
+ sym:=current_asmdata.WeakRefAsmSymbol(s);
+ reference_reset_symbol(r,sym,0,sizeof(pint));
+ if (cs_create_pic in current_settings.moduleswitches) and
+ { darwin's assembler doesn't want @PLT after call symbols }
+ not(target_info.system in [system_x86_64_darwin,system_i386_iphonesim]) then
+ begin
+{$ifdef i386}
+ include(current_procinfo.flags,pi_needs_got);
+{$endif i386}
+ r.refaddr:=addr_pic
+ end
+ else
+ r.refaddr:=addr_full;
+ end
+ else
+ begin
+ reference_reset_symbol(r,get_darwin_call_stub(s,weak),0,sizeof(pint));
+ r.refaddr:=addr_full;
+ end;
+ list.concat(taicpu.op_ref(A_CALL,S_NO,r));
+ end;
+
+
+ procedure tcgx86.a_call_name_static(list : TAsmList;const s : string);
+ var
+ sym : tasmsymbol;
+ r : treference;
+ begin
+ sym:=current_asmdata.RefAsmSymbol(s);
+ reference_reset_symbol(r,sym,0,sizeof(pint));
+ r.refaddr:=addr_full;
+ list.concat(taicpu.op_ref(A_CALL,S_NO,r));
+ end;
+
+
+ procedure tcgx86.a_call_reg(list : TAsmList;reg : tregister);
+ begin
+ list.concat(taicpu.op_reg(A_CALL,S_NO,reg));
+ end;
+
+
+ procedure tcgx86.a_call_ref(list : TAsmList;ref : treference);
+ begin
+ list.concat(taicpu.op_ref(A_CALL,S_NO,ref));
+ end;
+
+
+{********************** load instructions ********************}
+
+ procedure tcgx86.a_load_const_reg(list : TAsmList; tosize: TCGSize; a : tcgint; reg : TRegister);
+
+ begin
+ check_register_size(tosize,reg);
+ { the optimizer will change it to "xor reg,reg" when loading zero, }
+ { no need to do it here too (JM) }
+ list.concat(taicpu.op_const_reg(A_MOV,TCGSize2OpSize[tosize],a,reg))
+ end;
+
+
+ procedure tcgx86.a_load_const_ref(list : TAsmList; tosize: tcgsize; a : tcgint;const ref : treference);
+ var
+ tmpref : treference;
+ begin
+ tmpref:=ref;
+ make_simple_ref(list,tmpref);
+{$ifdef x86_64}
+ { x86_64 only supports signed 32 bits constants directly }
+ if (tosize in [OS_S64,OS_64]) and
+ ((a<low(longint)) or (a>high(longint))) then
+ begin
+ a_load_const_ref(list,OS_32,longint(a and $ffffffff),tmpref);
+ inc(tmpref.offset,4);
+ a_load_const_ref(list,OS_32,longint(a shr 32),tmpref);
+ end
+ else
+{$endif x86_64}
+ list.concat(taicpu.op_const_ref(A_MOV,TCGSize2OpSize[tosize],a,tmpref));
+ end;
+
+
+ procedure tcgx86.a_load_reg_ref(list : TAsmList; fromsize,tosize: TCGSize; reg : tregister;const ref : treference);
+ var
+ op: tasmop;
+ s: topsize;
+ tmpsize : tcgsize;
+ tmpreg : tregister;
+ tmpref : treference;
+ begin
+ tmpref:=ref;
+ make_simple_ref(list,tmpref);
+ check_register_size(fromsize,reg);
+ sizes2load(fromsize,tosize,op,s);
+ case s of
+{$ifdef x86_64}
+ S_BQ,S_WQ,S_LQ,
+{$endif x86_64}
+ S_BW,S_BL,S_WL :
+ begin
+ tmpreg:=getintregister(list,tosize);
+{$ifdef x86_64}
+ { zero extensions to 64 bit on the x86_64 are simply done by writting to the lower 32 bit
+ which clears the upper 64 bit too, so it could be that s is S_L while the reg is
+ 64 bit (FK) }
+ if s in [S_BL,S_WL,S_L] then
+ begin
+ tmpreg:=makeregsize(list,tmpreg,OS_32);
+ tmpsize:=OS_32;
+ end
+ else
+{$endif x86_64}
+ tmpsize:=tosize;
+ list.concat(taicpu.op_reg_reg(op,s,reg,tmpreg));
+ a_load_reg_ref(list,tmpsize,tosize,tmpreg,tmpref);
+ end;
+ else
+ list.concat(taicpu.op_reg_ref(op,s,reg,tmpref));
+ end;
+ end;
+
+
+ procedure tcgx86.a_load_ref_reg(list : TAsmList;fromsize,tosize : tcgsize;const ref: treference;reg : tregister);
+ var
+ op: tasmop;
+ s: topsize;
+ tmpref : treference;
+ begin
+ tmpref:=ref;
+ make_simple_ref(list,tmpref);
+ check_register_size(tosize,reg);
+ sizes2load(fromsize,tosize,op,s);
+ {$ifdef x86_64}
+ { zero extensions to 64 bit on the x86_64 are simply done by writting to the lower 32 bit
+ which clears the upper 64 bit too, so it could be that s is S_L while the reg is
+ 64 bit (FK) }
+ if s in [S_BL,S_WL,S_L] then
+ reg:=makeregsize(list,reg,OS_32);
+{$endif x86_64}
+ list.concat(taicpu.op_ref_reg(op,s,tmpref,reg));
+ end;
+
+
+ procedure tcgx86.a_load_reg_reg(list : TAsmList;fromsize,tosize : tcgsize;reg1,reg2 : tregister);
+ var
+ op: tasmop;
+ s: topsize;
+ instr:Taicpu;
+ begin
+ check_register_size(fromsize,reg1);
+ check_register_size(tosize,reg2);
+ if tcgsize2size[fromsize]>tcgsize2size[tosize] then
+ begin
+ reg1:=makeregsize(list,reg1,tosize);
+ s:=tcgsize2opsize[tosize];
+ op:=A_MOV;
+ end
+ else
+ sizes2load(fromsize,tosize,op,s);
+{$ifdef x86_64}
+ { zero extensions to 64 bit on the x86_64 are simply done by writting to the lower 32 bit
+ which clears the upper 64 bit too, so it could be that s is S_L while the reg is
+ 64 bit (FK)
+ }
+ if s in [S_BL,S_WL,S_L] then
+ reg2:=makeregsize(list,reg2,OS_32);
+{$endif x86_64}
+ if (reg1<>reg2) then
+ begin
+ instr:=taicpu.op_reg_reg(op,s,reg1,reg2);
+ { Notify the register allocator that we have written a move instruction so
+ it can try to eliminate it. }
+ if (reg1<>current_procinfo.framepointer) and (reg1<>NR_STACK_POINTER_REG) then
+ add_move_instruction(instr);
+ list.concat(instr);
+ end;
+{$ifdef x86_64}
+ { avoid merging of registers and killing the zero extensions (FK) }
+ if (tosize in [OS_64,OS_S64]) and (s=S_L) then
+ list.concat(taicpu.op_const_reg(A_AND,S_L,$ffffffff,reg2));
+{$endif x86_64}
+ end;
+
+
+ procedure tcgx86.a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);
+ var
+ tmpref : treference;
+ begin
+ with ref do
+ begin
+ if (base=NR_NO) and (index=NR_NO) then
+ begin
+ if assigned(ref.symbol) then
+ begin
+ if (target_info.system in [system_i386_darwin,system_i386_iphonesim]) and
+ ((ref.symbol.bind in [AB_EXTERNAL,AB_WEAK_EXTERNAL]) or
+ (cs_create_pic in current_settings.moduleswitches)) then
+ begin
+ if (ref.symbol.bind in [AB_EXTERNAL,AB_WEAK_EXTERNAL]) or
+ ((cs_create_pic in current_settings.moduleswitches) and
+ (ref.symbol.bind in [AB_COMMON,AB_GLOBAL,AB_PRIVATE_EXTERN])) then
+ begin
+ reference_reset_base(tmpref,
+ g_indirect_sym_load(list,ref.symbol.name,ref.symbol.bind=AB_WEAK_EXTERNAL),
+ offset,sizeof(pint));
+ a_loadaddr_ref_reg(list,tmpref,r);
+ end
+ else
+ begin
+ include(current_procinfo.flags,pi_needs_got);
+ reference_reset_base(tmpref,current_procinfo.got,offset,ref.alignment);
+ tmpref.symbol:=symbol;
+ tmpref.relsymbol:=current_procinfo.CurrGOTLabel;
+ list.concat(Taicpu.op_ref_reg(A_LEA,tcgsize2opsize[OS_ADDR],tmpref,r));
+ end;
+ end
+ else if (cs_create_pic in current_settings.moduleswitches)
+{$ifdef x86_64}
+ and not((ref.symbol.bind=AB_LOCAL) and
+ (ref.symbol.typ in [AT_DATA,AT_LABEL,AT_ADDR]))
+{$endif x86_64}
+ then
+ begin
+{$ifdef x86_64}
+ reference_reset_symbol(tmpref,ref.symbol,0,ref.alignment);
+ tmpref.refaddr:=addr_pic;
+ tmpref.base:=NR_RIP;
+ list.concat(taicpu.op_ref_reg(A_MOV,S_Q,tmpref,r));
+{$else x86_64}
+ reference_reset_symbol(tmpref,ref.symbol,0,ref.alignment);
+ tmpref.refaddr:=addr_pic;
+ tmpref.base:=current_procinfo.got;
+ include(current_procinfo.flags,pi_needs_got);
+ list.concat(taicpu.op_ref_reg(A_MOV,S_L,tmpref,r));
+{$endif x86_64}
+ if offset<>0 then
+ a_op_const_reg(list,OP_ADD,OS_ADDR,offset,r);
+ end
+{$ifdef x86_64}
+ else if (target_info.system in (systems_all_windows+[system_x86_64_darwin]))
+ or (cs_create_pic in current_settings.moduleswitches)
+ then
+ begin
+ { Win64 and Darwin/x86_64 always require RIP-relative addressing }
+ tmpref:=ref;
+ tmpref.base:=NR_RIP;
+ tmpref.refaddr:=addr_pic_no_got;
+ list.concat(Taicpu.op_ref_reg(A_LEA,S_Q,tmpref,r));
+ end
+{$endif x86_64}
+ else
+ begin
+ tmpref:=ref;
+ tmpref.refaddr:=ADDR_FULL;
+ list.concat(Taicpu.op_ref_reg(A_MOV,tcgsize2opsize[OS_ADDR],tmpref,r));
+ end
+ end
+ else
+ a_load_const_reg(list,OS_ADDR,offset,r)
+ end
+ else if (base=NR_NO) and (index<>NR_NO) and
+ (offset=0) and (scalefactor=0) and (symbol=nil) then
+ a_load_reg_reg(list,OS_ADDR,OS_ADDR,index,r)
+ else if (base<>NR_NO) and (index=NR_NO) and
+ (offset=0) and (symbol=nil) then
+ a_load_reg_reg(list,OS_ADDR,OS_ADDR,base,r)
+ else
+ begin
+ tmpref:=ref;
+ make_simple_ref(list,tmpref);
+ list.concat(Taicpu.op_ref_reg(A_LEA,tcgsize2opsize[OS_ADDR],tmpref,r));
+ end;
+ if segment<>NR_NO then
+ begin
+ if (tf_section_threadvars in target_info.flags) then
+ begin
+ { Convert thread local address to a process global addres
+ as we cannot handle far pointers.}
+ case target_info.system of
+ system_i386_linux:
+ if segment=NR_GS then
+ begin
+ reference_reset_symbol(tmpref,current_asmdata.RefAsmSymbol('___fpc_threadvar_offset'),0,ref.alignment);
+ tmpref.segment:=NR_GS;
+ list.concat(Taicpu.op_ref_reg(A_ADD,tcgsize2opsize[OS_ADDR],tmpref,r));
+ end
+ else
+ cgmessage(cg_e_cant_use_far_pointer_there);
+ system_i386_win32:
+ if segment=NR_FS then
+ begin
+ allocallcpuregisters(list);
+ a_call_name(list,'GetTls',false);
+ deallocallcpuregisters(list);
+ list.concat(Taicpu.op_reg_reg(A_ADD,tcgsize2opsize[OS_ADDR],NR_EAX,r));
+ end
+ else
+ cgmessage(cg_e_cant_use_far_pointer_there);
+
+ else
+ cgmessage(cg_e_cant_use_far_pointer_there);
+ end;
+ end
+ else
+ cgmessage(cg_e_cant_use_far_pointer_there);
+ end;
+ end;
+ end;
+
+
+ { all fpu load routines expect that R_ST[0-7] means an fpu regvar and }
+ { R_ST means "the current value at the top of the fpu stack" (JM) }
+ procedure tcgx86.a_loadfpu_reg_reg(list: TAsmList; fromsize, tosize: tcgsize; reg1, reg2: tregister);
+
+ var
+ href: treference;
+ op: tasmop;
+ s: topsize;
+ begin
+ if (reg1<>NR_ST) then
+ begin
+ floatloadops(tosize,op,s);
+ list.concat(taicpu.op_reg(op,s,rgfpu.correct_fpuregister(reg1,rgfpu.fpuvaroffset)));
+ inc_fpu_stack;
+ end;
+ if (reg2<>NR_ST) then
+ begin
+ floatstoreops(tosize,op,s);
+ list.concat(taicpu.op_reg(op,s,rgfpu.correct_fpuregister(reg2,rgfpu.fpuvaroffset)));
+ dec_fpu_stack;
+ end;
+ { OS_F80 < OS_C64, but OS_C64 fits perfectly in OS_F80 }
+ if (reg1=NR_ST) and
+ (reg2=NR_ST) and
+ (tosize<>OS_F80) and
+ (tosize<fromsize) then
+ begin
+ { can't round down to lower precision in x87 :/ }
+ tg.gettemp(list,tcgsize2size[tosize],tcgsize2size[tosize],tt_normal,href);
+ a_loadfpu_reg_ref(list,fromsize,tosize,NR_ST,href);
+ a_loadfpu_ref_reg(list,tosize,tosize,href,NR_ST);
+ tg.ungettemp(list,href);
+ end;
+ end;
+
+
+ procedure tcgx86.a_loadfpu_ref_reg(list: TAsmList; fromsize, tosize: tcgsize; const ref: treference; reg: tregister);
+ begin
+ floatload(list,fromsize,ref);
+ a_loadfpu_reg_reg(list,fromsize,tosize,NR_ST,reg);
+ end;
+
+
+ procedure tcgx86.a_loadfpu_reg_ref(list: TAsmList; fromsize,tosize: tcgsize; reg: tregister; const ref: treference);
+ begin
+ { in case a record returned in a floating point register
+ (LOC_FPUREGISTER with OS_F32/OS_F64) is stored in memory
+ (LOC_REFERENCE with OS_32/OS_64), we have to adjust the
+ tosize }
+ if (fromsize in [OS_F32,OS_F64]) and
+ (tcgsize2size[fromsize]=tcgsize2size[tosize]) then
+ case tosize of
+ OS_32:
+ tosize:=OS_F32;
+ OS_64:
+ tosize:=OS_F64;
+ end;
+ if reg<>NR_ST then
+ a_loadfpu_reg_reg(list,fromsize,tosize,reg,NR_ST);
+ floatstore(list,tosize,ref);
+ end;
+
+
+ function get_scalar_mm_op(fromsize,tosize : tcgsize) : tasmop;
+ const
+ convertop : array[OS_F32..OS_F128,OS_F32..OS_F128] of tasmop = (
+ (A_MOVSS,A_CVTSS2SD,A_NONE,A_NONE,A_NONE),
+ (A_CVTSD2SS,A_MOVSD,A_NONE,A_NONE,A_NONE),
+ (A_NONE,A_NONE,A_NONE,A_NONE,A_NONE),
+ (A_NONE,A_NONE,A_NONE,A_MOVQ,A_NONE),
+ (A_NONE,A_NONE,A_NONE,A_NONE,A_NONE));
+ begin
+ { we can have OS_F32/OS_F64 (record in function result/LOC_MMREGISTER) to
+ OS_32/OS_64 (record in memory/LOC_REFERENCE) }
+ if (fromsize in [OS_F32,OS_F64]) and
+ (tcgsize2size[fromsize]=tcgsize2size[tosize]) then
+ case tosize of
+ OS_32:
+ tosize:=OS_F32;
+ OS_64:
+ tosize:=OS_F64;
+ end;
+ if (fromsize in [low(convertop)..high(convertop)]) and
+ (tosize in [low(convertop)..high(convertop)]) then
+ result:=convertop[fromsize,tosize]
+ { we can have OS_M64 (record in function result/LOC_MMREGISTER) to
+ OS_64 (record in memory/LOC_REFERENCE) }
+ else if (tcgsize2size[fromsize]=tcgsize2size[tosize]) and
+ (fromsize=OS_M64) then
+ result:=A_MOVQ
+ else
+ internalerror(2010060104);
+ if result=A_NONE then
+ internalerror(200312205);
+ end;
+
+
+ procedure tcgx86.a_loadmm_reg_reg(list: TAsmList; fromsize, tosize : tcgsize;reg1, reg2: tregister;shuffle : pmmshuffle);
+ var
+ instr : taicpu;
+ begin
+ if shuffle=nil then
+ begin
+ if fromsize=tosize then
+ { needs correct size in case of spilling }
+ case fromsize of
+ OS_F32:
+ instr:=taicpu.op_reg_reg(A_MOVAPS,S_NO,reg1,reg2);
+ OS_F64:
+ instr:=taicpu.op_reg_reg(A_MOVAPD,S_NO,reg1,reg2);
+ OS_M64:
+ instr:=taicpu.op_reg_reg(A_MOVQ,S_NO,reg1,reg2);
+ else
+ internalerror(2006091201);
+ end
+ else
+ internalerror(200312202);
+ add_move_instruction(instr);
+ end
+ else if shufflescalar(shuffle) then
+ begin
+ instr:=taicpu.op_reg_reg(get_scalar_mm_op(fromsize,tosize),S_NO,reg1,reg2);
+ case get_scalar_mm_op(fromsize,tosize) of
+ A_MOVSS,
+ A_MOVSD,
+ A_MOVQ:
+ add_move_instruction(instr);
+ end;
+ end
+ else
+ internalerror(200312201);
+ list.concat(instr);
+ end;
+
+
+ procedure tcgx86.a_loadmm_ref_reg(list: TAsmList; fromsize, tosize : tcgsize;const ref: treference; reg: tregister;shuffle : pmmshuffle);
+ var
+ tmpref : treference;
+ begin
+ tmpref:=ref;
+ make_simple_ref(list,tmpref);
+ if shuffle=nil then
+ begin
+ if fromsize=OS_M64 then
+ list.concat(taicpu.op_ref_reg(A_MOVQ,S_NO,tmpref,reg))
+ else
+{$ifdef x86_64}
+ { x86-64 has always properly aligned data }
+ list.concat(taicpu.op_ref_reg(A_MOVDQA,S_NO,tmpref,reg));
+{$else x86_64}
+ list.concat(taicpu.op_ref_reg(A_MOVDQU,S_NO,tmpref,reg));
+{$endif x86_64}
+ end
+ else if shufflescalar(shuffle) then
+ list.concat(taicpu.op_ref_reg(get_scalar_mm_op(fromsize,tosize),S_NO,tmpref,reg))
+ else
+ internalerror(200312252);
+ end;
+
+
+ procedure tcgx86.a_loadmm_reg_ref(list: TAsmList; fromsize, tosize : tcgsize;reg: tregister; const ref: treference;shuffle : pmmshuffle);
+ var
+ hreg : tregister;
+ tmpref : treference;
+ begin
+ tmpref:=ref;
+ make_simple_ref(list,tmpref);
+ if shuffle=nil then
+ begin
+ if fromsize=OS_M64 then
+ list.concat(taicpu.op_reg_ref(A_MOVQ,S_NO,reg,tmpref))
+ else
+{$ifdef x86_64}
+ { x86-64 has always properly aligned data }
+ list.concat(taicpu.op_reg_ref(A_MOVDQA,S_NO,reg,tmpref))
+{$else x86_64}
+ list.concat(taicpu.op_reg_ref(A_MOVDQU,S_NO,reg,tmpref))
+{$endif x86_64}
+ end
+ else if shufflescalar(shuffle) then
+ begin
+ if tcgsize2size[tosize]<>tcgsize2size[fromsize] then
+ begin
+ hreg:=getmmregister(list,tosize);
+ list.concat(taicpu.op_reg_reg(get_scalar_mm_op(fromsize,tosize),S_NO,reg,hreg));
+ list.concat(taicpu.op_reg_ref(get_scalar_mm_op(tosize,tosize),S_NO,hreg,tmpref));
+ end
+ else
+ list.concat(taicpu.op_reg_ref(get_scalar_mm_op(fromsize,tosize),S_NO,reg,tmpref));
+ end
+ else
+ internalerror(200312252);
+ end;
+
+
+ procedure tcgx86.a_opmm_ref_reg(list: TAsmList; Op: TOpCG; size : tcgsize;const ref: treference; reg: tregister;shuffle : pmmshuffle);
+ var
+ l : tlocation;
+ begin
+ l.loc:=LOC_REFERENCE;
+ l.reference:=ref;
+ l.size:=size;
+ opmm_loc_reg(list,op,size,l,reg,shuffle);
+ end;
+
+
+ procedure tcgx86.a_opmm_reg_reg(list: TAsmList; Op: TOpCG; size : tcgsize;src,dst: tregister;shuffle : pmmshuffle);
+ var
+ l : tlocation;
+ begin
+ l.loc:=LOC_MMREGISTER;
+ l.register:=src;
+ l.size:=size;
+ opmm_loc_reg(list,op,size,l,dst,shuffle);
+ end;
+
+
+ procedure tcgx86.opmm_loc_reg(list: TAsmList; Op: TOpCG; size : tcgsize;loc : tlocation;dst: tregister; shuffle : pmmshuffle);
+ const
+ opmm2asmop : array[0..1,OS_F32..OS_F64,topcg] of tasmop = (
+ ( { scalar }
+ ( { OS_F32 }
+ A_NOP,A_NOP,A_ADDSS,A_NOP,A_DIVSS,A_NOP,A_NOP,A_MULSS,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_SUBSS,A_NOP,A_NOP,A_NOP
+ ),
+ ( { OS_F64 }
+ A_NOP,A_NOP,A_ADDSD,A_NOP,A_DIVSD,A_NOP,A_NOP,A_MULSD,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_SUBSD,A_NOP,A_NOP,A_NOP
+ )
+ ),
+ ( { vectorized/packed }
+ { because the logical packed single instructions have shorter op codes, we use always
+ these
+ }
+ ( { OS_F32 }
+ A_NOP,A_NOP,A_ADDPS,A_NOP,A_DIVPS,A_NOP,A_NOP,A_MULPS,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_SUBPS,A_XORPS,A_NOP,A_NOP
+ ),
+ ( { OS_F64 }
+ A_NOP,A_NOP,A_ADDPD,A_NOP,A_DIVPD,A_NOP,A_NOP,A_MULPD,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_SUBPD,A_XORPD,A_NOP,A_NOP
+ )
+ )
+ );
+
+ var
+ resultreg : tregister;
+ asmop : tasmop;
+ begin
+ { this is an internally used procedure so the parameters have
+ some constrains
+ }
+ if loc.size<>size then
+ internalerror(200312213);
+ resultreg:=dst;
+ { deshuffle }
+ //!!!
+ if (shuffle<>nil) and not(shufflescalar(shuffle)) then
+ begin
+ internalerror(2010060101);
+ end
+ else if (shuffle=nil) then
+ asmop:=opmm2asmop[1,size,op]
+ else if shufflescalar(shuffle) then
+ begin
+ asmop:=opmm2asmop[0,size,op];
+ { no scalar operation available? }
+ if asmop=A_NOP then
+ begin
+ { do vectorized and shuffle finally }
+ internalerror(2010060102);
+ end;
+ end
+ else
+ internalerror(200312211);
+ if asmop=A_NOP then
+ internalerror(200312216);
+ case loc.loc of
+ LOC_CREFERENCE,LOC_REFERENCE:
+ begin
+ make_simple_ref(current_asmdata.CurrAsmList,loc.reference);
+ list.concat(taicpu.op_ref_reg(asmop,S_NO,loc.reference,resultreg));
+ end;
+ LOC_CMMREGISTER,LOC_MMREGISTER:
+ list.concat(taicpu.op_reg_reg(asmop,S_NO,loc.register,resultreg));
+ else
+ internalerror(200312214);
+ end;
+ { shuffle }
+ if resultreg<>dst then
+ begin
+ internalerror(200312212);
+ end;
+ end;
+
+
+ procedure tcgx86.a_op_const_reg(list : TAsmList; Op: TOpCG; size: TCGSize; a: tcgint; reg: TRegister);
+
+ var
+ opcode : tasmop;
+ power : longint;
+{$ifdef x86_64}
+ tmpreg : tregister;
+{$endif x86_64}
+ begin
+ optimize_op_const(op, a);
+{$ifdef x86_64}
+ { x86_64 only supports signed 32 bits constants directly }
+ if not(op in [OP_NONE,OP_MOVE]) and
+ (size in [OS_S64,OS_64]) and
+ ((a<low(longint)) or (a>high(longint))) then
+ begin
+ tmpreg:=getintregister(list,size);
+ a_load_const_reg(list,size,a,tmpreg);
+ a_op_reg_reg(list,op,size,tmpreg,reg);
+ exit;
+ end;
+{$endif x86_64}
+ check_register_size(size,reg);
+ case op of
+ OP_NONE :
+ begin
+ { Opcode is optimized away }
+ end;
+ OP_MOVE :
+ begin
+ { Optimized, replaced with a simple load }
+ a_load_const_reg(list,size,a,reg);
+ end;
+ OP_DIV, OP_IDIV:
+ begin
+ if ispowerof2(int64(a),power) then
+ begin
+ case op of
+ OP_DIV:
+ opcode := A_SHR;
+ OP_IDIV:
+ opcode := A_SAR;
+ end;
+ list.concat(taicpu.op_const_reg(opcode,TCgSize2OpSize[size],power,reg));
+ exit;
+ end;
+ { the rest should be handled specifically in the code }
+ { generator because of the silly register usage restraints }
+ internalerror(200109224);
+ end;
+ OP_MUL,OP_IMUL:
+ begin
+ if not(cs_check_overflow in current_settings.localswitches) and
+ ispowerof2(int64(a),power) then
+ begin
+ list.concat(taicpu.op_const_reg(A_SHL,TCgSize2OpSize[size],power,reg));
+ exit;
+ end;
+ if op = OP_IMUL then
+ list.concat(taicpu.op_const_reg(A_IMUL,TCgSize2OpSize[size],a,reg))
+ else
+ { OP_MUL should be handled specifically in the code }
+ { generator because of the silly register usage restraints }
+ internalerror(200109225);
+ end;
+ OP_ADD, OP_AND, OP_OR, OP_SUB, OP_XOR:
+ if not(cs_check_overflow in current_settings.localswitches) and
+ (a = 1) and
+ (op in [OP_ADD,OP_SUB]) then
+ if op = OP_ADD then
+ list.concat(taicpu.op_reg(A_INC,TCgSize2OpSize[size],reg))
+ else
+ list.concat(taicpu.op_reg(A_DEC,TCgSize2OpSize[size],reg))
+ else if (a = 0) then
+ if (op <> OP_AND) then
+ exit
+ else
+ list.concat(taicpu.op_const_reg(A_MOV,TCgSize2OpSize[size],0,reg))
+ else if (aword(a) = high(aword)) and
+ (op in [OP_AND,OP_OR,OP_XOR]) then
+ begin
+ case op of
+ OP_AND:
+ exit;
+ OP_OR:
+ list.concat(taicpu.op_const_reg(A_MOV,TCgSize2OpSize[size],aint(high(aword)),reg));
+ OP_XOR:
+ list.concat(taicpu.op_reg(A_NOT,TCgSize2OpSize[size],reg));
+ end
+ end
+ else
+ list.concat(taicpu.op_const_reg(TOpCG2AsmOp[op],TCgSize2OpSize[size],aint(a),reg));
+ OP_SHL,OP_SHR,OP_SAR,OP_ROL,OP_ROR:
+ begin
+{$ifdef x86_64}
+ if (a and 63) <> 0 Then
+ list.concat(taicpu.op_const_reg(TOpCG2AsmOp[op],TCgSize2OpSize[size],a and 63,reg));
+ if (a shr 6) <> 0 Then
+ internalerror(200609073);
+{$else x86_64}
+ if (a and 31) <> 0 Then
+ list.concat(taicpu.op_const_reg(TOpCG2AsmOp[op],TCgSize2OpSize[size],a and 31,reg));
+ if (a shr 5) <> 0 Then
+ internalerror(200609071);
+{$endif x86_64}
+ end
+ else internalerror(200609072);
+ end;
+ end;
+
+
+ procedure tcgx86.a_op_const_ref(list : TAsmList; Op: TOpCG; size: TCGSize; a: tcgint; const ref: TReference);
+ var
+ opcode: tasmop;
+ power: longint;
+{$ifdef x86_64}
+ tmpreg : tregister;
+{$endif x86_64}
+ tmpref : treference;
+ begin
+ optimize_op_const(op, a);
+ tmpref:=ref;
+ make_simple_ref(list,tmpref);
+{$ifdef x86_64}
+ { x86_64 only supports signed 32 bits constants directly }
+ if not(op in [OP_NONE,OP_MOVE]) and
+ (size in [OS_S64,OS_64]) and
+ ((a<low(longint)) or (a>high(longint))) then
+ begin
+ tmpreg:=getintregister(list,size);
+ a_load_const_reg(list,size,a,tmpreg);
+ a_op_reg_ref(list,op,size,tmpreg,tmpref);
+ exit;
+ end;
+{$endif x86_64}
+ Case Op of
+ OP_NONE :
+ begin
+ { Opcode is optimized away }
+ end;
+ OP_MOVE :
+ begin
+ { Optimized, replaced with a simple load }
+ a_load_const_ref(list,size,a,ref);
+ end;
+ OP_DIV, OP_IDIV:
+ Begin
+ if ispowerof2(int64(a),power) then
+ begin
+ case op of
+ OP_DIV:
+ opcode := A_SHR;
+ OP_IDIV:
+ opcode := A_SAR;
+ end;
+ list.concat(taicpu.op_const_ref(opcode,
+ TCgSize2OpSize[size],power,tmpref));
+ exit;
+ end;
+ { the rest should be handled specifically in the code }
+ { generator because of the silly register usage restraints }
+ internalerror(200109231);
+ End;
+ OP_MUL,OP_IMUL:
+ begin
+ if not(cs_check_overflow in current_settings.localswitches) and
+ ispowerof2(int64(a),power) then
+ begin
+ list.concat(taicpu.op_const_ref(A_SHL,TCgSize2OpSize[size],
+ power,tmpref));
+ exit;
+ end;
+ { can't multiply a memory location directly with a constant }
+ if op = OP_IMUL then
+ inherited a_op_const_ref(list,op,size,a,tmpref)
+ else
+ { OP_MUL should be handled specifically in the code }
+ { generator because of the silly register usage restraints }
+ internalerror(200109232);
+ end;
+ OP_ADD, OP_AND, OP_OR, OP_SUB, OP_XOR:
+ if not(cs_check_overflow in current_settings.localswitches) and
+ (a = 1) and
+ (op in [OP_ADD,OP_SUB]) then
+ if op = OP_ADD then
+ list.concat(taicpu.op_ref(A_INC,TCgSize2OpSize[size],tmpref))
+ else
+ list.concat(taicpu.op_ref(A_DEC,TCgSize2OpSize[size],tmpref))
+ else if (a = 0) then
+ if (op <> OP_AND) then
+ exit
+ else
+ a_load_const_ref(list,size,0,tmpref)
+ else if (aword(a) = high(aword)) and
+ (op in [OP_AND,OP_OR,OP_XOR]) then
+ begin
+ case op of
+ OP_AND:
+ exit;
+ OP_OR:
+ list.concat(taicpu.op_const_ref(A_MOV,TCgSize2OpSize[size],aint(high(aword)),tmpref));
+ OP_XOR:
+ list.concat(taicpu.op_ref(A_NOT,TCgSize2OpSize[size],tmpref));
+ end
+ end
+ else
+ list.concat(taicpu.op_const_ref(TOpCG2AsmOp[op],
+ TCgSize2OpSize[size],a,tmpref));
+ OP_SHL,OP_SHR,OP_SAR,OP_ROL,OP_ROR:
+ begin
+ if (a and 31) <> 0 then
+ list.concat(taicpu.op_const_ref(
+ TOpCG2AsmOp[op],TCgSize2OpSize[size],a and 31,tmpref));
+ if (a shr 5) <> 0 Then
+ internalerror(68991);
+ end
+ else internalerror(68992);
+ end;
+ end;
+
+
+ procedure tcgx86.a_op_reg_reg(list : TAsmList; Op: TOpCG; size: TCGSize; src, dst: TRegister);
+ var
+ dstsize: topsize;
+ instr:Taicpu;
+ begin
+ check_register_size(size,src);
+ check_register_size(size,dst);
+ dstsize := tcgsize2opsize[size];
+ case op of
+ OP_NEG,OP_NOT:
+ begin
+ if src<>dst then
+ a_load_reg_reg(list,size,size,src,dst);
+ list.concat(taicpu.op_reg(TOpCG2AsmOp[op],dstsize,dst));
+ end;
+ OP_MUL,OP_DIV,OP_IDIV:
+ { special stuff, needs separate handling inside code }
+ { generator }
+ internalerror(200109233);
+ OP_SHR,OP_SHL,OP_SAR,OP_ROL,OP_ROR:
+ begin
+ { Use ecx to load the value, that allows better coalescing }
+ getcpuregister(list,NR_ECX);
+ a_load_reg_reg(list,size,OS_32,src,NR_ECX);
+ list.concat(taicpu.op_reg_reg(Topcg2asmop[op],tcgsize2opsize[size],NR_CL,dst));
+ ungetcpuregister(list,NR_ECX);
+ end;
+ else
+ begin
+ if reg2opsize(src) <> dstsize then
+ internalerror(200109226);
+ instr:=taicpu.op_reg_reg(TOpCG2AsmOp[op],dstsize,src,dst);
+ list.concat(instr);
+ end;
+ end;
+ end;
+
+
+ procedure tcgx86.a_op_ref_reg(list : TAsmList; Op: TOpCG; size: TCGSize; const ref: TReference; reg: TRegister);
+ var
+ tmpref : treference;
+ begin
+ tmpref:=ref;
+ make_simple_ref(list,tmpref);
+ check_register_size(size,reg);
+ case op of
+ OP_NEG,OP_NOT,OP_IMUL:
+ begin
+ inherited a_op_ref_reg(list,op,size,tmpref,reg);
+ end;
+ OP_MUL,OP_DIV,OP_IDIV:
+ { special stuff, needs separate handling inside code }
+ { generator }
+ internalerror(200109239);
+ else
+ begin
+ reg := makeregsize(list,reg,size);
+ list.concat(taicpu.op_ref_reg(TOpCG2AsmOp[op],tcgsize2opsize[size],tmpref,reg));
+ end;
+ end;
+ end;
+
+
+ procedure tcgx86.a_op_reg_ref(list : TAsmList; Op: TOpCG; size: TCGSize;reg: TRegister; const ref: TReference);
+ var
+ tmpref : treference;
+ begin
+ tmpref:=ref;
+ make_simple_ref(list,tmpref);
+ check_register_size(size,reg);
+ case op of
+ OP_NEG,OP_NOT:
+ begin
+ if reg<>NR_NO then
+ internalerror(200109237);
+ list.concat(taicpu.op_ref(TOpCG2AsmOp[op],tcgsize2opsize[size],tmpref));
+ end;
+ OP_IMUL:
+ begin
+ { this one needs a load/imul/store, which is the default }
+ inherited a_op_ref_reg(list,op,size,tmpref,reg);
+ end;
+ OP_MUL,OP_DIV,OP_IDIV:
+ { special stuff, needs separate handling inside code }
+ { generator }
+ internalerror(200109238);
+ else
+ begin
+ list.concat(taicpu.op_reg_ref(TOpCG2AsmOp[op],tcgsize2opsize[size],reg,tmpref));
+ end;
+ end;
+ end;
+
+ procedure tcgx86.a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; size: TCGSize; src, dst: TRegister);
+ var
+ opsize: topsize;
+ begin
+ opsize:=tcgsize2opsize[size];
+ if not reverse then
+ list.concat(taicpu.op_reg_reg(A_BSF,opsize,src,dst))
+ else
+ list.concat(taicpu.op_reg_reg(A_BSR,opsize,src,dst));
+ end;
+
+{*************** compare instructructions ****************}
+
+ procedure tcgx86.a_cmp_const_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;a : tcgint;reg : tregister;
+ l : tasmlabel);
+
+{$ifdef x86_64}
+ var
+ tmpreg : tregister;
+{$endif x86_64}
+ begin
+{$ifdef x86_64}
+ { x86_64 only supports signed 32 bits constants directly }
+ if (size in [OS_S64,OS_64]) and
+ ((a<low(longint)) or (a>high(longint))) then
+ begin
+ tmpreg:=getintregister(list,size);
+ a_load_const_reg(list,size,a,tmpreg);
+ a_cmp_reg_reg_label(list,size,cmp_op,tmpreg,reg,l);
+ exit;
+ end;
+{$endif x86_64}
+ if (a = 0) then
+ list.concat(taicpu.op_reg_reg(A_TEST,tcgsize2opsize[size],reg,reg))
+ else
+ list.concat(taicpu.op_const_reg(A_CMP,tcgsize2opsize[size],a,reg));
+ a_jmp_cond(list,cmp_op,l);
+ end;
+
+
+ procedure tcgx86.a_cmp_const_ref_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;a : tcgint;const ref : treference;
+ l : tasmlabel);
+
+ var
+{$ifdef x86_64}
+ tmpreg : tregister;
+{$endif x86_64}
+ tmpref : treference;
+ begin
+ tmpref:=ref;
+ make_simple_ref(list,tmpref);
+{$ifdef x86_64}
+ { x86_64 only supports signed 32 bits constants directly }
+ if (size in [OS_S64,OS_64]) and
+ ((a<low(longint)) or (a>high(longint))) then
+ begin
+ tmpreg:=getintregister(list,size);
+ a_load_const_reg(list,size,a,tmpreg);
+ a_cmp_reg_ref_label(list,size,cmp_op,tmpreg,tmpref,l);
+ exit;
+ end;
+{$endif x86_64}
+ list.concat(taicpu.op_const_ref(A_CMP,TCgSize2OpSize[size],a,tmpref));
+ a_jmp_cond(list,cmp_op,l);
+ end;
+
+
+ procedure tcgx86.a_cmp_reg_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;
+ reg1,reg2 : tregister;l : tasmlabel);
+
+ begin
+ check_register_size(size,reg1);
+ check_register_size(size,reg2);
+ list.concat(taicpu.op_reg_reg(A_CMP,TCgSize2OpSize[size],reg1,reg2));
+ a_jmp_cond(list,cmp_op,l);
+ end;
+
+
+ procedure tcgx86.a_cmp_ref_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;const ref: treference; reg : tregister;l : tasmlabel);
+ var
+ tmpref : treference;
+ begin
+ tmpref:=ref;
+ make_simple_ref(list,tmpref);
+ check_register_size(size,reg);
+ list.concat(taicpu.op_ref_reg(A_CMP,TCgSize2OpSize[size],tmpref,reg));
+ a_jmp_cond(list,cmp_op,l);
+ end;
+
+
+ procedure tcgx86.a_cmp_reg_ref_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;reg : tregister;const ref: treference; l : tasmlabel);
+ var
+ tmpref : treference;
+ begin
+ tmpref:=ref;
+ make_simple_ref(list,tmpref);
+ check_register_size(size,reg);
+ list.concat(taicpu.op_reg_ref(A_CMP,TCgSize2OpSize[size],reg,tmpref));
+ a_jmp_cond(list,cmp_op,l);
+ end;
+
+
+ procedure tcgx86.a_jmp_cond(list : TAsmList;cond : TOpCmp;l: tasmlabel);
+ var
+ ai : taicpu;
+ begin
+ if cond=OC_None then
+ ai := Taicpu.Op_sym(A_JMP,S_NO,l)
+ else
+ begin
+ ai:=Taicpu.Op_sym(A_Jcc,S_NO,l);
+ ai.SetCondition(TOpCmp2AsmCond[cond]);
+ end;
+ ai.is_jmp:=true;
+ list.concat(ai);
+ end;
+
+
+ procedure tcgx86.a_jmp_flags(list : TAsmList;const f : TResFlags;l: tasmlabel);
+ var
+ ai : taicpu;
+ begin
+ ai := Taicpu.op_sym(A_Jcc,S_NO,l);
+ ai.SetCondition(flags_to_cond(f));
+ ai.is_jmp := true;
+ list.concat(ai);
+ end;
+
+
+ procedure tcgx86.g_flags2reg(list: TAsmList; size: TCgSize; const f: tresflags; reg: TRegister);
+ var
+ ai : taicpu;
+ hreg : tregister;
+ begin
+ hreg:=makeregsize(list,reg,OS_8);
+ ai:=Taicpu.op_reg(A_SETcc,S_B,hreg);
+ ai.setcondition(flags_to_cond(f));
+ list.concat(ai);
+ if reg<>hreg then
+ a_load_reg_reg(list,OS_8,size,hreg,reg);
+ end;
+
+
+ procedure tcgx86.g_flags2ref(list: TAsmList; size: TCgSize; const f: tresflags; const ref: TReference);
+ var
+ ai : taicpu;
+ tmpref : treference;
+ begin
+ tmpref:=ref;
+ make_simple_ref(list,tmpref);
+ if not(size in [OS_8,OS_S8]) then
+ a_load_const_ref(list,size,0,tmpref);
+ ai:=Taicpu.op_ref(A_SETcc,S_B,tmpref);
+ ai.setcondition(flags_to_cond(f));
+ list.concat(ai);
+{$ifndef cpu64bitalu}
+ if size in [OS_S64,OS_64] then
+ begin
+ inc(tmpref.offset,4);
+ a_load_const_ref(list,OS_32,0,tmpref);
+ end;
+{$endif cpu64bitalu}
+ end;
+
+
+{ ************* concatcopy ************ }
+
+ procedure Tcgx86.g_concatcopy(list:TAsmList;const source,dest:Treference;len:tcgint);
+
+ const
+{$ifdef cpu64bitalu}
+ REGCX=NR_RCX;
+ REGSI=NR_RSI;
+ REGDI=NR_RDI;
+{$else cpu64bitalu}
+ REGCX=NR_ECX;
+ REGSI=NR_ESI;
+ REGDI=NR_EDI;
+{$endif cpu64bitalu}
+
+ type copymode=(copy_move,copy_mmx,copy_string);
+
+ var srcref,dstref:Treference;
+ r,r0,r1,r2,r3:Tregister;
+ helpsize:tcgint;
+ copysize:byte;
+ cgsize:Tcgsize;
+ cm:copymode;
+
+ begin
+ cm:=copy_move;
+ helpsize:=3*sizeof(aword);
+ if cs_opt_size in current_settings.optimizerswitches then
+ helpsize:=2*sizeof(aword);
+ if (cs_mmx in current_settings.localswitches) and
+ not(pi_uses_fpu in current_procinfo.flags) and
+ ((len=8) or (len=16) or (len=24) or (len=32)) then
+ cm:=copy_mmx;
+ if (len>helpsize) then
+ cm:=copy_string;
+ if (cs_opt_size in current_settings.optimizerswitches) and
+ not((len<=16) and (cm=copy_mmx)) and
+ not(len in [1,2,4{$ifdef x86_64},8{$endif x86_64}]) then
+ cm:=copy_string;
+ if (source.segment<>NR_NO) or
+ (dest.segment<>NR_NO) then
+ cm:=copy_string;
+ case cm of
+ copy_move:
+ begin
+ dstref:=dest;
+ srcref:=source;
+ copysize:=sizeof(aint);
+ cgsize:=int_cgsize(copysize);
+ while len<>0 do
+ begin
+ if len<2 then
+ begin
+ copysize:=1;
+ cgsize:=OS_8;
+ end
+ else if len<4 then
+ begin
+ copysize:=2;
+ cgsize:=OS_16;
+ end
+ else if len<8 then
+ begin
+ copysize:=4;
+ cgsize:=OS_32;
+ end
+{$ifdef cpu64bitalu}
+ else if len<16 then
+ begin
+ copysize:=8;
+ cgsize:=OS_64;
+ end
+{$endif}
+ ;
+ dec(len,copysize);
+ r:=getintregister(list,cgsize);
+ a_load_ref_reg(list,cgsize,cgsize,srcref,r);
+ a_load_reg_ref(list,cgsize,cgsize,r,dstref);
+ inc(srcref.offset,copysize);
+ inc(dstref.offset,copysize);
+ end;
+ end;
+ copy_mmx:
+ begin
+ dstref:=dest;
+ srcref:=source;
+ r0:=getmmxregister(list);
+ a_loadmm_ref_reg(list,OS_M64,OS_M64,srcref,r0,nil);
+ if len>=16 then
+ begin
+ inc(srcref.offset,8);
+ r1:=getmmxregister(list);
+ a_loadmm_ref_reg(list,OS_M64,OS_M64,srcref,r1,nil);
+ end;
+ if len>=24 then
+ begin
+ inc(srcref.offset,8);
+ r2:=getmmxregister(list);
+ a_loadmm_ref_reg(list,OS_M64,OS_M64,srcref,r2,nil);
+ end;
+ if len>=32 then
+ begin
+ inc(srcref.offset,8);
+ r3:=getmmxregister(list);
+ a_loadmm_ref_reg(list,OS_M64,OS_M64,srcref,r3,nil);
+ end;
+ a_loadmm_reg_ref(list,OS_M64,OS_M64,r0,dstref,nil);
+ if len>=16 then
+ begin
+ inc(dstref.offset,8);
+ a_loadmm_reg_ref(list,OS_M64,OS_M64,r1,dstref,nil);
+ end;
+ if len>=24 then
+ begin
+ inc(dstref.offset,8);
+ a_loadmm_reg_ref(list,OS_M64,OS_M64,r2,dstref,nil);
+ end;
+ if len>=32 then
+ begin
+ inc(dstref.offset,8);
+ a_loadmm_reg_ref(list,OS_M64,OS_M64,r3,dstref,nil);
+ end;
+ end
+ else {copy_string, should be a good fallback in case of unhandled}
+ begin
+ getcpuregister(list,REGDI);
+ if (dest.segment=NR_NO) then
+ a_loadaddr_ref_reg(list,dest,REGDI)
+ else
+ begin
+ dstref:=dest;
+ dstref.segment:=NR_NO;
+ a_loadaddr_ref_reg(list,dstref,REGDI);
+ list.concat(taicpu.op_reg(A_PUSH,S_L,NR_ES));
+ list.concat(taicpu.op_reg(A_PUSH,S_L,dest.segment));
+ list.concat(taicpu.op_reg(A_POP,S_L,NR_ES));
+ end;
+ getcpuregister(list,REGSI);
+ if (source.segment=NR_NO) then
+ a_loadaddr_ref_reg(list,source,REGSI)
+ else
+ begin
+ srcref:=source;
+ srcref.segment:=NR_NO;
+ a_loadaddr_ref_reg(list,srcref,REGSI);
+ list.concat(taicpu.op_reg(A_PUSH,S_L,NR_DS));
+ list.concat(taicpu.op_reg(A_PUSH,S_L,source.segment));
+ list.concat(taicpu.op_reg(A_POP,S_L,NR_DS));
+ end;
+
+ getcpuregister(list,REGCX);
+{$ifdef i386}
+ list.concat(Taicpu.op_none(A_CLD,S_NO));
+{$endif i386}
+ if (cs_opt_size in current_settings.optimizerswitches) and
+ (len>sizeof(aint)+(sizeof(aint) div 2)) then
+ begin
+ a_load_const_reg(list,OS_INT,len,REGCX);
+ list.concat(Taicpu.op_none(A_REP,S_NO));
+ list.concat(Taicpu.op_none(A_MOVSB,S_NO));
+ end
+ else
+ begin
+ helpsize:=len div sizeof(aint);
+ len:=len mod sizeof(aint);
+ if helpsize>1 then
+ begin
+ a_load_const_reg(list,OS_INT,helpsize,REGCX);
+ list.concat(Taicpu.op_none(A_REP,S_NO));
+ end;
+ if helpsize>0 then
+ begin
+{$ifdef cpu64bitalu}
+ list.concat(Taicpu.op_none(A_MOVSQ,S_NO))
+{$else}
+ list.concat(Taicpu.op_none(A_MOVSD,S_NO));
+{$endif cpu64bitalu}
+ end;
+ if len>=4 then
+ begin
+ dec(len,4);
+ list.concat(Taicpu.op_none(A_MOVSD,S_NO));
+ end;
+ if len>=2 then
+ begin
+ dec(len,2);
+ list.concat(Taicpu.op_none(A_MOVSW,S_NO));
+ end;
+ if len=1 then
+ list.concat(Taicpu.op_none(A_MOVSB,S_NO));
+ end;
+ ungetcpuregister(list,REGCX);
+ ungetcpuregister(list,REGSI);
+ ungetcpuregister(list,REGDI);
+ if (source.segment<>NR_NO) then
+ list.concat(taicpu.op_reg(A_POP,S_L,NR_DS));
+ if (dest.segment<>NR_NO) then
+ list.concat(taicpu.op_reg(A_POP,S_L,NR_ES));
+ end;
+ end;
+ end;
+
+
+{****************************************************************************
+ Entry/Exit Code Helpers
+****************************************************************************}
+
+ procedure tcgx86.g_profilecode(list : TAsmList);
+
+ var
+ pl : tasmlabel;
+ mcountprefix : String[4];
+
+ begin
+ case target_info.system of
+ {$ifndef NOTARGETWIN}
+ system_i386_win32,
+ {$endif}
+ system_i386_freebsd,
+ system_i386_netbsd,
+// system_i386_openbsd,
+ system_i386_wdosx :
+ begin
+ Case target_info.system Of
+ system_i386_freebsd : mcountprefix:='.';
+ system_i386_netbsd : mcountprefix:='__';
+// system_i386_openbsd : mcountprefix:='.';
+ else
+ mcountPrefix:='';
+ end;
+ current_asmdata.getaddrlabel(pl);
+ new_section(list,sec_data,lower(current_procinfo.procdef.mangledname),sizeof(pint));
+ list.concat(Tai_label.Create(pl));
+ list.concat(Tai_const.Create_32bit(0));
+ new_section(list,sec_code,lower(current_procinfo.procdef.mangledname),0);
+ list.concat(Taicpu.Op_reg(A_PUSH,S_L,NR_EDX));
+ list.concat(Taicpu.Op_sym_ofs_reg(A_MOV,S_L,pl,0,NR_EDX));
+ a_call_name(list,target_info.Cprefix+mcountprefix+'mcount',false);
+ list.concat(Taicpu.Op_reg(A_POP,S_L,NR_EDX));
+ end;
+
+ system_i386_linux:
+ a_call_name(list,target_info.Cprefix+'mcount',false);
+
+ system_i386_go32v2,system_i386_watcom:
+ begin
+ a_call_name(list,'MCOUNT',false);
+ end;
+ system_x86_64_linux,
+ system_x86_64_darwin:
+ begin
+ a_call_name(list,'mcount',false);
+ end;
+ end;
+ end;
+
+
+ procedure tcgx86.g_stackpointer_alloc(list : TAsmList;localsize : longint);
+{$ifdef x86}
+{$ifndef NOTARGETWIN}
+ var
+ href : treference;
+ i : integer;
+ again : tasmlabel;
+{$endif NOTARGETWIN}
+{$endif x86}
+ begin
+ if localsize>0 then
+ begin
+{$ifdef i386}
+{$ifndef NOTARGETWIN}
+ { windows guards only a few pages for stack growing,
+ so we have to access every page first }
+ if (target_info.system in [system_i386_win32,system_i386_wince]) and
+ (localsize>=winstackpagesize) then
+ begin
+ if localsize div winstackpagesize<=5 then
+ begin
+ list.concat(Taicpu.Op_const_reg(A_SUB,S_L,localsize-4,NR_ESP));
+ for i:=1 to localsize div winstackpagesize do
+ begin
+ reference_reset_base(href,NR_ESP,localsize-i*winstackpagesize,4);
+ list.concat(Taicpu.op_reg_ref(A_MOV,S_L,NR_EAX,href));
+ end;
+ list.concat(Taicpu.op_reg(A_PUSH,S_L,NR_EAX));
+ end
+ else
+ begin
+ current_asmdata.getjumplabel(again);
+ getcpuregister(list,NR_EDI);
+ list.concat(Taicpu.op_reg(A_PUSH,S_L,NR_EDI));
+ list.concat(Taicpu.op_const_reg(A_MOV,S_L,localsize div winstackpagesize,NR_EDI));
+ a_label(list,again);
+ list.concat(Taicpu.op_const_reg(A_SUB,S_L,winstackpagesize-4,NR_ESP));
+ list.concat(Taicpu.op_reg(A_PUSH,S_L,NR_EAX));
+ list.concat(Taicpu.op_reg(A_DEC,S_L,NR_EDI));
+ a_jmp_cond(list,OC_NE,again);
+ list.concat(Taicpu.op_const_reg(A_SUB,S_L,localsize mod winstackpagesize - 4,NR_ESP));
+ reference_reset_base(href,NR_ESP,localsize-4,4);
+ list.concat(Taicpu.op_ref_reg(A_MOV,S_L,href,NR_EDI));
+ ungetcpuregister(list,NR_EDI);
+ end
+ end
+ else
+{$endif NOTARGETWIN}
+{$endif i386}
+{$ifdef x86_64}
+{$ifndef NOTARGETWIN}
+ { windows guards only a few pages for stack growing,
+ so we have to access every page first }
+ if (target_info.system=system_x86_64_win64) and
+ (localsize>=winstackpagesize) then
+ begin
+ if localsize div winstackpagesize<=5 then
+ begin
+ list.concat(Taicpu.Op_const_reg(A_SUB,S_Q,localsize,NR_RSP));
+ for i:=1 to localsize div winstackpagesize do
+ begin
+ reference_reset_base(href,NR_RSP,localsize-i*winstackpagesize+4,4);
+ list.concat(Taicpu.op_reg_ref(A_MOV,S_L,NR_EAX,href));
+ end;
+ reference_reset_base(href,NR_RSP,0,4);
+ list.concat(Taicpu.op_reg_ref(A_MOV,S_L,NR_EAX,href));
+ end
+ else
+ begin
+ current_asmdata.getjumplabel(again);
+ getcpuregister(list,NR_R10);
+ list.concat(Taicpu.op_const_reg(A_MOV,S_Q,localsize div winstackpagesize,NR_R10));
+ a_label(list,again);
+ list.concat(Taicpu.op_const_reg(A_SUB,S_Q,winstackpagesize,NR_RSP));
+ reference_reset_base(href,NR_RSP,0,4);
+ list.concat(Taicpu.op_reg_ref(A_MOV,S_L,NR_EAX,href));
+ list.concat(Taicpu.op_reg(A_DEC,S_Q,NR_R10));
+ a_jmp_cond(list,OC_NE,again);
+ list.concat(Taicpu.op_const_reg(A_SUB,S_Q,localsize mod winstackpagesize,NR_RSP));
+ ungetcpuregister(list,NR_R10);
+ end
+ end
+ else
+{$endif NOTARGETWIN}
+{$endif x86_64}
+ list.concat(Taicpu.Op_const_reg(A_SUB,tcgsize2opsize[OS_ADDR],localsize,NR_STACK_POINTER_REG));
+ end;
+ end;
+
+
+ procedure tcgx86.g_proc_entry(list : TAsmList;localsize : longint;nostackframe:boolean);
+ var
+ stackmisalignment: longint;
+ para: tparavarsym;
+ begin
+{$ifdef i386}
+ { interrupt support for i386 }
+ if (po_interrupt in current_procinfo.procdef.procoptions) and
+ { this messes up stack alignment }
+ not(target_info.system in [system_i386_darwin,system_i386_iphonesim]) then
+ begin
+ { .... also the segment registers }
+ list.concat(Taicpu.Op_reg(A_PUSH,S_W,NR_GS));
+ list.concat(Taicpu.Op_reg(A_PUSH,S_W,NR_FS));
+ list.concat(Taicpu.Op_reg(A_PUSH,S_W,NR_ES));
+ list.concat(Taicpu.Op_reg(A_PUSH,S_W,NR_DS));
+ { save the registers of an interrupt procedure }
+ list.concat(Taicpu.Op_reg(A_PUSH,S_L,NR_EDI));
+ list.concat(Taicpu.Op_reg(A_PUSH,S_L,NR_ESI));
+ list.concat(Taicpu.Op_reg(A_PUSH,S_L,NR_EDX));
+ list.concat(Taicpu.Op_reg(A_PUSH,S_L,NR_ECX));
+ list.concat(Taicpu.Op_reg(A_PUSH,S_L,NR_EBX));
+ list.concat(Taicpu.Op_reg(A_PUSH,S_L,NR_EAX));
+ end;
+{$endif i386}
+
+ { save old framepointer }
+ if not nostackframe then
+ begin
+ { return address }
+ stackmisalignment := sizeof(pint);
+ list.concat(tai_regalloc.alloc(current_procinfo.framepointer,nil));
+ if current_procinfo.framepointer=NR_STACK_POINTER_REG then
+ CGmessage(cg_d_stackframe_omited)
+ else
+ begin
+ { push <frame_pointer> }
+ inc(stackmisalignment,sizeof(pint));
+ include(rg[R_INTREGISTER].preserved_by_proc,RS_FRAME_POINTER_REG);
+ list.concat(Taicpu.op_reg(A_PUSH,tcgsize2opsize[OS_ADDR],NR_FRAME_POINTER_REG));
+ if (target_info.system=system_x86_64_win64) then
+ begin
+ list.concat(cai_seh_directive.create_reg(ash_pushreg,NR_FRAME_POINTER_REG));
+ include(current_procinfo.flags,pi_has_unwind_info);
+ end;
+ { Return address and FP are both on stack }
+ current_asmdata.asmcfi.cfa_def_cfa_offset(list,2*sizeof(pint));
+ current_asmdata.asmcfi.cfa_offset(list,NR_FRAME_POINTER_REG,-(2*sizeof(pint)));
+ if current_procinfo.procdef.proctypeoption<>potype_exceptfilter then
+ list.concat(Taicpu.op_reg_reg(A_MOV,tcgsize2opsize[OS_ADDR],NR_STACK_POINTER_REG,NR_FRAME_POINTER_REG))
+ else
+ begin
+ { load framepointer from hidden $parentfp parameter }
+ para:=tparavarsym(current_procinfo.procdef.paras[0]);
+ if not (vo_is_parentfp in para.varoptions) then
+ InternalError(201201142);
+ if (para.paraloc[calleeside].location^.loc<>LOC_REGISTER) or
+ (para.paraloc[calleeside].location^.next<>nil) then
+ InternalError(201201143);
+ list.concat(Taicpu.op_reg_reg(A_MOV,tcgsize2opsize[OS_ADDR],
+ para.paraloc[calleeside].location^.register,NR_FRAME_POINTER_REG));
+ { Need only as much stack space as necessary to do the calls.
+ Exception filters don't have own local vars, and temps are 'mapped'
+ to the parent procedure.
+ maxpushedparasize is already aligned at least on x86_64. }
+ localsize:=current_procinfo.maxpushedparasize;
+ end;
+ current_asmdata.asmcfi.cfa_def_cfa_register(list,NR_FRAME_POINTER_REG);
+ {
+ TODO: current framepointer handling is not compatible with Win64 at all:
+ Win64 expects FP to point to the top or into the middle of local area.
+ In FPC it points to the bottom, making it impossible to generate
+ UWOP_SET_FPREG unwind code if local area is > 240 bytes.
+ So for now pretend we never have a framepointer.
+ }
+ end;
+
+ { allocate stackframe space }
+ if (localsize<>0) or
+ ((target_info.system in systems_need_16_byte_stack_alignment) and
+ (stackmisalignment <> 0) and
+ ((pi_do_call in current_procinfo.flags) or
+ (po_assembler in current_procinfo.procdef.procoptions))) then
+ begin
+ if (target_info.system in systems_need_16_byte_stack_alignment) then
+ localsize := align(localsize+stackmisalignment,16)-stackmisalignment;
+ cg.g_stackpointer_alloc(list,localsize);
+ if current_procinfo.framepointer=NR_STACK_POINTER_REG then
+ current_asmdata.asmcfi.cfa_def_cfa_offset(list,localsize+sizeof(pint));
+ current_procinfo.final_localsize:=localsize;
+ if (target_info.system=system_x86_64_win64) then
+ begin
+ if localsize<>0 then
+ list.concat(cai_seh_directive.create_offset(ash_stackalloc,localsize));
+ include(current_procinfo.flags,pi_has_unwind_info);
+ end;
+ end;
+ end;
+ end;
+
+
+ { produces if necessary overflowcode }
+ procedure tcgx86.g_overflowcheck(list: TAsmList; const l:tlocation;def:tdef);
+ var
+ hl : tasmlabel;
+ ai : taicpu;
+ cond : TAsmCond;
+ begin
+ if not(cs_check_overflow in current_settings.localswitches) then
+ exit;
+ current_asmdata.getjumplabel(hl);
+ if not ((def.typ=pointerdef) or
+ ((def.typ=orddef) and
+ (torddef(def).ordtype in [u64bit,u16bit,u32bit,u8bit,uchar,
+ pasbool8,pasbool16,pasbool32,pasbool64]))) then
+ cond:=C_NO
+ else
+ cond:=C_NB;
+ ai:=Taicpu.Op_Sym(A_Jcc,S_NO,hl);
+ ai.SetCondition(cond);
+ ai.is_jmp:=true;
+ list.concat(ai);
+
+ a_call_name(list,'FPC_OVERFLOW',false);
+ a_label(list,hl);
+ end;
+
+ procedure tcgx86.g_external_wrapper(list: TAsmList; procdef: tprocdef; const externalname: string);
+ var
+ ref : treference;
+ sym : tasmsymbol;
+ begin
+ if (target_info.system = system_i386_darwin) then
+ begin
+ { a_jmp_name jumps to a stub which is always pic-safe on darwin }
+ inherited g_external_wrapper(list,procdef,externalname);
+ exit;
+ end;
+
+ sym:=current_asmdata.RefAsmSymbol(externalname);
+ reference_reset_symbol(ref,sym,0,sizeof(pint));
+
+ { create pic'ed? }
+ if (cs_create_pic in current_settings.moduleswitches) and
+ { darwin/x86_64's assembler doesn't want @PLT after call symbols }
+ not(target_info.system in [system_x86_64_darwin,system_i386_iphonesim]) then
+ ref.refaddr:=addr_pic
+ else
+ ref.refaddr:=addr_full;
+ list.concat(taicpu.op_ref(A_JMP,S_NO,ref));
+ end;
+
+end.
diff --git a/closures/compiler/x86/cpubase.pas b/closures/compiler/x86/cpubase.pas
new file mode 100644
index 0000000000..056e571cf7
--- /dev/null
+++ b/closures/compiler/x86/cpubase.pas
@@ -0,0 +1,511 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl and Peter Vreman
+
+ Contains the base types for the i386 and x86-64 architecture
+
+ * This code was inspired by the NASM sources
+ The Netwide Assembler is Copyright (c) 1996 Simon Tatham and
+ Julian Hall. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+{# Base unit for processor information. This unit contains
+ enumerations of registers, opcodes, sizes, and other
+ such things which are processor specific.
+}
+unit cpubase;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ cutils,cclasses,
+ globtype,
+ cgbase
+ ;
+
+
+{*****************************************************************************
+ Assembler Opcodes
+*****************************************************************************}
+
+ type
+{$ifdef x86_64}
+ TAsmOp={$i x8664op.inc}
+{$else x86_64}
+ TAsmOp={$i i386op.inc}
+{$endif x86_64}
+
+ { This should define the array of instructions as string }
+ op2strtable=array[tasmop] of string[15];
+
+ const
+ { First value of opcode enumeration }
+ firstop = low(tasmop);
+ { Last value of opcode enumeration }
+ lastop = high(tasmop);
+
+{*****************************************************************************
+ Registers
+*****************************************************************************}
+
+ const
+ { Invalid register number }
+ RS_INVALID = $ff;
+
+ { Integer Super registers }
+ RS_RAX = $00; {EAX}
+ RS_RCX = $01; {ECX}
+ RS_RDX = $02; {EDX}
+ RS_RBX = $03; {EBX}
+ RS_RSI = $04; {ESI}
+ RS_RDI = $05; {EDI}
+ RS_RBP = $06; {EBP}
+ RS_RSP = $07; {ESP}
+ RS_R8 = $08; {R8}
+ RS_R9 = $09; {R9}
+ RS_R10 = $0a; {R10}
+ RS_R11 = $0b; {R11}
+ RS_R12 = $0c; {R12}
+ RS_R13 = $0d; {R13}
+ RS_R14 = $0e; {R14}
+ RS_R15 = $0f; {R15}
+ { create aliases to allow code sharing between x86-64 and i386 }
+ RS_EAX = RS_RAX;
+ RS_EBX = RS_RBX;
+ RS_ECX = RS_RCX;
+ RS_EDX = RS_RDX;
+ RS_ESI = RS_RSI;
+ RS_EDI = RS_RDI;
+ RS_EBP = RS_RBP;
+ RS_ESP = RS_RSP;
+
+ { Number of first imaginary register }
+ first_int_imreg = $10;
+
+ { Float Super registers }
+ RS_ST0 = $00;
+ RS_ST1 = $01;
+ RS_ST2 = $02;
+ RS_ST3 = $03;
+ RS_ST4 = $04;
+ RS_ST5 = $05;
+ RS_ST6 = $06;
+ RS_ST7 = $07;
+
+ { Number of first imaginary register }
+ first_fpu_imreg = $08;
+
+ { MM Super registers }
+ RS_XMM0 = $00;
+ RS_XMM1 = $01;
+ RS_XMM2 = $02;
+ RS_XMM3 = $03;
+ RS_XMM4 = $04;
+ RS_XMM5 = $05;
+ RS_XMM6 = $06;
+ RS_XMM7 = $07;
+ RS_XMM8 = $08;
+ RS_XMM9 = $09;
+ RS_XMM10 = $0a;
+ RS_XMM11 = $0b;
+ RS_XMM12 = $0c;
+ RS_XMM13 = $0d;
+ RS_XMM14 = $0e;
+ RS_XMM15 = $0f;
+
+ { Number of first imaginary register }
+{$ifdef x86_64}
+ first_mm_imreg = $10;
+{$else x86_64}
+ first_mm_imreg = $08;
+{$endif x86_64}
+
+ { The subregister that specifies the entire register and an address }
+{$ifdef x86_64}
+ { Hammer }
+ R_SUBWHOLE = R_SUBQ;
+ R_SUBADDR = R_SUBQ;
+{$else x86_64}
+ { i386 }
+ R_SUBWHOLE = R_SUBD;
+ R_SUBADDR = R_SUBD;
+{$endif x86_64}
+
+ { Available Registers }
+{$ifdef x86_64}
+ {$i r8664con.inc}
+{$else x86_64}
+ {$i r386con.inc}
+{$endif x86_64}
+
+ type
+ { Number of registers used for indexing in tables }
+{$ifdef x86_64}
+ tregisterindex=0..{$i r8664nor.inc}-1;
+{$else x86_64}
+ tregisterindex=0..{$i r386nor.inc}-1;
+{$endif x86_64}
+
+ const
+{ TODO: Calculate bsstart}
+ regnumber_count_bsstart = 64;
+
+ regnumber_table : array[tregisterindex] of tregister = (
+{$ifdef x86_64}
+ {$i r8664num.inc}
+{$else x86_64}
+ {$i r386num.inc}
+{$endif x86_64}
+ );
+
+ regstabs_table : array[tregisterindex] of shortint = (
+{$ifdef x86_64}
+ {$i r8664stab.inc}
+{$else x86_64}
+ {$i r386stab.inc}
+{$endif x86_64}
+ );
+
+ regdwarf_table : array[tregisterindex] of shortint = (
+{$ifdef x86_64}
+ {$i r8664dwrf.inc}
+{$else x86_64}
+ {$i r386dwrf.inc}
+{$endif x86_64}
+ );
+
+ type
+ totherregisterset = set of tregisterindex;
+
+
+{*****************************************************************************
+ Conditions
+*****************************************************************************}
+
+ type
+ TAsmCond=(C_None,
+ C_A,C_AE,C_B,C_BE,C_C,C_E,C_G,C_GE,C_L,C_LE,C_NA,C_NAE,
+ C_NB,C_NBE,C_NC,C_NE,C_NG,C_NGE,C_NL,C_NLE,C_NO,C_NP,
+ C_NS,C_NZ,C_O,C_P,C_PE,C_PO,C_S,C_Z
+ );
+
+ const
+ cond2str:array[TAsmCond] of string[3]=('',
+ 'a','ae','b','be','c','e','g','ge','l','le','na','nae',
+ 'nb','nbe','nc','ne','ng','nge','nl','nle','no','np',
+ 'ns','nz','o','p','pe','po','s','z'
+ );
+
+{*****************************************************************************
+ Flags
+*****************************************************************************}
+
+ type
+ TResFlags = (F_E,F_NE,F_G,F_L,F_GE,F_LE,F_C,F_NC,
+ F_A,F_AE,F_B,F_BE,
+ F_S,F_NS,F_O,F_NO);
+
+
+{*****************************************************************************
+ Constants
+*****************************************************************************}
+
+ const
+ { declare aliases }
+ LOC_SSEREGISTER = LOC_MMREGISTER;
+ LOC_CSSEREGISTER = LOC_CMMREGISTER;
+
+ max_operands = 4;
+ maxfpuregs = 8;
+
+{*****************************************************************************
+ CPU Dependent Constants
+*****************************************************************************}
+
+ {$i cpubase.inc}
+
+{*****************************************************************************
+ Helpers
+*****************************************************************************}
+
+ function cgsize2subreg(regtype: tregistertype; s:Tcgsize):Tsubregister;
+ function reg2opsize(r:Tregister):topsize;
+ function reg_cgsize(const reg: tregister): tcgsize;
+ function is_calljmp(o:tasmop):boolean;
+ procedure inverse_flags(var f: TResFlags);
+ function flags_to_cond(const f: TResFlags) : TAsmCond;
+ function is_segment_reg(r:tregister):boolean;
+ function findreg_by_number(r:Tregister):tregisterindex;
+ function std_regnum_search(const s:string):Tregister;
+ function std_regname(r:Tregister):string;
+ function dwarf_reg(r:tregister):shortint;
+
+ function inverse_cond(const c: TAsmCond): TAsmCond; {$ifdef USEINLINE}inline;{$endif USEINLINE}
+ function conditions_equal(const c1, c2: TAsmCond): boolean; {$ifdef USEINLINE}inline;{$endif USEINLINE}
+
+implementation
+
+ uses
+ rgbase,verbose;
+
+ const
+ {$ifdef x86_64}
+ std_regname_table : array[tregisterindex] of string[7] = (
+ {$i r8664std.inc}
+ );
+
+ regnumber_index : array[tregisterindex] of tregisterindex = (
+ {$i r8664rni.inc}
+ );
+ std_regname_index : array[tregisterindex] of tregisterindex = (
+ {$i r8664sri.inc}
+ );
+ {$else x86_64}
+ std_regname_table : array[tregisterindex] of string[7] = (
+ {$i r386std.inc}
+ );
+
+ regnumber_index : array[tregisterindex] of tregisterindex = (
+ {$i r386rni.inc}
+ );
+
+ std_regname_index : array[tregisterindex] of tregisterindex = (
+ {$i r386sri.inc}
+ );
+ {$endif x86_64}
+
+
+{*****************************************************************************
+ Helpers
+*****************************************************************************}
+
+ function cgsize2subreg(regtype: tregistertype; s:Tcgsize):Tsubregister;
+ begin
+ case s of
+ OS_8,OS_S8:
+ cgsize2subreg:=R_SUBL;
+ OS_16,OS_S16:
+ cgsize2subreg:=R_SUBW;
+ OS_32,OS_S32:
+ cgsize2subreg:=R_SUBD;
+ OS_64,OS_S64:
+ cgsize2subreg:=R_SUBQ;
+ OS_M64:
+ cgsize2subreg:=R_SUBNONE;
+ OS_F32,OS_F64,OS_C64:
+ case regtype of
+ R_FPUREGISTER:
+ cgsize2subreg:=R_SUBWHOLE;
+ R_MMREGISTER:
+ case s of
+ OS_F32:
+ cgsize2subreg:=R_SUBMMS;
+ OS_F64:
+ cgsize2subreg:=R_SUBMMD;
+ else
+ internalerror(2009071901);
+ end;
+ else
+ internalerror(2009071902);
+ end;
+ OS_M128,OS_MS128:
+ cgsize2subreg:=R_SUBMMWHOLE;
+ else
+ internalerror(200301231);
+ end;
+ end;
+
+
+ function reg_cgsize(const reg: tregister): tcgsize;
+ const subreg2cgsize:array[Tsubregister] of Tcgsize =
+ (OS_NO,OS_8,OS_8,OS_16,OS_32,OS_64,OS_NO,OS_NO,OS_NO,OS_F32,OS_F64,OS_M128);
+ begin
+ case getregtype(reg) of
+ R_INTREGISTER :
+ reg_cgsize:=subreg2cgsize[getsubreg(reg)];
+ R_FPUREGISTER :
+ reg_cgsize:=OS_F80;
+ R_MMXREGISTER:
+ reg_cgsize:=OS_M64;
+ R_MMREGISTER:
+ reg_cgsize:=subreg2cgsize[getsubreg(reg)];
+ R_SPECIALREGISTER :
+ case reg of
+ NR_CS,NR_DS,NR_ES,NR_SS,NR_FS,NR_GS:
+ reg_cgsize:=OS_16;
+{$ifdef x86_64}
+ NR_DR0..NR_TR7:
+ reg_cgsize:=OS_64;
+{$endif x86_64}
+ else
+ reg_cgsize:=OS_32
+ end
+ else
+ internalerror(200303181);
+ end;
+ end;
+
+
+ function reg2opsize(r:Tregister):topsize;
+ const
+ subreg2opsize : array[tsubregister] of topsize =
+ (S_NO,S_B,S_B,S_W,S_L,S_Q,S_NO,S_NO,S_NO,S_NO,S_NO,S_NO);
+ begin
+ reg2opsize:=S_L;
+ case getregtype(r) of
+ R_INTREGISTER :
+ reg2opsize:=subreg2opsize[getsubreg(r)];
+ R_FPUREGISTER :
+ reg2opsize:=S_FL;
+ R_MMXREGISTER,
+ R_MMREGISTER :
+ reg2opsize:=S_MD;
+ R_SPECIALREGISTER :
+ begin
+ case r of
+ NR_CS,NR_DS,NR_ES,
+ NR_SS,NR_FS,NR_GS :
+ reg2opsize:=S_W;
+ end;
+ end;
+ else
+ internalerror(200303181);
+ end;
+ end;
+
+
+ function is_calljmp(o:tasmop):boolean;
+ begin
+ case o of
+ A_CALL,
+{$ifdef i386}
+ A_JCXZ,
+{$endif i386}
+ A_JECXZ,
+{$ifdef x86_64}
+ A_JRCXZ,
+{$endif x86_64}
+ A_JMP,
+ A_LOOP,
+ A_LOOPE,
+ A_LOOPNE,
+ A_LOOPNZ,
+ A_LOOPZ,
+ A_LCALL,
+ A_LJMP,
+ A_Jcc :
+ is_calljmp:=true;
+ else
+ is_calljmp:=false;
+ end;
+ end;
+
+
+ procedure inverse_flags(var f: TResFlags);
+ const
+ inv_flags: array[TResFlags] of TResFlags =
+ (F_NE,F_E,F_LE,F_GE,F_L,F_G,F_NC,F_C,
+ F_BE,F_B,F_AE,F_A,
+ F_NS,F_S,F_NO,F_O);
+ begin
+ f:=inv_flags[f];
+ end;
+
+
+ function flags_to_cond(const f: TResFlags) : TAsmCond;
+ const
+ flags_2_cond : array[TResFlags] of TAsmCond =
+ (C_E,C_NE,C_G,C_L,C_GE,C_LE,C_C,C_NC,C_A,C_AE,C_B,C_BE,C_S,C_NS,C_O,C_NO);
+ begin
+ result := flags_2_cond[f];
+ end;
+
+
+ function is_segment_reg(r:tregister):boolean;
+ begin
+ result:=false;
+ case r of
+ NR_CS,NR_DS,NR_ES,
+ NR_SS,NR_FS,NR_GS :
+ result:=true;
+ end;
+ end;
+
+
+ function findreg_by_number(r:Tregister):tregisterindex;
+ var
+ hr : tregister;
+ begin
+ { for the name the sub reg doesn't matter }
+ hr:=r;
+ case getsubreg(hr) of
+ R_SUBMMS,R_SUBMMD,R_SUBMMWHOLE:
+ setsubreg(hr,R_SUBNONE);
+ end;
+ result:=findreg_by_number_table(hr,regnumber_index);
+ end;
+
+
+ function std_regnum_search(const s:string):Tregister;
+ begin
+ result:=regnumber_table[findreg_by_name_table(s,std_regname_table,std_regname_index)];
+ end;
+
+
+ function std_regname(r:Tregister):string;
+ var
+ p : tregisterindex;
+ begin
+ if getregtype(r) in [R_MMREGISTER,R_MMXREGISTER] then
+ r:=newreg(getregtype(r),getsupreg(r),R_SUBNONE);
+ p:=findreg_by_number_table(r,regnumber_index);
+ if p<>0 then
+ result:=std_regname_table[p]
+ else
+ result:=generic_regname(r);
+ end;
+
+
+ function inverse_cond(const c: TAsmCond): TAsmCond; {$ifdef USEINLINE}inline;{$endif USEINLINE}
+ const
+ inverse: array[TAsmCond] of TAsmCond=(C_None,
+ C_NA,C_NAE,C_NB,C_NBE,C_NC,C_NE,C_NG,C_NGE,C_NL,C_NLE,C_A,C_AE,
+ C_B,C_BE,C_C,C_E,C_G,C_GE,C_L,C_LE,C_O,C_P,
+ C_S,C_Z,C_NO,C_NP,C_NP,C_P,C_NS,C_NZ
+ );
+ begin
+ result := inverse[c];
+ end;
+
+
+ function conditions_equal(const c1, c2: TAsmCond): boolean; {$ifdef USEINLINE}inline;{$endif USEINLINE}
+ begin
+ result := c1 = c2;
+ end;
+
+
+ function dwarf_reg(r:tregister):shortint;
+ begin
+ result:=regdwarf_table[findreg_by_number(r)];
+ if result=-1 then
+ internalerror(200603251);
+ end;
+
+
+end.
diff --git a/closures/compiler/x86/itcpugas.pas b/closures/compiler/x86/itcpugas.pas
new file mode 100644
index 0000000000..4280245f4d
--- /dev/null
+++ b/closures/compiler/x86/itcpugas.pas
@@ -0,0 +1,167 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit contains the i386 AT&T instruction tables
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit itcpugas;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cgbase,cpubase;
+
+ type
+ TAttSuffix = (AttSufNONE,AttSufINT,AttSufFPU,AttSufFPUint,AttSufINTdual);
+
+ const
+{$ifdef x86_64}
+ {x86att.inc contains the name for each x86-64 mnemonic}
+ gas_op2str:op2strtable={$i x8664att.inc}
+ gas_needsuffix:array[tasmop] of TAttSuffix={$i x8664ats.inc}
+{$else x86_64}
+ {x86att.inc contains the name for each i386 mnemonic}
+ gas_op2str:op2strtable={$i i386att.inc}
+ gas_needsuffix:array[tasmop] of TAttSuffix={$i i386atts.inc}
+{$endif x86_64}
+
+{$ifdef x86_64}
+ gas_opsize2str : array[topsize] of string[2] = ('',
+ 'b','w','l','q','bw','bl','wl','bq','wq','lq',
+ 's','l','q',
+ 's','l','t','v','x',
+ 'd',
+ '','','',
+ 't',
+ ''
+ );
+ { suffix-to-opsize conversion tables, used in asmreadrer }
+ { !! S_LQ excluded: movzlq does not exist, movslq is processed
+ as a separate instruction w/o suffix (aka movsxd), and there are
+ no more instructions needing it. }
+ att_sizesuffixstr : array[0..11] of string[2] = (
+ '','BW','BL','WL','BQ','WQ',{'LQ',}'B','W','L','S','Q','T'
+ );
+ att_sizesuffix : array[0..11] of topsize = (
+ S_NO,S_BW,S_BL,S_WL,S_BQ,S_WQ,{S_LQ,}S_B,S_W,S_L,S_NO,S_Q,S_NO
+ );
+ att_sizefpusuffix : array[0..11] of topsize = (
+ S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,{S_NO,}S_NO,S_NO,S_FL,S_FS,S_NO,S_FX
+ );
+ att_sizefpuintsuffix : array[0..11] of topsize = (
+ S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,{S_NO,}S_NO,S_NO,S_IL,S_IS,S_IQ,S_NO
+ );
+{$else x86_64}
+ gas_opsize2str : array[topsize] of string[2] = ('',
+ 'b','w','l','q','bw','bl','wl',
+ 's','l','q',
+ 's','l','t','v','',
+ 'd',
+ '','','',
+ 't',
+ ''
+ );
+ { suffix-to-opsize conversion tables, used in asmreadrer }
+ att_sizesuffixstr : array[0..9] of string[2] = (
+ '','BW','BL','WL','B','W','L','S','Q','T'
+ );
+ att_sizesuffix : array[0..9] of topsize = (
+ S_NO,S_BW,S_BL,S_WL,S_B,S_W,S_L,S_NO,S_NO,S_NO
+ );
+ att_sizefpusuffix : array[0..9] of topsize = (
+ S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_FL,S_FS,S_NO,S_FX
+ );
+ att_sizefpuintsuffix : array[0..9] of topsize = (
+ S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_IL,S_IS,S_IQ,S_NO
+ );
+{$endif x86_64}
+
+
+ function gas_regnum_search(const s:string):Tregister;
+ function gas_regname(r:Tregister):string;
+
+
+implementation
+
+ uses
+ cutils,verbose;
+
+ const
+ {$ifdef x86_64}
+ att_regname_table : array[tregisterindex] of string[7] = (
+ {r8664att.inc contains the AT&T name of each register.}
+ {$i r8664att.inc}
+ );
+
+ att_regname_index : array[tregisterindex] of tregisterindex = (
+ {r8664ari.inc contains an index which sorts att_regname_table by
+ ATT name.}
+ {$i r8664ari.inc}
+ );
+ {$else x86_64}
+ att_regname_table : array[tregisterindex] of string[7] = (
+ {r386att.inc contains the AT&T name of each register.}
+ {$i r386att.inc}
+ );
+
+ att_regname_index : array[tregisterindex] of tregisterindex = (
+ {r386ari.inc contains an index which sorts att_regname_table by
+ ATT name.}
+ {$i r386ari.inc}
+ );
+ {$endif x86_64}
+
+ function findreg_by_attname(const s:string):byte;
+ var
+ i,p : tregisterindex;
+ begin
+ {Binary search.}
+ p:=0;
+ i:=regnumber_count_bsstart;
+ repeat
+ if (p+i<=high(tregisterindex)) and (att_regname_table[att_regname_index[p+i]]<=s) then
+ p:=p+i;
+ i:=i shr 1;
+ until i=0;
+ if att_regname_table[att_regname_index[p]]=s then
+ findreg_by_attname:=att_regname_index[p]
+ else
+ findreg_by_attname:=0;
+ end;
+
+
+ function gas_regnum_search(const s:string):Tregister;
+ begin
+ result:=regnumber_table[findreg_by_attname(s)];
+ end;
+
+
+ function gas_regname(r:Tregister):string;
+ var
+ p : tregisterindex;
+ begin
+ p:=findreg_by_number(r);
+ if p<>0 then
+ result:=att_regname_table[p]
+ else
+ result:='%'+generic_regname(r);
+ end;
+
+end.
diff --git a/closures/compiler/x86/itx86int.pas b/closures/compiler/x86/itx86int.pas
new file mode 100644
index 0000000000..182938678d
--- /dev/null
+++ b/closures/compiler/x86/itx86int.pas
@@ -0,0 +1,97 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit contains the i386 AT&T instruction tables
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit itx86int;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cgbase;
+
+ function masm_regnum_search(const s:string):Tregister;
+ function masm_regname(r:Tregister):string;
+
+
+implementation
+
+ uses
+ cutils,verbose,
+ cpubase;
+
+ const
+ {$ifdef x86_64}
+ int_regname_table : array[tregisterindex] of string[7] = (
+ {$i r8664int.inc}
+ );
+
+ int_regname_index : array[tregisterindex] of tregisterindex = (
+ {$i r8664iri.inc}
+ );
+ {$else x86_64}
+ int_regname_table : array[tregisterindex] of string[7] = (
+ {$i r386int.inc}
+ );
+
+ int_regname_index : array[tregisterindex] of tregisterindex = (
+ {$i r386iri.inc}
+ );
+ {$endif x86_64}
+
+
+ function findreg_by_intname(const s:string):byte;
+ var
+ i,p : tregisterindex;
+ begin
+ {Binary search.}
+ p:=0;
+ i:=regnumber_count_bsstart;
+ repeat
+ if (p+i<=high(tregisterindex)) and (int_regname_table[int_regname_index[p+i]]<=s) then
+ p:=p+i;
+ i:=i shr 1;
+ until i=0;
+ if int_regname_table[int_regname_index[p]]=s then
+ findreg_by_intname:=int_regname_index[p]
+ else
+ findreg_by_intname:=0;
+ end;
+
+
+ function masm_regnum_search(const s:string):Tregister;
+ begin
+ result:=regnumber_table[findreg_by_intname(s)];
+ end;
+
+
+ function masm_regname(r:Tregister):string;
+ var
+ p : tregisterindex;
+ begin
+ p:=findreg_by_number(r);
+ if p<>0 then
+ result:=int_regname_table[p]
+ else
+ result:=generic_regname(r);
+ end;
+
+end.
diff --git a/closures/compiler/x86/nx86add.pas b/closures/compiler/x86/nx86add.pas
new file mode 100644
index 0000000000..b1285d29b8
--- /dev/null
+++ b/closures/compiler/x86/nx86add.pas
@@ -0,0 +1,1080 @@
+{
+ Copyright (c) 2000-2002 by Florian Klaempfl
+
+ Common code generation for add nodes on the i386 and x86
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit nx86add;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ cgbase,
+ cpubase,
+ node,nadd,ncgadd;
+
+ type
+ tx86addnode = class(tcgaddnode)
+ protected
+ function getresflags(unsigned : boolean) : tresflags;
+ procedure left_must_be_reg(opsize:TCGSize;noswap:boolean);
+ procedure check_left_and_right_fpureg(force_fpureg: boolean);
+ procedure emit_op_right_left(op:TAsmOp;opsize:TCgSize);
+ procedure emit_generic_code(op:TAsmOp;opsize:TCgSize;unsigned,extra_not,mboverflow:boolean);
+
+ procedure second_cmpfloatsse;
+ procedure second_addfloatsse;
+ public
+ procedure second_addfloat;override;
+ procedure second_addsmallset;override;
+ procedure second_add64bit;override;
+ procedure second_cmpfloat;override;
+ procedure second_cmpsmallset;override;
+ procedure second_cmp64bit;override;
+ procedure second_cmpordinal;override;
+{$ifdef SUPPORT_MMX}
+ procedure second_opmmx;override;
+{$endif SUPPORT_MMX}
+ procedure second_opvector;override;
+ end;
+
+
+ implementation
+
+ uses
+ globtype,globals,
+ verbose,cutils,
+ cpuinfo,
+ aasmbase,aasmtai,aasmdata,aasmcpu,
+ symconst,symdef,
+ cgobj,cgx86,cga,cgutils,
+ paramgr,tgobj,ncgutil,
+ ncon,nset,ninl,
+ defutil;
+
+
+{*****************************************************************************
+ Helpers
+*****************************************************************************}
+
+ procedure tx86addnode.emit_generic_code(op:TAsmOp;opsize:TCGSize;unsigned,extra_not,mboverflow:boolean);
+ var
+ power : longint;
+ hl4 : tasmlabel;
+ r : Tregister;
+ begin
+ { at this point, left.location.loc should be LOC_REGISTER }
+ if right.location.loc=LOC_REGISTER then
+ begin
+ { right.location is a LOC_REGISTER }
+ { when swapped another result register }
+ if (nodetype=subn) and (nf_swapped in flags) then
+ begin
+ if extra_not then
+ emit_reg(A_NOT,TCGSize2Opsize[opsize],left.location.register);
+ emit_reg_reg(op,TCGSize2Opsize[opsize],left.location.register,right.location.register);
+ { newly swapped also set swapped flag }
+ location_swap(left.location,right.location);
+ toggleflag(nf_swapped);
+ end
+ else
+ begin
+ if extra_not then
+ emit_reg(A_NOT,TCGSize2Opsize[opsize],right.location.register);
+ if (op=A_ADD) or (op=A_OR) or (op=A_AND) or (op=A_XOR) or (op=A_IMUL) then
+ location_swap(left.location,right.location);
+ emit_reg_reg(op,TCGSize2Opsize[opsize],right.location.register,left.location.register);
+ end;
+ end
+ else
+ begin
+ { right.location is not a LOC_REGISTER }
+ if (nodetype=subn) and (nf_swapped in flags) then
+ begin
+ if extra_not then
+ cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_NOT,opsize,left.location.register,left.location.register);
+ r:=cg.getintregister(current_asmdata.CurrAsmList,opsize);
+ cg.a_load_loc_reg(current_asmdata.CurrAsmList,opsize,right.location,r);
+ emit_reg_reg(op,TCGSize2Opsize[opsize],left.location.register,r);
+ cg.a_load_reg_reg(current_asmdata.CurrAsmList,opsize,opsize,r,left.location.register);
+ end
+ else
+ begin
+ { Optimizations when right.location is a constant value }
+ if (op=A_CMP) and
+ (nodetype in [equaln,unequaln]) and
+ (right.location.loc=LOC_CONSTANT) and
+ (right.location.value=0) then
+ begin
+ emit_reg_reg(A_TEST,TCGSize2Opsize[opsize],left.location.register,left.location.register);
+ end
+ else
+ if (op=A_ADD) and
+ (right.location.loc=LOC_CONSTANT) and
+ (right.location.value=1) and
+ not(cs_check_overflow in current_settings.localswitches) then
+ begin
+ emit_reg(A_INC,TCGSize2Opsize[opsize],left.location.register);
+ end
+ else
+ if (op=A_SUB) and
+ (right.location.loc=LOC_CONSTANT) and
+ (right.location.value=1) and
+ not(cs_check_overflow in current_settings.localswitches) then
+ begin
+ emit_reg(A_DEC,TCGSize2Opsize[opsize],left.location.register);
+ end
+ else
+ if (op=A_IMUL) and
+ (right.location.loc=LOC_CONSTANT) and
+ (ispowerof2(int64(right.location.value),power)) and
+ not(cs_check_overflow in current_settings.localswitches) then
+ begin
+ emit_const_reg(A_SHL,TCGSize2Opsize[opsize],power,left.location.register);
+ end
+ else
+ begin
+ if extra_not then
+ begin
+ r:=cg.getintregister(current_asmdata.CurrAsmList,opsize);
+ cg.a_load_loc_reg(current_asmdata.CurrAsmList,opsize,right.location,r);
+ emit_reg(A_NOT,TCGSize2Opsize[opsize],r);
+ emit_reg_reg(A_AND,TCGSize2Opsize[opsize],r,left.location.register);
+ end
+ else
+ begin
+ emit_op_right_left(op,opsize);
+ end;
+ end;
+ end;
+ end;
+
+ { only in case of overflow operations }
+ { produce overflow code }
+ { we must put it here directly, because sign of operation }
+ { is in unsigned VAR!! }
+ if mboverflow then
+ begin
+ if cs_check_overflow in current_settings.localswitches then
+ begin
+ current_asmdata.getjumplabel(hl4);
+ if unsigned then
+ cg.a_jmp_flags(current_asmdata.CurrAsmList,F_AE,hl4)
+ else
+ cg.a_jmp_flags(current_asmdata.CurrAsmList,F_NO,hl4);
+ cg.a_call_name(current_asmdata.CurrAsmList,'FPC_OVERFLOW',false);
+ cg.a_label(current_asmdata.CurrAsmList,hl4);
+ end;
+ end;
+ end;
+
+
+ procedure tx86addnode.left_must_be_reg(opsize:TCGSize;noswap:boolean);
+ begin
+ { left location is not a register? }
+ if (left.location.loc<>LOC_REGISTER) then
+ begin
+ { if right is register then we can swap the locations }
+ if (not noswap) and
+ (right.location.loc=LOC_REGISTER) then
+ begin
+ location_swap(left.location,right.location);
+ toggleflag(nf_swapped);
+ end
+ else
+ begin
+ { maybe we can reuse a constant register when the
+ operation is a comparison that doesn't change the
+ value of the register }
+ location_force_reg(current_asmdata.CurrAsmList,left.location,opsize,(nodetype in [ltn,lten,gtn,gten,equaln,unequaln]));
+ end;
+ end;
+ if (right.location.loc<>LOC_CONSTANT) and
+ (tcgsize2unsigned[right.location.size]<>tcgsize2unsigned[opsize]) then
+ location_force_reg(current_asmdata.CurrAsmList,right.location,opsize,true);
+ if (left.location.loc<>LOC_CONSTANT) and
+ (tcgsize2unsigned[left.location.size]<>tcgsize2unsigned[opsize]) then
+ location_force_reg(current_asmdata.CurrAsmList,left.location,opsize,false);
+ end;
+
+
+ procedure tx86addnode.check_left_and_right_fpureg(force_fpureg: boolean);
+ begin
+ if (right.location.loc<>LOC_FPUREGISTER) then
+ begin
+ if (force_fpureg) then
+ begin
+ location_force_fpureg(current_asmdata.CurrAsmList,right.location,false);
+ if (left.location.loc<>LOC_FPUREGISTER) then
+ location_force_fpureg(current_asmdata.CurrAsmList,left.location,false)
+ else
+ { left was on the stack => swap }
+ toggleflag(nf_swapped);
+ end
+ end
+ { the nominator in st0 }
+ else if (left.location.loc<>LOC_FPUREGISTER) then
+ begin
+ if (force_fpureg) then
+ location_force_fpureg(current_asmdata.CurrAsmList,left.location,false)
+ end
+ else
+ begin
+ { fpu operands are always in the wrong order on the stack }
+ toggleflag(nf_swapped);
+ end;
+ end;
+
+
+ procedure tx86addnode.emit_op_right_left(op:TAsmOp;opsize:TCgsize);
+{$ifdef x86_64}
+ var
+ tmpreg : tregister;
+{$endif x86_64}
+ begin
+ if (right.location.loc in [LOC_CSUBSETREG,LOC_SUBSETREG,LOC_SUBSETREF,LOC_CSUBSETREF]) then
+ location_force_reg(current_asmdata.CurrAsmList,right.location,def_cgsize(right.resultdef),true);
+ { left must be a register }
+ case right.location.loc of
+ LOC_REGISTER,
+ LOC_CREGISTER :
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op,TCGSize2Opsize[opsize],right.location.register,left.location.register));
+ LOC_REFERENCE,
+ LOC_CREFERENCE :
+ begin
+ tcgx86(cg).make_simple_ref(current_asmdata.CurrAsmList,right.location.reference);
+ current_asmdata.CurrAsmList.concat(taicpu.op_ref_reg(op,TCGSize2Opsize[opsize],right.location.reference,left.location.register));
+ end;
+ LOC_CONSTANT :
+ begin
+{$ifdef x86_64}
+ { x86_64 only supports signed 32 bits constants directly }
+ if (opsize in [OS_S64,OS_64]) and
+ ((right.location.value<low(longint)) or (right.location.value>high(longint))) then
+ begin
+ tmpreg:=cg.getintregister(current_asmdata.CurrAsmList,opsize);
+ cg.a_load_const_reg(current_asmdata.CurrAsmList,opsize,right.location.value,tmpreg);
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op,TCGSize2Opsize[opsize],tmpreg,left.location.register));
+ end
+ else
+{$endif x86_64}
+ current_asmdata.CurrAsmList.concat(taicpu.op_const_reg(op,TCGSize2Opsize[opsize],right.location.value,left.location.register));
+ end;
+ else
+ internalerror(200203232);
+ end;
+ end;
+
+
+ function tx86addnode.getresflags(unsigned : boolean) : tresflags;
+ begin
+ case nodetype of
+ equaln : getresflags:=F_E;
+ unequaln : getresflags:=F_NE;
+ else
+ if not(unsigned) then
+ begin
+ if nf_swapped in flags then
+ case nodetype of
+ ltn : getresflags:=F_G;
+ lten : getresflags:=F_GE;
+ gtn : getresflags:=F_L;
+ gten : getresflags:=F_LE;
+ end
+ else
+ case nodetype of
+ ltn : getresflags:=F_L;
+ lten : getresflags:=F_LE;
+ gtn : getresflags:=F_G;
+ gten : getresflags:=F_GE;
+ end;
+ end
+ else
+ begin
+ if nf_swapped in flags then
+ case nodetype of
+ ltn : getresflags:=F_A;
+ lten : getresflags:=F_AE;
+ gtn : getresflags:=F_B;
+ gten : getresflags:=F_BE;
+ end
+ else
+ case nodetype of
+ ltn : getresflags:=F_B;
+ lten : getresflags:=F_BE;
+ gtn : getresflags:=F_A;
+ gten : getresflags:=F_AE;
+ end;
+ end;
+ end;
+ end;
+
+
+{*****************************************************************************
+ AddSmallSet
+*****************************************************************************}
+
+ procedure tx86addnode.second_addsmallset;
+ var
+ setbase : aint;
+ opsize : TCGSize;
+ op : TAsmOp;
+ extra_not,
+ noswap : boolean;
+ all_member_optimization:boolean;
+
+ begin
+ pass_left_right;
+
+ noswap:=false;
+ extra_not:=false;
+ all_member_optimization:=false;
+ opsize:=int_cgsize(resultdef.size);
+ if (left.resultdef.typ=setdef) then
+ setbase:=tsetdef(left.resultdef).setbase
+ else
+ setbase:=tsetdef(right.resultdef).setbase;
+ case nodetype of
+ addn :
+ begin
+ { adding elements is not commutative }
+ if (nf_swapped in flags) and (left.nodetype=setelementn) then
+ swapleftright;
+ { are we adding set elements ? }
+ if right.nodetype=setelementn then
+ begin
+ { no range support for smallsets! }
+ if assigned(tsetelementnode(right).right) then
+ internalerror(43244);
+ { btsb isn't supported }
+ if opsize=OS_8 then
+ opsize:=OS_32;
+ { bts requires both elements to be registers }
+ location_force_reg(current_asmdata.CurrAsmList,left.location,opsize,false);
+ location_force_reg(current_asmdata.CurrAsmList,right.location,opsize,true);
+ register_maybe_adjust_setbase(current_asmdata.CurrAsmList,right.location,setbase);
+ op:=A_BTS;
+ noswap:=true;
+ end
+ else
+ op:=A_OR;
+ end;
+ symdifn :
+ op:=A_XOR;
+ muln :
+ op:=A_AND;
+ subn :
+ begin
+ op:=A_AND;
+ if (not(nf_swapped in flags) and (left.location.loc=LOC_CONSTANT) and (left.location.value=-1)) or
+ ((nf_swapped in flags) and (right.location.loc=LOC_CONSTANT) and (right.location.value=-1)) then
+ all_member_optimization:=true;
+
+ if (not(nf_swapped in flags)) and
+ (right.location.loc=LOC_CONSTANT) then
+ right.location.value := not(right.location.value)
+ else if (nf_swapped in flags) and
+ (left.location.loc=LOC_CONSTANT) then
+ left.location.value := not(left.location.value)
+ else
+ extra_not:=true;
+ end;
+ xorn :
+ op:=A_XOR;
+ orn :
+ op:=A_OR;
+ andn :
+ op:=A_AND;
+ else
+ internalerror(2003042215);
+ end;
+ if all_member_optimization then
+ begin
+ {A set expression [0..31]-x can be implemented with a simple NOT.}
+ if nf_swapped in flags then
+ begin
+ { newly swapped also set swapped flag }
+ location_swap(left.location,right.location);
+ toggleflag(nf_swapped);
+ end;
+ location_force_reg(current_asmdata.currAsmList,right.location,opsize,false);
+ emit_reg(A_NOT,TCGSize2Opsize[opsize],right.location.register);
+ location:=right.location;
+ end
+ else
+ begin
+ { left must be a register }
+ left_must_be_reg(opsize,noswap);
+ emit_generic_code(op,opsize,true,extra_not,false);
+ location_freetemp(current_asmdata.CurrAsmList,right.location);
+
+ { left is always a register and contains the result }
+ location:=left.location;
+ end;
+
+ { fix the changed opsize we did above because of the missing btsb }
+ if opsize<>int_cgsize(resultdef.size) then
+ location_force_reg(current_asmdata.CurrAsmList,location,int_cgsize(resultdef.size),false);
+ end;
+
+
+ procedure tx86addnode.second_cmpsmallset;
+ var
+ opsize : TCGSize;
+ op : TAsmOp;
+ begin
+ pass_left_right;
+ opsize:=int_cgsize(left.resultdef.size);
+ case nodetype of
+ equaln,
+ unequaln :
+ op:=A_CMP;
+ lten,gten:
+ begin
+ if (not(nf_swapped in flags) and (nodetype = lten)) or
+ ((nf_swapped in flags) and (nodetype = gten)) then
+ swapleftright;
+ location_force_reg(current_asmdata.CurrAsmList,left.location,opsize,false);
+ emit_op_right_left(A_AND,opsize);
+ op:=A_CMP;
+ { warning: ugly hack, we need a JE so change the node to equaln }
+ nodetype:=equaln;
+ end;
+ else
+ internalerror(2003042215);
+ end;
+ { left must be a register }
+ left_must_be_reg(opsize,false);
+ emit_generic_code(op,opsize,true,false,false);
+ location_freetemp(current_asmdata.CurrAsmList,right.location);
+ location_freetemp(current_asmdata.CurrAsmList,left.location);
+
+ location_reset(location,LOC_FLAGS,OS_NO);
+ location.resflags:=getresflags(true);
+ end;
+
+
+{*****************************************************************************
+ AddMMX
+*****************************************************************************}
+
+{$ifdef SUPPORT_MMX}
+ procedure tx86addnode.second_opmmx;
+ var
+ op : TAsmOp;
+ cmpop : boolean;
+ mmxbase : tmmxtype;
+ hreg,
+ hregister : tregister;
+ begin
+ pass_left_right;
+
+ cmpop:=false;
+ mmxbase:=mmx_type(left.resultdef);
+ location_reset(location,LOC_MMXREGISTER,def_cgsize(resultdef));
+ case nodetype of
+ addn :
+ begin
+ if (cs_mmx_saturation in current_settings.localswitches) then
+ begin
+ case mmxbase of
+ mmxs8bit:
+ op:=A_PADDSB;
+ mmxu8bit:
+ op:=A_PADDUSB;
+ mmxs16bit,mmxfixed16:
+ op:=A_PADDSW;
+ mmxu16bit:
+ op:=A_PADDUSW;
+ end;
+ end
+ else
+ begin
+ case mmxbase of
+ mmxs8bit,mmxu8bit:
+ op:=A_PADDB;
+ mmxs16bit,mmxu16bit,mmxfixed16:
+ op:=A_PADDW;
+ mmxs32bit,mmxu32bit:
+ op:=A_PADDD;
+ end;
+ end;
+ end;
+ muln :
+ begin
+ case mmxbase of
+ mmxs16bit,mmxu16bit:
+ op:=A_PMULLW;
+ mmxfixed16:
+ op:=A_PMULHW;
+ end;
+ end;
+ subn :
+ begin
+ if (cs_mmx_saturation in current_settings.localswitches) then
+ begin
+ case mmxbase of
+ mmxs8bit:
+ op:=A_PSUBSB;
+ mmxu8bit:
+ op:=A_PSUBUSB;
+ mmxs16bit,mmxfixed16:
+ op:=A_PSUBSB;
+ mmxu16bit:
+ op:=A_PSUBUSW;
+ end;
+ end
+ else
+ begin
+ case mmxbase of
+ mmxs8bit,mmxu8bit:
+ op:=A_PSUBB;
+ mmxs16bit,mmxu16bit,mmxfixed16:
+ op:=A_PSUBW;
+ mmxs32bit,mmxu32bit:
+ op:=A_PSUBD;
+ end;
+ end;
+ end;
+ xorn:
+ op:=A_PXOR;
+ orn:
+ op:=A_POR;
+ andn:
+ op:=A_PAND;
+ else
+ internalerror(2003042214);
+ end;
+
+ { left and right no register? }
+ { then one must be demanded }
+ if (left.location.loc<>LOC_MMXREGISTER) then
+ begin
+ if (right.location.loc=LOC_MMXREGISTER) then
+ begin
+ location_swap(left.location,right.location);
+ toggleflag(nf_swapped);
+ end
+ else
+ begin
+ { register variable ? }
+ if (left.location.loc=LOC_CMMXREGISTER) then
+ begin
+ hregister:=tcgx86(cg).getmmxregister(current_asmdata.CurrAsmList);
+ emit_reg_reg(A_MOVQ,S_NO,left.location.register,hregister);
+ end
+ else
+ begin
+ if not(left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
+ internalerror(200203245);
+
+ hregister:=tcgx86(cg).getmmxregister(current_asmdata.CurrAsmList);
+ tcgx86(cg).make_simple_ref(current_asmdata.CurrAsmList,left.location.reference);
+ emit_ref_reg(A_MOVQ,S_NO,left.location.reference,hregister);
+ end;
+
+ location_reset(left.location,LOC_MMXREGISTER,OS_NO);
+ left.location.register:=hregister;
+ end;
+ end;
+
+ { at this point, left.location.loc should be LOC_MMXREGISTER }
+ if right.location.loc<>LOC_MMXREGISTER then
+ begin
+ if (nodetype=subn) and (nf_swapped in flags) then
+ begin
+ hreg:=tcgx86(cg).getmmxregister(current_asmdata.CurrAsmList);
+ if right.location.loc=LOC_CMMXREGISTER then
+ begin
+ emit_reg_reg(A_MOVQ,S_NO,right.location.register,hreg);
+ emit_reg_reg(op,S_NO,left.location.register,hreg);
+ end
+ else
+ begin
+ if not(left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
+ internalerror(200203247);
+ tcgx86(cg).make_simple_ref(current_asmdata.CurrAsmList,right.location.reference);
+ emit_ref_reg(A_MOVQ,S_NO,right.location.reference,hreg);
+ emit_reg_reg(op,S_NO,left.location.register,hreg);
+ end;
+ location.register:=hreg;
+ end
+ else
+ begin
+ if (right.location.loc=LOC_CMMXREGISTER) then
+ emit_reg_reg(op,S_NO,right.location.register,left.location.register)
+ else
+ begin
+ if not(right.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
+ internalerror(200203246);
+ tcgx86(cg).make_simple_ref(current_asmdata.CurrAsmList,right.location.reference);
+ emit_ref_reg(op,S_NO,right.location.reference,left.location.register);
+ end;
+ location.register:=left.location.register;
+ end;
+ end
+ else
+ begin
+ { right.location=LOC_MMXREGISTER }
+ if (nodetype=subn) and (nf_swapped in flags) then
+ begin
+ emit_reg_reg(op,S_NO,left.location.register,right.location.register);
+ location_swap(left.location,right.location);
+ toggleflag(nf_swapped);
+ end
+ else
+ begin
+ emit_reg_reg(op,S_NO,right.location.register,left.location.register);
+ end;
+ location.register:=left.location.register;
+ end;
+
+ location_freetemp(current_asmdata.CurrAsmList,right.location);
+ if cmpop then
+ location_freetemp(current_asmdata.CurrAsmList,left.location);
+ end;
+{$endif SUPPORT_MMX}
+
+
+{*****************************************************************************
+ AddFloat
+*****************************************************************************}
+
+ procedure tx86addnode.second_addfloatsse;
+ var
+ op : topcg;
+ sqr_sum : boolean;
+ tmp : tnode;
+ begin
+ sqr_sum:=false;
+ if (current_settings.fputype>=fpu_sse3) and
+ use_vectorfpu(resultdef) and
+ (nodetype in [addn,subn]) and
+ (left.nodetype=inlinen) and (tinlinenode(left).inlinenumber=in_sqr_real) and
+ (right.nodetype=inlinen) and (tinlinenode(right).inlinenumber=in_sqr_real) then
+ begin
+ sqr_sum:=true;
+ tmp:=tinlinenode(left).left;
+ tinlinenode(left).left:=nil;
+ left.free;
+ left:=tmp;
+
+ tmp:=tinlinenode(right).left;
+ tinlinenode(right).left:=nil;
+ right.free;
+ right:=tmp;
+ end;
+
+ pass_left_right;
+ check_left_and_right_fpureg(false);
+
+ if (nf_swapped in flags) then
+ { can't use swapleftright if both are on the fpu stack, since then }
+ { both are "R_ST" -> nothing would change -> manually switch }
+ if (left.location.loc = LOC_FPUREGISTER) and
+ (right.location.loc = LOC_FPUREGISTER) then
+ emit_none(A_FXCH,S_NO)
+ else
+ swapleftright;
+
+ case nodetype of
+ addn :
+ op:=OP_ADD;
+ muln :
+ op:=OP_MUL;
+ subn :
+ op:=OP_SUB;
+ slashn :
+ op:=OP_DIV;
+ else
+ internalerror(200312231);
+ end;
+
+ location_reset(location,LOC_MMREGISTER,def_cgsize(resultdef));
+
+ if sqr_sum then
+ begin
+ if nf_swapped in flags then
+ swapleftright;
+
+ location_force_mmregscalar(current_asmdata.CurrAsmList,left.location,false);
+ location_force_mmregscalar(current_asmdata.CurrAsmList,right.location,true);
+ location:=left.location;
+ if is_double(resultdef) then
+ begin
+ current_asmdata.CurrAsmList.concat(taicpu.op_const_reg_reg(A_SHUFPD,S_NO,%00,right.location.register,location.register));
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_MULPD,S_NO,location.register,location.register));
+ case nodetype of
+ addn:
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_HADDPD,S_NO,location.register,location.register));
+ subn:
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_HSUBPD,S_NO,location.register,location.register));
+ else
+ internalerror(201108162);
+ end;
+ end
+ else
+ begin
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_UNPCKLPS,S_NO,right.location.register,location.register));
+ { ensure that bits 64..127 contain valid values }
+ current_asmdata.CurrAsmList.concat(taicpu.op_const_reg_reg(A_SHUFPD,S_NO,%00,location.register,location.register));
+ { the data is now in bits 0..32 and 64..95 }
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_MULPS,S_NO,location.register,location.register));
+ case nodetype of
+ addn:
+ begin
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_HADDPS,S_NO,location.register,location.register));
+ end;
+ subn:
+ begin
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_HSUBPS,S_NO,location.register,location.register));
+ end;
+ else
+ internalerror(201108163);
+ end;
+ end
+ end
+ { we can use only right as left operand if the operation is commutative }
+ else if (right.location.loc=LOC_MMREGISTER) and (op in [OP_ADD,OP_MUL]) then
+ begin
+ location.register:=right.location.register;
+ { force floating point reg. location to be written to memory,
+ we don't force it to mm register because writing to memory
+ allows probably shorter code because there is no direct fpu->mm register
+ copy instruction
+ }
+ if left.location.loc in [LOC_FPUREGISTER,LOC_CFPUREGISTER] then
+ location_force_mem(current_asmdata.CurrAsmList,left.location);
+ cg.a_opmm_loc_reg(current_asmdata.CurrAsmList,op,location.size,left.location,location.register,mms_movescalar);
+ end
+ else
+ begin
+ if (nf_swapped in flags) then
+ swapleftright;
+
+ location_force_mmregscalar(current_asmdata.CurrAsmList,left.location,false);
+ location.register:=left.location.register;
+ { force floating point reg. location to be written to memory,
+ we don't force it to mm register because writing to memory
+ allows probably shorter code because there is no direct fpu->mm register
+ copy instruction
+ }
+ if right.location.loc in [LOC_FPUREGISTER,LOC_CFPUREGISTER] then
+ location_force_mem(current_asmdata.CurrAsmList,right.location);
+ cg.a_opmm_loc_reg(current_asmdata.CurrAsmList,op,location.size,right.location,location.register,mms_movescalar);
+ end;
+ end;
+
+
+ procedure tx86addnode.second_cmpfloatsse;
+ var
+ op : tasmop;
+ begin
+ if is_single(left.resultdef) then
+ op:=A_COMISS
+ else if is_double(left.resultdef) then
+ op:=A_COMISD
+ else
+ internalerror(200402222);
+ pass_left_right;
+
+ location_reset(location,LOC_FLAGS,def_cgsize(resultdef));
+ { we can use only right as left operand if the operation is commutative }
+ if (right.location.loc=LOC_MMREGISTER) then
+ begin
+ { force floating point reg. location to be written to memory,
+ we don't force it to mm register because writing to memory
+ allows probably shorter code because there is no direct fpu->mm register
+ copy instruction
+ }
+ if left.location.loc in [LOC_FPUREGISTER,LOC_CFPUREGISTER] then
+ location_force_mem(current_asmdata.CurrAsmList,left.location);
+ case left.location.loc of
+ LOC_REFERENCE,LOC_CREFERENCE:
+ begin
+ tcgx86(cg).make_simple_ref(current_asmdata.CurrAsmList,left.location.reference);
+ current_asmdata.CurrAsmList.concat(taicpu.op_ref_reg(op,S_NO,left.location.reference,right.location.register));
+ end;
+ LOC_MMREGISTER,LOC_CMMREGISTER:
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op,S_NO,left.location.register,right.location.register));
+ else
+ internalerror(200402221);
+ end;
+ if nf_swapped in flags then
+ exclude(flags,nf_swapped)
+ else
+ include(flags,nf_swapped)
+ end
+ else
+ begin
+ location_force_mmregscalar(current_asmdata.CurrAsmList,left.location,false);
+ { force floating point reg. location to be written to memory,
+ we don't force it to mm register because writing to memory
+ allows probably shorter code because there is no direct fpu->mm register
+ copy instruction
+ }
+ if right.location.loc in [LOC_FPUREGISTER,LOC_CFPUREGISTER] then
+ location_force_mem(current_asmdata.CurrAsmList,right.location);
+ case right.location.loc of
+ LOC_REFERENCE,LOC_CREFERENCE:
+ begin
+ tcgx86(cg).make_simple_ref(current_asmdata.CurrAsmList,right.location.reference);
+ current_asmdata.CurrAsmList.concat(taicpu.op_ref_reg(op,S_NO,right.location.reference,left.location.register));
+ end;
+ LOC_MMREGISTER,LOC_CMMREGISTER:
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op,S_NO,right.location.register,left.location.register));
+ else
+ internalerror(200402223);
+ end;
+ end;
+ location.resflags:=getresflags(true);
+ end;
+
+
+ procedure tx86addnode.second_opvector;
+ var
+ op : topcg;
+ begin
+ pass_left_right;
+ if (nf_swapped in flags) then
+ swapleftright;
+
+ case nodetype of
+ addn :
+ op:=OP_ADD;
+ muln :
+ op:=OP_MUL;
+ subn :
+ op:=OP_SUB;
+ slashn :
+ op:=OP_DIV;
+ else
+ internalerror(200610071);
+ end;
+
+ if fits_in_mm_register(left.resultdef) then
+ begin
+ location_reset(location,LOC_MMREGISTER,def_cgsize(resultdef));
+ { we can use only right as left operand if the operation is commutative }
+ if (right.location.loc=LOC_MMREGISTER) and (op in [OP_ADD,OP_MUL]) then
+ begin
+ location.register:=right.location.register;
+ cg.a_opmm_loc_reg(current_asmdata.CurrAsmList,op,tfloat2tcgsize[tfloatdef(left.resultdef).floattype],left.location,location.register,nil);
+ end
+ else
+ begin
+ location_force_mmreg(current_asmdata.CurrAsmList,left.location,false);
+ location.register:=left.location.register;
+ cg.a_opmm_loc_reg(current_asmdata.CurrAsmList,op,
+ tfloat2tcgsize[tfloatdef(tarraydef(left.resultdef).elementdef).floattype],right.location,location.register,nil);
+ end;
+ end
+ else
+ begin
+ { not yet supported }
+ internalerror(200610072);
+ end
+ end;
+
+
+ procedure tx86addnode.second_addfloat;
+ var
+ op : TAsmOp;
+ begin
+ if use_vectorfpu(resultdef) then
+ begin
+ second_addfloatsse;
+ exit;
+ end;
+
+ pass_left_right;
+
+ case nodetype of
+ addn :
+ op:=A_FADDP;
+ muln :
+ op:=A_FMULP;
+ subn :
+ op:=A_FSUBP;
+ slashn :
+ op:=A_FDIVP;
+ else
+ internalerror(2003042214);
+ end;
+
+ check_left_and_right_fpureg(true);
+
+ { if we swaped the tree nodes, then use the reverse operator }
+ if nf_swapped in flags then
+ begin
+ if (nodetype=slashn) then
+ op:=A_FDIVRP
+ else if (nodetype=subn) then
+ op:=A_FSUBRP;
+ end;
+
+ emit_reg_reg(op,S_NO,NR_ST,NR_ST1);
+ tcgx86(cg).dec_fpu_stack;
+
+ location_reset(location,LOC_FPUREGISTER,def_cgsize(resultdef));
+ location.register:=NR_ST;
+ end;
+
+
+ procedure tx86addnode.second_cmpfloat;
+ var
+ resflags : tresflags;
+ begin
+ if use_vectorfpu(left.resultdef) or use_vectorfpu(right.resultdef) then
+ begin
+ second_cmpfloatsse;
+ exit;
+ end;
+
+ pass_left_right;
+ check_left_and_right_fpureg(true);
+
+{$ifndef x86_64}
+ if current_settings.cputype<cpu_Pentium2 then
+ begin
+ emit_none(A_FCOMPP,S_NO);
+ tcgx86(cg).dec_fpu_stack;
+ tcgx86(cg).dec_fpu_stack;
+
+ { load fpu flags }
+ cg.getcpuregister(current_asmdata.CurrAsmList,NR_AX);
+ emit_reg(A_FSTSW,S_NO,NR_AX);
+ emit_none(A_SAHF,S_NO);
+ cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_AX);
+ if nf_swapped in flags then
+ begin
+ case nodetype of
+ equaln : resflags:=F_E;
+ unequaln : resflags:=F_NE;
+ ltn : resflags:=F_A;
+ lten : resflags:=F_AE;
+ gtn : resflags:=F_B;
+ gten : resflags:=F_BE;
+ end;
+ end
+ else
+ begin
+ case nodetype of
+ equaln : resflags:=F_E;
+ unequaln : resflags:=F_NE;
+ ltn : resflags:=F_B;
+ lten : resflags:=F_BE;
+ gtn : resflags:=F_A;
+ gten : resflags:=F_AE;
+ end;
+ end;
+ end
+ else
+{$endif x86_64}
+ begin
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FCOMIP,S_NO,NR_ST1,NR_ST0));
+ { fcomip pops only one fpu register }
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg(A_FSTP,S_NO,NR_ST0));
+ tcgx86(cg).dec_fpu_stack;
+ tcgx86(cg).dec_fpu_stack;
+
+ { load fpu flags }
+ if nf_swapped in flags then
+ begin
+ case nodetype of
+ equaln : resflags:=F_E;
+ unequaln : resflags:=F_NE;
+ ltn : resflags:=F_A;
+ lten : resflags:=F_AE;
+ gtn : resflags:=F_B;
+ gten : resflags:=F_BE;
+ end;
+ end
+ else
+ begin
+ case nodetype of
+ equaln : resflags:=F_E;
+ unequaln : resflags:=F_NE;
+ ltn : resflags:=F_B;
+ lten : resflags:=F_BE;
+ gtn : resflags:=F_A;
+ gten : resflags:=F_AE;
+ end;
+ end;
+ end;
+
+ location_reset(location,LOC_FLAGS,OS_NO);
+ location.resflags:=resflags;
+ end;
+
+
+{*****************************************************************************
+ Add64bit
+*****************************************************************************}
+
+ procedure tx86addnode.second_add64bit;
+ begin
+{$ifdef cpu64bitalu}
+ second_addordinal;
+{$else cpu64bitalu}
+ { must be implemented separate }
+ internalerror(200402042);
+{$endif cpu64bitalu}
+ end;
+
+
+ procedure tx86addnode.second_cmp64bit;
+ begin
+{$ifdef cpu64bitalu}
+ second_cmpordinal;
+{$else cpu64bitalu}
+ { must be implemented separate }
+ internalerror(200402043);
+{$endif cpu64bitalu}
+ end;
+
+
+{*****************************************************************************
+ AddOrdinal
+*****************************************************************************}
+
+ procedure tx86addnode.second_cmpordinal;
+ var
+ opsize : tcgsize;
+ unsigned : boolean;
+ begin
+ unsigned:=not(is_signed(left.resultdef)) or
+ not(is_signed(right.resultdef));
+ opsize:=def_cgsize(left.resultdef);
+
+ pass_left_right;
+
+ left_must_be_reg(opsize,false);
+ emit_generic_code(A_CMP,opsize,unsigned,false,false);
+ location_freetemp(current_asmdata.CurrAsmList,right.location);
+ location_freetemp(current_asmdata.CurrAsmList,left.location);
+
+ location_reset(location,LOC_FLAGS,OS_NO);
+ location.resflags:=getresflags(unsigned);
+ end;
+
+begin
+ caddnode:=tx86addnode;
+end.
diff --git a/closures/compiler/x86/nx86cnv.pas b/closures/compiler/x86/nx86cnv.pas
new file mode 100644
index 0000000000..7884c5c803
--- /dev/null
+++ b/closures/compiler/x86/nx86cnv.pas
@@ -0,0 +1,378 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate for x86-64 and i386 assembler for type converting nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit nx86cnv;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,ncgcnv,defutil,defcmp;
+
+ type
+ tx86typeconvnode = class(tcgtypeconvnode)
+ protected
+ function first_real_to_real : tnode;override;
+ { procedure second_int_to_int;override; }
+ { procedure second_string_to_string;override; }
+ { procedure second_cstring_to_pchar;override; }
+ { procedure second_string_to_chararray;override; }
+ { procedure second_array_to_pointer;override; }
+ { procedure second_pointer_to_array;override; }
+ { procedure second_chararray_to_string;override; }
+ { procedure second_char_to_string;override; }
+ function first_int_to_real: tnode; override;
+ procedure second_int_to_real;override;
+ { procedure second_real_to_real;override; }
+ { procedure second_cord_to_pointer;override; }
+ { procedure second_proc_to_procvar;override; }
+ { procedure second_bool_to_int;override; }
+ procedure second_int_to_bool;override;
+ { procedure second_set_to_set;override; }
+ { procedure second_ansistring_to_pchar;override; }
+ { procedure second_pchar_to_string;override; }
+ { procedure second_class_to_intf;override; }
+ { procedure second_char_to_char;override; }
+ end;
+
+
+implementation
+
+ uses
+ verbose,systems,globals,globtype,
+ aasmbase,aasmtai,aasmdata,aasmcpu,
+ symconst,symdef,
+ cgbase,cga,procinfo,pass_1,pass_2,
+ ncon,ncal,ncnv,
+ cpubase,
+ cgutils,cgobj,cgx86,ncgutil,
+ tgobj;
+
+
+ function tx86typeconvnode.first_real_to_real : tnode;
+ begin
+ first_real_to_real:=nil;
+ { comp isn't a floating type }
+ if (tfloatdef(resultdef).floattype=s64comp) and
+ (tfloatdef(left.resultdef).floattype<>s64comp) and
+ not (nf_explicit in flags) then
+ CGMessage(type_w_convert_real_2_comp);
+ if use_vectorfpu(resultdef) then
+ expectloc:=LOC_MMREGISTER
+ else
+ expectloc:=LOC_FPUREGISTER;
+ end;
+
+
+ procedure tx86typeconvnode.second_int_to_bool;
+ var
+{$ifndef cpu64bitalu}
+ hreg2,
+ hregister : tregister;
+ href : treference;
+{$endif not cpu64bitalu}
+ resflags : tresflags;
+ hlabel,oldTrueLabel,oldFalseLabel : tasmlabel;
+ newsize : tcgsize;
+ begin
+ oldTrueLabel:=current_procinfo.CurrTrueLabel;
+ oldFalseLabel:=current_procinfo.CurrFalseLabel;
+ current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
+ current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel);
+ secondpass(left);
+ if codegenerror then
+ exit;
+ { Explicit typecasts from any ordinal type to a boolean type }
+ { must not change the ordinal value }
+ if (nf_explicit in flags) and
+ not(left.location.loc in [LOC_FLAGS,LOC_JUMP]) then
+ begin
+ location_copy(location,left.location);
+ newsize:=def_cgsize(resultdef);
+ { change of size? change sign only if location is LOC_(C)REGISTER? Then we have to sign/zero-extend }
+ if (tcgsize2size[newsize]<>tcgsize2size[left.location.size]) or
+ ((newsize<>left.location.size) and (location.loc in [LOC_REGISTER,LOC_CREGISTER])) then
+ location_force_reg(current_asmdata.CurrAsmList,location,newsize,true)
+ else
+ location.size:=newsize;
+ current_procinfo.CurrTrueLabel:=oldTrueLabel;
+ current_procinfo.CurrFalseLabel:=oldFalseLabel;
+ exit;
+ end;
+
+ { Load left node into flag F_NE/F_E }
+ resflags:=F_NE;
+
+ if (left.location.loc in [LOC_SUBSETREG,LOC_CSUBSETREG,LOC_SUBSETREF,LOC_CSUBSETREF]) then
+ location_force_reg(current_asmdata.CurrAsmList,left.location,left.location.size,true);
+
+ case left.location.loc of
+ LOC_CREFERENCE,
+ LOC_REFERENCE :
+ begin
+{$ifndef cpu64bitalu}
+ if left.location.size in [OS_64,OS_S64] then
+ begin
+ hregister:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+ cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_32,OS_32,left.location.reference,hregister);
+ href:=left.location.reference;
+ inc(href.offset,4);
+ cg.a_op_ref_reg(current_asmdata.CurrAsmList,OP_OR,OS_32,href,hregister);
+ end
+ else
+{$endif not cpu64bitalu}
+ begin
+ location_force_reg(current_asmdata.CurrAsmList,left.location,left.location.size,true);
+ cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_OR,left.location.size,left.location.register,left.location.register);
+ end;
+ end;
+ LOC_FLAGS :
+ begin
+ resflags:=left.location.resflags;
+ end;
+ LOC_REGISTER,LOC_CREGISTER :
+ begin
+{$ifndef cpu64bitalu}
+ if left.location.size in [OS_64,OS_S64] then
+ begin
+ hregister:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
+ cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_32,OS_32,left.location.register64.reglo,hregister);
+ cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_OR,OS_32,left.location.register64.reghi,hregister);
+ end
+ else
+{$endif not cpu64bitalu}
+ cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_OR,left.location.size,left.location.register,left.location.register);
+ end;
+ LOC_JUMP :
+ begin
+ location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
+ location.register:=cg.getintregister(current_asmdata.CurrAsmList,location.size);
+ current_asmdata.getjumplabel(hlabel);
+ cg.a_label(current_asmdata.CurrAsmList,current_procinfo.CurrTrueLabel);
+ if not(is_cbool(resultdef)) then
+ cg.a_load_const_reg(current_asmdata.CurrAsmList,location.size,1,location.register)
+ else
+ cg.a_load_const_reg(current_asmdata.CurrAsmList,location.size,-1,location.register);
+ cg.a_jmp_always(current_asmdata.CurrAsmList,hlabel);
+ cg.a_label(current_asmdata.CurrAsmList,current_procinfo.CurrFalseLabel);
+ cg.a_load_const_reg(current_asmdata.CurrAsmList,location.size,0,location.register);
+ cg.a_label(current_asmdata.CurrAsmList,hlabel);
+ end;
+ else
+ internalerror(10062);
+ end;
+ if (left.location.loc<>LOC_JUMP) then
+ begin
+ { load flags to register }
+ location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
+{$ifndef cpu64bitalu}
+ if (location.size in [OS_64,OS_S64]) then
+ begin
+ hreg2:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
+ cg.g_flags2reg(current_asmdata.CurrAsmList,OS_32,resflags,hreg2);
+ if (is_cbool(resultdef)) then
+ cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_NEG,OS_32,hreg2,hreg2);
+ location.register64.reglo:=hreg2;
+ location.register64.reghi:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
+ if (is_cbool(resultdef)) then
+ { reglo is either 0 or -1 -> reghi has to become the same }
+ cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_32,OS_32,location.register64.reglo,location.register64.reghi)
+ else
+ { unsigned }
+ cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_32,0,location.register64.reghi);
+ end
+ else
+{$endif not cpu64bitalu}
+ begin
+ location.register:=cg.getintregister(current_asmdata.CurrAsmList,location.size);
+ cg.g_flags2reg(current_asmdata.CurrAsmList,location.size,resflags,location.register);
+ if (is_cbool(resultdef)) then
+ cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_NEG,location.size,location.register,location.register);
+ end
+ end;
+ current_procinfo.CurrTrueLabel:=oldTrueLabel;
+ current_procinfo.CurrFalseLabel:=oldFalseLabel;
+ end;
+
+
+ function tx86typeconvnode.first_int_to_real : tnode;
+
+ begin
+ first_int_to_real:=nil;
+ if (left.resultdef.size<4) then
+ begin
+ inserttypeconv(left,s32inttype);
+ firstpass(left)
+ end;
+
+ if use_vectorfpu(resultdef) and
+ (torddef(left.resultdef).ordtype = s32bit) then
+ expectloc:=LOC_MMREGISTER
+ else
+ expectloc:=LOC_FPUREGISTER;
+ end;
+
+
+ procedure tx86typeconvnode.second_int_to_real;
+
+ var
+ leftref,
+ href : treference;
+ l1,l2 : tasmlabel;
+ op: tasmop;
+ opsize: topsize;
+ signtested : boolean;
+ begin
+ if not(left.location.loc in [LOC_REGISTER,LOC_CREGISTER,LOC_REFERENCE,LOC_CREFERENCE]) then
+ location_force_reg(current_asmdata.CurrAsmList,left.location,left.location.size,false);
+ if use_vectorfpu(resultdef) and
+{$ifdef cpu64bitalu}
+ (torddef(left.resultdef).ordtype in [s32bit,s64bit]) then
+{$else cpu64bitalu}
+ (torddef(left.resultdef).ordtype=s32bit) then
+{$endif cpu64bitalu}
+ begin
+ location_reset(location,LOC_MMREGISTER,def_cgsize(resultdef));
+ location.register:=cg.getmmregister(current_asmdata.CurrAsmList,location.size);
+ case location.size of
+ OS_F32:
+ op:=A_CVTSI2SS;
+ OS_F64:
+ op:=A_CVTSI2SD;
+ else
+ internalerror(2007120902);
+ end;
+ { don't use left.location.size, because that one may be OS_32/OS_64
+ if the lower bound of the orddef >= 0
+ }
+ case torddef(left.resultdef).ordtype of
+ s32bit:
+ opsize:=S_L;
+ s64bit:
+ opsize:=S_Q;
+ else
+ internalerror(2007120903);
+ end;
+ case left.location.loc of
+ LOC_REFERENCE,
+ LOC_CREFERENCE:
+ begin
+ href:=left.location.reference;
+ tcgx86(cg).make_simple_ref(current_asmdata.CurrAsmList,href);
+ current_asmdata.CurrAsmList.concat(taicpu.op_ref_reg(op,opsize,href,location.register));
+ end;
+ LOC_REGISTER,
+ LOC_CREGISTER:
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op,opsize,left.location.register,location.register));
+ end;
+ end
+ else
+ begin
+ location_reset(location,LOC_FPUREGISTER,def_cgsize(resultdef));
+ if (left.location.loc=LOC_REGISTER) and (torddef(left.resultdef).ordtype=u64bit) then
+ begin
+ {$ifdef cpu64bitalu}
+ emit_const_reg(A_BT,S_Q,63,left.location.register);
+ {$else cpu64bitalu}
+ emit_const_reg(A_BT,S_L,31,left.location.register64.reghi);
+ {$endif cpu64bitalu}
+ signtested:=true;
+ end
+ else
+ signtested:=false;
+
+ { We need to load from a reference }
+ location_force_mem(current_asmdata.CurrAsmList,left.location);
+ { don't change left.location.reference, because if it's a temp we
+ need the original location at the end so we can free it }
+ leftref:=left.location.reference;
+ tcgx86(cg).make_simple_ref(current_asmdata.CurrAsmList,leftref);
+
+ { For u32bit we need to load it as comp and need to
+ make it 64bits }
+ if (torddef(left.resultdef).ordtype=u32bit) then
+ begin
+ tg.GetTemp(current_asmdata.CurrAsmList,8,8,tt_normal,href);
+ location_freetemp(current_asmdata.CurrAsmList,left.location);
+ cg.a_load_ref_ref(current_asmdata.CurrAsmList,left.location.size,OS_32,leftref,href);
+ inc(href.offset,4);
+ cg.a_load_const_ref(current_asmdata.CurrAsmList,OS_32,0,href);
+ dec(href.offset,4);
+ { could be a temp with an offset > 32 bit on x86_64 }
+ tcgx86(cg).make_simple_ref(current_asmdata.CurrAsmList,href);
+ leftref:=href;
+ end;
+
+ { Load from reference to fpu reg }
+ case torddef(left.resultdef).ordtype of
+ u32bit,
+ scurrency,
+ s64bit:
+ begin
+ current_asmdata.CurrAsmList.concat(taicpu.op_ref(A_FILD,S_IQ,leftref));
+ end;
+ u64bit:
+ begin
+ { unsigned 64 bit ints are harder to handle:
+ we load bits 0..62 and then check bit 63:
+ if it is 1 then we add $80000000 000000000
+ as double }
+ current_asmdata.getdatalabel(l1);
+ current_asmdata.getjumplabel(l2);
+
+ if not(signtested) then
+ begin
+ inc(leftref.offset,4);
+ emit_const_ref(A_BT,S_L,31,leftref);
+ dec(leftref.offset,4);
+ end;
+
+ current_asmdata.CurrAsmList.concat(taicpu.op_ref(A_FILD,S_IQ,leftref));
+ cg.a_jmp_flags(current_asmdata.CurrAsmList,F_NC,l2);
+ new_section(current_asmdata.asmlists[al_typedconsts],sec_rodata_norel,l1.name,const_align(sizeof(pint)));
+ current_asmdata.asmlists[al_typedconsts].concat(Tai_label.Create(l1));
+ { I got this constant from a test program (FK) }
+ current_asmdata.asmlists[al_typedconsts].concat(Tai_const.Create_32bit(0));
+ current_asmdata.asmlists[al_typedconsts].concat(Tai_const.Create_32bit(longint ($80000000)));
+ current_asmdata.asmlists[al_typedconsts].concat(Tai_const.Create_32bit($0000403f));
+ reference_reset_symbol(href,l1,0,4);
+ tcgx86(cg).make_simple_ref(current_asmdata.CurrAsmList,href);
+ current_asmdata.CurrAsmList.concat(Taicpu.Op_ref(A_FLD,S_FX,href));
+ current_asmdata.CurrAsmList.concat(Taicpu.Op_reg_reg(A_FADDP,S_NO,NR_ST,NR_ST1));
+ cg.a_label(current_asmdata.CurrAsmList,l2);
+ end
+ else
+ begin
+ if left.resultdef.size<4 then
+ internalerror(2007120901);
+ current_asmdata.CurrAsmList.concat(taicpu.op_ref(A_FILD,S_IL,leftref));
+ end;
+ end;
+ tcgx86(cg).inc_fpu_stack;
+ location.register:=NR_ST;
+ end;
+ location_freetemp(current_asmdata.CurrAsmList,left.location);
+ end;
+
+begin
+ ctypeconvnode:=tx86typeconvnode
+end.
diff --git a/closures/compiler/x86/nx86con.pas b/closures/compiler/x86/nx86con.pas
new file mode 100644
index 0000000000..90c1fca2f2
--- /dev/null
+++ b/closures/compiler/x86/nx86con.pas
@@ -0,0 +1,90 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate i386 assembler for constants
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit nx86con;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,ncon,ncgcon;
+
+ type
+ tx86realconstnode = class(tcgrealconstnode)
+ function pass_1 : tnode;override;
+ procedure pass_generate_code;override;
+ end;
+
+implementation
+
+ uses
+ systems,globals,
+ symdef,
+ defutil,
+ cpubase,
+ cga,cgx86,cgobj,cgbase,cgutils;
+
+{*****************************************************************************
+ TI386REALCONSTNODE
+*****************************************************************************}
+
+ function tx86realconstnode.pass_1 : tnode;
+ begin
+ result:=nil;
+ if is_number_float(value_real) and not(use_vectorfpu(resultdef)) and (value_real=1.0) or (value_real=0.0) then
+ expectloc:=LOC_FPUREGISTER
+ else
+ expectloc:=LOC_CREFERENCE;
+ end;
+
+ procedure tx86realconstnode.pass_generate_code;
+
+ begin
+ if is_number_float(value_real) then
+ begin
+ if (value_real=1.0) and not(use_vectorfpu(resultdef)) then
+ begin
+ emit_none(A_FLD1,S_NO);
+ location_reset(location,LOC_FPUREGISTER,def_cgsize(resultdef));
+ location.register:=NR_ST;
+ tcgx86(cg).inc_fpu_stack;
+ end
+ else if (value_real=0.0) and not(use_vectorfpu(resultdef)) then
+ begin
+ emit_none(A_FLDZ,S_NO);
+ if (get_real_sign(value_real) < 0) then
+ emit_none(A_FCHS,S_NO);
+ location_reset(location,LOC_FPUREGISTER,def_cgsize(resultdef));
+ location.register:=NR_ST;
+ tcgx86(cg).inc_fpu_stack;
+ end
+ else
+ inherited pass_generate_code;
+ end
+ else
+ inherited pass_generate_code;
+ end;
+
+
+begin
+ crealconstnode:=tx86realconstnode;
+end.
diff --git a/closures/compiler/x86/nx86inl.pas b/closures/compiler/x86/nx86inl.pas
new file mode 100644
index 0000000000..0aa25780df
--- /dev/null
+++ b/closures/compiler/x86/nx86inl.pas
@@ -0,0 +1,534 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate x86 inline nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit nx86inl;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,ninl,ncginl;
+
+ type
+ tx86inlinenode = class(tcginlinenode)
+ { first pass override
+ so that the code generator will actually generate
+ these nodes.
+ }
+ function first_pi: tnode ; override;
+ function first_arctan_real: tnode; override;
+ function first_abs_real: tnode; override;
+ function first_sqr_real: tnode; override;
+ function first_sqrt_real: tnode; override;
+ function first_ln_real: tnode; override;
+ function first_cos_real: tnode; override;
+ function first_sin_real: tnode; override;
+ function first_round_real: tnode; override;
+ function first_trunc_real: tnode; override;
+ { second pass override to generate these nodes }
+ procedure second_IncludeExclude;override;
+ procedure second_pi; override;
+ procedure second_arctan_real; override;
+ procedure second_abs_real; override;
+ procedure second_round_real; override;
+ procedure second_sqr_real; override;
+ procedure second_sqrt_real; override;
+ procedure second_ln_real; override;
+ procedure second_cos_real; override;
+ procedure second_sin_real; override;
+ procedure second_trunc_real; override;
+
+ procedure second_prefetch;override;
+
+ procedure second_abs_long;override;
+ private
+ procedure load_fpu_location;
+ end;
+
+implementation
+
+ uses
+ systems,
+ globtype,globals,
+ cutils,verbose,
+ symconst,
+ defutil,
+ aasmbase,aasmtai,aasmdata,aasmcpu,
+ symdef,
+ cgbase,pass_2,
+ cpuinfo,cpubase,paramgr,
+ nbas,ncon,ncal,ncnv,nld,ncgutil,
+ tgobj,
+ cga,cgutils,cgx86,cgobj;
+
+
+{*****************************************************************************
+ TX86INLINENODE
+*****************************************************************************}
+
+ function tx86inlinenode.first_pi : tnode;
+ begin
+ expectloc:=LOC_FPUREGISTER;
+ first_pi := nil;
+ end;
+
+
+ function tx86inlinenode.first_arctan_real : tnode;
+ begin
+ expectloc:=LOC_FPUREGISTER;
+ first_arctan_real := nil;
+ end;
+
+ function tx86inlinenode.first_abs_real : tnode;
+ begin
+ if use_vectorfpu(resultdef) then
+ expectloc:=LOC_MMREGISTER
+ else
+ expectloc:=LOC_FPUREGISTER;
+ first_abs_real := nil;
+ end;
+
+ function tx86inlinenode.first_sqr_real : tnode;
+ begin
+ expectloc:=LOC_FPUREGISTER;
+ first_sqr_real := nil;
+ end;
+
+ function tx86inlinenode.first_sqrt_real : tnode;
+ begin
+ expectloc:=LOC_FPUREGISTER;
+ first_sqrt_real := nil;
+ end;
+
+ function tx86inlinenode.first_ln_real : tnode;
+ begin
+ expectloc:=LOC_FPUREGISTER;
+ first_ln_real := nil;
+ end;
+
+ function tx86inlinenode.first_cos_real : tnode;
+ begin
+ expectloc:=LOC_FPUREGISTER;
+ first_cos_real := nil;
+ end;
+
+ function tx86inlinenode.first_sin_real : tnode;
+ begin
+ expectloc:=LOC_FPUREGISTER;
+ first_sin_real := nil;
+ end;
+
+
+ function tx86inlinenode.first_round_real : tnode;
+ begin
+{$ifdef x86_64}
+ if use_vectorfpu(left.resultdef) then
+ expectloc:=LOC_REGISTER
+ else
+{$endif x86_64}
+ expectloc:=LOC_REFERENCE;
+ result:=nil;
+ end;
+
+
+ function tx86inlinenode.first_trunc_real: tnode;
+ begin
+ if (cs_opt_size in current_settings.optimizerswitches)
+{$ifdef x86_64}
+ and not(use_vectorfpu(left.resultdef))
+{$endif x86_64}
+ then
+ result:=inherited
+ else
+ begin
+{$ifdef x86_64}
+ if use_vectorfpu(left.resultdef) then
+ expectloc:=LOC_REGISTER
+ else
+{$endif x86_64}
+ expectloc:=LOC_REFERENCE;
+ result:=nil;
+ end;
+ end;
+
+
+ procedure tx86inlinenode.second_Pi;
+ begin
+ location_reset(location,LOC_FPUREGISTER,def_cgsize(resultdef));
+ emit_none(A_FLDPI,S_NO);
+ tcgx86(cg).inc_fpu_stack;
+ location.register:=NR_FPU_RESULT_REG;
+ end;
+
+ { load the FPU into the an fpu register }
+ procedure tx86inlinenode.load_fpu_location;
+ begin
+ location_reset(location,LOC_FPUREGISTER,def_cgsize(resultdef));
+ location.register:=NR_FPU_RESULT_REG;
+ secondpass(left);
+ case left.location.loc of
+ LOC_FPUREGISTER:
+ ;
+ LOC_CFPUREGISTER:
+ begin
+ cg.a_loadfpu_reg_reg(current_asmdata.CurrAsmList,left.location.size,
+ left.location.size,left.location.register,location.register);
+ end;
+ LOC_REFERENCE,LOC_CREFERENCE:
+ begin
+ cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,
+ left.location.size,left.location.size,
+ left.location.reference,location.register);
+ end;
+ LOC_MMREGISTER,LOC_CMMREGISTER:
+ begin
+ location:=left.location;
+ location_force_fpureg(current_asmdata.CurrAsmList,location,false);
+ end;
+ else
+ internalerror(309991);
+ end;
+ end;
+
+
+ procedure tx86inlinenode.second_arctan_real;
+ begin
+ load_fpu_location;
+ emit_none(A_FLD1,S_NO);
+ emit_none(A_FPATAN,S_NO);
+ end;
+
+
+ procedure tx86inlinenode.second_abs_real;
+ var
+ href : treference;
+ begin
+ if use_vectorfpu(resultdef) then
+ begin
+ secondpass(left);
+ location_force_mmregscalar(current_asmdata.CurrAsmList,left.location,false);
+ location:=left.location;
+ case tfloatdef(resultdef).floattype of
+ s32real:
+ reference_reset_symbol(href,current_asmdata.RefAsmSymbol('FPC_ABSMASK_SINGLE'),0,4);
+ s64real:
+ reference_reset_symbol(href,current_asmdata.RefAsmSymbol('FPC_ABSMASK_DOUBLE'),0,4);
+ else
+ internalerror(200506081);
+ end;
+ tcgx86(cg).make_simple_ref(current_asmdata.CurrAsmList, href);
+ current_asmdata.CurrAsmList.concat(taicpu.op_ref_reg(A_ANDPS,S_XMM,href,location.register))
+ end
+ else
+ begin
+ load_fpu_location;
+ emit_none(A_FABS,S_NO);
+ end;
+ end;
+
+
+ procedure tx86inlinenode.second_round_real;
+ begin
+{$ifdef x86_64}
+ if use_vectorfpu(left.resultdef) then
+ begin
+ secondpass(left);
+ location_force_mmregscalar(current_asmdata.CurrAsmList,left.location,false);
+ location_reset(location,LOC_REGISTER,OS_S64);
+ location.register:=cg.getintregister(current_asmdata.CurrAsmList,OS_S64);
+ case left.location.size of
+ OS_F32:
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CVTSS2SI,S_Q,left.location.register,location.register));
+ OS_F64:
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CVTSD2SI,S_Q,left.location.register,location.register));
+ else
+ internalerror(2007031402);
+ end;
+ end
+ else
+{$endif x86_64}
+ begin
+ load_fpu_location;
+ location_reset_ref(location,LOC_REFERENCE,OS_S64,0);
+ tg.GetTemp(current_asmdata.CurrAsmList,resultdef.size,resultdef.alignment,tt_normal,location.reference);
+ emit_ref(A_FISTP,S_IQ,location.reference);
+ emit_none(A_FWAIT,S_NO);
+ end;
+ end;
+
+
+ procedure tx86inlinenode.second_trunc_real;
+ var
+ oldcw,newcw : treference;
+ begin
+{$ifdef x86_64}
+ if use_vectorfpu(left.resultdef) and
+ not((left.location.loc=LOC_FPUREGISTER) and (current_settings.fputype>=fpu_sse3)) then
+ begin
+ secondpass(left);
+ location_force_mmregscalar(current_asmdata.CurrAsmList,left.location,false);
+ location_reset(location,LOC_REGISTER,OS_S64);
+ location.register:=cg.getintregister(current_asmdata.CurrAsmList,OS_S64);
+ case left.location.size of
+ OS_F32:
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CVTTSS2SI,S_Q,left.location.register,location.register));
+ OS_F64:
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CVTTSD2SI,S_Q,left.location.register,location.register));
+ else
+ internalerror(2007031401);
+ end;
+ end
+ else
+{$endif x86_64}
+ begin
+ if (current_settings.fputype>=fpu_sse3) then
+ begin
+ load_fpu_location;
+ location_reset_ref(location,LOC_REFERENCE,OS_S64,0);
+ tg.GetTemp(current_asmdata.CurrAsmList,resultdef.size,resultdef.alignment,tt_normal,location.reference);
+ emit_ref(A_FISTTP,S_IQ,location.reference);
+ end
+ else
+ begin
+ tg.GetTemp(current_asmdata.CurrAsmList,2,2,tt_normal,oldcw);
+ tg.GetTemp(current_asmdata.CurrAsmList,2,2,tt_normal,newcw);
+ emit_ref(A_FNSTCW,S_NO,newcw);
+ emit_ref(A_FNSTCW,S_NO,oldcw);
+ emit_const_ref(A_OR,S_W,$0f00,newcw);
+ load_fpu_location;
+ emit_ref(A_FLDCW,S_NO,newcw);
+ location_reset_ref(location,LOC_REFERENCE,OS_S64,0);
+ tg.GetTemp(current_asmdata.CurrAsmList,resultdef.size,resultdef.alignment,tt_normal,location.reference);
+ emit_ref(A_FISTP,S_IQ,location.reference);
+ emit_ref(A_FLDCW,S_NO,oldcw);
+ emit_none(A_FWAIT,S_NO);
+ tg.UnGetTemp(current_asmdata.CurrAsmList,oldcw);
+ tg.UnGetTemp(current_asmdata.CurrAsmList,newcw);
+ end;
+ end;
+ end;
+
+
+ procedure tx86inlinenode.second_sqr_real;
+
+ begin
+ if use_vectorfpu(resultdef) then
+ begin
+ secondpass(left);
+ location_force_mmregscalar(current_asmdata.CurrAsmList,left.location,false);
+ location:=left.location;
+ cg.a_opmm_loc_reg(current_asmdata.CurrAsmList,OP_MUL,left.location.size,left.location,left.location.register,mms_movescalar);
+ end
+ else
+ begin
+ load_fpu_location;
+ emit_reg_reg(A_FMUL,S_NO,NR_ST0,NR_ST0);
+ end;
+ end;
+
+
+ procedure tx86inlinenode.second_sqrt_real;
+ begin
+ if use_vectorfpu(resultdef) then
+ begin
+ secondpass(left);
+ location_force_mmregscalar(current_asmdata.CurrAsmList,left.location,false);
+ location:=left.location;
+ case tfloatdef(resultdef).floattype of
+ s32real:
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_SQRTSS,S_XMM,location.register,location.register));
+ s64real:
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_SQRTSD,S_XMM,location.register,location.register));
+ else
+ internalerror(200510031);
+ end;
+ end
+ else
+ begin
+ load_fpu_location;
+ emit_none(A_FSQRT,S_NO);
+ end;
+ end;
+
+ procedure tx86inlinenode.second_ln_real;
+ begin
+ load_fpu_location;
+ emit_none(A_FLDLN2,S_NO);
+ emit_none(A_FXCH,S_NO);
+ emit_none(A_FYL2X,S_NO);
+ end;
+
+ procedure tx86inlinenode.second_cos_real;
+ begin
+ load_fpu_location;
+ emit_none(A_FCOS,S_NO);
+ end;
+
+ procedure tx86inlinenode.second_sin_real;
+ begin
+ load_fpu_location;
+ emit_none(A_FSIN,S_NO)
+ end;
+
+ procedure tx86inlinenode.second_prefetch;
+ var
+ ref : treference;
+ r : tregister;
+ begin
+{$ifdef i386}
+ if current_settings.cputype>=cpu_Pentium3 then
+{$endif i386}
+ begin
+ secondpass(left);
+ case left.location.loc of
+ LOC_CREFERENCE,
+ LOC_REFERENCE:
+ begin
+ r:=cg.getintregister(current_asmdata.CurrAsmList,OS_ADDR);
+ cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,left.location.reference,r);
+ reference_reset_base(ref,r,0,left.location.reference.alignment);
+ current_asmdata.CurrAsmList.concat(taicpu.op_ref(A_PREFETCHNTA,S_NO,ref));
+ end;
+ else
+ internalerror(200402021);
+ end;
+ end;
+ end;
+
+
+ procedure tx86inlinenode.second_abs_long;
+ var
+ hregister : tregister;
+ opsize : tcgsize;
+ hp : taicpu;
+ begin
+{$ifdef i386}
+ if current_settings.cputype<cpu_Pentium2 then
+ begin
+ opsize:=def_cgsize(left.resultdef);
+ secondpass(left);
+ location_force_reg(current_asmdata.CurrAsmList,left.location,opsize,false);
+ location:=left.location;
+ location.register:=cg.getintregister(current_asmdata.CurrAsmList,opsize);
+ emit_reg_reg(A_MOV,S_L,left.location.register,location.register);
+ emit_const_reg(A_SAR,tcgsize2opsize[opsize],31,left.location.register);
+ emit_reg_reg(A_XOR,S_L,left.location.register,location.register);
+ emit_reg_reg(A_SUB,S_L,left.location.register,location.register);
+ end
+ else
+{$endif i386}
+ begin
+ opsize:=def_cgsize(left.resultdef);
+ secondpass(left);
+ location_force_reg(current_asmdata.CurrAsmList,left.location,opsize,true);
+ hregister:=cg.getintregister(current_asmdata.CurrAsmList,opsize);
+ location:=left.location;
+ location.register:=cg.getintregister(current_asmdata.CurrAsmList,opsize);
+ cg.a_load_reg_reg(current_asmdata.CurrAsmList,opsize,opsize,left.location.register,hregister);
+ cg.a_load_reg_reg(current_asmdata.CurrAsmList,opsize,opsize,left.location.register,location.register);
+ emit_reg(A_NEG,tcgsize2opsize[opsize],hregister);
+ hp:=taicpu.op_reg_reg(A_CMOVcc,tcgsize2opsize[opsize],hregister,location.register);
+ hp.condition:=C_NS;
+ current_asmdata.CurrAsmList.concat(hp);
+ end;
+ end;
+
+{*****************************************************************************
+ INCLUDE/EXCLUDE GENERIC HANDLING
+*****************************************************************************}
+
+ procedure tx86inlinenode.second_IncludeExclude;
+ var
+ hregister,
+ hregister2: tregister;
+ setbase : aint;
+ bitsperop,l : longint;
+ cgop : topcg;
+ asmop : tasmop;
+ opsize,
+ orgsize: tcgsize;
+ begin
+ if is_smallset(tcallparanode(left).resultdef) then
+ opsize:=int_cgsize(tcallparanode(left).resultdef.size)
+ else
+ opsize:=OS_32;
+ bitsperop:=(8*tcgsize2size[opsize]);
+ secondpass(tcallparanode(left).left);
+ secondpass(tcallparanode(tcallparanode(left).right).left);
+ setbase:=tsetdef(tcallparanode(left).left.resultdef).setbase;
+ if tcallparanode(tcallparanode(left).right).left.location.loc=LOC_CONSTANT then
+ begin
+ { calculate bit position }
+ l:=1 shl ((tcallparanode(tcallparanode(left).right).left.location.value-setbase) mod bitsperop);
+
+ { determine operator }
+ if inlinenumber=in_include_x_y then
+ cgop:=OP_OR
+ else
+ begin
+ cgop:=OP_AND;
+ l:=not(l);
+ end;
+ case tcallparanode(left).left.location.loc of
+ LOC_REFERENCE :
+ begin
+ inc(tcallparanode(left).left.location.reference.offset,
+ ((tcallparanode(tcallparanode(left).right).left.location.value-setbase) div bitsperop)*tcgsize2size[opsize]);
+ cg.a_op_const_ref(current_asmdata.CurrAsmList,cgop,opsize,l,tcallparanode(left).left.location.reference);
+ end;
+ LOC_CREGISTER :
+ cg.a_op_const_reg(current_asmdata.CurrAsmList,cgop,tcallparanode(left).left.location.size,l,tcallparanode(left).left.location.register);
+ else
+ internalerror(200405022);
+ end;
+ end
+ else
+ begin
+ orgsize:=opsize;
+ if opsize in [OS_8,OS_S8] then
+ begin
+ opsize:=OS_32;
+ end;
+ { determine asm operator }
+ if inlinenumber=in_include_x_y then
+ asmop:=A_BTS
+ else
+ asmop:=A_BTR;
+
+ location_force_reg(current_asmdata.CurrAsmList,tcallparanode(tcallparanode(left).right).left.location,opsize,true);
+ register_maybe_adjust_setbase(current_asmdata.CurrAsmList,tcallparanode(tcallparanode(left).right).left.location,setbase);
+ hregister:=tcallparanode(tcallparanode(left).right).left.location.register;
+ if (tcallparanode(left).left.location.loc=LOC_REFERENCE) then
+ emit_reg_ref(asmop,tcgsize2opsize[opsize],hregister,tcallparanode(left).left.location.reference)
+ else
+ begin
+ { second argument can't be an 8 bit register either }
+ hregister2:=tcallparanode(left).left.location.register;
+ if (orgsize in [OS_8,OS_S8]) then
+ hregister2:=cg.makeregsize(current_asmdata.CurrAsmList,hregister2,opsize);
+ emit_reg_reg(asmop,tcgsize2opsize[opsize],hregister,hregister2);
+ end;
+ end;
+ end;
+
+
+end.
diff --git a/closures/compiler/x86/nx86mat.pas b/closures/compiler/x86/nx86mat.pas
new file mode 100644
index 0000000000..37999b611f
--- /dev/null
+++ b/closures/compiler/x86/nx86mat.pas
@@ -0,0 +1,309 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate x86 code for math nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit nx86mat;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,nmat,ncgmat;
+
+ type
+ tx86unaryminusnode = class(tcgunaryminusnode)
+{$ifdef SUPPORT_MMX}
+ procedure second_mmx;override;
+{$endif SUPPORT_MMX}
+ procedure second_float;override;
+ function pass_1:tnode;override;
+ end;
+
+ tx86notnode = class(tcgnotnode)
+ procedure second_boolean;override;
+{$ifdef SUPPORT_MMX}
+ procedure second_mmx;override;
+{$endif SUPPORT_MMX}
+ end;
+
+ implementation
+
+ uses
+ globtype,
+ systems,
+ cutils,verbose,globals,
+ symconst,symdef,
+ aasmbase,aasmtai,aasmdata,defutil,
+ cgbase,pass_1,pass_2,
+ ncon,
+ cpubase,procinfo,
+ cga,ncgutil,cgobj,cgx86,cgutils;
+
+
+{*****************************************************************************
+ TI386UNARYMINUSNODE
+*****************************************************************************}
+
+ function tx86unaryminusnode.pass_1 : tnode;
+ begin
+ result:=nil;
+ firstpass(left);
+ if codegenerror then
+ exit;
+
+ if (left.resultdef.typ=floatdef) then
+ begin
+ if use_vectorfpu(left.resultdef) then
+ expectloc:=LOC_MMREGISTER
+ else
+ expectloc:=LOC_FPUREGISTER;
+ end
+{$ifdef SUPPORT_MMX}
+ else
+ if (cs_mmx in current_settings.localswitches) and
+ is_mmx_able_array(left.resultdef) then
+ begin
+ expectloc:=LOC_MMXREGISTER;
+ end
+{$endif SUPPORT_MMX}
+ else
+ inherited pass_1;
+ end;
+
+
+{$ifdef SUPPORT_MMX}
+ procedure tx86unaryminusnode.second_mmx;
+ var
+ op : tasmop;
+ hreg : tregister;
+ begin
+ secondpass(left);
+ location_reset(location,LOC_MMXREGISTER,OS_NO);
+ hreg:=tcgx86(cg).getmmxregister(current_asmdata.CurrAsmList);
+ emit_reg_reg(A_PXOR,S_NO,hreg,hreg);
+ case left.location.loc of
+ LOC_MMXREGISTER:
+ begin
+ location.register:=left.location.register;
+ end;
+ LOC_CMMXREGISTER:
+ begin
+ location.register:=tcgx86(cg).getmmxregister(current_asmdata.CurrAsmList);
+ emit_reg_reg(A_MOVQ,S_NO,left.location.register,location.register);
+ end;
+ LOC_REFERENCE,
+ LOC_CREFERENCE:
+ begin
+ location.register:=tcgx86(cg).getmmxregister(current_asmdata.CurrAsmList);
+ emit_ref_reg(A_MOVQ,S_NO,left.location.reference,location.register);
+ end;
+ else
+ internalerror(200203225);
+ end;
+ if cs_mmx_saturation in current_settings.localswitches then
+ case mmx_type(resultdef) of
+ mmxs8bit:
+ op:=A_PSUBSB;
+ mmxu8bit:
+ op:=A_PSUBUSB;
+ mmxs16bit,mmxfixed16:
+ op:=A_PSUBSW;
+ mmxu16bit:
+ op:=A_PSUBUSW;
+ end
+ else
+ case mmx_type(resultdef) of
+ mmxs8bit,mmxu8bit:
+ op:=A_PSUBB;
+ mmxs16bit,mmxu16bit,mmxfixed16:
+ op:=A_PSUBW;
+ mmxs32bit,mmxu32bit:
+ op:=A_PSUBD;
+ end;
+ emit_reg_reg(op,S_NO,location.register,hreg);
+ emit_reg_reg(A_MOVQ,S_NO,hreg,location.register);
+ end;
+{$endif SUPPORT_MMX}
+
+
+ procedure tx86unaryminusnode.second_float;
+ var
+ reg : tregister;
+ href : treference;
+ l1 : tasmlabel;
+ begin
+ secondpass(left);
+
+ if expectloc=LOC_MMREGISTER then
+ begin
+ location_force_mmregscalar(current_asmdata.CurrAsmList,left.location,false);
+ location_reset(location,LOC_MMREGISTER,def_cgsize(resultdef));
+
+ { make life of register allocator easier }
+ location.register:=cg.getmmregister(current_asmdata.CurrAsmList,def_cgsize(resultdef));
+ cg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,def_cgsize(resultdef),def_cgsize(resultdef),left.location.register,location.register,mms_movescalar);
+
+ reg:=cg.getmmregister(current_asmdata.CurrAsmList,def_cgsize(resultdef));
+
+ current_asmdata.getdatalabel(l1);
+ new_section(current_asmdata.asmlists[al_typedconsts],sec_rodata_norel,l1.name,const_align(sizeof(pint)));
+ current_asmdata.asmlists[al_typedconsts].concat(Tai_label.Create(l1));
+ case def_cgsize(resultdef) of
+ OS_F32:
+ current_asmdata.asmlists[al_typedconsts].concat(tai_const.create_32bit(longint(1 shl 31)));
+ OS_F64:
+ begin
+ current_asmdata.asmlists[al_typedconsts].concat(tai_const.create_32bit(0));
+ current_asmdata.asmlists[al_typedconsts].concat(tai_const.create_32bit(-(1 shl 31)));
+ end
+ else
+ internalerror(2004110215);
+ end;
+
+ reference_reset_symbol(href,l1,0,resultdef.alignment);
+ cg.a_loadmm_ref_reg(current_asmdata.CurrAsmList,def_cgsize(resultdef),def_cgsize(resultdef),href,reg,mms_movescalar);
+
+ cg.a_opmm_reg_reg(current_asmdata.CurrAsmList,OP_XOR,left.location.size,reg,location.register,nil);
+ end
+ else
+ begin
+ location_reset(location,LOC_FPUREGISTER,def_cgsize(resultdef));
+ case left.location.loc of
+ LOC_REFERENCE,
+ LOC_CREFERENCE:
+ begin
+ location.register:=NR_ST;
+ cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,
+ left.location.size,location.size,
+ left.location.reference,location.register);
+ emit_none(A_FCHS,S_NO);
+ end;
+ LOC_FPUREGISTER,
+ LOC_CFPUREGISTER:
+ begin
+ { "load st,st" is ignored by the code generator }
+ cg.a_loadfpu_reg_reg(current_asmdata.CurrAsmList,left.location.size,location.size,left.location.register,NR_ST);
+ location.register:=NR_ST;
+ emit_none(A_FCHS,S_NO);
+ end;
+ else
+ internalerror(200312241);
+ end;
+ end;
+ end;
+
+
+{*****************************************************************************
+ TX86NOTNODE
+*****************************************************************************}
+
+ procedure tx86notnode.second_boolean;
+ var
+ hl : tasmlabel;
+ opsize : tcgsize;
+ begin
+ opsize:=def_cgsize(resultdef);
+
+ if left.expectloc=LOC_JUMP then
+ begin
+ location_reset(location,LOC_JUMP,OS_NO);
+ hl:=current_procinfo.CurrTrueLabel;
+ current_procinfo.CurrTrueLabel:=current_procinfo.CurrFalseLabel;
+ current_procinfo.CurrFalseLabel:=hl;
+ secondpass(left);
+ maketojumpbool(current_asmdata.CurrAsmList,left,lr_load_regvars);
+ hl:=current_procinfo.CurrTrueLabel;
+ current_procinfo.CurrTrueLabel:=current_procinfo.CurrFalseLabel;
+ current_procinfo.CurrFalseLabel:=hl;
+ end
+ else
+ begin
+ { the second pass could change the location of left }
+ { if it is a register variable, so we've to do }
+ { this before the case statement }
+ secondpass(left);
+ case left.expectloc of
+ LOC_FLAGS :
+ begin
+ location_reset(location,LOC_FLAGS,OS_NO);
+ location.resflags:=left.location.resflags;
+ inverse_flags(location.resflags);
+ end;
+ LOC_CONSTANT,
+ LOC_REGISTER,
+ LOC_CREGISTER,
+ LOC_REFERENCE,
+ LOC_CREFERENCE,
+ LOC_SUBSETREG,
+ LOC_CSUBSETREG,
+ LOC_SUBSETREF,
+ LOC_CSUBSETREF :
+ begin
+ location_force_reg(current_asmdata.CurrAsmList,left.location,opsize,true);
+ emit_reg_reg(A_TEST,TCGSize2Opsize[opsize],left.location.register,left.location.register);
+ location_reset(location,LOC_FLAGS,OS_NO);
+ location.resflags:=F_E;
+ end;
+ else
+ internalerror(200203224);
+ end;
+ end;
+ end;
+
+
+{$ifdef SUPPORT_MMX}
+ procedure tx86notnode.second_mmx;
+
+ var hreg,r:Tregister;
+
+ begin
+ secondpass(left);
+ location_reset(location,LOC_MMXREGISTER,OS_NO);
+ r:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+ emit_const_reg(A_MOV,S_L,longint($ffffffff),r);
+ { load operand }
+ case left.location.loc of
+ LOC_MMXREGISTER:
+ location_copy(location,left.location);
+ LOC_CMMXREGISTER:
+ begin
+ location.register:=tcgx86(cg).getmmxregister(current_asmdata.CurrAsmList);
+ emit_reg_reg(A_MOVQ,S_NO,left.location.register,location.register);
+ end;
+ LOC_REFERENCE,
+ LOC_CREFERENCE:
+ begin
+ location.register:=tcgx86(cg).getmmxregister(current_asmdata.CurrAsmList);
+ emit_ref_reg(A_MOVQ,S_NO,left.location.reference,location.register);
+ end;
+ end;
+ { load mask }
+ hreg:=tcgx86(cg).getmmxregister(current_asmdata.CurrAsmList);
+ emit_reg_reg(A_MOVD,S_NO,r,hreg);
+ { lower 32 bit }
+ emit_reg_reg(A_PXOR,S_NO,hreg,location.register);
+ { shift mask }
+ emit_const_reg(A_PSLLQ,S_B,32,hreg);
+ { higher 32 bit }
+ emit_reg_reg(A_PXOR,S_NO,hreg,location.register);
+ end;
+{$endif SUPPORT_MMX}
+end.
diff --git a/closures/compiler/x86/nx86mem.pas b/closures/compiler/x86/nx86mem.pas
new file mode 100644
index 0000000000..d29bbb62b0
--- /dev/null
+++ b/closures/compiler/x86/nx86mem.pas
@@ -0,0 +1,108 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate x86 assembler for in memory related nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit nx86mem;
+
+{$i fpcdefs.inc}
+
+interface
+ uses
+ globtype,
+ cgbase,cpuinfo,cpubase,
+ node,nmem,ncgmem;
+
+ type
+ tx86vecnode = class(tcgvecnode)
+ procedure update_reference_reg_mul(maybe_const_reg:tregister;l:aint);override;
+ end;
+
+implementation
+
+ uses
+ cutils,verbose,
+ aasmtai,aasmdata,
+ cgutils,cgobj;
+
+{*****************************************************************************
+ TX86VECNODE
+*****************************************************************************}
+
+ { this routine must, like any other routine, not change the contents }
+ { of base/index registers of references, as these may be regvars. }
+ { The register allocator can coalesce one LOC_REGISTER being moved }
+ { into another (as their live ranges won't overlap), but not a }
+ { LOC_CREGISTER moved into a LOC_(C)REGISTER most of the time (as }
+ { the live range of the LOC_CREGISTER will most likely overlap the }
+ { the live range of the target LOC_(C)REGISTER) }
+ { The passed register may be a LOC_CREGISTER as well. }
+ procedure tx86vecnode.update_reference_reg_mul(maybe_const_reg:tregister;l:aint);
+ var
+ l2 : integer;
+ hreg : tregister;
+ begin
+ { Optimized for x86 to use the index register and scalefactor }
+ if location.reference.index=NR_NO then
+ begin
+ { no preparations needed }
+ end
+ else if location.reference.base=NR_NO then
+ begin
+ if (location.reference.scalefactor > 1) then
+ hreg:=cg.getaddressregister(current_asmdata.CurrAsmList);
+ case location.reference.scalefactor of
+ 0,1 : hreg:=location.reference.index;
+ 2 : cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SHL,OS_ADDR,1,location.reference.index,hreg);
+ 4 : cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SHL,OS_ADDR,2,location.reference.index,hreg);
+ 8 : cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SHL,OS_ADDR,3,location.reference.index,hreg);
+ else
+ internalerror(2008091401);
+ end;
+ location.reference.base:=hreg;
+ end
+ else
+ begin
+ hreg:=cg.getaddressregister(current_asmdata.CurrAsmList);
+ cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,location.reference,hreg);
+ reference_reset_base(location.reference,hreg,0,location.reference.alignment);
+ end;
+ { insert the new index register and scalefactor or
+ do the multiplication manual }
+ case l of
+ 1,2,4,8 :
+ begin
+ location.reference.scalefactor:=l;
+ hreg:=maybe_const_reg;
+ end;
+ else
+ begin
+ hreg:=cg.getaddressregister(current_asmdata.CurrAsmList);
+ if ispowerof2(l,l2) then
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SHL,OS_ADDR,l2,maybe_const_reg,hreg)
+ else
+ cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_IMUL,OS_ADDR,l,maybe_const_reg,hreg);
+ end;
+ end;
+ location.reference.index:=hreg;
+ end;
+
+begin
+ cvecnode:=tx86vecnode;
+end.
diff --git a/closures/compiler/x86/nx86set.pas b/closures/compiler/x86/nx86set.pas
new file mode 100644
index 0000000000..9a8f5c3b2b
--- /dev/null
+++ b/closures/compiler/x86/nx86set.pas
@@ -0,0 +1,649 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate x86 assembler for in/case nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit nx86set;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ globtype,
+ node,nset,pass_1,ncgset;
+
+ type
+ tx86innode = class(tinnode)
+ procedure pass_generate_code;override;
+ function pass_1 : tnode;override;
+ end;
+
+ tx86casenode = class(tcgcasenode)
+ function has_jumptable : boolean;override;
+ procedure genjumptable(hp : pcaselabel;min_,max_ : aint);override;
+ procedure genlinearlist(hp : pcaselabel);override;
+ end;
+
+implementation
+
+ uses
+ systems,constexp,
+ verbose,globals,
+ symconst,symdef,defutil,
+ aasmbase,aasmtai,aasmdata,aasmcpu,
+ cgbase,pass_2,tgobj,
+ ncon,
+ cpubase,
+ cga,cgobj,cgutils,ncgutil,
+ cgx86,
+ procinfo;
+
+{*****************************************************************************
+ TX86CASENODE
+*****************************************************************************}
+
+ function tx86casenode.has_jumptable : boolean;
+ begin
+{$ifdef i386}
+ has_jumptable:=true;
+{$else}
+ has_jumptable:=false;
+{$endif}
+ end;
+
+
+ procedure tx86casenode.genjumptable(hp : pcaselabel;min_,max_ : aint);
+ var
+ table : tasmlabel;
+ last : TConstExprInt;
+ indexreg : tregister;
+ href : treference;
+ jtlist: tasmlist;
+ sectype: TAsmSectiontype;
+
+ procedure genitem(list:TAsmList;t : pcaselabel);
+ var
+ i : aint;
+ begin
+ if assigned(t^.less) then
+ genitem(list,t^.less);
+ { fill possible hole }
+ i:=last.svalue+1;
+ while i<=t^._low.svalue-1 do
+ begin
+ list.concat(Tai_const.Create_sym(elselabel));
+ inc(i);
+ end;
+ i:=t^._low.svalue;
+ while i<=t^._high.svalue do
+ begin
+ list.concat(Tai_const.Create_sym(blocklabel(t^.blockid)));
+ inc(i);
+ end;
+ last:=t^._high;
+ if assigned(t^.greater) then
+ genitem(list,t^.greater);
+ end;
+
+ begin
+ last:=min_;
+ if not(jumptable_no_range) then
+ begin
+ { a <= x <= b <-> unsigned(x-a) <= (b-a) }
+ cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_SUB,opsize,aint(min_),hregister);
+ { case expr greater than max_ => goto elselabel }
+ cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,opsize,OC_A,aint(max_)-aint(min_),hregister,elselabel);
+ min_:=0;
+ end;
+ current_asmdata.getdatalabel(table);
+ { make it a 32bit register }
+ indexreg:=cg.makeregsize(current_asmdata.CurrAsmList,hregister,OS_INT);
+ cg.a_load_reg_reg(current_asmdata.CurrAsmList,opsize,OS_INT,hregister,indexreg);
+ { create reference }
+ reference_reset_symbol(href,table,0,sizeof(pint));
+ href.offset:=(-aint(min_))*sizeof(aint);
+ href.index:=indexreg;
+ href.scalefactor:=sizeof(aint);
+ emit_ref(A_JMP,S_NO,href);
+ { generate jump table }
+ if (target_info.system in [system_i386_darwin,system_i386_iphonesim]) then
+ begin
+ jtlist:=current_asmdata.asmlists[al_const];
+ sectype:=sec_rodata;
+ end
+ else
+ begin
+ jtlist:=current_procinfo.aktlocaldata;
+ sectype:=sec_data;
+ end;
+ new_section(jtlist,sectype,current_procinfo.procdef.mangledname,sizeof(aint));
+ jtlist.concat(Tai_label.Create(table));
+ genitem(jtlist,hp);
+ end;
+
+ procedure tx86casenode.genlinearlist(hp : pcaselabel);
+ var
+ first : boolean;
+ lastrange : boolean;
+ last : TConstExprInt;
+ cond_lt,cond_le : tresflags;
+
+ procedure genitem(t : pcaselabel);
+ begin
+ if assigned(t^.less) then
+ genitem(t^.less);
+ { need we to test the first value }
+ if first and (t^._low>get_min_value(left.resultdef)) then
+ begin
+ cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,opsize,jmp_lt,aint(t^._low.svalue),hregister,elselabel);
+ end;
+ if t^._low=t^._high then
+ begin
+ if t^._low-last=0 then
+ cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList, opsize, OC_EQ,0,hregister,blocklabel(t^.blockid))
+ else
+ begin
+ cg.a_op_const_reg(current_asmdata.CurrAsmList, OP_SUB, opsize, aint(t^._low.svalue-last.svalue), hregister);
+ cg.a_jmp_flags(current_asmdata.CurrAsmList,F_E,blocklabel(t^.blockid));
+ end;
+ last:=t^._low;
+ lastrange:=false;
+ end
+ else
+ begin
+ { it begins with the smallest label, if the value }
+ { is even smaller then jump immediately to the }
+ { ELSE-label }
+ if first then
+ begin
+ { have we to ajust the first value ? }
+ if (t^._low>get_min_value(left.resultdef)) or (get_min_value(left.resultdef)<>0) then
+ cg.a_op_const_reg(current_asmdata.CurrAsmList, OP_SUB, opsize, aint(t^._low.svalue), hregister);
+ end
+ else
+ begin
+ { if there is no unused label between the last and the }
+ { present label then the lower limit can be checked }
+ { immediately. else check the range in between: }
+
+ cg.a_op_const_reg(current_asmdata.CurrAsmList, OP_SUB, opsize, aint(t^._low.svalue-last.svalue), hregister);
+ { no jump necessary here if the new range starts at }
+ { at the value following the previous one }
+ if ((t^._low-last) <> 1) or
+ (not lastrange) then
+ cg.a_jmp_flags(current_asmdata.CurrAsmList,cond_lt,elselabel);
+ end;
+ {we need to use A_SUB, because A_DEC does not set the correct flags, therefor
+ using a_op_const_reg(OP_SUB) is not possible }
+ emit_const_reg(A_SUB,TCGSize2OpSize[opsize],aint(t^._high.svalue-t^._low.svalue),hregister);
+ cg.a_jmp_flags(current_asmdata.CurrAsmList,cond_le,blocklabel(t^.blockid));
+ last:=t^._high;
+ lastrange:=true;
+ end;
+ first:=false;
+ if assigned(t^.greater) then
+ genitem(t^.greater);
+ end;
+
+ begin
+ if with_sign then
+ begin
+ cond_lt:=F_L;
+ cond_le:=F_LE;
+ end
+ else
+ begin
+ cond_lt:=F_B;
+ cond_le:=F_BE;
+ end;
+ { do we need to generate cmps? }
+ if (with_sign and (min_label<0)) then
+ genlinearcmplist(hp)
+ else
+ begin
+ last:=0;
+ lastrange:=false;
+ first:=true;
+ genitem(hp);
+ cg.a_jmp_always(current_asmdata.CurrAsmList,elselabel);
+ end;
+ end;
+
+{*****************************************************************************
+ TX86INNODE
+*****************************************************************************}
+
+ function tx86innode.pass_1 : tnode;
+ begin
+ result:=nil;
+ { this is the only difference from the generic version }
+ expectloc:=LOC_FLAGS;
+
+ firstpass(right);
+ firstpass(left);
+ if codegenerror then
+ exit;
+ end;
+
+ procedure tx86innode.pass_generate_code;
+ type
+ Tsetpart=record
+ range : boolean; {Part is a range.}
+ start,stop : byte; {Start/stop when range; Stop=element when an element.}
+ end;
+ var
+ hreg,hreg2,
+ pleftreg : tregister;
+ opsize : tcgsize;
+ orgopsize : tcgsize;
+ setparts : array[1..8] of Tsetpart;
+ setbase : aint;
+ adjustment : longint;
+ l,l2 : tasmlabel;
+ i,numparts : byte;
+ genjumps,
+ use_small,
+ ranges : boolean;
+{$ifdef CORRECT_SET_IN_FPC}
+ AM : tasmop;
+{$endif CORRECT_SET_IN_FPC}
+
+ function analizeset(Aset:pconstset;is_small:boolean):boolean;
+ var
+ compares,maxcompares:word;
+ i:byte;
+ begin
+ if tnormalset(Aset^)=[] then
+ {The expression...
+ if expr in []
+ ...is allways false. It should be optimized away in the
+ resultdef pass, and thus never occur here. Since we
+ do generate wrong code for it, do internalerror.}
+ internalerror(2002072301);
+ analizeset:=false;
+ ranges:=false;
+ numparts:=0;
+ compares:=0;
+ { Lots of comparisions take a lot of time, so do not allow
+ too much comparisions. 8 comparisions are, however, still
+ smalller than emitting the set }
+ if cs_opt_size in current_settings.optimizerswitches then
+ maxcompares:=8
+ else
+ maxcompares:=5;
+ { when smallset is possible allow only 3 compares the smallset
+ code is for littlesize also smaller when more compares are used }
+ if is_small then
+ maxcompares:=3;
+ for i:=0 to 255 do
+ if i in tnormalset(Aset^) then
+ begin
+ if (numparts=0) or (i<>setparts[numparts].stop+1) then
+ begin
+ {Set element is a separate element.}
+ inc(compares);
+ if compares>maxcompares then
+ exit;
+ inc(numparts);
+ setparts[numparts].range:=false;
+ setparts[numparts].stop:=i;
+ end
+ else
+ {Set element is part of a range.}
+ if not setparts[numparts].range then
+ begin
+ {Transform an element into a range.}
+ setparts[numparts].range:=true;
+ setparts[numparts].start:=setparts[numparts].stop;
+ setparts[numparts].stop:=i;
+ ranges := true;
+ end
+ else
+ begin
+ {Extend a range.}
+ setparts[numparts].stop:=i;
+ end;
+ end;
+ analizeset:=true;
+ end;
+
+ begin
+ { We check first if we can generate jumps, this can be done
+ because the resultdef is already set in firstpass }
+
+ { check if we can use smallset operation using btl which is limited
+ to 32 bits, the left side may also not contain higher values or be signed !! }
+ use_small:=is_smallset(right.resultdef) and
+ not is_signed(left.resultdef) and
+ ((left.resultdef.typ=orddef) and (torddef(left.resultdef).high.svalue<32) or
+ (left.resultdef.typ=enumdef) and (tenumdef(left.resultdef).max<32));
+
+ { Can we generate jumps? Possible for all types of sets }
+ genjumps:=(right.nodetype=setconstn) and
+ analizeset(tsetconstnode(right).value_set,use_small);
+ { calculate both operators }
+ { the complex one first }
+ { not in case of genjumps, because then we don't secondpass }
+ { right at all (so we have to make sure that "right" really is }
+ { "right" and not "swapped left" in that case) }
+ if not(genjumps) then
+ firstcomplex(self);
+ secondpass(left);
+ { Only process the right if we are not generating jumps }
+ if not genjumps then
+ begin
+ secondpass(right);
+ end;
+ if codegenerror then
+ exit;
+
+ { ofcourse not commutative }
+ if nf_swapped in flags then
+ swapleftright;
+
+ orgopsize := def_cgsize(left.resultdef);
+ opsize := OS_32;
+ if is_signed(left.resultdef) then
+ opsize := tcgsize(ord(opsize)+(ord(OS_S8)-ord(OS_8)));
+
+ if not(left.location.loc in [LOC_REGISTER,LOC_CREGISTER,LOC_REFERENCE,LOC_CREFERENCE,LOC_CONSTANT]) then
+ location_force_reg(current_asmdata.CurrAsmList,left.location,opsize,true);
+ if (right.location.loc in [LOC_SUBSETREG,LOC_CSUBSETREG]) then
+ location_force_reg(current_asmdata.CurrAsmList,right.location,opsize,true);
+
+ if genjumps then
+ begin
+ { It gives us advantage to check for the set elements
+ separately instead of using the SET_IN_BYTE procedure.
+ To do: Build in support for LOC_JUMP }
+
+ { load and zero or sign extend as necessary }
+ location_force_reg(current_asmdata.CurrAsmList,left.location,opsize,false);
+ pleftreg:=left.location.register;
+
+ { Get a label to jump to the end }
+ location_reset(location,LOC_FLAGS,OS_NO);
+
+ { It's better to use the zero flag when there are
+ no ranges }
+ if ranges then
+ location.resflags:=F_C
+ else
+ location.resflags:=F_E;
+
+ current_asmdata.getjumplabel(l);
+
+ { how much have we already substracted from the x in the }
+ { "x in [y..z]" expression }
+ adjustment := 0;
+
+ for i:=1 to numparts do
+ if setparts[i].range then
+ { use fact that a <= x <= b <=> cardinal(x-a) <= cardinal(b-a) }
+ begin
+ { is the range different from all legal values? }
+ if (setparts[i].stop-setparts[i].start <> 255) or not (orgopsize = OS_8) then
+ begin
+ { yes, is the lower bound <> 0? }
+ if (setparts[i].start <> 0) then
+ begin
+ location_force_reg(current_asmdata.CurrAsmList,left.location,opsize,false);
+ hreg:=left.location.register;
+ pleftreg:=hreg;
+ cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_SUB,opsize,setparts[i].start-adjustment,pleftreg);
+ end;
+
+ { new total value substracted from x: }
+ { adjustment + (setparts[i].start - adjustment) }
+ adjustment := setparts[i].start;
+
+ { check if result < b-a+1 (not "result <= b-a", since }
+ { we need a carry in case the element is in the range }
+ { (this will never overflow since we check at the }
+ { beginning whether stop-start <> 255) }
+ cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,opsize,OC_B,setparts[i].stop-setparts[i].start+1,pleftreg,l);
+ end
+ else
+ { if setparts[i].start = 0 and setparts[i].stop = 255, }
+ { it's always true since "in" is only allowed for bytes }
+ begin
+ current_asmdata.CurrAsmList.concat(taicpu.op_none(A_STC,S_NO));
+ cg.a_jmp_always(current_asmdata.CurrAsmList,l);
+ end;
+ end
+ else
+ begin
+ { Emit code to check if left is an element }
+ current_asmdata.CurrAsmList.concat(taicpu.op_const_reg(A_CMP,TCGSize2OpSize[opsize],setparts[i].stop-adjustment,
+ pleftreg));
+ { Result should be in carry flag when ranges are used }
+ if ranges then
+ current_asmdata.CurrAsmList.concat(taicpu.op_none(A_STC,S_NO));
+ { If found, jump to end }
+ cg.a_jmp_flags(current_asmdata.CurrAsmList,F_E,l);
+ end;
+ if ranges and
+ { if the last one was a range, the carry flag is already }
+ { set appropriately }
+ not(setparts[numparts].range) then
+ current_asmdata.CurrAsmList.concat(taicpu.op_none(A_CLC,S_NO));
+ { To compensate for not doing a second pass }
+ right.location.reference.symbol:=nil;
+ { Now place the end label }
+ cg.a_label(current_asmdata.CurrAsmList,l);
+ end
+ else
+ begin
+ location_reset(location,LOC_FLAGS,OS_NO);
+ setbase:=tsetdef(right.resultdef).setbase;
+
+ { We will now generated code to check the set itself, no jmps,
+ handle smallsets separate, because it allows faster checks }
+ if use_small then
+ begin
+ if left.location.loc=LOC_CONSTANT then
+ begin
+ location.resflags:=F_NE;
+ case right.location.loc of
+ LOC_REGISTER,
+ LOC_CREGISTER:
+ begin
+ emit_const_reg(A_TEST,TCGSize2OpSize[right.location.size],
+ 1 shl ((left.location.value-setbase) and 31),right.location.register);
+ end;
+ LOC_REFERENCE,
+ LOC_CREFERENCE :
+ begin
+ emit_const_ref(A_TEST,TCGSize2OpSize[right.location.size],1 shl ((left.location.value-setbase) and 31),
+ right.location.reference);
+ end;
+ else
+ internalerror(200203312);
+ end;
+ end
+ else
+ begin
+ location_force_reg(current_asmdata.CurrAsmList,left.location,OS_32,true);
+ register_maybe_adjust_setbase(current_asmdata.CurrAsmList,left.location,setbase);
+ if (tcgsize2size[right.location.size] < 4) or
+ (right.location.loc = LOC_CONSTANT) then
+ location_force_reg(current_asmdata.CurrAsmList,right.location,OS_32,true);
+ hreg:=left.location.register;
+
+ case right.location.loc of
+ LOC_REGISTER,
+ LOC_CREGISTER :
+ begin
+ emit_reg_reg(A_BT,S_L,hreg,right.location.register);
+ end;
+ LOC_CREFERENCE,
+ LOC_REFERENCE :
+ begin
+ emit_reg_ref(A_BT,S_L,hreg,right.location.reference);
+ end;
+ else
+ internalerror(2002032210);
+ end;
+ location.resflags:=F_C;
+ end;
+ end
+ else
+ begin
+ if right.location.loc=LOC_CONSTANT then
+ begin
+ location.resflags:=F_C;
+ current_asmdata.getjumplabel(l);
+ current_asmdata.getjumplabel(l2);
+
+ { load constants to a register }
+ if (left.location.loc=LOC_CONSTANT) or
+ (setbase<>0) then
+ begin
+ location_force_reg(current_asmdata.CurrAsmList,left.location,opsize,true);
+ register_maybe_adjust_setbase(current_asmdata.CurrAsmList,left.location,setbase);
+ end;
+
+ case left.location.loc of
+ LOC_REGISTER,
+ LOC_CREGISTER:
+ begin
+ hreg:=cg.makeregsize(current_asmdata.CurrAsmList,left.location.register,opsize);
+ cg.a_load_reg_reg(current_asmdata.CurrAsmList,left.location.size,opsize,left.location.register,hreg);
+ cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,opsize,OC_BE,31,hreg,l);
+ { reset carry flag }
+ current_asmdata.CurrAsmList.concat(taicpu.op_none(A_CLC,S_NO));
+ cg.a_jmp_always(current_asmdata.CurrAsmList,l2);
+ cg.a_label(current_asmdata.CurrAsmList,l);
+ { We have to load the value into a register because
+ btl does not accept values only refs or regs (PFV) }
+ hreg2:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
+ cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_32,right.location.value,hreg2);
+ emit_reg_reg(A_BT,S_L,hreg,hreg2);
+ end;
+ else
+ begin
+ emit_const_ref(A_CMP,TCGSize2OpSize[orgopsize],31,left.location.reference);
+ cg.a_jmp_flags(current_asmdata.CurrAsmList,F_BE,l);
+ { reset carry flag }
+ current_asmdata.CurrAsmList.concat(taicpu.op_none(A_CLC,S_NO));
+ cg.a_jmp_always(current_asmdata.CurrAsmList,l2);
+ cg.a_label(current_asmdata.CurrAsmList,l);
+ hreg:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
+ cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_32,OS_32,left.location.reference,hreg);
+ { We have to load the value into a register because
+ btl does not accept values only refs or regs (PFV) }
+ hreg2:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
+ cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_32,right.location.value,hreg2);
+ emit_reg_reg(A_BT,S_L,hreg,hreg2);
+ end;
+ end;
+ cg.a_label(current_asmdata.CurrAsmList,l2);
+ end { of right.location.loc=LOC_CONSTANT }
+ { do search in a normal set which could have >32 elementsm
+ but also used if the left side contains values > 32 or < 0 }
+ else if left.location.loc=LOC_CONSTANT then
+ begin
+ if (left.location.value<setbase) or (((left.location.value-setbase) shr 3) >= right.resultdef.size) then
+ {should be caught earlier }
+ internalerror(2007020201);
+
+ location.resflags:=F_NE;
+ case right.location.loc of
+ LOC_REFERENCE,LOC_CREFERENCE:
+ begin
+ inc(right.location.reference.offset,(left.location.value-setbase) shr 3);
+ emit_const_ref(A_TEST,S_B,1 shl (left.location.value and 7),right.location.reference);
+ end;
+ LOC_REGISTER,LOC_CREGISTER:
+ begin
+ emit_const_reg(A_TEST,TCGSize2OpSize[right.location.size],1 shl (left.location.value-setbase),right.location.register);
+ end;
+ else
+ internalerror(2007051901);
+ end;
+ end
+ else
+ begin
+ location_force_reg(current_asmdata.CurrAsmList,left.location,opsize,false);
+ register_maybe_adjust_setbase(current_asmdata.CurrAsmList,left.location,setbase);
+ if (right.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
+ location_force_reg(current_asmdata.CurrAsmList,right.location,opsize,true);
+ pleftreg:=left.location.register;
+
+ if (opsize >= OS_S8) or { = if signed }
+ ((left.resultdef.typ=orddef) and
+ ((torddef(left.resultdef).low < int64(tsetdef(right.resultdef).setbase)) or
+ (torddef(left.resultdef).high > int64(tsetdef(right.resultdef).setmax)))) or
+ ((left.resultdef.typ=enumdef) and
+ ((tenumdef(left.resultdef).min < aint(tsetdef(right.resultdef).setbase)) or
+ (tenumdef(left.resultdef).max > aint(tsetdef(right.resultdef).setmax)))) then
+ begin
+
+ { we have to check if the value is < 0 or > setmax }
+
+ current_asmdata.getjumplabel(l);
+ current_asmdata.getjumplabel(l2);
+
+ { BE will be false for negative values }
+ cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,opsize,OC_BE,tsetdef(right.resultdef).setmax-tsetdef(right.resultdef).setbase,pleftreg,l);
+ { reset carry flag }
+ current_asmdata.CurrAsmList.concat(taicpu.op_none(A_CLC,S_NO));
+ cg.a_jmp_always(current_asmdata.CurrAsmList,l2);
+
+ cg.a_label(current_asmdata.CurrAsmList,l);
+
+ pleftreg:=left.location.register;
+ case right.location.loc of
+ LOC_REGISTER, LOC_CREGISTER :
+ emit_reg_reg(A_BT,S_L,pleftreg,right.location.register);
+ LOC_CREFERENCE, LOC_REFERENCE :
+ emit_reg_ref(A_BT,S_L,pleftreg,right.location.reference);
+ else
+ internalerror(2007020301);
+ end;
+
+ cg.a_label(current_asmdata.CurrAsmList,l2);
+
+ location.resflags:=F_C;
+
+ end
+ else
+ begin
+ case right.location.loc of
+ LOC_REGISTER, LOC_CREGISTER :
+ emit_reg_reg(A_BT,S_L,pleftreg,right.location.register);
+ LOC_CREFERENCE, LOC_REFERENCE :
+ emit_reg_ref(A_BT,S_L,pleftreg,right.location.reference);
+ else
+ internalerror(2007020302);
+ end;
+ location.resflags:=F_C;
+ end;
+ end;
+ end;
+ end;
+ if not genjumps then
+ location_freetemp(current_asmdata.CurrAsmList,right.location);
+ end;
+
+begin
+ cinnode:=tx86innode;
+ ccasenode:=tx86casenode;
+end.
diff --git a/closures/compiler/x86/rax86.pas b/closures/compiler/x86/rax86.pas
new file mode 100644
index 0000000000..51afa60ac5
--- /dev/null
+++ b/closures/compiler/x86/rax86.pas
@@ -0,0 +1,782 @@
+{
+ Copyright (c) 1998-2002 by Carl Eric Codere and Peter Vreman
+
+ Handles the common x86 assembler reader routines
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+{
+ Contains the common x86 (i386 and x86-64) assembler reader routines.
+}
+unit rax86;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ aasmbase,aasmtai,aasmdata,aasmcpu,
+ cpubase,rautils,cclasses;
+
+{ Parser helpers }
+function is_prefix(t:tasmop):boolean;
+function is_override(t:tasmop):boolean;
+Function CheckPrefix(prefixop,op:tasmop): Boolean;
+Function CheckOverride(overrideop,op:tasmop): Boolean;
+Procedure FWaitWarning;
+
+type
+ Tx86Operand=class(TOperand)
+ opsize : topsize;
+ Procedure SetSize(_size:longint;force:boolean);override;
+ Procedure SetCorrectSize(opcode:tasmop);override;
+ Function CheckOperand: boolean; override;
+ end;
+
+ Tx86Instruction=class(TInstruction)
+ OpOrder : TOperandOrder;
+ opsize : topsize;
+ constructor Create(optype : tcoperand);override;
+ { Operand sizes }
+ procedure AddReferenceSizes;
+ procedure SetInstructionOpsize;
+ procedure CheckOperandSizes;
+ procedure CheckNonCommutativeOpcodes;
+ procedure SwapOperands;
+ { Additional actions required by specific reader }
+ procedure FixupOpcode;virtual;
+ { opcode adding }
+ function ConcatInstruction(p : TAsmList) : tai;override;
+ end;
+
+const
+ AsmPrefixes = 6;
+ AsmPrefix : array[0..AsmPrefixes-1] of TasmOP =(
+ A_LOCK,A_REP,A_REPE,A_REPNE,A_REPNZ,A_REPZ
+ );
+
+ AsmOverrides = 6;
+ AsmOverride : array[0..AsmOverrides-1] of TasmOP =(
+ A_SEGCS,A_SEGES,A_SEGDS,A_SEGFS,A_SEGGS,A_SEGSS
+ );
+
+ CondAsmOps=3;
+ CondAsmOp:array[0..CondAsmOps-1] of TasmOp=(
+ A_CMOVcc, A_Jcc, A_SETcc
+ );
+ CondAsmOpStr:array[0..CondAsmOps-1] of string[4]=(
+ 'CMOV','J','SET'
+ );
+
+implementation
+
+uses
+ globtype,globals,systems,verbose,
+ procinfo,
+ cpuinfo,cgbase,cgutils,
+ itcpugas,cgx86;
+
+
+{*****************************************************************************
+ Parser Helpers
+*****************************************************************************}
+
+function is_prefix(t:tasmop):boolean;
+var
+ i : longint;
+Begin
+ is_prefix:=false;
+ for i:=1 to AsmPrefixes do
+ if t=AsmPrefix[i-1] then
+ begin
+ is_prefix:=true;
+ exit;
+ end;
+end;
+
+
+function is_override(t:tasmop):boolean;
+var
+ i : longint;
+Begin
+ is_override:=false;
+ for i:=1 to AsmOverrides do
+ if t=AsmOverride[i-1] then
+ begin
+ is_override:=true;
+ exit;
+ end;
+end;
+
+
+Function CheckPrefix(prefixop,op:tasmop): Boolean;
+{ Checks if the prefix is valid with the following opcode }
+{ return false if not, otherwise true }
+Begin
+ CheckPrefix := TRUE;
+(* Case prefix of
+ A_REP,A_REPNE,A_REPE:
+ Case opcode Of
+ A_SCASB,A_SCASW,A_SCASD,
+ A_INS,A_OUTS,A_MOVS,A_CMPS,A_LODS,A_STOS:;
+ Else
+ Begin
+ CheckPrefix := FALSE;
+ exit;
+ end;
+ end; { case }
+ A_LOCK:
+ Case opcode Of
+ A_BT,A_BTS,A_BTR,A_BTC,A_XCHG,A_ADD,A_OR,A_ADC,A_SBB,A_AND,A_SUB,
+ A_XOR,A_NOT,A_NEG,A_INC,A_DEC:;
+ Else
+ Begin
+ CheckPrefix := FALSE;
+ Exit;
+ end;
+ end; { case }
+ A_NONE: exit; { no prefix here }
+ else
+ CheckPrefix := FALSE;
+ end; { end case } *)
+end;
+
+
+Function CheckOverride(overrideop,op:tasmop): Boolean;
+{ Check if the override is valid, and if so then }
+{ update the instr variable accordingly. }
+Begin
+ CheckOverride := true;
+{ Case instr.getinstruction of
+ A_MOVS,A_XLAT,A_CMPS:
+ Begin
+ CheckOverride := TRUE;
+ Message(assem_e_segment_override_not_supported);
+ end
+ end }
+end;
+
+
+Procedure FWaitWarning;
+begin
+ if (target_info.system=system_i386_GO32V2) and (cs_fp_emulation in current_settings.moduleswitches) then
+ Message(asmr_w_fwait_emu_prob);
+end;
+
+{*****************************************************************************
+ TX86Operand
+*****************************************************************************}
+
+Procedure Tx86Operand.SetSize(_size:longint;force:boolean);
+begin
+ inherited SetSize(_size,force);
+ { OS_64 will be set to S_L and be fixed later
+ in SetCorrectSize }
+ opsize:=TCGSize2Opsize[size];
+end;
+
+
+Procedure Tx86Operand.SetCorrectSize(opcode:tasmop);
+begin
+ if gas_needsuffix[opcode]=attsufFPU then
+ begin
+ case size of
+ OS_32 : opsize:=S_FS;
+ OS_64 : opsize:=S_FL;
+ end;
+ end
+ else if gas_needsuffix[opcode]=attsufFPUint then
+ begin
+ case size of
+ OS_16 : opsize:=S_IS;
+ OS_32 : opsize:=S_IL;
+ OS_64 : opsize:=S_IQ;
+ end;
+ end
+ else
+ begin
+ if size=OS_64 then
+ opsize:=S_Q;
+ end;
+end;
+
+Function Tx86Operand.CheckOperand: boolean;
+
+begin
+ result:=true;
+ if (opr.typ=OPR_Reference) then
+ begin
+ if not hasvar then
+ begin
+ if (getsupreg(opr.ref.base)=RS_EBP) and (opr.ref.offset>0) then
+ begin
+ if current_procinfo.procdef.proccalloption=pocall_register then
+ message(asmr_w_no_direct_ebp_for_parameter)
+ else
+ message(asmr_w_direct_ebp_for_parameter_regcall);
+ end
+ else if (getsupreg(opr.ref.base)=RS_EBP) and (opr.ref.offset<0) then
+ message(asmr_w_direct_ebp_neg_offset)
+ else if (getsupreg(opr.ref.base)=RS_ESP) and (opr.ref.offset<0) then
+ message(asmr_w_direct_esp_neg_offset);
+ end;
+ if (cs_create_pic in current_settings.moduleswitches) and
+ assigned(opr.ref.symbol) and
+ not assigned(opr.ref.relsymbol) and
+ not(opr.ref.refaddr in [addr_pic,addr_pic_no_got]) then
+ begin
+ if (opr.ref.symbol.name <> '_GLOBAL_OFFSET_TABLE_') then
+ begin
+ message(asmr_e_need_pic_ref);
+ result:=false;
+ end
+ else
+ opr.ref.refaddr:=addr_pic;
+ end;
+ end;
+end;
+
+
+{*****************************************************************************
+ T386Instruction
+*****************************************************************************}
+
+constructor Tx86Instruction.Create(optype : tcoperand);
+begin
+ inherited Create(optype);
+ Opsize:=S_NO;
+end;
+
+
+procedure Tx86Instruction.SwapOperands;
+begin
+ Inherited SwapOperands;
+ { mark the correct order }
+ if OpOrder=op_intel then
+ OpOrder:=op_att
+ else
+ OpOrder:=op_intel;
+end;
+
+
+procedure Tx86Instruction.AddReferenceSizes;
+{ this will add the sizes for references like [esi] which do not
+ have the size set yet, it will take only the size if the other
+ operand is a register }
+var
+ operand2,i : longint;
+ s : tasmsymbol;
+ so : aint;
+begin
+ for i:=1 to ops do
+ begin
+ operands[i].SetCorrectSize(opcode);
+ if tx86operand(operands[i]).opsize=S_NO then
+ begin
+{$ifdef x86_64}
+ if (opcode=A_MOVQ) and
+ (ops=2) and
+ (operands[1].opr.typ=OPR_CONSTANT) then
+ opsize:=S_Q
+ else
+{$endif x86_64}
+ case operands[i].Opr.Typ of
+ OPR_LOCAL,
+ OPR_REFERENCE :
+ begin
+ { for 3-operand opcodes, operand #1 (in ATT order) is always an immediate,
+ don't consider it. }
+ if i=ops then
+ operand2:=i-1
+ else
+ operand2:=i+1;
+ if operand2>0 then
+ begin
+ { Only allow register as operand to take the size from }
+ if operands[operand2].opr.typ=OPR_REGISTER then
+ begin
+ if ((opcode<>A_MOVD) and
+ (opcode<>A_CVTSI2SS)) then
+ tx86operand(operands[i]).opsize:=tx86operand(operands[operand2]).opsize;
+ end
+ else
+ begin
+ { if no register then take the opsize (which is available with ATT),
+ if not availble then give an error }
+ if opsize<>S_NO then
+ tx86operand(operands[i]).opsize:=opsize
+ else
+ begin
+ if (m_delphi in current_settings.modeswitches) then
+ Message(asmr_w_unable_to_determine_reference_size_using_dword)
+ else
+ Message(asmr_e_unable_to_determine_reference_size);
+ { recovery }
+ tx86operand(operands[i]).opsize:=S_L;
+ end;
+ end;
+ end
+ else
+ begin
+ if opsize<>S_NO then
+ tx86operand(operands[i]).opsize:=opsize
+ end;
+ end;
+ OPR_SYMBOL :
+ begin
+ { Fix lea which need a reference }
+ if opcode=A_LEA then
+ begin
+ s:=operands[i].opr.symbol;
+ so:=operands[i].opr.symofs;
+ operands[i].opr.typ:=OPR_REFERENCE;
+ Fillchar(operands[i].opr.ref,sizeof(treference),0);
+ operands[i].opr.ref.symbol:=s;
+ operands[i].opr.ref.offset:=so;
+ end;
+ {$ifdef x86_64}
+ tx86operand(operands[i]).opsize:=S_Q;
+ {$else x86_64}
+ tx86operand(operands[i]).opsize:=S_L;
+ {$endif x86_64}
+ end;
+ end;
+ end;
+ end;
+end;
+
+
+procedure Tx86Instruction.SetInstructionOpsize;
+begin
+ if opsize<>S_NO then
+ exit;
+ if (OpOrder=op_intel) then
+ SwapOperands;
+ case ops of
+ 0 : ;
+ 1 :
+ begin
+ { "push es" must be stored as a long PM }
+ if ((opcode=A_PUSH) or
+ (opcode=A_POP)) and
+ (operands[1].opr.typ=OPR_REGISTER) and
+ is_segment_reg(operands[1].opr.reg) then
+ opsize:=S_L
+ else
+ opsize:=tx86operand(operands[1]).opsize;
+ end;
+ 2 :
+ begin
+ case opcode of
+ A_MOVZX,A_MOVSX :
+ begin
+ if tx86operand(operands[1]).opsize=S_NO then
+ begin
+ tx86operand(operands[1]).opsize:=S_B;
+ if (m_delphi in current_settings.modeswitches) then
+ Message(asmr_w_unable_to_determine_reference_size_using_byte)
+ else
+ Message(asmr_e_unable_to_determine_reference_size);
+ end;
+ case tx86operand(operands[1]).opsize of
+ S_W :
+ case tx86operand(operands[2]).opsize of
+ S_L :
+ opsize:=S_WL;
+ end;
+ S_B :
+ begin
+ case tx86operand(operands[2]).opsize of
+ S_W :
+ opsize:=S_BW;
+ S_L :
+ opsize:=S_BL;
+ end;
+ end;
+ end;
+ end;
+ A_MOVD : { movd is a move from a mmx register to a
+ 32 bit register or memory, so no opsize is correct here PM }
+ exit;
+ A_MOVQ :
+ opsize:=S_IQ;
+ A_OUT :
+ opsize:=tx86operand(operands[1]).opsize;
+ else
+ opsize:=tx86operand(operands[2]).opsize;
+ end;
+ end;
+ 3 :
+ opsize:=tx86operand(operands[3]).opsize;
+ end;
+end;
+
+
+procedure Tx86Instruction.CheckOperandSizes;
+var
+ sizeerr : boolean;
+ i : longint;
+begin
+ { Check only the most common opcodes here, the others are done in
+ the assembler pass }
+ case opcode of
+ A_PUSH,A_POP,A_DEC,A_INC,A_NOT,A_NEG,
+ A_CMP,A_MOV,
+ A_ADD,A_SUB,A_ADC,A_SBB,
+ A_AND,A_OR,A_TEST,A_XOR: ;
+ else
+ exit;
+ end;
+ { Handle the BW,BL,WL separatly }
+ sizeerr:=false;
+ { special push/pop selector case }
+ if ((opcode=A_PUSH) or
+ (opcode=A_POP)) and
+ (operands[1].opr.typ=OPR_REGISTER) and
+ is_segment_reg(operands[1].opr.reg) then
+ exit;
+ if opsize in [S_BW,S_BL,S_WL] then
+ begin
+ if ops<>2 then
+ sizeerr:=true
+ else
+ begin
+ case opsize of
+ S_BW :
+ sizeerr:=(tx86operand(operands[1]).opsize<>S_B) or (tx86operand(operands[2]).opsize<>S_W);
+ S_BL :
+ sizeerr:=(tx86operand(operands[1]).opsize<>S_B) or (tx86operand(operands[2]).opsize<>S_L);
+ S_WL :
+ sizeerr:=(tx86operand(operands[1]).opsize<>S_W) or (tx86operand(operands[2]).opsize<>S_L);
+ end;
+ end;
+ end
+ else
+ begin
+ for i:=1 to ops do
+ begin
+ if (operands[i].opr.typ<>OPR_CONSTANT) and
+ (tx86operand(operands[i]).opsize in [S_B,S_W,S_L]) and
+ (tx86operand(operands[i]).opsize<>opsize) then
+ sizeerr:=true;
+ end;
+ end;
+ if sizeerr then
+ begin
+ { if range checks are on then generate an error }
+ if (cs_compilesystem in current_settings.moduleswitches) or
+ not (cs_check_range in current_settings.localswitches) then
+ Message(asmr_w_size_suffix_and_dest_dont_match)
+ else
+ Message(asmr_e_size_suffix_and_dest_dont_match);
+ end;
+end;
+
+
+{ This check must be done with the operand in ATT order
+ i.e.after swapping in the intel reader
+ but before swapping in the NASM and TASM writers PM }
+procedure Tx86Instruction.CheckNonCommutativeOpcodes;
+begin
+ if (OpOrder=op_intel) then
+ SwapOperands;
+ if (
+ (ops=2) and
+ (operands[1].opr.typ=OPR_REGISTER) and
+ (operands[2].opr.typ=OPR_REGISTER) and
+ { if the first is ST and the second is also a register
+ it is necessarily ST1 .. ST7 }
+ ((operands[1].opr.reg=NR_ST) or
+ (operands[1].opr.reg=NR_ST0))
+ ) or
+ (ops=0) then
+ if opcode=A_FSUBR then
+ opcode:=A_FSUB
+ else if opcode=A_FSUB then
+ opcode:=A_FSUBR
+ else if opcode=A_FDIVR then
+ opcode:=A_FDIV
+ else if opcode=A_FDIV then
+ opcode:=A_FDIVR
+ else if opcode=A_FSUBRP then
+ opcode:=A_FSUBP
+ else if opcode=A_FSUBP then
+ opcode:=A_FSUBRP
+ else if opcode=A_FDIVRP then
+ opcode:=A_FDIVP
+ else if opcode=A_FDIVP then
+ opcode:=A_FDIVRP;
+ if (
+ (ops=1) and
+ (operands[1].opr.typ=OPR_REGISTER) and
+ (getregtype(operands[1].opr.reg)=R_FPUREGISTER) and
+ (operands[1].opr.reg<>NR_ST) and
+ (operands[1].opr.reg<>NR_ST0)
+ ) then
+ if opcode=A_FSUBRP then
+ opcode:=A_FSUBP
+ else if opcode=A_FSUBP then
+ opcode:=A_FSUBRP
+ else if opcode=A_FDIVRP then
+ opcode:=A_FDIVP
+ else if opcode=A_FDIVP then
+ opcode:=A_FDIVRP;
+end;
+
+procedure Tx86Instruction.FixupOpcode;
+begin
+ { does nothing by default }
+end;
+
+{*****************************************************************************
+ opcode Adding
+*****************************************************************************}
+
+function Tx86Instruction.ConcatInstruction(p : TAsmList) : tai;
+var
+ siz : topsize;
+ i,asize : longint;
+ ai : taicpu;
+begin
+ if (OpOrder=op_intel) then
+ SwapOperands;
+
+ ai:=nil;
+ for i:=1 to Ops do
+ if not operands[i].CheckOperand then
+ exit;
+
+{ Get Opsize }
+ if (opsize<>S_NO) or (Ops=0) then
+ siz:=opsize
+ else
+ begin
+ if (Ops=2) and (operands[1].opr.typ=OPR_REGISTER) then
+ siz:=tx86operand(operands[1]).opsize
+ else
+ siz:=tx86operand(operands[Ops]).opsize;
+ { MOVD should be of size S_LQ or S_QL, but these do not exist PM }
+ if (ops=2) and
+ (tx86operand(operands[1]).opsize<>S_NO) and
+ (tx86operand(operands[2]).opsize<>S_NO) and
+ (tx86operand(operands[1]).opsize<>tx86operand(operands[2]).opsize) then
+ siz:=S_NO;
+ end;
+
+ if ((opcode=A_MOVD)or
+ (opcode=A_CVTSI2SS)) and
+ ((tx86operand(operands[1]).opsize=S_NO) or
+ (tx86operand(operands[2]).opsize=S_NO)) then
+ siz:=S_NO;
+ { NASM does not support FADD without args
+ as alias of FADDP
+ and GNU AS interprets FADD without operand differently
+ for version 2.9.1 and 2.9.5 !! }
+ if (ops=0) and
+ ((opcode=A_FADD) or
+ (opcode=A_FMUL) or
+ (opcode=A_FSUB) or
+ (opcode=A_FSUBR) or
+ (opcode=A_FDIV) or
+ (opcode=A_FDIVR)) then
+ begin
+ if opcode=A_FADD then
+ opcode:=A_FADDP
+ else if opcode=A_FMUL then
+ opcode:=A_FMULP
+ else if opcode=A_FSUB then
+ opcode:=A_FSUBP
+ else if opcode=A_FSUBR then
+ opcode:=A_FSUBRP
+ else if opcode=A_FDIV then
+ opcode:=A_FDIVP
+ else if opcode=A_FDIVR then
+ opcode:=A_FDIVRP;
+ message1(asmr_w_fadd_to_faddp,std_op2str[opcode]);
+ end;
+
+ {It is valid to specify some instructions without operand size.}
+ if siz=S_NO then
+ begin
+ if (ops=1) and (opcode=A_INT) then
+ siz:=S_B;
+ if (ops=1) and (opcode=A_RET) or (opcode=A_RETN) or (opcode=A_RETF) then
+ siz:=S_W;
+ if (ops=1) and (opcode=A_PUSH) then
+ begin
+ {We are a 32 compiler, assume 32-bit by default. This is Delphi
+ compatible but bad coding practise.}
+ siz:=S_L;
+ message(asmr_w_unable_to_determine_reference_size_using_dword);
+ end;
+ if (opcode=A_JMP) or (opcode=A_JCC) or (opcode=A_CALL) then
+ if ops=1 then
+ siz:=S_NEAR
+ else
+ siz:=S_FAR;
+ end;
+
+ { GNU AS interprets FDIV without operand differently
+ for version 2.9.1 and 2.10
+ we add explicit args to it !! }
+ if (ops=0) and
+ ((opcode=A_FSUBP) or
+ (opcode=A_FSUBRP) or
+ (opcode=A_FDIVP) or
+ (opcode=A_FDIVRP) or
+ (opcode=A_FSUB) or
+ (opcode=A_FSUBR) or
+ (opcode=A_FADD) or
+ (opcode=A_FADDP) or
+ (opcode=A_FDIV) or
+ (opcode=A_FDIVR)) then
+ begin
+ message1(asmr_w_adding_explicit_args_fXX,std_op2str[opcode]);
+ ops:=2;
+ operands[1].opr.typ:=OPR_REGISTER;
+ operands[2].opr.typ:=OPR_REGISTER;
+ operands[1].opr.reg:=NR_ST0;
+ operands[2].opr.reg:=NR_ST1;
+ end;
+ if (ops=1) and
+ (
+ (operands[1].opr.typ=OPR_REGISTER) and
+ (getregtype(operands[1].opr.reg)=R_FPUREGISTER) and
+ (operands[1].opr.reg<>NR_ST) and
+ (operands[1].opr.reg<>NR_ST0)
+ ) and
+ (
+ (opcode=A_FSUBP) or
+ (opcode=A_FSUBRP) or
+ (opcode=A_FDIVP) or
+ (opcode=A_FDIVRP) or
+ (opcode=A_FADDP) or
+ (opcode=A_FMULP)
+ ) then
+ begin
+ message1(asmr_w_adding_explicit_first_arg_fXX,std_op2str[opcode]);
+ ops:=2;
+ operands[2].opr.typ:=OPR_REGISTER;
+ operands[2].opr.reg:=operands[1].opr.reg;
+ operands[1].opr.reg:=NR_ST0;
+ end;
+
+ if (ops=1) and
+ (
+ (operands[1].opr.typ=OPR_REGISTER) and
+ (getregtype(operands[1].opr.reg)=R_FPUREGISTER) and
+ (operands[1].opr.reg<>NR_ST) and
+ (operands[1].opr.reg<>NR_ST0)
+ ) and
+ (
+ (opcode=A_FSUB) or
+ (opcode=A_FSUBR) or
+ (opcode=A_FDIV) or
+ (opcode=A_FDIVR) or
+ (opcode=A_FADD) or
+ (opcode=A_FMUL)
+ ) then
+ begin
+ message1(asmr_w_adding_explicit_second_arg_fXX,std_op2str[opcode]);
+ ops:=2;
+ operands[2].opr.typ:=OPR_REGISTER;
+ operands[2].opr.reg:=NR_ST0;
+ end;
+
+ { I tried to convince Linus Torvalds to add
+ code to support ENTER instruction
+ (when raising a stack page fault)
+ but he replied that ENTER is a bad instruction and
+ Linux does not need to support it
+ So I think its at least a good idea to add a warning
+ if someone uses this in assembler code
+ FPC itself does not use it at all PM }
+ if (opcode=A_ENTER) and
+ (target_info.system in [system_i386_linux,system_i386_FreeBSD]) then
+ Message(asmr_w_enter_not_supported_by_linux);
+
+ ai:=taicpu.op_none(opcode,siz);
+ ai.SetOperandOrder(OpOrder);
+ ai.Ops:=Ops;
+ ai.Allocate_oper(Ops);
+ for i:=1 to Ops do
+ case operands[i].opr.typ of
+ OPR_CONSTANT :
+ ai.loadconst(i-1,operands[i].opr.val);
+ OPR_REGISTER:
+ ai.loadreg(i-1,operands[i].opr.reg);
+ OPR_SYMBOL:
+ ai.loadsymbol(i-1,operands[i].opr.symbol,operands[i].opr.symofs);
+ OPR_LOCAL :
+ with operands[i].opr do
+ ai.loadlocal(i-1,localsym,localsymofs,localindexreg,
+ localscale,localgetoffset,localforceref);
+ OPR_REFERENCE:
+ begin
+ ai.loadref(i-1,operands[i].opr.ref);
+ if operands[i].size<>OS_NO then
+ begin
+ asize:=0;
+ case operands[i].size of
+ OS_8,OS_S8 :
+ asize:=OT_BITS8;
+ OS_16,OS_S16 :
+ asize:=OT_BITS16;
+ OS_32,OS_S32,OS_F32 :
+ asize:=OT_BITS32;
+ OS_64,OS_S64:
+ begin
+ { Only FPU operations know about 64bit values, for all
+ integer operations it is seen as 32bit
+
+ this applies only to i386, see tw16622}
+ if gas_needsuffix[opcode] in [attsufFPU,attsufFPUint] then
+ asize:=OT_BITS64
+{$ifdef i386}
+ else
+ asize:=OT_BITS32
+{$endif i386}
+ ;
+ end;
+ OS_F64,OS_C64 :
+ asize:=OT_BITS64;
+ OS_F80 :
+ asize:=OT_BITS80;
+ end;
+ if asize<>0 then
+ ai.oper[i-1]^.ot:=(ai.oper[i-1]^.ot and not OT_SIZE_MASK) or asize;
+ end;
+ end;
+ end;
+
+ { Condition ? }
+ if condition<>C_None then
+ ai.SetCondition(condition);
+
+ { Set is_jmp, it enables asmwriter to emit short jumps if appropriate }
+ if (opcode=A_JMP) or (opcode=A_JCC) then
+ ai.is_jmp := True;
+
+ { Concat the opcode or give an error }
+ if assigned(ai) then
+ p.concat(ai)
+ else
+ Message(asmr_e_invalid_opcode_and_operand);
+ result:=ai;
+end;
+
+end.
diff --git a/closures/compiler/x86/rax86att.pas b/closures/compiler/x86/rax86att.pas
new file mode 100644
index 0000000000..e03c69641d
--- /dev/null
+++ b/closures/compiler/x86/rax86att.pas
@@ -0,0 +1,920 @@
+{
+ Copyright (c) 1998-2002 by Carl Eric Codere and Peter Vreman
+
+ Does the parsing for the x86 GNU AS styled inline assembler.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+Unit rax86att;
+
+{$i fpcdefs.inc}
+
+Interface
+
+ uses
+ cpubase,
+ raatt,rax86;
+
+ type
+ tx86attreader = class(tattreader)
+ ActOpsize : topsize;
+ function is_asmopcode(const s: string):boolean;override;
+ procedure handleopcode;override;
+ procedure BuildReference(oper : tx86operand);
+ procedure BuildOperand(oper : tx86operand);
+ procedure BuildOpCode(instr : tx86instruction);
+ procedure handlepercent;override;
+ protected
+ procedure MaybeGetPICModifier(var oper: tx86operand);
+ end;
+
+ Tx86attInstruction = class(Tx86Instruction)
+ procedure FixupOpcode;override;
+ end;
+
+Implementation
+
+ uses
+ { helpers }
+ cutils,
+ { global }
+ globtype,verbose,
+ systems,
+ { aasm }
+ aasmbase,aasmtai,aasmdata,aasmcpu,
+ { symtable }
+ symconst,
+ { parser }
+ scanner,
+ procinfo,
+ itcpugas,
+ rabase,rautils,
+ cgbase
+ ;
+
+ { Tx86attInstruction }
+
+ procedure Tx86attInstruction.FixupOpcode;
+ begin
+ if (OpOrder=op_intel) then
+ SwapOperands;
+
+ case opcode of
+ A_MOVQ:
+ begin
+ { May be either real 'movq' or a generic 'mov' with 'q' suffix. Convert to mov
+ if source is a constant, or if neither operand is an mmx/xmm register }
+{$ifdef x86_64}
+ if (ops=2) and
+ (
+ (operands[1].opr.typ=OPR_CONSTANT) or not
+ (
+ ((operands[1].opr.typ=OPR_REGISTER) and
+ (getregtype(operands[1].opr.reg) in [R_MMXREGISTER,R_MMREGISTER])) or
+ ((operands[2].opr.typ=OPR_REGISTER) and
+ (getregtype(operands[2].opr.reg) in [R_MMXREGISTER,R_MMREGISTER]))
+ )
+ ) then
+ opcode:=A_MOV;
+{$endif x86_64}
+ end;
+ end;
+ end;
+
+ { Tx86attReader }
+
+ procedure tx86attreader.handlepercent;
+ var
+ len : longint;
+ begin
+ len:=1;
+ actasmpattern[len]:='%';
+ c:=current_scanner.asmgetchar;
+ { to be a register there must be a letter and not a number }
+ if c in ['0'..'9'] then
+ begin
+ actasmtoken:=AS_MOD;
+ end
+ else
+ begin
+ while c in ['a'..'z','A'..'Z','0'..'9'] do
+ Begin
+ inc(len);
+ actasmpattern[len]:=c;
+ c:=current_scanner.asmgetchar;
+ end;
+ actasmpattern[0]:=chr(len);
+ uppervar(actasmpattern);
+ if (actasmpattern = '%ST') and (c='(') then
+ Begin
+ actasmpattern:=actasmpattern+c;
+ c:=current_scanner.asmgetchar;
+ if c in ['0'..'9'] then
+ actasmpattern:=actasmpattern + c
+ else
+ Message(asmr_e_invalid_fpu_register);
+ c:=current_scanner.asmgetchar;
+ if c <> ')' then
+ Message(asmr_e_invalid_fpu_register)
+ else
+ Begin
+ actasmpattern:=actasmpattern + c;
+ c:=current_scanner.asmgetchar; { let us point to next character. }
+ end;
+ end;
+ if is_register(actasmpattern) then
+ exit;
+ Message(asmr_e_invalid_register);
+ actasmtoken:=raatt.AS_NONE;
+ end;
+ end;
+
+
+ Procedure tx86attreader.BuildReference(oper : tx86operand);
+
+ procedure Consume_RParen;
+ begin
+ if actasmtoken <> AS_RPAREN then
+ Begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(true);
+ end
+ else
+ begin
+ Consume(AS_RPAREN);
+ if not (actasmtoken in [AS_COMMA,AS_SEPARATOR,AS_END]) then
+ Begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(true);
+ end;
+ end;
+ end;
+
+
+ procedure Consume_Scale;
+ var
+ l : aint;
+ begin
+ { we have to process the scaling }
+ l:=BuildConstExpression(false,true);
+ if ((l = 2) or (l = 4) or (l = 8) or (l = 1)) then
+ oper.opr.ref.scalefactor:=l
+ else
+ Begin
+ Message(asmr_e_wrong_scale_factor);
+ oper.opr.ref.scalefactor:=0;
+ end;
+ end;
+
+
+ begin
+ oper.InitRef;
+ Consume(AS_LPAREN);
+ Case actasmtoken of
+ AS_INTNUM,
+ AS_MINUS,
+ AS_PLUS: { absolute offset, such as fs:(0x046c) }
+ Begin
+ { offset(offset) is invalid }
+ If oper.opr.Ref.Offset <> 0 Then
+ Begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(true);
+ End
+ Else
+ Begin
+ oper.opr.Ref.Offset:=BuildConstExpression(false,true);
+ Consume_RParen;
+ end;
+ exit;
+ End;
+ AS_REGISTER: { (reg ... }
+ Begin
+ { Check if there is already a base (mostly ebp,esp) than this is
+ not allowed, because it will give crashing code }
+ if ((oper.opr.typ=OPR_REFERENCE) and (oper.opr.ref.base<>NR_NO)) or
+ ((oper.opr.typ=OPR_LOCAL) and (oper.opr.localsym.localloc.loc<>LOC_REGISTER)) then
+ message(asmr_e_cannot_index_relative_var);
+ oper.opr.ref.base:=actasmregister;
+{$ifdef x86_64}
+ { non-GOT based RIP-relative accesses are also position-independent }
+ if (oper.opr.ref.base=NR_RIP) and
+ (oper.opr.ref.refaddr<>addr_pic) then
+ oper.opr.ref.refaddr:=addr_pic_no_got;
+{$endif x86_64}
+ Consume(AS_REGISTER);
+ { can either be a register or a right parenthesis }
+ { (reg) }
+ if actasmtoken=AS_RPAREN then
+ Begin
+ Consume_RParen;
+ exit;
+ end;
+ { (reg,reg .. }
+ Consume(AS_COMMA);
+ if actasmtoken=AS_REGISTER then
+ Begin
+ oper.opr.ref.index:=actasmregister;
+ Consume(AS_REGISTER);
+ { check for scaling ... }
+ case actasmtoken of
+ AS_RPAREN:
+ Begin
+ Consume_RParen;
+ exit;
+ end;
+ AS_COMMA:
+ Begin
+ Consume(AS_COMMA);
+ Consume_Scale;
+ Consume_RParen;
+ end;
+ else
+ Begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(false);
+ end;
+ end; { end case }
+ end
+ else
+ Begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(false);
+ end;
+ end; {end case }
+ AS_COMMA: { (, ... can either be scaling, or index }
+ Begin
+ Consume(AS_COMMA);
+ { Index }
+ if (actasmtoken=AS_REGISTER) then
+ Begin
+ oper.opr.ref.index:=actasmregister;
+ Consume(AS_REGISTER);
+ { check for scaling ... }
+ case actasmtoken of
+ AS_RPAREN:
+ Begin
+ Consume_RParen;
+ exit;
+ end;
+ AS_COMMA:
+ Begin
+ Consume(AS_COMMA);
+ Consume_Scale;
+ Consume_RParen;
+ end;
+ else
+ Begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(false);
+ end;
+ end; {end case }
+ end
+ { Scaling }
+ else
+ Begin
+ Consume_Scale;
+ Consume_RParen;
+ exit;
+ end;
+ end;
+ else
+ Begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(false);
+ end;
+ end;
+ end;
+
+
+ Procedure tx86attreader.MaybeGetPICModifier(var oper: tx86operand);
+ var
+ relsym: string;
+ asmsymtyp: tasmsymtype;
+ l: aint;
+ begin
+ case actasmtoken of
+ AS_AT:
+ begin
+ { darwin/i386 needs a relsym instead, and we can't }
+ { generate this automatically }
+ if (target_info.system in [system_i386_darwin,system_i386_iphonesim]) then
+ Message(asmr_e_invalid_reference_syntax);
+ consume(AS_AT);
+ if actasmtoken=AS_ID then
+ begin
+{$ifdef x86_64}
+ if (actasmpattern='GOTPCREL') or
+ (actasmpattern='PLT') then
+{$endif x86_64}
+{$ifdef i386}
+ if actasmpattern='GOT' then
+{$endif i386}
+ begin
+ oper.opr.ref.refaddr:=addr_pic;
+{$ifdef x86_64}
+ { local symbols don't have to
+ be accessed via the GOT
+ }
+ if (actasmpattern='GOTPCREL') and
+ assigned(oper.opr.ref.symbol) and
+ (oper.opr.ref.symbol.bind=AB_LOCAL) then
+ Message(asmr_w_useless_got_for_local);
+{$endif x86_64}
+ consume(AS_ID);
+ end
+ else
+ Message(asmr_e_invalid_reference_syntax);
+ end
+ else
+ Message(asmr_e_invalid_reference_syntax);
+ end;
+ AS_MINUS:
+ begin
+ { relsym? }
+ Consume(AS_MINUS);
+ BuildConstSymbolExpression(true,true,false,l,relsym,asmsymtyp);
+ if (relsym<>'') then
+ if not assigned(oper.opr.ref.relsymbol) then
+ oper.opr.ref.relsymbol:=current_asmdata.RefAsmSymbol(relsym)
+ else
+ Message(asmr_e_invalid_reference_syntax)
+ else
+ dec(oper.opr.ref.offset,l);
+ end;
+ end;
+ end;
+
+
+ Procedure tx86attreader.BuildOperand(oper : tx86operand);
+ var
+ tempstr,
+ expr : string;
+ typesize,l,k : aint;
+
+
+ procedure AddLabelOperand(hl:tasmlabel);
+ begin
+ if not(actasmtoken in [AS_PLUS,AS_MINUS,AS_LPAREN]) and
+ is_calljmp(actopcode) then
+ begin
+ oper.opr.typ:=OPR_SYMBOL;
+ oper.opr.symbol:=hl;
+ end
+ else
+ begin
+ oper.InitRef;
+ oper.opr.ref.symbol:=hl;
+ end;
+ end;
+
+
+ procedure MaybeRecordOffset;
+ var
+ mangledname: string;
+ hasdot : boolean;
+ l,
+ toffset,
+ tsize : aint;
+ begin
+ if not(actasmtoken in [AS_DOT,AS_PLUS,AS_MINUS]) then
+ exit;
+ l:=0;
+ hasdot:=(actasmtoken=AS_DOT);
+ if hasdot then
+ begin
+ if expr<>'' then
+ begin
+ BuildRecordOffsetSize(expr,toffset,tsize,mangledname,false);
+ if (oper.opr.typ<>OPR_CONSTANT) and
+ (mangledname<>'') then
+ Message(asmr_e_wrong_sym_type);
+ inc(l,toffset);
+ oper.SetSize(tsize,true);
+ end;
+ end;
+ if actasmtoken in [AS_PLUS,AS_MINUS] then
+ inc(l,BuildConstExpression(true,false));
+ case oper.opr.typ of
+ OPR_LOCAL :
+ begin
+ { don't allow direct access to fields of parameters, because that
+ will generate buggy code. Allow it only for explicit typecasting }
+ if hasdot and
+ (not oper.hastype) and
+ (oper.opr.localsym.owner.symtabletype=parasymtable) and
+ (current_procinfo.procdef.proccalloption<>pocall_register) then
+ Message(asmr_e_cannot_access_field_directly_for_parameters);
+ inc(oper.opr.localsymofs,l)
+ end;
+ OPR_CONSTANT :
+ if (mangledname<>'') then
+ begin
+ if (oper.opr.val<>0) then
+ Message(asmr_e_wrong_sym_type);
+ oper.opr.typ:=OPR_SYMBOL;
+ oper.opr.symbol:=current_asmdata.RefAsmSymbol(mangledname);
+ end
+ else
+ inc(oper.opr.val,l);
+ OPR_REFERENCE :
+ inc(oper.opr.ref.offset,l);
+ OPR_SYMBOL:
+ Message(asmr_e_invalid_symbol_ref);
+ else
+ internalerror(200309221);
+ end;
+ end;
+
+
+ function MaybeBuildReference:boolean;
+ { Try to create a reference, if not a reference is found then false
+ is returned }
+ var
+ mangledname: string;
+ begin
+ MaybeBuildReference:=true;
+ case actasmtoken of
+ AS_INTNUM:
+ Begin
+ { allow %segmentregister:number }
+ if oper.opr.ref.segment<>NR_NO then
+ begin
+ // already done before calling oper.InitRef;
+ if oper.opr.Ref.Offset <> 0 Then
+ Message(asmr_e_invalid_reference_syntax)
+ else
+ begin
+ oper.opr.Ref.Offset:=BuildConstExpression(true,false);
+ if actasmtoken=AS_LPAREN then
+ BuildReference(oper)
+ else if (oper.opr.ref.segment <> NR_FS) and
+ (oper.opr.ref.segment <> NR_GS) then
+ Message(asmr_w_general_segment_with_constant);
+ end;
+ end
+ else
+ begin
+ oper.opr.ref.offset:=BuildConstExpression(True,False);
+ BuildReference(oper);
+ end;
+ end;
+ AS_MINUS,
+ AS_PLUS:
+ Begin
+ oper.opr.ref.offset:=BuildConstExpression(True,False);
+ if actasmtoken<>AS_LPAREN then
+ Message(asmr_e_invalid_reference_syntax)
+ else
+ BuildReference(oper);
+ end;
+ AS_LPAREN:
+ BuildReference(oper);
+ AS_ID: { only a variable is allowed ... }
+ Begin
+ tempstr:=actasmpattern;
+ Consume(AS_ID);
+ { typecasting? }
+ if (actasmtoken=AS_LPAREN) and
+ SearchType(tempstr,typesize) then
+ begin
+ oper.hastype:=true;
+ Consume(AS_LPAREN);
+ BuildOperand(oper);
+ Consume(AS_RPAREN);
+ if oper.opr.typ in [OPR_REFERENCE,OPR_LOCAL] then
+ oper.SetSize(typesize,true);
+ end
+ else
+ if not oper.SetupVar(tempstr,false) then
+ Message1(sym_e_unknown_id,tempstr);
+ { record.field ? }
+ if actasmtoken=AS_DOT then
+ begin
+ BuildRecordOffsetSize(tempstr,l,k,mangledname,false);
+ if (mangledname<>'') then
+ Message(asmr_e_invalid_reference_syntax);
+ inc(oper.opr.ref.offset,l);
+ end;
+ MaybeGetPICModifier(oper);
+ case actasmtoken of
+ AS_END,
+ AS_SEPARATOR,
+ AS_COMMA: ;
+ AS_LPAREN:
+ BuildReference(oper);
+ else
+ Begin
+ Message(asmr_e_invalid_reference_syntax);
+ Consume(actasmtoken);
+ end;
+ end; {end case }
+ end;
+ else
+ MaybeBuildReference:=false;
+ end; { end case }
+ end;
+
+ var
+ tempreg : tregister;
+ hl : tasmlabel;
+ Begin
+ expr:='';
+ case actasmtoken of
+ AS_LPAREN: { Memory reference or constant expression }
+ Begin
+ oper.InitRef;
+ BuildReference(oper);
+ end;
+
+ AS_DOLLAR: { Constant expression }
+ Begin
+ Consume(AS_DOLLAR);
+ BuildConstantOperand(oper);
+ end;
+
+ AS_INTNUM,
+ AS_MINUS,
+ AS_PLUS:
+ Begin
+ { Constant memory offset }
+ { This must absolutely be followed by ( }
+ oper.InitRef;
+ oper.opr.ref.offset:=BuildConstExpression(True,False);
+ if actasmtoken<>AS_LPAREN then
+ Message(asmr_e_invalid_reference_syntax)
+ else
+ BuildReference(oper);
+ end;
+
+ AS_STAR: { Call from memory address }
+ Begin
+ Consume(AS_STAR);
+ if actasmtoken=AS_REGISTER then
+ begin
+ oper.opr.typ:=OPR_REGISTER;
+ oper.opr.reg:=actasmregister;
+ oper.SetSize(tcgsize2size[reg_cgsize(actasmregister)],true);
+ Consume(AS_REGISTER);
+ end
+ else
+ begin
+ oper.InitRef;
+ if not MaybeBuildReference then
+ Message(asmr_e_syn_operand);
+ end;
+ { this is only allowed for call's and jmp's }
+ if not is_calljmp(actopcode) then
+ Message(asmr_e_syn_operand);
+ end;
+
+ AS_ID: { A constant expression, or a Variable ref. }
+ Begin
+ { Local Label ? }
+ if is_locallabel(actasmpattern) then
+ begin
+ CreateLocalLabel(actasmpattern,hl,false);
+ Consume(AS_ID);
+ AddLabelOperand(hl);
+ end
+ else
+ { Check for label }
+ if SearchLabel(actasmpattern,hl,false) then
+ begin
+ Consume(AS_ID);
+ AddLabelOperand(hl);
+ end
+ else
+ { probably a variable or normal expression }
+ { or a procedure (such as in CALL ID) }
+ Begin
+ { is it a constant ? }
+ if SearchIConstant(actasmpattern,l) then
+ Begin
+ if not (oper.opr.typ in [OPR_NONE,OPR_CONSTANT]) then
+ Message(asmr_e_invalid_operand_type);
+ BuildConstantOperand(oper);
+ end
+ else
+ begin
+ expr:=actasmpattern;
+ Consume(AS_ID);
+ { typecasting? }
+ if (actasmtoken=AS_LPAREN) and
+ SearchType(expr,typesize) then
+ begin
+ oper.hastype:=true;
+ Consume(AS_LPAREN);
+ BuildOperand(oper);
+ Consume(AS_RPAREN);
+ if oper.opr.typ in [OPR_REFERENCE,OPR_LOCAL] then
+ oper.SetSize(typesize,true);
+ end
+ else
+ begin
+ if oper.SetupVar(expr,false) then
+ MaybeGetPICModifier(oper)
+ else
+ Begin
+ { look for special symbols ... }
+ if expr= '__HIGH' then
+ begin
+ consume(AS_LPAREN);
+ if not oper.setupvar('high'+actasmpattern,false) then
+ Message1(sym_e_unknown_id,'high'+actasmpattern);
+ consume(AS_ID);
+ consume(AS_RPAREN);
+ end
+ else
+ if expr = '__RESULT' then
+ oper.SetUpResult
+ else
+ if expr = '__SELF' then
+ oper.SetupSelf
+ else
+ if expr = '__OLDEBP' then
+ oper.SetupOldEBP
+ else
+ Message1(sym_e_unknown_id,expr);
+ end;
+ end;
+ end;
+ if oper.opr.typ<>OPR_NONE Then
+ begin
+ if (actasmtoken=AS_DOT) then
+ MaybeRecordOffset;
+ { add a constant expression? }
+ if (actasmtoken=AS_PLUS) then
+ begin
+ l:=BuildConstExpression(true,false);
+ case oper.opr.typ of
+ OPR_CONSTANT :
+ inc(oper.opr.val,l);
+ OPR_LOCAL :
+ inc(oper.opr.localsymofs,l);
+ OPR_REFERENCE :
+ inc(oper.opr.ref.offset,l);
+ else
+ internalerror(200309202);
+ end;
+ end;
+ end;
+ end;
+ { Do we have a indexing reference, then parse it also }
+ if actasmtoken=AS_LPAREN then
+ BuildReference(oper);
+ end;
+
+ AS_REGISTER: { Register, a variable reference or a constant reference }
+ Begin
+ { save the type of register used. }
+ tempreg:=actasmregister;
+ Consume(AS_REGISTER);
+ if actasmtoken = AS_COLON then
+ Begin
+ Consume(AS_COLON);
+ oper.InitRef;
+ oper.opr.ref.segment:=tempreg;
+ { This must absolutely be followed by a reference }
+ if not MaybeBuildReference then
+ Begin
+ Message(asmr_e_invalid_seg_override);
+ Consume(actasmtoken);
+ end;
+ end
+ { Simple register }
+ else if (actasmtoken in [AS_END,AS_SEPARATOR,AS_COMMA]) then
+ Begin
+ if not (oper.opr.typ in [OPR_NONE,OPR_REGISTER]) then
+ Message(asmr_e_invalid_operand_type);
+ oper.opr.typ:=OPR_REGISTER;
+ oper.opr.reg:=tempreg;
+ oper.SetSize(tcgsize2size[reg_cgsize(oper.opr.reg)],true);
+ end
+ else
+ Message(asmr_e_syn_operand);
+ end;
+ AS_END,
+ AS_SEPARATOR,
+ AS_COMMA: ;
+ else
+ Begin
+ Message(asmr_e_syn_operand);
+ Consume(actasmtoken);
+ end;
+ end; { end case }
+ end;
+
+
+ procedure tx86attreader.BuildOpCode(instr : tx86instruction);
+ var
+ operandnum : longint;
+ PrefixOp,OverrideOp: tasmop;
+ Begin
+ PrefixOp:=A_None;
+ OverrideOp:=A_None;
+ { prefix seg opcode / prefix opcode }
+ repeat
+ if is_prefix(actopcode) then
+ begin
+ PrefixOp:=ActOpcode;
+ with instr do
+ begin
+ opcode:=ActOpcode;
+ condition:=ActCondition;
+ opsize:=ActOpsize;
+ ConcatInstruction(curlist);
+ end;
+ Consume(AS_OPCODE);
+ end
+ else
+ if is_override(actopcode) then
+ begin
+ OverrideOp:=ActOpcode;
+ with instr do
+ begin
+ opcode:=ActOpcode;
+ condition:=ActCondition;
+ opsize:=ActOpsize;
+ ConcatInstruction(curlist);
+ end;
+ Consume(AS_OPCODE);
+ end
+ else
+ break;
+ { allow for newline as in gas styled syntax }
+ while actasmtoken=AS_SEPARATOR do
+ Consume(AS_SEPARATOR);
+ until (actasmtoken<>AS_OPCODE);
+ { opcode }
+ if (actasmtoken<>AS_OPCODE) then
+ Begin
+ Message(asmr_e_invalid_or_missing_opcode);
+ RecoverConsume(true);
+ exit;
+ end;
+ { Fill the instr object with the current state }
+ with instr do
+ begin
+ Opcode:=ActOpcode;
+ condition:=ActCondition;
+ opsize:=ActOpsize;
+ end;
+
+ { Valid combination of prefix/override and instruction ? }
+
+ if (prefixop<>A_NONE) and (NOT CheckPrefix(PrefixOp,actopcode)) then
+ Message1(asmr_e_invalid_prefix_and_opcode,actasmpattern);
+
+ if (overrideop<>A_NONE) and (NOT CheckOverride(OverrideOp,ActOpcode)) then
+ Message1(asmr_e_invalid_override_and_opcode,actasmpattern);
+ { We are reading operands, so opcode will be an AS_ID }
+ operandnum:=1;
+ Consume(AS_OPCODE);
+ { Zero operand opcode ? }
+ if actasmtoken in [AS_SEPARATOR,AS_END] then
+ begin
+ operandnum:=0;
+ exit;
+ end;
+ { Read the operands }
+ repeat
+ case actasmtoken of
+ AS_COMMA: { Operand delimiter }
+ Begin
+ if operandnum > Max_Operands then
+ Message(asmr_e_too_many_operands)
+ else
+ Inc(operandnum);
+ Consume(AS_COMMA);
+ end;
+ AS_SEPARATOR,
+ AS_END : { End of asm operands for this opcode }
+ begin
+ break;
+ end;
+ else
+ BuildOperand(instr.Operands[operandnum] as tx86operand);
+ end; { end case }
+ until false;
+ instr.Ops:=operandnum;
+ end;
+
+
+ function tx86attreader.is_asmopcode(const s: string):boolean;
+ var
+ cond : string[4];
+ cnd : tasmcond;
+ len,
+ j,
+ sufidx,
+ suflen : longint;
+ Begin
+ is_asmopcode:=FALSE;
+
+ actopcode:=A_None;
+ actcondition:=C_None;
+ actopsize:=S_NO;
+
+ { search for all possible suffixes }
+ for sufidx:=low(att_sizesuffixstr) to high(att_sizesuffixstr) do
+ begin
+ suflen:=length(att_sizesuffixstr[sufidx]);
+ len:=length(s)-suflen;
+ if copy(s,len+1,suflen)=att_sizesuffixstr[sufidx] then
+ begin
+ { Search opcodes }
+ if len>0 then
+ begin
+ actopcode:=tasmop(PtrUInt(iasmops.Find(copy(s,1,len))));
+
+ { two-letter suffix is allowed by just a few instructions (movsx,movzx),
+ and it is always required whenever allowed }
+ if (gas_needsuffix[actopcode]=attsufINTdual) xor (suflen=2) then
+ continue;
+
+ if actopcode<>A_NONE then
+ begin
+ if gas_needsuffix[actopcode]=attsufFPU then
+ actopsize:=att_sizefpusuffix[sufidx]
+ else if gas_needsuffix[actopcode]=attsufFPUint then
+ actopsize:=att_sizefpuintsuffix[sufidx]
+ else
+ actopsize:=att_sizesuffix[sufidx];
+ { only accept suffix from the same category that the opcode belongs to }
+ if (actopsize<>S_NO) or (suflen=0) then
+ begin
+ actasmtoken:=AS_OPCODE;
+ is_asmopcode:=TRUE;
+ exit;
+ end;
+ end;
+ end;
+ { not found, check condition opcodes }
+ j:=0;
+ while (j<CondAsmOps) do
+ begin
+ if Copy(s,1,Length(CondAsmOpStr[j]))=CondAsmOpStr[j] then
+ begin
+ cond:=Copy(s,Length(CondAsmOpStr[j])+1,len-Length(CondAsmOpStr[j]));
+ if cond<>'' then
+ begin
+ for cnd:=low(TasmCond) to high(TasmCond) do
+ if Cond=Upper(cond2str[cnd]) then
+ begin
+ actopcode:=CondASmOp[j];
+ if gas_needsuffix[actopcode]=attsufFPU then
+ actopsize:=att_sizefpusuffix[sufidx]
+ else if gas_needsuffix[actopcode]=attsufFPUint then
+ actopsize:=att_sizefpuintsuffix[sufidx]
+ else
+ actopsize:=att_sizesuffix[sufidx];
+ { only accept suffix from the same category that the opcode belongs to }
+ if (actopsize<>S_NO) or (suflen=0) then
+ begin
+ actcondition:=cnd;
+ actasmtoken:=AS_OPCODE;
+ is_asmopcode:=TRUE;
+ exit;
+ end;
+ end;
+ end;
+ end;
+ inc(j);
+ end;
+ end;
+ end;
+ end;
+
+
+ procedure tx86attreader.handleopcode;
+ var
+ instr : Tx86Instruction;
+ begin
+ instr:=Tx86attInstruction.Create(Tx86Operand);
+ instr.OpOrder:=op_att;
+ BuildOpcode(instr);
+ instr.AddReferenceSizes;
+ instr.SetInstructionOpsize;
+ instr.CheckOperandSizes;
+ instr.FixupOpcode;
+ instr.ConcatInstruction(curlist);
+ instr.Free;
+ end;
+
+
+end.
diff --git a/closures/compiler/x86/rax86int.pas b/closures/compiler/x86/rax86int.pas
new file mode 100644
index 0000000000..e5536a1083
--- /dev/null
+++ b/closures/compiler/x86/rax86int.pas
@@ -0,0 +1,2238 @@
+{
+ Copyright (c) 1998-2002 by Carl Eric Codere and Peter Vreman
+
+ Does the parsing process for the intel styled inline assembler.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+Unit Rax86int;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ cclasses,
+ cpubase,
+ globtype,
+ aasmbase,
+ rasm,
+ rax86;
+
+ type
+ tasmtoken = (
+ AS_NONE,AS_LABEL,AS_LLABEL,AS_STRING,AS_INTNUM,
+ AS_COMMA,AS_LBRACKET,AS_RBRACKET,AS_LPAREN,
+ AS_RPAREN,AS_COLON,AS_DOT,AS_PLUS,AS_MINUS,AS_STAR,
+ AS_SEPARATOR,AS_ID,AS_REGISTER,AS_OPCODE,AS_SLASH,
+ {------------------ Assembler directives --------------------}
+ AS_ALIGN,AS_DB,AS_DW,AS_DD,AS_DQ,AS_END,
+ {------------------ Assembler Operators --------------------}
+ AS_BYTE,AS_WORD,AS_DWORD,AS_QWORD,AS_TBYTE,AS_DQWORD,AS_NEAR,AS_FAR,
+ AS_HIGH,AS_LOW,AS_OFFSET,AS_SIZEOF,AS_VMTOFFSET,AS_SEG,AS_TYPE,AS_PTR,AS_MOD,AS_SHL,AS_SHR,AS_NOT,
+ AS_AND,AS_OR,AS_XOR);
+
+ type
+ tx86intreader = class(tasmreader)
+ actasmtoken : tasmtoken;
+ prevasmtoken : tasmtoken;
+ ActOpsize : topsize;
+ constructor create;override;
+ function is_asmopcode(const s: string):boolean;
+ function is_asmoperator(const s: string):boolean;
+ function is_asmdirective(const s: string):boolean;
+ function is_register(const s:string):boolean;
+ function is_locallabel(const s:string):boolean;
+ function Assemble: tlinkedlist;override;
+ procedure GetToken;
+ function consume(t : tasmtoken):boolean;
+ procedure RecoverConsume(allowcomma:boolean);
+ procedure BuildRecordOffsetSize(const expr: string;var offset:aint;var size:aint; var mangledname: string; needvmtofs: boolean);
+ procedure BuildConstSymbolExpression(needofs,isref,startingminus:boolean;var value:aint;var asmsym:string;var asmsymtyp:TAsmsymtype);
+ function BuildConstExpression:aint;
+ function BuildRefConstExpression:aint;
+ procedure BuildReference(oper : tx86operand);
+ procedure BuildOperand(oper: tx86operand;istypecast:boolean);
+ procedure BuildConstantOperand(oper: tx86operand);
+ procedure BuildOpCode(instr : tx86instruction);
+ procedure BuildConstant(constsize: byte);
+ end;
+
+
+ implementation
+
+ uses
+ { common }
+ cutils,
+ { global }
+ globals,verbose,
+ systems,
+ { aasm }
+ aasmtai,aasmdata,aasmcpu,
+ { symtable }
+ symconst,symbase,symtype,symsym,symdef,symtable,
+ { parser }
+ scanner,
+ { register allocator }
+ rabase,rautils,itx86int,
+ { codegen }
+ cgbase,cgobj,procinfo
+ ;
+
+ type
+ tasmkeyword = string[9];
+
+
+ const
+ { These tokens should be modified accordingly to the modifications }
+ { in the different enumerations. }
+ firstdirective = AS_ALIGN;
+ lastdirective = AS_END;
+ firstoperator = AS_BYTE;
+ lastoperator = AS_XOR;
+
+ _count_asmdirectives = longint(lastdirective)-longint(firstdirective);
+ _count_asmoperators = longint(lastoperator)-longint(firstoperator);
+
+ _asmdirectives : array[0.._count_asmdirectives] of tasmkeyword =
+ ('ALIGN','DB','DW','DD','DQ','END');
+
+ { problems with shl,shr,not,and,or and xor, they are }
+ { context sensitive. }
+ _asmoperators : array[0.._count_asmoperators] of tasmkeyword = (
+ 'BYTE','WORD','DWORD','QWORD','TBYTE','DQWORD','NEAR','FAR','HIGH',
+ 'LOW','OFFSET','SIZEOF','VMTOFFSET','SEG','TYPE','PTR','MOD','SHL','SHR','NOT','AND',
+ 'OR','XOR');
+
+ token2str : array[tasmtoken] of string[10] = (
+ '','Label','LLabel','String','Integer',
+ ',','[',']','(',
+ ')',':','.','+','-','*',
+ ';','identifier','register','opcode','/',
+ '','','','','','END',
+ '','','','','','','','','',
+ '','','sizeof','vmtoffset','','type','ptr','mod','shl','shr','not',
+ 'and','or','xor'
+ );
+
+ var
+ inexpression : boolean;
+
+ constructor tx86intreader.create;
+ var
+ i : tasmop;
+ Begin
+ inherited create;
+ iasmops:=TFPHashList.create;
+ for i:=firstop to lastop do
+ iasmops.Add(upper(std_op2str[i]),Pointer(PtrInt(i)));
+ end;
+
+
+{---------------------------------------------------------------------}
+{ Routines for the tokenizing }
+{---------------------------------------------------------------------}
+
+
+ function tx86intreader.is_asmopcode(const s: string):boolean;
+ var
+ cond : string[4];
+ cnd : tasmcond;
+ j: longint;
+ Begin
+ is_asmopcode:=FALSE;
+
+ actopcode:=A_None;
+ actcondition:=C_None;
+ actopsize:=S_NO;
+
+ { Search opcodes }
+ actopcode:=tasmop(PtrUInt(iasmops.Find(s)));
+ if actopcode<>A_NONE then
+ begin
+ actasmtoken:=AS_OPCODE;
+ result:=TRUE;
+ exit;
+ end;
+
+ { not found yet, check condition opcodes }
+ j:=0;
+ while (j<CondAsmOps) do
+ begin
+ if Copy(s,1,Length(CondAsmOpStr[j]))=CondAsmOpStr[j] then
+ begin
+ cond:=Copy(s,Length(CondAsmOpStr[j])+1,255);
+ if cond<>'' then
+ begin
+ for cnd:=low(TasmCond) to high(TasmCond) do
+ if Cond=Upper(cond2str[cnd]) then
+ begin
+ actopcode:=CondASmOp[j];
+ actcondition:=cnd;
+ is_asmopcode:=TRUE;
+ actasmtoken:=AS_OPCODE;
+ exit
+ end;
+ end;
+ end;
+ inc(j);
+ end;
+ end;
+
+
+ function tx86intreader.is_asmoperator(const s: string):boolean;
+ var
+ i : longint;
+ Begin
+ for i:=0 to _count_asmoperators do
+ if s=_asmoperators[i] then
+ begin
+ actasmtoken:=tasmtoken(longint(firstoperator)+i);
+ is_asmoperator:=true;
+ exit;
+ end;
+ is_asmoperator:=false;
+ end;
+
+
+ Function tx86intreader.is_asmdirective(const s: string):boolean;
+ var
+ i : longint;
+ Begin
+ for i:=0 to _count_asmdirectives do
+ if s=_asmdirectives[i] then
+ begin
+ actasmtoken:=tasmtoken(longint(firstdirective)+i);
+ is_asmdirective:=true;
+ exit;
+ end;
+ is_asmdirective:=false;
+ end;
+
+
+ function tx86intreader.is_register(const s:string):boolean;
+ var
+ entry: TSymEntry;
+ begin
+ is_register:=false;
+ actasmregister:=masm_regnum_search(lower(s));
+ if (actasmregister=NR_NO) and
+ (current_procinfo.procdef.proccalloption=pocall_register) and
+ (po_assembler in current_procinfo.procdef.procoptions) then
+ begin
+ entry:=current_procinfo.procdef.parast.Find(s);
+ if assigned(entry) and
+ (entry.typ=paravarsym) and
+ assigned(tparavarsym(entry).paraloc[calleeside].Location) and
+ (tparavarsym(entry).paraloc[calleeside].Location^.Loc=LOC_REGISTER) then
+ actasmregister:=tparavarsym(entry).paraloc[calleeside].Location^.register;
+ end;
+ if actasmregister<>NR_NO then
+ begin
+ is_register:=true;
+ actasmtoken:=AS_REGISTER;
+ end;
+ end;
+
+
+ function tx86intreader.is_locallabel(const s:string):boolean;
+ begin
+ is_locallabel:=(length(s)>1) and (s[1]='@');
+ end;
+
+
+ Procedure tx86intreader.GetToken;
+ var
+ len : longint;
+ forcelabel : boolean;
+ srsym : tsym;
+ srsymtable : TSymtable;
+ begin
+ { save old token and reset new token }
+ prevasmtoken:=actasmtoken;
+ actasmtoken:=AS_NONE;
+ { reset }
+ forcelabel:=FALSE;
+ actasmpattern:='';
+ { while space and tab , continue scan... }
+ while (c in [' ',#9]) do
+ c:=current_scanner.asmgetchar;
+ { get token pos }
+ if not (c in [#10,#13,'{',';']) then
+ current_scanner.gettokenpos;
+ { Local Label, Label, Directive, Prefix or Opcode }
+ if firsttoken and not (c in [#10,#13,'{',';']) then
+ begin
+ firsttoken:=FALSE;
+ len:=0;
+ while c in ['A'..'Z','a'..'z','0'..'9','_','@'] do
+ begin
+ { if there is an at_sign, then this must absolutely be a label }
+ if c = '@' then
+ forcelabel:=TRUE;
+ inc(len);
+ actasmpattern[len]:=c;
+ c:=current_scanner.asmgetchar;
+ end;
+ actasmpattern[0]:=chr(len);
+ uppervar(actasmpattern);
+ { allow spaces }
+ while (c in [' ',#9]) do
+ c:=current_scanner.asmgetchar;
+ { label ? }
+ if c = ':' then
+ begin
+ if actasmpattern[1]='@' then
+ actasmtoken:=AS_LLABEL
+ else
+ actasmtoken:=AS_LABEL;
+ { let us point to the next character }
+ c:=current_scanner.asmgetchar;
+ firsttoken:=true;
+ exit;
+ end;
+ { Are we trying to create an identifier with }
+ { an at-sign...? }
+ if forcelabel then
+ Message(asmr_e_none_label_contain_at);
+ { opcode ? }
+ If is_asmopcode(actasmpattern) then
+ Begin
+ { check if we are in an expression }
+ { then continue with asm directives }
+ if not inexpression then
+ exit;
+ end;
+ if is_asmdirective(actasmpattern) then
+ exit;
+ message1(asmr_e_unknown_opcode,actasmpattern);
+ actasmtoken:=AS_NONE;
+ exit;
+ end
+ else { else firsttoken }
+ begin
+ case c of
+ '@' : { possiblities : - local label reference , such as in jmp @local1 }
+ { - @Result, @Code or @Data special variables. }
+ begin
+ actasmpattern:=c;
+ c:=current_scanner.asmgetchar;
+ while c in ['A'..'Z','a'..'z','0'..'9','_','@'] do
+ begin
+ actasmpattern:=actasmpattern + c;
+ c:=current_scanner.asmgetchar;
+ end;
+ uppervar(actasmpattern);
+ actasmtoken:=AS_ID;
+ exit;
+ end;
+
+ 'A'..'Z','a'..'z','_': { identifier, register, opcode, prefix or directive }
+ begin
+ actasmpattern:=c;
+ c:=current_scanner.asmgetchar;
+ while c in ['A'..'Z','a'..'z','0'..'9','_'] do
+ begin
+ actasmpattern:=actasmpattern + c;
+ c:=current_scanner.asmgetchar;
+ end;
+ uppervar(actasmpattern);
+ { after prefix we allow also a new opcode }
+ If is_prefix(actopcode) and is_asmopcode(actasmpattern) then
+ Begin
+ { if we are not in a constant }
+ { expression than this is an }
+ { opcode. }
+ if not inexpression then
+ exit;
+ end;
+ { support st(X) for fpu registers }
+ if (actasmpattern = 'ST') and (c='(') then
+ Begin
+ actasmpattern:=actasmpattern+c;
+ c:=current_scanner.asmgetchar;
+ { allow spaces }
+ while (c in [' ',#9]) do
+ c:=current_scanner.asmgetchar;
+ if c in ['0'..'7'] then
+ actasmpattern:=actasmpattern + c
+ else
+ Message(asmr_e_invalid_fpu_register);
+ c:=current_scanner.asmgetchar;
+ { allow spaces }
+ while (c in [' ',#9]) do
+ c:=current_scanner.asmgetchar;
+ if c <> ')' then
+ Message(asmr_e_invalid_fpu_register)
+ else
+ Begin
+ actasmpattern:=actasmpattern + c;
+ c:=current_scanner.asmgetchar;
+ end;
+ end;
+ if is_asmdirective(actasmpattern) then
+ exit;
+ if is_asmoperator(actasmpattern) then
+ exit;
+ if is_register(actasmpattern) then
+ exit;
+ { allow spaces }
+ while (c in [' ',#9]) do
+ c:=current_scanner.asmgetchar;
+ { if next is a '.' and this is a unitsym then we also need to
+ parse the identifier }
+ if (c='.') then
+ begin
+ asmsearchsym(actasmpattern,srsym,srsymtable);
+ if assigned(srsym) and
+ (srsym.typ=unitsym) and
+ (srsym.owner.symtabletype in [staticsymtable,globalsymtable]) and
+ srsym.owner.iscurrentunit then
+ begin
+ { Add . to create System.Identifier }
+ actasmpattern:=actasmpattern+c;
+ c:=current_scanner.asmgetchar;
+ { Delphi allows System.@Halt, just ignore the @ }
+ if c='@' then
+ c:=current_scanner.asmgetchar;
+ while c in ['A'..'Z','a'..'z','0'..'9','_','$'] do
+ begin
+ actasmpattern:=actasmpattern + upcase(c);
+ c:=current_scanner.asmgetchar;
+ end;
+ end;
+ end;
+ actasmtoken:=AS_ID;
+ exit;
+ end;
+
+ '''' : { string or character }
+ begin
+ actasmpattern:='';
+ current_scanner.in_asm_string:=true;
+ repeat
+ if c = '''' then
+ begin
+ c:=current_scanner.asmgetchar;
+ if c in [#10,#13] then
+ begin
+ Message(scan_f_string_exceeds_line);
+ break;
+ end;
+ repeat
+ if c='''' then
+ begin
+ c:=current_scanner.asmgetchar;
+ if c='''' then
+ begin
+ actasmpattern:=actasmpattern+'''';
+ c:=current_scanner.asmgetchar;
+ if c in [#10,#13] then
+ begin
+ Message(scan_f_string_exceeds_line);
+ break;
+ end;
+ end
+ else
+ break;
+ end
+ else
+ begin
+ actasmpattern:=actasmpattern+c;
+ c:=current_scanner.asmgetchar;
+ if c in [#10,#13] then
+ begin
+ Message(scan_f_string_exceeds_line);
+ break
+ end;
+ end;
+ until false; { end repeat }
+ end
+ else
+ break; { end if }
+ until false;
+ current_scanner.in_asm_string:=false;
+ actasmtoken:=AS_STRING;
+ exit;
+ end;
+
+ '"' : { string or character }
+ begin
+ current_scanner.in_asm_string:=true;
+ actasmpattern:='';
+ repeat
+ if c = '"' then
+ begin
+ c:=current_scanner.asmgetchar;
+ if c in [#10,#13] then
+ begin
+ Message(scan_f_string_exceeds_line);
+ break;
+ end;
+ repeat
+ if c='"' then
+ begin
+ c:=current_scanner.asmgetchar;
+ if c='"' then
+ begin
+ actasmpattern:=actasmpattern+'"';
+ c:=current_scanner.asmgetchar;
+ if c in [#10,#13] then
+ begin
+ Message(scan_f_string_exceeds_line);
+ break;
+ end;
+ end
+ else
+ break;
+ end
+ else
+ begin
+ actasmpattern:=actasmpattern+c;
+ c:=current_scanner.asmgetchar;
+ if c in [#10,#13] then
+ begin
+ Message(scan_f_string_exceeds_line);
+ break
+ end;
+ end;
+ until false; { end repeat }
+ end
+ else
+ break; { end if }
+ until false;
+ current_scanner.in_asm_string:=false;
+ actasmtoken:=AS_STRING;
+ exit;
+ end;
+
+ '$' :
+ begin
+ c:=current_scanner.asmgetchar;
+ while c in ['0'..'9','A'..'F','a'..'f'] do
+ begin
+ actasmpattern:=actasmpattern + c;
+ c:=current_scanner.asmgetchar;
+ end;
+ actasmpattern:=tostr(ParseVal(actasmpattern,16));
+ actasmtoken:=AS_INTNUM;
+ exit;
+ end;
+
+ '&' : { identifier }
+ begin
+ actasmpattern:='';
+ c:=current_scanner.asmgetchar;
+ while c in ['A'..'Z','a'..'z','0'..'9','_'] do
+ begin
+ actasmpattern:=actasmpattern + c;
+ c:=current_scanner.asmgetchar;
+ end;
+ uppervar(actasmpattern);
+ actasmtoken:=AS_ID;
+ exit;
+ end;
+
+ ',' :
+ begin
+ actasmtoken:=AS_COMMA;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+
+ '[' :
+ begin
+ actasmtoken:=AS_LBRACKET;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+
+ ']' :
+ begin
+ actasmtoken:=AS_RBRACKET;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+
+ '(' :
+ begin
+ actasmtoken:=AS_LPAREN;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+
+ ')' :
+ begin
+ actasmtoken:=AS_RPAREN;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+
+ ':' :
+ begin
+ actasmtoken:=AS_COLON;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+
+ '.' :
+ begin
+ actasmtoken:=AS_DOT;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+
+ '+' :
+ begin
+ actasmtoken:=AS_PLUS;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+
+ '-' :
+ begin
+ actasmtoken:=AS_MINUS;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+
+ '*' :
+ begin
+ actasmtoken:=AS_STAR;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+
+ '/' :
+ begin
+ actasmtoken:=AS_SLASH;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+
+ '0'..'9':
+ begin
+ actasmpattern:=c;
+ c:=current_scanner.asmgetchar;
+ { Get the possible characters }
+ while c in ['0'..'9','A'..'F','a'..'f'] do
+ begin
+ actasmpattern:=actasmpattern + c;
+ c:=current_scanner.asmgetchar;
+ end;
+ { Get ending character }
+ uppervar(actasmpattern);
+ c:=upcase(c);
+ { possibly a binary number. }
+ if (actasmpattern[length(actasmpattern)] = 'B') and (c <> 'H') then
+ Begin
+ { Delete the last binary specifier }
+ delete(actasmpattern,length(actasmpattern),1);
+ actasmpattern:=tostr(ParseVal(actasmpattern,2));
+ actasmtoken:=AS_INTNUM;
+ exit;
+ end
+ else
+ Begin
+ case c of
+ 'O' :
+ Begin
+ actasmpattern:=tostr(ParseVal(actasmpattern,8));
+ actasmtoken:=AS_INTNUM;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+ 'H' :
+ Begin
+ actasmpattern:=tostr(ParseVal(actasmpattern,16));
+ actasmtoken:=AS_INTNUM;
+ c:=current_scanner.asmgetchar;
+ exit;
+ end;
+ else { must be an integer number }
+ begin
+ actasmpattern:=tostr(ParseVal(actasmpattern,10));
+ actasmtoken:=AS_INTNUM;
+ exit;
+ end;
+ end;
+ end;
+ end;
+ ';','{',#13,#10 :
+ begin
+ c:=current_scanner.asmgetchar;
+ firsttoken:=TRUE;
+ actasmtoken:=AS_SEPARATOR;
+ exit;
+ end;
+
+ else
+ current_scanner.illegal_char(c);
+ end;
+ end;
+ end;
+
+
+ function tx86intreader.consume(t : tasmtoken):boolean;
+ begin
+ Consume:=true;
+ if t<>actasmtoken then
+ begin
+ Message2(scan_f_syn_expected,token2str[t],token2str[actasmtoken]);
+ Consume:=false;
+ end;
+ repeat
+ gettoken;
+ until actasmtoken<>AS_NONE;
+ end;
+
+
+ procedure tx86intreader.RecoverConsume(allowcomma:boolean);
+ begin
+ While not (actasmtoken in [AS_SEPARATOR,AS_END]) do
+ begin
+ if allowcomma and (actasmtoken=AS_COMMA) then
+ break;
+ Consume(actasmtoken);
+ end;
+ end;
+
+
+{*****************************************************************************
+ Parsing Helpers
+*****************************************************************************}
+
+ { This routine builds up a record offset after a AS_DOT
+ token is encountered.
+ On entry actasmtoken should be equal to AS_DOT }
+ Procedure tx86intreader.BuildRecordOffsetSize(const expr: string;var offset:aint;var size:aint; var mangledname: string; needvmtofs: boolean);
+ var
+ s: string;
+ Begin
+ offset:=0;
+ size:=0;
+ s:=expr;
+ while (actasmtoken=AS_DOT) do
+ begin
+ Consume(AS_DOT);
+ if actasmtoken in [AS_BYTE,AS_ID,AS_WORD,AS_DWORD,AS_QWORD,AS_REGISTER] then
+ begin
+ s:=s+'.'+actasmpattern;
+ consume(actasmtoken);
+ end
+ else
+ begin
+ Consume(AS_ID);
+ RecoverConsume(true);
+ break;
+ end;
+ end;
+ if not GetRecordOffsetSize(s,offset,size,mangledname,needvmtofs) then
+ Message(asmr_e_building_record_offset);
+ end;
+
+
+ Procedure tx86intreader.BuildConstSymbolExpression(needofs,isref,startingminus:boolean;var value:aint;var asmsym:string;var asmsymtyp:TAsmsymtype);
+ var
+ tempstr,expr,hs,mangledname : string;
+ parenlevel : longint;
+ l,k : aint;
+ hasparen,
+ errorflag,
+ needvmtofs : boolean;
+ prevtok : tasmtoken;
+ hl : tasmlabel;
+ hssymtyp : Tasmsymtype;
+ def : tdef;
+ sym : tsym;
+ srsymtable : TSymtable;
+ Begin
+ { reset }
+ value:=0;
+ asmsym:='';
+ asmsymtyp:=AT_DATA;
+ errorflag:=FALSE;
+ tempstr:='';
+ expr:='';
+ if startingminus then
+ expr:='-';
+ inexpression:=TRUE;
+ parenlevel:=0;
+ sym:=nil;
+ needvmtofs:=FALSE;
+ Repeat
+ { Support ugly delphi constructs like: [ECX].1+2[EDX] }
+ if isref and (actasmtoken=AS_LBRACKET) then
+ break;
+ Case actasmtoken of
+ AS_LPAREN:
+ Begin
+ Consume(AS_LPAREN);
+ expr:=expr + '(';
+ inc(parenlevel);
+ end;
+ AS_RPAREN:
+ Begin
+ { Keep the AS_PAREN in actasmtoken, it is maybe a typecast }
+ if parenlevel=0 then
+ break;
+ Consume(AS_RPAREN);
+ expr:=expr + ')';
+ dec(parenlevel);
+ end;
+ AS_SHL:
+ Begin
+ Consume(AS_SHL);
+ expr:=expr + '<';
+ end;
+ AS_SHR:
+ Begin
+ Consume(AS_SHR);
+ expr:=expr + '>';
+ end;
+ AS_SLASH:
+ Begin
+ Consume(AS_SLASH);
+ expr:=expr + '/';
+ end;
+ AS_MOD:
+ Begin
+ Consume(AS_MOD);
+ expr:=expr + '%';
+ end;
+ AS_STAR:
+ Begin
+ Consume(AS_STAR);
+ if isref and (actasmtoken=AS_REGISTER) then
+ break;
+ expr:=expr + '*';
+ end;
+ AS_PLUS:
+ Begin
+ Consume(AS_PLUS);
+ if isref and (actasmtoken=AS_REGISTER) then
+ break;
+ expr:=expr + '+';
+ end;
+ AS_MINUS:
+ Begin
+ Consume(AS_MINUS);
+ expr:=expr + '-';
+ end;
+ AS_AND:
+ Begin
+ Consume(AS_AND);
+ expr:=expr + '&';
+ end;
+ AS_NOT:
+ Begin
+ Consume(AS_NOT);
+ expr:=expr + '~';
+ end;
+ AS_XOR:
+ Begin
+ Consume(AS_XOR);
+ expr:=expr + '^';
+ end;
+ AS_OR:
+ Begin
+ Consume(AS_OR);
+ expr:=expr + '|';
+ end;
+ AS_INTNUM:
+ Begin
+ expr:=expr + actasmpattern;
+ Consume(AS_INTNUM);
+ end;
+ AS_VMTOFFSET,
+ AS_OFFSET:
+ begin
+ if (actasmtoken = AS_OFFSET) then
+ needofs:=true
+ else
+ needvmtofs:=true;
+ Consume(actasmtoken);
+ if actasmtoken<>AS_ID then
+ Message(asmr_e_offset_without_identifier);
+ end;
+ AS_SIZEOF,
+ AS_TYPE:
+ begin
+ l:=0;
+ hasparen:=false;
+ Consume(actasmtoken);
+ if actasmtoken=AS_LPAREN then
+ begin
+ hasparen:=true;
+ Consume(AS_LPAREN);
+ end;
+ if actasmtoken<>AS_ID then
+ Message(asmr_e_type_without_identifier)
+ else
+ begin
+ tempstr:=actasmpattern;
+ Consume(AS_ID);
+ if actasmtoken=AS_DOT then
+ begin
+ BuildRecordOffsetSize(tempstr,k,l,mangledname,false);
+ if mangledname<>'' then
+ { procsym }
+ Message(asmr_e_wrong_sym_type);
+ end
+ else
+ begin
+ asmsearchsym(tempstr,sym,srsymtable);
+ if assigned(sym) then
+ begin
+ case sym.typ of
+ staticvarsym,
+ localvarsym,
+ paravarsym :
+ l:=tabstractvarsym(sym).getsize;
+ typesym :
+ l:=ttypesym(sym).typedef.size;
+ else
+ Message(asmr_e_wrong_sym_type);
+ end;
+ end
+ else
+ Message1(sym_e_unknown_id,tempstr);
+ end;
+ end;
+ str(l, tempstr);
+ expr:=expr + tempstr;
+ if hasparen then
+ Consume(AS_RPAREN);
+ end;
+ AS_PTR :
+ begin
+ { Support ugly delphi constructs like <constant> PTR [ref] }
+ break;
+ end;
+ AS_STRING:
+ begin
+ l:=0;
+ case Length(actasmpattern) of
+ 1 :
+ l:=ord(actasmpattern[1]);
+ 2 :
+ l:=ord(actasmpattern[2]) + ord(actasmpattern[1]) shl 8;
+ 3 :
+ l:=ord(actasmpattern[3]) +
+ Ord(actasmpattern[2]) shl 8 + ord(actasmpattern[1]) shl 16;
+ 4 :
+ l:=ord(actasmpattern[4]) + ord(actasmpattern[3]) shl 8 +
+ Ord(actasmpattern[2]) shl 16 + ord(actasmpattern[1]) shl 24;
+ else
+ Message1(asmr_e_invalid_string_as_opcode_operand,actasmpattern);
+ end;
+ str(l, tempstr);
+ expr:=expr + tempstr;
+ Consume(AS_STRING);
+ end;
+ AS_ID:
+ begin
+ hs:='';
+ hssymtyp:=AT_DATA;
+ def:=nil;
+ tempstr:=actasmpattern;
+ prevtok:=prevasmtoken;
+ { stop parsing a constant expression if we find an opcode after a
+ non-operator like "db $66 mov eax,ebx" }
+ if (prevtok in [AS_ID,AS_INTNUM,AS_RPAREN]) and
+ is_asmopcode(actasmpattern) then
+ break;
+ consume(AS_ID);
+ if SearchIConstant(tempstr,l) then
+ begin
+ str(l, tempstr);
+ expr:=expr + tempstr;
+ end
+ else
+ begin
+ if is_locallabel(tempstr) then
+ begin
+ CreateLocalLabel(tempstr,hl,false);
+ hs:=hl.name;
+ hssymtyp:=AT_FUNCTION;
+ end
+ else
+ if SearchLabel(tempstr,hl,false) then
+ begin
+ hs:=hl.name;
+ hssymtyp:=AT_FUNCTION;
+ end
+ else
+ begin
+ asmsearchsym(tempstr,sym,srsymtable);
+ if assigned(sym) then
+ begin
+ case sym.typ of
+ staticvarsym :
+ begin
+ hs:=tstaticvarsym(sym).mangledname;
+ def:=tstaticvarsym(sym).vardef;
+ end;
+ localvarsym,
+ paravarsym :
+ begin
+ Message(asmr_e_no_local_or_para_allowed);
+ end;
+ procsym :
+ begin
+ if Tprocsym(sym).ProcdefList.Count>1 then
+ Message(asmr_w_calling_overload_func);
+ hs:=tprocdef(tprocsym(sym).ProcdefList[0]).mangledname;
+ hssymtyp:=AT_FUNCTION;
+ end;
+ typesym :
+ begin
+ if not(ttypesym(sym).typedef.typ in [recorddef,objectdef]) then
+ Message(asmr_e_wrong_sym_type);
+ end;
+ fieldvarsym :
+ begin
+ tempstr:=upper(tdef(sym.owner.defowner).GetTypeName)+'.'+tempstr;
+ end;
+ else
+ Message(asmr_e_wrong_sym_type);
+ end;
+ end
+ else
+ Message1(sym_e_unknown_id,tempstr);
+ end;
+ { symbol found? }
+ if hs<>'' then
+ begin
+ if asmsym='' then
+ begin
+ asmsym:=hs;
+ asmsymtyp:=hssymtyp;
+ end
+ else
+ Message(asmr_e_cant_have_multiple_relocatable_symbols);
+ if (expr='') or (expr[length(expr)]='+') then
+ begin
+ { don't remove the + if there could be a record field }
+ if actasmtoken<>AS_DOT then
+ delete(expr,length(expr),1);
+ end
+ else
+ if needofs then
+ begin
+ if (prevtok<>AS_OFFSET) then
+ Message(asmr_e_need_offset);
+ end
+ else
+ Message(asmr_e_only_add_relocatable_symbol);
+ end;
+ if (actasmtoken=AS_DOT) or
+ (assigned(sym) and
+ (sym.typ = fieldvarsym)) then
+ begin
+ BuildRecordOffsetSize(tempstr,l,k,hs,needvmtofs);
+ if hs <> '' then
+ hssymtyp:=AT_FUNCTION
+ else
+ begin
+ str(l, tempstr);
+ expr:=expr + tempstr;
+ end
+ end
+ else
+ begin
+ if (expr='') or (expr[length(expr)] in ['+','-','/','*']) then
+ delete(expr,length(expr),1);
+ end;
+ if (actasmtoken=AS_LBRACKET) and
+ assigned(def) and
+ (def.typ=arraydef) then
+ begin
+ consume(AS_LBRACKET);
+ l:=BuildConstExpression;
+ if l<tarraydef(def).lowrange then
+ begin
+ Message(asmr_e_constant_out_of_bounds);
+ l:=0;
+ end
+ else
+ l:=(l-tarraydef(def).lowrange)*tarraydef(def).elesize;
+ str(l, tempstr);
+ expr:=expr + '+' + tempstr;
+ consume(AS_RBRACKET);
+ end;
+ end;
+ { check if there are wrong operator used like / or mod etc. }
+ if (hs<>'') and not(actasmtoken in [AS_MINUS,AS_PLUS,AS_COMMA,AS_SEPARATOR,AS_END,AS_RBRACKET]) then
+ Message(asmr_e_only_add_relocatable_symbol);
+ end;
+ AS_ALIGN,
+ AS_DB,
+ AS_DW,
+ AS_DD,
+ AS_DQ,
+ AS_END,
+ AS_RBRACKET,
+ AS_SEPARATOR,
+ AS_COMMA,
+ AS_COLON:
+ break;
+ else
+ begin
+ { write error only once. }
+ if not errorflag then
+ Message(asmr_e_invalid_constant_expression);
+ { consume tokens until we find COMMA or SEPARATOR }
+ Consume(actasmtoken);
+ errorflag:=TRUE;
+ end;
+ end;
+ Until false;
+ { calculate expression }
+ if not ErrorFlag then
+ value:=CalculateExpression(expr)
+ else
+ value:=0;
+ { no longer in an expression }
+ inexpression:=FALSE;
+ end;
+
+
+ Function tx86intreader.BuildConstExpression:aint;
+ var
+ l : aint;
+ hs : string;
+ hssymtyp : TAsmsymtype;
+ begin
+ BuildConstSymbolExpression(false,false,false,l,hs,hssymtyp);
+ if hs<>'' then
+ Message(asmr_e_relocatable_symbol_not_allowed);
+ BuildConstExpression:=l;
+ end;
+
+
+ Function tx86intreader.BuildRefConstExpression:aint;
+ var
+ l : aint;
+ hs : string;
+ hssymtyp : TAsmsymtype;
+ begin
+ BuildConstSymbolExpression(false,true,false,l,hs,hssymtyp);
+ if hs<>'' then
+ Message(asmr_e_relocatable_symbol_not_allowed);
+ BuildRefConstExpression:=l;
+ end;
+
+
+ procedure tx86intreader.BuildReference(oper : tx86operand);
+ var
+ scale : byte;
+ k,l : aint;
+ tempstr,hs : string;
+ tempsymtyp : tasmsymtype;
+ code : integer;
+ hreg : tregister;
+ GotStar,GotOffset,HadVar,
+ GotPlus,Negative : boolean;
+ hl : tasmlabel;
+ Begin
+ Consume(AS_LBRACKET);
+ if not(oper.opr.typ in [OPR_LOCAL,OPR_REFERENCE]) then
+ oper.InitRef;
+ GotStar:=false;
+ GotPlus:=true;
+ GotOffset:=false;
+ Negative:=false;
+ Scale:=0;
+ repeat
+ if GotOffset and (actasmtoken<>AS_ID) then
+ Message(asmr_e_invalid_reference_syntax);
+
+ Case actasmtoken of
+ AS_ID, { Constant reference expression OR variable reference expression }
+ AS_VMTOFFSET:
+ Begin
+ if not GotPlus then
+ Message(asmr_e_invalid_reference_syntax);
+ GotStar:=false;
+ GotPlus:=false;
+ if (actasmtoken = AS_VMTOFFSET) or
+ (SearchIConstant(actasmpattern,l) or
+ SearchRecordType(actasmpattern)) then
+ begin
+ l:=BuildRefConstExpression;
+ GotPlus:=(prevasmtoken=AS_PLUS);
+ GotStar:=(prevasmtoken=AS_STAR);
+ case oper.opr.typ of
+ OPR_LOCAL :
+ begin
+ if GotStar then
+ Message(asmr_e_invalid_reference_syntax);
+ if negative then
+ Dec(oper.opr.localsymofs,l)
+ else
+ Inc(oper.opr.localsymofs,l);
+ end;
+ OPR_REFERENCE :
+ begin
+ if GotStar then
+ oper.opr.ref.scalefactor:=l
+ else
+ begin
+ if negative then
+ Dec(oper.opr.ref.offset,l)
+ else
+ Inc(oper.opr.ref.offset,l);
+ end;
+ end;
+ end;
+ end
+ else
+ Begin
+ if negative and not oper.hasvar then
+ Message(asmr_e_only_add_relocatable_symbol)
+ else if oper.hasvar and not GotOffset and
+ (not negative or assigned(oper.opr.ref.relsymbol)) then
+ Message(asmr_e_cant_have_multiple_relocatable_symbols);
+ HadVar:=oper.hasvar and GotOffset;
+ tempstr:=actasmpattern;
+ Consume(AS_ID);
+ { typecasting? }
+ if (actasmtoken=AS_LPAREN) and
+ SearchType(tempstr,l) then
+ begin
+ oper.hastype:=true;
+ oper.typesize:=l;
+ Consume(AS_LPAREN);
+ BuildOperand(oper,true);
+ Consume(AS_RPAREN);
+ end
+ else
+ if is_locallabel(tempstr) then
+ begin
+ CreateLocalLabel(tempstr,hl,false);
+ oper.InitRef;
+ if not negative then
+ begin
+ oper.opr.ref.symbol:=hl;
+ oper.hasvar:=true;
+ end
+ else
+ oper.opr.ref.relsymbol:=hl;
+ end
+ else
+ if oper.SetupVar(tempstr,GotOffset) then
+ begin
+ { force OPR_LOCAL to be a reference }
+ if oper.opr.typ=OPR_LOCAL then
+ oper.opr.localforceref:=true;
+ end
+ else
+ Message1(sym_e_unknown_id,tempstr);
+ { record.field ? }
+ if actasmtoken=AS_DOT then
+ begin
+ BuildRecordOffsetSize(tempstr,l,k,hs,false);
+ if (hs<>'') then
+ Message(asmr_e_invalid_symbol_ref);
+ case oper.opr.typ of
+ OPR_LOCAL :
+ inc(oper.opr.localsymofs,l);
+ OPR_REFERENCE :
+ inc(oper.opr.ref.offset,l);
+ end;
+ end;
+ if GotOffset then
+ begin
+ if oper.hasvar and (oper.opr.ref.base=current_procinfo.framepointer) then
+ begin
+ if (oper.opr.typ=OPR_REFERENCE) then
+ oper.opr.ref.base:=NR_NO;
+ oper.hasvar:=hadvar;
+ end
+ else
+ begin
+ if oper.hasvar and hadvar then
+ Message(asmr_e_cant_have_multiple_relocatable_symbols);
+ { should we allow ?? }
+ end;
+ end;
+ end;
+ GotOffset:=false;
+ end;
+
+ AS_PLUS :
+ Begin
+ Consume(AS_PLUS);
+ Negative:=false;
+ GotPlus:=true;
+ GotStar:=false;
+ Scale:=0;
+ end;
+
+ AS_DOT :
+ Begin
+ { Handle like a + }
+ Consume(AS_DOT);
+ Negative:=false;
+ GotPlus:=true;
+ GotStar:=false;
+ Scale:=0;
+ end;
+
+ AS_MINUS :
+ begin
+ Consume(AS_MINUS);
+ Negative:=true;
+ GotPlus:=true;
+ GotStar:=false;
+ Scale:=0;
+ end;
+
+ AS_STAR : { Scaling, with eax*4 order }
+ begin
+ Consume(AS_STAR);
+ hs:='';
+ l:=0;
+ case actasmtoken of
+ AS_LPAREN :
+ l:=BuildConstExpression;
+ AS_INTNUM:
+ Begin
+ hs:=actasmpattern;
+ Consume(AS_INTNUM);
+ end;
+ AS_REGISTER :
+ begin
+ case oper.opr.typ of
+ OPR_REFERENCE :
+ begin
+ if oper.opr.ref.scalefactor=0 then
+ begin
+ if scale<>0 then
+ begin
+ oper.opr.ref.scalefactor:=scale;
+ scale:=0;
+ end
+ else
+ Message(asmr_e_wrong_scale_factor);
+ end
+ else
+ Message(asmr_e_invalid_reference_syntax);
+ end;
+ OPR_LOCAL :
+ begin
+ if oper.opr.localscale=0 then
+ begin
+ if scale<>0 then
+ begin
+ oper.opr.localscale:=scale;
+ scale:=0;
+ end
+ else
+ Message(asmr_e_wrong_scale_factor);
+ end
+ else
+ Message(asmr_e_invalid_reference_syntax);
+ end;
+ end;
+ end;
+ else
+ Message(asmr_e_invalid_reference_syntax);
+ end;
+ if actasmtoken<>AS_REGISTER then
+ begin
+ if hs<>'' then
+ val(hs,l,code);
+ case oper.opr.typ of
+ OPR_REFERENCE :
+ oper.opr.ref.scalefactor:=l;
+ OPR_LOCAL :
+ oper.opr.localscale:=l;
+ end;
+ if l>9 then
+ Message(asmr_e_wrong_scale_factor);
+ end;
+ GotPlus:=false;
+ GotStar:=false;
+ end;
+
+ AS_REGISTER :
+ begin
+ if not((GotPlus and (not Negative)) or
+ GotStar) then
+ Message(asmr_e_invalid_reference_syntax);
+ hreg:=actasmregister;
+ Consume(AS_REGISTER);
+ { this register will be the index:
+ 1. just read a *
+ 2. next token is a *
+ 3. base register is already used }
+ case oper.opr.typ of
+ OPR_LOCAL :
+ begin
+ if (oper.opr.localindexreg<>NR_NO) then
+ Message(asmr_e_multiple_index);
+ oper.opr.localindexreg:=hreg;
+ if scale<>0 then
+ begin
+ oper.opr.localscale:=scale;
+ scale:=0;
+ end;
+ end;
+ OPR_REFERENCE :
+ begin
+ if (GotStar) or
+ (actasmtoken=AS_STAR) or
+ (oper.opr.ref.base<>NR_NO) then
+ begin
+ if (oper.opr.ref.index<>NR_NO) then
+ Message(asmr_e_multiple_index);
+ oper.opr.ref.index:=hreg;
+ if scale<>0 then
+ begin
+ oper.opr.ref.scalefactor:=scale;
+ scale:=0;
+ end;
+ end
+ else
+ oper.opr.ref.base:=hreg;
+ end;
+ end;
+ GotPlus:=false;
+ GotStar:=false;
+ end;
+
+ AS_OFFSET :
+ begin
+ Consume(AS_OFFSET);
+ GotOffset:=true;
+ end;
+
+ AS_TYPE,
+ AS_NOT,
+ AS_STRING,
+ AS_INTNUM,
+ AS_LPAREN : { Constant reference expression }
+ begin
+ if not GotPlus and not GotStar then
+ Message(asmr_e_invalid_reference_syntax);
+ BuildConstSymbolExpression(true,true,GotPlus and negative,l,tempstr,tempsymtyp);
+ { already handled by BuildConstSymbolExpression(); must be
+ handled there to avoid [reg-1+1] being interpreted as
+ [reg-(1+1)] }
+ negative:=false;
+
+ if tempstr<>'' then
+ begin
+ if GotStar then
+ Message(asmr_e_only_add_relocatable_symbol);
+ if not assigned(oper.opr.ref.symbol) then
+ oper.opr.ref.symbol:=current_asmdata.RefAsmSymbol(tempstr)
+ else
+ Message(asmr_e_cant_have_multiple_relocatable_symbols);
+ end;
+ case oper.opr.typ of
+ OPR_REFERENCE :
+ begin
+ if GotStar then
+ oper.opr.ref.scalefactor:=l
+ else if (prevasmtoken = AS_STAR) then
+ begin
+ if scale<>0 then
+ scale:=l*scale
+ else
+ scale:=l;
+ end
+ else
+ Inc(oper.opr.ref.offset,l);
+ end;
+ OPR_LOCAL :
+ begin
+ if GotStar then
+ oper.opr.localscale:=l
+ else if (prevasmtoken = AS_STAR) then
+ begin
+ if scale<>0 then
+ scale:=l*scale
+ else
+ scale:=l;
+ end
+ else
+ Inc(oper.opr.localsymofs,l);
+ end;
+ end;
+ GotPlus:=(prevasmtoken=AS_PLUS) or
+ (prevasmtoken=AS_MINUS);
+ if GotPlus then
+ negative := prevasmtoken = AS_MINUS;
+ GotStar:=(prevasmtoken=AS_STAR);
+ end;
+
+ AS_RBRACKET :
+ begin
+ if GotPlus or GotStar then
+ Message(asmr_e_invalid_reference_syntax);
+ Consume(AS_RBRACKET);
+ break;
+ end;
+
+ else
+ Begin
+ Message(asmr_e_invalid_reference_syntax);
+ RecoverConsume(true);
+ break;
+ end;
+ end;
+ until false;
+ end;
+
+
+ Procedure tx86intreader.BuildConstantOperand(oper: tx86operand);
+ var
+ l : aint;
+ tempstr : string;
+ tempsymtyp : tasmsymtype;
+ begin
+ if not (oper.opr.typ in [OPR_NONE,OPR_CONSTANT]) then
+ Message(asmr_e_invalid_operand_type);
+ BuildConstSymbolExpression(true,false,false,l,tempstr,tempsymtyp);
+ if tempstr<>'' then
+ begin
+ oper.opr.typ:=OPR_SYMBOL;
+ oper.opr.symofs:=l;
+ oper.opr.symbol:=current_asmdata.RefAsmSymbol(tempstr);
+ end
+ else
+ if oper.opr.typ=OPR_NONE then
+ begin
+ oper.opr.typ:=OPR_CONSTANT;
+ oper.opr.val:=l;
+ end
+ else
+ inc(oper.opr.val,l);
+ end;
+
+
+ Procedure tx86intreader.BuildOperand(oper: tx86operand;istypecast:boolean);
+
+ procedure AddLabelOperand(hl:tasmlabel);
+ begin
+ if (oper.opr.typ=OPR_NONE) and
+ is_calljmp(actopcode) then
+ begin
+ oper.opr.typ:=OPR_SYMBOL;
+ oper.opr.symbol:=hl;
+ end
+ else
+ begin
+ oper.InitRef;
+ oper.opr.ref.symbol:=hl;
+ end;
+ end;
+
+ var
+ expr,
+ hs : string;
+ tempreg : tregister;
+ l : aint;
+ hl : tasmlabel;
+ toffset,
+ tsize : aint;
+ begin
+ expr:='';
+ repeat
+ if actasmtoken=AS_DOT then
+ begin
+ if expr<>'' then
+ begin
+ BuildRecordOffsetSize(expr,toffset,tsize,hs,false);
+ if (oper.opr.typ<>OPR_NONE) and
+ (hs<>'') then
+ Message(asmr_e_wrong_sym_type);
+ oper.SetSize(tsize,true);
+ { we have used the size of a field. Reset the typesize of the record }
+ oper.typesize:=0;
+ case oper.opr.typ of
+ OPR_LOCAL :
+ begin
+ { don't allow direct access to fields of parameters, because that
+ will generate buggy code. Allow it only for explicit typecasting
+ and when the parameter is in a register (delphi compatible) }
+ if (not oper.hastype) and
+ (oper.opr.localsym.owner.symtabletype=parasymtable) and
+ (current_procinfo.procdef.proccalloption<>pocall_register) then
+ Message(asmr_e_cannot_access_field_directly_for_parameters);
+ inc(oper.opr.localsymofs,toffset)
+ end;
+ OPR_CONSTANT :
+ inc(oper.opr.val,toffset);
+ OPR_REFERENCE :
+ inc(oper.opr.ref.offset,toffset);
+ OPR_NONE :
+ begin
+ if (hs <> '') then
+ begin
+ oper.opr.typ:=OPR_SYMBOL;
+ oper.opr.symbol:=current_asmdata.RefAsmSymbol(hs);
+ end
+ else
+ begin
+ oper.opr.typ:=OPR_CONSTANT;
+ oper.opr.val:=toffset;
+ end;
+ end;
+ OPR_REGISTER :
+ Message(asmr_e_invalid_reference_syntax);
+ OPR_SYMBOL:
+ Message(asmr_e_invalid_symbol_ref);
+ else
+ internalerror(200309222);
+ end;
+ expr:='';
+ end
+ else
+ begin
+ { See it as a separator }
+ Consume(AS_DOT);
+ end;
+ end;
+
+ case actasmtoken of
+ AS_OFFSET,
+ AS_SIZEOF,
+ AS_VMTOFFSET,
+ AS_TYPE,
+ AS_NOT,
+ AS_STRING,
+ AS_PLUS,
+ AS_MINUS,
+ AS_LPAREN,
+ AS_INTNUM :
+ begin
+ case oper.opr.typ of
+ OPR_REFERENCE :
+ if (actasmtoken=AS_OFFSET) and
+ (cs_create_pic in current_settings.moduleswitches) then
+ begin
+ Consume(AS_OFFSET);
+ oper.opr.ref.refaddr:=addr_pic;
+ BuildOperand(oper,false);
+ end
+ else
+ inc(oper.opr.ref.offset,BuildRefConstExpression);
+ OPR_LOCAL :
+ inc(oper.opr.localsymofs,BuildConstExpression);
+ OPR_NONE,
+ OPR_CONSTANT :
+ BuildConstantOperand(oper);
+ else
+ Message(asmr_e_invalid_operand_type);
+ end;
+ end;
+
+ AS_PTR :
+ begin
+ if not oper.hastype then
+ begin
+ if (oper.opr.typ=OPR_CONSTANT) then
+ begin
+ oper.typesize:=oper.opr.val;
+ { reset constant value of operand }
+ oper.opr.typ:=OPR_NONE;
+ oper.opr.val:=0;
+ end
+ else
+ Message(asmr_e_syn_operand);
+ end;
+ Consume(AS_PTR);
+ oper.InitRef;
+ { if the operand subscripts a record, the typesize will be
+ rest -> save it here and restore it afterwards }
+ l:=oper.typesize;
+ BuildOperand(oper,false);
+ oper.setsize(l,true);
+ end;
+
+ AS_ID : { A constant expression, or a Variable ref. }
+ Begin
+ { Label or Special symbol reference? }
+ if actasmpattern[1] = '@' then
+ Begin
+ if actasmpattern = '@RESULT' then
+ Begin
+ oper.SetupResult;
+ Consume(AS_ID);
+ end
+ else
+ if (actasmpattern = '@CODE') or (actasmpattern = '@DATA') then
+ begin
+ Message(asmr_w_CODE_and_DATA_not_supported);
+ Consume(AS_ID);
+ end
+ else
+ { Local Label }
+ begin
+ CreateLocalLabel(actasmpattern,hl,false);
+ Consume(AS_ID);
+ AddLabelOperand(hl);
+ end;
+ end
+ else
+ { support result for delphi modes }
+ if (m_objpas in current_settings.modeswitches) and (actasmpattern='RESULT') then
+ begin
+ oper.SetUpResult;
+ Consume(AS_ID);
+ end
+ { probably a variable or normal expression }
+ { or a procedure (such as in CALL ID) }
+ else
+ Begin
+ { is it a constant ? }
+ if SearchIConstant(actasmpattern,l) then
+ Begin
+ case oper.opr.typ of
+ OPR_REFERENCE :
+ inc(oper.opr.ref.offset,BuildRefConstExpression);
+ OPR_LOCAL :
+ inc(oper.opr.localsymofs,BuildRefConstExpression);
+ OPR_NONE,
+ OPR_CONSTANT :
+ BuildConstantOperand(oper);
+ else
+ Message(asmr_e_invalid_operand_type);
+ end;
+ end
+ else
+ { Check for pascal label }
+ if SearchLabel(actasmpattern,hl,false) then
+ begin
+ Consume(AS_ID);
+ AddLabelOperand(hl);
+ end
+ else
+ { is it a normal variable ? }
+ Begin
+ expr:=actasmpattern;
+ Consume(AS_ID);
+ { typecasting? }
+ if SearchType(expr,l) then
+ begin
+ oper.hastype:=true;
+ oper.typesize:=l;
+ case actasmtoken of
+ AS_LPAREN :
+ begin
+ { Support Type([Reference]) }
+ Consume(AS_LPAREN);
+ BuildOperand(oper,true);
+ { Delphi also supports Type(Register) and
+ interprets it the same as Type([Register]). }
+ if (oper.opr.typ = OPR_REGISTER) then
+ { This also sets base to the register. }
+ oper.InitRef;
+ Consume(AS_RPAREN);
+ end;
+ AS_LBRACKET :
+ begin
+ { Support Var.Type[Index] }
+ { Convert @label.Byte[1] to reference }
+ if oper.opr.typ=OPR_SYMBOL then
+ oper.initref;
+ end;
+ end;
+ end
+ else
+ begin
+ if not oper.SetupVar(expr,false) then
+ Begin
+ { not a variable, check special variables.. }
+ if expr = 'SELF' then
+ oper.SetupSelf
+ else
+ Message1(sym_e_unknown_id,expr);
+ expr:='';
+ end;
+ { indexed access to variable? }
+ if actasmtoken=AS_LBRACKET then
+ begin
+ { ... then the operand size is not known anymore }
+ oper.size:=OS_NO;
+ BuildReference(oper);
+ end;
+ end;
+ end;
+ end;
+ end;
+
+ AS_REGISTER : { Register, a variable reference or a constant reference }
+ begin
+ { save the type of register used. }
+ tempreg:=actasmregister;
+ Consume(AS_REGISTER);
+ if actasmtoken = AS_COLON then
+ Begin
+ Consume(AS_COLON);
+ oper.InitRef;
+ oper.opr.ref.segment:=tempreg;
+ BuildReference(oper);
+ end
+ else
+ { Simple register }
+ begin
+ if (oper.opr.typ <> OPR_NONE) then
+ Message(asmr_e_syn_operand);
+ oper.opr.typ:=OPR_REGISTER;
+ oper.opr.reg:=tempreg;
+ oper.SetSize(tcgsize2size[reg_cgsize(oper.opr.reg)],true);
+ end;
+ end;
+
+ AS_LBRACKET: { a variable reference, register ref. or a constant reference }
+ Begin
+ BuildReference(oper);
+ end;
+
+ AS_SEG :
+ Begin
+ Message(asmr_e_seg_not_supported);
+ Consume(actasmtoken);
+ end;
+
+ AS_DWORD,
+ AS_BYTE,
+ AS_WORD,
+ AS_TBYTE,
+ AS_DQWORD,
+ AS_QWORD :
+ begin
+ { Type specifier }
+ oper.hastype:=true;
+ oper.typesize:=0;
+ case actasmtoken of
+ AS_DWORD : oper.typesize:=4;
+ AS_WORD : oper.typesize:=2;
+ AS_BYTE : oper.typesize:=1;
+ AS_QWORD : oper.typesize:=8;
+ AS_DQWORD : oper.typesize:=16;
+ AS_TBYTE : oper.typesize:=10;
+ else
+ internalerror(2010061101);
+ end;
+ Consume(actasmtoken);
+ if (actasmtoken=AS_LPAREN) then
+ begin
+ { Support "xxx ptr [Reference]" }
+ { in case the expression subscripts a record, the typesize
+ is reset, so save the explicit size we set above }
+ l:=oper.typesize;
+ Consume(AS_LPAREN);
+ BuildOperand(oper,true);
+ Consume(AS_RPAREN);
+ oper.setsize(l,true);
+ end;
+ end;
+
+ AS_SEPARATOR,
+ AS_END,
+ AS_COMMA,
+ AS_COLON:
+ begin
+ break;
+ end;
+
+ AS_RPAREN:
+ begin
+ if not istypecast then
+ begin
+ Message(asmr_e_syn_operand);
+ Consume(AS_RPAREN);
+ end
+ else
+ break;
+ end;
+
+ else
+ begin
+ Message(asmr_e_syn_operand);
+ RecoverConsume(true);
+ break;
+ end;
+ end;
+ until false;
+ { End of operand, update size if a typecast is forced }
+ if (oper.typesize<>0) and
+ (oper.opr.typ in [OPR_REFERENCE,OPR_LOCAL]) then
+ oper.SetSize(oper.typesize,true);
+ end;
+
+
+ Procedure tx86intreader.BuildOpCode(instr : tx86instruction);
+ var
+ PrefixOp,OverrideOp: tasmop;
+ operandnum : longint;
+ is_far_const:boolean;
+ i:byte;
+ begin
+ PrefixOp:=A_None;
+ OverrideOp:=A_None;
+ is_far_const:=false;
+ { prefix seg opcode / prefix opcode }
+ repeat
+ if is_prefix(actopcode) then
+ with instr do
+ begin
+ OpOrder:=op_intel;
+ PrefixOp:=ActOpcode;
+ opcode:=ActOpcode;
+ condition:=ActCondition;
+ opsize:=ActOpsize;
+ ConcatInstruction(curlist);
+ consume(AS_OPCODE);
+ end
+ else
+ if is_override(actopcode) then
+ with instr do
+ begin
+ OpOrder:=op_intel;
+ OverrideOp:=ActOpcode;
+ opcode:=ActOpcode;
+ condition:=ActCondition;
+ opsize:=ActOpsize;
+ ConcatInstruction(curlist);
+ consume(AS_OPCODE);
+ end
+ else
+ break;
+ { allow for newline after prefix or override }
+ while actasmtoken=AS_SEPARATOR do
+ consume(AS_SEPARATOR);
+ until (actasmtoken<>AS_OPCODE);
+ { opcode }
+ if (actasmtoken <> AS_OPCODE) then
+ begin
+ Message(asmr_e_invalid_or_missing_opcode);
+ RecoverConsume(false);
+ exit;
+ end;
+ { Fill the instr object with the current state }
+ with instr do
+ begin
+ OpOrder:=op_intel;
+ Opcode:=ActOpcode;
+ condition:=ActCondition;
+ opsize:=ActOpsize;
+
+ { Valid combination of prefix/override and instruction ? }
+ if (prefixop<>A_NONE) and (NOT CheckPrefix(PrefixOp,actopcode)) then
+ Message1(asmr_e_invalid_prefix_and_opcode,actasmpattern);
+ if (overrideop<>A_NONE) and (NOT CheckOverride(OverrideOp,ActOpcode)) then
+ Message1(asmr_e_invalid_override_and_opcode,actasmpattern);
+ end;
+ { pushf/popf/pusha/popa have to default to 16 bit in Intel mode
+ (Intel manual and Delphi-compatbile) -- setting the opsize for
+ these instructions doesn't change anything in the internal assember,
+ so change the opcode }
+ if (instr.opcode=A_POPF) then
+ instr.opcode:=A_POPFW
+ else if (instr.opcode=A_PUSHF) then
+ instr.opcode:=A_PUSHFW
+ else if (instr.opcode=A_PUSHA) then
+ instr.opcode:=A_PUSHAW
+ else if (instr.opcode=A_POPA) then
+ instr.opcode:=A_POPAW;
+ { We are reading operands, so opcode will be an AS_ID }
+ operandnum:=1;
+ is_far_const:=false;
+ Consume(AS_OPCODE);
+ { Zero operand opcode ? }
+ if actasmtoken in [AS_SEPARATOR,AS_END] then
+ begin
+ operandnum:=0;
+ exit;
+ end;
+ { Read Operands }
+ repeat
+ case actasmtoken of
+ { End of asm operands for this opcode }
+ AS_END,
+ AS_SEPARATOR :
+ break;
+
+ { Operand delimiter }
+ AS_COMMA :
+ begin
+ if operandnum > Max_Operands then
+ Message(asmr_e_too_many_operands)
+ else
+ Inc(operandnum);
+ Consume(AS_COMMA);
+ end;
+
+ {Far constant, i.e. jmp $0000:$11111111.}
+ AS_COLON:
+ begin
+ is_far_const:=true;
+ if operandnum>1 then
+ message(asmr_e_too_many_operands)
+ else
+ inc(operandnum);
+ consume(AS_COLON);
+ end;
+
+ { Type specifier }
+ AS_NEAR,
+ AS_FAR :
+ begin
+ if actasmtoken = AS_NEAR then
+ begin
+ Message(asmr_w_near_ignored);
+ instr.opsize:=S_NEAR;
+ end
+ else
+ begin
+ Message(asmr_w_far_ignored);
+ instr.opsize:=S_FAR;
+ end;
+ Consume(actasmtoken);
+ if actasmtoken=AS_PTR then
+ begin
+ Consume(AS_PTR);
+ instr.Operands[operandnum].InitRef;
+ end;
+ BuildOperand(instr.Operands[operandnum] as tx86operand,false);
+ end;
+ else
+ BuildOperand(instr.Operands[operandnum] as tx86operand,false);
+ end; { end case }
+ until false;
+ instr.ops:=operandnum;
+ { Check operands }
+ for i:=1 to operandnum do
+ begin
+ if is_far_const and
+ (instr.operands[i].opr.typ<>OPR_CONSTANT) then
+ message(asmr_e_expr_illegal)
+ else
+ if instr.operands[i].opr.typ=OPR_NONE then
+ Message(asmr_e_syntax_error);
+ end;
+ { e.g. for "push dword 1", "push word 6" }
+ if (instr.ops=1) and
+ (instr.operands[1].typesize<>0) then
+ instr.operands[1].setsize(instr.operands[1].typesize,false);
+ end;
+
+
+ Procedure tx86intreader.BuildConstant(constsize: byte);
+ var
+ asmsymtyp : tasmsymtype;
+ asmsym,
+ expr: string;
+ value : aint;
+ Begin
+ Repeat
+ Case actasmtoken of
+ AS_STRING:
+ Begin
+ { DD and DW cases }
+ if constsize <> 1 then
+ Begin
+ if Not PadZero(actasmpattern,constsize) then
+ Message(scan_f_string_exceeds_line);
+ end;
+ expr:=actasmpattern;
+ Consume(AS_STRING);
+ Case actasmtoken of
+ AS_COMMA:
+ Consume(AS_COMMA);
+ AS_END,
+ AS_SEPARATOR: ;
+ else
+ Message(asmr_e_invalid_string_expression);
+ end;
+ ConcatString(curlist,expr);
+ end;
+ AS_PLUS,
+ AS_MINUS,
+ AS_LPAREN,
+ AS_NOT,
+ AS_INTNUM,
+ AS_ID :
+ Begin
+ BuildConstSymbolExpression(false,false,false,value,asmsym,asmsymtyp);
+ if asmsym<>'' then
+ begin
+ if constsize<>sizeof(pint) then
+ Message1(asmr_w_const32bit_for_address,asmsym);
+ ConcatConstSymbol(curlist,asmsym,asmsymtyp,value)
+ end
+ else
+ ConcatConstant(curlist,value,constsize);
+ end;
+ AS_COMMA:
+ begin
+ Consume(AS_COMMA);
+ end;
+ AS_ALIGN,
+ AS_DB,
+ AS_DW,
+ AS_DD,
+ AS_DQ,
+ AS_OPCODE,
+ AS_END,
+ AS_SEPARATOR:
+ break;
+ else
+ begin
+ Message(asmr_e_syn_constant);
+ RecoverConsume(false);
+ end
+ end;
+ Until false;
+ end;
+
+
+ function tx86intreader.Assemble: tlinkedlist;
+ Var
+ hl : tasmlabel;
+ instr : Tx86Instruction;
+ Begin
+ Message1(asmr_d_start_reading,'intel');
+ inexpression:=FALSE;
+ firsttoken:=TRUE;
+ { sets up all opcode and register tables in uppercase
+ done in the construtor now
+ if not _asmsorted then
+ Begin
+ SetupTables;
+ _asmsorted:=TRUE;
+ end;
+ }
+ curlist:=TAsmList.Create;
+ { setup label linked list }
+ LocalLabelList:=TLocalLabelList.Create;
+ { we might need to know which parameters are passed in registers }
+ current_procinfo.generate_parameter_info;
+ { start tokenizer }
+ c:=current_scanner.asmgetcharstart;
+ gettoken;
+ { main loop }
+ repeat
+ case actasmtoken of
+ AS_LLABEL:
+ Begin
+ if CreateLocalLabel(actasmpattern,hl,true) then
+ ConcatLabel(curlist,hl);
+ Consume(AS_LLABEL);
+ end;
+
+ AS_LABEL:
+ Begin
+ if SearchLabel(upper(actasmpattern),hl,true) then
+ ConcatLabel(curlist,hl)
+ else
+ Message1(asmr_e_unknown_label_identifier,actasmpattern);
+ Consume(AS_LABEL);
+ end;
+
+ AS_DW :
+ Begin
+ inexpression:=true;
+ Consume(AS_DW);
+ BuildConstant(2);
+ inexpression:=false;
+ end;
+
+ AS_DB :
+ Begin
+ inexpression:=true;
+ Consume(AS_DB);
+ BuildConstant(1);
+ inexpression:=false;
+ end;
+
+ AS_DD :
+ Begin
+ inexpression:=true;
+ Consume(AS_DD);
+ BuildConstant(4);
+ inexpression:=false;
+ end;
+
+{$ifdef cpu64bitaddr}
+ AS_DQ:
+ Begin
+ inexpression:=true;
+ Consume(AS_DQ);
+ BuildConstant(8);
+ inexpression:=false;
+ end;
+{$endif cpu64bitaddr}
+
+ AS_ALIGN:
+ Begin
+ Consume(AS_ALIGN);
+ ConcatAlign(curlist,BuildConstExpression);
+ if actasmtoken<>AS_SEPARATOR then
+ Consume(AS_SEPARATOR);
+ end;
+
+ AS_OPCODE :
+ Begin
+ instr:=Tx86Instruction.Create(Tx86Operand);
+ BuildOpcode(instr);
+ with instr do
+ begin
+ { We need AT&T style operands }
+ Swapoperands;
+ { Must be done with args in ATT order }
+ CheckNonCommutativeOpcodes;
+ AddReferenceSizes;
+ SetInstructionOpsize;
+ CheckOperandSizes;
+ ConcatInstruction(curlist);
+ end;
+ instr.Free;
+ end;
+
+ AS_SEPARATOR :
+ Begin
+ Consume(AS_SEPARATOR);
+ end;
+
+ AS_END :
+ break; { end assembly block }
+
+ else
+ Begin
+ Message(asmr_e_syntax_error);
+ RecoverConsume(false);
+ end;
+ end; { end case }
+ until false;
+ { Check LocalLabelList }
+ LocalLabelList.CheckEmitted;
+ LocalLabelList.Free;
+ { Return the list in an asmnode }
+ assemble:=curlist;
+ Message1(asmr_d_finish_reading,'intel');
+ end;
+
+
+end.
diff --git a/closures/compiler/x86/rgx86.pas b/closures/compiler/x86/rgx86.pas
new file mode 100644
index 0000000000..b0688e7f23
--- /dev/null
+++ b/closures/compiler/x86/rgx86.pas
@@ -0,0 +1,413 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit implements the x86 specific class for the register
+ allocator
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+
+unit rgx86;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ cclasses,globtype,
+ cpubase,cpuinfo,cgbase,cgutils,
+ aasmbase,aasmtai,aasmdata,aasmcpu,
+ rgobj;
+
+ type
+ trgx86 = class(trgobj)
+ function get_spill_subreg(r : tregister) : tsubregister;override;
+ function do_spill_replace(list:TAsmList;instr:taicpu;orgreg:tsuperregister;const spilltemp:treference):boolean;override;
+ end;
+
+ tpushedsavedloc = record
+ case byte of
+ 0: (pushed: boolean);
+ 1: (ofs: longint);
+ end;
+
+ tpushedsavedfpu = array[tsuperregister] of tpushedsavedloc;
+
+ trgx86fpu = class
+ { The "usableregsxxx" contain all registers of type "xxx" that }
+ { aren't currently allocated to a regvar. The "unusedregsxxx" }
+ { contain all registers of type "xxx" that aren't currently }
+ { allocated }
+ unusedregsfpu,usableregsfpu : Tsuperregisterset;
+ { these counters contain the number of elements in the }
+ { unusedregsxxx/usableregsxxx sets }
+ countunusedregsfpu : byte;
+
+ { Contains the registers which are really used by the proc itself.
+ It doesn't take care of registers used by called procedures
+ }
+ used_in_proc : tcpuregisterset;
+
+ {reg_pushes_other : regvarother_longintarray;
+ is_reg_var_other : regvarother_booleanarray;
+ regvar_loaded_other : regvarother_booleanarray;}
+
+ fpuvaroffset : byte;
+
+ constructor create;
+
+ function getregisterfpu(list: TAsmList) : tregister;
+ procedure ungetregisterfpu(list: TAsmList; r : tregister);
+
+ { pushes and restores registers }
+ procedure saveusedfpuregisters(list:TAsmList;
+ var saved:Tpushedsavedfpu;
+ const s:Tcpuregisterset);
+ procedure restoreusedfpuregisters(list:TAsmList;
+ const saved:Tpushedsavedfpu);
+
+ { corrects the fpu stack register by ofs }
+ function correct_fpuregister(r : tregister;ofs : byte) : tregister;
+ end;
+
+
+implementation
+
+ uses
+ systems,
+ verbose;
+
+ const
+ { This value is used in tsaved. If the array value is equal
+ to this, then this means that this register is not used.}
+ reg_not_saved = $7fffffff;
+
+
+{******************************************************************************
+ Trgcpu
+******************************************************************************}
+
+ function trgx86.get_spill_subreg(r : tregister) : tsubregister;
+ begin
+ result:=getsubreg(r);
+ end;
+
+
+ function trgx86.do_spill_replace(list:TAsmList;instr:taicpu;orgreg:tsuperregister;const spilltemp:treference):boolean;
+
+ {Decide wether a "replace" spill is possible, i.e. wether we can replace a register
+ in an instruction by a memory reference. For example, in "mov ireg26d,0", the imaginary
+ register ireg26d can be replaced by a memory reference.}
+
+ var
+ n,replaceoper : longint;
+ begin
+ result:=false;
+ with instr do
+ begin
+ replaceoper:=-1;
+ case ops of
+ 1 :
+ begin
+ if (oper[0]^.typ=top_reg) and
+ (getregtype(oper[0]^.reg)=regtype) then
+ begin
+ if get_alias(getsupreg(oper[0]^.reg))<>orgreg then
+ internalerror(200410101);
+ replaceoper:=0;
+ end;
+ end;
+ 2,3 :
+ begin
+ { We can handle opcodes with 2 and 3 operands the same way. The opcodes
+ with 3 registers are shrd/shld, where the 3rd operand is const or CL,
+ that doesn't need spilling.
+ However, due to AT&T order inside the compiler, the 3rd operand is
+ numbered 0, so look at operand no. 1 and 2 if we have 3 operands by
+ adding a "n". }
+ n:=0;
+ if ops=3 then
+ n:=1;
+ if (oper[n+0]^.typ=top_reg) and
+ (oper[n+1]^.typ=top_reg) and
+ ((getregtype(oper[n+0]^.reg)<>regtype) or
+ (getregtype(oper[n+1]^.reg)<>regtype) or
+ (get_alias(getsupreg(oper[n+0]^.reg))<>get_alias(getsupreg(oper[n+1]^.reg)))) then
+ begin
+ if (getregtype(oper[n+0]^.reg)=regtype) and
+ (get_alias(getsupreg(oper[n+0]^.reg))=orgreg) then
+ replaceoper:=0+n
+ else if (getregtype(oper[n+1]^.reg)=regtype) and
+ (get_alias(getsupreg(oper[n+1]^.reg))=orgreg) then
+ replaceoper:=1+n;
+ end
+ else if (oper[n+0]^.typ=top_reg) and
+ (oper[n+1]^.typ=top_const) then
+ begin
+ if (getregtype(oper[0+n]^.reg)=regtype) and
+ (get_alias(getsupreg(oper[0+n]^.reg))=orgreg) then
+ replaceoper:=0+n
+ else
+ internalerror(200704282);
+ end
+ else if (oper[n+0]^.typ=top_const) and
+ (oper[n+1]^.typ=top_reg) then
+ begin
+ if (getregtype(oper[1+n]^.reg)=regtype) and
+ (get_alias(getsupreg(oper[1+n]^.reg))=orgreg) then
+ replaceoper:=1+n
+ else
+ internalerror(200704283);
+ end;
+ case replaceoper of
+ 0 :
+ begin
+ { Some instructions don't allow memory references
+ for source }
+ case instr.opcode of
+ A_BT,
+ A_BTS,
+ A_BTC,
+ A_BTR,
+
+ { shufp* would require 16 byte alignment for memory locations so we force the source
+ operand into a register }
+ A_SHUFPD,
+ A_SHUFPS :
+ replaceoper:=-1;
+ end;
+ end;
+ 1 :
+ begin
+ { Some instructions don't allow memory references
+ for destination }
+ case instr.opcode of
+ A_CMOVcc,
+ A_MOVZX,
+ A_MOVSX,
+ A_MOVSXD,
+ A_MULSS,
+ A_MULSD,
+ A_SUBSS,
+ A_SUBSD,
+ A_ADDSD,
+ A_ADDSS,
+ A_DIVSD,
+ A_DIVSS,
+ A_SHLD,
+ A_SHRD,
+ A_CVTDQ2PD,
+ A_CVTDQ2PS,
+ A_CVTPD2DQ,
+ A_CVTPD2PI,
+ A_CVTPD2PS,
+ A_CVTPI2PD,
+ A_CVTPS2DQ,
+ A_CVTPS2PD,
+ A_CVTSD2SI,
+ A_CVTSD2SS,
+ A_CVTSI2SD,
+ A_CVTSS2SD,
+ A_CVTTPD2PI,
+ A_CVTTPD2DQ,
+ A_CVTTPS2DQ,
+ A_CVTTSD2SI,
+ A_CVTPI2PS,
+ A_CVTPS2PI,
+ A_CVTSI2SS,
+ A_CVTSS2SI,
+ A_CVTTPS2PI,
+ A_CVTTSS2SI,
+ A_IMUL,
+ A_XORPD,
+ A_XORPS,
+ A_ORPD,
+ A_ORPS,
+ A_ANDPD,
+ A_ANDPS,
+ A_UNPCKLPS,
+ A_UNPCKHPS,
+ A_SHUFPD,
+ A_SHUFPS:
+
+ replaceoper:=-1;
+{$ifdef x86_64}
+ A_MOV:
+ { 64 bit constants can only be moved into registers }
+ if (oper[0]^.typ=top_const) and
+ (oper[1]^.typ=top_reg) and
+ ((oper[0]^.val<low(longint)) or
+ (oper[0]^.val>high(longint))) then
+ replaceoper:=-1;
+{$endif x86_64}
+ end;
+ end;
+ end;
+ end;
+ end;
+
+ {$ifdef x86_64}
+ { 32 bit operations on 32 bit registers on x86_64 can result in
+ zeroing the upper 32 bits of the register. This does not happen
+ with memory operations, so we have to perform these calculations
+ in registers. }
+ if (instr.opsize=S_L) then
+ replaceoper:=-1;
+ {$endif x86_64}
+
+ { Replace register with spill reference }
+ if replaceoper<>-1 then
+ begin
+ oper[replaceoper]^.typ:=top_ref;
+ new(oper[replaceoper]^.ref);
+ oper[replaceoper]^.ref^:=spilltemp;
+ { memory locations aren't guaranteed to be aligned }
+ case opcode of
+ A_MOVAPS:
+ opcode:=A_MOVSS;
+ A_MOVAPD:
+ opcode:=A_MOVSD;
+ end;
+ result:=true;
+ end;
+ end;
+ end;
+
+
+{******************************************************************************
+ Trgx86fpu
+******************************************************************************}
+
+ constructor Trgx86fpu.create;
+ begin
+ used_in_proc:=[];
+ unusedregsfpu:=usableregsfpu;
+ end;
+
+
+ function trgx86fpu.getregisterfpu(list: TAsmList) : tregister;
+ begin
+ { note: don't return R_ST0, see comments above implementation of }
+ { a_loadfpu_* methods in cgcpu (JM) }
+ result:=NR_ST;
+ end;
+
+
+ procedure trgx86fpu.ungetregisterfpu(list : TAsmList; r : tregister);
+ begin
+ { nothing to do, fpu stack management is handled by the load/ }
+ { store operations in cgcpu (JM) }
+ end;
+
+
+
+ function trgx86fpu.correct_fpuregister(r : tregister;ofs : byte) : tregister;
+ begin
+ correct_fpuregister:=r;
+ setsupreg(correct_fpuregister,ofs);
+ end;
+
+
+ procedure trgx86fpu.saveusedfpuregisters(list: TAsmList;
+ var saved : tpushedsavedfpu;
+ const s: tcpuregisterset);
+ { var
+ r : tregister;
+ hr : treference; }
+ begin
+ used_in_proc:=used_in_proc+s;
+
+{ TODO: firstsavefpureg}
+(*
+ { don't try to save the fpu registers if not desired (e.g. for }
+ { the 80x86) }
+ if firstsavefpureg <> R_NO then
+ for r.enum:=firstsavefpureg to lastsavefpureg do
+ begin
+ saved[r.enum].ofs:=reg_not_saved;
+ { if the register is used by the calling subroutine and if }
+ { it's not a regvar (those are handled separately) }
+ if not is_reg_var_other[r.enum] and
+ (r.enum in s) and
+ { and is present in use }
+ not(r.enum in unusedregsfpu) then
+ begin
+ { then save it }
+ tg.GetTemp(list,extended_size,tt_persistent,hr);
+ saved[r.enum].ofs:=hr.offset;
+ cg.a_loadfpu_reg_ref(list,OS_FLOAT,OS_FLOAT,r,hr);
+ cg.a_reg_dealloc(list,r);
+ include(unusedregsfpu,r.enum);
+ inc(countunusedregsfpu);
+ end;
+ end;
+*)
+ end;
+
+
+ procedure trgx86fpu.restoreusedfpuregisters(list : TAsmList;
+ const saved : tpushedsavedfpu);
+{
+ var
+ r,r2 : tregister;
+ hr : treference;
+}
+ begin
+{ TODO: firstsavefpureg}
+(*
+ if firstsavefpureg <> R_NO then
+ for r.enum:=lastsavefpureg downto firstsavefpureg do
+ begin
+ if saved[r.enum].ofs <> reg_not_saved then
+ begin
+ r2.enum:=R_INTREGISTER;
+ r2.number:=NR_FRAME_POINTER_REG;
+ reference_reset_base(hr,r2,saved[r.enum].ofs);
+ cg.a_reg_alloc(list,r);
+ cg.a_loadfpu_ref_reg(list,OS_FLOAT,OS_FLOAT,hr,r);
+ if not (r.enum in unusedregsfpu) then
+ { internalerror(10)
+ in n386cal we always save/restore the reg *state*
+ using save/restoreunusedstate -> the current state
+ may not be real (JM) }
+ else
+ begin
+ dec(countunusedregsfpu);
+ exclude(unusedregsfpu,r.enum);
+ end;
+ tg.UnGetTemp(list,hr);
+ end;
+ end;
+*)
+ end;
+
+(*
+ procedure Trgx86fpu.saveotherregvars(list: TAsmList; const s: totherregisterset);
+ var
+ r: Tregister;
+ begin
+ if not(cs_opt_regvar in current_settings.optimizerswitches) then
+ exit;
+ if firstsavefpureg <> NR_NO then
+ for r.enum := firstsavefpureg to lastsavefpureg do
+ if is_reg_var_other[r.enum] and
+ (r.enum in s) then
+ store_regvar(list,r);
+ end;
+*)
+
+end.
diff --git a/closures/compiler/x86/x86ins.dat b/closures/compiler/x86/x86ins.dat
new file mode 100644
index 0000000000..662ac07f0c
--- /dev/null
+++ b/closures/compiler/x86/x86ins.dat
@@ -0,0 +1,3439 @@
+;
+; Table of assembler instructions for Free Pascal
+; adapted from Netwide Assembler by Peter Vreman
+;
+; The Netwide Assembler is copyright (C) 1996 Simon Tatham and
+; Julian Hall. All rights reserved.
+;
+; Layout
+; [OPCODE,attnameX] (X means suffix in att name)
+; arguments bytes flags
+;
+
+[NONE]
+(Ch_None, Ch_None, Ch_None)
+void void none
+
+[AAA]
+(Ch_MEAX, Ch_WFlags, Ch_None)
+void \1\x37 8086,NOX86_64
+
+[AAD,aadX]
+(Ch_MEAX, Ch_WFlags, Ch_None)
+void \2\xD5\x0A 8086,NOX86_64
+imm \1\xD5\24 8086,SB,NOX86_64
+
+[AAM,aamX]
+(Ch_MEAX, Ch_WFlags, Ch_None)
+void \2\xD4\x0A 8086,NOX86_64
+imm \1\xD4\24 8086,SB,NOX86_64
+
+[AAS]
+(Ch_MEAX, Ch_WFlags, Ch_None)
+void \1\x3F 8086,NOX86_64
+
+[ADC,adcX]
+(Ch_Mop2, Ch_Rop1, Ch_RWFlags)
+regmem,reg16|32|64 \320\1\x11\101 8086,SM
+reg16|32|64,regmem \320\1\x13\110 8086,SM
+rm8,reg8 \1\x10\101 8086
+reg8,rm8 \1\x12\110 8086
+rm16|32|64,imm8 \320\1\x83\202\15 8086
+reg_eax,imm \325\1\x15\41 386,SM
+reg_rax,imm \326\1\x15\255 X86_64,SM
+rm32,imm \325\1\x81\202\41 386,SM
+rm64,imm \326\1\x81\202\255 X86_64,SM
+reg_ax,imm \324\1\x15\31 8086,SW
+rm16,imm \324\1\x81\202\31 8086,SW
+reg_al,imm \1\x14\21 8086,SB
+rm8,imm \1\x80\202\21 8086,SB
+
+[ADD,addX]
+(Ch_Mop2, Ch_Rop1, Ch_WFlags)
+regmem,reg16|32|64 \320\1\x01\101 8086,SM
+reg16|32|64,regmem \320\1\x03\110 8086,SM
+rm8,reg8 \1\x00\101 8086
+reg8,rm8 \1\x02\110 8086,SM
+rm16|32|64,imm8 \320\1\x83\200\15 8086
+reg_eax,imm \320\1\x05\41 386,SM
+reg_rax,imm \326\1\x05\255 X86_64,SM
+rm32,imm \325\1\x81\200\41 386,SM
+rm64,imm \326\1\x81\200\255 X86_64,SM
+reg_ax,imm \324\1\x05\31 8086,SW
+rm16,imm \324\1\x81\200\31 8086,SW
+reg_al,imm \1\x04\21 8086,SB
+rm8,imm \1\x80\200\21 8086,SB
+
+[AND,andX]
+(Ch_Mop2, Ch_Rop1, Ch_WFlags)
+regmem,reg16|32|64 \320\1\x21\101 8086,SM
+reg16|32|64,regmem \320\1\x23\110 8086,SM
+rm8,reg8 \1\x20\101 8086
+reg8,rm8 \1\x22\110 8086
+rm16|32|64,imm8 \320\1\x83\204\15 8086
+reg_eax,imm \325\1\x25\41 386,SM
+reg_rax,imm \326\1\x25\255 X86_64,SM
+rm32,imm \325\1\x81\204\41 386,SM
+rm64,imm \326\1\x81\204\255 X86_64,SM
+reg_ax,imm \324\1\x25\31 8086,SW
+rm16,imm \324\1\x81\204\31 8086,SW
+reg_al,imm \1\x24\21 8086,SB
+rm8,imm \1\x80\204\21 8086,SB
+
+[ARPL,arplX]
+(Ch_WFlags, Ch_None, Ch_None)
+reg16,reg16 \1\x63\101 286,PROT,NOX86_64
+mem,reg16 \1\x63\101 286,PROT,SM,NOX86_64
+
+[BOUND,boundX]
+(Ch_Rop1, Ch_None, Ch_None)
+reg16|32,mem \320\1\x62\110 186,NOX86_64
+
+[BSF,bsfX]
+(Ch_Wop2, Ch_WFlags, Ch_Rop1)
+reg16|32|64,regmem \320\2\x0F\xBC\110 386,SM
+
+[BSR,bsrX]
+(Ch_Wop2, Ch_WFlags, Ch_Rop1)
+reg16|32|64,regmem \320\2\x0F\xBD\110 386,SM
+
+[BSWAP,bswapX]
+(Ch_MOp1, Ch_None, Ch_None)
+reg32|64 \320\1\x0F\10\xC8 486
+
+[BT,btX]
+(Ch_WFlags, Ch_Rop1, Ch_Rop2)
+regmem,reg16|32|64 \320\2\x0F\xA3\101 386,SM
+rm16|32|64,imm \320\2\x0F\xBA\204\25 386,SB
+
+[BTC,btcX]
+(Ch_Mop2, Ch_Rop1, Ch_WFlags)
+regmem,reg16|32|64 \320\2\x0F\xBB\101 386,SM
+rm16|32|64,imm \320\2\x0F\xBA\207\25 386,SB
+
+[BTR,btrX]
+(Ch_Mop2, Ch_Rop1, Ch_WFlags)
+regmem,reg16|32|64 \320\2\x0F\xB3\101 386,SM
+rm16|32|64,imm \320\2\x0F\xBA\206\25 386,SB
+
+[BTS,btsX]
+(Ch_Mop2, Ch_Rop1, Ch_WFlags)
+regmem,reg16|32|64 \320\2\x0F\xAB\101 386,SM
+rm16|32|64,imm \320\2\x0F\xBA\205\25 386,SB
+
+[CALL,call]
+; don't know value of any register
+(Ch_ROp1, Ch_All, Ch_None)
+; Compiler emits CALL/JMP with opsize=S_NO which matches any size,
+; and will match the first entry in sequence.
+; Therefore rm16 must be placed after rm32/rm64
+rm32 \325\1\xFF\202 386,NOX86_64
+rm64 \335\1\xFF\202 X86_64
+rm16 \324\1\xFF\202 8086
+imm \320\1\xE8\64 8086
+imm|near \320\1\xE8\64 8086
+imm|far \320\1\x9A\34\37 8086,ND,NOX86_64
+mem|near \320\1\xFF\202 8086
+mem|far \320\1\xFF\203 8086
+imm:imm \327\1\x9A\35\30 8086,NOX86_64
+imm16:imm \324\1\x9A\31\30 8086,NOX86_64
+imm:imm16 \324\1\x9A\31\30 8086,NOX86_64
+imm32:imm \325\1\x9A\41\30 386,NOX86_64
+imm:imm32 \325\1\x9A\41\30 386,NOX86_64
+
+[CBW,cbtw]
+(Ch_MEAX, Ch_None, Ch_None)
+void \324\1\x98 8086
+
+[CDQ,cltd]
+(Ch_MEAX, Ch_WEDX, Ch_None)
+void \325\1\x99 386
+
+[CLC]
+(Ch_WFlags, Ch_None, Ch_None)
+void \1\xF8 8086
+
+[CLD]
+(Ch_CDirFlag, Ch_None, Ch_None)
+void \1\xFC 8086
+
+[CLI]
+(Ch_WFlags, Ch_None, Ch_None)
+void \1\xFA 8086
+
+[CLTS]
+(Ch_None, Ch_None, Ch_None)
+void \2\x0F\x06 286,PRIV
+
+[CMC]
+(Ch_WFlags, Ch_None, Ch_None)
+void \1\xF5 8086
+
+[CMP,cmpX]
+(Ch_ROp1, Ch_ROp2, Ch_WFlags)
+regmem,reg16|32|64 \320\1\x39\101 8086,SM
+reg16|32|64,regmem \320\1\x3B\110 8086,SM
+rm8,reg8 \1\x38\101 8086
+reg8,rm8 \1\x3A\110 8086
+rm16|32|64,imm8 \320\1\x83\207\15 8086
+reg_eax,imm \325\1\x3D\41 386,SM
+reg_rax,imm \326\1\x3D\255 X86_64,SM
+rm32,imm \325\1\x81\207\41 386,SM
+rm64,imm \326\1\x81\207\255 X86_64,SM
+reg_ax,imm \324\1\x3D\31 8086,SW
+rm16,imm \324\1\x81\207\31 8086,SW
+reg_al,imm \1\x3C\21 8086,SB
+rm8,imm \1\x80\207\21 8086,SB
+mem,imm32 \325\1\x81\207\41 386,SD
+mem,imm16 \324\1\x81\207\31 8086,SW
+mem,imm8 \1\x80\207\21 8086,SB
+
+[CMPSB]
+(Ch_All, Ch_None, Ch_None)
+void \332\1\xA6 8086
+
+[CMPSD,cmpsl]
+(Ch_All, Ch_None, Ch_None)
+void \332\325\1\xA7 386
+xmmreg,xmmrm,imm \334\2\x0F\xC2\110\26 WILLAMETTE,SSE2,SM2,SB,AR2
+
+[CMPSW]
+(Ch_All, Ch_None, Ch_None)
+void \332\324\1\xA7 8086
+
+[CMPXCHG,cmpxchgX]
+(Ch_All, Ch_None, Ch_None)
+regmem,reg16|32|64 \320\2\x0F\xB1\101 PENT,SM
+rm8,reg8 \2\x0F\xB0\101 PENT
+
+[CMPXCHG486,cmpxchg486X]
+(Ch_All, Ch_None, Ch_None)
+regmem,reg16|32|64 \320\2\x0F\xA7\101 486,SM
+rm8,reg8 \2\x0F\xA6\101 486,UNDOC
+
+[CMPXCHG8B,cmpxchg8b]
+(Ch_All, Ch_None, Ch_None)
+mem \2\x0F\xC7\201 PENT
+
+[CPUID]
+(Ch_All, Ch_None, Ch_none)
+void \2\x0F\xA2 PENT
+
+[CWD]
+(Ch_MEAX, Ch_WEDX, Ch_None)
+void \324\1\x99 8086
+
+[CWDE,cwtl]
+(Ch_MEAX, Ch_None, Ch_None)
+void \325\1\x98 386
+
+[DAA]
+(Ch_MEAX, Ch_None, Ch_None)
+void \1\x27 8086,NOX86_64
+
+[DAS]
+(Ch_MEAX, Ch_None, Ch_None)
+void \1\x2F 8086,NOX86_64
+
+[DEC,decX]
+(Ch_Mop1, Ch_WFlags, Ch_None)
+reg16|32 \320\10\x48 8086,NOX86_64
+rm16|32|64 \320\1\xFF\201 8086
+rm8 \1\xFE\201 8086
+
+[DIV,divX]
+(Ch_RWEAX, Ch_WEDX, Ch_WFlags)
+rm16|32|64 \320\1\xF7\206 8086
+rm8 \1\xF6\206 8086
+
+[EMMS]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\x0F\x77 PENT,MMX
+
+[ENTER,enterX]
+(Ch_RWESP, Ch_None, Ch_None)
+imm,imm \1\xC8\30\25 186
+
+[F2XM1]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xD9\xF0 8086,FPU
+
+[FABS]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xD9\xE1 8086,FPU
+
+[FADD,faddF]
+(Ch_FPU, Ch_ROp1, Ch_None)
+mem32 \1\xD8\200 8086,FPU
+mem64 \1\xDC\200 8086,FPU
+void \2\xDE\xC1 8086,FPU
+fpureg|to \1\xDC\10\xC0 8086,FPU
+fpureg,fpu0 \1\xDC\10\xC0 8086,FPU
+fpureg \1\xD8\10\xC0 8086,FPU
+fpu0,fpureg \1\xD8\11\xC0 8086,FPU
+
+[FADDP,faddpF]
+(Ch_FPU, Ch_ROp1, Ch_None)
+void \2\xDE\xC1 8086,FPU
+fpureg \1\xDE\10\xC0 8086,FPU
+fpureg,fpu0 \1\xDE\10\xC0 8086,FPU
+
+[FBLD,fbldF]
+(Ch_Rop1, Ch_FPU, Ch_None)
+mem80 \1\xDF\204 8086,FPU
+mem \1\xDF\204 8086,FPU
+
+[FBSTP,fbstpF]
+(Ch_Wop1, Ch_FPU, Ch_None)
+mem80 \1\xDF\206 8086,FPU
+mem \1\xDF\206 8086,FPU
+
+[FCHS]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xD9\xE0 8086,FPU
+
+[FCLEX]
+(Ch_FPU, Ch_None, Ch_None)
+void \3\x9B\xDB\xE2 8086,FPU
+
+[FCMOVB,fcmovbF]
+(Ch_FPU, Ch_RFLAGS, Ch_None)
+void \2\xDA\xC1 P6,FPU
+fpureg \1\xDA\10\xC0 P6,FPU
+fpu0,fpureg \1\xDA\11\xC0 P6,FPU
+
+[FCMOVBE,fcmovbeF]
+(Ch_FPU, Ch_RFLAGS, Ch_None)
+void \2\xDA\xD1 P6,FPU
+fpureg \1\xDA\10\xD0 P6,FPU
+fpu0,fpureg \1\xDA\11\xD0 P6,FPU
+
+[FCMOVE,fcmoveF]
+(Ch_FPU, Ch_RFLAGS, Ch_None)
+void \2\xDA\xC9 P6,FPU
+fpureg \1\xDA\10\xC8 P6,FPU
+fpu0,fpureg \1\xDA\11\xC8 P6,FPU
+
+[FCMOVNB,fcmovnbF]
+(Ch_FPU, Ch_RFLAGS, Ch_None)
+void \2\xDB\xC1 P6,FPU
+fpureg \1\xDB\10\xC0 P6,FPU
+fpu0,fpureg \1\xDB\11\xC0 P6,FPU
+
+[FCMOVNBE,fcmovnbeF]
+(Ch_FPU, Ch_RFLAGS, Ch_None)
+void \2\xDB\xD1 P6,FPU
+fpureg \1\xDB\10\xD0 P6,FPU
+fpu0,fpureg \1\xDB\11\xD0 P6,FPU
+
+[FCMOVNE,fcmovneF]
+(Ch_FPU, Ch_RFLAGS, Ch_None)
+void \2\xDB\xC9 P6,FPU
+fpureg \1\xDB\10\xC8 P6,FPU
+fpu0,fpureg \1\xDB\11\xC8 P6,FPU
+
+[FCMOVNU,fcmovnuF]
+(Ch_FPU, Ch_RFLAGS, Ch_None)
+void \2\xDB\xD9 P6,FPU
+fpureg \1\xDB\10\xD8 P6,FPU
+fpu0,fpureg \1\xDB\11\xD8 P6,FPU
+
+[FCMOVU,fcmovuF]
+(Ch_FPU, Ch_RFLAGS, Ch_None)
+void \2\xDA\xD9 P6,FPU
+fpureg \1\xDA\10\xD8 P6,FPU
+fpu0,fpureg \1\xDA\11\xD8 P6,FPU
+
+[FCOM,fcomF]
+(Ch_FPU, Ch_None, Ch_None)
+mem32 \1\xD8\202 8086,FPU
+mem64 \1\xDC\202 8086,FPU
+void \2\xD8\xD1 8086,FPU
+fpureg \1\xD8\10\xD0 8086,FPU
+fpu0,fpureg \1\xD8\11\xD0 8086,FPU
+
+[FCOMI,fcomiF]
+(Ch_WFLAGS, Ch_None, Ch_None)
+void \2\xDB\xF1 P6,FPU
+fpureg \1\xDB\10\xF0 P6,FPU
+fpu0,fpureg \1\xDB\11\xF0 P6,FPU
+
+[FCOMIP,fcomipF]
+(Ch_FPU, Ch_WFLAGS, Ch_None)
+void \2\xDF\xF1 P6,FPU
+fpureg \1\xDF\10\xF0 P6,FPU
+fpu0,fpureg \1\xDF\11\xF0 P6,FPU
+
+[FCOMP,fcompF]
+(Ch_FPU, Ch_None, Ch_None)
+mem32 \1\xD8\203 8086,FPU
+mem64 \1\xDC\203 8086,FPU
+void \2\xD8\xD9 8086,FPU
+fpureg \1\xD8\10\xD8 8086,FPU
+fpu0,fpureg \1\xD8\11\xD8 8086,FPU
+
+[FCOMPP]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xDE\xD9 8086,FPU
+
+[FCOS]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xD9\xFF 386,FPU
+
+[FDECSTP]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xD9\xF6 8086,FPU
+
+[FDISI]
+(Ch_FPU, Ch_None, Ch_None)
+void \3\x9B\xDB\xE1 8086,FPU
+
+[FDIV,fdivF]
+(Ch_FPU, Ch_ROp1, Ch_None)
+mem32 \1\xD8\206 8086,FPU
+mem64 \1\xDC\206 8086,FPU
+void \2\xDC\xF1 8086,FPU
+fpureg|to \1\xDC\10\xF0 8086,FPU
+fpureg,fpu0 \1\xDC\10\xF0 8086,FPU
+fpureg \1\xD8\10\xF0 8086,FPU
+fpu0,fpureg \1\xD8\11\xF0 8086,FPU
+
+[FDIVP,fdivpF]
+(Ch_FPU, Ch_ROp1, Ch_None)
+void \2\xDE\xF1 8086,FPU
+fpureg,fpu0 \1\xDE\10\xF0 8086,FPU
+fpureg \1\xDE\10\xF0 8086,FPU
+
+[FDIVR,fdivrF]
+(Ch_FPU, Ch_ROp1, Ch_None)
+mem32 \1\xD8\207 8086,FPU
+mem64 \1\xDC\207 8086,FPU
+void \2\xDC\xF9 8086,FPU
+fpureg|to \1\xDC\10\xF8 8086,FPU
+fpureg,fpu0 \1\xDC\10\xF8 8086,FPU
+fpureg \1\xD8\10\xF8 8086,FPU
+fpu0,fpureg \1\xD8\11\xF8 8086,FPU
+
+[FDIVRP,fdivrpF]
+(Ch_FPU, Ch_ROp1, Ch_None)
+void \2\xDE\xF9 8086,FPU
+fpureg \1\xDE\10\xF8 8086,FPU
+fpureg,fpu0 \1\xDE\10\xF8 8086,FPU
+
+[FEMMS]
+(Ch_All, Ch_None, Ch_None)
+void \2\x0F\x0E PENT,3DNOW
+
+[FENI]
+(Ch_FPU, Ch_None, Ch_None)
+void \3\x9B\xDB\xE0 8086,FPU
+
+[FFREE]
+(Ch_FPU, Ch_None, Ch_None)
+fpureg \1\xDD\10\xC0 8086,FPU
+
+[FIADD,fiaddR]
+(Ch_FPU, Ch_ROp1, Ch_None)
+mem16 \1\xDE\200 8086,FPU
+mem32 \1\xDA\200 8086,FPU
+
+[FICOM,ficomR]
+(Ch_FPU, Ch_None, Ch_None)
+mem16 \1\xDE\202 8086,FPU
+mem32 \1\xDA\202 8086,FPU
+
+[FICOMP,ficompR]
+(Ch_FPU, Ch_None, Ch_None)
+mem16 \1\xDE\203 8086,FPU
+mem32 \1\xDA\203 8086,FPU
+
+[FIDIV,fidivR]
+(Ch_FPU, Ch_ROp1, Ch_None)
+mem16 \1\xDE\206 8086,FPU
+mem32 \1\xDA\206 8086,FPU
+
+[FIDIVR,fidivrR]
+(Ch_FPU, Ch_ROp1, Ch_None)
+mem16 \1\xDE\207 8086,FPU
+mem32 \1\xDA\207 8086,FPU
+
+[FILD,fildR]
+(Ch_FPU, Ch_ROp1, Ch_None)
+mem32 \1\xDB\200 8086,FPU
+mem16 \1\xDF\200 8086,FPU
+mem64 \1\xDF\205 8086,FPU
+
+[FIMUL,fimulR]
+(Ch_FPU, Ch_ROp1, Ch_None)
+mem16 \1\xDE\201 8086,FPU
+mem32 \1\xDA\201 8086,FPU
+
+[FINCSTP]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xD9\xF7 8086,FPU
+
+[FINIT]
+(Ch_FPU, Ch_None, Ch_None)
+void \3\x9B\xDB\xE3 8086,FPU
+
+[FIST,fistR]
+(Ch_Wop1, Ch_None, Ch_None)
+mem32 \1\xDB\202 8086,FPU
+mem16 \324\1\xDF\202 8086,FPU
+
+[FISTP,fistpR]
+(Ch_Wop1, Ch_None, Ch_None)
+mem32 \1\xDB\203 8086,FPU
+mem16 \324\1\xDF\203 8086,FPU
+mem64 \1\xDF\207 8086,FPU
+
+[FISTTP,fisttpR]
+(Ch_Wop1, Ch_None, Ch_None)
+mem32 \1\xDB\201 PRESCOTT,FPU
+mem16 \1\xDF\201 PRESCOTT,FPU
+mem64 \1\xDD\201 PRESCOTT,FPU
+
+[FISUB,fisubR]
+(Ch_FPU, Ch_ROp1, Ch_None)
+mem16 \1\xDE\204 8086,FPU
+mem32 \1\xDA\204 8086,FPU
+
+[FISUBR,fisubrR]
+(Ch_FPU, Ch_ROp1, Ch_None)
+mem16 \1\xDE\205 8086,FPU
+mem32 \1\xDA\205 8086,FPU
+
+[FLD,fldF]
+(Ch_Rop1, Ch_FPU, Ch_None)
+mem32 \1\xD9\200 8086,FPU
+mem64 \1\xDD\200 8086,FPU
+mem80 \1\xDB\205 8086,FPU
+fpureg \1\xD9\10\xC0 8086,FPU
+
+[FLD1]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xD9\xE8 8086,FPU
+
+[FLDCW,fldcwX]
+(Ch_FPU, Ch_None, Ch_None)
+mem \1\xD9\205 8086,FPU,SW
+
+[FLDENV,fldenv]
+(Ch_FPU, Ch_None, Ch_None)
+mem \1\xD9\204 8086,FPU
+
+[FLDL2E]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xD9\xEA 8086,FPU
+
+[FLDL2T]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xD9\xE9 8086,FPU
+
+[FLDLG2]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xD9\xEC 8086,FPU
+
+[FLDLN2]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xD9\xED 8086,FPU
+
+[FLDPI]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xD9\xEB 8086,FPU
+
+[FLDZ]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xD9\xEE 8086,FPU
+
+[FMUL,fmulF]
+(Ch_ROp1, Ch_FPU, Ch_None)
+mem32 \1\xD8\201 8086,FPU
+mem64 \1\xDC\201 8086,FPU
+void \2\xDC\xC9 8086,FPU
+fpureg|to \1\xDC\10\xC8 8086,FPU
+fpureg,fpu0 \1\xDC\10\xC8 8086,FPU
+fpureg \1\xD8\10\xC8 8086,FPU
+fpu0,fpureg \1\xD8\11\xC8 8086,FPU
+
+[FMULP,fmulpF]
+(Ch_ROp1, Ch_FPU, Ch_None)
+void \2\xDE\xC9 8086,FPU
+fpureg \1\xDE\10\xC8 8086,FPU
+fpureg,fpu0 \1\xDE\10\xC8 8086,FPU
+
+[FNCLEX]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xDB\xE2 8086,FPU
+
+[FNDISI]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xDB\xE1 8086,FPU
+
+[FNENI]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xDB\xE0 8086,FPU
+
+[FNINIT]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xDB\xE3 8086,FPU
+
+[FNOP]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xD9\xD0 8086,FPU
+
+[FNSAVE,fnsave]
+(Ch_FPU, Ch_None, Ch_None)
+mem \1\xDD\206 8086,FPU
+
+[FNSTCW,fnstcwX]
+(Ch_Wop1, Ch_None, Ch_None)
+mem \1\xD9\207 8086,FPU,SW
+
+[FNSTENV,fnstenv]
+(Ch_Wop1, Ch_None, Ch_None)
+mem \1\xD9\206 8086,FPU
+
+[FNSTSW,fnstswX]
+(Ch_Wop1, Ch_None, Ch_None)
+mem \1\xDD\207 8086,FPU,SW
+reg_ax \2\xDF\xE0 286,FPU
+
+[FPATAN]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xD9\xF3 8086,FPU
+
+[FPREM]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xD9\xF8 8086,FPU
+
+[FPREM1]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xD9\xF5 386,FPU
+
+[FPTAN]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xD9\xF2 8086,FPU
+
+[FRNDINT]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xD9\xFC 8086,FPU
+
+[FRSTOR,frstor]
+(Ch_FPU, Ch_None, Ch_None)
+mem \1\xDD\204 8086,FPU
+
+[FSAVE,fsave]
+(Ch_Wop1, Ch_None, Ch_None)
+mem \2\x9B\xDD\206 8086,FPU
+
+[FSCALE]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xD9\xFD 8086,FPU
+
+[FSETPM]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xDB\xE4 286,FPU
+
+[FSIN]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xD9\xFE 386,FPU
+
+[FSINCOS]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xD9\xFB 386,FPU
+
+[FSQRT]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xD9\xFA 8086,FPU
+
+[FST,fstF]
+(Ch_Wop1, Ch_None, Ch_None)
+mem32 \1\xD9\202 8086,FPU
+mem64 \1\xDD\202 8086,FPU
+fpureg \1\xDD\10\xD0 8086,FPU
+
+[FSTCW,fstcwX]
+(Ch_Wop1, Ch_None, Ch_None)
+mem \2\x9B\xD9\207 8086,FPU,SW
+
+[FSTENV,fstenv]
+(Ch_Wop1, Ch_None, Ch_None)
+mem \2\x9B\xD9\206 8086,FPU
+
+[FSTP,fstpF]
+(Ch_Wop1, Ch_FPU, Ch_None)
+mem32 \1\xD9\203 8086,FPU
+mem64 \1\xDD\203 8086,FPU
+mem80 \1\xDB\207 8086,FPU
+fpureg \1\xDD\10\xD8 8086,FPU
+
+[FSTSW,fstswX]
+(Ch_Wop1, Ch_None, Ch_None)
+mem \2\x9B\xDD\207 8086,FPU,SW
+void \3\x9B\xDF\xE0 286,FPU
+reg_ax \3\x9B\xDF\xE0 286,FPU
+
+[FSUB,fsubF]
+(Ch_ROp1, Ch_FPU, Ch_None)
+mem32 \1\xD8\204 8086,FPU
+mem64 \1\xDC\204 8086,FPU
+void \2\xDC\xE1 8086,FPU
+fpureg|to \1\xDC\10\xE0 8086,FPU
+fpureg,fpu0 \1\xDC\10\xE0 8086,FPU
+fpureg \1\xD8\10\xE0 8086,FPU
+fpu0,fpureg \1\xD8\11\xE0 8086,FPU
+
+[FSUBP,fsubpF]
+(Ch_ROp1, Ch_FPU, Ch_None)
+void \2\xDE\xE1 8086,FPU
+fpureg \1\xDE\10\xE0 8086,FPU
+fpureg,fpu0 \1\xDE\10\xE0 8086,FPU
+
+[FSUBR,fsubrF]
+(Ch_ROp1, Ch_FPU, Ch_None)
+mem32 \1\xD8\205 8086,FPU
+mem64 \1\xDC\205 8086,FPU
+void \2\xDC\xE9 8086,FPU
+fpureg|to \1\xDC\10\xE8 8086,FPU
+fpureg,fpu0 \1\xDC\10\xE8 8086,FPU
+fpureg \1\xD8\10\xE8 8086,FPU
+fpu0,fpureg \1\xD8\11\xE8 8086,FPU
+
+[FSUBRP,fsubrpF]
+(Ch_ROp1, Ch_FPU, Ch_None)
+void \2\xDE\xE9 8086,FPU
+fpureg \1\xDE\10\xE8 8086,FPU
+fpureg,fpu0 \1\xDE\10\xE8 8086,FPU
+
+[FTST]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xD9\xE4 8086,FPU
+
+[FUCOM,fucomF]
+(Ch_None, Ch_None, Ch_None)
+void \2\xDD\xE1 386,FPU
+fpureg \1\xDD\10\xE0 386,FPU
+fpu0,fpureg \1\xDD\11\xE0 386,FPU
+
+[FUCOMI,fucomiF]
+(Ch_WFLAGS, Ch_None, Ch_None)
+void \2\xDB\xE9 P6,FPU
+fpureg \1\xDB\10\xE8 P6,FPU
+fpu0,fpureg \1\xDB\11\xE8 P6,FPU
+
+[FUCOMIP,fucomipF]
+(Ch_FPU, Ch_WFLAGS, Ch_None)
+void \2\xDF\xE9 P6,FPU
+fpureg \1\xDF\10\xE8 P6,FPU
+fpu0,fpureg \1\xDF\11\xE8 P6,FPU
+
+[FUCOMP,fucompF]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xDD\xE9 386,FPU
+fpureg \1\xDD\10\xE8 386,FPU
+fpu0,fpureg \1\xDD\11\xE8 386,FPU
+
+[FUCOMPP]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xDA\xE9 386,FPU
+
+[FWAIT]
+(Ch_FPU, Ch_None, Ch_None)
+void \1\x9B 8086,FPU
+
+[FXAM]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xD9\xE5 8086,FPU
+
+[FXCH,fxchF]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xD9\xC9 8086,FPU
+fpureg \1\xD9\10\xC8 8086,FPU
+fpureg,fpu0 \1\xD9\10\xC8 8086,FPU
+fpu0,fpureg \1\xD9\11\xC8 8086,FPU
+
+[FXTRACT]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xD9\xF4 8086,FPU
+
+[FYL2X]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xD9\xF1 8086,FPU
+
+[FYL2XP1]
+(Ch_FPU, Ch_None, Ch_None)
+void \2\xD9\xF9 8086,FPU
+
+[HLT]
+(Ch_None, Ch_None, Ch_None)
+void \1\xF4 8086,PRIV
+
+[IBTS,ibtsX]
+(Ch_All, Ch_None, Ch_None)
+regmem,reg16|32|64 \320\2\x0F\xA7\101 386,SM,UNDOC,ND
+
+[ICEBP]
+(Ch_All, Ch_None, Ch_None)
+void \1\xF1 386,ND
+
+[IDIV,idivX]
+(Ch_RWEAX, Ch_WEDX, Ch_WFlags)
+rm16|32|64 \320\1\xF7\207 8086
+rm8 \1\xF6\207 8086
+
+[IMUL,imulX]
+(Ch_RWEAX, Ch_WEDX, Ch_WFlags)
+reg16|32|64,regmem \320\2\x0F\xAF\110 386,SM
+rm16|32|64 \320\1\xF7\205 8086
+reg32|64,regmem,imm8 \320\1\x6B\110\16 286,SM
+reg32|64,regmem,imm \320\1\x69\110\42 286,SM,SD,AR2
+reg32|64,imm8 \320\1\x6B\100\15 286
+reg32,imm \325\1\x69\100\41 286,SD
+reg64,imm \326\1\x69\100\255 X86_64
+reg16,regmem,imm8 \324\1\x6B\110\16 286,SM
+reg16,regmem,imm \324\1\x69\110\32 286,SM,SW,AR2
+reg16,imm8 \324\1\x6B\100\15 286
+reg16,imm \324\1\x69\100\31 286,SW
+rm8 \1\xF6\205 8086
+
+; 64-bit variant does not exist
+[IN,inX]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+reg_al,imm \1\xE4\25 8086,SB
+reg_ax|32,imm \320\1\xE5\25 8086,SB
+reg_al,reg_dx \1\xEC 8086
+reg_ax|32,reg_dx \320\1\xED 8086
+
+[INC,incX]
+(Ch_Mop1, Ch_WFlags, Ch_None)
+reg16|32 \320\10\x40 8086,NOX86_64
+rm16|32|64 \320\1\xFF\200 8086
+rm8 \1\xFE\200 8086
+
+[INSB]
+(Ch_WMemEDI, Ch_RWEDI, Ch_REDX)
+void \1\x6C 186
+
+[INSD,insl]
+(Ch_WMemEDI, Ch_RWEDI, Ch_REDX)
+void \325\1\x6D 386
+
+[INSW]
+(Ch_WMemEDI, Ch_RWEDI, Ch_REDX)
+void \324\1\x6D 186
+
+[INT]
+(Ch_All, Ch_None, Ch_None)
+imm \1\xCD\24 8086,SB
+
+[INT01]
+(Ch_All, Ch_None, Ch_None)
+void \1\xF1 386,ND
+
+[INT1]
+(Ch_All, Ch_None, Ch_None)
+void \1\xF1 386
+
+[INT03]
+(Ch_None, Ch_None, Ch_None)
+void \1\xCC 8086,ND
+
+[INT3]
+(Ch_None, Ch_None, Ch_None)
+void \1\xCC 8086
+
+[INTO]
+(Ch_All, Ch_None, Ch_None)
+void \1\xCE 8086,NOX86_64
+
+[INVD]
+(Ch_All, Ch_None, Ch_None)
+void \2\x0F\x08 486,PRIV
+
+[INVLPG,invlpgX]
+(Ch_All, Ch_None, Ch_None)
+mem \2\x0F\x01\207 486,PRIV
+
+[IRET]
+(Ch_All, Ch_None, Ch_None)
+void \327\1\xCF 8086
+
+[IRETD,iret]
+(Ch_All, Ch_None, Ch_None)
+void \325\1\xCF 386
+
+[IRETW]
+(Ch_All, Ch_None, Ch_None)
+void \324\1\xCF 8086
+
+[IRETQ]
+(Ch_All, Ch_None, Ch_None)
+void \326\1\xCF X86_64
+
+[JCXZ]
+(Ch_RECX, Ch_None, Ch_None)
+imm \310\1\xE3\50 8086,NOX86_64
+
+[JECXZ]
+(Ch_RECX, Ch_None, Ch_None)
+imm \311\1\xE3\50 386
+
+[JRCXZ]
+(Ch_RECX, Ch_None, Ch_None)
+imm \1\xE3\50 X86_64
+
+[JMP,jmpX]
+(Ch_ROp1, Ch_None, Ch_None)
+; rm16 should be after rm32/rm64, see comments for CALL.
+imm8 \1\xEB\50 8086,PASS2
+imm16|32 \320\1\xE9\64 8086,PASS2
+rm32 \325\1\xFF\204 386,NOX86_64
+rm64 \335\1\xFF\204 X86_64
+rm16 \324\1\xFF\204 8086
+imm|short \1\xEB\50 8086,PASS2
+imm|near \320\1\xE9\64 8086,ND,PASS2
+imm|far \320\1\xEA\34\37 8086,ND,PASS2,NOX86_64
+mem|near \320\1\xFF\204 8086
+mem|far \320\1\xFF\205 8086
+imm:imm \327\1\xEA\35\30 8086,NOX86_64
+imm:imm16 \324\1\xEA\31\30 8086,NOX86_64
+imm:imm32 \325\1\xEA\41\30 386,NOX86_64
+
+; SAHF/LAHF are valid in x86_64 only if CPUID.80000001h:ECX.0=1
+[LAHF]
+(Ch_WEAX, Ch_RFlags, Ch_None)
+void \1\x9F 8086
+
+[LAR,larX]
+(Ch_Wop2, Ch_None, Ch_None)
+reg16|32|64,regmem \320\2\x0F\x02\110 286,PROT,SM
+
+[LCALL,lcall]
+; don't know value of any register
+; Far call, AT&T only (there are no near/far modifiers in AT&T syntax, so separate mnemonic is needed)
+(Ch_All, Ch_None, Ch_None)
+mem32 \325\1\xFF\203 386,NOX86_64
+mem64 \335\1\xFF\203 X86_64
+mem16 \324\1\xFF\203 8086
+
+[LDS,ldsX]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+reg16|32,mem \320\1\xC5\110 8086,NOX86_64
+
+[LEA,leaX]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+reg32|64,mem \320\1\x8D\110 8086
+reg32|64,imm \320\1\x8D\110 8086,SD
+
+[LEAVE]
+(Ch_RWESP, Ch_WEBP, Ch_None)
+void \1\xC9 186
+
+[LES,lesX]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+reg16|32,mem \320\1\xC4\110 8086,NOX86_64
+
+[LFS,lfsX]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+reg16|32,mem \320\2\x0F\xB4\110 386
+
+[LGDT,lgdtX]
+(Ch_None, Ch_None, Ch_None)
+mem \2\x0F\x01\202 286,PRIV
+
+[LGS,lgsX]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+reg16|32,mem \320\2\x0F\xB5\110 386
+
+[LIDT,lidtX]
+(Ch_None, Ch_None, Ch_None)
+mem \2\x0F\x01\203 286,PRIV
+
+[LJMP,ljmp]
+(Ch_ROp1, Ch_None, Ch_None)
+mem32 \325\1\xFF\205 386,NOX86_64
+mem64 \335\1\xFF\205 X86_64
+mem16 \324\1\xFF\205 8086
+
+[LLDT,lldtX]
+(Ch_None, Ch_None, Ch_None)
+rm16 \2\x0F\x00\202 286,PROT,PRIV
+
+[LMSW,lmswX]
+(Ch_None, Ch_None, Ch_None)
+rm16 \2\x0F\x01\206 286,PRIV
+
+[LOADALL]
+(Ch_All, Ch_None, Ch_None)
+void \2\x0F\x07 386,UNDOC
+
+[LOADALL286]
+(Ch_All, Ch_None, Ch_None)
+void \2\x0F\x05 286,UNDOC
+
+[LOCK]
+(Ch_None, Ch_None, Ch_None)
+void \1\xF0 8086,PRE
+
+[LODSB]
+(Ch_WEAX, Ch_RWESI, Ch_None)
+void \1\xAC 8086
+
+[LODSD,lodsl]
+(Ch_WEAX, Ch_RWESI, Ch_None)
+void \325\1\xAD 386
+
+[LODSW]
+(Ch_WEAX, Ch_RWESI, Ch_None)
+void \324\1\xAD 8086
+
+[LOOP]
+(Ch_RWECX, Ch_None, Ch_None)
+imm \312\1\xE2\50 8086
+imm,reg_cx \310\1\xE2\50 8086,NOX86_64
+imm,reg_ecx|64 \311\1\xE2\50 386
+
+[LOOPE]
+(Ch_RWECX, Ch_RFlags, Ch_None)
+imm \312\1\xE1\50 8086
+imm,reg_cx \310\1\xE1\50 8086,NOX86_64
+imm,reg_ecx|64 \311\1\xE1\50 386
+
+[LOOPNE]
+(Ch_RWECX, Ch_RFlags, Ch_None)
+imm \312\1\xE0\50 8086
+imm,reg_cx \310\1\xE0\50 8086,NOX86_64
+imm,reg_ecx|64 \311\1\xE0\50 386
+
+[LOOPNZ]
+(Ch_RWECX, Ch_RFlags, Ch_None)
+imm \312\1\xE0\50 8086
+imm,reg_cx \310\1\xE0\50 8086,NOX86_64
+imm,reg_ecx|64 \311\1\xE0\50 386
+
+[LOOPZ]
+(Ch_RWECX, Ch_RFlags, Ch_None)
+imm \312\1\xE1\50 8086
+imm,reg_cx \310\1\xE1\50 8086,NOX86_64
+imm,reg_ecx|64 \311\1\xE1\50 386
+
+[LSL,lslX]
+(Ch_Wop2, Ch_WFlags, Ch_None)
+reg16|32|64,regmem \320\2\x0F\x03\110 286,PROT,SM
+
+[LSS,lssX]
+(Ch_Wop2, Ch_ROP1, Ch_None)
+reg16|32|64,mem \320\2\x0F\xB2\110 386
+
+[LTR,ltrX]
+(Ch_None, Ch_None, Ch_None)
+rm16 \2\x0F\x00\203 286,PROT,PRIV
+
+[MONITOR]
+(Ch_None, Ch_None, Ch_None)
+void \3\x0F\x01\xC8 PRESCOTT
+reg_eax,reg_ecx,reg_edx \3\x0F\x01\xC8 PRESCOTT,ND
+
+[MOV,movX]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+mem_offs,reg_ax \324\1\xA3\44 8086,SM
+mem_offs,reg_eax \325\1\xA3\44 386,SM
+mem_offs,reg_rax \326\1\xA3\44 X86_64,SM
+regmem,reg16|32|64 \320\1\x89\101 8086,SM
+reg_ax,mem_offs \324\1\xA1\45 8086,SM
+reg_eax,mem_offs \325\1\xA1\45 386,SM
+reg_rax,mem_offs \326\1\xA1\45 X86_64,SM
+reg16|32|64,regmem \320\1\x8B\110 8086,SM
+reg32,imm \325\10\xB8\41 386,SD
+reg64,imm \326\10\xB8\55 X86_64,SM
+rm32,imm \325\1\xC7\200\41 386,SM
+rm64,imm \326\1\xC7\200\255 X86_64,SM
+reg16,imm \324\10\xB8\31 8086,SW
+rm16,imm \324\1\xC7\200\31 8086,SW
+mem_offs,reg_al \1\xA2\44 8086,SM
+rm8,reg8 \1\x88\101 8086
+reg_al,mem_offs \1\xA0\45 8086,SM
+reg8,rm8 \1\x8A\110 8086,SM
+reg8,imm \10\xB0\21 8086,SB
+rm8,imm \1\xC6\200\21 8086,SB
+rm16|32,reg_cs \320\1\x8C\201 8086
+rm16|32,reg_dess \320\1\x8C\101 8086
+rm16|32,reg_fsgs \320\1\x8C\101 386
+reg_dess,rm16|32 \321\1\x8E\110 8086,SM
+reg_fsgs,rm16|32 \321\1\x8E\110 386,SM
+reg32,reg_cr4 \2\x0F\x20\204 PENT,PRIV,NOX86_64
+reg32,reg_creg \2\x0F\x20\101 386,PRIV,NOX86_64
+reg32,reg_dreg \2\x0F\x21\101 386,PRIV,NOX86_64
+reg32,reg_treg \2\x0F\x24\101 386,PRIV,NOX86_64
+reg64,reg_cr4 \2\x0F\x20\204 PENT,PRIV,X86_64
+reg64,reg_creg \2\x0F\x20\101 386,PRIV,X86_64
+reg64,reg_dreg \2\x0F\x21\101 386,PRIV,X86_64
+reg64,reg_treg \2\x0F\x24\101 386,PRIV,X86_64
+reg_cr4,reg32 \2\x0F\x22\214 PENT,PRIV,NOX86_64
+reg_creg,reg32 \2\x0F\x22\110 386,PRIV,NOX86_64
+reg_dreg,reg32 \2\x0F\x23\110 386,PRIV,NOX86_64
+reg_treg,reg32 \2\x0F\x26\110 386,PRIV,NOX86_64
+reg_cr4,reg64 \2\x0F\x22\214 PENT,PRIV,X86_64
+reg_creg,reg64 \2\x0F\x22\110 386,PRIV,X86_64
+reg_dreg,reg64 \2\x0F\x23\110 386,PRIV,X86_64
+reg_treg,reg64 \2\x0F\x26\110 386,PRIV,X86_64
+
+[MOVD,movd]
+(Ch_Rop1, Ch_Wop2, Ch_None)
+mmxreg,rm32 \2\x0F\x6E\110 PENT,MMX,SD
+rm32,mmxreg \2\x0F\x7E\101 PENT,MMX,SD
+xmmreg,rm32 \361\2\x0F\x6E\110 WILLAMETTE,SSE2
+rm32,xmmreg \361\2\x0F\x7E\101 WILLAMETTE,SSE2
+
+[MOVQ,movq]
+(Ch_Rop1, Ch_Wop2, Ch_None)
+mmxreg,mmxrm \2\x0F\x6F\110 PENT,MMX,SM
+mmxrm,mmxreg \2\x0F\x7F\101 PENT,MMX,SM
+mmxreg,rm64 \326\2\x0F\x6E\110 X86_64,MMX
+rm64,mmxreg \326\2\x0F\x7E\101 X86_64,MMX
+xmmreg,xmmrm \333\2\x0F\x7E\110 WILLAMETTE,SSE2
+xmmrm,xmmreg \361\2\x0F\xD6\101 WILLAMETTE,SSE2
+xmmreg,reg64 \361\326\2\x0F\x6E\110 WILLAMETTE,SSE2,X86_64
+reg64,xmmreg \361\326\2\x0F\x7E\101 WILLAMETTE,SSE2,X86_64
+
+[MOVSB]
+(Ch_All, Ch_None, Ch_None)
+void \1\xA4 8086
+
+[MOVSD,movsl]
+; Ch_All isn't correct for the sse move, but how can it be solved? (FK)
+(Ch_All, Ch_None, Ch_None)
+void \325\1\xA5 386
+xmmreg,xmmrm \334\2\x0F\x10\110 WILLAMETTE,SSE2
+xmmrm,xmmreg \334\2\x0F\x11\101 WILLAMETTE,SSE2
+
+[MOVSQ]
+(Ch_All, Ch_None, Ch_None)
+void \326\1\xA5 X86_64
+
+[MOVSW]
+(Ch_All, Ch_None, Ch_None)
+void \324\1\xA5 8086
+
+[MOVSX,movsY]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+reg32|64,rm16 \320\2\x0F\xBF\110 386
+reg16|32|64,rm8 \320\2\x0F\xBE\110 386
+
+[MOVZX,movzY]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+reg32|64,rm16 \320\2\x0F\xB7\110 386
+reg16|32|64,rm8 \320\2\x0F\xB6\110 386
+
+[MUL,mulX]
+(Ch_RWEAX, Ch_WEDX, Ch_WFlags)
+rm16|32|64 \320\1\xF7\204 8086
+rm8 \1\xF6\204 8086
+
+[MWAIT]
+(Ch_None, Ch_None, Ch_None)
+void \3\x0F\x01\xC9 PRESCOTT
+reg_eax,reg_ecx \3\x0F\x01\xC9 PRESCOTT,ND
+
+
+[NEG,negX]
+(Ch_Mop1, Ch_None, Ch_None)
+rm16|32|64 \320\1\xF7\203 8086
+rm8 \1\xF6\203 8086
+
+[NOP]
+(Ch_None, Ch_None, Ch_None)
+void \1\x90 8086
+
+[NOT,notX]
+(Ch_Mop1, Ch_WFlags, Ch_None)
+rm16|32|64 \320\1\xF7\202 8086
+rm8 \1\xF6\202 8086
+
+[OR,orX]
+(Ch_Mop2, Ch_Rop1, Ch_WFlags)
+regmem,reg16|32|64 \320\1\x09\101 8086,SM
+reg16|32|64,regmem \320\1\x0B\110 8086,SM
+rm8,reg8 \1\x08\101 8086
+reg8,rm8 \1\x0A\110 8086,SM
+rm16|32|64,imm8 \320\1\x83\201\15 8086
+reg_eax,imm \325\1\x0D\41 386,SM
+reg_rax,imm \326\1\x0D\255 X86_64,SM
+rm32,imm \325\1\x81\201\41 386,SM
+rm64,imm \326\1\x81\201\255 X86_64,SM
+reg_ax,imm \324\1\x0D\31 8086,SW
+rm16,imm \324\1\x81\201\31 8086,SW
+reg_al,imm \1\x0C\21 8086,SB
+rm8,imm \1\x80\201\21 8086,SB
+
+[OUT,outX]
+(Ch_Rop1, Ch_Rop2, Ch_None)
+imm,reg_al \1\xE6\24 8086,SB
+imm,reg_ax \324\1\xE7\24 8086,SB
+imm,reg_eax \325\1\xE7\24 386,SB
+reg_dx,reg_al \1\xEE 8086
+reg_dx,reg_ax \324\1\xEF 8086
+reg_dx,reg_eax \325\1\xEF 386
+
+[OUTSB]
+(Ch_All, Ch_None, Ch_None)
+void \1\x6E 186
+
+[OUTSD,outsl]
+(Ch_All, Ch_None, Ch_None)
+void \325\1\x6F 386
+
+[OUTSW]
+(Ch_All, Ch_None, Ch_None)
+void \324\1\x6F 186
+
+[PACKSSDW]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\x6B\110 PENT,MMX,SM
+xmmreg,xmmrm \361\2\x0F\x6B\110 WILLAMETTE,SSE2,SM
+
+[PACKSSWB]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\x63\110 PENT,MMX,SM
+xmmreg,xmmrm \361\2\x0F\x63\110 WILLAMETTE,SSE2,SM
+
+[PACKUSWB]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\x67\110 PENT,MMX,SM
+xmmreg,xmmrm \361\2\x0F\x67\110 WILLAMETTE,SSE2,SM
+
+[PADDB]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+mmxreg,mmxrm \2\x0F\xFC\110 PENT,MMX,SM
+xmmreg,xmmrm \361\2\x0F\xFC\110 WILLAMETTE,SSE2,SM
+
+[PADDD]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+mmxreg,mmxrm \2\x0F\xFE\110 PENT,MMX,SM
+xmmreg,xmmrm \361\2\x0F\xFE\110 WILLAMETTE,SSE2,SM
+
+[PADDSB]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+mmxreg,mmxrm \2\x0F\xEC\110 PENT,MMX,SM
+xmmreg,xmmrm \361\2\x0F\xEC\110 WILLAMETTE,SSE2,SM
+
+[PADDSIW]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+mmxreg,mmxrm \2\x0F\x51\110 PENT,MMX,SM,CYRIX
+
+[PADDSW]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+mmxreg,mmxrm \2\x0F\xED\110 PENT,MMX,SM
+xmmreg,xmmrm \361\2\x0F\xED\110 WILLAMETTE,SSE2,SM
+
+[PADDUSB]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\xDC\110 PENT,MMX,SM
+xmmreg,xmmrm \361\2\x0F\xDC\110 WILLAMETTE,SSE2,SM
+
+[PADDUSW]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\xDD\110 PENT,MMX,SM
+xmmreg,xmmrm \361\2\x0F\xDD\110 WILLAMETTE,SSE2,SM
+
+[PADDW]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\xFD\110 PENT,MMX,SM
+xmmreg,xmmrm \361\2\x0F\xFD\110 WILLAMETTE,SSE2,SM
+
+[PAND]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\xDB\110 PENT,MMX,SM
+xmmreg,xmmrm \361\2\x0F\xDB\110 WILLAMETTE,SSE2,SM
+
+[PANDN]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\xDF\110 PENT,MMX,SM
+xmmreg,xmmrm \361\2\x0F\xDF\110 WILLAMETTE,SSE2,SM
+
+[PAVEB]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\x50\110 PENT,MMX,SM,CYRIX
+
+[PAVGUSB]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\x0F\110\01\xBF PENT,3DNOW,SM
+
+[PCMPEQB]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\x74\110 PENT,MMX,SM
+xmmreg,xmmrm \361\2\x0F\x74\110 WILLAMETTE,SSE2,SM
+
+[PCMPEQD]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\x76\110 PENT,MMX,SM
+xmmreg,xmmrm \361\2\x0F\x76\110 WILLAMETTE,SSE2,SM
+
+[PCMPEQW]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\x75\110 PENT,MMX,SM
+xmmreg,xmmrm \361\2\x0F\x75\110 WILLAMETTE,SSE2,SM
+
+[PCMPGTB]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\x64\110 PENT,MMX,SM
+xmmreg,xmmrm \361\2\x0F\x64\110 WILLAMETTE,SSE2,SM
+
+[PCMPGTD]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\x66\110 PENT,MMX,SM
+xmmreg,xmmrm \361\2\x0F\x66\110 WILLAMETTE,SSE2,SM
+
+[PCMPGTW]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\x65\110 PENT,MMX,SM
+xmmreg,xmmrm \361\2\x0F\x65\110 WILLAMETTE,SSE2,SM
+
+[PDISTIB]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \2\x0F\x54\110 PENT,MMX,SM,CYRIX
+
+[PF2ID]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\x0F\110\01\x1D PENT,3DNOW,SM
+
+[PFACC]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\x0F\110\01\xAE PENT,3DNOW,SM
+
+[PFADD]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\x0F\110\01\x9E PENT,3DNOW,SM
+
+[PFCMPEQ]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\x0F\110\01\xB0 PENT,3DNOW,SM
+
+[PFCMPGE]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\x0F\110\01\x90 PENT,3DNOW,SM
+
+[PFCMPGT]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\x0F\110\01\xA0 PENT,3DNOW,SM
+
+[PFMAX]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\x0F\110\01\xA4 PENT,3DNOW,SM
+
+[PFMIN]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\x0F\110\01\x94 PENT,3DNOW,SM
+
+[PFMUL]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\x0F\110\01\xB4 PENT,3DNOW,SM
+
+[PFRCP]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\x0F\110\01\x96 PENT,3DNOW,SM
+
+[PFRCPIT1]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\x0F\110\01\xA6 PENT,3DNOW,SM
+
+[PFRCPIT2]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\x0F\110\01\xB6 PENT,3DNOW,SM
+
+[PFRSQIT1]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\x0F\110\01\xA7 PENT,3DNOW,SM
+
+[PFRSQRT]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\x0F\110\01\x97 PENT,3DNOW,SM
+
+[PFSUB]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\x0F\110\01\x9A PENT,3DNOW,SM
+
+[PFSUBR]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\x0F\110\01\xAA PENT,3DNOW,SM
+
+[PI2FD]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\x0F\110\01\x0D PENT,3DNOW,SM
+
+[PMACHRIW]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \2\x0F\x5E\110 PENT,MMX,SM,CYRIX
+
+[PMADDWD]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\xF5\110 PENT,MMX,SM
+xmmreg,xmmrm \361\2\x0F\xF5\110 WILLAMETTE,SM,SSE2
+
+[PMAGW]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\x52\110 PENT,MMX,SM,CYRIX
+
+[PMULHRIW]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\x5D\110 PENT,MMX,SM,CYRIX
+
+[PMULHRWA]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\x0F\110\1\xB7 PENT,3DNOW,SM
+
+[PMULHRWC]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\x59\110 PENT,MMX,SM,CYRIX
+
+[PMULHW]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\xE5\110 PENT,MMX,SM
+xmmreg,xmmrm \361\2\x0F\xE5\110 WILLAMETTE,SSE2,SM
+
+[PMULLW]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\xD5\110 PENT,MMX,SM
+xmmreg,xmmrm \361\2\x0F\xD5\110 WILLAMETTE,SSE2,SM
+
+[PMVGEZB]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \2\x0F\x5C\110 PENT,MMX,SM,CYRIX
+
+[PMVLZB]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \2\x0F\x5B\110 PENT,MMX,SM,CYRIX
+
+[PMVNZB]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \2\x0F\x5A\110 PENT,MMX,SM,CYRIX
+
+[PMVZB]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \2\x0F\x58\110 PENT,MMX,SM,CYRIX
+
+[POP,popX]
+(Ch_Wop1, Ch_RWESP, Ch_None)
+reg16 \324\10\x58 8086
+reg32 \325\10\x58 386,NOX86_64
+reg64 \335\10\x58 X86_64
+rm16 \324\1\x8F\200 8086
+rm32 \325\1\x8F\200 386,NOX86_64
+rm64 \335\1\x8F\200 X86_64
+reg_cs \1\x0F 8086,UNDOC,ND
+reg_dess \4 8086,NOX86_64
+reg_fsgs \1\x0F\5\335 386
+
+[POPA,popaX]
+(Ch_All, Ch_None, Ch_None)
+void \327\1\x61 186,NOX86_64
+
+[POPAD,popal]
+(Ch_All, Ch_None, Ch_None)
+void \325\1\x61 386,NOX86_64
+
+[POPAW]
+(Ch_All, Ch_None, Ch_None)
+void \324\1\x61 186,NOX86_64
+
+[POPF]
+(Ch_RWESP, Ch_WFlags, Ch_None)
+void \327\1\x9D 186,NOX86_64
+void \326\1\x9D X86_64
+
+[POPFD,popfl]
+(Ch_RWESP, Ch_WFlags, Ch_None)
+void \325\1\x9D 386,NOX86_64
+
+[POPFW]
+(Ch_RWESP, Ch_WFLAGS, Ch_None)
+void \324\1\x9D 186,NOX86_64
+void \1\x9D X86_64
+
+[POPFQ]
+(Ch_RWESP, Ch_WFlags, Ch_None)
+void \326\1\x9D X86_64
+
+[POR]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\xEB\110 PENT,MMX,SM
+xmmreg,xmmreg \361\2\x0F\xEB\110 WILLAMETTE,SSE2,SM
+
+[PREFETCH,prefetchX]
+(Ch_All, Ch_None, Ch_None)
+mem \2\x0F\x0D\200 PENT,3DNOW,SM
+
+[PREFETCHW,prefetchwX]
+(Ch_All, Ch_None, Ch_None)
+mem \2\x0F\x0D\201 PENT,3DNOW,SM
+
+[PSLLD]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\xF2\110 PENT,MMX,SM
+mmxreg,imm \2\x0F\x72\206\25 PENT,MMX,SB,AR1
+xmmreg,xmmrm \361\2\x0F\xF2\110 WILLAMETTE,SSE2,SM
+xmmreg,imm \361\2\x0F\x72\206\25 WILLAMETTE,SSE2,SB,AR1
+
+[PSLLDQ]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,imm \361\2\x0F\x73\207\25 WILLAMETTE,SSE2,SB,AR1
+
+[PSLLQ]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\xF3\110 PENT,MMX,SM
+mmxreg,imm \2\x0F\x73\206\25 PENT,MMX,SB,AR1
+xmmreg,xmmrm \361\2\x0F\xF3\110 WILLAMETTE,SSE2,SM
+xmmreg,imm \361\2\x0F\x73\206\25 WILLAMETTE,SSE2,SB,AR1
+
+[PSLLW]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\xF1\110 PENT,MMX,SM
+mmxreg,imm \2\x0F\x71\206\25 PENT,MMX,SB,AR1
+xmmreg,xmmrm \361\2\x0F\xF1\110 WILLAMETTE,SSE2,SM
+xmmreg,imm \361\2\x0F\x71\206\25 WILLAMETTE,SSE2,SB,AR1
+
+[PSRAD]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\xE2\110 PENT,MMX,SM
+mmxreg,imm \2\x0F\x72\204\25 PENT,MMX,SB,AR1
+xmmreg,xmmrm \361\2\x0F\xE2\110 WILLAMETTE,SSE2,SM
+xmmreg,imm \361\2\x0F\x72\204\25 WILLAMETTE,SSE2,SB,AR1
+
+[PSRAW]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\xE1\110 PENT,MMX,SM
+mmxreg,imm \2\x0F\x71\204\25 PENT,MMX,SB,AR1
+xmmreg,xmmrm \361\2\x0F\xE1\110 WILLAMETTE,SSE2,SM
+xmmreg,imm \361\2\x0F\x71\204\25 WILLAMETTE,SSE2,SB,AR1
+
+[PSRLD]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\xD2\110 PENT,MMX,SM
+mmxreg,imm \2\x0F\x72\202\25 PENT,MMX,SB,AR1
+xmmreg,xmmrm \361\2\x0F\xD2\110 WILLAMETTE,SSE2,SM
+xmmreg,imm \361\2\x0F\x72\202\25 WILLAMETTE,SSE2,SB,AR1
+
+[PSRLQ]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\xD3\110 PENT,MMX,SM
+mmxreg,imm \2\x0F\x73\202\25 PENT,MMX,SB,AR1
+xmmreg,xmmrm \361\2\x0F\xD3\110 WILLAMETTE,SSE2,SM
+xmmreg,imm \361\2\x0F\x73\202\25 WILLAMETTE,SSE2,SB,AR1
+
+[PSRLW]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\xD1\110 PENT,MMX,SM
+mmxreg,imm \2\x0F\x71\202\25 PENT,MMX,SB,AR1
+xmmreg,xmmrm \361\2\x0F\xD1\110 WILLAMETTE,SSE2,SM
+xmmreg,imm \361\2\x0F\x71\202\25 WILLAMETTE,SSE2,SB,AR1
+
+[PSUBB]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\xF8\110 PENT,MMX,SM
+xmmreg,xmmrm \361\2\x0F\xF8\110 WILLAMETTE,SSE2,SM
+
+[PSUBD]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\xFA\110 PENT,MMX,SM
+xmmreg,xmmrm \361\2\x0F\xFA\110 WILLAMETTE,SSE2,SM
+
+[PSUBSB]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\xE8\110 PENT,MMX,SM
+xmmreg,xmmrm \361\2\x0F\xE8\110 WILLAMETTE,SSE2,SM
+
+[PSUBSIW]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mem \2\x0F\x55\110 PENT,MMX,SM,CYRIX
+mmxreg,mmxreg \2\x0F\x55\110 PENT,MMX,CYRIX
+
+[PSUBSW]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\xE9\110 PENT,MMX,SM
+xmmreg,xmmrm \361\2\x0F\xE9\110 WILLAMETTE,SSE2,SM
+
+[PSUBUSB]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\xD8\110 PENT,MMX,SM
+xmmreg,xmmrm \361\2\x0F\xD8\110 WILLAMETTE,SSE2,SM
+
+[PSUBUSW]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\xD9\110 PENT,MMX,SM
+xmmreg,xmmrm \361\2\x0F\xD9\110 WILLAMETTE,SSE2,SM
+
+[PSUBW]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\xF9\110 PENT,MMX,SM
+xmmreg,xmmrm \361\2\x0F\xF9\110 WILLAMETTE,SSE2,SM
+
+[PUNPCKHBW]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\x68\110 PENT,MMX,SM
+xmmreg,xmmrm \361\2\x0F\x68\110 WILLAMETTE,SSE2,SM
+
+[PUNPCKHDQ]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\x6A\110 PENT,MMX,SM
+xmmreg,xmmrm \361\2\x0F\x6A\110 WILLAMETTE,SSE2,SM
+
+[PUNPCKHWD]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\x69\110 PENT,MMX,SM
+xmmreg,xmmrm \361\2\x0F\x69\110 WILLAMETTE,SSE2,SM
+
+[PUNPCKLBW]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\x60\110 PENT,MMX,SM
+xmmreg,xmmrm \361\2\x0F\x60\110 WILLAMETTE,SSE2,SM
+
+[PUNPCKLDQ]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\x62\110 PENT,MMX,SM
+xmmreg,xmmrm \361\2\x0F\x62\110 WILLAMETTE,SSE2,SM
+
+[PUNPCKLWD]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\x61\110 PENT,MMX,SM
+xmmreg,xmmrm \361\2\x0F\x61\110 WILLAMETTE,SSE2,SM
+
+[PUSH,pushX]
+(Ch_Rop1, Ch_RWESP, Ch_None)
+reg16 \324\10\x50 8086
+reg32 \325\10\x50 386,NOX86_64
+reg64 \335\10\x50 X86_64
+rm16 \324\1\xFF\206 8086
+rm32 \325\1\xFF\206 386,NOX86_64
+rm64 \335\1\xFF\206 X86_64
+imm32 \325\1\x68\40\335 386
+imm16 \324\1\x68\30\335 286
+imm8 \1\x6A\14\335 286
+reg_fsgs \1\x0F\7\335 386,NOX86_64
+reg_sreg \6 8086,NOX86_64
+
+[PUSHA,pushaX]
+(Ch_All, Ch_None, Ch_None)
+void \327\1\x60 186,NOX86_64
+
+[PUSHAD,pushal]
+(Ch_All, Ch_None, Ch_None)
+void \325\1\x60 386,NOX86_64
+
+[PUSHAW]
+(Ch_All, Ch_None, Ch_None)
+void \324\1\x60 186,NOX86_64
+
+[PUSHF]
+(Ch_RWESP, Ch_RFlags, Ch_None)
+void \327\1\x9C 186
+
+[PUSHFD,pushfl]
+(Ch_RWESP, Ch_RFlags, Ch_None)
+void \325\1\x9C 386,NOX86_64
+
+[PUSHFW]
+(Ch_RWESP, Ch_RFLAGS, Ch_None)
+void \324\1\x9C 186
+
+[PUSHFQ]
+(Ch_RWESP, Ch_RFlags, Ch_None)
+void \326\1\x9C X86_64
+
+[PXOR]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+mmxreg,mmxrm \2\x0F\xEF\110 PENT,MMX,SM
+xmmreg,xmmrm \361\2\x0F\xEF\110 WILLAMETTE,SSE2,SM
+
+[RCL,rclX]
+(Ch_Mop2, Ch_Rop1, Ch_RWFlags)
+rm16|32|64,unity \320\1\xD1\202 8086
+rm16|32|64,reg_cl \320\1\xD3\202 8086
+rm16|32|64,imm \320\1\xC1\202\25 8086,SB
+rm8,unity \1\xD0\202 8086
+rm8,reg_cl \1\xD2\202 8086
+rm8,imm \1\xC0\202\25 186,SB
+
+[RCR,rcrX]
+(Ch_Mop2, Ch_Rop1, Ch_RWFlags)
+rm16|32|64,unity \320\1\xD1\203 8086
+rm16|32|64,reg_cl \320\1\xD3\203 8086
+rm16|32|64,imm \320\1\xC1\203\25 8086,SB
+rm8,unity \1\xD0\203 8086
+rm8,reg_cl \1\xD2\203 8086
+rm8,imm \1\xC0\203\25 186,SB
+
+[RDSHR]
+(Ch_All, Ch_None, Ch_None)
+void \2\x0F\x36 P6,CYRIX,SMM
+
+[RDMSR]
+(Ch_WEAX, Ch_WEDX, Ch_None)
+void \2\x0F\x32 PENT,PRIV
+
+[RDPMC]
+(Ch_WEAX, Ch_WEDX, Ch_None)
+void \2\x0F\x33 P6
+
+[RDTSC]
+(Ch_WEAX, Ch_WEDX, Ch_None)
+void \2\x0F\x31 PENT
+
+[REP]
+(Ch_RWECX, Ch_RWFlags, Ch_None)
+void \1\xF3 8086,PRE
+
+[REPE]
+(Ch_RWECX, Ch_RWFlags, Ch_None)
+void \1\xF3 8086,PRE
+
+[REPNE]
+(Ch_RWECX, Ch_RWFlags, Ch_None)
+void \1\xF2 8086,PRE
+
+[REPNZ]
+(Ch_RWECX, Ch_RWFLAGS, Ch_None)
+void \1\xF2 8086,PRE
+
+[REPZ]
+(Ch_RWECX, Ch_RWFLAGS, Ch_None)
+void \1\xF3 8086,PRE
+
+[RET]
+(Ch_All, Ch_None, Ch_None)
+void \1\xC3 8086
+imm \1\xC2\30 8086,SW
+
+[RETF,lret]
+(Ch_All, Ch_None, Ch_None)
+void \1\xCB 8086
+imm \1\xCA\30 8086,SW
+
+[RETN,ret]
+(Ch_All, Ch_None, Ch_None)
+void \1\xC3 8086
+imm \1\xC2\30 8086,SW
+
+[ROL,rolX]
+(Ch_Mop2, Ch_Rop1, Ch_RWFlags)
+rm16|32|64,unity \320\1\xD1\200 8086
+rm16|32|64,reg_cl \320\1\xD3\200 8086
+rm16|32|64,imm \320\1\xC1\200\25 8086,SB
+rm8,unity \1\xD0\200 8086
+rm8,reg_cl \1\xD2\200 8086
+rm8,imm \1\xC0\200\25 186,SB
+
+[ROR,rorX]
+(Ch_Mop2, Ch_Rop1, Ch_RWFlags)
+rm16|32|64,unity \320\1\xD1\201 8086
+rm16|32|64,reg_cl \320\1\xD3\201 8086
+rm16|32|64,imm \320\1\xC1\201\25 8086,SB
+rm8,unity \1\xD0\201 8086
+rm8,reg_cl \1\xD2\201 8086
+rm8,imm \1\xC0\201\25 186,SB
+
+[RSDC]
+(Ch_All, Ch_None, Ch_None)
+reg_sreg,mem80 \2\x0F\x79\101 486,CYRIX,SMM
+
+[RSLDT]
+(Ch_All, Ch_None, Ch_None)
+mem80 \2\x0F\x7B\200 486,CYRIX,SMM
+
+[RSM]
+(Ch_All, Ch_None, Ch_None)
+void \2\x0F\xAA PENT,SMM
+
+; SAHF/LAHF are valid in x86_64 only if CPUID.80000001h:ECX.0=1
+[SAHF]
+(Ch_WFlags, Ch_REAX, Ch_None)
+void \1\x9E 8086
+
+[SAL,salX]
+(Ch_Mop2, Ch_Rop1, Ch_RWFlags)
+rm16|32|64,unity \320\1\xD1\204 8086,ND
+rm16|32|64,reg_cl \320\1\xD3\204 8086,ND
+rm16|32|64,imm \320\1\xC1\204\25 8086,ND,SB
+rm8,unity \1\xD0\204 8086,ND
+rm8,reg_cl \1\xD2\204 8086,ND
+rm8,imm \1\xC0\204\25 186,ND,SB
+
+[SALC]
+(Ch_WEAX, Ch_RFLAGS, Ch_None)
+void \1\xD6 8086,UNDOC,NOX86_64
+
+[SAR,sarX]
+(Ch_Mop2, Ch_Rop1, Ch_WFlags)
+rm16|32|64,unity \320\1\xD1\207 8086
+rm16|32|64,reg_cl \320\1\xD3\207 8086
+rm16|32|64,imm \320\1\xC1\207\25 8086,SB
+rm8,unity \1\xD0\207 8086
+rm8,reg_cl \1\xD2\207 8086
+rm8,imm \1\xC0\207\25 186,SB
+
+[SBB,sbbX]
+(Ch_Mop2, Ch_Rop1, Ch_RWFlags)
+regmem,reg16|32|64 \320\1\x19\101 8086,SM
+reg16|32|64,regmem \320\1\x1B\110 8086,SM
+rm16|32|64,imm8 \320\1\x83\203\15 8086
+rm8,reg8 \1\x18\101 8086
+reg8,rm8 \1\x1A\110 8086,SM
+reg_eax,imm \325\1\x1D\41 386,SM
+reg_rax,imm \326\1\x1D\255 X86_64,SM
+rm32,imm \320\1\x81\203\41 386,SM
+rm64,imm \326\1\x81\203\255 X86_64,SM
+reg_ax,imm \324\1\x1D\31 8086,SW
+rm16,imm \320\1\x81\203\31 8086,SW
+reg_al,imm \1\x1C\21 8086,SB
+rm8,imm \1\x80\203\21 8086,SB
+
+[SCASB]
+(Ch_All, Ch_None, Ch_None)
+void \332\1\xAE 8086
+
+[SCASD,scasl]
+(Ch_All, Ch_None, Ch_None)
+void \332\325\1\xAF 386
+
+[SCASQ]
+(Ch_All, Ch_None, Ch_None)
+void \332\326\1\xAF X86_64
+
+[SCASW]
+(Ch_All, Ch_None, Ch_None)
+void \332\324\1\xAF 8086
+
+[SEGCS,cs]
+(Ch_None, Ch_None, Ch_None)
+void \1\x2E 8086,PRE
+
+[SEGDS,ds]
+(Ch_None, Ch_None, Ch_None)
+void \1\x3E 8086,PRE
+
+[SEGES,es]
+(Ch_None, Ch_None, Ch_None)
+void \1\x26 8086,PRE
+
+[SEGFS,fs]
+(Ch_None, Ch_None, Ch_None)
+void \1\x64 8086,PRE
+
+[SEGGS,gs]
+(Ch_None, Ch_None, Ch_None)
+void \1\x65 8086,PRE
+
+[SEGSS,ss]
+(Ch_None, Ch_None, Ch_None)
+void \1\x36 8086,PRE
+
+[SGDT]
+(Ch_Wop1, Ch_None, Ch_None)
+mem \2\x0F\x01\200 286
+
+[SHL,shlX]
+(Ch_Mop2, Ch_Rop1, Ch_WFlags)
+rm16|32|64,unity \320\1\xD1\204 8086
+rm16|32|64,reg_cl \320\1\xD3\204 8086
+rm16|32|64,imm \320\1\xC1\204\25 186,SW
+rm8,unity \1\xD0\204 8086
+rm8,reg_cl \1\xD2\204 8086
+rm8,imm \1\xC0\204\25 186,SB
+
+[SHLD,shldX]
+(Ch_MOp3, Ch_RWFlags, Ch_Rop2)
+rm16|32|64,reg16|32|64,imm \321\2\x0F\xA4\101\26 386,SM2,SB,AR2
+rm16|32|64,reg16|32|64,reg_cl \321\2\x0F\xA5\101 386,SM
+
+[SHR,shrX]
+(Ch_Mop2, Ch_Rop1, Ch_WFlags)
+rm16|32|64,unity \320\1\xD1\205 8086
+rm16|32|64,reg_cl \320\1\xD3\205 8086
+rm16|32|64,imm \320\1\xC1\205\25 186,SW
+rm8,unity \1\xD0\205 8086
+rm8,reg_cl \1\xD2\205 8086
+rm8,imm \1\xC0\205\25 186,SB
+
+[SHRD,shrdX]
+(Ch_MOp3, Ch_RWFlags, Ch_Rop2)
+rm16|32|64,reg16|32|64,imm \321\2\x0F\xAC\101\26 386,SM2,SB,AR2
+rm16|32|64,reg16|32|64,reg_cl \321\2\x0F\xAD\101 386,SM
+
+[SIDT,sidtX]
+(Ch_Wop1, Ch_None, Ch_None)
+mem \2\x0F\x01\201 286
+
+[SLDT,sldtX]
+(Ch_Wop1, Ch_None, Ch_None)
+mem \2\x0F\x00\200 286
+reg16|32|64 \320\2\x0F\x00\200 286
+
+[SMI]
+(Ch_All, Ch_None, Ch_None)
+void \1\xF1 386,UNDOC
+
+[SMINT]
+(Ch_All, Ch_None, Ch_None)
+void \2\x0F\x38 P6,CYRIX
+
+[SMINTOLD]
+(Ch_All, Ch_None, Ch_None)
+void \2\x0F\x7E 486,CYRIX,ND
+
+[SMSW,smswX]
+(Ch_Wop1, Ch_None, Ch_None)
+rm16|32|64 \320\2\x0F\x01\204 286
+
+[STC]
+(Ch_WFlags, Ch_None, Ch_None)
+void \1\xF9 8086
+
+[STD]
+(Ch_SDirFlag, Ch_None, Ch_None)
+void \1\xFD 8086
+
+[STI]
+(Ch_WFlags, Ch_None, Ch_None)
+void \1\xFB 8086
+
+[STOSB]
+(Ch_REAX, Ch_WMemEDI, Ch_RWEDI)
+void \1\xAA 8086
+
+[STOSD,stosl]
+(Ch_REAX, Ch_WMemEDI, Ch_RWEDI)
+void \325\1\xAB 386
+
+[STOSW]
+(Ch_REAX, Ch_WMemEDI, Ch_RWEDI)
+void \324\1\xAB 8086
+
+[STR,strX]
+(Ch_Wop1, Ch_None, Ch_None)
+mem \2\x0F\x00\201 286,PROT
+reg16|32|64 \320\2\x0F\x00\201 286,PROT
+
+[SUB,subX]
+(Ch_Mop2, Ch_Rop1, Ch_WFlags)
+regmem,reg16|32|64 \320\1\x29\101 8086,SM
+reg16|32|64,regmem \320\1\x2B\110 8086,SM
+rm8,reg8 \1\x28\101 8086
+reg8,rm8 \1\x2A\110 8086,SM
+rm16|32|64,imm8 \320\1\x83\205\15 8086
+reg_eax,imm \325\1\x2D\41 386,SM
+reg_rax,imm \326\1\x2D\255 X86_64,SM
+rm32,imm \320\1\x81\205\41 386,SM
+rm64,imm \326\1\x81\205\255 X86_64,SM
+reg_ax,imm \324\1\x2D\31 8086,SW
+rm16,imm \324\1\x81\205\31 8086,SW
+reg_al,imm \1\x2C\21 8086,SB
+rm8,imm \1\x80\205\21 8086,SB
+
+[SVDC,svdcX]
+(Ch_All, Ch_None, Ch_None)
+mem80,reg_sreg \2\x0F\x78\101 486,CYRIX,SMM
+
+[SVLDT,svldtX]
+(Ch_All, Ch_None, Ch_None)
+mem80 \2\x0F\x7A\200 486,CYRIX,SMM
+
+[SVTS,svtsX]
+(Ch_All, Ch_None, Ch_None)
+mem80 \2\x0F\x7C\200 486,CYRIX,SMM
+
+[SYSCALL]
+(Ch_All, Ch_None, Ch_None)
+void \2\x0F\x05 P6,AMD
+
+[SYSENTER]
+(Ch_All, Ch_None, Ch_None)
+void \2\x0F\x34 P6
+
+[SYSEXIT]
+(Ch_All, Ch_None, Ch_None)
+void \2\x0F\x35 P6,PRIV
+
+[SYSRET]
+(Ch_All, Ch_None, Ch_None)
+void \2\x0F\x07 P6,PRIV,AMD
+
+[TEST,testX]
+(Ch_WFlags, Ch_Rop1, Ch_Rop2)
+regmem,reg16|32|64 \320\1\x85\101 8086,SM
+reg16|32|64,mem \320\1\x85\110 8086,SM
+reg8,reg8 \1\x84\101 8086
+rm8,reg8 \1\x84\101 8086,SM
+reg_rax,imm \326\1\xA9\255 X86_64,SM
+reg_eax,imm \325\1\xA9\41 386,SM
+reg_ax,imm \324\1\xA9\31 8086,SM
+reg_al,imm \1\xA8\21 8086,SM
+rm64,imm \326\1\xF7\200\255 X86_64,SM
+rm32,imm \325\1\xF7\200\41 386,SM
+rm16,imm \324\1\xF7\200\31 8086,SM
+rm8,imm \1\xF6\200\21 8086,SM
+mem,imm32 \325\1\xF7\200\41 386,SM
+mem,imm16 \324\1\xF7\200\31 8086,SM
+mem,imm8 \1\xF6\200\21 8086,SM
+
+[UD1]
+(Ch_All, Ch_None, Ch_None)
+void \2\x0F\xB9 286,UNDOC
+
+[UD2]
+(Ch_All, Ch_None, Ch_None)
+void \2\x0F\x0B 286
+
+[UMOV,umovX]
+(Ch_All, Ch_None, Ch_None)
+regmem,reg16|32|64 \320\2\x0F\x11\101 386,UNDOC,SM
+reg16|32|64,mem \320\2\x0F\x13\110 386,UNDOC,SM
+rm8,reg8 \2\x0F\x10\101 386,UNDOC
+reg8,rm8 \2\x0F\x12\110 386,UNDOC
+
+[VERR,verrX]
+(Ch_WFlags, Ch_None, Ch_None)
+mem \2\x0F\x00\204 286,PROT
+mem16 \2\x0F\x00\204 286,PROT
+reg16 \2\x0F\x00\204 286,PROT
+
+[VERW]
+(Ch_WFlags, Ch_None, Ch_None)
+mem \2\x0F\x00\205 286,PROT
+mem16 \2\x0F\x00\205 286,PROT
+reg16 \2\x0F\x00\205 286,PROT
+
+[WAIT]
+(Ch_None, Ch_None, Ch_None)
+void \1\x9B 8086
+
+[WBINVD]
+(Ch_None, Ch_None, Ch_None)
+void \2\x0F\x09 486,PRIV
+
+[WRSHR]
+(Ch_All, Ch_None, Ch_None)
+void \2\x0F\x37 P6,CYRIX,SMM
+
+[WRMSR]
+(Ch_All, Ch_None, Ch_None)
+void \2\x0F\x30 PENT,PRIV
+
+[XADD,xaddX]
+(Ch_All, Ch_None, Ch_None)
+mem,reg16|32|64 \320\2\x0F\xC1\101 486,SM
+rm8,reg8 \2\x0F\xC0\101 486
+
+[XBTS,xbtsX]
+(Ch_All, Ch_None, Ch_None)
+reg16,mem \324\2\x0F\xA6\110 386,SW,UNDOC,ND
+reg16,reg16 \324\2\x0F\xA6\110 386,UNDOC,ND
+reg32,mem \325\2\x0F\xA6\110 386,SD,UNDOC,ND
+reg32,reg32 \325\2\x0F\xA6\110 386,UNDOC,ND
+
+[XCHG,xchgX]
+(Ch_RWop1, Ch_RWop2, Ch_None)
+reg_ax,reg16 \324\11\x90 8086
+reg_eax,reg32 \325\11\x90 386
+reg_rax,reg64 \326\11\x90 X86_64
+reg16,reg_ax \324\10\x90 8086
+reg32,reg_eax \325\10\x90 386
+reg64,reg_rax \326\10\x90 X86_64
+reg16|32|64,regmem \320\1\x87\110 8086,SM
+mem,reg16|32|64 \320\1\x87\101 8086,SM
+reg8,rm8 \1\x86\110 8086
+mem8,reg8 \1\x86\101 8086
+
+[XLAT]
+(Ch_WEAX, Ch_REBX, Ch_None)
+void \1\xD7 8086
+
+[XLATB]
+(Ch_WEAX, Ch_REBX, Ch_None)
+void \1\xD7 8086
+
+[XOR,xorX]
+(Ch_Mop2, Ch_Rop1, Ch_WFlags)
+regmem,reg16|32|64 \320\1\x31\101 8086,SM
+reg16|32|64,regmem \320\1\x33\110 8086,SM
+rm8,reg8 \1\x30\101 8086
+reg8,rm8 \1\x32\110 8086
+rm16|32|64,imm8 \320\1\x83\206\15 8086
+reg_eax,imm \325\1\x35\41 386,SM
+reg_rax,imm \326\1\x35\255 X86_64,SM
+rm32,imm \320\1\x81\206\41 386,SM
+rm64,imm \326\1\x81\206\255 X86_64,SM
+reg_ax,imm \324\1\x35\31 8086,SW
+rm16,imm \324\1\x81\206\31 8086,SW
+reg_al,imm \1\x34\21 8086,SB
+rm8,imm \1\x80\206\21 8086,SB
+
+[XSTORE]
+(Ch_All, Ch_None, Ch_None)
+void \3\x0F\xA7\xC0 P6,CYRIX
+
+[XCRYPTECB]
+(Ch_All, Ch_None, Ch_None)
+void \333\3\x0F\xA7\xC8 P6,CYRIX
+
+[XCRYPTCBC]
+(Ch_All, Ch_None, Ch_None)
+void \333\3\x0F\xA7\xD0 P6,CYRIX
+
+[XCRYPTCFB]
+(Ch_All, Ch_None, Ch_None)
+void \333\3\x0F\xA7\xE0 P6,CYRIX
+
+[XCRYPTOFB]
+(Ch_All, Ch_None, Ch_None)
+void \333\3\x0F\xA7\xE8 P6,CYRIX
+
+[CMOVcc,cmovCCX]
+(Ch_ROp1, Ch_WOp2, Ch_RFLAGS)
+reg16|32|64,regmem \320\1\x0F\13\x40\110 P6,SM
+
+[Jcc]
+(Ch_RFLAGS, Ch_None, Ch_None)
+imm8 \13\x70\50 8086
+imm16|32 \320\1\x0F\13\x80\64 386,PASS2
+imm|short \13\x70\50 8086
+imm|near \320\1\x0F\13\x80\64 386,PASS2
+
+[SETcc,setCCX]
+(Ch_RFLAGS, Ch_WOp1, Ch_None)
+rm8 \1\x0F\13\x90\200 386
+
+;
+; Katmai Streaming SIMD instructions (SSE -- a.k.a. KNI, XMM, MMX2)
+;
+
+[ADDPS]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+xmmreg,xmmrm \331\2\x0F\x58\110 KATMAI,SSE
+
+[ADDSS]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+xmmreg,xmmrm \333\2\x0F\x58\110 KATMAI,SSE
+
+[ANDNPS]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+xmmreg,xmmrm \2\x0F\x55\110 KATMAI,SSE
+
+[ANDPS]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+xmmreg,xmmrm \2\x0F\x54\110 KATMAI,SSE
+
+[CMPEQPS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \331\2\x0F\xC2\110\1\x00 KATMAI,SSE
+
+[CMPEQSS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \333\2\x0F\xC2\110\1\x00 KATMAI,SSE
+
+[CMPLEPS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \331\2\x0F\xC2\110\1\x02 KATMAI,SSE
+
+[CMPLESS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \333\2\x0F\xC2\110\1\x02 KATMAI,SSE
+
+[CMPLTPS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \331\2\x0F\xC2\110\1\x01 KATMAI,SSE
+
+[CMPLTSS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \333\2\x0F\xC2\110\1\x01 KATMAI,SSE
+
+[CMPNEQPS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \331\2\x0F\xC2\110\1\x04 KATMAI,SSE
+
+[CMPNEQSS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \333\2\x0F\xC2\110\1\x04 KATMAI,SSE
+
+[CMPNLEPS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \331\2\x0F\xC2\110\1\x06 KATMAI,SSE
+
+[CMPNLESS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \333\2\x0F\xC2\110\1\x06 KATMAI,SSE
+
+[CMPNLTPS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \331\2\x0F\xC2\110\1\x05 KATMAI,SSE
+
+[CMPNLTSS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \333\2\x0F\xC2\110\1\x05 KATMAI,SSE
+
+[CMPORDPS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \331\2\x0F\xC2\110\1\x07 KATMAI,SSE
+
+[CMPORDSS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \333\2\x0F\xC2\110\1\x07 KATMAI,SSE
+
+[CMPUNORDPS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \331\2\x0F\xC2\110\1\x03 KATMAI,SSE
+
+[CMPUNORDSS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \333\2\x0F\xC2\110\1\x03 KATMAI,SSE
+
+;
+; CMPPS/CMPSS must come after the specific ops; that way the disassembler will find the
+; specific ops first and only disassemble illegal ones as cmpps.
+;
+
+[CMPPS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm,imm \331\2\x0F\xC2\110\22 KATMAI,SSE,SB,AR2
+
+[CMPSS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm,imm \333\2\x0F\xC2\110\22 KATMAI,SSE,SB,AR2
+
+[COMISS]
+(Ch_Rop1, Ch_Rop2, Ch_WFlags)
+xmmreg,xmmrm \2\x0F\x2F\110 KATMAI,SSE
+
+[CVTPI2PS]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+xmmreg,mem \331\2\x0F\x2A\110 KATMAI,SSE,MMX
+xmmreg,mmxreg \331\2\x0F\x2A\110 KATMAI,SSE,MMX
+
+[CVTPS2PI]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+mmxreg,mem \331\2\x0F\x2D\110 KATMAI,SSE,MMX
+mmxreg,xmmreg \331\2\x0F\x2D\110 KATMAI,SSE,MMX
+
+[CVTSI2SS,cvtsi2ssX]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+xmmreg,mem \333\321\2\x0F\x2A\110 KATMAI,SSE
+xmmreg,reg32|64 \333\321\2\x0F\x2A\110 KATMAI,SSE
+
+[CVTSS2SI,cvtss2siX]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+reg32|64,mem \333\320\2\x0F\x2D\110 KATMAI,SSE
+reg32|64,xmmreg \333\320\2\x0F\x2D\110 KATMAI,SSE
+
+[CVTTPS2PI]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+mmxreg,mem \331\2\x0F\x2C\110 KATMAI,SSE,MMX
+mmxreg,xmmreg \331\2\x0F\x2C\110 KATMAI,SSE,MMX
+
+[CVTTSS2SI,cvttss2siX]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+reg32|64,mem \333\320\2\x0F\x2C\110 KATMAI,SSE
+reg32|64,xmmreg \333\320\2\x0F\x2C\110 KATMAI,SSE
+
+[DIVPS]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+xmmreg,xmmrm \331\2\x0F\x5E\110 KATMAI,SSE
+
+[DIVSS]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+xmmreg,xmmrm \333\2\x0F\x5E\110 KATMAI,SSE
+
+[LDMXCSR]
+(Ch_All, Ch_None, Ch_None)
+mem \2\x0F\xAE\202 KATMAI,SSE,SD
+
+[MAXPS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \331\2\x0F\x5F\110 KATMAI,SSE
+
+[MAXSS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \333\2\x0F\x5F\110 KATMAI,SSE
+
+[MINPS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \331\2\x0F\x5D\110 KATMAI,SSE
+
+[MINSS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \333\2\x0F\x5D\110 KATMAI,SSE
+
+[MOVAPS]
+(Ch_ROp1, Ch_WOp2, Ch_None)
+xmmreg,xmmrm \2\x0F\x28\110 KATMAI,SSE
+xmmrm,xmmreg \2\x0F\x29\101 KATMAI,SSE
+
+[MOVHPS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,mem \2\x0F\x16\110 KATMAI,SSE
+mem,xmmreg \2\x0F\x17\101 KATMAI,SSE
+
+[MOVLHPS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmreg \2\x0F\x16\110 KATMAI,SSE
+
+[MOVLPS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,mem \2\x0F\x12\110 KATMAI,SSE
+mem,xmmreg \2\x0F\x13\101 KATMAI,SSE
+
+[MOVHLPS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmreg \2\x0F\x12\110 KATMAI,SSE
+
+[MOVMSKPS]
+(Ch_All, Ch_None, Ch_None)
+reg32,xmmreg \2\x0F\x50\110 KATMAI,SSE
+
+[MOVNTPS]
+(Ch_All, Ch_None, Ch_None)
+mem,xmmreg \2\x0F\x2B\101 KATMAI,SSE
+
+[MOVSS]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+xmmreg,xmmrm \333\2\x0F\x10\110 KATMAI,SSE
+xmmrm,xmmreg \333\2\x0F\x11\101 KATMAI,SSE
+
+[MOVUPS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \331\2\x0F\x10\110 KATMAI,SSE
+xmmrm,xmmreg \331\2\x0F\x11\101 KATMAI,SSE
+
+[MULPS]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+xmmreg,xmmrm \2\x0F\x59\110 KATMAI,SSE
+
+[MULSS]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+xmmreg,xmmrm \333\2\x0F\x59\110 KATMAI,SSE
+
+[ORPS]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+xmmreg,xmmrm \2\x0F\x56\110 KATMAI,SSE
+
+[RCPPS]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+xmmreg,xmmrm \331\2\x0F\x53\110 KATMAI,SSE
+
+[RCPSS]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+xmmreg,xmmrm \333\2\x0F\x53\110 KATMAI,SSE
+
+[RSQRTPS]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+xmmreg,xmmrm \331\2\x0F\x52\110 KATMAI,SSE
+
+[RSQRTSS]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+xmmreg,xmmrm \333\2\x0F\x52\110 KATMAI,SSE
+
+[SHUFPS]
+(Ch_Mop3, Ch_Rop2, Ch_None)
+xmmreg,xmmrm,imm \2\x0F\xC6\110\22 KATMAI,SSE,SB,AR2
+
+[SQRTPS]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+xmmreg,xmmrm \331\2\x0F\x51\110 KATMAI,SSE
+
+[SQRTSS]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+xmmreg,xmmrm \333\2\x0F\x51\110 KATMAI,SSE
+
+[STMXCSR]
+(Ch_All, Ch_None, Ch_None)
+mem \2\x0F\xAE\203 KATMAI,SSE,SD
+
+[SUBPS]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+xmmreg,xmmrm \331\2\x0F\x5C\110 KATMAI,SSE
+
+[SUBSS]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+xmmreg,xmmrm \333\2\x0F\x5C\110 KATMAI,SSE
+
+[UCOMISS]
+(Ch_Rop1, Ch_Rop2, Ch_WFlags)
+xmmreg,xmmrm \2\x0F\x2E\110 KATMAI,SSE
+
+[UNPCKHPS]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+xmmreg,xmmrm \2\x0F\x15\110 KATMAI,SSE
+
+[UNPCKLPS]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+xmmreg,xmmrm \2\x0F\x14\110 KATMAI,SSE
+
+[XORPS]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+xmmreg,xmmrm \2\x0F\x57\110 KATMAI,SSE
+
+;
+; Introduced in Dechutes but necessary for SSE support
+;
+
+[FXRSTOR]
+(Ch_All, Ch_None, Ch_None)
+mem \2\x0F\xAE\201 P6,SSE,FPU
+
+[FXSAVE]
+(Ch_All, Ch_None, Ch_None)
+mem \2\x0F\xAE\200 P6,SSE,FPU
+
+;
+; These instructions aren't SSE-specific; they are generic memory operations
+; and work even if CR4.OSFXFR == 0
+;
+
+[PREFETCHNTA]
+(Ch_All, Ch_None, Ch_None)
+mem \2\x0F\x18\200 KATMAI
+
+[PREFETCHT0]
+(Ch_All, Ch_None, Ch_None)
+mem \2\x0F\x18\201 KATMAI
+
+[PREFETCHT1]
+(Ch_All, Ch_None, Ch_None)
+mem \2\x0F\x18\202 KATMAI
+
+[PREFETCHT2]
+(Ch_All, Ch_None, Ch_None)
+mem \2\x0F\x18\203 KATMAI
+
+[SFENCE]
+(Ch_All, Ch_None, Ch_None)
+void \3\x0F\xAE\xF8 KATMAI
+
+;
+; New MMX instructions introduced in Katmai
+;
+
+[MASKMOVQ]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxreg \2\x0F\xF7\110 KATMAI,MMX
+
+[MOVNTQ]
+(Ch_All, Ch_None, Ch_None)
+mem,mmxreg \2\x0F\xE7\101 KATMAI,MMX,SM
+
+[PAVGB]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\xE0\110 KATMAI,MMX,SM
+xmmreg,xmmrm \361\2\x0F\xE0\110 WILLAMETTE,SSE2,SM
+
+[PAVGW]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\xE3\110 KATMAI,MMX,SM
+xmmreg,xmmrm \361\2\x0F\xE3\110 WILLAMETTE,SSE2,SM
+
+[PEXTRW]
+(Ch_All, Ch_None, Ch_None)
+reg32,mmxreg,imm \2\x0F\xC5\110\22 KATMAI,MMX,SB,AR2
+reg32,xmmreg,imm \361\2\x0F\xC5\110\26 SSE41
+mem32,xmmreg,imm \361\3\x0F\x3A\x15\101\26 SSE41
+
+
+[PINSRW]
+(Ch_All, Ch_None, Ch_None)
+; PINSRW is documented as using a reg32, but it's really using only 16 bit
+; -- accept either, but be truthful in disassembly
+mmxreg,reg16,imm \2\x0F\xC4\110\22 KATMAI,MMX,SB,AR2
+mmxreg,reg32,imm \2\x0F\xC4\110\22 KATMAI,MMX,SB,AR2,ND
+mmxreg,mem,imm \2\x0F\xC4\110\22 KATMAI,MMX,SB,AR2
+mmxreg,mem16,imm \2\x0F\xC4\110\22 KATMAI,MMX,SB,AR2,ND
+xmmreg,reg16,imm \361\2\x0F\xC4\110\26 WILLAMETTE,SSE2,SB,AR2
+xmmreg,reg32,imm \361\2\x0F\xC4\110\26 WILLAMETTE,SSE2,SB,AR2,ND
+xmmreg,mem,imm \361\2\x0F\xC4\110\26 WILLAMETTE,SSE2,SB,AR2
+xmmreg,mem16,imm \361\2\x0F\xC4\110\26 WILLAMETTE,SSE2,SB,AR2,ND
+
+[PMAXSW]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\xEE\110 KATMAI,MMX,SM
+xmmreg,xmmrm \361\2\x0F\xEE\110 WILLAMETTE,SSE2,SM
+
+[PMAXUB]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\xDE\110 KATMAI,MMX,SM
+xmmreg,xmmrm \361\2\x0F\xDE\110 WILLAMETTE,SSE2,SM
+
+[PMINSW]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\xEA\110 KATMAI,MMX,SM
+xmmreg,xmmrm \361\2\x0F\xEA\110 WILLAMETTE,SSE2,SM
+
+[PMINUB]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\xDA\110 KATMAI,MMX,SM
+xmmreg,xmmrm \361\2\x0F\xDA\110 WILLAMETTE,SSE2,SM
+
+[PMOVMSKB]
+(Ch_All, Ch_None, Ch_None)
+reg32,mmxreg \2\x0F\xD7\110 KATMAI,MMX
+reg32,xmmreg \361\2\x0F\xD7\110 WILLAMETTE,SSE2
+
+[PMULHUW]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\xE4\110 KATMAI,MMX,SM
+xmmreg,xmmrm \361\2\x0F\xE4\110 WILLAMETTE,SSE2,SM
+
+[PSADBW]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\xF6\110 KATMAI,MMX,SM
+xmmreg,xmmrm \361\2\x0F\xF6\110 WILLAMETTE,SSE2,SM
+
+[PSHUFW]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm,imm \2\x0F\x70\110\22 KATMAI,MMX,SM2,SB,AR2
+
+;
+; New Athlon Instructions
+;
+
+[PFNACC]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\x0F\110\01\x8A PENT,3DNOW,SM
+
+[PFPNACC]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\x0F\110\01\x8E PENT,3DNOW,SM
+
+[PI2FW]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\x0F\110\01\x0C PENT,3DNOW,SM
+
+[PF2IW]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\x0F\110\01\x1C PENT,3DNOW,SM
+
+[PSWAPD]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\x0F\110\01\xBB PENT,3DNOW,SM
+
+[FFREEP]
+(Ch_All, Ch_None, Ch_None)
+fpureg \1\xDF\10\xC0 PENT,3DNOW,FPU
+
+; Willamette SSE2 Cacheability Instructions
+[MASKMOVDQU]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmreg \361\2\x0F\xF7\110 WILLAMETTE,SSE2
+
+; CLFLUSH needs its own feature flag implemented one day
+[CLFLUSH]
+(Ch_All, Ch_None, Ch_None)
+mem \2\x0F\xAE\207 WILLAMETTE,SSE2
+
+[MOVNTDQ]
+(Ch_All, Ch_None, Ch_None)
+mem,xmmreg \361\2\x0F\xE7\101 WILLAMETTE,SSE2,SM
+
+[MOVNTI,movntiX]
+(Ch_All, Ch_None, Ch_None)
+mem,reg32|64 \320\2\x0F\xC3\101 WILLAMETTE,SSE2,SM
+
+[MOVNTPD]
+(Ch_All, Ch_None, Ch_None)
+mem,xmmreg \361\2\x0F\x2B\101 WILLAMETTE,SSE2,SM
+
+[PAUSE]
+(Ch_All, Ch_None, Ch_None)
+void \333\1\x90 WILLAMETTE,SSE2
+
+[LFENCE]
+(Ch_All, Ch_None, Ch_None)
+void \3\x0F\xAE\xE8 WILLAMETTE,SSE2
+
+[MFENCE]
+(Ch_All, Ch_None, Ch_None)
+void \3\x0F\xAE\xF0 WILLAMETTE,SSE2
+
+;
+; Willamette MMX instructions (SSE2 SIMD Integer Instructions)
+;
+[MOVDQA]
+(Ch_All, Ch_None, Ch_None)
+xmmrm,xmmreg \361\2\x0F\x7F\101 WILLAMETTE,SSE2,SM
+xmmreg,xmmrm \361\2\x0F\x6F\110 WILLAMETTE,SSE2,SM
+
+[MOVDQU]
+(Ch_All, Ch_None, Ch_None)
+xmmrm,xmmreg \333\2\x0F\x7F\101 WILLAMETTE,SSE2,SM
+xmmreg,xmmrm \333\2\x0F\x6F\110 WILLAMETTE,SSE2,SM
+
+[MOVDQ2Q]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,xmmreg \334\2\x0F\xD6\110 WILLAMETTE,SSE2
+
+[MOVQ2DQ]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,mmxreg \333\2\x0F\xD6\110 WILLAMETTE,SSE2
+
+[PADDQ]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\xD4\110 WILLAMETTE,SSE2,SM
+xmmreg,xmmrm \361\2\x0F\xD4\110 WILLAMETTE,SSE2,SM
+
+[PMULUDQ]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\xF4\110 WILLAMETTE,SSE2,SM
+xmmreg,xmmrm \361\2\x0F\xF4\110 WILLAMETTE,SSE2,SM
+
+[PSHUFD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm,imm \361\2\x0F\x70\110\22 WILLAMETTE,SSE2,SM2,SB,AR2
+
+[PSHUFHW]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm,imm \333\2\x0F\x70\110\22 WILLAMETTE,SSE2,SM2,SB,AR2
+
+[PSHUFLW]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm,imm \334\2\x0F\x70\110\22 WILLAMETTE,SSE2,SM2,SB,AR2
+
+[PSRLDQ]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,imm \361\2\x0F\x73\203\25 WILLAMETTE,SSE2,SB,AR1
+
+[PSUBQ]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \2\x0F\xFB\110 WILLAMETTE,SSE2,SM
+xmmreg,xmmrm \361\2\x0F\xFB\110 WILLAMETTE,SSE2,SM
+
+[PUNPCKHQDQ]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \361\2\x0F\x6D\110 WILLAMETTE,SSE2,SM
+
+[PUNPCKLQDQ]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \361\2\x0F\x6C\110 WILLAMETTE,SSE2,SM
+
+;
+; Willamette Streaming SIMD instructions (SSE2)
+;
+[ADDPD]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+xmmreg,xmmrm \361\2\x0F\x58\110 WILLAMETTE,SSE2,SM
+
+[ADDSD]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+xmmreg,xmmrm \334\2\x0F\x58\110 WILLAMETTE,SSE2
+
+[ANDNPD]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+xmmreg,xmmrm \361\2\x0F\x55\110 WILLAMETTE,SSE2,SM
+
+[ANDPD]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+xmmreg,xmmrm \361\2\x0F\x54\110 WILLAMETTE,SSE2,SM
+
+[CMPEQPD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \361\2\x0F\xC2\110\1\x00 WILLAMETTE,SSE2,SM
+
+; note: no SM flag on CMPxxSD, they use 64-bit memory location, not 128-bit
+[CMPEQSD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \334\2\x0F\xC2\110\1\x00 WILLAMETTE,SSE2
+
+[CMPLEPD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \361\2\x0F\xC2\110\1\x02 WILLAMETTE,SSE2,SM
+
+[CMPLESD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \334\2\x0F\xC2\110\1\x02 WILLAMETTE,SSE2
+
+[CMPLTPD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \361\2\x0F\xC2\110\1\x01 WILLAMETTE,SSE2,SM
+
+[CMPLTSD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \334\2\x0F\xC2\110\1\x01 WILLAMETTE,SSE2
+
+[CMPNEQPD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \361\2\x0F\xC2\110\1\x04 WILLAMETTE,SSE2,SM
+
+[CMPNEQSD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \334\2\x0F\xC2\110\1\x04 WILLAMETTE,SSE2
+
+[CMPNLEPD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \361\2\x0F\xC2\110\1\x06 WILLAMETTE,SSE2,SM
+
+[CMPNLESD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \334\2\x0F\xC2\110\1\x06 WILLAMETTE,SSE2
+
+[CMPNLTPD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \361\2\x0F\xC2\110\1\x05 WILLAMETTE,SSE2,SM
+
+[CMPNLTSD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \334\2\x0F\xC2\110\1\x05 WILLAMETTE,SSE2
+
+[CMPORDPD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \361\2\x0F\xC2\110\1\x07 WILLAMETTE,SSE2,SM
+
+[CMPORDSD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \334\2\x0F\xC2\110\1\x07 WILLAMETTE,SSE2
+
+[CMPUNORDPD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \361\2\x0F\xC2\110\1\x03 WILLAMETTE,SSE2,SM
+
+[CMPUNORDSD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \334\2\x0F\xC2\110\1\x03 WILLAMETTE,SSE2
+
+; CMPPD/CMPSD must come after the specific ops; that way the disassembler will find the
+; specific ops first and only disassemble illegal ones as cmppd/cmpsd.
+[CMPPD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm,imm \361\2\x0F\xC2\110\26 WILLAMETTE,SSE2,SM2,SB,AR2
+
+[COMISD]
+(Ch_Rop1, Ch_Rop2, Ch_WFlags)
+xmmreg,xmmrm \361\2\x0F\x2F\110 WILLAMETTE,SSE2
+
+[CVTDQ2PD]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+xmmreg,xmmrm \333\2\x0F\xE6\110 WILLAMETTE,SSE2
+
+[CVTDQ2PS]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+xmmreg,xmmrm \2\x0F\x5B\110 WILLAMETTE,SSE2,SM
+
+[CVTPD2DQ]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+xmmreg,xmmrm \334\2\x0F\xE6\110 WILLAMETTE,SSE2,SM
+
+[CVTPD2PI]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+mmxreg,xmmrm \361\2\x0F\x2D\110 WILLAMETTE,SSE2 ;,SO
+
+[CVTPD2PS]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+xmmreg,xmmrm \361\2\x0F\x5A\110 WILLAMETTE,SSE2,SM
+
+[CVTPI2PD]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+xmmreg,mmxrm \361\2\x0F\x2A\110 WILLAMETTE,SSE2 ;,SO
+
+[CVTPS2DQ]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+xmmreg,xmmrm \361\2\x0F\x5B\110 WILLAMETTE,SSE2,SM
+
+[CVTPS2PD]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+xmmreg,xmmrm \2\x0F\x5A\110 WILLAMETTE,SSE2 ;,SQ
+
+[CVTSD2SI,cvtsd2siX]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+reg32|64,xmmreg \334\320\2\x0F\x2D\110 WILLAMETTE,SSE2
+reg32|64,mem \334\320\2\x0F\x2D\110 WILLAMETTE,SSE2
+
+[CVTSD2SS]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+xmmreg,xmmrm \334\2\x0F\x5A\110 WILLAMETTE,SSE2 ;,SQ
+
+[CVTSI2SD,cvtsi2sdX]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+xmmreg,reg32|64 \334\321\2\x0F\x2A\110 WILLAMETTE,SSE2
+xmmreg,mem \334\321\2\x0F\x2A\110 WILLAMETTE,SSE2
+
+[CVTSS2SD]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+xmmreg,xmmrm \333\2\x0F\x5A\110 WILLAMETTE,SSE2 ;,SD
+
+[CVTTPD2PI]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+mmxreg,xmmreg \361\2\x0F\x2C\110 WILLAMETTE,SSE2
+mmxreg,mem \361\2\x0F\x2C\110 WILLAMETTE,SSE2
+
+[CVTTPD2DQ]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+xmmreg,xmmrm \361\2\x0F\xE6\110 WILLAMETTE,SSE2,SM
+
+[CVTTPS2DQ]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+xmmreg,xmmrm \333\2\x0F\x5B\110 WILLAMETTE,SSE2,SM
+
+[CVTTSD2SI,cvttsd2siX]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+reg32|64,xmmreg \334\320\2\x0F\x2C\110 WILLAMETTE,SSE2
+reg32|64,mem \334\320\2\x0F\x2C\110 WILLAMETTE,SSE2
+
+[DIVPD]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+xmmreg,xmmrm \361\2\x0F\x5E\110 WILLAMETTE,SSE2,SM
+
+[DIVSD]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+xmmreg,xmmrm \334\2\x0F\x5E\110 WILLAMETTE,SSE2
+
+[MAXPD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \361\2\x0F\x5F\110 WILLAMETTE,SSE2,SM
+
+[MAXSD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \334\2\x0F\x5F\110 WILLAMETTE,SSE2
+
+[MINPD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \361\2\x0F\x5D\110 WILLAMETTE,SSE2,SM
+
+[MINSD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \334\2\x0F\x5D\110 WILLAMETTE,SSE2
+
+[MOVAPD]
+(Ch_ROp1, Ch_WOp2, Ch_None)
+xmmrm,xmmreg \361\2\x0F\x29\101 WILLAMETTE,SSE2,SM
+xmmreg,xmmrm \361\2\x0F\x28\110 WILLAMETTE,SSE2,SM
+
+[MOVHPD]
+(Ch_All, Ch_None, Ch_None)
+mem,xmmreg \361\2\x0F\x17\101 WILLAMETTE,SSE2
+xmmreg,mem \361\2\x0F\x16\110 WILLAMETTE,SSE2
+
+[MOVLPD]
+(Ch_All, Ch_None, Ch_None)
+mem,xmmreg \361\2\x0F\x13\101 WILLAMETTE,SSE2
+xmmreg,mem \361\2\x0F\x12\110 WILLAMETTE,SSE2
+
+[MOVMSKPD]
+(Ch_All, Ch_None, Ch_None)
+reg32,xmmreg \361\2\x0F\x50\110 WILLAMETTE,SSE2
+
+[MOVUPD]
+(Ch_All, Ch_None, Ch_None)
+xmmrm,xmmreg \361\2\x0F\x11\101 WILLAMETTE,SSE2,SM
+xmmreg,xmmrm \361\2\x0F\x10\110 WILLAMETTE,SSE2,SM
+
+[MULPD]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+xmmreg,xmmrm \361\2\x0F\x59\110 WILLAMETTE,SSE2,SM
+
+[MULSD]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+xmmreg,xmmrm \334\2\x0F\x59\110 WILLAMETTE,SSE2
+
+[ORPD]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+xmmreg,xmmrm \361\2\x0F\x56\110 WILLAMETTE,SSE2,SM
+
+[SHUFPD]
+(Ch_Mop3, Ch_Rop2, Ch_None)
+xmmreg,xmmrm,imm \361\2\x0F\xC6\110\26 WILLAMETTE,SSE2,SM2,SB,AR2
+
+[SQRTPD]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+xmmreg,xmmrm \361\2\x0F\x51\110 WILLAMETTE,SSE2,SM
+
+[SQRTSD]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+xmmreg,xmmrm \334\2\x0F\x51\110 WILLAMETTE,SSE2
+
+
+[SUBPD]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+xmmreg,xmmrm \361\2\x0F\x5C\110 WILLAMETTE,SSE2,SM
+
+[SUBSD]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+xmmreg,xmmrm \334\2\x0F\x5C\110 WILLAMETTE,SSE2
+
+[UCOMISD]
+(Ch_Rop1, Ch_Rop2, Ch_WFlags)
+xmmreg,xmmrm \361\2\x0F\x2E\110 WILLAMETTE,SSE2
+
+[UNPCKHPD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \361\2\x0F\x15\110 WILLAMETTE,SSE2,SM
+
+[UNPCKLPD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \361\2\x0F\x14\110 WILLAMETTE,SSE2,SM
+
+[XORPD]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+xmmreg,xmmrm \361\2\x0F\x57\110 WILLAMETTE,SSE2,SM
+
+;
+; Prescott New Instructions (SSE3)
+;
+[ADDSUBPD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \361\2\x0F\xD0\110 PRESCOTT,SSE3,SM
+
+[ADDSUBPS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \334\2\x0F\xD0\110 PRESCOTT,SSE3,SM
+
+[HADDPD]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+xmmreg,xmmrm \361\2\x0F\x7C\110 PRESCOTT,SSE3,SM
+
+[HADDPS]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+xmmreg,xmmrm \334\2\x0F\x7C\110 PRESCOTT,SSE3,SM
+
+[HSUBPD]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+xmmreg,xmmrm \361\2\x0F\x7D\110 PRESCOTT,SSE3,SM
+
+[HSUBPS]
+(Ch_Mop2, Ch_Rop1, Ch_None)
+xmmreg,xmmrm \334\2\x0F\x7D\110 PRESCOTT,SSE3,SM
+
+[LDDQU]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,mem \334\2\x0F\xF0\110 PRESCOTT,SSE3
+
+[MOVDDUP]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \334\2\x0F\x12\110 PRESCOTT,SSE3
+
+[MOVSHDUP]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \333\2\x0F\x16\110 PRESCOTT,SSE3,SM
+
+[MOVSLDUP]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \333\2\x0F\x12\110 PRESCOTT,SSE3,SM
+
+;
+; Intel VT
+;
+[VMREAD]
+(Ch_All, Ch_None, Ch_None)
+reg32,reg32 \2\x0F\x78\101 386,PRIV,PROT
+mem,reg32 \2\x0F\x78\101 386,PRIV,PROT,SM
+
+[VMWRITE]
+(Ch_All, Ch_None, Ch_None)
+reg32,reg32 \2\x0F\x79\110 386,PRIV,PROT
+reg32,mem \2\x0F\x79\110 386,PRIV,PROT,SM
+
+[VMCALL]
+(Ch_All, Ch_None, Ch_None)
+void \3\x0F\x01\xC1 386,PRIV,PROT
+
+[VMLAUNCH]
+(Ch_All, Ch_None, Ch_None)
+void \3\x0F\x01\xC2 386,PRIV,PROT
+
+[VMRESUME]
+(Ch_All, Ch_None, Ch_None)
+void \3\x0F\x01\xC3 386,PRIV,PROT
+
+[VMXOFF]
+(Ch_All, Ch_None, Ch_None)
+void \3\x0F\x01\xC4 386,PRIV,PROT
+
+; note: ideally the following should be tagged with SQ
+
+[VMXON]
+(Ch_All, Ch_None, Ch_None)
+mem \333\2\x0F\xC7\206 PRIV,PROT
+
+[VMCLEAR]
+(Ch_All, Ch_None, Ch_None)
+mem \361\2\x0F\xC7\206 PRIV,PROT
+
+[VMPTRLD]
+(Ch_All, Ch_None, Ch_None)
+mem \2\x0F\xC7\206 PRIV,PROT
+
+[VMPTRST]
+(Ch_All, Ch_None, Ch_None)
+mem \2\x0F\xC7\207 PRIV,PROT
+
+;
+; AMD SVM
+;
+[VMRUN]
+(Ch_All, Ch_None, Ch_None)
+void \3\x0F\x01\xD8 386,SVM,PRIV,PROT
+
+[VMMCALL]
+(Ch_All, Ch_None, Ch_None)
+void \3\x0F\x01\xD9 386,SVM
+
+[VMLOAD]
+(Ch_All, Ch_None, Ch_None)
+void \3\x0F\x01\xDA 386,SVM,PRIV,PROT
+
+[VMSAVE]
+(Ch_All, Ch_None, Ch_None)
+void \3\x0F\x01\xDB 386,SVM,PRIV,PROT
+
+[STGI]
+(Ch_All, Ch_None, Ch_None)
+void \3\x0F\x01\xDC 386,SVM,PRIV,PROT
+
+[CLGI]
+(Ch_All, Ch_None, Ch_None)
+void \3\x0F\x01\xDD 386,SVM,PRIV,PROT
+
+[SKINIT]
+(Ch_All, Ch_None, Ch_None)
+void \3\x0F\x01\xDE 386,SVM,PRIV,PROT
+
+[INVLPGA]
+(Ch_All, Ch_None, Ch_None)
+void \3\x0F\x01\xDF 386,SVM,PRIV,PROT
+
+;
+; Centaur
+;
+[MONTMUL]
+(Ch_All, Ch_None, Ch_None)
+void \333\3\x0F\xA6\xC0 CENTAUR
+
+[XSHA1]
+(Ch_All, Ch_None, Ch_None)
+void \333\3\x0F\xA6\xC8 CENTAUR
+
+[XSHA256]
+(Ch_All, Ch_None, Ch_None)
+void \333\3\x0F\xA6\xD0 CENTAUR
+
+;
+; Geode
+;
+[DMINT]
+(Ch_All, Ch_None, Ch_None)
+void \2\x0F\x39 P6,CYRIX
+
+[RDM]
+(Ch_All, Ch_None, Ch_None)
+void \2\x0F\x3A P6,CYRIX
+
+;
+; GAS specific x86-64 instructions
+;
+[MOVABS]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+reg_al,mem_offs \1\xA0\45 X86_64,SM
+reg_ax|32|64,mem_offs \320\1\xA1\45 X86_64,SM
+mem_offs,reg_al \1\xA2\44 X86_64,SM
+mem_offs,reg_ax|32|64 \321\xA3\44 X86_64,SM
+reg64,imm \326\10\xB8\55 X86_64
+
+[MOVSXD,movslq]
+(Ch_Wop2, Ch_Rop1, Ch_None)
+reg64,mem \326\1\x63\110 X86_64
+reg64,reg32 \326\1\x63\110 X86_64
+
+[CQO,cqto]
+(Ch_MRAX, Ch_WRDX, Ch_None)
+void \326\1\x99 X86_64
+
+[CMPXCHG16B,cmpxchg16bX]
+(Ch_All, Ch_None, Ch_None)
+mem \326\2\x0F\xC7\201 X86_64
+
+;
+; SSE4a (AMD Barcelona CPUs, n/a on Intel)
+;
+[MOVNTSS]
+(Ch_All, Ch_None, Ch_None)
+mem,xmmreg \333\2\x0F\x2B\101 SSE4,SD
+
+[MOVNTSD]
+(Ch_All, Ch_None, Ch_None)
+mem,xmmreg \334\325\2\x0F\x2B\101 SSE4 ;,SQ
+
+[INSERTQ]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmreg \334\2\x0F\x79\110 SSE4
+xmmreg,xmmreg,imm,imm \334\2\x0F\x78\110\26\27 SSE4,SB
+
+[EXTRQ]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,imm,imm \361\2\x0F\x78\200\25\26 SSE4,SB
+xmmreg,xmmreg \361\2\x0F\x79\110 SSE4
+
+[LZCNT,lzcntX]
+(Ch_All, Ch_None, Ch_None)
+reg16,regmem \320\333\2\x0F\xBD\110 386,SM,SSE4
+reg32|64,regmem \321\333\2\x0F\xBD\110 386,SM,SSE4
+
+;*******************************************************************************
+;**********SSSE3****************************************************************
+;*******************************************************************************
+[PABSB]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \331\3\x0F\x38\x1C\110 SSSE3,MMX,SM
+xmmreg,xmmrm \361\3\x0F\x38\x1C\110 SSSE3,SM
+
+[PABSW]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \331\3\x0F\x38\x1D\110 SSSE3,MMX,SM
+xmmreg,xmmrm \361\3\x0F\x38\x1D\110 SSSE3,SM
+
+[PABSD]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \331\3\x0F\x38\x1E\110 SSSE3,MMX,SM
+xmmreg,xmmrm \361\3\x0F\x38\x1E\110 SSSE3,SM
+
+[PALIGNR]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm,imm \331\3\x0F\x3A\x0F\110\26 SSSE3,MMX,SM2,SB,AR2
+xmmreg,xmmrm,imm \361\3\x0F\x3A\x0F\110\26 SSSE3,SM2,SB,AR2
+
+[PHADDW]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \331\3\x0F\x38\x01\110 SSSE3,MMX,SM
+xmmreg,xmmrm \361\3\x0F\x38\x01\110 SSSE3,SM
+
+[PHADDD]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \331\3\x0F\x38\x02\110 SSSE3,MMX,SM
+xmmreg,xmmrm \361\3\x0F\x38\x02\110 SSSE3,SM
+
+[PHADDSW]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \331\3\x0F\x38\x03\110 SSSE3,MMX,SM
+xmmreg,xmmrm \361\3\x0F\x38\x03\110 SSSE3,SM
+
+[PHSUBW]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \331\3\x0F\x38\x05\110 SSSE3,MMX,SM
+xmmreg,xmmrm \361\3\x0F\x38\x05\110 SSSE3,SM
+
+[PHSUBD]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \331\3\x0F\x38\x06\110 SSSE3,MMX,SM
+xmmreg,xmmrm \361\3\x0F\x38\x06\110 SSSE3,SM
+
+[PHSUBSW]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \331\3\x0F\x38\x07\110 SSSE3,MMX,SM
+xmmreg,xmmrm \361\3\x0F\x38\x07\110 SSSE3,SM
+
+[PMADDUBSW]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \331\3\x0F\x38\x04\110 SSSE3,MMX,SM
+xmmreg,xmmrm \361\3\x0F\x38\x04\110 SSSE3,SM
+
+[PMULHRSW]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \331\3\x0F\x38\x0B\110 SSSE3,MMX,SM
+xmmreg,xmmrm \361\3\x0F\x38\x0B\110 SSSE3,SM
+
+[PSHUFB]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \331\3\x0F\x38\x00\110 SSSE3,MMX,SM
+xmmreg,xmmrm \361\3\x0F\x38\x00\110 SSSE3,SM
+
+[PSIGNB]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \331\3\x0F\x38\x08\110 SSSE3,MMX,SM
+xmmreg,xmmrm \361\3\x0F\x38\x08\110 SSSE3,SM
+
+[PSIGNW]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \331\3\x0F\x38\x09\110 SSSE3,MMX,SM
+xmmreg,xmmrm \361\3\x0F\x38\x09\110 SSSE3,SM
+
+[PSIGND]
+(Ch_All, Ch_None, Ch_None)
+mmxreg,mmxrm \331\3\x0F\x38\x0A\110 SSSE3,MMX,SM
+xmmreg,xmmrm \361\3\x0F\x38\x0A\110 SSSE3,SM
+
+;*******************************************************************************
+;**********SSE4.1***************************************************************
+;*******************************************************************************
+[BLENDPS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm,imm \361\3\x0F\x3A\x0C\110\26 SSE41,SM2,SB,AR2
+
+[BLENDPD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm,imm \361\3\x0F\x3A\x0D\110\26 SSE41,SM2,SB,AR2
+
+[BLENDVPS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \361\3\x0F\x38\x14\110 SSE41,SM
+
+[BLENDVPD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \361\3\x0F\x38\x15\110 SSE41,SM
+
+[DPPS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm,imm \361\3\x0F\x3A\x40\110\26 SSE41,SM2,SB,AR2
+
+[DPPD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm,imm \361\3\x0F\x3A\x41\110\26 SSE41,SM2,SB,AR2
+
+[EXTRACTPS]
+(Ch_All, Ch_None, Ch_None)
+mem,xmmreg,imm \361\325\3\x0F\x3A\x17\101\26 SSE41,SB,AR2
+reg32|64,xmmreg,imm \361\3\x0F\x3A\x17\101\26 SSE41,SB,AR2
+
+[INSERTPS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm,imm \361\3\x0F\x3A\x21\110\26 SSE41,SM2,SB,AR2
+
+[MOVNTDQA]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,mem \361\3\x0F\x38\x2A\110 SSE41,SM
+
+[MPSADBW]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm,imm \361\3\x0F\x3A\x42\110\26 SSE41,SM2,SB,AR2
+
+[PACKUSDW]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \361\3\x0F\x38\x2B\110 SSE41,SM
+
+[PBLENDVB]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \361\3\x0F\x38\x10\110 SSE41,SM
+
+[PBLENDW]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm,imm \361\3\x0F\x3A\x0E\110\26 SSE41,SM2,SB,AR2
+
+[PCMPEQQ]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \361\3\x0F\x38\x29\110 SSE41,SM
+
+[PEXTRB]
+(Ch_All, Ch_None, Ch_None)
+reg32|64,xmmreg,imm \361\3\x0F\x3A\x14\101\26 SSE41,SB,AR2
+mem8,xmmreg,imm \361\3\x0F\x3A\x14\101\26 SSE41,SB,AR2
+
+;PEXTRW - Look is prev. implementation
+
+[PEXTRD]
+(Ch_All, Ch_None, Ch_None)
+reg32,xmmreg,imm \361\3\x0F\x3A\x16\101\26 SSE41,SB,AR2
+mem32,xmmreg,imm \361\3\x0F\x3A\x16\101\26 SSE41,SB,AR2
+
+[PEXTRQ]
+(Ch_All, Ch_None, Ch_None)
+reg64,xmmreg,imm \361\326\3\x0F\x3A\x16\101\26 SSE41,X86_64,SB,AR2
+mem64,xmmreg,imm \361\326\3\x0F\x3A\x16\101\26 SSE41,X86_64,SB,AR2
+
+[PHMINPOSUW]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \361\3\x0F\x38\x41\110 SSE41,SM
+
+[PINSRB]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,reg32|64,imm \361\3\x0F\x3A\x20\110\26 SSE41,SB,AR2
+xmmreg,mem8,imm \361\3\x0F\x3A\x20\110\26 SSE41,SB,AR2
+
+[PINSRD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,reg32,imm \361\3\x0F\x3A\x22\110\26 SSE41,SB,AR2
+xmmreg,mem32,imm \361\3\x0F\x3A\x22\110\26 SSE41,SB,AR2
+
+[PINSRQ]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,reg64,imm \361\326\3\x0F\x3A\x22\110\26 SSE41,X86_64,SB,AR2
+xmmreg,mem64,imm \361\326\3\x0F\x3A\x22\110\26 SSE41,X86_64,SB,AR2
+
+[PMAXSB]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \361\3\x0F\x38\x3C\110 SSE41,SM
+
+[PMAXSD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \361\3\x0F\x38\x3D\110 SSE41,SM
+
+[PMAXUD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \361\3\x0F\x38\x3F\110 SSE41,SM
+
+[PMAXUW]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \361\3\x0F\x38\x3E\110 SSE41,SM
+
+[PMINSB]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \361\3\x0F\x38\x38\110 SSE41,SM
+
+[PMINSD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \361\3\x0F\x38\x39\110 SSE41,SM
+
+[PMINUW]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \361\3\x0F\x38\x3A\110 SSE41,SM
+
+[PMINUD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \361\3\x0F\x38\x3B\110 SSE41,SM
+
+[PMOVSXBW]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \361\3\x0F\x38\x20\110 SSE41,SM
+
+[PMOVSXBD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \361\3\x0F\x38\x21\110 SSE41,SM
+
+[PMOVSXBQ]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \361\3\x0F\x38\x22\110 SSE41,SM
+
+[PMOVSXWD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \361\3\x0F\x38\x23\110 SSE41,SM
+
+[PMOVSXWQ]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \361\3\x0F\x38\x24\110 SSE41,SM
+
+[PMOVSXDQ]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \361\3\x0F\x38\x25\110 SSE41,SM
+
+[PMOVZXBW]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \361\3\x0F\x38\x30\110 SSE41,SM
+
+[PMOVZXBD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \361\3\x0F\x38\x31\110 SSE41,SM
+
+[PMOVZXBQ]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \361\3\x0F\x38\x32\110 SSE41,SM
+
+[PMOVZXWD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \361\3\x0F\x38\x33\110 SSE41,SM
+
+[PMOVZXWQ]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \361\3\x0F\x38\x34\110 SSE41,SM
+
+[PMOVZXDQ]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \361\3\x0F\x38\x35\110 SSE41,SM
+
+[PMULDQ]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \361\3\x0F\x38\x28\110 SSE41,SM
+
+[PMULLD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \361\3\x0F\x38\x40\110 SSE41,SM
+
+[PTEST]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \361\3\x0F\x38\x17\110 SSE41,SM
+
+[ROUNDPS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm,imm \361\3\x0F\x3A\x08\110\26 SSE41,SM2,SB,AR2
+
+[ROUNDPD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm,imm \361\3\x0F\x3A\x09\110\26 SSE41,SM2,SB,AR2
+
+[ROUNDSS]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm,imm \361\3\x0F\x3A\x0A\110\26 SSE41,SM2,SB,AR2
+
+[ROUNDSD]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm,imm \361\3\x0F\x3A\x0B\110\26 SSE41,SM2,SB,AR2
+
+;*******************************************************************************
+;**********SSE4.2***************************************************************
+;*******************************************************************************
+
+[CRC32,crc32X]
+(Ch_Mop1, Ch_Rop2, Ch_None)
+reg32,rm8 \334\3\x0F\x38\xF0\110 SSE42
+reg32,rm16|32 \321\334\3\x0F\x38\xF1\110 SSE42
+reg64,rm8 \334\326\3\x0F\x38\xF0\110 SSE42,X86_64
+reg64,rm64 \334\326\3\x0F\x38\xF1\110 SSE42,X86_64
+
+[PCMPESTRI]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm,imm \361\3\x0F\x3A\x61\110\26 SSE42,SM2,SB,AR2
+
+[PCMPESTRM]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm,imm \361\3\x0F\x3A\x60\110\26 SSE42,SM2,SB,AR2
+
+[PCMPISTRI]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm,imm \361\3\x0F\x3A\x63\110\26 SSE42,SM2,SB,AR2
+
+[PCMPISTRM]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm,imm \361\3\x0F\x3A\x62\110\26 SSE42,SM2,SB,AR2
+
+[PCMPGTQ]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \361\3\x0F\x38\x37\110 SSE42,SM
+
+[POPCNT,popcntX]
+(Ch_All, Ch_None, Ch_None)
+reg16,rm16 \333\320\2\x0F\xB8\110 386,SM,SSE4
+reg32,rm32 \333\320\2\x0F\xB8\110 386,SM,SSE4
+reg64,rm64 \333\320\2\x0F\xB8\110 386,SM,SSE4,X86_64
+
+;*******************************************************************************
+;**********AES******************************************************************
+;*******************************************************************************
+;Use SSE4, but need special flag for AES insructions set
+
+[AESENC]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \361\3\x0F\x38\xDC\110 SSE4,SM
+
+[AESENCLAST]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \361\3\x0F\x38\xDD\110 SSE4,SM
+
+[AESDEC]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \361\3\x0F\x38\xDE\110 SSE4,SM
+
+[AESDECLAST]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \361\3\x0F\x38\xDF\110 SSE4,SM
+
+[AESIMC]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm \361\3\x0F\x38\xDB\110 SSE4,SM
+
+[AESKEYGENASSIST]
+(Ch_All, Ch_None, Ch_None)
+xmmreg,xmmrm,imm \361\3\x0F\x3A\xDF\110\26 SSE4,SB,AR2
+
+;*******************************************************************************
+;*******************************************************************************
+;*******************************************************************************
+[STOSQ]
+(Ch_RRAX, Ch_WMemEDI, Ch_RWRDI)
+void \326\1\xAB X86_64
+
+[LODSQ]
+(Ch_WRAX, Ch_RWRSI, Ch_None)
+void \326\1\xAD X86_64
+
+[CMPSQ]
+(Ch_All, Ch_None, Ch_None)
+void \326\1\xA7 X86_64
diff --git a/closures/compiler/x86/x86reg.dat b/closures/compiler/x86/x86reg.dat
new file mode 100644
index 0000000000..1ebea360b3
--- /dev/null
+++ b/closures/compiler/x86/x86reg.dat
@@ -0,0 +1,140 @@
+;
+; x86 registers
+;
+; layout
+; <name>,<value>,<stdname>,<attname>,<masmname>,<nasmname>,<stabidx>,<dwarf32idx>,<dwarf64idx>,<ot value>,<opcode value>,[AMD64 specific]
+;
+; For stab/dwarf numbers see gdb/i386-tdep.c and gdb/amd64-tdep.c
+;
+NR_NO,$00000000,INVALID,INVALID,INVALID,INVALID,-1,-1,-1,OT_NONE,0
+NR_AL,$01010000,al,%al,al,al,0,0,0,OT_REG_AL,0
+NR_AH,$01020000,ah,%ah,ah,ah,0,0,0,OT_REG8,4
+NR_AX,$01030000,ax,%ax,ax,ax,0,0,0,OT_REG_AX,0
+NR_EAX,$01040000,eax,%eax,eax,eax,0,0,0,OT_REG_EAX,0
+NR_RAX,$01050000,rax,%rax,rax,rax,0,0,0,OT_REG_RAX,0,64
+NR_CL,$01010001,cl,%cl,cl,cl,1,1,2,OT_REG_CL,1
+NR_CH,$01020001,ch,%ch,ch,ch,1,1,2,OT_REG8,5
+NR_CX,$01030001,cx,%cx,cx,cx,1,1,2,OT_REG_CX,1
+NR_ECX,$01040001,ecx,%ecx,ecx,ecx,1,1,2,OT_REG_ECX,1
+NR_RCX,$01050001,rcx,%rcx,rcx,rcx,1,1,2,OT_REG_RCX,1,64
+NR_DL,$01010002,dl,%dl,dl,dl,2,2,1,OT_REG8,2
+NR_DH,$01020002,dh,%dh,dh,dh,2,2,1,OT_REG8,6
+NR_DX,$01030002,dx,%dx,dx,dx,2,2,1,OT_REG_DX,2
+NR_EDX,$01040002,edx,%edx,edx,edx,2,2,1,OT_REG32,2
+NR_RDX,$01050002,rdx,%rdx,rdx,rdx,2,2,1,OT_REG64,2,64
+NR_BL,$01010003,bl,%bl,bl,bl,3,3,3,OT_REG8,3
+NR_BH,$01020003,bh,%bh,bh,bh,3,3,3,OT_REG8,7
+NR_BX,$01030003,bx,%bx,bx,bx,3,3,3,OT_REG16,3
+NR_EBX,$01040003,ebx,%ebx,ebx,ebx,3,3,3,OT_REG32,3
+NR_RBX,$01050003,rbx,%rbx,rbx,rbx,3,3,3,OT_REG64,3,64
+NR_SIL,$01010004,sil,%sil,sil,sil,6,6,4,OT_REG8,6,64
+NR_SI,$01030004,si,%si,si,si,6,6,4,OT_REG16,6
+NR_ESI,$01040004,esi,%esi,esi,esi,6,6,4,OT_REG32,6
+NR_RSI,$01050004,rsi,%rsi,rsi,rsi,6,6,4,OT_REG64,6,64
+NR_DIL,$01010005,dil,%dil,dil,dil,7,7,5,OT_REG8,7,64
+NR_DI,$01030005,di,%di,di,di,7,7,5,OT_REG16,7
+NR_EDI,$01040005,edi,%edi,edi,edi,7,7,5,OT_REG32,7
+NR_RDI,$01050005,rdi,%rdi,rdi,rdi,7,7,5,OT_REG64,7,64
+NR_BPL,$01010006,bpl,%bpl,bpl,bpl,5,5,6,OT_REG8,5,64
+NR_BP,$01030006,bp,%bp,bp,bp,5,5,6,OT_REG16,5
+NR_EBP,$01040006,ebp,%ebp,ebp,ebp,5,5,6,OT_REG32,5
+NR_RBP,$01050006,rbp,%rbp,rbp,rbp,5,5,6,OT_REG64,5,64
+NR_SPL,$01010007,spl,%spl,spl,spl,4,4,7,OT_REG8,4,64
+NR_SP,$01030007,sp,%sp,sp,sp,4,4,7,OT_REG16,4
+NR_ESP,$01040007,esp,%esp,esp,esp,4,4,7,OT_REG32,4
+NR_RSP,$01050007,rsp,%rsp,rsp,rsp,4,4,7,OT_REG64,4,64
+NR_R8,$01050008,r8,%r8,r8,r8,-1,-1,8,OT_REG64,0,64
+NR_R8L,$01010008,r8b,%r8b,r8b,r8b,-1,-1,8,OT_REG8,0,64
+NR_R8W,$01030008,r8w,%r8w,r8w,r8w,-1,-1,8,OT_REG16,0,64
+NR_R8D,$01040008,r8d,%r8d,r8d,r8d,-1,-1,8,OT_REG32,0,64
+NR_R9,$01050009,r9,%r9,r9,r9,-1,-1,9,OT_REG64,1,64
+NR_R9L,$01010009,r9b,%r9b,r9b,r9b,-1,-1,9,OT_REG8,1,64
+NR_R9W,$01030009,r9w,%r9w,r9w,r9w,-1,-1,9,OT_REG16,1,64
+NR_R9D,$01040009,r9d,%r9d,r9d,r9d,-1,-1,9,OT_REG32,1,64
+NR_R10,$0105000a,r10,%r10,r10,r10,-1,-1,10,OT_REG64,2,64
+NR_R10L,$0101000a,r10b,%r10b,r10b,r10b,-1,-1,10,OT_REG8,2,64
+NR_R10W,$0103000a,r10w,%r10w,r10w,r10w,-1,-1,10,OT_REG16,2,64
+NR_R10D,$0104000a,r10d,%r10d,r10d,r10d,-1,-1,10,OT_REG32,2,64
+NR_R11,$0105000b,r11,%r11,r11,r11,-1,-1,11,OT_REG64,3,64
+NR_R11L,$0101000b,r11b,%r11b,r11b,r11b,-1,-1,11,OT_REG8,3,64
+NR_R11W,$0103000b,r11w,%r11w,r11w,r11w,-1,-1,11,OT_REG16,3,64
+NR_R11D,$0104000b,r11d,%r11d,r11d,r11d,-1,-1,11,OT_REG32,3,64
+NR_R12,$0105000c,r12,%r12,r12,r12,-1,-1,12,OT_REG64,4,64
+NR_R12L,$0101000c,r12b,%r12b,r12b,r12b,-1,-1,12,OT_REG8,4,64
+NR_R12W,$0103000c,r12w,%r12w,r12w,r12w,-1,-1,12,OT_REG16,4,64
+NR_R12D,$0104000c,r12d,%r12d,r12d,r12d,-1,-1,12,OT_REG32,4,64
+NR_R13,$0105000d,r13,%r13,r13,r13,-1,-1,13,OT_REG64,5,64
+NR_R13L,$0101000d,r13b,%r13b,r13b,r13b,-1,-1,13,OT_REG8,5,64
+NR_R13W,$0103000d,r13w,%r13w,r13w,r13w,-1,-1,13,OT_REG16,5,64
+NR_R13D,$0104000d,r13d,%r13d,r13d,r13d,-1,-1,13,OT_REG32,5,64
+NR_R14,$0105000e,r14,%r14,r14,r14,-1,-1,14,OT_REG64,6,64
+NR_R14L,$0101000e,r14b,%r14b,r14b,r14b,-1,-1,14,OT_REG8,6,64
+NR_R14W,$0103000e,r14w,%r14w,r14w,r14w,-1,-1,14,OT_REG16,6,64
+NR_R14D,$0104000e,r14d,%r14d,r14d,r14d,-1,-1,14,OT_REG32,6,64
+NR_R15,$0105000f,r15,%r15,r15,r15,-1,-1,15,OT_REG64,7,64
+NR_R15L,$0101000f,r15b,%r15b,r15b,r15b,-1,-1,15,OT_REG8,7,64
+NR_R15W,$0103000f,r15w,%r15w,r15w,r15w,-1,-1,15,OT_REG16,7,64
+NR_R15D,$0104000f,r15d,%r15d,r15d,r15d,-1,-1,15,OT_REG32,7,64
+
+; EIP is needed for DWARF call frame info return address (RA)
+NR_RIP,$05000000,rip,%rip,rip,rip,-1,8,16,OT_NONE,0,64
+NR_EIP,$05000000,eip,%eip,eip,eip,-1,8,16,OT_NONE,0
+NR_CS,$05000001,cs,%cs,cs,cs,-1,-1,-1,OT_REG_CS,1
+NR_DS,$05000002,ds,%ds,ds,ds,-1,-1,-1,OT_REG_DESS,3
+NR_ES,$05000003,es,%es,es,es,-1,-1,-1,OT_REG_DESS,0
+NR_SS,$05000004,ss,%ss,ss,ss,-1,-1,-1,OT_REG_DESS,2
+NR_FS,$05000005,fs,%fs,fs,fs,-1,-1,-1,OT_REG_FSGS,4
+NR_GS,$05000006,gs,%gs,gs,gs,-1,-1,-1,OT_REG_FSGS,5
+
+NR_DR0,$05000007,dr0,%dr0,dr0,dr0,-1,-1,-1,OT_REG_DREG,0
+NR_DR1,$05000008,dr1,%dr1,dr1,dr1,-1,-1,-1,OT_REG_DREG,1
+NR_DR2,$05000009,dr2,%dr2,dr2,dr2,-1,-1,-1,OT_REG_DREG,2
+NR_DR3,$0500000a,dr3,%dr3,dr3,dr3,-1,-1,-1,OT_REG_DREG,3
+NR_DR6,$0500000b,dr6,%dr6,dr6,dr6,-1,-1,-1,OT_REG_DREG,6
+NR_DR7,$0500000c,dr7,%dr7,dr7,dr7,-1,-1,-1,OT_REG_DREG,7
+NR_CR0,$0500000d,cr0,%cr0,cr0,cr0,-1,-1,-1,OT_REG_CREG,0
+NR_CR2,$0500000e,cr2,%cr2,cr2,cr2,-1,-1,-1,OT_REG_CREG,2
+NR_CR3,$0500000f,cr3,%cr3,cr3,cr3,-1,-1,-1,OT_REG_CREG,3
+NR_CR4,$05000010,cr4,%cr4,cr4,cr4,-1,-1,-1,OT_REG_CR4,4
+NR_TR3,$05000011,tr3,%tr3,tr3,tr3,-1,-1,-1,OT_REG_TREG,3
+NR_TR4,$05000012,tr4,%tr4,tr4,tr4,-1,-1,-1,OT_REG_TREG,4
+NR_TR5,$05000013,tr5,%tr5,tr5,tr5,-1,-1,-1,OT_REG_TREG,5
+NR_TR6,$05000014,tr6,%tr6,tr6,tr6,-1,-1,-1,OT_REG_TREG,6
+NR_TR7,$05000015,tr7,%tr7,tr7,tr7,-1,-1,-1,OT_REG_TREG,7
+
+NR_ST0,$02000000,st(0),%st(0),st(0),st0,12,11,33,OT_FPU0,0
+NR_ST1,$02000001,st(1),%st(1),st(1),st1,13,12,34,OT_FPUREG,1
+NR_ST2,$02000002,st(2),%st(2),st(2),st2,14,13,35,OT_FPUREG,2
+NR_ST3,$02000003,st(3),%st(3),st(3),st3,15,14,36,OT_FPUREG,3
+NR_ST4,$02000004,st(4),%st(4),st(4),st4,16,15,37,OT_FPUREG,4
+NR_ST5,$02000005,st(5),%st(5),st(5),st5,17,16,38,OT_FPUREG,5
+NR_ST6,$02000006,st(6),%st(6),st(6),st6,18,17,39,OT_FPUREG,6
+NR_ST7,$02000007,st(7),%st(7),st(7),st7,19,18,40,OT_FPUREG,7
+; Special code to that will map to %st(0)
+NR_ST,$02000008,st,%st,st,st0,12,11,33,OT_FPU0,0
+
+NR_MM0,$03000000,mm0,%mm0,mm0,mm0,29,29,41,OT_MMXREG,0
+NR_MM1,$03000001,mm1,%mm1,mm1,mm1,30,30,42,OT_MMXREG,1
+NR_MM2,$03000002,mm2,%mm2,mm2,mm2,31,31,43,OT_MMXREG,2
+NR_MM3,$03000003,mm3,%mm3,mm3,mm3,32,32,44,OT_MMXREG,3
+NR_MM4,$03000004,mm4,%mm4,mm4,mm4,33,33,45,OT_MMXREG,4
+NR_MM5,$03000005,mm5,%mm5,mm5,mm5,34,34,46,OT_MMXREG,5
+NR_MM6,$03000006,mm6,%mm6,mm6,mm6,35,35,47,OT_MMXREG,6
+NR_MM7,$03000007,mm7,%mm7,mm7,mm7,36,36,48,OT_MMXREG,7
+
+NR_XMM0,$04000000,xmm0,%xmm0,xmm0,xmm0,21,21,17,OT_XMMREG,0
+NR_XMM1,$04000001,xmm1,%xmm1,xmm1,xmm1,22,22,18,OT_XMMREG,1
+NR_XMM2,$04000002,xmm2,%xmm2,xmm2,xmm2,23,23,19,OT_XMMREG,2
+NR_XMM3,$04000003,xmm3,%xmm3,xmm3,xmm3,24,24,20,OT_XMMREG,3
+NR_XMM4,$04000004,xmm4,%xmm4,xmm4,xmm4,25,25,21,OT_XMMREG,4
+NR_XMM5,$04000005,xmm5,%xmm5,xmm5,xmm5,26,26,22,OT_XMMREG,5
+NR_XMM6,$04000006,xmm6,%xmm6,xmm6,xmm6,27,27,23,OT_XMMREG,6
+NR_XMM7,$04000007,xmm7,%xmm7,xmm7,xmm7,28,28,24,OT_XMMREG,7
+NR_XMM8,$04000008,xmm8,%xmm8,xmm8,xmm8,-1,-1,25,OT_XMMREG,0,64
+NR_XMM9,$04000009,xmm9,%xmm9,xmm9,xmm9,-1,-1,26,OT_XMMREG,1,64
+NR_XMM10,$0400000a,xmm10,%xmm10,xmm10,xmm10,-1,-1,27,OT_XMMREG,2,64
+NR_XMM11,$0400000b,xmm11,%xmm11,xmm11,xmm11,-1,-1,28,OT_XMMREG,3,64
+NR_XMM12,$0400000c,xmm12,%xmm12,xmm12,xmm12,-1,-1,29,OT_XMMREG,4,64
+NR_XMM13,$0400000d,xmm13,%xmm13,xmm13,xmm13,-1,-1,30,OT_XMMREG,5,64
+NR_XMM14,$0400000e,xmm14,%xmm14,xmm14,xmm14,-1,-1,31,OT_XMMREG,6,64
+NR_XMM15,$0400000f,xmm15,%xmm15,xmm15,xmm15,-1,-1,32,OT_XMMREG,7,64
diff --git a/closures/compiler/x86_64/aoptcpu.pas b/closures/compiler/x86_64/aoptcpu.pas
new file mode 100644
index 0000000000..cb656af36e
--- /dev/null
+++ b/closures/compiler/x86_64/aoptcpu.pas
@@ -0,0 +1,41 @@
+{
+ Copyright (c) 1998-2004 by Jonas Maebe
+
+ This unit calls the optimization procedures to optimize the assembler
+ code for sparc
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+
+unit aoptcpu;
+
+{$i fpcdefs.inc}
+
+ Interface
+
+ uses
+ cpubase, aoptobj, aoptcpub, aopt;
+
+ Type
+ TCpuAsmOptimizer = class(TAsmOptimizer)
+ End;
+
+ Implementation
+
+begin
+ casmoptimizer:=TCpuAsmOptimizer;
+end.
diff --git a/closures/compiler/x86_64/aoptcpub.pas b/closures/compiler/x86_64/aoptcpub.pas
new file mode 100644
index 0000000000..de9031add3
--- /dev/null
+++ b/closures/compiler/x86_64/aoptcpub.pas
@@ -0,0 +1,120 @@
+ {
+ Copyright (c) 1998-2004 by Jonas Maebe, member of the Free Pascal
+ Development Team
+
+ This unit contains several types and constants necessary for the
+ optimizer to work on the sparc architecture
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+Unit aoptcpub; { Assembler OPTimizer CPU specific Base }
+
+{$i fpcdefs.inc}
+
+{ enable the following define if memory references can have both a base and }
+{ index register in 1 operand }
+
+{$define RefsHaveIndexReg}
+
+{ enable the following define if memory references can have a scaled index }
+
+{ define RefsHaveScale}
+
+{ enable the following define if memory references can have a segment }
+{ override }
+
+{ define RefsHaveSegment}
+
+Interface
+
+Uses
+ cpubase,aasmcpu,AOptBase;
+
+Type
+
+{ type of a normal instruction }
+ TInstr = Taicpu;
+ PInstr = ^TInstr;
+
+{ ************************************************************************* }
+{ **************************** TCondRegs ********************************** }
+{ ************************************************************************* }
+{ Info about the conditional registers }
+ TCondRegs = Object
+ Constructor Init;
+ Destructor Done;
+ End;
+
+{ ************************************************************************* }
+{ **************************** TAoptBaseCpu ******************************* }
+{ ************************************************************************* }
+
+ TAoptBaseCpu = class(TAoptBase)
+ End;
+
+
+{ ************************************************************************* }
+{ ******************************* Constants ******************************* }
+{ ************************************************************************* }
+Const
+
+{ the maximum number of things (registers, memory, ...) a single instruction }
+{ changes }
+
+ MaxCh = 3;
+
+{ the maximum number of operands an instruction has }
+
+ MaxOps = 3;
+
+{Oper index of operand that contains the source (reference) with a load }
+{instruction }
+
+ LoadSrc = 0;
+
+{Oper index of operand that contains the destination (register) with a load }
+{instruction }
+
+ LoadDst = 1;
+
+{Oper index of operand that contains the source (register) with a store }
+{instruction }
+
+ StoreSrc = 0;
+
+{Oper index of operand that contains the destination (reference) with a load }
+{instruction }
+
+ StoreDst = 1;
+
+ aopt_uncondjmp = A_JMP;
+ aopt_condjmp = A_Jcc;
+
+Implementation
+
+{ ************************************************************************* }
+{ **************************** TCondRegs ********************************** }
+{ ************************************************************************* }
+Constructor TCondRegs.init;
+Begin
+End;
+
+Destructor TCondRegs.Done; {$ifdef inl} inline; {$endif inl}
+Begin
+End;
+
+End.
diff --git a/closures/compiler/x86_64/aoptcpud.pas b/closures/compiler/x86_64/aoptcpud.pas
new file mode 100644
index 0000000000..cb8c5d319f
--- /dev/null
+++ b/closures/compiler/x86_64/aoptcpud.pas
@@ -0,0 +1,36 @@
+{
+ Copyright (c) 1998-2004 by Jonas Maebe, member of the Free Pascal
+ Development Team
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+Unit aoptcpud;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ aoptda;
+
+ type
+ TAOptDFACpu = class(TAOptDFA)
+ end;
+
+ implementation
+
+end.
diff --git a/closures/compiler/x86_64/cgcpu.pas b/closures/compiler/x86_64/cgcpu.pas
new file mode 100644
index 0000000000..8c20107361
--- /dev/null
+++ b/closures/compiler/x86_64/cgcpu.pas
@@ -0,0 +1,368 @@
+{
+ Copyright (c) 2002 by Florian Klaempfl
+
+ This unit implements the code generator for the x86-64.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit cgcpu;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ cgbase,cgutils,cgobj,cgx86,
+ aasmbase,aasmtai,aasmdata,aasmcpu,
+ cpubase,cpuinfo,cpupara,parabase,
+ symdef,
+ node,symconst,rgx86,procinfo;
+
+ type
+ tcgx86_64 = class(tcgx86)
+ procedure init_register_allocators;override;
+
+ procedure g_proc_entry(list : TAsmList; parasize:longint; nostackframe:boolean);override;
+ procedure g_proc_exit(list : TAsmList;parasize:longint;nostackframe:boolean);override;
+ procedure g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);override;
+ procedure g_local_unwind(list: TAsmList; l: TAsmLabel);override;
+
+ procedure a_loadmm_intreg_reg(list: TAsmList; fromsize, tosize : tcgsize;intreg, mmreg: tregister; shuffle: pmmshuffle); override;
+ procedure a_loadmm_reg_intreg(list: TAsmList; fromsize, tosize : tcgsize;mmreg, intreg: tregister;shuffle : pmmshuffle); override;
+ end;
+
+ procedure create_codegen;
+
+ implementation
+
+ uses
+ globtype,globals,verbose,systems,cutils,cclasses,
+ symsym,defutil,paramgr,fmodule,cpupi,
+ rgobj,tgobj,rgcpu;
+
+
+ procedure Tcgx86_64.init_register_allocators;
+ const
+ win64_saved_std_regs : array[0..6] of tsuperregister = (RS_RBX,RS_RDI,RS_RSI,RS_R12,RS_R13,RS_R14,RS_R15);
+ others_saved_std_regs : array[0..4] of tsuperregister = (RS_RBX,RS_R12,RS_R13,RS_R14,RS_R15);
+ saved_regs_length : array[boolean] of longint = (5,7);
+
+ win64_saved_xmm_regs : array[0..9] of tsuperregister = (RS_XMM6,RS_XMM7,
+ RS_XMM8,RS_XMM9,RS_XMM10,RS_XMM11,RS_XMM12,RS_XMM13,RS_XMM14,RS_XMM15);
+ var
+ i : longint;
+ framepointer : tsuperregister;
+ begin
+ inherited init_register_allocators;
+
+ if (length(saved_standard_registers)<>saved_regs_length[target_info.system=system_x86_64_win64]) then
+ begin
+ if target_info.system=system_x86_64_win64 then
+ begin
+ SetLength(saved_standard_registers,Length(win64_saved_std_regs));
+ SetLength(saved_mm_registers,Length(win64_saved_xmm_regs));
+
+ for i:=low(win64_saved_std_regs) to high(win64_saved_std_regs) do
+ saved_standard_registers[i]:=win64_saved_std_regs[i];
+
+ for i:=low(win64_saved_xmm_regs) to high(win64_saved_xmm_regs) do
+ saved_mm_registers[i]:=win64_saved_xmm_regs[i];
+ end
+ else
+ begin
+ SetLength(saved_standard_registers,Length(others_saved_std_regs));
+ SetLength(saved_mm_registers,0);
+
+ for i:=low(others_saved_std_regs) to high(others_saved_std_regs) do
+ saved_standard_registers[i]:=others_saved_std_regs[i];
+ end;
+ end;
+ if assigned(current_procinfo) then
+ framepointer:=getsupreg(current_procinfo.framepointer)
+ else
+ { in intf. wrapper code generation }
+ framepointer:=RS_FRAME_POINTER_REG;
+ if target_info.system=system_x86_64_win64 then
+ rg[R_INTREGISTER]:=trgcpu.create(R_INTREGISTER,R_SUBWHOLE,[RS_RAX,RS_RDX,RS_RCX,RS_R8,RS_R9,RS_R10,
+ RS_R11,RS_RBX,RS_RSI,RS_RDI,RS_R12,RS_R13,RS_R14,RS_R15],first_int_imreg,[framepointer])
+ else
+ rg[R_INTREGISTER]:=trgcpu.create(R_INTREGISTER,R_SUBWHOLE,[RS_RAX,RS_RDX,RS_RCX,RS_RSI,RS_RDI,RS_R8,
+ RS_R9,RS_R10,RS_R11,RS_RBX,RS_R12,RS_R13,RS_R14,RS_R15],first_int_imreg,[framepointer]);
+
+ rg[R_MMREGISTER]:=trgcpu.create(R_MMREGISTER,R_SUBWHOLE,[RS_XMM0,RS_XMM1,RS_XMM2,RS_XMM3,RS_XMM4,RS_XMM5,RS_XMM6,RS_XMM7,
+ RS_XMM8,RS_XMM9,RS_XMM10,RS_XMM11,RS_XMM12,RS_XMM13,RS_XMM14,RS_XMM15],first_mm_imreg,[]);
+ rgfpu:=Trgx86fpu.create;
+ end;
+
+
+ procedure tcgx86_64.g_proc_entry(list : TAsmList;parasize:longint;nostackframe:boolean);
+ var
+ hitem: tlinkedlistitem;
+ r: integer;
+ href: treference;
+ templist: TAsmList;
+ frame_offset: longint;
+ suppress_endprologue: boolean;
+ begin
+ hitem:=list.last;
+ { pi_has_unwind_info may already be set at this point if there are
+ SEH directives in assembler body. In this case, .seh_endprologue
+ is expected to be one of those directives, and not generated here. }
+ suppress_endprologue:=(pi_has_unwind_info in current_procinfo.flags);
+ inherited g_proc_entry(list,parasize,nostackframe);
+
+ if not (pi_has_unwind_info in current_procinfo.flags) then
+ exit;
+ { Generate unwind data for x86_64-win64 }
+ list.insertafter(cai_seh_directive.create_name(ash_proc,current_procinfo.procdef.mangledname),hitem);
+ templist:=TAsmList.Create;
+
+ { We need to record postive offsets from RSP; if registers are saved
+ at negative offsets from RBP we need to account for it. }
+ if current_procinfo.framepointer=NR_FRAME_POINTER_REG then
+ frame_offset:=current_procinfo.final_localsize
+ else
+ frame_offset:=0;
+
+ { There's no need to describe position of register saves precisely;
+ since registers are not modified before they are saved, and saves do not
+ change RSP, 'logically' all saves can happen at the end of prologue. }
+ href:=current_procinfo.save_regs_ref;
+ for r:=low(saved_standard_registers) to high(saved_standard_registers) do
+ if saved_standard_registers[r] in rg[R_INTREGISTER].used_in_proc then
+ begin
+ templist.concat(cai_seh_directive.create_reg_offset(ash_savereg,
+ newreg(R_INTREGISTER,saved_standard_registers[r],R_SUBWHOLE),
+ href.offset+frame_offset));
+ inc(href.offset,sizeof(aint));
+ end;
+ if uses_registers(R_MMREGISTER) then
+ begin
+ if (href.offset mod tcgsize2size[OS_VECTOR])<>0 then
+ inc(href.offset,tcgsize2size[OS_VECTOR]-(href.offset mod tcgsize2size[OS_VECTOR]));
+
+ for r:=low(saved_mm_registers) to high(saved_mm_registers) do
+ begin
+ if saved_mm_registers[r] in rg[R_MMREGISTER].used_in_proc then
+ begin
+ templist.concat(cai_seh_directive.create_reg_offset(ash_savexmm,
+ newreg(R_MMREGISTER,saved_mm_registers[r],R_SUBNONE),
+ href.offset+frame_offset));
+ inc(href.offset,tcgsize2size[OS_VECTOR]);
+ end;
+ end;
+ end;
+ if not suppress_endprologue then
+ templist.concat(cai_seh_directive.create(ash_endprologue));
+ if assigned(current_procinfo.endprologue_ai) then
+ current_procinfo.aktproccode.insertlistafter(current_procinfo.endprologue_ai,templist)
+ else
+ list.concatlist(templist);
+ templist.free;
+ end;
+
+
+ procedure tcgx86_64.g_proc_exit(list : TAsmList;parasize:longint;nostackframe:boolean);
+ var
+ href : treference;
+ begin
+ { Release PIC register }
+ if cs_create_pic in current_settings.moduleswitches then
+ list.concat(tai_regalloc.dealloc(NR_PIC_OFFSET_REG,nil));
+
+ { Prevent return address from a possible call from ending up in the epilogue }
+ { (restoring registers happens before epilogue, providing necessary padding) }
+ if (current_procinfo.flags*[pi_has_unwind_info,pi_do_call,pi_has_saved_regs])=[pi_has_unwind_info,pi_do_call] then
+ list.concat(Taicpu.op_none(A_NOP));
+ { remove stackframe }
+ if not nostackframe then
+ begin
+ if (current_procinfo.framepointer=NR_STACK_POINTER_REG) or
+ (current_procinfo.procdef.proctypeoption=potype_exceptfilter) then
+ begin
+ if (current_procinfo.final_localsize<>0) then
+ cg.a_op_const_reg(list,OP_ADD,OS_ADDR,current_procinfo.final_localsize,NR_STACK_POINTER_REG);
+ if (current_procinfo.procdef.proctypeoption=potype_exceptfilter) then
+ list.concat(Taicpu.op_reg(A_POP,tcgsize2opsize[OS_ADDR],NR_FRAME_POINTER_REG));
+ end
+ else if (target_info.system=system_x86_64_win64) then
+ begin
+ { Comply with Win64 unwinding mechanism, which only recognizes
+ 'add $constant,%rsp' and 'lea offset(FPREG),%rsp' as belonging to
+ the function epilog.
+ Neither 'leave' nor even 'mov %FPREG,%rsp' are allowed. }
+ reference_reset_base(href,current_procinfo.framepointer,0,sizeof(pint));
+ list.concat(Taicpu.op_ref_reg(A_LEA,tcgsize2opsize[OS_ADDR],href,NR_STACK_POINTER_REG));
+ list.concat(Taicpu.op_reg(A_POP,tcgsize2opsize[OS_ADDR],current_procinfo.framepointer));
+ end
+ else
+ list.concat(Taicpu.op_none(A_LEAVE,S_NO));
+ list.concat(tai_regalloc.dealloc(NR_FRAME_POINTER_REG,nil));
+ end;
+
+ list.concat(Taicpu.Op_none(A_RET,S_NO));
+ if (pi_has_unwind_info in current_procinfo.flags) then
+ begin
+ tx86_64procinfo(current_procinfo).dump_scopes(list);
+ list.concat(cai_seh_directive.create(ash_endproc));
+ end;
+ end;
+
+
+ procedure tcgx86_64.g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);
+ var
+ make_global : boolean;
+ href : treference;
+ sym : tasmsymbol;
+ r : treference;
+ begin
+ if not(procdef.proctypeoption in [potype_function,potype_procedure]) then
+ Internalerror(200006137);
+ if not assigned(procdef.struct) or
+ (procdef.procoptions*[po_classmethod, po_staticmethod,
+ po_methodpointer, po_interrupt, po_iocheck]<>[]) then
+ Internalerror(200006138);
+ if procdef.owner.symtabletype<>ObjectSymtable then
+ Internalerror(200109191);
+
+ make_global:=false;
+ if (not current_module.is_unit) or create_smartlink or
+ (procdef.owner.defowner.owner.symtabletype=globalsymtable) then
+ make_global:=true;
+
+ if make_global then
+ List.concat(Tai_symbol.Createname_global(labelname,AT_FUNCTION,0))
+ else
+ List.concat(Tai_symbol.Createname(labelname,AT_FUNCTION,0));
+
+ { set param1 interface to self }
+ g_adjust_self_value(list,procdef,ioffset);
+
+ if (po_virtualmethod in procdef.procoptions) and
+ not is_objectpascal_helper(procdef.struct) then
+ begin
+ if (procdef.extnumber=$ffff) then
+ Internalerror(200006139);
+ { load vmt from first paramter }
+ { win64 uses a different abi }
+ if target_info.system=system_x86_64_win64 then
+ reference_reset_base(href,NR_RCX,0,sizeof(pint))
+ else
+ reference_reset_base(href,NR_RDI,0,sizeof(pint));
+ cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_RAX);
+ { jmp *vmtoffs(%eax) ; method offs }
+ reference_reset_base(href,NR_RAX,tobjectdef(procdef.struct).vmtmethodoffset(procdef.extnumber),sizeof(pint));
+ list.concat(taicpu.op_ref_reg(A_MOV,S_Q,href,NR_RAX));
+ list.concat(taicpu.op_reg(A_JMP,S_Q,NR_RAX));
+ end
+ else
+ begin
+ sym:=current_asmdata.RefAsmSymbol(procdef.mangledname);
+ reference_reset_symbol(r,sym,0,sizeof(pint));
+ if (cs_create_pic in current_settings.moduleswitches) and
+ { darwin/x86_64's assembler doesn't want @PLT after call symbols }
+ (target_info.system<>system_x86_64_darwin) then
+ r.refaddr:=addr_pic
+ else
+ r.refaddr:=addr_full;
+
+ list.concat(taicpu.op_ref(A_JMP,S_NO,r));
+ end;
+
+ List.concat(Tai_symbol_end.Createname(labelname));
+ end;
+
+ procedure tcgx86_64.g_local_unwind(list: TAsmList; l: TAsmLabel);
+ var
+ para1,para2: tcgpara;
+ href:treference;
+ begin
+ if (target_info.system<>system_x86_64_win64) then
+ begin
+ inherited g_local_unwind(list,l);
+ exit;
+ end;
+ para1.init;
+ para2.init;
+ paramanager.getintparaloc(pocall_default,1,para1);
+ paramanager.getintparaloc(pocall_default,2,para2);
+ reference_reset_symbol(href,l,0,1);
+ { TODO: using RSP is correct only while the stack is fixed!!
+ (true now, but will change if/when allocating from stack is implemented) }
+ a_load_reg_cgpara(list,OS_ADDR,NR_STACK_POINTER_REG,para1);
+ a_loadaddr_ref_cgpara(list,href,para2);
+ paramanager.freecgpara(list,para2);
+ paramanager.freecgpara(list,para1);
+ g_call(current_asmdata.CurrAsmList,'_FPC_local_unwind');
+ para2.done;
+ para1.done;
+ end;
+
+ procedure tcgx86_64.a_loadmm_intreg_reg(list: TAsmList; fromsize, tosize : tcgsize; intreg, mmreg: tregister; shuffle: pmmshuffle);
+ var
+ opc: tasmop;
+ begin
+ { this code can only be used to transfer raw data, not to perform
+ conversions }
+ if (tcgsize2size[fromsize]<>tcgsize2size[tosize]) or
+ not(tosize in [OS_F32,OS_F64,OS_M64]) then
+ internalerror(2009112505);
+ case fromsize of
+ OS_32,OS_S32:
+ opc:=A_MOVD;
+ OS_64,OS_S64:
+ opc:=A_MOVQ;
+ else
+ internalerror(2009112506);
+ end;
+ if assigned(shuffle) and
+ not shufflescalar(shuffle) then
+ internalerror(2009112517);
+ list.concat(taicpu.op_reg_reg(opc,S_NO,intreg,mmreg));
+ end;
+
+
+ procedure tcgx86_64.a_loadmm_reg_intreg(list: TAsmList; fromsize, tosize : tcgsize; mmreg, intreg: tregister;shuffle : pmmshuffle);
+ var
+ opc: tasmop;
+ begin
+ { this code can only be used to transfer raw data, not to perform
+ conversions }
+ if (tcgsize2size[fromsize]<>tcgsize2size[tosize]) or
+ not (fromsize in [OS_F32,OS_F64,OS_M64]) then
+ internalerror(2009112507);
+ case tosize of
+ OS_32,OS_S32:
+ opc:=A_MOVD;
+ OS_64,OS_S64:
+ opc:=A_MOVQ;
+ else
+ internalerror(2009112408);
+ end;
+ if assigned(shuffle) and
+ not shufflescalar(shuffle) then
+ internalerror(2009112515);
+ list.concat(taicpu.op_reg_reg(opc,S_NO,mmreg,intreg));
+ end;
+
+
+ procedure create_codegen;
+ begin
+ cg:=tcgx86_64.create;
+ end;
+
+end.
diff --git a/closures/compiler/x86_64/cpubase.inc b/closures/compiler/x86_64/cpubase.inc
new file mode 100644
index 0000000000..5ad43262b3
--- /dev/null
+++ b/closures/compiler/x86_64/cpubase.inc
@@ -0,0 +1,134 @@
+{
+ Copyright (c) 1998-2000 by Florian Klaempfl and Peter Vreman
+
+ Contains the basic declarations for the x86-64 architecture
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+{ This include file contains the basic declarations for the x86-64 architecture.
+}
+
+{*****************************************************************************
+ Operand Sizes
+*****************************************************************************}
+
+type
+ topsize = (S_NO,
+ S_B,S_W,S_L,S_Q,S_BW,S_BL,S_WL,S_BQ,S_WQ,S_LQ,
+ S_IS,S_IL,S_IQ,
+ S_FS,S_FL,S_FX,S_FV,S_FXX,
+ S_MD,
+ S_NEAR,S_FAR,S_SHORT,
+ S_T,
+ S_XMM
+ );
+
+{*****************************************************************************
+ Registers
+*****************************************************************************}
+
+const
+ { Standard opcode string table (for each tasmop enumeration). The
+ opcode strings should conform to the names as defined by the
+ processor manufacturer.
+ }
+ std_op2str:op2strtable={$i x8664int.inc}
+
+{*****************************************************************************
+ GDB Information
+*****************************************************************************}
+
+ {# Register indexes for stabs information, when some
+ parameters or variables are stored in registers.
+
+ Taken from i386.c (dbx_register_map) and i386.h
+ (FIXED_REGISTERS) from GCC 3.x source code
+
+ }
+ stab_regindex : array[tregisterindex] of shortint = (
+ {$i r8664stab.inc}
+ );
+
+{*****************************************************************************
+ Default generic sizes
+*****************************************************************************}
+
+ { Defines the default address size for a processor, }
+ OS_ADDR = OS_64;
+ { the natural int size for a processor, }
+ OS_INT = OS_64;
+ OS_SINT = OS_S64;
+ { the maximum float size for a processor, }
+ OS_FLOAT = OS_F80;
+ { the size of a vector register for a processor }
+ OS_VECTOR = OS_M128;
+
+{*****************************************************************************
+ Generic Register names
+*****************************************************************************}
+
+ {# Stack pointer register }
+ RS_STACK_POINTER_REG = RS_RSP;
+ NR_STACK_POINTER_REG = NR_RSP;
+ {# Frame pointer register }
+ RS_FRAME_POINTER_REG = RS_RBP;
+ NR_FRAME_POINTER_REG = NR_RBP;
+ { Return address for DWARF }
+ NR_RETURN_ADDRESS_REG = NR_EIP;
+ { Register for addressing absolute data in a position independant way,
+ such as in PIC code. The exact meaning is ABI specific. For
+ further information look at GCC source : PIC_OFFSET_TABLE_REGNUM
+ }
+ NR_PIC_OFFSET_REG = NR_RBX;
+ { Results are returned in this register (both 32 and 64 bits }
+ NR_FUNCTION_RETURN_REG = NR_RAX;
+ RS_FUNCTION_RETURN_REG = RS_RAX;
+ NR_FUNCTION_RETURN_REG_HIGH = NR_RDX;
+ RS_FUNCTION_RETURN_REG_HIGH = RS_RDX;
+ { The value returned from a function is available in this register }
+ NR_FUNCTION_RESULT_REG = NR_FUNCTION_RETURN_REG;
+ RS_FUNCTION_RESULT_REG = RS_FUNCTION_RETURN_REG;
+ NR_FUNCTION_RESULT_REG_HIGH = NR_FUNCTION_RETURN_REG_HIGH;
+ RS_FUNCTION_RESULT_REG_HIGH = RS_FUNCTION_RETURN_REG_HIGH;
+
+ { WARNING: don't change to R_ST0!! See comments above implementation of }
+ { a_loadfpu* methods in rgcpu (JM) }
+ NR_FPU_RESULT_REG = NR_ST;
+ NR_MM_RESULT_REG = NR_XMM0;
+ RS_MM_RESULT_REG = RS_XMM0;
+ NR_MM_RESULT_REG_HIGH = NR_XMM1;
+ RS_MM_RESULT_REG_HIGH = RS_XMM1;
+
+ { Offset where the parent framepointer is pushed }
+ PARENT_FRAMEPOINTER_OFFSET = 16;
+
+{*****************************************************************************
+ GCC /ABI linking information
+*****************************************************************************}
+
+ const
+ { these arrays differ between unix and win64 }
+ saved_standard_registers : array of tsuperregister = nil;
+ saved_mm_registers : array of tsuperregister = nil;
+ { Required parameter alignment when calling a routine declared as
+ stdcall and cdecl. The alignment value should be the one defined
+ by GCC or the target ABI.
+
+ The value of this constant is equal to the constant
+ PARM_BOUNDARY / BITS_PER_UNIT in the GCC source.
+ }
+ std_param_align = 8;
diff --git a/closures/compiler/x86_64/cpuinfo.pas b/closures/compiler/x86_64/cpuinfo.pas
new file mode 100644
index 0000000000..3b44c3c906
--- /dev/null
+++ b/closures/compiler/x86_64/cpuinfo.pas
@@ -0,0 +1,103 @@
+{
+ Copyright (c) 1998-2000 by Florian Klaempfl
+
+ Basic Processor information
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+Unit cpuinfo;
+
+{$i fpcdefs.inc}
+
+Interface
+
+ uses
+ globtype;
+
+Type
+ bestreal = extended;
+ ts32real = single;
+ ts64real = double;
+ ts80real = extended;
+ ts128real = type extended;
+ ts64comp = type extended;
+
+ pbestreal=^bestreal;
+
+ tcputype =
+ (cpu_none,
+ cpu_athlon64
+ );
+
+ tfputype =
+ (fpu_none,
+// fpu_soft, { generic }
+ fpu_sse64,
+ fpu_sse3
+ );
+
+Const
+ { Size of native extended type }
+ extended_size = 10;
+ { Size of a multimedia register }
+ mmreg_size = 16;
+ { target cpu string (used by compiler options) }
+ target_cpu_string = 'x86_64';
+
+ { calling conventions supported by the code generator }
+ supported_calling_conventions : tproccalloptions = [
+ pocall_internproc,
+{ pocall_compilerproc,
+ pocall_inline,}
+ pocall_register,
+ pocall_safecall,
+ pocall_stdcall,
+ pocall_cdecl,
+ pocall_cppdecl,
+ pocall_mwpascal
+ ];
+
+ cputypestr : array[tcputype] of string[10] = ('',
+ 'ATHLON64'
+ );
+
+ fputypestr : array[tfputype] of string[6] = ('',
+// 'SOFT',
+ 'SSE64',
+ 'SSE3'
+ );
+
+ sse_singlescalar : set of tfputype = [fpu_sse64,fpu_sse3];
+ sse_doublescalar : set of tfputype = [fpu_sse64,fpu_sse3];
+
+ { Supported optimizations, only used for information }
+ supported_optimizerswitches = genericlevel1optimizerswitches+
+ genericlevel2optimizerswitches+
+ genericlevel3optimizerswitches-
+ { no need to write info about those }
+ [cs_opt_level1,cs_opt_level2,cs_opt_level3]+
+ [cs_opt_regvar,cs_opt_loopunroll,cs_opt_stackframe,
+ cs_opt_tailrecursion,cs_opt_nodecse];
+
+ level1optimizerswitches = genericlevel1optimizerswitches;
+ level2optimizerswitches = genericlevel2optimizerswitches + level1optimizerswitches +
+ [cs_opt_regvar,cs_opt_stackframe,cs_opt_tailrecursion,cs_opt_nodecse];
+ level3optimizerswitches = genericlevel3optimizerswitches + level2optimizerswitches + [{,cs_opt_loopunroll}];
+
+Implementation
+
+end.
diff --git a/closures/compiler/x86_64/cpunode.pas b/closures/compiler/x86_64/cpunode.pas
new file mode 100644
index 0000000000..4567381f6e
--- /dev/null
+++ b/closures/compiler/x86_64/cpunode.pas
@@ -0,0 +1,63 @@
+{
+ Copyright (c) 2000 by Florian Klaempfl
+
+ Includes the x86-64 code generator
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+{ This is a helper unit to include the necessary code generator units
+ for the x86-64 processor.
+}
+unit cpunode;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ implementation
+
+ uses
+ { generic nodes }
+ ncgbas,
+ ncgld,
+ ncgflw,
+ ncgcnv,
+ ncgmem,
+ ncgmat,
+ ncgcon,
+ ncgcal,
+ ncgset,
+ ncgopt,
+ ncgobjc,
+ // n386con,n386flw,n386mat,n386mem,
+ // n386set,n386inl,n386opt,
+ { the cpu specific node units must be used after the generic ones to
+ get the correct class pointer }
+ nx86set,
+ nx86con,
+ nx86mem,
+ nx64add,
+ nx64cal,
+ nx64cnv,
+ nx64mat,
+{$ifdef TEST_WIN64_SEH}
+ nx64flw,
+{$endif TEST_WIN64_SEH}
+ nx64inl
+ ;
+
+end.
diff --git a/closures/compiler/x86_64/cpupara.pas b/closures/compiler/x86_64/cpupara.pas
new file mode 100644
index 0000000000..bf785edcfa
--- /dev/null
+++ b/closures/compiler/x86_64/cpupara.pas
@@ -0,0 +1,1251 @@
+{
+ Copyright (c) 2002 by Florian Klaempfl
+
+ Generates the argument location information for x86-64 target
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit cpupara;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ globtype,
+ cpubase,cgbase,cgutils,
+ symconst,symtype,symsym,symdef,
+ aasmtai,aasmdata,
+ parabase,paramgr;
+
+ type
+ tx86_64paramanager = class(tparamanager)
+ private
+ procedure create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
+ procedure create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee;paras:tparalist;
+ var intparareg,mmparareg,parasize:longint;varargsparas: boolean);
+ public
+ function param_use_paraloc(const cgpara:tcgpara):boolean;override;
+ function push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override;
+ function ret_in_param(def : tdef;calloption : tproccalloption) : boolean;override;
+ procedure getintparaloc(calloption : tproccalloption; nr : longint;var cgpara:TCGPara);override;
+ function get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;override;
+ function get_volatile_registers_mm(calloption : tproccalloption):tcpuregisterset;override;
+ function get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;override;
+ function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override;
+ function create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;override;
+ function get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tcgpara;override;
+ end;
+
+ implementation
+
+ uses
+ cutils,verbose,
+ systems,
+ defutil,
+ symtable;
+
+ const
+ paraintsupregs : array[0..5] of tsuperregister = (RS_RDI,RS_RSI,RS_RDX,RS_RCX,RS_R8,RS_R9);
+ parammsupregs : array[0..7] of tsuperregister = (RS_XMM0,RS_XMM1,RS_XMM2,RS_XMM3,RS_XMM4,RS_XMM5,RS_XMM6,RS_XMM7);
+
+ paraintsupregs_winx64 : array[0..3] of tsuperregister = (RS_RCX,RS_RDX,RS_R8,RS_R9);
+ parammsupregs_winx64 : array[0..3] of tsuperregister = (RS_XMM0,RS_XMM1,RS_XMM2,RS_XMM3);
+
+{
+ The argument classification code largely comes from libffi:
+
+ ffi64.c - Copyright (c) 2002, 2007 Bo Thorsen <bo@suse.de>
+ Copyright (c) 2008 Red Hat, Inc.
+
+ x86-64 Foreign Function Interface
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ ``Software''), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
+ ----------------------------------------------------------------------- *)
+}
+
+ const
+ MAX_PARA_CLASSES = 4;
+
+ type
+ tx64paraclass = (
+ X86_64_NO_CLASS,
+ X86_64_INTEGER_CLASS,X86_64_INTEGERSI_CLASS,
+ X86_64_SSE_CLASS,X86_64_SSESF_CLASS,X86_64_SSEDF_CLASS,X86_64_SSEUP_CLASS,
+ X86_64_X87_CLASS,X86_64_X87UP_CLASS,
+ X86_64_COMPLEX_X87_CLASS,
+ X86_64_MEMORY_CLASS
+ );
+ tx64paraclasses = array[0..MAX_PARA_CLASSES-1] of tx64paraclass;
+
+ { Win64-specific helper }
+ function aggregate_in_registers_win64(varspez:tvarspez;size:longint):boolean;
+ begin
+ { TODO: Temporary hack: vs_const parameters are always passed by reference for win64}
+ result:=(varspez=vs_value) and (size in [1,2,4,8])
+ end;
+
+ (* x86-64 register passing implementation. See x86-64 ABI for details. Goal
+ of this code is to classify each 8bytes of incoming argument by the register
+ class and assign registers accordingly. *)
+
+ (* Return the union class of CLASS1 and CLASS2.
+ See the x86-64 PS ABI for details. *)
+
+ function merge_classes(class1, class2: tx64paraclass): tx64paraclass;
+ begin
+ (* Rule #1: If both classes are equal, this is the resulting class. *)
+ if (class1=class2) then
+ exit(class1);
+
+ (* Rule #2: If one of the classes is NO_CLASS, the resulting class is
+ the other class. *)
+ if (class1=X86_64_NO_CLASS) then
+ exit(class2);
+ if (class2=X86_64_NO_CLASS) then
+ exit(class1);
+
+ (* Rule #3: If one of the classes is MEMORY, the result is MEMORY. *)
+ if (class1=X86_64_MEMORY_CLASS) or
+ (class2=X86_64_MEMORY_CLASS) then
+ exit(X86_64_MEMORY_CLASS);
+
+ (* Rule #4: If one of the classes is INTEGER, the result is INTEGER. *)
+ { 32 bit }
+ if ((class1=X86_64_INTEGERSI_CLASS) and
+ (class2=X86_64_SSESF_CLASS)) or
+ ((class2=X86_64_INTEGERSI_CLASS) and
+ (class1=X86_64_SSESF_CLASS)) then
+ exit(X86_64_INTEGERSI_CLASS);
+ { 64 bit }
+ if (class1 in [X86_64_INTEGER_CLASS,X86_64_INTEGERSI_CLASS]) or
+ (class2 in [X86_64_INTEGER_CLASS,X86_64_INTEGERSI_CLASS]) then
+ exit(X86_64_INTEGER_CLASS);
+
+ (* Rule #5: If one of the classes is X87, X87UP, or COMPLEX_X87 class,
+ MEMORY is used. *)
+ if (class1 in [X86_64_X87_CLASS,X86_64_X87UP_CLASS,X86_64_COMPLEX_X87_CLASS]) or
+ (class2 in [X86_64_X87_CLASS,X86_64_X87UP_CLASS,X86_64_COMPLEX_X87_CLASS]) then
+ exit(X86_64_MEMORY_CLASS);
+
+ (* Rule #6: Otherwise class SSE is used. *)
+ result:=X86_64_SSE_CLASS;
+ end;
+
+ (* Classify the argument of type TYPE and mode MODE.
+ CLASSES will be filled by the register class used to pass each word
+ of the operand. The number of words is returned. In case the parameter
+ should be passed in memory, 0 is returned. As a special case for zero
+ sized containers, classes[0] will be NO_CLASS and 1 is returned.
+
+ real_size contains either def.size, or a value derived from
+ def.bitpackedsize and the field offset denoting the number of bytes
+ spanned by a bitpacked field
+
+ See the x86-64 PS ABI for details.
+ *)
+ function classify_as_integer_argument(real_size: aint; var classes: tx64paraclasses; byte_offset: aint): longint;
+ var
+ size: aint;
+ begin
+ size:=byte_offset+real_size;
+ if size<=4 then
+ classes[0]:=X86_64_INTEGERSI_CLASS
+ else
+ classes[0]:=X86_64_INTEGER_CLASS;
+ if size<=8 then
+ result:=1
+ else
+ begin
+ if size<=12 then
+ classes[1]:=X86_64_INTEGERSI_CLASS
+ else if (size<=16) then
+ classes[1]:=X86_64_INTEGER_CLASS
+ else
+ internalerror(2010021401);
+ result:=2;
+ end
+ end;
+
+
+ function classify_argument(def: tdef; varspez: tvarspez; real_size: aint; var classes: tx64paraclasses; byte_offset: aint): longint; forward;
+
+ function init_aggregate_classification(def: tdef; varspez: tvarspez; out words: longint; out classes: tx64paraclasses): longint;
+ var
+ i: longint;
+ begin
+ words:=0;
+ { win64 follows a different convention here }
+ if (target_info.system=system_x86_64_win64) then
+ begin
+ if aggregate_in_registers_win64(varspez,def.size) then
+ begin
+ classes[0]:=X86_64_INTEGER_CLASS;
+ result:=1;
+ end
+ else
+ result:=0;
+ exit;
+ end;
+
+ (* If the struct is larger than 32 bytes, pass it on the stack. *)
+ if def.size > 32 then
+ exit(0);
+
+ words:=(def.size+7) div 8;
+
+ (* Zero sized arrays or structures are NO_CLASS. We return 0 to
+ signal memory class, so handle it as special case. *)
+ if (words=0) then
+ begin
+ classes[0]:=X86_64_NO_CLASS;
+ exit(1);
+ end;
+
+ { we'll be merging the classes elements with the subclasses
+ elements, so initialise them first }
+ for i:=low(classes) to high(classes) do
+ classes[i]:=X86_64_NO_CLASS;
+ result:=words;
+ end;
+
+
+ function classify_aggregate_element(def: tdef; varspez: tvarspez; real_size: aint; var classes: tx64paraclasses; new_byte_offset: aint): longint;
+ var
+ subclasses: tx64paraclasses;
+ i,
+ pos: longint;
+ begin
+ result:=classify_argument(def,varspez,real_size,subclasses,new_byte_offset mod 8);
+ if (result=0) then
+ exit;
+ pos:=new_byte_offset div 8;
+ if result-1+pos>high(classes) then
+ internalerror(2010053108);
+ for i:=0 to result-1 do
+ begin
+ classes[i+pos] :=
+ merge_classes(subclasses[i],classes[i+pos]);
+ end;
+ end;
+
+
+ function finalize_aggregate_classification(def: tdef; words: longint; var classes: tx64paraclasses): longint;
+ var
+ i: longint;
+ begin
+ if (words>2) then
+ begin
+ (* When size > 16 bytes, if the first one isn't
+ X86_64_SSE_CLASS or any other ones aren't
+ X86_64_SSEUP_CLASS, everything should be passed in
+ memory. *)
+ if (classes[0]<>X86_64_SSE_CLASS) then
+ exit(0);
+
+ for i:=1 to words-1 do
+ if (classes[i]<>X86_64_SSEUP_CLASS) then
+ exit(0);
+ end;
+
+ (* Final merger cleanup. *)
+ (* The first one must never be X86_64_SSEUP_CLASS or
+ X86_64_X87UP_CLASS. *)
+ if (classes[0]=X86_64_SSEUP_CLASS) or
+ (classes[0]=X86_64_X87UP_CLASS) then
+ internalerror(2010021402);
+ for i:=0 to words-1 do
+ begin
+ (* If one class is MEMORY, everything should be passed in
+ memory. *)
+ if (classes[i]=X86_64_MEMORY_CLASS) then
+ exit(0);
+
+ (* The X86_64_SSEUP_CLASS should be always preceded by
+ X86_64_SSE_CLASS or X86_64_SSEUP_CLASS. *)
+ if (classes[i]=X86_64_SSEUP_CLASS) and
+ (classes[i-1]<>X86_64_SSE_CLASS) and
+ (classes[i-1]<>X86_64_SSEUP_CLASS) then
+ classes[i]:=X86_64_SSE_CLASS;
+
+ (* If X86_64_X87UP_CLASS isn't preceded by X86_64_X87_CLASS,
+ everything should be passed in memory. *)
+ if (classes[i]=X86_64_X87UP_CLASS) and
+ (classes[i-1]<>X86_64_X87_CLASS) then
+ exit(0);
+ end;
+
+ { FIXME: in case a record contains empty padding space, e.g. a
+ "single" field followed by a "double", then we have a problem
+ because the cgpara helpers cannot figure out that they should
+ skip 4 bytes after storing the single (LOC_MMREGISTER with size
+ OS_F32) to memory before storing the double -> for now scale
+ such locations always up to 64 bits, although this loads/stores
+ some superfluous data }
+ { 1) the first part is 32 bit while there is still a second part }
+ if (classes[1]<>X86_64_NO_CLASS) then
+ case classes[0] of
+ X86_64_INTEGERSI_CLASS:
+ classes[0]:=X86_64_INTEGER_CLASS;
+ X86_64_SSESF_CLASS:
+ classes[0]:=X86_64_SSE_CLASS;
+ end;
+ { 2) the second part is 32 bit, but the total size is > 12 bytes }
+ if (def.size>12) then
+ case classes[1] of
+ X86_64_INTEGERSI_CLASS:
+ classes[1]:=X86_64_INTEGER_CLASS;
+ X86_64_SSESF_CLASS:
+ classes[1]:=X86_64_SSE_CLASS;
+ end;
+
+ result:=words;
+ end;
+
+
+ function classify_record(def: tdef; varspez: tvarspez; var classes: tx64paraclasses; byte_offset: aint): longint;
+ var
+ vs: tfieldvarsym;
+ size,
+ new_byte_offset: aint;
+ i,
+ words,
+ num: longint;
+ begin
+ result:=init_aggregate_classification(def,varspez,words,classes);
+ if (words=0) then
+ exit;
+
+ (* Merge the fields of the structure. *)
+ for i:=0 to tabstractrecorddef(def).symtable.symlist.count-1 do
+ begin
+ if tsym(tabstractrecorddef(def).symtable.symlist[i]).typ<>fieldvarsym then
+ continue;
+ vs:=tfieldvarsym(tabstractrecorddef(def).symtable.symlist[i]);
+ num:=-1;
+ if not tabstractrecordsymtable(tabstractrecorddef(def).symtable).is_packed then
+ begin
+ new_byte_offset:=byte_offset+vs.fieldoffset;
+ size:=vs.vardef.size;
+ end
+ else
+ begin
+ new_byte_offset:=byte_offset+vs.fieldoffset div 8;
+ if (vs.vardef.typ in [orddef,enumdef]) then
+ { calculate the number of bytes spanned by
+ this bitpacked field }
+ size:=((vs.fieldoffset+vs.vardef.packedbitsize+7) div 8)-(vs.fieldoffset div 8)
+ else
+ size:=vs.vardef.size
+ end;
+ num:=classify_aggregate_element(vs.vardef,varspez,size,classes,new_byte_offset);
+ if (num=0) then
+ exit(0);
+ end;
+
+ result:=finalize_aggregate_classification(def,words,classes);
+ end;
+
+
+ function classify_normal_array(def: tarraydef; varspez: tvarspez; var classes: tx64paraclasses; byte_offset: aint): longint;
+ var
+ i, elecount: aword;
+ size,
+ elesize,
+ new_byte_offset,
+ bitoffset: aint;
+ words,
+ num: longint;
+ isbitpacked: boolean;
+ begin
+ result:=init_aggregate_classification(def,varspez,words,classes);
+ if (words=0) then
+ exit;
+
+ isbitpacked:=is_packed_array(def);
+ if not isbitpacked then
+ begin
+ elesize:=def.elesize;
+ size:=elesize;
+ end
+ else
+ begin
+ elesize:=def.elepackedbitsize;
+ bitoffset:=0;
+ end;
+
+ (* Merge the elements of the array. *)
+ i:=0;
+ elecount:=def.elecount;
+ repeat
+ if not isbitpacked then
+ begin
+ { size does not change }
+ new_byte_offset:=byte_offset+i*elesize;
+ end
+ else
+ begin
+ { calculate the number of bytes spanned by this bitpacked
+ element }
+ size:=((bitoffset+elesize+7) div 8)-(bitoffset div 8);
+ new_byte_offset:=byte_offset+(elesize*i) div 8;
+ { bit offset of next element }
+ inc(bitoffset,elesize);
+ end;
+ num:=classify_aggregate_element(def.elementdef,varspez,size,classes,new_byte_offset);
+ if (num=0) then
+ exit(0);
+ inc(i);
+ until (i=elecount);
+
+ result:=finalize_aggregate_classification(def,words,classes);
+ end;
+
+
+ function classify_argument(def: tdef; varspez: tvarspez; real_size: aint; var classes: tx64paraclasses; byte_offset: aint): longint;
+ begin
+ case def.typ of
+ orddef,
+ enumdef,
+ pointerdef,
+ classrefdef:
+ result:=classify_as_integer_argument(real_size,classes,byte_offset);
+ formaldef:
+ result:=classify_as_integer_argument(voidpointertype.size,classes,byte_offset);
+ floatdef:
+ begin
+ case tfloatdef(def).floattype of
+ s32real:
+ begin
+ if byte_offset=0 then
+ classes[0]:=X86_64_SSESF_CLASS
+ else
+ { if we have e.g. a record with two successive "single"
+ fields, we need a 64 bit rather than a 32 bit load }
+ classes[0]:=X86_64_SSE_CLASS;
+ result:=1;
+ end;
+ s64real:
+ begin
+ classes[0]:=X86_64_SSEDF_CLASS;
+ result:=1;
+ end;
+ s80real,
+ sc80real:
+ begin
+ classes[0]:=X86_64_X87_CLASS;
+ classes[1]:=X86_64_X87UP_CLASS;
+ result:=2;
+ end;
+ s64comp,
+ s64currency:
+ begin
+ classes[0]:=X86_64_INTEGER_CLASS;
+ result:=1;
+ end;
+ s128real:
+ begin
+ classes[0]:=X86_64_SSE_CLASS;
+ classes[1]:=X86_64_SSEUP_CLASS;
+ result:=2;
+ end;
+ else
+ internalerror(2010060301);
+ end;
+ end;
+ recorddef:
+ result:=classify_record(def,varspez,classes,byte_offset);
+ objectdef:
+ begin
+ if is_object(def) then
+ { pass by reference, like ppc and i386 }
+ result:=0
+ else
+ { all kinds of pointer types: class, objcclass, interface, ... }
+ result:=classify_as_integer_argument(voidpointertype.size,classes,byte_offset);
+ end;
+ setdef:
+ begin
+ if is_smallset(def) then
+ result:=classify_as_integer_argument(def.size,classes,byte_offset)
+ else
+ result:=0;
+ end;
+ stringdef:
+ begin
+ if (tstringdef(def).stringtype in [st_shortstring,st_longstring]) then
+ result:=0
+ else
+ result:=classify_as_integer_argument(def.size,classes,byte_offset);
+ end;
+ arraydef:
+ begin
+ { a dynamic array is treated like a pointer }
+ if is_dynamic_array(def) then
+ result:=classify_as_integer_argument(voidpointertype.size,classes,byte_offset)
+ { other special arrays are passed on the stack }
+ else if is_open_array(def) or
+ is_array_of_const(def) then
+ result:=0
+ else
+ { normal array }
+ result:=classify_normal_array(tarraydef(def),varspez,classes,byte_offset);
+ end;
+ { the file record is definitely too big }
+ filedef:
+ result:=0;
+ procvardef:
+ begin
+ if (po_methodpointer in tprocvardef(def).procoptions) then
+ begin
+ { treat as TMethod record }
+ def:=search_system_type('TMETHOD').typedef;
+ result:=classify_argument(def,varspez,def.size,classes,byte_offset);
+ end
+ else
+ { pointer }
+ result:=classify_as_integer_argument(def.size,classes,byte_offset);
+ end;
+ variantdef:
+ begin
+ { same as tvardata record }
+ def:=search_system_type('TVARDATA').typedef;
+ result:=classify_argument(def,varspez,def.size,classes,byte_offset);
+ end;
+ else
+ internalerror(2010021405);
+ end;
+ end;
+
+
+ procedure getvalueparaloc(varspez:tvarspez;def:tdef;var loc1,loc2:tx64paraclass);
+ var
+ size: aint;
+ i: longint;
+ classes: tx64paraclasses;
+ numclasses: longint;
+ begin
+ { init the classes array, because even if classify_argument inits only
+ one element we copy both to loc1/loc2 in case "1" is returned }
+ for i:=low(classes) to high(classes) do
+ classes[i]:=X86_64_NO_CLASS;
+ { def.size internalerrors for open arrays and dynamic arrays, since
+ their size cannot be determined at compile-time.
+ classify_argument does not look at the realsize argument for arrays
+ cases, but we obviously do have to pass something... }
+ if is_special_array(def) then
+ size:=-1
+ else
+ size:=def.size;
+ numclasses:=classify_argument(def,varspez,size,classes,0);
+ case numclasses of
+ 0:
+ begin
+ loc1:=X86_64_MEMORY_CLASS;
+ loc2:=X86_64_NO_CLASS;
+ end;
+ 1,2:
+ begin
+ { If the class is X87, X87UP or COMPLEX_X87, it is passed in memory }
+ if classes[0] in [X86_64_X87_CLASS,X86_64_X87UP_CLASS,X86_64_COMPLEX_X87_CLASS] then
+ classes[0]:=X86_64_MEMORY_CLASS;
+ if classes[1] in [X86_64_X87_CLASS,X86_64_X87UP_CLASS,X86_64_COMPLEX_X87_CLASS] then
+ classes[1]:=X86_64_MEMORY_CLASS;
+ loc1:=classes[0];
+ loc2:=classes[1];
+ end
+ else
+ { 4 can only happen for _m256 vectors, not yet supported }
+ internalerror(2010021501);
+ end;
+ end;
+
+
+ function tx86_64paramanager.ret_in_param(def : tdef;calloption : tproccalloption) : boolean;
+ var
+ classes: tx64paraclasses;
+ numclasses: longint;
+ begin
+ if (tf_safecall_exceptions in target_info.flags) and
+ (calloption=pocall_safecall) then
+ begin
+ result := true;
+ exit;
+ end;
+ case def.typ of
+ { for records it depends on their contents and size }
+ recorddef,
+ { make sure we handle 'procedure of object' correctly }
+ procvardef:
+ begin
+ numclasses:=classify_argument(def,vs_value,def.size,classes,0);
+ result:=(numclasses=0);
+ end;
+ else
+ result:=inherited ret_in_param(def,calloption);
+ end;
+ end;
+
+
+ function tx86_64paramanager.param_use_paraloc(const cgpara:tcgpara):boolean;
+ var
+ paraloc : pcgparalocation;
+ begin
+ if not assigned(cgpara.location) then
+ internalerror(200410102);
+ result:=true;
+ { All locations are LOC_REFERENCE }
+ paraloc:=cgpara.location;
+ while assigned(paraloc) do
+ begin
+ if (paraloc^.loc<>LOC_REFERENCE) then
+ begin
+ result:=false;
+ exit;
+ end;
+ paraloc:=paraloc^.next;
+ end;
+ end;
+
+
+ { true if a parameter is too large to copy and only the address is pushed }
+ function tx86_64paramanager.push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;
+ var
+ classes: tx64paraclasses;
+ numclasses: longint;
+ begin
+ result:=false;
+ { var,out,constref always require address }
+ if varspez in [vs_var,vs_out,vs_constref] then
+ begin
+ result:=true;
+ exit;
+ end;
+ { Only vs_const, vs_value here }
+ case def.typ of
+ formaldef :
+ result:=true;
+ recorddef :
+ begin
+ { MetroWerks Pascal: const records always passed by reference
+ (for Mac OS X interfaces) }
+ if (calloption=pocall_mwpascal) and
+ (varspez=vs_const) then
+ result:=true
+ { Win ABI depends on size to pass it in a register or not }
+ else if (target_info.system=system_x86_64_win64) then
+ result:=not aggregate_in_registers_win64(varspez,def.size)
+ { pass constant parameters that would be passed via memory by
+ reference for non-cdecl/cppdecl, and make sure that the tmethod
+ record (size=16) is passed the same way as a complex procvar }
+ else if ((varspez=vs_const) and
+ not(calloption in [pocall_cdecl,pocall_cppdecl])) or
+ (def.size=16) then
+ begin
+ numclasses:=classify_argument(def,vs_value,def.size,classes,0);
+ result:=numclasses=0;
+ end
+ else
+ { SysV ABI always passes it as value parameter }
+ result:=false;
+ end;
+ arraydef :
+ begin
+ { cdecl array of const need to be ignored and therefor be puhsed
+ as value parameter with length 0 }
+ if ((calloption in [pocall_cdecl,pocall_cppdecl]) and
+ is_array_of_const(def)) or
+ is_dynamic_array(def) then
+ result:=false
+ else
+ { pass all arrays by reference to be compatible with C (passing
+ an array by value (= copying it on the stack) does not exist,
+ because an array is the same as a pointer there }
+ result:=true
+ end;
+ objectdef :
+ begin
+ { don't treat objects like records, because we only know wheter
+ or not they'll have a VMT after the entire object is parsed
+ -> if they are used as function result from one of their own
+ methods, their size can still change after we've determined
+ whether this function result should be returned by reference or
+ by value }
+ if is_object(def) then
+ result:=true;
+ end;
+ variantdef,
+ stringdef,
+ procvardef,
+ setdef :
+ begin
+ numclasses:=classify_argument(def,vs_value,def.size,classes,0);
+ result:=numclasses=0;
+ end;
+ end;
+ end;
+
+
+ function tx86_64paramanager.get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;
+ begin
+ if target_info.system=system_x86_64_win64 then
+ result:=[RS_RAX,RS_RCX,RS_RDX,RS_R8,RS_R9,RS_R10,RS_R11]
+ else
+ result:=[RS_RAX,RS_RCX,RS_RDX,RS_RSI,RS_RDI,RS_R8,RS_R9,RS_R10,RS_R11];
+ end;
+
+
+ function tx86_64paramanager.get_volatile_registers_mm(calloption : tproccalloption):tcpuregisterset;
+ begin
+ if target_info.system=system_x86_64_win64 then
+ result:=[RS_XMM0..RS_XMM5]
+ else
+ result:=[RS_XMM0..RS_XMM15];
+ end;
+
+
+ function tx86_64paramanager.get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;
+ begin
+ result:=[RS_ST0..RS_ST7];
+ end;
+
+
+ procedure tx86_64paramanager.getintparaloc(calloption : tproccalloption; nr : longint;var cgpara:TCGPara);
+ var
+ paraloc : pcgparalocation;
+ begin
+ cgpara.reset;
+ cgpara.size:=OS_ADDR;
+ cgpara.intsize:=sizeof(pint);
+ cgpara.alignment:=get_para_align(calloption);
+ paraloc:=cgpara.add_location;
+ with paraloc^ do
+ begin
+ size:=OS_INT;
+ if target_info.system=system_x86_64_win64 then
+ begin
+ if nr<1 then
+ internalerror(200304303)
+ else if nr<=high(paraintsupregs_winx64)+1 then
+ begin
+ loc:=LOC_REGISTER;
+ register:=newreg(R_INTREGISTER,paraintsupregs_winx64[nr-1],R_SUBWHOLE);
+ end
+ else
+ begin
+ loc:=LOC_REFERENCE;
+ reference.index:=NR_STACK_POINTER_REG;
+ reference.offset:=(nr-6)*sizeof(aint);
+ end;
+ end
+ else
+ begin
+ if nr<1 then
+ internalerror(200304303)
+ else if nr<=high(paraintsupregs)+1 then
+ begin
+ loc:=LOC_REGISTER;
+ register:=newreg(R_INTREGISTER,paraintsupregs[nr-1],R_SUBWHOLE);
+ end
+ else
+ begin
+ loc:=LOC_REFERENCE;
+ reference.index:=NR_STACK_POINTER_REG;
+ reference.offset:=(nr-6)*sizeof(aint);
+ end;
+ end;
+ end;
+ end;
+
+
+ procedure tx86_64paramanager.create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
+ begin
+ p.funcretloc[side]:=get_funcretloc(p,side,p.returndef);
+ end;
+
+
+ function tx86_64paramanager.get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tcgpara;
+ const
+ intretregs: array[0..1] of tregister = (NR_FUNCTION_RETURN_REG,NR_FUNCTION_RETURN_REG_HIGH);
+ mmretregs: array[0..1] of tregister = (NR_MM_RESULT_REG,NR_MM_RESULT_REG_HIGH);
+ var
+ classes: tx64paraclasses;
+ i,
+ numclasses: longint;
+ intretregidx,
+ mmretregidx: longint;
+ retcgsize : tcgsize;
+ paraloc : pcgparalocation;
+ begin
+ result.init;
+ result.alignment:=get_para_align(p.proccalloption);
+ { void has no location }
+ if is_void(def) then
+ begin
+ paraloc:=result.add_location;
+ result.size:=OS_NO;
+ result.intsize:=0;
+ paraloc^.size:=OS_NO;
+ paraloc^.loc:=LOC_VOID;
+ exit;
+ end;
+ { Constructors return self instead of a boolean }
+ if (p.proctypeoption=potype_constructor) then
+ begin
+ retcgsize:=OS_ADDR;
+ result.intsize:=sizeof(pint);
+ end
+ else
+ begin
+ retcgsize:=def_cgsize(def);
+ { integer sizes < 32 bit have to be sign/zero extended to 32 bit on
+ the callee side (caller can expect those bits are valid) }
+ if (side=calleeside) and
+ (retcgsize in [OS_8,OS_S8,OS_16,OS_S16]) then
+ begin
+ retcgsize:=OS_S32;
+ result.intsize:=4;
+ end
+ else
+ result.intsize:=def.size;
+ end;
+ result.size:=retcgsize;
+ { Return is passed as var parameter }
+ if ret_in_param(def,p.proccalloption) then
+ begin
+ paraloc:=result.add_location;
+ paraloc^.loc:=LOC_REFERENCE;
+ paraloc^.size:=retcgsize;
+ exit;
+ end;
+
+ { Return in FPU register? -> don't use classify_argument(), because
+ currency and comp need special treatment here (they are integer class
+ when passing as parameter, but LOC_FPUREGISTER as function result) }
+ if def.typ=floatdef then
+ begin
+ paraloc:=result.add_location;
+ case tfloatdef(def).floattype of
+ s32real:
+ begin
+ paraloc^.loc:=LOC_MMREGISTER;
+ paraloc^.register:=newreg(R_MMREGISTER,RS_MM_RESULT_REG,R_SUBMMS);
+ paraloc^.size:=OS_F32;
+ end;
+ s64real:
+ begin
+ paraloc^.loc:=LOC_MMREGISTER;
+ paraloc^.register:=newreg(R_MMREGISTER,RS_MM_RESULT_REG,R_SUBMMD);
+ paraloc^.size:=OS_F64;
+ end;
+ { the first two only exist on targets with an x87, on others
+ they are replace by int64 }
+ s64currency,
+ s64comp,
+ s80real,
+ sc80real:
+ begin
+ paraloc^.loc:=LOC_FPUREGISTER;
+ paraloc^.register:=NR_FPU_RESULT_REG;
+ paraloc^.size:=retcgsize;
+ end;
+ else
+ internalerror(200405034);
+ end;
+ end
+ else
+ { Return in register }
+ begin
+ numclasses:=classify_argument(def,vs_value,def.size,classes,0);
+ { this would mean a memory return }
+ if (numclasses=0) then
+ internalerror(2010021502);
+ { this would mean an _m256 vector (valid, but not yet supported) }
+ if (numclasses>2) then
+ internalerror(2010021503);
+ intretregidx:=0;
+ mmretregidx:=0;
+ for i:=0 to numclasses-1 do
+ begin
+ paraloc:=result.add_location;
+ case classes[i] of
+ X86_64_INTEGERSI_CLASS,
+ X86_64_INTEGER_CLASS:
+ begin
+ paraloc^.loc:=LOC_REGISTER;
+ paraloc^.register:=intretregs[intretregidx];
+ if classes[i]=X86_64_INTEGER_CLASS then
+ paraloc^.size:=OS_64
+ else if result.intsize in [1,2,4] then
+ paraloc^.size:=retcgsize
+ else
+ paraloc^.size:=OS_32;
+ setsubreg(paraloc^.register,cgsize2subreg(R_INTREGISTER,paraloc^.size));
+ inc(intretregidx);
+ end;
+ X86_64_SSE_CLASS,
+ X86_64_SSEUP_CLASS,
+ X86_64_SSESF_CLASS,
+ X86_64_SSEDF_CLASS:
+ begin
+ paraloc^.loc:=LOC_MMREGISTER;
+ paraloc^.register:=mmretregs[mmretregidx];
+ case classes[i] of
+ X86_64_SSESF_CLASS:
+ begin
+ setsubreg(paraloc^.register,R_SUBMMS);
+ paraloc^.size:=OS_F32;
+ end;
+ X86_64_SSEDF_CLASS:
+ begin
+ setsubreg(paraloc^.register,R_SUBMMD);
+ paraloc^.size:=OS_F64;
+ end;
+ else
+ begin
+ setsubreg(paraloc^.register,R_SUBMMWHOLE);
+ paraloc^.size:=OS_M64;
+ end;
+ end;
+ inc(mmretregidx);
+ end;
+ X86_64_NO_CLASS:
+ begin
+ { empty record/array }
+ if (i<>0) or
+ (numclasses<>1) then
+ internalerror(2010060302);
+ paraloc^.loc:=LOC_VOID;
+ end;
+ else
+ internalerror(2010021504);
+ end;
+ end;
+ end;
+ end;
+
+
+ procedure tx86_64paramanager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee;paras:tparalist;
+ var intparareg,mmparareg,parasize:longint;varargsparas: boolean);
+ var
+ hp : tparavarsym;
+ paraloc : pcgparalocation;
+ subreg : tsubregister;
+ pushaddr : boolean;
+ paracgsize : tcgsize;
+ loc : array[1..2] of tx64paraclass;
+ needintloc,
+ needmmloc,
+ paralen,
+ locidx,
+ i,
+ varalign,
+ paraalign : longint;
+ begin
+ paraalign:=get_para_align(p.proccalloption);
+ { Register parameters are assigned from left to right }
+ for i:=0 to paras.count-1 do
+ begin
+ hp:=tparavarsym(paras[i]);
+ pushaddr:=push_addr_param(hp.varspez,hp.vardef,p.proccalloption);
+ if pushaddr then
+ begin
+ loc[1]:=X86_64_INTEGER_CLASS;
+ loc[2]:=X86_64_NO_CLASS;
+ paracgsize:=OS_ADDR;
+ paralen:=sizeof(pint);
+ end
+ else
+ begin
+ getvalueparaloc(hp.varspez,hp.vardef,loc[1],loc[2]);
+ paralen:=push_size(hp.varspez,hp.vardef,p.proccalloption);
+ paracgsize:=def_cgsize(hp.vardef);
+ { integer sizes < 32 bit have to be sign/zero extended to 32 bit
+ on the caller side }
+ if (side=callerside) and
+ (paracgsize in [OS_8,OS_S8,OS_16,OS_S16]) then
+ begin
+ paracgsize:=OS_S32;
+ paralen:=4;
+ end;
+ end;
+
+ { cheat for now, we should copy the value to an mm reg as well (FK) }
+ if varargsparas and
+ (target_info.system = system_x86_64_win64) and
+ (hp.vardef.typ = floatdef) then
+ begin
+ loc[2]:=X86_64_NO_CLASS;
+ if paracgsize=OS_F64 then
+ begin
+ loc[1]:=X86_64_INTEGER_CLASS;
+ paracgsize:=OS_64
+ end
+ else
+ begin
+ loc[1]:=X86_64_INTEGERSI_CLASS;
+ paracgsize:=OS_32;
+ end;
+ end;
+
+ hp.paraloc[side].reset;
+ hp.paraloc[side].size:=paracgsize;
+ hp.paraloc[side].intsize:=paralen;
+ hp.paraloc[side].Alignment:=paraalign;
+ if paralen>0 then
+ begin
+ { Enough registers free? }
+ needintloc:=0;
+ needmmloc:=0;
+ for locidx:=low(loc) to high(loc) do
+ case loc[locidx] of
+ X86_64_INTEGER_CLASS,
+ X86_64_INTEGERSI_CLASS:
+ inc(needintloc);
+ X86_64_SSE_CLASS,
+ X86_64_SSESF_CLASS,
+ X86_64_SSEDF_CLASS,
+ X86_64_SSEUP_CLASS:
+ inc(needmmloc);
+ end;
+ { the "-1" is because we can also use the current register }
+ if ((target_info.system=system_x86_64_win64) and
+ ((intparareg+needintloc-1 > high(paraintsupregs_winx64)) or
+ (mmparareg+needmmloc-1 > high(parammsupregs_winx64)))) or
+ ((target_info.system<>system_x86_64_win64) and
+ ((intparareg+needintloc-1 > high(paraintsupregs)) or
+ (mmparareg+needmmloc-1 > high(parammsupregs)))) then
+ begin
+ { If there are no registers available for any
+ eightbyte of an argument, the whole argument is
+ passed on the stack. }
+ loc[low(loc)]:=X86_64_MEMORY_CLASS;
+ for locidx:=succ(low(loc)) to high(loc) do
+ loc[locidx]:=X86_64_NO_CLASS;
+ end;
+
+ locidx:=1;
+ while (paralen>0) do
+ begin
+ if locidx>2 then
+ internalerror(200501283);
+ { Allocate }
+ case loc[locidx] of
+ X86_64_INTEGER_CLASS,
+ X86_64_INTEGERSI_CLASS:
+ begin
+ paraloc:=hp.paraloc[side].add_location;
+ paraloc^.loc:=LOC_REGISTER;
+ if (paracgsize=OS_NO) or (loc[2]<>X86_64_NO_CLASS) then
+ begin
+ if loc[locidx]=X86_64_INTEGER_CLASS then
+ begin
+ paraloc^.size:=OS_INT;
+ subreg:=R_SUBWHOLE;
+ end
+ else
+ begin
+ paraloc^.size:=OS_32;
+ subreg:=R_SUBD;
+ end;
+ end
+ else
+ begin
+ paraloc^.size:=paracgsize;
+ { s64comp is pushed in an int register }
+ if paraloc^.size=OS_C64 then
+ paraloc^.size:=OS_64;
+ subreg:=cgsize2subreg(R_INTREGISTER,paraloc^.size);
+ end;
+
+ { winx64 uses different registers }
+ if target_info.system=system_x86_64_win64 then
+ paraloc^.register:=newreg(R_INTREGISTER,paraintsupregs_winx64[intparareg],subreg)
+ else
+ paraloc^.register:=newreg(R_INTREGISTER,paraintsupregs[intparareg],subreg);
+
+ { matching mm register must be skipped }
+ if target_info.system=system_x86_64_win64 then
+ inc(mmparareg);
+
+ inc(intparareg);
+ dec(paralen,tcgsize2size[paraloc^.size]);
+ end;
+ X86_64_SSE_CLASS,
+ X86_64_SSESF_CLASS,
+ X86_64_SSEDF_CLASS,
+ X86_64_SSEUP_CLASS:
+ begin
+ paraloc:=hp.paraloc[side].add_location;
+ paraloc^.loc:=LOC_MMREGISTER;
+
+ case loc[locidx] of
+ X86_64_SSESF_CLASS:
+ begin
+ subreg:=R_SUBMMS;
+ paraloc^.size:=OS_F32;
+ end;
+ X86_64_SSEDF_CLASS:
+ begin
+ subreg:=R_SUBMMD;
+ paraloc^.size:=OS_F64;
+ end;
+ else
+ begin
+ subreg:=R_SUBMMWHOLE;
+ paraloc^.size:=OS_M64;
+ end;
+ end;
+
+ { winx64 uses different registers }
+ if target_info.system=system_x86_64_win64 then
+ paraloc^.register:=newreg(R_MMREGISTER,parammsupregs_winx64[mmparareg],subreg)
+ else
+ paraloc^.register:=newreg(R_MMREGISTER,parammsupregs[mmparareg],subreg);
+
+ { matching int register must be skipped }
+ if target_info.system=system_x86_64_win64 then
+ inc(intparareg);
+
+ inc(mmparareg);
+ dec(paralen,tcgsize2size[paraloc^.size]);
+ end;
+ X86_64_MEMORY_CLASS :
+ begin
+ paraloc:=hp.paraloc[side].add_location;
+ paraloc^.loc:=LOC_REFERENCE;
+ {Hack alert!!! We should modify int_cgsize to handle OS_128,
+ however, since int_cgsize is called in many places in the
+ compiler where only a few can already handle OS_128, fixing it
+ properly is out of the question to release 2.2.0 in time. (DM)}
+ if paracgsize=OS_128 then
+ if paralen=8 then
+ paraloc^.size:=OS_64
+ else if paralen=16 then
+ paraloc^.size:=OS_128
+ else
+ internalerror(200707143)
+ else if paracgsize in [OS_F32,OS_F64,OS_F80,OS_F128] then
+ paraloc^.size:=int_float_cgsize(paralen)
+ else
+ paraloc^.size:=int_cgsize(paralen);
+ if side=callerside then
+ paraloc^.reference.index:=NR_STACK_POINTER_REG
+ else
+ paraloc^.reference.index:=NR_FRAME_POINTER_REG;
+ varalign:=used_align(size_2_align(paralen),paraalign,paraalign);
+ paraloc^.reference.offset:=parasize;
+ parasize:=align(parasize+paralen,varalign);
+ paralen:=0;
+ end;
+ else
+ internalerror(2010053113);
+ end;
+ if (locidx<2) and
+ (loc[locidx+1]<>X86_64_NO_CLASS) then
+ inc(locidx);
+ end;
+ end
+ else
+ begin
+ paraloc:=hp.paraloc[side].add_location;
+ paraloc^.loc:=LOC_VOID;
+ end;
+ end;
+ { Register parameters are assigned from left-to-right, but the
+ offsets on the stack are right-to-left. There is no need
+ to reverse the offset, only adapt the calleeside with the
+ start offset of the first param on the stack }
+ if side=calleeside then
+ begin
+ for i:=0 to paras.count-1 do
+ begin
+ hp:=tparavarsym(paras[i]);
+ paraloc:=hp.paraloc[side].location;
+ while paraloc<>nil do
+ begin
+ with paraloc^ do
+ if (loc=LOC_REFERENCE) then
+ inc(reference.offset,target_info.first_parm_offset);
+ paraloc:=paraloc^.next;
+ end;
+ end;
+ end;
+ end;
+
+
+ function tx86_64paramanager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;
+ var
+ intparareg,mmparareg,
+ parasize : longint;
+ begin
+ intparareg:=0;
+ mmparareg:=0;
+ if target_info.system=system_x86_64_win64 then
+ parasize:=4*8
+ else
+ parasize:=0;
+ { calculate the registers for the normal parameters }
+ create_paraloc_info_intern(p,callerside,p.paras,intparareg,mmparareg,parasize,false);
+ { append the varargs }
+ create_paraloc_info_intern(p,callerside,varargspara,intparareg,mmparareg,parasize,true);
+ { store used no. of SSE registers, that needs to be passed in %AL }
+ varargspara.mmregsused:=mmparareg;
+ result:=parasize;
+ end;
+
+
+ function tx86_64paramanager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;
+ var
+ intparareg,mmparareg,
+ parasize : longint;
+ begin
+ intparareg:=0;
+ mmparareg:=0;
+ if target_info.system=system_x86_64_win64 then
+ parasize:=4*8
+ else
+ parasize:=0;
+ create_paraloc_info_intern(p,side,p.paras,intparareg,mmparareg,parasize,false);
+ { Create Function result paraloc }
+ create_funcretloc_info(p,side);
+ { We need to return the size allocated on the stack }
+ result:=parasize;
+ end;
+
+
+begin
+ paramanager:=tx86_64paramanager.create;
+end.
diff --git a/closures/compiler/x86_64/cpupi.pas b/closures/compiler/x86_64/cpupi.pas
new file mode 100644
index 0000000000..b259f9647f
--- /dev/null
+++ b/closures/compiler/x86_64/cpupi.pas
@@ -0,0 +1,166 @@
+{
+ Copyright (c) 2002-2006 by Florian Klaempfl
+
+ This unit contains the CPU specific part of tprocinfo
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+
+{ This unit contains the CPU specific part of tprocinfo. }
+unit cpupi;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ psub,procinfo,aasmbase,aasmdata;
+
+ type
+ tx86_64procinfo = class(tcgprocinfo)
+ private
+ scopes: TAsmList;
+ scopecount: longint;
+ unwindflags: byte;
+ public
+ procedure set_first_temp_offset;override;
+ procedure generate_parameter_info;override;
+ function calc_stackframe_size:longint;override;
+ procedure add_finally_scope(startlabel,endlabel,handler:TAsmSymbol;implicit:Boolean);
+ procedure add_except_scope(trylabel,exceptlabel,endlabel,filter:TAsmSymbol);
+ procedure dump_scopes(list:TAsmList);
+ destructor destroy;override;
+ end;
+
+
+implementation
+
+ uses
+ systems,
+ globtype,
+ globals,
+ cutils,
+ symconst,
+ aasmtai,
+ tgobj;
+
+ const
+ SCOPE_FINALLY=0;
+ SCOPE_CATCHALL=1;
+ SCOPE_IMPLICIT=2;
+
+ procedure tx86_64procinfo.set_first_temp_offset;
+ begin
+ if target_info.system=system_x86_64_win64 then
+ begin
+ { Fixes the case when there are calls done by low-level means
+ (cg.a_call_name) but no child callnode }
+ if (pi_do_call in flags) then
+ allocate_push_parasize(32);
+
+ if not(po_assembler in procdef.procoptions) and
+ (tg.direction > 0) then
+ { maxpushedparasize already contains 32 bytes of spilling area }
+ tg.setfirsttemp(tg.direction*maxpushedparasize);
+ end
+ else
+ tg.setfirsttemp(tg.direction*maxpushedparasize);
+ end;
+
+
+ procedure tx86_64procinfo.generate_parameter_info;
+ begin
+ inherited generate_parameter_info;
+ if target_info.system=system_x86_64_win64 then
+ para_stack_size:=0;
+ end;
+
+
+ function tx86_64procinfo.calc_stackframe_size:longint;
+ begin
+ maxpushedparasize:=align(maxpushedparasize,max(current_settings.alignment.localalignmin,16));
+ { Note 1: when tg.direction>0, tg.lasttemp is already offset by maxpushedparasize
+ (because tg.setfirsttemp also sets lasttemp)
+ Note 2: Align to 8 bytes here. The final 16-byte alignment is handled in
+ tcgx86.g_proc_entry, which considers saved rbp and the misalignment
+ caused by the call itself. }
+ if (tg.direction>0) then
+ result:=Align(tg.lasttemp,8)
+ else
+ result:=Align(tg.direction*tg.lasttemp+maxpushedparasize,8);
+ end;
+
+ procedure tx86_64procinfo.add_finally_scope(startlabel,endlabel,handler:TAsmSymbol;implicit:Boolean);
+ begin
+ unwindflags:=unwindflags or 2;
+ if implicit then { also needs catch functionality }
+ unwindflags:=unwindflags or 1;
+ inc(scopecount);
+ if scopes=nil then
+ scopes:=TAsmList.Create;
+
+ if implicit then
+ scopes.concat(tai_const.create_32bit(SCOPE_IMPLICIT))
+ else
+ scopes.concat(tai_const.create_32bit(SCOPE_FINALLY));
+ scopes.concat(tai_const.create_rva_sym(startlabel));
+ scopes.concat(tai_const.create_rva_sym(endlabel));
+ scopes.concat(tai_const.create_rva_sym(handler));
+ end;
+
+ procedure tx86_64procinfo.add_except_scope(trylabel,exceptlabel,endlabel,filter:TAsmSymbol);
+ begin
+ unwindflags:=unwindflags or 3;
+ inc(scopecount);
+ if scopes=nil then
+ scopes:=TAsmList.Create;
+
+ if Assigned(filter) then
+ scopes.concat(tai_const.create_rva_sym(filter))
+ else
+ scopes.concat(tai_const.create_32bit(SCOPE_CATCHALL));
+ scopes.concat(tai_const.create_rva_sym(trylabel));
+ scopes.concat(tai_const.create_rva_sym(exceptlabel));
+ scopes.concat(tai_const.create_rva_sym(endlabel));
+ end;
+
+ procedure tx86_64procinfo.dump_scopes(list: TAsmList);
+ var
+ hdir: tai_seh_directive;
+ begin
+ if (scopecount=0) then
+ exit;
+ hdir:=cai_seh_directive.create_name(ash_handler,'__FPC_specific_handler');
+ hdir.data.flags:=unwindflags;
+ list.concat(hdir);
+ list.concat(cai_seh_directive.create(ash_handlerdata));
+ list.concat(tai_const.create_32bit(scopecount));
+ list.concatlist(scopes);
+ { return to text, required for GAS compatibility }
+ { This creates a tai_align which is redundant here (although harmless) }
+ new_section(list,sec_code,lower(procdef.mangledname),0);
+ end;
+
+ destructor tx86_64procinfo.destroy;
+ begin
+ scopes.free;
+ inherited destroy;
+ end;
+
+begin
+ cprocinfo:=tx86_64procinfo;
+end.
diff --git a/closures/compiler/x86_64/cputarg.pas b/closures/compiler/x86_64/cputarg.pas
new file mode 100644
index 0000000000..b69184c509
--- /dev/null
+++ b/closures/compiler/x86_64/cputarg.pas
@@ -0,0 +1,94 @@
+{
+ Copyright (c) 2001 by Peter Vreman
+
+ Includes the x86-64 dependent target units
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+{ This unit includes the x86-64 dependent target units. }
+unit cputarg;
+
+{$i fpcdefs.inc}
+
+interface
+
+
+implementation
+
+ uses
+ systems { prevent a syntax error when nothing is included }
+
+{**************************************
+ Targets
+**************************************}
+
+ {$ifndef NOTARGETLINUX}
+ ,t_linux
+ {$endif}
+ {$ifndef NOTARGETFREEBSD}
+ ,t_bsd
+ {$endif}
+ {$ifndef NOTARGETWIN}
+ ,t_win
+ ,win64unw
+ {$endif}
+ {$ifndef NOTARGETSUNOS}
+ ,t_sunos
+ {$endif}
+
+{**************************************
+ Assemblers
+**************************************}
+
+ {$ifndef NOAGX86_64INT}
+ ,agx86int
+ {$endif}
+ {$ifndef NOAGX86_64ATT}
+ ,agx86att
+ {$endif}
+
+ ,ogcoff
+ ,ogelf
+
+{**************************************
+ Assembler Readers
+**************************************}
+
+ {$ifndef NoRax64att}
+ ,rax64att
+ {$endif NoRax64att}
+ {$ifndef NoRax64int}
+ ,rax64int
+ {$endif NoRax64int}
+
+{**************************************
+ Debuginfo
+**************************************}
+
+ {$ifndef NoCFIDwarf}
+ ,cfidwarf
+ {$endif NoCFIDwarf}
+ {$ifndef NoDbgStabs}
+ ,dbgstabs
+ {$endif NoDbgStabs}
+ {$ifndef NoDbgDwarf}
+ ,dbgdwarf
+ {$endif NoDbgDwarf}
+
+ ;
+
+end.
diff --git a/closures/compiler/x86_64/nx64add.pas b/closures/compiler/x86_64/nx64add.pas
new file mode 100644
index 0000000000..2888b7f326
--- /dev/null
+++ b/closures/compiler/x86_64/nx64add.pas
@@ -0,0 +1,126 @@
+{
+ Copyright (c) 2000-2002 by Florian Klaempfl
+
+ Code generation for add nodes on the x86-64
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit nx64add;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,nadd,cpubase,nx86add;
+
+ type
+ tx8664addnode = class(tx86addnode)
+ procedure second_addordinal; override;
+ procedure second_mul;
+ end;
+
+ implementation
+
+ uses
+ globtype,globals,
+ aasmbase,aasmtai,aasmdata,
+ defutil,
+ cgbase,cgutils,cga,cgobj,
+ tgobj;
+
+{*****************************************************************************
+ Addordinal
+*****************************************************************************}
+
+ procedure tx8664addnode.second_addordinal;
+ begin
+ { filter unsigned MUL opcode, which requires special handling }
+ if (nodetype=muln) and
+ (not(is_signed(left.resultdef)) or
+ not(is_signed(right.resultdef))) then
+ begin
+ second_mul;
+ exit;
+ end;
+
+ inherited second_addordinal;
+ end;
+
+{*****************************************************************************
+ MUL
+*****************************************************************************}
+
+ procedure tx8664addnode.second_mul;
+
+ var reg:Tregister;
+ ref:Treference;
+ use_ref:boolean;
+ hl4 : tasmlabel;
+
+ begin
+ pass_left_right;
+
+ { The location.register will be filled in later (JM) }
+ location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
+ { Mul supports registers and references, so if not register/reference,
+ load the location into a register}
+ use_ref:=false;
+ if left.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
+ reg:=left.location.register
+ else if left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE] then
+ begin
+ ref:=left.location.reference;
+ use_ref:=true;
+ end
+ else
+ begin
+ {LOC_CONSTANT for example.}
+ reg:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+ cg.a_load_loc_reg(current_asmdata.CurrAsmList,OS_INT,left.location,reg);
+ end;
+ { Allocate RAX. }
+ cg.getcpuregister(current_asmdata.CurrAsmList,NR_RAX);
+ { Load the right value. }
+ cg.a_load_loc_reg(current_asmdata.CurrAsmList,OS_INT,right.location,NR_RAX);
+ { Also allocate RDX, since it is also modified by a mul (JM). }
+ cg.getcpuregister(current_asmdata.CurrAsmList,NR_RDX);
+ if use_ref then
+ emit_ref(A_MUL,S_Q,ref)
+ else
+ emit_reg(A_MUL,S_Q,reg);
+ if cs_check_overflow in current_settings.localswitches then
+ begin
+ current_asmdata.getjumplabel(hl4);
+ cg.a_jmp_flags(current_asmdata.CurrAsmList,F_AE,hl4);
+ cg.a_call_name(current_asmdata.CurrAsmList,'FPC_OVERFLOW',false);
+ cg.a_label(current_asmdata.CurrAsmList,hl4);
+ end;
+ { Free RDX,RAX }
+ cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_RDX);
+ cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_RAX);
+ { Allocate a new register and store the result in RAX in it. }
+ location.register:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+ emit_reg_reg(A_MOV,S_Q,NR_RAX,location.register);
+ location_freetemp(current_asmdata.CurrAsmList,left.location);
+ location_freetemp(current_asmdata.CurrAsmList,right.location);
+ end;
+
+
+begin
+ caddnode:=tx8664addnode;
+end.
diff --git a/closures/compiler/x86_64/nx64cal.pas b/closures/compiler/x86_64/nx64cal.pas
new file mode 100644
index 0000000000..1217282463
--- /dev/null
+++ b/closures/compiler/x86_64/nx64cal.pas
@@ -0,0 +1,82 @@
+{
+ Copyright (c) 2002 by Florian Klaempfl
+
+ Implements the x86-64 specific part of call nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit nx64cal;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ symdef,
+ ncal,ncgcal;
+
+ type
+ tx8664callnode = class(tcgcallnode)
+ protected
+ procedure extra_call_code;override;
+ procedure set_result_location(realresdef: tstoreddef);override;
+ end;
+
+
+implementation
+
+ uses
+ globtype,
+ systems,
+ cpubase,cgbase,cgutils,cgobj,
+ aasmtai,aasmdata,aasmcpu;
+
+ procedure tx8664callnode.extra_call_code;
+ var
+ mmregs : aint;
+ begin
+ { x86_64 requires %al to contain the no. SSE regs passed }
+ if (cnf_uses_varargs in callnodeflags) and (target_info.system<>system_x86_64_win64) then
+ begin
+ if assigned(varargsparas) then
+ mmregs:=varargsparas.mmregsused
+ else
+ mmregs:=0;
+ current_asmdata.CurrAsmList.concat(taicpu.op_const_reg(A_MOV,S_Q,mmregs,NR_RAX))
+ end;
+ end;
+
+
+ procedure tx8664callnode.set_result_location(realresdef: tstoreddef);
+ begin
+ { avoid useless "movq %xmm0,%rax" and "movq %rax,%xmm0" instructions
+ (which moreover for some reason are not supported by the Darwin
+ x86-64 assembler) }
+ if assigned(retloc.location) and
+ not assigned(retloc.location^.next) and
+ (retloc.location^.loc in [LOC_MMREGISTER,LOC_CMMREGISTER]) then
+ begin
+ location_reset(location,LOC_MMREGISTER,retloc.location^.size);
+ location.register:=cg.getmmregister(current_asmdata.CurrAsmList,retloc.location^.size);
+ end
+ else
+ inherited
+ end;
+
+begin
+ ccallnode:=tx8664callnode;
+end.
diff --git a/closures/compiler/x86_64/nx64cnv.pas b/closures/compiler/x86_64/nx64cnv.pas
new file mode 100644
index 0000000000..e79dcd021e
--- /dev/null
+++ b/closures/compiler/x86_64/nx64cnv.pas
@@ -0,0 +1,175 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate x86-64 assembler for type converting nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit nx64cnv;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,ncgcnv,defutil,defcmp,pass_1,
+ nx86cnv;
+
+ type
+ tx8664typeconvnode = class(tx86typeconvnode)
+ protected
+ { procedure second_int_to_int;override; }
+ { procedure second_string_to_string;override; }
+ { procedure second_cstring_to_pchar;override; }
+ { procedure second_string_to_chararray;override; }
+ { procedure second_array_to_pointer;override; }
+ { procedure second_pointer_to_array;override; }
+ { procedure second_chararray_to_string;override; }
+ { procedure second_char_to_string;override; }
+ { function first_int_to_real: tnode; override; }
+ function first_int_to_real : tnode;override;
+ procedure second_int_to_real;override;
+ { procedure second_real_to_real;override; }
+ { procedure second_cord_to_pointer;override; }
+ { procedure second_proc_to_procvar;override; }
+ { procedure second_bool_to_int;override; }
+ { procedure second_int_to_bool;override; }
+ { procedure second_load_smallset;override; }
+ { procedure second_ansistring_to_pchar;override; }
+ { procedure second_pchar_to_string;override; }
+ { procedure second_class_to_intf;override; }
+ { procedure second_char_to_char;override; }
+ end;
+
+
+implementation
+
+ uses
+ verbose,systems,globals,globtype,
+ aasmbase,aasmtai,aasmdata,aasmcpu,
+ symconst,symdef,
+ cgbase,cga,procinfo,pass_2,
+ ncon,ncal,ncnv,
+ cpubase,
+ cgutils,cgobj,cgx86,ncgutil,
+ tgobj;
+
+
+ function tx8664typeconvnode.first_int_to_real : tnode;
+ begin
+ result:=nil;
+ if use_vectorfpu(resultdef) and
+ (torddef(left.resultdef).ordtype=u32bit) then
+ begin
+ inserttypeconv(left,s64inttype);
+ firstpass(left);
+ end
+ else
+ result:=inherited first_int_to_real;
+ if use_vectorfpu(resultdef) then
+ expectloc:=LOC_MMREGISTER;
+ end;
+
+
+ procedure tx8664typeconvnode.second_int_to_real;
+ var
+ href : treference;
+ l1,l2 : tasmlabel;
+ op : tasmop;
+ begin
+ if use_vectorfpu(resultdef) then
+ begin
+ if is_double(resultdef) then
+ op:=A_CVTSI2SD
+ else if is_single(resultdef) then
+ op:=A_CVTSI2SS
+ else
+ internalerror(200506061);
+
+ location_reset(location,LOC_MMREGISTER,def_cgsize(resultdef));
+ location.register:=cg.getmmregister(current_asmdata.CurrAsmList,location.size);
+
+ case torddef(left.resultdef).ordtype of
+ u64bit:
+ begin
+ { unsigned 64 bit ints are harder to handle:
+ we load bits 0..62 and then check bit 63:
+ if it is 1 then we add $80000000 000000000
+ as double }
+ current_asmdata.getdatalabel(l1);
+ current_asmdata.getjumplabel(l2);
+
+ { Get sign bit }
+ if not(left.location.loc in [LOC_REGISTER,LOC_REFERENCE]) then
+ location_force_reg(current_asmdata.CurrAsmList,left.location,left.location.size,false);
+ case left.location.loc of
+ LOC_REGISTER :
+ begin
+ emit_const_reg(A_BT,S_Q,63,left.location.register);
+ current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op,S_Q,left.location.register,location.register));
+ end;
+ LOC_REFERENCE :
+ begin
+ href:=left.location.reference;
+ tcgx86(cg).make_simple_ref(current_asmdata.CurrAsmList,href);
+ inc(href.offset,4);
+ emit_const_ref(A_BT,S_L,31,href);
+ dec(href.offset,4);
+ current_asmdata.CurrAsmList.concat(taicpu.op_ref_reg(op,S_Q,href,location.register));
+ end;
+ else
+ internalerror(200710181);
+ end;
+
+ cg.a_jmp_flags(current_asmdata.CurrAsmList,F_NC,l2);
+ new_section(current_asmdata.asmlists[al_typedconsts],sec_rodata_norel,l1.name,const_align(sizeof(pint)));
+ current_asmdata.asmlists[al_typedconsts].concat(Tai_label.Create(l1));
+ reference_reset_symbol(href,l1,0,4);
+ { simplify for PIC }
+ tcgx86(cg).make_simple_ref(current_asmdata.CurrAsmList,href);
+
+ { I got these constant from a test program (FK) }
+ if is_double(resultdef) then
+ begin
+ { double (2^64) }
+ current_asmdata.asmlists[al_typedconsts].concat(Tai_const.Create_32bit(0));
+ current_asmdata.asmlists[al_typedconsts].concat(Tai_const.Create_32bit($43f00000));
+ tcgx86(cg).make_simple_ref(current_asmdata.CurrAsmList,href);
+ current_asmdata.CurrAsmList.concat(taicpu.op_ref_reg(A_ADDSD,S_NO,href,location.register));
+ end
+ else if is_single(resultdef) then
+ begin
+ { single(2^64) }
+ current_asmdata.asmlists[al_typedconsts].concat(Tai_const.Create_32bit($5f800000));
+ current_asmdata.CurrAsmList.concat(taicpu.op_ref_reg(A_ADDSS,S_NO,href,location.register));
+ end
+ else
+ internalerror(200506071);
+ cg.a_label(current_asmdata.CurrAsmList,l2);
+ end
+ else
+ inherited second_int_to_real;
+ end;
+ end
+ else
+ inherited second_int_to_real;
+ end;
+
+
+begin
+ ctypeconvnode:=tx8664typeconvnode;
+end.
diff --git a/closures/compiler/x86_64/nx64flw.pas b/closures/compiler/x86_64/nx64flw.pas
new file mode 100644
index 0000000000..15be927383
--- /dev/null
+++ b/closures/compiler/x86_64/nx64flw.pas
@@ -0,0 +1,559 @@
+{
+ Copyright (c) 2011 by Free Pascal development team
+
+ Generate Win64-specific exception handling code
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit nx64flw;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,nflw,ncgflw,psub;
+
+ type
+ tx64raisenode=class(tcgraisenode)
+ procedure pass_generate_code;override;
+ end;
+
+ tx64onnode=class(tcgonnode)
+ procedure pass_generate_code;override;
+ end;
+
+ tx64tryexceptnode=class(tcgtryexceptnode)
+ procedure pass_generate_code;override;
+ end;
+
+ tx64tryfinallynode=class(tcgtryfinallynode)
+ finalizepi: tcgprocinfo;
+ constructor create(l,r:TNode);override;
+ constructor create_implicit(l,r,_t1:TNode);override;
+ function simplify(forinline: boolean): tnode;override;
+ procedure pass_generate_code;override;
+ end;
+
+implementation
+
+ uses
+ cutils,globtype,globals,verbose,systems,
+ nbas,ncal,nmem,nutils,
+ symconst,symbase,symtable,symsym,symdef,
+ cgbase,cgobj,cgcpu,cgutils,tgobj,
+ cpubase,htypechk,
+ parabase,paramgr,pdecsub,pass_1,pass_2,ncgutil,cga,
+ aasmbase,aasmtai,aasmdata,aasmcpu,procinfo,cpupi;
+
+ var
+ endexceptlabel: tasmlabel;
+
+
+{ tx64raisenode }
+
+procedure tx64raisenode.pass_generate_code;
+ begin
+ { difference from generic code is that address stack is not popped on reraise }
+ if (target_info.system<>system_x86_64_win64) or assigned(left) then
+ inherited pass_generate_code
+ else
+ cg.g_call(current_asmdata.CurrAsmList,'FPC_RERAISE');
+ end;
+
+{ tx64onnode }
+
+procedure tx64onnode.pass_generate_code;
+ var
+ oldflowcontrol : tflowcontrol;
+ exceptvarsym : tlocalvarsym;
+ begin
+ if (target_info.system<>system_x86_64_win64) then
+ begin
+ inherited pass_generate_code;
+ exit;
+ end;
+
+ location_reset(location,LOC_VOID,OS_NO);
+
+ oldflowcontrol:=flowcontrol;
+ flowcontrol:=[fc_inflowcontrol];
+
+ { RTL will put exceptobject into RAX when jumping here }
+ cg.a_reg_alloc(current_asmdata.CurrAsmList,NR_FUNCTION_RESULT_REG);
+
+ { Retrieve exception variable }
+ if assigned(excepTSymtable) then
+ exceptvarsym:=tlocalvarsym(excepTSymtable.SymList[0])
+ else
+ exceptvarsym:=nil;
+
+ if assigned(exceptvarsym) then
+ begin
+ exceptvarsym.localloc.loc:=LOC_REFERENCE;
+ exceptvarsym.localloc.size:=OS_ADDR;
+ tg.GetLocal(current_asmdata.CurrAsmList,sizeof(pint),voidpointertype,exceptvarsym.localloc.reference);
+ cg.a_load_reg_ref(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,NR_FUNCTION_RESULT_REG,exceptvarsym.localloc.reference);
+ end;
+ cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_FUNCTION_RESULT_REG);
+
+ if assigned(right) then
+ secondpass(right);
+
+ { deallocate exception symbol }
+ if assigned(exceptvarsym) then
+ begin
+ tg.UngetLocal(current_asmdata.CurrAsmList,exceptvarsym.localloc.reference);
+ exceptvarsym.localloc.loc:=LOC_INVALID;
+ end;
+ cg.g_call(current_asmdata.CurrAsmList,'FPC_DONEEXCEPTION');
+ cg.a_jmp_always(current_asmdata.CurrAsmList,endexceptlabel);
+
+ flowcontrol:=oldflowcontrol+(flowcontrol-[fc_inflowcontrol]);
+ end;
+
+{ tx64tryfinallynode }
+var
+ seq: longint=0;
+
+
+function create_pd: tprocdef;
+ var
+ st:TSymTable;
+ checkstack: psymtablestackitem;
+ sym:tprocsym;
+ begin
+ { get actual procedure symtable (skip withsymtables, etc.) }
+ st:=nil;
+ checkstack:=symtablestack.stack;
+ while assigned(checkstack) do
+ begin
+ st:=checkstack^.symtable;
+ if st.symtabletype in [staticsymtable,globalsymtable,localsymtable] then
+ break;
+ checkstack:=checkstack^.next;
+ end;
+ { Create a nested procedure, even from main_program_level. }
+ result:=tprocdef.create(max(normal_function_level,st.symtablelevel)+1);
+ result.struct:=current_procinfo.procdef.struct;
+ result.proctypeoption:=potype_exceptfilter;
+ handle_calling_convention(result);
+ sym:=tprocsym.create('$fin$'+tostr(seq));
+ st.insert(sym);
+ inc(seq);
+
+ result.procsym:=sym;
+ proc_add_definition(result);
+ result.forwarddef:=false;
+ result.aliasnames.insert(result.mangledname);
+ alloc_proc_symbol(result);
+ end;
+
+function reset_regvars(var n: tnode; arg: pointer): foreachnoderesult;
+ begin
+ case n.nodetype of
+ temprefn:
+ make_not_regable(n,[]);
+ calln:
+ include(tprocinfo(arg).flags,pi_do_call);
+ end;
+ result:=fen_true;
+ end;
+
+function copy_parasize(var n: tnode; arg: pointer): foreachnoderesult;
+ begin
+ case n.nodetype of
+ calln:
+ tcgprocinfo(arg).allocate_push_parasize(tcallnode(n).pushed_parasize);
+ end;
+ result:=fen_true;
+ end;
+
+constructor tx64tryfinallynode.create(l, r: TNode);
+ begin
+ inherited create(l,r);
+ if (target_info.system<>system_x86_64_win64) then
+ exit;
+ finalizepi:=tcgprocinfo(cprocinfo.create(current_procinfo));
+ finalizepi.force_nested;
+ finalizepi.procdef:=create_pd;
+ finalizepi.entrypos:=r.fileinfo;
+ finalizepi.entryswitches:=r.localswitches;
+ finalizepi.exitpos:=current_filepos; // last_endtoken_pos?
+ finalizepi.exitswitches:=current_settings.localswitches;
+ { Regvar optimization for symbols is suppressed when using exceptions, but
+ temps may be still placed into registers. This must be fixed. }
+ foreachnodestatic(r,@reset_regvars,finalizepi);
+ end;
+
+constructor tx64tryfinallynode.create_implicit(l, r, _t1: TNode);
+ begin
+ inherited create_implicit(l, r, _t1);
+ if (target_info.system<>system_x86_64_win64) then
+ exit;
+ finalizepi:=tcgprocinfo(cprocinfo.create(current_procinfo));
+ finalizepi.force_nested;
+ finalizepi.procdef:=create_pd;
+
+ finalizepi.entrypos:=current_filepos;
+ finalizepi.exitpos:=current_filepos; // last_endtoken_pos?
+ finalizepi.entryswitches:=r.localswitches;
+ finalizepi.exitswitches:=current_settings.localswitches;
+ include(finalizepi.flags,pi_do_call);
+ finalizepi.allocate_push_parasize(32);
+ end;
+
+function tx64tryfinallynode.simplify(forinline: boolean): tnode;
+ begin
+ result:=inherited simplify(forinline);
+ if (target_info.system<>system_x86_64_win64) then
+ exit;
+ if (result=nil) then
+ begin
+ finalizepi.code:=right;
+ foreachnodestatic(right,@copy_parasize,finalizepi);
+ right:=ccallnode.create(nil,tprocsym(finalizepi.procdef.procsym),nil,nil,[]);
+ firstpass(right);
+ { For implicit frames, no actual code is available at this time,
+ it is added later in assembler form. So store the nested procinfo
+ for later use. }
+ if implicitframe then
+ begin
+ current_procinfo.finalize_procinfo:=finalizepi;
+ { don't leave dangling pointer }
+ tcgprocinfo(current_procinfo).final_asmnode:=nil;
+ end;
+ end;
+ end;
+
+procedure emit_nop;
+ var
+ dummy: TAsmLabel;
+ begin
+ { To avoid optimizing away the whole thing, prepend a jumplabel with increased refcount }
+ current_asmdata.getjumplabel(dummy);
+ dummy.increfs;
+ cg.a_label(current_asmdata.CurrAsmList,dummy);
+ current_asmdata.CurrAsmList.concat(Taicpu.op_none(A_NOP,S_NO));
+ end;
+
+procedure tx64tryfinallynode.pass_generate_code;
+ var
+ trylabel,
+ endtrylabel,
+ finallylabel,
+ endfinallylabel,
+ oldexitlabel: tasmlabel;
+ oldflowcontrol: tflowcontrol;
+ catch_frame: boolean;
+ begin
+ if (target_info.system<>system_x86_64_win64) then
+ begin
+ inherited pass_generate_code;
+ exit;
+ end;
+
+ location_reset(location,LOC_VOID,OS_NO);
+
+ { Do not generate a frame that catches exceptions if the only action
+ would be reraising it. Doing so is extremely inefficient with SEH
+ (in contrast with setjmp/longjmp exception handling) }
+ catch_frame:=implicitframe and ((not has_no_code(t1)) or
+ (current_procinfo.procdef.proccalloption=pocall_safecall));
+
+ oldflowcontrol:=flowcontrol;
+ flowcontrol:=[fc_inflowcontrol];
+
+ current_asmdata.getjumplabel(trylabel);
+ current_asmdata.getjumplabel(endtrylabel);
+ current_asmdata.getjumplabel(finallylabel);
+ current_asmdata.getjumplabel(endfinallylabel);
+ oldexitlabel:=current_procinfo.CurrExitLabel;
+ if implicitframe then
+ current_procinfo.CurrExitLabel:=finallylabel;
+
+ { Start of scope }
+ { Padding with NOP is necessary here because exceptions in called
+ procedures are seen at the next instruction, while CPU/OS exceptions
+ like AV are seen at the current instruction.
+
+ So in the following code
+
+ raise_some_exception; //(a)
+ try
+ pchar(nil)^:='0'; //(b)
+ ...
+
+ without NOP, exceptions (a) and (b) will be seen at the same address
+ and fall into the same scope. However they should be seen in different scopes.
+ }
+
+ emit_nop;
+ cg.a_label(current_asmdata.CurrAsmList,trylabel);
+
+ { try code }
+ if assigned(left) then
+ begin
+ { fc_unwind tells exit/continue/break statements to emit special
+ unwind code instead of just JMP }
+ if not implicitframe then
+ include(flowcontrol,fc_unwind);
+ secondpass(left);
+ exclude(flowcontrol,fc_unwind);
+ if codegenerror then
+ exit;
+ end;
+
+ { If the immediately preceding instruction is CALL,
+ its return address must not end up outside the scope, so pad with NOP. }
+ if catch_frame then
+ cg.a_jmp_always(current_asmdata.CurrAsmList,finallylabel)
+ else
+ emit_nop;
+
+ cg.a_label(current_asmdata.CurrAsmList,endtrylabel);
+
+ { Handle the except block first, so endtrylabel serves both
+ as end of scope and as unwind target. This way it is possible to
+ encode everything into a single scope record. }
+ if catch_frame then
+ begin
+ flowcontrol:=[fc_inflowcontrol];
+ secondpass(t1);
+ { note 1: this is not a 'finally' block, no flow restrictions apply
+ note 2: it contains autogenerated sequential code, flow away is impossible }
+ if flowcontrol<>[fc_inflowcontrol] then
+ CGMessage(cg_e_control_flow_outside_finally);
+ if codegenerror then
+ exit;
+
+ if (current_procinfo.procdef.proccalloption=pocall_safecall) then
+ begin
+ handle_safecall_exception;
+ cg.a_jmp_always(current_asmdata.CurrAsmList,endfinallylabel);
+ end
+ else
+ cg.a_call_name(current_asmdata.CurrAsmList,'FPC_RERAISE_IMPLICIT',false);
+ end;
+
+ flowcontrol:=[fc_inflowcontrol];
+ cg.a_label(current_asmdata.CurrAsmList,finallylabel);
+ { generate finally code as a separate procedure }
+ if not implicitframe then
+ tcgprocinfo(current_procinfo).generate_exceptfilter(finalizepi);
+ { right is a call to finalizer procedure }
+ secondpass(right);
+
+ if codegenerror then
+ exit;
+
+ { normal exit from safecall proc must zero the result register }
+ if implicitframe and (current_procinfo.procdef.proccalloption=pocall_safecall) then
+ cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_INT,0,NR_FUNCTION_RESULT_REG);
+
+ cg.a_label(current_asmdata.CurrAsmList,endfinallylabel);
+
+ { generate the scope record in .xdata }
+ tx86_64procinfo(current_procinfo).add_finally_scope(trylabel,endtrylabel,
+ current_asmdata.RefAsmSymbol(finalizepi.procdef.mangledname),catch_frame);
+
+ if implicitframe then
+ current_procinfo.CurrExitLabel:=oldexitlabel;
+ flowcontrol:=oldflowcontrol;
+ end;
+
+{ tx64tryexceptnode }
+
+procedure tx64tryexceptnode.pass_generate_code;
+ var
+ trylabel,
+ exceptlabel,oldendexceptlabel,
+ lastonlabel,
+ exitexceptlabel,
+ continueexceptlabel,
+ breakexceptlabel,
+ oldCurrExitLabel,
+ oldContinueLabel,
+ oldBreakLabel : tasmlabel;
+ onlabel,
+ filterlabel: tasmlabel;
+ oldflowcontrol,tryflowcontrol,
+ exceptflowcontrol : tflowcontrol;
+ hnode : tnode;
+ hlist : tasmlist;
+ onnodecount : tai_const;
+ label
+ errorexit;
+ begin
+ if (target_info.system<>system_x86_64_win64) then
+ begin
+ inherited pass_generate_code;
+ exit;
+ end;
+ location_reset(location,LOC_VOID,OS_NO);
+
+ oldflowcontrol:=flowcontrol;
+ flowcontrol:=[fc_inflowcontrol];
+ { this can be called recursivly }
+ oldBreakLabel:=nil;
+ oldContinueLabel:=nil;
+ oldendexceptlabel:=endexceptlabel;
+
+ { save the old labels for control flow statements }
+ oldCurrExitLabel:=current_procinfo.CurrExitLabel;
+ current_asmdata.getjumplabel(exitexceptlabel);
+ if assigned(current_procinfo.CurrBreakLabel) then
+ begin
+ oldContinueLabel:=current_procinfo.CurrContinueLabel;
+ oldBreakLabel:=current_procinfo.CurrBreakLabel;
+ current_asmdata.getjumplabel(breakexceptlabel);
+ current_asmdata.getjumplabel(continueexceptlabel);
+ end;
+
+ current_asmdata.getjumplabel(exceptlabel);
+ current_asmdata.getjumplabel(endexceptlabel);
+ current_asmdata.getjumplabel(lastonlabel);
+ filterlabel:=nil;
+
+ { start of scope }
+ current_asmdata.getjumplabel(trylabel);
+ emit_nop;
+ cg.a_label(current_asmdata.CurrAsmList,trylabel);
+
+ { control flow in try block needs no special handling,
+ just make sure that target labels are outside the scope }
+ secondpass(left);
+ tryflowcontrol:=flowcontrol;
+ if codegenerror then
+ goto errorexit;
+
+ { jump over except handlers }
+ cg.a_jmp_always(current_asmdata.CurrAsmList,endexceptlabel);
+
+ { end of scope }
+ cg.a_label(current_asmdata.CurrAsmList,exceptlabel);
+
+ { set control flow labels for the except block }
+ { and the on statements }
+ current_procinfo.CurrExitLabel:=exitexceptlabel;
+ if assigned(oldBreakLabel) then
+ begin
+ current_procinfo.CurrContinueLabel:=continueexceptlabel;
+ current_procinfo.CurrBreakLabel:=breakexceptlabel;
+ end;
+
+ flowcontrol:=[fc_inflowcontrol];
+ { on statements }
+ if assigned(right) then
+ begin
+ { emit filter table to a temporary asmlist }
+ hlist:=TAsmList.Create;
+ current_asmdata.getdatalabel(filterlabel);
+ new_section(hlist,sec_rodata_norel,filterlabel.name,4);
+ cg.a_label(hlist,filterlabel);
+ onnodecount:=tai_const.create_32bit(0);
+ hlist.concat(onnodecount);
+
+ hnode:=right;
+ while assigned(hnode) do
+ begin
+ if hnode.nodetype<>onn then
+ InternalError(2011103101);
+ { TODO: make it done without using global label }
+ current_asmdata.getglobaljumplabel(onlabel);
+ hlist.concat(tai_const.create_rva_sym(current_asmdata.RefAsmSymbol(tonnode(hnode).excepttype.vmt_mangledname)));
+ hlist.concat(tai_const.create_rva_sym(onlabel));
+ cg.a_label(current_asmdata.CurrAsmList,onlabel);
+ secondpass(hnode);
+ inc(onnodecount.value);
+ hnode:=tonnode(hnode).left;
+ end;
+ { add 'else' node to the filter list, too }
+ if assigned(t1) then
+ begin
+ hlist.concat(tai_const.create_32bit(-1));
+ hlist.concat(tai_const.create_rva_sym(lastonlabel));
+ inc(onnodecount.value);
+ end;
+ { now move filter table to permanent list all at once }
+ maybe_new_object_file(current_asmdata.asmlists[al_typedconsts]);
+ current_asmdata.asmlists[al_typedconsts].concatlist(hlist);
+ hlist.free;
+ end;
+
+ cg.a_label(current_asmdata.CurrAsmList,lastonlabel);
+ if assigned(t1) then
+ begin
+ { here we don't have to reset flowcontrol }
+ { the default and on flowcontrols are handled equal }
+ secondpass(t1);
+ cg.g_call(current_asmdata.CurrAsmList,'FPC_DONEEXCEPTION');
+ if (flowcontrol*[fc_exit,fc_break,fc_continue]<>[]) then
+ cg.a_jmp_always(current_asmdata.CurrAsmList,endexceptlabel);
+ end;
+ exceptflowcontrol:=flowcontrol;
+
+ if fc_exit in exceptflowcontrol then
+ begin
+ { do some magic for exit in the try block }
+ cg.a_label(current_asmdata.CurrAsmList,exitexceptlabel);
+ cg.g_call(current_asmdata.CurrAsmList,'FPC_DONEEXCEPTION');
+ cg.a_jmp_always(current_asmdata.CurrAsmList,oldCurrExitLabel);
+ end;
+
+ if fc_break in exceptflowcontrol then
+ begin
+ cg.a_label(current_asmdata.CurrAsmList,breakexceptlabel);
+ cg.g_call(current_asmdata.CurrAsmList,'FPC_DONEEXCEPTION');
+ cg.a_jmp_always(current_asmdata.CurrAsmList,oldBreakLabel);
+ end;
+
+ if fc_continue in exceptflowcontrol then
+ begin
+ cg.a_label(current_asmdata.CurrAsmList,continueexceptlabel);
+ cg.g_call(current_asmdata.CurrAsmList,'FPC_DONEEXCEPTION');
+ cg.a_jmp_always(current_asmdata.CurrAsmList,oldContinueLabel);
+ end;
+
+ emit_nop;
+ cg.a_label(current_asmdata.CurrAsmList,endexceptlabel);
+ tx86_64procinfo(current_procinfo).add_except_scope(trylabel,exceptlabel,endexceptlabel,filterlabel);
+
+errorexit:
+ { restore all saved labels }
+ endexceptlabel:=oldendexceptlabel;
+
+ { restore the control flow labels }
+ current_procinfo.CurrExitLabel:=oldCurrExitLabel;
+ if assigned(oldBreakLabel) then
+ begin
+ current_procinfo.CurrContinueLabel:=oldContinueLabel;
+ current_procinfo.CurrBreakLabel:=oldBreakLabel;
+ end;
+
+ { return all used control flow statements }
+ flowcontrol:=oldflowcontrol+(exceptflowcontrol +
+ tryflowcontrol - [fc_inflowcontrol]);
+ end;
+
+initialization
+ craisenode:=tx64raisenode;
+ connode:=tx64onnode;
+ ctryexceptnode:=tx64tryexceptnode;
+ ctryfinallynode:=tx64tryfinallynode;
+end.
+
diff --git a/closures/compiler/x86_64/nx64inl.pas b/closures/compiler/x86_64/nx64inl.pas
new file mode 100644
index 0000000000..2c322f897c
--- /dev/null
+++ b/closures/compiler/x86_64/nx64inl.pas
@@ -0,0 +1,42 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate x86-64 inline nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit nx64inl;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ nx86inl;
+
+ type
+ tx8664inlinenode = class(tx86inlinenode)
+ end;
+
+implementation
+
+ uses
+ ninl;
+
+begin
+ cinlinenode:=tx8664inlinenode;
+end.
diff --git a/closures/compiler/x86_64/nx64mat.pas b/closures/compiler/x86_64/nx64mat.pas
new file mode 100644
index 0000000000..3085872c88
--- /dev/null
+++ b/closures/compiler/x86_64/nx64mat.pas
@@ -0,0 +1,213 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ Generate x86-64 assembler for math nodes
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit nx64mat;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ node,nmat,ncgmat,nx86mat;
+
+ type
+ tx8664moddivnode = class(tmoddivnode)
+ procedure pass_generate_code;override;
+ end;
+
+ tx8664shlshrnode = class(tshlshrnode)
+ procedure pass_generate_code;override;
+ end;
+
+ tx8664unaryminusnode = class(tx86unaryminusnode)
+ end;
+
+ tx8664notnode = class(tx86notnode)
+ end;
+
+implementation
+
+ uses
+ globtype,systems,constexp,
+ cutils,verbose,globals,
+ symconst,symdef,aasmbase,aasmtai,aasmdata,defutil,
+ pass_1,pass_2,
+ ncon,
+ cpubase,cpuinfo,
+ cgbase,cgutils,cga,cgobj,cgx86,
+ ncgutil;
+
+{*****************************************************************************
+ TX8664MODDIVNODE
+*****************************************************************************}
+
+ procedure tx8664moddivnode.pass_generate_code;
+ var
+ hreg1,hreg2:Tregister;
+ power:longint;
+ op:Tasmop;
+ begin
+ secondpass(left);
+ if codegenerror then
+ exit;
+ secondpass(right);
+ if codegenerror then
+ exit;
+
+ { put numerator in register }
+ location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
+ location_force_reg(current_asmdata.CurrAsmList,left.location,location.size,false);
+ hreg1:=left.location.register;
+
+ if (nodetype=divn) and (right.nodetype=ordconstn) and
+ ispowerof2(int64(tordconstnode(right).value),power) then
+ begin
+ { for signed numbers, the numerator must be adjusted before the
+ shift instruction, but not wih unsigned numbers! Otherwise,
+ "Cardinal($ffffffff) div 16" overflows! (JM) }
+ if is_signed(left.resultdef) Then
+ begin
+ { use a sequence without jumps, saw this in
+ comp.compilers (JM) }
+ { no jumps, but more operations }
+ hreg2:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+ emit_reg_reg(A_MOV,S_Q,hreg1,hreg2);
+ {If the left value is signed, hreg2=$ffffffff, otherwise 0.}
+ emit_const_reg(A_SAR,S_Q,63,hreg2);
+ {If signed, hreg2=right value-1, otherwise 0.}
+ { (don't use emit_const_reg, because if value>high(longint)
+ then it must first be loaded into a register) }
+ cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_AND,OS_S64,tordconstnode(right).value-1,hreg2);
+ { add to the left value }
+ emit_reg_reg(A_ADD,S_Q,hreg2,hreg1);
+ { do the shift }
+ emit_const_reg(A_SAR,S_Q,power,hreg1);
+ end
+ else
+ emit_const_reg(A_SHR,S_Q,power,hreg1);
+ location.register:=hreg1;
+ end
+ else
+ begin
+ {Bring denominator to a register.}
+ cg.getcpuregister(current_asmdata.CurrAsmList,NR_RAX);
+ emit_reg_reg(A_MOV,S_Q,hreg1,NR_RAX);
+ cg.getcpuregister(current_asmdata.CurrAsmList,NR_RDX);
+ {Sign extension depends on the left type.}
+ if torddef(left.resultdef).ordtype=u64bit then
+ emit_reg_reg(A_XOR,S_Q,NR_RDX,NR_RDX)
+ else
+ emit_none(A_CQO,S_NO);
+
+ {Division depends on the right type.}
+ if Torddef(right.resultdef).ordtype=u64bit then
+ op:=A_DIV
+ else
+ op:=A_IDIV;
+
+ if right.location.loc in [LOC_REFERENCE,LOC_CREFERENCE] then
+ emit_ref(op,S_Q,right.location.reference)
+ else if right.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
+ emit_reg(op,S_Q,right.location.register)
+ else
+ begin
+ hreg1:=cg.getintregister(current_asmdata.CurrAsmList,right.location.size);
+ cg.a_load_loc_reg(current_asmdata.CurrAsmList,OS_64,right.location,hreg1);
+ emit_reg(op,S_Q,hreg1);
+ end;
+
+ { Copy the result into a new register. Release RAX & RDX.}
+ cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_RDX);
+ cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_RAX);
+ location.register:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
+ if nodetype=divn then
+ cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_INT,OS_INT,NR_RAX,location.register)
+ else
+ cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_INT,OS_INT,NR_RDX,location.register);
+ end;
+ end;
+
+
+{*****************************************************************************
+ TX8664SHLRSHRNODE
+*****************************************************************************}
+
+
+ procedure tx8664shlshrnode.pass_generate_code;
+ var
+ op : Tasmop;
+ opsize : tcgsize;
+ mask : aint;
+ begin
+ secondpass(left);
+ secondpass(right);
+
+ { determine operator }
+ if nodetype=shln then
+ op:=A_SHL
+ else
+ op:=A_SHR;
+
+ { special treatment of 32bit values for backwards compatibility }
+ { mul optimizations require to keep the sign (FK) }
+ if left.resultdef.size<=4 then
+ begin
+ if is_signed(left.resultdef) then
+ opsize:=OS_S32
+ else
+ opsize:=OS_32;
+ mask:=31;
+ end
+ else
+ begin
+ if is_signed(left.resultdef) then
+ opsize:=OS_S64
+ else
+ opsize:=OS_64;
+ mask:=63;
+ end;
+
+ { load left operators in a register }
+ location_copy(location,left.location);
+ location_force_reg(current_asmdata.CurrAsmList,location,opsize,false);
+
+ { shifting by a constant directly coded: }
+ if (right.nodetype=ordconstn) then
+ emit_const_reg(op,tcgsize2opsize[opsize],tordconstnode(right).value and mask,location.register)
+ else
+ begin
+ { load right operators in a RCX }
+ cg.getcpuregister(current_asmdata.CurrAsmList,NR_RCX);
+ cg.a_load_loc_reg(current_asmdata.CurrAsmList,OS_INT,right.location,NR_RCX);
+
+ { right operand is in ECX }
+ cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_RCX);
+ emit_reg_reg(op,tcgsize2opsize[opsize],NR_CL,location.register);
+ end;
+ end;
+
+
+begin
+ cunaryminusnode:=tx8664unaryminusnode;
+ cmoddivnode:=tx8664moddivnode;
+ cshlshrnode:=tx8664shlshrnode;
+ cnotnode:=tx8664notnode;
+end.
diff --git a/closures/compiler/x86_64/r8664ari.inc b/closures/compiler/x86_64/r8664ari.inc
new file mode 100644
index 0000000000..bdce69ce50
--- /dev/null
+++ b/closures/compiler/x86_64/r8664ari.inc
@@ -0,0 +1,126 @@
+{ don't edit, this file is generated from x86reg.dat }
+2,
+1,
+3,
+17,
+16,
+30,
+29,
+18,
+7,
+6,
+83,
+84,
+85,
+86,
+71,
+8,
+12,
+26,
+25,
+11,
+77,
+78,
+79,
+80,
+81,
+82,
+72,
+13,
+4,
+31,
+19,
+9,
+27,
+14,
+70,
+73,
+23,
+35,
+75,
+76,
+101,
+102,
+103,
+104,
+105,
+106,
+107,
+108,
+45,
+46,
+48,
+47,
+49,
+50,
+52,
+51,
+53,
+54,
+56,
+55,
+57,
+58,
+60,
+59,
+61,
+62,
+64,
+63,
+65,
+66,
+68,
+67,
+37,
+38,
+40,
+39,
+41,
+42,
+44,
+43,
+5,
+32,
+20,
+10,
+28,
+15,
+69,
+24,
+36,
+22,
+21,
+34,
+33,
+74,
+100,
+92,
+93,
+94,
+95,
+96,
+97,
+98,
+99,
+87,
+88,
+89,
+90,
+91,
+109,
+110,
+119,
+120,
+121,
+122,
+123,
+124,
+111,
+112,
+113,
+114,
+115,
+116,
+117,
+118,
+0
diff --git a/closures/compiler/x86_64/r8664att.inc b/closures/compiler/x86_64/r8664att.inc
new file mode 100644
index 0000000000..f9539b56f8
--- /dev/null
+++ b/closures/compiler/x86_64/r8664att.inc
@@ -0,0 +1,126 @@
+{ don't edit, this file is generated from x86reg.dat }
+'INVALID',
+'%al',
+'%ah',
+'%ax',
+'%eax',
+'%rax',
+'%cl',
+'%ch',
+'%cx',
+'%ecx',
+'%rcx',
+'%dl',
+'%dh',
+'%dx',
+'%edx',
+'%rdx',
+'%bl',
+'%bh',
+'%bx',
+'%ebx',
+'%rbx',
+'%sil',
+'%si',
+'%esi',
+'%rsi',
+'%dil',
+'%di',
+'%edi',
+'%rdi',
+'%bpl',
+'%bp',
+'%ebp',
+'%rbp',
+'%spl',
+'%sp',
+'%esp',
+'%rsp',
+'%r8',
+'%r8b',
+'%r8w',
+'%r8d',
+'%r9',
+'%r9b',
+'%r9w',
+'%r9d',
+'%r10',
+'%r10b',
+'%r10w',
+'%r10d',
+'%r11',
+'%r11b',
+'%r11w',
+'%r11d',
+'%r12',
+'%r12b',
+'%r12w',
+'%r12d',
+'%r13',
+'%r13b',
+'%r13w',
+'%r13d',
+'%r14',
+'%r14b',
+'%r14w',
+'%r14d',
+'%r15',
+'%r15b',
+'%r15w',
+'%r15d',
+'%rip',
+'%eip',
+'%cs',
+'%ds',
+'%es',
+'%ss',
+'%fs',
+'%gs',
+'%dr0',
+'%dr1',
+'%dr2',
+'%dr3',
+'%dr6',
+'%dr7',
+'%cr0',
+'%cr2',
+'%cr3',
+'%cr4',
+'%tr3',
+'%tr4',
+'%tr5',
+'%tr6',
+'%tr7',
+'%st(0)',
+'%st(1)',
+'%st(2)',
+'%st(3)',
+'%st(4)',
+'%st(5)',
+'%st(6)',
+'%st(7)',
+'%st',
+'%mm0',
+'%mm1',
+'%mm2',
+'%mm3',
+'%mm4',
+'%mm5',
+'%mm6',
+'%mm7',
+'%xmm0',
+'%xmm1',
+'%xmm2',
+'%xmm3',
+'%xmm4',
+'%xmm5',
+'%xmm6',
+'%xmm7',
+'%xmm8',
+'%xmm9',
+'%xmm10',
+'%xmm11',
+'%xmm12',
+'%xmm13',
+'%xmm14',
+'%xmm15'
diff --git a/closures/compiler/x86_64/r8664con.inc b/closures/compiler/x86_64/r8664con.inc
new file mode 100644
index 0000000000..ae6a0d28e3
--- /dev/null
+++ b/closures/compiler/x86_64/r8664con.inc
@@ -0,0 +1,126 @@
+{ don't edit, this file is generated from x86reg.dat }
+NR_NO = tregister($00000000);
+NR_AL = tregister($01010000);
+NR_AH = tregister($01020000);
+NR_AX = tregister($01030000);
+NR_EAX = tregister($01040000);
+NR_RAX = tregister($01050000);
+NR_CL = tregister($01010001);
+NR_CH = tregister($01020001);
+NR_CX = tregister($01030001);
+NR_ECX = tregister($01040001);
+NR_RCX = tregister($01050001);
+NR_DL = tregister($01010002);
+NR_DH = tregister($01020002);
+NR_DX = tregister($01030002);
+NR_EDX = tregister($01040002);
+NR_RDX = tregister($01050002);
+NR_BL = tregister($01010003);
+NR_BH = tregister($01020003);
+NR_BX = tregister($01030003);
+NR_EBX = tregister($01040003);
+NR_RBX = tregister($01050003);
+NR_SIL = tregister($01010004);
+NR_SI = tregister($01030004);
+NR_ESI = tregister($01040004);
+NR_RSI = tregister($01050004);
+NR_DIL = tregister($01010005);
+NR_DI = tregister($01030005);
+NR_EDI = tregister($01040005);
+NR_RDI = tregister($01050005);
+NR_BPL = tregister($01010006);
+NR_BP = tregister($01030006);
+NR_EBP = tregister($01040006);
+NR_RBP = tregister($01050006);
+NR_SPL = tregister($01010007);
+NR_SP = tregister($01030007);
+NR_ESP = tregister($01040007);
+NR_RSP = tregister($01050007);
+NR_R8 = tregister($01050008);
+NR_R8L = tregister($01010008);
+NR_R8W = tregister($01030008);
+NR_R8D = tregister($01040008);
+NR_R9 = tregister($01050009);
+NR_R9L = tregister($01010009);
+NR_R9W = tregister($01030009);
+NR_R9D = tregister($01040009);
+NR_R10 = tregister($0105000a);
+NR_R10L = tregister($0101000a);
+NR_R10W = tregister($0103000a);
+NR_R10D = tregister($0104000a);
+NR_R11 = tregister($0105000b);
+NR_R11L = tregister($0101000b);
+NR_R11W = tregister($0103000b);
+NR_R11D = tregister($0104000b);
+NR_R12 = tregister($0105000c);
+NR_R12L = tregister($0101000c);
+NR_R12W = tregister($0103000c);
+NR_R12D = tregister($0104000c);
+NR_R13 = tregister($0105000d);
+NR_R13L = tregister($0101000d);
+NR_R13W = tregister($0103000d);
+NR_R13D = tregister($0104000d);
+NR_R14 = tregister($0105000e);
+NR_R14L = tregister($0101000e);
+NR_R14W = tregister($0103000e);
+NR_R14D = tregister($0104000e);
+NR_R15 = tregister($0105000f);
+NR_R15L = tregister($0101000f);
+NR_R15W = tregister($0103000f);
+NR_R15D = tregister($0104000f);
+NR_RIP = tregister($05000000);
+NR_EIP = tregister($05000000);
+NR_CS = tregister($05000001);
+NR_DS = tregister($05000002);
+NR_ES = tregister($05000003);
+NR_SS = tregister($05000004);
+NR_FS = tregister($05000005);
+NR_GS = tregister($05000006);
+NR_DR0 = tregister($05000007);
+NR_DR1 = tregister($05000008);
+NR_DR2 = tregister($05000009);
+NR_DR3 = tregister($0500000a);
+NR_DR6 = tregister($0500000b);
+NR_DR7 = tregister($0500000c);
+NR_CR0 = tregister($0500000d);
+NR_CR2 = tregister($0500000e);
+NR_CR3 = tregister($0500000f);
+NR_CR4 = tregister($05000010);
+NR_TR3 = tregister($05000011);
+NR_TR4 = tregister($05000012);
+NR_TR5 = tregister($05000013);
+NR_TR6 = tregister($05000014);
+NR_TR7 = tregister($05000015);
+NR_ST0 = tregister($02000000);
+NR_ST1 = tregister($02000001);
+NR_ST2 = tregister($02000002);
+NR_ST3 = tregister($02000003);
+NR_ST4 = tregister($02000004);
+NR_ST5 = tregister($02000005);
+NR_ST6 = tregister($02000006);
+NR_ST7 = tregister($02000007);
+NR_ST = tregister($02000008);
+NR_MM0 = tregister($03000000);
+NR_MM1 = tregister($03000001);
+NR_MM2 = tregister($03000002);
+NR_MM3 = tregister($03000003);
+NR_MM4 = tregister($03000004);
+NR_MM5 = tregister($03000005);
+NR_MM6 = tregister($03000006);
+NR_MM7 = tregister($03000007);
+NR_XMM0 = tregister($04000000);
+NR_XMM1 = tregister($04000001);
+NR_XMM2 = tregister($04000002);
+NR_XMM3 = tregister($04000003);
+NR_XMM4 = tregister($04000004);
+NR_XMM5 = tregister($04000005);
+NR_XMM6 = tregister($04000006);
+NR_XMM7 = tregister($04000007);
+NR_XMM8 = tregister($04000008);
+NR_XMM9 = tregister($04000009);
+NR_XMM10 = tregister($0400000a);
+NR_XMM11 = tregister($0400000b);
+NR_XMM12 = tregister($0400000c);
+NR_XMM13 = tregister($0400000d);
+NR_XMM14 = tregister($0400000e);
+NR_XMM15 = tregister($0400000f);
diff --git a/closures/compiler/x86_64/r8664dwrf.inc b/closures/compiler/x86_64/r8664dwrf.inc
new file mode 100644
index 0000000000..27f736cb5c
--- /dev/null
+++ b/closures/compiler/x86_64/r8664dwrf.inc
@@ -0,0 +1,126 @@
+{ don't edit, this file is generated from x86reg.dat }
+-1,
+0,
+0,
+0,
+0,
+0,
+2,
+2,
+2,
+2,
+2,
+1,
+1,
+1,
+1,
+1,
+3,
+3,
+3,
+3,
+3,
+4,
+4,
+4,
+4,
+5,
+5,
+5,
+5,
+6,
+6,
+6,
+6,
+7,
+7,
+7,
+7,
+8,
+8,
+8,
+8,
+9,
+9,
+9,
+9,
+10,
+10,
+10,
+10,
+11,
+11,
+11,
+11,
+12,
+12,
+12,
+12,
+13,
+13,
+13,
+13,
+14,
+14,
+14,
+14,
+15,
+15,
+15,
+15,
+16,
+16,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+33,
+34,
+35,
+36,
+37,
+38,
+39,
+40,
+33,
+41,
+42,
+43,
+44,
+45,
+46,
+47,
+48,
+17,
+18,
+19,
+20,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+31,
+32
diff --git a/closures/compiler/x86_64/r8664int.inc b/closures/compiler/x86_64/r8664int.inc
new file mode 100644
index 0000000000..55ea578074
--- /dev/null
+++ b/closures/compiler/x86_64/r8664int.inc
@@ -0,0 +1,126 @@
+{ don't edit, this file is generated from x86reg.dat }
+'INVALID',
+'al',
+'ah',
+'ax',
+'eax',
+'rax',
+'cl',
+'ch',
+'cx',
+'ecx',
+'rcx',
+'dl',
+'dh',
+'dx',
+'edx',
+'rdx',
+'bl',
+'bh',
+'bx',
+'ebx',
+'rbx',
+'sil',
+'si',
+'esi',
+'rsi',
+'dil',
+'di',
+'edi',
+'rdi',
+'bpl',
+'bp',
+'ebp',
+'rbp',
+'spl',
+'sp',
+'esp',
+'rsp',
+'r8',
+'r8b',
+'r8w',
+'r8d',
+'r9',
+'r9b',
+'r9w',
+'r9d',
+'r10',
+'r10b',
+'r10w',
+'r10d',
+'r11',
+'r11b',
+'r11w',
+'r11d',
+'r12',
+'r12b',
+'r12w',
+'r12d',
+'r13',
+'r13b',
+'r13w',
+'r13d',
+'r14',
+'r14b',
+'r14w',
+'r14d',
+'r15',
+'r15b',
+'r15w',
+'r15d',
+'rip',
+'eip',
+'cs',
+'ds',
+'es',
+'ss',
+'fs',
+'gs',
+'dr0',
+'dr1',
+'dr2',
+'dr3',
+'dr6',
+'dr7',
+'cr0',
+'cr2',
+'cr3',
+'cr4',
+'tr3',
+'tr4',
+'tr5',
+'tr6',
+'tr7',
+'st(0)',
+'st(1)',
+'st(2)',
+'st(3)',
+'st(4)',
+'st(5)',
+'st(6)',
+'st(7)',
+'st',
+'mm0',
+'mm1',
+'mm2',
+'mm3',
+'mm4',
+'mm5',
+'mm6',
+'mm7',
+'xmm0',
+'xmm1',
+'xmm2',
+'xmm3',
+'xmm4',
+'xmm5',
+'xmm6',
+'xmm7',
+'xmm8',
+'xmm9',
+'xmm10',
+'xmm11',
+'xmm12',
+'xmm13',
+'xmm14',
+'xmm15'
diff --git a/closures/compiler/x86_64/r8664iri.inc b/closures/compiler/x86_64/r8664iri.inc
new file mode 100644
index 0000000000..67d9df19f9
--- /dev/null
+++ b/closures/compiler/x86_64/r8664iri.inc
@@ -0,0 +1,126 @@
+{ don't edit, this file is generated from x86reg.dat }
+0,
+2,
+1,
+3,
+17,
+16,
+30,
+29,
+18,
+7,
+6,
+83,
+84,
+85,
+86,
+71,
+8,
+12,
+26,
+25,
+11,
+77,
+78,
+79,
+80,
+81,
+82,
+72,
+13,
+4,
+31,
+19,
+9,
+27,
+14,
+70,
+73,
+23,
+35,
+75,
+76,
+101,
+102,
+103,
+104,
+105,
+106,
+107,
+108,
+45,
+46,
+48,
+47,
+49,
+50,
+52,
+51,
+53,
+54,
+56,
+55,
+57,
+58,
+60,
+59,
+61,
+62,
+64,
+63,
+65,
+66,
+68,
+67,
+37,
+38,
+40,
+39,
+41,
+42,
+44,
+43,
+5,
+32,
+20,
+10,
+28,
+15,
+69,
+24,
+36,
+22,
+21,
+34,
+33,
+74,
+100,
+92,
+93,
+94,
+95,
+96,
+97,
+98,
+99,
+87,
+88,
+89,
+90,
+91,
+109,
+110,
+119,
+120,
+121,
+122,
+123,
+124,
+111,
+112,
+113,
+114,
+115,
+116,
+117,
+118
diff --git a/closures/compiler/x86_64/r8664nor.inc b/closures/compiler/x86_64/r8664nor.inc
new file mode 100644
index 0000000000..7b3502fb2e
--- /dev/null
+++ b/closures/compiler/x86_64/r8664nor.inc
@@ -0,0 +1,2 @@
+{ don't edit, this file is generated from x86reg.dat }
+125
diff --git a/closures/compiler/x86_64/r8664num.inc b/closures/compiler/x86_64/r8664num.inc
new file mode 100644
index 0000000000..01e0b0dfa7
--- /dev/null
+++ b/closures/compiler/x86_64/r8664num.inc
@@ -0,0 +1,126 @@
+{ don't edit, this file is generated from x86reg.dat }
+tregister($00000000),
+tregister($01010000),
+tregister($01020000),
+tregister($01030000),
+tregister($01040000),
+tregister($01050000),
+tregister($01010001),
+tregister($01020001),
+tregister($01030001),
+tregister($01040001),
+tregister($01050001),
+tregister($01010002),
+tregister($01020002),
+tregister($01030002),
+tregister($01040002),
+tregister($01050002),
+tregister($01010003),
+tregister($01020003),
+tregister($01030003),
+tregister($01040003),
+tregister($01050003),
+tregister($01010004),
+tregister($01030004),
+tregister($01040004),
+tregister($01050004),
+tregister($01010005),
+tregister($01030005),
+tregister($01040005),
+tregister($01050005),
+tregister($01010006),
+tregister($01030006),
+tregister($01040006),
+tregister($01050006),
+tregister($01010007),
+tregister($01030007),
+tregister($01040007),
+tregister($01050007),
+tregister($01050008),
+tregister($01010008),
+tregister($01030008),
+tregister($01040008),
+tregister($01050009),
+tregister($01010009),
+tregister($01030009),
+tregister($01040009),
+tregister($0105000a),
+tregister($0101000a),
+tregister($0103000a),
+tregister($0104000a),
+tregister($0105000b),
+tregister($0101000b),
+tregister($0103000b),
+tregister($0104000b),
+tregister($0105000c),
+tregister($0101000c),
+tregister($0103000c),
+tregister($0104000c),
+tregister($0105000d),
+tregister($0101000d),
+tregister($0103000d),
+tregister($0104000d),
+tregister($0105000e),
+tregister($0101000e),
+tregister($0103000e),
+tregister($0104000e),
+tregister($0105000f),
+tregister($0101000f),
+tregister($0103000f),
+tregister($0104000f),
+tregister($05000000),
+tregister($05000000),
+tregister($05000001),
+tregister($05000002),
+tregister($05000003),
+tregister($05000004),
+tregister($05000005),
+tregister($05000006),
+tregister($05000007),
+tregister($05000008),
+tregister($05000009),
+tregister($0500000a),
+tregister($0500000b),
+tregister($0500000c),
+tregister($0500000d),
+tregister($0500000e),
+tregister($0500000f),
+tregister($05000010),
+tregister($05000011),
+tregister($05000012),
+tregister($05000013),
+tregister($05000014),
+tregister($05000015),
+tregister($02000000),
+tregister($02000001),
+tregister($02000002),
+tregister($02000003),
+tregister($02000004),
+tregister($02000005),
+tregister($02000006),
+tregister($02000007),
+tregister($02000008),
+tregister($03000000),
+tregister($03000001),
+tregister($03000002),
+tregister($03000003),
+tregister($03000004),
+tregister($03000005),
+tregister($03000006),
+tregister($03000007),
+tregister($04000000),
+tregister($04000001),
+tregister($04000002),
+tregister($04000003),
+tregister($04000004),
+tregister($04000005),
+tregister($04000006),
+tregister($04000007),
+tregister($04000008),
+tregister($04000009),
+tregister($0400000a),
+tregister($0400000b),
+tregister($0400000c),
+tregister($0400000d),
+tregister($0400000e),
+tregister($0400000f)
diff --git a/closures/compiler/x86_64/r8664op.inc b/closures/compiler/x86_64/r8664op.inc
new file mode 100644
index 0000000000..2681385b44
--- /dev/null
+++ b/closures/compiler/x86_64/r8664op.inc
@@ -0,0 +1,126 @@
+{ don't edit, this file is generated from x86reg.dat }
+0,
+0,
+4,
+0,
+0,
+0,
+1,
+5,
+1,
+1,
+1,
+2,
+6,
+2,
+2,
+2,
+3,
+7,
+3,
+3,
+3,
+6,
+6,
+6,
+6,
+7,
+7,
+7,
+7,
+5,
+5,
+5,
+5,
+4,
+4,
+4,
+4,
+0,
+0,
+0,
+0,
+1,
+1,
+1,
+1,
+2,
+2,
+2,
+2,
+3,
+3,
+3,
+3,
+4,
+4,
+4,
+4,
+5,
+5,
+5,
+5,
+6,
+6,
+6,
+6,
+7,
+7,
+7,
+7,
+0,
+0,
+1,
+3,
+0,
+2,
+4,
+5,
+0,
+1,
+2,
+3,
+6,
+7,
+0,
+2,
+3,
+4,
+3,
+4,
+5,
+6,
+7,
+0,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+0,
+0,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+0,
+1,
+2,
+3,
+4,
+5,
+6,
+7,
+0,
+1,
+2,
+3,
+4,
+5,
+6,
+7
diff --git a/closures/compiler/x86_64/r8664ot.inc b/closures/compiler/x86_64/r8664ot.inc
new file mode 100644
index 0000000000..7db67465fe
--- /dev/null
+++ b/closures/compiler/x86_64/r8664ot.inc
@@ -0,0 +1,126 @@
+{ don't edit, this file is generated from x86reg.dat }
+OT_NONE,
+OT_REG_AL,
+OT_REG8,
+OT_REG_AX,
+OT_REG_EAX,
+OT_REG_RAX,
+OT_REG_CL,
+OT_REG8,
+OT_REG_CX,
+OT_REG_ECX,
+OT_REG_RCX,
+OT_REG8,
+OT_REG8,
+OT_REG_DX,
+OT_REG32,
+OT_REG64,
+OT_REG8,
+OT_REG8,
+OT_REG16,
+OT_REG32,
+OT_REG64,
+OT_REG8,
+OT_REG16,
+OT_REG32,
+OT_REG64,
+OT_REG8,
+OT_REG16,
+OT_REG32,
+OT_REG64,
+OT_REG8,
+OT_REG16,
+OT_REG32,
+OT_REG64,
+OT_REG8,
+OT_REG16,
+OT_REG32,
+OT_REG64,
+OT_REG64,
+OT_REG8,
+OT_REG16,
+OT_REG32,
+OT_REG64,
+OT_REG8,
+OT_REG16,
+OT_REG32,
+OT_REG64,
+OT_REG8,
+OT_REG16,
+OT_REG32,
+OT_REG64,
+OT_REG8,
+OT_REG16,
+OT_REG32,
+OT_REG64,
+OT_REG8,
+OT_REG16,
+OT_REG32,
+OT_REG64,
+OT_REG8,
+OT_REG16,
+OT_REG32,
+OT_REG64,
+OT_REG8,
+OT_REG16,
+OT_REG32,
+OT_REG64,
+OT_REG8,
+OT_REG16,
+OT_REG32,
+OT_NONE,
+OT_NONE,
+OT_REG_CS,
+OT_REG_DESS,
+OT_REG_DESS,
+OT_REG_DESS,
+OT_REG_FSGS,
+OT_REG_FSGS,
+OT_REG_DREG,
+OT_REG_DREG,
+OT_REG_DREG,
+OT_REG_DREG,
+OT_REG_DREG,
+OT_REG_DREG,
+OT_REG_CREG,
+OT_REG_CREG,
+OT_REG_CREG,
+OT_REG_CR4,
+OT_REG_TREG,
+OT_REG_TREG,
+OT_REG_TREG,
+OT_REG_TREG,
+OT_REG_TREG,
+OT_FPU0,
+OT_FPUREG,
+OT_FPUREG,
+OT_FPUREG,
+OT_FPUREG,
+OT_FPUREG,
+OT_FPUREG,
+OT_FPUREG,
+OT_FPU0,
+OT_MMXREG,
+OT_MMXREG,
+OT_MMXREG,
+OT_MMXREG,
+OT_MMXREG,
+OT_MMXREG,
+OT_MMXREG,
+OT_MMXREG,
+OT_XMMREG,
+OT_XMMREG,
+OT_XMMREG,
+OT_XMMREG,
+OT_XMMREG,
+OT_XMMREG,
+OT_XMMREG,
+OT_XMMREG,
+OT_XMMREG,
+OT_XMMREG,
+OT_XMMREG,
+OT_XMMREG,
+OT_XMMREG,
+OT_XMMREG,
+OT_XMMREG,
+OT_XMMREG
diff --git a/closures/compiler/x86_64/r8664rni.inc b/closures/compiler/x86_64/r8664rni.inc
new file mode 100644
index 0000000000..3ab0a735ab
--- /dev/null
+++ b/closures/compiler/x86_64/r8664rni.inc
@@ -0,0 +1,126 @@
+{ don't edit, this file is generated from x86reg.dat }
+0,
+1,
+6,
+11,
+16,
+21,
+25,
+29,
+33,
+38,
+42,
+46,
+50,
+54,
+58,
+62,
+66,
+2,
+7,
+12,
+17,
+3,
+8,
+13,
+18,
+22,
+26,
+30,
+34,
+39,
+43,
+47,
+51,
+55,
+59,
+63,
+67,
+4,
+9,
+14,
+19,
+23,
+27,
+31,
+35,
+40,
+44,
+48,
+52,
+56,
+60,
+64,
+68,
+5,
+10,
+15,
+20,
+24,
+28,
+32,
+36,
+37,
+41,
+45,
+49,
+53,
+57,
+61,
+65,
+92,
+93,
+94,
+95,
+96,
+97,
+98,
+99,
+100,
+101,
+102,
+103,
+104,
+105,
+106,
+107,
+108,
+109,
+110,
+111,
+112,
+113,
+114,
+115,
+116,
+117,
+118,
+119,
+120,
+121,
+122,
+123,
+124,
+69,
+70,
+71,
+72,
+73,
+74,
+75,
+76,
+77,
+78,
+79,
+80,
+81,
+82,
+83,
+84,
+85,
+86,
+87,
+88,
+89,
+90,
+91
diff --git a/closures/compiler/x86_64/r8664sri.inc b/closures/compiler/x86_64/r8664sri.inc
new file mode 100644
index 0000000000..67d9df19f9
--- /dev/null
+++ b/closures/compiler/x86_64/r8664sri.inc
@@ -0,0 +1,126 @@
+{ don't edit, this file is generated from x86reg.dat }
+0,
+2,
+1,
+3,
+17,
+16,
+30,
+29,
+18,
+7,
+6,
+83,
+84,
+85,
+86,
+71,
+8,
+12,
+26,
+25,
+11,
+77,
+78,
+79,
+80,
+81,
+82,
+72,
+13,
+4,
+31,
+19,
+9,
+27,
+14,
+70,
+73,
+23,
+35,
+75,
+76,
+101,
+102,
+103,
+104,
+105,
+106,
+107,
+108,
+45,
+46,
+48,
+47,
+49,
+50,
+52,
+51,
+53,
+54,
+56,
+55,
+57,
+58,
+60,
+59,
+61,
+62,
+64,
+63,
+65,
+66,
+68,
+67,
+37,
+38,
+40,
+39,
+41,
+42,
+44,
+43,
+5,
+32,
+20,
+10,
+28,
+15,
+69,
+24,
+36,
+22,
+21,
+34,
+33,
+74,
+100,
+92,
+93,
+94,
+95,
+96,
+97,
+98,
+99,
+87,
+88,
+89,
+90,
+91,
+109,
+110,
+119,
+120,
+121,
+122,
+123,
+124,
+111,
+112,
+113,
+114,
+115,
+116,
+117,
+118
diff --git a/closures/compiler/x86_64/r8664stab.inc b/closures/compiler/x86_64/r8664stab.inc
new file mode 100644
index 0000000000..27f736cb5c
--- /dev/null
+++ b/closures/compiler/x86_64/r8664stab.inc
@@ -0,0 +1,126 @@
+{ don't edit, this file is generated from x86reg.dat }
+-1,
+0,
+0,
+0,
+0,
+0,
+2,
+2,
+2,
+2,
+2,
+1,
+1,
+1,
+1,
+1,
+3,
+3,
+3,
+3,
+3,
+4,
+4,
+4,
+4,
+5,
+5,
+5,
+5,
+6,
+6,
+6,
+6,
+7,
+7,
+7,
+7,
+8,
+8,
+8,
+8,
+9,
+9,
+9,
+9,
+10,
+10,
+10,
+10,
+11,
+11,
+11,
+11,
+12,
+12,
+12,
+12,
+13,
+13,
+13,
+13,
+14,
+14,
+14,
+14,
+15,
+15,
+15,
+15,
+16,
+16,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+-1,
+33,
+34,
+35,
+36,
+37,
+38,
+39,
+40,
+33,
+41,
+42,
+43,
+44,
+45,
+46,
+47,
+48,
+17,
+18,
+19,
+20,
+21,
+22,
+23,
+24,
+25,
+26,
+27,
+28,
+29,
+30,
+31,
+32
diff --git a/closures/compiler/x86_64/r8664std.inc b/closures/compiler/x86_64/r8664std.inc
new file mode 100644
index 0000000000..55ea578074
--- /dev/null
+++ b/closures/compiler/x86_64/r8664std.inc
@@ -0,0 +1,126 @@
+{ don't edit, this file is generated from x86reg.dat }
+'INVALID',
+'al',
+'ah',
+'ax',
+'eax',
+'rax',
+'cl',
+'ch',
+'cx',
+'ecx',
+'rcx',
+'dl',
+'dh',
+'dx',
+'edx',
+'rdx',
+'bl',
+'bh',
+'bx',
+'ebx',
+'rbx',
+'sil',
+'si',
+'esi',
+'rsi',
+'dil',
+'di',
+'edi',
+'rdi',
+'bpl',
+'bp',
+'ebp',
+'rbp',
+'spl',
+'sp',
+'esp',
+'rsp',
+'r8',
+'r8b',
+'r8w',
+'r8d',
+'r9',
+'r9b',
+'r9w',
+'r9d',
+'r10',
+'r10b',
+'r10w',
+'r10d',
+'r11',
+'r11b',
+'r11w',
+'r11d',
+'r12',
+'r12b',
+'r12w',
+'r12d',
+'r13',
+'r13b',
+'r13w',
+'r13d',
+'r14',
+'r14b',
+'r14w',
+'r14d',
+'r15',
+'r15b',
+'r15w',
+'r15d',
+'rip',
+'eip',
+'cs',
+'ds',
+'es',
+'ss',
+'fs',
+'gs',
+'dr0',
+'dr1',
+'dr2',
+'dr3',
+'dr6',
+'dr7',
+'cr0',
+'cr2',
+'cr3',
+'cr4',
+'tr3',
+'tr4',
+'tr5',
+'tr6',
+'tr7',
+'st(0)',
+'st(1)',
+'st(2)',
+'st(3)',
+'st(4)',
+'st(5)',
+'st(6)',
+'st(7)',
+'st',
+'mm0',
+'mm1',
+'mm2',
+'mm3',
+'mm4',
+'mm5',
+'mm6',
+'mm7',
+'xmm0',
+'xmm1',
+'xmm2',
+'xmm3',
+'xmm4',
+'xmm5',
+'xmm6',
+'xmm7',
+'xmm8',
+'xmm9',
+'xmm10',
+'xmm11',
+'xmm12',
+'xmm13',
+'xmm14',
+'xmm15'
diff --git a/closures/compiler/x86_64/rax64att.pas b/closures/compiler/x86_64/rax64att.pas
new file mode 100644
index 0000000000..5f5ac9ccf9
--- /dev/null
+++ b/closures/compiler/x86_64/rax64att.pas
@@ -0,0 +1,243 @@
+{
+ Copyright (c) 1998-2002 by Carl Eric Codere and Peter Vreman
+
+ Does the parsing for the i386 GNU AS styled inline assembler.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+Unit rax64att;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ raatt,rax86att,aasmtai;
+
+ type
+ tx8664attreader = class(tx86attreader)
+ actsehdirective: TAsmSehDirective;
+ procedure handleopcode;override;
+ function is_targetdirective(const s:string):boolean;override;
+ procedure handletargetdirective;override;
+ end;
+
+
+ implementation
+
+ uses
+ cutils,globtype,rabase,systems,rax86,aasmcpu,cgbase,procinfo,symconst,verbose;
+
+ procedure tx8664attreader.handleopcode;
+ var
+ instr : Tx86Instruction;
+ begin
+ instr:=Tx86attInstruction.Create(Tx86Operand);
+ instr.OpOrder:=op_att;
+ BuildOpcode(instr);
+ instr.AddReferenceSizes;
+ instr.SetInstructionOpsize;
+ instr.CheckOperandSizes;
+ instr.FixupOpcode;
+ instr.ConcatInstruction(curlist);
+ instr.Free;
+ end;
+
+ const
+ { x86_64 subset of SEH directives. .seh_proc and .seh_endproc excluded
+ because they are generated automatically when needed. }
+ recognized_directives: set of TAsmSehDirective=[
+ ash_endprologue,ash_handler,ash_handlerdata,
+ ash_setframe,ash_stackalloc,ash_pushreg,
+ ash_savereg,ash_savexmm,ash_pushframe
+ ];
+
+ { max offset and bitmask for .seh_savereg and .seh_setframe }
+ maxoffset: array[boolean] of aint=(high(dword), 240);
+ modulo: array[boolean] of integer=(7, 15);
+
+ function tx8664attreader.is_targetdirective(const s:string):boolean;
+ var
+ i: TAsmSehDirective;
+ begin
+ result:=false;
+ if target_info.system<>system_x86_64_win64 then
+ exit;
+
+ for i:=low(TAsmSehDirective) to high(TAsmSehDirective) do
+ begin
+ if not (i in recognized_directives) then
+ continue;
+ if s=sehdirectivestr[i] then
+ begin
+ actsehdirective:=i;
+ result:=true;
+ break;
+ end;
+ end;
+ { allow SEH directives only in pure assember routines }
+ if result and not (po_assembler in current_procinfo.procdef.procoptions) then
+ begin
+ Message(asmr_e_seh_in_pure_asm_only);
+ result:=false;
+ end;
+ end;
+
+ procedure tx8664attreader.handletargetdirective;
+ var
+ hreg: TRegister;
+ hnum: aint;
+ flags: integer;
+ ai: tai_seh_directive;
+ hs: string;
+ err: boolean;
+ begin
+ if actasmtoken<>AS_TARGET_DIRECTIVE then
+ InternalError(2011100201);
+ Consume(AS_TARGET_DIRECTIVE);
+ Include(current_procinfo.flags,pi_has_unwind_info);
+
+ case actsehdirective of
+ { TODO: .seh_pushframe is supposed to have a boolean parameter,
+ but GAS 2.21 does not support it. }
+ ash_endprologue,
+ ash_pushframe,
+ ash_handlerdata:
+ curlist.concat(cai_seh_directive.create(actsehdirective));
+
+ ash_handler:
+ begin
+ hs:=actasmpattern;
+ Consume(AS_ID);
+ flags:=0;
+ err:=false;
+ while actasmtoken=AS_COMMA do
+ begin
+ Consume(AS_COMMA);
+ if actasmtoken=AS_AT then
+ begin
+ Consume(AS_AT);
+ if actasmtoken=AS_ID then
+ begin
+ uppervar(actasmpattern);
+ if actasmpattern='EXCEPT' then
+ flags:=flags or 1
+ else if actasmpattern='UNWIND' then
+ flags:=flags or 2
+ else
+ err:=true;
+ Consume(AS_ID);
+ end
+ else
+ err:=true;
+ end
+ else
+ err:=true;
+ if err then
+ begin
+ Message(asmr_e_syntax_error);
+ RecoverConsume(false);
+ exit;
+ end;
+ end;
+
+ ai:=cai_seh_directive.create_name(ash_handler,hs);
+ ai.data.flags:=flags;
+ curlist.concat(ai);
+ end;
+ ash_stackalloc:
+ begin
+ hnum:=BuildConstExpression(false,false);
+ if (hnum<0) or (hnum>high(dword)) or ((hnum and 7)<>0) then
+ Message1(asmr_e_bad_seh_directive_offset,sehdirectivestr[ash_stackalloc])
+ else
+ curlist.concat(cai_seh_directive.create_offset(ash_stackalloc,hnum));
+ end;
+ ash_pushreg:
+ begin
+ hreg:=actasmregister;
+ Consume(AS_REGISTER);
+ if (getregtype(hreg)<>R_INTREGISTER) or (getsubreg(hreg)<>R_SUBQ) then
+ Message1(asmr_e_bad_seh_directive_register,sehdirectivestr[ash_pushreg])
+ else
+ curlist.concat(cai_seh_directive.create_reg(ash_pushreg,hreg));
+ end;
+ ash_setframe,
+ ash_savereg:
+ begin
+ hreg:=actasmregister;
+ Consume(AS_REGISTER);
+ if (getregtype(hreg)<>R_INTREGISTER) or (getsubreg(hreg)<>R_SUBQ) then
+ Message1(asmr_e_bad_seh_directive_register,sehdirectivestr[actsehdirective]);
+ Consume(AS_COMMA);
+ hnum:=BuildConstExpression(false,false);
+ if (hnum<0) or (hnum>maxoffset[actsehdirective=ash_setframe]) or
+ ((hnum mod modulo[actsehdirective=ash_setframe])<>0) then
+ Message1(asmr_e_bad_seh_directive_offset,sehdirectivestr[actsehdirective])
+ else
+ curlist.concat(cai_seh_directive.create_reg_offset(actsehdirective,hreg,hnum));
+ end;
+ ash_savexmm:
+ begin
+ hreg:=actasmregister;
+ Consume(AS_REGISTER);
+ if (getregtype(hreg)<>R_MMREGISTER) then
+ Message1(asmr_e_bad_seh_directive_register,sehdirectivestr[ash_savexmm]);
+ Consume(AS_COMMA);
+ hnum:=BuildConstExpression(false,false);
+ if (hnum<0) or (hnum>high(dword)) or ((hnum and 15)<>0) then
+ Message1(asmr_e_bad_seh_directive_offset,sehdirectivestr[ash_savexmm])
+ else
+ curlist.concat(cai_seh_directive.create_reg_offset(actsehdirective,hreg,hnum));
+ end;
+
+ else
+ InternalError(2011100202);
+ end;
+ if actasmtoken<>AS_SEPARATOR then
+ Consume(AS_SEPARATOR);
+ end;
+
+
+const
+ asmmode_x86_64_gas_info : tasmmodeinfo =
+ (
+ id : asmmode_x86_64_gas;
+ idtxt : 'GAS';
+ casmreader : tx8664attreader;
+ );
+
+ { Added to be compatible with i386 }
+ asmmode_x86_64_att_info : tasmmodeinfo =
+ (
+ id : asmmode_x86_64_att;
+ idtxt : 'ATT';
+ casmreader : tx8664attreader;
+ );
+
+ asmmode_x86_64_standard_info : tasmmodeinfo =
+ (
+ id : asmmode_standard;
+ idtxt : 'STANDARD';
+ casmreader : tx8664attreader;
+ );
+
+initialization
+ RegisterAsmMode(asmmode_x86_64_gas_info);
+ RegisterAsmMode(asmmode_x86_64_att_info);
+ RegisterAsmMode(asmmode_x86_64_standard_info);
+end.
diff --git a/closures/compiler/x86_64/rax64int.pas b/closures/compiler/x86_64/rax64int.pas
new file mode 100644
index 0000000000..0241cde5e6
--- /dev/null
+++ b/closures/compiler/x86_64/rax64int.pas
@@ -0,0 +1,70 @@
+{
+ Copyright (c) 1998-2006 by Carl Eric Codere and Peter Vreman
+
+ Does the parsing for the x86-64 intel styled inline assembler.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+Unit rax64int;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ rax86int;
+
+ type
+ tx8664intreader = class(tx86intreader)
+ // procedure handleopcode;override;
+ end;
+
+
+ implementation
+
+ uses
+ rabase,systems,rax86,aasmcpu;
+
+(*
+ procedure tx8664intreader.handleopcode;
+ var
+ instr : Tx86Instruction;
+ begin
+ instr:=Tx86Instruction.Create(Tx86Operand);
+ instr.OpOrder:=op_att;
+ BuildOpcode(instr);
+ instr.AddReferenceSizes;
+ instr.SetInstructionOpsize;
+ {
+ instr.CheckOperandSizes;
+ }
+ instr.ConcatInstruction(curlist);
+ instr.Free;
+ end;
+*)
+
+const
+ asmmode_x86_64_intel_info : tasmmodeinfo =
+ (
+ id : asmmode_x86_64_intel;
+ idtxt : 'INTEL';
+ casmreader : tx8664intreader;
+ );
+
+initialization
+ RegisterAsmMode(asmmode_x86_64_intel_info);
+end.
diff --git a/closures/compiler/x86_64/rgcpu.pas b/closures/compiler/x86_64/rgcpu.pas
new file mode 100644
index 0000000000..566d15aa41
--- /dev/null
+++ b/closures/compiler/x86_64/rgcpu.pas
@@ -0,0 +1,53 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl
+
+ This unit implements the x86-64 specific class for the register
+ allocator
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+
+unit rgcpu;
+
+{$i fpcdefs.inc}
+
+ interface
+
+ uses
+ cgbase,rgx86;
+
+ type
+ trgcpu = class(trgx86)
+ procedure add_constraints(reg:Tregister); override;
+ end;
+
+ implementation
+
+ uses
+ cpubase;
+
+ procedure trgcpu.add_constraints(reg:Tregister);
+ var
+ supreg : tsuperregister;
+ begin
+ supreg:=getsupreg(reg);
+ { All registers conflict with rsp/rbp }
+ add_edge(supreg,RS_RSP);
+ add_edge(supreg,RS_RBP);
+ end;
+
+end.
diff --git a/closures/compiler/x86_64/win64unw.pas b/closures/compiler/x86_64/win64unw.pas
new file mode 100644
index 0000000000..63ca259fee
--- /dev/null
+++ b/closures/compiler/x86_64/win64unw.pas
@@ -0,0 +1,408 @@
+{
+ Copyright (c) 2011 by Free Pascal development team
+
+ Support for win64 unwind data
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit win64unw;
+
+{$i fpcdefs.inc}
+
+interface
+
+uses
+ cclasses,globtype,aasmbase,aasmdata,aasmtai,cgbase,ogbase;
+
+type
+ TWin64CFI=class
+ private
+ FFrameOffs, FFrameReg: Integer;
+ FFlags: Integer;
+ FHandler: TObjSymbol;
+ FCount: Integer;
+ FElements:TLinkedList;
+ FFrameStartSym:TObjSymbol;
+ FFrameStartSec:TObjSection;
+ FXdataSym:TObjSymbol;
+ FXdataSec:TObjSection;
+ FPrologueEndPos:aword;
+ FPrologueEndSeen:Boolean;
+ FName: pshortstring;
+ procedure AddElement(objdata:TObjData;aCode,aInfo:Integer;aOffs:dword);
+ public
+ constructor create;
+ destructor destroy;override;
+ procedure generate_prologue_data(objdata:TObjData);
+ procedure start_frame(objdata:TObjData; const name: string);
+ procedure end_frame(objdata:TObjData);
+ procedure end_prologue(objdata:TObjData);
+ procedure push_reg(objdata:TObjData;reg:tregister);
+ procedure save_reg(objdata:TObjData;reg:tregister;ofs:dword);
+ procedure save_xmm(objdata:TObjData;reg:tregister;ofs:dword);
+ procedure set_frame(objdata:TObjData; reg:tregister;ofs:dword);
+ procedure stack_alloc(objdata:TObjData;ofs:dword);
+ procedure switch_to_handlerdata(objdata:TObjData);
+ end;
+
+
+implementation
+
+uses
+ cutils,globals,verbose,cpubase;
+
+const
+ UWOP_PUSH_NONVOL = 0; { info = register number }
+ UWOP_ALLOC_LARGE = 1; { no info, alloc size in next 2 slots }
+ UWOP_ALLOC_SMALL = 2; { info = size of allocation / 8 - 1 }
+ UWOP_SET_FPREG = 3; { no info, FP = RSP + UNWIND_INFO.FPRegOffset*16 }
+ UWOP_SAVE_NONVOL = 4; { info = register number, offset in next slot }
+ UWOP_SAVE_NONVOL_FAR = 5; { info = register number, offset in next 2 slots }
+ UWOP_SAVE_XMM = 6;
+ UWOP_SAVE_XMM_FAR = 7;
+ UWOP_SAVE_XMM128 = 8; { info = XMM reg number, offset in next slot }
+ UWOP_SAVE_XMM128_FAR = 9; { info = XMM reg number, offset in next 2 slots }
+ UWOP_PUSH_MACHFRAME = 10; { info = 0: no error-code, 1: error-code }
+
+ UNW_FLAG_EHANDLER = $01; { exceptiion handler }
+ UNW_FLAG_UHANDLER = $02; { termination handler }
+ UNW_FLAG_FHANDLER = UNW_FLAG_EHANDLER or UNW_FLAG_UHANDLER;
+ UNW_FLAG_CHAININFO = $04; { mutually exclusive with the above }
+
+
+type
+ tai_seh_directive_x64=class(tai_seh_directive)
+ procedure generate_code(objdata:TObjData);override;
+ end;
+
+ TPrologueElement=class(TLinkedListItem)
+ public
+ opcode: Integer; { =(info shl 4) or code }
+ ofs: dword;
+ addr: aword;
+ end;
+
+var
+ current_unw: TWin64Cfi;
+
+function EncodeReg(r: TRegister): integer;
+begin
+ case r of
+ NR_RAX: result:=0;
+ NR_RCX: result:=1;
+ NR_RDX: result:=2;
+ NR_RBX: result:=3;
+ NR_RSP: result:=4;
+ NR_RBP: result:=5;
+ NR_RSI: result:=6;
+ NR_RDI: result:=7;
+ NR_R8: result:=8;
+ NR_R9: result:=9;
+ NR_R10: result:=10;
+ NR_R11: result:=11;
+ NR_R12: result:=12;
+ NR_R13: result:=13;
+ NR_R14: result:=14;
+ NR_R15: result:=15;
+ else
+ InternalError(2011072305);
+ end;
+end;
+
+function EncodeXMM(r: TRegister): integer;
+begin
+ if getregtype(r)=R_MMREGISTER then
+ result:=getsupreg(r)
+ else
+ InternalError(2011072308);
+end;
+
+
+{ TWin64CFI }
+
+constructor TWin64CFI.create;
+begin
+ inherited create;
+ FElements:=TLinkedList.Create;
+end;
+
+destructor TWin64CFI.destroy;
+begin
+ FElements.Free;
+ stringdispose(FName);
+ inherited destroy;
+end;
+
+procedure TWin64CFI.AddElement(objdata:TObjData;aCode,aInfo:Integer;aOffs:dword);
+var
+ el:TPrologueElement;
+begin
+ el:=TPrologueElement.Create;
+ FElements.concat(el);
+ el.opcode:=(aInfo shl 4) or aCode;
+ el.ofs:=aOffs;
+ el.addr:=objdata.CurrObjSec.Size;
+
+ { a single element may occupy 1,2 or 3 word-sized slots }
+ case aCode of
+ UWOP_ALLOC_LARGE:
+ Inc(FCount,2+ord(aInfo<>0));
+
+ UWOP_SAVE_NONVOL_FAR,
+ UWOP_SAVE_XMM128_FAR:
+ Inc(FCount,3);
+
+ UWOP_SAVE_NONVOL,
+ UWOP_SAVE_XMM128:
+ Inc(FCount,2);
+
+ else
+ inc(FCount);
+ end;
+end;
+
+{ Changes objdata.CurrObjSec to .xdata, so generation of
+ handler data may continue }
+procedure TWin64CFI.generate_prologue_data(objdata:TObjData);
+var
+ hp: TPrologueElement;
+ uwcode: array [0..1] of byte;
+ uwdata: array [0..3] of byte;
+ zero: word;
+begin
+ if FCount>255 then
+ InternalError(2011072301);
+ if not FPrologueEndSeen then
+ CGMessage(asmw_e_missing_endprologue);
+ if (FPrologueEndPos-FFrameStartSym.address) > 255 then
+ CGMessage(asmw_e_prologue_too_large);
+ if codegenerror then
+ exit;
+
+ FXdataSec:=objdata.createsection('.xdata.n_'+lower(FName^),4,[oso_data,oso_load]);
+ FXdataSym:=objdata.symboldefine('$unwind$'+FName^,AB_GLOBAL,AT_DATA);
+ uwdata[0]:=(FFlags shl 3) or 1;
+ uwdata[1]:=FPrologueEndPos-FFrameStartSym.address;
+ uwdata[2]:=FCount;
+ { Offset is multiple of 16, so it is already shifted into correct position }
+ uwdata[3]:=FFrameOffs or FFrameReg;
+ objdata.writebytes(uwdata,4);
+
+ { write elements in reverse order (offset descending) }
+ hp:=TPrologueElement(FElements.Last);
+ while Assigned(hp) do
+ begin
+ uwcode[0]:=hp.addr-FFrameStartSym.address;
+ uwcode[1]:=hp.opcode;
+ objdata.writebytes(uwcode,2);
+ case hp.opcode and $0F of
+ UWOP_PUSH_NONVOL,
+ UWOP_ALLOC_SMALL,
+ UWOP_SET_FPREG,
+ UWOP_PUSH_MACHFRAME: ; { These have no extra data }
+
+ UWOP_ALLOC_LARGE:
+ if (hp.opcode and $F0)<>0 then
+ objdata.writebytes(hp.ofs,4)
+ else
+ objdata.writebytes(hp.ofs,2);
+
+ UWOP_SAVE_NONVOL_FAR,
+ UWOP_SAVE_XMM128_FAR:
+ objdata.writebytes(hp.ofs,4);
+
+ UWOP_SAVE_NONVOL,
+ UWOP_SAVE_XMM128:
+ objdata.writebytes(hp.ofs,2);
+ else
+ InternalError(2011072302);
+ end;
+
+ hp:=TPrologueElement(hp.Previous);
+ end;
+ { pad with zeros to dword boundary }
+ zero:=0;
+ if odd(FCount) then
+ objdata.writebytes(zero,2);
+ if Assigned(FHandler) then
+ objdata.writereloc(0,sizeof(longint),FHandler,RELOC_RVA);
+end;
+
+procedure TWin64CFI.start_frame(objdata:TObjData;const name:string);
+begin
+ if assigned(FName) then
+ internalerror(2011072306);
+ FName:=stringdup(name);
+ FFrameStartSym:=objdata.symbolref(name);
+ FFrameStartSec:=objdata.CurrObjSec;
+ FCount:=0;
+ FFrameReg:=0;
+ FFrameOffs:=0;
+ FPrologueEndPos:=0;
+ FPrologueEndSeen:=false;
+ FHandler:=nil;
+ FXdataSec:=nil;
+ FXdataSym:=nil;
+ FFlags:=0;
+end;
+
+procedure TWin64CFI.switch_to_handlerdata(objdata:TObjData);
+begin
+ if not assigned(FName) then
+ internalerror(2011072310);
+
+ if FHandler=nil then
+ CGMessage(asmw_e_handlerdata_no_handler);
+
+ if FXdataSec=nil then
+ generate_prologue_data(objdata)
+ else
+ objdata.SetSection(FXdataSec);
+end;
+
+procedure TWin64CFI.end_frame(objdata:TObjData);
+var
+ pdatasym:TObjSymbol;
+begin
+ if not assigned(FName) then
+ internalerror(2011072307);
+
+ if FXdataSec=nil then
+ generate_prologue_data(objdata);
+
+ if not codegenerror then
+ begin
+ objdata.createsection(sec_pdata,lower(FName^));
+ pdatasym:=objdata.symboldefine('$pdata$'+FName^,AB_LOCAL,AT_DATA);
+ objdata.writereloc(0,4,FFrameStartSym,RELOC_RVA);
+ objdata.writereloc(FFrameStartSec.Size,4,FFrameStartSym,RELOC_RVA);
+ objdata.writereloc(0,4,FXdataSym,RELOC_RVA);
+ { restore previous state }
+ objdata.SetSection(FFrameStartSec);
+ { create a dummy relocation, so pdata is not smartlinked away }
+ objdata.writereloc(0,0,pdatasym,RELOC_NONE);
+ end;
+ FElements.Clear;
+ FFrameStartSym:=nil;
+ FHandler:=nil;
+ FXdataSec:=nil;
+ FXdataSym:=nil;
+ FFlags:=0;
+ stringdispose(FName);
+end;
+
+procedure TWin64CFI.end_prologue(objdata:TObjData);
+begin
+ if not assigned(FName) then
+ internalerror(2011072312);
+ FPrologueEndPos:=objdata.CurrObjSec.Size;
+ FPrologueEndSeen:=true;
+end;
+
+procedure TWin64CFI.push_reg(objdata:TObjData;reg:tregister);
+begin
+ AddElement(objdata,UWOP_PUSH_NONVOL,EncodeReg(reg),0);
+end;
+
+procedure TWin64CFI.save_reg(objdata:TObjData;reg:tregister;ofs:dword);
+var
+ info: Integer;
+begin
+ info:=EncodeReg(reg);
+ if ((ofs and 7) = 0) and (ofs<=$ffff*8) then
+ AddElement(objdata,UWOP_SAVE_NONVOL,info,ofs shr 3)
+ else
+ AddElement(objdata,UWOP_SAVE_NONVOL_FAR,info,ofs);
+end;
+
+procedure TWin64CFI.save_xmm(objdata:TObjData;reg:tregister;ofs:dword);
+var
+ info: Integer;
+begin
+ info:=EncodeXMM(reg);
+ if ((ofs and 15)=0) and (ofs<=$ffff*16) then
+ AddElement(objdata,UWOP_SAVE_XMM128, info, ofs shr 4)
+ else
+ AddElement(objdata,UWOP_SAVE_XMM128_FAR, info, ofs);
+end;
+
+procedure TWin64CFI.set_frame(objdata:TObjData;reg:tregister;ofs:dword);
+var
+ info: Integer;
+begin
+ info:=EncodeReg(reg);
+ if FFrameReg<>0 then
+ InternalError(2011072303);
+ if info=0 then { frame register cannot be RAX }
+ InternalError(2011072304);
+ if (ofs>240) or ((ofs and 15)<>0) then
+ InternalError(2011072310);
+ FFrameReg:=info;
+ FFrameOffs:=ofs;
+ { !! looks like docs aren't correct and info should be set to register }
+ AddElement(objdata,UWOP_SET_FPREG,0,0);
+end;
+
+procedure TWin64CFI.stack_alloc(objdata:TObjData;ofs:dword);
+begin
+ if ((ofs and 7)=0) and (ofs<=128) then
+ AddElement(objdata,UWOP_ALLOC_SMALL,(ofs-8) shr 3,0)
+ else if ((ofs and 7) = 0) and (ofs<=$ffff * 8) then
+ AddElement(objdata,UWOP_ALLOC_LARGE,0,ofs shr 3)
+ else
+ AddElement(objdata,UWOP_ALLOC_LARGE,1,ofs);
+end;
+
+procedure tai_seh_directive_x64.generate_code(objdata:TObjData);
+begin
+ case kind of
+ ash_proc:
+ current_unw.start_frame(objdata,data.name^);
+ ash_endproc:
+ current_unw.end_frame(objdata);
+ ash_endprologue:
+ current_unw.end_prologue(objdata);
+ ash_handler:
+ begin
+ current_unw.FHandler:=objdata.symbolref(data.name^);
+ current_unw.FFlags:=data.flags;
+ end;
+ ash_handlerdata:
+ current_unw.switch_to_handlerdata(objdata);
+ ash_eh,ash_32,ash_no32: ; { these are not for x86_64 }
+ ash_setframe:
+ current_unw.set_frame(objdata,data.reg,data.offset);
+ ash_stackalloc:
+ current_unw.stack_alloc(objdata,data.offset);
+ ash_pushreg:
+ current_unw.push_reg(objdata,data.reg);
+ ash_savereg:
+ current_unw.save_reg(objdata,data.reg,data.offset);
+ ash_savexmm:
+ current_unw.save_xmm(objdata,data.reg,data.offset);
+ ash_pushframe: {TBD};
+ end;
+end;
+
+
+initialization
+ cai_seh_directive:=tai_seh_directive_x64;
+ current_unw:=TWin64CFI.Create;
+finalization
+ current_unw.Free;
+end.
+
diff --git a/closures/compiler/x86_64/x8664ats.inc b/closures/compiler/x86_64/x8664ats.inc
new file mode 100644
index 0000000000..31bc9cd421
--- /dev/null
+++ b/closures/compiler/x86_64/x8664ats.inc
@@ -0,0 +1,688 @@
+{ don't edit, this file is generated from x86ins.dat }
+(
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufNONE,
+attsufNONE,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufFPUint,
+attsufFPUint,
+attsufFPUint,
+attsufFPUint,
+attsufFPUint,
+attsufFPUint,
+attsufFPUint,
+attsufNONE,
+attsufNONE,
+attsufFPUint,
+attsufFPUint,
+attsufFPUint,
+attsufFPUint,
+attsufFPUint,
+attsufFPU,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufFPU,
+attsufFPU,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufFPU,
+attsufINT,
+attsufNONE,
+attsufFPU,
+attsufINT,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufNONE,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufFPU,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufFPU,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINTdual,
+attsufINTdual,
+attsufINT,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufINT,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufINT,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE
+);
diff --git a/closures/compiler/x86_64/x8664att.inc b/closures/compiler/x86_64/x8664att.inc
new file mode 100644
index 0000000000..a591dad220
--- /dev/null
+++ b/closures/compiler/x86_64/x8664att.inc
@@ -0,0 +1,688 @@
+{ don't edit, this file is generated from x86ins.dat }
+(
+'none',
+'aaa',
+'aad',
+'aam',
+'aas',
+'adc',
+'add',
+'and',
+'arpl',
+'bound',
+'bsf',
+'bsr',
+'bswap',
+'bt',
+'btc',
+'btr',
+'bts',
+'call',
+'cbtw',
+'cltd',
+'clc',
+'cld',
+'cli',
+'clts',
+'cmc',
+'cmp',
+'cmpsb',
+'cmpsl',
+'cmpsw',
+'cmpxchg',
+'cmpxchg486',
+'cmpxchg8b',
+'cpuid',
+'cwd',
+'cwtl',
+'daa',
+'das',
+'dec',
+'div',
+'emms',
+'enter',
+'f2xm1',
+'fabs',
+'fadd',
+'faddp',
+'fbld',
+'fbstp',
+'fchs',
+'fclex',
+'fcmovb',
+'fcmovbe',
+'fcmove',
+'fcmovnb',
+'fcmovnbe',
+'fcmovne',
+'fcmovnu',
+'fcmovu',
+'fcom',
+'fcomi',
+'fcomip',
+'fcomp',
+'fcompp',
+'fcos',
+'fdecstp',
+'fdisi',
+'fdiv',
+'fdivp',
+'fdivr',
+'fdivrp',
+'femms',
+'feni',
+'ffree',
+'fiadd',
+'ficom',
+'ficomp',
+'fidiv',
+'fidivr',
+'fild',
+'fimul',
+'fincstp',
+'finit',
+'fist',
+'fistp',
+'fisttp',
+'fisub',
+'fisubr',
+'fld',
+'fld1',
+'fldcw',
+'fldenv',
+'fldl2e',
+'fldl2t',
+'fldlg2',
+'fldln2',
+'fldpi',
+'fldz',
+'fmul',
+'fmulp',
+'fnclex',
+'fndisi',
+'fneni',
+'fninit',
+'fnop',
+'fnsave',
+'fnstcw',
+'fnstenv',
+'fnstsw',
+'fpatan',
+'fprem',
+'fprem1',
+'fptan',
+'frndint',
+'frstor',
+'fsave',
+'fscale',
+'fsetpm',
+'fsin',
+'fsincos',
+'fsqrt',
+'fst',
+'fstcw',
+'fstenv',
+'fstp',
+'fstsw',
+'fsub',
+'fsubp',
+'fsubr',
+'fsubrp',
+'ftst',
+'fucom',
+'fucomi',
+'fucomip',
+'fucomp',
+'fucompp',
+'fwait',
+'fxam',
+'fxch',
+'fxtract',
+'fyl2x',
+'fyl2xp1',
+'hlt',
+'ibts',
+'icebp',
+'idiv',
+'imul',
+'in',
+'inc',
+'insb',
+'insl',
+'insw',
+'int',
+'int01',
+'int1',
+'int03',
+'int3',
+'into',
+'invd',
+'invlpg',
+'iret',
+'iret',
+'iretw',
+'iretq',
+'jcxz',
+'jecxz',
+'jrcxz',
+'jmp',
+'lahf',
+'lar',
+'lcall',
+'lds',
+'lea',
+'leave',
+'les',
+'lfs',
+'lgdt',
+'lgs',
+'lidt',
+'ljmp',
+'lldt',
+'lmsw',
+'loadall',
+'loadall286',
+'lock',
+'lodsb',
+'lodsl',
+'lodsw',
+'loop',
+'loope',
+'loopne',
+'loopnz',
+'loopz',
+'lsl',
+'lss',
+'ltr',
+'monitor',
+'mov',
+'movd',
+'movq',
+'movsb',
+'movsl',
+'movsq',
+'movsw',
+'movs',
+'movz',
+'mul',
+'mwait',
+'neg',
+'nop',
+'not',
+'or',
+'out',
+'outsb',
+'outsl',
+'outsw',
+'packssdw',
+'packsswb',
+'packuswb',
+'paddb',
+'paddd',
+'paddsb',
+'paddsiw',
+'paddsw',
+'paddusb',
+'paddusw',
+'paddw',
+'pand',
+'pandn',
+'paveb',
+'pavgusb',
+'pcmpeqb',
+'pcmpeqd',
+'pcmpeqw',
+'pcmpgtb',
+'pcmpgtd',
+'pcmpgtw',
+'pdistib',
+'pf2id',
+'pfacc',
+'pfadd',
+'pfcmpeq',
+'pfcmpge',
+'pfcmpgt',
+'pfmax',
+'pfmin',
+'pfmul',
+'pfrcp',
+'pfrcpit1',
+'pfrcpit2',
+'pfrsqit1',
+'pfrsqrt',
+'pfsub',
+'pfsubr',
+'pi2fd',
+'pmachriw',
+'pmaddwd',
+'pmagw',
+'pmulhriw',
+'pmulhrwa',
+'pmulhrwc',
+'pmulhw',
+'pmullw',
+'pmvgezb',
+'pmvlzb',
+'pmvnzb',
+'pmvzb',
+'pop',
+'popa',
+'popal',
+'popaw',
+'popf',
+'popfl',
+'popfw',
+'popfq',
+'por',
+'prefetch',
+'prefetchw',
+'pslld',
+'pslldq',
+'psllq',
+'psllw',
+'psrad',
+'psraw',
+'psrld',
+'psrlq',
+'psrlw',
+'psubb',
+'psubd',
+'psubsb',
+'psubsiw',
+'psubsw',
+'psubusb',
+'psubusw',
+'psubw',
+'punpckhbw',
+'punpckhdq',
+'punpckhwd',
+'punpcklbw',
+'punpckldq',
+'punpcklwd',
+'push',
+'pusha',
+'pushal',
+'pushaw',
+'pushf',
+'pushfl',
+'pushfw',
+'pushfq',
+'pxor',
+'rcl',
+'rcr',
+'rdshr',
+'rdmsr',
+'rdpmc',
+'rdtsc',
+'rep',
+'repe',
+'repne',
+'repnz',
+'repz',
+'ret',
+'lret',
+'ret',
+'rol',
+'ror',
+'rsdc',
+'rsldt',
+'rsm',
+'sahf',
+'sal',
+'salc',
+'sar',
+'sbb',
+'scasb',
+'scasl',
+'scasq',
+'scasw',
+'cs',
+'ds',
+'es',
+'fs',
+'gs',
+'ss',
+'sgdt',
+'shl',
+'shld',
+'shr',
+'shrd',
+'sidt',
+'sldt',
+'smi',
+'smint',
+'smintold',
+'smsw',
+'stc',
+'std',
+'sti',
+'stosb',
+'stosl',
+'stosw',
+'str',
+'sub',
+'svdc',
+'svldt',
+'svts',
+'syscall',
+'sysenter',
+'sysexit',
+'sysret',
+'test',
+'ud1',
+'ud2',
+'umov',
+'verr',
+'verw',
+'wait',
+'wbinvd',
+'wrshr',
+'wrmsr',
+'xadd',
+'xbts',
+'xchg',
+'xlat',
+'xlatb',
+'xor',
+'xstore',
+'xcryptecb',
+'xcryptcbc',
+'xcryptcfb',
+'xcryptofb',
+'cmov',
+'j',
+'set',
+'addps',
+'addss',
+'andnps',
+'andps',
+'cmpeqps',
+'cmpeqss',
+'cmpleps',
+'cmpless',
+'cmpltps',
+'cmpltss',
+'cmpneqps',
+'cmpneqss',
+'cmpnleps',
+'cmpnless',
+'cmpnltps',
+'cmpnltss',
+'cmpordps',
+'cmpordss',
+'cmpunordps',
+'cmpunordss',
+'cmpps',
+'cmpss',
+'comiss',
+'cvtpi2ps',
+'cvtps2pi',
+'cvtsi2ss',
+'cvtss2si',
+'cvttps2pi',
+'cvttss2si',
+'divps',
+'divss',
+'ldmxcsr',
+'maxps',
+'maxss',
+'minps',
+'minss',
+'movaps',
+'movhps',
+'movlhps',
+'movlps',
+'movhlps',
+'movmskps',
+'movntps',
+'movss',
+'movups',
+'mulps',
+'mulss',
+'orps',
+'rcpps',
+'rcpss',
+'rsqrtps',
+'rsqrtss',
+'shufps',
+'sqrtps',
+'sqrtss',
+'stmxcsr',
+'subps',
+'subss',
+'ucomiss',
+'unpckhps',
+'unpcklps',
+'xorps',
+'fxrstor',
+'fxsave',
+'prefetchnta',
+'prefetcht0',
+'prefetcht1',
+'prefetcht2',
+'sfence',
+'maskmovq',
+'movntq',
+'pavgb',
+'pavgw',
+'pextrw',
+'pinsrw',
+'pmaxsw',
+'pmaxub',
+'pminsw',
+'pminub',
+'pmovmskb',
+'pmulhuw',
+'psadbw',
+'pshufw',
+'pfnacc',
+'pfpnacc',
+'pi2fw',
+'pf2iw',
+'pswapd',
+'ffreep',
+'maskmovdqu',
+'clflush',
+'movntdq',
+'movnti',
+'movntpd',
+'pause',
+'lfence',
+'mfence',
+'movdqa',
+'movdqu',
+'movdq2q',
+'movq2dq',
+'paddq',
+'pmuludq',
+'pshufd',
+'pshufhw',
+'pshuflw',
+'psrldq',
+'psubq',
+'punpckhqdq',
+'punpcklqdq',
+'addpd',
+'addsd',
+'andnpd',
+'andpd',
+'cmpeqpd',
+'cmpeqsd',
+'cmplepd',
+'cmplesd',
+'cmpltpd',
+'cmpltsd',
+'cmpneqpd',
+'cmpneqsd',
+'cmpnlepd',
+'cmpnlesd',
+'cmpnltpd',
+'cmpnltsd',
+'cmpordpd',
+'cmpordsd',
+'cmpunordpd',
+'cmpunordsd',
+'cmppd',
+'comisd',
+'cvtdq2pd',
+'cvtdq2ps',
+'cvtpd2dq',
+'cvtpd2pi',
+'cvtpd2ps',
+'cvtpi2pd',
+'cvtps2dq',
+'cvtps2pd',
+'cvtsd2si',
+'cvtsd2ss',
+'cvtsi2sd',
+'cvtss2sd',
+'cvttpd2pi',
+'cvttpd2dq',
+'cvttps2dq',
+'cvttsd2si',
+'divpd',
+'divsd',
+'maxpd',
+'maxsd',
+'minpd',
+'minsd',
+'movapd',
+'movhpd',
+'movlpd',
+'movmskpd',
+'movupd',
+'mulpd',
+'mulsd',
+'orpd',
+'shufpd',
+'sqrtpd',
+'sqrtsd',
+'subpd',
+'subsd',
+'ucomisd',
+'unpckhpd',
+'unpcklpd',
+'xorpd',
+'addsubpd',
+'addsubps',
+'haddpd',
+'haddps',
+'hsubpd',
+'hsubps',
+'lddqu',
+'movddup',
+'movshdup',
+'movsldup',
+'vmread',
+'vmwrite',
+'vmcall',
+'vmlaunch',
+'vmresume',
+'vmxoff',
+'vmxon',
+'vmclear',
+'vmptrld',
+'vmptrst',
+'vmrun',
+'vmmcall',
+'vmload',
+'vmsave',
+'stgi',
+'clgi',
+'skinit',
+'invlpga',
+'montmul',
+'xsha1',
+'xsha256',
+'dmint',
+'rdm',
+'movabs',
+'movslq',
+'cqto',
+'cmpxchg16b',
+'movntss',
+'movntsd',
+'insertq',
+'extrq',
+'lzcnt',
+'pabsb',
+'pabsw',
+'pabsd',
+'palignr',
+'phaddw',
+'phaddd',
+'phaddsw',
+'phsubw',
+'phsubd',
+'phsubsw',
+'pmaddubsw',
+'pmulhrsw',
+'pshufb',
+'psignb',
+'psignw',
+'psignd',
+'blendps',
+'blendpd',
+'blendvps',
+'blendvpd',
+'dpps',
+'dppd',
+'extractps',
+'insertps',
+'movntdqa',
+'mpsadbw',
+'packusdw',
+'pblendvb',
+'pblendw',
+'pcmpeqq',
+'pextrb',
+'pextrd',
+'pextrq',
+'phminposuw',
+'pinsrb',
+'pinsrd',
+'pinsrq',
+'pmaxsb',
+'pmaxsd',
+'pmaxud',
+'pmaxuw',
+'pminsb',
+'pminsd',
+'pminuw',
+'pminud',
+'pmovsxbw',
+'pmovsxbd',
+'pmovsxbq',
+'pmovsxwd',
+'pmovsxwq',
+'pmovsxdq',
+'pmovzxbw',
+'pmovzxbd',
+'pmovzxbq',
+'pmovzxwd',
+'pmovzxwq',
+'pmovzxdq',
+'pmuldq',
+'pmulld',
+'ptest',
+'roundps',
+'roundpd',
+'roundss',
+'roundsd',
+'crc32',
+'pcmpestri',
+'pcmpestrm',
+'pcmpistri',
+'pcmpistrm',
+'pcmpgtq',
+'popcnt',
+'aesenc',
+'aesenclast',
+'aesdec',
+'aesdeclast',
+'aesimc',
+'aeskeygenassist',
+'stosq',
+'lodsq',
+'cmpsq'
+);
diff --git a/closures/compiler/x86_64/x8664int.inc b/closures/compiler/x86_64/x8664int.inc
new file mode 100644
index 0000000000..b6cc4caa78
--- /dev/null
+++ b/closures/compiler/x86_64/x8664int.inc
@@ -0,0 +1,688 @@
+{ don't edit, this file is generated from x86ins.dat }
+(
+'none',
+'aaa',
+'aad',
+'aam',
+'aas',
+'adc',
+'add',
+'and',
+'arpl',
+'bound',
+'bsf',
+'bsr',
+'bswap',
+'bt',
+'btc',
+'btr',
+'bts',
+'call',
+'cbw',
+'cdq',
+'clc',
+'cld',
+'cli',
+'clts',
+'cmc',
+'cmp',
+'cmpsb',
+'cmpsd',
+'cmpsw',
+'cmpxchg',
+'cmpxchg486',
+'cmpxchg8b',
+'cpuid',
+'cwd',
+'cwde',
+'daa',
+'das',
+'dec',
+'div',
+'emms',
+'enter',
+'f2xm1',
+'fabs',
+'fadd',
+'faddp',
+'fbld',
+'fbstp',
+'fchs',
+'fclex',
+'fcmovb',
+'fcmovbe',
+'fcmove',
+'fcmovnb',
+'fcmovnbe',
+'fcmovne',
+'fcmovnu',
+'fcmovu',
+'fcom',
+'fcomi',
+'fcomip',
+'fcomp',
+'fcompp',
+'fcos',
+'fdecstp',
+'fdisi',
+'fdiv',
+'fdivp',
+'fdivr',
+'fdivrp',
+'femms',
+'feni',
+'ffree',
+'fiadd',
+'ficom',
+'ficomp',
+'fidiv',
+'fidivr',
+'fild',
+'fimul',
+'fincstp',
+'finit',
+'fist',
+'fistp',
+'fisttp',
+'fisub',
+'fisubr',
+'fld',
+'fld1',
+'fldcw',
+'fldenv',
+'fldl2e',
+'fldl2t',
+'fldlg2',
+'fldln2',
+'fldpi',
+'fldz',
+'fmul',
+'fmulp',
+'fnclex',
+'fndisi',
+'fneni',
+'fninit',
+'fnop',
+'fnsave',
+'fnstcw',
+'fnstenv',
+'fnstsw',
+'fpatan',
+'fprem',
+'fprem1',
+'fptan',
+'frndint',
+'frstor',
+'fsave',
+'fscale',
+'fsetpm',
+'fsin',
+'fsincos',
+'fsqrt',
+'fst',
+'fstcw',
+'fstenv',
+'fstp',
+'fstsw',
+'fsub',
+'fsubp',
+'fsubr',
+'fsubrp',
+'ftst',
+'fucom',
+'fucomi',
+'fucomip',
+'fucomp',
+'fucompp',
+'fwait',
+'fxam',
+'fxch',
+'fxtract',
+'fyl2x',
+'fyl2xp1',
+'hlt',
+'ibts',
+'icebp',
+'idiv',
+'imul',
+'in',
+'inc',
+'insb',
+'insd',
+'insw',
+'int',
+'int01',
+'int1',
+'int03',
+'int3',
+'into',
+'invd',
+'invlpg',
+'iret',
+'iretd',
+'iretw',
+'iretq',
+'jcxz',
+'jecxz',
+'jrcxz',
+'jmp',
+'lahf',
+'lar',
+'lcall',
+'lds',
+'lea',
+'leave',
+'les',
+'lfs',
+'lgdt',
+'lgs',
+'lidt',
+'ljmp',
+'lldt',
+'lmsw',
+'loadall',
+'loadall286',
+'lock',
+'lodsb',
+'lodsd',
+'lodsw',
+'loop',
+'loope',
+'loopne',
+'loopnz',
+'loopz',
+'lsl',
+'lss',
+'ltr',
+'monitor',
+'mov',
+'movd',
+'movq',
+'movsb',
+'movsd',
+'movsq',
+'movsw',
+'movsx',
+'movzx',
+'mul',
+'mwait',
+'neg',
+'nop',
+'not',
+'or',
+'out',
+'outsb',
+'outsd',
+'outsw',
+'packssdw',
+'packsswb',
+'packuswb',
+'paddb',
+'paddd',
+'paddsb',
+'paddsiw',
+'paddsw',
+'paddusb',
+'paddusw',
+'paddw',
+'pand',
+'pandn',
+'paveb',
+'pavgusb',
+'pcmpeqb',
+'pcmpeqd',
+'pcmpeqw',
+'pcmpgtb',
+'pcmpgtd',
+'pcmpgtw',
+'pdistib',
+'pf2id',
+'pfacc',
+'pfadd',
+'pfcmpeq',
+'pfcmpge',
+'pfcmpgt',
+'pfmax',
+'pfmin',
+'pfmul',
+'pfrcp',
+'pfrcpit1',
+'pfrcpit2',
+'pfrsqit1',
+'pfrsqrt',
+'pfsub',
+'pfsubr',
+'pi2fd',
+'pmachriw',
+'pmaddwd',
+'pmagw',
+'pmulhriw',
+'pmulhrwa',
+'pmulhrwc',
+'pmulhw',
+'pmullw',
+'pmvgezb',
+'pmvlzb',
+'pmvnzb',
+'pmvzb',
+'pop',
+'popa',
+'popad',
+'popaw',
+'popf',
+'popfd',
+'popfw',
+'popfq',
+'por',
+'prefetch',
+'prefetchw',
+'pslld',
+'pslldq',
+'psllq',
+'psllw',
+'psrad',
+'psraw',
+'psrld',
+'psrlq',
+'psrlw',
+'psubb',
+'psubd',
+'psubsb',
+'psubsiw',
+'psubsw',
+'psubusb',
+'psubusw',
+'psubw',
+'punpckhbw',
+'punpckhdq',
+'punpckhwd',
+'punpcklbw',
+'punpckldq',
+'punpcklwd',
+'push',
+'pusha',
+'pushad',
+'pushaw',
+'pushf',
+'pushfd',
+'pushfw',
+'pushfq',
+'pxor',
+'rcl',
+'rcr',
+'rdshr',
+'rdmsr',
+'rdpmc',
+'rdtsc',
+'rep',
+'repe',
+'repne',
+'repnz',
+'repz',
+'ret',
+'retf',
+'retn',
+'rol',
+'ror',
+'rsdc',
+'rsldt',
+'rsm',
+'sahf',
+'sal',
+'salc',
+'sar',
+'sbb',
+'scasb',
+'scasd',
+'scasq',
+'scasw',
+'segcs',
+'segds',
+'seges',
+'segfs',
+'seggs',
+'segss',
+'sgdt',
+'shl',
+'shld',
+'shr',
+'shrd',
+'sidt',
+'sldt',
+'smi',
+'smint',
+'smintold',
+'smsw',
+'stc',
+'std',
+'sti',
+'stosb',
+'stosd',
+'stosw',
+'str',
+'sub',
+'svdc',
+'svldt',
+'svts',
+'syscall',
+'sysenter',
+'sysexit',
+'sysret',
+'test',
+'ud1',
+'ud2',
+'umov',
+'verr',
+'verw',
+'wait',
+'wbinvd',
+'wrshr',
+'wrmsr',
+'xadd',
+'xbts',
+'xchg',
+'xlat',
+'xlatb',
+'xor',
+'xstore',
+'xcryptecb',
+'xcryptcbc',
+'xcryptcfb',
+'xcryptofb',
+'cmov',
+'j',
+'set',
+'addps',
+'addss',
+'andnps',
+'andps',
+'cmpeqps',
+'cmpeqss',
+'cmpleps',
+'cmpless',
+'cmpltps',
+'cmpltss',
+'cmpneqps',
+'cmpneqss',
+'cmpnleps',
+'cmpnless',
+'cmpnltps',
+'cmpnltss',
+'cmpordps',
+'cmpordss',
+'cmpunordps',
+'cmpunordss',
+'cmpps',
+'cmpss',
+'comiss',
+'cvtpi2ps',
+'cvtps2pi',
+'cvtsi2ss',
+'cvtss2si',
+'cvttps2pi',
+'cvttss2si',
+'divps',
+'divss',
+'ldmxcsr',
+'maxps',
+'maxss',
+'minps',
+'minss',
+'movaps',
+'movhps',
+'movlhps',
+'movlps',
+'movhlps',
+'movmskps',
+'movntps',
+'movss',
+'movups',
+'mulps',
+'mulss',
+'orps',
+'rcpps',
+'rcpss',
+'rsqrtps',
+'rsqrtss',
+'shufps',
+'sqrtps',
+'sqrtss',
+'stmxcsr',
+'subps',
+'subss',
+'ucomiss',
+'unpckhps',
+'unpcklps',
+'xorps',
+'fxrstor',
+'fxsave',
+'prefetchnta',
+'prefetcht0',
+'prefetcht1',
+'prefetcht2',
+'sfence',
+'maskmovq',
+'movntq',
+'pavgb',
+'pavgw',
+'pextrw',
+'pinsrw',
+'pmaxsw',
+'pmaxub',
+'pminsw',
+'pminub',
+'pmovmskb',
+'pmulhuw',
+'psadbw',
+'pshufw',
+'pfnacc',
+'pfpnacc',
+'pi2fw',
+'pf2iw',
+'pswapd',
+'ffreep',
+'maskmovdqu',
+'clflush',
+'movntdq',
+'movnti',
+'movntpd',
+'pause',
+'lfence',
+'mfence',
+'movdqa',
+'movdqu',
+'movdq2q',
+'movq2dq',
+'paddq',
+'pmuludq',
+'pshufd',
+'pshufhw',
+'pshuflw',
+'psrldq',
+'psubq',
+'punpckhqdq',
+'punpcklqdq',
+'addpd',
+'addsd',
+'andnpd',
+'andpd',
+'cmpeqpd',
+'cmpeqsd',
+'cmplepd',
+'cmplesd',
+'cmpltpd',
+'cmpltsd',
+'cmpneqpd',
+'cmpneqsd',
+'cmpnlepd',
+'cmpnlesd',
+'cmpnltpd',
+'cmpnltsd',
+'cmpordpd',
+'cmpordsd',
+'cmpunordpd',
+'cmpunordsd',
+'cmppd',
+'comisd',
+'cvtdq2pd',
+'cvtdq2ps',
+'cvtpd2dq',
+'cvtpd2pi',
+'cvtpd2ps',
+'cvtpi2pd',
+'cvtps2dq',
+'cvtps2pd',
+'cvtsd2si',
+'cvtsd2ss',
+'cvtsi2sd',
+'cvtss2sd',
+'cvttpd2pi',
+'cvttpd2dq',
+'cvttps2dq',
+'cvttsd2si',
+'divpd',
+'divsd',
+'maxpd',
+'maxsd',
+'minpd',
+'minsd',
+'movapd',
+'movhpd',
+'movlpd',
+'movmskpd',
+'movupd',
+'mulpd',
+'mulsd',
+'orpd',
+'shufpd',
+'sqrtpd',
+'sqrtsd',
+'subpd',
+'subsd',
+'ucomisd',
+'unpckhpd',
+'unpcklpd',
+'xorpd',
+'addsubpd',
+'addsubps',
+'haddpd',
+'haddps',
+'hsubpd',
+'hsubps',
+'lddqu',
+'movddup',
+'movshdup',
+'movsldup',
+'vmread',
+'vmwrite',
+'vmcall',
+'vmlaunch',
+'vmresume',
+'vmxoff',
+'vmxon',
+'vmclear',
+'vmptrld',
+'vmptrst',
+'vmrun',
+'vmmcall',
+'vmload',
+'vmsave',
+'stgi',
+'clgi',
+'skinit',
+'invlpga',
+'montmul',
+'xsha1',
+'xsha256',
+'dmint',
+'rdm',
+'movabs',
+'movsxd',
+'cqo',
+'cmpxchg16b',
+'movntss',
+'movntsd',
+'insertq',
+'extrq',
+'lzcnt',
+'pabsb',
+'pabsw',
+'pabsd',
+'palignr',
+'phaddw',
+'phaddd',
+'phaddsw',
+'phsubw',
+'phsubd',
+'phsubsw',
+'pmaddubsw',
+'pmulhrsw',
+'pshufb',
+'psignb',
+'psignw',
+'psignd',
+'blendps',
+'blendpd',
+'blendvps',
+'blendvpd',
+'dpps',
+'dppd',
+'extractps',
+'insertps',
+'movntdqa',
+'mpsadbw',
+'packusdw',
+'pblendvb',
+'pblendw',
+'pcmpeqq',
+'pextrb',
+'pextrd',
+'pextrq',
+'phminposuw',
+'pinsrb',
+'pinsrd',
+'pinsrq',
+'pmaxsb',
+'pmaxsd',
+'pmaxud',
+'pmaxuw',
+'pminsb',
+'pminsd',
+'pminuw',
+'pminud',
+'pmovsxbw',
+'pmovsxbd',
+'pmovsxbq',
+'pmovsxwd',
+'pmovsxwq',
+'pmovsxdq',
+'pmovzxbw',
+'pmovzxbd',
+'pmovzxbq',
+'pmovzxwd',
+'pmovzxwq',
+'pmovzxdq',
+'pmuldq',
+'pmulld',
+'ptest',
+'roundps',
+'roundpd',
+'roundss',
+'roundsd',
+'crc32',
+'pcmpestri',
+'pcmpestrm',
+'pcmpistri',
+'pcmpistrm',
+'pcmpgtq',
+'popcnt',
+'aesenc',
+'aesenclast',
+'aesdec',
+'aesdeclast',
+'aesimc',
+'aeskeygenassist',
+'stosq',
+'lodsq',
+'cmpsq'
+);
diff --git a/closures/compiler/x86_64/x8664nop.inc b/closures/compiler/x86_64/x8664nop.inc
new file mode 100644
index 0000000000..011999b15f
--- /dev/null
+++ b/closures/compiler/x86_64/x8664nop.inc
@@ -0,0 +1,2 @@
+{ don't edit, this file is generated from x86ins.dat }
+1215;
diff --git a/closures/compiler/x86_64/x8664op.inc b/closures/compiler/x86_64/x8664op.inc
new file mode 100644
index 0000000000..4070734e54
--- /dev/null
+++ b/closures/compiler/x86_64/x8664op.inc
@@ -0,0 +1,688 @@
+{ don't edit, this file is generated from x86ins.dat }
+(
+A_NONE,
+A_AAA,
+A_AAD,
+A_AAM,
+A_AAS,
+A_ADC,
+A_ADD,
+A_AND,
+A_ARPL,
+A_BOUND,
+A_BSF,
+A_BSR,
+A_BSWAP,
+A_BT,
+A_BTC,
+A_BTR,
+A_BTS,
+A_CALL,
+A_CBW,
+A_CDQ,
+A_CLC,
+A_CLD,
+A_CLI,
+A_CLTS,
+A_CMC,
+A_CMP,
+A_CMPSB,
+A_CMPSD,
+A_CMPSW,
+A_CMPXCHG,
+A_CMPXCHG486,
+A_CMPXCHG8B,
+A_CPUID,
+A_CWD,
+A_CWDE,
+A_DAA,
+A_DAS,
+A_DEC,
+A_DIV,
+A_EMMS,
+A_ENTER,
+A_F2XM1,
+A_FABS,
+A_FADD,
+A_FADDP,
+A_FBLD,
+A_FBSTP,
+A_FCHS,
+A_FCLEX,
+A_FCMOVB,
+A_FCMOVBE,
+A_FCMOVE,
+A_FCMOVNB,
+A_FCMOVNBE,
+A_FCMOVNE,
+A_FCMOVNU,
+A_FCMOVU,
+A_FCOM,
+A_FCOMI,
+A_FCOMIP,
+A_FCOMP,
+A_FCOMPP,
+A_FCOS,
+A_FDECSTP,
+A_FDISI,
+A_FDIV,
+A_FDIVP,
+A_FDIVR,
+A_FDIVRP,
+A_FEMMS,
+A_FENI,
+A_FFREE,
+A_FIADD,
+A_FICOM,
+A_FICOMP,
+A_FIDIV,
+A_FIDIVR,
+A_FILD,
+A_FIMUL,
+A_FINCSTP,
+A_FINIT,
+A_FIST,
+A_FISTP,
+A_FISTTP,
+A_FISUB,
+A_FISUBR,
+A_FLD,
+A_FLD1,
+A_FLDCW,
+A_FLDENV,
+A_FLDL2E,
+A_FLDL2T,
+A_FLDLG2,
+A_FLDLN2,
+A_FLDPI,
+A_FLDZ,
+A_FMUL,
+A_FMULP,
+A_FNCLEX,
+A_FNDISI,
+A_FNENI,
+A_FNINIT,
+A_FNOP,
+A_FNSAVE,
+A_FNSTCW,
+A_FNSTENV,
+A_FNSTSW,
+A_FPATAN,
+A_FPREM,
+A_FPREM1,
+A_FPTAN,
+A_FRNDINT,
+A_FRSTOR,
+A_FSAVE,
+A_FSCALE,
+A_FSETPM,
+A_FSIN,
+A_FSINCOS,
+A_FSQRT,
+A_FST,
+A_FSTCW,
+A_FSTENV,
+A_FSTP,
+A_FSTSW,
+A_FSUB,
+A_FSUBP,
+A_FSUBR,
+A_FSUBRP,
+A_FTST,
+A_FUCOM,
+A_FUCOMI,
+A_FUCOMIP,
+A_FUCOMP,
+A_FUCOMPP,
+A_FWAIT,
+A_FXAM,
+A_FXCH,
+A_FXTRACT,
+A_FYL2X,
+A_FYL2XP1,
+A_HLT,
+A_IBTS,
+A_ICEBP,
+A_IDIV,
+A_IMUL,
+A_IN,
+A_INC,
+A_INSB,
+A_INSD,
+A_INSW,
+A_INT,
+A_INT01,
+A_INT1,
+A_INT03,
+A_INT3,
+A_INTO,
+A_INVD,
+A_INVLPG,
+A_IRET,
+A_IRETD,
+A_IRETW,
+A_IRETQ,
+A_JCXZ,
+A_JECXZ,
+A_JRCXZ,
+A_JMP,
+A_LAHF,
+A_LAR,
+A_LCALL,
+A_LDS,
+A_LEA,
+A_LEAVE,
+A_LES,
+A_LFS,
+A_LGDT,
+A_LGS,
+A_LIDT,
+A_LJMP,
+A_LLDT,
+A_LMSW,
+A_LOADALL,
+A_LOADALL286,
+A_LOCK,
+A_LODSB,
+A_LODSD,
+A_LODSW,
+A_LOOP,
+A_LOOPE,
+A_LOOPNE,
+A_LOOPNZ,
+A_LOOPZ,
+A_LSL,
+A_LSS,
+A_LTR,
+A_MONITOR,
+A_MOV,
+A_MOVD,
+A_MOVQ,
+A_MOVSB,
+A_MOVSD,
+A_MOVSQ,
+A_MOVSW,
+A_MOVSX,
+A_MOVZX,
+A_MUL,
+A_MWAIT,
+A_NEG,
+A_NOP,
+A_NOT,
+A_OR,
+A_OUT,
+A_OUTSB,
+A_OUTSD,
+A_OUTSW,
+A_PACKSSDW,
+A_PACKSSWB,
+A_PACKUSWB,
+A_PADDB,
+A_PADDD,
+A_PADDSB,
+A_PADDSIW,
+A_PADDSW,
+A_PADDUSB,
+A_PADDUSW,
+A_PADDW,
+A_PAND,
+A_PANDN,
+A_PAVEB,
+A_PAVGUSB,
+A_PCMPEQB,
+A_PCMPEQD,
+A_PCMPEQW,
+A_PCMPGTB,
+A_PCMPGTD,
+A_PCMPGTW,
+A_PDISTIB,
+A_PF2ID,
+A_PFACC,
+A_PFADD,
+A_PFCMPEQ,
+A_PFCMPGE,
+A_PFCMPGT,
+A_PFMAX,
+A_PFMIN,
+A_PFMUL,
+A_PFRCP,
+A_PFRCPIT1,
+A_PFRCPIT2,
+A_PFRSQIT1,
+A_PFRSQRT,
+A_PFSUB,
+A_PFSUBR,
+A_PI2FD,
+A_PMACHRIW,
+A_PMADDWD,
+A_PMAGW,
+A_PMULHRIW,
+A_PMULHRWA,
+A_PMULHRWC,
+A_PMULHW,
+A_PMULLW,
+A_PMVGEZB,
+A_PMVLZB,
+A_PMVNZB,
+A_PMVZB,
+A_POP,
+A_POPA,
+A_POPAD,
+A_POPAW,
+A_POPF,
+A_POPFD,
+A_POPFW,
+A_POPFQ,
+A_POR,
+A_PREFETCH,
+A_PREFETCHW,
+A_PSLLD,
+A_PSLLDQ,
+A_PSLLQ,
+A_PSLLW,
+A_PSRAD,
+A_PSRAW,
+A_PSRLD,
+A_PSRLQ,
+A_PSRLW,
+A_PSUBB,
+A_PSUBD,
+A_PSUBSB,
+A_PSUBSIW,
+A_PSUBSW,
+A_PSUBUSB,
+A_PSUBUSW,
+A_PSUBW,
+A_PUNPCKHBW,
+A_PUNPCKHDQ,
+A_PUNPCKHWD,
+A_PUNPCKLBW,
+A_PUNPCKLDQ,
+A_PUNPCKLWD,
+A_PUSH,
+A_PUSHA,
+A_PUSHAD,
+A_PUSHAW,
+A_PUSHF,
+A_PUSHFD,
+A_PUSHFW,
+A_PUSHFQ,
+A_PXOR,
+A_RCL,
+A_RCR,
+A_RDSHR,
+A_RDMSR,
+A_RDPMC,
+A_RDTSC,
+A_REP,
+A_REPE,
+A_REPNE,
+A_REPNZ,
+A_REPZ,
+A_RET,
+A_RETF,
+A_RETN,
+A_ROL,
+A_ROR,
+A_RSDC,
+A_RSLDT,
+A_RSM,
+A_SAHF,
+A_SAL,
+A_SALC,
+A_SAR,
+A_SBB,
+A_SCASB,
+A_SCASD,
+A_SCASQ,
+A_SCASW,
+A_SEGCS,
+A_SEGDS,
+A_SEGES,
+A_SEGFS,
+A_SEGGS,
+A_SEGSS,
+A_SGDT,
+A_SHL,
+A_SHLD,
+A_SHR,
+A_SHRD,
+A_SIDT,
+A_SLDT,
+A_SMI,
+A_SMINT,
+A_SMINTOLD,
+A_SMSW,
+A_STC,
+A_STD,
+A_STI,
+A_STOSB,
+A_STOSD,
+A_STOSW,
+A_STR,
+A_SUB,
+A_SVDC,
+A_SVLDT,
+A_SVTS,
+A_SYSCALL,
+A_SYSENTER,
+A_SYSEXIT,
+A_SYSRET,
+A_TEST,
+A_UD1,
+A_UD2,
+A_UMOV,
+A_VERR,
+A_VERW,
+A_WAIT,
+A_WBINVD,
+A_WRSHR,
+A_WRMSR,
+A_XADD,
+A_XBTS,
+A_XCHG,
+A_XLAT,
+A_XLATB,
+A_XOR,
+A_XSTORE,
+A_XCRYPTECB,
+A_XCRYPTCBC,
+A_XCRYPTCFB,
+A_XCRYPTOFB,
+A_CMOVcc,
+A_Jcc,
+A_SETcc,
+A_ADDPS,
+A_ADDSS,
+A_ANDNPS,
+A_ANDPS,
+A_CMPEQPS,
+A_CMPEQSS,
+A_CMPLEPS,
+A_CMPLESS,
+A_CMPLTPS,
+A_CMPLTSS,
+A_CMPNEQPS,
+A_CMPNEQSS,
+A_CMPNLEPS,
+A_CMPNLESS,
+A_CMPNLTPS,
+A_CMPNLTSS,
+A_CMPORDPS,
+A_CMPORDSS,
+A_CMPUNORDPS,
+A_CMPUNORDSS,
+A_CMPPS,
+A_CMPSS,
+A_COMISS,
+A_CVTPI2PS,
+A_CVTPS2PI,
+A_CVTSI2SS,
+A_CVTSS2SI,
+A_CVTTPS2PI,
+A_CVTTSS2SI,
+A_DIVPS,
+A_DIVSS,
+A_LDMXCSR,
+A_MAXPS,
+A_MAXSS,
+A_MINPS,
+A_MINSS,
+A_MOVAPS,
+A_MOVHPS,
+A_MOVLHPS,
+A_MOVLPS,
+A_MOVHLPS,
+A_MOVMSKPS,
+A_MOVNTPS,
+A_MOVSS,
+A_MOVUPS,
+A_MULPS,
+A_MULSS,
+A_ORPS,
+A_RCPPS,
+A_RCPSS,
+A_RSQRTPS,
+A_RSQRTSS,
+A_SHUFPS,
+A_SQRTPS,
+A_SQRTSS,
+A_STMXCSR,
+A_SUBPS,
+A_SUBSS,
+A_UCOMISS,
+A_UNPCKHPS,
+A_UNPCKLPS,
+A_XORPS,
+A_FXRSTOR,
+A_FXSAVE,
+A_PREFETCHNTA,
+A_PREFETCHT0,
+A_PREFETCHT1,
+A_PREFETCHT2,
+A_SFENCE,
+A_MASKMOVQ,
+A_MOVNTQ,
+A_PAVGB,
+A_PAVGW,
+A_PEXTRW,
+A_PINSRW,
+A_PMAXSW,
+A_PMAXUB,
+A_PMINSW,
+A_PMINUB,
+A_PMOVMSKB,
+A_PMULHUW,
+A_PSADBW,
+A_PSHUFW,
+A_PFNACC,
+A_PFPNACC,
+A_PI2FW,
+A_PF2IW,
+A_PSWAPD,
+A_FFREEP,
+A_MASKMOVDQU,
+A_CLFLUSH,
+A_MOVNTDQ,
+A_MOVNTI,
+A_MOVNTPD,
+A_PAUSE,
+A_LFENCE,
+A_MFENCE,
+A_MOVDQA,
+A_MOVDQU,
+A_MOVDQ2Q,
+A_MOVQ2DQ,
+A_PADDQ,
+A_PMULUDQ,
+A_PSHUFD,
+A_PSHUFHW,
+A_PSHUFLW,
+A_PSRLDQ,
+A_PSUBQ,
+A_PUNPCKHQDQ,
+A_PUNPCKLQDQ,
+A_ADDPD,
+A_ADDSD,
+A_ANDNPD,
+A_ANDPD,
+A_CMPEQPD,
+A_CMPEQSD,
+A_CMPLEPD,
+A_CMPLESD,
+A_CMPLTPD,
+A_CMPLTSD,
+A_CMPNEQPD,
+A_CMPNEQSD,
+A_CMPNLEPD,
+A_CMPNLESD,
+A_CMPNLTPD,
+A_CMPNLTSD,
+A_CMPORDPD,
+A_CMPORDSD,
+A_CMPUNORDPD,
+A_CMPUNORDSD,
+A_CMPPD,
+A_COMISD,
+A_CVTDQ2PD,
+A_CVTDQ2PS,
+A_CVTPD2DQ,
+A_CVTPD2PI,
+A_CVTPD2PS,
+A_CVTPI2PD,
+A_CVTPS2DQ,
+A_CVTPS2PD,
+A_CVTSD2SI,
+A_CVTSD2SS,
+A_CVTSI2SD,
+A_CVTSS2SD,
+A_CVTTPD2PI,
+A_CVTTPD2DQ,
+A_CVTTPS2DQ,
+A_CVTTSD2SI,
+A_DIVPD,
+A_DIVSD,
+A_MAXPD,
+A_MAXSD,
+A_MINPD,
+A_MINSD,
+A_MOVAPD,
+A_MOVHPD,
+A_MOVLPD,
+A_MOVMSKPD,
+A_MOVUPD,
+A_MULPD,
+A_MULSD,
+A_ORPD,
+A_SHUFPD,
+A_SQRTPD,
+A_SQRTSD,
+A_SUBPD,
+A_SUBSD,
+A_UCOMISD,
+A_UNPCKHPD,
+A_UNPCKLPD,
+A_XORPD,
+A_ADDSUBPD,
+A_ADDSUBPS,
+A_HADDPD,
+A_HADDPS,
+A_HSUBPD,
+A_HSUBPS,
+A_LDDQU,
+A_MOVDDUP,
+A_MOVSHDUP,
+A_MOVSLDUP,
+A_VMREAD,
+A_VMWRITE,
+A_VMCALL,
+A_VMLAUNCH,
+A_VMRESUME,
+A_VMXOFF,
+A_VMXON,
+A_VMCLEAR,
+A_VMPTRLD,
+A_VMPTRST,
+A_VMRUN,
+A_VMMCALL,
+A_VMLOAD,
+A_VMSAVE,
+A_STGI,
+A_CLGI,
+A_SKINIT,
+A_INVLPGA,
+A_MONTMUL,
+A_XSHA1,
+A_XSHA256,
+A_DMINT,
+A_RDM,
+A_MOVABS,
+A_MOVSXD,
+A_CQO,
+A_CMPXCHG16B,
+A_MOVNTSS,
+A_MOVNTSD,
+A_INSERTQ,
+A_EXTRQ,
+A_LZCNT,
+A_PABSB,
+A_PABSW,
+A_PABSD,
+A_PALIGNR,
+A_PHADDW,
+A_PHADDD,
+A_PHADDSW,
+A_PHSUBW,
+A_PHSUBD,
+A_PHSUBSW,
+A_PMADDUBSW,
+A_PMULHRSW,
+A_PSHUFB,
+A_PSIGNB,
+A_PSIGNW,
+A_PSIGND,
+A_BLENDPS,
+A_BLENDPD,
+A_BLENDVPS,
+A_BLENDVPD,
+A_DPPS,
+A_DPPD,
+A_EXTRACTPS,
+A_INSERTPS,
+A_MOVNTDQA,
+A_MPSADBW,
+A_PACKUSDW,
+A_PBLENDVB,
+A_PBLENDW,
+A_PCMPEQQ,
+A_PEXTRB,
+A_PEXTRD,
+A_PEXTRQ,
+A_PHMINPOSUW,
+A_PINSRB,
+A_PINSRD,
+A_PINSRQ,
+A_PMAXSB,
+A_PMAXSD,
+A_PMAXUD,
+A_PMAXUW,
+A_PMINSB,
+A_PMINSD,
+A_PMINUW,
+A_PMINUD,
+A_PMOVSXBW,
+A_PMOVSXBD,
+A_PMOVSXBQ,
+A_PMOVSXWD,
+A_PMOVSXWQ,
+A_PMOVSXDQ,
+A_PMOVZXBW,
+A_PMOVZXBD,
+A_PMOVZXBQ,
+A_PMOVZXWD,
+A_PMOVZXWQ,
+A_PMOVZXDQ,
+A_PMULDQ,
+A_PMULLD,
+A_PTEST,
+A_ROUNDPS,
+A_ROUNDPD,
+A_ROUNDSS,
+A_ROUNDSD,
+A_CRC32,
+A_PCMPESTRI,
+A_PCMPESTRM,
+A_PCMPISTRI,
+A_PCMPISTRM,
+A_PCMPGTQ,
+A_POPCNT,
+A_AESENC,
+A_AESENCLAST,
+A_AESDEC,
+A_AESDECLAST,
+A_AESIMC,
+A_AESKEYGENASSIST,
+A_STOSQ,
+A_LODSQ,
+A_CMPSQ
+);
diff --git a/closures/compiler/x86_64/x8664pro.inc b/closures/compiler/x86_64/x8664pro.inc
new file mode 100644
index 0000000000..4a8f2f7fa4
--- /dev/null
+++ b/closures/compiler/x86_64/x8664pro.inc
@@ -0,0 +1,688 @@
+{ don't edit, this file is generated from x86ins.dat }
+(
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_MEAX, Ch_WFlags, Ch_None)),
+(Ch: (Ch_MEAX, Ch_WFlags, Ch_None)),
+(Ch: (Ch_MEAX, Ch_WFlags, Ch_None)),
+(Ch: (Ch_MEAX, Ch_WFlags, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_RWFlags)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_WFlags)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_WFlags)),
+(Ch: (Ch_WFlags, Ch_None, Ch_None)),
+(Ch: (Ch_Rop1, Ch_None, Ch_None)),
+(Ch: (Ch_Wop2, Ch_WFlags, Ch_Rop1)),
+(Ch: (Ch_Wop2, Ch_WFlags, Ch_Rop1)),
+(Ch: (Ch_MOp1, Ch_None, Ch_None)),
+(Ch: (Ch_WFlags, Ch_Rop1, Ch_Rop2)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_WFlags)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_WFlags)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_WFlags)),
+(Ch: (Ch_ROp1, Ch_All, Ch_None)),
+(Ch: (Ch_MEAX, Ch_None, Ch_None)),
+(Ch: (Ch_MEAX, Ch_WEDX, Ch_None)),
+(Ch: (Ch_WFlags, Ch_None, Ch_None)),
+(Ch: (Ch_CDirFlag, Ch_None, Ch_None)),
+(Ch: (Ch_WFlags, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_WFlags, Ch_None, Ch_None)),
+(Ch: (Ch_ROp1, Ch_ROp2, Ch_WFlags)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_none)),
+(Ch: (Ch_MEAX, Ch_WEDX, Ch_None)),
+(Ch: (Ch_MEAX, Ch_None, Ch_None)),
+(Ch: (Ch_MEAX, Ch_None, Ch_None)),
+(Ch: (Ch_MEAX, Ch_None, Ch_None)),
+(Ch: (Ch_Mop1, Ch_WFlags, Ch_None)),
+(Ch: (Ch_RWEAX, Ch_WEDX, Ch_WFlags)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_RWESP, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_ROp1, Ch_None)),
+(Ch: (Ch_FPU, Ch_ROp1, Ch_None)),
+(Ch: (Ch_Rop1, Ch_FPU, Ch_None)),
+(Ch: (Ch_Wop1, Ch_FPU, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_RFLAGS, Ch_None)),
+(Ch: (Ch_FPU, Ch_RFLAGS, Ch_None)),
+(Ch: (Ch_FPU, Ch_RFLAGS, Ch_None)),
+(Ch: (Ch_FPU, Ch_RFLAGS, Ch_None)),
+(Ch: (Ch_FPU, Ch_RFLAGS, Ch_None)),
+(Ch: (Ch_FPU, Ch_RFLAGS, Ch_None)),
+(Ch: (Ch_FPU, Ch_RFLAGS, Ch_None)),
+(Ch: (Ch_FPU, Ch_RFLAGS, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_WFLAGS, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_WFLAGS, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_ROp1, Ch_None)),
+(Ch: (Ch_FPU, Ch_ROp1, Ch_None)),
+(Ch: (Ch_FPU, Ch_ROp1, Ch_None)),
+(Ch: (Ch_FPU, Ch_ROp1, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_ROp1, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_ROp1, Ch_None)),
+(Ch: (Ch_FPU, Ch_ROp1, Ch_None)),
+(Ch: (Ch_FPU, Ch_ROp1, Ch_None)),
+(Ch: (Ch_FPU, Ch_ROp1, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_Wop1, Ch_None, Ch_None)),
+(Ch: (Ch_Wop1, Ch_None, Ch_None)),
+(Ch: (Ch_Wop1, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_ROp1, Ch_None)),
+(Ch: (Ch_FPU, Ch_ROp1, Ch_None)),
+(Ch: (Ch_Rop1, Ch_FPU, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_ROp1, Ch_FPU, Ch_None)),
+(Ch: (Ch_ROp1, Ch_FPU, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_Wop1, Ch_None, Ch_None)),
+(Ch: (Ch_Wop1, Ch_None, Ch_None)),
+(Ch: (Ch_Wop1, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_Wop1, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_Wop1, Ch_None, Ch_None)),
+(Ch: (Ch_Wop1, Ch_None, Ch_None)),
+(Ch: (Ch_Wop1, Ch_None, Ch_None)),
+(Ch: (Ch_Wop1, Ch_FPU, Ch_None)),
+(Ch: (Ch_Wop1, Ch_None, Ch_None)),
+(Ch: (Ch_ROp1, Ch_FPU, Ch_None)),
+(Ch: (Ch_ROp1, Ch_FPU, Ch_None)),
+(Ch: (Ch_ROp1, Ch_FPU, Ch_None)),
+(Ch: (Ch_ROp1, Ch_FPU, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_WFLAGS, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_WFLAGS, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_FPU, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_RWEAX, Ch_WEDX, Ch_WFlags)),
+(Ch: (Ch_RWEAX, Ch_WEDX, Ch_WFlags)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop1, Ch_WFlags, Ch_None)),
+(Ch: (Ch_WMemEDI, Ch_RWEDI, Ch_REDX)),
+(Ch: (Ch_WMemEDI, Ch_RWEDI, Ch_REDX)),
+(Ch: (Ch_WMemEDI, Ch_RWEDI, Ch_REDX)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_RECX, Ch_None, Ch_None)),
+(Ch: (Ch_RECX, Ch_None, Ch_None)),
+(Ch: (Ch_RECX, Ch_None, Ch_None)),
+(Ch: (Ch_ROp1, Ch_None, Ch_None)),
+(Ch: (Ch_WEAX, Ch_RFlags, Ch_None)),
+(Ch: (Ch_Wop2, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_RWESP, Ch_WEBP, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_ROp1, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_WEAX, Ch_RWESI, Ch_None)),
+(Ch: (Ch_WEAX, Ch_RWESI, Ch_None)),
+(Ch: (Ch_WEAX, Ch_RWESI, Ch_None)),
+(Ch: (Ch_RWECX, Ch_None, Ch_None)),
+(Ch: (Ch_RWECX, Ch_RFlags, Ch_None)),
+(Ch: (Ch_RWECX, Ch_RFlags, Ch_None)),
+(Ch: (Ch_RWECX, Ch_RFlags, Ch_None)),
+(Ch: (Ch_RWECX, Ch_RFlags, Ch_None)),
+(Ch: (Ch_Wop2, Ch_WFlags, Ch_None)),
+(Ch: (Ch_Wop2, Ch_ROP1, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Rop1, Ch_Wop2, Ch_None)),
+(Ch: (Ch_Rop1, Ch_Wop2, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_RWEAX, Ch_WEDX, Ch_WFlags)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_Mop1, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_Mop1, Ch_WFlags, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_WFlags)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Wop1, Ch_RWESP, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_RWESP, Ch_WFlags, Ch_None)),
+(Ch: (Ch_RWESP, Ch_WFlags, Ch_None)),
+(Ch: (Ch_RWESP, Ch_WFLAGS, Ch_None)),
+(Ch: (Ch_RWESP, Ch_WFlags, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Rop1, Ch_RWESP, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_RWESP, Ch_RFlags, Ch_None)),
+(Ch: (Ch_RWESP, Ch_RFlags, Ch_None)),
+(Ch: (Ch_RWESP, Ch_RFLAGS, Ch_None)),
+(Ch: (Ch_RWESP, Ch_RFlags, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_RWFlags)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_RWFlags)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_WEAX, Ch_WEDX, Ch_None)),
+(Ch: (Ch_WEAX, Ch_WEDX, Ch_None)),
+(Ch: (Ch_WEAX, Ch_WEDX, Ch_None)),
+(Ch: (Ch_RWECX, Ch_RWFlags, Ch_None)),
+(Ch: (Ch_RWECX, Ch_RWFlags, Ch_None)),
+(Ch: (Ch_RWECX, Ch_RWFlags, Ch_None)),
+(Ch: (Ch_RWECX, Ch_RWFLAGS, Ch_None)),
+(Ch: (Ch_RWECX, Ch_RWFLAGS, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_RWFlags)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_RWFlags)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_WFlags, Ch_REAX, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_RWFlags)),
+(Ch: (Ch_WEAX, Ch_RFLAGS, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_WFlags)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_RWFlags)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_Wop1, Ch_None, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_WFlags)),
+(Ch: (Ch_MOp3, Ch_RWFlags, Ch_Rop2)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_WFlags)),
+(Ch: (Ch_MOp3, Ch_RWFlags, Ch_Rop2)),
+(Ch: (Ch_Wop1, Ch_None, Ch_None)),
+(Ch: (Ch_Wop1, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Wop1, Ch_None, Ch_None)),
+(Ch: (Ch_WFlags, Ch_None, Ch_None)),
+(Ch: (Ch_SDirFlag, Ch_None, Ch_None)),
+(Ch: (Ch_WFlags, Ch_None, Ch_None)),
+(Ch: (Ch_REAX, Ch_WMemEDI, Ch_RWEDI)),
+(Ch: (Ch_REAX, Ch_WMemEDI, Ch_RWEDI)),
+(Ch: (Ch_REAX, Ch_WMemEDI, Ch_RWEDI)),
+(Ch: (Ch_Wop1, Ch_None, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_WFlags)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_WFlags, Ch_Rop1, Ch_Rop2)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_WFlags, Ch_None, Ch_None)),
+(Ch: (Ch_WFlags, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_None, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_RWop1, Ch_RWop2, Ch_None)),
+(Ch: (Ch_WEAX, Ch_REBX, Ch_None)),
+(Ch: (Ch_WEAX, Ch_REBX, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_WFlags)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_ROp1, Ch_WOp2, Ch_RFLAGS)),
+(Ch: (Ch_RFLAGS, Ch_None, Ch_None)),
+(Ch: (Ch_RFLAGS, Ch_WOp1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_WFlags)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_ROp1, Ch_WOp2, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_WFlags)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_WFlags)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_ROp1, Ch_WOp2, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop3, Ch_Rop2, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Rop1, Ch_Rop2, Ch_WFlags)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Mop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_Wop2, Ch_Rop1, Ch_None)),
+(Ch: (Ch_MRAX, Ch_WRDX, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_Mop1, Ch_Rop2, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None)),
+(Ch: (Ch_RRAX, Ch_WMemEDI, Ch_RWRDI)),
+(Ch: (Ch_WRAX, Ch_RWRSI, Ch_None)),
+(Ch: (Ch_All, Ch_None, Ch_None))
+);
diff --git a/closures/compiler/x86_64/x8664tab.inc b/closures/compiler/x86_64/x8664tab.inc
new file mode 100644
index 0000000000..188e47e1ca
--- /dev/null
+++ b/closures/compiler/x86_64/x8664tab.inc
@@ -0,0 +1,8508 @@
+{ don't edit, this file is generated from x86ins.dat }
+(
+ (
+ opcode : A_NONE;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #0;
+ flags : if_none
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_rm_gpr,ot_reg16 or ot_bits32 or ot_bits64,ot_none,ot_none);
+ code : #208#1#17#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_reg16 or ot_bits32 or ot_bits64,ot_rm_gpr,ot_none,ot_none);
+ code : #208#1#19#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_reg8,ot_none,ot_none);
+ code : #1#16#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_reg8,ot_rm_gpr or ot_bits8,ot_none,ot_none);
+ code : #1#18#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_immediate or ot_bits8 or ot_signed,ot_none,ot_none);
+ code : #208#1#131#130#13;
+ flags : if_8086
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_reg_eax,ot_immediate,ot_none,ot_none);
+ code : #213#1#21#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_reg_rax,ot_immediate,ot_none,ot_none);
+ code : #214#1#21#173;
+ flags : if_x86_64 or if_sm
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits32,ot_immediate,ot_none,ot_none);
+ code : #213#1#129#130#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits64,ot_immediate,ot_none,ot_none);
+ code : #214#1#129#130#173;
+ flags : if_x86_64 or if_sm
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_reg_ax,ot_immediate,ot_none,ot_none);
+ code : #212#1#21#25;
+ flags : if_8086 or if_sw
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16,ot_immediate,ot_none,ot_none);
+ code : #212#1#129#130#25;
+ flags : if_8086 or if_sw
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_reg_al,ot_immediate,ot_none,ot_none);
+ code : #1#20#17;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_immediate,ot_none,ot_none);
+ code : #1#128#130#17;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_rm_gpr,ot_reg16 or ot_bits32 or ot_bits64,ot_none,ot_none);
+ code : #208#1#1#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_reg16 or ot_bits32 or ot_bits64,ot_rm_gpr,ot_none,ot_none);
+ code : #208#1#3#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_reg8,ot_none,ot_none);
+ code : #1#0#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_reg8,ot_rm_gpr or ot_bits8,ot_none,ot_none);
+ code : #1#2#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_immediate or ot_bits8 or ot_signed,ot_none,ot_none);
+ code : #208#1#131#128#13;
+ flags : if_8086
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_reg_eax,ot_immediate,ot_none,ot_none);
+ code : #208#1#5#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_reg_rax,ot_immediate,ot_none,ot_none);
+ code : #214#1#5#173;
+ flags : if_x86_64 or if_sm
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits32,ot_immediate,ot_none,ot_none);
+ code : #213#1#129#128#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits64,ot_immediate,ot_none,ot_none);
+ code : #214#1#129#128#173;
+ flags : if_x86_64 or if_sm
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_reg_ax,ot_immediate,ot_none,ot_none);
+ code : #212#1#5#25;
+ flags : if_8086 or if_sw
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16,ot_immediate,ot_none,ot_none);
+ code : #212#1#129#128#25;
+ flags : if_8086 or if_sw
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_reg_al,ot_immediate,ot_none,ot_none);
+ code : #1#4#17;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_immediate,ot_none,ot_none);
+ code : #1#128#128#17;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_rm_gpr,ot_reg16 or ot_bits32 or ot_bits64,ot_none,ot_none);
+ code : #208#1#33#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_reg16 or ot_bits32 or ot_bits64,ot_rm_gpr,ot_none,ot_none);
+ code : #208#1#35#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_reg8,ot_none,ot_none);
+ code : #1#32#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_reg8,ot_rm_gpr or ot_bits8,ot_none,ot_none);
+ code : #1#34#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_immediate or ot_bits8 or ot_signed,ot_none,ot_none);
+ code : #208#1#131#132#13;
+ flags : if_8086
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_reg_eax,ot_immediate,ot_none,ot_none);
+ code : #213#1#37#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_reg_rax,ot_immediate,ot_none,ot_none);
+ code : #214#1#37#173;
+ flags : if_x86_64 or if_sm
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits32,ot_immediate,ot_none,ot_none);
+ code : #213#1#129#132#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits64,ot_immediate,ot_none,ot_none);
+ code : #214#1#129#132#173;
+ flags : if_x86_64 or if_sm
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_reg_ax,ot_immediate,ot_none,ot_none);
+ code : #212#1#37#25;
+ flags : if_8086 or if_sw
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16,ot_immediate,ot_none,ot_none);
+ code : #212#1#129#132#25;
+ flags : if_8086 or if_sw
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_reg_al,ot_immediate,ot_none,ot_none);
+ code : #1#36#17;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_immediate,ot_none,ot_none);
+ code : #1#128#132#17;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_BSF;
+ ops : 2;
+ optypes : (ot_reg16 or ot_bits32 or ot_bits64,ot_rm_gpr,ot_none,ot_none);
+ code : #208#2#15#188#72;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_BSR;
+ ops : 2;
+ optypes : (ot_reg16 or ot_bits32 or ot_bits64,ot_rm_gpr,ot_none,ot_none);
+ code : #208#2#15#189#72;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_BSWAP;
+ ops : 1;
+ optypes : (ot_reg32 or ot_bits64,ot_none,ot_none,ot_none);
+ code : #208#1#15#8#200;
+ flags : if_486
+ ),
+ (
+ opcode : A_BT;
+ ops : 2;
+ optypes : (ot_rm_gpr,ot_reg16 or ot_bits32 or ot_bits64,ot_none,ot_none);
+ code : #208#2#15#163#65;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_BT;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_immediate,ot_none,ot_none);
+ code : #208#2#15#186#132#21;
+ flags : if_386 or if_sb
+ ),
+ (
+ opcode : A_BTC;
+ ops : 2;
+ optypes : (ot_rm_gpr,ot_reg16 or ot_bits32 or ot_bits64,ot_none,ot_none);
+ code : #208#2#15#187#65;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_BTC;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_immediate,ot_none,ot_none);
+ code : #208#2#15#186#135#21;
+ flags : if_386 or if_sb
+ ),
+ (
+ opcode : A_BTR;
+ ops : 2;
+ optypes : (ot_rm_gpr,ot_reg16 or ot_bits32 or ot_bits64,ot_none,ot_none);
+ code : #208#2#15#179#65;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_BTR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_immediate,ot_none,ot_none);
+ code : #208#2#15#186#134#21;
+ flags : if_386 or if_sb
+ ),
+ (
+ opcode : A_BTS;
+ ops : 2;
+ optypes : (ot_rm_gpr,ot_reg16 or ot_bits32 or ot_bits64,ot_none,ot_none);
+ code : #208#2#15#171#65;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_BTS;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_immediate,ot_none,ot_none);
+ code : #208#2#15#186#133#21;
+ flags : if_386 or if_sb
+ ),
+ (
+ opcode : A_CALL;
+ ops : 1;
+ optypes : (ot_rm_gpr or ot_bits64,ot_none,ot_none,ot_none);
+ code : #221#1#255#130;
+ flags : if_x86_64
+ ),
+ (
+ opcode : A_CALL;
+ ops : 1;
+ optypes : (ot_rm_gpr or ot_bits16,ot_none,ot_none,ot_none);
+ code : #212#1#255#130;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CALL;
+ ops : 1;
+ optypes : (ot_immediate,ot_none,ot_none,ot_none);
+ code : #208#1#232#52;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CALL;
+ ops : 1;
+ optypes : (ot_immediate or ot_near,ot_none,ot_none,ot_none);
+ code : #208#1#232#52;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CALL;
+ ops : 1;
+ optypes : (ot_memory or ot_near,ot_none,ot_none,ot_none);
+ code : #208#1#255#130;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CALL;
+ ops : 1;
+ optypes : (ot_memory or ot_far,ot_none,ot_none,ot_none);
+ code : #208#1#255#131;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CBW;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #212#1#152;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CDQ;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #213#1#153;
+ flags : if_386
+ ),
+ (
+ opcode : A_CLC;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#248;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CLD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#252;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CLI;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#250;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CLTS;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#15#6;
+ flags : if_286 or if_priv
+ ),
+ (
+ opcode : A_CMC;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#245;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_rm_gpr,ot_reg16 or ot_bits32 or ot_bits64,ot_none,ot_none);
+ code : #208#1#57#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_reg16 or ot_bits32 or ot_bits64,ot_rm_gpr,ot_none,ot_none);
+ code : #208#1#59#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_reg8,ot_none,ot_none);
+ code : #1#56#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_reg8,ot_rm_gpr or ot_bits8,ot_none,ot_none);
+ code : #1#58#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_immediate or ot_bits8 or ot_signed,ot_none,ot_none);
+ code : #208#1#131#135#13;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_reg_eax,ot_immediate,ot_none,ot_none);
+ code : #213#1#61#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_reg_rax,ot_immediate,ot_none,ot_none);
+ code : #214#1#61#173;
+ flags : if_x86_64 or if_sm
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits32,ot_immediate,ot_none,ot_none);
+ code : #213#1#129#135#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits64,ot_immediate,ot_none,ot_none);
+ code : #214#1#129#135#173;
+ flags : if_x86_64 or if_sm
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_reg_ax,ot_immediate,ot_none,ot_none);
+ code : #212#1#61#25;
+ flags : if_8086 or if_sw
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16,ot_immediate,ot_none,ot_none);
+ code : #212#1#129#135#25;
+ flags : if_8086 or if_sw
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_reg_al,ot_immediate,ot_none,ot_none);
+ code : #1#60#17;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_immediate,ot_none,ot_none);
+ code : #1#128#135#17;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits32,ot_none,ot_none);
+ code : #213#1#129#135#33;
+ flags : if_386 or if_sd
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits16,ot_none,ot_none);
+ code : #212#1#129#135#25;
+ flags : if_8086 or if_sw
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits8,ot_none,ot_none);
+ code : #1#128#135#17;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_CMPSB;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #218#1#166;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CMPSD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #218#213#1#167;
+ flags : if_386
+ ),
+ (
+ opcode : A_CMPSD;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_immediate,ot_none);
+ code : #220#2#15#194#72#22;
+ flags : if_willamette or if_sse2 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_CMPSW;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #218#212#1#167;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CMPXCHG;
+ ops : 2;
+ optypes : (ot_rm_gpr,ot_reg16 or ot_bits32 or ot_bits64,ot_none,ot_none);
+ code : #208#2#15#177#65;
+ flags : if_pent or if_sm
+ ),
+ (
+ opcode : A_CMPXCHG;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_reg8,ot_none,ot_none);
+ code : #2#15#176#65;
+ flags : if_pent
+ ),
+ (
+ opcode : A_CMPXCHG486;
+ ops : 2;
+ optypes : (ot_rm_gpr,ot_reg16 or ot_bits32 or ot_bits64,ot_none,ot_none);
+ code : #208#2#15#167#65;
+ flags : if_486 or if_sm
+ ),
+ (
+ opcode : A_CMPXCHG486;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_reg8,ot_none,ot_none);
+ code : #2#15#166#65;
+ flags : if_486 or if_undoc
+ ),
+ (
+ opcode : A_CMPXCHG8B;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #2#15#199#129;
+ flags : if_pent
+ ),
+ (
+ opcode : A_CPUID;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#15#162;
+ flags : if_pent
+ ),
+ (
+ opcode : A_CWD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #212#1#153;
+ flags : if_8086
+ ),
+ (
+ opcode : A_CWDE;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #213#1#152;
+ flags : if_386
+ ),
+ (
+ opcode : A_DEC;
+ ops : 1;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_none,ot_none,ot_none);
+ code : #208#1#255#129;
+ flags : if_8086
+ ),
+ (
+ opcode : A_DEC;
+ ops : 1;
+ optypes : (ot_rm_gpr or ot_bits8,ot_none,ot_none,ot_none);
+ code : #1#254#129;
+ flags : if_8086
+ ),
+ (
+ opcode : A_DIV;
+ ops : 1;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_none,ot_none,ot_none);
+ code : #208#1#247#134;
+ flags : if_8086
+ ),
+ (
+ opcode : A_DIV;
+ ops : 1;
+ optypes : (ot_rm_gpr or ot_bits8,ot_none,ot_none,ot_none);
+ code : #1#246#134;
+ flags : if_8086
+ ),
+ (
+ opcode : A_EMMS;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#15#119;
+ flags : if_pent or if_mmx
+ ),
+ (
+ opcode : A_ENTER;
+ ops : 2;
+ optypes : (ot_immediate,ot_immediate,ot_none,ot_none);
+ code : #1#200#24#21;
+ flags : if_186
+ ),
+ (
+ opcode : A_F2XM1;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#217#240;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FABS;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#217#225;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FADD;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+ code : #1#216#128;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FADD;
+ ops : 1;
+ optypes : (ot_memory or ot_bits64,ot_none,ot_none,ot_none);
+ code : #1#220#128;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FADD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#222#193;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FADD;
+ ops : 1;
+ optypes : (ot_fpureg or ot_to,ot_none,ot_none,ot_none);
+ code : #1#220#8#192;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FADD;
+ ops : 2;
+ optypes : (ot_fpureg,ot_fpu0,ot_none,ot_none);
+ code : #1#220#8#192;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FADD;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#216#8#192;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FADD;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none,ot_none);
+ code : #1#216#9#192;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FADDP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#222#193;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FADDP;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#222#8#192;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FADDP;
+ ops : 2;
+ optypes : (ot_fpureg,ot_fpu0,ot_none,ot_none);
+ code : #1#222#8#192;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FBLD;
+ ops : 1;
+ optypes : (ot_memory or ot_bits80,ot_none,ot_none,ot_none);
+ code : #1#223#132;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FBLD;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #1#223#132;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FBSTP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits80,ot_none,ot_none,ot_none);
+ code : #1#223#134;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FBSTP;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #1#223#134;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FCHS;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#217#224;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FCLEX;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #3#155#219#226;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVB;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#218#193;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVB;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#218#8#192;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVB;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none,ot_none);
+ code : #1#218#9#192;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVBE;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#218#209;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVBE;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#218#8#208;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVBE;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none,ot_none);
+ code : #1#218#9#208;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVE;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#218#201;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVE;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#218#8#200;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVE;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none,ot_none);
+ code : #1#218#9#200;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVNB;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#219#193;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVNB;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#219#8#192;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVNB;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none,ot_none);
+ code : #1#219#9#192;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVNBE;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#219#209;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVNBE;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#219#8#208;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVNBE;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none,ot_none);
+ code : #1#219#9#208;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVNE;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#219#201;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVNE;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#219#8#200;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVNE;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none,ot_none);
+ code : #1#219#9#200;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVNU;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#219#217;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVNU;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#219#8#216;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVNU;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none,ot_none);
+ code : #1#219#9#216;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVU;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#218#217;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVU;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#218#8#216;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCMOVU;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none,ot_none);
+ code : #1#218#9#216;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCOM;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+ code : #1#216#130;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FCOM;
+ ops : 1;
+ optypes : (ot_memory or ot_bits64,ot_none,ot_none,ot_none);
+ code : #1#220#130;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FCOM;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#216#209;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FCOM;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#216#8#208;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FCOM;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none,ot_none);
+ code : #1#216#9#208;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FCOMI;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#219#241;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCOMI;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#219#8#240;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCOMI;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none,ot_none);
+ code : #1#219#9#240;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCOMIP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#223#241;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCOMIP;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#223#8#240;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCOMIP;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none,ot_none);
+ code : #1#223#9#240;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FCOMP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+ code : #1#216#131;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FCOMP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits64,ot_none,ot_none,ot_none);
+ code : #1#220#131;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FCOMP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#216#217;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FCOMP;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#216#8#216;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FCOMP;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none,ot_none);
+ code : #1#216#9#216;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FCOMPP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#222#217;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FCOS;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#217#255;
+ flags : if_386 or if_fpu
+ ),
+ (
+ opcode : A_FDECSTP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#217#246;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDISI;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #3#155#219#225;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIV;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+ code : #1#216#134;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIV;
+ ops : 1;
+ optypes : (ot_memory or ot_bits64,ot_none,ot_none,ot_none);
+ code : #1#220#134;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIV;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#220#241;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIV;
+ ops : 1;
+ optypes : (ot_fpureg or ot_to,ot_none,ot_none,ot_none);
+ code : #1#220#8#240;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIV;
+ ops : 2;
+ optypes : (ot_fpureg,ot_fpu0,ot_none,ot_none);
+ code : #1#220#8#240;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIV;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#216#8#240;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIV;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none,ot_none);
+ code : #1#216#9#240;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIVP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#222#241;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIVP;
+ ops : 2;
+ optypes : (ot_fpureg,ot_fpu0,ot_none,ot_none);
+ code : #1#222#8#240;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIVP;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#222#8#240;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIVR;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+ code : #1#216#135;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIVR;
+ ops : 1;
+ optypes : (ot_memory or ot_bits64,ot_none,ot_none,ot_none);
+ code : #1#220#135;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIVR;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#220#249;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIVR;
+ ops : 1;
+ optypes : (ot_fpureg or ot_to,ot_none,ot_none,ot_none);
+ code : #1#220#8#248;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIVR;
+ ops : 2;
+ optypes : (ot_fpureg,ot_fpu0,ot_none,ot_none);
+ code : #1#220#8#248;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIVR;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#216#8#248;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIVR;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none,ot_none);
+ code : #1#216#9#248;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIVRP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#222#249;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIVRP;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#222#8#248;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FDIVRP;
+ ops : 2;
+ optypes : (ot_fpureg,ot_fpu0,ot_none,ot_none);
+ code : #1#222#8#248;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FEMMS;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#15#14;
+ flags : if_pent or if_3dnow
+ ),
+ (
+ opcode : A_FENI;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #3#155#219#224;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FFREE;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#221#8#192;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FIADD;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none,ot_none);
+ code : #1#222#128;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FIADD;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+ code : #1#218#128;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FICOM;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none,ot_none);
+ code : #1#222#130;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FICOM;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+ code : #1#218#130;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FICOMP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none,ot_none);
+ code : #1#222#131;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FICOMP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+ code : #1#218#131;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FIDIV;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none,ot_none);
+ code : #1#222#134;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FIDIV;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+ code : #1#218#134;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FIDIVR;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none,ot_none);
+ code : #1#222#135;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FIDIVR;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+ code : #1#218#135;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FILD;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+ code : #1#219#128;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FILD;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none,ot_none);
+ code : #1#223#128;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FILD;
+ ops : 1;
+ optypes : (ot_memory or ot_bits64,ot_none,ot_none,ot_none);
+ code : #1#223#133;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FIMUL;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none,ot_none);
+ code : #1#222#129;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FIMUL;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+ code : #1#218#129;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FINCSTP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#217#247;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FINIT;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #3#155#219#227;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FIST;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+ code : #1#219#130;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FIST;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none,ot_none);
+ code : #212#1#223#130;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FISTP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+ code : #1#219#131;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FISTP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none,ot_none);
+ code : #212#1#223#131;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FISTP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits64,ot_none,ot_none,ot_none);
+ code : #1#223#135;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FISTTP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+ code : #1#219#129;
+ flags : if_prescott or if_fpu
+ ),
+ (
+ opcode : A_FISTTP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none,ot_none);
+ code : #1#223#129;
+ flags : if_prescott or if_fpu
+ ),
+ (
+ opcode : A_FISTTP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits64,ot_none,ot_none,ot_none);
+ code : #1#221#129;
+ flags : if_prescott or if_fpu
+ ),
+ (
+ opcode : A_FISUB;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none,ot_none);
+ code : #1#222#132;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FISUB;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+ code : #1#218#132;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FISUBR;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none,ot_none);
+ code : #1#222#133;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FISUBR;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+ code : #1#218#133;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FLD;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+ code : #1#217#128;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FLD;
+ ops : 1;
+ optypes : (ot_memory or ot_bits64,ot_none,ot_none,ot_none);
+ code : #1#221#128;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FLD;
+ ops : 1;
+ optypes : (ot_memory or ot_bits80,ot_none,ot_none,ot_none);
+ code : #1#219#133;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FLD;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#217#8#192;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FLD1;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#217#232;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FLDCW;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #1#217#133;
+ flags : if_8086 or if_fpu or if_sw
+ ),
+ (
+ opcode : A_FLDENV;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #1#217#132;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FLDL2E;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#217#234;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FLDL2T;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#217#233;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FLDLG2;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#217#236;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FLDLN2;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#217#237;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FLDPI;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#217#235;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FLDZ;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#217#238;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FMUL;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+ code : #1#216#129;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FMUL;
+ ops : 1;
+ optypes : (ot_memory or ot_bits64,ot_none,ot_none,ot_none);
+ code : #1#220#129;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FMUL;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#220#201;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FMUL;
+ ops : 1;
+ optypes : (ot_fpureg or ot_to,ot_none,ot_none,ot_none);
+ code : #1#220#8#200;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FMUL;
+ ops : 2;
+ optypes : (ot_fpureg,ot_fpu0,ot_none,ot_none);
+ code : #1#220#8#200;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FMUL;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#216#8#200;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FMUL;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none,ot_none);
+ code : #1#216#9#200;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FMULP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#222#201;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FMULP;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#222#8#200;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FMULP;
+ ops : 2;
+ optypes : (ot_fpureg,ot_fpu0,ot_none,ot_none);
+ code : #1#222#8#200;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FNCLEX;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#219#226;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FNDISI;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#219#225;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FNENI;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#219#224;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FNINIT;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#219#227;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FNOP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#217#208;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FNSAVE;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #1#221#134;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FNSTCW;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #1#217#135;
+ flags : if_8086 or if_fpu or if_sw
+ ),
+ (
+ opcode : A_FNSTENV;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #1#217#134;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FNSTSW;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #1#221#135;
+ flags : if_8086 or if_fpu or if_sw
+ ),
+ (
+ opcode : A_FNSTSW;
+ ops : 1;
+ optypes : (ot_reg_ax,ot_none,ot_none,ot_none);
+ code : #2#223#224;
+ flags : if_286 or if_fpu
+ ),
+ (
+ opcode : A_FPATAN;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#217#243;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FPREM;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#217#248;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FPREM1;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#217#245;
+ flags : if_386 or if_fpu
+ ),
+ (
+ opcode : A_FPTAN;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#217#242;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FRNDINT;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#217#252;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FRSTOR;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #1#221#132;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSAVE;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #2#155#221#134;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSCALE;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#217#253;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSETPM;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#219#228;
+ flags : if_286 or if_fpu
+ ),
+ (
+ opcode : A_FSIN;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#217#254;
+ flags : if_386 or if_fpu
+ ),
+ (
+ opcode : A_FSINCOS;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#217#251;
+ flags : if_386 or if_fpu
+ ),
+ (
+ opcode : A_FSQRT;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#217#250;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FST;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+ code : #1#217#130;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FST;
+ ops : 1;
+ optypes : (ot_memory or ot_bits64,ot_none,ot_none,ot_none);
+ code : #1#221#130;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FST;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#221#8#208;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSTCW;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #2#155#217#135;
+ flags : if_8086 or if_fpu or if_sw
+ ),
+ (
+ opcode : A_FSTENV;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #2#155#217#134;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSTP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+ code : #1#217#131;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSTP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits64,ot_none,ot_none,ot_none);
+ code : #1#221#131;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSTP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits80,ot_none,ot_none,ot_none);
+ code : #1#219#135;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSTP;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#221#8#216;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSTSW;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #2#155#221#135;
+ flags : if_8086 or if_fpu or if_sw
+ ),
+ (
+ opcode : A_FSTSW;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #3#155#223#224;
+ flags : if_286 or if_fpu
+ ),
+ (
+ opcode : A_FSTSW;
+ ops : 1;
+ optypes : (ot_reg_ax,ot_none,ot_none,ot_none);
+ code : #3#155#223#224;
+ flags : if_286 or if_fpu
+ ),
+ (
+ opcode : A_FSUB;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+ code : #1#216#132;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUB;
+ ops : 1;
+ optypes : (ot_memory or ot_bits64,ot_none,ot_none,ot_none);
+ code : #1#220#132;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUB;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#220#225;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUB;
+ ops : 1;
+ optypes : (ot_fpureg or ot_to,ot_none,ot_none,ot_none);
+ code : #1#220#8#224;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUB;
+ ops : 2;
+ optypes : (ot_fpureg,ot_fpu0,ot_none,ot_none);
+ code : #1#220#8#224;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUB;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#216#8#224;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUB;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none,ot_none);
+ code : #1#216#9#224;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUBP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#222#225;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUBP;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#222#8#224;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUBP;
+ ops : 2;
+ optypes : (ot_fpureg,ot_fpu0,ot_none,ot_none);
+ code : #1#222#8#224;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUBR;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+ code : #1#216#133;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUBR;
+ ops : 1;
+ optypes : (ot_memory or ot_bits64,ot_none,ot_none,ot_none);
+ code : #1#220#133;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUBR;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#220#233;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUBR;
+ ops : 1;
+ optypes : (ot_fpureg or ot_to,ot_none,ot_none,ot_none);
+ code : #1#220#8#232;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUBR;
+ ops : 2;
+ optypes : (ot_fpureg,ot_fpu0,ot_none,ot_none);
+ code : #1#220#8#232;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUBR;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#216#8#232;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUBR;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none,ot_none);
+ code : #1#216#9#232;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUBRP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#222#233;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUBRP;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#222#8#232;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FSUBRP;
+ ops : 2;
+ optypes : (ot_fpureg,ot_fpu0,ot_none,ot_none);
+ code : #1#222#8#232;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FTST;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#217#228;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FUCOM;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#221#225;
+ flags : if_386 or if_fpu
+ ),
+ (
+ opcode : A_FUCOM;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#221#8#224;
+ flags : if_386 or if_fpu
+ ),
+ (
+ opcode : A_FUCOM;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none,ot_none);
+ code : #1#221#9#224;
+ flags : if_386 or if_fpu
+ ),
+ (
+ opcode : A_FUCOMI;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#219#233;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FUCOMI;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#219#8#232;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FUCOMI;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none,ot_none);
+ code : #1#219#9#232;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FUCOMIP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#223#233;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FUCOMIP;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#223#8#232;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FUCOMIP;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none,ot_none);
+ code : #1#223#9#232;
+ flags : if_p6 or if_fpu
+ ),
+ (
+ opcode : A_FUCOMP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#221#233;
+ flags : if_386 or if_fpu
+ ),
+ (
+ opcode : A_FUCOMP;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#221#8#232;
+ flags : if_386 or if_fpu
+ ),
+ (
+ opcode : A_FUCOMP;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none,ot_none);
+ code : #1#221#9#232;
+ flags : if_386 or if_fpu
+ ),
+ (
+ opcode : A_FUCOMPP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#218#233;
+ flags : if_386 or if_fpu
+ ),
+ (
+ opcode : A_FWAIT;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#155;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FXAM;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#217#229;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FXCH;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#217#201;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FXCH;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#217#8#200;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FXCH;
+ ops : 2;
+ optypes : (ot_fpureg,ot_fpu0,ot_none,ot_none);
+ code : #1#217#8#200;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FXCH;
+ ops : 2;
+ optypes : (ot_fpu0,ot_fpureg,ot_none,ot_none);
+ code : #1#217#9#200;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FXTRACT;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#217#244;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FYL2X;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#217#241;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_FYL2XP1;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#217#249;
+ flags : if_8086 or if_fpu
+ ),
+ (
+ opcode : A_HLT;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#244;
+ flags : if_8086 or if_priv
+ ),
+ (
+ opcode : A_IBTS;
+ ops : 2;
+ optypes : (ot_rm_gpr,ot_reg16 or ot_bits32 or ot_bits64,ot_none,ot_none);
+ code : #208#2#15#167#65;
+ flags : if_386 or if_sm or if_undoc
+ ),
+ (
+ opcode : A_ICEBP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#241;
+ flags : if_386
+ ),
+ (
+ opcode : A_IDIV;
+ ops : 1;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_none,ot_none,ot_none);
+ code : #208#1#247#135;
+ flags : if_8086
+ ),
+ (
+ opcode : A_IDIV;
+ ops : 1;
+ optypes : (ot_rm_gpr or ot_bits8,ot_none,ot_none,ot_none);
+ code : #1#246#135;
+ flags : if_8086
+ ),
+ (
+ opcode : A_IMUL;
+ ops : 2;
+ optypes : (ot_reg16 or ot_bits32 or ot_bits64,ot_rm_gpr,ot_none,ot_none);
+ code : #208#2#15#175#72;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_IMUL;
+ ops : 1;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_none,ot_none,ot_none);
+ code : #208#1#247#133;
+ flags : if_8086
+ ),
+ (
+ opcode : A_IMUL;
+ ops : 3;
+ optypes : (ot_reg32 or ot_bits64,ot_rm_gpr,ot_immediate or ot_bits8 or ot_signed,ot_none);
+ code : #208#1#107#72#14;
+ flags : if_286 or if_sm
+ ),
+ (
+ opcode : A_IMUL;
+ ops : 3;
+ optypes : (ot_reg32 or ot_bits64,ot_rm_gpr,ot_immediate,ot_none);
+ code : #208#1#105#72#34;
+ flags : if_286 or if_sm or if_sd or if_ar2
+ ),
+ (
+ opcode : A_IMUL;
+ ops : 2;
+ optypes : (ot_reg32 or ot_bits64,ot_immediate or ot_bits8 or ot_signed,ot_none,ot_none);
+ code : #208#1#107#64#13;
+ flags : if_286
+ ),
+ (
+ opcode : A_IMUL;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediate,ot_none,ot_none);
+ code : #213#1#105#64#33;
+ flags : if_286 or if_sd
+ ),
+ (
+ opcode : A_IMUL;
+ ops : 2;
+ optypes : (ot_reg64,ot_immediate,ot_none,ot_none);
+ code : #214#1#105#64#173;
+ flags : if_x86_64
+ ),
+ (
+ opcode : A_IMUL;
+ ops : 3;
+ optypes : (ot_reg16,ot_rm_gpr,ot_immediate or ot_bits8 or ot_signed,ot_none);
+ code : #212#1#107#72#14;
+ flags : if_286 or if_sm
+ ),
+ (
+ opcode : A_IMUL;
+ ops : 3;
+ optypes : (ot_reg16,ot_rm_gpr,ot_immediate,ot_none);
+ code : #212#1#105#72#26;
+ flags : if_286 or if_sm or if_sw or if_ar2
+ ),
+ (
+ opcode : A_IMUL;
+ ops : 2;
+ optypes : (ot_reg16,ot_immediate or ot_bits8 or ot_signed,ot_none,ot_none);
+ code : #212#1#107#64#13;
+ flags : if_286
+ ),
+ (
+ opcode : A_IMUL;
+ ops : 2;
+ optypes : (ot_reg16,ot_immediate,ot_none,ot_none);
+ code : #212#1#105#64#25;
+ flags : if_286 or if_sw
+ ),
+ (
+ opcode : A_IMUL;
+ ops : 1;
+ optypes : (ot_rm_gpr or ot_bits8,ot_none,ot_none,ot_none);
+ code : #1#246#133;
+ flags : if_8086
+ ),
+ (
+ opcode : A_IN;
+ ops : 2;
+ optypes : (ot_reg_al,ot_immediate,ot_none,ot_none);
+ code : #1#228#21;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_IN;
+ ops : 2;
+ optypes : (ot_reg_ax or ot_bits32,ot_immediate,ot_none,ot_none);
+ code : #208#1#229#21;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_IN;
+ ops : 2;
+ optypes : (ot_reg_al,ot_reg_dx,ot_none,ot_none);
+ code : #1#236;
+ flags : if_8086
+ ),
+ (
+ opcode : A_IN;
+ ops : 2;
+ optypes : (ot_reg_ax or ot_bits32,ot_reg_dx,ot_none,ot_none);
+ code : #208#1#237;
+ flags : if_8086
+ ),
+ (
+ opcode : A_INC;
+ ops : 1;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_none,ot_none,ot_none);
+ code : #208#1#255#128;
+ flags : if_8086
+ ),
+ (
+ opcode : A_INC;
+ ops : 1;
+ optypes : (ot_rm_gpr or ot_bits8,ot_none,ot_none,ot_none);
+ code : #1#254#128;
+ flags : if_8086
+ ),
+ (
+ opcode : A_INSB;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#108;
+ flags : if_186
+ ),
+ (
+ opcode : A_INSD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #213#1#109;
+ flags : if_386
+ ),
+ (
+ opcode : A_INSW;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #212#1#109;
+ flags : if_186
+ ),
+ (
+ opcode : A_INT;
+ ops : 1;
+ optypes : (ot_immediate,ot_none,ot_none,ot_none);
+ code : #1#205#20;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_INT01;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#241;
+ flags : if_386
+ ),
+ (
+ opcode : A_INT1;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#241;
+ flags : if_386
+ ),
+ (
+ opcode : A_INT03;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#204;
+ flags : if_8086
+ ),
+ (
+ opcode : A_INT3;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#204;
+ flags : if_8086
+ ),
+ (
+ opcode : A_INVD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#15#8;
+ flags : if_486 or if_priv
+ ),
+ (
+ opcode : A_INVLPG;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #2#15#1#135;
+ flags : if_486 or if_priv
+ ),
+ (
+ opcode : A_IRET;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #215#1#207;
+ flags : if_8086
+ ),
+ (
+ opcode : A_IRETD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #213#1#207;
+ flags : if_386
+ ),
+ (
+ opcode : A_IRETW;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #212#1#207;
+ flags : if_8086
+ ),
+ (
+ opcode : A_IRETQ;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #214#1#207;
+ flags : if_x86_64
+ ),
+ (
+ opcode : A_JECXZ;
+ ops : 1;
+ optypes : (ot_immediate,ot_none,ot_none,ot_none);
+ code : #201#1#227#40;
+ flags : if_386
+ ),
+ (
+ opcode : A_JRCXZ;
+ ops : 1;
+ optypes : (ot_immediate,ot_none,ot_none,ot_none);
+ code : #1#227#40;
+ flags : if_x86_64
+ ),
+ (
+ opcode : A_JMP;
+ ops : 1;
+ optypes : (ot_immediate or ot_bits8,ot_none,ot_none,ot_none);
+ code : #1#235#40;
+ flags : if_8086 or if_pass2
+ ),
+ (
+ opcode : A_JMP;
+ ops : 1;
+ optypes : (ot_immediate or ot_bits16 or ot_bits32,ot_none,ot_none,ot_none);
+ code : #208#1#233#52;
+ flags : if_8086 or if_pass2
+ ),
+ (
+ opcode : A_JMP;
+ ops : 1;
+ optypes : (ot_rm_gpr or ot_bits64,ot_none,ot_none,ot_none);
+ code : #221#1#255#132;
+ flags : if_x86_64
+ ),
+ (
+ opcode : A_JMP;
+ ops : 1;
+ optypes : (ot_rm_gpr or ot_bits16,ot_none,ot_none,ot_none);
+ code : #212#1#255#132;
+ flags : if_8086
+ ),
+ (
+ opcode : A_JMP;
+ ops : 1;
+ optypes : (ot_immediate or ot_short,ot_none,ot_none,ot_none);
+ code : #1#235#40;
+ flags : if_8086 or if_pass2
+ ),
+ (
+ opcode : A_JMP;
+ ops : 1;
+ optypes : (ot_immediate or ot_near,ot_none,ot_none,ot_none);
+ code : #208#1#233#52;
+ flags : if_8086 or if_pass2
+ ),
+ (
+ opcode : A_JMP;
+ ops : 1;
+ optypes : (ot_memory or ot_near,ot_none,ot_none,ot_none);
+ code : #208#1#255#132;
+ flags : if_8086
+ ),
+ (
+ opcode : A_JMP;
+ ops : 1;
+ optypes : (ot_memory or ot_far,ot_none,ot_none,ot_none);
+ code : #208#1#255#133;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LAHF;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#159;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LAR;
+ ops : 2;
+ optypes : (ot_reg16 or ot_bits32 or ot_bits64,ot_rm_gpr,ot_none,ot_none);
+ code : #208#2#15#2#72;
+ flags : if_286 or if_prot or if_sm
+ ),
+ (
+ opcode : A_LCALL;
+ ops : 1;
+ optypes : (ot_memory or ot_bits64,ot_none,ot_none,ot_none);
+ code : #221#1#255#131;
+ flags : if_x86_64
+ ),
+ (
+ opcode : A_LCALL;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none,ot_none);
+ code : #212#1#255#131;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LEA;
+ ops : 2;
+ optypes : (ot_reg32 or ot_bits64,ot_memory,ot_none,ot_none);
+ code : #208#1#141#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LEA;
+ ops : 2;
+ optypes : (ot_reg32 or ot_bits64,ot_immediate,ot_none,ot_none);
+ code : #208#1#141#72;
+ flags : if_8086 or if_sd
+ ),
+ (
+ opcode : A_LEAVE;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#201;
+ flags : if_186
+ ),
+ (
+ opcode : A_LFS;
+ ops : 2;
+ optypes : (ot_reg16 or ot_bits32,ot_memory,ot_none,ot_none);
+ code : #208#2#15#180#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_LGDT;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #2#15#1#130;
+ flags : if_286 or if_priv
+ ),
+ (
+ opcode : A_LGS;
+ ops : 2;
+ optypes : (ot_reg16 or ot_bits32,ot_memory,ot_none,ot_none);
+ code : #208#2#15#181#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_LIDT;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #2#15#1#131;
+ flags : if_286 or if_priv
+ ),
+ (
+ opcode : A_LJMP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits64,ot_none,ot_none,ot_none);
+ code : #221#1#255#133;
+ flags : if_x86_64
+ ),
+ (
+ opcode : A_LJMP;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none,ot_none);
+ code : #212#1#255#133;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LLDT;
+ ops : 1;
+ optypes : (ot_rm_gpr or ot_bits16,ot_none,ot_none,ot_none);
+ code : #2#15#0#130;
+ flags : if_286 or if_prot or if_priv
+ ),
+ (
+ opcode : A_LMSW;
+ ops : 1;
+ optypes : (ot_rm_gpr or ot_bits16,ot_none,ot_none,ot_none);
+ code : #2#15#1#134;
+ flags : if_286 or if_priv
+ ),
+ (
+ opcode : A_LOADALL;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#15#7;
+ flags : if_386 or if_undoc
+ ),
+ (
+ opcode : A_LOADALL286;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#15#5;
+ flags : if_286 or if_undoc
+ ),
+ (
+ opcode : A_LOCK;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#240;
+ flags : if_8086 or if_pre
+ ),
+ (
+ opcode : A_LODSB;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#172;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LODSD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #213#1#173;
+ flags : if_386
+ ),
+ (
+ opcode : A_LODSW;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #212#1#173;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LOOP;
+ ops : 1;
+ optypes : (ot_immediate,ot_none,ot_none,ot_none);
+ code : #202#1#226#40;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LOOP;
+ ops : 2;
+ optypes : (ot_immediate,ot_reg_ecx or ot_bits64,ot_none,ot_none);
+ code : #201#1#226#40;
+ flags : if_386
+ ),
+ (
+ opcode : A_LOOPE;
+ ops : 1;
+ optypes : (ot_immediate,ot_none,ot_none,ot_none);
+ code : #202#1#225#40;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LOOPE;
+ ops : 2;
+ optypes : (ot_immediate,ot_reg_ecx or ot_bits64,ot_none,ot_none);
+ code : #201#1#225#40;
+ flags : if_386
+ ),
+ (
+ opcode : A_LOOPNE;
+ ops : 1;
+ optypes : (ot_immediate,ot_none,ot_none,ot_none);
+ code : #202#1#224#40;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LOOPNE;
+ ops : 2;
+ optypes : (ot_immediate,ot_reg_ecx or ot_bits64,ot_none,ot_none);
+ code : #201#1#224#40;
+ flags : if_386
+ ),
+ (
+ opcode : A_LOOPNZ;
+ ops : 1;
+ optypes : (ot_immediate,ot_none,ot_none,ot_none);
+ code : #202#1#224#40;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LOOPNZ;
+ ops : 2;
+ optypes : (ot_immediate,ot_reg_ecx or ot_bits64,ot_none,ot_none);
+ code : #201#1#224#40;
+ flags : if_386
+ ),
+ (
+ opcode : A_LOOPZ;
+ ops : 1;
+ optypes : (ot_immediate,ot_none,ot_none,ot_none);
+ code : #202#1#225#40;
+ flags : if_8086
+ ),
+ (
+ opcode : A_LOOPZ;
+ ops : 2;
+ optypes : (ot_immediate,ot_reg_ecx or ot_bits64,ot_none,ot_none);
+ code : #201#1#225#40;
+ flags : if_386
+ ),
+ (
+ opcode : A_LSL;
+ ops : 2;
+ optypes : (ot_reg16 or ot_bits32 or ot_bits64,ot_rm_gpr,ot_none,ot_none);
+ code : #208#2#15#3#72;
+ flags : if_286 or if_prot or if_sm
+ ),
+ (
+ opcode : A_LSS;
+ ops : 2;
+ optypes : (ot_reg16 or ot_bits32 or ot_bits64,ot_memory,ot_none,ot_none);
+ code : #208#2#15#178#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_LTR;
+ ops : 1;
+ optypes : (ot_rm_gpr or ot_bits16,ot_none,ot_none,ot_none);
+ code : #2#15#0#131;
+ flags : if_286 or if_prot or if_priv
+ ),
+ (
+ opcode : A_MONITOR;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #3#15#1#200;
+ flags : if_prescott
+ ),
+ (
+ opcode : A_MONITOR;
+ ops : 3;
+ optypes : (ot_reg_eax,ot_reg_ecx,ot_reg_edx,ot_none);
+ code : #3#15#1#200;
+ flags : if_prescott
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_mem_offs,ot_reg_ax,ot_none,ot_none);
+ code : #212#1#163#36;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_mem_offs,ot_reg_eax,ot_none,ot_none);
+ code : #213#1#163#36;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_mem_offs,ot_reg_rax,ot_none,ot_none);
+ code : #214#1#163#36;
+ flags : if_x86_64 or if_sm
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_rm_gpr,ot_reg16 or ot_bits32 or ot_bits64,ot_none,ot_none);
+ code : #208#1#137#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg_ax,ot_mem_offs,ot_none,ot_none);
+ code : #212#1#161#37;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg_eax,ot_mem_offs,ot_none,ot_none);
+ code : #213#1#161#37;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg_rax,ot_mem_offs,ot_none,ot_none);
+ code : #214#1#161#37;
+ flags : if_x86_64 or if_sm
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg16 or ot_bits32 or ot_bits64,ot_rm_gpr,ot_none,ot_none);
+ code : #208#1#139#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediate,ot_none,ot_none);
+ code : #213#8#184#33;
+ flags : if_386 or if_sd
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg64,ot_immediate,ot_none,ot_none);
+ code : #214#8#184#45;
+ flags : if_x86_64 or if_sm
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits32,ot_immediate,ot_none,ot_none);
+ code : #213#1#199#128#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits64,ot_immediate,ot_none,ot_none);
+ code : #214#1#199#128#173;
+ flags : if_x86_64 or if_sm
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg16,ot_immediate,ot_none,ot_none);
+ code : #212#8#184#25;
+ flags : if_8086 or if_sw
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16,ot_immediate,ot_none,ot_none);
+ code : #212#1#199#128#25;
+ flags : if_8086 or if_sw
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_mem_offs,ot_reg_al,ot_none,ot_none);
+ code : #1#162#36;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_reg8,ot_none,ot_none);
+ code : #1#136#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg_al,ot_mem_offs,ot_none,ot_none);
+ code : #1#160#37;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg8,ot_rm_gpr or ot_bits8,ot_none,ot_none);
+ code : #1#138#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg8,ot_immediate,ot_none,ot_none);
+ code : #8#176#17;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_immediate,ot_none,ot_none);
+ code : #1#198#128#17;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32,ot_reg_cs,ot_none,ot_none);
+ code : #208#1#140#129;
+ flags : if_8086
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32,ot_reg_dess,ot_none,ot_none);
+ code : #208#1#140#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32,ot_reg_fsgs,ot_none,ot_none);
+ code : #208#1#140#65;
+ flags : if_386
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg_dess,ot_rm_gpr or ot_bits16 or ot_bits32,ot_none,ot_none);
+ code : #209#1#142#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg_fsgs,ot_rm_gpr or ot_bits16 or ot_bits32,ot_none,ot_none);
+ code : #209#1#142#72;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg64,ot_reg_cr4,ot_none,ot_none);
+ code : #2#15#32#132;
+ flags : if_pent or if_priv or if_x86_64
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg64,ot_reg_creg,ot_none,ot_none);
+ code : #2#15#32#65;
+ flags : if_386 or if_priv or if_x86_64
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg64,ot_reg_dreg,ot_none,ot_none);
+ code : #2#15#33#65;
+ flags : if_386 or if_priv or if_x86_64
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg64,ot_reg_treg,ot_none,ot_none);
+ code : #2#15#36#65;
+ flags : if_386 or if_priv or if_x86_64
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg_cr4,ot_reg64,ot_none,ot_none);
+ code : #2#15#34#140;
+ flags : if_pent or if_priv or if_x86_64
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg_creg,ot_reg64,ot_none,ot_none);
+ code : #2#15#34#72;
+ flags : if_386 or if_priv or if_x86_64
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg_dreg,ot_reg64,ot_none,ot_none);
+ code : #2#15#35#72;
+ flags : if_386 or if_priv or if_x86_64
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg_treg,ot_reg64,ot_none,ot_none);
+ code : #2#15#38#72;
+ flags : if_386 or if_priv or if_x86_64
+ ),
+ (
+ opcode : A_MOVD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_rm_gpr or ot_bits32,ot_none,ot_none);
+ code : #2#15#110#72;
+ flags : if_pent or if_mmx or if_sd
+ ),
+ (
+ opcode : A_MOVD;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits32,ot_mmxreg,ot_none,ot_none);
+ code : #2#15#126#65;
+ flags : if_pent or if_mmx or if_sd
+ ),
+ (
+ opcode : A_MOVD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_rm_gpr or ot_bits32,ot_none,ot_none);
+ code : #241#2#15#110#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVD;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits32,ot_xmmreg,ot_none,ot_none);
+ code : #241#2#15#126#65;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#111#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_MOVQ;
+ ops : 2;
+ optypes : (ot_mmxrm,ot_mmxreg,ot_none,ot_none);
+ code : #2#15#127#65;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_MOVQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_rm_gpr or ot_bits64,ot_none,ot_none);
+ code : #214#2#15#110#72;
+ flags : if_x86_64 or if_mmx
+ ),
+ (
+ opcode : A_MOVQ;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits64,ot_mmxreg,ot_none,ot_none);
+ code : #214#2#15#126#65;
+ flags : if_x86_64 or if_mmx
+ ),
+ (
+ opcode : A_MOVQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #219#2#15#126#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVQ;
+ ops : 2;
+ optypes : (ot_xmmrm,ot_xmmreg,ot_none,ot_none);
+ code : #241#2#15#214#65;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_reg64,ot_none,ot_none);
+ code : #241#214#2#15#110#72;
+ flags : if_willamette or if_sse2 or if_x86_64
+ ),
+ (
+ opcode : A_MOVQ;
+ ops : 2;
+ optypes : (ot_reg64,ot_xmmreg,ot_none,ot_none);
+ code : #241#214#2#15#126#65;
+ flags : if_willamette or if_sse2 or if_x86_64
+ ),
+ (
+ opcode : A_MOVSB;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#164;
+ flags : if_8086
+ ),
+ (
+ opcode : A_MOVSD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #213#1#165;
+ flags : if_386
+ ),
+ (
+ opcode : A_MOVSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #220#2#15#16#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVSD;
+ ops : 2;
+ optypes : (ot_xmmrm,ot_xmmreg,ot_none,ot_none);
+ code : #220#2#15#17#65;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVSQ;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #214#1#165;
+ flags : if_x86_64
+ ),
+ (
+ opcode : A_MOVSW;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #212#1#165;
+ flags : if_8086
+ ),
+ (
+ opcode : A_MOVSX;
+ ops : 2;
+ optypes : (ot_reg32 or ot_bits64,ot_rm_gpr or ot_bits16,ot_none,ot_none);
+ code : #208#2#15#191#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_MOVSX;
+ ops : 2;
+ optypes : (ot_reg16 or ot_bits32 or ot_bits64,ot_rm_gpr or ot_bits8,ot_none,ot_none);
+ code : #208#2#15#190#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_MOVZX;
+ ops : 2;
+ optypes : (ot_reg32 or ot_bits64,ot_rm_gpr or ot_bits16,ot_none,ot_none);
+ code : #208#2#15#183#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_MOVZX;
+ ops : 2;
+ optypes : (ot_reg16 or ot_bits32 or ot_bits64,ot_rm_gpr or ot_bits8,ot_none,ot_none);
+ code : #208#2#15#182#72;
+ flags : if_386
+ ),
+ (
+ opcode : A_MUL;
+ ops : 1;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_none,ot_none,ot_none);
+ code : #208#1#247#132;
+ flags : if_8086
+ ),
+ (
+ opcode : A_MUL;
+ ops : 1;
+ optypes : (ot_rm_gpr or ot_bits8,ot_none,ot_none,ot_none);
+ code : #1#246#132;
+ flags : if_8086
+ ),
+ (
+ opcode : A_MWAIT;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #3#15#1#201;
+ flags : if_prescott
+ ),
+ (
+ opcode : A_MWAIT;
+ ops : 2;
+ optypes : (ot_reg_eax,ot_reg_ecx,ot_none,ot_none);
+ code : #3#15#1#201;
+ flags : if_prescott
+ ),
+ (
+ opcode : A_NEG;
+ ops : 1;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_none,ot_none,ot_none);
+ code : #208#1#247#131;
+ flags : if_8086
+ ),
+ (
+ opcode : A_NEG;
+ ops : 1;
+ optypes : (ot_rm_gpr or ot_bits8,ot_none,ot_none,ot_none);
+ code : #1#246#131;
+ flags : if_8086
+ ),
+ (
+ opcode : A_NOP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#144;
+ flags : if_8086
+ ),
+ (
+ opcode : A_NOT;
+ ops : 1;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_none,ot_none,ot_none);
+ code : #208#1#247#130;
+ flags : if_8086
+ ),
+ (
+ opcode : A_NOT;
+ ops : 1;
+ optypes : (ot_rm_gpr or ot_bits8,ot_none,ot_none,ot_none);
+ code : #1#246#130;
+ flags : if_8086
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_rm_gpr,ot_reg16 or ot_bits32 or ot_bits64,ot_none,ot_none);
+ code : #208#1#9#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_reg16 or ot_bits32 or ot_bits64,ot_rm_gpr,ot_none,ot_none);
+ code : #208#1#11#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_reg8,ot_none,ot_none);
+ code : #1#8#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_reg8,ot_rm_gpr or ot_bits8,ot_none,ot_none);
+ code : #1#10#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_immediate or ot_bits8 or ot_signed,ot_none,ot_none);
+ code : #208#1#131#129#13;
+ flags : if_8086
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_reg_eax,ot_immediate,ot_none,ot_none);
+ code : #213#1#13#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_reg_rax,ot_immediate,ot_none,ot_none);
+ code : #214#1#13#173;
+ flags : if_x86_64 or if_sm
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits32,ot_immediate,ot_none,ot_none);
+ code : #213#1#129#129#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits64,ot_immediate,ot_none,ot_none);
+ code : #214#1#129#129#173;
+ flags : if_x86_64 or if_sm
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_reg_ax,ot_immediate,ot_none,ot_none);
+ code : #212#1#13#25;
+ flags : if_8086 or if_sw
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16,ot_immediate,ot_none,ot_none);
+ code : #212#1#129#129#25;
+ flags : if_8086 or if_sw
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_reg_al,ot_immediate,ot_none,ot_none);
+ code : #1#12#17;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_OR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_immediate,ot_none,ot_none);
+ code : #1#128#129#17;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_OUT;
+ ops : 2;
+ optypes : (ot_immediate,ot_reg_al,ot_none,ot_none);
+ code : #1#230#20;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_OUT;
+ ops : 2;
+ optypes : (ot_immediate,ot_reg_ax,ot_none,ot_none);
+ code : #212#1#231#20;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_OUT;
+ ops : 2;
+ optypes : (ot_immediate,ot_reg_eax,ot_none,ot_none);
+ code : #213#1#231#20;
+ flags : if_386 or if_sb
+ ),
+ (
+ opcode : A_OUT;
+ ops : 2;
+ optypes : (ot_reg_dx,ot_reg_al,ot_none,ot_none);
+ code : #1#238;
+ flags : if_8086
+ ),
+ (
+ opcode : A_OUT;
+ ops : 2;
+ optypes : (ot_reg_dx,ot_reg_ax,ot_none,ot_none);
+ code : #212#1#239;
+ flags : if_8086
+ ),
+ (
+ opcode : A_OUT;
+ ops : 2;
+ optypes : (ot_reg_dx,ot_reg_eax,ot_none,ot_none);
+ code : #213#1#239;
+ flags : if_386
+ ),
+ (
+ opcode : A_OUTSB;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#110;
+ flags : if_186
+ ),
+ (
+ opcode : A_OUTSD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #213#1#111;
+ flags : if_386
+ ),
+ (
+ opcode : A_OUTSW;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #212#1#111;
+ flags : if_186
+ ),
+ (
+ opcode : A_PACKSSDW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#107#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PACKSSDW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#107#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PACKSSWB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#99#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PACKSSWB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#99#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PACKUSWB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#103#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PACKUSWB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#103#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PADDB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#252#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PADDB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#252#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PADDD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#254#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PADDD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#254#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PADDSB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#236#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PADDSB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#236#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PADDSIW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#81#72;
+ flags : if_pent or if_mmx or if_sm or if_cyrix
+ ),
+ (
+ opcode : A_PADDSW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#237#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PADDSW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#237#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PADDUSB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#220#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PADDUSB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#220#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PADDUSW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#221#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PADDUSW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#221#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PADDW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#253#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PADDW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#253#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PAND;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#219#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PAND;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#219#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PANDN;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#223#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PANDN;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#223#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PAVEB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#80#72;
+ flags : if_pent or if_mmx or if_sm or if_cyrix
+ ),
+ (
+ opcode : A_PAVGUSB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#15#72#1#191;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PCMPEQB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#116#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PCMPEQB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#116#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PCMPEQD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#118#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PCMPEQD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#118#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PCMPEQW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#117#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PCMPEQW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#117#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PCMPGTB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#100#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PCMPGTB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#100#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PCMPGTD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#102#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PCMPGTD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#102#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PCMPGTW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#101#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PCMPGTW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#101#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PDISTIB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none,ot_none);
+ code : #2#15#84#72;
+ flags : if_pent or if_mmx or if_sm or if_cyrix
+ ),
+ (
+ opcode : A_PF2ID;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#15#72#1#29;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PFACC;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#15#72#1#174;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PFADD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#15#72#1#158;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PFCMPEQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#15#72#1#176;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PFCMPGE;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#15#72#1#144;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PFCMPGT;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#15#72#1#160;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PFMAX;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#15#72#1#164;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PFMIN;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#15#72#1#148;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PFMUL;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#15#72#1#180;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PFRCP;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#15#72#1#150;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PFRCPIT1;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#15#72#1#166;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PFRCPIT2;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#15#72#1#182;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PFRSQIT1;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#15#72#1#167;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PFRSQRT;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#15#72#1#151;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PFSUB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#15#72#1#154;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PFSUBR;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#15#72#1#170;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PI2FD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#15#72#1#13;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PMACHRIW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none,ot_none);
+ code : #2#15#94#72;
+ flags : if_pent or if_mmx or if_sm or if_cyrix
+ ),
+ (
+ opcode : A_PMADDWD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#245#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PMADDWD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#245#72;
+ flags : if_willamette or if_sm or if_sse2
+ ),
+ (
+ opcode : A_PMAGW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#82#72;
+ flags : if_pent or if_mmx or if_sm or if_cyrix
+ ),
+ (
+ opcode : A_PMULHRIW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#93#72;
+ flags : if_pent or if_mmx or if_sm or if_cyrix
+ ),
+ (
+ opcode : A_PMULHRWA;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#15#72#1#183;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PMULHRWC;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#89#72;
+ flags : if_pent or if_mmx or if_sm or if_cyrix
+ ),
+ (
+ opcode : A_PMULHW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#229#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PMULHW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#229#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PMULLW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#213#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PMULLW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#213#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PMVGEZB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none,ot_none);
+ code : #2#15#92#72;
+ flags : if_pent or if_mmx or if_sm or if_cyrix
+ ),
+ (
+ opcode : A_PMVLZB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none,ot_none);
+ code : #2#15#91#72;
+ flags : if_pent or if_mmx or if_sm or if_cyrix
+ ),
+ (
+ opcode : A_PMVNZB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none,ot_none);
+ code : #2#15#90#72;
+ flags : if_pent or if_mmx or if_sm or if_cyrix
+ ),
+ (
+ opcode : A_PMVZB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none,ot_none);
+ code : #2#15#88#72;
+ flags : if_pent or if_mmx or if_sm or if_cyrix
+ ),
+ (
+ opcode : A_POP;
+ ops : 1;
+ optypes : (ot_reg16,ot_none,ot_none,ot_none);
+ code : #212#8#88;
+ flags : if_8086
+ ),
+ (
+ opcode : A_POP;
+ ops : 1;
+ optypes : (ot_reg64,ot_none,ot_none,ot_none);
+ code : #221#8#88;
+ flags : if_x86_64
+ ),
+ (
+ opcode : A_POP;
+ ops : 1;
+ optypes : (ot_rm_gpr or ot_bits16,ot_none,ot_none,ot_none);
+ code : #212#1#143#128;
+ flags : if_8086
+ ),
+ (
+ opcode : A_POP;
+ ops : 1;
+ optypes : (ot_rm_gpr or ot_bits64,ot_none,ot_none,ot_none);
+ code : #221#1#143#128;
+ flags : if_x86_64
+ ),
+ (
+ opcode : A_POP;
+ ops : 1;
+ optypes : (ot_reg_cs,ot_none,ot_none,ot_none);
+ code : #1#15;
+ flags : if_8086 or if_undoc
+ ),
+ (
+ opcode : A_POP;
+ ops : 1;
+ optypes : (ot_reg_fsgs,ot_none,ot_none,ot_none);
+ code : #1#15#5#221;
+ flags : if_386
+ ),
+ (
+ opcode : A_POPF;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #214#1#157;
+ flags : if_x86_64
+ ),
+ (
+ opcode : A_POPFW;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#157;
+ flags : if_x86_64
+ ),
+ (
+ opcode : A_POPFQ;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #214#1#157;
+ flags : if_x86_64
+ ),
+ (
+ opcode : A_POR;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#235#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_POR;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none,ot_none);
+ code : #241#2#15#235#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PREFETCH;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #2#15#13#128;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PREFETCHW;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #2#15#13#129;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PSLLD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#242#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSLLD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_immediate,ot_none,ot_none);
+ code : #2#15#114#134#21;
+ flags : if_pent or if_mmx or if_sb or if_ar1
+ ),
+ (
+ opcode : A_PSLLD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#242#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSLLD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_immediate,ot_none,ot_none);
+ code : #241#2#15#114#134#21;
+ flags : if_willamette or if_sse2 or if_sb or if_ar1
+ ),
+ (
+ opcode : A_PSLLDQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_immediate,ot_none,ot_none);
+ code : #241#2#15#115#135#21;
+ flags : if_willamette or if_sse2 or if_sb or if_ar1
+ ),
+ (
+ opcode : A_PSLLQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#243#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSLLQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_immediate,ot_none,ot_none);
+ code : #2#15#115#134#21;
+ flags : if_pent or if_mmx or if_sb or if_ar1
+ ),
+ (
+ opcode : A_PSLLQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#243#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSLLQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_immediate,ot_none,ot_none);
+ code : #241#2#15#115#134#21;
+ flags : if_willamette or if_sse2 or if_sb or if_ar1
+ ),
+ (
+ opcode : A_PSLLW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#241#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSLLW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_immediate,ot_none,ot_none);
+ code : #2#15#113#134#21;
+ flags : if_pent or if_mmx or if_sb or if_ar1
+ ),
+ (
+ opcode : A_PSLLW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#241#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSLLW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_immediate,ot_none,ot_none);
+ code : #241#2#15#113#134#21;
+ flags : if_willamette or if_sse2 or if_sb or if_ar1
+ ),
+ (
+ opcode : A_PSRAD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#226#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSRAD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_immediate,ot_none,ot_none);
+ code : #2#15#114#132#21;
+ flags : if_pent or if_mmx or if_sb or if_ar1
+ ),
+ (
+ opcode : A_PSRAD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#226#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSRAD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_immediate,ot_none,ot_none);
+ code : #241#2#15#114#132#21;
+ flags : if_willamette or if_sse2 or if_sb or if_ar1
+ ),
+ (
+ opcode : A_PSRAW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#225#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSRAW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_immediate,ot_none,ot_none);
+ code : #2#15#113#132#21;
+ flags : if_pent or if_mmx or if_sb or if_ar1
+ ),
+ (
+ opcode : A_PSRAW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#225#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSRAW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_immediate,ot_none,ot_none);
+ code : #241#2#15#113#132#21;
+ flags : if_willamette or if_sse2 or if_sb or if_ar1
+ ),
+ (
+ opcode : A_PSRLD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#210#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSRLD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_immediate,ot_none,ot_none);
+ code : #2#15#114#130#21;
+ flags : if_pent or if_mmx or if_sb or if_ar1
+ ),
+ (
+ opcode : A_PSRLD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#210#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSRLD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_immediate,ot_none,ot_none);
+ code : #241#2#15#114#130#21;
+ flags : if_willamette or if_sse2 or if_sb or if_ar1
+ ),
+ (
+ opcode : A_PSRLQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#211#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSRLQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_immediate,ot_none,ot_none);
+ code : #2#15#115#130#21;
+ flags : if_pent or if_mmx or if_sb or if_ar1
+ ),
+ (
+ opcode : A_PSRLQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#211#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSRLQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_immediate,ot_none,ot_none);
+ code : #241#2#15#115#130#21;
+ flags : if_willamette or if_sse2 or if_sb or if_ar1
+ ),
+ (
+ opcode : A_PSRLW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#209#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSRLW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_immediate,ot_none,ot_none);
+ code : #2#15#113#130#21;
+ flags : if_pent or if_mmx or if_sb or if_ar1
+ ),
+ (
+ opcode : A_PSRLW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#209#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSRLW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_immediate,ot_none,ot_none);
+ code : #241#2#15#113#130#21;
+ flags : if_willamette or if_sse2 or if_sb or if_ar1
+ ),
+ (
+ opcode : A_PSUBB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#248#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSUBB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#248#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSUBD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#250#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSUBD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#250#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSUBSB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#232#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSUBSB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#232#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSUBSIW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none,ot_none);
+ code : #2#15#85#72;
+ flags : if_pent or if_mmx or if_sm or if_cyrix
+ ),
+ (
+ opcode : A_PSUBSIW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none,ot_none);
+ code : #2#15#85#72;
+ flags : if_pent or if_mmx or if_cyrix
+ ),
+ (
+ opcode : A_PSUBSW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#233#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSUBSW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#233#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSUBUSB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#216#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSUBUSB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#216#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSUBUSW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#217#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSUBUSW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#217#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSUBW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#249#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSUBW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#249#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PUNPCKHBW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#104#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PUNPCKHBW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#104#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PUNPCKHDQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#106#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PUNPCKHDQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#106#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PUNPCKHWD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#105#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PUNPCKHWD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#105#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PUNPCKLBW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#96#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PUNPCKLBW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#96#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PUNPCKLDQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#98#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PUNPCKLDQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#98#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PUNPCKLWD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#97#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PUNPCKLWD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#97#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PUSH;
+ ops : 1;
+ optypes : (ot_reg16,ot_none,ot_none,ot_none);
+ code : #212#8#80;
+ flags : if_8086
+ ),
+ (
+ opcode : A_PUSH;
+ ops : 1;
+ optypes : (ot_reg64,ot_none,ot_none,ot_none);
+ code : #221#8#80;
+ flags : if_x86_64
+ ),
+ (
+ opcode : A_PUSH;
+ ops : 1;
+ optypes : (ot_rm_gpr or ot_bits16,ot_none,ot_none,ot_none);
+ code : #212#1#255#134;
+ flags : if_8086
+ ),
+ (
+ opcode : A_PUSH;
+ ops : 1;
+ optypes : (ot_rm_gpr or ot_bits64,ot_none,ot_none,ot_none);
+ code : #221#1#255#134;
+ flags : if_x86_64
+ ),
+ (
+ opcode : A_PUSH;
+ ops : 1;
+ optypes : (ot_immediate or ot_bits32,ot_none,ot_none,ot_none);
+ code : #213#1#104#32#221;
+ flags : if_386
+ ),
+ (
+ opcode : A_PUSH;
+ ops : 1;
+ optypes : (ot_immediate or ot_bits16,ot_none,ot_none,ot_none);
+ code : #212#1#104#24#221;
+ flags : if_286
+ ),
+ (
+ opcode : A_PUSH;
+ ops : 1;
+ optypes : (ot_immediate or ot_bits8 or ot_signed,ot_none,ot_none,ot_none);
+ code : #1#106#12#221;
+ flags : if_286
+ ),
+ (
+ opcode : A_PUSHF;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #215#1#156;
+ flags : if_186
+ ),
+ (
+ opcode : A_PUSHFW;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #212#1#156;
+ flags : if_186
+ ),
+ (
+ opcode : A_PUSHFQ;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #214#1#156;
+ flags : if_x86_64
+ ),
+ (
+ opcode : A_PXOR;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#239#72;
+ flags : if_pent or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PXOR;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#239#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_RCL;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_unity,ot_none,ot_none);
+ code : #208#1#209#130;
+ flags : if_8086
+ ),
+ (
+ opcode : A_RCL;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_reg_cl,ot_none,ot_none);
+ code : #208#1#211#130;
+ flags : if_8086
+ ),
+ (
+ opcode : A_RCL;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_immediate,ot_none,ot_none);
+ code : #208#1#193#130#21;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_RCL;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_unity,ot_none,ot_none);
+ code : #1#208#130;
+ flags : if_8086
+ ),
+ (
+ opcode : A_RCL;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_reg_cl,ot_none,ot_none);
+ code : #1#210#130;
+ flags : if_8086
+ ),
+ (
+ opcode : A_RCL;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_immediate,ot_none,ot_none);
+ code : #1#192#130#21;
+ flags : if_186 or if_sb
+ ),
+ (
+ opcode : A_RCR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_unity,ot_none,ot_none);
+ code : #208#1#209#131;
+ flags : if_8086
+ ),
+ (
+ opcode : A_RCR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_reg_cl,ot_none,ot_none);
+ code : #208#1#211#131;
+ flags : if_8086
+ ),
+ (
+ opcode : A_RCR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_immediate,ot_none,ot_none);
+ code : #208#1#193#131#21;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_RCR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_unity,ot_none,ot_none);
+ code : #1#208#131;
+ flags : if_8086
+ ),
+ (
+ opcode : A_RCR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_reg_cl,ot_none,ot_none);
+ code : #1#210#131;
+ flags : if_8086
+ ),
+ (
+ opcode : A_RCR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_immediate,ot_none,ot_none);
+ code : #1#192#131#21;
+ flags : if_186 or if_sb
+ ),
+ (
+ opcode : A_RDSHR;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#15#54;
+ flags : if_p6 or if_cyrix or if_smm
+ ),
+ (
+ opcode : A_RDMSR;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#15#50;
+ flags : if_pent or if_priv
+ ),
+ (
+ opcode : A_RDPMC;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#15#51;
+ flags : if_p6
+ ),
+ (
+ opcode : A_RDTSC;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#15#49;
+ flags : if_pent
+ ),
+ (
+ opcode : A_REP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#243;
+ flags : if_8086 or if_pre
+ ),
+ (
+ opcode : A_REPE;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#243;
+ flags : if_8086 or if_pre
+ ),
+ (
+ opcode : A_REPNE;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#242;
+ flags : if_8086 or if_pre
+ ),
+ (
+ opcode : A_REPNZ;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#242;
+ flags : if_8086 or if_pre
+ ),
+ (
+ opcode : A_REPZ;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#243;
+ flags : if_8086 or if_pre
+ ),
+ (
+ opcode : A_RET;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#195;
+ flags : if_8086
+ ),
+ (
+ opcode : A_RET;
+ ops : 1;
+ optypes : (ot_immediate,ot_none,ot_none,ot_none);
+ code : #1#194#24;
+ flags : if_8086 or if_sw
+ ),
+ (
+ opcode : A_RETF;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#203;
+ flags : if_8086
+ ),
+ (
+ opcode : A_RETF;
+ ops : 1;
+ optypes : (ot_immediate,ot_none,ot_none,ot_none);
+ code : #1#202#24;
+ flags : if_8086 or if_sw
+ ),
+ (
+ opcode : A_RETN;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#195;
+ flags : if_8086
+ ),
+ (
+ opcode : A_RETN;
+ ops : 1;
+ optypes : (ot_immediate,ot_none,ot_none,ot_none);
+ code : #1#194#24;
+ flags : if_8086 or if_sw
+ ),
+ (
+ opcode : A_ROL;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_unity,ot_none,ot_none);
+ code : #208#1#209#128;
+ flags : if_8086
+ ),
+ (
+ opcode : A_ROL;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_reg_cl,ot_none,ot_none);
+ code : #208#1#211#128;
+ flags : if_8086
+ ),
+ (
+ opcode : A_ROL;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_immediate,ot_none,ot_none);
+ code : #208#1#193#128#21;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_ROL;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_unity,ot_none,ot_none);
+ code : #1#208#128;
+ flags : if_8086
+ ),
+ (
+ opcode : A_ROL;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_reg_cl,ot_none,ot_none);
+ code : #1#210#128;
+ flags : if_8086
+ ),
+ (
+ opcode : A_ROL;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_immediate,ot_none,ot_none);
+ code : #1#192#128#21;
+ flags : if_186 or if_sb
+ ),
+ (
+ opcode : A_ROR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_unity,ot_none,ot_none);
+ code : #208#1#209#129;
+ flags : if_8086
+ ),
+ (
+ opcode : A_ROR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_reg_cl,ot_none,ot_none);
+ code : #208#1#211#129;
+ flags : if_8086
+ ),
+ (
+ opcode : A_ROR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_immediate,ot_none,ot_none);
+ code : #208#1#193#129#21;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_ROR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_unity,ot_none,ot_none);
+ code : #1#208#129;
+ flags : if_8086
+ ),
+ (
+ opcode : A_ROR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_reg_cl,ot_none,ot_none);
+ code : #1#210#129;
+ flags : if_8086
+ ),
+ (
+ opcode : A_ROR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_immediate,ot_none,ot_none);
+ code : #1#192#129#21;
+ flags : if_186 or if_sb
+ ),
+ (
+ opcode : A_RSDC;
+ ops : 2;
+ optypes : (ot_reg_sreg,ot_memory or ot_bits80,ot_none,ot_none);
+ code : #2#15#121#65;
+ flags : if_486 or if_cyrix or if_smm
+ ),
+ (
+ opcode : A_RSLDT;
+ ops : 1;
+ optypes : (ot_memory or ot_bits80,ot_none,ot_none,ot_none);
+ code : #2#15#123#128;
+ flags : if_486 or if_cyrix or if_smm
+ ),
+ (
+ opcode : A_RSM;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#15#170;
+ flags : if_pent or if_smm
+ ),
+ (
+ opcode : A_SAHF;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#158;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SAL;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_unity,ot_none,ot_none);
+ code : #208#1#209#132;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SAL;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_reg_cl,ot_none,ot_none);
+ code : #208#1#211#132;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SAL;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_immediate,ot_none,ot_none);
+ code : #208#1#193#132#21;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_SAL;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_unity,ot_none,ot_none);
+ code : #1#208#132;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SAL;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_reg_cl,ot_none,ot_none);
+ code : #1#210#132;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SAL;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_immediate,ot_none,ot_none);
+ code : #1#192#132#21;
+ flags : if_186 or if_sb
+ ),
+ (
+ opcode : A_SAR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_unity,ot_none,ot_none);
+ code : #208#1#209#135;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SAR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_reg_cl,ot_none,ot_none);
+ code : #208#1#211#135;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SAR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_immediate,ot_none,ot_none);
+ code : #208#1#193#135#21;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_SAR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_unity,ot_none,ot_none);
+ code : #1#208#135;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SAR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_reg_cl,ot_none,ot_none);
+ code : #1#210#135;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SAR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_immediate,ot_none,ot_none);
+ code : #1#192#135#21;
+ flags : if_186 or if_sb
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_rm_gpr,ot_reg16 or ot_bits32 or ot_bits64,ot_none,ot_none);
+ code : #208#1#25#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_reg16 or ot_bits32 or ot_bits64,ot_rm_gpr,ot_none,ot_none);
+ code : #208#1#27#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_immediate or ot_bits8 or ot_signed,ot_none,ot_none);
+ code : #208#1#131#131#13;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_reg8,ot_none,ot_none);
+ code : #1#24#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_reg8,ot_rm_gpr or ot_bits8,ot_none,ot_none);
+ code : #1#26#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_reg_eax,ot_immediate,ot_none,ot_none);
+ code : #213#1#29#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_reg_rax,ot_immediate,ot_none,ot_none);
+ code : #214#1#29#173;
+ flags : if_x86_64 or if_sm
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits32,ot_immediate,ot_none,ot_none);
+ code : #208#1#129#131#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits64,ot_immediate,ot_none,ot_none);
+ code : #214#1#129#131#173;
+ flags : if_x86_64 or if_sm
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_reg_ax,ot_immediate,ot_none,ot_none);
+ code : #212#1#29#25;
+ flags : if_8086 or if_sw
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16,ot_immediate,ot_none,ot_none);
+ code : #208#1#129#131#25;
+ flags : if_8086 or if_sw
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_reg_al,ot_immediate,ot_none,ot_none);
+ code : #1#28#17;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_SBB;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_immediate,ot_none,ot_none);
+ code : #1#128#131#17;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_SCASB;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #218#1#174;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SCASD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #218#213#1#175;
+ flags : if_386
+ ),
+ (
+ opcode : A_SCASQ;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #218#214#1#175;
+ flags : if_x86_64
+ ),
+ (
+ opcode : A_SCASW;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #218#212#1#175;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SEGCS;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#46;
+ flags : if_8086 or if_pre
+ ),
+ (
+ opcode : A_SEGDS;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#62;
+ flags : if_8086 or if_pre
+ ),
+ (
+ opcode : A_SEGES;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#38;
+ flags : if_8086 or if_pre
+ ),
+ (
+ opcode : A_SEGFS;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#100;
+ flags : if_8086 or if_pre
+ ),
+ (
+ opcode : A_SEGGS;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#101;
+ flags : if_8086 or if_pre
+ ),
+ (
+ opcode : A_SEGSS;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#54;
+ flags : if_8086 or if_pre
+ ),
+ (
+ opcode : A_SGDT;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #2#15#1#128;
+ flags : if_286
+ ),
+ (
+ opcode : A_SHL;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_unity,ot_none,ot_none);
+ code : #208#1#209#132;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SHL;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_reg_cl,ot_none,ot_none);
+ code : #208#1#211#132;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SHL;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_immediate,ot_none,ot_none);
+ code : #208#1#193#132#21;
+ flags : if_186 or if_sw
+ ),
+ (
+ opcode : A_SHL;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_unity,ot_none,ot_none);
+ code : #1#208#132;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SHL;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_reg_cl,ot_none,ot_none);
+ code : #1#210#132;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SHL;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_immediate,ot_none,ot_none);
+ code : #1#192#132#21;
+ flags : if_186 or if_sb
+ ),
+ (
+ opcode : A_SHLD;
+ ops : 3;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_reg16 or ot_bits32 or ot_bits64,ot_immediate,ot_none);
+ code : #209#2#15#164#65#22;
+ flags : if_386 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_SHLD;
+ ops : 3;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_reg16 or ot_bits32 or ot_bits64,ot_reg_cl,ot_none);
+ code : #209#2#15#165#65;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_SHR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_unity,ot_none,ot_none);
+ code : #208#1#209#133;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SHR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_reg_cl,ot_none,ot_none);
+ code : #208#1#211#133;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SHR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_immediate,ot_none,ot_none);
+ code : #208#1#193#133#21;
+ flags : if_186 or if_sw
+ ),
+ (
+ opcode : A_SHR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_unity,ot_none,ot_none);
+ code : #1#208#133;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SHR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_reg_cl,ot_none,ot_none);
+ code : #1#210#133;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SHR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_immediate,ot_none,ot_none);
+ code : #1#192#133#21;
+ flags : if_186 or if_sb
+ ),
+ (
+ opcode : A_SHRD;
+ ops : 3;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_reg16 or ot_bits32 or ot_bits64,ot_immediate,ot_none);
+ code : #209#2#15#172#65#22;
+ flags : if_386 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_SHRD;
+ ops : 3;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_reg16 or ot_bits32 or ot_bits64,ot_reg_cl,ot_none);
+ code : #209#2#15#173#65;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_SIDT;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #2#15#1#129;
+ flags : if_286
+ ),
+ (
+ opcode : A_SLDT;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #2#15#0#128;
+ flags : if_286
+ ),
+ (
+ opcode : A_SLDT;
+ ops : 1;
+ optypes : (ot_reg16 or ot_bits32 or ot_bits64,ot_none,ot_none,ot_none);
+ code : #208#2#15#0#128;
+ flags : if_286
+ ),
+ (
+ opcode : A_SMI;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#241;
+ flags : if_386 or if_undoc
+ ),
+ (
+ opcode : A_SMINT;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#15#56;
+ flags : if_p6 or if_cyrix
+ ),
+ (
+ opcode : A_SMINTOLD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#15#126;
+ flags : if_486 or if_cyrix
+ ),
+ (
+ opcode : A_SMSW;
+ ops : 1;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_none,ot_none,ot_none);
+ code : #208#2#15#1#132;
+ flags : if_286
+ ),
+ (
+ opcode : A_STC;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#249;
+ flags : if_8086
+ ),
+ (
+ opcode : A_STD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#253;
+ flags : if_8086
+ ),
+ (
+ opcode : A_STI;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#251;
+ flags : if_8086
+ ),
+ (
+ opcode : A_STOSB;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#170;
+ flags : if_8086
+ ),
+ (
+ opcode : A_STOSD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #213#1#171;
+ flags : if_386
+ ),
+ (
+ opcode : A_STOSW;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #212#1#171;
+ flags : if_8086
+ ),
+ (
+ opcode : A_STR;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #2#15#0#129;
+ flags : if_286 or if_prot
+ ),
+ (
+ opcode : A_STR;
+ ops : 1;
+ optypes : (ot_reg16 or ot_bits32 or ot_bits64,ot_none,ot_none,ot_none);
+ code : #208#2#15#0#129;
+ flags : if_286 or if_prot
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_rm_gpr,ot_reg16 or ot_bits32 or ot_bits64,ot_none,ot_none);
+ code : #208#1#41#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_reg16 or ot_bits32 or ot_bits64,ot_rm_gpr,ot_none,ot_none);
+ code : #208#1#43#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_reg8,ot_none,ot_none);
+ code : #1#40#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_reg8,ot_rm_gpr or ot_bits8,ot_none,ot_none);
+ code : #1#42#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_immediate or ot_bits8 or ot_signed,ot_none,ot_none);
+ code : #208#1#131#133#13;
+ flags : if_8086
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_reg_eax,ot_immediate,ot_none,ot_none);
+ code : #213#1#45#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_reg_rax,ot_immediate,ot_none,ot_none);
+ code : #214#1#45#173;
+ flags : if_x86_64 or if_sm
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits32,ot_immediate,ot_none,ot_none);
+ code : #208#1#129#133#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits64,ot_immediate,ot_none,ot_none);
+ code : #214#1#129#133#173;
+ flags : if_x86_64 or if_sm
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_reg_ax,ot_immediate,ot_none,ot_none);
+ code : #212#1#45#25;
+ flags : if_8086 or if_sw
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16,ot_immediate,ot_none,ot_none);
+ code : #212#1#129#133#25;
+ flags : if_8086 or if_sw
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_reg_al,ot_immediate,ot_none,ot_none);
+ code : #1#44#17;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_immediate,ot_none,ot_none);
+ code : #1#128#133#17;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_SVDC;
+ ops : 2;
+ optypes : (ot_memory or ot_bits80,ot_reg_sreg,ot_none,ot_none);
+ code : #2#15#120#65;
+ flags : if_486 or if_cyrix or if_smm
+ ),
+ (
+ opcode : A_SVLDT;
+ ops : 1;
+ optypes : (ot_memory or ot_bits80,ot_none,ot_none,ot_none);
+ code : #2#15#122#128;
+ flags : if_486 or if_cyrix or if_smm
+ ),
+ (
+ opcode : A_SVTS;
+ ops : 1;
+ optypes : (ot_memory or ot_bits80,ot_none,ot_none,ot_none);
+ code : #2#15#124#128;
+ flags : if_486 or if_cyrix or if_smm
+ ),
+ (
+ opcode : A_SYSCALL;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#15#5;
+ flags : if_p6 or if_amd
+ ),
+ (
+ opcode : A_SYSENTER;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#15#52;
+ flags : if_p6
+ ),
+ (
+ opcode : A_SYSEXIT;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#15#53;
+ flags : if_p6 or if_priv
+ ),
+ (
+ opcode : A_SYSRET;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#15#7;
+ flags : if_p6 or if_priv or if_amd
+ ),
+ (
+ opcode : A_TEST;
+ ops : 2;
+ optypes : (ot_rm_gpr,ot_reg16 or ot_bits32 or ot_bits64,ot_none,ot_none);
+ code : #208#1#133#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_TEST;
+ ops : 2;
+ optypes : (ot_reg16 or ot_bits32 or ot_bits64,ot_memory,ot_none,ot_none);
+ code : #208#1#133#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_TEST;
+ ops : 2;
+ optypes : (ot_reg8,ot_reg8,ot_none,ot_none);
+ code : #1#132#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_TEST;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_reg8,ot_none,ot_none);
+ code : #1#132#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_TEST;
+ ops : 2;
+ optypes : (ot_reg_rax,ot_immediate,ot_none,ot_none);
+ code : #214#1#169#173;
+ flags : if_x86_64 or if_sm
+ ),
+ (
+ opcode : A_TEST;
+ ops : 2;
+ optypes : (ot_reg_eax,ot_immediate,ot_none,ot_none);
+ code : #213#1#169#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_TEST;
+ ops : 2;
+ optypes : (ot_reg_ax,ot_immediate,ot_none,ot_none);
+ code : #212#1#169#25;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_TEST;
+ ops : 2;
+ optypes : (ot_reg_al,ot_immediate,ot_none,ot_none);
+ code : #1#168#17;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_TEST;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits64,ot_immediate,ot_none,ot_none);
+ code : #214#1#247#128#173;
+ flags : if_x86_64 or if_sm
+ ),
+ (
+ opcode : A_TEST;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits32,ot_immediate,ot_none,ot_none);
+ code : #213#1#247#128#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_TEST;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16,ot_immediate,ot_none,ot_none);
+ code : #212#1#247#128#25;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_TEST;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_immediate,ot_none,ot_none);
+ code : #1#246#128#17;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_TEST;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits32,ot_none,ot_none);
+ code : #213#1#247#128#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_TEST;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits16,ot_none,ot_none);
+ code : #212#1#247#128#25;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_TEST;
+ ops : 2;
+ optypes : (ot_memory,ot_immediate or ot_bits8,ot_none,ot_none);
+ code : #1#246#128#17;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_UD1;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#15#185;
+ flags : if_286 or if_undoc
+ ),
+ (
+ opcode : A_UD2;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#15#11;
+ flags : if_286
+ ),
+ (
+ opcode : A_UMOV;
+ ops : 2;
+ optypes : (ot_rm_gpr,ot_reg16 or ot_bits32 or ot_bits64,ot_none,ot_none);
+ code : #208#2#15#17#65;
+ flags : if_386 or if_undoc or if_sm
+ ),
+ (
+ opcode : A_UMOV;
+ ops : 2;
+ optypes : (ot_reg16 or ot_bits32 or ot_bits64,ot_memory,ot_none,ot_none);
+ code : #208#2#15#19#72;
+ flags : if_386 or if_undoc or if_sm
+ ),
+ (
+ opcode : A_UMOV;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_reg8,ot_none,ot_none);
+ code : #2#15#16#65;
+ flags : if_386 or if_undoc
+ ),
+ (
+ opcode : A_UMOV;
+ ops : 2;
+ optypes : (ot_reg8,ot_rm_gpr or ot_bits8,ot_none,ot_none);
+ code : #2#15#18#72;
+ flags : if_386 or if_undoc
+ ),
+ (
+ opcode : A_VERR;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #2#15#0#132;
+ flags : if_286 or if_prot
+ ),
+ (
+ opcode : A_VERR;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none,ot_none);
+ code : #2#15#0#132;
+ flags : if_286 or if_prot
+ ),
+ (
+ opcode : A_VERR;
+ ops : 1;
+ optypes : (ot_reg16,ot_none,ot_none,ot_none);
+ code : #2#15#0#132;
+ flags : if_286 or if_prot
+ ),
+ (
+ opcode : A_VERW;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #2#15#0#133;
+ flags : if_286 or if_prot
+ ),
+ (
+ opcode : A_VERW;
+ ops : 1;
+ optypes : (ot_memory or ot_bits16,ot_none,ot_none,ot_none);
+ code : #2#15#0#133;
+ flags : if_286 or if_prot
+ ),
+ (
+ opcode : A_VERW;
+ ops : 1;
+ optypes : (ot_reg16,ot_none,ot_none,ot_none);
+ code : #2#15#0#133;
+ flags : if_286 or if_prot
+ ),
+ (
+ opcode : A_WAIT;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#155;
+ flags : if_8086
+ ),
+ (
+ opcode : A_WBINVD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#15#9;
+ flags : if_486 or if_priv
+ ),
+ (
+ opcode : A_WRSHR;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#15#55;
+ flags : if_p6 or if_cyrix or if_smm
+ ),
+ (
+ opcode : A_WRMSR;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#15#48;
+ flags : if_pent or if_priv
+ ),
+ (
+ opcode : A_XADD;
+ ops : 2;
+ optypes : (ot_memory,ot_reg16 or ot_bits32 or ot_bits64,ot_none,ot_none);
+ code : #208#2#15#193#65;
+ flags : if_486 or if_sm
+ ),
+ (
+ opcode : A_XADD;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_reg8,ot_none,ot_none);
+ code : #2#15#192#65;
+ flags : if_486
+ ),
+ (
+ opcode : A_XBTS;
+ ops : 2;
+ optypes : (ot_reg16,ot_memory,ot_none,ot_none);
+ code : #212#2#15#166#72;
+ flags : if_386 or if_sw or if_undoc
+ ),
+ (
+ opcode : A_XBTS;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg16,ot_none,ot_none);
+ code : #212#2#15#166#72;
+ flags : if_386 or if_undoc
+ ),
+ (
+ opcode : A_XBTS;
+ ops : 2;
+ optypes : (ot_reg32,ot_memory,ot_none,ot_none);
+ code : #213#2#15#166#72;
+ flags : if_386 or if_sd or if_undoc
+ ),
+ (
+ opcode : A_XBTS;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #213#2#15#166#72;
+ flags : if_386 or if_undoc
+ ),
+ (
+ opcode : A_XCHG;
+ ops : 2;
+ optypes : (ot_reg_ax,ot_reg16,ot_none,ot_none);
+ code : #212#9#144;
+ flags : if_8086
+ ),
+ (
+ opcode : A_XCHG;
+ ops : 2;
+ optypes : (ot_reg_eax,ot_reg32,ot_none,ot_none);
+ code : #213#9#144;
+ flags : if_386
+ ),
+ (
+ opcode : A_XCHG;
+ ops : 2;
+ optypes : (ot_reg_rax,ot_reg64,ot_none,ot_none);
+ code : #214#9#144;
+ flags : if_x86_64
+ ),
+ (
+ opcode : A_XCHG;
+ ops : 2;
+ optypes : (ot_reg16,ot_reg_ax,ot_none,ot_none);
+ code : #212#8#144;
+ flags : if_8086
+ ),
+ (
+ opcode : A_XCHG;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg_eax,ot_none,ot_none);
+ code : #213#8#144;
+ flags : if_386
+ ),
+ (
+ opcode : A_XCHG;
+ ops : 2;
+ optypes : (ot_reg64,ot_reg_rax,ot_none,ot_none);
+ code : #214#8#144;
+ flags : if_x86_64
+ ),
+ (
+ opcode : A_XCHG;
+ ops : 2;
+ optypes : (ot_reg16 or ot_bits32 or ot_bits64,ot_rm_gpr,ot_none,ot_none);
+ code : #208#1#135#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_XCHG;
+ ops : 2;
+ optypes : (ot_memory,ot_reg16 or ot_bits32 or ot_bits64,ot_none,ot_none);
+ code : #208#1#135#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_XCHG;
+ ops : 2;
+ optypes : (ot_reg8,ot_rm_gpr or ot_bits8,ot_none,ot_none);
+ code : #1#134#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_XCHG;
+ ops : 2;
+ optypes : (ot_memory or ot_bits8,ot_reg8,ot_none,ot_none);
+ code : #1#134#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_XLAT;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#215;
+ flags : if_8086
+ ),
+ (
+ opcode : A_XLATB;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #1#215;
+ flags : if_8086
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_rm_gpr,ot_reg16 or ot_bits32 or ot_bits64,ot_none,ot_none);
+ code : #208#1#49#65;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_reg16 or ot_bits32 or ot_bits64,ot_rm_gpr,ot_none,ot_none);
+ code : #208#1#51#72;
+ flags : if_8086 or if_sm
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_reg8,ot_none,ot_none);
+ code : #1#48#65;
+ flags : if_8086
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_reg8,ot_rm_gpr or ot_bits8,ot_none,ot_none);
+ code : #1#50#72;
+ flags : if_8086
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16 or ot_bits32 or ot_bits64,ot_immediate or ot_bits8 or ot_signed,ot_none,ot_none);
+ code : #208#1#131#134#13;
+ flags : if_8086
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_reg_eax,ot_immediate,ot_none,ot_none);
+ code : #213#1#53#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_reg_rax,ot_immediate,ot_none,ot_none);
+ code : #214#1#53#173;
+ flags : if_x86_64 or if_sm
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits32,ot_immediate,ot_none,ot_none);
+ code : #208#1#129#134#33;
+ flags : if_386 or if_sm
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits64,ot_immediate,ot_none,ot_none);
+ code : #214#1#129#134#173;
+ flags : if_x86_64 or if_sm
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_reg_ax,ot_immediate,ot_none,ot_none);
+ code : #212#1#53#25;
+ flags : if_8086 or if_sw
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits16,ot_immediate,ot_none,ot_none);
+ code : #212#1#129#134#25;
+ flags : if_8086 or if_sw
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_reg_al,ot_immediate,ot_none,ot_none);
+ code : #1#52#17;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_XOR;
+ ops : 2;
+ optypes : (ot_rm_gpr or ot_bits8,ot_immediate,ot_none,ot_none);
+ code : #1#128#134#17;
+ flags : if_8086 or if_sb
+ ),
+ (
+ opcode : A_XSTORE;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #3#15#167#192;
+ flags : if_p6 or if_cyrix
+ ),
+ (
+ opcode : A_XCRYPTECB;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #219#3#15#167#200;
+ flags : if_p6 or if_cyrix
+ ),
+ (
+ opcode : A_XCRYPTCBC;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #219#3#15#167#208;
+ flags : if_p6 or if_cyrix
+ ),
+ (
+ opcode : A_XCRYPTCFB;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #219#3#15#167#224;
+ flags : if_p6 or if_cyrix
+ ),
+ (
+ opcode : A_XCRYPTOFB;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #219#3#15#167#232;
+ flags : if_p6 or if_cyrix
+ ),
+ (
+ opcode : A_CMOVcc;
+ ops : 2;
+ optypes : (ot_reg16 or ot_bits32 or ot_bits64,ot_rm_gpr,ot_none,ot_none);
+ code : #208#1#15#11#64#72;
+ flags : if_p6 or if_sm
+ ),
+ (
+ opcode : A_Jcc;
+ ops : 1;
+ optypes : (ot_immediate or ot_bits8,ot_none,ot_none,ot_none);
+ code : #11#112#40;
+ flags : if_8086
+ ),
+ (
+ opcode : A_Jcc;
+ ops : 1;
+ optypes : (ot_immediate or ot_bits16 or ot_bits32,ot_none,ot_none,ot_none);
+ code : #208#1#15#11#128#52;
+ flags : if_386 or if_pass2
+ ),
+ (
+ opcode : A_Jcc;
+ ops : 1;
+ optypes : (ot_immediate or ot_short,ot_none,ot_none,ot_none);
+ code : #11#112#40;
+ flags : if_8086
+ ),
+ (
+ opcode : A_Jcc;
+ ops : 1;
+ optypes : (ot_immediate or ot_near,ot_none,ot_none,ot_none);
+ code : #208#1#15#11#128#52;
+ flags : if_386 or if_pass2
+ ),
+ (
+ opcode : A_SETcc;
+ ops : 1;
+ optypes : (ot_rm_gpr or ot_bits8,ot_none,ot_none,ot_none);
+ code : #1#15#11#144#128;
+ flags : if_386
+ ),
+ (
+ opcode : A_ADDPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #217#2#15#88#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_ADDSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #219#2#15#88#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_ANDNPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #2#15#85#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_ANDPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #2#15#84#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPEQPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #217#2#15#194#72#1#0;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPEQSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #219#2#15#194#72#1#0;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPLEPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #217#2#15#194#72#1#2;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPLESS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #219#2#15#194#72#1#2;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPLTPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #217#2#15#194#72#1#1;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPLTSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #219#2#15#194#72#1#1;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPNEQPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #217#2#15#194#72#1#4;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPNEQSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #219#2#15#194#72#1#4;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPNLEPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #217#2#15#194#72#1#6;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPNLESS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #219#2#15#194#72#1#6;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPNLTPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #217#2#15#194#72#1#5;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPNLTSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #219#2#15#194#72#1#5;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPORDPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #217#2#15#194#72#1#7;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPORDSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #219#2#15#194#72#1#7;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPUNORDPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #217#2#15#194#72#1#3;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPUNORDSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #219#2#15#194#72#1#3;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CMPPS;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_immediate,ot_none);
+ code : #217#2#15#194#72#18;
+ flags : if_katmai or if_sse or if_sb or if_ar2
+ ),
+ (
+ opcode : A_CMPSS;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_immediate,ot_none);
+ code : #219#2#15#194#72#18;
+ flags : if_katmai or if_sse or if_sb or if_ar2
+ ),
+ (
+ opcode : A_COMISS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #2#15#47#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CVTPI2PS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none,ot_none);
+ code : #217#2#15#42#72;
+ flags : if_katmai or if_sse or if_mmx
+ ),
+ (
+ opcode : A_CVTPI2PS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_mmxreg,ot_none,ot_none);
+ code : #217#2#15#42#72;
+ flags : if_katmai or if_sse or if_mmx
+ ),
+ (
+ opcode : A_CVTPS2PI;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none,ot_none);
+ code : #217#2#15#45#72;
+ flags : if_katmai or if_sse or if_mmx
+ ),
+ (
+ opcode : A_CVTPS2PI;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_xmmreg,ot_none,ot_none);
+ code : #217#2#15#45#72;
+ flags : if_katmai or if_sse or if_mmx
+ ),
+ (
+ opcode : A_CVTSI2SS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none,ot_none);
+ code : #219#209#2#15#42#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CVTSI2SS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_reg32 or ot_bits64,ot_none,ot_none);
+ code : #219#209#2#15#42#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CVTSS2SI;
+ ops : 2;
+ optypes : (ot_reg32 or ot_bits64,ot_memory,ot_none,ot_none);
+ code : #219#208#2#15#45#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CVTSS2SI;
+ ops : 2;
+ optypes : (ot_reg32 or ot_bits64,ot_xmmreg,ot_none,ot_none);
+ code : #219#208#2#15#45#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CVTTPS2PI;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none,ot_none);
+ code : #217#2#15#44#72;
+ flags : if_katmai or if_sse or if_mmx
+ ),
+ (
+ opcode : A_CVTTPS2PI;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_xmmreg,ot_none,ot_none);
+ code : #217#2#15#44#72;
+ flags : if_katmai or if_sse or if_mmx
+ ),
+ (
+ opcode : A_CVTTSS2SI;
+ ops : 2;
+ optypes : (ot_reg32 or ot_bits64,ot_memory,ot_none,ot_none);
+ code : #219#208#2#15#44#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_CVTTSS2SI;
+ ops : 2;
+ optypes : (ot_reg32 or ot_bits64,ot_xmmreg,ot_none,ot_none);
+ code : #219#208#2#15#44#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_DIVPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #217#2#15#94#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_DIVSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #219#2#15#94#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_LDMXCSR;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #2#15#174#130;
+ flags : if_katmai or if_sse or if_sd
+ ),
+ (
+ opcode : A_MAXPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #217#2#15#95#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MAXSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #219#2#15#95#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MINPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #217#2#15#93#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MINSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #219#2#15#93#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVAPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #2#15#40#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVAPS;
+ ops : 2;
+ optypes : (ot_xmmrm,ot_xmmreg,ot_none,ot_none);
+ code : #2#15#41#65;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVHPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none,ot_none);
+ code : #2#15#22#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVHPS;
+ ops : 2;
+ optypes : (ot_memory,ot_xmmreg,ot_none,ot_none);
+ code : #2#15#23#65;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVLHPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none,ot_none);
+ code : #2#15#22#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVLPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none,ot_none);
+ code : #2#15#18#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVLPS;
+ ops : 2;
+ optypes : (ot_memory,ot_xmmreg,ot_none,ot_none);
+ code : #2#15#19#65;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVHLPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none,ot_none);
+ code : #2#15#18#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVMSKPS;
+ ops : 2;
+ optypes : (ot_reg32,ot_xmmreg,ot_none,ot_none);
+ code : #2#15#80#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVNTPS;
+ ops : 2;
+ optypes : (ot_memory,ot_xmmreg,ot_none,ot_none);
+ code : #2#15#43#65;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #219#2#15#16#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVSS;
+ ops : 2;
+ optypes : (ot_xmmrm,ot_xmmreg,ot_none,ot_none);
+ code : #219#2#15#17#65;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVUPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #217#2#15#16#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MOVUPS;
+ ops : 2;
+ optypes : (ot_xmmrm,ot_xmmreg,ot_none,ot_none);
+ code : #217#2#15#17#65;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MULPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #2#15#89#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_MULSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #219#2#15#89#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_ORPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #2#15#86#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_RCPPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #217#2#15#83#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_RCPSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #219#2#15#83#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_RSQRTPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #217#2#15#82#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_RSQRTSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #219#2#15#82#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_SHUFPS;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_immediate,ot_none);
+ code : #2#15#198#72#18;
+ flags : if_katmai or if_sse or if_sb or if_ar2
+ ),
+ (
+ opcode : A_SQRTPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #217#2#15#81#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_SQRTSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #219#2#15#81#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_STMXCSR;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #2#15#174#131;
+ flags : if_katmai or if_sse or if_sd
+ ),
+ (
+ opcode : A_SUBPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #217#2#15#92#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_SUBSS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #219#2#15#92#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_UCOMISS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #2#15#46#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_UNPCKHPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #2#15#21#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_UNPCKLPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #2#15#20#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_XORPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #2#15#87#72;
+ flags : if_katmai or if_sse
+ ),
+ (
+ opcode : A_FXRSTOR;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #2#15#174#129;
+ flags : if_p6 or if_sse or if_fpu
+ ),
+ (
+ opcode : A_FXSAVE;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #2#15#174#128;
+ flags : if_p6 or if_sse or if_fpu
+ ),
+ (
+ opcode : A_PREFETCHNTA;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #2#15#24#128;
+ flags : if_katmai
+ ),
+ (
+ opcode : A_PREFETCHT0;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #2#15#24#129;
+ flags : if_katmai
+ ),
+ (
+ opcode : A_PREFETCHT1;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #2#15#24#130;
+ flags : if_katmai
+ ),
+ (
+ opcode : A_PREFETCHT2;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #2#15#24#131;
+ flags : if_katmai
+ ),
+ (
+ opcode : A_SFENCE;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #3#15#174#248;
+ flags : if_katmai
+ ),
+ (
+ opcode : A_MASKMOVQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxreg,ot_none,ot_none);
+ code : #2#15#247#72;
+ flags : if_katmai or if_mmx
+ ),
+ (
+ opcode : A_MOVNTQ;
+ ops : 2;
+ optypes : (ot_memory,ot_mmxreg,ot_none,ot_none);
+ code : #2#15#231#65;
+ flags : if_katmai or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PAVGB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#224#72;
+ flags : if_katmai or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PAVGB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#224#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PAVGW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#227#72;
+ flags : if_katmai or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PAVGW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#227#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PEXTRW;
+ ops : 3;
+ optypes : (ot_reg32,ot_mmxreg,ot_immediate,ot_none);
+ code : #2#15#197#72#18;
+ flags : if_katmai or if_mmx or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PEXTRW;
+ ops : 3;
+ optypes : (ot_reg32,ot_xmmreg,ot_immediate,ot_none);
+ code : #241#2#15#197#72#22;
+ flags : if_sse41
+ ),
+ (
+ opcode : A_PEXTRW;
+ ops : 3;
+ optypes : (ot_memory or ot_bits32,ot_xmmreg,ot_immediate,ot_none);
+ code : #241#3#15#58#21#65#22;
+ flags : if_sse41
+ ),
+ (
+ opcode : A_PINSRW;
+ ops : 3;
+ optypes : (ot_mmxreg,ot_reg16,ot_immediate,ot_none);
+ code : #2#15#196#72#18;
+ flags : if_katmai or if_mmx or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PINSRW;
+ ops : 3;
+ optypes : (ot_mmxreg,ot_reg32,ot_immediate,ot_none);
+ code : #2#15#196#72#18;
+ flags : if_katmai or if_mmx or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PINSRW;
+ ops : 3;
+ optypes : (ot_mmxreg,ot_memory,ot_immediate,ot_none);
+ code : #2#15#196#72#18;
+ flags : if_katmai or if_mmx or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PINSRW;
+ ops : 3;
+ optypes : (ot_mmxreg,ot_memory or ot_bits16,ot_immediate,ot_none);
+ code : #2#15#196#72#18;
+ flags : if_katmai or if_mmx or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PINSRW;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_reg16,ot_immediate,ot_none);
+ code : #241#2#15#196#72#22;
+ flags : if_willamette or if_sse2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PINSRW;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_reg32,ot_immediate,ot_none);
+ code : #241#2#15#196#72#22;
+ flags : if_willamette or if_sse2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PINSRW;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_memory,ot_immediate,ot_none);
+ code : #241#2#15#196#72#22;
+ flags : if_willamette or if_sse2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PINSRW;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_memory or ot_bits16,ot_immediate,ot_none);
+ code : #241#2#15#196#72#22;
+ flags : if_willamette or if_sse2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PMAXSW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#238#72;
+ flags : if_katmai or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PMAXSW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#238#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PMAXUB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#222#72;
+ flags : if_katmai or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PMAXUB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#222#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PMINSW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#234#72;
+ flags : if_katmai or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PMINSW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#234#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PMINUB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#218#72;
+ flags : if_katmai or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PMINUB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#218#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PMOVMSKB;
+ ops : 2;
+ optypes : (ot_reg32,ot_mmxreg,ot_none,ot_none);
+ code : #2#15#215#72;
+ flags : if_katmai or if_mmx
+ ),
+ (
+ opcode : A_PMOVMSKB;
+ ops : 2;
+ optypes : (ot_reg32,ot_xmmreg,ot_none,ot_none);
+ code : #241#2#15#215#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PMULHUW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#228#72;
+ flags : if_katmai or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PMULHUW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#228#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSADBW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#246#72;
+ flags : if_katmai or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSADBW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#246#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSHUFW;
+ ops : 3;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_immediate,ot_none);
+ code : #2#15#112#72#18;
+ flags : if_katmai or if_mmx or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PFNACC;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#15#72#1#138;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PFPNACC;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#15#72#1#142;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PI2FW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#15#72#1#12;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PF2IW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#15#72#1#28;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_PSWAPD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#15#72#1#187;
+ flags : if_pent or if_3dnow or if_sm
+ ),
+ (
+ opcode : A_FFREEP;
+ ops : 1;
+ optypes : (ot_fpureg,ot_none,ot_none,ot_none);
+ code : #1#223#8#192;
+ flags : if_pent or if_3dnow or if_fpu
+ ),
+ (
+ opcode : A_MASKMOVDQU;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none,ot_none);
+ code : #241#2#15#247#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CLFLUSH;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #2#15#174#135;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVNTDQ;
+ ops : 2;
+ optypes : (ot_memory,ot_xmmreg,ot_none,ot_none);
+ code : #241#2#15#231#65;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_MOVNTI;
+ ops : 2;
+ optypes : (ot_memory,ot_reg32 or ot_bits64,ot_none,ot_none);
+ code : #208#2#15#195#65;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_MOVNTPD;
+ ops : 2;
+ optypes : (ot_memory,ot_xmmreg,ot_none,ot_none);
+ code : #241#2#15#43#65;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PAUSE;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #219#1#144;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_LFENCE;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #3#15#174#232;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MFENCE;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #3#15#174#240;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVDQA;
+ ops : 2;
+ optypes : (ot_xmmrm,ot_xmmreg,ot_none,ot_none);
+ code : #241#2#15#127#65;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_MOVDQA;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#111#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_MOVDQU;
+ ops : 2;
+ optypes : (ot_xmmrm,ot_xmmreg,ot_none,ot_none);
+ code : #219#2#15#127#65;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_MOVDQU;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #219#2#15#111#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_MOVDQ2Q;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_xmmreg,ot_none,ot_none);
+ code : #220#2#15#214#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVQ2DQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_mmxreg,ot_none,ot_none);
+ code : #219#2#15#214#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_PADDQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#212#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PADDQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#212#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PMULUDQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#244#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PMULUDQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#244#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSHUFD;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_immediate,ot_none);
+ code : #241#2#15#112#72#18;
+ flags : if_willamette or if_sse2 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PSHUFHW;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_immediate,ot_none);
+ code : #219#2#15#112#72#18;
+ flags : if_willamette or if_sse2 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PSHUFLW;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_immediate,ot_none);
+ code : #220#2#15#112#72#18;
+ flags : if_willamette or if_sse2 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PSRLDQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_immediate,ot_none,ot_none);
+ code : #241#2#15#115#131#21;
+ flags : if_willamette or if_sse2 or if_sb or if_ar1
+ ),
+ (
+ opcode : A_PSUBQ;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #2#15#251#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PSUBQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#251#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PUNPCKHQDQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#109#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_PUNPCKLQDQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#108#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_ADDPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#88#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_ADDSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #220#2#15#88#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_ANDNPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#85#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_ANDPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#84#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_CMPEQPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#194#72#1#0;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_CMPEQSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #220#2#15#194#72#1#0;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CMPLEPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#194#72#1#2;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_CMPLESD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #220#2#15#194#72#1#2;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CMPLTPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#194#72#1#1;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_CMPLTSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #220#2#15#194#72#1#1;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CMPNEQPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#194#72#1#4;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_CMPNEQSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #220#2#15#194#72#1#4;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CMPNLEPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#194#72#1#6;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_CMPNLESD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #220#2#15#194#72#1#6;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CMPNLTPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#194#72#1#5;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_CMPNLTSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #220#2#15#194#72#1#5;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CMPORDPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#194#72#1#7;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_CMPORDSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #220#2#15#194#72#1#7;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CMPUNORDPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#194#72#1#3;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_CMPUNORDSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #220#2#15#194#72#1#3;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CMPPD;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_immediate,ot_none);
+ code : #241#2#15#194#72#22;
+ flags : if_willamette or if_sse2 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_COMISD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#47#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTDQ2PD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #219#2#15#230#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTDQ2PS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #2#15#91#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_CVTPD2DQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #220#2#15#230#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_CVTPD2PI;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#45#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTPD2PS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#90#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_CVTPI2PD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_mmxrm,ot_none,ot_none);
+ code : #241#2#15#42#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTPS2DQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#91#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_CVTPS2PD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #2#15#90#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTSD2SI;
+ ops : 2;
+ optypes : (ot_reg32 or ot_bits64,ot_xmmreg,ot_none,ot_none);
+ code : #220#208#2#15#45#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTSD2SI;
+ ops : 2;
+ optypes : (ot_reg32 or ot_bits64,ot_memory,ot_none,ot_none);
+ code : #220#208#2#15#45#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTSD2SS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #220#2#15#90#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTSI2SD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_reg32 or ot_bits64,ot_none,ot_none);
+ code : #220#209#2#15#42#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTSI2SD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none,ot_none);
+ code : #220#209#2#15#42#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTSS2SD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #219#2#15#90#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTTPD2PI;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_xmmreg,ot_none,ot_none);
+ code : #241#2#15#44#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTTPD2PI;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_memory,ot_none,ot_none);
+ code : #241#2#15#44#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTTPD2DQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#230#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_CVTTPS2DQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #219#2#15#91#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_CVTTSD2SI;
+ ops : 2;
+ optypes : (ot_reg32 or ot_bits64,ot_xmmreg,ot_none,ot_none);
+ code : #220#208#2#15#44#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_CVTTSD2SI;
+ ops : 2;
+ optypes : (ot_reg32 or ot_bits64,ot_memory,ot_none,ot_none);
+ code : #220#208#2#15#44#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_DIVPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#94#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_DIVSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #220#2#15#94#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MAXPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#95#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_MAXSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #220#2#15#95#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MINPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#93#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_MINSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #220#2#15#93#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVAPD;
+ ops : 2;
+ optypes : (ot_xmmrm,ot_xmmreg,ot_none,ot_none);
+ code : #241#2#15#41#65;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_MOVAPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#40#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_MOVHPD;
+ ops : 2;
+ optypes : (ot_memory,ot_xmmreg,ot_none,ot_none);
+ code : #241#2#15#23#65;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVHPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none,ot_none);
+ code : #241#2#15#22#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVLPD;
+ ops : 2;
+ optypes : (ot_memory,ot_xmmreg,ot_none,ot_none);
+ code : #241#2#15#19#65;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVLPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none,ot_none);
+ code : #241#2#15#18#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVMSKPD;
+ ops : 2;
+ optypes : (ot_reg32,ot_xmmreg,ot_none,ot_none);
+ code : #241#2#15#80#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_MOVUPD;
+ ops : 2;
+ optypes : (ot_xmmrm,ot_xmmreg,ot_none,ot_none);
+ code : #241#2#15#17#65;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_MOVUPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#16#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_MULPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#89#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_MULSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #220#2#15#89#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_ORPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#86#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_SHUFPD;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_immediate,ot_none);
+ code : #241#2#15#198#72#22;
+ flags : if_willamette or if_sse2 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_SQRTPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#81#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_SQRTSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #220#2#15#81#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_SUBPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#92#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_SUBSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #220#2#15#92#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_UCOMISD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#46#72;
+ flags : if_willamette or if_sse2
+ ),
+ (
+ opcode : A_UNPCKHPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#21#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_UNPCKLPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#20#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_XORPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#87#72;
+ flags : if_willamette or if_sse2 or if_sm
+ ),
+ (
+ opcode : A_ADDSUBPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#208#72;
+ flags : if_prescott or if_sse3 or if_sm
+ ),
+ (
+ opcode : A_ADDSUBPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #220#2#15#208#72;
+ flags : if_prescott or if_sse3 or if_sm
+ ),
+ (
+ opcode : A_HADDPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#124#72;
+ flags : if_prescott or if_sse3 or if_sm
+ ),
+ (
+ opcode : A_HADDPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #220#2#15#124#72;
+ flags : if_prescott or if_sse3 or if_sm
+ ),
+ (
+ opcode : A_HSUBPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#2#15#125#72;
+ flags : if_prescott or if_sse3 or if_sm
+ ),
+ (
+ opcode : A_HSUBPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #220#2#15#125#72;
+ flags : if_prescott or if_sse3 or if_sm
+ ),
+ (
+ opcode : A_LDDQU;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none,ot_none);
+ code : #220#2#15#240#72;
+ flags : if_prescott or if_sse3
+ ),
+ (
+ opcode : A_MOVDDUP;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #220#2#15#18#72;
+ flags : if_prescott or if_sse3
+ ),
+ (
+ opcode : A_MOVSHDUP;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #219#2#15#22#72;
+ flags : if_prescott or if_sse3 or if_sm
+ ),
+ (
+ opcode : A_MOVSLDUP;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #219#2#15#18#72;
+ flags : if_prescott or if_sse3 or if_sm
+ ),
+ (
+ opcode : A_VMREAD;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #2#15#120#65;
+ flags : if_386 or if_priv or if_prot
+ ),
+ (
+ opcode : A_VMREAD;
+ ops : 2;
+ optypes : (ot_memory,ot_reg32,ot_none,ot_none);
+ code : #2#15#120#65;
+ flags : if_386 or if_priv or if_prot or if_sm
+ ),
+ (
+ opcode : A_VMWRITE;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #2#15#121#72;
+ flags : if_386 or if_priv or if_prot
+ ),
+ (
+ opcode : A_VMWRITE;
+ ops : 2;
+ optypes : (ot_reg32,ot_memory,ot_none,ot_none);
+ code : #2#15#121#72;
+ flags : if_386 or if_priv or if_prot or if_sm
+ ),
+ (
+ opcode : A_VMCALL;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #3#15#1#193;
+ flags : if_386 or if_priv or if_prot
+ ),
+ (
+ opcode : A_VMLAUNCH;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #3#15#1#194;
+ flags : if_386 or if_priv or if_prot
+ ),
+ (
+ opcode : A_VMRESUME;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #3#15#1#195;
+ flags : if_386 or if_priv or if_prot
+ ),
+ (
+ opcode : A_VMXOFF;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #3#15#1#196;
+ flags : if_386 or if_priv or if_prot
+ ),
+ (
+ opcode : A_VMXON;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #219#2#15#199#134;
+ flags : if_priv or if_prot
+ ),
+ (
+ opcode : A_VMCLEAR;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #241#2#15#199#134;
+ flags : if_priv or if_prot
+ ),
+ (
+ opcode : A_VMPTRLD;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #2#15#199#134;
+ flags : if_priv or if_prot
+ ),
+ (
+ opcode : A_VMPTRST;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #2#15#199#135;
+ flags : if_priv or if_prot
+ ),
+ (
+ opcode : A_VMRUN;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #3#15#1#216;
+ flags : if_386 or if_svm or if_priv or if_prot
+ ),
+ (
+ opcode : A_VMMCALL;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #3#15#1#217;
+ flags : if_386 or if_svm
+ ),
+ (
+ opcode : A_VMLOAD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #3#15#1#218;
+ flags : if_386 or if_svm or if_priv or if_prot
+ ),
+ (
+ opcode : A_VMSAVE;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #3#15#1#219;
+ flags : if_386 or if_svm or if_priv or if_prot
+ ),
+ (
+ opcode : A_STGI;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #3#15#1#220;
+ flags : if_386 or if_svm or if_priv or if_prot
+ ),
+ (
+ opcode : A_CLGI;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #3#15#1#221;
+ flags : if_386 or if_svm or if_priv or if_prot
+ ),
+ (
+ opcode : A_SKINIT;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #3#15#1#222;
+ flags : if_386 or if_svm or if_priv or if_prot
+ ),
+ (
+ opcode : A_INVLPGA;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #3#15#1#223;
+ flags : if_386 or if_svm or if_priv or if_prot
+ ),
+ (
+ opcode : A_MONTMUL;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #219#3#15#166#192;
+ flags : if_centaur
+ ),
+ (
+ opcode : A_XSHA1;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #219#3#15#166#200;
+ flags : if_centaur
+ ),
+ (
+ opcode : A_XSHA256;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #219#3#15#166#208;
+ flags : if_centaur
+ ),
+ (
+ opcode : A_DMINT;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#15#57;
+ flags : if_p6 or if_cyrix
+ ),
+ (
+ opcode : A_RDM;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #2#15#58;
+ flags : if_p6 or if_cyrix
+ ),
+ (
+ opcode : A_MOVABS;
+ ops : 2;
+ optypes : (ot_reg_al,ot_mem_offs,ot_none,ot_none);
+ code : #1#160#37;
+ flags : if_x86_64 or if_sm
+ ),
+ (
+ opcode : A_MOVABS;
+ ops : 2;
+ optypes : (ot_reg_ax or ot_bits32 or ot_bits64,ot_mem_offs,ot_none,ot_none);
+ code : #208#1#161#37;
+ flags : if_x86_64 or if_sm
+ ),
+ (
+ opcode : A_MOVABS;
+ ops : 2;
+ optypes : (ot_mem_offs,ot_reg_al,ot_none,ot_none);
+ code : #1#162#36;
+ flags : if_x86_64 or if_sm
+ ),
+ (
+ opcode : A_MOVABS;
+ ops : 2;
+ optypes : (ot_mem_offs,ot_reg_ax or ot_bits32 or ot_bits64,ot_none,ot_none);
+ code : #209#163#36;
+ flags : if_x86_64 or if_sm
+ ),
+ (
+ opcode : A_MOVABS;
+ ops : 2;
+ optypes : (ot_reg64,ot_immediate,ot_none,ot_none);
+ code : #214#8#184#45;
+ flags : if_x86_64
+ ),
+ (
+ opcode : A_MOVSXD;
+ ops : 2;
+ optypes : (ot_reg64,ot_memory,ot_none,ot_none);
+ code : #214#1#99#72;
+ flags : if_x86_64
+ ),
+ (
+ opcode : A_MOVSXD;
+ ops : 2;
+ optypes : (ot_reg64,ot_reg32,ot_none,ot_none);
+ code : #214#1#99#72;
+ flags : if_x86_64
+ ),
+ (
+ opcode : A_CQO;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #214#1#153;
+ flags : if_x86_64
+ ),
+ (
+ opcode : A_CMPXCHG16B;
+ ops : 1;
+ optypes : (ot_memory,ot_none,ot_none,ot_none);
+ code : #214#2#15#199#129;
+ flags : if_x86_64
+ ),
+ (
+ opcode : A_MOVNTSS;
+ ops : 2;
+ optypes : (ot_memory,ot_xmmreg,ot_none,ot_none);
+ code : #219#2#15#43#65;
+ flags : if_sse4 or if_sd
+ ),
+ (
+ opcode : A_MOVNTSD;
+ ops : 2;
+ optypes : (ot_memory,ot_xmmreg,ot_none,ot_none);
+ code : #220#213#2#15#43#65;
+ flags : if_sse4
+ ),
+ (
+ opcode : A_INSERTQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none,ot_none);
+ code : #220#2#15#121#72;
+ flags : if_sse4
+ ),
+ (
+ opcode : A_INSERTQ;
+ ops : 4;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_immediate,ot_immediate);
+ code : #220#2#15#120#72#22#23;
+ flags : if_sse4 or if_sb
+ ),
+ (
+ opcode : A_EXTRQ;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_immediate,ot_immediate,ot_none);
+ code : #241#2#15#120#128#21#22;
+ flags : if_sse4 or if_sb
+ ),
+ (
+ opcode : A_EXTRQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmreg,ot_none,ot_none);
+ code : #241#2#15#121#72;
+ flags : if_sse4
+ ),
+ (
+ opcode : A_LZCNT;
+ ops : 2;
+ optypes : (ot_reg16,ot_rm_gpr,ot_none,ot_none);
+ code : #208#219#2#15#189#72;
+ flags : if_386 or if_sm or if_sse4
+ ),
+ (
+ opcode : A_LZCNT;
+ ops : 2;
+ optypes : (ot_reg32 or ot_bits64,ot_rm_gpr,ot_none,ot_none);
+ code : #209#219#2#15#189#72;
+ flags : if_386 or if_sm or if_sse4
+ ),
+ (
+ opcode : A_PABSB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #217#3#15#56#28#72;
+ flags : if_ssse3 or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PABSB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#28#72;
+ flags : if_ssse3 or if_sm
+ ),
+ (
+ opcode : A_PABSW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #217#3#15#56#29#72;
+ flags : if_ssse3 or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PABSW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#29#72;
+ flags : if_ssse3 or if_sm
+ ),
+ (
+ opcode : A_PABSD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #217#3#15#56#30#72;
+ flags : if_ssse3 or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PABSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#30#72;
+ flags : if_ssse3 or if_sm
+ ),
+ (
+ opcode : A_PALIGNR;
+ ops : 3;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_immediate,ot_none);
+ code : #217#3#15#58#15#72#22;
+ flags : if_ssse3 or if_mmx or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PALIGNR;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_immediate,ot_none);
+ code : #241#3#15#58#15#72#22;
+ flags : if_ssse3 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PHADDW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #217#3#15#56#1#72;
+ flags : if_ssse3 or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PHADDW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#1#72;
+ flags : if_ssse3 or if_sm
+ ),
+ (
+ opcode : A_PHADDD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #217#3#15#56#2#72;
+ flags : if_ssse3 or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PHADDD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#2#72;
+ flags : if_ssse3 or if_sm
+ ),
+ (
+ opcode : A_PHADDSW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #217#3#15#56#3#72;
+ flags : if_ssse3 or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PHADDSW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#3#72;
+ flags : if_ssse3 or if_sm
+ ),
+ (
+ opcode : A_PHSUBW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #217#3#15#56#5#72;
+ flags : if_ssse3 or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PHSUBW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#5#72;
+ flags : if_ssse3 or if_sm
+ ),
+ (
+ opcode : A_PHSUBD;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #217#3#15#56#6#72;
+ flags : if_ssse3 or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PHSUBD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#6#72;
+ flags : if_ssse3 or if_sm
+ ),
+ (
+ opcode : A_PHSUBSW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #217#3#15#56#7#72;
+ flags : if_ssse3 or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PHSUBSW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#7#72;
+ flags : if_ssse3 or if_sm
+ ),
+ (
+ opcode : A_PMADDUBSW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #217#3#15#56#4#72;
+ flags : if_ssse3 or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PMADDUBSW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#4#72;
+ flags : if_ssse3 or if_sm
+ ),
+ (
+ opcode : A_PMULHRSW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #217#3#15#56#11#72;
+ flags : if_ssse3 or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PMULHRSW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#11#72;
+ flags : if_ssse3 or if_sm
+ ),
+ (
+ opcode : A_PSHUFB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #217#3#15#56#0#72;
+ flags : if_ssse3 or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSHUFB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#0#72;
+ flags : if_ssse3 or if_sm
+ ),
+ (
+ opcode : A_PSIGNB;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #217#3#15#56#8#72;
+ flags : if_ssse3 or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSIGNB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#8#72;
+ flags : if_ssse3 or if_sm
+ ),
+ (
+ opcode : A_PSIGNW;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #217#3#15#56#9#72;
+ flags : if_ssse3 or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSIGNW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#9#72;
+ flags : if_ssse3 or if_sm
+ ),
+ (
+ opcode : A_PSIGND;
+ ops : 2;
+ optypes : (ot_mmxreg,ot_mmxrm,ot_none,ot_none);
+ code : #217#3#15#56#10#72;
+ flags : if_ssse3 or if_mmx or if_sm
+ ),
+ (
+ opcode : A_PSIGND;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#10#72;
+ flags : if_ssse3 or if_sm
+ ),
+ (
+ opcode : A_BLENDPS;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_immediate,ot_none);
+ code : #241#3#15#58#12#72#22;
+ flags : if_sse41 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_BLENDPD;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_immediate,ot_none);
+ code : #241#3#15#58#13#72#22;
+ flags : if_sse41 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_BLENDVPS;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#20#72;
+ flags : if_sse41 or if_sm
+ ),
+ (
+ opcode : A_BLENDVPD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#21#72;
+ flags : if_sse41 or if_sm
+ ),
+ (
+ opcode : A_DPPS;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_immediate,ot_none);
+ code : #241#3#15#58#64#72#22;
+ flags : if_sse41 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_DPPD;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_immediate,ot_none);
+ code : #241#3#15#58#65#72#22;
+ flags : if_sse41 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_EXTRACTPS;
+ ops : 3;
+ optypes : (ot_memory,ot_xmmreg,ot_immediate,ot_none);
+ code : #241#213#3#15#58#23#65#22;
+ flags : if_sse41 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_EXTRACTPS;
+ ops : 3;
+ optypes : (ot_reg32 or ot_bits64,ot_xmmreg,ot_immediate,ot_none);
+ code : #241#3#15#58#23#65#22;
+ flags : if_sse41 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_INSERTPS;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_immediate,ot_none);
+ code : #241#3#15#58#33#72#22;
+ flags : if_sse41 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_MOVNTDQA;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_memory,ot_none,ot_none);
+ code : #241#3#15#56#42#72;
+ flags : if_sse41 or if_sm
+ ),
+ (
+ opcode : A_MPSADBW;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_immediate,ot_none);
+ code : #241#3#15#58#66#72#22;
+ flags : if_sse41 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PACKUSDW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#43#72;
+ flags : if_sse41 or if_sm
+ ),
+ (
+ opcode : A_PBLENDVB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#16#72;
+ flags : if_sse41 or if_sm
+ ),
+ (
+ opcode : A_PBLENDW;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_immediate,ot_none);
+ code : #241#3#15#58#14#72#22;
+ flags : if_sse41 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PCMPEQQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#41#72;
+ flags : if_sse41 or if_sm
+ ),
+ (
+ opcode : A_PEXTRB;
+ ops : 3;
+ optypes : (ot_reg32 or ot_bits64,ot_xmmreg,ot_immediate,ot_none);
+ code : #241#3#15#58#20#65#22;
+ flags : if_sse41 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PEXTRB;
+ ops : 3;
+ optypes : (ot_memory or ot_bits8,ot_xmmreg,ot_immediate,ot_none);
+ code : #241#3#15#58#20#65#22;
+ flags : if_sse41 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PEXTRD;
+ ops : 3;
+ optypes : (ot_reg32,ot_xmmreg,ot_immediate,ot_none);
+ code : #241#3#15#58#22#65#22;
+ flags : if_sse41 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PEXTRD;
+ ops : 3;
+ optypes : (ot_memory or ot_bits32,ot_xmmreg,ot_immediate,ot_none);
+ code : #241#3#15#58#22#65#22;
+ flags : if_sse41 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PEXTRQ;
+ ops : 3;
+ optypes : (ot_reg64,ot_xmmreg,ot_immediate,ot_none);
+ code : #241#214#3#15#58#22#65#22;
+ flags : if_sse41 or if_x86_64 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PEXTRQ;
+ ops : 3;
+ optypes : (ot_memory or ot_bits64,ot_xmmreg,ot_immediate,ot_none);
+ code : #241#214#3#15#58#22#65#22;
+ flags : if_sse41 or if_x86_64 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PHMINPOSUW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#65#72;
+ flags : if_sse41 or if_sm
+ ),
+ (
+ opcode : A_PINSRB;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_reg32 or ot_bits64,ot_immediate,ot_none);
+ code : #241#3#15#58#32#72#22;
+ flags : if_sse41 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PINSRB;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_memory or ot_bits8,ot_immediate,ot_none);
+ code : #241#3#15#58#32#72#22;
+ flags : if_sse41 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PINSRD;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_reg32,ot_immediate,ot_none);
+ code : #241#3#15#58#34#72#22;
+ flags : if_sse41 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PINSRD;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_memory or ot_bits32,ot_immediate,ot_none);
+ code : #241#3#15#58#34#72#22;
+ flags : if_sse41 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PINSRQ;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_reg64,ot_immediate,ot_none);
+ code : #241#214#3#15#58#34#72#22;
+ flags : if_sse41 or if_x86_64 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PINSRQ;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_memory or ot_bits64,ot_immediate,ot_none);
+ code : #241#214#3#15#58#34#72#22;
+ flags : if_sse41 or if_x86_64 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PMAXSB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#60#72;
+ flags : if_sse41 or if_sm
+ ),
+ (
+ opcode : A_PMAXSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#61#72;
+ flags : if_sse41 or if_sm
+ ),
+ (
+ opcode : A_PMAXUD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#63#72;
+ flags : if_sse41 or if_sm
+ ),
+ (
+ opcode : A_PMAXUW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#62#72;
+ flags : if_sse41 or if_sm
+ ),
+ (
+ opcode : A_PMINSB;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#56#72;
+ flags : if_sse41 or if_sm
+ ),
+ (
+ opcode : A_PMINSD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#57#72;
+ flags : if_sse41 or if_sm
+ ),
+ (
+ opcode : A_PMINUW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#58#72;
+ flags : if_sse41 or if_sm
+ ),
+ (
+ opcode : A_PMINUD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#59#72;
+ flags : if_sse41 or if_sm
+ ),
+ (
+ opcode : A_PMOVSXBW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#32#72;
+ flags : if_sse41 or if_sm
+ ),
+ (
+ opcode : A_PMOVSXBD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#33#72;
+ flags : if_sse41 or if_sm
+ ),
+ (
+ opcode : A_PMOVSXBQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#34#72;
+ flags : if_sse41 or if_sm
+ ),
+ (
+ opcode : A_PMOVSXWD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#35#72;
+ flags : if_sse41 or if_sm
+ ),
+ (
+ opcode : A_PMOVSXWQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#36#72;
+ flags : if_sse41 or if_sm
+ ),
+ (
+ opcode : A_PMOVSXDQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#37#72;
+ flags : if_sse41 or if_sm
+ ),
+ (
+ opcode : A_PMOVZXBW;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#48#72;
+ flags : if_sse41 or if_sm
+ ),
+ (
+ opcode : A_PMOVZXBD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#49#72;
+ flags : if_sse41 or if_sm
+ ),
+ (
+ opcode : A_PMOVZXBQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#50#72;
+ flags : if_sse41 or if_sm
+ ),
+ (
+ opcode : A_PMOVZXWD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#51#72;
+ flags : if_sse41 or if_sm
+ ),
+ (
+ opcode : A_PMOVZXWQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#52#72;
+ flags : if_sse41 or if_sm
+ ),
+ (
+ opcode : A_PMOVZXDQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#53#72;
+ flags : if_sse41 or if_sm
+ ),
+ (
+ opcode : A_PMULDQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#40#72;
+ flags : if_sse41 or if_sm
+ ),
+ (
+ opcode : A_PMULLD;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#64#72;
+ flags : if_sse41 or if_sm
+ ),
+ (
+ opcode : A_PTEST;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#23#72;
+ flags : if_sse41 or if_sm
+ ),
+ (
+ opcode : A_ROUNDPS;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_immediate,ot_none);
+ code : #241#3#15#58#8#72#22;
+ flags : if_sse41 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_ROUNDPD;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_immediate,ot_none);
+ code : #241#3#15#58#9#72#22;
+ flags : if_sse41 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_ROUNDSS;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_immediate,ot_none);
+ code : #241#3#15#58#10#72#22;
+ flags : if_sse41 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_ROUNDSD;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_immediate,ot_none);
+ code : #241#3#15#58#11#72#22;
+ flags : if_sse41 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_CRC32;
+ ops : 2;
+ optypes : (ot_reg32,ot_rm_gpr or ot_bits8,ot_none,ot_none);
+ code : #220#3#15#56#240#72;
+ flags : if_sse42
+ ),
+ (
+ opcode : A_CRC32;
+ ops : 2;
+ optypes : (ot_reg32,ot_rm_gpr or ot_bits16 or ot_bits32,ot_none,ot_none);
+ code : #209#220#3#15#56#241#72;
+ flags : if_sse42
+ ),
+ (
+ opcode : A_CRC32;
+ ops : 2;
+ optypes : (ot_reg64,ot_rm_gpr or ot_bits8,ot_none,ot_none);
+ code : #220#214#3#15#56#240#72;
+ flags : if_sse42 or if_x86_64
+ ),
+ (
+ opcode : A_CRC32;
+ ops : 2;
+ optypes : (ot_reg64,ot_rm_gpr or ot_bits64,ot_none,ot_none);
+ code : #220#214#3#15#56#241#72;
+ flags : if_sse42 or if_x86_64
+ ),
+ (
+ opcode : A_PCMPESTRI;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_immediate,ot_none);
+ code : #241#3#15#58#97#72#22;
+ flags : if_sse42 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PCMPESTRM;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_immediate,ot_none);
+ code : #241#3#15#58#96#72#22;
+ flags : if_sse42 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PCMPISTRI;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_immediate,ot_none);
+ code : #241#3#15#58#99#72#22;
+ flags : if_sse42 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PCMPISTRM;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_immediate,ot_none);
+ code : #241#3#15#58#98#72#22;
+ flags : if_sse42 or if_sm2 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_PCMPGTQ;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#55#72;
+ flags : if_sse42 or if_sm
+ ),
+ (
+ opcode : A_POPCNT;
+ ops : 2;
+ optypes : (ot_reg16,ot_rm_gpr or ot_bits16,ot_none,ot_none);
+ code : #219#208#2#15#184#72;
+ flags : if_386 or if_sm or if_sse4
+ ),
+ (
+ opcode : A_POPCNT;
+ ops : 2;
+ optypes : (ot_reg32,ot_rm_gpr or ot_bits32,ot_none,ot_none);
+ code : #219#208#2#15#184#72;
+ flags : if_386 or if_sm or if_sse4
+ ),
+ (
+ opcode : A_POPCNT;
+ ops : 2;
+ optypes : (ot_reg64,ot_rm_gpr or ot_bits64,ot_none,ot_none);
+ code : #219#208#2#15#184#72;
+ flags : if_386 or if_sm or if_sse4 or if_x86_64
+ ),
+ (
+ opcode : A_AESENC;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#220#72;
+ flags : if_sse4 or if_sm
+ ),
+ (
+ opcode : A_AESENCLAST;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#221#72;
+ flags : if_sse4 or if_sm
+ ),
+ (
+ opcode : A_AESDEC;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#222#72;
+ flags : if_sse4 or if_sm
+ ),
+ (
+ opcode : A_AESDECLAST;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#223#72;
+ flags : if_sse4 or if_sm
+ ),
+ (
+ opcode : A_AESIMC;
+ ops : 2;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_none,ot_none);
+ code : #241#3#15#56#219#72;
+ flags : if_sse4 or if_sm
+ ),
+ (
+ opcode : A_AESKEYGENASSIST;
+ ops : 3;
+ optypes : (ot_xmmreg,ot_xmmrm,ot_immediate,ot_none);
+ code : #241#3#15#58#223#72#22;
+ flags : if_sse4 or if_sb or if_ar2
+ ),
+ (
+ opcode : A_STOSQ;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #214#1#171;
+ flags : if_x86_64
+ ),
+ (
+ opcode : A_LODSQ;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #214#1#173;
+ flags : if_x86_64
+ ),
+ (
+ opcode : A_CMPSQ;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none);
+ code : #214#1#167;
+ flags : if_x86_64
+ )
+);